diff --git a/.gitignore b/.gitignore index 4e2441389..26a7cd8d6 100644 --- a/.gitignore +++ b/.gitignore @@ -18,3 +18,4 @@ stamp-h1 *.swp TAGS /target.h +libclamav/c++/autom4te.cache/* diff --git a/COPYING.llvm b/COPYING.llvm new file mode 100644 index 000000000..2ee7e2ba1 --- /dev/null +++ b/COPYING.llvm @@ -0,0 +1,72 @@ +The files in libclamav/llvm/llvm are from the LLVM project, original license is +in libclamav/llvm/llvm/LICENSE.TXT: + +============================================================================== +LLVM Release License +============================================================================== +University of Illinois/NCSA +Open Source License + +Copyright (c) 2003-2009 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 + diff --git a/ChangeLog b/ChangeLog index 8ee984528..b6e00fe8a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -253,6 +253,10 @@ Fri Oct 2 14:33:09 CEST 2009 (tk) ---------------------------------- * libclamav/scanners.c: fix whitelisting of scripts (bb#1706) +Fri Oct 30 14:04:43 EET 2009 (edwin) +------------------------------------ + * configure, m4/acinclude.m4: Avoid trailing slash in libdir for old gcc (#1738). + Wed Sep 30 19:41:43 EEST 2009 (edwin) ------------------------------------- * configure{.in,}: Only use -fno-strict-aliasing for gcc-4.3+ to avoid bugs diff --git a/Makefile.am b/Makefile.am index 230ad600d..73c202940 100644 --- a/Makefile.am +++ b/Makefile.am @@ -29,8 +29,9 @@ pkgconfig_DATA = libclamav.pc # don't complain that configuration files and databases are not removed, this is intended distuninstallcheck_listfiles = find . -type f ! -name clamd.conf ! -name freshclam.conf ! -name daily.cvd ! -name main.cvd -print DISTCLEANFILES = target.h -DISTCHECK_CONFIGURE_FLAGS=--enable-milter --disable-clamav --enable-distcheck-werror +DISTCHECK_CONFIGURE_FLAGS=--enable-milter --disable-clamav --enable-distcheck-werror --enable-all-jit-targets --enable-llvm=yes lcov: ($(MAKE); cd unit_tests; $(MAKE) lcov) quick-check: ($(MAKE); cd unit_tests; $(MAKE) quick-check) + diff --git a/Makefile.in b/Makefile.in index 8edee4975..34b3475dc 100644 --- a/Makefile.in +++ b/Makefile.in @@ -77,9 +77,9 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/acinclude.m4 \ $(top_srcdir)/m4/argz.m4 $(top_srcdir)/m4/fdpassing.m4 \ $(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \ $(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/m4/libtool.m4 \ - $(top_srcdir)/m4/ltdl.m4 $(top_srcdir)/m4/ltoptions.m4 \ - $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ - $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/m4/llvm.m4 $(top_srcdir)/m4/ltdl.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/mmap_private.m4 $(top_srcdir)/m4/resolv.m4 \ $(top_srcdir)/configure.in am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ @@ -324,6 +324,7 @@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ +subdirs = @subdirs@ sys_symbol_underscore = @sys_symbol_underscore@ sysconfdir = @sysconfdir@ target = @target@ @@ -344,7 +345,7 @@ pkgconfig_DATA = libclamav.pc # don't complain that configuration files and databases are not removed, this is intended distuninstallcheck_listfiles = find . -type f ! -name clamd.conf ! -name freshclam.conf ! -name daily.cvd ! -name main.cvd -print DISTCLEANFILES = target.h -DISTCHECK_CONFIGURE_FLAGS = --enable-milter --disable-clamav --enable-distcheck-werror +DISTCHECK_CONFIGURE_FLAGS = --enable-milter --disable-clamav --enable-distcheck-werror --enable-all-jit-targets --enable-llvm=yes all: clamav-config.h $(MAKE) $(AM_MAKEFLAGS) all-recursive diff --git a/aclocal.m4 b/aclocal.m4 index e40d19731..e22e4deaa 100644 --- a/aclocal.m4 +++ b/aclocal.m4 @@ -1000,6 +1000,7 @@ m4_include([m4/lib-ld.m4]) m4_include([m4/lib-link.m4]) m4_include([m4/lib-prefix.m4]) m4_include([m4/libtool.m4]) +m4_include([m4/llvm.m4]) m4_include([m4/ltdl.m4]) m4_include([m4/ltoptions.m4]) m4_include([m4/ltsugar.m4]) diff --git a/clamav-milter/Makefile.in b/clamav-milter/Makefile.in index 484d616a5..0373f1b62 100644 --- a/clamav-milter/Makefile.in +++ b/clamav-milter/Makefile.in @@ -62,9 +62,9 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/acinclude.m4 \ $(top_srcdir)/m4/argz.m4 $(top_srcdir)/m4/fdpassing.m4 \ $(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \ $(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/m4/libtool.m4 \ - $(top_srcdir)/m4/ltdl.m4 $(top_srcdir)/m4/ltoptions.m4 \ - $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ - $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/m4/llvm.m4 $(top_srcdir)/m4/ltdl.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/mmap_private.m4 $(top_srcdir)/m4/resolv.m4 \ $(top_srcdir)/configure.in am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ @@ -300,6 +300,7 @@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ +subdirs = @subdirs@ sys_symbol_underscore = @sys_symbol_underscore@ sysconfdir = @sysconfdir@ target = @target@ diff --git a/clamav-milter/netcode.c b/clamav-milter/netcode.c index c6b3d820a..bcdd16de5 100644 --- a/clamav-milter/netcode.c +++ b/clamav-milter/netcode.c @@ -257,6 +257,8 @@ char *nc_recv(int s) { } if(res==-1) { char er[256]; + if (errno == EAGAIN) + continue; strerror_print("!recv failed after successful select"); close(s); return NULL; diff --git a/clambc/Makefile.in b/clambc/Makefile.in index fde191cf8..0020746cb 100644 --- a/clambc/Makefile.in +++ b/clambc/Makefile.in @@ -43,9 +43,9 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/acinclude.m4 \ $(top_srcdir)/m4/argz.m4 $(top_srcdir)/m4/fdpassing.m4 \ $(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \ $(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/m4/libtool.m4 \ - $(top_srcdir)/m4/ltdl.m4 $(top_srcdir)/m4/ltoptions.m4 \ - $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ - $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/m4/llvm.m4 $(top_srcdir)/m4/ltdl.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/mmap_private.m4 $(top_srcdir)/m4/resolv.m4 \ $(top_srcdir)/configure.in am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ @@ -242,6 +242,7 @@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ +subdirs = @subdirs@ sys_symbol_underscore = @sys_symbol_underscore@ sysconfdir = @sysconfdir@ target = @target@ diff --git a/clambc/bcrun.c b/clambc/bcrun.c index 45f0af376..596788ead 100644 --- a/clambc/bcrun.c +++ b/clambc/bcrun.c @@ -22,12 +22,20 @@ #if HAVE_CONFIG_H #include "clamav-config.h" #endif +#include "cltypes.h" +#include +#include #include "bytecode.h" +#include "bytecode_priv.h" #include "clamav.h" #include "shared/optparser.h" #include "shared/misc.h" +#include #include +#include +#include +#include static void help(void) { @@ -39,35 +47,101 @@ static void help(void) printf("clambc [function] [param1 ...]\n\n"); printf(" --help -h Show help\n"); printf(" --version -V Show version\n"); + printf(" --trace Set bytecode trace level 0..7 (default 7)\n"); + printf(" --no-trace-showsource Don't show source line during tracing\n"); printf(" file file to test\n"); printf("\n"); return; } +static struct dbg_state { + const char *directory; + const char *file; + const char *scope; + uint32_t scopeid; + unsigned line; + unsigned col; + unsigned showline; +} dbg_state; + +static void tracehook(struct cli_bc_ctx *ctx, unsigned event) +{ + dbg_state.directory = ctx->directory; + if (*ctx->file == '?') + return; + switch (event) { + case trace_func: + fprintf(stderr, "[trace] %s:%u:%u -> %s:%u:%u Entered function %s\n", + dbg_state.file, dbg_state.line, dbg_state.col, + ctx->file, ctx->line, ctx->col, ctx->scope); + dbg_state.scope = ctx->scope; + break; + case trace_param: + fprintf(stderr, "[trace] function parameter:\n"); + return; + case trace_scope: + fprintf(stderr, "[trace] %s:%u:%u -> %s:%u:%u\n", + dbg_state.file, dbg_state.line, dbg_state.col, + ctx->file, ctx->line, ctx->col); + dbg_state.scope = ctx->scope; + break; + case trace_line: + case trace_col: + if (dbg_state.showline) + cli_bytecode_debug_printsrc(ctx); + else + fprintf(stderr, "[trace] %s:%u:%u\n", + dbg_state.file, dbg_state.line, dbg_state.col); + break; + default: + break; + } + dbg_state.file = ctx->file; + dbg_state.line = ctx->line; + dbg_state.col = ctx->col; +} + +static void tracehook_op(struct cli_bc_ctx *ctx, const char *op) +{ + fprintf(stderr, "[trace] %s\n", op); +} + +static void tracehook_val(struct cli_bc_ctx *ctx, const char *name, uint32_t value) +{ + fprintf(stderr, "[trace] %s = %u\n", name, value); +} + int main(int argc, char *argv[]) { FILE *f; struct cli_bc *bc; struct cli_bc_ctx *ctx; - int rc; + int rc, dbgargc; struct optstruct *opts; + const struct optstruct *opt; unsigned funcid=0, i; + struct cli_all_bc bcs; + unsigned int fd = -1; + unsigned tracelevel; opts = optparse(NULL, argc, argv, 1, OPT_CLAMBC, 0, NULL); if (!opts) { fprintf(stderr, "ERROR: Can't parse command line options\n"); exit(1); } + if(optget(opts, "version")->enabled) { + char* argvx[] = {argv[0], "--version",NULL}; + printf("Clam AntiVirus Bytecode Testing Tool %s\n", get_version()); + cl_init(CL_INIT_DEFAULT); + cli_bytecode_debug(2, argvx); + optfree(opts); + exit(0); + } if(optget(opts, "help")->enabled || !opts->filename) { optfree(opts); help(); exit(0); } - if(optget(opts, "version")->enabled) { - printf("Clam AntiVirus Bytecode Testing Tool %s\n", get_version()); - optfree(opts); - exit(0); - } f = fopen(opts->filename[0], "r"); if (!f) { fprintf(stderr, "Unable to load %s\n", argv[1]); @@ -83,6 +157,33 @@ int main(int argc, char *argv[]) } cl_debug(); + rc = cl_init(CL_INIT_DEFAULT); + if (rc != CL_SUCCESS) { + fprintf(stderr,"Unable to init libclamav: %s\n", cl_strerror(rc)); + optfree(opts); + exit(4); + } + + dbgargc=1; + while (opts->filename[dbgargc]) dbgargc++; + + if (dbgargc > 1) + cli_bytecode_debug(dbgargc, opts->filename); + + if (optget(opts, "force-interpreter")->enabled) { + bcs.engine = NULL; + } else { + rc = cli_bytecode_init(&bcs); + if (rc != CL_SUCCESS) { + fprintf(stderr,"Unable to init bytecode engine: %s\n", cl_strerror(rc)); + optfree(opts); + exit(4); + } + } + + bcs.all_bcs = bc; + bcs.count = 1; + rc = cli_bytecode_load(bc, f, NULL); if (rc != CL_SUCCESS) { fprintf(stderr,"Unable to load bytecode: %s\n", cl_strerror(rc)); @@ -90,7 +191,7 @@ int main(int argc, char *argv[]) exit(4); } - rc = cli_bytecode_prepare(bc); + rc = cli_bytecode_prepare(&bcs); if (rc != CL_SUCCESS) { fprintf(stderr,"Unable to prepare bytecode: %s\n", cl_strerror(rc)); optfree(opts); @@ -104,6 +205,16 @@ int main(int argc, char *argv[]) fprintf(stderr,"Out of memory\n"); exit(3); } + memset(&dbg_state, 0, sizeof(dbg_state)); + dbg_state.file = ""; + dbg_state.line = 0; + dbg_state.col = 0; + dbg_state.showline = !optget(opts, "no-trace-showsource")->enabled; + tracelevel = optget(opts, "trace")->numarg; + cli_bytecode_context_set_trace(ctx, tracelevel, + tracehook, + tracehook_op, + tracehook_val); if (opts->filename[1]) { funcid = atoi(opts->filename[1]); @@ -122,7 +233,29 @@ int main(int argc, char *argv[]) } } - rc = cli_bytecode_run(bc, ctx); + if ((opt = optget(opts,"input"))->enabled) { + fmap_t *map; + fd = open(opt->strarg, O_RDONLY); + if (fd == -1) { + fprintf(stderr, "Unable to open input file %s: %s\n", opt->strarg, strerror(errno)); + optfree(opts); + exit(5); + } + map = fmap(fd, 0, 0); + if (!map) { + fprintf(stderr, "Unable to map input file %s\n", opt->strarg); + } + rc = cli_bytecode_context_setfile(ctx, map); + if (rc != CL_SUCCESS) { + fprintf(stderr, "Unable to set file %s: %s\n", opt->strarg, cl_strerror(rc)); + optfree(opts); + exit(5); + } + funmap(map); + } + + + rc = cli_bytecode_run(&bcs, bc, ctx); if (rc != CL_SUCCESS) { fprintf(stderr,"Unable to run bytecode: %s\n", cl_strerror(rc)); } else { @@ -133,8 +266,11 @@ int main(int argc, char *argv[]) } cli_bytecode_context_destroy(ctx); cli_bytecode_destroy(bc); + cli_bytecode_done(&bcs); free(bc); optfree(opts); + if (fd != -1) + close(fd); printf("Exiting\n"); return 0; } diff --git a/clamconf/Makefile.in b/clamconf/Makefile.in index 9c3b279ec..36bfeb082 100644 --- a/clamconf/Makefile.in +++ b/clamconf/Makefile.in @@ -61,9 +61,9 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/acinclude.m4 \ $(top_srcdir)/m4/argz.m4 $(top_srcdir)/m4/fdpassing.m4 \ $(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \ $(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/m4/libtool.m4 \ - $(top_srcdir)/m4/ltdl.m4 $(top_srcdir)/m4/ltoptions.m4 \ - $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ - $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/m4/llvm.m4 $(top_srcdir)/m4/ltdl.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/mmap_private.m4 $(top_srcdir)/m4/resolv.m4 \ $(top_srcdir)/configure.in am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ @@ -260,6 +260,7 @@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ +subdirs = @subdirs@ sys_symbol_underscore = @sys_symbol_underscore@ sysconfdir = @sysconfdir@ target = @target@ diff --git a/clamconf/clamconf.c b/clamconf/clamconf.c index d1d2f4025..08264fbb6 100644 --- a/clamconf/clamconf.c +++ b/clamconf/clamconf.c @@ -34,6 +34,7 @@ #include "libclamav/str.h" #include "libclamav/clamav.h" #include "libclamav/others.h" +#include "libclamav/bytecode.h" #ifndef _WIN32 extern const struct clam_option *clam_options; @@ -294,7 +295,9 @@ int main(int argc, char **argv) printf("BZIP2 "); #endif if(have_rar) - printf("RAR"); + printf("RAR "); + if (have_clamjit) + printf("JIT"); printf("\n"); if(!strlen(dbdir)) { diff --git a/clamd/Makefile.in b/clamd/Makefile.in index 6b292b60e..7d1ed000a 100644 --- a/clamd/Makefile.in +++ b/clamd/Makefile.in @@ -61,9 +61,9 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/acinclude.m4 \ $(top_srcdir)/m4/argz.m4 $(top_srcdir)/m4/fdpassing.m4 \ $(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \ $(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/m4/libtool.m4 \ - $(top_srcdir)/m4/ltdl.m4 $(top_srcdir)/m4/ltoptions.m4 \ - $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ - $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/m4/llvm.m4 $(top_srcdir)/m4/ltdl.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/mmap_private.m4 $(top_srcdir)/m4/resolv.m4 \ $(top_srcdir)/configure.in am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ @@ -278,6 +278,7 @@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ +subdirs = @subdirs@ sys_symbol_underscore = @sys_symbol_underscore@ sysconfdir = @sysconfdir@ target = @target@ diff --git a/clamd/clamd.c b/clamd/clamd.c index 479fbd5ba..23b441be0 100644 --- a/clamd/clamd.c +++ b/clamd/clamd.c @@ -407,6 +407,9 @@ int main(int argc, char **argv) else logg("#Not loading phishing signatures.\n"); + if(optget(opts,"Bytecode")->enabled) + dboptions |= CL_DB_BYTECODE; + if(optget(opts,"PhishingScanURLs")->enabled) dboptions |= CL_DB_PHISHING_URLS; else diff --git a/clamdscan/Makefile.in b/clamdscan/Makefile.in index 118b5ded2..4c0cf1068 100644 --- a/clamdscan/Makefile.in +++ b/clamdscan/Makefile.in @@ -61,9 +61,9 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/acinclude.m4 \ $(top_srcdir)/m4/argz.m4 $(top_srcdir)/m4/fdpassing.m4 \ $(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \ $(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/m4/libtool.m4 \ - $(top_srcdir)/m4/ltdl.m4 $(top_srcdir)/m4/ltoptions.m4 \ - $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ - $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/m4/llvm.m4 $(top_srcdir)/m4/ltdl.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/mmap_private.m4 $(top_srcdir)/m4/resolv.m4 \ $(top_srcdir)/configure.in am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ @@ -271,6 +271,7 @@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ +subdirs = @subdirs@ sys_symbol_underscore = @sys_symbol_underscore@ sysconfdir = @sysconfdir@ target = @target@ diff --git a/clamdtop/Makefile.in b/clamdtop/Makefile.in index 6cf5b6395..3047af40b 100644 --- a/clamdtop/Makefile.in +++ b/clamdtop/Makefile.in @@ -43,9 +43,9 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/acinclude.m4 \ $(top_srcdir)/m4/argz.m4 $(top_srcdir)/m4/fdpassing.m4 \ $(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \ $(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/m4/libtool.m4 \ - $(top_srcdir)/m4/ltdl.m4 $(top_srcdir)/m4/ltoptions.m4 \ - $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ - $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/m4/llvm.m4 $(top_srcdir)/m4/ltdl.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/mmap_private.m4 $(top_srcdir)/m4/resolv.m4 \ $(top_srcdir)/configure.in am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ @@ -271,6 +271,7 @@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ +subdirs = @subdirs@ sys_symbol_underscore = @sys_symbol_underscore@ sysconfdir = @sysconfdir@ target = @target@ diff --git a/clamscan/Makefile.in b/clamscan/Makefile.in index 384608a36..77a87946f 100644 --- a/clamscan/Makefile.in +++ b/clamscan/Makefile.in @@ -62,9 +62,9 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/acinclude.m4 \ $(top_srcdir)/m4/argz.m4 $(top_srcdir)/m4/fdpassing.m4 \ $(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \ $(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/m4/libtool.m4 \ - $(top_srcdir)/m4/ltdl.m4 $(top_srcdir)/m4/ltoptions.m4 \ - $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ - $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/m4/llvm.m4 $(top_srcdir)/m4/ltdl.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/mmap_private.m4 $(top_srcdir)/m4/resolv.m4 \ $(top_srcdir)/configure.in am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ @@ -262,6 +262,7 @@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ +subdirs = @subdirs@ sys_symbol_underscore = @sys_symbol_underscore@ sysconfdir = @sysconfdir@ target = @target@ diff --git a/clamscan/manager.c b/clamscan/manager.c index b8558062c..c02e5680d 100644 --- a/clamscan/manager.c +++ b/clamscan/manager.c @@ -332,6 +332,9 @@ int scanmanager(const struct optstruct *opts) if(optget(opts,"phishing-scan-urls")->enabled) dboptions |= CL_DB_PHISHING_URLS; + if(optget(opts,"bytecode")->enabled) + dboptions |= CL_DB_BYTECODE; + if((ret = cl_init(CL_INIT_DEFAULT))) { logg("!Can't initialize libclamav: %s\n", cl_strerror(ret)); return 50; diff --git a/configure b/configure index 218824460..05f0151eb 100755 --- a/configure +++ b/configure @@ -745,12 +745,16 @@ ac_includes_default="\ # include #endif" -ac_subst_vars='ltdl_LTLIBOBJS +enable_option_checking=no +ac_subst_vars='ENABLE_LLVM_FALSE +ENABLE_LLVM_TRUE +ltdl_LTLIBOBJS ltdl_LIBOBJS am__EXEEXT_FALSE am__EXEEXT_TRUE LTLIBOBJS LIBOBJS +subdirs HAVE_CURSES_FALSE HAVE_CURSES_TRUE CURSES_LIBS @@ -928,8 +932,8 @@ ac_subst_files='' ac_user_opts=' enable_option_checking enable_silent_rules -enable_shared enable_static +enable_shared with_pic enable_fast_install enable_dependency_tracking @@ -978,6 +982,7 @@ enable_clamdtop with_libncurses_prefix with_libpdcurses_prefix enable_distcheck_werror +enable_llvm ' ac_precious_vars='build_alias host_alias @@ -988,7 +993,8 @@ LDFLAGS LIBS CPPFLAGS CPP' - +ac_subdirs_all=' +libclamav/c++' # Initialize some variables set by options. ac_init_help= @@ -1610,8 +1616,8 @@ Optional Features: --enable-FEATURE[=ARG] include FEATURE [ARG=yes] --enable-silent-rules less verbose build output (undo: `make V=1') --disable-silent-rules verbose build output (undo: `make V=0') + --enable-static[=PKGS] build static libraries [default=no] --enable-shared[=PKGS] build shared libraries [default=yes] - --enable-static[=PKGS] build static libraries [default=yes] --enable-fast-install[=PKGS] optimize for fast installation [default=yes] --disable-dependency-tracking speeds up one-time build @@ -1649,6 +1655,7 @@ Optional Features: --enable-clamdtop Enable 'clamdtop' tool [default=auto] --enable-distcheck-werror enable warnings as error for distcheck [default=no] + --enable-llvm Enable 'llvm' JIT/verifier support [default=auto] Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] @@ -5157,13 +5164,13 @@ if test "${lt_cv_nm_interface+set}" = set; then : else lt_cv_nm_interface="BSD nm" echo "int some_variable = 0;" > conftest.$ac_ext - (eval echo "\"\$as_me:5160: $ac_compile\"" >&5) + (eval echo "\"\$as_me:5167: $ac_compile\"" >&5) (eval "$ac_compile" 2>conftest.err) cat conftest.err >&5 - (eval echo "\"\$as_me:5163: $NM \\\"conftest.$ac_objext\\\"\"" >&5) + (eval echo "\"\$as_me:5170: $NM \\\"conftest.$ac_objext\\\"\"" >&5) (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) cat conftest.err >&5 - (eval echo "\"\$as_me:5166: output\"" >&5) + (eval echo "\"\$as_me:5173: output\"" >&5) cat conftest.out >&5 if $GREP 'External.*some_variable' conftest.out > /dev/null; then lt_cv_nm_interface="MS dumpbin" @@ -6358,7 +6365,7 @@ ia64-*-hpux*) ;; *-*-irix6*) # Find out which ABI we are using. - echo '#line 6361 "configure"' > conftest.$ac_ext + echo '#line 6368 "configure"' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? @@ -7390,6 +7397,35 @@ done # Set options enable_dlopen=yes +# Check whether --enable-static was given. +if test "${enable_static+set}" = set; then : + enableval=$enable_static; p=${PACKAGE-default} + case $enableval in + yes) enable_static=yes ;; + no) enable_static=no ;; + *) + enable_static=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_static=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac +else + enable_static=no +fi + + + + + + + @@ -7428,36 +7464,6 @@ fi - # Check whether --enable-static was given. -if test "${enable_static+set}" = set; then : - enableval=$enable_static; p=${PACKAGE-default} - case $enableval in - yes) enable_static=yes ;; - no) enable_static=no ;; - *) - enable_static=no - # Look at the argument we got. We use all the common list separators. - lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," - for pkg in $enableval; do - IFS="$lt_save_ifs" - if test "X$pkg" = "X$p"; then - enable_static=yes - fi - done - IFS="$lt_save_ifs" - ;; - esac -else - enable_static=yes -fi - - - - - - - - # Check whether --with-pic was given. @@ -7887,11 +7893,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:7890: $lt_compile\"" >&5) + (eval echo "\"\$as_me:7896: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:7894: \$? = $ac_status" >&5 + echo "$as_me:7900: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. @@ -8226,11 +8232,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:8229: $lt_compile\"" >&5) + (eval echo "\"\$as_me:8235: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:8233: \$? = $ac_status" >&5 + echo "$as_me:8239: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. @@ -8331,11 +8337,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:8334: $lt_compile\"" >&5) + (eval echo "\"\$as_me:8340: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 - echo "$as_me:8338: \$? = $ac_status" >&5 + echo "$as_me:8344: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized @@ -8386,11 +8392,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:8389: $lt_compile\"" >&5) + (eval echo "\"\$as_me:8395: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 - echo "$as_me:8393: \$? = $ac_status" >&5 + echo "$as_me:8399: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized @@ -10770,7 +10776,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 10773 "configure" +#line 10779 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -10866,7 +10872,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 10869 "configure" +#line 10875 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -11538,7 +11544,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 11541 "configure" +#line 11547 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -19809,7 +19815,29 @@ if test "x$enable_distcheckwerror" = "xyes"; then fi fi -ac_config_files="$ac_config_files libclamav/Makefile clamscan/Makefile database/Makefile docs/Makefile clamd/Makefile clamdscan/Makefile clamav-milter/Makefile freshclam/Makefile sigtool/Makefile clamconf/Makefile etc/Makefile test/Makefile unit_tests/Makefile clamdtop/Makefile clambc/Makefile Makefile clamav-config libclamav.pc platform.h docs/man/clamav-milter.8 docs/man/clamconf.1 docs/man/clamd.8 docs/man/clamd.conf.5 docs/man/clamdscan.1 docs/man/clamscan.1 docs/man/freshclam.1 docs/man/freshclam.conf.5 docs/man/sigtool.1 docs/man/clamdtop.1" +# Check whether --enable-llvm was given. +if test "${enable_llvm+set}" = set; then : + enableval=$enable_llvm; enable_llvm=$enableval +else + enable_llvm="auto" +fi + + +if test "$enable_llvm" != "no"; then + + +subdirs="$subdirs " + + + +subdirfailed=no +subdirs="$subdirs libclamav/c++" + + + +fi + +ac_config_files="$ac_config_files clamscan/Makefile database/Makefile docs/Makefile clamd/Makefile clamdscan/Makefile clamav-milter/Makefile freshclam/Makefile sigtool/Makefile clamconf/Makefile etc/Makefile test/Makefile unit_tests/Makefile clamdtop/Makefile clambc/Makefile Makefile clamav-config libclamav.pc platform.h docs/man/clamav-milter.8 docs/man/clamconf.1 docs/man/clamd.8 docs/man/clamd.conf.5 docs/man/clamdscan.1 docs/man/clamscan.1 docs/man/freshclam.1 docs/man/freshclam.conf.5 docs/man/sigtool.1 docs/man/clamdtop.1" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure @@ -20586,8 +20614,8 @@ double_quote_subst='$double_quote_subst' delay_variable_subst='$delay_variable_subst' macro_version='`$ECHO "X$macro_version" | $Xsed -e "$delay_single_quote_subst"`' macro_revision='`$ECHO "X$macro_revision" | $Xsed -e "$delay_single_quote_subst"`' -enable_shared='`$ECHO "X$enable_shared" | $Xsed -e "$delay_single_quote_subst"`' enable_static='`$ECHO "X$enable_static" | $Xsed -e "$delay_single_quote_subst"`' +enable_shared='`$ECHO "X$enable_shared" | $Xsed -e "$delay_single_quote_subst"`' pic_mode='`$ECHO "X$pic_mode" | $Xsed -e "$delay_single_quote_subst"`' enable_fast_install='`$ECHO "X$enable_fast_install" | $Xsed -e "$delay_single_quote_subst"`' host_alias='`$ECHO "X$host_alias" | $Xsed -e "$delay_single_quote_subst"`' @@ -20843,7 +20871,6 @@ do "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; "libtool") CONFIG_COMMANDS="$CONFIG_COMMANDS libtool" ;; "libltdl/Makefile") CONFIG_FILES="$CONFIG_FILES libltdl/Makefile" ;; - "libclamav/Makefile") CONFIG_FILES="$CONFIG_FILES libclamav/Makefile" ;; "clamscan/Makefile") CONFIG_FILES="$CONFIG_FILES clamscan/Makefile" ;; "database/Makefile") CONFIG_FILES="$CONFIG_FILES database/Makefile" ;; "docs/Makefile") CONFIG_FILES="$CONFIG_FILES docs/Makefile" ;; @@ -21608,12 +21635,12 @@ available_tags="" macro_version=$macro_version macro_revision=$macro_revision -# Whether or not to build shared libraries. -build_libtool_libs=$enable_shared - # Whether or not to build static libraries. build_old_libs=$enable_static +# Whether or not to build shared libraries. +build_libtool_libs=$enable_shared + # What type of objects to build. pic_mode=$pic_mode @@ -22219,7 +22246,2740 @@ if test "$no_create" != yes; then # would make configure fail if this is the last instruction. $ac_cs_success || as_fn_exit $? fi -if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then + + + +# +# CONFIG_SUBDIRS section. +# +if test "$no_recursion" != yes; then + + # Remove --cache-file, --srcdir, and --disable-option-checking arguments + # so they do not pile up. + ac_sub_configure_args= + ac_prev= + eval "set x $ac_configure_args" + shift + for ac_arg + do + if test -n "$ac_prev"; then + ac_prev= + continue + fi + case $ac_arg in + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* \ + | --c=*) + ;; + --config-cache | -C) + ;; + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + ;; + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + ;; + --disable-option-checking) + ;; + *) + case $ac_arg in + *\'*) ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + as_fn_append ac_sub_configure_args " '$ac_arg'" ;; + esac + done + + # Always prepend --prefix to ensure using the same prefix + # in subdir configurations. + ac_arg="--prefix=$prefix" + case $ac_arg in + *\'*) ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + ac_sub_configure_args="'$ac_arg' $ac_sub_configure_args" + + # Pass --silent + if test "$silent" = yes; then + ac_sub_configure_args="--silent $ac_sub_configure_args" + fi + + # Always prepend --disable-option-checking to silence warnings, since + # different subdirs can have different --enable and --with options. + ac_sub_configure_args="--disable-option-checking $ac_sub_configure_args" + + ac_popdir=`pwd` + for ac_dir in : $subdirs; do test "x$ac_dir" = x: && continue + + # Do not complain, so a configure script can configure whichever + # parts of a large source tree are present. + test -d "$srcdir/$ac_dir" || continue + + ac_msg="=== configuring in $ac_dir (`pwd`/$ac_dir)" + $as_echo "$as_me:${as_lineno-$LINENO}: $ac_msg" >&5 + $as_echo "$ac_msg" >&6 + as_dir="$ac_dir"; as_fn_mkdir_p + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + + cd "$ac_dir" + + # Check for guested configure; otherwise get Cygnus style configure. + if test -f "$ac_srcdir/configure.gnu"; then + ac_sub_configure=$ac_srcdir/configure.gnu + elif test -f "$ac_srcdir/configure"; then + ac_sub_configure=$ac_srcdir/configure + elif test -f "$ac_srcdir/configure.in"; then + # This should be Cygnus configure. + ac_sub_configure=$ac_aux_dir/configure + else + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: no configuration information is in $ac_dir" >&5 +$as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2;} + ac_sub_configure= + fi + + # The recursion is here. + if test -n "$ac_sub_configure"; then + # Make the cache file name correct relative to the subdirectory. + case $cache_file in + [\\/]* | ?:[\\/]* ) ac_sub_cache_file=$cache_file ;; + *) # Relative name. + ac_sub_cache_file=$ac_top_build_prefix$cache_file ;; + esac + + { $as_echo "$as_me:${as_lineno-$LINENO}: running $SHELL $ac_sub_configure $ac_sub_configure_args --cache-file=$ac_sub_cache_file --srcdir=$ac_srcdir" >&5 +$as_echo "$as_me: running $SHELL $ac_sub_configure $ac_sub_configure_args --cache-file=$ac_sub_cache_file --srcdir=$ac_srcdir" >&6;} + # The eval makes quoting arguments work. + eval "\$SHELL \"\$ac_sub_configure\" $ac_sub_configure_args \ + --cache-file=\"\$ac_sub_cache_file\" --srcdir=\"\$ac_srcdir\"" || + subdirfailed=yes + fi + + cd "$ac_popdir" + done +fi + + if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 +$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} +fi + + +if test "$enable_llvm" = "yes" && test "$subdirfailed" != "no"; then + as_fn_error "Failed to configure LLVM, and LLVM was explicitly requested" "$LINENO" 5 +fi + if test "$subdirfailed" != "yes" && test "$enable_llvm" != "no"; then + ENABLE_LLVM_TRUE= + ENABLE_LLVM_FALSE='#' +else + ENABLE_LLVM_TRUE='#' + ENABLE_LLVM_FALSE= +fi + +no_recursion="yes"; +ac_config_files="$ac_config_files libclamav/Makefile" + +cat >confcache <<\_ACEOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs, see configure's option --config-cache. +# It is not useful on other systems. If it contains results you don't +# want to keep, you may remove or edit it. +# +# config.status only pays attention to the cache file if you give it +# the --recheck option to rerun configure. +# +# `ac_cv_env_foo' variables (set or unset) will be overridden when +# loading this file, other *unset* `ac_cv_foo' will be assigned the +# following values. + +_ACEOF + +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, we kill variables containing newlines. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +( + for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + + (set) 2>&1 | + case $as_nl`(ac_space=' '; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + # `set' does not quote correctly, so add quotes: double-quote + # substitution turns \\\\ into \\, and sed turns \\ into \. + sed -n \ + "s/'/'\\\\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" + ;; #( + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) | + sed ' + /^ac_cv_env_/b end + t clear + :clear + s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ + t end + s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ + :end' >>confcache +if diff "$cache_file" confcache >/dev/null 2>&1; then :; else + if test -w "$cache_file"; then + test "x$cache_file" != "x/dev/null" && + { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 +$as_echo "$as_me: updating cache $cache_file" >&6;} + cat confcache >$cache_file + else + { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 +$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} + fi +fi +rm -f confcache + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +DEFS=-DHAVE_CONFIG_H + +ac_libobjs= +ac_ltlibobjs= +for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue + # 1. Remove the extension, and $U if already installed. + ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' + ac_i=`$as_echo "$ac_i" | sed "$ac_script"` + # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR + # will be set to the directory where LIBOBJS objects are built. + as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" + as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' +done +LIBOBJS=$ac_libobjs + +LTLIBOBJS=$ac_ltlibobjs + + + if test -n "$EXEEXT"; then + am__EXEEXT_TRUE= + am__EXEEXT_FALSE='#' +else + am__EXEEXT_TRUE='#' + am__EXEEXT_FALSE= +fi + +if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then + as_fn_error "conditional \"AMDEP\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then + as_fn_error "conditional \"am__fastdepCC\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${INSTALL_LTDL_TRUE}" && test -z "${INSTALL_LTDL_FALSE}"; then + as_fn_error "conditional \"INSTALL_LTDL\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${CONVENIENCE_LTDL_TRUE}" && test -z "${CONVENIENCE_LTDL_FALSE}"; then + as_fn_error "conditional \"CONVENIENCE_LTDL\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +LT_CONFIG_H=clamav-config.h + + _ltdl_libobjs= + _ltdl_ltlibobjs= + if test -n "$_LT_LIBOBJS"; then + # Remove the extension. + _lt_sed_drop_objext='s/\.o$//;s/\.obj$//' + for i in `for i in $_LT_LIBOBJS; do echo "$i"; done | sed "$_lt_sed_drop_objext" | sort -u`; do + _ltdl_libobjs="$_ltdl_libobjs $lt_libobj_prefix$i.$ac_objext" + _ltdl_ltlibobjs="$_ltdl_ltlibobjs $lt_libobj_prefix$i.lo" + done + fi + ltdl_LIBOBJS=$_ltdl_libobjs + + ltdl_LTLIBOBJS=$_ltdl_ltlibobjs + + + +if test -z "${VERSIONSCRIPT_TRUE}" && test -z "${VERSIONSCRIPT_FALSE}"; then + as_fn_error "conditional \"VERSIONSCRIPT\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${HAVE_LIBCHECK_TRUE}" && test -z "${HAVE_LIBCHECK_FALSE}"; then + as_fn_error "conditional \"HAVE_LIBCHECK\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${ENABLE_COVERAGE_TRUE}" && test -z "${ENABLE_COVERAGE_FALSE}"; then + as_fn_error "conditional \"ENABLE_COVERAGE\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${MAINTAINER_MODE_TRUE}" && test -z "${MAINTAINER_MODE_FALSE}"; then + as_fn_error "conditional \"MAINTAINER_MODE\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${ENABLE_UNRAR_TRUE}" && test -z "${ENABLE_UNRAR_FALSE}"; then + as_fn_error "conditional \"ENABLE_UNRAR\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${LINK_TOMMATH_TRUE}" && test -z "${LINK_TOMMATH_FALSE}"; then + as_fn_error "conditional \"LINK_TOMMATH\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${BUILD_CLAMD_TRUE}" && test -z "${BUILD_CLAMD_FALSE}"; then + as_fn_error "conditional \"BUILD_CLAMD\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${HAVE_MILTER_TRUE}" && test -z "${HAVE_MILTER_FALSE}"; then + as_fn_error "conditional \"HAVE_MILTER\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${HAVE_CURSES_TRUE}" && test -z "${HAVE_CURSES_FALSE}"; then + as_fn_error "conditional \"HAVE_CURSES\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${am__EXEEXT_TRUE}" && test -z "${am__EXEEXT_FALSE}"; then + as_fn_error "conditional \"am__EXEEXT\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${ENABLE_LLVM_TRUE}" && test -z "${ENABLE_LLVM_FALSE}"; then + as_fn_error "conditional \"ENABLE_LLVM\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi + +: ${CONFIG_STATUS=./config.status} +ac_write_fail=0 +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files $CONFIG_STATUS" +{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 +$as_echo "$as_me: creating $CONFIG_STATUS" >&6;} +as_write_fail=0 +cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 +#! $SHELL +# Generated by $as_me. +# Run this file to recreate the current configuration. +# Compiler output produced by configure, useful for debugging +# configure, is in config.log if it exists. + +debug=false +ac_cs_recheck=false +ac_cs_silent=false + +SHELL=\${CONFIG_SHELL-$SHELL} +export SHELL +_ASEOF +cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi + + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +case $0 in #(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + + +# as_fn_error ERROR [LINENO LOG_FD] +# --------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with status $?, using 1 if that was 0. +as_fn_error () +{ + as_status=$?; test $as_status -eq 0 && as_status=1 + if test "$3"; then + as_lineno=${as_lineno-"$2"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $1" >&$3 + fi + $as_echo "$as_me: error: $1" >&2 + as_fn_exit $as_status +} # as_fn_error + + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -p'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -p' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -p' + fi +else + as_ln_s='cp -p' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error "cannot create directory $as_dir" + + +} # as_fn_mkdir_p +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +if test -x / >/dev/null 2>&1; then + as_test_x='test -x' +else + if ls -dL / >/dev/null 2>&1; then + as_ls_L_option=L + else + as_ls_L_option= + fi + as_test_x=' + eval sh -c '\'' + if test -d "$1"; then + test -d "$1/."; + else + case $1 in #( + -*)set "./$1";; + esac; + case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #(( + ???[sx]*):;;*)false;;esac;fi + '\'' sh + ' +fi +as_executable_p=$as_test_x + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +exec 6>&1 +## ----------------------------------- ## +## Main body of $CONFIG_STATUS script. ## +## ----------------------------------- ## +_ASEOF +test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# Save the log message, to keep $0 and so on meaningful, and to +# report actual input values of CONFIG_FILES etc. instead of their +# values after options handling. +ac_log=" +This file was extended by ClamAV $as_me devel, which was +generated by GNU Autoconf 2.65. Invocation command line was + + CONFIG_FILES = $CONFIG_FILES + CONFIG_HEADERS = $CONFIG_HEADERS + CONFIG_LINKS = $CONFIG_LINKS + CONFIG_COMMANDS = $CONFIG_COMMANDS + $ $0 $@ + +on `(hostname || uname -n) 2>/dev/null | sed 1q` +" + +_ACEOF + +case $ac_config_files in *" +"*) set x $ac_config_files; shift; ac_config_files=$*;; +esac + +case $ac_config_headers in *" +"*) set x $ac_config_headers; shift; ac_config_headers=$*;; +esac + + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +# Files that config.status was made for. +config_files="$ac_config_files" +config_headers="$ac_config_headers" +config_commands="$ac_config_commands" + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +ac_cs_usage="\ +\`$as_me' instantiates files and other configuration actions +from templates according to the current configuration. Unless the files +and actions are specified as TAGs, all are instantiated by default. + +Usage: $0 [OPTION]... [TAG]... + + -h, --help print this help, then exit + -V, --version print version number and configuration settings, then exit + --config print configuration, then exit + -q, --quiet, --silent + do not print progress messages + -d, --debug don't remove temporary files + --recheck update $as_me by reconfiguring in the same conditions + --file=FILE[:TEMPLATE] + instantiate the configuration file FILE + --header=FILE[:TEMPLATE] + instantiate the configuration header FILE + +Configuration files: +$config_files + +Configuration headers: +$config_headers + +Configuration commands: +$config_commands + +Report bugs to . +ClamAV home page: ." + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" +ac_cs_version="\\ +ClamAV config.status devel +configured by $0, generated by GNU Autoconf 2.65, + with options \\"\$ac_cs_config\\" + +Copyright (C) 2009 Free Software Foundation, Inc. +This config.status script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it." + +ac_pwd='$ac_pwd' +srcdir='$srcdir' +INSTALL='$INSTALL' +MKDIR_P='$MKDIR_P' +AWK='$AWK' +test -n "\$AWK" || AWK=awk +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# The default lists apply if the user does not specify any file. +ac_need_defaults=: +while test $# != 0 +do + case $1 in + --*=*) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` + ac_shift=: + ;; + *) + ac_option=$1 + ac_optarg=$2 + ac_shift=shift + ;; + esac + + case $ac_option in + # Handling of the options. + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + ac_cs_recheck=: ;; + --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) + $as_echo "$ac_cs_version"; exit ;; + --config | --confi | --conf | --con | --co | --c ) + $as_echo "$ac_cs_config"; exit ;; + --debug | --debu | --deb | --de | --d | -d ) + debug=: ;; + --file | --fil | --fi | --f ) + $ac_shift + case $ac_optarg in + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + as_fn_append CONFIG_FILES " '$ac_optarg'" + ac_need_defaults=false;; + --header | --heade | --head | --hea ) + $ac_shift + case $ac_optarg in + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + as_fn_append CONFIG_HEADERS " '$ac_optarg'" + ac_need_defaults=false;; + --he | --h) + # Conflict between --help and --header + as_fn_error "ambiguous option: \`$1' +Try \`$0 --help' for more information.";; + --help | --hel | -h ) + $as_echo "$ac_cs_usage"; exit ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil | --si | --s) + ac_cs_silent=: ;; + + # This is an error. + -*) as_fn_error "unrecognized option: \`$1' +Try \`$0 --help' for more information." ;; + + *) as_fn_append ac_config_targets " $1" + ac_need_defaults=false ;; + + esac + shift +done + +ac_configure_extra_args= + +if $ac_cs_silent; then + exec 6>/dev/null + ac_configure_extra_args="$ac_configure_extra_args --silent" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +if \$ac_cs_recheck; then + set X '$SHELL' '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion + shift + \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 + CONFIG_SHELL='$SHELL' + export CONFIG_SHELL + exec "\$@" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +exec 5>>config.log +{ + echo + sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX +## Running $as_me. ## +_ASBOX + $as_echo "$ac_log" +} >&5 + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +# +# INIT-COMMANDS +# +AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir" + + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +sed_quote_subst='$sed_quote_subst' +double_quote_subst='$double_quote_subst' +delay_variable_subst='$delay_variable_subst' +macro_version='`$ECHO "X$macro_version" | $Xsed -e "$delay_single_quote_subst"`' +macro_revision='`$ECHO "X$macro_revision" | $Xsed -e "$delay_single_quote_subst"`' +enable_static='`$ECHO "X$enable_static" | $Xsed -e "$delay_single_quote_subst"`' +enable_shared='`$ECHO "X$enable_shared" | $Xsed -e "$delay_single_quote_subst"`' +pic_mode='`$ECHO "X$pic_mode" | $Xsed -e "$delay_single_quote_subst"`' +enable_fast_install='`$ECHO "X$enable_fast_install" | $Xsed -e "$delay_single_quote_subst"`' +host_alias='`$ECHO "X$host_alias" | $Xsed -e "$delay_single_quote_subst"`' +host='`$ECHO "X$host" | $Xsed -e "$delay_single_quote_subst"`' +host_os='`$ECHO "X$host_os" | $Xsed -e "$delay_single_quote_subst"`' +build_alias='`$ECHO "X$build_alias" | $Xsed -e "$delay_single_quote_subst"`' +build='`$ECHO "X$build" | $Xsed -e "$delay_single_quote_subst"`' +build_os='`$ECHO "X$build_os" | $Xsed -e "$delay_single_quote_subst"`' +SED='`$ECHO "X$SED" | $Xsed -e "$delay_single_quote_subst"`' +Xsed='`$ECHO "X$Xsed" | $Xsed -e "$delay_single_quote_subst"`' +GREP='`$ECHO "X$GREP" | $Xsed -e "$delay_single_quote_subst"`' +EGREP='`$ECHO "X$EGREP" | $Xsed -e "$delay_single_quote_subst"`' +FGREP='`$ECHO "X$FGREP" | $Xsed -e "$delay_single_quote_subst"`' +LD='`$ECHO "X$LD" | $Xsed -e "$delay_single_quote_subst"`' +NM='`$ECHO "X$NM" | $Xsed -e "$delay_single_quote_subst"`' +LN_S='`$ECHO "X$LN_S" | $Xsed -e "$delay_single_quote_subst"`' +max_cmd_len='`$ECHO "X$max_cmd_len" | $Xsed -e "$delay_single_quote_subst"`' +ac_objext='`$ECHO "X$ac_objext" | $Xsed -e "$delay_single_quote_subst"`' +exeext='`$ECHO "X$exeext" | $Xsed -e "$delay_single_quote_subst"`' +lt_unset='`$ECHO "X$lt_unset" | $Xsed -e "$delay_single_quote_subst"`' +lt_SP2NL='`$ECHO "X$lt_SP2NL" | $Xsed -e "$delay_single_quote_subst"`' +lt_NL2SP='`$ECHO "X$lt_NL2SP" | $Xsed -e "$delay_single_quote_subst"`' +reload_flag='`$ECHO "X$reload_flag" | $Xsed -e "$delay_single_quote_subst"`' +reload_cmds='`$ECHO "X$reload_cmds" | $Xsed -e "$delay_single_quote_subst"`' +OBJDUMP='`$ECHO "X$OBJDUMP" | $Xsed -e "$delay_single_quote_subst"`' +deplibs_check_method='`$ECHO "X$deplibs_check_method" | $Xsed -e "$delay_single_quote_subst"`' +file_magic_cmd='`$ECHO "X$file_magic_cmd" | $Xsed -e "$delay_single_quote_subst"`' +AR='`$ECHO "X$AR" | $Xsed -e "$delay_single_quote_subst"`' +AR_FLAGS='`$ECHO "X$AR_FLAGS" | $Xsed -e "$delay_single_quote_subst"`' +STRIP='`$ECHO "X$STRIP" | $Xsed -e "$delay_single_quote_subst"`' +RANLIB='`$ECHO "X$RANLIB" | $Xsed -e "$delay_single_quote_subst"`' +old_postinstall_cmds='`$ECHO "X$old_postinstall_cmds" | $Xsed -e "$delay_single_quote_subst"`' +old_postuninstall_cmds='`$ECHO "X$old_postuninstall_cmds" | $Xsed -e "$delay_single_quote_subst"`' +old_archive_cmds='`$ECHO "X$old_archive_cmds" | $Xsed -e "$delay_single_quote_subst"`' +CC='`$ECHO "X$CC" | $Xsed -e "$delay_single_quote_subst"`' +CFLAGS='`$ECHO "X$CFLAGS" | $Xsed -e "$delay_single_quote_subst"`' +compiler='`$ECHO "X$compiler" | $Xsed -e "$delay_single_quote_subst"`' +GCC='`$ECHO "X$GCC" | $Xsed -e "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_pipe='`$ECHO "X$lt_cv_sys_global_symbol_pipe" | $Xsed -e "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_to_cdecl='`$ECHO "X$lt_cv_sys_global_symbol_to_cdecl" | $Xsed -e "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_to_c_name_address='`$ECHO "X$lt_cv_sys_global_symbol_to_c_name_address" | $Xsed -e "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix='`$ECHO "X$lt_cv_sys_global_symbol_to_c_name_address_lib_prefix" | $Xsed -e "$delay_single_quote_subst"`' +objdir='`$ECHO "X$objdir" | $Xsed -e "$delay_single_quote_subst"`' +SHELL='`$ECHO "X$SHELL" | $Xsed -e "$delay_single_quote_subst"`' +ECHO='`$ECHO "X$ECHO" | $Xsed -e "$delay_single_quote_subst"`' +MAGIC_CMD='`$ECHO "X$MAGIC_CMD" | $Xsed -e "$delay_single_quote_subst"`' +lt_prog_compiler_no_builtin_flag='`$ECHO "X$lt_prog_compiler_no_builtin_flag" | $Xsed -e "$delay_single_quote_subst"`' +lt_prog_compiler_wl='`$ECHO "X$lt_prog_compiler_wl" | $Xsed -e "$delay_single_quote_subst"`' +lt_prog_compiler_pic='`$ECHO "X$lt_prog_compiler_pic" | $Xsed -e "$delay_single_quote_subst"`' +lt_prog_compiler_static='`$ECHO "X$lt_prog_compiler_static" | $Xsed -e "$delay_single_quote_subst"`' +lt_cv_prog_compiler_c_o='`$ECHO "X$lt_cv_prog_compiler_c_o" | $Xsed -e "$delay_single_quote_subst"`' +need_locks='`$ECHO "X$need_locks" | $Xsed -e "$delay_single_quote_subst"`' +DSYMUTIL='`$ECHO "X$DSYMUTIL" | $Xsed -e "$delay_single_quote_subst"`' +NMEDIT='`$ECHO "X$NMEDIT" | $Xsed -e "$delay_single_quote_subst"`' +LIPO='`$ECHO "X$LIPO" | $Xsed -e "$delay_single_quote_subst"`' +OTOOL='`$ECHO "X$OTOOL" | $Xsed -e "$delay_single_quote_subst"`' +OTOOL64='`$ECHO "X$OTOOL64" | $Xsed -e "$delay_single_quote_subst"`' +libext='`$ECHO "X$libext" | $Xsed -e "$delay_single_quote_subst"`' +shrext_cmds='`$ECHO "X$shrext_cmds" | $Xsed -e "$delay_single_quote_subst"`' +extract_expsyms_cmds='`$ECHO "X$extract_expsyms_cmds" | $Xsed -e "$delay_single_quote_subst"`' +archive_cmds_need_lc='`$ECHO "X$archive_cmds_need_lc" | $Xsed -e "$delay_single_quote_subst"`' +enable_shared_with_static_runtimes='`$ECHO "X$enable_shared_with_static_runtimes" | $Xsed -e "$delay_single_quote_subst"`' +export_dynamic_flag_spec='`$ECHO "X$export_dynamic_flag_spec" | $Xsed -e "$delay_single_quote_subst"`' +whole_archive_flag_spec='`$ECHO "X$whole_archive_flag_spec" | $Xsed -e "$delay_single_quote_subst"`' +compiler_needs_object='`$ECHO "X$compiler_needs_object" | $Xsed -e "$delay_single_quote_subst"`' +old_archive_from_new_cmds='`$ECHO "X$old_archive_from_new_cmds" | $Xsed -e "$delay_single_quote_subst"`' +old_archive_from_expsyms_cmds='`$ECHO "X$old_archive_from_expsyms_cmds" | $Xsed -e "$delay_single_quote_subst"`' +archive_cmds='`$ECHO "X$archive_cmds" | $Xsed -e "$delay_single_quote_subst"`' +archive_expsym_cmds='`$ECHO "X$archive_expsym_cmds" | $Xsed -e "$delay_single_quote_subst"`' +module_cmds='`$ECHO "X$module_cmds" | $Xsed -e "$delay_single_quote_subst"`' +module_expsym_cmds='`$ECHO "X$module_expsym_cmds" | $Xsed -e "$delay_single_quote_subst"`' +with_gnu_ld='`$ECHO "X$with_gnu_ld" | $Xsed -e "$delay_single_quote_subst"`' +allow_undefined_flag='`$ECHO "X$allow_undefined_flag" | $Xsed -e "$delay_single_quote_subst"`' +no_undefined_flag='`$ECHO "X$no_undefined_flag" | $Xsed -e "$delay_single_quote_subst"`' +hardcode_libdir_flag_spec='`$ECHO "X$hardcode_libdir_flag_spec" | $Xsed -e "$delay_single_quote_subst"`' +hardcode_libdir_flag_spec_ld='`$ECHO "X$hardcode_libdir_flag_spec_ld" | $Xsed -e "$delay_single_quote_subst"`' +hardcode_libdir_separator='`$ECHO "X$hardcode_libdir_separator" | $Xsed -e "$delay_single_quote_subst"`' +hardcode_direct='`$ECHO "X$hardcode_direct" | $Xsed -e "$delay_single_quote_subst"`' +hardcode_direct_absolute='`$ECHO "X$hardcode_direct_absolute" | $Xsed -e "$delay_single_quote_subst"`' +hardcode_minus_L='`$ECHO "X$hardcode_minus_L" | $Xsed -e "$delay_single_quote_subst"`' +hardcode_shlibpath_var='`$ECHO "X$hardcode_shlibpath_var" | $Xsed -e "$delay_single_quote_subst"`' +hardcode_automatic='`$ECHO "X$hardcode_automatic" | $Xsed -e "$delay_single_quote_subst"`' +inherit_rpath='`$ECHO "X$inherit_rpath" | $Xsed -e "$delay_single_quote_subst"`' +link_all_deplibs='`$ECHO "X$link_all_deplibs" | $Xsed -e "$delay_single_quote_subst"`' +fix_srcfile_path='`$ECHO "X$fix_srcfile_path" | $Xsed -e "$delay_single_quote_subst"`' +always_export_symbols='`$ECHO "X$always_export_symbols" | $Xsed -e "$delay_single_quote_subst"`' +export_symbols_cmds='`$ECHO "X$export_symbols_cmds" | $Xsed -e "$delay_single_quote_subst"`' +exclude_expsyms='`$ECHO "X$exclude_expsyms" | $Xsed -e "$delay_single_quote_subst"`' +include_expsyms='`$ECHO "X$include_expsyms" | $Xsed -e "$delay_single_quote_subst"`' +prelink_cmds='`$ECHO "X$prelink_cmds" | $Xsed -e "$delay_single_quote_subst"`' +file_list_spec='`$ECHO "X$file_list_spec" | $Xsed -e "$delay_single_quote_subst"`' +variables_saved_for_relink='`$ECHO "X$variables_saved_for_relink" | $Xsed -e "$delay_single_quote_subst"`' +need_lib_prefix='`$ECHO "X$need_lib_prefix" | $Xsed -e "$delay_single_quote_subst"`' +need_version='`$ECHO "X$need_version" | $Xsed -e "$delay_single_quote_subst"`' +version_type='`$ECHO "X$version_type" | $Xsed -e "$delay_single_quote_subst"`' +runpath_var='`$ECHO "X$runpath_var" | $Xsed -e "$delay_single_quote_subst"`' +shlibpath_var='`$ECHO "X$shlibpath_var" | $Xsed -e "$delay_single_quote_subst"`' +shlibpath_overrides_runpath='`$ECHO "X$shlibpath_overrides_runpath" | $Xsed -e "$delay_single_quote_subst"`' +libname_spec='`$ECHO "X$libname_spec" | $Xsed -e "$delay_single_quote_subst"`' +library_names_spec='`$ECHO "X$library_names_spec" | $Xsed -e "$delay_single_quote_subst"`' +soname_spec='`$ECHO "X$soname_spec" | $Xsed -e "$delay_single_quote_subst"`' +postinstall_cmds='`$ECHO "X$postinstall_cmds" | $Xsed -e "$delay_single_quote_subst"`' +postuninstall_cmds='`$ECHO "X$postuninstall_cmds" | $Xsed -e "$delay_single_quote_subst"`' +finish_cmds='`$ECHO "X$finish_cmds" | $Xsed -e "$delay_single_quote_subst"`' +finish_eval='`$ECHO "X$finish_eval" | $Xsed -e "$delay_single_quote_subst"`' +hardcode_into_libs='`$ECHO "X$hardcode_into_libs" | $Xsed -e "$delay_single_quote_subst"`' +sys_lib_search_path_spec='`$ECHO "X$sys_lib_search_path_spec" | $Xsed -e "$delay_single_quote_subst"`' +sys_lib_dlsearch_path_spec='`$ECHO "X$sys_lib_dlsearch_path_spec" | $Xsed -e "$delay_single_quote_subst"`' +hardcode_action='`$ECHO "X$hardcode_action" | $Xsed -e "$delay_single_quote_subst"`' +enable_dlopen='`$ECHO "X$enable_dlopen" | $Xsed -e "$delay_single_quote_subst"`' +enable_dlopen_self='`$ECHO "X$enable_dlopen_self" | $Xsed -e "$delay_single_quote_subst"`' +enable_dlopen_self_static='`$ECHO "X$enable_dlopen_self_static" | $Xsed -e "$delay_single_quote_subst"`' +old_striplib='`$ECHO "X$old_striplib" | $Xsed -e "$delay_single_quote_subst"`' +striplib='`$ECHO "X$striplib" | $Xsed -e "$delay_single_quote_subst"`' + +LTCC='$LTCC' +LTCFLAGS='$LTCFLAGS' +compiler='$compiler_DEFAULT' + +# Quote evaled strings. +for var in SED \ +GREP \ +EGREP \ +FGREP \ +LD \ +NM \ +LN_S \ +lt_SP2NL \ +lt_NL2SP \ +reload_flag \ +OBJDUMP \ +deplibs_check_method \ +file_magic_cmd \ +AR \ +AR_FLAGS \ +STRIP \ +RANLIB \ +CC \ +CFLAGS \ +compiler \ +lt_cv_sys_global_symbol_pipe \ +lt_cv_sys_global_symbol_to_cdecl \ +lt_cv_sys_global_symbol_to_c_name_address \ +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix \ +SHELL \ +ECHO \ +lt_prog_compiler_no_builtin_flag \ +lt_prog_compiler_wl \ +lt_prog_compiler_pic \ +lt_prog_compiler_static \ +lt_cv_prog_compiler_c_o \ +need_locks \ +DSYMUTIL \ +NMEDIT \ +LIPO \ +OTOOL \ +OTOOL64 \ +shrext_cmds \ +export_dynamic_flag_spec \ +whole_archive_flag_spec \ +compiler_needs_object \ +with_gnu_ld \ +allow_undefined_flag \ +no_undefined_flag \ +hardcode_libdir_flag_spec \ +hardcode_libdir_flag_spec_ld \ +hardcode_libdir_separator \ +fix_srcfile_path \ +exclude_expsyms \ +include_expsyms \ +file_list_spec \ +variables_saved_for_relink \ +libname_spec \ +library_names_spec \ +soname_spec \ +finish_eval \ +old_striplib \ +striplib; do + case \`eval \\\\\$ECHO "X\\\\\$\$var"\` in + *[\\\\\\\`\\"\\\$]*) + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"X\\\$\$var\\" | \\\$Xsed -e \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" + ;; + *) + eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" + ;; + esac +done + +# Double-quote double-evaled strings. +for var in reload_cmds \ +old_postinstall_cmds \ +old_postuninstall_cmds \ +old_archive_cmds \ +extract_expsyms_cmds \ +old_archive_from_new_cmds \ +old_archive_from_expsyms_cmds \ +archive_cmds \ +archive_expsym_cmds \ +module_cmds \ +module_expsym_cmds \ +export_symbols_cmds \ +prelink_cmds \ +postinstall_cmds \ +postuninstall_cmds \ +finish_cmds \ +sys_lib_search_path_spec \ +sys_lib_dlsearch_path_spec; do + case \`eval \\\\\$ECHO "X\\\\\$\$var"\` in + *[\\\\\\\`\\"\\\$]*) + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"X\\\$\$var\\" | \\\$Xsed -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" + ;; + *) + eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" + ;; + esac +done + +# Fix-up fallback echo if it was mangled by the above quoting rules. +case \$lt_ECHO in +*'\\\$0 --fallback-echo"') lt_ECHO=\`\$ECHO "X\$lt_ECHO" | \$Xsed -e 's/\\\\\\\\\\\\\\\$0 --fallback-echo"\$/\$0 --fallback-echo"/'\` + ;; +esac + +ac_aux_dir='$ac_aux_dir' +xsi_shell='$xsi_shell' +lt_shell_append='$lt_shell_append' + +# See if we are running on zsh, and set the options which allow our +# commands through without removal of \ escapes INIT. +if test -n "\${ZSH_VERSION+set}" ; then + setopt NO_GLOB_SUBST +fi + + + PACKAGE='$PACKAGE' + VERSION='$VERSION' + TIMESTAMP='$TIMESTAMP' + RM='$RM' + ofile='$ofile' + +ac_aux_dir='$ac_aux_dir' + + + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 + +# Handling of arguments. +for ac_config_target in $ac_config_targets +do + case $ac_config_target in + "clamav-config.h") CONFIG_HEADERS="$CONFIG_HEADERS clamav-config.h" ;; + "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; + "libtool") CONFIG_COMMANDS="$CONFIG_COMMANDS libtool" ;; + "libltdl/Makefile") CONFIG_FILES="$CONFIG_FILES libltdl/Makefile" ;; + "clamscan/Makefile") CONFIG_FILES="$CONFIG_FILES clamscan/Makefile" ;; + "database/Makefile") CONFIG_FILES="$CONFIG_FILES database/Makefile" ;; + "docs/Makefile") CONFIG_FILES="$CONFIG_FILES docs/Makefile" ;; + "clamd/Makefile") CONFIG_FILES="$CONFIG_FILES clamd/Makefile" ;; + "clamdscan/Makefile") CONFIG_FILES="$CONFIG_FILES clamdscan/Makefile" ;; + "clamav-milter/Makefile") CONFIG_FILES="$CONFIG_FILES clamav-milter/Makefile" ;; + "freshclam/Makefile") CONFIG_FILES="$CONFIG_FILES freshclam/Makefile" ;; + "sigtool/Makefile") CONFIG_FILES="$CONFIG_FILES sigtool/Makefile" ;; + "clamconf/Makefile") CONFIG_FILES="$CONFIG_FILES clamconf/Makefile" ;; + "etc/Makefile") CONFIG_FILES="$CONFIG_FILES etc/Makefile" ;; + "test/Makefile") CONFIG_FILES="$CONFIG_FILES test/Makefile" ;; + "unit_tests/Makefile") CONFIG_FILES="$CONFIG_FILES unit_tests/Makefile" ;; + "clamdtop/Makefile") CONFIG_FILES="$CONFIG_FILES clamdtop/Makefile" ;; + "clambc/Makefile") CONFIG_FILES="$CONFIG_FILES clambc/Makefile" ;; + "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; + "clamav-config") CONFIG_FILES="$CONFIG_FILES clamav-config" ;; + "libclamav.pc") CONFIG_FILES="$CONFIG_FILES libclamav.pc" ;; + "platform.h") CONFIG_FILES="$CONFIG_FILES platform.h" ;; + "docs/man/clamav-milter.8") CONFIG_FILES="$CONFIG_FILES docs/man/clamav-milter.8" ;; + "docs/man/clamconf.1") CONFIG_FILES="$CONFIG_FILES docs/man/clamconf.1" ;; + "docs/man/clamd.8") CONFIG_FILES="$CONFIG_FILES docs/man/clamd.8" ;; + "docs/man/clamd.conf.5") CONFIG_FILES="$CONFIG_FILES docs/man/clamd.conf.5" ;; + "docs/man/clamdscan.1") CONFIG_FILES="$CONFIG_FILES docs/man/clamdscan.1" ;; + "docs/man/clamscan.1") CONFIG_FILES="$CONFIG_FILES docs/man/clamscan.1" ;; + "docs/man/freshclam.1") CONFIG_FILES="$CONFIG_FILES docs/man/freshclam.1" ;; + "docs/man/freshclam.conf.5") CONFIG_FILES="$CONFIG_FILES docs/man/freshclam.conf.5" ;; + "docs/man/sigtool.1") CONFIG_FILES="$CONFIG_FILES docs/man/sigtool.1" ;; + "docs/man/clamdtop.1") CONFIG_FILES="$CONFIG_FILES docs/man/clamdtop.1" ;; + "libclamav/Makefile") CONFIG_FILES="$CONFIG_FILES libclamav/Makefile" ;; + + *) as_fn_error "invalid argument: \`$ac_config_target'" "$LINENO" 5;; + esac +done + + +# If the user did not use the arguments to specify the items to instantiate, +# then the envvar interface is used. Set only those that are not. +# We use the long form for the default assignment because of an extremely +# bizarre bug on SunOS 4.1.3. +if $ac_need_defaults; then + test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files + test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers + test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands +fi + +# Have a temporary directory for convenience. Make it in the build tree +# simply because there is no reason against having it here, and in addition, +# creating and moving files from /tmp can sometimes cause problems. +# Hook for its removal unless debugging. +# Note that there is a small window in which the directory will not be cleaned: +# after its creation but before its name has been assigned to `$tmp'. +$debug || +{ + tmp= + trap 'exit_status=$? + { test -z "$tmp" || test ! -d "$tmp" || rm -fr "$tmp"; } && exit $exit_status +' 0 + trap 'as_fn_exit 1' 1 2 13 15 +} +# Create a (secure) tmp directory for tmp files. + +{ + tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && + test -n "$tmp" && test -d "$tmp" +} || +{ + tmp=./conf$$-$RANDOM + (umask 077 && mkdir "$tmp") +} || as_fn_error "cannot create a temporary directory in ." "$LINENO" 5 + +# Set up the scripts for CONFIG_FILES section. +# No need to generate them if there are no CONFIG_FILES. +# This happens for instance with `./config.status config.h'. +if test -n "$CONFIG_FILES"; then + + +ac_cr=`echo X | tr X '\015'` +# On cygwin, bash can eat \r inside `` if the user requested igncr. +# But we know of no other shell where ac_cr would be empty at this +# point, so we can use a bashism as a fallback. +if test "x$ac_cr" = x; then + eval ac_cr=\$\'\\r\' +fi +ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` +if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then + ac_cs_awk_cr='\r' +else + ac_cs_awk_cr=$ac_cr +fi + +echo 'BEGIN {' >"$tmp/subs1.awk" && +_ACEOF + + +{ + echo "cat >conf$$subs.awk <<_ACEOF" && + echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && + echo "_ACEOF" +} >conf$$subs.sh || + as_fn_error "could not make $CONFIG_STATUS" "$LINENO" 5 +ac_delim_num=`echo "$ac_subst_vars" | grep -c '$'` +ac_delim='%!_!# ' +for ac_last_try in false false false false false :; do + . ./conf$$subs.sh || + as_fn_error "could not make $CONFIG_STATUS" "$LINENO" 5 + + ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` + if test $ac_delim_n = $ac_delim_num; then + break + elif $ac_last_try; then + as_fn_error "could not make $CONFIG_STATUS" "$LINENO" 5 + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done +rm -f conf$$subs.sh + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +cat >>"\$tmp/subs1.awk" <<\\_ACAWK && +_ACEOF +sed -n ' +h +s/^/S["/; s/!.*/"]=/ +p +g +s/^[^!]*!// +:repl +t repl +s/'"$ac_delim"'$// +t delim +:nl +h +s/\(.\{148\}\)..*/\1/ +t more1 +s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ +p +n +b repl +:more1 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t nl +:delim +h +s/\(.\{148\}\)..*/\1/ +t more2 +s/["\\]/\\&/g; s/^/"/; s/$/"/ +p +b +:more2 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t delim +' >$CONFIG_STATUS || ac_write_fail=1 +rm -f conf$$subs.awk +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +_ACAWK +cat >>"\$tmp/subs1.awk" <<_ACAWK && + for (key in S) S_is_set[key] = 1 + FS = "" + +} +{ + line = $ 0 + nfields = split(line, field, "@") + substed = 0 + len = length(field[1]) + for (i = 2; i < nfields; i++) { + key = field[i] + keylen = length(key) + if (S_is_set[key]) { + value = S[key] + line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) + len += length(value) + length(field[++i]) + substed = 1 + } else + len += 1 + keylen + } + + print line +} + +_ACAWK +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then + sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" +else + cat +fi < "$tmp/subs1.awk" > "$tmp/subs.awk" \ + || as_fn_error "could not setup config files machinery" "$LINENO" 5 +_ACEOF + +# VPATH may cause trouble with some makes, so we remove $(srcdir), +# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and +# trailing colons and then remove the whole line if VPATH becomes empty +# (actually we leave an empty line to preserve line numbers). +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=/{ +s/:*\$(srcdir):*/:/ +s/:*\${srcdir}:*/:/ +s/:*@srcdir@:*/:/ +s/^\([^=]*=[ ]*\):*/\1/ +s/:*$// +s/^[^=]*=[ ]*$// +}' +fi + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +fi # test -n "$CONFIG_FILES" + +# Set up the scripts for CONFIG_HEADERS section. +# No need to generate them if there are no CONFIG_HEADERS. +# This happens for instance with `./config.status Makefile'. +if test -n "$CONFIG_HEADERS"; then +cat >"$tmp/defines.awk" <<\_ACAWK || +BEGIN { +_ACEOF + +# Transform confdefs.h into an awk script `defines.awk', embedded as +# here-document in config.status, that substitutes the proper values into +# config.h.in to produce config.h. + +# Create a delimiter string that does not exist in confdefs.h, to ease +# handling of long lines. +ac_delim='%!_!# ' +for ac_last_try in false false :; do + ac_t=`sed -n "/$ac_delim/p" confdefs.h` + if test -z "$ac_t"; then + break + elif $ac_last_try; then + as_fn_error "could not make $CONFIG_HEADERS" "$LINENO" 5 + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done + +# For the awk script, D is an array of macro values keyed by name, +# likewise P contains macro parameters if any. Preserve backslash +# newline sequences. + +ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* +sed -n ' +s/.\{148\}/&'"$ac_delim"'/g +t rset +:rset +s/^[ ]*#[ ]*define[ ][ ]*/ / +t def +d +:def +s/\\$// +t bsnl +s/["\\]/\\&/g +s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ +D["\1"]=" \3"/p +s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p +d +:bsnl +s/["\\]/\\&/g +s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ +D["\1"]=" \3\\\\\\n"\\/p +t cont +s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p +t cont +d +:cont +n +s/.\{148\}/&'"$ac_delim"'/g +t clear +:clear +s/\\$// +t bsnlc +s/["\\]/\\&/g; s/^/"/; s/$/"/p +d +:bsnlc +s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p +b cont +' >$CONFIG_STATUS || ac_write_fail=1 + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 + for (key in D) D_is_set[key] = 1 + FS = "" +} +/^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ { + line = \$ 0 + split(line, arg, " ") + if (arg[1] == "#") { + defundef = arg[2] + mac1 = arg[3] + } else { + defundef = substr(arg[1], 2) + mac1 = arg[2] + } + split(mac1, mac2, "(") #) + macro = mac2[1] + prefix = substr(line, 1, index(line, defundef) - 1) + if (D_is_set[macro]) { + # Preserve the white space surrounding the "#". + print prefix "define", macro P[macro] D[macro] + next + } else { + # Replace #undef with comments. This is necessary, for example, + # in the case of _POSIX_SOURCE, which is predefined and required + # on some systems where configure will not decide to define it. + if (defundef == "undef") { + print "/*", prefix defundef, macro, "*/" + next + } + } +} +{ print } +_ACAWK +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 + as_fn_error "could not setup config headers machinery" "$LINENO" 5 +fi # test -n "$CONFIG_HEADERS" + + +eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS :C $CONFIG_COMMANDS" +shift +for ac_tag +do + case $ac_tag in + :[FHLC]) ac_mode=$ac_tag; continue;; + esac + case $ac_mode$ac_tag in + :[FHL]*:*);; + :L* | :C*:*) as_fn_error "invalid tag \`$ac_tag'" "$LINENO" 5;; + :[FH]-) ac_tag=-:-;; + :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; + esac + ac_save_IFS=$IFS + IFS=: + set x $ac_tag + IFS=$ac_save_IFS + shift + ac_file=$1 + shift + + case $ac_mode in + :L) ac_source=$1;; + :[FH]) + ac_file_inputs= + for ac_f + do + case $ac_f in + -) ac_f="$tmp/stdin";; + *) # Look for the file first in the build tree, then in the source tree + # (if the path is not absolute). The absolute path cannot be DOS-style, + # because $ac_f cannot contain `:'. + test -f "$ac_f" || + case $ac_f in + [\\/$]*) false;; + *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; + esac || + as_fn_error "cannot find input file: \`$ac_f'" "$LINENO" 5;; + esac + case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac + as_fn_append ac_file_inputs " '$ac_f'" + done + + # Let's still pretend it is `configure' which instantiates (i.e., don't + # use $as_me), people would be surprised to read: + # /* config.h. Generated by config.status. */ + configure_input='Generated from '` + $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' + `' by configure.' + if test x"$ac_file" != x-; then + configure_input="$ac_file. $configure_input" + { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 +$as_echo "$as_me: creating $ac_file" >&6;} + fi + # Neutralize special characters interpreted by sed in replacement strings. + case $configure_input in #( + *\&* | *\|* | *\\* ) + ac_sed_conf_input=`$as_echo "$configure_input" | + sed 's/[\\\\&|]/\\\\&/g'`;; #( + *) ac_sed_conf_input=$configure_input;; + esac + + case $ac_tag in + *:-:* | *:-) cat >"$tmp/stdin" \ + || as_fn_error "could not create $ac_file" "$LINENO" 5 ;; + esac + ;; + esac + + ac_dir=`$as_dirname -- "$ac_file" || +$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + as_dir="$ac_dir"; as_fn_mkdir_p + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + + case $ac_mode in + :F) + # + # CONFIG_FILE + # + + case $INSTALL in + [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; + *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; + esac + ac_MKDIR_P=$MKDIR_P + case $MKDIR_P in + [\\/$]* | ?:[\\/]* ) ;; + */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;; + esac +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# If the template does not know about datarootdir, expand it. +# FIXME: This hack should be removed a few years after 2.60. +ac_datarootdir_hack=; ac_datarootdir_seen= +ac_sed_dataroot=' +/datarootdir/ { + p + q +} +/@datadir@/p +/@docdir@/p +/@infodir@/p +/@localedir@/p +/@mandir@/p' +case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in +*datarootdir*) ac_datarootdir_seen=yes;; +*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 +$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 + ac_datarootdir_hack=' + s&@datadir@&$datadir&g + s&@docdir@&$docdir&g + s&@infodir@&$infodir&g + s&@localedir@&$localedir&g + s&@mandir@&$mandir&g + s&\\\${datarootdir}&$datarootdir&g' ;; +esac +_ACEOF + +# Neutralize VPATH when `$srcdir' = `.'. +# Shell code in configure.ac might set extrasub. +# FIXME: do we really want to maintain this feature? +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_sed_extra="$ac_vpsub +$extrasub +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +:t +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b +s|@configure_input@|$ac_sed_conf_input|;t t +s&@top_builddir@&$ac_top_builddir_sub&;t t +s&@top_build_prefix@&$ac_top_build_prefix&;t t +s&@srcdir@&$ac_srcdir&;t t +s&@abs_srcdir@&$ac_abs_srcdir&;t t +s&@top_srcdir@&$ac_top_srcdir&;t t +s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t +s&@builddir@&$ac_builddir&;t t +s&@abs_builddir@&$ac_abs_builddir&;t t +s&@abs_top_builddir@&$ac_abs_top_builddir&;t t +s&@INSTALL@&$ac_INSTALL&;t t +s&@MKDIR_P@&$ac_MKDIR_P&;t t +$ac_datarootdir_hack +" +eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$tmp/subs.awk" >$tmp/out \ + || as_fn_error "could not create $ac_file" "$LINENO" 5 + +test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && + { ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } && + { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' "$tmp/out"`; test -z "$ac_out"; } && + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined." >&5 +$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined." >&2;} + + rm -f "$tmp/stdin" + case $ac_file in + -) cat "$tmp/out" && rm -f "$tmp/out";; + *) rm -f "$ac_file" && mv "$tmp/out" "$ac_file";; + esac \ + || as_fn_error "could not create $ac_file" "$LINENO" 5 + ;; + :H) + # + # CONFIG_HEADER + # + if test x"$ac_file" != x-; then + { + $as_echo "/* $configure_input */" \ + && eval '$AWK -f "$tmp/defines.awk"' "$ac_file_inputs" + } >"$tmp/config.h" \ + || as_fn_error "could not create $ac_file" "$LINENO" 5 + if diff "$ac_file" "$tmp/config.h" >/dev/null 2>&1; then + { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 +$as_echo "$as_me: $ac_file is unchanged" >&6;} + else + rm -f "$ac_file" + mv "$tmp/config.h" "$ac_file" \ + || as_fn_error "could not create $ac_file" "$LINENO" 5 + fi + else + $as_echo "/* $configure_input */" \ + && eval '$AWK -f "$tmp/defines.awk"' "$ac_file_inputs" \ + || as_fn_error "could not create -" "$LINENO" 5 + fi +# Compute "$ac_file"'s index in $config_headers. +_am_arg="$ac_file" +_am_stamp_count=1 +for _am_header in $config_headers :; do + case $_am_header in + $_am_arg | $_am_arg:* ) + break ;; + * ) + _am_stamp_count=`expr $_am_stamp_count + 1` ;; + esac +done +echo "timestamp for $_am_arg" >`$as_dirname -- "$_am_arg" || +$as_expr X"$_am_arg" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$_am_arg" : 'X\(//\)[^/]' \| \ + X"$_am_arg" : 'X\(//\)$' \| \ + X"$_am_arg" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$_am_arg" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'`/stamp-h$_am_stamp_count + ;; + + :C) { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5 +$as_echo "$as_me: executing $ac_file commands" >&6;} + ;; + esac + + + case $ac_file$ac_mode in + "depfiles":C) test x"$AMDEP_TRUE" != x"" || { + # Autoconf 2.62 quotes --file arguments for eval, but not when files + # are listed without --file. Let's play safe and only enable the eval + # if we detect the quoting. + case $CONFIG_FILES in + *\'*) eval set x "$CONFIG_FILES" ;; + *) set x $CONFIG_FILES ;; + esac + shift + for mf + do + # Strip MF so we end up with the name of the file. + mf=`echo "$mf" | sed -e 's/:.*$//'` + # Check whether this is an Automake generated Makefile or not. + # We used to match only the files named `Makefile.in', but + # some people rename them; so instead we look at the file content. + # Grep'ing the first line is not enough: some people post-process + # each Makefile.in and add a new line on top of each file to say so. + # Grep'ing the whole file is not good either: AIX grep has a line + # limit of 2048, but all sed's we know have understand at least 4000. + if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then + dirpart=`$as_dirname -- "$mf" || +$as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$mf" : 'X\(//\)[^/]' \| \ + X"$mf" : 'X\(//\)$' \| \ + X"$mf" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$mf" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + else + continue + fi + # Extract the definition of DEPDIR, am__include, and am__quote + # from the Makefile without running `make'. + DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` + test -z "$DEPDIR" && continue + am__include=`sed -n 's/^am__include = //p' < "$mf"` + test -z "am__include" && continue + am__quote=`sed -n 's/^am__quote = //p' < "$mf"` + # When using ansi2knr, U may be empty or an underscore; expand it + U=`sed -n 's/^U = //p' < "$mf"` + # Find all dependency output files, they are included files with + # $(DEPDIR) in their names. We invoke sed twice because it is the + # simplest approach to changing $(DEPDIR) to its actual value in the + # expansion. + for file in `sed -n " + s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ + sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do + # Make sure the directory exists. + test -f "$dirpart/$file" && continue + fdir=`$as_dirname -- "$file" || +$as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$file" : 'X\(//\)[^/]' \| \ + X"$file" : 'X\(//\)$' \| \ + X"$file" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + as_dir=$dirpart/$fdir; as_fn_mkdir_p + # echo "creating $dirpart/$file" + echo '# dummy' > "$dirpart/$file" + done + done +} + ;; + "libtool":C) + + # See if we are running on zsh, and set the options which allow our + # commands through without removal of \ escapes. + if test -n "${ZSH_VERSION+set}" ; then + setopt NO_GLOB_SUBST + fi + + cfgfile="${ofile}T" + trap "$RM \"$cfgfile\"; exit 1" 1 2 15 + $RM "$cfgfile" + + cat <<_LT_EOF >> "$cfgfile" +#! $SHELL + +# `$ECHO "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services. +# Generated automatically by $as_me ($PACKAGE$TIMESTAMP) $VERSION +# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: +# NOTE: Changes made to this file will be lost: look at ltmain.sh. +# +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, +# 2006, 2007, 2008 Free Software Foundation, Inc. +# Written by Gordon Matzigkeit, 1996 +# +# This file is part of GNU Libtool. +# +# GNU Libtool is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# As a special exception to the GNU General Public License, +# if you distribute this file as part of a program or library that +# is built using GNU Libtool, you may include this file under the +# same distribution terms that you use for the rest of that program. +# +# GNU Libtool is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Libtool; see the file COPYING. If not, a copy +# can be downloaded from http://www.gnu.org/licenses/gpl.html, or +# obtained by writing to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + +# The names of the tagged configurations supported by this script. +available_tags="" + +# ### BEGIN LIBTOOL CONFIG + +# Which release of libtool.m4 was used? +macro_version=$macro_version +macro_revision=$macro_revision + +# Whether or not to build static libraries. +build_old_libs=$enable_static + +# Whether or not to build shared libraries. +build_libtool_libs=$enable_shared + +# What type of objects to build. +pic_mode=$pic_mode + +# Whether or not to optimize for fast installation. +fast_install=$enable_fast_install + +# The host system. +host_alias=$host_alias +host=$host +host_os=$host_os + +# The build system. +build_alias=$build_alias +build=$build +build_os=$build_os + +# A sed program that does not truncate output. +SED=$lt_SED + +# Sed that helps us avoid accidentally triggering echo(1) options like -n. +Xsed="\$SED -e 1s/^X//" + +# A grep program that handles long lines. +GREP=$lt_GREP + +# An ERE matcher. +EGREP=$lt_EGREP + +# A literal string matcher. +FGREP=$lt_FGREP + +# A BSD- or MS-compatible name lister. +NM=$lt_NM + +# Whether we need soft or hard links. +LN_S=$lt_LN_S + +# What is the maximum length of a command? +max_cmd_len=$max_cmd_len + +# Object file suffix (normally "o"). +objext=$ac_objext + +# Executable file suffix (normally ""). +exeext=$exeext + +# whether the shell understands "unset". +lt_unset=$lt_unset + +# turn spaces into newlines. +SP2NL=$lt_lt_SP2NL + +# turn newlines into spaces. +NL2SP=$lt_lt_NL2SP + +# How to create reloadable object files. +reload_flag=$lt_reload_flag +reload_cmds=$lt_reload_cmds + +# An object symbol dumper. +OBJDUMP=$lt_OBJDUMP + +# Method to check whether dependent libraries are shared objects. +deplibs_check_method=$lt_deplibs_check_method + +# Command to use when deplibs_check_method == "file_magic". +file_magic_cmd=$lt_file_magic_cmd + +# The archiver. +AR=$lt_AR +AR_FLAGS=$lt_AR_FLAGS + +# A symbol stripping program. +STRIP=$lt_STRIP + +# Commands used to install an old-style archive. +RANLIB=$lt_RANLIB +old_postinstall_cmds=$lt_old_postinstall_cmds +old_postuninstall_cmds=$lt_old_postuninstall_cmds + +# A C compiler. +LTCC=$lt_CC + +# LTCC compiler flags. +LTCFLAGS=$lt_CFLAGS + +# Take the output of nm and produce a listing of raw symbols and C names. +global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe + +# Transform the output of nm in a proper C declaration. +global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl + +# Transform the output of nm in a C name address pair. +global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address + +# Transform the output of nm in a C name address pair when lib prefix is needed. +global_symbol_to_c_name_address_lib_prefix=$lt_lt_cv_sys_global_symbol_to_c_name_address_lib_prefix + +# The name of the directory that contains temporary libtool files. +objdir=$objdir + +# Shell to use when invoking shell scripts. +SHELL=$lt_SHELL + +# An echo program that does not interpret backslashes. +ECHO=$lt_ECHO + +# Used to examine libraries when file_magic_cmd begins with "file". +MAGIC_CMD=$MAGIC_CMD + +# Must we lock files when doing compilation? +need_locks=$lt_need_locks + +# Tool to manipulate archived DWARF debug symbol files on Mac OS X. +DSYMUTIL=$lt_DSYMUTIL + +# Tool to change global to local symbols on Mac OS X. +NMEDIT=$lt_NMEDIT + +# Tool to manipulate fat objects and archives on Mac OS X. +LIPO=$lt_LIPO + +# ldd/readelf like tool for Mach-O binaries on Mac OS X. +OTOOL=$lt_OTOOL + +# ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4. +OTOOL64=$lt_OTOOL64 + +# Old archive suffix (normally "a"). +libext=$libext + +# Shared library suffix (normally ".so"). +shrext_cmds=$lt_shrext_cmds + +# The commands to extract the exported symbol list from a shared archive. +extract_expsyms_cmds=$lt_extract_expsyms_cmds + +# Variables whose values should be saved in libtool wrapper scripts and +# restored at link time. +variables_saved_for_relink=$lt_variables_saved_for_relink + +# Do we need the "lib" prefix for modules? +need_lib_prefix=$need_lib_prefix + +# Do we need a version for libraries? +need_version=$need_version + +# Library versioning type. +version_type=$version_type + +# Shared library runtime path variable. +runpath_var=$runpath_var + +# Shared library path variable. +shlibpath_var=$shlibpath_var + +# Is shlibpath searched before the hard-coded library search path? +shlibpath_overrides_runpath=$shlibpath_overrides_runpath + +# Format of library name prefix. +libname_spec=$lt_libname_spec + +# List of archive names. First name is the real one, the rest are links. +# The last name is the one that the linker finds with -lNAME +library_names_spec=$lt_library_names_spec + +# The coded name of the library, if different from the real name. +soname_spec=$lt_soname_spec + +# Command to use after installation of a shared archive. +postinstall_cmds=$lt_postinstall_cmds + +# Command to use after uninstallation of a shared archive. +postuninstall_cmds=$lt_postuninstall_cmds + +# Commands used to finish a libtool library installation in a directory. +finish_cmds=$lt_finish_cmds + +# As "finish_cmds", except a single script fragment to be evaled but +# not shown. +finish_eval=$lt_finish_eval + +# Whether we should hardcode library paths into libraries. +hardcode_into_libs=$hardcode_into_libs + +# Compile-time system search path for libraries. +sys_lib_search_path_spec=$lt_sys_lib_search_path_spec + +# Run-time system search path for libraries. +sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec + +# Whether dlopen is supported. +dlopen_support=$enable_dlopen + +# Whether dlopen of programs is supported. +dlopen_self=$enable_dlopen_self + +# Whether dlopen of statically linked programs is supported. +dlopen_self_static=$enable_dlopen_self_static + +# Commands to strip libraries. +old_striplib=$lt_old_striplib +striplib=$lt_striplib + + +# The linker used to build libraries. +LD=$lt_LD + +# Commands used to build an old-style archive. +old_archive_cmds=$lt_old_archive_cmds + +# A language specific compiler. +CC=$lt_compiler + +# Is the compiler the GNU compiler? +with_gcc=$GCC + +# Compiler flag to turn off builtin functions. +no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag + +# How to pass a linker flag through the compiler. +wl=$lt_lt_prog_compiler_wl + +# Additional compiler flags for building library objects. +pic_flag=$lt_lt_prog_compiler_pic + +# Compiler flag to prevent dynamic linking. +link_static_flag=$lt_lt_prog_compiler_static + +# Does compiler simultaneously support -c and -o options? +compiler_c_o=$lt_lt_cv_prog_compiler_c_o + +# Whether or not to add -lc for building shared libraries. +build_libtool_need_lc=$archive_cmds_need_lc + +# Whether or not to disallow shared libs when runtime libs are static. +allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes + +# Compiler flag to allow reflexive dlopens. +export_dynamic_flag_spec=$lt_export_dynamic_flag_spec + +# Compiler flag to generate shared objects directly from archives. +whole_archive_flag_spec=$lt_whole_archive_flag_spec + +# Whether the compiler copes with passing no objects directly. +compiler_needs_object=$lt_compiler_needs_object + +# Create an old-style archive from a shared archive. +old_archive_from_new_cmds=$lt_old_archive_from_new_cmds + +# Create a temporary old-style archive to link instead of a shared archive. +old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds + +# Commands used to build a shared archive. +archive_cmds=$lt_archive_cmds +archive_expsym_cmds=$lt_archive_expsym_cmds + +# Commands used to build a loadable module if different from building +# a shared archive. +module_cmds=$lt_module_cmds +module_expsym_cmds=$lt_module_expsym_cmds + +# Whether we are building with GNU ld or not. +with_gnu_ld=$lt_with_gnu_ld + +# Flag that allows shared libraries with undefined symbols to be built. +allow_undefined_flag=$lt_allow_undefined_flag + +# Flag that enforces no undefined symbols. +no_undefined_flag=$lt_no_undefined_flag + +# Flag to hardcode \$libdir into a binary during linking. +# This must work even if \$libdir does not exist +hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec + +# If ld is used when linking, flag to hardcode \$libdir into a binary +# during linking. This must work even if \$libdir does not exist. +hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld + +# Whether we need a single "-rpath" flag with a separated argument. +hardcode_libdir_separator=$lt_hardcode_libdir_separator + +# Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes +# DIR into the resulting binary. +hardcode_direct=$hardcode_direct + +# Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes +# DIR into the resulting binary and the resulting library dependency is +# "absolute",i.e impossible to change by setting \${shlibpath_var} if the +# library is relocated. +hardcode_direct_absolute=$hardcode_direct_absolute + +# Set to "yes" if using the -LDIR flag during linking hardcodes DIR +# into the resulting binary. +hardcode_minus_L=$hardcode_minus_L + +# Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR +# into the resulting binary. +hardcode_shlibpath_var=$hardcode_shlibpath_var + +# Set to "yes" if building a shared library automatically hardcodes DIR +# into the library and all subsequent libraries and executables linked +# against it. +hardcode_automatic=$hardcode_automatic + +# Set to yes if linker adds runtime paths of dependent libraries +# to runtime path list. +inherit_rpath=$inherit_rpath + +# Whether libtool must link a program against all its dependency libraries. +link_all_deplibs=$link_all_deplibs + +# Fix the shell variable \$srcfile for the compiler. +fix_srcfile_path=$lt_fix_srcfile_path + +# Set to "yes" if exported symbols are required. +always_export_symbols=$always_export_symbols + +# The commands to list exported symbols. +export_symbols_cmds=$lt_export_symbols_cmds + +# Symbols that should not be listed in the preloaded symbols. +exclude_expsyms=$lt_exclude_expsyms + +# Symbols that must always be exported. +include_expsyms=$lt_include_expsyms + +# Commands necessary for linking programs (against libraries) with templates. +prelink_cmds=$lt_prelink_cmds + +# Specify filename containing input files. +file_list_spec=$lt_file_list_spec + +# How to hardcode a shared library path into an executable. +hardcode_action=$hardcode_action + +# ### END LIBTOOL CONFIG + +_LT_EOF + + case $host_os in + aix3*) + cat <<\_LT_EOF >> "$cfgfile" +# AIX sometimes has problems with the GCC collect2 program. For some +# reason, if we set the COLLECT_NAMES environment variable, the problems +# vanish in a puff of smoke. +if test "X${COLLECT_NAMES+set}" != Xset; then + COLLECT_NAMES= + export COLLECT_NAMES +fi +_LT_EOF + ;; + esac + + +ltmain="$ac_aux_dir/ltmain.sh" + + + # We use sed instead of cat because bash on DJGPP gets confused if + # if finds mixed CR/LF and LF-only lines. Since sed operates in + # text mode, it properly converts lines to CR/LF. This bash problem + # is reportedly fixed, but why not run on old versions too? + sed '/^# Generated shell functions inserted here/q' "$ltmain" >> "$cfgfile" \ + || (rm -f "$cfgfile"; exit 1) + + case $xsi_shell in + yes) + cat << \_LT_EOF >> "$cfgfile" + +# func_dirname file append nondir_replacement +# Compute the dirname of FILE. If nonempty, add APPEND to the result, +# otherwise set result to NONDIR_REPLACEMENT. +func_dirname () +{ + case ${1} in + */*) func_dirname_result="${1%/*}${2}" ;; + * ) func_dirname_result="${3}" ;; + esac +} + +# func_basename file +func_basename () +{ + func_basename_result="${1##*/}" +} + +# func_dirname_and_basename file append nondir_replacement +# perform func_basename and func_dirname in a single function +# call: +# dirname: Compute the dirname of FILE. If nonempty, +# add APPEND to the result, otherwise set result +# to NONDIR_REPLACEMENT. +# value returned in "$func_dirname_result" +# basename: Compute filename of FILE. +# value retuned in "$func_basename_result" +# Implementation must be kept synchronized with func_dirname +# and func_basename. For efficiency, we do not delegate to +# those functions but instead duplicate the functionality here. +func_dirname_and_basename () +{ + case ${1} in + */*) func_dirname_result="${1%/*}${2}" ;; + * ) func_dirname_result="${3}" ;; + esac + func_basename_result="${1##*/}" +} + +# func_stripname prefix suffix name +# strip PREFIX and SUFFIX off of NAME. +# PREFIX and SUFFIX must not contain globbing or regex special +# characters, hashes, percent signs, but SUFFIX may contain a leading +# dot (in which case that matches only a dot). +func_stripname () +{ + # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are + # positional parameters, so assign one to ordinary parameter first. + func_stripname_result=${3} + func_stripname_result=${func_stripname_result#"${1}"} + func_stripname_result=${func_stripname_result%"${2}"} +} + +# func_opt_split +func_opt_split () +{ + func_opt_split_opt=${1%%=*} + func_opt_split_arg=${1#*=} +} + +# func_lo2o object +func_lo2o () +{ + case ${1} in + *.lo) func_lo2o_result=${1%.lo}.${objext} ;; + *) func_lo2o_result=${1} ;; + esac +} + +# func_xform libobj-or-source +func_xform () +{ + func_xform_result=${1%.*}.lo +} + +# func_arith arithmetic-term... +func_arith () +{ + func_arith_result=$(( $* )) +} + +# func_len string +# STRING may not start with a hyphen. +func_len () +{ + func_len_result=${#1} +} + +_LT_EOF + ;; + *) # Bourne compatible functions. + cat << \_LT_EOF >> "$cfgfile" + +# func_dirname file append nondir_replacement +# Compute the dirname of FILE. If nonempty, add APPEND to the result, +# otherwise set result to NONDIR_REPLACEMENT. +func_dirname () +{ + # Extract subdirectory from the argument. + func_dirname_result=`$ECHO "X${1}" | $Xsed -e "$dirname"` + if test "X$func_dirname_result" = "X${1}"; then + func_dirname_result="${3}" + else + func_dirname_result="$func_dirname_result${2}" + fi +} + +# func_basename file +func_basename () +{ + func_basename_result=`$ECHO "X${1}" | $Xsed -e "$basename"` +} + + +# func_stripname prefix suffix name +# strip PREFIX and SUFFIX off of NAME. +# PREFIX and SUFFIX must not contain globbing or regex special +# characters, hashes, percent signs, but SUFFIX may contain a leading +# dot (in which case that matches only a dot). +# func_strip_suffix prefix name +func_stripname () +{ + case ${2} in + .*) func_stripname_result=`$ECHO "X${3}" \ + | $Xsed -e "s%^${1}%%" -e "s%\\\\${2}\$%%"`;; + *) func_stripname_result=`$ECHO "X${3}" \ + | $Xsed -e "s%^${1}%%" -e "s%${2}\$%%"`;; + esac +} + +# sed scripts: +my_sed_long_opt='1s/^\(-[^=]*\)=.*/\1/;q' +my_sed_long_arg='1s/^-[^=]*=//' + +# func_opt_split +func_opt_split () +{ + func_opt_split_opt=`$ECHO "X${1}" | $Xsed -e "$my_sed_long_opt"` + func_opt_split_arg=`$ECHO "X${1}" | $Xsed -e "$my_sed_long_arg"` +} + +# func_lo2o object +func_lo2o () +{ + func_lo2o_result=`$ECHO "X${1}" | $Xsed -e "$lo2o"` +} + +# func_xform libobj-or-source +func_xform () +{ + func_xform_result=`$ECHO "X${1}" | $Xsed -e 's/\.[^.]*$/.lo/'` +} + +# func_arith arithmetic-term... +func_arith () +{ + func_arith_result=`expr "$@"` +} + +# func_len string +# STRING may not start with a hyphen. +func_len () +{ + func_len_result=`expr "$1" : ".*" 2>/dev/null || echo $max_cmd_len` +} + +_LT_EOF +esac + +case $lt_shell_append in + yes) + cat << \_LT_EOF >> "$cfgfile" + +# func_append var value +# Append VALUE to the end of shell variable VAR. +func_append () +{ + eval "$1+=\$2" +} +_LT_EOF + ;; + *) + cat << \_LT_EOF >> "$cfgfile" + +# func_append var value +# Append VALUE to the end of shell variable VAR. +func_append () +{ + eval "$1=\$$1\$2" +} + +_LT_EOF + ;; + esac + + + sed -n '/^# Generated shell functions inserted here/,$p' "$ltmain" >> "$cfgfile" \ + || (rm -f "$cfgfile"; exit 1) + + mv -f "$cfgfile" "$ofile" || + (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") + chmod +x "$ofile" + + ;; + + esac +done # for ac_tag + + +as_fn_exit 0 +_ACEOF +ac_clean_files=$ac_clean_files_save + +test $ac_write_fail = 0 || + as_fn_error "write failure creating $CONFIG_STATUS" "$LINENO" 5 + + +# configure is writing to config.log, and then calls config.status. +# config.status does its own redirection, appending to config.log. +# Unfortunately, on DOS this fails, as config.log is still kept open +# by configure, so config.status won't be able to write to it; its +# output is simply discarded. So we exec the FD to /dev/null, +# effectively closing config.log, so it can be properly (re)opened and +# appended to by config.status. When coming back to configure, we +# need to make the FD available again. +if test "$no_create" != yes; then + ac_cs_success=: + ac_config_status_args= + test "$silent" = yes && + ac_config_status_args="$ac_config_status_args --quiet" + exec 5>/dev/null + $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false + exec 5>>config.log + # Use ||, not &&, to avoid exiting from the if with $? = 1, which + # would make configure fail if this is the last instruction. + $ac_cs_success || as_fn_exit $? +fi + + + +# +# CONFIG_SUBDIRS section. +# +if test "$no_recursion" != yes; then + + # Remove --cache-file, --srcdir, and --disable-option-checking arguments + # so they do not pile up. + ac_sub_configure_args= + ac_prev= + eval "set x $ac_configure_args" + shift + for ac_arg + do + if test -n "$ac_prev"; then + ac_prev= + continue + fi + case $ac_arg in + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* \ + | --c=*) + ;; + --config-cache | -C) + ;; + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + ;; + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + ;; + --disable-option-checking) + ;; + *) + case $ac_arg in + *\'*) ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + as_fn_append ac_sub_configure_args " '$ac_arg'" ;; + esac + done + + # Always prepend --prefix to ensure using the same prefix + # in subdir configurations. + ac_arg="--prefix=$prefix" + case $ac_arg in + *\'*) ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + ac_sub_configure_args="'$ac_arg' $ac_sub_configure_args" + + # Pass --silent + if test "$silent" = yes; then + ac_sub_configure_args="--silent $ac_sub_configure_args" + fi + + # Always prepend --disable-option-checking to silence warnings, since + # different subdirs can have different --enable and --with options. + ac_sub_configure_args="--disable-option-checking $ac_sub_configure_args" + + ac_popdir=`pwd` + for ac_dir in : $subdirs; do test "x$ac_dir" = x: && continue + + # Do not complain, so a configure script can configure whichever + # parts of a large source tree are present. + test -d "$srcdir/$ac_dir" || continue + + ac_msg="=== configuring in $ac_dir (`pwd`/$ac_dir)" + $as_echo "$as_me:${as_lineno-$LINENO}: $ac_msg" >&5 + $as_echo "$ac_msg" >&6 + as_dir="$ac_dir"; as_fn_mkdir_p + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + + cd "$ac_dir" + + # Check for guested configure; otherwise get Cygnus style configure. + if test -f "$ac_srcdir/configure.gnu"; then + ac_sub_configure=$ac_srcdir/configure.gnu + elif test -f "$ac_srcdir/configure"; then + ac_sub_configure=$ac_srcdir/configure + elif test -f "$ac_srcdir/configure.in"; then + # This should be Cygnus configure. + ac_sub_configure=$ac_aux_dir/configure + else + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: no configuration information is in $ac_dir" >&5 +$as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2;} + ac_sub_configure= + fi + + # The recursion is here. + if test -n "$ac_sub_configure"; then + # Make the cache file name correct relative to the subdirectory. + case $cache_file in + [\\/]* | ?:[\\/]* ) ac_sub_cache_file=$cache_file ;; + *) # Relative name. + ac_sub_cache_file=$ac_top_build_prefix$cache_file ;; + esac + + { $as_echo "$as_me:${as_lineno-$LINENO}: running $SHELL $ac_sub_configure $ac_sub_configure_args --cache-file=$ac_sub_cache_file --srcdir=$ac_srcdir" >&5 +$as_echo "$as_me: running $SHELL $ac_sub_configure $ac_sub_configure_args --cache-file=$ac_sub_cache_file --srcdir=$ac_srcdir" >&6;} + # The eval makes quoting arguments work. + eval "\$SHELL \"\$ac_sub_configure\" $ac_sub_configure_args \ + --cache-file=\"\$ac_sub_cache_file\" --srcdir=\"\$ac_srcdir\"" || + subdirfailed=yes + fi + + cd "$ac_popdir" + done +fi + + if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} fi diff --git a/configure.in b/configure.in index 5c7284e47..c0f8c083b 100644 --- a/configure.in +++ b/configure.in @@ -58,7 +58,7 @@ AC_PROG_LN_S AC_PROG_MAKE_SET LT_CONFIG_LTDL_DIR([libltdl]) -LT_INIT([dlopen]) +LT_INIT([dlopen disable-static]) LTDL_INIT([recursive]) AC_CONFIG_FILES([libltdl/Makefile]) @@ -1530,8 +1530,16 @@ if test "x$enable_distcheckwerror" = "xyes"; then fi fi +AC_ARG_ENABLE([llvm],AC_HELP_STRING([--enable-llvm], + [Enable 'llvm' JIT/verifier support @<:@default=auto@:>@]), + [enable_llvm=$enableval], [enable_llvm="auto"]) + +if test "$enable_llvm" != "no"; then + dnl Try to configure subdir, optionally + AC_CONFIG_SUBDIRS_OPTIONAL([libclamav/c++]) +fi + AC_OUTPUT([ -libclamav/Makefile clamscan/Makefile database/Makefile docs/Makefile @@ -1562,6 +1570,14 @@ docs/man/sigtool.1 docs/man/clamdtop.1 ]) +if test "$enable_llvm" = "yes" && test "$subdirfailed" != "no"; then + AC_MSG_ERROR([Failed to configure LLVM, and LLVM was explicitly requested]) +fi +AM_CONDITIONAL([ENABLE_LLVM], + [test "$subdirfailed" != "yes" && test "$enable_llvm" != "no"]) +no_recursion="yes"; +AC_OUTPUT([libclamav/Makefile]) + # Yep, downgrading the compiler avoids the bug too: # 4.0.x, and 4.1.0 are the known buggy versions # 3.4 doesn't have the bug diff --git a/database/Makefile.in b/database/Makefile.in index 13dc84408..6ffb997ed 100644 --- a/database/Makefile.in +++ b/database/Makefile.in @@ -60,9 +60,9 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/acinclude.m4 \ $(top_srcdir)/m4/argz.m4 $(top_srcdir)/m4/fdpassing.m4 \ $(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \ $(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/m4/libtool.m4 \ - $(top_srcdir)/m4/ltdl.m4 $(top_srcdir)/m4/ltoptions.m4 \ - $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ - $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/m4/llvm.m4 $(top_srcdir)/m4/ltdl.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/mmap_private.m4 $(top_srcdir)/m4/resolv.m4 \ $(top_srcdir)/configure.in am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ @@ -228,6 +228,7 @@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ +subdirs = @subdirs@ sys_symbol_underscore = @sys_symbol_underscore@ sysconfdir = @sysconfdir@ target = @target@ diff --git a/docs/Makefile.in b/docs/Makefile.in index 7d9ade2b4..b9c977f7e 100644 --- a/docs/Makefile.in +++ b/docs/Makefile.in @@ -59,9 +59,9 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/acinclude.m4 \ $(top_srcdir)/m4/argz.m4 $(top_srcdir)/m4/fdpassing.m4 \ $(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \ $(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/m4/libtool.m4 \ - $(top_srcdir)/m4/ltdl.m4 $(top_srcdir)/m4/ltoptions.m4 \ - $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ - $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/m4/llvm.m4 $(top_srcdir)/m4/ltdl.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/mmap_private.m4 $(top_srcdir)/m4/resolv.m4 \ $(top_srcdir)/configure.in am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ @@ -255,6 +255,7 @@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ +subdirs = @subdirs@ sys_symbol_underscore = @sys_symbol_underscore@ sysconfdir = @sysconfdir@ target = @target@ diff --git a/etc/Makefile.in b/etc/Makefile.in index 7d85dcf90..64f3abff2 100644 --- a/etc/Makefile.in +++ b/etc/Makefile.in @@ -59,9 +59,9 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/acinclude.m4 \ $(top_srcdir)/m4/argz.m4 $(top_srcdir)/m4/fdpassing.m4 \ $(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \ $(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/m4/libtool.m4 \ - $(top_srcdir)/m4/ltdl.m4 $(top_srcdir)/m4/ltoptions.m4 \ - $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ - $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/m4/llvm.m4 $(top_srcdir)/m4/ltdl.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/mmap_private.m4 $(top_srcdir)/m4/resolv.m4 \ $(top_srcdir)/configure.in am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ @@ -227,6 +227,7 @@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ +subdirs = @subdirs@ sys_symbol_underscore = @sys_symbol_underscore@ sysconfdir = @sysconfdir@ target = @target@ diff --git a/freshclam/Makefile.in b/freshclam/Makefile.in index ac74f88d4..072f11dd3 100644 --- a/freshclam/Makefile.in +++ b/freshclam/Makefile.in @@ -62,9 +62,9 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/acinclude.m4 \ $(top_srcdir)/m4/argz.m4 $(top_srcdir)/m4/fdpassing.m4 \ $(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \ $(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/m4/libtool.m4 \ - $(top_srcdir)/m4/ltdl.m4 $(top_srcdir)/m4/ltoptions.m4 \ - $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ - $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/m4/llvm.m4 $(top_srcdir)/m4/ltdl.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/mmap_private.m4 $(top_srcdir)/m4/resolv.m4 \ $(top_srcdir)/configure.in am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ @@ -264,6 +264,7 @@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ +subdirs = @subdirs@ sys_symbol_underscore = @sys_symbol_underscore@ sysconfdir = @sysconfdir@ target = @target@ diff --git a/libclamav/Makefile.am b/libclamav/Makefile.am index 564c593a7..c846f5063 100644 --- a/libclamav/Makefile.am +++ b/libclamav/Makefile.am @@ -17,11 +17,8 @@ # MA 02110-1301, USA. AM_CPPFLAGS = -I$(top_srcdir) -I@srcdir@/nsis $(LTDLINCL) - lib_LTLIBRARIES = EXTRA_DIST = - - if ENABLE_UNRAR AM_CPPFLAGS += -DWARN_DLOPEN_FAIL @@ -114,8 +111,19 @@ libclamav_internal_utils_nothreads_la_SOURCES=str.c\ libclamav_internal_utils_nothreads_la_LDFLAGS=-static libclamav_internal_utils_nothreads_la_CFLAGS=-DCL_NOTHREADS -libclamav_la_LIBADD = @LIBLTDL@ $(IFACELIBADD) libclamav_internal_utils.la @LIBCLAMAV_LIBS@ @THREAD_LIBS@ @LIBM@ -libclamav_la_DEPENDENCIES = @LTDLDEPS@ $(IFACEDEP) libclamav_internal_utils.la +if ENABLE_LLVM +LLVMLIBADD=c++/libclamavcxx.la -lstdc++ -lm +LLVMDEP=c++/libclamavcxx.la +SUBDIRS=c++ +else +LLVMLIBADD=libclamav_nocxx.la +LLVMDEP=libclamav_nocxx.la +endif + +libclamav_nocxx_la_SOURCES = bytecode_nojit.c + +libclamav_la_LIBADD = @LIBLTDL@ $(IFACELIBADD) $(LLVMLIBADD) libclamav_internal_utils.la @LIBCLAMAV_LIBS@ @THREAD_LIBS@ @LIBM@ +libclamav_la_DEPENDENCIES = @LTDLDEPS@ $(IFACEDEP) $(LLVMDEP) libclamav_internal_utils.la libclamav_la_CFLAGS = -DSEARCH_LIBDIR=\"$(libdir)\" libclamav_la_LDFLAGS = @TH_SAFE@ -version-info @LIBCLAMAV_VERSION@ -no-undefined @@ -331,9 +339,12 @@ libclamav_la_SOURCES = \ ishield.c \ ishield.h \ type_desc.h \ + bcfeatures.h \ bytecode_api.c \ bytecode_api_decl.c \ - bytecode_api.h + bytecode_api.h \ + bytecode_api_impl.h \ + bytecode_hooks.h if !LINK_TOMMATH libclamav_la_SOURCES += bignum.c \ @@ -366,7 +377,7 @@ version.h.tmp: fi lib_LTLIBRARIES += libclamav.la -noinst_LTLIBRARIES = libclamav_internal_utils.la libclamav_internal_utils_nothreads.la +noinst_LTLIBRARIES = libclamav_internal_utils.la libclamav_internal_utils_nothreads.la libclamav_nocxx.la EXTRA_DIST += regex/engine.c libclamav.map \ jsparse/generated/operators.h jsparse/generated/keywords.h jsparse/future_reserved_words.list\ jsparse/keywords.list jsparse/special_keywords.list jsparse/operators.gperf diff --git a/libclamav/Makefile.in b/libclamav/Makefile.in index 2bf842d49..4a428cfe1 100644 --- a/libclamav/Makefile.in +++ b/libclamav/Makefile.in @@ -74,9 +74,9 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/acinclude.m4 \ $(top_srcdir)/m4/argz.m4 $(top_srcdir)/m4/fdpassing.m4 \ $(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \ $(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/m4/libtool.m4 \ - $(top_srcdir)/m4/ltdl.m4 $(top_srcdir)/m4/ltoptions.m4 \ - $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ - $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/m4/llvm.m4 $(top_srcdir)/m4/ltdl.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/mmap_private.m4 $(top_srcdir)/m4/resolv.m4 \ $(top_srcdir)/configure.in am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ @@ -109,6 +109,8 @@ am__base_list = \ am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(includedir)" LTLIBRARIES = $(lib_LTLIBRARIES) $(noinst_LTLIBRARIES) @ENABLE_UNRAR_TRUE@am__DEPENDENCIES_1 = libclamunrar_iface.la +@ENABLE_LLVM_FALSE@am__DEPENDENCIES_2 = libclamav_nocxx.la +@ENABLE_LLVM_TRUE@am__DEPENDENCIES_2 = c++/libclamavcxx.la am__libclamav_la_SOURCES_DIST = clamav.h matcher-ac.c matcher-ac.h \ matcher-bm.c matcher-bm.h matcher.c matcher.h others.c \ others.h readdb.c readdb.h cvd.c cvd.h dsig.c dsig.h \ @@ -148,8 +150,9 @@ am__libclamav_la_SOURCES_DIST = clamav.h matcher-ac.c matcher-ac.h \ uniq.h version.c version.h mpool.c mpool.h fmap.c fmap.h \ default.h sha256.c sha256.h bignum.h bytecode.c bytecode.h \ bytecode_vm.c bytecode_priv.h clambc.h cpio.c cpio.h macho.c \ - macho.h ishield.c ishield.h type_desc.h bytecode_api.c \ - bytecode_api_decl.c bytecode_api.h bignum.c bignum_class.h + macho.h ishield.c ishield.h type_desc.h bcfeatures.h \ + bytecode_api.c bytecode_api_decl.c bytecode_api.h \ + bytecode_api_impl.h bytecode_hooks.h bignum.c bignum_class.h @LINK_TOMMATH_FALSE@am__objects_1 = libclamav_la-bignum.lo am_libclamav_la_OBJECTS = libclamav_la-matcher-ac.lo \ libclamav_la-matcher-bm.lo libclamav_la-matcher.lo \ @@ -241,6 +244,9 @@ libclamav_internal_utils_nothreads_la_LINK = $(LIBTOOL) $(AM_V_lt) \ $(CCLD) $(libclamav_internal_utils_nothreads_la_CFLAGS) \ $(CFLAGS) $(libclamav_internal_utils_nothreads_la_LDFLAGS) \ $(LDFLAGS) -o $@ +libclamav_nocxx_la_LIBADD = +am_libclamav_nocxx_la_OBJECTS = bytecode_nojit.lo +libclamav_nocxx_la_OBJECTS = $(am_libclamav_nocxx_la_OBJECTS) libclamunrar_la_LIBADD = am__libclamunrar_la_SOURCES_DIST = ../libclamunrar/unrar15.c \ ../libclamunrar/unrar20.h ../libclamunrar/unrar.h \ @@ -301,16 +307,56 @@ am__v_GEN_0 = @echo " GEN " $@; SOURCES = $(libclamav_la_SOURCES) \ $(libclamav_internal_utils_la_SOURCES) \ $(libclamav_internal_utils_nothreads_la_SOURCES) \ - $(libclamunrar_la_SOURCES) $(libclamunrar_iface_la_SOURCES) + $(libclamav_nocxx_la_SOURCES) $(libclamunrar_la_SOURCES) \ + $(libclamunrar_iface_la_SOURCES) DIST_SOURCES = $(am__libclamav_la_SOURCES_DIST) \ $(libclamav_internal_utils_la_SOURCES) \ $(libclamav_internal_utils_nothreads_la_SOURCES) \ + $(libclamav_nocxx_la_SOURCES) \ $(am__libclamunrar_la_SOURCES_DIST) \ $(am__libclamunrar_iface_la_SOURCES_DIST) +RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ + html-recursive info-recursive install-data-recursive \ + install-dvi-recursive install-exec-recursive \ + install-html-recursive install-info-recursive \ + install-pdf-recursive install-ps-recursive install-recursive \ + installcheck-recursive installdirs-recursive pdf-recursive \ + ps-recursive uninstall-recursive HEADERS = $(include_HEADERS) +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \ + $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \ + distdir ETAGS = etags CTAGS = ctags +DIST_SUBDIRS = c++ DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ @@ -459,6 +505,7 @@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ +subdirs = @subdirs@ sys_symbol_underscore = @sys_symbol_underscore@ sysconfdir = @sysconfdir@ target = @target@ @@ -548,8 +595,14 @@ libclamav_internal_utils_nothreads_la_SOURCES = str.c\ libclamav_internal_utils_nothreads_la_LDFLAGS = -static libclamav_internal_utils_nothreads_la_CFLAGS = -DCL_NOTHREADS -libclamav_la_LIBADD = @LIBLTDL@ $(IFACELIBADD) libclamav_internal_utils.la @LIBCLAMAV_LIBS@ @THREAD_LIBS@ @LIBM@ -libclamav_la_DEPENDENCIES = @LTDLDEPS@ $(IFACEDEP) libclamav_internal_utils.la +@ENABLE_LLVM_FALSE@LLVMLIBADD = libclamav_nocxx.la +@ENABLE_LLVM_TRUE@LLVMLIBADD = c++/libclamavcxx.la -lstdc++ -lm +@ENABLE_LLVM_FALSE@LLVMDEP = libclamav_nocxx.la +@ENABLE_LLVM_TRUE@LLVMDEP = c++/libclamavcxx.la +@ENABLE_LLVM_TRUE@SUBDIRS = c++ +libclamav_nocxx_la_SOURCES = bytecode_nojit.c +libclamav_la_LIBADD = @LIBLTDL@ $(IFACELIBADD) $(LLVMLIBADD) libclamav_internal_utils.la @LIBCLAMAV_LIBS@ @THREAD_LIBS@ @LIBM@ +libclamav_la_DEPENDENCIES = @LTDLDEPS@ $(IFACEDEP) $(LLVMDEP) libclamav_internal_utils.la libclamav_la_CFLAGS = -DSEARCH_LIBDIR=\"$(libdir)\" libclamav_la_LDFLAGS = @TH_SAFE@ -version-info @LIBCLAMAV_VERSION@ \ -no-undefined $(am__append_6) @@ -593,16 +646,17 @@ libclamav_la_SOURCES = clamav.h matcher-ac.c matcher-ac.h matcher-bm.c \ uniq.h version.c version.h mpool.c mpool.h fmap.c fmap.h \ default.h sha256.c sha256.h bignum.h bytecode.c bytecode.h \ bytecode_vm.c bytecode_priv.h clambc.h cpio.c cpio.h macho.c \ - macho.h ishield.c ishield.h type_desc.h bytecode_api.c \ - bytecode_api_decl.c bytecode_api.h $(am__append_7) -noinst_LTLIBRARIES = libclamav_internal_utils.la libclamav_internal_utils_nothreads.la + macho.h ishield.c ishield.h type_desc.h bcfeatures.h \ + bytecode_api.c bytecode_api_decl.c bytecode_api.h \ + bytecode_api_impl.h bytecode_hooks.h $(am__append_7) +noinst_LTLIBRARIES = libclamav_internal_utils.la libclamav_internal_utils_nothreads.la libclamav_nocxx.la COMMON_CLEANFILES = version.h version.h.tmp *.gcda *.gcno @MAINTAINER_MODE_TRUE@BUILT_SOURCES = jsparse/generated/operators.h jsparse/generated/keywords.h jsparse-keywords.gperf @MAINTAINER_MODE_TRUE@GPERF_FLAGS = -E -t -L ANSI-C -C -F ', TOK_ERROR' -c @MAINTAINER_MODE_FALSE@CLEANFILES = $(COMMON_CLEANFILES) @MAINTAINER_MODE_TRUE@CLEANFILES = $(COMMON_CLEANFILES) @srcdir@/jsparse/generated/operators.h @srcdir@/jsparse/generated/keywords.h all: $(BUILT_SOURCES) - $(MAKE) $(AM_MAKEFLAGS) all-am + $(MAKE) $(AM_MAKEFLAGS) all-recursive .SUFFIXES: .SUFFIXES: .c .lo .o .obj @@ -682,6 +736,8 @@ libclamav_internal_utils.la: $(libclamav_internal_utils_la_OBJECTS) $(libclamav_ $(AM_V_CCLD)$(libclamav_internal_utils_la_LINK) $(libclamav_internal_utils_la_OBJECTS) $(libclamav_internal_utils_la_LIBADD) $(LIBS) libclamav_internal_utils_nothreads.la: $(libclamav_internal_utils_nothreads_la_OBJECTS) $(libclamav_internal_utils_nothreads_la_DEPENDENCIES) $(AM_V_CCLD)$(libclamav_internal_utils_nothreads_la_LINK) $(libclamav_internal_utils_nothreads_la_OBJECTS) $(libclamav_internal_utils_nothreads_la_LIBADD) $(LIBS) +libclamav_nocxx.la: $(libclamav_nocxx_la_OBJECTS) $(libclamav_nocxx_la_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) $(libclamav_nocxx_la_OBJECTS) $(libclamav_nocxx_la_LIBADD) $(LIBS) libclamunrar.la: $(libclamunrar_la_OBJECTS) $(libclamunrar_la_DEPENDENCIES) $(AM_V_CCLD)$(libclamunrar_la_LINK) $(am_libclamunrar_la_rpath) $(libclamunrar_la_OBJECTS) $(libclamunrar_la_LIBADD) $(LIBS) libclamunrar_iface.la: $(libclamunrar_iface_la_OBJECTS) $(libclamunrar_iface_la_DEPENDENCIES) @@ -693,6 +749,7 @@ mostlyclean-compile: distclean-compile: -rm -f *.tab.c +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bytecode_nojit.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libclamav_internal_utils_la-md5.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libclamav_internal_utils_la-others_common.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libclamav_internal_utils_la-qsort.Plo@am__quote@ @@ -1851,6 +1908,76 @@ uninstall-includeHEADERS: echo " ( cd '$(DESTDIR)$(includedir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(includedir)" && rm -f $$files +# This directory's subdirectories are mostly independent; you can cd +# into them and run `make' without going through this Makefile. +# To change the values of `make' variables: instead of editing Makefiles, +# (1) if the variable is set in `config.status', edit `config.status' +# (which will cause the Makefiles to be regenerated when you run `make'); +# (2) otherwise, pass the desired values on the `make' command line. +$(RECURSIVE_TARGETS): + @failcom='exit 1'; \ + for f in x $$MAKEFLAGS; do \ + case $$f in \ + *=* | --[!k]*);; \ + *k*) failcom='fail=yes';; \ + esac; \ + done; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +$(RECURSIVE_CLEAN_TARGETS): + @failcom='exit 1'; \ + for f in x $$MAKEFLAGS; do \ + case $$f in \ + *=* | --[!k]*);; \ + *k*) failcom='fail=yes';; \ + esac; \ + done; \ + dot_seen=no; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + rev=''; for subdir in $$list; do \ + if test "$$subdir" = "."; then :; else \ + rev="$$subdir $$rev"; \ + fi; \ + done; \ + rev="$$rev ."; \ + target=`echo $@ | sed s/-recursive//`; \ + for subdir in $$rev; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done && test -z "$$fail" +tags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ + done +ctags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ + done + ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ @@ -1861,10 +1988,23 @@ ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) mkid -fID $$unique tags: TAGS -TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ +TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) set x; \ here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ @@ -1883,7 +2023,7 @@ TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ fi; \ fi ctags: CTAGS -CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ +CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ @@ -1933,24 +2073,53 @@ distdir: $(DISTFILES) || exit 1; \ fi; \ done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done check-am: all-am check: $(BUILT_SOURCES) - $(MAKE) $(AM_MAKEFLAGS) check-am + $(MAKE) $(AM_MAKEFLAGS) check-recursive all-am: Makefile $(LTLIBRARIES) $(HEADERS) -installdirs: +installdirs: installdirs-recursive +installdirs-am: for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(includedir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: $(BUILT_SOURCES) - $(MAKE) $(AM_MAKEFLAGS) install-am -install-exec: install-exec-am -install-data: install-data-am -uninstall: uninstall-am + $(MAKE) $(AM_MAKEFLAGS) install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am -installcheck: installcheck-am +installcheck: installcheck-recursive install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ @@ -1969,94 +2138,97 @@ maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) -clean: clean-am +clean: clean-recursive clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \ clean-noinstLTLIBRARIES mostlyclean-am -distclean: distclean-am +distclean: distclean-recursive -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags -dvi: dvi-am +dvi: dvi-recursive dvi-am: -html: html-am +html: html-recursive html-am: -info: info-am +info: info-recursive info-am: install-data-am: install-includeHEADERS -install-dvi: install-dvi-am +install-dvi: install-dvi-recursive install-dvi-am: install-exec-am: install-libLTLIBRARIES -install-html: install-html-am +install-html: install-html-recursive install-html-am: -install-info: install-info-am +install-info: install-info-recursive install-info-am: install-man: -install-pdf: install-pdf-am +install-pdf: install-pdf-recursive install-pdf-am: -install-ps: install-ps-am +install-ps: install-ps-recursive install-ps-am: installcheck-am: -maintainer-clean: maintainer-clean-am +maintainer-clean: maintainer-clean-recursive -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic -mostlyclean: mostlyclean-am +mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool -pdf: pdf-am +pdf: pdf-recursive pdf-am: -ps: ps-am +ps: ps-recursive ps-am: uninstall-am: uninstall-includeHEADERS uninstall-libLTLIBRARIES -.MAKE: all check install install-am install-strip +.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) all check \ + ctags-recursive install install-am install-strip \ + tags-recursive -.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ +.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \ + all all-am check check-am clean clean-generic \ clean-libLTLIBRARIES clean-libtool clean-noinstLTLIBRARIES \ - ctags distclean distclean-compile distclean-generic \ - distclean-libtool distclean-tags distdir dvi dvi-am html \ - html-am info info-am install install-am install-data \ - install-data-am install-dvi install-dvi-am install-exec \ - install-exec-am install-html install-html-am \ + ctags ctags-recursive distclean distclean-compile \ + distclean-generic distclean-libtool distclean-tags distdir dvi \ + dvi-am html html-am info info-am install install-am \ + install-data install-data-am install-dvi install-dvi-am \ + install-exec install-exec-am install-html install-html-am \ install-includeHEADERS install-info install-info-am \ install-libLTLIBRARIES install-man install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ - installcheck-am installdirs maintainer-clean \ + installcheck-am installdirs installdirs-am maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ - tags uninstall uninstall-am uninstall-includeHEADERS \ - uninstall-libLTLIBRARIES + tags tags-recursive uninstall uninstall-am \ + uninstall-includeHEADERS uninstall-libLTLIBRARIES .PHONY: version.h.tmp diff --git a/libclamav/bcfeatures.h b/libclamav/bcfeatures.h new file mode 100644 index 000000000..4763b2cb3 --- /dev/null +++ b/libclamav/bcfeatures.h @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2009 Sourcefire, Inc. + * All rights reserved. + * Authors: Török Edvin + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#ifndef BC_FEATURES_H +#define BC_FEATURES_H + +/* Compatibility for non-clang compilers */ +#ifndef __has_feature +#define __has_feature(x) 0 +#endif + +#if __has_feature(attribute_bounds) +#define EBOUNDS(fieldname) __attribute__((bounds(fieldname))) +#else +#define EBOUNDS(x) +#endif + +#endif diff --git a/libclamav/bytecode.c b/libclamav/bytecode.c index de3bb0750..44e02dd50 100644 --- a/libclamav/bytecode.c +++ b/libclamav/bytecode.c @@ -26,11 +26,15 @@ #include "clamav.h" #include "others.h" +#include "pe.h" #include "bytecode.h" #include "bytecode_priv.h" #include "readdb.h" #include +/* TODO: we should make sure lsigcnt is never NULL, and has at least as many + * elements as the bytecode needs */ +static const uint32_t nomatch[64]; struct cli_bc_ctx *cli_bytecode_context_alloc(void) { struct cli_bc_ctx *ctx = cli_malloc(sizeof(*ctx)); @@ -39,6 +43,25 @@ struct cli_bc_ctx *cli_bytecode_context_alloc(void) ctx->values = NULL; ctx->operands = NULL; ctx->opsizes = NULL; + ctx->fmap = NULL; + ctx->off = 0; + ctx->ctx = NULL; + ctx->hooks.match_counts = nomatch; + /* TODO: init all hooks with safe values */ + ctx->virname = NULL; + ctx->outfd = -1; + ctx->tempfile = NULL; + ctx->written = 0; + ctx->trace_level = trace_none; + ctx->trace = NULL; + ctx->trace_op = NULL; + ctx->trace_val = NULL; + ctx->scope = NULL; + ctx->scopeid = 0; + ctx->file = "??"; + ctx->directory = ""; + ctx->line = 0; + ctx->col = 0; return ctx; } @@ -48,17 +71,49 @@ void cli_bytecode_context_destroy(struct cli_bc_ctx *ctx) free(ctx); } -int cli_bytecode_context_clear(struct cli_bc_ctx *ctx) +int cli_bytecode_context_getresult_file(struct cli_bc_ctx *ctx, char **tempfilename) +{ + int fd; + *tempfilename = ctx->tempfile; + fd = ctx->outfd; + ctx->tempfile = NULL; + ctx->outfd = -1; + return fd; +} + +/* resets bytecode state, so you can run another bytecode with same ctx */ +int cli_bytecode_context_reset(struct cli_bc_ctx *ctx) { free(ctx->opsizes); free(ctx->values); free(ctx->operands); + ctx->operands = NULL; + ctx->values = NULL; + ctx->opsizes = NULL; + ctx->written = 0; + if (ctx->outfd != -1) { + cli_dbgmsg("Bytecode: nobody cared about FD %d, %s\n", ctx->outfd, + ctx->tempfile); + ftruncate(ctx->outfd, 0); + close(ctx->outfd); + cli_unlink(ctx->tempfile); + free(ctx->tempfile); + ctx->tempfile = NULL; + ctx->outfd = -1; + } + return CL_SUCCESS; +} + +int cli_bytecode_context_clear(struct cli_bc_ctx *ctx) +{ + cli_bytecode_context_reset(ctx); memset(ctx, 0, sizeof(ctx)); return CL_SUCCESS; } static unsigned typesize(const struct cli_bc *bc, uint16_t type) { + type &= 0x7fff; if (!type) return 0; if (type <= 8) @@ -69,13 +124,17 @@ static unsigned typesize(const struct cli_bc *bc, uint16_t type) return 4; if (type <= 64) return 8; - return 0; + return bc->types[type-65].size; } static unsigned typealign(const struct cli_bc *bc, uint16_t type) { - unsigned size = typesize(bc, type); - return size ? size : 1; + type &= 0x7fff; + if (type <= 64) { + unsigned size = typesize(bc, type); + return size ? size : 1; + } + return bc->types[type-65].align; } int cli_bytecode_context_setfuncid(struct cli_bc_ctx *ctx, const struct cli_bc *bc, unsigned funcid) @@ -263,9 +322,8 @@ static inline operand_t readOperand(struct cli_bc_func *func, unsigned char *p, *dest= 0; ty = 8*readFixedNumber(p, off, len, ok, 1); if (!ty) { - cli_errmsg("bytecode: void type constant is invalid!\n"); - *ok = 0; - return MAX_OP; + /* This is a global variable */ + return 0x80000000 | v; } if (ty <= 8) *(uint8_t*)dest = v; @@ -299,7 +357,7 @@ static inline unsigned char *readData(const unsigned char *p, unsigned *off, uns } (*off)++; l = readNumber(p, off, len, ok); - if (!l) { + if (!l || !ok) { *datalen = l; return NULL; } @@ -345,12 +403,13 @@ static inline char *readString(const unsigned char *p, unsigned *off, unsigned l return str; } -static int parseHeader(struct cli_bc *bc, unsigned char *buffer) +static int parseHeader(struct cli_bc *bc, unsigned char *buffer, unsigned *linelength) { uint64_t magic1; unsigned magic2; char ok = 1; unsigned offset, len, flevel; + char *pos; if (strncmp((const char*)buffer, BC_HEADER, sizeof(BC_HEADER)-1)) { cli_errmsg("Missing file magic in bytecode"); return CL_EMALFDB; @@ -362,7 +421,7 @@ static int parseHeader(struct cli_bc *bc, unsigned char *buffer) cli_errmsg("Unable to parse functionality level in bytecode header\n"); return CL_EMALFDB; } - if (flevel > BC_FUNC_LEVEL) { + if (flevel != BC_FUNC_LEVEL) { cli_dbgmsg("Skipping bytecode with functionality level: %u\n", flevel); return CL_BREAK; } @@ -370,6 +429,7 @@ static int parseHeader(struct cli_bc *bc, unsigned char *buffer) bc->verifier = readNumber(buffer, &offset, len, &ok); bc->sigmaker = readString(buffer, &offset, len, &ok); bc->id = readNumber(buffer, &offset, len, &ok); + bc->kind = readNumber(buffer, &offset, len, &ok); bc->metadata.maxStack = readNumber(buffer, &offset, len, &ok); bc->metadata.maxMem = readNumber(buffer, &offset, len, &ok); bc->metadata.maxTime = readNumber(buffer, &offset, len, &ok); @@ -378,6 +438,8 @@ static int parseHeader(struct cli_bc *bc, unsigned char *buffer) bc->num_func = readNumber(buffer, &offset, len, &ok); bc->state = bc_loaded; bc->uses_apis = NULL; + bc->dbgnodes = NULL; + bc->dbgnode_cnt = 0; if (!ok) { cli_errmsg("Invalid bytecode header at %u\n", offset); return CL_EMALFDB; @@ -390,9 +452,14 @@ static int parseHeader(struct cli_bc *bc, unsigned char *buffer) cli_errmsg("Magic numbers don't match: %lx%lx, %u\n", m0, m1, magic2); return CL_EMALFDB; } - if (offset != len) { - cli_errmsg("Trailing garbage in bytecode header: %d extra bytes\n", - len-offset); + if (buffer[offset] != ':') { + cli_errmsg("Expected : but found: %c\n", buffer[offset]); + return CL_EMALFDB; + } + offset++; + *linelength = strtol(buffer+offset, &pos, 10); + if (*pos != '\n') { + cli_errmsg("Invalid number: %s\n", buffer+offset); return CL_EMALFDB; } @@ -409,6 +476,23 @@ static int parseHeader(struct cli_bc *bc, unsigned char *buffer) return CL_SUCCESS; } +static int parseLSig(struct cli_bc *bc, unsigned char *buffer) +{ + const char *prefix; + char *vnames, *vend = strchr(buffer, ';'); + if (vend) { + bc->lsig = cli_strdup(buffer); + *vend++ = '\0'; + prefix = buffer; + vnames = strchr(vend, '{'); + } else { + /* Not a logical signature, but we still have a virusname */ + bc->lsig = NULL; + } + + return CL_SUCCESS; +} + static uint16_t readTypeID(struct cli_bc *bc, unsigned char *buffer, unsigned *offset, unsigned len, char *ok) { @@ -429,7 +513,7 @@ static void parseType(struct cli_bc *bc, struct cli_bc_type *ty, { unsigned j; - ty->numElements = readFixedNumber(buffer, off, len, ok, 1); + ty->numElements = readNumber(buffer, off, len, ok); if (!ok) { cli_errmsg("Error parsing type\n"); *ok = 0; @@ -453,9 +537,10 @@ static void add_static_types(struct cli_bc *bc) { unsigned i; for (i=0;itypes[i].kind = PointerType; + bc->types[i].kind = DPointerType; bc->types[i].numElements = 1; bc->types[i].containedTypes = &containedTy[i]; + bc->types[i].size = bc->types[i].align = sizeof(void*); } } @@ -475,7 +560,7 @@ static int parseTypes(struct cli_bc *bc, unsigned char *buffer) return CL_BREAK; } add_static_types(bc); - for (i=(BC_START_TID - 64);inum_types;i++) { + for (i=(BC_START_TID - 65);inum_types-1;i++) { struct cli_bc_type *ty = &bc->types[i]; uint8_t t = readFixedNumber(buffer, &offset, len, &ok, 1); if (!ok) { @@ -484,16 +569,22 @@ static int parseTypes(struct cli_bc *bc, unsigned char *buffer) } switch (t) { case 1: - ty->kind = FunctionType; + ty->kind = DFunctionType; + ty->size = ty->align = sizeof(void*); parseType(bc, ty, buffer, &offset, len, &ok); if (!ok) { cli_errmsg("Error parsing type %u\n", i); return CL_EMALFDB; } + if (!ty->numElements) { + cli_errmsg("Function with no return type? %u\n", i); + return CL_EMALFDB; + } break; case 2: case 3: - ty->kind = (t == 2) ? StructType : PackedStructType; + ty->kind = (t == 2) ? DPackedStructType : DStructType; + ty->size = ty->align = 0;/* TODO:calculate size/align of structs */ parseType(bc, ty, buffer, &offset, len, &ok); if (!ok) { cli_errmsg("Error parsing type %u\n", i); @@ -501,7 +592,7 @@ static int parseTypes(struct cli_bc *bc, unsigned char *buffer) } break; case 4: - ty->kind = ArrayType; + ty->kind = DArrayType; /* number of elements of array, not subtypes! */ ty->numElements = readNumber(buffer, &offset, len, &ok); if (!ok) { @@ -511,7 +602,7 @@ static int parseTypes(struct cli_bc *bc, unsigned char *buffer) /* fall-through */ case 5: if (t == 5) { - ty->kind = PointerType; + ty->kind = DPointerType; ty->numElements = 1; } ty->containedTypes = cli_malloc(sizeof(*ty->containedTypes)); @@ -524,6 +615,12 @@ static int parseTypes(struct cli_bc *bc, unsigned char *buffer) cli_errmsg("Error parsing type %u\n", i); return CL_EMALFDB; } + if (t == 5) { + ty->size = ty->align = sizeof(void*); + } else { + ty->size = ty->numElements*typesize(bc, ty->containedTypes[0]); + ty->align = typealign(bc, ty->containedTypes[0]); + } break; default: cli_errmsg("Invalid type kind: %u\n", t); @@ -538,7 +635,7 @@ static int parseTypes(struct cli_bc *bc, unsigned char *buffer) static int types_equal(const struct cli_bc *bc, uint16_t *apity2ty, uint16_t tid, uint16_t apitid) { unsigned i; - const struct cli_bc_type *ty = &bc->types[tid - 63]; + const struct cli_bc_type *ty = &bc->types[tid - 65]; const struct cli_bc_type *apity = &cli_apicall_types[apitid]; /* If we've already verified type equality, return. * Since we need to check equality of recursive types, we assume types are @@ -634,6 +731,159 @@ static int parseApis(struct cli_bc *bc, unsigned char *buffer) return CL_SUCCESS; } +static uint16_t type_components(struct cli_bc *bc, uint16_t id, char *ok) +{ + unsigned i, sum=0; + const struct cli_bc_type *ty; + if (id <= 64) + return 1; + ty = &bc->types[id-65]; + /* TODO: protect against recursive types */ + switch (ty->kind) { + case DFunctionType: + cli_errmsg("bytecode: function type not accepted for constant: %u\n", id); + /* don't accept functions as constant initializers */ + *ok = 0; + return 0; + case DPointerType: + return 2; + case DStructType: + case DPackedStructType: + for (i=0;inumElements;i++) { + sum += type_components(bc, ty->containedTypes[i], ok); + } + return sum; + case DArrayType: + return type_components(bc, ty->containedTypes[0], ok)*ty->numElements; + default: + *ok = 0; + return 0; + } +} + +static void readConstant(struct cli_bc *bc, unsigned i, unsigned comp, + unsigned char *buffer, unsigned *offset, + unsigned len, char *ok) +{ + unsigned j=0; + while (*ok && buffer[*offset] != 0x60) { + if (j >= comp) { + cli_errmsg("bytecode: constant has too many subcomponents, expected %u\n", comp); + *ok = 0; + return; + } + buffer[*offset] |= 0x20; + bc->globals[i][j++] = readNumber(buffer, offset, len, ok); + } + if (*ok && j != comp) { + cli_errmsg("bytecode: constant has too few subcomponents: %u < %u\n", j, comp); + } + (*offset)++; +} + +/* parse constant globals with constant initializers */ +static int parseGlobals(struct cli_bc *bc, unsigned char *buffer) +{ + unsigned i, offset = 1, len = strlen((const char*)buffer), numglobals; + unsigned maxglobal; + char ok=1; + + if (buffer[0] != 'G') { + cli_errmsg("bytecode: Invalid globals header: %c\n", buffer[0]); + return CL_EMALFDB; + } + maxglobal = readNumber(buffer, &offset, len, &ok); + if (maxglobal > cli_apicall_maxglobal) { + cli_dbgmsg("bytecode using global %u, but highest global known to libclamav is %u, skipping\n", maxglobal, cli_apicall_maxglobal); + return CL_BREAK; + } + numglobals = readNumber(buffer, &offset, len, &ok); + bc->globals = cli_calloc(numglobals, sizeof(*bc->globals)); + if (!bc->globals) { + cli_errmsg("bytecode: OOM allocating memory for %u globals\n", numglobals); + return CL_EMEM; + } + bc->globaltys = cli_calloc(numglobals, sizeof(*bc->globaltys)); + if (!bc->globaltys) { + cli_errmsg("bytecode: OOM allocating memory for %u global types\n", numglobals); + return CL_EMEM; + } + bc->num_globals = numglobals; + if (!ok) + return CL_EMALFDB; + for (i=0;iglobaltys[i] = readTypeID(bc, buffer, &offset, len, &ok); + comp = type_components(bc, bc->globaltys[i], &ok); + if (!ok) + return CL_EMALFDB; + bc->globals[i] = cli_malloc(sizeof(bc->globals[0])*comp); + if (!bc->globals[i]) + return CL_EMEM; + readConstant(bc, i, comp, buffer, &offset, len, &ok); + } + if (!ok) + return CL_EMALFDB; + if (offset != len) { + cli_errmsg("Trailing garbage in globals: %d extra bytes\n", + len-offset); + return CL_EMALFDB; + } + return CL_SUCCESS; +} + +static int parseMD(struct cli_bc *bc, unsigned char *buffer) +{ + unsigned offset = 1, len = strlen(buffer); + unsigned numMD, i, b; + char ok = 1; + if (buffer[0] != 'D') + return CL_EMALFDB; + numMD = readNumber(buffer, &offset, len, &ok); + if (!ok) { + cli_errmsg("Unable to parse number of MD nodes\n"); + return CL_EMALFDB; + } + b = bc->dbgnode_cnt; + bc->dbgnode_cnt += numMD; + bc->dbgnodes = cli_realloc(bc->dbgnodes, bc->dbgnode_cnt * sizeof(*bc->dbgnodes)); + if (!bc->dbgnodes) + return CL_EMEM; + for (i=0;idbgnodes[b+i].numelements = el; + bc->dbgnodes[b+i].elements = elts = cli_calloc(el, sizeof(*elts)); + if (!elts) + return CL_EMEM; + for (j=0;jdbgnode_cnt); + return CL_SUCCESS; +} + static int parseFunctionHeader(struct cli_bc *bc, unsigned fn, unsigned char *buffer) { char ok=1; @@ -654,6 +904,7 @@ static int parseFunctionHeader(struct cli_bc *bc, unsigned fn, unsigned char *bu } offset = 1; func->numArgs = readFixedNumber(buffer, &offset, len, &ok, 1); + func->returnType = readTypeID(bc, buffer, &offset, len, &ok); if (buffer[offset] != 'L') { cli_errmsg("Invalid function locals header: %c\n", buffer[offset]); return CL_EMALFDB; @@ -672,6 +923,8 @@ static int parseFunctionHeader(struct cli_bc *bc, unsigned fn, unsigned char *bu } for (i=0;itypes[i] = readNumber(buffer, &offset, len, &ok); + if (readFixedNumber(buffer, &offset, len, &ok, 1)) + func->types[i] |= 0x8000; } if (!ok) { cli_errmsg("Invalid local types\n"); @@ -766,26 +1019,26 @@ static int parseBB(struct cli_bc *bc, unsigned func, unsigned bb, unsigned char cli_errmsg("Invalid type or operand\n"); return CL_EMALFDB; } - if (inst.opcode >= OP_INVALID) { + if (inst.opcode >= OP_BC_INVALID) { cli_errmsg("Invalid opcode: %u\n", inst.opcode); return CL_EMALFDB; } switch (inst.opcode) { - case OP_JMP: + case OP_BC_JMP: inst.u.jump = readBBID(bcfunc, buffer, &offset, len, &ok); break; - case OP_RET: + case OP_BC_RET: inst.type = readNumber(buffer, &offset, len, &ok); inst.u.unaryop = readOperand(bcfunc, buffer, &offset, len, &ok); break; - case OP_BRANCH: + case OP_BC_BRANCH: inst.u.branch.condition = readOperand(bcfunc, buffer, &offset, len, &ok); inst.u.branch.br_true = readBBID(bcfunc, buffer, &offset, len, &ok); inst.u.branch.br_false = readBBID(bcfunc, buffer, &offset, len, &ok); break; - case OP_CALL_API:/* fall-through */ - case OP_CALL_DIRECT: + case OP_BC_CALL_API:/* fall-through */ + case OP_BC_CALL_DIRECT: numOp = readFixedNumber(buffer, &offset, len, &ok, 1); if (ok) { inst.u.ops.numOps = numOp; @@ -795,7 +1048,7 @@ static int parseBB(struct cli_bc *bc, unsigned func, unsigned bb, unsigned char cli_errmsg("Out of memory allocating operands\n"); return CL_EMALFDB; } - if (inst.opcode == OP_CALL_DIRECT) + if (inst.opcode == OP_BC_CALL_DIRECT) inst.u.ops.funcid = readFuncID(bc, buffer, &offset, len, &ok); else inst.u.ops.funcid = readAPIFuncID(bc, buffer, &offset, len, &ok); @@ -804,9 +1057,9 @@ static int parseBB(struct cli_bc *bc, unsigned func, unsigned bb, unsigned char } } break; - case OP_ZEXT: - case OP_SEXT: - case OP_TRUNC: + case OP_BC_ZEXT: + case OP_BC_SEXT: + case OP_BC_TRUNC: inst.u.cast.source = readOperand(bcfunc, buffer, &offset, len, &ok); inst.u.cast.mask = bcfunc->types[inst.u.cast.source]; if (inst.u.cast.mask == 1) @@ -820,27 +1073,29 @@ static int parseBB(struct cli_bc *bc, unsigned func, unsigned bb, unsigned char else if (inst.u.cast.mask <= 64) inst.u.cast.size = 4; /* calculate mask */ - if (inst.opcode != OP_SEXT) + if (inst.opcode != OP_BC_SEXT) inst.u.cast.mask = inst.u.cast.mask != 64 ? (1ull<= len) + return CL_EMALFDB; + num = readNumber(buffer, &offset, len, &ok); + if (!ok) + return CL_EMALFDB; + if (num != bcfunc->numInsts) { + cli_errmsg("invalid number of dbg nodes, expected: %u, got: %u\n", bcfunc->numInsts, num); + return CL_EMALFDB; + } + bcfunc->dbgnodes = cli_malloc(num*sizeof(*bcfunc->dbgnodes)); + if (!bcfunc->dbgnodes) + return CL_EMEM; + for (i=0;idbgnodes[i] = readNumber(buffer, &offset, len, &ok); + if (!ok) + return CL_EMALFDB; + } + } if (offset != len) { cli_errmsg("Trailing garbage in basicblock: %d extra bytes\n", len-offset); @@ -899,9 +1175,11 @@ static int parseBB(struct cli_bc *bc, unsigned func, unsigned bb, unsigned char } enum parse_state { - PARSE_BC_HEADER=0, - PARSE_BC_TYPES, + PARSE_BC_TYPES=0, PARSE_BC_APIS, + PARSE_BC_GLOBALS, + PARSE_BC_LSIG, + PARSE_MD_OPT_HEADER, PARSE_FUNC_HEADER, PARSE_BB }; @@ -909,24 +1187,49 @@ enum parse_state { int cli_bytecode_load(struct cli_bc *bc, FILE *f, struct cli_dbio *dbio) { unsigned row = 0, current_func = 0, bb=0; - char buffer[FILEBUFF]; - enum parse_state state = PARSE_BC_HEADER; + char *buffer; + unsigned linelength=0; + char firstbuf[FILEBUFF]; + enum parse_state state; + int rc; if (!f && !dbio) { cli_errmsg("Unable to load bytecode (null file)\n"); return CL_ENULLARG; } - while (cli_dbgets(buffer, FILEBUFF, f, dbio)) { - int rc; + if (!cli_dbgets(firstbuf, FILEBUFF, f, dbio)) { + cli_errmsg("Unable to load bytecode (empty file)\n"); + return CL_EMALFDB; + } + rc = parseHeader(bc, (unsigned char*)firstbuf, &linelength); + if (rc == CL_BREAK) { + bc->state = bc_skip; + return CL_SUCCESS; + } + if (rc != CL_SUCCESS) { + cli_errmsg("Error at bytecode line %u\n", row); + return rc; + } + buffer = cli_malloc(linelength); + if (!buffer) { + cli_errmsg("Out of memory allocating line of length %u\n", linelength); + return CL_EMEM; + } + state = PARSE_BC_LSIG; + while (cli_dbgets(buffer, linelength, f, dbio)) { cli_chomp(buffer); row++; switch (state) { - case PARSE_BC_HEADER: - rc = parseHeader(bc, (unsigned char*)buffer); - if (rc == CL_BREAK) /* skip */ + case PARSE_BC_LSIG: + rc = parseLSig(bc, (unsigned char*)buffer); + if (rc == CL_BREAK) /* skip */ { + bc->state = bc_skip; + free(buffer); return CL_SUCCESS; + } if (rc != CL_SUCCESS) { cli_errmsg("Error at bytecode line %u\n", row); + free(buffer); return rc; } state = PARSE_BC_TYPES; @@ -935,24 +1238,55 @@ int cli_bytecode_load(struct cli_bc *bc, FILE *f, struct cli_dbio *dbio) rc = parseTypes(bc, (unsigned char*)buffer); if (rc != CL_SUCCESS) { cli_errmsg("Error at bytecode line %u\n", row); + free(buffer); return rc; } state = PARSE_BC_APIS; break; case PARSE_BC_APIS: rc = parseApis(bc, (unsigned char*)buffer); - if (rc == CL_BREAK) /* skip */ + if (rc == CL_BREAK) /* skip */ { + bc->state = bc_skip; + free(buffer); return CL_SUCCESS; + } if (rc != CL_SUCCESS) { cli_errmsg("Error at bytecode line %u\n", row); + free(buffer); return rc; } - state = PARSE_FUNC_HEADER; + state = PARSE_BC_GLOBALS; break; + case PARSE_BC_GLOBALS: + rc = parseGlobals(bc, (unsigned char*)buffer); + if (rc == CL_BREAK) /* skip */ { + bc->state = bc_skip; + free(buffer); + return CL_SUCCESS; + } + if (rc != CL_SUCCESS) { + cli_errmsg("Error at bytecode line %u\n", row); + free(buffer); + return rc; + } + state = PARSE_MD_OPT_HEADER; + break; + case PARSE_MD_OPT_HEADER: + if (buffer[0] == 'D') { + rc = parseMD(bc, (unsigned char*)buffer); + if (rc != CL_SUCCESS) { + cli_errmsg("Error at bytecode line %u\n", row); + free(buffer); + return rc; + } + break; + } + // fall-through case PARSE_FUNC_HEADER: rc = parseFunctionHeader(bc, current_func, (unsigned char*)buffer); if (rc != CL_SUCCESS) { cli_errmsg("Error at bytecode line %u\n", row); + free(buffer); return rc; } bb = 0; @@ -962,12 +1296,14 @@ int cli_bytecode_load(struct cli_bc *bc, FILE *f, struct cli_dbio *dbio) rc = parseBB(bc, current_func, bb++, (unsigned char*)buffer); if (rc != CL_SUCCESS) { cli_errmsg("Error at bytecode line %u\n", row); + free(buffer); return rc; } if (bb >= bc->funcs[current_func].numBB) { if (bc->funcs[current_func].insn_idx != bc->funcs[current_func].numInsts) { cli_errmsg("Parsed different number of instructions than declared: %u != %u\n", bc->funcs[current_func].insn_idx, bc->funcs[current_func].numInsts); + free(buffer); return CL_EMALFDB; } cli_dbgmsg("Parsed %u BBs, %u instructions\n", @@ -978,6 +1314,7 @@ int cli_bytecode_load(struct cli_bc *bc, FILE *f, struct cli_dbio *dbio) break; } } + free(buffer); cli_dbgmsg("Parsed %d functions\n", current_func); if (current_func != bc->num_func) { cli_errmsg("Loaded less functions than declared: %u vs. %u\n", @@ -987,7 +1324,7 @@ int cli_bytecode_load(struct cli_bc *bc, FILE *f, struct cli_dbio *dbio) return CL_SUCCESS; } -int cli_bytecode_run(const struct cli_bc *bc, struct cli_bc_ctx *ctx) +int cli_bytecode_run(const struct cli_all_bc *bcs, const struct cli_bc *bc, struct cli_bc_ctx *ctx) { struct cli_bc_inst inst; struct cli_bc_func func; @@ -999,21 +1336,24 @@ int cli_bytecode_run(const struct cli_bc *bc, struct cli_bc_ctx *ctx) cli_errmsg("bytecode has to be prepared either for interpreter or JIT!\n"); return CL_EARG; } - memset(&func, 0, sizeof(func)); - func.numInsts = 1; - func.numValues = 1; - func.numBytes = ctx->bytes; - memset(ctx->values+ctx->bytes-8, 0, 8); + if (bc->state == bc_interp) { + memset(&func, 0, sizeof(func)); + func.numInsts = 1; + func.numValues = 1; + func.numBytes = ctx->bytes; + memset(ctx->values+ctx->bytes-8, 0, 8); - inst.opcode = OP_CALL_DIRECT; - inst.interp_op = OP_CALL_DIRECT*5; - inst.dest = func.numArgs; - inst.type = 0; - inst.u.ops.numOps = ctx->numParams; - inst.u.ops.funcid = ctx->funcid; - inst.u.ops.ops = ctx->operands; - inst.u.ops.opsizes = ctx->opsizes; - return cli_vm_execute(ctx->bc, ctx, &func, &inst); + inst.opcode = OP_BC_CALL_DIRECT; + inst.interp_op = OP_BC_CALL_DIRECT*5; + inst.dest = func.numArgs; + inst.type = 0; + inst.u.ops.numOps = ctx->numParams; + inst.u.ops.funcid = ctx->funcid; + inst.u.ops.ops = ctx->operands; + inst.u.ops.opsizes = ctx->opsizes; + return cli_vm_execute(ctx->bc, ctx, &func, &inst); + } + return cli_vm_execute_jit(bcs, ctx, &bc->funcs[ctx->funcid]); } uint64_t cli_bytecode_context_getresult_int(struct cli_bc_ctx *ctx) @@ -1037,7 +1377,7 @@ void cli_bytecode_destroy(struct cli_bc *bc) for(k=0;knumInsts;k++) { struct cli_bc_inst *ii = &BB->insts[k]; if (operand_counts[ii->opcode] > 3 || - ii->opcode == OP_CALL_DIRECT || ii->opcode == OP_CALL_API) { + ii->opcode == OP_BC_CALL_DIRECT || ii->opcode == OP_BC_CALL_API) { free(ii->u.ops.ops); free(ii->u.ops.opsizes); } @@ -1053,8 +1393,22 @@ void cli_bytecode_destroy(struct cli_bc *bc) free(bc->types[i].containedTypes); } free(bc->types); + for (i=0;inum_globals;i++) { + free(bc->globals[i]); + } + for (i=0;idbgnode_cnt;i++) { + for (j=0;jdbgnodes[i].numelements;j++) { + struct cli_bc_dbgnode_element *el = &bc->dbgnodes[i].elements[j]; + if (el && el->string) + free(el->string); + } + } + free(bc->dbgnodes); + free(bc->globals); + free(bc->globaltys); if (bc->uses_apis) cli_bitset_free(bc->uses_apis); + free(bc->lsig); } #define MAP(val) do { operand_t o = val; \ @@ -1074,10 +1428,6 @@ static int cli_bytecode_prepare_interpreter(struct cli_bc *bc) for (j=0;jnumValues;j++) { uint16_t ty = bcfunc->types[j]; unsigned align; - if (ty > 64) { - cli_errmsg("Bytecode: non-integer types not yet implemented\n"); - return CL_EMALFDB; - } align = typealign(bc, ty); bcfunc->numBytes = (bcfunc->numBytes + align-1)&(~(align-1)); map[j] = bcfunc->numBytes; @@ -1092,56 +1442,57 @@ static int cli_bytecode_prepare_interpreter(struct cli_bc *bc) struct cli_bc_inst *inst = &bcfunc->allinsts[j]; inst->dest = map[inst->dest]; switch (inst->opcode) { - case OP_ADD: - case OP_SUB: - case OP_MUL: - case OP_UDIV: - case OP_SDIV: - case OP_UREM: - case OP_SREM: - case OP_SHL: - case OP_LSHR: - case OP_ASHR: - case OP_AND: - case OP_OR: - case OP_XOR: - case OP_ICMP_EQ: - case OP_ICMP_NE: - case OP_ICMP_UGT: - case OP_ICMP_UGE: - case OP_ICMP_ULT: - case OP_ICMP_ULE: - case OP_ICMP_SGT: - case OP_ICMP_SGE: - case OP_ICMP_SLT: - case OP_ICMP_SLE: - case OP_COPY: + case OP_BC_ADD: + case OP_BC_SUB: + case OP_BC_MUL: + case OP_BC_UDIV: + case OP_BC_SDIV: + case OP_BC_UREM: + case OP_BC_SREM: + case OP_BC_SHL: + case OP_BC_LSHR: + case OP_BC_ASHR: + case OP_BC_AND: + case OP_BC_OR: + case OP_BC_XOR: + case OP_BC_ICMP_EQ: + case OP_BC_ICMP_NE: + case OP_BC_ICMP_UGT: + case OP_BC_ICMP_UGE: + case OP_BC_ICMP_ULT: + case OP_BC_ICMP_ULE: + case OP_BC_ICMP_SGT: + case OP_BC_ICMP_SGE: + case OP_BC_ICMP_SLT: + case OP_BC_ICMP_SLE: + case OP_BC_COPY: + case OP_BC_STORE: MAP(inst->u.binop[0]); MAP(inst->u.binop[1]); break; - case OP_SEXT: - case OP_ZEXT: - case OP_TRUNC: + case OP_BC_SEXT: + case OP_BC_ZEXT: + case OP_BC_TRUNC: MAP(inst->u.cast.source); break; - case OP_BRANCH: + case OP_BC_BRANCH: MAP(inst->u.branch.condition); break; - case OP_JMP: + case OP_BC_JMP: break; - case OP_RET: + case OP_BC_RET: MAP(inst->u.unaryop); break; - case OP_SELECT: + case OP_BC_SELECT: MAP(inst->u.three[0]); MAP(inst->u.three[1]); MAP(inst->u.three[2]); break; - case OP_CALL_API:/* fall-through */ - case OP_CALL_DIRECT: + case OP_BC_CALL_API:/* fall-through */ + case OP_BC_CALL_DIRECT: { struct cli_bc_func *target = NULL; - if (inst->opcode == OP_CALL_DIRECT) { + if (inst->opcode == OP_BC_CALL_DIRECT) { target = &bc->funcs[inst->u.ops.funcid]; if (inst->u.ops.funcid > bc->num_func) { cli_errmsg("bytecode: called function out of range: %u > %u\n", inst->u.ops.funcid, bc->num_func); @@ -1168,13 +1519,25 @@ static int cli_bytecode_prepare_interpreter(struct cli_bc *bc) inst->u.ops.opsizes = NULL; for (k=0;ku.ops.numOps;k++) { MAP(inst->u.ops.ops[k]); - if (inst->opcode == OP_CALL_DIRECT) + if (inst->opcode == OP_BC_CALL_DIRECT) inst->u.ops.opsizes[k] = typesize(bc, target->types[k]); else inst->u.ops.opsizes[k] = 32; /*XXX*/ } break; } + case OP_BC_LOAD: + MAP(inst->u.unaryop); + break; + case OP_BC_GEP1: + MAP(inst->u.binop[0]); + MAP(inst->u.binop[1]); + break; + case OP_BC_GEP2: + MAP(inst->u.three[0]); + MAP(inst->u.three[1]); + MAP(inst->u.three[2]); + break; default: cli_dbgmsg("Unhandled opcode: %d\n", inst->opcode); return CL_EBYTECODE; @@ -1186,21 +1549,141 @@ static int cli_bytecode_prepare_interpreter(struct cli_bc *bc) return CL_SUCCESS; } -static int cli_bytecode_prepare_jit(struct cli_bc *bc) +int cli_bytecode_prepare(struct cli_all_bc *bcs) { - if (bc->state != bc_loaded) { - cli_warnmsg("Cannot prepare for JIT, because it has already been converted to interpreter"); - return CL_EBYTECODE; + unsigned i; + int rc; + if (cli_bytecode_prepare_jit(bcs) == CL_SUCCESS) + return CL_SUCCESS; + for (i=0;icount;i++) { + struct cli_bc *bc = &bcs->all_bcs[i]; + if (bc->state == bc_interp || bc->state == bc_jit) + continue; + rc = cli_bytecode_prepare_interpreter(bc); + if (rc != CL_SUCCESS) + return rc; } - cli_warnmsg("JIT not yet implemented\n"); - return CL_EBYTECODE; + return CL_SUCCESS; } -int cli_bytecode_prepare(struct cli_bc *bc) +int cli_bytecode_init(struct cli_all_bc *allbc) { - if (bc->state == bc_interp || bc->state == bc_jit) - return CL_SUCCESS; - if (cli_bytecode_prepare_jit(bc) == CL_SUCCESS) - return CL_SUCCESS; - return cli_bytecode_prepare_interpreter(bc); + memset(allbc, 0, sizeof(*allbc)); + return cli_bytecode_init_jit(allbc); +} + +int cli_bytecode_done(struct cli_all_bc *allbc) +{ + return cli_bytecode_done_jit(allbc); +} + +int cli_bytecode_context_setfile(struct cli_bc_ctx *ctx, fmap_t *map) +{ + struct stat buf; + ctx->fmap = map; + ctx->file_size = map->len + map->offset; + return 0; +} + +int cli_bytecode_runlsig(const struct cli_all_bc *bcs, const struct cli_bc *bc, const char **virname, const uint32_t* lsigcnt, fmap_t *map) +{ + int ret; + struct cli_bc_ctx ctx; + memset(&ctx, 0, sizeof(ctx)); + cli_bytecode_context_setfuncid(&ctx, bc, 0); + ctx.hooks.match_counts = lsigcnt; + cli_bytecode_context_setfile(&ctx, map); + + cli_dbgmsg("Running bytecode for logical signature match\n"); + ret = cli_bytecode_run(bcs, bc, &ctx); + if (ret != CL_SUCCESS) { + cli_warnmsg("Bytcode failed to run: %s\n", cl_strerror(ret)); + return CL_SUCCESS; + } + if (ctx.virname) { + cli_dbgmsg("Bytecode found virus: %s\n", ctx.virname); + if (virname) + *virname = ctx.virname; + cli_bytecode_context_clear(&ctx); + return CL_VIRUS; + } + ret = cli_bytecode_context_getresult_int(&ctx); + cli_dbgmsg("Bytecode %u returned code: %u\n", bc->id, ret); + cli_bytecode_context_clear(&ctx); + return CL_SUCCESS; +} + +int cli_bytecode_runhook(const struct cl_engine *engine, struct cli_bc_ctx *ctx, + unsigned id, fmap_t *map, const char **virname) +{ + const unsigned *hooks = engine->hooks[id - _BC_START_HOOKS]; + unsigned i, hooks_cnt = engine->hooks_cnt[id - _BC_START_HOOKS]; + int ret; + + cli_bytecode_context_setfile(ctx, map); + cli_dbgmsg("Bytecode executing hook id %u (%u hooks)\n", id, hooks_cnt); + for (i=0;i < hooks_cnt;i++) { + const struct cli_bc *bc = &engine->bcs.all_bcs[hooks[i]]; + cli_bytecode_context_setfuncid(ctx, bc, 0); + ret = cli_bytecode_run(&engine->bcs, bc, ctx); + if (ret != CL_SUCCESS) { + cli_warnmsg("Bytecode failed to run: %s\n", cl_strerror(ret)); + return CL_SUCCESS; + } + if (ctx->virname) { + cli_dbgmsg("Bytecode found virus: %s\n", ctx->virname); + if (virname) + *virname = ctx->virname; + cli_bytecode_context_clear(ctx); + return CL_VIRUS; + } + ret = cli_bytecode_context_getresult_int(ctx); + /* TODO: use prefix here */ + cli_dbgmsg("Bytecode %u returned %u\n", bc->id, ret); + if (!ret) { + char *tempfile; + cli_ctx *cctx = ctx->ctx; + int fd = cli_bytecode_context_getresult_file(ctx, &tempfile); + if (fd != -1) { + if (cctx && cctx->engine->keeptmp) + cli_dbgmsg("Bytecode %u unpacked file saved in %s\n", + bc->id, tempfile); + else + cli_dbgmsg("Bytecode %u unpacked file\n", bc->id); + lseek(fd, 0, SEEK_SET); + cli_dbgmsg("***** Scanning unpacked file ******\n"); + ret = cli_magic_scandesc(fd, cctx); + if (!cctx || !cctx->engine->keeptmp) + ftruncate(fd, 0); + close(fd); + if (!cctx || !cctx->engine->keeptmp) { + if (cli_unlink(tempfile)) + ret = CL_EUNLINK; + } + free(tempfile); + if (ret != CL_CLEAN) { + if (ret == CL_VIRUS) + cli_dbgmsg("Scanning unpacked file by bytecode %u found a virus\n", bc->id); + cli_bytecode_context_clear(ctx); + return ret; + } + cli_bytecode_context_reset(ctx); + continue; + } + } + cli_bytecode_context_reset(ctx); + } + return CL_CLEAN; +} + +int cli_bytecode_context_setpe(struct cli_bc_ctx *ctx, const struct cli_pe_hook_data *data) +{ + ctx->hooks.exeinfo = &data->exe_info; + ctx->hooks.pedata = data; + return 0; +} + +void cli_bytecode_context_setctx(struct cli_bc_ctx *ctx, void *cctx) +{ + ctx->ctx = cctx; } diff --git a/libclamav/bytecode.h b/libclamav/bytecode.h index 1721f98f1..1f566514d 100644 --- a/libclamav/bytecode.h +++ b/libclamav/bytecode.h @@ -21,10 +21,10 @@ */ #ifndef BYTECODE_H #define BYTECODE_H -#include +#include #include "clambc.h" -#include "cltypes.h" -#include "others.h" +#include +#include "fmap.h" struct cli_dbio; struct cli_bc_ctx; @@ -32,8 +32,13 @@ struct cli_bc_func; struct cli_bc_value; struct cli_bc_inst; struct cli_bc_type; +struct cli_bc_engine; +struct cli_bc_dbgnode; +struct bitset_tag; +struct cl_engine; enum bc_state { + bc_skip, bc_loaded, bc_jit, bc_interp @@ -43,27 +48,80 @@ struct cli_bc { unsigned verifier; char *sigmaker; unsigned id; + unsigned kind; struct bytecode_metadata metadata; unsigned num_types; unsigned num_func; struct cli_bc_func *funcs; struct cli_bc_type *types; + uint64_t **globals; + uint16_t *globaltys; + size_t num_globals; enum bc_state state; uint16_t start_tid; - bitset_t *uses_apis; + struct bitset_tag *uses_apis; + char *lsig; + char *vnameprefix; + char **vnames; + unsigned vnames_cnt; + struct cli_bc_dbgnode *dbgnodes; + unsigned dbgnode_cnt; }; +struct cli_all_bc { + struct cli_bc *all_bcs; + unsigned count; + struct cli_bcengine *engine; +}; + +struct cli_pe_hook_data; struct cli_bc_ctx *cli_bytecode_context_alloc(void); +/* FIXME: we can't include others.h because others.h includes us...*/ +void cli_bytecode_context_setctx(struct cli_bc_ctx *ctx, void *cctx); int cli_bytecode_context_setfuncid(struct cli_bc_ctx *ctx, const struct cli_bc *bc, unsigned funcid); int cli_bytecode_context_setparam_int(struct cli_bc_ctx *ctx, unsigned i, uint64_t c); int cli_bytecode_context_setparam_ptr(struct cli_bc_ctx *ctx, unsigned i, void *data, unsigned datalen); +int cli_bytecode_context_setfile(struct cli_bc_ctx *ctx, fmap_t *map); +int cli_bytecode_context_setpe(struct cli_bc_ctx *ctx, const struct cli_pe_hook_data *data); int cli_bytecode_context_clear(struct cli_bc_ctx *ctx); +/* returns file descriptor, sets tempfile. Caller takes ownership, and is + * responsible for freeing/unlinking */ +int cli_bytecode_context_getresult_file(struct cli_bc_ctx *ctx, char **tempfilename); uint64_t cli_bytecode_context_getresult_int(struct cli_bc_ctx *ctx); void cli_bytecode_context_destroy(struct cli_bc_ctx *ctx); +extern int have_clamjit; +int cli_bytecode_init(struct cli_all_bc *allbc); int cli_bytecode_load(struct cli_bc *bc, FILE *f, struct cli_dbio *dbio); -int cli_bytecode_prepare(struct cli_bc *bc); -int cli_bytecode_run(const struct cli_bc *bc, struct cli_bc_ctx *ctx); +int cli_bytecode_prepare(struct cli_all_bc *allbc); +int cli_bytecode_run(const struct cli_all_bc *bcs, const struct cli_bc *bc, struct cli_bc_ctx *ctx); void cli_bytecode_destroy(struct cli_bc *bc); +int cli_bytecode_done(struct cli_all_bc *allbc); + +/* Hooks */ +struct cli_exe_info; +int cli_bytecode_runlsig(const struct cli_all_bc *bcs, const struct cli_bc* bc, const char **virname, const uint32_t* lsigcnt, fmap_t *fmap); +int cli_bytecode_runhook(const struct cl_engine *engine, struct cli_bc_ctx *ctx, unsigned id, fmap_t *map, const char **virname); + +#ifdef __cplusplus +extern "C" { +#endif + +int bytecode_init(void); +/* Bytecode internal debug API */ +void cli_bytecode_debug(int argc, char **argv); +void cli_bytecode_debug_printsrc(const struct cli_bc_ctx *ctx); + +typedef void (*bc_dbg_callback_trace)(struct cli_bc_ctx*, unsigned event); +typedef void (*bc_dbg_callback_trace_op)(struct cli_bc_ctx*, const char *op); +typedef void (*bc_dbg_callback_trace_val)(struct cli_bc_ctx*, const char *name, uint32_t value); +void cli_bytecode_context_set_trace(struct cli_bc_ctx*, unsigned mask, + bc_dbg_callback_trace, + bc_dbg_callback_trace_op, + bc_dbg_callback_trace_val); + +#ifdef __cplusplus +} +#endif #endif diff --git a/libclamav/bytecode_api.c b/libclamav/bytecode_api.c index df752954e..3c4cd624b 100644 --- a/libclamav/bytecode_api.c +++ b/libclamav/bytecode_api.c @@ -3,6 +3,8 @@ * * Copyright (C) 2009 Sourcefire, Inc. * + * Authors: Török Edvin + * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. @@ -18,16 +20,200 @@ * MA 02110-1301, USA. */ +#define _XOPEN_SOURCE 600 +#include +#include +#include +#include #include "cltypes.h" +#include "clambc.h" +#include "bytecode.h" +#include "bytecode_priv.h" #include "type_desc.h" #include "bytecode_api.h" +#include "bytecode_api_impl.h" +#include "others.h" -int32_t cli_bcapi_test0(struct foo* s, uint32_t u) +uint32_t cli_bcapi_test0(struct cli_bc_ctx *ctx, struct foo* s, uint32_t u) { return (s && s->nxt == s && u == 0xdeadbeef) ? 0x12345678 : 0x55; } -int32_t cli_bcapi_test1(int32_t a, int32_t b) +uint32_t cli_bcapi_test1(struct cli_bc_ctx *ctx, uint32_t a, uint32_t b) { return (a==0xf00dbeef && b==0xbeeff00d) ? 0x12345678 : 0x55; } + +int32_t cli_bcapi_read(struct cli_bc_ctx* ctx, uint8_t *data, int32_t size) +{ + if (!ctx->fmap) + return -1; + return fmap_readn(ctx->fmap, data, ctx->off, size); +} + +int32_t cli_bcapi_seek(struct cli_bc_ctx* ctx, int32_t pos, uint32_t whence) +{ + off_t off; + if (!ctx->fmap) + return -1; + switch (whence) { + case 0: + off = pos; + break; + case 1: + off = ctx->off + pos; + break; + case 2: + off = ctx->file_size + pos; + break; + } + if (off < 0 || off > ctx->file_size) + return -1; + ctx->off = off; + return off; +} + +uint32_t cli_bcapi_debug_print_str(struct cli_bc_ctx *ctx, const uint8_t *str, uint32_t len) +{ + cli_dbgmsg("bytecode debug: %s\n", str); + return 0; +} + +uint32_t cli_bcapi_debug_print_uint(struct cli_bc_ctx *ctx, uint32_t a, uint32_t b) +{ + cli_dbgmsg("bytecode debug: %u\n", a); + return 0; +} + +/*TODO: compiler should make sure that only constants are passed here, and not + * pointers to arbitrary locations that may not be valid when bytecode finishes + * executing */ +uint32_t cli_bcapi_setvirusname(struct cli_bc_ctx* ctx, const uint8_t *name, uint32_t len) +{ + ctx->virname = name; + return 0; +} + +uint32_t cli_bcapi_disasm_x86(struct cli_bc_ctx *ctx, struct DISASM_RESULT *res, uint32_t len) +{ + //TODO: call disasm_x86_wrap, which outputs a MARIO struct +} + +/* TODO: field in ctx, id of last bytecode that called magicscandesc, reset + * after hooks/other bytecodes are run. TODO: need a more generic solution + * to avoid uselessly recursing on bytecode-unpacked files, but also a way to + * override the limit if we need it in a special situation */ +int32_t cli_bcapi_write(struct cli_bc_ctx *ctx, uint8_t*data, int32_t len) +{ + int32_t res; + cli_ctx *cctx = (cli_ctx*)ctx->ctx; + if (len < 0) { + cli_warnmsg("Bytecode API: called with negative length!\n"); + return -1; + } + if (ctx->outfd == -1) { + ctx->tempfile = cli_gentemp(cctx ? cctx->engine->tmpdir : NULL); + if (!ctx->tempfile) { + cli_dbgmsg("Bytecode API: Unable to allocate memory for tempfile\n"); + return -1; + } + ctx->outfd = open(ctx->tempfile, O_RDWR|O_CREAT|O_EXCL|O_TRUNC|O_BINARY, 0600); + if (ctx->outfd == -1) { + cli_warnmsg("Bytecode API: Can't create file %s\n", ctx->tempfile); + free(ctx->tempfile); + return -1; + } + } + if (cli_checklimits("bytecode api", cctx, ctx->written + len, 0, 0)) + return -1; + res = cli_writen(ctx->outfd, data, len); + if (res > 0) ctx->written += res; + if (res == -1) + cli_dbgmsg("Bytecode API: write failed: %s\n", errno); + return res; +} + +void cli_bytecode_context_set_trace(struct cli_bc_ctx* ctx, enum trace_level level, + bc_dbg_callback_trace trace, + bc_dbg_callback_trace_op trace_op, + bc_dbg_callback_trace_val trace_val) +{ + ctx->trace = trace; + ctx->trace_op = trace_op; + ctx->trace_val = trace_val; + ctx->trace_level = level; +} + +uint32_t cli_bcapi_trace_scope(struct cli_bc_ctx *ctx, const const uint8_t *scope, uint32_t scopeid) +{ + if (LIKELY(!ctx->trace_level)) + return 0; + if (ctx->scope != (const char*)scope) { + ctx->scope = (const char*)scope ? (const char*)scope : "?"; + ctx->scopeid = scopeid; + ctx->trace_level |= 0x80;/* temporarely increase level to print params */ + } else if ((ctx->trace_level >= trace_scope) && ctx->scopeid != scopeid) { + ctx->scopeid = scopeid; + ctx->trace_level |= 0x40;/* temporarely increase level to print location */ + } + return 0; +} + +uint32_t cli_bcapi_trace_directory(struct cli_bc_ctx *ctx, const const uint8_t* dir, uint32_t dummy) +{ + if (LIKELY(!ctx->trace_level)) + return 0; + ctx->directory = (const char*)dir ? (const char*)dir : ""; + return 0; +} + +uint32_t cli_bcapi_trace_source(struct cli_bc_ctx *ctx, const const uint8_t *file, uint32_t line) +{ + if (LIKELY(ctx->trace_level < trace_line)) + return 0; + if (ctx->file != (const char*)file || ctx->line != line) { + ctx->col = 0; + ctx->file =(const char*)file ? (const char*)file : "??"; + ctx->line = line; + } + return 0; +} + +uint32_t cli_bcapi_trace_op(struct cli_bc_ctx *ctx, const const uint8_t *op, uint32_t col) +{ + if (LIKELY(ctx->trace_level < trace_col)) + return 0; + if (ctx->trace_level&0xc0) { + ctx->col = col; + /* func/scope changed and they needed param/location event */ + ctx->trace(ctx, (ctx->trace_level&0x80) ? trace_func : trace_scope); + ctx->trace_level &= ~0xc0; + } + if (LIKELY(ctx->trace_level < trace_col)) + return 0; + if (ctx->col != col) { + ctx->col = col; + ctx->trace(ctx, trace_col); + } else { + ctx->trace(ctx, trace_line); + } + if (LIKELY(ctx->trace_level < trace_op)) + return 0; + if (ctx->trace_op && op) + ctx->trace_op(ctx, (const char*)op); + return 0; +} + +uint32_t cli_bcapi_trace_value(struct cli_bc_ctx *ctx, const const uint8_t* name, uint32_t value) +{ + if (LIKELY(ctx->trace_level < trace_val)) + return 0; + if (ctx->trace_level&0x80) { + if ((ctx->trace_level&0x7f) < trace_param) + return 0; + ctx->trace(ctx, trace_param); + } + if (ctx->trace_val && name) + ctx->trace_val(ctx, name, value); + return 0; +} diff --git a/libclamav/bytecode_api.h b/libclamav/bytecode_api.h index ed7338f4e..ba1b8afa0 100644 --- a/libclamav/bytecode_api.h +++ b/libclamav/bytecode_api.h @@ -1,6 +1,169 @@ +/* + * Copyright (C) 2009 Sourcefire, Inc. + * All rights reserved. + * Authors: Török Edvin + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/** @file */ +#ifndef BYTECODE_API_H +#define BYTECODE_API_H + +#ifdef __CLAMBC__ +#include "bytecode_execs.h" +#include "bytecode_pe.h" +#include "bytecode_disasm.h" +#endif + +#ifndef __CLAMBC__ +#include "execs.h" +struct DISASM_RESULT; +#endif + struct foo { struct foo *nxt; }; -int32_t cli_bcapi_test0(struct foo*, uint32_t); -int32_t cli_bcapi_test1(int32_t, int32_t); +/** Bytecode trigger kind */ +enum BytecodeKind { + /** generic bytecode, not tied a specific hook */ + BC_GENERIC=0, + _BC_START_HOOKS=256, + /** triggered by a logical signature */ + BC_LOGICAL=256, + /** a PE unpacker */ + BC_PE_UNPACKER, + _BC_LAST_HOOK +}; + +#ifdef __CLAMBC__ + +/** @brief Logical signature match counts + * + * This is a low-level variable, use the Macros in bytecode_local.h instead to + * access it. + * */ +extern const uint32_t __clambc_match_counts[64]; +/** Executable info, if this is a PE hook */ +extern const struct cli_exe_info __clambc_exeinfo; +/** PE data, if this is a PE hook */ +extern const struct cli_pe_hook_data __clambc_pedata; + +/** Kind of the bytecode */ +const uint16_t __clambc_kind; + +uint32_t test0(struct foo*, uint32_t); +uint32_t test1(uint32_t, uint32_t); + +/** + * @brief Reads specified amount of bytes from the current file + * into a buffer. + * + * @param[in] size amount of bytes to read + * @param[out] data pointer to buffer where data is read into + * @return amount read. + */ +int32_t read(uint8_t *data, int32_t size); + + +enum { + /**set file position to specified absolute position */ + SEEK_SET=0, + /**set file position relative to current position */ + SEEK_CUR, + /**set file position relative to file end*/ + SEEK_END +}; + +/** + * @brief Writes the specified amount of bytes from a buffer to the + * current temporary file. + * @param[in] data pointer to buffer of data to write + * @param[in] size amount of bytes to write + * \p size bytes to temporary file, from the buffer pointed to + * byte + * @return amount of bytes successfully written + */ +int32_t write(uint8_t *data, int32_t size); + +/** + * @brief Changes the current file position to the specified one. + * @sa SEEK_SET, SEEK_CUR, SEEK_END + * @param[in] pos offset (absolute or relative depending on \p whence param) + * @param[in] whence one of \p SEEK_SET, \p SEEK_CUR, \p SEEK_END + * @return absolute position in file + */ +int32_t seek(int32_t pos, uint32_t whence); + +/** + * Sets the name of the virus found. + * + * @param[in] name the name of the virus + * @param[in] len length of the virusname + * @return 0 + */ +uint32_t setvirusname(const uint8_t *name, uint32_t len); + +/** + * Prints a debug message. + * + * @param[in] str Message to print + * @param[in] len length of message to print + * @return 0 + */ +uint32_t debug_print_str(const uint8_t *str, uint32_t len); + +/** + * Prints a number as a debug message. + * + * @param[in] a number to print + * @param b unused + * @return 0 + */ +uint32_t debug_print_uint(uint32_t a, uint32_t b); + +/** + * Disassembles starting from current file position, the specified amount of + * bytes. + * @param[out] result pointer to struct holding result + * @param[in] len how many bytes to disassemble + * @return 0 for success + * + * You can use lseek to disassemble starting from a different location. + * This is a low-level API, the result is in ClamAV type-8 signature format + * (64 bytes/instruction). + * \sa DisassembleAt + * */ +uint32_t disasm_x86(struct DISASM_RESULT* result, uint32_t len); + +/* tracing API */ + +/* a scope: lexical block, function, or compile unit */ +uint32_t trace_directory(const uint8_t* directory, uint32_t dummy); +uint32_t trace_scope(const uint8_t* newscope, uint32_t scopeid); +uint32_t trace_source(const uint8_t* srcfile, uint32_t line); +uint32_t trace_op(const uint8_t* opname, uint32_t column); +uint32_t trace_value(const uint8_t* name, uint32_t v); + +#endif +#endif diff --git a/libclamav/bytecode_api_decl.c b/libclamav/bytecode_api_decl.c index fe23bbeda..34cf72aa3 100644 --- a/libclamav/bytecode_api_decl.c +++ b/libclamav/bytecode_api_decl.c @@ -3,49 +3,153 @@ * This is an automatically generated file! * * Copyright (C) 2009 Sourcefire, Inc. + * All rights reserved. * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, - * MA 02110-1301, USA. + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE */ - #include "cltypes.h" #include "type_desc.h" #include "bytecode_api.h" +#include "bytecode_api_impl.h" +#include "bytecode_priv.h" +#include -static uint16_t cli_tmp0[]={32, 70, 32}; +uint32_t cli_bcapi_test0(struct cli_bc_ctx *ctx, struct foo*, uint32_t); +uint32_t cli_bcapi_test1(struct cli_bc_ctx *ctx, uint32_t, uint32_t); +int32_t cli_bcapi_read(struct cli_bc_ctx *ctx, uint8_t*, int32_t); +int32_t cli_bcapi_write(struct cli_bc_ctx *ctx, uint8_t*, int32_t); +int32_t cli_bcapi_seek(struct cli_bc_ctx *ctx, int32_t, uint32_t); +uint32_t cli_bcapi_setvirusname(struct cli_bc_ctx *ctx, const const uint8_t*, uint32_t); +uint32_t cli_bcapi_debug_print_str(struct cli_bc_ctx *ctx, const const uint8_t*, uint32_t); +uint32_t cli_bcapi_debug_print_uint(struct cli_bc_ctx *ctx, uint32_t, uint32_t); +uint32_t cli_bcapi_disasm_x86(struct cli_bc_ctx *ctx, struct DISASM_RESULT*, uint32_t); +uint32_t cli_bcapi_trace_directory(struct cli_bc_ctx *ctx, const const uint8_t*, uint32_t); +uint32_t cli_bcapi_trace_scope(struct cli_bc_ctx *ctx, const const uint8_t*, uint32_t); +uint32_t cli_bcapi_trace_source(struct cli_bc_ctx *ctx, const const uint8_t*, uint32_t); +uint32_t cli_bcapi_trace_op(struct cli_bc_ctx *ctx, const const uint8_t*, uint32_t); +uint32_t cli_bcapi_trace_value(struct cli_bc_ctx *ctx, const const uint8_t*, uint32_t); + +const struct cli_apiglobal cli_globals[] = { +/* Bytecode globals BEGIN */ + {"__clambc_kind", GLOBAL_KIND, 16, + ((char*)&((struct cli_bc_ctx*)0)->hooks.kind - (char*)NULL)}, + {"__clambc_match_counts", GLOBAL_MATCH_COUNTS, 82, + ((char*)&((struct cli_bc_ctx*)0)->hooks.match_counts - (char*)NULL)}, + {"__clambc_exeinfo", GLOBAL_EXEINFO, 79, + ((char*)&((struct cli_bc_ctx*)0)->hooks.exeinfo - (char*)NULL)}, + {"__clambc_pedata", GLOBAL_PEDATA, 69, + ((char*)&((struct cli_bc_ctx*)0)->hooks.pedata - (char*)NULL)} +/* Bytecode globals END */ +}; +const unsigned cli_apicall_maxglobal = _LAST_GLOBAL-1; +static uint16_t cli_tmp0[]={79, 77, 75, 72, 70, 32, 32, 32, 8, 65}; static uint16_t cli_tmp1[]={71}; -static uint16_t cli_tmp2[]={70}; -static uint16_t cli_tmp3[]={32, 32, 32}; +static uint16_t cli_tmp2[]={32, 32}; +static uint16_t cli_tmp3[]={73}; +static uint16_t cli_tmp4[]={16, 8, 8, 32, 32, 32, 32, 32, 64, 32, 32, 16, 16, 16, 16, 16, 16, 32, 32, 32, 32, 16, 16, 64, 64, 64, 64, 32, 32, 74}; +static uint16_t cli_tmp5[]={71}; +static uint16_t cli_tmp6[]={76}; +static uint16_t cli_tmp7[]={16, 8, 8, 32, 32, 32, 32, 32, 32, 32, 32, 32, 16, 16, 16, 16, 16, 16, 32, 32, 32, 32, 16, 16, 32, 32, 32, 32, 32, 32, 74}; +static uint16_t cli_tmp8[]={78}; +static uint16_t cli_tmp9[]={32, 16, 16, 32, 32, 32, 16, 16}; +static uint16_t cli_tmp10[]={80, 32, 32, 16}; +static uint16_t cli_tmp11[]={81}; +static uint16_t cli_tmp12[]={32, 32, 32, 32, 32, 32, 32, 32, 32}; +static uint16_t cli_tmp13[]={32}; +static uint16_t cli_tmp14[]={32, 65, 32}; +static uint16_t cli_tmp15[]={32, 85, 32}; +static uint16_t cli_tmp16[]={86}; +static uint16_t cli_tmp17[]={16, 8, 8, 8, 88, 87}; +static uint16_t cli_tmp18[]={8}; +static uint16_t cli_tmp19[]={89}; +static uint16_t cli_tmp20[]={8}; +static uint16_t cli_tmp21[]={32, 32, 32}; +static uint16_t cli_tmp22[]={32, 92, 32}; +static uint16_t cli_tmp23[]={93}; +static uint16_t cli_tmp24[]={92}; const struct cli_bc_type cli_apicall_types[]={ - {FunctionType, cli_tmp0, 3}, - {PointerType, cli_tmp1, 1}, - {StructType, cli_tmp2, 1}, - {FunctionType, cli_tmp3, 3} + {DStructType, cli_tmp0, 10, 0, 0}, + {DPointerType, cli_tmp1, 1, 0, 0}, + {DStructType, cli_tmp2, 2, 0, 0}, + {DPointerType, cli_tmp3, 1, 0, 0}, + {DStructType, cli_tmp4, 30, 0, 0}, + {DArrayType, cli_tmp5, 16, 0, 0}, + {DPointerType, cli_tmp6, 1, 0, 0}, + {DStructType, cli_tmp7, 31, 0, 0}, + {DPointerType, cli_tmp8, 1, 0, 0}, + {DStructType, cli_tmp9, 8, 0, 0}, + {DStructType, cli_tmp10, 4, 0, 0}, + {DPointerType, cli_tmp11, 1, 0, 0}, + {DStructType, cli_tmp12, 9, 0, 0}, + {DArrayType, cli_tmp13, 64, 0, 0}, + {DFunctionType, cli_tmp14, 3, 0, 0}, + {DFunctionType, cli_tmp15, 3, 0, 0}, + {DPointerType, cli_tmp16, 1, 0, 0}, + {DStructType, cli_tmp17, 6, 0, 0}, + {DArrayType, cli_tmp18, 29, 0, 0}, + {DArrayType, cli_tmp19, 10, 0, 0}, + {DArrayType, cli_tmp20, 3, 0, 0}, + {DFunctionType, cli_tmp21, 3, 0, 0}, + {DFunctionType, cli_tmp22, 3, 0, 0}, + {DPointerType, cli_tmp23, 1, 0, 0}, + {DStructType, cli_tmp24, 1, 0, 0} }; const unsigned cli_apicall_maxtypes=sizeof(cli_apicall_types)/sizeof(cli_apicall_types[0]); const struct cli_apicall cli_apicalls[]={ /* Bytecode APIcalls BEGIN */ - {"cli_bcapi_test0", 0, 0, 1}, - {"cli_bcapi_test1", 3, 0, 0} + {"test0", 22, 0, 1}, + {"test1", 21, 0, 0}, + {"read", 14, 1, 1}, + {"write", 14, 2, 1}, + {"seek", 21, 1, 0}, + {"setvirusname", 14, 3, 1}, + {"debug_print_str", 14, 4, 1}, + {"debug_print_uint", 21, 2, 0}, + {"disasm_x86", 15, 5, 1}, + {"trace_directory", 14, 6, 1}, + {"trace_scope", 14, 7, 1}, + {"trace_source", 14, 8, 1}, + {"trace_op", 14, 9, 1}, + {"trace_value", 14, 10, 1} /* Bytecode APIcalls END */ }; const cli_apicall_int2 cli_apicalls0[] = { - cli_bcapi_test1 + (cli_apicall_int2)cli_bcapi_test1, + (cli_apicall_int2)cli_bcapi_seek, + (cli_apicall_int2)cli_bcapi_debug_print_uint }; const cli_apicall_pointer cli_apicalls1[] = { - (cli_apicall_pointer)cli_bcapi_test0 + (cli_apicall_pointer)cli_bcapi_test0, + (cli_apicall_pointer)cli_bcapi_read, + (cli_apicall_pointer)cli_bcapi_write, + (cli_apicall_pointer)cli_bcapi_setvirusname, + (cli_apicall_pointer)cli_bcapi_debug_print_str, + (cli_apicall_pointer)cli_bcapi_disasm_x86, + (cli_apicall_pointer)cli_bcapi_trace_directory, + (cli_apicall_pointer)cli_bcapi_trace_scope, + (cli_apicall_pointer)cli_bcapi_trace_source, + (cli_apicall_pointer)cli_bcapi_trace_op, + (cli_apicall_pointer)cli_bcapi_trace_value }; const unsigned cli_apicall_maxapi = sizeof(cli_apicalls)/sizeof(cli_apicalls[0]); diff --git a/libclamav/bytecode_api_impl.h b/libclamav/bytecode_api_impl.h new file mode 100644 index 000000000..b24e8e60e --- /dev/null +++ b/libclamav/bytecode_api_impl.h @@ -0,0 +1,48 @@ +/* + * ClamAV bytecode internal API + * This is an automatically generated file! + * + * Copyright (C) 2009 Sourcefire, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE + */ +#ifndef BYTECODE_API_IMPL_H +#define BYTECODE_API_IMPL_H + +struct cli_bc_bctx; +uint32_t cli_bcapi_test0(struct cli_bc_ctx *ctx, struct foo*, uint32_t); +uint32_t cli_bcapi_test1(struct cli_bc_ctx *ctx, uint32_t, uint32_t); +int32_t cli_bcapi_read(struct cli_bc_ctx *ctx, uint8_t*, int32_t); +int32_t cli_bcapi_write(struct cli_bc_ctx *ctx, uint8_t*, int32_t); +int32_t cli_bcapi_seek(struct cli_bc_ctx *ctx, int32_t, uint32_t); +uint32_t cli_bcapi_setvirusname(struct cli_bc_ctx *ctx, const const uint8_t*, uint32_t); +uint32_t cli_bcapi_debug_print_str(struct cli_bc_ctx *ctx, const const uint8_t*, uint32_t); +uint32_t cli_bcapi_debug_print_uint(struct cli_bc_ctx *ctx, uint32_t, uint32_t); +uint32_t cli_bcapi_disasm_x86(struct cli_bc_ctx *ctx, struct DISASM_RESULT*, uint32_t); +uint32_t cli_bcapi_trace_directory(struct cli_bc_ctx *ctx, const const uint8_t*, uint32_t); +uint32_t cli_bcapi_trace_scope(struct cli_bc_ctx *ctx, const const uint8_t*, uint32_t); +uint32_t cli_bcapi_trace_source(struct cli_bc_ctx *ctx, const const uint8_t*, uint32_t); +uint32_t cli_bcapi_trace_op(struct cli_bc_ctx *ctx, const const uint8_t*, uint32_t); +uint32_t cli_bcapi_trace_value(struct cli_bc_ctx *ctx, const const uint8_t*, uint32_t); + +#endif diff --git a/libclamav/bytecode_hooks.h b/libclamav/bytecode_hooks.h new file mode 100644 index 000000000..16e1471bd --- /dev/null +++ b/libclamav/bytecode_hooks.h @@ -0,0 +1,38 @@ +/* + * ClamAV bytecode internal API + * This is an automatically generated file! + * + * Copyright (C) 2009 Sourcefire, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE + */ +#ifndef BYTECODE_HOOKS_H +#define BYTECODE_HOOKS_H + +struct cli_bc_hooks { + const uint16_t* kind; + const uint32_t* match_counts; + const struct cli_exe_info* exeinfo; + const struct cli_pe_hook_data* pedata; +}; +#endif diff --git a/libclamav/bytecode_nojit.c b/libclamav/bytecode_nojit.c new file mode 100644 index 000000000..1a944c5a6 --- /dev/null +++ b/libclamav/bytecode_nojit.c @@ -0,0 +1,72 @@ +/* + * Load, and verify ClamAV bytecode. + * + * Copyright (C) 2009 Sourcefire, Inc. + * + * Authors: Török Edvin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +#include +#include "cltypes.h" +#include "bytecode.h" +#include "bytecode_priv.h" +#include "clamav.h" +#include "others.h" + +int cli_bytecode_prepare_jit(struct cli_all_bc *bcs) +{ + unsigned i; + for (i=0;icount;i++) { + if (bcs->all_bcs[i].state == bc_skip) + continue; + if (bcs->all_bcs[i].state != bc_loaded) { + cli_warnmsg("Cannot prepare for JIT, because it has already been converted to interpreter"); + return CL_EBYTECODE; + } + } + cli_warnmsg("JIT not compiled in\n"); + return CL_EBYTECODE; +} + +int cli_vm_execute_jit(const struct cli_all_bc *bcs, struct cli_bc_ctx *ctx, const struct cli_bc_func *func) +{ + return CL_EBYTECODE; +} + +int cli_bytecode_init_jit(struct cli_all_bc *allbc) +{ + return CL_SUCCESS; +} + +int cli_bytecode_done_jit(struct cli_all_bc *allbc) +{ + return CL_SUCCESS; +} + +void cli_bytecode_debug(int argc, char **argv) { + // Empty +} + +int bytecode_init(void) +{ + return 0; +} + +void cli_bytecode_debug_printsrc(const struct cli_bc_ctx *ctx) { + // Empty +} +int have_clamjit=0; diff --git a/libclamav/bytecode_priv.h b/libclamav/bytecode_priv.h index 052f89cd4..9d5411e9b 100644 --- a/libclamav/bytecode_priv.h +++ b/libclamav/bytecode_priv.h @@ -23,7 +23,12 @@ #ifndef BYTECODE_PRIV_H #define BYTECODE_PRIV_H +#include "bytecode.h" #include "type_desc.h" +#include "execs.h" +#include "bytecode_hooks.h" +#include "fmap.h" + typedef uint32_t operand_t; typedef uint16_t bbid_t; typedef uint16_t funcid_t; @@ -77,13 +82,38 @@ struct cli_bc_func { uint32_t numConstants; uint32_t numBytes;/* stack size */ uint16_t numBB; + uint16_t returnType; uint16_t *types; uint32_t insn_idx; struct cli_bc_bb *BB; struct cli_bc_inst *allinsts; uint64_t *constants; + unsigned *dbgnodes; }; + +struct cli_bc_dbgnode_element { + unsigned nodeid; + char *string; + unsigned len; + uint64_t constant; +}; + +struct cli_bc_dbgnode { + unsigned numelements; + struct cli_bc_dbgnode_element* elements; +}; + #define MAX_OP ~0u +enum trace_level { + trace_none=0, + trace_func, + trace_param, + trace_scope, + trace_line, + trace_col, + trace_op, + trace_val +}; struct cli_bc_ctx { /* id and params of toplevel function called */ const struct cli_bc *bc; @@ -94,7 +124,39 @@ struct cli_bc_ctx { operand_t *operands; uint16_t funcid; unsigned numParams; + size_t file_size; + off_t off; + fmap_t *fmap; + const char *virname; + struct cli_bc_hooks hooks; + int outfd; + char *tempfile; + void *ctx; + unsigned written; + bc_dbg_callback_trace trace; + bc_dbg_callback_trace_op trace_op; + bc_dbg_callback_trace_val trace_val; + unsigned trace_level; + const char *directory; + const char *file; + const char *scope; + uint32_t scopeid; + unsigned line; + unsigned col; }; - +struct cli_all_bc; int cli_vm_execute(const struct cli_bc *bc, struct cli_bc_ctx *ctx, const struct cli_bc_func *func, const struct cli_bc_inst *inst); + +#ifdef __cplusplus +extern "C" { +#endif + +int cli_vm_execute_jit(const struct cli_all_bc *bcs, struct cli_bc_ctx *ctx, const struct cli_bc_func *func); +int cli_bytecode_prepare_jit(struct cli_all_bc *bc); +int cli_bytecode_init_jit(struct cli_all_bc *bc); +int cli_bytecode_done_jit(struct cli_all_bc *bc); + +#ifdef __cplusplus +} +#endif #endif diff --git a/libclamav/bytecode_vm.c b/libclamav/bytecode_vm.c index 672cec228..aeb26268c 100644 --- a/libclamav/bytecode_vm.c +++ b/libclamav/bytecode_vm.c @@ -251,6 +251,10 @@ static always_inline struct stack_entry *pop_stack(struct stack *stack, CHECK_EQ((p)&7, 0);\ TRACE_W(x, p, 64);\ *(uint64_t*)&values[p] = x +#define WRITEP(x, p) CHECK_GT(func->numBytes, p+PSIZE-1);\ + CHECK_EQ((p)&(PSIZE-1), 0);\ + TRACE_W(x, p, PSIZE*8);\ + *(void**)&values[p] = x #define READ1(x, p) CHECK_GT(func->numBytes, p);\ x = (*(uint8_t*)&values[p])&1;\ @@ -270,6 +274,11 @@ static always_inline struct stack_entry *pop_stack(struct stack *stack, CHECK_EQ((p)&7, 0);\ x = *(uint64_t*)&values[p];\ TRACE_R(x) +#define PSIZE sizeof(void*) +#define READP(x, p) CHECK_GT(func->numBytes, p+PSIZE-1);\ + CHECK_EQ((p)&(PSIZE-1), 0);\ + x = *(void**)&values[p];\ + TRACE_R(x) #define READOLD8(x, p) CHECK_GT(func->numBytes, p);\ x = *(uint8_t*)&old_values[p];\ @@ -289,7 +298,7 @@ static always_inline struct stack_entry *pop_stack(struct stack *stack, #define BINOP(i) inst->u.binop[i] -#define DEFINE_BINOP_HELPER(opc, OP, W0, W1, W2, W3, W4) \ +#define DEFINE_BINOP_BC_HELPER(opc, OP, W0, W1, W2, W3, W4) \ case opc*5: {\ uint8_t op0, op1, res;\ int8_t sop0, sop1;\ @@ -341,10 +350,10 @@ static always_inline struct stack_entry *pop_stack(struct stack *stack, break;\ } -#define DEFINE_BINOP(opc, OP) DEFINE_BINOP_HELPER(opc, OP, WRITE8, WRITE8, WRITE16, WRITE32, WRITE64) -#define DEFINE_ICMPOP(opc, OP) DEFINE_BINOP_HELPER(opc, OP, WRITE8, WRITE8, WRITE8, WRITE8, WRITE8) +#define DEFINE_BINOP(opc, OP) DEFINE_BINOP_BC_HELPER(opc, OP, WRITE8, WRITE8, WRITE16, WRITE32, WRITE64) +#define DEFINE_ICMPOP(opc, OP) DEFINE_BINOP_BC_HELPER(opc, OP, WRITE8, WRITE8, WRITE8, WRITE8, WRITE8) -#define CHECK_OP(cond, msg) if((cond)) { cli_dbgmsg(msg); return CL_EBYTECODE;} +#define CHECK_OP(cond, msg) if((cond)) { cli_dbgmsg(msg); stop = CL_EBYTECODE; break;} #define DEFINE_CASTOP(opc, OP) \ case opc*5: {\ @@ -400,7 +409,7 @@ static always_inline struct stack_entry *pop_stack(struct stack *stack, default: CHECK_UNREACHABLE;\ } -#define DEFINE_OP_RET_N(OP, T, R0, W0) \ +#define DEFINE_OP_BC_RET_N(OP, T, R0, W0) \ case OP: {\ T tmp;\ R0(tmp, inst->u.unaryop);\ @@ -438,77 +447,77 @@ int cli_vm_execute(const struct cli_bc *bc, struct cli_bc_ctx *ctx, const struct do { pc++; switch (inst->interp_op) { - DEFINE_BINOP(OP_ADD, res = op0 + op1); - DEFINE_BINOP(OP_SUB, res = op0 - op1); - DEFINE_BINOP(OP_MUL, res = op0 * op1); + DEFINE_BINOP(OP_BC_ADD, res = op0 + op1); + DEFINE_BINOP(OP_BC_SUB, res = op0 - op1); + DEFINE_BINOP(OP_BC_MUL, res = op0 * op1); - DEFINE_BINOP(OP_UDIV, CHECK_OP(op1 == 0, "bytecode attempted to execute udiv#0\n"); + DEFINE_BINOP(OP_BC_UDIV, CHECK_OP(op1 == 0, "bytecode attempted to execute udiv#0\n"); res=op0/op1); - DEFINE_BINOP(OP_SDIV, CHECK_OP(check_sdivops(sop0, sop1), "bytecode attempted to execute sdiv#0\n"); + DEFINE_BINOP(OP_BC_SDIV, CHECK_OP(check_sdivops(sop0, sop1), "bytecode attempted to execute sdiv#0\n"); res=sop0/sop1); - DEFINE_BINOP(OP_UREM, CHECK_OP(op1 == 0, "bytecode attempted to execute urem#0\n"); + DEFINE_BINOP(OP_BC_UREM, CHECK_OP(op1 == 0, "bytecode attempted to execute urem#0\n"); res=op0 % op1); - DEFINE_BINOP(OP_SREM, CHECK_OP(check_sdivops(sop0,sop1), "bytecode attempted to execute urem#0\n"); + DEFINE_BINOP(OP_BC_SREM, CHECK_OP(check_sdivops(sop0,sop1), "bytecode attempted to execute urem#0\n"); res=sop0 % sop1); - DEFINE_BINOP(OP_SHL, CHECK_OP(op1 > inst->type, "bytecode attempted to execute shl greater than bitwidth\n"); + DEFINE_BINOP(OP_BC_SHL, CHECK_OP(op1 > inst->type, "bytecode attempted to execute shl greater than bitwidth\n"); res = op0 << op1); - DEFINE_BINOP(OP_LSHR, CHECK_OP(op1 > inst->type, "bytecode attempted to execute lshr greater than bitwidth\n"); + DEFINE_BINOP(OP_BC_LSHR, CHECK_OP(op1 > inst->type, "bytecode attempted to execute lshr greater than bitwidth\n"); res = op0 >> op1); - DEFINE_BINOP(OP_ASHR, CHECK_OP(op1 > inst->type, "bytecode attempted to execute ashr greater than bitwidth\n"); + DEFINE_BINOP(OP_BC_ASHR, CHECK_OP(op1 > inst->type, "bytecode attempted to execute ashr greater than bitwidth\n"); res = CLI_SRS(sop0, op1)); - DEFINE_BINOP(OP_AND, res = op0 & op1); - DEFINE_BINOP(OP_OR, res = op0 | op1); - DEFINE_BINOP(OP_XOR, res = op0 ^ op1); + DEFINE_BINOP(OP_BC_AND, res = op0 & op1); + DEFINE_BINOP(OP_BC_OR, res = op0 | op1); + DEFINE_BINOP(OP_BC_XOR, res = op0 ^ op1); - DEFINE_CASTOP(OP_SEXT, + DEFINE_CASTOP(OP_BC_SEXT, CHOOSE(READ1(sres, inst->u.cast.source); res = sres ? ~0ull : 0, READ8(sres, inst->u.cast.source); res=sres=SIGNEXT(sres, inst->u.cast.mask), READ16(sres, inst->u.cast.source); res=sres=SIGNEXT(sres, inst->u.cast.mask), READ32(sres, inst->u.cast.source); res=sres=SIGNEXT(sres, inst->u.cast.mask), READ64(sres, inst->u.cast.source); res=sres=SIGNEXT(sres, inst->u.cast.mask))); - DEFINE_CASTOP(OP_ZEXT, + DEFINE_CASTOP(OP_BC_ZEXT, CHOOSE(READ1(res, inst->u.cast.source), READ8(res, inst->u.cast.source), READ16(res, inst->u.cast.source), READ32(res, inst->u.cast.source), READ64(res, inst->u.cast.source))); - DEFINE_CASTOP(OP_TRUNC, + DEFINE_CASTOP(OP_BC_TRUNC, CHOOSE(READ1(res, inst->u.cast.source), READ8(res, inst->u.cast.source), READ16(res, inst->u.cast.source), READ32(res, inst->u.cast.source), READ64(res, inst->u.cast.source))); - DEFINE_OP(OP_BRANCH) + DEFINE_OP(OP_BC_BRANCH) stop = jump(func, (values[inst->u.branch.condition]&1) ? inst->u.branch.br_true : inst->u.branch.br_false, &bb, &inst, &bb_inst); continue; - DEFINE_OP(OP_JMP) + DEFINE_OP(OP_BC_JMP) stop = jump(func, inst->u.jump, &bb, &inst, &bb_inst); continue; - DEFINE_OP_RET_N(OP_RET*5, uint8_t, READ1, WRITE8); - DEFINE_OP_RET_N(OP_RET*5+1, uint8_t, READ8, WRITE8); - DEFINE_OP_RET_N(OP_RET*5+2, uint16_t, READ16, WRITE16); - DEFINE_OP_RET_N(OP_RET*5+3, uint32_t, READ32, WRITE32); - DEFINE_OP_RET_N(OP_RET*5+4, uint64_t, READ64, WRITE64); + DEFINE_OP_BC_RET_N(OP_BC_RET*5, uint8_t, READ1, WRITE8); + DEFINE_OP_BC_RET_N(OP_BC_RET*5+1, uint8_t, READ8, WRITE8); + DEFINE_OP_BC_RET_N(OP_BC_RET*5+2, uint16_t, READ16, WRITE16); + DEFINE_OP_BC_RET_N(OP_BC_RET*5+3, uint32_t, READ32, WRITE32); + DEFINE_OP_BC_RET_N(OP_BC_RET*5+4, uint64_t, READ64, WRITE64); - DEFINE_ICMPOP(OP_ICMP_EQ, res = (op0 == op1)); - DEFINE_ICMPOP(OP_ICMP_NE, res = (op0 != op1)); - DEFINE_ICMPOP(OP_ICMP_UGT, res = (op0 > op1)); - DEFINE_ICMPOP(OP_ICMP_UGE, res = (op0 >= op1)); - DEFINE_ICMPOP(OP_ICMP_ULT, res = (op0 < op1)); - DEFINE_ICMPOP(OP_ICMP_ULE, res = (op0 <= op1)); - DEFINE_ICMPOP(OP_ICMP_SGT, res = (sop0 > sop1)); - DEFINE_ICMPOP(OP_ICMP_SGE, res = (sop0 >= sop1)); - DEFINE_ICMPOP(OP_ICMP_SLE, res = (sop0 <= sop1)); - DEFINE_ICMPOP(OP_ICMP_SLT, res = (sop0 < sop1)); + DEFINE_ICMPOP(OP_BC_ICMP_EQ, res = (op0 == op1)); + DEFINE_ICMPOP(OP_BC_ICMP_NE, res = (op0 != op1)); + DEFINE_ICMPOP(OP_BC_ICMP_UGT, res = (op0 > op1)); + DEFINE_ICMPOP(OP_BC_ICMP_UGE, res = (op0 >= op1)); + DEFINE_ICMPOP(OP_BC_ICMP_ULT, res = (op0 < op1)); + DEFINE_ICMPOP(OP_BC_ICMP_ULE, res = (op0 <= op1)); + DEFINE_ICMPOP(OP_BC_ICMP_SGT, res = (sop0 > sop1)); + DEFINE_ICMPOP(OP_BC_ICMP_SGE, res = (sop0 >= sop1)); + DEFINE_ICMPOP(OP_BC_ICMP_SLE, res = (sop0 <= sop1)); + DEFINE_ICMPOP(OP_BC_ICMP_SLT, res = (sop0 < sop1)); - case OP_SELECT*5: + case OP_BC_SELECT*5: { uint8_t t0, t1, t2; READ1(t0, inst->u.three[0]); @@ -517,7 +526,7 @@ int cli_vm_execute(const struct cli_bc *bc, struct cli_bc_ctx *ctx, const struct WRITE8(inst->dest, t0 ? t1 : t2); break; } - case OP_SELECT*5+1: + case OP_BC_SELECT*5+1: { uint8_t t0, t1, t2; READ1(t0, inst->u.three[0]); @@ -526,7 +535,7 @@ int cli_vm_execute(const struct cli_bc *bc, struct cli_bc_ctx *ctx, const struct WRITE8(inst->dest, t0 ? t1 : t2); break; } - case OP_SELECT*5+2: + case OP_BC_SELECT*5+2: { uint8_t t0; uint16_t t1, t2; @@ -536,7 +545,7 @@ int cli_vm_execute(const struct cli_bc *bc, struct cli_bc_ctx *ctx, const struct WRITE16(inst->dest, t0 ? t1 : t2); break; } - case OP_SELECT*5+3: + case OP_BC_SELECT*5+3: { uint8_t t0; uint32_t t1, t2; @@ -546,7 +555,7 @@ int cli_vm_execute(const struct cli_bc *bc, struct cli_bc_ctx *ctx, const struct WRITE32(inst->dest, t0 ? t1 : t2); break; } - case OP_SELECT*5+4: + case OP_BC_SELECT*5+4: { uint8_t t0; uint64_t t1, t2; @@ -557,7 +566,7 @@ int cli_vm_execute(const struct cli_bc *bc, struct cli_bc_ctx *ctx, const struct break; } - DEFINE_OP(OP_CALL_API) { + DEFINE_OP(OP_BC_CALL_API) { const struct cli_apicall *api = &cli_apicalls[inst->u.ops.funcid]; int32_t res; CHECK_APIID(inst->u.ops.funcid); @@ -567,7 +576,7 @@ int cli_vm_execute(const struct cli_bc *bc, struct cli_bc_ctx *ctx, const struct int32_t a, b, r; READ32(a, inst->u.ops.ops[0]); READ32(b, inst->u.ops.ops[1]); - res = cli_apicalls0[api->idx](a, b); + res = cli_apicalls0[api->idx](ctx, a, b); break; } case 1: { @@ -585,13 +594,17 @@ int cli_vm_execute(const struct cli_bc *bc, struct cli_bc_ctx *ctx, const struct break; } - DEFINE_OP(OP_CALL_DIRECT) + DEFINE_OP(OP_BC_CALL_DIRECT) CHECK_FUNCID(inst->u.ops.funcid); func2 = &bc->funcs[inst->u.ops.funcid]; CHECK_EQ(func2->numArgs, inst->u.ops.numOps); old_values = values; stack_entry = allocate_stack(&stack, stack_entry, func2, func, inst->dest, bb, bb_inst); + if (!stack_entry) { + stop = CL_EMEM; + break; + } values = stack_entry->values; TRACE_EXEC(inst->u.ops.funcid, inst->dest, inst->type, stack_depth); if (stack_depth > 10000) { @@ -644,35 +657,35 @@ int cli_vm_execute(const struct cli_bc *bc, struct cli_bc_ctx *ctx, const struct stack_depth++; continue; - case OP_COPY*5: + case OP_BC_COPY*5: { uint8_t op; READ1(op, BINOP(0)); WRITE8(BINOP(1), op); break; } - case OP_COPY*5+1: + case OP_BC_COPY*5+1: { uint8_t op; READ8(op, BINOP(0)); WRITE8(BINOP(1), op); break; } - case OP_COPY*5+2: + case OP_BC_COPY*5+2: { uint16_t op; READ16(op, BINOP(0)); WRITE16(BINOP(1), op); break; } - case OP_COPY*5+3: + case OP_BC_COPY*5+3: { uint32_t op; READ32(op, BINOP(0)); WRITE32(BINOP(1), op); break; } - case OP_COPY*5+4: + case OP_BC_COPY*5+4: { uint64_t op; READ32(op, BINOP(0)); @@ -680,6 +693,82 @@ int cli_vm_execute(const struct cli_bc *bc, struct cli_bc_ctx *ctx, const struct break; } + case OP_BC_LOAD*5: + case OP_BC_LOAD*5+1: + { + uint8_t *ptr; + READP(ptr, inst->u.unaryop); + WRITE8(inst->dest, (*ptr)); + break; + } + case OP_BC_LOAD*5+2: + { + const union unaligned_16 *ptr; + READP(ptr, inst->u.unaryop); + WRITE16(inst->dest, (ptr->una_u16)); + break; + } + case OP_BC_LOAD*5+3: + { + const union unaligned_32 *ptr; + READP(ptr, inst->u.unaryop); + WRITE32(inst->dest, (ptr->una_u32)); + break; + } + case OP_BC_LOAD*5+4: + { + const union unaligned_64 *ptr; + READP(ptr, inst->u.unaryop); + WRITE64(inst->dest, (ptr->una_u64)); + break; + } + + case OP_BC_STORE*5: + { + uint8_t *ptr; + uint8_t v; + READP(ptr, BINOP(0)); + READ1(v, BINOP(1)); + *ptr = v; + break; + } + case OP_BC_STORE*5+1: + { + uint8_t *ptr; + uint8_t v; + READP(ptr, BINOP(0)); + READ8(v, BINOP(1)); + *ptr = v; + break; + } + case OP_BC_STORE*5+2: + { + union unaligned_16 *ptr; + uint16_t v; + READP(ptr, BINOP(0)); + READ16(v, BINOP(1)); + ptr->una_s16 = v; + break; + } + case OP_BC_STORE*5+3: + { + union unaligned_32 *ptr; + uint32_t v; + READP(ptr, BINOP(0)); + READ32(v, BINOP(1)); + ptr->una_u32 = v; + break; + } + case OP_BC_STORE*5+4: + { + union unaligned_64 *ptr; + uint64_t v; + READP(ptr, BINOP(0)); + READ64(v, BINOP(1)); + ptr->una_u64 = v; + break; + } + /* TODO: implement OP_BC_GEP1, OP_BC_GEP2, OP_BC_GEPN */ default: cli_errmsg("Opcode %u of type %u is not implemented yet!\n", inst->interp_op/5, inst->interp_op%5); @@ -688,7 +777,9 @@ int cli_vm_execute(const struct cli_bc *bc, struct cli_bc_ctx *ctx, const struct } bb_inst++; inst++; - CHECK_GT(bb->numInsts, bb_inst); + if (bb) { + CHECK_GT(bb->numInsts, bb_inst); + } } while (stop == CL_SUCCESS); cli_stack_destroy(&stack); diff --git a/libclamav/c++/Makefile.am b/libclamav/c++/Makefile.am new file mode 100644 index 000000000..72dd9f05a --- /dev/null +++ b/libclamav/c++/Makefile.am @@ -0,0 +1,854 @@ +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +# MA 02110-1301, USA. + +AM_CPPFLAGS = -I$(top_srcdir)/../.. -I$(top_srcdir)/.. -I$(top_builddir)/../../ +ACLOCAL_AMFLAGS=-I m4 +if DEBUG_BUILD +LLVM_CONFIG=llvm/Debug/bin/llvm-config +else +LLVM_CONFIG=llvm/Release/bin/llvm-config +endif + +#$(LLVM_CONFIG): build-llvm +# we know this will be built with GNU make, so its safe to use GNU make specific +# $(shell ...) +#LLVM_DEPS=$(shell $(LLVM_CONFIG) --libfiles jit nativecodegen) +#libclamavcxx_la_CPPFLAGS = $(AM_CPPFLAGS) `$(LLVM_CONFIG) --cppflags` +#libclamavcxx_la_DEPENDENCIES = $(LLVM_DEPS) +#libclamavcxx_la_LDFLAGS = `$(LLVM_CONFIG) --ldflags --libs jit nativecodegen` +libclamavcxx_la_CPPFLAGS = $(AM_CPPFLAGS) $(LLVM_INCLUDES) $(LLVM_DEFS) +#libclamavcxx_la_DEPENDENCIES = $(LLVM_DEPS) + +noinst_LTLIBRARIES = libclamavcxx.la libllvmsupport.la libllvmsystem.la\ + libllvmcore.la libllvmtarget.la libllvmsdag.la libllvmcodegen.la libllvmexecutionengine.la\ + libllvmscalar.la libllvmipa.la libllvmtransformutils.la\ + libllvmmc.la +libclamavcxx_la_LIBADD= +if BUILD_X86 +libclamavcxx_la_LIBADD+=libllvmtargetx86.la +noinst_LTLIBRARIES+=libllvmtargetx86.la +endif +if BUILD_PPC +libclamavcxx_la_LIBADD+=libllvmtargetppc.la +noinst_LTLIBRARIES+=libllvmtargetppc.la +endif +if BUILD_ARM +libclamavcxx_la_LIBADD+=libllvmtargetarm.la +noinst_LTLIBRARIES+=libllvmtargetarm.la +endif + +libclamavcxx_la_LIBADD+=libllvmsdag.la libllvmexecutionengine.la\ + libllvmcodegen.la libllvmscalar.la\ + libllvmtransformutils.la libllvmipa.la libllvmtarget.la libllvmmc.la\ + libllvmcore.la libllvmsupport.la libllvmsystem.la + +libclamavcxx_la_LDFLAGS=-no-undefined +#libclamavcxx_la_LDFLAGS = `$(LLVM_CONFIG) --ldflags --libs jit nativecodegen` +libclamavcxx_la_SOURCES = bytecode2llvm.cpp + +LLVM_INCLUDES=-I$(top_srcdir)/llvm/include -I$(top_builddir)/llvm/include +# TODO: _DEBUG should be defined for --enable-debug, and NDEBUG otherwise, but +# keep it like this while I'm testing LLVM +# TODO: HP-UX should have -D_REENTRANT -D_HPUX_SOURCE +LLVM_DEFS=-D__STDC_LIMIT_MACROS -D__STDC_CONSTANT_MACROS -D_DEBUG -D_GNU_SOURCE +LLVM_CXXFLAGS=-Woverloaded-virtual -pedantic -Wno-long-long -Wall -W -Wno-unused-parameter -Wwrite-strings + +EXTRA_DIST=$(top_srcdir)/llvm llvmdejagnu.sh + +libllvmsystem_la_CPPFLAGS=$(LLVM_INCLUDES) $(LLVM_DEFS) +libllvmsystem_la_CXXFLAGS=$(LLVM_CXXFLAGS) -fno-exceptions +libllvmsystem_la_LDFLAGS=-pthread +libllvmsystem_la_LIBADD=-ldl +libllvmsystem_la_SOURCES = \ + llvm/lib/System/Alarm.cpp\ + llvm/lib/System/Atomic.cpp\ + llvm/lib/System/Disassembler.cpp\ + llvm/lib/System/DynamicLibrary.cpp\ + llvm/lib/System/Errno.cpp\ + llvm/lib/System/Host.cpp\ + llvm/lib/System/IncludeFile.cpp\ + llvm/lib/System/Memory.cpp\ + llvm/lib/System/Mutex.cpp\ + llvm/lib/System/Path.cpp\ + llvm/lib/System/Process.cpp\ + llvm/lib/System/Program.cpp\ + llvm/lib/System/RWMutex.cpp\ + llvm/lib/System/Signals.cpp\ + llvm/lib/System/ThreadLocal.cpp\ + llvm/lib/System/Threading.cpp\ + llvm/lib/System/TimeValue.cpp\ + llvm/lib/System/Unix/Alarm.inc\ + llvm/lib/System/Unix/Host.inc\ + llvm/lib/System/Unix/Memory.inc\ + llvm/lib/System/Unix/Mutex.inc\ + llvm/lib/System/Unix/Path.inc\ + llvm/lib/System/Unix/Process.inc\ + llvm/lib/System/Unix/Program.inc\ + llvm/lib/System/Unix/RWMutex.inc\ + llvm/lib/System/Unix/Signals.inc\ + llvm/lib/System/Unix/ThreadLocal.inc\ + llvm/lib/System/Unix/TimeValue.inc\ + llvm/lib/System/Win32/Alarm.inc\ + llvm/lib/System/Win32/DynamicLibrary.inc\ + llvm/lib/System/Win32/Host.inc\ + llvm/lib/System/Win32/Memory.inc\ + llvm/lib/System/Win32/Mutex.inc\ + llvm/lib/System/Win32/Path.inc\ + llvm/lib/System/Win32/Process.inc\ + llvm/lib/System/Win32/Program.inc\ + llvm/lib/System/Win32/RWMutex.inc\ + llvm/lib/System/Win32/Signals.inc\ + llvm/lib/System/Win32/ThreadLocal.inc\ + llvm/lib/System/Win32/TimeValue.inc + +libllvmsupport_la_CPPFLAGS=$(LLVM_INCLUDES) $(LLVM_DEFS) +libllvmsupport_la_CXXFLAGS=$(LLVM_CXXFLAGS) -fno-exceptions +libllvmsupport_la_SOURCES=\ + llvm/lib/Support/APFloat.cpp\ + llvm/lib/Support/APInt.cpp\ + llvm/lib/Support/APSInt.cpp\ + llvm/lib/Support/Allocator.cpp\ + llvm/lib/Support/CommandLine.cpp\ + llvm/lib/Support/ConstantRange.cpp\ + llvm/lib/Support/Debug.cpp\ + llvm/lib/Support/Dwarf.cpp\ + llvm/lib/Support/ErrorHandling.cpp\ + llvm/lib/Support/FileUtilities.cpp\ + llvm/lib/Support/FoldingSet.cpp\ + llvm/lib/Support/FormattedStream.cpp\ + llvm/lib/Support/GraphWriter.cpp\ + llvm/lib/Support/IsInf.cpp\ + llvm/lib/Support/IsNAN.cpp\ + llvm/lib/Support/ManagedStatic.cpp\ + llvm/lib/Support/MemoryBuffer.cpp\ + llvm/lib/Support/PluginLoader.cpp\ + llvm/lib/Support/PrettyStackTrace.cpp\ + llvm/lib/Support/SlowOperationInformer.cpp\ + llvm/lib/Support/SmallPtrSet.cpp\ + llvm/lib/Support/SourceMgr.cpp\ + llvm/lib/Support/Statistic.cpp\ + llvm/lib/Support/StringExtras.cpp\ + llvm/lib/Support/StringMap.cpp\ + llvm/lib/Support/StringPool.cpp\ + llvm/lib/Support/StringRef.cpp\ + llvm/lib/Support/SystemUtils.cpp\ + llvm/lib/Support/TargetRegistry.cpp\ + llvm/lib/Support/Timer.cpp\ + llvm/lib/Support/Triple.cpp\ + llvm/lib/Support/Twine.cpp\ + llvm/lib/Support/raw_os_ostream.cpp\ + llvm/lib/Support/raw_ostream.cpp\ + llvm/lib/Support/Regex.cpp\ + llvm/lib/Support/regcomp.c\ + llvm/lib/Support/regerror.c\ + llvm/lib/Support/regexec.c\ + llvm/lib/Support/regfree.c\ + llvm/lib/Support/regstrlcpy.c + +tblgen_CPPFLAGS=$(LLVM_INCLUDES) $(LLVM_DEFS) +tblgen_CXXFLAGS=$(LLVM_CXXFLAGS) +tblgen_LDADD=libllvmsupport.la libllvmsystem.la +#TODO: if VERSIONSCRIPT +tblgen_LDFLAGS= -Wl,--version-script,@top_srcdir@/llvm/autoconf/ExportMap.map +tblgen_SOURCES=\ + llvm/utils/TableGen/AsmMatcherEmitter.cpp\ + llvm/utils/TableGen/AsmWriterEmitter.cpp\ + llvm/utils/TableGen/CallingConvEmitter.cpp\ + llvm/utils/TableGen/ClangDiagnosticsEmitter.cpp\ + llvm/utils/TableGen/CodeEmitterGen.cpp\ + llvm/utils/TableGen/CodeGenDAGPatterns.cpp\ + llvm/utils/TableGen/CodeGenInstruction.cpp\ + llvm/utils/TableGen/CodeGenTarget.cpp\ + llvm/utils/TableGen/DisassemblerEmitter.cpp\ + llvm/utils/TableGen/DAGISelEmitter.cpp\ + llvm/utils/TableGen/FastISelEmitter.cpp\ + llvm/utils/TableGen/InstrEnumEmitter.cpp\ + llvm/utils/TableGen/InstrInfoEmitter.cpp\ + llvm/utils/TableGen/IntrinsicEmitter.cpp\ + llvm/utils/TableGen/LLVMCConfigurationEmitter.cpp\ + llvm/utils/TableGen/OptParserEmitter.cpp\ + llvm/utils/TableGen/Record.cpp\ + llvm/utils/TableGen/RegisterInfoEmitter.cpp\ + llvm/utils/TableGen/SubtargetEmitter.cpp\ + llvm/utils/TableGen/TGLexer.cpp\ + llvm/utils/TableGen/TGParser.cpp\ + llvm/utils/TableGen/TGValueTypes.cpp\ + llvm/utils/TableGen/TableGen.cpp\ + llvm/utils/TableGen/TableGenBackend.cpp + +libllvmcore_la_CPPFLAGS=$(LLVM_INCLUDES) $(LLVM_DEFS) +libllvmcore_la_CXXFLAGS=$(LLVM_CXXFLAGS) -fno-exceptions +libllvmcore_la_SOURCES=\ + llvm/lib/VMCore/AsmWriter.cpp\ + llvm/lib/VMCore/Attributes.cpp\ + llvm/lib/VMCore/AutoUpgrade.cpp\ + llvm/lib/VMCore/BasicBlock.cpp\ + llvm/lib/VMCore/ConstantFold.cpp\ + llvm/lib/VMCore/Constants.cpp\ + llvm/lib/VMCore/Core.cpp\ + llvm/lib/VMCore/Dominators.cpp\ + llvm/lib/VMCore/Function.cpp\ + llvm/lib/VMCore/Globals.cpp\ + llvm/lib/VMCore/InlineAsm.cpp\ + llvm/lib/VMCore/Instruction.cpp\ + llvm/lib/VMCore/Instructions.cpp\ + llvm/lib/VMCore/IntrinsicInst.cpp\ + llvm/lib/VMCore/LLVMContext.cpp\ + llvm/lib/VMCore/LeakDetector.cpp\ + llvm/lib/VMCore/Mangler.cpp\ + llvm/lib/VMCore/Metadata.cpp\ + llvm/lib/VMCore/Module.cpp\ + llvm/lib/VMCore/ModuleProvider.cpp\ + llvm/lib/VMCore/Pass.cpp\ + llvm/lib/VMCore/PassManager.cpp\ + llvm/lib/VMCore/PrintModulePass.cpp\ + llvm/lib/VMCore/Type.cpp\ + llvm/lib/VMCore/TypeSymbolTable.cpp\ + llvm/lib/VMCore/Use.cpp\ + llvm/lib/VMCore/Value.cpp\ + llvm/lib/VMCore/ValueSymbolTable.cpp\ + llvm/lib/VMCore/ValueTypes.cpp\ + llvm/lib/VMCore/Verifier.cpp + +TBLGEN=$(top_builddir)/tblgen +TBLGEN_V=$(AM_V_GEN)$(TBLGEN) +TBLGEN_FLAGS=-I$(top_srcdir)/llvm/include -I$(top_srcdir)/llvm/lib/Target + +BUILT_SOURCES=llvm/include/llvm/Intrinsics.gen +llvm/include/llvm/Intrinsics.gen: llvm/include/llvm/Intrinsics.td $(TBLGEN) + $(TBLGEN_V) $(TBLGEN_FLAGS) -gen-intrinsic -o $@ $< + +# X86 Target +if BUILD_X86 +TBLGEN_FLAGS_X86= $(TBLGEN_FLAGS) -I$(top_srcdir)/llvm/lib/Target/X86 +X86GenRegisterInfo.h.inc: llvm/lib/Target/X86/X86.td $(TBLGEN) + $(TBLGEN_V) $(TBLGEN_FLAGS_X86) -gen-register-desc-header -o $@ $< + +X86GenRegisterNames.inc: llvm/lib/Target/X86/X86.td $(TBLGEN) + $(TBLGEN_V) $(TBLGEN_FLAGS_X86) -gen-register-enums -o $@ $< + +X86GenRegisterInfo.inc: llvm/lib/Target/X86/X86.td $(TBLGEN) + $(TBLGEN_V) $(TBLGEN_FLAGS_X86) -gen-register-desc -o $@ $< + +X86GenInstrNames.inc: llvm/lib/Target/X86/X86.td $(TBLGEN) + $(TBLGEN_V) $(TBLGEN_FLAGS_X86) -gen-instr-enums -o $@ $< + +X86GenInstrInfo.inc: llvm/lib/Target/X86/X86.td $(TBLGEN) + $(TBLGEN_V) $(TBLGEN_FLAGS_X86) -gen-instr-desc -o $@ $< + +X86GenAsmWriter.inc: llvm/lib/Target/X86/X86.td $(TBLGEN) + $(TBLGEN_V) $(TBLGEN_FLAGS_X86) -gen-asm-writer -o $@ $< + +X86GenAsmWriter1.inc: llvm/lib/Target/X86/X86.td $(TBLGEN) + $(TBLGEN_V) $(TBLGEN_FLAGS_X86) -gen-asm-writer -asmwriternum=1 -o $@ $< + +X86GenAsmMatcher.inc: llvm/lib/Target/X86/X86.td $(TBLGEN) + $(TBLGEN_V) $(TBLGEN_FLAGS_X86) -gen-asm-matcher -o $@ $< + +X86GenDAGISel.inc: llvm/lib/Target/X86/X86.td $(TBLGEN) + $(TBLGEN_V) $(TBLGEN_FLAGS_X86) -gen-dag-isel -o $@ $< + +X86GenFastISel.inc: llvm/lib/Target/X86/X86.td $(TBLGEN) + $(TBLGEN_V) $(TBLGEN_FLAGS_X86) -gen-fast-isel -o $@ $< + +X86GenCallingConv.inc: llvm/lib/Target/X86/X86.td $(TBLGEN) + $(TBLGEN_V) $(TBLGEN_FLAGS_X86) -gen-callingconv -o $@ $< + +X86GenSubtarget.inc: llvm/lib/Target/X86/X86.td $(TBLGEN) + $(TBLGEN_V) $(TBLGEN_FLAGS_X86) -gen-subtarget -o $@ $< + +libllvmtargetx86_la_CPPFLAGS=$(LLVM_INCLUDES) $(LLVM_DEFS) -I$(top_builddir) -I$(top_srcdir)/llvm/lib/Target/X86 +BUILT_SOURCES+=X86GenRegisterInfo.h.inc X86GenRegisterNames.inc X86GenRegisterInfo.inc X86GenInstrNames.inc X86GenInstrInfo.inc\ + X86GenAsmWriter.inc X86GenAsmWriter1.inc X86GenAsmMatcher.inc X86GenDAGISel.inc X86GenFastISel.inc X86GenCallingConv.inc\ + X86GenSubtarget.inc + +libllvmtargetx86_la_CXXFLAGS=$(LLVM_CXXFLAGS) -fno-exceptions +libllvmtargetx86_la_SOURCES=\ + llvm/lib/Target/X86/X86CodeEmitter.cpp\ + llvm/lib/Target/X86/X86ELFWriterInfo.cpp\ + llvm/lib/Target/X86/X86FloatingPoint.cpp\ + llvm/lib/Target/X86/X86FloatingPointRegKill.cpp\ + llvm/lib/Target/X86/X86ISelDAGToDAG.cpp\ + llvm/lib/Target/X86/X86ISelLowering.cpp\ + llvm/lib/Target/X86/X86InstrInfo.cpp\ + llvm/lib/Target/X86/X86JITInfo.cpp\ + llvm/lib/Target/X86/X86MCAsmInfo.cpp\ + llvm/lib/Target/X86/X86RegisterInfo.cpp\ + llvm/lib/Target/X86/X86Subtarget.cpp\ + llvm/lib/Target/X86/X86TargetMachine.cpp\ + llvm/lib/Target/X86/X86FastISel.cpp\ + llvm/lib/Target/X86/X86TargetObjectFile.cpp\ + llvm/lib/Target/X86/TargetInfo/X86TargetInfo.cpp +endif + +if BUILD_PPC +# PPC Target +TBLGEN_FLAGS_PPC= $(TBLGEN_FLAGS) -I$(top_srcdir)/llvm/lib/Target/PowerPC +PPCGenInstrNames.inc: llvm/lib/Target/PowerPC/PPC.td $(TBLGEN) + $(TBLGEN_V) $(TBLGEN_FLAGS_PPC) -gen-instr-enums -o $@ $< + +PPCGenRegisterNames.inc: llvm/lib/Target/PowerPC/PPC.td $(TBLGEN) + $(TBLGEN_V) $(TBLGEN_FLAGS_PPC) -gen-register-enums -o $@ $< + +PPCGenAsmWriter.inc: llvm/lib/Target/PowerPC/PPC.td $(TBLGEN) + $(TBLGEN_V) $(TBLGEN_FLAGS_PPC) -gen-asm-writer -o $@ $< + +PPCGenCodeEmitter.inc: llvm/lib/Target/PowerPC/PPC.td $(TBLGEN) + $(TBLGEN_V) $(TBLGEN_FLAGS_PPC) -gen-emitter -o $@ $< + +PPCRegisterInfo.h.inc: llvm/lib/Target/PowerPC/PPC.td $(TBLGEN) + $(TBLGEN_V) $(TBLGEN_FLAGS_PPC) -gen-register-desc-header -o $@ $< + +PPCGenRegisterInfo.inc: llvm/lib/Target/PowerPC/PPC.td $(TBLGEN) + $(TBLGEN_V) $(TBLGEN_FLAGS_PPC) -gen-register-desc -o $@ $< + +PPCGenRegisterInfo.h.inc: llvm/lib/Target/PowerPC/PPC.td $(TBLGEN) + $(TBLGEN_V) $(TBLGEN_FLAGS_PPC) -gen-register-desc-header -o $@ $< + +PPCGenInstrInfo.inc: llvm/lib/Target/PowerPC/PPC.td $(TBLGEN) + $(TBLGEN_V) $(TBLGEN_FLAGS_PPC) -gen-instr-desc -o $@ $< + +PPCGenDAGISel.inc: llvm/lib/Target/PowerPC/PPC.td $(TBLGEN) + $(TBLGEN_V) $(TBLGEN_FLAGS_PPC) -gen-dag-isel -o $@ $< + +PPCGenCallingConv.inc: llvm/lib/Target/PowerPC/PPC.td $(TBLGEN) + $(TBLGEN_V) $(TBLGEN_FLAGS_PPC) -gen-callingconv -o $@ $< + +PPCGenSubtarget.inc: llvm/lib/Target/PowerPC/PPC.td $(TBLGEN) + $(TBLGEN_V) $(TBLGEN_FLAGS_PPC) -gen-subtarget -o $@ $< + +libllvmtargetppc_la_CPPFLAGS=$(LLVM_INCLUDES) $(LLVM_DEFS) -I$(top_builddir) -I$(top_srcdir)/llvm/lib/Target/PowerPC +BUILT_SOURCES += PPCGenInstrNames.inc PPCGenRegisterNames.inc PPCGenAsmWriter.inc PPCGenCodeEmitter.inc PPCGenRegisterInfo.h.inc PPCGenRegisterInfo.inc\ + PPCGenInstrInfo.inc PPCGenDAGISel.inc PPCGenCallingConv.inc PPCGenSubtarget.inc + +libllvmtargetppc_la_CXXFLAGS=$(LLVM_CXXFLAGS) -fno-exceptions +libllvmtargetppc_la_SOURCES=\ + llvm/lib/Target/PowerPC/PPCBranchSelector.cpp\ + llvm/lib/Target/PowerPC/PPCCodeEmitter.cpp\ + llvm/lib/Target/PowerPC/PPCHazardRecognizers.cpp\ + llvm/lib/Target/PowerPC/PPCInstrInfo.cpp\ + llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp\ + llvm/lib/Target/PowerPC/PPCISelLowering.cpp\ + llvm/lib/Target/PowerPC/PPCJITInfo.cpp\ + llvm/lib/Target/PowerPC/PPCMachOWriterInfo.cpp\ + llvm/lib/Target/PowerPC/PPCMCAsmInfo.cpp\ + llvm/lib/Target/PowerPC/PPCPredicates.cpp\ + llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp\ + llvm/lib/Target/PowerPC/PPCSubtarget.cpp\ + llvm/lib/Target/PowerPC/PPCTargetMachine.cpp\ + llvm/lib/Target/PowerPC/TargetInfo/PowerPCTargetInfo.cpp +endif + +if BUILD_ARM +# ARM Target +TBLGEN_FLAGS_ARM= $(TBLGEN_FLAGS) -I$(top_srcdir)/llvm/lib/Target/ARM +ARMGenRegisterInfo.h.inc: llvm/lib/Target/ARM/ARM.td $(TBLGEN) + $(TBLGEN_V) $(TBLGEN_FLAGS_ARM) -gen-register-desc-header -o $@ $< + +ARMGenRegisterNames.inc: llvm/lib/Target/ARM/ARM.td $(TBLGEN) + $(TBLGEN_V) $(TBLGEN_FLAGS_ARM) -gen-register-enums -o $@ $< + +ARMGenRegisterInfo.inc: llvm/lib/Target/ARM/ARM.td $(TBLGEN) + $(TBLGEN_V) $(TBLGEN_FLAGS_ARM) -gen-register-desc -o $@ $< + +ARMGenInstrNames.inc: llvm/lib/Target/ARM/ARM.td $(TBLGEN) + $(TBLGEN_V) $(TBLGEN_FLAGS_ARM) -gen-instr-enums -o $@ $< + +ARMGenInstrInfo.inc: llvm/lib/Target/ARM/ARM.td $(TBLGEN) + $(TBLGEN_V) $(TBLGEN_FLAGS_ARM) -gen-instr-desc -o $@ $< + +ARMGenCodeEmitter.inc: llvm/lib/Target/ARM/ARM.td $(TBLGEN) + $(TBLGEN_V) $(TBLGEN_FLAGS_ARM) -gen-emitter -o $@ $< + +ARMGenAsmWriter.inc: llvm/lib/Target/ARM/ARM.td $(TBLGEN) + $(TBLGEN_V) $(TBLGEN_FLAGS_ARM) -gen-asm-writer -o $@ $< + +ARMGenDAGISel.inc: llvm/lib/Target/ARM/ARM.td $(TBLGEN) + $(TBLGEN_V) $(TBLGEN_FLAGS_ARM) -gen-dag-isel -o $@ $< + +ARMGenCallingConv.inc: llvm/lib/Target/ARM/ARM.td $(TBLGEN) + $(TBLGEN_V) $(TBLGEN_FLAGS_ARM) -gen-callingconv -o $@ $< + +ARMGenSubtarget.inc: llvm/lib/Target/ARM/ARM.td $(TBLGEN) + $(TBLGEN_V) $(TBLGEN_FLAGS_ARM) -gen-subtarget -o $@ $< + +libllvmtargetarm_la_CPPFLAGS=$(LLVM_INCLUDES) $(LLVM_DEFS) -I$(top_builddir) -I$(top_srcdir)/llvm/lib/Target/ARM +BUILT_SOURCES += ARMGenRegisterInfo.h.inc ARMGenRegisterNames.inc ARMGenRegisterInfo.inc ARMGenInstrNames.inc ARMGenInstrInfo.inc ARMGenCodeEmitter.inc\ + ARMGenAsmWriter.inc ARMGenDAGISel.inc ARMGenCallingConv.inc ARMGenSubtarget.inc + +libllvmtargetarm_la_CXXFLAGS=$(LLVM_CXXFLAGS) -fno-exceptions +libllvmtargetarm_la_SOURCES=\ + llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp\ + llvm/lib/Target/ARM/ARMBaseRegisterInfo.cpp\ + llvm/lib/Target/ARM/ARMCodeEmitter.cpp\ + llvm/lib/Target/ARM/ARMConstantIslandPass.cpp\ + llvm/lib/Target/ARM/ARMConstantPoolValue.cpp\ + llvm/lib/Target/ARM/ARMExpandPseudoInsts.cpp\ + llvm/lib/Target/ARM/ARMInstrInfo.cpp\ + llvm/lib/Target/ARM/ARMISelDAGToDAG.cpp\ + llvm/lib/Target/ARM/ARMISelLowering.cpp\ + llvm/lib/Target/ARM/ARMJITInfo.cpp\ + llvm/lib/Target/ARM/ARMLoadStoreOptimizer.cpp\ + llvm/lib/Target/ARM/ARMMCAsmInfo.cpp\ + llvm/lib/Target/ARM/ARMRegisterInfo.cpp\ + llvm/lib/Target/ARM/ARMSubtarget.cpp\ + llvm/lib/Target/ARM/ARMTargetMachine.cpp\ + llvm/lib/Target/ARM/NEONMoveFix.cpp\ + llvm/lib/Target/ARM/NEONPreAllocPass.cpp\ + llvm/lib/Target/ARM/Thumb1InstrInfo.cpp\ + llvm/lib/Target/ARM/Thumb1RegisterInfo.cpp\ + llvm/lib/Target/ARM/Thumb2ITBlockPass.cpp\ + llvm/lib/Target/ARM/Thumb2InstrInfo.cpp\ + llvm/lib/Target/ARM/Thumb2RegisterInfo.cpp\ + llvm/lib/Target/ARM/Thumb2SizeReduction.cpp\ + llvm/lib/Target/ARM/TargetInfo/ARMTargetInfo.cpp +endif + +# End of Targets + +libllvmtarget_la_CPPFLAGS=$(LLVM_INCLUDES) $(LLVM_DEFS) +libllvmtarget_la_CXXFLAGS=$(LLVM_CXXFLAGS) -fno-exceptions +libllvmtarget_la_SOURCES=\ + llvm/lib/Target/SubtargetFeature.cpp\ + llvm/lib/Target/Target.cpp\ + llvm/lib/Target/TargetData.cpp\ + llvm/lib/Target/TargetELFWriterInfo.cpp\ + llvm/lib/Target/TargetFrameInfo.cpp\ + llvm/lib/Target/TargetInstrInfo.cpp\ + llvm/lib/Target/TargetIntrinsicInfo.cpp\ + llvm/lib/Target/TargetLoweringObjectFile.cpp\ + llvm/lib/Target/TargetMachOWriterInfo.cpp\ + llvm/lib/Target/TargetMachine.cpp\ + llvm/lib/Target/TargetRegisterInfo.cpp\ + llvm/lib/Target/TargetSubtarget.cpp + +libllvmmc_la_CPPFLAGS=$(LLVM_INCLUDES) $(LLVM_DEFS) +libllvmmc_la_CXXFLAGS=$(LLVM_CXXFLAGS) -fno-exceptions +libllvmmc_la_SOURCES=\ + llvm/lib/MC/MCAsmInfo.cpp\ + llvm/lib/MC/MCAsmInfoCOFF.cpp\ + llvm/lib/MC/MCAsmInfoDarwin.cpp\ + llvm/lib/MC/MCAsmLexer.cpp\ + llvm/lib/MC/MCAsmParser.cpp\ + llvm/lib/MC/MCAsmStreamer.cpp\ + llvm/lib/MC/MCAssembler.cpp\ + llvm/lib/MC/MCCodeEmitter.cpp\ + llvm/lib/MC/MCContext.cpp\ + llvm/lib/MC/MCExpr.cpp\ + llvm/lib/MC/MCInst.cpp\ + llvm/lib/MC/MCMachOStreamer.cpp\ + llvm/lib/MC/MCNullStreamer.cpp\ + llvm/lib/MC/MCSection.cpp\ + llvm/lib/MC/MCSectionELF.cpp\ + llvm/lib/MC/MCSectionMachO.cpp\ + llvm/lib/MC/MCStreamer.cpp\ + llvm/lib/MC/MCSymbol.cpp\ + llvm/lib/MC/MCValue.cpp\ + llvm/lib/MC/TargetAsmParser.cpp + +libllvmsdag_la_CPPFLAGS=$(LLVM_INCLUDES) $(LLVM_DEFS) +libllvmsdag_la_CXXFLAGS=$(LLVM_CXXFLAGS) -fno-exceptions +libllvmsdag_la_SOURCES=\ + llvm/lib/CodeGen/SelectionDAG/CallingConvLower.cpp\ + llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp\ + llvm/lib/CodeGen/SelectionDAG/FastISel.cpp\ + llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp\ + llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp\ + llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp\ + llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp\ + llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp\ + llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp\ + llvm/lib/CodeGen/SelectionDAG/LegalizeTypesGeneric.cpp\ + llvm/lib/CodeGen/SelectionDAG/LegalizeVectorOps.cpp\ + llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp\ + llvm/lib/CodeGen/SelectionDAG/ScheduleDAGFast.cpp\ + llvm/lib/CodeGen/SelectionDAG/ScheduleDAGList.cpp\ + llvm/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp\ + llvm/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp\ + llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp\ + llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp\ + llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp\ + llvm/lib/CodeGen/SelectionDAG/SelectionDAGPrinter.cpp\ + llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp\ + llvm/lib/CodeGen/AsmPrinter/DwarfWriter.cpp\ + llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp\ + llvm/lib/CodeGen/AsmPrinter/DwarfException.cpp\ + llvm/lib/CodeGen/AsmPrinter/DwarfLabel.cpp\ + llvm/lib/CodeGen/AsmPrinter/DwarfPrinter.cpp\ + llvm/lib/CodeGen/AsmPrinter/DIE.cpp\ + llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp + +libllvmipa_la_CPPFLAGS=$(LLVM_INCLUDES) $(LLVM_DEFS) +libllvmipa_la_CXXFLAGS=$(LLVM_CXXFLAGS) -fno-exceptions +libllvmipa_la_SOURCES=\ + llvm/lib/Analysis/AliasAnalysis.cpp\ + llvm/lib/Analysis/AliasSetTracker.cpp\ + llvm/lib/Analysis/BasicAliasAnalysis.cpp\ + llvm/lib/Analysis/CaptureTracking.cpp\ + llvm/lib/Analysis/ConstantFolding.cpp\ + llvm/lib/Analysis/DebugInfo.cpp\ + llvm/lib/Analysis/IVUsers.cpp\ + llvm/lib/Analysis/InstructionSimplify.cpp\ + llvm/lib/Analysis/LiveValues.cpp\ + llvm/lib/Analysis/LoopDependenceAnalysis.cpp\ + llvm/lib/Analysis/LoopInfo.cpp\ + llvm/lib/Analysis/LoopPass.cpp\ + llvm/lib/Analysis/MemoryBuiltins.cpp\ + llvm/lib/Analysis/MemoryDependenceAnalysis.cpp\ + llvm/lib/Analysis/ProfileInfo.cpp\ + llvm/lib/Analysis/ScalarEvolution.cpp\ + llvm/lib/Analysis/ScalarEvolutionExpander.cpp\ + llvm/lib/Analysis/ValueTracking.cpp\ + llvm/lib/Analysis/IPA/CallGraph.cpp + +libllvmcodegen_la_CPPFLAGS=$(LLVM_INCLUDES) $(LLVM_DEFS) +libllvmcodegen_la_CXXFLAGS=$(LLVM_CXXFLAGS) -fno-exceptions +libllvmcodegen_la_SOURCES=\ + llvm/lib/CodeGen/AggressiveAntiDepBreaker.cpp\ + llvm/lib/CodeGen/BranchFolding.cpp\ + llvm/lib/CodeGen/CriticalAntiDepBreaker.cpp\ + llvm/lib/CodeGen/CodePlacementOpt.cpp\ + llvm/lib/CodeGen/DeadMachineInstructionElim.cpp\ + llvm/lib/CodeGen/DwarfEHPrepare.cpp\ + llvm/lib/CodeGen/ELFCodeEmitter.cpp\ + llvm/lib/CodeGen/ELFWriter.cpp\ + llvm/lib/CodeGen/ExactHazardRecognizer.cpp\ + llvm/lib/CodeGen/GCMetadata.cpp\ + llvm/lib/CodeGen/GCMetadataPrinter.cpp\ + llvm/lib/CodeGen/GCStrategy.cpp\ + llvm/lib/CodeGen/IfConversion.cpp\ + llvm/lib/CodeGen/IntrinsicLowering.cpp\ + llvm/lib/CodeGen/LLVMTargetMachine.cpp\ + llvm/lib/CodeGen/LatencyPriorityQueue.cpp\ + llvm/lib/CodeGen/LiveInterval.cpp\ + llvm/lib/CodeGen/LiveIntervalAnalysis.cpp\ + llvm/lib/CodeGen/LiveStackAnalysis.cpp\ + llvm/lib/CodeGen/LiveVariables.cpp\ + llvm/lib/CodeGen/LowerSubregs.cpp\ + llvm/lib/CodeGen/MachineBasicBlock.cpp\ + llvm/lib/CodeGen/MachineDominators.cpp\ + llvm/lib/CodeGen/MachineFunction.cpp\ + llvm/lib/CodeGen/MachineFunctionAnalysis.cpp\ + llvm/lib/CodeGen/MachineFunctionPass.cpp\ + llvm/lib/CodeGen/MachineInstr.cpp\ + llvm/lib/CodeGen/MachineLICM.cpp\ + llvm/lib/CodeGen/MachineLoopInfo.cpp\ + llvm/lib/CodeGen/MachineModuleInfo.cpp\ + llvm/lib/CodeGen/MachineModuleInfoImpls.cpp\ + llvm/lib/CodeGen/MachinePassRegistry.cpp\ + llvm/lib/CodeGen/MachineRegisterInfo.cpp\ + llvm/lib/CodeGen/MachineSink.cpp\ + llvm/lib/CodeGen/MachineVerifier.cpp\ + llvm/lib/CodeGen/ObjectCodeEmitter.cpp\ + llvm/lib/CodeGen/OcamlGC.cpp\ + llvm/lib/CodeGen/PHIElimination.cpp\ + llvm/lib/CodeGen/Passes.cpp\ + llvm/lib/CodeGen/PostRASchedulerList.cpp\ + llvm/lib/CodeGen/PreAllocSplitting.cpp\ + llvm/lib/CodeGen/ProcessImplicitDefs.cpp\ + llvm/lib/CodeGen/PrologEpilogInserter.cpp\ + llvm/lib/CodeGen/PseudoSourceValue.cpp\ + llvm/lib/CodeGen/RegAllocLinearScan.cpp\ + llvm/lib/CodeGen/RegAllocLocal.cpp\ + llvm/lib/CodeGen/RegAllocPBQP.cpp\ + llvm/lib/CodeGen/RegisterCoalescer.cpp\ + llvm/lib/CodeGen/RegisterScavenging.cpp\ + llvm/lib/CodeGen/ScheduleDAG.cpp\ + llvm/lib/CodeGen/ScheduleDAGEmit.cpp\ + llvm/lib/CodeGen/ScheduleDAGInstrs.cpp\ + llvm/lib/CodeGen/ScheduleDAGPrinter.cpp\ + llvm/lib/CodeGen/ShadowStackGC.cpp\ + llvm/lib/CodeGen/ShrinkWrapping.cpp\ + llvm/lib/CodeGen/SimpleRegisterCoalescing.cpp\ + llvm/lib/CodeGen/SjLjEHPrepare.cpp\ + llvm/lib/CodeGen/SlotIndexes.cpp\ + llvm/lib/CodeGen/Spiller.cpp\ + llvm/lib/CodeGen/StackProtector.cpp\ + llvm/lib/CodeGen/StackSlotColoring.cpp\ + llvm/lib/CodeGen/StrongPHIElimination.cpp\ + llvm/lib/CodeGen/TailDuplication.cpp\ + llvm/lib/CodeGen/TargetInstrInfoImpl.cpp\ + llvm/lib/CodeGen/TwoAddressInstructionPass.cpp\ + llvm/lib/CodeGen/UnreachableBlockElim.cpp\ + llvm/lib/CodeGen/VirtRegMap.cpp\ + llvm/lib/CodeGen/VirtRegRewriter.cpp + + +libllvmscalar_la_CPPFLAGS=$(LLVM_INCLUDES) $(LLVM_DEFS) +libllvmscalar_la_CXXFLAGS=$(LLVM_CXXFLAGS) -fno-exceptions +libllvmscalar_la_SOURCES=\ + llvm/lib/Transforms/Scalar/CodeGenPrepare.cpp\ + llvm/lib/Transforms/Scalar/DCE.cpp\ + llvm/lib/Transforms/Scalar/GEPSplitter.cpp\ + llvm/lib/Transforms/Scalar/GVN.cpp\ + llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp\ + llvm/lib/Transforms/Scalar/ConstantProp.cpp\ + llvm/lib/Transforms/Scalar/SimplifyCFGPass.cpp + +libllvmtransformutils_la_CPPFLAGS=$(LLVM_INCLUDES) $(LLVM_DEFS) +libllvmtransformutils_la_CXXFLAGS=$(LLVM_CXXFLAGS) -fno-exceptions +libllvmtransformutils_la_SOURCES=\ + llvm/lib/Transforms/Utils/AddrModeMatcher.cpp\ + llvm/lib/Transforms/Utils/BasicBlockUtils.cpp\ + llvm/lib/Transforms/Utils/BreakCriticalEdges.cpp\ + llvm/lib/Transforms/Utils/DemoteRegToStack.cpp\ + llvm/lib/Transforms/Utils/LCSSA.cpp\ + llvm/lib/Transforms/Utils/Local.cpp\ + llvm/lib/Transforms/Utils/LoopSimplify.cpp\ + llvm/lib/Transforms/Utils/LowerInvoke.cpp\ + llvm/lib/Transforms/Utils/LowerSwitch.cpp\ + llvm/lib/Transforms/Utils/Mem2Reg.cpp\ + llvm/lib/Transforms/Utils/PromoteMemoryToRegister.cpp\ + llvm/lib/Transforms/Utils/SimplifyCFG.cpp\ + llvm/lib/Transforms/Utils/SSAUpdater.cpp\ + llvm/lib/Transforms/Utils/UnifyFunctionExitNodes.cpp + +libllvmexecutionengine_la_CPPFLAGS=$(LLVM_INCLUDES) $(LLVM_DEFS) +libllvmexecutionengine_la_CXXFLAGS=$(LLVM_CXXFLAGS) -fno-exceptions +libllvmexecutionengine_la_SOURCES=\ + llvm/lib/ExecutionEngine/ExecutionEngine.cpp\ + llvm/lib/ExecutionEngine/JIT/Intercept.cpp\ + llvm/lib/ExecutionEngine/JIT/JIT.cpp\ + llvm/lib/ExecutionEngine/JIT/JITDebugRegisterer.cpp\ + llvm/lib/ExecutionEngine/JIT/JITDwarfEmitter.cpp\ + llvm/lib/ExecutionEngine/JIT/JITEmitter.cpp\ + llvm/lib/ExecutionEngine/JIT/JITMemoryManager.cpp\ + llvm/lib/ExecutionEngine/JIT/TargetSelect.cpp +# llvm/lib/ExecutionEngine/JIT/OProfileJITEventListener.cpp + +# Used only by make check + +libllvmbitreader_la_CPPFLAGS=$(LLVM_INCLUDES) $(LLVM_DEFS) +libllvmbitreader_la_CXXFLAGS=$(LLVM_CXXFLAGS) -fno-exceptions +libllvmbitreader_la_SOURCES=\ + llvm/lib/Bitcode/Reader/BitReader.cpp\ + llvm/lib/Bitcode/Reader/BitcodeReader.cpp\ + llvm/lib/Bitcode/Reader/Deserialize.cpp\ + llvm/lib/Bitcode/Reader/DeserializeAPFloat.cpp\ + llvm/lib/Bitcode/Reader/DeserializeAPInt.cpp + +libllvmbitwriter_la_CPPFLAGS=$(LLVM_INCLUDES) $(LLVM_DEFS) +libllvmbitwriter_la_CXXFLAGS=$(LLVM_CXXFLAGS) -fno-exceptions +libllvmbitwriter_la_SOURCES=\ + llvm/lib/Bitcode/Writer/BitWriter.cpp\ + llvm/lib/Bitcode/Writer/BitcodeWriter.cpp\ + llvm/lib/Bitcode/Writer/BitcodeWriterPass.cpp\ + llvm/lib/Bitcode/Writer/Serialize.cpp\ + llvm/lib/Bitcode/Writer/SerializeAPFloat.cpp\ + llvm/lib/Bitcode/Writer/SerializeAPInt.cpp\ + llvm/lib/Bitcode/Writer/ValueEnumerator.cpp + +libllvmasmparser_la_CPPFLAGS=$(LLVM_INCLUDES) $(LLVM_DEFS) +libllvmasmparser_la_CXXFLAGS=$(LLVM_CXXFLAGS) -fno-exceptions +libllvmasmparser_la_SOURCES=\ + llvm/lib/AsmParser/LLLexer.cpp\ + llvm/lib/AsmParser/LLParser.cpp\ + llvm/lib/AsmParser/Parser.cpp + +libllvminterpreter_la_CPPFLAGS=$(LLVM_INCLUDES) $(LLVM_DEFS) -I$(top_srcdir)/llvm/utils/unittest/googletest/include +libllvminterpreter_la_CXXFLAGS=$(LLVM_CXXFLAGS) -fno-exceptions -Wno-missing-field-initializers -Wno-variadic-macros +libllvminterpreter_la_SOURCES=\ + llvm/lib/ExecutionEngine/Interpreter/Execution.cpp\ + llvm/lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp\ + llvm/lib/ExecutionEngine/Interpreter/Interpreter.cpp + +libgoogletest_la_CPPFLAGS=$(LLVM_INCLUDES) $(LLVM_DEFS) -I$(top_srcdir)/llvm/utils/unittest/googletest/include +libgoogletest_la_CXXFLAGS=$(LLVM_CXXFLAGS) -fno-exceptions -Wno-missing-field-initializers -Wno-variadic-macros +libgoogletest_la_SOURCES=\ + llvm/utils/unittest/googletest/gtest-death-test.cc\ + llvm/utils/unittest/googletest/gtest-filepath.cc\ + llvm/utils/unittest/googletest/gtest-port.cc\ + llvm/utils/unittest/googletest/gtest-test-part.cc\ + llvm/utils/unittest/googletest/gtest-typed-test.cc\ + llvm/utils/unittest/googletest/gtest.cc\ + llvm/utils/unittest/UnitTestMain/TestMain.cpp + +llvmunittest_ADT_CPPFLAGS=$(LLVM_INCLUDES) $(LLVM_DEFS) -I$(top_srcdir)/llvm/utils/unittest/googletest/include +llvmunittest_ADT_CXXFLAGS=$(LLVM_CXXFLAGS) -fno-exceptions -Wno-variadic-macros +llvmunittest_ADT_LDADD=libgoogletest.la libllvmcore.la libllvmsupport.la libllvmsystem.la +llvmunittest_ADT_SOURCES=\ + llvm/unittests/ADT/APFloatTest.cpp\ + llvm/unittests/ADT/APIntTest.cpp\ + llvm/unittests/ADT/DenseMapTest.cpp\ + llvm/unittests/ADT/DenseSetTest.cpp\ + llvm/unittests/ADT/ImmutableSetTest.cpp\ + llvm/unittests/ADT/SmallStringTest.cpp\ + llvm/unittests/ADT/SmallVectorTest.cpp\ + llvm/unittests/ADT/SparseBitVectorTest.cpp\ + llvm/unittests/ADT/StringMapTest.cpp\ + llvm/unittests/ADT/StringRefTest.cpp\ + llvm/unittests/ADT/TripleTest.cpp\ + llvm/unittests/ADT/TwineTest.cpp + +llvmunittest_Support_CPPFLAGS=$(LLVM_INCLUDES) $(LLVM_DEFS) -I$(top_srcdir)/llvm/utils/unittest/googletest/include +llvmunittest_Support_CXXFLAGS=$(LLVM_CXXFLAGS) -fno-exceptions -Wno-variadic-macros +llvmunittest_Support_LDADD=libgoogletest.la libllvmcore.la libllvmsupport.la libllvmsystem.la +llvmunittest_Support_SOURCES=\ + llvm/unittests/Support/AllocatorTest.cpp\ + llvm/unittests/Support/ConstantRangeTest.cpp\ + llvm/unittests/Support/MathExtrasTest.cpp\ + llvm/unittests/Support/RegexTest.cpp\ + llvm/unittests/Support/TypeBuilderTest.cpp\ + llvm/unittests/Support/ValueHandleTest.cpp\ + llvm/unittests/Support/raw_ostream_test.cpp + +llvmunittest_VMCore_CPPFLAGS=$(LLVM_INCLUDES) $(LLVM_DEFS) -I$(top_srcdir)/llvm/utils/unittest/googletest/include +llvmunittest_VMCore_CXXFLAGS=$(LLVM_CXXFLAGS) -fno-exceptions -Wno-variadic-macros +llvmunittest_VMCore_LDADD=libgoogletest.la libllvmtarget.la libllvmipa.la libllvmcore.la libllvmsupport.la libllvmsystem.la +llvmunittest_VMCore_SOURCES=\ + llvm/lib/Analysis/IPA/CallGraphSCCPass.cpp\ + llvm/unittests/VMCore/ConstantsTest.cpp\ + llvm/unittests/VMCore/MetadataTest.cpp\ + llvm/unittests/VMCore/PassManagerTest.cpp + +llvmunittest_JIT_CPPFLAGS=$(LLVM_INCLUDES) $(LLVM_DEFS) -I$(top_srcdir)/llvm/utils/unittest/googletest/include +llvmunittest_JIT_CXXFLAGS=$(LLVM_CXXFLAGS) -fno-exceptions -Wno-variadic-macros +llvmunittest_JIT_LDADD=libgoogletest.la libllvmasmparser.la $(libclamavcxx_la_LIBADD) +llvmunittest_JIT_SOURCES=\ + llvm/unittests/ExecutionEngine/JIT/JITEventListenerTest.cpp\ + llvm/unittests/ExecutionEngine/JIT/JITMemoryManagerTest.cpp\ + llvm/unittests/ExecutionEngine/JIT/JITTest.cpp + +llvmunittest_ExecutionEngine_CPPFLAGS=$(LLVM_INCLUDES) $(LLVM_DEFS) -I$(top_srcdir)/llvm/utils/unittest/googletest/include +llvmunittest_ExecutionEngine_CXXFLAGS=$(LLVM_CXXFLAGS) -fno-exceptions -Wno-variadic-macros +llvmunittest_ExecutionEngine_LDADD=libgoogletest.la libllvminterpreter.la $(libclamavcxx_la_LIBADD) +llvmunittest_ExecutionEngine_SOURCES=\ + llvm/unittests/ExecutionEngine/ExecutionEngineTest.cpp + +count_CPPFLAGS=$(LLVM_INCLUDES) $(LLVM_DEFS) +count_SOURCES=llvm/utils/count/count.c +count_LDADD=libllvmsystem.la +not_CPPFLAGS=$(LLVM_INCLUDES) $(LLVM_DEFS) +not_CXXFLAGS=$(LLVM_CXXFLAGS) +not_SOURCES=llvm/utils/not/not.cpp +not_LDADD=libllvmsystem.la + +FileCheck_CPPFLAGS=$(LLVM_INCLUDES) $(LLVM_DEFS) +FileCheck_CXXFLAGS=$(LLVM_CXXFLAGS) +FileCheck_LDADD=libllvmsupport.la libllvmsystem.la +FileCheck_SOURCES=llvm/utils/FileCheck/FileCheck.cpp + +check_LTLIBRARIES=libllvmbitreader.la libllvmasmprinter.la libllvmbitwriter.la libllvmasmparser.la libgoogletest.la libllvminterpreter.la +check_PROGRAMS=count not lli llc llvm-as llvm-dis llvmunittest_ADT llvmunittest_Support llvmunittest_VMCore llvmunittest_ExecutionEngine llvmunittest_JIT FileCheck +# Disable LLVM make check for now, there are some things to fix first: +# - check python version (2.4 doesn't work, needs 2.5+) +# - run llvm's make check after clamav's was run +# - have a way to run only clamav's make check and not llvm's +#check_SCRIPTS=llvmdejagnu.sh +TESTS_ENVIRONMENT=export GMAKE=@GMAKE@; +TESTS=llvmunittest_ADT llvmunittest_Support llvmunittest_VMCore llvmunittest_ExecutionEngine llvmunittest_JIT +@ifGNUmake@ TESTS+=llvmdejagnu.sh + +libllvmasmprinter_la_CPPFLAGS=$(LLVM_INCLUDES) $(LLVM_DEFS) -I$(top_srcdir)/llvm/lib/Target/X86 \ + -I$(top_srcdir)/llvm/lib/Target/PowerPC -I$(top_srcdir)/llvm/lib/Target/ARM +libllvmasmprinter_la_CXXFLAGS=$(LLVM_CXXFLAGS) -fno-exceptions +libllvmasmprinter_la_SOURCES=\ + llvm/lib/CodeGen/AsmPrinter/OcamlGCPrinter.cpp\ + llvm/lib/CodeGen/ELFCodeEmitter.cpp\ + llvm/lib/CodeGen/ELFWriter.cpp\ + llvm/lib/CodeGen/MachOCodeEmitter.cpp\ + llvm/lib/CodeGen/MachOWriter.cpp + +if BUILD_X86 +libllvmasmprinter_la_SOURCES+=llvm/lib/Target/X86/AsmPrinter/X86AsmPrinter.cpp\ + llvm/lib/Target/X86/AsmPrinter/X86ATTInstPrinter.cpp\ + llvm/lib/Target/X86/AsmPrinter/X86IntelInstPrinter.cpp\ + llvm/lib/Target/X86/AsmPrinter/X86AsmPrinter.cpp\ + llvm/lib/Target/X86/AsmPrinter/X86MCInstLower.cpp\ + llvm/lib/Target/X86/X86COFFMachineModuleInfo.cpp +endif + +if BUILD_PPC +libllvmasmprinter_la_SOURCES+= llvm/lib/Target/PowerPC/AsmPrinter/PPCAsmPrinter.cpp +endif + +if BUILD_ARM +libllvmasmprinter_la_SOURCES+= llvm/lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp \ + llvm/lib/Target/ARM/AsmPrinter/ARMInstPrinter.cpp\ + llvm/lib/Target/ARM/AsmPrinter/ARMMCInstLower.cpp +endif + +lli_CPPFLAGS=$(LLVM_INCLUDES) $(LLVM_DEFS) +lli_CXXFLAGS=$(LLVM_CXXFLAGS) +lli_LDADD=libllvmbitreader.la libllvminterpreter.la $(libclamavcxx_la_LIBADD) +lli_SOURCES=\ + llvm/lib/ExecutionEngine/JIT/OProfileJITEventListener.cpp\ + llvm/tools/lli/lli.cpp + +llc_CPPFLAGS=$(LLVM_INCLUDES) $(LLVM_DEFS) +llc_CXXFLAGS=$(LLVM_CXXFLAGS) +llc_LDADD=libllvmbitreader.la libllvmasmparser.la libllvmasmprinter.la $(libclamavcxx_la_LIBADD) +llc_SOURCES=\ + llvm/lib/MC/MCInstPrinter.cpp\ + llvm/tools/llc/llc.cpp + +llvm_as_CPPFLAGS=$(LLVM_INCLUDES) $(LLVM_DEFS) +llvm_as_CXXFLAGS=$(LLVM_CXXFLAGS) +llvm_as_LDADD=libllvmasmparser.la libllvmbitwriter.la libllvmcore.la libllvmsupport.la libllvmsystem.la +llvm_as_SOURCES=\ + llvm/tools/llvm-as/llvm-as.cpp + +llvm_dis_CPPFLAGS=$(LLVM_INCLUDES) $(LLVM_DEFS) +llvm_dis_CXXFLAGS=$(LLVM_CXXFLAGS) +llvm_dis_LDADD=libllvmasmparser.la libllvmbitreader.la libllvmcore.la libllvmsupport.la libllvmsystem.la +llvm_dis_SOURCES=\ + llvm/tools/llvm-dis/llvm-dis.cpp + +noinst_PROGRAMS = tblgen +#bytecode2llvm.cpp: build-llvm + +build-llvm: + +$(GMAKE) -C llvm OPTIMIZE_OPTION=-O2 libs-only + +build-llvm-for-check: + +$(GMAKE) -C llvm OPTIMIZE_OPTION=-O2 tools-only + +# Don't use make -C here, otherwise there's a racecondition between distclean +# and clean (distclean removes all Makefiles in llvm/) +clean-local: + rm -rf `find llvm/test -name Output -type d -print` + rm -rf llvm/Release llvm/Debug + rm -f *.inc + rm -f llvm/include/llvm/Intrinsics.gen + rm -f llvm/test/site.exp llvm/test/site.bak llvm/test/*.out llvm/test/*.sum llvm/test/*.log + +distclean-local: + rm -f llvm/lib/Makefile llvm/docs/doxygen.cfg llvm/test/Unit/.dir llvm/test/Unit/lit.site.cfg + rm -f llvm/test/Makefile llvm/test/lit.site.cfg llvm/test/Makefile.tests llvm/Makefile llvm/config.status + rm -f llvm/mklib llvm/tools/Makefile llvm/tools/llvmc/llvm-config.in llvm/utils/Makefile + rm -f llvm/Makefile.common llvm/Makefile.config llvm/config.log llvm/unittests/Makefile + rm -f llvm/llvm.spec llvm/include/llvm/Config/AsmPrinters.def llvm/include/llvm/Config/config.h + rm -f llvm/include/llvm/Support/DataTypes.h llvm/include/llvm/Config/Targets.def + rm -f llvm/tools/llvmc/plugins/Base/Base.td llvm/tools/llvm-config/llvm-config.in + rm -f llvm/include/llvm/Config/AsmParsers.def + +check-llvm: build-llvm-for-check + +$(GMAKE) -C llvm check + +$(GMAKE) -C llvm unittests + +CONFIG_STATUS_DEPENDENCIES = $(top_builddir)/llvm/config.status +# config.status needs to be run twice, once without recheck so that it has a +# chance to create configure generated files. +$(top_builddir)/llvm/config.status: llvm/configure + cd llvm; ./config.status --recheck; ./config.status + +# rm configure generated files +dist-hook: + make -C llvm dist-hook + rm -f $(distdir)/llvm/include/llvm/Config/*.h $(distdir)/llvm/include/llvm/Config/*.def $(distdir)/llvm/Makefile.config $(distdir)/llvm/llvm.spec + rm -f $(distdir)/llvm/docs/doxygen.cfg $(distdir)/llvm/tools/llvmc/plugins/Base/Base.td $(distdir)/llvm/tools/llvm-config/llvm-config.in + rm -f $(distdir)/llvm/include/llvm/Intrinsics.gen + rm -f $(distdir)/llvm/include/llvm/Support/DataTypes.h $(distdir)/llvm/config.log $(distdir)/llvm/config.status + diff --git a/libclamav/c++/Makefile.in b/libclamav/c++/Makefile.in new file mode 100644 index 000000000..01078b39c --- /dev/null +++ b/libclamav/c++/Makefile.in @@ -0,0 +1,6684 @@ +# Makefile.in generated by automake 1.11 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, +# Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +# MA 02110-1301, USA. + + +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +@BUILD_X86_TRUE@am__append_1 = libllvmtargetx86.la +@BUILD_X86_TRUE@am__append_2 = libllvmtargetx86.la +@BUILD_PPC_TRUE@am__append_3 = libllvmtargetppc.la +@BUILD_PPC_TRUE@am__append_4 = libllvmtargetppc.la +@BUILD_ARM_TRUE@am__append_5 = libllvmtargetarm.la +@BUILD_ARM_TRUE@am__append_6 = libllvmtargetarm.la +@BUILD_X86_TRUE@am__append_7 = X86GenRegisterInfo.h.inc X86GenRegisterNames.inc X86GenRegisterInfo.inc X86GenInstrNames.inc X86GenInstrInfo.inc\ +@BUILD_X86_TRUE@ X86GenAsmWriter.inc X86GenAsmWriter1.inc X86GenAsmMatcher.inc X86GenDAGISel.inc X86GenFastISel.inc X86GenCallingConv.inc\ +@BUILD_X86_TRUE@ X86GenSubtarget.inc + +@BUILD_PPC_TRUE@am__append_8 = PPCGenInstrNames.inc PPCGenRegisterNames.inc PPCGenAsmWriter.inc PPCGenCodeEmitter.inc PPCGenRegisterInfo.h.inc PPCGenRegisterInfo.inc\ +@BUILD_PPC_TRUE@ PPCGenInstrInfo.inc PPCGenDAGISel.inc PPCGenCallingConv.inc PPCGenSubtarget.inc + +@BUILD_ARM_TRUE@am__append_9 = ARMGenRegisterInfo.h.inc ARMGenRegisterNames.inc ARMGenRegisterInfo.inc ARMGenInstrNames.inc ARMGenInstrInfo.inc ARMGenCodeEmitter.inc\ +@BUILD_ARM_TRUE@ ARMGenAsmWriter.inc ARMGenDAGISel.inc ARMGenCallingConv.inc ARMGenSubtarget.inc + +check_PROGRAMS = count$(EXEEXT) not$(EXEEXT) lli$(EXEEXT) llc$(EXEEXT) \ + llvm-as$(EXEEXT) llvm-dis$(EXEEXT) llvmunittest_ADT$(EXEEXT) \ + llvmunittest_Support$(EXEEXT) llvmunittest_VMCore$(EXEEXT) \ + llvmunittest_ExecutionEngine$(EXEEXT) \ + llvmunittest_JIT$(EXEEXT) FileCheck$(EXEEXT) +TESTS = llvmunittest_ADT$(EXEEXT) llvmunittest_Support$(EXEEXT) \ + llvmunittest_VMCore$(EXEEXT) \ + llvmunittest_ExecutionEngine$(EXEEXT) \ + llvmunittest_JIT$(EXEEXT) +@BUILD_X86_TRUE@am__append_10 = llvm/lib/Target/X86/AsmPrinter/X86AsmPrinter.cpp\ +@BUILD_X86_TRUE@ llvm/lib/Target/X86/AsmPrinter/X86ATTInstPrinter.cpp\ +@BUILD_X86_TRUE@ llvm/lib/Target/X86/AsmPrinter/X86IntelInstPrinter.cpp\ +@BUILD_X86_TRUE@ llvm/lib/Target/X86/AsmPrinter/X86AsmPrinter.cpp\ +@BUILD_X86_TRUE@ llvm/lib/Target/X86/AsmPrinter/X86MCInstLower.cpp\ +@BUILD_X86_TRUE@ llvm/lib/Target/X86/X86COFFMachineModuleInfo.cpp + +@BUILD_PPC_TRUE@am__append_11 = llvm/lib/Target/PowerPC/AsmPrinter/PPCAsmPrinter.cpp +@BUILD_ARM_TRUE@am__append_12 = llvm/lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp \ +@BUILD_ARM_TRUE@ llvm/lib/Target/ARM/AsmPrinter/ARMInstPrinter.cpp\ +@BUILD_ARM_TRUE@ llvm/lib/Target/ARM/AsmPrinter/ARMMCInstLower.cpp + +noinst_PROGRAMS = tblgen$(EXEEXT) +subdir = . +DIST_COMMON = $(am__configure_deps) $(srcdir)/Makefile.am \ + $(srcdir)/Makefile.in $(srcdir)/clamavcxx-config.h.in \ + $(top_srcdir)/configure config/config.guess config/config.sub \ + config/depcomp config/install-sh config/ltmain.sh \ + config/missing +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/check_gnu_make.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ + configure.lineno config.status.lineno +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = clamavcxx-config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +LTLIBRARIES = $(noinst_LTLIBRARIES) +libclamavcxx_la_DEPENDENCIES = $(am__append_1) $(am__append_3) \ + $(am__append_5) libllvmsdag.la libllvmexecutionengine.la \ + libllvmcodegen.la libllvmscalar.la libllvmtransformutils.la \ + libllvmipa.la libllvmtarget.la libllvmmc.la libllvmcore.la \ + libllvmsupport.la libllvmsystem.la +am_libclamavcxx_la_OBJECTS = libclamavcxx_la-bytecode2llvm.lo +libclamavcxx_la_OBJECTS = $(am_libclamavcxx_la_OBJECTS) +AM_V_lt = $(am__v_lt_$(V)) +am__v_lt_ = $(am__v_lt_$(AM_DEFAULT_VERBOSITY)) +am__v_lt_0 = --silent +libclamavcxx_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(AM_CXXFLAGS) $(CXXFLAGS) $(libclamavcxx_la_LDFLAGS) \ + $(LDFLAGS) -o $@ +libgoogletest_la_LIBADD = +am_libgoogletest_la_OBJECTS = libgoogletest_la-gtest-death-test.lo \ + libgoogletest_la-gtest-filepath.lo \ + libgoogletest_la-gtest-port.lo \ + libgoogletest_la-gtest-test-part.lo \ + libgoogletest_la-gtest-typed-test.lo libgoogletest_la-gtest.lo \ + libgoogletest_la-TestMain.lo +libgoogletest_la_OBJECTS = $(am_libgoogletest_la_OBJECTS) +libgoogletest_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(libgoogletest_la_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +libllvmasmparser_la_LIBADD = +am_libllvmasmparser_la_OBJECTS = libllvmasmparser_la-LLLexer.lo \ + libllvmasmparser_la-LLParser.lo libllvmasmparser_la-Parser.lo +libllvmasmparser_la_OBJECTS = $(am_libllvmasmparser_la_OBJECTS) +libllvmasmparser_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(libllvmasmparser_la_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +libllvmasmprinter_la_LIBADD = +am__libllvmasmprinter_la_SOURCES_DIST = \ + llvm/lib/CodeGen/AsmPrinter/OcamlGCPrinter.cpp \ + llvm/lib/CodeGen/ELFCodeEmitter.cpp \ + llvm/lib/CodeGen/ELFWriter.cpp \ + llvm/lib/CodeGen/MachOCodeEmitter.cpp \ + llvm/lib/CodeGen/MachOWriter.cpp \ + llvm/lib/Target/X86/AsmPrinter/X86AsmPrinter.cpp \ + llvm/lib/Target/X86/AsmPrinter/X86ATTInstPrinter.cpp \ + llvm/lib/Target/X86/AsmPrinter/X86IntelInstPrinter.cpp \ + llvm/lib/Target/X86/AsmPrinter/X86MCInstLower.cpp \ + llvm/lib/Target/X86/X86COFFMachineModuleInfo.cpp \ + llvm/lib/Target/PowerPC/AsmPrinter/PPCAsmPrinter.cpp \ + llvm/lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp \ + llvm/lib/Target/ARM/AsmPrinter/ARMInstPrinter.cpp \ + llvm/lib/Target/ARM/AsmPrinter/ARMMCInstLower.cpp +@BUILD_X86_TRUE@am__objects_1 = libllvmasmprinter_la-X86AsmPrinter.lo \ +@BUILD_X86_TRUE@ libllvmasmprinter_la-X86ATTInstPrinter.lo \ +@BUILD_X86_TRUE@ libllvmasmprinter_la-X86IntelInstPrinter.lo \ +@BUILD_X86_TRUE@ libllvmasmprinter_la-X86AsmPrinter.lo \ +@BUILD_X86_TRUE@ libllvmasmprinter_la-X86MCInstLower.lo \ +@BUILD_X86_TRUE@ libllvmasmprinter_la-X86COFFMachineModuleInfo.lo +@BUILD_PPC_TRUE@am__objects_2 = libllvmasmprinter_la-PPCAsmPrinter.lo +@BUILD_ARM_TRUE@am__objects_3 = libllvmasmprinter_la-ARMAsmPrinter.lo \ +@BUILD_ARM_TRUE@ libllvmasmprinter_la-ARMInstPrinter.lo \ +@BUILD_ARM_TRUE@ libllvmasmprinter_la-ARMMCInstLower.lo +am_libllvmasmprinter_la_OBJECTS = \ + libllvmasmprinter_la-OcamlGCPrinter.lo \ + libllvmasmprinter_la-ELFCodeEmitter.lo \ + libllvmasmprinter_la-ELFWriter.lo \ + libllvmasmprinter_la-MachOCodeEmitter.lo \ + libllvmasmprinter_la-MachOWriter.lo $(am__objects_1) \ + $(am__objects_2) $(am__objects_3) +libllvmasmprinter_la_OBJECTS = $(am_libllvmasmprinter_la_OBJECTS) +libllvmasmprinter_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(libllvmasmprinter_la_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +libllvmbitreader_la_LIBADD = +am_libllvmbitreader_la_OBJECTS = libllvmbitreader_la-BitReader.lo \ + libllvmbitreader_la-BitcodeReader.lo \ + libllvmbitreader_la-Deserialize.lo \ + libllvmbitreader_la-DeserializeAPFloat.lo \ + libllvmbitreader_la-DeserializeAPInt.lo +libllvmbitreader_la_OBJECTS = $(am_libllvmbitreader_la_OBJECTS) +libllvmbitreader_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(libllvmbitreader_la_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +libllvmbitwriter_la_LIBADD = +am_libllvmbitwriter_la_OBJECTS = libllvmbitwriter_la-BitWriter.lo \ + libllvmbitwriter_la-BitcodeWriter.lo \ + libllvmbitwriter_la-BitcodeWriterPass.lo \ + libllvmbitwriter_la-Serialize.lo \ + libllvmbitwriter_la-SerializeAPFloat.lo \ + libllvmbitwriter_la-SerializeAPInt.lo \ + libllvmbitwriter_la-ValueEnumerator.lo +libllvmbitwriter_la_OBJECTS = $(am_libllvmbitwriter_la_OBJECTS) +libllvmbitwriter_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(libllvmbitwriter_la_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +libllvmcodegen_la_LIBADD = +am_libllvmcodegen_la_OBJECTS = \ + libllvmcodegen_la-AggressiveAntiDepBreaker.lo \ + libllvmcodegen_la-BranchFolding.lo \ + libllvmcodegen_la-CriticalAntiDepBreaker.lo \ + libllvmcodegen_la-CodePlacementOpt.lo \ + libllvmcodegen_la-DeadMachineInstructionElim.lo \ + libllvmcodegen_la-DwarfEHPrepare.lo \ + libllvmcodegen_la-ELFCodeEmitter.lo \ + libllvmcodegen_la-ELFWriter.lo \ + libllvmcodegen_la-ExactHazardRecognizer.lo \ + libllvmcodegen_la-GCMetadata.lo \ + libllvmcodegen_la-GCMetadataPrinter.lo \ + libllvmcodegen_la-GCStrategy.lo \ + libllvmcodegen_la-IfConversion.lo \ + libllvmcodegen_la-IntrinsicLowering.lo \ + libllvmcodegen_la-LLVMTargetMachine.lo \ + libllvmcodegen_la-LatencyPriorityQueue.lo \ + libllvmcodegen_la-LiveInterval.lo \ + libllvmcodegen_la-LiveIntervalAnalysis.lo \ + libllvmcodegen_la-LiveStackAnalysis.lo \ + libllvmcodegen_la-LiveVariables.lo \ + libllvmcodegen_la-LowerSubregs.lo \ + libllvmcodegen_la-MachineBasicBlock.lo \ + libllvmcodegen_la-MachineDominators.lo \ + libllvmcodegen_la-MachineFunction.lo \ + libllvmcodegen_la-MachineFunctionAnalysis.lo \ + libllvmcodegen_la-MachineFunctionPass.lo \ + libllvmcodegen_la-MachineInstr.lo \ + libllvmcodegen_la-MachineLICM.lo \ + libllvmcodegen_la-MachineLoopInfo.lo \ + libllvmcodegen_la-MachineModuleInfo.lo \ + libllvmcodegen_la-MachineModuleInfoImpls.lo \ + libllvmcodegen_la-MachinePassRegistry.lo \ + libllvmcodegen_la-MachineRegisterInfo.lo \ + libllvmcodegen_la-MachineSink.lo \ + libllvmcodegen_la-MachineVerifier.lo \ + libllvmcodegen_la-ObjectCodeEmitter.lo \ + libllvmcodegen_la-OcamlGC.lo \ + libllvmcodegen_la-PHIElimination.lo \ + libllvmcodegen_la-Passes.lo \ + libllvmcodegen_la-PostRASchedulerList.lo \ + libllvmcodegen_la-PreAllocSplitting.lo \ + libllvmcodegen_la-ProcessImplicitDefs.lo \ + libllvmcodegen_la-PrologEpilogInserter.lo \ + libllvmcodegen_la-PseudoSourceValue.lo \ + libllvmcodegen_la-RegAllocLinearScan.lo \ + libllvmcodegen_la-RegAllocLocal.lo \ + libllvmcodegen_la-RegAllocPBQP.lo \ + libllvmcodegen_la-RegisterCoalescer.lo \ + libllvmcodegen_la-RegisterScavenging.lo \ + libllvmcodegen_la-ScheduleDAG.lo \ + libllvmcodegen_la-ScheduleDAGEmit.lo \ + libllvmcodegen_la-ScheduleDAGInstrs.lo \ + libllvmcodegen_la-ScheduleDAGPrinter.lo \ + libllvmcodegen_la-ShadowStackGC.lo \ + libllvmcodegen_la-ShrinkWrapping.lo \ + libllvmcodegen_la-SimpleRegisterCoalescing.lo \ + libllvmcodegen_la-SjLjEHPrepare.lo \ + libllvmcodegen_la-SlotIndexes.lo libllvmcodegen_la-Spiller.lo \ + libllvmcodegen_la-StackProtector.lo \ + libllvmcodegen_la-StackSlotColoring.lo \ + libllvmcodegen_la-StrongPHIElimination.lo \ + libllvmcodegen_la-TailDuplication.lo \ + libllvmcodegen_la-TargetInstrInfoImpl.lo \ + libllvmcodegen_la-TwoAddressInstructionPass.lo \ + libllvmcodegen_la-UnreachableBlockElim.lo \ + libllvmcodegen_la-VirtRegMap.lo \ + libllvmcodegen_la-VirtRegRewriter.lo +libllvmcodegen_la_OBJECTS = $(am_libllvmcodegen_la_OBJECTS) +libllvmcodegen_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +libllvmcore_la_LIBADD = +am_libllvmcore_la_OBJECTS = libllvmcore_la-AsmWriter.lo \ + libllvmcore_la-Attributes.lo libllvmcore_la-AutoUpgrade.lo \ + libllvmcore_la-BasicBlock.lo libllvmcore_la-ConstantFold.lo \ + libllvmcore_la-Constants.lo libllvmcore_la-Core.lo \ + libllvmcore_la-Dominators.lo libllvmcore_la-Function.lo \ + libllvmcore_la-Globals.lo libllvmcore_la-InlineAsm.lo \ + libllvmcore_la-Instruction.lo libllvmcore_la-Instructions.lo \ + libllvmcore_la-IntrinsicInst.lo libllvmcore_la-LLVMContext.lo \ + libllvmcore_la-LeakDetector.lo libllvmcore_la-Mangler.lo \ + libllvmcore_la-Metadata.lo libllvmcore_la-Module.lo \ + libllvmcore_la-ModuleProvider.lo libllvmcore_la-Pass.lo \ + libllvmcore_la-PassManager.lo \ + libllvmcore_la-PrintModulePass.lo libllvmcore_la-Type.lo \ + libllvmcore_la-TypeSymbolTable.lo libllvmcore_la-Use.lo \ + libllvmcore_la-Value.lo libllvmcore_la-ValueSymbolTable.lo \ + libllvmcore_la-ValueTypes.lo libllvmcore_la-Verifier.lo +libllvmcore_la_OBJECTS = $(am_libllvmcore_la_OBJECTS) +libllvmcore_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(libllvmcore_la_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +libllvmexecutionengine_la_LIBADD = +am_libllvmexecutionengine_la_OBJECTS = \ + libllvmexecutionengine_la-ExecutionEngine.lo \ + libllvmexecutionengine_la-Intercept.lo \ + libllvmexecutionengine_la-JIT.lo \ + libllvmexecutionengine_la-JITDebugRegisterer.lo \ + libllvmexecutionengine_la-JITDwarfEmitter.lo \ + libllvmexecutionengine_la-JITEmitter.lo \ + libllvmexecutionengine_la-JITMemoryManager.lo \ + libllvmexecutionengine_la-TargetSelect.lo +libllvmexecutionengine_la_OBJECTS = \ + $(am_libllvmexecutionengine_la_OBJECTS) +libllvmexecutionengine_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(libllvmexecutionengine_la_CXXFLAGS) $(CXXFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +libllvminterpreter_la_LIBADD = +am_libllvminterpreter_la_OBJECTS = libllvminterpreter_la-Execution.lo \ + libllvminterpreter_la-ExternalFunctions.lo \ + libllvminterpreter_la-Interpreter.lo +libllvminterpreter_la_OBJECTS = $(am_libllvminterpreter_la_OBJECTS) +libllvminterpreter_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(libllvminterpreter_la_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +libllvmipa_la_LIBADD = +am_libllvmipa_la_OBJECTS = libllvmipa_la-AliasAnalysis.lo \ + libllvmipa_la-AliasSetTracker.lo \ + libllvmipa_la-BasicAliasAnalysis.lo \ + libllvmipa_la-CaptureTracking.lo \ + libllvmipa_la-ConstantFolding.lo libllvmipa_la-DebugInfo.lo \ + libllvmipa_la-IVUsers.lo libllvmipa_la-InstructionSimplify.lo \ + libllvmipa_la-LiveValues.lo \ + libllvmipa_la-LoopDependenceAnalysis.lo \ + libllvmipa_la-LoopInfo.lo libllvmipa_la-LoopPass.lo \ + libllvmipa_la-MemoryBuiltins.lo \ + libllvmipa_la-MemoryDependenceAnalysis.lo \ + libllvmipa_la-ProfileInfo.lo libllvmipa_la-ScalarEvolution.lo \ + libllvmipa_la-ScalarEvolutionExpander.lo \ + libllvmipa_la-ValueTracking.lo libllvmipa_la-CallGraph.lo +libllvmipa_la_OBJECTS = $(am_libllvmipa_la_OBJECTS) +libllvmipa_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(libllvmipa_la_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \ + -o $@ +libllvmmc_la_LIBADD = +am_libllvmmc_la_OBJECTS = libllvmmc_la-MCAsmInfo.lo \ + libllvmmc_la-MCAsmInfoCOFF.lo libllvmmc_la-MCAsmInfoDarwin.lo \ + libllvmmc_la-MCAsmLexer.lo libllvmmc_la-MCAsmParser.lo \ + libllvmmc_la-MCAsmStreamer.lo libllvmmc_la-MCAssembler.lo \ + libllvmmc_la-MCCodeEmitter.lo libllvmmc_la-MCContext.lo \ + libllvmmc_la-MCExpr.lo libllvmmc_la-MCInst.lo \ + libllvmmc_la-MCMachOStreamer.lo libllvmmc_la-MCNullStreamer.lo \ + libllvmmc_la-MCSection.lo libllvmmc_la-MCSectionELF.lo \ + libllvmmc_la-MCSectionMachO.lo libllvmmc_la-MCStreamer.lo \ + libllvmmc_la-MCSymbol.lo libllvmmc_la-MCValue.lo \ + libllvmmc_la-TargetAsmParser.lo +libllvmmc_la_OBJECTS = $(am_libllvmmc_la_OBJECTS) +libllvmmc_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(libllvmmc_la_CXXFLAGS) \ + $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +libllvmscalar_la_LIBADD = +am_libllvmscalar_la_OBJECTS = libllvmscalar_la-CodeGenPrepare.lo \ + libllvmscalar_la-DCE.lo libllvmscalar_la-GEPSplitter.lo \ + libllvmscalar_la-GVN.lo libllvmscalar_la-LoopStrengthReduce.lo \ + libllvmscalar_la-ConstantProp.lo \ + libllvmscalar_la-SimplifyCFGPass.lo +libllvmscalar_la_OBJECTS = $(am_libllvmscalar_la_OBJECTS) +libllvmscalar_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(libllvmscalar_la_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +libllvmsdag_la_LIBADD = +am_libllvmsdag_la_OBJECTS = libllvmsdag_la-CallingConvLower.lo \ + libllvmsdag_la-DAGCombiner.lo libllvmsdag_la-FastISel.lo \ + libllvmsdag_la-FunctionLoweringInfo.lo \ + libllvmsdag_la-InstrEmitter.lo libllvmsdag_la-LegalizeDAG.lo \ + libllvmsdag_la-LegalizeFloatTypes.lo \ + libllvmsdag_la-LegalizeIntegerTypes.lo \ + libllvmsdag_la-LegalizeTypes.lo \ + libllvmsdag_la-LegalizeTypesGeneric.lo \ + libllvmsdag_la-LegalizeVectorOps.lo \ + libllvmsdag_la-LegalizeVectorTypes.lo \ + libllvmsdag_la-ScheduleDAGFast.lo \ + libllvmsdag_la-ScheduleDAGList.lo \ + libllvmsdag_la-ScheduleDAGRRList.lo \ + libllvmsdag_la-ScheduleDAGSDNodes.lo \ + libllvmsdag_la-SelectionDAG.lo \ + libllvmsdag_la-SelectionDAGBuilder.lo \ + libllvmsdag_la-SelectionDAGISel.lo \ + libllvmsdag_la-SelectionDAGPrinter.lo \ + libllvmsdag_la-TargetLowering.lo libllvmsdag_la-DwarfWriter.lo \ + libllvmsdag_la-DwarfDebug.lo libllvmsdag_la-DwarfException.lo \ + libllvmsdag_la-DwarfLabel.lo libllvmsdag_la-DwarfPrinter.lo \ + libllvmsdag_la-DIE.lo libllvmsdag_la-AsmPrinter.lo +libllvmsdag_la_OBJECTS = $(am_libllvmsdag_la_OBJECTS) +libllvmsdag_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(libllvmsdag_la_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +libllvmsupport_la_LIBADD = +am_libllvmsupport_la_OBJECTS = libllvmsupport_la-APFloat.lo \ + libllvmsupport_la-APInt.lo libllvmsupport_la-APSInt.lo \ + libllvmsupport_la-Allocator.lo \ + libllvmsupport_la-CommandLine.lo \ + libllvmsupport_la-ConstantRange.lo libllvmsupport_la-Debug.lo \ + libllvmsupport_la-Dwarf.lo libllvmsupport_la-ErrorHandling.lo \ + libllvmsupport_la-FileUtilities.lo \ + libllvmsupport_la-FoldingSet.lo \ + libllvmsupport_la-FormattedStream.lo \ + libllvmsupport_la-GraphWriter.lo libllvmsupport_la-IsInf.lo \ + libllvmsupport_la-IsNAN.lo libllvmsupport_la-ManagedStatic.lo \ + libllvmsupport_la-MemoryBuffer.lo \ + libllvmsupport_la-PluginLoader.lo \ + libllvmsupport_la-PrettyStackTrace.lo \ + libllvmsupport_la-SlowOperationInformer.lo \ + libllvmsupport_la-SmallPtrSet.lo \ + libllvmsupport_la-SourceMgr.lo libllvmsupport_la-Statistic.lo \ + libllvmsupport_la-StringExtras.lo \ + libllvmsupport_la-StringMap.lo libllvmsupport_la-StringPool.lo \ + libllvmsupport_la-StringRef.lo \ + libllvmsupport_la-SystemUtils.lo \ + libllvmsupport_la-TargetRegistry.lo libllvmsupport_la-Timer.lo \ + libllvmsupport_la-Triple.lo libllvmsupport_la-Twine.lo \ + libllvmsupport_la-raw_os_ostream.lo \ + libllvmsupport_la-raw_ostream.lo libllvmsupport_la-Regex.lo \ + libllvmsupport_la-regcomp.lo libllvmsupport_la-regerror.lo \ + libllvmsupport_la-regexec.lo libllvmsupport_la-regfree.lo \ + libllvmsupport_la-regstrlcpy.lo +libllvmsupport_la_OBJECTS = $(am_libllvmsupport_la_OBJECTS) +libllvmsupport_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(libllvmsupport_la_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +libllvmsystem_la_DEPENDENCIES = +am_libllvmsystem_la_OBJECTS = libllvmsystem_la-Alarm.lo \ + libllvmsystem_la-Atomic.lo libllvmsystem_la-Disassembler.lo \ + libllvmsystem_la-DynamicLibrary.lo libllvmsystem_la-Errno.lo \ + libllvmsystem_la-Host.lo libllvmsystem_la-IncludeFile.lo \ + libllvmsystem_la-Memory.lo libllvmsystem_la-Mutex.lo \ + libllvmsystem_la-Path.lo libllvmsystem_la-Process.lo \ + libllvmsystem_la-Program.lo libllvmsystem_la-RWMutex.lo \ + libllvmsystem_la-Signals.lo libllvmsystem_la-ThreadLocal.lo \ + libllvmsystem_la-Threading.lo libllvmsystem_la-TimeValue.lo +libllvmsystem_la_OBJECTS = $(am_libllvmsystem_la_OBJECTS) +libllvmsystem_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(libllvmsystem_la_CXXFLAGS) $(CXXFLAGS) \ + $(libllvmsystem_la_LDFLAGS) $(LDFLAGS) -o $@ +libllvmtarget_la_LIBADD = +am_libllvmtarget_la_OBJECTS = libllvmtarget_la-SubtargetFeature.lo \ + libllvmtarget_la-Target.lo libllvmtarget_la-TargetData.lo \ + libllvmtarget_la-TargetELFWriterInfo.lo \ + libllvmtarget_la-TargetFrameInfo.lo \ + libllvmtarget_la-TargetInstrInfo.lo \ + libllvmtarget_la-TargetIntrinsicInfo.lo \ + libllvmtarget_la-TargetLoweringObjectFile.lo \ + libllvmtarget_la-TargetMachOWriterInfo.lo \ + libllvmtarget_la-TargetMachine.lo \ + libllvmtarget_la-TargetRegisterInfo.lo \ + libllvmtarget_la-TargetSubtarget.lo +libllvmtarget_la_OBJECTS = $(am_libllvmtarget_la_OBJECTS) +libllvmtarget_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(libllvmtarget_la_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +libllvmtargetarm_la_LIBADD = +am__libllvmtargetarm_la_SOURCES_DIST = \ + llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp \ + llvm/lib/Target/ARM/ARMBaseRegisterInfo.cpp \ + llvm/lib/Target/ARM/ARMCodeEmitter.cpp \ + llvm/lib/Target/ARM/ARMConstantIslandPass.cpp \ + llvm/lib/Target/ARM/ARMConstantPoolValue.cpp \ + llvm/lib/Target/ARM/ARMExpandPseudoInsts.cpp \ + llvm/lib/Target/ARM/ARMInstrInfo.cpp \ + llvm/lib/Target/ARM/ARMISelDAGToDAG.cpp \ + llvm/lib/Target/ARM/ARMISelLowering.cpp \ + llvm/lib/Target/ARM/ARMJITInfo.cpp \ + llvm/lib/Target/ARM/ARMLoadStoreOptimizer.cpp \ + llvm/lib/Target/ARM/ARMMCAsmInfo.cpp \ + llvm/lib/Target/ARM/ARMRegisterInfo.cpp \ + llvm/lib/Target/ARM/ARMSubtarget.cpp \ + llvm/lib/Target/ARM/ARMTargetMachine.cpp \ + llvm/lib/Target/ARM/NEONMoveFix.cpp \ + llvm/lib/Target/ARM/NEONPreAllocPass.cpp \ + llvm/lib/Target/ARM/Thumb1InstrInfo.cpp \ + llvm/lib/Target/ARM/Thumb1RegisterInfo.cpp \ + llvm/lib/Target/ARM/Thumb2ITBlockPass.cpp \ + llvm/lib/Target/ARM/Thumb2InstrInfo.cpp \ + llvm/lib/Target/ARM/Thumb2RegisterInfo.cpp \ + llvm/lib/Target/ARM/Thumb2SizeReduction.cpp \ + llvm/lib/Target/ARM/TargetInfo/ARMTargetInfo.cpp +@BUILD_ARM_TRUE@am_libllvmtargetarm_la_OBJECTS = \ +@BUILD_ARM_TRUE@ libllvmtargetarm_la-ARMBaseInstrInfo.lo \ +@BUILD_ARM_TRUE@ libllvmtargetarm_la-ARMBaseRegisterInfo.lo \ +@BUILD_ARM_TRUE@ libllvmtargetarm_la-ARMCodeEmitter.lo \ +@BUILD_ARM_TRUE@ libllvmtargetarm_la-ARMConstantIslandPass.lo \ +@BUILD_ARM_TRUE@ libllvmtargetarm_la-ARMConstantPoolValue.lo \ +@BUILD_ARM_TRUE@ libllvmtargetarm_la-ARMExpandPseudoInsts.lo \ +@BUILD_ARM_TRUE@ libllvmtargetarm_la-ARMInstrInfo.lo \ +@BUILD_ARM_TRUE@ libllvmtargetarm_la-ARMISelDAGToDAG.lo \ +@BUILD_ARM_TRUE@ libllvmtargetarm_la-ARMISelLowering.lo \ +@BUILD_ARM_TRUE@ libllvmtargetarm_la-ARMJITInfo.lo \ +@BUILD_ARM_TRUE@ libllvmtargetarm_la-ARMLoadStoreOptimizer.lo \ +@BUILD_ARM_TRUE@ libllvmtargetarm_la-ARMMCAsmInfo.lo \ +@BUILD_ARM_TRUE@ libllvmtargetarm_la-ARMRegisterInfo.lo \ +@BUILD_ARM_TRUE@ libllvmtargetarm_la-ARMSubtarget.lo \ +@BUILD_ARM_TRUE@ libllvmtargetarm_la-ARMTargetMachine.lo \ +@BUILD_ARM_TRUE@ libllvmtargetarm_la-NEONMoveFix.lo \ +@BUILD_ARM_TRUE@ libllvmtargetarm_la-NEONPreAllocPass.lo \ +@BUILD_ARM_TRUE@ libllvmtargetarm_la-Thumb1InstrInfo.lo \ +@BUILD_ARM_TRUE@ libllvmtargetarm_la-Thumb1RegisterInfo.lo \ +@BUILD_ARM_TRUE@ libllvmtargetarm_la-Thumb2ITBlockPass.lo \ +@BUILD_ARM_TRUE@ libllvmtargetarm_la-Thumb2InstrInfo.lo \ +@BUILD_ARM_TRUE@ libllvmtargetarm_la-Thumb2RegisterInfo.lo \ +@BUILD_ARM_TRUE@ libllvmtargetarm_la-Thumb2SizeReduction.lo \ +@BUILD_ARM_TRUE@ libllvmtargetarm_la-ARMTargetInfo.lo +libllvmtargetarm_la_OBJECTS = $(am_libllvmtargetarm_la_OBJECTS) +libllvmtargetarm_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(libllvmtargetarm_la_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +@BUILD_ARM_TRUE@am_libllvmtargetarm_la_rpath = +libllvmtargetppc_la_LIBADD = +am__libllvmtargetppc_la_SOURCES_DIST = \ + llvm/lib/Target/PowerPC/PPCBranchSelector.cpp \ + llvm/lib/Target/PowerPC/PPCCodeEmitter.cpp \ + llvm/lib/Target/PowerPC/PPCHazardRecognizers.cpp \ + llvm/lib/Target/PowerPC/PPCInstrInfo.cpp \ + llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp \ + llvm/lib/Target/PowerPC/PPCISelLowering.cpp \ + llvm/lib/Target/PowerPC/PPCJITInfo.cpp \ + llvm/lib/Target/PowerPC/PPCMachOWriterInfo.cpp \ + llvm/lib/Target/PowerPC/PPCMCAsmInfo.cpp \ + llvm/lib/Target/PowerPC/PPCPredicates.cpp \ + llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp \ + llvm/lib/Target/PowerPC/PPCSubtarget.cpp \ + llvm/lib/Target/PowerPC/PPCTargetMachine.cpp \ + llvm/lib/Target/PowerPC/TargetInfo/PowerPCTargetInfo.cpp +@BUILD_PPC_TRUE@am_libllvmtargetppc_la_OBJECTS = \ +@BUILD_PPC_TRUE@ libllvmtargetppc_la-PPCBranchSelector.lo \ +@BUILD_PPC_TRUE@ libllvmtargetppc_la-PPCCodeEmitter.lo \ +@BUILD_PPC_TRUE@ libllvmtargetppc_la-PPCHazardRecognizers.lo \ +@BUILD_PPC_TRUE@ libllvmtargetppc_la-PPCInstrInfo.lo \ +@BUILD_PPC_TRUE@ libllvmtargetppc_la-PPCISelDAGToDAG.lo \ +@BUILD_PPC_TRUE@ libllvmtargetppc_la-PPCISelLowering.lo \ +@BUILD_PPC_TRUE@ libllvmtargetppc_la-PPCJITInfo.lo \ +@BUILD_PPC_TRUE@ libllvmtargetppc_la-PPCMachOWriterInfo.lo \ +@BUILD_PPC_TRUE@ libllvmtargetppc_la-PPCMCAsmInfo.lo \ +@BUILD_PPC_TRUE@ libllvmtargetppc_la-PPCPredicates.lo \ +@BUILD_PPC_TRUE@ libllvmtargetppc_la-PPCRegisterInfo.lo \ +@BUILD_PPC_TRUE@ libllvmtargetppc_la-PPCSubtarget.lo \ +@BUILD_PPC_TRUE@ libllvmtargetppc_la-PPCTargetMachine.lo \ +@BUILD_PPC_TRUE@ libllvmtargetppc_la-PowerPCTargetInfo.lo +libllvmtargetppc_la_OBJECTS = $(am_libllvmtargetppc_la_OBJECTS) +libllvmtargetppc_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(libllvmtargetppc_la_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +@BUILD_PPC_TRUE@am_libllvmtargetppc_la_rpath = +libllvmtargetx86_la_LIBADD = +am__libllvmtargetx86_la_SOURCES_DIST = \ + llvm/lib/Target/X86/X86CodeEmitter.cpp \ + llvm/lib/Target/X86/X86ELFWriterInfo.cpp \ + llvm/lib/Target/X86/X86FloatingPoint.cpp \ + llvm/lib/Target/X86/X86FloatingPointRegKill.cpp \ + llvm/lib/Target/X86/X86ISelDAGToDAG.cpp \ + llvm/lib/Target/X86/X86ISelLowering.cpp \ + llvm/lib/Target/X86/X86InstrInfo.cpp \ + llvm/lib/Target/X86/X86JITInfo.cpp \ + llvm/lib/Target/X86/X86MCAsmInfo.cpp \ + llvm/lib/Target/X86/X86RegisterInfo.cpp \ + llvm/lib/Target/X86/X86Subtarget.cpp \ + llvm/lib/Target/X86/X86TargetMachine.cpp \ + llvm/lib/Target/X86/X86FastISel.cpp \ + llvm/lib/Target/X86/X86TargetObjectFile.cpp \ + llvm/lib/Target/X86/TargetInfo/X86TargetInfo.cpp +@BUILD_X86_TRUE@am_libllvmtargetx86_la_OBJECTS = \ +@BUILD_X86_TRUE@ libllvmtargetx86_la-X86CodeEmitter.lo \ +@BUILD_X86_TRUE@ libllvmtargetx86_la-X86ELFWriterInfo.lo \ +@BUILD_X86_TRUE@ libllvmtargetx86_la-X86FloatingPoint.lo \ +@BUILD_X86_TRUE@ libllvmtargetx86_la-X86FloatingPointRegKill.lo \ +@BUILD_X86_TRUE@ libllvmtargetx86_la-X86ISelDAGToDAG.lo \ +@BUILD_X86_TRUE@ libllvmtargetx86_la-X86ISelLowering.lo \ +@BUILD_X86_TRUE@ libllvmtargetx86_la-X86InstrInfo.lo \ +@BUILD_X86_TRUE@ libllvmtargetx86_la-X86JITInfo.lo \ +@BUILD_X86_TRUE@ libllvmtargetx86_la-X86MCAsmInfo.lo \ +@BUILD_X86_TRUE@ libllvmtargetx86_la-X86RegisterInfo.lo \ +@BUILD_X86_TRUE@ libllvmtargetx86_la-X86Subtarget.lo \ +@BUILD_X86_TRUE@ libllvmtargetx86_la-X86TargetMachine.lo \ +@BUILD_X86_TRUE@ libllvmtargetx86_la-X86FastISel.lo \ +@BUILD_X86_TRUE@ libllvmtargetx86_la-X86TargetObjectFile.lo \ +@BUILD_X86_TRUE@ libllvmtargetx86_la-X86TargetInfo.lo +libllvmtargetx86_la_OBJECTS = $(am_libllvmtargetx86_la_OBJECTS) +libllvmtargetx86_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(libllvmtargetx86_la_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +@BUILD_X86_TRUE@am_libllvmtargetx86_la_rpath = +libllvmtransformutils_la_LIBADD = +am_libllvmtransformutils_la_OBJECTS = \ + libllvmtransformutils_la-AddrModeMatcher.lo \ + libllvmtransformutils_la-BasicBlockUtils.lo \ + libllvmtransformutils_la-BreakCriticalEdges.lo \ + libllvmtransformutils_la-DemoteRegToStack.lo \ + libllvmtransformutils_la-LCSSA.lo \ + libllvmtransformutils_la-Local.lo \ + libllvmtransformutils_la-LoopSimplify.lo \ + libllvmtransformutils_la-LowerInvoke.lo \ + libllvmtransformutils_la-LowerSwitch.lo \ + libllvmtransformutils_la-Mem2Reg.lo \ + libllvmtransformutils_la-PromoteMemoryToRegister.lo \ + libllvmtransformutils_la-SimplifyCFG.lo \ + libllvmtransformutils_la-SSAUpdater.lo \ + libllvmtransformutils_la-UnifyFunctionExitNodes.lo +libllvmtransformutils_la_OBJECTS = \ + $(am_libllvmtransformutils_la_OBJECTS) +libllvmtransformutils_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(libllvmtransformutils_la_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +PROGRAMS = $(noinst_PROGRAMS) +am_FileCheck_OBJECTS = FileCheck-FileCheck.$(OBJEXT) +FileCheck_OBJECTS = $(am_FileCheck_OBJECTS) +FileCheck_DEPENDENCIES = libllvmsupport.la libllvmsystem.la +FileCheck_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(FileCheck_CXXFLAGS) \ + $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +am_count_OBJECTS = count-count.$(OBJEXT) +count_OBJECTS = $(am_count_OBJECTS) +count_DEPENDENCIES = libllvmsystem.la +am_llc_OBJECTS = llc-MCInstPrinter.$(OBJEXT) llc-llc.$(OBJEXT) +llc_OBJECTS = $(am_llc_OBJECTS) +llc_DEPENDENCIES = libllvmbitreader.la libllvmasmparser.la \ + libllvmasmprinter.la $(libclamavcxx_la_LIBADD) +llc_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(llc_CXXFLAGS) \ + $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +am_lli_OBJECTS = lli-OProfileJITEventListener.$(OBJEXT) \ + lli-lli.$(OBJEXT) +lli_OBJECTS = $(am_lli_OBJECTS) +lli_DEPENDENCIES = libllvmbitreader.la libllvminterpreter.la \ + $(libclamavcxx_la_LIBADD) +lli_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(lli_CXXFLAGS) \ + $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +am_llvm_as_OBJECTS = llvm_as-llvm-as.$(OBJEXT) +llvm_as_OBJECTS = $(am_llvm_as_OBJECTS) +llvm_as_DEPENDENCIES = libllvmasmparser.la libllvmbitwriter.la \ + libllvmcore.la libllvmsupport.la libllvmsystem.la +llvm_as_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(llvm_as_CXXFLAGS) \ + $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +am_llvm_dis_OBJECTS = llvm_dis-llvm-dis.$(OBJEXT) +llvm_dis_OBJECTS = $(am_llvm_dis_OBJECTS) +llvm_dis_DEPENDENCIES = libllvmasmparser.la libllvmbitreader.la \ + libllvmcore.la libllvmsupport.la libllvmsystem.la +llvm_dis_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(llvm_dis_CXXFLAGS) \ + $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +am_llvmunittest_ADT_OBJECTS = llvmunittest_ADT-APFloatTest.$(OBJEXT) \ + llvmunittest_ADT-APIntTest.$(OBJEXT) \ + llvmunittest_ADT-DenseMapTest.$(OBJEXT) \ + llvmunittest_ADT-DenseSetTest.$(OBJEXT) \ + llvmunittest_ADT-ImmutableSetTest.$(OBJEXT) \ + llvmunittest_ADT-SmallStringTest.$(OBJEXT) \ + llvmunittest_ADT-SmallVectorTest.$(OBJEXT) \ + llvmunittest_ADT-SparseBitVectorTest.$(OBJEXT) \ + llvmunittest_ADT-StringMapTest.$(OBJEXT) \ + llvmunittest_ADT-StringRefTest.$(OBJEXT) \ + llvmunittest_ADT-TripleTest.$(OBJEXT) \ + llvmunittest_ADT-TwineTest.$(OBJEXT) +llvmunittest_ADT_OBJECTS = $(am_llvmunittest_ADT_OBJECTS) +llvmunittest_ADT_DEPENDENCIES = libgoogletest.la libllvmcore.la \ + libllvmsupport.la libllvmsystem.la +llvmunittest_ADT_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(llvmunittest_ADT_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +am_llvmunittest_ExecutionEngine_OBJECTS = \ + llvmunittest_ExecutionEngine-ExecutionEngineTest.$(OBJEXT) +llvmunittest_ExecutionEngine_OBJECTS = \ + $(am_llvmunittest_ExecutionEngine_OBJECTS) +llvmunittest_ExecutionEngine_DEPENDENCIES = libgoogletest.la \ + libllvminterpreter.la $(libclamavcxx_la_LIBADD) +llvmunittest_ExecutionEngine_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(llvmunittest_ExecutionEngine_CXXFLAGS) $(CXXFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +am_llvmunittest_JIT_OBJECTS = \ + llvmunittest_JIT-JITEventListenerTest.$(OBJEXT) \ + llvmunittest_JIT-JITMemoryManagerTest.$(OBJEXT) \ + llvmunittest_JIT-JITTest.$(OBJEXT) +llvmunittest_JIT_OBJECTS = $(am_llvmunittest_JIT_OBJECTS) +llvmunittest_JIT_DEPENDENCIES = libgoogletest.la libllvmasmparser.la \ + $(libclamavcxx_la_LIBADD) +llvmunittest_JIT_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(llvmunittest_JIT_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +am_llvmunittest_Support_OBJECTS = \ + llvmunittest_Support-AllocatorTest.$(OBJEXT) \ + llvmunittest_Support-ConstantRangeTest.$(OBJEXT) \ + llvmunittest_Support-MathExtrasTest.$(OBJEXT) \ + llvmunittest_Support-RegexTest.$(OBJEXT) \ + llvmunittest_Support-TypeBuilderTest.$(OBJEXT) \ + llvmunittest_Support-ValueHandleTest.$(OBJEXT) \ + llvmunittest_Support-raw_ostream_test.$(OBJEXT) +llvmunittest_Support_OBJECTS = $(am_llvmunittest_Support_OBJECTS) +llvmunittest_Support_DEPENDENCIES = libgoogletest.la libllvmcore.la \ + libllvmsupport.la libllvmsystem.la +llvmunittest_Support_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(llvmunittest_Support_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +am_llvmunittest_VMCore_OBJECTS = \ + llvmunittest_VMCore-CallGraphSCCPass.$(OBJEXT) \ + llvmunittest_VMCore-ConstantsTest.$(OBJEXT) \ + llvmunittest_VMCore-MetadataTest.$(OBJEXT) \ + llvmunittest_VMCore-PassManagerTest.$(OBJEXT) +llvmunittest_VMCore_OBJECTS = $(am_llvmunittest_VMCore_OBJECTS) +llvmunittest_VMCore_DEPENDENCIES = libgoogletest.la libllvmtarget.la \ + libllvmipa.la libllvmcore.la libllvmsupport.la \ + libllvmsystem.la +llvmunittest_VMCore_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(llvmunittest_VMCore_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +am_not_OBJECTS = not-not.$(OBJEXT) +not_OBJECTS = $(am_not_OBJECTS) +not_DEPENDENCIES = libllvmsystem.la +not_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(not_CXXFLAGS) \ + $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +am_tblgen_OBJECTS = tblgen-AsmMatcherEmitter.$(OBJEXT) \ + tblgen-AsmWriterEmitter.$(OBJEXT) \ + tblgen-CallingConvEmitter.$(OBJEXT) \ + tblgen-ClangDiagnosticsEmitter.$(OBJEXT) \ + tblgen-CodeEmitterGen.$(OBJEXT) \ + tblgen-CodeGenDAGPatterns.$(OBJEXT) \ + tblgen-CodeGenInstruction.$(OBJEXT) \ + tblgen-CodeGenTarget.$(OBJEXT) \ + tblgen-DisassemblerEmitter.$(OBJEXT) \ + tblgen-DAGISelEmitter.$(OBJEXT) \ + tblgen-FastISelEmitter.$(OBJEXT) \ + tblgen-InstrEnumEmitter.$(OBJEXT) \ + tblgen-InstrInfoEmitter.$(OBJEXT) \ + tblgen-IntrinsicEmitter.$(OBJEXT) \ + tblgen-LLVMCConfigurationEmitter.$(OBJEXT) \ + tblgen-OptParserEmitter.$(OBJEXT) tblgen-Record.$(OBJEXT) \ + tblgen-RegisterInfoEmitter.$(OBJEXT) \ + tblgen-SubtargetEmitter.$(OBJEXT) tblgen-TGLexer.$(OBJEXT) \ + tblgen-TGParser.$(OBJEXT) tblgen-TGValueTypes.$(OBJEXT) \ + tblgen-TableGen.$(OBJEXT) tblgen-TableGenBackend.$(OBJEXT) +tblgen_OBJECTS = $(am_tblgen_OBJECTS) +tblgen_DEPENDENCIES = libllvmsupport.la libllvmsystem.la +tblgen_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(tblgen_CXXFLAGS) \ + $(CXXFLAGS) $(tblgen_LDFLAGS) $(LDFLAGS) -o $@ +DEFAULT_INCLUDES = -I.@am__isrc@ +depcomp = $(SHELL) $(top_srcdir)/config/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_$(V)) +am__v_CC_ = $(am__v_CC_$(AM_DEFAULT_VERBOSITY)) +am__v_CC_0 = @echo " CC " $@; +AM_V_at = $(am__v_at_$(V)) +am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY)) +am__v_at_0 = @ +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_$(V)) +am__v_CCLD_ = $(am__v_CCLD_$(AM_DEFAULT_VERBOSITY)) +am__v_CCLD_0 = @echo " CCLD " $@; +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CXXFLAGS) $(CXXFLAGS) +AM_V_CXX = $(am__v_CXX_$(V)) +am__v_CXX_ = $(am__v_CXX_$(AM_DEFAULT_VERBOSITY)) +am__v_CXX_0 = @echo " CXX " $@; +CXXLD = $(CXX) +CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ + $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CXXLD = $(am__v_CXXLD_$(V)) +am__v_CXXLD_ = $(am__v_CXXLD_$(AM_DEFAULT_VERBOSITY)) +am__v_CXXLD_0 = @echo " CXXLD " $@; +AM_V_GEN = $(am__v_GEN_$(V)) +am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY)) +am__v_GEN_0 = @echo " GEN " $@; +SOURCES = $(libclamavcxx_la_SOURCES) $(libgoogletest_la_SOURCES) \ + $(libllvmasmparser_la_SOURCES) $(libllvmasmprinter_la_SOURCES) \ + $(libllvmbitreader_la_SOURCES) $(libllvmbitwriter_la_SOURCES) \ + $(libllvmcodegen_la_SOURCES) $(libllvmcore_la_SOURCES) \ + $(libllvmexecutionengine_la_SOURCES) \ + $(libllvminterpreter_la_SOURCES) $(libllvmipa_la_SOURCES) \ + $(libllvmmc_la_SOURCES) $(libllvmscalar_la_SOURCES) \ + $(libllvmsdag_la_SOURCES) $(libllvmsupport_la_SOURCES) \ + $(libllvmsystem_la_SOURCES) $(libllvmtarget_la_SOURCES) \ + $(libllvmtargetarm_la_SOURCES) $(libllvmtargetppc_la_SOURCES) \ + $(libllvmtargetx86_la_SOURCES) \ + $(libllvmtransformutils_la_SOURCES) $(FileCheck_SOURCES) \ + $(count_SOURCES) $(llc_SOURCES) $(lli_SOURCES) \ + $(llvm_as_SOURCES) $(llvm_dis_SOURCES) \ + $(llvmunittest_ADT_SOURCES) \ + $(llvmunittest_ExecutionEngine_SOURCES) \ + $(llvmunittest_JIT_SOURCES) $(llvmunittest_Support_SOURCES) \ + $(llvmunittest_VMCore_SOURCES) $(not_SOURCES) \ + $(tblgen_SOURCES) +DIST_SOURCES = $(libclamavcxx_la_SOURCES) $(libgoogletest_la_SOURCES) \ + $(libllvmasmparser_la_SOURCES) \ + $(am__libllvmasmprinter_la_SOURCES_DIST) \ + $(libllvmbitreader_la_SOURCES) $(libllvmbitwriter_la_SOURCES) \ + $(libllvmcodegen_la_SOURCES) $(libllvmcore_la_SOURCES) \ + $(libllvmexecutionengine_la_SOURCES) \ + $(libllvminterpreter_la_SOURCES) $(libllvmipa_la_SOURCES) \ + $(libllvmmc_la_SOURCES) $(libllvmscalar_la_SOURCES) \ + $(libllvmsdag_la_SOURCES) $(libllvmsupport_la_SOURCES) \ + $(libllvmsystem_la_SOURCES) $(libllvmtarget_la_SOURCES) \ + $(am__libllvmtargetarm_la_SOURCES_DIST) \ + $(am__libllvmtargetppc_la_SOURCES_DIST) \ + $(am__libllvmtargetx86_la_SOURCES_DIST) \ + $(libllvmtransformutils_la_SOURCES) $(FileCheck_SOURCES) \ + $(count_SOURCES) $(llc_SOURCES) $(lli_SOURCES) \ + $(llvm_as_SOURCES) $(llvm_dis_SOURCES) \ + $(llvmunittest_ADT_SOURCES) \ + $(llvmunittest_ExecutionEngine_SOURCES) \ + $(llvmunittest_JIT_SOURCES) $(llvmunittest_Support_SOURCES) \ + $(llvmunittest_VMCore_SOURCES) $(not_SOURCES) \ + $(tblgen_SOURCES) +ETAGS = etags +CTAGS = ctags +# If stdout is a non-dumb tty, use colors. If test -t is not supported, +# then this fails; a conservative approach. Of course do not redirect +# stdout here, just stderr. +am__tty_colors = \ +red=; grn=; lgn=; blu=; std=; \ +test "X$(AM_COLOR_TESTS)" != Xno \ +&& test "X$$TERM" != Xdumb \ +&& { test "X$(AM_COLOR_TESTS)" = Xalways || test -t 1 2>/dev/null; } \ +&& { \ + red=''; \ + grn=''; \ + lgn=''; \ + blu=''; \ + std=''; \ +} +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +distdir = $(PACKAGE)-$(VERSION) +top_distdir = $(distdir) +am__remove_distdir = \ + { test ! -d "$(distdir)" \ + || { find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \ + && rm -fr "$(distdir)"; }; } +DIST_ARCHIVES = $(distdir).tar.gz +GZIP_ENV = --best +distuninstallcheck_listfiles = find . -type f -print +distcleancheck_listfiles = find . -type f -print +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GMAKE = @GMAKE@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +ifGNUmake = @ifGNUmake@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +lt_ECHO = @lt_ECHO@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +subdirs = @subdirs@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +AM_CPPFLAGS = -I$(top_srcdir)/../.. -I$(top_srcdir)/.. -I$(top_builddir)/../../ +ACLOCAL_AMFLAGS = -I m4 +@DEBUG_BUILD_FALSE@LLVM_CONFIG = llvm/Release/bin/llvm-config +@DEBUG_BUILD_TRUE@LLVM_CONFIG = llvm/Debug/bin/llvm-config + +#$(LLVM_CONFIG): build-llvm +# we know this will be built with GNU make, so its safe to use GNU make specific +# $(shell ...) +#LLVM_DEPS=$(shell $(LLVM_CONFIG) --libfiles jit nativecodegen) +#libclamavcxx_la_CPPFLAGS = $(AM_CPPFLAGS) `$(LLVM_CONFIG) --cppflags` +#libclamavcxx_la_DEPENDENCIES = $(LLVM_DEPS) +#libclamavcxx_la_LDFLAGS = `$(LLVM_CONFIG) --ldflags --libs jit nativecodegen` +libclamavcxx_la_CPPFLAGS = $(AM_CPPFLAGS) $(LLVM_INCLUDES) $(LLVM_DEFS) +#libclamavcxx_la_DEPENDENCIES = $(LLVM_DEPS) +noinst_LTLIBRARIES = libclamavcxx.la libllvmsupport.la \ + libllvmsystem.la libllvmcore.la libllvmtarget.la \ + libllvmsdag.la libllvmcodegen.la libllvmexecutionengine.la \ + libllvmscalar.la libllvmipa.la libllvmtransformutils.la \ + libllvmmc.la $(am__append_2) $(am__append_4) $(am__append_6) +libclamavcxx_la_LIBADD = $(am__append_1) $(am__append_3) \ + $(am__append_5) libllvmsdag.la libllvmexecutionengine.la \ + libllvmcodegen.la libllvmscalar.la libllvmtransformutils.la \ + libllvmipa.la libllvmtarget.la libllvmmc.la libllvmcore.la \ + libllvmsupport.la libllvmsystem.la +libclamavcxx_la_LDFLAGS = -no-undefined +#libclamavcxx_la_LDFLAGS = `$(LLVM_CONFIG) --ldflags --libs jit nativecodegen` +libclamavcxx_la_SOURCES = bytecode2llvm.cpp +LLVM_INCLUDES = -I$(top_srcdir)/llvm/include -I$(top_builddir)/llvm/include +# TODO: _DEBUG should be defined for --enable-debug, and NDEBUG otherwise, but +# keep it like this while I'm testing LLVM +# TODO: HP-UX should have -D_REENTRANT -D_HPUX_SOURCE +LLVM_DEFS = -D__STDC_LIMIT_MACROS -D__STDC_CONSTANT_MACROS -D_DEBUG -D_GNU_SOURCE +LLVM_CXXFLAGS = -Woverloaded-virtual -pedantic -Wno-long-long -Wall -W -Wno-unused-parameter -Wwrite-strings +EXTRA_DIST = $(top_srcdir)/llvm llvmdejagnu.sh +libllvmsystem_la_CPPFLAGS = $(LLVM_INCLUDES) $(LLVM_DEFS) +libllvmsystem_la_CXXFLAGS = $(LLVM_CXXFLAGS) -fno-exceptions +libllvmsystem_la_LDFLAGS = -pthread +libllvmsystem_la_LIBADD = -ldl +libllvmsystem_la_SOURCES = \ + llvm/lib/System/Alarm.cpp\ + llvm/lib/System/Atomic.cpp\ + llvm/lib/System/Disassembler.cpp\ + llvm/lib/System/DynamicLibrary.cpp\ + llvm/lib/System/Errno.cpp\ + llvm/lib/System/Host.cpp\ + llvm/lib/System/IncludeFile.cpp\ + llvm/lib/System/Memory.cpp\ + llvm/lib/System/Mutex.cpp\ + llvm/lib/System/Path.cpp\ + llvm/lib/System/Process.cpp\ + llvm/lib/System/Program.cpp\ + llvm/lib/System/RWMutex.cpp\ + llvm/lib/System/Signals.cpp\ + llvm/lib/System/ThreadLocal.cpp\ + llvm/lib/System/Threading.cpp\ + llvm/lib/System/TimeValue.cpp\ + llvm/lib/System/Unix/Alarm.inc\ + llvm/lib/System/Unix/Host.inc\ + llvm/lib/System/Unix/Memory.inc\ + llvm/lib/System/Unix/Mutex.inc\ + llvm/lib/System/Unix/Path.inc\ + llvm/lib/System/Unix/Process.inc\ + llvm/lib/System/Unix/Program.inc\ + llvm/lib/System/Unix/RWMutex.inc\ + llvm/lib/System/Unix/Signals.inc\ + llvm/lib/System/Unix/ThreadLocal.inc\ + llvm/lib/System/Unix/TimeValue.inc\ + llvm/lib/System/Win32/Alarm.inc\ + llvm/lib/System/Win32/DynamicLibrary.inc\ + llvm/lib/System/Win32/Host.inc\ + llvm/lib/System/Win32/Memory.inc\ + llvm/lib/System/Win32/Mutex.inc\ + llvm/lib/System/Win32/Path.inc\ + llvm/lib/System/Win32/Process.inc\ + llvm/lib/System/Win32/Program.inc\ + llvm/lib/System/Win32/RWMutex.inc\ + llvm/lib/System/Win32/Signals.inc\ + llvm/lib/System/Win32/ThreadLocal.inc\ + llvm/lib/System/Win32/TimeValue.inc + +libllvmsupport_la_CPPFLAGS = $(LLVM_INCLUDES) $(LLVM_DEFS) +libllvmsupport_la_CXXFLAGS = $(LLVM_CXXFLAGS) -fno-exceptions +libllvmsupport_la_SOURCES = \ + llvm/lib/Support/APFloat.cpp\ + llvm/lib/Support/APInt.cpp\ + llvm/lib/Support/APSInt.cpp\ + llvm/lib/Support/Allocator.cpp\ + llvm/lib/Support/CommandLine.cpp\ + llvm/lib/Support/ConstantRange.cpp\ + llvm/lib/Support/Debug.cpp\ + llvm/lib/Support/Dwarf.cpp\ + llvm/lib/Support/ErrorHandling.cpp\ + llvm/lib/Support/FileUtilities.cpp\ + llvm/lib/Support/FoldingSet.cpp\ + llvm/lib/Support/FormattedStream.cpp\ + llvm/lib/Support/GraphWriter.cpp\ + llvm/lib/Support/IsInf.cpp\ + llvm/lib/Support/IsNAN.cpp\ + llvm/lib/Support/ManagedStatic.cpp\ + llvm/lib/Support/MemoryBuffer.cpp\ + llvm/lib/Support/PluginLoader.cpp\ + llvm/lib/Support/PrettyStackTrace.cpp\ + llvm/lib/Support/SlowOperationInformer.cpp\ + llvm/lib/Support/SmallPtrSet.cpp\ + llvm/lib/Support/SourceMgr.cpp\ + llvm/lib/Support/Statistic.cpp\ + llvm/lib/Support/StringExtras.cpp\ + llvm/lib/Support/StringMap.cpp\ + llvm/lib/Support/StringPool.cpp\ + llvm/lib/Support/StringRef.cpp\ + llvm/lib/Support/SystemUtils.cpp\ + llvm/lib/Support/TargetRegistry.cpp\ + llvm/lib/Support/Timer.cpp\ + llvm/lib/Support/Triple.cpp\ + llvm/lib/Support/Twine.cpp\ + llvm/lib/Support/raw_os_ostream.cpp\ + llvm/lib/Support/raw_ostream.cpp\ + llvm/lib/Support/Regex.cpp\ + llvm/lib/Support/regcomp.c\ + llvm/lib/Support/regerror.c\ + llvm/lib/Support/regexec.c\ + llvm/lib/Support/regfree.c\ + llvm/lib/Support/regstrlcpy.c + +tblgen_CPPFLAGS = $(LLVM_INCLUDES) $(LLVM_DEFS) +tblgen_CXXFLAGS = $(LLVM_CXXFLAGS) +tblgen_LDADD = libllvmsupport.la libllvmsystem.la +#TODO: if VERSIONSCRIPT +tblgen_LDFLAGS = -Wl,--version-script,@top_srcdir@/llvm/autoconf/ExportMap.map +tblgen_SOURCES = \ + llvm/utils/TableGen/AsmMatcherEmitter.cpp\ + llvm/utils/TableGen/AsmWriterEmitter.cpp\ + llvm/utils/TableGen/CallingConvEmitter.cpp\ + llvm/utils/TableGen/ClangDiagnosticsEmitter.cpp\ + llvm/utils/TableGen/CodeEmitterGen.cpp\ + llvm/utils/TableGen/CodeGenDAGPatterns.cpp\ + llvm/utils/TableGen/CodeGenInstruction.cpp\ + llvm/utils/TableGen/CodeGenTarget.cpp\ + llvm/utils/TableGen/DisassemblerEmitter.cpp\ + llvm/utils/TableGen/DAGISelEmitter.cpp\ + llvm/utils/TableGen/FastISelEmitter.cpp\ + llvm/utils/TableGen/InstrEnumEmitter.cpp\ + llvm/utils/TableGen/InstrInfoEmitter.cpp\ + llvm/utils/TableGen/IntrinsicEmitter.cpp\ + llvm/utils/TableGen/LLVMCConfigurationEmitter.cpp\ + llvm/utils/TableGen/OptParserEmitter.cpp\ + llvm/utils/TableGen/Record.cpp\ + llvm/utils/TableGen/RegisterInfoEmitter.cpp\ + llvm/utils/TableGen/SubtargetEmitter.cpp\ + llvm/utils/TableGen/TGLexer.cpp\ + llvm/utils/TableGen/TGParser.cpp\ + llvm/utils/TableGen/TGValueTypes.cpp\ + llvm/utils/TableGen/TableGen.cpp\ + llvm/utils/TableGen/TableGenBackend.cpp + +libllvmcore_la_CPPFLAGS = $(LLVM_INCLUDES) $(LLVM_DEFS) +libllvmcore_la_CXXFLAGS = $(LLVM_CXXFLAGS) -fno-exceptions +libllvmcore_la_SOURCES = \ + llvm/lib/VMCore/AsmWriter.cpp\ + llvm/lib/VMCore/Attributes.cpp\ + llvm/lib/VMCore/AutoUpgrade.cpp\ + llvm/lib/VMCore/BasicBlock.cpp\ + llvm/lib/VMCore/ConstantFold.cpp\ + llvm/lib/VMCore/Constants.cpp\ + llvm/lib/VMCore/Core.cpp\ + llvm/lib/VMCore/Dominators.cpp\ + llvm/lib/VMCore/Function.cpp\ + llvm/lib/VMCore/Globals.cpp\ + llvm/lib/VMCore/InlineAsm.cpp\ + llvm/lib/VMCore/Instruction.cpp\ + llvm/lib/VMCore/Instructions.cpp\ + llvm/lib/VMCore/IntrinsicInst.cpp\ + llvm/lib/VMCore/LLVMContext.cpp\ + llvm/lib/VMCore/LeakDetector.cpp\ + llvm/lib/VMCore/Mangler.cpp\ + llvm/lib/VMCore/Metadata.cpp\ + llvm/lib/VMCore/Module.cpp\ + llvm/lib/VMCore/ModuleProvider.cpp\ + llvm/lib/VMCore/Pass.cpp\ + llvm/lib/VMCore/PassManager.cpp\ + llvm/lib/VMCore/PrintModulePass.cpp\ + llvm/lib/VMCore/Type.cpp\ + llvm/lib/VMCore/TypeSymbolTable.cpp\ + llvm/lib/VMCore/Use.cpp\ + llvm/lib/VMCore/Value.cpp\ + llvm/lib/VMCore/ValueSymbolTable.cpp\ + llvm/lib/VMCore/ValueTypes.cpp\ + llvm/lib/VMCore/Verifier.cpp + +TBLGEN = $(top_builddir)/tblgen +TBLGEN_V = $(AM_V_GEN)$(TBLGEN) +TBLGEN_FLAGS = -I$(top_srcdir)/llvm/include -I$(top_srcdir)/llvm/lib/Target +BUILT_SOURCES = llvm/include/llvm/Intrinsics.gen $(am__append_7) \ + $(am__append_8) $(am__append_9) + +# X86 Target +@BUILD_X86_TRUE@TBLGEN_FLAGS_X86 = $(TBLGEN_FLAGS) -I$(top_srcdir)/llvm/lib/Target/X86 +@BUILD_X86_TRUE@libllvmtargetx86_la_CPPFLAGS = $(LLVM_INCLUDES) $(LLVM_DEFS) -I$(top_builddir) -I$(top_srcdir)/llvm/lib/Target/X86 +@BUILD_X86_TRUE@libllvmtargetx86_la_CXXFLAGS = $(LLVM_CXXFLAGS) -fno-exceptions +@BUILD_X86_TRUE@libllvmtargetx86_la_SOURCES = \ +@BUILD_X86_TRUE@ llvm/lib/Target/X86/X86CodeEmitter.cpp\ +@BUILD_X86_TRUE@ llvm/lib/Target/X86/X86ELFWriterInfo.cpp\ +@BUILD_X86_TRUE@ llvm/lib/Target/X86/X86FloatingPoint.cpp\ +@BUILD_X86_TRUE@ llvm/lib/Target/X86/X86FloatingPointRegKill.cpp\ +@BUILD_X86_TRUE@ llvm/lib/Target/X86/X86ISelDAGToDAG.cpp\ +@BUILD_X86_TRUE@ llvm/lib/Target/X86/X86ISelLowering.cpp\ +@BUILD_X86_TRUE@ llvm/lib/Target/X86/X86InstrInfo.cpp\ +@BUILD_X86_TRUE@ llvm/lib/Target/X86/X86JITInfo.cpp\ +@BUILD_X86_TRUE@ llvm/lib/Target/X86/X86MCAsmInfo.cpp\ +@BUILD_X86_TRUE@ llvm/lib/Target/X86/X86RegisterInfo.cpp\ +@BUILD_X86_TRUE@ llvm/lib/Target/X86/X86Subtarget.cpp\ +@BUILD_X86_TRUE@ llvm/lib/Target/X86/X86TargetMachine.cpp\ +@BUILD_X86_TRUE@ llvm/lib/Target/X86/X86FastISel.cpp\ +@BUILD_X86_TRUE@ llvm/lib/Target/X86/X86TargetObjectFile.cpp\ +@BUILD_X86_TRUE@ llvm/lib/Target/X86/TargetInfo/X86TargetInfo.cpp + + +# PPC Target +@BUILD_PPC_TRUE@TBLGEN_FLAGS_PPC = $(TBLGEN_FLAGS) -I$(top_srcdir)/llvm/lib/Target/PowerPC +@BUILD_PPC_TRUE@libllvmtargetppc_la_CPPFLAGS = $(LLVM_INCLUDES) $(LLVM_DEFS) -I$(top_builddir) -I$(top_srcdir)/llvm/lib/Target/PowerPC +@BUILD_PPC_TRUE@libllvmtargetppc_la_CXXFLAGS = $(LLVM_CXXFLAGS) -fno-exceptions +@BUILD_PPC_TRUE@libllvmtargetppc_la_SOURCES = \ +@BUILD_PPC_TRUE@ llvm/lib/Target/PowerPC/PPCBranchSelector.cpp\ +@BUILD_PPC_TRUE@ llvm/lib/Target/PowerPC/PPCCodeEmitter.cpp\ +@BUILD_PPC_TRUE@ llvm/lib/Target/PowerPC/PPCHazardRecognizers.cpp\ +@BUILD_PPC_TRUE@ llvm/lib/Target/PowerPC/PPCInstrInfo.cpp\ +@BUILD_PPC_TRUE@ llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp\ +@BUILD_PPC_TRUE@ llvm/lib/Target/PowerPC/PPCISelLowering.cpp\ +@BUILD_PPC_TRUE@ llvm/lib/Target/PowerPC/PPCJITInfo.cpp\ +@BUILD_PPC_TRUE@ llvm/lib/Target/PowerPC/PPCMachOWriterInfo.cpp\ +@BUILD_PPC_TRUE@ llvm/lib/Target/PowerPC/PPCMCAsmInfo.cpp\ +@BUILD_PPC_TRUE@ llvm/lib/Target/PowerPC/PPCPredicates.cpp\ +@BUILD_PPC_TRUE@ llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp\ +@BUILD_PPC_TRUE@ llvm/lib/Target/PowerPC/PPCSubtarget.cpp\ +@BUILD_PPC_TRUE@ llvm/lib/Target/PowerPC/PPCTargetMachine.cpp\ +@BUILD_PPC_TRUE@ llvm/lib/Target/PowerPC/TargetInfo/PowerPCTargetInfo.cpp + + +# ARM Target +@BUILD_ARM_TRUE@TBLGEN_FLAGS_ARM = $(TBLGEN_FLAGS) -I$(top_srcdir)/llvm/lib/Target/ARM +@BUILD_ARM_TRUE@libllvmtargetarm_la_CPPFLAGS = $(LLVM_INCLUDES) $(LLVM_DEFS) -I$(top_builddir) -I$(top_srcdir)/llvm/lib/Target/ARM +@BUILD_ARM_TRUE@libllvmtargetarm_la_CXXFLAGS = $(LLVM_CXXFLAGS) -fno-exceptions +@BUILD_ARM_TRUE@libllvmtargetarm_la_SOURCES = \ +@BUILD_ARM_TRUE@ llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp\ +@BUILD_ARM_TRUE@ llvm/lib/Target/ARM/ARMBaseRegisterInfo.cpp\ +@BUILD_ARM_TRUE@ llvm/lib/Target/ARM/ARMCodeEmitter.cpp\ +@BUILD_ARM_TRUE@ llvm/lib/Target/ARM/ARMConstantIslandPass.cpp\ +@BUILD_ARM_TRUE@ llvm/lib/Target/ARM/ARMConstantPoolValue.cpp\ +@BUILD_ARM_TRUE@ llvm/lib/Target/ARM/ARMExpandPseudoInsts.cpp\ +@BUILD_ARM_TRUE@ llvm/lib/Target/ARM/ARMInstrInfo.cpp\ +@BUILD_ARM_TRUE@ llvm/lib/Target/ARM/ARMISelDAGToDAG.cpp\ +@BUILD_ARM_TRUE@ llvm/lib/Target/ARM/ARMISelLowering.cpp\ +@BUILD_ARM_TRUE@ llvm/lib/Target/ARM/ARMJITInfo.cpp\ +@BUILD_ARM_TRUE@ llvm/lib/Target/ARM/ARMLoadStoreOptimizer.cpp\ +@BUILD_ARM_TRUE@ llvm/lib/Target/ARM/ARMMCAsmInfo.cpp\ +@BUILD_ARM_TRUE@ llvm/lib/Target/ARM/ARMRegisterInfo.cpp\ +@BUILD_ARM_TRUE@ llvm/lib/Target/ARM/ARMSubtarget.cpp\ +@BUILD_ARM_TRUE@ llvm/lib/Target/ARM/ARMTargetMachine.cpp\ +@BUILD_ARM_TRUE@ llvm/lib/Target/ARM/NEONMoveFix.cpp\ +@BUILD_ARM_TRUE@ llvm/lib/Target/ARM/NEONPreAllocPass.cpp\ +@BUILD_ARM_TRUE@ llvm/lib/Target/ARM/Thumb1InstrInfo.cpp\ +@BUILD_ARM_TRUE@ llvm/lib/Target/ARM/Thumb1RegisterInfo.cpp\ +@BUILD_ARM_TRUE@ llvm/lib/Target/ARM/Thumb2ITBlockPass.cpp\ +@BUILD_ARM_TRUE@ llvm/lib/Target/ARM/Thumb2InstrInfo.cpp\ +@BUILD_ARM_TRUE@ llvm/lib/Target/ARM/Thumb2RegisterInfo.cpp\ +@BUILD_ARM_TRUE@ llvm/lib/Target/ARM/Thumb2SizeReduction.cpp\ +@BUILD_ARM_TRUE@ llvm/lib/Target/ARM/TargetInfo/ARMTargetInfo.cpp + + +# End of Targets +libllvmtarget_la_CPPFLAGS = $(LLVM_INCLUDES) $(LLVM_DEFS) +libllvmtarget_la_CXXFLAGS = $(LLVM_CXXFLAGS) -fno-exceptions +libllvmtarget_la_SOURCES = \ + llvm/lib/Target/SubtargetFeature.cpp\ + llvm/lib/Target/Target.cpp\ + llvm/lib/Target/TargetData.cpp\ + llvm/lib/Target/TargetELFWriterInfo.cpp\ + llvm/lib/Target/TargetFrameInfo.cpp\ + llvm/lib/Target/TargetInstrInfo.cpp\ + llvm/lib/Target/TargetIntrinsicInfo.cpp\ + llvm/lib/Target/TargetLoweringObjectFile.cpp\ + llvm/lib/Target/TargetMachOWriterInfo.cpp\ + llvm/lib/Target/TargetMachine.cpp\ + llvm/lib/Target/TargetRegisterInfo.cpp\ + llvm/lib/Target/TargetSubtarget.cpp + +libllvmmc_la_CPPFLAGS = $(LLVM_INCLUDES) $(LLVM_DEFS) +libllvmmc_la_CXXFLAGS = $(LLVM_CXXFLAGS) -fno-exceptions +libllvmmc_la_SOURCES = \ + llvm/lib/MC/MCAsmInfo.cpp\ + llvm/lib/MC/MCAsmInfoCOFF.cpp\ + llvm/lib/MC/MCAsmInfoDarwin.cpp\ + llvm/lib/MC/MCAsmLexer.cpp\ + llvm/lib/MC/MCAsmParser.cpp\ + llvm/lib/MC/MCAsmStreamer.cpp\ + llvm/lib/MC/MCAssembler.cpp\ + llvm/lib/MC/MCCodeEmitter.cpp\ + llvm/lib/MC/MCContext.cpp\ + llvm/lib/MC/MCExpr.cpp\ + llvm/lib/MC/MCInst.cpp\ + llvm/lib/MC/MCMachOStreamer.cpp\ + llvm/lib/MC/MCNullStreamer.cpp\ + llvm/lib/MC/MCSection.cpp\ + llvm/lib/MC/MCSectionELF.cpp\ + llvm/lib/MC/MCSectionMachO.cpp\ + llvm/lib/MC/MCStreamer.cpp\ + llvm/lib/MC/MCSymbol.cpp\ + llvm/lib/MC/MCValue.cpp\ + llvm/lib/MC/TargetAsmParser.cpp + +libllvmsdag_la_CPPFLAGS = $(LLVM_INCLUDES) $(LLVM_DEFS) +libllvmsdag_la_CXXFLAGS = $(LLVM_CXXFLAGS) -fno-exceptions +libllvmsdag_la_SOURCES = \ + llvm/lib/CodeGen/SelectionDAG/CallingConvLower.cpp\ + llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp\ + llvm/lib/CodeGen/SelectionDAG/FastISel.cpp\ + llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp\ + llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp\ + llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp\ + llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp\ + llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp\ + llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp\ + llvm/lib/CodeGen/SelectionDAG/LegalizeTypesGeneric.cpp\ + llvm/lib/CodeGen/SelectionDAG/LegalizeVectorOps.cpp\ + llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp\ + llvm/lib/CodeGen/SelectionDAG/ScheduleDAGFast.cpp\ + llvm/lib/CodeGen/SelectionDAG/ScheduleDAGList.cpp\ + llvm/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp\ + llvm/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp\ + llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp\ + llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp\ + llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp\ + llvm/lib/CodeGen/SelectionDAG/SelectionDAGPrinter.cpp\ + llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp\ + llvm/lib/CodeGen/AsmPrinter/DwarfWriter.cpp\ + llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp\ + llvm/lib/CodeGen/AsmPrinter/DwarfException.cpp\ + llvm/lib/CodeGen/AsmPrinter/DwarfLabel.cpp\ + llvm/lib/CodeGen/AsmPrinter/DwarfPrinter.cpp\ + llvm/lib/CodeGen/AsmPrinter/DIE.cpp\ + llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp + +libllvmipa_la_CPPFLAGS = $(LLVM_INCLUDES) $(LLVM_DEFS) +libllvmipa_la_CXXFLAGS = $(LLVM_CXXFLAGS) -fno-exceptions +libllvmipa_la_SOURCES = \ + llvm/lib/Analysis/AliasAnalysis.cpp\ + llvm/lib/Analysis/AliasSetTracker.cpp\ + llvm/lib/Analysis/BasicAliasAnalysis.cpp\ + llvm/lib/Analysis/CaptureTracking.cpp\ + llvm/lib/Analysis/ConstantFolding.cpp\ + llvm/lib/Analysis/DebugInfo.cpp\ + llvm/lib/Analysis/IVUsers.cpp\ + llvm/lib/Analysis/InstructionSimplify.cpp\ + llvm/lib/Analysis/LiveValues.cpp\ + llvm/lib/Analysis/LoopDependenceAnalysis.cpp\ + llvm/lib/Analysis/LoopInfo.cpp\ + llvm/lib/Analysis/LoopPass.cpp\ + llvm/lib/Analysis/MemoryBuiltins.cpp\ + llvm/lib/Analysis/MemoryDependenceAnalysis.cpp\ + llvm/lib/Analysis/ProfileInfo.cpp\ + llvm/lib/Analysis/ScalarEvolution.cpp\ + llvm/lib/Analysis/ScalarEvolutionExpander.cpp\ + llvm/lib/Analysis/ValueTracking.cpp\ + llvm/lib/Analysis/IPA/CallGraph.cpp + +libllvmcodegen_la_CPPFLAGS = $(LLVM_INCLUDES) $(LLVM_DEFS) +libllvmcodegen_la_CXXFLAGS = $(LLVM_CXXFLAGS) -fno-exceptions +libllvmcodegen_la_SOURCES = \ + llvm/lib/CodeGen/AggressiveAntiDepBreaker.cpp\ + llvm/lib/CodeGen/BranchFolding.cpp\ + llvm/lib/CodeGen/CriticalAntiDepBreaker.cpp\ + llvm/lib/CodeGen/CodePlacementOpt.cpp\ + llvm/lib/CodeGen/DeadMachineInstructionElim.cpp\ + llvm/lib/CodeGen/DwarfEHPrepare.cpp\ + llvm/lib/CodeGen/ELFCodeEmitter.cpp\ + llvm/lib/CodeGen/ELFWriter.cpp\ + llvm/lib/CodeGen/ExactHazardRecognizer.cpp\ + llvm/lib/CodeGen/GCMetadata.cpp\ + llvm/lib/CodeGen/GCMetadataPrinter.cpp\ + llvm/lib/CodeGen/GCStrategy.cpp\ + llvm/lib/CodeGen/IfConversion.cpp\ + llvm/lib/CodeGen/IntrinsicLowering.cpp\ + llvm/lib/CodeGen/LLVMTargetMachine.cpp\ + llvm/lib/CodeGen/LatencyPriorityQueue.cpp\ + llvm/lib/CodeGen/LiveInterval.cpp\ + llvm/lib/CodeGen/LiveIntervalAnalysis.cpp\ + llvm/lib/CodeGen/LiveStackAnalysis.cpp\ + llvm/lib/CodeGen/LiveVariables.cpp\ + llvm/lib/CodeGen/LowerSubregs.cpp\ + llvm/lib/CodeGen/MachineBasicBlock.cpp\ + llvm/lib/CodeGen/MachineDominators.cpp\ + llvm/lib/CodeGen/MachineFunction.cpp\ + llvm/lib/CodeGen/MachineFunctionAnalysis.cpp\ + llvm/lib/CodeGen/MachineFunctionPass.cpp\ + llvm/lib/CodeGen/MachineInstr.cpp\ + llvm/lib/CodeGen/MachineLICM.cpp\ + llvm/lib/CodeGen/MachineLoopInfo.cpp\ + llvm/lib/CodeGen/MachineModuleInfo.cpp\ + llvm/lib/CodeGen/MachineModuleInfoImpls.cpp\ + llvm/lib/CodeGen/MachinePassRegistry.cpp\ + llvm/lib/CodeGen/MachineRegisterInfo.cpp\ + llvm/lib/CodeGen/MachineSink.cpp\ + llvm/lib/CodeGen/MachineVerifier.cpp\ + llvm/lib/CodeGen/ObjectCodeEmitter.cpp\ + llvm/lib/CodeGen/OcamlGC.cpp\ + llvm/lib/CodeGen/PHIElimination.cpp\ + llvm/lib/CodeGen/Passes.cpp\ + llvm/lib/CodeGen/PostRASchedulerList.cpp\ + llvm/lib/CodeGen/PreAllocSplitting.cpp\ + llvm/lib/CodeGen/ProcessImplicitDefs.cpp\ + llvm/lib/CodeGen/PrologEpilogInserter.cpp\ + llvm/lib/CodeGen/PseudoSourceValue.cpp\ + llvm/lib/CodeGen/RegAllocLinearScan.cpp\ + llvm/lib/CodeGen/RegAllocLocal.cpp\ + llvm/lib/CodeGen/RegAllocPBQP.cpp\ + llvm/lib/CodeGen/RegisterCoalescer.cpp\ + llvm/lib/CodeGen/RegisterScavenging.cpp\ + llvm/lib/CodeGen/ScheduleDAG.cpp\ + llvm/lib/CodeGen/ScheduleDAGEmit.cpp\ + llvm/lib/CodeGen/ScheduleDAGInstrs.cpp\ + llvm/lib/CodeGen/ScheduleDAGPrinter.cpp\ + llvm/lib/CodeGen/ShadowStackGC.cpp\ + llvm/lib/CodeGen/ShrinkWrapping.cpp\ + llvm/lib/CodeGen/SimpleRegisterCoalescing.cpp\ + llvm/lib/CodeGen/SjLjEHPrepare.cpp\ + llvm/lib/CodeGen/SlotIndexes.cpp\ + llvm/lib/CodeGen/Spiller.cpp\ + llvm/lib/CodeGen/StackProtector.cpp\ + llvm/lib/CodeGen/StackSlotColoring.cpp\ + llvm/lib/CodeGen/StrongPHIElimination.cpp\ + llvm/lib/CodeGen/TailDuplication.cpp\ + llvm/lib/CodeGen/TargetInstrInfoImpl.cpp\ + llvm/lib/CodeGen/TwoAddressInstructionPass.cpp\ + llvm/lib/CodeGen/UnreachableBlockElim.cpp\ + llvm/lib/CodeGen/VirtRegMap.cpp\ + llvm/lib/CodeGen/VirtRegRewriter.cpp + +libllvmscalar_la_CPPFLAGS = $(LLVM_INCLUDES) $(LLVM_DEFS) +libllvmscalar_la_CXXFLAGS = $(LLVM_CXXFLAGS) -fno-exceptions +libllvmscalar_la_SOURCES = \ + llvm/lib/Transforms/Scalar/CodeGenPrepare.cpp\ + llvm/lib/Transforms/Scalar/DCE.cpp\ + llvm/lib/Transforms/Scalar/GEPSplitter.cpp\ + llvm/lib/Transforms/Scalar/GVN.cpp\ + llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp\ + llvm/lib/Transforms/Scalar/ConstantProp.cpp\ + llvm/lib/Transforms/Scalar/SimplifyCFGPass.cpp + +libllvmtransformutils_la_CPPFLAGS = $(LLVM_INCLUDES) $(LLVM_DEFS) +libllvmtransformutils_la_CXXFLAGS = $(LLVM_CXXFLAGS) -fno-exceptions +libllvmtransformutils_la_SOURCES = \ + llvm/lib/Transforms/Utils/AddrModeMatcher.cpp\ + llvm/lib/Transforms/Utils/BasicBlockUtils.cpp\ + llvm/lib/Transforms/Utils/BreakCriticalEdges.cpp\ + llvm/lib/Transforms/Utils/DemoteRegToStack.cpp\ + llvm/lib/Transforms/Utils/LCSSA.cpp\ + llvm/lib/Transforms/Utils/Local.cpp\ + llvm/lib/Transforms/Utils/LoopSimplify.cpp\ + llvm/lib/Transforms/Utils/LowerInvoke.cpp\ + llvm/lib/Transforms/Utils/LowerSwitch.cpp\ + llvm/lib/Transforms/Utils/Mem2Reg.cpp\ + llvm/lib/Transforms/Utils/PromoteMemoryToRegister.cpp\ + llvm/lib/Transforms/Utils/SimplifyCFG.cpp\ + llvm/lib/Transforms/Utils/SSAUpdater.cpp\ + llvm/lib/Transforms/Utils/UnifyFunctionExitNodes.cpp + +libllvmexecutionengine_la_CPPFLAGS = $(LLVM_INCLUDES) $(LLVM_DEFS) +libllvmexecutionengine_la_CXXFLAGS = $(LLVM_CXXFLAGS) -fno-exceptions +libllvmexecutionengine_la_SOURCES = \ + llvm/lib/ExecutionEngine/ExecutionEngine.cpp\ + llvm/lib/ExecutionEngine/JIT/Intercept.cpp\ + llvm/lib/ExecutionEngine/JIT/JIT.cpp\ + llvm/lib/ExecutionEngine/JIT/JITDebugRegisterer.cpp\ + llvm/lib/ExecutionEngine/JIT/JITDwarfEmitter.cpp\ + llvm/lib/ExecutionEngine/JIT/JITEmitter.cpp\ + llvm/lib/ExecutionEngine/JIT/JITMemoryManager.cpp\ + llvm/lib/ExecutionEngine/JIT/TargetSelect.cpp + +# llvm/lib/ExecutionEngine/JIT/OProfileJITEventListener.cpp + +# Used only by make check +libllvmbitreader_la_CPPFLAGS = $(LLVM_INCLUDES) $(LLVM_DEFS) +libllvmbitreader_la_CXXFLAGS = $(LLVM_CXXFLAGS) -fno-exceptions +libllvmbitreader_la_SOURCES = \ + llvm/lib/Bitcode/Reader/BitReader.cpp\ + llvm/lib/Bitcode/Reader/BitcodeReader.cpp\ + llvm/lib/Bitcode/Reader/Deserialize.cpp\ + llvm/lib/Bitcode/Reader/DeserializeAPFloat.cpp\ + llvm/lib/Bitcode/Reader/DeserializeAPInt.cpp + +libllvmbitwriter_la_CPPFLAGS = $(LLVM_INCLUDES) $(LLVM_DEFS) +libllvmbitwriter_la_CXXFLAGS = $(LLVM_CXXFLAGS) -fno-exceptions +libllvmbitwriter_la_SOURCES = \ + llvm/lib/Bitcode/Writer/BitWriter.cpp\ + llvm/lib/Bitcode/Writer/BitcodeWriter.cpp\ + llvm/lib/Bitcode/Writer/BitcodeWriterPass.cpp\ + llvm/lib/Bitcode/Writer/Serialize.cpp\ + llvm/lib/Bitcode/Writer/SerializeAPFloat.cpp\ + llvm/lib/Bitcode/Writer/SerializeAPInt.cpp\ + llvm/lib/Bitcode/Writer/ValueEnumerator.cpp + +libllvmasmparser_la_CPPFLAGS = $(LLVM_INCLUDES) $(LLVM_DEFS) +libllvmasmparser_la_CXXFLAGS = $(LLVM_CXXFLAGS) -fno-exceptions +libllvmasmparser_la_SOURCES = \ + llvm/lib/AsmParser/LLLexer.cpp\ + llvm/lib/AsmParser/LLParser.cpp\ + llvm/lib/AsmParser/Parser.cpp + +libllvminterpreter_la_CPPFLAGS = $(LLVM_INCLUDES) $(LLVM_DEFS) -I$(top_srcdir)/llvm/utils/unittest/googletest/include +libllvminterpreter_la_CXXFLAGS = $(LLVM_CXXFLAGS) -fno-exceptions -Wno-missing-field-initializers -Wno-variadic-macros +libllvminterpreter_la_SOURCES = \ + llvm/lib/ExecutionEngine/Interpreter/Execution.cpp\ + llvm/lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp\ + llvm/lib/ExecutionEngine/Interpreter/Interpreter.cpp + +libgoogletest_la_CPPFLAGS = $(LLVM_INCLUDES) $(LLVM_DEFS) -I$(top_srcdir)/llvm/utils/unittest/googletest/include +libgoogletest_la_CXXFLAGS = $(LLVM_CXXFLAGS) -fno-exceptions -Wno-missing-field-initializers -Wno-variadic-macros +libgoogletest_la_SOURCES = \ + llvm/utils/unittest/googletest/gtest-death-test.cc\ + llvm/utils/unittest/googletest/gtest-filepath.cc\ + llvm/utils/unittest/googletest/gtest-port.cc\ + llvm/utils/unittest/googletest/gtest-test-part.cc\ + llvm/utils/unittest/googletest/gtest-typed-test.cc\ + llvm/utils/unittest/googletest/gtest.cc\ + llvm/utils/unittest/UnitTestMain/TestMain.cpp + +llvmunittest_ADT_CPPFLAGS = $(LLVM_INCLUDES) $(LLVM_DEFS) -I$(top_srcdir)/llvm/utils/unittest/googletest/include +llvmunittest_ADT_CXXFLAGS = $(LLVM_CXXFLAGS) -fno-exceptions -Wno-variadic-macros +llvmunittest_ADT_LDADD = libgoogletest.la libllvmcore.la libllvmsupport.la libllvmsystem.la +llvmunittest_ADT_SOURCES = \ + llvm/unittests/ADT/APFloatTest.cpp\ + llvm/unittests/ADT/APIntTest.cpp\ + llvm/unittests/ADT/DenseMapTest.cpp\ + llvm/unittests/ADT/DenseSetTest.cpp\ + llvm/unittests/ADT/ImmutableSetTest.cpp\ + llvm/unittests/ADT/SmallStringTest.cpp\ + llvm/unittests/ADT/SmallVectorTest.cpp\ + llvm/unittests/ADT/SparseBitVectorTest.cpp\ + llvm/unittests/ADT/StringMapTest.cpp\ + llvm/unittests/ADT/StringRefTest.cpp\ + llvm/unittests/ADT/TripleTest.cpp\ + llvm/unittests/ADT/TwineTest.cpp + +llvmunittest_Support_CPPFLAGS = $(LLVM_INCLUDES) $(LLVM_DEFS) -I$(top_srcdir)/llvm/utils/unittest/googletest/include +llvmunittest_Support_CXXFLAGS = $(LLVM_CXXFLAGS) -fno-exceptions -Wno-variadic-macros +llvmunittest_Support_LDADD = libgoogletest.la libllvmcore.la libllvmsupport.la libllvmsystem.la +llvmunittest_Support_SOURCES = \ + llvm/unittests/Support/AllocatorTest.cpp\ + llvm/unittests/Support/ConstantRangeTest.cpp\ + llvm/unittests/Support/MathExtrasTest.cpp\ + llvm/unittests/Support/RegexTest.cpp\ + llvm/unittests/Support/TypeBuilderTest.cpp\ + llvm/unittests/Support/ValueHandleTest.cpp\ + llvm/unittests/Support/raw_ostream_test.cpp + +llvmunittest_VMCore_CPPFLAGS = $(LLVM_INCLUDES) $(LLVM_DEFS) -I$(top_srcdir)/llvm/utils/unittest/googletest/include +llvmunittest_VMCore_CXXFLAGS = $(LLVM_CXXFLAGS) -fno-exceptions -Wno-variadic-macros +llvmunittest_VMCore_LDADD = libgoogletest.la libllvmtarget.la libllvmipa.la libllvmcore.la libllvmsupport.la libllvmsystem.la +llvmunittest_VMCore_SOURCES = \ + llvm/lib/Analysis/IPA/CallGraphSCCPass.cpp\ + llvm/unittests/VMCore/ConstantsTest.cpp\ + llvm/unittests/VMCore/MetadataTest.cpp\ + llvm/unittests/VMCore/PassManagerTest.cpp + +llvmunittest_JIT_CPPFLAGS = $(LLVM_INCLUDES) $(LLVM_DEFS) -I$(top_srcdir)/llvm/utils/unittest/googletest/include +llvmunittest_JIT_CXXFLAGS = $(LLVM_CXXFLAGS) -fno-exceptions -Wno-variadic-macros +llvmunittest_JIT_LDADD = libgoogletest.la libllvmasmparser.la $(libclamavcxx_la_LIBADD) +llvmunittest_JIT_SOURCES = \ + llvm/unittests/ExecutionEngine/JIT/JITEventListenerTest.cpp\ + llvm/unittests/ExecutionEngine/JIT/JITMemoryManagerTest.cpp\ + llvm/unittests/ExecutionEngine/JIT/JITTest.cpp + +llvmunittest_ExecutionEngine_CPPFLAGS = $(LLVM_INCLUDES) $(LLVM_DEFS) -I$(top_srcdir)/llvm/utils/unittest/googletest/include +llvmunittest_ExecutionEngine_CXXFLAGS = $(LLVM_CXXFLAGS) -fno-exceptions -Wno-variadic-macros +llvmunittest_ExecutionEngine_LDADD = libgoogletest.la libllvminterpreter.la $(libclamavcxx_la_LIBADD) +llvmunittest_ExecutionEngine_SOURCES = \ + llvm/unittests/ExecutionEngine/ExecutionEngineTest.cpp + +count_CPPFLAGS = $(LLVM_INCLUDES) $(LLVM_DEFS) +count_SOURCES = llvm/utils/count/count.c +count_LDADD = libllvmsystem.la +not_CPPFLAGS = $(LLVM_INCLUDES) $(LLVM_DEFS) +not_CXXFLAGS = $(LLVM_CXXFLAGS) +not_SOURCES = llvm/utils/not/not.cpp +not_LDADD = libllvmsystem.la +FileCheck_CPPFLAGS = $(LLVM_INCLUDES) $(LLVM_DEFS) +FileCheck_CXXFLAGS = $(LLVM_CXXFLAGS) +FileCheck_LDADD = libllvmsupport.la libllvmsystem.la +FileCheck_SOURCES = llvm/utils/FileCheck/FileCheck.cpp +check_LTLIBRARIES = libllvmbitreader.la libllvmasmprinter.la libllvmbitwriter.la libllvmasmparser.la libgoogletest.la libllvminterpreter.la +# Disable LLVM make check for now, there are some things to fix first: +# - check python version (2.4 doesn't work, needs 2.5+) +# - run llvm's make check after clamav's was run +# - have a way to run only clamav's make check and not llvm's +#check_SCRIPTS=llvmdejagnu.sh +TESTS_ENVIRONMENT = export GMAKE=@GMAKE@; +libllvmasmprinter_la_CPPFLAGS = $(LLVM_INCLUDES) $(LLVM_DEFS) -I$(top_srcdir)/llvm/lib/Target/X86 \ + -I$(top_srcdir)/llvm/lib/Target/PowerPC -I$(top_srcdir)/llvm/lib/Target/ARM + +libllvmasmprinter_la_CXXFLAGS = $(LLVM_CXXFLAGS) -fno-exceptions +libllvmasmprinter_la_SOURCES = \ + llvm/lib/CodeGen/AsmPrinter/OcamlGCPrinter.cpp \ + llvm/lib/CodeGen/ELFCodeEmitter.cpp \ + llvm/lib/CodeGen/ELFWriter.cpp \ + llvm/lib/CodeGen/MachOCodeEmitter.cpp \ + llvm/lib/CodeGen/MachOWriter.cpp $(am__append_10) \ + $(am__append_11) $(am__append_12) +lli_CPPFLAGS = $(LLVM_INCLUDES) $(LLVM_DEFS) +lli_CXXFLAGS = $(LLVM_CXXFLAGS) +lli_LDADD = libllvmbitreader.la libllvminterpreter.la $(libclamavcxx_la_LIBADD) +lli_SOURCES = \ + llvm/lib/ExecutionEngine/JIT/OProfileJITEventListener.cpp\ + llvm/tools/lli/lli.cpp + +llc_CPPFLAGS = $(LLVM_INCLUDES) $(LLVM_DEFS) +llc_CXXFLAGS = $(LLVM_CXXFLAGS) +llc_LDADD = libllvmbitreader.la libllvmasmparser.la libllvmasmprinter.la $(libclamavcxx_la_LIBADD) +llc_SOURCES = \ + llvm/lib/MC/MCInstPrinter.cpp\ + llvm/tools/llc/llc.cpp + +llvm_as_CPPFLAGS = $(LLVM_INCLUDES) $(LLVM_DEFS) +llvm_as_CXXFLAGS = $(LLVM_CXXFLAGS) +llvm_as_LDADD = libllvmasmparser.la libllvmbitwriter.la libllvmcore.la libllvmsupport.la libllvmsystem.la +llvm_as_SOURCES = \ + llvm/tools/llvm-as/llvm-as.cpp + +llvm_dis_CPPFLAGS = $(LLVM_INCLUDES) $(LLVM_DEFS) +llvm_dis_CXXFLAGS = $(LLVM_CXXFLAGS) +llvm_dis_LDADD = libllvmasmparser.la libllvmbitreader.la libllvmcore.la libllvmsupport.la libllvmsystem.la +llvm_dis_SOURCES = \ + llvm/tools/llvm-dis/llvm-dis.cpp + +CONFIG_STATUS_DEPENDENCIES = $(top_builddir)/llvm/config.status +all: $(BUILT_SOURCES) clamavcxx-config.h + $(MAKE) $(AM_MAKEFLAGS) all-am + +.SUFFIXES: +.SUFFIXES: .c .cc .cpp .lo .o .obj +am--refresh: + @: +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + echo ' cd $(srcdir) && $(AUTOMAKE) --foreign'; \ + $(am__cd) $(srcdir) && $(AUTOMAKE) --foreign \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + echo ' $(SHELL) ./config.status'; \ + $(SHELL) ./config.status;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + $(SHELL) ./config.status --recheck + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + $(am__cd) $(srcdir) && $(AUTOCONF) +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + $(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) +$(am__aclocal_m4_deps): + +clamavcxx-config.h: stamp-h1 + @if test ! -f $@; then \ + rm -f stamp-h1; \ + $(MAKE) $(AM_MAKEFLAGS) stamp-h1; \ + else :; fi + +stamp-h1: $(srcdir)/clamavcxx-config.h.in $(top_builddir)/config.status + @rm -f stamp-h1 + cd $(top_builddir) && $(SHELL) ./config.status clamavcxx-config.h +$(srcdir)/clamavcxx-config.h.in: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + ($(am__cd) $(top_srcdir) && $(AUTOHEADER)) + rm -f stamp-h1 + touch $@ + +distclean-hdr: + -rm -f clamavcxx-config.h stamp-h1 + +clean-checkLTLIBRARIES: + -test -z "$(check_LTLIBRARIES)" || rm -f $(check_LTLIBRARIES) + @list='$(check_LTLIBRARIES)'; for p in $$list; do \ + dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ + test "$$dir" != "$$p" || dir=.; \ + echo "rm -f \"$${dir}/so_locations\""; \ + rm -f "$${dir}/so_locations"; \ + done + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \ + dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ + test "$$dir" != "$$p" || dir=.; \ + echo "rm -f \"$${dir}/so_locations\""; \ + rm -f "$${dir}/so_locations"; \ + done +libclamavcxx.la: $(libclamavcxx_la_OBJECTS) $(libclamavcxx_la_DEPENDENCIES) + $(AM_V_CXXLD)$(libclamavcxx_la_LINK) $(libclamavcxx_la_OBJECTS) $(libclamavcxx_la_LIBADD) $(LIBS) +libgoogletest.la: $(libgoogletest_la_OBJECTS) $(libgoogletest_la_DEPENDENCIES) + $(AM_V_CXXLD)$(libgoogletest_la_LINK) $(libgoogletest_la_OBJECTS) $(libgoogletest_la_LIBADD) $(LIBS) +libllvmasmparser.la: $(libllvmasmparser_la_OBJECTS) $(libllvmasmparser_la_DEPENDENCIES) + $(AM_V_CXXLD)$(libllvmasmparser_la_LINK) $(libllvmasmparser_la_OBJECTS) $(libllvmasmparser_la_LIBADD) $(LIBS) +libllvmasmprinter.la: $(libllvmasmprinter_la_OBJECTS) $(libllvmasmprinter_la_DEPENDENCIES) + $(AM_V_CXXLD)$(libllvmasmprinter_la_LINK) $(libllvmasmprinter_la_OBJECTS) $(libllvmasmprinter_la_LIBADD) $(LIBS) +libllvmbitreader.la: $(libllvmbitreader_la_OBJECTS) $(libllvmbitreader_la_DEPENDENCIES) + $(AM_V_CXXLD)$(libllvmbitreader_la_LINK) $(libllvmbitreader_la_OBJECTS) $(libllvmbitreader_la_LIBADD) $(LIBS) +libllvmbitwriter.la: $(libllvmbitwriter_la_OBJECTS) $(libllvmbitwriter_la_DEPENDENCIES) + $(AM_V_CXXLD)$(libllvmbitwriter_la_LINK) $(libllvmbitwriter_la_OBJECTS) $(libllvmbitwriter_la_LIBADD) $(LIBS) +libllvmcodegen.la: $(libllvmcodegen_la_OBJECTS) $(libllvmcodegen_la_DEPENDENCIES) + $(AM_V_CXXLD)$(libllvmcodegen_la_LINK) $(libllvmcodegen_la_OBJECTS) $(libllvmcodegen_la_LIBADD) $(LIBS) +libllvmcore.la: $(libllvmcore_la_OBJECTS) $(libllvmcore_la_DEPENDENCIES) + $(AM_V_CXXLD)$(libllvmcore_la_LINK) $(libllvmcore_la_OBJECTS) $(libllvmcore_la_LIBADD) $(LIBS) +libllvmexecutionengine.la: $(libllvmexecutionengine_la_OBJECTS) $(libllvmexecutionengine_la_DEPENDENCIES) + $(AM_V_CXXLD)$(libllvmexecutionengine_la_LINK) $(libllvmexecutionengine_la_OBJECTS) $(libllvmexecutionengine_la_LIBADD) $(LIBS) +libllvminterpreter.la: $(libllvminterpreter_la_OBJECTS) $(libllvminterpreter_la_DEPENDENCIES) + $(AM_V_CXXLD)$(libllvminterpreter_la_LINK) $(libllvminterpreter_la_OBJECTS) $(libllvminterpreter_la_LIBADD) $(LIBS) +libllvmipa.la: $(libllvmipa_la_OBJECTS) $(libllvmipa_la_DEPENDENCIES) + $(AM_V_CXXLD)$(libllvmipa_la_LINK) $(libllvmipa_la_OBJECTS) $(libllvmipa_la_LIBADD) $(LIBS) +libllvmmc.la: $(libllvmmc_la_OBJECTS) $(libllvmmc_la_DEPENDENCIES) + $(AM_V_CXXLD)$(libllvmmc_la_LINK) $(libllvmmc_la_OBJECTS) $(libllvmmc_la_LIBADD) $(LIBS) +libllvmscalar.la: $(libllvmscalar_la_OBJECTS) $(libllvmscalar_la_DEPENDENCIES) + $(AM_V_CXXLD)$(libllvmscalar_la_LINK) $(libllvmscalar_la_OBJECTS) $(libllvmscalar_la_LIBADD) $(LIBS) +libllvmsdag.la: $(libllvmsdag_la_OBJECTS) $(libllvmsdag_la_DEPENDENCIES) + $(AM_V_CXXLD)$(libllvmsdag_la_LINK) $(libllvmsdag_la_OBJECTS) $(libllvmsdag_la_LIBADD) $(LIBS) +libllvmsupport.la: $(libllvmsupport_la_OBJECTS) $(libllvmsupport_la_DEPENDENCIES) + $(AM_V_CXXLD)$(libllvmsupport_la_LINK) $(libllvmsupport_la_OBJECTS) $(libllvmsupport_la_LIBADD) $(LIBS) +libllvmsystem.la: $(libllvmsystem_la_OBJECTS) $(libllvmsystem_la_DEPENDENCIES) + $(AM_V_CXXLD)$(libllvmsystem_la_LINK) $(libllvmsystem_la_OBJECTS) $(libllvmsystem_la_LIBADD) $(LIBS) +libllvmtarget.la: $(libllvmtarget_la_OBJECTS) $(libllvmtarget_la_DEPENDENCIES) + $(AM_V_CXXLD)$(libllvmtarget_la_LINK) $(libllvmtarget_la_OBJECTS) $(libllvmtarget_la_LIBADD) $(LIBS) +libllvmtargetarm.la: $(libllvmtargetarm_la_OBJECTS) $(libllvmtargetarm_la_DEPENDENCIES) + $(AM_V_CXXLD)$(libllvmtargetarm_la_LINK) $(am_libllvmtargetarm_la_rpath) $(libllvmtargetarm_la_OBJECTS) $(libllvmtargetarm_la_LIBADD) $(LIBS) +libllvmtargetppc.la: $(libllvmtargetppc_la_OBJECTS) $(libllvmtargetppc_la_DEPENDENCIES) + $(AM_V_CXXLD)$(libllvmtargetppc_la_LINK) $(am_libllvmtargetppc_la_rpath) $(libllvmtargetppc_la_OBJECTS) $(libllvmtargetppc_la_LIBADD) $(LIBS) +libllvmtargetx86.la: $(libllvmtargetx86_la_OBJECTS) $(libllvmtargetx86_la_DEPENDENCIES) + $(AM_V_CXXLD)$(libllvmtargetx86_la_LINK) $(am_libllvmtargetx86_la_rpath) $(libllvmtargetx86_la_OBJECTS) $(libllvmtargetx86_la_LIBADD) $(LIBS) +libllvmtransformutils.la: $(libllvmtransformutils_la_OBJECTS) $(libllvmtransformutils_la_DEPENDENCIES) + $(AM_V_CXXLD)$(libllvmtransformutils_la_LINK) $(libllvmtransformutils_la_OBJECTS) $(libllvmtransformutils_la_LIBADD) $(LIBS) + +clean-checkPROGRAMS: + @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list + +clean-noinstPROGRAMS: + @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list +FileCheck$(EXEEXT): $(FileCheck_OBJECTS) $(FileCheck_DEPENDENCIES) + @rm -f FileCheck$(EXEEXT) + $(AM_V_CXXLD)$(FileCheck_LINK) $(FileCheck_OBJECTS) $(FileCheck_LDADD) $(LIBS) +count$(EXEEXT): $(count_OBJECTS) $(count_DEPENDENCIES) + @rm -f count$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(count_OBJECTS) $(count_LDADD) $(LIBS) +llc$(EXEEXT): $(llc_OBJECTS) $(llc_DEPENDENCIES) + @rm -f llc$(EXEEXT) + $(AM_V_CXXLD)$(llc_LINK) $(llc_OBJECTS) $(llc_LDADD) $(LIBS) +lli$(EXEEXT): $(lli_OBJECTS) $(lli_DEPENDENCIES) + @rm -f lli$(EXEEXT) + $(AM_V_CXXLD)$(lli_LINK) $(lli_OBJECTS) $(lli_LDADD) $(LIBS) +llvm-as$(EXEEXT): $(llvm_as_OBJECTS) $(llvm_as_DEPENDENCIES) + @rm -f llvm-as$(EXEEXT) + $(AM_V_CXXLD)$(llvm_as_LINK) $(llvm_as_OBJECTS) $(llvm_as_LDADD) $(LIBS) +llvm-dis$(EXEEXT): $(llvm_dis_OBJECTS) $(llvm_dis_DEPENDENCIES) + @rm -f llvm-dis$(EXEEXT) + $(AM_V_CXXLD)$(llvm_dis_LINK) $(llvm_dis_OBJECTS) $(llvm_dis_LDADD) $(LIBS) +llvmunittest_ADT$(EXEEXT): $(llvmunittest_ADT_OBJECTS) $(llvmunittest_ADT_DEPENDENCIES) + @rm -f llvmunittest_ADT$(EXEEXT) + $(AM_V_CXXLD)$(llvmunittest_ADT_LINK) $(llvmunittest_ADT_OBJECTS) $(llvmunittest_ADT_LDADD) $(LIBS) +llvmunittest_ExecutionEngine$(EXEEXT): $(llvmunittest_ExecutionEngine_OBJECTS) $(llvmunittest_ExecutionEngine_DEPENDENCIES) + @rm -f llvmunittest_ExecutionEngine$(EXEEXT) + $(AM_V_CXXLD)$(llvmunittest_ExecutionEngine_LINK) $(llvmunittest_ExecutionEngine_OBJECTS) $(llvmunittest_ExecutionEngine_LDADD) $(LIBS) +llvmunittest_JIT$(EXEEXT): $(llvmunittest_JIT_OBJECTS) $(llvmunittest_JIT_DEPENDENCIES) + @rm -f llvmunittest_JIT$(EXEEXT) + $(AM_V_CXXLD)$(llvmunittest_JIT_LINK) $(llvmunittest_JIT_OBJECTS) $(llvmunittest_JIT_LDADD) $(LIBS) +llvmunittest_Support$(EXEEXT): $(llvmunittest_Support_OBJECTS) $(llvmunittest_Support_DEPENDENCIES) + @rm -f llvmunittest_Support$(EXEEXT) + $(AM_V_CXXLD)$(llvmunittest_Support_LINK) $(llvmunittest_Support_OBJECTS) $(llvmunittest_Support_LDADD) $(LIBS) +llvmunittest_VMCore$(EXEEXT): $(llvmunittest_VMCore_OBJECTS) $(llvmunittest_VMCore_DEPENDENCIES) + @rm -f llvmunittest_VMCore$(EXEEXT) + $(AM_V_CXXLD)$(llvmunittest_VMCore_LINK) $(llvmunittest_VMCore_OBJECTS) $(llvmunittest_VMCore_LDADD) $(LIBS) +not$(EXEEXT): $(not_OBJECTS) $(not_DEPENDENCIES) + @rm -f not$(EXEEXT) + $(AM_V_CXXLD)$(not_LINK) $(not_OBJECTS) $(not_LDADD) $(LIBS) +tblgen$(EXEEXT): $(tblgen_OBJECTS) $(tblgen_DEPENDENCIES) + @rm -f tblgen$(EXEEXT) + $(AM_V_CXXLD)$(tblgen_LINK) $(tblgen_OBJECTS) $(tblgen_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/FileCheck-FileCheck.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/count-count.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libclamavcxx_la-bytecode2llvm.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgoogletest_la-TestMain.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgoogletest_la-gtest-death-test.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgoogletest_la-gtest-filepath.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgoogletest_la-gtest-port.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgoogletest_la-gtest-test-part.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgoogletest_la-gtest-typed-test.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgoogletest_la-gtest.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmasmparser_la-LLLexer.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmasmparser_la-LLParser.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmasmparser_la-Parser.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmasmprinter_la-ARMAsmPrinter.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmasmprinter_la-ARMInstPrinter.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmasmprinter_la-ARMMCInstLower.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmasmprinter_la-ELFCodeEmitter.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmasmprinter_la-ELFWriter.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmasmprinter_la-MachOCodeEmitter.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmasmprinter_la-MachOWriter.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmasmprinter_la-OcamlGCPrinter.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmasmprinter_la-PPCAsmPrinter.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmasmprinter_la-X86ATTInstPrinter.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmasmprinter_la-X86AsmPrinter.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmasmprinter_la-X86COFFMachineModuleInfo.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmasmprinter_la-X86IntelInstPrinter.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmasmprinter_la-X86MCInstLower.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmbitreader_la-BitReader.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmbitreader_la-BitcodeReader.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmbitreader_la-Deserialize.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmbitreader_la-DeserializeAPFloat.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmbitreader_la-DeserializeAPInt.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmbitwriter_la-BitWriter.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmbitwriter_la-BitcodeWriter.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmbitwriter_la-BitcodeWriterPass.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmbitwriter_la-Serialize.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmbitwriter_la-SerializeAPFloat.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmbitwriter_la-SerializeAPInt.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmbitwriter_la-ValueEnumerator.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmcodegen_la-AggressiveAntiDepBreaker.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmcodegen_la-BranchFolding.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmcodegen_la-CodePlacementOpt.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmcodegen_la-CriticalAntiDepBreaker.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmcodegen_la-DeadMachineInstructionElim.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmcodegen_la-DwarfEHPrepare.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmcodegen_la-ELFCodeEmitter.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmcodegen_la-ELFWriter.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmcodegen_la-ExactHazardRecognizer.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmcodegen_la-GCMetadata.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmcodegen_la-GCMetadataPrinter.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmcodegen_la-GCStrategy.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmcodegen_la-IfConversion.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmcodegen_la-IntrinsicLowering.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmcodegen_la-LLVMTargetMachine.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmcodegen_la-LatencyPriorityQueue.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmcodegen_la-LiveInterval.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmcodegen_la-LiveIntervalAnalysis.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmcodegen_la-LiveStackAnalysis.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmcodegen_la-LiveVariables.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmcodegen_la-LowerSubregs.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmcodegen_la-MachineBasicBlock.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmcodegen_la-MachineDominators.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmcodegen_la-MachineFunction.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmcodegen_la-MachineFunctionAnalysis.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmcodegen_la-MachineFunctionPass.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmcodegen_la-MachineInstr.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmcodegen_la-MachineLICM.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmcodegen_la-MachineLoopInfo.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmcodegen_la-MachineModuleInfo.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmcodegen_la-MachineModuleInfoImpls.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmcodegen_la-MachinePassRegistry.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmcodegen_la-MachineRegisterInfo.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmcodegen_la-MachineSink.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmcodegen_la-MachineVerifier.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmcodegen_la-ObjectCodeEmitter.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmcodegen_la-OcamlGC.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmcodegen_la-PHIElimination.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmcodegen_la-Passes.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmcodegen_la-PostRASchedulerList.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmcodegen_la-PreAllocSplitting.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmcodegen_la-ProcessImplicitDefs.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmcodegen_la-PrologEpilogInserter.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmcodegen_la-PseudoSourceValue.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmcodegen_la-RegAllocLinearScan.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmcodegen_la-RegAllocLocal.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmcodegen_la-RegAllocPBQP.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmcodegen_la-RegisterCoalescer.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmcodegen_la-RegisterScavenging.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmcodegen_la-ScheduleDAG.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmcodegen_la-ScheduleDAGEmit.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmcodegen_la-ScheduleDAGInstrs.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmcodegen_la-ScheduleDAGPrinter.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmcodegen_la-ShadowStackGC.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmcodegen_la-ShrinkWrapping.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmcodegen_la-SimpleRegisterCoalescing.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmcodegen_la-SjLjEHPrepare.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmcodegen_la-SlotIndexes.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmcodegen_la-Spiller.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmcodegen_la-StackProtector.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmcodegen_la-StackSlotColoring.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmcodegen_la-StrongPHIElimination.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmcodegen_la-TailDuplication.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmcodegen_la-TargetInstrInfoImpl.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmcodegen_la-TwoAddressInstructionPass.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmcodegen_la-UnreachableBlockElim.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmcodegen_la-VirtRegMap.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmcodegen_la-VirtRegRewriter.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmcore_la-AsmWriter.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmcore_la-Attributes.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmcore_la-AutoUpgrade.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmcore_la-BasicBlock.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmcore_la-ConstantFold.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmcore_la-Constants.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmcore_la-Core.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmcore_la-Dominators.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmcore_la-Function.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmcore_la-Globals.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmcore_la-InlineAsm.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmcore_la-Instruction.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmcore_la-Instructions.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmcore_la-IntrinsicInst.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmcore_la-LLVMContext.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmcore_la-LeakDetector.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmcore_la-Mangler.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmcore_la-Metadata.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmcore_la-Module.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmcore_la-ModuleProvider.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmcore_la-Pass.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmcore_la-PassManager.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmcore_la-PrintModulePass.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmcore_la-Type.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmcore_la-TypeSymbolTable.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmcore_la-Use.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmcore_la-Value.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmcore_la-ValueSymbolTable.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmcore_la-ValueTypes.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmcore_la-Verifier.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmexecutionengine_la-ExecutionEngine.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmexecutionengine_la-Intercept.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmexecutionengine_la-JIT.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmexecutionengine_la-JITDebugRegisterer.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmexecutionengine_la-JITDwarfEmitter.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmexecutionengine_la-JITEmitter.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmexecutionengine_la-JITMemoryManager.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmexecutionengine_la-TargetSelect.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvminterpreter_la-Execution.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvminterpreter_la-ExternalFunctions.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvminterpreter_la-Interpreter.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmipa_la-AliasAnalysis.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmipa_la-AliasSetTracker.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmipa_la-BasicAliasAnalysis.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmipa_la-CallGraph.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmipa_la-CaptureTracking.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmipa_la-ConstantFolding.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmipa_la-DebugInfo.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmipa_la-IVUsers.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmipa_la-InstructionSimplify.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmipa_la-LiveValues.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmipa_la-LoopDependenceAnalysis.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmipa_la-LoopInfo.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmipa_la-LoopPass.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmipa_la-MemoryBuiltins.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmipa_la-MemoryDependenceAnalysis.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmipa_la-ProfileInfo.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmipa_la-ScalarEvolution.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmipa_la-ScalarEvolutionExpander.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmipa_la-ValueTracking.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmmc_la-MCAsmInfo.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmmc_la-MCAsmInfoCOFF.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmmc_la-MCAsmInfoDarwin.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmmc_la-MCAsmLexer.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmmc_la-MCAsmParser.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmmc_la-MCAsmStreamer.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmmc_la-MCAssembler.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmmc_la-MCCodeEmitter.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmmc_la-MCContext.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmmc_la-MCExpr.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmmc_la-MCInst.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmmc_la-MCMachOStreamer.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmmc_la-MCNullStreamer.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmmc_la-MCSection.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmmc_la-MCSectionELF.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmmc_la-MCSectionMachO.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmmc_la-MCStreamer.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmmc_la-MCSymbol.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmmc_la-MCValue.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmmc_la-TargetAsmParser.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmscalar_la-CodeGenPrepare.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmscalar_la-ConstantProp.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmscalar_la-DCE.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmscalar_la-GEPSplitter.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmscalar_la-GVN.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmscalar_la-LoopStrengthReduce.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmscalar_la-SimplifyCFGPass.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmsdag_la-AsmPrinter.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmsdag_la-CallingConvLower.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmsdag_la-DAGCombiner.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmsdag_la-DIE.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmsdag_la-DwarfDebug.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmsdag_la-DwarfException.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmsdag_la-DwarfLabel.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmsdag_la-DwarfPrinter.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmsdag_la-DwarfWriter.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmsdag_la-FastISel.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmsdag_la-FunctionLoweringInfo.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmsdag_la-InstrEmitter.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmsdag_la-LegalizeDAG.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmsdag_la-LegalizeFloatTypes.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmsdag_la-LegalizeIntegerTypes.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmsdag_la-LegalizeTypes.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmsdag_la-LegalizeTypesGeneric.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmsdag_la-LegalizeVectorOps.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmsdag_la-LegalizeVectorTypes.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmsdag_la-ScheduleDAGFast.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmsdag_la-ScheduleDAGList.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmsdag_la-ScheduleDAGRRList.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmsdag_la-ScheduleDAGSDNodes.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmsdag_la-SelectionDAG.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmsdag_la-SelectionDAGBuilder.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmsdag_la-SelectionDAGISel.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmsdag_la-SelectionDAGPrinter.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmsdag_la-TargetLowering.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmsupport_la-APFloat.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmsupport_la-APInt.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmsupport_la-APSInt.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmsupport_la-Allocator.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmsupport_la-CommandLine.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmsupport_la-ConstantRange.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmsupport_la-Debug.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmsupport_la-Dwarf.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmsupport_la-ErrorHandling.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmsupport_la-FileUtilities.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmsupport_la-FoldingSet.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmsupport_la-FormattedStream.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmsupport_la-GraphWriter.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmsupport_la-IsInf.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmsupport_la-IsNAN.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmsupport_la-ManagedStatic.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmsupport_la-MemoryBuffer.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmsupport_la-PluginLoader.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmsupport_la-PrettyStackTrace.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmsupport_la-Regex.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmsupport_la-SlowOperationInformer.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmsupport_la-SmallPtrSet.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmsupport_la-SourceMgr.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmsupport_la-Statistic.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmsupport_la-StringExtras.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmsupport_la-StringMap.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmsupport_la-StringPool.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmsupport_la-StringRef.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmsupport_la-SystemUtils.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmsupport_la-TargetRegistry.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmsupport_la-Timer.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmsupport_la-Triple.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmsupport_la-Twine.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmsupport_la-raw_os_ostream.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmsupport_la-raw_ostream.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmsupport_la-regcomp.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmsupport_la-regerror.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmsupport_la-regexec.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmsupport_la-regfree.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmsupport_la-regstrlcpy.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmsystem_la-Alarm.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmsystem_la-Atomic.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmsystem_la-Disassembler.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmsystem_la-DynamicLibrary.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmsystem_la-Errno.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmsystem_la-Host.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmsystem_la-IncludeFile.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmsystem_la-Memory.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmsystem_la-Mutex.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmsystem_la-Path.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmsystem_la-Process.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmsystem_la-Program.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmsystem_la-RWMutex.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmsystem_la-Signals.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmsystem_la-ThreadLocal.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmsystem_la-Threading.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmsystem_la-TimeValue.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmtarget_la-SubtargetFeature.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmtarget_la-Target.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmtarget_la-TargetData.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmtarget_la-TargetELFWriterInfo.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmtarget_la-TargetFrameInfo.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmtarget_la-TargetInstrInfo.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmtarget_la-TargetIntrinsicInfo.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmtarget_la-TargetLoweringObjectFile.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmtarget_la-TargetMachOWriterInfo.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmtarget_la-TargetMachine.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmtarget_la-TargetRegisterInfo.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmtarget_la-TargetSubtarget.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmtargetarm_la-ARMBaseInstrInfo.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmtargetarm_la-ARMBaseRegisterInfo.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmtargetarm_la-ARMCodeEmitter.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmtargetarm_la-ARMConstantIslandPass.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmtargetarm_la-ARMConstantPoolValue.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmtargetarm_la-ARMExpandPseudoInsts.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmtargetarm_la-ARMISelDAGToDAG.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmtargetarm_la-ARMISelLowering.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmtargetarm_la-ARMInstrInfo.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmtargetarm_la-ARMJITInfo.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmtargetarm_la-ARMLoadStoreOptimizer.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmtargetarm_la-ARMMCAsmInfo.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmtargetarm_la-ARMRegisterInfo.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmtargetarm_la-ARMSubtarget.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmtargetarm_la-ARMTargetInfo.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmtargetarm_la-ARMTargetMachine.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmtargetarm_la-NEONMoveFix.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmtargetarm_la-NEONPreAllocPass.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmtargetarm_la-Thumb1InstrInfo.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmtargetarm_la-Thumb1RegisterInfo.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmtargetarm_la-Thumb2ITBlockPass.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmtargetarm_la-Thumb2InstrInfo.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmtargetarm_la-Thumb2RegisterInfo.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmtargetarm_la-Thumb2SizeReduction.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmtargetppc_la-PPCBranchSelector.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmtargetppc_la-PPCCodeEmitter.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmtargetppc_la-PPCHazardRecognizers.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmtargetppc_la-PPCISelDAGToDAG.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmtargetppc_la-PPCISelLowering.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmtargetppc_la-PPCInstrInfo.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmtargetppc_la-PPCJITInfo.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmtargetppc_la-PPCMCAsmInfo.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmtargetppc_la-PPCMachOWriterInfo.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmtargetppc_la-PPCPredicates.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmtargetppc_la-PPCRegisterInfo.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmtargetppc_la-PPCSubtarget.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmtargetppc_la-PPCTargetMachine.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmtargetppc_la-PowerPCTargetInfo.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmtargetx86_la-X86CodeEmitter.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmtargetx86_la-X86ELFWriterInfo.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmtargetx86_la-X86FastISel.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmtargetx86_la-X86FloatingPoint.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmtargetx86_la-X86FloatingPointRegKill.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmtargetx86_la-X86ISelDAGToDAG.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmtargetx86_la-X86ISelLowering.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmtargetx86_la-X86InstrInfo.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmtargetx86_la-X86JITInfo.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmtargetx86_la-X86MCAsmInfo.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmtargetx86_la-X86RegisterInfo.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmtargetx86_la-X86Subtarget.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmtargetx86_la-X86TargetInfo.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmtargetx86_la-X86TargetMachine.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmtargetx86_la-X86TargetObjectFile.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmtransformutils_la-AddrModeMatcher.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmtransformutils_la-BasicBlockUtils.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmtransformutils_la-BreakCriticalEdges.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmtransformutils_la-DemoteRegToStack.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmtransformutils_la-LCSSA.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmtransformutils_la-Local.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmtransformutils_la-LoopSimplify.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmtransformutils_la-LowerInvoke.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmtransformutils_la-LowerSwitch.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmtransformutils_la-Mem2Reg.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmtransformutils_la-PromoteMemoryToRegister.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmtransformutils_la-SSAUpdater.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmtransformutils_la-SimplifyCFG.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmtransformutils_la-UnifyFunctionExitNodes.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/llc-MCInstPrinter.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/llc-llc.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lli-OProfileJITEventListener.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lli-lli.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/llvm_as-llvm-as.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/llvm_dis-llvm-dis.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/llvmunittest_ADT-APFloatTest.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/llvmunittest_ADT-APIntTest.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/llvmunittest_ADT-DenseMapTest.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/llvmunittest_ADT-DenseSetTest.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/llvmunittest_ADT-ImmutableSetTest.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/llvmunittest_ADT-SmallStringTest.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/llvmunittest_ADT-SmallVectorTest.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/llvmunittest_ADT-SparseBitVectorTest.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/llvmunittest_ADT-StringMapTest.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/llvmunittest_ADT-StringRefTest.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/llvmunittest_ADT-TripleTest.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/llvmunittest_ADT-TwineTest.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/llvmunittest_ExecutionEngine-ExecutionEngineTest.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/llvmunittest_JIT-JITEventListenerTest.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/llvmunittest_JIT-JITMemoryManagerTest.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/llvmunittest_JIT-JITTest.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/llvmunittest_Support-AllocatorTest.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/llvmunittest_Support-ConstantRangeTest.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/llvmunittest_Support-MathExtrasTest.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/llvmunittest_Support-RegexTest.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/llvmunittest_Support-TypeBuilderTest.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/llvmunittest_Support-ValueHandleTest.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/llvmunittest_Support-raw_ostream_test.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/llvmunittest_VMCore-CallGraphSCCPass.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/llvmunittest_VMCore-ConstantsTest.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/llvmunittest_VMCore-MetadataTest.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/llvmunittest_VMCore-PassManagerTest.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/not-not.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tblgen-AsmMatcherEmitter.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tblgen-AsmWriterEmitter.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tblgen-CallingConvEmitter.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tblgen-ClangDiagnosticsEmitter.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tblgen-CodeEmitterGen.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tblgen-CodeGenDAGPatterns.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tblgen-CodeGenInstruction.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tblgen-CodeGenTarget.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tblgen-DAGISelEmitter.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tblgen-DisassemblerEmitter.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tblgen-FastISelEmitter.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tblgen-InstrEnumEmitter.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tblgen-InstrInfoEmitter.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tblgen-IntrinsicEmitter.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tblgen-LLVMCConfigurationEmitter.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tblgen-OptParserEmitter.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tblgen-Record.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tblgen-RegisterInfoEmitter.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tblgen-SubtargetEmitter.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tblgen-TGLexer.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tblgen-TGParser.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tblgen-TGValueTypes.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tblgen-TableGen.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tblgen-TableGenBackend.Po@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< + +libllvmsupport_la-regcomp.lo: llvm/lib/Support/regcomp.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsupport_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libllvmsupport_la-regcomp.lo -MD -MP -MF $(DEPDIR)/libllvmsupport_la-regcomp.Tpo -c -o libllvmsupport_la-regcomp.lo `test -f 'llvm/lib/Support/regcomp.c' || echo '$(srcdir)/'`llvm/lib/Support/regcomp.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmsupport_la-regcomp.Tpo $(DEPDIR)/libllvmsupport_la-regcomp.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='llvm/lib/Support/regcomp.c' object='libllvmsupport_la-regcomp.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsupport_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libllvmsupport_la-regcomp.lo `test -f 'llvm/lib/Support/regcomp.c' || echo '$(srcdir)/'`llvm/lib/Support/regcomp.c + +libllvmsupport_la-regerror.lo: llvm/lib/Support/regerror.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsupport_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libllvmsupport_la-regerror.lo -MD -MP -MF $(DEPDIR)/libllvmsupport_la-regerror.Tpo -c -o libllvmsupport_la-regerror.lo `test -f 'llvm/lib/Support/regerror.c' || echo '$(srcdir)/'`llvm/lib/Support/regerror.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmsupport_la-regerror.Tpo $(DEPDIR)/libllvmsupport_la-regerror.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='llvm/lib/Support/regerror.c' object='libllvmsupport_la-regerror.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsupport_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libllvmsupport_la-regerror.lo `test -f 'llvm/lib/Support/regerror.c' || echo '$(srcdir)/'`llvm/lib/Support/regerror.c + +libllvmsupport_la-regexec.lo: llvm/lib/Support/regexec.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsupport_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libllvmsupport_la-regexec.lo -MD -MP -MF $(DEPDIR)/libllvmsupport_la-regexec.Tpo -c -o libllvmsupport_la-regexec.lo `test -f 'llvm/lib/Support/regexec.c' || echo '$(srcdir)/'`llvm/lib/Support/regexec.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmsupport_la-regexec.Tpo $(DEPDIR)/libllvmsupport_la-regexec.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='llvm/lib/Support/regexec.c' object='libllvmsupport_la-regexec.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsupport_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libllvmsupport_la-regexec.lo `test -f 'llvm/lib/Support/regexec.c' || echo '$(srcdir)/'`llvm/lib/Support/regexec.c + +libllvmsupport_la-regfree.lo: llvm/lib/Support/regfree.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsupport_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libllvmsupport_la-regfree.lo -MD -MP -MF $(DEPDIR)/libllvmsupport_la-regfree.Tpo -c -o libllvmsupport_la-regfree.lo `test -f 'llvm/lib/Support/regfree.c' || echo '$(srcdir)/'`llvm/lib/Support/regfree.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmsupport_la-regfree.Tpo $(DEPDIR)/libllvmsupport_la-regfree.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='llvm/lib/Support/regfree.c' object='libllvmsupport_la-regfree.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsupport_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libllvmsupport_la-regfree.lo `test -f 'llvm/lib/Support/regfree.c' || echo '$(srcdir)/'`llvm/lib/Support/regfree.c + +libllvmsupport_la-regstrlcpy.lo: llvm/lib/Support/regstrlcpy.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsupport_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libllvmsupport_la-regstrlcpy.lo -MD -MP -MF $(DEPDIR)/libllvmsupport_la-regstrlcpy.Tpo -c -o libllvmsupport_la-regstrlcpy.lo `test -f 'llvm/lib/Support/regstrlcpy.c' || echo '$(srcdir)/'`llvm/lib/Support/regstrlcpy.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmsupport_la-regstrlcpy.Tpo $(DEPDIR)/libllvmsupport_la-regstrlcpy.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='llvm/lib/Support/regstrlcpy.c' object='libllvmsupport_la-regstrlcpy.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsupport_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libllvmsupport_la-regstrlcpy.lo `test -f 'llvm/lib/Support/regstrlcpy.c' || echo '$(srcdir)/'`llvm/lib/Support/regstrlcpy.c + +count-count.o: llvm/utils/count/count.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(count_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT count-count.o -MD -MP -MF $(DEPDIR)/count-count.Tpo -c -o count-count.o `test -f 'llvm/utils/count/count.c' || echo '$(srcdir)/'`llvm/utils/count/count.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/count-count.Tpo $(DEPDIR)/count-count.Po +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='llvm/utils/count/count.c' object='count-count.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(count_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o count-count.o `test -f 'llvm/utils/count/count.c' || echo '$(srcdir)/'`llvm/utils/count/count.c + +count-count.obj: llvm/utils/count/count.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(count_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT count-count.obj -MD -MP -MF $(DEPDIR)/count-count.Tpo -c -o count-count.obj `if test -f 'llvm/utils/count/count.c'; then $(CYGPATH_W) 'llvm/utils/count/count.c'; else $(CYGPATH_W) '$(srcdir)/llvm/utils/count/count.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/count-count.Tpo $(DEPDIR)/count-count.Po +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='llvm/utils/count/count.c' object='count-count.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(count_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o count-count.obj `if test -f 'llvm/utils/count/count.c'; then $(CYGPATH_W) 'llvm/utils/count/count.c'; else $(CYGPATH_W) '$(srcdir)/llvm/utils/count/count.c'; fi` + +.cc.o: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ $< + +.cc.obj: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.cc.lo: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LTCXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LTCXXCOMPILE) -c -o $@ $< + +libclamavcxx_la-bytecode2llvm.lo: bytecode2llvm.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libclamavcxx_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libclamavcxx_la-bytecode2llvm.lo -MD -MP -MF $(DEPDIR)/libclamavcxx_la-bytecode2llvm.Tpo -c -o libclamavcxx_la-bytecode2llvm.lo `test -f 'bytecode2llvm.cpp' || echo '$(srcdir)/'`bytecode2llvm.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libclamavcxx_la-bytecode2llvm.Tpo $(DEPDIR)/libclamavcxx_la-bytecode2llvm.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='bytecode2llvm.cpp' object='libclamavcxx_la-bytecode2llvm.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libclamavcxx_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libclamavcxx_la-bytecode2llvm.lo `test -f 'bytecode2llvm.cpp' || echo '$(srcdir)/'`bytecode2llvm.cpp + +libgoogletest_la-gtest-death-test.lo: llvm/utils/unittest/googletest/gtest-death-test.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgoogletest_la_CPPFLAGS) $(CPPFLAGS) $(libgoogletest_la_CXXFLAGS) $(CXXFLAGS) -MT libgoogletest_la-gtest-death-test.lo -MD -MP -MF $(DEPDIR)/libgoogletest_la-gtest-death-test.Tpo -c -o libgoogletest_la-gtest-death-test.lo `test -f 'llvm/utils/unittest/googletest/gtest-death-test.cc' || echo '$(srcdir)/'`llvm/utils/unittest/googletest/gtest-death-test.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgoogletest_la-gtest-death-test.Tpo $(DEPDIR)/libgoogletest_la-gtest-death-test.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/utils/unittest/googletest/gtest-death-test.cc' object='libgoogletest_la-gtest-death-test.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgoogletest_la_CPPFLAGS) $(CPPFLAGS) $(libgoogletest_la_CXXFLAGS) $(CXXFLAGS) -c -o libgoogletest_la-gtest-death-test.lo `test -f 'llvm/utils/unittest/googletest/gtest-death-test.cc' || echo '$(srcdir)/'`llvm/utils/unittest/googletest/gtest-death-test.cc + +libgoogletest_la-gtest-filepath.lo: llvm/utils/unittest/googletest/gtest-filepath.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgoogletest_la_CPPFLAGS) $(CPPFLAGS) $(libgoogletest_la_CXXFLAGS) $(CXXFLAGS) -MT libgoogletest_la-gtest-filepath.lo -MD -MP -MF $(DEPDIR)/libgoogletest_la-gtest-filepath.Tpo -c -o libgoogletest_la-gtest-filepath.lo `test -f 'llvm/utils/unittest/googletest/gtest-filepath.cc' || echo '$(srcdir)/'`llvm/utils/unittest/googletest/gtest-filepath.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgoogletest_la-gtest-filepath.Tpo $(DEPDIR)/libgoogletest_la-gtest-filepath.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/utils/unittest/googletest/gtest-filepath.cc' object='libgoogletest_la-gtest-filepath.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgoogletest_la_CPPFLAGS) $(CPPFLAGS) $(libgoogletest_la_CXXFLAGS) $(CXXFLAGS) -c -o libgoogletest_la-gtest-filepath.lo `test -f 'llvm/utils/unittest/googletest/gtest-filepath.cc' || echo '$(srcdir)/'`llvm/utils/unittest/googletest/gtest-filepath.cc + +libgoogletest_la-gtest-port.lo: llvm/utils/unittest/googletest/gtest-port.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgoogletest_la_CPPFLAGS) $(CPPFLAGS) $(libgoogletest_la_CXXFLAGS) $(CXXFLAGS) -MT libgoogletest_la-gtest-port.lo -MD -MP -MF $(DEPDIR)/libgoogletest_la-gtest-port.Tpo -c -o libgoogletest_la-gtest-port.lo `test -f 'llvm/utils/unittest/googletest/gtest-port.cc' || echo '$(srcdir)/'`llvm/utils/unittest/googletest/gtest-port.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgoogletest_la-gtest-port.Tpo $(DEPDIR)/libgoogletest_la-gtest-port.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/utils/unittest/googletest/gtest-port.cc' object='libgoogletest_la-gtest-port.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgoogletest_la_CPPFLAGS) $(CPPFLAGS) $(libgoogletest_la_CXXFLAGS) $(CXXFLAGS) -c -o libgoogletest_la-gtest-port.lo `test -f 'llvm/utils/unittest/googletest/gtest-port.cc' || echo '$(srcdir)/'`llvm/utils/unittest/googletest/gtest-port.cc + +libgoogletest_la-gtest-test-part.lo: llvm/utils/unittest/googletest/gtest-test-part.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgoogletest_la_CPPFLAGS) $(CPPFLAGS) $(libgoogletest_la_CXXFLAGS) $(CXXFLAGS) -MT libgoogletest_la-gtest-test-part.lo -MD -MP -MF $(DEPDIR)/libgoogletest_la-gtest-test-part.Tpo -c -o libgoogletest_la-gtest-test-part.lo `test -f 'llvm/utils/unittest/googletest/gtest-test-part.cc' || echo '$(srcdir)/'`llvm/utils/unittest/googletest/gtest-test-part.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgoogletest_la-gtest-test-part.Tpo $(DEPDIR)/libgoogletest_la-gtest-test-part.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/utils/unittest/googletest/gtest-test-part.cc' object='libgoogletest_la-gtest-test-part.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgoogletest_la_CPPFLAGS) $(CPPFLAGS) $(libgoogletest_la_CXXFLAGS) $(CXXFLAGS) -c -o libgoogletest_la-gtest-test-part.lo `test -f 'llvm/utils/unittest/googletest/gtest-test-part.cc' || echo '$(srcdir)/'`llvm/utils/unittest/googletest/gtest-test-part.cc + +libgoogletest_la-gtest-typed-test.lo: llvm/utils/unittest/googletest/gtest-typed-test.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgoogletest_la_CPPFLAGS) $(CPPFLAGS) $(libgoogletest_la_CXXFLAGS) $(CXXFLAGS) -MT libgoogletest_la-gtest-typed-test.lo -MD -MP -MF $(DEPDIR)/libgoogletest_la-gtest-typed-test.Tpo -c -o libgoogletest_la-gtest-typed-test.lo `test -f 'llvm/utils/unittest/googletest/gtest-typed-test.cc' || echo '$(srcdir)/'`llvm/utils/unittest/googletest/gtest-typed-test.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgoogletest_la-gtest-typed-test.Tpo $(DEPDIR)/libgoogletest_la-gtest-typed-test.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/utils/unittest/googletest/gtest-typed-test.cc' object='libgoogletest_la-gtest-typed-test.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgoogletest_la_CPPFLAGS) $(CPPFLAGS) $(libgoogletest_la_CXXFLAGS) $(CXXFLAGS) -c -o libgoogletest_la-gtest-typed-test.lo `test -f 'llvm/utils/unittest/googletest/gtest-typed-test.cc' || echo '$(srcdir)/'`llvm/utils/unittest/googletest/gtest-typed-test.cc + +libgoogletest_la-gtest.lo: llvm/utils/unittest/googletest/gtest.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgoogletest_la_CPPFLAGS) $(CPPFLAGS) $(libgoogletest_la_CXXFLAGS) $(CXXFLAGS) -MT libgoogletest_la-gtest.lo -MD -MP -MF $(DEPDIR)/libgoogletest_la-gtest.Tpo -c -o libgoogletest_la-gtest.lo `test -f 'llvm/utils/unittest/googletest/gtest.cc' || echo '$(srcdir)/'`llvm/utils/unittest/googletest/gtest.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgoogletest_la-gtest.Tpo $(DEPDIR)/libgoogletest_la-gtest.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/utils/unittest/googletest/gtest.cc' object='libgoogletest_la-gtest.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgoogletest_la_CPPFLAGS) $(CPPFLAGS) $(libgoogletest_la_CXXFLAGS) $(CXXFLAGS) -c -o libgoogletest_la-gtest.lo `test -f 'llvm/utils/unittest/googletest/gtest.cc' || echo '$(srcdir)/'`llvm/utils/unittest/googletest/gtest.cc + +libgoogletest_la-TestMain.lo: llvm/utils/unittest/UnitTestMain/TestMain.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgoogletest_la_CPPFLAGS) $(CPPFLAGS) $(libgoogletest_la_CXXFLAGS) $(CXXFLAGS) -MT libgoogletest_la-TestMain.lo -MD -MP -MF $(DEPDIR)/libgoogletest_la-TestMain.Tpo -c -o libgoogletest_la-TestMain.lo `test -f 'llvm/utils/unittest/UnitTestMain/TestMain.cpp' || echo '$(srcdir)/'`llvm/utils/unittest/UnitTestMain/TestMain.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgoogletest_la-TestMain.Tpo $(DEPDIR)/libgoogletest_la-TestMain.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/utils/unittest/UnitTestMain/TestMain.cpp' object='libgoogletest_la-TestMain.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgoogletest_la_CPPFLAGS) $(CPPFLAGS) $(libgoogletest_la_CXXFLAGS) $(CXXFLAGS) -c -o libgoogletest_la-TestMain.lo `test -f 'llvm/utils/unittest/UnitTestMain/TestMain.cpp' || echo '$(srcdir)/'`llvm/utils/unittest/UnitTestMain/TestMain.cpp + +libllvmasmparser_la-LLLexer.lo: llvm/lib/AsmParser/LLLexer.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmasmparser_la_CPPFLAGS) $(CPPFLAGS) $(libllvmasmparser_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmasmparser_la-LLLexer.lo -MD -MP -MF $(DEPDIR)/libllvmasmparser_la-LLLexer.Tpo -c -o libllvmasmparser_la-LLLexer.lo `test -f 'llvm/lib/AsmParser/LLLexer.cpp' || echo '$(srcdir)/'`llvm/lib/AsmParser/LLLexer.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmasmparser_la-LLLexer.Tpo $(DEPDIR)/libllvmasmparser_la-LLLexer.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/AsmParser/LLLexer.cpp' object='libllvmasmparser_la-LLLexer.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmasmparser_la_CPPFLAGS) $(CPPFLAGS) $(libllvmasmparser_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmasmparser_la-LLLexer.lo `test -f 'llvm/lib/AsmParser/LLLexer.cpp' || echo '$(srcdir)/'`llvm/lib/AsmParser/LLLexer.cpp + +libllvmasmparser_la-LLParser.lo: llvm/lib/AsmParser/LLParser.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmasmparser_la_CPPFLAGS) $(CPPFLAGS) $(libllvmasmparser_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmasmparser_la-LLParser.lo -MD -MP -MF $(DEPDIR)/libllvmasmparser_la-LLParser.Tpo -c -o libllvmasmparser_la-LLParser.lo `test -f 'llvm/lib/AsmParser/LLParser.cpp' || echo '$(srcdir)/'`llvm/lib/AsmParser/LLParser.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmasmparser_la-LLParser.Tpo $(DEPDIR)/libllvmasmparser_la-LLParser.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/AsmParser/LLParser.cpp' object='libllvmasmparser_la-LLParser.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmasmparser_la_CPPFLAGS) $(CPPFLAGS) $(libllvmasmparser_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmasmparser_la-LLParser.lo `test -f 'llvm/lib/AsmParser/LLParser.cpp' || echo '$(srcdir)/'`llvm/lib/AsmParser/LLParser.cpp + +libllvmasmparser_la-Parser.lo: llvm/lib/AsmParser/Parser.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmasmparser_la_CPPFLAGS) $(CPPFLAGS) $(libllvmasmparser_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmasmparser_la-Parser.lo -MD -MP -MF $(DEPDIR)/libllvmasmparser_la-Parser.Tpo -c -o libllvmasmparser_la-Parser.lo `test -f 'llvm/lib/AsmParser/Parser.cpp' || echo '$(srcdir)/'`llvm/lib/AsmParser/Parser.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmasmparser_la-Parser.Tpo $(DEPDIR)/libllvmasmparser_la-Parser.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/AsmParser/Parser.cpp' object='libllvmasmparser_la-Parser.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmasmparser_la_CPPFLAGS) $(CPPFLAGS) $(libllvmasmparser_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmasmparser_la-Parser.lo `test -f 'llvm/lib/AsmParser/Parser.cpp' || echo '$(srcdir)/'`llvm/lib/AsmParser/Parser.cpp + +libllvmasmprinter_la-OcamlGCPrinter.lo: llvm/lib/CodeGen/AsmPrinter/OcamlGCPrinter.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmasmprinter_la_CPPFLAGS) $(CPPFLAGS) $(libllvmasmprinter_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmasmprinter_la-OcamlGCPrinter.lo -MD -MP -MF $(DEPDIR)/libllvmasmprinter_la-OcamlGCPrinter.Tpo -c -o libllvmasmprinter_la-OcamlGCPrinter.lo `test -f 'llvm/lib/CodeGen/AsmPrinter/OcamlGCPrinter.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/AsmPrinter/OcamlGCPrinter.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmasmprinter_la-OcamlGCPrinter.Tpo $(DEPDIR)/libllvmasmprinter_la-OcamlGCPrinter.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/CodeGen/AsmPrinter/OcamlGCPrinter.cpp' object='libllvmasmprinter_la-OcamlGCPrinter.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmasmprinter_la_CPPFLAGS) $(CPPFLAGS) $(libllvmasmprinter_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmasmprinter_la-OcamlGCPrinter.lo `test -f 'llvm/lib/CodeGen/AsmPrinter/OcamlGCPrinter.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/AsmPrinter/OcamlGCPrinter.cpp + +libllvmasmprinter_la-ELFCodeEmitter.lo: llvm/lib/CodeGen/ELFCodeEmitter.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmasmprinter_la_CPPFLAGS) $(CPPFLAGS) $(libllvmasmprinter_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmasmprinter_la-ELFCodeEmitter.lo -MD -MP -MF $(DEPDIR)/libllvmasmprinter_la-ELFCodeEmitter.Tpo -c -o libllvmasmprinter_la-ELFCodeEmitter.lo `test -f 'llvm/lib/CodeGen/ELFCodeEmitter.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/ELFCodeEmitter.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmasmprinter_la-ELFCodeEmitter.Tpo $(DEPDIR)/libllvmasmprinter_la-ELFCodeEmitter.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/CodeGen/ELFCodeEmitter.cpp' object='libllvmasmprinter_la-ELFCodeEmitter.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmasmprinter_la_CPPFLAGS) $(CPPFLAGS) $(libllvmasmprinter_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmasmprinter_la-ELFCodeEmitter.lo `test -f 'llvm/lib/CodeGen/ELFCodeEmitter.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/ELFCodeEmitter.cpp + +libllvmasmprinter_la-ELFWriter.lo: llvm/lib/CodeGen/ELFWriter.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmasmprinter_la_CPPFLAGS) $(CPPFLAGS) $(libllvmasmprinter_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmasmprinter_la-ELFWriter.lo -MD -MP -MF $(DEPDIR)/libllvmasmprinter_la-ELFWriter.Tpo -c -o libllvmasmprinter_la-ELFWriter.lo `test -f 'llvm/lib/CodeGen/ELFWriter.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/ELFWriter.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmasmprinter_la-ELFWriter.Tpo $(DEPDIR)/libllvmasmprinter_la-ELFWriter.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/CodeGen/ELFWriter.cpp' object='libllvmasmprinter_la-ELFWriter.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmasmprinter_la_CPPFLAGS) $(CPPFLAGS) $(libllvmasmprinter_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmasmprinter_la-ELFWriter.lo `test -f 'llvm/lib/CodeGen/ELFWriter.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/ELFWriter.cpp + +libllvmasmprinter_la-MachOCodeEmitter.lo: llvm/lib/CodeGen/MachOCodeEmitter.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmasmprinter_la_CPPFLAGS) $(CPPFLAGS) $(libllvmasmprinter_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmasmprinter_la-MachOCodeEmitter.lo -MD -MP -MF $(DEPDIR)/libllvmasmprinter_la-MachOCodeEmitter.Tpo -c -o libllvmasmprinter_la-MachOCodeEmitter.lo `test -f 'llvm/lib/CodeGen/MachOCodeEmitter.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/MachOCodeEmitter.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmasmprinter_la-MachOCodeEmitter.Tpo $(DEPDIR)/libllvmasmprinter_la-MachOCodeEmitter.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/CodeGen/MachOCodeEmitter.cpp' object='libllvmasmprinter_la-MachOCodeEmitter.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmasmprinter_la_CPPFLAGS) $(CPPFLAGS) $(libllvmasmprinter_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmasmprinter_la-MachOCodeEmitter.lo `test -f 'llvm/lib/CodeGen/MachOCodeEmitter.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/MachOCodeEmitter.cpp + +libllvmasmprinter_la-MachOWriter.lo: llvm/lib/CodeGen/MachOWriter.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmasmprinter_la_CPPFLAGS) $(CPPFLAGS) $(libllvmasmprinter_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmasmprinter_la-MachOWriter.lo -MD -MP -MF $(DEPDIR)/libllvmasmprinter_la-MachOWriter.Tpo -c -o libllvmasmprinter_la-MachOWriter.lo `test -f 'llvm/lib/CodeGen/MachOWriter.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/MachOWriter.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmasmprinter_la-MachOWriter.Tpo $(DEPDIR)/libllvmasmprinter_la-MachOWriter.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/CodeGen/MachOWriter.cpp' object='libllvmasmprinter_la-MachOWriter.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmasmprinter_la_CPPFLAGS) $(CPPFLAGS) $(libllvmasmprinter_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmasmprinter_la-MachOWriter.lo `test -f 'llvm/lib/CodeGen/MachOWriter.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/MachOWriter.cpp + +libllvmasmprinter_la-X86AsmPrinter.lo: llvm/lib/Target/X86/AsmPrinter/X86AsmPrinter.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmasmprinter_la_CPPFLAGS) $(CPPFLAGS) $(libllvmasmprinter_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmasmprinter_la-X86AsmPrinter.lo -MD -MP -MF $(DEPDIR)/libllvmasmprinter_la-X86AsmPrinter.Tpo -c -o libllvmasmprinter_la-X86AsmPrinter.lo `test -f 'llvm/lib/Target/X86/AsmPrinter/X86AsmPrinter.cpp' || echo '$(srcdir)/'`llvm/lib/Target/X86/AsmPrinter/X86AsmPrinter.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmasmprinter_la-X86AsmPrinter.Tpo $(DEPDIR)/libllvmasmprinter_la-X86AsmPrinter.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Target/X86/AsmPrinter/X86AsmPrinter.cpp' object='libllvmasmprinter_la-X86AsmPrinter.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmasmprinter_la_CPPFLAGS) $(CPPFLAGS) $(libllvmasmprinter_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmasmprinter_la-X86AsmPrinter.lo `test -f 'llvm/lib/Target/X86/AsmPrinter/X86AsmPrinter.cpp' || echo '$(srcdir)/'`llvm/lib/Target/X86/AsmPrinter/X86AsmPrinter.cpp + +libllvmasmprinter_la-X86ATTInstPrinter.lo: llvm/lib/Target/X86/AsmPrinter/X86ATTInstPrinter.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmasmprinter_la_CPPFLAGS) $(CPPFLAGS) $(libllvmasmprinter_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmasmprinter_la-X86ATTInstPrinter.lo -MD -MP -MF $(DEPDIR)/libllvmasmprinter_la-X86ATTInstPrinter.Tpo -c -o libllvmasmprinter_la-X86ATTInstPrinter.lo `test -f 'llvm/lib/Target/X86/AsmPrinter/X86ATTInstPrinter.cpp' || echo '$(srcdir)/'`llvm/lib/Target/X86/AsmPrinter/X86ATTInstPrinter.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmasmprinter_la-X86ATTInstPrinter.Tpo $(DEPDIR)/libllvmasmprinter_la-X86ATTInstPrinter.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Target/X86/AsmPrinter/X86ATTInstPrinter.cpp' object='libllvmasmprinter_la-X86ATTInstPrinter.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmasmprinter_la_CPPFLAGS) $(CPPFLAGS) $(libllvmasmprinter_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmasmprinter_la-X86ATTInstPrinter.lo `test -f 'llvm/lib/Target/X86/AsmPrinter/X86ATTInstPrinter.cpp' || echo '$(srcdir)/'`llvm/lib/Target/X86/AsmPrinter/X86ATTInstPrinter.cpp + +libllvmasmprinter_la-X86IntelInstPrinter.lo: llvm/lib/Target/X86/AsmPrinter/X86IntelInstPrinter.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmasmprinter_la_CPPFLAGS) $(CPPFLAGS) $(libllvmasmprinter_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmasmprinter_la-X86IntelInstPrinter.lo -MD -MP -MF $(DEPDIR)/libllvmasmprinter_la-X86IntelInstPrinter.Tpo -c -o libllvmasmprinter_la-X86IntelInstPrinter.lo `test -f 'llvm/lib/Target/X86/AsmPrinter/X86IntelInstPrinter.cpp' || echo '$(srcdir)/'`llvm/lib/Target/X86/AsmPrinter/X86IntelInstPrinter.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmasmprinter_la-X86IntelInstPrinter.Tpo $(DEPDIR)/libllvmasmprinter_la-X86IntelInstPrinter.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Target/X86/AsmPrinter/X86IntelInstPrinter.cpp' object='libllvmasmprinter_la-X86IntelInstPrinter.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmasmprinter_la_CPPFLAGS) $(CPPFLAGS) $(libllvmasmprinter_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmasmprinter_la-X86IntelInstPrinter.lo `test -f 'llvm/lib/Target/X86/AsmPrinter/X86IntelInstPrinter.cpp' || echo '$(srcdir)/'`llvm/lib/Target/X86/AsmPrinter/X86IntelInstPrinter.cpp + +libllvmasmprinter_la-X86MCInstLower.lo: llvm/lib/Target/X86/AsmPrinter/X86MCInstLower.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmasmprinter_la_CPPFLAGS) $(CPPFLAGS) $(libllvmasmprinter_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmasmprinter_la-X86MCInstLower.lo -MD -MP -MF $(DEPDIR)/libllvmasmprinter_la-X86MCInstLower.Tpo -c -o libllvmasmprinter_la-X86MCInstLower.lo `test -f 'llvm/lib/Target/X86/AsmPrinter/X86MCInstLower.cpp' || echo '$(srcdir)/'`llvm/lib/Target/X86/AsmPrinter/X86MCInstLower.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmasmprinter_la-X86MCInstLower.Tpo $(DEPDIR)/libllvmasmprinter_la-X86MCInstLower.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Target/X86/AsmPrinter/X86MCInstLower.cpp' object='libllvmasmprinter_la-X86MCInstLower.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmasmprinter_la_CPPFLAGS) $(CPPFLAGS) $(libllvmasmprinter_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmasmprinter_la-X86MCInstLower.lo `test -f 'llvm/lib/Target/X86/AsmPrinter/X86MCInstLower.cpp' || echo '$(srcdir)/'`llvm/lib/Target/X86/AsmPrinter/X86MCInstLower.cpp + +libllvmasmprinter_la-X86COFFMachineModuleInfo.lo: llvm/lib/Target/X86/X86COFFMachineModuleInfo.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmasmprinter_la_CPPFLAGS) $(CPPFLAGS) $(libllvmasmprinter_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmasmprinter_la-X86COFFMachineModuleInfo.lo -MD -MP -MF $(DEPDIR)/libllvmasmprinter_la-X86COFFMachineModuleInfo.Tpo -c -o libllvmasmprinter_la-X86COFFMachineModuleInfo.lo `test -f 'llvm/lib/Target/X86/X86COFFMachineModuleInfo.cpp' || echo '$(srcdir)/'`llvm/lib/Target/X86/X86COFFMachineModuleInfo.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmasmprinter_la-X86COFFMachineModuleInfo.Tpo $(DEPDIR)/libllvmasmprinter_la-X86COFFMachineModuleInfo.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Target/X86/X86COFFMachineModuleInfo.cpp' object='libllvmasmprinter_la-X86COFFMachineModuleInfo.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmasmprinter_la_CPPFLAGS) $(CPPFLAGS) $(libllvmasmprinter_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmasmprinter_la-X86COFFMachineModuleInfo.lo `test -f 'llvm/lib/Target/X86/X86COFFMachineModuleInfo.cpp' || echo '$(srcdir)/'`llvm/lib/Target/X86/X86COFFMachineModuleInfo.cpp + +libllvmasmprinter_la-PPCAsmPrinter.lo: llvm/lib/Target/PowerPC/AsmPrinter/PPCAsmPrinter.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmasmprinter_la_CPPFLAGS) $(CPPFLAGS) $(libllvmasmprinter_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmasmprinter_la-PPCAsmPrinter.lo -MD -MP -MF $(DEPDIR)/libllvmasmprinter_la-PPCAsmPrinter.Tpo -c -o libllvmasmprinter_la-PPCAsmPrinter.lo `test -f 'llvm/lib/Target/PowerPC/AsmPrinter/PPCAsmPrinter.cpp' || echo '$(srcdir)/'`llvm/lib/Target/PowerPC/AsmPrinter/PPCAsmPrinter.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmasmprinter_la-PPCAsmPrinter.Tpo $(DEPDIR)/libllvmasmprinter_la-PPCAsmPrinter.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Target/PowerPC/AsmPrinter/PPCAsmPrinter.cpp' object='libllvmasmprinter_la-PPCAsmPrinter.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmasmprinter_la_CPPFLAGS) $(CPPFLAGS) $(libllvmasmprinter_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmasmprinter_la-PPCAsmPrinter.lo `test -f 'llvm/lib/Target/PowerPC/AsmPrinter/PPCAsmPrinter.cpp' || echo '$(srcdir)/'`llvm/lib/Target/PowerPC/AsmPrinter/PPCAsmPrinter.cpp + +libllvmasmprinter_la-ARMAsmPrinter.lo: llvm/lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmasmprinter_la_CPPFLAGS) $(CPPFLAGS) $(libllvmasmprinter_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmasmprinter_la-ARMAsmPrinter.lo -MD -MP -MF $(DEPDIR)/libllvmasmprinter_la-ARMAsmPrinter.Tpo -c -o libllvmasmprinter_la-ARMAsmPrinter.lo `test -f 'llvm/lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp' || echo '$(srcdir)/'`llvm/lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmasmprinter_la-ARMAsmPrinter.Tpo $(DEPDIR)/libllvmasmprinter_la-ARMAsmPrinter.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp' object='libllvmasmprinter_la-ARMAsmPrinter.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmasmprinter_la_CPPFLAGS) $(CPPFLAGS) $(libllvmasmprinter_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmasmprinter_la-ARMAsmPrinter.lo `test -f 'llvm/lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp' || echo '$(srcdir)/'`llvm/lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp + +libllvmasmprinter_la-ARMInstPrinter.lo: llvm/lib/Target/ARM/AsmPrinter/ARMInstPrinter.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmasmprinter_la_CPPFLAGS) $(CPPFLAGS) $(libllvmasmprinter_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmasmprinter_la-ARMInstPrinter.lo -MD -MP -MF $(DEPDIR)/libllvmasmprinter_la-ARMInstPrinter.Tpo -c -o libllvmasmprinter_la-ARMInstPrinter.lo `test -f 'llvm/lib/Target/ARM/AsmPrinter/ARMInstPrinter.cpp' || echo '$(srcdir)/'`llvm/lib/Target/ARM/AsmPrinter/ARMInstPrinter.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmasmprinter_la-ARMInstPrinter.Tpo $(DEPDIR)/libllvmasmprinter_la-ARMInstPrinter.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Target/ARM/AsmPrinter/ARMInstPrinter.cpp' object='libllvmasmprinter_la-ARMInstPrinter.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmasmprinter_la_CPPFLAGS) $(CPPFLAGS) $(libllvmasmprinter_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmasmprinter_la-ARMInstPrinter.lo `test -f 'llvm/lib/Target/ARM/AsmPrinter/ARMInstPrinter.cpp' || echo '$(srcdir)/'`llvm/lib/Target/ARM/AsmPrinter/ARMInstPrinter.cpp + +libllvmasmprinter_la-ARMMCInstLower.lo: llvm/lib/Target/ARM/AsmPrinter/ARMMCInstLower.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmasmprinter_la_CPPFLAGS) $(CPPFLAGS) $(libllvmasmprinter_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmasmprinter_la-ARMMCInstLower.lo -MD -MP -MF $(DEPDIR)/libllvmasmprinter_la-ARMMCInstLower.Tpo -c -o libllvmasmprinter_la-ARMMCInstLower.lo `test -f 'llvm/lib/Target/ARM/AsmPrinter/ARMMCInstLower.cpp' || echo '$(srcdir)/'`llvm/lib/Target/ARM/AsmPrinter/ARMMCInstLower.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmasmprinter_la-ARMMCInstLower.Tpo $(DEPDIR)/libllvmasmprinter_la-ARMMCInstLower.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Target/ARM/AsmPrinter/ARMMCInstLower.cpp' object='libllvmasmprinter_la-ARMMCInstLower.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmasmprinter_la_CPPFLAGS) $(CPPFLAGS) $(libllvmasmprinter_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmasmprinter_la-ARMMCInstLower.lo `test -f 'llvm/lib/Target/ARM/AsmPrinter/ARMMCInstLower.cpp' || echo '$(srcdir)/'`llvm/lib/Target/ARM/AsmPrinter/ARMMCInstLower.cpp + +libllvmbitreader_la-BitReader.lo: llvm/lib/Bitcode/Reader/BitReader.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmbitreader_la_CPPFLAGS) $(CPPFLAGS) $(libllvmbitreader_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmbitreader_la-BitReader.lo -MD -MP -MF $(DEPDIR)/libllvmbitreader_la-BitReader.Tpo -c -o libllvmbitreader_la-BitReader.lo `test -f 'llvm/lib/Bitcode/Reader/BitReader.cpp' || echo '$(srcdir)/'`llvm/lib/Bitcode/Reader/BitReader.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmbitreader_la-BitReader.Tpo $(DEPDIR)/libllvmbitreader_la-BitReader.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Bitcode/Reader/BitReader.cpp' object='libllvmbitreader_la-BitReader.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmbitreader_la_CPPFLAGS) $(CPPFLAGS) $(libllvmbitreader_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmbitreader_la-BitReader.lo `test -f 'llvm/lib/Bitcode/Reader/BitReader.cpp' || echo '$(srcdir)/'`llvm/lib/Bitcode/Reader/BitReader.cpp + +libllvmbitreader_la-BitcodeReader.lo: llvm/lib/Bitcode/Reader/BitcodeReader.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmbitreader_la_CPPFLAGS) $(CPPFLAGS) $(libllvmbitreader_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmbitreader_la-BitcodeReader.lo -MD -MP -MF $(DEPDIR)/libllvmbitreader_la-BitcodeReader.Tpo -c -o libllvmbitreader_la-BitcodeReader.lo `test -f 'llvm/lib/Bitcode/Reader/BitcodeReader.cpp' || echo '$(srcdir)/'`llvm/lib/Bitcode/Reader/BitcodeReader.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmbitreader_la-BitcodeReader.Tpo $(DEPDIR)/libllvmbitreader_la-BitcodeReader.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Bitcode/Reader/BitcodeReader.cpp' object='libllvmbitreader_la-BitcodeReader.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmbitreader_la_CPPFLAGS) $(CPPFLAGS) $(libllvmbitreader_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmbitreader_la-BitcodeReader.lo `test -f 'llvm/lib/Bitcode/Reader/BitcodeReader.cpp' || echo '$(srcdir)/'`llvm/lib/Bitcode/Reader/BitcodeReader.cpp + +libllvmbitreader_la-Deserialize.lo: llvm/lib/Bitcode/Reader/Deserialize.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmbitreader_la_CPPFLAGS) $(CPPFLAGS) $(libllvmbitreader_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmbitreader_la-Deserialize.lo -MD -MP -MF $(DEPDIR)/libllvmbitreader_la-Deserialize.Tpo -c -o libllvmbitreader_la-Deserialize.lo `test -f 'llvm/lib/Bitcode/Reader/Deserialize.cpp' || echo '$(srcdir)/'`llvm/lib/Bitcode/Reader/Deserialize.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmbitreader_la-Deserialize.Tpo $(DEPDIR)/libllvmbitreader_la-Deserialize.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Bitcode/Reader/Deserialize.cpp' object='libllvmbitreader_la-Deserialize.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmbitreader_la_CPPFLAGS) $(CPPFLAGS) $(libllvmbitreader_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmbitreader_la-Deserialize.lo `test -f 'llvm/lib/Bitcode/Reader/Deserialize.cpp' || echo '$(srcdir)/'`llvm/lib/Bitcode/Reader/Deserialize.cpp + +libllvmbitreader_la-DeserializeAPFloat.lo: llvm/lib/Bitcode/Reader/DeserializeAPFloat.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmbitreader_la_CPPFLAGS) $(CPPFLAGS) $(libllvmbitreader_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmbitreader_la-DeserializeAPFloat.lo -MD -MP -MF $(DEPDIR)/libllvmbitreader_la-DeserializeAPFloat.Tpo -c -o libllvmbitreader_la-DeserializeAPFloat.lo `test -f 'llvm/lib/Bitcode/Reader/DeserializeAPFloat.cpp' || echo '$(srcdir)/'`llvm/lib/Bitcode/Reader/DeserializeAPFloat.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmbitreader_la-DeserializeAPFloat.Tpo $(DEPDIR)/libllvmbitreader_la-DeserializeAPFloat.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Bitcode/Reader/DeserializeAPFloat.cpp' object='libllvmbitreader_la-DeserializeAPFloat.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmbitreader_la_CPPFLAGS) $(CPPFLAGS) $(libllvmbitreader_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmbitreader_la-DeserializeAPFloat.lo `test -f 'llvm/lib/Bitcode/Reader/DeserializeAPFloat.cpp' || echo '$(srcdir)/'`llvm/lib/Bitcode/Reader/DeserializeAPFloat.cpp + +libllvmbitreader_la-DeserializeAPInt.lo: llvm/lib/Bitcode/Reader/DeserializeAPInt.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmbitreader_la_CPPFLAGS) $(CPPFLAGS) $(libllvmbitreader_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmbitreader_la-DeserializeAPInt.lo -MD -MP -MF $(DEPDIR)/libllvmbitreader_la-DeserializeAPInt.Tpo -c -o libllvmbitreader_la-DeserializeAPInt.lo `test -f 'llvm/lib/Bitcode/Reader/DeserializeAPInt.cpp' || echo '$(srcdir)/'`llvm/lib/Bitcode/Reader/DeserializeAPInt.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmbitreader_la-DeserializeAPInt.Tpo $(DEPDIR)/libllvmbitreader_la-DeserializeAPInt.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Bitcode/Reader/DeserializeAPInt.cpp' object='libllvmbitreader_la-DeserializeAPInt.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmbitreader_la_CPPFLAGS) $(CPPFLAGS) $(libllvmbitreader_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmbitreader_la-DeserializeAPInt.lo `test -f 'llvm/lib/Bitcode/Reader/DeserializeAPInt.cpp' || echo '$(srcdir)/'`llvm/lib/Bitcode/Reader/DeserializeAPInt.cpp + +libllvmbitwriter_la-BitWriter.lo: llvm/lib/Bitcode/Writer/BitWriter.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmbitwriter_la_CPPFLAGS) $(CPPFLAGS) $(libllvmbitwriter_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmbitwriter_la-BitWriter.lo -MD -MP -MF $(DEPDIR)/libllvmbitwriter_la-BitWriter.Tpo -c -o libllvmbitwriter_la-BitWriter.lo `test -f 'llvm/lib/Bitcode/Writer/BitWriter.cpp' || echo '$(srcdir)/'`llvm/lib/Bitcode/Writer/BitWriter.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmbitwriter_la-BitWriter.Tpo $(DEPDIR)/libllvmbitwriter_la-BitWriter.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Bitcode/Writer/BitWriter.cpp' object='libllvmbitwriter_la-BitWriter.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmbitwriter_la_CPPFLAGS) $(CPPFLAGS) $(libllvmbitwriter_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmbitwriter_la-BitWriter.lo `test -f 'llvm/lib/Bitcode/Writer/BitWriter.cpp' || echo '$(srcdir)/'`llvm/lib/Bitcode/Writer/BitWriter.cpp + +libllvmbitwriter_la-BitcodeWriter.lo: llvm/lib/Bitcode/Writer/BitcodeWriter.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmbitwriter_la_CPPFLAGS) $(CPPFLAGS) $(libllvmbitwriter_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmbitwriter_la-BitcodeWriter.lo -MD -MP -MF $(DEPDIR)/libllvmbitwriter_la-BitcodeWriter.Tpo -c -o libllvmbitwriter_la-BitcodeWriter.lo `test -f 'llvm/lib/Bitcode/Writer/BitcodeWriter.cpp' || echo '$(srcdir)/'`llvm/lib/Bitcode/Writer/BitcodeWriter.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmbitwriter_la-BitcodeWriter.Tpo $(DEPDIR)/libllvmbitwriter_la-BitcodeWriter.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Bitcode/Writer/BitcodeWriter.cpp' object='libllvmbitwriter_la-BitcodeWriter.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmbitwriter_la_CPPFLAGS) $(CPPFLAGS) $(libllvmbitwriter_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmbitwriter_la-BitcodeWriter.lo `test -f 'llvm/lib/Bitcode/Writer/BitcodeWriter.cpp' || echo '$(srcdir)/'`llvm/lib/Bitcode/Writer/BitcodeWriter.cpp + +libllvmbitwriter_la-BitcodeWriterPass.lo: llvm/lib/Bitcode/Writer/BitcodeWriterPass.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmbitwriter_la_CPPFLAGS) $(CPPFLAGS) $(libllvmbitwriter_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmbitwriter_la-BitcodeWriterPass.lo -MD -MP -MF $(DEPDIR)/libllvmbitwriter_la-BitcodeWriterPass.Tpo -c -o libllvmbitwriter_la-BitcodeWriterPass.lo `test -f 'llvm/lib/Bitcode/Writer/BitcodeWriterPass.cpp' || echo '$(srcdir)/'`llvm/lib/Bitcode/Writer/BitcodeWriterPass.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmbitwriter_la-BitcodeWriterPass.Tpo $(DEPDIR)/libllvmbitwriter_la-BitcodeWriterPass.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Bitcode/Writer/BitcodeWriterPass.cpp' object='libllvmbitwriter_la-BitcodeWriterPass.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmbitwriter_la_CPPFLAGS) $(CPPFLAGS) $(libllvmbitwriter_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmbitwriter_la-BitcodeWriterPass.lo `test -f 'llvm/lib/Bitcode/Writer/BitcodeWriterPass.cpp' || echo '$(srcdir)/'`llvm/lib/Bitcode/Writer/BitcodeWriterPass.cpp + +libllvmbitwriter_la-Serialize.lo: llvm/lib/Bitcode/Writer/Serialize.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmbitwriter_la_CPPFLAGS) $(CPPFLAGS) $(libllvmbitwriter_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmbitwriter_la-Serialize.lo -MD -MP -MF $(DEPDIR)/libllvmbitwriter_la-Serialize.Tpo -c -o libllvmbitwriter_la-Serialize.lo `test -f 'llvm/lib/Bitcode/Writer/Serialize.cpp' || echo '$(srcdir)/'`llvm/lib/Bitcode/Writer/Serialize.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmbitwriter_la-Serialize.Tpo $(DEPDIR)/libllvmbitwriter_la-Serialize.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Bitcode/Writer/Serialize.cpp' object='libllvmbitwriter_la-Serialize.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmbitwriter_la_CPPFLAGS) $(CPPFLAGS) $(libllvmbitwriter_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmbitwriter_la-Serialize.lo `test -f 'llvm/lib/Bitcode/Writer/Serialize.cpp' || echo '$(srcdir)/'`llvm/lib/Bitcode/Writer/Serialize.cpp + +libllvmbitwriter_la-SerializeAPFloat.lo: llvm/lib/Bitcode/Writer/SerializeAPFloat.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmbitwriter_la_CPPFLAGS) $(CPPFLAGS) $(libllvmbitwriter_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmbitwriter_la-SerializeAPFloat.lo -MD -MP -MF $(DEPDIR)/libllvmbitwriter_la-SerializeAPFloat.Tpo -c -o libllvmbitwriter_la-SerializeAPFloat.lo `test -f 'llvm/lib/Bitcode/Writer/SerializeAPFloat.cpp' || echo '$(srcdir)/'`llvm/lib/Bitcode/Writer/SerializeAPFloat.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmbitwriter_la-SerializeAPFloat.Tpo $(DEPDIR)/libllvmbitwriter_la-SerializeAPFloat.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Bitcode/Writer/SerializeAPFloat.cpp' object='libllvmbitwriter_la-SerializeAPFloat.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmbitwriter_la_CPPFLAGS) $(CPPFLAGS) $(libllvmbitwriter_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmbitwriter_la-SerializeAPFloat.lo `test -f 'llvm/lib/Bitcode/Writer/SerializeAPFloat.cpp' || echo '$(srcdir)/'`llvm/lib/Bitcode/Writer/SerializeAPFloat.cpp + +libllvmbitwriter_la-SerializeAPInt.lo: llvm/lib/Bitcode/Writer/SerializeAPInt.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmbitwriter_la_CPPFLAGS) $(CPPFLAGS) $(libllvmbitwriter_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmbitwriter_la-SerializeAPInt.lo -MD -MP -MF $(DEPDIR)/libllvmbitwriter_la-SerializeAPInt.Tpo -c -o libllvmbitwriter_la-SerializeAPInt.lo `test -f 'llvm/lib/Bitcode/Writer/SerializeAPInt.cpp' || echo '$(srcdir)/'`llvm/lib/Bitcode/Writer/SerializeAPInt.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmbitwriter_la-SerializeAPInt.Tpo $(DEPDIR)/libllvmbitwriter_la-SerializeAPInt.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Bitcode/Writer/SerializeAPInt.cpp' object='libllvmbitwriter_la-SerializeAPInt.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmbitwriter_la_CPPFLAGS) $(CPPFLAGS) $(libllvmbitwriter_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmbitwriter_la-SerializeAPInt.lo `test -f 'llvm/lib/Bitcode/Writer/SerializeAPInt.cpp' || echo '$(srcdir)/'`llvm/lib/Bitcode/Writer/SerializeAPInt.cpp + +libllvmbitwriter_la-ValueEnumerator.lo: llvm/lib/Bitcode/Writer/ValueEnumerator.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmbitwriter_la_CPPFLAGS) $(CPPFLAGS) $(libllvmbitwriter_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmbitwriter_la-ValueEnumerator.lo -MD -MP -MF $(DEPDIR)/libllvmbitwriter_la-ValueEnumerator.Tpo -c -o libllvmbitwriter_la-ValueEnumerator.lo `test -f 'llvm/lib/Bitcode/Writer/ValueEnumerator.cpp' || echo '$(srcdir)/'`llvm/lib/Bitcode/Writer/ValueEnumerator.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmbitwriter_la-ValueEnumerator.Tpo $(DEPDIR)/libllvmbitwriter_la-ValueEnumerator.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Bitcode/Writer/ValueEnumerator.cpp' object='libllvmbitwriter_la-ValueEnumerator.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmbitwriter_la_CPPFLAGS) $(CPPFLAGS) $(libllvmbitwriter_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmbitwriter_la-ValueEnumerator.lo `test -f 'llvm/lib/Bitcode/Writer/ValueEnumerator.cpp' || echo '$(srcdir)/'`llvm/lib/Bitcode/Writer/ValueEnumerator.cpp + +libllvmcodegen_la-AggressiveAntiDepBreaker.lo: llvm/lib/CodeGen/AggressiveAntiDepBreaker.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmcodegen_la-AggressiveAntiDepBreaker.lo -MD -MP -MF $(DEPDIR)/libllvmcodegen_la-AggressiveAntiDepBreaker.Tpo -c -o libllvmcodegen_la-AggressiveAntiDepBreaker.lo `test -f 'llvm/lib/CodeGen/AggressiveAntiDepBreaker.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/AggressiveAntiDepBreaker.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmcodegen_la-AggressiveAntiDepBreaker.Tpo $(DEPDIR)/libllvmcodegen_la-AggressiveAntiDepBreaker.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/CodeGen/AggressiveAntiDepBreaker.cpp' object='libllvmcodegen_la-AggressiveAntiDepBreaker.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmcodegen_la-AggressiveAntiDepBreaker.lo `test -f 'llvm/lib/CodeGen/AggressiveAntiDepBreaker.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/AggressiveAntiDepBreaker.cpp + +libllvmcodegen_la-BranchFolding.lo: llvm/lib/CodeGen/BranchFolding.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmcodegen_la-BranchFolding.lo -MD -MP -MF $(DEPDIR)/libllvmcodegen_la-BranchFolding.Tpo -c -o libllvmcodegen_la-BranchFolding.lo `test -f 'llvm/lib/CodeGen/BranchFolding.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/BranchFolding.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmcodegen_la-BranchFolding.Tpo $(DEPDIR)/libllvmcodegen_la-BranchFolding.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/CodeGen/BranchFolding.cpp' object='libllvmcodegen_la-BranchFolding.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmcodegen_la-BranchFolding.lo `test -f 'llvm/lib/CodeGen/BranchFolding.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/BranchFolding.cpp + +libllvmcodegen_la-CriticalAntiDepBreaker.lo: llvm/lib/CodeGen/CriticalAntiDepBreaker.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmcodegen_la-CriticalAntiDepBreaker.lo -MD -MP -MF $(DEPDIR)/libllvmcodegen_la-CriticalAntiDepBreaker.Tpo -c -o libllvmcodegen_la-CriticalAntiDepBreaker.lo `test -f 'llvm/lib/CodeGen/CriticalAntiDepBreaker.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/CriticalAntiDepBreaker.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmcodegen_la-CriticalAntiDepBreaker.Tpo $(DEPDIR)/libllvmcodegen_la-CriticalAntiDepBreaker.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/CodeGen/CriticalAntiDepBreaker.cpp' object='libllvmcodegen_la-CriticalAntiDepBreaker.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmcodegen_la-CriticalAntiDepBreaker.lo `test -f 'llvm/lib/CodeGen/CriticalAntiDepBreaker.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/CriticalAntiDepBreaker.cpp + +libllvmcodegen_la-CodePlacementOpt.lo: llvm/lib/CodeGen/CodePlacementOpt.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmcodegen_la-CodePlacementOpt.lo -MD -MP -MF $(DEPDIR)/libllvmcodegen_la-CodePlacementOpt.Tpo -c -o libllvmcodegen_la-CodePlacementOpt.lo `test -f 'llvm/lib/CodeGen/CodePlacementOpt.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/CodePlacementOpt.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmcodegen_la-CodePlacementOpt.Tpo $(DEPDIR)/libllvmcodegen_la-CodePlacementOpt.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/CodeGen/CodePlacementOpt.cpp' object='libllvmcodegen_la-CodePlacementOpt.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmcodegen_la-CodePlacementOpt.lo `test -f 'llvm/lib/CodeGen/CodePlacementOpt.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/CodePlacementOpt.cpp + +libllvmcodegen_la-DeadMachineInstructionElim.lo: llvm/lib/CodeGen/DeadMachineInstructionElim.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmcodegen_la-DeadMachineInstructionElim.lo -MD -MP -MF $(DEPDIR)/libllvmcodegen_la-DeadMachineInstructionElim.Tpo -c -o libllvmcodegen_la-DeadMachineInstructionElim.lo `test -f 'llvm/lib/CodeGen/DeadMachineInstructionElim.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/DeadMachineInstructionElim.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmcodegen_la-DeadMachineInstructionElim.Tpo $(DEPDIR)/libllvmcodegen_la-DeadMachineInstructionElim.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/CodeGen/DeadMachineInstructionElim.cpp' object='libllvmcodegen_la-DeadMachineInstructionElim.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmcodegen_la-DeadMachineInstructionElim.lo `test -f 'llvm/lib/CodeGen/DeadMachineInstructionElim.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/DeadMachineInstructionElim.cpp + +libllvmcodegen_la-DwarfEHPrepare.lo: llvm/lib/CodeGen/DwarfEHPrepare.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmcodegen_la-DwarfEHPrepare.lo -MD -MP -MF $(DEPDIR)/libllvmcodegen_la-DwarfEHPrepare.Tpo -c -o libllvmcodegen_la-DwarfEHPrepare.lo `test -f 'llvm/lib/CodeGen/DwarfEHPrepare.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/DwarfEHPrepare.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmcodegen_la-DwarfEHPrepare.Tpo $(DEPDIR)/libllvmcodegen_la-DwarfEHPrepare.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/CodeGen/DwarfEHPrepare.cpp' object='libllvmcodegen_la-DwarfEHPrepare.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmcodegen_la-DwarfEHPrepare.lo `test -f 'llvm/lib/CodeGen/DwarfEHPrepare.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/DwarfEHPrepare.cpp + +libllvmcodegen_la-ELFCodeEmitter.lo: llvm/lib/CodeGen/ELFCodeEmitter.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmcodegen_la-ELFCodeEmitter.lo -MD -MP -MF $(DEPDIR)/libllvmcodegen_la-ELFCodeEmitter.Tpo -c -o libllvmcodegen_la-ELFCodeEmitter.lo `test -f 'llvm/lib/CodeGen/ELFCodeEmitter.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/ELFCodeEmitter.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmcodegen_la-ELFCodeEmitter.Tpo $(DEPDIR)/libllvmcodegen_la-ELFCodeEmitter.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/CodeGen/ELFCodeEmitter.cpp' object='libllvmcodegen_la-ELFCodeEmitter.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmcodegen_la-ELFCodeEmitter.lo `test -f 'llvm/lib/CodeGen/ELFCodeEmitter.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/ELFCodeEmitter.cpp + +libllvmcodegen_la-ELFWriter.lo: llvm/lib/CodeGen/ELFWriter.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmcodegen_la-ELFWriter.lo -MD -MP -MF $(DEPDIR)/libllvmcodegen_la-ELFWriter.Tpo -c -o libllvmcodegen_la-ELFWriter.lo `test -f 'llvm/lib/CodeGen/ELFWriter.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/ELFWriter.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmcodegen_la-ELFWriter.Tpo $(DEPDIR)/libllvmcodegen_la-ELFWriter.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/CodeGen/ELFWriter.cpp' object='libllvmcodegen_la-ELFWriter.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmcodegen_la-ELFWriter.lo `test -f 'llvm/lib/CodeGen/ELFWriter.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/ELFWriter.cpp + +libllvmcodegen_la-ExactHazardRecognizer.lo: llvm/lib/CodeGen/ExactHazardRecognizer.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmcodegen_la-ExactHazardRecognizer.lo -MD -MP -MF $(DEPDIR)/libllvmcodegen_la-ExactHazardRecognizer.Tpo -c -o libllvmcodegen_la-ExactHazardRecognizer.lo `test -f 'llvm/lib/CodeGen/ExactHazardRecognizer.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/ExactHazardRecognizer.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmcodegen_la-ExactHazardRecognizer.Tpo $(DEPDIR)/libllvmcodegen_la-ExactHazardRecognizer.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/CodeGen/ExactHazardRecognizer.cpp' object='libllvmcodegen_la-ExactHazardRecognizer.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmcodegen_la-ExactHazardRecognizer.lo `test -f 'llvm/lib/CodeGen/ExactHazardRecognizer.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/ExactHazardRecognizer.cpp + +libllvmcodegen_la-GCMetadata.lo: llvm/lib/CodeGen/GCMetadata.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmcodegen_la-GCMetadata.lo -MD -MP -MF $(DEPDIR)/libllvmcodegen_la-GCMetadata.Tpo -c -o libllvmcodegen_la-GCMetadata.lo `test -f 'llvm/lib/CodeGen/GCMetadata.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/GCMetadata.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmcodegen_la-GCMetadata.Tpo $(DEPDIR)/libllvmcodegen_la-GCMetadata.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/CodeGen/GCMetadata.cpp' object='libllvmcodegen_la-GCMetadata.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmcodegen_la-GCMetadata.lo `test -f 'llvm/lib/CodeGen/GCMetadata.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/GCMetadata.cpp + +libllvmcodegen_la-GCMetadataPrinter.lo: llvm/lib/CodeGen/GCMetadataPrinter.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmcodegen_la-GCMetadataPrinter.lo -MD -MP -MF $(DEPDIR)/libllvmcodegen_la-GCMetadataPrinter.Tpo -c -o libllvmcodegen_la-GCMetadataPrinter.lo `test -f 'llvm/lib/CodeGen/GCMetadataPrinter.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/GCMetadataPrinter.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmcodegen_la-GCMetadataPrinter.Tpo $(DEPDIR)/libllvmcodegen_la-GCMetadataPrinter.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/CodeGen/GCMetadataPrinter.cpp' object='libllvmcodegen_la-GCMetadataPrinter.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmcodegen_la-GCMetadataPrinter.lo `test -f 'llvm/lib/CodeGen/GCMetadataPrinter.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/GCMetadataPrinter.cpp + +libllvmcodegen_la-GCStrategy.lo: llvm/lib/CodeGen/GCStrategy.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmcodegen_la-GCStrategy.lo -MD -MP -MF $(DEPDIR)/libllvmcodegen_la-GCStrategy.Tpo -c -o libllvmcodegen_la-GCStrategy.lo `test -f 'llvm/lib/CodeGen/GCStrategy.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/GCStrategy.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmcodegen_la-GCStrategy.Tpo $(DEPDIR)/libllvmcodegen_la-GCStrategy.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/CodeGen/GCStrategy.cpp' object='libllvmcodegen_la-GCStrategy.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmcodegen_la-GCStrategy.lo `test -f 'llvm/lib/CodeGen/GCStrategy.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/GCStrategy.cpp + +libllvmcodegen_la-IfConversion.lo: llvm/lib/CodeGen/IfConversion.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmcodegen_la-IfConversion.lo -MD -MP -MF $(DEPDIR)/libllvmcodegen_la-IfConversion.Tpo -c -o libllvmcodegen_la-IfConversion.lo `test -f 'llvm/lib/CodeGen/IfConversion.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/IfConversion.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmcodegen_la-IfConversion.Tpo $(DEPDIR)/libllvmcodegen_la-IfConversion.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/CodeGen/IfConversion.cpp' object='libllvmcodegen_la-IfConversion.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmcodegen_la-IfConversion.lo `test -f 'llvm/lib/CodeGen/IfConversion.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/IfConversion.cpp + +libllvmcodegen_la-IntrinsicLowering.lo: llvm/lib/CodeGen/IntrinsicLowering.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmcodegen_la-IntrinsicLowering.lo -MD -MP -MF $(DEPDIR)/libllvmcodegen_la-IntrinsicLowering.Tpo -c -o libllvmcodegen_la-IntrinsicLowering.lo `test -f 'llvm/lib/CodeGen/IntrinsicLowering.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/IntrinsicLowering.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmcodegen_la-IntrinsicLowering.Tpo $(DEPDIR)/libllvmcodegen_la-IntrinsicLowering.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/CodeGen/IntrinsicLowering.cpp' object='libllvmcodegen_la-IntrinsicLowering.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmcodegen_la-IntrinsicLowering.lo `test -f 'llvm/lib/CodeGen/IntrinsicLowering.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/IntrinsicLowering.cpp + +libllvmcodegen_la-LLVMTargetMachine.lo: llvm/lib/CodeGen/LLVMTargetMachine.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmcodegen_la-LLVMTargetMachine.lo -MD -MP -MF $(DEPDIR)/libllvmcodegen_la-LLVMTargetMachine.Tpo -c -o libllvmcodegen_la-LLVMTargetMachine.lo `test -f 'llvm/lib/CodeGen/LLVMTargetMachine.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/LLVMTargetMachine.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmcodegen_la-LLVMTargetMachine.Tpo $(DEPDIR)/libllvmcodegen_la-LLVMTargetMachine.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/CodeGen/LLVMTargetMachine.cpp' object='libllvmcodegen_la-LLVMTargetMachine.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmcodegen_la-LLVMTargetMachine.lo `test -f 'llvm/lib/CodeGen/LLVMTargetMachine.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/LLVMTargetMachine.cpp + +libllvmcodegen_la-LatencyPriorityQueue.lo: llvm/lib/CodeGen/LatencyPriorityQueue.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmcodegen_la-LatencyPriorityQueue.lo -MD -MP -MF $(DEPDIR)/libllvmcodegen_la-LatencyPriorityQueue.Tpo -c -o libllvmcodegen_la-LatencyPriorityQueue.lo `test -f 'llvm/lib/CodeGen/LatencyPriorityQueue.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/LatencyPriorityQueue.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmcodegen_la-LatencyPriorityQueue.Tpo $(DEPDIR)/libllvmcodegen_la-LatencyPriorityQueue.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/CodeGen/LatencyPriorityQueue.cpp' object='libllvmcodegen_la-LatencyPriorityQueue.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmcodegen_la-LatencyPriorityQueue.lo `test -f 'llvm/lib/CodeGen/LatencyPriorityQueue.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/LatencyPriorityQueue.cpp + +libllvmcodegen_la-LiveInterval.lo: llvm/lib/CodeGen/LiveInterval.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmcodegen_la-LiveInterval.lo -MD -MP -MF $(DEPDIR)/libllvmcodegen_la-LiveInterval.Tpo -c -o libllvmcodegen_la-LiveInterval.lo `test -f 'llvm/lib/CodeGen/LiveInterval.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/LiveInterval.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmcodegen_la-LiveInterval.Tpo $(DEPDIR)/libllvmcodegen_la-LiveInterval.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/CodeGen/LiveInterval.cpp' object='libllvmcodegen_la-LiveInterval.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmcodegen_la-LiveInterval.lo `test -f 'llvm/lib/CodeGen/LiveInterval.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/LiveInterval.cpp + +libllvmcodegen_la-LiveIntervalAnalysis.lo: llvm/lib/CodeGen/LiveIntervalAnalysis.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmcodegen_la-LiveIntervalAnalysis.lo -MD -MP -MF $(DEPDIR)/libllvmcodegen_la-LiveIntervalAnalysis.Tpo -c -o libllvmcodegen_la-LiveIntervalAnalysis.lo `test -f 'llvm/lib/CodeGen/LiveIntervalAnalysis.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/LiveIntervalAnalysis.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmcodegen_la-LiveIntervalAnalysis.Tpo $(DEPDIR)/libllvmcodegen_la-LiveIntervalAnalysis.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/CodeGen/LiveIntervalAnalysis.cpp' object='libllvmcodegen_la-LiveIntervalAnalysis.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmcodegen_la-LiveIntervalAnalysis.lo `test -f 'llvm/lib/CodeGen/LiveIntervalAnalysis.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/LiveIntervalAnalysis.cpp + +libllvmcodegen_la-LiveStackAnalysis.lo: llvm/lib/CodeGen/LiveStackAnalysis.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmcodegen_la-LiveStackAnalysis.lo -MD -MP -MF $(DEPDIR)/libllvmcodegen_la-LiveStackAnalysis.Tpo -c -o libllvmcodegen_la-LiveStackAnalysis.lo `test -f 'llvm/lib/CodeGen/LiveStackAnalysis.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/LiveStackAnalysis.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmcodegen_la-LiveStackAnalysis.Tpo $(DEPDIR)/libllvmcodegen_la-LiveStackAnalysis.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/CodeGen/LiveStackAnalysis.cpp' object='libllvmcodegen_la-LiveStackAnalysis.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmcodegen_la-LiveStackAnalysis.lo `test -f 'llvm/lib/CodeGen/LiveStackAnalysis.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/LiveStackAnalysis.cpp + +libllvmcodegen_la-LiveVariables.lo: llvm/lib/CodeGen/LiveVariables.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmcodegen_la-LiveVariables.lo -MD -MP -MF $(DEPDIR)/libllvmcodegen_la-LiveVariables.Tpo -c -o libllvmcodegen_la-LiveVariables.lo `test -f 'llvm/lib/CodeGen/LiveVariables.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/LiveVariables.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmcodegen_la-LiveVariables.Tpo $(DEPDIR)/libllvmcodegen_la-LiveVariables.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/CodeGen/LiveVariables.cpp' object='libllvmcodegen_la-LiveVariables.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmcodegen_la-LiveVariables.lo `test -f 'llvm/lib/CodeGen/LiveVariables.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/LiveVariables.cpp + +libllvmcodegen_la-LowerSubregs.lo: llvm/lib/CodeGen/LowerSubregs.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmcodegen_la-LowerSubregs.lo -MD -MP -MF $(DEPDIR)/libllvmcodegen_la-LowerSubregs.Tpo -c -o libllvmcodegen_la-LowerSubregs.lo `test -f 'llvm/lib/CodeGen/LowerSubregs.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/LowerSubregs.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmcodegen_la-LowerSubregs.Tpo $(DEPDIR)/libllvmcodegen_la-LowerSubregs.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/CodeGen/LowerSubregs.cpp' object='libllvmcodegen_la-LowerSubregs.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmcodegen_la-LowerSubregs.lo `test -f 'llvm/lib/CodeGen/LowerSubregs.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/LowerSubregs.cpp + +libllvmcodegen_la-MachineBasicBlock.lo: llvm/lib/CodeGen/MachineBasicBlock.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmcodegen_la-MachineBasicBlock.lo -MD -MP -MF $(DEPDIR)/libllvmcodegen_la-MachineBasicBlock.Tpo -c -o libllvmcodegen_la-MachineBasicBlock.lo `test -f 'llvm/lib/CodeGen/MachineBasicBlock.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/MachineBasicBlock.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmcodegen_la-MachineBasicBlock.Tpo $(DEPDIR)/libllvmcodegen_la-MachineBasicBlock.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/CodeGen/MachineBasicBlock.cpp' object='libllvmcodegen_la-MachineBasicBlock.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmcodegen_la-MachineBasicBlock.lo `test -f 'llvm/lib/CodeGen/MachineBasicBlock.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/MachineBasicBlock.cpp + +libllvmcodegen_la-MachineDominators.lo: llvm/lib/CodeGen/MachineDominators.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmcodegen_la-MachineDominators.lo -MD -MP -MF $(DEPDIR)/libllvmcodegen_la-MachineDominators.Tpo -c -o libllvmcodegen_la-MachineDominators.lo `test -f 'llvm/lib/CodeGen/MachineDominators.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/MachineDominators.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmcodegen_la-MachineDominators.Tpo $(DEPDIR)/libllvmcodegen_la-MachineDominators.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/CodeGen/MachineDominators.cpp' object='libllvmcodegen_la-MachineDominators.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmcodegen_la-MachineDominators.lo `test -f 'llvm/lib/CodeGen/MachineDominators.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/MachineDominators.cpp + +libllvmcodegen_la-MachineFunction.lo: llvm/lib/CodeGen/MachineFunction.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmcodegen_la-MachineFunction.lo -MD -MP -MF $(DEPDIR)/libllvmcodegen_la-MachineFunction.Tpo -c -o libllvmcodegen_la-MachineFunction.lo `test -f 'llvm/lib/CodeGen/MachineFunction.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/MachineFunction.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmcodegen_la-MachineFunction.Tpo $(DEPDIR)/libllvmcodegen_la-MachineFunction.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/CodeGen/MachineFunction.cpp' object='libllvmcodegen_la-MachineFunction.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmcodegen_la-MachineFunction.lo `test -f 'llvm/lib/CodeGen/MachineFunction.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/MachineFunction.cpp + +libllvmcodegen_la-MachineFunctionAnalysis.lo: llvm/lib/CodeGen/MachineFunctionAnalysis.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmcodegen_la-MachineFunctionAnalysis.lo -MD -MP -MF $(DEPDIR)/libllvmcodegen_la-MachineFunctionAnalysis.Tpo -c -o libllvmcodegen_la-MachineFunctionAnalysis.lo `test -f 'llvm/lib/CodeGen/MachineFunctionAnalysis.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/MachineFunctionAnalysis.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmcodegen_la-MachineFunctionAnalysis.Tpo $(DEPDIR)/libllvmcodegen_la-MachineFunctionAnalysis.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/CodeGen/MachineFunctionAnalysis.cpp' object='libllvmcodegen_la-MachineFunctionAnalysis.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmcodegen_la-MachineFunctionAnalysis.lo `test -f 'llvm/lib/CodeGen/MachineFunctionAnalysis.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/MachineFunctionAnalysis.cpp + +libllvmcodegen_la-MachineFunctionPass.lo: llvm/lib/CodeGen/MachineFunctionPass.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmcodegen_la-MachineFunctionPass.lo -MD -MP -MF $(DEPDIR)/libllvmcodegen_la-MachineFunctionPass.Tpo -c -o libllvmcodegen_la-MachineFunctionPass.lo `test -f 'llvm/lib/CodeGen/MachineFunctionPass.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/MachineFunctionPass.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmcodegen_la-MachineFunctionPass.Tpo $(DEPDIR)/libllvmcodegen_la-MachineFunctionPass.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/CodeGen/MachineFunctionPass.cpp' object='libllvmcodegen_la-MachineFunctionPass.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmcodegen_la-MachineFunctionPass.lo `test -f 'llvm/lib/CodeGen/MachineFunctionPass.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/MachineFunctionPass.cpp + +libllvmcodegen_la-MachineInstr.lo: llvm/lib/CodeGen/MachineInstr.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmcodegen_la-MachineInstr.lo -MD -MP -MF $(DEPDIR)/libllvmcodegen_la-MachineInstr.Tpo -c -o libllvmcodegen_la-MachineInstr.lo `test -f 'llvm/lib/CodeGen/MachineInstr.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/MachineInstr.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmcodegen_la-MachineInstr.Tpo $(DEPDIR)/libllvmcodegen_la-MachineInstr.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/CodeGen/MachineInstr.cpp' object='libllvmcodegen_la-MachineInstr.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmcodegen_la-MachineInstr.lo `test -f 'llvm/lib/CodeGen/MachineInstr.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/MachineInstr.cpp + +libllvmcodegen_la-MachineLICM.lo: llvm/lib/CodeGen/MachineLICM.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmcodegen_la-MachineLICM.lo -MD -MP -MF $(DEPDIR)/libllvmcodegen_la-MachineLICM.Tpo -c -o libllvmcodegen_la-MachineLICM.lo `test -f 'llvm/lib/CodeGen/MachineLICM.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/MachineLICM.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmcodegen_la-MachineLICM.Tpo $(DEPDIR)/libllvmcodegen_la-MachineLICM.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/CodeGen/MachineLICM.cpp' object='libllvmcodegen_la-MachineLICM.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmcodegen_la-MachineLICM.lo `test -f 'llvm/lib/CodeGen/MachineLICM.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/MachineLICM.cpp + +libllvmcodegen_la-MachineLoopInfo.lo: llvm/lib/CodeGen/MachineLoopInfo.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmcodegen_la-MachineLoopInfo.lo -MD -MP -MF $(DEPDIR)/libllvmcodegen_la-MachineLoopInfo.Tpo -c -o libllvmcodegen_la-MachineLoopInfo.lo `test -f 'llvm/lib/CodeGen/MachineLoopInfo.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/MachineLoopInfo.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmcodegen_la-MachineLoopInfo.Tpo $(DEPDIR)/libllvmcodegen_la-MachineLoopInfo.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/CodeGen/MachineLoopInfo.cpp' object='libllvmcodegen_la-MachineLoopInfo.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmcodegen_la-MachineLoopInfo.lo `test -f 'llvm/lib/CodeGen/MachineLoopInfo.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/MachineLoopInfo.cpp + +libllvmcodegen_la-MachineModuleInfo.lo: llvm/lib/CodeGen/MachineModuleInfo.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmcodegen_la-MachineModuleInfo.lo -MD -MP -MF $(DEPDIR)/libllvmcodegen_la-MachineModuleInfo.Tpo -c -o libllvmcodegen_la-MachineModuleInfo.lo `test -f 'llvm/lib/CodeGen/MachineModuleInfo.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/MachineModuleInfo.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmcodegen_la-MachineModuleInfo.Tpo $(DEPDIR)/libllvmcodegen_la-MachineModuleInfo.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/CodeGen/MachineModuleInfo.cpp' object='libllvmcodegen_la-MachineModuleInfo.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmcodegen_la-MachineModuleInfo.lo `test -f 'llvm/lib/CodeGen/MachineModuleInfo.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/MachineModuleInfo.cpp + +libllvmcodegen_la-MachineModuleInfoImpls.lo: llvm/lib/CodeGen/MachineModuleInfoImpls.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmcodegen_la-MachineModuleInfoImpls.lo -MD -MP -MF $(DEPDIR)/libllvmcodegen_la-MachineModuleInfoImpls.Tpo -c -o libllvmcodegen_la-MachineModuleInfoImpls.lo `test -f 'llvm/lib/CodeGen/MachineModuleInfoImpls.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/MachineModuleInfoImpls.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmcodegen_la-MachineModuleInfoImpls.Tpo $(DEPDIR)/libllvmcodegen_la-MachineModuleInfoImpls.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/CodeGen/MachineModuleInfoImpls.cpp' object='libllvmcodegen_la-MachineModuleInfoImpls.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmcodegen_la-MachineModuleInfoImpls.lo `test -f 'llvm/lib/CodeGen/MachineModuleInfoImpls.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/MachineModuleInfoImpls.cpp + +libllvmcodegen_la-MachinePassRegistry.lo: llvm/lib/CodeGen/MachinePassRegistry.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmcodegen_la-MachinePassRegistry.lo -MD -MP -MF $(DEPDIR)/libllvmcodegen_la-MachinePassRegistry.Tpo -c -o libllvmcodegen_la-MachinePassRegistry.lo `test -f 'llvm/lib/CodeGen/MachinePassRegistry.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/MachinePassRegistry.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmcodegen_la-MachinePassRegistry.Tpo $(DEPDIR)/libllvmcodegen_la-MachinePassRegistry.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/CodeGen/MachinePassRegistry.cpp' object='libllvmcodegen_la-MachinePassRegistry.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmcodegen_la-MachinePassRegistry.lo `test -f 'llvm/lib/CodeGen/MachinePassRegistry.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/MachinePassRegistry.cpp + +libllvmcodegen_la-MachineRegisterInfo.lo: llvm/lib/CodeGen/MachineRegisterInfo.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmcodegen_la-MachineRegisterInfo.lo -MD -MP -MF $(DEPDIR)/libllvmcodegen_la-MachineRegisterInfo.Tpo -c -o libllvmcodegen_la-MachineRegisterInfo.lo `test -f 'llvm/lib/CodeGen/MachineRegisterInfo.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/MachineRegisterInfo.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmcodegen_la-MachineRegisterInfo.Tpo $(DEPDIR)/libllvmcodegen_la-MachineRegisterInfo.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/CodeGen/MachineRegisterInfo.cpp' object='libllvmcodegen_la-MachineRegisterInfo.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmcodegen_la-MachineRegisterInfo.lo `test -f 'llvm/lib/CodeGen/MachineRegisterInfo.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/MachineRegisterInfo.cpp + +libllvmcodegen_la-MachineSink.lo: llvm/lib/CodeGen/MachineSink.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmcodegen_la-MachineSink.lo -MD -MP -MF $(DEPDIR)/libllvmcodegen_la-MachineSink.Tpo -c -o libllvmcodegen_la-MachineSink.lo `test -f 'llvm/lib/CodeGen/MachineSink.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/MachineSink.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmcodegen_la-MachineSink.Tpo $(DEPDIR)/libllvmcodegen_la-MachineSink.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/CodeGen/MachineSink.cpp' object='libllvmcodegen_la-MachineSink.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmcodegen_la-MachineSink.lo `test -f 'llvm/lib/CodeGen/MachineSink.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/MachineSink.cpp + +libllvmcodegen_la-MachineVerifier.lo: llvm/lib/CodeGen/MachineVerifier.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmcodegen_la-MachineVerifier.lo -MD -MP -MF $(DEPDIR)/libllvmcodegen_la-MachineVerifier.Tpo -c -o libllvmcodegen_la-MachineVerifier.lo `test -f 'llvm/lib/CodeGen/MachineVerifier.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/MachineVerifier.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmcodegen_la-MachineVerifier.Tpo $(DEPDIR)/libllvmcodegen_la-MachineVerifier.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/CodeGen/MachineVerifier.cpp' object='libllvmcodegen_la-MachineVerifier.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmcodegen_la-MachineVerifier.lo `test -f 'llvm/lib/CodeGen/MachineVerifier.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/MachineVerifier.cpp + +libllvmcodegen_la-ObjectCodeEmitter.lo: llvm/lib/CodeGen/ObjectCodeEmitter.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmcodegen_la-ObjectCodeEmitter.lo -MD -MP -MF $(DEPDIR)/libllvmcodegen_la-ObjectCodeEmitter.Tpo -c -o libllvmcodegen_la-ObjectCodeEmitter.lo `test -f 'llvm/lib/CodeGen/ObjectCodeEmitter.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/ObjectCodeEmitter.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmcodegen_la-ObjectCodeEmitter.Tpo $(DEPDIR)/libllvmcodegen_la-ObjectCodeEmitter.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/CodeGen/ObjectCodeEmitter.cpp' object='libllvmcodegen_la-ObjectCodeEmitter.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmcodegen_la-ObjectCodeEmitter.lo `test -f 'llvm/lib/CodeGen/ObjectCodeEmitter.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/ObjectCodeEmitter.cpp + +libllvmcodegen_la-OcamlGC.lo: llvm/lib/CodeGen/OcamlGC.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmcodegen_la-OcamlGC.lo -MD -MP -MF $(DEPDIR)/libllvmcodegen_la-OcamlGC.Tpo -c -o libllvmcodegen_la-OcamlGC.lo `test -f 'llvm/lib/CodeGen/OcamlGC.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/OcamlGC.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmcodegen_la-OcamlGC.Tpo $(DEPDIR)/libllvmcodegen_la-OcamlGC.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/CodeGen/OcamlGC.cpp' object='libllvmcodegen_la-OcamlGC.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmcodegen_la-OcamlGC.lo `test -f 'llvm/lib/CodeGen/OcamlGC.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/OcamlGC.cpp + +libllvmcodegen_la-PHIElimination.lo: llvm/lib/CodeGen/PHIElimination.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmcodegen_la-PHIElimination.lo -MD -MP -MF $(DEPDIR)/libllvmcodegen_la-PHIElimination.Tpo -c -o libllvmcodegen_la-PHIElimination.lo `test -f 'llvm/lib/CodeGen/PHIElimination.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/PHIElimination.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmcodegen_la-PHIElimination.Tpo $(DEPDIR)/libllvmcodegen_la-PHIElimination.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/CodeGen/PHIElimination.cpp' object='libllvmcodegen_la-PHIElimination.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmcodegen_la-PHIElimination.lo `test -f 'llvm/lib/CodeGen/PHIElimination.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/PHIElimination.cpp + +libllvmcodegen_la-Passes.lo: llvm/lib/CodeGen/Passes.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmcodegen_la-Passes.lo -MD -MP -MF $(DEPDIR)/libllvmcodegen_la-Passes.Tpo -c -o libllvmcodegen_la-Passes.lo `test -f 'llvm/lib/CodeGen/Passes.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/Passes.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmcodegen_la-Passes.Tpo $(DEPDIR)/libllvmcodegen_la-Passes.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/CodeGen/Passes.cpp' object='libllvmcodegen_la-Passes.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmcodegen_la-Passes.lo `test -f 'llvm/lib/CodeGen/Passes.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/Passes.cpp + +libllvmcodegen_la-PostRASchedulerList.lo: llvm/lib/CodeGen/PostRASchedulerList.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmcodegen_la-PostRASchedulerList.lo -MD -MP -MF $(DEPDIR)/libllvmcodegen_la-PostRASchedulerList.Tpo -c -o libllvmcodegen_la-PostRASchedulerList.lo `test -f 'llvm/lib/CodeGen/PostRASchedulerList.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/PostRASchedulerList.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmcodegen_la-PostRASchedulerList.Tpo $(DEPDIR)/libllvmcodegen_la-PostRASchedulerList.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/CodeGen/PostRASchedulerList.cpp' object='libllvmcodegen_la-PostRASchedulerList.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmcodegen_la-PostRASchedulerList.lo `test -f 'llvm/lib/CodeGen/PostRASchedulerList.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/PostRASchedulerList.cpp + +libllvmcodegen_la-PreAllocSplitting.lo: llvm/lib/CodeGen/PreAllocSplitting.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmcodegen_la-PreAllocSplitting.lo -MD -MP -MF $(DEPDIR)/libllvmcodegen_la-PreAllocSplitting.Tpo -c -o libllvmcodegen_la-PreAllocSplitting.lo `test -f 'llvm/lib/CodeGen/PreAllocSplitting.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/PreAllocSplitting.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmcodegen_la-PreAllocSplitting.Tpo $(DEPDIR)/libllvmcodegen_la-PreAllocSplitting.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/CodeGen/PreAllocSplitting.cpp' object='libllvmcodegen_la-PreAllocSplitting.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmcodegen_la-PreAllocSplitting.lo `test -f 'llvm/lib/CodeGen/PreAllocSplitting.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/PreAllocSplitting.cpp + +libllvmcodegen_la-ProcessImplicitDefs.lo: llvm/lib/CodeGen/ProcessImplicitDefs.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmcodegen_la-ProcessImplicitDefs.lo -MD -MP -MF $(DEPDIR)/libllvmcodegen_la-ProcessImplicitDefs.Tpo -c -o libllvmcodegen_la-ProcessImplicitDefs.lo `test -f 'llvm/lib/CodeGen/ProcessImplicitDefs.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/ProcessImplicitDefs.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmcodegen_la-ProcessImplicitDefs.Tpo $(DEPDIR)/libllvmcodegen_la-ProcessImplicitDefs.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/CodeGen/ProcessImplicitDefs.cpp' object='libllvmcodegen_la-ProcessImplicitDefs.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmcodegen_la-ProcessImplicitDefs.lo `test -f 'llvm/lib/CodeGen/ProcessImplicitDefs.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/ProcessImplicitDefs.cpp + +libllvmcodegen_la-PrologEpilogInserter.lo: llvm/lib/CodeGen/PrologEpilogInserter.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmcodegen_la-PrologEpilogInserter.lo -MD -MP -MF $(DEPDIR)/libllvmcodegen_la-PrologEpilogInserter.Tpo -c -o libllvmcodegen_la-PrologEpilogInserter.lo `test -f 'llvm/lib/CodeGen/PrologEpilogInserter.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/PrologEpilogInserter.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmcodegen_la-PrologEpilogInserter.Tpo $(DEPDIR)/libllvmcodegen_la-PrologEpilogInserter.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/CodeGen/PrologEpilogInserter.cpp' object='libllvmcodegen_la-PrologEpilogInserter.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmcodegen_la-PrologEpilogInserter.lo `test -f 'llvm/lib/CodeGen/PrologEpilogInserter.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/PrologEpilogInserter.cpp + +libllvmcodegen_la-PseudoSourceValue.lo: llvm/lib/CodeGen/PseudoSourceValue.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmcodegen_la-PseudoSourceValue.lo -MD -MP -MF $(DEPDIR)/libllvmcodegen_la-PseudoSourceValue.Tpo -c -o libllvmcodegen_la-PseudoSourceValue.lo `test -f 'llvm/lib/CodeGen/PseudoSourceValue.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/PseudoSourceValue.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmcodegen_la-PseudoSourceValue.Tpo $(DEPDIR)/libllvmcodegen_la-PseudoSourceValue.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/CodeGen/PseudoSourceValue.cpp' object='libllvmcodegen_la-PseudoSourceValue.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmcodegen_la-PseudoSourceValue.lo `test -f 'llvm/lib/CodeGen/PseudoSourceValue.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/PseudoSourceValue.cpp + +libllvmcodegen_la-RegAllocLinearScan.lo: llvm/lib/CodeGen/RegAllocLinearScan.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmcodegen_la-RegAllocLinearScan.lo -MD -MP -MF $(DEPDIR)/libllvmcodegen_la-RegAllocLinearScan.Tpo -c -o libllvmcodegen_la-RegAllocLinearScan.lo `test -f 'llvm/lib/CodeGen/RegAllocLinearScan.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/RegAllocLinearScan.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmcodegen_la-RegAllocLinearScan.Tpo $(DEPDIR)/libllvmcodegen_la-RegAllocLinearScan.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/CodeGen/RegAllocLinearScan.cpp' object='libllvmcodegen_la-RegAllocLinearScan.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmcodegen_la-RegAllocLinearScan.lo `test -f 'llvm/lib/CodeGen/RegAllocLinearScan.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/RegAllocLinearScan.cpp + +libllvmcodegen_la-RegAllocLocal.lo: llvm/lib/CodeGen/RegAllocLocal.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmcodegen_la-RegAllocLocal.lo -MD -MP -MF $(DEPDIR)/libllvmcodegen_la-RegAllocLocal.Tpo -c -o libllvmcodegen_la-RegAllocLocal.lo `test -f 'llvm/lib/CodeGen/RegAllocLocal.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/RegAllocLocal.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmcodegen_la-RegAllocLocal.Tpo $(DEPDIR)/libllvmcodegen_la-RegAllocLocal.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/CodeGen/RegAllocLocal.cpp' object='libllvmcodegen_la-RegAllocLocal.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmcodegen_la-RegAllocLocal.lo `test -f 'llvm/lib/CodeGen/RegAllocLocal.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/RegAllocLocal.cpp + +libllvmcodegen_la-RegAllocPBQP.lo: llvm/lib/CodeGen/RegAllocPBQP.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmcodegen_la-RegAllocPBQP.lo -MD -MP -MF $(DEPDIR)/libllvmcodegen_la-RegAllocPBQP.Tpo -c -o libllvmcodegen_la-RegAllocPBQP.lo `test -f 'llvm/lib/CodeGen/RegAllocPBQP.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/RegAllocPBQP.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmcodegen_la-RegAllocPBQP.Tpo $(DEPDIR)/libllvmcodegen_la-RegAllocPBQP.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/CodeGen/RegAllocPBQP.cpp' object='libllvmcodegen_la-RegAllocPBQP.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmcodegen_la-RegAllocPBQP.lo `test -f 'llvm/lib/CodeGen/RegAllocPBQP.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/RegAllocPBQP.cpp + +libllvmcodegen_la-RegisterCoalescer.lo: llvm/lib/CodeGen/RegisterCoalescer.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmcodegen_la-RegisterCoalescer.lo -MD -MP -MF $(DEPDIR)/libllvmcodegen_la-RegisterCoalescer.Tpo -c -o libllvmcodegen_la-RegisterCoalescer.lo `test -f 'llvm/lib/CodeGen/RegisterCoalescer.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/RegisterCoalescer.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmcodegen_la-RegisterCoalescer.Tpo $(DEPDIR)/libllvmcodegen_la-RegisterCoalescer.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/CodeGen/RegisterCoalescer.cpp' object='libllvmcodegen_la-RegisterCoalescer.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmcodegen_la-RegisterCoalescer.lo `test -f 'llvm/lib/CodeGen/RegisterCoalescer.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/RegisterCoalescer.cpp + +libllvmcodegen_la-RegisterScavenging.lo: llvm/lib/CodeGen/RegisterScavenging.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmcodegen_la-RegisterScavenging.lo -MD -MP -MF $(DEPDIR)/libllvmcodegen_la-RegisterScavenging.Tpo -c -o libllvmcodegen_la-RegisterScavenging.lo `test -f 'llvm/lib/CodeGen/RegisterScavenging.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/RegisterScavenging.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmcodegen_la-RegisterScavenging.Tpo $(DEPDIR)/libllvmcodegen_la-RegisterScavenging.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/CodeGen/RegisterScavenging.cpp' object='libllvmcodegen_la-RegisterScavenging.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmcodegen_la-RegisterScavenging.lo `test -f 'llvm/lib/CodeGen/RegisterScavenging.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/RegisterScavenging.cpp + +libllvmcodegen_la-ScheduleDAG.lo: llvm/lib/CodeGen/ScheduleDAG.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmcodegen_la-ScheduleDAG.lo -MD -MP -MF $(DEPDIR)/libllvmcodegen_la-ScheduleDAG.Tpo -c -o libllvmcodegen_la-ScheduleDAG.lo `test -f 'llvm/lib/CodeGen/ScheduleDAG.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/ScheduleDAG.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmcodegen_la-ScheduleDAG.Tpo $(DEPDIR)/libllvmcodegen_la-ScheduleDAG.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/CodeGen/ScheduleDAG.cpp' object='libllvmcodegen_la-ScheduleDAG.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmcodegen_la-ScheduleDAG.lo `test -f 'llvm/lib/CodeGen/ScheduleDAG.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/ScheduleDAG.cpp + +libllvmcodegen_la-ScheduleDAGEmit.lo: llvm/lib/CodeGen/ScheduleDAGEmit.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmcodegen_la-ScheduleDAGEmit.lo -MD -MP -MF $(DEPDIR)/libllvmcodegen_la-ScheduleDAGEmit.Tpo -c -o libllvmcodegen_la-ScheduleDAGEmit.lo `test -f 'llvm/lib/CodeGen/ScheduleDAGEmit.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/ScheduleDAGEmit.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmcodegen_la-ScheduleDAGEmit.Tpo $(DEPDIR)/libllvmcodegen_la-ScheduleDAGEmit.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/CodeGen/ScheduleDAGEmit.cpp' object='libllvmcodegen_la-ScheduleDAGEmit.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmcodegen_la-ScheduleDAGEmit.lo `test -f 'llvm/lib/CodeGen/ScheduleDAGEmit.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/ScheduleDAGEmit.cpp + +libllvmcodegen_la-ScheduleDAGInstrs.lo: llvm/lib/CodeGen/ScheduleDAGInstrs.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmcodegen_la-ScheduleDAGInstrs.lo -MD -MP -MF $(DEPDIR)/libllvmcodegen_la-ScheduleDAGInstrs.Tpo -c -o libllvmcodegen_la-ScheduleDAGInstrs.lo `test -f 'llvm/lib/CodeGen/ScheduleDAGInstrs.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/ScheduleDAGInstrs.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmcodegen_la-ScheduleDAGInstrs.Tpo $(DEPDIR)/libllvmcodegen_la-ScheduleDAGInstrs.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/CodeGen/ScheduleDAGInstrs.cpp' object='libllvmcodegen_la-ScheduleDAGInstrs.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmcodegen_la-ScheduleDAGInstrs.lo `test -f 'llvm/lib/CodeGen/ScheduleDAGInstrs.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/ScheduleDAGInstrs.cpp + +libllvmcodegen_la-ScheduleDAGPrinter.lo: llvm/lib/CodeGen/ScheduleDAGPrinter.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmcodegen_la-ScheduleDAGPrinter.lo -MD -MP -MF $(DEPDIR)/libllvmcodegen_la-ScheduleDAGPrinter.Tpo -c -o libllvmcodegen_la-ScheduleDAGPrinter.lo `test -f 'llvm/lib/CodeGen/ScheduleDAGPrinter.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/ScheduleDAGPrinter.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmcodegen_la-ScheduleDAGPrinter.Tpo $(DEPDIR)/libllvmcodegen_la-ScheduleDAGPrinter.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/CodeGen/ScheduleDAGPrinter.cpp' object='libllvmcodegen_la-ScheduleDAGPrinter.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmcodegen_la-ScheduleDAGPrinter.lo `test -f 'llvm/lib/CodeGen/ScheduleDAGPrinter.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/ScheduleDAGPrinter.cpp + +libllvmcodegen_la-ShadowStackGC.lo: llvm/lib/CodeGen/ShadowStackGC.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmcodegen_la-ShadowStackGC.lo -MD -MP -MF $(DEPDIR)/libllvmcodegen_la-ShadowStackGC.Tpo -c -o libllvmcodegen_la-ShadowStackGC.lo `test -f 'llvm/lib/CodeGen/ShadowStackGC.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/ShadowStackGC.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmcodegen_la-ShadowStackGC.Tpo $(DEPDIR)/libllvmcodegen_la-ShadowStackGC.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/CodeGen/ShadowStackGC.cpp' object='libllvmcodegen_la-ShadowStackGC.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmcodegen_la-ShadowStackGC.lo `test -f 'llvm/lib/CodeGen/ShadowStackGC.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/ShadowStackGC.cpp + +libllvmcodegen_la-ShrinkWrapping.lo: llvm/lib/CodeGen/ShrinkWrapping.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmcodegen_la-ShrinkWrapping.lo -MD -MP -MF $(DEPDIR)/libllvmcodegen_la-ShrinkWrapping.Tpo -c -o libllvmcodegen_la-ShrinkWrapping.lo `test -f 'llvm/lib/CodeGen/ShrinkWrapping.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/ShrinkWrapping.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmcodegen_la-ShrinkWrapping.Tpo $(DEPDIR)/libllvmcodegen_la-ShrinkWrapping.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/CodeGen/ShrinkWrapping.cpp' object='libllvmcodegen_la-ShrinkWrapping.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmcodegen_la-ShrinkWrapping.lo `test -f 'llvm/lib/CodeGen/ShrinkWrapping.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/ShrinkWrapping.cpp + +libllvmcodegen_la-SimpleRegisterCoalescing.lo: llvm/lib/CodeGen/SimpleRegisterCoalescing.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmcodegen_la-SimpleRegisterCoalescing.lo -MD -MP -MF $(DEPDIR)/libllvmcodegen_la-SimpleRegisterCoalescing.Tpo -c -o libllvmcodegen_la-SimpleRegisterCoalescing.lo `test -f 'llvm/lib/CodeGen/SimpleRegisterCoalescing.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/SimpleRegisterCoalescing.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmcodegen_la-SimpleRegisterCoalescing.Tpo $(DEPDIR)/libllvmcodegen_la-SimpleRegisterCoalescing.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/CodeGen/SimpleRegisterCoalescing.cpp' object='libllvmcodegen_la-SimpleRegisterCoalescing.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmcodegen_la-SimpleRegisterCoalescing.lo `test -f 'llvm/lib/CodeGen/SimpleRegisterCoalescing.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/SimpleRegisterCoalescing.cpp + +libllvmcodegen_la-SjLjEHPrepare.lo: llvm/lib/CodeGen/SjLjEHPrepare.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmcodegen_la-SjLjEHPrepare.lo -MD -MP -MF $(DEPDIR)/libllvmcodegen_la-SjLjEHPrepare.Tpo -c -o libllvmcodegen_la-SjLjEHPrepare.lo `test -f 'llvm/lib/CodeGen/SjLjEHPrepare.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/SjLjEHPrepare.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmcodegen_la-SjLjEHPrepare.Tpo $(DEPDIR)/libllvmcodegen_la-SjLjEHPrepare.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/CodeGen/SjLjEHPrepare.cpp' object='libllvmcodegen_la-SjLjEHPrepare.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmcodegen_la-SjLjEHPrepare.lo `test -f 'llvm/lib/CodeGen/SjLjEHPrepare.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/SjLjEHPrepare.cpp + +libllvmcodegen_la-SlotIndexes.lo: llvm/lib/CodeGen/SlotIndexes.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmcodegen_la-SlotIndexes.lo -MD -MP -MF $(DEPDIR)/libllvmcodegen_la-SlotIndexes.Tpo -c -o libllvmcodegen_la-SlotIndexes.lo `test -f 'llvm/lib/CodeGen/SlotIndexes.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/SlotIndexes.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmcodegen_la-SlotIndexes.Tpo $(DEPDIR)/libllvmcodegen_la-SlotIndexes.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/CodeGen/SlotIndexes.cpp' object='libllvmcodegen_la-SlotIndexes.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmcodegen_la-SlotIndexes.lo `test -f 'llvm/lib/CodeGen/SlotIndexes.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/SlotIndexes.cpp + +libllvmcodegen_la-Spiller.lo: llvm/lib/CodeGen/Spiller.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmcodegen_la-Spiller.lo -MD -MP -MF $(DEPDIR)/libllvmcodegen_la-Spiller.Tpo -c -o libllvmcodegen_la-Spiller.lo `test -f 'llvm/lib/CodeGen/Spiller.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/Spiller.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmcodegen_la-Spiller.Tpo $(DEPDIR)/libllvmcodegen_la-Spiller.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/CodeGen/Spiller.cpp' object='libllvmcodegen_la-Spiller.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmcodegen_la-Spiller.lo `test -f 'llvm/lib/CodeGen/Spiller.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/Spiller.cpp + +libllvmcodegen_la-StackProtector.lo: llvm/lib/CodeGen/StackProtector.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmcodegen_la-StackProtector.lo -MD -MP -MF $(DEPDIR)/libllvmcodegen_la-StackProtector.Tpo -c -o libllvmcodegen_la-StackProtector.lo `test -f 'llvm/lib/CodeGen/StackProtector.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/StackProtector.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmcodegen_la-StackProtector.Tpo $(DEPDIR)/libllvmcodegen_la-StackProtector.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/CodeGen/StackProtector.cpp' object='libllvmcodegen_la-StackProtector.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmcodegen_la-StackProtector.lo `test -f 'llvm/lib/CodeGen/StackProtector.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/StackProtector.cpp + +libllvmcodegen_la-StackSlotColoring.lo: llvm/lib/CodeGen/StackSlotColoring.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmcodegen_la-StackSlotColoring.lo -MD -MP -MF $(DEPDIR)/libllvmcodegen_la-StackSlotColoring.Tpo -c -o libllvmcodegen_la-StackSlotColoring.lo `test -f 'llvm/lib/CodeGen/StackSlotColoring.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/StackSlotColoring.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmcodegen_la-StackSlotColoring.Tpo $(DEPDIR)/libllvmcodegen_la-StackSlotColoring.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/CodeGen/StackSlotColoring.cpp' object='libllvmcodegen_la-StackSlotColoring.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmcodegen_la-StackSlotColoring.lo `test -f 'llvm/lib/CodeGen/StackSlotColoring.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/StackSlotColoring.cpp + +libllvmcodegen_la-StrongPHIElimination.lo: llvm/lib/CodeGen/StrongPHIElimination.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmcodegen_la-StrongPHIElimination.lo -MD -MP -MF $(DEPDIR)/libllvmcodegen_la-StrongPHIElimination.Tpo -c -o libllvmcodegen_la-StrongPHIElimination.lo `test -f 'llvm/lib/CodeGen/StrongPHIElimination.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/StrongPHIElimination.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmcodegen_la-StrongPHIElimination.Tpo $(DEPDIR)/libllvmcodegen_la-StrongPHIElimination.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/CodeGen/StrongPHIElimination.cpp' object='libllvmcodegen_la-StrongPHIElimination.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmcodegen_la-StrongPHIElimination.lo `test -f 'llvm/lib/CodeGen/StrongPHIElimination.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/StrongPHIElimination.cpp + +libllvmcodegen_la-TailDuplication.lo: llvm/lib/CodeGen/TailDuplication.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmcodegen_la-TailDuplication.lo -MD -MP -MF $(DEPDIR)/libllvmcodegen_la-TailDuplication.Tpo -c -o libllvmcodegen_la-TailDuplication.lo `test -f 'llvm/lib/CodeGen/TailDuplication.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/TailDuplication.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmcodegen_la-TailDuplication.Tpo $(DEPDIR)/libllvmcodegen_la-TailDuplication.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/CodeGen/TailDuplication.cpp' object='libllvmcodegen_la-TailDuplication.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmcodegen_la-TailDuplication.lo `test -f 'llvm/lib/CodeGen/TailDuplication.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/TailDuplication.cpp + +libllvmcodegen_la-TargetInstrInfoImpl.lo: llvm/lib/CodeGen/TargetInstrInfoImpl.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmcodegen_la-TargetInstrInfoImpl.lo -MD -MP -MF $(DEPDIR)/libllvmcodegen_la-TargetInstrInfoImpl.Tpo -c -o libllvmcodegen_la-TargetInstrInfoImpl.lo `test -f 'llvm/lib/CodeGen/TargetInstrInfoImpl.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/TargetInstrInfoImpl.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmcodegen_la-TargetInstrInfoImpl.Tpo $(DEPDIR)/libllvmcodegen_la-TargetInstrInfoImpl.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/CodeGen/TargetInstrInfoImpl.cpp' object='libllvmcodegen_la-TargetInstrInfoImpl.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmcodegen_la-TargetInstrInfoImpl.lo `test -f 'llvm/lib/CodeGen/TargetInstrInfoImpl.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/TargetInstrInfoImpl.cpp + +libllvmcodegen_la-TwoAddressInstructionPass.lo: llvm/lib/CodeGen/TwoAddressInstructionPass.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmcodegen_la-TwoAddressInstructionPass.lo -MD -MP -MF $(DEPDIR)/libllvmcodegen_la-TwoAddressInstructionPass.Tpo -c -o libllvmcodegen_la-TwoAddressInstructionPass.lo `test -f 'llvm/lib/CodeGen/TwoAddressInstructionPass.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/TwoAddressInstructionPass.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmcodegen_la-TwoAddressInstructionPass.Tpo $(DEPDIR)/libllvmcodegen_la-TwoAddressInstructionPass.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/CodeGen/TwoAddressInstructionPass.cpp' object='libllvmcodegen_la-TwoAddressInstructionPass.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmcodegen_la-TwoAddressInstructionPass.lo `test -f 'llvm/lib/CodeGen/TwoAddressInstructionPass.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/TwoAddressInstructionPass.cpp + +libllvmcodegen_la-UnreachableBlockElim.lo: llvm/lib/CodeGen/UnreachableBlockElim.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmcodegen_la-UnreachableBlockElim.lo -MD -MP -MF $(DEPDIR)/libllvmcodegen_la-UnreachableBlockElim.Tpo -c -o libllvmcodegen_la-UnreachableBlockElim.lo `test -f 'llvm/lib/CodeGen/UnreachableBlockElim.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/UnreachableBlockElim.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmcodegen_la-UnreachableBlockElim.Tpo $(DEPDIR)/libllvmcodegen_la-UnreachableBlockElim.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/CodeGen/UnreachableBlockElim.cpp' object='libllvmcodegen_la-UnreachableBlockElim.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmcodegen_la-UnreachableBlockElim.lo `test -f 'llvm/lib/CodeGen/UnreachableBlockElim.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/UnreachableBlockElim.cpp + +libllvmcodegen_la-VirtRegMap.lo: llvm/lib/CodeGen/VirtRegMap.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmcodegen_la-VirtRegMap.lo -MD -MP -MF $(DEPDIR)/libllvmcodegen_la-VirtRegMap.Tpo -c -o libllvmcodegen_la-VirtRegMap.lo `test -f 'llvm/lib/CodeGen/VirtRegMap.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/VirtRegMap.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmcodegen_la-VirtRegMap.Tpo $(DEPDIR)/libllvmcodegen_la-VirtRegMap.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/CodeGen/VirtRegMap.cpp' object='libllvmcodegen_la-VirtRegMap.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmcodegen_la-VirtRegMap.lo `test -f 'llvm/lib/CodeGen/VirtRegMap.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/VirtRegMap.cpp + +libllvmcodegen_la-VirtRegRewriter.lo: llvm/lib/CodeGen/VirtRegRewriter.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmcodegen_la-VirtRegRewriter.lo -MD -MP -MF $(DEPDIR)/libllvmcodegen_la-VirtRegRewriter.Tpo -c -o libllvmcodegen_la-VirtRegRewriter.lo `test -f 'llvm/lib/CodeGen/VirtRegRewriter.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/VirtRegRewriter.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmcodegen_la-VirtRegRewriter.Tpo $(DEPDIR)/libllvmcodegen_la-VirtRegRewriter.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/CodeGen/VirtRegRewriter.cpp' object='libllvmcodegen_la-VirtRegRewriter.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcodegen_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcodegen_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmcodegen_la-VirtRegRewriter.lo `test -f 'llvm/lib/CodeGen/VirtRegRewriter.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/VirtRegRewriter.cpp + +libllvmcore_la-AsmWriter.lo: llvm/lib/VMCore/AsmWriter.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcore_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcore_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmcore_la-AsmWriter.lo -MD -MP -MF $(DEPDIR)/libllvmcore_la-AsmWriter.Tpo -c -o libllvmcore_la-AsmWriter.lo `test -f 'llvm/lib/VMCore/AsmWriter.cpp' || echo '$(srcdir)/'`llvm/lib/VMCore/AsmWriter.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmcore_la-AsmWriter.Tpo $(DEPDIR)/libllvmcore_la-AsmWriter.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/VMCore/AsmWriter.cpp' object='libllvmcore_la-AsmWriter.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcore_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcore_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmcore_la-AsmWriter.lo `test -f 'llvm/lib/VMCore/AsmWriter.cpp' || echo '$(srcdir)/'`llvm/lib/VMCore/AsmWriter.cpp + +libllvmcore_la-Attributes.lo: llvm/lib/VMCore/Attributes.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcore_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcore_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmcore_la-Attributes.lo -MD -MP -MF $(DEPDIR)/libllvmcore_la-Attributes.Tpo -c -o libllvmcore_la-Attributes.lo `test -f 'llvm/lib/VMCore/Attributes.cpp' || echo '$(srcdir)/'`llvm/lib/VMCore/Attributes.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmcore_la-Attributes.Tpo $(DEPDIR)/libllvmcore_la-Attributes.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/VMCore/Attributes.cpp' object='libllvmcore_la-Attributes.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcore_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcore_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmcore_la-Attributes.lo `test -f 'llvm/lib/VMCore/Attributes.cpp' || echo '$(srcdir)/'`llvm/lib/VMCore/Attributes.cpp + +libllvmcore_la-AutoUpgrade.lo: llvm/lib/VMCore/AutoUpgrade.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcore_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcore_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmcore_la-AutoUpgrade.lo -MD -MP -MF $(DEPDIR)/libllvmcore_la-AutoUpgrade.Tpo -c -o libllvmcore_la-AutoUpgrade.lo `test -f 'llvm/lib/VMCore/AutoUpgrade.cpp' || echo '$(srcdir)/'`llvm/lib/VMCore/AutoUpgrade.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmcore_la-AutoUpgrade.Tpo $(DEPDIR)/libllvmcore_la-AutoUpgrade.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/VMCore/AutoUpgrade.cpp' object='libllvmcore_la-AutoUpgrade.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcore_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcore_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmcore_la-AutoUpgrade.lo `test -f 'llvm/lib/VMCore/AutoUpgrade.cpp' || echo '$(srcdir)/'`llvm/lib/VMCore/AutoUpgrade.cpp + +libllvmcore_la-BasicBlock.lo: llvm/lib/VMCore/BasicBlock.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcore_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcore_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmcore_la-BasicBlock.lo -MD -MP -MF $(DEPDIR)/libllvmcore_la-BasicBlock.Tpo -c -o libllvmcore_la-BasicBlock.lo `test -f 'llvm/lib/VMCore/BasicBlock.cpp' || echo '$(srcdir)/'`llvm/lib/VMCore/BasicBlock.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmcore_la-BasicBlock.Tpo $(DEPDIR)/libllvmcore_la-BasicBlock.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/VMCore/BasicBlock.cpp' object='libllvmcore_la-BasicBlock.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcore_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcore_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmcore_la-BasicBlock.lo `test -f 'llvm/lib/VMCore/BasicBlock.cpp' || echo '$(srcdir)/'`llvm/lib/VMCore/BasicBlock.cpp + +libllvmcore_la-ConstantFold.lo: llvm/lib/VMCore/ConstantFold.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcore_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcore_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmcore_la-ConstantFold.lo -MD -MP -MF $(DEPDIR)/libllvmcore_la-ConstantFold.Tpo -c -o libllvmcore_la-ConstantFold.lo `test -f 'llvm/lib/VMCore/ConstantFold.cpp' || echo '$(srcdir)/'`llvm/lib/VMCore/ConstantFold.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmcore_la-ConstantFold.Tpo $(DEPDIR)/libllvmcore_la-ConstantFold.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/VMCore/ConstantFold.cpp' object='libllvmcore_la-ConstantFold.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcore_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcore_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmcore_la-ConstantFold.lo `test -f 'llvm/lib/VMCore/ConstantFold.cpp' || echo '$(srcdir)/'`llvm/lib/VMCore/ConstantFold.cpp + +libllvmcore_la-Constants.lo: llvm/lib/VMCore/Constants.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcore_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcore_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmcore_la-Constants.lo -MD -MP -MF $(DEPDIR)/libllvmcore_la-Constants.Tpo -c -o libllvmcore_la-Constants.lo `test -f 'llvm/lib/VMCore/Constants.cpp' || echo '$(srcdir)/'`llvm/lib/VMCore/Constants.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmcore_la-Constants.Tpo $(DEPDIR)/libllvmcore_la-Constants.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/VMCore/Constants.cpp' object='libllvmcore_la-Constants.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcore_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcore_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmcore_la-Constants.lo `test -f 'llvm/lib/VMCore/Constants.cpp' || echo '$(srcdir)/'`llvm/lib/VMCore/Constants.cpp + +libllvmcore_la-Core.lo: llvm/lib/VMCore/Core.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcore_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcore_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmcore_la-Core.lo -MD -MP -MF $(DEPDIR)/libllvmcore_la-Core.Tpo -c -o libllvmcore_la-Core.lo `test -f 'llvm/lib/VMCore/Core.cpp' || echo '$(srcdir)/'`llvm/lib/VMCore/Core.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmcore_la-Core.Tpo $(DEPDIR)/libllvmcore_la-Core.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/VMCore/Core.cpp' object='libllvmcore_la-Core.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcore_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcore_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmcore_la-Core.lo `test -f 'llvm/lib/VMCore/Core.cpp' || echo '$(srcdir)/'`llvm/lib/VMCore/Core.cpp + +libllvmcore_la-Dominators.lo: llvm/lib/VMCore/Dominators.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcore_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcore_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmcore_la-Dominators.lo -MD -MP -MF $(DEPDIR)/libllvmcore_la-Dominators.Tpo -c -o libllvmcore_la-Dominators.lo `test -f 'llvm/lib/VMCore/Dominators.cpp' || echo '$(srcdir)/'`llvm/lib/VMCore/Dominators.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmcore_la-Dominators.Tpo $(DEPDIR)/libllvmcore_la-Dominators.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/VMCore/Dominators.cpp' object='libllvmcore_la-Dominators.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcore_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcore_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmcore_la-Dominators.lo `test -f 'llvm/lib/VMCore/Dominators.cpp' || echo '$(srcdir)/'`llvm/lib/VMCore/Dominators.cpp + +libllvmcore_la-Function.lo: llvm/lib/VMCore/Function.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcore_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcore_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmcore_la-Function.lo -MD -MP -MF $(DEPDIR)/libllvmcore_la-Function.Tpo -c -o libllvmcore_la-Function.lo `test -f 'llvm/lib/VMCore/Function.cpp' || echo '$(srcdir)/'`llvm/lib/VMCore/Function.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmcore_la-Function.Tpo $(DEPDIR)/libllvmcore_la-Function.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/VMCore/Function.cpp' object='libllvmcore_la-Function.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcore_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcore_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmcore_la-Function.lo `test -f 'llvm/lib/VMCore/Function.cpp' || echo '$(srcdir)/'`llvm/lib/VMCore/Function.cpp + +libllvmcore_la-Globals.lo: llvm/lib/VMCore/Globals.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcore_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcore_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmcore_la-Globals.lo -MD -MP -MF $(DEPDIR)/libllvmcore_la-Globals.Tpo -c -o libllvmcore_la-Globals.lo `test -f 'llvm/lib/VMCore/Globals.cpp' || echo '$(srcdir)/'`llvm/lib/VMCore/Globals.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmcore_la-Globals.Tpo $(DEPDIR)/libllvmcore_la-Globals.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/VMCore/Globals.cpp' object='libllvmcore_la-Globals.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcore_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcore_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmcore_la-Globals.lo `test -f 'llvm/lib/VMCore/Globals.cpp' || echo '$(srcdir)/'`llvm/lib/VMCore/Globals.cpp + +libllvmcore_la-InlineAsm.lo: llvm/lib/VMCore/InlineAsm.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcore_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcore_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmcore_la-InlineAsm.lo -MD -MP -MF $(DEPDIR)/libllvmcore_la-InlineAsm.Tpo -c -o libllvmcore_la-InlineAsm.lo `test -f 'llvm/lib/VMCore/InlineAsm.cpp' || echo '$(srcdir)/'`llvm/lib/VMCore/InlineAsm.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmcore_la-InlineAsm.Tpo $(DEPDIR)/libllvmcore_la-InlineAsm.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/VMCore/InlineAsm.cpp' object='libllvmcore_la-InlineAsm.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcore_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcore_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmcore_la-InlineAsm.lo `test -f 'llvm/lib/VMCore/InlineAsm.cpp' || echo '$(srcdir)/'`llvm/lib/VMCore/InlineAsm.cpp + +libllvmcore_la-Instruction.lo: llvm/lib/VMCore/Instruction.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcore_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcore_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmcore_la-Instruction.lo -MD -MP -MF $(DEPDIR)/libllvmcore_la-Instruction.Tpo -c -o libllvmcore_la-Instruction.lo `test -f 'llvm/lib/VMCore/Instruction.cpp' || echo '$(srcdir)/'`llvm/lib/VMCore/Instruction.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmcore_la-Instruction.Tpo $(DEPDIR)/libllvmcore_la-Instruction.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/VMCore/Instruction.cpp' object='libllvmcore_la-Instruction.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcore_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcore_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmcore_la-Instruction.lo `test -f 'llvm/lib/VMCore/Instruction.cpp' || echo '$(srcdir)/'`llvm/lib/VMCore/Instruction.cpp + +libllvmcore_la-Instructions.lo: llvm/lib/VMCore/Instructions.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcore_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcore_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmcore_la-Instructions.lo -MD -MP -MF $(DEPDIR)/libllvmcore_la-Instructions.Tpo -c -o libllvmcore_la-Instructions.lo `test -f 'llvm/lib/VMCore/Instructions.cpp' || echo '$(srcdir)/'`llvm/lib/VMCore/Instructions.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmcore_la-Instructions.Tpo $(DEPDIR)/libllvmcore_la-Instructions.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/VMCore/Instructions.cpp' object='libllvmcore_la-Instructions.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcore_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcore_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmcore_la-Instructions.lo `test -f 'llvm/lib/VMCore/Instructions.cpp' || echo '$(srcdir)/'`llvm/lib/VMCore/Instructions.cpp + +libllvmcore_la-IntrinsicInst.lo: llvm/lib/VMCore/IntrinsicInst.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcore_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcore_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmcore_la-IntrinsicInst.lo -MD -MP -MF $(DEPDIR)/libllvmcore_la-IntrinsicInst.Tpo -c -o libllvmcore_la-IntrinsicInst.lo `test -f 'llvm/lib/VMCore/IntrinsicInst.cpp' || echo '$(srcdir)/'`llvm/lib/VMCore/IntrinsicInst.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmcore_la-IntrinsicInst.Tpo $(DEPDIR)/libllvmcore_la-IntrinsicInst.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/VMCore/IntrinsicInst.cpp' object='libllvmcore_la-IntrinsicInst.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcore_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcore_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmcore_la-IntrinsicInst.lo `test -f 'llvm/lib/VMCore/IntrinsicInst.cpp' || echo '$(srcdir)/'`llvm/lib/VMCore/IntrinsicInst.cpp + +libllvmcore_la-LLVMContext.lo: llvm/lib/VMCore/LLVMContext.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcore_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcore_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmcore_la-LLVMContext.lo -MD -MP -MF $(DEPDIR)/libllvmcore_la-LLVMContext.Tpo -c -o libllvmcore_la-LLVMContext.lo `test -f 'llvm/lib/VMCore/LLVMContext.cpp' || echo '$(srcdir)/'`llvm/lib/VMCore/LLVMContext.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmcore_la-LLVMContext.Tpo $(DEPDIR)/libllvmcore_la-LLVMContext.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/VMCore/LLVMContext.cpp' object='libllvmcore_la-LLVMContext.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcore_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcore_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmcore_la-LLVMContext.lo `test -f 'llvm/lib/VMCore/LLVMContext.cpp' || echo '$(srcdir)/'`llvm/lib/VMCore/LLVMContext.cpp + +libllvmcore_la-LeakDetector.lo: llvm/lib/VMCore/LeakDetector.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcore_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcore_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmcore_la-LeakDetector.lo -MD -MP -MF $(DEPDIR)/libllvmcore_la-LeakDetector.Tpo -c -o libllvmcore_la-LeakDetector.lo `test -f 'llvm/lib/VMCore/LeakDetector.cpp' || echo '$(srcdir)/'`llvm/lib/VMCore/LeakDetector.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmcore_la-LeakDetector.Tpo $(DEPDIR)/libllvmcore_la-LeakDetector.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/VMCore/LeakDetector.cpp' object='libllvmcore_la-LeakDetector.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcore_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcore_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmcore_la-LeakDetector.lo `test -f 'llvm/lib/VMCore/LeakDetector.cpp' || echo '$(srcdir)/'`llvm/lib/VMCore/LeakDetector.cpp + +libllvmcore_la-Mangler.lo: llvm/lib/VMCore/Mangler.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcore_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcore_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmcore_la-Mangler.lo -MD -MP -MF $(DEPDIR)/libllvmcore_la-Mangler.Tpo -c -o libllvmcore_la-Mangler.lo `test -f 'llvm/lib/VMCore/Mangler.cpp' || echo '$(srcdir)/'`llvm/lib/VMCore/Mangler.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmcore_la-Mangler.Tpo $(DEPDIR)/libllvmcore_la-Mangler.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/VMCore/Mangler.cpp' object='libllvmcore_la-Mangler.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcore_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcore_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmcore_la-Mangler.lo `test -f 'llvm/lib/VMCore/Mangler.cpp' || echo '$(srcdir)/'`llvm/lib/VMCore/Mangler.cpp + +libllvmcore_la-Metadata.lo: llvm/lib/VMCore/Metadata.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcore_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcore_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmcore_la-Metadata.lo -MD -MP -MF $(DEPDIR)/libllvmcore_la-Metadata.Tpo -c -o libllvmcore_la-Metadata.lo `test -f 'llvm/lib/VMCore/Metadata.cpp' || echo '$(srcdir)/'`llvm/lib/VMCore/Metadata.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmcore_la-Metadata.Tpo $(DEPDIR)/libllvmcore_la-Metadata.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/VMCore/Metadata.cpp' object='libllvmcore_la-Metadata.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcore_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcore_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmcore_la-Metadata.lo `test -f 'llvm/lib/VMCore/Metadata.cpp' || echo '$(srcdir)/'`llvm/lib/VMCore/Metadata.cpp + +libllvmcore_la-Module.lo: llvm/lib/VMCore/Module.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcore_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcore_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmcore_la-Module.lo -MD -MP -MF $(DEPDIR)/libllvmcore_la-Module.Tpo -c -o libllvmcore_la-Module.lo `test -f 'llvm/lib/VMCore/Module.cpp' || echo '$(srcdir)/'`llvm/lib/VMCore/Module.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmcore_la-Module.Tpo $(DEPDIR)/libllvmcore_la-Module.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/VMCore/Module.cpp' object='libllvmcore_la-Module.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcore_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcore_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmcore_la-Module.lo `test -f 'llvm/lib/VMCore/Module.cpp' || echo '$(srcdir)/'`llvm/lib/VMCore/Module.cpp + +libllvmcore_la-ModuleProvider.lo: llvm/lib/VMCore/ModuleProvider.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcore_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcore_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmcore_la-ModuleProvider.lo -MD -MP -MF $(DEPDIR)/libllvmcore_la-ModuleProvider.Tpo -c -o libllvmcore_la-ModuleProvider.lo `test -f 'llvm/lib/VMCore/ModuleProvider.cpp' || echo '$(srcdir)/'`llvm/lib/VMCore/ModuleProvider.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmcore_la-ModuleProvider.Tpo $(DEPDIR)/libllvmcore_la-ModuleProvider.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/VMCore/ModuleProvider.cpp' object='libllvmcore_la-ModuleProvider.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcore_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcore_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmcore_la-ModuleProvider.lo `test -f 'llvm/lib/VMCore/ModuleProvider.cpp' || echo '$(srcdir)/'`llvm/lib/VMCore/ModuleProvider.cpp + +libllvmcore_la-Pass.lo: llvm/lib/VMCore/Pass.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcore_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcore_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmcore_la-Pass.lo -MD -MP -MF $(DEPDIR)/libllvmcore_la-Pass.Tpo -c -o libllvmcore_la-Pass.lo `test -f 'llvm/lib/VMCore/Pass.cpp' || echo '$(srcdir)/'`llvm/lib/VMCore/Pass.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmcore_la-Pass.Tpo $(DEPDIR)/libllvmcore_la-Pass.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/VMCore/Pass.cpp' object='libllvmcore_la-Pass.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcore_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcore_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmcore_la-Pass.lo `test -f 'llvm/lib/VMCore/Pass.cpp' || echo '$(srcdir)/'`llvm/lib/VMCore/Pass.cpp + +libllvmcore_la-PassManager.lo: llvm/lib/VMCore/PassManager.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcore_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcore_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmcore_la-PassManager.lo -MD -MP -MF $(DEPDIR)/libllvmcore_la-PassManager.Tpo -c -o libllvmcore_la-PassManager.lo `test -f 'llvm/lib/VMCore/PassManager.cpp' || echo '$(srcdir)/'`llvm/lib/VMCore/PassManager.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmcore_la-PassManager.Tpo $(DEPDIR)/libllvmcore_la-PassManager.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/VMCore/PassManager.cpp' object='libllvmcore_la-PassManager.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcore_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcore_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmcore_la-PassManager.lo `test -f 'llvm/lib/VMCore/PassManager.cpp' || echo '$(srcdir)/'`llvm/lib/VMCore/PassManager.cpp + +libllvmcore_la-PrintModulePass.lo: llvm/lib/VMCore/PrintModulePass.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcore_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcore_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmcore_la-PrintModulePass.lo -MD -MP -MF $(DEPDIR)/libllvmcore_la-PrintModulePass.Tpo -c -o libllvmcore_la-PrintModulePass.lo `test -f 'llvm/lib/VMCore/PrintModulePass.cpp' || echo '$(srcdir)/'`llvm/lib/VMCore/PrintModulePass.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmcore_la-PrintModulePass.Tpo $(DEPDIR)/libllvmcore_la-PrintModulePass.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/VMCore/PrintModulePass.cpp' object='libllvmcore_la-PrintModulePass.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcore_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcore_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmcore_la-PrintModulePass.lo `test -f 'llvm/lib/VMCore/PrintModulePass.cpp' || echo '$(srcdir)/'`llvm/lib/VMCore/PrintModulePass.cpp + +libllvmcore_la-Type.lo: llvm/lib/VMCore/Type.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcore_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcore_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmcore_la-Type.lo -MD -MP -MF $(DEPDIR)/libllvmcore_la-Type.Tpo -c -o libllvmcore_la-Type.lo `test -f 'llvm/lib/VMCore/Type.cpp' || echo '$(srcdir)/'`llvm/lib/VMCore/Type.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmcore_la-Type.Tpo $(DEPDIR)/libllvmcore_la-Type.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/VMCore/Type.cpp' object='libllvmcore_la-Type.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcore_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcore_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmcore_la-Type.lo `test -f 'llvm/lib/VMCore/Type.cpp' || echo '$(srcdir)/'`llvm/lib/VMCore/Type.cpp + +libllvmcore_la-TypeSymbolTable.lo: llvm/lib/VMCore/TypeSymbolTable.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcore_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcore_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmcore_la-TypeSymbolTable.lo -MD -MP -MF $(DEPDIR)/libllvmcore_la-TypeSymbolTable.Tpo -c -o libllvmcore_la-TypeSymbolTable.lo `test -f 'llvm/lib/VMCore/TypeSymbolTable.cpp' || echo '$(srcdir)/'`llvm/lib/VMCore/TypeSymbolTable.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmcore_la-TypeSymbolTable.Tpo $(DEPDIR)/libllvmcore_la-TypeSymbolTable.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/VMCore/TypeSymbolTable.cpp' object='libllvmcore_la-TypeSymbolTable.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcore_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcore_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmcore_la-TypeSymbolTable.lo `test -f 'llvm/lib/VMCore/TypeSymbolTable.cpp' || echo '$(srcdir)/'`llvm/lib/VMCore/TypeSymbolTable.cpp + +libllvmcore_la-Use.lo: llvm/lib/VMCore/Use.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcore_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcore_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmcore_la-Use.lo -MD -MP -MF $(DEPDIR)/libllvmcore_la-Use.Tpo -c -o libllvmcore_la-Use.lo `test -f 'llvm/lib/VMCore/Use.cpp' || echo '$(srcdir)/'`llvm/lib/VMCore/Use.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmcore_la-Use.Tpo $(DEPDIR)/libllvmcore_la-Use.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/VMCore/Use.cpp' object='libllvmcore_la-Use.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcore_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcore_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmcore_la-Use.lo `test -f 'llvm/lib/VMCore/Use.cpp' || echo '$(srcdir)/'`llvm/lib/VMCore/Use.cpp + +libllvmcore_la-Value.lo: llvm/lib/VMCore/Value.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcore_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcore_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmcore_la-Value.lo -MD -MP -MF $(DEPDIR)/libllvmcore_la-Value.Tpo -c -o libllvmcore_la-Value.lo `test -f 'llvm/lib/VMCore/Value.cpp' || echo '$(srcdir)/'`llvm/lib/VMCore/Value.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmcore_la-Value.Tpo $(DEPDIR)/libllvmcore_la-Value.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/VMCore/Value.cpp' object='libllvmcore_la-Value.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcore_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcore_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmcore_la-Value.lo `test -f 'llvm/lib/VMCore/Value.cpp' || echo '$(srcdir)/'`llvm/lib/VMCore/Value.cpp + +libllvmcore_la-ValueSymbolTable.lo: llvm/lib/VMCore/ValueSymbolTable.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcore_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcore_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmcore_la-ValueSymbolTable.lo -MD -MP -MF $(DEPDIR)/libllvmcore_la-ValueSymbolTable.Tpo -c -o libllvmcore_la-ValueSymbolTable.lo `test -f 'llvm/lib/VMCore/ValueSymbolTable.cpp' || echo '$(srcdir)/'`llvm/lib/VMCore/ValueSymbolTable.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmcore_la-ValueSymbolTable.Tpo $(DEPDIR)/libllvmcore_la-ValueSymbolTable.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/VMCore/ValueSymbolTable.cpp' object='libllvmcore_la-ValueSymbolTable.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcore_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcore_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmcore_la-ValueSymbolTable.lo `test -f 'llvm/lib/VMCore/ValueSymbolTable.cpp' || echo '$(srcdir)/'`llvm/lib/VMCore/ValueSymbolTable.cpp + +libllvmcore_la-ValueTypes.lo: llvm/lib/VMCore/ValueTypes.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcore_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcore_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmcore_la-ValueTypes.lo -MD -MP -MF $(DEPDIR)/libllvmcore_la-ValueTypes.Tpo -c -o libllvmcore_la-ValueTypes.lo `test -f 'llvm/lib/VMCore/ValueTypes.cpp' || echo '$(srcdir)/'`llvm/lib/VMCore/ValueTypes.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmcore_la-ValueTypes.Tpo $(DEPDIR)/libllvmcore_la-ValueTypes.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/VMCore/ValueTypes.cpp' object='libllvmcore_la-ValueTypes.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcore_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcore_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmcore_la-ValueTypes.lo `test -f 'llvm/lib/VMCore/ValueTypes.cpp' || echo '$(srcdir)/'`llvm/lib/VMCore/ValueTypes.cpp + +libllvmcore_la-Verifier.lo: llvm/lib/VMCore/Verifier.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcore_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcore_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmcore_la-Verifier.lo -MD -MP -MF $(DEPDIR)/libllvmcore_la-Verifier.Tpo -c -o libllvmcore_la-Verifier.lo `test -f 'llvm/lib/VMCore/Verifier.cpp' || echo '$(srcdir)/'`llvm/lib/VMCore/Verifier.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmcore_la-Verifier.Tpo $(DEPDIR)/libllvmcore_la-Verifier.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/VMCore/Verifier.cpp' object='libllvmcore_la-Verifier.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmcore_la_CPPFLAGS) $(CPPFLAGS) $(libllvmcore_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmcore_la-Verifier.lo `test -f 'llvm/lib/VMCore/Verifier.cpp' || echo '$(srcdir)/'`llvm/lib/VMCore/Verifier.cpp + +libllvmexecutionengine_la-ExecutionEngine.lo: llvm/lib/ExecutionEngine/ExecutionEngine.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmexecutionengine_la_CPPFLAGS) $(CPPFLAGS) $(libllvmexecutionengine_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmexecutionengine_la-ExecutionEngine.lo -MD -MP -MF $(DEPDIR)/libllvmexecutionengine_la-ExecutionEngine.Tpo -c -o libllvmexecutionengine_la-ExecutionEngine.lo `test -f 'llvm/lib/ExecutionEngine/ExecutionEngine.cpp' || echo '$(srcdir)/'`llvm/lib/ExecutionEngine/ExecutionEngine.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmexecutionengine_la-ExecutionEngine.Tpo $(DEPDIR)/libllvmexecutionengine_la-ExecutionEngine.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/ExecutionEngine/ExecutionEngine.cpp' object='libllvmexecutionengine_la-ExecutionEngine.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmexecutionengine_la_CPPFLAGS) $(CPPFLAGS) $(libllvmexecutionengine_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmexecutionengine_la-ExecutionEngine.lo `test -f 'llvm/lib/ExecutionEngine/ExecutionEngine.cpp' || echo '$(srcdir)/'`llvm/lib/ExecutionEngine/ExecutionEngine.cpp + +libllvmexecutionengine_la-Intercept.lo: llvm/lib/ExecutionEngine/JIT/Intercept.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmexecutionengine_la_CPPFLAGS) $(CPPFLAGS) $(libllvmexecutionengine_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmexecutionengine_la-Intercept.lo -MD -MP -MF $(DEPDIR)/libllvmexecutionengine_la-Intercept.Tpo -c -o libllvmexecutionengine_la-Intercept.lo `test -f 'llvm/lib/ExecutionEngine/JIT/Intercept.cpp' || echo '$(srcdir)/'`llvm/lib/ExecutionEngine/JIT/Intercept.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmexecutionengine_la-Intercept.Tpo $(DEPDIR)/libllvmexecutionengine_la-Intercept.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/ExecutionEngine/JIT/Intercept.cpp' object='libllvmexecutionengine_la-Intercept.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmexecutionengine_la_CPPFLAGS) $(CPPFLAGS) $(libllvmexecutionengine_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmexecutionengine_la-Intercept.lo `test -f 'llvm/lib/ExecutionEngine/JIT/Intercept.cpp' || echo '$(srcdir)/'`llvm/lib/ExecutionEngine/JIT/Intercept.cpp + +libllvmexecutionengine_la-JIT.lo: llvm/lib/ExecutionEngine/JIT/JIT.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmexecutionengine_la_CPPFLAGS) $(CPPFLAGS) $(libllvmexecutionengine_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmexecutionengine_la-JIT.lo -MD -MP -MF $(DEPDIR)/libllvmexecutionengine_la-JIT.Tpo -c -o libllvmexecutionengine_la-JIT.lo `test -f 'llvm/lib/ExecutionEngine/JIT/JIT.cpp' || echo '$(srcdir)/'`llvm/lib/ExecutionEngine/JIT/JIT.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmexecutionengine_la-JIT.Tpo $(DEPDIR)/libllvmexecutionengine_la-JIT.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/ExecutionEngine/JIT/JIT.cpp' object='libllvmexecutionengine_la-JIT.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmexecutionengine_la_CPPFLAGS) $(CPPFLAGS) $(libllvmexecutionengine_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmexecutionengine_la-JIT.lo `test -f 'llvm/lib/ExecutionEngine/JIT/JIT.cpp' || echo '$(srcdir)/'`llvm/lib/ExecutionEngine/JIT/JIT.cpp + +libllvmexecutionengine_la-JITDebugRegisterer.lo: llvm/lib/ExecutionEngine/JIT/JITDebugRegisterer.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmexecutionengine_la_CPPFLAGS) $(CPPFLAGS) $(libllvmexecutionengine_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmexecutionengine_la-JITDebugRegisterer.lo -MD -MP -MF $(DEPDIR)/libllvmexecutionengine_la-JITDebugRegisterer.Tpo -c -o libllvmexecutionengine_la-JITDebugRegisterer.lo `test -f 'llvm/lib/ExecutionEngine/JIT/JITDebugRegisterer.cpp' || echo '$(srcdir)/'`llvm/lib/ExecutionEngine/JIT/JITDebugRegisterer.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmexecutionengine_la-JITDebugRegisterer.Tpo $(DEPDIR)/libllvmexecutionengine_la-JITDebugRegisterer.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/ExecutionEngine/JIT/JITDebugRegisterer.cpp' object='libllvmexecutionengine_la-JITDebugRegisterer.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmexecutionengine_la_CPPFLAGS) $(CPPFLAGS) $(libllvmexecutionengine_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmexecutionengine_la-JITDebugRegisterer.lo `test -f 'llvm/lib/ExecutionEngine/JIT/JITDebugRegisterer.cpp' || echo '$(srcdir)/'`llvm/lib/ExecutionEngine/JIT/JITDebugRegisterer.cpp + +libllvmexecutionengine_la-JITDwarfEmitter.lo: llvm/lib/ExecutionEngine/JIT/JITDwarfEmitter.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmexecutionengine_la_CPPFLAGS) $(CPPFLAGS) $(libllvmexecutionengine_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmexecutionengine_la-JITDwarfEmitter.lo -MD -MP -MF $(DEPDIR)/libllvmexecutionengine_la-JITDwarfEmitter.Tpo -c -o libllvmexecutionengine_la-JITDwarfEmitter.lo `test -f 'llvm/lib/ExecutionEngine/JIT/JITDwarfEmitter.cpp' || echo '$(srcdir)/'`llvm/lib/ExecutionEngine/JIT/JITDwarfEmitter.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmexecutionengine_la-JITDwarfEmitter.Tpo $(DEPDIR)/libllvmexecutionengine_la-JITDwarfEmitter.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/ExecutionEngine/JIT/JITDwarfEmitter.cpp' object='libllvmexecutionengine_la-JITDwarfEmitter.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmexecutionengine_la_CPPFLAGS) $(CPPFLAGS) $(libllvmexecutionengine_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmexecutionengine_la-JITDwarfEmitter.lo `test -f 'llvm/lib/ExecutionEngine/JIT/JITDwarfEmitter.cpp' || echo '$(srcdir)/'`llvm/lib/ExecutionEngine/JIT/JITDwarfEmitter.cpp + +libllvmexecutionengine_la-JITEmitter.lo: llvm/lib/ExecutionEngine/JIT/JITEmitter.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmexecutionengine_la_CPPFLAGS) $(CPPFLAGS) $(libllvmexecutionengine_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmexecutionengine_la-JITEmitter.lo -MD -MP -MF $(DEPDIR)/libllvmexecutionengine_la-JITEmitter.Tpo -c -o libllvmexecutionengine_la-JITEmitter.lo `test -f 'llvm/lib/ExecutionEngine/JIT/JITEmitter.cpp' || echo '$(srcdir)/'`llvm/lib/ExecutionEngine/JIT/JITEmitter.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmexecutionengine_la-JITEmitter.Tpo $(DEPDIR)/libllvmexecutionengine_la-JITEmitter.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/ExecutionEngine/JIT/JITEmitter.cpp' object='libllvmexecutionengine_la-JITEmitter.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmexecutionengine_la_CPPFLAGS) $(CPPFLAGS) $(libllvmexecutionengine_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmexecutionengine_la-JITEmitter.lo `test -f 'llvm/lib/ExecutionEngine/JIT/JITEmitter.cpp' || echo '$(srcdir)/'`llvm/lib/ExecutionEngine/JIT/JITEmitter.cpp + +libllvmexecutionengine_la-JITMemoryManager.lo: llvm/lib/ExecutionEngine/JIT/JITMemoryManager.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmexecutionengine_la_CPPFLAGS) $(CPPFLAGS) $(libllvmexecutionengine_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmexecutionengine_la-JITMemoryManager.lo -MD -MP -MF $(DEPDIR)/libllvmexecutionengine_la-JITMemoryManager.Tpo -c -o libllvmexecutionengine_la-JITMemoryManager.lo `test -f 'llvm/lib/ExecutionEngine/JIT/JITMemoryManager.cpp' || echo '$(srcdir)/'`llvm/lib/ExecutionEngine/JIT/JITMemoryManager.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmexecutionengine_la-JITMemoryManager.Tpo $(DEPDIR)/libllvmexecutionengine_la-JITMemoryManager.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/ExecutionEngine/JIT/JITMemoryManager.cpp' object='libllvmexecutionengine_la-JITMemoryManager.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmexecutionengine_la_CPPFLAGS) $(CPPFLAGS) $(libllvmexecutionengine_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmexecutionengine_la-JITMemoryManager.lo `test -f 'llvm/lib/ExecutionEngine/JIT/JITMemoryManager.cpp' || echo '$(srcdir)/'`llvm/lib/ExecutionEngine/JIT/JITMemoryManager.cpp + +libllvmexecutionengine_la-TargetSelect.lo: llvm/lib/ExecutionEngine/JIT/TargetSelect.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmexecutionengine_la_CPPFLAGS) $(CPPFLAGS) $(libllvmexecutionengine_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmexecutionengine_la-TargetSelect.lo -MD -MP -MF $(DEPDIR)/libllvmexecutionengine_la-TargetSelect.Tpo -c -o libllvmexecutionengine_la-TargetSelect.lo `test -f 'llvm/lib/ExecutionEngine/JIT/TargetSelect.cpp' || echo '$(srcdir)/'`llvm/lib/ExecutionEngine/JIT/TargetSelect.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmexecutionengine_la-TargetSelect.Tpo $(DEPDIR)/libllvmexecutionengine_la-TargetSelect.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/ExecutionEngine/JIT/TargetSelect.cpp' object='libllvmexecutionengine_la-TargetSelect.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmexecutionengine_la_CPPFLAGS) $(CPPFLAGS) $(libllvmexecutionengine_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmexecutionengine_la-TargetSelect.lo `test -f 'llvm/lib/ExecutionEngine/JIT/TargetSelect.cpp' || echo '$(srcdir)/'`llvm/lib/ExecutionEngine/JIT/TargetSelect.cpp + +libllvminterpreter_la-Execution.lo: llvm/lib/ExecutionEngine/Interpreter/Execution.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvminterpreter_la_CPPFLAGS) $(CPPFLAGS) $(libllvminterpreter_la_CXXFLAGS) $(CXXFLAGS) -MT libllvminterpreter_la-Execution.lo -MD -MP -MF $(DEPDIR)/libllvminterpreter_la-Execution.Tpo -c -o libllvminterpreter_la-Execution.lo `test -f 'llvm/lib/ExecutionEngine/Interpreter/Execution.cpp' || echo '$(srcdir)/'`llvm/lib/ExecutionEngine/Interpreter/Execution.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvminterpreter_la-Execution.Tpo $(DEPDIR)/libllvminterpreter_la-Execution.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/ExecutionEngine/Interpreter/Execution.cpp' object='libllvminterpreter_la-Execution.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvminterpreter_la_CPPFLAGS) $(CPPFLAGS) $(libllvminterpreter_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvminterpreter_la-Execution.lo `test -f 'llvm/lib/ExecutionEngine/Interpreter/Execution.cpp' || echo '$(srcdir)/'`llvm/lib/ExecutionEngine/Interpreter/Execution.cpp + +libllvminterpreter_la-ExternalFunctions.lo: llvm/lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvminterpreter_la_CPPFLAGS) $(CPPFLAGS) $(libllvminterpreter_la_CXXFLAGS) $(CXXFLAGS) -MT libllvminterpreter_la-ExternalFunctions.lo -MD -MP -MF $(DEPDIR)/libllvminterpreter_la-ExternalFunctions.Tpo -c -o libllvminterpreter_la-ExternalFunctions.lo `test -f 'llvm/lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp' || echo '$(srcdir)/'`llvm/lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvminterpreter_la-ExternalFunctions.Tpo $(DEPDIR)/libllvminterpreter_la-ExternalFunctions.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp' object='libllvminterpreter_la-ExternalFunctions.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvminterpreter_la_CPPFLAGS) $(CPPFLAGS) $(libllvminterpreter_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvminterpreter_la-ExternalFunctions.lo `test -f 'llvm/lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp' || echo '$(srcdir)/'`llvm/lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp + +libllvminterpreter_la-Interpreter.lo: llvm/lib/ExecutionEngine/Interpreter/Interpreter.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvminterpreter_la_CPPFLAGS) $(CPPFLAGS) $(libllvminterpreter_la_CXXFLAGS) $(CXXFLAGS) -MT libllvminterpreter_la-Interpreter.lo -MD -MP -MF $(DEPDIR)/libllvminterpreter_la-Interpreter.Tpo -c -o libllvminterpreter_la-Interpreter.lo `test -f 'llvm/lib/ExecutionEngine/Interpreter/Interpreter.cpp' || echo '$(srcdir)/'`llvm/lib/ExecutionEngine/Interpreter/Interpreter.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvminterpreter_la-Interpreter.Tpo $(DEPDIR)/libllvminterpreter_la-Interpreter.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/ExecutionEngine/Interpreter/Interpreter.cpp' object='libllvminterpreter_la-Interpreter.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvminterpreter_la_CPPFLAGS) $(CPPFLAGS) $(libllvminterpreter_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvminterpreter_la-Interpreter.lo `test -f 'llvm/lib/ExecutionEngine/Interpreter/Interpreter.cpp' || echo '$(srcdir)/'`llvm/lib/ExecutionEngine/Interpreter/Interpreter.cpp + +libllvmipa_la-AliasAnalysis.lo: llvm/lib/Analysis/AliasAnalysis.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmipa_la_CPPFLAGS) $(CPPFLAGS) $(libllvmipa_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmipa_la-AliasAnalysis.lo -MD -MP -MF $(DEPDIR)/libllvmipa_la-AliasAnalysis.Tpo -c -o libllvmipa_la-AliasAnalysis.lo `test -f 'llvm/lib/Analysis/AliasAnalysis.cpp' || echo '$(srcdir)/'`llvm/lib/Analysis/AliasAnalysis.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmipa_la-AliasAnalysis.Tpo $(DEPDIR)/libllvmipa_la-AliasAnalysis.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Analysis/AliasAnalysis.cpp' object='libllvmipa_la-AliasAnalysis.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmipa_la_CPPFLAGS) $(CPPFLAGS) $(libllvmipa_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmipa_la-AliasAnalysis.lo `test -f 'llvm/lib/Analysis/AliasAnalysis.cpp' || echo '$(srcdir)/'`llvm/lib/Analysis/AliasAnalysis.cpp + +libllvmipa_la-AliasSetTracker.lo: llvm/lib/Analysis/AliasSetTracker.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmipa_la_CPPFLAGS) $(CPPFLAGS) $(libllvmipa_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmipa_la-AliasSetTracker.lo -MD -MP -MF $(DEPDIR)/libllvmipa_la-AliasSetTracker.Tpo -c -o libllvmipa_la-AliasSetTracker.lo `test -f 'llvm/lib/Analysis/AliasSetTracker.cpp' || echo '$(srcdir)/'`llvm/lib/Analysis/AliasSetTracker.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmipa_la-AliasSetTracker.Tpo $(DEPDIR)/libllvmipa_la-AliasSetTracker.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Analysis/AliasSetTracker.cpp' object='libllvmipa_la-AliasSetTracker.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmipa_la_CPPFLAGS) $(CPPFLAGS) $(libllvmipa_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmipa_la-AliasSetTracker.lo `test -f 'llvm/lib/Analysis/AliasSetTracker.cpp' || echo '$(srcdir)/'`llvm/lib/Analysis/AliasSetTracker.cpp + +libllvmipa_la-BasicAliasAnalysis.lo: llvm/lib/Analysis/BasicAliasAnalysis.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmipa_la_CPPFLAGS) $(CPPFLAGS) $(libllvmipa_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmipa_la-BasicAliasAnalysis.lo -MD -MP -MF $(DEPDIR)/libllvmipa_la-BasicAliasAnalysis.Tpo -c -o libllvmipa_la-BasicAliasAnalysis.lo `test -f 'llvm/lib/Analysis/BasicAliasAnalysis.cpp' || echo '$(srcdir)/'`llvm/lib/Analysis/BasicAliasAnalysis.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmipa_la-BasicAliasAnalysis.Tpo $(DEPDIR)/libllvmipa_la-BasicAliasAnalysis.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Analysis/BasicAliasAnalysis.cpp' object='libllvmipa_la-BasicAliasAnalysis.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmipa_la_CPPFLAGS) $(CPPFLAGS) $(libllvmipa_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmipa_la-BasicAliasAnalysis.lo `test -f 'llvm/lib/Analysis/BasicAliasAnalysis.cpp' || echo '$(srcdir)/'`llvm/lib/Analysis/BasicAliasAnalysis.cpp + +libllvmipa_la-CaptureTracking.lo: llvm/lib/Analysis/CaptureTracking.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmipa_la_CPPFLAGS) $(CPPFLAGS) $(libllvmipa_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmipa_la-CaptureTracking.lo -MD -MP -MF $(DEPDIR)/libllvmipa_la-CaptureTracking.Tpo -c -o libllvmipa_la-CaptureTracking.lo `test -f 'llvm/lib/Analysis/CaptureTracking.cpp' || echo '$(srcdir)/'`llvm/lib/Analysis/CaptureTracking.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmipa_la-CaptureTracking.Tpo $(DEPDIR)/libllvmipa_la-CaptureTracking.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Analysis/CaptureTracking.cpp' object='libllvmipa_la-CaptureTracking.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmipa_la_CPPFLAGS) $(CPPFLAGS) $(libllvmipa_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmipa_la-CaptureTracking.lo `test -f 'llvm/lib/Analysis/CaptureTracking.cpp' || echo '$(srcdir)/'`llvm/lib/Analysis/CaptureTracking.cpp + +libllvmipa_la-ConstantFolding.lo: llvm/lib/Analysis/ConstantFolding.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmipa_la_CPPFLAGS) $(CPPFLAGS) $(libllvmipa_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmipa_la-ConstantFolding.lo -MD -MP -MF $(DEPDIR)/libllvmipa_la-ConstantFolding.Tpo -c -o libllvmipa_la-ConstantFolding.lo `test -f 'llvm/lib/Analysis/ConstantFolding.cpp' || echo '$(srcdir)/'`llvm/lib/Analysis/ConstantFolding.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmipa_la-ConstantFolding.Tpo $(DEPDIR)/libllvmipa_la-ConstantFolding.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Analysis/ConstantFolding.cpp' object='libllvmipa_la-ConstantFolding.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmipa_la_CPPFLAGS) $(CPPFLAGS) $(libllvmipa_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmipa_la-ConstantFolding.lo `test -f 'llvm/lib/Analysis/ConstantFolding.cpp' || echo '$(srcdir)/'`llvm/lib/Analysis/ConstantFolding.cpp + +libllvmipa_la-DebugInfo.lo: llvm/lib/Analysis/DebugInfo.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmipa_la_CPPFLAGS) $(CPPFLAGS) $(libllvmipa_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmipa_la-DebugInfo.lo -MD -MP -MF $(DEPDIR)/libllvmipa_la-DebugInfo.Tpo -c -o libllvmipa_la-DebugInfo.lo `test -f 'llvm/lib/Analysis/DebugInfo.cpp' || echo '$(srcdir)/'`llvm/lib/Analysis/DebugInfo.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmipa_la-DebugInfo.Tpo $(DEPDIR)/libllvmipa_la-DebugInfo.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Analysis/DebugInfo.cpp' object='libllvmipa_la-DebugInfo.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmipa_la_CPPFLAGS) $(CPPFLAGS) $(libllvmipa_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmipa_la-DebugInfo.lo `test -f 'llvm/lib/Analysis/DebugInfo.cpp' || echo '$(srcdir)/'`llvm/lib/Analysis/DebugInfo.cpp + +libllvmipa_la-IVUsers.lo: llvm/lib/Analysis/IVUsers.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmipa_la_CPPFLAGS) $(CPPFLAGS) $(libllvmipa_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmipa_la-IVUsers.lo -MD -MP -MF $(DEPDIR)/libllvmipa_la-IVUsers.Tpo -c -o libllvmipa_la-IVUsers.lo `test -f 'llvm/lib/Analysis/IVUsers.cpp' || echo '$(srcdir)/'`llvm/lib/Analysis/IVUsers.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmipa_la-IVUsers.Tpo $(DEPDIR)/libllvmipa_la-IVUsers.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Analysis/IVUsers.cpp' object='libllvmipa_la-IVUsers.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmipa_la_CPPFLAGS) $(CPPFLAGS) $(libllvmipa_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmipa_la-IVUsers.lo `test -f 'llvm/lib/Analysis/IVUsers.cpp' || echo '$(srcdir)/'`llvm/lib/Analysis/IVUsers.cpp + +libllvmipa_la-InstructionSimplify.lo: llvm/lib/Analysis/InstructionSimplify.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmipa_la_CPPFLAGS) $(CPPFLAGS) $(libllvmipa_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmipa_la-InstructionSimplify.lo -MD -MP -MF $(DEPDIR)/libllvmipa_la-InstructionSimplify.Tpo -c -o libllvmipa_la-InstructionSimplify.lo `test -f 'llvm/lib/Analysis/InstructionSimplify.cpp' || echo '$(srcdir)/'`llvm/lib/Analysis/InstructionSimplify.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmipa_la-InstructionSimplify.Tpo $(DEPDIR)/libllvmipa_la-InstructionSimplify.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Analysis/InstructionSimplify.cpp' object='libllvmipa_la-InstructionSimplify.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmipa_la_CPPFLAGS) $(CPPFLAGS) $(libllvmipa_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmipa_la-InstructionSimplify.lo `test -f 'llvm/lib/Analysis/InstructionSimplify.cpp' || echo '$(srcdir)/'`llvm/lib/Analysis/InstructionSimplify.cpp + +libllvmipa_la-LiveValues.lo: llvm/lib/Analysis/LiveValues.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmipa_la_CPPFLAGS) $(CPPFLAGS) $(libllvmipa_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmipa_la-LiveValues.lo -MD -MP -MF $(DEPDIR)/libllvmipa_la-LiveValues.Tpo -c -o libllvmipa_la-LiveValues.lo `test -f 'llvm/lib/Analysis/LiveValues.cpp' || echo '$(srcdir)/'`llvm/lib/Analysis/LiveValues.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmipa_la-LiveValues.Tpo $(DEPDIR)/libllvmipa_la-LiveValues.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Analysis/LiveValues.cpp' object='libllvmipa_la-LiveValues.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmipa_la_CPPFLAGS) $(CPPFLAGS) $(libllvmipa_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmipa_la-LiveValues.lo `test -f 'llvm/lib/Analysis/LiveValues.cpp' || echo '$(srcdir)/'`llvm/lib/Analysis/LiveValues.cpp + +libllvmipa_la-LoopDependenceAnalysis.lo: llvm/lib/Analysis/LoopDependenceAnalysis.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmipa_la_CPPFLAGS) $(CPPFLAGS) $(libllvmipa_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmipa_la-LoopDependenceAnalysis.lo -MD -MP -MF $(DEPDIR)/libllvmipa_la-LoopDependenceAnalysis.Tpo -c -o libllvmipa_la-LoopDependenceAnalysis.lo `test -f 'llvm/lib/Analysis/LoopDependenceAnalysis.cpp' || echo '$(srcdir)/'`llvm/lib/Analysis/LoopDependenceAnalysis.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmipa_la-LoopDependenceAnalysis.Tpo $(DEPDIR)/libllvmipa_la-LoopDependenceAnalysis.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Analysis/LoopDependenceAnalysis.cpp' object='libllvmipa_la-LoopDependenceAnalysis.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmipa_la_CPPFLAGS) $(CPPFLAGS) $(libllvmipa_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmipa_la-LoopDependenceAnalysis.lo `test -f 'llvm/lib/Analysis/LoopDependenceAnalysis.cpp' || echo '$(srcdir)/'`llvm/lib/Analysis/LoopDependenceAnalysis.cpp + +libllvmipa_la-LoopInfo.lo: llvm/lib/Analysis/LoopInfo.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmipa_la_CPPFLAGS) $(CPPFLAGS) $(libllvmipa_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmipa_la-LoopInfo.lo -MD -MP -MF $(DEPDIR)/libllvmipa_la-LoopInfo.Tpo -c -o libllvmipa_la-LoopInfo.lo `test -f 'llvm/lib/Analysis/LoopInfo.cpp' || echo '$(srcdir)/'`llvm/lib/Analysis/LoopInfo.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmipa_la-LoopInfo.Tpo $(DEPDIR)/libllvmipa_la-LoopInfo.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Analysis/LoopInfo.cpp' object='libllvmipa_la-LoopInfo.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmipa_la_CPPFLAGS) $(CPPFLAGS) $(libllvmipa_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmipa_la-LoopInfo.lo `test -f 'llvm/lib/Analysis/LoopInfo.cpp' || echo '$(srcdir)/'`llvm/lib/Analysis/LoopInfo.cpp + +libllvmipa_la-LoopPass.lo: llvm/lib/Analysis/LoopPass.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmipa_la_CPPFLAGS) $(CPPFLAGS) $(libllvmipa_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmipa_la-LoopPass.lo -MD -MP -MF $(DEPDIR)/libllvmipa_la-LoopPass.Tpo -c -o libllvmipa_la-LoopPass.lo `test -f 'llvm/lib/Analysis/LoopPass.cpp' || echo '$(srcdir)/'`llvm/lib/Analysis/LoopPass.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmipa_la-LoopPass.Tpo $(DEPDIR)/libllvmipa_la-LoopPass.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Analysis/LoopPass.cpp' object='libllvmipa_la-LoopPass.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmipa_la_CPPFLAGS) $(CPPFLAGS) $(libllvmipa_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmipa_la-LoopPass.lo `test -f 'llvm/lib/Analysis/LoopPass.cpp' || echo '$(srcdir)/'`llvm/lib/Analysis/LoopPass.cpp + +libllvmipa_la-MemoryBuiltins.lo: llvm/lib/Analysis/MemoryBuiltins.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmipa_la_CPPFLAGS) $(CPPFLAGS) $(libllvmipa_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmipa_la-MemoryBuiltins.lo -MD -MP -MF $(DEPDIR)/libllvmipa_la-MemoryBuiltins.Tpo -c -o libllvmipa_la-MemoryBuiltins.lo `test -f 'llvm/lib/Analysis/MemoryBuiltins.cpp' || echo '$(srcdir)/'`llvm/lib/Analysis/MemoryBuiltins.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmipa_la-MemoryBuiltins.Tpo $(DEPDIR)/libllvmipa_la-MemoryBuiltins.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Analysis/MemoryBuiltins.cpp' object='libllvmipa_la-MemoryBuiltins.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmipa_la_CPPFLAGS) $(CPPFLAGS) $(libllvmipa_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmipa_la-MemoryBuiltins.lo `test -f 'llvm/lib/Analysis/MemoryBuiltins.cpp' || echo '$(srcdir)/'`llvm/lib/Analysis/MemoryBuiltins.cpp + +libllvmipa_la-MemoryDependenceAnalysis.lo: llvm/lib/Analysis/MemoryDependenceAnalysis.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmipa_la_CPPFLAGS) $(CPPFLAGS) $(libllvmipa_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmipa_la-MemoryDependenceAnalysis.lo -MD -MP -MF $(DEPDIR)/libllvmipa_la-MemoryDependenceAnalysis.Tpo -c -o libllvmipa_la-MemoryDependenceAnalysis.lo `test -f 'llvm/lib/Analysis/MemoryDependenceAnalysis.cpp' || echo '$(srcdir)/'`llvm/lib/Analysis/MemoryDependenceAnalysis.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmipa_la-MemoryDependenceAnalysis.Tpo $(DEPDIR)/libllvmipa_la-MemoryDependenceAnalysis.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Analysis/MemoryDependenceAnalysis.cpp' object='libllvmipa_la-MemoryDependenceAnalysis.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmipa_la_CPPFLAGS) $(CPPFLAGS) $(libllvmipa_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmipa_la-MemoryDependenceAnalysis.lo `test -f 'llvm/lib/Analysis/MemoryDependenceAnalysis.cpp' || echo '$(srcdir)/'`llvm/lib/Analysis/MemoryDependenceAnalysis.cpp + +libllvmipa_la-ProfileInfo.lo: llvm/lib/Analysis/ProfileInfo.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmipa_la_CPPFLAGS) $(CPPFLAGS) $(libllvmipa_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmipa_la-ProfileInfo.lo -MD -MP -MF $(DEPDIR)/libllvmipa_la-ProfileInfo.Tpo -c -o libllvmipa_la-ProfileInfo.lo `test -f 'llvm/lib/Analysis/ProfileInfo.cpp' || echo '$(srcdir)/'`llvm/lib/Analysis/ProfileInfo.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmipa_la-ProfileInfo.Tpo $(DEPDIR)/libllvmipa_la-ProfileInfo.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Analysis/ProfileInfo.cpp' object='libllvmipa_la-ProfileInfo.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmipa_la_CPPFLAGS) $(CPPFLAGS) $(libllvmipa_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmipa_la-ProfileInfo.lo `test -f 'llvm/lib/Analysis/ProfileInfo.cpp' || echo '$(srcdir)/'`llvm/lib/Analysis/ProfileInfo.cpp + +libllvmipa_la-ScalarEvolution.lo: llvm/lib/Analysis/ScalarEvolution.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmipa_la_CPPFLAGS) $(CPPFLAGS) $(libllvmipa_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmipa_la-ScalarEvolution.lo -MD -MP -MF $(DEPDIR)/libllvmipa_la-ScalarEvolution.Tpo -c -o libllvmipa_la-ScalarEvolution.lo `test -f 'llvm/lib/Analysis/ScalarEvolution.cpp' || echo '$(srcdir)/'`llvm/lib/Analysis/ScalarEvolution.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmipa_la-ScalarEvolution.Tpo $(DEPDIR)/libllvmipa_la-ScalarEvolution.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Analysis/ScalarEvolution.cpp' object='libllvmipa_la-ScalarEvolution.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmipa_la_CPPFLAGS) $(CPPFLAGS) $(libllvmipa_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmipa_la-ScalarEvolution.lo `test -f 'llvm/lib/Analysis/ScalarEvolution.cpp' || echo '$(srcdir)/'`llvm/lib/Analysis/ScalarEvolution.cpp + +libllvmipa_la-ScalarEvolutionExpander.lo: llvm/lib/Analysis/ScalarEvolutionExpander.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmipa_la_CPPFLAGS) $(CPPFLAGS) $(libllvmipa_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmipa_la-ScalarEvolutionExpander.lo -MD -MP -MF $(DEPDIR)/libllvmipa_la-ScalarEvolutionExpander.Tpo -c -o libllvmipa_la-ScalarEvolutionExpander.lo `test -f 'llvm/lib/Analysis/ScalarEvolutionExpander.cpp' || echo '$(srcdir)/'`llvm/lib/Analysis/ScalarEvolutionExpander.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmipa_la-ScalarEvolutionExpander.Tpo $(DEPDIR)/libllvmipa_la-ScalarEvolutionExpander.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Analysis/ScalarEvolutionExpander.cpp' object='libllvmipa_la-ScalarEvolutionExpander.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmipa_la_CPPFLAGS) $(CPPFLAGS) $(libllvmipa_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmipa_la-ScalarEvolutionExpander.lo `test -f 'llvm/lib/Analysis/ScalarEvolutionExpander.cpp' || echo '$(srcdir)/'`llvm/lib/Analysis/ScalarEvolutionExpander.cpp + +libllvmipa_la-ValueTracking.lo: llvm/lib/Analysis/ValueTracking.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmipa_la_CPPFLAGS) $(CPPFLAGS) $(libllvmipa_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmipa_la-ValueTracking.lo -MD -MP -MF $(DEPDIR)/libllvmipa_la-ValueTracking.Tpo -c -o libllvmipa_la-ValueTracking.lo `test -f 'llvm/lib/Analysis/ValueTracking.cpp' || echo '$(srcdir)/'`llvm/lib/Analysis/ValueTracking.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmipa_la-ValueTracking.Tpo $(DEPDIR)/libllvmipa_la-ValueTracking.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Analysis/ValueTracking.cpp' object='libllvmipa_la-ValueTracking.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmipa_la_CPPFLAGS) $(CPPFLAGS) $(libllvmipa_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmipa_la-ValueTracking.lo `test -f 'llvm/lib/Analysis/ValueTracking.cpp' || echo '$(srcdir)/'`llvm/lib/Analysis/ValueTracking.cpp + +libllvmipa_la-CallGraph.lo: llvm/lib/Analysis/IPA/CallGraph.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmipa_la_CPPFLAGS) $(CPPFLAGS) $(libllvmipa_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmipa_la-CallGraph.lo -MD -MP -MF $(DEPDIR)/libllvmipa_la-CallGraph.Tpo -c -o libllvmipa_la-CallGraph.lo `test -f 'llvm/lib/Analysis/IPA/CallGraph.cpp' || echo '$(srcdir)/'`llvm/lib/Analysis/IPA/CallGraph.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmipa_la-CallGraph.Tpo $(DEPDIR)/libllvmipa_la-CallGraph.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Analysis/IPA/CallGraph.cpp' object='libllvmipa_la-CallGraph.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmipa_la_CPPFLAGS) $(CPPFLAGS) $(libllvmipa_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmipa_la-CallGraph.lo `test -f 'llvm/lib/Analysis/IPA/CallGraph.cpp' || echo '$(srcdir)/'`llvm/lib/Analysis/IPA/CallGraph.cpp + +libllvmmc_la-MCAsmInfo.lo: llvm/lib/MC/MCAsmInfo.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmmc_la_CPPFLAGS) $(CPPFLAGS) $(libllvmmc_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmmc_la-MCAsmInfo.lo -MD -MP -MF $(DEPDIR)/libllvmmc_la-MCAsmInfo.Tpo -c -o libllvmmc_la-MCAsmInfo.lo `test -f 'llvm/lib/MC/MCAsmInfo.cpp' || echo '$(srcdir)/'`llvm/lib/MC/MCAsmInfo.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmmc_la-MCAsmInfo.Tpo $(DEPDIR)/libllvmmc_la-MCAsmInfo.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/MC/MCAsmInfo.cpp' object='libllvmmc_la-MCAsmInfo.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmmc_la_CPPFLAGS) $(CPPFLAGS) $(libllvmmc_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmmc_la-MCAsmInfo.lo `test -f 'llvm/lib/MC/MCAsmInfo.cpp' || echo '$(srcdir)/'`llvm/lib/MC/MCAsmInfo.cpp + +libllvmmc_la-MCAsmInfoCOFF.lo: llvm/lib/MC/MCAsmInfoCOFF.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmmc_la_CPPFLAGS) $(CPPFLAGS) $(libllvmmc_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmmc_la-MCAsmInfoCOFF.lo -MD -MP -MF $(DEPDIR)/libllvmmc_la-MCAsmInfoCOFF.Tpo -c -o libllvmmc_la-MCAsmInfoCOFF.lo `test -f 'llvm/lib/MC/MCAsmInfoCOFF.cpp' || echo '$(srcdir)/'`llvm/lib/MC/MCAsmInfoCOFF.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmmc_la-MCAsmInfoCOFF.Tpo $(DEPDIR)/libllvmmc_la-MCAsmInfoCOFF.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/MC/MCAsmInfoCOFF.cpp' object='libllvmmc_la-MCAsmInfoCOFF.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmmc_la_CPPFLAGS) $(CPPFLAGS) $(libllvmmc_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmmc_la-MCAsmInfoCOFF.lo `test -f 'llvm/lib/MC/MCAsmInfoCOFF.cpp' || echo '$(srcdir)/'`llvm/lib/MC/MCAsmInfoCOFF.cpp + +libllvmmc_la-MCAsmInfoDarwin.lo: llvm/lib/MC/MCAsmInfoDarwin.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmmc_la_CPPFLAGS) $(CPPFLAGS) $(libllvmmc_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmmc_la-MCAsmInfoDarwin.lo -MD -MP -MF $(DEPDIR)/libllvmmc_la-MCAsmInfoDarwin.Tpo -c -o libllvmmc_la-MCAsmInfoDarwin.lo `test -f 'llvm/lib/MC/MCAsmInfoDarwin.cpp' || echo '$(srcdir)/'`llvm/lib/MC/MCAsmInfoDarwin.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmmc_la-MCAsmInfoDarwin.Tpo $(DEPDIR)/libllvmmc_la-MCAsmInfoDarwin.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/MC/MCAsmInfoDarwin.cpp' object='libllvmmc_la-MCAsmInfoDarwin.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmmc_la_CPPFLAGS) $(CPPFLAGS) $(libllvmmc_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmmc_la-MCAsmInfoDarwin.lo `test -f 'llvm/lib/MC/MCAsmInfoDarwin.cpp' || echo '$(srcdir)/'`llvm/lib/MC/MCAsmInfoDarwin.cpp + +libllvmmc_la-MCAsmLexer.lo: llvm/lib/MC/MCAsmLexer.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmmc_la_CPPFLAGS) $(CPPFLAGS) $(libllvmmc_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmmc_la-MCAsmLexer.lo -MD -MP -MF $(DEPDIR)/libllvmmc_la-MCAsmLexer.Tpo -c -o libllvmmc_la-MCAsmLexer.lo `test -f 'llvm/lib/MC/MCAsmLexer.cpp' || echo '$(srcdir)/'`llvm/lib/MC/MCAsmLexer.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmmc_la-MCAsmLexer.Tpo $(DEPDIR)/libllvmmc_la-MCAsmLexer.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/MC/MCAsmLexer.cpp' object='libllvmmc_la-MCAsmLexer.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmmc_la_CPPFLAGS) $(CPPFLAGS) $(libllvmmc_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmmc_la-MCAsmLexer.lo `test -f 'llvm/lib/MC/MCAsmLexer.cpp' || echo '$(srcdir)/'`llvm/lib/MC/MCAsmLexer.cpp + +libllvmmc_la-MCAsmParser.lo: llvm/lib/MC/MCAsmParser.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmmc_la_CPPFLAGS) $(CPPFLAGS) $(libllvmmc_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmmc_la-MCAsmParser.lo -MD -MP -MF $(DEPDIR)/libllvmmc_la-MCAsmParser.Tpo -c -o libllvmmc_la-MCAsmParser.lo `test -f 'llvm/lib/MC/MCAsmParser.cpp' || echo '$(srcdir)/'`llvm/lib/MC/MCAsmParser.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmmc_la-MCAsmParser.Tpo $(DEPDIR)/libllvmmc_la-MCAsmParser.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/MC/MCAsmParser.cpp' object='libllvmmc_la-MCAsmParser.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmmc_la_CPPFLAGS) $(CPPFLAGS) $(libllvmmc_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmmc_la-MCAsmParser.lo `test -f 'llvm/lib/MC/MCAsmParser.cpp' || echo '$(srcdir)/'`llvm/lib/MC/MCAsmParser.cpp + +libllvmmc_la-MCAsmStreamer.lo: llvm/lib/MC/MCAsmStreamer.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmmc_la_CPPFLAGS) $(CPPFLAGS) $(libllvmmc_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmmc_la-MCAsmStreamer.lo -MD -MP -MF $(DEPDIR)/libllvmmc_la-MCAsmStreamer.Tpo -c -o libllvmmc_la-MCAsmStreamer.lo `test -f 'llvm/lib/MC/MCAsmStreamer.cpp' || echo '$(srcdir)/'`llvm/lib/MC/MCAsmStreamer.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmmc_la-MCAsmStreamer.Tpo $(DEPDIR)/libllvmmc_la-MCAsmStreamer.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/MC/MCAsmStreamer.cpp' object='libllvmmc_la-MCAsmStreamer.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmmc_la_CPPFLAGS) $(CPPFLAGS) $(libllvmmc_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmmc_la-MCAsmStreamer.lo `test -f 'llvm/lib/MC/MCAsmStreamer.cpp' || echo '$(srcdir)/'`llvm/lib/MC/MCAsmStreamer.cpp + +libllvmmc_la-MCAssembler.lo: llvm/lib/MC/MCAssembler.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmmc_la_CPPFLAGS) $(CPPFLAGS) $(libllvmmc_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmmc_la-MCAssembler.lo -MD -MP -MF $(DEPDIR)/libllvmmc_la-MCAssembler.Tpo -c -o libllvmmc_la-MCAssembler.lo `test -f 'llvm/lib/MC/MCAssembler.cpp' || echo '$(srcdir)/'`llvm/lib/MC/MCAssembler.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmmc_la-MCAssembler.Tpo $(DEPDIR)/libllvmmc_la-MCAssembler.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/MC/MCAssembler.cpp' object='libllvmmc_la-MCAssembler.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmmc_la_CPPFLAGS) $(CPPFLAGS) $(libllvmmc_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmmc_la-MCAssembler.lo `test -f 'llvm/lib/MC/MCAssembler.cpp' || echo '$(srcdir)/'`llvm/lib/MC/MCAssembler.cpp + +libllvmmc_la-MCCodeEmitter.lo: llvm/lib/MC/MCCodeEmitter.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmmc_la_CPPFLAGS) $(CPPFLAGS) $(libllvmmc_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmmc_la-MCCodeEmitter.lo -MD -MP -MF $(DEPDIR)/libllvmmc_la-MCCodeEmitter.Tpo -c -o libllvmmc_la-MCCodeEmitter.lo `test -f 'llvm/lib/MC/MCCodeEmitter.cpp' || echo '$(srcdir)/'`llvm/lib/MC/MCCodeEmitter.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmmc_la-MCCodeEmitter.Tpo $(DEPDIR)/libllvmmc_la-MCCodeEmitter.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/MC/MCCodeEmitter.cpp' object='libllvmmc_la-MCCodeEmitter.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmmc_la_CPPFLAGS) $(CPPFLAGS) $(libllvmmc_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmmc_la-MCCodeEmitter.lo `test -f 'llvm/lib/MC/MCCodeEmitter.cpp' || echo '$(srcdir)/'`llvm/lib/MC/MCCodeEmitter.cpp + +libllvmmc_la-MCContext.lo: llvm/lib/MC/MCContext.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmmc_la_CPPFLAGS) $(CPPFLAGS) $(libllvmmc_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmmc_la-MCContext.lo -MD -MP -MF $(DEPDIR)/libllvmmc_la-MCContext.Tpo -c -o libllvmmc_la-MCContext.lo `test -f 'llvm/lib/MC/MCContext.cpp' || echo '$(srcdir)/'`llvm/lib/MC/MCContext.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmmc_la-MCContext.Tpo $(DEPDIR)/libllvmmc_la-MCContext.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/MC/MCContext.cpp' object='libllvmmc_la-MCContext.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmmc_la_CPPFLAGS) $(CPPFLAGS) $(libllvmmc_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmmc_la-MCContext.lo `test -f 'llvm/lib/MC/MCContext.cpp' || echo '$(srcdir)/'`llvm/lib/MC/MCContext.cpp + +libllvmmc_la-MCExpr.lo: llvm/lib/MC/MCExpr.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmmc_la_CPPFLAGS) $(CPPFLAGS) $(libllvmmc_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmmc_la-MCExpr.lo -MD -MP -MF $(DEPDIR)/libllvmmc_la-MCExpr.Tpo -c -o libllvmmc_la-MCExpr.lo `test -f 'llvm/lib/MC/MCExpr.cpp' || echo '$(srcdir)/'`llvm/lib/MC/MCExpr.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmmc_la-MCExpr.Tpo $(DEPDIR)/libllvmmc_la-MCExpr.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/MC/MCExpr.cpp' object='libllvmmc_la-MCExpr.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmmc_la_CPPFLAGS) $(CPPFLAGS) $(libllvmmc_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmmc_la-MCExpr.lo `test -f 'llvm/lib/MC/MCExpr.cpp' || echo '$(srcdir)/'`llvm/lib/MC/MCExpr.cpp + +libllvmmc_la-MCInst.lo: llvm/lib/MC/MCInst.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmmc_la_CPPFLAGS) $(CPPFLAGS) $(libllvmmc_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmmc_la-MCInst.lo -MD -MP -MF $(DEPDIR)/libllvmmc_la-MCInst.Tpo -c -o libllvmmc_la-MCInst.lo `test -f 'llvm/lib/MC/MCInst.cpp' || echo '$(srcdir)/'`llvm/lib/MC/MCInst.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmmc_la-MCInst.Tpo $(DEPDIR)/libllvmmc_la-MCInst.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/MC/MCInst.cpp' object='libllvmmc_la-MCInst.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmmc_la_CPPFLAGS) $(CPPFLAGS) $(libllvmmc_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmmc_la-MCInst.lo `test -f 'llvm/lib/MC/MCInst.cpp' || echo '$(srcdir)/'`llvm/lib/MC/MCInst.cpp + +libllvmmc_la-MCMachOStreamer.lo: llvm/lib/MC/MCMachOStreamer.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmmc_la_CPPFLAGS) $(CPPFLAGS) $(libllvmmc_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmmc_la-MCMachOStreamer.lo -MD -MP -MF $(DEPDIR)/libllvmmc_la-MCMachOStreamer.Tpo -c -o libllvmmc_la-MCMachOStreamer.lo `test -f 'llvm/lib/MC/MCMachOStreamer.cpp' || echo '$(srcdir)/'`llvm/lib/MC/MCMachOStreamer.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmmc_la-MCMachOStreamer.Tpo $(DEPDIR)/libllvmmc_la-MCMachOStreamer.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/MC/MCMachOStreamer.cpp' object='libllvmmc_la-MCMachOStreamer.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmmc_la_CPPFLAGS) $(CPPFLAGS) $(libllvmmc_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmmc_la-MCMachOStreamer.lo `test -f 'llvm/lib/MC/MCMachOStreamer.cpp' || echo '$(srcdir)/'`llvm/lib/MC/MCMachOStreamer.cpp + +libllvmmc_la-MCNullStreamer.lo: llvm/lib/MC/MCNullStreamer.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmmc_la_CPPFLAGS) $(CPPFLAGS) $(libllvmmc_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmmc_la-MCNullStreamer.lo -MD -MP -MF $(DEPDIR)/libllvmmc_la-MCNullStreamer.Tpo -c -o libllvmmc_la-MCNullStreamer.lo `test -f 'llvm/lib/MC/MCNullStreamer.cpp' || echo '$(srcdir)/'`llvm/lib/MC/MCNullStreamer.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmmc_la-MCNullStreamer.Tpo $(DEPDIR)/libllvmmc_la-MCNullStreamer.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/MC/MCNullStreamer.cpp' object='libllvmmc_la-MCNullStreamer.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmmc_la_CPPFLAGS) $(CPPFLAGS) $(libllvmmc_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmmc_la-MCNullStreamer.lo `test -f 'llvm/lib/MC/MCNullStreamer.cpp' || echo '$(srcdir)/'`llvm/lib/MC/MCNullStreamer.cpp + +libllvmmc_la-MCSection.lo: llvm/lib/MC/MCSection.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmmc_la_CPPFLAGS) $(CPPFLAGS) $(libllvmmc_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmmc_la-MCSection.lo -MD -MP -MF $(DEPDIR)/libllvmmc_la-MCSection.Tpo -c -o libllvmmc_la-MCSection.lo `test -f 'llvm/lib/MC/MCSection.cpp' || echo '$(srcdir)/'`llvm/lib/MC/MCSection.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmmc_la-MCSection.Tpo $(DEPDIR)/libllvmmc_la-MCSection.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/MC/MCSection.cpp' object='libllvmmc_la-MCSection.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmmc_la_CPPFLAGS) $(CPPFLAGS) $(libllvmmc_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmmc_la-MCSection.lo `test -f 'llvm/lib/MC/MCSection.cpp' || echo '$(srcdir)/'`llvm/lib/MC/MCSection.cpp + +libllvmmc_la-MCSectionELF.lo: llvm/lib/MC/MCSectionELF.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmmc_la_CPPFLAGS) $(CPPFLAGS) $(libllvmmc_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmmc_la-MCSectionELF.lo -MD -MP -MF $(DEPDIR)/libllvmmc_la-MCSectionELF.Tpo -c -o libllvmmc_la-MCSectionELF.lo `test -f 'llvm/lib/MC/MCSectionELF.cpp' || echo '$(srcdir)/'`llvm/lib/MC/MCSectionELF.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmmc_la-MCSectionELF.Tpo $(DEPDIR)/libllvmmc_la-MCSectionELF.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/MC/MCSectionELF.cpp' object='libllvmmc_la-MCSectionELF.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmmc_la_CPPFLAGS) $(CPPFLAGS) $(libllvmmc_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmmc_la-MCSectionELF.lo `test -f 'llvm/lib/MC/MCSectionELF.cpp' || echo '$(srcdir)/'`llvm/lib/MC/MCSectionELF.cpp + +libllvmmc_la-MCSectionMachO.lo: llvm/lib/MC/MCSectionMachO.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmmc_la_CPPFLAGS) $(CPPFLAGS) $(libllvmmc_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmmc_la-MCSectionMachO.lo -MD -MP -MF $(DEPDIR)/libllvmmc_la-MCSectionMachO.Tpo -c -o libllvmmc_la-MCSectionMachO.lo `test -f 'llvm/lib/MC/MCSectionMachO.cpp' || echo '$(srcdir)/'`llvm/lib/MC/MCSectionMachO.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmmc_la-MCSectionMachO.Tpo $(DEPDIR)/libllvmmc_la-MCSectionMachO.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/MC/MCSectionMachO.cpp' object='libllvmmc_la-MCSectionMachO.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmmc_la_CPPFLAGS) $(CPPFLAGS) $(libllvmmc_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmmc_la-MCSectionMachO.lo `test -f 'llvm/lib/MC/MCSectionMachO.cpp' || echo '$(srcdir)/'`llvm/lib/MC/MCSectionMachO.cpp + +libllvmmc_la-MCStreamer.lo: llvm/lib/MC/MCStreamer.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmmc_la_CPPFLAGS) $(CPPFLAGS) $(libllvmmc_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmmc_la-MCStreamer.lo -MD -MP -MF $(DEPDIR)/libllvmmc_la-MCStreamer.Tpo -c -o libllvmmc_la-MCStreamer.lo `test -f 'llvm/lib/MC/MCStreamer.cpp' || echo '$(srcdir)/'`llvm/lib/MC/MCStreamer.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmmc_la-MCStreamer.Tpo $(DEPDIR)/libllvmmc_la-MCStreamer.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/MC/MCStreamer.cpp' object='libllvmmc_la-MCStreamer.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmmc_la_CPPFLAGS) $(CPPFLAGS) $(libllvmmc_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmmc_la-MCStreamer.lo `test -f 'llvm/lib/MC/MCStreamer.cpp' || echo '$(srcdir)/'`llvm/lib/MC/MCStreamer.cpp + +libllvmmc_la-MCSymbol.lo: llvm/lib/MC/MCSymbol.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmmc_la_CPPFLAGS) $(CPPFLAGS) $(libllvmmc_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmmc_la-MCSymbol.lo -MD -MP -MF $(DEPDIR)/libllvmmc_la-MCSymbol.Tpo -c -o libllvmmc_la-MCSymbol.lo `test -f 'llvm/lib/MC/MCSymbol.cpp' || echo '$(srcdir)/'`llvm/lib/MC/MCSymbol.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmmc_la-MCSymbol.Tpo $(DEPDIR)/libllvmmc_la-MCSymbol.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/MC/MCSymbol.cpp' object='libllvmmc_la-MCSymbol.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmmc_la_CPPFLAGS) $(CPPFLAGS) $(libllvmmc_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmmc_la-MCSymbol.lo `test -f 'llvm/lib/MC/MCSymbol.cpp' || echo '$(srcdir)/'`llvm/lib/MC/MCSymbol.cpp + +libllvmmc_la-MCValue.lo: llvm/lib/MC/MCValue.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmmc_la_CPPFLAGS) $(CPPFLAGS) $(libllvmmc_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmmc_la-MCValue.lo -MD -MP -MF $(DEPDIR)/libllvmmc_la-MCValue.Tpo -c -o libllvmmc_la-MCValue.lo `test -f 'llvm/lib/MC/MCValue.cpp' || echo '$(srcdir)/'`llvm/lib/MC/MCValue.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmmc_la-MCValue.Tpo $(DEPDIR)/libllvmmc_la-MCValue.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/MC/MCValue.cpp' object='libllvmmc_la-MCValue.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmmc_la_CPPFLAGS) $(CPPFLAGS) $(libllvmmc_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmmc_la-MCValue.lo `test -f 'llvm/lib/MC/MCValue.cpp' || echo '$(srcdir)/'`llvm/lib/MC/MCValue.cpp + +libllvmmc_la-TargetAsmParser.lo: llvm/lib/MC/TargetAsmParser.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmmc_la_CPPFLAGS) $(CPPFLAGS) $(libllvmmc_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmmc_la-TargetAsmParser.lo -MD -MP -MF $(DEPDIR)/libllvmmc_la-TargetAsmParser.Tpo -c -o libllvmmc_la-TargetAsmParser.lo `test -f 'llvm/lib/MC/TargetAsmParser.cpp' || echo '$(srcdir)/'`llvm/lib/MC/TargetAsmParser.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmmc_la-TargetAsmParser.Tpo $(DEPDIR)/libllvmmc_la-TargetAsmParser.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/MC/TargetAsmParser.cpp' object='libllvmmc_la-TargetAsmParser.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmmc_la_CPPFLAGS) $(CPPFLAGS) $(libllvmmc_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmmc_la-TargetAsmParser.lo `test -f 'llvm/lib/MC/TargetAsmParser.cpp' || echo '$(srcdir)/'`llvm/lib/MC/TargetAsmParser.cpp + +libllvmscalar_la-CodeGenPrepare.lo: llvm/lib/Transforms/Scalar/CodeGenPrepare.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmscalar_la_CPPFLAGS) $(CPPFLAGS) $(libllvmscalar_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmscalar_la-CodeGenPrepare.lo -MD -MP -MF $(DEPDIR)/libllvmscalar_la-CodeGenPrepare.Tpo -c -o libllvmscalar_la-CodeGenPrepare.lo `test -f 'llvm/lib/Transforms/Scalar/CodeGenPrepare.cpp' || echo '$(srcdir)/'`llvm/lib/Transforms/Scalar/CodeGenPrepare.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmscalar_la-CodeGenPrepare.Tpo $(DEPDIR)/libllvmscalar_la-CodeGenPrepare.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Transforms/Scalar/CodeGenPrepare.cpp' object='libllvmscalar_la-CodeGenPrepare.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmscalar_la_CPPFLAGS) $(CPPFLAGS) $(libllvmscalar_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmscalar_la-CodeGenPrepare.lo `test -f 'llvm/lib/Transforms/Scalar/CodeGenPrepare.cpp' || echo '$(srcdir)/'`llvm/lib/Transforms/Scalar/CodeGenPrepare.cpp + +libllvmscalar_la-DCE.lo: llvm/lib/Transforms/Scalar/DCE.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmscalar_la_CPPFLAGS) $(CPPFLAGS) $(libllvmscalar_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmscalar_la-DCE.lo -MD -MP -MF $(DEPDIR)/libllvmscalar_la-DCE.Tpo -c -o libllvmscalar_la-DCE.lo `test -f 'llvm/lib/Transforms/Scalar/DCE.cpp' || echo '$(srcdir)/'`llvm/lib/Transforms/Scalar/DCE.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmscalar_la-DCE.Tpo $(DEPDIR)/libllvmscalar_la-DCE.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Transforms/Scalar/DCE.cpp' object='libllvmscalar_la-DCE.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmscalar_la_CPPFLAGS) $(CPPFLAGS) $(libllvmscalar_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmscalar_la-DCE.lo `test -f 'llvm/lib/Transforms/Scalar/DCE.cpp' || echo '$(srcdir)/'`llvm/lib/Transforms/Scalar/DCE.cpp + +libllvmscalar_la-GEPSplitter.lo: llvm/lib/Transforms/Scalar/GEPSplitter.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmscalar_la_CPPFLAGS) $(CPPFLAGS) $(libllvmscalar_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmscalar_la-GEPSplitter.lo -MD -MP -MF $(DEPDIR)/libllvmscalar_la-GEPSplitter.Tpo -c -o libllvmscalar_la-GEPSplitter.lo `test -f 'llvm/lib/Transforms/Scalar/GEPSplitter.cpp' || echo '$(srcdir)/'`llvm/lib/Transforms/Scalar/GEPSplitter.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmscalar_la-GEPSplitter.Tpo $(DEPDIR)/libllvmscalar_la-GEPSplitter.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Transforms/Scalar/GEPSplitter.cpp' object='libllvmscalar_la-GEPSplitter.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmscalar_la_CPPFLAGS) $(CPPFLAGS) $(libllvmscalar_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmscalar_la-GEPSplitter.lo `test -f 'llvm/lib/Transforms/Scalar/GEPSplitter.cpp' || echo '$(srcdir)/'`llvm/lib/Transforms/Scalar/GEPSplitter.cpp + +libllvmscalar_la-GVN.lo: llvm/lib/Transforms/Scalar/GVN.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmscalar_la_CPPFLAGS) $(CPPFLAGS) $(libllvmscalar_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmscalar_la-GVN.lo -MD -MP -MF $(DEPDIR)/libllvmscalar_la-GVN.Tpo -c -o libllvmscalar_la-GVN.lo `test -f 'llvm/lib/Transforms/Scalar/GVN.cpp' || echo '$(srcdir)/'`llvm/lib/Transforms/Scalar/GVN.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmscalar_la-GVN.Tpo $(DEPDIR)/libllvmscalar_la-GVN.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Transforms/Scalar/GVN.cpp' object='libllvmscalar_la-GVN.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmscalar_la_CPPFLAGS) $(CPPFLAGS) $(libllvmscalar_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmscalar_la-GVN.lo `test -f 'llvm/lib/Transforms/Scalar/GVN.cpp' || echo '$(srcdir)/'`llvm/lib/Transforms/Scalar/GVN.cpp + +libllvmscalar_la-LoopStrengthReduce.lo: llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmscalar_la_CPPFLAGS) $(CPPFLAGS) $(libllvmscalar_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmscalar_la-LoopStrengthReduce.lo -MD -MP -MF $(DEPDIR)/libllvmscalar_la-LoopStrengthReduce.Tpo -c -o libllvmscalar_la-LoopStrengthReduce.lo `test -f 'llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp' || echo '$(srcdir)/'`llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmscalar_la-LoopStrengthReduce.Tpo $(DEPDIR)/libllvmscalar_la-LoopStrengthReduce.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp' object='libllvmscalar_la-LoopStrengthReduce.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmscalar_la_CPPFLAGS) $(CPPFLAGS) $(libllvmscalar_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmscalar_la-LoopStrengthReduce.lo `test -f 'llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp' || echo '$(srcdir)/'`llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp + +libllvmscalar_la-ConstantProp.lo: llvm/lib/Transforms/Scalar/ConstantProp.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmscalar_la_CPPFLAGS) $(CPPFLAGS) $(libllvmscalar_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmscalar_la-ConstantProp.lo -MD -MP -MF $(DEPDIR)/libllvmscalar_la-ConstantProp.Tpo -c -o libllvmscalar_la-ConstantProp.lo `test -f 'llvm/lib/Transforms/Scalar/ConstantProp.cpp' || echo '$(srcdir)/'`llvm/lib/Transforms/Scalar/ConstantProp.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmscalar_la-ConstantProp.Tpo $(DEPDIR)/libllvmscalar_la-ConstantProp.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Transforms/Scalar/ConstantProp.cpp' object='libllvmscalar_la-ConstantProp.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmscalar_la_CPPFLAGS) $(CPPFLAGS) $(libllvmscalar_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmscalar_la-ConstantProp.lo `test -f 'llvm/lib/Transforms/Scalar/ConstantProp.cpp' || echo '$(srcdir)/'`llvm/lib/Transforms/Scalar/ConstantProp.cpp + +libllvmscalar_la-SimplifyCFGPass.lo: llvm/lib/Transforms/Scalar/SimplifyCFGPass.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmscalar_la_CPPFLAGS) $(CPPFLAGS) $(libllvmscalar_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmscalar_la-SimplifyCFGPass.lo -MD -MP -MF $(DEPDIR)/libllvmscalar_la-SimplifyCFGPass.Tpo -c -o libllvmscalar_la-SimplifyCFGPass.lo `test -f 'llvm/lib/Transforms/Scalar/SimplifyCFGPass.cpp' || echo '$(srcdir)/'`llvm/lib/Transforms/Scalar/SimplifyCFGPass.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmscalar_la-SimplifyCFGPass.Tpo $(DEPDIR)/libllvmscalar_la-SimplifyCFGPass.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Transforms/Scalar/SimplifyCFGPass.cpp' object='libllvmscalar_la-SimplifyCFGPass.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmscalar_la_CPPFLAGS) $(CPPFLAGS) $(libllvmscalar_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmscalar_la-SimplifyCFGPass.lo `test -f 'llvm/lib/Transforms/Scalar/SimplifyCFGPass.cpp' || echo '$(srcdir)/'`llvm/lib/Transforms/Scalar/SimplifyCFGPass.cpp + +libllvmsdag_la-CallingConvLower.lo: llvm/lib/CodeGen/SelectionDAG/CallingConvLower.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsdag_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsdag_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmsdag_la-CallingConvLower.lo -MD -MP -MF $(DEPDIR)/libllvmsdag_la-CallingConvLower.Tpo -c -o libllvmsdag_la-CallingConvLower.lo `test -f 'llvm/lib/CodeGen/SelectionDAG/CallingConvLower.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/SelectionDAG/CallingConvLower.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmsdag_la-CallingConvLower.Tpo $(DEPDIR)/libllvmsdag_la-CallingConvLower.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/CodeGen/SelectionDAG/CallingConvLower.cpp' object='libllvmsdag_la-CallingConvLower.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsdag_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsdag_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmsdag_la-CallingConvLower.lo `test -f 'llvm/lib/CodeGen/SelectionDAG/CallingConvLower.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/SelectionDAG/CallingConvLower.cpp + +libllvmsdag_la-DAGCombiner.lo: llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsdag_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsdag_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmsdag_la-DAGCombiner.lo -MD -MP -MF $(DEPDIR)/libllvmsdag_la-DAGCombiner.Tpo -c -o libllvmsdag_la-DAGCombiner.lo `test -f 'llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmsdag_la-DAGCombiner.Tpo $(DEPDIR)/libllvmsdag_la-DAGCombiner.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp' object='libllvmsdag_la-DAGCombiner.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsdag_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsdag_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmsdag_la-DAGCombiner.lo `test -f 'llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp + +libllvmsdag_la-FastISel.lo: llvm/lib/CodeGen/SelectionDAG/FastISel.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsdag_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsdag_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmsdag_la-FastISel.lo -MD -MP -MF $(DEPDIR)/libllvmsdag_la-FastISel.Tpo -c -o libllvmsdag_la-FastISel.lo `test -f 'llvm/lib/CodeGen/SelectionDAG/FastISel.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/SelectionDAG/FastISel.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmsdag_la-FastISel.Tpo $(DEPDIR)/libllvmsdag_la-FastISel.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/CodeGen/SelectionDAG/FastISel.cpp' object='libllvmsdag_la-FastISel.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsdag_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsdag_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmsdag_la-FastISel.lo `test -f 'llvm/lib/CodeGen/SelectionDAG/FastISel.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/SelectionDAG/FastISel.cpp + +libllvmsdag_la-FunctionLoweringInfo.lo: llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsdag_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsdag_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmsdag_la-FunctionLoweringInfo.lo -MD -MP -MF $(DEPDIR)/libllvmsdag_la-FunctionLoweringInfo.Tpo -c -o libllvmsdag_la-FunctionLoweringInfo.lo `test -f 'llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmsdag_la-FunctionLoweringInfo.Tpo $(DEPDIR)/libllvmsdag_la-FunctionLoweringInfo.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp' object='libllvmsdag_la-FunctionLoweringInfo.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsdag_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsdag_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmsdag_la-FunctionLoweringInfo.lo `test -f 'llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp + +libllvmsdag_la-InstrEmitter.lo: llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsdag_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsdag_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmsdag_la-InstrEmitter.lo -MD -MP -MF $(DEPDIR)/libllvmsdag_la-InstrEmitter.Tpo -c -o libllvmsdag_la-InstrEmitter.lo `test -f 'llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmsdag_la-InstrEmitter.Tpo $(DEPDIR)/libllvmsdag_la-InstrEmitter.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp' object='libllvmsdag_la-InstrEmitter.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsdag_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsdag_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmsdag_la-InstrEmitter.lo `test -f 'llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp + +libllvmsdag_la-LegalizeDAG.lo: llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsdag_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsdag_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmsdag_la-LegalizeDAG.lo -MD -MP -MF $(DEPDIR)/libllvmsdag_la-LegalizeDAG.Tpo -c -o libllvmsdag_la-LegalizeDAG.lo `test -f 'llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmsdag_la-LegalizeDAG.Tpo $(DEPDIR)/libllvmsdag_la-LegalizeDAG.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp' object='libllvmsdag_la-LegalizeDAG.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsdag_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsdag_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmsdag_la-LegalizeDAG.lo `test -f 'llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp + +libllvmsdag_la-LegalizeFloatTypes.lo: llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsdag_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsdag_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmsdag_la-LegalizeFloatTypes.lo -MD -MP -MF $(DEPDIR)/libllvmsdag_la-LegalizeFloatTypes.Tpo -c -o libllvmsdag_la-LegalizeFloatTypes.lo `test -f 'llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmsdag_la-LegalizeFloatTypes.Tpo $(DEPDIR)/libllvmsdag_la-LegalizeFloatTypes.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp' object='libllvmsdag_la-LegalizeFloatTypes.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsdag_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsdag_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmsdag_la-LegalizeFloatTypes.lo `test -f 'llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp + +libllvmsdag_la-LegalizeIntegerTypes.lo: llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsdag_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsdag_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmsdag_la-LegalizeIntegerTypes.lo -MD -MP -MF $(DEPDIR)/libllvmsdag_la-LegalizeIntegerTypes.Tpo -c -o libllvmsdag_la-LegalizeIntegerTypes.lo `test -f 'llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmsdag_la-LegalizeIntegerTypes.Tpo $(DEPDIR)/libllvmsdag_la-LegalizeIntegerTypes.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp' object='libllvmsdag_la-LegalizeIntegerTypes.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsdag_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsdag_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmsdag_la-LegalizeIntegerTypes.lo `test -f 'llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp + +libllvmsdag_la-LegalizeTypes.lo: llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsdag_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsdag_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmsdag_la-LegalizeTypes.lo -MD -MP -MF $(DEPDIR)/libllvmsdag_la-LegalizeTypes.Tpo -c -o libllvmsdag_la-LegalizeTypes.lo `test -f 'llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmsdag_la-LegalizeTypes.Tpo $(DEPDIR)/libllvmsdag_la-LegalizeTypes.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp' object='libllvmsdag_la-LegalizeTypes.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsdag_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsdag_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmsdag_la-LegalizeTypes.lo `test -f 'llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp + +libllvmsdag_la-LegalizeTypesGeneric.lo: llvm/lib/CodeGen/SelectionDAG/LegalizeTypesGeneric.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsdag_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsdag_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmsdag_la-LegalizeTypesGeneric.lo -MD -MP -MF $(DEPDIR)/libllvmsdag_la-LegalizeTypesGeneric.Tpo -c -o libllvmsdag_la-LegalizeTypesGeneric.lo `test -f 'llvm/lib/CodeGen/SelectionDAG/LegalizeTypesGeneric.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/SelectionDAG/LegalizeTypesGeneric.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmsdag_la-LegalizeTypesGeneric.Tpo $(DEPDIR)/libllvmsdag_la-LegalizeTypesGeneric.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/CodeGen/SelectionDAG/LegalizeTypesGeneric.cpp' object='libllvmsdag_la-LegalizeTypesGeneric.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsdag_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsdag_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmsdag_la-LegalizeTypesGeneric.lo `test -f 'llvm/lib/CodeGen/SelectionDAG/LegalizeTypesGeneric.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/SelectionDAG/LegalizeTypesGeneric.cpp + +libllvmsdag_la-LegalizeVectorOps.lo: llvm/lib/CodeGen/SelectionDAG/LegalizeVectorOps.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsdag_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsdag_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmsdag_la-LegalizeVectorOps.lo -MD -MP -MF $(DEPDIR)/libllvmsdag_la-LegalizeVectorOps.Tpo -c -o libllvmsdag_la-LegalizeVectorOps.lo `test -f 'llvm/lib/CodeGen/SelectionDAG/LegalizeVectorOps.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/SelectionDAG/LegalizeVectorOps.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmsdag_la-LegalizeVectorOps.Tpo $(DEPDIR)/libllvmsdag_la-LegalizeVectorOps.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/CodeGen/SelectionDAG/LegalizeVectorOps.cpp' object='libllvmsdag_la-LegalizeVectorOps.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsdag_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsdag_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmsdag_la-LegalizeVectorOps.lo `test -f 'llvm/lib/CodeGen/SelectionDAG/LegalizeVectorOps.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/SelectionDAG/LegalizeVectorOps.cpp + +libllvmsdag_la-LegalizeVectorTypes.lo: llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsdag_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsdag_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmsdag_la-LegalizeVectorTypes.lo -MD -MP -MF $(DEPDIR)/libllvmsdag_la-LegalizeVectorTypes.Tpo -c -o libllvmsdag_la-LegalizeVectorTypes.lo `test -f 'llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmsdag_la-LegalizeVectorTypes.Tpo $(DEPDIR)/libllvmsdag_la-LegalizeVectorTypes.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp' object='libllvmsdag_la-LegalizeVectorTypes.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsdag_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsdag_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmsdag_la-LegalizeVectorTypes.lo `test -f 'llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp + +libllvmsdag_la-ScheduleDAGFast.lo: llvm/lib/CodeGen/SelectionDAG/ScheduleDAGFast.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsdag_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsdag_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmsdag_la-ScheduleDAGFast.lo -MD -MP -MF $(DEPDIR)/libllvmsdag_la-ScheduleDAGFast.Tpo -c -o libllvmsdag_la-ScheduleDAGFast.lo `test -f 'llvm/lib/CodeGen/SelectionDAG/ScheduleDAGFast.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/SelectionDAG/ScheduleDAGFast.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmsdag_la-ScheduleDAGFast.Tpo $(DEPDIR)/libllvmsdag_la-ScheduleDAGFast.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/CodeGen/SelectionDAG/ScheduleDAGFast.cpp' object='libllvmsdag_la-ScheduleDAGFast.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsdag_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsdag_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmsdag_la-ScheduleDAGFast.lo `test -f 'llvm/lib/CodeGen/SelectionDAG/ScheduleDAGFast.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/SelectionDAG/ScheduleDAGFast.cpp + +libllvmsdag_la-ScheduleDAGList.lo: llvm/lib/CodeGen/SelectionDAG/ScheduleDAGList.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsdag_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsdag_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmsdag_la-ScheduleDAGList.lo -MD -MP -MF $(DEPDIR)/libllvmsdag_la-ScheduleDAGList.Tpo -c -o libllvmsdag_la-ScheduleDAGList.lo `test -f 'llvm/lib/CodeGen/SelectionDAG/ScheduleDAGList.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/SelectionDAG/ScheduleDAGList.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmsdag_la-ScheduleDAGList.Tpo $(DEPDIR)/libllvmsdag_la-ScheduleDAGList.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/CodeGen/SelectionDAG/ScheduleDAGList.cpp' object='libllvmsdag_la-ScheduleDAGList.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsdag_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsdag_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmsdag_la-ScheduleDAGList.lo `test -f 'llvm/lib/CodeGen/SelectionDAG/ScheduleDAGList.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/SelectionDAG/ScheduleDAGList.cpp + +libllvmsdag_la-ScheduleDAGRRList.lo: llvm/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsdag_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsdag_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmsdag_la-ScheduleDAGRRList.lo -MD -MP -MF $(DEPDIR)/libllvmsdag_la-ScheduleDAGRRList.Tpo -c -o libllvmsdag_la-ScheduleDAGRRList.lo `test -f 'llvm/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmsdag_la-ScheduleDAGRRList.Tpo $(DEPDIR)/libllvmsdag_la-ScheduleDAGRRList.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp' object='libllvmsdag_la-ScheduleDAGRRList.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsdag_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsdag_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmsdag_la-ScheduleDAGRRList.lo `test -f 'llvm/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp + +libllvmsdag_la-ScheduleDAGSDNodes.lo: llvm/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsdag_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsdag_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmsdag_la-ScheduleDAGSDNodes.lo -MD -MP -MF $(DEPDIR)/libllvmsdag_la-ScheduleDAGSDNodes.Tpo -c -o libllvmsdag_la-ScheduleDAGSDNodes.lo `test -f 'llvm/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmsdag_la-ScheduleDAGSDNodes.Tpo $(DEPDIR)/libllvmsdag_la-ScheduleDAGSDNodes.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp' object='libllvmsdag_la-ScheduleDAGSDNodes.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsdag_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsdag_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmsdag_la-ScheduleDAGSDNodes.lo `test -f 'llvm/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp + +libllvmsdag_la-SelectionDAG.lo: llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsdag_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsdag_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmsdag_la-SelectionDAG.lo -MD -MP -MF $(DEPDIR)/libllvmsdag_la-SelectionDAG.Tpo -c -o libllvmsdag_la-SelectionDAG.lo `test -f 'llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmsdag_la-SelectionDAG.Tpo $(DEPDIR)/libllvmsdag_la-SelectionDAG.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp' object='libllvmsdag_la-SelectionDAG.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsdag_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsdag_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmsdag_la-SelectionDAG.lo `test -f 'llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp + +libllvmsdag_la-SelectionDAGBuilder.lo: llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsdag_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsdag_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmsdag_la-SelectionDAGBuilder.lo -MD -MP -MF $(DEPDIR)/libllvmsdag_la-SelectionDAGBuilder.Tpo -c -o libllvmsdag_la-SelectionDAGBuilder.lo `test -f 'llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmsdag_la-SelectionDAGBuilder.Tpo $(DEPDIR)/libllvmsdag_la-SelectionDAGBuilder.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp' object='libllvmsdag_la-SelectionDAGBuilder.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsdag_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsdag_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmsdag_la-SelectionDAGBuilder.lo `test -f 'llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp + +libllvmsdag_la-SelectionDAGISel.lo: llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsdag_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsdag_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmsdag_la-SelectionDAGISel.lo -MD -MP -MF $(DEPDIR)/libllvmsdag_la-SelectionDAGISel.Tpo -c -o libllvmsdag_la-SelectionDAGISel.lo `test -f 'llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmsdag_la-SelectionDAGISel.Tpo $(DEPDIR)/libllvmsdag_la-SelectionDAGISel.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp' object='libllvmsdag_la-SelectionDAGISel.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsdag_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsdag_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmsdag_la-SelectionDAGISel.lo `test -f 'llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp + +libllvmsdag_la-SelectionDAGPrinter.lo: llvm/lib/CodeGen/SelectionDAG/SelectionDAGPrinter.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsdag_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsdag_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmsdag_la-SelectionDAGPrinter.lo -MD -MP -MF $(DEPDIR)/libllvmsdag_la-SelectionDAGPrinter.Tpo -c -o libllvmsdag_la-SelectionDAGPrinter.lo `test -f 'llvm/lib/CodeGen/SelectionDAG/SelectionDAGPrinter.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/SelectionDAG/SelectionDAGPrinter.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmsdag_la-SelectionDAGPrinter.Tpo $(DEPDIR)/libllvmsdag_la-SelectionDAGPrinter.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/CodeGen/SelectionDAG/SelectionDAGPrinter.cpp' object='libllvmsdag_la-SelectionDAGPrinter.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsdag_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsdag_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmsdag_la-SelectionDAGPrinter.lo `test -f 'llvm/lib/CodeGen/SelectionDAG/SelectionDAGPrinter.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/SelectionDAG/SelectionDAGPrinter.cpp + +libllvmsdag_la-TargetLowering.lo: llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsdag_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsdag_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmsdag_la-TargetLowering.lo -MD -MP -MF $(DEPDIR)/libllvmsdag_la-TargetLowering.Tpo -c -o libllvmsdag_la-TargetLowering.lo `test -f 'llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmsdag_la-TargetLowering.Tpo $(DEPDIR)/libllvmsdag_la-TargetLowering.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp' object='libllvmsdag_la-TargetLowering.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsdag_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsdag_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmsdag_la-TargetLowering.lo `test -f 'llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp + +libllvmsdag_la-DwarfWriter.lo: llvm/lib/CodeGen/AsmPrinter/DwarfWriter.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsdag_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsdag_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmsdag_la-DwarfWriter.lo -MD -MP -MF $(DEPDIR)/libllvmsdag_la-DwarfWriter.Tpo -c -o libllvmsdag_la-DwarfWriter.lo `test -f 'llvm/lib/CodeGen/AsmPrinter/DwarfWriter.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/AsmPrinter/DwarfWriter.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmsdag_la-DwarfWriter.Tpo $(DEPDIR)/libllvmsdag_la-DwarfWriter.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/CodeGen/AsmPrinter/DwarfWriter.cpp' object='libllvmsdag_la-DwarfWriter.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsdag_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsdag_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmsdag_la-DwarfWriter.lo `test -f 'llvm/lib/CodeGen/AsmPrinter/DwarfWriter.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/AsmPrinter/DwarfWriter.cpp + +libllvmsdag_la-DwarfDebug.lo: llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsdag_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsdag_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmsdag_la-DwarfDebug.lo -MD -MP -MF $(DEPDIR)/libllvmsdag_la-DwarfDebug.Tpo -c -o libllvmsdag_la-DwarfDebug.lo `test -f 'llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmsdag_la-DwarfDebug.Tpo $(DEPDIR)/libllvmsdag_la-DwarfDebug.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp' object='libllvmsdag_la-DwarfDebug.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsdag_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsdag_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmsdag_la-DwarfDebug.lo `test -f 'llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp + +libllvmsdag_la-DwarfException.lo: llvm/lib/CodeGen/AsmPrinter/DwarfException.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsdag_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsdag_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmsdag_la-DwarfException.lo -MD -MP -MF $(DEPDIR)/libllvmsdag_la-DwarfException.Tpo -c -o libllvmsdag_la-DwarfException.lo `test -f 'llvm/lib/CodeGen/AsmPrinter/DwarfException.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/AsmPrinter/DwarfException.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmsdag_la-DwarfException.Tpo $(DEPDIR)/libllvmsdag_la-DwarfException.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/CodeGen/AsmPrinter/DwarfException.cpp' object='libllvmsdag_la-DwarfException.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsdag_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsdag_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmsdag_la-DwarfException.lo `test -f 'llvm/lib/CodeGen/AsmPrinter/DwarfException.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/AsmPrinter/DwarfException.cpp + +libllvmsdag_la-DwarfLabel.lo: llvm/lib/CodeGen/AsmPrinter/DwarfLabel.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsdag_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsdag_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmsdag_la-DwarfLabel.lo -MD -MP -MF $(DEPDIR)/libllvmsdag_la-DwarfLabel.Tpo -c -o libllvmsdag_la-DwarfLabel.lo `test -f 'llvm/lib/CodeGen/AsmPrinter/DwarfLabel.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/AsmPrinter/DwarfLabel.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmsdag_la-DwarfLabel.Tpo $(DEPDIR)/libllvmsdag_la-DwarfLabel.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/CodeGen/AsmPrinter/DwarfLabel.cpp' object='libllvmsdag_la-DwarfLabel.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsdag_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsdag_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmsdag_la-DwarfLabel.lo `test -f 'llvm/lib/CodeGen/AsmPrinter/DwarfLabel.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/AsmPrinter/DwarfLabel.cpp + +libllvmsdag_la-DwarfPrinter.lo: llvm/lib/CodeGen/AsmPrinter/DwarfPrinter.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsdag_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsdag_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmsdag_la-DwarfPrinter.lo -MD -MP -MF $(DEPDIR)/libllvmsdag_la-DwarfPrinter.Tpo -c -o libllvmsdag_la-DwarfPrinter.lo `test -f 'llvm/lib/CodeGen/AsmPrinter/DwarfPrinter.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/AsmPrinter/DwarfPrinter.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmsdag_la-DwarfPrinter.Tpo $(DEPDIR)/libllvmsdag_la-DwarfPrinter.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/CodeGen/AsmPrinter/DwarfPrinter.cpp' object='libllvmsdag_la-DwarfPrinter.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsdag_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsdag_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmsdag_la-DwarfPrinter.lo `test -f 'llvm/lib/CodeGen/AsmPrinter/DwarfPrinter.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/AsmPrinter/DwarfPrinter.cpp + +libllvmsdag_la-DIE.lo: llvm/lib/CodeGen/AsmPrinter/DIE.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsdag_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsdag_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmsdag_la-DIE.lo -MD -MP -MF $(DEPDIR)/libllvmsdag_la-DIE.Tpo -c -o libllvmsdag_la-DIE.lo `test -f 'llvm/lib/CodeGen/AsmPrinter/DIE.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/AsmPrinter/DIE.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmsdag_la-DIE.Tpo $(DEPDIR)/libllvmsdag_la-DIE.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/CodeGen/AsmPrinter/DIE.cpp' object='libllvmsdag_la-DIE.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsdag_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsdag_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmsdag_la-DIE.lo `test -f 'llvm/lib/CodeGen/AsmPrinter/DIE.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/AsmPrinter/DIE.cpp + +libllvmsdag_la-AsmPrinter.lo: llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsdag_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsdag_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmsdag_la-AsmPrinter.lo -MD -MP -MF $(DEPDIR)/libllvmsdag_la-AsmPrinter.Tpo -c -o libllvmsdag_la-AsmPrinter.lo `test -f 'llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmsdag_la-AsmPrinter.Tpo $(DEPDIR)/libllvmsdag_la-AsmPrinter.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp' object='libllvmsdag_la-AsmPrinter.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsdag_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsdag_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmsdag_la-AsmPrinter.lo `test -f 'llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp + +libllvmsupport_la-APFloat.lo: llvm/lib/Support/APFloat.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsupport_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsupport_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmsupport_la-APFloat.lo -MD -MP -MF $(DEPDIR)/libllvmsupport_la-APFloat.Tpo -c -o libllvmsupport_la-APFloat.lo `test -f 'llvm/lib/Support/APFloat.cpp' || echo '$(srcdir)/'`llvm/lib/Support/APFloat.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmsupport_la-APFloat.Tpo $(DEPDIR)/libllvmsupport_la-APFloat.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Support/APFloat.cpp' object='libllvmsupport_la-APFloat.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsupport_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsupport_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmsupport_la-APFloat.lo `test -f 'llvm/lib/Support/APFloat.cpp' || echo '$(srcdir)/'`llvm/lib/Support/APFloat.cpp + +libllvmsupport_la-APInt.lo: llvm/lib/Support/APInt.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsupport_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsupport_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmsupport_la-APInt.lo -MD -MP -MF $(DEPDIR)/libllvmsupport_la-APInt.Tpo -c -o libllvmsupport_la-APInt.lo `test -f 'llvm/lib/Support/APInt.cpp' || echo '$(srcdir)/'`llvm/lib/Support/APInt.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmsupport_la-APInt.Tpo $(DEPDIR)/libllvmsupport_la-APInt.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Support/APInt.cpp' object='libllvmsupport_la-APInt.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsupport_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsupport_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmsupport_la-APInt.lo `test -f 'llvm/lib/Support/APInt.cpp' || echo '$(srcdir)/'`llvm/lib/Support/APInt.cpp + +libllvmsupport_la-APSInt.lo: llvm/lib/Support/APSInt.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsupport_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsupport_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmsupport_la-APSInt.lo -MD -MP -MF $(DEPDIR)/libllvmsupport_la-APSInt.Tpo -c -o libllvmsupport_la-APSInt.lo `test -f 'llvm/lib/Support/APSInt.cpp' || echo '$(srcdir)/'`llvm/lib/Support/APSInt.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmsupport_la-APSInt.Tpo $(DEPDIR)/libllvmsupport_la-APSInt.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Support/APSInt.cpp' object='libllvmsupport_la-APSInt.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsupport_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsupport_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmsupport_la-APSInt.lo `test -f 'llvm/lib/Support/APSInt.cpp' || echo '$(srcdir)/'`llvm/lib/Support/APSInt.cpp + +libllvmsupport_la-Allocator.lo: llvm/lib/Support/Allocator.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsupport_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsupport_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmsupport_la-Allocator.lo -MD -MP -MF $(DEPDIR)/libllvmsupport_la-Allocator.Tpo -c -o libllvmsupport_la-Allocator.lo `test -f 'llvm/lib/Support/Allocator.cpp' || echo '$(srcdir)/'`llvm/lib/Support/Allocator.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmsupport_la-Allocator.Tpo $(DEPDIR)/libllvmsupport_la-Allocator.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Support/Allocator.cpp' object='libllvmsupport_la-Allocator.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsupport_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsupport_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmsupport_la-Allocator.lo `test -f 'llvm/lib/Support/Allocator.cpp' || echo '$(srcdir)/'`llvm/lib/Support/Allocator.cpp + +libllvmsupport_la-CommandLine.lo: llvm/lib/Support/CommandLine.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsupport_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsupport_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmsupport_la-CommandLine.lo -MD -MP -MF $(DEPDIR)/libllvmsupport_la-CommandLine.Tpo -c -o libllvmsupport_la-CommandLine.lo `test -f 'llvm/lib/Support/CommandLine.cpp' || echo '$(srcdir)/'`llvm/lib/Support/CommandLine.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmsupport_la-CommandLine.Tpo $(DEPDIR)/libllvmsupport_la-CommandLine.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Support/CommandLine.cpp' object='libllvmsupport_la-CommandLine.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsupport_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsupport_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmsupport_la-CommandLine.lo `test -f 'llvm/lib/Support/CommandLine.cpp' || echo '$(srcdir)/'`llvm/lib/Support/CommandLine.cpp + +libllvmsupport_la-ConstantRange.lo: llvm/lib/Support/ConstantRange.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsupport_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsupport_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmsupport_la-ConstantRange.lo -MD -MP -MF $(DEPDIR)/libllvmsupport_la-ConstantRange.Tpo -c -o libllvmsupport_la-ConstantRange.lo `test -f 'llvm/lib/Support/ConstantRange.cpp' || echo '$(srcdir)/'`llvm/lib/Support/ConstantRange.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmsupport_la-ConstantRange.Tpo $(DEPDIR)/libllvmsupport_la-ConstantRange.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Support/ConstantRange.cpp' object='libllvmsupport_la-ConstantRange.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsupport_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsupport_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmsupport_la-ConstantRange.lo `test -f 'llvm/lib/Support/ConstantRange.cpp' || echo '$(srcdir)/'`llvm/lib/Support/ConstantRange.cpp + +libllvmsupport_la-Debug.lo: llvm/lib/Support/Debug.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsupport_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsupport_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmsupport_la-Debug.lo -MD -MP -MF $(DEPDIR)/libllvmsupport_la-Debug.Tpo -c -o libllvmsupport_la-Debug.lo `test -f 'llvm/lib/Support/Debug.cpp' || echo '$(srcdir)/'`llvm/lib/Support/Debug.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmsupport_la-Debug.Tpo $(DEPDIR)/libllvmsupport_la-Debug.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Support/Debug.cpp' object='libllvmsupport_la-Debug.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsupport_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsupport_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmsupport_la-Debug.lo `test -f 'llvm/lib/Support/Debug.cpp' || echo '$(srcdir)/'`llvm/lib/Support/Debug.cpp + +libllvmsupport_la-Dwarf.lo: llvm/lib/Support/Dwarf.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsupport_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsupport_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmsupport_la-Dwarf.lo -MD -MP -MF $(DEPDIR)/libllvmsupport_la-Dwarf.Tpo -c -o libllvmsupport_la-Dwarf.lo `test -f 'llvm/lib/Support/Dwarf.cpp' || echo '$(srcdir)/'`llvm/lib/Support/Dwarf.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmsupport_la-Dwarf.Tpo $(DEPDIR)/libllvmsupport_la-Dwarf.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Support/Dwarf.cpp' object='libllvmsupport_la-Dwarf.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsupport_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsupport_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmsupport_la-Dwarf.lo `test -f 'llvm/lib/Support/Dwarf.cpp' || echo '$(srcdir)/'`llvm/lib/Support/Dwarf.cpp + +libllvmsupport_la-ErrorHandling.lo: llvm/lib/Support/ErrorHandling.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsupport_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsupport_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmsupport_la-ErrorHandling.lo -MD -MP -MF $(DEPDIR)/libllvmsupport_la-ErrorHandling.Tpo -c -o libllvmsupport_la-ErrorHandling.lo `test -f 'llvm/lib/Support/ErrorHandling.cpp' || echo '$(srcdir)/'`llvm/lib/Support/ErrorHandling.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmsupport_la-ErrorHandling.Tpo $(DEPDIR)/libllvmsupport_la-ErrorHandling.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Support/ErrorHandling.cpp' object='libllvmsupport_la-ErrorHandling.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsupport_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsupport_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmsupport_la-ErrorHandling.lo `test -f 'llvm/lib/Support/ErrorHandling.cpp' || echo '$(srcdir)/'`llvm/lib/Support/ErrorHandling.cpp + +libllvmsupport_la-FileUtilities.lo: llvm/lib/Support/FileUtilities.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsupport_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsupport_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmsupport_la-FileUtilities.lo -MD -MP -MF $(DEPDIR)/libllvmsupport_la-FileUtilities.Tpo -c -o libllvmsupport_la-FileUtilities.lo `test -f 'llvm/lib/Support/FileUtilities.cpp' || echo '$(srcdir)/'`llvm/lib/Support/FileUtilities.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmsupport_la-FileUtilities.Tpo $(DEPDIR)/libllvmsupport_la-FileUtilities.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Support/FileUtilities.cpp' object='libllvmsupport_la-FileUtilities.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsupport_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsupport_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmsupport_la-FileUtilities.lo `test -f 'llvm/lib/Support/FileUtilities.cpp' || echo '$(srcdir)/'`llvm/lib/Support/FileUtilities.cpp + +libllvmsupport_la-FoldingSet.lo: llvm/lib/Support/FoldingSet.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsupport_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsupport_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmsupport_la-FoldingSet.lo -MD -MP -MF $(DEPDIR)/libllvmsupport_la-FoldingSet.Tpo -c -o libllvmsupport_la-FoldingSet.lo `test -f 'llvm/lib/Support/FoldingSet.cpp' || echo '$(srcdir)/'`llvm/lib/Support/FoldingSet.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmsupport_la-FoldingSet.Tpo $(DEPDIR)/libllvmsupport_la-FoldingSet.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Support/FoldingSet.cpp' object='libllvmsupport_la-FoldingSet.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsupport_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsupport_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmsupport_la-FoldingSet.lo `test -f 'llvm/lib/Support/FoldingSet.cpp' || echo '$(srcdir)/'`llvm/lib/Support/FoldingSet.cpp + +libllvmsupport_la-FormattedStream.lo: llvm/lib/Support/FormattedStream.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsupport_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsupport_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmsupport_la-FormattedStream.lo -MD -MP -MF $(DEPDIR)/libllvmsupport_la-FormattedStream.Tpo -c -o libllvmsupport_la-FormattedStream.lo `test -f 'llvm/lib/Support/FormattedStream.cpp' || echo '$(srcdir)/'`llvm/lib/Support/FormattedStream.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmsupport_la-FormattedStream.Tpo $(DEPDIR)/libllvmsupport_la-FormattedStream.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Support/FormattedStream.cpp' object='libllvmsupport_la-FormattedStream.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsupport_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsupport_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmsupport_la-FormattedStream.lo `test -f 'llvm/lib/Support/FormattedStream.cpp' || echo '$(srcdir)/'`llvm/lib/Support/FormattedStream.cpp + +libllvmsupport_la-GraphWriter.lo: llvm/lib/Support/GraphWriter.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsupport_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsupport_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmsupport_la-GraphWriter.lo -MD -MP -MF $(DEPDIR)/libllvmsupport_la-GraphWriter.Tpo -c -o libllvmsupport_la-GraphWriter.lo `test -f 'llvm/lib/Support/GraphWriter.cpp' || echo '$(srcdir)/'`llvm/lib/Support/GraphWriter.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmsupport_la-GraphWriter.Tpo $(DEPDIR)/libllvmsupport_la-GraphWriter.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Support/GraphWriter.cpp' object='libllvmsupport_la-GraphWriter.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsupport_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsupport_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmsupport_la-GraphWriter.lo `test -f 'llvm/lib/Support/GraphWriter.cpp' || echo '$(srcdir)/'`llvm/lib/Support/GraphWriter.cpp + +libllvmsupport_la-IsInf.lo: llvm/lib/Support/IsInf.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsupport_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsupport_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmsupport_la-IsInf.lo -MD -MP -MF $(DEPDIR)/libllvmsupport_la-IsInf.Tpo -c -o libllvmsupport_la-IsInf.lo `test -f 'llvm/lib/Support/IsInf.cpp' || echo '$(srcdir)/'`llvm/lib/Support/IsInf.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmsupport_la-IsInf.Tpo $(DEPDIR)/libllvmsupport_la-IsInf.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Support/IsInf.cpp' object='libllvmsupport_la-IsInf.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsupport_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsupport_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmsupport_la-IsInf.lo `test -f 'llvm/lib/Support/IsInf.cpp' || echo '$(srcdir)/'`llvm/lib/Support/IsInf.cpp + +libllvmsupport_la-IsNAN.lo: llvm/lib/Support/IsNAN.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsupport_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsupport_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmsupport_la-IsNAN.lo -MD -MP -MF $(DEPDIR)/libllvmsupport_la-IsNAN.Tpo -c -o libllvmsupport_la-IsNAN.lo `test -f 'llvm/lib/Support/IsNAN.cpp' || echo '$(srcdir)/'`llvm/lib/Support/IsNAN.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmsupport_la-IsNAN.Tpo $(DEPDIR)/libllvmsupport_la-IsNAN.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Support/IsNAN.cpp' object='libllvmsupport_la-IsNAN.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsupport_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsupport_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmsupport_la-IsNAN.lo `test -f 'llvm/lib/Support/IsNAN.cpp' || echo '$(srcdir)/'`llvm/lib/Support/IsNAN.cpp + +libllvmsupport_la-ManagedStatic.lo: llvm/lib/Support/ManagedStatic.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsupport_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsupport_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmsupport_la-ManagedStatic.lo -MD -MP -MF $(DEPDIR)/libllvmsupport_la-ManagedStatic.Tpo -c -o libllvmsupport_la-ManagedStatic.lo `test -f 'llvm/lib/Support/ManagedStatic.cpp' || echo '$(srcdir)/'`llvm/lib/Support/ManagedStatic.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmsupport_la-ManagedStatic.Tpo $(DEPDIR)/libllvmsupport_la-ManagedStatic.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Support/ManagedStatic.cpp' object='libllvmsupport_la-ManagedStatic.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsupport_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsupport_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmsupport_la-ManagedStatic.lo `test -f 'llvm/lib/Support/ManagedStatic.cpp' || echo '$(srcdir)/'`llvm/lib/Support/ManagedStatic.cpp + +libllvmsupport_la-MemoryBuffer.lo: llvm/lib/Support/MemoryBuffer.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsupport_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsupport_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmsupport_la-MemoryBuffer.lo -MD -MP -MF $(DEPDIR)/libllvmsupport_la-MemoryBuffer.Tpo -c -o libllvmsupport_la-MemoryBuffer.lo `test -f 'llvm/lib/Support/MemoryBuffer.cpp' || echo '$(srcdir)/'`llvm/lib/Support/MemoryBuffer.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmsupport_la-MemoryBuffer.Tpo $(DEPDIR)/libllvmsupport_la-MemoryBuffer.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Support/MemoryBuffer.cpp' object='libllvmsupport_la-MemoryBuffer.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsupport_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsupport_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmsupport_la-MemoryBuffer.lo `test -f 'llvm/lib/Support/MemoryBuffer.cpp' || echo '$(srcdir)/'`llvm/lib/Support/MemoryBuffer.cpp + +libllvmsupport_la-PluginLoader.lo: llvm/lib/Support/PluginLoader.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsupport_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsupport_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmsupport_la-PluginLoader.lo -MD -MP -MF $(DEPDIR)/libllvmsupport_la-PluginLoader.Tpo -c -o libllvmsupport_la-PluginLoader.lo `test -f 'llvm/lib/Support/PluginLoader.cpp' || echo '$(srcdir)/'`llvm/lib/Support/PluginLoader.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmsupport_la-PluginLoader.Tpo $(DEPDIR)/libllvmsupport_la-PluginLoader.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Support/PluginLoader.cpp' object='libllvmsupport_la-PluginLoader.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsupport_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsupport_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmsupport_la-PluginLoader.lo `test -f 'llvm/lib/Support/PluginLoader.cpp' || echo '$(srcdir)/'`llvm/lib/Support/PluginLoader.cpp + +libllvmsupport_la-PrettyStackTrace.lo: llvm/lib/Support/PrettyStackTrace.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsupport_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsupport_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmsupport_la-PrettyStackTrace.lo -MD -MP -MF $(DEPDIR)/libllvmsupport_la-PrettyStackTrace.Tpo -c -o libllvmsupport_la-PrettyStackTrace.lo `test -f 'llvm/lib/Support/PrettyStackTrace.cpp' || echo '$(srcdir)/'`llvm/lib/Support/PrettyStackTrace.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmsupport_la-PrettyStackTrace.Tpo $(DEPDIR)/libllvmsupport_la-PrettyStackTrace.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Support/PrettyStackTrace.cpp' object='libllvmsupport_la-PrettyStackTrace.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsupport_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsupport_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmsupport_la-PrettyStackTrace.lo `test -f 'llvm/lib/Support/PrettyStackTrace.cpp' || echo '$(srcdir)/'`llvm/lib/Support/PrettyStackTrace.cpp + +libllvmsupport_la-SlowOperationInformer.lo: llvm/lib/Support/SlowOperationInformer.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsupport_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsupport_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmsupport_la-SlowOperationInformer.lo -MD -MP -MF $(DEPDIR)/libllvmsupport_la-SlowOperationInformer.Tpo -c -o libllvmsupport_la-SlowOperationInformer.lo `test -f 'llvm/lib/Support/SlowOperationInformer.cpp' || echo '$(srcdir)/'`llvm/lib/Support/SlowOperationInformer.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmsupport_la-SlowOperationInformer.Tpo $(DEPDIR)/libllvmsupport_la-SlowOperationInformer.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Support/SlowOperationInformer.cpp' object='libllvmsupport_la-SlowOperationInformer.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsupport_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsupport_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmsupport_la-SlowOperationInformer.lo `test -f 'llvm/lib/Support/SlowOperationInformer.cpp' || echo '$(srcdir)/'`llvm/lib/Support/SlowOperationInformer.cpp + +libllvmsupport_la-SmallPtrSet.lo: llvm/lib/Support/SmallPtrSet.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsupport_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsupport_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmsupport_la-SmallPtrSet.lo -MD -MP -MF $(DEPDIR)/libllvmsupport_la-SmallPtrSet.Tpo -c -o libllvmsupport_la-SmallPtrSet.lo `test -f 'llvm/lib/Support/SmallPtrSet.cpp' || echo '$(srcdir)/'`llvm/lib/Support/SmallPtrSet.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmsupport_la-SmallPtrSet.Tpo $(DEPDIR)/libllvmsupport_la-SmallPtrSet.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Support/SmallPtrSet.cpp' object='libllvmsupport_la-SmallPtrSet.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsupport_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsupport_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmsupport_la-SmallPtrSet.lo `test -f 'llvm/lib/Support/SmallPtrSet.cpp' || echo '$(srcdir)/'`llvm/lib/Support/SmallPtrSet.cpp + +libllvmsupport_la-SourceMgr.lo: llvm/lib/Support/SourceMgr.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsupport_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsupport_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmsupport_la-SourceMgr.lo -MD -MP -MF $(DEPDIR)/libllvmsupport_la-SourceMgr.Tpo -c -o libllvmsupport_la-SourceMgr.lo `test -f 'llvm/lib/Support/SourceMgr.cpp' || echo '$(srcdir)/'`llvm/lib/Support/SourceMgr.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmsupport_la-SourceMgr.Tpo $(DEPDIR)/libllvmsupport_la-SourceMgr.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Support/SourceMgr.cpp' object='libllvmsupport_la-SourceMgr.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsupport_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsupport_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmsupport_la-SourceMgr.lo `test -f 'llvm/lib/Support/SourceMgr.cpp' || echo '$(srcdir)/'`llvm/lib/Support/SourceMgr.cpp + +libllvmsupport_la-Statistic.lo: llvm/lib/Support/Statistic.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsupport_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsupport_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmsupport_la-Statistic.lo -MD -MP -MF $(DEPDIR)/libllvmsupport_la-Statistic.Tpo -c -o libllvmsupport_la-Statistic.lo `test -f 'llvm/lib/Support/Statistic.cpp' || echo '$(srcdir)/'`llvm/lib/Support/Statistic.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmsupport_la-Statistic.Tpo $(DEPDIR)/libllvmsupport_la-Statistic.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Support/Statistic.cpp' object='libllvmsupport_la-Statistic.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsupport_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsupport_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmsupport_la-Statistic.lo `test -f 'llvm/lib/Support/Statistic.cpp' || echo '$(srcdir)/'`llvm/lib/Support/Statistic.cpp + +libllvmsupport_la-StringExtras.lo: llvm/lib/Support/StringExtras.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsupport_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsupport_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmsupport_la-StringExtras.lo -MD -MP -MF $(DEPDIR)/libllvmsupport_la-StringExtras.Tpo -c -o libllvmsupport_la-StringExtras.lo `test -f 'llvm/lib/Support/StringExtras.cpp' || echo '$(srcdir)/'`llvm/lib/Support/StringExtras.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmsupport_la-StringExtras.Tpo $(DEPDIR)/libllvmsupport_la-StringExtras.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Support/StringExtras.cpp' object='libllvmsupport_la-StringExtras.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsupport_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsupport_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmsupport_la-StringExtras.lo `test -f 'llvm/lib/Support/StringExtras.cpp' || echo '$(srcdir)/'`llvm/lib/Support/StringExtras.cpp + +libllvmsupport_la-StringMap.lo: llvm/lib/Support/StringMap.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsupport_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsupport_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmsupport_la-StringMap.lo -MD -MP -MF $(DEPDIR)/libllvmsupport_la-StringMap.Tpo -c -o libllvmsupport_la-StringMap.lo `test -f 'llvm/lib/Support/StringMap.cpp' || echo '$(srcdir)/'`llvm/lib/Support/StringMap.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmsupport_la-StringMap.Tpo $(DEPDIR)/libllvmsupport_la-StringMap.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Support/StringMap.cpp' object='libllvmsupport_la-StringMap.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsupport_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsupport_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmsupport_la-StringMap.lo `test -f 'llvm/lib/Support/StringMap.cpp' || echo '$(srcdir)/'`llvm/lib/Support/StringMap.cpp + +libllvmsupport_la-StringPool.lo: llvm/lib/Support/StringPool.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsupport_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsupport_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmsupport_la-StringPool.lo -MD -MP -MF $(DEPDIR)/libllvmsupport_la-StringPool.Tpo -c -o libllvmsupport_la-StringPool.lo `test -f 'llvm/lib/Support/StringPool.cpp' || echo '$(srcdir)/'`llvm/lib/Support/StringPool.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmsupport_la-StringPool.Tpo $(DEPDIR)/libllvmsupport_la-StringPool.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Support/StringPool.cpp' object='libllvmsupport_la-StringPool.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsupport_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsupport_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmsupport_la-StringPool.lo `test -f 'llvm/lib/Support/StringPool.cpp' || echo '$(srcdir)/'`llvm/lib/Support/StringPool.cpp + +libllvmsupport_la-StringRef.lo: llvm/lib/Support/StringRef.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsupport_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsupport_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmsupport_la-StringRef.lo -MD -MP -MF $(DEPDIR)/libllvmsupport_la-StringRef.Tpo -c -o libllvmsupport_la-StringRef.lo `test -f 'llvm/lib/Support/StringRef.cpp' || echo '$(srcdir)/'`llvm/lib/Support/StringRef.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmsupport_la-StringRef.Tpo $(DEPDIR)/libllvmsupport_la-StringRef.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Support/StringRef.cpp' object='libllvmsupport_la-StringRef.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsupport_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsupport_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmsupport_la-StringRef.lo `test -f 'llvm/lib/Support/StringRef.cpp' || echo '$(srcdir)/'`llvm/lib/Support/StringRef.cpp + +libllvmsupport_la-SystemUtils.lo: llvm/lib/Support/SystemUtils.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsupport_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsupport_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmsupport_la-SystemUtils.lo -MD -MP -MF $(DEPDIR)/libllvmsupport_la-SystemUtils.Tpo -c -o libllvmsupport_la-SystemUtils.lo `test -f 'llvm/lib/Support/SystemUtils.cpp' || echo '$(srcdir)/'`llvm/lib/Support/SystemUtils.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmsupport_la-SystemUtils.Tpo $(DEPDIR)/libllvmsupport_la-SystemUtils.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Support/SystemUtils.cpp' object='libllvmsupport_la-SystemUtils.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsupport_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsupport_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmsupport_la-SystemUtils.lo `test -f 'llvm/lib/Support/SystemUtils.cpp' || echo '$(srcdir)/'`llvm/lib/Support/SystemUtils.cpp + +libllvmsupport_la-TargetRegistry.lo: llvm/lib/Support/TargetRegistry.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsupport_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsupport_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmsupport_la-TargetRegistry.lo -MD -MP -MF $(DEPDIR)/libllvmsupport_la-TargetRegistry.Tpo -c -o libllvmsupport_la-TargetRegistry.lo `test -f 'llvm/lib/Support/TargetRegistry.cpp' || echo '$(srcdir)/'`llvm/lib/Support/TargetRegistry.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmsupport_la-TargetRegistry.Tpo $(DEPDIR)/libllvmsupport_la-TargetRegistry.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Support/TargetRegistry.cpp' object='libllvmsupport_la-TargetRegistry.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsupport_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsupport_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmsupport_la-TargetRegistry.lo `test -f 'llvm/lib/Support/TargetRegistry.cpp' || echo '$(srcdir)/'`llvm/lib/Support/TargetRegistry.cpp + +libllvmsupport_la-Timer.lo: llvm/lib/Support/Timer.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsupport_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsupport_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmsupport_la-Timer.lo -MD -MP -MF $(DEPDIR)/libllvmsupport_la-Timer.Tpo -c -o libllvmsupport_la-Timer.lo `test -f 'llvm/lib/Support/Timer.cpp' || echo '$(srcdir)/'`llvm/lib/Support/Timer.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmsupport_la-Timer.Tpo $(DEPDIR)/libllvmsupport_la-Timer.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Support/Timer.cpp' object='libllvmsupport_la-Timer.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsupport_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsupport_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmsupport_la-Timer.lo `test -f 'llvm/lib/Support/Timer.cpp' || echo '$(srcdir)/'`llvm/lib/Support/Timer.cpp + +libllvmsupport_la-Triple.lo: llvm/lib/Support/Triple.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsupport_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsupport_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmsupport_la-Triple.lo -MD -MP -MF $(DEPDIR)/libllvmsupport_la-Triple.Tpo -c -o libllvmsupport_la-Triple.lo `test -f 'llvm/lib/Support/Triple.cpp' || echo '$(srcdir)/'`llvm/lib/Support/Triple.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmsupport_la-Triple.Tpo $(DEPDIR)/libllvmsupport_la-Triple.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Support/Triple.cpp' object='libllvmsupport_la-Triple.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsupport_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsupport_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmsupport_la-Triple.lo `test -f 'llvm/lib/Support/Triple.cpp' || echo '$(srcdir)/'`llvm/lib/Support/Triple.cpp + +libllvmsupport_la-Twine.lo: llvm/lib/Support/Twine.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsupport_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsupport_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmsupport_la-Twine.lo -MD -MP -MF $(DEPDIR)/libllvmsupport_la-Twine.Tpo -c -o libllvmsupport_la-Twine.lo `test -f 'llvm/lib/Support/Twine.cpp' || echo '$(srcdir)/'`llvm/lib/Support/Twine.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmsupport_la-Twine.Tpo $(DEPDIR)/libllvmsupport_la-Twine.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Support/Twine.cpp' object='libllvmsupport_la-Twine.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsupport_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsupport_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmsupport_la-Twine.lo `test -f 'llvm/lib/Support/Twine.cpp' || echo '$(srcdir)/'`llvm/lib/Support/Twine.cpp + +libllvmsupport_la-raw_os_ostream.lo: llvm/lib/Support/raw_os_ostream.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsupport_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsupport_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmsupport_la-raw_os_ostream.lo -MD -MP -MF $(DEPDIR)/libllvmsupport_la-raw_os_ostream.Tpo -c -o libllvmsupport_la-raw_os_ostream.lo `test -f 'llvm/lib/Support/raw_os_ostream.cpp' || echo '$(srcdir)/'`llvm/lib/Support/raw_os_ostream.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmsupport_la-raw_os_ostream.Tpo $(DEPDIR)/libllvmsupport_la-raw_os_ostream.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Support/raw_os_ostream.cpp' object='libllvmsupport_la-raw_os_ostream.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsupport_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsupport_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmsupport_la-raw_os_ostream.lo `test -f 'llvm/lib/Support/raw_os_ostream.cpp' || echo '$(srcdir)/'`llvm/lib/Support/raw_os_ostream.cpp + +libllvmsupport_la-raw_ostream.lo: llvm/lib/Support/raw_ostream.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsupport_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsupport_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmsupport_la-raw_ostream.lo -MD -MP -MF $(DEPDIR)/libllvmsupport_la-raw_ostream.Tpo -c -o libllvmsupport_la-raw_ostream.lo `test -f 'llvm/lib/Support/raw_ostream.cpp' || echo '$(srcdir)/'`llvm/lib/Support/raw_ostream.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmsupport_la-raw_ostream.Tpo $(DEPDIR)/libllvmsupport_la-raw_ostream.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Support/raw_ostream.cpp' object='libllvmsupport_la-raw_ostream.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsupport_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsupport_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmsupport_la-raw_ostream.lo `test -f 'llvm/lib/Support/raw_ostream.cpp' || echo '$(srcdir)/'`llvm/lib/Support/raw_ostream.cpp + +libllvmsupport_la-Regex.lo: llvm/lib/Support/Regex.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsupport_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsupport_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmsupport_la-Regex.lo -MD -MP -MF $(DEPDIR)/libllvmsupport_la-Regex.Tpo -c -o libllvmsupport_la-Regex.lo `test -f 'llvm/lib/Support/Regex.cpp' || echo '$(srcdir)/'`llvm/lib/Support/Regex.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmsupport_la-Regex.Tpo $(DEPDIR)/libllvmsupport_la-Regex.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Support/Regex.cpp' object='libllvmsupport_la-Regex.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsupport_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsupport_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmsupport_la-Regex.lo `test -f 'llvm/lib/Support/Regex.cpp' || echo '$(srcdir)/'`llvm/lib/Support/Regex.cpp + +libllvmsystem_la-Alarm.lo: llvm/lib/System/Alarm.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsystem_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsystem_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmsystem_la-Alarm.lo -MD -MP -MF $(DEPDIR)/libllvmsystem_la-Alarm.Tpo -c -o libllvmsystem_la-Alarm.lo `test -f 'llvm/lib/System/Alarm.cpp' || echo '$(srcdir)/'`llvm/lib/System/Alarm.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmsystem_la-Alarm.Tpo $(DEPDIR)/libllvmsystem_la-Alarm.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/System/Alarm.cpp' object='libllvmsystem_la-Alarm.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsystem_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsystem_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmsystem_la-Alarm.lo `test -f 'llvm/lib/System/Alarm.cpp' || echo '$(srcdir)/'`llvm/lib/System/Alarm.cpp + +libllvmsystem_la-Atomic.lo: llvm/lib/System/Atomic.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsystem_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsystem_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmsystem_la-Atomic.lo -MD -MP -MF $(DEPDIR)/libllvmsystem_la-Atomic.Tpo -c -o libllvmsystem_la-Atomic.lo `test -f 'llvm/lib/System/Atomic.cpp' || echo '$(srcdir)/'`llvm/lib/System/Atomic.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmsystem_la-Atomic.Tpo $(DEPDIR)/libllvmsystem_la-Atomic.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/System/Atomic.cpp' object='libllvmsystem_la-Atomic.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsystem_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsystem_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmsystem_la-Atomic.lo `test -f 'llvm/lib/System/Atomic.cpp' || echo '$(srcdir)/'`llvm/lib/System/Atomic.cpp + +libllvmsystem_la-Disassembler.lo: llvm/lib/System/Disassembler.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsystem_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsystem_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmsystem_la-Disassembler.lo -MD -MP -MF $(DEPDIR)/libllvmsystem_la-Disassembler.Tpo -c -o libllvmsystem_la-Disassembler.lo `test -f 'llvm/lib/System/Disassembler.cpp' || echo '$(srcdir)/'`llvm/lib/System/Disassembler.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmsystem_la-Disassembler.Tpo $(DEPDIR)/libllvmsystem_la-Disassembler.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/System/Disassembler.cpp' object='libllvmsystem_la-Disassembler.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsystem_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsystem_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmsystem_la-Disassembler.lo `test -f 'llvm/lib/System/Disassembler.cpp' || echo '$(srcdir)/'`llvm/lib/System/Disassembler.cpp + +libllvmsystem_la-DynamicLibrary.lo: llvm/lib/System/DynamicLibrary.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsystem_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsystem_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmsystem_la-DynamicLibrary.lo -MD -MP -MF $(DEPDIR)/libllvmsystem_la-DynamicLibrary.Tpo -c -o libllvmsystem_la-DynamicLibrary.lo `test -f 'llvm/lib/System/DynamicLibrary.cpp' || echo '$(srcdir)/'`llvm/lib/System/DynamicLibrary.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmsystem_la-DynamicLibrary.Tpo $(DEPDIR)/libllvmsystem_la-DynamicLibrary.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/System/DynamicLibrary.cpp' object='libllvmsystem_la-DynamicLibrary.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsystem_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsystem_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmsystem_la-DynamicLibrary.lo `test -f 'llvm/lib/System/DynamicLibrary.cpp' || echo '$(srcdir)/'`llvm/lib/System/DynamicLibrary.cpp + +libllvmsystem_la-Errno.lo: llvm/lib/System/Errno.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsystem_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsystem_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmsystem_la-Errno.lo -MD -MP -MF $(DEPDIR)/libllvmsystem_la-Errno.Tpo -c -o libllvmsystem_la-Errno.lo `test -f 'llvm/lib/System/Errno.cpp' || echo '$(srcdir)/'`llvm/lib/System/Errno.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmsystem_la-Errno.Tpo $(DEPDIR)/libllvmsystem_la-Errno.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/System/Errno.cpp' object='libllvmsystem_la-Errno.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsystem_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsystem_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmsystem_la-Errno.lo `test -f 'llvm/lib/System/Errno.cpp' || echo '$(srcdir)/'`llvm/lib/System/Errno.cpp + +libllvmsystem_la-Host.lo: llvm/lib/System/Host.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsystem_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsystem_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmsystem_la-Host.lo -MD -MP -MF $(DEPDIR)/libllvmsystem_la-Host.Tpo -c -o libllvmsystem_la-Host.lo `test -f 'llvm/lib/System/Host.cpp' || echo '$(srcdir)/'`llvm/lib/System/Host.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmsystem_la-Host.Tpo $(DEPDIR)/libllvmsystem_la-Host.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/System/Host.cpp' object='libllvmsystem_la-Host.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsystem_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsystem_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmsystem_la-Host.lo `test -f 'llvm/lib/System/Host.cpp' || echo '$(srcdir)/'`llvm/lib/System/Host.cpp + +libllvmsystem_la-IncludeFile.lo: llvm/lib/System/IncludeFile.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsystem_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsystem_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmsystem_la-IncludeFile.lo -MD -MP -MF $(DEPDIR)/libllvmsystem_la-IncludeFile.Tpo -c -o libllvmsystem_la-IncludeFile.lo `test -f 'llvm/lib/System/IncludeFile.cpp' || echo '$(srcdir)/'`llvm/lib/System/IncludeFile.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmsystem_la-IncludeFile.Tpo $(DEPDIR)/libllvmsystem_la-IncludeFile.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/System/IncludeFile.cpp' object='libllvmsystem_la-IncludeFile.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsystem_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsystem_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmsystem_la-IncludeFile.lo `test -f 'llvm/lib/System/IncludeFile.cpp' || echo '$(srcdir)/'`llvm/lib/System/IncludeFile.cpp + +libllvmsystem_la-Memory.lo: llvm/lib/System/Memory.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsystem_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsystem_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmsystem_la-Memory.lo -MD -MP -MF $(DEPDIR)/libllvmsystem_la-Memory.Tpo -c -o libllvmsystem_la-Memory.lo `test -f 'llvm/lib/System/Memory.cpp' || echo '$(srcdir)/'`llvm/lib/System/Memory.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmsystem_la-Memory.Tpo $(DEPDIR)/libllvmsystem_la-Memory.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/System/Memory.cpp' object='libllvmsystem_la-Memory.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsystem_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsystem_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmsystem_la-Memory.lo `test -f 'llvm/lib/System/Memory.cpp' || echo '$(srcdir)/'`llvm/lib/System/Memory.cpp + +libllvmsystem_la-Mutex.lo: llvm/lib/System/Mutex.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsystem_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsystem_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmsystem_la-Mutex.lo -MD -MP -MF $(DEPDIR)/libllvmsystem_la-Mutex.Tpo -c -o libllvmsystem_la-Mutex.lo `test -f 'llvm/lib/System/Mutex.cpp' || echo '$(srcdir)/'`llvm/lib/System/Mutex.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmsystem_la-Mutex.Tpo $(DEPDIR)/libllvmsystem_la-Mutex.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/System/Mutex.cpp' object='libllvmsystem_la-Mutex.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsystem_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsystem_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmsystem_la-Mutex.lo `test -f 'llvm/lib/System/Mutex.cpp' || echo '$(srcdir)/'`llvm/lib/System/Mutex.cpp + +libllvmsystem_la-Path.lo: llvm/lib/System/Path.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsystem_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsystem_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmsystem_la-Path.lo -MD -MP -MF $(DEPDIR)/libllvmsystem_la-Path.Tpo -c -o libllvmsystem_la-Path.lo `test -f 'llvm/lib/System/Path.cpp' || echo '$(srcdir)/'`llvm/lib/System/Path.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmsystem_la-Path.Tpo $(DEPDIR)/libllvmsystem_la-Path.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/System/Path.cpp' object='libllvmsystem_la-Path.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsystem_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsystem_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmsystem_la-Path.lo `test -f 'llvm/lib/System/Path.cpp' || echo '$(srcdir)/'`llvm/lib/System/Path.cpp + +libllvmsystem_la-Process.lo: llvm/lib/System/Process.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsystem_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsystem_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmsystem_la-Process.lo -MD -MP -MF $(DEPDIR)/libllvmsystem_la-Process.Tpo -c -o libllvmsystem_la-Process.lo `test -f 'llvm/lib/System/Process.cpp' || echo '$(srcdir)/'`llvm/lib/System/Process.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmsystem_la-Process.Tpo $(DEPDIR)/libllvmsystem_la-Process.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/System/Process.cpp' object='libllvmsystem_la-Process.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsystem_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsystem_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmsystem_la-Process.lo `test -f 'llvm/lib/System/Process.cpp' || echo '$(srcdir)/'`llvm/lib/System/Process.cpp + +libllvmsystem_la-Program.lo: llvm/lib/System/Program.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsystem_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsystem_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmsystem_la-Program.lo -MD -MP -MF $(DEPDIR)/libllvmsystem_la-Program.Tpo -c -o libllvmsystem_la-Program.lo `test -f 'llvm/lib/System/Program.cpp' || echo '$(srcdir)/'`llvm/lib/System/Program.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmsystem_la-Program.Tpo $(DEPDIR)/libllvmsystem_la-Program.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/System/Program.cpp' object='libllvmsystem_la-Program.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsystem_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsystem_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmsystem_la-Program.lo `test -f 'llvm/lib/System/Program.cpp' || echo '$(srcdir)/'`llvm/lib/System/Program.cpp + +libllvmsystem_la-RWMutex.lo: llvm/lib/System/RWMutex.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsystem_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsystem_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmsystem_la-RWMutex.lo -MD -MP -MF $(DEPDIR)/libllvmsystem_la-RWMutex.Tpo -c -o libllvmsystem_la-RWMutex.lo `test -f 'llvm/lib/System/RWMutex.cpp' || echo '$(srcdir)/'`llvm/lib/System/RWMutex.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmsystem_la-RWMutex.Tpo $(DEPDIR)/libllvmsystem_la-RWMutex.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/System/RWMutex.cpp' object='libllvmsystem_la-RWMutex.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsystem_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsystem_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmsystem_la-RWMutex.lo `test -f 'llvm/lib/System/RWMutex.cpp' || echo '$(srcdir)/'`llvm/lib/System/RWMutex.cpp + +libllvmsystem_la-Signals.lo: llvm/lib/System/Signals.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsystem_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsystem_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmsystem_la-Signals.lo -MD -MP -MF $(DEPDIR)/libllvmsystem_la-Signals.Tpo -c -o libllvmsystem_la-Signals.lo `test -f 'llvm/lib/System/Signals.cpp' || echo '$(srcdir)/'`llvm/lib/System/Signals.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmsystem_la-Signals.Tpo $(DEPDIR)/libllvmsystem_la-Signals.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/System/Signals.cpp' object='libllvmsystem_la-Signals.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsystem_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsystem_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmsystem_la-Signals.lo `test -f 'llvm/lib/System/Signals.cpp' || echo '$(srcdir)/'`llvm/lib/System/Signals.cpp + +libllvmsystem_la-ThreadLocal.lo: llvm/lib/System/ThreadLocal.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsystem_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsystem_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmsystem_la-ThreadLocal.lo -MD -MP -MF $(DEPDIR)/libllvmsystem_la-ThreadLocal.Tpo -c -o libllvmsystem_la-ThreadLocal.lo `test -f 'llvm/lib/System/ThreadLocal.cpp' || echo '$(srcdir)/'`llvm/lib/System/ThreadLocal.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmsystem_la-ThreadLocal.Tpo $(DEPDIR)/libllvmsystem_la-ThreadLocal.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/System/ThreadLocal.cpp' object='libllvmsystem_la-ThreadLocal.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsystem_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsystem_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmsystem_la-ThreadLocal.lo `test -f 'llvm/lib/System/ThreadLocal.cpp' || echo '$(srcdir)/'`llvm/lib/System/ThreadLocal.cpp + +libllvmsystem_la-Threading.lo: llvm/lib/System/Threading.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsystem_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsystem_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmsystem_la-Threading.lo -MD -MP -MF $(DEPDIR)/libllvmsystem_la-Threading.Tpo -c -o libllvmsystem_la-Threading.lo `test -f 'llvm/lib/System/Threading.cpp' || echo '$(srcdir)/'`llvm/lib/System/Threading.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmsystem_la-Threading.Tpo $(DEPDIR)/libllvmsystem_la-Threading.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/System/Threading.cpp' object='libllvmsystem_la-Threading.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsystem_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsystem_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmsystem_la-Threading.lo `test -f 'llvm/lib/System/Threading.cpp' || echo '$(srcdir)/'`llvm/lib/System/Threading.cpp + +libllvmsystem_la-TimeValue.lo: llvm/lib/System/TimeValue.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsystem_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsystem_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmsystem_la-TimeValue.lo -MD -MP -MF $(DEPDIR)/libllvmsystem_la-TimeValue.Tpo -c -o libllvmsystem_la-TimeValue.lo `test -f 'llvm/lib/System/TimeValue.cpp' || echo '$(srcdir)/'`llvm/lib/System/TimeValue.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmsystem_la-TimeValue.Tpo $(DEPDIR)/libllvmsystem_la-TimeValue.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/System/TimeValue.cpp' object='libllvmsystem_la-TimeValue.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsystem_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsystem_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmsystem_la-TimeValue.lo `test -f 'llvm/lib/System/TimeValue.cpp' || echo '$(srcdir)/'`llvm/lib/System/TimeValue.cpp + +libllvmtarget_la-SubtargetFeature.lo: llvm/lib/Target/SubtargetFeature.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtarget_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtarget_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmtarget_la-SubtargetFeature.lo -MD -MP -MF $(DEPDIR)/libllvmtarget_la-SubtargetFeature.Tpo -c -o libllvmtarget_la-SubtargetFeature.lo `test -f 'llvm/lib/Target/SubtargetFeature.cpp' || echo '$(srcdir)/'`llvm/lib/Target/SubtargetFeature.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmtarget_la-SubtargetFeature.Tpo $(DEPDIR)/libllvmtarget_la-SubtargetFeature.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Target/SubtargetFeature.cpp' object='libllvmtarget_la-SubtargetFeature.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtarget_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtarget_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmtarget_la-SubtargetFeature.lo `test -f 'llvm/lib/Target/SubtargetFeature.cpp' || echo '$(srcdir)/'`llvm/lib/Target/SubtargetFeature.cpp + +libllvmtarget_la-Target.lo: llvm/lib/Target/Target.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtarget_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtarget_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmtarget_la-Target.lo -MD -MP -MF $(DEPDIR)/libllvmtarget_la-Target.Tpo -c -o libllvmtarget_la-Target.lo `test -f 'llvm/lib/Target/Target.cpp' || echo '$(srcdir)/'`llvm/lib/Target/Target.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmtarget_la-Target.Tpo $(DEPDIR)/libllvmtarget_la-Target.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Target/Target.cpp' object='libllvmtarget_la-Target.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtarget_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtarget_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmtarget_la-Target.lo `test -f 'llvm/lib/Target/Target.cpp' || echo '$(srcdir)/'`llvm/lib/Target/Target.cpp + +libllvmtarget_la-TargetData.lo: llvm/lib/Target/TargetData.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtarget_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtarget_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmtarget_la-TargetData.lo -MD -MP -MF $(DEPDIR)/libllvmtarget_la-TargetData.Tpo -c -o libllvmtarget_la-TargetData.lo `test -f 'llvm/lib/Target/TargetData.cpp' || echo '$(srcdir)/'`llvm/lib/Target/TargetData.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmtarget_la-TargetData.Tpo $(DEPDIR)/libllvmtarget_la-TargetData.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Target/TargetData.cpp' object='libllvmtarget_la-TargetData.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtarget_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtarget_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmtarget_la-TargetData.lo `test -f 'llvm/lib/Target/TargetData.cpp' || echo '$(srcdir)/'`llvm/lib/Target/TargetData.cpp + +libllvmtarget_la-TargetELFWriterInfo.lo: llvm/lib/Target/TargetELFWriterInfo.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtarget_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtarget_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmtarget_la-TargetELFWriterInfo.lo -MD -MP -MF $(DEPDIR)/libllvmtarget_la-TargetELFWriterInfo.Tpo -c -o libllvmtarget_la-TargetELFWriterInfo.lo `test -f 'llvm/lib/Target/TargetELFWriterInfo.cpp' || echo '$(srcdir)/'`llvm/lib/Target/TargetELFWriterInfo.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmtarget_la-TargetELFWriterInfo.Tpo $(DEPDIR)/libllvmtarget_la-TargetELFWriterInfo.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Target/TargetELFWriterInfo.cpp' object='libllvmtarget_la-TargetELFWriterInfo.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtarget_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtarget_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmtarget_la-TargetELFWriterInfo.lo `test -f 'llvm/lib/Target/TargetELFWriterInfo.cpp' || echo '$(srcdir)/'`llvm/lib/Target/TargetELFWriterInfo.cpp + +libllvmtarget_la-TargetFrameInfo.lo: llvm/lib/Target/TargetFrameInfo.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtarget_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtarget_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmtarget_la-TargetFrameInfo.lo -MD -MP -MF $(DEPDIR)/libllvmtarget_la-TargetFrameInfo.Tpo -c -o libllvmtarget_la-TargetFrameInfo.lo `test -f 'llvm/lib/Target/TargetFrameInfo.cpp' || echo '$(srcdir)/'`llvm/lib/Target/TargetFrameInfo.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmtarget_la-TargetFrameInfo.Tpo $(DEPDIR)/libllvmtarget_la-TargetFrameInfo.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Target/TargetFrameInfo.cpp' object='libllvmtarget_la-TargetFrameInfo.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtarget_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtarget_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmtarget_la-TargetFrameInfo.lo `test -f 'llvm/lib/Target/TargetFrameInfo.cpp' || echo '$(srcdir)/'`llvm/lib/Target/TargetFrameInfo.cpp + +libllvmtarget_la-TargetInstrInfo.lo: llvm/lib/Target/TargetInstrInfo.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtarget_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtarget_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmtarget_la-TargetInstrInfo.lo -MD -MP -MF $(DEPDIR)/libllvmtarget_la-TargetInstrInfo.Tpo -c -o libllvmtarget_la-TargetInstrInfo.lo `test -f 'llvm/lib/Target/TargetInstrInfo.cpp' || echo '$(srcdir)/'`llvm/lib/Target/TargetInstrInfo.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmtarget_la-TargetInstrInfo.Tpo $(DEPDIR)/libllvmtarget_la-TargetInstrInfo.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Target/TargetInstrInfo.cpp' object='libllvmtarget_la-TargetInstrInfo.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtarget_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtarget_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmtarget_la-TargetInstrInfo.lo `test -f 'llvm/lib/Target/TargetInstrInfo.cpp' || echo '$(srcdir)/'`llvm/lib/Target/TargetInstrInfo.cpp + +libllvmtarget_la-TargetIntrinsicInfo.lo: llvm/lib/Target/TargetIntrinsicInfo.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtarget_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtarget_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmtarget_la-TargetIntrinsicInfo.lo -MD -MP -MF $(DEPDIR)/libllvmtarget_la-TargetIntrinsicInfo.Tpo -c -o libllvmtarget_la-TargetIntrinsicInfo.lo `test -f 'llvm/lib/Target/TargetIntrinsicInfo.cpp' || echo '$(srcdir)/'`llvm/lib/Target/TargetIntrinsicInfo.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmtarget_la-TargetIntrinsicInfo.Tpo $(DEPDIR)/libllvmtarget_la-TargetIntrinsicInfo.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Target/TargetIntrinsicInfo.cpp' object='libllvmtarget_la-TargetIntrinsicInfo.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtarget_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtarget_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmtarget_la-TargetIntrinsicInfo.lo `test -f 'llvm/lib/Target/TargetIntrinsicInfo.cpp' || echo '$(srcdir)/'`llvm/lib/Target/TargetIntrinsicInfo.cpp + +libllvmtarget_la-TargetLoweringObjectFile.lo: llvm/lib/Target/TargetLoweringObjectFile.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtarget_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtarget_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmtarget_la-TargetLoweringObjectFile.lo -MD -MP -MF $(DEPDIR)/libllvmtarget_la-TargetLoweringObjectFile.Tpo -c -o libllvmtarget_la-TargetLoweringObjectFile.lo `test -f 'llvm/lib/Target/TargetLoweringObjectFile.cpp' || echo '$(srcdir)/'`llvm/lib/Target/TargetLoweringObjectFile.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmtarget_la-TargetLoweringObjectFile.Tpo $(DEPDIR)/libllvmtarget_la-TargetLoweringObjectFile.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Target/TargetLoweringObjectFile.cpp' object='libllvmtarget_la-TargetLoweringObjectFile.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtarget_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtarget_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmtarget_la-TargetLoweringObjectFile.lo `test -f 'llvm/lib/Target/TargetLoweringObjectFile.cpp' || echo '$(srcdir)/'`llvm/lib/Target/TargetLoweringObjectFile.cpp + +libllvmtarget_la-TargetMachOWriterInfo.lo: llvm/lib/Target/TargetMachOWriterInfo.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtarget_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtarget_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmtarget_la-TargetMachOWriterInfo.lo -MD -MP -MF $(DEPDIR)/libllvmtarget_la-TargetMachOWriterInfo.Tpo -c -o libllvmtarget_la-TargetMachOWriterInfo.lo `test -f 'llvm/lib/Target/TargetMachOWriterInfo.cpp' || echo '$(srcdir)/'`llvm/lib/Target/TargetMachOWriterInfo.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmtarget_la-TargetMachOWriterInfo.Tpo $(DEPDIR)/libllvmtarget_la-TargetMachOWriterInfo.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Target/TargetMachOWriterInfo.cpp' object='libllvmtarget_la-TargetMachOWriterInfo.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtarget_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtarget_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmtarget_la-TargetMachOWriterInfo.lo `test -f 'llvm/lib/Target/TargetMachOWriterInfo.cpp' || echo '$(srcdir)/'`llvm/lib/Target/TargetMachOWriterInfo.cpp + +libllvmtarget_la-TargetMachine.lo: llvm/lib/Target/TargetMachine.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtarget_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtarget_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmtarget_la-TargetMachine.lo -MD -MP -MF $(DEPDIR)/libllvmtarget_la-TargetMachine.Tpo -c -o libllvmtarget_la-TargetMachine.lo `test -f 'llvm/lib/Target/TargetMachine.cpp' || echo '$(srcdir)/'`llvm/lib/Target/TargetMachine.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmtarget_la-TargetMachine.Tpo $(DEPDIR)/libllvmtarget_la-TargetMachine.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Target/TargetMachine.cpp' object='libllvmtarget_la-TargetMachine.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtarget_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtarget_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmtarget_la-TargetMachine.lo `test -f 'llvm/lib/Target/TargetMachine.cpp' || echo '$(srcdir)/'`llvm/lib/Target/TargetMachine.cpp + +libllvmtarget_la-TargetRegisterInfo.lo: llvm/lib/Target/TargetRegisterInfo.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtarget_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtarget_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmtarget_la-TargetRegisterInfo.lo -MD -MP -MF $(DEPDIR)/libllvmtarget_la-TargetRegisterInfo.Tpo -c -o libllvmtarget_la-TargetRegisterInfo.lo `test -f 'llvm/lib/Target/TargetRegisterInfo.cpp' || echo '$(srcdir)/'`llvm/lib/Target/TargetRegisterInfo.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmtarget_la-TargetRegisterInfo.Tpo $(DEPDIR)/libllvmtarget_la-TargetRegisterInfo.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Target/TargetRegisterInfo.cpp' object='libllvmtarget_la-TargetRegisterInfo.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtarget_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtarget_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmtarget_la-TargetRegisterInfo.lo `test -f 'llvm/lib/Target/TargetRegisterInfo.cpp' || echo '$(srcdir)/'`llvm/lib/Target/TargetRegisterInfo.cpp + +libllvmtarget_la-TargetSubtarget.lo: llvm/lib/Target/TargetSubtarget.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtarget_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtarget_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmtarget_la-TargetSubtarget.lo -MD -MP -MF $(DEPDIR)/libllvmtarget_la-TargetSubtarget.Tpo -c -o libllvmtarget_la-TargetSubtarget.lo `test -f 'llvm/lib/Target/TargetSubtarget.cpp' || echo '$(srcdir)/'`llvm/lib/Target/TargetSubtarget.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmtarget_la-TargetSubtarget.Tpo $(DEPDIR)/libllvmtarget_la-TargetSubtarget.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Target/TargetSubtarget.cpp' object='libllvmtarget_la-TargetSubtarget.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtarget_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtarget_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmtarget_la-TargetSubtarget.lo `test -f 'llvm/lib/Target/TargetSubtarget.cpp' || echo '$(srcdir)/'`llvm/lib/Target/TargetSubtarget.cpp + +libllvmtargetarm_la-ARMBaseInstrInfo.lo: llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtargetarm_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtargetarm_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmtargetarm_la-ARMBaseInstrInfo.lo -MD -MP -MF $(DEPDIR)/libllvmtargetarm_la-ARMBaseInstrInfo.Tpo -c -o libllvmtargetarm_la-ARMBaseInstrInfo.lo `test -f 'llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp' || echo '$(srcdir)/'`llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmtargetarm_la-ARMBaseInstrInfo.Tpo $(DEPDIR)/libllvmtargetarm_la-ARMBaseInstrInfo.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp' object='libllvmtargetarm_la-ARMBaseInstrInfo.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtargetarm_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtargetarm_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmtargetarm_la-ARMBaseInstrInfo.lo `test -f 'llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp' || echo '$(srcdir)/'`llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp + +libllvmtargetarm_la-ARMBaseRegisterInfo.lo: llvm/lib/Target/ARM/ARMBaseRegisterInfo.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtargetarm_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtargetarm_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmtargetarm_la-ARMBaseRegisterInfo.lo -MD -MP -MF $(DEPDIR)/libllvmtargetarm_la-ARMBaseRegisterInfo.Tpo -c -o libllvmtargetarm_la-ARMBaseRegisterInfo.lo `test -f 'llvm/lib/Target/ARM/ARMBaseRegisterInfo.cpp' || echo '$(srcdir)/'`llvm/lib/Target/ARM/ARMBaseRegisterInfo.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmtargetarm_la-ARMBaseRegisterInfo.Tpo $(DEPDIR)/libllvmtargetarm_la-ARMBaseRegisterInfo.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Target/ARM/ARMBaseRegisterInfo.cpp' object='libllvmtargetarm_la-ARMBaseRegisterInfo.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtargetarm_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtargetarm_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmtargetarm_la-ARMBaseRegisterInfo.lo `test -f 'llvm/lib/Target/ARM/ARMBaseRegisterInfo.cpp' || echo '$(srcdir)/'`llvm/lib/Target/ARM/ARMBaseRegisterInfo.cpp + +libllvmtargetarm_la-ARMCodeEmitter.lo: llvm/lib/Target/ARM/ARMCodeEmitter.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtargetarm_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtargetarm_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmtargetarm_la-ARMCodeEmitter.lo -MD -MP -MF $(DEPDIR)/libllvmtargetarm_la-ARMCodeEmitter.Tpo -c -o libllvmtargetarm_la-ARMCodeEmitter.lo `test -f 'llvm/lib/Target/ARM/ARMCodeEmitter.cpp' || echo '$(srcdir)/'`llvm/lib/Target/ARM/ARMCodeEmitter.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmtargetarm_la-ARMCodeEmitter.Tpo $(DEPDIR)/libllvmtargetarm_la-ARMCodeEmitter.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Target/ARM/ARMCodeEmitter.cpp' object='libllvmtargetarm_la-ARMCodeEmitter.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtargetarm_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtargetarm_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmtargetarm_la-ARMCodeEmitter.lo `test -f 'llvm/lib/Target/ARM/ARMCodeEmitter.cpp' || echo '$(srcdir)/'`llvm/lib/Target/ARM/ARMCodeEmitter.cpp + +libllvmtargetarm_la-ARMConstantIslandPass.lo: llvm/lib/Target/ARM/ARMConstantIslandPass.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtargetarm_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtargetarm_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmtargetarm_la-ARMConstantIslandPass.lo -MD -MP -MF $(DEPDIR)/libllvmtargetarm_la-ARMConstantIslandPass.Tpo -c -o libllvmtargetarm_la-ARMConstantIslandPass.lo `test -f 'llvm/lib/Target/ARM/ARMConstantIslandPass.cpp' || echo '$(srcdir)/'`llvm/lib/Target/ARM/ARMConstantIslandPass.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmtargetarm_la-ARMConstantIslandPass.Tpo $(DEPDIR)/libllvmtargetarm_la-ARMConstantIslandPass.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Target/ARM/ARMConstantIslandPass.cpp' object='libllvmtargetarm_la-ARMConstantIslandPass.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtargetarm_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtargetarm_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmtargetarm_la-ARMConstantIslandPass.lo `test -f 'llvm/lib/Target/ARM/ARMConstantIslandPass.cpp' || echo '$(srcdir)/'`llvm/lib/Target/ARM/ARMConstantIslandPass.cpp + +libllvmtargetarm_la-ARMConstantPoolValue.lo: llvm/lib/Target/ARM/ARMConstantPoolValue.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtargetarm_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtargetarm_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmtargetarm_la-ARMConstantPoolValue.lo -MD -MP -MF $(DEPDIR)/libllvmtargetarm_la-ARMConstantPoolValue.Tpo -c -o libllvmtargetarm_la-ARMConstantPoolValue.lo `test -f 'llvm/lib/Target/ARM/ARMConstantPoolValue.cpp' || echo '$(srcdir)/'`llvm/lib/Target/ARM/ARMConstantPoolValue.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmtargetarm_la-ARMConstantPoolValue.Tpo $(DEPDIR)/libllvmtargetarm_la-ARMConstantPoolValue.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Target/ARM/ARMConstantPoolValue.cpp' object='libllvmtargetarm_la-ARMConstantPoolValue.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtargetarm_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtargetarm_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmtargetarm_la-ARMConstantPoolValue.lo `test -f 'llvm/lib/Target/ARM/ARMConstantPoolValue.cpp' || echo '$(srcdir)/'`llvm/lib/Target/ARM/ARMConstantPoolValue.cpp + +libllvmtargetarm_la-ARMExpandPseudoInsts.lo: llvm/lib/Target/ARM/ARMExpandPseudoInsts.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtargetarm_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtargetarm_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmtargetarm_la-ARMExpandPseudoInsts.lo -MD -MP -MF $(DEPDIR)/libllvmtargetarm_la-ARMExpandPseudoInsts.Tpo -c -o libllvmtargetarm_la-ARMExpandPseudoInsts.lo `test -f 'llvm/lib/Target/ARM/ARMExpandPseudoInsts.cpp' || echo '$(srcdir)/'`llvm/lib/Target/ARM/ARMExpandPseudoInsts.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmtargetarm_la-ARMExpandPseudoInsts.Tpo $(DEPDIR)/libllvmtargetarm_la-ARMExpandPseudoInsts.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Target/ARM/ARMExpandPseudoInsts.cpp' object='libllvmtargetarm_la-ARMExpandPseudoInsts.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtargetarm_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtargetarm_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmtargetarm_la-ARMExpandPseudoInsts.lo `test -f 'llvm/lib/Target/ARM/ARMExpandPseudoInsts.cpp' || echo '$(srcdir)/'`llvm/lib/Target/ARM/ARMExpandPseudoInsts.cpp + +libllvmtargetarm_la-ARMInstrInfo.lo: llvm/lib/Target/ARM/ARMInstrInfo.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtargetarm_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtargetarm_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmtargetarm_la-ARMInstrInfo.lo -MD -MP -MF $(DEPDIR)/libllvmtargetarm_la-ARMInstrInfo.Tpo -c -o libllvmtargetarm_la-ARMInstrInfo.lo `test -f 'llvm/lib/Target/ARM/ARMInstrInfo.cpp' || echo '$(srcdir)/'`llvm/lib/Target/ARM/ARMInstrInfo.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmtargetarm_la-ARMInstrInfo.Tpo $(DEPDIR)/libllvmtargetarm_la-ARMInstrInfo.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Target/ARM/ARMInstrInfo.cpp' object='libllvmtargetarm_la-ARMInstrInfo.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtargetarm_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtargetarm_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmtargetarm_la-ARMInstrInfo.lo `test -f 'llvm/lib/Target/ARM/ARMInstrInfo.cpp' || echo '$(srcdir)/'`llvm/lib/Target/ARM/ARMInstrInfo.cpp + +libllvmtargetarm_la-ARMISelDAGToDAG.lo: llvm/lib/Target/ARM/ARMISelDAGToDAG.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtargetarm_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtargetarm_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmtargetarm_la-ARMISelDAGToDAG.lo -MD -MP -MF $(DEPDIR)/libllvmtargetarm_la-ARMISelDAGToDAG.Tpo -c -o libllvmtargetarm_la-ARMISelDAGToDAG.lo `test -f 'llvm/lib/Target/ARM/ARMISelDAGToDAG.cpp' || echo '$(srcdir)/'`llvm/lib/Target/ARM/ARMISelDAGToDAG.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmtargetarm_la-ARMISelDAGToDAG.Tpo $(DEPDIR)/libllvmtargetarm_la-ARMISelDAGToDAG.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Target/ARM/ARMISelDAGToDAG.cpp' object='libllvmtargetarm_la-ARMISelDAGToDAG.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtargetarm_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtargetarm_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmtargetarm_la-ARMISelDAGToDAG.lo `test -f 'llvm/lib/Target/ARM/ARMISelDAGToDAG.cpp' || echo '$(srcdir)/'`llvm/lib/Target/ARM/ARMISelDAGToDAG.cpp + +libllvmtargetarm_la-ARMISelLowering.lo: llvm/lib/Target/ARM/ARMISelLowering.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtargetarm_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtargetarm_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmtargetarm_la-ARMISelLowering.lo -MD -MP -MF $(DEPDIR)/libllvmtargetarm_la-ARMISelLowering.Tpo -c -o libllvmtargetarm_la-ARMISelLowering.lo `test -f 'llvm/lib/Target/ARM/ARMISelLowering.cpp' || echo '$(srcdir)/'`llvm/lib/Target/ARM/ARMISelLowering.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmtargetarm_la-ARMISelLowering.Tpo $(DEPDIR)/libllvmtargetarm_la-ARMISelLowering.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Target/ARM/ARMISelLowering.cpp' object='libllvmtargetarm_la-ARMISelLowering.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtargetarm_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtargetarm_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmtargetarm_la-ARMISelLowering.lo `test -f 'llvm/lib/Target/ARM/ARMISelLowering.cpp' || echo '$(srcdir)/'`llvm/lib/Target/ARM/ARMISelLowering.cpp + +libllvmtargetarm_la-ARMJITInfo.lo: llvm/lib/Target/ARM/ARMJITInfo.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtargetarm_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtargetarm_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmtargetarm_la-ARMJITInfo.lo -MD -MP -MF $(DEPDIR)/libllvmtargetarm_la-ARMJITInfo.Tpo -c -o libllvmtargetarm_la-ARMJITInfo.lo `test -f 'llvm/lib/Target/ARM/ARMJITInfo.cpp' || echo '$(srcdir)/'`llvm/lib/Target/ARM/ARMJITInfo.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmtargetarm_la-ARMJITInfo.Tpo $(DEPDIR)/libllvmtargetarm_la-ARMJITInfo.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Target/ARM/ARMJITInfo.cpp' object='libllvmtargetarm_la-ARMJITInfo.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtargetarm_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtargetarm_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmtargetarm_la-ARMJITInfo.lo `test -f 'llvm/lib/Target/ARM/ARMJITInfo.cpp' || echo '$(srcdir)/'`llvm/lib/Target/ARM/ARMJITInfo.cpp + +libllvmtargetarm_la-ARMLoadStoreOptimizer.lo: llvm/lib/Target/ARM/ARMLoadStoreOptimizer.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtargetarm_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtargetarm_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmtargetarm_la-ARMLoadStoreOptimizer.lo -MD -MP -MF $(DEPDIR)/libllvmtargetarm_la-ARMLoadStoreOptimizer.Tpo -c -o libllvmtargetarm_la-ARMLoadStoreOptimizer.lo `test -f 'llvm/lib/Target/ARM/ARMLoadStoreOptimizer.cpp' || echo '$(srcdir)/'`llvm/lib/Target/ARM/ARMLoadStoreOptimizer.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmtargetarm_la-ARMLoadStoreOptimizer.Tpo $(DEPDIR)/libllvmtargetarm_la-ARMLoadStoreOptimizer.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Target/ARM/ARMLoadStoreOptimizer.cpp' object='libllvmtargetarm_la-ARMLoadStoreOptimizer.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtargetarm_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtargetarm_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmtargetarm_la-ARMLoadStoreOptimizer.lo `test -f 'llvm/lib/Target/ARM/ARMLoadStoreOptimizer.cpp' || echo '$(srcdir)/'`llvm/lib/Target/ARM/ARMLoadStoreOptimizer.cpp + +libllvmtargetarm_la-ARMMCAsmInfo.lo: llvm/lib/Target/ARM/ARMMCAsmInfo.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtargetarm_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtargetarm_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmtargetarm_la-ARMMCAsmInfo.lo -MD -MP -MF $(DEPDIR)/libllvmtargetarm_la-ARMMCAsmInfo.Tpo -c -o libllvmtargetarm_la-ARMMCAsmInfo.lo `test -f 'llvm/lib/Target/ARM/ARMMCAsmInfo.cpp' || echo '$(srcdir)/'`llvm/lib/Target/ARM/ARMMCAsmInfo.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmtargetarm_la-ARMMCAsmInfo.Tpo $(DEPDIR)/libllvmtargetarm_la-ARMMCAsmInfo.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Target/ARM/ARMMCAsmInfo.cpp' object='libllvmtargetarm_la-ARMMCAsmInfo.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtargetarm_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtargetarm_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmtargetarm_la-ARMMCAsmInfo.lo `test -f 'llvm/lib/Target/ARM/ARMMCAsmInfo.cpp' || echo '$(srcdir)/'`llvm/lib/Target/ARM/ARMMCAsmInfo.cpp + +libllvmtargetarm_la-ARMRegisterInfo.lo: llvm/lib/Target/ARM/ARMRegisterInfo.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtargetarm_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtargetarm_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmtargetarm_la-ARMRegisterInfo.lo -MD -MP -MF $(DEPDIR)/libllvmtargetarm_la-ARMRegisterInfo.Tpo -c -o libllvmtargetarm_la-ARMRegisterInfo.lo `test -f 'llvm/lib/Target/ARM/ARMRegisterInfo.cpp' || echo '$(srcdir)/'`llvm/lib/Target/ARM/ARMRegisterInfo.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmtargetarm_la-ARMRegisterInfo.Tpo $(DEPDIR)/libllvmtargetarm_la-ARMRegisterInfo.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Target/ARM/ARMRegisterInfo.cpp' object='libllvmtargetarm_la-ARMRegisterInfo.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtargetarm_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtargetarm_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmtargetarm_la-ARMRegisterInfo.lo `test -f 'llvm/lib/Target/ARM/ARMRegisterInfo.cpp' || echo '$(srcdir)/'`llvm/lib/Target/ARM/ARMRegisterInfo.cpp + +libllvmtargetarm_la-ARMSubtarget.lo: llvm/lib/Target/ARM/ARMSubtarget.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtargetarm_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtargetarm_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmtargetarm_la-ARMSubtarget.lo -MD -MP -MF $(DEPDIR)/libllvmtargetarm_la-ARMSubtarget.Tpo -c -o libllvmtargetarm_la-ARMSubtarget.lo `test -f 'llvm/lib/Target/ARM/ARMSubtarget.cpp' || echo '$(srcdir)/'`llvm/lib/Target/ARM/ARMSubtarget.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmtargetarm_la-ARMSubtarget.Tpo $(DEPDIR)/libllvmtargetarm_la-ARMSubtarget.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Target/ARM/ARMSubtarget.cpp' object='libllvmtargetarm_la-ARMSubtarget.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtargetarm_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtargetarm_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmtargetarm_la-ARMSubtarget.lo `test -f 'llvm/lib/Target/ARM/ARMSubtarget.cpp' || echo '$(srcdir)/'`llvm/lib/Target/ARM/ARMSubtarget.cpp + +libllvmtargetarm_la-ARMTargetMachine.lo: llvm/lib/Target/ARM/ARMTargetMachine.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtargetarm_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtargetarm_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmtargetarm_la-ARMTargetMachine.lo -MD -MP -MF $(DEPDIR)/libllvmtargetarm_la-ARMTargetMachine.Tpo -c -o libllvmtargetarm_la-ARMTargetMachine.lo `test -f 'llvm/lib/Target/ARM/ARMTargetMachine.cpp' || echo '$(srcdir)/'`llvm/lib/Target/ARM/ARMTargetMachine.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmtargetarm_la-ARMTargetMachine.Tpo $(DEPDIR)/libllvmtargetarm_la-ARMTargetMachine.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Target/ARM/ARMTargetMachine.cpp' object='libllvmtargetarm_la-ARMTargetMachine.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtargetarm_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtargetarm_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmtargetarm_la-ARMTargetMachine.lo `test -f 'llvm/lib/Target/ARM/ARMTargetMachine.cpp' || echo '$(srcdir)/'`llvm/lib/Target/ARM/ARMTargetMachine.cpp + +libllvmtargetarm_la-NEONMoveFix.lo: llvm/lib/Target/ARM/NEONMoveFix.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtargetarm_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtargetarm_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmtargetarm_la-NEONMoveFix.lo -MD -MP -MF $(DEPDIR)/libllvmtargetarm_la-NEONMoveFix.Tpo -c -o libllvmtargetarm_la-NEONMoveFix.lo `test -f 'llvm/lib/Target/ARM/NEONMoveFix.cpp' || echo '$(srcdir)/'`llvm/lib/Target/ARM/NEONMoveFix.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmtargetarm_la-NEONMoveFix.Tpo $(DEPDIR)/libllvmtargetarm_la-NEONMoveFix.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Target/ARM/NEONMoveFix.cpp' object='libllvmtargetarm_la-NEONMoveFix.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtargetarm_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtargetarm_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmtargetarm_la-NEONMoveFix.lo `test -f 'llvm/lib/Target/ARM/NEONMoveFix.cpp' || echo '$(srcdir)/'`llvm/lib/Target/ARM/NEONMoveFix.cpp + +libllvmtargetarm_la-NEONPreAllocPass.lo: llvm/lib/Target/ARM/NEONPreAllocPass.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtargetarm_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtargetarm_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmtargetarm_la-NEONPreAllocPass.lo -MD -MP -MF $(DEPDIR)/libllvmtargetarm_la-NEONPreAllocPass.Tpo -c -o libllvmtargetarm_la-NEONPreAllocPass.lo `test -f 'llvm/lib/Target/ARM/NEONPreAllocPass.cpp' || echo '$(srcdir)/'`llvm/lib/Target/ARM/NEONPreAllocPass.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmtargetarm_la-NEONPreAllocPass.Tpo $(DEPDIR)/libllvmtargetarm_la-NEONPreAllocPass.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Target/ARM/NEONPreAllocPass.cpp' object='libllvmtargetarm_la-NEONPreAllocPass.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtargetarm_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtargetarm_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmtargetarm_la-NEONPreAllocPass.lo `test -f 'llvm/lib/Target/ARM/NEONPreAllocPass.cpp' || echo '$(srcdir)/'`llvm/lib/Target/ARM/NEONPreAllocPass.cpp + +libllvmtargetarm_la-Thumb1InstrInfo.lo: llvm/lib/Target/ARM/Thumb1InstrInfo.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtargetarm_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtargetarm_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmtargetarm_la-Thumb1InstrInfo.lo -MD -MP -MF $(DEPDIR)/libllvmtargetarm_la-Thumb1InstrInfo.Tpo -c -o libllvmtargetarm_la-Thumb1InstrInfo.lo `test -f 'llvm/lib/Target/ARM/Thumb1InstrInfo.cpp' || echo '$(srcdir)/'`llvm/lib/Target/ARM/Thumb1InstrInfo.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmtargetarm_la-Thumb1InstrInfo.Tpo $(DEPDIR)/libllvmtargetarm_la-Thumb1InstrInfo.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Target/ARM/Thumb1InstrInfo.cpp' object='libllvmtargetarm_la-Thumb1InstrInfo.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtargetarm_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtargetarm_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmtargetarm_la-Thumb1InstrInfo.lo `test -f 'llvm/lib/Target/ARM/Thumb1InstrInfo.cpp' || echo '$(srcdir)/'`llvm/lib/Target/ARM/Thumb1InstrInfo.cpp + +libllvmtargetarm_la-Thumb1RegisterInfo.lo: llvm/lib/Target/ARM/Thumb1RegisterInfo.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtargetarm_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtargetarm_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmtargetarm_la-Thumb1RegisterInfo.lo -MD -MP -MF $(DEPDIR)/libllvmtargetarm_la-Thumb1RegisterInfo.Tpo -c -o libllvmtargetarm_la-Thumb1RegisterInfo.lo `test -f 'llvm/lib/Target/ARM/Thumb1RegisterInfo.cpp' || echo '$(srcdir)/'`llvm/lib/Target/ARM/Thumb1RegisterInfo.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmtargetarm_la-Thumb1RegisterInfo.Tpo $(DEPDIR)/libllvmtargetarm_la-Thumb1RegisterInfo.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Target/ARM/Thumb1RegisterInfo.cpp' object='libllvmtargetarm_la-Thumb1RegisterInfo.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtargetarm_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtargetarm_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmtargetarm_la-Thumb1RegisterInfo.lo `test -f 'llvm/lib/Target/ARM/Thumb1RegisterInfo.cpp' || echo '$(srcdir)/'`llvm/lib/Target/ARM/Thumb1RegisterInfo.cpp + +libllvmtargetarm_la-Thumb2ITBlockPass.lo: llvm/lib/Target/ARM/Thumb2ITBlockPass.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtargetarm_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtargetarm_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmtargetarm_la-Thumb2ITBlockPass.lo -MD -MP -MF $(DEPDIR)/libllvmtargetarm_la-Thumb2ITBlockPass.Tpo -c -o libllvmtargetarm_la-Thumb2ITBlockPass.lo `test -f 'llvm/lib/Target/ARM/Thumb2ITBlockPass.cpp' || echo '$(srcdir)/'`llvm/lib/Target/ARM/Thumb2ITBlockPass.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmtargetarm_la-Thumb2ITBlockPass.Tpo $(DEPDIR)/libllvmtargetarm_la-Thumb2ITBlockPass.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Target/ARM/Thumb2ITBlockPass.cpp' object='libllvmtargetarm_la-Thumb2ITBlockPass.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtargetarm_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtargetarm_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmtargetarm_la-Thumb2ITBlockPass.lo `test -f 'llvm/lib/Target/ARM/Thumb2ITBlockPass.cpp' || echo '$(srcdir)/'`llvm/lib/Target/ARM/Thumb2ITBlockPass.cpp + +libllvmtargetarm_la-Thumb2InstrInfo.lo: llvm/lib/Target/ARM/Thumb2InstrInfo.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtargetarm_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtargetarm_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmtargetarm_la-Thumb2InstrInfo.lo -MD -MP -MF $(DEPDIR)/libllvmtargetarm_la-Thumb2InstrInfo.Tpo -c -o libllvmtargetarm_la-Thumb2InstrInfo.lo `test -f 'llvm/lib/Target/ARM/Thumb2InstrInfo.cpp' || echo '$(srcdir)/'`llvm/lib/Target/ARM/Thumb2InstrInfo.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmtargetarm_la-Thumb2InstrInfo.Tpo $(DEPDIR)/libllvmtargetarm_la-Thumb2InstrInfo.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Target/ARM/Thumb2InstrInfo.cpp' object='libllvmtargetarm_la-Thumb2InstrInfo.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtargetarm_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtargetarm_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmtargetarm_la-Thumb2InstrInfo.lo `test -f 'llvm/lib/Target/ARM/Thumb2InstrInfo.cpp' || echo '$(srcdir)/'`llvm/lib/Target/ARM/Thumb2InstrInfo.cpp + +libllvmtargetarm_la-Thumb2RegisterInfo.lo: llvm/lib/Target/ARM/Thumb2RegisterInfo.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtargetarm_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtargetarm_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmtargetarm_la-Thumb2RegisterInfo.lo -MD -MP -MF $(DEPDIR)/libllvmtargetarm_la-Thumb2RegisterInfo.Tpo -c -o libllvmtargetarm_la-Thumb2RegisterInfo.lo `test -f 'llvm/lib/Target/ARM/Thumb2RegisterInfo.cpp' || echo '$(srcdir)/'`llvm/lib/Target/ARM/Thumb2RegisterInfo.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmtargetarm_la-Thumb2RegisterInfo.Tpo $(DEPDIR)/libllvmtargetarm_la-Thumb2RegisterInfo.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Target/ARM/Thumb2RegisterInfo.cpp' object='libllvmtargetarm_la-Thumb2RegisterInfo.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtargetarm_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtargetarm_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmtargetarm_la-Thumb2RegisterInfo.lo `test -f 'llvm/lib/Target/ARM/Thumb2RegisterInfo.cpp' || echo '$(srcdir)/'`llvm/lib/Target/ARM/Thumb2RegisterInfo.cpp + +libllvmtargetarm_la-Thumb2SizeReduction.lo: llvm/lib/Target/ARM/Thumb2SizeReduction.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtargetarm_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtargetarm_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmtargetarm_la-Thumb2SizeReduction.lo -MD -MP -MF $(DEPDIR)/libllvmtargetarm_la-Thumb2SizeReduction.Tpo -c -o libllvmtargetarm_la-Thumb2SizeReduction.lo `test -f 'llvm/lib/Target/ARM/Thumb2SizeReduction.cpp' || echo '$(srcdir)/'`llvm/lib/Target/ARM/Thumb2SizeReduction.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmtargetarm_la-Thumb2SizeReduction.Tpo $(DEPDIR)/libllvmtargetarm_la-Thumb2SizeReduction.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Target/ARM/Thumb2SizeReduction.cpp' object='libllvmtargetarm_la-Thumb2SizeReduction.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtargetarm_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtargetarm_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmtargetarm_la-Thumb2SizeReduction.lo `test -f 'llvm/lib/Target/ARM/Thumb2SizeReduction.cpp' || echo '$(srcdir)/'`llvm/lib/Target/ARM/Thumb2SizeReduction.cpp + +libllvmtargetarm_la-ARMTargetInfo.lo: llvm/lib/Target/ARM/TargetInfo/ARMTargetInfo.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtargetarm_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtargetarm_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmtargetarm_la-ARMTargetInfo.lo -MD -MP -MF $(DEPDIR)/libllvmtargetarm_la-ARMTargetInfo.Tpo -c -o libllvmtargetarm_la-ARMTargetInfo.lo `test -f 'llvm/lib/Target/ARM/TargetInfo/ARMTargetInfo.cpp' || echo '$(srcdir)/'`llvm/lib/Target/ARM/TargetInfo/ARMTargetInfo.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmtargetarm_la-ARMTargetInfo.Tpo $(DEPDIR)/libllvmtargetarm_la-ARMTargetInfo.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Target/ARM/TargetInfo/ARMTargetInfo.cpp' object='libllvmtargetarm_la-ARMTargetInfo.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtargetarm_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtargetarm_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmtargetarm_la-ARMTargetInfo.lo `test -f 'llvm/lib/Target/ARM/TargetInfo/ARMTargetInfo.cpp' || echo '$(srcdir)/'`llvm/lib/Target/ARM/TargetInfo/ARMTargetInfo.cpp + +libllvmtargetppc_la-PPCBranchSelector.lo: llvm/lib/Target/PowerPC/PPCBranchSelector.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtargetppc_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtargetppc_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmtargetppc_la-PPCBranchSelector.lo -MD -MP -MF $(DEPDIR)/libllvmtargetppc_la-PPCBranchSelector.Tpo -c -o libllvmtargetppc_la-PPCBranchSelector.lo `test -f 'llvm/lib/Target/PowerPC/PPCBranchSelector.cpp' || echo '$(srcdir)/'`llvm/lib/Target/PowerPC/PPCBranchSelector.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmtargetppc_la-PPCBranchSelector.Tpo $(DEPDIR)/libllvmtargetppc_la-PPCBranchSelector.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Target/PowerPC/PPCBranchSelector.cpp' object='libllvmtargetppc_la-PPCBranchSelector.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtargetppc_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtargetppc_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmtargetppc_la-PPCBranchSelector.lo `test -f 'llvm/lib/Target/PowerPC/PPCBranchSelector.cpp' || echo '$(srcdir)/'`llvm/lib/Target/PowerPC/PPCBranchSelector.cpp + +libllvmtargetppc_la-PPCCodeEmitter.lo: llvm/lib/Target/PowerPC/PPCCodeEmitter.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtargetppc_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtargetppc_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmtargetppc_la-PPCCodeEmitter.lo -MD -MP -MF $(DEPDIR)/libllvmtargetppc_la-PPCCodeEmitter.Tpo -c -o libllvmtargetppc_la-PPCCodeEmitter.lo `test -f 'llvm/lib/Target/PowerPC/PPCCodeEmitter.cpp' || echo '$(srcdir)/'`llvm/lib/Target/PowerPC/PPCCodeEmitter.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmtargetppc_la-PPCCodeEmitter.Tpo $(DEPDIR)/libllvmtargetppc_la-PPCCodeEmitter.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Target/PowerPC/PPCCodeEmitter.cpp' object='libllvmtargetppc_la-PPCCodeEmitter.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtargetppc_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtargetppc_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmtargetppc_la-PPCCodeEmitter.lo `test -f 'llvm/lib/Target/PowerPC/PPCCodeEmitter.cpp' || echo '$(srcdir)/'`llvm/lib/Target/PowerPC/PPCCodeEmitter.cpp + +libllvmtargetppc_la-PPCHazardRecognizers.lo: llvm/lib/Target/PowerPC/PPCHazardRecognizers.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtargetppc_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtargetppc_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmtargetppc_la-PPCHazardRecognizers.lo -MD -MP -MF $(DEPDIR)/libllvmtargetppc_la-PPCHazardRecognizers.Tpo -c -o libllvmtargetppc_la-PPCHazardRecognizers.lo `test -f 'llvm/lib/Target/PowerPC/PPCHazardRecognizers.cpp' || echo '$(srcdir)/'`llvm/lib/Target/PowerPC/PPCHazardRecognizers.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmtargetppc_la-PPCHazardRecognizers.Tpo $(DEPDIR)/libllvmtargetppc_la-PPCHazardRecognizers.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Target/PowerPC/PPCHazardRecognizers.cpp' object='libllvmtargetppc_la-PPCHazardRecognizers.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtargetppc_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtargetppc_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmtargetppc_la-PPCHazardRecognizers.lo `test -f 'llvm/lib/Target/PowerPC/PPCHazardRecognizers.cpp' || echo '$(srcdir)/'`llvm/lib/Target/PowerPC/PPCHazardRecognizers.cpp + +libllvmtargetppc_la-PPCInstrInfo.lo: llvm/lib/Target/PowerPC/PPCInstrInfo.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtargetppc_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtargetppc_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmtargetppc_la-PPCInstrInfo.lo -MD -MP -MF $(DEPDIR)/libllvmtargetppc_la-PPCInstrInfo.Tpo -c -o libllvmtargetppc_la-PPCInstrInfo.lo `test -f 'llvm/lib/Target/PowerPC/PPCInstrInfo.cpp' || echo '$(srcdir)/'`llvm/lib/Target/PowerPC/PPCInstrInfo.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmtargetppc_la-PPCInstrInfo.Tpo $(DEPDIR)/libllvmtargetppc_la-PPCInstrInfo.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Target/PowerPC/PPCInstrInfo.cpp' object='libllvmtargetppc_la-PPCInstrInfo.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtargetppc_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtargetppc_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmtargetppc_la-PPCInstrInfo.lo `test -f 'llvm/lib/Target/PowerPC/PPCInstrInfo.cpp' || echo '$(srcdir)/'`llvm/lib/Target/PowerPC/PPCInstrInfo.cpp + +libllvmtargetppc_la-PPCISelDAGToDAG.lo: llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtargetppc_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtargetppc_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmtargetppc_la-PPCISelDAGToDAG.lo -MD -MP -MF $(DEPDIR)/libllvmtargetppc_la-PPCISelDAGToDAG.Tpo -c -o libllvmtargetppc_la-PPCISelDAGToDAG.lo `test -f 'llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp' || echo '$(srcdir)/'`llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmtargetppc_la-PPCISelDAGToDAG.Tpo $(DEPDIR)/libllvmtargetppc_la-PPCISelDAGToDAG.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp' object='libllvmtargetppc_la-PPCISelDAGToDAG.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtargetppc_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtargetppc_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmtargetppc_la-PPCISelDAGToDAG.lo `test -f 'llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp' || echo '$(srcdir)/'`llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp + +libllvmtargetppc_la-PPCISelLowering.lo: llvm/lib/Target/PowerPC/PPCISelLowering.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtargetppc_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtargetppc_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmtargetppc_la-PPCISelLowering.lo -MD -MP -MF $(DEPDIR)/libllvmtargetppc_la-PPCISelLowering.Tpo -c -o libllvmtargetppc_la-PPCISelLowering.lo `test -f 'llvm/lib/Target/PowerPC/PPCISelLowering.cpp' || echo '$(srcdir)/'`llvm/lib/Target/PowerPC/PPCISelLowering.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmtargetppc_la-PPCISelLowering.Tpo $(DEPDIR)/libllvmtargetppc_la-PPCISelLowering.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Target/PowerPC/PPCISelLowering.cpp' object='libllvmtargetppc_la-PPCISelLowering.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtargetppc_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtargetppc_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmtargetppc_la-PPCISelLowering.lo `test -f 'llvm/lib/Target/PowerPC/PPCISelLowering.cpp' || echo '$(srcdir)/'`llvm/lib/Target/PowerPC/PPCISelLowering.cpp + +libllvmtargetppc_la-PPCJITInfo.lo: llvm/lib/Target/PowerPC/PPCJITInfo.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtargetppc_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtargetppc_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmtargetppc_la-PPCJITInfo.lo -MD -MP -MF $(DEPDIR)/libllvmtargetppc_la-PPCJITInfo.Tpo -c -o libllvmtargetppc_la-PPCJITInfo.lo `test -f 'llvm/lib/Target/PowerPC/PPCJITInfo.cpp' || echo '$(srcdir)/'`llvm/lib/Target/PowerPC/PPCJITInfo.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmtargetppc_la-PPCJITInfo.Tpo $(DEPDIR)/libllvmtargetppc_la-PPCJITInfo.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Target/PowerPC/PPCJITInfo.cpp' object='libllvmtargetppc_la-PPCJITInfo.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtargetppc_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtargetppc_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmtargetppc_la-PPCJITInfo.lo `test -f 'llvm/lib/Target/PowerPC/PPCJITInfo.cpp' || echo '$(srcdir)/'`llvm/lib/Target/PowerPC/PPCJITInfo.cpp + +libllvmtargetppc_la-PPCMachOWriterInfo.lo: llvm/lib/Target/PowerPC/PPCMachOWriterInfo.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtargetppc_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtargetppc_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmtargetppc_la-PPCMachOWriterInfo.lo -MD -MP -MF $(DEPDIR)/libllvmtargetppc_la-PPCMachOWriterInfo.Tpo -c -o libllvmtargetppc_la-PPCMachOWriterInfo.lo `test -f 'llvm/lib/Target/PowerPC/PPCMachOWriterInfo.cpp' || echo '$(srcdir)/'`llvm/lib/Target/PowerPC/PPCMachOWriterInfo.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmtargetppc_la-PPCMachOWriterInfo.Tpo $(DEPDIR)/libllvmtargetppc_la-PPCMachOWriterInfo.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Target/PowerPC/PPCMachOWriterInfo.cpp' object='libllvmtargetppc_la-PPCMachOWriterInfo.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtargetppc_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtargetppc_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmtargetppc_la-PPCMachOWriterInfo.lo `test -f 'llvm/lib/Target/PowerPC/PPCMachOWriterInfo.cpp' || echo '$(srcdir)/'`llvm/lib/Target/PowerPC/PPCMachOWriterInfo.cpp + +libllvmtargetppc_la-PPCMCAsmInfo.lo: llvm/lib/Target/PowerPC/PPCMCAsmInfo.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtargetppc_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtargetppc_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmtargetppc_la-PPCMCAsmInfo.lo -MD -MP -MF $(DEPDIR)/libllvmtargetppc_la-PPCMCAsmInfo.Tpo -c -o libllvmtargetppc_la-PPCMCAsmInfo.lo `test -f 'llvm/lib/Target/PowerPC/PPCMCAsmInfo.cpp' || echo '$(srcdir)/'`llvm/lib/Target/PowerPC/PPCMCAsmInfo.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmtargetppc_la-PPCMCAsmInfo.Tpo $(DEPDIR)/libllvmtargetppc_la-PPCMCAsmInfo.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Target/PowerPC/PPCMCAsmInfo.cpp' object='libllvmtargetppc_la-PPCMCAsmInfo.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtargetppc_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtargetppc_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmtargetppc_la-PPCMCAsmInfo.lo `test -f 'llvm/lib/Target/PowerPC/PPCMCAsmInfo.cpp' || echo '$(srcdir)/'`llvm/lib/Target/PowerPC/PPCMCAsmInfo.cpp + +libllvmtargetppc_la-PPCPredicates.lo: llvm/lib/Target/PowerPC/PPCPredicates.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtargetppc_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtargetppc_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmtargetppc_la-PPCPredicates.lo -MD -MP -MF $(DEPDIR)/libllvmtargetppc_la-PPCPredicates.Tpo -c -o libllvmtargetppc_la-PPCPredicates.lo `test -f 'llvm/lib/Target/PowerPC/PPCPredicates.cpp' || echo '$(srcdir)/'`llvm/lib/Target/PowerPC/PPCPredicates.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmtargetppc_la-PPCPredicates.Tpo $(DEPDIR)/libllvmtargetppc_la-PPCPredicates.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Target/PowerPC/PPCPredicates.cpp' object='libllvmtargetppc_la-PPCPredicates.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtargetppc_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtargetppc_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmtargetppc_la-PPCPredicates.lo `test -f 'llvm/lib/Target/PowerPC/PPCPredicates.cpp' || echo '$(srcdir)/'`llvm/lib/Target/PowerPC/PPCPredicates.cpp + +libllvmtargetppc_la-PPCRegisterInfo.lo: llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtargetppc_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtargetppc_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmtargetppc_la-PPCRegisterInfo.lo -MD -MP -MF $(DEPDIR)/libllvmtargetppc_la-PPCRegisterInfo.Tpo -c -o libllvmtargetppc_la-PPCRegisterInfo.lo `test -f 'llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp' || echo '$(srcdir)/'`llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmtargetppc_la-PPCRegisterInfo.Tpo $(DEPDIR)/libllvmtargetppc_la-PPCRegisterInfo.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp' object='libllvmtargetppc_la-PPCRegisterInfo.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtargetppc_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtargetppc_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmtargetppc_la-PPCRegisterInfo.lo `test -f 'llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp' || echo '$(srcdir)/'`llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp + +libllvmtargetppc_la-PPCSubtarget.lo: llvm/lib/Target/PowerPC/PPCSubtarget.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtargetppc_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtargetppc_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmtargetppc_la-PPCSubtarget.lo -MD -MP -MF $(DEPDIR)/libllvmtargetppc_la-PPCSubtarget.Tpo -c -o libllvmtargetppc_la-PPCSubtarget.lo `test -f 'llvm/lib/Target/PowerPC/PPCSubtarget.cpp' || echo '$(srcdir)/'`llvm/lib/Target/PowerPC/PPCSubtarget.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmtargetppc_la-PPCSubtarget.Tpo $(DEPDIR)/libllvmtargetppc_la-PPCSubtarget.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Target/PowerPC/PPCSubtarget.cpp' object='libllvmtargetppc_la-PPCSubtarget.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtargetppc_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtargetppc_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmtargetppc_la-PPCSubtarget.lo `test -f 'llvm/lib/Target/PowerPC/PPCSubtarget.cpp' || echo '$(srcdir)/'`llvm/lib/Target/PowerPC/PPCSubtarget.cpp + +libllvmtargetppc_la-PPCTargetMachine.lo: llvm/lib/Target/PowerPC/PPCTargetMachine.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtargetppc_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtargetppc_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmtargetppc_la-PPCTargetMachine.lo -MD -MP -MF $(DEPDIR)/libllvmtargetppc_la-PPCTargetMachine.Tpo -c -o libllvmtargetppc_la-PPCTargetMachine.lo `test -f 'llvm/lib/Target/PowerPC/PPCTargetMachine.cpp' || echo '$(srcdir)/'`llvm/lib/Target/PowerPC/PPCTargetMachine.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmtargetppc_la-PPCTargetMachine.Tpo $(DEPDIR)/libllvmtargetppc_la-PPCTargetMachine.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Target/PowerPC/PPCTargetMachine.cpp' object='libllvmtargetppc_la-PPCTargetMachine.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtargetppc_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtargetppc_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmtargetppc_la-PPCTargetMachine.lo `test -f 'llvm/lib/Target/PowerPC/PPCTargetMachine.cpp' || echo '$(srcdir)/'`llvm/lib/Target/PowerPC/PPCTargetMachine.cpp + +libllvmtargetppc_la-PowerPCTargetInfo.lo: llvm/lib/Target/PowerPC/TargetInfo/PowerPCTargetInfo.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtargetppc_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtargetppc_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmtargetppc_la-PowerPCTargetInfo.lo -MD -MP -MF $(DEPDIR)/libllvmtargetppc_la-PowerPCTargetInfo.Tpo -c -o libllvmtargetppc_la-PowerPCTargetInfo.lo `test -f 'llvm/lib/Target/PowerPC/TargetInfo/PowerPCTargetInfo.cpp' || echo '$(srcdir)/'`llvm/lib/Target/PowerPC/TargetInfo/PowerPCTargetInfo.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmtargetppc_la-PowerPCTargetInfo.Tpo $(DEPDIR)/libllvmtargetppc_la-PowerPCTargetInfo.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Target/PowerPC/TargetInfo/PowerPCTargetInfo.cpp' object='libllvmtargetppc_la-PowerPCTargetInfo.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtargetppc_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtargetppc_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmtargetppc_la-PowerPCTargetInfo.lo `test -f 'llvm/lib/Target/PowerPC/TargetInfo/PowerPCTargetInfo.cpp' || echo '$(srcdir)/'`llvm/lib/Target/PowerPC/TargetInfo/PowerPCTargetInfo.cpp + +libllvmtargetx86_la-X86CodeEmitter.lo: llvm/lib/Target/X86/X86CodeEmitter.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtargetx86_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtargetx86_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmtargetx86_la-X86CodeEmitter.lo -MD -MP -MF $(DEPDIR)/libllvmtargetx86_la-X86CodeEmitter.Tpo -c -o libllvmtargetx86_la-X86CodeEmitter.lo `test -f 'llvm/lib/Target/X86/X86CodeEmitter.cpp' || echo '$(srcdir)/'`llvm/lib/Target/X86/X86CodeEmitter.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmtargetx86_la-X86CodeEmitter.Tpo $(DEPDIR)/libllvmtargetx86_la-X86CodeEmitter.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Target/X86/X86CodeEmitter.cpp' object='libllvmtargetx86_la-X86CodeEmitter.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtargetx86_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtargetx86_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmtargetx86_la-X86CodeEmitter.lo `test -f 'llvm/lib/Target/X86/X86CodeEmitter.cpp' || echo '$(srcdir)/'`llvm/lib/Target/X86/X86CodeEmitter.cpp + +libllvmtargetx86_la-X86ELFWriterInfo.lo: llvm/lib/Target/X86/X86ELFWriterInfo.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtargetx86_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtargetx86_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmtargetx86_la-X86ELFWriterInfo.lo -MD -MP -MF $(DEPDIR)/libllvmtargetx86_la-X86ELFWriterInfo.Tpo -c -o libllvmtargetx86_la-X86ELFWriterInfo.lo `test -f 'llvm/lib/Target/X86/X86ELFWriterInfo.cpp' || echo '$(srcdir)/'`llvm/lib/Target/X86/X86ELFWriterInfo.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmtargetx86_la-X86ELFWriterInfo.Tpo $(DEPDIR)/libllvmtargetx86_la-X86ELFWriterInfo.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Target/X86/X86ELFWriterInfo.cpp' object='libllvmtargetx86_la-X86ELFWriterInfo.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtargetx86_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtargetx86_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmtargetx86_la-X86ELFWriterInfo.lo `test -f 'llvm/lib/Target/X86/X86ELFWriterInfo.cpp' || echo '$(srcdir)/'`llvm/lib/Target/X86/X86ELFWriterInfo.cpp + +libllvmtargetx86_la-X86FloatingPoint.lo: llvm/lib/Target/X86/X86FloatingPoint.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtargetx86_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtargetx86_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmtargetx86_la-X86FloatingPoint.lo -MD -MP -MF $(DEPDIR)/libllvmtargetx86_la-X86FloatingPoint.Tpo -c -o libllvmtargetx86_la-X86FloatingPoint.lo `test -f 'llvm/lib/Target/X86/X86FloatingPoint.cpp' || echo '$(srcdir)/'`llvm/lib/Target/X86/X86FloatingPoint.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmtargetx86_la-X86FloatingPoint.Tpo $(DEPDIR)/libllvmtargetx86_la-X86FloatingPoint.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Target/X86/X86FloatingPoint.cpp' object='libllvmtargetx86_la-X86FloatingPoint.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtargetx86_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtargetx86_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmtargetx86_la-X86FloatingPoint.lo `test -f 'llvm/lib/Target/X86/X86FloatingPoint.cpp' || echo '$(srcdir)/'`llvm/lib/Target/X86/X86FloatingPoint.cpp + +libllvmtargetx86_la-X86FloatingPointRegKill.lo: llvm/lib/Target/X86/X86FloatingPointRegKill.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtargetx86_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtargetx86_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmtargetx86_la-X86FloatingPointRegKill.lo -MD -MP -MF $(DEPDIR)/libllvmtargetx86_la-X86FloatingPointRegKill.Tpo -c -o libllvmtargetx86_la-X86FloatingPointRegKill.lo `test -f 'llvm/lib/Target/X86/X86FloatingPointRegKill.cpp' || echo '$(srcdir)/'`llvm/lib/Target/X86/X86FloatingPointRegKill.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmtargetx86_la-X86FloatingPointRegKill.Tpo $(DEPDIR)/libllvmtargetx86_la-X86FloatingPointRegKill.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Target/X86/X86FloatingPointRegKill.cpp' object='libllvmtargetx86_la-X86FloatingPointRegKill.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtargetx86_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtargetx86_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmtargetx86_la-X86FloatingPointRegKill.lo `test -f 'llvm/lib/Target/X86/X86FloatingPointRegKill.cpp' || echo '$(srcdir)/'`llvm/lib/Target/X86/X86FloatingPointRegKill.cpp + +libllvmtargetx86_la-X86ISelDAGToDAG.lo: llvm/lib/Target/X86/X86ISelDAGToDAG.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtargetx86_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtargetx86_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmtargetx86_la-X86ISelDAGToDAG.lo -MD -MP -MF $(DEPDIR)/libllvmtargetx86_la-X86ISelDAGToDAG.Tpo -c -o libllvmtargetx86_la-X86ISelDAGToDAG.lo `test -f 'llvm/lib/Target/X86/X86ISelDAGToDAG.cpp' || echo '$(srcdir)/'`llvm/lib/Target/X86/X86ISelDAGToDAG.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmtargetx86_la-X86ISelDAGToDAG.Tpo $(DEPDIR)/libllvmtargetx86_la-X86ISelDAGToDAG.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Target/X86/X86ISelDAGToDAG.cpp' object='libllvmtargetx86_la-X86ISelDAGToDAG.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtargetx86_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtargetx86_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmtargetx86_la-X86ISelDAGToDAG.lo `test -f 'llvm/lib/Target/X86/X86ISelDAGToDAG.cpp' || echo '$(srcdir)/'`llvm/lib/Target/X86/X86ISelDAGToDAG.cpp + +libllvmtargetx86_la-X86ISelLowering.lo: llvm/lib/Target/X86/X86ISelLowering.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtargetx86_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtargetx86_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmtargetx86_la-X86ISelLowering.lo -MD -MP -MF $(DEPDIR)/libllvmtargetx86_la-X86ISelLowering.Tpo -c -o libllvmtargetx86_la-X86ISelLowering.lo `test -f 'llvm/lib/Target/X86/X86ISelLowering.cpp' || echo '$(srcdir)/'`llvm/lib/Target/X86/X86ISelLowering.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmtargetx86_la-X86ISelLowering.Tpo $(DEPDIR)/libllvmtargetx86_la-X86ISelLowering.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Target/X86/X86ISelLowering.cpp' object='libllvmtargetx86_la-X86ISelLowering.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtargetx86_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtargetx86_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmtargetx86_la-X86ISelLowering.lo `test -f 'llvm/lib/Target/X86/X86ISelLowering.cpp' || echo '$(srcdir)/'`llvm/lib/Target/X86/X86ISelLowering.cpp + +libllvmtargetx86_la-X86InstrInfo.lo: llvm/lib/Target/X86/X86InstrInfo.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtargetx86_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtargetx86_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmtargetx86_la-X86InstrInfo.lo -MD -MP -MF $(DEPDIR)/libllvmtargetx86_la-X86InstrInfo.Tpo -c -o libllvmtargetx86_la-X86InstrInfo.lo `test -f 'llvm/lib/Target/X86/X86InstrInfo.cpp' || echo '$(srcdir)/'`llvm/lib/Target/X86/X86InstrInfo.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmtargetx86_la-X86InstrInfo.Tpo $(DEPDIR)/libllvmtargetx86_la-X86InstrInfo.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Target/X86/X86InstrInfo.cpp' object='libllvmtargetx86_la-X86InstrInfo.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtargetx86_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtargetx86_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmtargetx86_la-X86InstrInfo.lo `test -f 'llvm/lib/Target/X86/X86InstrInfo.cpp' || echo '$(srcdir)/'`llvm/lib/Target/X86/X86InstrInfo.cpp + +libllvmtargetx86_la-X86JITInfo.lo: llvm/lib/Target/X86/X86JITInfo.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtargetx86_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtargetx86_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmtargetx86_la-X86JITInfo.lo -MD -MP -MF $(DEPDIR)/libllvmtargetx86_la-X86JITInfo.Tpo -c -o libllvmtargetx86_la-X86JITInfo.lo `test -f 'llvm/lib/Target/X86/X86JITInfo.cpp' || echo '$(srcdir)/'`llvm/lib/Target/X86/X86JITInfo.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmtargetx86_la-X86JITInfo.Tpo $(DEPDIR)/libllvmtargetx86_la-X86JITInfo.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Target/X86/X86JITInfo.cpp' object='libllvmtargetx86_la-X86JITInfo.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtargetx86_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtargetx86_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmtargetx86_la-X86JITInfo.lo `test -f 'llvm/lib/Target/X86/X86JITInfo.cpp' || echo '$(srcdir)/'`llvm/lib/Target/X86/X86JITInfo.cpp + +libllvmtargetx86_la-X86MCAsmInfo.lo: llvm/lib/Target/X86/X86MCAsmInfo.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtargetx86_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtargetx86_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmtargetx86_la-X86MCAsmInfo.lo -MD -MP -MF $(DEPDIR)/libllvmtargetx86_la-X86MCAsmInfo.Tpo -c -o libllvmtargetx86_la-X86MCAsmInfo.lo `test -f 'llvm/lib/Target/X86/X86MCAsmInfo.cpp' || echo '$(srcdir)/'`llvm/lib/Target/X86/X86MCAsmInfo.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmtargetx86_la-X86MCAsmInfo.Tpo $(DEPDIR)/libllvmtargetx86_la-X86MCAsmInfo.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Target/X86/X86MCAsmInfo.cpp' object='libllvmtargetx86_la-X86MCAsmInfo.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtargetx86_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtargetx86_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmtargetx86_la-X86MCAsmInfo.lo `test -f 'llvm/lib/Target/X86/X86MCAsmInfo.cpp' || echo '$(srcdir)/'`llvm/lib/Target/X86/X86MCAsmInfo.cpp + +libllvmtargetx86_la-X86RegisterInfo.lo: llvm/lib/Target/X86/X86RegisterInfo.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtargetx86_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtargetx86_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmtargetx86_la-X86RegisterInfo.lo -MD -MP -MF $(DEPDIR)/libllvmtargetx86_la-X86RegisterInfo.Tpo -c -o libllvmtargetx86_la-X86RegisterInfo.lo `test -f 'llvm/lib/Target/X86/X86RegisterInfo.cpp' || echo '$(srcdir)/'`llvm/lib/Target/X86/X86RegisterInfo.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmtargetx86_la-X86RegisterInfo.Tpo $(DEPDIR)/libllvmtargetx86_la-X86RegisterInfo.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Target/X86/X86RegisterInfo.cpp' object='libllvmtargetx86_la-X86RegisterInfo.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtargetx86_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtargetx86_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmtargetx86_la-X86RegisterInfo.lo `test -f 'llvm/lib/Target/X86/X86RegisterInfo.cpp' || echo '$(srcdir)/'`llvm/lib/Target/X86/X86RegisterInfo.cpp + +libllvmtargetx86_la-X86Subtarget.lo: llvm/lib/Target/X86/X86Subtarget.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtargetx86_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtargetx86_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmtargetx86_la-X86Subtarget.lo -MD -MP -MF $(DEPDIR)/libllvmtargetx86_la-X86Subtarget.Tpo -c -o libllvmtargetx86_la-X86Subtarget.lo `test -f 'llvm/lib/Target/X86/X86Subtarget.cpp' || echo '$(srcdir)/'`llvm/lib/Target/X86/X86Subtarget.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmtargetx86_la-X86Subtarget.Tpo $(DEPDIR)/libllvmtargetx86_la-X86Subtarget.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Target/X86/X86Subtarget.cpp' object='libllvmtargetx86_la-X86Subtarget.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtargetx86_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtargetx86_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmtargetx86_la-X86Subtarget.lo `test -f 'llvm/lib/Target/X86/X86Subtarget.cpp' || echo '$(srcdir)/'`llvm/lib/Target/X86/X86Subtarget.cpp + +libllvmtargetx86_la-X86TargetMachine.lo: llvm/lib/Target/X86/X86TargetMachine.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtargetx86_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtargetx86_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmtargetx86_la-X86TargetMachine.lo -MD -MP -MF $(DEPDIR)/libllvmtargetx86_la-X86TargetMachine.Tpo -c -o libllvmtargetx86_la-X86TargetMachine.lo `test -f 'llvm/lib/Target/X86/X86TargetMachine.cpp' || echo '$(srcdir)/'`llvm/lib/Target/X86/X86TargetMachine.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmtargetx86_la-X86TargetMachine.Tpo $(DEPDIR)/libllvmtargetx86_la-X86TargetMachine.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Target/X86/X86TargetMachine.cpp' object='libllvmtargetx86_la-X86TargetMachine.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtargetx86_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtargetx86_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmtargetx86_la-X86TargetMachine.lo `test -f 'llvm/lib/Target/X86/X86TargetMachine.cpp' || echo '$(srcdir)/'`llvm/lib/Target/X86/X86TargetMachine.cpp + +libllvmtargetx86_la-X86FastISel.lo: llvm/lib/Target/X86/X86FastISel.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtargetx86_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtargetx86_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmtargetx86_la-X86FastISel.lo -MD -MP -MF $(DEPDIR)/libllvmtargetx86_la-X86FastISel.Tpo -c -o libllvmtargetx86_la-X86FastISel.lo `test -f 'llvm/lib/Target/X86/X86FastISel.cpp' || echo '$(srcdir)/'`llvm/lib/Target/X86/X86FastISel.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmtargetx86_la-X86FastISel.Tpo $(DEPDIR)/libllvmtargetx86_la-X86FastISel.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Target/X86/X86FastISel.cpp' object='libllvmtargetx86_la-X86FastISel.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtargetx86_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtargetx86_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmtargetx86_la-X86FastISel.lo `test -f 'llvm/lib/Target/X86/X86FastISel.cpp' || echo '$(srcdir)/'`llvm/lib/Target/X86/X86FastISel.cpp + +libllvmtargetx86_la-X86TargetObjectFile.lo: llvm/lib/Target/X86/X86TargetObjectFile.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtargetx86_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtargetx86_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmtargetx86_la-X86TargetObjectFile.lo -MD -MP -MF $(DEPDIR)/libllvmtargetx86_la-X86TargetObjectFile.Tpo -c -o libllvmtargetx86_la-X86TargetObjectFile.lo `test -f 'llvm/lib/Target/X86/X86TargetObjectFile.cpp' || echo '$(srcdir)/'`llvm/lib/Target/X86/X86TargetObjectFile.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmtargetx86_la-X86TargetObjectFile.Tpo $(DEPDIR)/libllvmtargetx86_la-X86TargetObjectFile.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Target/X86/X86TargetObjectFile.cpp' object='libllvmtargetx86_la-X86TargetObjectFile.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtargetx86_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtargetx86_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmtargetx86_la-X86TargetObjectFile.lo `test -f 'llvm/lib/Target/X86/X86TargetObjectFile.cpp' || echo '$(srcdir)/'`llvm/lib/Target/X86/X86TargetObjectFile.cpp + +libllvmtargetx86_la-X86TargetInfo.lo: llvm/lib/Target/X86/TargetInfo/X86TargetInfo.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtargetx86_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtargetx86_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmtargetx86_la-X86TargetInfo.lo -MD -MP -MF $(DEPDIR)/libllvmtargetx86_la-X86TargetInfo.Tpo -c -o libllvmtargetx86_la-X86TargetInfo.lo `test -f 'llvm/lib/Target/X86/TargetInfo/X86TargetInfo.cpp' || echo '$(srcdir)/'`llvm/lib/Target/X86/TargetInfo/X86TargetInfo.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmtargetx86_la-X86TargetInfo.Tpo $(DEPDIR)/libllvmtargetx86_la-X86TargetInfo.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Target/X86/TargetInfo/X86TargetInfo.cpp' object='libllvmtargetx86_la-X86TargetInfo.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtargetx86_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtargetx86_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmtargetx86_la-X86TargetInfo.lo `test -f 'llvm/lib/Target/X86/TargetInfo/X86TargetInfo.cpp' || echo '$(srcdir)/'`llvm/lib/Target/X86/TargetInfo/X86TargetInfo.cpp + +libllvmtransformutils_la-AddrModeMatcher.lo: llvm/lib/Transforms/Utils/AddrModeMatcher.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtransformutils_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtransformutils_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmtransformutils_la-AddrModeMatcher.lo -MD -MP -MF $(DEPDIR)/libllvmtransformutils_la-AddrModeMatcher.Tpo -c -o libllvmtransformutils_la-AddrModeMatcher.lo `test -f 'llvm/lib/Transforms/Utils/AddrModeMatcher.cpp' || echo '$(srcdir)/'`llvm/lib/Transforms/Utils/AddrModeMatcher.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmtransformutils_la-AddrModeMatcher.Tpo $(DEPDIR)/libllvmtransformutils_la-AddrModeMatcher.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Transforms/Utils/AddrModeMatcher.cpp' object='libllvmtransformutils_la-AddrModeMatcher.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtransformutils_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtransformutils_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmtransformutils_la-AddrModeMatcher.lo `test -f 'llvm/lib/Transforms/Utils/AddrModeMatcher.cpp' || echo '$(srcdir)/'`llvm/lib/Transforms/Utils/AddrModeMatcher.cpp + +libllvmtransformutils_la-BasicBlockUtils.lo: llvm/lib/Transforms/Utils/BasicBlockUtils.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtransformutils_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtransformutils_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmtransformutils_la-BasicBlockUtils.lo -MD -MP -MF $(DEPDIR)/libllvmtransformutils_la-BasicBlockUtils.Tpo -c -o libllvmtransformutils_la-BasicBlockUtils.lo `test -f 'llvm/lib/Transforms/Utils/BasicBlockUtils.cpp' || echo '$(srcdir)/'`llvm/lib/Transforms/Utils/BasicBlockUtils.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmtransformutils_la-BasicBlockUtils.Tpo $(DEPDIR)/libllvmtransformutils_la-BasicBlockUtils.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Transforms/Utils/BasicBlockUtils.cpp' object='libllvmtransformutils_la-BasicBlockUtils.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtransformutils_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtransformutils_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmtransformutils_la-BasicBlockUtils.lo `test -f 'llvm/lib/Transforms/Utils/BasicBlockUtils.cpp' || echo '$(srcdir)/'`llvm/lib/Transforms/Utils/BasicBlockUtils.cpp + +libllvmtransformutils_la-BreakCriticalEdges.lo: llvm/lib/Transforms/Utils/BreakCriticalEdges.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtransformutils_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtransformutils_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmtransformutils_la-BreakCriticalEdges.lo -MD -MP -MF $(DEPDIR)/libllvmtransformutils_la-BreakCriticalEdges.Tpo -c -o libllvmtransformutils_la-BreakCriticalEdges.lo `test -f 'llvm/lib/Transforms/Utils/BreakCriticalEdges.cpp' || echo '$(srcdir)/'`llvm/lib/Transforms/Utils/BreakCriticalEdges.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmtransformutils_la-BreakCriticalEdges.Tpo $(DEPDIR)/libllvmtransformutils_la-BreakCriticalEdges.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Transforms/Utils/BreakCriticalEdges.cpp' object='libllvmtransformutils_la-BreakCriticalEdges.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtransformutils_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtransformutils_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmtransformutils_la-BreakCriticalEdges.lo `test -f 'llvm/lib/Transforms/Utils/BreakCriticalEdges.cpp' || echo '$(srcdir)/'`llvm/lib/Transforms/Utils/BreakCriticalEdges.cpp + +libllvmtransformutils_la-DemoteRegToStack.lo: llvm/lib/Transforms/Utils/DemoteRegToStack.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtransformutils_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtransformutils_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmtransformutils_la-DemoteRegToStack.lo -MD -MP -MF $(DEPDIR)/libllvmtransformutils_la-DemoteRegToStack.Tpo -c -o libllvmtransformutils_la-DemoteRegToStack.lo `test -f 'llvm/lib/Transforms/Utils/DemoteRegToStack.cpp' || echo '$(srcdir)/'`llvm/lib/Transforms/Utils/DemoteRegToStack.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmtransformutils_la-DemoteRegToStack.Tpo $(DEPDIR)/libllvmtransformutils_la-DemoteRegToStack.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Transforms/Utils/DemoteRegToStack.cpp' object='libllvmtransformutils_la-DemoteRegToStack.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtransformutils_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtransformutils_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmtransformutils_la-DemoteRegToStack.lo `test -f 'llvm/lib/Transforms/Utils/DemoteRegToStack.cpp' || echo '$(srcdir)/'`llvm/lib/Transforms/Utils/DemoteRegToStack.cpp + +libllvmtransformutils_la-LCSSA.lo: llvm/lib/Transforms/Utils/LCSSA.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtransformutils_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtransformutils_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmtransformutils_la-LCSSA.lo -MD -MP -MF $(DEPDIR)/libllvmtransformutils_la-LCSSA.Tpo -c -o libllvmtransformutils_la-LCSSA.lo `test -f 'llvm/lib/Transforms/Utils/LCSSA.cpp' || echo '$(srcdir)/'`llvm/lib/Transforms/Utils/LCSSA.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmtransformutils_la-LCSSA.Tpo $(DEPDIR)/libllvmtransformutils_la-LCSSA.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Transforms/Utils/LCSSA.cpp' object='libllvmtransformutils_la-LCSSA.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtransformutils_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtransformutils_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmtransformutils_la-LCSSA.lo `test -f 'llvm/lib/Transforms/Utils/LCSSA.cpp' || echo '$(srcdir)/'`llvm/lib/Transforms/Utils/LCSSA.cpp + +libllvmtransformutils_la-Local.lo: llvm/lib/Transforms/Utils/Local.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtransformutils_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtransformutils_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmtransformutils_la-Local.lo -MD -MP -MF $(DEPDIR)/libllvmtransformutils_la-Local.Tpo -c -o libllvmtransformutils_la-Local.lo `test -f 'llvm/lib/Transforms/Utils/Local.cpp' || echo '$(srcdir)/'`llvm/lib/Transforms/Utils/Local.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmtransformutils_la-Local.Tpo $(DEPDIR)/libllvmtransformutils_la-Local.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Transforms/Utils/Local.cpp' object='libllvmtransformutils_la-Local.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtransformutils_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtransformutils_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmtransformutils_la-Local.lo `test -f 'llvm/lib/Transforms/Utils/Local.cpp' || echo '$(srcdir)/'`llvm/lib/Transforms/Utils/Local.cpp + +libllvmtransformutils_la-LoopSimplify.lo: llvm/lib/Transforms/Utils/LoopSimplify.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtransformutils_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtransformutils_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmtransformutils_la-LoopSimplify.lo -MD -MP -MF $(DEPDIR)/libllvmtransformutils_la-LoopSimplify.Tpo -c -o libllvmtransformutils_la-LoopSimplify.lo `test -f 'llvm/lib/Transforms/Utils/LoopSimplify.cpp' || echo '$(srcdir)/'`llvm/lib/Transforms/Utils/LoopSimplify.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmtransformutils_la-LoopSimplify.Tpo $(DEPDIR)/libllvmtransformutils_la-LoopSimplify.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Transforms/Utils/LoopSimplify.cpp' object='libllvmtransformutils_la-LoopSimplify.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtransformutils_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtransformutils_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmtransformutils_la-LoopSimplify.lo `test -f 'llvm/lib/Transforms/Utils/LoopSimplify.cpp' || echo '$(srcdir)/'`llvm/lib/Transforms/Utils/LoopSimplify.cpp + +libllvmtransformutils_la-LowerInvoke.lo: llvm/lib/Transforms/Utils/LowerInvoke.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtransformutils_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtransformutils_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmtransformutils_la-LowerInvoke.lo -MD -MP -MF $(DEPDIR)/libllvmtransformutils_la-LowerInvoke.Tpo -c -o libllvmtransformutils_la-LowerInvoke.lo `test -f 'llvm/lib/Transforms/Utils/LowerInvoke.cpp' || echo '$(srcdir)/'`llvm/lib/Transforms/Utils/LowerInvoke.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmtransformutils_la-LowerInvoke.Tpo $(DEPDIR)/libllvmtransformutils_la-LowerInvoke.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Transforms/Utils/LowerInvoke.cpp' object='libllvmtransformutils_la-LowerInvoke.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtransformutils_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtransformutils_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmtransformutils_la-LowerInvoke.lo `test -f 'llvm/lib/Transforms/Utils/LowerInvoke.cpp' || echo '$(srcdir)/'`llvm/lib/Transforms/Utils/LowerInvoke.cpp + +libllvmtransformutils_la-LowerSwitch.lo: llvm/lib/Transforms/Utils/LowerSwitch.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtransformutils_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtransformutils_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmtransformutils_la-LowerSwitch.lo -MD -MP -MF $(DEPDIR)/libllvmtransformutils_la-LowerSwitch.Tpo -c -o libllvmtransformutils_la-LowerSwitch.lo `test -f 'llvm/lib/Transforms/Utils/LowerSwitch.cpp' || echo '$(srcdir)/'`llvm/lib/Transforms/Utils/LowerSwitch.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmtransformutils_la-LowerSwitch.Tpo $(DEPDIR)/libllvmtransformutils_la-LowerSwitch.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Transforms/Utils/LowerSwitch.cpp' object='libllvmtransformutils_la-LowerSwitch.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtransformutils_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtransformutils_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmtransformutils_la-LowerSwitch.lo `test -f 'llvm/lib/Transforms/Utils/LowerSwitch.cpp' || echo '$(srcdir)/'`llvm/lib/Transforms/Utils/LowerSwitch.cpp + +libllvmtransformutils_la-Mem2Reg.lo: llvm/lib/Transforms/Utils/Mem2Reg.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtransformutils_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtransformutils_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmtransformutils_la-Mem2Reg.lo -MD -MP -MF $(DEPDIR)/libllvmtransformutils_la-Mem2Reg.Tpo -c -o libllvmtransformutils_la-Mem2Reg.lo `test -f 'llvm/lib/Transforms/Utils/Mem2Reg.cpp' || echo '$(srcdir)/'`llvm/lib/Transforms/Utils/Mem2Reg.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmtransformutils_la-Mem2Reg.Tpo $(DEPDIR)/libllvmtransformutils_la-Mem2Reg.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Transforms/Utils/Mem2Reg.cpp' object='libllvmtransformutils_la-Mem2Reg.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtransformutils_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtransformutils_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmtransformutils_la-Mem2Reg.lo `test -f 'llvm/lib/Transforms/Utils/Mem2Reg.cpp' || echo '$(srcdir)/'`llvm/lib/Transforms/Utils/Mem2Reg.cpp + +libllvmtransformutils_la-PromoteMemoryToRegister.lo: llvm/lib/Transforms/Utils/PromoteMemoryToRegister.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtransformutils_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtransformutils_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmtransformutils_la-PromoteMemoryToRegister.lo -MD -MP -MF $(DEPDIR)/libllvmtransformutils_la-PromoteMemoryToRegister.Tpo -c -o libllvmtransformutils_la-PromoteMemoryToRegister.lo `test -f 'llvm/lib/Transforms/Utils/PromoteMemoryToRegister.cpp' || echo '$(srcdir)/'`llvm/lib/Transforms/Utils/PromoteMemoryToRegister.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmtransformutils_la-PromoteMemoryToRegister.Tpo $(DEPDIR)/libllvmtransformutils_la-PromoteMemoryToRegister.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Transforms/Utils/PromoteMemoryToRegister.cpp' object='libllvmtransformutils_la-PromoteMemoryToRegister.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtransformutils_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtransformutils_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmtransformutils_la-PromoteMemoryToRegister.lo `test -f 'llvm/lib/Transforms/Utils/PromoteMemoryToRegister.cpp' || echo '$(srcdir)/'`llvm/lib/Transforms/Utils/PromoteMemoryToRegister.cpp + +libllvmtransformutils_la-SimplifyCFG.lo: llvm/lib/Transforms/Utils/SimplifyCFG.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtransformutils_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtransformutils_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmtransformutils_la-SimplifyCFG.lo -MD -MP -MF $(DEPDIR)/libllvmtransformutils_la-SimplifyCFG.Tpo -c -o libllvmtransformutils_la-SimplifyCFG.lo `test -f 'llvm/lib/Transforms/Utils/SimplifyCFG.cpp' || echo '$(srcdir)/'`llvm/lib/Transforms/Utils/SimplifyCFG.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmtransformutils_la-SimplifyCFG.Tpo $(DEPDIR)/libllvmtransformutils_la-SimplifyCFG.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Transforms/Utils/SimplifyCFG.cpp' object='libllvmtransformutils_la-SimplifyCFG.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtransformutils_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtransformutils_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmtransformutils_la-SimplifyCFG.lo `test -f 'llvm/lib/Transforms/Utils/SimplifyCFG.cpp' || echo '$(srcdir)/'`llvm/lib/Transforms/Utils/SimplifyCFG.cpp + +libllvmtransformutils_la-SSAUpdater.lo: llvm/lib/Transforms/Utils/SSAUpdater.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtransformutils_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtransformutils_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmtransformutils_la-SSAUpdater.lo -MD -MP -MF $(DEPDIR)/libllvmtransformutils_la-SSAUpdater.Tpo -c -o libllvmtransformutils_la-SSAUpdater.lo `test -f 'llvm/lib/Transforms/Utils/SSAUpdater.cpp' || echo '$(srcdir)/'`llvm/lib/Transforms/Utils/SSAUpdater.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmtransformutils_la-SSAUpdater.Tpo $(DEPDIR)/libllvmtransformutils_la-SSAUpdater.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Transforms/Utils/SSAUpdater.cpp' object='libllvmtransformutils_la-SSAUpdater.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtransformutils_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtransformutils_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmtransformutils_la-SSAUpdater.lo `test -f 'llvm/lib/Transforms/Utils/SSAUpdater.cpp' || echo '$(srcdir)/'`llvm/lib/Transforms/Utils/SSAUpdater.cpp + +libllvmtransformutils_la-UnifyFunctionExitNodes.lo: llvm/lib/Transforms/Utils/UnifyFunctionExitNodes.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtransformutils_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtransformutils_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmtransformutils_la-UnifyFunctionExitNodes.lo -MD -MP -MF $(DEPDIR)/libllvmtransformutils_la-UnifyFunctionExitNodes.Tpo -c -o libllvmtransformutils_la-UnifyFunctionExitNodes.lo `test -f 'llvm/lib/Transforms/Utils/UnifyFunctionExitNodes.cpp' || echo '$(srcdir)/'`llvm/lib/Transforms/Utils/UnifyFunctionExitNodes.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmtransformutils_la-UnifyFunctionExitNodes.Tpo $(DEPDIR)/libllvmtransformutils_la-UnifyFunctionExitNodes.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Transforms/Utils/UnifyFunctionExitNodes.cpp' object='libllvmtransformutils_la-UnifyFunctionExitNodes.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmtransformutils_la_CPPFLAGS) $(CPPFLAGS) $(libllvmtransformutils_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmtransformutils_la-UnifyFunctionExitNodes.lo `test -f 'llvm/lib/Transforms/Utils/UnifyFunctionExitNodes.cpp' || echo '$(srcdir)/'`llvm/lib/Transforms/Utils/UnifyFunctionExitNodes.cpp + +FileCheck-FileCheck.o: llvm/utils/FileCheck/FileCheck.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(FileCheck_CPPFLAGS) $(CPPFLAGS) $(FileCheck_CXXFLAGS) $(CXXFLAGS) -MT FileCheck-FileCheck.o -MD -MP -MF $(DEPDIR)/FileCheck-FileCheck.Tpo -c -o FileCheck-FileCheck.o `test -f 'llvm/utils/FileCheck/FileCheck.cpp' || echo '$(srcdir)/'`llvm/utils/FileCheck/FileCheck.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/FileCheck-FileCheck.Tpo $(DEPDIR)/FileCheck-FileCheck.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/utils/FileCheck/FileCheck.cpp' object='FileCheck-FileCheck.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(FileCheck_CPPFLAGS) $(CPPFLAGS) $(FileCheck_CXXFLAGS) $(CXXFLAGS) -c -o FileCheck-FileCheck.o `test -f 'llvm/utils/FileCheck/FileCheck.cpp' || echo '$(srcdir)/'`llvm/utils/FileCheck/FileCheck.cpp + +FileCheck-FileCheck.obj: llvm/utils/FileCheck/FileCheck.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(FileCheck_CPPFLAGS) $(CPPFLAGS) $(FileCheck_CXXFLAGS) $(CXXFLAGS) -MT FileCheck-FileCheck.obj -MD -MP -MF $(DEPDIR)/FileCheck-FileCheck.Tpo -c -o FileCheck-FileCheck.obj `if test -f 'llvm/utils/FileCheck/FileCheck.cpp'; then $(CYGPATH_W) 'llvm/utils/FileCheck/FileCheck.cpp'; else $(CYGPATH_W) '$(srcdir)/llvm/utils/FileCheck/FileCheck.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/FileCheck-FileCheck.Tpo $(DEPDIR)/FileCheck-FileCheck.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/utils/FileCheck/FileCheck.cpp' object='FileCheck-FileCheck.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(FileCheck_CPPFLAGS) $(CPPFLAGS) $(FileCheck_CXXFLAGS) $(CXXFLAGS) -c -o FileCheck-FileCheck.obj `if test -f 'llvm/utils/FileCheck/FileCheck.cpp'; then $(CYGPATH_W) 'llvm/utils/FileCheck/FileCheck.cpp'; else $(CYGPATH_W) '$(srcdir)/llvm/utils/FileCheck/FileCheck.cpp'; fi` + +llc-MCInstPrinter.o: llvm/lib/MC/MCInstPrinter.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llc_CPPFLAGS) $(CPPFLAGS) $(llc_CXXFLAGS) $(CXXFLAGS) -MT llc-MCInstPrinter.o -MD -MP -MF $(DEPDIR)/llc-MCInstPrinter.Tpo -c -o llc-MCInstPrinter.o `test -f 'llvm/lib/MC/MCInstPrinter.cpp' || echo '$(srcdir)/'`llvm/lib/MC/MCInstPrinter.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/llc-MCInstPrinter.Tpo $(DEPDIR)/llc-MCInstPrinter.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/MC/MCInstPrinter.cpp' object='llc-MCInstPrinter.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llc_CPPFLAGS) $(CPPFLAGS) $(llc_CXXFLAGS) $(CXXFLAGS) -c -o llc-MCInstPrinter.o `test -f 'llvm/lib/MC/MCInstPrinter.cpp' || echo '$(srcdir)/'`llvm/lib/MC/MCInstPrinter.cpp + +llc-MCInstPrinter.obj: llvm/lib/MC/MCInstPrinter.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llc_CPPFLAGS) $(CPPFLAGS) $(llc_CXXFLAGS) $(CXXFLAGS) -MT llc-MCInstPrinter.obj -MD -MP -MF $(DEPDIR)/llc-MCInstPrinter.Tpo -c -o llc-MCInstPrinter.obj `if test -f 'llvm/lib/MC/MCInstPrinter.cpp'; then $(CYGPATH_W) 'llvm/lib/MC/MCInstPrinter.cpp'; else $(CYGPATH_W) '$(srcdir)/llvm/lib/MC/MCInstPrinter.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/llc-MCInstPrinter.Tpo $(DEPDIR)/llc-MCInstPrinter.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/MC/MCInstPrinter.cpp' object='llc-MCInstPrinter.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llc_CPPFLAGS) $(CPPFLAGS) $(llc_CXXFLAGS) $(CXXFLAGS) -c -o llc-MCInstPrinter.obj `if test -f 'llvm/lib/MC/MCInstPrinter.cpp'; then $(CYGPATH_W) 'llvm/lib/MC/MCInstPrinter.cpp'; else $(CYGPATH_W) '$(srcdir)/llvm/lib/MC/MCInstPrinter.cpp'; fi` + +llc-llc.o: llvm/tools/llc/llc.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llc_CPPFLAGS) $(CPPFLAGS) $(llc_CXXFLAGS) $(CXXFLAGS) -MT llc-llc.o -MD -MP -MF $(DEPDIR)/llc-llc.Tpo -c -o llc-llc.o `test -f 'llvm/tools/llc/llc.cpp' || echo '$(srcdir)/'`llvm/tools/llc/llc.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/llc-llc.Tpo $(DEPDIR)/llc-llc.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/tools/llc/llc.cpp' object='llc-llc.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llc_CPPFLAGS) $(CPPFLAGS) $(llc_CXXFLAGS) $(CXXFLAGS) -c -o llc-llc.o `test -f 'llvm/tools/llc/llc.cpp' || echo '$(srcdir)/'`llvm/tools/llc/llc.cpp + +llc-llc.obj: llvm/tools/llc/llc.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llc_CPPFLAGS) $(CPPFLAGS) $(llc_CXXFLAGS) $(CXXFLAGS) -MT llc-llc.obj -MD -MP -MF $(DEPDIR)/llc-llc.Tpo -c -o llc-llc.obj `if test -f 'llvm/tools/llc/llc.cpp'; then $(CYGPATH_W) 'llvm/tools/llc/llc.cpp'; else $(CYGPATH_W) '$(srcdir)/llvm/tools/llc/llc.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/llc-llc.Tpo $(DEPDIR)/llc-llc.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/tools/llc/llc.cpp' object='llc-llc.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llc_CPPFLAGS) $(CPPFLAGS) $(llc_CXXFLAGS) $(CXXFLAGS) -c -o llc-llc.obj `if test -f 'llvm/tools/llc/llc.cpp'; then $(CYGPATH_W) 'llvm/tools/llc/llc.cpp'; else $(CYGPATH_W) '$(srcdir)/llvm/tools/llc/llc.cpp'; fi` + +lli-OProfileJITEventListener.o: llvm/lib/ExecutionEngine/JIT/OProfileJITEventListener.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lli_CPPFLAGS) $(CPPFLAGS) $(lli_CXXFLAGS) $(CXXFLAGS) -MT lli-OProfileJITEventListener.o -MD -MP -MF $(DEPDIR)/lli-OProfileJITEventListener.Tpo -c -o lli-OProfileJITEventListener.o `test -f 'llvm/lib/ExecutionEngine/JIT/OProfileJITEventListener.cpp' || echo '$(srcdir)/'`llvm/lib/ExecutionEngine/JIT/OProfileJITEventListener.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/lli-OProfileJITEventListener.Tpo $(DEPDIR)/lli-OProfileJITEventListener.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/ExecutionEngine/JIT/OProfileJITEventListener.cpp' object='lli-OProfileJITEventListener.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lli_CPPFLAGS) $(CPPFLAGS) $(lli_CXXFLAGS) $(CXXFLAGS) -c -o lli-OProfileJITEventListener.o `test -f 'llvm/lib/ExecutionEngine/JIT/OProfileJITEventListener.cpp' || echo '$(srcdir)/'`llvm/lib/ExecutionEngine/JIT/OProfileJITEventListener.cpp + +lli-OProfileJITEventListener.obj: llvm/lib/ExecutionEngine/JIT/OProfileJITEventListener.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lli_CPPFLAGS) $(CPPFLAGS) $(lli_CXXFLAGS) $(CXXFLAGS) -MT lli-OProfileJITEventListener.obj -MD -MP -MF $(DEPDIR)/lli-OProfileJITEventListener.Tpo -c -o lli-OProfileJITEventListener.obj `if test -f 'llvm/lib/ExecutionEngine/JIT/OProfileJITEventListener.cpp'; then $(CYGPATH_W) 'llvm/lib/ExecutionEngine/JIT/OProfileJITEventListener.cpp'; else $(CYGPATH_W) '$(srcdir)/llvm/lib/ExecutionEngine/JIT/OProfileJITEventListener.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/lli-OProfileJITEventListener.Tpo $(DEPDIR)/lli-OProfileJITEventListener.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/ExecutionEngine/JIT/OProfileJITEventListener.cpp' object='lli-OProfileJITEventListener.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lli_CPPFLAGS) $(CPPFLAGS) $(lli_CXXFLAGS) $(CXXFLAGS) -c -o lli-OProfileJITEventListener.obj `if test -f 'llvm/lib/ExecutionEngine/JIT/OProfileJITEventListener.cpp'; then $(CYGPATH_W) 'llvm/lib/ExecutionEngine/JIT/OProfileJITEventListener.cpp'; else $(CYGPATH_W) '$(srcdir)/llvm/lib/ExecutionEngine/JIT/OProfileJITEventListener.cpp'; fi` + +lli-lli.o: llvm/tools/lli/lli.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lli_CPPFLAGS) $(CPPFLAGS) $(lli_CXXFLAGS) $(CXXFLAGS) -MT lli-lli.o -MD -MP -MF $(DEPDIR)/lli-lli.Tpo -c -o lli-lli.o `test -f 'llvm/tools/lli/lli.cpp' || echo '$(srcdir)/'`llvm/tools/lli/lli.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/lli-lli.Tpo $(DEPDIR)/lli-lli.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/tools/lli/lli.cpp' object='lli-lli.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lli_CPPFLAGS) $(CPPFLAGS) $(lli_CXXFLAGS) $(CXXFLAGS) -c -o lli-lli.o `test -f 'llvm/tools/lli/lli.cpp' || echo '$(srcdir)/'`llvm/tools/lli/lli.cpp + +lli-lli.obj: llvm/tools/lli/lli.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lli_CPPFLAGS) $(CPPFLAGS) $(lli_CXXFLAGS) $(CXXFLAGS) -MT lli-lli.obj -MD -MP -MF $(DEPDIR)/lli-lli.Tpo -c -o lli-lli.obj `if test -f 'llvm/tools/lli/lli.cpp'; then $(CYGPATH_W) 'llvm/tools/lli/lli.cpp'; else $(CYGPATH_W) '$(srcdir)/llvm/tools/lli/lli.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/lli-lli.Tpo $(DEPDIR)/lli-lli.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/tools/lli/lli.cpp' object='lli-lli.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lli_CPPFLAGS) $(CPPFLAGS) $(lli_CXXFLAGS) $(CXXFLAGS) -c -o lli-lli.obj `if test -f 'llvm/tools/lli/lli.cpp'; then $(CYGPATH_W) 'llvm/tools/lli/lli.cpp'; else $(CYGPATH_W) '$(srcdir)/llvm/tools/lli/lli.cpp'; fi` + +llvm_as-llvm-as.o: llvm/tools/llvm-as/llvm-as.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llvm_as_CPPFLAGS) $(CPPFLAGS) $(llvm_as_CXXFLAGS) $(CXXFLAGS) -MT llvm_as-llvm-as.o -MD -MP -MF $(DEPDIR)/llvm_as-llvm-as.Tpo -c -o llvm_as-llvm-as.o `test -f 'llvm/tools/llvm-as/llvm-as.cpp' || echo '$(srcdir)/'`llvm/tools/llvm-as/llvm-as.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/llvm_as-llvm-as.Tpo $(DEPDIR)/llvm_as-llvm-as.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/tools/llvm-as/llvm-as.cpp' object='llvm_as-llvm-as.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llvm_as_CPPFLAGS) $(CPPFLAGS) $(llvm_as_CXXFLAGS) $(CXXFLAGS) -c -o llvm_as-llvm-as.o `test -f 'llvm/tools/llvm-as/llvm-as.cpp' || echo '$(srcdir)/'`llvm/tools/llvm-as/llvm-as.cpp + +llvm_as-llvm-as.obj: llvm/tools/llvm-as/llvm-as.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llvm_as_CPPFLAGS) $(CPPFLAGS) $(llvm_as_CXXFLAGS) $(CXXFLAGS) -MT llvm_as-llvm-as.obj -MD -MP -MF $(DEPDIR)/llvm_as-llvm-as.Tpo -c -o llvm_as-llvm-as.obj `if test -f 'llvm/tools/llvm-as/llvm-as.cpp'; then $(CYGPATH_W) 'llvm/tools/llvm-as/llvm-as.cpp'; else $(CYGPATH_W) '$(srcdir)/llvm/tools/llvm-as/llvm-as.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/llvm_as-llvm-as.Tpo $(DEPDIR)/llvm_as-llvm-as.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/tools/llvm-as/llvm-as.cpp' object='llvm_as-llvm-as.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llvm_as_CPPFLAGS) $(CPPFLAGS) $(llvm_as_CXXFLAGS) $(CXXFLAGS) -c -o llvm_as-llvm-as.obj `if test -f 'llvm/tools/llvm-as/llvm-as.cpp'; then $(CYGPATH_W) 'llvm/tools/llvm-as/llvm-as.cpp'; else $(CYGPATH_W) '$(srcdir)/llvm/tools/llvm-as/llvm-as.cpp'; fi` + +llvm_dis-llvm-dis.o: llvm/tools/llvm-dis/llvm-dis.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llvm_dis_CPPFLAGS) $(CPPFLAGS) $(llvm_dis_CXXFLAGS) $(CXXFLAGS) -MT llvm_dis-llvm-dis.o -MD -MP -MF $(DEPDIR)/llvm_dis-llvm-dis.Tpo -c -o llvm_dis-llvm-dis.o `test -f 'llvm/tools/llvm-dis/llvm-dis.cpp' || echo '$(srcdir)/'`llvm/tools/llvm-dis/llvm-dis.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/llvm_dis-llvm-dis.Tpo $(DEPDIR)/llvm_dis-llvm-dis.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/tools/llvm-dis/llvm-dis.cpp' object='llvm_dis-llvm-dis.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llvm_dis_CPPFLAGS) $(CPPFLAGS) $(llvm_dis_CXXFLAGS) $(CXXFLAGS) -c -o llvm_dis-llvm-dis.o `test -f 'llvm/tools/llvm-dis/llvm-dis.cpp' || echo '$(srcdir)/'`llvm/tools/llvm-dis/llvm-dis.cpp + +llvm_dis-llvm-dis.obj: llvm/tools/llvm-dis/llvm-dis.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llvm_dis_CPPFLAGS) $(CPPFLAGS) $(llvm_dis_CXXFLAGS) $(CXXFLAGS) -MT llvm_dis-llvm-dis.obj -MD -MP -MF $(DEPDIR)/llvm_dis-llvm-dis.Tpo -c -o llvm_dis-llvm-dis.obj `if test -f 'llvm/tools/llvm-dis/llvm-dis.cpp'; then $(CYGPATH_W) 'llvm/tools/llvm-dis/llvm-dis.cpp'; else $(CYGPATH_W) '$(srcdir)/llvm/tools/llvm-dis/llvm-dis.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/llvm_dis-llvm-dis.Tpo $(DEPDIR)/llvm_dis-llvm-dis.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/tools/llvm-dis/llvm-dis.cpp' object='llvm_dis-llvm-dis.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llvm_dis_CPPFLAGS) $(CPPFLAGS) $(llvm_dis_CXXFLAGS) $(CXXFLAGS) -c -o llvm_dis-llvm-dis.obj `if test -f 'llvm/tools/llvm-dis/llvm-dis.cpp'; then $(CYGPATH_W) 'llvm/tools/llvm-dis/llvm-dis.cpp'; else $(CYGPATH_W) '$(srcdir)/llvm/tools/llvm-dis/llvm-dis.cpp'; fi` + +llvmunittest_ADT-APFloatTest.o: llvm/unittests/ADT/APFloatTest.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llvmunittest_ADT_CPPFLAGS) $(CPPFLAGS) $(llvmunittest_ADT_CXXFLAGS) $(CXXFLAGS) -MT llvmunittest_ADT-APFloatTest.o -MD -MP -MF $(DEPDIR)/llvmunittest_ADT-APFloatTest.Tpo -c -o llvmunittest_ADT-APFloatTest.o `test -f 'llvm/unittests/ADT/APFloatTest.cpp' || echo '$(srcdir)/'`llvm/unittests/ADT/APFloatTest.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/llvmunittest_ADT-APFloatTest.Tpo $(DEPDIR)/llvmunittest_ADT-APFloatTest.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/unittests/ADT/APFloatTest.cpp' object='llvmunittest_ADT-APFloatTest.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llvmunittest_ADT_CPPFLAGS) $(CPPFLAGS) $(llvmunittest_ADT_CXXFLAGS) $(CXXFLAGS) -c -o llvmunittest_ADT-APFloatTest.o `test -f 'llvm/unittests/ADT/APFloatTest.cpp' || echo '$(srcdir)/'`llvm/unittests/ADT/APFloatTest.cpp + +llvmunittest_ADT-APFloatTest.obj: llvm/unittests/ADT/APFloatTest.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llvmunittest_ADT_CPPFLAGS) $(CPPFLAGS) $(llvmunittest_ADT_CXXFLAGS) $(CXXFLAGS) -MT llvmunittest_ADT-APFloatTest.obj -MD -MP -MF $(DEPDIR)/llvmunittest_ADT-APFloatTest.Tpo -c -o llvmunittest_ADT-APFloatTest.obj `if test -f 'llvm/unittests/ADT/APFloatTest.cpp'; then $(CYGPATH_W) 'llvm/unittests/ADT/APFloatTest.cpp'; else $(CYGPATH_W) '$(srcdir)/llvm/unittests/ADT/APFloatTest.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/llvmunittest_ADT-APFloatTest.Tpo $(DEPDIR)/llvmunittest_ADT-APFloatTest.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/unittests/ADT/APFloatTest.cpp' object='llvmunittest_ADT-APFloatTest.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llvmunittest_ADT_CPPFLAGS) $(CPPFLAGS) $(llvmunittest_ADT_CXXFLAGS) $(CXXFLAGS) -c -o llvmunittest_ADT-APFloatTest.obj `if test -f 'llvm/unittests/ADT/APFloatTest.cpp'; then $(CYGPATH_W) 'llvm/unittests/ADT/APFloatTest.cpp'; else $(CYGPATH_W) '$(srcdir)/llvm/unittests/ADT/APFloatTest.cpp'; fi` + +llvmunittest_ADT-APIntTest.o: llvm/unittests/ADT/APIntTest.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llvmunittest_ADT_CPPFLAGS) $(CPPFLAGS) $(llvmunittest_ADT_CXXFLAGS) $(CXXFLAGS) -MT llvmunittest_ADT-APIntTest.o -MD -MP -MF $(DEPDIR)/llvmunittest_ADT-APIntTest.Tpo -c -o llvmunittest_ADT-APIntTest.o `test -f 'llvm/unittests/ADT/APIntTest.cpp' || echo '$(srcdir)/'`llvm/unittests/ADT/APIntTest.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/llvmunittest_ADT-APIntTest.Tpo $(DEPDIR)/llvmunittest_ADT-APIntTest.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/unittests/ADT/APIntTest.cpp' object='llvmunittest_ADT-APIntTest.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llvmunittest_ADT_CPPFLAGS) $(CPPFLAGS) $(llvmunittest_ADT_CXXFLAGS) $(CXXFLAGS) -c -o llvmunittest_ADT-APIntTest.o `test -f 'llvm/unittests/ADT/APIntTest.cpp' || echo '$(srcdir)/'`llvm/unittests/ADT/APIntTest.cpp + +llvmunittest_ADT-APIntTest.obj: llvm/unittests/ADT/APIntTest.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llvmunittest_ADT_CPPFLAGS) $(CPPFLAGS) $(llvmunittest_ADT_CXXFLAGS) $(CXXFLAGS) -MT llvmunittest_ADT-APIntTest.obj -MD -MP -MF $(DEPDIR)/llvmunittest_ADT-APIntTest.Tpo -c -o llvmunittest_ADT-APIntTest.obj `if test -f 'llvm/unittests/ADT/APIntTest.cpp'; then $(CYGPATH_W) 'llvm/unittests/ADT/APIntTest.cpp'; else $(CYGPATH_W) '$(srcdir)/llvm/unittests/ADT/APIntTest.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/llvmunittest_ADT-APIntTest.Tpo $(DEPDIR)/llvmunittest_ADT-APIntTest.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/unittests/ADT/APIntTest.cpp' object='llvmunittest_ADT-APIntTest.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llvmunittest_ADT_CPPFLAGS) $(CPPFLAGS) $(llvmunittest_ADT_CXXFLAGS) $(CXXFLAGS) -c -o llvmunittest_ADT-APIntTest.obj `if test -f 'llvm/unittests/ADT/APIntTest.cpp'; then $(CYGPATH_W) 'llvm/unittests/ADT/APIntTest.cpp'; else $(CYGPATH_W) '$(srcdir)/llvm/unittests/ADT/APIntTest.cpp'; fi` + +llvmunittest_ADT-DenseMapTest.o: llvm/unittests/ADT/DenseMapTest.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llvmunittest_ADT_CPPFLAGS) $(CPPFLAGS) $(llvmunittest_ADT_CXXFLAGS) $(CXXFLAGS) -MT llvmunittest_ADT-DenseMapTest.o -MD -MP -MF $(DEPDIR)/llvmunittest_ADT-DenseMapTest.Tpo -c -o llvmunittest_ADT-DenseMapTest.o `test -f 'llvm/unittests/ADT/DenseMapTest.cpp' || echo '$(srcdir)/'`llvm/unittests/ADT/DenseMapTest.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/llvmunittest_ADT-DenseMapTest.Tpo $(DEPDIR)/llvmunittest_ADT-DenseMapTest.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/unittests/ADT/DenseMapTest.cpp' object='llvmunittest_ADT-DenseMapTest.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llvmunittest_ADT_CPPFLAGS) $(CPPFLAGS) $(llvmunittest_ADT_CXXFLAGS) $(CXXFLAGS) -c -o llvmunittest_ADT-DenseMapTest.o `test -f 'llvm/unittests/ADT/DenseMapTest.cpp' || echo '$(srcdir)/'`llvm/unittests/ADT/DenseMapTest.cpp + +llvmunittest_ADT-DenseMapTest.obj: llvm/unittests/ADT/DenseMapTest.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llvmunittest_ADT_CPPFLAGS) $(CPPFLAGS) $(llvmunittest_ADT_CXXFLAGS) $(CXXFLAGS) -MT llvmunittest_ADT-DenseMapTest.obj -MD -MP -MF $(DEPDIR)/llvmunittest_ADT-DenseMapTest.Tpo -c -o llvmunittest_ADT-DenseMapTest.obj `if test -f 'llvm/unittests/ADT/DenseMapTest.cpp'; then $(CYGPATH_W) 'llvm/unittests/ADT/DenseMapTest.cpp'; else $(CYGPATH_W) '$(srcdir)/llvm/unittests/ADT/DenseMapTest.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/llvmunittest_ADT-DenseMapTest.Tpo $(DEPDIR)/llvmunittest_ADT-DenseMapTest.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/unittests/ADT/DenseMapTest.cpp' object='llvmunittest_ADT-DenseMapTest.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llvmunittest_ADT_CPPFLAGS) $(CPPFLAGS) $(llvmunittest_ADT_CXXFLAGS) $(CXXFLAGS) -c -o llvmunittest_ADT-DenseMapTest.obj `if test -f 'llvm/unittests/ADT/DenseMapTest.cpp'; then $(CYGPATH_W) 'llvm/unittests/ADT/DenseMapTest.cpp'; else $(CYGPATH_W) '$(srcdir)/llvm/unittests/ADT/DenseMapTest.cpp'; fi` + +llvmunittest_ADT-DenseSetTest.o: llvm/unittests/ADT/DenseSetTest.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llvmunittest_ADT_CPPFLAGS) $(CPPFLAGS) $(llvmunittest_ADT_CXXFLAGS) $(CXXFLAGS) -MT llvmunittest_ADT-DenseSetTest.o -MD -MP -MF $(DEPDIR)/llvmunittest_ADT-DenseSetTest.Tpo -c -o llvmunittest_ADT-DenseSetTest.o `test -f 'llvm/unittests/ADT/DenseSetTest.cpp' || echo '$(srcdir)/'`llvm/unittests/ADT/DenseSetTest.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/llvmunittest_ADT-DenseSetTest.Tpo $(DEPDIR)/llvmunittest_ADT-DenseSetTest.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/unittests/ADT/DenseSetTest.cpp' object='llvmunittest_ADT-DenseSetTest.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llvmunittest_ADT_CPPFLAGS) $(CPPFLAGS) $(llvmunittest_ADT_CXXFLAGS) $(CXXFLAGS) -c -o llvmunittest_ADT-DenseSetTest.o `test -f 'llvm/unittests/ADT/DenseSetTest.cpp' || echo '$(srcdir)/'`llvm/unittests/ADT/DenseSetTest.cpp + +llvmunittest_ADT-DenseSetTest.obj: llvm/unittests/ADT/DenseSetTest.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llvmunittest_ADT_CPPFLAGS) $(CPPFLAGS) $(llvmunittest_ADT_CXXFLAGS) $(CXXFLAGS) -MT llvmunittest_ADT-DenseSetTest.obj -MD -MP -MF $(DEPDIR)/llvmunittest_ADT-DenseSetTest.Tpo -c -o llvmunittest_ADT-DenseSetTest.obj `if test -f 'llvm/unittests/ADT/DenseSetTest.cpp'; then $(CYGPATH_W) 'llvm/unittests/ADT/DenseSetTest.cpp'; else $(CYGPATH_W) '$(srcdir)/llvm/unittests/ADT/DenseSetTest.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/llvmunittest_ADT-DenseSetTest.Tpo $(DEPDIR)/llvmunittest_ADT-DenseSetTest.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/unittests/ADT/DenseSetTest.cpp' object='llvmunittest_ADT-DenseSetTest.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llvmunittest_ADT_CPPFLAGS) $(CPPFLAGS) $(llvmunittest_ADT_CXXFLAGS) $(CXXFLAGS) -c -o llvmunittest_ADT-DenseSetTest.obj `if test -f 'llvm/unittests/ADT/DenseSetTest.cpp'; then $(CYGPATH_W) 'llvm/unittests/ADT/DenseSetTest.cpp'; else $(CYGPATH_W) '$(srcdir)/llvm/unittests/ADT/DenseSetTest.cpp'; fi` + +llvmunittest_ADT-ImmutableSetTest.o: llvm/unittests/ADT/ImmutableSetTest.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llvmunittest_ADT_CPPFLAGS) $(CPPFLAGS) $(llvmunittest_ADT_CXXFLAGS) $(CXXFLAGS) -MT llvmunittest_ADT-ImmutableSetTest.o -MD -MP -MF $(DEPDIR)/llvmunittest_ADT-ImmutableSetTest.Tpo -c -o llvmunittest_ADT-ImmutableSetTest.o `test -f 'llvm/unittests/ADT/ImmutableSetTest.cpp' || echo '$(srcdir)/'`llvm/unittests/ADT/ImmutableSetTest.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/llvmunittest_ADT-ImmutableSetTest.Tpo $(DEPDIR)/llvmunittest_ADT-ImmutableSetTest.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/unittests/ADT/ImmutableSetTest.cpp' object='llvmunittest_ADT-ImmutableSetTest.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llvmunittest_ADT_CPPFLAGS) $(CPPFLAGS) $(llvmunittest_ADT_CXXFLAGS) $(CXXFLAGS) -c -o llvmunittest_ADT-ImmutableSetTest.o `test -f 'llvm/unittests/ADT/ImmutableSetTest.cpp' || echo '$(srcdir)/'`llvm/unittests/ADT/ImmutableSetTest.cpp + +llvmunittest_ADT-ImmutableSetTest.obj: llvm/unittests/ADT/ImmutableSetTest.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llvmunittest_ADT_CPPFLAGS) $(CPPFLAGS) $(llvmunittest_ADT_CXXFLAGS) $(CXXFLAGS) -MT llvmunittest_ADT-ImmutableSetTest.obj -MD -MP -MF $(DEPDIR)/llvmunittest_ADT-ImmutableSetTest.Tpo -c -o llvmunittest_ADT-ImmutableSetTest.obj `if test -f 'llvm/unittests/ADT/ImmutableSetTest.cpp'; then $(CYGPATH_W) 'llvm/unittests/ADT/ImmutableSetTest.cpp'; else $(CYGPATH_W) '$(srcdir)/llvm/unittests/ADT/ImmutableSetTest.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/llvmunittest_ADT-ImmutableSetTest.Tpo $(DEPDIR)/llvmunittest_ADT-ImmutableSetTest.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/unittests/ADT/ImmutableSetTest.cpp' object='llvmunittest_ADT-ImmutableSetTest.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llvmunittest_ADT_CPPFLAGS) $(CPPFLAGS) $(llvmunittest_ADT_CXXFLAGS) $(CXXFLAGS) -c -o llvmunittest_ADT-ImmutableSetTest.obj `if test -f 'llvm/unittests/ADT/ImmutableSetTest.cpp'; then $(CYGPATH_W) 'llvm/unittests/ADT/ImmutableSetTest.cpp'; else $(CYGPATH_W) '$(srcdir)/llvm/unittests/ADT/ImmutableSetTest.cpp'; fi` + +llvmunittest_ADT-SmallStringTest.o: llvm/unittests/ADT/SmallStringTest.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llvmunittest_ADT_CPPFLAGS) $(CPPFLAGS) $(llvmunittest_ADT_CXXFLAGS) $(CXXFLAGS) -MT llvmunittest_ADT-SmallStringTest.o -MD -MP -MF $(DEPDIR)/llvmunittest_ADT-SmallStringTest.Tpo -c -o llvmunittest_ADT-SmallStringTest.o `test -f 'llvm/unittests/ADT/SmallStringTest.cpp' || echo '$(srcdir)/'`llvm/unittests/ADT/SmallStringTest.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/llvmunittest_ADT-SmallStringTest.Tpo $(DEPDIR)/llvmunittest_ADT-SmallStringTest.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/unittests/ADT/SmallStringTest.cpp' object='llvmunittest_ADT-SmallStringTest.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llvmunittest_ADT_CPPFLAGS) $(CPPFLAGS) $(llvmunittest_ADT_CXXFLAGS) $(CXXFLAGS) -c -o llvmunittest_ADT-SmallStringTest.o `test -f 'llvm/unittests/ADT/SmallStringTest.cpp' || echo '$(srcdir)/'`llvm/unittests/ADT/SmallStringTest.cpp + +llvmunittest_ADT-SmallStringTest.obj: llvm/unittests/ADT/SmallStringTest.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llvmunittest_ADT_CPPFLAGS) $(CPPFLAGS) $(llvmunittest_ADT_CXXFLAGS) $(CXXFLAGS) -MT llvmunittest_ADT-SmallStringTest.obj -MD -MP -MF $(DEPDIR)/llvmunittest_ADT-SmallStringTest.Tpo -c -o llvmunittest_ADT-SmallStringTest.obj `if test -f 'llvm/unittests/ADT/SmallStringTest.cpp'; then $(CYGPATH_W) 'llvm/unittests/ADT/SmallStringTest.cpp'; else $(CYGPATH_W) '$(srcdir)/llvm/unittests/ADT/SmallStringTest.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/llvmunittest_ADT-SmallStringTest.Tpo $(DEPDIR)/llvmunittest_ADT-SmallStringTest.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/unittests/ADT/SmallStringTest.cpp' object='llvmunittest_ADT-SmallStringTest.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llvmunittest_ADT_CPPFLAGS) $(CPPFLAGS) $(llvmunittest_ADT_CXXFLAGS) $(CXXFLAGS) -c -o llvmunittest_ADT-SmallStringTest.obj `if test -f 'llvm/unittests/ADT/SmallStringTest.cpp'; then $(CYGPATH_W) 'llvm/unittests/ADT/SmallStringTest.cpp'; else $(CYGPATH_W) '$(srcdir)/llvm/unittests/ADT/SmallStringTest.cpp'; fi` + +llvmunittest_ADT-SmallVectorTest.o: llvm/unittests/ADT/SmallVectorTest.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llvmunittest_ADT_CPPFLAGS) $(CPPFLAGS) $(llvmunittest_ADT_CXXFLAGS) $(CXXFLAGS) -MT llvmunittest_ADT-SmallVectorTest.o -MD -MP -MF $(DEPDIR)/llvmunittest_ADT-SmallVectorTest.Tpo -c -o llvmunittest_ADT-SmallVectorTest.o `test -f 'llvm/unittests/ADT/SmallVectorTest.cpp' || echo '$(srcdir)/'`llvm/unittests/ADT/SmallVectorTest.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/llvmunittest_ADT-SmallVectorTest.Tpo $(DEPDIR)/llvmunittest_ADT-SmallVectorTest.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/unittests/ADT/SmallVectorTest.cpp' object='llvmunittest_ADT-SmallVectorTest.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llvmunittest_ADT_CPPFLAGS) $(CPPFLAGS) $(llvmunittest_ADT_CXXFLAGS) $(CXXFLAGS) -c -o llvmunittest_ADT-SmallVectorTest.o `test -f 'llvm/unittests/ADT/SmallVectorTest.cpp' || echo '$(srcdir)/'`llvm/unittests/ADT/SmallVectorTest.cpp + +llvmunittest_ADT-SmallVectorTest.obj: llvm/unittests/ADT/SmallVectorTest.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llvmunittest_ADT_CPPFLAGS) $(CPPFLAGS) $(llvmunittest_ADT_CXXFLAGS) $(CXXFLAGS) -MT llvmunittest_ADT-SmallVectorTest.obj -MD -MP -MF $(DEPDIR)/llvmunittest_ADT-SmallVectorTest.Tpo -c -o llvmunittest_ADT-SmallVectorTest.obj `if test -f 'llvm/unittests/ADT/SmallVectorTest.cpp'; then $(CYGPATH_W) 'llvm/unittests/ADT/SmallVectorTest.cpp'; else $(CYGPATH_W) '$(srcdir)/llvm/unittests/ADT/SmallVectorTest.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/llvmunittest_ADT-SmallVectorTest.Tpo $(DEPDIR)/llvmunittest_ADT-SmallVectorTest.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/unittests/ADT/SmallVectorTest.cpp' object='llvmunittest_ADT-SmallVectorTest.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llvmunittest_ADT_CPPFLAGS) $(CPPFLAGS) $(llvmunittest_ADT_CXXFLAGS) $(CXXFLAGS) -c -o llvmunittest_ADT-SmallVectorTest.obj `if test -f 'llvm/unittests/ADT/SmallVectorTest.cpp'; then $(CYGPATH_W) 'llvm/unittests/ADT/SmallVectorTest.cpp'; else $(CYGPATH_W) '$(srcdir)/llvm/unittests/ADT/SmallVectorTest.cpp'; fi` + +llvmunittest_ADT-SparseBitVectorTest.o: llvm/unittests/ADT/SparseBitVectorTest.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llvmunittest_ADT_CPPFLAGS) $(CPPFLAGS) $(llvmunittest_ADT_CXXFLAGS) $(CXXFLAGS) -MT llvmunittest_ADT-SparseBitVectorTest.o -MD -MP -MF $(DEPDIR)/llvmunittest_ADT-SparseBitVectorTest.Tpo -c -o llvmunittest_ADT-SparseBitVectorTest.o `test -f 'llvm/unittests/ADT/SparseBitVectorTest.cpp' || echo '$(srcdir)/'`llvm/unittests/ADT/SparseBitVectorTest.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/llvmunittest_ADT-SparseBitVectorTest.Tpo $(DEPDIR)/llvmunittest_ADT-SparseBitVectorTest.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/unittests/ADT/SparseBitVectorTest.cpp' object='llvmunittest_ADT-SparseBitVectorTest.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llvmunittest_ADT_CPPFLAGS) $(CPPFLAGS) $(llvmunittest_ADT_CXXFLAGS) $(CXXFLAGS) -c -o llvmunittest_ADT-SparseBitVectorTest.o `test -f 'llvm/unittests/ADT/SparseBitVectorTest.cpp' || echo '$(srcdir)/'`llvm/unittests/ADT/SparseBitVectorTest.cpp + +llvmunittest_ADT-SparseBitVectorTest.obj: llvm/unittests/ADT/SparseBitVectorTest.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llvmunittest_ADT_CPPFLAGS) $(CPPFLAGS) $(llvmunittest_ADT_CXXFLAGS) $(CXXFLAGS) -MT llvmunittest_ADT-SparseBitVectorTest.obj -MD -MP -MF $(DEPDIR)/llvmunittest_ADT-SparseBitVectorTest.Tpo -c -o llvmunittest_ADT-SparseBitVectorTest.obj `if test -f 'llvm/unittests/ADT/SparseBitVectorTest.cpp'; then $(CYGPATH_W) 'llvm/unittests/ADT/SparseBitVectorTest.cpp'; else $(CYGPATH_W) '$(srcdir)/llvm/unittests/ADT/SparseBitVectorTest.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/llvmunittest_ADT-SparseBitVectorTest.Tpo $(DEPDIR)/llvmunittest_ADT-SparseBitVectorTest.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/unittests/ADT/SparseBitVectorTest.cpp' object='llvmunittest_ADT-SparseBitVectorTest.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llvmunittest_ADT_CPPFLAGS) $(CPPFLAGS) $(llvmunittest_ADT_CXXFLAGS) $(CXXFLAGS) -c -o llvmunittest_ADT-SparseBitVectorTest.obj `if test -f 'llvm/unittests/ADT/SparseBitVectorTest.cpp'; then $(CYGPATH_W) 'llvm/unittests/ADT/SparseBitVectorTest.cpp'; else $(CYGPATH_W) '$(srcdir)/llvm/unittests/ADT/SparseBitVectorTest.cpp'; fi` + +llvmunittest_ADT-StringMapTest.o: llvm/unittests/ADT/StringMapTest.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llvmunittest_ADT_CPPFLAGS) $(CPPFLAGS) $(llvmunittest_ADT_CXXFLAGS) $(CXXFLAGS) -MT llvmunittest_ADT-StringMapTest.o -MD -MP -MF $(DEPDIR)/llvmunittest_ADT-StringMapTest.Tpo -c -o llvmunittest_ADT-StringMapTest.o `test -f 'llvm/unittests/ADT/StringMapTest.cpp' || echo '$(srcdir)/'`llvm/unittests/ADT/StringMapTest.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/llvmunittest_ADT-StringMapTest.Tpo $(DEPDIR)/llvmunittest_ADT-StringMapTest.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/unittests/ADT/StringMapTest.cpp' object='llvmunittest_ADT-StringMapTest.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llvmunittest_ADT_CPPFLAGS) $(CPPFLAGS) $(llvmunittest_ADT_CXXFLAGS) $(CXXFLAGS) -c -o llvmunittest_ADT-StringMapTest.o `test -f 'llvm/unittests/ADT/StringMapTest.cpp' || echo '$(srcdir)/'`llvm/unittests/ADT/StringMapTest.cpp + +llvmunittest_ADT-StringMapTest.obj: llvm/unittests/ADT/StringMapTest.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llvmunittest_ADT_CPPFLAGS) $(CPPFLAGS) $(llvmunittest_ADT_CXXFLAGS) $(CXXFLAGS) -MT llvmunittest_ADT-StringMapTest.obj -MD -MP -MF $(DEPDIR)/llvmunittest_ADT-StringMapTest.Tpo -c -o llvmunittest_ADT-StringMapTest.obj `if test -f 'llvm/unittests/ADT/StringMapTest.cpp'; then $(CYGPATH_W) 'llvm/unittests/ADT/StringMapTest.cpp'; else $(CYGPATH_W) '$(srcdir)/llvm/unittests/ADT/StringMapTest.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/llvmunittest_ADT-StringMapTest.Tpo $(DEPDIR)/llvmunittest_ADT-StringMapTest.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/unittests/ADT/StringMapTest.cpp' object='llvmunittest_ADT-StringMapTest.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llvmunittest_ADT_CPPFLAGS) $(CPPFLAGS) $(llvmunittest_ADT_CXXFLAGS) $(CXXFLAGS) -c -o llvmunittest_ADT-StringMapTest.obj `if test -f 'llvm/unittests/ADT/StringMapTest.cpp'; then $(CYGPATH_W) 'llvm/unittests/ADT/StringMapTest.cpp'; else $(CYGPATH_W) '$(srcdir)/llvm/unittests/ADT/StringMapTest.cpp'; fi` + +llvmunittest_ADT-StringRefTest.o: llvm/unittests/ADT/StringRefTest.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llvmunittest_ADT_CPPFLAGS) $(CPPFLAGS) $(llvmunittest_ADT_CXXFLAGS) $(CXXFLAGS) -MT llvmunittest_ADT-StringRefTest.o -MD -MP -MF $(DEPDIR)/llvmunittest_ADT-StringRefTest.Tpo -c -o llvmunittest_ADT-StringRefTest.o `test -f 'llvm/unittests/ADT/StringRefTest.cpp' || echo '$(srcdir)/'`llvm/unittests/ADT/StringRefTest.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/llvmunittest_ADT-StringRefTest.Tpo $(DEPDIR)/llvmunittest_ADT-StringRefTest.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/unittests/ADT/StringRefTest.cpp' object='llvmunittest_ADT-StringRefTest.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llvmunittest_ADT_CPPFLAGS) $(CPPFLAGS) $(llvmunittest_ADT_CXXFLAGS) $(CXXFLAGS) -c -o llvmunittest_ADT-StringRefTest.o `test -f 'llvm/unittests/ADT/StringRefTest.cpp' || echo '$(srcdir)/'`llvm/unittests/ADT/StringRefTest.cpp + +llvmunittest_ADT-StringRefTest.obj: llvm/unittests/ADT/StringRefTest.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llvmunittest_ADT_CPPFLAGS) $(CPPFLAGS) $(llvmunittest_ADT_CXXFLAGS) $(CXXFLAGS) -MT llvmunittest_ADT-StringRefTest.obj -MD -MP -MF $(DEPDIR)/llvmunittest_ADT-StringRefTest.Tpo -c -o llvmunittest_ADT-StringRefTest.obj `if test -f 'llvm/unittests/ADT/StringRefTest.cpp'; then $(CYGPATH_W) 'llvm/unittests/ADT/StringRefTest.cpp'; else $(CYGPATH_W) '$(srcdir)/llvm/unittests/ADT/StringRefTest.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/llvmunittest_ADT-StringRefTest.Tpo $(DEPDIR)/llvmunittest_ADT-StringRefTest.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/unittests/ADT/StringRefTest.cpp' object='llvmunittest_ADT-StringRefTest.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llvmunittest_ADT_CPPFLAGS) $(CPPFLAGS) $(llvmunittest_ADT_CXXFLAGS) $(CXXFLAGS) -c -o llvmunittest_ADT-StringRefTest.obj `if test -f 'llvm/unittests/ADT/StringRefTest.cpp'; then $(CYGPATH_W) 'llvm/unittests/ADT/StringRefTest.cpp'; else $(CYGPATH_W) '$(srcdir)/llvm/unittests/ADT/StringRefTest.cpp'; fi` + +llvmunittest_ADT-TripleTest.o: llvm/unittests/ADT/TripleTest.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llvmunittest_ADT_CPPFLAGS) $(CPPFLAGS) $(llvmunittest_ADT_CXXFLAGS) $(CXXFLAGS) -MT llvmunittest_ADT-TripleTest.o -MD -MP -MF $(DEPDIR)/llvmunittest_ADT-TripleTest.Tpo -c -o llvmunittest_ADT-TripleTest.o `test -f 'llvm/unittests/ADT/TripleTest.cpp' || echo '$(srcdir)/'`llvm/unittests/ADT/TripleTest.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/llvmunittest_ADT-TripleTest.Tpo $(DEPDIR)/llvmunittest_ADT-TripleTest.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/unittests/ADT/TripleTest.cpp' object='llvmunittest_ADT-TripleTest.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llvmunittest_ADT_CPPFLAGS) $(CPPFLAGS) $(llvmunittest_ADT_CXXFLAGS) $(CXXFLAGS) -c -o llvmunittest_ADT-TripleTest.o `test -f 'llvm/unittests/ADT/TripleTest.cpp' || echo '$(srcdir)/'`llvm/unittests/ADT/TripleTest.cpp + +llvmunittest_ADT-TripleTest.obj: llvm/unittests/ADT/TripleTest.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llvmunittest_ADT_CPPFLAGS) $(CPPFLAGS) $(llvmunittest_ADT_CXXFLAGS) $(CXXFLAGS) -MT llvmunittest_ADT-TripleTest.obj -MD -MP -MF $(DEPDIR)/llvmunittest_ADT-TripleTest.Tpo -c -o llvmunittest_ADT-TripleTest.obj `if test -f 'llvm/unittests/ADT/TripleTest.cpp'; then $(CYGPATH_W) 'llvm/unittests/ADT/TripleTest.cpp'; else $(CYGPATH_W) '$(srcdir)/llvm/unittests/ADT/TripleTest.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/llvmunittest_ADT-TripleTest.Tpo $(DEPDIR)/llvmunittest_ADT-TripleTest.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/unittests/ADT/TripleTest.cpp' object='llvmunittest_ADT-TripleTest.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llvmunittest_ADT_CPPFLAGS) $(CPPFLAGS) $(llvmunittest_ADT_CXXFLAGS) $(CXXFLAGS) -c -o llvmunittest_ADT-TripleTest.obj `if test -f 'llvm/unittests/ADT/TripleTest.cpp'; then $(CYGPATH_W) 'llvm/unittests/ADT/TripleTest.cpp'; else $(CYGPATH_W) '$(srcdir)/llvm/unittests/ADT/TripleTest.cpp'; fi` + +llvmunittest_ADT-TwineTest.o: llvm/unittests/ADT/TwineTest.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llvmunittest_ADT_CPPFLAGS) $(CPPFLAGS) $(llvmunittest_ADT_CXXFLAGS) $(CXXFLAGS) -MT llvmunittest_ADT-TwineTest.o -MD -MP -MF $(DEPDIR)/llvmunittest_ADT-TwineTest.Tpo -c -o llvmunittest_ADT-TwineTest.o `test -f 'llvm/unittests/ADT/TwineTest.cpp' || echo '$(srcdir)/'`llvm/unittests/ADT/TwineTest.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/llvmunittest_ADT-TwineTest.Tpo $(DEPDIR)/llvmunittest_ADT-TwineTest.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/unittests/ADT/TwineTest.cpp' object='llvmunittest_ADT-TwineTest.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llvmunittest_ADT_CPPFLAGS) $(CPPFLAGS) $(llvmunittest_ADT_CXXFLAGS) $(CXXFLAGS) -c -o llvmunittest_ADT-TwineTest.o `test -f 'llvm/unittests/ADT/TwineTest.cpp' || echo '$(srcdir)/'`llvm/unittests/ADT/TwineTest.cpp + +llvmunittest_ADT-TwineTest.obj: llvm/unittests/ADT/TwineTest.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llvmunittest_ADT_CPPFLAGS) $(CPPFLAGS) $(llvmunittest_ADT_CXXFLAGS) $(CXXFLAGS) -MT llvmunittest_ADT-TwineTest.obj -MD -MP -MF $(DEPDIR)/llvmunittest_ADT-TwineTest.Tpo -c -o llvmunittest_ADT-TwineTest.obj `if test -f 'llvm/unittests/ADT/TwineTest.cpp'; then $(CYGPATH_W) 'llvm/unittests/ADT/TwineTest.cpp'; else $(CYGPATH_W) '$(srcdir)/llvm/unittests/ADT/TwineTest.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/llvmunittest_ADT-TwineTest.Tpo $(DEPDIR)/llvmunittest_ADT-TwineTest.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/unittests/ADT/TwineTest.cpp' object='llvmunittest_ADT-TwineTest.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llvmunittest_ADT_CPPFLAGS) $(CPPFLAGS) $(llvmunittest_ADT_CXXFLAGS) $(CXXFLAGS) -c -o llvmunittest_ADT-TwineTest.obj `if test -f 'llvm/unittests/ADT/TwineTest.cpp'; then $(CYGPATH_W) 'llvm/unittests/ADT/TwineTest.cpp'; else $(CYGPATH_W) '$(srcdir)/llvm/unittests/ADT/TwineTest.cpp'; fi` + +llvmunittest_ExecutionEngine-ExecutionEngineTest.o: llvm/unittests/ExecutionEngine/ExecutionEngineTest.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llvmunittest_ExecutionEngine_CPPFLAGS) $(CPPFLAGS) $(llvmunittest_ExecutionEngine_CXXFLAGS) $(CXXFLAGS) -MT llvmunittest_ExecutionEngine-ExecutionEngineTest.o -MD -MP -MF $(DEPDIR)/llvmunittest_ExecutionEngine-ExecutionEngineTest.Tpo -c -o llvmunittest_ExecutionEngine-ExecutionEngineTest.o `test -f 'llvm/unittests/ExecutionEngine/ExecutionEngineTest.cpp' || echo '$(srcdir)/'`llvm/unittests/ExecutionEngine/ExecutionEngineTest.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/llvmunittest_ExecutionEngine-ExecutionEngineTest.Tpo $(DEPDIR)/llvmunittest_ExecutionEngine-ExecutionEngineTest.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/unittests/ExecutionEngine/ExecutionEngineTest.cpp' object='llvmunittest_ExecutionEngine-ExecutionEngineTest.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llvmunittest_ExecutionEngine_CPPFLAGS) $(CPPFLAGS) $(llvmunittest_ExecutionEngine_CXXFLAGS) $(CXXFLAGS) -c -o llvmunittest_ExecutionEngine-ExecutionEngineTest.o `test -f 'llvm/unittests/ExecutionEngine/ExecutionEngineTest.cpp' || echo '$(srcdir)/'`llvm/unittests/ExecutionEngine/ExecutionEngineTest.cpp + +llvmunittest_ExecutionEngine-ExecutionEngineTest.obj: llvm/unittests/ExecutionEngine/ExecutionEngineTest.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llvmunittest_ExecutionEngine_CPPFLAGS) $(CPPFLAGS) $(llvmunittest_ExecutionEngine_CXXFLAGS) $(CXXFLAGS) -MT llvmunittest_ExecutionEngine-ExecutionEngineTest.obj -MD -MP -MF $(DEPDIR)/llvmunittest_ExecutionEngine-ExecutionEngineTest.Tpo -c -o llvmunittest_ExecutionEngine-ExecutionEngineTest.obj `if test -f 'llvm/unittests/ExecutionEngine/ExecutionEngineTest.cpp'; then $(CYGPATH_W) 'llvm/unittests/ExecutionEngine/ExecutionEngineTest.cpp'; else $(CYGPATH_W) '$(srcdir)/llvm/unittests/ExecutionEngine/ExecutionEngineTest.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/llvmunittest_ExecutionEngine-ExecutionEngineTest.Tpo $(DEPDIR)/llvmunittest_ExecutionEngine-ExecutionEngineTest.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/unittests/ExecutionEngine/ExecutionEngineTest.cpp' object='llvmunittest_ExecutionEngine-ExecutionEngineTest.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llvmunittest_ExecutionEngine_CPPFLAGS) $(CPPFLAGS) $(llvmunittest_ExecutionEngine_CXXFLAGS) $(CXXFLAGS) -c -o llvmunittest_ExecutionEngine-ExecutionEngineTest.obj `if test -f 'llvm/unittests/ExecutionEngine/ExecutionEngineTest.cpp'; then $(CYGPATH_W) 'llvm/unittests/ExecutionEngine/ExecutionEngineTest.cpp'; else $(CYGPATH_W) '$(srcdir)/llvm/unittests/ExecutionEngine/ExecutionEngineTest.cpp'; fi` + +llvmunittest_JIT-JITEventListenerTest.o: llvm/unittests/ExecutionEngine/JIT/JITEventListenerTest.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llvmunittest_JIT_CPPFLAGS) $(CPPFLAGS) $(llvmunittest_JIT_CXXFLAGS) $(CXXFLAGS) -MT llvmunittest_JIT-JITEventListenerTest.o -MD -MP -MF $(DEPDIR)/llvmunittest_JIT-JITEventListenerTest.Tpo -c -o llvmunittest_JIT-JITEventListenerTest.o `test -f 'llvm/unittests/ExecutionEngine/JIT/JITEventListenerTest.cpp' || echo '$(srcdir)/'`llvm/unittests/ExecutionEngine/JIT/JITEventListenerTest.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/llvmunittest_JIT-JITEventListenerTest.Tpo $(DEPDIR)/llvmunittest_JIT-JITEventListenerTest.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/unittests/ExecutionEngine/JIT/JITEventListenerTest.cpp' object='llvmunittest_JIT-JITEventListenerTest.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llvmunittest_JIT_CPPFLAGS) $(CPPFLAGS) $(llvmunittest_JIT_CXXFLAGS) $(CXXFLAGS) -c -o llvmunittest_JIT-JITEventListenerTest.o `test -f 'llvm/unittests/ExecutionEngine/JIT/JITEventListenerTest.cpp' || echo '$(srcdir)/'`llvm/unittests/ExecutionEngine/JIT/JITEventListenerTest.cpp + +llvmunittest_JIT-JITEventListenerTest.obj: llvm/unittests/ExecutionEngine/JIT/JITEventListenerTest.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llvmunittest_JIT_CPPFLAGS) $(CPPFLAGS) $(llvmunittest_JIT_CXXFLAGS) $(CXXFLAGS) -MT llvmunittest_JIT-JITEventListenerTest.obj -MD -MP -MF $(DEPDIR)/llvmunittest_JIT-JITEventListenerTest.Tpo -c -o llvmunittest_JIT-JITEventListenerTest.obj `if test -f 'llvm/unittests/ExecutionEngine/JIT/JITEventListenerTest.cpp'; then $(CYGPATH_W) 'llvm/unittests/ExecutionEngine/JIT/JITEventListenerTest.cpp'; else $(CYGPATH_W) '$(srcdir)/llvm/unittests/ExecutionEngine/JIT/JITEventListenerTest.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/llvmunittest_JIT-JITEventListenerTest.Tpo $(DEPDIR)/llvmunittest_JIT-JITEventListenerTest.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/unittests/ExecutionEngine/JIT/JITEventListenerTest.cpp' object='llvmunittest_JIT-JITEventListenerTest.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llvmunittest_JIT_CPPFLAGS) $(CPPFLAGS) $(llvmunittest_JIT_CXXFLAGS) $(CXXFLAGS) -c -o llvmunittest_JIT-JITEventListenerTest.obj `if test -f 'llvm/unittests/ExecutionEngine/JIT/JITEventListenerTest.cpp'; then $(CYGPATH_W) 'llvm/unittests/ExecutionEngine/JIT/JITEventListenerTest.cpp'; else $(CYGPATH_W) '$(srcdir)/llvm/unittests/ExecutionEngine/JIT/JITEventListenerTest.cpp'; fi` + +llvmunittest_JIT-JITMemoryManagerTest.o: llvm/unittests/ExecutionEngine/JIT/JITMemoryManagerTest.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llvmunittest_JIT_CPPFLAGS) $(CPPFLAGS) $(llvmunittest_JIT_CXXFLAGS) $(CXXFLAGS) -MT llvmunittest_JIT-JITMemoryManagerTest.o -MD -MP -MF $(DEPDIR)/llvmunittest_JIT-JITMemoryManagerTest.Tpo -c -o llvmunittest_JIT-JITMemoryManagerTest.o `test -f 'llvm/unittests/ExecutionEngine/JIT/JITMemoryManagerTest.cpp' || echo '$(srcdir)/'`llvm/unittests/ExecutionEngine/JIT/JITMemoryManagerTest.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/llvmunittest_JIT-JITMemoryManagerTest.Tpo $(DEPDIR)/llvmunittest_JIT-JITMemoryManagerTest.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/unittests/ExecutionEngine/JIT/JITMemoryManagerTest.cpp' object='llvmunittest_JIT-JITMemoryManagerTest.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llvmunittest_JIT_CPPFLAGS) $(CPPFLAGS) $(llvmunittest_JIT_CXXFLAGS) $(CXXFLAGS) -c -o llvmunittest_JIT-JITMemoryManagerTest.o `test -f 'llvm/unittests/ExecutionEngine/JIT/JITMemoryManagerTest.cpp' || echo '$(srcdir)/'`llvm/unittests/ExecutionEngine/JIT/JITMemoryManagerTest.cpp + +llvmunittest_JIT-JITMemoryManagerTest.obj: llvm/unittests/ExecutionEngine/JIT/JITMemoryManagerTest.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llvmunittest_JIT_CPPFLAGS) $(CPPFLAGS) $(llvmunittest_JIT_CXXFLAGS) $(CXXFLAGS) -MT llvmunittest_JIT-JITMemoryManagerTest.obj -MD -MP -MF $(DEPDIR)/llvmunittest_JIT-JITMemoryManagerTest.Tpo -c -o llvmunittest_JIT-JITMemoryManagerTest.obj `if test -f 'llvm/unittests/ExecutionEngine/JIT/JITMemoryManagerTest.cpp'; then $(CYGPATH_W) 'llvm/unittests/ExecutionEngine/JIT/JITMemoryManagerTest.cpp'; else $(CYGPATH_W) '$(srcdir)/llvm/unittests/ExecutionEngine/JIT/JITMemoryManagerTest.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/llvmunittest_JIT-JITMemoryManagerTest.Tpo $(DEPDIR)/llvmunittest_JIT-JITMemoryManagerTest.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/unittests/ExecutionEngine/JIT/JITMemoryManagerTest.cpp' object='llvmunittest_JIT-JITMemoryManagerTest.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llvmunittest_JIT_CPPFLAGS) $(CPPFLAGS) $(llvmunittest_JIT_CXXFLAGS) $(CXXFLAGS) -c -o llvmunittest_JIT-JITMemoryManagerTest.obj `if test -f 'llvm/unittests/ExecutionEngine/JIT/JITMemoryManagerTest.cpp'; then $(CYGPATH_W) 'llvm/unittests/ExecutionEngine/JIT/JITMemoryManagerTest.cpp'; else $(CYGPATH_W) '$(srcdir)/llvm/unittests/ExecutionEngine/JIT/JITMemoryManagerTest.cpp'; fi` + +llvmunittest_JIT-JITTest.o: llvm/unittests/ExecutionEngine/JIT/JITTest.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llvmunittest_JIT_CPPFLAGS) $(CPPFLAGS) $(llvmunittest_JIT_CXXFLAGS) $(CXXFLAGS) -MT llvmunittest_JIT-JITTest.o -MD -MP -MF $(DEPDIR)/llvmunittest_JIT-JITTest.Tpo -c -o llvmunittest_JIT-JITTest.o `test -f 'llvm/unittests/ExecutionEngine/JIT/JITTest.cpp' || echo '$(srcdir)/'`llvm/unittests/ExecutionEngine/JIT/JITTest.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/llvmunittest_JIT-JITTest.Tpo $(DEPDIR)/llvmunittest_JIT-JITTest.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/unittests/ExecutionEngine/JIT/JITTest.cpp' object='llvmunittest_JIT-JITTest.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llvmunittest_JIT_CPPFLAGS) $(CPPFLAGS) $(llvmunittest_JIT_CXXFLAGS) $(CXXFLAGS) -c -o llvmunittest_JIT-JITTest.o `test -f 'llvm/unittests/ExecutionEngine/JIT/JITTest.cpp' || echo '$(srcdir)/'`llvm/unittests/ExecutionEngine/JIT/JITTest.cpp + +llvmunittest_JIT-JITTest.obj: llvm/unittests/ExecutionEngine/JIT/JITTest.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llvmunittest_JIT_CPPFLAGS) $(CPPFLAGS) $(llvmunittest_JIT_CXXFLAGS) $(CXXFLAGS) -MT llvmunittest_JIT-JITTest.obj -MD -MP -MF $(DEPDIR)/llvmunittest_JIT-JITTest.Tpo -c -o llvmunittest_JIT-JITTest.obj `if test -f 'llvm/unittests/ExecutionEngine/JIT/JITTest.cpp'; then $(CYGPATH_W) 'llvm/unittests/ExecutionEngine/JIT/JITTest.cpp'; else $(CYGPATH_W) '$(srcdir)/llvm/unittests/ExecutionEngine/JIT/JITTest.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/llvmunittest_JIT-JITTest.Tpo $(DEPDIR)/llvmunittest_JIT-JITTest.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/unittests/ExecutionEngine/JIT/JITTest.cpp' object='llvmunittest_JIT-JITTest.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llvmunittest_JIT_CPPFLAGS) $(CPPFLAGS) $(llvmunittest_JIT_CXXFLAGS) $(CXXFLAGS) -c -o llvmunittest_JIT-JITTest.obj `if test -f 'llvm/unittests/ExecutionEngine/JIT/JITTest.cpp'; then $(CYGPATH_W) 'llvm/unittests/ExecutionEngine/JIT/JITTest.cpp'; else $(CYGPATH_W) '$(srcdir)/llvm/unittests/ExecutionEngine/JIT/JITTest.cpp'; fi` + +llvmunittest_Support-AllocatorTest.o: llvm/unittests/Support/AllocatorTest.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llvmunittest_Support_CPPFLAGS) $(CPPFLAGS) $(llvmunittest_Support_CXXFLAGS) $(CXXFLAGS) -MT llvmunittest_Support-AllocatorTest.o -MD -MP -MF $(DEPDIR)/llvmunittest_Support-AllocatorTest.Tpo -c -o llvmunittest_Support-AllocatorTest.o `test -f 'llvm/unittests/Support/AllocatorTest.cpp' || echo '$(srcdir)/'`llvm/unittests/Support/AllocatorTest.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/llvmunittest_Support-AllocatorTest.Tpo $(DEPDIR)/llvmunittest_Support-AllocatorTest.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/unittests/Support/AllocatorTest.cpp' object='llvmunittest_Support-AllocatorTest.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llvmunittest_Support_CPPFLAGS) $(CPPFLAGS) $(llvmunittest_Support_CXXFLAGS) $(CXXFLAGS) -c -o llvmunittest_Support-AllocatorTest.o `test -f 'llvm/unittests/Support/AllocatorTest.cpp' || echo '$(srcdir)/'`llvm/unittests/Support/AllocatorTest.cpp + +llvmunittest_Support-AllocatorTest.obj: llvm/unittests/Support/AllocatorTest.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llvmunittest_Support_CPPFLAGS) $(CPPFLAGS) $(llvmunittest_Support_CXXFLAGS) $(CXXFLAGS) -MT llvmunittest_Support-AllocatorTest.obj -MD -MP -MF $(DEPDIR)/llvmunittest_Support-AllocatorTest.Tpo -c -o llvmunittest_Support-AllocatorTest.obj `if test -f 'llvm/unittests/Support/AllocatorTest.cpp'; then $(CYGPATH_W) 'llvm/unittests/Support/AllocatorTest.cpp'; else $(CYGPATH_W) '$(srcdir)/llvm/unittests/Support/AllocatorTest.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/llvmunittest_Support-AllocatorTest.Tpo $(DEPDIR)/llvmunittest_Support-AllocatorTest.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/unittests/Support/AllocatorTest.cpp' object='llvmunittest_Support-AllocatorTest.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llvmunittest_Support_CPPFLAGS) $(CPPFLAGS) $(llvmunittest_Support_CXXFLAGS) $(CXXFLAGS) -c -o llvmunittest_Support-AllocatorTest.obj `if test -f 'llvm/unittests/Support/AllocatorTest.cpp'; then $(CYGPATH_W) 'llvm/unittests/Support/AllocatorTest.cpp'; else $(CYGPATH_W) '$(srcdir)/llvm/unittests/Support/AllocatorTest.cpp'; fi` + +llvmunittest_Support-ConstantRangeTest.o: llvm/unittests/Support/ConstantRangeTest.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llvmunittest_Support_CPPFLAGS) $(CPPFLAGS) $(llvmunittest_Support_CXXFLAGS) $(CXXFLAGS) -MT llvmunittest_Support-ConstantRangeTest.o -MD -MP -MF $(DEPDIR)/llvmunittest_Support-ConstantRangeTest.Tpo -c -o llvmunittest_Support-ConstantRangeTest.o `test -f 'llvm/unittests/Support/ConstantRangeTest.cpp' || echo '$(srcdir)/'`llvm/unittests/Support/ConstantRangeTest.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/llvmunittest_Support-ConstantRangeTest.Tpo $(DEPDIR)/llvmunittest_Support-ConstantRangeTest.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/unittests/Support/ConstantRangeTest.cpp' object='llvmunittest_Support-ConstantRangeTest.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llvmunittest_Support_CPPFLAGS) $(CPPFLAGS) $(llvmunittest_Support_CXXFLAGS) $(CXXFLAGS) -c -o llvmunittest_Support-ConstantRangeTest.o `test -f 'llvm/unittests/Support/ConstantRangeTest.cpp' || echo '$(srcdir)/'`llvm/unittests/Support/ConstantRangeTest.cpp + +llvmunittest_Support-ConstantRangeTest.obj: llvm/unittests/Support/ConstantRangeTest.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llvmunittest_Support_CPPFLAGS) $(CPPFLAGS) $(llvmunittest_Support_CXXFLAGS) $(CXXFLAGS) -MT llvmunittest_Support-ConstantRangeTest.obj -MD -MP -MF $(DEPDIR)/llvmunittest_Support-ConstantRangeTest.Tpo -c -o llvmunittest_Support-ConstantRangeTest.obj `if test -f 'llvm/unittests/Support/ConstantRangeTest.cpp'; then $(CYGPATH_W) 'llvm/unittests/Support/ConstantRangeTest.cpp'; else $(CYGPATH_W) '$(srcdir)/llvm/unittests/Support/ConstantRangeTest.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/llvmunittest_Support-ConstantRangeTest.Tpo $(DEPDIR)/llvmunittest_Support-ConstantRangeTest.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/unittests/Support/ConstantRangeTest.cpp' object='llvmunittest_Support-ConstantRangeTest.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llvmunittest_Support_CPPFLAGS) $(CPPFLAGS) $(llvmunittest_Support_CXXFLAGS) $(CXXFLAGS) -c -o llvmunittest_Support-ConstantRangeTest.obj `if test -f 'llvm/unittests/Support/ConstantRangeTest.cpp'; then $(CYGPATH_W) 'llvm/unittests/Support/ConstantRangeTest.cpp'; else $(CYGPATH_W) '$(srcdir)/llvm/unittests/Support/ConstantRangeTest.cpp'; fi` + +llvmunittest_Support-MathExtrasTest.o: llvm/unittests/Support/MathExtrasTest.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llvmunittest_Support_CPPFLAGS) $(CPPFLAGS) $(llvmunittest_Support_CXXFLAGS) $(CXXFLAGS) -MT llvmunittest_Support-MathExtrasTest.o -MD -MP -MF $(DEPDIR)/llvmunittest_Support-MathExtrasTest.Tpo -c -o llvmunittest_Support-MathExtrasTest.o `test -f 'llvm/unittests/Support/MathExtrasTest.cpp' || echo '$(srcdir)/'`llvm/unittests/Support/MathExtrasTest.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/llvmunittest_Support-MathExtrasTest.Tpo $(DEPDIR)/llvmunittest_Support-MathExtrasTest.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/unittests/Support/MathExtrasTest.cpp' object='llvmunittest_Support-MathExtrasTest.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llvmunittest_Support_CPPFLAGS) $(CPPFLAGS) $(llvmunittest_Support_CXXFLAGS) $(CXXFLAGS) -c -o llvmunittest_Support-MathExtrasTest.o `test -f 'llvm/unittests/Support/MathExtrasTest.cpp' || echo '$(srcdir)/'`llvm/unittests/Support/MathExtrasTest.cpp + +llvmunittest_Support-MathExtrasTest.obj: llvm/unittests/Support/MathExtrasTest.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llvmunittest_Support_CPPFLAGS) $(CPPFLAGS) $(llvmunittest_Support_CXXFLAGS) $(CXXFLAGS) -MT llvmunittest_Support-MathExtrasTest.obj -MD -MP -MF $(DEPDIR)/llvmunittest_Support-MathExtrasTest.Tpo -c -o llvmunittest_Support-MathExtrasTest.obj `if test -f 'llvm/unittests/Support/MathExtrasTest.cpp'; then $(CYGPATH_W) 'llvm/unittests/Support/MathExtrasTest.cpp'; else $(CYGPATH_W) '$(srcdir)/llvm/unittests/Support/MathExtrasTest.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/llvmunittest_Support-MathExtrasTest.Tpo $(DEPDIR)/llvmunittest_Support-MathExtrasTest.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/unittests/Support/MathExtrasTest.cpp' object='llvmunittest_Support-MathExtrasTest.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llvmunittest_Support_CPPFLAGS) $(CPPFLAGS) $(llvmunittest_Support_CXXFLAGS) $(CXXFLAGS) -c -o llvmunittest_Support-MathExtrasTest.obj `if test -f 'llvm/unittests/Support/MathExtrasTest.cpp'; then $(CYGPATH_W) 'llvm/unittests/Support/MathExtrasTest.cpp'; else $(CYGPATH_W) '$(srcdir)/llvm/unittests/Support/MathExtrasTest.cpp'; fi` + +llvmunittest_Support-RegexTest.o: llvm/unittests/Support/RegexTest.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llvmunittest_Support_CPPFLAGS) $(CPPFLAGS) $(llvmunittest_Support_CXXFLAGS) $(CXXFLAGS) -MT llvmunittest_Support-RegexTest.o -MD -MP -MF $(DEPDIR)/llvmunittest_Support-RegexTest.Tpo -c -o llvmunittest_Support-RegexTest.o `test -f 'llvm/unittests/Support/RegexTest.cpp' || echo '$(srcdir)/'`llvm/unittests/Support/RegexTest.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/llvmunittest_Support-RegexTest.Tpo $(DEPDIR)/llvmunittest_Support-RegexTest.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/unittests/Support/RegexTest.cpp' object='llvmunittest_Support-RegexTest.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llvmunittest_Support_CPPFLAGS) $(CPPFLAGS) $(llvmunittest_Support_CXXFLAGS) $(CXXFLAGS) -c -o llvmunittest_Support-RegexTest.o `test -f 'llvm/unittests/Support/RegexTest.cpp' || echo '$(srcdir)/'`llvm/unittests/Support/RegexTest.cpp + +llvmunittest_Support-RegexTest.obj: llvm/unittests/Support/RegexTest.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llvmunittest_Support_CPPFLAGS) $(CPPFLAGS) $(llvmunittest_Support_CXXFLAGS) $(CXXFLAGS) -MT llvmunittest_Support-RegexTest.obj -MD -MP -MF $(DEPDIR)/llvmunittest_Support-RegexTest.Tpo -c -o llvmunittest_Support-RegexTest.obj `if test -f 'llvm/unittests/Support/RegexTest.cpp'; then $(CYGPATH_W) 'llvm/unittests/Support/RegexTest.cpp'; else $(CYGPATH_W) '$(srcdir)/llvm/unittests/Support/RegexTest.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/llvmunittest_Support-RegexTest.Tpo $(DEPDIR)/llvmunittest_Support-RegexTest.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/unittests/Support/RegexTest.cpp' object='llvmunittest_Support-RegexTest.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llvmunittest_Support_CPPFLAGS) $(CPPFLAGS) $(llvmunittest_Support_CXXFLAGS) $(CXXFLAGS) -c -o llvmunittest_Support-RegexTest.obj `if test -f 'llvm/unittests/Support/RegexTest.cpp'; then $(CYGPATH_W) 'llvm/unittests/Support/RegexTest.cpp'; else $(CYGPATH_W) '$(srcdir)/llvm/unittests/Support/RegexTest.cpp'; fi` + +llvmunittest_Support-TypeBuilderTest.o: llvm/unittests/Support/TypeBuilderTest.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llvmunittest_Support_CPPFLAGS) $(CPPFLAGS) $(llvmunittest_Support_CXXFLAGS) $(CXXFLAGS) -MT llvmunittest_Support-TypeBuilderTest.o -MD -MP -MF $(DEPDIR)/llvmunittest_Support-TypeBuilderTest.Tpo -c -o llvmunittest_Support-TypeBuilderTest.o `test -f 'llvm/unittests/Support/TypeBuilderTest.cpp' || echo '$(srcdir)/'`llvm/unittests/Support/TypeBuilderTest.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/llvmunittest_Support-TypeBuilderTest.Tpo $(DEPDIR)/llvmunittest_Support-TypeBuilderTest.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/unittests/Support/TypeBuilderTest.cpp' object='llvmunittest_Support-TypeBuilderTest.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llvmunittest_Support_CPPFLAGS) $(CPPFLAGS) $(llvmunittest_Support_CXXFLAGS) $(CXXFLAGS) -c -o llvmunittest_Support-TypeBuilderTest.o `test -f 'llvm/unittests/Support/TypeBuilderTest.cpp' || echo '$(srcdir)/'`llvm/unittests/Support/TypeBuilderTest.cpp + +llvmunittest_Support-TypeBuilderTest.obj: llvm/unittests/Support/TypeBuilderTest.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llvmunittest_Support_CPPFLAGS) $(CPPFLAGS) $(llvmunittest_Support_CXXFLAGS) $(CXXFLAGS) -MT llvmunittest_Support-TypeBuilderTest.obj -MD -MP -MF $(DEPDIR)/llvmunittest_Support-TypeBuilderTest.Tpo -c -o llvmunittest_Support-TypeBuilderTest.obj `if test -f 'llvm/unittests/Support/TypeBuilderTest.cpp'; then $(CYGPATH_W) 'llvm/unittests/Support/TypeBuilderTest.cpp'; else $(CYGPATH_W) '$(srcdir)/llvm/unittests/Support/TypeBuilderTest.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/llvmunittest_Support-TypeBuilderTest.Tpo $(DEPDIR)/llvmunittest_Support-TypeBuilderTest.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/unittests/Support/TypeBuilderTest.cpp' object='llvmunittest_Support-TypeBuilderTest.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llvmunittest_Support_CPPFLAGS) $(CPPFLAGS) $(llvmunittest_Support_CXXFLAGS) $(CXXFLAGS) -c -o llvmunittest_Support-TypeBuilderTest.obj `if test -f 'llvm/unittests/Support/TypeBuilderTest.cpp'; then $(CYGPATH_W) 'llvm/unittests/Support/TypeBuilderTest.cpp'; else $(CYGPATH_W) '$(srcdir)/llvm/unittests/Support/TypeBuilderTest.cpp'; fi` + +llvmunittest_Support-ValueHandleTest.o: llvm/unittests/Support/ValueHandleTest.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llvmunittest_Support_CPPFLAGS) $(CPPFLAGS) $(llvmunittest_Support_CXXFLAGS) $(CXXFLAGS) -MT llvmunittest_Support-ValueHandleTest.o -MD -MP -MF $(DEPDIR)/llvmunittest_Support-ValueHandleTest.Tpo -c -o llvmunittest_Support-ValueHandleTest.o `test -f 'llvm/unittests/Support/ValueHandleTest.cpp' || echo '$(srcdir)/'`llvm/unittests/Support/ValueHandleTest.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/llvmunittest_Support-ValueHandleTest.Tpo $(DEPDIR)/llvmunittest_Support-ValueHandleTest.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/unittests/Support/ValueHandleTest.cpp' object='llvmunittest_Support-ValueHandleTest.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llvmunittest_Support_CPPFLAGS) $(CPPFLAGS) $(llvmunittest_Support_CXXFLAGS) $(CXXFLAGS) -c -o llvmunittest_Support-ValueHandleTest.o `test -f 'llvm/unittests/Support/ValueHandleTest.cpp' || echo '$(srcdir)/'`llvm/unittests/Support/ValueHandleTest.cpp + +llvmunittest_Support-ValueHandleTest.obj: llvm/unittests/Support/ValueHandleTest.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llvmunittest_Support_CPPFLAGS) $(CPPFLAGS) $(llvmunittest_Support_CXXFLAGS) $(CXXFLAGS) -MT llvmunittest_Support-ValueHandleTest.obj -MD -MP -MF $(DEPDIR)/llvmunittest_Support-ValueHandleTest.Tpo -c -o llvmunittest_Support-ValueHandleTest.obj `if test -f 'llvm/unittests/Support/ValueHandleTest.cpp'; then $(CYGPATH_W) 'llvm/unittests/Support/ValueHandleTest.cpp'; else $(CYGPATH_W) '$(srcdir)/llvm/unittests/Support/ValueHandleTest.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/llvmunittest_Support-ValueHandleTest.Tpo $(DEPDIR)/llvmunittest_Support-ValueHandleTest.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/unittests/Support/ValueHandleTest.cpp' object='llvmunittest_Support-ValueHandleTest.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llvmunittest_Support_CPPFLAGS) $(CPPFLAGS) $(llvmunittest_Support_CXXFLAGS) $(CXXFLAGS) -c -o llvmunittest_Support-ValueHandleTest.obj `if test -f 'llvm/unittests/Support/ValueHandleTest.cpp'; then $(CYGPATH_W) 'llvm/unittests/Support/ValueHandleTest.cpp'; else $(CYGPATH_W) '$(srcdir)/llvm/unittests/Support/ValueHandleTest.cpp'; fi` + +llvmunittest_Support-raw_ostream_test.o: llvm/unittests/Support/raw_ostream_test.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llvmunittest_Support_CPPFLAGS) $(CPPFLAGS) $(llvmunittest_Support_CXXFLAGS) $(CXXFLAGS) -MT llvmunittest_Support-raw_ostream_test.o -MD -MP -MF $(DEPDIR)/llvmunittest_Support-raw_ostream_test.Tpo -c -o llvmunittest_Support-raw_ostream_test.o `test -f 'llvm/unittests/Support/raw_ostream_test.cpp' || echo '$(srcdir)/'`llvm/unittests/Support/raw_ostream_test.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/llvmunittest_Support-raw_ostream_test.Tpo $(DEPDIR)/llvmunittest_Support-raw_ostream_test.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/unittests/Support/raw_ostream_test.cpp' object='llvmunittest_Support-raw_ostream_test.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llvmunittest_Support_CPPFLAGS) $(CPPFLAGS) $(llvmunittest_Support_CXXFLAGS) $(CXXFLAGS) -c -o llvmunittest_Support-raw_ostream_test.o `test -f 'llvm/unittests/Support/raw_ostream_test.cpp' || echo '$(srcdir)/'`llvm/unittests/Support/raw_ostream_test.cpp + +llvmunittest_Support-raw_ostream_test.obj: llvm/unittests/Support/raw_ostream_test.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llvmunittest_Support_CPPFLAGS) $(CPPFLAGS) $(llvmunittest_Support_CXXFLAGS) $(CXXFLAGS) -MT llvmunittest_Support-raw_ostream_test.obj -MD -MP -MF $(DEPDIR)/llvmunittest_Support-raw_ostream_test.Tpo -c -o llvmunittest_Support-raw_ostream_test.obj `if test -f 'llvm/unittests/Support/raw_ostream_test.cpp'; then $(CYGPATH_W) 'llvm/unittests/Support/raw_ostream_test.cpp'; else $(CYGPATH_W) '$(srcdir)/llvm/unittests/Support/raw_ostream_test.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/llvmunittest_Support-raw_ostream_test.Tpo $(DEPDIR)/llvmunittest_Support-raw_ostream_test.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/unittests/Support/raw_ostream_test.cpp' object='llvmunittest_Support-raw_ostream_test.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llvmunittest_Support_CPPFLAGS) $(CPPFLAGS) $(llvmunittest_Support_CXXFLAGS) $(CXXFLAGS) -c -o llvmunittest_Support-raw_ostream_test.obj `if test -f 'llvm/unittests/Support/raw_ostream_test.cpp'; then $(CYGPATH_W) 'llvm/unittests/Support/raw_ostream_test.cpp'; else $(CYGPATH_W) '$(srcdir)/llvm/unittests/Support/raw_ostream_test.cpp'; fi` + +llvmunittest_VMCore-CallGraphSCCPass.o: llvm/lib/Analysis/IPA/CallGraphSCCPass.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llvmunittest_VMCore_CPPFLAGS) $(CPPFLAGS) $(llvmunittest_VMCore_CXXFLAGS) $(CXXFLAGS) -MT llvmunittest_VMCore-CallGraphSCCPass.o -MD -MP -MF $(DEPDIR)/llvmunittest_VMCore-CallGraphSCCPass.Tpo -c -o llvmunittest_VMCore-CallGraphSCCPass.o `test -f 'llvm/lib/Analysis/IPA/CallGraphSCCPass.cpp' || echo '$(srcdir)/'`llvm/lib/Analysis/IPA/CallGraphSCCPass.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/llvmunittest_VMCore-CallGraphSCCPass.Tpo $(DEPDIR)/llvmunittest_VMCore-CallGraphSCCPass.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Analysis/IPA/CallGraphSCCPass.cpp' object='llvmunittest_VMCore-CallGraphSCCPass.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llvmunittest_VMCore_CPPFLAGS) $(CPPFLAGS) $(llvmunittest_VMCore_CXXFLAGS) $(CXXFLAGS) -c -o llvmunittest_VMCore-CallGraphSCCPass.o `test -f 'llvm/lib/Analysis/IPA/CallGraphSCCPass.cpp' || echo '$(srcdir)/'`llvm/lib/Analysis/IPA/CallGraphSCCPass.cpp + +llvmunittest_VMCore-CallGraphSCCPass.obj: llvm/lib/Analysis/IPA/CallGraphSCCPass.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llvmunittest_VMCore_CPPFLAGS) $(CPPFLAGS) $(llvmunittest_VMCore_CXXFLAGS) $(CXXFLAGS) -MT llvmunittest_VMCore-CallGraphSCCPass.obj -MD -MP -MF $(DEPDIR)/llvmunittest_VMCore-CallGraphSCCPass.Tpo -c -o llvmunittest_VMCore-CallGraphSCCPass.obj `if test -f 'llvm/lib/Analysis/IPA/CallGraphSCCPass.cpp'; then $(CYGPATH_W) 'llvm/lib/Analysis/IPA/CallGraphSCCPass.cpp'; else $(CYGPATH_W) '$(srcdir)/llvm/lib/Analysis/IPA/CallGraphSCCPass.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/llvmunittest_VMCore-CallGraphSCCPass.Tpo $(DEPDIR)/llvmunittest_VMCore-CallGraphSCCPass.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Analysis/IPA/CallGraphSCCPass.cpp' object='llvmunittest_VMCore-CallGraphSCCPass.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llvmunittest_VMCore_CPPFLAGS) $(CPPFLAGS) $(llvmunittest_VMCore_CXXFLAGS) $(CXXFLAGS) -c -o llvmunittest_VMCore-CallGraphSCCPass.obj `if test -f 'llvm/lib/Analysis/IPA/CallGraphSCCPass.cpp'; then $(CYGPATH_W) 'llvm/lib/Analysis/IPA/CallGraphSCCPass.cpp'; else $(CYGPATH_W) '$(srcdir)/llvm/lib/Analysis/IPA/CallGraphSCCPass.cpp'; fi` + +llvmunittest_VMCore-ConstantsTest.o: llvm/unittests/VMCore/ConstantsTest.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llvmunittest_VMCore_CPPFLAGS) $(CPPFLAGS) $(llvmunittest_VMCore_CXXFLAGS) $(CXXFLAGS) -MT llvmunittest_VMCore-ConstantsTest.o -MD -MP -MF $(DEPDIR)/llvmunittest_VMCore-ConstantsTest.Tpo -c -o llvmunittest_VMCore-ConstantsTest.o `test -f 'llvm/unittests/VMCore/ConstantsTest.cpp' || echo '$(srcdir)/'`llvm/unittests/VMCore/ConstantsTest.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/llvmunittest_VMCore-ConstantsTest.Tpo $(DEPDIR)/llvmunittest_VMCore-ConstantsTest.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/unittests/VMCore/ConstantsTest.cpp' object='llvmunittest_VMCore-ConstantsTest.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llvmunittest_VMCore_CPPFLAGS) $(CPPFLAGS) $(llvmunittest_VMCore_CXXFLAGS) $(CXXFLAGS) -c -o llvmunittest_VMCore-ConstantsTest.o `test -f 'llvm/unittests/VMCore/ConstantsTest.cpp' || echo '$(srcdir)/'`llvm/unittests/VMCore/ConstantsTest.cpp + +llvmunittest_VMCore-ConstantsTest.obj: llvm/unittests/VMCore/ConstantsTest.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llvmunittest_VMCore_CPPFLAGS) $(CPPFLAGS) $(llvmunittest_VMCore_CXXFLAGS) $(CXXFLAGS) -MT llvmunittest_VMCore-ConstantsTest.obj -MD -MP -MF $(DEPDIR)/llvmunittest_VMCore-ConstantsTest.Tpo -c -o llvmunittest_VMCore-ConstantsTest.obj `if test -f 'llvm/unittests/VMCore/ConstantsTest.cpp'; then $(CYGPATH_W) 'llvm/unittests/VMCore/ConstantsTest.cpp'; else $(CYGPATH_W) '$(srcdir)/llvm/unittests/VMCore/ConstantsTest.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/llvmunittest_VMCore-ConstantsTest.Tpo $(DEPDIR)/llvmunittest_VMCore-ConstantsTest.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/unittests/VMCore/ConstantsTest.cpp' object='llvmunittest_VMCore-ConstantsTest.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llvmunittest_VMCore_CPPFLAGS) $(CPPFLAGS) $(llvmunittest_VMCore_CXXFLAGS) $(CXXFLAGS) -c -o llvmunittest_VMCore-ConstantsTest.obj `if test -f 'llvm/unittests/VMCore/ConstantsTest.cpp'; then $(CYGPATH_W) 'llvm/unittests/VMCore/ConstantsTest.cpp'; else $(CYGPATH_W) '$(srcdir)/llvm/unittests/VMCore/ConstantsTest.cpp'; fi` + +llvmunittest_VMCore-MetadataTest.o: llvm/unittests/VMCore/MetadataTest.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llvmunittest_VMCore_CPPFLAGS) $(CPPFLAGS) $(llvmunittest_VMCore_CXXFLAGS) $(CXXFLAGS) -MT llvmunittest_VMCore-MetadataTest.o -MD -MP -MF $(DEPDIR)/llvmunittest_VMCore-MetadataTest.Tpo -c -o llvmunittest_VMCore-MetadataTest.o `test -f 'llvm/unittests/VMCore/MetadataTest.cpp' || echo '$(srcdir)/'`llvm/unittests/VMCore/MetadataTest.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/llvmunittest_VMCore-MetadataTest.Tpo $(DEPDIR)/llvmunittest_VMCore-MetadataTest.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/unittests/VMCore/MetadataTest.cpp' object='llvmunittest_VMCore-MetadataTest.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llvmunittest_VMCore_CPPFLAGS) $(CPPFLAGS) $(llvmunittest_VMCore_CXXFLAGS) $(CXXFLAGS) -c -o llvmunittest_VMCore-MetadataTest.o `test -f 'llvm/unittests/VMCore/MetadataTest.cpp' || echo '$(srcdir)/'`llvm/unittests/VMCore/MetadataTest.cpp + +llvmunittest_VMCore-MetadataTest.obj: llvm/unittests/VMCore/MetadataTest.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llvmunittest_VMCore_CPPFLAGS) $(CPPFLAGS) $(llvmunittest_VMCore_CXXFLAGS) $(CXXFLAGS) -MT llvmunittest_VMCore-MetadataTest.obj -MD -MP -MF $(DEPDIR)/llvmunittest_VMCore-MetadataTest.Tpo -c -o llvmunittest_VMCore-MetadataTest.obj `if test -f 'llvm/unittests/VMCore/MetadataTest.cpp'; then $(CYGPATH_W) 'llvm/unittests/VMCore/MetadataTest.cpp'; else $(CYGPATH_W) '$(srcdir)/llvm/unittests/VMCore/MetadataTest.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/llvmunittest_VMCore-MetadataTest.Tpo $(DEPDIR)/llvmunittest_VMCore-MetadataTest.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/unittests/VMCore/MetadataTest.cpp' object='llvmunittest_VMCore-MetadataTest.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llvmunittest_VMCore_CPPFLAGS) $(CPPFLAGS) $(llvmunittest_VMCore_CXXFLAGS) $(CXXFLAGS) -c -o llvmunittest_VMCore-MetadataTest.obj `if test -f 'llvm/unittests/VMCore/MetadataTest.cpp'; then $(CYGPATH_W) 'llvm/unittests/VMCore/MetadataTest.cpp'; else $(CYGPATH_W) '$(srcdir)/llvm/unittests/VMCore/MetadataTest.cpp'; fi` + +llvmunittest_VMCore-PassManagerTest.o: llvm/unittests/VMCore/PassManagerTest.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llvmunittest_VMCore_CPPFLAGS) $(CPPFLAGS) $(llvmunittest_VMCore_CXXFLAGS) $(CXXFLAGS) -MT llvmunittest_VMCore-PassManagerTest.o -MD -MP -MF $(DEPDIR)/llvmunittest_VMCore-PassManagerTest.Tpo -c -o llvmunittest_VMCore-PassManagerTest.o `test -f 'llvm/unittests/VMCore/PassManagerTest.cpp' || echo '$(srcdir)/'`llvm/unittests/VMCore/PassManagerTest.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/llvmunittest_VMCore-PassManagerTest.Tpo $(DEPDIR)/llvmunittest_VMCore-PassManagerTest.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/unittests/VMCore/PassManagerTest.cpp' object='llvmunittest_VMCore-PassManagerTest.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llvmunittest_VMCore_CPPFLAGS) $(CPPFLAGS) $(llvmunittest_VMCore_CXXFLAGS) $(CXXFLAGS) -c -o llvmunittest_VMCore-PassManagerTest.o `test -f 'llvm/unittests/VMCore/PassManagerTest.cpp' || echo '$(srcdir)/'`llvm/unittests/VMCore/PassManagerTest.cpp + +llvmunittest_VMCore-PassManagerTest.obj: llvm/unittests/VMCore/PassManagerTest.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llvmunittest_VMCore_CPPFLAGS) $(CPPFLAGS) $(llvmunittest_VMCore_CXXFLAGS) $(CXXFLAGS) -MT llvmunittest_VMCore-PassManagerTest.obj -MD -MP -MF $(DEPDIR)/llvmunittest_VMCore-PassManagerTest.Tpo -c -o llvmunittest_VMCore-PassManagerTest.obj `if test -f 'llvm/unittests/VMCore/PassManagerTest.cpp'; then $(CYGPATH_W) 'llvm/unittests/VMCore/PassManagerTest.cpp'; else $(CYGPATH_W) '$(srcdir)/llvm/unittests/VMCore/PassManagerTest.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/llvmunittest_VMCore-PassManagerTest.Tpo $(DEPDIR)/llvmunittest_VMCore-PassManagerTest.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/unittests/VMCore/PassManagerTest.cpp' object='llvmunittest_VMCore-PassManagerTest.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(llvmunittest_VMCore_CPPFLAGS) $(CPPFLAGS) $(llvmunittest_VMCore_CXXFLAGS) $(CXXFLAGS) -c -o llvmunittest_VMCore-PassManagerTest.obj `if test -f 'llvm/unittests/VMCore/PassManagerTest.cpp'; then $(CYGPATH_W) 'llvm/unittests/VMCore/PassManagerTest.cpp'; else $(CYGPATH_W) '$(srcdir)/llvm/unittests/VMCore/PassManagerTest.cpp'; fi` + +not-not.o: llvm/utils/not/not.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(not_CPPFLAGS) $(CPPFLAGS) $(not_CXXFLAGS) $(CXXFLAGS) -MT not-not.o -MD -MP -MF $(DEPDIR)/not-not.Tpo -c -o not-not.o `test -f 'llvm/utils/not/not.cpp' || echo '$(srcdir)/'`llvm/utils/not/not.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/not-not.Tpo $(DEPDIR)/not-not.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/utils/not/not.cpp' object='not-not.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(not_CPPFLAGS) $(CPPFLAGS) $(not_CXXFLAGS) $(CXXFLAGS) -c -o not-not.o `test -f 'llvm/utils/not/not.cpp' || echo '$(srcdir)/'`llvm/utils/not/not.cpp + +not-not.obj: llvm/utils/not/not.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(not_CPPFLAGS) $(CPPFLAGS) $(not_CXXFLAGS) $(CXXFLAGS) -MT not-not.obj -MD -MP -MF $(DEPDIR)/not-not.Tpo -c -o not-not.obj `if test -f 'llvm/utils/not/not.cpp'; then $(CYGPATH_W) 'llvm/utils/not/not.cpp'; else $(CYGPATH_W) '$(srcdir)/llvm/utils/not/not.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/not-not.Tpo $(DEPDIR)/not-not.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/utils/not/not.cpp' object='not-not.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(not_CPPFLAGS) $(CPPFLAGS) $(not_CXXFLAGS) $(CXXFLAGS) -c -o not-not.obj `if test -f 'llvm/utils/not/not.cpp'; then $(CYGPATH_W) 'llvm/utils/not/not.cpp'; else $(CYGPATH_W) '$(srcdir)/llvm/utils/not/not.cpp'; fi` + +tblgen-AsmMatcherEmitter.o: llvm/utils/TableGen/AsmMatcherEmitter.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tblgen_CPPFLAGS) $(CPPFLAGS) $(tblgen_CXXFLAGS) $(CXXFLAGS) -MT tblgen-AsmMatcherEmitter.o -MD -MP -MF $(DEPDIR)/tblgen-AsmMatcherEmitter.Tpo -c -o tblgen-AsmMatcherEmitter.o `test -f 'llvm/utils/TableGen/AsmMatcherEmitter.cpp' || echo '$(srcdir)/'`llvm/utils/TableGen/AsmMatcherEmitter.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/tblgen-AsmMatcherEmitter.Tpo $(DEPDIR)/tblgen-AsmMatcherEmitter.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/utils/TableGen/AsmMatcherEmitter.cpp' object='tblgen-AsmMatcherEmitter.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tblgen_CPPFLAGS) $(CPPFLAGS) $(tblgen_CXXFLAGS) $(CXXFLAGS) -c -o tblgen-AsmMatcherEmitter.o `test -f 'llvm/utils/TableGen/AsmMatcherEmitter.cpp' || echo '$(srcdir)/'`llvm/utils/TableGen/AsmMatcherEmitter.cpp + +tblgen-AsmMatcherEmitter.obj: llvm/utils/TableGen/AsmMatcherEmitter.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tblgen_CPPFLAGS) $(CPPFLAGS) $(tblgen_CXXFLAGS) $(CXXFLAGS) -MT tblgen-AsmMatcherEmitter.obj -MD -MP -MF $(DEPDIR)/tblgen-AsmMatcherEmitter.Tpo -c -o tblgen-AsmMatcherEmitter.obj `if test -f 'llvm/utils/TableGen/AsmMatcherEmitter.cpp'; then $(CYGPATH_W) 'llvm/utils/TableGen/AsmMatcherEmitter.cpp'; else $(CYGPATH_W) '$(srcdir)/llvm/utils/TableGen/AsmMatcherEmitter.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/tblgen-AsmMatcherEmitter.Tpo $(DEPDIR)/tblgen-AsmMatcherEmitter.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/utils/TableGen/AsmMatcherEmitter.cpp' object='tblgen-AsmMatcherEmitter.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tblgen_CPPFLAGS) $(CPPFLAGS) $(tblgen_CXXFLAGS) $(CXXFLAGS) -c -o tblgen-AsmMatcherEmitter.obj `if test -f 'llvm/utils/TableGen/AsmMatcherEmitter.cpp'; then $(CYGPATH_W) 'llvm/utils/TableGen/AsmMatcherEmitter.cpp'; else $(CYGPATH_W) '$(srcdir)/llvm/utils/TableGen/AsmMatcherEmitter.cpp'; fi` + +tblgen-AsmWriterEmitter.o: llvm/utils/TableGen/AsmWriterEmitter.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tblgen_CPPFLAGS) $(CPPFLAGS) $(tblgen_CXXFLAGS) $(CXXFLAGS) -MT tblgen-AsmWriterEmitter.o -MD -MP -MF $(DEPDIR)/tblgen-AsmWriterEmitter.Tpo -c -o tblgen-AsmWriterEmitter.o `test -f 'llvm/utils/TableGen/AsmWriterEmitter.cpp' || echo '$(srcdir)/'`llvm/utils/TableGen/AsmWriterEmitter.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/tblgen-AsmWriterEmitter.Tpo $(DEPDIR)/tblgen-AsmWriterEmitter.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/utils/TableGen/AsmWriterEmitter.cpp' object='tblgen-AsmWriterEmitter.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tblgen_CPPFLAGS) $(CPPFLAGS) $(tblgen_CXXFLAGS) $(CXXFLAGS) -c -o tblgen-AsmWriterEmitter.o `test -f 'llvm/utils/TableGen/AsmWriterEmitter.cpp' || echo '$(srcdir)/'`llvm/utils/TableGen/AsmWriterEmitter.cpp + +tblgen-AsmWriterEmitter.obj: llvm/utils/TableGen/AsmWriterEmitter.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tblgen_CPPFLAGS) $(CPPFLAGS) $(tblgen_CXXFLAGS) $(CXXFLAGS) -MT tblgen-AsmWriterEmitter.obj -MD -MP -MF $(DEPDIR)/tblgen-AsmWriterEmitter.Tpo -c -o tblgen-AsmWriterEmitter.obj `if test -f 'llvm/utils/TableGen/AsmWriterEmitter.cpp'; then $(CYGPATH_W) 'llvm/utils/TableGen/AsmWriterEmitter.cpp'; else $(CYGPATH_W) '$(srcdir)/llvm/utils/TableGen/AsmWriterEmitter.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/tblgen-AsmWriterEmitter.Tpo $(DEPDIR)/tblgen-AsmWriterEmitter.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/utils/TableGen/AsmWriterEmitter.cpp' object='tblgen-AsmWriterEmitter.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tblgen_CPPFLAGS) $(CPPFLAGS) $(tblgen_CXXFLAGS) $(CXXFLAGS) -c -o tblgen-AsmWriterEmitter.obj `if test -f 'llvm/utils/TableGen/AsmWriterEmitter.cpp'; then $(CYGPATH_W) 'llvm/utils/TableGen/AsmWriterEmitter.cpp'; else $(CYGPATH_W) '$(srcdir)/llvm/utils/TableGen/AsmWriterEmitter.cpp'; fi` + +tblgen-CallingConvEmitter.o: llvm/utils/TableGen/CallingConvEmitter.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tblgen_CPPFLAGS) $(CPPFLAGS) $(tblgen_CXXFLAGS) $(CXXFLAGS) -MT tblgen-CallingConvEmitter.o -MD -MP -MF $(DEPDIR)/tblgen-CallingConvEmitter.Tpo -c -o tblgen-CallingConvEmitter.o `test -f 'llvm/utils/TableGen/CallingConvEmitter.cpp' || echo '$(srcdir)/'`llvm/utils/TableGen/CallingConvEmitter.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/tblgen-CallingConvEmitter.Tpo $(DEPDIR)/tblgen-CallingConvEmitter.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/utils/TableGen/CallingConvEmitter.cpp' object='tblgen-CallingConvEmitter.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tblgen_CPPFLAGS) $(CPPFLAGS) $(tblgen_CXXFLAGS) $(CXXFLAGS) -c -o tblgen-CallingConvEmitter.o `test -f 'llvm/utils/TableGen/CallingConvEmitter.cpp' || echo '$(srcdir)/'`llvm/utils/TableGen/CallingConvEmitter.cpp + +tblgen-CallingConvEmitter.obj: llvm/utils/TableGen/CallingConvEmitter.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tblgen_CPPFLAGS) $(CPPFLAGS) $(tblgen_CXXFLAGS) $(CXXFLAGS) -MT tblgen-CallingConvEmitter.obj -MD -MP -MF $(DEPDIR)/tblgen-CallingConvEmitter.Tpo -c -o tblgen-CallingConvEmitter.obj `if test -f 'llvm/utils/TableGen/CallingConvEmitter.cpp'; then $(CYGPATH_W) 'llvm/utils/TableGen/CallingConvEmitter.cpp'; else $(CYGPATH_W) '$(srcdir)/llvm/utils/TableGen/CallingConvEmitter.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/tblgen-CallingConvEmitter.Tpo $(DEPDIR)/tblgen-CallingConvEmitter.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/utils/TableGen/CallingConvEmitter.cpp' object='tblgen-CallingConvEmitter.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tblgen_CPPFLAGS) $(CPPFLAGS) $(tblgen_CXXFLAGS) $(CXXFLAGS) -c -o tblgen-CallingConvEmitter.obj `if test -f 'llvm/utils/TableGen/CallingConvEmitter.cpp'; then $(CYGPATH_W) 'llvm/utils/TableGen/CallingConvEmitter.cpp'; else $(CYGPATH_W) '$(srcdir)/llvm/utils/TableGen/CallingConvEmitter.cpp'; fi` + +tblgen-ClangDiagnosticsEmitter.o: llvm/utils/TableGen/ClangDiagnosticsEmitter.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tblgen_CPPFLAGS) $(CPPFLAGS) $(tblgen_CXXFLAGS) $(CXXFLAGS) -MT tblgen-ClangDiagnosticsEmitter.o -MD -MP -MF $(DEPDIR)/tblgen-ClangDiagnosticsEmitter.Tpo -c -o tblgen-ClangDiagnosticsEmitter.o `test -f 'llvm/utils/TableGen/ClangDiagnosticsEmitter.cpp' || echo '$(srcdir)/'`llvm/utils/TableGen/ClangDiagnosticsEmitter.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/tblgen-ClangDiagnosticsEmitter.Tpo $(DEPDIR)/tblgen-ClangDiagnosticsEmitter.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/utils/TableGen/ClangDiagnosticsEmitter.cpp' object='tblgen-ClangDiagnosticsEmitter.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tblgen_CPPFLAGS) $(CPPFLAGS) $(tblgen_CXXFLAGS) $(CXXFLAGS) -c -o tblgen-ClangDiagnosticsEmitter.o `test -f 'llvm/utils/TableGen/ClangDiagnosticsEmitter.cpp' || echo '$(srcdir)/'`llvm/utils/TableGen/ClangDiagnosticsEmitter.cpp + +tblgen-ClangDiagnosticsEmitter.obj: llvm/utils/TableGen/ClangDiagnosticsEmitter.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tblgen_CPPFLAGS) $(CPPFLAGS) $(tblgen_CXXFLAGS) $(CXXFLAGS) -MT tblgen-ClangDiagnosticsEmitter.obj -MD -MP -MF $(DEPDIR)/tblgen-ClangDiagnosticsEmitter.Tpo -c -o tblgen-ClangDiagnosticsEmitter.obj `if test -f 'llvm/utils/TableGen/ClangDiagnosticsEmitter.cpp'; then $(CYGPATH_W) 'llvm/utils/TableGen/ClangDiagnosticsEmitter.cpp'; else $(CYGPATH_W) '$(srcdir)/llvm/utils/TableGen/ClangDiagnosticsEmitter.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/tblgen-ClangDiagnosticsEmitter.Tpo $(DEPDIR)/tblgen-ClangDiagnosticsEmitter.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/utils/TableGen/ClangDiagnosticsEmitter.cpp' object='tblgen-ClangDiagnosticsEmitter.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tblgen_CPPFLAGS) $(CPPFLAGS) $(tblgen_CXXFLAGS) $(CXXFLAGS) -c -o tblgen-ClangDiagnosticsEmitter.obj `if test -f 'llvm/utils/TableGen/ClangDiagnosticsEmitter.cpp'; then $(CYGPATH_W) 'llvm/utils/TableGen/ClangDiagnosticsEmitter.cpp'; else $(CYGPATH_W) '$(srcdir)/llvm/utils/TableGen/ClangDiagnosticsEmitter.cpp'; fi` + +tblgen-CodeEmitterGen.o: llvm/utils/TableGen/CodeEmitterGen.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tblgen_CPPFLAGS) $(CPPFLAGS) $(tblgen_CXXFLAGS) $(CXXFLAGS) -MT tblgen-CodeEmitterGen.o -MD -MP -MF $(DEPDIR)/tblgen-CodeEmitterGen.Tpo -c -o tblgen-CodeEmitterGen.o `test -f 'llvm/utils/TableGen/CodeEmitterGen.cpp' || echo '$(srcdir)/'`llvm/utils/TableGen/CodeEmitterGen.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/tblgen-CodeEmitterGen.Tpo $(DEPDIR)/tblgen-CodeEmitterGen.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/utils/TableGen/CodeEmitterGen.cpp' object='tblgen-CodeEmitterGen.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tblgen_CPPFLAGS) $(CPPFLAGS) $(tblgen_CXXFLAGS) $(CXXFLAGS) -c -o tblgen-CodeEmitterGen.o `test -f 'llvm/utils/TableGen/CodeEmitterGen.cpp' || echo '$(srcdir)/'`llvm/utils/TableGen/CodeEmitterGen.cpp + +tblgen-CodeEmitterGen.obj: llvm/utils/TableGen/CodeEmitterGen.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tblgen_CPPFLAGS) $(CPPFLAGS) $(tblgen_CXXFLAGS) $(CXXFLAGS) -MT tblgen-CodeEmitterGen.obj -MD -MP -MF $(DEPDIR)/tblgen-CodeEmitterGen.Tpo -c -o tblgen-CodeEmitterGen.obj `if test -f 'llvm/utils/TableGen/CodeEmitterGen.cpp'; then $(CYGPATH_W) 'llvm/utils/TableGen/CodeEmitterGen.cpp'; else $(CYGPATH_W) '$(srcdir)/llvm/utils/TableGen/CodeEmitterGen.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/tblgen-CodeEmitterGen.Tpo $(DEPDIR)/tblgen-CodeEmitterGen.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/utils/TableGen/CodeEmitterGen.cpp' object='tblgen-CodeEmitterGen.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tblgen_CPPFLAGS) $(CPPFLAGS) $(tblgen_CXXFLAGS) $(CXXFLAGS) -c -o tblgen-CodeEmitterGen.obj `if test -f 'llvm/utils/TableGen/CodeEmitterGen.cpp'; then $(CYGPATH_W) 'llvm/utils/TableGen/CodeEmitterGen.cpp'; else $(CYGPATH_W) '$(srcdir)/llvm/utils/TableGen/CodeEmitterGen.cpp'; fi` + +tblgen-CodeGenDAGPatterns.o: llvm/utils/TableGen/CodeGenDAGPatterns.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tblgen_CPPFLAGS) $(CPPFLAGS) $(tblgen_CXXFLAGS) $(CXXFLAGS) -MT tblgen-CodeGenDAGPatterns.o -MD -MP -MF $(DEPDIR)/tblgen-CodeGenDAGPatterns.Tpo -c -o tblgen-CodeGenDAGPatterns.o `test -f 'llvm/utils/TableGen/CodeGenDAGPatterns.cpp' || echo '$(srcdir)/'`llvm/utils/TableGen/CodeGenDAGPatterns.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/tblgen-CodeGenDAGPatterns.Tpo $(DEPDIR)/tblgen-CodeGenDAGPatterns.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/utils/TableGen/CodeGenDAGPatterns.cpp' object='tblgen-CodeGenDAGPatterns.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tblgen_CPPFLAGS) $(CPPFLAGS) $(tblgen_CXXFLAGS) $(CXXFLAGS) -c -o tblgen-CodeGenDAGPatterns.o `test -f 'llvm/utils/TableGen/CodeGenDAGPatterns.cpp' || echo '$(srcdir)/'`llvm/utils/TableGen/CodeGenDAGPatterns.cpp + +tblgen-CodeGenDAGPatterns.obj: llvm/utils/TableGen/CodeGenDAGPatterns.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tblgen_CPPFLAGS) $(CPPFLAGS) $(tblgen_CXXFLAGS) $(CXXFLAGS) -MT tblgen-CodeGenDAGPatterns.obj -MD -MP -MF $(DEPDIR)/tblgen-CodeGenDAGPatterns.Tpo -c -o tblgen-CodeGenDAGPatterns.obj `if test -f 'llvm/utils/TableGen/CodeGenDAGPatterns.cpp'; then $(CYGPATH_W) 'llvm/utils/TableGen/CodeGenDAGPatterns.cpp'; else $(CYGPATH_W) '$(srcdir)/llvm/utils/TableGen/CodeGenDAGPatterns.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/tblgen-CodeGenDAGPatterns.Tpo $(DEPDIR)/tblgen-CodeGenDAGPatterns.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/utils/TableGen/CodeGenDAGPatterns.cpp' object='tblgen-CodeGenDAGPatterns.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tblgen_CPPFLAGS) $(CPPFLAGS) $(tblgen_CXXFLAGS) $(CXXFLAGS) -c -o tblgen-CodeGenDAGPatterns.obj `if test -f 'llvm/utils/TableGen/CodeGenDAGPatterns.cpp'; then $(CYGPATH_W) 'llvm/utils/TableGen/CodeGenDAGPatterns.cpp'; else $(CYGPATH_W) '$(srcdir)/llvm/utils/TableGen/CodeGenDAGPatterns.cpp'; fi` + +tblgen-CodeGenInstruction.o: llvm/utils/TableGen/CodeGenInstruction.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tblgen_CPPFLAGS) $(CPPFLAGS) $(tblgen_CXXFLAGS) $(CXXFLAGS) -MT tblgen-CodeGenInstruction.o -MD -MP -MF $(DEPDIR)/tblgen-CodeGenInstruction.Tpo -c -o tblgen-CodeGenInstruction.o `test -f 'llvm/utils/TableGen/CodeGenInstruction.cpp' || echo '$(srcdir)/'`llvm/utils/TableGen/CodeGenInstruction.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/tblgen-CodeGenInstruction.Tpo $(DEPDIR)/tblgen-CodeGenInstruction.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/utils/TableGen/CodeGenInstruction.cpp' object='tblgen-CodeGenInstruction.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tblgen_CPPFLAGS) $(CPPFLAGS) $(tblgen_CXXFLAGS) $(CXXFLAGS) -c -o tblgen-CodeGenInstruction.o `test -f 'llvm/utils/TableGen/CodeGenInstruction.cpp' || echo '$(srcdir)/'`llvm/utils/TableGen/CodeGenInstruction.cpp + +tblgen-CodeGenInstruction.obj: llvm/utils/TableGen/CodeGenInstruction.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tblgen_CPPFLAGS) $(CPPFLAGS) $(tblgen_CXXFLAGS) $(CXXFLAGS) -MT tblgen-CodeGenInstruction.obj -MD -MP -MF $(DEPDIR)/tblgen-CodeGenInstruction.Tpo -c -o tblgen-CodeGenInstruction.obj `if test -f 'llvm/utils/TableGen/CodeGenInstruction.cpp'; then $(CYGPATH_W) 'llvm/utils/TableGen/CodeGenInstruction.cpp'; else $(CYGPATH_W) '$(srcdir)/llvm/utils/TableGen/CodeGenInstruction.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/tblgen-CodeGenInstruction.Tpo $(DEPDIR)/tblgen-CodeGenInstruction.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/utils/TableGen/CodeGenInstruction.cpp' object='tblgen-CodeGenInstruction.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tblgen_CPPFLAGS) $(CPPFLAGS) $(tblgen_CXXFLAGS) $(CXXFLAGS) -c -o tblgen-CodeGenInstruction.obj `if test -f 'llvm/utils/TableGen/CodeGenInstruction.cpp'; then $(CYGPATH_W) 'llvm/utils/TableGen/CodeGenInstruction.cpp'; else $(CYGPATH_W) '$(srcdir)/llvm/utils/TableGen/CodeGenInstruction.cpp'; fi` + +tblgen-CodeGenTarget.o: llvm/utils/TableGen/CodeGenTarget.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tblgen_CPPFLAGS) $(CPPFLAGS) $(tblgen_CXXFLAGS) $(CXXFLAGS) -MT tblgen-CodeGenTarget.o -MD -MP -MF $(DEPDIR)/tblgen-CodeGenTarget.Tpo -c -o tblgen-CodeGenTarget.o `test -f 'llvm/utils/TableGen/CodeGenTarget.cpp' || echo '$(srcdir)/'`llvm/utils/TableGen/CodeGenTarget.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/tblgen-CodeGenTarget.Tpo $(DEPDIR)/tblgen-CodeGenTarget.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/utils/TableGen/CodeGenTarget.cpp' object='tblgen-CodeGenTarget.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tblgen_CPPFLAGS) $(CPPFLAGS) $(tblgen_CXXFLAGS) $(CXXFLAGS) -c -o tblgen-CodeGenTarget.o `test -f 'llvm/utils/TableGen/CodeGenTarget.cpp' || echo '$(srcdir)/'`llvm/utils/TableGen/CodeGenTarget.cpp + +tblgen-CodeGenTarget.obj: llvm/utils/TableGen/CodeGenTarget.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tblgen_CPPFLAGS) $(CPPFLAGS) $(tblgen_CXXFLAGS) $(CXXFLAGS) -MT tblgen-CodeGenTarget.obj -MD -MP -MF $(DEPDIR)/tblgen-CodeGenTarget.Tpo -c -o tblgen-CodeGenTarget.obj `if test -f 'llvm/utils/TableGen/CodeGenTarget.cpp'; then $(CYGPATH_W) 'llvm/utils/TableGen/CodeGenTarget.cpp'; else $(CYGPATH_W) '$(srcdir)/llvm/utils/TableGen/CodeGenTarget.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/tblgen-CodeGenTarget.Tpo $(DEPDIR)/tblgen-CodeGenTarget.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/utils/TableGen/CodeGenTarget.cpp' object='tblgen-CodeGenTarget.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tblgen_CPPFLAGS) $(CPPFLAGS) $(tblgen_CXXFLAGS) $(CXXFLAGS) -c -o tblgen-CodeGenTarget.obj `if test -f 'llvm/utils/TableGen/CodeGenTarget.cpp'; then $(CYGPATH_W) 'llvm/utils/TableGen/CodeGenTarget.cpp'; else $(CYGPATH_W) '$(srcdir)/llvm/utils/TableGen/CodeGenTarget.cpp'; fi` + +tblgen-DisassemblerEmitter.o: llvm/utils/TableGen/DisassemblerEmitter.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tblgen_CPPFLAGS) $(CPPFLAGS) $(tblgen_CXXFLAGS) $(CXXFLAGS) -MT tblgen-DisassemblerEmitter.o -MD -MP -MF $(DEPDIR)/tblgen-DisassemblerEmitter.Tpo -c -o tblgen-DisassemblerEmitter.o `test -f 'llvm/utils/TableGen/DisassemblerEmitter.cpp' || echo '$(srcdir)/'`llvm/utils/TableGen/DisassemblerEmitter.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/tblgen-DisassemblerEmitter.Tpo $(DEPDIR)/tblgen-DisassemblerEmitter.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/utils/TableGen/DisassemblerEmitter.cpp' object='tblgen-DisassemblerEmitter.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tblgen_CPPFLAGS) $(CPPFLAGS) $(tblgen_CXXFLAGS) $(CXXFLAGS) -c -o tblgen-DisassemblerEmitter.o `test -f 'llvm/utils/TableGen/DisassemblerEmitter.cpp' || echo '$(srcdir)/'`llvm/utils/TableGen/DisassemblerEmitter.cpp + +tblgen-DisassemblerEmitter.obj: llvm/utils/TableGen/DisassemblerEmitter.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tblgen_CPPFLAGS) $(CPPFLAGS) $(tblgen_CXXFLAGS) $(CXXFLAGS) -MT tblgen-DisassemblerEmitter.obj -MD -MP -MF $(DEPDIR)/tblgen-DisassemblerEmitter.Tpo -c -o tblgen-DisassemblerEmitter.obj `if test -f 'llvm/utils/TableGen/DisassemblerEmitter.cpp'; then $(CYGPATH_W) 'llvm/utils/TableGen/DisassemblerEmitter.cpp'; else $(CYGPATH_W) '$(srcdir)/llvm/utils/TableGen/DisassemblerEmitter.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/tblgen-DisassemblerEmitter.Tpo $(DEPDIR)/tblgen-DisassemblerEmitter.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/utils/TableGen/DisassemblerEmitter.cpp' object='tblgen-DisassemblerEmitter.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tblgen_CPPFLAGS) $(CPPFLAGS) $(tblgen_CXXFLAGS) $(CXXFLAGS) -c -o tblgen-DisassemblerEmitter.obj `if test -f 'llvm/utils/TableGen/DisassemblerEmitter.cpp'; then $(CYGPATH_W) 'llvm/utils/TableGen/DisassemblerEmitter.cpp'; else $(CYGPATH_W) '$(srcdir)/llvm/utils/TableGen/DisassemblerEmitter.cpp'; fi` + +tblgen-DAGISelEmitter.o: llvm/utils/TableGen/DAGISelEmitter.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tblgen_CPPFLAGS) $(CPPFLAGS) $(tblgen_CXXFLAGS) $(CXXFLAGS) -MT tblgen-DAGISelEmitter.o -MD -MP -MF $(DEPDIR)/tblgen-DAGISelEmitter.Tpo -c -o tblgen-DAGISelEmitter.o `test -f 'llvm/utils/TableGen/DAGISelEmitter.cpp' || echo '$(srcdir)/'`llvm/utils/TableGen/DAGISelEmitter.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/tblgen-DAGISelEmitter.Tpo $(DEPDIR)/tblgen-DAGISelEmitter.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/utils/TableGen/DAGISelEmitter.cpp' object='tblgen-DAGISelEmitter.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tblgen_CPPFLAGS) $(CPPFLAGS) $(tblgen_CXXFLAGS) $(CXXFLAGS) -c -o tblgen-DAGISelEmitter.o `test -f 'llvm/utils/TableGen/DAGISelEmitter.cpp' || echo '$(srcdir)/'`llvm/utils/TableGen/DAGISelEmitter.cpp + +tblgen-DAGISelEmitter.obj: llvm/utils/TableGen/DAGISelEmitter.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tblgen_CPPFLAGS) $(CPPFLAGS) $(tblgen_CXXFLAGS) $(CXXFLAGS) -MT tblgen-DAGISelEmitter.obj -MD -MP -MF $(DEPDIR)/tblgen-DAGISelEmitter.Tpo -c -o tblgen-DAGISelEmitter.obj `if test -f 'llvm/utils/TableGen/DAGISelEmitter.cpp'; then $(CYGPATH_W) 'llvm/utils/TableGen/DAGISelEmitter.cpp'; else $(CYGPATH_W) '$(srcdir)/llvm/utils/TableGen/DAGISelEmitter.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/tblgen-DAGISelEmitter.Tpo $(DEPDIR)/tblgen-DAGISelEmitter.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/utils/TableGen/DAGISelEmitter.cpp' object='tblgen-DAGISelEmitter.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tblgen_CPPFLAGS) $(CPPFLAGS) $(tblgen_CXXFLAGS) $(CXXFLAGS) -c -o tblgen-DAGISelEmitter.obj `if test -f 'llvm/utils/TableGen/DAGISelEmitter.cpp'; then $(CYGPATH_W) 'llvm/utils/TableGen/DAGISelEmitter.cpp'; else $(CYGPATH_W) '$(srcdir)/llvm/utils/TableGen/DAGISelEmitter.cpp'; fi` + +tblgen-FastISelEmitter.o: llvm/utils/TableGen/FastISelEmitter.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tblgen_CPPFLAGS) $(CPPFLAGS) $(tblgen_CXXFLAGS) $(CXXFLAGS) -MT tblgen-FastISelEmitter.o -MD -MP -MF $(DEPDIR)/tblgen-FastISelEmitter.Tpo -c -o tblgen-FastISelEmitter.o `test -f 'llvm/utils/TableGen/FastISelEmitter.cpp' || echo '$(srcdir)/'`llvm/utils/TableGen/FastISelEmitter.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/tblgen-FastISelEmitter.Tpo $(DEPDIR)/tblgen-FastISelEmitter.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/utils/TableGen/FastISelEmitter.cpp' object='tblgen-FastISelEmitter.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tblgen_CPPFLAGS) $(CPPFLAGS) $(tblgen_CXXFLAGS) $(CXXFLAGS) -c -o tblgen-FastISelEmitter.o `test -f 'llvm/utils/TableGen/FastISelEmitter.cpp' || echo '$(srcdir)/'`llvm/utils/TableGen/FastISelEmitter.cpp + +tblgen-FastISelEmitter.obj: llvm/utils/TableGen/FastISelEmitter.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tblgen_CPPFLAGS) $(CPPFLAGS) $(tblgen_CXXFLAGS) $(CXXFLAGS) -MT tblgen-FastISelEmitter.obj -MD -MP -MF $(DEPDIR)/tblgen-FastISelEmitter.Tpo -c -o tblgen-FastISelEmitter.obj `if test -f 'llvm/utils/TableGen/FastISelEmitter.cpp'; then $(CYGPATH_W) 'llvm/utils/TableGen/FastISelEmitter.cpp'; else $(CYGPATH_W) '$(srcdir)/llvm/utils/TableGen/FastISelEmitter.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/tblgen-FastISelEmitter.Tpo $(DEPDIR)/tblgen-FastISelEmitter.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/utils/TableGen/FastISelEmitter.cpp' object='tblgen-FastISelEmitter.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tblgen_CPPFLAGS) $(CPPFLAGS) $(tblgen_CXXFLAGS) $(CXXFLAGS) -c -o tblgen-FastISelEmitter.obj `if test -f 'llvm/utils/TableGen/FastISelEmitter.cpp'; then $(CYGPATH_W) 'llvm/utils/TableGen/FastISelEmitter.cpp'; else $(CYGPATH_W) '$(srcdir)/llvm/utils/TableGen/FastISelEmitter.cpp'; fi` + +tblgen-InstrEnumEmitter.o: llvm/utils/TableGen/InstrEnumEmitter.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tblgen_CPPFLAGS) $(CPPFLAGS) $(tblgen_CXXFLAGS) $(CXXFLAGS) -MT tblgen-InstrEnumEmitter.o -MD -MP -MF $(DEPDIR)/tblgen-InstrEnumEmitter.Tpo -c -o tblgen-InstrEnumEmitter.o `test -f 'llvm/utils/TableGen/InstrEnumEmitter.cpp' || echo '$(srcdir)/'`llvm/utils/TableGen/InstrEnumEmitter.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/tblgen-InstrEnumEmitter.Tpo $(DEPDIR)/tblgen-InstrEnumEmitter.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/utils/TableGen/InstrEnumEmitter.cpp' object='tblgen-InstrEnumEmitter.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tblgen_CPPFLAGS) $(CPPFLAGS) $(tblgen_CXXFLAGS) $(CXXFLAGS) -c -o tblgen-InstrEnumEmitter.o `test -f 'llvm/utils/TableGen/InstrEnumEmitter.cpp' || echo '$(srcdir)/'`llvm/utils/TableGen/InstrEnumEmitter.cpp + +tblgen-InstrEnumEmitter.obj: llvm/utils/TableGen/InstrEnumEmitter.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tblgen_CPPFLAGS) $(CPPFLAGS) $(tblgen_CXXFLAGS) $(CXXFLAGS) -MT tblgen-InstrEnumEmitter.obj -MD -MP -MF $(DEPDIR)/tblgen-InstrEnumEmitter.Tpo -c -o tblgen-InstrEnumEmitter.obj `if test -f 'llvm/utils/TableGen/InstrEnumEmitter.cpp'; then $(CYGPATH_W) 'llvm/utils/TableGen/InstrEnumEmitter.cpp'; else $(CYGPATH_W) '$(srcdir)/llvm/utils/TableGen/InstrEnumEmitter.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/tblgen-InstrEnumEmitter.Tpo $(DEPDIR)/tblgen-InstrEnumEmitter.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/utils/TableGen/InstrEnumEmitter.cpp' object='tblgen-InstrEnumEmitter.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tblgen_CPPFLAGS) $(CPPFLAGS) $(tblgen_CXXFLAGS) $(CXXFLAGS) -c -o tblgen-InstrEnumEmitter.obj `if test -f 'llvm/utils/TableGen/InstrEnumEmitter.cpp'; then $(CYGPATH_W) 'llvm/utils/TableGen/InstrEnumEmitter.cpp'; else $(CYGPATH_W) '$(srcdir)/llvm/utils/TableGen/InstrEnumEmitter.cpp'; fi` + +tblgen-InstrInfoEmitter.o: llvm/utils/TableGen/InstrInfoEmitter.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tblgen_CPPFLAGS) $(CPPFLAGS) $(tblgen_CXXFLAGS) $(CXXFLAGS) -MT tblgen-InstrInfoEmitter.o -MD -MP -MF $(DEPDIR)/tblgen-InstrInfoEmitter.Tpo -c -o tblgen-InstrInfoEmitter.o `test -f 'llvm/utils/TableGen/InstrInfoEmitter.cpp' || echo '$(srcdir)/'`llvm/utils/TableGen/InstrInfoEmitter.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/tblgen-InstrInfoEmitter.Tpo $(DEPDIR)/tblgen-InstrInfoEmitter.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/utils/TableGen/InstrInfoEmitter.cpp' object='tblgen-InstrInfoEmitter.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tblgen_CPPFLAGS) $(CPPFLAGS) $(tblgen_CXXFLAGS) $(CXXFLAGS) -c -o tblgen-InstrInfoEmitter.o `test -f 'llvm/utils/TableGen/InstrInfoEmitter.cpp' || echo '$(srcdir)/'`llvm/utils/TableGen/InstrInfoEmitter.cpp + +tblgen-InstrInfoEmitter.obj: llvm/utils/TableGen/InstrInfoEmitter.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tblgen_CPPFLAGS) $(CPPFLAGS) $(tblgen_CXXFLAGS) $(CXXFLAGS) -MT tblgen-InstrInfoEmitter.obj -MD -MP -MF $(DEPDIR)/tblgen-InstrInfoEmitter.Tpo -c -o tblgen-InstrInfoEmitter.obj `if test -f 'llvm/utils/TableGen/InstrInfoEmitter.cpp'; then $(CYGPATH_W) 'llvm/utils/TableGen/InstrInfoEmitter.cpp'; else $(CYGPATH_W) '$(srcdir)/llvm/utils/TableGen/InstrInfoEmitter.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/tblgen-InstrInfoEmitter.Tpo $(DEPDIR)/tblgen-InstrInfoEmitter.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/utils/TableGen/InstrInfoEmitter.cpp' object='tblgen-InstrInfoEmitter.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tblgen_CPPFLAGS) $(CPPFLAGS) $(tblgen_CXXFLAGS) $(CXXFLAGS) -c -o tblgen-InstrInfoEmitter.obj `if test -f 'llvm/utils/TableGen/InstrInfoEmitter.cpp'; then $(CYGPATH_W) 'llvm/utils/TableGen/InstrInfoEmitter.cpp'; else $(CYGPATH_W) '$(srcdir)/llvm/utils/TableGen/InstrInfoEmitter.cpp'; fi` + +tblgen-IntrinsicEmitter.o: llvm/utils/TableGen/IntrinsicEmitter.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tblgen_CPPFLAGS) $(CPPFLAGS) $(tblgen_CXXFLAGS) $(CXXFLAGS) -MT tblgen-IntrinsicEmitter.o -MD -MP -MF $(DEPDIR)/tblgen-IntrinsicEmitter.Tpo -c -o tblgen-IntrinsicEmitter.o `test -f 'llvm/utils/TableGen/IntrinsicEmitter.cpp' || echo '$(srcdir)/'`llvm/utils/TableGen/IntrinsicEmitter.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/tblgen-IntrinsicEmitter.Tpo $(DEPDIR)/tblgen-IntrinsicEmitter.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/utils/TableGen/IntrinsicEmitter.cpp' object='tblgen-IntrinsicEmitter.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tblgen_CPPFLAGS) $(CPPFLAGS) $(tblgen_CXXFLAGS) $(CXXFLAGS) -c -o tblgen-IntrinsicEmitter.o `test -f 'llvm/utils/TableGen/IntrinsicEmitter.cpp' || echo '$(srcdir)/'`llvm/utils/TableGen/IntrinsicEmitter.cpp + +tblgen-IntrinsicEmitter.obj: llvm/utils/TableGen/IntrinsicEmitter.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tblgen_CPPFLAGS) $(CPPFLAGS) $(tblgen_CXXFLAGS) $(CXXFLAGS) -MT tblgen-IntrinsicEmitter.obj -MD -MP -MF $(DEPDIR)/tblgen-IntrinsicEmitter.Tpo -c -o tblgen-IntrinsicEmitter.obj `if test -f 'llvm/utils/TableGen/IntrinsicEmitter.cpp'; then $(CYGPATH_W) 'llvm/utils/TableGen/IntrinsicEmitter.cpp'; else $(CYGPATH_W) '$(srcdir)/llvm/utils/TableGen/IntrinsicEmitter.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/tblgen-IntrinsicEmitter.Tpo $(DEPDIR)/tblgen-IntrinsicEmitter.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/utils/TableGen/IntrinsicEmitter.cpp' object='tblgen-IntrinsicEmitter.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tblgen_CPPFLAGS) $(CPPFLAGS) $(tblgen_CXXFLAGS) $(CXXFLAGS) -c -o tblgen-IntrinsicEmitter.obj `if test -f 'llvm/utils/TableGen/IntrinsicEmitter.cpp'; then $(CYGPATH_W) 'llvm/utils/TableGen/IntrinsicEmitter.cpp'; else $(CYGPATH_W) '$(srcdir)/llvm/utils/TableGen/IntrinsicEmitter.cpp'; fi` + +tblgen-LLVMCConfigurationEmitter.o: llvm/utils/TableGen/LLVMCConfigurationEmitter.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tblgen_CPPFLAGS) $(CPPFLAGS) $(tblgen_CXXFLAGS) $(CXXFLAGS) -MT tblgen-LLVMCConfigurationEmitter.o -MD -MP -MF $(DEPDIR)/tblgen-LLVMCConfigurationEmitter.Tpo -c -o tblgen-LLVMCConfigurationEmitter.o `test -f 'llvm/utils/TableGen/LLVMCConfigurationEmitter.cpp' || echo '$(srcdir)/'`llvm/utils/TableGen/LLVMCConfigurationEmitter.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/tblgen-LLVMCConfigurationEmitter.Tpo $(DEPDIR)/tblgen-LLVMCConfigurationEmitter.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/utils/TableGen/LLVMCConfigurationEmitter.cpp' object='tblgen-LLVMCConfigurationEmitter.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tblgen_CPPFLAGS) $(CPPFLAGS) $(tblgen_CXXFLAGS) $(CXXFLAGS) -c -o tblgen-LLVMCConfigurationEmitter.o `test -f 'llvm/utils/TableGen/LLVMCConfigurationEmitter.cpp' || echo '$(srcdir)/'`llvm/utils/TableGen/LLVMCConfigurationEmitter.cpp + +tblgen-LLVMCConfigurationEmitter.obj: llvm/utils/TableGen/LLVMCConfigurationEmitter.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tblgen_CPPFLAGS) $(CPPFLAGS) $(tblgen_CXXFLAGS) $(CXXFLAGS) -MT tblgen-LLVMCConfigurationEmitter.obj -MD -MP -MF $(DEPDIR)/tblgen-LLVMCConfigurationEmitter.Tpo -c -o tblgen-LLVMCConfigurationEmitter.obj `if test -f 'llvm/utils/TableGen/LLVMCConfigurationEmitter.cpp'; then $(CYGPATH_W) 'llvm/utils/TableGen/LLVMCConfigurationEmitter.cpp'; else $(CYGPATH_W) '$(srcdir)/llvm/utils/TableGen/LLVMCConfigurationEmitter.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/tblgen-LLVMCConfigurationEmitter.Tpo $(DEPDIR)/tblgen-LLVMCConfigurationEmitter.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/utils/TableGen/LLVMCConfigurationEmitter.cpp' object='tblgen-LLVMCConfigurationEmitter.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tblgen_CPPFLAGS) $(CPPFLAGS) $(tblgen_CXXFLAGS) $(CXXFLAGS) -c -o tblgen-LLVMCConfigurationEmitter.obj `if test -f 'llvm/utils/TableGen/LLVMCConfigurationEmitter.cpp'; then $(CYGPATH_W) 'llvm/utils/TableGen/LLVMCConfigurationEmitter.cpp'; else $(CYGPATH_W) '$(srcdir)/llvm/utils/TableGen/LLVMCConfigurationEmitter.cpp'; fi` + +tblgen-OptParserEmitter.o: llvm/utils/TableGen/OptParserEmitter.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tblgen_CPPFLAGS) $(CPPFLAGS) $(tblgen_CXXFLAGS) $(CXXFLAGS) -MT tblgen-OptParserEmitter.o -MD -MP -MF $(DEPDIR)/tblgen-OptParserEmitter.Tpo -c -o tblgen-OptParserEmitter.o `test -f 'llvm/utils/TableGen/OptParserEmitter.cpp' || echo '$(srcdir)/'`llvm/utils/TableGen/OptParserEmitter.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/tblgen-OptParserEmitter.Tpo $(DEPDIR)/tblgen-OptParserEmitter.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/utils/TableGen/OptParserEmitter.cpp' object='tblgen-OptParserEmitter.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tblgen_CPPFLAGS) $(CPPFLAGS) $(tblgen_CXXFLAGS) $(CXXFLAGS) -c -o tblgen-OptParserEmitter.o `test -f 'llvm/utils/TableGen/OptParserEmitter.cpp' || echo '$(srcdir)/'`llvm/utils/TableGen/OptParserEmitter.cpp + +tblgen-OptParserEmitter.obj: llvm/utils/TableGen/OptParserEmitter.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tblgen_CPPFLAGS) $(CPPFLAGS) $(tblgen_CXXFLAGS) $(CXXFLAGS) -MT tblgen-OptParserEmitter.obj -MD -MP -MF $(DEPDIR)/tblgen-OptParserEmitter.Tpo -c -o tblgen-OptParserEmitter.obj `if test -f 'llvm/utils/TableGen/OptParserEmitter.cpp'; then $(CYGPATH_W) 'llvm/utils/TableGen/OptParserEmitter.cpp'; else $(CYGPATH_W) '$(srcdir)/llvm/utils/TableGen/OptParserEmitter.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/tblgen-OptParserEmitter.Tpo $(DEPDIR)/tblgen-OptParserEmitter.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/utils/TableGen/OptParserEmitter.cpp' object='tblgen-OptParserEmitter.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tblgen_CPPFLAGS) $(CPPFLAGS) $(tblgen_CXXFLAGS) $(CXXFLAGS) -c -o tblgen-OptParserEmitter.obj `if test -f 'llvm/utils/TableGen/OptParserEmitter.cpp'; then $(CYGPATH_W) 'llvm/utils/TableGen/OptParserEmitter.cpp'; else $(CYGPATH_W) '$(srcdir)/llvm/utils/TableGen/OptParserEmitter.cpp'; fi` + +tblgen-Record.o: llvm/utils/TableGen/Record.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tblgen_CPPFLAGS) $(CPPFLAGS) $(tblgen_CXXFLAGS) $(CXXFLAGS) -MT tblgen-Record.o -MD -MP -MF $(DEPDIR)/tblgen-Record.Tpo -c -o tblgen-Record.o `test -f 'llvm/utils/TableGen/Record.cpp' || echo '$(srcdir)/'`llvm/utils/TableGen/Record.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/tblgen-Record.Tpo $(DEPDIR)/tblgen-Record.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/utils/TableGen/Record.cpp' object='tblgen-Record.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tblgen_CPPFLAGS) $(CPPFLAGS) $(tblgen_CXXFLAGS) $(CXXFLAGS) -c -o tblgen-Record.o `test -f 'llvm/utils/TableGen/Record.cpp' || echo '$(srcdir)/'`llvm/utils/TableGen/Record.cpp + +tblgen-Record.obj: llvm/utils/TableGen/Record.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tblgen_CPPFLAGS) $(CPPFLAGS) $(tblgen_CXXFLAGS) $(CXXFLAGS) -MT tblgen-Record.obj -MD -MP -MF $(DEPDIR)/tblgen-Record.Tpo -c -o tblgen-Record.obj `if test -f 'llvm/utils/TableGen/Record.cpp'; then $(CYGPATH_W) 'llvm/utils/TableGen/Record.cpp'; else $(CYGPATH_W) '$(srcdir)/llvm/utils/TableGen/Record.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/tblgen-Record.Tpo $(DEPDIR)/tblgen-Record.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/utils/TableGen/Record.cpp' object='tblgen-Record.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tblgen_CPPFLAGS) $(CPPFLAGS) $(tblgen_CXXFLAGS) $(CXXFLAGS) -c -o tblgen-Record.obj `if test -f 'llvm/utils/TableGen/Record.cpp'; then $(CYGPATH_W) 'llvm/utils/TableGen/Record.cpp'; else $(CYGPATH_W) '$(srcdir)/llvm/utils/TableGen/Record.cpp'; fi` + +tblgen-RegisterInfoEmitter.o: llvm/utils/TableGen/RegisterInfoEmitter.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tblgen_CPPFLAGS) $(CPPFLAGS) $(tblgen_CXXFLAGS) $(CXXFLAGS) -MT tblgen-RegisterInfoEmitter.o -MD -MP -MF $(DEPDIR)/tblgen-RegisterInfoEmitter.Tpo -c -o tblgen-RegisterInfoEmitter.o `test -f 'llvm/utils/TableGen/RegisterInfoEmitter.cpp' || echo '$(srcdir)/'`llvm/utils/TableGen/RegisterInfoEmitter.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/tblgen-RegisterInfoEmitter.Tpo $(DEPDIR)/tblgen-RegisterInfoEmitter.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/utils/TableGen/RegisterInfoEmitter.cpp' object='tblgen-RegisterInfoEmitter.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tblgen_CPPFLAGS) $(CPPFLAGS) $(tblgen_CXXFLAGS) $(CXXFLAGS) -c -o tblgen-RegisterInfoEmitter.o `test -f 'llvm/utils/TableGen/RegisterInfoEmitter.cpp' || echo '$(srcdir)/'`llvm/utils/TableGen/RegisterInfoEmitter.cpp + +tblgen-RegisterInfoEmitter.obj: llvm/utils/TableGen/RegisterInfoEmitter.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tblgen_CPPFLAGS) $(CPPFLAGS) $(tblgen_CXXFLAGS) $(CXXFLAGS) -MT tblgen-RegisterInfoEmitter.obj -MD -MP -MF $(DEPDIR)/tblgen-RegisterInfoEmitter.Tpo -c -o tblgen-RegisterInfoEmitter.obj `if test -f 'llvm/utils/TableGen/RegisterInfoEmitter.cpp'; then $(CYGPATH_W) 'llvm/utils/TableGen/RegisterInfoEmitter.cpp'; else $(CYGPATH_W) '$(srcdir)/llvm/utils/TableGen/RegisterInfoEmitter.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/tblgen-RegisterInfoEmitter.Tpo $(DEPDIR)/tblgen-RegisterInfoEmitter.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/utils/TableGen/RegisterInfoEmitter.cpp' object='tblgen-RegisterInfoEmitter.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tblgen_CPPFLAGS) $(CPPFLAGS) $(tblgen_CXXFLAGS) $(CXXFLAGS) -c -o tblgen-RegisterInfoEmitter.obj `if test -f 'llvm/utils/TableGen/RegisterInfoEmitter.cpp'; then $(CYGPATH_W) 'llvm/utils/TableGen/RegisterInfoEmitter.cpp'; else $(CYGPATH_W) '$(srcdir)/llvm/utils/TableGen/RegisterInfoEmitter.cpp'; fi` + +tblgen-SubtargetEmitter.o: llvm/utils/TableGen/SubtargetEmitter.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tblgen_CPPFLAGS) $(CPPFLAGS) $(tblgen_CXXFLAGS) $(CXXFLAGS) -MT tblgen-SubtargetEmitter.o -MD -MP -MF $(DEPDIR)/tblgen-SubtargetEmitter.Tpo -c -o tblgen-SubtargetEmitter.o `test -f 'llvm/utils/TableGen/SubtargetEmitter.cpp' || echo '$(srcdir)/'`llvm/utils/TableGen/SubtargetEmitter.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/tblgen-SubtargetEmitter.Tpo $(DEPDIR)/tblgen-SubtargetEmitter.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/utils/TableGen/SubtargetEmitter.cpp' object='tblgen-SubtargetEmitter.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tblgen_CPPFLAGS) $(CPPFLAGS) $(tblgen_CXXFLAGS) $(CXXFLAGS) -c -o tblgen-SubtargetEmitter.o `test -f 'llvm/utils/TableGen/SubtargetEmitter.cpp' || echo '$(srcdir)/'`llvm/utils/TableGen/SubtargetEmitter.cpp + +tblgen-SubtargetEmitter.obj: llvm/utils/TableGen/SubtargetEmitter.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tblgen_CPPFLAGS) $(CPPFLAGS) $(tblgen_CXXFLAGS) $(CXXFLAGS) -MT tblgen-SubtargetEmitter.obj -MD -MP -MF $(DEPDIR)/tblgen-SubtargetEmitter.Tpo -c -o tblgen-SubtargetEmitter.obj `if test -f 'llvm/utils/TableGen/SubtargetEmitter.cpp'; then $(CYGPATH_W) 'llvm/utils/TableGen/SubtargetEmitter.cpp'; else $(CYGPATH_W) '$(srcdir)/llvm/utils/TableGen/SubtargetEmitter.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/tblgen-SubtargetEmitter.Tpo $(DEPDIR)/tblgen-SubtargetEmitter.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/utils/TableGen/SubtargetEmitter.cpp' object='tblgen-SubtargetEmitter.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tblgen_CPPFLAGS) $(CPPFLAGS) $(tblgen_CXXFLAGS) $(CXXFLAGS) -c -o tblgen-SubtargetEmitter.obj `if test -f 'llvm/utils/TableGen/SubtargetEmitter.cpp'; then $(CYGPATH_W) 'llvm/utils/TableGen/SubtargetEmitter.cpp'; else $(CYGPATH_W) '$(srcdir)/llvm/utils/TableGen/SubtargetEmitter.cpp'; fi` + +tblgen-TGLexer.o: llvm/utils/TableGen/TGLexer.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tblgen_CPPFLAGS) $(CPPFLAGS) $(tblgen_CXXFLAGS) $(CXXFLAGS) -MT tblgen-TGLexer.o -MD -MP -MF $(DEPDIR)/tblgen-TGLexer.Tpo -c -o tblgen-TGLexer.o `test -f 'llvm/utils/TableGen/TGLexer.cpp' || echo '$(srcdir)/'`llvm/utils/TableGen/TGLexer.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/tblgen-TGLexer.Tpo $(DEPDIR)/tblgen-TGLexer.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/utils/TableGen/TGLexer.cpp' object='tblgen-TGLexer.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tblgen_CPPFLAGS) $(CPPFLAGS) $(tblgen_CXXFLAGS) $(CXXFLAGS) -c -o tblgen-TGLexer.o `test -f 'llvm/utils/TableGen/TGLexer.cpp' || echo '$(srcdir)/'`llvm/utils/TableGen/TGLexer.cpp + +tblgen-TGLexer.obj: llvm/utils/TableGen/TGLexer.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tblgen_CPPFLAGS) $(CPPFLAGS) $(tblgen_CXXFLAGS) $(CXXFLAGS) -MT tblgen-TGLexer.obj -MD -MP -MF $(DEPDIR)/tblgen-TGLexer.Tpo -c -o tblgen-TGLexer.obj `if test -f 'llvm/utils/TableGen/TGLexer.cpp'; then $(CYGPATH_W) 'llvm/utils/TableGen/TGLexer.cpp'; else $(CYGPATH_W) '$(srcdir)/llvm/utils/TableGen/TGLexer.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/tblgen-TGLexer.Tpo $(DEPDIR)/tblgen-TGLexer.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/utils/TableGen/TGLexer.cpp' object='tblgen-TGLexer.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tblgen_CPPFLAGS) $(CPPFLAGS) $(tblgen_CXXFLAGS) $(CXXFLAGS) -c -o tblgen-TGLexer.obj `if test -f 'llvm/utils/TableGen/TGLexer.cpp'; then $(CYGPATH_W) 'llvm/utils/TableGen/TGLexer.cpp'; else $(CYGPATH_W) '$(srcdir)/llvm/utils/TableGen/TGLexer.cpp'; fi` + +tblgen-TGParser.o: llvm/utils/TableGen/TGParser.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tblgen_CPPFLAGS) $(CPPFLAGS) $(tblgen_CXXFLAGS) $(CXXFLAGS) -MT tblgen-TGParser.o -MD -MP -MF $(DEPDIR)/tblgen-TGParser.Tpo -c -o tblgen-TGParser.o `test -f 'llvm/utils/TableGen/TGParser.cpp' || echo '$(srcdir)/'`llvm/utils/TableGen/TGParser.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/tblgen-TGParser.Tpo $(DEPDIR)/tblgen-TGParser.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/utils/TableGen/TGParser.cpp' object='tblgen-TGParser.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tblgen_CPPFLAGS) $(CPPFLAGS) $(tblgen_CXXFLAGS) $(CXXFLAGS) -c -o tblgen-TGParser.o `test -f 'llvm/utils/TableGen/TGParser.cpp' || echo '$(srcdir)/'`llvm/utils/TableGen/TGParser.cpp + +tblgen-TGParser.obj: llvm/utils/TableGen/TGParser.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tblgen_CPPFLAGS) $(CPPFLAGS) $(tblgen_CXXFLAGS) $(CXXFLAGS) -MT tblgen-TGParser.obj -MD -MP -MF $(DEPDIR)/tblgen-TGParser.Tpo -c -o tblgen-TGParser.obj `if test -f 'llvm/utils/TableGen/TGParser.cpp'; then $(CYGPATH_W) 'llvm/utils/TableGen/TGParser.cpp'; else $(CYGPATH_W) '$(srcdir)/llvm/utils/TableGen/TGParser.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/tblgen-TGParser.Tpo $(DEPDIR)/tblgen-TGParser.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/utils/TableGen/TGParser.cpp' object='tblgen-TGParser.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tblgen_CPPFLAGS) $(CPPFLAGS) $(tblgen_CXXFLAGS) $(CXXFLAGS) -c -o tblgen-TGParser.obj `if test -f 'llvm/utils/TableGen/TGParser.cpp'; then $(CYGPATH_W) 'llvm/utils/TableGen/TGParser.cpp'; else $(CYGPATH_W) '$(srcdir)/llvm/utils/TableGen/TGParser.cpp'; fi` + +tblgen-TGValueTypes.o: llvm/utils/TableGen/TGValueTypes.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tblgen_CPPFLAGS) $(CPPFLAGS) $(tblgen_CXXFLAGS) $(CXXFLAGS) -MT tblgen-TGValueTypes.o -MD -MP -MF $(DEPDIR)/tblgen-TGValueTypes.Tpo -c -o tblgen-TGValueTypes.o `test -f 'llvm/utils/TableGen/TGValueTypes.cpp' || echo '$(srcdir)/'`llvm/utils/TableGen/TGValueTypes.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/tblgen-TGValueTypes.Tpo $(DEPDIR)/tblgen-TGValueTypes.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/utils/TableGen/TGValueTypes.cpp' object='tblgen-TGValueTypes.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tblgen_CPPFLAGS) $(CPPFLAGS) $(tblgen_CXXFLAGS) $(CXXFLAGS) -c -o tblgen-TGValueTypes.o `test -f 'llvm/utils/TableGen/TGValueTypes.cpp' || echo '$(srcdir)/'`llvm/utils/TableGen/TGValueTypes.cpp + +tblgen-TGValueTypes.obj: llvm/utils/TableGen/TGValueTypes.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tblgen_CPPFLAGS) $(CPPFLAGS) $(tblgen_CXXFLAGS) $(CXXFLAGS) -MT tblgen-TGValueTypes.obj -MD -MP -MF $(DEPDIR)/tblgen-TGValueTypes.Tpo -c -o tblgen-TGValueTypes.obj `if test -f 'llvm/utils/TableGen/TGValueTypes.cpp'; then $(CYGPATH_W) 'llvm/utils/TableGen/TGValueTypes.cpp'; else $(CYGPATH_W) '$(srcdir)/llvm/utils/TableGen/TGValueTypes.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/tblgen-TGValueTypes.Tpo $(DEPDIR)/tblgen-TGValueTypes.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/utils/TableGen/TGValueTypes.cpp' object='tblgen-TGValueTypes.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tblgen_CPPFLAGS) $(CPPFLAGS) $(tblgen_CXXFLAGS) $(CXXFLAGS) -c -o tblgen-TGValueTypes.obj `if test -f 'llvm/utils/TableGen/TGValueTypes.cpp'; then $(CYGPATH_W) 'llvm/utils/TableGen/TGValueTypes.cpp'; else $(CYGPATH_W) '$(srcdir)/llvm/utils/TableGen/TGValueTypes.cpp'; fi` + +tblgen-TableGen.o: llvm/utils/TableGen/TableGen.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tblgen_CPPFLAGS) $(CPPFLAGS) $(tblgen_CXXFLAGS) $(CXXFLAGS) -MT tblgen-TableGen.o -MD -MP -MF $(DEPDIR)/tblgen-TableGen.Tpo -c -o tblgen-TableGen.o `test -f 'llvm/utils/TableGen/TableGen.cpp' || echo '$(srcdir)/'`llvm/utils/TableGen/TableGen.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/tblgen-TableGen.Tpo $(DEPDIR)/tblgen-TableGen.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/utils/TableGen/TableGen.cpp' object='tblgen-TableGen.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tblgen_CPPFLAGS) $(CPPFLAGS) $(tblgen_CXXFLAGS) $(CXXFLAGS) -c -o tblgen-TableGen.o `test -f 'llvm/utils/TableGen/TableGen.cpp' || echo '$(srcdir)/'`llvm/utils/TableGen/TableGen.cpp + +tblgen-TableGen.obj: llvm/utils/TableGen/TableGen.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tblgen_CPPFLAGS) $(CPPFLAGS) $(tblgen_CXXFLAGS) $(CXXFLAGS) -MT tblgen-TableGen.obj -MD -MP -MF $(DEPDIR)/tblgen-TableGen.Tpo -c -o tblgen-TableGen.obj `if test -f 'llvm/utils/TableGen/TableGen.cpp'; then $(CYGPATH_W) 'llvm/utils/TableGen/TableGen.cpp'; else $(CYGPATH_W) '$(srcdir)/llvm/utils/TableGen/TableGen.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/tblgen-TableGen.Tpo $(DEPDIR)/tblgen-TableGen.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/utils/TableGen/TableGen.cpp' object='tblgen-TableGen.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tblgen_CPPFLAGS) $(CPPFLAGS) $(tblgen_CXXFLAGS) $(CXXFLAGS) -c -o tblgen-TableGen.obj `if test -f 'llvm/utils/TableGen/TableGen.cpp'; then $(CYGPATH_W) 'llvm/utils/TableGen/TableGen.cpp'; else $(CYGPATH_W) '$(srcdir)/llvm/utils/TableGen/TableGen.cpp'; fi` + +tblgen-TableGenBackend.o: llvm/utils/TableGen/TableGenBackend.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tblgen_CPPFLAGS) $(CPPFLAGS) $(tblgen_CXXFLAGS) $(CXXFLAGS) -MT tblgen-TableGenBackend.o -MD -MP -MF $(DEPDIR)/tblgen-TableGenBackend.Tpo -c -o tblgen-TableGenBackend.o `test -f 'llvm/utils/TableGen/TableGenBackend.cpp' || echo '$(srcdir)/'`llvm/utils/TableGen/TableGenBackend.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/tblgen-TableGenBackend.Tpo $(DEPDIR)/tblgen-TableGenBackend.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/utils/TableGen/TableGenBackend.cpp' object='tblgen-TableGenBackend.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tblgen_CPPFLAGS) $(CPPFLAGS) $(tblgen_CXXFLAGS) $(CXXFLAGS) -c -o tblgen-TableGenBackend.o `test -f 'llvm/utils/TableGen/TableGenBackend.cpp' || echo '$(srcdir)/'`llvm/utils/TableGen/TableGenBackend.cpp + +tblgen-TableGenBackend.obj: llvm/utils/TableGen/TableGenBackend.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tblgen_CPPFLAGS) $(CPPFLAGS) $(tblgen_CXXFLAGS) $(CXXFLAGS) -MT tblgen-TableGenBackend.obj -MD -MP -MF $(DEPDIR)/tblgen-TableGenBackend.Tpo -c -o tblgen-TableGenBackend.obj `if test -f 'llvm/utils/TableGen/TableGenBackend.cpp'; then $(CYGPATH_W) 'llvm/utils/TableGen/TableGenBackend.cpp'; else $(CYGPATH_W) '$(srcdir)/llvm/utils/TableGen/TableGenBackend.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/tblgen-TableGenBackend.Tpo $(DEPDIR)/tblgen-TableGenBackend.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/utils/TableGen/TableGenBackend.cpp' object='tblgen-TableGenBackend.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tblgen_CPPFLAGS) $(CPPFLAGS) $(tblgen_CXXFLAGS) $(CXXFLAGS) -c -o tblgen-TableGenBackend.obj `if test -f 'llvm/utils/TableGen/TableGenBackend.cpp'; then $(CYGPATH_W) 'llvm/utils/TableGen/TableGenBackend.cpp'; else $(CYGPATH_W) '$(srcdir)/llvm/utils/TableGen/TableGenBackend.cpp'; fi` + +.cpp.o: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ $< + +.cpp.obj: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.cpp.lo: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LTCXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LTCXXCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +distclean-libtool: + -rm -f libtool config.lt + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) clamavcxx-config.h.in $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) clamavcxx-config.h.in $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) clamavcxx-config.h.in $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) clamavcxx-config.h.in $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +check-TESTS: $(TESTS) + @failed=0; all=0; xfail=0; xpass=0; skip=0; \ + srcdir=$(srcdir); export srcdir; \ + list=' $(TESTS) '; \ + $(am__tty_colors); \ + if test -n "$$list"; then \ + for tst in $$list; do \ + if test -f ./$$tst; then dir=./; \ + elif test -f $$tst; then dir=; \ + else dir="$(srcdir)/"; fi; \ + if $(TESTS_ENVIRONMENT) $${dir}$$tst; then \ + all=`expr $$all + 1`; \ + case " $(XFAIL_TESTS) " in \ + *[\ \ ]$$tst[\ \ ]*) \ + xpass=`expr $$xpass + 1`; \ + failed=`expr $$failed + 1`; \ + col=$$red; res=XPASS; \ + ;; \ + *) \ + col=$$grn; res=PASS; \ + ;; \ + esac; \ + elif test $$? -ne 77; then \ + all=`expr $$all + 1`; \ + case " $(XFAIL_TESTS) " in \ + *[\ \ ]$$tst[\ \ ]*) \ + xfail=`expr $$xfail + 1`; \ + col=$$lgn; res=XFAIL; \ + ;; \ + *) \ + failed=`expr $$failed + 1`; \ + col=$$red; res=FAIL; \ + ;; \ + esac; \ + else \ + skip=`expr $$skip + 1`; \ + col=$$blu; res=SKIP; \ + fi; \ + echo "$${col}$$res$${std}: $$tst"; \ + done; \ + if test "$$all" -eq 1; then \ + tests="test"; \ + All=""; \ + else \ + tests="tests"; \ + All="All "; \ + fi; \ + if test "$$failed" -eq 0; then \ + if test "$$xfail" -eq 0; then \ + banner="$$All$$all $$tests passed"; \ + else \ + if test "$$xfail" -eq 1; then failures=failure; else failures=failures; fi; \ + banner="$$All$$all $$tests behaved as expected ($$xfail expected $$failures)"; \ + fi; \ + else \ + if test "$$xpass" -eq 0; then \ + banner="$$failed of $$all $$tests failed"; \ + else \ + if test "$$xpass" -eq 1; then passes=pass; else passes=passes; fi; \ + banner="$$failed of $$all $$tests did not behave as expected ($$xpass unexpected $$passes)"; \ + fi; \ + fi; \ + dashes="$$banner"; \ + skipped=""; \ + if test "$$skip" -ne 0; then \ + if test "$$skip" -eq 1; then \ + skipped="($$skip test was not run)"; \ + else \ + skipped="($$skip tests were not run)"; \ + fi; \ + test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \ + dashes="$$skipped"; \ + fi; \ + report=""; \ + if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \ + report="Please report to $(PACKAGE_BUGREPORT)"; \ + test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \ + dashes="$$report"; \ + fi; \ + dashes=`echo "$$dashes" | sed s/./=/g`; \ + if test "$$failed" -eq 0; then \ + echo "$$grn$$dashes"; \ + else \ + echo "$$red$$dashes"; \ + fi; \ + echo "$$banner"; \ + test -z "$$skipped" || echo "$$skipped"; \ + test -z "$$report" || echo "$$report"; \ + echo "$$dashes$$std"; \ + test "$$failed" -eq 0; \ + else :; fi + +distdir: $(DISTFILES) + $(am__remove_distdir) + test -d "$(distdir)" || mkdir "$(distdir)" + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$(top_distdir)" distdir="$(distdir)" \ + dist-hook + -test -n "$(am__skip_mode_fix)" \ + || find "$(distdir)" -type d ! -perm -777 -exec chmod a+rwx {} \; -o \ + ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \ + ! -type d ! -perm -400 -exec chmod a+r {} \; -o \ + ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \ + || chmod -R a+r "$(distdir)" +dist-gzip: distdir + tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz + $(am__remove_distdir) + +dist-bzip2: distdir + tardir=$(distdir) && $(am__tar) | bzip2 -9 -c >$(distdir).tar.bz2 + $(am__remove_distdir) + +dist-lzma: distdir + tardir=$(distdir) && $(am__tar) | lzma -9 -c >$(distdir).tar.lzma + $(am__remove_distdir) + +dist-xz: distdir + tardir=$(distdir) && $(am__tar) | xz -c >$(distdir).tar.xz + $(am__remove_distdir) + +dist-tarZ: distdir + tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z + $(am__remove_distdir) + +dist-shar: distdir + shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz + $(am__remove_distdir) + +dist-zip: distdir + -rm -f $(distdir).zip + zip -rq $(distdir).zip $(distdir) + $(am__remove_distdir) + +dist dist-all: distdir + tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz + $(am__remove_distdir) + +# This target untars the dist file and tries a VPATH configuration. Then +# it guarantees that the distribution is self-contained by making another +# tarfile. +distcheck: dist + case '$(DIST_ARCHIVES)' in \ + *.tar.gz*) \ + GZIP=$(GZIP_ENV) gunzip -c $(distdir).tar.gz | $(am__untar) ;;\ + *.tar.bz2*) \ + bunzip2 -c $(distdir).tar.bz2 | $(am__untar) ;;\ + *.tar.lzma*) \ + unlzma -c $(distdir).tar.lzma | $(am__untar) ;;\ + *.tar.xz*) \ + xz -dc $(distdir).tar.xz | $(am__untar) ;;\ + *.tar.Z*) \ + uncompress -c $(distdir).tar.Z | $(am__untar) ;;\ + *.shar.gz*) \ + GZIP=$(GZIP_ENV) gunzip -c $(distdir).shar.gz | unshar ;;\ + *.zip*) \ + unzip $(distdir).zip ;;\ + esac + chmod -R a-w $(distdir); chmod a+w $(distdir) + mkdir $(distdir)/_build + mkdir $(distdir)/_inst + chmod a-w $(distdir) + test -d $(distdir)/_build || exit 0; \ + dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \ + && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \ + && am__cwd=`pwd` \ + && $(am__cd) $(distdir)/_build \ + && ../configure --srcdir=.. --prefix="$$dc_install_base" \ + $(DISTCHECK_CONFIGURE_FLAGS) \ + && $(MAKE) $(AM_MAKEFLAGS) \ + && $(MAKE) $(AM_MAKEFLAGS) dvi \ + && $(MAKE) $(AM_MAKEFLAGS) check \ + && $(MAKE) $(AM_MAKEFLAGS) install \ + && $(MAKE) $(AM_MAKEFLAGS) installcheck \ + && $(MAKE) $(AM_MAKEFLAGS) uninstall \ + && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \ + distuninstallcheck \ + && chmod -R a-w "$$dc_install_base" \ + && ({ \ + (cd ../.. && umask 077 && mkdir "$$dc_destdir") \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \ + distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \ + } || { rm -rf "$$dc_destdir"; exit 1; }) \ + && rm -rf "$$dc_destdir" \ + && $(MAKE) $(AM_MAKEFLAGS) dist \ + && rm -rf $(DIST_ARCHIVES) \ + && $(MAKE) $(AM_MAKEFLAGS) distcleancheck \ + && cd "$$am__cwd" \ + || exit 1 + $(am__remove_distdir) + @(echo "$(distdir) archives ready for distribution: "; \ + list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \ + sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x' +distuninstallcheck: + @$(am__cd) '$(distuninstallcheck_dir)' \ + && test `$(distuninstallcheck_listfiles) | wc -l` -le 1 \ + || { echo "ERROR: files left after uninstall:" ; \ + if test -n "$(DESTDIR)"; then \ + echo " (check DESTDIR support)"; \ + fi ; \ + $(distuninstallcheck_listfiles) ; \ + exit 1; } >&2 +distcleancheck: distclean + @if test '$(srcdir)' = . ; then \ + echo "ERROR: distcleancheck can only run from a VPATH build" ; \ + exit 1 ; \ + fi + @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \ + || { echo "ERROR: files left in build directory after distclean:" ; \ + $(distcleancheck_listfiles) ; \ + exit 1; } >&2 +check-am: all-am + $(MAKE) $(AM_MAKEFLAGS) $(check_LTLIBRARIES) $(check_PROGRAMS) + $(MAKE) $(AM_MAKEFLAGS) check-TESTS +check: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) check-am +all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) clamavcxx-config.h +installdirs: +install: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." + -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) +clean: clean-am + +clean-am: clean-checkLTLIBRARIES clean-checkPROGRAMS clean-generic \ + clean-libtool clean-local clean-noinstLTLIBRARIES \ + clean-noinstPROGRAMS mostlyclean-am + +distclean: distclean-am + -rm -f $(am__CONFIG_DISTCLEAN_FILES) + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-hdr distclean-libtool distclean-local distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f $(am__CONFIG_DISTCLEAN_FILES) + -rm -rf $(top_srcdir)/autom4te.cache + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: all check check-am install install-am install-strip + +.PHONY: CTAGS GTAGS all all-am am--refresh check check-TESTS check-am \ + clean clean-checkLTLIBRARIES clean-checkPROGRAMS clean-generic \ + clean-libtool clean-local clean-noinstLTLIBRARIES \ + clean-noinstPROGRAMS ctags dist dist-all dist-bzip2 dist-gzip \ + dist-hook dist-lzma dist-shar dist-tarZ dist-xz dist-zip \ + distcheck distclean distclean-compile distclean-generic \ + distclean-hdr distclean-libtool distclean-local distclean-tags \ + distcleancheck distdir distuninstallcheck dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags uninstall uninstall-am + +llvm/include/llvm/Intrinsics.gen: llvm/include/llvm/Intrinsics.td $(TBLGEN) + $(TBLGEN_V) $(TBLGEN_FLAGS) -gen-intrinsic -o $@ $< +@BUILD_X86_TRUE@X86GenRegisterInfo.h.inc: llvm/lib/Target/X86/X86.td $(TBLGEN) +@BUILD_X86_TRUE@ $(TBLGEN_V) $(TBLGEN_FLAGS_X86) -gen-register-desc-header -o $@ $< + +@BUILD_X86_TRUE@X86GenRegisterNames.inc: llvm/lib/Target/X86/X86.td $(TBLGEN) +@BUILD_X86_TRUE@ $(TBLGEN_V) $(TBLGEN_FLAGS_X86) -gen-register-enums -o $@ $< + +@BUILD_X86_TRUE@X86GenRegisterInfo.inc: llvm/lib/Target/X86/X86.td $(TBLGEN) +@BUILD_X86_TRUE@ $(TBLGEN_V) $(TBLGEN_FLAGS_X86) -gen-register-desc -o $@ $< + +@BUILD_X86_TRUE@X86GenInstrNames.inc: llvm/lib/Target/X86/X86.td $(TBLGEN) +@BUILD_X86_TRUE@ $(TBLGEN_V) $(TBLGEN_FLAGS_X86) -gen-instr-enums -o $@ $< + +@BUILD_X86_TRUE@X86GenInstrInfo.inc: llvm/lib/Target/X86/X86.td $(TBLGEN) +@BUILD_X86_TRUE@ $(TBLGEN_V) $(TBLGEN_FLAGS_X86) -gen-instr-desc -o $@ $< + +@BUILD_X86_TRUE@X86GenAsmWriter.inc: llvm/lib/Target/X86/X86.td $(TBLGEN) +@BUILD_X86_TRUE@ $(TBLGEN_V) $(TBLGEN_FLAGS_X86) -gen-asm-writer -o $@ $< + +@BUILD_X86_TRUE@X86GenAsmWriter1.inc: llvm/lib/Target/X86/X86.td $(TBLGEN) +@BUILD_X86_TRUE@ $(TBLGEN_V) $(TBLGEN_FLAGS_X86) -gen-asm-writer -asmwriternum=1 -o $@ $< + +@BUILD_X86_TRUE@X86GenAsmMatcher.inc: llvm/lib/Target/X86/X86.td $(TBLGEN) +@BUILD_X86_TRUE@ $(TBLGEN_V) $(TBLGEN_FLAGS_X86) -gen-asm-matcher -o $@ $< + +@BUILD_X86_TRUE@X86GenDAGISel.inc: llvm/lib/Target/X86/X86.td $(TBLGEN) +@BUILD_X86_TRUE@ $(TBLGEN_V) $(TBLGEN_FLAGS_X86) -gen-dag-isel -o $@ $< + +@BUILD_X86_TRUE@X86GenFastISel.inc: llvm/lib/Target/X86/X86.td $(TBLGEN) +@BUILD_X86_TRUE@ $(TBLGEN_V) $(TBLGEN_FLAGS_X86) -gen-fast-isel -o $@ $< + +@BUILD_X86_TRUE@X86GenCallingConv.inc: llvm/lib/Target/X86/X86.td $(TBLGEN) +@BUILD_X86_TRUE@ $(TBLGEN_V) $(TBLGEN_FLAGS_X86) -gen-callingconv -o $@ $< + +@BUILD_X86_TRUE@X86GenSubtarget.inc: llvm/lib/Target/X86/X86.td $(TBLGEN) +@BUILD_X86_TRUE@ $(TBLGEN_V) $(TBLGEN_FLAGS_X86) -gen-subtarget -o $@ $< +@BUILD_PPC_TRUE@PPCGenInstrNames.inc: llvm/lib/Target/PowerPC/PPC.td $(TBLGEN) +@BUILD_PPC_TRUE@ $(TBLGEN_V) $(TBLGEN_FLAGS_PPC) -gen-instr-enums -o $@ $< + +@BUILD_PPC_TRUE@PPCGenRegisterNames.inc: llvm/lib/Target/PowerPC/PPC.td $(TBLGEN) +@BUILD_PPC_TRUE@ $(TBLGEN_V) $(TBLGEN_FLAGS_PPC) -gen-register-enums -o $@ $< + +@BUILD_PPC_TRUE@PPCGenAsmWriter.inc: llvm/lib/Target/PowerPC/PPC.td $(TBLGEN) +@BUILD_PPC_TRUE@ $(TBLGEN_V) $(TBLGEN_FLAGS_PPC) -gen-asm-writer -o $@ $< + +@BUILD_PPC_TRUE@PPCGenCodeEmitter.inc: llvm/lib/Target/PowerPC/PPC.td $(TBLGEN) +@BUILD_PPC_TRUE@ $(TBLGEN_V) $(TBLGEN_FLAGS_PPC) -gen-emitter -o $@ $< + +@BUILD_PPC_TRUE@PPCRegisterInfo.h.inc: llvm/lib/Target/PowerPC/PPC.td $(TBLGEN) +@BUILD_PPC_TRUE@ $(TBLGEN_V) $(TBLGEN_FLAGS_PPC) -gen-register-desc-header -o $@ $< + +@BUILD_PPC_TRUE@PPCGenRegisterInfo.inc: llvm/lib/Target/PowerPC/PPC.td $(TBLGEN) +@BUILD_PPC_TRUE@ $(TBLGEN_V) $(TBLGEN_FLAGS_PPC) -gen-register-desc -o $@ $< + +@BUILD_PPC_TRUE@PPCGenRegisterInfo.h.inc: llvm/lib/Target/PowerPC/PPC.td $(TBLGEN) +@BUILD_PPC_TRUE@ $(TBLGEN_V) $(TBLGEN_FLAGS_PPC) -gen-register-desc-header -o $@ $< + +@BUILD_PPC_TRUE@PPCGenInstrInfo.inc: llvm/lib/Target/PowerPC/PPC.td $(TBLGEN) +@BUILD_PPC_TRUE@ $(TBLGEN_V) $(TBLGEN_FLAGS_PPC) -gen-instr-desc -o $@ $< + +@BUILD_PPC_TRUE@PPCGenDAGISel.inc: llvm/lib/Target/PowerPC/PPC.td $(TBLGEN) +@BUILD_PPC_TRUE@ $(TBLGEN_V) $(TBLGEN_FLAGS_PPC) -gen-dag-isel -o $@ $< + +@BUILD_PPC_TRUE@PPCGenCallingConv.inc: llvm/lib/Target/PowerPC/PPC.td $(TBLGEN) +@BUILD_PPC_TRUE@ $(TBLGEN_V) $(TBLGEN_FLAGS_PPC) -gen-callingconv -o $@ $< + +@BUILD_PPC_TRUE@PPCGenSubtarget.inc: llvm/lib/Target/PowerPC/PPC.td $(TBLGEN) +@BUILD_PPC_TRUE@ $(TBLGEN_V) $(TBLGEN_FLAGS_PPC) -gen-subtarget -o $@ $< +@BUILD_ARM_TRUE@ARMGenRegisterInfo.h.inc: llvm/lib/Target/ARM/ARM.td $(TBLGEN) +@BUILD_ARM_TRUE@ $(TBLGEN_V) $(TBLGEN_FLAGS_ARM) -gen-register-desc-header -o $@ $< + +@BUILD_ARM_TRUE@ARMGenRegisterNames.inc: llvm/lib/Target/ARM/ARM.td $(TBLGEN) +@BUILD_ARM_TRUE@ $(TBLGEN_V) $(TBLGEN_FLAGS_ARM) -gen-register-enums -o $@ $< + +@BUILD_ARM_TRUE@ARMGenRegisterInfo.inc: llvm/lib/Target/ARM/ARM.td $(TBLGEN) +@BUILD_ARM_TRUE@ $(TBLGEN_V) $(TBLGEN_FLAGS_ARM) -gen-register-desc -o $@ $< + +@BUILD_ARM_TRUE@ARMGenInstrNames.inc: llvm/lib/Target/ARM/ARM.td $(TBLGEN) +@BUILD_ARM_TRUE@ $(TBLGEN_V) $(TBLGEN_FLAGS_ARM) -gen-instr-enums -o $@ $< + +@BUILD_ARM_TRUE@ARMGenInstrInfo.inc: llvm/lib/Target/ARM/ARM.td $(TBLGEN) +@BUILD_ARM_TRUE@ $(TBLGEN_V) $(TBLGEN_FLAGS_ARM) -gen-instr-desc -o $@ $< + +@BUILD_ARM_TRUE@ARMGenCodeEmitter.inc: llvm/lib/Target/ARM/ARM.td $(TBLGEN) +@BUILD_ARM_TRUE@ $(TBLGEN_V) $(TBLGEN_FLAGS_ARM) -gen-emitter -o $@ $< + +@BUILD_ARM_TRUE@ARMGenAsmWriter.inc: llvm/lib/Target/ARM/ARM.td $(TBLGEN) +@BUILD_ARM_TRUE@ $(TBLGEN_V) $(TBLGEN_FLAGS_ARM) -gen-asm-writer -o $@ $< + +@BUILD_ARM_TRUE@ARMGenDAGISel.inc: llvm/lib/Target/ARM/ARM.td $(TBLGEN) +@BUILD_ARM_TRUE@ $(TBLGEN_V) $(TBLGEN_FLAGS_ARM) -gen-dag-isel -o $@ $< + +@BUILD_ARM_TRUE@ARMGenCallingConv.inc: llvm/lib/Target/ARM/ARM.td $(TBLGEN) +@BUILD_ARM_TRUE@ $(TBLGEN_V) $(TBLGEN_FLAGS_ARM) -gen-callingconv -o $@ $< + +@BUILD_ARM_TRUE@ARMGenSubtarget.inc: llvm/lib/Target/ARM/ARM.td $(TBLGEN) +@BUILD_ARM_TRUE@ $(TBLGEN_V) $(TBLGEN_FLAGS_ARM) -gen-subtarget -o $@ $< +@ifGNUmake@ TESTS+=llvmdejagnu.sh +#bytecode2llvm.cpp: build-llvm + +build-llvm: + +$(GMAKE) -C llvm OPTIMIZE_OPTION=-O2 libs-only + +build-llvm-for-check: + +$(GMAKE) -C llvm OPTIMIZE_OPTION=-O2 tools-only + +# Don't use make -C here, otherwise there's a racecondition between distclean +# and clean (distclean removes all Makefiles in llvm/) +clean-local: + rm -rf `find llvm/test -name Output -type d -print` + rm -rf llvm/Release llvm/Debug + rm -f *.inc + rm -f llvm/include/llvm/Intrinsics.gen + rm -f llvm/test/site.exp llvm/test/site.bak llvm/test/*.out llvm/test/*.sum llvm/test/*.log + +distclean-local: + rm -f llvm/lib/Makefile llvm/docs/doxygen.cfg llvm/test/Unit/.dir llvm/test/Unit/lit.site.cfg + rm -f llvm/test/Makefile llvm/test/lit.site.cfg llvm/test/Makefile.tests llvm/Makefile llvm/config.status + rm -f llvm/mklib llvm/tools/Makefile llvm/tools/llvmc/llvm-config.in llvm/utils/Makefile + rm -f llvm/Makefile.common llvm/Makefile.config llvm/config.log llvm/unittests/Makefile + rm -f llvm/llvm.spec llvm/include/llvm/Config/AsmPrinters.def llvm/include/llvm/Config/config.h + rm -f llvm/include/llvm/Support/DataTypes.h llvm/include/llvm/Config/Targets.def + rm -f llvm/tools/llvmc/plugins/Base/Base.td llvm/tools/llvm-config/llvm-config.in + rm -f llvm/include/llvm/Config/AsmParsers.def + +check-llvm: build-llvm-for-check + +$(GMAKE) -C llvm check + +$(GMAKE) -C llvm unittests +# config.status needs to be run twice, once without recheck so that it has a +# chance to create configure generated files. +$(top_builddir)/llvm/config.status: llvm/configure + cd llvm; ./config.status --recheck; ./config.status + +# rm configure generated files +dist-hook: + make -C llvm dist-hook + rm -f $(distdir)/llvm/include/llvm/Config/*.h $(distdir)/llvm/include/llvm/Config/*.def $(distdir)/llvm/Makefile.config $(distdir)/llvm/llvm.spec + rm -f $(distdir)/llvm/docs/doxygen.cfg $(distdir)/llvm/tools/llvmc/plugins/Base/Base.td $(distdir)/llvm/tools/llvm-config/llvm-config.in + rm -f $(distdir)/llvm/include/llvm/Intrinsics.gen + rm -f $(distdir)/llvm/include/llvm/Support/DataTypes.h $(distdir)/llvm/config.log $(distdir)/llvm/config.status + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/libclamav/c++/TODO.CLAMAV b/libclamav/c++/TODO.CLAMAV new file mode 100644 index 000000000..dc02bc508 --- /dev/null +++ b/libclamav/c++/TODO.CLAMAV @@ -0,0 +1,15 @@ +Convert to clamav's build system -> impl. cross-compilation support (tblgen) + +Right now static linking of libclamav doesn't work with llvm parts for a number +of reasons: +1. llvm is not built with libtool, and it builds .a files (or .so files) +2. if I link with .a files, that works for a .so (LLVM's .a files are PIC), but + the created libclamav.a will miss the .a files, so I'd need to install the llvm + .a files together with clamav's +3. libtool solves this by putting individual .o files into the target libtool .a +archive, but since I link against non-libtool archives it doesn't know how to do +that +4. if I link against a .so then obviously it is not static linking + +If llvm would be converted to clamav's buildsystem then static linking of +libclamav would work. diff --git a/libclamav/c++/aclocal.m4 b/libclamav/c++/aclocal.m4 new file mode 100644 index 000000000..31006c551 --- /dev/null +++ b/libclamav/c++/aclocal.m4 @@ -0,0 +1,1041 @@ +# generated automatically by aclocal 1.11 -*- Autoconf -*- + +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, +# 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc. +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +m4_ifndef([AC_AUTOCONF_VERSION], + [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl +m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.65],, +[m4_warning([this file was generated for autoconf 2.65. +You have another version of autoconf. It may work, but is not guaranteed to. +If you have problems, you may need to regenerate the build system entirely. +To do so, use the procedure documented by the package, typically `autoreconf'.])]) + +# Copyright (C) 2002, 2003, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_AUTOMAKE_VERSION(VERSION) +# ---------------------------- +# Automake X.Y traces this macro to ensure aclocal.m4 has been +# generated from the m4 files accompanying Automake X.Y. +# (This private macro should not be called outside this file.) +AC_DEFUN([AM_AUTOMAKE_VERSION], +[am__api_version='1.11' +dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to +dnl require some minimum version. Point them to the right macro. +m4_if([$1], [1.11], [], + [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl +]) + +# _AM_AUTOCONF_VERSION(VERSION) +# ----------------------------- +# aclocal traces this macro to find the Autoconf version. +# This is a private macro too. Using m4_define simplifies +# the logic in aclocal, which can simply ignore this definition. +m4_define([_AM_AUTOCONF_VERSION], []) + +# AM_SET_CURRENT_AUTOMAKE_VERSION +# ------------------------------- +# Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced. +# This function is AC_REQUIREd by AM_INIT_AUTOMAKE. +AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], +[AM_AUTOMAKE_VERSION([1.11])dnl +m4_ifndef([AC_AUTOCONF_VERSION], + [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl +_AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))]) + +# AM_AUX_DIR_EXPAND -*- Autoconf -*- + +# Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets +# $ac_aux_dir to `$srcdir/foo'. In other projects, it is set to +# `$srcdir', `$srcdir/..', or `$srcdir/../..'. +# +# Of course, Automake must honor this variable whenever it calls a +# tool from the auxiliary directory. The problem is that $srcdir (and +# therefore $ac_aux_dir as well) can be either absolute or relative, +# depending on how configure is run. This is pretty annoying, since +# it makes $ac_aux_dir quite unusable in subdirectories: in the top +# source directory, any form will work fine, but in subdirectories a +# relative path needs to be adjusted first. +# +# $ac_aux_dir/missing +# fails when called from a subdirectory if $ac_aux_dir is relative +# $top_srcdir/$ac_aux_dir/missing +# fails if $ac_aux_dir is absolute, +# fails when called from a subdirectory in a VPATH build with +# a relative $ac_aux_dir +# +# The reason of the latter failure is that $top_srcdir and $ac_aux_dir +# are both prefixed by $srcdir. In an in-source build this is usually +# harmless because $srcdir is `.', but things will broke when you +# start a VPATH build or use an absolute $srcdir. +# +# So we could use something similar to $top_srcdir/$ac_aux_dir/missing, +# iff we strip the leading $srcdir from $ac_aux_dir. That would be: +# am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"` +# and then we would define $MISSING as +# MISSING="\${SHELL} $am_aux_dir/missing" +# This will work as long as MISSING is not called from configure, because +# unfortunately $(top_srcdir) has no meaning in configure. +# However there are other variables, like CC, which are often used in +# configure, and could therefore not use this "fixed" $ac_aux_dir. +# +# Another solution, used here, is to always expand $ac_aux_dir to an +# absolute PATH. The drawback is that using absolute paths prevent a +# configured tree to be moved without reconfiguration. + +AC_DEFUN([AM_AUX_DIR_EXPAND], +[dnl Rely on autoconf to set up CDPATH properly. +AC_PREREQ([2.50])dnl +# expand $ac_aux_dir to an absolute path +am_aux_dir=`cd $ac_aux_dir && pwd` +]) + +# AM_CONDITIONAL -*- Autoconf -*- + +# Copyright (C) 1997, 2000, 2001, 2003, 2004, 2005, 2006, 2008 +# Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 9 + +# AM_CONDITIONAL(NAME, SHELL-CONDITION) +# ------------------------------------- +# Define a conditional. +AC_DEFUN([AM_CONDITIONAL], +[AC_PREREQ(2.52)dnl + ifelse([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])], + [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl +AC_SUBST([$1_TRUE])dnl +AC_SUBST([$1_FALSE])dnl +_AM_SUBST_NOTMAKE([$1_TRUE])dnl +_AM_SUBST_NOTMAKE([$1_FALSE])dnl +m4_define([_AM_COND_VALUE_$1], [$2])dnl +if $2; then + $1_TRUE= + $1_FALSE='#' +else + $1_TRUE='#' + $1_FALSE= +fi +AC_CONFIG_COMMANDS_PRE( +[if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then + AC_MSG_ERROR([[conditional "$1" was never defined. +Usually this means the macro was only invoked conditionally.]]) +fi])]) + +# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2009 +# Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 10 + +# There are a few dirty hacks below to avoid letting `AC_PROG_CC' be +# written in clear, in which case automake, when reading aclocal.m4, +# will think it sees a *use*, and therefore will trigger all it's +# C support machinery. Also note that it means that autoscan, seeing +# CC etc. in the Makefile, will ask for an AC_PROG_CC use... + + +# _AM_DEPENDENCIES(NAME) +# ---------------------- +# See how the compiler implements dependency checking. +# NAME is "CC", "CXX", "GCJ", or "OBJC". +# We try a few techniques and use that to set a single cache variable. +# +# We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was +# modified to invoke _AM_DEPENDENCIES(CC); we would have a circular +# dependency, and given that the user is not expected to run this macro, +# just rely on AC_PROG_CC. +AC_DEFUN([_AM_DEPENDENCIES], +[AC_REQUIRE([AM_SET_DEPDIR])dnl +AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl +AC_REQUIRE([AM_MAKE_INCLUDE])dnl +AC_REQUIRE([AM_DEP_TRACK])dnl + +ifelse([$1], CC, [depcc="$CC" am_compiler_list=], + [$1], CXX, [depcc="$CXX" am_compiler_list=], + [$1], OBJC, [depcc="$OBJC" am_compiler_list='gcc3 gcc'], + [$1], UPC, [depcc="$UPC" am_compiler_list=], + [$1], GCJ, [depcc="$GCJ" am_compiler_list='gcc3 gcc'], + [depcc="$$1" am_compiler_list=]) + +AC_CACHE_CHECK([dependency style of $depcc], + [am_cv_$1_dependencies_compiler_type], +[if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then + # We make a subdir and do the tests there. Otherwise we can end up + # making bogus files that we don't know about and never remove. For + # instance it was reported that on HP-UX the gcc test will end up + # making a dummy file named `D' -- because `-MD' means `put the output + # in D'. + mkdir conftest.dir + # Copy depcomp to subdir because otherwise we won't find it if we're + # using a relative directory. + cp "$am_depcomp" conftest.dir + cd conftest.dir + # We will build objects and dependencies in a subdirectory because + # it helps to detect inapplicable dependency modes. For instance + # both Tru64's cc and ICC support -MD to output dependencies as a + # side effect of compilation, but ICC will put the dependencies in + # the current directory while Tru64 will put them in the object + # directory. + mkdir sub + + am_cv_$1_dependencies_compiler_type=none + if test "$am_compiler_list" = ""; then + am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp` + fi + am__universal=false + m4_case([$1], [CC], + [case " $depcc " in #( + *\ -arch\ *\ -arch\ *) am__universal=true ;; + esac], + [CXX], + [case " $depcc " in #( + *\ -arch\ *\ -arch\ *) am__universal=true ;; + esac]) + + for depmode in $am_compiler_list; do + # Setup a source with many dependencies, because some compilers + # like to wrap large dependency lists on column 80 (with \), and + # we should not choose a depcomp mode which is confused by this. + # + # We need to recreate these files for each test, as the compiler may + # overwrite some of them when testing with obscure command lines. + # This happens at least with the AIX C compiler. + : > sub/conftest.c + for i in 1 2 3 4 5 6; do + echo '#include "conftst'$i'.h"' >> sub/conftest.c + # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with + # Solaris 8's {/usr,}/bin/sh. + touch sub/conftst$i.h + done + echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf + + # We check with `-c' and `-o' for the sake of the "dashmstdout" + # mode. It turns out that the SunPro C++ compiler does not properly + # handle `-M -o', and we need to detect this. Also, some Intel + # versions had trouble with output in subdirs + am__obj=sub/conftest.${OBJEXT-o} + am__minus_obj="-o $am__obj" + case $depmode in + gcc) + # This depmode causes a compiler race in universal mode. + test "$am__universal" = false || continue + ;; + nosideeffect) + # after this tag, mechanisms are not by side-effect, so they'll + # only be used when explicitly requested + if test "x$enable_dependency_tracking" = xyes; then + continue + else + break + fi + ;; + msvisualcpp | msvcmsys) + # This compiler won't grok `-c -o', but also, the minuso test has + # not run yet. These depmodes are late enough in the game, and + # so weak that their functioning should not be impacted. + am__obj=conftest.${OBJEXT-o} + am__minus_obj= + ;; + none) break ;; + esac + if depmode=$depmode \ + source=sub/conftest.c object=$am__obj \ + depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ + $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ + >/dev/null 2>conftest.err && + grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && + grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && + grep $am__obj sub/conftest.Po > /dev/null 2>&1 && + ${MAKE-make} -s -f confmf > /dev/null 2>&1; then + # icc doesn't choke on unknown options, it will just issue warnings + # or remarks (even with -Werror). So we grep stderr for any message + # that says an option was ignored or not supported. + # When given -MP, icc 7.0 and 7.1 complain thusly: + # icc: Command line warning: ignoring option '-M'; no argument required + # The diagnosis changed in icc 8.0: + # icc: Command line remark: option '-MP' not supported + if (grep 'ignoring option' conftest.err || + grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else + am_cv_$1_dependencies_compiler_type=$depmode + break + fi + fi + done + + cd .. + rm -rf conftest.dir +else + am_cv_$1_dependencies_compiler_type=none +fi +]) +AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type]) +AM_CONDITIONAL([am__fastdep$1], [ + test "x$enable_dependency_tracking" != xno \ + && test "$am_cv_$1_dependencies_compiler_type" = gcc3]) +]) + + +# AM_SET_DEPDIR +# ------------- +# Choose a directory name for dependency files. +# This macro is AC_REQUIREd in _AM_DEPENDENCIES +AC_DEFUN([AM_SET_DEPDIR], +[AC_REQUIRE([AM_SET_LEADING_DOT])dnl +AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl +]) + + +# AM_DEP_TRACK +# ------------ +AC_DEFUN([AM_DEP_TRACK], +[AC_ARG_ENABLE(dependency-tracking, +[ --disable-dependency-tracking speeds up one-time build + --enable-dependency-tracking do not reject slow dependency extractors]) +if test "x$enable_dependency_tracking" != xno; then + am_depcomp="$ac_aux_dir/depcomp" + AMDEPBACKSLASH='\' +fi +AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno]) +AC_SUBST([AMDEPBACKSLASH])dnl +_AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl +]) + +# Generate code to set up dependency tracking. -*- Autoconf -*- + +# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2008 +# Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +#serial 5 + +# _AM_OUTPUT_DEPENDENCY_COMMANDS +# ------------------------------ +AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], +[{ + # Autoconf 2.62 quotes --file arguments for eval, but not when files + # are listed without --file. Let's play safe and only enable the eval + # if we detect the quoting. + case $CONFIG_FILES in + *\'*) eval set x "$CONFIG_FILES" ;; + *) set x $CONFIG_FILES ;; + esac + shift + for mf + do + # Strip MF so we end up with the name of the file. + mf=`echo "$mf" | sed -e 's/:.*$//'` + # Check whether this is an Automake generated Makefile or not. + # We used to match only the files named `Makefile.in', but + # some people rename them; so instead we look at the file content. + # Grep'ing the first line is not enough: some people post-process + # each Makefile.in and add a new line on top of each file to say so. + # Grep'ing the whole file is not good either: AIX grep has a line + # limit of 2048, but all sed's we know have understand at least 4000. + if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then + dirpart=`AS_DIRNAME("$mf")` + else + continue + fi + # Extract the definition of DEPDIR, am__include, and am__quote + # from the Makefile without running `make'. + DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` + test -z "$DEPDIR" && continue + am__include=`sed -n 's/^am__include = //p' < "$mf"` + test -z "am__include" && continue + am__quote=`sed -n 's/^am__quote = //p' < "$mf"` + # When using ansi2knr, U may be empty or an underscore; expand it + U=`sed -n 's/^U = //p' < "$mf"` + # Find all dependency output files, they are included files with + # $(DEPDIR) in their names. We invoke sed twice because it is the + # simplest approach to changing $(DEPDIR) to its actual value in the + # expansion. + for file in `sed -n " + s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ + sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do + # Make sure the directory exists. + test -f "$dirpart/$file" && continue + fdir=`AS_DIRNAME(["$file"])` + AS_MKDIR_P([$dirpart/$fdir]) + # echo "creating $dirpart/$file" + echo '# dummy' > "$dirpart/$file" + done + done +} +])# _AM_OUTPUT_DEPENDENCY_COMMANDS + + +# AM_OUTPUT_DEPENDENCY_COMMANDS +# ----------------------------- +# This macro should only be invoked once -- use via AC_REQUIRE. +# +# This code is only required when automatic dependency tracking +# is enabled. FIXME. This creates each `.P' file that we will +# need in order to bootstrap the dependency handling code. +AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS], +[AC_CONFIG_COMMANDS([depfiles], + [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS], + [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"]) +]) + +# Do all the work for Automake. -*- Autoconf -*- + +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, +# 2005, 2006, 2008, 2009 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 16 + +# This macro actually does too much. Some checks are only needed if +# your package does certain things. But this isn't really a big deal. + +# AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE]) +# AM_INIT_AUTOMAKE([OPTIONS]) +# ----------------------------------------------- +# The call with PACKAGE and VERSION arguments is the old style +# call (pre autoconf-2.50), which is being phased out. PACKAGE +# and VERSION should now be passed to AC_INIT and removed from +# the call to AM_INIT_AUTOMAKE. +# We support both call styles for the transition. After +# the next Automake release, Autoconf can make the AC_INIT +# arguments mandatory, and then we can depend on a new Autoconf +# release and drop the old call support. +AC_DEFUN([AM_INIT_AUTOMAKE], +[AC_PREREQ([2.62])dnl +dnl Autoconf wants to disallow AM_ names. We explicitly allow +dnl the ones we care about. +m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl +AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl +AC_REQUIRE([AC_PROG_INSTALL])dnl +if test "`cd $srcdir && pwd`" != "`pwd`"; then + # Use -I$(srcdir) only when $(srcdir) != ., so that make's output + # is not polluted with repeated "-I." + AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl + # test to see if srcdir already configured + if test -f $srcdir/config.status; then + AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) + fi +fi + +# test whether we have cygpath +if test -z "$CYGPATH_W"; then + if (cygpath --version) >/dev/null 2>/dev/null; then + CYGPATH_W='cygpath -w' + else + CYGPATH_W=echo + fi +fi +AC_SUBST([CYGPATH_W]) + +# Define the identity of the package. +dnl Distinguish between old-style and new-style calls. +m4_ifval([$2], +[m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl + AC_SUBST([PACKAGE], [$1])dnl + AC_SUBST([VERSION], [$2])], +[_AM_SET_OPTIONS([$1])dnl +dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT. +m4_if(m4_ifdef([AC_PACKAGE_NAME], 1)m4_ifdef([AC_PACKAGE_VERSION], 1), 11,, + [m4_fatal([AC_INIT should be called with package and version arguments])])dnl + AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl + AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl + +_AM_IF_OPTION([no-define],, +[AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package]) + AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package])])dnl + +# Some tools Automake needs. +AC_REQUIRE([AM_SANITY_CHECK])dnl +AC_REQUIRE([AC_ARG_PROGRAM])dnl +AM_MISSING_PROG(ACLOCAL, aclocal-${am__api_version}) +AM_MISSING_PROG(AUTOCONF, autoconf) +AM_MISSING_PROG(AUTOMAKE, automake-${am__api_version}) +AM_MISSING_PROG(AUTOHEADER, autoheader) +AM_MISSING_PROG(MAKEINFO, makeinfo) +AC_REQUIRE([AM_PROG_INSTALL_SH])dnl +AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl +AC_REQUIRE([AM_PROG_MKDIR_P])dnl +# We need awk for the "check" target. The system "awk" is bad on +# some platforms. +AC_REQUIRE([AC_PROG_AWK])dnl +AC_REQUIRE([AC_PROG_MAKE_SET])dnl +AC_REQUIRE([AM_SET_LEADING_DOT])dnl +_AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])], + [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])], + [_AM_PROG_TAR([v7])])]) +_AM_IF_OPTION([no-dependencies],, +[AC_PROVIDE_IFELSE([AC_PROG_CC], + [_AM_DEPENDENCIES(CC)], + [define([AC_PROG_CC], + defn([AC_PROG_CC])[_AM_DEPENDENCIES(CC)])])dnl +AC_PROVIDE_IFELSE([AC_PROG_CXX], + [_AM_DEPENDENCIES(CXX)], + [define([AC_PROG_CXX], + defn([AC_PROG_CXX])[_AM_DEPENDENCIES(CXX)])])dnl +AC_PROVIDE_IFELSE([AC_PROG_OBJC], + [_AM_DEPENDENCIES(OBJC)], + [define([AC_PROG_OBJC], + defn([AC_PROG_OBJC])[_AM_DEPENDENCIES(OBJC)])])dnl +]) +_AM_IF_OPTION([silent-rules], [AC_REQUIRE([AM_SILENT_RULES])])dnl +dnl The `parallel-tests' driver may need to know about EXEEXT, so add the +dnl `am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This macro +dnl is hooked onto _AC_COMPILER_EXEEXT early, see below. +AC_CONFIG_COMMANDS_PRE(dnl +[m4_provide_if([_AM_COMPILER_EXEEXT], + [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl +]) + +dnl Hook into `_AC_COMPILER_EXEEXT' early to learn its expansion. Do not +dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further +dnl mangled by Autoconf and run in a shell conditional statement. +m4_define([_AC_COMPILER_EXEEXT], +m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])]) + + +# When config.status generates a header, we must update the stamp-h file. +# This file resides in the same directory as the config header +# that is generated. The stamp files are numbered to have different names. + +# Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the +# loop where config.status creates the headers, so we can generate +# our stamp files there. +AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK], +[# Compute $1's index in $config_headers. +_am_arg=$1 +_am_stamp_count=1 +for _am_header in $config_headers :; do + case $_am_header in + $_am_arg | $_am_arg:* ) + break ;; + * ) + _am_stamp_count=`expr $_am_stamp_count + 1` ;; + esac +done +echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count]) + +# Copyright (C) 2001, 2003, 2005, 2008 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_PROG_INSTALL_SH +# ------------------ +# Define $install_sh. +AC_DEFUN([AM_PROG_INSTALL_SH], +[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +if test x"${install_sh}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; + *) + install_sh="\${SHELL} $am_aux_dir/install-sh" + esac +fi +AC_SUBST(install_sh)]) + +# Copyright (C) 2003, 2005 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 2 + +# Check whether the underlying file-system supports filenames +# with a leading dot. For instance MS-DOS doesn't. +AC_DEFUN([AM_SET_LEADING_DOT], +[rm -rf .tst 2>/dev/null +mkdir .tst 2>/dev/null +if test -d .tst; then + am__leading_dot=. +else + am__leading_dot=_ +fi +rmdir .tst 2>/dev/null +AC_SUBST([am__leading_dot])]) + +# Add --enable-maintainer-mode option to configure. -*- Autoconf -*- +# From Jim Meyering + +# Copyright (C) 1996, 1998, 2000, 2001, 2002, 2003, 2004, 2005, 2008 +# Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 5 + +# AM_MAINTAINER_MODE([DEFAULT-MODE]) +# ---------------------------------- +# Control maintainer-specific portions of Makefiles. +# Default is to disable them, unless `enable' is passed literally. +# For symmetry, `disable' may be passed as well. Anyway, the user +# can override the default with the --enable/--disable switch. +AC_DEFUN([AM_MAINTAINER_MODE], +[m4_case(m4_default([$1], [disable]), + [enable], [m4_define([am_maintainer_other], [disable])], + [disable], [m4_define([am_maintainer_other], [enable])], + [m4_define([am_maintainer_other], [enable]) + m4_warn([syntax], [unexpected argument to AM@&t@_MAINTAINER_MODE: $1])]) +AC_MSG_CHECKING([whether to am_maintainer_other maintainer-specific portions of Makefiles]) + dnl maintainer-mode's default is 'disable' unless 'enable' is passed + AC_ARG_ENABLE([maintainer-mode], +[ --][am_maintainer_other][-maintainer-mode am_maintainer_other make rules and dependencies not useful + (and sometimes confusing) to the casual installer], + [USE_MAINTAINER_MODE=$enableval], + [USE_MAINTAINER_MODE=]m4_if(am_maintainer_other, [enable], [no], [yes])) + AC_MSG_RESULT([$USE_MAINTAINER_MODE]) + AM_CONDITIONAL([MAINTAINER_MODE], [test $USE_MAINTAINER_MODE = yes]) + MAINT=$MAINTAINER_MODE_TRUE + AC_SUBST([MAINT])dnl +] +) + +AU_DEFUN([jm_MAINTAINER_MODE], [AM_MAINTAINER_MODE]) + +# Check to see how 'make' treats includes. -*- Autoconf -*- + +# Copyright (C) 2001, 2002, 2003, 2005, 2009 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 4 + +# AM_MAKE_INCLUDE() +# ----------------- +# Check to see how make treats includes. +AC_DEFUN([AM_MAKE_INCLUDE], +[am_make=${MAKE-make} +cat > confinc << 'END' +am__doit: + @echo this is the am__doit target +.PHONY: am__doit +END +# If we don't find an include directive, just comment out the code. +AC_MSG_CHECKING([for style of include used by $am_make]) +am__include="#" +am__quote= +_am_result=none +# First try GNU make style include. +echo "include confinc" > confmf +# Ignore all kinds of additional output from `make'. +case `$am_make -s -f confmf 2> /dev/null` in #( +*the\ am__doit\ target*) + am__include=include + am__quote= + _am_result=GNU + ;; +esac +# Now try BSD make style include. +if test "$am__include" = "#"; then + echo '.include "confinc"' > confmf + case `$am_make -s -f confmf 2> /dev/null` in #( + *the\ am__doit\ target*) + am__include=.include + am__quote="\"" + _am_result=BSD + ;; + esac +fi +AC_SUBST([am__include]) +AC_SUBST([am__quote]) +AC_MSG_RESULT([$_am_result]) +rm -f confinc confmf +]) + +# Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- + +# Copyright (C) 1997, 1999, 2000, 2001, 2003, 2004, 2005, 2008 +# Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 6 + +# AM_MISSING_PROG(NAME, PROGRAM) +# ------------------------------ +AC_DEFUN([AM_MISSING_PROG], +[AC_REQUIRE([AM_MISSING_HAS_RUN]) +$1=${$1-"${am_missing_run}$2"} +AC_SUBST($1)]) + + +# AM_MISSING_HAS_RUN +# ------------------ +# Define MISSING if not defined so far and test if it supports --run. +# If it does, set am_missing_run to use it, otherwise, to nothing. +AC_DEFUN([AM_MISSING_HAS_RUN], +[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +AC_REQUIRE_AUX_FILE([missing])dnl +if test x"${MISSING+set}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; + *) + MISSING="\${SHELL} $am_aux_dir/missing" ;; + esac +fi +# Use eval to expand $SHELL +if eval "$MISSING --run true"; then + am_missing_run="$MISSING --run " +else + am_missing_run= + AC_MSG_WARN([`missing' script is too old or missing]) +fi +]) + +# Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_PROG_MKDIR_P +# --------------- +# Check for `mkdir -p'. +AC_DEFUN([AM_PROG_MKDIR_P], +[AC_PREREQ([2.60])dnl +AC_REQUIRE([AC_PROG_MKDIR_P])dnl +dnl Automake 1.8 to 1.9.6 used to define mkdir_p. We now use MKDIR_P, +dnl while keeping a definition of mkdir_p for backward compatibility. +dnl @MKDIR_P@ is magic: AC_OUTPUT adjusts its value for each Makefile. +dnl However we cannot define mkdir_p as $(MKDIR_P) for the sake of +dnl Makefile.ins that do not define MKDIR_P, so we do our own +dnl adjustment using top_builddir (which is defined more often than +dnl MKDIR_P). +AC_SUBST([mkdir_p], ["$MKDIR_P"])dnl +case $mkdir_p in + [[\\/$]]* | ?:[[\\/]]*) ;; + */*) mkdir_p="\$(top_builddir)/$mkdir_p" ;; +esac +]) + +# Helper functions for option handling. -*- Autoconf -*- + +# Copyright (C) 2001, 2002, 2003, 2005, 2008 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 4 + +# _AM_MANGLE_OPTION(NAME) +# ----------------------- +AC_DEFUN([_AM_MANGLE_OPTION], +[[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])]) + +# _AM_SET_OPTION(NAME) +# ------------------------------ +# Set option NAME. Presently that only means defining a flag for this option. +AC_DEFUN([_AM_SET_OPTION], +[m4_define(_AM_MANGLE_OPTION([$1]), 1)]) + +# _AM_SET_OPTIONS(OPTIONS) +# ---------------------------------- +# OPTIONS is a space-separated list of Automake options. +AC_DEFUN([_AM_SET_OPTIONS], +[m4_foreach_w([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])]) + +# _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET]) +# ------------------------------------------- +# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. +AC_DEFUN([_AM_IF_OPTION], +[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) + +# Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_RUN_LOG(COMMAND) +# ------------------- +# Run COMMAND, save the exit status in ac_status, and log it. +# (This has been adapted from Autoconf's _AC_RUN_LOG macro.) +AC_DEFUN([AM_RUN_LOG], +[{ echo "$as_me:$LINENO: $1" >&AS_MESSAGE_LOG_FD + ($1) >&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD + (exit $ac_status); }]) + +# Check to make sure that the build environment is sane. -*- Autoconf -*- + +# Copyright (C) 1996, 1997, 2000, 2001, 2003, 2005, 2008 +# Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 5 + +# AM_SANITY_CHECK +# --------------- +AC_DEFUN([AM_SANITY_CHECK], +[AC_MSG_CHECKING([whether build environment is sane]) +# Just in case +sleep 1 +echo timestamp > conftest.file +# Reject unsafe characters in $srcdir or the absolute working directory +# name. Accept space and tab only in the latter. +am_lf=' +' +case `pwd` in + *[[\\\"\#\$\&\'\`$am_lf]]*) + AC_MSG_ERROR([unsafe absolute working directory name]);; +esac +case $srcdir in + *[[\\\"\#\$\&\'\`$am_lf\ \ ]]*) + AC_MSG_ERROR([unsafe srcdir value: `$srcdir']);; +esac + +# Do `set' in a subshell so we don't clobber the current shell's +# arguments. Must try -L first in case configure is actually a +# symlink; some systems play weird games with the mod time of symlinks +# (eg FreeBSD returns the mod time of the symlink's containing +# directory). +if ( + set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` + if test "$[*]" = "X"; then + # -L didn't work. + set X `ls -t "$srcdir/configure" conftest.file` + fi + rm -f conftest.file + if test "$[*]" != "X $srcdir/configure conftest.file" \ + && test "$[*]" != "X conftest.file $srcdir/configure"; then + + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken +alias in your environment]) + fi + + test "$[2]" = conftest.file + ) +then + # Ok. + : +else + AC_MSG_ERROR([newly created file is older than distributed files! +Check your system clock]) +fi +AC_MSG_RESULT(yes)]) + +# Copyright (C) 2009 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 1 + +# AM_SILENT_RULES([DEFAULT]) +# -------------------------- +# Enable less verbose build rules; with the default set to DEFAULT +# (`yes' being less verbose, `no' or empty being verbose). +AC_DEFUN([AM_SILENT_RULES], +[AC_ARG_ENABLE([silent-rules], +[ --enable-silent-rules less verbose build output (undo: `make V=1') + --disable-silent-rules verbose build output (undo: `make V=0')]) +case $enable_silent_rules in +yes) AM_DEFAULT_VERBOSITY=0;; +no) AM_DEFAULT_VERBOSITY=1;; +*) AM_DEFAULT_VERBOSITY=m4_if([$1], [yes], [0], [1]);; +esac +AC_SUBST([AM_DEFAULT_VERBOSITY])dnl +AM_BACKSLASH='\' +AC_SUBST([AM_BACKSLASH])dnl +_AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl +]) + +# Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_PROG_INSTALL_STRIP +# --------------------- +# One issue with vendor `install' (even GNU) is that you can't +# specify the program used to strip binaries. This is especially +# annoying in cross-compiling environments, where the build's strip +# is unlikely to handle the host's binaries. +# Fortunately install-sh will honor a STRIPPROG variable, so we +# always use install-sh in `make install-strip', and initialize +# STRIPPROG with the value of the STRIP variable (set by the user). +AC_DEFUN([AM_PROG_INSTALL_STRIP], +[AC_REQUIRE([AM_PROG_INSTALL_SH])dnl +# Installed binaries are usually stripped using `strip' when the user +# run `make install-strip'. However `strip' might not be the right +# tool to use in cross-compilation environments, therefore Automake +# will honor the `STRIP' environment variable to overrule this program. +dnl Don't test for $cross_compiling = yes, because it might be `maybe'. +if test "$cross_compiling" != no; then + AC_CHECK_TOOL([STRIP], [strip], :) +fi +INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" +AC_SUBST([INSTALL_STRIP_PROGRAM])]) + +# Copyright (C) 2006, 2008 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 2 + +# _AM_SUBST_NOTMAKE(VARIABLE) +# --------------------------- +# Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in. +# This macro is traced by Automake. +AC_DEFUN([_AM_SUBST_NOTMAKE]) + +# AM_SUBST_NOTMAKE(VARIABLE) +# --------------------------- +# Public sister of _AM_SUBST_NOTMAKE. +AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)]) + +# Check how to create a tarball. -*- Autoconf -*- + +# Copyright (C) 2004, 2005 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 2 + +# _AM_PROG_TAR(FORMAT) +# -------------------- +# Check how to create a tarball in format FORMAT. +# FORMAT should be one of `v7', `ustar', or `pax'. +# +# Substitute a variable $(am__tar) that is a command +# writing to stdout a FORMAT-tarball containing the directory +# $tardir. +# tardir=directory && $(am__tar) > result.tar +# +# Substitute a variable $(am__untar) that extract such +# a tarball read from stdin. +# $(am__untar) < result.tar +AC_DEFUN([_AM_PROG_TAR], +[# Always define AMTAR for backward compatibility. +AM_MISSING_PROG([AMTAR], [tar]) +m4_if([$1], [v7], + [am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -'], + [m4_case([$1], [ustar],, [pax],, + [m4_fatal([Unknown tar format])]) +AC_MSG_CHECKING([how to create a $1 tar archive]) +# Loop over all known methods to create a tar archive until one works. +_am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none' +_am_tools=${am_cv_prog_tar_$1-$_am_tools} +# Do not fold the above two line into one, because Tru64 sh and +# Solaris sh will not grok spaces in the rhs of `-'. +for _am_tool in $_am_tools +do + case $_am_tool in + gnutar) + for _am_tar in tar gnutar gtar; + do + AM_RUN_LOG([$_am_tar --version]) && break + done + am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"' + am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"' + am__untar="$_am_tar -xf -" + ;; + plaintar) + # Must skip GNU tar: if it does not support --format= it doesn't create + # ustar tarball either. + (tar --version) >/dev/null 2>&1 && continue + am__tar='tar chf - "$$tardir"' + am__tar_='tar chf - "$tardir"' + am__untar='tar xf -' + ;; + pax) + am__tar='pax -L -x $1 -w "$$tardir"' + am__tar_='pax -L -x $1 -w "$tardir"' + am__untar='pax -r' + ;; + cpio) + am__tar='find "$$tardir" -print | cpio -o -H $1 -L' + am__tar_='find "$tardir" -print | cpio -o -H $1 -L' + am__untar='cpio -i -H $1 -d' + ;; + none) + am__tar=false + am__tar_=false + am__untar=false + ;; + esac + + # If the value was cached, stop now. We just wanted to have am__tar + # and am__untar set. + test -n "${am_cv_prog_tar_$1}" && break + + # tar/untar a dummy directory, and stop if the command works + rm -rf conftest.dir + mkdir conftest.dir + echo GrepMe > conftest.dir/file + AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar]) + rm -rf conftest.dir + if test -s conftest.tar; then + AM_RUN_LOG([$am__untar /dev/null 2>&1 && break + fi +done +rm -rf conftest.dir + +AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool]) +AC_MSG_RESULT([$am_cv_prog_tar_$1])]) +AC_SUBST([am__tar]) +AC_SUBST([am__untar]) +]) # _AM_PROG_TAR + +m4_include([m4/check_gnu_make.m4]) +m4_include([m4/libtool.m4]) +m4_include([m4/ltoptions.m4]) +m4_include([m4/ltsugar.m4]) +m4_include([m4/ltversion.m4]) +m4_include([m4/lt~obsolete.m4]) diff --git a/libclamav/c++/bytecode2llvm.cpp b/libclamav/c++/bytecode2llvm.cpp new file mode 100644 index 000000000..4cd9d40c3 --- /dev/null +++ b/libclamav/c++/bytecode2llvm.cpp @@ -0,0 +1,1292 @@ +/* + * JIT compile ClamAV bytecode. + * + * Copyright (C) 2009 Sourcefire, Inc. + * + * Authors: Török Edvin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ +#define DEBUG_TYPE "clamavjit" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/BitVector.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/CallingConv.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Function.h" +#include "llvm/ExecutionEngine/ExecutionEngine.h" +#include "llvm/ExecutionEngine/JIT.h" +#include "llvm/ExecutionEngine/JITEventListener.h" +#include "llvm/LLVMContext.h" +#include "llvm/Module.h" +#include "llvm/PassManager.h" +#include "llvm/ModuleProvider.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/ManagedStatic.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/SourceMgr.h" +#include "llvm/Support/IRBuilder.h" +#include "llvm/Support/PrettyStackTrace.h" +#include "llvm/System/DataTypes.h" +#include "llvm/System/Mutex.h" +#include "llvm/System/Signals.h" +#include "llvm/System/Threading.h" +#include "llvm/Target/TargetSelect.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetOptions.h" +#include "llvm/Support/TargetFolder.h" +#include "llvm/Analysis/Verifier.h" +#include "llvm/Transforms/Scalar.h" +#include "llvm/System/ThreadLocal.h" +#include +#include +#include + +#include "llvm/Config/config.h" +#ifndef LLVM_MULTITHREADED +#error "Multithreading support must be available to LLVM!" +#endif + +#ifdef HAVE_CONFIG_H +#undef PACKAGE_BUGREPORT +#undef PACKAGE_NAME +#undef PACKAGE_STRING +#undef PACKAGE_TARNAME +#undef PACKAGE_VERSION +#include "clamav-config.h" +#endif +#include "clamav.h" +#include "clambc.h" +#include "bytecode.h" +#include "bytecode_priv.h" +#include "type_desc.h" + +#define MODULE "libclamav JIT: " + +using namespace llvm; +typedef DenseMap FunctionMapTy; +struct cli_bcengine { + ExecutionEngine *EE; + LLVMContext Context; + FunctionMapTy compiledFunctions; +}; + +namespace { + +static sys::ThreadLocal ExceptionReturn; +static sys::ThreadLocal MatchCounts; + +void do_shutdown() { + llvm_shutdown(); +} + +static void NORETURN jit_exception_handler(void) +{ + longjmp(*const_cast(ExceptionReturn.get()), 1); +} + +void llvm_error_handler(void *user_data, const std::string &reason) +{ + // Output it to stderr, it might exceed the 1k/4k limit of cli_errmsg + errs() << MODULE << reason; + jit_exception_handler(); +} + +class LLVMTypeMapper { +private: + std::vector TypeMap; + LLVMContext &Context; + unsigned numTypes; + const Type *getStatic(uint16_t ty) + { + if (!ty) + return Type::getVoidTy(Context); + if (ty <= 64) + return IntegerType::get(Context, ty); + switch (ty) { + case 65: + return PointerType::getUnqual(Type::getInt8Ty(Context)); + case 66: + return PointerType::getUnqual(Type::getInt16Ty(Context)); + case 67: + return PointerType::getUnqual(Type::getInt32Ty(Context)); + case 68: + return PointerType::getUnqual(Type::getInt64Ty(Context)); + } + llvm_unreachable("getStatic"); + } +public: + LLVMTypeMapper(LLVMContext &Context, const struct cli_bc_type *types, + unsigned count, const Type *Hidden=0) : Context(Context), numTypes(count) + { + TypeMap.reserve(count); + // During recursive type construction pointers to Type* may be + // invalidated, so we must use a TypeHolder to an Opaque type as a + // start. + for (unsigned i=0;i Elts; + for (unsigned i=0;ikind == DArrayType ? 1 : type->numElements; + for (unsigned j=0;jcontainedTypes[j])); + } + const Type *Ty; + switch (type->kind) { + case DFunctionType: + { + assert(Elts.size() > 0 && "Function with no return type?"); + const Type *RetTy = Elts[0]; + if (Hidden) + Elts[0] = Hidden; + else + Elts.erase(Elts.begin()); + Ty = FunctionType::get(RetTy, Elts, false); + break; + } + case DPointerType: + Ty = PointerType::getUnqual(Elts[0]); + break; + case DStructType: + Ty = StructType::get(Context, Elts); + break; + case DPackedStructType: + Ty = StructType::get(Context, Elts, true); + break; + case DArrayType: + Ty = ArrayType::get(Elts[0], type->numElements); + break; + } + // Make the opaque type a concrete type, doing recursive type + // unification if needed. + cast(TypeMap[i].get())->refineAbstractTypeTo(Ty); + } + } + + const Type *get(uint16_t ty) + { + ty &= 0x7fff; + if (ty < 69) + return getStatic(ty); + ty -= 69; + assert(ty < numTypes && "TypeID out of range"); + return TypeMap[ty].get(); + } +}; + + +class VISIBILITY_HIDDEN LLVMCodegen { +private: + const struct cli_bc *bc; + Module *M; + LLVMContext &Context; + LLVMTypeMapper *TypeMap; + Function **apiFuncs; + FunctionMapTy &compiledFunctions; + LLVMTypeMapper &apiMap; + Twine BytecodeID; + ExecutionEngine *EE; + TargetFolder Folder; + IRBuilder Builder; + std::vector globals; + Value **Values; + FunctionPassManager &PM; + unsigned numLocals; + unsigned numArgs; + DenseMap GVoffsetMap; + DenseMap GVtypeMap; + std::vector mdnodes; + + Value *getOperand(const struct cli_bc_func *func, const Type *Ty, operand_t operand) + { + unsigned map[] = {0, 1, 2, 3, 3, 4, 4, 4, 4}; + if (operand < func->numValues) + return Values[operand]; + unsigned w = (Ty->getPrimitiveSizeInBits()+7)/8; + return convertOperand(func, map[w], operand); + } + + Value *convertOperand(const struct cli_bc_func *func, const Type *Ty, operand_t operand) + { + unsigned map[] = {0, 1, 2, 3, 3, 4, 4, 4, 4}; + if (operand < func->numArgs) + return Values[operand]; + if (operand < func->numValues) { + Value *V = Values[operand]; + if (func->types[operand]&0x8000 && V->getType() == Ty) { + return V; + } + V = Builder.CreateLoad(V); + if (V->getType() != Ty) { + errs() << operand << " "; + V->dump(); + Ty->dump(); + llvm_report_error("(libclamav) Type mismatch converting operand"); + } + return V; + } + unsigned w = (Ty->getPrimitiveSizeInBits()+7)/8; + return convertOperand(func, map[w], operand); + } + + Value *convertOperand(const struct cli_bc_func *func, + const struct cli_bc_inst *inst, operand_t operand) + { + return convertOperand(func, inst->interp_op%5, operand); + } + + Value *convertOperand(const struct cli_bc_func *func, + unsigned w, operand_t operand) { + if (operand < func->numArgs) + return Values[operand]; + if (operand < func->numValues) { + if (func->types[operand]&0x8000) + return Values[operand]; + return Builder.CreateLoad(Values[operand]); + } + + if (operand & 0x80000000) { + operand &= 0x7fffffff; + assert(operand < globals.size() && "Global index out of range"); + // Global + if (!operand) + return ConstantPointerNull::get(PointerType::getUnqual(Type::getInt8Ty(Context))); + assert(globals[operand]); + if (GlobalVariable *GV = dyn_cast(globals[operand])) { + if (ConstantExpr *CE = dyn_cast(GV->getInitializer())) { + return CE; + } + return GV; + } + return globals[operand]; + } + // Constant + operand -= func->numValues; + // This was already validated by libclamav. + assert(operand < func->numConstants && "Constant out of range"); + uint64_t *c = &func->constants[operand]; + uint64_t v; + const Type *Ty; + switch (w) { + case 0: + case 1: + Ty = w ? Type::getInt8Ty(Context) : + Type::getInt1Ty(Context); + v = *(uint8_t*)c; + break; + case 2: + Ty = Type::getInt16Ty(Context); + v = *(uint16_t*)c; + break; + case 3: + Ty = Type::getInt32Ty(Context); + v = *(uint32_t*)c; + break; + case 4: + Ty = Type::getInt64Ty(Context); + v = *(uint64_t*)c; + break; + } + return ConstantInt::get(Ty, v); + } + + void Store(uint16_t dest, Value *V) + { + assert(dest >= numArgs && dest < numLocals+numArgs && "Instruction destination out of range"); + Builder.CreateStore(V, Values[dest]); + } + + // Insert code that calls \arg FHandler if \arg FailCond is true. + void InsertVerify(Value *FailCond, BasicBlock *&Fail, Function *FHandler, + Function *F) { + if (!Fail) { + Fail = BasicBlock::Create(Context, "fail", F); + CallInst::Create(FHandler,"",Fail); + new UnreachableInst(Context, Fail); + } + BasicBlock *OkBB = BasicBlock::Create(Context, "", F); + Builder.CreateCondBr(FailCond, Fail, OkBB); + Builder.SetInsertPoint(OkBB); + } + + const Type* mapType(uint16_t typeID) + { + return TypeMap->get(typeID&0x7fffffff); + } + + Constant *buildConstant(const Type *Ty, uint64_t *components, unsigned &c) + { + if (const PointerType *PTy = dyn_cast(Ty)) { + Value *idxs[2] = { + ConstantInt::get(Type::getInt32Ty(Context), 0), + ConstantInt::get(Type::getInt32Ty(Context), components[c++]) + }; + unsigned idx = components[c++]; + if (!idx) + return ConstantPointerNull::get(PTy); + assert(idx < globals.size()); + GlobalVariable *GV = cast(globals[idx]); + const Type *GTy = GetElementPtrInst::getIndexedType(GV->getType(), idxs, 2); + if (!GTy) { + errs() << "Type mismatch for GEP: " << *PTy->getElementType() << + "; base is " << *GV << "\n"; + llvm_report_error("(libclamav) Type mismatch converting constant"); + } + return ConstantExpr::getPointerCast( + ConstantExpr::getInBoundsGetElementPtr(GV, idxs, 2), + PTy); + } + if (isa(Ty)) { + return ConstantInt::get(Ty, components[c++]); + } + if (const ArrayType *ATy = dyn_cast(Ty)) { + std::vector elements; + elements.reserve(ATy->getNumElements()); + for (unsigned i=0;igetNumElements();i++) { + elements.push_back(buildConstant(ATy->getElementType(), components, c)); + } + return ConstantArray::get(ATy, elements); + } + if (const StructType *STy = dyn_cast(Ty)) { + std::vector elements; + elements.reserve(STy->getNumElements()); + for (unsigned i=0;igetNumElements();i++) { + elements.push_back(buildConstant(STy->getElementType(i), components, c)); + } + return ConstantStruct::get(STy, elements); + } + Ty->dump(); + assert(0 && "Not reached"); + return 0; + } + + +public: + LLVMCodegen(const struct cli_bc *bc, Module *M, FunctionMapTy &cFuncs, + ExecutionEngine *EE, FunctionPassManager &PM, + Function **apiFuncs, LLVMTypeMapper &apiMap) + : bc(bc), M(M), Context(M->getContext()), compiledFunctions(cFuncs), + BytecodeID("bc"+Twine(bc->id)), EE(EE), + Folder(EE->getTargetData()), Builder(Context, Folder), PM(PM), + apiFuncs(apiFuncs), apiMap(apiMap) + { + for (unsigned i=0;i + Value* createGEP(Value *Base, const Type *ETy, InputIterator Start, InputIterator End) { + const Type *Ty = GetElementPtrInst::getIndexedType(Base->getType(), Start, End); + if (!Ty || (ETy && (Ty != ETy && (!isa(Ty) || !isa(ETy))))) { + errs() << MODULE << "Wrong indices for GEP opcode: " + << " expected type: " << *ETy; + if (Ty) + errs() << " actual type: " << *Ty; + errs() << " base: " << *Base << " indices: "; + for (InputIterator I=Start; I != End; I++) { + errs() << **I << ", "; + } + errs() << "\n"; + return 0; + } + return Builder.CreateGEP(Base, Start, End); + } + + template + bool createGEP(unsigned dest, Value *Base, InputIterator Start, InputIterator End) { + assert(dest >= numArgs && dest < numLocals+numArgs && "Instruction destination out of range"); + const Type *ETy = cast(cast(Values[dest]->getType())->getElementType())->getElementType(); + Value *V = createGEP(Base, ETy, Start, End); + if (!V) + return false; + V = Builder.CreateBitCast(V, PointerType::getUnqual(ETy)); + Store(dest, V); + return true; + } + + MDNode *convertMDNode(unsigned i) { + if (i < mdnodes.size()) { + if (mdnodes[i]) + return mdnodes[i]; + } else + mdnodes.resize(i+1); + assert(i < mdnodes.size()); + const struct cli_bc_dbgnode *node = &bc->dbgnodes[i]; + Value **Vals = new Value*[node->numelements]; + for (unsigned j=0;jnumelements;j++) { + const struct cli_bc_dbgnode_element* el = &node->elements[j]; + Value *V; + if (!el->len) { + if (el->nodeid == ~0u) + V = 0; + else if (el->nodeid) + V = convertMDNode(el->nodeid); + else + V = MDString::get(Context, ""); + } else if (el->string) { + V = MDString::get(Context, StringRef(el->string, el->len)); + } else { + V = ConstantInt::get(IntegerType::get(Context, el->len), + el->constant); + } + Vals[j] = V; + } + MDNode *N = MDNode::get(Context, Vals, node->numelements); + delete[] Vals; + mdnodes[i] = N; + return N; + } + + bool generate() { + TypeMap = new LLVMTypeMapper(Context, bc->types + 4, bc->num_types - 5); + for (unsigned i=0;idbgnode_cnt;i++) { + mdnodes.push_back(convertMDNode(i)); + } + + for (unsigned i=0;i(Ty)) + Ty = PointerType::getUnqual(ATy->getElementType());*/ + GVtypeMap[id] = Ty; + } + FunctionType *FTy = FunctionType::get(Type::getVoidTy(Context), + false); + Function *FHandler = Function::Create(FTy, Function::InternalLinkage, + "clamjit.fail", M); + FHandler->setDoesNotReturn(); + FHandler->setDoesNotThrow(); + FHandler->addFnAttr(Attribute::NoInline); + EE->addGlobalMapping(FHandler, (void*)jit_exception_handler); + + std::vector args; + args.push_back(PointerType::getUnqual(Type::getInt8Ty(Context))); + args.push_back(Type::getInt8Ty(Context)); + args.push_back(Type::getInt32Ty(Context)); + args.push_back(Type::getInt32Ty(Context)); + FunctionType* FuncTy_3 = FunctionType::get(Type::getVoidTy(Context), + args, false); + Function *FMemset = Function::Create(FuncTy_3, GlobalValue::ExternalLinkage, + "llvm.memset.i32", M); + FMemset->setDoesNotThrow(); + FMemset->setDoesNotCapture(1, true); + + args.clear(); + args.push_back(PointerType::getUnqual(Type::getInt8Ty(Context))); + args.push_back(PointerType::getUnqual(Type::getInt8Ty(Context))); + args.push_back(Type::getInt32Ty(Context)); + args.push_back(Type::getInt32Ty(Context)); + FunctionType* FuncTy_4 = FunctionType::get(Type::getVoidTy(Context), + args, false); + Function *FMemmove = Function::Create(FuncTy_4, GlobalValue::ExternalLinkage, + "llvm.memmove.i32", M); + FMemmove->setDoesNotThrow(); + FMemmove->setDoesNotCapture(1, true); + + Function *FMemcpy = Function::Create(FuncTy_4, GlobalValue::ExternalLinkage, + "llvm.memcpy.i32", M); + FMemcpy->setDoesNotThrow(); + FMemcpy->setDoesNotCapture(1, true); + + FunctionType* DummyTy = FunctionType::get(Type::getVoidTy(Context), false); + Function *FRealMemset = Function::Create(DummyTy, GlobalValue::ExternalLinkage, + "memset", M); + EE->addGlobalMapping(FRealMemset, (void*)memset); + Function *FRealMemmove = Function::Create(DummyTy, GlobalValue::ExternalLinkage, + "memmove", M); + EE->addGlobalMapping(FRealMemmove, (void*)memmove); + Function *FRealMemcpy = Function::Create(DummyTy, GlobalValue::ExternalLinkage, + "memcpy", M); + EE->addGlobalMapping(FRealMemcpy, (void*)memcpy); + + args.clear(); + args.push_back(PointerType::getUnqual(Type::getInt8Ty(Context))); + args.push_back(PointerType::getUnqual(Type::getInt8Ty(Context))); + args.push_back(EE->getTargetData()->getIntPtrType(Context)); + FunctionType* FuncTy_5 = FunctionType::get(Type::getInt32Ty(Context), + args, false); + Function* FRealMemcmp = Function::Create(FuncTy_5, GlobalValue::ExternalLinkage, "memcmp", M); + EE->addGlobalMapping(FRealMemcmp, (void*)memcmp); + + // The hidden ctx param to all functions + const Type *HiddenCtx = PointerType::getUnqual(Type::getInt8Ty(Context)); + + globals.reserve(bc->num_globals); + BitVector FakeGVs; + FakeGVs.resize(bc->num_globals); + globals.push_back(0); + for (unsigned i=1;inum_globals;i++) { + const Type *Ty = mapType(bc->globaltys[i]); + + // TODO: validate number of components against type_components + unsigned c = 0; + GlobalVariable *GV; + if (isa(Ty)) { + unsigned g = bc->globals[i][1]; + if (GVoffsetMap.count(g)) { + FakeGVs.set(i); + globals.push_back(0); + continue; + } + } + Constant *C = buildConstant(Ty, bc->globals[i], c); + GV = new GlobalVariable(*M, Ty, true, + GlobalValue::InternalLinkage, + C, "glob"+Twine(i)); + globals.push_back(GV); + } + + Function **Functions = new Function*[bc->num_func]; + for (unsigned j=0;jnum_func;j++) { + PrettyStackTraceString CrashInfo("Generate LLVM IR functions"); + // Create LLVM IR Function + const struct cli_bc_func *func = &bc->funcs[j]; + std::vector argTypes; + argTypes.push_back(HiddenCtx); + for (unsigned a=0;anumArgs;a++) { + argTypes.push_back(mapType(func->types[a])); + } + const Type *RetTy = mapType(func->returnType); + FunctionType *FTy = FunctionType::get(RetTy, argTypes, + false); + Functions[j] = Function::Create(FTy, Function::InternalLinkage, + BytecodeID+"f"+Twine(j), M); + Functions[j]->setDoesNotThrow(); + Functions[j]->setCallingConv(CallingConv::Fast); + } + const Type *I32Ty = Type::getInt32Ty(Context); + for (unsigned j=0;jnum_func;j++) { + PrettyStackTraceString CrashInfo("Generate LLVM IR"); + const struct cli_bc_func *func = &bc->funcs[j]; + + // Create all BasicBlocks + Function *F = Functions[j]; + BasicBlock **BB = new BasicBlock*[func->numBB]; + for (unsigned i=0;inumBB;i++) { + BB[i] = BasicBlock::Create(Context, "", F); + } + + BasicBlock *Fail = 0; + Values = new Value*[func->numValues]; + Builder.SetInsertPoint(BB[0]); + Function::arg_iterator I = F->arg_begin(); + assert(F->arg_size() == func->numArgs + 1 && "Mismatched args"); + ++I; + for (unsigned i=0;inumArgs; i++) { + assert(I != F->arg_end()); + Values[i] = &*I; + ++I; + } + for (unsigned i=func->numArgs;inumValues;i++) { + if (!func->types[i]) { + //instructions without return value, like store + Values[i] = 0; + continue; + } + Values[i] = Builder.CreateAlloca(mapType(func->types[i])); + } + numLocals = func->numLocals; + numArgs = func->numArgs; + + if (FakeGVs.any()) { + Argument *Ctx = F->arg_begin(); + struct cli_bc_ctx *N = 0; + for (unsigned i=0;inum_globals;i++) { + if (!FakeGVs[i]) + continue; + unsigned g = bc->globals[i][1]; + unsigned offset = GVoffsetMap[g]; + Constant *Idx = ConstantInt::get(Type::getInt32Ty(Context), + offset); + Value *GEP = Builder.CreateInBoundsGEP(Ctx, Idx); + const Type *Ty = GVtypeMap[g]; + Ty = PointerType::getUnqual(PointerType::getUnqual(Ty)); + Value *Cast = Builder.CreateBitCast(GEP, Ty); + Value *SpecialGV = Builder.CreateLoad(Cast); + Value *C[] = { + ConstantInt::get(Type::getInt32Ty(Context), 0), + ConstantInt::get(Type::getInt32Ty(Context), bc->globals[i][0]) + }; + globals[i] = createGEP(SpecialGV, 0, C, C+2); + if (!globals[i]) { + errs() << i << ":" << g << ":" << bc->globals[i][0] <<"\n"; + Ty->dump(); + llvm_report_error("(libclamav) unable to create fake global"); + } + else if(GetElementPtrInst *GI = dyn_cast(globals[i])) + GI->setIsInBounds(true); + } + } + + // Generate LLVM IR for each BB + for (unsigned i=0;inumBB;i++) { + bool unreachable = false; + const struct cli_bc_bb *bb = &func->BB[i]; + Builder.SetInsertPoint(BB[i]); + unsigned c = 0; + for (unsigned j=0;jnumInsts;j++) { + const struct cli_bc_inst *inst = &bb->insts[j]; + Value *Op0, *Op1, *Op2; + // libclamav has already validated this. + assert(inst->opcode < OP_BC_INVALID && "Invalid opcode"); + if (func->dbgnodes) { + if (func->dbgnodes[c] != ~0u) { + unsigned j = func->dbgnodes[c]; + assert(j < mdnodes.size()); + Builder.SetCurrentDebugLocation(mdnodes[j]); + } else + Builder.SetCurrentDebugLocation(0); + } + c++; + switch (inst->opcode) { + case OP_BC_JMP: + case OP_BC_BRANCH: + case OP_BC_CALL_API: + case OP_BC_CALL_DIRECT: + case OP_BC_ZEXT: + case OP_BC_SEXT: + case OP_BC_TRUNC: + case OP_BC_GEP1: + case OP_BC_GEP2: + case OP_BC_GEPN: + case OP_BC_STORE: + case OP_BC_COPY: + case OP_BC_RET: + // these instructions represents operands differently + break; + default: + switch (operand_counts[inst->opcode]) { + case 1: + Op0 = convertOperand(func, inst, inst->u.unaryop); + break; + case 2: + Op0 = convertOperand(func, inst, inst->u.binop[0]); + Op1 = convertOperand(func, inst, inst->u.binop[1]); + if (Op0->getType() != Op1->getType()) { + Op0->dump(); + Op1->dump(); + llvm_report_error("(libclamav) binop type mismatch"); + } + break; + case 3: + Op0 = convertOperand(func, inst, inst->u.three[0]); + Op1 = convertOperand(func, inst, inst->u.three[1]); + Op2 = convertOperand(func, inst, inst->u.three[2]); + break; + } + } + + switch (inst->opcode) { + case OP_BC_ADD: + Store(inst->dest, Builder.CreateAdd(Op0, Op1)); + break; + case OP_BC_SUB: + Store(inst->dest, Builder.CreateSub(Op0, Op1)); + break; + case OP_BC_MUL: + Store(inst->dest, Builder.CreateMul(Op0, Op1)); + break; + case OP_BC_UDIV: + { + Value *Bad = Builder.CreateICmpEQ(Op1, ConstantInt::get(Op1->getType(), 0)); + InsertVerify(Bad, Fail, FHandler, F); + Store(inst->dest, Builder.CreateUDiv(Op0, Op1)); + break; + } + case OP_BC_SDIV: + { + //TODO: also verify Op0 == -1 && Op1 = INT_MIN + Value *Bad = Builder.CreateICmpEQ(Op1, ConstantInt::get(Op1->getType(), 0)); + InsertVerify(Bad, Fail, FHandler, F); + Store(inst->dest, Builder.CreateSDiv(Op0, Op1)); + break; + } + case OP_BC_UREM: + { + Value *Bad = Builder.CreateICmpEQ(Op1, ConstantInt::get(Op1->getType(), 0)); + InsertVerify(Bad, Fail, FHandler, F); + Store(inst->dest, Builder.CreateURem(Op0, Op1)); + break; + } + case OP_BC_SREM: + { + //TODO: also verify Op0 == -1 && Op1 = INT_MIN + Value *Bad = Builder.CreateICmpEQ(Op1, ConstantInt::get(Op1->getType(), 0)); + InsertVerify(Bad, Fail, FHandler, F); + Store(inst->dest, Builder.CreateSRem(Op0, Op1)); + break; + } + case OP_BC_SHL: + Store(inst->dest, Builder.CreateShl(Op0, Op1)); + break; + case OP_BC_LSHR: + Store(inst->dest, Builder.CreateLShr(Op0, Op1)); + break; + case OP_BC_ASHR: + Store(inst->dest, Builder.CreateAShr(Op0, Op1)); + break; + case OP_BC_AND: + Store(inst->dest, Builder.CreateAnd(Op0, Op1)); + break; + case OP_BC_OR: + Store(inst->dest, Builder.CreateOr(Op0, Op1)); + break; + case OP_BC_XOR: + Store(inst->dest, Builder.CreateXor(Op0, Op1)); + break; + case OP_BC_TRUNC: + { + Value *Src = convertOperand(func, inst, inst->u.cast.source); + const Type *Ty = mapType(func->types[inst->dest]); + Store(inst->dest, Builder.CreateTrunc(Src, Ty)); + break; + } + case OP_BC_ZEXT: + { + Value *Src = convertOperand(func, inst, inst->u.cast.source); + const Type *Ty = mapType(func->types[inst->dest]); + Store(inst->dest, Builder.CreateZExt(Src, Ty)); + break; + } + case OP_BC_SEXT: + { + Value *Src = convertOperand(func, inst, inst->u.cast.source); + const Type *Ty = mapType(func->types[inst->dest]); + Store(inst->dest, Builder.CreateSExt(Src, Ty)); + break; + } + case OP_BC_BRANCH: + { + Value *Cond = convertOperand(func, inst, inst->u.branch.condition); + BasicBlock *True = BB[inst->u.branch.br_true]; + BasicBlock *False = BB[inst->u.branch.br_false]; + if (Cond->getType() != Type::getInt1Ty(Context)) { + errs() << MODULE << "type mismatch in condition\n"; + return false; + } + Builder.CreateCondBr(Cond, True, False); + break; + } + case OP_BC_JMP: + { + BasicBlock *Jmp = BB[inst->u.jump]; + Builder.CreateBr(Jmp); + break; + } + case OP_BC_RET: + { + Op0 = convertOperand(func, F->getReturnType(), inst->u.unaryop); + Builder.CreateRet(Op0); + break; + } + case OP_BC_RET_VOID: + Builder.CreateRetVoid(); + break; + case OP_BC_ICMP_EQ: + Store(inst->dest, Builder.CreateICmpEQ(Op0, Op1)); + break; + case OP_BC_ICMP_NE: + Store(inst->dest, Builder.CreateICmpNE(Op0, Op1)); + break; + case OP_BC_ICMP_UGT: + Store(inst->dest, Builder.CreateICmpUGT(Op0, Op1)); + break; + case OP_BC_ICMP_UGE: + Store(inst->dest, Builder.CreateICmpUGE(Op0, Op1)); + break; + case OP_BC_ICMP_ULT: + Store(inst->dest, Builder.CreateICmpULT(Op0, Op1)); + break; + case OP_BC_ICMP_ULE: + Store(inst->dest, Builder.CreateICmpULE(Op0, Op1)); + break; + case OP_BC_ICMP_SGT: + Store(inst->dest, Builder.CreateICmpSGT(Op0, Op1)); + break; + case OP_BC_ICMP_SGE: + Store(inst->dest, Builder.CreateICmpSGE(Op0, Op1)); + break; + case OP_BC_ICMP_SLT: + Store(inst->dest, Builder.CreateICmpSLT(Op0, Op1)); + break; + case OP_BC_SELECT: + Store(inst->dest, Builder.CreateSelect(Op0, Op1, Op2)); + break; + case OP_BC_COPY: + { + Value *Dest = Values[inst->u.binop[1]]; + const PointerType *PTy = cast(Dest->getType()); + Op0 = convertOperand(func, PTy->getElementType(), inst->u.binop[0]); + Builder.CreateStore(Op0, Dest); + break; + } + case OP_BC_CALL_DIRECT: + { + Function *DestF = Functions[inst->u.ops.funcid]; + SmallVector args; + args.push_back(&*F->arg_begin()); // pass hidden arg + for (unsigned a=0;au.ops.numOps;a++) { + operand_t op = inst->u.ops.ops[a]; + args.push_back(convertOperand(func, DestF->getFunctionType()->getParamType(a+1), op)); + } + CallInst *CI = Builder.CreateCall(DestF, args.begin(), args.end()); + CI->setCallingConv(CallingConv::Fast); + if (CI->getType()->getTypeID() != Type::VoidTyID) + Store(inst->dest, CI); + break; + } + case OP_BC_CALL_API: + { + assert(inst->u.ops.funcid < cli_apicall_maxapi && "APICall out of range"); + const struct cli_apicall *api = &cli_apicalls[inst->u.ops.funcid]; + std::vector args; + Function *DestF = apiFuncs[inst->u.ops.funcid]; + args.push_back(&*F->arg_begin()); // pass hidden arg + for (unsigned a=0;au.ops.numOps;a++) { + operand_t op = inst->u.ops.ops[a]; + args.push_back(convertOperand(func, DestF->getFunctionType()->getParamType(a+1), op)); + } + Store(inst->dest, Builder.CreateCall(DestF, args.begin(), args.end())); + break; + } + case OP_BC_GEP1: + { + Value *V = convertOperand(func, inst, inst->u.binop[0]); + Value *Op = convertOperand(func, I32Ty, inst->u.binop[1]); + if (!createGEP(inst->dest, V, &Op, &Op+1)) + return false; + break; + } + case OP_BC_GEP2: + { + std::vector Idxs; + Value *V = convertOperand(func, inst, inst->u.three[0]); + Idxs.push_back(convertOperand(func, I32Ty, inst->u.three[1])); + Idxs.push_back(convertOperand(func, I32Ty, inst->u.three[2])); + if (!createGEP(inst->dest, V, Idxs.begin(), Idxs.end())) + return false; + break; + } + case OP_BC_GEPN: + { + std::vector Idxs; + assert(inst->u.ops.numOps > 1); + Value *V = convertOperand(func, inst, inst->u.binop[0]); + for (unsigned a=1;au.ops.numOps;a++) + Idxs.push_back(convertOperand(func, I32Ty, inst->u.ops.ops[a])); + if (!createGEP(inst->dest, V, Idxs.begin(), Idxs.end())) + return false; + break; + } + case OP_BC_STORE: + { + Value *Dest = convertOperand(func, inst, inst->u.binop[1]); + Value *V = convertOperand(func, inst, inst->u.binop[0]); + const Type *VPTy = PointerType::getUnqual(V->getType()); + if (VPTy != Dest->getType()) + Dest = Builder.CreateBitCast(Dest, VPTy); + Builder.CreateStore(V, Dest); + break; + } + case OP_BC_LOAD: + { + Op0 = Builder.CreateBitCast(Op0, + Values[inst->dest]->getType()); + Op0 = Builder.CreateLoad(Op0); + Store(inst->dest, Op0); + break; + } + case OP_BC_MEMSET: + { + Value *Dst = convertOperand(func, inst, inst->u.three[0]); + Value *Val = convertOperand(func, Type::getInt8Ty(Context), inst->u.three[1]); + Value *Len = convertOperand(func, Type::getInt32Ty(Context), inst->u.three[2]); + CallInst *c = Builder.CreateCall4(FMemset, Dst, Val, Len, + ConstantInt::get(Type::getInt32Ty(Context), 1)); + c->setTailCall(true); + c->setDoesNotThrow(); + break; + } + case OP_BC_MEMCPY: + { + Value *Dst = convertOperand(func, inst, inst->u.three[0]); + Value *Src = convertOperand(func, inst, inst->u.three[1]); + Value *Len = convertOperand(func, Type::getInt32Ty(Context), inst->u.three[2]); + CallInst *c = Builder.CreateCall4(FMemcpy, Dst, Src, Len, + ConstantInt::get(Type::getInt32Ty(Context), 1)); + c->setTailCall(true); + c->setDoesNotThrow(); + break; + } + case OP_BC_MEMMOVE: + { + Value *Dst = convertOperand(func, inst, inst->u.three[0]); + Value *Src = convertOperand(func, inst, inst->u.three[1]); + Value *Len = convertOperand(func, Type::getInt32Ty(Context), inst->u.three[2]); + CallInst *c = Builder.CreateCall4(FMemmove, Dst, Src, Len, + ConstantInt::get(Type::getInt32Ty(Context), 1)); + c->setTailCall(true); + c->setDoesNotThrow(); + break; + } + case OP_BC_MEMCMP: + { + Value *Dst = convertOperand(func, inst, inst->u.three[0]); + Value *Src = convertOperand(func, inst, inst->u.three[1]); + Value *Len = convertOperand(func, EE->getTargetData()->getIntPtrType(Context), inst->u.three[2]); + CallInst *c = Builder.CreateCall3(FRealMemcmp, Dst, Src, Len); + c->setTailCall(true); + c->setDoesNotThrow(); + Store(inst->dest, c); + break; + } + case OP_BC_ISBIGENDIAN: + Store(inst->dest, WORDS_BIGENDIAN ? + ConstantInt::getTrue(Context) : + ConstantInt::getFalse(Context)); + break; + case OP_BC_ABORT: + if (!unreachable) { + CallInst *CI = Builder.CreateCall(FHandler); + CI->setDoesNotReturn(); + CI->setDoesNotThrow(); + Builder.CreateUnreachable(); + unreachable = true; + } + break; + default: + errs() << MODULE << "JIT doesn't implement opcode " << + inst->opcode << " yet!\n"; + return false; + } + } + } + + if (verifyFunction(*F, PrintMessageAction)) { + errs() << MODULE << "Verification failed\n"; + F->dump(); + // verification failed + return false; + } + PM.run(*F); + delete [] Values; + delete [] BB; + } + + DEBUG(M->dump()); + delete TypeMap; + args.clear(); + args.push_back(PointerType::getUnqual(Type::getInt8Ty(Context))); + FunctionType *Callable = FunctionType::get(Type::getInt32Ty(Context), + args, false); + for (unsigned j=0;jnum_func;j++) { + const struct cli_bc_func *func = &bc->funcs[j]; + PrettyStackTraceString CrashInfo2("Native machine codegen"); + + // If prototype matches, add to callable functions + if (Functions[j]->getFunctionType() == Callable) { + // All functions have the Fast calling convention, however + // entrypoint can only be C, emit wrapper + Function *F = Function::Create(Functions[j]->getFunctionType(), + Function::ExternalLinkage, + Functions[j]->getName()+"_wrap", M); + F->setDoesNotThrow(); + BasicBlock *BB = BasicBlock::Create(Context, "", F); + std::vector args; + for (Function::arg_iterator J=F->arg_begin(), + JE=F->arg_end(); J != JE; ++JE) { + args.push_back(&*J); + } + CallInst *CI = CallInst::Create(Functions[j], args.begin(), args.end(), "", BB); + CI->setCallingConv(CallingConv::Fast); + ReturnInst::Create(Context, CI, BB); + + if (verifyFunction(*F, PrintMessageAction)); + // Codegen current function as executable machine code. + void *code = EE->getPointerToFunction(F); + + compiledFunctions[func] = code; + } + } + delete [] Functions; + return true; + } +}; +} + +int cli_vm_execute_jit(const struct cli_all_bc *bcs, struct cli_bc_ctx *ctx, + const struct cli_bc_func *func) +{ + jmp_buf env; + void *code = bcs->engine->compiledFunctions[func]; + if (!code) { + errs() << MODULE << "Unable to find compiled function\n"; + if (func->numArgs) + errs() << MODULE << "Function has " + << (unsigned)func->numArgs << " arguments, it must have 0 to be called as entrypoint\n"; + return CL_EBYTECODE; + } + // execute; + if (setjmp(env) == 0) { + // setup exception handler to longjmp back here + ExceptionReturn.set(&env); + uint32_t result = ((uint32_t (*)(struct cli_bc_ctx *))code)(ctx); + *(uint32_t*)ctx->values = result; + return 0; + } + errs() << "\n"; + errs().changeColor(raw_ostream::RED, true) << MODULE + << "*** JITed code intercepted runtime error!\n"; + errs().resetColor(); + return CL_EBYTECODE; +} + +int cli_bytecode_prepare_jit(struct cli_all_bc *bcs) +{ + if (!bcs->engine) + return CL_EBYTECODE; + jmp_buf env; + // setup exception handler to longjmp back here + ExceptionReturn.set(&env); + if (setjmp(env) != 0) { + errs() << "\n"; + errs().changeColor(raw_ostream::RED, true) << MODULE + << "*** FATAL error encountered during bytecode generation\n"; + errs().resetColor(); + return CL_EBYTECODE; + } + // LLVM itself never throws exceptions, but operator new may throw bad_alloc + try { + Module *M = new Module("ClamAV jit module", bcs->engine->Context); + ExistingModuleProvider *MP = new ExistingModuleProvider(M); + { + // Create the JIT. + std::string ErrorMsg; + EngineBuilder builder(MP); + builder.setErrorStr(&ErrorMsg); + builder.setEngineKind(EngineKind::JIT); + builder.setOptLevel(CodeGenOpt::Aggressive); + ExecutionEngine *EE = bcs->engine->EE = builder.create(); + if (!EE) { + if (!ErrorMsg.empty()) + errs() << MODULE << "error creating execution engine: " << ErrorMsg << "\n"; + else + errs() << MODULE << "JIT not registered?\n"; + return CL_EBYTECODE; + } + +// EE->RegisterJITEventListener(createOProfileJITEventListener()); + // Due to LLVM PR4816 only X86 supports non-lazy compilation, disable + // for now. + EE->DisableLazyCompilation(); + EE->DisableSymbolSearching(); + + FunctionPassManager OurFPM(MP); + // Set up the optimizer pipeline. Start with registering info about how + // the target lays out data structures. + OurFPM.add(new TargetData(*EE->getTargetData())); + // Promote allocas to registers. + OurFPM.add(createPromoteMemoryToRegisterPass()); + // Delete dead instructions + OurFPM.add(createDeadCodeEliminationPass()); + // Fold constants + OurFPM.add(createConstantPropagationPass()); + // SimplifyCFG + OurFPM.add(createCFGSimplificationPass()); + OurFPM.doInitialization(); + + //TODO: create a wrapper that calls pthread_getspecific + const Type *HiddenCtx = PointerType::getUnqual(Type::getInt8Ty(bcs->engine->Context)); + + LLVMTypeMapper apiMap(bcs->engine->Context, cli_apicall_types, cli_apicall_maxtypes, HiddenCtx); + Function **apiFuncs = new Function *[cli_apicall_maxapi]; + for (unsigned i=0;i(apiMap.get(69+api->type)); + Function *F = Function::Create(FTy, Function::ExternalLinkage, + api->name, M); + void *dest; + switch (api->kind) { + case 0: + dest = (void*)cli_apicalls0[api->idx]; + break; + case 1: + dest = (void*)cli_apicalls1[api->idx]; + break; + } + EE->addGlobalMapping(F, dest); + apiFuncs[i] = F; + } + + for (unsigned i=0;icount;i++) { + const struct cli_bc *bc = &bcs->all_bcs[i]; + if (bc->state == bc_skip) + continue; + LLVMCodegen Codegen(bc, M, bcs->engine->compiledFunctions, EE, + OurFPM, apiFuncs, apiMap); + if (!Codegen.generate()) { + errs() << MODULE << "JIT codegen failed\n"; + return CL_EBYTECODE; + } + } + + for (unsigned i=0;icount;i++) { + bcs->all_bcs[i].state = bc_jit; + } + // compile all functions now, not lazily! + for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I) { + Function *Fn = &*I; + if (!Fn->isDeclaration()) + EE->getPointerToFunction(Fn); + } + delete [] apiFuncs; + } + return -1; + } catch (std::bad_alloc &badalloc) { + errs() << MODULE << badalloc.what() << "\n"; + return CL_EMEM; + } catch (...) { + errs() << MODULE << "Unexpected unknown exception occurred.\n"; + return CL_EBYTECODE; + } +} + +int bytecode_init(void) +{ + // If already initialized return + if (llvm_is_multithreaded()) + return 0; + llvm_install_error_handler(llvm_error_handler); +#ifdef CL_DEBUG + sys::PrintStackTraceOnErrorSignal(); +#else + llvm::DisablePrettyStackTrace = true; +#endif + atexit(do_shutdown); + +#ifdef CL_DEBUG + llvm::JITEmitDebugInfo = true; +#else + llvm::JITEmitDebugInfo = false; +#endif + llvm::DwarfExceptionHandling = false; + llvm_start_multithreaded(); + + // If we have a native target, initialize it to ensure it is linked in and + // usable by the JIT. + InitializeNativeTarget(); + return 0; +} + +// Called once when loading a new set of BC files +int cli_bytecode_init_jit(struct cli_all_bc *bcs) +{ + //TODO: if !llvm_is_multi... + bcs->engine = new(std::nothrow) struct cli_bcengine; + if (!bcs->engine) + return CL_EMEM; + bcs->engine->EE = 0; + return 0; +} + +int cli_bytecode_done_jit(struct cli_all_bc *bcs) +{ + if (bcs->engine) { + if (bcs->engine->EE) + delete bcs->engine->EE; + delete bcs->engine; + bcs->engine = 0; + } + return 0; +} + +void cli_bytecode_debug(int argc, char **argv) +{ + cl::ParseCommandLineOptions(argc, argv); +} + +struct lines { + MemoryBuffer *buffer; + std::vector lines; +}; + +static struct lineprinter { + StringMap files; +} LinePrinter; + +void cli_bytecode_debug_printsrc(const struct cli_bc_ctx *ctx) +{ + if (!ctx->file || !ctx->directory || !ctx->line) { + errs() << (ctx->directory ? "d":"null") << ":" << (ctx->file ? "f" : "null")<< ":" << ctx->line << "\n"; + return; + } + // acquire a mutex here + sys::Mutex mtx(false); + sys::SmartScopedLock lock(mtx); + + std::string path = std::string(ctx->directory) + "/" + std::string(ctx->file); + StringMap::iterator I = LinePrinter.files.find(path); + struct lines *lines; + if (I == LinePrinter.files.end()) { + lines = new struct lines; + std::string ErrorMessage; + lines->buffer = MemoryBuffer::getFile(path, &ErrorMessage); + if (!lines->buffer) { + errs() << "Unable to open file '" << path << "'\n"; + return ; + } + LinePrinter.files[path] = lines; + } else { + lines = I->getValue(); + } + const char *linestart; + while (lines->lines.size() <= ctx->line+1) { + const char *p; + if (lines->lines.empty()) { + p = lines->buffer->getBufferStart(); + lines->lines.push_back(p); + } else { + p = lines->lines.back(); + if (p == lines->buffer->getBufferEnd()) + break; + p = strchr(p, '\n'); + if (!p) { + p = lines->buffer->getBufferEnd(); + lines->lines.push_back(p); + } else + lines->lines.push_back(p+1); + } + } + if (ctx->line >= lines->lines.size()) { + errs() << "Line number " << ctx->line << "out of file\n"; + return; + } + assert(ctx->line < lines->lines.size()); + SMDiagnostic diag(ctx->file, ctx->line ? ctx->line : -1, + ctx->col ? ctx->col-1 : -1, + "", std::string(lines->lines[ctx->line-1], lines->lines[ctx->line]-1)); + diag.Print("[trace]", errs()); +} + +int have_clamjit=1; diff --git a/libclamav/c++/clamavcxx-config.h.in b/libclamav/c++/clamavcxx-config.h.in new file mode 100644 index 000000000..a6b475aa3 --- /dev/null +++ b/libclamav/c++/clamavcxx-config.h.in @@ -0,0 +1,56 @@ +/* clamavcxx-config.h.in. Generated from configure.ac by autoheader. */ + +/* Define to 1 if you have the header file. */ +#undef HAVE_DLFCN_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_INTTYPES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_MEMORY_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDINT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDLIB_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRINGS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRING_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_STAT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TYPES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_UNISTD_H + +/* Define to the sub-directory in which libtool stores uninstalled libraries. + */ +#undef LT_OBJDIR + +/* Define to the address where bug reports for this package should be sent. */ +#undef PACKAGE_BUGREPORT + +/* Define to the full name of this package. */ +#undef PACKAGE_NAME + +/* Define to the full name and version of this package. */ +#undef PACKAGE_STRING + +/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME + +/* Define to the home page for this package. */ +#undef PACKAGE_URL + +/* Define to the version of this package. */ +#undef PACKAGE_VERSION + +/* Define to 1 if you have the ANSI C header files. */ +#undef STDC_HEADERS diff --git a/libclamav/c++/config/config.guess b/libclamav/c++/config/config.guess new file mode 100755 index 000000000..e3a2116a7 --- /dev/null +++ b/libclamav/c++/config/config.guess @@ -0,0 +1,1533 @@ +#! /bin/sh +# Attempt to guess a canonical system name. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 +# Free Software Foundation, Inc. + +timestamp='2009-06-10' + +# This file is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA +# 02110-1301, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + + +# Originally written by Per Bothner . +# Please send patches to . Submit a context +# diff and a properly formatted ChangeLog entry. +# +# This script attempts to guess a canonical system name similar to +# config.sub. If it succeeds, it prints the system name on stdout, and +# exits with 0. Otherwise, it exits with 1. +# +# The plan is that this can be called by configure scripts if you +# don't specify an explicit build system type. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] + +Output the configuration name of the system \`$me' is run on. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.guess ($timestamp) + +Originally written by Per Bothner. +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, +2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" >&2 + exit 1 ;; + * ) + break ;; + esac +done + +if test $# != 0; then + echo "$me: too many arguments$help" >&2 + exit 1 +fi + +trap 'exit 1' 1 2 15 + +# CC_FOR_BUILD -- compiler used by this script. Note that the use of a +# compiler to aid in system detection is discouraged as it requires +# temporary files to be created and, as you can see below, it is a +# headache to deal with in a portable fashion. + +# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still +# use `HOST_CC' if defined, but it is deprecated. + +# Portable tmp directory creation inspired by the Autoconf team. + +set_cc_for_build=' +trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; +trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; +: ${TMPDIR=/tmp} ; + { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || + { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || + { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || + { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; +dummy=$tmp/dummy ; +tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; +case $CC_FOR_BUILD,$HOST_CC,$CC in + ,,) echo "int x;" > $dummy.c ; + for c in cc gcc c89 c99 ; do + if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then + CC_FOR_BUILD="$c"; break ; + fi ; + done ; + if test x"$CC_FOR_BUILD" = x ; then + CC_FOR_BUILD=no_compiler_found ; + fi + ;; + ,,*) CC_FOR_BUILD=$CC ;; + ,*,*) CC_FOR_BUILD=$HOST_CC ;; +esac ; set_cc_for_build= ;' + +# This is needed to find uname on a Pyramid OSx when run in the BSD universe. +# (ghazi@noc.rutgers.edu 1994-08-24) +if (test -f /.attbin/uname) >/dev/null 2>&1 ; then + PATH=$PATH:/.attbin ; export PATH +fi + +UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown +UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown +UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown +UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown + +# Note: order is significant - the case branches are not exclusive. + +case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in + *:NetBSD:*:*) + # NetBSD (nbsd) targets should (where applicable) match one or + # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*, + # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently + # switched to ELF, *-*-netbsd* would select the old + # object file format. This provides both forward + # compatibility and a consistent mechanism for selecting the + # object file format. + # + # Note: NetBSD doesn't particularly care about the vendor + # portion of the name. We always set it to "unknown". + sysctl="sysctl -n hw.machine_arch" + UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ + /usr/sbin/$sysctl 2>/dev/null || echo unknown)` + case "${UNAME_MACHINE_ARCH}" in + armeb) machine=armeb-unknown ;; + arm*) machine=arm-unknown ;; + sh3el) machine=shl-unknown ;; + sh3eb) machine=sh-unknown ;; + sh5el) machine=sh5le-unknown ;; + *) machine=${UNAME_MACHINE_ARCH}-unknown ;; + esac + # The Operating System including object format, if it has switched + # to ELF recently, or will in the future. + case "${UNAME_MACHINE_ARCH}" in + arm*|i386|m68k|ns32k|sh3*|sparc|vax) + eval $set_cc_for_build + if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ELF__ + then + # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). + # Return netbsd for either. FIX? + os=netbsd + else + os=netbsdelf + fi + ;; + *) + os=netbsd + ;; + esac + # The OS release + # Debian GNU/NetBSD machines have a different userland, and + # thus, need a distinct triplet. However, they do not need + # kernel version information, so it can be replaced with a + # suitable tag, in the style of linux-gnu. + case "${UNAME_VERSION}" in + Debian*) + release='-gnu' + ;; + *) + release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + ;; + esac + # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: + # contains redundant information, the shorter form: + # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. + echo "${machine}-${os}${release}" + exit ;; + *:OpenBSD:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` + echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} + exit ;; + *:ekkoBSD:*:*) + echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} + exit ;; + *:SolidBSD:*:*) + echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} + exit ;; + macppc:MirBSD:*:*) + echo powerpc-unknown-mirbsd${UNAME_RELEASE} + exit ;; + *:MirBSD:*:*) + echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} + exit ;; + alpha:OSF1:*:*) + case $UNAME_RELEASE in + *4.0) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` + ;; + *5.*) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` + ;; + esac + # According to Compaq, /usr/sbin/psrinfo has been available on + # OSF/1 and Tru64 systems produced since 1995. I hope that + # covers most systems running today. This code pipes the CPU + # types through head -n 1, so we only detect the type of CPU 0. + ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` + case "$ALPHA_CPU_TYPE" in + "EV4 (21064)") + UNAME_MACHINE="alpha" ;; + "EV4.5 (21064)") + UNAME_MACHINE="alpha" ;; + "LCA4 (21066/21068)") + UNAME_MACHINE="alpha" ;; + "EV5 (21164)") + UNAME_MACHINE="alphaev5" ;; + "EV5.6 (21164A)") + UNAME_MACHINE="alphaev56" ;; + "EV5.6 (21164PC)") + UNAME_MACHINE="alphapca56" ;; + "EV5.7 (21164PC)") + UNAME_MACHINE="alphapca57" ;; + "EV6 (21264)") + UNAME_MACHINE="alphaev6" ;; + "EV6.7 (21264A)") + UNAME_MACHINE="alphaev67" ;; + "EV6.8CB (21264C)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8AL (21264B)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8CX (21264D)") + UNAME_MACHINE="alphaev68" ;; + "EV6.9A (21264/EV69A)") + UNAME_MACHINE="alphaev69" ;; + "EV7 (21364)") + UNAME_MACHINE="alphaev7" ;; + "EV7.9 (21364A)") + UNAME_MACHINE="alphaev79" ;; + esac + # A Pn.n version is a patched version. + # A Vn.n version is a released version. + # A Tn.n version is a released field test version. + # A Xn.n version is an unreleased experimental baselevel. + # 1.2 uses "1.2" for uname -r. + echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + exit ;; + Alpha\ *:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # Should we change UNAME_MACHINE based on the output of uname instead + # of the specific Alpha model? + echo alpha-pc-interix + exit ;; + 21064:Windows_NT:50:3) + echo alpha-dec-winnt3.5 + exit ;; + Amiga*:UNIX_System_V:4.0:*) + echo m68k-unknown-sysv4 + exit ;; + *:[Aa]miga[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-amigaos + exit ;; + *:[Mm]orph[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-morphos + exit ;; + *:OS/390:*:*) + echo i370-ibm-openedition + exit ;; + *:z/VM:*:*) + echo s390-ibm-zvmoe + exit ;; + *:OS400:*:*) + echo powerpc-ibm-os400 + exit ;; + arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) + echo arm-acorn-riscix${UNAME_RELEASE} + exit ;; + arm:riscos:*:*|arm:RISCOS:*:*) + echo arm-unknown-riscos + exit ;; + SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) + echo hppa1.1-hitachi-hiuxmpp + exit ;; + Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) + # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. + if test "`(/bin/universe) 2>/dev/null`" = att ; then + echo pyramid-pyramid-sysv3 + else + echo pyramid-pyramid-bsd + fi + exit ;; + NILE*:*:*:dcosx) + echo pyramid-pyramid-svr4 + exit ;; + DRS?6000:unix:4.0:6*) + echo sparc-icl-nx6 + exit ;; + DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) + case `/usr/bin/uname -p` in + sparc) echo sparc-icl-nx7; exit ;; + esac ;; + s390x:SunOS:*:*) + echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4H:SunOS:5.*:*) + echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) + echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) + eval $set_cc_for_build + SUN_ARCH="i386" + # If there is a compiler, see if it is configured for 64-bit objects. + # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. + # This test works for both compilers. + if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then + if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + SUN_ARCH="x86_64" + fi + fi + echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:6*:*) + # According to config.sub, this is the proper way to canonicalize + # SunOS6. Hard to guess exactly what SunOS6 will be like, but + # it's likely to be more like Solaris than SunOS4. + echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:*:*) + case "`/usr/bin/arch -k`" in + Series*|S4*) + UNAME_RELEASE=`uname -v` + ;; + esac + # Japanese Language versions have a version number like `4.1.3-JL'. + echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` + exit ;; + sun3*:SunOS:*:*) + echo m68k-sun-sunos${UNAME_RELEASE} + exit ;; + sun*:*:4.2BSD:*) + UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` + test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 + case "`/bin/arch`" in + sun3) + echo m68k-sun-sunos${UNAME_RELEASE} + ;; + sun4) + echo sparc-sun-sunos${UNAME_RELEASE} + ;; + esac + exit ;; + aushp:SunOS:*:*) + echo sparc-auspex-sunos${UNAME_RELEASE} + exit ;; + # The situation for MiNT is a little confusing. The machine name + # can be virtually everything (everything which is not + # "atarist" or "atariste" at least should have a processor + # > m68000). The system name ranges from "MiNT" over "FreeMiNT" + # to the lowercase version "mint" (or "freemint"). Finally + # the system name "TOS" denotes a system which is actually not + # MiNT. But MiNT is downward compatible to TOS, so this should + # be no problem. + atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) + echo m68k-milan-mint${UNAME_RELEASE} + exit ;; + hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) + echo m68k-hades-mint${UNAME_RELEASE} + exit ;; + *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) + echo m68k-unknown-mint${UNAME_RELEASE} + exit ;; + m68k:machten:*:*) + echo m68k-apple-machten${UNAME_RELEASE} + exit ;; + powerpc:machten:*:*) + echo powerpc-apple-machten${UNAME_RELEASE} + exit ;; + RISC*:Mach:*:*) + echo mips-dec-mach_bsd4.3 + exit ;; + RISC*:ULTRIX:*:*) + echo mips-dec-ultrix${UNAME_RELEASE} + exit ;; + VAX*:ULTRIX*:*:*) + echo vax-dec-ultrix${UNAME_RELEASE} + exit ;; + 2020:CLIX:*:* | 2430:CLIX:*:*) + echo clipper-intergraph-clix${UNAME_RELEASE} + exit ;; + mips:*:*:UMIPS | mips:*:*:RISCos) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c +#ifdef __cplusplus +#include /* for printf() prototype */ + int main (int argc, char *argv[]) { +#else + int main (argc, argv) int argc; char *argv[]; { +#endif + #if defined (host_mips) && defined (MIPSEB) + #if defined (SYSTYPE_SYSV) + printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_SVR4) + printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) + printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); + #endif + #endif + exit (-1); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && + dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && + SYSTEM_NAME=`$dummy $dummyarg` && + { echo "$SYSTEM_NAME"; exit; } + echo mips-mips-riscos${UNAME_RELEASE} + exit ;; + Motorola:PowerMAX_OS:*:*) + echo powerpc-motorola-powermax + exit ;; + Motorola:*:4.3:PL8-*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:Power_UNIX:*:*) + echo powerpc-harris-powerunix + exit ;; + m88k:CX/UX:7*:*) + echo m88k-harris-cxux7 + exit ;; + m88k:*:4*:R4*) + echo m88k-motorola-sysv4 + exit ;; + m88k:*:3*:R3*) + echo m88k-motorola-sysv3 + exit ;; + AViiON:dgux:*:*) + # DG/UX returns AViiON for all architectures + UNAME_PROCESSOR=`/usr/bin/uname -p` + if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] + then + if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ + [ ${TARGET_BINARY_INTERFACE}x = x ] + then + echo m88k-dg-dgux${UNAME_RELEASE} + else + echo m88k-dg-dguxbcs${UNAME_RELEASE} + fi + else + echo i586-dg-dgux${UNAME_RELEASE} + fi + exit ;; + M88*:DolphinOS:*:*) # DolphinOS (SVR3) + echo m88k-dolphin-sysv3 + exit ;; + M88*:*:R3*:*) + # Delta 88k system running SVR3 + echo m88k-motorola-sysv3 + exit ;; + XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) + echo m88k-tektronix-sysv3 + exit ;; + Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) + echo m68k-tektronix-bsd + exit ;; + *:IRIX*:*:*) + echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` + exit ;; + ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. + echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id + exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' + i*86:AIX:*:*) + echo i386-ibm-aix + exit ;; + ia64:AIX:*:*) + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} + exit ;; + *:AIX:2:3) + if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + + main() + { + if (!__power_pc()) + exit(1); + puts("powerpc-ibm-aix3.2.5"); + exit(0); + } +EOF + if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` + then + echo "$SYSTEM_NAME" + else + echo rs6000-ibm-aix3.2.5 + fi + elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then + echo rs6000-ibm-aix3.2.4 + else + echo rs6000-ibm-aix3.2 + fi + exit ;; + *:AIX:*:[456]) + IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` + if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then + IBM_ARCH=rs6000 + else + IBM_ARCH=powerpc + fi + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${IBM_ARCH}-ibm-aix${IBM_REV} + exit ;; + *:AIX:*:*) + echo rs6000-ibm-aix + exit ;; + ibmrt:4.4BSD:*|romp-ibm:BSD:*) + echo romp-ibm-bsd4.4 + exit ;; + ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and + echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to + exit ;; # report: romp-ibm BSD 4.3 + *:BOSX:*:*) + echo rs6000-bull-bosx + exit ;; + DPX/2?00:B.O.S.:*:*) + echo m68k-bull-sysv3 + exit ;; + 9000/[34]??:4.3bsd:1.*:*) + echo m68k-hp-bsd + exit ;; + hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) + echo m68k-hp-bsd4.4 + exit ;; + 9000/[34678]??:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + case "${UNAME_MACHINE}" in + 9000/31? ) HP_ARCH=m68000 ;; + 9000/[34]?? ) HP_ARCH=m68k ;; + 9000/[678][0-9][0-9]) + if [ -x /usr/bin/getconf ]; then + sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` + sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` + case "${sc_cpu_version}" in + 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 + 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 + 532) # CPU_PA_RISC2_0 + case "${sc_kernel_bits}" in + 32) HP_ARCH="hppa2.0n" ;; + 64) HP_ARCH="hppa2.0w" ;; + '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 + esac ;; + esac + fi + if [ "${HP_ARCH}" = "" ]; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + + #define _HPUX_SOURCE + #include + #include + + int main () + { + #if defined(_SC_KERNEL_BITS) + long bits = sysconf(_SC_KERNEL_BITS); + #endif + long cpu = sysconf (_SC_CPU_VERSION); + + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1"); break; + case CPU_PA_RISC2_0: + #if defined(_SC_KERNEL_BITS) + switch (bits) + { + case 64: puts ("hppa2.0w"); break; + case 32: puts ("hppa2.0n"); break; + default: puts ("hppa2.0"); break; + } break; + #else /* !defined(_SC_KERNEL_BITS) */ + puts ("hppa2.0"); break; + #endif + default: puts ("hppa1.0"); break; + } + exit (0); + } +EOF + (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` + test -z "$HP_ARCH" && HP_ARCH=hppa + fi ;; + esac + if [ ${HP_ARCH} = "hppa2.0w" ] + then + eval $set_cc_for_build + + # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating + # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler + # generating 64-bit code. GNU and HP use different nomenclature: + # + # $ CC_FOR_BUILD=cc ./config.guess + # => hppa2.0w-hp-hpux11.23 + # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess + # => hppa64-hp-hpux11.23 + + if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | + grep -q __LP64__ + then + HP_ARCH="hppa2.0w" + else + HP_ARCH="hppa64" + fi + fi + echo ${HP_ARCH}-hp-hpux${HPUX_REV} + exit ;; + ia64:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + echo ia64-hp-hpux${HPUX_REV} + exit ;; + 3050*:HI-UX:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + int + main () + { + long cpu = sysconf (_SC_CPU_VERSION); + /* The order matters, because CPU_IS_HP_MC68K erroneously returns + true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct + results, however. */ + if (CPU_IS_PA_RISC (cpu)) + { + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; + case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; + default: puts ("hppa-hitachi-hiuxwe2"); break; + } + } + else if (CPU_IS_HP_MC68K (cpu)) + puts ("m68k-hitachi-hiuxwe2"); + else puts ("unknown-hitachi-hiuxwe2"); + exit (0); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } + echo unknown-hitachi-hiuxwe2 + exit ;; + 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) + echo hppa1.1-hp-bsd + exit ;; + 9000/8??:4.3bsd:*:*) + echo hppa1.0-hp-bsd + exit ;; + *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) + echo hppa1.0-hp-mpeix + exit ;; + hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) + echo hppa1.1-hp-osf + exit ;; + hp8??:OSF1:*:*) + echo hppa1.0-hp-osf + exit ;; + i*86:OSF1:*:*) + if [ -x /usr/sbin/sysversion ] ; then + echo ${UNAME_MACHINE}-unknown-osf1mk + else + echo ${UNAME_MACHINE}-unknown-osf1 + fi + exit ;; + parisc*:Lites*:*:*) + echo hppa1.1-hp-lites + exit ;; + C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) + echo c1-convex-bsd + exit ;; + C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit ;; + C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) + echo c34-convex-bsd + exit ;; + C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) + echo c38-convex-bsd + exit ;; + C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) + echo c4-convex-bsd + exit ;; + CRAY*Y-MP:*:*:*) + echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*[A-Z]90:*:*:*) + echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ + | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ + -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ + -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*TS:*:*:*) + echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*T3E:*:*:*) + echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*SV1:*:*:*) + echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + *:UNICOS/mp:*:*) + echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) + FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` + echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + 5000:UNIX_System_V:4.*:*) + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` + echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) + echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} + exit ;; + sparc*:BSD/OS:*:*) + echo sparc-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:BSD/OS:*:*) + echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:FreeBSD:*:*) + case ${UNAME_MACHINE} in + pc98) + echo i386-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + amd64) + echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + *) + echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + esac + exit ;; + i*:CYGWIN*:*) + echo ${UNAME_MACHINE}-pc-cygwin + exit ;; + *:MINGW*:*) + echo ${UNAME_MACHINE}-pc-mingw32 + exit ;; + i*:windows32*:*) + # uname -m includes "-pc" on this system. + echo ${UNAME_MACHINE}-mingw32 + exit ;; + i*:PW*:*) + echo ${UNAME_MACHINE}-pc-pw32 + exit ;; + *:Interix*:[3456]*) + case ${UNAME_MACHINE} in + x86) + echo i586-pc-interix${UNAME_RELEASE} + exit ;; + EM64T | authenticamd | genuineintel) + echo x86_64-unknown-interix${UNAME_RELEASE} + exit ;; + IA64) + echo ia64-unknown-interix${UNAME_RELEASE} + exit ;; + esac ;; + [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) + echo i${UNAME_MACHINE}-pc-mks + exit ;; + 8664:Windows_NT:*) + echo x86_64-pc-mks + exit ;; + i*:Windows_NT*:* | Pentium*:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we + # UNAME_MACHINE based on the output of uname instead of i386? + echo i586-pc-interix + exit ;; + i*:UWIN*:*) + echo ${UNAME_MACHINE}-pc-uwin + exit ;; + amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) + echo x86_64-unknown-cygwin + exit ;; + p*:CYGWIN*:*) + echo powerpcle-unknown-cygwin + exit ;; + prep*:SunOS:5.*:*) + echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + *:GNU:*:*) + # the GNU system + echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` + exit ;; + *:GNU/*:*:*) + # other systems with GNU libc and userland + echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu + exit ;; + i*86:Minix:*:*) + echo ${UNAME_MACHINE}-pc-minix + exit ;; + arm*:Linux:*:*) + eval $set_cc_for_build + if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_EABI__ + then + echo ${UNAME_MACHINE}-unknown-linux-gnu + else + echo ${UNAME_MACHINE}-unknown-linux-gnueabi + fi + exit ;; + avr32*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + cris:Linux:*:*) + echo cris-axis-linux-gnu + exit ;; + crisv32:Linux:*:*) + echo crisv32-axis-linux-gnu + exit ;; + frv:Linux:*:*) + echo frv-unknown-linux-gnu + exit ;; + ia64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + m32r*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + m68*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + mips:Linux:*:* | mips64:Linux:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #undef CPU + #undef ${UNAME_MACHINE} + #undef ${UNAME_MACHINE}el + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=${UNAME_MACHINE}el + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=${UNAME_MACHINE} + #else + CPU= + #endif + #endif +EOF + eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n ' + /^CPU/{ + s: ::g + p + }'`" + test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } + ;; + or32:Linux:*:*) + echo or32-unknown-linux-gnu + exit ;; + ppc:Linux:*:*) + echo powerpc-unknown-linux-gnu + exit ;; + ppc64:Linux:*:*) + echo powerpc64-unknown-linux-gnu + exit ;; + alpha:Linux:*:*) + case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in + EV5) UNAME_MACHINE=alphaev5 ;; + EV56) UNAME_MACHINE=alphaev56 ;; + PCA56) UNAME_MACHINE=alphapca56 ;; + PCA57) UNAME_MACHINE=alphapca56 ;; + EV6) UNAME_MACHINE=alphaev6 ;; + EV67) UNAME_MACHINE=alphaev67 ;; + EV68*) UNAME_MACHINE=alphaev68 ;; + esac + objdump --private-headers /bin/sh | grep -q ld.so.1 + if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi + echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} + exit ;; + padre:Linux:*:*) + echo sparc-unknown-linux-gnu + exit ;; + parisc:Linux:*:* | hppa:Linux:*:*) + # Look for CPU level + case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in + PA7*) echo hppa1.1-unknown-linux-gnu ;; + PA8*) echo hppa2.0-unknown-linux-gnu ;; + *) echo hppa-unknown-linux-gnu ;; + esac + exit ;; + parisc64:Linux:*:* | hppa64:Linux:*:*) + echo hppa64-unknown-linux-gnu + exit ;; + s390:Linux:*:* | s390x:Linux:*:*) + echo ${UNAME_MACHINE}-ibm-linux + exit ;; + sh64*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + sh*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + sparc:Linux:*:* | sparc64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + vax:Linux:*:*) + echo ${UNAME_MACHINE}-dec-linux-gnu + exit ;; + x86_64:Linux:*:*) + echo x86_64-unknown-linux-gnu + exit ;; + xtensa*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + i*86:Linux:*:*) + # The BFD linker knows what the default object file format is, so + # first see if it will tell us. cd to the root directory to prevent + # problems with other programs or directories called `ld' in the path. + # Set LC_ALL=C to ensure ld outputs messages in English. + ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \ + | sed -ne '/supported targets:/!d + s/[ ][ ]*/ /g + s/.*supported targets: *// + s/ .*// + p'` + case "$ld_supported_targets" in + elf32-i386) + TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu" + ;; + esac + # Determine whether the default compiler is a.out or elf + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + #ifdef __ELF__ + # ifdef __GLIBC__ + # if __GLIBC__ >= 2 + LIBC=gnu + # else + LIBC=gnulibc1 + # endif + # else + LIBC=gnulibc1 + # endif + #else + #if defined(__INTEL_COMPILER) || defined(__PGI) || defined(__SUNPRO_C) || defined(__SUNPRO_CC) + LIBC=gnu + #else + LIBC=gnuaout + #endif + #endif + #ifdef __dietlibc__ + LIBC=dietlibc + #endif +EOF + eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n ' + /^LIBC/{ + s: ::g + p + }'`" + test x"${LIBC}" != x && { + echo "${UNAME_MACHINE}-pc-linux-${LIBC}" + exit + } + test x"${TENTATIVE}" != x && { echo "${TENTATIVE}"; exit; } + ;; + i*86:DYNIX/ptx:4*:*) + # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. + # earlier versions are messed up and put the nodename in both + # sysname and nodename. + echo i386-sequent-sysv4 + exit ;; + i*86:UNIX_SV:4.2MP:2.*) + # Unixware is an offshoot of SVR4, but it has its own version + # number series starting with 2... + # I am not positive that other SVR4 systems won't match this, + # I just have to hope. -- rms. + # Use sysv4.2uw... so that sysv4* matches it. + echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} + exit ;; + i*86:OS/2:*:*) + # If we were able to find `uname', then EMX Unix compatibility + # is probably installed. + echo ${UNAME_MACHINE}-pc-os2-emx + exit ;; + i*86:XTS-300:*:STOP) + echo ${UNAME_MACHINE}-unknown-stop + exit ;; + i*86:atheos:*:*) + echo ${UNAME_MACHINE}-unknown-atheos + exit ;; + i*86:syllable:*:*) + echo ${UNAME_MACHINE}-pc-syllable + exit ;; + i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) + echo i386-unknown-lynxos${UNAME_RELEASE} + exit ;; + i*86:*DOS:*:*) + echo ${UNAME_MACHINE}-pc-msdosdjgpp + exit ;; + i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) + UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` + if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then + echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} + else + echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} + fi + exit ;; + i*86:*:5:[678]*) + # UnixWare 7.x, OpenUNIX and OpenServer 6. + case `/bin/uname -X | grep "^Machine"` in + *486*) UNAME_MACHINE=i486 ;; + *Pentium) UNAME_MACHINE=i586 ;; + *Pent*|*Celeron) UNAME_MACHINE=i686 ;; + esac + echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} + exit ;; + i*86:*:3.2:*) + if test -f /usr/options/cb.name; then + UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then + UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` + (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 + (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ + && UNAME_MACHINE=i586 + (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ + && UNAME_MACHINE=i686 + (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ + && UNAME_MACHINE=i686 + echo ${UNAME_MACHINE}-pc-sco$UNAME_REL + else + echo ${UNAME_MACHINE}-pc-sysv32 + fi + exit ;; + pc:*:*:*) + # Left here for compatibility: + # uname -m prints for DJGPP always 'pc', but it prints nothing about + # the processor, so we play safe by assuming i586. + # Note: whatever this is, it MUST be the same as what config.sub + # prints for the "djgpp" host, or else GDB configury will decide that + # this is a cross-build. + echo i586-pc-msdosdjgpp + exit ;; + Intel:Mach:3*:*) + echo i386-pc-mach3 + exit ;; + paragon:*:*:*) + echo i860-intel-osf1 + exit ;; + i860:*:4.*:*) # i860-SVR4 + if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then + echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 + else # Add other i860-SVR4 vendors below as they are discovered. + echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 + fi + exit ;; + mini*:CTIX:SYS*5:*) + # "miniframe" + echo m68010-convergent-sysv + exit ;; + mc68k:UNIX:SYSTEM5:3.51m) + echo m68k-convergent-sysv + exit ;; + M680?0:D-NIX:5.3:*) + echo m68k-diab-dnix + exit ;; + M68*:*:R3V[5678]*:*) + test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; + 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) + OS_REL='' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4; exit; } ;; + NCR*:*:4.2:* | MPRAS*:*:4.2:*) + OS_REL='.3' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) + echo m68k-unknown-lynxos${UNAME_RELEASE} + exit ;; + mc68030:UNIX_System_V:4.*:*) + echo m68k-atari-sysv4 + exit ;; + TSUNAMI:LynxOS:2.*:*) + echo sparc-unknown-lynxos${UNAME_RELEASE} + exit ;; + rs6000:LynxOS:2.*:*) + echo rs6000-unknown-lynxos${UNAME_RELEASE} + exit ;; + PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) + echo powerpc-unknown-lynxos${UNAME_RELEASE} + exit ;; + SM[BE]S:UNIX_SV:*:*) + echo mips-dde-sysv${UNAME_RELEASE} + exit ;; + RM*:ReliantUNIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + RM*:SINIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + *:SINIX-*:*:*) + if uname -p 2>/dev/null >/dev/null ; then + UNAME_MACHINE=`(uname -p) 2>/dev/null` + echo ${UNAME_MACHINE}-sni-sysv4 + else + echo ns32k-sni-sysv + fi + exit ;; + PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort + # says + echo i586-unisys-sysv4 + exit ;; + *:UNIX_System_V:4*:FTX*) + # From Gerald Hewes . + # How about differentiating between stratus architectures? -djm + echo hppa1.1-stratus-sysv4 + exit ;; + *:*:*:FTX*) + # From seanf@swdc.stratus.com. + echo i860-stratus-sysv4 + exit ;; + i*86:VOS:*:*) + # From Paul.Green@stratus.com. + echo ${UNAME_MACHINE}-stratus-vos + exit ;; + *:VOS:*:*) + # From Paul.Green@stratus.com. + echo hppa1.1-stratus-vos + exit ;; + mc68*:A/UX:*:*) + echo m68k-apple-aux${UNAME_RELEASE} + exit ;; + news*:NEWS-OS:6*:*) + echo mips-sony-newsos6 + exit ;; + R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) + if [ -d /usr/nec ]; then + echo mips-nec-sysv${UNAME_RELEASE} + else + echo mips-unknown-sysv${UNAME_RELEASE} + fi + exit ;; + BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. + echo powerpc-be-beos + exit ;; + BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. + echo powerpc-apple-beos + exit ;; + BePC:BeOS:*:*) # BeOS running on Intel PC compatible. + echo i586-pc-beos + exit ;; + BePC:Haiku:*:*) # Haiku running on Intel PC compatible. + echo i586-pc-haiku + exit ;; + SX-4:SUPER-UX:*:*) + echo sx4-nec-superux${UNAME_RELEASE} + exit ;; + SX-5:SUPER-UX:*:*) + echo sx5-nec-superux${UNAME_RELEASE} + exit ;; + SX-6:SUPER-UX:*:*) + echo sx6-nec-superux${UNAME_RELEASE} + exit ;; + SX-7:SUPER-UX:*:*) + echo sx7-nec-superux${UNAME_RELEASE} + exit ;; + SX-8:SUPER-UX:*:*) + echo sx8-nec-superux${UNAME_RELEASE} + exit ;; + SX-8R:SUPER-UX:*:*) + echo sx8r-nec-superux${UNAME_RELEASE} + exit ;; + Power*:Rhapsody:*:*) + echo powerpc-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Rhapsody:*:*) + echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Darwin:*:*) + UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown + case $UNAME_PROCESSOR in + unknown) UNAME_PROCESSOR=powerpc ;; + esac + echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} + exit ;; + *:procnto*:*:* | *:QNX:[0123456789]*:*) + UNAME_PROCESSOR=`uname -p` + if test "$UNAME_PROCESSOR" = "x86"; then + UNAME_PROCESSOR=i386 + UNAME_MACHINE=pc + fi + echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} + exit ;; + *:QNX:*:4*) + echo i386-pc-qnx + exit ;; + NSE-?:NONSTOP_KERNEL:*:*) + echo nse-tandem-nsk${UNAME_RELEASE} + exit ;; + NSR-?:NONSTOP_KERNEL:*:*) + echo nsr-tandem-nsk${UNAME_RELEASE} + exit ;; + *:NonStop-UX:*:*) + echo mips-compaq-nonstopux + exit ;; + BS2000:POSIX*:*:*) + echo bs2000-siemens-sysv + exit ;; + DS/*:UNIX_System_V:*:*) + echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} + exit ;; + *:Plan9:*:*) + # "uname -m" is not consistent, so use $cputype instead. 386 + # is converted to i386 for consistency with other x86 + # operating systems. + if test "$cputype" = "386"; then + UNAME_MACHINE=i386 + else + UNAME_MACHINE="$cputype" + fi + echo ${UNAME_MACHINE}-unknown-plan9 + exit ;; + *:TOPS-10:*:*) + echo pdp10-unknown-tops10 + exit ;; + *:TENEX:*:*) + echo pdp10-unknown-tenex + exit ;; + KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) + echo pdp10-dec-tops20 + exit ;; + XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) + echo pdp10-xkl-tops20 + exit ;; + *:TOPS-20:*:*) + echo pdp10-unknown-tops20 + exit ;; + *:ITS:*:*) + echo pdp10-unknown-its + exit ;; + SEI:*:*:SEIUX) + echo mips-sei-seiux${UNAME_RELEASE} + exit ;; + *:DragonFly:*:*) + echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` + exit ;; + *:*VMS:*:*) + UNAME_MACHINE=`(uname -p) 2>/dev/null` + case "${UNAME_MACHINE}" in + A*) echo alpha-dec-vms ; exit ;; + I*) echo ia64-dec-vms ; exit ;; + V*) echo vax-dec-vms ; exit ;; + esac ;; + *:XENIX:*:SysV) + echo i386-pc-xenix + exit ;; + i*86:skyos:*:*) + echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' + exit ;; + i*86:rdos:*:*) + echo ${UNAME_MACHINE}-pc-rdos + exit ;; + i*86:AROS:*:*) + echo ${UNAME_MACHINE}-pc-aros + exit ;; +esac + +#echo '(No uname command or uname output not recognized.)' 1>&2 +#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 + +eval $set_cc_for_build +cat >$dummy.c < +# include +#endif +main () +{ +#if defined (sony) +#if defined (MIPSEB) + /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, + I don't know.... */ + printf ("mips-sony-bsd\n"); exit (0); +#else +#include + printf ("m68k-sony-newsos%s\n", +#ifdef NEWSOS4 + "4" +#else + "" +#endif + ); exit (0); +#endif +#endif + +#if defined (__arm) && defined (__acorn) && defined (__unix) + printf ("arm-acorn-riscix\n"); exit (0); +#endif + +#if defined (hp300) && !defined (hpux) + printf ("m68k-hp-bsd\n"); exit (0); +#endif + +#if defined (NeXT) +#if !defined (__ARCHITECTURE__) +#define __ARCHITECTURE__ "m68k" +#endif + int version; + version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; + if (version < 4) + printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); + else + printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); + exit (0); +#endif + +#if defined (MULTIMAX) || defined (n16) +#if defined (UMAXV) + printf ("ns32k-encore-sysv\n"); exit (0); +#else +#if defined (CMU) + printf ("ns32k-encore-mach\n"); exit (0); +#else + printf ("ns32k-encore-bsd\n"); exit (0); +#endif +#endif +#endif + +#if defined (__386BSD__) + printf ("i386-pc-bsd\n"); exit (0); +#endif + +#if defined (sequent) +#if defined (i386) + printf ("i386-sequent-dynix\n"); exit (0); +#endif +#if defined (ns32000) + printf ("ns32k-sequent-dynix\n"); exit (0); +#endif +#endif + +#if defined (_SEQUENT_) + struct utsname un; + + uname(&un); + + if (strncmp(un.version, "V2", 2) == 0) { + printf ("i386-sequent-ptx2\n"); exit (0); + } + if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ + printf ("i386-sequent-ptx1\n"); exit (0); + } + printf ("i386-sequent-ptx\n"); exit (0); + +#endif + +#if defined (vax) +# if !defined (ultrix) +# include +# if defined (BSD) +# if BSD == 43 + printf ("vax-dec-bsd4.3\n"); exit (0); +# else +# if BSD == 199006 + printf ("vax-dec-bsd4.3reno\n"); exit (0); +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# endif +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# else + printf ("vax-dec-ultrix\n"); exit (0); +# endif +#endif + +#if defined (alliant) && defined (i860) + printf ("i860-alliant-bsd\n"); exit (0); +#endif + + exit (1); +} +EOF + +$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } + +# Apollos put the system type in the environment. + +test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; } + +# Convex versions that predate uname can use getsysinfo(1) + +if [ -x /usr/convex/getsysinfo ] +then + case `getsysinfo -f cpu_type` in + c1*) + echo c1-convex-bsd + exit ;; + c2*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit ;; + c34*) + echo c34-convex-bsd + exit ;; + c38*) + echo c38-convex-bsd + exit ;; + c4*) + echo c4-convex-bsd + exit ;; + esac +fi + +cat >&2 < in order to provide the needed +information to handle your system. + +config.guess timestamp = $timestamp + +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null` + +hostinfo = `(hostinfo) 2>/dev/null` +/bin/universe = `(/bin/universe) 2>/dev/null` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` +/bin/arch = `(/bin/arch) 2>/dev/null` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` + +UNAME_MACHINE = ${UNAME_MACHINE} +UNAME_RELEASE = ${UNAME_RELEASE} +UNAME_SYSTEM = ${UNAME_SYSTEM} +UNAME_VERSION = ${UNAME_VERSION} +EOF + +exit 1 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/libclamav/c++/config/config.sub b/libclamav/c++/config/config.sub new file mode 100755 index 000000000..eb0389a69 --- /dev/null +++ b/libclamav/c++/config/config.sub @@ -0,0 +1,1693 @@ +#! /bin/sh +# Configuration validation subroutine script. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 +# Free Software Foundation, Inc. + +timestamp='2009-06-11' + +# This file is (in principle) common to ALL GNU software. +# The presence of a machine in this file suggests that SOME GNU software +# can handle that machine. It does not imply ALL GNU software can. +# +# This file is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA +# 02110-1301, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + + +# Please send patches to . Submit a context +# diff and a properly formatted ChangeLog entry. +# +# Configuration subroutine to validate and canonicalize a configuration type. +# Supply the specified configuration type as an argument. +# If it is invalid, we print an error message on stderr and exit with code 1. +# Otherwise, we print the canonical config type on stdout and succeed. + +# This file is supposed to be the same for all GNU packages +# and recognize all the CPU types, system types and aliases +# that are meaningful with *any* GNU software. +# Each package is responsible for reporting which valid configurations +# it does not support. The user should be able to distinguish +# a failure to support a valid configuration from a meaningless +# configuration. + +# The goal of this file is to map all the various variations of a given +# machine specification into a single specification in the form: +# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM +# or in some cases, the newer four-part form: +# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM +# It is wrong to echo any other type of specification. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] CPU-MFR-OPSYS + $0 [OPTION] ALIAS + +Canonicalize a configuration name. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.sub ($timestamp) + +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, +2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" + exit 1 ;; + + *local*) + # First pass through any local machine types. + echo $1 + exit ;; + + * ) + break ;; + esac +done + +case $# in + 0) echo "$me: missing argument$help" >&2 + exit 1;; + 1) ;; + *) echo "$me: too many arguments$help" >&2 + exit 1;; +esac + +# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). +# Here we must recognize all the valid KERNEL-OS combinations. +maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` +case $maybe_os in + nto-qnx* | linux-gnu* | linux-dietlibc | linux-newlib* | linux-uclibc* | \ + uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | \ + kopensolaris*-gnu* | \ + storm-chaos* | os2-emx* | rtmk-nova*) + os=-$maybe_os + basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` + ;; + *) + basic_machine=`echo $1 | sed 's/-[^-]*$//'` + if [ $basic_machine != $1 ] + then os=`echo $1 | sed 's/.*-/-/'` + else os=; fi + ;; +esac + +### Let's recognize common machines as not being operating systems so +### that things like config.sub decstation-3100 work. We also +### recognize some manufacturers as not being operating systems, so we +### can provide default operating systems below. +case $os in + -sun*os*) + # Prevent following clause from handling this invalid input. + ;; + -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ + -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ + -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ + -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ + -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ + -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ + -apple | -axis | -knuth | -cray) + os= + basic_machine=$1 + ;; + -bluegene*) + os=-cnk + ;; + -sim | -cisco | -oki | -wec | -winbond) + os= + basic_machine=$1 + ;; + -scout) + ;; + -wrs) + os=-vxworks + basic_machine=$1 + ;; + -chorusos*) + os=-chorusos + basic_machine=$1 + ;; + -chorusrdb) + os=-chorusrdb + basic_machine=$1 + ;; + -hiux*) + os=-hiuxwe2 + ;; + -sco6) + os=-sco5v6 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco5) + os=-sco3.2v5 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco4) + os=-sco3.2v4 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2.[4-9]*) + os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2v[4-9]*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco5v6*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco*) + os=-sco3.2v2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -udk*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -isc) + os=-isc2.2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -clix*) + basic_machine=clipper-intergraph + ;; + -isc*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -lynx*) + os=-lynxos + ;; + -ptx*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` + ;; + -windowsnt*) + os=`echo $os | sed -e 's/windowsnt/winnt/'` + ;; + -psos*) + os=-psos + ;; + -mint | -mint[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; +esac + +# Decode aliases for certain CPU-COMPANY combinations. +case $basic_machine in + # Recognize the basic CPU types without company name. + # Some are omitted here because they have special meanings below. + 1750a | 580 \ + | a29k \ + | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ + | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ + | am33_2.0 \ + | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \ + | bfin \ + | c4x | clipper \ + | d10v | d30v | dlx | dsp16xx \ + | fido | fr30 | frv \ + | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ + | i370 | i860 | i960 | ia64 \ + | ip2k | iq2000 \ + | lm32 \ + | m32c | m32r | m32rle | m68000 | m68k | m88k \ + | maxq | mb | microblaze | mcore | mep | metag \ + | mips | mipsbe | mipseb | mipsel | mipsle \ + | mips16 \ + | mips64 | mips64el \ + | mips64octeon | mips64octeonel \ + | mips64orion | mips64orionel \ + | mips64r5900 | mips64r5900el \ + | mips64vr | mips64vrel \ + | mips64vr4100 | mips64vr4100el \ + | mips64vr4300 | mips64vr4300el \ + | mips64vr5000 | mips64vr5000el \ + | mips64vr5900 | mips64vr5900el \ + | mipsisa32 | mipsisa32el \ + | mipsisa32r2 | mipsisa32r2el \ + | mipsisa64 | mipsisa64el \ + | mipsisa64r2 | mipsisa64r2el \ + | mipsisa64sb1 | mipsisa64sb1el \ + | mipsisa64sr71k | mipsisa64sr71kel \ + | mipstx39 | mipstx39el \ + | mn10200 | mn10300 \ + | moxie \ + | mt \ + | msp430 \ + | nios | nios2 \ + | ns16k | ns32k \ + | or32 \ + | pdp10 | pdp11 | pj | pjl \ + | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \ + | pyramid \ + | score \ + | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ + | sh64 | sh64le \ + | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ + | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ + | spu | strongarm \ + | tahoe | thumb | tic4x | tic80 | tron \ + | v850 | v850e \ + | we32k \ + | x86 | xc16x | xscale | xscalee[bl] | xstormy16 | xtensa \ + | z8k | z80) + basic_machine=$basic_machine-unknown + ;; + m6811 | m68hc11 | m6812 | m68hc12) + # Motorola 68HC11/12. + basic_machine=$basic_machine-unknown + os=-none + ;; + m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) + ;; + ms1) + basic_machine=mt-unknown + ;; + + # We use `pc' rather than `unknown' + # because (1) that's what they normally are, and + # (2) the word "unknown" tends to confuse beginning users. + i*86 | x86_64) + basic_machine=$basic_machine-pc + ;; + # Object if more than one company name word. + *-*-*) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; + # Recognize the basic CPU types with company name. + 580-* \ + | a29k-* \ + | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ + | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ + | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ + | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ + | avr-* | avr32-* \ + | bfin-* | bs2000-* \ + | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \ + | clipper-* | craynv-* | cydra-* \ + | d10v-* | d30v-* | dlx-* \ + | elxsi-* \ + | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ + | h8300-* | h8500-* \ + | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ + | i*86-* | i860-* | i960-* | ia64-* \ + | ip2k-* | iq2000-* \ + | lm32-* \ + | m32c-* | m32r-* | m32rle-* \ + | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ + | m88110-* | m88k-* | maxq-* | mcore-* | metag-* \ + | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ + | mips16-* \ + | mips64-* | mips64el-* \ + | mips64octeon-* | mips64octeonel-* \ + | mips64orion-* | mips64orionel-* \ + | mips64r5900-* | mips64r5900el-* \ + | mips64vr-* | mips64vrel-* \ + | mips64vr4100-* | mips64vr4100el-* \ + | mips64vr4300-* | mips64vr4300el-* \ + | mips64vr5000-* | mips64vr5000el-* \ + | mips64vr5900-* | mips64vr5900el-* \ + | mipsisa32-* | mipsisa32el-* \ + | mipsisa32r2-* | mipsisa32r2el-* \ + | mipsisa64-* | mipsisa64el-* \ + | mipsisa64r2-* | mipsisa64r2el-* \ + | mipsisa64sb1-* | mipsisa64sb1el-* \ + | mipsisa64sr71k-* | mipsisa64sr71kel-* \ + | mipstx39-* | mipstx39el-* \ + | mmix-* \ + | mt-* \ + | msp430-* \ + | nios-* | nios2-* \ + | none-* | np1-* | ns16k-* | ns32k-* \ + | orion-* \ + | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ + | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \ + | pyramid-* \ + | romp-* | rs6000-* \ + | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ + | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ + | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ + | sparclite-* \ + | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | strongarm-* | sv1-* | sx?-* \ + | tahoe-* | thumb-* \ + | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* | tile-* \ + | tron-* \ + | v850-* | v850e-* | vax-* \ + | we32k-* \ + | x86-* | x86_64-* | xc16x-* | xps100-* | xscale-* | xscalee[bl]-* \ + | xstormy16-* | xtensa*-* \ + | ymp-* \ + | z8k-* | z80-*) + ;; + # Recognize the basic CPU types without company name, with glob match. + xtensa*) + basic_machine=$basic_machine-unknown + ;; + # Recognize the various machine names and aliases which stand + # for a CPU type and a company and sometimes even an OS. + 386bsd) + basic_machine=i386-unknown + os=-bsd + ;; + 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) + basic_machine=m68000-att + ;; + 3b*) + basic_machine=we32k-att + ;; + a29khif) + basic_machine=a29k-amd + os=-udi + ;; + abacus) + basic_machine=abacus-unknown + ;; + adobe68k) + basic_machine=m68010-adobe + os=-scout + ;; + alliant | fx80) + basic_machine=fx80-alliant + ;; + altos | altos3068) + basic_machine=m68k-altos + ;; + am29k) + basic_machine=a29k-none + os=-bsd + ;; + amd64) + basic_machine=x86_64-pc + ;; + amd64-*) + basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + amdahl) + basic_machine=580-amdahl + os=-sysv + ;; + amiga | amiga-*) + basic_machine=m68k-unknown + ;; + amigaos | amigados) + basic_machine=m68k-unknown + os=-amigaos + ;; + amigaunix | amix) + basic_machine=m68k-unknown + os=-sysv4 + ;; + apollo68) + basic_machine=m68k-apollo + os=-sysv + ;; + apollo68bsd) + basic_machine=m68k-apollo + os=-bsd + ;; + aros) + basic_machine=i386-pc + os=-aros + ;; + aux) + basic_machine=m68k-apple + os=-aux + ;; + balance) + basic_machine=ns32k-sequent + os=-dynix + ;; + blackfin) + basic_machine=bfin-unknown + os=-linux + ;; + blackfin-*) + basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + bluegene*) + basic_machine=powerpc-ibm + os=-cnk + ;; + c90) + basic_machine=c90-cray + os=-unicos + ;; + cegcc) + basic_machine=arm-unknown + os=-cegcc + ;; + convex-c1) + basic_machine=c1-convex + os=-bsd + ;; + convex-c2) + basic_machine=c2-convex + os=-bsd + ;; + convex-c32) + basic_machine=c32-convex + os=-bsd + ;; + convex-c34) + basic_machine=c34-convex + os=-bsd + ;; + convex-c38) + basic_machine=c38-convex + os=-bsd + ;; + cray | j90) + basic_machine=j90-cray + os=-unicos + ;; + craynv) + basic_machine=craynv-cray + os=-unicosmp + ;; + cr16) + basic_machine=cr16-unknown + os=-elf + ;; + crds | unos) + basic_machine=m68k-crds + ;; + crisv32 | crisv32-* | etraxfs*) + basic_machine=crisv32-axis + ;; + cris | cris-* | etrax*) + basic_machine=cris-axis + ;; + crx) + basic_machine=crx-unknown + os=-elf + ;; + da30 | da30-*) + basic_machine=m68k-da30 + ;; + decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) + basic_machine=mips-dec + ;; + decsystem10* | dec10*) + basic_machine=pdp10-dec + os=-tops10 + ;; + decsystem20* | dec20*) + basic_machine=pdp10-dec + os=-tops20 + ;; + delta | 3300 | motorola-3300 | motorola-delta \ + | 3300-motorola | delta-motorola) + basic_machine=m68k-motorola + ;; + delta88) + basic_machine=m88k-motorola + os=-sysv3 + ;; + dicos) + basic_machine=i686-pc + os=-dicos + ;; + djgpp) + basic_machine=i586-pc + os=-msdosdjgpp + ;; + dpx20 | dpx20-*) + basic_machine=rs6000-bull + os=-bosx + ;; + dpx2* | dpx2*-bull) + basic_machine=m68k-bull + os=-sysv3 + ;; + ebmon29k) + basic_machine=a29k-amd + os=-ebmon + ;; + elxsi) + basic_machine=elxsi-elxsi + os=-bsd + ;; + encore | umax | mmax) + basic_machine=ns32k-encore + ;; + es1800 | OSE68k | ose68k | ose | OSE) + basic_machine=m68k-ericsson + os=-ose + ;; + fx2800) + basic_machine=i860-alliant + ;; + genix) + basic_machine=ns32k-ns + ;; + gmicro) + basic_machine=tron-gmicro + os=-sysv + ;; + go32) + basic_machine=i386-pc + os=-go32 + ;; + h3050r* | hiux*) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + h8300hms) + basic_machine=h8300-hitachi + os=-hms + ;; + h8300xray) + basic_machine=h8300-hitachi + os=-xray + ;; + h8500hms) + basic_machine=h8500-hitachi + os=-hms + ;; + harris) + basic_machine=m88k-harris + os=-sysv3 + ;; + hp300-*) + basic_machine=m68k-hp + ;; + hp300bsd) + basic_machine=m68k-hp + os=-bsd + ;; + hp300hpux) + basic_machine=m68k-hp + os=-hpux + ;; + hp3k9[0-9][0-9] | hp9[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k2[0-9][0-9] | hp9k31[0-9]) + basic_machine=m68000-hp + ;; + hp9k3[2-9][0-9]) + basic_machine=m68k-hp + ;; + hp9k6[0-9][0-9] | hp6[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k7[0-79][0-9] | hp7[0-79][0-9]) + basic_machine=hppa1.1-hp + ;; + hp9k78[0-9] | hp78[0-9]) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][13679] | hp8[0-9][13679]) + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][0-9] | hp8[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hppa-next) + os=-nextstep3 + ;; + hppaosf) + basic_machine=hppa1.1-hp + os=-osf + ;; + hppro) + basic_machine=hppa1.1-hp + os=-proelf + ;; + i370-ibm* | ibm*) + basic_machine=i370-ibm + ;; +# I'm not sure what "Sysv32" means. Should this be sysv3.2? + i*86v32) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv32 + ;; + i*86v4*) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv4 + ;; + i*86v) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv + ;; + i*86sol2) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-solaris2 + ;; + i386mach) + basic_machine=i386-mach + os=-mach + ;; + i386-vsta | vsta) + basic_machine=i386-unknown + os=-vsta + ;; + iris | iris4d) + basic_machine=mips-sgi + case $os in + -irix*) + ;; + *) + os=-irix4 + ;; + esac + ;; + isi68 | isi) + basic_machine=m68k-isi + os=-sysv + ;; + m68knommu) + basic_machine=m68k-unknown + os=-linux + ;; + m68knommu-*) + basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + m88k-omron*) + basic_machine=m88k-omron + ;; + magnum | m3230) + basic_machine=mips-mips + os=-sysv + ;; + merlin) + basic_machine=ns32k-utek + os=-sysv + ;; + mingw32) + basic_machine=i386-pc + os=-mingw32 + ;; + mingw32ce) + basic_machine=arm-unknown + os=-mingw32ce + ;; + miniframe) + basic_machine=m68000-convergent + ;; + *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; + mips3*-*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` + ;; + mips3*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown + ;; + monitor) + basic_machine=m68k-rom68k + os=-coff + ;; + morphos) + basic_machine=powerpc-unknown + os=-morphos + ;; + msdos) + basic_machine=i386-pc + os=-msdos + ;; + ms1-*) + basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` + ;; + mvs) + basic_machine=i370-ibm + os=-mvs + ;; + ncr3000) + basic_machine=i486-ncr + os=-sysv4 + ;; + netbsd386) + basic_machine=i386-unknown + os=-netbsd + ;; + netwinder) + basic_machine=armv4l-rebel + os=-linux + ;; + news | news700 | news800 | news900) + basic_machine=m68k-sony + os=-newsos + ;; + news1000) + basic_machine=m68030-sony + os=-newsos + ;; + news-3600 | risc-news) + basic_machine=mips-sony + os=-newsos + ;; + necv70) + basic_machine=v70-nec + os=-sysv + ;; + next | m*-next ) + basic_machine=m68k-next + case $os in + -nextstep* ) + ;; + -ns2*) + os=-nextstep2 + ;; + *) + os=-nextstep3 + ;; + esac + ;; + nh3000) + basic_machine=m68k-harris + os=-cxux + ;; + nh[45]000) + basic_machine=m88k-harris + os=-cxux + ;; + nindy960) + basic_machine=i960-intel + os=-nindy + ;; + mon960) + basic_machine=i960-intel + os=-mon960 + ;; + nonstopux) + basic_machine=mips-compaq + os=-nonstopux + ;; + np1) + basic_machine=np1-gould + ;; + nsr-tandem) + basic_machine=nsr-tandem + ;; + op50n-* | op60c-*) + basic_machine=hppa1.1-oki + os=-proelf + ;; + openrisc | openrisc-*) + basic_machine=or32-unknown + ;; + os400) + basic_machine=powerpc-ibm + os=-os400 + ;; + OSE68000 | ose68000) + basic_machine=m68000-ericsson + os=-ose + ;; + os68k) + basic_machine=m68k-none + os=-os68k + ;; + pa-hitachi) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + paragon) + basic_machine=i860-intel + os=-osf + ;; + parisc) + basic_machine=hppa-unknown + os=-linux + ;; + parisc-*) + basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + pbd) + basic_machine=sparc-tti + ;; + pbb) + basic_machine=m68k-tti + ;; + pc532 | pc532-*) + basic_machine=ns32k-pc532 + ;; + pc98) + basic_machine=i386-pc + ;; + pc98-*) + basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium | p5 | k5 | k6 | nexgen | viac3) + basic_machine=i586-pc + ;; + pentiumpro | p6 | 6x86 | athlon | athlon_*) + basic_machine=i686-pc + ;; + pentiumii | pentium2 | pentiumiii | pentium3) + basic_machine=i686-pc + ;; + pentium4) + basic_machine=i786-pc + ;; + pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) + basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumpro-* | p6-* | 6x86-* | athlon-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium4-*) + basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pn) + basic_machine=pn-gould + ;; + power) basic_machine=power-ibm + ;; + ppc) basic_machine=powerpc-unknown + ;; + ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppcle | powerpclittle | ppc-le | powerpc-little) + basic_machine=powerpcle-unknown + ;; + ppcle-* | powerpclittle-*) + basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64) basic_machine=powerpc64-unknown + ;; + ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64le | powerpc64little | ppc64-le | powerpc64-little) + basic_machine=powerpc64le-unknown + ;; + ppc64le-* | powerpc64little-*) + basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ps2) + basic_machine=i386-ibm + ;; + pw32) + basic_machine=i586-unknown + os=-pw32 + ;; + rdos) + basic_machine=i386-pc + os=-rdos + ;; + rom68k) + basic_machine=m68k-rom68k + os=-coff + ;; + rm[46]00) + basic_machine=mips-siemens + ;; + rtpc | rtpc-*) + basic_machine=romp-ibm + ;; + s390 | s390-*) + basic_machine=s390-ibm + ;; + s390x | s390x-*) + basic_machine=s390x-ibm + ;; + sa29200) + basic_machine=a29k-amd + os=-udi + ;; + sb1) + basic_machine=mipsisa64sb1-unknown + ;; + sb1el) + basic_machine=mipsisa64sb1el-unknown + ;; + sde) + basic_machine=mipsisa32-sde + os=-elf + ;; + sei) + basic_machine=mips-sei + os=-seiux + ;; + sequent) + basic_machine=i386-sequent + ;; + sh) + basic_machine=sh-hitachi + os=-hms + ;; + sh5el) + basic_machine=sh5le-unknown + ;; + sh64) + basic_machine=sh64-unknown + ;; + sparclite-wrs | simso-wrs) + basic_machine=sparclite-wrs + os=-vxworks + ;; + sps7) + basic_machine=m68k-bull + os=-sysv2 + ;; + spur) + basic_machine=spur-unknown + ;; + st2000) + basic_machine=m68k-tandem + ;; + stratus) + basic_machine=i860-stratus + os=-sysv4 + ;; + sun2) + basic_machine=m68000-sun + ;; + sun2os3) + basic_machine=m68000-sun + os=-sunos3 + ;; + sun2os4) + basic_machine=m68000-sun + os=-sunos4 + ;; + sun3os3) + basic_machine=m68k-sun + os=-sunos3 + ;; + sun3os4) + basic_machine=m68k-sun + os=-sunos4 + ;; + sun4os3) + basic_machine=sparc-sun + os=-sunos3 + ;; + sun4os4) + basic_machine=sparc-sun + os=-sunos4 + ;; + sun4sol2) + basic_machine=sparc-sun + os=-solaris2 + ;; + sun3 | sun3-*) + basic_machine=m68k-sun + ;; + sun4) + basic_machine=sparc-sun + ;; + sun386 | sun386i | roadrunner) + basic_machine=i386-sun + ;; + sv1) + basic_machine=sv1-cray + os=-unicos + ;; + symmetry) + basic_machine=i386-sequent + os=-dynix + ;; + t3e) + basic_machine=alphaev5-cray + os=-unicos + ;; + t90) + basic_machine=t90-cray + os=-unicos + ;; + tic54x | c54x*) + basic_machine=tic54x-unknown + os=-coff + ;; + tic55x | c55x*) + basic_machine=tic55x-unknown + os=-coff + ;; + tic6x | c6x*) + basic_machine=tic6x-unknown + os=-coff + ;; + tile*) + basic_machine=tile-unknown + os=-linux-gnu + ;; + tx39) + basic_machine=mipstx39-unknown + ;; + tx39el) + basic_machine=mipstx39el-unknown + ;; + toad1) + basic_machine=pdp10-xkl + os=-tops20 + ;; + tower | tower-32) + basic_machine=m68k-ncr + ;; + tpf) + basic_machine=s390x-ibm + os=-tpf + ;; + udi29k) + basic_machine=a29k-amd + os=-udi + ;; + ultra3) + basic_machine=a29k-nyu + os=-sym1 + ;; + v810 | necv810) + basic_machine=v810-nec + os=-none + ;; + vaxv) + basic_machine=vax-dec + os=-sysv + ;; + vms) + basic_machine=vax-dec + os=-vms + ;; + vpp*|vx|vx-*) + basic_machine=f301-fujitsu + ;; + vxworks960) + basic_machine=i960-wrs + os=-vxworks + ;; + vxworks68) + basic_machine=m68k-wrs + os=-vxworks + ;; + vxworks29k) + basic_machine=a29k-wrs + os=-vxworks + ;; + w65*) + basic_machine=w65-wdc + os=-none + ;; + w89k-*) + basic_machine=hppa1.1-winbond + os=-proelf + ;; + xbox) + basic_machine=i686-pc + os=-mingw32 + ;; + xps | xps100) + basic_machine=xps100-honeywell + ;; + ymp) + basic_machine=ymp-cray + os=-unicos + ;; + z8k-*-coff) + basic_machine=z8k-unknown + os=-sim + ;; + z80-*-coff) + basic_machine=z80-unknown + os=-sim + ;; + none) + basic_machine=none-none + os=-none + ;; + +# Here we handle the default manufacturer of certain CPU types. It is in +# some cases the only manufacturer, in others, it is the most popular. + w89k) + basic_machine=hppa1.1-winbond + ;; + op50n) + basic_machine=hppa1.1-oki + ;; + op60c) + basic_machine=hppa1.1-oki + ;; + romp) + basic_machine=romp-ibm + ;; + mmix) + basic_machine=mmix-knuth + ;; + rs6000) + basic_machine=rs6000-ibm + ;; + vax) + basic_machine=vax-dec + ;; + pdp10) + # there are many clones, so DEC is not a safe bet + basic_machine=pdp10-unknown + ;; + pdp11) + basic_machine=pdp11-dec + ;; + we32k) + basic_machine=we32k-att + ;; + sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) + basic_machine=sh-unknown + ;; + sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) + basic_machine=sparc-sun + ;; + cydra) + basic_machine=cydra-cydrome + ;; + orion) + basic_machine=orion-highlevel + ;; + orion105) + basic_machine=clipper-highlevel + ;; + mac | mpw | mac-mpw) + basic_machine=m68k-apple + ;; + pmac | pmac-mpw) + basic_machine=powerpc-apple + ;; + *-unknown) + # Make sure to match an already-canonicalized machine name. + ;; + *) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; +esac + +# Here we canonicalize certain aliases for manufacturers. +case $basic_machine in + *-digital*) + basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` + ;; + *-commodore*) + basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` + ;; + *) + ;; +esac + +# Decode manufacturer-specific aliases for certain operating systems. + +if [ x"$os" != x"" ] +then +case $os in + # First match some system type aliases + # that might get confused with valid system types. + # -solaris* is a basic system type, with this one exception. + -solaris1 | -solaris1.*) + os=`echo $os | sed -e 's|solaris1|sunos4|'` + ;; + -solaris) + os=-solaris2 + ;; + -svr4*) + os=-sysv4 + ;; + -unixware*) + os=-sysv4.2uw + ;; + -gnu/linux*) + os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` + ;; + # First accept the basic system types. + # The portable systems comes first. + # Each alternative MUST END IN A *, to match a version number. + # -sysv* is not here because it comes later, after sysvr4. + -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ + | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ + | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \ + | -kopensolaris* \ + | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ + | -aos* | -aros* \ + | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ + | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ + | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ + | -openbsd* | -solidbsd* \ + | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ + | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ + | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ + | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ + | -chorusos* | -chorusrdb* | -cegcc* \ + | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ + | -mingw32* | -linux-gnu* | -linux-newlib* | -linux-uclibc* \ + | -uxpv* | -beos* | -mpeix* | -udk* \ + | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ + | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ + | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ + | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ + | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ + | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ + | -skyos* | -haiku* | -rdos* | -toppers* | -drops*) + # Remember, each alternative MUST END IN *, to match a version number. + ;; + -qnx*) + case $basic_machine in + x86-* | i*86-*) + ;; + *) + os=-nto$os + ;; + esac + ;; + -nto-qnx*) + ;; + -nto*) + os=`echo $os | sed -e 's|nto|nto-qnx|'` + ;; + -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ + | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ + | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) + ;; + -mac*) + os=`echo $os | sed -e 's|mac|macos|'` + ;; + -linux-dietlibc) + os=-linux-dietlibc + ;; + -linux*) + os=`echo $os | sed -e 's|linux|linux-gnu|'` + ;; + -sunos5*) + os=`echo $os | sed -e 's|sunos5|solaris2|'` + ;; + -sunos6*) + os=`echo $os | sed -e 's|sunos6|solaris3|'` + ;; + -opened*) + os=-openedition + ;; + -os400*) + os=-os400 + ;; + -wince*) + os=-wince + ;; + -osfrose*) + os=-osfrose + ;; + -osf*) + os=-osf + ;; + -utek*) + os=-bsd + ;; + -dynix*) + os=-bsd + ;; + -acis*) + os=-aos + ;; + -atheos*) + os=-atheos + ;; + -syllable*) + os=-syllable + ;; + -386bsd) + os=-bsd + ;; + -ctix* | -uts*) + os=-sysv + ;; + -nova*) + os=-rtmk-nova + ;; + -ns2 ) + os=-nextstep2 + ;; + -nsk*) + os=-nsk + ;; + # Preserve the version number of sinix5. + -sinix5.*) + os=`echo $os | sed -e 's|sinix|sysv|'` + ;; + -sinix*) + os=-sysv4 + ;; + -tpf*) + os=-tpf + ;; + -triton*) + os=-sysv3 + ;; + -oss*) + os=-sysv3 + ;; + -svr4) + os=-sysv4 + ;; + -svr3) + os=-sysv3 + ;; + -sysvr4) + os=-sysv4 + ;; + # This must come after -sysvr4. + -sysv*) + ;; + -ose*) + os=-ose + ;; + -es1800*) + os=-ose + ;; + -xenix) + os=-xenix + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + os=-mint + ;; + -aros*) + os=-aros + ;; + -kaos*) + os=-kaos + ;; + -zvmoe) + os=-zvmoe + ;; + -dicos*) + os=-dicos + ;; + -none) + ;; + *) + # Get rid of the `-' at the beginning of $os. + os=`echo $os | sed 's/[^-]*-//'` + echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 + exit 1 + ;; +esac +else + +# Here we handle the default operating systems that come with various machines. +# The value should be what the vendor currently ships out the door with their +# machine or put another way, the most popular os provided with the machine. + +# Note that if you're going to try to match "-MANUFACTURER" here (say, +# "-sun"), then you have to tell the case statement up towards the top +# that MANUFACTURER isn't an operating system. Otherwise, code above +# will signal an error saying that MANUFACTURER isn't an operating +# system, and we'll never get to this point. + +case $basic_machine in + score-*) + os=-elf + ;; + spu-*) + os=-elf + ;; + *-acorn) + os=-riscix1.2 + ;; + arm*-rebel) + os=-linux + ;; + arm*-semi) + os=-aout + ;; + c4x-* | tic4x-*) + os=-coff + ;; + # This must come before the *-dec entry. + pdp10-*) + os=-tops20 + ;; + pdp11-*) + os=-none + ;; + *-dec | vax-*) + os=-ultrix4.2 + ;; + m68*-apollo) + os=-domain + ;; + i386-sun) + os=-sunos4.0.2 + ;; + m68000-sun) + os=-sunos3 + # This also exists in the configure program, but was not the + # default. + # os=-sunos4 + ;; + m68*-cisco) + os=-aout + ;; + mep-*) + os=-elf + ;; + mips*-cisco) + os=-elf + ;; + mips*-*) + os=-elf + ;; + or32-*) + os=-coff + ;; + *-tti) # must be before sparc entry or we get the wrong os. + os=-sysv3 + ;; + sparc-* | *-sun) + os=-sunos4.1.1 + ;; + *-be) + os=-beos + ;; + *-haiku) + os=-haiku + ;; + *-ibm) + os=-aix + ;; + *-knuth) + os=-mmixware + ;; + *-wec) + os=-proelf + ;; + *-winbond) + os=-proelf + ;; + *-oki) + os=-proelf + ;; + *-hp) + os=-hpux + ;; + *-hitachi) + os=-hiux + ;; + i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) + os=-sysv + ;; + *-cbm) + os=-amigaos + ;; + *-dg) + os=-dgux + ;; + *-dolphin) + os=-sysv3 + ;; + m68k-ccur) + os=-rtu + ;; + m88k-omron*) + os=-luna + ;; + *-next ) + os=-nextstep + ;; + *-sequent) + os=-ptx + ;; + *-crds) + os=-unos + ;; + *-ns) + os=-genix + ;; + i370-*) + os=-mvs + ;; + *-next) + os=-nextstep3 + ;; + *-gould) + os=-sysv + ;; + *-highlevel) + os=-bsd + ;; + *-encore) + os=-bsd + ;; + *-sgi) + os=-irix + ;; + *-siemens) + os=-sysv4 + ;; + *-masscomp) + os=-rtu + ;; + f30[01]-fujitsu | f700-fujitsu) + os=-uxpv + ;; + *-rom68k) + os=-coff + ;; + *-*bug) + os=-coff + ;; + *-apple) + os=-macos + ;; + *-atari*) + os=-mint + ;; + *) + os=-none + ;; +esac +fi + +# Here we handle the case where we know the os, and the CPU type, but not the +# manufacturer. We pick the logical manufacturer. +vendor=unknown +case $basic_machine in + *-unknown) + case $os in + -riscix*) + vendor=acorn + ;; + -sunos*) + vendor=sun + ;; + -cnk*|-aix*) + vendor=ibm + ;; + -beos*) + vendor=be + ;; + -hpux*) + vendor=hp + ;; + -mpeix*) + vendor=hp + ;; + -hiux*) + vendor=hitachi + ;; + -unos*) + vendor=crds + ;; + -dgux*) + vendor=dg + ;; + -luna*) + vendor=omron + ;; + -genix*) + vendor=ns + ;; + -mvs* | -opened*) + vendor=ibm + ;; + -os400*) + vendor=ibm + ;; + -ptx*) + vendor=sequent + ;; + -tpf*) + vendor=ibm + ;; + -vxsim* | -vxworks* | -windiss*) + vendor=wrs + ;; + -aux*) + vendor=apple + ;; + -hms*) + vendor=hitachi + ;; + -mpw* | -macos*) + vendor=apple + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + vendor=atari + ;; + -vos*) + vendor=stratus + ;; + esac + basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` + ;; +esac + +echo $basic_machine$os +exit + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/libclamav/c++/config/depcomp b/libclamav/c++/config/depcomp new file mode 100755 index 000000000..df8eea7e4 --- /dev/null +++ b/libclamav/c++/config/depcomp @@ -0,0 +1,630 @@ +#! /bin/sh +# depcomp - compile a program generating dependencies as side-effects + +scriptversion=2009-04-28.21; # UTC + +# Copyright (C) 1999, 2000, 2003, 2004, 2005, 2006, 2007, 2009 Free +# Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# Originally written by Alexandre Oliva . + +case $1 in + '') + echo "$0: No command. Try \`$0 --help' for more information." 1>&2 + exit 1; + ;; + -h | --h*) + cat <<\EOF +Usage: depcomp [--help] [--version] PROGRAM [ARGS] + +Run PROGRAMS ARGS to compile a file, generating dependencies +as side-effects. + +Environment variables: + depmode Dependency tracking mode. + source Source file read by `PROGRAMS ARGS'. + object Object file output by `PROGRAMS ARGS'. + DEPDIR directory where to store dependencies. + depfile Dependency file to output. + tmpdepfile Temporary file to use when outputing dependencies. + libtool Whether libtool is used (yes/no). + +Report bugs to . +EOF + exit $? + ;; + -v | --v*) + echo "depcomp $scriptversion" + exit $? + ;; +esac + +if test -z "$depmode" || test -z "$source" || test -z "$object"; then + echo "depcomp: Variables source, object and depmode must be set" 1>&2 + exit 1 +fi + +# Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po. +depfile=${depfile-`echo "$object" | + sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`} +tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`} + +rm -f "$tmpdepfile" + +# Some modes work just like other modes, but use different flags. We +# parameterize here, but still list the modes in the big case below, +# to make depend.m4 easier to write. Note that we *cannot* use a case +# here, because this file can only contain one case statement. +if test "$depmode" = hp; then + # HP compiler uses -M and no extra arg. + gccflag=-M + depmode=gcc +fi + +if test "$depmode" = dashXmstdout; then + # This is just like dashmstdout with a different argument. + dashmflag=-xM + depmode=dashmstdout +fi + +cygpath_u="cygpath -u -f -" +if test "$depmode" = msvcmsys; then + # This is just like msvisualcpp but w/o cygpath translation. + # Just convert the backslash-escaped backslashes to single forward + # slashes to satisfy depend.m4 + cygpath_u="sed s,\\\\\\\\,/,g" + depmode=msvisualcpp +fi + +case "$depmode" in +gcc3) +## gcc 3 implements dependency tracking that does exactly what +## we want. Yay! Note: for some reason libtool 1.4 doesn't like +## it if -MD -MP comes after the -MF stuff. Hmm. +## Unfortunately, FreeBSD c89 acceptance of flags depends upon +## the command line argument order; so add the flags where they +## appear in depend2.am. Note that the slowdown incurred here +## affects only configure: in makefiles, %FASTDEP% shortcuts this. + for arg + do + case $arg in + -c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;; + *) set fnord "$@" "$arg" ;; + esac + shift # fnord + shift # $arg + done + "$@" + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + mv "$tmpdepfile" "$depfile" + ;; + +gcc) +## There are various ways to get dependency output from gcc. Here's +## why we pick this rather obscure method: +## - Don't want to use -MD because we'd like the dependencies to end +## up in a subdir. Having to rename by hand is ugly. +## (We might end up doing this anyway to support other compilers.) +## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like +## -MM, not -M (despite what the docs say). +## - Using -M directly means running the compiler twice (even worse +## than renaming). + if test -z "$gccflag"; then + gccflag=-MD, + fi + "$@" -Wp,"$gccflag$tmpdepfile" + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + echo "$object : \\" > "$depfile" + alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz +## The second -e expression handles DOS-style file names with drive letters. + sed -e 's/^[^:]*: / /' \ + -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile" +## This next piece of magic avoids the `deleted header file' problem. +## The problem is that when a header file which appears in a .P file +## is deleted, the dependency causes make to die (because there is +## typically no way to rebuild the header). We avoid this by adding +## dummy dependencies for each header file. Too bad gcc doesn't do +## this for us directly. + tr ' ' ' +' < "$tmpdepfile" | +## Some versions of gcc put a space before the `:'. On the theory +## that the space means something, we add a space to the output as +## well. +## Some versions of the HPUX 10.20 sed can't process this invocation +## correctly. Breaking it into two sed invocations is a workaround. + sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +hp) + # This case exists only to let depend.m4 do its work. It works by + # looking at the text of this script. This case will never be run, + # since it is checked for above. + exit 1 + ;; + +sgi) + if test "$libtool" = yes; then + "$@" "-Wp,-MDupdate,$tmpdepfile" + else + "$@" -MDupdate "$tmpdepfile" + fi + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + + if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files + echo "$object : \\" > "$depfile" + + # Clip off the initial element (the dependent). Don't try to be + # clever and replace this with sed code, as IRIX sed won't handle + # lines with more than a fixed number of characters (4096 in + # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines; + # the IRIX cc adds comments like `#:fec' to the end of the + # dependency line. + tr ' ' ' +' < "$tmpdepfile" \ + | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \ + tr ' +' ' ' >> "$depfile" + echo >> "$depfile" + + # The second pass generates a dummy entry for each header file. + tr ' ' ' +' < "$tmpdepfile" \ + | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ + >> "$depfile" + else + # The sourcefile does not contain any dependencies, so just + # store a dummy comment line, to avoid errors with the Makefile + # "include basename.Plo" scheme. + echo "#dummy" > "$depfile" + fi + rm -f "$tmpdepfile" + ;; + +aix) + # The C for AIX Compiler uses -M and outputs the dependencies + # in a .u file. In older versions, this file always lives in the + # current directory. Also, the AIX compiler puts `$object:' at the + # start of each line; $object doesn't have directory information. + # Version 6 uses the directory in both cases. + dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` + test "x$dir" = "x$object" && dir= + base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` + if test "$libtool" = yes; then + tmpdepfile1=$dir$base.u + tmpdepfile2=$base.u + tmpdepfile3=$dir.libs/$base.u + "$@" -Wc,-M + else + tmpdepfile1=$dir$base.u + tmpdepfile2=$dir$base.u + tmpdepfile3=$dir$base.u + "$@" -M + fi + stat=$? + + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" + exit $stat + fi + + for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" + do + test -f "$tmpdepfile" && break + done + if test -f "$tmpdepfile"; then + # Each line is of the form `foo.o: dependent.h'. + # Do two passes, one to just change these to + # `$object: dependent.h' and one to simply `dependent.h:'. + sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile" + # That's a tab and a space in the []. + sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile" + else + # The sourcefile does not contain any dependencies, so just + # store a dummy comment line, to avoid errors with the Makefile + # "include basename.Plo" scheme. + echo "#dummy" > "$depfile" + fi + rm -f "$tmpdepfile" + ;; + +icc) + # Intel's C compiler understands `-MD -MF file'. However on + # icc -MD -MF foo.d -c -o sub/foo.o sub/foo.c + # ICC 7.0 will fill foo.d with something like + # foo.o: sub/foo.c + # foo.o: sub/foo.h + # which is wrong. We want: + # sub/foo.o: sub/foo.c + # sub/foo.o: sub/foo.h + # sub/foo.c: + # sub/foo.h: + # ICC 7.1 will output + # foo.o: sub/foo.c sub/foo.h + # and will wrap long lines using \ : + # foo.o: sub/foo.c ... \ + # sub/foo.h ... \ + # ... + + "$@" -MD -MF "$tmpdepfile" + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + # Each line is of the form `foo.o: dependent.h', + # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'. + # Do two passes, one to just change these to + # `$object: dependent.h' and one to simply `dependent.h:'. + sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile" + # Some versions of the HPUX 10.20 sed can't process this invocation + # correctly. Breaking it into two sed invocations is a workaround. + sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" | + sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +hp2) + # The "hp" stanza above does not work with aCC (C++) and HP's ia64 + # compilers, which have integrated preprocessors. The correct option + # to use with these is +Maked; it writes dependencies to a file named + # 'foo.d', which lands next to the object file, wherever that + # happens to be. + # Much of this is similar to the tru64 case; see comments there. + dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` + test "x$dir" = "x$object" && dir= + base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` + if test "$libtool" = yes; then + tmpdepfile1=$dir$base.d + tmpdepfile2=$dir.libs/$base.d + "$@" -Wc,+Maked + else + tmpdepfile1=$dir$base.d + tmpdepfile2=$dir$base.d + "$@" +Maked + fi + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile1" "$tmpdepfile2" + exit $stat + fi + + for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" + do + test -f "$tmpdepfile" && break + done + if test -f "$tmpdepfile"; then + sed -e "s,^.*\.[a-z]*:,$object:," "$tmpdepfile" > "$depfile" + # Add `dependent.h:' lines. + sed -ne '2,${ + s/^ *// + s/ \\*$// + s/$/:/ + p + }' "$tmpdepfile" >> "$depfile" + else + echo "#dummy" > "$depfile" + fi + rm -f "$tmpdepfile" "$tmpdepfile2" + ;; + +tru64) + # The Tru64 compiler uses -MD to generate dependencies as a side + # effect. `cc -MD -o foo.o ...' puts the dependencies into `foo.o.d'. + # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put + # dependencies in `foo.d' instead, so we check for that too. + # Subdirectories are respected. + dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` + test "x$dir" = "x$object" && dir= + base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` + + if test "$libtool" = yes; then + # With Tru64 cc, shared objects can also be used to make a + # static library. This mechanism is used in libtool 1.4 series to + # handle both shared and static libraries in a single compilation. + # With libtool 1.4, dependencies were output in $dir.libs/$base.lo.d. + # + # With libtool 1.5 this exception was removed, and libtool now + # generates 2 separate objects for the 2 libraries. These two + # compilations output dependencies in $dir.libs/$base.o.d and + # in $dir$base.o.d. We have to check for both files, because + # one of the two compilations can be disabled. We should prefer + # $dir$base.o.d over $dir.libs/$base.o.d because the latter is + # automatically cleaned when .libs/ is deleted, while ignoring + # the former would cause a distcleancheck panic. + tmpdepfile1=$dir.libs/$base.lo.d # libtool 1.4 + tmpdepfile2=$dir$base.o.d # libtool 1.5 + tmpdepfile3=$dir.libs/$base.o.d # libtool 1.5 + tmpdepfile4=$dir.libs/$base.d # Compaq CCC V6.2-504 + "$@" -Wc,-MD + else + tmpdepfile1=$dir$base.o.d + tmpdepfile2=$dir$base.d + tmpdepfile3=$dir$base.d + tmpdepfile4=$dir$base.d + "$@" -MD + fi + + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4" + exit $stat + fi + + for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4" + do + test -f "$tmpdepfile" && break + done + if test -f "$tmpdepfile"; then + sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile" + # That's a tab and a space in the []. + sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile" + else + echo "#dummy" > "$depfile" + fi + rm -f "$tmpdepfile" + ;; + +#nosideeffect) + # This comment above is used by automake to tell side-effect + # dependency tracking mechanisms from slower ones. + +dashmstdout) + # Important note: in order to support this mode, a compiler *must* + # always write the preprocessed file to stdout, regardless of -o. + "$@" || exit $? + + # Remove the call to Libtool. + if test "$libtool" = yes; then + while test "X$1" != 'X--mode=compile'; do + shift + done + shift + fi + + # Remove `-o $object'. + IFS=" " + for arg + do + case $arg in + -o) + shift + ;; + $object) + shift + ;; + *) + set fnord "$@" "$arg" + shift # fnord + shift # $arg + ;; + esac + done + + test -z "$dashmflag" && dashmflag=-M + # Require at least two characters before searching for `:' + # in the target name. This is to cope with DOS-style filenames: + # a dependency such as `c:/foo/bar' could be seen as target `c' otherwise. + "$@" $dashmflag | + sed 's:^[ ]*[^: ][^:][^:]*\:[ ]*:'"$object"'\: :' > "$tmpdepfile" + rm -f "$depfile" + cat < "$tmpdepfile" > "$depfile" + tr ' ' ' +' < "$tmpdepfile" | \ +## Some versions of the HPUX 10.20 sed can't process this invocation +## correctly. Breaking it into two sed invocations is a workaround. + sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +dashXmstdout) + # This case only exists to satisfy depend.m4. It is never actually + # run, as this mode is specially recognized in the preamble. + exit 1 + ;; + +makedepend) + "$@" || exit $? + # Remove any Libtool call + if test "$libtool" = yes; then + while test "X$1" != 'X--mode=compile'; do + shift + done + shift + fi + # X makedepend + shift + cleared=no eat=no + for arg + do + case $cleared in + no) + set ""; shift + cleared=yes ;; + esac + if test $eat = yes; then + eat=no + continue + fi + case "$arg" in + -D*|-I*) + set fnord "$@" "$arg"; shift ;; + # Strip any option that makedepend may not understand. Remove + # the object too, otherwise makedepend will parse it as a source file. + -arch) + eat=yes ;; + -*|$object) + ;; + *) + set fnord "$@" "$arg"; shift ;; + esac + done + obj_suffix=`echo "$object" | sed 's/^.*\././'` + touch "$tmpdepfile" + ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@" + rm -f "$depfile" + cat < "$tmpdepfile" > "$depfile" + sed '1,2d' "$tmpdepfile" | tr ' ' ' +' | \ +## Some versions of the HPUX 10.20 sed can't process this invocation +## correctly. Breaking it into two sed invocations is a workaround. + sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" "$tmpdepfile".bak + ;; + +cpp) + # Important note: in order to support this mode, a compiler *must* + # always write the preprocessed file to stdout. + "$@" || exit $? + + # Remove the call to Libtool. + if test "$libtool" = yes; then + while test "X$1" != 'X--mode=compile'; do + shift + done + shift + fi + + # Remove `-o $object'. + IFS=" " + for arg + do + case $arg in + -o) + shift + ;; + $object) + shift + ;; + *) + set fnord "$@" "$arg" + shift # fnord + shift # $arg + ;; + esac + done + + "$@" -E | + sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ + -e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' | + sed '$ s: \\$::' > "$tmpdepfile" + rm -f "$depfile" + echo "$object : \\" > "$depfile" + cat < "$tmpdepfile" >> "$depfile" + sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +msvisualcpp) + # Important note: in order to support this mode, a compiler *must* + # always write the preprocessed file to stdout. + "$@" || exit $? + + # Remove the call to Libtool. + if test "$libtool" = yes; then + while test "X$1" != 'X--mode=compile'; do + shift + done + shift + fi + + IFS=" " + for arg + do + case "$arg" in + -o) + shift + ;; + $object) + shift + ;; + "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") + set fnord "$@" + shift + shift + ;; + *) + set fnord "$@" "$arg" + shift + shift + ;; + esac + done + "$@" -E 2>/dev/null | + sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile" + rm -f "$depfile" + echo "$object : \\" > "$depfile" + sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s:: \1 \\:p' >> "$depfile" + echo " " >> "$depfile" + sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +msvcmsys) + # This case exists only to let depend.m4 do its work. It works by + # looking at the text of this script. This case will never be run, + # since it is checked for above. + exit 1 + ;; + +none) + exec "$@" + ;; + +*) + echo "Unknown depmode $depmode" 1>&2 + exit 1 + ;; +esac + +exit 0 + +# Local Variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/libclamav/c++/config/install-sh b/libclamav/c++/config/install-sh new file mode 100755 index 000000000..6781b987b --- /dev/null +++ b/libclamav/c++/config/install-sh @@ -0,0 +1,520 @@ +#!/bin/sh +# install - install a program, script, or datafile + +scriptversion=2009-04-28.21; # UTC + +# This originates from X11R5 (mit/util/scripts/install.sh), which was +# later released in X11R6 (xc/config/util/install.sh) with the +# following copyright and license. +# +# Copyright (C) 1994 X Consortium +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in 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: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# 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 +# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- +# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# +# Except as contained in this notice, the name of the X Consortium shall not +# be used in advertising or otherwise to promote the sale, use or other deal- +# ings in this Software without prior written authorization from the X Consor- +# tium. +# +# +# FSF changes to this file are in the public domain. +# +# Calling this script install-sh is preferred over install.sh, to prevent +# `make' implicit rules from creating a file called install from it +# when there is no Makefile. +# +# This script is compatible with the BSD install script, but was written +# from scratch. + +nl=' +' +IFS=" "" $nl" + +# set DOITPROG to echo to test this script + +# Don't use :- since 4.3BSD and earlier shells don't like it. +doit=${DOITPROG-} +if test -z "$doit"; then + doit_exec=exec +else + doit_exec=$doit +fi + +# Put in absolute file names if you don't have them in your path; +# or use environment vars. + +chgrpprog=${CHGRPPROG-chgrp} +chmodprog=${CHMODPROG-chmod} +chownprog=${CHOWNPROG-chown} +cmpprog=${CMPPROG-cmp} +cpprog=${CPPROG-cp} +mkdirprog=${MKDIRPROG-mkdir} +mvprog=${MVPROG-mv} +rmprog=${RMPROG-rm} +stripprog=${STRIPPROG-strip} + +posix_glob='?' +initialize_posix_glob=' + test "$posix_glob" != "?" || { + if (set -f) 2>/dev/null; then + posix_glob= + else + posix_glob=: + fi + } +' + +posix_mkdir= + +# Desired mode of installed file. +mode=0755 + +chgrpcmd= +chmodcmd=$chmodprog +chowncmd= +mvcmd=$mvprog +rmcmd="$rmprog -f" +stripcmd= + +src= +dst= +dir_arg= +dst_arg= + +copy_on_change=false +no_target_directory= + +usage="\ +Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE + or: $0 [OPTION]... SRCFILES... DIRECTORY + or: $0 [OPTION]... -t DIRECTORY SRCFILES... + or: $0 [OPTION]... -d DIRECTORIES... + +In the 1st form, copy SRCFILE to DSTFILE. +In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. +In the 4th, create DIRECTORIES. + +Options: + --help display this help and exit. + --version display version info and exit. + + -c (ignored) + -C install only if different (preserve the last data modification time) + -d create directories instead of installing files. + -g GROUP $chgrpprog installed files to GROUP. + -m MODE $chmodprog installed files to MODE. + -o USER $chownprog installed files to USER. + -s $stripprog installed files. + -t DIRECTORY install into DIRECTORY. + -T report an error if DSTFILE is a directory. + +Environment variables override the default commands: + CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG + RMPROG STRIPPROG +" + +while test $# -ne 0; do + case $1 in + -c) ;; + + -C) copy_on_change=true;; + + -d) dir_arg=true;; + + -g) chgrpcmd="$chgrpprog $2" + shift;; + + --help) echo "$usage"; exit $?;; + + -m) mode=$2 + case $mode in + *' '* | *' '* | *' +'* | *'*'* | *'?'* | *'['*) + echo "$0: invalid mode: $mode" >&2 + exit 1;; + esac + shift;; + + -o) chowncmd="$chownprog $2" + shift;; + + -s) stripcmd=$stripprog;; + + -t) dst_arg=$2 + shift;; + + -T) no_target_directory=true;; + + --version) echo "$0 $scriptversion"; exit $?;; + + --) shift + break;; + + -*) echo "$0: invalid option: $1" >&2 + exit 1;; + + *) break;; + esac + shift +done + +if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then + # When -d is used, all remaining arguments are directories to create. + # When -t is used, the destination is already specified. + # Otherwise, the last argument is the destination. Remove it from $@. + for arg + do + if test -n "$dst_arg"; then + # $@ is not empty: it contains at least $arg. + set fnord "$@" "$dst_arg" + shift # fnord + fi + shift # arg + dst_arg=$arg + done +fi + +if test $# -eq 0; then + if test -z "$dir_arg"; then + echo "$0: no input file specified." >&2 + exit 1 + fi + # It's OK to call `install-sh -d' without argument. + # This can happen when creating conditional directories. + exit 0 +fi + +if test -z "$dir_arg"; then + trap '(exit $?); exit' 1 2 13 15 + + # Set umask so as not to create temps with too-generous modes. + # However, 'strip' requires both read and write access to temps. + case $mode in + # Optimize common cases. + *644) cp_umask=133;; + *755) cp_umask=22;; + + *[0-7]) + if test -z "$stripcmd"; then + u_plus_rw= + else + u_plus_rw='% 200' + fi + cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; + *) + if test -z "$stripcmd"; then + u_plus_rw= + else + u_plus_rw=,u+rw + fi + cp_umask=$mode$u_plus_rw;; + esac +fi + +for src +do + # Protect names starting with `-'. + case $src in + -*) src=./$src;; + esac + + if test -n "$dir_arg"; then + dst=$src + dstdir=$dst + test -d "$dstdir" + dstdir_status=$? + else + + # Waiting for this to be detected by the "$cpprog $src $dsttmp" command + # might cause directories to be created, which would be especially bad + # if $src (and thus $dsttmp) contains '*'. + if test ! -f "$src" && test ! -d "$src"; then + echo "$0: $src does not exist." >&2 + exit 1 + fi + + if test -z "$dst_arg"; then + echo "$0: no destination specified." >&2 + exit 1 + fi + + dst=$dst_arg + # Protect names starting with `-'. + case $dst in + -*) dst=./$dst;; + esac + + # If destination is a directory, append the input filename; won't work + # if double slashes aren't ignored. + if test -d "$dst"; then + if test -n "$no_target_directory"; then + echo "$0: $dst_arg: Is a directory" >&2 + exit 1 + fi + dstdir=$dst + dst=$dstdir/`basename "$src"` + dstdir_status=0 + else + # Prefer dirname, but fall back on a substitute if dirname fails. + dstdir=` + (dirname "$dst") 2>/dev/null || + expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$dst" : 'X\(//\)[^/]' \| \ + X"$dst" : 'X\(//\)$' \| \ + X"$dst" : 'X\(/\)' \| . 2>/dev/null || + echo X"$dst" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q' + ` + + test -d "$dstdir" + dstdir_status=$? + fi + fi + + obsolete_mkdir_used=false + + if test $dstdir_status != 0; then + case $posix_mkdir in + '') + # Create intermediate dirs using mode 755 as modified by the umask. + # This is like FreeBSD 'install' as of 1997-10-28. + umask=`umask` + case $stripcmd.$umask in + # Optimize common cases. + *[2367][2367]) mkdir_umask=$umask;; + .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; + + *[0-7]) + mkdir_umask=`expr $umask + 22 \ + - $umask % 100 % 40 + $umask % 20 \ + - $umask % 10 % 4 + $umask % 2 + `;; + *) mkdir_umask=$umask,go-w;; + esac + + # With -d, create the new directory with the user-specified mode. + # Otherwise, rely on $mkdir_umask. + if test -n "$dir_arg"; then + mkdir_mode=-m$mode + else + mkdir_mode= + fi + + posix_mkdir=false + case $umask in + *[123567][0-7][0-7]) + # POSIX mkdir -p sets u+wx bits regardless of umask, which + # is incompatible with FreeBSD 'install' when (umask & 300) != 0. + ;; + *) + tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ + trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0 + + if (umask $mkdir_umask && + exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1 + then + if test -z "$dir_arg" || { + # Check for POSIX incompatibilities with -m. + # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or + # other-writeable bit of parent directory when it shouldn't. + # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. + ls_ld_tmpdir=`ls -ld "$tmpdir"` + case $ls_ld_tmpdir in + d????-?r-*) different_mode=700;; + d????-?--*) different_mode=755;; + *) false;; + esac && + $mkdirprog -m$different_mode -p -- "$tmpdir" && { + ls_ld_tmpdir_1=`ls -ld "$tmpdir"` + test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" + } + } + then posix_mkdir=: + fi + rmdir "$tmpdir/d" "$tmpdir" + else + # Remove any dirs left behind by ancient mkdir implementations. + rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null + fi + trap '' 0;; + esac;; + esac + + if + $posix_mkdir && ( + umask $mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" + ) + then : + else + + # The umask is ridiculous, or mkdir does not conform to POSIX, + # or it failed possibly due to a race condition. Create the + # directory the slow way, step by step, checking for races as we go. + + case $dstdir in + /*) prefix='/';; + -*) prefix='./';; + *) prefix='';; + esac + + eval "$initialize_posix_glob" + + oIFS=$IFS + IFS=/ + $posix_glob set -f + set fnord $dstdir + shift + $posix_glob set +f + IFS=$oIFS + + prefixes= + + for d + do + test -z "$d" && continue + + prefix=$prefix$d + if test -d "$prefix"; then + prefixes= + else + if $posix_mkdir; then + (umask=$mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break + # Don't fail if two instances are running concurrently. + test -d "$prefix" || exit 1 + else + case $prefix in + *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; + *) qprefix=$prefix;; + esac + prefixes="$prefixes '$qprefix'" + fi + fi + prefix=$prefix/ + done + + if test -n "$prefixes"; then + # Don't fail if two instances are running concurrently. + (umask $mkdir_umask && + eval "\$doit_exec \$mkdirprog $prefixes") || + test -d "$dstdir" || exit 1 + obsolete_mkdir_used=true + fi + fi + fi + + if test -n "$dir_arg"; then + { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && + { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && + { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || + test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 + else + + # Make a couple of temp file names in the proper directory. + dsttmp=$dstdir/_inst.$$_ + rmtmp=$dstdir/_rm.$$_ + + # Trap to clean up those temp files at exit. + trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 + + # Copy the file name to the temp name. + (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") && + + # and set any options; do chmod last to preserve setuid bits. + # + # If any of these fail, we abort the whole thing. If we want to + # ignore errors from any of these, just make sure not to ignore + # errors from the above "$doit $cpprog $src $dsttmp" command. + # + { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && + { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && + { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && + { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && + + # If -C, don't bother to copy if it wouldn't change the file. + if $copy_on_change && + old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && + new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && + + eval "$initialize_posix_glob" && + $posix_glob set -f && + set X $old && old=:$2:$4:$5:$6 && + set X $new && new=:$2:$4:$5:$6 && + $posix_glob set +f && + + test "$old" = "$new" && + $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 + then + rm -f "$dsttmp" + else + # Rename the file to the real destination. + $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || + + # The rename failed, perhaps because mv can't rename something else + # to itself, or perhaps because mv is so ancient that it does not + # support -f. + { + # Now remove or move aside any old file at destination location. + # We try this two ways since rm can't unlink itself on some + # systems and the destination file might be busy for other + # reasons. In this case, the final cleanup might fail but the new + # file should still install successfully. + { + test ! -f "$dst" || + $doit $rmcmd -f "$dst" 2>/dev/null || + { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && + { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } + } || + { echo "$0: cannot unlink or rename $dst" >&2 + (exit 1); exit 1 + } + } && + + # Now rename the file to the real destination. + $doit $mvcmd "$dsttmp" "$dst" + } + fi || exit 1 + + trap '' 0 + fi +done + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/libclamav/c++/config/ltmain.sh b/libclamav/c++/config/ltmain.sh new file mode 100755 index 000000000..d88da2c26 --- /dev/null +++ b/libclamav/c++/config/ltmain.sh @@ -0,0 +1,8413 @@ +# Generated from ltmain.m4sh. + +# ltmain.sh (GNU libtool) 2.2.6b +# Written by Gordon Matzigkeit , 1996 + +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006, 2007 2008 Free Software Foundation, Inc. +# This is free software; see the source for copying conditions. There is NO +# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +# GNU Libtool is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# As a special exception to the GNU General Public License, +# if you distribute this file as part of a program or library that +# is built using GNU Libtool, you may include this file under the +# same distribution terms that you use for the rest of that program. +# +# GNU Libtool is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Libtool; see the file COPYING. If not, a copy +# can be downloaded from http://www.gnu.org/licenses/gpl.html, +# or obtained by writing to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +# Usage: $progname [OPTION]... [MODE-ARG]... +# +# Provide generalized library-building support services. +# +# --config show all configuration variables +# --debug enable verbose shell tracing +# -n, --dry-run display commands without modifying any files +# --features display basic configuration information and exit +# --mode=MODE use operation mode MODE +# --preserve-dup-deps don't remove duplicate dependency libraries +# --quiet, --silent don't print informational messages +# --tag=TAG use configuration variables from tag TAG +# -v, --verbose print informational messages (default) +# --version print version information +# -h, --help print short or long help message +# +# MODE must be one of the following: +# +# clean remove files from the build directory +# compile compile a source file into a libtool object +# execute automatically set library path, then run a program +# finish complete the installation of libtool libraries +# install install libraries or executables +# link create a library or an executable +# uninstall remove libraries from an installed directory +# +# MODE-ARGS vary depending on the MODE. +# Try `$progname --help --mode=MODE' for a more detailed description of MODE. +# +# When reporting a bug, please describe a test case to reproduce it and +# include the following information: +# +# host-triplet: $host +# shell: $SHELL +# compiler: $LTCC +# compiler flags: $LTCFLAGS +# linker: $LD (gnu? $with_gnu_ld) +# $progname: (GNU libtool) 2.2.6b Debian-2.2.6b-2 +# automake: $automake_version +# autoconf: $autoconf_version +# +# Report bugs to . + +PROGRAM=ltmain.sh +PACKAGE=libtool +VERSION="2.2.6b Debian-2.2.6b-2" +TIMESTAMP="" +package_revision=1.3017 + +# Be Bourne compatible +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac +fi +BIN_SH=xpg4; export BIN_SH # for Tru64 +DUALCASE=1; export DUALCASE # for MKS sh + +# NLS nuisances: We save the old values to restore during execute mode. +# Only set LANG and LC_ALL to C if already set. +# These must not be set unconditionally because not all systems understand +# e.g. LANG=C (notably SCO). +lt_user_locale= +lt_safe_locale= +for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES +do + eval "if test \"\${$lt_var+set}\" = set; then + save_$lt_var=\$$lt_var + $lt_var=C + export $lt_var + lt_user_locale=\"$lt_var=\\\$save_\$lt_var; \$lt_user_locale\" + lt_safe_locale=\"$lt_var=C; \$lt_safe_locale\" + fi" +done + +$lt_unset CDPATH + + + + + +: ${CP="cp -f"} +: ${ECHO="echo"} +: ${EGREP="/bin/grep -E"} +: ${FGREP="/bin/grep -F"} +: ${GREP="/bin/grep"} +: ${LN_S="ln -s"} +: ${MAKE="make"} +: ${MKDIR="mkdir"} +: ${MV="mv -f"} +: ${RM="rm -f"} +: ${SED="/bin/sed"} +: ${SHELL="${CONFIG_SHELL-/bin/sh}"} +: ${Xsed="$SED -e 1s/^X//"} + +# Global variables: +EXIT_SUCCESS=0 +EXIT_FAILURE=1 +EXIT_MISMATCH=63 # $? = 63 is used to indicate version mismatch to missing. +EXIT_SKIP=77 # $? = 77 is used to indicate a skipped test to automake. + +exit_status=$EXIT_SUCCESS + +# Make sure IFS has a sensible default +lt_nl=' +' +IFS=" $lt_nl" + +dirname="s,/[^/]*$,," +basename="s,^.*/,," + +# func_dirname_and_basename file append nondir_replacement +# perform func_basename and func_dirname in a single function +# call: +# dirname: Compute the dirname of FILE. If nonempty, +# add APPEND to the result, otherwise set result +# to NONDIR_REPLACEMENT. +# value returned in "$func_dirname_result" +# basename: Compute filename of FILE. +# value retuned in "$func_basename_result" +# Implementation must be kept synchronized with func_dirname +# and func_basename. For efficiency, we do not delegate to +# those functions but instead duplicate the functionality here. +func_dirname_and_basename () +{ + # Extract subdirectory from the argument. + func_dirname_result=`$ECHO "X${1}" | $Xsed -e "$dirname"` + if test "X$func_dirname_result" = "X${1}"; then + func_dirname_result="${3}" + else + func_dirname_result="$func_dirname_result${2}" + fi + func_basename_result=`$ECHO "X${1}" | $Xsed -e "$basename"` +} + +# Generated shell functions inserted here. + +# Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh +# is ksh but when the shell is invoked as "sh" and the current value of +# the _XPG environment variable is not equal to 1 (one), the special +# positional parameter $0, within a function call, is the name of the +# function. +progpath="$0" + +# The name of this program: +# In the unlikely event $progname began with a '-', it would play havoc with +# func_echo (imagine progname=-n), so we prepend ./ in that case: +func_dirname_and_basename "$progpath" +progname=$func_basename_result +case $progname in + -*) progname=./$progname ;; +esac + +# Make sure we have an absolute path for reexecution: +case $progpath in + [\\/]*|[A-Za-z]:\\*) ;; + *[\\/]*) + progdir=$func_dirname_result + progdir=`cd "$progdir" && pwd` + progpath="$progdir/$progname" + ;; + *) + save_IFS="$IFS" + IFS=: + for progdir in $PATH; do + IFS="$save_IFS" + test -x "$progdir/$progname" && break + done + IFS="$save_IFS" + test -n "$progdir" || progdir=`pwd` + progpath="$progdir/$progname" + ;; +esac + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +Xsed="${SED}"' -e 1s/^X//' +sed_quote_subst='s/\([`"$\\]\)/\\\1/g' + +# Same as above, but do not quote variable references. +double_quote_subst='s/\(["`\\]\)/\\\1/g' + +# Re-`\' parameter expansions in output of double_quote_subst that were +# `\'-ed in input to the same. If an odd number of `\' preceded a '$' +# in input to double_quote_subst, that '$' was protected from expansion. +# Since each input `\' is now two `\'s, look for any number of runs of +# four `\'s followed by two `\'s and then a '$'. `\' that '$'. +bs='\\' +bs2='\\\\' +bs4='\\\\\\\\' +dollar='\$' +sed_double_backslash="\ + s/$bs4/&\\ +/g + s/^$bs2$dollar/$bs&/ + s/\\([^$bs]\\)$bs2$dollar/\\1$bs2$bs$dollar/g + s/\n//g" + +# Standard options: +opt_dry_run=false +opt_help=false +opt_quiet=false +opt_verbose=false +opt_warning=: + +# func_echo arg... +# Echo program name prefixed message, along with the current mode +# name if it has been set yet. +func_echo () +{ + $ECHO "$progname${mode+: }$mode: $*" +} + +# func_verbose arg... +# Echo program name prefixed message in verbose mode only. +func_verbose () +{ + $opt_verbose && func_echo ${1+"$@"} + + # A bug in bash halts the script if the last line of a function + # fails when set -e is in force, so we need another command to + # work around that: + : +} + +# func_error arg... +# Echo program name prefixed message to standard error. +func_error () +{ + $ECHO "$progname${mode+: }$mode: "${1+"$@"} 1>&2 +} + +# func_warning arg... +# Echo program name prefixed warning message to standard error. +func_warning () +{ + $opt_warning && $ECHO "$progname${mode+: }$mode: warning: "${1+"$@"} 1>&2 + + # bash bug again: + : +} + +# func_fatal_error arg... +# Echo program name prefixed message to standard error, and exit. +func_fatal_error () +{ + func_error ${1+"$@"} + exit $EXIT_FAILURE +} + +# func_fatal_help arg... +# Echo program name prefixed message to standard error, followed by +# a help hint, and exit. +func_fatal_help () +{ + func_error ${1+"$@"} + func_fatal_error "$help" +} +help="Try \`$progname --help' for more information." ## default + + +# func_grep expression filename +# Check whether EXPRESSION matches any line of FILENAME, without output. +func_grep () +{ + $GREP "$1" "$2" >/dev/null 2>&1 +} + + +# func_mkdir_p directory-path +# Make sure the entire path to DIRECTORY-PATH is available. +func_mkdir_p () +{ + my_directory_path="$1" + my_dir_list= + + if test -n "$my_directory_path" && test "$opt_dry_run" != ":"; then + + # Protect directory names starting with `-' + case $my_directory_path in + -*) my_directory_path="./$my_directory_path" ;; + esac + + # While some portion of DIR does not yet exist... + while test ! -d "$my_directory_path"; do + # ...make a list in topmost first order. Use a colon delimited + # list incase some portion of path contains whitespace. + my_dir_list="$my_directory_path:$my_dir_list" + + # If the last portion added has no slash in it, the list is done + case $my_directory_path in */*) ;; *) break ;; esac + + # ...otherwise throw away the child directory and loop + my_directory_path=`$ECHO "X$my_directory_path" | $Xsed -e "$dirname"` + done + my_dir_list=`$ECHO "X$my_dir_list" | $Xsed -e 's,:*$,,'` + + save_mkdir_p_IFS="$IFS"; IFS=':' + for my_dir in $my_dir_list; do + IFS="$save_mkdir_p_IFS" + # mkdir can fail with a `File exist' error if two processes + # try to create one of the directories concurrently. Don't + # stop in that case! + $MKDIR "$my_dir" 2>/dev/null || : + done + IFS="$save_mkdir_p_IFS" + + # Bail out if we (or some other process) failed to create a directory. + test -d "$my_directory_path" || \ + func_fatal_error "Failed to create \`$1'" + fi +} + + +# func_mktempdir [string] +# Make a temporary directory that won't clash with other running +# libtool processes, and avoids race conditions if possible. If +# given, STRING is the basename for that directory. +func_mktempdir () +{ + my_template="${TMPDIR-/tmp}/${1-$progname}" + + if test "$opt_dry_run" = ":"; then + # Return a directory name, but don't create it in dry-run mode + my_tmpdir="${my_template}-$$" + else + + # If mktemp works, use that first and foremost + my_tmpdir=`mktemp -d "${my_template}-XXXXXXXX" 2>/dev/null` + + if test ! -d "$my_tmpdir"; then + # Failing that, at least try and use $RANDOM to avoid a race + my_tmpdir="${my_template}-${RANDOM-0}$$" + + save_mktempdir_umask=`umask` + umask 0077 + $MKDIR "$my_tmpdir" + umask $save_mktempdir_umask + fi + + # If we're not in dry-run mode, bomb out on failure + test -d "$my_tmpdir" || \ + func_fatal_error "cannot create temporary directory \`$my_tmpdir'" + fi + + $ECHO "X$my_tmpdir" | $Xsed +} + + +# func_quote_for_eval arg +# Aesthetically quote ARG to be evaled later. +# This function returns two values: FUNC_QUOTE_FOR_EVAL_RESULT +# is double-quoted, suitable for a subsequent eval, whereas +# FUNC_QUOTE_FOR_EVAL_UNQUOTED_RESULT has merely all characters +# which are still active within double quotes backslashified. +func_quote_for_eval () +{ + case $1 in + *[\\\`\"\$]*) + func_quote_for_eval_unquoted_result=`$ECHO "X$1" | $Xsed -e "$sed_quote_subst"` ;; + *) + func_quote_for_eval_unquoted_result="$1" ;; + esac + + case $func_quote_for_eval_unquoted_result in + # Double-quote args containing shell metacharacters to delay + # word splitting, command substitution and and variable + # expansion for a subsequent eval. + # Many Bourne shells cannot handle close brackets correctly + # in scan sets, so we specify it separately. + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + func_quote_for_eval_result="\"$func_quote_for_eval_unquoted_result\"" + ;; + *) + func_quote_for_eval_result="$func_quote_for_eval_unquoted_result" + esac +} + + +# func_quote_for_expand arg +# Aesthetically quote ARG to be evaled later; same as above, +# but do not quote variable references. +func_quote_for_expand () +{ + case $1 in + *[\\\`\"]*) + my_arg=`$ECHO "X$1" | $Xsed \ + -e "$double_quote_subst" -e "$sed_double_backslash"` ;; + *) + my_arg="$1" ;; + esac + + case $my_arg in + # Double-quote args containing shell metacharacters to delay + # word splitting and command substitution for a subsequent eval. + # Many Bourne shells cannot handle close brackets correctly + # in scan sets, so we specify it separately. + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + my_arg="\"$my_arg\"" + ;; + esac + + func_quote_for_expand_result="$my_arg" +} + + +# func_show_eval cmd [fail_exp] +# Unless opt_silent is true, then output CMD. Then, if opt_dryrun is +# not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP +# is given, then evaluate it. +func_show_eval () +{ + my_cmd="$1" + my_fail_exp="${2-:}" + + ${opt_silent-false} || { + func_quote_for_expand "$my_cmd" + eval "func_echo $func_quote_for_expand_result" + } + + if ${opt_dry_run-false}; then :; else + eval "$my_cmd" + my_status=$? + if test "$my_status" -eq 0; then :; else + eval "(exit $my_status); $my_fail_exp" + fi + fi +} + + +# func_show_eval_locale cmd [fail_exp] +# Unless opt_silent is true, then output CMD. Then, if opt_dryrun is +# not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP +# is given, then evaluate it. Use the saved locale for evaluation. +func_show_eval_locale () +{ + my_cmd="$1" + my_fail_exp="${2-:}" + + ${opt_silent-false} || { + func_quote_for_expand "$my_cmd" + eval "func_echo $func_quote_for_expand_result" + } + + if ${opt_dry_run-false}; then :; else + eval "$lt_user_locale + $my_cmd" + my_status=$? + eval "$lt_safe_locale" + if test "$my_status" -eq 0; then :; else + eval "(exit $my_status); $my_fail_exp" + fi + fi +} + + + + + +# func_version +# Echo version message to standard output and exit. +func_version () +{ + $SED -n '/^# '$PROGRAM' (GNU /,/# warranty; / { + s/^# // + s/^# *$// + s/\((C)\)[ 0-9,-]*\( [1-9][0-9]*\)/\1\2/ + p + }' < "$progpath" + exit $? +} + +# func_usage +# Echo short help message to standard output and exit. +func_usage () +{ + $SED -n '/^# Usage:/,/# -h/ { + s/^# // + s/^# *$// + s/\$progname/'$progname'/ + p + }' < "$progpath" + $ECHO + $ECHO "run \`$progname --help | more' for full usage" + exit $? +} + +# func_help +# Echo long help message to standard output and exit. +func_help () +{ + $SED -n '/^# Usage:/,/# Report bugs to/ { + s/^# // + s/^# *$// + s*\$progname*'$progname'* + s*\$host*'"$host"'* + s*\$SHELL*'"$SHELL"'* + s*\$LTCC*'"$LTCC"'* + s*\$LTCFLAGS*'"$LTCFLAGS"'* + s*\$LD*'"$LD"'* + s/\$with_gnu_ld/'"$with_gnu_ld"'/ + s/\$automake_version/'"`(automake --version) 2>/dev/null |$SED 1q`"'/ + s/\$autoconf_version/'"`(autoconf --version) 2>/dev/null |$SED 1q`"'/ + p + }' < "$progpath" + exit $? +} + +# func_missing_arg argname +# Echo program name prefixed message to standard error and set global +# exit_cmd. +func_missing_arg () +{ + func_error "missing argument for $1" + exit_cmd=exit +} + +exit_cmd=: + + + + + +# Check that we have a working $ECHO. +if test "X$1" = X--no-reexec; then + # Discard the --no-reexec flag, and continue. + shift +elif test "X$1" = X--fallback-echo; then + # Avoid inline document here, it may be left over + : +elif test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t'; then + # Yippee, $ECHO works! + : +else + # Restart under the correct shell, and then maybe $ECHO will work. + exec $SHELL "$progpath" --no-reexec ${1+"$@"} +fi + +if test "X$1" = X--fallback-echo; then + # used as fallback echo + shift + cat </dev/null 2>&1; then + taglist="$taglist $tagname" + + # Evaluate the configuration. Be careful to quote the path + # and the sed script, to avoid splitting on whitespace, but + # also don't use non-portable quotes within backquotes within + # quotes we have to do it in 2 steps: + extractedcf=`$SED -n -e "$sed_extractcf" < "$progpath"` + eval "$extractedcf" + else + func_error "ignoring unknown tag $tagname" + fi + ;; + esac +} + +# Parse options once, thoroughly. This comes as soon as possible in +# the script to make things like `libtool --version' happen quickly. +{ + + # Shorthand for --mode=foo, only valid as the first argument + case $1 in + clean|clea|cle|cl) + shift; set dummy --mode clean ${1+"$@"}; shift + ;; + compile|compil|compi|comp|com|co|c) + shift; set dummy --mode compile ${1+"$@"}; shift + ;; + execute|execut|execu|exec|exe|ex|e) + shift; set dummy --mode execute ${1+"$@"}; shift + ;; + finish|finis|fini|fin|fi|f) + shift; set dummy --mode finish ${1+"$@"}; shift + ;; + install|instal|insta|inst|ins|in|i) + shift; set dummy --mode install ${1+"$@"}; shift + ;; + link|lin|li|l) + shift; set dummy --mode link ${1+"$@"}; shift + ;; + uninstall|uninstal|uninsta|uninst|unins|unin|uni|un|u) + shift; set dummy --mode uninstall ${1+"$@"}; shift + ;; + esac + + # Parse non-mode specific arguments: + while test "$#" -gt 0; do + opt="$1" + shift + + case $opt in + --config) func_config ;; + + --debug) preserve_args="$preserve_args $opt" + func_echo "enabling shell trace mode" + opt_debug='set -x' + $opt_debug + ;; + + -dlopen) test "$#" -eq 0 && func_missing_arg "$opt" && break + execute_dlfiles="$execute_dlfiles $1" + shift + ;; + + --dry-run | -n) opt_dry_run=: ;; + --features) func_features ;; + --finish) mode="finish" ;; + + --mode) test "$#" -eq 0 && func_missing_arg "$opt" && break + case $1 in + # Valid mode arguments: + clean) ;; + compile) ;; + execute) ;; + finish) ;; + install) ;; + link) ;; + relink) ;; + uninstall) ;; + + # Catch anything else as an error + *) func_error "invalid argument for $opt" + exit_cmd=exit + break + ;; + esac + + mode="$1" + shift + ;; + + --preserve-dup-deps) + opt_duplicate_deps=: ;; + + --quiet|--silent) preserve_args="$preserve_args $opt" + opt_silent=: + ;; + + --verbose| -v) preserve_args="$preserve_args $opt" + opt_silent=false + ;; + + --tag) test "$#" -eq 0 && func_missing_arg "$opt" && break + preserve_args="$preserve_args $opt $1" + func_enable_tag "$1" # tagname is set here + shift + ;; + + # Separate optargs to long options: + -dlopen=*|--mode=*|--tag=*) + func_opt_split "$opt" + set dummy "$func_opt_split_opt" "$func_opt_split_arg" ${1+"$@"} + shift + ;; + + -\?|-h) func_usage ;; + --help) opt_help=: ;; + --version) func_version ;; + + -*) func_fatal_help "unrecognized option \`$opt'" ;; + + *) nonopt="$opt" + break + ;; + esac + done + + + case $host in + *cygwin* | *mingw* | *pw32* | *cegcc*) + # don't eliminate duplications in $postdeps and $predeps + opt_duplicate_compiler_generated_deps=: + ;; + *) + opt_duplicate_compiler_generated_deps=$opt_duplicate_deps + ;; + esac + + # Having warned about all mis-specified options, bail out if + # anything was wrong. + $exit_cmd $EXIT_FAILURE +} + +# func_check_version_match +# Ensure that we are using m4 macros, and libtool script from the same +# release of libtool. +func_check_version_match () +{ + if test "$package_revision" != "$macro_revision"; then + if test "$VERSION" != "$macro_version"; then + if test -z "$macro_version"; then + cat >&2 <<_LT_EOF +$progname: Version mismatch error. This is $PACKAGE $VERSION, but the +$progname: definition of this LT_INIT comes from an older release. +$progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION +$progname: and run autoconf again. +_LT_EOF + else + cat >&2 <<_LT_EOF +$progname: Version mismatch error. This is $PACKAGE $VERSION, but the +$progname: definition of this LT_INIT comes from $PACKAGE $macro_version. +$progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION +$progname: and run autoconf again. +_LT_EOF + fi + else + cat >&2 <<_LT_EOF +$progname: Version mismatch error. This is $PACKAGE $VERSION, revision $package_revision, +$progname: but the definition of this LT_INIT comes from revision $macro_revision. +$progname: You should recreate aclocal.m4 with macros from revision $package_revision +$progname: of $PACKAGE $VERSION and run autoconf again. +_LT_EOF + fi + + exit $EXIT_MISMATCH + fi +} + + +## ----------- ## +## Main. ## +## ----------- ## + +$opt_help || { + # Sanity checks first: + func_check_version_match + + if test "$build_libtool_libs" != yes && test "$build_old_libs" != yes; then + func_fatal_configuration "not configured to build any kind of library" + fi + + test -z "$mode" && func_fatal_error "error: you must specify a MODE." + + + # Darwin sucks + eval std_shrext=\"$shrext_cmds\" + + + # Only execute mode is allowed to have -dlopen flags. + if test -n "$execute_dlfiles" && test "$mode" != execute; then + func_error "unrecognized option \`-dlopen'" + $ECHO "$help" 1>&2 + exit $EXIT_FAILURE + fi + + # Change the help message to a mode-specific one. + generic_help="$help" + help="Try \`$progname --help --mode=$mode' for more information." +} + + +# func_lalib_p file +# True iff FILE is a libtool `.la' library or `.lo' object file. +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_lalib_p () +{ + test -f "$1" && + $SED -e 4q "$1" 2>/dev/null \ + | $GREP "^# Generated by .*$PACKAGE" > /dev/null 2>&1 +} + +# func_lalib_unsafe_p file +# True iff FILE is a libtool `.la' library or `.lo' object file. +# This function implements the same check as func_lalib_p without +# resorting to external programs. To this end, it redirects stdin and +# closes it afterwards, without saving the original file descriptor. +# As a safety measure, use it only where a negative result would be +# fatal anyway. Works if `file' does not exist. +func_lalib_unsafe_p () +{ + lalib_p=no + if test -f "$1" && test -r "$1" && exec 5<&0 <"$1"; then + for lalib_p_l in 1 2 3 4 + do + read lalib_p_line + case "$lalib_p_line" in + \#\ Generated\ by\ *$PACKAGE* ) lalib_p=yes; break;; + esac + done + exec 0<&5 5<&- + fi + test "$lalib_p" = yes +} + +# func_ltwrapper_script_p file +# True iff FILE is a libtool wrapper script +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_ltwrapper_script_p () +{ + func_lalib_p "$1" +} + +# func_ltwrapper_executable_p file +# True iff FILE is a libtool wrapper executable +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_ltwrapper_executable_p () +{ + func_ltwrapper_exec_suffix= + case $1 in + *.exe) ;; + *) func_ltwrapper_exec_suffix=.exe ;; + esac + $GREP "$magic_exe" "$1$func_ltwrapper_exec_suffix" >/dev/null 2>&1 +} + +# func_ltwrapper_scriptname file +# Assumes file is an ltwrapper_executable +# uses $file to determine the appropriate filename for a +# temporary ltwrapper_script. +func_ltwrapper_scriptname () +{ + func_ltwrapper_scriptname_result="" + if func_ltwrapper_executable_p "$1"; then + func_dirname_and_basename "$1" "" "." + func_stripname '' '.exe' "$func_basename_result" + func_ltwrapper_scriptname_result="$func_dirname_result/$objdir/${func_stripname_result}_ltshwrapper" + fi +} + +# func_ltwrapper_p file +# True iff FILE is a libtool wrapper script or wrapper executable +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_ltwrapper_p () +{ + func_ltwrapper_script_p "$1" || func_ltwrapper_executable_p "$1" +} + + +# func_execute_cmds commands fail_cmd +# Execute tilde-delimited COMMANDS. +# If FAIL_CMD is given, eval that upon failure. +# FAIL_CMD may read-access the current command in variable CMD! +func_execute_cmds () +{ + $opt_debug + save_ifs=$IFS; IFS='~' + for cmd in $1; do + IFS=$save_ifs + eval cmd=\"$cmd\" + func_show_eval "$cmd" "${2-:}" + done + IFS=$save_ifs +} + + +# func_source file +# Source FILE, adding directory component if necessary. +# Note that it is not necessary on cygwin/mingw to append a dot to +# FILE even if both FILE and FILE.exe exist: automatic-append-.exe +# behavior happens only for exec(3), not for open(2)! Also, sourcing +# `FILE.' does not work on cygwin managed mounts. +func_source () +{ + $opt_debug + case $1 in + */* | *\\*) . "$1" ;; + *) . "./$1" ;; + esac +} + + +# func_infer_tag arg +# Infer tagged configuration to use if any are available and +# if one wasn't chosen via the "--tag" command line option. +# Only attempt this if the compiler in the base compile +# command doesn't match the default compiler. +# arg is usually of the form 'gcc ...' +func_infer_tag () +{ + $opt_debug + if test -n "$available_tags" && test -z "$tagname"; then + CC_quoted= + for arg in $CC; do + func_quote_for_eval "$arg" + CC_quoted="$CC_quoted $func_quote_for_eval_result" + done + case $@ in + # Blanks in the command may have been stripped by the calling shell, + # but not from the CC environment variable when configure was run. + " $CC "* | "$CC "* | " `$ECHO $CC` "* | "`$ECHO $CC` "* | " $CC_quoted"* | "$CC_quoted "* | " `$ECHO $CC_quoted` "* | "`$ECHO $CC_quoted` "*) ;; + # Blanks at the start of $base_compile will cause this to fail + # if we don't check for them as well. + *) + for z in $available_tags; do + if $GREP "^# ### BEGIN LIBTOOL TAG CONFIG: $z$" < "$progpath" > /dev/null; then + # Evaluate the configuration. + eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $progpath`" + CC_quoted= + for arg in $CC; do + # Double-quote args containing other shell metacharacters. + func_quote_for_eval "$arg" + CC_quoted="$CC_quoted $func_quote_for_eval_result" + done + case "$@ " in + " $CC "* | "$CC "* | " `$ECHO $CC` "* | "`$ECHO $CC` "* | " $CC_quoted"* | "$CC_quoted "* | " `$ECHO $CC_quoted` "* | "`$ECHO $CC_quoted` "*) + # The compiler in the base compile command matches + # the one in the tagged configuration. + # Assume this is the tagged configuration we want. + tagname=$z + break + ;; + esac + fi + done + # If $tagname still isn't set, then no tagged configuration + # was found and let the user know that the "--tag" command + # line option must be used. + if test -z "$tagname"; then + func_echo "unable to infer tagged configuration" + func_fatal_error "specify a tag with \`--tag'" +# else +# func_verbose "using $tagname tagged configuration" + fi + ;; + esac + fi +} + + + +# func_write_libtool_object output_name pic_name nonpic_name +# Create a libtool object file (analogous to a ".la" file), +# but don't create it if we're doing a dry run. +func_write_libtool_object () +{ + write_libobj=${1} + if test "$build_libtool_libs" = yes; then + write_lobj=\'${2}\' + else + write_lobj=none + fi + + if test "$build_old_libs" = yes; then + write_oldobj=\'${3}\' + else + write_oldobj=none + fi + + $opt_dry_run || { + cat >${write_libobj}T <?"'"'"' &()|`$[]' \ + && func_warning "libobj name \`$libobj' may not contain shell special characters." + func_dirname_and_basename "$obj" "/" "" + objname="$func_basename_result" + xdir="$func_dirname_result" + lobj=${xdir}$objdir/$objname + + test -z "$base_compile" && \ + func_fatal_help "you must specify a compilation command" + + # Delete any leftover library objects. + if test "$build_old_libs" = yes; then + removelist="$obj $lobj $libobj ${libobj}T" + else + removelist="$lobj $libobj ${libobj}T" + fi + + # On Cygwin there's no "real" PIC flag so we must build both object types + case $host_os in + cygwin* | mingw* | pw32* | os2* | cegcc*) + pic_mode=default + ;; + esac + if test "$pic_mode" = no && test "$deplibs_check_method" != pass_all; then + # non-PIC code in shared libraries is not supported + pic_mode=default + fi + + # Calculate the filename of the output object if compiler does + # not support -o with -c + if test "$compiler_c_o" = no; then + output_obj=`$ECHO "X$srcfile" | $Xsed -e 's%^.*/%%' -e 's%\.[^.]*$%%'`.${objext} + lockfile="$output_obj.lock" + else + output_obj= + need_locks=no + lockfile= + fi + + # Lock this critical section if it is needed + # We use this script file to make the link, it avoids creating a new file + if test "$need_locks" = yes; then + until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do + func_echo "Waiting for $lockfile to be removed" + sleep 2 + done + elif test "$need_locks" = warn; then + if test -f "$lockfile"; then + $ECHO "\ +*** ERROR, $lockfile exists and contains: +`cat $lockfile 2>/dev/null` + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support \`-c' and \`-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $opt_dry_run || $RM $removelist + exit $EXIT_FAILURE + fi + removelist="$removelist $output_obj" + $ECHO "$srcfile" > "$lockfile" + fi + + $opt_dry_run || $RM $removelist + removelist="$removelist $lockfile" + trap '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' 1 2 15 + + if test -n "$fix_srcfile_path"; then + eval srcfile=\"$fix_srcfile_path\" + fi + func_quote_for_eval "$srcfile" + qsrcfile=$func_quote_for_eval_result + + # Only build a PIC object if we are building libtool libraries. + if test "$build_libtool_libs" = yes; then + # Without this assignment, base_compile gets emptied. + fbsd_hideous_sh_bug=$base_compile + + if test "$pic_mode" != no; then + command="$base_compile $qsrcfile $pic_flag" + else + # Don't build PIC code + command="$base_compile $qsrcfile" + fi + + func_mkdir_p "$xdir$objdir" + + if test -z "$output_obj"; then + # Place PIC objects in $objdir + command="$command -o $lobj" + fi + + func_show_eval_locale "$command" \ + 'test -n "$output_obj" && $RM $removelist; exit $EXIT_FAILURE' + + if test "$need_locks" = warn && + test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then + $ECHO "\ +*** ERROR, $lockfile contains: +`cat $lockfile 2>/dev/null` + +but it should contain: +$srcfile + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support \`-c' and \`-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $opt_dry_run || $RM $removelist + exit $EXIT_FAILURE + fi + + # Just move the object if needed, then go on to compile the next one + if test -n "$output_obj" && test "X$output_obj" != "X$lobj"; then + func_show_eval '$MV "$output_obj" "$lobj"' \ + 'error=$?; $opt_dry_run || $RM $removelist; exit $error' + fi + + # Allow error messages only from the first compilation. + if test "$suppress_opt" = yes; then + suppress_output=' >/dev/null 2>&1' + fi + fi + + # Only build a position-dependent object if we build old libraries. + if test "$build_old_libs" = yes; then + if test "$pic_mode" != yes; then + # Don't build PIC code + command="$base_compile $qsrcfile$pie_flag" + else + command="$base_compile $qsrcfile $pic_flag" + fi + if test "$compiler_c_o" = yes; then + command="$command -o $obj" + fi + + # Suppress compiler output if we already did a PIC compilation. + command="$command$suppress_output" + func_show_eval_locale "$command" \ + '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' + + if test "$need_locks" = warn && + test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then + $ECHO "\ +*** ERROR, $lockfile contains: +`cat $lockfile 2>/dev/null` + +but it should contain: +$srcfile + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support \`-c' and \`-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $opt_dry_run || $RM $removelist + exit $EXIT_FAILURE + fi + + # Just move the object if needed + if test -n "$output_obj" && test "X$output_obj" != "X$obj"; then + func_show_eval '$MV "$output_obj" "$obj"' \ + 'error=$?; $opt_dry_run || $RM $removelist; exit $error' + fi + fi + + $opt_dry_run || { + func_write_libtool_object "$libobj" "$objdir/$objname" "$objname" + + # Unlock the critical section if it was locked + if test "$need_locks" != no; then + removelist=$lockfile + $RM "$lockfile" + fi + } + + exit $EXIT_SUCCESS +} + +$opt_help || { +test "$mode" = compile && func_mode_compile ${1+"$@"} +} + +func_mode_help () +{ + # We need to display help for each of the modes. + case $mode in + "") + # Generic help is extracted from the usage comments + # at the start of this file. + func_help + ;; + + clean) + $ECHO \ +"Usage: $progname [OPTION]... --mode=clean RM [RM-OPTION]... FILE... + +Remove files from the build directory. + +RM is the name of the program to use to delete files associated with each FILE +(typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed +to RM. + +If FILE is a libtool library, object or program, all the files associated +with it are deleted. Otherwise, only FILE itself is deleted using RM." + ;; + + compile) + $ECHO \ +"Usage: $progname [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE + +Compile a source file into a libtool library object. + +This mode accepts the following additional options: + + -o OUTPUT-FILE set the output file name to OUTPUT-FILE + -no-suppress do not suppress compiler output for multiple passes + -prefer-pic try to building PIC objects only + -prefer-non-pic try to building non-PIC objects only + -shared do not build a \`.o' file suitable for static linking + -static only build a \`.o' file suitable for static linking + +COMPILE-COMMAND is a command to be used in creating a \`standard' object file +from the given SOURCEFILE. + +The output file name is determined by removing the directory component from +SOURCEFILE, then substituting the C source code suffix \`.c' with the +library object suffix, \`.lo'." + ;; + + execute) + $ECHO \ +"Usage: $progname [OPTION]... --mode=execute COMMAND [ARGS]... + +Automatically set library path, then run a program. + +This mode accepts the following additional options: + + -dlopen FILE add the directory containing FILE to the library path + +This mode sets the library path environment variable according to \`-dlopen' +flags. + +If any of the ARGS are libtool executable wrappers, then they are translated +into their corresponding uninstalled binary, and any of their required library +directories are added to the library path. + +Then, COMMAND is executed, with ARGS as arguments." + ;; + + finish) + $ECHO \ +"Usage: $progname [OPTION]... --mode=finish [LIBDIR]... + +Complete the installation of libtool libraries. + +Each LIBDIR is a directory that contains libtool libraries. + +The commands that this mode executes may require superuser privileges. Use +the \`--dry-run' option if you just want to see what would be executed." + ;; + + install) + $ECHO \ +"Usage: $progname [OPTION]... --mode=install INSTALL-COMMAND... + +Install executables or libraries. + +INSTALL-COMMAND is the installation command. The first component should be +either the \`install' or \`cp' program. + +The following components of INSTALL-COMMAND are treated specially: + + -inst-prefix PREFIX-DIR Use PREFIX-DIR as a staging area for installation + +The rest of the components are interpreted as arguments to that command (only +BSD-compatible install options are recognized)." + ;; + + link) + $ECHO \ +"Usage: $progname [OPTION]... --mode=link LINK-COMMAND... + +Link object files or libraries together to form another library, or to +create an executable program. + +LINK-COMMAND is a command using the C compiler that you would use to create +a program from several object files. + +The following components of LINK-COMMAND are treated specially: + + -all-static do not do any dynamic linking at all + -avoid-version do not add a version suffix if possible + -dlopen FILE \`-dlpreopen' FILE if it cannot be dlopened at runtime + -dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols + -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3) + -export-symbols SYMFILE + try to export only the symbols listed in SYMFILE + -export-symbols-regex REGEX + try to export only the symbols matching REGEX + -LLIBDIR search LIBDIR for required installed libraries + -lNAME OUTPUT-FILE requires the installed library libNAME + -module build a library that can dlopened + -no-fast-install disable the fast-install mode + -no-install link a not-installable executable + -no-undefined declare that a library does not refer to external symbols + -o OUTPUT-FILE create OUTPUT-FILE from the specified objects + -objectlist FILE Use a list of object files found in FILE to specify objects + -precious-files-regex REGEX + don't remove output files matching REGEX + -release RELEASE specify package release information + -rpath LIBDIR the created library will eventually be installed in LIBDIR + -R[ ]LIBDIR add LIBDIR to the runtime path of programs and libraries + -shared only do dynamic linking of libtool libraries + -shrext SUFFIX override the standard shared library file extension + -static do not do any dynamic linking of uninstalled libtool libraries + -static-libtool-libs + do not do any dynamic linking of libtool libraries + -version-info CURRENT[:REVISION[:AGE]] + specify library version info [each variable defaults to 0] + -weak LIBNAME declare that the target provides the LIBNAME interface + +All other options (arguments beginning with \`-') are ignored. + +Every other argument is treated as a filename. Files ending in \`.la' are +treated as uninstalled libtool libraries, other files are standard or library +object files. + +If the OUTPUT-FILE ends in \`.la', then a libtool library is created, +only library objects (\`.lo' files) may be specified, and \`-rpath' is +required, except when creating a convenience library. + +If OUTPUT-FILE ends in \`.a' or \`.lib', then a standard library is created +using \`ar' and \`ranlib', or on Windows using \`lib'. + +If OUTPUT-FILE ends in \`.lo' or \`.${objext}', then a reloadable object file +is created, otherwise an executable program is created." + ;; + + uninstall) + $ECHO \ +"Usage: $progname [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE... + +Remove libraries from an installation directory. + +RM is the name of the program to use to delete files associated with each FILE +(typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed +to RM. + +If FILE is a libtool library, all the files associated with it are deleted. +Otherwise, only FILE itself is deleted using RM." + ;; + + *) + func_fatal_help "invalid operation mode \`$mode'" + ;; + esac + + $ECHO + $ECHO "Try \`$progname --help' for more information about other modes." + + exit $? +} + + # Now that we've collected a possible --mode arg, show help if necessary + $opt_help && func_mode_help + + +# func_mode_execute arg... +func_mode_execute () +{ + $opt_debug + # The first argument is the command name. + cmd="$nonopt" + test -z "$cmd" && \ + func_fatal_help "you must specify a COMMAND" + + # Handle -dlopen flags immediately. + for file in $execute_dlfiles; do + test -f "$file" \ + || func_fatal_help "\`$file' is not a file" + + dir= + case $file in + *.la) + # Check to see that this really is a libtool archive. + func_lalib_unsafe_p "$file" \ + || func_fatal_help "\`$lib' is not a valid libtool archive" + + # Read the libtool library. + dlname= + library_names= + func_source "$file" + + # Skip this library if it cannot be dlopened. + if test -z "$dlname"; then + # Warn if it was a shared library. + test -n "$library_names" && \ + func_warning "\`$file' was not linked with \`-export-dynamic'" + continue + fi + + func_dirname "$file" "" "." + dir="$func_dirname_result" + + if test -f "$dir/$objdir/$dlname"; then + dir="$dir/$objdir" + else + if test ! -f "$dir/$dlname"; then + func_fatal_error "cannot find \`$dlname' in \`$dir' or \`$dir/$objdir'" + fi + fi + ;; + + *.lo) + # Just add the directory containing the .lo file. + func_dirname "$file" "" "." + dir="$func_dirname_result" + ;; + + *) + func_warning "\`-dlopen' is ignored for non-libtool libraries and objects" + continue + ;; + esac + + # Get the absolute pathname. + absdir=`cd "$dir" && pwd` + test -n "$absdir" && dir="$absdir" + + # Now add the directory to shlibpath_var. + if eval "test -z \"\$$shlibpath_var\""; then + eval "$shlibpath_var=\"\$dir\"" + else + eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\"" + fi + done + + # This variable tells wrapper scripts just to set shlibpath_var + # rather than running their programs. + libtool_execute_magic="$magic" + + # Check if any of the arguments is a wrapper script. + args= + for file + do + case $file in + -*) ;; + *) + # Do a test to see if this is really a libtool program. + if func_ltwrapper_script_p "$file"; then + func_source "$file" + # Transform arg to wrapped name. + file="$progdir/$program" + elif func_ltwrapper_executable_p "$file"; then + func_ltwrapper_scriptname "$file" + func_source "$func_ltwrapper_scriptname_result" + # Transform arg to wrapped name. + file="$progdir/$program" + fi + ;; + esac + # Quote arguments (to preserve shell metacharacters). + func_quote_for_eval "$file" + args="$args $func_quote_for_eval_result" + done + + if test "X$opt_dry_run" = Xfalse; then + if test -n "$shlibpath_var"; then + # Export the shlibpath_var. + eval "export $shlibpath_var" + fi + + # Restore saved environment variables + for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES + do + eval "if test \"\${save_$lt_var+set}\" = set; then + $lt_var=\$save_$lt_var; export $lt_var + else + $lt_unset $lt_var + fi" + done + + # Now prepare to actually exec the command. + exec_cmd="\$cmd$args" + else + # Display what would be done. + if test -n "$shlibpath_var"; then + eval "\$ECHO \"\$shlibpath_var=\$$shlibpath_var\"" + $ECHO "export $shlibpath_var" + fi + $ECHO "$cmd$args" + exit $EXIT_SUCCESS + fi +} + +test "$mode" = execute && func_mode_execute ${1+"$@"} + + +# func_mode_finish arg... +func_mode_finish () +{ + $opt_debug + libdirs="$nonopt" + admincmds= + + if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then + for dir + do + libdirs="$libdirs $dir" + done + + for libdir in $libdirs; do + if test -n "$finish_cmds"; then + # Do each command in the finish commands. + func_execute_cmds "$finish_cmds" 'admincmds="$admincmds +'"$cmd"'"' + fi + if test -n "$finish_eval"; then + # Do the single finish_eval. + eval cmds=\"$finish_eval\" + $opt_dry_run || eval "$cmds" || admincmds="$admincmds + $cmds" + fi + done + fi + + # Exit here if they wanted silent mode. + $opt_silent && exit $EXIT_SUCCESS + + $ECHO "X----------------------------------------------------------------------" | $Xsed + $ECHO "Libraries have been installed in:" + for libdir in $libdirs; do + $ECHO " $libdir" + done + $ECHO + $ECHO "If you ever happen to want to link against installed libraries" + $ECHO "in a given directory, LIBDIR, you must either use libtool, and" + $ECHO "specify the full pathname of the library, or use the \`-LLIBDIR'" + $ECHO "flag during linking and do at least one of the following:" + if test -n "$shlibpath_var"; then + $ECHO " - add LIBDIR to the \`$shlibpath_var' environment variable" + $ECHO " during execution" + fi + if test -n "$runpath_var"; then + $ECHO " - add LIBDIR to the \`$runpath_var' environment variable" + $ECHO " during linking" + fi + if test -n "$hardcode_libdir_flag_spec"; then + libdir=LIBDIR + eval flag=\"$hardcode_libdir_flag_spec\" + + $ECHO " - use the \`$flag' linker flag" + fi + if test -n "$admincmds"; then + $ECHO " - have your system administrator run these commands:$admincmds" + fi + if test -f /etc/ld.so.conf; then + $ECHO " - have your system administrator add LIBDIR to \`/etc/ld.so.conf'" + fi + $ECHO + + $ECHO "See any operating system documentation about shared libraries for" + case $host in + solaris2.[6789]|solaris2.1[0-9]) + $ECHO "more information, such as the ld(1), crle(1) and ld.so(8) manual" + $ECHO "pages." + ;; + *) + $ECHO "more information, such as the ld(1) and ld.so(8) manual pages." + ;; + esac + $ECHO "X----------------------------------------------------------------------" | $Xsed + exit $EXIT_SUCCESS +} + +test "$mode" = finish && func_mode_finish ${1+"$@"} + + +# func_mode_install arg... +func_mode_install () +{ + $opt_debug + # There may be an optional sh(1) argument at the beginning of + # install_prog (especially on Windows NT). + if test "$nonopt" = "$SHELL" || test "$nonopt" = /bin/sh || + # Allow the use of GNU shtool's install command. + $ECHO "X$nonopt" | $GREP shtool >/dev/null; then + # Aesthetically quote it. + func_quote_for_eval "$nonopt" + install_prog="$func_quote_for_eval_result " + arg=$1 + shift + else + install_prog= + arg=$nonopt + fi + + # The real first argument should be the name of the installation program. + # Aesthetically quote it. + func_quote_for_eval "$arg" + install_prog="$install_prog$func_quote_for_eval_result" + + # We need to accept at least all the BSD install flags. + dest= + files= + opts= + prev= + install_type= + isdir=no + stripme= + for arg + do + if test -n "$dest"; then + files="$files $dest" + dest=$arg + continue + fi + + case $arg in + -d) isdir=yes ;; + -f) + case " $install_prog " in + *[\\\ /]cp\ *) ;; + *) prev=$arg ;; + esac + ;; + -g | -m | -o) + prev=$arg + ;; + -s) + stripme=" -s" + continue + ;; + -*) + ;; + *) + # If the previous option needed an argument, then skip it. + if test -n "$prev"; then + prev= + else + dest=$arg + continue + fi + ;; + esac + + # Aesthetically quote the argument. + func_quote_for_eval "$arg" + install_prog="$install_prog $func_quote_for_eval_result" + done + + test -z "$install_prog" && \ + func_fatal_help "you must specify an install program" + + test -n "$prev" && \ + func_fatal_help "the \`$prev' option requires an argument" + + if test -z "$files"; then + if test -z "$dest"; then + func_fatal_help "no file or destination specified" + else + func_fatal_help "you must specify a destination" + fi + fi + + # Strip any trailing slash from the destination. + func_stripname '' '/' "$dest" + dest=$func_stripname_result + + # Check to see that the destination is a directory. + test -d "$dest" && isdir=yes + if test "$isdir" = yes; then + destdir="$dest" + destname= + else + func_dirname_and_basename "$dest" "" "." + destdir="$func_dirname_result" + destname="$func_basename_result" + + # Not a directory, so check to see that there is only one file specified. + set dummy $files; shift + test "$#" -gt 1 && \ + func_fatal_help "\`$dest' is not a directory" + fi + case $destdir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + for file in $files; do + case $file in + *.lo) ;; + *) + func_fatal_help "\`$destdir' must be an absolute directory name" + ;; + esac + done + ;; + esac + + # This variable tells wrapper scripts just to set variables rather + # than running their programs. + libtool_install_magic="$magic" + + staticlibs= + future_libdirs= + current_libdirs= + for file in $files; do + + # Do each installation. + case $file in + *.$libext) + # Do the static libraries later. + staticlibs="$staticlibs $file" + ;; + + *.la) + # Check to see that this really is a libtool archive. + func_lalib_unsafe_p "$file" \ + || func_fatal_help "\`$file' is not a valid libtool archive" + + library_names= + old_library= + relink_command= + func_source "$file" + + # Add the libdir to current_libdirs if it is the destination. + if test "X$destdir" = "X$libdir"; then + case "$current_libdirs " in + *" $libdir "*) ;; + *) current_libdirs="$current_libdirs $libdir" ;; + esac + else + # Note the libdir as a future libdir. + case "$future_libdirs " in + *" $libdir "*) ;; + *) future_libdirs="$future_libdirs $libdir" ;; + esac + fi + + func_dirname "$file" "/" "" + dir="$func_dirname_result" + dir="$dir$objdir" + + if test -n "$relink_command"; then + # Determine the prefix the user has applied to our future dir. + inst_prefix_dir=`$ECHO "X$destdir" | $Xsed -e "s%$libdir\$%%"` + + # Don't allow the user to place us outside of our expected + # location b/c this prevents finding dependent libraries that + # are installed to the same prefix. + # At present, this check doesn't affect windows .dll's that + # are installed into $libdir/../bin (currently, that works fine) + # but it's something to keep an eye on. + test "$inst_prefix_dir" = "$destdir" && \ + func_fatal_error "error: cannot install \`$file' to a directory not ending in $libdir" + + if test -n "$inst_prefix_dir"; then + # Stick the inst_prefix_dir data into the link command. + relink_command=`$ECHO "X$relink_command" | $Xsed -e "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"` + else + relink_command=`$ECHO "X$relink_command" | $Xsed -e "s%@inst_prefix_dir@%%"` + fi + + func_warning "relinking \`$file'" + func_show_eval "$relink_command" \ + 'func_fatal_error "error: relink \`$file'\'' with the above command before installing it"' + fi + + # See the names of the shared library. + set dummy $library_names; shift + if test -n "$1"; then + realname="$1" + shift + + srcname="$realname" + test -n "$relink_command" && srcname="$realname"T + + # Install the shared library and build the symlinks. + func_show_eval "$install_prog $dir/$srcname $destdir/$realname" \ + 'exit $?' + tstripme="$stripme" + case $host_os in + cygwin* | mingw* | pw32* | cegcc*) + case $realname in + *.dll.a) + tstripme="" + ;; + esac + ;; + esac + if test -n "$tstripme" && test -n "$striplib"; then + func_show_eval "$striplib $destdir/$realname" 'exit $?' + fi + + if test "$#" -gt 0; then + # Delete the old symlinks, and create new ones. + # Try `ln -sf' first, because the `ln' binary might depend on + # the symlink we replace! Solaris /bin/ln does not understand -f, + # so we also need to try rm && ln -s. + for linkname + do + test "$linkname" != "$realname" \ + && func_show_eval "(cd $destdir && { $LN_S -f $realname $linkname || { $RM $linkname && $LN_S $realname $linkname; }; })" + done + fi + + # Do each command in the postinstall commands. + lib="$destdir/$realname" + func_execute_cmds "$postinstall_cmds" 'exit $?' + fi + + # Install the pseudo-library for information purposes. + func_basename "$file" + name="$func_basename_result" + instname="$dir/$name"i + func_show_eval "$install_prog $instname $destdir/$name" 'exit $?' + + # Maybe install the static library, too. + test -n "$old_library" && staticlibs="$staticlibs $dir/$old_library" + ;; + + *.lo) + # Install (i.e. copy) a libtool object. + + # Figure out destination file name, if it wasn't already specified. + if test -n "$destname"; then + destfile="$destdir/$destname" + else + func_basename "$file" + destfile="$func_basename_result" + destfile="$destdir/$destfile" + fi + + # Deduce the name of the destination old-style object file. + case $destfile in + *.lo) + func_lo2o "$destfile" + staticdest=$func_lo2o_result + ;; + *.$objext) + staticdest="$destfile" + destfile= + ;; + *) + func_fatal_help "cannot copy a libtool object to \`$destfile'" + ;; + esac + + # Install the libtool object if requested. + test -n "$destfile" && \ + func_show_eval "$install_prog $file $destfile" 'exit $?' + + # Install the old object if enabled. + if test "$build_old_libs" = yes; then + # Deduce the name of the old-style object file. + func_lo2o "$file" + staticobj=$func_lo2o_result + func_show_eval "$install_prog \$staticobj \$staticdest" 'exit $?' + fi + exit $EXIT_SUCCESS + ;; + + *) + # Figure out destination file name, if it wasn't already specified. + if test -n "$destname"; then + destfile="$destdir/$destname" + else + func_basename "$file" + destfile="$func_basename_result" + destfile="$destdir/$destfile" + fi + + # If the file is missing, and there is a .exe on the end, strip it + # because it is most likely a libtool script we actually want to + # install + stripped_ext="" + case $file in + *.exe) + if test ! -f "$file"; then + func_stripname '' '.exe' "$file" + file=$func_stripname_result + stripped_ext=".exe" + fi + ;; + esac + + # Do a test to see if this is really a libtool program. + case $host in + *cygwin* | *mingw*) + if func_ltwrapper_executable_p "$file"; then + func_ltwrapper_scriptname "$file" + wrapper=$func_ltwrapper_scriptname_result + else + func_stripname '' '.exe' "$file" + wrapper=$func_stripname_result + fi + ;; + *) + wrapper=$file + ;; + esac + if func_ltwrapper_script_p "$wrapper"; then + notinst_deplibs= + relink_command= + + func_source "$wrapper" + + # Check the variables that should have been set. + test -z "$generated_by_libtool_version" && \ + func_fatal_error "invalid libtool wrapper script \`$wrapper'" + + finalize=yes + for lib in $notinst_deplibs; do + # Check to see that each library is installed. + libdir= + if test -f "$lib"; then + func_source "$lib" + fi + libfile="$libdir/"`$ECHO "X$lib" | $Xsed -e 's%^.*/%%g'` ### testsuite: skip nested quoting test + if test -n "$libdir" && test ! -f "$libfile"; then + func_warning "\`$lib' has not been installed in \`$libdir'" + finalize=no + fi + done + + relink_command= + func_source "$wrapper" + + outputname= + if test "$fast_install" = no && test -n "$relink_command"; then + $opt_dry_run || { + if test "$finalize" = yes; then + tmpdir=`func_mktempdir` + func_basename "$file$stripped_ext" + file="$func_basename_result" + outputname="$tmpdir/$file" + # Replace the output file specification. + relink_command=`$ECHO "X$relink_command" | $Xsed -e 's%@OUTPUT@%'"$outputname"'%g'` + + $opt_silent || { + func_quote_for_expand "$relink_command" + eval "func_echo $func_quote_for_expand_result" + } + if eval "$relink_command"; then : + else + func_error "error: relink \`$file' with the above command before installing it" + $opt_dry_run || ${RM}r "$tmpdir" + continue + fi + file="$outputname" + else + func_warning "cannot relink \`$file'" + fi + } + else + # Install the binary that we compiled earlier. + file=`$ECHO "X$file$stripped_ext" | $Xsed -e "s%\([^/]*\)$%$objdir/\1%"` + fi + fi + + # remove .exe since cygwin /usr/bin/install will append another + # one anyway + case $install_prog,$host in + */usr/bin/install*,*cygwin*) + case $file:$destfile in + *.exe:*.exe) + # this is ok + ;; + *.exe:*) + destfile=$destfile.exe + ;; + *:*.exe) + func_stripname '' '.exe' "$destfile" + destfile=$func_stripname_result + ;; + esac + ;; + esac + func_show_eval "$install_prog\$stripme \$file \$destfile" 'exit $?' + $opt_dry_run || if test -n "$outputname"; then + ${RM}r "$tmpdir" + fi + ;; + esac + done + + for file in $staticlibs; do + func_basename "$file" + name="$func_basename_result" + + # Set up the ranlib parameters. + oldlib="$destdir/$name" + + func_show_eval "$install_prog \$file \$oldlib" 'exit $?' + + if test -n "$stripme" && test -n "$old_striplib"; then + func_show_eval "$old_striplib $oldlib" 'exit $?' + fi + + # Do each command in the postinstall commands. + func_execute_cmds "$old_postinstall_cmds" 'exit $?' + done + + test -n "$future_libdirs" && \ + func_warning "remember to run \`$progname --finish$future_libdirs'" + + if test -n "$current_libdirs"; then + # Maybe just do a dry run. + $opt_dry_run && current_libdirs=" -n$current_libdirs" + exec_cmd='$SHELL $progpath $preserve_args --finish$current_libdirs' + else + exit $EXIT_SUCCESS + fi +} + +test "$mode" = install && func_mode_install ${1+"$@"} + + +# func_generate_dlsyms outputname originator pic_p +# Extract symbols from dlprefiles and create ${outputname}S.o with +# a dlpreopen symbol table. +func_generate_dlsyms () +{ + $opt_debug + my_outputname="$1" + my_originator="$2" + my_pic_p="${3-no}" + my_prefix=`$ECHO "$my_originator" | sed 's%[^a-zA-Z0-9]%_%g'` + my_dlsyms= + + if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then + if test -n "$NM" && test -n "$global_symbol_pipe"; then + my_dlsyms="${my_outputname}S.c" + else + func_error "not configured to extract global symbols from dlpreopened files" + fi + fi + + if test -n "$my_dlsyms"; then + case $my_dlsyms in + "") ;; + *.c) + # Discover the nlist of each of the dlfiles. + nlist="$output_objdir/${my_outputname}.nm" + + func_show_eval "$RM $nlist ${nlist}S ${nlist}T" + + # Parse the name list into a source file. + func_verbose "creating $output_objdir/$my_dlsyms" + + $opt_dry_run || $ECHO > "$output_objdir/$my_dlsyms" "\ +/* $my_dlsyms - symbol resolution table for \`$my_outputname' dlsym emulation. */ +/* Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION */ + +#ifdef __cplusplus +extern \"C\" { +#endif + +/* External symbol declarations for the compiler. */\ +" + + if test "$dlself" = yes; then + func_verbose "generating symbol list for \`$output'" + + $opt_dry_run || echo ': @PROGRAM@ ' > "$nlist" + + # Add our own program objects to the symbol list. + progfiles=`$ECHO "X$objs$old_deplibs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` + for progfile in $progfiles; do + func_verbose "extracting global C symbols from \`$progfile'" + $opt_dry_run || eval "$NM $progfile | $global_symbol_pipe >> '$nlist'" + done + + if test -n "$exclude_expsyms"; then + $opt_dry_run || { + eval '$EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T' + eval '$MV "$nlist"T "$nlist"' + } + fi + + if test -n "$export_symbols_regex"; then + $opt_dry_run || { + eval '$EGREP -e "$export_symbols_regex" "$nlist" > "$nlist"T' + eval '$MV "$nlist"T "$nlist"' + } + fi + + # Prepare the list of exported symbols + if test -z "$export_symbols"; then + export_symbols="$output_objdir/$outputname.exp" + $opt_dry_run || { + $RM $export_symbols + eval "${SED} -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"' + case $host in + *cygwin* | *mingw* | *cegcc* ) + eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' + eval 'cat "$export_symbols" >> "$output_objdir/$outputname.def"' + ;; + esac + } + else + $opt_dry_run || { + eval "${SED} -e 's/\([].[*^$]\)/\\\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$outputname.exp"' + eval '$GREP -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T' + eval '$MV "$nlist"T "$nlist"' + case $host in + *cygwin | *mingw* | *cegcc* ) + eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' + eval 'cat "$nlist" >> "$output_objdir/$outputname.def"' + ;; + esac + } + fi + fi + + for dlprefile in $dlprefiles; do + func_verbose "extracting global C symbols from \`$dlprefile'" + func_basename "$dlprefile" + name="$func_basename_result" + $opt_dry_run || { + eval '$ECHO ": $name " >> "$nlist"' + eval "$NM $dlprefile 2>/dev/null | $global_symbol_pipe >> '$nlist'" + } + done + + $opt_dry_run || { + # Make sure we have at least an empty file. + test -f "$nlist" || : > "$nlist" + + if test -n "$exclude_expsyms"; then + $EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T + $MV "$nlist"T "$nlist" + fi + + # Try sorting and uniquifying the output. + if $GREP -v "^: " < "$nlist" | + if sort -k 3 /dev/null 2>&1; then + sort -k 3 + else + sort +2 + fi | + uniq > "$nlist"S; then + : + else + $GREP -v "^: " < "$nlist" > "$nlist"S + fi + + if test -f "$nlist"S; then + eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$my_dlsyms"' + else + $ECHO '/* NONE */' >> "$output_objdir/$my_dlsyms" + fi + + $ECHO >> "$output_objdir/$my_dlsyms" "\ + +/* The mapping between symbol names and symbols. */ +typedef struct { + const char *name; + void *address; +} lt_dlsymlist; +" + case $host in + *cygwin* | *mingw* | *cegcc* ) + $ECHO >> "$output_objdir/$my_dlsyms" "\ +/* DATA imports from DLLs on WIN32 con't be const, because + runtime relocations are performed -- see ld's documentation + on pseudo-relocs. */" + lt_dlsym_const= ;; + *osf5*) + echo >> "$output_objdir/$my_dlsyms" "\ +/* This system does not cope well with relocations in const data */" + lt_dlsym_const= ;; + *) + lt_dlsym_const=const ;; + esac + + $ECHO >> "$output_objdir/$my_dlsyms" "\ +extern $lt_dlsym_const lt_dlsymlist +lt_${my_prefix}_LTX_preloaded_symbols[]; +$lt_dlsym_const lt_dlsymlist +lt_${my_prefix}_LTX_preloaded_symbols[] = +{\ + { \"$my_originator\", (void *) 0 }," + + case $need_lib_prefix in + no) + eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$my_dlsyms" + ;; + *) + eval "$global_symbol_to_c_name_address_lib_prefix" < "$nlist" >> "$output_objdir/$my_dlsyms" + ;; + esac + $ECHO >> "$output_objdir/$my_dlsyms" "\ + {0, (void *) 0} +}; + +/* This works around a problem in FreeBSD linker */ +#ifdef FREEBSD_WORKAROUND +static const void *lt_preloaded_setup() { + return lt_${my_prefix}_LTX_preloaded_symbols; +} +#endif + +#ifdef __cplusplus +} +#endif\ +" + } # !$opt_dry_run + + pic_flag_for_symtable= + case "$compile_command " in + *" -static "*) ;; + *) + case $host in + # compiling the symbol table file with pic_flag works around + # a FreeBSD bug that causes programs to crash when -lm is + # linked before any other PIC object. But we must not use + # pic_flag when linking with -static. The problem exists in + # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1. + *-*-freebsd2*|*-*-freebsd3.0*|*-*-freebsdelf3.0*) + pic_flag_for_symtable=" $pic_flag -DFREEBSD_WORKAROUND" ;; + *-*-hpux*) + pic_flag_for_symtable=" $pic_flag" ;; + *) + if test "X$my_pic_p" != Xno; then + pic_flag_for_symtable=" $pic_flag" + fi + ;; + esac + ;; + esac + symtab_cflags= + for arg in $LTCFLAGS; do + case $arg in + -pie | -fpie | -fPIE) ;; + *) symtab_cflags="$symtab_cflags $arg" ;; + esac + done + + # Now compile the dynamic symbol file. + func_show_eval '(cd $output_objdir && $LTCC$symtab_cflags -c$no_builtin_flag$pic_flag_for_symtable "$my_dlsyms")' 'exit $?' + + # Clean up the generated files. + func_show_eval '$RM "$output_objdir/$my_dlsyms" "$nlist" "${nlist}S" "${nlist}T"' + + # Transform the symbol file into the correct name. + symfileobj="$output_objdir/${my_outputname}S.$objext" + case $host in + *cygwin* | *mingw* | *cegcc* ) + if test -f "$output_objdir/$my_outputname.def"; then + compile_command=`$ECHO "X$compile_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` + finalize_command=`$ECHO "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` + else + compile_command=`$ECHO "X$compile_command" | $Xsed -e "s%@SYMFILE@%$symfileobj%"` + finalize_command=`$ECHO "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$symfileobj%"` + fi + ;; + *) + compile_command=`$ECHO "X$compile_command" | $Xsed -e "s%@SYMFILE@%$symfileobj%"` + finalize_command=`$ECHO "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$symfileobj%"` + ;; + esac + ;; + *) + func_fatal_error "unknown suffix for \`$my_dlsyms'" + ;; + esac + else + # We keep going just in case the user didn't refer to + # lt_preloaded_symbols. The linker will fail if global_symbol_pipe + # really was required. + + # Nullify the symbol file. + compile_command=`$ECHO "X$compile_command" | $Xsed -e "s% @SYMFILE@%%"` + finalize_command=`$ECHO "X$finalize_command" | $Xsed -e "s% @SYMFILE@%%"` + fi +} + +# func_win32_libid arg +# return the library type of file 'arg' +# +# Need a lot of goo to handle *both* DLLs and import libs +# Has to be a shell function in order to 'eat' the argument +# that is supplied when $file_magic_command is called. +func_win32_libid () +{ + $opt_debug + win32_libid_type="unknown" + win32_fileres=`file -L $1 2>/dev/null` + case $win32_fileres in + *ar\ archive\ import\ library*) # definitely import + win32_libid_type="x86 archive import" + ;; + *ar\ archive*) # could be an import, or static + if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null | + $EGREP 'file format pe-i386(.*architecture: i386)?' >/dev/null ; then + win32_nmres=`eval $NM -f posix -A $1 | + $SED -n -e ' + 1,100{ + / I /{ + s,.*,import, + p + q + } + }'` + case $win32_nmres in + import*) win32_libid_type="x86 archive import";; + *) win32_libid_type="x86 archive static";; + esac + fi + ;; + *DLL*) + win32_libid_type="x86 DLL" + ;; + *executable*) # but shell scripts are "executable" too... + case $win32_fileres in + *MS\ Windows\ PE\ Intel*) + win32_libid_type="x86 DLL" + ;; + esac + ;; + esac + $ECHO "$win32_libid_type" +} + + + +# func_extract_an_archive dir oldlib +func_extract_an_archive () +{ + $opt_debug + f_ex_an_ar_dir="$1"; shift + f_ex_an_ar_oldlib="$1" + func_show_eval "(cd \$f_ex_an_ar_dir && $AR x \"\$f_ex_an_ar_oldlib\")" 'exit $?' + if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then + : + else + func_fatal_error "object name conflicts in archive: $f_ex_an_ar_dir/$f_ex_an_ar_oldlib" + fi +} + + +# func_extract_archives gentop oldlib ... +func_extract_archives () +{ + $opt_debug + my_gentop="$1"; shift + my_oldlibs=${1+"$@"} + my_oldobjs="" + my_xlib="" + my_xabs="" + my_xdir="" + + for my_xlib in $my_oldlibs; do + # Extract the objects. + case $my_xlib in + [\\/]* | [A-Za-z]:[\\/]*) my_xabs="$my_xlib" ;; + *) my_xabs=`pwd`"/$my_xlib" ;; + esac + func_basename "$my_xlib" + my_xlib="$func_basename_result" + my_xlib_u=$my_xlib + while :; do + case " $extracted_archives " in + *" $my_xlib_u "*) + func_arith $extracted_serial + 1 + extracted_serial=$func_arith_result + my_xlib_u=lt$extracted_serial-$my_xlib ;; + *) break ;; + esac + done + extracted_archives="$extracted_archives $my_xlib_u" + my_xdir="$my_gentop/$my_xlib_u" + + func_mkdir_p "$my_xdir" + + case $host in + *-darwin*) + func_verbose "Extracting $my_xabs" + # Do not bother doing anything if just a dry run + $opt_dry_run || { + darwin_orig_dir=`pwd` + cd $my_xdir || exit $? + darwin_archive=$my_xabs + darwin_curdir=`pwd` + darwin_base_archive=`basename "$darwin_archive"` + darwin_arches=`$LIPO -info "$darwin_archive" 2>/dev/null | $GREP Architectures 2>/dev/null || true` + if test -n "$darwin_arches"; then + darwin_arches=`$ECHO "$darwin_arches" | $SED -e 's/.*are://'` + darwin_arch= + func_verbose "$darwin_base_archive has multiple architectures $darwin_arches" + for darwin_arch in $darwin_arches ; do + func_mkdir_p "unfat-$$/${darwin_base_archive}-${darwin_arch}" + $LIPO -thin $darwin_arch -output "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" "${darwin_archive}" + cd "unfat-$$/${darwin_base_archive}-${darwin_arch}" + func_extract_an_archive "`pwd`" "${darwin_base_archive}" + cd "$darwin_curdir" + $RM "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" + done # $darwin_arches + ## Okay now we've a bunch of thin objects, gotta fatten them up :) + darwin_filelist=`find unfat-$$ -type f -name \*.o -print -o -name \*.lo -print | $SED -e "$basename" | sort -u` + darwin_file= + darwin_files= + for darwin_file in $darwin_filelist; do + darwin_files=`find unfat-$$ -name $darwin_file -print | $NL2SP` + $LIPO -create -output "$darwin_file" $darwin_files + done # $darwin_filelist + $RM -rf unfat-$$ + cd "$darwin_orig_dir" + else + cd $darwin_orig_dir + func_extract_an_archive "$my_xdir" "$my_xabs" + fi # $darwin_arches + } # !$opt_dry_run + ;; + *) + func_extract_an_archive "$my_xdir" "$my_xabs" + ;; + esac + my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | $NL2SP` + done + + func_extract_archives_result="$my_oldobjs" +} + + + +# func_emit_wrapper_part1 [arg=no] +# +# Emit the first part of a libtool wrapper script on stdout. +# For more information, see the description associated with +# func_emit_wrapper(), below. +func_emit_wrapper_part1 () +{ + func_emit_wrapper_part1_arg1=no + if test -n "$1" ; then + func_emit_wrapper_part1_arg1=$1 + fi + + $ECHO "\ +#! $SHELL + +# $output - temporary wrapper script for $objdir/$outputname +# Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION +# +# The $output program cannot be directly executed until all the libtool +# libraries that it depends on are installed. +# +# This wrapper script should never be moved out of the build directory. +# If it is, it will not operate correctly. + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +Xsed='${SED} -e 1s/^X//' +sed_quote_subst='$sed_quote_subst' + +# Be Bourne compatible +if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on \${1+\"\$@\"}, which + # is contrary to our usage. Disable this feature. + alias -g '\${1+\"\$@\"}'='\"\$@\"' + setopt NO_GLOB_SUBST +else + case \`(set -o) 2>/dev/null\` in *posix*) set -o posix;; esac +fi +BIN_SH=xpg4; export BIN_SH # for Tru64 +DUALCASE=1; export DUALCASE # for MKS sh + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +relink_command=\"$relink_command\" + +# This environment variable determines our operation mode. +if test \"\$libtool_install_magic\" = \"$magic\"; then + # install mode needs the following variables: + generated_by_libtool_version='$macro_version' + notinst_deplibs='$notinst_deplibs' +else + # When we are sourced in execute mode, \$file and \$ECHO are already set. + if test \"\$libtool_execute_magic\" != \"$magic\"; then + ECHO=\"$qecho\" + file=\"\$0\" + # Make sure echo works. + if test \"X\$1\" = X--no-reexec; then + # Discard the --no-reexec flag, and continue. + shift + elif test \"X\`{ \$ECHO '\t'; } 2>/dev/null\`\" = 'X\t'; then + # Yippee, \$ECHO works! + : + else + # Restart under the correct shell, and then maybe \$ECHO will work. + exec $SHELL \"\$0\" --no-reexec \${1+\"\$@\"} + fi + fi\ +" + $ECHO "\ + + # Find the directory that this script lives in. + thisdir=\`\$ECHO \"X\$file\" | \$Xsed -e 's%/[^/]*$%%'\` + test \"x\$thisdir\" = \"x\$file\" && thisdir=. + + # Follow symbolic links until we get to the real thisdir. + file=\`ls -ld \"\$file\" | ${SED} -n 's/.*-> //p'\` + while test -n \"\$file\"; do + destdir=\`\$ECHO \"X\$file\" | \$Xsed -e 's%/[^/]*\$%%'\` + + # If there was a directory component, then change thisdir. + if test \"x\$destdir\" != \"x\$file\"; then + case \"\$destdir\" in + [\\\\/]* | [A-Za-z]:[\\\\/]*) thisdir=\"\$destdir\" ;; + *) thisdir=\"\$thisdir/\$destdir\" ;; + esac + fi + + file=\`\$ECHO \"X\$file\" | \$Xsed -e 's%^.*/%%'\` + file=\`ls -ld \"\$thisdir/\$file\" | ${SED} -n 's/.*-> //p'\` + done +" +} +# end: func_emit_wrapper_part1 + +# func_emit_wrapper_part2 [arg=no] +# +# Emit the second part of a libtool wrapper script on stdout. +# For more information, see the description associated with +# func_emit_wrapper(), below. +func_emit_wrapper_part2 () +{ + func_emit_wrapper_part2_arg1=no + if test -n "$1" ; then + func_emit_wrapper_part2_arg1=$1 + fi + + $ECHO "\ + + # Usually 'no', except on cygwin/mingw when embedded into + # the cwrapper. + WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=$func_emit_wrapper_part2_arg1 + if test \"\$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR\" = \"yes\"; then + # special case for '.' + if test \"\$thisdir\" = \".\"; then + thisdir=\`pwd\` + fi + # remove .libs from thisdir + case \"\$thisdir\" in + *[\\\\/]$objdir ) thisdir=\`\$ECHO \"X\$thisdir\" | \$Xsed -e 's%[\\\\/][^\\\\/]*$%%'\` ;; + $objdir ) thisdir=. ;; + esac + fi + + # Try to get the absolute directory name. + absdir=\`cd \"\$thisdir\" && pwd\` + test -n \"\$absdir\" && thisdir=\"\$absdir\" +" + + if test "$fast_install" = yes; then + $ECHO "\ + program=lt-'$outputname'$exeext + progdir=\"\$thisdir/$objdir\" + + if test ! -f \"\$progdir/\$program\" || + { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | ${SED} 1q\`; \\ + test \"X\$file\" != \"X\$progdir/\$program\"; }; then + + file=\"\$\$-\$program\" + + if test ! -d \"\$progdir\"; then + $MKDIR \"\$progdir\" + else + $RM \"\$progdir/\$file\" + fi" + + $ECHO "\ + + # relink executable if necessary + if test -n \"\$relink_command\"; then + if relink_command_output=\`eval \$relink_command 2>&1\`; then : + else + $ECHO \"\$relink_command_output\" >&2 + $RM \"\$progdir/\$file\" + exit 1 + fi + fi + + $MV \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null || + { $RM \"\$progdir/\$program\"; + $MV \"\$progdir/\$file\" \"\$progdir/\$program\"; } + $RM \"\$progdir/\$file\" + fi" + else + $ECHO "\ + program='$outputname' + progdir=\"\$thisdir/$objdir\" +" + fi + + $ECHO "\ + + if test -f \"\$progdir/\$program\"; then" + + # Export our shlibpath_var if we have one. + if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then + $ECHO "\ + # Add our own library path to $shlibpath_var + $shlibpath_var=\"$temp_rpath\$$shlibpath_var\" + + # Some systems cannot cope with colon-terminated $shlibpath_var + # The second colon is a workaround for a bug in BeOS R4 sed + $shlibpath_var=\`\$ECHO \"X\$$shlibpath_var\" | \$Xsed -e 's/::*\$//'\` + + export $shlibpath_var +" + fi + + # fixup the dll searchpath if we need to. + if test -n "$dllsearchpath"; then + $ECHO "\ + # Add the dll search path components to the executable PATH + PATH=$dllsearchpath:\$PATH +" + fi + + $ECHO "\ + if test \"\$libtool_execute_magic\" != \"$magic\"; then + # Run the actual program with our arguments. +" + case $host in + # Backslashes separate directories on plain windows + *-*-mingw | *-*-os2* | *-cegcc*) + $ECHO "\ + exec \"\$progdir\\\\\$program\" \${1+\"\$@\"} +" + ;; + + *) + $ECHO "\ + exec \"\$progdir/\$program\" \${1+\"\$@\"} +" + ;; + esac + $ECHO "\ + \$ECHO \"\$0: cannot exec \$program \$*\" 1>&2 + exit 1 + fi + else + # The program doesn't exist. + \$ECHO \"\$0: error: \\\`\$progdir/\$program' does not exist\" 1>&2 + \$ECHO \"This script is just a wrapper for \$program.\" 1>&2 + $ECHO \"See the $PACKAGE documentation for more information.\" 1>&2 + exit 1 + fi +fi\ +" +} +# end: func_emit_wrapper_part2 + + +# func_emit_wrapper [arg=no] +# +# Emit a libtool wrapper script on stdout. +# Don't directly open a file because we may want to +# incorporate the script contents within a cygwin/mingw +# wrapper executable. Must ONLY be called from within +# func_mode_link because it depends on a number of variables +# set therein. +# +# ARG is the value that the WRAPPER_SCRIPT_BELONGS_IN_OBJDIR +# variable will take. If 'yes', then the emitted script +# will assume that the directory in which it is stored is +# the $objdir directory. This is a cygwin/mingw-specific +# behavior. +func_emit_wrapper () +{ + func_emit_wrapper_arg1=no + if test -n "$1" ; then + func_emit_wrapper_arg1=$1 + fi + + # split this up so that func_emit_cwrapperexe_src + # can call each part independently. + func_emit_wrapper_part1 "${func_emit_wrapper_arg1}" + func_emit_wrapper_part2 "${func_emit_wrapper_arg1}" +} + + +# func_to_host_path arg +# +# Convert paths to host format when used with build tools. +# Intended for use with "native" mingw (where libtool itself +# is running under the msys shell), or in the following cross- +# build environments: +# $build $host +# mingw (msys) mingw [e.g. native] +# cygwin mingw +# *nix + wine mingw +# where wine is equipped with the `winepath' executable. +# In the native mingw case, the (msys) shell automatically +# converts paths for any non-msys applications it launches, +# but that facility isn't available from inside the cwrapper. +# Similar accommodations are necessary for $host mingw and +# $build cygwin. Calling this function does no harm for other +# $host/$build combinations not listed above. +# +# ARG is the path (on $build) that should be converted to +# the proper representation for $host. The result is stored +# in $func_to_host_path_result. +func_to_host_path () +{ + func_to_host_path_result="$1" + if test -n "$1" ; then + case $host in + *mingw* ) + lt_sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g' + case $build in + *mingw* ) # actually, msys + # awkward: cmd appends spaces to result + lt_sed_strip_trailing_spaces="s/[ ]*\$//" + func_to_host_path_tmp1=`( cmd //c echo "$1" |\ + $SED -e "$lt_sed_strip_trailing_spaces" ) 2>/dev/null || echo ""` + func_to_host_path_result=`echo "$func_to_host_path_tmp1" |\ + $SED -e "$lt_sed_naive_backslashify"` + ;; + *cygwin* ) + func_to_host_path_tmp1=`cygpath -w "$1"` + func_to_host_path_result=`echo "$func_to_host_path_tmp1" |\ + $SED -e "$lt_sed_naive_backslashify"` + ;; + * ) + # Unfortunately, winepath does not exit with a non-zero + # error code, so we are forced to check the contents of + # stdout. On the other hand, if the command is not + # found, the shell will set an exit code of 127 and print + # *an error message* to stdout. So we must check for both + # error code of zero AND non-empty stdout, which explains + # the odd construction: + func_to_host_path_tmp1=`winepath -w "$1" 2>/dev/null` + if test "$?" -eq 0 && test -n "${func_to_host_path_tmp1}"; then + func_to_host_path_result=`echo "$func_to_host_path_tmp1" |\ + $SED -e "$lt_sed_naive_backslashify"` + else + # Allow warning below. + func_to_host_path_result="" + fi + ;; + esac + if test -z "$func_to_host_path_result" ; then + func_error "Could not determine host path corresponding to" + func_error " '$1'" + func_error "Continuing, but uninstalled executables may not work." + # Fallback: + func_to_host_path_result="$1" + fi + ;; + esac + fi +} +# end: func_to_host_path + +# func_to_host_pathlist arg +# +# Convert pathlists to host format when used with build tools. +# See func_to_host_path(), above. This function supports the +# following $build/$host combinations (but does no harm for +# combinations not listed here): +# $build $host +# mingw (msys) mingw [e.g. native] +# cygwin mingw +# *nix + wine mingw +# +# Path separators are also converted from $build format to +# $host format. If ARG begins or ends with a path separator +# character, it is preserved (but converted to $host format) +# on output. +# +# ARG is a pathlist (on $build) that should be converted to +# the proper representation on $host. The result is stored +# in $func_to_host_pathlist_result. +func_to_host_pathlist () +{ + func_to_host_pathlist_result="$1" + if test -n "$1" ; then + case $host in + *mingw* ) + lt_sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g' + # Remove leading and trailing path separator characters from + # ARG. msys behavior is inconsistent here, cygpath turns them + # into '.;' and ';.', and winepath ignores them completely. + func_to_host_pathlist_tmp2="$1" + # Once set for this call, this variable should not be + # reassigned. It is used in tha fallback case. + func_to_host_pathlist_tmp1=`echo "$func_to_host_pathlist_tmp2" |\ + $SED -e 's|^:*||' -e 's|:*$||'` + case $build in + *mingw* ) # Actually, msys. + # Awkward: cmd appends spaces to result. + lt_sed_strip_trailing_spaces="s/[ ]*\$//" + func_to_host_pathlist_tmp2=`( cmd //c echo "$func_to_host_pathlist_tmp1" |\ + $SED -e "$lt_sed_strip_trailing_spaces" ) 2>/dev/null || echo ""` + func_to_host_pathlist_result=`echo "$func_to_host_pathlist_tmp2" |\ + $SED -e "$lt_sed_naive_backslashify"` + ;; + *cygwin* ) + func_to_host_pathlist_tmp2=`cygpath -w -p "$func_to_host_pathlist_tmp1"` + func_to_host_pathlist_result=`echo "$func_to_host_pathlist_tmp2" |\ + $SED -e "$lt_sed_naive_backslashify"` + ;; + * ) + # unfortunately, winepath doesn't convert pathlists + func_to_host_pathlist_result="" + func_to_host_pathlist_oldIFS=$IFS + IFS=: + for func_to_host_pathlist_f in $func_to_host_pathlist_tmp1 ; do + IFS=$func_to_host_pathlist_oldIFS + if test -n "$func_to_host_pathlist_f" ; then + func_to_host_path "$func_to_host_pathlist_f" + if test -n "$func_to_host_path_result" ; then + if test -z "$func_to_host_pathlist_result" ; then + func_to_host_pathlist_result="$func_to_host_path_result" + else + func_to_host_pathlist_result="$func_to_host_pathlist_result;$func_to_host_path_result" + fi + fi + fi + IFS=: + done + IFS=$func_to_host_pathlist_oldIFS + ;; + esac + if test -z "$func_to_host_pathlist_result" ; then + func_error "Could not determine the host path(s) corresponding to" + func_error " '$1'" + func_error "Continuing, but uninstalled executables may not work." + # Fallback. This may break if $1 contains DOS-style drive + # specifications. The fix is not to complicate the expression + # below, but for the user to provide a working wine installation + # with winepath so that path translation in the cross-to-mingw + # case works properly. + lt_replace_pathsep_nix_to_dos="s|:|;|g" + func_to_host_pathlist_result=`echo "$func_to_host_pathlist_tmp1" |\ + $SED -e "$lt_replace_pathsep_nix_to_dos"` + fi + # Now, add the leading and trailing path separators back + case "$1" in + :* ) func_to_host_pathlist_result=";$func_to_host_pathlist_result" + ;; + esac + case "$1" in + *: ) func_to_host_pathlist_result="$func_to_host_pathlist_result;" + ;; + esac + ;; + esac + fi +} +# end: func_to_host_pathlist + +# func_emit_cwrapperexe_src +# emit the source code for a wrapper executable on stdout +# Must ONLY be called from within func_mode_link because +# it depends on a number of variable set therein. +func_emit_cwrapperexe_src () +{ + cat < +#include +#ifdef _MSC_VER +# include +# include +# include +# define setmode _setmode +#else +# include +# include +# ifdef __CYGWIN__ +# include +# define HAVE_SETENV +# ifdef __STRICT_ANSI__ +char *realpath (const char *, char *); +int putenv (char *); +int setenv (const char *, const char *, int); +# endif +# endif +#endif +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(PATH_MAX) +# define LT_PATHMAX PATH_MAX +#elif defined(MAXPATHLEN) +# define LT_PATHMAX MAXPATHLEN +#else +# define LT_PATHMAX 1024 +#endif + +#ifndef S_IXOTH +# define S_IXOTH 0 +#endif +#ifndef S_IXGRP +# define S_IXGRP 0 +#endif + +#ifdef _MSC_VER +# define S_IXUSR _S_IEXEC +# define stat _stat +# ifndef _INTPTR_T_DEFINED +# define intptr_t int +# endif +#endif + +#ifndef DIR_SEPARATOR +# define DIR_SEPARATOR '/' +# define PATH_SEPARATOR ':' +#endif + +#if defined (_WIN32) || defined (__MSDOS__) || defined (__DJGPP__) || \ + defined (__OS2__) +# define HAVE_DOS_BASED_FILE_SYSTEM +# define FOPEN_WB "wb" +# ifndef DIR_SEPARATOR_2 +# define DIR_SEPARATOR_2 '\\' +# endif +# ifndef PATH_SEPARATOR_2 +# define PATH_SEPARATOR_2 ';' +# endif +#endif + +#ifndef DIR_SEPARATOR_2 +# define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR) +#else /* DIR_SEPARATOR_2 */ +# define IS_DIR_SEPARATOR(ch) \ + (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2)) +#endif /* DIR_SEPARATOR_2 */ + +#ifndef PATH_SEPARATOR_2 +# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR) +#else /* PATH_SEPARATOR_2 */ +# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR_2) +#endif /* PATH_SEPARATOR_2 */ + +#ifdef __CYGWIN__ +# define FOPEN_WB "wb" +#endif + +#ifndef FOPEN_WB +# define FOPEN_WB "w" +#endif +#ifndef _O_BINARY +# define _O_BINARY 0 +#endif + +#define XMALLOC(type, num) ((type *) xmalloc ((num) * sizeof(type))) +#define XFREE(stale) do { \ + if (stale) { free ((void *) stale); stale = 0; } \ +} while (0) + +#undef LTWRAPPER_DEBUGPRINTF +#if defined DEBUGWRAPPER +# define LTWRAPPER_DEBUGPRINTF(args) ltwrapper_debugprintf args +static void +ltwrapper_debugprintf (const char *fmt, ...) +{ + va_list args; + va_start (args, fmt); + (void) vfprintf (stderr, fmt, args); + va_end (args); +} +#else +# define LTWRAPPER_DEBUGPRINTF(args) +#endif + +const char *program_name = NULL; + +void *xmalloc (size_t num); +char *xstrdup (const char *string); +const char *base_name (const char *name); +char *find_executable (const char *wrapper); +char *chase_symlinks (const char *pathspec); +int make_executable (const char *path); +int check_executable (const char *path); +char *strendzap (char *str, const char *pat); +void lt_fatal (const char *message, ...); +void lt_setenv (const char *name, const char *value); +char *lt_extend_str (const char *orig_value, const char *add, int to_end); +void lt_opt_process_env_set (const char *arg); +void lt_opt_process_env_prepend (const char *arg); +void lt_opt_process_env_append (const char *arg); +int lt_split_name_value (const char *arg, char** name, char** value); +void lt_update_exe_path (const char *name, const char *value); +void lt_update_lib_path (const char *name, const char *value); + +static const char *script_text_part1 = +EOF + + func_emit_wrapper_part1 yes | + $SED -e 's/\([\\"]\)/\\\1/g' \ + -e 's/^/ "/' -e 's/$/\\n"/' + echo ";" + cat <"))); + for (i = 0; i < newargc; i++) + { + LTWRAPPER_DEBUGPRINTF (("(main) newargz[%d] : %s\n", i, (newargz[i] ? newargz[i] : ""))); + } + +EOF + + case $host_os in + mingw*) + cat <<"EOF" + /* execv doesn't actually work on mingw as expected on unix */ + rval = _spawnv (_P_WAIT, lt_argv_zero, (const char * const *) newargz); + if (rval == -1) + { + /* failed to start process */ + LTWRAPPER_DEBUGPRINTF (("(main) failed to launch target \"%s\": errno = %d\n", lt_argv_zero, errno)); + return 127; + } + return rval; +EOF + ;; + *) + cat <<"EOF" + execv (lt_argv_zero, newargz); + return rval; /* =127, but avoids unused variable warning */ +EOF + ;; + esac + + cat <<"EOF" +} + +void * +xmalloc (size_t num) +{ + void *p = (void *) malloc (num); + if (!p) + lt_fatal ("Memory exhausted"); + + return p; +} + +char * +xstrdup (const char *string) +{ + return string ? strcpy ((char *) xmalloc (strlen (string) + 1), + string) : NULL; +} + +const char * +base_name (const char *name) +{ + const char *base; + +#if defined (HAVE_DOS_BASED_FILE_SYSTEM) + /* Skip over the disk name in MSDOS pathnames. */ + if (isalpha ((unsigned char) name[0]) && name[1] == ':') + name += 2; +#endif + + for (base = name; *name; name++) + if (IS_DIR_SEPARATOR (*name)) + base = name + 1; + return base; +} + +int +check_executable (const char *path) +{ + struct stat st; + + LTWRAPPER_DEBUGPRINTF (("(check_executable) : %s\n", + path ? (*path ? path : "EMPTY!") : "NULL!")); + if ((!path) || (!*path)) + return 0; + + if ((stat (path, &st) >= 0) + && (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))) + return 1; + else + return 0; +} + +int +make_executable (const char *path) +{ + int rval = 0; + struct stat st; + + LTWRAPPER_DEBUGPRINTF (("(make_executable) : %s\n", + path ? (*path ? path : "EMPTY!") : "NULL!")); + if ((!path) || (!*path)) + return 0; + + if (stat (path, &st) >= 0) + { + rval = chmod (path, st.st_mode | S_IXOTH | S_IXGRP | S_IXUSR); + } + return rval; +} + +/* Searches for the full path of the wrapper. Returns + newly allocated full path name if found, NULL otherwise + Does not chase symlinks, even on platforms that support them. +*/ +char * +find_executable (const char *wrapper) +{ + int has_slash = 0; + const char *p; + const char *p_next; + /* static buffer for getcwd */ + char tmp[LT_PATHMAX + 1]; + int tmp_len; + char *concat_name; + + LTWRAPPER_DEBUGPRINTF (("(find_executable) : %s\n", + wrapper ? (*wrapper ? wrapper : "EMPTY!") : "NULL!")); + + if ((wrapper == NULL) || (*wrapper == '\0')) + return NULL; + + /* Absolute path? */ +#if defined (HAVE_DOS_BASED_FILE_SYSTEM) + if (isalpha ((unsigned char) wrapper[0]) && wrapper[1] == ':') + { + concat_name = xstrdup (wrapper); + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + } + else + { +#endif + if (IS_DIR_SEPARATOR (wrapper[0])) + { + concat_name = xstrdup (wrapper); + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + } +#if defined (HAVE_DOS_BASED_FILE_SYSTEM) + } +#endif + + for (p = wrapper; *p; p++) + if (*p == '/') + { + has_slash = 1; + break; + } + if (!has_slash) + { + /* no slashes; search PATH */ + const char *path = getenv ("PATH"); + if (path != NULL) + { + for (p = path; *p; p = p_next) + { + const char *q; + size_t p_len; + for (q = p; *q; q++) + if (IS_PATH_SEPARATOR (*q)) + break; + p_len = q - p; + p_next = (*q == '\0' ? q : q + 1); + if (p_len == 0) + { + /* empty path: current directory */ + if (getcwd (tmp, LT_PATHMAX) == NULL) + lt_fatal ("getcwd failed"); + tmp_len = strlen (tmp); + concat_name = + XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); + memcpy (concat_name, tmp, tmp_len); + concat_name[tmp_len] = '/'; + strcpy (concat_name + tmp_len + 1, wrapper); + } + else + { + concat_name = + XMALLOC (char, p_len + 1 + strlen (wrapper) + 1); + memcpy (concat_name, p, p_len); + concat_name[p_len] = '/'; + strcpy (concat_name + p_len + 1, wrapper); + } + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + } + } + /* not found in PATH; assume curdir */ + } + /* Relative path | not found in path: prepend cwd */ + if (getcwd (tmp, LT_PATHMAX) == NULL) + lt_fatal ("getcwd failed"); + tmp_len = strlen (tmp); + concat_name = XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); + memcpy (concat_name, tmp, tmp_len); + concat_name[tmp_len] = '/'; + strcpy (concat_name + tmp_len + 1, wrapper); + + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + return NULL; +} + +char * +chase_symlinks (const char *pathspec) +{ +#ifndef S_ISLNK + return xstrdup (pathspec); +#else + char buf[LT_PATHMAX]; + struct stat s; + char *tmp_pathspec = xstrdup (pathspec); + char *p; + int has_symlinks = 0; + while (strlen (tmp_pathspec) && !has_symlinks) + { + LTWRAPPER_DEBUGPRINTF (("checking path component for symlinks: %s\n", + tmp_pathspec)); + if (lstat (tmp_pathspec, &s) == 0) + { + if (S_ISLNK (s.st_mode) != 0) + { + has_symlinks = 1; + break; + } + + /* search backwards for last DIR_SEPARATOR */ + p = tmp_pathspec + strlen (tmp_pathspec) - 1; + while ((p > tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) + p--; + if ((p == tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) + { + /* no more DIR_SEPARATORS left */ + break; + } + *p = '\0'; + } + else + { + char *errstr = strerror (errno); + lt_fatal ("Error accessing file %s (%s)", tmp_pathspec, errstr); + } + } + XFREE (tmp_pathspec); + + if (!has_symlinks) + { + return xstrdup (pathspec); + } + + tmp_pathspec = realpath (pathspec, buf); + if (tmp_pathspec == 0) + { + lt_fatal ("Could not follow symlinks for %s", pathspec); + } + return xstrdup (tmp_pathspec); +#endif +} + +char * +strendzap (char *str, const char *pat) +{ + size_t len, patlen; + + assert (str != NULL); + assert (pat != NULL); + + len = strlen (str); + patlen = strlen (pat); + + if (patlen <= len) + { + str += len - patlen; + if (strcmp (str, pat) == 0) + *str = '\0'; + } + return str; +} + +static void +lt_error_core (int exit_status, const char *mode, + const char *message, va_list ap) +{ + fprintf (stderr, "%s: %s: ", program_name, mode); + vfprintf (stderr, message, ap); + fprintf (stderr, ".\n"); + + if (exit_status >= 0) + exit (exit_status); +} + +void +lt_fatal (const char *message, ...) +{ + va_list ap; + va_start (ap, message); + lt_error_core (EXIT_FAILURE, "FATAL", message, ap); + va_end (ap); +} + +void +lt_setenv (const char *name, const char *value) +{ + LTWRAPPER_DEBUGPRINTF (("(lt_setenv) setting '%s' to '%s'\n", + (name ? name : ""), + (value ? value : ""))); + { +#ifdef HAVE_SETENV + /* always make a copy, for consistency with !HAVE_SETENV */ + char *str = xstrdup (value); + setenv (name, str, 1); +#else + int len = strlen (name) + 1 + strlen (value) + 1; + char *str = XMALLOC (char, len); + sprintf (str, "%s=%s", name, value); + if (putenv (str) != EXIT_SUCCESS) + { + XFREE (str); + } +#endif + } +} + +char * +lt_extend_str (const char *orig_value, const char *add, int to_end) +{ + char *new_value; + if (orig_value && *orig_value) + { + int orig_value_len = strlen (orig_value); + int add_len = strlen (add); + new_value = XMALLOC (char, add_len + orig_value_len + 1); + if (to_end) + { + strcpy (new_value, orig_value); + strcpy (new_value + orig_value_len, add); + } + else + { + strcpy (new_value, add); + strcpy (new_value + add_len, orig_value); + } + } + else + { + new_value = xstrdup (add); + } + return new_value; +} + +int +lt_split_name_value (const char *arg, char** name, char** value) +{ + const char *p; + int len; + if (!arg || !*arg) + return 1; + + p = strchr (arg, (int)'='); + + if (!p) + return 1; + + *value = xstrdup (++p); + + len = strlen (arg) - strlen (*value); + *name = XMALLOC (char, len); + strncpy (*name, arg, len-1); + (*name)[len - 1] = '\0'; + + return 0; +} + +void +lt_opt_process_env_set (const char *arg) +{ + char *name = NULL; + char *value = NULL; + + if (lt_split_name_value (arg, &name, &value) != 0) + { + XFREE (name); + XFREE (value); + lt_fatal ("bad argument for %s: '%s'", env_set_opt, arg); + } + + lt_setenv (name, value); + XFREE (name); + XFREE (value); +} + +void +lt_opt_process_env_prepend (const char *arg) +{ + char *name = NULL; + char *value = NULL; + char *new_value = NULL; + + if (lt_split_name_value (arg, &name, &value) != 0) + { + XFREE (name); + XFREE (value); + lt_fatal ("bad argument for %s: '%s'", env_prepend_opt, arg); + } + + new_value = lt_extend_str (getenv (name), value, 0); + lt_setenv (name, new_value); + XFREE (new_value); + XFREE (name); + XFREE (value); +} + +void +lt_opt_process_env_append (const char *arg) +{ + char *name = NULL; + char *value = NULL; + char *new_value = NULL; + + if (lt_split_name_value (arg, &name, &value) != 0) + { + XFREE (name); + XFREE (value); + lt_fatal ("bad argument for %s: '%s'", env_append_opt, arg); + } + + new_value = lt_extend_str (getenv (name), value, 1); + lt_setenv (name, new_value); + XFREE (new_value); + XFREE (name); + XFREE (value); +} + +void +lt_update_exe_path (const char *name, const char *value) +{ + LTWRAPPER_DEBUGPRINTF (("(lt_update_exe_path) modifying '%s' by prepending '%s'\n", + (name ? name : ""), + (value ? value : ""))); + + if (name && *name && value && *value) + { + char *new_value = lt_extend_str (getenv (name), value, 0); + /* some systems can't cope with a ':'-terminated path #' */ + int len = strlen (new_value); + while (((len = strlen (new_value)) > 0) && IS_PATH_SEPARATOR (new_value[len-1])) + { + new_value[len-1] = '\0'; + } + lt_setenv (name, new_value); + XFREE (new_value); + } +} + +void +lt_update_lib_path (const char *name, const char *value) +{ + LTWRAPPER_DEBUGPRINTF (("(lt_update_lib_path) modifying '%s' by prepending '%s'\n", + (name ? name : ""), + (value ? value : ""))); + + if (name && *name && value && *value) + { + char *new_value = lt_extend_str (getenv (name), value, 0); + lt_setenv (name, new_value); + XFREE (new_value); + } +} + + +EOF +} +# end: func_emit_cwrapperexe_src + +# func_mode_link arg... +func_mode_link () +{ + $opt_debug + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) + # It is impossible to link a dll without this setting, and + # we shouldn't force the makefile maintainer to figure out + # which system we are compiling for in order to pass an extra + # flag for every libtool invocation. + # allow_undefined=no + + # FIXME: Unfortunately, there are problems with the above when trying + # to make a dll which has undefined symbols, in which case not + # even a static library is built. For now, we need to specify + # -no-undefined on the libtool link line when we can be certain + # that all symbols are satisfied, otherwise we get a static library. + allow_undefined=yes + ;; + *) + allow_undefined=yes + ;; + esac + libtool_args=$nonopt + base_compile="$nonopt $@" + compile_command=$nonopt + finalize_command=$nonopt + + compile_rpath= + finalize_rpath= + compile_shlibpath= + finalize_shlibpath= + convenience= + old_convenience= + deplibs= + old_deplibs= + compiler_flags= + linker_flags= + dllsearchpath= + lib_search_path=`pwd` + inst_prefix_dir= + new_inherited_linker_flags= + + avoid_version=no + dlfiles= + dlprefiles= + dlself=no + export_dynamic=no + export_symbols= + export_symbols_regex= + generated= + libobjs= + ltlibs= + module=no + no_install=no + objs= + non_pic_objects= + precious_files_regex= + prefer_static_libs=no + preload=no + prev= + prevarg= + release= + rpath= + xrpath= + perm_rpath= + temp_rpath= + thread_safe=no + vinfo= + vinfo_number=no + weak_libs= + single_module="${wl}-single_module" + func_infer_tag $base_compile + + # We need to know -static, to get the right output filenames. + for arg + do + case $arg in + -shared) + test "$build_libtool_libs" != yes && \ + func_fatal_configuration "can not build a shared library" + build_old_libs=no + break + ;; + -all-static | -static | -static-libtool-libs) + case $arg in + -all-static) + if test "$build_libtool_libs" = yes && test -z "$link_static_flag"; then + func_warning "complete static linking is impossible in this configuration" + fi + if test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + prefer_static_libs=yes + ;; + -static) + if test -z "$pic_flag" && test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + prefer_static_libs=built + ;; + -static-libtool-libs) + if test -z "$pic_flag" && test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + prefer_static_libs=yes + ;; + esac + build_libtool_libs=no + build_old_libs=yes + break + ;; + esac + done + + # See if our shared archives depend on static archives. + test -n "$old_archive_from_new_cmds" && build_old_libs=yes + + # Go through the arguments, transforming them on the way. + while test "$#" -gt 0; do + arg="$1" + shift + func_quote_for_eval "$arg" + qarg=$func_quote_for_eval_unquoted_result + func_append libtool_args " $func_quote_for_eval_result" + + # If the previous option needs an argument, assign it. + if test -n "$prev"; then + case $prev in + output) + func_append compile_command " @OUTPUT@" + func_append finalize_command " @OUTPUT@" + ;; + esac + + case $prev in + dlfiles|dlprefiles) + if test "$preload" = no; then + # Add the symbol object into the linking commands. + func_append compile_command " @SYMFILE@" + func_append finalize_command " @SYMFILE@" + preload=yes + fi + case $arg in + *.la | *.lo) ;; # We handle these cases below. + force) + if test "$dlself" = no; then + dlself=needless + export_dynamic=yes + fi + prev= + continue + ;; + self) + if test "$prev" = dlprefiles; then + dlself=yes + elif test "$prev" = dlfiles && test "$dlopen_self" != yes; then + dlself=yes + else + dlself=needless + export_dynamic=yes + fi + prev= + continue + ;; + *) + if test "$prev" = dlfiles; then + dlfiles="$dlfiles $arg" + else + dlprefiles="$dlprefiles $arg" + fi + prev= + continue + ;; + esac + ;; + expsyms) + export_symbols="$arg" + test -f "$arg" \ + || func_fatal_error "symbol file \`$arg' does not exist" + prev= + continue + ;; + expsyms_regex) + export_symbols_regex="$arg" + prev= + continue + ;; + framework) + case $host in + *-*-darwin*) + case "$deplibs " in + *" $qarg.ltframework "*) ;; + *) deplibs="$deplibs $qarg.ltframework" # this is fixed later + ;; + esac + ;; + esac + prev= + continue + ;; + inst_prefix) + inst_prefix_dir="$arg" + prev= + continue + ;; + objectlist) + if test -f "$arg"; then + save_arg=$arg + moreargs= + for fil in `cat "$save_arg"` + do +# moreargs="$moreargs $fil" + arg=$fil + # A libtool-controlled object. + + # Check to see that this really is a libtool object. + if func_lalib_unsafe_p "$arg"; then + pic_object= + non_pic_object= + + # Read the .lo file + func_source "$arg" + + if test -z "$pic_object" || + test -z "$non_pic_object" || + test "$pic_object" = none && + test "$non_pic_object" = none; then + func_fatal_error "cannot find name of object for \`$arg'" + fi + + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir="$func_dirname_result" + + if test "$pic_object" != none; then + # Prepend the subdirectory the object is found in. + pic_object="$xdir$pic_object" + + if test "$prev" = dlfiles; then + if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then + dlfiles="$dlfiles $pic_object" + prev= + continue + else + # If libtool objects are unsupported, then we need to preload. + prev=dlprefiles + fi + fi + + # CHECK ME: I think I busted this. -Ossama + if test "$prev" = dlprefiles; then + # Preload the old-style object. + dlprefiles="$dlprefiles $pic_object" + prev= + fi + + # A PIC object. + func_append libobjs " $pic_object" + arg="$pic_object" + fi + + # Non-PIC object. + if test "$non_pic_object" != none; then + # Prepend the subdirectory the object is found in. + non_pic_object="$xdir$non_pic_object" + + # A standard non-PIC object + func_append non_pic_objects " $non_pic_object" + if test -z "$pic_object" || test "$pic_object" = none ; then + arg="$non_pic_object" + fi + else + # If the PIC object exists, use it instead. + # $xdir was prepended to $pic_object above. + non_pic_object="$pic_object" + func_append non_pic_objects " $non_pic_object" + fi + else + # Only an error if not doing a dry-run. + if $opt_dry_run; then + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir="$func_dirname_result" + + func_lo2o "$arg" + pic_object=$xdir$objdir/$func_lo2o_result + non_pic_object=$xdir$func_lo2o_result + func_append libobjs " $pic_object" + func_append non_pic_objects " $non_pic_object" + else + func_fatal_error "\`$arg' is not a valid libtool object" + fi + fi + done + else + func_fatal_error "link input file \`$arg' does not exist" + fi + arg=$save_arg + prev= + continue + ;; + precious_regex) + precious_files_regex="$arg" + prev= + continue + ;; + release) + release="-$arg" + prev= + continue + ;; + rpath | xrpath) + # We need an absolute path. + case $arg in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + func_fatal_error "only absolute run-paths are allowed" + ;; + esac + if test "$prev" = rpath; then + case "$rpath " in + *" $arg "*) ;; + *) rpath="$rpath $arg" ;; + esac + else + case "$xrpath " in + *" $arg "*) ;; + *) xrpath="$xrpath $arg" ;; + esac + fi + prev= + continue + ;; + shrext) + shrext_cmds="$arg" + prev= + continue + ;; + weak) + weak_libs="$weak_libs $arg" + prev= + continue + ;; + xcclinker) + linker_flags="$linker_flags $qarg" + compiler_flags="$compiler_flags $qarg" + prev= + func_append compile_command " $qarg" + func_append finalize_command " $qarg" + continue + ;; + xcompiler) + compiler_flags="$compiler_flags $qarg" + prev= + func_append compile_command " $qarg" + func_append finalize_command " $qarg" + continue + ;; + xlinker) + linker_flags="$linker_flags $qarg" + compiler_flags="$compiler_flags $wl$qarg" + prev= + func_append compile_command " $wl$qarg" + func_append finalize_command " $wl$qarg" + continue + ;; + *) + eval "$prev=\"\$arg\"" + prev= + continue + ;; + esac + fi # test -n "$prev" + + prevarg="$arg" + + case $arg in + -all-static) + if test -n "$link_static_flag"; then + # See comment for -static flag below, for more details. + func_append compile_command " $link_static_flag" + func_append finalize_command " $link_static_flag" + fi + continue + ;; + + -allow-undefined) + # FIXME: remove this flag sometime in the future. + func_fatal_error "\`-allow-undefined' must not be used because it is the default" + ;; + + -avoid-version) + avoid_version=yes + continue + ;; + + -dlopen) + prev=dlfiles + continue + ;; + + -dlpreopen) + prev=dlprefiles + continue + ;; + + -export-dynamic) + export_dynamic=yes + continue + ;; + + -export-symbols | -export-symbols-regex) + if test -n "$export_symbols" || test -n "$export_symbols_regex"; then + func_fatal_error "more than one -exported-symbols argument is not allowed" + fi + if test "X$arg" = "X-export-symbols"; then + prev=expsyms + else + prev=expsyms_regex + fi + continue + ;; + + -framework) + prev=framework + continue + ;; + + -inst-prefix-dir) + prev=inst_prefix + continue + ;; + + # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:* + # so, if we see these flags be careful not to treat them like -L + -L[A-Z][A-Z]*:*) + case $with_gcc/$host in + no/*-*-irix* | /*-*-irix*) + func_append compile_command " $arg" + func_append finalize_command " $arg" + ;; + esac + continue + ;; + + -L*) + func_stripname '-L' '' "$arg" + dir=$func_stripname_result + if test -z "$dir"; then + if test "$#" -gt 0; then + func_fatal_error "require no space between \`-L' and \`$1'" + else + func_fatal_error "need path for \`-L' option" + fi + fi + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + absdir=`cd "$dir" && pwd` + test -z "$absdir" && \ + func_fatal_error "cannot determine absolute directory name of \`$dir'" + dir="$absdir" + ;; + esac + case "$deplibs " in + *" -L$dir "*) ;; + *) + deplibs="$deplibs -L$dir" + lib_search_path="$lib_search_path $dir" + ;; + esac + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) + testbindir=`$ECHO "X$dir" | $Xsed -e 's*/lib$*/bin*'` + case :$dllsearchpath: in + *":$dir:"*) ;; + ::) dllsearchpath=$dir;; + *) dllsearchpath="$dllsearchpath:$dir";; + esac + case :$dllsearchpath: in + *":$testbindir:"*) ;; + ::) dllsearchpath=$testbindir;; + *) dllsearchpath="$dllsearchpath:$testbindir";; + esac + ;; + esac + continue + ;; + + -l*) + if test "X$arg" = "X-lc" || test "X$arg" = "X-lm"; then + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-beos* | *-cegcc*) + # These systems don't actually have a C or math library (as such) + continue + ;; + *-*-os2*) + # These systems don't actually have a C library (as such) + test "X$arg" = "X-lc" && continue + ;; + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) + # Do not include libc due to us having libc/libc_r. + test "X$arg" = "X-lc" && continue + ;; + *-*-rhapsody* | *-*-darwin1.[012]) + # Rhapsody C and math libraries are in the System framework + deplibs="$deplibs System.ltframework" + continue + ;; + *-*-sco3.2v5* | *-*-sco5v6*) + # Causes problems with __ctype + test "X$arg" = "X-lc" && continue + ;; + *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) + # Compiler inserts libc in the correct place for threads to work + test "X$arg" = "X-lc" && continue + ;; + esac + elif test "X$arg" = "X-lc_r"; then + case $host in + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) + # Do not include libc_r directly, use -pthread flag. + continue + ;; + esac + fi + deplibs="$deplibs $arg" + continue + ;; + + -module) + module=yes + continue + ;; + + # Tru64 UNIX uses -model [arg] to determine the layout of C++ + # classes, name mangling, and exception handling. + # Darwin uses the -arch flag to determine output architecture. + -model|-arch|-isysroot) + compiler_flags="$compiler_flags $arg" + func_append compile_command " $arg" + func_append finalize_command " $arg" + prev=xcompiler + continue + ;; + + -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe|-threads) + compiler_flags="$compiler_flags $arg" + func_append compile_command " $arg" + func_append finalize_command " $arg" + case "$new_inherited_linker_flags " in + *" $arg "*) ;; + * ) new_inherited_linker_flags="$new_inherited_linker_flags $arg" ;; + esac + continue + ;; + + -multi_module) + single_module="${wl}-multi_module" + continue + ;; + + -no-fast-install) + fast_install=no + continue + ;; + + -no-install) + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-darwin* | *-cegcc*) + # The PATH hackery in wrapper scripts is required on Windows + # and Darwin in order for the loader to find any dlls it needs. + func_warning "\`-no-install' is ignored for $host" + func_warning "assuming \`-no-fast-install' instead" + fast_install=no + ;; + *) no_install=yes ;; + esac + continue + ;; + + -no-undefined) + allow_undefined=no + continue + ;; + + -objectlist) + prev=objectlist + continue + ;; + + -o) prev=output ;; + + -precious-files-regex) + prev=precious_regex + continue + ;; + + -release) + prev=release + continue + ;; + + -rpath) + prev=rpath + continue + ;; + + -R) + prev=xrpath + continue + ;; + + -R*) + func_stripname '-R' '' "$arg" + dir=$func_stripname_result + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + func_fatal_error "only absolute run-paths are allowed" + ;; + esac + case "$xrpath " in + *" $dir "*) ;; + *) xrpath="$xrpath $dir" ;; + esac + continue + ;; + + -shared) + # The effects of -shared are defined in a previous loop. + continue + ;; + + -shrext) + prev=shrext + continue + ;; + + -static | -static-libtool-libs) + # The effects of -static are defined in a previous loop. + # We used to do the same as -all-static on platforms that + # didn't have a PIC flag, but the assumption that the effects + # would be equivalent was wrong. It would break on at least + # Digital Unix and AIX. + continue + ;; + + -thread-safe) + thread_safe=yes + continue + ;; + + -version-info) + prev=vinfo + continue + ;; + + -version-number) + prev=vinfo + vinfo_number=yes + continue + ;; + + -weak) + prev=weak + continue + ;; + + -Wc,*) + func_stripname '-Wc,' '' "$arg" + args=$func_stripname_result + arg= + save_ifs="$IFS"; IFS=',' + for flag in $args; do + IFS="$save_ifs" + func_quote_for_eval "$flag" + arg="$arg $wl$func_quote_for_eval_result" + compiler_flags="$compiler_flags $func_quote_for_eval_result" + done + IFS="$save_ifs" + func_stripname ' ' '' "$arg" + arg=$func_stripname_result + ;; + + -Wl,*) + func_stripname '-Wl,' '' "$arg" + args=$func_stripname_result + arg= + save_ifs="$IFS"; IFS=',' + for flag in $args; do + IFS="$save_ifs" + func_quote_for_eval "$flag" + arg="$arg $wl$func_quote_for_eval_result" + compiler_flags="$compiler_flags $wl$func_quote_for_eval_result" + linker_flags="$linker_flags $func_quote_for_eval_result" + done + IFS="$save_ifs" + func_stripname ' ' '' "$arg" + arg=$func_stripname_result + ;; + + -Xcompiler) + prev=xcompiler + continue + ;; + + -Xlinker) + prev=xlinker + continue + ;; + + -XCClinker) + prev=xcclinker + continue + ;; + + # -msg_* for osf cc + -msg_*) + func_quote_for_eval "$arg" + arg="$func_quote_for_eval_result" + ;; + + # -64, -mips[0-9] enable 64-bit mode on the SGI compiler + # -r[0-9][0-9]* specifies the processor on the SGI compiler + # -xarch=*, -xtarget=* enable 64-bit mode on the Sun compiler + # +DA*, +DD* enable 64-bit mode on the HP compiler + # -q* pass through compiler args for the IBM compiler + # -m*, -t[45]*, -txscale* pass through architecture-specific + # compiler args for GCC + # -F/path gives path to uninstalled frameworks, gcc on darwin + # -p, -pg, --coverage, -fprofile-* pass through profiling flag for GCC + # @file GCC response files + -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*| \ + -t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*) + func_quote_for_eval "$arg" + arg="$func_quote_for_eval_result" + func_append compile_command " $arg" + func_append finalize_command " $arg" + compiler_flags="$compiler_flags $arg" + continue + ;; + + # Some other compiler flag. + -* | +*) + func_quote_for_eval "$arg" + arg="$func_quote_for_eval_result" + ;; + + *.$objext) + # A standard object. + objs="$objs $arg" + ;; + + *.lo) + # A libtool-controlled object. + + # Check to see that this really is a libtool object. + if func_lalib_unsafe_p "$arg"; then + pic_object= + non_pic_object= + + # Read the .lo file + func_source "$arg" + + if test -z "$pic_object" || + test -z "$non_pic_object" || + test "$pic_object" = none && + test "$non_pic_object" = none; then + func_fatal_error "cannot find name of object for \`$arg'" + fi + + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir="$func_dirname_result" + + if test "$pic_object" != none; then + # Prepend the subdirectory the object is found in. + pic_object="$xdir$pic_object" + + if test "$prev" = dlfiles; then + if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then + dlfiles="$dlfiles $pic_object" + prev= + continue + else + # If libtool objects are unsupported, then we need to preload. + prev=dlprefiles + fi + fi + + # CHECK ME: I think I busted this. -Ossama + if test "$prev" = dlprefiles; then + # Preload the old-style object. + dlprefiles="$dlprefiles $pic_object" + prev= + fi + + # A PIC object. + func_append libobjs " $pic_object" + arg="$pic_object" + fi + + # Non-PIC object. + if test "$non_pic_object" != none; then + # Prepend the subdirectory the object is found in. + non_pic_object="$xdir$non_pic_object" + + # A standard non-PIC object + func_append non_pic_objects " $non_pic_object" + if test -z "$pic_object" || test "$pic_object" = none ; then + arg="$non_pic_object" + fi + else + # If the PIC object exists, use it instead. + # $xdir was prepended to $pic_object above. + non_pic_object="$pic_object" + func_append non_pic_objects " $non_pic_object" + fi + else + # Only an error if not doing a dry-run. + if $opt_dry_run; then + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir="$func_dirname_result" + + func_lo2o "$arg" + pic_object=$xdir$objdir/$func_lo2o_result + non_pic_object=$xdir$func_lo2o_result + func_append libobjs " $pic_object" + func_append non_pic_objects " $non_pic_object" + else + func_fatal_error "\`$arg' is not a valid libtool object" + fi + fi + ;; + + *.$libext) + # An archive. + deplibs="$deplibs $arg" + old_deplibs="$old_deplibs $arg" + continue + ;; + + *.la) + # A libtool-controlled library. + + if test "$prev" = dlfiles; then + # This library was specified with -dlopen. + dlfiles="$dlfiles $arg" + prev= + elif test "$prev" = dlprefiles; then + # The library was specified with -dlpreopen. + dlprefiles="$dlprefiles $arg" + prev= + else + deplibs="$deplibs $arg" + fi + continue + ;; + + # Some other compiler argument. + *) + # Unknown arguments in both finalize_command and compile_command need + # to be aesthetically quoted because they are evaled later. + func_quote_for_eval "$arg" + arg="$func_quote_for_eval_result" + ;; + esac # arg + + # Now actually substitute the argument into the commands. + if test -n "$arg"; then + func_append compile_command " $arg" + func_append finalize_command " $arg" + fi + done # argument parsing loop + + test -n "$prev" && \ + func_fatal_help "the \`$prevarg' option requires an argument" + + if test "$export_dynamic" = yes && test -n "$export_dynamic_flag_spec"; then + eval arg=\"$export_dynamic_flag_spec\" + func_append compile_command " $arg" + func_append finalize_command " $arg" + fi + + oldlibs= + # calculate the name of the file, without its directory + func_basename "$output" + outputname="$func_basename_result" + libobjs_save="$libobjs" + + if test -n "$shlibpath_var"; then + # get the directories listed in $shlibpath_var + eval shlib_search_path=\`\$ECHO \"X\${$shlibpath_var}\" \| \$Xsed -e \'s/:/ /g\'\` + else + shlib_search_path= + fi + eval sys_lib_search_path=\"$sys_lib_search_path_spec\" + eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\" + + func_dirname "$output" "/" "" + output_objdir="$func_dirname_result$objdir" + # Create the object directory. + func_mkdir_p "$output_objdir" + + # Determine the type of output + case $output in + "") + func_fatal_help "you must specify an output file" + ;; + *.$libext) linkmode=oldlib ;; + *.lo | *.$objext) linkmode=obj ;; + *.la) linkmode=lib ;; + *) linkmode=prog ;; # Anything else should be a program. + esac + + specialdeplibs= + + libs= + # Find all interdependent deplibs by searching for libraries + # that are linked more than once (e.g. -la -lb -la) + for deplib in $deplibs; do + if $opt_duplicate_deps ; then + case "$libs " in + *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; + esac + fi + libs="$libs $deplib" + done + + if test "$linkmode" = lib; then + libs="$predeps $libs $compiler_lib_search_path $postdeps" + + # Compute libraries that are listed more than once in $predeps + # $postdeps and mark them as special (i.e., whose duplicates are + # not to be eliminated). + pre_post_deps= + if $opt_duplicate_compiler_generated_deps; then + for pre_post_dep in $predeps $postdeps; do + case "$pre_post_deps " in + *" $pre_post_dep "*) specialdeplibs="$specialdeplibs $pre_post_deps" ;; + esac + pre_post_deps="$pre_post_deps $pre_post_dep" + done + fi + pre_post_deps= + fi + + deplibs= + newdependency_libs= + newlib_search_path= + need_relink=no # whether we're linking any uninstalled libtool libraries + notinst_deplibs= # not-installed libtool libraries + notinst_path= # paths that contain not-installed libtool libraries + + case $linkmode in + lib) + passes="conv dlpreopen link" + for file in $dlfiles $dlprefiles; do + case $file in + *.la) ;; + *) + func_fatal_help "libraries can \`-dlopen' only libtool libraries: $file" + ;; + esac + done + ;; + prog) + compile_deplibs= + finalize_deplibs= + alldeplibs=no + newdlfiles= + newdlprefiles= + passes="conv scan dlopen dlpreopen link" + ;; + *) passes="conv" + ;; + esac + + for pass in $passes; do + # The preopen pass in lib mode reverses $deplibs; put it back here + # so that -L comes before libs that need it for instance... + if test "$linkmode,$pass" = "lib,link"; then + ## FIXME: Find the place where the list is rebuilt in the wrong + ## order, and fix it there properly + tmp_deplibs= + for deplib in $deplibs; do + tmp_deplibs="$deplib $tmp_deplibs" + done + deplibs="$tmp_deplibs" + fi + + if test "$linkmode,$pass" = "lib,link" || + test "$linkmode,$pass" = "prog,scan"; then + libs="$deplibs" + deplibs= + fi + if test "$linkmode" = prog; then + case $pass in + dlopen) libs="$dlfiles" ;; + dlpreopen) libs="$dlprefiles" ;; + link) + libs="$deplibs %DEPLIBS%" + test "X$link_all_deplibs" != Xno && libs="$libs $dependency_libs" + ;; + esac + fi + if test "$linkmode,$pass" = "lib,dlpreopen"; then + # Collect and forward deplibs of preopened libtool libs + for lib in $dlprefiles; do + # Ignore non-libtool-libs + dependency_libs= + case $lib in + *.la) func_source "$lib" ;; + esac + + # Collect preopened libtool deplibs, except any this library + # has declared as weak libs + for deplib in $dependency_libs; do + deplib_base=`$ECHO "X$deplib" | $Xsed -e "$basename"` + case " $weak_libs " in + *" $deplib_base "*) ;; + *) deplibs="$deplibs $deplib" ;; + esac + done + done + libs="$dlprefiles" + fi + if test "$pass" = dlopen; then + # Collect dlpreopened libraries + save_deplibs="$deplibs" + deplibs= + fi + + for deplib in $libs; do + lib= + found=no + case $deplib in + -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe|-threads) + if test "$linkmode,$pass" = "prog,link"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + compiler_flags="$compiler_flags $deplib" + if test "$linkmode" = lib ; then + case "$new_inherited_linker_flags " in + *" $deplib "*) ;; + * ) new_inherited_linker_flags="$new_inherited_linker_flags $deplib" ;; + esac + fi + fi + continue + ;; + -l*) + if test "$linkmode" != lib && test "$linkmode" != prog; then + func_warning "\`-l' is ignored for archives/objects" + continue + fi + func_stripname '-l' '' "$deplib" + name=$func_stripname_result + if test "$linkmode" = lib; then + searchdirs="$newlib_search_path $lib_search_path $compiler_lib_search_dirs $sys_lib_search_path $shlib_search_path" + else + searchdirs="$newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path" + fi + for searchdir in $searchdirs; do + for search_ext in .la $std_shrext .so .a; do + # Search the libtool library + lib="$searchdir/lib${name}${search_ext}" + if test -f "$lib"; then + if test "$search_ext" = ".la"; then + found=yes + else + found=no + fi + break 2 + fi + done + done + if test "$found" != yes; then + # deplib doesn't seem to be a libtool library + if test "$linkmode,$pass" = "prog,link"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + deplibs="$deplib $deplibs" + test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs" + fi + continue + else # deplib is a libtool library + # If $allow_libtool_libs_with_static_runtimes && $deplib is a stdlib, + # We need to do some special things here, and not later. + if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then + case " $predeps $postdeps " in + *" $deplib "*) + if func_lalib_p "$lib"; then + library_names= + old_library= + func_source "$lib" + for l in $old_library $library_names; do + ll="$l" + done + if test "X$ll" = "X$old_library" ; then # only static version available + found=no + func_dirname "$lib" "" "." + ladir="$func_dirname_result" + lib=$ladir/$old_library + if test "$linkmode,$pass" = "prog,link"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + deplibs="$deplib $deplibs" + test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs" + fi + continue + fi + fi + ;; + *) ;; + esac + fi + fi + ;; # -l + *.ltframework) + if test "$linkmode,$pass" = "prog,link"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + deplibs="$deplib $deplibs" + if test "$linkmode" = lib ; then + case "$new_inherited_linker_flags " in + *" $deplib "*) ;; + * ) new_inherited_linker_flags="$new_inherited_linker_flags $deplib" ;; + esac + fi + fi + continue + ;; + -L*) + case $linkmode in + lib) + deplibs="$deplib $deplibs" + test "$pass" = conv && continue + newdependency_libs="$deplib $newdependency_libs" + func_stripname '-L' '' "$deplib" + newlib_search_path="$newlib_search_path $func_stripname_result" + ;; + prog) + if test "$pass" = conv; then + deplibs="$deplib $deplibs" + continue + fi + if test "$pass" = scan; then + deplibs="$deplib $deplibs" + else + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + fi + func_stripname '-L' '' "$deplib" + newlib_search_path="$newlib_search_path $func_stripname_result" + ;; + *) + func_warning "\`-L' is ignored for archives/objects" + ;; + esac # linkmode + continue + ;; # -L + -R*) + if test "$pass" = link; then + func_stripname '-R' '' "$deplib" + dir=$func_stripname_result + # Make sure the xrpath contains only unique directories. + case "$xrpath " in + *" $dir "*) ;; + *) xrpath="$xrpath $dir" ;; + esac + fi + deplibs="$deplib $deplibs" + continue + ;; + *.la) lib="$deplib" ;; + *.$libext) + if test "$pass" = conv; then + deplibs="$deplib $deplibs" + continue + fi + case $linkmode in + lib) + # Linking convenience modules into shared libraries is allowed, + # but linking other static libraries is non-portable. + case " $dlpreconveniencelibs " in + *" $deplib "*) ;; + *) + valid_a_lib=no + case $deplibs_check_method in + match_pattern*) + set dummy $deplibs_check_method; shift + match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` + if eval "\$ECHO \"X$deplib\"" 2>/dev/null | $Xsed -e 10q \ + | $EGREP "$match_pattern_regex" > /dev/null; then + valid_a_lib=yes + fi + ;; + pass_all) + valid_a_lib=yes + ;; + esac + if test "$valid_a_lib" != yes; then + $ECHO + $ECHO "*** Warning: Trying to link with static lib archive $deplib." + $ECHO "*** I have the capability to make that library automatically link in when" + $ECHO "*** you link to this library. But I can only do this if you have a" + $ECHO "*** shared version of the library, which you do not appear to have" + $ECHO "*** because the file extensions .$libext of this argument makes me believe" + $ECHO "*** that it is just a static archive that I should not use here." + else + $ECHO + $ECHO "*** Warning: Linking the shared library $output against the" + $ECHO "*** static library $deplib is not portable!" + deplibs="$deplib $deplibs" + fi + ;; + esac + continue + ;; + prog) + if test "$pass" != link; then + deplibs="$deplib $deplibs" + else + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + fi + continue + ;; + esac # linkmode + ;; # *.$libext + *.lo | *.$objext) + if test "$pass" = conv; then + deplibs="$deplib $deplibs" + elif test "$linkmode" = prog; then + if test "$pass" = dlpreopen || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then + # If there is no dlopen support or we're linking statically, + # we need to preload. + newdlprefiles="$newdlprefiles $deplib" + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + newdlfiles="$newdlfiles $deplib" + fi + fi + continue + ;; + %DEPLIBS%) + alldeplibs=yes + continue + ;; + esac # case $deplib + + if test "$found" = yes || test -f "$lib"; then : + else + func_fatal_error "cannot find the library \`$lib' or unhandled argument \`$deplib'" + fi + + # Check to see that this really is a libtool archive. + func_lalib_unsafe_p "$lib" \ + || func_fatal_error "\`$lib' is not a valid libtool archive" + + func_dirname "$lib" "" "." + ladir="$func_dirname_result" + + dlname= + dlopen= + dlpreopen= + libdir= + library_names= + old_library= + inherited_linker_flags= + # If the library was installed with an old release of libtool, + # it will not redefine variables installed, or shouldnotlink + installed=yes + shouldnotlink=no + avoidtemprpath= + + + # Read the .la file + func_source "$lib" + + # Convert "-framework foo" to "foo.ltframework" + if test -n "$inherited_linker_flags"; then + tmp_inherited_linker_flags=`$ECHO "X$inherited_linker_flags" | $Xsed -e 's/-framework \([^ $]*\)/\1.ltframework/g'` + for tmp_inherited_linker_flag in $tmp_inherited_linker_flags; do + case " $new_inherited_linker_flags " in + *" $tmp_inherited_linker_flag "*) ;; + *) new_inherited_linker_flags="$new_inherited_linker_flags $tmp_inherited_linker_flag";; + esac + done + fi + dependency_libs=`$ECHO "X $dependency_libs" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'` + if test "$linkmode,$pass" = "lib,link" || + test "$linkmode,$pass" = "prog,scan" || + { test "$linkmode" != prog && test "$linkmode" != lib; }; then + test -n "$dlopen" && dlfiles="$dlfiles $dlopen" + test -n "$dlpreopen" && dlprefiles="$dlprefiles $dlpreopen" + fi + + if test "$pass" = conv; then + # Only check for convenience libraries + deplibs="$lib $deplibs" + if test -z "$libdir"; then + if test -z "$old_library"; then + func_fatal_error "cannot find name of link library for \`$lib'" + fi + # It is a libtool convenience library, so add in its objects. + convenience="$convenience $ladir/$objdir/$old_library" + old_convenience="$old_convenience $ladir/$objdir/$old_library" + tmp_libs= + for deplib in $dependency_libs; do + deplibs="$deplib $deplibs" + if $opt_duplicate_deps ; then + case "$tmp_libs " in + *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; + esac + fi + tmp_libs="$tmp_libs $deplib" + done + elif test "$linkmode" != prog && test "$linkmode" != lib; then + func_fatal_error "\`$lib' is not a convenience library" + fi + continue + fi # $pass = conv + + + # Get the name of the library we link against. + linklib= + for l in $old_library $library_names; do + linklib="$l" + done + if test -z "$linklib"; then + func_fatal_error "cannot find name of link library for \`$lib'" + fi + + # This library was specified with -dlopen. + if test "$pass" = dlopen; then + if test -z "$libdir"; then + func_fatal_error "cannot -dlopen a convenience library: \`$lib'" + fi + if test -z "$dlname" || + test "$dlopen_support" != yes || + test "$build_libtool_libs" = no; then + # If there is no dlname, no dlopen support or we're linking + # statically, we need to preload. We also need to preload any + # dependent libraries so libltdl's deplib preloader doesn't + # bomb out in the load deplibs phase. + dlprefiles="$dlprefiles $lib $dependency_libs" + else + newdlfiles="$newdlfiles $lib" + fi + continue + fi # $pass = dlopen + + # We need an absolute path. + case $ladir in + [\\/]* | [A-Za-z]:[\\/]*) abs_ladir="$ladir" ;; + *) + abs_ladir=`cd "$ladir" && pwd` + if test -z "$abs_ladir"; then + func_warning "cannot determine absolute directory name of \`$ladir'" + func_warning "passing it literally to the linker, although it might fail" + abs_ladir="$ladir" + fi + ;; + esac + func_basename "$lib" + laname="$func_basename_result" + + # Find the relevant object directory and library name. + if test "X$installed" = Xyes; then + if test ! -f "$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then + func_warning "library \`$lib' was moved." + dir="$ladir" + absdir="$abs_ladir" + libdir="$abs_ladir" + else + dir="$libdir" + absdir="$libdir" + fi + test "X$hardcode_automatic" = Xyes && avoidtemprpath=yes + else + if test ! -f "$ladir/$objdir/$linklib" && test -f "$abs_ladir/$linklib"; then + dir="$ladir" + absdir="$abs_ladir" + # Remove this search path later + notinst_path="$notinst_path $abs_ladir" + else + dir="$ladir/$objdir" + absdir="$abs_ladir/$objdir" + # Remove this search path later + notinst_path="$notinst_path $abs_ladir" + fi + fi # $installed = yes + func_stripname 'lib' '.la' "$laname" + name=$func_stripname_result + + # This library was specified with -dlpreopen. + if test "$pass" = dlpreopen; then + if test -z "$libdir" && test "$linkmode" = prog; then + func_fatal_error "only libraries may -dlpreopen a convenience library: \`$lib'" + fi + # Prefer using a static library (so that no silly _DYNAMIC symbols + # are required to link). + if test -n "$old_library"; then + newdlprefiles="$newdlprefiles $dir/$old_library" + # Keep a list of preopened convenience libraries to check + # that they are being used correctly in the link pass. + test -z "$libdir" && \ + dlpreconveniencelibs="$dlpreconveniencelibs $dir/$old_library" + # Otherwise, use the dlname, so that lt_dlopen finds it. + elif test -n "$dlname"; then + newdlprefiles="$newdlprefiles $dir/$dlname" + else + newdlprefiles="$newdlprefiles $dir/$linklib" + fi + fi # $pass = dlpreopen + + if test -z "$libdir"; then + # Link the convenience library + if test "$linkmode" = lib; then + deplibs="$dir/$old_library $deplibs" + elif test "$linkmode,$pass" = "prog,link"; then + compile_deplibs="$dir/$old_library $compile_deplibs" + finalize_deplibs="$dir/$old_library $finalize_deplibs" + else + deplibs="$lib $deplibs" # used for prog,scan pass + fi + continue + fi + + + if test "$linkmode" = prog && test "$pass" != link; then + newlib_search_path="$newlib_search_path $ladir" + deplibs="$lib $deplibs" + + linkalldeplibs=no + if test "$link_all_deplibs" != no || test -z "$library_names" || + test "$build_libtool_libs" = no; then + linkalldeplibs=yes + fi + + tmp_libs= + for deplib in $dependency_libs; do + case $deplib in + -L*) func_stripname '-L' '' "$deplib" + newlib_search_path="$newlib_search_path $func_stripname_result" + ;; + esac + # Need to link against all dependency_libs? + if test "$linkalldeplibs" = yes; then + deplibs="$deplib $deplibs" + else + # Need to hardcode shared library paths + # or/and link against static libraries + newdependency_libs="$deplib $newdependency_libs" + fi + if $opt_duplicate_deps ; then + case "$tmp_libs " in + *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; + esac + fi + tmp_libs="$tmp_libs $deplib" + done # for deplib + continue + fi # $linkmode = prog... + + if test "$linkmode,$pass" = "prog,link"; then + if test -n "$library_names" && + { { test "$prefer_static_libs" = no || + test "$prefer_static_libs,$installed" = "built,yes"; } || + test -z "$old_library"; }; then + # We need to hardcode the library path + if test -n "$shlibpath_var" && test -z "$avoidtemprpath" ; then + # Make sure the rpath contains only unique directories. + case "$temp_rpath:" in + *"$absdir:"*) ;; + *) temp_rpath="$temp_rpath$absdir:" ;; + esac + fi + + # Hardcode the library path. + # Skip directories that are in the system default run-time + # search path. + case " $sys_lib_dlsearch_path " in + *" $absdir "*) ;; + *) + case "$compile_rpath " in + *" $absdir "*) ;; + *) compile_rpath="$compile_rpath $absdir" + esac + ;; + esac + case " $sys_lib_dlsearch_path " in + *" $libdir "*) ;; + *) + case "$finalize_rpath " in + *" $libdir "*) ;; + *) finalize_rpath="$finalize_rpath $libdir" + esac + ;; + esac + fi # $linkmode,$pass = prog,link... + + if test "$alldeplibs" = yes && + { test "$deplibs_check_method" = pass_all || + { test "$build_libtool_libs" = yes && + test -n "$library_names"; }; }; then + # We only need to search for static libraries + continue + fi + fi + + link_static=no # Whether the deplib will be linked statically + use_static_libs=$prefer_static_libs + if test "$use_static_libs" = built && test "$installed" = yes; then + use_static_libs=no + fi + if test -n "$library_names" && + { test "$use_static_libs" = no || test -z "$old_library"; }; then + case $host in + *cygwin* | *mingw* | *cegcc*) + # No point in relinking DLLs because paths are not encoded + notinst_deplibs="$notinst_deplibs $lib" + need_relink=no + ;; + *) + if test "$installed" = no; then + notinst_deplibs="$notinst_deplibs $lib" + need_relink=yes + fi + ;; + esac + # This is a shared library + + # Warn about portability, can't link against -module's on some + # systems (darwin). Don't bleat about dlopened modules though! + dlopenmodule="" + for dlpremoduletest in $dlprefiles; do + if test "X$dlpremoduletest" = "X$lib"; then + dlopenmodule="$dlpremoduletest" + break + fi + done + if test -z "$dlopenmodule" && test "$shouldnotlink" = yes && test "$pass" = link; then + $ECHO + if test "$linkmode" = prog; then + $ECHO "*** Warning: Linking the executable $output against the loadable module" + else + $ECHO "*** Warning: Linking the shared library $output against the loadable module" + fi + $ECHO "*** $linklib is not portable!" + fi + if test "$linkmode" = lib && + test "$hardcode_into_libs" = yes; then + # Hardcode the library path. + # Skip directories that are in the system default run-time + # search path. + case " $sys_lib_dlsearch_path " in + *" $absdir "*) ;; + *) + case "$compile_rpath " in + *" $absdir "*) ;; + *) compile_rpath="$compile_rpath $absdir" + esac + ;; + esac + case " $sys_lib_dlsearch_path " in + *" $libdir "*) ;; + *) + case "$finalize_rpath " in + *" $libdir "*) ;; + *) finalize_rpath="$finalize_rpath $libdir" + esac + ;; + esac + fi + + if test -n "$old_archive_from_expsyms_cmds"; then + # figure out the soname + set dummy $library_names + shift + realname="$1" + shift + libname=`eval "\\$ECHO \"$libname_spec\""` + # use dlname if we got it. it's perfectly good, no? + if test -n "$dlname"; then + soname="$dlname" + elif test -n "$soname_spec"; then + # bleh windows + case $host in + *cygwin* | mingw* | *cegcc*) + func_arith $current - $age + major=$func_arith_result + versuffix="-$major" + ;; + esac + eval soname=\"$soname_spec\" + else + soname="$realname" + fi + + # Make a new name for the extract_expsyms_cmds to use + soroot="$soname" + func_basename "$soroot" + soname="$func_basename_result" + func_stripname 'lib' '.dll' "$soname" + newlib=libimp-$func_stripname_result.a + + # If the library has no export list, then create one now + if test -f "$output_objdir/$soname-def"; then : + else + func_verbose "extracting exported symbol list from \`$soname'" + func_execute_cmds "$extract_expsyms_cmds" 'exit $?' + fi + + # Create $newlib + if test -f "$output_objdir/$newlib"; then :; else + func_verbose "generating import library for \`$soname'" + func_execute_cmds "$old_archive_from_expsyms_cmds" 'exit $?' + fi + # make sure the library variables are pointing to the new library + dir=$output_objdir + linklib=$newlib + fi # test -n "$old_archive_from_expsyms_cmds" + + if test "$linkmode" = prog || test "$mode" != relink; then + add_shlibpath= + add_dir= + add= + lib_linked=yes + case $hardcode_action in + immediate | unsupported) + if test "$hardcode_direct" = no; then + add="$dir/$linklib" + case $host in + *-*-sco3.2v5.0.[024]*) add_dir="-L$dir" ;; + *-*-sysv4*uw2*) add_dir="-L$dir" ;; + *-*-sysv5OpenUNIX* | *-*-sysv5UnixWare7.[01].[10]* | \ + *-*-unixware7*) add_dir="-L$dir" ;; + *-*-darwin* ) + # if the lib is a (non-dlopened) module then we can not + # link against it, someone is ignoring the earlier warnings + if /usr/bin/file -L $add 2> /dev/null | + $GREP ": [^:]* bundle" >/dev/null ; then + if test "X$dlopenmodule" != "X$lib"; then + $ECHO "*** Warning: lib $linklib is a module, not a shared library" + if test -z "$old_library" ; then + $ECHO + $ECHO "*** And there doesn't seem to be a static archive available" + $ECHO "*** The link will probably fail, sorry" + else + add="$dir/$old_library" + fi + elif test -n "$old_library"; then + add="$dir/$old_library" + fi + fi + esac + elif test "$hardcode_minus_L" = no; then + case $host in + *-*-sunos*) add_shlibpath="$dir" ;; + esac + add_dir="-L$dir" + add="-l$name" + elif test "$hardcode_shlibpath_var" = no; then + add_shlibpath="$dir" + add="-l$name" + else + lib_linked=no + fi + ;; + relink) + if test "$hardcode_direct" = yes && + test "$hardcode_direct_absolute" = no; then + add="$dir/$linklib" + elif test "$hardcode_minus_L" = yes; then + add_dir="-L$dir" + # Try looking first in the location we're being installed to. + if test -n "$inst_prefix_dir"; then + case $libdir in + [\\/]*) + add_dir="$add_dir -L$inst_prefix_dir$libdir" + ;; + esac + fi + add="-l$name" + elif test "$hardcode_shlibpath_var" = yes; then + add_shlibpath="$dir" + add="-l$name" + else + lib_linked=no + fi + ;; + *) lib_linked=no ;; + esac + + if test "$lib_linked" != yes; then + func_fatal_configuration "unsupported hardcode properties" + fi + + if test -n "$add_shlibpath"; then + case :$compile_shlibpath: in + *":$add_shlibpath:"*) ;; + *) compile_shlibpath="$compile_shlibpath$add_shlibpath:" ;; + esac + fi + if test "$linkmode" = prog; then + test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs" + test -n "$add" && compile_deplibs="$add $compile_deplibs" + else + test -n "$add_dir" && deplibs="$add_dir $deplibs" + test -n "$add" && deplibs="$add $deplibs" + if test "$hardcode_direct" != yes && + test "$hardcode_minus_L" != yes && + test "$hardcode_shlibpath_var" = yes; then + case :$finalize_shlibpath: in + *":$libdir:"*) ;; + *) finalize_shlibpath="$finalize_shlibpath$libdir:" ;; + esac + fi + fi + fi + + if test "$linkmode" = prog || test "$mode" = relink; then + add_shlibpath= + add_dir= + add= + # Finalize command for both is simple: just hardcode it. + if test "$hardcode_direct" = yes && + test "$hardcode_direct_absolute" = no; then + add="$libdir/$linklib" + elif test "$hardcode_minus_L" = yes; then + add_dir="-L$libdir" + add="-l$name" + elif test "$hardcode_shlibpath_var" = yes; then + case :$finalize_shlibpath: in + *":$libdir:"*) ;; + *) finalize_shlibpath="$finalize_shlibpath$libdir:" ;; + esac + add="-l$name" + elif test "$hardcode_automatic" = yes; then + if test -n "$inst_prefix_dir" && + test -f "$inst_prefix_dir$libdir/$linklib" ; then + add="$inst_prefix_dir$libdir/$linklib" + else + add="$libdir/$linklib" + fi + else + # We cannot seem to hardcode it, guess we'll fake it. + add_dir="-L$libdir" + # Try looking first in the location we're being installed to. + if test -n "$inst_prefix_dir"; then + case $libdir in + [\\/]*) + add_dir="$add_dir -L$inst_prefix_dir$libdir" + ;; + esac + fi + add="-l$name" + fi + + if test "$linkmode" = prog; then + test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs" + test -n "$add" && finalize_deplibs="$add $finalize_deplibs" + else + test -n "$add_dir" && deplibs="$add_dir $deplibs" + test -n "$add" && deplibs="$add $deplibs" + fi + fi + elif test "$linkmode" = prog; then + # Here we assume that one of hardcode_direct or hardcode_minus_L + # is not unsupported. This is valid on all known static and + # shared platforms. + if test "$hardcode_direct" != unsupported; then + test -n "$old_library" && linklib="$old_library" + compile_deplibs="$dir/$linklib $compile_deplibs" + finalize_deplibs="$dir/$linklib $finalize_deplibs" + else + compile_deplibs="-l$name -L$dir $compile_deplibs" + finalize_deplibs="-l$name -L$dir $finalize_deplibs" + fi + elif test "$build_libtool_libs" = yes; then + # Not a shared library + if test "$deplibs_check_method" != pass_all; then + # We're trying link a shared library against a static one + # but the system doesn't support it. + + # Just print a warning and add the library to dependency_libs so + # that the program can be linked against the static library. + $ECHO + $ECHO "*** Warning: This system can not link to static lib archive $lib." + $ECHO "*** I have the capability to make that library automatically link in when" + $ECHO "*** you link to this library. But I can only do this if you have a" + $ECHO "*** shared version of the library, which you do not appear to have." + if test "$module" = yes; then + $ECHO "*** But as you try to build a module library, libtool will still create " + $ECHO "*** a static module, that should work as long as the dlopening application" + $ECHO "*** is linked with the -dlopen flag to resolve symbols at runtime." + if test -z "$global_symbol_pipe"; then + $ECHO + $ECHO "*** However, this would only work if libtool was able to extract symbol" + $ECHO "*** lists from a program, using \`nm' or equivalent, but libtool could" + $ECHO "*** not find such a program. So, this module is probably useless." + $ECHO "*** \`nm' from GNU binutils and a full rebuild may help." + fi + if test "$build_old_libs" = no; then + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + fi + else + deplibs="$dir/$old_library $deplibs" + link_static=yes + fi + fi # link shared/static library? + + if test "$linkmode" = lib; then + if test -n "$dependency_libs" && + { test "$hardcode_into_libs" != yes || + test "$build_old_libs" = yes || + test "$link_static" = yes; }; then + # Extract -R from dependency_libs + temp_deplibs= + for libdir in $dependency_libs; do + case $libdir in + -R*) func_stripname '-R' '' "$libdir" + temp_xrpath=$func_stripname_result + case " $xrpath " in + *" $temp_xrpath "*) ;; + *) xrpath="$xrpath $temp_xrpath";; + esac;; + *) temp_deplibs="$temp_deplibs $libdir";; + esac + done + dependency_libs="$temp_deplibs" + fi + + newlib_search_path="$newlib_search_path $absdir" + # Link against this library + test "$link_static" = no && newdependency_libs="$abs_ladir/$laname $newdependency_libs" + # ... and its dependency_libs + tmp_libs= + for deplib in $dependency_libs; do + newdependency_libs="$deplib $newdependency_libs" + if $opt_duplicate_deps ; then + case "$tmp_libs " in + *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; + esac + fi + tmp_libs="$tmp_libs $deplib" + done + + if test "$link_all_deplibs" != no; then + # Add the search paths of all dependency libraries + for deplib in $dependency_libs; do + path= + case $deplib in + -L*) path="$deplib" ;; + *.la) + func_dirname "$deplib" "" "." + dir="$func_dirname_result" + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) absdir="$dir" ;; + *) + absdir=`cd "$dir" && pwd` + if test -z "$absdir"; then + func_warning "cannot determine absolute directory name of \`$dir'" + absdir="$dir" + fi + ;; + esac + if $GREP "^installed=no" $deplib > /dev/null; then + case $host in + *-*-darwin*) + depdepl= + eval deplibrary_names=`${SED} -n -e 's/^library_names=\(.*\)$/\1/p' $deplib` + if test -n "$deplibrary_names" ; then + for tmp in $deplibrary_names ; do + depdepl=$tmp + done + if test -f "$absdir/$objdir/$depdepl" ; then + depdepl="$absdir/$objdir/$depdepl" + darwin_install_name=`${OTOOL} -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` + if test -z "$darwin_install_name"; then + darwin_install_name=`${OTOOL64} -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` + fi + compiler_flags="$compiler_flags ${wl}-dylib_file ${wl}${darwin_install_name}:${depdepl}" + linker_flags="$linker_flags -dylib_file ${darwin_install_name}:${depdepl}" + path= + fi + fi + ;; + *) + path="-L$absdir/$objdir" + ;; + esac + else + eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` + test -z "$libdir" && \ + func_fatal_error "\`$deplib' is not a valid libtool archive" + test "$absdir" != "$libdir" && \ + func_warning "\`$deplib' seems to be moved" + + path="-L$absdir" + fi + ;; + esac + case " $deplibs " in + *" $path "*) ;; + *) deplibs="$path $deplibs" ;; + esac + done + fi # link_all_deplibs != no + fi # linkmode = lib + done # for deplib in $libs + if test "$pass" = link; then + if test "$linkmode" = "prog"; then + compile_deplibs="$new_inherited_linker_flags $compile_deplibs" + finalize_deplibs="$new_inherited_linker_flags $finalize_deplibs" + else + compiler_flags="$compiler_flags "`$ECHO "X $new_inherited_linker_flags" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'` + fi + fi + dependency_libs="$newdependency_libs" + if test "$pass" = dlpreopen; then + # Link the dlpreopened libraries before other libraries + for deplib in $save_deplibs; do + deplibs="$deplib $deplibs" + done + fi + if test "$pass" != dlopen; then + if test "$pass" != conv; then + # Make sure lib_search_path contains only unique directories. + lib_search_path= + for dir in $newlib_search_path; do + case "$lib_search_path " in + *" $dir "*) ;; + *) lib_search_path="$lib_search_path $dir" ;; + esac + done + newlib_search_path= + fi + + if test "$linkmode,$pass" != "prog,link"; then + vars="deplibs" + else + vars="compile_deplibs finalize_deplibs" + fi + for var in $vars dependency_libs; do + # Add libraries to $var in reverse order + eval tmp_libs=\"\$$var\" + new_libs= + for deplib in $tmp_libs; do + # FIXME: Pedantically, this is the right thing to do, so + # that some nasty dependency loop isn't accidentally + # broken: + #new_libs="$deplib $new_libs" + # Pragmatically, this seems to cause very few problems in + # practice: + case $deplib in + -L*) new_libs="$deplib $new_libs" ;; + -R*) ;; + *) + # And here is the reason: when a library appears more + # than once as an explicit dependence of a library, or + # is implicitly linked in more than once by the + # compiler, it is considered special, and multiple + # occurrences thereof are not removed. Compare this + # with having the same library being listed as a + # dependency of multiple other libraries: in this case, + # we know (pedantically, we assume) the library does not + # need to be listed more than once, so we keep only the + # last copy. This is not always right, but it is rare + # enough that we require users that really mean to play + # such unportable linking tricks to link the library + # using -Wl,-lname, so that libtool does not consider it + # for duplicate removal. + case " $specialdeplibs " in + *" $deplib "*) new_libs="$deplib $new_libs" ;; + *) + case " $new_libs " in + *" $deplib "*) ;; + *) new_libs="$deplib $new_libs" ;; + esac + ;; + esac + ;; + esac + done + tmp_libs= + for deplib in $new_libs; do + case $deplib in + -L*) + case " $tmp_libs " in + *" $deplib "*) ;; + *) tmp_libs="$tmp_libs $deplib" ;; + esac + ;; + *) tmp_libs="$tmp_libs $deplib" ;; + esac + done + eval $var=\"$tmp_libs\" + done # for var + fi + # Last step: remove runtime libs from dependency_libs + # (they stay in deplibs) + tmp_libs= + for i in $dependency_libs ; do + case " $predeps $postdeps $compiler_lib_search_path " in + *" $i "*) + i="" + ;; + esac + if test -n "$i" ; then + tmp_libs="$tmp_libs $i" + fi + done + dependency_libs=$tmp_libs + done # for pass + if test "$linkmode" = prog; then + dlfiles="$newdlfiles" + fi + if test "$linkmode" = prog || test "$linkmode" = lib; then + dlprefiles="$newdlprefiles" + fi + + case $linkmode in + oldlib) + if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then + func_warning "\`-dlopen' is ignored for archives" + fi + + case " $deplibs" in + *\ -l* | *\ -L*) + func_warning "\`-l' and \`-L' are ignored for archives" ;; + esac + + test -n "$rpath" && \ + func_warning "\`-rpath' is ignored for archives" + + test -n "$xrpath" && \ + func_warning "\`-R' is ignored for archives" + + test -n "$vinfo" && \ + func_warning "\`-version-info/-version-number' is ignored for archives" + + test -n "$release" && \ + func_warning "\`-release' is ignored for archives" + + test -n "$export_symbols$export_symbols_regex" && \ + func_warning "\`-export-symbols' is ignored for archives" + + # Now set the variables for building old libraries. + build_libtool_libs=no + oldlibs="$output" + objs="$objs$old_deplibs" + ;; + + lib) + # Make sure we only generate libraries of the form `libNAME.la'. + case $outputname in + lib*) + func_stripname 'lib' '.la' "$outputname" + name=$func_stripname_result + eval shared_ext=\"$shrext_cmds\" + eval libname=\"$libname_spec\" + ;; + *) + test "$module" = no && \ + func_fatal_help "libtool library \`$output' must begin with \`lib'" + + if test "$need_lib_prefix" != no; then + # Add the "lib" prefix for modules if required + func_stripname '' '.la' "$outputname" + name=$func_stripname_result + eval shared_ext=\"$shrext_cmds\" + eval libname=\"$libname_spec\" + else + func_stripname '' '.la' "$outputname" + libname=$func_stripname_result + fi + ;; + esac + + if test -n "$objs"; then + if test "$deplibs_check_method" != pass_all; then + func_fatal_error "cannot build libtool library \`$output' from non-libtool objects on this host:$objs" + else + $ECHO + $ECHO "*** Warning: Linking the shared library $output against the non-libtool" + $ECHO "*** objects $objs is not portable!" + libobjs="$libobjs $objs" + fi + fi + + test "$dlself" != no && \ + func_warning "\`-dlopen self' is ignored for libtool libraries" + + set dummy $rpath + shift + test "$#" -gt 1 && \ + func_warning "ignoring multiple \`-rpath's for a libtool library" + + install_libdir="$1" + + oldlibs= + if test -z "$rpath"; then + if test "$build_libtool_libs" = yes; then + # Building a libtool convenience library. + # Some compilers have problems with a `.al' extension so + # convenience libraries should have the same extension an + # archive normally would. + oldlibs="$output_objdir/$libname.$libext $oldlibs" + build_libtool_libs=convenience + build_old_libs=yes + fi + + test -n "$vinfo" && \ + func_warning "\`-version-info/-version-number' is ignored for convenience libraries" + + test -n "$release" && \ + func_warning "\`-release' is ignored for convenience libraries" + else + + # Parse the version information argument. + save_ifs="$IFS"; IFS=':' + set dummy $vinfo 0 0 0 + shift + IFS="$save_ifs" + + test -n "$7" && \ + func_fatal_help "too many parameters to \`-version-info'" + + # convert absolute version numbers to libtool ages + # this retains compatibility with .la files and attempts + # to make the code below a bit more comprehensible + + case $vinfo_number in + yes) + number_major="$1" + number_minor="$2" + number_revision="$3" + # + # There are really only two kinds -- those that + # use the current revision as the major version + # and those that subtract age and use age as + # a minor version. But, then there is irix + # which has an extra 1 added just for fun + # + case $version_type in + darwin|linux|osf|windows|none) + func_arith $number_major + $number_minor + current=$func_arith_result + age="$number_minor" + revision="$number_revision" + ;; + freebsd-aout|freebsd-elf|sunos) + current="$number_major" + revision="$number_minor" + age="0" + ;; + irix|nonstopux) + func_arith $number_major + $number_minor + current=$func_arith_result + age="$number_minor" + revision="$number_minor" + lt_irix_increment=no + ;; + *) + func_fatal_configuration "$modename: unknown library version type \`$version_type'" + ;; + esac + ;; + no) + current="$1" + revision="$2" + age="$3" + ;; + esac + + # Check that each of the things are valid numbers. + case $current in + 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; + *) + func_error "CURRENT \`$current' must be a nonnegative integer" + func_fatal_error "\`$vinfo' is not valid version information" + ;; + esac + + case $revision in + 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; + *) + func_error "REVISION \`$revision' must be a nonnegative integer" + func_fatal_error "\`$vinfo' is not valid version information" + ;; + esac + + case $age in + 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; + *) + func_error "AGE \`$age' must be a nonnegative integer" + func_fatal_error "\`$vinfo' is not valid version information" + ;; + esac + + if test "$age" -gt "$current"; then + func_error "AGE \`$age' is greater than the current interface number \`$current'" + func_fatal_error "\`$vinfo' is not valid version information" + fi + + # Calculate the version variables. + major= + versuffix= + verstring= + case $version_type in + none) ;; + + darwin) + # Like Linux, but with the current version available in + # verstring for coding it into the library header + func_arith $current - $age + major=.$func_arith_result + versuffix="$major.$age.$revision" + # Darwin ld doesn't like 0 for these options... + func_arith $current + 1 + minor_current=$func_arith_result + xlcverstring="${wl}-compatibility_version ${wl}$minor_current ${wl}-current_version ${wl}$minor_current.$revision" + verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" + ;; + + freebsd-aout) + major=".$current" + versuffix=".$current.$revision"; + ;; + + freebsd-elf) + major=".$current" + versuffix=".$current" + ;; + + irix | nonstopux) + if test "X$lt_irix_increment" = "Xno"; then + func_arith $current - $age + else + func_arith $current - $age + 1 + fi + major=$func_arith_result + + case $version_type in + nonstopux) verstring_prefix=nonstopux ;; + *) verstring_prefix=sgi ;; + esac + verstring="$verstring_prefix$major.$revision" + + # Add in all the interfaces that we are compatible with. + loop=$revision + while test "$loop" -ne 0; do + func_arith $revision - $loop + iface=$func_arith_result + func_arith $loop - 1 + loop=$func_arith_result + verstring="$verstring_prefix$major.$iface:$verstring" + done + + # Before this point, $major must not contain `.'. + major=.$major + versuffix="$major.$revision" + ;; + + linux) + func_arith $current - $age + major=.$func_arith_result + versuffix="$major.$age.$revision" + ;; + + osf) + func_arith $current - $age + major=.$func_arith_result + versuffix=".$current.$age.$revision" + verstring="$current.$age.$revision" + + # Add in all the interfaces that we are compatible with. + loop=$age + while test "$loop" -ne 0; do + func_arith $current - $loop + iface=$func_arith_result + func_arith $loop - 1 + loop=$func_arith_result + verstring="$verstring:${iface}.0" + done + + # Make executables depend on our current version. + verstring="$verstring:${current}.0" + ;; + + qnx) + major=".$current" + versuffix=".$current" + ;; + + sunos) + major=".$current" + versuffix=".$current.$revision" + ;; + + windows) + # Use '-' rather than '.', since we only want one + # extension on DOS 8.3 filesystems. + func_arith $current - $age + major=$func_arith_result + versuffix="-$major" + ;; + + *) + func_fatal_configuration "unknown library version type \`$version_type'" + ;; + esac + + # Clear the version info if we defaulted, and they specified a release. + if test -z "$vinfo" && test -n "$release"; then + major= + case $version_type in + darwin) + # we can't check for "0.0" in archive_cmds due to quoting + # problems, so we reset it completely + verstring= + ;; + *) + verstring="0.0" + ;; + esac + if test "$need_version" = no; then + versuffix= + else + versuffix=".0.0" + fi + fi + + # Remove version info from name if versioning should be avoided + if test "$avoid_version" = yes && test "$need_version" = no; then + major= + versuffix= + verstring="" + fi + + # Check to see if the archive will have undefined symbols. + if test "$allow_undefined" = yes; then + if test "$allow_undefined_flag" = unsupported; then + func_warning "undefined symbols not allowed in $host shared libraries" + build_libtool_libs=no + build_old_libs=yes + fi + else + # Don't allow undefined symbols. + allow_undefined_flag="$no_undefined_flag" + fi + + fi + + func_generate_dlsyms "$libname" "$libname" "yes" + libobjs="$libobjs $symfileobj" + test "X$libobjs" = "X " && libobjs= + + if test "$mode" != relink; then + # Remove our outputs, but don't remove object files since they + # may have been created when compiling PIC objects. + removelist= + tempremovelist=`$ECHO "$output_objdir/*"` + for p in $tempremovelist; do + case $p in + *.$objext | *.gcno) + ;; + $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/${libname}${release}.*) + if test "X$precious_files_regex" != "X"; then + if $ECHO "$p" | $EGREP -e "$precious_files_regex" >/dev/null 2>&1 + then + continue + fi + fi + removelist="$removelist $p" + ;; + *) ;; + esac + done + test -n "$removelist" && \ + func_show_eval "${RM}r \$removelist" + fi + + # Now set the variables for building old libraries. + if test "$build_old_libs" = yes && test "$build_libtool_libs" != convenience ; then + oldlibs="$oldlibs $output_objdir/$libname.$libext" + + # Transform .lo files to .o files. + oldobjs="$objs "`$ECHO "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}'$/d' -e "$lo2o" | $NL2SP` + fi + + # Eliminate all temporary directories. + #for path in $notinst_path; do + # lib_search_path=`$ECHO "X$lib_search_path " | $Xsed -e "s% $path % %g"` + # deplibs=`$ECHO "X$deplibs " | $Xsed -e "s% -L$path % %g"` + # dependency_libs=`$ECHO "X$dependency_libs " | $Xsed -e "s% -L$path % %g"` + #done + + if test -n "$xrpath"; then + # If the user specified any rpath flags, then add them. + temp_xrpath= + for libdir in $xrpath; do + temp_xrpath="$temp_xrpath -R$libdir" + case "$finalize_rpath " in + *" $libdir "*) ;; + *) finalize_rpath="$finalize_rpath $libdir" ;; + esac + done + if test "$hardcode_into_libs" != yes || test "$build_old_libs" = yes; then + dependency_libs="$temp_xrpath $dependency_libs" + fi + fi + + # Make sure dlfiles contains only unique files that won't be dlpreopened + old_dlfiles="$dlfiles" + dlfiles= + for lib in $old_dlfiles; do + case " $dlprefiles $dlfiles " in + *" $lib "*) ;; + *) dlfiles="$dlfiles $lib" ;; + esac + done + + # Make sure dlprefiles contains only unique files + old_dlprefiles="$dlprefiles" + dlprefiles= + for lib in $old_dlprefiles; do + case "$dlprefiles " in + *" $lib "*) ;; + *) dlprefiles="$dlprefiles $lib" ;; + esac + done + + if test "$build_libtool_libs" = yes; then + if test -n "$rpath"; then + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos* | *-cegcc*) + # these systems don't actually have a c library (as such)! + ;; + *-*-rhapsody* | *-*-darwin1.[012]) + # Rhapsody C library is in the System framework + deplibs="$deplibs System.ltframework" + ;; + *-*-netbsd*) + # Don't link with libc until the a.out ld.so is fixed. + ;; + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) + # Do not include libc due to us having libc/libc_r. + ;; + *-*-sco3.2v5* | *-*-sco5v6*) + # Causes problems with __ctype + ;; + *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) + # Compiler inserts libc in the correct place for threads to work + ;; + *) + # Add libc to deplibs on all other systems if necessary. + if test "$build_libtool_need_lc" = "yes"; then + deplibs="$deplibs -lc" + fi + ;; + esac + fi + + # Transform deplibs into only deplibs that can be linked in shared. + name_save=$name + libname_save=$libname + release_save=$release + versuffix_save=$versuffix + major_save=$major + # I'm not sure if I'm treating the release correctly. I think + # release should show up in the -l (ie -lgmp5) so we don't want to + # add it in twice. Is that correct? + release="" + versuffix="" + major="" + newdeplibs= + droppeddeps=no + case $deplibs_check_method in + pass_all) + # Don't check for shared/static. Everything works. + # This might be a little naive. We might want to check + # whether the library exists or not. But this is on + # osf3 & osf4 and I'm not really sure... Just + # implementing what was already the behavior. + newdeplibs=$deplibs + ;; + test_compile) + # This code stresses the "libraries are programs" paradigm to its + # limits. Maybe even breaks it. We compile a program, linking it + # against the deplibs as a proxy for the library. Then we can check + # whether they linked in statically or dynamically with ldd. + $opt_dry_run || $RM conftest.c + cat > conftest.c </dev/null` + for potent_lib in $potential_libs; do + # Follow soft links. + if ls -lLd "$potent_lib" 2>/dev/null | + $GREP " -> " >/dev/null; then + continue + fi + # The statement above tries to avoid entering an + # endless loop below, in case of cyclic links. + # We might still enter an endless loop, since a link + # loop can be closed while we follow links, + # but so what? + potlib="$potent_lib" + while test -h "$potlib" 2>/dev/null; do + potliblink=`ls -ld $potlib | ${SED} 's/.* -> //'` + case $potliblink in + [\\/]* | [A-Za-z]:[\\/]*) potlib="$potliblink";; + *) potlib=`$ECHO "X$potlib" | $Xsed -e 's,[^/]*$,,'`"$potliblink";; + esac + done + if eval $file_magic_cmd \"\$potlib\" 2>/dev/null | + $SED -e 10q | + $EGREP "$file_magic_regex" > /dev/null; then + newdeplibs="$newdeplibs $a_deplib" + a_deplib="" + break 2 + fi + done + done + fi + if test -n "$a_deplib" ; then + droppeddeps=yes + $ECHO + $ECHO "*** Warning: linker path does not have real file for library $a_deplib." + $ECHO "*** I have the capability to make that library automatically link in when" + $ECHO "*** you link to this library. But I can only do this if you have a" + $ECHO "*** shared version of the library, which you do not appear to have" + $ECHO "*** because I did check the linker path looking for a file starting" + if test -z "$potlib" ; then + $ECHO "*** with $libname but no candidates were found. (...for file magic test)" + else + $ECHO "*** with $libname and none of the candidates passed a file format test" + $ECHO "*** using a file magic. Last file checked: $potlib" + fi + fi + ;; + *) + # Add a -L argument. + newdeplibs="$newdeplibs $a_deplib" + ;; + esac + done # Gone through all deplibs. + ;; + match_pattern*) + set dummy $deplibs_check_method; shift + match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` + for a_deplib in $deplibs; do + case $a_deplib in + -l*) + func_stripname -l '' "$a_deplib" + name=$func_stripname_result + if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then + case " $predeps $postdeps " in + *" $a_deplib "*) + newdeplibs="$newdeplibs $a_deplib" + a_deplib="" + ;; + esac + fi + if test -n "$a_deplib" ; then + libname=`eval "\\$ECHO \"$libname_spec\""` + for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do + potential_libs=`ls $i/$libname[.-]* 2>/dev/null` + for potent_lib in $potential_libs; do + potlib="$potent_lib" # see symlink-check above in file_magic test + if eval "\$ECHO \"X$potent_lib\"" 2>/dev/null | $Xsed -e 10q | \ + $EGREP "$match_pattern_regex" > /dev/null; then + newdeplibs="$newdeplibs $a_deplib" + a_deplib="" + break 2 + fi + done + done + fi + if test -n "$a_deplib" ; then + droppeddeps=yes + $ECHO + $ECHO "*** Warning: linker path does not have real file for library $a_deplib." + $ECHO "*** I have the capability to make that library automatically link in when" + $ECHO "*** you link to this library. But I can only do this if you have a" + $ECHO "*** shared version of the library, which you do not appear to have" + $ECHO "*** because I did check the linker path looking for a file starting" + if test -z "$potlib" ; then + $ECHO "*** with $libname but no candidates were found. (...for regex pattern test)" + else + $ECHO "*** with $libname and none of the candidates passed a file format test" + $ECHO "*** using a regex pattern. Last file checked: $potlib" + fi + fi + ;; + *) + # Add a -L argument. + newdeplibs="$newdeplibs $a_deplib" + ;; + esac + done # Gone through all deplibs. + ;; + none | unknown | *) + newdeplibs="" + tmp_deplibs=`$ECHO "X $deplibs" | $Xsed \ + -e 's/ -lc$//' -e 's/ -[LR][^ ]*//g'` + if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then + for i in $predeps $postdeps ; do + # can't use Xsed below, because $i might contain '/' + tmp_deplibs=`$ECHO "X $tmp_deplibs" | $Xsed -e "s,$i,,"` + done + fi + if $ECHO "X $tmp_deplibs" | $Xsed -e 's/[ ]//g' | + $GREP . >/dev/null; then + $ECHO + if test "X$deplibs_check_method" = "Xnone"; then + $ECHO "*** Warning: inter-library dependencies are not supported in this platform." + else + $ECHO "*** Warning: inter-library dependencies are not known to be supported." + fi + $ECHO "*** All declared inter-library dependencies are being dropped." + droppeddeps=yes + fi + ;; + esac + versuffix=$versuffix_save + major=$major_save + release=$release_save + libname=$libname_save + name=$name_save + + case $host in + *-*-rhapsody* | *-*-darwin1.[012]) + # On Rhapsody replace the C library with the System framework + newdeplibs=`$ECHO "X $newdeplibs" | $Xsed -e 's/ -lc / System.ltframework /'` + ;; + esac + + if test "$droppeddeps" = yes; then + if test "$module" = yes; then + $ECHO + $ECHO "*** Warning: libtool could not satisfy all declared inter-library" + $ECHO "*** dependencies of module $libname. Therefore, libtool will create" + $ECHO "*** a static module, that should work as long as the dlopening" + $ECHO "*** application is linked with the -dlopen flag." + if test -z "$global_symbol_pipe"; then + $ECHO + $ECHO "*** However, this would only work if libtool was able to extract symbol" + $ECHO "*** lists from a program, using \`nm' or equivalent, but libtool could" + $ECHO "*** not find such a program. So, this module is probably useless." + $ECHO "*** \`nm' from GNU binutils and a full rebuild may help." + fi + if test "$build_old_libs" = no; then + oldlibs="$output_objdir/$libname.$libext" + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + else + $ECHO "*** The inter-library dependencies that have been dropped here will be" + $ECHO "*** automatically added whenever a program is linked with this library" + $ECHO "*** or is declared to -dlopen it." + + if test "$allow_undefined" = no; then + $ECHO + $ECHO "*** Since this library must not contain undefined symbols," + $ECHO "*** because either the platform does not support them or" + $ECHO "*** it was explicitly requested with -no-undefined," + $ECHO "*** libtool will only create a static version of it." + if test "$build_old_libs" = no; then + oldlibs="$output_objdir/$libname.$libext" + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + fi + fi + fi + # Done checking deplibs! + deplibs=$newdeplibs + fi + # Time to change all our "foo.ltframework" stuff back to "-framework foo" + case $host in + *-*-darwin*) + newdeplibs=`$ECHO "X $newdeplibs" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'` + new_inherited_linker_flags=`$ECHO "X $new_inherited_linker_flags" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'` + deplibs=`$ECHO "X $deplibs" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'` + ;; + esac + + # move library search paths that coincide with paths to not yet + # installed libraries to the beginning of the library search list + new_libs= + for path in $notinst_path; do + case " $new_libs " in + *" -L$path/$objdir "*) ;; + *) + case " $deplibs " in + *" -L$path/$objdir "*) + new_libs="$new_libs -L$path/$objdir" ;; + esac + ;; + esac + done + for deplib in $deplibs; do + case $deplib in + -L*) + case " $new_libs " in + *" $deplib "*) ;; + *) new_libs="$new_libs $deplib" ;; + esac + ;; + *) new_libs="$new_libs $deplib" ;; + esac + done + deplibs="$new_libs" + + # All the library-specific variables (install_libdir is set above). + library_names= + old_library= + dlname= + + # Test again, we may have decided not to build it any more + if test "$build_libtool_libs" = yes; then + if test "$hardcode_into_libs" = yes; then + # Hardcode the library paths + hardcode_libdirs= + dep_rpath= + rpath="$finalize_rpath" + test "$mode" != relink && rpath="$compile_rpath$rpath" + for libdir in $rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + if test -z "$hardcode_libdirs"; then + hardcode_libdirs="$libdir" + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + dep_rpath="$dep_rpath $flag" + fi + elif test -n "$runpath_var"; then + case "$perm_rpath " in + *" $libdir "*) ;; + *) perm_rpath="$perm_rpath $libdir" ;; + esac + fi + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir="$hardcode_libdirs" + if test -n "$hardcode_libdir_flag_spec_ld"; then + eval dep_rpath=\"$hardcode_libdir_flag_spec_ld\" + else + eval dep_rpath=\"$hardcode_libdir_flag_spec\" + fi + fi + if test -n "$runpath_var" && test -n "$perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $perm_rpath; do + rpath="$rpath$dir:" + done + eval "$runpath_var='$rpath\$$runpath_var'; export $runpath_var" + fi + test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs" + fi + + shlibpath="$finalize_shlibpath" + test "$mode" != relink && shlibpath="$compile_shlibpath$shlibpath" + if test -n "$shlibpath"; then + eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var" + fi + + # Get the real and link names of the library. + eval shared_ext=\"$shrext_cmds\" + eval library_names=\"$library_names_spec\" + set dummy $library_names + shift + realname="$1" + shift + + if test -n "$soname_spec"; then + eval soname=\"$soname_spec\" + else + soname="$realname" + fi + if test -z "$dlname"; then + dlname=$soname + fi + + lib="$output_objdir/$realname" + linknames= + for link + do + linknames="$linknames $link" + done + + # Use standard objects if they are pic + test -z "$pic_flag" && libobjs=`$ECHO "X$libobjs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` + test "X$libobjs" = "X " && libobjs= + + delfiles= + if test -n "$export_symbols" && test -n "$include_expsyms"; then + $opt_dry_run || cp "$export_symbols" "$output_objdir/$libname.uexp" + export_symbols="$output_objdir/$libname.uexp" + delfiles="$delfiles $export_symbols" + fi + + orig_export_symbols= + case $host_os in + cygwin* | mingw* | cegcc*) + if test -n "$export_symbols" && test -z "$export_symbols_regex"; then + # exporting using user supplied symfile + if test "x`$SED 1q $export_symbols`" != xEXPORTS; then + # and it's NOT already a .def file. Must figure out + # which of the given symbols are data symbols and tag + # them as such. So, trigger use of export_symbols_cmds. + # export_symbols gets reassigned inside the "prepare + # the list of exported symbols" if statement, so the + # include_expsyms logic still works. + orig_export_symbols="$export_symbols" + export_symbols= + always_export_symbols=yes + fi + fi + ;; + esac + + # Prepare the list of exported symbols + if test -z "$export_symbols"; then + if test "$always_export_symbols" = yes || test -n "$export_symbols_regex"; then + func_verbose "generating symbol list for \`$libname.la'" + export_symbols="$output_objdir/$libname.exp" + $opt_dry_run || $RM $export_symbols + cmds=$export_symbols_cmds + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + func_len " $cmd" + len=$func_len_result + if test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then + func_show_eval "$cmd" 'exit $?' + skipped_export=false + else + # The command line is too long to execute in one step. + func_verbose "using reloadable object file for export list..." + skipped_export=: + # Break out early, otherwise skipped_export may be + # set to false by a later but shorter cmd. + break + fi + done + IFS="$save_ifs" + if test -n "$export_symbols_regex" && test "X$skipped_export" != "X:"; then + func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' + func_show_eval '$MV "${export_symbols}T" "$export_symbols"' + fi + fi + fi + + if test -n "$export_symbols" && test -n "$include_expsyms"; then + tmp_export_symbols="$export_symbols" + test -n "$orig_export_symbols" && tmp_export_symbols="$orig_export_symbols" + $opt_dry_run || eval '$ECHO "X$include_expsyms" | $Xsed | $SP2NL >> "$tmp_export_symbols"' + fi + + if test "X$skipped_export" != "X:" && test -n "$orig_export_symbols"; then + # The given exports_symbols file has to be filtered, so filter it. + func_verbose "filter symbol list for \`$libname.la' to tag DATA exports" + # FIXME: $output_objdir/$libname.filter potentially contains lots of + # 's' commands which not all seds can handle. GNU sed should be fine + # though. Also, the filter scales superlinearly with the number of + # global variables. join(1) would be nice here, but unfortunately + # isn't a blessed tool. + $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter + delfiles="$delfiles $export_symbols $output_objdir/$libname.filter" + export_symbols=$output_objdir/$libname.def + $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols + fi + + tmp_deplibs= + for test_deplib in $deplibs; do + case " $convenience " in + *" $test_deplib "*) ;; + *) + tmp_deplibs="$tmp_deplibs $test_deplib" + ;; + esac + done + deplibs="$tmp_deplibs" + + if test -n "$convenience"; then + if test -n "$whole_archive_flag_spec" && + test "$compiler_needs_object" = yes && + test -z "$libobjs"; then + # extract the archives, so we have objects to list. + # TODO: could optimize this to just extract one archive. + whole_archive_flag_spec= + fi + if test -n "$whole_archive_flag_spec"; then + save_libobjs=$libobjs + eval libobjs=\"\$libobjs $whole_archive_flag_spec\" + test "X$libobjs" = "X " && libobjs= + else + gentop="$output_objdir/${outputname}x" + generated="$generated $gentop" + + func_extract_archives $gentop $convenience + libobjs="$libobjs $func_extract_archives_result" + test "X$libobjs" = "X " && libobjs= + fi + fi + + if test "$thread_safe" = yes && test -n "$thread_safe_flag_spec"; then + eval flag=\"$thread_safe_flag_spec\" + linker_flags="$linker_flags $flag" + fi + + # Make a backup of the uninstalled library when relinking + if test "$mode" = relink; then + $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}U && $MV $realname ${realname}U)' || exit $? + fi + + # Do each of the archive commands. + if test "$module" = yes && test -n "$module_cmds" ; then + if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then + eval test_cmds=\"$module_expsym_cmds\" + cmds=$module_expsym_cmds + else + eval test_cmds=\"$module_cmds\" + cmds=$module_cmds + fi + else + if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then + eval test_cmds=\"$archive_expsym_cmds\" + cmds=$archive_expsym_cmds + else + eval test_cmds=\"$archive_cmds\" + cmds=$archive_cmds + fi + fi + + if test "X$skipped_export" != "X:" && + func_len " $test_cmds" && + len=$func_len_result && + test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then + : + else + # The command line is too long to link in one step, link piecewise + # or, if using GNU ld and skipped_export is not :, use a linker + # script. + + # Save the value of $output and $libobjs because we want to + # use them later. If we have whole_archive_flag_spec, we + # want to use save_libobjs as it was before + # whole_archive_flag_spec was expanded, because we can't + # assume the linker understands whole_archive_flag_spec. + # This may have to be revisited, in case too many + # convenience libraries get linked in and end up exceeding + # the spec. + if test -z "$convenience" || test -z "$whole_archive_flag_spec"; then + save_libobjs=$libobjs + fi + save_output=$output + output_la=`$ECHO "X$output" | $Xsed -e "$basename"` + + # Clear the reloadable object creation command queue and + # initialize k to one. + test_cmds= + concat_cmds= + objlist= + last_robj= + k=1 + + if test -n "$save_libobjs" && test "X$skipped_export" != "X:" && test "$with_gnu_ld" = yes; then + output=${output_objdir}/${output_la}.lnkscript + func_verbose "creating GNU ld script: $output" + $ECHO 'INPUT (' > $output + for obj in $save_libobjs + do + $ECHO "$obj" >> $output + done + $ECHO ')' >> $output + delfiles="$delfiles $output" + elif test -n "$save_libobjs" && test "X$skipped_export" != "X:" && test "X$file_list_spec" != X; then + output=${output_objdir}/${output_la}.lnk + func_verbose "creating linker input file list: $output" + : > $output + set x $save_libobjs + shift + firstobj= + if test "$compiler_needs_object" = yes; then + firstobj="$1 " + shift + fi + for obj + do + $ECHO "$obj" >> $output + done + delfiles="$delfiles $output" + output=$firstobj\"$file_list_spec$output\" + else + if test -n "$save_libobjs"; then + func_verbose "creating reloadable object files..." + output=$output_objdir/$output_la-${k}.$objext + eval test_cmds=\"$reload_cmds\" + func_len " $test_cmds" + len0=$func_len_result + len=$len0 + + # Loop over the list of objects to be linked. + for obj in $save_libobjs + do + func_len " $obj" + func_arith $len + $func_len_result + len=$func_arith_result + if test "X$objlist" = X || + test "$len" -lt "$max_cmd_len"; then + func_append objlist " $obj" + else + # The command $test_cmds is almost too long, add a + # command to the queue. + if test "$k" -eq 1 ; then + # The first file doesn't have a previous command to add. + eval concat_cmds=\"$reload_cmds $objlist $last_robj\" + else + # All subsequent reloadable object files will link in + # the last one created. + eval concat_cmds=\"\$concat_cmds~$reload_cmds $objlist $last_robj~\$RM $last_robj\" + fi + last_robj=$output_objdir/$output_la-${k}.$objext + func_arith $k + 1 + k=$func_arith_result + output=$output_objdir/$output_la-${k}.$objext + objlist=$obj + func_len " $last_robj" + func_arith $len0 + $func_len_result + len=$func_arith_result + fi + done + # Handle the remaining objects by creating one last + # reloadable object file. All subsequent reloadable object + # files will link in the last one created. + test -z "$concat_cmds" || concat_cmds=$concat_cmds~ + eval concat_cmds=\"\${concat_cmds}$reload_cmds $objlist $last_robj\" + if test -n "$last_robj"; then + eval concat_cmds=\"\${concat_cmds}~\$RM $last_robj\" + fi + delfiles="$delfiles $output" + + else + output= + fi + + if ${skipped_export-false}; then + func_verbose "generating symbol list for \`$libname.la'" + export_symbols="$output_objdir/$libname.exp" + $opt_dry_run || $RM $export_symbols + libobjs=$output + # Append the command to create the export file. + test -z "$concat_cmds" || concat_cmds=$concat_cmds~ + eval concat_cmds=\"\$concat_cmds$export_symbols_cmds\" + if test -n "$last_robj"; then + eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\" + fi + fi + + test -n "$save_libobjs" && + func_verbose "creating a temporary reloadable object file: $output" + + # Loop through the commands generated above and execute them. + save_ifs="$IFS"; IFS='~' + for cmd in $concat_cmds; do + IFS="$save_ifs" + $opt_silent || { + func_quote_for_expand "$cmd" + eval "func_echo $func_quote_for_expand_result" + } + $opt_dry_run || eval "$cmd" || { + lt_exit=$? + + # Restore the uninstalled library and exit + if test "$mode" = relink; then + ( cd "$output_objdir" && \ + $RM "${realname}T" && \ + $MV "${realname}U" "$realname" ) + fi + + exit $lt_exit + } + done + IFS="$save_ifs" + + if test -n "$export_symbols_regex" && ${skipped_export-false}; then + func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' + func_show_eval '$MV "${export_symbols}T" "$export_symbols"' + fi + fi + + if ${skipped_export-false}; then + if test -n "$export_symbols" && test -n "$include_expsyms"; then + tmp_export_symbols="$export_symbols" + test -n "$orig_export_symbols" && tmp_export_symbols="$orig_export_symbols" + $opt_dry_run || eval '$ECHO "X$include_expsyms" | $Xsed | $SP2NL >> "$tmp_export_symbols"' + fi + + if test -n "$orig_export_symbols"; then + # The given exports_symbols file has to be filtered, so filter it. + func_verbose "filter symbol list for \`$libname.la' to tag DATA exports" + # FIXME: $output_objdir/$libname.filter potentially contains lots of + # 's' commands which not all seds can handle. GNU sed should be fine + # though. Also, the filter scales superlinearly with the number of + # global variables. join(1) would be nice here, but unfortunately + # isn't a blessed tool. + $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter + delfiles="$delfiles $export_symbols $output_objdir/$libname.filter" + export_symbols=$output_objdir/$libname.def + $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols + fi + fi + + libobjs=$output + # Restore the value of output. + output=$save_output + + if test -n "$convenience" && test -n "$whole_archive_flag_spec"; then + eval libobjs=\"\$libobjs $whole_archive_flag_spec\" + test "X$libobjs" = "X " && libobjs= + fi + # Expand the library linking commands again to reset the + # value of $libobjs for piecewise linking. + + # Do each of the archive commands. + if test "$module" = yes && test -n "$module_cmds" ; then + if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then + cmds=$module_expsym_cmds + else + cmds=$module_cmds + fi + else + if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then + cmds=$archive_expsym_cmds + else + cmds=$archive_cmds + fi + fi + fi + + if test -n "$delfiles"; then + # Append the command to remove temporary files to $cmds. + eval cmds=\"\$cmds~\$RM $delfiles\" + fi + + # Add any objects from preloaded convenience libraries + if test -n "$dlprefiles"; then + gentop="$output_objdir/${outputname}x" + generated="$generated $gentop" + + func_extract_archives $gentop $dlprefiles + libobjs="$libobjs $func_extract_archives_result" + test "X$libobjs" = "X " && libobjs= + fi + + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + $opt_silent || { + func_quote_for_expand "$cmd" + eval "func_echo $func_quote_for_expand_result" + } + $opt_dry_run || eval "$cmd" || { + lt_exit=$? + + # Restore the uninstalled library and exit + if test "$mode" = relink; then + ( cd "$output_objdir" && \ + $RM "${realname}T" && \ + $MV "${realname}U" "$realname" ) + fi + + exit $lt_exit + } + done + IFS="$save_ifs" + + # Restore the uninstalled library and exit + if test "$mode" = relink; then + $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}T && $MV $realname ${realname}T && $MV ${realname}U $realname)' || exit $? + + if test -n "$convenience"; then + if test -z "$whole_archive_flag_spec"; then + func_show_eval '${RM}r "$gentop"' + fi + fi + + exit $EXIT_SUCCESS + fi + + # Create links to the real library. + for linkname in $linknames; do + if test "$realname" != "$linkname"; then + func_show_eval '(cd "$output_objdir" && $RM "$linkname" && $LN_S "$realname" "$linkname")' 'exit $?' + fi + done + + # If -module or -export-dynamic was specified, set the dlname. + if test "$module" = yes || test "$export_dynamic" = yes; then + # On all known operating systems, these are identical. + dlname="$soname" + fi + fi + ;; + + obj) + if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then + func_warning "\`-dlopen' is ignored for objects" + fi + + case " $deplibs" in + *\ -l* | *\ -L*) + func_warning "\`-l' and \`-L' are ignored for objects" ;; + esac + + test -n "$rpath" && \ + func_warning "\`-rpath' is ignored for objects" + + test -n "$xrpath" && \ + func_warning "\`-R' is ignored for objects" + + test -n "$vinfo" && \ + func_warning "\`-version-info' is ignored for objects" + + test -n "$release" && \ + func_warning "\`-release' is ignored for objects" + + case $output in + *.lo) + test -n "$objs$old_deplibs" && \ + func_fatal_error "cannot build library object \`$output' from non-libtool objects" + + libobj=$output + func_lo2o "$libobj" + obj=$func_lo2o_result + ;; + *) + libobj= + obj="$output" + ;; + esac + + # Delete the old objects. + $opt_dry_run || $RM $obj $libobj + + # Objects from convenience libraries. This assumes + # single-version convenience libraries. Whenever we create + # different ones for PIC/non-PIC, this we'll have to duplicate + # the extraction. + reload_conv_objs= + gentop= + # reload_cmds runs $LD directly, so let us get rid of + # -Wl from whole_archive_flag_spec and hope we can get by with + # turning comma into space.. + wl= + + if test -n "$convenience"; then + if test -n "$whole_archive_flag_spec"; then + eval tmp_whole_archive_flags=\"$whole_archive_flag_spec\" + reload_conv_objs=$reload_objs\ `$ECHO "X$tmp_whole_archive_flags" | $Xsed -e 's|,| |g'` + else + gentop="$output_objdir/${obj}x" + generated="$generated $gentop" + + func_extract_archives $gentop $convenience + reload_conv_objs="$reload_objs $func_extract_archives_result" + fi + fi + + # Create the old-style object. + reload_objs="$objs$old_deplibs "`$ECHO "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}$'/d' -e '/\.lib$/d' -e "$lo2o" | $NL2SP`" $reload_conv_objs" ### testsuite: skip nested quoting test + + output="$obj" + func_execute_cmds "$reload_cmds" 'exit $?' + + # Exit if we aren't doing a library object file. + if test -z "$libobj"; then + if test -n "$gentop"; then + func_show_eval '${RM}r "$gentop"' + fi + + exit $EXIT_SUCCESS + fi + + if test "$build_libtool_libs" != yes; then + if test -n "$gentop"; then + func_show_eval '${RM}r "$gentop"' + fi + + # Create an invalid libtool object if no PIC, so that we don't + # accidentally link it into a program. + # $show "echo timestamp > $libobj" + # $opt_dry_run || eval "echo timestamp > $libobj" || exit $? + exit $EXIT_SUCCESS + fi + + if test -n "$pic_flag" || test "$pic_mode" != default; then + # Only do commands if we really have different PIC objects. + reload_objs="$libobjs $reload_conv_objs" + output="$libobj" + func_execute_cmds "$reload_cmds" 'exit $?' + fi + + if test -n "$gentop"; then + func_show_eval '${RM}r "$gentop"' + fi + + exit $EXIT_SUCCESS + ;; + + prog) + case $host in + *cygwin*) func_stripname '' '.exe' "$output" + output=$func_stripname_result.exe;; + esac + test -n "$vinfo" && \ + func_warning "\`-version-info' is ignored for programs" + + test -n "$release" && \ + func_warning "\`-release' is ignored for programs" + + test "$preload" = yes \ + && test "$dlopen_support" = unknown \ + && test "$dlopen_self" = unknown \ + && test "$dlopen_self_static" = unknown && \ + func_warning "\`LT_INIT([dlopen])' not used. Assuming no dlopen support." + + case $host in + *-*-rhapsody* | *-*-darwin1.[012]) + # On Rhapsody replace the C library is the System framework + compile_deplibs=`$ECHO "X $compile_deplibs" | $Xsed -e 's/ -lc / System.ltframework /'` + finalize_deplibs=`$ECHO "X $finalize_deplibs" | $Xsed -e 's/ -lc / System.ltframework /'` + ;; + esac + + case $host in + *-*-darwin*) + # Don't allow lazy linking, it breaks C++ global constructors + # But is supposedly fixed on 10.4 or later (yay!). + if test "$tagname" = CXX ; then + case ${MACOSX_DEPLOYMENT_TARGET-10.0} in + 10.[0123]) + compile_command="$compile_command ${wl}-bind_at_load" + finalize_command="$finalize_command ${wl}-bind_at_load" + ;; + esac + fi + # Time to change all our "foo.ltframework" stuff back to "-framework foo" + compile_deplibs=`$ECHO "X $compile_deplibs" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'` + finalize_deplibs=`$ECHO "X $finalize_deplibs" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'` + ;; + esac + + + # move library search paths that coincide with paths to not yet + # installed libraries to the beginning of the library search list + new_libs= + for path in $notinst_path; do + case " $new_libs " in + *" -L$path/$objdir "*) ;; + *) + case " $compile_deplibs " in + *" -L$path/$objdir "*) + new_libs="$new_libs -L$path/$objdir" ;; + esac + ;; + esac + done + for deplib in $compile_deplibs; do + case $deplib in + -L*) + case " $new_libs " in + *" $deplib "*) ;; + *) new_libs="$new_libs $deplib" ;; + esac + ;; + *) new_libs="$new_libs $deplib" ;; + esac + done + compile_deplibs="$new_libs" + + + compile_command="$compile_command $compile_deplibs" + finalize_command="$finalize_command $finalize_deplibs" + + if test -n "$rpath$xrpath"; then + # If the user specified any rpath flags, then add them. + for libdir in $rpath $xrpath; do + # This is the magic to use -rpath. + case "$finalize_rpath " in + *" $libdir "*) ;; + *) finalize_rpath="$finalize_rpath $libdir" ;; + esac + done + fi + + # Now hardcode the library paths + rpath= + hardcode_libdirs= + for libdir in $compile_rpath $finalize_rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + if test -z "$hardcode_libdirs"; then + hardcode_libdirs="$libdir" + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + rpath="$rpath $flag" + fi + elif test -n "$runpath_var"; then + case "$perm_rpath " in + *" $libdir "*) ;; + *) perm_rpath="$perm_rpath $libdir" ;; + esac + fi + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) + testbindir=`${ECHO} "$libdir" | ${SED} -e 's*/lib$*/bin*'` + case :$dllsearchpath: in + *":$libdir:"*) ;; + ::) dllsearchpath=$libdir;; + *) dllsearchpath="$dllsearchpath:$libdir";; + esac + case :$dllsearchpath: in + *":$testbindir:"*) ;; + ::) dllsearchpath=$testbindir;; + *) dllsearchpath="$dllsearchpath:$testbindir";; + esac + ;; + esac + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir="$hardcode_libdirs" + eval rpath=\" $hardcode_libdir_flag_spec\" + fi + compile_rpath="$rpath" + + rpath= + hardcode_libdirs= + for libdir in $finalize_rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + if test -z "$hardcode_libdirs"; then + hardcode_libdirs="$libdir" + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + rpath="$rpath $flag" + fi + elif test -n "$runpath_var"; then + case "$finalize_perm_rpath " in + *" $libdir "*) ;; + *) finalize_perm_rpath="$finalize_perm_rpath $libdir" ;; + esac + fi + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir="$hardcode_libdirs" + eval rpath=\" $hardcode_libdir_flag_spec\" + fi + finalize_rpath="$rpath" + + if test -n "$libobjs" && test "$build_old_libs" = yes; then + # Transform all the library objects into standard objects. + compile_command=`$ECHO "X$compile_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` + finalize_command=`$ECHO "X$finalize_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` + fi + + func_generate_dlsyms "$outputname" "@PROGRAM@" "no" + + # template prelinking step + if test -n "$prelink_cmds"; then + func_execute_cmds "$prelink_cmds" 'exit $?' + fi + + wrappers_required=yes + case $host in + *cygwin* | *mingw* ) + if test "$build_libtool_libs" != yes; then + wrappers_required=no + fi + ;; + *cegcc) + # Disable wrappers for cegcc, we are cross compiling anyway. + wrappers_required=no + ;; + *) + if test "$need_relink" = no || test "$build_libtool_libs" != yes; then + wrappers_required=no + fi + ;; + esac + if test "$wrappers_required" = no; then + # Replace the output file specification. + compile_command=`$ECHO "X$compile_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'` + link_command="$compile_command$compile_rpath" + + # We have no uninstalled library dependencies, so finalize right now. + exit_status=0 + func_show_eval "$link_command" 'exit_status=$?' + + # Delete the generated files. + if test -f "$output_objdir/${outputname}S.${objext}"; then + func_show_eval '$RM "$output_objdir/${outputname}S.${objext}"' + fi + + exit $exit_status + fi + + if test -n "$compile_shlibpath$finalize_shlibpath"; then + compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command" + fi + if test -n "$finalize_shlibpath"; then + finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command" + fi + + compile_var= + finalize_var= + if test -n "$runpath_var"; then + if test -n "$perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $perm_rpath; do + rpath="$rpath$dir:" + done + compile_var="$runpath_var=\"$rpath\$$runpath_var\" " + fi + if test -n "$finalize_perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $finalize_perm_rpath; do + rpath="$rpath$dir:" + done + finalize_var="$runpath_var=\"$rpath\$$runpath_var\" " + fi + fi + + if test "$no_install" = yes; then + # We don't need to create a wrapper script. + link_command="$compile_var$compile_command$compile_rpath" + # Replace the output file specification. + link_command=`$ECHO "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'` + # Delete the old output file. + $opt_dry_run || $RM $output + # Link the executable and exit + func_show_eval "$link_command" 'exit $?' + exit $EXIT_SUCCESS + fi + + if test "$hardcode_action" = relink; then + # Fast installation is not supported + link_command="$compile_var$compile_command$compile_rpath" + relink_command="$finalize_var$finalize_command$finalize_rpath" + + func_warning "this platform does not like uninstalled shared libraries" + func_warning "\`$output' will be relinked during installation" + else + if test "$fast_install" != no; then + link_command="$finalize_var$compile_command$finalize_rpath" + if test "$fast_install" = yes; then + relink_command=`$ECHO "X$compile_var$compile_command$compile_rpath" | $Xsed -e 's%@OUTPUT@%\$progdir/\$file%g'` + else + # fast_install is set to needless + relink_command= + fi + else + link_command="$compile_var$compile_command$compile_rpath" + relink_command="$finalize_var$finalize_command$finalize_rpath" + fi + fi + + # Replace the output file specification. + link_command=`$ECHO "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'` + + # Delete the old output files. + $opt_dry_run || $RM $output $output_objdir/$outputname $output_objdir/lt-$outputname + + func_show_eval "$link_command" 'exit $?' + + # Now create the wrapper script. + func_verbose "creating $output" + + # Quote the relink command for shipping. + if test -n "$relink_command"; then + # Preserve any variables that may affect compiler behavior + for var in $variables_saved_for_relink; do + if eval test -z \"\${$var+set}\"; then + relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" + elif eval var_value=\$$var; test -z "$var_value"; then + relink_command="$var=; export $var; $relink_command" + else + func_quote_for_eval "$var_value" + relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" + fi + done + relink_command="(cd `pwd`; $relink_command)" + relink_command=`$ECHO "X$relink_command" | $Xsed -e "$sed_quote_subst"` + fi + + # Quote $ECHO for shipping. + if test "X$ECHO" = "X$SHELL $progpath --fallback-echo"; then + case $progpath in + [\\/]* | [A-Za-z]:[\\/]*) qecho="$SHELL $progpath --fallback-echo";; + *) qecho="$SHELL `pwd`/$progpath --fallback-echo";; + esac + qecho=`$ECHO "X$qecho" | $Xsed -e "$sed_quote_subst"` + else + qecho=`$ECHO "X$ECHO" | $Xsed -e "$sed_quote_subst"` + fi + + # Only actually do things if not in dry run mode. + $opt_dry_run || { + # win32 will think the script is a binary if it has + # a .exe suffix, so we strip it off here. + case $output in + *.exe) func_stripname '' '.exe' "$output" + output=$func_stripname_result ;; + esac + # test for cygwin because mv fails w/o .exe extensions + case $host in + *cygwin*) + exeext=.exe + func_stripname '' '.exe' "$outputname" + outputname=$func_stripname_result ;; + *) exeext= ;; + esac + case $host in + *cygwin* | *mingw* ) + func_dirname_and_basename "$output" "" "." + output_name=$func_basename_result + output_path=$func_dirname_result + cwrappersource="$output_path/$objdir/lt-$output_name.c" + cwrapper="$output_path/$output_name.exe" + $RM $cwrappersource $cwrapper + trap "$RM $cwrappersource $cwrapper; exit $EXIT_FAILURE" 1 2 15 + + func_emit_cwrapperexe_src > $cwrappersource + + # The wrapper executable is built using the $host compiler, + # because it contains $host paths and files. If cross- + # compiling, it, like the target executable, must be + # executed on the $host or under an emulation environment. + $opt_dry_run || { + $LTCC $LTCFLAGS -o $cwrapper $cwrappersource + $STRIP $cwrapper + } + + # Now, create the wrapper script for func_source use: + func_ltwrapper_scriptname $cwrapper + $RM $func_ltwrapper_scriptname_result + trap "$RM $func_ltwrapper_scriptname_result; exit $EXIT_FAILURE" 1 2 15 + $opt_dry_run || { + # note: this script will not be executed, so do not chmod. + if test "x$build" = "x$host" ; then + $cwrapper --lt-dump-script > $func_ltwrapper_scriptname_result + else + func_emit_wrapper no > $func_ltwrapper_scriptname_result + fi + } + ;; + * ) + $RM $output + trap "$RM $output; exit $EXIT_FAILURE" 1 2 15 + + func_emit_wrapper no > $output + chmod +x $output + ;; + esac + } + exit $EXIT_SUCCESS + ;; + esac + + # See if we need to build an old-fashioned archive. + for oldlib in $oldlibs; do + + if test "$build_libtool_libs" = convenience; then + oldobjs="$libobjs_save $symfileobj" + addlibs="$convenience" + build_libtool_libs=no + else + if test "$build_libtool_libs" = module; then + oldobjs="$libobjs_save" + build_libtool_libs=no + else + oldobjs="$old_deplibs $non_pic_objects" + if test "$preload" = yes && test -f "$symfileobj"; then + oldobjs="$oldobjs $symfileobj" + fi + fi + addlibs="$old_convenience" + fi + + if test -n "$addlibs"; then + gentop="$output_objdir/${outputname}x" + generated="$generated $gentop" + + func_extract_archives $gentop $addlibs + oldobjs="$oldobjs $func_extract_archives_result" + fi + + # Do each command in the archive commands. + if test -n "$old_archive_from_new_cmds" && test "$build_libtool_libs" = yes; then + cmds=$old_archive_from_new_cmds + else + + # Add any objects from preloaded convenience libraries + if test -n "$dlprefiles"; then + gentop="$output_objdir/${outputname}x" + generated="$generated $gentop" + + func_extract_archives $gentop $dlprefiles + oldobjs="$oldobjs $func_extract_archives_result" + fi + + # POSIX demands no paths to be encoded in archives. We have + # to avoid creating archives with duplicate basenames if we + # might have to extract them afterwards, e.g., when creating a + # static archive out of a convenience library, or when linking + # the entirety of a libtool archive into another (currently + # not supported by libtool). + if (for obj in $oldobjs + do + func_basename "$obj" + $ECHO "$func_basename_result" + done | sort | sort -uc >/dev/null 2>&1); then + : + else + $ECHO "copying selected object files to avoid basename conflicts..." + gentop="$output_objdir/${outputname}x" + generated="$generated $gentop" + func_mkdir_p "$gentop" + save_oldobjs=$oldobjs + oldobjs= + counter=1 + for obj in $save_oldobjs + do + func_basename "$obj" + objbase="$func_basename_result" + case " $oldobjs " in + " ") oldobjs=$obj ;; + *[\ /]"$objbase "*) + while :; do + # Make sure we don't pick an alternate name that also + # overlaps. + newobj=lt$counter-$objbase + func_arith $counter + 1 + counter=$func_arith_result + case " $oldobjs " in + *[\ /]"$newobj "*) ;; + *) if test ! -f "$gentop/$newobj"; then break; fi ;; + esac + done + func_show_eval "ln $obj $gentop/$newobj || cp $obj $gentop/$newobj" + oldobjs="$oldobjs $gentop/$newobj" + ;; + *) oldobjs="$oldobjs $obj" ;; + esac + done + fi + eval cmds=\"$old_archive_cmds\" + + func_len " $cmds" + len=$func_len_result + if test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then + cmds=$old_archive_cmds + else + # the command line is too long to link in one step, link in parts + func_verbose "using piecewise archive linking..." + save_RANLIB=$RANLIB + RANLIB=: + objlist= + concat_cmds= + save_oldobjs=$oldobjs + oldobjs= + # Is there a better way of finding the last object in the list? + for obj in $save_oldobjs + do + last_oldobj=$obj + done + eval test_cmds=\"$old_archive_cmds\" + func_len " $test_cmds" + len0=$func_len_result + len=$len0 + for obj in $save_oldobjs + do + func_len " $obj" + func_arith $len + $func_len_result + len=$func_arith_result + func_append objlist " $obj" + if test "$len" -lt "$max_cmd_len"; then + : + else + # the above command should be used before it gets too long + oldobjs=$objlist + if test "$obj" = "$last_oldobj" ; then + RANLIB=$save_RANLIB + fi + test -z "$concat_cmds" || concat_cmds=$concat_cmds~ + eval concat_cmds=\"\${concat_cmds}$old_archive_cmds\" + objlist= + len=$len0 + fi + done + RANLIB=$save_RANLIB + oldobjs=$objlist + if test "X$oldobjs" = "X" ; then + eval cmds=\"\$concat_cmds\" + else + eval cmds=\"\$concat_cmds~\$old_archive_cmds\" + fi + fi + fi + func_execute_cmds "$cmds" 'exit $?' + done + + test -n "$generated" && \ + func_show_eval "${RM}r$generated" + + # Now create the libtool archive. + case $output in + *.la) + old_library= + test "$build_old_libs" = yes && old_library="$libname.$libext" + func_verbose "creating $output" + + # Preserve any variables that may affect compiler behavior + for var in $variables_saved_for_relink; do + if eval test -z \"\${$var+set}\"; then + relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" + elif eval var_value=\$$var; test -z "$var_value"; then + relink_command="$var=; export $var; $relink_command" + else + func_quote_for_eval "$var_value" + relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" + fi + done + # Quote the link command for shipping. + relink_command="(cd `pwd`; $SHELL $progpath $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)" + relink_command=`$ECHO "X$relink_command" | $Xsed -e "$sed_quote_subst"` + if test "$hardcode_automatic" = yes ; then + relink_command= + fi + + # Only create the output if not a dry run. + $opt_dry_run || { + for installed in no yes; do + if test "$installed" = yes; then + if test -z "$install_libdir"; then + break + fi + output="$output_objdir/$outputname"i + # Replace all uninstalled libtool libraries with the installed ones + newdependency_libs= + for deplib in $dependency_libs; do + case $deplib in + *.la) + func_basename "$deplib" + name="$func_basename_result" + eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` + test -z "$libdir" && \ + func_fatal_error "\`$deplib' is not a valid libtool archive" + newdependency_libs="$newdependency_libs $libdir/$name" + ;; + *) newdependency_libs="$newdependency_libs $deplib" ;; + esac + done + dependency_libs="$newdependency_libs" + newdlfiles= + + for lib in $dlfiles; do + case $lib in + *.la) + func_basename "$lib" + name="$func_basename_result" + eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` + test -z "$libdir" && \ + func_fatal_error "\`$lib' is not a valid libtool archive" + newdlfiles="$newdlfiles $libdir/$name" + ;; + *) newdlfiles="$newdlfiles $lib" ;; + esac + done + dlfiles="$newdlfiles" + newdlprefiles= + for lib in $dlprefiles; do + case $lib in + *.la) + # Only pass preopened files to the pseudo-archive (for + # eventual linking with the app. that links it) if we + # didn't already link the preopened objects directly into + # the library: + func_basename "$lib" + name="$func_basename_result" + eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` + test -z "$libdir" && \ + func_fatal_error "\`$lib' is not a valid libtool archive" + newdlprefiles="$newdlprefiles $libdir/$name" + ;; + esac + done + dlprefiles="$newdlprefiles" + else + newdlfiles= + for lib in $dlfiles; do + case $lib in + [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;; + *) abs=`pwd`"/$lib" ;; + esac + newdlfiles="$newdlfiles $abs" + done + dlfiles="$newdlfiles" + newdlprefiles= + for lib in $dlprefiles; do + case $lib in + [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;; + *) abs=`pwd`"/$lib" ;; + esac + newdlprefiles="$newdlprefiles $abs" + done + dlprefiles="$newdlprefiles" + fi + $RM $output + # place dlname in correct position for cygwin + tdlname=$dlname + case $host,$output,$installed,$module,$dlname in + *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll | *cegcc*,*lai,yes,no,*.dll) tdlname=../bin/$dlname ;; + esac + $ECHO > $output "\ +# $outputname - a libtool library file +# Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION +# +# Please DO NOT delete this file! +# It is necessary for linking the library. + +# The name that we can dlopen(3). +dlname='$tdlname' + +# Names of this library. +library_names='$library_names' + +# The name of the static archive. +old_library='$old_library' + +# Linker flags that can not go in dependency_libs. +inherited_linker_flags='$new_inherited_linker_flags' + +# Libraries that this one depends upon. +dependency_libs='$dependency_libs' + +# Names of additional weak libraries provided by this library +weak_library_names='$weak_libs' + +# Version information for $libname. +current=$current +age=$age +revision=$revision + +# Is this an already installed library? +installed=$installed + +# Should we warn about portability when linking against -modules? +shouldnotlink=$module + +# Files to dlopen/dlpreopen +dlopen='$dlfiles' +dlpreopen='$dlprefiles' + +# Directory that this library needs to be installed in: +libdir='$install_libdir'" + if test "$installed" = no && test "$need_relink" = yes; then + $ECHO >> $output "\ +relink_command=\"$relink_command\"" + fi + done + } + + # Do a symbolic link so that the libtool archive can be found in + # LD_LIBRARY_PATH before the program is installed. + func_show_eval '( cd "$output_objdir" && $RM "$outputname" && $LN_S "../$outputname" "$outputname" )' 'exit $?' + ;; + esac + exit $EXIT_SUCCESS +} + +{ test "$mode" = link || test "$mode" = relink; } && + func_mode_link ${1+"$@"} + + +# func_mode_uninstall arg... +func_mode_uninstall () +{ + $opt_debug + RM="$nonopt" + files= + rmforce= + exit_status=0 + + # This variable tells wrapper scripts just to set variables rather + # than running their programs. + libtool_install_magic="$magic" + + for arg + do + case $arg in + -f) RM="$RM $arg"; rmforce=yes ;; + -*) RM="$RM $arg" ;; + *) files="$files $arg" ;; + esac + done + + test -z "$RM" && \ + func_fatal_help "you must specify an RM program" + + rmdirs= + + origobjdir="$objdir" + for file in $files; do + func_dirname "$file" "" "." + dir="$func_dirname_result" + if test "X$dir" = X.; then + objdir="$origobjdir" + else + objdir="$dir/$origobjdir" + fi + func_basename "$file" + name="$func_basename_result" + test "$mode" = uninstall && objdir="$dir" + + # Remember objdir for removal later, being careful to avoid duplicates + if test "$mode" = clean; then + case " $rmdirs " in + *" $objdir "*) ;; + *) rmdirs="$rmdirs $objdir" ;; + esac + fi + + # Don't error if the file doesn't exist and rm -f was used. + if { test -L "$file"; } >/dev/null 2>&1 || + { test -h "$file"; } >/dev/null 2>&1 || + test -f "$file"; then + : + elif test -d "$file"; then + exit_status=1 + continue + elif test "$rmforce" = yes; then + continue + fi + + rmfiles="$file" + + case $name in + *.la) + # Possibly a libtool archive, so verify it. + if func_lalib_p "$file"; then + func_source $dir/$name + + # Delete the libtool libraries and symlinks. + for n in $library_names; do + rmfiles="$rmfiles $objdir/$n" + done + test -n "$old_library" && rmfiles="$rmfiles $objdir/$old_library" + + case "$mode" in + clean) + case " $library_names " in + # " " in the beginning catches empty $dlname + *" $dlname "*) ;; + *) rmfiles="$rmfiles $objdir/$dlname" ;; + esac + test -n "$libdir" && rmfiles="$rmfiles $objdir/$name $objdir/${name}i" + ;; + uninstall) + if test -n "$library_names"; then + # Do each command in the postuninstall commands. + func_execute_cmds "$postuninstall_cmds" 'test "$rmforce" = yes || exit_status=1' + fi + + if test -n "$old_library"; then + # Do each command in the old_postuninstall commands. + func_execute_cmds "$old_postuninstall_cmds" 'test "$rmforce" = yes || exit_status=1' + fi + # FIXME: should reinstall the best remaining shared library. + ;; + esac + fi + ;; + + *.lo) + # Possibly a libtool object, so verify it. + if func_lalib_p "$file"; then + + # Read the .lo file + func_source $dir/$name + + # Add PIC object to the list of files to remove. + if test -n "$pic_object" && + test "$pic_object" != none; then + rmfiles="$rmfiles $dir/$pic_object" + fi + + # Add non-PIC object to the list of files to remove. + if test -n "$non_pic_object" && + test "$non_pic_object" != none; then + rmfiles="$rmfiles $dir/$non_pic_object" + fi + fi + ;; + + *) + if test "$mode" = clean ; then + noexename=$name + case $file in + *.exe) + func_stripname '' '.exe' "$file" + file=$func_stripname_result + func_stripname '' '.exe' "$name" + noexename=$func_stripname_result + # $file with .exe has already been added to rmfiles, + # add $file without .exe + rmfiles="$rmfiles $file" + ;; + esac + # Do a test to see if this is a libtool program. + if func_ltwrapper_p "$file"; then + if func_ltwrapper_executable_p "$file"; then + func_ltwrapper_scriptname "$file" + relink_command= + func_source $func_ltwrapper_scriptname_result + rmfiles="$rmfiles $func_ltwrapper_scriptname_result" + else + relink_command= + func_source $dir/$noexename + fi + + # note $name still contains .exe if it was in $file originally + # as does the version of $file that was added into $rmfiles + rmfiles="$rmfiles $objdir/$name $objdir/${name}S.${objext}" + if test "$fast_install" = yes && test -n "$relink_command"; then + rmfiles="$rmfiles $objdir/lt-$name" + fi + if test "X$noexename" != "X$name" ; then + rmfiles="$rmfiles $objdir/lt-${noexename}.c" + fi + fi + fi + ;; + esac + func_show_eval "$RM $rmfiles" 'exit_status=1' + done + objdir="$origobjdir" + + # Try to remove the ${objdir}s in the directories where we deleted files + for dir in $rmdirs; do + if test -d "$dir"; then + func_show_eval "rmdir $dir >/dev/null 2>&1" + fi + done + + exit $exit_status +} + +{ test "$mode" = uninstall || test "$mode" = clean; } && + func_mode_uninstall ${1+"$@"} + +test -z "$mode" && { + help="$generic_help" + func_fatal_help "you must specify a MODE" +} + +test -z "$exec_cmd" && \ + func_fatal_help "invalid operation mode \`$mode'" + +if test -n "$exec_cmd"; then + eval exec "$exec_cmd" + exit $EXIT_FAILURE +fi + +exit $exit_status + + +# The TAGs below are defined such that we never get into a situation +# in which we disable both kinds of libraries. Given conflicting +# choices, we go for a static library, that is the most portable, +# since we can't tell whether shared libraries were disabled because +# the user asked for that or because the platform doesn't support +# them. This is particularly important on AIX, because we don't +# support having both static and shared libraries enabled at the same +# time on that platform, so we default to a shared-only configuration. +# If a disable-shared tag is given, we'll fallback to a static-only +# configuration. But we'll never go from static-only to shared-only. + +# ### BEGIN LIBTOOL TAG CONFIG: disable-shared +build_libtool_libs=no +build_old_libs=yes +# ### END LIBTOOL TAG CONFIG: disable-shared + +# ### BEGIN LIBTOOL TAG CONFIG: disable-static +build_old_libs=`case $build_libtool_libs in yes) echo no;; *) echo yes;; esac` +# ### END LIBTOOL TAG CONFIG: disable-static + +# Local Variables: +# mode:shell-script +# sh-indentation:2 +# End: +# vi:sw=2 + diff --git a/libclamav/c++/config/missing b/libclamav/c++/config/missing new file mode 100755 index 000000000..28055d2ae --- /dev/null +++ b/libclamav/c++/config/missing @@ -0,0 +1,376 @@ +#! /bin/sh +# Common stub for a few missing GNU programs while installing. + +scriptversion=2009-04-28.21; # UTC + +# Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003, 2004, 2005, 2006, +# 2008, 2009 Free Software Foundation, Inc. +# Originally by Fran,cois Pinard , 1996. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +if test $# -eq 0; then + echo 1>&2 "Try \`$0 --help' for more information" + exit 1 +fi + +run=: +sed_output='s/.* --output[ =]\([^ ]*\).*/\1/p' +sed_minuso='s/.* -o \([^ ]*\).*/\1/p' + +# In the cases where this matters, `missing' is being run in the +# srcdir already. +if test -f configure.ac; then + configure_ac=configure.ac +else + configure_ac=configure.in +fi + +msg="missing on your system" + +case $1 in +--run) + # Try to run requested program, and just exit if it succeeds. + run= + shift + "$@" && exit 0 + # Exit code 63 means version mismatch. This often happens + # when the user try to use an ancient version of a tool on + # a file that requires a minimum version. In this case we + # we should proceed has if the program had been absent, or + # if --run hadn't been passed. + if test $? = 63; then + run=: + msg="probably too old" + fi + ;; + + -h|--h|--he|--hel|--help) + echo "\ +$0 [OPTION]... PROGRAM [ARGUMENT]... + +Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an +error status if there is no known handling for PROGRAM. + +Options: + -h, --help display this help and exit + -v, --version output version information and exit + --run try to run the given command, and emulate it if it fails + +Supported PROGRAM values: + aclocal touch file \`aclocal.m4' + autoconf touch file \`configure' + autoheader touch file \`config.h.in' + autom4te touch the output file, or create a stub one + automake touch all \`Makefile.in' files + bison create \`y.tab.[ch]', if possible, from existing .[ch] + flex create \`lex.yy.c', if possible, from existing .c + help2man touch the output file + lex create \`lex.yy.c', if possible, from existing .c + makeinfo touch the output file + tar try tar, gnutar, gtar, then tar without non-portable flags + yacc create \`y.tab.[ch]', if possible, from existing .[ch] + +Version suffixes to PROGRAM as well as the prefixes \`gnu-', \`gnu', and +\`g' are ignored when checking the name. + +Send bug reports to ." + exit $? + ;; + + -v|--v|--ve|--ver|--vers|--versi|--versio|--version) + echo "missing $scriptversion (GNU Automake)" + exit $? + ;; + + -*) + echo 1>&2 "$0: Unknown \`$1' option" + echo 1>&2 "Try \`$0 --help' for more information" + exit 1 + ;; + +esac + +# normalize program name to check for. +program=`echo "$1" | sed ' + s/^gnu-//; t + s/^gnu//; t + s/^g//; t'` + +# Now exit if we have it, but it failed. Also exit now if we +# don't have it and --version was passed (most likely to detect +# the program). This is about non-GNU programs, so use $1 not +# $program. +case $1 in + lex*|yacc*) + # Not GNU programs, they don't have --version. + ;; + + tar*) + if test -n "$run"; then + echo 1>&2 "ERROR: \`tar' requires --run" + exit 1 + elif test "x$2" = "x--version" || test "x$2" = "x--help"; then + exit 1 + fi + ;; + + *) + if test -z "$run" && ($1 --version) > /dev/null 2>&1; then + # We have it, but it failed. + exit 1 + elif test "x$2" = "x--version" || test "x$2" = "x--help"; then + # Could not run --version or --help. This is probably someone + # running `$TOOL --version' or `$TOOL --help' to check whether + # $TOOL exists and not knowing $TOOL uses missing. + exit 1 + fi + ;; +esac + +# If it does not exist, or fails to run (possibly an outdated version), +# try to emulate it. +case $program in + aclocal*) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified \`acinclude.m4' or \`${configure_ac}'. You might want + to install the \`Automake' and \`Perl' packages. Grab them from + any GNU archive site." + touch aclocal.m4 + ;; + + autoconf*) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified \`${configure_ac}'. You might want to install the + \`Autoconf' and \`GNU m4' packages. Grab them from any GNU + archive site." + touch configure + ;; + + autoheader*) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified \`acconfig.h' or \`${configure_ac}'. You might want + to install the \`Autoconf' and \`GNU m4' packages. Grab them + from any GNU archive site." + files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}` + test -z "$files" && files="config.h" + touch_files= + for f in $files; do + case $f in + *:*) touch_files="$touch_files "`echo "$f" | + sed -e 's/^[^:]*://' -e 's/:.*//'`;; + *) touch_files="$touch_files $f.in";; + esac + done + touch $touch_files + ;; + + automake*) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'. + You might want to install the \`Automake' and \`Perl' packages. + Grab them from any GNU archive site." + find . -type f -name Makefile.am -print | + sed 's/\.am$/.in/' | + while read f; do touch "$f"; done + ;; + + autom4te*) + echo 1>&2 "\ +WARNING: \`$1' is needed, but is $msg. + You might have modified some files without having the + proper tools for further handling them. + You can get \`$1' as part of \`Autoconf' from any GNU + archive site." + + file=`echo "$*" | sed -n "$sed_output"` + test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` + if test -f "$file"; then + touch $file + else + test -z "$file" || exec >$file + echo "#! /bin/sh" + echo "# Created by GNU Automake missing as a replacement of" + echo "# $ $@" + echo "exit 0" + chmod +x $file + exit 1 + fi + ;; + + bison*|yacc*) + echo 1>&2 "\ +WARNING: \`$1' $msg. You should only need it if + you modified a \`.y' file. You may need the \`Bison' package + in order for those modifications to take effect. You can get + \`Bison' from any GNU archive site." + rm -f y.tab.c y.tab.h + if test $# -ne 1; then + eval LASTARG="\${$#}" + case $LASTARG in + *.y) + SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'` + if test -f "$SRCFILE"; then + cp "$SRCFILE" y.tab.c + fi + SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'` + if test -f "$SRCFILE"; then + cp "$SRCFILE" y.tab.h + fi + ;; + esac + fi + if test ! -f y.tab.h; then + echo >y.tab.h + fi + if test ! -f y.tab.c; then + echo 'main() { return 0; }' >y.tab.c + fi + ;; + + lex*|flex*) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified a \`.l' file. You may need the \`Flex' package + in order for those modifications to take effect. You can get + \`Flex' from any GNU archive site." + rm -f lex.yy.c + if test $# -ne 1; then + eval LASTARG="\${$#}" + case $LASTARG in + *.l) + SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'` + if test -f "$SRCFILE"; then + cp "$SRCFILE" lex.yy.c + fi + ;; + esac + fi + if test ! -f lex.yy.c; then + echo 'main() { return 0; }' >lex.yy.c + fi + ;; + + help2man*) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified a dependency of a manual page. You may need the + \`Help2man' package in order for those modifications to take + effect. You can get \`Help2man' from any GNU archive site." + + file=`echo "$*" | sed -n "$sed_output"` + test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` + if test -f "$file"; then + touch $file + else + test -z "$file" || exec >$file + echo ".ab help2man is required to generate this page" + exit $? + fi + ;; + + makeinfo*) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified a \`.texi' or \`.texinfo' file, or any other file + indirectly affecting the aspect of the manual. The spurious + call might also be the consequence of using a buggy \`make' (AIX, + DU, IRIX). You might want to install the \`Texinfo' package or + the \`GNU make' package. Grab either from any GNU archive site." + # The file to touch is that specified with -o ... + file=`echo "$*" | sed -n "$sed_output"` + test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` + if test -z "$file"; then + # ... or it is the one specified with @setfilename ... + infile=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'` + file=`sed -n ' + /^@setfilename/{ + s/.* \([^ ]*\) *$/\1/ + p + q + }' $infile` + # ... or it is derived from the source name (dir/f.texi becomes f.info) + test -z "$file" && file=`echo "$infile" | sed 's,.*/,,;s,.[^.]*$,,'`.info + fi + # If the file does not exist, the user really needs makeinfo; + # let's fail without touching anything. + test -f $file || exit 1 + touch $file + ;; + + tar*) + shift + + # We have already tried tar in the generic part. + # Look for gnutar/gtar before invocation to avoid ugly error + # messages. + if (gnutar --version > /dev/null 2>&1); then + gnutar "$@" && exit 0 + fi + if (gtar --version > /dev/null 2>&1); then + gtar "$@" && exit 0 + fi + firstarg="$1" + if shift; then + case $firstarg in + *o*) + firstarg=`echo "$firstarg" | sed s/o//` + tar "$firstarg" "$@" && exit 0 + ;; + esac + case $firstarg in + *h*) + firstarg=`echo "$firstarg" | sed s/h//` + tar "$firstarg" "$@" && exit 0 + ;; + esac + fi + + echo 1>&2 "\ +WARNING: I can't seem to be able to run \`tar' with the given arguments. + You may want to install GNU tar or Free paxutils, or check the + command line arguments." + exit 1 + ;; + + *) + echo 1>&2 "\ +WARNING: \`$1' is needed, and is $msg. + You might have modified some files without having the + proper tools for further handling them. Check the \`README' file, + it often tells you about the needed prerequisites for installing + this package. You may also peek at any GNU archive site, in case + some other package would contain this missing \`$1' program." + exit 1 + ;; +esac + +exit 0 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/libclamav/c++/configure b/libclamav/c++/configure new file mode 100755 index 000000000..62a00437f --- /dev/null +++ b/libclamav/c++/configure @@ -0,0 +1,17327 @@ +#! /bin/sh +# Guess values for system-dependent variables and create Makefiles. +# Generated by GNU Autoconf 2.65 for libclamavc++ devel. +# +# Report bugs to . +# +# +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, +# 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, +# Inc. +# +# +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi + + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +case $0 in #(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +if test "x$CONFIG_SHELL" = x; then + as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which + # is contrary to our usage. Disable this feature. + alias -g '\${1+\"\$@\"}'='\"\$@\"' + setopt NO_GLOB_SUBST +else + case \`(set -o) 2>/dev/null\` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi +" + as_required="as_fn_return () { (exit \$1); } +as_fn_success () { as_fn_return 0; } +as_fn_failure () { as_fn_return 1; } +as_fn_ret_success () { return 0; } +as_fn_ret_failure () { return 1; } + +exitcode=0 +as_fn_success || { exitcode=1; echo as_fn_success failed.; } +as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } +as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } +as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } +if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : + +else + exitcode=1; echo positional parameters were not saved. +fi +test x\$exitcode = x0 || exit 1" + as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO + as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO + eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && + test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 +test \$(( 1 + 1 )) = 2 || exit 1" + if (eval "$as_required") 2>/dev/null; then : + as_have_required=yes +else + as_have_required=no +fi + if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : + +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +as_found=false +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + as_found=: + case $as_dir in #( + /*) + for as_base in sh bash ksh sh5; do + # Try only shells that exist, to save several forks. + as_shell=$as_dir/$as_base + if { test -f "$as_shell" || test -f "$as_shell.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : + CONFIG_SHELL=$as_shell as_have_required=yes + if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : + break 2 +fi +fi + done;; + esac + as_found=false +done +$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : + CONFIG_SHELL=$SHELL as_have_required=yes +fi; } +IFS=$as_save_IFS + + + if test "x$CONFIG_SHELL" != x; then : + # We cannot yet assume a decent shell, so we have to provide a + # neutralization value for shells without unset; and this also + # works around shells that cannot unset nonexistent variables. + BASH_ENV=/dev/null + ENV=/dev/null + (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV + export CONFIG_SHELL + exec "$CONFIG_SHELL" "$as_myself" ${1+"$@"} +fi + + if test x$as_have_required = xno; then : + $as_echo "$0: This script requires a shell more modern than all" + $as_echo "$0: the shells that I found on your system." + if test x${ZSH_VERSION+set} = xset ; then + $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" + $as_echo "$0: be upgraded to zsh 4.3.4 or later." + else + $as_echo "$0: Please tell bug-autoconf@gnu.org and +$0: http://bugs.clamav.net about your system, including any +$0: error possibly output before this message. Then install +$0: a modern shell, or manually run the script under such a +$0: shell if you do have one." + fi + exit 1 +fi +fi +fi +SHELL=${CONFIG_SHELL-/bin/sh} +export SHELL +# Unset more variables known to interfere with behavior of common tools. +CLICOLOR_FORCE= GREP_OPTIONS= +unset CLICOLOR_FORCE GREP_OPTIONS + +## --------------------- ## +## M4sh Shell Functions. ## +## --------------------- ## +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error "cannot create directory $as_dir" + + +} # as_fn_mkdir_p +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +# as_fn_error ERROR [LINENO LOG_FD] +# --------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with status $?, using 1 if that was 0. +as_fn_error () +{ + as_status=$?; test $as_status -eq 0 && as_status=1 + if test "$3"; then + as_lineno=${as_lineno-"$2"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $1" >&$3 + fi + $as_echo "$as_me: error: $1" >&2 + as_fn_exit $as_status +} # as_fn_error + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + + + as_lineno_1=$LINENO as_lineno_1a=$LINENO + as_lineno_2=$LINENO as_lineno_2a=$LINENO + eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && + test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { + # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) + sed -n ' + p + /[$]LINENO/= + ' <$as_myself | + sed ' + s/[$]LINENO.*/&-/ + t lineno + b + :lineno + N + :loop + s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ + t loop + s/-\n.*// + ' >$as_me.lineno && + chmod +x "$as_me.lineno" || + { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } + + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensitive to this). + . "./$as_me.lineno" + # Exit status is that of the last command. + exit +} + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -p'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -p' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -p' + fi +else + as_ln_s='cp -p' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +if test -x / >/dev/null 2>&1; then + as_test_x='test -x' +else + if ls -dL / >/dev/null 2>&1; then + as_ls_L_option=L + else + as_ls_L_option= + fi + as_test_x=' + eval sh -c '\'' + if test -d "$1"; then + test -d "$1/."; + else + case $1 in #( + -*)set "./$1";; + esac; + case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #(( + ???[sx]*):;;*)false;;esac;fi + '\'' sh + ' +fi +as_executable_p=$as_test_x + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + + +# Check that we are running under the correct shell. +SHELL=${CONFIG_SHELL-/bin/sh} + +case X$lt_ECHO in +X*--fallback-echo) + # Remove one level of quotation (which was required for Make). + ECHO=`echo "$lt_ECHO" | sed 's,\\\\\$\\$0,'$0','` + ;; +esac + +ECHO=${lt_ECHO-echo} +if test "X$1" = X--no-reexec; then + # Discard the --no-reexec flag, and continue. + shift +elif test "X$1" = X--fallback-echo; then + # Avoid inline document here, it may be left over + : +elif test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t' ; then + # Yippee, $ECHO works! + : +else + # Restart under the correct shell. + exec $SHELL "$0" --no-reexec ${1+"$@"} +fi + +if test "X$1" = X--fallback-echo; then + # used as fallback echo + shift + cat <<_LT_EOF +$* +_LT_EOF + exit 0 +fi + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +if test -z "$lt_ECHO"; then + if test "X${echo_test_string+set}" != Xset; then + # find a string as large as possible, as long as the shell can cope with it + for cmd in 'sed 50q "$0"' 'sed 20q "$0"' 'sed 10q "$0"' 'sed 2q "$0"' 'echo test'; do + # expected sizes: less than 2Kb, 1Kb, 512 bytes, 16 bytes, ... + if { echo_test_string=`eval $cmd`; } 2>/dev/null && + { test "X$echo_test_string" = "X$echo_test_string"; } 2>/dev/null + then + break + fi + done + fi + + if test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t' && + echo_testing_string=`{ $ECHO "$echo_test_string"; } 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + : + else + # The Solaris, AIX, and Digital Unix default echo programs unquote + # backslashes. This makes it impossible to quote backslashes using + # echo "$something" | sed 's/\\/\\\\/g' + # + # So, first we look for a working echo in the user's PATH. + + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for dir in $PATH /usr/ucb; do + IFS="$lt_save_ifs" + if (test -f $dir/echo || test -f $dir/echo$ac_exeext) && + test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' && + echo_testing_string=`($dir/echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + ECHO="$dir/echo" + break + fi + done + IFS="$lt_save_ifs" + + if test "X$ECHO" = Xecho; then + # We didn't find a better echo, so look for alternatives. + if test "X`{ print -r '\t'; } 2>/dev/null`" = 'X\t' && + echo_testing_string=`{ print -r "$echo_test_string"; } 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + # This shell has a builtin print -r that does the trick. + ECHO='print -r' + elif { test -f /bin/ksh || test -f /bin/ksh$ac_exeext; } && + test "X$CONFIG_SHELL" != X/bin/ksh; then + # If we have ksh, try running configure again with it. + ORIGINAL_CONFIG_SHELL=${CONFIG_SHELL-/bin/sh} + export ORIGINAL_CONFIG_SHELL + CONFIG_SHELL=/bin/ksh + export CONFIG_SHELL + exec $CONFIG_SHELL "$0" --no-reexec ${1+"$@"} + else + # Try using printf. + ECHO='printf %s\n' + if test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t' && + echo_testing_string=`{ $ECHO "$echo_test_string"; } 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + # Cool, printf works + : + elif echo_testing_string=`($ORIGINAL_CONFIG_SHELL "$0" --fallback-echo '\t') 2>/dev/null` && + test "X$echo_testing_string" = 'X\t' && + echo_testing_string=`($ORIGINAL_CONFIG_SHELL "$0" --fallback-echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + CONFIG_SHELL=$ORIGINAL_CONFIG_SHELL + export CONFIG_SHELL + SHELL="$CONFIG_SHELL" + export SHELL + ECHO="$CONFIG_SHELL $0 --fallback-echo" + elif echo_testing_string=`($CONFIG_SHELL "$0" --fallback-echo '\t') 2>/dev/null` && + test "X$echo_testing_string" = 'X\t' && + echo_testing_string=`($CONFIG_SHELL "$0" --fallback-echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + ECHO="$CONFIG_SHELL $0 --fallback-echo" + else + # maybe with a smaller string... + prev=: + + for cmd in 'echo test' 'sed 2q "$0"' 'sed 10q "$0"' 'sed 20q "$0"' 'sed 50q "$0"'; do + if { test "X$echo_test_string" = "X`eval $cmd`"; } 2>/dev/null + then + break + fi + prev="$cmd" + done + + if test "$prev" != 'sed 50q "$0"'; then + echo_test_string=`eval $prev` + export echo_test_string + exec ${ORIGINAL_CONFIG_SHELL-${CONFIG_SHELL-/bin/sh}} "$0" ${1+"$@"} + else + # Oops. We lost completely, so just stick with echo. + ECHO=echo + fi + fi + fi + fi + fi +fi + +# Copy echo and quote the copy suitably for passing to libtool from +# the Makefile, instead of quoting the original, which is used later. +lt_ECHO=$ECHO +if test "X$lt_ECHO" = "X$CONFIG_SHELL $0 --fallback-echo"; then + lt_ECHO="$CONFIG_SHELL \\\$\$0 --fallback-echo" +fi + + + + +test -n "$DJDIR" || exec 7<&0 &1 + +# Name of the host. +# hostname on some systems (SVR3.2, Linux) returns a bogus exit status, +# so uname gets run too. +ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` + +# +# Initializations. +# +ac_default_prefix=/usr/local +ac_clean_files= +ac_config_libobj_dir=. +LIBOBJS= +cross_compiling=no +subdirs= +MFLAGS= +MAKEFLAGS= + +# Identity of this package. +PACKAGE_NAME='libclamavc++' +PACKAGE_TARNAME='libclamavc--' +PACKAGE_VERSION='devel' +PACKAGE_STRING='libclamavc++ devel' +PACKAGE_BUGREPORT='http://bugs.clamav.net' +PACKAGE_URL='' + +ac_unique_file="llvm/configure" +# Factoring default headers for most tests. +ac_includes_default="\ +#include +#ifdef HAVE_SYS_TYPES_H +# include +#endif +#ifdef HAVE_SYS_STAT_H +# include +#endif +#ifdef STDC_HEADERS +# include +# include +#else +# ifdef HAVE_STDLIB_H +# include +# endif +#endif +#ifdef HAVE_STRING_H +# if !defined STDC_HEADERS && defined HAVE_MEMORY_H +# include +# endif +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif +#ifdef HAVE_INTTYPES_H +# include +#endif +#ifdef HAVE_STDINT_H +# include +#endif +#ifdef HAVE_UNISTD_H +# include +#endif" + +enable_option_checking=no +ac_subst_vars='am__EXEEXT_FALSE +am__EXEEXT_TRUE +LTLIBOBJS +LIBOBJS +BUILD_ARM_FALSE +BUILD_ARM_TRUE +BUILD_PPC_FALSE +BUILD_PPC_TRUE +BUILD_X86_FALSE +BUILD_X86_TRUE +DEBUG_BUILD_FALSE +DEBUG_BUILD_TRUE +subdirs +GMAKE +ifGNUmake +CXXCPP +CPP +OTOOL64 +OTOOL +LIPO +NMEDIT +DSYMUTIL +lt_ECHO +RANLIB +AR +OBJDUMP +LN_S +NM +ac_ct_DUMPBIN +DUMPBIN +LD +FGREP +EGREP +GREP +SED +am__fastdepCC_FALSE +am__fastdepCC_TRUE +CCDEPMODE +ac_ct_CC +CFLAGS +CC +LIBTOOL +MAINT +MAINTAINER_MODE_FALSE +MAINTAINER_MODE_TRUE +am__fastdepCXX_FALSE +am__fastdepCXX_TRUE +CXXDEPMODE +AMDEPBACKSLASH +AMDEP_FALSE +AMDEP_TRUE +am__quote +am__include +DEPDIR +OBJEXT +EXEEXT +ac_ct_CXX +CPPFLAGS +LDFLAGS +CXXFLAGS +CXX +AM_BACKSLASH +AM_DEFAULT_VERBOSITY +am__untar +am__tar +AMTAR +am__leading_dot +SET_MAKE +AWK +mkdir_p +MKDIR_P +INSTALL_STRIP_PROGRAM +STRIP +install_sh +MAKEINFO +AUTOHEADER +AUTOMAKE +AUTOCONF +ACLOCAL +VERSION +PACKAGE +CYGPATH_W +am__isrc +INSTALL_DATA +INSTALL_SCRIPT +INSTALL_PROGRAM +target_os +target_vendor +target_cpu +target +host_os +host_vendor +host_cpu +host +build_os +build_vendor +build_cpu +build +target_alias +host_alias +build_alias +LIBS +ECHO_T +ECHO_N +ECHO_C +DEFS +mandir +localedir +libdir +psdir +pdfdir +dvidir +htmldir +infodir +docdir +oldincludedir +includedir +localstatedir +sharedstatedir +sysconfdir +datadir +datarootdir +libexecdir +sbindir +bindir +program_transform_name +prefix +exec_prefix +PACKAGE_URL +PACKAGE_BUGREPORT +PACKAGE_STRING +PACKAGE_VERSION +PACKAGE_TARNAME +PACKAGE_NAME +PATH_SEPARATOR +SHELL' +ac_subst_files='' +ac_user_opts=' +enable_option_checking +enable_silent_rules +enable_dependency_tracking +enable_maintainer_mode +enable_static +enable_shared +with_pic +enable_fast_install +with_gnu_ld +enable_libtool_lock +enable_llvm +enable_optimized +enable_all_jit_targets +' + ac_precious_vars='build_alias +host_alias +target_alias +CXX +CXXFLAGS +LDFLAGS +LIBS +CPPFLAGS +CCC +CC +CFLAGS +CPP +CXXCPP' +ac_subdirs_all='llvm' + +# Initialize some variables set by options. +ac_init_help= +ac_init_version=false +ac_unrecognized_opts= +ac_unrecognized_sep= +# The variables have the same names as the options, with +# dashes changed to underlines. +cache_file=/dev/null +exec_prefix=NONE +no_create= +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +verbose= +x_includes=NONE +x_libraries=NONE + +# Installation directory options. +# These are left unexpanded so users can "make install exec_prefix=/foo" +# and all the variables that are supposed to be based on exec_prefix +# by default will actually change. +# Use braces instead of parens because sh, perl, etc. also accept them. +# (The list follows the same order as the GNU Coding Standards.) +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datarootdir='${prefix}/share' +datadir='${datarootdir}' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +includedir='${prefix}/include' +oldincludedir='/usr/include' +docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' +infodir='${datarootdir}/info' +htmldir='${docdir}' +dvidir='${docdir}' +pdfdir='${docdir}' +psdir='${docdir}' +libdir='${exec_prefix}/lib' +localedir='${datarootdir}/locale' +mandir='${datarootdir}/man' + +ac_prev= +ac_dashdash= +for ac_option +do + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval $ac_prev=\$ac_option + ac_prev= + continue + fi + + case $ac_option in + *=*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; + *) ac_optarg=yes ;; + esac + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case $ac_dashdash$ac_option in + --) + ac_dashdash=yes ;; + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir=$ac_optarg ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build_alias ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build_alias=$ac_optarg ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file=$ac_optarg ;; + + --config-cache | -C) + cache_file=config.cache ;; + + -datadir | --datadir | --datadi | --datad) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=*) + datadir=$ac_optarg ;; + + -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ + | --dataroo | --dataro | --datar) + ac_prev=datarootdir ;; + -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ + | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) + datarootdir=$ac_optarg ;; + + -disable-* | --disable-*) + ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error "invalid feature name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=no ;; + + -docdir | --docdir | --docdi | --doc | --do) + ac_prev=docdir ;; + -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) + docdir=$ac_optarg ;; + + -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) + ac_prev=dvidir ;; + -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) + dvidir=$ac_optarg ;; + + -enable-* | --enable-*) + ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error "invalid feature name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=\$ac_optarg ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix=$ac_optarg ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he | -h) + ac_init_help=long ;; + -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) + ac_init_help=recursive ;; + -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) + ac_init_help=short ;; + + -host | --host | --hos | --ho) + ac_prev=host_alias ;; + -host=* | --host=* | --hos=* | --ho=*) + host_alias=$ac_optarg ;; + + -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) + ac_prev=htmldir ;; + -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ + | --ht=*) + htmldir=$ac_optarg ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir=$ac_optarg ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir=$ac_optarg ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir=$ac_optarg ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir=$ac_optarg ;; + + -localedir | --localedir | --localedi | --localed | --locale) + ac_prev=localedir ;; + -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) + localedir=$ac_optarg ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst | --locals) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) + localstatedir=$ac_optarg ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir=$ac_optarg ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c | -n) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir=$ac_optarg ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix=$ac_optarg ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix=$ac_optarg ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix=$ac_optarg ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name=$ac_optarg ;; + + -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) + ac_prev=pdfdir ;; + -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) + pdfdir=$ac_optarg ;; + + -psdir | --psdir | --psdi | --psd | --ps) + ac_prev=psdir ;; + -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) + psdir=$ac_optarg ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir=$ac_optarg ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir=$ac_optarg ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site=$ac_optarg ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir=$ac_optarg ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir=$ac_optarg ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target_alias ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target_alias=$ac_optarg ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers | -V) + ac_init_version=: ;; + + -with-* | --with-*) + ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error "invalid package name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=\$ac_optarg ;; + + -without-* | --without-*) + ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error "invalid package name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=no ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes=$ac_optarg ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries=$ac_optarg ;; + + -*) as_fn_error "unrecognized option: \`$ac_option' +Try \`$0 --help' for more information." + ;; + + *=*) + ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` + # Reject names that are not valid shell variable names. + case $ac_envvar in #( + '' | [0-9]* | *[!_$as_cr_alnum]* ) + as_fn_error "invalid variable name: \`$ac_envvar'" ;; + esac + eval $ac_envvar=\$ac_optarg + export $ac_envvar ;; + + *) + # FIXME: should be removed in autoconf 3.0. + $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 + expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && + $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 + : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option} + ;; + + esac +done + +if test -n "$ac_prev"; then + ac_option=--`echo $ac_prev | sed 's/_/-/g'` + as_fn_error "missing argument to $ac_option" +fi + +if test -n "$ac_unrecognized_opts"; then + case $enable_option_checking in + no) ;; + fatal) as_fn_error "unrecognized options: $ac_unrecognized_opts" ;; + *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; + esac +fi + +# Check all directory arguments for consistency. +for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ + datadir sysconfdir sharedstatedir localstatedir includedir \ + oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ + libdir localedir mandir +do + eval ac_val=\$$ac_var + # Remove trailing slashes. + case $ac_val in + */ ) + ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` + eval $ac_var=\$ac_val;; + esac + # Be sure to have absolute directory names. + case $ac_val in + [\\/$]* | ?:[\\/]* ) continue;; + NONE | '' ) case $ac_var in *prefix ) continue;; esac;; + esac + as_fn_error "expected an absolute directory name for --$ac_var: $ac_val" +done + +# There might be people who depend on the old broken behavior: `$host' +# used to hold the argument of --host etc. +# FIXME: To remove some day. +build=$build_alias +host=$host_alias +target=$target_alias + +# FIXME: To remove some day. +if test "x$host_alias" != x; then + if test "x$build_alias" = x; then + cross_compiling=maybe + $as_echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host. + If a cross compiler is detected then cross compile mode will be used." >&2 + elif test "x$build_alias" != "x$host_alias"; then + cross_compiling=yes + fi +fi + +ac_tool_prefix= +test -n "$host_alias" && ac_tool_prefix=$host_alias- + +test "$silent" = yes && exec 6>/dev/null + + +ac_pwd=`pwd` && test -n "$ac_pwd" && +ac_ls_di=`ls -di .` && +ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || + as_fn_error "working directory cannot be determined" +test "X$ac_ls_di" = "X$ac_pwd_ls_di" || + as_fn_error "pwd does not report name of working directory" + + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then the parent directory. + ac_confdir=`$as_dirname -- "$as_myself" || +$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_myself" : 'X\(//\)[^/]' \| \ + X"$as_myself" : 'X\(//\)$' \| \ + X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_myself" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + srcdir=$ac_confdir + if test ! -r "$srcdir/$ac_unique_file"; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r "$srcdir/$ac_unique_file"; then + test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." + as_fn_error "cannot find sources ($ac_unique_file) in $srcdir" +fi +ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" +ac_abs_confdir=`( + cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error "$ac_msg" + pwd)` +# When building in place, set srcdir=. +if test "$ac_abs_confdir" = "$ac_pwd"; then + srcdir=. +fi +# Remove unnecessary trailing slashes from srcdir. +# Double slashes in file names in object file debugging info +# mess up M-x gdb in Emacs. +case $srcdir in +*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; +esac +for ac_var in $ac_precious_vars; do + eval ac_env_${ac_var}_set=\${${ac_var}+set} + eval ac_env_${ac_var}_value=\$${ac_var} + eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} + eval ac_cv_env_${ac_var}_value=\$${ac_var} +done + +# +# Report the --help message. +# +if test "$ac_init_help" = "long"; then + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat <<_ACEOF +\`configure' configures libclamavc++ devel to adapt to many kinds of systems. + +Usage: $0 [OPTION]... [VAR=VALUE]... + +To assign environment variables (e.g., CC, CFLAGS...), specify them as +VAR=VALUE. See below for descriptions of some of the useful variables. + +Defaults for the options are specified in brackets. + +Configuration: + -h, --help display this help and exit + --help=short display options specific to this package + --help=recursive display the short help of all the included packages + -V, --version display version information and exit + -q, --quiet, --silent do not print \`checking...' messages + --cache-file=FILE cache test results in FILE [disabled] + -C, --config-cache alias for \`--cache-file=config.cache' + -n, --no-create do not create output files + --srcdir=DIR find the sources in DIR [configure dir or \`..'] + +Installation directories: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [PREFIX] + +By default, \`make install' will install all the files in +\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify +an installation prefix other than \`$ac_default_prefix' using \`--prefix', +for instance \`--prefix=\$HOME'. + +For better control, use the options below. + +Fine tuning of the installation directories: + --bindir=DIR user executables [EPREFIX/bin] + --sbindir=DIR system admin executables [EPREFIX/sbin] + --libexecdir=DIR program executables [EPREFIX/libexec] + --sysconfdir=DIR read-only single-machine data [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] + --localstatedir=DIR modifiable single-machine data [PREFIX/var] + --libdir=DIR object code libraries [EPREFIX/lib] + --includedir=DIR C header files [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc [/usr/include] + --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] + --datadir=DIR read-only architecture-independent data [DATAROOTDIR] + --infodir=DIR info documentation [DATAROOTDIR/info] + --localedir=DIR locale-dependent data [DATAROOTDIR/locale] + --mandir=DIR man documentation [DATAROOTDIR/man] + --docdir=DIR documentation root [DATAROOTDIR/doc/libclamavc--] + --htmldir=DIR html documentation [DOCDIR] + --dvidir=DIR dvi documentation [DOCDIR] + --pdfdir=DIR pdf documentation [DOCDIR] + --psdir=DIR ps documentation [DOCDIR] +_ACEOF + + cat <<\_ACEOF + +Program names: + --program-prefix=PREFIX prepend PREFIX to installed program names + --program-suffix=SUFFIX append SUFFIX to installed program names + --program-transform-name=PROGRAM run sed PROGRAM on installed program names + +System types: + --build=BUILD configure for building on BUILD [guessed] + --host=HOST cross-compile to build programs to run on HOST [BUILD] + --target=TARGET configure for building compilers for TARGET [HOST] +_ACEOF +fi + +if test -n "$ac_init_help"; then + case $ac_init_help in + short | recursive ) echo "Configuration of libclamavc++ devel:";; + esac + cat <<\_ACEOF + +Optional Features: + --disable-option-checking ignore unrecognized --enable/--with options + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --enable-silent-rules less verbose build output (undo: `make V=1') + --disable-silent-rules verbose build output (undo: `make V=0') + --disable-dependency-tracking speeds up one-time build + --enable-dependency-tracking do not reject slow dependency extractors + --enable-maintainer-mode enable make rules and dependencies not useful + (and sometimes confusing) to the casual installer + --enable-static[=PKGS] build static libraries [default=no] + --enable-shared[=PKGS] build shared libraries [default=yes] + --enable-fast-install[=PKGS] + optimize for fast installation [default=yes] + --disable-libtool-lock avoid locking (might break parallel builds) + -enable-llvm Enable 'llvm' JIT/verifier support [default=auto] + -enable-optimized Compile with optimizations enabled (default is YES) + -enable-all-jit-targets Build all the targets that support JIT for testing + (default NO) + +Optional Packages: + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --with-pic try to use only PIC/non-PIC objects [default=use + both] + --with-gnu-ld assume the C compiler uses GNU ld [default=no] + +Some influential environment variables: + CXX C++ compiler command + CXXFLAGS C++ compiler flags + LDFLAGS linker flags, e.g. -L if you have libraries in a + nonstandard directory + LIBS libraries to pass to the linker, e.g. -l + CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if + you have headers in a nonstandard directory + CC C compiler command + CFLAGS C compiler flags + CPP C preprocessor + CXXCPP C++ preprocessor + +Use these variables to override the choices made by `configure' or to help +it to find libraries and programs with nonstandard names/locations. + +Report bugs to . +_ACEOF +ac_status=$? +fi + +if test "$ac_init_help" = "recursive"; then + # If there are subdirs, report their specific --help. + for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue + test -d "$ac_dir" || + { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || + continue + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + cd "$ac_dir" || { ac_status=$?; continue; } + # Check for guested configure. + if test -f "$ac_srcdir/configure.gnu"; then + echo && + $SHELL "$ac_srcdir/configure.gnu" --help=recursive + elif test -f "$ac_srcdir/configure"; then + echo && + $SHELL "$ac_srcdir/configure" --help=recursive + else + $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 + fi || ac_status=$? + cd "$ac_pwd" || { ac_status=$?; break; } + done +fi + +test -n "$ac_init_help" && exit $ac_status +if $ac_init_version; then + cat <<\_ACEOF +libclamavc++ configure devel +generated by GNU Autoconf 2.65 + +Copyright (C) 2009 Free Software Foundation, Inc. +This configure script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it. +_ACEOF + exit +fi + +## ------------------------ ## +## Autoconf initialization. ## +## ------------------------ ## + +# ac_fn_cxx_try_compile LINENO +# ---------------------------- +# Try to compile conftest.$ac_ext, and return whether this succeeded. +ac_fn_cxx_try_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext + if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_cxx_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} + as_fn_set_status $ac_retval + +} # ac_fn_cxx_try_compile + +# ac_fn_c_try_compile LINENO +# -------------------------- +# Try to compile conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext + if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} + as_fn_set_status $ac_retval + +} # ac_fn_c_try_compile + +# ac_fn_c_try_link LINENO +# ----------------------- +# Try to link conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_link () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext conftest$ac_exeext + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_test_x conftest$ac_exeext + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information + # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would + # interfere with the next link command; also delete a directory that is + # left behind by Apple's compiler. We do this before executing the actions. + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} + as_fn_set_status $ac_retval + +} # ac_fn_c_try_link + +# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES +# ------------------------------------------------------- +# Tests whether HEADER exists and can be compiled using the include files in +# INCLUDES, setting the cache variable VAR accordingly. +ac_fn_c_check_header_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +#include <$2> +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} + +} # ac_fn_c_check_header_compile + +# ac_fn_c_try_cpp LINENO +# ---------------------- +# Try to preprocess conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_cpp () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } >/dev/null && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} + as_fn_set_status $ac_retval + +} # ac_fn_c_try_cpp + +# ac_fn_c_try_run LINENO +# ---------------------- +# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes +# that executables *can* be run. +ac_fn_c_try_run () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then : + ac_retval=0 +else + $as_echo "$as_me: program exited with status $ac_status" >&5 + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=$ac_status +fi + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} + as_fn_set_status $ac_retval + +} # ac_fn_c_try_run + +# ac_fn_c_check_func LINENO FUNC VAR +# ---------------------------------- +# Tests whether FUNC exists, setting the cache variable VAR accordingly +ac_fn_c_check_func () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +/* Define $2 to an innocuous variant, in case declares $2. + For example, HP-UX 11i declares gettimeofday. */ +#define $2 innocuous_$2 + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $2 (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $2 + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $2 (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$2 || defined __stub___$2 +choke me +#endif + +int +main () +{ +return $2 (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} + +} # ac_fn_c_check_func + +# ac_fn_cxx_try_cpp LINENO +# ------------------------ +# Try to preprocess conftest.$ac_ext, and return whether this succeeded. +ac_fn_cxx_try_cpp () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } >/dev/null && { + test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" || + test ! -s conftest.err + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} + as_fn_set_status $ac_retval + +} # ac_fn_cxx_try_cpp + +# ac_fn_cxx_try_link LINENO +# ------------------------- +# Try to link conftest.$ac_ext, and return whether this succeeded. +ac_fn_cxx_try_link () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext conftest$ac_exeext + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_cxx_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_test_x conftest$ac_exeext + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information + # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would + # interfere with the next link command; also delete a directory that is + # left behind by Apple's compiler. We do this before executing the actions. + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} + as_fn_set_status $ac_retval + +} # ac_fn_cxx_try_link +cat >config.log <<_ACEOF +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. + +It was created by libclamavc++ $as_me devel, which was +generated by GNU Autoconf 2.65. Invocation command line was + + $ $0 $@ + +_ACEOF +exec 5>>config.log +{ +cat <<_ASUNAME +## --------- ## +## Platform. ## +## --------- ## + +hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` + +/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` +/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` +/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` +/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` + +_ASUNAME + +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + $as_echo "PATH: $as_dir" + done +IFS=$as_save_IFS + +} >&5 + +cat >&5 <<_ACEOF + + +## ----------- ## +## Core tests. ## +## ----------- ## + +_ACEOF + + +# Keep a trace of the command line. +# Strip out --no-create and --no-recursion so they do not pile up. +# Strip out --silent because we don't want to record it for future runs. +# Also quote any args containing shell meta-characters. +# Make two passes to allow for proper duplicate-argument suppression. +ac_configure_args= +ac_configure_args0= +ac_configure_args1= +ac_must_keep_next=false +for ac_pass in 1 2 +do + for ac_arg + do + case $ac_arg in + -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + continue ;; + *\'*) + ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + case $ac_pass in + 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; + 2) + as_fn_append ac_configure_args1 " '$ac_arg'" + if test $ac_must_keep_next = true; then + ac_must_keep_next=false # Got value, back to normal. + else + case $ac_arg in + *=* | --config-cache | -C | -disable-* | --disable-* \ + | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ + | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ + | -with-* | --with-* | -without-* | --without-* | --x) + case "$ac_configure_args0 " in + "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; + esac + ;; + -* ) ac_must_keep_next=true ;; + esac + fi + as_fn_append ac_configure_args " '$ac_arg'" + ;; + esac + done +done +{ ac_configure_args0=; unset ac_configure_args0;} +{ ac_configure_args1=; unset ac_configure_args1;} + +# When interrupted or exit'd, cleanup temporary files, and complete +# config.log. We remove comments because anyway the quotes in there +# would cause problems or look ugly. +# WARNING: Use '\'' to represent an apostrophe within the trap. +# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. +trap 'exit_status=$? + # Save into config.log some information that might help in debugging. + { + echo + + cat <<\_ASBOX +## ---------------- ## +## Cache variables. ## +## ---------------- ## +_ASBOX + echo + # The following way of writing the cache mishandles newlines in values, +( + for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + (set) 2>&1 | + case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + sed -n \ + "s/'\''/'\''\\\\'\'''\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" + ;; #( + *) + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) + echo + + cat <<\_ASBOX +## ----------------- ## +## Output variables. ## +## ----------------- ## +_ASBOX + echo + for ac_var in $ac_subst_vars + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + $as_echo "$ac_var='\''$ac_val'\''" + done | sort + echo + + if test -n "$ac_subst_files"; then + cat <<\_ASBOX +## ------------------- ## +## File substitutions. ## +## ------------------- ## +_ASBOX + echo + for ac_var in $ac_subst_files + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + $as_echo "$ac_var='\''$ac_val'\''" + done | sort + echo + fi + + if test -s confdefs.h; then + cat <<\_ASBOX +## ----------- ## +## confdefs.h. ## +## ----------- ## +_ASBOX + echo + cat confdefs.h + echo + fi + test "$ac_signal" != 0 && + $as_echo "$as_me: caught signal $ac_signal" + $as_echo "$as_me: exit $exit_status" + } >&5 + rm -f core *.core core.conftest.* && + rm -f -r conftest* confdefs* conf$$* $ac_clean_files && + exit $exit_status +' 0 +for ac_signal in 1 2 13 15; do + trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal +done +ac_signal=0 + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -f -r conftest* confdefs.h + +$as_echo "/* confdefs.h */" > confdefs.h + +# Predefined preprocessor variables. + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_NAME "$PACKAGE_NAME" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_TARNAME "$PACKAGE_TARNAME" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_VERSION "$PACKAGE_VERSION" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_STRING "$PACKAGE_STRING" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_URL "$PACKAGE_URL" +_ACEOF + + +# Let the site file select an alternate cache file if it wants to. +# Prefer an explicitly selected file to automatically selected ones. +ac_site_file1=NONE +ac_site_file2=NONE +if test -n "$CONFIG_SITE"; then + ac_site_file1=$CONFIG_SITE +elif test "x$prefix" != xNONE; then + ac_site_file1=$prefix/share/config.site + ac_site_file2=$prefix/etc/config.site +else + ac_site_file1=$ac_default_prefix/share/config.site + ac_site_file2=$ac_default_prefix/etc/config.site +fi +for ac_site_file in "$ac_site_file1" "$ac_site_file2" +do + test "x$ac_site_file" = xNONE && continue + if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 +$as_echo "$as_me: loading site script $ac_site_file" >&6;} + sed 's/^/| /' "$ac_site_file" >&5 + . "$ac_site_file" + fi +done + +if test -r "$cache_file"; then + # Some versions of bash will fail to source /dev/null (special files + # actually), so we avoid doing that. DJGPP emulates it as a regular file. + if test /dev/null != "$cache_file" && test -f "$cache_file"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 +$as_echo "$as_me: loading cache $cache_file" >&6;} + case $cache_file in + [\\/]* | ?:[\\/]* ) . "$cache_file";; + *) . "./$cache_file";; + esac + fi +else + { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 +$as_echo "$as_me: creating cache $cache_file" >&6;} + >$cache_file +fi + +# Check that the precious variables saved in the cache have kept the same +# value. +ac_cache_corrupted=false +for ac_var in $ac_precious_vars; do + eval ac_old_set=\$ac_cv_env_${ac_var}_set + eval ac_new_set=\$ac_env_${ac_var}_set + eval ac_old_val=\$ac_cv_env_${ac_var}_value + eval ac_new_val=\$ac_env_${ac_var}_value + case $ac_old_set,$ac_new_set in + set,) + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 +$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,set) + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 +$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,);; + *) + if test "x$ac_old_val" != "x$ac_new_val"; then + # differences in whitespace do not lead to failure. + ac_old_val_w=`echo x $ac_old_val` + ac_new_val_w=`echo x $ac_new_val` + if test "$ac_old_val_w" != "$ac_new_val_w"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 +$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} + ac_cache_corrupted=: + else + { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 +$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} + eval $ac_var=\$ac_old_val + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 +$as_echo "$as_me: former value: \`$ac_old_val'" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 +$as_echo "$as_me: current value: \`$ac_new_val'" >&2;} + fi;; + esac + # Pass precious variables to config.status. + if test "$ac_new_set" = set; then + case $ac_new_val in + *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; + *) ac_arg=$ac_var=$ac_new_val ;; + esac + case " $ac_configure_args " in + *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. + *) as_fn_append ac_configure_args " '$ac_arg'" ;; + esac + fi +done +if $ac_cache_corrupted; then + { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 +$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} + as_fn_error "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 +fi +## -------------------- ## +## Main body of script. ## +## -------------------- ## + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +ac_aux_dir= +for ac_dir in config "$srcdir"/config; do + for ac_t in install-sh install.sh shtool; do + if test -f "$ac_dir/$ac_t"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/$ac_t -c" + break 2 + fi + done +done +if test -z "$ac_aux_dir"; then + as_fn_error "cannot find install-sh, install.sh, or shtool in config \"$srcdir\"/config" "$LINENO" 5 +fi + +# These three variables are undocumented and unsupported, +# and are intended to be withdrawn in a future Autoconf release. +# They can cause serious problems if a builder's source tree is in a directory +# whose full name contains unusual characters. +ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. +ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. +ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. + + + + +ac_config_headers="$ac_config_headers clamavcxx-config.h" + +# Make sure we can run config.sub. +$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || + as_fn_error "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5 + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5 +$as_echo_n "checking build system type... " >&6; } +if test "${ac_cv_build+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + ac_build_alias=$build_alias +test "x$ac_build_alias" = x && + ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"` +test "x$ac_build_alias" = x && + as_fn_error "cannot guess build type; you must specify one" "$LINENO" 5 +ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` || + as_fn_error "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5 + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5 +$as_echo "$ac_cv_build" >&6; } +case $ac_cv_build in +*-*-*) ;; +*) as_fn_error "invalid value of canonical build" "$LINENO" 5;; +esac +build=$ac_cv_build +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_build +shift +build_cpu=$1 +build_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +build_os=$* +IFS=$ac_save_IFS +case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5 +$as_echo_n "checking host system type... " >&6; } +if test "${ac_cv_host+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test "x$host_alias" = x; then + ac_cv_host=$ac_cv_build +else + ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` || + as_fn_error "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5 +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5 +$as_echo "$ac_cv_host" >&6; } +case $ac_cv_host in +*-*-*) ;; +*) as_fn_error "invalid value of canonical host" "$LINENO" 5;; +esac +host=$ac_cv_host +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_host +shift +host_cpu=$1 +host_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +host_os=$* +IFS=$ac_save_IFS +case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking target system type" >&5 +$as_echo_n "checking target system type... " >&6; } +if test "${ac_cv_target+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test "x$target_alias" = x; then + ac_cv_target=$ac_cv_host +else + ac_cv_target=`$SHELL "$ac_aux_dir/config.sub" $target_alias` || + as_fn_error "$SHELL $ac_aux_dir/config.sub $target_alias failed" "$LINENO" 5 +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_target" >&5 +$as_echo "$ac_cv_target" >&6; } +case $ac_cv_target in +*-*-*) ;; +*) as_fn_error "invalid value of canonical target" "$LINENO" 5;; +esac +target=$ac_cv_target +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_target +shift +target_cpu=$1 +target_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +target_os=$* +IFS=$ac_save_IFS +case $target_os in *\ *) target_os=`echo "$target_os" | sed 's/ /-/g'`;; esac + + +# The aliases save the names the user supplied, while $host etc. +# will get canonicalized. +test -n "$target_alias" && + test "$program_prefix$program_suffix$program_transform_name" = \ + NONENONEs,x,x, && + program_prefix=${target_alias}- +am__api_version='1.11' + +# Find a good install program. We prefer a C program (faster), +# so one script is as good as another. But avoid the broken or +# incompatible versions: +# SysV /etc/install, /usr/sbin/install +# SunOS /usr/etc/install +# IRIX /sbin/install +# AIX /bin/install +# AmigaOS /C/install, which installs bootblocks on floppy discs +# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag +# AFS /usr/afsws/bin/install, which mishandles nonexistent args +# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# OS/2's system install, which has a completely different semantic +# ./install, which can be erroneously created by make from ./install.sh. +# Reject install programs that cannot install multiple files. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5 +$as_echo_n "checking for a BSD-compatible install... " >&6; } +if test -z "$INSTALL"; then +if test "${ac_cv_path_install+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + # Account for people who put trailing slashes in PATH elements. +case $as_dir/ in #(( + ./ | .// | /[cC]/* | \ + /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ + ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \ + /usr/ucb/* ) ;; + *) + # OSF1 and SCO ODT 3.0 have their own names for install. + # Don't use installbsd from OSF since it installs stuff as root + # by default. + for ac_prog in ginstall scoinst install; do + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; }; then + if test $ac_prog = install && + grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # AIX install. It has an incompatible calling convention. + : + elif test $ac_prog = install && + grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # program-specific install script used by HP pwplus--don't use. + : + else + rm -rf conftest.one conftest.two conftest.dir + echo one > conftest.one + echo two > conftest.two + mkdir conftest.dir + if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" && + test -s conftest.one && test -s conftest.two && + test -s conftest.dir/conftest.one && + test -s conftest.dir/conftest.two + then + ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" + break 3 + fi + fi + fi + done + done + ;; +esac + + done +IFS=$as_save_IFS + +rm -rf conftest.one conftest.two conftest.dir + +fi + if test "${ac_cv_path_install+set}" = set; then + INSTALL=$ac_cv_path_install + else + # As a last resort, use the slow shell script. Don't cache a + # value for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the value is a relative name. + INSTALL=$ac_install_sh + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5 +$as_echo "$INSTALL" >&6; } + +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' + +test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' + +test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether build environment is sane" >&5 +$as_echo_n "checking whether build environment is sane... " >&6; } +# Just in case +sleep 1 +echo timestamp > conftest.file +# Reject unsafe characters in $srcdir or the absolute working directory +# name. Accept space and tab only in the latter. +am_lf=' +' +case `pwd` in + *[\\\"\#\$\&\'\`$am_lf]*) + as_fn_error "unsafe absolute working directory name" "$LINENO" 5;; +esac +case $srcdir in + *[\\\"\#\$\&\'\`$am_lf\ \ ]*) + as_fn_error "unsafe srcdir value: \`$srcdir'" "$LINENO" 5;; +esac + +# Do `set' in a subshell so we don't clobber the current shell's +# arguments. Must try -L first in case configure is actually a +# symlink; some systems play weird games with the mod time of symlinks +# (eg FreeBSD returns the mod time of the symlink's containing +# directory). +if ( + set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` + if test "$*" = "X"; then + # -L didn't work. + set X `ls -t "$srcdir/configure" conftest.file` + fi + rm -f conftest.file + if test "$*" != "X $srcdir/configure conftest.file" \ + && test "$*" != "X conftest.file $srcdir/configure"; then + + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + as_fn_error "ls -t appears to fail. Make sure there is not a broken +alias in your environment" "$LINENO" 5 + fi + + test "$2" = conftest.file + ) +then + # Ok. + : +else + as_fn_error "newly created file is older than distributed files! +Check your system clock" "$LINENO" 5 +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +test "$program_prefix" != NONE && + program_transform_name="s&^&$program_prefix&;$program_transform_name" +# Use a double $ so make ignores it. +test "$program_suffix" != NONE && + program_transform_name="s&\$&$program_suffix&;$program_transform_name" +# Double any \ or $. +# By default was `s,x,x', remove it if useless. +ac_script='s/[\\$]/&&/g;s/;s,x,x,$//' +program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"` + +# expand $ac_aux_dir to an absolute path +am_aux_dir=`cd $ac_aux_dir && pwd` + +if test x"${MISSING+set}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; + *) + MISSING="\${SHELL} $am_aux_dir/missing" ;; + esac +fi +# Use eval to expand $SHELL +if eval "$MISSING --run true"; then + am_missing_run="$MISSING --run " +else + am_missing_run= + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \`missing' script is too old or missing" >&5 +$as_echo "$as_me: WARNING: \`missing' script is too old or missing" >&2;} +fi + +if test x"${install_sh}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; + *) + install_sh="\${SHELL} $am_aux_dir/install-sh" + esac +fi + +# Installed binaries are usually stripped using `strip' when the user +# run `make install-strip'. However `strip' might not be the right +# tool to use in cross-compilation environments, therefore Automake +# will honor the `STRIP' environment variable to overrule this program. +if test "$cross_compiling" != no; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. +set dummy ${ac_tool_prefix}strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_STRIP+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$STRIP"; then + ac_cv_prog_STRIP="$STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_STRIP="${ac_tool_prefix}strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +STRIP=$ac_cv_prog_STRIP +if test -n "$STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 +$as_echo "$STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_STRIP"; then + ac_ct_STRIP=$STRIP + # Extract the first word of "strip", so it can be a program name with args. +set dummy strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_ac_ct_STRIP+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_STRIP"; then + ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_STRIP="strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP +if test -n "$ac_ct_STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 +$as_echo "$ac_ct_STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_STRIP" = x; then + STRIP=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + STRIP=$ac_ct_STRIP + fi +else + STRIP="$ac_cv_prog_STRIP" +fi + +fi +INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a thread-safe mkdir -p" >&5 +$as_echo_n "checking for a thread-safe mkdir -p... " >&6; } +if test -z "$MKDIR_P"; then + if test "${ac_cv_path_mkdir+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in mkdir gmkdir; do + for ac_exec_ext in '' $ac_executable_extensions; do + { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; } || continue + case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #( + 'mkdir (GNU coreutils) '* | \ + 'mkdir (coreutils) '* | \ + 'mkdir (fileutils) '4.1*) + ac_cv_path_mkdir=$as_dir/$ac_prog$ac_exec_ext + break 3;; + esac + done + done + done +IFS=$as_save_IFS + +fi + + test -d ./--version && rmdir ./--version + if test "${ac_cv_path_mkdir+set}" = set; then + MKDIR_P="$ac_cv_path_mkdir -p" + else + # As a last resort, use the slow shell script. Don't cache a + # value for MKDIR_P within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the value is a relative name. + MKDIR_P="$ac_install_sh -d" + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $MKDIR_P" >&5 +$as_echo "$MKDIR_P" >&6; } + +mkdir_p="$MKDIR_P" +case $mkdir_p in + [\\/$]* | ?:[\\/]*) ;; + */*) mkdir_p="\$(top_builddir)/$mkdir_p" ;; +esac + +for ac_prog in gawk mawk nawk awk +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_AWK+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$AWK"; then + ac_cv_prog_AWK="$AWK" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_AWK="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +AWK=$ac_cv_prog_AWK +if test -n "$AWK"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5 +$as_echo "$AWK" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$AWK" && break +done + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 +$as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } +set x ${MAKE-make} +ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` +if { as_var=ac_cv_prog_make_${ac_make}_set; eval "test \"\${$as_var+set}\" = set"; }; then : + $as_echo_n "(cached) " >&6 +else + cat >conftest.make <<\_ACEOF +SHELL = /bin/sh +all: + @echo '@@@%%%=$(MAKE)=@@@%%%' +_ACEOF +# GNU make sometimes prints "make[1]: Entering...", which would confuse us. +case `${MAKE-make} -f conftest.make 2>/dev/null` in + *@@@%%%=?*=@@@%%%*) + eval ac_cv_prog_make_${ac_make}_set=yes;; + *) + eval ac_cv_prog_make_${ac_make}_set=no;; +esac +rm -f conftest.make +fi +if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + SET_MAKE= +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + SET_MAKE="MAKE=${MAKE-make}" +fi + +rm -rf .tst 2>/dev/null +mkdir .tst 2>/dev/null +if test -d .tst; then + am__leading_dot=. +else + am__leading_dot=_ +fi +rmdir .tst 2>/dev/null + +if test "`cd $srcdir && pwd`" != "`pwd`"; then + # Use -I$(srcdir) only when $(srcdir) != ., so that make's output + # is not polluted with repeated "-I." + am__isrc=' -I$(srcdir)' + # test to see if srcdir already configured + if test -f $srcdir/config.status; then + as_fn_error "source directory already configured; run \"make distclean\" there first" "$LINENO" 5 + fi +fi + +# test whether we have cygpath +if test -z "$CYGPATH_W"; then + if (cygpath --version) >/dev/null 2>/dev/null; then + CYGPATH_W='cygpath -w' + else + CYGPATH_W=echo + fi +fi + + +# Define the identity of the package. + PACKAGE='libclamavc--' + VERSION='devel' + + +# Some tools Automake needs. + +ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"} + + +AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"} + + +AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"} + + +AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"} + + +MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"} + +# We need awk for the "check" target. The system "awk" is bad on +# some platforms. +# Always define AMTAR for backward compatibility. + +AMTAR=${AMTAR-"${am_missing_run}tar"} + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to create a pax tar archive" >&5 +$as_echo_n "checking how to create a pax tar archive... " >&6; } +# Loop over all known methods to create a tar archive until one works. +_am_tools='gnutar pax cpio none' +_am_tools=${am_cv_prog_tar_pax-$_am_tools} +# Do not fold the above two line into one, because Tru64 sh and +# Solaris sh will not grok spaces in the rhs of `-'. +for _am_tool in $_am_tools +do + case $_am_tool in + gnutar) + for _am_tar in tar gnutar gtar; + do + { echo "$as_me:$LINENO: $_am_tar --version" >&5 + ($_am_tar --version) >&5 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && break + done + am__tar="$_am_tar --format=posix -chf - "'"$$tardir"' + am__tar_="$_am_tar --format=posix -chf - "'"$tardir"' + am__untar="$_am_tar -xf -" + ;; + plaintar) + # Must skip GNU tar: if it does not support --format= it doesn't create + # ustar tarball either. + (tar --version) >/dev/null 2>&1 && continue + am__tar='tar chf - "$$tardir"' + am__tar_='tar chf - "$tardir"' + am__untar='tar xf -' + ;; + pax) + am__tar='pax -L -x pax -w "$$tardir"' + am__tar_='pax -L -x pax -w "$tardir"' + am__untar='pax -r' + ;; + cpio) + am__tar='find "$$tardir" -print | cpio -o -H pax -L' + am__tar_='find "$tardir" -print | cpio -o -H pax -L' + am__untar='cpio -i -H pax -d' + ;; + none) + am__tar=false + am__tar_=false + am__untar=false + ;; + esac + + # If the value was cached, stop now. We just wanted to have am__tar + # and am__untar set. + test -n "${am_cv_prog_tar_pax}" && break + + # tar/untar a dummy directory, and stop if the command works + rm -rf conftest.dir + mkdir conftest.dir + echo GrepMe > conftest.dir/file + { echo "$as_me:$LINENO: tardir=conftest.dir && eval $am__tar_ >conftest.tar" >&5 + (tardir=conftest.dir && eval $am__tar_ >conftest.tar) >&5 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + rm -rf conftest.dir + if test -s conftest.tar; then + { echo "$as_me:$LINENO: $am__untar &5 + ($am__untar &5 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + grep GrepMe conftest.dir/file >/dev/null 2>&1 && break + fi +done +rm -rf conftest.dir + +if test "${am_cv_prog_tar_pax+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + am_cv_prog_tar_pax=$_am_tool +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_tar_pax" >&5 +$as_echo "$am_cv_prog_tar_pax" >&6; } + + + + + +# Check whether --enable-silent-rules was given. +if test "${enable_silent_rules+set}" = set; then : + enableval=$enable_silent_rules; +fi + +case $enable_silent_rules in +yes) AM_DEFAULT_VERBOSITY=0;; +no) AM_DEFAULT_VERBOSITY=1;; +*) AM_DEFAULT_VERBOSITY=0;; +esac +AM_BACKSLASH='\' + + +cxxset=${CXXFLAGS+set} +ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu +if test -z "$CXX"; then + if test -n "$CCC"; then + CXX=$CCC + else + if test -n "$ac_tool_prefix"; then + for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_CXX+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CXX"; then + ac_cv_prog_CXX="$CXX" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CXX="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CXX=$ac_cv_prog_CXX +if test -n "$CXX"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXX" >&5 +$as_echo "$CXX" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$CXX" && break + done +fi +if test -z "$CXX"; then + ac_ct_CXX=$CXX + for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_ac_ct_CXX+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CXX"; then + ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_CXX="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CXX=$ac_cv_prog_ac_ct_CXX +if test -n "$ac_ct_CXX"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CXX" >&5 +$as_echo "$ac_ct_CXX" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_CXX" && break +done + + if test "x$ac_ct_CXX" = x; then + CXX="g++" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CXX=$ac_ct_CXX + fi +fi + + fi +fi +# Provide some information about the compiler. +$as_echo "$as_me:${as_lineno-$LINENO}: checking for C++ compiler version" >&5 +set X $ac_compile +ac_compiler=$2 +for ac_option in --version -v -V -qversion; do + { { ac_try="$ac_compiler $ac_option >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compiler $ac_option >&5") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + sed '10a\ +... rest of stderr output deleted ... + 10q' conftest.err >conftest.er1 + cat conftest.er1 >&5 + fi + rm -f conftest.er1 conftest.err + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } +done + +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" +# Try to create an executable without -o first, disregard a.out. +# It will help us diagnose broken compilers, and finding out an intuition +# of exeext. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C++ compiler works" >&5 +$as_echo_n "checking whether the C++ compiler works... " >&6; } +ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` + +# The possible output files: +ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" + +ac_rmfiles= +for ac_file in $ac_files +do + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; + * ) ac_rmfiles="$ac_rmfiles $ac_file";; + esac +done +rm -f $ac_rmfiles + +if { { ac_try="$ac_link_default" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link_default") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. +# So ignore a value of `no', otherwise this would lead to `EXEEXT = no' +# in a Makefile. We should not override ac_cv_exeext if it was cached, +# so that the user can short-circuit this test for compilers unknown to +# Autoconf. +for ac_file in $ac_files '' +do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) + ;; + [ab].out ) + # We found the default executable, but exeext='' is most + # certainly right. + break;; + *.* ) + if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; + then :; else + ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + fi + # We set ac_cv_exeext here because the later test for it is not + # safe: cross compilers may not add the suffix if given an `-o' + # argument, so we may need to know it at that point already. + # Even if this section looks crufty: it has the advantage of + # actually working. + break;; + * ) + break;; + esac +done +test "$ac_cv_exeext" = no && ac_cv_exeext= + +else + ac_file='' +fi +if test -z "$ac_file"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +$as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +{ as_fn_set_status 77 +as_fn_error "C++ compiler cannot create executables +See \`config.log' for more details." "$LINENO" 5; }; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C++ compiler default output file name" >&5 +$as_echo_n "checking for C++ compiler default output file name... " >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 +$as_echo "$ac_file" >&6; } +ac_exeext=$ac_cv_exeext + +rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out +ac_clean_files=$ac_clean_files_save +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 +$as_echo_n "checking for suffix of executables... " >&6; } +if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + # If both `conftest.exe' and `conftest' are `present' (well, observable) +# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will +# work properly (i.e., refer to `conftest.exe'), while it won't with +# `rm'. +for ac_file in conftest.exe conftest conftest.*; do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; + *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + break;; + * ) break;; + esac +done +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error "cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details." "$LINENO" 5; } +fi +rm -f conftest conftest$ac_cv_exeext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 +$as_echo "$ac_cv_exeext" >&6; } + +rm -f conftest.$ac_ext +EXEEXT=$ac_cv_exeext +ac_exeext=$EXEEXT +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +FILE *f = fopen ("conftest.out", "w"); + return ferror (f) || fclose (f) != 0; + + ; + return 0; +} +_ACEOF +ac_clean_files="$ac_clean_files conftest.out" +# Check that the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 +$as_echo_n "checking whether we are cross compiling... " >&6; } +if test "$cross_compiling" != yes; then + { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + if { ac_try='./conftest$ac_cv_exeext' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then + cross_compiling=no + else + if test "$cross_compiling" = maybe; then + cross_compiling=yes + else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error "cannot run C++ compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details." "$LINENO" 5; } + fi + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 +$as_echo "$cross_compiling" >&6; } + +rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out +ac_clean_files=$ac_clean_files_save +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 +$as_echo_n "checking for suffix of object files... " >&6; } +if test "${ac_cv_objext+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.o conftest.obj +if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + for ac_file in conftest.o conftest.obj conftest.*; do + test -f "$ac_file" || continue; + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; + *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` + break;; + esac +done +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error "cannot compute suffix of object files: cannot compile +See \`config.log' for more details." "$LINENO" 5; } +fi +rm -f conftest.$ac_cv_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 +$as_echo "$ac_cv_objext" >&6; } +OBJEXT=$ac_cv_objext +ac_objext=$OBJEXT +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C++ compiler" >&5 +$as_echo_n "checking whether we are using the GNU C++ compiler... " >&6; } +if test "${ac_cv_cxx_compiler_gnu+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + ac_compiler_gnu=yes +else + ac_compiler_gnu=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_cxx_compiler_gnu=$ac_compiler_gnu + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cxx_compiler_gnu" >&5 +$as_echo "$ac_cv_cxx_compiler_gnu" >&6; } +if test $ac_compiler_gnu = yes; then + GXX=yes +else + GXX= +fi +ac_test_CXXFLAGS=${CXXFLAGS+set} +ac_save_CXXFLAGS=$CXXFLAGS +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX accepts -g" >&5 +$as_echo_n "checking whether $CXX accepts -g... " >&6; } +if test "${ac_cv_prog_cxx_g+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + ac_save_cxx_werror_flag=$ac_cxx_werror_flag + ac_cxx_werror_flag=yes + ac_cv_prog_cxx_g=no + CXXFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + ac_cv_prog_cxx_g=yes +else + CXXFLAGS="" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + +else + ac_cxx_werror_flag=$ac_save_cxx_werror_flag + CXXFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + ac_cv_prog_cxx_g=yes +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_cxx_werror_flag=$ac_save_cxx_werror_flag +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_g" >&5 +$as_echo "$ac_cv_prog_cxx_g" >&6; } +if test "$ac_test_CXXFLAGS" = set; then + CXXFLAGS=$ac_save_CXXFLAGS +elif test $ac_cv_prog_cxx_g = yes; then + if test "$GXX" = yes; then + CXXFLAGS="-g -O2" + else + CXXFLAGS="-g" + fi +else + if test "$GXX" = yes; then + CXXFLAGS="-O2" + else + CXXFLAGS= + fi +fi +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +DEPDIR="${am__leading_dot}deps" + +ac_config_commands="$ac_config_commands depfiles" + + +am_make=${MAKE-make} +cat > confinc << 'END' +am__doit: + @echo this is the am__doit target +.PHONY: am__doit +END +# If we don't find an include directive, just comment out the code. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for style of include used by $am_make" >&5 +$as_echo_n "checking for style of include used by $am_make... " >&6; } +am__include="#" +am__quote= +_am_result=none +# First try GNU make style include. +echo "include confinc" > confmf +# Ignore all kinds of additional output from `make'. +case `$am_make -s -f confmf 2> /dev/null` in #( +*the\ am__doit\ target*) + am__include=include + am__quote= + _am_result=GNU + ;; +esac +# Now try BSD make style include. +if test "$am__include" = "#"; then + echo '.include "confinc"' > confmf + case `$am_make -s -f confmf 2> /dev/null` in #( + *the\ am__doit\ target*) + am__include=.include + am__quote="\"" + _am_result=BSD + ;; + esac +fi + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $_am_result" >&5 +$as_echo "$_am_result" >&6; } +rm -f confinc confmf + +# Check whether --enable-dependency-tracking was given. +if test "${enable_dependency_tracking+set}" = set; then : + enableval=$enable_dependency_tracking; +fi + +if test "x$enable_dependency_tracking" != xno; then + am_depcomp="$ac_aux_dir/depcomp" + AMDEPBACKSLASH='\' +fi + if test "x$enable_dependency_tracking" != xno; then + AMDEP_TRUE= + AMDEP_FALSE='#' +else + AMDEP_TRUE='#' + AMDEP_FALSE= +fi + + + +depcc="$CXX" am_compiler_list= + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 +$as_echo_n "checking dependency style of $depcc... " >&6; } +if test "${am_cv_CXX_dependencies_compiler_type+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then + # We make a subdir and do the tests there. Otherwise we can end up + # making bogus files that we don't know about and never remove. For + # instance it was reported that on HP-UX the gcc test will end up + # making a dummy file named `D' -- because `-MD' means `put the output + # in D'. + mkdir conftest.dir + # Copy depcomp to subdir because otherwise we won't find it if we're + # using a relative directory. + cp "$am_depcomp" conftest.dir + cd conftest.dir + # We will build objects and dependencies in a subdirectory because + # it helps to detect inapplicable dependency modes. For instance + # both Tru64's cc and ICC support -MD to output dependencies as a + # side effect of compilation, but ICC will put the dependencies in + # the current directory while Tru64 will put them in the object + # directory. + mkdir sub + + am_cv_CXX_dependencies_compiler_type=none + if test "$am_compiler_list" = ""; then + am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` + fi + am__universal=false + case " $depcc " in #( + *\ -arch\ *\ -arch\ *) am__universal=true ;; + esac + + for depmode in $am_compiler_list; do + # Setup a source with many dependencies, because some compilers + # like to wrap large dependency lists on column 80 (with \), and + # we should not choose a depcomp mode which is confused by this. + # + # We need to recreate these files for each test, as the compiler may + # overwrite some of them when testing with obscure command lines. + # This happens at least with the AIX C compiler. + : > sub/conftest.c + for i in 1 2 3 4 5 6; do + echo '#include "conftst'$i'.h"' >> sub/conftest.c + # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with + # Solaris 8's {/usr,}/bin/sh. + touch sub/conftst$i.h + done + echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf + + # We check with `-c' and `-o' for the sake of the "dashmstdout" + # mode. It turns out that the SunPro C++ compiler does not properly + # handle `-M -o', and we need to detect this. Also, some Intel + # versions had trouble with output in subdirs + am__obj=sub/conftest.${OBJEXT-o} + am__minus_obj="-o $am__obj" + case $depmode in + gcc) + # This depmode causes a compiler race in universal mode. + test "$am__universal" = false || continue + ;; + nosideeffect) + # after this tag, mechanisms are not by side-effect, so they'll + # only be used when explicitly requested + if test "x$enable_dependency_tracking" = xyes; then + continue + else + break + fi + ;; + msvisualcpp | msvcmsys) + # This compiler won't grok `-c -o', but also, the minuso test has + # not run yet. These depmodes are late enough in the game, and + # so weak that their functioning should not be impacted. + am__obj=conftest.${OBJEXT-o} + am__minus_obj= + ;; + none) break ;; + esac + if depmode=$depmode \ + source=sub/conftest.c object=$am__obj \ + depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ + $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ + >/dev/null 2>conftest.err && + grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && + grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && + grep $am__obj sub/conftest.Po > /dev/null 2>&1 && + ${MAKE-make} -s -f confmf > /dev/null 2>&1; then + # icc doesn't choke on unknown options, it will just issue warnings + # or remarks (even with -Werror). So we grep stderr for any message + # that says an option was ignored or not supported. + # When given -MP, icc 7.0 and 7.1 complain thusly: + # icc: Command line warning: ignoring option '-M'; no argument required + # The diagnosis changed in icc 8.0: + # icc: Command line remark: option '-MP' not supported + if (grep 'ignoring option' conftest.err || + grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else + am_cv_CXX_dependencies_compiler_type=$depmode + break + fi + fi + done + + cd .. + rm -rf conftest.dir +else + am_cv_CXX_dependencies_compiler_type=none +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CXX_dependencies_compiler_type" >&5 +$as_echo "$am_cv_CXX_dependencies_compiler_type" >&6; } +CXXDEPMODE=depmode=$am_cv_CXX_dependencies_compiler_type + + if + test "x$enable_dependency_tracking" != xno \ + && test "$am_cv_CXX_dependencies_compiler_type" = gcc3; then + am__fastdepCXX_TRUE= + am__fastdepCXX_FALSE='#' +else + am__fastdepCXX_TRUE='#' + am__fastdepCXX_FALSE= +fi + + + +if test "$cxxset" != set; then +# don't use the default -O2 -g because -g bloats the C++ binaries too much + CXXFLAGS="-O2" +fi + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable maintainer-specific portions of Makefiles" >&5 +$as_echo_n "checking whether to enable maintainer-specific portions of Makefiles... " >&6; } + # Check whether --enable-maintainer-mode was given. +if test "${enable_maintainer_mode+set}" = set; then : + enableval=$enable_maintainer_mode; USE_MAINTAINER_MODE=$enableval +else + USE_MAINTAINER_MODE=no +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $USE_MAINTAINER_MODE" >&5 +$as_echo "$USE_MAINTAINER_MODE" >&6; } + if test $USE_MAINTAINER_MODE = yes; then + MAINTAINER_MODE_TRUE= + MAINTAINER_MODE_FALSE='#' +else + MAINTAINER_MODE_TRUE='#' + MAINTAINER_MODE_FALSE= +fi + + MAINT=$MAINTAINER_MODE_TRUE + + +case `pwd` in + *\ * | *\ *) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&5 +$as_echo "$as_me: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&2;} ;; +esac + + + +macro_version='2.2.6b' +macro_revision='1.3017' + + + + + + + + + + + + + +ltmain="$ac_aux_dir/ltmain.sh" + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. +set dummy ${ac_tool_prefix}gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_CC+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CC="${ac_tool_prefix}gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_ac_ct_CC+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_CC="gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +else + CC="$ac_cv_prog_CC" +fi + +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. +set dummy ${ac_tool_prefix}cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_CC+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CC="${ac_tool_prefix}cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + fi +fi +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_CC+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + ac_prog_rejected=no +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# != 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" + fi +fi +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + for ac_prog in cl.exe + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_CC+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CC="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$CC" && break + done +fi +if test -z "$CC"; then + ac_ct_CC=$CC + for ac_prog in cl.exe +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_ac_ct_CC+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_CC="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_CC" && break +done + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +fi + +fi + + +test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error "no acceptable C compiler found in \$PATH +See \`config.log' for more details." "$LINENO" 5; } + +# Provide some information about the compiler. +$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 +set X $ac_compile +ac_compiler=$2 +for ac_option in --version -v -V -qversion; do + { { ac_try="$ac_compiler $ac_option >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compiler $ac_option >&5") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + sed '10a\ +... rest of stderr output deleted ... + 10q' conftest.err >conftest.er1 + cat conftest.er1 >&5 + fi + rm -f conftest.er1 conftest.err + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } +done + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 +$as_echo_n "checking whether we are using the GNU C compiler... " >&6; } +if test "${ac_cv_c_compiler_gnu+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_compiler_gnu=yes +else + ac_compiler_gnu=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_c_compiler_gnu=$ac_compiler_gnu + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 +$as_echo "$ac_cv_c_compiler_gnu" >&6; } +if test $ac_compiler_gnu = yes; then + GCC=yes +else + GCC= +fi +ac_test_CFLAGS=${CFLAGS+set} +ac_save_CFLAGS=$CFLAGS +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 +$as_echo_n "checking whether $CC accepts -g... " >&6; } +if test "${ac_cv_prog_cc_g+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + ac_save_c_werror_flag=$ac_c_werror_flag + ac_c_werror_flag=yes + ac_cv_prog_cc_g=no + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +else + CFLAGS="" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +else + ac_c_werror_flag=$ac_save_c_werror_flag + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_c_werror_flag=$ac_save_c_werror_flag +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 +$as_echo "$ac_cv_prog_cc_g" >&6; } +if test "$ac_test_CFLAGS" = set; then + CFLAGS=$ac_save_CFLAGS +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 +$as_echo_n "checking for $CC option to accept ISO C89... " >&6; } +if test "${ac_cv_prog_cc_c89+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_prog_cc_c89=no +ac_save_CC=$CC +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#include +#include +/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ +struct buf { int x; }; +FILE * (*rcsopen) (struct buf *, struct stat *, int); +static char *e (p, i) + char **p; + int i; +{ + return p[i]; +} +static char *f (char * (*g) (char **, int), char **p, ...) +{ + char *s; + va_list v; + va_start (v,p); + s = g (p, va_arg (v,int)); + va_end (v); + return s; +} + +/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has + function prototypes and stuff, but not '\xHH' hex character constants. + These don't provoke an error unfortunately, instead are silently treated + as 'x'. The following induces an error, until -std is added to get + proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an + array size at least. It's necessary to write '\x00'==0 to get something + that's true only with -std. */ +int osf4_cc_array ['\x00' == 0 ? 1 : -1]; + +/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters + inside strings and character constants. */ +#define FOO(x) 'x' +int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; + +int test (int i, double x); +struct s1 {int (*f) (int a);}; +struct s2 {int (*f) (double a);}; +int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); +int argc; +char **argv; +int +main () +{ +return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; + ; + return 0; +} +_ACEOF +for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ + -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" +do + CC="$ac_save_CC $ac_arg" + if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_c89=$ac_arg +fi +rm -f core conftest.err conftest.$ac_objext + test "x$ac_cv_prog_cc_c89" != "xno" && break +done +rm -f conftest.$ac_ext +CC=$ac_save_CC + +fi +# AC_CACHE_VAL +case "x$ac_cv_prog_cc_c89" in + x) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 +$as_echo "none needed" >&6; } ;; + xno) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 +$as_echo "unsupported" >&6; } ;; + *) + CC="$CC $ac_cv_prog_cc_c89" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 +$as_echo "$ac_cv_prog_cc_c89" >&6; } ;; +esac +if test "x$ac_cv_prog_cc_c89" != xno; then : + +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +depcc="$CC" am_compiler_list= + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 +$as_echo_n "checking dependency style of $depcc... " >&6; } +if test "${am_cv_CC_dependencies_compiler_type+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then + # We make a subdir and do the tests there. Otherwise we can end up + # making bogus files that we don't know about and never remove. For + # instance it was reported that on HP-UX the gcc test will end up + # making a dummy file named `D' -- because `-MD' means `put the output + # in D'. + mkdir conftest.dir + # Copy depcomp to subdir because otherwise we won't find it if we're + # using a relative directory. + cp "$am_depcomp" conftest.dir + cd conftest.dir + # We will build objects and dependencies in a subdirectory because + # it helps to detect inapplicable dependency modes. For instance + # both Tru64's cc and ICC support -MD to output dependencies as a + # side effect of compilation, but ICC will put the dependencies in + # the current directory while Tru64 will put them in the object + # directory. + mkdir sub + + am_cv_CC_dependencies_compiler_type=none + if test "$am_compiler_list" = ""; then + am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` + fi + am__universal=false + case " $depcc " in #( + *\ -arch\ *\ -arch\ *) am__universal=true ;; + esac + + for depmode in $am_compiler_list; do + # Setup a source with many dependencies, because some compilers + # like to wrap large dependency lists on column 80 (with \), and + # we should not choose a depcomp mode which is confused by this. + # + # We need to recreate these files for each test, as the compiler may + # overwrite some of them when testing with obscure command lines. + # This happens at least with the AIX C compiler. + : > sub/conftest.c + for i in 1 2 3 4 5 6; do + echo '#include "conftst'$i'.h"' >> sub/conftest.c + # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with + # Solaris 8's {/usr,}/bin/sh. + touch sub/conftst$i.h + done + echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf + + # We check with `-c' and `-o' for the sake of the "dashmstdout" + # mode. It turns out that the SunPro C++ compiler does not properly + # handle `-M -o', and we need to detect this. Also, some Intel + # versions had trouble with output in subdirs + am__obj=sub/conftest.${OBJEXT-o} + am__minus_obj="-o $am__obj" + case $depmode in + gcc) + # This depmode causes a compiler race in universal mode. + test "$am__universal" = false || continue + ;; + nosideeffect) + # after this tag, mechanisms are not by side-effect, so they'll + # only be used when explicitly requested + if test "x$enable_dependency_tracking" = xyes; then + continue + else + break + fi + ;; + msvisualcpp | msvcmsys) + # This compiler won't grok `-c -o', but also, the minuso test has + # not run yet. These depmodes are late enough in the game, and + # so weak that their functioning should not be impacted. + am__obj=conftest.${OBJEXT-o} + am__minus_obj= + ;; + none) break ;; + esac + if depmode=$depmode \ + source=sub/conftest.c object=$am__obj \ + depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ + $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ + >/dev/null 2>conftest.err && + grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && + grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && + grep $am__obj sub/conftest.Po > /dev/null 2>&1 && + ${MAKE-make} -s -f confmf > /dev/null 2>&1; then + # icc doesn't choke on unknown options, it will just issue warnings + # or remarks (even with -Werror). So we grep stderr for any message + # that says an option was ignored or not supported. + # When given -MP, icc 7.0 and 7.1 complain thusly: + # icc: Command line warning: ignoring option '-M'; no argument required + # The diagnosis changed in icc 8.0: + # icc: Command line remark: option '-MP' not supported + if (grep 'ignoring option' conftest.err || + grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else + am_cv_CC_dependencies_compiler_type=$depmode + break + fi + fi + done + + cd .. + rm -rf conftest.dir +else + am_cv_CC_dependencies_compiler_type=none +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5 +$as_echo "$am_cv_CC_dependencies_compiler_type" >&6; } +CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type + + if + test "x$enable_dependency_tracking" != xno \ + && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then + am__fastdepCC_TRUE= + am__fastdepCC_FALSE='#' +else + am__fastdepCC_TRUE='#' + am__fastdepCC_FALSE= +fi + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output" >&5 +$as_echo_n "checking for a sed that does not truncate output... " >&6; } +if test "${ac_cv_path_SED+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + ac_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ + for ac_i in 1 2 3 4 5 6 7; do + ac_script="$ac_script$as_nl$ac_script" + done + echo "$ac_script" 2>/dev/null | sed 99q >conftest.sed + { ac_script=; unset ac_script;} + if test -z "$SED"; then + ac_path_SED_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in sed gsed; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_SED="$as_dir/$ac_prog$ac_exec_ext" + { test -f "$ac_path_SED" && $as_test_x "$ac_path_SED"; } || continue +# Check for GNU ac_path_SED and select it if it is found. + # Check for GNU $ac_path_SED +case `"$ac_path_SED" --version 2>&1` in +*GNU*) + ac_cv_path_SED="$ac_path_SED" ac_path_SED_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo '' >> "conftest.nl" + "$ac_path_SED" -f conftest.sed < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_SED_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_SED="$ac_path_SED" + ac_path_SED_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_SED_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_SED"; then + as_fn_error "no acceptable sed could be found in \$PATH" "$LINENO" 5 + fi +else + ac_cv_path_SED=$SED +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_SED" >&5 +$as_echo "$ac_cv_path_SED" >&6; } + SED="$ac_cv_path_SED" + rm -f conftest.sed + +test -z "$SED" && SED=sed +Xsed="$SED -e 1s/^X//" + + + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 +$as_echo_n "checking for grep that handles long lines and -e... " >&6; } +if test "${ac_cv_path_GREP+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$GREP"; then + ac_path_GREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in grep ggrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" + { test -f "$ac_path_GREP" && $as_test_x "$ac_path_GREP"; } || continue +# Check for GNU ac_path_GREP and select it if it is found. + # Check for GNU $ac_path_GREP +case `"$ac_path_GREP" --version 2>&1` in +*GNU*) + ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'GREP' >> "conftest.nl" + "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_GREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_GREP="$ac_path_GREP" + ac_path_GREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_GREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_GREP"; then + as_fn_error "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_GREP=$GREP +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 +$as_echo "$ac_cv_path_GREP" >&6; } + GREP="$ac_cv_path_GREP" + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 +$as_echo_n "checking for egrep... " >&6; } +if test "${ac_cv_path_EGREP+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 + then ac_cv_path_EGREP="$GREP -E" + else + if test -z "$EGREP"; then + ac_path_EGREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in egrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" + { test -f "$ac_path_EGREP" && $as_test_x "$ac_path_EGREP"; } || continue +# Check for GNU ac_path_EGREP and select it if it is found. + # Check for GNU $ac_path_EGREP +case `"$ac_path_EGREP" --version 2>&1` in +*GNU*) + ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'EGREP' >> "conftest.nl" + "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_EGREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_EGREP="$ac_path_EGREP" + ac_path_EGREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_EGREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_EGREP"; then + as_fn_error "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_EGREP=$EGREP +fi + + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 +$as_echo "$ac_cv_path_EGREP" >&6; } + EGREP="$ac_cv_path_EGREP" + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for fgrep" >&5 +$as_echo_n "checking for fgrep... " >&6; } +if test "${ac_cv_path_FGREP+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if echo 'ab*c' | $GREP -F 'ab*c' >/dev/null 2>&1 + then ac_cv_path_FGREP="$GREP -F" + else + if test -z "$FGREP"; then + ac_path_FGREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in fgrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_FGREP="$as_dir/$ac_prog$ac_exec_ext" + { test -f "$ac_path_FGREP" && $as_test_x "$ac_path_FGREP"; } || continue +# Check for GNU ac_path_FGREP and select it if it is found. + # Check for GNU $ac_path_FGREP +case `"$ac_path_FGREP" --version 2>&1` in +*GNU*) + ac_cv_path_FGREP="$ac_path_FGREP" ac_path_FGREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'FGREP' >> "conftest.nl" + "$ac_path_FGREP" FGREP < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_FGREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_FGREP="$ac_path_FGREP" + ac_path_FGREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_FGREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_FGREP"; then + as_fn_error "no acceptable fgrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_FGREP=$FGREP +fi + + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_FGREP" >&5 +$as_echo "$ac_cv_path_FGREP" >&6; } + FGREP="$ac_cv_path_FGREP" + + +test -z "$GREP" && GREP=grep + + + + + + + + + + + + + + + + + + + +# Check whether --with-gnu-ld was given. +if test "${with_gnu_ld+set}" = set; then : + withval=$with_gnu_ld; test "$withval" = no || with_gnu_ld=yes +else + with_gnu_ld=no +fi + +ac_prog=ld +if test "$GCC" = yes; then + # Check if gcc -print-prog-name=ld gives a path. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5 +$as_echo_n "checking for ld used by $CC... " >&6; } + case $host in + *-*-mingw*) + # gcc leaves a trailing carriage return which upsets mingw + ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; + *) + ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; + esac + case $ac_prog in + # Accept absolute paths. + [\\/]* | ?:[\\/]*) + re_direlt='/[^/][^/]*/\.\./' + # Canonicalize the pathname of ld + ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` + while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do + ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` + done + test -z "$LD" && LD="$ac_prog" + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test "$with_gnu_ld" = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5 +$as_echo_n "checking for GNU ld... " >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5 +$as_echo_n "checking for non-GNU ld... " >&6; } +fi +if test "${lt_cv_path_LD+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$LD"; then + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then + lt_cv_path_LD="$ac_dir/$ac_prog" + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some variants of GNU ld only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + case `"$lt_cv_path_LD" -v 2>&1 &5 +$as_echo "$LD" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +test -z "$LD" && as_fn_error "no acceptable ld found in \$PATH" "$LINENO" 5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5 +$as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; } +if test "${lt_cv_prog_gnu_ld+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + # I'd rather use --version here, but apparently some GNU lds only accept -v. +case `$LD -v 2>&1 &5 +$as_echo "$lt_cv_prog_gnu_ld" >&6; } +with_gnu_ld=$lt_cv_prog_gnu_ld + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for BSD- or MS-compatible name lister (nm)" >&5 +$as_echo_n "checking for BSD- or MS-compatible name lister (nm)... " >&6; } +if test "${lt_cv_path_NM+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$NM"; then + # Let the user override the test. + lt_cv_path_NM="$NM" +else + lt_nm_to_check="${ac_tool_prefix}nm" + if test -n "$ac_tool_prefix" && test "$build" = "$host"; then + lt_nm_to_check="$lt_nm_to_check nm" + fi + for lt_tmp_nm in $lt_nm_to_check; do + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + tmp_nm="$ac_dir/$lt_tmp_nm" + if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then + # Check to see if the nm accepts a BSD-compat flag. + # Adding the `sed 1q' prevents false positives on HP-UX, which says: + # nm: unknown option "B" ignored + # Tru64's nm complains that /dev/null is an invalid object file + case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in + */dev/null* | *'Invalid file or object type'*) + lt_cv_path_NM="$tmp_nm -B" + break + ;; + *) + case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in + */dev/null*) + lt_cv_path_NM="$tmp_nm -p" + break + ;; + *) + lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but + continue # so that we can try to find one that supports BSD flags + ;; + esac + ;; + esac + fi + done + IFS="$lt_save_ifs" + done + : ${lt_cv_path_NM=no} +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_NM" >&5 +$as_echo "$lt_cv_path_NM" >&6; } +if test "$lt_cv_path_NM" != "no"; then + NM="$lt_cv_path_NM" +else + # Didn't find any BSD compatible name lister, look for dumpbin. + if test -n "$ac_tool_prefix"; then + for ac_prog in "dumpbin -symbols" "link -dump -symbols" + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_DUMPBIN+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$DUMPBIN"; then + ac_cv_prog_DUMPBIN="$DUMPBIN" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_DUMPBIN="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +DUMPBIN=$ac_cv_prog_DUMPBIN +if test -n "$DUMPBIN"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DUMPBIN" >&5 +$as_echo "$DUMPBIN" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$DUMPBIN" && break + done +fi +if test -z "$DUMPBIN"; then + ac_ct_DUMPBIN=$DUMPBIN + for ac_prog in "dumpbin -symbols" "link -dump -symbols" +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_ac_ct_DUMPBIN+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_DUMPBIN"; then + ac_cv_prog_ac_ct_DUMPBIN="$ac_ct_DUMPBIN" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_DUMPBIN="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_DUMPBIN=$ac_cv_prog_ac_ct_DUMPBIN +if test -n "$ac_ct_DUMPBIN"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DUMPBIN" >&5 +$as_echo "$ac_ct_DUMPBIN" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_DUMPBIN" && break +done + + if test "x$ac_ct_DUMPBIN" = x; then + DUMPBIN=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + DUMPBIN=$ac_ct_DUMPBIN + fi +fi + + + if test "$DUMPBIN" != ":"; then + NM="$DUMPBIN" + fi +fi +test -z "$NM" && NM=nm + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking the name lister ($NM) interface" >&5 +$as_echo_n "checking the name lister ($NM) interface... " >&6; } +if test "${lt_cv_nm_interface+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_nm_interface="BSD nm" + echo "int some_variable = 0;" > conftest.$ac_ext + (eval echo "\"\$as_me:5083: $ac_compile\"" >&5) + (eval "$ac_compile" 2>conftest.err) + cat conftest.err >&5 + (eval echo "\"\$as_me:5086: $NM \\\"conftest.$ac_objext\\\"\"" >&5) + (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) + cat conftest.err >&5 + (eval echo "\"\$as_me:5089: output\"" >&5) + cat conftest.out >&5 + if $GREP 'External.*some_variable' conftest.out > /dev/null; then + lt_cv_nm_interface="MS dumpbin" + fi + rm -f conftest* +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_nm_interface" >&5 +$as_echo "$lt_cv_nm_interface" >&6; } + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5 +$as_echo_n "checking whether ln -s works... " >&6; } +LN_S=$as_ln_s +if test "$LN_S" = "ln -s"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, using $LN_S" >&5 +$as_echo "no, using $LN_S" >&6; } +fi + +# find the maximum length of command line arguments +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking the maximum length of command line arguments" >&5 +$as_echo_n "checking the maximum length of command line arguments... " >&6; } +if test "${lt_cv_sys_max_cmd_len+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + i=0 + teststring="ABCD" + + case $build_os in + msdosdjgpp*) + # On DJGPP, this test can blow up pretty badly due to problems in libc + # (any single argument exceeding 2000 bytes causes a buffer overrun + # during glob expansion). Even if it were fixed, the result of this + # check would be larger than it should be. + lt_cv_sys_max_cmd_len=12288; # 12K is about right + ;; + + gnu*) + # Under GNU Hurd, this test is not required because there is + # no limit to the length of command line arguments. + # Libtool will interpret -1 as no limit whatsoever + lt_cv_sys_max_cmd_len=-1; + ;; + + cygwin* | mingw* | cegcc*) + # On Win9x/ME, this test blows up -- it succeeds, but takes + # about 5 minutes as the teststring grows exponentially. + # Worse, since 9x/ME are not pre-emptively multitasking, + # you end up with a "frozen" computer, even though with patience + # the test eventually succeeds (with a max line length of 256k). + # Instead, let's just punt: use the minimum linelength reported by + # all of the supported platforms: 8192 (on NT/2K/XP). + lt_cv_sys_max_cmd_len=8192; + ;; + + amigaos*) + # On AmigaOS with pdksh, this test takes hours, literally. + # So we just punt and use a minimum line length of 8192. + lt_cv_sys_max_cmd_len=8192; + ;; + + netbsd* | freebsd* | openbsd* | darwin* | dragonfly*) + # This has been around since 386BSD, at least. Likely further. + if test -x /sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` + elif test -x /usr/sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` + else + lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs + fi + # And add a safety zone + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + ;; + + interix*) + # We know the value 262144 and hardcode it with a safety zone (like BSD) + lt_cv_sys_max_cmd_len=196608 + ;; + + osf*) + # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure + # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not + # nice to cause kernel panics so lets avoid the loop below. + # First set a reasonable default. + lt_cv_sys_max_cmd_len=16384 + # + if test -x /sbin/sysconfig; then + case `/sbin/sysconfig -q proc exec_disable_arg_limit` in + *1*) lt_cv_sys_max_cmd_len=-1 ;; + esac + fi + ;; + sco3.2v5*) + lt_cv_sys_max_cmd_len=102400 + ;; + sysv5* | sco5v6* | sysv4.2uw2*) + kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` + if test -n "$kargmax"; then + lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[ ]//'` + else + lt_cv_sys_max_cmd_len=32768 + fi + ;; + *) + lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` + if test -n "$lt_cv_sys_max_cmd_len"; then + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + else + # Make teststring a little bigger before we do anything with it. + # a 1K string should be a reasonable start. + for i in 1 2 3 4 5 6 7 8 ; do + teststring=$teststring$teststring + done + SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} + # If test is not a shell built-in, we'll probably end up computing a + # maximum length that is only half of the actual maximum length, but + # we can't tell. + while { test "X"`$SHELL $0 --fallback-echo "X$teststring$teststring" 2>/dev/null` \ + = "XX$teststring$teststring"; } >/dev/null 2>&1 && + test $i != 17 # 1/2 MB should be enough + do + i=`expr $i + 1` + teststring=$teststring$teststring + done + # Only check the string length outside the loop. + lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1` + teststring= + # Add a significant safety factor because C++ compilers can tack on + # massive amounts of additional arguments before passing them to the + # linker. It appears as though 1/2 is a usable value. + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` + fi + ;; + esac + +fi + +if test -n $lt_cv_sys_max_cmd_len ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sys_max_cmd_len" >&5 +$as_echo "$lt_cv_sys_max_cmd_len" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none" >&5 +$as_echo "none" >&6; } +fi +max_cmd_len=$lt_cv_sys_max_cmd_len + + + + + + +: ${CP="cp -f"} +: ${MV="mv -f"} +: ${RM="rm -f"} + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the shell understands some XSI constructs" >&5 +$as_echo_n "checking whether the shell understands some XSI constructs... " >&6; } +# Try some XSI features +xsi_shell=no +( _lt_dummy="a/b/c" + test "${_lt_dummy##*/},${_lt_dummy%/*},"${_lt_dummy%"$_lt_dummy"}, \ + = c,a/b,, \ + && eval 'test $(( 1 + 1 )) -eq 2 \ + && test "${#_lt_dummy}" -eq 5' ) >/dev/null 2>&1 \ + && xsi_shell=yes +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $xsi_shell" >&5 +$as_echo "$xsi_shell" >&6; } + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the shell understands \"+=\"" >&5 +$as_echo_n "checking whether the shell understands \"+=\"... " >&6; } +lt_shell_append=no +( foo=bar; set foo baz; eval "$1+=\$2" && test "$foo" = barbaz ) \ + >/dev/null 2>&1 \ + && lt_shell_append=yes +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_shell_append" >&5 +$as_echo "$lt_shell_append" >&6; } + + +if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then + lt_unset=unset +else + lt_unset=false +fi + + + + + +# test EBCDIC or ASCII +case `echo X|tr X '\101'` in + A) # ASCII based system + # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr + lt_SP2NL='tr \040 \012' + lt_NL2SP='tr \015\012 \040\040' + ;; + *) # EBCDIC based system + lt_SP2NL='tr \100 \n' + lt_NL2SP='tr \r\n \100\100' + ;; +esac + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $LD option to reload object files" >&5 +$as_echo_n "checking for $LD option to reload object files... " >&6; } +if test "${lt_cv_ld_reload_flag+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_ld_reload_flag='-r' +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_reload_flag" >&5 +$as_echo "$lt_cv_ld_reload_flag" >&6; } +reload_flag=$lt_cv_ld_reload_flag +case $reload_flag in +"" | " "*) ;; +*) reload_flag=" $reload_flag" ;; +esac +reload_cmds='$LD$reload_flag -o $output$reload_objs' +case $host_os in + darwin*) + if test "$GCC" = yes; then + reload_cmds='$LTCC $LTCFLAGS -nostdlib ${wl}-r -o $output$reload_objs' + else + reload_cmds='$LD$reload_flag -o $output$reload_objs' + fi + ;; +esac + + + + + + + + + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}objdump", so it can be a program name with args. +set dummy ${ac_tool_prefix}objdump; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_OBJDUMP+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$OBJDUMP"; then + ac_cv_prog_OBJDUMP="$OBJDUMP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_OBJDUMP="${ac_tool_prefix}objdump" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +OBJDUMP=$ac_cv_prog_OBJDUMP +if test -n "$OBJDUMP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OBJDUMP" >&5 +$as_echo "$OBJDUMP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_OBJDUMP"; then + ac_ct_OBJDUMP=$OBJDUMP + # Extract the first word of "objdump", so it can be a program name with args. +set dummy objdump; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_ac_ct_OBJDUMP+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_OBJDUMP"; then + ac_cv_prog_ac_ct_OBJDUMP="$ac_ct_OBJDUMP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_OBJDUMP="objdump" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_OBJDUMP=$ac_cv_prog_ac_ct_OBJDUMP +if test -n "$ac_ct_OBJDUMP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OBJDUMP" >&5 +$as_echo "$ac_ct_OBJDUMP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_OBJDUMP" = x; then + OBJDUMP="false" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + OBJDUMP=$ac_ct_OBJDUMP + fi +else + OBJDUMP="$ac_cv_prog_OBJDUMP" +fi + +test -z "$OBJDUMP" && OBJDUMP=objdump + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to recognize dependent libraries" >&5 +$as_echo_n "checking how to recognize dependent libraries... " >&6; } +if test "${lt_cv_deplibs_check_method+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_file_magic_cmd='$MAGIC_CMD' +lt_cv_file_magic_test_file= +lt_cv_deplibs_check_method='unknown' +# Need to set the preceding variable on all platforms that support +# interlibrary dependencies. +# 'none' -- dependencies not supported. +# `unknown' -- same as none, but documents that we really don't know. +# 'pass_all' -- all dependencies passed with no checks. +# 'test_compile' -- check by making test program. +# 'file_magic [[regex]]' -- check by looking for files in library path +# which responds to the $file_magic_cmd with a given extended regex. +# If you have `file' or equivalent on your system and you're not sure +# whether `pass_all' will *always* work, you probably want this one. + +case $host_os in +aix[4-9]*) + lt_cv_deplibs_check_method=pass_all + ;; + +beos*) + lt_cv_deplibs_check_method=pass_all + ;; + +bsdi[45]*) + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)' + lt_cv_file_magic_cmd='/usr/bin/file -L' + lt_cv_file_magic_test_file=/shlib/libc.so + ;; + +cygwin*) + # func_win32_libid is a shell function defined in ltmain.sh + lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' + lt_cv_file_magic_cmd='func_win32_libid' + ;; + +mingw* | pw32*) + # Base MSYS/MinGW do not provide the 'file' command needed by + # func_win32_libid shell function, so use a weaker test based on 'objdump', + # unless we find 'file', for example because we are cross-compiling. + if ( file / ) >/dev/null 2>&1; then + lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' + lt_cv_file_magic_cmd='func_win32_libid' + else + lt_cv_deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?' + lt_cv_file_magic_cmd='$OBJDUMP -f' + fi + ;; + +cegcc) + # use the weaker test based on 'objdump'. See mingw*. + lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' + lt_cv_file_magic_cmd='$OBJDUMP -f' + ;; + +darwin* | rhapsody*) + lt_cv_deplibs_check_method=pass_all + ;; + +freebsd* | dragonfly*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then + case $host_cpu in + i*86 ) + # Not sure whether the presence of OpenBSD here was a mistake. + # Let's accept both of them until this is cleared up. + lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[3-9]86 (compact )?demand paged shared library' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` + ;; + esac + else + lt_cv_deplibs_check_method=pass_all + fi + ;; + +gnu*) + lt_cv_deplibs_check_method=pass_all + ;; + +hpux10.20* | hpux11*) + lt_cv_file_magic_cmd=/usr/bin/file + case $host_cpu in + ia64*) + lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - IA64' + lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so + ;; + hppa*64*) + lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - PA-RISC [0-9].[0-9]' + lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl + ;; + *) + lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9].[0-9]) shared library' + lt_cv_file_magic_test_file=/usr/lib/libc.sl + ;; + esac + ;; + +interix[3-9]*) + # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|\.a)$' + ;; + +irix5* | irix6* | nonstopux*) + case $LD in + *-32|*"-32 ") libmagic=32-bit;; + *-n32|*"-n32 ") libmagic=N32;; + *-64|*"-64 ") libmagic=64-bit;; + *) libmagic=never-match;; + esac + lt_cv_deplibs_check_method=pass_all + ;; + +# This must be Linux ELF. +linux* | k*bsd*-gnu | kopensolaris*-gnu) + lt_cv_deplibs_check_method=pass_all + ;; + +netbsd* | netbsdelf*-gnu) + if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|_pic\.a)$' + fi + ;; + +newos6*) + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (executable|dynamic lib)' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=/usr/lib/libnls.so + ;; + +*nto* | *qnx*) + lt_cv_deplibs_check_method=pass_all + ;; + +openbsd*) + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|\.so|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' + fi + ;; + +osf3* | osf4* | osf5*) + lt_cv_deplibs_check_method=pass_all + ;; + +rdos*) + lt_cv_deplibs_check_method=pass_all + ;; + +solaris*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv4 | sysv4.3*) + case $host_vendor in + motorola) + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]' + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` + ;; + ncr) + lt_cv_deplibs_check_method=pass_all + ;; + sequent) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )' + ;; + sni) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method="file_magic ELF [0-9][0-9]*-bit [LM]SB dynamic lib" + lt_cv_file_magic_test_file=/lib/libc.so + ;; + siemens) + lt_cv_deplibs_check_method=pass_all + ;; + pc) + lt_cv_deplibs_check_method=pass_all + ;; + esac + ;; + +tpf*) + lt_cv_deplibs_check_method=pass_all + ;; +esac + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_deplibs_check_method" >&5 +$as_echo "$lt_cv_deplibs_check_method" >&6; } +file_magic_cmd=$lt_cv_file_magic_cmd +deplibs_check_method=$lt_cv_deplibs_check_method +test -z "$deplibs_check_method" && deplibs_check_method=unknown + + + + + + + + + + + + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args. +set dummy ${ac_tool_prefix}ar; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_AR+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$AR"; then + ac_cv_prog_AR="$AR" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_AR="${ac_tool_prefix}ar" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +AR=$ac_cv_prog_AR +if test -n "$AR"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5 +$as_echo "$AR" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_AR"; then + ac_ct_AR=$AR + # Extract the first word of "ar", so it can be a program name with args. +set dummy ar; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_ac_ct_AR+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_AR"; then + ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_AR="ar" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_AR=$ac_cv_prog_ac_ct_AR +if test -n "$ac_ct_AR"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5 +$as_echo "$ac_ct_AR" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_AR" = x; then + AR="false" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + AR=$ac_ct_AR + fi +else + AR="$ac_cv_prog_AR" +fi + +test -z "$AR" && AR=ar +test -z "$AR_FLAGS" && AR_FLAGS=cru + + + + + + + + + + + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. +set dummy ${ac_tool_prefix}strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_STRIP+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$STRIP"; then + ac_cv_prog_STRIP="$STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_STRIP="${ac_tool_prefix}strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +STRIP=$ac_cv_prog_STRIP +if test -n "$STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 +$as_echo "$STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_STRIP"; then + ac_ct_STRIP=$STRIP + # Extract the first word of "strip", so it can be a program name with args. +set dummy strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_ac_ct_STRIP+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_STRIP"; then + ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_STRIP="strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP +if test -n "$ac_ct_STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 +$as_echo "$ac_ct_STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_STRIP" = x; then + STRIP=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + STRIP=$ac_ct_STRIP + fi +else + STRIP="$ac_cv_prog_STRIP" +fi + +test -z "$STRIP" && STRIP=: + + + + + + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. +set dummy ${ac_tool_prefix}ranlib; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_RANLIB+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$RANLIB"; then + ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +RANLIB=$ac_cv_prog_RANLIB +if test -n "$RANLIB"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5 +$as_echo "$RANLIB" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_RANLIB"; then + ac_ct_RANLIB=$RANLIB + # Extract the first word of "ranlib", so it can be a program name with args. +set dummy ranlib; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_RANLIB"; then + ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_RANLIB="ranlib" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB +if test -n "$ac_ct_RANLIB"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5 +$as_echo "$ac_ct_RANLIB" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_RANLIB" = x; then + RANLIB=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + RANLIB=$ac_ct_RANLIB + fi +else + RANLIB="$ac_cv_prog_RANLIB" +fi + +test -z "$RANLIB" && RANLIB=: + + + + + + +# Determine commands to create old-style static archives. +old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' +old_postinstall_cmds='chmod 644 $oldlib' +old_postuninstall_cmds= + +if test -n "$RANLIB"; then + case $host_os in + openbsd*) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$oldlib" + ;; + *) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$oldlib" + ;; + esac + old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib" +fi + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC + + +# Check for command to grab the raw symbol name followed by C symbol from nm. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking command to parse $NM output from $compiler object" >&5 +$as_echo_n "checking command to parse $NM output from $compiler object... " >&6; } +if test "${lt_cv_sys_global_symbol_pipe+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + +# These are sane defaults that work on at least a few old systems. +# [They come from Ultrix. What could be older than Ultrix?!! ;)] + +# Character class describing NM global symbol codes. +symcode='[BCDEGRST]' + +# Regexp to match symbols that can be accessed directly from C. +sympat='\([_A-Za-z][_A-Za-z0-9]*\)' + +# Define system-specific variables. +case $host_os in +aix*) + symcode='[BCDT]' + ;; +cygwin* | mingw* | pw32* | cegcc*) + symcode='[ABCDGISTW]' + ;; +hpux*) + if test "$host_cpu" = ia64; then + symcode='[ABCDEGRST]' + fi + ;; +irix* | nonstopux*) + symcode='[BCDEGRST]' + ;; +osf*) + symcode='[BCDEGQRST]' + ;; +solaris*) + symcode='[BDRT]' + ;; +sco3.2v5*) + symcode='[DT]' + ;; +sysv4.2uw2*) + symcode='[DT]' + ;; +sysv5* | sco5v6* | unixware* | OpenUNIX*) + symcode='[ABDT]' + ;; +sysv4) + symcode='[DFNSTU]' + ;; +esac + +# If we're using GNU nm, then use its standard symbol codes. +case `$NM -V 2>&1` in +*GNU* | *'with BFD'*) + symcode='[ABCDGIRSTW]' ;; +esac + +# Transform an extracted symbol line into a proper C declaration. +# Some systems (esp. on ia64) link data and code symbols differently, +# so use this general approach. +lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" + +# Transform an extracted symbol line into symbol name and symbol address +lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\) $/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"\2\", (void *) \&\2},/p'" +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n -e 's/^: \([^ ]*\) $/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([^ ]*\) \(lib[^ ]*\)$/ {\"\2\", (void *) \&\2},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"lib\2\", (void *) \&\2},/p'" + +# Handle CRLF in mingw tool chain +opt_cr= +case $build_os in +mingw*) + opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp + ;; +esac + +# Try without a prefix underscore, then with it. +for ac_symprfx in "" "_"; do + + # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. + symxfrm="\\1 $ac_symprfx\\2 \\2" + + # Write the raw and C identifiers. + if test "$lt_cv_nm_interface" = "MS dumpbin"; then + # Fake it for dumpbin and say T for any non-static function + # and D for any global variable. + # Also find C++ and __fastcall symbols from MSVC++, + # which start with @ or ?. + lt_cv_sys_global_symbol_pipe="$AWK '"\ +" {last_section=section; section=\$ 3};"\ +" /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ +" \$ 0!~/External *\|/{next};"\ +" / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ +" {if(hide[section]) next};"\ +" {f=0}; \$ 0~/\(\).*\|/{f=1}; {printf f ? \"T \" : \"D \"};"\ +" {split(\$ 0, a, /\||\r/); split(a[2], s)};"\ +" s[1]~/^[@?]/{print s[1], s[1]; next};"\ +" s[1]~prfx {split(s[1],t,\"@\"); print t[1], substr(t[1],length(prfx))}"\ +" ' prfx=^$ac_symprfx" + else + lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[ ]\($symcode$symcode*\)[ ][ ]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" + fi + + # Check to see that the pipe works correctly. + pipe_works=no + + rm -f conftest* + cat > conftest.$ac_ext <<_LT_EOF +#ifdef __cplusplus +extern "C" { +#endif +char nm_test_var; +void nm_test_func(void); +void nm_test_func(void){} +#ifdef __cplusplus +} +#endif +int main(){nm_test_var='a';nm_test_func();return(0);} +_LT_EOF + + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + # Now try to grab the symbols. + nlist=conftest.nm + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist\""; } >&5 + (eval $NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && test -s "$nlist"; then + # Try sorting and uniquifying the output. + if sort "$nlist" | uniq > "$nlist"T; then + mv -f "$nlist"T "$nlist" + else + rm -f "$nlist"T + fi + + # Make sure that we snagged all the symbols we need. + if $GREP ' nm_test_var$' "$nlist" >/dev/null; then + if $GREP ' nm_test_func$' "$nlist" >/dev/null; then + cat <<_LT_EOF > conftest.$ac_ext +#ifdef __cplusplus +extern "C" { +#endif + +_LT_EOF + # Now generate the symbol file. + eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext' + + cat <<_LT_EOF >> conftest.$ac_ext + +/* The mapping between symbol names and symbols. */ +const struct { + const char *name; + void *address; +} +lt__PROGRAM__LTX_preloaded_symbols[] = +{ + { "@PROGRAM@", (void *) 0 }, +_LT_EOF + $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (void *) \&\2},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext + cat <<\_LT_EOF >> conftest.$ac_ext + {0, (void *) 0} +}; + +/* This works around a problem in FreeBSD linker */ +#ifdef FREEBSD_WORKAROUND +static const void *lt_preloaded_setup() { + return lt__PROGRAM__LTX_preloaded_symbols; +} +#endif + +#ifdef __cplusplus +} +#endif +_LT_EOF + # Now try linking the two files. + mv conftest.$ac_objext conftstm.$ac_objext + lt_save_LIBS="$LIBS" + lt_save_CFLAGS="$CFLAGS" + LIBS="conftstm.$ac_objext" + CFLAGS="$CFLAGS$lt_prog_compiler_no_builtin_flag" + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 + (eval $ac_link) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && test -s conftest${ac_exeext}; then + pipe_works=yes + fi + LIBS="$lt_save_LIBS" + CFLAGS="$lt_save_CFLAGS" + else + echo "cannot find nm_test_func in $nlist" >&5 + fi + else + echo "cannot find nm_test_var in $nlist" >&5 + fi + else + echo "cannot run $lt_cv_sys_global_symbol_pipe" >&5 + fi + else + echo "$progname: failed program was:" >&5 + cat conftest.$ac_ext >&5 + fi + rm -rf conftest* conftst* + + # Do not use the global_symbol_pipe unless it works. + if test "$pipe_works" = yes; then + break + else + lt_cv_sys_global_symbol_pipe= + fi +done + +fi + +if test -z "$lt_cv_sys_global_symbol_pipe"; then + lt_cv_sys_global_symbol_to_cdecl= +fi +if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: failed" >&5 +$as_echo "failed" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 +$as_echo "ok" >&6; } +fi + + + + + + + + + + + + + + + + + + + + + + + +# Check whether --enable-libtool-lock was given. +if test "${enable_libtool_lock+set}" = set; then : + enableval=$enable_libtool_lock; +fi + +test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes + +# Some flags need to be propagated to the compiler or linker for good +# libtool support. +case $host in +ia64-*-hpux*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + case `/usr/bin/file conftest.$ac_objext` in + *ELF-32*) + HPUX_IA64_MODE="32" + ;; + *ELF-64*) + HPUX_IA64_MODE="64" + ;; + esac + fi + rm -rf conftest* + ;; +*-*-irix6*) + # Find out which ABI we are using. + echo '#line 6295 "configure"' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + if test "$lt_cv_prog_gnu_ld" = yes; then + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -melf32bsmip" + ;; + *N32*) + LD="${LD-ld} -melf32bmipn32" + ;; + *64-bit*) + LD="${LD-ld} -melf64bmip" + ;; + esac + else + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -32" + ;; + *N32*) + LD="${LD-ld} -n32" + ;; + *64-bit*) + LD="${LD-ld} -64" + ;; + esac + fi + fi + rm -rf conftest* + ;; + +x86_64-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \ +s390*-*linux*|s390*-*tpf*|sparc*-*linux*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + case `/usr/bin/file conftest.o` in + *32-bit*) + case $host in + x86_64-*kfreebsd*-gnu) + LD="${LD-ld} -m elf_i386_fbsd" + ;; + x86_64-*linux*) + LD="${LD-ld} -m elf_i386" + ;; + ppc64-*linux*|powerpc64-*linux*) + LD="${LD-ld} -m elf32ppclinux" + ;; + s390x-*linux*) + LD="${LD-ld} -m elf_s390" + ;; + sparc64-*linux*) + LD="${LD-ld} -m elf32_sparc" + ;; + esac + ;; + *64-bit*) + case $host in + x86_64-*kfreebsd*-gnu) + LD="${LD-ld} -m elf_x86_64_fbsd" + ;; + x86_64-*linux*) + LD="${LD-ld} -m elf_x86_64" + ;; + ppc*-*linux*|powerpc*-*linux*) + LD="${LD-ld} -m elf64ppc" + ;; + s390*-*linux*|s390*-*tpf*) + LD="${LD-ld} -m elf64_s390" + ;; + sparc*-*linux*) + LD="${LD-ld} -m elf64_sparc" + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; + +*-*-sco3.2v5*) + # On SCO OpenServer 5, we need -belf to get full-featured binaries. + SAVE_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -belf" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler needs -belf" >&5 +$as_echo_n "checking whether the C compiler needs -belf... " >&6; } +if test "${lt_cv_cc_needs_belf+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + lt_cv_cc_needs_belf=yes +else + lt_cv_cc_needs_belf=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_cc_needs_belf" >&5 +$as_echo "$lt_cv_cc_needs_belf" >&6; } + if test x"$lt_cv_cc_needs_belf" != x"yes"; then + # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf + CFLAGS="$SAVE_CFLAGS" + fi + ;; +sparc*-*solaris*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + case `/usr/bin/file conftest.o` in + *64-bit*) + case $lt_cv_prog_gnu_ld in + yes*) LD="${LD-ld} -m elf64_sparc" ;; + *) + if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then + LD="${LD-ld} -64" + fi + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; +esac + +need_locks="$enable_libtool_lock" + + + case $host_os in + rhapsody* | darwin*) + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}dsymutil", so it can be a program name with args. +set dummy ${ac_tool_prefix}dsymutil; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_DSYMUTIL+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$DSYMUTIL"; then + ac_cv_prog_DSYMUTIL="$DSYMUTIL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_DSYMUTIL="${ac_tool_prefix}dsymutil" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +DSYMUTIL=$ac_cv_prog_DSYMUTIL +if test -n "$DSYMUTIL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DSYMUTIL" >&5 +$as_echo "$DSYMUTIL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_DSYMUTIL"; then + ac_ct_DSYMUTIL=$DSYMUTIL + # Extract the first word of "dsymutil", so it can be a program name with args. +set dummy dsymutil; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_ac_ct_DSYMUTIL+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_DSYMUTIL"; then + ac_cv_prog_ac_ct_DSYMUTIL="$ac_ct_DSYMUTIL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_DSYMUTIL="dsymutil" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_DSYMUTIL=$ac_cv_prog_ac_ct_DSYMUTIL +if test -n "$ac_ct_DSYMUTIL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DSYMUTIL" >&5 +$as_echo "$ac_ct_DSYMUTIL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_DSYMUTIL" = x; then + DSYMUTIL=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + DSYMUTIL=$ac_ct_DSYMUTIL + fi +else + DSYMUTIL="$ac_cv_prog_DSYMUTIL" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}nmedit", so it can be a program name with args. +set dummy ${ac_tool_prefix}nmedit; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_NMEDIT+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$NMEDIT"; then + ac_cv_prog_NMEDIT="$NMEDIT" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_NMEDIT="${ac_tool_prefix}nmedit" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +NMEDIT=$ac_cv_prog_NMEDIT +if test -n "$NMEDIT"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $NMEDIT" >&5 +$as_echo "$NMEDIT" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_NMEDIT"; then + ac_ct_NMEDIT=$NMEDIT + # Extract the first word of "nmedit", so it can be a program name with args. +set dummy nmedit; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_ac_ct_NMEDIT+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_NMEDIT"; then + ac_cv_prog_ac_ct_NMEDIT="$ac_ct_NMEDIT" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_NMEDIT="nmedit" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_NMEDIT=$ac_cv_prog_ac_ct_NMEDIT +if test -n "$ac_ct_NMEDIT"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_NMEDIT" >&5 +$as_echo "$ac_ct_NMEDIT" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_NMEDIT" = x; then + NMEDIT=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + NMEDIT=$ac_ct_NMEDIT + fi +else + NMEDIT="$ac_cv_prog_NMEDIT" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}lipo", so it can be a program name with args. +set dummy ${ac_tool_prefix}lipo; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_LIPO+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$LIPO"; then + ac_cv_prog_LIPO="$LIPO" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_LIPO="${ac_tool_prefix}lipo" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +LIPO=$ac_cv_prog_LIPO +if test -n "$LIPO"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIPO" >&5 +$as_echo "$LIPO" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_LIPO"; then + ac_ct_LIPO=$LIPO + # Extract the first word of "lipo", so it can be a program name with args. +set dummy lipo; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_ac_ct_LIPO+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_LIPO"; then + ac_cv_prog_ac_ct_LIPO="$ac_ct_LIPO" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_LIPO="lipo" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_LIPO=$ac_cv_prog_ac_ct_LIPO +if test -n "$ac_ct_LIPO"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_LIPO" >&5 +$as_echo "$ac_ct_LIPO" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_LIPO" = x; then + LIPO=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + LIPO=$ac_ct_LIPO + fi +else + LIPO="$ac_cv_prog_LIPO" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}otool", so it can be a program name with args. +set dummy ${ac_tool_prefix}otool; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_OTOOL+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$OTOOL"; then + ac_cv_prog_OTOOL="$OTOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_OTOOL="${ac_tool_prefix}otool" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +OTOOL=$ac_cv_prog_OTOOL +if test -n "$OTOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL" >&5 +$as_echo "$OTOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_OTOOL"; then + ac_ct_OTOOL=$OTOOL + # Extract the first word of "otool", so it can be a program name with args. +set dummy otool; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_ac_ct_OTOOL+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_OTOOL"; then + ac_cv_prog_ac_ct_OTOOL="$ac_ct_OTOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_OTOOL="otool" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_OTOOL=$ac_cv_prog_ac_ct_OTOOL +if test -n "$ac_ct_OTOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL" >&5 +$as_echo "$ac_ct_OTOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_OTOOL" = x; then + OTOOL=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + OTOOL=$ac_ct_OTOOL + fi +else + OTOOL="$ac_cv_prog_OTOOL" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}otool64", so it can be a program name with args. +set dummy ${ac_tool_prefix}otool64; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_OTOOL64+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$OTOOL64"; then + ac_cv_prog_OTOOL64="$OTOOL64" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_OTOOL64="${ac_tool_prefix}otool64" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +OTOOL64=$ac_cv_prog_OTOOL64 +if test -n "$OTOOL64"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL64" >&5 +$as_echo "$OTOOL64" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_OTOOL64"; then + ac_ct_OTOOL64=$OTOOL64 + # Extract the first word of "otool64", so it can be a program name with args. +set dummy otool64; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_ac_ct_OTOOL64+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_OTOOL64"; then + ac_cv_prog_ac_ct_OTOOL64="$ac_ct_OTOOL64" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_OTOOL64="otool64" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_OTOOL64=$ac_cv_prog_ac_ct_OTOOL64 +if test -n "$ac_ct_OTOOL64"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL64" >&5 +$as_echo "$ac_ct_OTOOL64" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_OTOOL64" = x; then + OTOOL64=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + OTOOL64=$ac_ct_OTOOL64 + fi +else + OTOOL64="$ac_cv_prog_OTOOL64" +fi + + + + + + + + + + + + + + + + + + + + + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -single_module linker flag" >&5 +$as_echo_n "checking for -single_module linker flag... " >&6; } +if test "${lt_cv_apple_cc_single_mod+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_apple_cc_single_mod=no + if test -z "${LT_MULTI_MODULE}"; then + # By default we will add the -single_module flag. You can override + # by either setting the environment variable LT_MULTI_MODULE + # non-empty at configure time, or by adding -multi_module to the + # link flags. + rm -rf libconftest.dylib* + echo "int foo(void){return 1;}" > conftest.c + echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ +-dynamiclib -Wl,-single_module conftest.c" >&5 + $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ + -dynamiclib -Wl,-single_module conftest.c 2>conftest.err + _lt_result=$? + if test -f libconftest.dylib && test ! -s conftest.err && test $_lt_result = 0; then + lt_cv_apple_cc_single_mod=yes + else + cat conftest.err >&5 + fi + rm -rf libconftest.dylib* + rm -f conftest.* + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_apple_cc_single_mod" >&5 +$as_echo "$lt_cv_apple_cc_single_mod" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -exported_symbols_list linker flag" >&5 +$as_echo_n "checking for -exported_symbols_list linker flag... " >&6; } +if test "${lt_cv_ld_exported_symbols_list+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_ld_exported_symbols_list=no + save_LDFLAGS=$LDFLAGS + echo "_main" > conftest.sym + LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + lt_cv_ld_exported_symbols_list=yes +else + lt_cv_ld_exported_symbols_list=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS="$save_LDFLAGS" + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_exported_symbols_list" >&5 +$as_echo "$lt_cv_ld_exported_symbols_list" >&6; } + case $host_os in + rhapsody* | darwin1.[012]) + _lt_dar_allow_undefined='${wl}-undefined ${wl}suppress' ;; + darwin1.*) + _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; + darwin*) # darwin 5.x on + # if running on 10.5 or later, the deployment target defaults + # to the OS version, if on x86, and 10.4, the deployment + # target defaults to 10.4. Don't you love it? + case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in + 10.0,*86*-darwin8*|10.0,*-darwin[91]*) + _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; + 10.[012]*) + _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; + 10.*) + _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; + esac + ;; + esac + if test "$lt_cv_apple_cc_single_mod" = "yes"; then + _lt_dar_single_mod='$single_module' + fi + if test "$lt_cv_ld_exported_symbols_list" = "yes"; then + _lt_dar_export_syms=' ${wl}-exported_symbols_list,$output_objdir/${libname}-symbols.expsym' + else + _lt_dar_export_syms='~$NMEDIT -s $output_objdir/${libname}-symbols.expsym ${lib}' + fi + if test "$DSYMUTIL" != ":"; then + _lt_dsymutil='~$DSYMUTIL $lib || :' + else + _lt_dsymutil= + fi + ;; + esac + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 +$as_echo_n "checking how to run the C preprocessor... " >&6; } +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then + if test "${ac_cv_prog_CPP+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + # Double quotes because CPP needs to be expanded + for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" + do + ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + break +fi + + done + ac_cv_prog_CPP=$CPP + +fi + CPP=$ac_cv_prog_CPP +else + ac_cv_prog_CPP=$CPP +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 +$as_echo "$CPP" >&6; } +ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error "C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details." "$LINENO" 5; } +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 +$as_echo_n "checking for ANSI C header files... " >&6; } +if test "${ac_cv_header_stdc+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#include +#include + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_header_stdc=yes +else + ac_cv_header_stdc=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "memchr" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "free" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. + if test "$cross_compiling" = yes; then : + : +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#if ((' ' & 0x0FF) == 0x020) +# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#else +# define ISLOWER(c) \ + (('a' <= (c) && (c) <= 'i') \ + || ('j' <= (c) && (c) <= 'r') \ + || ('s' <= (c) && (c) <= 'z')) +# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) +#endif + +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int +main () +{ + int i; + for (i = 0; i < 256; i++) + if (XOR (islower (i), ISLOWER (i)) + || toupper (i) != TOUPPER (i)) + return 2; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + +else + ac_cv_header_stdc=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 +$as_echo "$ac_cv_header_stdc" >&6; } +if test $ac_cv_header_stdc = yes; then + +$as_echo "#define STDC_HEADERS 1" >>confdefs.h + +fi + +# On IRIX 5.3, sys/types and inttypes.h are conflicting. +for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ + inttypes.h stdint.h unistd.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default +" +eval as_val=\$$as_ac_Header + if test "x$as_val" = x""yes; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + +for ac_header in dlfcn.h +do : + ac_fn_c_check_header_compile "$LINENO" "dlfcn.h" "ac_cv_header_dlfcn_h" "$ac_includes_default +" +if test "x$ac_cv_header_dlfcn_h" = x""yes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_DLFCN_H 1 +_ACEOF + +fi + +done + + + +ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu +if test -z "$CXX"; then + if test -n "$CCC"; then + CXX=$CCC + else + if test -n "$ac_tool_prefix"; then + for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_CXX+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CXX"; then + ac_cv_prog_CXX="$CXX" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CXX="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CXX=$ac_cv_prog_CXX +if test -n "$CXX"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXX" >&5 +$as_echo "$CXX" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$CXX" && break + done +fi +if test -z "$CXX"; then + ac_ct_CXX=$CXX + for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_ac_ct_CXX+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CXX"; then + ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_CXX="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CXX=$ac_cv_prog_ac_ct_CXX +if test -n "$ac_ct_CXX"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CXX" >&5 +$as_echo "$ac_ct_CXX" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_CXX" && break +done + + if test "x$ac_ct_CXX" = x; then + CXX="g++" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CXX=$ac_ct_CXX + fi +fi + + fi +fi +# Provide some information about the compiler. +$as_echo "$as_me:${as_lineno-$LINENO}: checking for C++ compiler version" >&5 +set X $ac_compile +ac_compiler=$2 +for ac_option in --version -v -V -qversion; do + { { ac_try="$ac_compiler $ac_option >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compiler $ac_option >&5") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + sed '10a\ +... rest of stderr output deleted ... + 10q' conftest.err >conftest.er1 + cat conftest.er1 >&5 + fi + rm -f conftest.er1 conftest.err + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } +done + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C++ compiler" >&5 +$as_echo_n "checking whether we are using the GNU C++ compiler... " >&6; } +if test "${ac_cv_cxx_compiler_gnu+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + ac_compiler_gnu=yes +else + ac_compiler_gnu=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_cxx_compiler_gnu=$ac_compiler_gnu + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cxx_compiler_gnu" >&5 +$as_echo "$ac_cv_cxx_compiler_gnu" >&6; } +if test $ac_compiler_gnu = yes; then + GXX=yes +else + GXX= +fi +ac_test_CXXFLAGS=${CXXFLAGS+set} +ac_save_CXXFLAGS=$CXXFLAGS +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX accepts -g" >&5 +$as_echo_n "checking whether $CXX accepts -g... " >&6; } +if test "${ac_cv_prog_cxx_g+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + ac_save_cxx_werror_flag=$ac_cxx_werror_flag + ac_cxx_werror_flag=yes + ac_cv_prog_cxx_g=no + CXXFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + ac_cv_prog_cxx_g=yes +else + CXXFLAGS="" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + +else + ac_cxx_werror_flag=$ac_save_cxx_werror_flag + CXXFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + ac_cv_prog_cxx_g=yes +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_cxx_werror_flag=$ac_save_cxx_werror_flag +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_g" >&5 +$as_echo "$ac_cv_prog_cxx_g" >&6; } +if test "$ac_test_CXXFLAGS" = set; then + CXXFLAGS=$ac_save_CXXFLAGS +elif test $ac_cv_prog_cxx_g = yes; then + if test "$GXX" = yes; then + CXXFLAGS="-g -O2" + else + CXXFLAGS="-g" + fi +else + if test "$GXX" = yes; then + CXXFLAGS="-O2" + else + CXXFLAGS= + fi +fi +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +depcc="$CXX" am_compiler_list= + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 +$as_echo_n "checking dependency style of $depcc... " >&6; } +if test "${am_cv_CXX_dependencies_compiler_type+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then + # We make a subdir and do the tests there. Otherwise we can end up + # making bogus files that we don't know about and never remove. For + # instance it was reported that on HP-UX the gcc test will end up + # making a dummy file named `D' -- because `-MD' means `put the output + # in D'. + mkdir conftest.dir + # Copy depcomp to subdir because otherwise we won't find it if we're + # using a relative directory. + cp "$am_depcomp" conftest.dir + cd conftest.dir + # We will build objects and dependencies in a subdirectory because + # it helps to detect inapplicable dependency modes. For instance + # both Tru64's cc and ICC support -MD to output dependencies as a + # side effect of compilation, but ICC will put the dependencies in + # the current directory while Tru64 will put them in the object + # directory. + mkdir sub + + am_cv_CXX_dependencies_compiler_type=none + if test "$am_compiler_list" = ""; then + am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` + fi + am__universal=false + case " $depcc " in #( + *\ -arch\ *\ -arch\ *) am__universal=true ;; + esac + + for depmode in $am_compiler_list; do + # Setup a source with many dependencies, because some compilers + # like to wrap large dependency lists on column 80 (with \), and + # we should not choose a depcomp mode which is confused by this. + # + # We need to recreate these files for each test, as the compiler may + # overwrite some of them when testing with obscure command lines. + # This happens at least with the AIX C compiler. + : > sub/conftest.c + for i in 1 2 3 4 5 6; do + echo '#include "conftst'$i'.h"' >> sub/conftest.c + # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with + # Solaris 8's {/usr,}/bin/sh. + touch sub/conftst$i.h + done + echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf + + # We check with `-c' and `-o' for the sake of the "dashmstdout" + # mode. It turns out that the SunPro C++ compiler does not properly + # handle `-M -o', and we need to detect this. Also, some Intel + # versions had trouble with output in subdirs + am__obj=sub/conftest.${OBJEXT-o} + am__minus_obj="-o $am__obj" + case $depmode in + gcc) + # This depmode causes a compiler race in universal mode. + test "$am__universal" = false || continue + ;; + nosideeffect) + # after this tag, mechanisms are not by side-effect, so they'll + # only be used when explicitly requested + if test "x$enable_dependency_tracking" = xyes; then + continue + else + break + fi + ;; + msvisualcpp | msvcmsys) + # This compiler won't grok `-c -o', but also, the minuso test has + # not run yet. These depmodes are late enough in the game, and + # so weak that their functioning should not be impacted. + am__obj=conftest.${OBJEXT-o} + am__minus_obj= + ;; + none) break ;; + esac + if depmode=$depmode \ + source=sub/conftest.c object=$am__obj \ + depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ + $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ + >/dev/null 2>conftest.err && + grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && + grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && + grep $am__obj sub/conftest.Po > /dev/null 2>&1 && + ${MAKE-make} -s -f confmf > /dev/null 2>&1; then + # icc doesn't choke on unknown options, it will just issue warnings + # or remarks (even with -Werror). So we grep stderr for any message + # that says an option was ignored or not supported. + # When given -MP, icc 7.0 and 7.1 complain thusly: + # icc: Command line warning: ignoring option '-M'; no argument required + # The diagnosis changed in icc 8.0: + # icc: Command line remark: option '-MP' not supported + if (grep 'ignoring option' conftest.err || + grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else + am_cv_CXX_dependencies_compiler_type=$depmode + break + fi + fi + done + + cd .. + rm -rf conftest.dir +else + am_cv_CXX_dependencies_compiler_type=none +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CXX_dependencies_compiler_type" >&5 +$as_echo "$am_cv_CXX_dependencies_compiler_type" >&6; } +CXXDEPMODE=depmode=$am_cv_CXX_dependencies_compiler_type + + if + test "x$enable_dependency_tracking" != xno \ + && test "$am_cv_CXX_dependencies_compiler_type" = gcc3; then + am__fastdepCXX_TRUE= + am__fastdepCXX_FALSE='#' +else + am__fastdepCXX_TRUE='#' + am__fastdepCXX_FALSE= +fi + + +if test -n "$CXX" && ( test "X$CXX" != "Xno" && + ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) || + (test "X$CXX" != "Xg++"))) ; then + ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C++ preprocessor" >&5 +$as_echo_n "checking how to run the C++ preprocessor... " >&6; } +if test -z "$CXXCPP"; then + if test "${ac_cv_prog_CXXCPP+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + # Double quotes because CXXCPP needs to be expanded + for CXXCPP in "$CXX -E" "/lib/cpp" + do + ac_preproc_ok=false +for ac_cxx_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if ac_fn_cxx_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_cxx_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + break +fi + + done + ac_cv_prog_CXXCPP=$CXXCPP + +fi + CXXCPP=$ac_cv_prog_CXXCPP +else + ac_cv_prog_CXXCPP=$CXXCPP +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXXCPP" >&5 +$as_echo "$CXXCPP" >&6; } +ac_preproc_ok=false +for ac_cxx_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if ac_fn_cxx_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_cxx_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +_lt_caught_CXX_error=yes; } +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +else + _lt_caught_CXX_error=yes +fi + + + + + +# Set options +# Check whether --enable-static was given. +if test "${enable_static+set}" = set; then : + enableval=$enable_static; p=${PACKAGE-default} + case $enableval in + yes) enable_static=yes ;; + no) enable_static=no ;; + *) + enable_static=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_static=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac +else + enable_static=no +fi + + + + + + + + + + + enable_dlopen=no + + + enable_win32_dll=no + + + # Check whether --enable-shared was given. +if test "${enable_shared+set}" = set; then : + enableval=$enable_shared; p=${PACKAGE-default} + case $enableval in + yes) enable_shared=yes ;; + no) enable_shared=no ;; + *) + enable_shared=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_shared=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac +else + enable_shared=yes +fi + + + + + + + + + + + +# Check whether --with-pic was given. +if test "${with_pic+set}" = set; then : + withval=$with_pic; pic_mode="$withval" +else + pic_mode=default +fi + + +test -z "$pic_mode" && pic_mode=default + + + + + + + + # Check whether --enable-fast-install was given. +if test "${enable_fast_install+set}" = set; then : + enableval=$enable_fast_install; p=${PACKAGE-default} + case $enableval in + yes) enable_fast_install=yes ;; + no) enable_fast_install=no ;; + *) + enable_fast_install=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_fast_install=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac +else + enable_fast_install=yes +fi + + + + + + + + + + + +# This can be used to rebuild libtool when needed +LIBTOOL_DEPS="$ltmain" + +# Always use our own libtool. +LIBTOOL='$(SHELL) $(top_builddir)/libtool' + + + + + + + + + + + + + + + + + + + + + + + + + +test -z "$LN_S" && LN_S="ln -s" + + + + + + + + + + + + + + +if test -n "${ZSH_VERSION+set}" ; then + setopt NO_GLOB_SUBST +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for objdir" >&5 +$as_echo_n "checking for objdir... " >&6; } +if test "${lt_cv_objdir+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + rm -f .libs 2>/dev/null +mkdir .libs 2>/dev/null +if test -d .libs; then + lt_cv_objdir=.libs +else + # MS-DOS does not allow filenames that begin with a dot. + lt_cv_objdir=_libs +fi +rmdir .libs 2>/dev/null +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_objdir" >&5 +$as_echo "$lt_cv_objdir" >&6; } +objdir=$lt_cv_objdir + + + + + +cat >>confdefs.h <<_ACEOF +#define LT_OBJDIR "$lt_cv_objdir/" +_ACEOF + + + + + + + + + + + + + + + + + +case $host_os in +aix3*) + # AIX sometimes has problems with the GCC collect2 program. For some + # reason, if we set the COLLECT_NAMES environment variable, the problems + # vanish in a puff of smoke. + if test "X${COLLECT_NAMES+set}" != Xset; then + COLLECT_NAMES= + export COLLECT_NAMES + fi + ;; +esac + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +sed_quote_subst='s/\(["`$\\]\)/\\\1/g' + +# Same as above, but do not quote variable references. +double_quote_subst='s/\(["`\\]\)/\\\1/g' + +# Sed substitution to delay expansion of an escaped shell variable in a +# double_quote_subst'ed string. +delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' + +# Sed substitution to delay expansion of an escaped single quote. +delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' + +# Sed substitution to avoid accidental globbing in evaled expressions +no_glob_subst='s/\*/\\\*/g' + +# Global variables: +ofile=libtool +can_build_shared=yes + +# All known linkers require a `.a' archive for static linking (except MSVC, +# which needs '.lib'). +libext=a + +with_gnu_ld="$lt_cv_prog_gnu_ld" + +old_CC="$CC" +old_CFLAGS="$CFLAGS" + +# Set sane defaults for various variables +test -z "$CC" && CC=cc +test -z "$LTCC" && LTCC=$CC +test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS +test -z "$LD" && LD=ld +test -z "$ac_objext" && ac_objext=o + +for cc_temp in $compiler""; do + case $cc_temp in + compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; + distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; + \-*) ;; + *) break;; + esac +done +cc_basename=`$ECHO "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` + + +# Only perform the check for file, if the check method requires it +test -z "$MAGIC_CMD" && MAGIC_CMD=file +case $deplibs_check_method in +file_magic*) + if test "$file_magic_cmd" = '$MAGIC_CMD'; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${ac_tool_prefix}file" >&5 +$as_echo_n "checking for ${ac_tool_prefix}file... " >&6; } +if test "${lt_cv_path_MAGIC_CMD+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + case $MAGIC_CMD in +[\\/*] | ?:[\\/]*) + lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. + ;; +*) + lt_save_MAGIC_CMD="$MAGIC_CMD" + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" + for ac_dir in $ac_dummy; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/${ac_tool_prefix}file; then + lt_cv_path_MAGIC_CMD="$ac_dir/${ac_tool_prefix}file" + if test -n "$file_magic_test_file"; then + case $deplibs_check_method in + "file_magic "*) + file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` + MAGIC_CMD="$lt_cv_path_MAGIC_CMD" + if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | + $EGREP "$file_magic_regex" > /dev/null; then + : + else + cat <<_LT_EOF 1>&2 + +*** Warning: the command libtool uses to detect shared libraries, +*** $file_magic_cmd, produces output that libtool cannot recognize. +*** The result is that libtool may fail to recognize shared libraries +*** as such. This will affect the creation of libtool libraries that +*** depend on shared libraries, but programs linked with such libtool +*** libraries will work regardless of this problem. Nevertheless, you +*** may want to report the problem to your system manager and/or to +*** bug-libtool@gnu.org + +_LT_EOF + fi ;; + esac + fi + break + fi + done + IFS="$lt_save_ifs" + MAGIC_CMD="$lt_save_MAGIC_CMD" + ;; +esac +fi + +MAGIC_CMD="$lt_cv_path_MAGIC_CMD" +if test -n "$MAGIC_CMD"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 +$as_echo "$MAGIC_CMD" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + + + +if test -z "$lt_cv_path_MAGIC_CMD"; then + if test -n "$ac_tool_prefix"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for file" >&5 +$as_echo_n "checking for file... " >&6; } +if test "${lt_cv_path_MAGIC_CMD+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + case $MAGIC_CMD in +[\\/*] | ?:[\\/]*) + lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. + ;; +*) + lt_save_MAGIC_CMD="$MAGIC_CMD" + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" + for ac_dir in $ac_dummy; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/file; then + lt_cv_path_MAGIC_CMD="$ac_dir/file" + if test -n "$file_magic_test_file"; then + case $deplibs_check_method in + "file_magic "*) + file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` + MAGIC_CMD="$lt_cv_path_MAGIC_CMD" + if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | + $EGREP "$file_magic_regex" > /dev/null; then + : + else + cat <<_LT_EOF 1>&2 + +*** Warning: the command libtool uses to detect shared libraries, +*** $file_magic_cmd, produces output that libtool cannot recognize. +*** The result is that libtool may fail to recognize shared libraries +*** as such. This will affect the creation of libtool libraries that +*** depend on shared libraries, but programs linked with such libtool +*** libraries will work regardless of this problem. Nevertheless, you +*** may want to report the problem to your system manager and/or to +*** bug-libtool@gnu.org + +_LT_EOF + fi ;; + esac + fi + break + fi + done + IFS="$lt_save_ifs" + MAGIC_CMD="$lt_save_MAGIC_CMD" + ;; +esac +fi + +MAGIC_CMD="$lt_cv_path_MAGIC_CMD" +if test -n "$MAGIC_CMD"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 +$as_echo "$MAGIC_CMD" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + else + MAGIC_CMD=: + fi +fi + + fi + ;; +esac + +# Use C for the default configuration in the libtool script + +lt_save_CC="$CC" +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +# Source file extension for C test sources. +ac_ext=c + +# Object file extension for compiled C test sources. +objext=o +objext=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="int some_variable = 0;" + +# Code to be used in simple link tests +lt_simple_link_test_code='int main(){return(0);}' + + + + + + + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC + +# Save the default compiler, since it gets overwritten when the other +# tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP. +compiler_DEFAULT=$CC + +# save warnings/boilerplate of simple test code +ac_outfile=conftest.$ac_objext +echo "$lt_simple_compile_test_code" >conftest.$ac_ext +eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_compiler_boilerplate=`cat conftest.err` +$RM conftest* + +ac_outfile=conftest.$ac_objext +echo "$lt_simple_link_test_code" >conftest.$ac_ext +eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_linker_boilerplate=`cat conftest.err` +$RM -r conftest* + + +## CAVEAT EMPTOR: +## There is no encapsulation within the following macros, do not change +## the running order or otherwise move them around unless you know exactly +## what you are doing... +if test -n "$compiler"; then + +lt_prog_compiler_no_builtin_flag= + +if test "$GCC" = yes; then + lt_prog_compiler_no_builtin_flag=' -fno-builtin' + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -fno-rtti -fno-exceptions" >&5 +$as_echo_n "checking if $compiler supports -fno-rtti -fno-exceptions... " >&6; } +if test "${lt_cv_prog_compiler_rtti_exceptions+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_rtti_exceptions=no + ac_outfile=conftest.$ac_objext + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="-fno-rtti -fno-exceptions" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:8351: $lt_compile\"" >&5) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&5 + echo "$as_me:8355: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings other than the usual output. + $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler_rtti_exceptions=yes + fi + fi + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_rtti_exceptions" >&5 +$as_echo "$lt_cv_prog_compiler_rtti_exceptions" >&6; } + +if test x"$lt_cv_prog_compiler_rtti_exceptions" = xyes; then + lt_prog_compiler_no_builtin_flag="$lt_prog_compiler_no_builtin_flag -fno-rtti -fno-exceptions" +else + : +fi + +fi + + + + + + + lt_prog_compiler_wl= +lt_prog_compiler_pic= +lt_prog_compiler_static= + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5 +$as_echo_n "checking for $compiler option to produce PIC... " >&6; } + + if test "$GCC" = yes; then + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_static='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + lt_prog_compiler_static='-Bstatic' + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + lt_prog_compiler_pic='-fPIC' + ;; + m68k) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the `-m68020' flag to GCC prevents building anything better, + # like `-m68040'. + lt_prog_compiler_pic='-m68020 -resident32 -malways-restore-a4' + ;; + esac + ;; + + beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + + mingw* | cygwin* | pw32* | os2* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + # Although the cygwin gcc ignores -fPIC, still need this for old-style + # (--disable-auto-import) libraries + lt_prog_compiler_pic='-DDLL_EXPORT' + ;; + + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + lt_prog_compiler_pic='-fno-common' + ;; + + hpux*) + # PIC is the default for 64-bit PA HP-UX, but not for 32-bit + # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag + # sets the default TLS model and affects inlining. + case $host_cpu in + hppa*64*) + # +Z the default + ;; + *) + lt_prog_compiler_pic='-fPIC' + ;; + esac + ;; + + interix[3-9]*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + + msdosdjgpp*) + # Just because we use GCC doesn't mean we suddenly get shared libraries + # on systems that don't support them. + lt_prog_compiler_can_build_shared=no + enable_shared=no + ;; + + *nto* | *qnx*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + lt_prog_compiler_pic='-fPIC -shared' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + lt_prog_compiler_pic=-Kconform_pic + fi + ;; + + *) + lt_prog_compiler_pic='-fPIC' + ;; + esac + else + # PORTME Check for flag to pass linker flags through the system compiler. + case $host_os in + aix*) + lt_prog_compiler_wl='-Wl,' + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + lt_prog_compiler_static='-Bstatic' + else + lt_prog_compiler_static='-bnso -bI:/lib/syscalls.exp' + fi + ;; + + mingw* | cygwin* | pw32* | os2* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + lt_prog_compiler_pic='-DDLL_EXPORT' + ;; + + hpux9* | hpux10* | hpux11*) + lt_prog_compiler_wl='-Wl,' + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + lt_prog_compiler_pic='+Z' + ;; + esac + # Is there a better lt_prog_compiler_static that works with the bundled CC? + lt_prog_compiler_static='${wl}-a ${wl}archive' + ;; + + irix5* | irix6* | nonstopux*) + lt_prog_compiler_wl='-Wl,' + # PIC (with -KPIC) is the default. + lt_prog_compiler_static='-non_shared' + ;; + + linux* | k*bsd*-gnu | kopensolaris*-gnu) + case $cc_basename in + # old Intel for x86_64 which still supported -KPIC. + ecc*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-static' + ;; + # icc used to be incompatible with GCC. + # ICC 10 doesn't accept -KPIC any more. + icc* | ifort*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-fPIC' + lt_prog_compiler_static='-static' + ;; + # Lahey Fortran 8.1. + lf95*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='--shared' + lt_prog_compiler_static='--static' + ;; + pgcc* | pgf77* | pgf90* | pgf95*) + # Portland Group compilers (*not* the Pentium gcc compiler, + # which looks to be a dead project) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-fpic' + lt_prog_compiler_static='-Bstatic' + ;; + ccc*) + lt_prog_compiler_wl='-Wl,' + # All Alpha code is PIC. + lt_prog_compiler_static='-non_shared' + ;; + xl*) + # IBM XL C 8.0/Fortran 10.1 on PPC + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-qpic' + lt_prog_compiler_static='-qstaticlink' + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) + # Sun C 5.9 + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + lt_prog_compiler_wl='-Wl,' + ;; + *Sun\ F*) + # Sun Fortran 8.3 passes all unrecognized flags to the linker + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + lt_prog_compiler_wl='' + ;; + esac + ;; + esac + ;; + + newsos6) + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + ;; + + *nto* | *qnx*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + lt_prog_compiler_pic='-fPIC -shared' + ;; + + osf3* | osf4* | osf5*) + lt_prog_compiler_wl='-Wl,' + # All OSF/1 code is PIC. + lt_prog_compiler_static='-non_shared' + ;; + + rdos*) + lt_prog_compiler_static='-non_shared' + ;; + + solaris*) + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + case $cc_basename in + f77* | f90* | f95*) + lt_prog_compiler_wl='-Qoption ld ';; + *) + lt_prog_compiler_wl='-Wl,';; + esac + ;; + + sunos4*) + lt_prog_compiler_wl='-Qoption ld ' + lt_prog_compiler_pic='-PIC' + lt_prog_compiler_static='-Bstatic' + ;; + + sysv4 | sysv4.2uw2* | sysv4.3*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + ;; + + sysv4*MP*) + if test -d /usr/nec ;then + lt_prog_compiler_pic='-Kconform_pic' + lt_prog_compiler_static='-Bstatic' + fi + ;; + + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + ;; + + unicos*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_can_build_shared=no + ;; + + uts4*) + lt_prog_compiler_pic='-pic' + lt_prog_compiler_static='-Bstatic' + ;; + + *) + lt_prog_compiler_can_build_shared=no + ;; + esac + fi + +case $host_os in + # For platforms which do not support PIC, -DPIC is meaningless: + *djgpp*) + lt_prog_compiler_pic= + ;; + *) + lt_prog_compiler_pic="$lt_prog_compiler_pic -DPIC" + ;; +esac +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_prog_compiler_pic" >&5 +$as_echo "$lt_prog_compiler_pic" >&6; } + + + + + + +# +# Check to make sure the PIC flag actually works. +# +if test -n "$lt_prog_compiler_pic"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic works" >&5 +$as_echo_n "checking if $compiler PIC flag $lt_prog_compiler_pic works... " >&6; } +if test "${lt_cv_prog_compiler_pic_works+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_pic_works=no + ac_outfile=conftest.$ac_objext + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="$lt_prog_compiler_pic -DPIC" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:8690: $lt_compile\"" >&5) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&5 + echo "$as_me:8694: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings other than the usual output. + $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler_pic_works=yes + fi + fi + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works" >&5 +$as_echo "$lt_cv_prog_compiler_pic_works" >&6; } + +if test x"$lt_cv_prog_compiler_pic_works" = xyes; then + case $lt_prog_compiler_pic in + "" | " "*) ;; + *) lt_prog_compiler_pic=" $lt_prog_compiler_pic" ;; + esac +else + lt_prog_compiler_pic= + lt_prog_compiler_can_build_shared=no +fi + +fi + + + + + + +# +# Check to make sure the static flag actually works. +# +wl=$lt_prog_compiler_wl eval lt_tmp_static_flag=\"$lt_prog_compiler_static\" +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler static flag $lt_tmp_static_flag works" >&5 +$as_echo_n "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; } +if test "${lt_cv_prog_compiler_static_works+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_static_works=no + save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS $lt_tmp_static_flag" + echo "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The linker can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&5 + $ECHO "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler_static_works=yes + fi + else + lt_cv_prog_compiler_static_works=yes + fi + fi + $RM -r conftest* + LDFLAGS="$save_LDFLAGS" + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works" >&5 +$as_echo "$lt_cv_prog_compiler_static_works" >&6; } + +if test x"$lt_cv_prog_compiler_static_works" = xyes; then + : +else + lt_prog_compiler_static= +fi + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 +$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } +if test "${lt_cv_prog_compiler_c_o+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_c_o=no + $RM -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:8795: $lt_compile\"" >&5) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&5 + echo "$as_me:8799: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + lt_cv_prog_compiler_c_o=yes + fi + fi + chmod u+w . 2>&5 + $RM conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files + $RM out/* && rmdir out + cd .. + $RM -r conftest + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5 +$as_echo "$lt_cv_prog_compiler_c_o" >&6; } + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 +$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } +if test "${lt_cv_prog_compiler_c_o+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_c_o=no + $RM -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:8850: $lt_compile\"" >&5) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&5 + echo "$as_me:8854: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + lt_cv_prog_compiler_c_o=yes + fi + fi + chmod u+w . 2>&5 + $RM conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files + $RM out/* && rmdir out + cd .. + $RM -r conftest + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5 +$as_echo "$lt_cv_prog_compiler_c_o" >&6; } + + + + +hard_links="nottested" +if test "$lt_cv_prog_compiler_c_o" = no && test "$need_locks" != no; then + # do not overwrite the value of need_locks provided by the user + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5 +$as_echo_n "checking if we can lock with hard links... " >&6; } + hard_links=yes + $RM conftest* + ln conftest.a conftest.b 2>/dev/null && hard_links=no + touch conftest.a + ln conftest.a conftest.b 2>&5 || hard_links=no + ln conftest.a conftest.b 2>/dev/null && hard_links=no + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5 +$as_echo "$hard_links" >&6; } + if test "$hard_links" = no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5 +$as_echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;} + need_locks=warn + fi +else + need_locks=no +fi + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5 +$as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; } + + runpath_var= + allow_undefined_flag= + always_export_symbols=no + archive_cmds= + archive_expsym_cmds= + compiler_needs_object=no + enable_shared_with_static_runtimes=no + export_dynamic_flag_spec= + export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + hardcode_automatic=no + hardcode_direct=no + hardcode_direct_absolute=no + hardcode_libdir_flag_spec= + hardcode_libdir_flag_spec_ld= + hardcode_libdir_separator= + hardcode_minus_L=no + hardcode_shlibpath_var=unsupported + inherit_rpath=no + link_all_deplibs=unknown + module_cmds= + module_expsym_cmds= + old_archive_from_new_cmds= + old_archive_from_expsyms_cmds= + thread_safe_flag_spec= + whole_archive_flag_spec= + # include_expsyms should be a list of space-separated symbols to be *always* + # included in the symbol list + include_expsyms= + # exclude_expsyms can be an extended regexp of symbols to exclude + # it will be wrapped by ` (' and `)$', so one must not match beginning or + # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', + # as well as any symbol that contains `d'. + exclude_expsyms='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*' + # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out + # platforms (ab)use it in PIC code, but their linkers get confused if + # the symbol is explicitly referenced. Since portable code cannot + # rely on this symbol name, it's probably fine to never include it in + # preloaded symbol tables. + # Exclude shared library initialization/finalization symbols. + extract_expsyms_cmds= + + case $host_os in + cygwin* | mingw* | pw32* | cegcc*) + # FIXME: the MSVC++ port hasn't been tested in a loooong time + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + if test "$GCC" != yes; then + with_gnu_ld=no + fi + ;; + interix*) + # we just hope/assume this is gcc and not c89 (= MSVC++) + with_gnu_ld=yes + ;; + openbsd*) + with_gnu_ld=no + ;; + linux* | k*bsd*-gnu) + link_all_deplibs=no + ;; + esac + + ld_shlibs=yes + if test "$with_gnu_ld" = yes; then + # If archive_cmds runs LD, not CC, wlarc should be empty + wlarc='${wl}' + + # Set some defaults for GNU ld with shared library support. These + # are reset later if shared libraries are not supported. Putting them + # here allows them to be overridden if necessary. + runpath_var=LD_RUN_PATH + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + export_dynamic_flag_spec='${wl}--export-dynamic' + # ancient GNU ld didn't support --whole-archive et. al. + if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then + whole_archive_flag_spec="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + else + whole_archive_flag_spec= + fi + supports_anon_versioning=no + case `$LD -v 2>&1` in + *GNU\ gold*) supports_anon_versioning=yes ;; + *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11 + *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... + *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... + *\ 2.11.*) ;; # other 2.11 versions + *) supports_anon_versioning=yes ;; + esac + + # See if GNU ld supports shared libraries. + case $host_os in + aix[3-9]*) + # On AIX/PPC, the GNU linker is very broken + if test "$host_cpu" != ia64; then + ld_shlibs=no + cat <<_LT_EOF 1>&2 + +*** Warning: the GNU linker, at least up to release 2.9.1, is reported +*** to be unable to reliably create shared libraries on AIX. +*** Therefore, libtool is disabling shared libraries support. If you +*** really care for shared libraries, you may want to modify your PATH +*** so that a non-GNU linker is found, and then restart. + +_LT_EOF + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='' + ;; + m68k) + archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + ;; + esac + ;; + + beos*) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + allow_undefined_flag=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + else + ld_shlibs=no + fi + ;; + + cygwin* | mingw* | pw32* | cegcc*) + # _LT_TAGVAR(hardcode_libdir_flag_spec, ) is actually meaningless, + # as there is no search path for DLLs. + hardcode_libdir_flag_spec='-L$libdir' + allow_undefined_flag=unsupported + always_export_symbols=no + enable_shared_with_static_runtimes=yes + export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/'\'' | $SED -e '\''/^[AITW][ ]/s/.*[ ]//'\'' | sort | uniq > $export_symbols' + + if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file (1st line + # is EXPORTS), use it as is; otherwise, prepend... + archive_expsym_cmds='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + ld_shlibs=no + fi + ;; + + interix[3-9]*) + hardcode_direct=no + hardcode_shlibpath_var=no + hardcode_libdir_flag_spec='${wl}-rpath,$libdir' + export_dynamic_flag_spec='${wl}-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + archive_expsym_cmds='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + + gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) + tmp_diet=no + if test "$host_os" = linux-dietlibc; then + case $cc_basename in + diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) + esac + fi + if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ + && test "$tmp_diet" = no + then + tmp_addflag= + tmp_sharedflag='-shared' + case $cc_basename,$host_cpu in + pgcc*) # Portland Group C compiler + whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive' + tmp_addflag=' $pic_flag' + ;; + pgf77* | pgf90* | pgf95*) # Portland Group f77 and f90 compilers + whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive' + tmp_addflag=' $pic_flag -Mnomain' ;; + ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 + tmp_addflag=' -i_dynamic' ;; + efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 + tmp_addflag=' -i_dynamic -nofor_main' ;; + ifc* | ifort*) # Intel Fortran compiler + tmp_addflag=' -nofor_main' ;; + lf95*) # Lahey Fortran 8.1 + whole_archive_flag_spec= + tmp_sharedflag='--shared' ;; + xl[cC]*) # IBM XL C 8.0 on PPC (deal with xlf below) + tmp_sharedflag='-qmkshrobj' + tmp_addflag= ;; + esac + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) # Sun C 5.9 + whole_archive_flag_spec='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive' + compiler_needs_object=yes + tmp_sharedflag='-G' ;; + *Sun\ F*) # Sun Fortran 8.3 + tmp_sharedflag='-G' ;; + esac + archive_cmds='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + + if test "x$supports_anon_versioning" = xyes; then + archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' + fi + + case $cc_basename in + xlf*) + # IBM XL Fortran 10.1 on PPC cannot create shared libs itself + whole_archive_flag_spec='--whole-archive$convenience --no-whole-archive' + hardcode_libdir_flag_spec= + hardcode_libdir_flag_spec_ld='-rpath $libdir' + archive_cmds='$LD -shared $libobjs $deplibs $compiler_flags -soname $soname -o $lib' + if test "x$supports_anon_versioning" = xyes; then + archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $LD -shared $libobjs $deplibs $compiler_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' + fi + ;; + esac + else + ld_shlibs=no + fi + ;; + + netbsd* | netbsdelf*-gnu) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' + wlarc= + else + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + fi + ;; + + solaris*) + if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then + ld_shlibs=no + cat <<_LT_EOF 1>&2 + +*** Warning: The releases 2.8.* of the GNU linker cannot reliably +*** create shared libraries on Solaris systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.9.1 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + ld_shlibs=no + fi + ;; + + sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) + case `$LD -v 2>&1` in + *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*) + ld_shlibs=no + cat <<_LT_EOF 1>&2 + +*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not +*** reliably create shared libraries on SCO systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.16.91.0.3 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + ;; + *) + # For security reasons, it is highly recommended that you always + # use absolute paths for naming shared libraries, and exclude the + # DT_RUNPATH tag from executables and libraries. But doing so + # requires that you compile everything twice, which is a pain. + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + ld_shlibs=no + fi + ;; + esac + ;; + + sunos4*) + archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' + wlarc= + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + *) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + ld_shlibs=no + fi + ;; + esac + + if test "$ld_shlibs" = no; then + runpath_var= + hardcode_libdir_flag_spec= + export_dynamic_flag_spec= + whole_archive_flag_spec= + fi + else + # PORTME fill in a description of your system's linker (not GNU ld) + case $host_os in + aix3*) + allow_undefined_flag=unsupported + always_export_symbols=yes + archive_expsym_cmds='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' + # Note: this linker hardcodes the directories in LIBPATH if there + # are no directories specified by -L. + hardcode_minus_L=yes + if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then + # Neither direct hardcoding nor static linking is supported with a + # broken collect2. + hardcode_direct=unsupported + fi + ;; + + aix[4-9]*) + if test "$host_cpu" = ia64; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag="" + else + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to AIX nm, but means don't demangle with GNU nm + if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then + export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' + else + export_symbols_cmds='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' + fi + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # need to do runtime linking. + case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*) + for ld_flag in $LDFLAGS; do + if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then + aix_use_runtimelinking=yes + break + fi + done + ;; + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + archive_cmds='' + hardcode_direct=yes + hardcode_direct_absolute=yes + hardcode_libdir_separator=':' + link_all_deplibs=yes + file_list_spec='${wl}-f,' + + if test "$GCC" = yes; then + case $host_os in aix4.[012]|aix4.[012].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`${CC} -print-prog-name=collect2` + if test -f "$collect2name" && + strings "$collect2name" | $GREP resolve_lib_name >/dev/null + then + # We have reworked collect2 + : + else + # We have old collect2 + hardcode_direct=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + hardcode_minus_L=yes + hardcode_libdir_flag_spec='-L$libdir' + hardcode_libdir_separator= + fi + ;; + esac + shared_flag='-shared' + if test "$aix_use_runtimelinking" = yes; then + shared_flag="$shared_flag "'${wl}-G' + fi + link_all_deplibs=no + else + # not using gcc + if test "$host_cpu" = ia64; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test "$aix_use_runtimelinking" = yes; then + shared_flag='${wl}-G' + else + shared_flag='${wl}-bM:SRE' + fi + fi + fi + + export_dynamic_flag_spec='${wl}-bexpall' + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to export. + always_export_symbols=yes + if test "$aix_use_runtimelinking" = yes; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + allow_undefined_flag='-berok' + # Determine the default libpath from the value encoded in an + # empty executable. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + +lt_aix_libpath_sed=' + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\(.*\)$/\1/ + p + } + }' +aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` +# Check for a 64-bit object if we didn't find anything. +if test -z "$aix_libpath"; then + aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` +fi +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi + + hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" + archive_expsym_cmds='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then $ECHO "X${wl}${allow_undefined_flag}" | $Xsed; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" + else + if test "$host_cpu" = ia64; then + hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib' + allow_undefined_flag="-z nodefs" + archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an + # empty executable. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + +lt_aix_libpath_sed=' + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\(.*\)$/\1/ + p + } + }' +aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` +# Check for a 64-bit object if we didn't find anything. +if test -z "$aix_libpath"; then + aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` +fi +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi + + hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + no_undefined_flag=' ${wl}-bernotok' + allow_undefined_flag=' ${wl}-berok' + # Exported symbols can be pulled into shared objects from archives + whole_archive_flag_spec='$convenience' + archive_cmds_need_lc=yes + # This is similar to how AIX traditionally builds its shared libraries. + archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' + fi + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='' + ;; + m68k) + archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + ;; + esac + ;; + + bsdi[45]*) + export_dynamic_flag_spec=-rdynamic + ;; + + cygwin* | mingw* | pw32* | cegcc*) + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + hardcode_libdir_flag_spec=' ' + allow_undefined_flag=unsupported + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=".dll" + # FIXME: Setting linknames here is a bad hack. + archive_cmds='$CC -o $lib $libobjs $compiler_flags `$ECHO "X$deplibs" | $Xsed -e '\''s/ -lc$//'\''` -link -dll~linknames=' + # The linker will automatically build a .lib file if we build a DLL. + old_archive_from_new_cmds='true' + # FIXME: Should let the user specify the lib program. + old_archive_cmds='lib -OUT:$oldlib$oldobjs$old_deplibs' + fix_srcfile_path='`cygpath -w "$srcfile"`' + enable_shared_with_static_runtimes=yes + ;; + + darwin* | rhapsody*) + + + archive_cmds_need_lc=no + hardcode_direct=no + hardcode_automatic=yes + hardcode_shlibpath_var=unsupported + whole_archive_flag_spec='' + link_all_deplibs=yes + allow_undefined_flag="$_lt_dar_allow_undefined" + case $cc_basename in + ifort*) _lt_dar_can_shared=yes ;; + *) _lt_dar_can_shared=$GCC ;; + esac + if test "$_lt_dar_can_shared" = "yes"; then + output_verbose_link_cmd=echo + archive_cmds="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}" + module_cmds="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}" + archive_expsym_cmds="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}" + module_expsym_cmds="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}" + + else + ld_shlibs=no + fi + + ;; + + dgux*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_shlibpath_var=no + ;; + + freebsd1*) + ld_shlibs=no + ;; + + # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor + # support. Future versions do this automatically, but an explicit c++rt0.o + # does not break anything, and helps significantly (at the cost of a little + # extra space). + freebsd2.2*) + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + # Unfortunately, older versions of FreeBSD 2 do not have this feature. + freebsd2*) + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=yes + hardcode_minus_L=yes + hardcode_shlibpath_var=no + ;; + + # FreeBSD 3 and greater uses gcc -shared to do shared libraries. + freebsd* | dragonfly*) + archive_cmds='$CC -shared -o $lib $libobjs $deplibs $compiler_flags' + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + hpux9*) + if test "$GCC" = yes; then + archive_cmds='$RM $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + else + archive_cmds='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + fi + hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' + hardcode_libdir_separator=: + hardcode_direct=yes + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L=yes + export_dynamic_flag_spec='${wl}-E' + ;; + + hpux10*) + if test "$GCC" = yes -a "$with_gnu_ld" = no; then + archive_cmds='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' + fi + if test "$with_gnu_ld" = no; then + hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' + hardcode_libdir_flag_spec_ld='+b $libdir' + hardcode_libdir_separator=: + hardcode_direct=yes + hardcode_direct_absolute=yes + export_dynamic_flag_spec='${wl}-E' + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L=yes + fi + ;; + + hpux11*) + if test "$GCC" = yes -a "$with_gnu_ld" = no; then + case $host_cpu in + hppa*64*) + archive_cmds='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + archive_cmds='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + archive_cmds='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + else + case $host_cpu in + hppa*64*) + archive_cmds='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + fi + if test "$with_gnu_ld" = no; then + hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' + hardcode_libdir_separator=: + + case $host_cpu in + hppa*64*|ia64*) + hardcode_direct=no + hardcode_shlibpath_var=no + ;; + *) + hardcode_direct=yes + hardcode_direct_absolute=yes + export_dynamic_flag_spec='${wl}-E' + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L=yes + ;; + esac + fi + ;; + + irix5* | irix6* | nonstopux*) + if test "$GCC" = yes; then + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + # Try to use the -exported_symbol ld option, if it does not + # work, assume that -exports_file does not work either and + # implicitly export all symbols. + save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS -shared ${wl}-exported_symbol ${wl}foo ${wl}-update_registry ${wl}/dev/null" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +int foo(void) {} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations ${wl}-exports_file ${wl}$export_symbols -o $lib' + +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS="$save_LDFLAGS" + else + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib' + archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -exports_file $export_symbols -o $lib' + fi + archive_cmds_need_lc='no' + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator=: + inherit_rpath=yes + link_all_deplibs=yes + ;; + + netbsd* | netbsdelf*-gnu) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out + else + archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF + fi + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + newsos6) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=yes + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator=: + hardcode_shlibpath_var=no + ;; + + *nto* | *qnx*) + ;; + + openbsd*) + if test -f /usr/libexec/ld.so; then + hardcode_direct=yes + hardcode_shlibpath_var=no + hardcode_direct_absolute=yes + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' + hardcode_libdir_flag_spec='${wl}-rpath,$libdir' + export_dynamic_flag_spec='${wl}-E' + else + case $host_os in + openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*) + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec='-R$libdir' + ;; + *) + archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + hardcode_libdir_flag_spec='${wl}-rpath,$libdir' + ;; + esac + fi + else + ld_shlibs=no + fi + ;; + + os2*) + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + allow_undefined_flag=unsupported + archive_cmds='$ECHO "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$ECHO DATA >> $output_objdir/$libname.def~$ECHO " SINGLE NONSHARED" >> $output_objdir/$libname.def~$ECHO EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' + old_archive_from_new_cmds='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' + ;; + + osf3*) + if test "$GCC" = yes; then + allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' + archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + allow_undefined_flag=' -expect_unresolved \*' + archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib' + fi + archive_cmds_need_lc='no' + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator=: + ;; + + osf4* | osf5*) # as osf3* with the addition of -msym flag + if test "$GCC" = yes; then + allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' + archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + else + allow_undefined_flag=' -expect_unresolved \*' + archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib' + archive_expsym_cmds='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ + $CC -shared${allow_undefined_flag} ${wl}-input ${wl}$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib~$RM $lib.exp' + + # Both c and cxx compiler support -rpath directly + hardcode_libdir_flag_spec='-rpath $libdir' + fi + archive_cmds_need_lc='no' + hardcode_libdir_separator=: + ;; + + solaris*) + no_undefined_flag=' -z defs' + if test "$GCC" = yes; then + wlarc='${wl}' + archive_cmds='$CC -shared ${wl}-z ${wl}text ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -shared ${wl}-z ${wl}text ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + else + case `$CC -V 2>&1` in + *"Compilers 5.0"*) + wlarc='' + archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' + archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' + ;; + *) + wlarc='${wl}' + archive_cmds='$CC -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + ;; + esac + fi + hardcode_libdir_flag_spec='-R$libdir' + hardcode_shlibpath_var=no + case $host_os in + solaris2.[0-5] | solaris2.[0-5].*) ;; + *) + # The compiler driver will combine and reorder linker options, + # but understands `-z linker_flag'. GCC discards it without `$wl', + # but is careful enough not to reorder. + # Supported since Solaris 2.6 (maybe 2.5.1?) + if test "$GCC" = yes; then + whole_archive_flag_spec='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' + else + whole_archive_flag_spec='-z allextract$convenience -z defaultextract' + fi + ;; + esac + link_all_deplibs=yes + ;; + + sunos4*) + if test "x$host_vendor" = xsequent; then + # Use $CC to link under sequent, because it throws in some extra .o + # files that make .init and .fini sections work. + archive_cmds='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' + fi + hardcode_libdir_flag_spec='-L$libdir' + hardcode_direct=yes + hardcode_minus_L=yes + hardcode_shlibpath_var=no + ;; + + sysv4) + case $host_vendor in + sni) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=yes # is this really true??? + ;; + siemens) + ## LD is ld it makes a PLAMLIB + ## CC just makes a GrossModule. + archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags' + reload_cmds='$CC -r -o $output$reload_objs' + hardcode_direct=no + ;; + motorola) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=no #Motorola manual says yes, but my tests say they lie + ;; + esac + runpath_var='LD_RUN_PATH' + hardcode_shlibpath_var=no + ;; + + sysv4.3*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_shlibpath_var=no + export_dynamic_flag_spec='-Bexport' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_shlibpath_var=no + runpath_var=LD_RUN_PATH + hardcode_runpath_var=yes + ld_shlibs=yes + fi + ;; + + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) + no_undefined_flag='${wl}-z,text' + archive_cmds_need_lc=no + hardcode_shlibpath_var=no + runpath_var='LD_RUN_PATH' + + if test "$GCC" = yes; then + archive_cmds='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + sysv5* | sco3.2v5* | sco5v6*) + # Note: We can NOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + no_undefined_flag='${wl}-z,text' + allow_undefined_flag='${wl}-z,nodefs' + archive_cmds_need_lc=no + hardcode_shlibpath_var=no + hardcode_libdir_flag_spec='${wl}-R,$libdir' + hardcode_libdir_separator=':' + link_all_deplibs=yes + export_dynamic_flag_spec='${wl}-Bexport' + runpath_var='LD_RUN_PATH' + + if test "$GCC" = yes; then + archive_cmds='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + uts4*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_shlibpath_var=no + ;; + + *) + ld_shlibs=no + ;; + esac + + if test x$host_vendor = xsni; then + case $host in + sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) + export_dynamic_flag_spec='${wl}-Blargedynsym' + ;; + esac + fi + fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs" >&5 +$as_echo "$ld_shlibs" >&6; } +test "$ld_shlibs" = no && can_build_shared=no + +with_gnu_ld=$with_gnu_ld + + + + + + + + + + + + + + + +# +# Do we need to explicitly link libc? +# +case "x$archive_cmds_need_lc" in +x|xyes) + # Assume -lc should be added + archive_cmds_need_lc=yes + + if test "$enable_shared" = yes && test "$GCC" = yes; then + case $archive_cmds in + *'~'*) + # FIXME: we may have to deal with multi-command sequences. + ;; + '$CC '*) + # Test whether the compiler implicitly links with -lc since on some + # systems, -lgcc has to come before -lc. If gcc already passes -lc + # to ld, don't add -lc before -lgcc. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5 +$as_echo_n "checking whether -lc should be explicitly linked in... " >&6; } + $RM conftest* + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } 2>conftest.err; then + soname=conftest + lib=conftest + libobjs=conftest.$ac_objext + deplibs= + wl=$lt_prog_compiler_wl + pic_flag=$lt_prog_compiler_pic + compiler_flags=-v + linker_flags=-v + verstring= + output_objdir=. + libname=conftest + lt_save_allow_undefined_flag=$allow_undefined_flag + allow_undefined_flag= + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5 + (eval $archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + then + archive_cmds_need_lc=no + else + archive_cmds_need_lc=yes + fi + allow_undefined_flag=$lt_save_allow_undefined_flag + else + cat conftest.err 1>&5 + fi + $RM conftest* + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $archive_cmds_need_lc" >&5 +$as_echo "$archive_cmds_need_lc" >&6; } + ;; + esac + fi + ;; +esac + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5 +$as_echo_n "checking dynamic linker characteristics... " >&6; } + +if test "$GCC" = yes; then + case $host_os in + darwin*) lt_awk_arg="/^libraries:/,/LR/" ;; + *) lt_awk_arg="/^libraries:/" ;; + esac + lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e "s,=/,/,g"` + if $ECHO "$lt_search_path_spec" | $GREP ';' >/dev/null ; then + # if the path contains ";" then we assume it to be the separator + # otherwise default to the standard path separator (i.e. ":") - it is + # assumed that no part of a normal pathname contains ";" but that should + # okay in the real world where ";" in dirpaths is itself problematic. + lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED -e 's/;/ /g'` + else + lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi + # Ok, now we have the path, separated by spaces, we can step through it + # and add multilib dir if necessary. + lt_tmp_lt_search_path_spec= + lt_multi_os_dir=`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` + for lt_sys_path in $lt_search_path_spec; do + if test -d "$lt_sys_path/$lt_multi_os_dir"; then + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path/$lt_multi_os_dir" + else + test -d "$lt_sys_path" && \ + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" + fi + done + lt_search_path_spec=`$ECHO $lt_tmp_lt_search_path_spec | awk ' +BEGIN {RS=" "; FS="/|\n";} { + lt_foo=""; + lt_count=0; + for (lt_i = NF; lt_i > 0; lt_i--) { + if ($lt_i != "" && $lt_i != ".") { + if ($lt_i == "..") { + lt_count++; + } else { + if (lt_count == 0) { + lt_foo="/" $lt_i lt_foo; + } else { + lt_count--; + } + } + } + } + if (lt_foo != "") { lt_freq[lt_foo]++; } + if (lt_freq[lt_foo] == 1) { print lt_foo; } +}'` + sys_lib_search_path_spec=`$ECHO $lt_search_path_spec` +else + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" +fi +library_names_spec= +libname_spec='lib$name' +soname_spec= +shrext_cmds=".so" +postinstall_cmds= +postuninstall_cmds= +finish_cmds= +finish_eval= +shlibpath_var= +shlibpath_overrides_runpath=unknown +version_type=none +dynamic_linker="$host_os ld.so" +sys_lib_dlsearch_path_spec="/lib /usr/lib" +need_lib_prefix=unknown +hardcode_into_libs=no + +# when you set need_version to no, make sure it does not cause -set_version +# flags to be left without arguments +need_version=unknown + +case $host_os in +aix3*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' + shlibpath_var=LIBPATH + + # AIX 3 has no versioning support, so we append a major version to the name. + soname_spec='${libname}${release}${shared_ext}$major' + ;; + +aix[4-9]*) + version_type=linux + need_lib_prefix=no + need_version=no + hardcode_into_libs=yes + if test "$host_cpu" = ia64; then + # AIX 5 supports IA64 + library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + else + # With GCC up to 2.95.x, collect2 would create an import file + # for dependence libraries. The import file would start with + # the line `#! .'. This would cause the generated library to + # depend on `.', always an invalid library. This was fixed in + # development snapshots of GCC prior to 3.0. + case $host_os in + aix4 | aix4.[01] | aix4.[01].*) + if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' + echo ' yes ' + echo '#endif'; } | ${CC} -E - | $GREP yes > /dev/null; then + : + else + can_build_shared=no + fi + ;; + esac + # AIX (on Power*) has no versioning support, so currently we can not hardcode correct + # soname into executable. Probably we can add versioning support to + # collect2, so additional links can be useful in future. + if test "$aix_use_runtimelinking" = yes; then + # If using run time linking (on AIX 4.2 or later) use lib.so + # instead of lib.a to let people know that these are not + # typical AIX shared libraries. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + else + # We preserve .a as extension for shared libraries through AIX4.2 + # and later when we are not doing run time linking. + library_names_spec='${libname}${release}.a $libname.a' + soname_spec='${libname}${release}${shared_ext}$major' + fi + shlibpath_var=LIBPATH + fi + ;; + +amigaos*) + case $host_cpu in + powerpc) + # Since July 2007 AmigaOS4 officially supports .so libraries. + # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + ;; + m68k) + library_names_spec='$libname.ixlibrary $libname.a' + # Create ${libname}_ixlibrary.a entries in /sys/libs. + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$ECHO "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' + ;; + esac + ;; + +beos*) + library_names_spec='${libname}${shared_ext}' + dynamic_linker="$host_os ld.so" + shlibpath_var=LIBRARY_PATH + ;; + +bsdi[45]*) + version_type=linux + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" + sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" + # the default ld.so.conf also contains /usr/contrib/lib and + # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow + # libtool to hard-code these into programs + ;; + +cygwin* | mingw* | pw32* | cegcc*) + version_type=windows + shrext_cmds=".dll" + need_version=no + need_lib_prefix=no + + case $GCC,$host_os in + yes,cygwin* | yes,mingw* | yes,pw32* | yes,cegcc*) + library_names_spec='$libname.dll.a' + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \${file}`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname~ + if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then + eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; + fi' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + shlibpath_overrides_runpath=yes + + case $host_os in + cygwin*) + # Cygwin DLLs use 'cyg' prefix rather than 'lib' + soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib" + ;; + mingw* | cegcc*) + # MinGW DLLs use traditional 'lib' prefix + soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + sys_lib_search_path_spec=`$CC -print-search-dirs | $GREP "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` + if $ECHO "$sys_lib_search_path_spec" | $GREP ';[c-zC-Z]:/' >/dev/null; then + # It is most probably a Windows format PATH printed by + # mingw gcc, but we are running on Cygwin. Gcc prints its search + # path with ; separators, and with drive letters. We can handle the + # drive letters (cygwin fileutils understands them), so leave them, + # especially as we might pass files found there to a mingw objdump, + # which wouldn't understand a cygwinified path. Ahh. + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi + ;; + pw32*) + # pw32 DLLs use 'pw' prefix rather than 'lib' + library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + ;; + esac + ;; + + *) + library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib' + ;; + esac + dynamic_linker='Win32 ld.exe' + # FIXME: first we should search . and the directory the executable is in + shlibpath_var=PATH + ;; + +darwin* | rhapsody*) + dynamic_linker="$host_os dyld" + version_type=darwin + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${major}$shared_ext ${libname}$shared_ext' + soname_spec='${libname}${release}${major}$shared_ext' + shlibpath_overrides_runpath=yes + shlibpath_var=DYLD_LIBRARY_PATH + shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' + + sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib" + sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' + ;; + +dgux*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +freebsd1*) + dynamic_linker=no + ;; + +freebsd* | dragonfly*) + # DragonFly does not have aout. When/if they implement a new + # versioning mechanism, adjust this. + if test -x /usr/bin/objformat; then + objformat=`/usr/bin/objformat` + else + case $host_os in + freebsd[123]*) objformat=aout ;; + *) objformat=elf ;; + esac + fi + version_type=freebsd-$objformat + case $version_type in + freebsd-elf*) + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + need_version=no + need_lib_prefix=no + ;; + freebsd-*) + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' + need_version=yes + ;; + esac + shlibpath_var=LD_LIBRARY_PATH + case $host_os in + freebsd2*) + shlibpath_overrides_runpath=yes + ;; + freebsd3.[01]* | freebsdelf3.[01]*) + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ + freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + *) # from 4.6 on, and DragonFly + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + esac + ;; + +gnu*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + hardcode_into_libs=yes + ;; + +hpux9* | hpux10* | hpux11*) + # Give a soname corresponding to the major version so that dld.sl refuses to + # link against other versions. + version_type=sunos + need_lib_prefix=no + need_version=no + case $host_cpu in + ia64*) + shrext_cmds='.so' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.so" + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + if test "X$HPUX_IA64_MODE" = X32; then + sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" + else + sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" + fi + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + hppa*64*) + shrext_cmds='.sl' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.sl" + shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + *) + shrext_cmds='.sl' + dynamic_linker="$host_os dld.sl" + shlibpath_var=SHLIB_PATH + shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + ;; + esac + # HP-UX runs *really* slowly unless shared libraries are mode 555. + postinstall_cmds='chmod 555 $lib' + ;; + +interix[3-9]*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +irix5* | irix6* | nonstopux*) + case $host_os in + nonstopux*) version_type=nonstopux ;; + *) + if test "$lt_cv_prog_gnu_ld" = yes; then + version_type=linux + else + version_type=irix + fi ;; + esac + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' + case $host_os in + irix5* | nonstopux*) + libsuff= shlibsuff= + ;; + *) + case $LD in # libtool.m4 will add one of these switches to LD + *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") + libsuff= shlibsuff= libmagic=32-bit;; + *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") + libsuff=32 shlibsuff=N32 libmagic=N32;; + *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") + libsuff=64 shlibsuff=64 libmagic=64-bit;; + *) libsuff= shlibsuff= libmagic=never-match;; + esac + ;; + esac + shlibpath_var=LD_LIBRARY${shlibsuff}_PATH + shlibpath_overrides_runpath=no + sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" + sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" + hardcode_into_libs=yes + ;; + +# No shared lib support for Linux oldld, aout, or coff. +linux*oldld* | linux*aout* | linux*coff*) + dynamic_linker=no + ;; + +# This must be Linux ELF. +linux* | k*bsd*-gnu | kopensolaris*-gnu) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + # Some binutils ld are patched to set DT_RUNPATH + save_LDFLAGS=$LDFLAGS + save_libdir=$libdir + eval "libdir=/foo; wl=\"$lt_prog_compiler_wl\"; \ + LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec\"" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + if ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null; then : + shlibpath_overrides_runpath=yes +fi +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS=$save_LDFLAGS + libdir=$save_libdir + + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + # Append ld.so.conf contents to the search path + if test -f /etc/ld.so.conf; then + lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '` + sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" + fi + + # We used to test for /lib/ld.so.1 and disable shared libraries on + # powerpc, because MkLinux only supported shared libraries with the + # GNU dynamic linker. Since this was broken with cross compilers, + # most powerpc-linux boxes support dynamic linking these days and + # people can always --disable-shared, the test was removed, and we + # assume the GNU/Linux dynamic linker is in use. + dynamic_linker='GNU/Linux ld.so' + ;; + +netbsdelf*-gnu) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='NetBSD ld.elf_so' + ;; + +netbsd*) + version_type=sunos + need_lib_prefix=no + need_version=no + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + dynamic_linker='NetBSD (a.out) ld.so' + else + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='NetBSD ld.elf_so' + fi + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + +newsos6) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +*nto* | *qnx*) + version_type=qnx + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='ldqnx.so' + ;; + +openbsd*) + version_type=sunos + sys_lib_dlsearch_path_spec="/usr/lib" + need_lib_prefix=no + # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. + case $host_os in + openbsd3.3 | openbsd3.3.*) need_version=yes ;; + *) need_version=no ;; + esac + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + shlibpath_var=LD_LIBRARY_PATH + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + case $host_os in + openbsd2.[89] | openbsd2.[89].*) + shlibpath_overrides_runpath=no + ;; + *) + shlibpath_overrides_runpath=yes + ;; + esac + else + shlibpath_overrides_runpath=yes + fi + ;; + +os2*) + libname_spec='$name' + shrext_cmds=".dll" + need_lib_prefix=no + library_names_spec='$libname${shared_ext} $libname.a' + dynamic_linker='OS/2 ld.exe' + shlibpath_var=LIBPATH + ;; + +osf3* | osf4* | osf5*) + version_type=osf + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" + sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" + ;; + +rdos*) + dynamic_linker=no + ;; + +solaris*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + # ldd complains unless libraries are executable + postinstall_cmds='chmod +x $lib' + ;; + +sunos4*) + version_type=sunos + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + if test "$with_gnu_ld" = yes; then + need_lib_prefix=no + fi + need_version=yes + ;; + +sysv4 | sysv4.3*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + case $host_vendor in + sni) + shlibpath_overrides_runpath=no + need_lib_prefix=no + runpath_var=LD_RUN_PATH + ;; + siemens) + need_lib_prefix=no + ;; + motorola) + need_lib_prefix=no + need_version=no + shlibpath_overrides_runpath=no + sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' + ;; + esac + ;; + +sysv4*MP*) + if test -d /usr/nec ;then + version_type=linux + library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' + soname_spec='$libname${shared_ext}.$major' + shlibpath_var=LD_LIBRARY_PATH + fi + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + version_type=freebsd-elf + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + if test "$with_gnu_ld" = yes; then + sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' + else + sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' + case $host_os in + sco3.2v5*) + sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" + ;; + esac + fi + sys_lib_dlsearch_path_spec='/usr/lib' + ;; + +tpf*) + # TPF is a cross-target only. Preferred cross-host = GNU/Linux. + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +uts4*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +*) + dynamic_linker=no + ;; +esac +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5 +$as_echo "$dynamic_linker" >&6; } +test "$dynamic_linker" = no && can_build_shared=no + +variables_saved_for_relink="PATH $shlibpath_var $runpath_var" +if test "$GCC" = yes; then + variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" +fi + +if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then + sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec" +fi +if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then + sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec" +fi + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs" >&5 +$as_echo_n "checking how to hardcode library paths into programs... " >&6; } +hardcode_action= +if test -n "$hardcode_libdir_flag_spec" || + test -n "$runpath_var" || + test "X$hardcode_automatic" = "Xyes" ; then + + # We can hardcode non-existent directories. + if test "$hardcode_direct" != no && + # If the only mechanism to avoid hardcoding is shlibpath_var, we + # have to relink, otherwise we might link with an installed library + # when we should be linking with a yet-to-be-installed one + ## test "$_LT_TAGVAR(hardcode_shlibpath_var, )" != no && + test "$hardcode_minus_L" != no; then + # Linking always hardcodes the temporary library directory. + hardcode_action=relink + else + # We can link without hardcoding, and we can hardcode nonexisting dirs. + hardcode_action=immediate + fi +else + # We cannot hardcode anything, or else we can only hardcode existing + # directories. + hardcode_action=unsupported +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $hardcode_action" >&5 +$as_echo "$hardcode_action" >&6; } + +if test "$hardcode_action" = relink || + test "$inherit_rpath" = yes; then + # Fast installation is not supported + enable_fast_install=no +elif test "$shlibpath_overrides_runpath" = yes || + test "$enable_shared" = no; then + # Fast installation is not necessary + enable_fast_install=needless +fi + + + + + + + if test "x$enable_dlopen" != xyes; then + enable_dlopen=unknown + enable_dlopen_self=unknown + enable_dlopen_self_static=unknown +else + lt_cv_dlopen=no + lt_cv_dlopen_libs= + + case $host_os in + beos*) + lt_cv_dlopen="load_add_on" + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ;; + + mingw* | pw32* | cegcc*) + lt_cv_dlopen="LoadLibrary" + lt_cv_dlopen_libs= + ;; + + cygwin*) + lt_cv_dlopen="dlopen" + lt_cv_dlopen_libs= + ;; + + darwin*) + # if libdl is installed we need to link against it + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 +$as_echo_n "checking for dlopen in -ldl... " >&6; } +if test "${ac_cv_lib_dl_dlopen+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldl $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dlopen (); +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dl_dlopen=yes +else + ac_cv_lib_dl_dlopen=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 +$as_echo "$ac_cv_lib_dl_dlopen" >&6; } +if test "x$ac_cv_lib_dl_dlopen" = x""yes; then : + lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" +else + + lt_cv_dlopen="dyld" + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + +fi + + ;; + + *) + ac_fn_c_check_func "$LINENO" "shl_load" "ac_cv_func_shl_load" +if test "x$ac_cv_func_shl_load" = x""yes; then : + lt_cv_dlopen="shl_load" +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld" >&5 +$as_echo_n "checking for shl_load in -ldld... " >&6; } +if test "${ac_cv_lib_dld_shl_load+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldld $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char shl_load (); +int +main () +{ +return shl_load (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dld_shl_load=yes +else + ac_cv_lib_dld_shl_load=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load" >&5 +$as_echo "$ac_cv_lib_dld_shl_load" >&6; } +if test "x$ac_cv_lib_dld_shl_load" = x""yes; then : + lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld" +else + ac_fn_c_check_func "$LINENO" "dlopen" "ac_cv_func_dlopen" +if test "x$ac_cv_func_dlopen" = x""yes; then : + lt_cv_dlopen="dlopen" +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 +$as_echo_n "checking for dlopen in -ldl... " >&6; } +if test "${ac_cv_lib_dl_dlopen+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldl $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dlopen (); +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dl_dlopen=yes +else + ac_cv_lib_dl_dlopen=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 +$as_echo "$ac_cv_lib_dl_dlopen" >&6; } +if test "x$ac_cv_lib_dl_dlopen" = x""yes; then : + lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -lsvld" >&5 +$as_echo_n "checking for dlopen in -lsvld... " >&6; } +if test "${ac_cv_lib_svld_dlopen+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lsvld $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dlopen (); +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_svld_dlopen=yes +else + ac_cv_lib_svld_dlopen=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_svld_dlopen" >&5 +$as_echo "$ac_cv_lib_svld_dlopen" >&6; } +if test "x$ac_cv_lib_svld_dlopen" = x""yes; then : + lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld" +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dld_link in -ldld" >&5 +$as_echo_n "checking for dld_link in -ldld... " >&6; } +if test "${ac_cv_lib_dld_dld_link+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldld $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dld_link (); +int +main () +{ +return dld_link (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dld_dld_link=yes +else + ac_cv_lib_dld_dld_link=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_dld_link" >&5 +$as_echo "$ac_cv_lib_dld_dld_link" >&6; } +if test "x$ac_cv_lib_dld_dld_link" = x""yes; then : + lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld" +fi + + +fi + + +fi + + +fi + + +fi + + +fi + + ;; + esac + + if test "x$lt_cv_dlopen" != xno; then + enable_dlopen=yes + else + enable_dlopen=no + fi + + case $lt_cv_dlopen in + dlopen) + save_CPPFLAGS="$CPPFLAGS" + test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" + + save_LDFLAGS="$LDFLAGS" + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" + + save_LIBS="$LIBS" + LIBS="$lt_cv_dlopen_libs $LIBS" + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a program can dlopen itself" >&5 +$as_echo_n "checking whether a program can dlopen itself... " >&6; } +if test "${lt_cv_dlopen_self+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test "$cross_compiling" = yes; then : + lt_cv_dlopen_self=cross +else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext <<_LT_EOF +#line 11234 "configure" +#include "confdefs.h" + +#if HAVE_DLFCN_H +#include +#endif + +#include + +#ifdef RTLD_GLOBAL +# define LT_DLGLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LT_DLGLOBAL DL_GLOBAL +# else +# define LT_DLGLOBAL 0 +# endif +#endif + +/* We may have to define LT_DLLAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LT_DLLAZY_OR_NOW +# ifdef RTLD_LAZY +# define LT_DLLAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LT_DLLAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LT_DLLAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LT_DLLAZY_OR_NOW DL_NOW +# else +# define LT_DLLAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +void fnord() { int i=42;} +int main () +{ + void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); + int status = $lt_dlunknown; + + if (self) + { + if (dlsym (self,"fnord")) status = $lt_dlno_uscore; + else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + /* dlclose (self); */ + } + else + puts (dlerror ()); + + return status; +} +_LT_EOF + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 + (eval $ac_link) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && test -s conftest${ac_exeext} 2>/dev/null; then + (./conftest; exit; ) >&5 2>/dev/null + lt_status=$? + case x$lt_status in + x$lt_dlno_uscore) lt_cv_dlopen_self=yes ;; + x$lt_dlneed_uscore) lt_cv_dlopen_self=yes ;; + x$lt_dlunknown|x*) lt_cv_dlopen_self=no ;; + esac + else : + # compilation failed + lt_cv_dlopen_self=no + fi +fi +rm -fr conftest* + + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self" >&5 +$as_echo "$lt_cv_dlopen_self" >&6; } + + if test "x$lt_cv_dlopen_self" = xyes; then + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a statically linked program can dlopen itself" >&5 +$as_echo_n "checking whether a statically linked program can dlopen itself... " >&6; } +if test "${lt_cv_dlopen_self_static+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test "$cross_compiling" = yes; then : + lt_cv_dlopen_self_static=cross +else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext <<_LT_EOF +#line 11330 "configure" +#include "confdefs.h" + +#if HAVE_DLFCN_H +#include +#endif + +#include + +#ifdef RTLD_GLOBAL +# define LT_DLGLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LT_DLGLOBAL DL_GLOBAL +# else +# define LT_DLGLOBAL 0 +# endif +#endif + +/* We may have to define LT_DLLAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LT_DLLAZY_OR_NOW +# ifdef RTLD_LAZY +# define LT_DLLAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LT_DLLAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LT_DLLAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LT_DLLAZY_OR_NOW DL_NOW +# else +# define LT_DLLAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +void fnord() { int i=42;} +int main () +{ + void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); + int status = $lt_dlunknown; + + if (self) + { + if (dlsym (self,"fnord")) status = $lt_dlno_uscore; + else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + /* dlclose (self); */ + } + else + puts (dlerror ()); + + return status; +} +_LT_EOF + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 + (eval $ac_link) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && test -s conftest${ac_exeext} 2>/dev/null; then + (./conftest; exit; ) >&5 2>/dev/null + lt_status=$? + case x$lt_status in + x$lt_dlno_uscore) lt_cv_dlopen_self_static=yes ;; + x$lt_dlneed_uscore) lt_cv_dlopen_self_static=yes ;; + x$lt_dlunknown|x*) lt_cv_dlopen_self_static=no ;; + esac + else : + # compilation failed + lt_cv_dlopen_self_static=no + fi +fi +rm -fr conftest* + + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self_static" >&5 +$as_echo "$lt_cv_dlopen_self_static" >&6; } + fi + + CPPFLAGS="$save_CPPFLAGS" + LDFLAGS="$save_LDFLAGS" + LIBS="$save_LIBS" + ;; + esac + + case $lt_cv_dlopen_self in + yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; + *) enable_dlopen_self=unknown ;; + esac + + case $lt_cv_dlopen_self_static in + yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; + *) enable_dlopen_self_static=unknown ;; + esac +fi + + + + + + + + + + + + + + + + + +striplib= +old_striplib= +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether stripping libraries is possible" >&5 +$as_echo_n "checking whether stripping libraries is possible... " >&6; } +if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then + test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" + test -z "$striplib" && striplib="$STRIP --strip-unneeded" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else +# FIXME - insert some real tests, host_os isn't really good enough + case $host_os in + darwin*) + if test -n "$STRIP" ; then + striplib="$STRIP -x" + old_striplib="$STRIP -S" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + fi + ;; + *) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + ;; + esac +fi + + + + + + + + + + + + + # Report which library types will actually be built + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if libtool supports shared libraries" >&5 +$as_echo_n "checking if libtool supports shared libraries... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $can_build_shared" >&5 +$as_echo "$can_build_shared" >&6; } + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build shared libraries" >&5 +$as_echo_n "checking whether to build shared libraries... " >&6; } + test "$can_build_shared" = "no" && enable_shared=no + + # On AIX, shared libraries and static libraries use the same namespace, and + # are all built from PIC. + case $host_os in + aix3*) + test "$enable_shared" = yes && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + + aix[4-9]*) + if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then + test "$enable_shared" = yes && enable_static=no + fi + ;; + esac + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_shared" >&5 +$as_echo "$enable_shared" >&6; } + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build static libraries" >&5 +$as_echo_n "checking whether to build static libraries... " >&6; } + # Make sure either enable_shared or enable_static is yes. + test "$enable_shared" = yes || enable_static=yes + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_static" >&5 +$as_echo "$enable_static" >&6; } + + + + +fi +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +CC="$lt_save_CC" + + +ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + +archive_cmds_need_lc_CXX=no +allow_undefined_flag_CXX= +always_export_symbols_CXX=no +archive_expsym_cmds_CXX= +compiler_needs_object_CXX=no +export_dynamic_flag_spec_CXX= +hardcode_direct_CXX=no +hardcode_direct_absolute_CXX=no +hardcode_libdir_flag_spec_CXX= +hardcode_libdir_flag_spec_ld_CXX= +hardcode_libdir_separator_CXX= +hardcode_minus_L_CXX=no +hardcode_shlibpath_var_CXX=unsupported +hardcode_automatic_CXX=no +inherit_rpath_CXX=no +module_cmds_CXX= +module_expsym_cmds_CXX= +link_all_deplibs_CXX=unknown +old_archive_cmds_CXX=$old_archive_cmds +no_undefined_flag_CXX= +whole_archive_flag_spec_CXX= +enable_shared_with_static_runtimes_CXX=no + +# Source file extension for C++ test sources. +ac_ext=cpp + +# Object file extension for compiled C++ test sources. +objext=o +objext_CXX=$objext + +# No sense in running all these tests if we already determined that +# the CXX compiler isn't working. Some variables (like enable_shared) +# are currently assumed to apply to all compilers on this platform, +# and will be corrupted by setting them based on a non-working compiler. +if test "$_lt_caught_CXX_error" != yes; then + # Code to be used in simple compile tests + lt_simple_compile_test_code="int some_variable = 0;" + + # Code to be used in simple link tests + lt_simple_link_test_code='int main(int, char *[]) { return(0); }' + + # ltmain only uses $CC for tagged configurations so make sure $CC is set. + + + + + + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC + + + # save warnings/boilerplate of simple test code + ac_outfile=conftest.$ac_objext +echo "$lt_simple_compile_test_code" >conftest.$ac_ext +eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_compiler_boilerplate=`cat conftest.err` +$RM conftest* + + ac_outfile=conftest.$ac_objext +echo "$lt_simple_link_test_code" >conftest.$ac_ext +eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_linker_boilerplate=`cat conftest.err` +$RM -r conftest* + + + # Allow CC to be a program name with arguments. + lt_save_CC=$CC + lt_save_LD=$LD + lt_save_GCC=$GCC + GCC=$GXX + lt_save_with_gnu_ld=$with_gnu_ld + lt_save_path_LD=$lt_cv_path_LD + if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then + lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx + else + $as_unset lt_cv_prog_gnu_ld + fi + if test -n "${lt_cv_path_LDCXX+set}"; then + lt_cv_path_LD=$lt_cv_path_LDCXX + else + $as_unset lt_cv_path_LD + fi + test -z "${LDCXX+set}" || LD=$LDCXX + CC=${CXX-"c++"} + compiler=$CC + compiler_CXX=$CC + for cc_temp in $compiler""; do + case $cc_temp in + compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; + distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; + \-*) ;; + *) break;; + esac +done +cc_basename=`$ECHO "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` + + + if test -n "$compiler"; then + # We don't want -fno-exception when compiling C++ code, so set the + # no_builtin_flag separately + if test "$GXX" = yes; then + lt_prog_compiler_no_builtin_flag_CXX=' -fno-builtin' + else + lt_prog_compiler_no_builtin_flag_CXX= + fi + + if test "$GXX" = yes; then + # Set up default GNU C++ configuration + + + +# Check whether --with-gnu-ld was given. +if test "${with_gnu_ld+set}" = set; then : + withval=$with_gnu_ld; test "$withval" = no || with_gnu_ld=yes +else + with_gnu_ld=no +fi + +ac_prog=ld +if test "$GCC" = yes; then + # Check if gcc -print-prog-name=ld gives a path. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5 +$as_echo_n "checking for ld used by $CC... " >&6; } + case $host in + *-*-mingw*) + # gcc leaves a trailing carriage return which upsets mingw + ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; + *) + ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; + esac + case $ac_prog in + # Accept absolute paths. + [\\/]* | ?:[\\/]*) + re_direlt='/[^/][^/]*/\.\./' + # Canonicalize the pathname of ld + ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` + while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do + ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` + done + test -z "$LD" && LD="$ac_prog" + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test "$with_gnu_ld" = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5 +$as_echo_n "checking for GNU ld... " >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5 +$as_echo_n "checking for non-GNU ld... " >&6; } +fi +if test "${lt_cv_path_LD+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$LD"; then + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then + lt_cv_path_LD="$ac_dir/$ac_prog" + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some variants of GNU ld only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + case `"$lt_cv_path_LD" -v 2>&1 &5 +$as_echo "$LD" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +test -z "$LD" && as_fn_error "no acceptable ld found in \$PATH" "$LINENO" 5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5 +$as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; } +if test "${lt_cv_prog_gnu_ld+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + # I'd rather use --version here, but apparently some GNU lds only accept -v. +case `$LD -v 2>&1 &5 +$as_echo "$lt_cv_prog_gnu_ld" >&6; } +with_gnu_ld=$lt_cv_prog_gnu_ld + + + + + + + + # Check if GNU C++ uses GNU ld as the underlying linker, since the + # archiving commands below assume that GNU ld is being used. + if test "$with_gnu_ld" = yes; then + archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + + hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir' + export_dynamic_flag_spec_CXX='${wl}--export-dynamic' + + # If archive_cmds runs LD, not CC, wlarc should be empty + # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to + # investigate it a little bit more. (MM) + wlarc='${wl}' + + # ancient GNU ld didn't support --whole-archive et. al. + if eval "`$CC -print-prog-name=ld` --help 2>&1" | + $GREP 'no-whole-archive' > /dev/null; then + whole_archive_flag_spec_CXX="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + else + whole_archive_flag_spec_CXX= + fi + else + with_gnu_ld=no + wlarc= + + # A generic and very simple default shared library creation + # command for GNU C++ for the case where it uses the native + # linker, instead of GNU ld. If possible, this setting should + # overridden to take advantage of the native linker features on + # the platform it is being used on. + archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' + fi + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "\-L"' + + else + GXX=no + with_gnu_ld=no + wlarc= + fi + + # PORTME: fill in a description of your system's C++ link characteristics + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5 +$as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; } + ld_shlibs_CXX=yes + case $host_os in + aix3*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + aix[4-9]*) + if test "$host_cpu" = ia64; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag="" + else + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # need to do runtime linking. + case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*) + for ld_flag in $LDFLAGS; do + case $ld_flag in + *-brtl*) + aix_use_runtimelinking=yes + break + ;; + esac + done + ;; + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + archive_cmds_CXX='' + hardcode_direct_CXX=yes + hardcode_direct_absolute_CXX=yes + hardcode_libdir_separator_CXX=':' + link_all_deplibs_CXX=yes + file_list_spec_CXX='${wl}-f,' + + if test "$GXX" = yes; then + case $host_os in aix4.[012]|aix4.[012].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`${CC} -print-prog-name=collect2` + if test -f "$collect2name" && + strings "$collect2name" | $GREP resolve_lib_name >/dev/null + then + # We have reworked collect2 + : + else + # We have old collect2 + hardcode_direct_CXX=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + hardcode_minus_L_CXX=yes + hardcode_libdir_flag_spec_CXX='-L$libdir' + hardcode_libdir_separator_CXX= + fi + esac + shared_flag='-shared' + if test "$aix_use_runtimelinking" = yes; then + shared_flag="$shared_flag "'${wl}-G' + fi + else + # not using gcc + if test "$host_cpu" = ia64; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test "$aix_use_runtimelinking" = yes; then + shared_flag='${wl}-G' + else + shared_flag='${wl}-bM:SRE' + fi + fi + fi + + export_dynamic_flag_spec_CXX='${wl}-bexpall' + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to + # export. + always_export_symbols_CXX=yes + if test "$aix_use_runtimelinking" = yes; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + allow_undefined_flag_CXX='-berok' + # Determine the default libpath from the value encoded in an empty + # executable. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + +lt_aix_libpath_sed=' + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\(.*\)$/\1/ + p + } + }' +aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` +# Check for a 64-bit object if we didn't find anything. +if test -z "$aix_libpath"; then + aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` +fi +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi + + hardcode_libdir_flag_spec_CXX='${wl}-blibpath:$libdir:'"$aix_libpath" + + archive_expsym_cmds_CXX='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then $ECHO "X${wl}${allow_undefined_flag}" | $Xsed; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" + else + if test "$host_cpu" = ia64; then + hardcode_libdir_flag_spec_CXX='${wl}-R $libdir:/usr/lib:/lib' + allow_undefined_flag_CXX="-z nodefs" + archive_expsym_cmds_CXX="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an + # empty executable. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + +lt_aix_libpath_sed=' + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\(.*\)$/\1/ + p + } + }' +aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` +# Check for a 64-bit object if we didn't find anything. +if test -z "$aix_libpath"; then + aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` +fi +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi + + hardcode_libdir_flag_spec_CXX='${wl}-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + no_undefined_flag_CXX=' ${wl}-bernotok' + allow_undefined_flag_CXX=' ${wl}-berok' + # Exported symbols can be pulled into shared objects from archives + whole_archive_flag_spec_CXX='$convenience' + archive_cmds_need_lc_CXX=yes + # This is similar to how AIX traditionally builds its shared + # libraries. + archive_expsym_cmds_CXX="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' + fi + fi + ;; + + beos*) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + allow_undefined_flag_CXX=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + archive_cmds_CXX='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + else + ld_shlibs_CXX=no + fi + ;; + + chorus*) + case $cc_basename in + *) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + esac + ;; + + cygwin* | mingw* | pw32* | cegcc*) + # _LT_TAGVAR(hardcode_libdir_flag_spec, CXX) is actually meaningless, + # as there is no search path for DLLs. + hardcode_libdir_flag_spec_CXX='-L$libdir' + allow_undefined_flag_CXX=unsupported + always_export_symbols_CXX=no + enable_shared_with_static_runtimes_CXX=yes + + if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then + archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file (1st line + # is EXPORTS), use it as is; otherwise, prepend... + archive_expsym_cmds_CXX='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + ld_shlibs_CXX=no + fi + ;; + darwin* | rhapsody*) + + + archive_cmds_need_lc_CXX=no + hardcode_direct_CXX=no + hardcode_automatic_CXX=yes + hardcode_shlibpath_var_CXX=unsupported + whole_archive_flag_spec_CXX='' + link_all_deplibs_CXX=yes + allow_undefined_flag_CXX="$_lt_dar_allow_undefined" + case $cc_basename in + ifort*) _lt_dar_can_shared=yes ;; + *) _lt_dar_can_shared=$GCC ;; + esac + if test "$_lt_dar_can_shared" = "yes"; then + output_verbose_link_cmd=echo + archive_cmds_CXX="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}" + module_cmds_CXX="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}" + archive_expsym_cmds_CXX="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}" + module_expsym_cmds_CXX="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}" + if test "$lt_cv_apple_cc_single_mod" != "yes"; then + archive_cmds_CXX="\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dsymutil}" + archive_expsym_cmds_CXX="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dar_export_syms}${_lt_dsymutil}" + fi + + else + ld_shlibs_CXX=no + fi + + ;; + + dgux*) + case $cc_basename in + ec++*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + ghcx*) + # Green Hills C++ Compiler + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + *) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + esac + ;; + + freebsd[12]*) + # C++ shared libraries reported to be fairly broken before + # switch to ELF + ld_shlibs_CXX=no + ;; + + freebsd-elf*) + archive_cmds_need_lc_CXX=no + ;; + + freebsd* | dragonfly*) + # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF + # conventions + ld_shlibs_CXX=yes + ;; + + gnu*) + ;; + + hpux9*) + hardcode_libdir_flag_spec_CXX='${wl}+b ${wl}$libdir' + hardcode_libdir_separator_CXX=: + export_dynamic_flag_spec_CXX='${wl}-E' + hardcode_direct_CXX=yes + hardcode_minus_L_CXX=yes # Not in the search PATH, + # but as the default + # location of the library. + + case $cc_basename in + CC*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + aCC*) + archive_cmds_CXX='$RM $output_objdir/$soname~$CC -b ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; $ECHO "X$list" | $Xsed' + ;; + *) + if test "$GXX" = yes; then + archive_cmds_CXX='$RM $output_objdir/$soname~$CC -shared -nostdlib -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + else + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + fi + ;; + esac + ;; + + hpux10*|hpux11*) + if test $with_gnu_ld = no; then + hardcode_libdir_flag_spec_CXX='${wl}+b ${wl}$libdir' + hardcode_libdir_separator_CXX=: + + case $host_cpu in + hppa*64*|ia64*) + ;; + *) + export_dynamic_flag_spec_CXX='${wl}-E' + ;; + esac + fi + case $host_cpu in + hppa*64*|ia64*) + hardcode_direct_CXX=no + hardcode_shlibpath_var_CXX=no + ;; + *) + hardcode_direct_CXX=yes + hardcode_direct_absolute_CXX=yes + hardcode_minus_L_CXX=yes # Not in the search PATH, + # but as the default + # location of the library. + ;; + esac + + case $cc_basename in + CC*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + aCC*) + case $host_cpu in + hppa*64*) + archive_cmds_CXX='$CC -b ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + ia64*) + archive_cmds_CXX='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + *) + archive_cmds_CXX='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + esac + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; $ECHO "X$list" | $Xsed' + ;; + *) + if test "$GXX" = yes; then + if test $with_gnu_ld = no; then + case $host_cpu in + hppa*64*) + archive_cmds_CXX='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + ia64*) + archive_cmds_CXX='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + *) + archive_cmds_CXX='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + esac + fi + else + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + fi + ;; + esac + ;; + + interix[3-9]*) + hardcode_direct_CXX=no + hardcode_shlibpath_var_CXX=no + hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' + export_dynamic_flag_spec_CXX='${wl}-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + archive_cmds_CXX='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + archive_expsym_cmds_CXX='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + irix5* | irix6*) + case $cc_basename in + CC*) + # SGI C++ + archive_cmds_CXX='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib' + + # Archives containing C++ object files must be created using + # "CC -ar", where "CC" is the IRIX C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + old_archive_cmds_CXX='$CC -ar -WR,-u -o $oldlib $oldobjs' + ;; + *) + if test "$GXX" = yes; then + if test "$with_gnu_ld" = no; then + archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` -o $lib' + fi + fi + link_all_deplibs_CXX=yes + ;; + esac + hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator_CXX=: + inherit_rpath_CXX=yes + ;; + + linux* | k*bsd*-gnu | kopensolaris*-gnu) + case $cc_basename in + KCC*) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + archive_expsym_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib ${wl}-retain-symbols-file,$export_symbols; mv \$templib $lib' + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; $ECHO "X$list" | $Xsed' + + hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' + export_dynamic_flag_spec_CXX='${wl}--export-dynamic' + + # Archives containing C++ object files must be created using + # "CC -Bstatic", where "CC" is the KAI C++ compiler. + old_archive_cmds_CXX='$CC -Bstatic -o $oldlib $oldobjs' + ;; + icpc* | ecpc* ) + # Intel C++ + with_gnu_ld=yes + # version 8.0 and above of icpc choke on multiply defined symbols + # if we add $predep_objects and $postdep_objects, however 7.1 and + # earlier do not add the objects themselves. + case `$CC -V 2>&1` in + *"Version 7."*) + archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + ;; + *) # Version 8.0 or newer + tmp_idyn= + case $host_cpu in + ia64*) tmp_idyn=' -i_dynamic';; + esac + archive_cmds_CXX='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds_CXX='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + ;; + esac + archive_cmds_need_lc_CXX=no + hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' + export_dynamic_flag_spec_CXX='${wl}--export-dynamic' + whole_archive_flag_spec_CXX='${wl}--whole-archive$convenience ${wl}--no-whole-archive' + ;; + pgCC* | pgcpp*) + # Portland Group C++ compiler + case `$CC -V` in + *pgCC\ [1-5]* | *pgcpp\ [1-5]*) + prelink_cmds_CXX='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~ + compile_command="$compile_command `find $tpldir -name \*.o | $NL2SP`"' + old_archive_cmds_CXX='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~ + $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | $NL2SP`~ + $RANLIB $oldlib' + archive_cmds_CXX='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ + $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' + archive_expsym_cmds_CXX='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ + $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' + ;; + *) # Version 6 will use weak symbols + archive_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' + archive_expsym_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' + ;; + esac + + hardcode_libdir_flag_spec_CXX='${wl}--rpath ${wl}$libdir' + export_dynamic_flag_spec_CXX='${wl}--export-dynamic' + whole_archive_flag_spec_CXX='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive' + ;; + cxx*) + # Compaq C++ + archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib ${wl}-retain-symbols-file $wl$export_symbols' + + runpath_var=LD_RUN_PATH + hardcode_libdir_flag_spec_CXX='-rpath $libdir' + hardcode_libdir_separator_CXX=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`$ECHO "X$templist" | $Xsed -e "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; $ECHO "X$list" | $Xsed' + ;; + xl*) + # IBM XL 8.0 on PPC, with GNU ld + hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir' + export_dynamic_flag_spec_CXX='${wl}--export-dynamic' + archive_cmds_CXX='$CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + if test "x$supports_anon_versioning" = xyes; then + archive_expsym_cmds_CXX='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' + fi + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) + # Sun C++ 5.9 + no_undefined_flag_CXX=' -zdefs' + archive_cmds_CXX='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + archive_expsym_cmds_CXX='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file ${wl}$export_symbols' + hardcode_libdir_flag_spec_CXX='-R$libdir' + whole_archive_flag_spec_CXX='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive' + compiler_needs_object_CXX=yes + + # Not sure whether something based on + # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 + # would be better. + output_verbose_link_cmd='echo' + + # Archives containing C++ object files must be created using + # "CC -xar", where "CC" is the Sun C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + old_archive_cmds_CXX='$CC -xar -o $oldlib $oldobjs' + ;; + esac + ;; + esac + ;; + + lynxos*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + + m88k*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + + mvs*) + case $cc_basename in + cxx*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + *) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + esac + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + archive_cmds_CXX='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags' + wlarc= + hardcode_libdir_flag_spec_CXX='-R$libdir' + hardcode_direct_CXX=yes + hardcode_shlibpath_var_CXX=no + fi + # Workaround some broken pre-1.5 toolchains + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"' + ;; + + *nto* | *qnx*) + ld_shlibs_CXX=yes + ;; + + openbsd2*) + # C++ shared libraries are fairly broken + ld_shlibs_CXX=no + ;; + + openbsd*) + if test -f /usr/libexec/ld.so; then + hardcode_direct_CXX=yes + hardcode_shlibpath_var_CXX=no + hardcode_direct_absolute_CXX=yes + archive_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' + hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + archive_expsym_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file,$export_symbols -o $lib' + export_dynamic_flag_spec_CXX='${wl}-E' + whole_archive_flag_spec_CXX="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + fi + output_verbose_link_cmd=echo + else + ld_shlibs_CXX=no + fi + ;; + + osf3* | osf4* | osf5*) + case $cc_basename in + KCC*) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + + hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' + hardcode_libdir_separator_CXX=: + + # Archives containing C++ object files must be created using + # the KAI C++ compiler. + case $host in + osf3*) old_archive_cmds_CXX='$CC -Bstatic -o $oldlib $oldobjs' ;; + *) old_archive_cmds_CXX='$CC -o $oldlib $oldobjs' ;; + esac + ;; + RCC*) + # Rational C++ 2.4.1 + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + cxx*) + case $host in + osf3*) + allow_undefined_flag_CXX=' ${wl}-expect_unresolved ${wl}\*' + archive_cmds_CXX='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && $ECHO "X${wl}-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib' + hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir' + ;; + *) + allow_undefined_flag_CXX=' -expect_unresolved \*' + archive_cmds_CXX='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib' + archive_expsym_cmds_CXX='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ + echo "-hidden">> $lib.exp~ + $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname ${wl}-input ${wl}$lib.exp `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib~ + $RM $lib.exp' + hardcode_libdir_flag_spec_CXX='-rpath $libdir' + ;; + esac + + hardcode_libdir_separator_CXX=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`$ECHO "X$templist" | $Xsed -e "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; $ECHO "X$list" | $Xsed' + ;; + *) + if test "$GXX" = yes && test "$with_gnu_ld" = no; then + allow_undefined_flag_CXX=' ${wl}-expect_unresolved ${wl}\*' + case $host in + osf3*) + archive_cmds_CXX='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + ;; + *) + archive_cmds_CXX='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + ;; + esac + + hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator_CXX=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "\-L"' + + else + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + fi + ;; + esac + ;; + + psos*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + + sunos4*) + case $cc_basename in + CC*) + # Sun C++ 4.x + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + lcc*) + # Lucid + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + *) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + esac + ;; + + solaris*) + case $cc_basename in + CC*) + # Sun C++ 4.2, 5.x and Centerline C++ + archive_cmds_need_lc_CXX=yes + no_undefined_flag_CXX=' -zdefs' + archive_cmds_CXX='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + archive_expsym_cmds_CXX='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -G${allow_undefined_flag} ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' + + hardcode_libdir_flag_spec_CXX='-R$libdir' + hardcode_shlibpath_var_CXX=no + case $host_os in + solaris2.[0-5] | solaris2.[0-5].*) ;; + *) + # The compiler driver will combine and reorder linker options, + # but understands `-z linker_flag'. + # Supported since Solaris 2.6 (maybe 2.5.1?) + whole_archive_flag_spec_CXX='-z allextract$convenience -z defaultextract' + ;; + esac + link_all_deplibs_CXX=yes + + output_verbose_link_cmd='echo' + + # Archives containing C++ object files must be created using + # "CC -xar", where "CC" is the Sun C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + old_archive_cmds_CXX='$CC -xar -o $oldlib $oldobjs' + ;; + gcx*) + # Green Hills C++ Compiler + archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' + + # The C++ compiler must be used to create the archive. + old_archive_cmds_CXX='$CC $LDFLAGS -archive -o $oldlib $oldobjs' + ;; + *) + # GNU C++ compiler with Solaris linker + if test "$GXX" = yes && test "$with_gnu_ld" = no; then + no_undefined_flag_CXX=' ${wl}-z ${wl}defs' + if $CC --version | $GREP -v '^2\.7' > /dev/null; then + archive_cmds_CXX='$CC -shared -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' + archive_expsym_cmds_CXX='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -shared -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "\-L"' + else + # g++ 2.7 appears to require `-G' NOT `-shared' on this + # platform. + archive_cmds_CXX='$CC -G -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' + archive_expsym_cmds_CXX='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -G -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP "\-L"' + fi + + hardcode_libdir_flag_spec_CXX='${wl}-R $wl$libdir' + case $host_os in + solaris2.[0-5] | solaris2.[0-5].*) ;; + *) + whole_archive_flag_spec_CXX='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' + ;; + esac + fi + ;; + esac + ;; + + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) + no_undefined_flag_CXX='${wl}-z,text' + archive_cmds_need_lc_CXX=no + hardcode_shlibpath_var_CXX=no + runpath_var='LD_RUN_PATH' + + case $cc_basename in + CC*) + archive_cmds_CXX='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_CXX='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + archive_cmds_CXX='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_CXX='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + + sysv5* | sco3.2v5* | sco5v6*) + # Note: We can NOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + no_undefined_flag_CXX='${wl}-z,text' + allow_undefined_flag_CXX='${wl}-z,nodefs' + archive_cmds_need_lc_CXX=no + hardcode_shlibpath_var_CXX=no + hardcode_libdir_flag_spec_CXX='${wl}-R,$libdir' + hardcode_libdir_separator_CXX=':' + link_all_deplibs_CXX=yes + export_dynamic_flag_spec_CXX='${wl}-Bexport' + runpath_var='LD_RUN_PATH' + + case $cc_basename in + CC*) + archive_cmds_CXX='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_CXX='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + archive_cmds_CXX='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_CXX='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + + tandem*) + case $cc_basename in + NCC*) + # NonStop-UX NCC 3.20 + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + *) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + esac + ;; + + vxworks*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + + *) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + esac + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs_CXX" >&5 +$as_echo "$ld_shlibs_CXX" >&6; } + test "$ld_shlibs_CXX" = no && can_build_shared=no + + GCC_CXX="$GXX" + LD_CXX="$LD" + + ## CAVEAT EMPTOR: + ## There is no encapsulation within the following macros, do not change + ## the running order or otherwise move them around unless you know exactly + ## what you are doing... + # Dependencies to place before and after the object being linked: +predep_objects_CXX= +postdep_objects_CXX= +predeps_CXX= +postdeps_CXX= +compiler_lib_search_path_CXX= + +cat > conftest.$ac_ext <<_LT_EOF +class Foo +{ +public: + Foo (void) { a = 0; } +private: + int a; +}; +_LT_EOF + +if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + # Parse the compiler output and extract the necessary + # objects, libraries and library flags. + + # Sentinel used to keep track of whether or not we are before + # the conftest object file. + pre_test_object_deps_done=no + + for p in `eval "$output_verbose_link_cmd"`; do + case $p in + + -L* | -R* | -l*) + # Some compilers place space between "-{L,R}" and the path. + # Remove the space. + if test $p = "-L" || + test $p = "-R"; then + prev=$p + continue + else + prev= + fi + + if test "$pre_test_object_deps_done" = no; then + case $p in + -L* | -R*) + # Internal compiler library paths should come after those + # provided the user. The postdeps already come after the + # user supplied libs so there is no need to process them. + if test -z "$compiler_lib_search_path_CXX"; then + compiler_lib_search_path_CXX="${prev}${p}" + else + compiler_lib_search_path_CXX="${compiler_lib_search_path_CXX} ${prev}${p}" + fi + ;; + # The "-l" case would never come before the object being + # linked, so don't bother handling this case. + esac + else + if test -z "$postdeps_CXX"; then + postdeps_CXX="${prev}${p}" + else + postdeps_CXX="${postdeps_CXX} ${prev}${p}" + fi + fi + ;; + + *.$objext) + # This assumes that the test object file only shows up + # once in the compiler output. + if test "$p" = "conftest.$objext"; then + pre_test_object_deps_done=yes + continue + fi + + if test "$pre_test_object_deps_done" = no; then + if test -z "$predep_objects_CXX"; then + predep_objects_CXX="$p" + else + predep_objects_CXX="$predep_objects_CXX $p" + fi + else + if test -z "$postdep_objects_CXX"; then + postdep_objects_CXX="$p" + else + postdep_objects_CXX="$postdep_objects_CXX $p" + fi + fi + ;; + + *) ;; # Ignore the rest. + + esac + done + + # Clean up. + rm -f a.out a.exe +else + echo "libtool.m4: error: problem compiling CXX test program" +fi + +$RM -f confest.$objext + +# PORTME: override above test on systems where it is broken +case $host_os in +interix[3-9]*) + # Interix 3.5 installs completely hosed .la files for C++, so rather than + # hack all around it, let's just trust "g++" to DTRT. + predep_objects_CXX= + postdep_objects_CXX= + postdeps_CXX= + ;; + +linux*) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) + # Sun C++ 5.9 + + # The more standards-conforming stlport4 library is + # incompatible with the Cstd library. Avoid specifying + # it if it's in CXXFLAGS. Ignore libCrun as + # -library=stlport4 depends on it. + case " $CXX $CXXFLAGS " in + *" -library=stlport4 "*) + solaris_use_stlport4=yes + ;; + esac + + if test "$solaris_use_stlport4" != yes; then + postdeps_CXX='-library=Cstd -library=Crun' + fi + ;; + esac + ;; + +solaris*) + case $cc_basename in + CC*) + # The more standards-conforming stlport4 library is + # incompatible with the Cstd library. Avoid specifying + # it if it's in CXXFLAGS. Ignore libCrun as + # -library=stlport4 depends on it. + case " $CXX $CXXFLAGS " in + *" -library=stlport4 "*) + solaris_use_stlport4=yes + ;; + esac + + # Adding this requires a known-good setup of shared libraries for + # Sun compiler versions before 5.6, else PIC objects from an old + # archive will be linked into the output, leading to subtle bugs. + if test "$solaris_use_stlport4" != yes; then + postdeps_CXX='-library=Cstd -library=Crun' + fi + ;; + esac + ;; +esac + + +case " $postdeps_CXX " in +*" -lc "*) archive_cmds_need_lc_CXX=no ;; +esac + compiler_lib_search_dirs_CXX= +if test -n "${compiler_lib_search_path_CXX}"; then + compiler_lib_search_dirs_CXX=`echo " ${compiler_lib_search_path_CXX}" | ${SED} -e 's! -L! !g' -e 's!^ !!'` +fi + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + lt_prog_compiler_wl_CXX= +lt_prog_compiler_pic_CXX= +lt_prog_compiler_static_CXX= + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5 +$as_echo_n "checking for $compiler option to produce PIC... " >&6; } + + # C++ specific cases for pic, static, wl, etc. + if test "$GXX" = yes; then + lt_prog_compiler_wl_CXX='-Wl,' + lt_prog_compiler_static_CXX='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + lt_prog_compiler_static_CXX='-Bstatic' + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + lt_prog_compiler_pic_CXX='-fPIC' + ;; + m68k) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the `-m68020' flag to GCC prevents building anything better, + # like `-m68040'. + lt_prog_compiler_pic_CXX='-m68020 -resident32 -malways-restore-a4' + ;; + esac + ;; + + beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + mingw* | cygwin* | os2* | pw32* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + # Although the cygwin gcc ignores -fPIC, still need this for old-style + # (--disable-auto-import) libraries + lt_prog_compiler_pic_CXX='-DDLL_EXPORT' + ;; + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + lt_prog_compiler_pic_CXX='-fno-common' + ;; + *djgpp*) + # DJGPP does not support shared libraries at all + lt_prog_compiler_pic_CXX= + ;; + interix[3-9]*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + sysv4*MP*) + if test -d /usr/nec; then + lt_prog_compiler_pic_CXX=-Kconform_pic + fi + ;; + hpux*) + # PIC is the default for 64-bit PA HP-UX, but not for 32-bit + # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag + # sets the default TLS model and affects inlining. + case $host_cpu in + hppa*64*) + ;; + *) + lt_prog_compiler_pic_CXX='-fPIC' + ;; + esac + ;; + *qnx* | *nto*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + lt_prog_compiler_pic_CXX='-fPIC -shared' + ;; + *) + lt_prog_compiler_pic_CXX='-fPIC' + ;; + esac + else + case $host_os in + aix[4-9]*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + lt_prog_compiler_static_CXX='-Bstatic' + else + lt_prog_compiler_static_CXX='-bnso -bI:/lib/syscalls.exp' + fi + ;; + chorus*) + case $cc_basename in + cxch68*) + # Green Hills C++ Compiler + # _LT_TAGVAR(lt_prog_compiler_static, CXX)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a" + ;; + esac + ;; + dgux*) + case $cc_basename in + ec++*) + lt_prog_compiler_pic_CXX='-KPIC' + ;; + ghcx*) + # Green Hills C++ Compiler + lt_prog_compiler_pic_CXX='-pic' + ;; + *) + ;; + esac + ;; + freebsd* | dragonfly*) + # FreeBSD uses GNU C++ + ;; + hpux9* | hpux10* | hpux11*) + case $cc_basename in + CC*) + lt_prog_compiler_wl_CXX='-Wl,' + lt_prog_compiler_static_CXX='${wl}-a ${wl}archive' + if test "$host_cpu" != ia64; then + lt_prog_compiler_pic_CXX='+Z' + fi + ;; + aCC*) + lt_prog_compiler_wl_CXX='-Wl,' + lt_prog_compiler_static_CXX='${wl}-a ${wl}archive' + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + lt_prog_compiler_pic_CXX='+Z' + ;; + esac + ;; + *) + ;; + esac + ;; + interix*) + # This is c89, which is MS Visual C++ (no shared libs) + # Anyone wants to do a port? + ;; + irix5* | irix6* | nonstopux*) + case $cc_basename in + CC*) + lt_prog_compiler_wl_CXX='-Wl,' + lt_prog_compiler_static_CXX='-non_shared' + # CC pic flag -KPIC is the default. + ;; + *) + ;; + esac + ;; + linux* | k*bsd*-gnu | kopensolaris*-gnu) + case $cc_basename in + KCC*) + # KAI C++ Compiler + lt_prog_compiler_wl_CXX='--backend -Wl,' + lt_prog_compiler_pic_CXX='-fPIC' + ;; + ecpc* ) + # old Intel C++ for x86_64 which still supported -KPIC. + lt_prog_compiler_wl_CXX='-Wl,' + lt_prog_compiler_pic_CXX='-KPIC' + lt_prog_compiler_static_CXX='-static' + ;; + icpc* ) + # Intel C++, used to be incompatible with GCC. + # ICC 10 doesn't accept -KPIC any more. + lt_prog_compiler_wl_CXX='-Wl,' + lt_prog_compiler_pic_CXX='-fPIC' + lt_prog_compiler_static_CXX='-static' + ;; + pgCC* | pgcpp*) + # Portland Group C++ compiler + lt_prog_compiler_wl_CXX='-Wl,' + lt_prog_compiler_pic_CXX='-fpic' + lt_prog_compiler_static_CXX='-Bstatic' + ;; + cxx*) + # Compaq C++ + # Make sure the PIC flag is empty. It appears that all Alpha + # Linux and Compaq Tru64 Unix objects are PIC. + lt_prog_compiler_pic_CXX= + lt_prog_compiler_static_CXX='-non_shared' + ;; + xlc* | xlC*) + # IBM XL 8.0 on PPC + lt_prog_compiler_wl_CXX='-Wl,' + lt_prog_compiler_pic_CXX='-qpic' + lt_prog_compiler_static_CXX='-qstaticlink' + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) + # Sun C++ 5.9 + lt_prog_compiler_pic_CXX='-KPIC' + lt_prog_compiler_static_CXX='-Bstatic' + lt_prog_compiler_wl_CXX='-Qoption ld ' + ;; + esac + ;; + esac + ;; + lynxos*) + ;; + m88k*) + ;; + mvs*) + case $cc_basename in + cxx*) + lt_prog_compiler_pic_CXX='-W c,exportall' + ;; + *) + ;; + esac + ;; + netbsd* | netbsdelf*-gnu) + ;; + *qnx* | *nto*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + lt_prog_compiler_pic_CXX='-fPIC -shared' + ;; + osf3* | osf4* | osf5*) + case $cc_basename in + KCC*) + lt_prog_compiler_wl_CXX='--backend -Wl,' + ;; + RCC*) + # Rational C++ 2.4.1 + lt_prog_compiler_pic_CXX='-pic' + ;; + cxx*) + # Digital/Compaq C++ + lt_prog_compiler_wl_CXX='-Wl,' + # Make sure the PIC flag is empty. It appears that all Alpha + # Linux and Compaq Tru64 Unix objects are PIC. + lt_prog_compiler_pic_CXX= + lt_prog_compiler_static_CXX='-non_shared' + ;; + *) + ;; + esac + ;; + psos*) + ;; + solaris*) + case $cc_basename in + CC*) + # Sun C++ 4.2, 5.x and Centerline C++ + lt_prog_compiler_pic_CXX='-KPIC' + lt_prog_compiler_static_CXX='-Bstatic' + lt_prog_compiler_wl_CXX='-Qoption ld ' + ;; + gcx*) + # Green Hills C++ Compiler + lt_prog_compiler_pic_CXX='-PIC' + ;; + *) + ;; + esac + ;; + sunos4*) + case $cc_basename in + CC*) + # Sun C++ 4.x + lt_prog_compiler_pic_CXX='-pic' + lt_prog_compiler_static_CXX='-Bstatic' + ;; + lcc*) + # Lucid + lt_prog_compiler_pic_CXX='-pic' + ;; + *) + ;; + esac + ;; + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + case $cc_basename in + CC*) + lt_prog_compiler_wl_CXX='-Wl,' + lt_prog_compiler_pic_CXX='-KPIC' + lt_prog_compiler_static_CXX='-Bstatic' + ;; + esac + ;; + tandem*) + case $cc_basename in + NCC*) + # NonStop-UX NCC 3.20 + lt_prog_compiler_pic_CXX='-KPIC' + ;; + *) + ;; + esac + ;; + vxworks*) + ;; + *) + lt_prog_compiler_can_build_shared_CXX=no + ;; + esac + fi + +case $host_os in + # For platforms which do not support PIC, -DPIC is meaningless: + *djgpp*) + lt_prog_compiler_pic_CXX= + ;; + *) + lt_prog_compiler_pic_CXX="$lt_prog_compiler_pic_CXX -DPIC" + ;; +esac +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_prog_compiler_pic_CXX" >&5 +$as_echo "$lt_prog_compiler_pic_CXX" >&6; } + + + +# +# Check to make sure the PIC flag actually works. +# +if test -n "$lt_prog_compiler_pic_CXX"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic_CXX works" >&5 +$as_echo_n "checking if $compiler PIC flag $lt_prog_compiler_pic_CXX works... " >&6; } +if test "${lt_cv_prog_compiler_pic_works_CXX+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_pic_works_CXX=no + ac_outfile=conftest.$ac_objext + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="$lt_prog_compiler_pic_CXX -DPIC" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:13286: $lt_compile\"" >&5) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&5 + echo "$as_me:13290: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings other than the usual output. + $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler_pic_works_CXX=yes + fi + fi + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works_CXX" >&5 +$as_echo "$lt_cv_prog_compiler_pic_works_CXX" >&6; } + +if test x"$lt_cv_prog_compiler_pic_works_CXX" = xyes; then + case $lt_prog_compiler_pic_CXX in + "" | " "*) ;; + *) lt_prog_compiler_pic_CXX=" $lt_prog_compiler_pic_CXX" ;; + esac +else + lt_prog_compiler_pic_CXX= + lt_prog_compiler_can_build_shared_CXX=no +fi + +fi + + + +# +# Check to make sure the static flag actually works. +# +wl=$lt_prog_compiler_wl_CXX eval lt_tmp_static_flag=\"$lt_prog_compiler_static_CXX\" +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler static flag $lt_tmp_static_flag works" >&5 +$as_echo_n "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; } +if test "${lt_cv_prog_compiler_static_works_CXX+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_static_works_CXX=no + save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS $lt_tmp_static_flag" + echo "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The linker can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&5 + $ECHO "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler_static_works_CXX=yes + fi + else + lt_cv_prog_compiler_static_works_CXX=yes + fi + fi + $RM -r conftest* + LDFLAGS="$save_LDFLAGS" + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works_CXX" >&5 +$as_echo "$lt_cv_prog_compiler_static_works_CXX" >&6; } + +if test x"$lt_cv_prog_compiler_static_works_CXX" = xyes; then + : +else + lt_prog_compiler_static_CXX= +fi + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 +$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } +if test "${lt_cv_prog_compiler_c_o_CXX+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_c_o_CXX=no + $RM -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:13385: $lt_compile\"" >&5) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&5 + echo "$as_me:13389: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + lt_cv_prog_compiler_c_o_CXX=yes + fi + fi + chmod u+w . 2>&5 + $RM conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files + $RM out/* && rmdir out + cd .. + $RM -r conftest + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o_CXX" >&5 +$as_echo "$lt_cv_prog_compiler_c_o_CXX" >&6; } + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 +$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } +if test "${lt_cv_prog_compiler_c_o_CXX+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_c_o_CXX=no + $RM -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:13437: $lt_compile\"" >&5) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&5 + echo "$as_me:13441: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + lt_cv_prog_compiler_c_o_CXX=yes + fi + fi + chmod u+w . 2>&5 + $RM conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files + $RM out/* && rmdir out + cd .. + $RM -r conftest + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o_CXX" >&5 +$as_echo "$lt_cv_prog_compiler_c_o_CXX" >&6; } + + + + +hard_links="nottested" +if test "$lt_cv_prog_compiler_c_o_CXX" = no && test "$need_locks" != no; then + # do not overwrite the value of need_locks provided by the user + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5 +$as_echo_n "checking if we can lock with hard links... " >&6; } + hard_links=yes + $RM conftest* + ln conftest.a conftest.b 2>/dev/null && hard_links=no + touch conftest.a + ln conftest.a conftest.b 2>&5 || hard_links=no + ln conftest.a conftest.b 2>/dev/null && hard_links=no + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5 +$as_echo "$hard_links" >&6; } + if test "$hard_links" = no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5 +$as_echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;} + need_locks=warn + fi +else + need_locks=no +fi + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5 +$as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; } + + export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + case $host_os in + aix[4-9]*) + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to AIX nm, but means don't demangle with GNU nm + if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then + export_symbols_cmds_CXX='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' + else + export_symbols_cmds_CXX='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' + fi + ;; + pw32*) + export_symbols_cmds_CXX="$ltdll_cmds" + ;; + cygwin* | mingw* | cegcc*) + export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/;/^.*[ ]__nm__/s/^.*[ ]__nm__\([^ ]*\)[ ][^ ]*/\1 DATA/;/^I[ ]/d;/^[AITW][ ]/s/.* //'\'' | sort | uniq > $export_symbols' + ;; + linux* | k*bsd*-gnu) + link_all_deplibs_CXX=no + ;; + *) + export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + ;; + esac + exclude_expsyms_CXX='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*' + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs_CXX" >&5 +$as_echo "$ld_shlibs_CXX" >&6; } +test "$ld_shlibs_CXX" = no && can_build_shared=no + +with_gnu_ld_CXX=$with_gnu_ld + + + + + + +# +# Do we need to explicitly link libc? +# +case "x$archive_cmds_need_lc_CXX" in +x|xyes) + # Assume -lc should be added + archive_cmds_need_lc_CXX=yes + + if test "$enable_shared" = yes && test "$GCC" = yes; then + case $archive_cmds_CXX in + *'~'*) + # FIXME: we may have to deal with multi-command sequences. + ;; + '$CC '*) + # Test whether the compiler implicitly links with -lc since on some + # systems, -lgcc has to come before -lc. If gcc already passes -lc + # to ld, don't add -lc before -lgcc. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5 +$as_echo_n "checking whether -lc should be explicitly linked in... " >&6; } + $RM conftest* + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } 2>conftest.err; then + soname=conftest + lib=conftest + libobjs=conftest.$ac_objext + deplibs= + wl=$lt_prog_compiler_wl_CXX + pic_flag=$lt_prog_compiler_pic_CXX + compiler_flags=-v + linker_flags=-v + verstring= + output_objdir=. + libname=conftest + lt_save_allow_undefined_flag=$allow_undefined_flag_CXX + allow_undefined_flag_CXX= + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds_CXX 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5 + (eval $archive_cmds_CXX 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + then + archive_cmds_need_lc_CXX=no + else + archive_cmds_need_lc_CXX=yes + fi + allow_undefined_flag_CXX=$lt_save_allow_undefined_flag + else + cat conftest.err 1>&5 + fi + $RM conftest* + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $archive_cmds_need_lc_CXX" >&5 +$as_echo "$archive_cmds_need_lc_CXX" >&6; } + ;; + esac + fi + ;; +esac + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5 +$as_echo_n "checking dynamic linker characteristics... " >&6; } + +library_names_spec= +libname_spec='lib$name' +soname_spec= +shrext_cmds=".so" +postinstall_cmds= +postuninstall_cmds= +finish_cmds= +finish_eval= +shlibpath_var= +shlibpath_overrides_runpath=unknown +version_type=none +dynamic_linker="$host_os ld.so" +sys_lib_dlsearch_path_spec="/lib /usr/lib" +need_lib_prefix=unknown +hardcode_into_libs=no + +# when you set need_version to no, make sure it does not cause -set_version +# flags to be left without arguments +need_version=unknown + +case $host_os in +aix3*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' + shlibpath_var=LIBPATH + + # AIX 3 has no versioning support, so we append a major version to the name. + soname_spec='${libname}${release}${shared_ext}$major' + ;; + +aix[4-9]*) + version_type=linux + need_lib_prefix=no + need_version=no + hardcode_into_libs=yes + if test "$host_cpu" = ia64; then + # AIX 5 supports IA64 + library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + else + # With GCC up to 2.95.x, collect2 would create an import file + # for dependence libraries. The import file would start with + # the line `#! .'. This would cause the generated library to + # depend on `.', always an invalid library. This was fixed in + # development snapshots of GCC prior to 3.0. + case $host_os in + aix4 | aix4.[01] | aix4.[01].*) + if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' + echo ' yes ' + echo '#endif'; } | ${CC} -E - | $GREP yes > /dev/null; then + : + else + can_build_shared=no + fi + ;; + esac + # AIX (on Power*) has no versioning support, so currently we can not hardcode correct + # soname into executable. Probably we can add versioning support to + # collect2, so additional links can be useful in future. + if test "$aix_use_runtimelinking" = yes; then + # If using run time linking (on AIX 4.2 or later) use lib.so + # instead of lib.a to let people know that these are not + # typical AIX shared libraries. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + else + # We preserve .a as extension for shared libraries through AIX4.2 + # and later when we are not doing run time linking. + library_names_spec='${libname}${release}.a $libname.a' + soname_spec='${libname}${release}${shared_ext}$major' + fi + shlibpath_var=LIBPATH + fi + ;; + +amigaos*) + case $host_cpu in + powerpc) + # Since July 2007 AmigaOS4 officially supports .so libraries. + # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + ;; + m68k) + library_names_spec='$libname.ixlibrary $libname.a' + # Create ${libname}_ixlibrary.a entries in /sys/libs. + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$ECHO "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' + ;; + esac + ;; + +beos*) + library_names_spec='${libname}${shared_ext}' + dynamic_linker="$host_os ld.so" + shlibpath_var=LIBRARY_PATH + ;; + +bsdi[45]*) + version_type=linux + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" + sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" + # the default ld.so.conf also contains /usr/contrib/lib and + # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow + # libtool to hard-code these into programs + ;; + +cygwin* | mingw* | pw32* | cegcc*) + version_type=windows + shrext_cmds=".dll" + need_version=no + need_lib_prefix=no + + case $GCC,$host_os in + yes,cygwin* | yes,mingw* | yes,pw32* | yes,cegcc*) + library_names_spec='$libname.dll.a' + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \${file}`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname~ + if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then + eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; + fi' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + shlibpath_overrides_runpath=yes + + case $host_os in + cygwin*) + # Cygwin DLLs use 'cyg' prefix rather than 'lib' + soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib" + ;; + mingw* | cegcc*) + # MinGW DLLs use traditional 'lib' prefix + soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + sys_lib_search_path_spec=`$CC -print-search-dirs | $GREP "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` + if $ECHO "$sys_lib_search_path_spec" | $GREP ';[c-zC-Z]:/' >/dev/null; then + # It is most probably a Windows format PATH printed by + # mingw gcc, but we are running on Cygwin. Gcc prints its search + # path with ; separators, and with drive letters. We can handle the + # drive letters (cygwin fileutils understands them), so leave them, + # especially as we might pass files found there to a mingw objdump, + # which wouldn't understand a cygwinified path. Ahh. + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi + ;; + pw32*) + # pw32 DLLs use 'pw' prefix rather than 'lib' + library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + ;; + esac + ;; + + *) + library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib' + ;; + esac + dynamic_linker='Win32 ld.exe' + # FIXME: first we should search . and the directory the executable is in + shlibpath_var=PATH + ;; + +darwin* | rhapsody*) + dynamic_linker="$host_os dyld" + version_type=darwin + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${major}$shared_ext ${libname}$shared_ext' + soname_spec='${libname}${release}${major}$shared_ext' + shlibpath_overrides_runpath=yes + shlibpath_var=DYLD_LIBRARY_PATH + shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' + + sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' + ;; + +dgux*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +freebsd1*) + dynamic_linker=no + ;; + +freebsd* | dragonfly*) + # DragonFly does not have aout. When/if they implement a new + # versioning mechanism, adjust this. + if test -x /usr/bin/objformat; then + objformat=`/usr/bin/objformat` + else + case $host_os in + freebsd[123]*) objformat=aout ;; + *) objformat=elf ;; + esac + fi + version_type=freebsd-$objformat + case $version_type in + freebsd-elf*) + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + need_version=no + need_lib_prefix=no + ;; + freebsd-*) + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' + need_version=yes + ;; + esac + shlibpath_var=LD_LIBRARY_PATH + case $host_os in + freebsd2*) + shlibpath_overrides_runpath=yes + ;; + freebsd3.[01]* | freebsdelf3.[01]*) + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ + freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + *) # from 4.6 on, and DragonFly + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + esac + ;; + +gnu*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + hardcode_into_libs=yes + ;; + +hpux9* | hpux10* | hpux11*) + # Give a soname corresponding to the major version so that dld.sl refuses to + # link against other versions. + version_type=sunos + need_lib_prefix=no + need_version=no + case $host_cpu in + ia64*) + shrext_cmds='.so' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.so" + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + if test "X$HPUX_IA64_MODE" = X32; then + sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" + else + sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" + fi + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + hppa*64*) + shrext_cmds='.sl' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.sl" + shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + *) + shrext_cmds='.sl' + dynamic_linker="$host_os dld.sl" + shlibpath_var=SHLIB_PATH + shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + ;; + esac + # HP-UX runs *really* slowly unless shared libraries are mode 555. + postinstall_cmds='chmod 555 $lib' + ;; + +interix[3-9]*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +irix5* | irix6* | nonstopux*) + case $host_os in + nonstopux*) version_type=nonstopux ;; + *) + if test "$lt_cv_prog_gnu_ld" = yes; then + version_type=linux + else + version_type=irix + fi ;; + esac + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' + case $host_os in + irix5* | nonstopux*) + libsuff= shlibsuff= + ;; + *) + case $LD in # libtool.m4 will add one of these switches to LD + *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") + libsuff= shlibsuff= libmagic=32-bit;; + *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") + libsuff=32 shlibsuff=N32 libmagic=N32;; + *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") + libsuff=64 shlibsuff=64 libmagic=64-bit;; + *) libsuff= shlibsuff= libmagic=never-match;; + esac + ;; + esac + shlibpath_var=LD_LIBRARY${shlibsuff}_PATH + shlibpath_overrides_runpath=no + sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" + sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" + hardcode_into_libs=yes + ;; + +# No shared lib support for Linux oldld, aout, or coff. +linux*oldld* | linux*aout* | linux*coff*) + dynamic_linker=no + ;; + +# This must be Linux ELF. +linux* | k*bsd*-gnu | kopensolaris*-gnu) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + # Some binutils ld are patched to set DT_RUNPATH + save_LDFLAGS=$LDFLAGS + save_libdir=$libdir + eval "libdir=/foo; wl=\"$lt_prog_compiler_wl_CXX\"; \ + LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec_CXX\"" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + if ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null; then : + shlibpath_overrides_runpath=yes +fi +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS=$save_LDFLAGS + libdir=$save_libdir + + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + # Append ld.so.conf contents to the search path + if test -f /etc/ld.so.conf; then + lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '` + sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" + fi + + # We used to test for /lib/ld.so.1 and disable shared libraries on + # powerpc, because MkLinux only supported shared libraries with the + # GNU dynamic linker. Since this was broken with cross compilers, + # most powerpc-linux boxes support dynamic linking these days and + # people can always --disable-shared, the test was removed, and we + # assume the GNU/Linux dynamic linker is in use. + dynamic_linker='GNU/Linux ld.so' + ;; + +netbsdelf*-gnu) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='NetBSD ld.elf_so' + ;; + +netbsd*) + version_type=sunos + need_lib_prefix=no + need_version=no + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + dynamic_linker='NetBSD (a.out) ld.so' + else + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='NetBSD ld.elf_so' + fi + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + +newsos6) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +*nto* | *qnx*) + version_type=qnx + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='ldqnx.so' + ;; + +openbsd*) + version_type=sunos + sys_lib_dlsearch_path_spec="/usr/lib" + need_lib_prefix=no + # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. + case $host_os in + openbsd3.3 | openbsd3.3.*) need_version=yes ;; + *) need_version=no ;; + esac + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + shlibpath_var=LD_LIBRARY_PATH + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + case $host_os in + openbsd2.[89] | openbsd2.[89].*) + shlibpath_overrides_runpath=no + ;; + *) + shlibpath_overrides_runpath=yes + ;; + esac + else + shlibpath_overrides_runpath=yes + fi + ;; + +os2*) + libname_spec='$name' + shrext_cmds=".dll" + need_lib_prefix=no + library_names_spec='$libname${shared_ext} $libname.a' + dynamic_linker='OS/2 ld.exe' + shlibpath_var=LIBPATH + ;; + +osf3* | osf4* | osf5*) + version_type=osf + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" + sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" + ;; + +rdos*) + dynamic_linker=no + ;; + +solaris*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + # ldd complains unless libraries are executable + postinstall_cmds='chmod +x $lib' + ;; + +sunos4*) + version_type=sunos + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + if test "$with_gnu_ld" = yes; then + need_lib_prefix=no + fi + need_version=yes + ;; + +sysv4 | sysv4.3*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + case $host_vendor in + sni) + shlibpath_overrides_runpath=no + need_lib_prefix=no + runpath_var=LD_RUN_PATH + ;; + siemens) + need_lib_prefix=no + ;; + motorola) + need_lib_prefix=no + need_version=no + shlibpath_overrides_runpath=no + sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' + ;; + esac + ;; + +sysv4*MP*) + if test -d /usr/nec ;then + version_type=linux + library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' + soname_spec='$libname${shared_ext}.$major' + shlibpath_var=LD_LIBRARY_PATH + fi + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + version_type=freebsd-elf + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + if test "$with_gnu_ld" = yes; then + sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' + else + sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' + case $host_os in + sco3.2v5*) + sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" + ;; + esac + fi + sys_lib_dlsearch_path_spec='/usr/lib' + ;; + +tpf*) + # TPF is a cross-target only. Preferred cross-host = GNU/Linux. + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +uts4*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +*) + dynamic_linker=no + ;; +esac +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5 +$as_echo "$dynamic_linker" >&6; } +test "$dynamic_linker" = no && can_build_shared=no + +variables_saved_for_relink="PATH $shlibpath_var $runpath_var" +if test "$GCC" = yes; then + variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" +fi + +if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then + sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec" +fi +if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then + sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec" +fi + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs" >&5 +$as_echo_n "checking how to hardcode library paths into programs... " >&6; } +hardcode_action_CXX= +if test -n "$hardcode_libdir_flag_spec_CXX" || + test -n "$runpath_var_CXX" || + test "X$hardcode_automatic_CXX" = "Xyes" ; then + + # We can hardcode non-existent directories. + if test "$hardcode_direct_CXX" != no && + # If the only mechanism to avoid hardcoding is shlibpath_var, we + # have to relink, otherwise we might link with an installed library + # when we should be linking with a yet-to-be-installed one + ## test "$_LT_TAGVAR(hardcode_shlibpath_var, CXX)" != no && + test "$hardcode_minus_L_CXX" != no; then + # Linking always hardcodes the temporary library directory. + hardcode_action_CXX=relink + else + # We can link without hardcoding, and we can hardcode nonexisting dirs. + hardcode_action_CXX=immediate + fi +else + # We cannot hardcode anything, or else we can only hardcode existing + # directories. + hardcode_action_CXX=unsupported +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $hardcode_action_CXX" >&5 +$as_echo "$hardcode_action_CXX" >&6; } + +if test "$hardcode_action_CXX" = relink || + test "$inherit_rpath_CXX" = yes; then + # Fast installation is not supported + enable_fast_install=no +elif test "$shlibpath_overrides_runpath" = yes || + test "$enable_shared" = no; then + # Fast installation is not necessary + enable_fast_install=needless +fi + + + + + + + + fi # test -n "$compiler" + + CC=$lt_save_CC + LDCXX=$LD + LD=$lt_save_LD + GCC=$lt_save_GCC + with_gnu_ld=$lt_save_with_gnu_ld + lt_cv_path_LDCXX=$lt_cv_path_LD + lt_cv_path_LD=$lt_save_path_LD + lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld + lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld +fi # test "$_lt_caught_CXX_error" != yes + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + + + + + + + + + + + + ac_config_commands="$ac_config_commands libtool" + + + + +# Only expand once: + + +if test "$GXX" != "yes"; then + as_fn_error "GNU C++ compiler not found, not building LLVM" "$LINENO" 5 +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU make" >&5 +$as_echo_n "checking for GNU make... " >&6; } +if test "${llvm_cv_gnu_make_command+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + llvm_cv_gnu_make_command='' + for a in "$MAKE" make gmake gnumake ; do + if test -z "$a" ; then continue ; fi ; + if ( sh -c "$a --version" 2> /dev/null | grep GNU 2>&1 > /dev/null ) + then + llvm_cv_gnu_make_command=$a ; + break; + fi + done +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $llvm_cv_gnu_make_command" >&5 +$as_echo "$llvm_cv_gnu_make_command" >&6; } + if test "x$llvm_cv_gnu_make_command" != "x" ; then + ifGNUmake='' ; + else + ifGNUmake='#' ; + { $as_echo "$as_me:${as_lineno-$LINENO}: result: \"Not found\"" >&5 +$as_echo "\"Not found\"" >&6; }; + fi + + +GMAKE="$llvm_cv_gnu_make_command" + + + +subdirs="$subdirs llvm" + +# Check whether --enable-llvm was given. +if test "${enable_llvm+set}" = set; then : + enableval=$enable_llvm; enable_llvm=$enableval +else + enable_llvm="auto" +fi + + +# Check whether --enable-optimized was given. +if test "${enable_optimized+set}" = set; then : + enableval=$enable_optimized; enable_optimized=$enableval +else + enable_optimized=default +fi + + if test "x$enable_optimized" == "xno"; then + DEBUG_BUILD_TRUE= + DEBUG_BUILD_FALSE='#' +else + DEBUG_BUILD_TRUE='#' + DEBUG_BUILD_FALSE= +fi + + +if test "$enable_optimized" = "default"; then + ac_configure_args="$ac_configure_args --enable-optimized" +fi + +ac_configure_args="$ac_configure_args llvm_cv_gnu_make_command=make" +# Check whether --enable-all-jit-targets was given. +if test "${enable_all_jit_targets+set}" = set; then : + enableval=$enable_all_jit_targets; enable_alltargets=$enableval +else + enable_alltargets=no +fi + +if test "$enable_alltargets" = "yes"; then + new_args="$ac_configure_args --enable-targets=x86,powerpc,arm --enable-bindings=none --enable-libffi=no --without-llvmgcc --without-llvmgxx" +else + new_args="$ac_configure_args --enable-targets=host-only --enable-bindings=none --enable-libffi=no --without-llvmgcc --without-llvmgxx" +fi +echo "$new_args" +ac_configure_args=`echo $new_args | sed -e 's/-Werror //g'` +echo "$ac_configure_args" + +if test "$enable_llvm" = "auto"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for supported C++ compiler version" >&5 +$as_echo_n "checking for supported C++ compiler version... " >&6; } + gxx_version=`${CXX} -dumpversion` || + as_fn_error "Unable to get GNU C++ compiler version" "$LINENO" 5 + case "${gxx_version}" in + [012].*|3.[0123].*) + as_fn_error "C++ compiler too old (${gxx_version})" "$LINENO" 5 + ;; + 3.4.[012]*|4.0.1*|4.1.[12]*) + as_fn_error "C++ compiler is buggy" "$LINENO" 5 + ;; + *) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok (${gxx_version})" >&5 +$as_echo "ok (${gxx_version})" >&6; } + esac + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for supported OS" >&5 +$as_echo_n "checking for supported OS... " >&6; } + case "$target_cpu" in + i?86|amd64|x86_64|powerpc*) + case "$target_os" in + darwin*|freebsd*|openbsd*|netbsd*|dragonfly*|linux*|solaris*|win32*|mingw*) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok ($target_cpu-$target_os)" >&5 +$as_echo "ok ($target_cpu-$target_os)" >&6; } + ;; + *) + as_fn_error "OS $target_os is not supported, not building LLVM" "$LINENO" 5 + ;; + esac + ;; + alpha*|arm*) + as_fn_error "CPU support is untested, not building LLVM" "$LINENO" 5 + ;; + *) + as_fn_error "Unsupported CPU for JIT: $target_cpu, not building LLVM" "$LINENO" 5 + ;; + esac +fi + +build_x86=no +build_ppc=no +build_arm=no +case "$target_cpu" in + i?86|amd64|x86_64) + build_x86=yes + ;; + powerpc*) + build_ppc=yes + ;; + arm*) + build_arm=yes + ;; +esac +if test "$enable_alltargets" = "yes"; then + build_x86=yes + build_ppc=yes + build_arm=yes +fi + if test "$build_x86" = "yes"; then + BUILD_X86_TRUE= + BUILD_X86_FALSE='#' +else + BUILD_X86_TRUE='#' + BUILD_X86_FALSE= +fi + + if test "$build_ppc" = "yes"; then + BUILD_PPC_TRUE= + BUILD_PPC_FALSE='#' +else + BUILD_PPC_TRUE='#' + BUILD_PPC_FALSE= +fi + + if test "$build_arm" = "yes"; then + BUILD_ARM_TRUE= + BUILD_ARM_FALSE='#' +else + BUILD_ARM_TRUE='#' + BUILD_ARM_FALSE= +fi + + +ac_config_files="$ac_config_files Makefile" + +cat >confcache <<\_ACEOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs, see configure's option --config-cache. +# It is not useful on other systems. If it contains results you don't +# want to keep, you may remove or edit it. +# +# config.status only pays attention to the cache file if you give it +# the --recheck option to rerun configure. +# +# `ac_cv_env_foo' variables (set or unset) will be overridden when +# loading this file, other *unset* `ac_cv_foo' will be assigned the +# following values. + +_ACEOF + +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, we kill variables containing newlines. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +( + for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + + (set) 2>&1 | + case $as_nl`(ac_space=' '; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + # `set' does not quote correctly, so add quotes: double-quote + # substitution turns \\\\ into \\, and sed turns \\ into \. + sed -n \ + "s/'/'\\\\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" + ;; #( + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) | + sed ' + /^ac_cv_env_/b end + t clear + :clear + s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ + t end + s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ + :end' >>confcache +if diff "$cache_file" confcache >/dev/null 2>&1; then :; else + if test -w "$cache_file"; then + test "x$cache_file" != "x/dev/null" && + { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 +$as_echo "$as_me: updating cache $cache_file" >&6;} + cat confcache >$cache_file + else + { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 +$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} + fi +fi +rm -f confcache + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +DEFS=-DHAVE_CONFIG_H + +ac_libobjs= +ac_ltlibobjs= +for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue + # 1. Remove the extension, and $U if already installed. + ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' + ac_i=`$as_echo "$ac_i" | sed "$ac_script"` + # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR + # will be set to the directory where LIBOBJS objects are built. + as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" + as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' +done +LIBOBJS=$ac_libobjs + +LTLIBOBJS=$ac_ltlibobjs + + + if test -n "$EXEEXT"; then + am__EXEEXT_TRUE= + am__EXEEXT_FALSE='#' +else + am__EXEEXT_TRUE='#' + am__EXEEXT_FALSE= +fi + +if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then + as_fn_error "conditional \"AMDEP\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${am__fastdepCXX_TRUE}" && test -z "${am__fastdepCXX_FALSE}"; then + as_fn_error "conditional \"am__fastdepCXX\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${MAINTAINER_MODE_TRUE}" && test -z "${MAINTAINER_MODE_FALSE}"; then + as_fn_error "conditional \"MAINTAINER_MODE\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then + as_fn_error "conditional \"am__fastdepCC\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${am__fastdepCXX_TRUE}" && test -z "${am__fastdepCXX_FALSE}"; then + as_fn_error "conditional \"am__fastdepCXX\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${DEBUG_BUILD_TRUE}" && test -z "${DEBUG_BUILD_FALSE}"; then + as_fn_error "conditional \"DEBUG_BUILD\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${BUILD_X86_TRUE}" && test -z "${BUILD_X86_FALSE}"; then + as_fn_error "conditional \"BUILD_X86\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${BUILD_PPC_TRUE}" && test -z "${BUILD_PPC_FALSE}"; then + as_fn_error "conditional \"BUILD_PPC\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${BUILD_ARM_TRUE}" && test -z "${BUILD_ARM_FALSE}"; then + as_fn_error "conditional \"BUILD_ARM\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi + +: ${CONFIG_STATUS=./config.status} +ac_write_fail=0 +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files $CONFIG_STATUS" +{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 +$as_echo "$as_me: creating $CONFIG_STATUS" >&6;} +as_write_fail=0 +cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 +#! $SHELL +# Generated by $as_me. +# Run this file to recreate the current configuration. +# Compiler output produced by configure, useful for debugging +# configure, is in config.log if it exists. + +debug=false +ac_cs_recheck=false +ac_cs_silent=false + +SHELL=\${CONFIG_SHELL-$SHELL} +export SHELL +_ASEOF +cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi + + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +case $0 in #(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + + +# as_fn_error ERROR [LINENO LOG_FD] +# --------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with status $?, using 1 if that was 0. +as_fn_error () +{ + as_status=$?; test $as_status -eq 0 && as_status=1 + if test "$3"; then + as_lineno=${as_lineno-"$2"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $1" >&$3 + fi + $as_echo "$as_me: error: $1" >&2 + as_fn_exit $as_status +} # as_fn_error + + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -p'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -p' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -p' + fi +else + as_ln_s='cp -p' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error "cannot create directory $as_dir" + + +} # as_fn_mkdir_p +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +if test -x / >/dev/null 2>&1; then + as_test_x='test -x' +else + if ls -dL / >/dev/null 2>&1; then + as_ls_L_option=L + else + as_ls_L_option= + fi + as_test_x=' + eval sh -c '\'' + if test -d "$1"; then + test -d "$1/."; + else + case $1 in #( + -*)set "./$1";; + esac; + case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #(( + ???[sx]*):;;*)false;;esac;fi + '\'' sh + ' +fi +as_executable_p=$as_test_x + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +exec 6>&1 +## ----------------------------------- ## +## Main body of $CONFIG_STATUS script. ## +## ----------------------------------- ## +_ASEOF +test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# Save the log message, to keep $0 and so on meaningful, and to +# report actual input values of CONFIG_FILES etc. instead of their +# values after options handling. +ac_log=" +This file was extended by libclamavc++ $as_me devel, which was +generated by GNU Autoconf 2.65. Invocation command line was + + CONFIG_FILES = $CONFIG_FILES + CONFIG_HEADERS = $CONFIG_HEADERS + CONFIG_LINKS = $CONFIG_LINKS + CONFIG_COMMANDS = $CONFIG_COMMANDS + $ $0 $@ + +on `(hostname || uname -n) 2>/dev/null | sed 1q` +" + +_ACEOF + +case $ac_config_files in *" +"*) set x $ac_config_files; shift; ac_config_files=$*;; +esac + +case $ac_config_headers in *" +"*) set x $ac_config_headers; shift; ac_config_headers=$*;; +esac + + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +# Files that config.status was made for. +config_files="$ac_config_files" +config_headers="$ac_config_headers" +config_commands="$ac_config_commands" + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +ac_cs_usage="\ +\`$as_me' instantiates files and other configuration actions +from templates according to the current configuration. Unless the files +and actions are specified as TAGs, all are instantiated by default. + +Usage: $0 [OPTION]... [TAG]... + + -h, --help print this help, then exit + -V, --version print version number and configuration settings, then exit + --config print configuration, then exit + -q, --quiet, --silent + do not print progress messages + -d, --debug don't remove temporary files + --recheck update $as_me by reconfiguring in the same conditions + --file=FILE[:TEMPLATE] + instantiate the configuration file FILE + --header=FILE[:TEMPLATE] + instantiate the configuration header FILE + +Configuration files: +$config_files + +Configuration headers: +$config_headers + +Configuration commands: +$config_commands + +Report bugs to ." + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" +ac_cs_version="\\ +libclamavc++ config.status devel +configured by $0, generated by GNU Autoconf 2.65, + with options \\"\$ac_cs_config\\" + +Copyright (C) 2009 Free Software Foundation, Inc. +This config.status script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it." + +ac_pwd='$ac_pwd' +srcdir='$srcdir' +INSTALL='$INSTALL' +MKDIR_P='$MKDIR_P' +AWK='$AWK' +test -n "\$AWK" || AWK=awk +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# The default lists apply if the user does not specify any file. +ac_need_defaults=: +while test $# != 0 +do + case $1 in + --*=*) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` + ac_shift=: + ;; + *) + ac_option=$1 + ac_optarg=$2 + ac_shift=shift + ;; + esac + + case $ac_option in + # Handling of the options. + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + ac_cs_recheck=: ;; + --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) + $as_echo "$ac_cs_version"; exit ;; + --config | --confi | --conf | --con | --co | --c ) + $as_echo "$ac_cs_config"; exit ;; + --debug | --debu | --deb | --de | --d | -d ) + debug=: ;; + --file | --fil | --fi | --f ) + $ac_shift + case $ac_optarg in + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + as_fn_append CONFIG_FILES " '$ac_optarg'" + ac_need_defaults=false;; + --header | --heade | --head | --hea ) + $ac_shift + case $ac_optarg in + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + as_fn_append CONFIG_HEADERS " '$ac_optarg'" + ac_need_defaults=false;; + --he | --h) + # Conflict between --help and --header + as_fn_error "ambiguous option: \`$1' +Try \`$0 --help' for more information.";; + --help | --hel | -h ) + $as_echo "$ac_cs_usage"; exit ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil | --si | --s) + ac_cs_silent=: ;; + + # This is an error. + -*) as_fn_error "unrecognized option: \`$1' +Try \`$0 --help' for more information." ;; + + *) as_fn_append ac_config_targets " $1" + ac_need_defaults=false ;; + + esac + shift +done + +ac_configure_extra_args= + +if $ac_cs_silent; then + exec 6>/dev/null + ac_configure_extra_args="$ac_configure_extra_args --silent" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +if \$ac_cs_recheck; then + set X '$SHELL' '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion + shift + \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 + CONFIG_SHELL='$SHELL' + export CONFIG_SHELL + exec "\$@" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +exec 5>>config.log +{ + echo + sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX +## Running $as_me. ## +_ASBOX + $as_echo "$ac_log" +} >&5 + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +# +# INIT-COMMANDS +# +AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir" + + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +sed_quote_subst='$sed_quote_subst' +double_quote_subst='$double_quote_subst' +delay_variable_subst='$delay_variable_subst' +macro_version='`$ECHO "X$macro_version" | $Xsed -e "$delay_single_quote_subst"`' +macro_revision='`$ECHO "X$macro_revision" | $Xsed -e "$delay_single_quote_subst"`' +enable_static='`$ECHO "X$enable_static" | $Xsed -e "$delay_single_quote_subst"`' +enable_shared='`$ECHO "X$enable_shared" | $Xsed -e "$delay_single_quote_subst"`' +pic_mode='`$ECHO "X$pic_mode" | $Xsed -e "$delay_single_quote_subst"`' +enable_fast_install='`$ECHO "X$enable_fast_install" | $Xsed -e "$delay_single_quote_subst"`' +host_alias='`$ECHO "X$host_alias" | $Xsed -e "$delay_single_quote_subst"`' +host='`$ECHO "X$host" | $Xsed -e "$delay_single_quote_subst"`' +host_os='`$ECHO "X$host_os" | $Xsed -e "$delay_single_quote_subst"`' +build_alias='`$ECHO "X$build_alias" | $Xsed -e "$delay_single_quote_subst"`' +build='`$ECHO "X$build" | $Xsed -e "$delay_single_quote_subst"`' +build_os='`$ECHO "X$build_os" | $Xsed -e "$delay_single_quote_subst"`' +SED='`$ECHO "X$SED" | $Xsed -e "$delay_single_quote_subst"`' +Xsed='`$ECHO "X$Xsed" | $Xsed -e "$delay_single_quote_subst"`' +GREP='`$ECHO "X$GREP" | $Xsed -e "$delay_single_quote_subst"`' +EGREP='`$ECHO "X$EGREP" | $Xsed -e "$delay_single_quote_subst"`' +FGREP='`$ECHO "X$FGREP" | $Xsed -e "$delay_single_quote_subst"`' +LD='`$ECHO "X$LD" | $Xsed -e "$delay_single_quote_subst"`' +NM='`$ECHO "X$NM" | $Xsed -e "$delay_single_quote_subst"`' +LN_S='`$ECHO "X$LN_S" | $Xsed -e "$delay_single_quote_subst"`' +max_cmd_len='`$ECHO "X$max_cmd_len" | $Xsed -e "$delay_single_quote_subst"`' +ac_objext='`$ECHO "X$ac_objext" | $Xsed -e "$delay_single_quote_subst"`' +exeext='`$ECHO "X$exeext" | $Xsed -e "$delay_single_quote_subst"`' +lt_unset='`$ECHO "X$lt_unset" | $Xsed -e "$delay_single_quote_subst"`' +lt_SP2NL='`$ECHO "X$lt_SP2NL" | $Xsed -e "$delay_single_quote_subst"`' +lt_NL2SP='`$ECHO "X$lt_NL2SP" | $Xsed -e "$delay_single_quote_subst"`' +reload_flag='`$ECHO "X$reload_flag" | $Xsed -e "$delay_single_quote_subst"`' +reload_cmds='`$ECHO "X$reload_cmds" | $Xsed -e "$delay_single_quote_subst"`' +OBJDUMP='`$ECHO "X$OBJDUMP" | $Xsed -e "$delay_single_quote_subst"`' +deplibs_check_method='`$ECHO "X$deplibs_check_method" | $Xsed -e "$delay_single_quote_subst"`' +file_magic_cmd='`$ECHO "X$file_magic_cmd" | $Xsed -e "$delay_single_quote_subst"`' +AR='`$ECHO "X$AR" | $Xsed -e "$delay_single_quote_subst"`' +AR_FLAGS='`$ECHO "X$AR_FLAGS" | $Xsed -e "$delay_single_quote_subst"`' +STRIP='`$ECHO "X$STRIP" | $Xsed -e "$delay_single_quote_subst"`' +RANLIB='`$ECHO "X$RANLIB" | $Xsed -e "$delay_single_quote_subst"`' +old_postinstall_cmds='`$ECHO "X$old_postinstall_cmds" | $Xsed -e "$delay_single_quote_subst"`' +old_postuninstall_cmds='`$ECHO "X$old_postuninstall_cmds" | $Xsed -e "$delay_single_quote_subst"`' +old_archive_cmds='`$ECHO "X$old_archive_cmds" | $Xsed -e "$delay_single_quote_subst"`' +CC='`$ECHO "X$CC" | $Xsed -e "$delay_single_quote_subst"`' +CFLAGS='`$ECHO "X$CFLAGS" | $Xsed -e "$delay_single_quote_subst"`' +compiler='`$ECHO "X$compiler" | $Xsed -e "$delay_single_quote_subst"`' +GCC='`$ECHO "X$GCC" | $Xsed -e "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_pipe='`$ECHO "X$lt_cv_sys_global_symbol_pipe" | $Xsed -e "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_to_cdecl='`$ECHO "X$lt_cv_sys_global_symbol_to_cdecl" | $Xsed -e "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_to_c_name_address='`$ECHO "X$lt_cv_sys_global_symbol_to_c_name_address" | $Xsed -e "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix='`$ECHO "X$lt_cv_sys_global_symbol_to_c_name_address_lib_prefix" | $Xsed -e "$delay_single_quote_subst"`' +objdir='`$ECHO "X$objdir" | $Xsed -e "$delay_single_quote_subst"`' +SHELL='`$ECHO "X$SHELL" | $Xsed -e "$delay_single_quote_subst"`' +ECHO='`$ECHO "X$ECHO" | $Xsed -e "$delay_single_quote_subst"`' +MAGIC_CMD='`$ECHO "X$MAGIC_CMD" | $Xsed -e "$delay_single_quote_subst"`' +lt_prog_compiler_no_builtin_flag='`$ECHO "X$lt_prog_compiler_no_builtin_flag" | $Xsed -e "$delay_single_quote_subst"`' +lt_prog_compiler_wl='`$ECHO "X$lt_prog_compiler_wl" | $Xsed -e "$delay_single_quote_subst"`' +lt_prog_compiler_pic='`$ECHO "X$lt_prog_compiler_pic" | $Xsed -e "$delay_single_quote_subst"`' +lt_prog_compiler_static='`$ECHO "X$lt_prog_compiler_static" | $Xsed -e "$delay_single_quote_subst"`' +lt_cv_prog_compiler_c_o='`$ECHO "X$lt_cv_prog_compiler_c_o" | $Xsed -e "$delay_single_quote_subst"`' +need_locks='`$ECHO "X$need_locks" | $Xsed -e "$delay_single_quote_subst"`' +DSYMUTIL='`$ECHO "X$DSYMUTIL" | $Xsed -e "$delay_single_quote_subst"`' +NMEDIT='`$ECHO "X$NMEDIT" | $Xsed -e "$delay_single_quote_subst"`' +LIPO='`$ECHO "X$LIPO" | $Xsed -e "$delay_single_quote_subst"`' +OTOOL='`$ECHO "X$OTOOL" | $Xsed -e "$delay_single_quote_subst"`' +OTOOL64='`$ECHO "X$OTOOL64" | $Xsed -e "$delay_single_quote_subst"`' +libext='`$ECHO "X$libext" | $Xsed -e "$delay_single_quote_subst"`' +shrext_cmds='`$ECHO "X$shrext_cmds" | $Xsed -e "$delay_single_quote_subst"`' +extract_expsyms_cmds='`$ECHO "X$extract_expsyms_cmds" | $Xsed -e "$delay_single_quote_subst"`' +archive_cmds_need_lc='`$ECHO "X$archive_cmds_need_lc" | $Xsed -e "$delay_single_quote_subst"`' +enable_shared_with_static_runtimes='`$ECHO "X$enable_shared_with_static_runtimes" | $Xsed -e "$delay_single_quote_subst"`' +export_dynamic_flag_spec='`$ECHO "X$export_dynamic_flag_spec" | $Xsed -e "$delay_single_quote_subst"`' +whole_archive_flag_spec='`$ECHO "X$whole_archive_flag_spec" | $Xsed -e "$delay_single_quote_subst"`' +compiler_needs_object='`$ECHO "X$compiler_needs_object" | $Xsed -e "$delay_single_quote_subst"`' +old_archive_from_new_cmds='`$ECHO "X$old_archive_from_new_cmds" | $Xsed -e "$delay_single_quote_subst"`' +old_archive_from_expsyms_cmds='`$ECHO "X$old_archive_from_expsyms_cmds" | $Xsed -e "$delay_single_quote_subst"`' +archive_cmds='`$ECHO "X$archive_cmds" | $Xsed -e "$delay_single_quote_subst"`' +archive_expsym_cmds='`$ECHO "X$archive_expsym_cmds" | $Xsed -e "$delay_single_quote_subst"`' +module_cmds='`$ECHO "X$module_cmds" | $Xsed -e "$delay_single_quote_subst"`' +module_expsym_cmds='`$ECHO "X$module_expsym_cmds" | $Xsed -e "$delay_single_quote_subst"`' +with_gnu_ld='`$ECHO "X$with_gnu_ld" | $Xsed -e "$delay_single_quote_subst"`' +allow_undefined_flag='`$ECHO "X$allow_undefined_flag" | $Xsed -e "$delay_single_quote_subst"`' +no_undefined_flag='`$ECHO "X$no_undefined_flag" | $Xsed -e "$delay_single_quote_subst"`' +hardcode_libdir_flag_spec='`$ECHO "X$hardcode_libdir_flag_spec" | $Xsed -e "$delay_single_quote_subst"`' +hardcode_libdir_flag_spec_ld='`$ECHO "X$hardcode_libdir_flag_spec_ld" | $Xsed -e "$delay_single_quote_subst"`' +hardcode_libdir_separator='`$ECHO "X$hardcode_libdir_separator" | $Xsed -e "$delay_single_quote_subst"`' +hardcode_direct='`$ECHO "X$hardcode_direct" | $Xsed -e "$delay_single_quote_subst"`' +hardcode_direct_absolute='`$ECHO "X$hardcode_direct_absolute" | $Xsed -e "$delay_single_quote_subst"`' +hardcode_minus_L='`$ECHO "X$hardcode_minus_L" | $Xsed -e "$delay_single_quote_subst"`' +hardcode_shlibpath_var='`$ECHO "X$hardcode_shlibpath_var" | $Xsed -e "$delay_single_quote_subst"`' +hardcode_automatic='`$ECHO "X$hardcode_automatic" | $Xsed -e "$delay_single_quote_subst"`' +inherit_rpath='`$ECHO "X$inherit_rpath" | $Xsed -e "$delay_single_quote_subst"`' +link_all_deplibs='`$ECHO "X$link_all_deplibs" | $Xsed -e "$delay_single_quote_subst"`' +fix_srcfile_path='`$ECHO "X$fix_srcfile_path" | $Xsed -e "$delay_single_quote_subst"`' +always_export_symbols='`$ECHO "X$always_export_symbols" | $Xsed -e "$delay_single_quote_subst"`' +export_symbols_cmds='`$ECHO "X$export_symbols_cmds" | $Xsed -e "$delay_single_quote_subst"`' +exclude_expsyms='`$ECHO "X$exclude_expsyms" | $Xsed -e "$delay_single_quote_subst"`' +include_expsyms='`$ECHO "X$include_expsyms" | $Xsed -e "$delay_single_quote_subst"`' +prelink_cmds='`$ECHO "X$prelink_cmds" | $Xsed -e "$delay_single_quote_subst"`' +file_list_spec='`$ECHO "X$file_list_spec" | $Xsed -e "$delay_single_quote_subst"`' +variables_saved_for_relink='`$ECHO "X$variables_saved_for_relink" | $Xsed -e "$delay_single_quote_subst"`' +need_lib_prefix='`$ECHO "X$need_lib_prefix" | $Xsed -e "$delay_single_quote_subst"`' +need_version='`$ECHO "X$need_version" | $Xsed -e "$delay_single_quote_subst"`' +version_type='`$ECHO "X$version_type" | $Xsed -e "$delay_single_quote_subst"`' +runpath_var='`$ECHO "X$runpath_var" | $Xsed -e "$delay_single_quote_subst"`' +shlibpath_var='`$ECHO "X$shlibpath_var" | $Xsed -e "$delay_single_quote_subst"`' +shlibpath_overrides_runpath='`$ECHO "X$shlibpath_overrides_runpath" | $Xsed -e "$delay_single_quote_subst"`' +libname_spec='`$ECHO "X$libname_spec" | $Xsed -e "$delay_single_quote_subst"`' +library_names_spec='`$ECHO "X$library_names_spec" | $Xsed -e "$delay_single_quote_subst"`' +soname_spec='`$ECHO "X$soname_spec" | $Xsed -e "$delay_single_quote_subst"`' +postinstall_cmds='`$ECHO "X$postinstall_cmds" | $Xsed -e "$delay_single_quote_subst"`' +postuninstall_cmds='`$ECHO "X$postuninstall_cmds" | $Xsed -e "$delay_single_quote_subst"`' +finish_cmds='`$ECHO "X$finish_cmds" | $Xsed -e "$delay_single_quote_subst"`' +finish_eval='`$ECHO "X$finish_eval" | $Xsed -e "$delay_single_quote_subst"`' +hardcode_into_libs='`$ECHO "X$hardcode_into_libs" | $Xsed -e "$delay_single_quote_subst"`' +sys_lib_search_path_spec='`$ECHO "X$sys_lib_search_path_spec" | $Xsed -e "$delay_single_quote_subst"`' +sys_lib_dlsearch_path_spec='`$ECHO "X$sys_lib_dlsearch_path_spec" | $Xsed -e "$delay_single_quote_subst"`' +hardcode_action='`$ECHO "X$hardcode_action" | $Xsed -e "$delay_single_quote_subst"`' +enable_dlopen='`$ECHO "X$enable_dlopen" | $Xsed -e "$delay_single_quote_subst"`' +enable_dlopen_self='`$ECHO "X$enable_dlopen_self" | $Xsed -e "$delay_single_quote_subst"`' +enable_dlopen_self_static='`$ECHO "X$enable_dlopen_self_static" | $Xsed -e "$delay_single_quote_subst"`' +old_striplib='`$ECHO "X$old_striplib" | $Xsed -e "$delay_single_quote_subst"`' +striplib='`$ECHO "X$striplib" | $Xsed -e "$delay_single_quote_subst"`' +compiler_lib_search_dirs='`$ECHO "X$compiler_lib_search_dirs" | $Xsed -e "$delay_single_quote_subst"`' +predep_objects='`$ECHO "X$predep_objects" | $Xsed -e "$delay_single_quote_subst"`' +postdep_objects='`$ECHO "X$postdep_objects" | $Xsed -e "$delay_single_quote_subst"`' +predeps='`$ECHO "X$predeps" | $Xsed -e "$delay_single_quote_subst"`' +postdeps='`$ECHO "X$postdeps" | $Xsed -e "$delay_single_quote_subst"`' +compiler_lib_search_path='`$ECHO "X$compiler_lib_search_path" | $Xsed -e "$delay_single_quote_subst"`' +LD_CXX='`$ECHO "X$LD_CXX" | $Xsed -e "$delay_single_quote_subst"`' +old_archive_cmds_CXX='`$ECHO "X$old_archive_cmds_CXX" | $Xsed -e "$delay_single_quote_subst"`' +compiler_CXX='`$ECHO "X$compiler_CXX" | $Xsed -e "$delay_single_quote_subst"`' +GCC_CXX='`$ECHO "X$GCC_CXX" | $Xsed -e "$delay_single_quote_subst"`' +lt_prog_compiler_no_builtin_flag_CXX='`$ECHO "X$lt_prog_compiler_no_builtin_flag_CXX" | $Xsed -e "$delay_single_quote_subst"`' +lt_prog_compiler_wl_CXX='`$ECHO "X$lt_prog_compiler_wl_CXX" | $Xsed -e "$delay_single_quote_subst"`' +lt_prog_compiler_pic_CXX='`$ECHO "X$lt_prog_compiler_pic_CXX" | $Xsed -e "$delay_single_quote_subst"`' +lt_prog_compiler_static_CXX='`$ECHO "X$lt_prog_compiler_static_CXX" | $Xsed -e "$delay_single_quote_subst"`' +lt_cv_prog_compiler_c_o_CXX='`$ECHO "X$lt_cv_prog_compiler_c_o_CXX" | $Xsed -e "$delay_single_quote_subst"`' +archive_cmds_need_lc_CXX='`$ECHO "X$archive_cmds_need_lc_CXX" | $Xsed -e "$delay_single_quote_subst"`' +enable_shared_with_static_runtimes_CXX='`$ECHO "X$enable_shared_with_static_runtimes_CXX" | $Xsed -e "$delay_single_quote_subst"`' +export_dynamic_flag_spec_CXX='`$ECHO "X$export_dynamic_flag_spec_CXX" | $Xsed -e "$delay_single_quote_subst"`' +whole_archive_flag_spec_CXX='`$ECHO "X$whole_archive_flag_spec_CXX" | $Xsed -e "$delay_single_quote_subst"`' +compiler_needs_object_CXX='`$ECHO "X$compiler_needs_object_CXX" | $Xsed -e "$delay_single_quote_subst"`' +old_archive_from_new_cmds_CXX='`$ECHO "X$old_archive_from_new_cmds_CXX" | $Xsed -e "$delay_single_quote_subst"`' +old_archive_from_expsyms_cmds_CXX='`$ECHO "X$old_archive_from_expsyms_cmds_CXX" | $Xsed -e "$delay_single_quote_subst"`' +archive_cmds_CXX='`$ECHO "X$archive_cmds_CXX" | $Xsed -e "$delay_single_quote_subst"`' +archive_expsym_cmds_CXX='`$ECHO "X$archive_expsym_cmds_CXX" | $Xsed -e "$delay_single_quote_subst"`' +module_cmds_CXX='`$ECHO "X$module_cmds_CXX" | $Xsed -e "$delay_single_quote_subst"`' +module_expsym_cmds_CXX='`$ECHO "X$module_expsym_cmds_CXX" | $Xsed -e "$delay_single_quote_subst"`' +with_gnu_ld_CXX='`$ECHO "X$with_gnu_ld_CXX" | $Xsed -e "$delay_single_quote_subst"`' +allow_undefined_flag_CXX='`$ECHO "X$allow_undefined_flag_CXX" | $Xsed -e "$delay_single_quote_subst"`' +no_undefined_flag_CXX='`$ECHO "X$no_undefined_flag_CXX" | $Xsed -e "$delay_single_quote_subst"`' +hardcode_libdir_flag_spec_CXX='`$ECHO "X$hardcode_libdir_flag_spec_CXX" | $Xsed -e "$delay_single_quote_subst"`' +hardcode_libdir_flag_spec_ld_CXX='`$ECHO "X$hardcode_libdir_flag_spec_ld_CXX" | $Xsed -e "$delay_single_quote_subst"`' +hardcode_libdir_separator_CXX='`$ECHO "X$hardcode_libdir_separator_CXX" | $Xsed -e "$delay_single_quote_subst"`' +hardcode_direct_CXX='`$ECHO "X$hardcode_direct_CXX" | $Xsed -e "$delay_single_quote_subst"`' +hardcode_direct_absolute_CXX='`$ECHO "X$hardcode_direct_absolute_CXX" | $Xsed -e "$delay_single_quote_subst"`' +hardcode_minus_L_CXX='`$ECHO "X$hardcode_minus_L_CXX" | $Xsed -e "$delay_single_quote_subst"`' +hardcode_shlibpath_var_CXX='`$ECHO "X$hardcode_shlibpath_var_CXX" | $Xsed -e "$delay_single_quote_subst"`' +hardcode_automatic_CXX='`$ECHO "X$hardcode_automatic_CXX" | $Xsed -e "$delay_single_quote_subst"`' +inherit_rpath_CXX='`$ECHO "X$inherit_rpath_CXX" | $Xsed -e "$delay_single_quote_subst"`' +link_all_deplibs_CXX='`$ECHO "X$link_all_deplibs_CXX" | $Xsed -e "$delay_single_quote_subst"`' +fix_srcfile_path_CXX='`$ECHO "X$fix_srcfile_path_CXX" | $Xsed -e "$delay_single_quote_subst"`' +always_export_symbols_CXX='`$ECHO "X$always_export_symbols_CXX" | $Xsed -e "$delay_single_quote_subst"`' +export_symbols_cmds_CXX='`$ECHO "X$export_symbols_cmds_CXX" | $Xsed -e "$delay_single_quote_subst"`' +exclude_expsyms_CXX='`$ECHO "X$exclude_expsyms_CXX" | $Xsed -e "$delay_single_quote_subst"`' +include_expsyms_CXX='`$ECHO "X$include_expsyms_CXX" | $Xsed -e "$delay_single_quote_subst"`' +prelink_cmds_CXX='`$ECHO "X$prelink_cmds_CXX" | $Xsed -e "$delay_single_quote_subst"`' +file_list_spec_CXX='`$ECHO "X$file_list_spec_CXX" | $Xsed -e "$delay_single_quote_subst"`' +hardcode_action_CXX='`$ECHO "X$hardcode_action_CXX" | $Xsed -e "$delay_single_quote_subst"`' +compiler_lib_search_dirs_CXX='`$ECHO "X$compiler_lib_search_dirs_CXX" | $Xsed -e "$delay_single_quote_subst"`' +predep_objects_CXX='`$ECHO "X$predep_objects_CXX" | $Xsed -e "$delay_single_quote_subst"`' +postdep_objects_CXX='`$ECHO "X$postdep_objects_CXX" | $Xsed -e "$delay_single_quote_subst"`' +predeps_CXX='`$ECHO "X$predeps_CXX" | $Xsed -e "$delay_single_quote_subst"`' +postdeps_CXX='`$ECHO "X$postdeps_CXX" | $Xsed -e "$delay_single_quote_subst"`' +compiler_lib_search_path_CXX='`$ECHO "X$compiler_lib_search_path_CXX" | $Xsed -e "$delay_single_quote_subst"`' + +LTCC='$LTCC' +LTCFLAGS='$LTCFLAGS' +compiler='$compiler_DEFAULT' + +# Quote evaled strings. +for var in SED \ +GREP \ +EGREP \ +FGREP \ +LD \ +NM \ +LN_S \ +lt_SP2NL \ +lt_NL2SP \ +reload_flag \ +OBJDUMP \ +deplibs_check_method \ +file_magic_cmd \ +AR \ +AR_FLAGS \ +STRIP \ +RANLIB \ +CC \ +CFLAGS \ +compiler \ +lt_cv_sys_global_symbol_pipe \ +lt_cv_sys_global_symbol_to_cdecl \ +lt_cv_sys_global_symbol_to_c_name_address \ +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix \ +SHELL \ +ECHO \ +lt_prog_compiler_no_builtin_flag \ +lt_prog_compiler_wl \ +lt_prog_compiler_pic \ +lt_prog_compiler_static \ +lt_cv_prog_compiler_c_o \ +need_locks \ +DSYMUTIL \ +NMEDIT \ +LIPO \ +OTOOL \ +OTOOL64 \ +shrext_cmds \ +export_dynamic_flag_spec \ +whole_archive_flag_spec \ +compiler_needs_object \ +with_gnu_ld \ +allow_undefined_flag \ +no_undefined_flag \ +hardcode_libdir_flag_spec \ +hardcode_libdir_flag_spec_ld \ +hardcode_libdir_separator \ +fix_srcfile_path \ +exclude_expsyms \ +include_expsyms \ +file_list_spec \ +variables_saved_for_relink \ +libname_spec \ +library_names_spec \ +soname_spec \ +finish_eval \ +old_striplib \ +striplib \ +compiler_lib_search_dirs \ +predep_objects \ +postdep_objects \ +predeps \ +postdeps \ +compiler_lib_search_path \ +LD_CXX \ +compiler_CXX \ +lt_prog_compiler_no_builtin_flag_CXX \ +lt_prog_compiler_wl_CXX \ +lt_prog_compiler_pic_CXX \ +lt_prog_compiler_static_CXX \ +lt_cv_prog_compiler_c_o_CXX \ +export_dynamic_flag_spec_CXX \ +whole_archive_flag_spec_CXX \ +compiler_needs_object_CXX \ +with_gnu_ld_CXX \ +allow_undefined_flag_CXX \ +no_undefined_flag_CXX \ +hardcode_libdir_flag_spec_CXX \ +hardcode_libdir_flag_spec_ld_CXX \ +hardcode_libdir_separator_CXX \ +fix_srcfile_path_CXX \ +exclude_expsyms_CXX \ +include_expsyms_CXX \ +file_list_spec_CXX \ +compiler_lib_search_dirs_CXX \ +predep_objects_CXX \ +postdep_objects_CXX \ +predeps_CXX \ +postdeps_CXX \ +compiler_lib_search_path_CXX; do + case \`eval \\\\\$ECHO "X\\\\\$\$var"\` in + *[\\\\\\\`\\"\\\$]*) + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"X\\\$\$var\\" | \\\$Xsed -e \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" + ;; + *) + eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" + ;; + esac +done + +# Double-quote double-evaled strings. +for var in reload_cmds \ +old_postinstall_cmds \ +old_postuninstall_cmds \ +old_archive_cmds \ +extract_expsyms_cmds \ +old_archive_from_new_cmds \ +old_archive_from_expsyms_cmds \ +archive_cmds \ +archive_expsym_cmds \ +module_cmds \ +module_expsym_cmds \ +export_symbols_cmds \ +prelink_cmds \ +postinstall_cmds \ +postuninstall_cmds \ +finish_cmds \ +sys_lib_search_path_spec \ +sys_lib_dlsearch_path_spec \ +old_archive_cmds_CXX \ +old_archive_from_new_cmds_CXX \ +old_archive_from_expsyms_cmds_CXX \ +archive_cmds_CXX \ +archive_expsym_cmds_CXX \ +module_cmds_CXX \ +module_expsym_cmds_CXX \ +export_symbols_cmds_CXX \ +prelink_cmds_CXX; do + case \`eval \\\\\$ECHO "X\\\\\$\$var"\` in + *[\\\\\\\`\\"\\\$]*) + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"X\\\$\$var\\" | \\\$Xsed -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" + ;; + *) + eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" + ;; + esac +done + +# Fix-up fallback echo if it was mangled by the above quoting rules. +case \$lt_ECHO in +*'\\\$0 --fallback-echo"') lt_ECHO=\`\$ECHO "X\$lt_ECHO" | \$Xsed -e 's/\\\\\\\\\\\\\\\$0 --fallback-echo"\$/\$0 --fallback-echo"/'\` + ;; +esac + +ac_aux_dir='$ac_aux_dir' +xsi_shell='$xsi_shell' +lt_shell_append='$lt_shell_append' + +# See if we are running on zsh, and set the options which allow our +# commands through without removal of \ escapes INIT. +if test -n "\${ZSH_VERSION+set}" ; then + setopt NO_GLOB_SUBST +fi + + + PACKAGE='$PACKAGE' + VERSION='$VERSION' + TIMESTAMP='$TIMESTAMP' + RM='$RM' + ofile='$ofile' + + + + + + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 + +# Handling of arguments. +for ac_config_target in $ac_config_targets +do + case $ac_config_target in + "clamavcxx-config.h") CONFIG_HEADERS="$CONFIG_HEADERS clamavcxx-config.h" ;; + "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; + "libtool") CONFIG_COMMANDS="$CONFIG_COMMANDS libtool" ;; + "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; + + *) as_fn_error "invalid argument: \`$ac_config_target'" "$LINENO" 5;; + esac +done + + +# If the user did not use the arguments to specify the items to instantiate, +# then the envvar interface is used. Set only those that are not. +# We use the long form for the default assignment because of an extremely +# bizarre bug on SunOS 4.1.3. +if $ac_need_defaults; then + test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files + test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers + test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands +fi + +# Have a temporary directory for convenience. Make it in the build tree +# simply because there is no reason against having it here, and in addition, +# creating and moving files from /tmp can sometimes cause problems. +# Hook for its removal unless debugging. +# Note that there is a small window in which the directory will not be cleaned: +# after its creation but before its name has been assigned to `$tmp'. +$debug || +{ + tmp= + trap 'exit_status=$? + { test -z "$tmp" || test ! -d "$tmp" || rm -fr "$tmp"; } && exit $exit_status +' 0 + trap 'as_fn_exit 1' 1 2 13 15 +} +# Create a (secure) tmp directory for tmp files. + +{ + tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && + test -n "$tmp" && test -d "$tmp" +} || +{ + tmp=./conf$$-$RANDOM + (umask 077 && mkdir "$tmp") +} || as_fn_error "cannot create a temporary directory in ." "$LINENO" 5 + +# Set up the scripts for CONFIG_FILES section. +# No need to generate them if there are no CONFIG_FILES. +# This happens for instance with `./config.status config.h'. +if test -n "$CONFIG_FILES"; then + + +ac_cr=`echo X | tr X '\015'` +# On cygwin, bash can eat \r inside `` if the user requested igncr. +# But we know of no other shell where ac_cr would be empty at this +# point, so we can use a bashism as a fallback. +if test "x$ac_cr" = x; then + eval ac_cr=\$\'\\r\' +fi +ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` +if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then + ac_cs_awk_cr='\r' +else + ac_cs_awk_cr=$ac_cr +fi + +echo 'BEGIN {' >"$tmp/subs1.awk" && +_ACEOF + + +{ + echo "cat >conf$$subs.awk <<_ACEOF" && + echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && + echo "_ACEOF" +} >conf$$subs.sh || + as_fn_error "could not make $CONFIG_STATUS" "$LINENO" 5 +ac_delim_num=`echo "$ac_subst_vars" | grep -c '$'` +ac_delim='%!_!# ' +for ac_last_try in false false false false false :; do + . ./conf$$subs.sh || + as_fn_error "could not make $CONFIG_STATUS" "$LINENO" 5 + + ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` + if test $ac_delim_n = $ac_delim_num; then + break + elif $ac_last_try; then + as_fn_error "could not make $CONFIG_STATUS" "$LINENO" 5 + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done +rm -f conf$$subs.sh + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +cat >>"\$tmp/subs1.awk" <<\\_ACAWK && +_ACEOF +sed -n ' +h +s/^/S["/; s/!.*/"]=/ +p +g +s/^[^!]*!// +:repl +t repl +s/'"$ac_delim"'$// +t delim +:nl +h +s/\(.\{148\}\)..*/\1/ +t more1 +s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ +p +n +b repl +:more1 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t nl +:delim +h +s/\(.\{148\}\)..*/\1/ +t more2 +s/["\\]/\\&/g; s/^/"/; s/$/"/ +p +b +:more2 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t delim +' >$CONFIG_STATUS || ac_write_fail=1 +rm -f conf$$subs.awk +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +_ACAWK +cat >>"\$tmp/subs1.awk" <<_ACAWK && + for (key in S) S_is_set[key] = 1 + FS = "" + +} +{ + line = $ 0 + nfields = split(line, field, "@") + substed = 0 + len = length(field[1]) + for (i = 2; i < nfields; i++) { + key = field[i] + keylen = length(key) + if (S_is_set[key]) { + value = S[key] + line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) + len += length(value) + length(field[++i]) + substed = 1 + } else + len += 1 + keylen + } + + print line +} + +_ACAWK +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then + sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" +else + cat +fi < "$tmp/subs1.awk" > "$tmp/subs.awk" \ + || as_fn_error "could not setup config files machinery" "$LINENO" 5 +_ACEOF + +# VPATH may cause trouble with some makes, so we remove $(srcdir), +# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and +# trailing colons and then remove the whole line if VPATH becomes empty +# (actually we leave an empty line to preserve line numbers). +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=/{ +s/:*\$(srcdir):*/:/ +s/:*\${srcdir}:*/:/ +s/:*@srcdir@:*/:/ +s/^\([^=]*=[ ]*\):*/\1/ +s/:*$// +s/^[^=]*=[ ]*$// +}' +fi + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +fi # test -n "$CONFIG_FILES" + +# Set up the scripts for CONFIG_HEADERS section. +# No need to generate them if there are no CONFIG_HEADERS. +# This happens for instance with `./config.status Makefile'. +if test -n "$CONFIG_HEADERS"; then +cat >"$tmp/defines.awk" <<\_ACAWK || +BEGIN { +_ACEOF + +# Transform confdefs.h into an awk script `defines.awk', embedded as +# here-document in config.status, that substitutes the proper values into +# config.h.in to produce config.h. + +# Create a delimiter string that does not exist in confdefs.h, to ease +# handling of long lines. +ac_delim='%!_!# ' +for ac_last_try in false false :; do + ac_t=`sed -n "/$ac_delim/p" confdefs.h` + if test -z "$ac_t"; then + break + elif $ac_last_try; then + as_fn_error "could not make $CONFIG_HEADERS" "$LINENO" 5 + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done + +# For the awk script, D is an array of macro values keyed by name, +# likewise P contains macro parameters if any. Preserve backslash +# newline sequences. + +ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* +sed -n ' +s/.\{148\}/&'"$ac_delim"'/g +t rset +:rset +s/^[ ]*#[ ]*define[ ][ ]*/ / +t def +d +:def +s/\\$// +t bsnl +s/["\\]/\\&/g +s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ +D["\1"]=" \3"/p +s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p +d +:bsnl +s/["\\]/\\&/g +s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ +D["\1"]=" \3\\\\\\n"\\/p +t cont +s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p +t cont +d +:cont +n +s/.\{148\}/&'"$ac_delim"'/g +t clear +:clear +s/\\$// +t bsnlc +s/["\\]/\\&/g; s/^/"/; s/$/"/p +d +:bsnlc +s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p +b cont +' >$CONFIG_STATUS || ac_write_fail=1 + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 + for (key in D) D_is_set[key] = 1 + FS = "" +} +/^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ { + line = \$ 0 + split(line, arg, " ") + if (arg[1] == "#") { + defundef = arg[2] + mac1 = arg[3] + } else { + defundef = substr(arg[1], 2) + mac1 = arg[2] + } + split(mac1, mac2, "(") #) + macro = mac2[1] + prefix = substr(line, 1, index(line, defundef) - 1) + if (D_is_set[macro]) { + # Preserve the white space surrounding the "#". + print prefix "define", macro P[macro] D[macro] + next + } else { + # Replace #undef with comments. This is necessary, for example, + # in the case of _POSIX_SOURCE, which is predefined and required + # on some systems where configure will not decide to define it. + if (defundef == "undef") { + print "/*", prefix defundef, macro, "*/" + next + } + } +} +{ print } +_ACAWK +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 + as_fn_error "could not setup config headers machinery" "$LINENO" 5 +fi # test -n "$CONFIG_HEADERS" + + +eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS :C $CONFIG_COMMANDS" +shift +for ac_tag +do + case $ac_tag in + :[FHLC]) ac_mode=$ac_tag; continue;; + esac + case $ac_mode$ac_tag in + :[FHL]*:*);; + :L* | :C*:*) as_fn_error "invalid tag \`$ac_tag'" "$LINENO" 5;; + :[FH]-) ac_tag=-:-;; + :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; + esac + ac_save_IFS=$IFS + IFS=: + set x $ac_tag + IFS=$ac_save_IFS + shift + ac_file=$1 + shift + + case $ac_mode in + :L) ac_source=$1;; + :[FH]) + ac_file_inputs= + for ac_f + do + case $ac_f in + -) ac_f="$tmp/stdin";; + *) # Look for the file first in the build tree, then in the source tree + # (if the path is not absolute). The absolute path cannot be DOS-style, + # because $ac_f cannot contain `:'. + test -f "$ac_f" || + case $ac_f in + [\\/$]*) false;; + *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; + esac || + as_fn_error "cannot find input file: \`$ac_f'" "$LINENO" 5;; + esac + case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac + as_fn_append ac_file_inputs " '$ac_f'" + done + + # Let's still pretend it is `configure' which instantiates (i.e., don't + # use $as_me), people would be surprised to read: + # /* config.h. Generated by config.status. */ + configure_input='Generated from '` + $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' + `' by configure.' + if test x"$ac_file" != x-; then + configure_input="$ac_file. $configure_input" + { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 +$as_echo "$as_me: creating $ac_file" >&6;} + fi + # Neutralize special characters interpreted by sed in replacement strings. + case $configure_input in #( + *\&* | *\|* | *\\* ) + ac_sed_conf_input=`$as_echo "$configure_input" | + sed 's/[\\\\&|]/\\\\&/g'`;; #( + *) ac_sed_conf_input=$configure_input;; + esac + + case $ac_tag in + *:-:* | *:-) cat >"$tmp/stdin" \ + || as_fn_error "could not create $ac_file" "$LINENO" 5 ;; + esac + ;; + esac + + ac_dir=`$as_dirname -- "$ac_file" || +$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + as_dir="$ac_dir"; as_fn_mkdir_p + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + + case $ac_mode in + :F) + # + # CONFIG_FILE + # + + case $INSTALL in + [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; + *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; + esac + ac_MKDIR_P=$MKDIR_P + case $MKDIR_P in + [\\/$]* | ?:[\\/]* ) ;; + */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;; + esac +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# If the template does not know about datarootdir, expand it. +# FIXME: This hack should be removed a few years after 2.60. +ac_datarootdir_hack=; ac_datarootdir_seen= +ac_sed_dataroot=' +/datarootdir/ { + p + q +} +/@datadir@/p +/@docdir@/p +/@infodir@/p +/@localedir@/p +/@mandir@/p' +case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in +*datarootdir*) ac_datarootdir_seen=yes;; +*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 +$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 + ac_datarootdir_hack=' + s&@datadir@&$datadir&g + s&@docdir@&$docdir&g + s&@infodir@&$infodir&g + s&@localedir@&$localedir&g + s&@mandir@&$mandir&g + s&\\\${datarootdir}&$datarootdir&g' ;; +esac +_ACEOF + +# Neutralize VPATH when `$srcdir' = `.'. +# Shell code in configure.ac might set extrasub. +# FIXME: do we really want to maintain this feature? +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_sed_extra="$ac_vpsub +$extrasub +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +:t +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b +s|@configure_input@|$ac_sed_conf_input|;t t +s&@top_builddir@&$ac_top_builddir_sub&;t t +s&@top_build_prefix@&$ac_top_build_prefix&;t t +s&@srcdir@&$ac_srcdir&;t t +s&@abs_srcdir@&$ac_abs_srcdir&;t t +s&@top_srcdir@&$ac_top_srcdir&;t t +s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t +s&@builddir@&$ac_builddir&;t t +s&@abs_builddir@&$ac_abs_builddir&;t t +s&@abs_top_builddir@&$ac_abs_top_builddir&;t t +s&@INSTALL@&$ac_INSTALL&;t t +s&@MKDIR_P@&$ac_MKDIR_P&;t t +$ac_datarootdir_hack +" +eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$tmp/subs.awk" >$tmp/out \ + || as_fn_error "could not create $ac_file" "$LINENO" 5 + +test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && + { ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } && + { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' "$tmp/out"`; test -z "$ac_out"; } && + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined." >&5 +$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined." >&2;} + + rm -f "$tmp/stdin" + case $ac_file in + -) cat "$tmp/out" && rm -f "$tmp/out";; + *) rm -f "$ac_file" && mv "$tmp/out" "$ac_file";; + esac \ + || as_fn_error "could not create $ac_file" "$LINENO" 5 + ;; + :H) + # + # CONFIG_HEADER + # + if test x"$ac_file" != x-; then + { + $as_echo "/* $configure_input */" \ + && eval '$AWK -f "$tmp/defines.awk"' "$ac_file_inputs" + } >"$tmp/config.h" \ + || as_fn_error "could not create $ac_file" "$LINENO" 5 + if diff "$ac_file" "$tmp/config.h" >/dev/null 2>&1; then + { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 +$as_echo "$as_me: $ac_file is unchanged" >&6;} + else + rm -f "$ac_file" + mv "$tmp/config.h" "$ac_file" \ + || as_fn_error "could not create $ac_file" "$LINENO" 5 + fi + else + $as_echo "/* $configure_input */" \ + && eval '$AWK -f "$tmp/defines.awk"' "$ac_file_inputs" \ + || as_fn_error "could not create -" "$LINENO" 5 + fi +# Compute "$ac_file"'s index in $config_headers. +_am_arg="$ac_file" +_am_stamp_count=1 +for _am_header in $config_headers :; do + case $_am_header in + $_am_arg | $_am_arg:* ) + break ;; + * ) + _am_stamp_count=`expr $_am_stamp_count + 1` ;; + esac +done +echo "timestamp for $_am_arg" >`$as_dirname -- "$_am_arg" || +$as_expr X"$_am_arg" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$_am_arg" : 'X\(//\)[^/]' \| \ + X"$_am_arg" : 'X\(//\)$' \| \ + X"$_am_arg" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$_am_arg" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'`/stamp-h$_am_stamp_count + ;; + + :C) { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5 +$as_echo "$as_me: executing $ac_file commands" >&6;} + ;; + esac + + + case $ac_file$ac_mode in + "depfiles":C) test x"$AMDEP_TRUE" != x"" || { + # Autoconf 2.62 quotes --file arguments for eval, but not when files + # are listed without --file. Let's play safe and only enable the eval + # if we detect the quoting. + case $CONFIG_FILES in + *\'*) eval set x "$CONFIG_FILES" ;; + *) set x $CONFIG_FILES ;; + esac + shift + for mf + do + # Strip MF so we end up with the name of the file. + mf=`echo "$mf" | sed -e 's/:.*$//'` + # Check whether this is an Automake generated Makefile or not. + # We used to match only the files named `Makefile.in', but + # some people rename them; so instead we look at the file content. + # Grep'ing the first line is not enough: some people post-process + # each Makefile.in and add a new line on top of each file to say so. + # Grep'ing the whole file is not good either: AIX grep has a line + # limit of 2048, but all sed's we know have understand at least 4000. + if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then + dirpart=`$as_dirname -- "$mf" || +$as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$mf" : 'X\(//\)[^/]' \| \ + X"$mf" : 'X\(//\)$' \| \ + X"$mf" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$mf" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + else + continue + fi + # Extract the definition of DEPDIR, am__include, and am__quote + # from the Makefile without running `make'. + DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` + test -z "$DEPDIR" && continue + am__include=`sed -n 's/^am__include = //p' < "$mf"` + test -z "am__include" && continue + am__quote=`sed -n 's/^am__quote = //p' < "$mf"` + # When using ansi2knr, U may be empty or an underscore; expand it + U=`sed -n 's/^U = //p' < "$mf"` + # Find all dependency output files, they are included files with + # $(DEPDIR) in their names. We invoke sed twice because it is the + # simplest approach to changing $(DEPDIR) to its actual value in the + # expansion. + for file in `sed -n " + s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ + sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do + # Make sure the directory exists. + test -f "$dirpart/$file" && continue + fdir=`$as_dirname -- "$file" || +$as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$file" : 'X\(//\)[^/]' \| \ + X"$file" : 'X\(//\)$' \| \ + X"$file" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + as_dir=$dirpart/$fdir; as_fn_mkdir_p + # echo "creating $dirpart/$file" + echo '# dummy' > "$dirpart/$file" + done + done +} + ;; + "libtool":C) + + # See if we are running on zsh, and set the options which allow our + # commands through without removal of \ escapes. + if test -n "${ZSH_VERSION+set}" ; then + setopt NO_GLOB_SUBST + fi + + cfgfile="${ofile}T" + trap "$RM \"$cfgfile\"; exit 1" 1 2 15 + $RM "$cfgfile" + + cat <<_LT_EOF >> "$cfgfile" +#! $SHELL + +# `$ECHO "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services. +# Generated automatically by $as_me ($PACKAGE$TIMESTAMP) $VERSION +# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: +# NOTE: Changes made to this file will be lost: look at ltmain.sh. +# +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, +# 2006, 2007, 2008 Free Software Foundation, Inc. +# Written by Gordon Matzigkeit, 1996 +# +# This file is part of GNU Libtool. +# +# GNU Libtool is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# As a special exception to the GNU General Public License, +# if you distribute this file as part of a program or library that +# is built using GNU Libtool, you may include this file under the +# same distribution terms that you use for the rest of that program. +# +# GNU Libtool is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Libtool; see the file COPYING. If not, a copy +# can be downloaded from http://www.gnu.org/licenses/gpl.html, or +# obtained by writing to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + +# The names of the tagged configurations supported by this script. +available_tags="CXX " + +# ### BEGIN LIBTOOL CONFIG + +# Which release of libtool.m4 was used? +macro_version=$macro_version +macro_revision=$macro_revision + +# Whether or not to build static libraries. +build_old_libs=$enable_static + +# Whether or not to build shared libraries. +build_libtool_libs=$enable_shared + +# What type of objects to build. +pic_mode=$pic_mode + +# Whether or not to optimize for fast installation. +fast_install=$enable_fast_install + +# The host system. +host_alias=$host_alias +host=$host +host_os=$host_os + +# The build system. +build_alias=$build_alias +build=$build +build_os=$build_os + +# A sed program that does not truncate output. +SED=$lt_SED + +# Sed that helps us avoid accidentally triggering echo(1) options like -n. +Xsed="\$SED -e 1s/^X//" + +# A grep program that handles long lines. +GREP=$lt_GREP + +# An ERE matcher. +EGREP=$lt_EGREP + +# A literal string matcher. +FGREP=$lt_FGREP + +# A BSD- or MS-compatible name lister. +NM=$lt_NM + +# Whether we need soft or hard links. +LN_S=$lt_LN_S + +# What is the maximum length of a command? +max_cmd_len=$max_cmd_len + +# Object file suffix (normally "o"). +objext=$ac_objext + +# Executable file suffix (normally ""). +exeext=$exeext + +# whether the shell understands "unset". +lt_unset=$lt_unset + +# turn spaces into newlines. +SP2NL=$lt_lt_SP2NL + +# turn newlines into spaces. +NL2SP=$lt_lt_NL2SP + +# How to create reloadable object files. +reload_flag=$lt_reload_flag +reload_cmds=$lt_reload_cmds + +# An object symbol dumper. +OBJDUMP=$lt_OBJDUMP + +# Method to check whether dependent libraries are shared objects. +deplibs_check_method=$lt_deplibs_check_method + +# Command to use when deplibs_check_method == "file_magic". +file_magic_cmd=$lt_file_magic_cmd + +# The archiver. +AR=$lt_AR +AR_FLAGS=$lt_AR_FLAGS + +# A symbol stripping program. +STRIP=$lt_STRIP + +# Commands used to install an old-style archive. +RANLIB=$lt_RANLIB +old_postinstall_cmds=$lt_old_postinstall_cmds +old_postuninstall_cmds=$lt_old_postuninstall_cmds + +# A C compiler. +LTCC=$lt_CC + +# LTCC compiler flags. +LTCFLAGS=$lt_CFLAGS + +# Take the output of nm and produce a listing of raw symbols and C names. +global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe + +# Transform the output of nm in a proper C declaration. +global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl + +# Transform the output of nm in a C name address pair. +global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address + +# Transform the output of nm in a C name address pair when lib prefix is needed. +global_symbol_to_c_name_address_lib_prefix=$lt_lt_cv_sys_global_symbol_to_c_name_address_lib_prefix + +# The name of the directory that contains temporary libtool files. +objdir=$objdir + +# Shell to use when invoking shell scripts. +SHELL=$lt_SHELL + +# An echo program that does not interpret backslashes. +ECHO=$lt_ECHO + +# Used to examine libraries when file_magic_cmd begins with "file". +MAGIC_CMD=$MAGIC_CMD + +# Must we lock files when doing compilation? +need_locks=$lt_need_locks + +# Tool to manipulate archived DWARF debug symbol files on Mac OS X. +DSYMUTIL=$lt_DSYMUTIL + +# Tool to change global to local symbols on Mac OS X. +NMEDIT=$lt_NMEDIT + +# Tool to manipulate fat objects and archives on Mac OS X. +LIPO=$lt_LIPO + +# ldd/readelf like tool for Mach-O binaries on Mac OS X. +OTOOL=$lt_OTOOL + +# ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4. +OTOOL64=$lt_OTOOL64 + +# Old archive suffix (normally "a"). +libext=$libext + +# Shared library suffix (normally ".so"). +shrext_cmds=$lt_shrext_cmds + +# The commands to extract the exported symbol list from a shared archive. +extract_expsyms_cmds=$lt_extract_expsyms_cmds + +# Variables whose values should be saved in libtool wrapper scripts and +# restored at link time. +variables_saved_for_relink=$lt_variables_saved_for_relink + +# Do we need the "lib" prefix for modules? +need_lib_prefix=$need_lib_prefix + +# Do we need a version for libraries? +need_version=$need_version + +# Library versioning type. +version_type=$version_type + +# Shared library runtime path variable. +runpath_var=$runpath_var + +# Shared library path variable. +shlibpath_var=$shlibpath_var + +# Is shlibpath searched before the hard-coded library search path? +shlibpath_overrides_runpath=$shlibpath_overrides_runpath + +# Format of library name prefix. +libname_spec=$lt_libname_spec + +# List of archive names. First name is the real one, the rest are links. +# The last name is the one that the linker finds with -lNAME +library_names_spec=$lt_library_names_spec + +# The coded name of the library, if different from the real name. +soname_spec=$lt_soname_spec + +# Command to use after installation of a shared archive. +postinstall_cmds=$lt_postinstall_cmds + +# Command to use after uninstallation of a shared archive. +postuninstall_cmds=$lt_postuninstall_cmds + +# Commands used to finish a libtool library installation in a directory. +finish_cmds=$lt_finish_cmds + +# As "finish_cmds", except a single script fragment to be evaled but +# not shown. +finish_eval=$lt_finish_eval + +# Whether we should hardcode library paths into libraries. +hardcode_into_libs=$hardcode_into_libs + +# Compile-time system search path for libraries. +sys_lib_search_path_spec=$lt_sys_lib_search_path_spec + +# Run-time system search path for libraries. +sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec + +# Whether dlopen is supported. +dlopen_support=$enable_dlopen + +# Whether dlopen of programs is supported. +dlopen_self=$enable_dlopen_self + +# Whether dlopen of statically linked programs is supported. +dlopen_self_static=$enable_dlopen_self_static + +# Commands to strip libraries. +old_striplib=$lt_old_striplib +striplib=$lt_striplib + + +# The linker used to build libraries. +LD=$lt_LD + +# Commands used to build an old-style archive. +old_archive_cmds=$lt_old_archive_cmds + +# A language specific compiler. +CC=$lt_compiler + +# Is the compiler the GNU compiler? +with_gcc=$GCC + +# Compiler flag to turn off builtin functions. +no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag + +# How to pass a linker flag through the compiler. +wl=$lt_lt_prog_compiler_wl + +# Additional compiler flags for building library objects. +pic_flag=$lt_lt_prog_compiler_pic + +# Compiler flag to prevent dynamic linking. +link_static_flag=$lt_lt_prog_compiler_static + +# Does compiler simultaneously support -c and -o options? +compiler_c_o=$lt_lt_cv_prog_compiler_c_o + +# Whether or not to add -lc for building shared libraries. +build_libtool_need_lc=$archive_cmds_need_lc + +# Whether or not to disallow shared libs when runtime libs are static. +allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes + +# Compiler flag to allow reflexive dlopens. +export_dynamic_flag_spec=$lt_export_dynamic_flag_spec + +# Compiler flag to generate shared objects directly from archives. +whole_archive_flag_spec=$lt_whole_archive_flag_spec + +# Whether the compiler copes with passing no objects directly. +compiler_needs_object=$lt_compiler_needs_object + +# Create an old-style archive from a shared archive. +old_archive_from_new_cmds=$lt_old_archive_from_new_cmds + +# Create a temporary old-style archive to link instead of a shared archive. +old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds + +# Commands used to build a shared archive. +archive_cmds=$lt_archive_cmds +archive_expsym_cmds=$lt_archive_expsym_cmds + +# Commands used to build a loadable module if different from building +# a shared archive. +module_cmds=$lt_module_cmds +module_expsym_cmds=$lt_module_expsym_cmds + +# Whether we are building with GNU ld or not. +with_gnu_ld=$lt_with_gnu_ld + +# Flag that allows shared libraries with undefined symbols to be built. +allow_undefined_flag=$lt_allow_undefined_flag + +# Flag that enforces no undefined symbols. +no_undefined_flag=$lt_no_undefined_flag + +# Flag to hardcode \$libdir into a binary during linking. +# This must work even if \$libdir does not exist +hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec + +# If ld is used when linking, flag to hardcode \$libdir into a binary +# during linking. This must work even if \$libdir does not exist. +hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld + +# Whether we need a single "-rpath" flag with a separated argument. +hardcode_libdir_separator=$lt_hardcode_libdir_separator + +# Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes +# DIR into the resulting binary. +hardcode_direct=$hardcode_direct + +# Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes +# DIR into the resulting binary and the resulting library dependency is +# "absolute",i.e impossible to change by setting \${shlibpath_var} if the +# library is relocated. +hardcode_direct_absolute=$hardcode_direct_absolute + +# Set to "yes" if using the -LDIR flag during linking hardcodes DIR +# into the resulting binary. +hardcode_minus_L=$hardcode_minus_L + +# Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR +# into the resulting binary. +hardcode_shlibpath_var=$hardcode_shlibpath_var + +# Set to "yes" if building a shared library automatically hardcodes DIR +# into the library and all subsequent libraries and executables linked +# against it. +hardcode_automatic=$hardcode_automatic + +# Set to yes if linker adds runtime paths of dependent libraries +# to runtime path list. +inherit_rpath=$inherit_rpath + +# Whether libtool must link a program against all its dependency libraries. +link_all_deplibs=$link_all_deplibs + +# Fix the shell variable \$srcfile for the compiler. +fix_srcfile_path=$lt_fix_srcfile_path + +# Set to "yes" if exported symbols are required. +always_export_symbols=$always_export_symbols + +# The commands to list exported symbols. +export_symbols_cmds=$lt_export_symbols_cmds + +# Symbols that should not be listed in the preloaded symbols. +exclude_expsyms=$lt_exclude_expsyms + +# Symbols that must always be exported. +include_expsyms=$lt_include_expsyms + +# Commands necessary for linking programs (against libraries) with templates. +prelink_cmds=$lt_prelink_cmds + +# Specify filename containing input files. +file_list_spec=$lt_file_list_spec + +# How to hardcode a shared library path into an executable. +hardcode_action=$hardcode_action + +# The directories searched by this compiler when creating a shared library. +compiler_lib_search_dirs=$lt_compiler_lib_search_dirs + +# Dependencies to place before and after the objects being linked to +# create a shared library. +predep_objects=$lt_predep_objects +postdep_objects=$lt_postdep_objects +predeps=$lt_predeps +postdeps=$lt_postdeps + +# The library search path used internally by the compiler when linking +# a shared library. +compiler_lib_search_path=$lt_compiler_lib_search_path + +# ### END LIBTOOL CONFIG + +_LT_EOF + + case $host_os in + aix3*) + cat <<\_LT_EOF >> "$cfgfile" +# AIX sometimes has problems with the GCC collect2 program. For some +# reason, if we set the COLLECT_NAMES environment variable, the problems +# vanish in a puff of smoke. +if test "X${COLLECT_NAMES+set}" != Xset; then + COLLECT_NAMES= + export COLLECT_NAMES +fi +_LT_EOF + ;; + esac + + +ltmain="$ac_aux_dir/ltmain.sh" + + + # We use sed instead of cat because bash on DJGPP gets confused if + # if finds mixed CR/LF and LF-only lines. Since sed operates in + # text mode, it properly converts lines to CR/LF. This bash problem + # is reportedly fixed, but why not run on old versions too? + sed '/^# Generated shell functions inserted here/q' "$ltmain" >> "$cfgfile" \ + || (rm -f "$cfgfile"; exit 1) + + case $xsi_shell in + yes) + cat << \_LT_EOF >> "$cfgfile" + +# func_dirname file append nondir_replacement +# Compute the dirname of FILE. If nonempty, add APPEND to the result, +# otherwise set result to NONDIR_REPLACEMENT. +func_dirname () +{ + case ${1} in + */*) func_dirname_result="${1%/*}${2}" ;; + * ) func_dirname_result="${3}" ;; + esac +} + +# func_basename file +func_basename () +{ + func_basename_result="${1##*/}" +} + +# func_dirname_and_basename file append nondir_replacement +# perform func_basename and func_dirname in a single function +# call: +# dirname: Compute the dirname of FILE. If nonempty, +# add APPEND to the result, otherwise set result +# to NONDIR_REPLACEMENT. +# value returned in "$func_dirname_result" +# basename: Compute filename of FILE. +# value retuned in "$func_basename_result" +# Implementation must be kept synchronized with func_dirname +# and func_basename. For efficiency, we do not delegate to +# those functions but instead duplicate the functionality here. +func_dirname_and_basename () +{ + case ${1} in + */*) func_dirname_result="${1%/*}${2}" ;; + * ) func_dirname_result="${3}" ;; + esac + func_basename_result="${1##*/}" +} + +# func_stripname prefix suffix name +# strip PREFIX and SUFFIX off of NAME. +# PREFIX and SUFFIX must not contain globbing or regex special +# characters, hashes, percent signs, but SUFFIX may contain a leading +# dot (in which case that matches only a dot). +func_stripname () +{ + # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are + # positional parameters, so assign one to ordinary parameter first. + func_stripname_result=${3} + func_stripname_result=${func_stripname_result#"${1}"} + func_stripname_result=${func_stripname_result%"${2}"} +} + +# func_opt_split +func_opt_split () +{ + func_opt_split_opt=${1%%=*} + func_opt_split_arg=${1#*=} +} + +# func_lo2o object +func_lo2o () +{ + case ${1} in + *.lo) func_lo2o_result=${1%.lo}.${objext} ;; + *) func_lo2o_result=${1} ;; + esac +} + +# func_xform libobj-or-source +func_xform () +{ + func_xform_result=${1%.*}.lo +} + +# func_arith arithmetic-term... +func_arith () +{ + func_arith_result=$(( $* )) +} + +# func_len string +# STRING may not start with a hyphen. +func_len () +{ + func_len_result=${#1} +} + +_LT_EOF + ;; + *) # Bourne compatible functions. + cat << \_LT_EOF >> "$cfgfile" + +# func_dirname file append nondir_replacement +# Compute the dirname of FILE. If nonempty, add APPEND to the result, +# otherwise set result to NONDIR_REPLACEMENT. +func_dirname () +{ + # Extract subdirectory from the argument. + func_dirname_result=`$ECHO "X${1}" | $Xsed -e "$dirname"` + if test "X$func_dirname_result" = "X${1}"; then + func_dirname_result="${3}" + else + func_dirname_result="$func_dirname_result${2}" + fi +} + +# func_basename file +func_basename () +{ + func_basename_result=`$ECHO "X${1}" | $Xsed -e "$basename"` +} + + +# func_stripname prefix suffix name +# strip PREFIX and SUFFIX off of NAME. +# PREFIX and SUFFIX must not contain globbing or regex special +# characters, hashes, percent signs, but SUFFIX may contain a leading +# dot (in which case that matches only a dot). +# func_strip_suffix prefix name +func_stripname () +{ + case ${2} in + .*) func_stripname_result=`$ECHO "X${3}" \ + | $Xsed -e "s%^${1}%%" -e "s%\\\\${2}\$%%"`;; + *) func_stripname_result=`$ECHO "X${3}" \ + | $Xsed -e "s%^${1}%%" -e "s%${2}\$%%"`;; + esac +} + +# sed scripts: +my_sed_long_opt='1s/^\(-[^=]*\)=.*/\1/;q' +my_sed_long_arg='1s/^-[^=]*=//' + +# func_opt_split +func_opt_split () +{ + func_opt_split_opt=`$ECHO "X${1}" | $Xsed -e "$my_sed_long_opt"` + func_opt_split_arg=`$ECHO "X${1}" | $Xsed -e "$my_sed_long_arg"` +} + +# func_lo2o object +func_lo2o () +{ + func_lo2o_result=`$ECHO "X${1}" | $Xsed -e "$lo2o"` +} + +# func_xform libobj-or-source +func_xform () +{ + func_xform_result=`$ECHO "X${1}" | $Xsed -e 's/\.[^.]*$/.lo/'` +} + +# func_arith arithmetic-term... +func_arith () +{ + func_arith_result=`expr "$@"` +} + +# func_len string +# STRING may not start with a hyphen. +func_len () +{ + func_len_result=`expr "$1" : ".*" 2>/dev/null || echo $max_cmd_len` +} + +_LT_EOF +esac + +case $lt_shell_append in + yes) + cat << \_LT_EOF >> "$cfgfile" + +# func_append var value +# Append VALUE to the end of shell variable VAR. +func_append () +{ + eval "$1+=\$2" +} +_LT_EOF + ;; + *) + cat << \_LT_EOF >> "$cfgfile" + +# func_append var value +# Append VALUE to the end of shell variable VAR. +func_append () +{ + eval "$1=\$$1\$2" +} + +_LT_EOF + ;; + esac + + + sed -n '/^# Generated shell functions inserted here/,$p' "$ltmain" >> "$cfgfile" \ + || (rm -f "$cfgfile"; exit 1) + + mv -f "$cfgfile" "$ofile" || + (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") + chmod +x "$ofile" + + + cat <<_LT_EOF >> "$ofile" + +# ### BEGIN LIBTOOL TAG CONFIG: CXX + +# The linker used to build libraries. +LD=$lt_LD_CXX + +# Commands used to build an old-style archive. +old_archive_cmds=$lt_old_archive_cmds_CXX + +# A language specific compiler. +CC=$lt_compiler_CXX + +# Is the compiler the GNU compiler? +with_gcc=$GCC_CXX + +# Compiler flag to turn off builtin functions. +no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_CXX + +# How to pass a linker flag through the compiler. +wl=$lt_lt_prog_compiler_wl_CXX + +# Additional compiler flags for building library objects. +pic_flag=$lt_lt_prog_compiler_pic_CXX + +# Compiler flag to prevent dynamic linking. +link_static_flag=$lt_lt_prog_compiler_static_CXX + +# Does compiler simultaneously support -c and -o options? +compiler_c_o=$lt_lt_cv_prog_compiler_c_o_CXX + +# Whether or not to add -lc for building shared libraries. +build_libtool_need_lc=$archive_cmds_need_lc_CXX + +# Whether or not to disallow shared libs when runtime libs are static. +allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes_CXX + +# Compiler flag to allow reflexive dlopens. +export_dynamic_flag_spec=$lt_export_dynamic_flag_spec_CXX + +# Compiler flag to generate shared objects directly from archives. +whole_archive_flag_spec=$lt_whole_archive_flag_spec_CXX + +# Whether the compiler copes with passing no objects directly. +compiler_needs_object=$lt_compiler_needs_object_CXX + +# Create an old-style archive from a shared archive. +old_archive_from_new_cmds=$lt_old_archive_from_new_cmds_CXX + +# Create a temporary old-style archive to link instead of a shared archive. +old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds_CXX + +# Commands used to build a shared archive. +archive_cmds=$lt_archive_cmds_CXX +archive_expsym_cmds=$lt_archive_expsym_cmds_CXX + +# Commands used to build a loadable module if different from building +# a shared archive. +module_cmds=$lt_module_cmds_CXX +module_expsym_cmds=$lt_module_expsym_cmds_CXX + +# Whether we are building with GNU ld or not. +with_gnu_ld=$lt_with_gnu_ld_CXX + +# Flag that allows shared libraries with undefined symbols to be built. +allow_undefined_flag=$lt_allow_undefined_flag_CXX + +# Flag that enforces no undefined symbols. +no_undefined_flag=$lt_no_undefined_flag_CXX + +# Flag to hardcode \$libdir into a binary during linking. +# This must work even if \$libdir does not exist +hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_CXX + +# If ld is used when linking, flag to hardcode \$libdir into a binary +# during linking. This must work even if \$libdir does not exist. +hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld_CXX + +# Whether we need a single "-rpath" flag with a separated argument. +hardcode_libdir_separator=$lt_hardcode_libdir_separator_CXX + +# Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes +# DIR into the resulting binary. +hardcode_direct=$hardcode_direct_CXX + +# Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes +# DIR into the resulting binary and the resulting library dependency is +# "absolute",i.e impossible to change by setting \${shlibpath_var} if the +# library is relocated. +hardcode_direct_absolute=$hardcode_direct_absolute_CXX + +# Set to "yes" if using the -LDIR flag during linking hardcodes DIR +# into the resulting binary. +hardcode_minus_L=$hardcode_minus_L_CXX + +# Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR +# into the resulting binary. +hardcode_shlibpath_var=$hardcode_shlibpath_var_CXX + +# Set to "yes" if building a shared library automatically hardcodes DIR +# into the library and all subsequent libraries and executables linked +# against it. +hardcode_automatic=$hardcode_automatic_CXX + +# Set to yes if linker adds runtime paths of dependent libraries +# to runtime path list. +inherit_rpath=$inherit_rpath_CXX + +# Whether libtool must link a program against all its dependency libraries. +link_all_deplibs=$link_all_deplibs_CXX + +# Fix the shell variable \$srcfile for the compiler. +fix_srcfile_path=$lt_fix_srcfile_path_CXX + +# Set to "yes" if exported symbols are required. +always_export_symbols=$always_export_symbols_CXX + +# The commands to list exported symbols. +export_symbols_cmds=$lt_export_symbols_cmds_CXX + +# Symbols that should not be listed in the preloaded symbols. +exclude_expsyms=$lt_exclude_expsyms_CXX + +# Symbols that must always be exported. +include_expsyms=$lt_include_expsyms_CXX + +# Commands necessary for linking programs (against libraries) with templates. +prelink_cmds=$lt_prelink_cmds_CXX + +# Specify filename containing input files. +file_list_spec=$lt_file_list_spec_CXX + +# How to hardcode a shared library path into an executable. +hardcode_action=$hardcode_action_CXX + +# The directories searched by this compiler when creating a shared library. +compiler_lib_search_dirs=$lt_compiler_lib_search_dirs_CXX + +# Dependencies to place before and after the objects being linked to +# create a shared library. +predep_objects=$lt_predep_objects_CXX +postdep_objects=$lt_postdep_objects_CXX +predeps=$lt_predeps_CXX +postdeps=$lt_postdeps_CXX + +# The library search path used internally by the compiler when linking +# a shared library. +compiler_lib_search_path=$lt_compiler_lib_search_path_CXX + +# ### END LIBTOOL TAG CONFIG: CXX +_LT_EOF + + ;; + + esac +done # for ac_tag + + +as_fn_exit 0 +_ACEOF +ac_clean_files=$ac_clean_files_save + +test $ac_write_fail = 0 || + as_fn_error "write failure creating $CONFIG_STATUS" "$LINENO" 5 + + +# configure is writing to config.log, and then calls config.status. +# config.status does its own redirection, appending to config.log. +# Unfortunately, on DOS this fails, as config.log is still kept open +# by configure, so config.status won't be able to write to it; its +# output is simply discarded. So we exec the FD to /dev/null, +# effectively closing config.log, so it can be properly (re)opened and +# appended to by config.status. When coming back to configure, we +# need to make the FD available again. +if test "$no_create" != yes; then + ac_cs_success=: + ac_config_status_args= + test "$silent" = yes && + ac_config_status_args="$ac_config_status_args --quiet" + exec 5>/dev/null + $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false + exec 5>>config.log + # Use ||, not &&, to avoid exiting from the if with $? = 1, which + # would make configure fail if this is the last instruction. + $ac_cs_success || as_fn_exit $? +fi + +# +# CONFIG_SUBDIRS section. +# +if test "$no_recursion" != yes; then + + # Remove --cache-file, --srcdir, and --disable-option-checking arguments + # so they do not pile up. + ac_sub_configure_args= + ac_prev= + eval "set x $ac_configure_args" + shift + for ac_arg + do + if test -n "$ac_prev"; then + ac_prev= + continue + fi + case $ac_arg in + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* \ + | --c=*) + ;; + --config-cache | -C) + ;; + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + ;; + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + ;; + --disable-option-checking) + ;; + *) + case $ac_arg in + *\'*) ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + as_fn_append ac_sub_configure_args " '$ac_arg'" ;; + esac + done + + # Always prepend --prefix to ensure using the same prefix + # in subdir configurations. + ac_arg="--prefix=$prefix" + case $ac_arg in + *\'*) ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + ac_sub_configure_args="'$ac_arg' $ac_sub_configure_args" + + # Pass --silent + if test "$silent" = yes; then + ac_sub_configure_args="--silent $ac_sub_configure_args" + fi + + # Always prepend --disable-option-checking to silence warnings, since + # different subdirs can have different --enable and --with options. + ac_sub_configure_args="--disable-option-checking $ac_sub_configure_args" + + ac_popdir=`pwd` + for ac_dir in : $subdirs; do test "x$ac_dir" = x: && continue + + # Do not complain, so a configure script can configure whichever + # parts of a large source tree are present. + test -d "$srcdir/$ac_dir" || continue + + ac_msg="=== configuring in $ac_dir (`pwd`/$ac_dir)" + $as_echo "$as_me:${as_lineno-$LINENO}: $ac_msg" >&5 + $as_echo "$ac_msg" >&6 + as_dir="$ac_dir"; as_fn_mkdir_p + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + + cd "$ac_dir" + + # Check for guested configure; otherwise get Cygnus style configure. + if test -f "$ac_srcdir/configure.gnu"; then + ac_sub_configure=$ac_srcdir/configure.gnu + elif test -f "$ac_srcdir/configure"; then + ac_sub_configure=$ac_srcdir/configure + elif test -f "$ac_srcdir/configure.in"; then + # This should be Cygnus configure. + ac_sub_configure=$ac_aux_dir/configure + else + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: no configuration information is in $ac_dir" >&5 +$as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2;} + ac_sub_configure= + fi + + # The recursion is here. + if test -n "$ac_sub_configure"; then + # Make the cache file name correct relative to the subdirectory. + case $cache_file in + [\\/]* | ?:[\\/]* ) ac_sub_cache_file=$cache_file ;; + *) # Relative name. + ac_sub_cache_file=$ac_top_build_prefix$cache_file ;; + esac + + { $as_echo "$as_me:${as_lineno-$LINENO}: running $SHELL $ac_sub_configure $ac_sub_configure_args --cache-file=$ac_sub_cache_file --srcdir=$ac_srcdir" >&5 +$as_echo "$as_me: running $SHELL $ac_sub_configure $ac_sub_configure_args --cache-file=$ac_sub_cache_file --srcdir=$ac_srcdir" >&6;} + # The eval makes quoting arguments work. + eval "\$SHELL \"\$ac_sub_configure\" $ac_sub_configure_args \ + --cache-file=\"\$ac_sub_cache_file\" --srcdir=\"\$ac_srcdir\"" || + as_fn_error "$ac_sub_configure failed for $ac_dir" "$LINENO" 5 + fi + + cd "$ac_popdir" + done +fi +if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 +$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} +fi + diff --git a/libclamav/c++/configure.ac b/libclamav/c++/configure.ac new file mode 100644 index 000000000..e637c550d --- /dev/null +++ b/libclamav/c++/configure.ac @@ -0,0 +1,137 @@ +dnl This program is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2 of the License, or +dnl (at your option) any later version. +dnl +dnl This program is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with this program; if not, write to the Free Software +dnl Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +dnl MA 02110-1301, USA. + +AC_PREREQ([2.59]) +AC_INIT([libclamavc++],[devel],[http://bugs.clamav.net]) +AC_CONFIG_AUX_DIR([config]) +AC_CONFIG_SRCDIR([llvm/configure]) +AC_CONFIG_MACRO_DIR([m4]) +AC_CONFIG_HEADER([clamavcxx-config.h]) +AC_CANONICAL_TARGET +AM_INIT_AUTOMAKE([1.9 -Wall -Wportability -Werror foreign no-define color-tests tar-pax]) +AM_SILENT_RULES([yes]) + +cxxset=${CXXFLAGS+set} +AC_PROG_CXX + +if test "$cxxset" != set; then +# don't use the default -O2 -g because -g bloats the C++ binaries too much + CXXFLAGS="-O2" +fi + +AM_MAINTAINER_MODE +LT_INIT([disable-static]) +if test "$GXX" != "yes"; then + AC_MSG_ERROR([GNU C++ compiler not found, not building LLVM]) +fi + +AC_CHECK_GNU_MAKE +GMAKE="$llvm_cv_gnu_make_command" +AC_SUBST([GMAKE]) +AC_CONFIG_SUBDIRS([llvm]) +AC_ARG_ENABLE([llvm],AC_HELP_STRING([-enable-llvm], + [Enable 'llvm' JIT/verifier support @<:@default=auto@:>@]), + [enable_llvm=$enableval], [enable_llvm="auto"]) + +AC_ARG_ENABLE(optimized, AC_HELP_STRING([-enable-optimized], + [Compile with optimizations enabled (default is YES)]), + enable_optimized=$enableval, enable_optimized=default) +AM_CONDITIONAL(DEBUG_BUILD,[test "x$enable_optimized" == "xno"]) + +dnl Set configure args for subdir +if test "$enable_optimized" = "default"; then + ac_configure_args="$ac_configure_args --enable-optimized" +fi + +dnl Pretend that GNU make is available for LLVM, we don't use LLVM's buildsystem +dnl anyway (except for make check) +ac_configure_args="$ac_configure_args llvm_cv_gnu_make_command=make" +AC_ARG_ENABLE(all-jit-targets, AC_HELP_STRING([-enable-all-jit-targets], + [Build all the targets that support JIT for testing (default NO)]), + enable_alltargets=$enableval, enable_alltargets=no) +if test "$enable_alltargets" = "yes"; then + new_args="$ac_configure_args --enable-targets=x86,powerpc,arm --enable-bindings=none --enable-libffi=no --without-llvmgcc --without-llvmgxx" +else + new_args="$ac_configure_args --enable-targets=host-only --enable-bindings=none --enable-libffi=no --without-llvmgcc --without-llvmgxx" +fi +echo "$new_args" +ac_configure_args=`echo $new_args | sed -e 's/-Werror //g'` +echo "$ac_configure_args" + +if test "$enable_llvm" = "auto"; then + dnl Do some sanity checks, and don't automatically build on platforms + dnl that are not supported or have broken compilers. + dnl The user can override this by specifying --enable-llvm=yes. + AC_MSG_CHECKING([for supported C++ compiler version]) + gxx_version=`${CXX} -dumpversion` || + AC_MSG_ERROR([Unable to get GNU C++ compiler version]) + case "${gxx_version}" in + [[012]].*|3.[[0123]].*) + AC_MSG_ERROR([C++ compiler too old (${gxx_version})]) + ;; + 3.4.[[012]]*|4.0.1*|4.1.[[12]]*) + AC_MSG_ERROR([C++ compiler is buggy]) + ;; + *) + AC_MSG_RESULT([ok (${gxx_version})]) + esac + + AC_MSG_CHECKING([for supported OS]) + case "$target_cpu" in + i?86|amd64|x86_64|powerpc*) + case "$target_os" in + darwin*|freebsd*|openbsd*|netbsd*|dragonfly*|linux*|solaris*|win32*|mingw*) + AC_MSG_RESULT([ok ($target_cpu-$target_os)]) + ;; + *) + AC_MSG_ERROR([OS $target_os is not supported, not building LLVM]) + ;; + esac + ;; + alpha*|arm*) + AC_MSG_ERROR([CPU support is untested, not building LLVM]) + ;; + *) + AC_MSG_ERROR([Unsupported CPU for JIT: $target_cpu, not building LLVM]) + ;; + esac +fi + +build_x86=no +build_ppc=no +build_arm=no +case "$target_cpu" in + i?86|amd64|x86_64) + build_x86=yes + ;; + powerpc*) + build_ppc=yes + ;; + arm*) + build_arm=yes + ;; +esac +if test "$enable_alltargets" = "yes"; then + build_x86=yes + build_ppc=yes + build_arm=yes +fi +AM_CONDITIONAL(BUILD_X86, [test "$build_x86" = "yes"]) +AM_CONDITIONAL(BUILD_PPC, [test "$build_ppc" = "yes"]) +AM_CONDITIONAL(BUILD_ARM, [test "$build_arm" = "yes"]) + +AC_OUTPUT([ + Makefile +]) diff --git a/libclamav/c++/llvm/CMakeLists.txt b/libclamav/c++/llvm/CMakeLists.txt new file mode 100644 index 000000000..39ccfbb10 --- /dev/null +++ b/libclamav/c++/llvm/CMakeLists.txt @@ -0,0 +1,361 @@ +# See docs/CMake.html for instructions about how to build LLVM with CMake. + +project(LLVM) +cmake_minimum_required(VERSION 2.6.1) + +set(PACKAGE_NAME llvm) +set(PACKAGE_VERSION 2.7svn) +set(PACKAGE_STRING "${PACKAGE_NAME} ${PACKAGE_VERSION}") +set(PACKAGE_BUGREPORT "llvmbugs@cs.uiuc.edu") + +if( CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR AND NOT MSVC_IDE ) + message(FATAL_ERROR "In-source builds are not allowed. +CMake would overwrite the makefiles distributed with LLVM. +Please create a directory and run cmake from there, passing the path +to this source directory as the last argument. +This process created the file `CMakeCache.txt' and the directory `CMakeFiles'. +Please delete them.") +endif() + +string(TOUPPER "${CMAKE_BUILD_TYPE}" uppercase_CMAKE_BUILD_TYPE) + +set(LLVM_MAIN_SRC_DIR ${CMAKE_CURRENT_SOURCE_DIR}) +set(LLVM_MAIN_INCLUDE_DIR ${LLVM_MAIN_SRC_DIR}/include) +set(LLVM_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}) +set(LLVM_TOOLS_BINARY_DIR ${LLVM_BINARY_DIR}/bin) +set(LLVM_EXAMPLES_BINARY_DIR ${LLVM_BINARY_DIR}/examples) +set(LLVM_LIBDIR_SUFFIX "" CACHE STRING "Define suffix of library directory name (32/64)" ) + +if( NOT CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR ) + file(GLOB_RECURSE + tablegenned_files_on_include_dir + "${LLVM_MAIN_SRC_DIR}/include/llvm/*.gen") + file(GLOB_RECURSE + tablegenned_files_on_lib_dir + "${LLVM_MAIN_SRC_DIR}/lib/Target/*.inc") + if( tablegenned_files_on_include_dir OR tablegenned_files_on_lib_dir) + message(FATAL_ERROR "Apparently there is a previous in-source build, +probably as the result of running `configure' and `make' on +${LLVM_MAIN_SRC_DIR}. +This may cause problems. The suspicious files are: +${tablegenned_files_on_lib_dir} +${tablegenned_files_on_include_dir} +Please clean the source directory.") + endif() +endif() + +set(LLVM_ALL_TARGETS + Alpha + ARM + Blackfin + CBackend + CellSPU + CppBackend + Mips + MSIL + MSP430 + PIC16 + PowerPC + Sparc + SystemZ + X86 + XCore + ) + +if( MSVC ) + set(LLVM_TARGETS_TO_BUILD X86 + CACHE STRING "Semicolon-separated list of targets to build, or \"all\".") +else( MSVC ) + set(LLVM_TARGETS_TO_BUILD ${LLVM_ALL_TARGETS} + CACHE STRING "Semicolon-separated list of targets to build, or \"all\".") +endif( MSVC ) + +set(C_INCLUDE_DIRS "" CACHE STRING + "Colon separated list of directories clang will search for headers.") + +set(LLVM_TARGET_ARCH "host" + CACHE STRING "Set target to use for LLVM JIT or use \"host\" for automatic detection.") + +option(LLVM_ENABLE_THREADS "Use threads if available." ON) + +if( uppercase_CMAKE_BUILD_TYPE STREQUAL "RELEASE" ) + option(LLVM_ENABLE_ASSERTIONS "Enable assertions" OFF) +else() + option(LLVM_ENABLE_ASSERTIONS "Enable assertions" ON) +endif() + +if( LLVM_ENABLE_ASSERTIONS ) + # MSVC doesn't like _DEBUG on release builds. See PR 4379. + if( NOT MSVC ) + add_definitions( -D_DEBUG ) + endif() + # On Release builds cmake automatically defines NDEBUG, so we + # explicitly undefine it: + if( uppercase_CMAKE_BUILD_TYPE STREQUAL "RELEASE" ) + add_definitions( -UNDEBUG ) + endif() +else() + if( NOT uppercase_CMAKE_BUILD_TYPE STREQUAL "RELEASE" ) + add_definitions( -DNDEBUG ) + endif() +endif() + +if( LLVM_TARGETS_TO_BUILD STREQUAL "all" ) + set( LLVM_TARGETS_TO_BUILD ${LLVM_ALL_TARGETS} ) +endif() + +set(LLVM_ENUM_TARGETS "") +foreach(c ${LLVM_TARGETS_TO_BUILD}) + list(FIND LLVM_ALL_TARGETS ${c} idx) + if( idx LESS 0 ) + message(FATAL_ERROR "The target `${c}' does not exist. + It should be one of\n${LLVM_ALL_TARGETS}") + else() + set(LLVM_ENUM_TARGETS "${LLVM_ENUM_TARGETS}LLVM_TARGET(${c})\n") + endif() +endforeach(c) + +# Produce llvm/Config/Targets.def +configure_file( + ${LLVM_MAIN_INCLUDE_DIR}/llvm/Config/Targets.def.in + ${LLVM_BINARY_DIR}/include/llvm/Config/Targets.def + ) + +set(llvm_builded_incs_dir ${LLVM_BINARY_DIR}/include/llvm) + +# Add path for custom modules +set(CMAKE_MODULE_PATH + ${CMAKE_MODULE_PATH} + "${LLVM_MAIN_SRC_DIR}/cmake" + "${LLVM_MAIN_SRC_DIR}/cmake/modules" + ) + +include(AddLLVMDefinitions) + +if(WIN32) + if(CYGWIN) + set(LLVM_ON_WIN32 0) + set(LLVM_ON_UNIX 1) + else(CYGWIN) + set(LLVM_ON_WIN32 1) + set(LLVM_ON_UNIX 0) + endif(CYGWIN) + set(LTDL_SHLIB_EXT ".dll") + set(EXEEXT ".exe") + # Maximum path length is 160 for non-unicode paths + set(MAXPATHLEN 160) +else(WIN32) + if(UNIX) + set(LLVM_ON_WIN32 0) + set(LLVM_ON_UNIX 1) + if(APPLE) + set(LTDL_SHLIB_EXT ".dylib") + else(APPLE) + set(LTDL_SHLIB_EXT ".so") + endif(APPLE) + set(EXEEXT "") + # FIXME: Maximum path length is currently set to 'safe' fixed value + set(MAXPATHLEN 2024) + else(UNIX) + MESSAGE(SEND_ERROR "Unable to determine platform") + endif(UNIX) +endif(WIN32) + +include(config-ix) + +option(LLVM_ENABLE_PIC "Build Position-Independent Code" ON) + +set(ENABLE_PIC 0) +if( LLVM_ENABLE_PIC ) + if( XCODE ) + # Xcode has -mdynamic-no-pic on by default, which overrides -fPIC. I don't + # know how to disable this, so just force ENABLE_PIC off for now. + message(STATUS "Warning: -fPIC not supported with Xcode.") + else( XCODE ) + if( SUPPORTS_FPIC_FLAG ) + message(STATUS "Building with -fPIC") + add_llvm_definitions(-fPIC) + set(ENABLE_PIC 1) + else( SUPPORTS_FPIC_FLAG ) + message(STATUS "Warning: -fPIC not supported.") + endif() + endif() +endif() + +set( CMAKE_RUNTIME_OUTPUT_DIRECTORY ${LLVM_TOOLS_BINARY_DIR} ) +set( CMAKE_LIBRARY_OUTPUT_DIRECTORY ${LLVM_BINARY_DIR}/lib ) +set( CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${LLVM_BINARY_DIR}/lib ) + +# set(CMAKE_VERBOSE_MAKEFILE true) + +add_llvm_definitions( -D__STDC_LIMIT_MACROS ) +add_llvm_definitions( -D__STDC_CONSTANT_MACROS ) + +if( CMAKE_SIZEOF_VOID_P EQUAL 8 AND NOT WIN32 ) + # TODO: support other platforms and toolchains. + option(LLVM_BUILD_32_BITS "Build 32 bits executables and libraries." OFF) + if( LLVM_BUILD_32_BITS ) + message(STATUS "Building 32 bits executables and libraries.") + add_llvm_definitions( -m32 ) + list(APPEND CMAKE_EXE_LINKER_FLAGS -m32) + list(APPEND CMAKE_SHARED_LINKER_FLAGS -m32) + endif( LLVM_BUILD_32_BITS ) +endif( CMAKE_SIZEOF_VOID_P EQUAL 8 AND NOT WIN32 ) + +if( MSVC ) + # List of valid CRTs for MSVC + set(MSVC_CRT + MD + MDd) + + set(LLVM_USE_CRT "" CACHE STRING "Specify VC++ CRT to use for debug/release configurations.") + add_llvm_definitions( -D_CRT_SECURE_NO_DEPRECATE -D_CRT_SECURE_NO_WARNINGS ) + add_llvm_definitions( -D_SCL_SECURE_NO_WARNINGS -DCRT_NONSTDC_NO_WARNINGS ) + add_llvm_definitions( -D_SCL_SECURE_NO_DEPRECATE ) + add_llvm_definitions( -wd4146 -wd4503 -wd4996 -wd4800 -wd4244 -wd4624 ) + add_llvm_definitions( -wd4355 -wd4715 -wd4180 -wd4345 -wd4224 ) + + # Suppress 'new behavior: elements of array 'array' will be default initialized' + add_llvm_definitions( -wd4351 ) + + if (NOT ${LLVM_USE_CRT} STREQUAL "") + list(FIND MSVC_CRT ${LLVM_USE_CRT} idx) + if (idx LESS 0) + message(FATAL_ERROR "Invalid value for LLVM_USE_CRT: ${LLVM_USE_CRT}. Valid options are one of: ${MSVC_CRT}") + endif (idx LESS 0) + add_llvm_definitions("/${LLVM_USE_CRT}") + message(STATUS "Using VC++ CRT: ${LLVM_USE_CRT}") + endif (NOT ${LLVM_USE_CRT} STREQUAL "") +endif( MSVC ) + +include_directories( ${LLVM_BINARY_DIR}/include ${LLVM_MAIN_INCLUDE_DIR}) + +if( ${CMAKE_SYSTEM_NAME} MATCHES SunOS ) + SET(CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} "-include llvm/System/Solaris.h") +endif( ${CMAKE_SYSTEM_NAME} MATCHES SunOS ) + +include(AddLLVM) +include(TableGen) + +add_subdirectory(lib/Support) +add_subdirectory(lib/System) + +# Everything else depends on Support and System: +set(LLVM_COMMON_DEPENDS ${LLVM_COMMON_DEPENDS} ${LLVM_LIBS} ) + +set(LLVM_TABLEGEN "tblgen" CACHE + STRING "Native TableGen executable. Saves building one when cross-compiling.") +# Effective tblgen executable to be used: +set(LLVM_TABLEGEN_EXE ${LLVM_TABLEGEN}) + +add_subdirectory(utils/TableGen) + +if( CMAKE_CROSSCOMPILING ) + # This adds a dependency on target `tblgen', so must go after utils/TableGen + include( CrossCompileLLVM ) +endif( CMAKE_CROSSCOMPILING ) + +add_subdirectory(include/llvm) + +add_subdirectory(lib/VMCore) +add_subdirectory(lib/CodeGen) +add_subdirectory(lib/CodeGen/SelectionDAG) +add_subdirectory(lib/CodeGen/AsmPrinter) +add_subdirectory(lib/Bitcode/Reader) +add_subdirectory(lib/Bitcode/Writer) +add_subdirectory(lib/Transforms/Utils) +add_subdirectory(lib/Transforms/Instrumentation) +add_subdirectory(lib/Transforms/Scalar) +add_subdirectory(lib/Transforms/IPO) +add_subdirectory(lib/Transforms/Hello) +add_subdirectory(lib/Linker) +add_subdirectory(lib/Analysis) +add_subdirectory(lib/Analysis/IPA) +add_subdirectory(lib/MC) +add_subdirectory(test) + +add_subdirectory(utils/FileCheck) +add_subdirectory(utils/count) +add_subdirectory(utils/not) + +set(LLVM_ENUM_ASM_PRINTERS "") +set(LLVM_ENUM_ASM_PARSERS "") +set(LLVM_ENUM_DISASSEMBLERS "") +foreach(t ${LLVM_TARGETS_TO_BUILD}) + message(STATUS "Targeting ${t}") + add_subdirectory(lib/Target/${t}) + add_subdirectory(lib/Target/${t}/TargetInfo) + if( EXISTS ${LLVM_MAIN_SRC_DIR}/lib/Target/${t}/AsmPrinter/CMakeLists.txt ) + add_subdirectory(lib/Target/${t}/AsmPrinter) + set(LLVM_ENUM_ASM_PRINTERS + "${LLVM_ENUM_ASM_PRINTERS}LLVM_ASM_PRINTER(${t})\n") + endif( EXISTS ${LLVM_MAIN_SRC_DIR}/lib/Target/${t}/AsmPrinter/CMakeLists.txt ) + if( EXISTS ${LLVM_MAIN_SRC_DIR}/lib/Target/${t}/AsmParser/CMakeLists.txt ) + add_subdirectory(lib/Target/${t}/AsmParser) + set(LLVM_ENUM_ASM_PARSERS + "${LLVM_ENUM_ASM_PARSERS}LLVM_ASM_PARSER(${t})\n") + endif( EXISTS ${LLVM_MAIN_SRC_DIR}/lib/Target/${t}/AsmParser/CMakeLists.txt ) + if( EXISTS ${LLVM_MAIN_SRC_DIR}/lib/Target/${t}/Disassembler/CMakeLists.txt ) + add_subdirectory(lib/Target/${t}/Disassembler) + set(LLVM_ENUM_DISASSEMBLERS + "${LLVM_ENUM_DISASSEMBLERS}LLVM_DISASSEMBLER(${t})\n") + endif( EXISTS ${LLVM_MAIN_SRC_DIR}/lib/Target/${t}/Disassembler/CMakeLists.txt ) + set(CURRENT_LLVM_TARGET) +endforeach(t) + +# Produce llvm/Config/AsmPrinters.def +configure_file( + ${LLVM_MAIN_INCLUDE_DIR}/llvm/Config/AsmPrinters.def.in + ${LLVM_BINARY_DIR}/include/llvm/Config/AsmPrinters.def + ) + +# Produce llvm/Config/AsmParsers.def +configure_file( + ${LLVM_MAIN_INCLUDE_DIR}/llvm/Config/AsmParsers.def.in + ${LLVM_BINARY_DIR}/include/llvm/Config/AsmParsers.def + ) + +# Produce llvm/Config/Disassemblers.def +configure_file( + ${LLVM_MAIN_INCLUDE_DIR}/llvm/Config/Disassemblers.def.in + ${LLVM_BINARY_DIR}/include/llvm/Config/Disassemblers.def + ) + +add_subdirectory(lib/ExecutionEngine) +add_subdirectory(lib/ExecutionEngine/Interpreter) +add_subdirectory(lib/ExecutionEngine/JIT) +add_subdirectory(lib/Target) +add_subdirectory(lib/AsmParser) +add_subdirectory(lib/Archive) + +add_subdirectory(projects) + +option(LLVM_BUILD_TOOLS "Build LLVM tool programs." ON) +add_subdirectory(tools) + +option(LLVM_BUILD_EXAMPLES "Build LLVM example programs." OFF) +add_subdirectory(examples) + +install(DIRECTORY include/ + DESTINATION include + FILES_MATCHING + PATTERN "*.def" + PATTERN "*.h" + PATTERN "*.td" + PATTERN "*.inc" + PATTERN ".svn" EXCLUDE + ) + +install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/include/ + DESTINATION include + FILES_MATCHING + PATTERN "*.def" + PATTERN "*.h" + PATTERN "*.gen" + PATTERN "*.inc" + # Exclude include/llvm/CMakeFiles/intrinsics_gen.dir, matched by "*.def" + PATTERN "CMakeFiles" EXCLUDE + PATTERN ".svn" EXCLUDE + ) + +# TODO: make and install documentation. diff --git a/libclamav/c++/llvm/CREDITS.TXT b/libclamav/c++/llvm/CREDITS.TXT new file mode 100644 index 000000000..f6467abfc --- /dev/null +++ b/libclamav/c++/llvm/CREDITS.TXT @@ -0,0 +1,337 @@ +This file is a partial list of people who have contributed to the LLVM +project. If you have contributed a patch or made some other contribution to +LLVM, please submit a patch to this file to add yourself, and it will be +done! + +The list is sorted by surname and formatted to allow easy grepping and +beautification by scripts. The fields are: name (N), email (E), web-address +(W), PGP key ID and fingerprint (P), description (D), and snail-mail address +(S). + +N: Vikram Adve +E: vadve@cs.uiuc.edu +W: http://www.cs.uiuc.edu/~vadve/ +D: The Sparc64 backend, provider of much wisdom, and motivator for LLVM + +N: Owen Anderson +E: resistor@mac.com +D: LCSSA pass and related LoopUnswitch work +D: GVNPRE pass, TargetData refactoring, random improvements + +N: Henrik Bach +D: MingW Win32 API portability layer + +N: Nate Begeman +E: natebegeman@mac.com +D: PowerPC backend developer +D: Target-independent code generator and analysis improvements + +N: Daniel Berlin +E: dberlin@dberlin.org +D: ET-Forest implementation. +D: Sparse bitmap + +N: Neil Booth +E: neil@daikokuya.co.uk +D: APFloat implementation. + +N: Misha Brukman +E: brukman+llvm@uiuc.edu +W: http://misha.brukman.net +D: Portions of X86 and Sparc JIT compilers, PowerPC backend +D: Incremental bytecode loader + +N: Cameron Buschardt +E: buschard@uiuc.edu +D: The `mem2reg' pass - promotes values stored in memory to registers + +N: Chandler Carruth +E: chandlerc@gmail.com +D: LinkTimeOptimizer for Linux, via binutils integration, and C API + +N: Casey Carter +E: ccarter@uiuc.edu +D: Fixes to the Reassociation pass, various improvement patches + +N: Evan Cheng +E: evan.cheng@apple.com +D: ARM and X86 backends +D: Instruction scheduler improvements +D: Register allocator improvements +D: Loop optimizer improvements +D: Target-independent code generator improvements + +N: Dan Villiom Podlaski Christiansen +E: danchr@gmail.com +E: danchr@cs.au.dk +W: http://villiom.dk +D: LLVM Makefile improvements +D: Clang diagnostic & driver tweaks +S: Aarhus, Denmark + +N: Jeff Cohen +E: jeffc@jolt-lang.org +W: http://jolt-lang.org +D: Native Win32 API portability layer + +N: John T. Criswell +E: criswell@uiuc.edu +D: Original Autoconf support, documentation improvements, bug fixes + +N: Stefanus Du Toit +E: stefanus.dutoit@rapidmind.com +D: Bug fixes and minor improvements + +N: Rafael Avila de Espindola +E: rafael.espindola@gmail.com +D: The ARM backend + +N: Alkis Evlogimenos +E: alkis@evlogimenos.com +D: Linear scan register allocator, many codegen improvements, Java frontend + +N: Ryan Flynn +E: pizza@parseerror.com +D: Miscellaneous bug fixes + +N: Brian Gaeke +E: gaeke@uiuc.edu +W: http://www.students.uiuc.edu/~gaeke/ +D: Portions of X86 static and JIT compilers; initial SparcV8 backend +D: Dynamic trace optimizer +D: FreeBSD/X86 compatibility fixes, the llvm-nm tool + +N: Nicolas Geoffray +E: nicolas.geoffray@lip6.fr +W: http://www-src.lip6.fr/homepages/Nicolas.Geoffray/ +D: PPC backend fixes for Linux + +N: Louis Gerbarg +D: Portions of the PowerPC backend + +N: Saem Ghani +E: saemghani@gmail.com +D: Callgraph class cleanups + +N: Mikhail Glushenkov +E: foldr@codedgers.com +D: Author of llvmc2 + +N: Dan Gohman +E: gohman@apple.com +D: Miscellaneous bug fixes + +N: David Goodwin +E: david@goodwinz.net +D: Thumb-2 code generator + +N: David Greene +E: greened@obbligato.org +D: Miscellaneous bug fixes +D: Register allocation refactoring + +N: Gabor Greif +E: ggreif@gmail.com +D: Improvements for space efficiency + +N: Lang Hames +E: lhames@gmail.com +D: PBQP-based register allocator + +N: Gordon Henriksen +E: gordonhenriksen@mac.com +D: Pluggable GC support +D: C interface +D: Ocaml bindings + +N: Raul Fernandes Herbster +E: raul@dsc.ufcg.edu.br +D: JIT support for ARM + +N: Paolo Invernizzi +E: arathorn@fastwebnet.it +D: Visual C++ compatibility fixes + +N: Patrick Jenkins +E: patjenk@wam.umd.edu +D: Nightly Tester + +N: Dale Johannesen +E: dalej@apple.com +D: ARM constant islands improvements +D: Tail merging improvements +D: Rewrite X87 back end +D: Use APFloat for floating point constants widely throughout compiler +D: Implement X87 long double + +N: Brad Jones +E: kungfoomaster@nondot.org +D: Support for packed types + +N: Rod Kay +E: rkay@auroraux.org +D: Author of LLVM Ada bindings + +N: Eric Kidd +W: http://randomhacks.net/ +D: llvm-config script + +N: Anton Korobeynikov +E: asl@math.spbu.ru +D: Mingw32 fixes, cross-compiling support, stdcall/fastcall calling conv. +D: x86/linux PIC codegen, aliases, regparm/visibility attributes +D: Switch lowering refactoring + +N: Sumant Kowshik +E: kowshik@uiuc.edu +D: Author of the original C backend + +N: Benjamin Kramer +E: benny.kra@gmail.com +D: Miscellaneous bug fixes + +N: Christopher Lamb +E: christopher.lamb@gmail.com +D: aligned load/store support, parts of noalias and restrict support +D: vreg subreg infrastructure, X86 codegen improvements based on subregs +D: address spaces + +N: Jim Laskey +E: jlaskey@apple.com +D: Improvements to the PPC backend, instruction scheduling +D: Debug and Dwarf implementation +D: Auto upgrade mangler +D: llvm-gcc4 svn wrangler + +N: Chris Lattner +E: sabre@nondot.org +W: http://nondot.org/~sabre/ +D: Primary architect of LLVM + +N: Tanya Lattner (Tanya Brethour) +E: tonic@nondot.org +W: http://nondot.org/~tonic/ +D: The initial llvm-ar tool, converted regression testsuite to dejagnu +D: Modulo scheduling in the SparcV9 backend +D: Release manager (1.7+) + +N: Andrew Lenharth +E: alenhar2@cs.uiuc.edu +W: http://www.lenharth.org/~andrewl/ +D: Alpha backend +D: Sampling based profiling + +N: Nick Lewycky +E: nicholas@mxc.ca +D: PredicateSimplifier pass + +N: Bruno Cardoso Lopes +E: bruno.cardoso@gmail.com +W: http://www.brunocardoso.org +D: The Mips backend + +N: Duraid Madina +E: duraid@octopus.com.au +W: http://kinoko.c.u-tokyo.ac.jp/~duraid/ +D: IA64 backend, BigBlock register allocator + +N: Michael McCracken +E: michael.mccracken@gmail.com +D: Line number support for llvmgcc + +N: Vladimir Merzliakov +E: wanderer@rsu.ru +D: Test suite fixes for FreeBSD + +N: Scott Michel +E: scottm@aero.org +D: Added STI Cell SPU backend. + +N: Edward O'Callaghan +E: eocallaghan@auroraux.org +W: http://www.auroraux.org +D: Add Clang support with various other improvements to utils/NewNightlyTest.pl +D: Fix and maintain Solaris & AuroraUX support for llvm, various build warnings +D: and error clean ups. + +N: Morten Ofstad +E: morten@hue.no +D: Visual C++ compatibility fixes + +N: Jakob Stoklund Olesen +E: stoklund@2pi.dk +D: Machine code verifier +D: Blackfin backend + +N: Richard Osborne +E: richard@xmos.com +D: XCore backend + +N: Devang Patel +E: dpatel@apple.com +D: LTO tool, PassManager rewrite, Loop Pass Manager, Loop Rotate +D: GCC PCH Integration (llvm-gcc), llvm-gcc improvements +D: Optimizer improvements, Loop Index Split + +N: Sandeep Patel +E: deeppatel1987@gmail.com +D: ARM calling conventions rewrite, hard float support + +N: Vladimir Prus +W: http://vladimir_prus.blogspot.com +E: ghost@cs.msu.su +D: Made inst_iterator behave like a proper iterator, LowerConstantExprs pass + +N: Roman Samoilov +E: roman@codedgers.com +D: MSIL backend + +N: Duncan Sands +E: baldrick@free.fr +D: Ada front-end, exception handling improvements + +N: Ruchira Sasanka +E: sasanka@uiuc.edu +D: Graph coloring register allocator for the Sparc64 backend + +N: Arnold Schwaighofer +E: arnold.schwaighofer@gmail.com +D: Tail call optimization for the x86 backend + +N: Shantonu Sen +E: ssen@apple.com +D: Miscellaneous bug fixes + +N: Anand Shukla +E: ashukla@cs.uiuc.edu +D: The `paths' pass + +N: Reid Spencer +E: rspencer@reidspencer.com +W: http://reidspencer.com/ +D: Lots of stuff, see: http://wiki.llvm.org/index.php/User:Reid + +N: Edwin Torok +E: edwintorok@gmail.com +D: Miscellaneous bug fixes + +N: Adam Treat +E: manyoso@yahoo.com +D: C++ bugs filed, and C++ front-end bug fixes. + +N: Lauro Ramos Venancio +E: lauro.venancio@indt.org.br +D: ARM backend improvements +D: Thread Local Storage implementation + +N: Xerxes Ranby +E: xerxes@zafena.se +D: Cmake dependency chain and various bug fixes + +N: Bill Wendling +E: isanbard@gmail.com +D: Bunches of stuff + +N: Bob Wilson +E: bob.wilson@acm.org +D: Advanced SIMD (NEON) support in the ARM backend diff --git a/libclamav/c++/llvm/LICENSE.TXT b/libclamav/c++/llvm/LICENSE.TXT new file mode 100644 index 000000000..fd4917266 --- /dev/null +++ b/libclamav/c++/llvm/LICENSE.TXT @@ -0,0 +1,69 @@ +============================================================================== +LLVM Release License +============================================================================== +University of Illinois/NCSA +Open Source License + +Copyright (c) 2003-2009 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} diff --git a/libclamav/c++/llvm/Makefile b/libclamav/c++/llvm/Makefile new file mode 100644 index 000000000..1ef89e4ed --- /dev/null +++ b/libclamav/c++/llvm/Makefile @@ -0,0 +1,233 @@ +#===- ./Makefile -------------------------------------------*- Makefile -*--===# +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +#===------------------------------------------------------------------------===# + +LEVEL := . + +# Top-Level LLVM Build Stages: +# 1. Build lib/System and lib/Support, which are used by utils (tblgen). +# 2. Build utils, which is used by VMCore. +# 3. Build VMCore, which builds the Intrinsics.inc file used by libs. +# 4. Build libs, which are needed by llvm-config. +# 5. Build llvm-config, which determines inter-lib dependencies for tools. +# 6. Build tools, runtime, docs. +# +# When cross-compiling, there are some things (tablegen) that need to +# be build for the build system first. + +# If "RC_ProjectName" exists in the environment, and its value is +# "llvmCore", then this is an "Apple-style" build; search for +# "Apple-style" in the comments for more info. Anything else is a +# normal build. +ifneq ($(findstring llvmCore, $(RC_ProjectName)),llvmCore) # Normal build (not "Apple-style"). + +ifeq ($(BUILD_DIRS_ONLY),1) + DIRS := lib/System lib/Support utils + OPTIONAL_DIRS := +else + DIRS := lib/System lib/Support utils lib/VMCore lib tools/llvm-config \ + tools runtime docs unittests + OPTIONAL_DIRS := projects bindings +endif + +ifeq ($(BUILD_EXAMPLES),1) + OPTIONAL_DIRS += examples +endif + +EXTRA_DIST := test unittests llvm.spec include win32 Xcode + +include $(LEVEL)/Makefile.config + +# llvm-gcc4 doesn't need runtime libs. llvm-gcc4 is the only supported one. +# FIXME: Remove runtime entirely once we have an understanding of where +# libprofile etc should go. +#ifeq ($(LLVMGCC_MAJVERS),4) +# DIRS := $(filter-out runtime, $(DIRS)) +#endif + +ifeq ($(MAKECMDGOALS),libs-only) + DIRS := $(filter-out tools runtime docs, $(DIRS)) + OPTIONAL_DIRS := +endif + +ifeq ($(MAKECMDGOALS),install-libs) + DIRS := $(filter-out tools runtime docs, $(DIRS)) + OPTIONAL_DIRS := $(filter bindings, $(OPTIONAL_DIRS)) +endif + +ifeq ($(MAKECMDGOALS),tools-only) + DIRS := $(filter-out runtime docs, $(DIRS)) + OPTIONAL_DIRS := +endif + +ifeq ($(MAKECMDGOALS),install-clang) + DIRS := tools/clang/tools/driver tools/clang/tools/clang-cc \ + tools/clang/lib/Headers tools/clang/docs + OPTIONAL_DIRS := + NO_INSTALL = 1 +endif + +ifeq ($(MAKECMDGOALS),clang-only) + DIRS := $(filter-out tools runtime docs unittests, $(DIRS)) tools/clang + OPTIONAL_DIRS := +endif + +ifeq ($(MAKECMDGOALS),unittests) + DIRS := $(filter-out tools runtime docs, $(DIRS)) utils unittests + OPTIONAL_DIRS := +endif + +# Use NO_INSTALL define of the Makefile of each directory for deciding +# if the directory is installed or not +ifeq ($(MAKECMDGOALS),install) + OPTIONAL_DIRS := $(filter bindings, $(OPTIONAL_DIRS)) +endif + +# If we're cross-compiling, build the build-hosted tools first +ifeq ($(LLVM_CROSS_COMPILING),1) +all:: cross-compile-build-tools + +clean:: + $(Verb) rm -rf BuildTools + +cross-compile-build-tools: + $(Verb) if [ ! -f BuildTools/Makefile ]; then \ + $(MKDIR) BuildTools; \ + cd BuildTools ; \ + unset CFLAGS ; \ + unset CXXFLAGS ; \ + $(PROJ_SRC_DIR)/configure --build=$(BUILD_TRIPLE) \ + --host=$(BUILD_TRIPLE) --target=$(BUILD_TRIPLE); \ + cd .. ; \ + fi; \ + ($(MAKE) -C BuildTools \ + BUILD_DIRS_ONLY=1 \ + UNIVERSAL= \ + ENABLE_OPTIMIZED=$(ENABLE_OPTIMIZED) \ + ENABLE_PROFILING=$(ENABLE_PROFILING) \ + ENABLE_COVERAGE=$(ENABLE_COVERAGE) \ + DISABLE_ASSERTIONS=$(DISABLE_ASSERTIONS) \ + ENABLE_EXPENSIVE_CHECKS=$(ENABLE_EXPENSIVE_CHECKS) \ + ) || exit 1; +endif + +# Include the main makefile machinery. +include $(LLVM_SRC_ROOT)/Makefile.rules + +# Specify options to pass to configure script when we're +# running the dist-check target +DIST_CHECK_CONFIG_OPTIONS = --with-llvmgccdir=$(LLVMGCCDIR) + +.PHONY: debug-opt-prof +debug-opt-prof: + $(Echo) Building Debug Version + $(Verb) $(MAKE) + $(Echo) + $(Echo) Building Optimized Version + $(Echo) + $(Verb) $(MAKE) ENABLE_OPTIMIZED=1 + $(Echo) + $(Echo) Building Profiling Version + $(Echo) + $(Verb) $(MAKE) ENABLE_PROFILING=1 + +dist-hook:: + $(Echo) Eliminating files constructed by configure + $(Verb) $(RM) -f \ + $(TopDistDir)/include/llvm/Config/config.h \ + $(TopDistDir)/include/llvm/System/DataTypes.h + +clang-only: all +tools-only: all +libs-only: all +install-clang: install +install-libs: install + +#------------------------------------------------------------------------ +# Make sure the generated headers are up-to-date. This must be kept in +# sync with the AC_CONFIG_HEADER invocations in autoconf/configure.ac +#------------------------------------------------------------------------ +FilesToConfig := \ + include/llvm/Config/config.h \ + include/llvm/Config/Targets.def \ + include/llvm/Config/AsmPrinters.def \ + include/llvm/Config/AsmParsers.def \ + include/llvm/Config/Disassemblers.def \ + include/llvm/System/DataTypes.h \ + tools/llvmc/plugins/Base/Base.td +FilesToConfigPATH := $(addprefix $(LLVM_OBJ_ROOT)/,$(FilesToConfig)) + +all-local:: $(FilesToConfigPATH) +$(FilesToConfigPATH) : $(LLVM_OBJ_ROOT)/% : $(LLVM_SRC_ROOT)/%.in + $(Echo) Regenerating $* + $(Verb) cd $(LLVM_OBJ_ROOT) && $(ConfigStatusScript) $* +.PRECIOUS: $(FilesToConfigPATH) + +# NOTE: This needs to remain as the last target definition in this file so +# that it gets executed last. +ifneq ($(BUILD_DIRS_ONLY),1) +all:: + $(Echo) '*****' Completed $(BuildMode)$(AssertMode) Build +ifeq ($(BuildMode),Debug) + $(Echo) '*****' Note: Debug build can be 10 times slower than an + $(Echo) '*****' optimized build. Use 'make ENABLE_OPTIMIZED=1' to + $(Echo) '*****' make an optimized build. Alternatively you can + $(Echo) '*****' configure with --enable-optimized. +endif +endif + +check-llvm2cpp: + $(Verb)$(MAKE) check TESTSUITE=Feature RUNLLVM2CPP=1 + +check-one: + $(Verb)$(MAKE) -C test check-one TESTONE=$(TESTONE) + +srpm: $(LLVM_OBJ_ROOT)/llvm.spec + rpmbuild -bs $(LLVM_OBJ_ROOT)/llvm.spec + +rpm: $(LLVM_OBJ_ROOT)/llvm.spec + rpmbuild -bb --target $(TARGET_TRIPLE) $(LLVM_OBJ_ROOT)/llvm.spec + +show-footprint: + $(Verb) du -sk $(LibDir) + $(Verb) du -sk $(ToolDir) + $(Verb) du -sk $(ExmplDir) + $(Verb) du -sk $(ObjDir) + +build-for-llvm-top: + $(Verb) if test ! -f ./config.status ; then \ + ./configure --prefix="$(LLVM_TOP)/install" \ + --with-llvm-gcc="$(LLVM_TOP)/llvm-gcc" ; \ + fi + $(Verb) $(MAKE) tools-only + +SVN = svn +SVN-UPDATE-OPTIONS = +AWK = awk +SUB-SVN-DIRS = $(AWK) '/\?\ \ \ \ \ \ / {print $$2}' \ + | LC_ALL=C xargs $(SVN) info 2>/dev/null \ + | $(AWK) '/Path:\ / {print $$2}' + +update: + $(SVN) $(SVN-UPDATE-OPTIONS) update $(LLVM_SRC_ROOT) + @ $(SVN) status $(LLVM_SRC_ROOT) | $(SUB-SVN-DIRS) | xargs $(SVN) $(SVN-UPDATE-OPTIONS) update + +happiness: update all check unittests + +.PHONY: srpm rpm update happiness + +# declare all targets at this level to be serial: + +.NOTPARALLEL: + +else # Building "Apple-style." +# In an Apple-style build, once configuration is done, lines marked +# "Apple-style" are removed with sed! Please don't remove these! +# Look for the string "Apple-style" in utils/buildit/build_llvm. +include $(shell find . -name GNUmakefile) # Building "Apple-style." +endif # Building "Apple-style." diff --git a/libclamav/c++/llvm/Makefile.common b/libclamav/c++/llvm/Makefile.common new file mode 100644 index 000000000..e1f52036f --- /dev/null +++ b/libclamav/c++/llvm/Makefile.common @@ -0,0 +1,70 @@ +#===-- Makefile.common - Common make rules for LLVM --------*- Makefile -*--===# +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +#===------------------------------------------------------------------------===# +# +# This file is included by all of the LLVM makefiles. This file defines common +# rules to do things like compile a .cpp file or generate dependency info. +# These are platform dependent, so this is the file used to specify these +# system dependent operations. +# +# The following functionality can be set by setting incoming variables. +# The variable $(LEVEL) *must* be set: +# +# 1. LEVEL - The level of the current subdirectory from the top of the +# source directory. This level should be expressed as a path, for +# example, ../.. for two levels deep. +# +# 2. DIRS - A list of subdirectories to be built. Fake targets are set up +# so that each of the targets "all", "install", and "clean" each build +# the subdirectories before the local target. DIRS are guaranteed to be +# built in order. +# +# 3. PARALLEL_DIRS - A list of subdirectories to be built, but that may be +# built in any order. All DIRS are built in order before PARALLEL_DIRS are +# built, which are then built in any order. +# +# 4. Source - If specified, this sets the source code filenames. If this +# is not set, it defaults to be all of the .cpp, .c, .y, and .l files +# in the current directory. Also, if you want to build files in addition +# to the local files, you can use the ExtraSource variable +# +# 5. SourceDir - If specified, this specifies a directory that the source files +# are in, if they are not in the current directory. This should include a +# trailing / character. +# +# 6. LLVM_SRC_ROOT - If specified, points to the top of the LLVM source tree. +# +# 8. PROJ_SRC_DIR - The directory which contains the current set of Makefiles +# and usually the source code too (unless SourceDir is set). +# +# 9. PROJ_SRC_ROOT - The root directory of the source code being compiled. +# +# 10. PROJ_OBJ_DIR - The directory where object code should be placed. +# +# 11. PROJ_OBJ_ROOT - The root directory for where object code should be +# placed. +# +# For building, +# LLVM, LLVM_SRC_ROOT = PROJ_SRC_ROOT +# +#===-----------------------------------------------------------------------==== + +# +# Configuration file to set paths specific to local installation of LLVM +# +ifndef LLVM_OBJ_ROOT +include $(LEVEL)/Makefile.config +else +include $(LLVM_OBJ_ROOT)/Makefile.config +endif + +# +# Include all of the build rules used for making LLVM +# +include $(LLVM_SRC_ROOT)/Makefile.rules + diff --git a/libclamav/c++/llvm/Makefile.config.in b/libclamav/c++/llvm/Makefile.config.in new file mode 100644 index 000000000..44296a466 --- /dev/null +++ b/libclamav/c++/llvm/Makefile.config.in @@ -0,0 +1,337 @@ +#===-- Makefile.config - Local configuration for LLVM ------*- Makefile -*--===# +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +#===------------------------------------------------------------------------===# +# +# This file is included by Makefile.common. It defines paths and other +# values specific to a particular installation of LLVM. +# +#===------------------------------------------------------------------------===# + +# Define LLVM specific info and directories based on the autoconf variables +LLVMPackageName := @PACKAGE_NAME@ +LLVMVersion := @PACKAGE_VERSION@ +LLVM_CONFIGTIME := @LLVM_CONFIGTIME@ + +########################################################################### +# Directory Configuration +# This section of the Makefile determines what is where. To be +# specific, there are several locations that need to be defined: +# +# o LLVM_SRC_ROOT : The root directory of the LLVM source code. +# o LLVM_OBJ_ROOT : The root directory containing the built LLVM code. +# +# o PROJ_SRC_DIR : The directory containing the code to build. +# o PROJ_SRC_ROOT : The root directory of the code to build. +# +# o PROJ_OBJ_DIR : The directory in which compiled code will be placed. +# o PROJ_OBJ_ROOT : The root directory in which compiled code is placed. +# +########################################################################### + +PWD := @BINPWD@ +# Set the project name to LLVM if its not defined +ifndef PROJECT_NAME +PROJECT_NAME := $(LLVMPackageName) +endif + +PROJ_OBJ_DIR := $(shell $(PWD)) +PROJ_OBJ_ROOT := $(shell cd $(PROJ_OBJ_DIR)/$(LEVEL); $(PWD)) + +ifeq ($(PROJECT_NAME),llvm) +LLVM_SRC_ROOT := $(shell cd @abs_top_srcdir@; $(PWD)) +LLVM_OBJ_ROOT := $(shell cd @abs_top_builddir@; $(PWD)) +PROJ_SRC_ROOT := $(shell cd $(LLVM_SRC_ROOT); $(PWD)) +PROJ_SRC_DIR := $(shell cd $(LLVM_SRC_ROOT)/$(patsubst $(PROJ_OBJ_ROOT)%,%,$(PROJ_OBJ_DIR)); $(PWD)) +prefix := @prefix@ +PROJ_prefix := $(prefix) +PROJ_VERSION := $(LLVMVersion) +else +ifndef PROJ_SRC_ROOT +$(error Projects must define PROJ_SRC_ROOT) +endif +ifndef PROJ_OBJ_ROOT +$(error Projects must define PROJ_OBJ_ROOT) +endif +ifndef PROJ_INSTALL_ROOT +$(error Projects must define PROJ_INSTALL_ROOT) +endif +ifndef LLVM_SRC_ROOT +$(error Projects must define LLVM_SRC_ROOT) +endif +ifndef LLVM_OBJ_ROOT +$(error Projects must define LLVM_OBJ_ROOT) +endif +PROJ_SRC_DIR := $(shell cd $(PROJ_SRC_ROOT)/$(patsubst $(PROJ_OBJ_ROOT)%,%,$(PROJ_OBJ_DIR)); $(PWD)) +prefix := $(PROJ_INSTALL_ROOT) +PROJ_prefix := $(prefix) +ifndef PROJ_VERSION +PROJ_VERSION := 1.0 +endif +endif + +LLVMMAKE := $(LLVM_SRC_ROOT)/make + +PROJ_bindir := $(DESTDIR)$(PROJ_prefix)/bin +PROJ_libdir := $(DESTDIR)$(PROJ_prefix)/lib +PROJ_datadir := $(DESTDIR)$(PROJ_prefix)/share +PROJ_docsdir := $(DESTDIR)$(PROJ_prefix)/docs/llvm +PROJ_etcdir := $(DESTDIR)$(PROJ_prefix)/etc/llvm +PROJ_includedir := $(DESTDIR)$(PROJ_prefix)/include +PROJ_infodir := $(DESTDIR)$(PROJ_prefix)/info +PROJ_mandir := $(DESTDIR)$(PROJ_prefix)/share/man + +# Determine if we're on a unix type operating system +LLVM_ON_UNIX:=@LLVM_ON_UNIX@ +LLVM_ON_WIN32:=@LLVM_ON_WIN32@ + +# Host operating system for which LLVM will be run. +OS=@OS@ +HOST_OS=@HOST_OS@ +# Target operating system for which LLVM will compile for. +TARGET_OS=@TARGET_OS@ + +# Target hardware architecture +ARCH=@ARCH@ + +# Indicates, whether we're cross-compiling LLVM or not +LLVM_CROSS_COMPILING=@LLVM_CROSS_COMPILING@ + +# Executable file extension for build platform (mainly for +# tablegen call if we're cross-compiling). +BUILD_EXEEXT=@BUILD_EXEEXT@ + +# Compilers for the build platflorm (mainly for tablegen +# call if we're cross-compiling). +BUILD_CC=@BUILD_CC@ +BUILD_CXX=@BUILD_CXX@ + +# Triple for configuring build tools when cross-compiling +BUILD_TRIPLE=@build@ + +# Target triple (cpu-vendor-os) for which we should generate code +TARGET_TRIPLE=@target@ + +# Extra options to compile LLVM with +EXTRA_OPTIONS=@EXTRA_OPTIONS@ + +# Endian-ness of the target +ENDIAN=@ENDIAN@ + +# Path to the C++ compiler to use. This is an optional setting, which defaults +# to whatever your gmake defaults to. +CXX = @CXX@ + +# Path to the CC binary, which use used by testcases for native builds. +CC := @CC@ + +# Linker flags. +LDFLAGS+=@LDFLAGS@ + +# Path to the library archiver program. +AR_PATH = @AR@ +AR = @AR@ + +# Path to the nm program +NM_PATH = @NM@ + +# The pathnames of the programs we require to build +CMP := @CMP@ +CP := @CP@ +DATE := @DATE@ +FIND := @FIND@ +GREP := @GREP@ +INSTALL := @INSTALL@ +MKDIR := $(LLVM_SRC_ROOT)/autoconf/mkinstalldirs +MV := @MV@ +RANLIB := @RANLIB@ +RM := @RM@ +SED := @SED@ +TAR := @TAR@ + +# Paths to miscellaneous programs we hope are present but might not be +PERL := @PERL@ +BZIP2 := @BZIP2@ +DOT := @DOT@ +DOXYGEN := @DOXYGEN@ +GROFF := @GROFF@ +GZIP := @GZIP@ +OCAMLC := @OCAMLC@ +OCAMLOPT := @OCAMLOPT@ +OCAMLDEP := @OCAMLDEP@ +OCAMLDOC := @OCAMLDOC@ +GAS := @GAS@ +POD2HTML := @POD2HTML@ +POD2MAN := @POD2MAN@ +RUNTEST := @RUNTEST@ +TCLSH := @TCLSH@ +ZIP := @ZIP@ + +HAVE_PERL := @HAVE_PERL@ +HAVE_PTHREAD := @HAVE_PTHREAD@ + +LIBS := @LIBS@ + +# Targets that we should build +TARGETS_TO_BUILD=@TARGETS_TO_BUILD@ + +# Path to location for LLVM C/C++ front-end. You can modify this if you +# want to override the value set by configure. +LLVMGCCDIR := @LLVMGCCDIR@ + +# Determine the target for which LLVM should generate code. +ifeq (@LLVMGCC_MAJVERS@,3) +LLVMGCCARCH := @target@/3.4-llvm +else +LLVMGCCARCH := @target@/@LLVMGCC_VERSION@ +endif + +# Determine the path where the library executables are +LLVMGCCLIBEXEC := @LLVMGCCLIBEXEC@ + +# Full pathnames of LLVM C/C++ front-end 'cc1' and 'cc1plus' binaries: +LLVMGCC := @LLVMGCC@ +LLVMGXX := @LLVMGXX@ +LLVMCC1 := @LLVMCC1@ +LLVMCC1PLUS := @LLVMCC1PLUS@ +LLVMGCC_VERSION := @LLVMGCC_VERSION@ +LLVMGCC_MAJVERS := @LLVMGCC_MAJVERS@ +LLVMGCC_LANGS := @LLVMGCC_LANGS@ + +# Path to directory where object files should be stored during a build. +# Set OBJ_ROOT to "." if you do not want to use a separate place for +# object files. +OBJ_ROOT := . + +# What to pass as rpath flag to g++ +RPATH := @RPATH@ + +# What to pass as -rdynamic flag to g++ +RDYNAMIC := @RDYNAMIC@ + +# These are options that can either be enabled here, or can be enabled on the +# make command line (ie, make ENABLE_PROFILING=1): + +# When ENABLE_OPTIMIZED is enabled, LLVM code is optimized and output is put +# into the "Release" directories. Otherwise, LLVM code is not optimized and +# output is put in the "Debug" directories. +#ENABLE_OPTIMIZED = 1 +@ENABLE_OPTIMIZED@ + +# When ENABLE_PROFILING is enabled, profile instrumentation is done +# and output is put into the "+Profile" directories, where +# is either Debug or Release depending on how other builkd +# flags are set.. Otherwise, output is put in the +# directories. +#ENABLE_PROFILING = 1 +@ENABLE_PROFILING@ + +# When DISABLE_ASSERTIONS is enabled, builds of all of the LLVM code will +# exclude assertion checks, otherwise they are included. +#DISABLE_ASSERTIONS = 1 +@DISABLE_ASSERTIONS@ + +# When ENABLE_EXPENSIVE_CHECKS is enabled, builds of all of the LLVM +# code will include expensive checks, otherwise they are excluded. +#ENABLE_EXPENSIVE_CHECKS = 0 +@ENABLE_EXPENSIVE_CHECKS@ + +# When DEBUG_RUNTIME is enabled, the runtime libraries will retain debug +# symbols. +#DEBUG_RUNTIME = 1 +@DEBUG_RUNTIME@ + +# When DEBUG_SYMBOLS is enabled, the compiler libraries will retain debug +# symbols. +#DEBUG_SYMBOLS = 1 +@DEBUG_SYMBOLS@ + +# The compiler flags to use for optimized builds. +OPTIMIZE_OPTION := @OPTIMIZE_OPTION@ + +# When ENABLE_PROFILING is enabled, the llvm source base is built with profile +# information to allow gprof to be used to get execution frequencies. +#ENABLE_PROFILING = 1 + +# When ENABLE_DOXYGEN is enabled, the doxygen documentation will be built +ENABLE_DOXYGEN = @ENABLE_DOXYGEN@ + +# Do we want to enable threads? +ENABLE_THREADS := @ENABLE_THREADS@ + +# Do we want to build with position independent code? +ENABLE_PIC := @ENABLE_PIC@ + +# Use -fvisibility-inlines-hidden? +ENABLE_VISIBILITY_INLINES_HIDDEN := @ENABLE_VISIBILITY_INLINES_HIDDEN@ + +# This option tells the Makefiles to produce verbose output. +# It essentially prints the commands that make is executing +#VERBOSE = 1 + +# Enable JIT for this platform +TARGET_HAS_JIT = @TARGET_HAS_JIT@ + +# Shared library extension for host platform. +SHLIBEXT = @SHLIBEXT@ + +# Executable file extension for host platform. +EXEEXT = @EXEEXT@ + +# Things we just assume are "there" +ECHO := echo + +# Get the options for causing archives to link all their content instead of +# just missing symbols, and the inverse of that. This is used for certain LLVM +# tools that permit loadable modules. It ensures that the LLVM symbols will be +# available to those loadable modules. +LINKALL := @LINKALL@ +NOLINKALL := @NOLINKALL@ + +# Get the value of HUGE_VAL_SANITY which will be either "yes" or "no" depending +# on the check. +HUGE_VAL_SANITY = @HUGE_VAL_SANITY@ + +# Bindings that we should build +BINDINGS_TO_BUILD := @BINDINGS_TO_BUILD@ +ALL_BINDINGS := @ALL_BINDINGS@ +OCAML_LIBDIR := @OCAML_LIBDIR@ + +# When compiling under Mingw/Cygwin, executables such as tblgen +# expect Windows paths, whereas the build system uses Unix paths. +# The function SYSPATH transforms Unix paths into Windows paths. +ifneq (,$(findstring -mno-cygwin, $(CXX))) + SYSPATH = $(shell echo $(1) | cygpath -m -f -) +else + SYSPATH = $(1) +endif + +# Location of the plugin header file for gold. +BINUTILS_INCDIR := @BINUTILS_INCDIR@ + +C_INCLUDE_DIRS := @C_INCLUDE_DISR@ +CXX_INCLUDE_ROOT := @CXX_INCLUDE_ROOT@ +CXX_INCLUDE_ARCH := @CXX_INCLUDE_ARCH@ +CXX_INCLUDE_32BIT_DIR = @CXX_INCLUDE_32BIT_DIR@ +CXX_INCLUDE_64BIT_DIR = @CXX_INCLUDE_64BIT_DIR@ + +# When ENABLE_LLVMC_DYNAMIC is enabled, LLVMC will link libCompilerDriver +# dynamically. This is needed to make dynamic plugins work on some targets +# (Windows). +ENABLE_LLVMC_DYNAMIC = 0 +#@ENABLE_LLVMC_DYNAMIC@ + +# When ENABLE_LLVMC_DYNAMIC_PLUGINS is enabled, LLVMC will have dynamic plugin +# support (via the -load option). +ENABLE_LLVMC_DYNAMIC_PLUGINS = 1 +#@ENABLE_LLVMC_DYNAMIC_PLUGINS@ + +# Optional flags supported by the compiler +# -Wno-missing-field-initializers +NO_MISSING_FIELD_INITIALIZERS = @NO_MISSING_FIELD_INITIALIZERS@ +# -Wno-variadic-macros +NO_VARIADIC_MACROS = @NO_VARIADIC_MACROS@ diff --git a/libclamav/c++/llvm/Makefile.rules b/libclamav/c++/llvm/Makefile.rules new file mode 100644 index 000000000..49ecb1e2d --- /dev/null +++ b/libclamav/c++/llvm/Makefile.rules @@ -0,0 +1,2047 @@ +#===-- Makefile.rules - Common make rules for LLVM ---------*- Makefile -*--===# +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +#===------------------------------------------------------------------------===# +# +# This file is included by all of the LLVM makefiles. For details on how to use +# it properly, please see the document MakefileGuide.html in the docs directory. +# +#===-----------------------------------------------------------------------====# + +################################################################################ +# TARGETS: Define standard targets that can be invoked +################################################################################ + +#-------------------------------------------------------------------- +# Define the various target sets +#-------------------------------------------------------------------- +RecursiveTargets := all clean clean-all install uninstall install-bytecode \ + unitcheck +LocalTargets := all-local clean-local clean-all-local check-local \ + install-local printvars uninstall-local \ + install-bytecode-local +TopLevelTargets := check dist dist-check dist-clean dist-gzip dist-bzip2 \ + dist-zip unittests +UserTargets := $(RecursiveTargets) $(LocalTargets) $(TopLevelTargets) +InternalTargets := preconditions distdir dist-hook + +################################################################################ +# INITIALIZATION: Basic things the makefile needs +################################################################################ + +#-------------------------------------------------------------------- +# Set the VPATH so that we can find source files. +#-------------------------------------------------------------------- +VPATH=$(PROJ_SRC_DIR) + +#-------------------------------------------------------------------- +# Reset the list of suffixes we know how to build. +#-------------------------------------------------------------------- +.SUFFIXES: +.SUFFIXES: .c .cpp .cc .h .hpp .o .a .bc .td .ps .dot .ll +.SUFFIXES: $(SHLIBEXT) $(SUFFIXES) + +#-------------------------------------------------------------------- +# Mark all of these targets as phony to avoid implicit rule search +#-------------------------------------------------------------------- +.PHONY: $(UserTargets) $(InternalTargets) + +#-------------------------------------------------------------------- +# Make sure all the user-target rules are double colon rules and +# they are defined first. +#-------------------------------------------------------------------- + +$(UserTargets):: + +################################################################################ +# PRECONDITIONS: that which must be built/checked first +################################################################################ + +SrcMakefiles := $(filter %Makefile %Makefile.tests,\ + $(wildcard $(PROJ_SRC_DIR)/Makefile*)) +ObjMakefiles := $(subst $(PROJ_SRC_DIR),$(PROJ_OBJ_DIR),$(SrcMakefiles)) +ConfigureScript := $(PROJ_SRC_ROOT)/configure +ConfigStatusScript := $(PROJ_OBJ_ROOT)/config.status +MakefileConfigIn := $(strip $(wildcard $(PROJ_SRC_ROOT)/Makefile.config.in)) +MakefileCommonIn := $(strip $(wildcard $(PROJ_SRC_ROOT)/Makefile.common.in)) +MakefileConfig := $(PROJ_OBJ_ROOT)/Makefile.config +MakefileCommon := $(PROJ_OBJ_ROOT)/Makefile.common +PreConditions := $(ConfigStatusScript) $(ObjMakefiles) +ifneq ($(MakefileCommonIn),) +PreConditions += $(MakefileCommon) +endif + +ifneq ($(MakefileConfigIn),) +PreConditions += $(MakefileConfig) +endif + +preconditions: $(PreConditions) + +#------------------------------------------------------------------------ +# Make sure the BUILT_SOURCES are built first +#------------------------------------------------------------------------ +$(filter-out clean clean-local,$(UserTargets)):: $(BUILT_SOURCES) + +clean-all-local:: +ifneq ($(strip $(BUILT_SOURCES)),) + -$(Verb) $(RM) -f $(BUILT_SOURCES) +endif + +ifneq ($(PROJ_OBJ_ROOT),$(PROJ_SRC_ROOT)) +spotless: + $(Verb) if test -x config.status ; then \ + $(EchoCmd) Wiping out $(PROJ_OBJ_ROOT) ; \ + $(MKDIR) .spotless.save ; \ + $(MV) config.status .spotless.save ; \ + $(MV) mklib .spotless.save ; \ + $(MV) projects .spotless.save ; \ + $(RM) -rf * ; \ + $(MV) .spotless.save/config.status . ; \ + $(MV) .spotless.save/mklib . ; \ + $(MV) .spotless.save/projects . ; \ + $(RM) -rf .spotless.save ; \ + $(EchoCmd) Rebuilding configuration of $(PROJ_OBJ_ROOT) ; \ + $(ConfigStatusScript) --recheck $(ConfigureScriptFLAGS) && \ + $(ConfigStatusScript) ; \ + else \ + $(EchoCmd) "make spotless" can only be run from $(PROJ_OBJ_ROOT); \ + fi +else +spotless: + $(EchoCmd) "spotless target not supported for objdir == srcdir" +endif + +$(BUILT_SOURCES) : $(ObjMakefiles) + +#------------------------------------------------------------------------ +# Make sure we're not using a stale configuration +#------------------------------------------------------------------------ +reconfigure: + $(Echo) Reconfiguring $(PROJ_OBJ_ROOT) + $(Verb) cd $(PROJ_OBJ_ROOT) && \ + if test -w $(PROJ_OBJ_ROOT)/config.cache ; then \ + $(RM) $(PROJ_OBJ_ROOT)/config.cache ; \ + fi ; \ + $(ConfigStatusScript) --recheck $(ConfigureScriptFLAGS) && \ + $(ConfigStatusScript) + +# FIXME: The {PIC16,MSP430}/AsmPrinter line here is a hack to force a reconfigure to pick +# up AsmPrinter changes. Remove it after a reasonable delay from 2009-08-13. + +.PRECIOUS: $(ConfigStatusScript) +$(ConfigStatusScript): $(ConfigureScript) $(LLVM_SRC_ROOT)/lib/Target/PIC16/AsmPrinter/Makefile $(LLVM_SRC_ROOT)/lib/Target/MSP430/AsmPrinter/Makefile + $(Echo) Reconfiguring with $< + $(Verb) cd $(PROJ_OBJ_ROOT) && \ + if test -w $(PROJ_OBJ_ROOT)/config.cache ; then \ + $(RM) $(PROJ_OBJ_ROOT)/config.cache ; \ + fi ; \ + $(ConfigStatusScript) --recheck $(ConfigureScriptFLAGS) && \ + $(ConfigStatusScript) + +#------------------------------------------------------------------------ +# Make sure the configuration makefile is up to date +#------------------------------------------------------------------------ +ifneq ($(MakefileConfigIn),) +$(MakefileConfig): $(MakefileConfigIn) $(ConfigStatusScript) + $(Echo) Regenerating $@ + $(Verb) cd $(PROJ_OBJ_ROOT) ; $(ConfigStatusScript) Makefile.config +endif + +ifneq ($(MakefileCommonIn),) +$(MakefileCommon): $(MakefileCommonIn) $(ConfigStatusScript) + $(Echo) Regenerating $@ + $(Verb) cd $(PROJ_OBJ_ROOT) ; $(ConfigStatusScript) Makefile.common +endif + +#------------------------------------------------------------------------ +# If the Makefile in the source tree has been updated, copy it over into the +# build tree. But, only do this if the source and object makefiles differ +#------------------------------------------------------------------------ +ifneq ($(PROJ_OBJ_DIR),$(PROJ_SRC_DIR)) + +Makefile: $(PROJ_SRC_DIR)/Makefile $(ExtraMakefiles) + $(Echo) "Updating Makefile" + $(Verb) $(MKDIR) $(@D) + $(Verb) $(CP) -f $< $@ + +# Copy the Makefile.* files unless we're in the root directory which avoids +# the copying of Makefile.config.in or other things that should be explicitly +# taken care of. +$(PROJ_OBJ_DIR)/Makefile% : $(PROJ_SRC_DIR)/Makefile% + @case '$?' in \ + *Makefile.rules) ;; \ + *.in) ;; \ + *) $(EchoCmd) "Updating $(@F)" ; \ + $(MKDIR) $(@D) ; \ + $(CP) -f $< $@ ;; \ + esac + +endif + +#------------------------------------------------------------------------ +# Set up the basic dependencies +#------------------------------------------------------------------------ +$(UserTargets):: $(PreConditions) + +all:: all-local +clean:: clean-local +clean-all:: clean-local clean-all-local +install:: install-local +uninstall:: uninstall-local +install-local:: all-local +install-bytecode:: install-bytecode-local + +############################################################################### +# LLVMC: Provide rules for compiling llvmc plugins +############################################################################### + +ifdef LLVMC_PLUGIN + +LIBRARYNAME := $(patsubst %,plugin_llvmc_%,$(LLVMC_PLUGIN)) +CPP.Flags += -DLLVMC_PLUGIN_NAME=$(LLVMC_PLUGIN) +REQUIRES_EH := 1 + +ifeq ($(ENABLE_LLVMC_DYNAMIC),1) + LD.Flags += -lCompilerDriver +endif + +# Build a dynamic library if the user runs `make` directly from the plugin +# directory. +ifndef LLVMC_BUILTIN_PLUGIN + LOADABLE_MODULE = 1 +endif + +# TableGen stuff... +ifneq ($(BUILT_SOURCES),) + LLVMC_BUILD_AUTOGENERATED_INC=1 +endif + +endif # LLVMC_PLUGIN + +ifdef LLVMC_BASED_DRIVER + +TOOLNAME = $(LLVMC_BASED_DRIVER) + +REQUIRES_EH := 1 + +ifeq ($(ENABLE_LLVMC_DYNAMIC),1) + LD.Flags += -lCompilerDriver +else + LLVMLIBS = CompilerDriver.a + LINK_COMPONENTS = support system +endif + +# Preprocessor magic that generates references to static variables in built-in +# plugins. +ifneq ($(LLVMC_BUILTIN_PLUGINS),) + +USEDLIBS += $(patsubst %,plugin_llvmc_%.a,$(LLVMC_BUILTIN_PLUGINS)) + +LLVMC_BUILTIN_PLUGIN_1 = $(word 1, $(LLVMC_BUILTIN_PLUGINS)) +LLVMC_BUILTIN_PLUGIN_2 = $(word 2, $(LLVMC_BUILTIN_PLUGINS)) +LLVMC_BUILTIN_PLUGIN_3 = $(word 3, $(LLVMC_BUILTIN_PLUGINS)) +LLVMC_BUILTIN_PLUGIN_4 = $(word 4, $(LLVMC_BUILTIN_PLUGINS)) +LLVMC_BUILTIN_PLUGIN_5 = $(word 5, $(LLVMC_BUILTIN_PLUGINS)) +LLVMC_BUILTIN_PLUGIN_6 = $(word 6, $(LLVMC_BUILTIN_PLUGINS)) +LLVMC_BUILTIN_PLUGIN_7 = $(word 7, $(LLVMC_BUILTIN_PLUGINS)) +LLVMC_BUILTIN_PLUGIN_8 = $(word 8, $(LLVMC_BUILTIN_PLUGINS)) +LLVMC_BUILTIN_PLUGIN_9 = $(word 9, $(LLVMC_BUILTIN_PLUGINS)) +LLVMC_BUILTIN_PLUGIN_10 = $(word 10, $(LLVMC_BUILTIN_PLUGINS)) + + +ifneq ($(LLVMC_BUILTIN_PLUGIN_1),) +CPP.Flags += -DLLVMC_BUILTIN_PLUGIN_1=$(LLVMC_BUILTIN_PLUGIN_1) +endif + +ifneq ($(LLVMC_BUILTIN_PLUGIN_2),) +CPP.Flags += -DLLVMC_BUILTIN_PLUGIN_2=$(LLVMC_BUILTIN_PLUGIN_2) +endif + +ifneq ($(LLVMC_BUILTIN_PLUGIN_3),) +CPP.Flags += -DLLVMC_BUILTIN_PLUGIN_3=$(LLVMC_BUILTIN_PLUGIN_3) +endif + +ifneq ($(LLVMC_BUILTIN_PLUGIN_4),) +CPP.Flags += -DLLVMC_BUILTIN_PLUGIN_4=$(LLVMC_BUILTIN_PLUGIN_4) +endif + +ifneq ($(LLVMC_BUILTIN_PLUGIN_5),) +CPP.Flags += -DLLVMC_BUILTIN_PLUGIN_5=$(LLVMC_BUILTIN_PLUGIN_5) +endif + +ifneq ($(LLVMC_BUILTIN_PLUGIN_6),) +CPP.Flags += -DLLVMC_BUILTIN_PLUGIN_5=$(LLVMC_BUILTIN_PLUGIN_6) +endif + +ifneq ($(LLVMC_BUILTIN_PLUGIN_7),) +CPP.Flags += -DLLVMC_BUILTIN_PLUGIN_5=$(LLVMC_BUILTIN_PLUGIN_7) +endif + +ifneq ($(LLVMC_BUILTIN_PLUGIN_8),) +CPP.Flags += -DLLVMC_BUILTIN_PLUGIN_5=$(LLVMC_BUILTIN_PLUGIN_8) +endif + +ifneq ($(LLVMC_BUILTIN_PLUGIN_9),) +CPP.Flags += -DLLVMC_BUILTIN_PLUGIN_5=$(LLVMC_BUILTIN_PLUGIN_9) +endif + +ifneq ($(LLVMC_BUILTIN_PLUGIN_10),) +CPP.Flags += -DLLVMC_BUILTIN_PLUGIN_5=$(LLVMC_BUILTIN_PLUGIN_10) +endif + + +endif + +endif # LLVMC_BASED_DRIVER + +############################################################################### +# VARIABLES: Set up various variables based on configuration data +############################################################################### + +# Variable for if this make is for a "cleaning" target +ifneq ($(strip $(filter clean clean-local dist-clean,$(MAKECMDGOALS))),) + IS_CLEANING_TARGET=1 +endif + +#-------------------------------------------------------------------- +# Variables derived from configuration we are building +#-------------------------------------------------------------------- + +CPP.Defines := +ifeq ($(ENABLE_OPTIMIZED),1) + BuildMode := Release + # Don't use -fomit-frame-pointer on Darwin or FreeBSD. + ifneq ($(HOST_OS),FreeBSD) + ifneq ($(HOST_OS),Darwin) + OmitFramePointer := -fomit-frame-pointer + endif + endif + + # Darwin requires -fstrict-aliasing to be explicitly enabled. + # Avoid -fstrict-aliasing on Darwin for now, there are unresolved issues + # with -fstrict-aliasing and ipa-type-escape radr://6756684 + #ifeq ($(HOST_OS),Darwin) + # EXTRA_OPTIONS += -fstrict-aliasing -Wstrict-aliasing + #endif + CXX.Flags += $(OPTIMIZE_OPTION) $(OmitFramePointer) + C.Flags += $(OPTIMIZE_OPTION) $(OmitFramePointer) + LD.Flags += $(OPTIMIZE_OPTION) + ifdef DEBUG_SYMBOLS + BuildMode := $(BuildMode)+Debug + CXX.Flags += -g + C.Flags += -g + LD.Flags += -g + KEEP_SYMBOLS := 1 + endif +else + ifdef NO_DEBUG_SYMBOLS + BuildMode := Unoptimized + CXX.Flags += + C.Flags += + LD.Flags += + KEEP_SYMBOLS := 1 + else + BuildMode := Debug + CXX.Flags += -g + C.Flags += -g + LD.Flags += -g + KEEP_SYMBOLS := 1 + endif +endif + +ifeq ($(ENABLE_PROFILING),1) + BuildMode := $(BuildMode)+Profile + CXX.Flags := $(filter-out -fomit-frame-pointer,$(CXX.Flags)) -pg -g + C.Flags := $(filter-out -fomit-frame-pointer,$(C.Flags)) -pg -g + LD.Flags := $(filter-out -fomit-frame-pointer,$(LD.Flags)) -pg -g + KEEP_SYMBOLS := 1 +endif + +#ifeq ($(ENABLE_VISIBILITY_INLINES_HIDDEN),1) +# CXX.Flags += -fvisibility-inlines-hidden +#endif + +# IF REQUIRES_EH=1 is specified then don't disable exceptions +ifndef REQUIRES_EH + CXX.Flags += -fno-exceptions +endif + +ifdef REQUIRES_FRAME_POINTER + CXX.Flags := $(filter-out -fomit-frame-pointer,$(CXX.Flags)) + C.Flags := $(filter-out -fomit-frame-pointer,$(C.Flags)) + LD.Flags := $(filter-out -fomit-frame-pointer,$(LD.Flags)) +endif + +# If REQUIRES_RTTI=1 is specified then don't disable run-time type id. +ifeq ($(REQUIRES_RTTI), 1) + CXX.Flags := $(filter-out -fno-rtti,$(CXX.Flags)) + CXXFLAGS := $(filter-out -fno-rtti,$(CXXFLAGS)) +endif + +ifdef ENABLE_COVERAGE + BuildMode := $(BuildMode)+Coverage + CXX.Flags += -ftest-coverage -fprofile-arcs + C.Flags += -ftest-coverage -fprofile-arcs +endif + +# If DISABLE_ASSERTIONS=1 is specified (make command line or configured), +# then disable assertions by defining the appropriate preprocessor symbols. +ifdef DISABLE_ASSERTIONS + # Indicate that assertions are turned off using a minus sign + BuildMode := $(BuildMode)-Asserts + CPP.Defines += -DNDEBUG +else + CPP.Defines += -D_DEBUG +endif + +# If ENABLE_EXPENSIVE_CHECKS=1 is specified (make command line or +# configured), then enable expensive checks by defining the +# appropriate preprocessor symbols. +ifdef ENABLE_EXPENSIVE_CHECKS + BuildMode := $(BuildMode)+Checks + CPP.Defines += -D_GLIBCXX_DEBUG -DXDEBUG +endif + +# LOADABLE_MODULE implies several other things so we force them to be +# defined/on. +ifdef LOADABLE_MODULE + SHARED_LIBRARY := 1 + LINK_LIBS_IN_SHARED := 1 +endif + +ifdef SHARED_LIBRARY + ENABLE_PIC := 1 + PIC_FLAG = "(PIC)" +endif + +ifeq ($(ENABLE_PIC),1) + ifeq ($(HOST_OS), $(filter $(HOST_OS), Cygwin MingW)) + # Nothing. Win32 defaults to PIC and warns when given -fPIC + else + ifeq ($(HOST_OS),Darwin) + # Common symbols not allowed in dylib files + CXX.Flags += -fno-common + C.Flags += -fno-common + else + # Linux and others; pass -fPIC + CXX.Flags += -fPIC + C.Flags += -fPIC + endif + endif +else + ifeq ($(HOST_OS),Darwin) + CXX.Flags += -mdynamic-no-pic + C.Flags += -mdynamic-no-pic + endif +endif + +CXX.Flags += -Woverloaded-virtual +CPP.BaseFlags += $(CPP.Defines) +AR.Flags := cru + +# Make Floating point IEEE compliant on Alpha. +ifeq ($(ARCH),Alpha) + CXX.Flags += -mieee + CPP.BaseFlags += -mieee +ifeq ($(ENABLE_PIC),0) + CXX.Flags += -fPIC + CPP.BaseFlags += -fPIC +endif +endif + +ifeq ($(ARCH),Alpha) + LD.Flags += -Wl,--no-relax +endif + +ifeq ($(HOST_OS),MingW) + ifeq ($(LLVM_CROSS_COMPILING),1) + # Work around http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=525016 + ifdef TOOLNAME + LD.Flags += -Wl,--allow-multiple-definition + endif + endif +endif + +ifdef ENABLE_EXPENSIVE_CHECKS + # GNU libstdc++ uses RTTI if you define _GLIBCXX_DEBUG, which we did above. + # See http://gcc.gnu.org/bugzilla/show_bug.cgi?id=40160 + CXX.Flags := $(filter-out -fno-rtti,$(CXX.Flags)) + CXXFLAGS := $(filter-out -fno-rtti,$(CXXFLAGS)) +endif + +#-------------------------------------------------------------------- +# Directory locations +#-------------------------------------------------------------------- +TargetMode := +ifeq ($(LLVM_CROSS_COMPILING),1) + BuildLLVMToolDir := $(LLVM_OBJ_ROOT)/BuildTools/$(BuildMode)/bin +endif + +ObjRootDir := $(PROJ_OBJ_DIR)/$(BuildMode) +ObjDir := $(ObjRootDir) +LibDir := $(PROJ_OBJ_ROOT)/$(BuildMode)/lib +ToolDir := $(PROJ_OBJ_ROOT)/$(BuildMode)/bin +ExmplDir := $(PROJ_OBJ_ROOT)/$(BuildMode)/examples +LLVMLibDir := $(LLVM_OBJ_ROOT)/$(BuildMode)/lib +LLVMToolDir := $(LLVM_OBJ_ROOT)/$(BuildMode)/bin +LLVMExmplDir:= $(LLVM_OBJ_ROOT)/$(BuildMode)/examples +CFERuntimeLibDir := $(LLVMGCCDIR)/lib + +#-------------------------------------------------------------------- +# Full Paths To Compiled Tools and Utilities +#-------------------------------------------------------------------- +EchoCmd = $(ECHO) llvm[$(MAKELEVEL)]: +Echo = @$(EchoCmd) +ifndef LLVMAS +LLVMAS := $(LLVMToolDir)/llvm-as$(EXEEXT) +endif +ifndef TBLGEN + ifeq ($(LLVM_CROSS_COMPILING),1) + TBLGEN := $(BuildLLVMToolDir)/tblgen$(BUILD_EXEEXT) + else + TBLGEN := $(LLVMToolDir)/tblgen$(EXEEXT) + endif +endif +LLVM_CONFIG := $(LLVMToolDir)/llvm-config +ifndef LLVMLD +LLVMLD := $(LLVMToolDir)/llvm-ld$(EXEEXT) +endif +ifndef LLVMDIS +LLVMDIS := $(LLVMToolDir)/llvm-dis$(EXEEXT) +endif +ifndef LLI +LLI := $(LLVMToolDir)/lli$(EXEEXT) +endif +ifndef LLC +LLC := $(LLVMToolDir)/llc$(EXEEXT) +endif +ifndef LOPT +LOPT := $(LLVMToolDir)/opt$(EXEEXT) +endif +ifndef LBUGPOINT +LBUGPOINT := $(LLVMToolDir)/bugpoint$(EXEEXT) +endif +ifndef LUPGRADE +LUPGRADE := $(LLVMToolDir)/llvm-upgrade$(EXEEXT) +endif +ifeq ($(LLVMGCC_MAJVERS),3) +LLVMGCCWITHPATH := PATH="$(LLVMToolDir):$(PATH)" $(LLVMGCC) +LLVMGXXWITHPATH := PATH="$(LLVMToolDir):$(PATH)" $(LLVMGXX) +else +LLVMGCCWITHPATH := $(LLVMGCC) +LLVMGXXWITHPATH := $(LLVMGXX) +endif + +#-------------------------------------------------------------------- +# Adjust to user's request +#-------------------------------------------------------------------- + +ifeq ($(HOST_OS),Darwin) + DARWIN_VERSION := `sw_vers -productVersion` + # Strip a number like 10.4.7 to 10.4 + DARWIN_VERSION := $(shell echo $(DARWIN_VERSION)| sed -E 's/(10.[0-9]).*/\1/') + # Get "4" out of 10.4 for later pieces in the makefile. + DARWIN_MAJVERS := $(shell echo $(DARWIN_VERSION)| sed -E 's/10.([0-9]).*/\1/') + + SharedLinkOptions=-Wl,-flat_namespace -Wl,-undefined -Wl,suppress \ + -dynamiclib + ifneq ($(ARCH),ARM) + SharedLinkOptions += -mmacosx-version-min=$(DARWIN_VERSION) + endif +else + ifeq ($(HOST_OS),Cygwin) + SharedLinkOptions=-shared -nostdlib -Wl,--export-all-symbols \ + -Wl,--enable-auto-import -Wl,--enable-auto-image-base + else + SharedLinkOptions=-shared + endif +endif + +ifeq ($(TARGET_OS),Darwin) + ifneq ($(ARCH),ARM) + TargetCommonOpts += -mmacosx-version-min=$(DARWIN_VERSION) + else + TargetCommonOpts += -marm + endif +endif + +# Adjust LD.Flags depending on the kind of library that is to be built. Note +# that if LOADABLE_MODULE is specified then the resulting shared library can +# be opened with dlopen. +ifdef LOADABLE_MODULE + LD.Flags += -module +endif + +ifdef SHARED_LIBRARY +ifneq ($(DARWIN_MAJVERS),4) + LD.Flags += $(RPATH) -Wl,$(LibDir) +endif +endif + +ifdef TOOL_VERBOSE + C.Flags += -v + CXX.Flags += -v + LD.Flags += -v + VERBOSE := 1 +endif + +# Adjust settings for verbose mode +ifndef VERBOSE + Verb := @ + AR.Flags += >/dev/null 2>/dev/null + ConfigureScriptFLAGS += >$(PROJ_OBJ_DIR)/configure.out 2>&1 +else + ConfigureScriptFLAGS := +endif + +# By default, strip symbol information from executable +ifndef KEEP_SYMBOLS + Strip := $(PLATFORMSTRIPOPTS) + StripWarnMsg := "(without symbols)" + Install.StripFlag += -s +endif + +# Adjust linker flags for building an executable +ifneq ($(HOST_OS),Darwin) +ifneq ($(DARWIN_MAJVERS),4) +ifdef TOOLNAME +ifdef EXAMPLE_TOOL + LD.Flags += $(RPATH) -Wl,$(ExmplDir) $(RDYNAMIC) +else + LD.Flags += $(RPATH) -Wl,$(ToolDir) $(RDYNAMIC) +endif +endif +endif +endif + +#---------------------------------------------------------- +# Options To Invoke Tools +#---------------------------------------------------------- + +ifndef NO_PEDANTIC +CompileCommonOpts += -pedantic -Wno-long-long +endif +CompileCommonOpts += -Wall -W -Wno-unused-parameter -Wwrite-strings \ + $(EXTRA_OPTIONS) + +ifeq ($(HOST_OS),HP-UX) + CompileCommonOpts := -D_REENTRANT -D_HPUX_SOURCE +endif + +# If we are building a universal binary on Mac OS/X, pass extra options. This +# is useful to people that want to link the LLVM libraries into their universal +# apps. +# +# The following can be optionally specified: +# UNIVERSAL_SDK_PATH variable can be specified as a path to the SDK to use. +# For Mac OS/X 10.4 Intel machines, the traditional one is: +# UNIVERSAL_SDK_PATH=/Developer/SDKs/MacOSX10.4u.sdk/ +# UNIVERSAL_ARCH can be optionally specified to be a list of architectures +# to build for, e.g. UNIVERSAL_ARCH="i386 ppc ppc64". This defaults to +# i386/ppc only. +ifdef UNIVERSAL + ifndef UNIVERSAL_ARCH + UNIVERSAL_ARCH := i386 ppc + endif + UNIVERSAL_ARCH_OPTIONS := $(UNIVERSAL_ARCH:%=-arch %) + CompileCommonOpts += $(UNIVERSAL_ARCH_OPTIONS) + ifdef UNIVERSAL_SDK_PATH + CompileCommonOpts += -isysroot $(UNIVERSAL_SDK_PATH) + endif + + # Building universal cannot compute dependencies automatically. + DISABLE_AUTO_DEPENDENCIES=1 +else + ifeq ($(TARGET_OS),Darwin) + ifeq ($(ARCH),x86_64) + TargetCommonOpts = -m64 + else + ifeq ($(ARCH),x86) + TargetCommonOpts = -m32 + endif + endif + endif +endif + +ifeq ($(HOST_OS),SunOS) +CPP.BaseFlags += -include llvm/System/Solaris.h +endif + +ifeq ($(HOST_OS),AuroraUX) +CPP.BaseFlags += -include llvm/System/Solaris.h +endif # !HOST_OS - AuroraUX. + +LD.Flags += -L$(LibDir) -L$(LLVMLibDir) +CPP.BaseFlags += -D_GNU_SOURCE -D__STDC_LIMIT_MACROS -D__STDC_CONSTANT_MACROS +# All -I flags should go here, so that they don't confuse llvm-config. +CPP.Flags += $(sort -I$(PROJ_OBJ_DIR) -I$(PROJ_SRC_DIR) \ + $(patsubst %,-I%/include,\ + $(PROJ_OBJ_ROOT) $(PROJ_SRC_ROOT) \ + $(LLVM_OBJ_ROOT) $(LLVM_SRC_ROOT))) \ + $(CPP.BaseFlags) + +ifeq ($(BUILD_COMPONENT), 1) + Compile.C = $(BUILD_CC) $(CPP.Flags) $(C.Flags) $(CFLAGS) $(CPPFLAGS) \ + $(TargetCommonOpts) $(CompileCommonOpts) -c + Compile.CXX = $(BUILD_CXX) $(CPP.Flags) $(CXX.Flags) $(CXXFLAGS) \ + $(CPPFLAGS) \ + $(TargetCommonOpts) $(CompileCommonOpts) -c + Preprocess.CXX= $(BUILD_CXX) $(CPP.Flags) $(CPPFLAGS) $(TargetCommonOpts) \ + $(CompileCommonOpts) $(CXX.Flags) -E + Link = $(BUILD_CXX) $(CPP.Flags) $(CXX.Flags) $(CXXFLAGS) \ + $(LDFLAGS) \ + $(TargetCommonOpts) $(CompileCommonOpts) $(LD.Flags) $(Strip) +else + Compile.C = $(CC) $(CPP.Flags) $(C.Flags) $(CFLAGS) $(CPPFLAGS) \ + $(TargetCommonOpts) $(CompileCommonOpts) -c + Compile.CXX = $(CXX) $(CPP.Flags) $(CXX.Flags) $(CXXFLAGS) $(CPPFLAGS) \ + $(TargetCommonOpts) $(CompileCommonOpts) -c + Preprocess.CXX= $(CXX) $(CPP.Flags) $(TargetCommonOpts) $(CPPFLAGS) \ + $(CompileCommonOpts) $(CXX.Flags) -E + Link = $(CXX) $(CPP.Flags) $(CXX.Flags) $(CXXFLAGS) $(LDFLAGS) \ + $(TargetCommonOpts) $(CompileCommonOpts) $(LD.Flags) $(Strip) +endif + +BCCompile.C = $(LLVMGCCWITHPATH) $(CPP.Flags) $(C.Flags) $(CFLAGS) \ + $(CPPFLAGS) \ + $(TargetCommonOpts) $(CompileCommonOpts) +Preprocess.C = $(CC) $(CPP.Flags) $(C.Flags) $(CPPFLAGS) \ + $(TargetCommonOpts) $(CompileCommonOpts) -E + +BCCompile.CXX = $(LLVMGXXWITHPATH) $(CPP.Flags) $(CXX.Flags) $(CXXFLAGS) \ + $(CPPFLAGS) \ + $(TargetCommonOpts) $(CompileCommonOpts) + +ProgInstall = $(INSTALL) $(Install.StripFlag) -m 0755 +ScriptInstall = $(INSTALL) -m 0755 +DataInstall = $(INSTALL) -m 0644 + +# When compiling under Mingw/Cygwin, the tblgen tool expects Windows +# paths. In this case, the SYSPATH function (defined in +# Makefile.config) transforms Unix paths into Windows paths. +TableGen = $(TBLGEN) -I $(call SYSPATH, $(PROJ_SRC_DIR)) \ + -I $(call SYSPATH, $(LLVM_SRC_ROOT)/include) \ + -I $(call SYSPATH, $(PROJ_SRC_ROOT)/include) \ + -I $(call SYSPATH, $(PROJ_SRC_ROOT)/lib/Target) + +Archive = $(AR) $(AR.Flags) +LArchive = $(LLVMToolDir)/llvm-ar rcsf +ifdef RANLIB +Ranlib = $(RANLIB) +else +Ranlib = ranlib +endif + +AliasTool = ln -s + +#---------------------------------------------------------- +# Get the list of source files and compute object file +# names from them. +#---------------------------------------------------------- + +ifndef SOURCES + Sources := $(notdir $(wildcard $(PROJ_SRC_DIR)/*.cpp \ + $(PROJ_SRC_DIR)/*.cc $(PROJ_SRC_DIR)/*.c)) +else + Sources := $(SOURCES) +endif + +ifdef BUILT_SOURCES +Sources += $(filter %.cpp %.c %.cc,$(BUILT_SOURCES)) +endif + +BaseNameSources := $(sort $(basename $(Sources))) + +ObjectsO := $(BaseNameSources:%=$(ObjDir)/%.o) +ObjectsBC := $(BaseNameSources:%=$(ObjDir)/%.bc) + +############################################################################### +# DIRECTORIES: Handle recursive descent of directory structure +############################################################################### + +#--------------------------------------------------------- +# Provide rules to make install dirs. This must be early +# in the file so they get built before dependencies +#--------------------------------------------------------- + +$(PROJ_bindir) $(PROJ_libdir) $(PROJ_includedir) $(PROJ_etcdir):: + $(Verb) $(MKDIR) $@ + +# To create other directories, as needed, and timestamp their creation +%/.dir: + $(Verb) $(MKDIR) $* > /dev/null + $(Verb) $(DATE) > $@ + +.PRECIOUS: $(ObjDir)/.dir $(LibDir)/.dir $(ToolDir)/.dir $(ExmplDir)/.dir +.PRECIOUS: $(LLVMLibDir)/.dir $(LLVMToolDir)/.dir $(LLVMExmplDir)/.dir + +#--------------------------------------------------------- +# Handle the DIRS options for sequential construction +#--------------------------------------------------------- + +SubDirs := +ifdef DIRS +SubDirs += $(DIRS) + +ifneq ($(PROJ_SRC_ROOT),$(PROJ_OBJ_ROOT)) +$(RecursiveTargets):: + $(Verb) for dir in $(DIRS); do \ + if [ ! -f $$dir/Makefile ]; then \ + $(MKDIR) $$dir; \ + $(CP) $(PROJ_SRC_DIR)/$$dir/Makefile $$dir/Makefile; \ + fi; \ + ($(MAKE) -C $$dir $@ ) || exit 1; \ + done +else +$(RecursiveTargets):: + $(Verb) for dir in $(DIRS); do \ + ($(MAKE) -C $$dir $@ ) || exit 1; \ + done +endif + +endif + +#--------------------------------------------------------- +# Handle the EXPERIMENTAL_DIRS options ensuring success +# after each directory is built. +#--------------------------------------------------------- +ifdef EXPERIMENTAL_DIRS +$(RecursiveTargets):: + $(Verb) for dir in $(EXPERIMENTAL_DIRS); do \ + if [ ! -f $$dir/Makefile ]; then \ + $(MKDIR) $$dir; \ + $(CP) $(PROJ_SRC_DIR)/$$dir/Makefile $$dir/Makefile; \ + fi; \ + ($(MAKE) -C $$dir $@ ) || exit 0; \ + done +endif + +#----------------------------------------------------------- +# Handle the OPTIONAL_PARALLEL_DIRS options for optional parallel construction +#----------------------------------------------------------- +ifdef OPTIONAL_PARALLEL_DIRS + PARALLEL_DIRS += $(foreach T,$(OPTIONAL_PARALLEL_DIRS),$(shell test -d $(PROJ_SRC_DIR)/$(T) && echo "$(T)")) +endif + +#----------------------------------------------------------- +# Handle the PARALLEL_DIRS options for parallel construction +#----------------------------------------------------------- +ifdef PARALLEL_DIRS + +SubDirs += $(PARALLEL_DIRS) + +# Unfortunately, this list must be maintained if new recursive targets are added +all :: $(addsuffix /.makeall ,$(PARALLEL_DIRS)) +clean :: $(addsuffix /.makeclean ,$(PARALLEL_DIRS)) +clean-all:: $(addsuffix /.makeclean-all,$(PARALLEL_DIRS)) +install :: $(addsuffix /.makeinstall ,$(PARALLEL_DIRS)) +uninstall:: $(addsuffix /.makeuninstall,$(PARALLEL_DIRS)) +install-bytecode :: $(addsuffix /.makeinstall-bytecode,$(PARALLEL_DIRS)) +unitcheck:: $(addsuffix /.makeunitcheck,$(PARALLEL_DIRS)) + +ParallelTargets := $(foreach T,$(RecursiveTargets),%/.make$(T)) + +$(ParallelTargets) : + $(Verb) if [ ! -f $(@D)/Makefile ]; then \ + $(MKDIR) $(@D); \ + $(CP) $(PROJ_SRC_DIR)/$(@D)/Makefile $(@D)/Makefile; \ + fi; \ + $(MAKE) -C $(@D) $(subst $(@D)/.make,,$@) +endif + +#--------------------------------------------------------- +# Handle the OPTIONAL_DIRS options for directores that may +# or may not exist. +#--------------------------------------------------------- +ifdef OPTIONAL_DIRS + +SubDirs += $(OPTIONAL_DIRS) + +ifneq ($(PROJ_SRC_ROOT),$(PROJ_OBJ_ROOT)) +$(RecursiveTargets):: + $(Verb) for dir in $(OPTIONAL_DIRS); do \ + if [ -d $(PROJ_SRC_DIR)/$$dir ]; then\ + if [ ! -f $$dir/Makefile ]; then \ + $(MKDIR) $$dir; \ + $(CP) $(PROJ_SRC_DIR)/$$dir/Makefile $$dir/Makefile; \ + fi; \ + ($(MAKE) -C$$dir $@ ) || exit 1; \ + fi \ + done +else +$(RecursiveTargets):: + $(Verb) for dir in $(OPTIONAL_DIRS); do \ + ($(MAKE) -C$$dir $@ ) || exit 1; \ + done +endif +endif + +#--------------------------------------------------------- +# Handle the CONFIG_FILES options +#--------------------------------------------------------- +ifdef CONFIG_FILES + +ifdef NO_INSTALL +install-local:: + $(Echo) Install circumvented with NO_INSTALL +uninstall-local:: + $(Echo) UnInstall circumvented with NO_INSTALL +else +install-local:: $(PROJ_etcdir) $(CONFIG_FILES) + $(Echo) Installing Configuration Files To $(PROJ_etcdir) + $(Verb)for file in $(CONFIG_FILES); do \ + if test -f $(PROJ_OBJ_DIR)/$${file} ; then \ + $(DataInstall) $(PROJ_OBJ_DIR)/$${file} $(PROJ_etcdir) ; \ + elif test -f $(PROJ_SRC_DIR)/$${file} ; then \ + $(DataInstall) $(PROJ_SRC_DIR)/$${file} $(PROJ_etcdir) ; \ + else \ + $(ECHO) Error: cannot find config file $${file}. ; \ + fi \ + done + +uninstall-local:: + $(Echo) Uninstalling Configuration Files From $(PROJ_etcdir) + $(Verb)for file in $(CONFIG_FILES); do \ + $(RM) -f $(PROJ_etcdir)/$${file} ; \ + done +endif + +endif + +############################################################################### +# Set up variables for building libararies +############################################################################### + +#--------------------------------------------------------- +# Define various command line options pertaining to the +# libraries needed when linking. There are "Proj" libs +# (defined by the user's project) and "LLVM" libs (defined +# by the LLVM project). +#--------------------------------------------------------- + +ifdef USEDLIBS +ProjLibsOptions := $(patsubst %.a.o, -l%, $(addsuffix .o, $(USEDLIBS))) +ProjLibsOptions := $(patsubst %.o, $(LibDir)/%.o, $(ProjLibsOptions)) +ProjUsedLibs := $(patsubst %.a.o, lib%.a, $(addsuffix .o, $(USEDLIBS))) +ProjLibsPaths := $(addprefix $(LibDir)/,$(ProjUsedLibs)) +endif + +ifdef LLVMLIBS +LLVMLibsOptions := $(patsubst %.a.o, -l%, $(addsuffix .o, $(LLVMLIBS))) +LLVMLibsOptions := $(patsubst %.o, $(LLVMLibDir)/%.o, $(LLVMLibsOptions)) +LLVMUsedLibs := $(patsubst %.a.o, lib%.a, $(addsuffix .o, $(LLVMLIBS))) +LLVMLibsPaths := $(addprefix $(LLVMLibDir)/,$(LLVMUsedLibs)) +endif + +ifndef IS_CLEANING_TARGET +ifdef LINK_COMPONENTS + +# If LLVM_CONFIG doesn't exist, build it. This can happen if you do a make +# clean in tools, then do a make in tools (instead of at the top level). +$(LLVM_CONFIG): + @echo "*** llvm-config doesn't exist - rebuilding it." + @$(MAKE) -C $(PROJ_OBJ_ROOT)/tools/llvm-config + +$(ToolDir)/$(strip $(TOOLNAME))$(EXEEXT): $(LLVM_CONFIG) + +LLVMLibsOptions += $(shell $(LLVM_CONFIG) --libs $(LINK_COMPONENTS)) +LLVMLibsPaths += $(LLVM_CONFIG) \ + $(shell $(LLVM_CONFIG) --libfiles $(LINK_COMPONENTS)) +endif +endif + +############################################################################### +# Library Build Rules: Four ways to build a library +############################################################################### + +#--------------------------------------------------------- +# Bytecode Module Targets: +# If the user set MODULE_NAME then they want to build a +# bytecode module from the sources. We compile all the +# sources and link it together into a single bytecode +# module. +#--------------------------------------------------------- + +ifdef MODULE_NAME +ifeq ($(strip $(LLVMGCC)),) +$(warning Modules require llvm-gcc but no llvm-gcc is available ****) +else + +Module := $(LibDir)/$(MODULE_NAME).bc +LinkModule := $(LLVMLD) -L$(CFERuntimeLibDir) -r + + +ifdef EXPORTED_SYMBOL_FILE +LinkModule += -internalize-public-api-file=$(EXPORTED_SYMBOL_FILE) +endif + +$(Module): $(BUILT_SOURCES) $(ObjectsBC) $(LibDir)/.dir $(LLVMLD) + $(Echo) Building $(BuildMode) Bytecode Module $(notdir $@) + $(Verb) $(LinkModule) -o $@ $(ObjectsBC) + +all-local:: $(Module) + +clean-local:: +ifneq ($(strip $(Module)),) + -$(Verb) $(RM) -f $(Module) +endif + +ifdef BYTECODE_DESTINATION +ModuleDestDir := $(BYTECODE_DESTINATION) +else +ModuleDestDir := $(PROJ_libdir) +endif + +ifdef NO_INSTALL +install-local:: + $(Echo) Install circumvented with NO_INSTALL +uninstall-local:: + $(Echo) Uninstall circumvented with NO_INSTALL +else +DestModule := $(ModuleDestDir)/$(MODULE_NAME).bc + +install-module:: $(DestModule) +install-local:: $(DestModule) + +$(DestModule): $(ModuleDestDir) $(Module) + $(Echo) Installing $(BuildMode) Bytecode Module $(DestModule) + $(Verb) $(DataInstall) $(Module) $(DestModule) + +uninstall-local:: + $(Echo) Uninstalling $(BuildMode) Bytecode Module $(DestModule) + -$(Verb) $(RM) -f $(DestModule) +endif + +endif +endif + +# if we're building a library ... +ifdef LIBRARYNAME + +# Make sure there isn't any extraneous whitespace on the LIBRARYNAME option +LIBRARYNAME := $(strip $(LIBRARYNAME)) +ifdef LOADABLE_MODULE +LibName.A := $(LibDir)/$(LIBRARYNAME).a +LibName.SO := $(LibDir)/$(LIBRARYNAME)$(SHLIBEXT) +else +LibName.A := $(LibDir)/lib$(LIBRARYNAME).a +LibName.SO := $(LibDir)/lib$(LIBRARYNAME)$(SHLIBEXT) +endif +LibName.O := $(LibDir)/$(LIBRARYNAME).o +LibName.BCA:= $(LibDir)/lib$(LIBRARYNAME).bca + +#--------------------------------------------------------- +# Shared Library Targets: +# If the user asked for a shared library to be built +# with the SHARED_LIBRARY variable, then we provide +# targets for building them. +#--------------------------------------------------------- +ifdef SHARED_LIBRARY + +all-local:: $(LibName.SO) + +ifdef LINK_LIBS_IN_SHARED +ifdef LOADABLE_MODULE +SharedLibKindMessage := "Loadable Module" +else +SharedLibKindMessage := "Shared Library" +endif +$(LibName.SO): $(ObjectsO) $(ProjLibsPaths) $(LLVMLibsPaths) $(LibDir)/.dir + $(Echo) Linking $(BuildMode) $(SharedLibKindMessage) \ + $(LIBRARYNAME)$(SHLIBEXT) + $(Verb) $(Link) $(SharedLinkOptions) -o $@ $(ObjectsO) \ + $(ProjLibsOptions) $(LLVMLibsOptions) $(LIBS) +else +$(LibName.SO): $(ObjectsO) $(LibDir)/.dir + $(Echo) Linking $(BuildMode) Shared Library $(LIBRARYNAME)$(SHLIBEXT) + $(Verb) $(Link) $(SharedLinkOptions) -o $@ $(ObjectsO) +endif + +clean-local:: +ifneq ($(strip $(LibName.SO)),) + -$(Verb) $(RM) -f $(LibName.SO) +endif + +ifdef NO_INSTALL +install-local:: + $(Echo) Install circumvented with NO_INSTALL +uninstall-local:: + $(Echo) Uninstall circumvented with NO_INSTALL +else +DestSharedLib = $(PROJ_libdir)/lib$(LIBRARYNAME)$(SHLIBEXT) + +install-local:: $(DestSharedLib) + +$(DestSharedLib): $(LibName.SO) $(PROJ_libdir) + $(Echo) Installing $(BuildMode) Shared Library $(DestSharedLib) + $(Verb) $(INSTALL) $(LibName.SO) $(DestSharedLib) + +uninstall-local:: + $(Echo) Uninstalling $(BuildMode) Shared Library $(DestSharedLib) + -$(Verb) $(RM) -f $(PROJ_libdir)/lib$(LIBRARYNAME).* +endif +endif + +#--------------------------------------------------------- +# Bytecode Library Targets: +# If the user asked for a bytecode library to be built +# with the BYTECODE_LIBRARY variable, then we provide +# targets for building them. +#--------------------------------------------------------- +ifdef BYTECODE_LIBRARY +ifeq ($(strip $(LLVMGCC)),) +$(warning Bytecode libraries require llvm-gcc which could not be found ****) +else + +all-local:: $(LibName.BCA) + +ifdef EXPORTED_SYMBOL_FILE +BCLinkLib = $(LLVMLD) -L$(CFERuntimeLibDir) \ + -internalize-public-api-file=$(EXPORTED_SYMBOL_FILE) + +$(LibName.BCA): $(ObjectsBC) $(LibDir)/.dir $(LLVMLD) \ + $(LLVMToolDir)/llvm-ar + $(Echo) Building $(BuildMode) Bytecode Archive $(notdir $@) \ + "(internalize)" + $(Verb) $(BCLinkLib) -o $(ObjDir)/$(LIBRARYNAME).internalize $(ObjectsBC) + $(Verb) $(RM) -f $@ + $(Verb) $(LArchive) $@ $(ObjDir)/$(LIBRARYNAME).internalize.bc +else +$(LibName.BCA): $(ObjectsBC) $(LibDir)/.dir \ + $(LLVMToolDir)/llvm-ar + $(Echo) Building $(BuildMode) Bytecode Archive $(notdir $@) + $(Verb) $(RM) -f $@ + $(Verb) $(LArchive) $@ $(ObjectsBC) + +endif + +clean-local:: +ifneq ($(strip $(LibName.BCA)),) + -$(Verb) $(RM) -f $(LibName.BCA) +endif + +ifdef BYTECODE_DESTINATION +BytecodeDestDir := $(BYTECODE_DESTINATION) +else +BytecodeDestDir := $(PROJ_libdir) +endif + +DestBytecodeLib = $(BytecodeDestDir)/lib$(LIBRARYNAME).bca + +install-bytecode-local:: $(DestBytecodeLib) + +ifdef NO_INSTALL +install-local:: + $(Echo) Install circumvented with NO_INSTALL +uninstall-local:: + $(Echo) Uninstall circumvented with NO_INSTALL +else +install-local:: $(DestBytecodeLib) + +$(DestBytecodeLib): $(LibName.BCA) $(BytecodeDestDir) + $(Echo) Installing $(BuildMode) Bytecode Archive $(DestBytecodeLib) + $(Verb) $(DataInstall) $(LibName.BCA) $(DestBytecodeLib) + +uninstall-local:: + $(Echo) Uninstalling $(BuildMode) Bytecode Archive $(DestBytecodeLib) + -$(Verb) $(RM) -f $(DestBytecodeLib) +endif +endif +endif + +#--------------------------------------------------------- +# Library Targets: +# If neither BUILD_ARCHIVE or LOADABLE_MODULE are specified, default to +# building an archive. +#--------------------------------------------------------- +ifndef BUILD_ARCHIVE +ifndef LOADABLE_MODULE +BUILD_ARCHIVE = 1 +endif +endif + +#--------------------------------------------------------- +# Archive Library Targets: +# If the user wanted a regular archive library built, +# then we provide targets for building them. +#--------------------------------------------------------- +ifdef BUILD_ARCHIVE + +all-local:: $(LibName.A) + +$(LibName.A): $(ObjectsO) $(LibDir)/.dir + $(Echo) Building $(BuildMode) Archive Library $(notdir $@) + -$(Verb) $(RM) -f $@ + $(Verb) $(Archive) $@ $(ObjectsO) + $(Verb) $(Ranlib) $@ + +clean-local:: +ifneq ($(strip $(LibName.A)),) + -$(Verb) $(RM) -f $(LibName.A) +endif + +ifdef NO_INSTALL +install-local:: + $(Echo) Install circumvented with NO_INSTALL +uninstall-local:: + $(Echo) Uninstall circumvented with NO_INSTALL +else +DestArchiveLib := $(PROJ_libdir)/lib$(LIBRARYNAME).a + +install-local:: $(DestArchiveLib) + +$(DestArchiveLib): $(LibName.A) $(PROJ_libdir) + $(Echo) Installing $(BuildMode) Archive Library $(DestArchiveLib) + $(Verb) $(MKDIR) $(PROJ_libdir) + $(Verb) $(INSTALL) $(LibName.A) $(DestArchiveLib) + +uninstall-local:: + $(Echo) Uninstalling $(BuildMode) Archive Library $(DestArchiveLib) + -$(Verb) $(RM) -f $(DestArchiveLib) +endif +endif + +# endif LIBRARYNAME +endif + +############################################################################### +# Tool Build Rules: Build executable tool based on TOOLNAME option +############################################################################### + +ifdef TOOLNAME + +#--------------------------------------------------------- +# Set up variables for building a tool. +#--------------------------------------------------------- +TOOLEXENAME := $(strip $(TOOLNAME))$(EXEEXT) +ifdef EXAMPLE_TOOL +ToolBuildPath := $(ExmplDir)/$(TOOLEXENAME) +else +ToolBuildPath := $(ToolDir)/$(TOOLEXENAME) +endif + +# TOOLALIAS is a name to symlink (or copy) the tool to. +ifdef TOOLALIAS +ifdef EXAMPLE_TOOL +ToolAliasBuildPath := $(ExmplDir)/$(strip $(TOOLALIAS))$(EXEEXT) +else +ToolAliasBuildPath := $(ToolDir)/$(strip $(TOOLALIAS))$(EXEEXT) +endif +endif + +#--------------------------------------------------------- +# Prune Exports +#--------------------------------------------------------- + +# If the tool opts in with TOOL_NO_EXPORTS, optimize startup time of the app by +# not exporting all of the weak symbols from the binary. This reduces dyld +# startup time by 4x on darwin in some cases. +ifdef TOOL_NO_EXPORTS +ifeq ($(HOST_OS),Darwin) + +# Tiger tools don't support this. +ifneq ($(DARWIN_MAJVERS),4) +LD.Flags += -Wl,-exported_symbol -Wl,_main +endif +endif + +ifeq ($(HOST_OS), $(filter $(HOST_OS), Linux NetBSD FreeBSD)) + LD.Flags += -Wl,--version-script=$(LLVM_SRC_ROOT)/autoconf/ExportMap.map +endif +endif + + +#--------------------------------------------------------- +# Provide targets for building the tools +#--------------------------------------------------------- +all-local:: $(ToolBuildPath) $(ToolAliasBuildPath) + +clean-local:: +ifneq ($(strip $(ToolBuildPath)),) + -$(Verb) $(RM) -f $(ToolBuildPath) +endif +ifneq ($(strip $(ToolAliasBuildPath)),) + -$(Verb) $(RM) -f $(ToolAliasBuildPath) +endif + +ifdef EXAMPLE_TOOL +$(ToolBuildPath): $(ExmplDir)/.dir +else +$(ToolBuildPath): $(ToolDir)/.dir +endif + +$(ToolBuildPath): $(ObjectsO) $(ProjLibsPaths) $(LLVMLibsPaths) + $(Echo) Linking $(BuildMode) executable $(TOOLNAME) $(StripWarnMsg) + $(Verb) $(Link) -o $@ $(TOOLLINKOPTS) $(ObjectsO) $(ProjLibsOptions) \ + $(LLVMLibsOptions) $(ExtraLibs) $(TOOLLINKOPTSB) $(LIBS) + $(Echo) ======= Finished Linking $(BuildMode) Executable $(TOOLNAME) \ + $(StripWarnMsg) + +ifneq ($(strip $(ToolAliasBuildPath)),) +$(ToolAliasBuildPath): $(ToolBuildPath) + $(Echo) Creating $(BuildMode) Alias $(TOOLALIAS) $(StripWarnMsg) + $(Verb) $(RM) -f $(ToolAliasBuildPath) + $(Verb) $(AliasTool) $(TOOLEXENAME) $(ToolAliasBuildPath) + $(Echo) ======= Finished Creating $(BuildMode) Alias $(TOOLNAME) \ + $(StripWarnMsg) +endif + +ifdef NO_INSTALL +install-local:: + $(Echo) Install circumvented with NO_INSTALL +uninstall-local:: + $(Echo) Uninstall circumvented with NO_INSTALL +else +DestTool = $(PROJ_bindir)/$(TOOLEXENAME) + +install-local:: $(DestTool) + +$(DestTool): $(ToolBuildPath) $(PROJ_bindir) + $(Echo) Installing $(BuildMode) $(DestTool) + $(Verb) $(ProgInstall) $(ToolBuildPath) $(DestTool) + +uninstall-local:: + $(Echo) Uninstalling $(BuildMode) $(DestTool) + -$(Verb) $(RM) -f $(DestTool) + +# TOOLALIAS install. +ifdef TOOLALIAS +DestToolAlias = $(PROJ_bindir)/$(TOOLALIAS)$(EXEEXT) + +install-local:: $(DestToolAlias) + +$(DestToolAlias): $(DestTool) $(PROJ_bindir) + $(Echo) Installing $(BuildMode) $(DestToolAlias) + $(Verb) $(RM) -f $(DestToolAlias) + $(Verb) $(AliasTool) $(TOOLEXENAME) $(DestToolAlias) + +uninstall-local:: + $(Echo) Uninstalling $(BuildMode) $(DestToolAlias) + -$(Verb) $(RM) -f $(DestToolAlias) +endif + +endif +endif + +############################################################################### +# Object Build Rules: Build object files based on sources +############################################################################### + +# FIXME: This should be checking for "if not GCC or ICC", not for "if HP-UX" +ifeq ($(HOST_OS),HP-UX) + DISABLE_AUTO_DEPENDENCIES=1 +endif + +# Provide rule sets for when dependency generation is enabled +ifndef DISABLE_AUTO_DEPENDENCIES + +#--------------------------------------------------------- +# Create .o files in the ObjDir directory from the .cpp and .c files... +#--------------------------------------------------------- + +DEPEND_OPTIONS = -MMD -MP -MF "$(ObjDir)/$*.d.tmp" \ + -MT "$(ObjDir)/$*.o" -MT "$(ObjDir)/$*.d" + +# If the build succeeded, move the dependency file over, otherwise +# remove it. +DEPEND_MOVEFILE = then $(MV) -f "$(ObjDir)/$*.d.tmp" "$(ObjDir)/$*.d"; \ + else $(RM) "$(ObjDir)/$*.d.tmp"; exit 1; fi + +$(ObjDir)/%.o: %.cpp $(ObjDir)/.dir $(BUILT_SOURCES) + $(Echo) "Compiling $*.cpp for $(BuildMode) build" $(PIC_FLAG) + $(Verb) if $(Compile.CXX) $(DEPEND_OPTIONS) $< -o $(ObjDir)/$*.o ; \ + $(DEPEND_MOVEFILE) + +$(ObjDir)/%.o: %.cc $(ObjDir)/.dir $(BUILT_SOURCES) + $(Echo) "Compiling $*.cc for $(BuildMode) build" $(PIC_FLAG) + $(Verb) if $(Compile.CXX) $(DEPEND_OPTIONS) $< -o $(ObjDir)/$*.o ; \ + $(DEPEND_MOVEFILE) + +$(ObjDir)/%.o: %.c $(ObjDir)/.dir $(BUILT_SOURCES) + $(Echo) "Compiling $*.c for $(BuildMode) build" $(PIC_FLAG) + $(Verb) if $(Compile.C) $(DEPEND_OPTIONS) $< -o $(ObjDir)/$*.o ; \ + $(DEPEND_MOVEFILE) + +#--------------------------------------------------------- +# Create .bc files in the ObjDir directory from .cpp .cc and .c files... +#--------------------------------------------------------- + +BC_DEPEND_OPTIONS = -MMD -MP -MF "$(ObjDir)/$*.bc.d.tmp" \ + -MT "$(ObjDir)/$*.ll" -MT "$(ObjDir)/$*.bc.d" + +# If the build succeeded, move the dependency file over, otherwise +# remove it. +BC_DEPEND_MOVEFILE = then $(MV) -f "$(ObjDir)/$*.bc.d.tmp" "$(ObjDir)/$*.bc.d"; \ + else $(RM) "$(ObjDir)/$*.bc.d.tmp"; exit 1; fi + +$(ObjDir)/%.ll: %.cpp $(ObjDir)/.dir $(BUILT_SOURCES) $(LLVMGXX) + $(Echo) "Compiling $*.cpp for $(BuildMode) build (bytecode)" + $(Verb) if $(BCCompile.CXX) $(BC_DEPEND_OPTIONS) \ + $< -o $(ObjDir)/$*.ll -S -emit-llvm ; \ + $(BC_DEPEND_MOVEFILE) + +$(ObjDir)/%.ll: %.cc $(ObjDir)/.dir $(BUILT_SOURCES) $(LLVMGXX) + $(Echo) "Compiling $*.cc for $(BuildMode) build (bytecode)" + $(Verb) if $(BCCompile.CXX) $(BC_DEPEND_OPTIONS) \ + $< -o $(ObjDir)/$*.ll -S -emit-llvm ; \ + $(BC_DEPEND_MOVEFILE) + +$(ObjDir)/%.ll: %.c $(ObjDir)/.dir $(BUILT_SOURCES) $(LLVMGCC) + $(Echo) "Compiling $*.c for $(BuildMode) build (bytecode)" + $(Verb) if $(BCCompile.C) $(BC_DEPEND_OPTIONS) \ + $< -o $(ObjDir)/$*.ll -S -emit-llvm ; \ + $(BC_DEPEND_MOVEFILE) + +# Provide alternate rule sets if dependencies are disabled +else + +$(ObjDir)/%.o: %.cpp $(ObjDir)/.dir $(BUILT_SOURCES) + $(Echo) "Compiling $*.cpp for $(BuildMode) build" $(PIC_FLAG) + $(Compile.CXX) $< -o $@ + +$(ObjDir)/%.o: %.cc $(ObjDir)/.dir $(BUILT_SOURCES) + $(Echo) "Compiling $*.cc for $(BuildMode) build" $(PIC_FLAG) + $(Compile.CXX) $< -o $@ + +$(ObjDir)/%.o: %.c $(ObjDir)/.dir $(BUILT_SOURCES) + $(Echo) "Compiling $*.c for $(BuildMode) build" $(PIC_FLAG) + $(Compile.C) $< -o $@ + +$(ObjDir)/%.ll: %.cpp $(ObjDir)/.dir $(BUILT_SOURCES) $(LLVMGXX) + $(Echo) "Compiling $*.cpp for $(BuildMode) build (bytecode)" + $(BCCompile.CXX) $< -o $@ -S -emit-llvm + +$(ObjDir)/%.ll: %.cc $(ObjDir)/.dir $(BUILT_SOURCES) $(LLVMGXX) + $(Echo) "Compiling $*.cc for $(BuildMode) build (bytecode)" + $(BCCompile.CXX) $< -o $@ -S -emit-llvm + +$(ObjDir)/%.ll: %.c $(ObjDir)/.dir $(BUILT_SOURCES) $(LLVMGCC) + $(Echo) "Compiling $*.c for $(BuildMode) build (bytecode)" + $(BCCompile.C) $< -o $@ -S -emit-llvm + +endif + + +## Rules for building preprocessed (.i/.ii) outputs. +$(BuildMode)/%.ii: %.cpp $(ObjDir)/.dir $(BUILT_SOURCES) + $(Echo) "Compiling $*.cpp for $(BuildMode) build to .ii file" + $(Verb) $(Preprocess.CXX) $< -o $@ + +$(BuildMode)/%.ii: %.cc $(ObjDir)/.dir $(BUILT_SOURCES) + $(Echo) "Compiling $*.cc for $(BuildMode) build to .ii file" + $(Verb) $(Preprocess.CXX) $< -o $@ + +$(BuildMode)/%.i: %.c $(ObjDir)/.dir $(BUILT_SOURCES) + $(Echo) "Compiling $*.c for $(BuildMode) build to .i file" + $(Verb) $(Preprocess.C) $< -o $@ + + +$(ObjDir)/%.s: %.cpp $(ObjDir)/.dir $(BUILT_SOURCES) + $(Echo) "Compiling $*.cpp to asm for $(BuildMode) build" $(PIC_FLAG) + $(Compile.CXX) $< -o $@ -S + +$(ObjDir)/%.s: %.cc $(ObjDir)/.dir $(BUILT_SOURCES) + $(Echo) "Compiling $*.cc to asm for $(BuildMode) build" $(PIC_FLAG) + $(Compile.CXX) $< -o $@ -S + +$(ObjDir)/%.s: %.c $(ObjDir)/.dir $(BUILT_SOURCES) + $(Echo) "Compiling $*.c to asm for $(BuildMode) build" $(PIC_FLAG) + $(Compile.C) $< -o $@ -S + + +# make the C and C++ compilers strip debug info out of bytecode libraries. +ifdef DEBUG_RUNTIME +$(ObjectsBC): $(ObjDir)/%.bc: $(ObjDir)/%.ll $(LOPT) + $(Echo) "Compiling $*.ll to $*.bc for $(BuildMode) build (bytecode)" + $(Verb) $(LOPT) $< -std-compile-opts -o $@ +else +$(ObjectsBC): $(ObjDir)/%.bc: $(ObjDir)/%.ll $(LOPT) + $(Echo) "Compiling $*.ll to $*.bc for $(BuildMode) build (bytecode)" + $(Verb) $(LOPT) $< -std-compile-opts -strip-debug -o $@ +endif + + +#--------------------------------------------------------- +# Provide rule to build .bc files from .ll sources, +# regardless of dependencies +#--------------------------------------------------------- +$(ObjDir)/%.bc: %.ll $(ObjDir)/.dir $(LLVMAS) + $(Echo) "Compiling $*.ll for $(BuildMode) build" + $(Verb) $(LLVMAS) $< -f -o $@ + +############################################################################### +# TABLEGEN: Provide rules for running tblgen to produce *.inc files +############################################################################### + +ifdef TARGET +TABLEGEN_INC_FILES_COMMON = 1 +endif + +ifdef LLVMC_BUILD_AUTOGENERATED_INC +TABLEGEN_INC_FILES_COMMON = 1 +endif + +ifdef TABLEGEN_INC_FILES_COMMON + +INCFiles := $(filter %.inc,$(BUILT_SOURCES)) +INCTMPFiles := $(INCFiles:%=$(ObjDir)/%.tmp) +.PRECIOUS: $(INCTMPFiles) $(INCFiles) + +# INCFiles rule: All of the tblgen generated files are emitted to +# $(ObjDir)/%.inc.tmp, instead of emitting them directly to %.inc. This allows +# us to only "touch" the real file if the contents of it change. IOW, if +# tblgen is modified, all of the .inc.tmp files are regenerated, but no +# dependencies of the .inc files are, unless the contents of the .inc file +# changes. +$(INCFiles) : %.inc : $(ObjDir)/%.inc.tmp + $(Verb) $(CMP) -s $@ $< || $(CP) $< $@ + +endif # TABLEGEN_INC_FILES_COMMON + +ifdef TARGET + +TDFiles := $(strip $(wildcard $(PROJ_SRC_DIR)/*.td) \ + $(LLVM_SRC_ROOT)/include/llvm/Target/Target.td \ + $(LLVM_SRC_ROOT)/include/llvm/Target/TargetCallingConv.td \ + $(LLVM_SRC_ROOT)/include/llvm/Target/TargetSchedule.td \ + $(LLVM_SRC_ROOT)/include/llvm/Target/TargetSelectionDAG.td \ + $(LLVM_SRC_ROOT)/include/llvm/CodeGen/ValueTypes.td) \ + $(wildcard $(LLVM_SRC_ROOT)/include/llvm/Intrinsics*.td) + +# All of these files depend on tblgen and the .td files. +$(INCTMPFiles) : $(TBLGEN) $(TDFiles) + +$(TARGET:%=$(ObjDir)/%GenRegisterNames.inc.tmp): \ +$(ObjDir)/%GenRegisterNames.inc.tmp : %.td $(ObjDir)/.dir + $(Echo) "Building $( $@ +else +%.ps: %.dot + $(Echo) "Cannot build $@: The program dot is not installed" +endif + +# This rules ensures that header files that are removed still have a rule for +# which they can be "generated." This allows make to ignore them and +# reproduce the dependency lists. +%.h:: ; +%.hpp:: ; + +# Define clean-local to clean the current directory. Note that this uses a +# very conservative approach ensuring that empty variables do not cause +# errors or disastrous removal. +clean-local:: +ifneq ($(strip $(ObjRootDir)),) + -$(Verb) $(RM) -rf $(ObjRootDir) +endif + -$(Verb) $(RM) -f core core.[0-9][0-9]* *.o *.d *~ *.flc +ifneq ($(strip $(SHLIBEXT)),) # Extra paranoia - make real sure SHLIBEXT is set + -$(Verb) $(RM) -f *$(SHLIBEXT) +endif + +clean-all-local:: + -$(Verb) $(RM) -rf Debug Release Profile + + +############################################################################### +# DEPENDENCIES: Include the dependency files if we should +############################################################################### +ifndef DISABLE_AUTO_DEPENDENCIES + +# If its not one of the cleaning targets +ifndef IS_CLEANING_TARGET + +# Get the list of dependency files +DependSourceFiles := $(basename $(filter %.cpp %.c %.cc, $(Sources))) +DependFiles := $(DependSourceFiles:%=$(PROJ_OBJ_DIR)/$(BuildMode)/%.d) + +# Include bitcode dependency files if using bitcode libraries +ifdef BYTECODE_LIBRARY +DependFiles += $(DependSourceFiles:%=$(PROJ_OBJ_DIR)/$(BuildMode)/%.bc.d) +endif + +-include $(DependFiles) "" + +endif + +endif + +############################################################################### +# CHECK: Running the test suite +############################################################################### + +check:: + $(Verb) if test -d "$(PROJ_OBJ_ROOT)/test" ; then \ + if test -f "$(PROJ_OBJ_ROOT)/test/Makefile" ; then \ + $(EchoCmd) Running test suite ; \ + $(MAKE) -C $(PROJ_OBJ_ROOT)/test check-local \ + TESTSUITE=$(TESTSUITE) ; \ + else \ + $(EchoCmd) No Makefile in test directory ; \ + fi ; \ + else \ + $(EchoCmd) No test directory ; \ + fi + +check-lit:: + $(Verb) if test -d "$(PROJ_OBJ_ROOT)/test" ; then \ + if test -f "$(PROJ_OBJ_ROOT)/test/Makefile" ; then \ + $(EchoCmd) Running test suite ; \ + $(MAKE) -C $(PROJ_OBJ_ROOT)/test check-local-lit ; \ + else \ + $(EchoCmd) No Makefile in test directory ; \ + fi ; \ + else \ + $(EchoCmd) No test directory ; \ + fi + +check-all:: + $(Verb) if test -d "$(PROJ_OBJ_ROOT)/test" ; then \ + if test -f "$(PROJ_OBJ_ROOT)/test/Makefile" ; then \ + $(EchoCmd) Running test suite ; \ + $(MAKE) -C $(PROJ_OBJ_ROOT)/test check-local-all ; \ + else \ + $(EchoCmd) No Makefile in test directory ; \ + fi ; \ + else \ + $(EchoCmd) No test directory ; \ + fi + +############################################################################### +# UNITTESTS: Running the unittests test suite +############################################################################### + +unittests:: + $(Verb) if test -d "$(PROJ_OBJ_ROOT)/unittests" ; then \ + if test -f "$(PROJ_OBJ_ROOT)/unittests/Makefile" ; then \ + $(EchoCmd) Running unittests test suite ; \ + $(MAKE) -C $(PROJ_OBJ_ROOT)/unittests unitcheck; \ + else \ + $(EchoCmd) No Makefile in unittests directory ; \ + fi ; \ + else \ + $(EchoCmd) No unittests directory ; \ + fi + +############################################################################### +# DISTRIBUTION: Handle construction of a distribution tarball +############################################################################### + +#------------------------------------------------------------------------ +# Define distribution related variables +#------------------------------------------------------------------------ +DistName := $(PROJECT_NAME)-$(PROJ_VERSION) +DistDir := $(PROJ_OBJ_ROOT)/$(DistName) +TopDistDir := $(PROJ_OBJ_ROOT)/$(DistName) +DistTarGZip := $(PROJ_OBJ_ROOT)/$(DistName).tar.gz +DistZip := $(PROJ_OBJ_ROOT)/$(DistName).zip +DistTarBZ2 := $(PROJ_OBJ_ROOT)/$(DistName).tar.bz2 +DistAlways := CREDITS.TXT LICENSE.TXT README.txt README AUTHORS COPYING \ + ChangeLog INSTALL NEWS Makefile Makefile.common Makefile.rules \ + Makefile.config.in configure autoconf +DistOther := $(notdir $(wildcard \ + $(PROJ_SRC_DIR)/*.h \ + $(PROJ_SRC_DIR)/*.td \ + $(PROJ_SRC_DIR)/*.def \ + $(PROJ_SRC_DIR)/*.ll \ + $(PROJ_SRC_DIR)/*.in)) +DistSubDirs := $(SubDirs) +DistSources = $(Sources) $(EXTRA_DIST) +DistFiles = $(DistAlways) $(DistSources) $(DistOther) + +#------------------------------------------------------------------------ +# We MUST build distribution with OBJ_DIR != SRC_DIR +#------------------------------------------------------------------------ +ifeq ($(PROJ_SRC_DIR),$(PROJ_OBJ_DIR)) +dist dist-check dist-clean dist-gzip dist-bzip2 dist-zip :: + $(Echo) ERROR: Target $@ only available with OBJ_DIR != SRC_DIR + +else + +#------------------------------------------------------------------------ +# Prevent attempt to run dist targets from anywhere but the top level +#------------------------------------------------------------------------ +ifneq ($(LEVEL),.) +dist dist-check dist-clean dist-gzip dist-bzip2 dist-zip :: + $(Echo) ERROR: You must run $@ from $(PROJ_OBJ_ROOT) +else + +#------------------------------------------------------------------------ +# Provide the top level targets +#------------------------------------------------------------------------ + +dist-gzip:: $(DistTarGZip) + +$(DistTarGZip) : $(TopDistDir)/.makedistdir + $(Echo) Packing gzipped distribution tar file. + $(Verb) cd $(PROJ_OBJ_ROOT) ; $(TAR) chf - "$(DistName)" | \ + $(GZIP) -c > "$(DistTarGZip)" + +dist-bzip2:: $(DistTarBZ2) + +$(DistTarBZ2) : $(TopDistDir)/.makedistdir + $(Echo) Packing bzipped distribution tar file. + $(Verb) cd $(PROJ_OBJ_ROOT) ; $(TAR) chf - $(DistName) | \ + $(BZIP2) -c >$(DistTarBZ2) + +dist-zip:: $(DistZip) + +$(DistZip) : $(TopDistDir)/.makedistdir + $(Echo) Packing zipped distribution file. + $(Verb) rm -f $(DistZip) + $(Verb) cd $(PROJ_OBJ_ROOT) ; $(ZIP) -rq $(DistZip) $(DistName) + +dist :: $(DistTarGZip) $(DistTarBZ2) $(DistZip) + $(Echo) ===== DISTRIBUTION PACKAGING SUCESSFUL ===== + +DistCheckDir := $(PROJ_OBJ_ROOT)/_distcheckdir + +dist-check:: $(DistTarGZip) + $(Echo) Checking distribution tar file. + $(Verb) if test -d $(DistCheckDir) ; then \ + $(RM) -rf $(DistCheckDir) ; \ + fi + $(Verb) $(MKDIR) $(DistCheckDir) + $(Verb) cd $(DistCheckDir) && \ + $(MKDIR) $(DistCheckDir)/build && \ + $(MKDIR) $(DistCheckDir)/install && \ + gunzip -c $(DistTarGZip) | $(TAR) xf - && \ + cd build && \ + ../$(DistName)/configure --prefix="$(DistCheckDir)/install" \ + --srcdir=../$(DistName) $(DIST_CHECK_CONFIG_OPTIONS) && \ + $(MAKE) all && \ + $(MAKE) check && \ + $(MAKE) unittests && \ + $(MAKE) install && \ + $(MAKE) uninstall && \ + $(MAKE) dist-clean && \ + $(EchoCmd) ===== $(DistTarGZip) Ready For Distribution ===== + +dist-clean:: + $(Echo) Cleaning distribution files + -$(Verb) $(RM) -rf $(DistTarGZip) $(DistTarBZ2) $(DistZip) $(DistName) \ + $(DistCheckDir) + +endif + +#------------------------------------------------------------------------ +# Provide the recursive distdir target for building the distribution directory +#------------------------------------------------------------------------ +distdir: $(DistDir)/.makedistdir +$(DistDir)/.makedistdir: $(DistSources) + $(Verb) if test "$(DistDir)" = "$(TopDistDir)" ; then \ + if test -d "$(DistDir)" ; then \ + find $(DistDir) -type d ! -perm -200 -exec chmod u+w {} ';' || \ + exit 1 ; \ + fi ; \ + $(EchoCmd) Removing old $(DistDir) ; \ + $(RM) -rf $(DistDir); \ + $(EchoCmd) Making 'all' to verify build ; \ + $(MAKE) ENABLE_OPTIMIZED=1 all ; \ + fi + $(Echo) Building Distribution Directory $(DistDir) + $(Verb) $(MKDIR) $(DistDir) + $(Verb) srcdirstrip=`echo "$(PROJ_SRC_DIR)" | sed 's|.|.|g'`; \ + srcrootstrip=`echo "$(PROJ_SRC_ROOT)" | sed 's|.|.|g'`; \ + for file in $(DistFiles) ; do \ + case "$$file" in \ + $(PROJ_SRC_DIR)/*) \ + file=`echo "$$file" | sed "s#^$$srcdirstrip/##"` \ + ;; \ + $(PROJ_SRC_ROOT)/*) \ + file=`echo "$$file" | \ + sed "s#^$$srcrootstrip/##"` \ + ;; \ + esac; \ + if test -f "$(PROJ_SRC_DIR)/$$file" || \ + test -d "$(PROJ_SRC_DIR)/$$file" ; then \ + from_dir="$(PROJ_SRC_DIR)" ; \ + elif test -f "$$file" || test -d "$$file" ; then \ + from_dir=. ; \ + fi ; \ + to_dir=`echo "$$file" | sed -e 's#/[^/]*$$##'` ; \ + if test "$$to_dir" != "$$file" && test "$$to_dir" != "."; then \ + to_dir="$(DistDir)/$$dir"; \ + $(MKDIR) "$$to_dir" ; \ + else \ + to_dir="$(DistDir)"; \ + fi; \ + mid_dir=`echo "$$file" | sed -n -e 's#^\(.*\)/[^/]*$$#\1#p'`; \ + if test -n "$$mid_dir" ; then \ + $(MKDIR) "$$to_dir/$$mid_dir" || exit 1; \ + fi ; \ + if test -d "$$from_dir/$$file"; then \ + if test -d "$(PROJ_SRC_DIR)/$$file" && \ + test "$$from_dir" != "$(PROJ_SRC_DIR)" ; then \ + cd $(PROJ_SRC_DIR) ; \ + $(TAR) cf - $$file --exclude .svn --exclude CVS | \ + ( cd $$to_dir ; $(TAR) xf - ) ; \ + cd $(PROJ_OBJ_DIR) ; \ + else \ + cd $$from_dir ; \ + $(TAR) cf - $$file --exclude .svn --exclude CVS | \ + ( cd $$to_dir ; $(TAR) xf - ) ; \ + cd $(PROJ_OBJ_DIR) ; \ + fi; \ + elif test -f "$$from_dir/$$file" ; then \ + $(CP) -p "$$from_dir/$$file" "$(DistDir)/$$file" || exit 1; \ + elif test -L "$$from_dir/$$file" ; then \ + $(CP) -pd "$$from_dir/$$file" $(DistDir)/$$file || exit 1; \ + elif echo "$(DistAlways)" | grep -v "$$file" >/dev/null ; then \ + $(EchoCmd) "===== WARNING: Distribution Source " \ + "$$from_dir/$$file Not Found!" ; \ + elif test "$(Verb)" != '@' ; then \ + $(EchoCmd) "Skipping non-existent $$from_dir/$$file" ; \ + fi; \ + done + $(Verb) for subdir in $(DistSubDirs) ; do \ + if test "$$subdir" \!= "." ; then \ + new_distdir="$(DistDir)/$$subdir" ; \ + test -d "$$new_distdir" || $(MKDIR) "$$new_distdir" || exit 1; \ + ( cd $$subdir && $(MAKE) ENABLE_OPTIMIZED=1 \ + DistDir="$$new_distdir" distdir ) || exit 1; \ + fi; \ + done + $(Verb) if test "$(DistDir)" = "$(TopDistDir)" ; then \ + $(EchoCmd) Eliminating CVS/.svn directories from distribution ; \ + $(RM) -rf `find $(TopDistDir) -type d \( -name CVS -o \ + -name .svn \) -print` ;\ + $(MAKE) dist-hook ; \ + $(FIND) $(TopDistDir) -type d ! -perm -777 -exec chmod a+rwx {} \; \ + -o ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; \ + -o ! -type d ! -perm -400 -exec chmod a+r {} \; \ + -o ! -type d ! -perm -444 -exec \ + $(SHELL) $(INSTALL_SH) -c -m a+r {} {} \; \ + || chmod -R a+r $(DistDir) ; \ + fi + +# This is invoked by distdir target, define it as a no-op to avoid errors if not +# defined by user. +dist-hook:: + +endif + +############################################################################### +# TOP LEVEL - targets only to apply at the top level directory +############################################################################### + +ifeq ($(LEVEL),.) + +#------------------------------------------------------------------------ +# Install support for the project's include files: +#------------------------------------------------------------------------ +ifdef NO_INSTALL +install-local:: + $(Echo) Install circumvented with NO_INSTALL +uninstall-local:: + $(Echo) Uninstall circumvented with NO_INSTALL +else +install-local:: + $(Echo) Installing include files + $(Verb) $(MKDIR) $(PROJ_includedir) + $(Verb) if test -d "$(PROJ_SRC_ROOT)/include" ; then \ + cd $(PROJ_SRC_ROOT)/include && \ + for hdr in `find . -type f '!' '(' -name '*~' \ + -o -name '.#*' -o -name '*.in' ')' -print | grep -v CVS | \ + grep -v .svn` ; do \ + instdir=`dirname "$(PROJ_includedir)/$$hdr"` ; \ + if test \! -d "$$instdir" ; then \ + $(EchoCmd) Making install directory $$instdir ; \ + $(MKDIR) $$instdir ;\ + fi ; \ + $(DataInstall) $$hdr $(PROJ_includedir)/$$hdr ; \ + done ; \ + fi +ifneq ($(PROJ_SRC_ROOT),$(PROJ_OBJ_ROOT)) + $(Verb) if test -d "$(PROJ_OBJ_ROOT)/include" ; then \ + cd $(PROJ_OBJ_ROOT)/include && \ + for hdr in `find . -type f -print | grep -v CVS` ; do \ + $(DataInstall) $$hdr $(PROJ_includedir)/$$hdr ; \ + done ; \ + fi +endif + +uninstall-local:: + $(Echo) Uninstalling include files + $(Verb) if [ -d "$(PROJ_SRC_ROOT)/include" ] ; then \ + cd $(PROJ_SRC_ROOT)/include && \ + $(RM) -f `find . -path '*/Internal' -prune -o '(' -type f \ + '!' '(' -name '*~' -o -name '.#*' \ + -o -name '*.in' ')' -print ')' | \ + grep -v CVS | sed 's#^#$(PROJ_includedir)/#'` ; \ + cd $(PROJ_SRC_ROOT)/include && \ + $(RM) -f `find . -path '*/Internal' -prune -o '(' -type f -name '*.in' \ + -print ')' | sed 's#\.in$$##;s#^#$(PROJ_includedir)/#'` ; \ + fi +endif +endif + +check-line-length: + @echo searching for overlength lines in files: $(Sources) + @echo + @echo + egrep -n '.{81}' $(Sources) /dev/null + +check-for-tabs: + @echo searching for tabs in files: $(Sources) + @echo + @echo + egrep -n ' ' $(Sources) /dev/null + +check-footprint: + @ls -l $(LibDir) | awk '\ + BEGIN { sum = 0; } \ + { sum += $$5; } \ + END { printf("Libraries: %6.3f MBytes\n", sum/(1024.0*1024.0)); }' + @ls -l $(ToolDir) | awk '\ + BEGIN { sum = 0; } \ + { sum += $$5; } \ + END { printf("Programs: %6.3f MBytes\n", sum/(1024.0*1024.0)); }' +#------------------------------------------------------------------------ +# Print out the directories used for building +#------------------------------------------------------------------------ +printvars:: + $(Echo) "BuildMode : " '$(BuildMode)' + $(Echo) "PROJ_SRC_ROOT: " '$(PROJ_SRC_ROOT)' + $(Echo) "PROJ_SRC_DIR : " '$(PROJ_SRC_DIR)' + $(Echo) "PROJ_OBJ_ROOT: " '$(PROJ_OBJ_ROOT)' + $(Echo) "PROJ_OBJ_DIR : " '$(PROJ_OBJ_DIR)' + $(Echo) "LLVM_SRC_ROOT: " '$(LLVM_SRC_ROOT)' + $(Echo) "LLVM_OBJ_ROOT: " '$(LLVM_OBJ_ROOT)' + $(Echo) "PROJ_prefix : " '$(PROJ_prefix)' + $(Echo) "PROJ_bindir : " '$(PROJ_bindir)' + $(Echo) "PROJ_libdir : " '$(PROJ_libdir)' + $(Echo) "PROJ_etcdir : " '$(PROJ_etcdir)' + $(Echo) "PROJ_includedir : " '$(PROJ_includedir)' + $(Echo) "UserTargets : " '$(UserTargets)' + $(Echo) "ObjMakefiles : " '$(ObjMakefiles)' + $(Echo) "SrcMakefiles : " '$(SrcMakefiles)' + $(Echo) "ObjDir : " '$(ObjDir)' + $(Echo) "LibDir : " '$(LibDir)' + $(Echo) "ToolDir : " '$(ToolDir)' + $(Echo) "ExmplDir : " '$(ExmplDir)' + $(Echo) "Sources : " '$(Sources)' + $(Echo) "TDFiles : " '$(TDFiles)' + $(Echo) "INCFiles : " '$(INCFiles)' + $(Echo) "INCTMPFiles : " '$(INCTMPFiles)' + $(Echo) "PreConditions: " '$(PreConditions)' + $(Echo) "Compile.CXX : " '$(Compile.CXX)' + $(Echo) "Compile.C : " '$(Compile.C)' + $(Echo) "Archive : " '$(Archive)' + $(Echo) "YaccFiles : " '$(YaccFiles)' + $(Echo) "LexFiles : " '$(LexFiles)' + $(Echo) "Module : " '$(Module)' + $(Echo) "FilesToConfig: " '$(FilesToConfigPATH)' + $(Echo) "SubDirs : " '$(SubDirs)' + $(Echo) "ProjLibsPaths: " '$(ProjLibsPaths)' + $(Echo) "ProjLibsOptions: " '$(ProjLibsOptions)' + +### +# Debugging + +# General debugging rule, use 'make dbg-print-XXX' to print the +# definition, value and origin of XXX. +make-print-%: + $(error PRINT: $(value $*) = "$($*)" (from $(origin $*))) diff --git a/libclamav/c++/llvm/ModuleInfo.txt b/libclamav/c++/llvm/ModuleInfo.txt new file mode 100644 index 000000000..5a1d8b85a --- /dev/null +++ b/libclamav/c++/llvm/ModuleInfo.txt @@ -0,0 +1,4 @@ +DepModule: +BuildCmd: ./build-for-llvm-top.sh +CleanCmd: make clean -C ../build.llvm +InstallCmd: make install -C ../build.llvm diff --git a/libclamav/c++/llvm/README.txt b/libclamav/c++/llvm/README.txt new file mode 100644 index 000000000..c78a9ee15 --- /dev/null +++ b/libclamav/c++/llvm/README.txt @@ -0,0 +1,13 @@ +Low Level Virtual Machine (LLVM) +================================ + +This directory and its subdirectories contain source code for the Low Level +Virtual Machine, a toolkit for the construction of highly optimized compilers, +optimizers, and runtime environments. + +LLVM is open source software. You may freely distribute it under the terms of +the license agreement found in LICENSE.txt. + +Please see the HTML documentation provided in docs/index.html for further +assistance with LLVM. + diff --git a/libclamav/c++/llvm/autoconf/AutoRegen.sh b/libclamav/c++/llvm/autoconf/AutoRegen.sh new file mode 100755 index 000000000..7809667ac --- /dev/null +++ b/libclamav/c++/llvm/autoconf/AutoRegen.sh @@ -0,0 +1,58 @@ +#!/bin/bash + +die() { + echo "$@" 1>&2 + exit 1 +} + +clean() { + echo $1 | sed -e 's/\\//g' +} + +### NOTE: ############################################################ +### These variables specify the tool versions we want to use. +### Periods should be escaped with backslash for use by grep. +### +### If you update these, please also update docs/GettingStarted.html +want_autoconf_version='2\.60' +want_autoheader_version=$want_autoconf_version +want_aclocal_version='1\.9\.6' +want_libtool_version='1\.5\.22' +### END NOTE ######################################################### + +outfile=configure +configfile=configure.ac + +want_autoconf_version_clean=$(clean $want_autoconf_version) +want_autoheader_version_clean=$(clean $want_autoheader_version) +want_aclocal_version_clean=$(clean $want_aclocal_version) +want_libtool_version_clean=$(clean $want_libtool_version) + +test -d autoconf && test -f autoconf/$configfile && cd autoconf +test -f $configfile || die "Can't find 'autoconf' dir; please cd into it first" +autoconf --version | grep $want_autoconf_version > /dev/null +test $? -eq 0 || die "Your autoconf was not detected as being $want_autoconf_version_clean" +aclocal --version | grep '^aclocal.*'$want_aclocal_version > /dev/null +test $? -eq 0 || die "Your aclocal was not detected as being $want_aclocal_version_clean" +autoheader --version | grep '^autoheader.*'$want_autoheader_version > /dev/null +test $? -eq 0 || die "Your autoheader was not detected as being $want_autoheader_version_clean" +libtool --version | grep $want_libtool_version > /dev/null +test $? -eq 0 || die "Your libtool was not detected as being $want_libtool_version_clean" +echo "" +echo "### NOTE: ############################################################" +echo "### If you get *any* warnings from autoconf below you MUST fix the" +echo "### scripts in the m4 directory because there are future forward" +echo "### compatibility or platform support issues at risk. Please do NOT" +echo "### commit any configure script that was generated with warnings" +echo "### present. You should get just three 'Regenerating..' lines." +echo "######################################################################" +echo "" +echo "Regenerating aclocal.m4 with aclocal $want_aclocal_version_clean" +cwd=`pwd` +aclocal --force -I $cwd/m4 || die "aclocal failed" +echo "Regenerating configure with autoconf $want_autoconf_version_clean" +autoconf --force --warnings=all -o ../$outfile $configfile || die "autoconf failed" +cd .. +echo "Regenerating config.h.in with autoheader $want_autoheader_version_clean" +autoheader --warnings=all -I autoconf -I autoconf/m4 autoconf/$configfile || die "autoheader failed" +exit 0 diff --git a/libclamav/c++/llvm/autoconf/ExportMap.map b/libclamav/c++/llvm/autoconf/ExportMap.map new file mode 100644 index 000000000..43e310e05 --- /dev/null +++ b/libclamav/c++/llvm/autoconf/ExportMap.map @@ -0,0 +1,4 @@ +{ + global: main; + local: *; +}; diff --git a/libclamav/c++/llvm/autoconf/LICENSE.TXT b/libclamav/c++/llvm/autoconf/LICENSE.TXT new file mode 100644 index 000000000..72fdd39ed --- /dev/null +++ b/libclamav/c++/llvm/autoconf/LICENSE.TXT @@ -0,0 +1,24 @@ +------------------------------------------------------------------------------ +Autoconf Files +------------------------------------------------------------------------------ +All autoconf files are licensed under the LLVM license with the following +additions: + +llvm/autoconf/install-sh: + This script is licensed under the LLVM license, with the following + additional copyrights and restrictions: + + Copyright 1991 by the Massachusetts Institute of Technology + + Permission to use, copy, modify, distribute, and sell this software and its + documentation for any purpose is hereby granted without fee, provided that + the above copyright notice appear in all copies and that both that + copyright notice and this permission notice appear in supporting + documentation, and that the name of M.I.T. not be used in advertising or + publicity pertaining to distribution of the software without specific, + written prior permission. M.I.T. makes no representations about the + suitability of this software for any purpose. It is provided "as is" + without express or implied warranty. + +Please see the source files for additional copyrights. + diff --git a/libclamav/c++/llvm/autoconf/README.TXT b/libclamav/c++/llvm/autoconf/README.TXT new file mode 100644 index 000000000..3dabdf7b8 --- /dev/null +++ b/libclamav/c++/llvm/autoconf/README.TXT @@ -0,0 +1,49 @@ +Upgrading Libtool +=============================================================================== + +If you are in the mood to upgrade libtool, you must do the following: + + 1. Get the new version of libtool and put it in + 2. configure/build/install libtool with --prefix= + 3. Copy /ltdl.m4 to llvm/autoconf/m4 + 4. Copy /share/aclocal/libtool.m4 to llvm/autoconf/m4/libtool.m4 + 5. Copy /share/libtool/ltmain.sh to llvm/autoconf/ltmain.sh + 6. Copy /share/libtool/libltdl/ltdl.c to llvm/lib/System + 7. Copy /share/libtool/libltdl/ltdl.h to llvm/lib/System + 8. Edit the ltdl.h file to #include "llvm/Config/config.h" at the very top. You + might also need to resolve some compiler warnings (typically about + comparison of signed vs. unsigned values). But, you won't find out about + those until you build LLVM (step 13). + 9. Edit the llvm/autoconf/m4/libtool.m4 file so that: + a) in AC_PROB_LIBTOOL macro, the value of LIBTOOL is set to + $(top_builddir)/mklib, not $(top_builddir)/libtool + b) in AC_LIBTOOL_SETUP macro, the variable default_ofile is set to + "mklib" instead of "libtool" + c) s/AC_ENABLE_SHARED_DEFAULT/enable_shared_default/g + d) s/AC_ENABLE_STATIC_DEFAULT/enable_static_default/g + e) s/AC_ENABLE_FAST_INSTALL_DEFAULT/enable_fast_install_default/g +10. Run "autoupdate libtool.m4 ltdl.m4" in the llvm/autoconf/m4 directory. + This should correctly update the macro definitions in the libtool m4 + files to match the version of autoconf that LLVM uses. This converts + AC_HELP_STRING to AS_HELP_STRING and AC_TRY_LINK to AC_LINK_IFELSE, amongst + other things. You may need to manually adjust the files. +11. Run AutoRegen.sh to get the new macros into configure script +12. If there are any warnings from AutoRegen.sh, go to step 9. +13. Rebuild LLVM, making sure it reconfigures +14. Test the JIT which uses libltdl +15. If it all works, only THEN commit the changes. + +Upgrading autoconf +=============================================================================== + +If you are in the mood to upgrade autoconf, you should: + + 1. Consider not upgrading. + 2. No really, this is a hassle, you don't want to do it. + 3. Get the new version of autoconf and put it in + 4. configure/build/install autoconf with --prefix= + 5. Run autoupdate on all the m4 macros in llvm/autoconf/m4 + 6. Run autoupdate on llvm/autoconf/configure.ac + 7. Regenerate configure script with AutoRegen.sh + 8. If there are any warnings from AutoRegen.sh, fix them and go to step 7. + 9. Test, test, test. diff --git a/libclamav/c++/llvm/autoconf/config.guess b/libclamav/c++/llvm/autoconf/config.guess new file mode 100755 index 000000000..865fe53d6 --- /dev/null +++ b/libclamav/c++/llvm/autoconf/config.guess @@ -0,0 +1,1498 @@ +#! /bin/sh +# Attempt to guess a canonical system name. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 +# Free Software Foundation, Inc. + +timestamp='2009-09-18' + +# This file is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA +# 02110-1301, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + + +# Originally written by Per Bothner. Please send patches (context +# diff format) to and include a ChangeLog +# entry. +# +# This script attempts to guess a canonical system name similar to +# config.sub. If it succeeds, it prints the system name on stdout, and +# exits with 0. Otherwise, it exits with 1. +# +# You can get the latest version of this script from: +# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] + +Output the configuration name of the system \`$me' is run on. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.guess ($timestamp) + +Originally written by Per Bothner. +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, +2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" >&2 + exit 1 ;; + * ) + break ;; + esac +done + +if test $# != 0; then + echo "$me: too many arguments$help" >&2 + exit 1 +fi + +trap 'exit 1' 1 2 15 + +# CC_FOR_BUILD -- compiler used by this script. Note that the use of a +# compiler to aid in system detection is discouraged as it requires +# temporary files to be created and, as you can see below, it is a +# headache to deal with in a portable fashion. + +# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still +# use `HOST_CC' if defined, but it is deprecated. + +# Portable tmp directory creation inspired by the Autoconf team. + +set_cc_for_build=' +trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; +trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; +: ${TMPDIR=/tmp} ; + { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || + { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || + { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || + { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; +dummy=$tmp/dummy ; +tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; +case $CC_FOR_BUILD,$HOST_CC,$CC in + ,,) echo "int x;" > $dummy.c ; + for c in cc gcc c89 c99 ; do + if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then + CC_FOR_BUILD="$c"; break ; + fi ; + done ; + if test x"$CC_FOR_BUILD" = x ; then + CC_FOR_BUILD=no_compiler_found ; + fi + ;; + ,,*) CC_FOR_BUILD=$CC ;; + ,*,*) CC_FOR_BUILD=$HOST_CC ;; +esac ; set_cc_for_build= ;' + +# This is needed to find uname on a Pyramid OSx when run in the BSD universe. +# (ghazi@noc.rutgers.edu 1994-08-24) +if (test -f /.attbin/uname) >/dev/null 2>&1 ; then + PATH=$PATH:/.attbin ; export PATH +fi + +UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown +UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown +UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown +UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown + +# Note: order is significant - the case branches are not exclusive. + +case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in + *:NetBSD:*:*) + # NetBSD (nbsd) targets should (where applicable) match one or + # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*, + # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently + # switched to ELF, *-*-netbsd* would select the old + # object file format. This provides both forward + # compatibility and a consistent mechanism for selecting the + # object file format. + # + # Note: NetBSD doesn't particularly care about the vendor + # portion of the name. We always set it to "unknown". + sysctl="sysctl -n hw.machine_arch" + UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ + /usr/sbin/$sysctl 2>/dev/null || echo unknown)` + case "${UNAME_MACHINE_ARCH}" in + armeb) machine=armeb-unknown ;; + arm*) machine=arm-unknown ;; + sh3el) machine=shl-unknown ;; + sh3eb) machine=sh-unknown ;; + sh5el) machine=sh5le-unknown ;; + *) machine=${UNAME_MACHINE_ARCH}-unknown ;; + esac + # The Operating System including object format, if it has switched + # to ELF recently, or will in the future. + case "${UNAME_MACHINE_ARCH}" in + arm*|i386|m68k|ns32k|sh3*|sparc|vax) + eval $set_cc_for_build + if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ELF__ + then + # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). + # Return netbsd for either. FIX? + os=netbsd + else + os=netbsdelf + fi + ;; + *) + os=netbsd + ;; + esac + # The OS release + # Debian GNU/NetBSD machines have a different userland, and + # thus, need a distinct triplet. However, they do not need + # kernel version information, so it can be replaced with a + # suitable tag, in the style of linux-gnu. + case "${UNAME_VERSION}" in + Debian*) + release='-gnu' + ;; + *) + release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + ;; + esac + # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: + # contains redundant information, the shorter form: + # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. + echo "${machine}-${os}${release}" + exit ;; + *:OpenBSD:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` + echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} + exit ;; + *:ekkoBSD:*:*) + echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} + exit ;; + *:SolidBSD:*:*) + echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} + exit ;; + macppc:MirBSD:*:*) + echo powerpc-unknown-mirbsd${UNAME_RELEASE} + exit ;; + *:MirBSD:*:*) + echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} + exit ;; + alpha:OSF1:*:*) + case $UNAME_RELEASE in + *4.0) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` + ;; + *5.*) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` + ;; + esac + # According to Compaq, /usr/sbin/psrinfo has been available on + # OSF/1 and Tru64 systems produced since 1995. I hope that + # covers most systems running today. This code pipes the CPU + # types through head -n 1, so we only detect the type of CPU 0. + ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` + case "$ALPHA_CPU_TYPE" in + "EV4 (21064)") + UNAME_MACHINE="alpha" ;; + "EV4.5 (21064)") + UNAME_MACHINE="alpha" ;; + "LCA4 (21066/21068)") + UNAME_MACHINE="alpha" ;; + "EV5 (21164)") + UNAME_MACHINE="alphaev5" ;; + "EV5.6 (21164A)") + UNAME_MACHINE="alphaev56" ;; + "EV5.6 (21164PC)") + UNAME_MACHINE="alphapca56" ;; + "EV5.7 (21164PC)") + UNAME_MACHINE="alphapca57" ;; + "EV6 (21264)") + UNAME_MACHINE="alphaev6" ;; + "EV6.7 (21264A)") + UNAME_MACHINE="alphaev67" ;; + "EV6.8CB (21264C)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8AL (21264B)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8CX (21264D)") + UNAME_MACHINE="alphaev68" ;; + "EV6.9A (21264/EV69A)") + UNAME_MACHINE="alphaev69" ;; + "EV7 (21364)") + UNAME_MACHINE="alphaev7" ;; + "EV7.9 (21364A)") + UNAME_MACHINE="alphaev79" ;; + esac + # A Pn.n version is a patched version. + # A Vn.n version is a released version. + # A Tn.n version is a released field test version. + # A Xn.n version is an unreleased experimental baselevel. + # 1.2 uses "1.2" for uname -r. + echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + exit ;; + Alpha\ *:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # Should we change UNAME_MACHINE based on the output of uname instead + # of the specific Alpha model? + echo alpha-pc-interix + exit ;; + 21064:Windows_NT:50:3) + echo alpha-dec-winnt3.5 + exit ;; + Amiga*:UNIX_System_V:4.0:*) + echo m68k-unknown-sysv4 + exit ;; + *:[Aa]miga[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-amigaos + exit ;; + *:[Mm]orph[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-morphos + exit ;; + *:OS/390:*:*) + echo i370-ibm-openedition + exit ;; + *:z/VM:*:*) + echo s390-ibm-zvmoe + exit ;; + *:OS400:*:*) + echo powerpc-ibm-os400 + exit ;; + arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) + echo arm-acorn-riscix${UNAME_RELEASE} + exit ;; + arm:riscos:*:*|arm:RISCOS:*:*) + echo arm-unknown-riscos + exit ;; + SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) + echo hppa1.1-hitachi-hiuxmpp + exit ;; + Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) + # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. + if test "`(/bin/universe) 2>/dev/null`" = att ; then + echo pyramid-pyramid-sysv3 + else + echo pyramid-pyramid-bsd + fi + exit ;; + NILE*:*:*:dcosx) + echo pyramid-pyramid-svr4 + exit ;; + DRS?6000:unix:4.0:6*) + echo sparc-icl-nx6 + exit ;; + DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) + case `/usr/bin/uname -p` in + sparc) echo sparc-icl-nx7; exit ;; + esac ;; + s390x:SunOS:*:*) + echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4H:SunOS:5.*:*) + echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) + echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) + AUX_ARCH="i386" + echo ${AUX_ARCH}-pc-auroraux`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) + eval $set_cc_for_build + SUN_ARCH="i386" + # If there is a compiler, see if it is configured for 64-bit objects. + # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. + # This test works for both compilers. + if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then + if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + SUN_ARCH="x86_64" + fi + fi + echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:6*:*) + # According to config.sub, this is the proper way to canonicalize + # SunOS6. Hard to guess exactly what SunOS6 will be like, but + # it's likely to be more like Solaris than SunOS4. + echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:*:*) + case "`/usr/bin/arch -k`" in + Series*|S4*) + UNAME_RELEASE=`uname -v` + ;; + esac + # Japanese Language versions have a version number like `4.1.3-JL'. + echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` + exit ;; + sun3*:SunOS:*:*) + echo m68k-sun-sunos${UNAME_RELEASE} + exit ;; + sun*:*:4.2BSD:*) + UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` + test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 + case "`/bin/arch`" in + sun3) + echo m68k-sun-sunos${UNAME_RELEASE} + ;; + sun4) + echo sparc-sun-sunos${UNAME_RELEASE} + ;; + esac + exit ;; + aushp:SunOS:*:*) + echo sparc-auspex-sunos${UNAME_RELEASE} + exit ;; + # The situation for MiNT is a little confusing. The machine name + # can be virtually everything (everything which is not + # "atarist" or "atariste" at least should have a processor + # > m68000). The system name ranges from "MiNT" over "FreeMiNT" + # to the lowercase version "mint" (or "freemint"). Finally + # the system name "TOS" denotes a system which is actually not + # MiNT. But MiNT is downward compatible to TOS, so this should + # be no problem. + atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) + echo m68k-milan-mint${UNAME_RELEASE} + exit ;; + hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) + echo m68k-hades-mint${UNAME_RELEASE} + exit ;; + *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) + echo m68k-unknown-mint${UNAME_RELEASE} + exit ;; + m68k:machten:*:*) + echo m68k-apple-machten${UNAME_RELEASE} + exit ;; + powerpc:machten:*:*) + echo powerpc-apple-machten${UNAME_RELEASE} + exit ;; + RISC*:Mach:*:*) + echo mips-dec-mach_bsd4.3 + exit ;; + RISC*:ULTRIX:*:*) + echo mips-dec-ultrix${UNAME_RELEASE} + exit ;; + VAX*:ULTRIX*:*:*) + echo vax-dec-ultrix${UNAME_RELEASE} + exit ;; + 2020:CLIX:*:* | 2430:CLIX:*:*) + echo clipper-intergraph-clix${UNAME_RELEASE} + exit ;; + mips:*:*:UMIPS | mips:*:*:RISCos) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c +#ifdef __cplusplus +#include /* for printf() prototype */ + int main (int argc, char *argv[]) { +#else + int main (argc, argv) int argc; char *argv[]; { +#endif + #if defined (host_mips) && defined (MIPSEB) + #if defined (SYSTYPE_SYSV) + printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_SVR4) + printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) + printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); + #endif + #endif + exit (-1); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && + dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && + SYSTEM_NAME=`$dummy $dummyarg` && + { echo "$SYSTEM_NAME"; exit; } + echo mips-mips-riscos${UNAME_RELEASE} + exit ;; + Motorola:PowerMAX_OS:*:*) + echo powerpc-motorola-powermax + exit ;; + Motorola:*:4.3:PL8-*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:Power_UNIX:*:*) + echo powerpc-harris-powerunix + exit ;; + m88k:CX/UX:7*:*) + echo m88k-harris-cxux7 + exit ;; + m88k:*:4*:R4*) + echo m88k-motorola-sysv4 + exit ;; + m88k:*:3*:R3*) + echo m88k-motorola-sysv3 + exit ;; + AViiON:dgux:*:*) + # DG/UX returns AViiON for all architectures + UNAME_PROCESSOR=`/usr/bin/uname -p` + if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] + then + if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ + [ ${TARGET_BINARY_INTERFACE}x = x ] + then + echo m88k-dg-dgux${UNAME_RELEASE} + else + echo m88k-dg-dguxbcs${UNAME_RELEASE} + fi + else + echo i586-dg-dgux${UNAME_RELEASE} + fi + exit ;; + M88*:DolphinOS:*:*) # DolphinOS (SVR3) + echo m88k-dolphin-sysv3 + exit ;; + M88*:*:R3*:*) + # Delta 88k system running SVR3 + echo m88k-motorola-sysv3 + exit ;; + XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) + echo m88k-tektronix-sysv3 + exit ;; + Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) + echo m68k-tektronix-bsd + exit ;; + *:IRIX*:*:*) + echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` + exit ;; + ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. + echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id + exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' + i*86:AIX:*:*) + echo i386-ibm-aix + exit ;; + ia64:AIX:*:*) + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} + exit ;; + *:AIX:2:3) + if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + + main() + { + if (!__power_pc()) + exit(1); + puts("powerpc-ibm-aix3.2.5"); + exit(0); + } +EOF + if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` + then + echo "$SYSTEM_NAME" + else + echo rs6000-ibm-aix3.2.5 + fi + elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then + echo rs6000-ibm-aix3.2.4 + else + echo rs6000-ibm-aix3.2 + fi + exit ;; + *:AIX:*:[456]) + IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` + if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then + IBM_ARCH=rs6000 + else + IBM_ARCH=powerpc + fi + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${IBM_ARCH}-ibm-aix${IBM_REV} + exit ;; + *:AIX:*:*) + echo rs6000-ibm-aix + exit ;; + ibmrt:4.4BSD:*|romp-ibm:BSD:*) + echo romp-ibm-bsd4.4 + exit ;; + ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and + echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to + exit ;; # report: romp-ibm BSD 4.3 + *:BOSX:*:*) + echo rs6000-bull-bosx + exit ;; + DPX/2?00:B.O.S.:*:*) + echo m68k-bull-sysv3 + exit ;; + 9000/[34]??:4.3bsd:1.*:*) + echo m68k-hp-bsd + exit ;; + hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) + echo m68k-hp-bsd4.4 + exit ;; + 9000/[34678]??:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + case "${UNAME_MACHINE}" in + 9000/31? ) HP_ARCH=m68000 ;; + 9000/[34]?? ) HP_ARCH=m68k ;; + 9000/[678][0-9][0-9]) + if [ -x /usr/bin/getconf ]; then + sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` + sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` + case "${sc_cpu_version}" in + 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 + 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 + 532) # CPU_PA_RISC2_0 + case "${sc_kernel_bits}" in + 32) HP_ARCH="hppa2.0n" ;; + 64) HP_ARCH="hppa2.0w" ;; + '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 + esac ;; + esac + fi + if [ "${HP_ARCH}" = "" ]; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + + #define _HPUX_SOURCE + #include + #include + + int main () + { + #if defined(_SC_KERNEL_BITS) + long bits = sysconf(_SC_KERNEL_BITS); + #endif + long cpu = sysconf (_SC_CPU_VERSION); + + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1"); break; + case CPU_PA_RISC2_0: + #if defined(_SC_KERNEL_BITS) + switch (bits) + { + case 64: puts ("hppa2.0w"); break; + case 32: puts ("hppa2.0n"); break; + default: puts ("hppa2.0"); break; + } break; + #else /* !defined(_SC_KERNEL_BITS) */ + puts ("hppa2.0"); break; + #endif + default: puts ("hppa1.0"); break; + } + exit (0); + } +EOF + (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` + test -z "$HP_ARCH" && HP_ARCH=hppa + fi ;; + esac + if [ ${HP_ARCH} = "hppa2.0w" ] + then + eval $set_cc_for_build + + # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating + # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler + # generating 64-bit code. GNU and HP use different nomenclature: + # + # $ CC_FOR_BUILD=cc ./config.guess + # => hppa2.0w-hp-hpux11.23 + # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess + # => hppa64-hp-hpux11.23 + + if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | + grep -q __LP64__ + then + HP_ARCH="hppa2.0w" + else + HP_ARCH="hppa64" + fi + fi + echo ${HP_ARCH}-hp-hpux${HPUX_REV} + exit ;; + ia64:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + echo ia64-hp-hpux${HPUX_REV} + exit ;; + 3050*:HI-UX:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + int + main () + { + long cpu = sysconf (_SC_CPU_VERSION); + /* The order matters, because CPU_IS_HP_MC68K erroneously returns + true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct + results, however. */ + if (CPU_IS_PA_RISC (cpu)) + { + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; + case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; + default: puts ("hppa-hitachi-hiuxwe2"); break; + } + } + else if (CPU_IS_HP_MC68K (cpu)) + puts ("m68k-hitachi-hiuxwe2"); + else puts ("unknown-hitachi-hiuxwe2"); + exit (0); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } + echo unknown-hitachi-hiuxwe2 + exit ;; + 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) + echo hppa1.1-hp-bsd + exit ;; + 9000/8??:4.3bsd:*:*) + echo hppa1.0-hp-bsd + exit ;; + *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) + echo hppa1.0-hp-mpeix + exit ;; + hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) + echo hppa1.1-hp-osf + exit ;; + hp8??:OSF1:*:*) + echo hppa1.0-hp-osf + exit ;; + i*86:OSF1:*:*) + if [ -x /usr/sbin/sysversion ] ; then + echo ${UNAME_MACHINE}-unknown-osf1mk + else + echo ${UNAME_MACHINE}-unknown-osf1 + fi + exit ;; + parisc*:Lites*:*:*) + echo hppa1.1-hp-lites + exit ;; + C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) + echo c1-convex-bsd + exit ;; + C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit ;; + C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) + echo c34-convex-bsd + exit ;; + C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) + echo c38-convex-bsd + exit ;; + C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) + echo c4-convex-bsd + exit ;; + CRAY*Y-MP:*:*:*) + echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*[A-Z]90:*:*:*) + echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ + | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ + -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ + -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*TS:*:*:*) + echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*T3E:*:*:*) + echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*SV1:*:*:*) + echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + *:UNICOS/mp:*:*) + echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) + FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` + echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + 5000:UNIX_System_V:4.*:*) + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` + echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) + echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} + exit ;; + sparc*:BSD/OS:*:*) + echo sparc-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:BSD/OS:*:*) + echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:FreeBSD:*:*) + case ${UNAME_MACHINE} in + pc98) + echo i386-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + amd64) + echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + *) + echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + esac + exit ;; + i*:CYGWIN*:*) + echo ${UNAME_MACHINE}-pc-cygwin + exit ;; + *:MINGW*:*) + echo ${UNAME_MACHINE}-pc-mingw32 + exit ;; + i*:windows32*:*) + # uname -m includes "-pc" on this system. + echo ${UNAME_MACHINE}-mingw32 + exit ;; + i*:PW*:*) + echo ${UNAME_MACHINE}-pc-pw32 + exit ;; + *:Interix*:[3456]*) + case ${UNAME_MACHINE} in + x86) + echo i586-pc-interix${UNAME_RELEASE} + exit ;; + EM64T | authenticamd | genuineintel) + echo x86_64-unknown-interix${UNAME_RELEASE} + exit ;; + IA64) + echo ia64-unknown-interix${UNAME_RELEASE} + exit ;; + esac ;; + [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) + echo i${UNAME_MACHINE}-pc-mks + exit ;; + 8664:Windows_NT:*) + echo x86_64-pc-mks + exit ;; + i*:Windows_NT*:* | Pentium*:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we + # UNAME_MACHINE based on the output of uname instead of i386? + echo i586-pc-interix + exit ;; + i*:UWIN*:*) + echo ${UNAME_MACHINE}-pc-uwin + exit ;; + amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) + echo x86_64-unknown-cygwin + exit ;; + p*:CYGWIN*:*) + echo powerpcle-unknown-cygwin + exit ;; + prep*:SunOS:5.*:*) + echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + *:GNU:*:*) + # the GNU system + echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` + exit ;; + *:GNU/*:*:*) + # other systems with GNU libc and userland + echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu + exit ;; + i*86:Minix:*:*) + echo ${UNAME_MACHINE}-pc-minix + exit ;; + alpha:Linux:*:*) + case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in + EV5) UNAME_MACHINE=alphaev5 ;; + EV56) UNAME_MACHINE=alphaev56 ;; + PCA56) UNAME_MACHINE=alphapca56 ;; + PCA57) UNAME_MACHINE=alphapca56 ;; + EV6) UNAME_MACHINE=alphaev6 ;; + EV67) UNAME_MACHINE=alphaev67 ;; + EV68*) UNAME_MACHINE=alphaev68 ;; + esac + objdump --private-headers /bin/sh | grep -q ld.so.1 + if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi + echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} + exit ;; + arm*:Linux:*:*) + eval $set_cc_for_build + if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_EABI__ + then + echo ${UNAME_MACHINE}-unknown-linux-gnu + else + echo ${UNAME_MACHINE}-unknown-linux-gnueabi + fi + exit ;; + avr32*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + cris:Linux:*:*) + echo cris-axis-linux-gnu + exit ;; + crisv32:Linux:*:*) + echo crisv32-axis-linux-gnu + exit ;; + frv:Linux:*:*) + echo frv-unknown-linux-gnu + exit ;; + i*86:Linux:*:*) + echo ${UNAME_MACHINE}-pc-linux-gnu + exit ;; + ia64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + m32r*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + m68*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + mips:Linux:*:* | mips64:Linux:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #undef CPU + #undef ${UNAME_MACHINE} + #undef ${UNAME_MACHINE}el + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=${UNAME_MACHINE}el + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=${UNAME_MACHINE} + #else + CPU= + #endif + #endif +EOF + eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n ' + /^CPU/{ + s: ::g + p + }'`" + test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } + ;; + or32:Linux:*:*) + echo or32-unknown-linux-gnu + exit ;; + padre:Linux:*:*) + echo sparc-unknown-linux-gnu + exit ;; + parisc64:Linux:*:* | hppa64:Linux:*:*) + echo hppa64-unknown-linux-gnu + exit ;; + parisc:Linux:*:* | hppa:Linux:*:*) + # Look for CPU level + case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in + PA7*) echo hppa1.1-unknown-linux-gnu ;; + PA8*) echo hppa2.0-unknown-linux-gnu ;; + *) echo hppa-unknown-linux-gnu ;; + esac + exit ;; + ppc64:Linux:*:*) + echo powerpc64-unknown-linux-gnu + exit ;; + ppc:Linux:*:*) + echo powerpc-unknown-linux-gnu + exit ;; + s390:Linux:*:* | s390x:Linux:*:*) + echo ${UNAME_MACHINE}-ibm-linux + exit ;; + sh64*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + sh*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + sparc:Linux:*:* | sparc64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + vax:Linux:*:*) + echo ${UNAME_MACHINE}-dec-linux-gnu + exit ;; + x86_64:Linux:*:*) + echo x86_64-unknown-linux-gnu + exit ;; + xtensa*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + i*86:DYNIX/ptx:4*:*) + # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. + # earlier versions are messed up and put the nodename in both + # sysname and nodename. + echo i386-sequent-sysv4 + exit ;; + i*86:UNIX_SV:4.2MP:2.*) + # Unixware is an offshoot of SVR4, but it has its own version + # number series starting with 2... + # I am not positive that other SVR4 systems won't match this, + # I just have to hope. -- rms. + # Use sysv4.2uw... so that sysv4* matches it. + echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} + exit ;; + i*86:OS/2:*:*) + # If we were able to find `uname', then EMX Unix compatibility + # is probably installed. + echo ${UNAME_MACHINE}-pc-os2-emx + exit ;; + i*86:XTS-300:*:STOP) + echo ${UNAME_MACHINE}-unknown-stop + exit ;; + i*86:atheos:*:*) + echo ${UNAME_MACHINE}-unknown-atheos + exit ;; + i*86:syllable:*:*) + echo ${UNAME_MACHINE}-pc-syllable + exit ;; + i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) + echo i386-unknown-lynxos${UNAME_RELEASE} + exit ;; + i*86:*DOS:*:*) + echo ${UNAME_MACHINE}-pc-msdosdjgpp + exit ;; + i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) + UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` + if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then + echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} + else + echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} + fi + exit ;; + i*86:*:5:[678]*) + # UnixWare 7.x, OpenUNIX and OpenServer 6. + case `/bin/uname -X | grep "^Machine"` in + *486*) UNAME_MACHINE=i486 ;; + *Pentium) UNAME_MACHINE=i586 ;; + *Pent*|*Celeron) UNAME_MACHINE=i686 ;; + esac + echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} + exit ;; + i*86:*:3.2:*) + if test -f /usr/options/cb.name; then + UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then + UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` + (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 + (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ + && UNAME_MACHINE=i586 + (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ + && UNAME_MACHINE=i686 + (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ + && UNAME_MACHINE=i686 + echo ${UNAME_MACHINE}-pc-sco$UNAME_REL + else + echo ${UNAME_MACHINE}-pc-sysv32 + fi + exit ;; + pc:*:*:*) + # Left here for compatibility: + # uname -m prints for DJGPP always 'pc', but it prints nothing about + # the processor, so we play safe by assuming i586. + # Note: whatever this is, it MUST be the same as what config.sub + # prints for the "djgpp" host, or else GDB configury will decide that + # this is a cross-build. + echo i586-pc-msdosdjgpp + exit ;; + Intel:Mach:3*:*) + echo i386-pc-mach3 + exit ;; + paragon:*:*:*) + echo i860-intel-osf1 + exit ;; + i860:*:4.*:*) # i860-SVR4 + if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then + echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 + else # Add other i860-SVR4 vendors below as they are discovered. + echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 + fi + exit ;; + mini*:CTIX:SYS*5:*) + # "miniframe" + echo m68010-convergent-sysv + exit ;; + mc68k:UNIX:SYSTEM5:3.51m) + echo m68k-convergent-sysv + exit ;; + M680?0:D-NIX:5.3:*) + echo m68k-diab-dnix + exit ;; + M68*:*:R3V[5678]*:*) + test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; + 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) + OS_REL='' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4; exit; } ;; + NCR*:*:4.2:* | MPRAS*:*:4.2:*) + OS_REL='.3' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) + echo m68k-unknown-lynxos${UNAME_RELEASE} + exit ;; + mc68030:UNIX_System_V:4.*:*) + echo m68k-atari-sysv4 + exit ;; + TSUNAMI:LynxOS:2.*:*) + echo sparc-unknown-lynxos${UNAME_RELEASE} + exit ;; + rs6000:LynxOS:2.*:*) + echo rs6000-unknown-lynxos${UNAME_RELEASE} + exit ;; + PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) + echo powerpc-unknown-lynxos${UNAME_RELEASE} + exit ;; + SM[BE]S:UNIX_SV:*:*) + echo mips-dde-sysv${UNAME_RELEASE} + exit ;; + RM*:ReliantUNIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + RM*:SINIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + *:SINIX-*:*:*) + if uname -p 2>/dev/null >/dev/null ; then + UNAME_MACHINE=`(uname -p) 2>/dev/null` + echo ${UNAME_MACHINE}-sni-sysv4 + else + echo ns32k-sni-sysv + fi + exit ;; + PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort + # says + echo i586-unisys-sysv4 + exit ;; + *:UNIX_System_V:4*:FTX*) + # From Gerald Hewes . + # How about differentiating between stratus architectures? -djm + echo hppa1.1-stratus-sysv4 + exit ;; + *:*:*:FTX*) + # From seanf@swdc.stratus.com. + echo i860-stratus-sysv4 + exit ;; + i*86:VOS:*:*) + # From Paul.Green@stratus.com. + echo ${UNAME_MACHINE}-stratus-vos + exit ;; + *:VOS:*:*) + # From Paul.Green@stratus.com. + echo hppa1.1-stratus-vos + exit ;; + mc68*:A/UX:*:*) + echo m68k-apple-aux${UNAME_RELEASE} + exit ;; + news*:NEWS-OS:6*:*) + echo mips-sony-newsos6 + exit ;; + R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) + if [ -d /usr/nec ]; then + echo mips-nec-sysv${UNAME_RELEASE} + else + echo mips-unknown-sysv${UNAME_RELEASE} + fi + exit ;; + BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. + echo powerpc-be-beos + exit ;; + BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. + echo powerpc-apple-beos + exit ;; + BePC:BeOS:*:*) # BeOS running on Intel PC compatible. + echo i586-pc-beos + exit ;; + BePC:Haiku:*:*) # Haiku running on Intel PC compatible. + echo i586-pc-haiku + exit ;; + SX-4:SUPER-UX:*:*) + echo sx4-nec-superux${UNAME_RELEASE} + exit ;; + SX-5:SUPER-UX:*:*) + echo sx5-nec-superux${UNAME_RELEASE} + exit ;; + SX-6:SUPER-UX:*:*) + echo sx6-nec-superux${UNAME_RELEASE} + exit ;; + SX-7:SUPER-UX:*:*) + echo sx7-nec-superux${UNAME_RELEASE} + exit ;; + SX-8:SUPER-UX:*:*) + echo sx8-nec-superux${UNAME_RELEASE} + exit ;; + SX-8R:SUPER-UX:*:*) + echo sx8r-nec-superux${UNAME_RELEASE} + exit ;; + Power*:Rhapsody:*:*) + echo powerpc-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Rhapsody:*:*) + echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Darwin:*:*) + UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown + case $UNAME_PROCESSOR in + i386) + eval $set_cc_for_build + if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then + if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + UNAME_PROCESSOR="x86_64" + fi + fi ;; + unknown) UNAME_PROCESSOR=powerpc ;; + esac + echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} + exit ;; + *:procnto*:*:* | *:QNX:[0123456789]*:*) + UNAME_PROCESSOR=`uname -p` + if test "$UNAME_PROCESSOR" = "x86"; then + UNAME_PROCESSOR=i386 + UNAME_MACHINE=pc + fi + echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} + exit ;; + *:QNX:*:4*) + echo i386-pc-qnx + exit ;; + NSE-?:NONSTOP_KERNEL:*:*) + echo nse-tandem-nsk${UNAME_RELEASE} + exit ;; + NSR-?:NONSTOP_KERNEL:*:*) + echo nsr-tandem-nsk${UNAME_RELEASE} + exit ;; + *:NonStop-UX:*:*) + echo mips-compaq-nonstopux + exit ;; + BS2000:POSIX*:*:*) + echo bs2000-siemens-sysv + exit ;; + DS/*:UNIX_System_V:*:*) + echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} + exit ;; + *:Plan9:*:*) + # "uname -m" is not consistent, so use $cputype instead. 386 + # is converted to i386 for consistency with other x86 + # operating systems. + if test "$cputype" = "386"; then + UNAME_MACHINE=i386 + else + UNAME_MACHINE="$cputype" + fi + echo ${UNAME_MACHINE}-unknown-plan9 + exit ;; + *:TOPS-10:*:*) + echo pdp10-unknown-tops10 + exit ;; + *:TENEX:*:*) + echo pdp10-unknown-tenex + exit ;; + KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) + echo pdp10-dec-tops20 + exit ;; + XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) + echo pdp10-xkl-tops20 + exit ;; + *:TOPS-20:*:*) + echo pdp10-unknown-tops20 + exit ;; + *:ITS:*:*) + echo pdp10-unknown-its + exit ;; + SEI:*:*:SEIUX) + echo mips-sei-seiux${UNAME_RELEASE} + exit ;; + *:DragonFly:*:*) + echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` + exit ;; + *:*VMS:*:*) + UNAME_MACHINE=`(uname -p) 2>/dev/null` + case "${UNAME_MACHINE}" in + A*) echo alpha-dec-vms ; exit ;; + I*) echo ia64-dec-vms ; exit ;; + V*) echo vax-dec-vms ; exit ;; + esac ;; + *:XENIX:*:SysV) + echo i386-pc-xenix + exit ;; + i*86:skyos:*:*) + echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' + exit ;; + i*86:rdos:*:*) + echo ${UNAME_MACHINE}-pc-rdos + exit ;; + i*86:AROS:*:*) + echo ${UNAME_MACHINE}-pc-aros + exit ;; +esac + +#echo '(No uname command or uname output not recognized.)' 1>&2 +#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 + +eval $set_cc_for_build +cat >$dummy.c < +# include +#endif +main () +{ +#if defined (sony) +#if defined (MIPSEB) + /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, + I don't know.... */ + printf ("mips-sony-bsd\n"); exit (0); +#else +#include + printf ("m68k-sony-newsos%s\n", +#ifdef NEWSOS4 + "4" +#else + "" +#endif + ); exit (0); +#endif +#endif + +#if defined (__arm) && defined (__acorn) && defined (__unix) + printf ("arm-acorn-riscix\n"); exit (0); +#endif + +#if defined (hp300) && !defined (hpux) + printf ("m68k-hp-bsd\n"); exit (0); +#endif + +#if defined (NeXT) +#if !defined (__ARCHITECTURE__) +#define __ARCHITECTURE__ "m68k" +#endif + int version; + version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; + if (version < 4) + printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); + else + printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); + exit (0); +#endif + +#if defined (MULTIMAX) || defined (n16) +#if defined (UMAXV) + printf ("ns32k-encore-sysv\n"); exit (0); +#else +#if defined (CMU) + printf ("ns32k-encore-mach\n"); exit (0); +#else + printf ("ns32k-encore-bsd\n"); exit (0); +#endif +#endif +#endif + +#if defined (__386BSD__) + printf ("i386-pc-bsd\n"); exit (0); +#endif + +#if defined (sequent) +#if defined (i386) + printf ("i386-sequent-dynix\n"); exit (0); +#endif +#if defined (ns32000) + printf ("ns32k-sequent-dynix\n"); exit (0); +#endif +#endif + +#if defined (_SEQUENT_) + struct utsname un; + + uname(&un); + + if (strncmp(un.version, "V2", 2) == 0) { + printf ("i386-sequent-ptx2\n"); exit (0); + } + if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ + printf ("i386-sequent-ptx1\n"); exit (0); + } + printf ("i386-sequent-ptx\n"); exit (0); + +#endif + +#if defined (vax) +# if !defined (ultrix) +# include +# if defined (BSD) +# if BSD == 43 + printf ("vax-dec-bsd4.3\n"); exit (0); +# else +# if BSD == 199006 + printf ("vax-dec-bsd4.3reno\n"); exit (0); +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# endif +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# else + printf ("vax-dec-ultrix\n"); exit (0); +# endif +#endif + +#if defined (alliant) && defined (i860) + printf ("i860-alliant-bsd\n"); exit (0); +#endif + + exit (1); +} +EOF + +$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } + +# Apollos put the system type in the environment. + +test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; } + +# Convex versions that predate uname can use getsysinfo(1) + +if [ -x /usr/convex/getsysinfo ] +then + case `getsysinfo -f cpu_type` in + c1*) + echo c1-convex-bsd + exit ;; + c2*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit ;; + c34*) + echo c34-convex-bsd + exit ;; + c38*) + echo c38-convex-bsd + exit ;; + c4*) + echo c4-convex-bsd + exit ;; + esac +fi + +cat >&2 < in order to provide the needed +information to handle your system. + +config.guess timestamp = $timestamp + +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null` + +hostinfo = `(hostinfo) 2>/dev/null` +/bin/universe = `(/bin/universe) 2>/dev/null` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` +/bin/arch = `(/bin/arch) 2>/dev/null` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` + +UNAME_MACHINE = ${UNAME_MACHINE} +UNAME_RELEASE = ${UNAME_RELEASE} +UNAME_SYSTEM = ${UNAME_SYSTEM} +UNAME_VERSION = ${UNAME_VERSION} +EOF + +exit 1 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/libclamav/c++/llvm/autoconf/config.sub b/libclamav/c++/llvm/autoconf/config.sub new file mode 100755 index 000000000..183976a06 --- /dev/null +++ b/libclamav/c++/llvm/autoconf/config.sub @@ -0,0 +1,1702 @@ +#! /bin/sh +# Configuration validation subroutine script. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 +# Free Software Foundation, Inc. + +timestamp='2009-08-19' + +# This file is (in principle) common to ALL GNU software. +# The presence of a machine in this file suggests that SOME GNU software +# can handle that machine. It does not imply ALL GNU software can. +# +# This file is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA +# 02110-1301, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + + +# Please send patches to . Submit a context +# diff and a properly formatted GNU ChangeLog entry. +# +# Configuration subroutine to validate and canonicalize a configuration type. +# Supply the specified configuration type as an argument. +# If it is invalid, we print an error message on stderr and exit with code 1. +# Otherwise, we print the canonical config type on stdout and succeed. + +# You can get the latest version of this script from: +# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD + +# This file is supposed to be the same for all GNU packages +# and recognize all the CPU types, system types and aliases +# that are meaningful with *any* GNU software. +# Each package is responsible for reporting which valid configurations +# it does not support. The user should be able to distinguish +# a failure to support a valid configuration from a meaningless +# configuration. + +# The goal of this file is to map all the various variations of a given +# machine specification into a single specification in the form: +# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM +# or in some cases, the newer four-part form: +# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM +# It is wrong to echo any other type of specification. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] CPU-MFR-OPSYS + $0 [OPTION] ALIAS + +Canonicalize a configuration name. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.sub ($timestamp) + +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, +2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" + exit 1 ;; + + *local*) + # First pass through any local machine types. + echo $1 + exit ;; + + * ) + break ;; + esac +done + +case $# in + 0) echo "$me: missing argument$help" >&2 + exit 1;; + 1) ;; + *) echo "$me: too many arguments$help" >&2 + exit 1;; +esac + +# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). +# Here we must recognize all the valid KERNEL-OS combinations. +maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` +case $maybe_os in + nto-qnx* | linux-gnu* | linux-dietlibc | linux-newlib* | linux-uclibc* | \ + uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | \ + kopensolaris*-gnu* | \ + storm-chaos* | os2-emx* | rtmk-nova*) + os=-$maybe_os + basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` + ;; + *) + basic_machine=`echo $1 | sed 's/-[^-]*$//'` + if [ $basic_machine != $1 ] + then os=`echo $1 | sed 's/.*-/-/'` + else os=; fi + ;; +esac + +### Let's recognize common machines as not being operating systems so +### that things like config.sub decstation-3100 work. We also +### recognize some manufacturers as not being operating systems, so we +### can provide default operating systems below. +case $os in + -sun*os*) + # Prevent following clause from handling this invalid input. + ;; + -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ + -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ + -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ + -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ + -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ + -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ + -apple | -axis | -knuth | -cray | -microblaze) + os= + basic_machine=$1 + ;; + -bluegene*) + os=-cnk + ;; + -sim | -cisco | -oki | -wec | -winbond) + os= + basic_machine=$1 + ;; + -scout) + ;; + -wrs) + os=-vxworks + basic_machine=$1 + ;; + -chorusos*) + os=-chorusos + basic_machine=$1 + ;; + -chorusrdb) + os=-chorusrdb + basic_machine=$1 + ;; + -hiux*) + os=-hiuxwe2 + ;; + -sco6) + os=-sco5v6 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco5) + os=-sco3.2v5 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco4) + os=-sco3.2v4 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2.[4-9]*) + os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2v[4-9]*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco5v6*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco*) + os=-sco3.2v2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -udk*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -isc) + os=-isc2.2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -clix*) + basic_machine=clipper-intergraph + ;; + -isc*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -lynx*) + os=-lynxos + ;; + -ptx*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` + ;; + -windowsnt*) + os=`echo $os | sed -e 's/windowsnt/winnt/'` + ;; + -psos*) + os=-psos + ;; + -mint | -mint[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; +esac + +# Decode aliases for certain CPU-COMPANY combinations. +case $basic_machine in + # Recognize the basic CPU types without company name. + # Some are omitted here because they have special meanings below. + 1750a | 580 \ + | a29k \ + | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ + | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ + | am33_2.0 \ + | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \ + | bfin \ + | c4x | clipper \ + | d10v | d30v | dlx | dsp16xx \ + | fido | fr30 | frv \ + | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ + | i370 | i860 | i960 | ia64 \ + | ip2k | iq2000 \ + | lm32 \ + | m32c | m32r | m32rle | m68000 | m68k | m88k \ + | maxq | mb | microblaze | mcore | mep | metag \ + | mips | mipsbe | mipseb | mipsel | mipsle \ + | mips16 \ + | mips64 | mips64el \ + | mips64octeon | mips64octeonel \ + | mips64orion | mips64orionel \ + | mips64r5900 | mips64r5900el \ + | mips64vr | mips64vrel \ + | mips64vr4100 | mips64vr4100el \ + | mips64vr4300 | mips64vr4300el \ + | mips64vr5000 | mips64vr5000el \ + | mips64vr5900 | mips64vr5900el \ + | mipsisa32 | mipsisa32el \ + | mipsisa32r2 | mipsisa32r2el \ + | mipsisa64 | mipsisa64el \ + | mipsisa64r2 | mipsisa64r2el \ + | mipsisa64sb1 | mipsisa64sb1el \ + | mipsisa64sr71k | mipsisa64sr71kel \ + | mipstx39 | mipstx39el \ + | mn10200 | mn10300 \ + | moxie \ + | mt \ + | msp430 \ + | nios | nios2 \ + | ns16k | ns32k \ + | or32 \ + | pdp10 | pdp11 | pj | pjl \ + | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \ + | pyramid \ + | score \ + | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ + | sh64 | sh64le \ + | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ + | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ + | spu | strongarm \ + | tahoe | thumb | tic4x | tic80 | tron \ + | v850 | v850e \ + | we32k \ + | x86 | xc16x | xscale | xscalee[bl] | xstormy16 | xtensa \ + | z8k | z80) + basic_machine=$basic_machine-unknown + ;; + m6811 | m68hc11 | m6812 | m68hc12) + # Motorola 68HC11/12. + basic_machine=$basic_machine-unknown + os=-none + ;; + m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) + ;; + ms1) + basic_machine=mt-unknown + ;; + + # We use `pc' rather than `unknown' + # because (1) that's what they normally are, and + # (2) the word "unknown" tends to confuse beginning users. + i*86 | x86_64) + basic_machine=$basic_machine-pc + ;; + # Object if more than one company name word. + *-*-*) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; + # Recognize the basic CPU types with company name. + 580-* \ + | a29k-* \ + | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ + | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ + | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ + | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ + | avr-* | avr32-* \ + | bfin-* | bs2000-* \ + | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \ + | clipper-* | craynv-* | cydra-* \ + | d10v-* | d30v-* | dlx-* \ + | elxsi-* \ + | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ + | h8300-* | h8500-* \ + | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ + | i*86-* | i860-* | i960-* | ia64-* \ + | ip2k-* | iq2000-* \ + | lm32-* \ + | m32c-* | m32r-* | m32rle-* \ + | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ + | m88110-* | m88k-* | maxq-* | mcore-* | metag-* | microblaze-* \ + | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ + | mips16-* \ + | mips64-* | mips64el-* \ + | mips64octeon-* | mips64octeonel-* \ + | mips64orion-* | mips64orionel-* \ + | mips64r5900-* | mips64r5900el-* \ + | mips64vr-* | mips64vrel-* \ + | mips64vr4100-* | mips64vr4100el-* \ + | mips64vr4300-* | mips64vr4300el-* \ + | mips64vr5000-* | mips64vr5000el-* \ + | mips64vr5900-* | mips64vr5900el-* \ + | mipsisa32-* | mipsisa32el-* \ + | mipsisa32r2-* | mipsisa32r2el-* \ + | mipsisa64-* | mipsisa64el-* \ + | mipsisa64r2-* | mipsisa64r2el-* \ + | mipsisa64sb1-* | mipsisa64sb1el-* \ + | mipsisa64sr71k-* | mipsisa64sr71kel-* \ + | mipstx39-* | mipstx39el-* \ + | mmix-* \ + | mt-* \ + | msp430-* \ + | nios-* | nios2-* \ + | none-* | np1-* | ns16k-* | ns32k-* \ + | orion-* \ + | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ + | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \ + | pyramid-* \ + | romp-* | rs6000-* \ + | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ + | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ + | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ + | sparclite-* \ + | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | strongarm-* | sv1-* | sx?-* \ + | tahoe-* | thumb-* \ + | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* | tile-* \ + | tron-* \ + | v850-* | v850e-* | vax-* \ + | we32k-* \ + | x86-* | x86_64-* | xc16x-* | xps100-* | xscale-* | xscalee[bl]-* \ + | xstormy16-* | xtensa*-* \ + | ymp-* \ + | z8k-* | z80-*) + ;; + # Recognize the basic CPU types without company name, with glob match. + xtensa*) + basic_machine=$basic_machine-unknown + ;; + # Recognize the various machine names and aliases which stand + # for a CPU type and a company and sometimes even an OS. + 386bsd) + basic_machine=i386-unknown + os=-bsd + ;; + 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) + basic_machine=m68000-att + ;; + 3b*) + basic_machine=we32k-att + ;; + a29khif) + basic_machine=a29k-amd + os=-udi + ;; + abacus) + basic_machine=abacus-unknown + ;; + adobe68k) + basic_machine=m68010-adobe + os=-scout + ;; + alliant | fx80) + basic_machine=fx80-alliant + ;; + altos | altos3068) + basic_machine=m68k-altos + ;; + am29k) + basic_machine=a29k-none + os=-bsd + ;; + amd64) + basic_machine=x86_64-pc + ;; + amd64-*) + basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + amdahl) + basic_machine=580-amdahl + os=-sysv + ;; + amiga | amiga-*) + basic_machine=m68k-unknown + ;; + amigaos | amigados) + basic_machine=m68k-unknown + os=-amigaos + ;; + amigaunix | amix) + basic_machine=m68k-unknown + os=-sysv4 + ;; + apollo68) + basic_machine=m68k-apollo + os=-sysv + ;; + apollo68bsd) + basic_machine=m68k-apollo + os=-bsd + ;; + aros) + basic_machine=i386-pc + os=-aros + ;; + aux) + basic_machine=m68k-apple + os=-aux + ;; + balance) + basic_machine=ns32k-sequent + os=-dynix + ;; + blackfin) + basic_machine=bfin-unknown + os=-linux + ;; + blackfin-*) + basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + bluegene*) + basic_machine=powerpc-ibm + os=-cnk + ;; + c90) + basic_machine=c90-cray + os=-unicos + ;; + cegcc) + basic_machine=arm-unknown + os=-cegcc + ;; + convex-c1) + basic_machine=c1-convex + os=-bsd + ;; + convex-c2) + basic_machine=c2-convex + os=-bsd + ;; + convex-c32) + basic_machine=c32-convex + os=-bsd + ;; + convex-c34) + basic_machine=c34-convex + os=-bsd + ;; + convex-c38) + basic_machine=c38-convex + os=-bsd + ;; + cray | j90) + basic_machine=j90-cray + os=-unicos + ;; + craynv) + basic_machine=craynv-cray + os=-unicosmp + ;; + cr16) + basic_machine=cr16-unknown + os=-elf + ;; + crds | unos) + basic_machine=m68k-crds + ;; + crisv32 | crisv32-* | etraxfs*) + basic_machine=crisv32-axis + ;; + cris | cris-* | etrax*) + basic_machine=cris-axis + ;; + crx) + basic_machine=crx-unknown + os=-elf + ;; + da30 | da30-*) + basic_machine=m68k-da30 + ;; + decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) + basic_machine=mips-dec + ;; + decsystem10* | dec10*) + basic_machine=pdp10-dec + os=-tops10 + ;; + decsystem20* | dec20*) + basic_machine=pdp10-dec + os=-tops20 + ;; + delta | 3300 | motorola-3300 | motorola-delta \ + | 3300-motorola | delta-motorola) + basic_machine=m68k-motorola + ;; + delta88) + basic_machine=m88k-motorola + os=-sysv3 + ;; + dicos) + basic_machine=i686-pc + os=-dicos + ;; + djgpp) + basic_machine=i586-pc + os=-msdosdjgpp + ;; + dpx20 | dpx20-*) + basic_machine=rs6000-bull + os=-bosx + ;; + dpx2* | dpx2*-bull) + basic_machine=m68k-bull + os=-sysv3 + ;; + ebmon29k) + basic_machine=a29k-amd + os=-ebmon + ;; + elxsi) + basic_machine=elxsi-elxsi + os=-bsd + ;; + encore | umax | mmax) + basic_machine=ns32k-encore + ;; + es1800 | OSE68k | ose68k | ose | OSE) + basic_machine=m68k-ericsson + os=-ose + ;; + fx2800) + basic_machine=i860-alliant + ;; + genix) + basic_machine=ns32k-ns + ;; + gmicro) + basic_machine=tron-gmicro + os=-sysv + ;; + go32) + basic_machine=i386-pc + os=-go32 + ;; + h3050r* | hiux*) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + h8300hms) + basic_machine=h8300-hitachi + os=-hms + ;; + h8300xray) + basic_machine=h8300-hitachi + os=-xray + ;; + h8500hms) + basic_machine=h8500-hitachi + os=-hms + ;; + harris) + basic_machine=m88k-harris + os=-sysv3 + ;; + hp300-*) + basic_machine=m68k-hp + ;; + hp300bsd) + basic_machine=m68k-hp + os=-bsd + ;; + hp300hpux) + basic_machine=m68k-hp + os=-hpux + ;; + hp3k9[0-9][0-9] | hp9[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k2[0-9][0-9] | hp9k31[0-9]) + basic_machine=m68000-hp + ;; + hp9k3[2-9][0-9]) + basic_machine=m68k-hp + ;; + hp9k6[0-9][0-9] | hp6[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k7[0-79][0-9] | hp7[0-79][0-9]) + basic_machine=hppa1.1-hp + ;; + hp9k78[0-9] | hp78[0-9]) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][13679] | hp8[0-9][13679]) + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][0-9] | hp8[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hppa-next) + os=-nextstep3 + ;; + hppaosf) + basic_machine=hppa1.1-hp + os=-osf + ;; + hppro) + basic_machine=hppa1.1-hp + os=-proelf + ;; + i370-ibm* | ibm*) + basic_machine=i370-ibm + ;; +# I'm not sure what "Sysv32" means. Should this be sysv3.2? + i*86v32) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv32 + ;; + i*86v4*) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv4 + ;; + i*86v) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv + ;; + i*86sol2) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-solaris2 + ;; + i386mach) + basic_machine=i386-mach + os=-mach + ;; + i386-vsta | vsta) + basic_machine=i386-unknown + os=-vsta + ;; + iris | iris4d) + basic_machine=mips-sgi + case $os in + -irix*) + ;; + *) + os=-irix4 + ;; + esac + ;; + isi68 | isi) + basic_machine=m68k-isi + os=-sysv + ;; + m68knommu) + basic_machine=m68k-unknown + os=-linux + ;; + m68knommu-*) + basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + m88k-omron*) + basic_machine=m88k-omron + ;; + magnum | m3230) + basic_machine=mips-mips + os=-sysv + ;; + merlin) + basic_machine=ns32k-utek + os=-sysv + ;; + microblaze) + basic_machine=microblaze-xilinx + ;; + mingw32) + basic_machine=i386-pc + os=-mingw32 + ;; + mingw32ce) + basic_machine=arm-unknown + os=-mingw32ce + ;; + miniframe) + basic_machine=m68000-convergent + ;; + *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; + mips3*-*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` + ;; + mips3*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown + ;; + monitor) + basic_machine=m68k-rom68k + os=-coff + ;; + morphos) + basic_machine=powerpc-unknown + os=-morphos + ;; + msdos) + basic_machine=i386-pc + os=-msdos + ;; + ms1-*) + basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` + ;; + mvs) + basic_machine=i370-ibm + os=-mvs + ;; + ncr3000) + basic_machine=i486-ncr + os=-sysv4 + ;; + netbsd386) + basic_machine=i386-unknown + os=-netbsd + ;; + netwinder) + basic_machine=armv4l-rebel + os=-linux + ;; + news | news700 | news800 | news900) + basic_machine=m68k-sony + os=-newsos + ;; + news1000) + basic_machine=m68030-sony + os=-newsos + ;; + news-3600 | risc-news) + basic_machine=mips-sony + os=-newsos + ;; + necv70) + basic_machine=v70-nec + os=-sysv + ;; + next | m*-next ) + basic_machine=m68k-next + case $os in + -nextstep* ) + ;; + -ns2*) + os=-nextstep2 + ;; + *) + os=-nextstep3 + ;; + esac + ;; + nh3000) + basic_machine=m68k-harris + os=-cxux + ;; + nh[45]000) + basic_machine=m88k-harris + os=-cxux + ;; + nindy960) + basic_machine=i960-intel + os=-nindy + ;; + mon960) + basic_machine=i960-intel + os=-mon960 + ;; + nonstopux) + basic_machine=mips-compaq + os=-nonstopux + ;; + np1) + basic_machine=np1-gould + ;; + nsr-tandem) + basic_machine=nsr-tandem + ;; + op50n-* | op60c-*) + basic_machine=hppa1.1-oki + os=-proelf + ;; + openrisc | openrisc-*) + basic_machine=or32-unknown + ;; + os400) + basic_machine=powerpc-ibm + os=-os400 + ;; + OSE68000 | ose68000) + basic_machine=m68000-ericsson + os=-ose + ;; + os68k) + basic_machine=m68k-none + os=-os68k + ;; + pa-hitachi) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + paragon) + basic_machine=i860-intel + os=-osf + ;; + parisc) + basic_machine=hppa-unknown + os=-linux + ;; + parisc-*) + basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + pbd) + basic_machine=sparc-tti + ;; + pbb) + basic_machine=m68k-tti + ;; + pc532 | pc532-*) + basic_machine=ns32k-pc532 + ;; + pc98) + basic_machine=i386-pc + ;; + pc98-*) + basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium | p5 | k5 | k6 | nexgen | viac3) + basic_machine=i586-pc + ;; + pentiumpro | p6 | 6x86 | athlon | athlon_*) + basic_machine=i686-pc + ;; + pentiumii | pentium2 | pentiumiii | pentium3) + basic_machine=i686-pc + ;; + pentium4) + basic_machine=i786-pc + ;; + pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) + basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumpro-* | p6-* | 6x86-* | athlon-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium4-*) + basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pn) + basic_machine=pn-gould + ;; + power) basic_machine=power-ibm + ;; + ppc) basic_machine=powerpc-unknown + ;; + ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppcle | powerpclittle | ppc-le | powerpc-little) + basic_machine=powerpcle-unknown + ;; + ppcle-* | powerpclittle-*) + basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64) basic_machine=powerpc64-unknown + ;; + ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64le | powerpc64little | ppc64-le | powerpc64-little) + basic_machine=powerpc64le-unknown + ;; + ppc64le-* | powerpc64little-*) + basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ps2) + basic_machine=i386-ibm + ;; + pw32) + basic_machine=i586-unknown + os=-pw32 + ;; + rdos) + basic_machine=i386-pc + os=-rdos + ;; + rom68k) + basic_machine=m68k-rom68k + os=-coff + ;; + rm[46]00) + basic_machine=mips-siemens + ;; + rtpc | rtpc-*) + basic_machine=romp-ibm + ;; + s390 | s390-*) + basic_machine=s390-ibm + ;; + s390x | s390x-*) + basic_machine=s390x-ibm + ;; + sa29200) + basic_machine=a29k-amd + os=-udi + ;; + sb1) + basic_machine=mipsisa64sb1-unknown + ;; + sb1el) + basic_machine=mipsisa64sb1el-unknown + ;; + sde) + basic_machine=mipsisa32-sde + os=-elf + ;; + sei) + basic_machine=mips-sei + os=-seiux + ;; + sequent) + basic_machine=i386-sequent + ;; + sh) + basic_machine=sh-hitachi + os=-hms + ;; + sh5el) + basic_machine=sh5le-unknown + ;; + sh64) + basic_machine=sh64-unknown + ;; + sparclite-wrs | simso-wrs) + basic_machine=sparclite-wrs + os=-vxworks + ;; + sps7) + basic_machine=m68k-bull + os=-sysv2 + ;; + spur) + basic_machine=spur-unknown + ;; + st2000) + basic_machine=m68k-tandem + ;; + stratus) + basic_machine=i860-stratus + os=-sysv4 + ;; + sun2) + basic_machine=m68000-sun + ;; + sun2os3) + basic_machine=m68000-sun + os=-sunos3 + ;; + sun2os4) + basic_machine=m68000-sun + os=-sunos4 + ;; + sun3os3) + basic_machine=m68k-sun + os=-sunos3 + ;; + sun3os4) + basic_machine=m68k-sun + os=-sunos4 + ;; + sun4os3) + basic_machine=sparc-sun + os=-sunos3 + ;; + sun4os4) + basic_machine=sparc-sun + os=-sunos4 + ;; + sun4sol2) + basic_machine=sparc-sun + os=-solaris2 + ;; + sun3 | sun3-*) + basic_machine=m68k-sun + ;; + sun4) + basic_machine=sparc-sun + ;; + sun386 | sun386i | roadrunner) + basic_machine=i386-sun + ;; + sv1) + basic_machine=sv1-cray + os=-unicos + ;; + symmetry) + basic_machine=i386-sequent + os=-dynix + ;; + t3e) + basic_machine=alphaev5-cray + os=-unicos + ;; + t90) + basic_machine=t90-cray + os=-unicos + ;; + tic54x | c54x*) + basic_machine=tic54x-unknown + os=-coff + ;; + tic55x | c55x*) + basic_machine=tic55x-unknown + os=-coff + ;; + tic6x | c6x*) + basic_machine=tic6x-unknown + os=-coff + ;; + tile*) + basic_machine=tile-unknown + os=-linux-gnu + ;; + tx39) + basic_machine=mipstx39-unknown + ;; + tx39el) + basic_machine=mipstx39el-unknown + ;; + toad1) + basic_machine=pdp10-xkl + os=-tops20 + ;; + tower | tower-32) + basic_machine=m68k-ncr + ;; + tpf) + basic_machine=s390x-ibm + os=-tpf + ;; + udi29k) + basic_machine=a29k-amd + os=-udi + ;; + ultra3) + basic_machine=a29k-nyu + os=-sym1 + ;; + v810 | necv810) + basic_machine=v810-nec + os=-none + ;; + vaxv) + basic_machine=vax-dec + os=-sysv + ;; + vms) + basic_machine=vax-dec + os=-vms + ;; + vpp*|vx|vx-*) + basic_machine=f301-fujitsu + ;; + vxworks960) + basic_machine=i960-wrs + os=-vxworks + ;; + vxworks68) + basic_machine=m68k-wrs + os=-vxworks + ;; + vxworks29k) + basic_machine=a29k-wrs + os=-vxworks + ;; + w65*) + basic_machine=w65-wdc + os=-none + ;; + w89k-*) + basic_machine=hppa1.1-winbond + os=-proelf + ;; + xbox) + basic_machine=i686-pc + os=-mingw32 + ;; + xps | xps100) + basic_machine=xps100-honeywell + ;; + ymp) + basic_machine=ymp-cray + os=-unicos + ;; + z8k-*-coff) + basic_machine=z8k-unknown + os=-sim + ;; + z80-*-coff) + basic_machine=z80-unknown + os=-sim + ;; + none) + basic_machine=none-none + os=-none + ;; + +# Here we handle the default manufacturer of certain CPU types. It is in +# some cases the only manufacturer, in others, it is the most popular. + w89k) + basic_machine=hppa1.1-winbond + ;; + op50n) + basic_machine=hppa1.1-oki + ;; + op60c) + basic_machine=hppa1.1-oki + ;; + romp) + basic_machine=romp-ibm + ;; + mmix) + basic_machine=mmix-knuth + ;; + rs6000) + basic_machine=rs6000-ibm + ;; + vax) + basic_machine=vax-dec + ;; + pdp10) + # there are many clones, so DEC is not a safe bet + basic_machine=pdp10-unknown + ;; + pdp11) + basic_machine=pdp11-dec + ;; + we32k) + basic_machine=we32k-att + ;; + sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) + basic_machine=sh-unknown + ;; + sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) + basic_machine=sparc-sun + ;; + cydra) + basic_machine=cydra-cydrome + ;; + orion) + basic_machine=orion-highlevel + ;; + orion105) + basic_machine=clipper-highlevel + ;; + mac | mpw | mac-mpw) + basic_machine=m68k-apple + ;; + pmac | pmac-mpw) + basic_machine=powerpc-apple + ;; + *-unknown) + # Make sure to match an already-canonicalized machine name. + ;; + *) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; +esac + +# Here we canonicalize certain aliases for manufacturers. +case $basic_machine in + *-digital*) + basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` + ;; + *-commodore*) + basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` + ;; + *) + ;; +esac + +# Decode manufacturer-specific aliases for certain operating systems. + +if [ x"$os" != x"" ] +then +case $os in + # First match some system type aliases + # that might get confused with valid system types. + # -solaris* is a basic system type, with this one exception. + -solaris1 | -solaris1.*) + os=`echo $os | sed -e 's|solaris1|sunos4|'` + ;; + -auroraux) + os=-auroraux + ;; + -solaris) + os=-solaris2 + ;; + -svr4*) + os=-sysv4 + ;; + -unixware*) + os=-sysv4.2uw + ;; + -gnu/linux*) + os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` + ;; + # First accept the basic system types. + # The portable systems comes first. + # Each alternative MUST END IN A *, to match a version number. + # -sysv* is not here because it comes later, after sysvr4. + -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ + | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ + | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* | -sym* \ + | -kopensolaris* \ + | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ + | -aos* | -aros* \ + | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ + | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ + | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ + | -openbsd* | -solidbsd* \ + | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ + | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ + | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ + | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ + | -chorusos* | -chorusrdb* | -cegcc* \ + | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ + | -mingw32* | -linux-gnu* | -linux-newlib* | -linux-uclibc* \ + | -uxpv* | -beos* | -mpeix* | -udk* \ + | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ + | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ + | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ + | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ + | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ + | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ + | -skyos* | -haiku* | -rdos* | -toppers* | -drops*) + # Remember, each alternative MUST END IN *, to match a version number. + ;; + -qnx*) + case $basic_machine in + x86-* | i*86-*) + ;; + *) + os=-nto$os + ;; + esac + ;; + -nto-qnx*) + ;; + -nto*) + os=`echo $os | sed -e 's|nto|nto-qnx|'` + ;; + -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ + | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ + | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) + ;; + -mac*) + os=`echo $os | sed -e 's|mac|macos|'` + ;; + -linux-dietlibc) + os=-linux-dietlibc + ;; + -linux*) + os=`echo $os | sed -e 's|linux|linux-gnu|'` + ;; + -sunos5*) + os=`echo $os | sed -e 's|sunos5|solaris2|'` + ;; + -sunos6*) + os=`echo $os | sed -e 's|sunos6|solaris3|'` + ;; + -opened*) + os=-openedition + ;; + -os400*) + os=-os400 + ;; + -wince*) + os=-wince + ;; + -osfrose*) + os=-osfrose + ;; + -osf*) + os=-osf + ;; + -utek*) + os=-bsd + ;; + -dynix*) + os=-bsd + ;; + -acis*) + os=-aos + ;; + -atheos*) + os=-atheos + ;; + -syllable*) + os=-syllable + ;; + -386bsd) + os=-bsd + ;; + -ctix* | -uts*) + os=-sysv + ;; + -nova*) + os=-rtmk-nova + ;; + -ns2 ) + os=-nextstep2 + ;; + -nsk*) + os=-nsk + ;; + # Preserve the version number of sinix5. + -sinix5.*) + os=`echo $os | sed -e 's|sinix|sysv|'` + ;; + -sinix*) + os=-sysv4 + ;; + -tpf*) + os=-tpf + ;; + -triton*) + os=-sysv3 + ;; + -oss*) + os=-sysv3 + ;; + -svr4) + os=-sysv4 + ;; + -svr3) + os=-sysv3 + ;; + -sysvr4) + os=-sysv4 + ;; + # This must come after -sysvr4. + -sysv*) + ;; + -ose*) + os=-ose + ;; + -es1800*) + os=-ose + ;; + -xenix) + os=-xenix + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + os=-mint + ;; + -aros*) + os=-aros + ;; + -kaos*) + os=-kaos + ;; + -zvmoe) + os=-zvmoe + ;; + -dicos*) + os=-dicos + ;; + -none) + ;; + *) + # Get rid of the `-' at the beginning of $os. + os=`echo $os | sed 's/[^-]*-//'` + echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 + exit 1 + ;; +esac +else + +# Here we handle the default operating systems that come with various machines. +# The value should be what the vendor currently ships out the door with their +# machine or put another way, the most popular os provided with the machine. + +# Note that if you're going to try to match "-MANUFACTURER" here (say, +# "-sun"), then you have to tell the case statement up towards the top +# that MANUFACTURER isn't an operating system. Otherwise, code above +# will signal an error saying that MANUFACTURER isn't an operating +# system, and we'll never get to this point. + +case $basic_machine in + score-*) + os=-elf + ;; + spu-*) + os=-elf + ;; + *-acorn) + os=-riscix1.2 + ;; + arm*-rebel) + os=-linux + ;; + arm*-semi) + os=-aout + ;; + c4x-* | tic4x-*) + os=-coff + ;; + # This must come before the *-dec entry. + pdp10-*) + os=-tops20 + ;; + pdp11-*) + os=-none + ;; + *-dec | vax-*) + os=-ultrix4.2 + ;; + m68*-apollo) + os=-domain + ;; + i386-sun) + os=-sunos4.0.2 + ;; + m68000-sun) + os=-sunos3 + # This also exists in the configure program, but was not the + # default. + # os=-sunos4 + ;; + m68*-cisco) + os=-aout + ;; + mep-*) + os=-elf + ;; + mips*-cisco) + os=-elf + ;; + mips*-*) + os=-elf + ;; + or32-*) + os=-coff + ;; + *-tti) # must be before sparc entry or we get the wrong os. + os=-sysv3 + ;; + sparc-* | *-sun) + os=-sunos4.1.1 + ;; + *-be) + os=-beos + ;; + *-haiku) + os=-haiku + ;; + *-ibm) + os=-aix + ;; + *-knuth) + os=-mmixware + ;; + *-wec) + os=-proelf + ;; + *-winbond) + os=-proelf + ;; + *-oki) + os=-proelf + ;; + *-hp) + os=-hpux + ;; + *-hitachi) + os=-hiux + ;; + i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) + os=-sysv + ;; + *-cbm) + os=-amigaos + ;; + *-dg) + os=-dgux + ;; + *-dolphin) + os=-sysv3 + ;; + m68k-ccur) + os=-rtu + ;; + m88k-omron*) + os=-luna + ;; + *-next ) + os=-nextstep + ;; + *-sequent) + os=-ptx + ;; + *-crds) + os=-unos + ;; + *-ns) + os=-genix + ;; + i370-*) + os=-mvs + ;; + *-next) + os=-nextstep3 + ;; + *-gould) + os=-sysv + ;; + *-highlevel) + os=-bsd + ;; + *-encore) + os=-bsd + ;; + *-sgi) + os=-irix + ;; + *-siemens) + os=-sysv4 + ;; + *-masscomp) + os=-rtu + ;; + f30[01]-fujitsu | f700-fujitsu) + os=-uxpv + ;; + *-rom68k) + os=-coff + ;; + *-*bug) + os=-coff + ;; + *-apple) + os=-macos + ;; + *-atari*) + os=-mint + ;; + *) + os=-none + ;; +esac +fi + +# Here we handle the case where we know the os, and the CPU type, but not the +# manufacturer. We pick the logical manufacturer. +vendor=unknown +case $basic_machine in + *-unknown) + case $os in + -riscix*) + vendor=acorn + ;; + -sunos*) + vendor=sun + ;; + -cnk*|-aix*) + vendor=ibm + ;; + -beos*) + vendor=be + ;; + -hpux*) + vendor=hp + ;; + -mpeix*) + vendor=hp + ;; + -hiux*) + vendor=hitachi + ;; + -unos*) + vendor=crds + ;; + -dgux*) + vendor=dg + ;; + -luna*) + vendor=omron + ;; + -genix*) + vendor=ns + ;; + -mvs* | -opened*) + vendor=ibm + ;; + -os400*) + vendor=ibm + ;; + -ptx*) + vendor=sequent + ;; + -tpf*) + vendor=ibm + ;; + -vxsim* | -vxworks* | -windiss*) + vendor=wrs + ;; + -aux*) + vendor=apple + ;; + -hms*) + vendor=hitachi + ;; + -mpw* | -macos*) + vendor=apple + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + vendor=atari + ;; + -vos*) + vendor=stratus + ;; + esac + basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` + ;; +esac + +echo $basic_machine$os +exit + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/libclamav/c++/llvm/autoconf/configure.ac b/libclamav/c++/llvm/autoconf/configure.ac new file mode 100644 index 000000000..951969846 --- /dev/null +++ b/libclamav/c++/llvm/autoconf/configure.ac @@ -0,0 +1,1450 @@ +dnl === configure.ac --------------------------------------------------------=== +dnl The LLVM Compiler Infrastructure +dnl +dnl This file is distributed under the University of Illinois Open Source +dnl License. See LICENSE.TXT for details. +dnl +dnl===-----------------------------------------------------------------------=== +dnl This is the LLVM configuration script. It is processed by the autoconf +dnl program to produce a script named configure. This script contains the +dnl configuration checks that LLVM needs in order to support multiple platforms. +dnl This file is composed of 10 sections per the recommended organization of +dnl autoconf input defined in the autoconf documentation. As this file evolves, +dnl please keep the various types of checks within their sections. The sections +dnl are as follows: +dnl +dnl SECTION 1: Initialization & Setup +dnl SECTION 2: Architecture, target, and host checks +dnl SECTION 3: Command line arguments for the configure script. +dnl SECTION 4: Check for programs we need and that they are the right version +dnl SECTION 5: Check for libraries +dnl SECTION 6: Check for header files +dnl SECTION 7: Check for types and structures +dnl SECTION 8: Check for specific functions needed +dnl SECTION 9: Additional checks, variables, etc. +dnl SECTION 10: Specify the output files and generate it +dnl +dnl===-----------------------------------------------------------------------=== +dnl=== +dnl=== SECTION 1: Initialization & Setup +dnl=== +dnl===-----------------------------------------------------------------------=== +dnl Initialize autoconf and define the package name, version number and +dnl email address for reporting bugs. +AC_INIT([[llvm]],[[2.7svn]],[llvmbugs@cs.uiuc.edu]) + +dnl Provide a copyright substitution and ensure the copyright notice is included +dnl in the output of --version option of the generated configure script. +AC_SUBST(LLVM_COPYRIGHT,["Copyright (c) 2003-2009 University of Illinois at Urbana-Champaign."]) +AC_COPYRIGHT([Copyright (c) 2003-2009 University of Illinois at Urbana-Champaign.]) + +dnl Indicate that we require autoconf 2.59 or later. Ths is needed because we +dnl use some autoconf macros only available in 2.59. +AC_PREREQ(2.59) + +dnl Verify that the source directory is valid. This makes sure that we are +dnl configuring LLVM and not some other package (it validates --srcdir argument) +AC_CONFIG_SRCDIR([lib/VMCore/Module.cpp]) + +dnl Place all of the extra autoconf files into the config subdirectory. Tell +dnl various tools where the m4 autoconf macros are. +AC_CONFIG_AUX_DIR([autoconf]) + +dnl Quit if the source directory has already been configured. +dnl NOTE: This relies upon undocumented autoconf behavior. +if test ${srcdir} != "." ; then + if test -f ${srcdir}/include/llvm/Config/config.h ; then + AC_MSG_ERROR([Already configured in ${srcdir}]) + fi +fi + +dnl Configure all of the projects present in our source tree. While we could +dnl just AC_CONFIG_SUBDIRS on the set of directories in projects that have a +dnl configure script, that usage of the AC_CONFIG_SUBDIRS macro is deprecated. +dnl Instead we match on the known projects. +for i in `ls ${srcdir}/projects` +do + if test -d ${srcdir}/projects/${i} ; then + case ${i} in + CVS) ;; + sample) AC_CONFIG_SUBDIRS([projects/sample]) ;; + privbracket) AC_CONFIG_SUBDIRS([projects/privbracket]) ;; + llvm-stacker) AC_CONFIG_SUBDIRS([projects/llvm-stacker]) ;; + # llvm-test is the old name of the test-suite, kept here for backwards + # compatibility + llvm-test) AC_CONFIG_SUBDIRS([projects/llvm-test]) ;; + test-suite) AC_CONFIG_SUBDIRS([projects/test-suite]) ;; + llvm-reopt) AC_CONFIG_SUBDIRS([projects/llvm-reopt]);; + llvm-gcc) AC_CONFIG_SUBDIRS([projects/llvm-gcc]) ;; + llvm-java) AC_CONFIG_SUBDIRS([projects/llvm-java]) ;; + llvm-tv) AC_CONFIG_SUBDIRS([projects/llvm-tv]) ;; + llvm-poolalloc) AC_CONFIG_SUBDIRS([projects/llvm-poolalloc]) ;; + poolalloc) AC_CONFIG_SUBDIRS([projects/poolalloc]) ;; + llvm-kernel) AC_CONFIG_SUBDIRS([projects/llvm-kernel]) ;; + *) + AC_MSG_WARN([Unknown project (${i}) won't be configured automatically]) + ;; + esac + fi +done + +dnl===-----------------------------------------------------------------------=== +dnl=== +dnl=== SECTION 2: Architecture, target, and host checks +dnl=== +dnl===-----------------------------------------------------------------------=== + +dnl Check the target for which we're compiling and the host that will do the +dnl compilations. This will tell us which LLVM compiler will be used for +dnl compiling SSA into object code. This needs to be done early because +dnl following tests depend on it. +AC_CANONICAL_TARGET + +dnl Determine the platform type and cache its value. This helps us configure +dnl the System library to the correct build platform. +AC_CACHE_CHECK([type of operating system we're going to host on], + [llvm_cv_os_type], +[case $host in + *-*-aix*) + llvm_cv_link_all_option="-Wl,--whole-archive" + llvm_cv_no_link_all_option="-Wl,--no-whole-archive" + llvm_cv_os_type="AIX" + llvm_cv_platform_type="Unix" ;; + *-*-irix*) + llvm_cv_link_all_option="-Wl,--whole-archive" + llvm_cv_no_link_all_option="-Wl,--no-whole-archive" + llvm_cv_os_type="IRIX" + llvm_cv_platform_type="Unix" ;; + *-*-cygwin*) + llvm_cv_link_all_option="-Wl,--whole-archive" + llvm_cv_no_link_all_option="-Wl,--no-whole-archive" + llvm_cv_os_type="Cygwin" + llvm_cv_platform_type="Unix" ;; + *-*-darwin*) + llvm_cv_link_all_option="-Wl,-all_load" + llvm_cv_no_link_all_option="-Wl,-noall_load" + llvm_cv_os_type="Darwin" + llvm_cv_platform_type="Unix" ;; + *-*-freebsd*) + llvm_cv_link_all_option="-Wl,--whole-archive" + llvm_cv_no_link_all_option="-Wl,--no-whole-archive" + llvm_cv_os_type="FreeBSD" + llvm_cv_platform_type="Unix" ;; + *-*-openbsd*) + llvm_cv_link_all_option="-Wl,--whole-archive" + llvm_cv_no_link_all_option="-Wl,--no-whole-archive" + llvm_cv_os_type="OpenBSD" + llvm_cv_platform_type="Unix" ;; + *-*-netbsd*) + llvm_cv_link_all_option="-Wl,--whole-archive" + llvm_cv_no_link_all_option="-Wl,--no-whole-archive" + llvm_cv_os_type="NetBSD" + llvm_cv_platform_type="Unix" ;; + *-*-dragonfly*) + llvm_cv_link_all_option="-Wl,--whole-archive" + llvm_cv_no_link_all_option="-Wl,--no-whole-archive" + llvm_cv_os_type="DragonFly" + llvm_cv_platform_type="Unix" ;; + *-*-hpux*) + llvm_cv_link_all_option="-Wl,--whole-archive" + llvm_cv_no_link_all_option="-Wl,--no-whole-archive" + llvm_cv_os_type="HP-UX" + llvm_cv_platform_type="Unix" ;; + *-*-interix*) + llvm_cv_link_all_option="-Wl,--whole-archive" + llvm_cv_no_link_all_option="-Wl,--no-whole-archive" + llvm_cv_os_type="Interix" + llvm_cv_platform_type="Unix" ;; + *-*-linux*) + llvm_cv_link_all_option="-Wl,--whole-archive" + llvm_cv_no_link_all_option="-Wl,--no-whole-archive" + llvm_cv_os_type="Linux" + llvm_cv_platform_type="Unix" ;; + *-*-solaris*) + llvm_cv_link_all_option="-Wl,-z,allextract" + llvm_cv_no_link_all_option="-Wl,-z,defaultextract" + llvm_cv_os_type="SunOS" + llvm_cv_platform_type="Unix" ;; + *-*-auroraux*) + llvm_cv_link_all_option="-Wl,-z,allextract" + llvm_cv_link_all_option="-Wl,-z,defaultextract" + llvm_cv_os_type="AuroraUX" + llvm_cv_platform_type="Unix" ;; + *-*-win32*) + llvm_cv_link_all_option="-Wl,--whole-archive" + llvm_cv_no_link_all_option="-Wl,--no-whole-archive" + llvm_cv_os_type="Win32" + llvm_cv_platform_type="Win32" ;; + *-*-mingw*) + llvm_cv_link_all_option="-Wl,--whole-archive" + llvm_cv_no_link_all_option="-Wl,--no-whole-archive" + llvm_cv_os_type="MingW" + llvm_cv_platform_type="Win32" ;; + *-*-haiku*) + llvm_cv_link_all_option="-Wl,--whole-archive" + llvm_cv_no_link_all_option="-Wl,--no-whole-archive" + llvm_cv_os_type="Haiku" + llvm_cv_platform_type="Unix" ;; + *-unknown-eabi*) + llvm_cv_link_all_option="-Wl,--whole-archive" + llvm_cv_no_link_all_option="-Wl,--no-whole-archive" + llvm_cv_os_type="Freestanding" + llvm_cv_platform_type="Unix" ;; + *-unknown-elf*) + llvm_cv_link_all_option="-Wl,--whole-archive" + llvm_cv_no_link_all_option="-Wl,--no-whole-archive" + llvm_cv_os_type="Freestanding" + llvm_cv_platform_type="Unix" ;; + *) + llvm_cv_link_all_option="" + llvm_cv_no_link_all_option="" + llvm_cv_os_type="Unknown" + llvm_cv_platform_type="Unknown" ;; +esac]) + +AC_CACHE_CHECK([type of operating system we're going to target], + [llvm_cv_target_os_type], +[case $target in + *-*-aix*) + llvm_cv_target_os_type="AIX" ;; + *-*-irix*) + llvm_cv_target_os_type="IRIX" ;; + *-*-cygwin*) + llvm_cv_target_os_type="Cygwin" ;; + *-*-darwin*) + llvm_cv_target_os_type="Darwin" ;; + *-*-freebsd*) + llvm_cv_target_os_type="FreeBSD" ;; + *-*-openbsd*) + llvm_cv_target_os_type="OpenBSD" ;; + *-*-netbsd*) + llvm_cv_target_os_type="NetBSD" ;; + *-*-dragonfly*) + llvm_cv_target_os_type="DragonFly" ;; + *-*-hpux*) + llvm_cv_target_os_type="HP-UX" ;; + *-*-interix*) + llvm_cv_target_os_type="Interix" ;; + *-*-linux*) + llvm_cv_target_os_type="Linux" ;; + *-*-solaris*) + llvm_cv_target_os_type="SunOS" ;; + *-*-auroraux*) + llvm_cv_target_os_type="AuroraUX" ;; + *-*-win32*) + llvm_cv_target_os_type="Win32" ;; + *-*-mingw*) + llvm_cv_target_os_type="MingW" ;; + *-*-haiku*) + llvm_cv_target_os_type="Haiku" ;; + *-unknown-eabi*) + llvm_cv_target_os_type="Freestanding" ;; + *) + llvm_cv_target_os_type="Unknown" ;; +esac]) + +dnl Make sure we aren't attempting to configure for an unknown system +if test "$llvm_cv_os_type" = "Unknown" ; then + AC_MSG_ERROR([Operating system is unknown, configure can't continue]) +fi + +dnl Set the "OS" Makefile variable based on the platform type so the +dnl makefile can configure itself to specific build hosts +AC_SUBST(OS,$llvm_cv_os_type) +AC_SUBST(HOST_OS,$llvm_cv_os_type) +AC_SUBST(TARGET_OS,$llvm_cv_target_os_type) + +dnl Set the LINKALL and NOLINKALL Makefile variables based on the platform +AC_SUBST(LINKALL,$llvm_cv_link_all_option) +AC_SUBST(NOLINKALL,$llvm_cv_no_link_all_option) + +dnl Set the "LLVM_ON_*" variables based on llvm_cvs_platform_type +dnl This is used by lib/System to determine the basic kind of implementation +dnl to use. +case $llvm_cv_platform_type in + Unix) + AC_DEFINE([LLVM_ON_UNIX],[1],[Define if this is Unixish platform]) + AC_SUBST(LLVM_ON_UNIX,[1]) + AC_SUBST(LLVM_ON_WIN32,[0]) + ;; + Win32) + AC_DEFINE([LLVM_ON_WIN32],[1],[Define if this is Win32ish platform]) + AC_SUBST(LLVM_ON_UNIX,[0]) + AC_SUBST(LLVM_ON_WIN32,[1]) + ;; +esac + +dnl Determine what our target architecture is and configure accordingly. +dnl This will allow Makefiles to make a distinction between the hardware and +dnl the OS. +AC_CACHE_CHECK([target architecture],[llvm_cv_target_arch], +[case $target in + i?86-*) llvm_cv_target_arch="x86" ;; + amd64-* | x86_64-*) llvm_cv_target_arch="x86_64" ;; + sparc*-*) llvm_cv_target_arch="Sparc" ;; + powerpc*-*) llvm_cv_target_arch="PowerPC" ;; + alpha*-*) llvm_cv_target_arch="Alpha" ;; + arm*-*) llvm_cv_target_arch="ARM" ;; + mips-*) llvm_cv_target_arch="Mips" ;; + pic16-*) llvm_cv_target_arch="PIC16" ;; + xcore-*) llvm_cv_target_arch="XCore" ;; + msp430-*) llvm_cv_target_arch="MSP430" ;; + s390x-*) llvm_cv_target_arch="SystemZ" ;; + bfin-*) llvm_cv_target_arch="Blackfin" ;; + *) llvm_cv_target_arch="Unknown" ;; +esac]) + +if test "$llvm_cv_target_arch" = "Unknown" ; then + AC_MSG_WARN([Configuring LLVM for an unknown target archicture]) +fi + +# Determine the LLVM native architecture for the target +case "$llvm_cv_target_arch" in + x86) LLVM_NATIVE_ARCH="X86" ;; + x86_64) LLVM_NATIVE_ARCH="X86" ;; + *) LLVM_NATIVE_ARCH="$llvm_cv_target_arch" ;; +esac + +dnl Define a substitution, ARCH, for the target architecture +AC_SUBST(ARCH,$llvm_cv_target_arch) + +dnl Check for the endianness of the target +AC_C_BIGENDIAN(AC_SUBST([ENDIAN],[big]),AC_SUBST([ENDIAN],[little])) + +dnl Check for build platform executable suffix if we're crosscompiling +if test "$cross_compiling" = yes; then + AC_SUBST(LLVM_CROSS_COMPILING, [1]) + AC_BUILD_EXEEXT + ac_build_prefix=${build_alias}- + AC_CHECK_PROG(BUILD_CXX, ${ac_build_prefix}g++, ${ac_build_prefix}g++) + if test -z "$BUILD_CXX"; then + AC_CHECK_PROG(BUILD_CXX, g++, g++) + if test -z "$BUILD_CXX"; then + AC_CHECK_PROG(BUILD_CXX, c++, c++, , , /usr/ucb/c++) + fi + fi +else + AC_SUBST(LLVM_CROSS_COMPILING, [0]) +fi + +dnl Check to see if there's a "CVS" (or .svn or .git) directory indicating +dnl that this build is being done from a checkout. This sets up several +dnl defaults for the command line switches. When we build with a CVS directory, +dnl we get a debug with assertions turned on. Without, we assume a source +dnl release and we get an optimized build without assertions. +dnl See --enable-optimized and --enable-assertions below +if test -d "CVS" -o -d "${srcdir}/CVS" -o -d ".svn" -o -d "${srcdir}/.svn" -o -d ".git" -o -d "${srcdir}/.git"; then + cvsbuild="yes" + optimize="no" + AC_SUBST(CVSBUILD,[[CVSBUILD=1]]) +else + cvsbuild="no" + optimize="yes" +fi + +dnl===-----------------------------------------------------------------------=== +dnl=== +dnl=== SECTION 3: Command line arguments for the configure script. +dnl=== +dnl===-----------------------------------------------------------------------=== + +dnl --enable-optimized : check whether they want to do an optimized build: +AC_ARG_ENABLE(optimized, AS_HELP_STRING( + --enable-optimized,[Compile with optimizations enabled (default is NO)]),,enableval=$optimize) +if test ${enableval} = "no" ; then + AC_SUBST(ENABLE_OPTIMIZED,[[]]) +else + AC_SUBST(ENABLE_OPTIMIZED,[[ENABLE_OPTIMIZED=1]]) +fi + +dnl --enable-profiling : check whether they want to do a profile build: +AC_ARG_ENABLE(profiling, AS_HELP_STRING( + --enable-profiling,[Compile with profiling enabled (default is NO)]),,enableval="no") +if test ${enableval} = "no" ; then + AC_SUBST(ENABLE_PROFILING,[[]]) +else + AC_SUBST(ENABLE_PROFILING,[[ENABLE_PROFILING=1]]) +fi + +dnl --enable-assertions : check whether they want to turn on assertions or not: +AC_ARG_ENABLE(assertions,AS_HELP_STRING( + --enable-assertions,[Compile with assertion checks enabled (default is YES)]),, enableval="yes") +if test ${enableval} = "yes" ; then + AC_SUBST(DISABLE_ASSERTIONS,[[]]) +else + AC_SUBST(DISABLE_ASSERTIONS,[[DISABLE_ASSERTIONS=1]]) +fi + +dnl --enable-expensive-checks : check whether they want to turn on expensive debug checks: +AC_ARG_ENABLE(expensive-checks,AS_HELP_STRING( + --enable-expensive-checks,[Compile with expensive debug checks enabled (default is NO)]),, enableval="no") +if test ${enableval} = "yes" ; then + AC_SUBST(ENABLE_EXPENSIVE_CHECKS,[[ENABLE_EXPENSIVE_CHECKS=1]]) + AC_SUBST(EXPENSIVE_CHECKS,[[yes]]) +else + AC_SUBST(ENABLE_EXPENSIVE_CHECKS,[[]]) + AC_SUBST(EXPENSIVE_CHECKS,[[no]]) +fi + +dnl --enable-debug-runtime : should runtime libraries have debug symbols? +AC_ARG_ENABLE(debug-runtime, + AS_HELP_STRING(--enable-debug-runtime,[Build runtime libs with debug symbols (default is NO)]),,enableval=no) +if test ${enableval} = "no" ; then + AC_SUBST(DEBUG_RUNTIME,[[]]) +else + AC_SUBST(DEBUG_RUNTIME,[[DEBUG_RUNTIME=1]]) +fi + +dnl --enable-debug-symbols : should even optimized compiler libraries +dnl have debug symbols? +AC_ARG_ENABLE(debug-symbols, + AS_HELP_STRING(--enable-debug-symbols,[Build compiler with debug symbols (default is NO if optimization is on and YES if it's off)]),,enableval=no) +if test ${enableval} = "no" ; then + AC_SUBST(DEBUG_SYMBOLS,[[]]) +else + AC_SUBST(DEBUG_SYMBOLS,[[DEBUG_SYMBOLS=1]]) +fi + +dnl --enable-jit: check whether they want to enable the jit +AC_ARG_ENABLE(jit, + AS_HELP_STRING(--enable-jit, + [Enable Just In Time Compiling (default is YES)]),, + enableval=default) +if test ${enableval} = "no" +then + AC_SUBST(JIT,[[]]) +else + case "$llvm_cv_target_arch" in + x86) AC_SUBST(TARGET_HAS_JIT,1) ;; + Sparc) AC_SUBST(TARGET_HAS_JIT,0) ;; + PowerPC) AC_SUBST(TARGET_HAS_JIT,1) ;; + x86_64) AC_SUBST(TARGET_HAS_JIT,1) ;; + Alpha) AC_SUBST(TARGET_HAS_JIT,1) ;; + ARM) AC_SUBST(TARGET_HAS_JIT,1) ;; + Mips) AC_SUBST(TARGET_HAS_JIT,0) ;; + PIC16) AC_SUBST(TARGET_HAS_JIT,0) ;; + XCore) AC_SUBST(TARGET_HAS_JIT,0) ;; + MSP430) AC_SUBST(TARGET_HAS_JIT,0) ;; + SystemZ) AC_SUBST(TARGET_HAS_JIT,0) ;; + Blackfin) AC_SUBST(TARGET_HAS_JIT,0) ;; + *) AC_SUBST(TARGET_HAS_JIT,0) ;; + esac +fi + +dnl Allow enablement of doxygen generated documentation +AC_ARG_ENABLE(doxygen, + AS_HELP_STRING([--enable-doxygen], + [Build doxygen documentation (default is NO)]),, + enableval=default) +case "$enableval" in + yes) AC_SUBST(ENABLE_DOXYGEN,[1]) ;; + no) AC_SUBST(ENABLE_DOXYGEN,[0]) ;; + default) AC_SUBST(ENABLE_DOXYGEN,[0]) ;; + *) AC_MSG_ERROR([Invalid setting for --enable-doxygen. Use "yes" or "no"]) ;; +esac + +dnl Allow disablement of threads +AC_ARG_ENABLE(threads, + AS_HELP_STRING([--enable-threads], + [Use threads if available (default is YES)]),, + enableval=default) +case "$enableval" in + yes) AC_SUBST(ENABLE_THREADS,[1]) ;; + no) AC_SUBST(ENABLE_THREADS,[0]) ;; + default) AC_SUBST(ENABLE_THREADS,[1]) ;; + *) AC_MSG_ERROR([Invalid setting for --enable-threads. Use "yes" or "no"]) ;; +esac +AC_DEFINE_UNQUOTED([ENABLE_THREADS],$ENABLE_THREADS,[Define if threads enabled]) + +dnl Allow building without position independent code +AC_ARG_ENABLE(pic, + AS_HELP_STRING([--enable-pic], + [Build LLVM with Position Independent Code (default is YES)]),, + enableval=default) +case "$enableval" in + yes) AC_SUBST(ENABLE_PIC,[1]) ;; + no) AC_SUBST(ENABLE_PIC,[0]) ;; + default) AC_SUBST(ENABLE_PIC,[1]) ;; + *) AC_MSG_ERROR([Invalid setting for --enable-pic. Use "yes" or "no"]) ;; +esac +AC_DEFINE_UNQUOTED([ENABLE_PIC],$ENABLE_PIC, + [Define if position independent code is enabled]) + +dnl Allow specific targets to be specified for building (or not) +TARGETS_TO_BUILD="" +AC_ARG_ENABLE([targets],AS_HELP_STRING([--enable-targets], + [Build specific host targets: all or target1,target2,... Valid targets are: + host, x86, x86_64, sparc, powerpc, alpha, arm, mips, spu, pic16, + xcore, msp430, systemz, blackfin, cbe, msil, and cpp (default=all)]),, + enableval=all) +if test "$enableval" = host-only ; then + enableval=host +fi +case "$enableval" in + all) TARGETS_TO_BUILD="X86 Sparc PowerPC Alpha ARM Mips CellSPU PIC16 XCore MSP430 SystemZ Blackfin CBackend MSIL CppBackend" ;; + *)for a_target in `echo $enableval|sed -e 's/,/ /g' ` ; do + case "$a_target" in + x86) TARGETS_TO_BUILD="X86 $TARGETS_TO_BUILD" ;; + x86_64) TARGETS_TO_BUILD="X86 $TARGETS_TO_BUILD" ;; + sparc) TARGETS_TO_BUILD="Sparc $TARGETS_TO_BUILD" ;; + powerpc) TARGETS_TO_BUILD="PowerPC $TARGETS_TO_BUILD" ;; + alpha) TARGETS_TO_BUILD="Alpha $TARGETS_TO_BUILD" ;; + arm) TARGETS_TO_BUILD="ARM $TARGETS_TO_BUILD" ;; + mips) TARGETS_TO_BUILD="Mips $TARGETS_TO_BUILD" ;; + spu) TARGETS_TO_BUILD="CellSPU $TARGETS_TO_BUILD" ;; + pic16) TARGETS_TO_BUILD="PIC16 $TARGETS_TO_BUILD" ;; + xcore) TARGETS_TO_BUILD="XCore $TARGETS_TO_BUILD" ;; + msp430) TARGETS_TO_BUILD="MSP430 $TARGETS_TO_BUILD" ;; + systemz) TARGETS_TO_BUILD="SystemZ $TARGETS_TO_BUILD" ;; + blackfin) TARGETS_TO_BUILD="Blackfin $TARGETS_TO_BUILD" ;; + cbe) TARGETS_TO_BUILD="CBackend $TARGETS_TO_BUILD" ;; + msil) TARGETS_TO_BUILD="MSIL $TARGETS_TO_BUILD" ;; + cpp) TARGETS_TO_BUILD="CppBackend $TARGETS_TO_BUILD" ;; + host) case "$llvm_cv_target_arch" in + x86) TARGETS_TO_BUILD="X86 $TARGETS_TO_BUILD" ;; + x86_64) TARGETS_TO_BUILD="X86 $TARGETS_TO_BUILD" ;; + Sparc) TARGETS_TO_BUILD="Sparc $TARGETS_TO_BUILD" ;; + PowerPC) TARGETS_TO_BUILD="PowerPC $TARGETS_TO_BUILD" ;; + Alpha) TARGETS_TO_BUILD="Alpha $TARGETS_TO_BUILD" ;; + ARM) TARGETS_TO_BUILD="ARM $TARGETS_TO_BUILD" ;; + Mips) TARGETS_TO_BUILD="Mips $TARGETS_TO_BUILD" ;; + CellSPU|SPU) TARGETS_TO_BUILD="CellSPU $TARGETS_TO_BUILD" ;; + PIC16) TARGETS_TO_BUILD="PIC16 $TARGETS_TO_BUILD" ;; + XCore) TARGETS_TO_BUILD="XCore $TARGETS_TO_BUILD" ;; + MSP430) TARGETS_TO_BUILD="MSP430 $TARGETS_TO_BUILD" ;; + SystemZ) TARGETS_TO_BUILD="SystemZ $TARGETS_TO_BUILD" ;; + Blackfin) TARGETS_TO_BUILD="Blackfin $TARGETS_TO_BUILD" ;; + *) AC_MSG_ERROR([Can not set target to build]) ;; + esac ;; + *) AC_MSG_ERROR([Unrecognized target $a_target]) ;; + esac + done + ;; +esac +AC_SUBST(TARGETS_TO_BUILD,$TARGETS_TO_BUILD) + +# Determine whether we are building LLVM support for the native architecture. +# If so, define LLVM_NATIVE_ARCH to that LLVM target. +for a_target in $TARGETS_TO_BUILD; do + if test "$a_target" = "$LLVM_NATIVE_ARCH"; then + LLVM_NATIVE_ARCHTARGET="${LLVM_NATIVE_ARCH}Target" + AC_DEFINE_UNQUOTED(LLVM_NATIVE_ARCH,$LLVM_NATIVE_ARCHTARGET, + [LLVM architecture name for the native architecture, if available]) + fi +done + +# Build the LLVM_TARGET and LLVM_... macros for Targets.def and the individual +# target feature def files. +LLVM_ENUM_TARGETS="" +LLVM_ENUM_ASM_PRINTERS="" +LLVM_ENUM_ASM_PARSERS="" +LLVM_ENUM_DISASSEMBLERS="" +for target_to_build in $TARGETS_TO_BUILD; do + LLVM_ENUM_TARGETS="LLVM_TARGET($target_to_build) $LLVM_ENUM_TARGETS" + if test -f ${srcdir}/lib/Target/${target_to_build}/AsmPrinter/Makefile ; then + LLVM_ENUM_ASM_PRINTERS="LLVM_ASM_PRINTER($target_to_build) $LLVM_ENUM_ASM_PRINTERS"; + fi + if test -f ${srcdir}/lib/Target/${target_to_build}/AsmParser/Makefile ; then + LLVM_ENUM_ASM_PARSERS="LLVM_ASM_PARSER($target_to_build) $LLVM_ENUM_ASM_PARSERS"; + fi + if test -f ${srcdir}/lib/Target/${target_to_build}/Disassembler/Makefile ; then + LLVM_ENUM_DISASSEMBLERS="LLVM_DISASSEMBLER($target_to_build) $LLVM_ENUM_DISASSEMBLERS"; + fi +done +AC_SUBST(LLVM_ENUM_TARGETS) +AC_SUBST(LLVM_ENUM_ASM_PRINTERS) +AC_SUBST(LLVM_ENUM_ASM_PARSERS) +AC_SUBST(LLVM_ENUM_DISASSEMBLERS) + +dnl Prevent the CBackend from using printf("%a") for floating point so older +dnl C compilers that cannot deal with the 0x0p+0 hex floating point format +dnl can still compile the CBE's output +AC_ARG_ENABLE([cbe-printf-a],AS_HELP_STRING([--enable-cbe-printf-a], + [Enable C Backend output with hex floating point via %a (default is YES)]),, + enableval=default) +case "$enableval" in + yes) AC_SUBST(ENABLE_CBE_PRINTF_A,[1]) ;; + no) AC_SUBST(ENABLE_CBE_PRINTF_A,[0]) ;; + default) AC_SUBST(ENABLE_CBE_PRINTF_A,[1]) ;; + *) AC_MSG_ERROR([Invalid setting for --enable-cbe-printf-a. Use "yes" or "no"]) ;; +esac +AC_DEFINE_UNQUOTED([ENABLE_CBE_PRINTF_A],$ENABLE_CBE_PRINTF_A, + [Define if CBE is enabled for printf %a output]) + +dnl Allow a specific llvm-gcc/llvm-g++ pair to be used with this LLVM config. +AC_ARG_WITH(llvmgccdir, + AS_HELP_STRING([--with-llvmgccdir], + [Specify location of llvm-gcc install dir (default searches PATH)]),, + withval=default) +case "$withval" in + default) WITH_LLVMGCCDIR=default ;; + /* | [[A-Za-z]]:[[\\/]]*) WITH_LLVMGCCDIR=$withval ;; + *) AC_MSG_ERROR([Invalid path for --with-llvmgccdir. Provide full path]) ;; +esac + +dnl Allow a specific llvm-gcc compiler to be used with this LLVM config. +AC_ARG_WITH(llvmgcc, + AS_HELP_STRING([--with-llvmgcc], + [Specify location of llvm-gcc driver (default searches PATH)]), + LLVMGCC=$with_llvmgcc + WITH_LLVMGCCDIR="",) + +dnl Allow a specific llvm-g++ compiler to be used with this LLVM config. +AC_ARG_WITH(llvmgxx, + AS_HELP_STRING([--with-llvmgxx], + [Specify location of llvm-g++ driver (default searches PATH)]), + LLVMGXX=$with_llvmgxx + WITH_LLVMGCCDIR="",) + +if test -n "$LLVMGCC"; then + LLVMGCCCOMMAND="$LLVMGCC" +fi + +if test -n "$LLVMGXX"; then + LLVMGXXCOMMAND="$LLVMGXX" +fi + +if test -n "$LLVMGCC" && test -z "$LLVMGXX"; then + AC_MSG_ERROR([Invalid llvm-g++. Use --with-llvmgxx when --with-llvmgcc is used]); +fi + +if test -n "$LLVMGXX" && test -z "$LLVMGCC"; then + AC_MSG_ERROR([Invalid llvm-gcc. Use --with-llvmgcc when --with-llvmgxx is used]); +fi + +dnl Override the option to use for optimized builds. +AC_ARG_WITH(optimize-option, + AS_HELP_STRING([--with-optimize-option], + [Select the compiler options to use for optimized builds]),, + withval=default) +AC_MSG_CHECKING([optimization flags]) +case "$withval" in + default) + case "$llvm_cv_os_type" in + MingW) optimize_option=-O3 ;; + *) optimize_option=-O2 ;; + esac ;; + *) optimize_option="$withval" ;; +esac +AC_SUBST(OPTIMIZE_OPTION,$optimize_option) +AC_MSG_RESULT([$optimize_option]) + +dnl Specify extra build options +AC_ARG_WITH(extra-options, + AS_HELP_STRING([--with-extra-options], + [Specify additional options to compile LLVM with]),, + withval=default) +case "$withval" in + default) EXTRA_OPTIONS= ;; + *) EXTRA_OPTIONS=$withval ;; +esac +AC_SUBST(EXTRA_OPTIONS,$EXTRA_OPTIONS) + +dnl Allow specific bindings to be specified for building (or not) +AC_ARG_ENABLE([bindings],AS_HELP_STRING([--enable-bindings], + [Build specific language bindings: all,auto,none,{binding-name} (default=auto)]),, + enableval=default) +BINDINGS_TO_BUILD="" +case "$enableval" in + yes | default | auto) BINDINGS_TO_BUILD="auto" ;; + all ) BINDINGS_TO_BUILD="ocaml" ;; + none | no) BINDINGS_TO_BUILD="" ;; + *)for a_binding in `echo $enableval|sed -e 's/,/ /g' ` ; do + case "$a_binding" in + ocaml) BINDINGS_TO_BUILD="ocaml $BINDINGS_TO_BUILD" ;; + *) AC_MSG_ERROR([Unrecognized binding $a_binding]) ;; + esac + done + ;; +esac + +dnl Allow the ocaml libdir to be overridden. This could go in a configure +dnl script for bindings/ocaml/configure, except that its auto value depends on +dnl OCAMLC, which is found here to support tests. +AC_ARG_WITH([ocaml-libdir], + [AS_HELP_STRING([--with-ocaml-libdir], + [Specify install location for ocaml bindings (default is stdlib)])], + [], + [withval=auto]) +case "$withval" in + auto) with_ocaml_libdir="$withval" ;; + /* | [[A-Za-z]]:[[\\/]]*) with_ocaml_libdir="$withval" ;; + *) AC_MSG_ERROR([Invalid path for --with-ocaml-libdir. Provide full path]) ;; +esac + +AC_ARG_WITH(c-include-dir, + AS_HELP_STRING([--with-c-include-dirs], + [Colon separated list of directories clang will search for headers]),, + withval="") +AC_DEFINE_UNQUOTED(C_INCLUDE_DIRS,"$withval", + [Directories clang will search for headers]) + +AC_ARG_WITH(cxx-include-root, + AS_HELP_STRING([--with-cxx-include-root], + [Directory with the libstdc++ headers.]),, + withval="") +AC_DEFINE_UNQUOTED(CXX_INCLUDE_ROOT,"$withval", + [Directory with the libstdc++ headers.]) + +AC_ARG_WITH(cxx-include-arch, + AS_HELP_STRING([--with-cxx-include-arch], + [Architecture of the libstdc++ headers.]),, + withval="") +AC_DEFINE_UNQUOTED(CXX_INCLUDE_ARCH,"$withval", + [Arch the libstdc++ headers.]) + +AC_ARG_WITH(cxx-include-32bit-dir, + AS_HELP_STRING([--with-cxx-include-32bit-dir], + [32 bit multilib dir.]),, + withval="") +AC_DEFINE_UNQUOTED(CXX_INCLUDE_32BIT_DIR,"$withval", + [32 bit multilib directory.]) + +AC_ARG_WITH(cxx-include-64bit-dir, + AS_HELP_STRING([--with-cxx-include-64bit-dir], + [64 bit multilib directory.]),, + withval="") +AC_DEFINE_UNQUOTED(CXX_INCLUDE_64BIT_DIR,"$withval", + [64 bit multilib directory.]) + +dnl Allow linking of LLVM with GPLv3 binutils code. +AC_ARG_WITH(binutils-include, + AS_HELP_STRING([--with-binutils-include], + [Specify path to binutils/include/ containing plugin-api.h file for gold plugin.]),, + withval=default) +case "$withval" in + default) WITH_BINUTILS_INCDIR=default ;; + /* | [[A-Za-z]]:[[\\/]]*) WITH_BINUTILS_INCDIR=$withval ;; + *) AC_MSG_ERROR([Invalid path for --with-binutils-include. Provide full path]) ;; +esac +if test "x$WITH_BINUTILS_INCDIR" != xdefault ; then + AC_SUBST(BINUTILS_INCDIR,$WITH_BINUTILS_INCDIR) + if test ! -f "$WITH_BINUTILS_INCDIR/plugin-api.h"; then + echo "$WITH_BINUTILS_INCDIR/plugin-api.h" + AC_MSG_ERROR([Invalid path to directory containing plugin-api.h.]); + fi +fi + +dnl --enable-libffi : check whether the user wants to turn off libffi: +AC_ARG_ENABLE(libffi,AS_HELP_STRING( + --enable-libffi,[Check for the presence of libffi (default is YES)]),, + enableval=yes) +case "$enableval" in + yes) llvm_cv_enable_libffi="yes" ;; + no) llvm_cv_enable_libffi="no" ;; + *) AC_MSG_ERROR([Invalid setting for --enable-libffi. Use "yes" or "no"]) ;; +esac + +dnl Only Windows needs dynamic libCompilerDriver to support plugins. +if test "$llvm_cv_os_type" = "Win32" ; then + llvmc_dynamic="yes" +else + llvmc_dynamic="no" +fi + +dnl --enable-llvmc-dynamic : should LLVMC link libCompilerDriver dynamically? +AC_ARG_ENABLE(llvmc-dynamic,AS_HELP_STRING( +--enable-llvmc-dynamic, +[Link LLVMC dynamically (default is NO, unless on Win32)]),, +enableval=$llvmc_dynamic) +if test ${enableval} = "yes" && test "$ENABLE_PIC" -eq 1 ; then + AC_SUBST(ENABLE_LLVMC_DYNAMIC,[[ENABLE_LLVMC_DYNAMIC=1]]) +else + AC_SUBST(ENABLE_LLVMC_DYNAMIC,[[]]) +fi + +dnl --enable-llvmc-dynamic-plugins : should LLVMC support dynamic plugins? +AC_ARG_ENABLE(llvmc-dynamic-plugins,AS_HELP_STRING( +--enable-llvmc-dynamic-plugins, +[Enable dynamic LLVMC plugins (default is YES)]),, +enableval=yes) +if test ${enableval} = "yes" ; then + AC_SUBST(ENABLE_LLVMC_DYNAMIC_PLUGINS,[[ENABLE_LLVMC_DYNAMIC_PLUGINS=1]]) +else + AC_SUBST(ENABLE_LLVMC_DYNAMIC_PLUGINS,[[]]) +fi + +dnl===-----------------------------------------------------------------------=== +dnl=== +dnl=== SECTION 4: Check for programs we need and that they are the right version +dnl=== +dnl===-----------------------------------------------------------------------=== + +dnl Check for compilation tools +AC_PROG_CPP +AC_PROG_CC(gcc) +AC_PROG_CXX(g++) + +AC_PROG_NM +AC_SUBST(NM) + +dnl Check for the tools that the makefiles require +AC_CHECK_GNU_MAKE +AC_PROG_LN_S +AC_PATH_PROG(CMP, [cmp], [cmp]) +AC_PATH_PROG(CP, [cp], [cp]) +AC_PATH_PROG(DATE, [date], [date]) +AC_PATH_PROG(FIND, [find], [find]) +AC_PATH_PROG(GREP, [grep], [grep]) +AC_PATH_PROG(MKDIR,[mkdir],[mkdir]) +AC_PATH_PROG(MV, [mv], [mv]) +AC_PROG_RANLIB +AC_PATH_PROG(RM, [rm], [rm]) +AC_PATH_PROG(SED, [sed], [sed]) +AC_PATH_PROG(TAR, [tar], [gtar]) +AC_PATH_PROG(BINPWD,[pwd], [pwd]) + +dnl Looking for misc. graph plotting software +AC_PATH_PROG(GRAPHVIZ, [Graphviz], [echo Graphviz]) +if test "$GRAPHVIZ" != "echo Graphviz" ; then + AC_DEFINE([HAVE_GRAPHVIZ],[1],[Define if the Graphviz program is available]) + dnl If we're targeting for mingw we should emit windows paths, not msys + if test "$llvm_cv_os_type" = "MingW" ; then + GRAPHVIZ=`echo $GRAPHVIZ | sed 's/^\/\([[A-Za-z]]\)\//\1:\//' ` + fi + AC_DEFINE_UNQUOTED([LLVM_PATH_GRAPHVIZ],"$GRAPHVIZ${EXEEXT}", + [Define to path to Graphviz program if found or 'echo Graphviz' otherwise]) +fi +AC_PATH_PROG(DOT, [dot], [echo dot]) +if test "$DOT" != "echo dot" ; then + AC_DEFINE([HAVE_DOT],[1],[Define if the dot program is available]) + dnl If we're targeting for mingw we should emit windows paths, not msys + if test "$llvm_cv_os_type" = "MingW" ; then + DOT=`echo $DOT | sed 's/^\/\([[A-Za-z]]\)\//\1:\//' ` + fi + AC_DEFINE_UNQUOTED([LLVM_PATH_DOT],"$DOT${EXEEXT}", + [Define to path to dot program if found or 'echo dot' otherwise]) +fi +AC_PATH_PROG(FDP, [fdp], [echo fdp]) +if test "$FDP" != "echo fdp" ; then + AC_DEFINE([HAVE_FDP],[1],[Define if the neat program is available]) + dnl If we're targeting for mingw we should emit windows paths, not msys + if test "$llvm_cv_os_type" = "MingW" ; then + FDP=`echo $FDP | sed 's/^\/\([[A-Za-z]]\)\//\1:\//' ` + fi + AC_DEFINE_UNQUOTED([LLVM_PATH_FDP],"$FDP${EXEEXT}", + [Define to path to fdp program if found or 'echo fdp' otherwise]) +fi +AC_PATH_PROG(NEATO, [neato], [echo neato]) +if test "$NEATO" != "echo neato" ; then + AC_DEFINE([HAVE_NEATO],[1],[Define if the neat program is available]) + dnl If we're targeting for mingw we should emit windows paths, not msys + if test "$llvm_cv_os_type" = "MingW" ; then + NEATO=`echo $NEATO | sed 's/^\/\([[A-Za-z]]\)\//\1:\//' ` + fi + AC_DEFINE_UNQUOTED([LLVM_PATH_NEATO],"$NEATO${EXEEXT}", + [Define to path to neato program if found or 'echo neato' otherwise]) +fi +AC_PATH_PROG(TWOPI, [twopi], [echo twopi]) +if test "$TWOPI" != "echo twopi" ; then + AC_DEFINE([HAVE_TWOPI],[1],[Define if the neat program is available]) + dnl If we're targeting for mingw we should emit windows paths, not msys + if test "$llvm_cv_os_type" = "MingW" ; then + TWOPI=`echo $TWOPI | sed 's/^\/\([[A-Za-z]]\)\//\1:\//' ` + fi + AC_DEFINE_UNQUOTED([LLVM_PATH_TWOPI],"$TWOPI${EXEEXT}", + [Define to path to twopi program if found or 'echo twopi' otherwise]) +fi +AC_PATH_PROG(CIRCO, [circo], [echo circo]) +if test "$CIRCO" != "echo circo" ; then + AC_DEFINE([HAVE_CIRCO],[1],[Define if the neat program is available]) + dnl If we're targeting for mingw we should emit windows paths, not msys + if test "$llvm_cv_os_type" = "MingW" ; then + CIRCO=`echo $CIRCO | sed 's/^\/\([[A-Za-z]]\)\//\1:\//' ` + fi + AC_DEFINE_UNQUOTED([LLVM_PATH_CIRCO],"$CIRCO${EXEEXT}", + [Define to path to circo program if found or 'echo circo' otherwise]) +fi +AC_PATH_PROGS(GV, [gv gsview32], [echo gv]) +if test "$GV" != "echo gv" ; then + AC_DEFINE([HAVE_GV],[1],[Define if the gv program is available]) + dnl If we're targeting for mingw we should emit windows paths, not msys + if test "$llvm_cv_os_type" = "MingW" ; then + GV=`echo $GV | sed 's/^\/\([[A-Za-z]]\)\//\1:\//' ` + fi + AC_DEFINE_UNQUOTED([LLVM_PATH_GV],"$GV${EXEEXT}", + [Define to path to gv program if found or 'echo gv' otherwise]) +fi +AC_PATH_PROG(DOTTY, [dotty], [echo dotty]) +if test "$DOTTY" != "echo dotty" ; then + AC_DEFINE([HAVE_DOTTY],[1],[Define if the dotty program is available]) + dnl If we're targeting for mingw we should emit windows paths, not msys + if test "$llvm_cv_os_type" = "MingW" ; then + DOTTY=`echo $DOTTY | sed 's/^\/\([[A-Za-z]]\)\//\1:\//' ` + fi + AC_DEFINE_UNQUOTED([LLVM_PATH_DOTTY],"$DOTTY${EXEEXT}", + [Define to path to dotty program if found or 'echo dotty' otherwise]) +fi + +dnl Look for a sufficiently recent version of Perl. +LLVM_PROG_PERL([5.006]) +AC_SUBST(PERL) +if test x"$PERL" = xnone; then + AC_SUBST(HAVE_PERL,0) + AC_MSG_ERROR([perl is required but was not found, please install it]) +else + AC_SUBST(HAVE_PERL,1) +fi + +dnl Find the install program +AC_PROG_INSTALL + +dnl Checks for documentation and testing tools that we can do without. If these +dnl are not found then they are set to "true" which always succeeds but does +dnl nothing. This just lets the build output show that we could have done +dnl something if the tool was available. +AC_PATH_PROG(BZIP2, [bzip2]) +AC_PATH_PROG(DOXYGEN, [doxygen]) +AC_PATH_PROG(GROFF, [groff]) +AC_PATH_PROG(GZIP, [gzip]) +AC_PATH_PROG(POD2HTML, [pod2html]) +AC_PATH_PROG(POD2MAN, [pod2man]) +AC_PATH_PROG(RUNTEST, [runtest]) +DJ_AC_PATH_TCLSH +AC_PATH_PROG(ZIP, [zip]) +AC_PATH_PROGS(OCAMLC, [ocamlc]) +AC_PATH_PROGS(OCAMLOPT, [ocamlopt]) +AC_PATH_PROGS(OCAMLDEP, [ocamldep]) +AC_PATH_PROGS(OCAMLDOC, [ocamldoc]) +AC_PATH_PROGS(GAS, [gas as]) + +dnl Determine whether the linker supports the -R option. +AC_LINK_USE_R + +dnl Determine whether the linker supports the -export-dynamic option. +AC_LINK_EXPORT_DYNAMIC + +dnl Check for libtool and the library that has dlopen function (which must come +dnl before the AC_PROG_LIBTOOL check in order to enable dlopening libraries with +dnl libtool). +AC_LIBTOOL_DLOPEN +AC_LIB_LTDL +AC_PROG_LIBTOOL + +if test "$lt_cv_dlopen_self" = "yes" ; then + AC_DEFINE([CAN_DLOPEN_SELF],[1], + [Define if dlopen(0) will open the symbols of the program]) +fi + + +if test "$WITH_LLVMGCCDIR" = "default" ; then + LLVMGCC="llvm-gcc${EXEEXT}" + LLVMGXX="llvm-g++${EXEEXT}" + LLVMGCCCOMMAND="$LLVMGCC" + LLVMGXXCOMMAND="$LLVMGXX" + AC_SUBST(LLVMGCCCOMMAND,$LLVMGCCCOMMAND) + AC_SUBST(LLVMGXXCOMMAND,$LLVMGXXCOMMAND) + AC_PATH_PROG(LLVMGCC, $LLVMGCC, []) + AC_PATH_PROG(LLVMGXX, $LLVMGXX, []) +else + if test -z "$LLVMGCC"; then + LLVMGCC="$WITH_LLVMGCCDIR/bin/llvm-gcc${EXEEXT}" + LLVMGCCCOMMAND="$LLVMGCC" + fi + if test -z "$LLVMGXX"; then + LLVMGXX="$WITH_LLVMGCCDIR/bin/llvm-g++${EXEEXT}" + LLVMGXXCOMMAND="$LLVMGXX" + fi + + AC_SUBST(LLVMGCC,$LLVMGCC) + AC_SUBST(LLVMGXX,$LLVMGXX) + AC_SUBST(LLVMGCCCOMMAND,$LLVMGCCCOMMAND) + AC_SUBST(LLVMGXXCOMMAND,$LLVMGXXCOMMAND) +fi + + +AC_MSG_CHECKING([tool compatibility]) + +dnl Ensure that compilation tools are GCC or a GNU compatible compiler such as +dnl ICC; we use GCC specific options in the makefiles so the compiler needs +dnl to support those options. +dnl "icc" emits gcc signatures +dnl "icc -no-gcc" emits no gcc signature BUT is still compatible +ICC=no +IXX=no +case $CC in + icc*|icpc*) + ICC=yes + IXX=yes + ;; + *) + ;; +esac + +if test "$GCC" != "yes" && test "$ICC" != "yes" +then + AC_MSG_ERROR([gcc|icc required but not found]) +fi + +dnl Ensure that compilation tools are GCC; we use GCC specific extensions +if test "$GXX" != "yes" && test "$IXX" != "yes" +then + AC_MSG_ERROR([g++|icc required but not found]) +fi + +dnl Verify that GCC is version 3.0 or higher +if test "$GCC" = "yes" +then + AC_COMPILE_IFELSE([[#if !defined(__GNUC__) || __GNUC__ < 3 +#error Unsupported GCC version +#endif +]], [], [AC_MSG_ERROR([gcc 3.x required, but you have a lower version])]) +fi + +dnl Check for GNU Make. We use its extensions, so don't build without it +if test -z "$llvm_cv_gnu_make_command" +then + AC_MSG_ERROR([GNU Make required but not found]) +fi + +dnl Tool compatibility is okay if we make it here. +AC_MSG_RESULT([ok]) + +dnl Check optional compiler flags. +AC_MSG_CHECKING([optional compiler flags]) +CXX_FLAG_CHECK(NO_VARIADIC_MACROS, [-Wno-variadic-macros]) +CXX_FLAG_CHECK(NO_MISSING_FIELD_INITIALIZERS, [-Wno-missing-field-initializers]) +AC_MSG_RESULT([$NO_VARIADIC_MACROS $NO_MISSING_FIELD_INITIALIZERS]) + +dnl===-----------------------------------------------------------------------=== +dnl=== +dnl=== SECTION 5: Check for libraries +dnl=== +dnl===-----------------------------------------------------------------------=== + +AC_CHECK_LIB(m,sin) +if test "$llvm_cv_os_type" = "MingW" ; then + AC_CHECK_LIB(imagehlp, main) + AC_CHECK_LIB(psapi, main) +fi + +dnl dlopen() is required for plugin support. +AC_SEARCH_LIBS(dlopen,dl,AC_DEFINE([HAVE_DLOPEN],[1], + [Define if dlopen() is available on this platform.]), + AC_MSG_WARN([dlopen() not found - disabling plugin support])) + +dnl libffi is optional; used to call external functions from the interpreter +if test "$llvm_cv_enable_libffi" = "yes" ; then + AC_SEARCH_LIBS(ffi_call,ffi,AC_DEFINE([HAVE_FFI_CALL],[1], + [Define if libffi is available on this platform.]), + AC_MSG_WARN([libffi not found - disabling external calls from interpreter])) +fi + +dnl mallinfo is optional; the code can compile (minus features) without it +AC_SEARCH_LIBS(mallinfo,malloc,AC_DEFINE([HAVE_MALLINFO],[1], + [Define if mallinfo() is available on this platform.])) + +dnl pthread locking functions are optional - but llvm will not be thread-safe +dnl without locks. +if test "$ENABLE_THREADS" -eq 1 ; then + AC_CHECK_LIB(pthread, pthread_mutex_init) + AC_SEARCH_LIBS(pthread_mutex_lock,pthread, + AC_DEFINE([HAVE_PTHREAD_MUTEX_LOCK],[1], + [Have pthread_mutex_lock])) + AC_SEARCH_LIBS(pthread_rwlock_init,pthread, + AC_DEFINE([HAVE_PTHREAD_RWLOCK_INIT],[1], + [Have pthread_rwlock_init])) + AC_SEARCH_LIBS(pthread_getspecific,pthread, + AC_DEFINE([HAVE_PTHREAD_GETSPECIFIC],[1], + [Have pthread_getspecific])) +fi + +dnl Allow extra x86-disassembler library +AC_ARG_WITH(udis86, + AS_HELP_STRING([--with-udis86=], + [Use udis86 external x86 disassembler library]), + [ + AC_SUBST(USE_UDIS86, [1]) + case "$withval" in + /usr/lib|yes) ;; + *) LDFLAGS="$LDFLAGS -L${withval}" ;; + esac + AC_CHECK_LIB(udis86, ud_init, [], [ + echo "Error! You need to have libudis86 around." + exit -1 + ]) + ], + AC_SUBST(USE_UDIS86, [0])) +AC_DEFINE_UNQUOTED([USE_UDIS86],$USE_UDIS86, + [Define if use udis86 library]) + +dnl Allow OProfile support for JIT output. +AC_ARG_WITH(oprofile, + AS_HELP_STRING([--with-oprofile=], + [Tell OProfile >= 0.9.4 how to symbolize JIT output]), + [ + AC_SUBST(USE_OPROFILE, [1]) + case "$withval" in + /usr|yes) llvm_cv_oppath=/usr/lib/oprofile ;; + no) llvm_cv_oppath= + AC_SUBST(USE_OPROFILE, [0]) ;; + *) llvm_cv_oppath="${withval}/lib/oprofile" + CPPFLAGS="-I${withval}/include";; + esac + if test -n "$llvm_cv_oppath" ; then + LIBS="$LIBS -L${llvm_cv_oppath} -Wl,-rpath,${llvm_cv_oppath}" + dnl Work around http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=537744: + dnl libbfd is not included properly in libopagent in some Debian + dnl versions. If libbfd isn't found at all, we assume opagent works + dnl anyway. + AC_SEARCH_LIBS(bfd_init, bfd, [], []) + AC_SEARCH_LIBS(op_open_agent, opagent, [], [ + echo "Error! You need to have libopagent around." + exit -1 + ]) + AC_CHECK_HEADER([opagent.h], [], [ + echo "Error! You need to have opagent.h around." + exit -1 + ]) + fi + ], + [ + AC_SUBST(USE_OPROFILE, [0]) + ]) +AC_DEFINE_UNQUOTED([USE_OPROFILE],$USE_OPROFILE, + [Define if we have the oprofile JIT-support library]) + +dnl===-----------------------------------------------------------------------=== +dnl=== +dnl=== SECTION 6: Check for header files +dnl=== +dnl===-----------------------------------------------------------------------=== + +dnl First, use autoconf provided macros for specific headers that we need +dnl We don't check for ancient stuff or things that are guaranteed to be there +dnl by the C++ standard. We always use the versions of C headers. +dnl Generally we're looking for POSIX headers. +AC_HEADER_DIRENT +AC_HEADER_MMAP_ANONYMOUS +AC_HEADER_STAT +AC_HEADER_STDC +AC_HEADER_SYS_WAIT +AC_HEADER_TIME + +AC_CHECK_HEADERS([dlfcn.h execinfo.h fcntl.h inttypes.h limits.h link.h]) +AC_CHECK_HEADERS([malloc.h setjmp.h signal.h stdint.h termios.h unistd.h]) +AC_CHECK_HEADERS([utime.h windows.h]) +AC_CHECK_HEADERS([sys/mman.h sys/param.h sys/resource.h sys/time.h]) +AC_CHECK_HEADERS([sys/types.h sys/ioctl.h malloc/malloc.h mach/mach.h]) +if test "$ENABLE_THREADS" -eq 1 ; then + AC_CHECK_HEADERS(pthread.h, + AC_SUBST(HAVE_PTHREAD, 1), + AC_SUBST(HAVE_PTHREAD, 0)) +else + AC_SUBST(HAVE_PTHREAD, 0) +fi + +dnl Try to find ffi.h. +if test "$llvm_cv_enable_libffi" = "yes" ; then + AC_CHECK_HEADERS([ffi.h ffi/ffi.h]) +fi + +dnl===-----------------------------------------------------------------------=== +dnl=== +dnl=== SECTION 7: Check for types and structures +dnl=== +dnl===-----------------------------------------------------------------------=== + +AC_HUGE_VAL_CHECK +AC_TYPE_PID_T +AC_TYPE_SIZE_T +AC_TYPE_SIGNAL +AC_STRUCT_TM +AC_CHECK_TYPES([int64_t],,AC_MSG_ERROR([Type int64_t required but not found])) +AC_CHECK_TYPES([uint64_t],, + AC_CHECK_TYPES([u_int64_t],, + AC_MSG_ERROR([Type uint64_t or u_int64_t required but not found]))) + +dnl===-----------------------------------------------------------------------=== +dnl=== +dnl=== SECTION 8: Check for specific functions needed +dnl=== +dnl===-----------------------------------------------------------------------=== + +AC_CHECK_FUNCS([backtrace ceilf floorf roundf rintf nearbyintf getcwd ]) +AC_CHECK_FUNCS([powf fmodf strtof round ]) +AC_CHECK_FUNCS([getpagesize getrusage getrlimit setrlimit gettimeofday ]) +AC_CHECK_FUNCS([isatty mkdtemp mkstemp ]) +AC_CHECK_FUNCS([mktemp realpath sbrk setrlimit strdup ]) +AC_CHECK_FUNCS([strerror strerror_r strerror_s setenv ]) +AC_CHECK_FUNCS([strtoll strtoq sysconf malloc_zone_statistics ]) +AC_CHECK_FUNCS([setjmp longjmp sigsetjmp siglongjmp]) +AC_C_PRINTF_A +dnl FIXME: This is no longer used, please remove (but test)!!! +AC_FUNC_ALLOCA +AC_FUNC_RAND48 + +dnl Check for variations in the Standard C++ library and STL. These macros are +dnl provided by LLVM in the autoconf/m4 directory. +AC_CXX_HAVE_STD_ITERATOR +AC_CXX_HAVE_BI_ITERATOR +AC_CXX_HAVE_FWD_ITERATOR +AC_FUNC_ISNAN +AC_FUNC_ISINF + +dnl Check for mmap support.We also need to know if /dev/zero is required to +dnl be opened for allocating RWX memory. +dnl Make sure we aren't attempting to configure for an unknown system +if test "$llvm_cv_platform_type" = "Unix" ; then + AC_FUNC_MMAP + AC_FUNC_MMAP_FILE + AC_NEED_DEV_ZERO_FOR_MMAP + + if test "$ac_cv_func_mmap_fixed_mapped" = "no" + then + AC_MSG_WARN([mmap() of a fixed address required but not supported]) + fi + if test "$ac_cv_func_mmap_file" = "no" + then + AC_MSG_WARN([mmap() of files required but not found]) + fi +fi + +dnl atomic builtins are required for threading support. +AC_MSG_CHECKING(for GCC atomic builtins) +AC_LINK_IFELSE( + AC_LANG_SOURCE( + [[int main() { + volatile unsigned long val = 1; + __sync_synchronize(); + __sync_val_compare_and_swap(&val, 1, 0); + __sync_add_and_fetch(&val, 1); + __sync_sub_and_fetch(&val, 1); + return 0; + } + ]]), + AC_MSG_RESULT(yes) + AC_DEFINE(LLVM_MULTITHREADED, 1, Build multithreading support into LLVM), + AC_MSG_RESULT(no) + AC_DEFINE(LLVM_MULTITHREADED, 0, Build multithreading support into LLVM) + AC_MSG_WARN([LLVM will be built thread-unsafe because atomic builtins are missing])) + + +dnl===-----------------------------------------------------------------------=== +dnl=== +dnl=== SECTION 9: Additional checks, variables, etc. +dnl=== +dnl===-----------------------------------------------------------------------=== + +dnl Handle 32-bit linux systems running a 64-bit kernel. +dnl This has to come after section 4 because it invokes the compiler. +if test "$llvm_cv_os_type" = "Linux" -a "$llvm_cv_target_arch" = "x86_64" ; then + AC_IS_LINUX_MIXED + if test "$llvm_cv_linux_mixed" = "yes"; then + llvm_cv_target_arch="x86" + ARCH="x86" + fi +fi + +dnl Check, whether __dso_handle is present +AC_CHECK_FUNCS([__dso_handle]) + +dnl See if the llvm-gcc executable can compile to LLVM assembly +AC_CACHE_CHECK([whether llvm-gcc is sane],[llvm_cv_llvmgcc_sanity], +[llvm_cv_llvmgcc_sanity="no" +if test -x "$LLVMGCC" ; then + cp /dev/null conftest.c + "$LLVMGCC" -emit-llvm -S -o - conftest.c | \ + grep 'target datalayout =' > /dev/null 2>&1 + if test $? -eq 0 ; then + llvm_cv_llvmgcc_sanity="yes" + fi + rm conftest.c +fi]) + +dnl Since we have a sane llvm-gcc, identify it and its sub-tools +if test "$llvm_cv_llvmgcc_sanity" = "yes" ; then + AC_MSG_CHECKING([llvm-gcc component support]) + llvmcc1path=`"$LLVMGCC" --print-prog-name=cc1` + AC_SUBST(LLVMCC1,$llvmcc1path) + llvmcc1pluspath=`"$LLVMGCC" --print-prog-name=cc1plus` + AC_SUBST(LLVMCC1PLUS,$llvmcc1pluspath) + llvmgccdir=`echo "$llvmcc1path" | sed 's,/libexec/.*,,'` + AC_SUBST(LLVMGCCDIR,$llvmgccdir) + llvmgcclibexec=`echo "$llvmcc1path" | sed 's,/cc1,,'` + AC_SUBST(LLVMGCCLIBEXEC,$llvmgcclibexec) + llvmgccversion=[`"$LLVMGCC" -dumpversion 2>&1 | sed 's/^\([0-9.]*\).*/\1/'`] + llvmgccmajvers=[`echo $llvmgccversion | sed 's/^\([0-9]\).*/\1/'`] + AC_SUBST(LLVMGCC_VERSION,$llvmgccversion) + AC_SUBST(LLVMGCC_MAJVERS,$llvmgccmajvers) + llvmgcclangs=[`"$LLVMGCC" -v --help 2>&1 | grep '^Configured with:' | sed 's/^.*--enable-languages=\([^ ]*\).*/\1/'`] + AC_SUBST(LLVMGCC_LANGS,$llvmgcclangs) + AC_MSG_RESULT([ok]) +fi + +dnl Propagate the shared library extension that the libltdl checks did to +dnl the Makefiles so we can use it there too +AC_SUBST(SHLIBEXT,$libltdl_cv_shlibext) + +# Translate the various configuration directories and other basic +# information into substitutions that will end up in Makefile.config.in +# that these configured values can be used by the makefiles +if test "${prefix}" = "NONE" ; then + prefix="/usr/local" +fi +eval LLVM_PREFIX="${prefix}"; +eval LLVM_BINDIR="${prefix}/bin"; +eval LLVM_LIBDIR="${prefix}/lib"; +eval LLVM_DATADIR="${prefix}/share/llvm"; +eval LLVM_DOCSDIR="${prefix}/docs/llvm"; +eval LLVM_ETCDIR="${prefix}/etc/llvm"; +eval LLVM_INCLUDEDIR="${prefix}/include"; +eval LLVM_INFODIR="${prefix}/info"; +eval LLVM_MANDIR="${prefix}/man"; +LLVM_CONFIGTIME=`date` +AC_SUBST(LLVM_PREFIX) +AC_SUBST(LLVM_BINDIR) +AC_SUBST(LLVM_LIBDIR) +AC_SUBST(LLVM_DATADIR) +AC_SUBST(LLVM_DOCSDIR) +AC_SUBST(LLVM_ETCDIR) +AC_SUBST(LLVM_INCLUDEDIR) +AC_SUBST(LLVM_INFODIR) +AC_SUBST(LLVM_MANDIR) +AC_SUBST(LLVM_CONFIGTIME) + +# Place the various directores into the config.h file as #defines so that we +# can know about the installation paths within LLVM. +AC_DEFINE_UNQUOTED(LLVM_PREFIX,"$LLVM_PREFIX", + [Installation prefix directory]) +AC_DEFINE_UNQUOTED(LLVM_BINDIR, "$LLVM_BINDIR", + [Installation directory for binary executables]) +AC_DEFINE_UNQUOTED(LLVM_LIBDIR, "$LLVM_LIBDIR", + [Installation directory for libraries]) +AC_DEFINE_UNQUOTED(LLVM_DATADIR, "$LLVM_DATADIR", + [Installation directory for data files]) +AC_DEFINE_UNQUOTED(LLVM_DOCSDIR, "$LLVM_DOCSDIR", + [Installation directory for documentation]) +AC_DEFINE_UNQUOTED(LLVM_ETCDIR, "$LLVM_ETCDIR", + [Installation directory for config files]) +AC_DEFINE_UNQUOTED(LLVM_INCLUDEDIR, "$LLVM_INCLUDEDIR", + [Installation directory for include files]) +AC_DEFINE_UNQUOTED(LLVM_INFODIR, "$LLVM_INFODIR", + [Installation directory for .info files]) +AC_DEFINE_UNQUOTED(LLVM_MANDIR, "$LLVM_MANDIR", + [Installation directory for man pages]) +AC_DEFINE_UNQUOTED(LLVM_CONFIGTIME, "$LLVM_CONFIGTIME", + [Time at which LLVM was configured]) +AC_DEFINE_UNQUOTED(LLVM_HOSTTRIPLE, "$host", + [Host triple we were built on]) + +# Determine which bindings to build. +if test "$BINDINGS_TO_BUILD" = auto ; then + BINDINGS_TO_BUILD="" + if test "x$OCAMLC" != x -a "x$OCAMLDEP" != x ; then + BINDINGS_TO_BUILD="ocaml $BINDINGS_TO_BUILD" + fi +fi +AC_SUBST(BINDINGS_TO_BUILD,$BINDINGS_TO_BUILD) + +# This isn't really configurey, but it avoids having to repeat the list in +# other files. +AC_SUBST(ALL_BINDINGS,ocaml) + +# Do any work necessary to ensure that bindings have what they need. +binding_prereqs_failed=0 +for a_binding in $BINDINGS_TO_BUILD ; do + case "$a_binding" in + ocaml) + if test "x$OCAMLC" = x ; then + AC_MSG_WARN([--enable-bindings=ocaml specified, but ocamlc not found. Try configure OCAMLC=/path/to/ocamlc]) + binding_prereqs_failed=1 + fi + if test "x$OCAMLDEP" = x ; then + AC_MSG_WARN([--enable-bindings=ocaml specified, but ocamldep not found. Try configure OCAMLDEP=/path/to/ocamldep]) + binding_prereqs_failed=1 + fi + if test "x$OCAMLOPT" = x ; then + AC_MSG_WARN([--enable-bindings=ocaml specified, but ocamlopt not found. Try configure OCAMLOPT=/path/to/ocamlopt]) + dnl ocamlopt is optional! + fi + if test "x$with_ocaml_libdir" != xauto ; then + AC_SUBST(OCAML_LIBDIR,$with_ocaml_libdir) + else + ocaml_stdlib="`"$OCAMLC" -where`" + if test "$LLVM_PREFIX" '<' "$ocaml_stdlib" -a "$ocaml_stdlib" '<' "$LLVM_PREFIX~" + then + # ocaml stdlib is beneath our prefix; use stdlib + AC_SUBST(OCAML_LIBDIR,$ocaml_stdlib) + else + # ocaml stdlib is outside our prefix; use libdir/ocaml + AC_SUBST(OCAML_LIBDIR,$LLVM_LIBDIR/ocaml) + fi + fi + ;; + esac +done +if test "$binding_prereqs_failed" = 1 ; then + AC_MSG_ERROR([Prequisites for bindings not satisfied. Fix them or use configure --disable-bindings.]) +fi + +dnl Determine whether the compiler supports -fvisibility-inlines-hidden. +AC_CXX_USE_VISIBILITY_INLINES_HIDDEN + +dnl Determine linker rpath flag +if test "$llvm_cv_link_use_r" = "yes" ; then + RPATH="-Wl,-R" +else + RPATH="-Wl,-rpath" +fi +AC_SUBST(RPATH) + +dnl Determine linker rdynamic flag +if test "$llvm_cv_link_use_export_dynamic" = "yes" ; then + RDYNAMIC="-Wl,-export-dynamic" +else + RDYNAMIC="" +fi +AC_SUBST(RDYNAMIC) + +dnl===-----------------------------------------------------------------------=== +dnl=== +dnl=== SECTION 10: Specify the output files and generate it +dnl=== +dnl===-----------------------------------------------------------------------=== + +dnl Configure header files +dnl WARNING: dnl If you add or remove any of the following config headers, then +dnl you MUST also update Makefile.rules so that the variable FilesToConfig +dnl contains the same list of files as AC_CONFIG_HEADERS below. This ensures the +dnl files can be updated automatically when their *.in sources change. +AC_CONFIG_HEADERS([include/llvm/Config/config.h]) +AC_CONFIG_FILES([include/llvm/Config/Targets.def]) +AC_CONFIG_FILES([include/llvm/Config/AsmPrinters.def]) +AC_CONFIG_FILES([include/llvm/Config/AsmParsers.def]) +AC_CONFIG_FILES([include/llvm/Config/Disassemblers.def]) +AC_CONFIG_HEADERS([include/llvm/System/DataTypes.h]) + +dnl Configure the makefile's configuration data +AC_CONFIG_FILES([Makefile.config]) + +dnl Configure the RPM spec file for LLVM +AC_CONFIG_FILES([llvm.spec]) + +dnl Configure doxygen's configuration file +AC_CONFIG_FILES([docs/doxygen.cfg]) + +dnl Configure llvmc's Base plugin +AC_CONFIG_FILES([tools/llvmc/plugins/Base/Base.td]) + +dnl Do the first stage of configuration for llvm-config.in. +AC_CONFIG_FILES([tools/llvm-config/llvm-config.in]) + +dnl Do special configuration of Makefiles +AC_CONFIG_COMMANDS([setup],,[llvm_src="${srcdir}"]) +AC_CONFIG_MAKEFILE(Makefile) +AC_CONFIG_MAKEFILE(Makefile.common) +AC_CONFIG_MAKEFILE(examples/Makefile) +AC_CONFIG_MAKEFILE(lib/Makefile) +AC_CONFIG_MAKEFILE(runtime/Makefile) +AC_CONFIG_MAKEFILE(test/Makefile) +AC_CONFIG_MAKEFILE(test/Makefile.tests) +AC_CONFIG_MAKEFILE(unittests/Makefile) +AC_CONFIG_MAKEFILE(tools/Makefile) +AC_CONFIG_MAKEFILE(utils/Makefile) +AC_CONFIG_MAKEFILE(projects/Makefile) +AC_CONFIG_MAKEFILE(bindings/Makefile) +AC_CONFIG_MAKEFILE(bindings/ocaml/Makefile.ocaml) + +dnl Finally, crank out the output +AC_OUTPUT diff --git a/libclamav/c++/llvm/autoconf/depcomp b/libclamav/c++/llvm/autoconf/depcomp new file mode 100755 index 000000000..11e2d3bfe --- /dev/null +++ b/libclamav/c++/llvm/autoconf/depcomp @@ -0,0 +1,522 @@ +#! /bin/sh +# depcomp - compile a program generating dependencies as side-effects + +scriptversion=2004-05-31.23 + +# Copyright (C) 1999, 2000, 2003, 2004 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA. + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# Originally written by Alexandre Oliva . + +case $1 in + '') + echo "$0: No command. Try \`$0 --help' for more information." 1>&2 + exit 1; + ;; + -h | --h*) + cat <<\EOF +Usage: depcomp [--help] [--version] PROGRAM [ARGS] + +Run PROGRAMS ARGS to compile a file, generating dependencies +as side-effects. + +Environment variables: + depmode Dependency tracking mode. + source Source file read by `PROGRAMS ARGS'. + object Object file output by `PROGRAMS ARGS'. + DEPDIR directory where to store dependencies. + depfile Dependency file to output. + tmpdepfile Temporary file to use when outputing dependencies. + libtool Whether libtool is used (yes/no). + +Report bugs to . +EOF + exit 0 + ;; + -v | --v*) + echo "depcomp $scriptversion" + exit 0 + ;; +esac + +if test -z "$depmode" || test -z "$source" || test -z "$object"; then + echo "depcomp: Variables source, object and depmode must be set" 1>&2 + exit 1 +fi + +# Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po. +depfile=${depfile-`echo "$object" | + sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`} +tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`} + +rm -f "$tmpdepfile" + +# Some modes work just like other modes, but use different flags. We +# parameterize here, but still list the modes in the big case below, +# to make depend.m4 easier to write. Note that we *cannot* use a case +# here, because this file can only contain one case statement. +if test "$depmode" = hp; then + # HP compiler uses -M and no extra arg. + gccflag=-M + depmode=gcc +fi + +if test "$depmode" = dashXmstdout; then + # This is just like dashmstdout with a different argument. + dashmflag=-xM + depmode=dashmstdout +fi + +case "$depmode" in +gcc3) +## gcc 3 implements dependency tracking that does exactly what +## we want. Yay! Note: for some reason libtool 1.4 doesn't like +## it if -MD -MP comes after the -MF stuff. Hmm. + "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + mv "$tmpdepfile" "$depfile" + ;; + +gcc) +## There are various ways to get dependency output from gcc. Here's +## why we pick this rather obscure method: +## - Don't want to use -MD because we'd like the dependencies to end +## up in a subdir. Having to rename by hand is ugly. +## (We might end up doing this anyway to support other compilers.) +## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like +## -MM, not -M (despite what the docs say). +## - Using -M directly means running the compiler twice (even worse +## than renaming). + if test -z "$gccflag"; then + gccflag=-MD, + fi + "$@" -Wp,"$gccflag$tmpdepfile" + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + echo "$object : \\" > "$depfile" + alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz +## The second -e expression handles DOS-style file names with drive letters. + sed -e 's/^[^:]*: / /' \ + -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile" +## This next piece of magic avoids the `deleted header file' problem. +## The problem is that when a header file which appears in a .P file +## is deleted, the dependency causes make to die (because there is +## typically no way to rebuild the header). We avoid this by adding +## dummy dependencies for each header file. Too bad gcc doesn't do +## this for us directly. + tr ' ' ' +' < "$tmpdepfile" | +## Some versions of gcc put a space before the `:'. On the theory +## that the space means something, we add a space to the output as +## well. +## Some versions of the HPUX 10.20 sed can't process this invocation +## correctly. Breaking it into two sed invocations is a workaround. + sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +hp) + # This case exists only to let depend.m4 do its work. It works by + # looking at the text of this script. This case will never be run, + # since it is checked for above. + exit 1 + ;; + +sgi) + if test "$libtool" = yes; then + "$@" "-Wp,-MDupdate,$tmpdepfile" + else + "$@" -MDupdate "$tmpdepfile" + fi + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + + if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files + echo "$object : \\" > "$depfile" + + # Clip off the initial element (the dependent). Don't try to be + # clever and replace this with sed code, as IRIX sed won't handle + # lines with more than a fixed number of characters (4096 in + # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines; + # the IRIX cc adds comments like `#:fec' to the end of the + # dependency line. + tr ' ' ' +' < "$tmpdepfile" \ + | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \ + tr ' +' ' ' >> $depfile + echo >> $depfile + + # The second pass generates a dummy entry for each header file. + tr ' ' ' +' < "$tmpdepfile" \ + | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ + >> $depfile + else + # The sourcefile does not contain any dependencies, so just + # store a dummy comment line, to avoid errors with the Makefile + # "include basename.Plo" scheme. + echo "#dummy" > "$depfile" + fi + rm -f "$tmpdepfile" + ;; + +aix) + # The C for AIX Compiler uses -M and outputs the dependencies + # in a .u file. In older versions, this file always lives in the + # current directory. Also, the AIX compiler puts `$object:' at the + # start of each line; $object doesn't have directory information. + # Version 6 uses the directory in both cases. + stripped=`echo "$object" | sed 's/\(.*\)\..*$/\1/'` + tmpdepfile="$stripped.u" + if test "$libtool" = yes; then + "$@" -Wc,-M + else + "$@" -M + fi + stat=$? + + if test -f "$tmpdepfile"; then : + else + stripped=`echo "$stripped" | sed 's,^.*/,,'` + tmpdepfile="$stripped.u" + fi + + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + + if test -f "$tmpdepfile"; then + outname="$stripped.o" + # Each line is of the form `foo.o: dependent.h'. + # Do two passes, one to just change these to + # `$object: dependent.h' and one to simply `dependent.h:'. + sed -e "s,^$outname:,$object :," < "$tmpdepfile" > "$depfile" + sed -e "s,^$outname: \(.*\)$,\1:," < "$tmpdepfile" >> "$depfile" + else + # The sourcefile does not contain any dependencies, so just + # store a dummy comment line, to avoid errors with the Makefile + # "include basename.Plo" scheme. + echo "#dummy" > "$depfile" + fi + rm -f "$tmpdepfile" + ;; + +icc) + # Intel's C compiler understands `-MD -MF file'. However on + # icc -MD -MF foo.d -c -o sub/foo.o sub/foo.c + # ICC 7.0 will fill foo.d with something like + # foo.o: sub/foo.c + # foo.o: sub/foo.h + # which is wrong. We want: + # sub/foo.o: sub/foo.c + # sub/foo.o: sub/foo.h + # sub/foo.c: + # sub/foo.h: + # ICC 7.1 will output + # foo.o: sub/foo.c sub/foo.h + # and will wrap long lines using \ : + # foo.o: sub/foo.c ... \ + # sub/foo.h ... \ + # ... + + "$@" -MD -MF "$tmpdepfile" + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + # Each line is of the form `foo.o: dependent.h', + # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'. + # Do two passes, one to just change these to + # `$object: dependent.h' and one to simply `dependent.h:'. + sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile" + # Some versions of the HPUX 10.20 sed can't process this invocation + # correctly. Breaking it into two sed invocations is a workaround. + sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" | + sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +tru64) + # The Tru64 compiler uses -MD to generate dependencies as a side + # effect. `cc -MD -o foo.o ...' puts the dependencies into `foo.o.d'. + # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put + # dependencies in `foo.d' instead, so we check for that too. + # Subdirectories are respected. + dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` + test "x$dir" = "x$object" && dir= + base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` + + if test "$libtool" = yes; then + # Dependencies are output in .lo.d with libtool 1.4. + # With libtool 1.5 they are output both in $dir.libs/$base.o.d + # and in $dir.libs/$base.o.d and $dir$base.o.d. We process the + # latter, because the former will be cleaned when $dir.libs is + # erased. + tmpdepfile1="$dir.libs/$base.lo.d" + tmpdepfile2="$dir$base.o.d" + tmpdepfile3="$dir.libs/$base.d" + "$@" -Wc,-MD + else + tmpdepfile1="$dir$base.o.d" + tmpdepfile2="$dir$base.d" + tmpdepfile3="$dir$base.d" + "$@" -MD + fi + + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" + exit $stat + fi + + if test -f "$tmpdepfile1"; then + tmpdepfile="$tmpdepfile1" + elif test -f "$tmpdepfile2"; then + tmpdepfile="$tmpdepfile2" + else + tmpdepfile="$tmpdepfile3" + fi + if test -f "$tmpdepfile"; then + sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile" + # That's a tab and a space in the []. + sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile" + else + echo "#dummy" > "$depfile" + fi + rm -f "$tmpdepfile" + ;; + +#nosideeffect) + # This comment above is used by automake to tell side-effect + # dependency tracking mechanisms from slower ones. + +dashmstdout) + # Important note: in order to support this mode, a compiler *must* + # always write the preprocessed file to stdout, regardless of -o. + "$@" || exit $? + + # Remove the call to Libtool. + if test "$libtool" = yes; then + while test $1 != '--mode=compile'; do + shift + done + shift + fi + + # Remove `-o $object'. + IFS=" " + for arg + do + case $arg in + -o) + shift + ;; + $object) + shift + ;; + *) + set fnord "$@" "$arg" + shift # fnord + shift # $arg + ;; + esac + done + + test -z "$dashmflag" && dashmflag=-M + # Require at least two characters before searching for `:' + # in the target name. This is to cope with DOS-style filenames: + # a dependency such as `c:/foo/bar' could be seen as target `c' otherwise. + "$@" $dashmflag | + sed 's:^[ ]*[^: ][^:][^:]*\:[ ]*:'"$object"'\: :' > "$tmpdepfile" + rm -f "$depfile" + cat < "$tmpdepfile" > "$depfile" + tr ' ' ' +' < "$tmpdepfile" | \ +## Some versions of the HPUX 10.20 sed can't process this invocation +## correctly. Breaking it into two sed invocations is a workaround. + sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +dashXmstdout) + # This case only exists to satisfy depend.m4. It is never actually + # run, as this mode is specially recognized in the preamble. + exit 1 + ;; + +makedepend) + "$@" || exit $? + # Remove any Libtool call + if test "$libtool" = yes; then + while test $1 != '--mode=compile'; do + shift + done + shift + fi + # X makedepend + shift + cleared=no + for arg in "$@"; do + case $cleared in + no) + set ""; shift + cleared=yes ;; + esac + case "$arg" in + -D*|-I*) + set fnord "$@" "$arg"; shift ;; + # Strip any option that makedepend may not understand. Remove + # the object too, otherwise makedepend will parse it as a source file. + -*|$object) + ;; + *) + set fnord "$@" "$arg"; shift ;; + esac + done + obj_suffix="`echo $object | sed 's/^.*\././'`" + touch "$tmpdepfile" + ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@" + rm -f "$depfile" + cat < "$tmpdepfile" > "$depfile" + sed '1,2d' "$tmpdepfile" | tr ' ' ' +' | \ +## Some versions of the HPUX 10.20 sed can't process this invocation +## correctly. Breaking it into two sed invocations is a workaround. + sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" "$tmpdepfile".bak + ;; + +cpp) + # Important note: in order to support this mode, a compiler *must* + # always write the preprocessed file to stdout. + "$@" || exit $? + + # Remove the call to Libtool. + if test "$libtool" = yes; then + while test $1 != '--mode=compile'; do + shift + done + shift + fi + + # Remove `-o $object'. + IFS=" " + for arg + do + case $arg in + -o) + shift + ;; + $object) + shift + ;; + *) + set fnord "$@" "$arg" + shift # fnord + shift # $arg + ;; + esac + done + + "$@" -E | + sed -n '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' | + sed '$ s: \\$::' > "$tmpdepfile" + rm -f "$depfile" + echo "$object : \\" > "$depfile" + cat < "$tmpdepfile" >> "$depfile" + sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +msvisualcpp) + # Important note: in order to support this mode, a compiler *must* + # always write the preprocessed file to stdout, regardless of -o, + # because we must use -o when running libtool. + "$@" || exit $? + IFS=" " + for arg + do + case "$arg" in + "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") + set fnord "$@" + shift + shift + ;; + *) + set fnord "$@" "$arg" + shift + shift + ;; + esac + done + "$@" -E | + sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::echo "`cygpath -u \\"\1\\"`":p' | sort | uniq > "$tmpdepfile" + rm -f "$depfile" + echo "$object : \\" > "$depfile" + . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s:: \1 \\:p' >> "$depfile" + echo " " >> "$depfile" + . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s::\1\::p' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +none) + exec "$@" + ;; + +*) + echo "Unknown depmode $depmode" 1>&2 + exit 1 + ;; +esac + +exit 0 + +# Local Variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-end: "$" +# End: diff --git a/libclamav/c++/llvm/autoconf/install-sh b/libclamav/c++/llvm/autoconf/install-sh new file mode 100755 index 000000000..dd97db7aa --- /dev/null +++ b/libclamav/c++/llvm/autoconf/install-sh @@ -0,0 +1,322 @@ +#!/bin/sh +# install - install a program, script, or datafile + +scriptversion=2004-09-10.20 + +# This originates from X11R5 (mit/util/scripts/install.sh), which was +# later released in X11R6 (xc/config/util/install.sh) with the +# following copyright and license. +# +# Copyright (C) 1994 X Consortium +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in 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: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# 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 +# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- +# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# +# Except as contained in this notice, the name of the X Consortium shall not +# be used in advertising or otherwise to promote the sale, use or other deal- +# ings in this Software without prior written authorization from the X Consor- +# tium. +# +# +# FSF changes to this file are in the public domain. +# +# Calling this script install-sh is preferred over install.sh, to prevent +# `make' implicit rules from creating a file called install from it +# when there is no Makefile. +# +# This script is compatible with the BSD install script, but was written +# from scratch. It can only install one file at a time, a restriction +# shared with many OS's install programs. + +# set DOITPROG to echo to test this script + +# Don't use :- since 4.3BSD and earlier shells don't like it. +doit="${DOITPROG-}" + +# put in absolute paths if you don't have them in your path; or use env. vars. + +mvprog="${MVPROG-mv}" +cpprog="${CPPROG-cp}" +chmodprog="${CHMODPROG-chmod}" +chownprog="${CHOWNPROG-chown}" +chgrpprog="${CHGRPPROG-chgrp}" +stripprog="${STRIPPROG-strip}" +rmprog="${RMPROG-rm}" +mkdirprog="${MKDIRPROG-mkdir}" + +chmodcmd="$chmodprog 0755" +chowncmd= +chgrpcmd= +stripcmd= +rmcmd="$rmprog -f" +mvcmd="$mvprog" +src= +dst= +dir_arg= +dstarg= +no_target_directory= + +usage="Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE + or: $0 [OPTION]... SRCFILES... DIRECTORY + or: $0 [OPTION]... -t DIRECTORY SRCFILES... + or: $0 [OPTION]... -d DIRECTORIES... + +In the 1st form, copy SRCFILE to DSTFILE. +In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. +In the 4th, create DIRECTORIES. + +Options: +-c (ignored) +-d create directories instead of installing files. +-g GROUP $chgrpprog installed files to GROUP. +-m MODE $chmodprog installed files to MODE. +-o USER $chownprog installed files to USER. +-s $stripprog installed files. +-t DIRECTORY install into DIRECTORY. +-T report an error if DSTFILE is a directory. +--help display this help and exit. +--version display version info and exit. + +Environment variables override the default commands: + CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG +" + +while test -n "$1"; do + case $1 in + -c) shift + continue;; + + -d) dir_arg=true + shift + continue;; + + -g) chgrpcmd="$chgrpprog $2" + shift + shift + continue;; + + --help) echo "$usage"; exit 0;; + + -m) chmodcmd="$chmodprog $2" + shift + shift + continue;; + + -o) chowncmd="$chownprog $2" + shift + shift + continue;; + + -s) stripcmd=$stripprog + shift + continue;; + + -t) dstarg=$2 + shift + shift + continue;; + + -T) no_target_directory=true + shift + continue;; + + --version) echo "$0 $scriptversion"; exit 0;; + + *) # When -d is used, all remaining arguments are directories to create. + # When -t is used, the destination is already specified. + test -n "$dir_arg$dstarg" && break + # Otherwise, the last argument is the destination. Remove it from $@. + for arg + do + if test -n "$dstarg"; then + # $@ is not empty: it contains at least $arg. + set fnord "$@" "$dstarg" + shift # fnord + fi + shift # arg + dstarg=$arg + done + break;; + esac +done + +if test -z "$1"; then + if test -z "$dir_arg"; then + echo "$0: no input file specified." >&2 + exit 1 + fi + # It's OK to call `install-sh -d' without argument. + # This can happen when creating conditional directories. + exit 0 +fi + +for src +do + # Protect names starting with `-'. + case $src in + -*) src=./$src ;; + esac + + if test -n "$dir_arg"; then + dst=$src + src= + + if test -d "$dst"; then + mkdircmd=: + chmodcmd= + else + mkdircmd=$mkdirprog + fi + else + # Waiting for this to be detected by the "$cpprog $src $dsttmp" command + # might cause directories to be created, which would be especially bad + # if $src (and thus $dsttmp) contains '*'. + if test ! -f "$src" && test ! -d "$src"; then + echo "$0: $src does not exist." >&2 + exit 1 + fi + + if test -z "$dstarg"; then + echo "$0: no destination specified." >&2 + exit 1 + fi + + dst=$dstarg + # Protect names starting with `-'. + case $dst in + -*) dst=./$dst ;; + esac + + # If destination is a directory, append the input filename; won't work + # if double slashes aren't ignored. + if test -d "$dst"; then + if test -n "$no_target_directory"; then + echo "$0: $dstarg: Is a directory" >&2 + exit 1 + fi + dst=$dst/`basename "$src"` + fi + fi + + # This sed command emulates the dirname command. + dstdir=`echo "$dst" | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` + + # Make sure that the destination directory exists. + + # Skip lots of stat calls in the usual case. + if test ! -d "$dstdir"; then + defaultIFS=' + ' + IFS="${IFS-$defaultIFS}" + + oIFS=$IFS + # Some sh's can't handle IFS=/ for some reason. + IFS='%' + set - `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'` + IFS=$oIFS + + pathcomp= + + while test $# -ne 0 ; do + pathcomp=$pathcomp$1 + shift + if test ! -d "$pathcomp"; then + $mkdirprog "$pathcomp" + # mkdir can fail with a `File exist' error in case several + # install-sh are creating the directory concurrently. This + # is OK. + test -d "$pathcomp" || exit + fi + pathcomp=$pathcomp/ + done + fi + + if test -n "$dir_arg"; then + $doit $mkdircmd "$dst" \ + && { test -z "$chowncmd" || $doit $chowncmd "$dst"; } \ + && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } \ + && { test -z "$stripcmd" || $doit $stripcmd "$dst"; } \ + && { test -z "$chmodcmd" || $doit $chmodcmd "$dst"; } + + else + dstfile=`basename "$dst"` + + # Make a couple of temp file names in the proper directory. + dsttmp=$dstdir/_inst.$$_ + rmtmp=$dstdir/_rm.$$_ + + # Trap to clean up those temp files at exit. + trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 + trap '(exit $?); exit' 1 2 13 15 + + # Copy the file name to the temp name. + $doit $cpprog "$src" "$dsttmp" && + + # and set any options; do chmod last to preserve setuid bits. + # + # If any of these fail, we abort the whole thing. If we want to + # ignore errors from any of these, just make sure not to ignore + # errors from the above "$doit $cpprog $src $dsttmp" command. + # + { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \ + && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \ + && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \ + && { test -z "$chmodcmd" || $doit $chmodcmd "$dsttmp"; } && + + # Now rename the file to the real destination. + { $doit $mvcmd -f "$dsttmp" "$dstdir/$dstfile" 2>/dev/null \ + || { + # The rename failed, perhaps because mv can't rename something else + # to itself, or perhaps because mv is so ancient that it does not + # support -f. + + # Now remove or move aside any old file at destination location. + # We try this two ways since rm can't unlink itself on some + # systems and the destination file might be busy for other + # reasons. In this case, the final cleanup might fail but the new + # file should still install successfully. + { + if test -f "$dstdir/$dstfile"; then + $doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null \ + || $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null \ + || { + echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2 + (exit 1); exit + } + else + : + fi + } && + + # Now rename the file to the real destination. + $doit $mvcmd "$dsttmp" "$dstdir/$dstfile" + } + } + fi || { (exit 1); exit; } +done + +# The final little trick to "correctly" pass the exit status to the exit trap. +{ + (exit 0); exit +} + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-end: "$" +# End: diff --git a/libclamav/c++/llvm/autoconf/ltmain.sh b/libclamav/c++/llvm/autoconf/ltmain.sh new file mode 100644 index 000000000..06823e057 --- /dev/null +++ b/libclamav/c++/llvm/autoconf/ltmain.sh @@ -0,0 +1,6863 @@ +# ltmain.sh - Provide generalized library-building support services. +# NOTE: Changing this file will not affect anything until you rerun configure. +# +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005 +# Free Software Foundation, Inc. +# Originally by Gordon Matzigkeit , 1996 +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +basename="s,^.*/,,g" + +# Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh +# is ksh but when the shell is invoked as "sh" and the current value of +# the _XPG environment variable is not equal to 1 (one), the special +# positional parameter $0, within a function call, is the name of the +# function. +progpath="$0" + +# The name of this program: +progname=`echo "$progpath" | $SED $basename` +modename="$progname" + +# Global variables: +EXIT_SUCCESS=0 +EXIT_FAILURE=1 + +PROGRAM=ltmain.sh +PACKAGE=libtool +VERSION=1.5.22 +TIMESTAMP=" (1.1220.2.365 2005/12/18 22:14:06)" + +# See if we are running on zsh, and set the options which allow our +# commands through without removal of \ escapes. +if test -n "${ZSH_VERSION+set}" ; then + setopt NO_GLOB_SUBST +fi + +# Check that we have a working $echo. +if test "X$1" = X--no-reexec; then + # Discard the --no-reexec flag, and continue. + shift +elif test "X$1" = X--fallback-echo; then + # Avoid inline document here, it may be left over + : +elif test "X`($echo '\t') 2>/dev/null`" = 'X\t'; then + # Yippee, $echo works! + : +else + # Restart under the correct shell, and then maybe $echo will work. + exec $SHELL "$progpath" --no-reexec ${1+"$@"} +fi + +if test "X$1" = X--fallback-echo; then + # used as fallback echo + shift + cat <&2 + $echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2 + exit $EXIT_FAILURE +fi + +# Global variables. +mode=$default_mode +nonopt= +prev= +prevopt= +run= +show="$echo" +show_help= +execute_dlfiles= +duplicate_deps=no +preserve_args= +lo2o="s/\\.lo\$/.${objext}/" +o2lo="s/\\.${objext}\$/.lo/" + +##################################### +# Shell function definitions: +# This seems to be the best place for them + +# func_mktempdir [string] +# Make a temporary directory that won't clash with other running +# libtool processes, and avoids race conditions if possible. If +# given, STRING is the basename for that directory. +func_mktempdir () +{ + my_template="${TMPDIR-/tmp}/${1-$progname}" + + if test "$run" = ":"; then + # Return a directory name, but don't create it in dry-run mode + my_tmpdir="${my_template}-$$" + else + + # If mktemp works, use that first and foremost + my_tmpdir=`mktemp -d "${my_template}-XXXXXXXX" 2>/dev/null` + + if test ! -d "$my_tmpdir"; then + # Failing that, at least try and use $RANDOM to avoid a race + my_tmpdir="${my_template}-${RANDOM-0}$$" + + save_mktempdir_umask=`umask` + umask 0077 + $mkdir "$my_tmpdir" + umask $save_mktempdir_umask + fi + + # If we're not in dry-run mode, bomb out on failure + test -d "$my_tmpdir" || { + $echo "cannot create temporary directory \`$my_tmpdir'" 1>&2 + exit $EXIT_FAILURE + } + fi + + $echo "X$my_tmpdir" | $Xsed +} + + +# func_win32_libid arg +# return the library type of file 'arg' +# +# Need a lot of goo to handle *both* DLLs and import libs +# Has to be a shell function in order to 'eat' the argument +# that is supplied when $file_magic_command is called. +func_win32_libid () +{ + win32_libid_type="unknown" + win32_fileres=`file -L $1 2>/dev/null` + case $win32_fileres in + *ar\ archive\ import\ library*) # definitely import + win32_libid_type="x86 archive import" + ;; + *ar\ archive*) # could be an import, or static + if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null | \ + $EGREP -e 'file format pe-i386(.*architecture: i386)?' >/dev/null ; then + win32_nmres=`eval $NM -f posix -A $1 | \ + $SED -n -e '1,100{/ I /{s,.*,import,;p;q;};}'` + case $win32_nmres in + import*) win32_libid_type="x86 archive import";; + *) win32_libid_type="x86 archive static";; + esac + fi + ;; + *DLL*) + win32_libid_type="x86 DLL" + ;; + *executable*) # but shell scripts are "executable" too... + case $win32_fileres in + *MS\ Windows\ PE\ Intel*) + win32_libid_type="x86 DLL" + ;; + esac + ;; + esac + $echo $win32_libid_type +} + + +# func_infer_tag arg +# Infer tagged configuration to use if any are available and +# if one wasn't chosen via the "--tag" command line option. +# Only attempt this if the compiler in the base compile +# command doesn't match the default compiler. +# arg is usually of the form 'gcc ...' +func_infer_tag () +{ + if test -n "$available_tags" && test -z "$tagname"; then + CC_quoted= + for arg in $CC; do + case $arg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + arg="\"$arg\"" + ;; + esac + CC_quoted="$CC_quoted $arg" + done + case $@ in + # Blanks in the command may have been stripped by the calling shell, + # but not from the CC environment variable when configure was run. + " $CC "* | "$CC "* | " `$echo $CC` "* | "`$echo $CC` "* | " $CC_quoted"* | "$CC_quoted "* | " `$echo $CC_quoted` "* | "`$echo $CC_quoted` "*) ;; + # Blanks at the start of $base_compile will cause this to fail + # if we don't check for them as well. + *) + for z in $available_tags; do + if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $z$" < "$progpath" > /dev/null; then + # Evaluate the configuration. + eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $progpath`" + CC_quoted= + for arg in $CC; do + # Double-quote args containing other shell metacharacters. + case $arg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + arg="\"$arg\"" + ;; + esac + CC_quoted="$CC_quoted $arg" + done + case "$@ " in + " $CC "* | "$CC "* | " `$echo $CC` "* | "`$echo $CC` "* | " $CC_quoted"* | "$CC_quoted "* | " `$echo $CC_quoted` "* | "`$echo $CC_quoted` "*) + # The compiler in the base compile command matches + # the one in the tagged configuration. + # Assume this is the tagged configuration we want. + tagname=$z + break + ;; + esac + fi + done + # If $tagname still isn't set, then no tagged configuration + # was found and let the user know that the "--tag" command + # line option must be used. + if test -z "$tagname"; then + $echo "$modename: unable to infer tagged configuration" + $echo "$modename: specify a tag with \`--tag'" 1>&2 + exit $EXIT_FAILURE +# else +# $echo "$modename: using $tagname tagged configuration" + fi + ;; + esac + fi +} + + +# func_extract_an_archive dir oldlib +func_extract_an_archive () +{ + f_ex_an_ar_dir="$1"; shift + f_ex_an_ar_oldlib="$1" + + $show "(cd $f_ex_an_ar_dir && $AR x $f_ex_an_ar_oldlib)" + $run eval "(cd \$f_ex_an_ar_dir && $AR x \$f_ex_an_ar_oldlib)" || exit $? + if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then + : + else + $echo "$modename: ERROR: object name conflicts: $f_ex_an_ar_dir/$f_ex_an_ar_oldlib" 1>&2 + exit $EXIT_FAILURE + fi +} + +# func_extract_archives gentop oldlib ... +func_extract_archives () +{ + my_gentop="$1"; shift + my_oldlibs=${1+"$@"} + my_oldobjs="" + my_xlib="" + my_xabs="" + my_xdir="" + my_status="" + + $show "${rm}r $my_gentop" + $run ${rm}r "$my_gentop" + $show "$mkdir $my_gentop" + $run $mkdir "$my_gentop" + my_status=$? + if test "$my_status" -ne 0 && test ! -d "$my_gentop"; then + exit $my_status + fi + + for my_xlib in $my_oldlibs; do + # Extract the objects. + case $my_xlib in + [\\/]* | [A-Za-z]:[\\/]*) my_xabs="$my_xlib" ;; + *) my_xabs=`pwd`"/$my_xlib" ;; + esac + my_xlib=`$echo "X$my_xlib" | $Xsed -e 's%^.*/%%'` + my_xdir="$my_gentop/$my_xlib" + + $show "${rm}r $my_xdir" + $run ${rm}r "$my_xdir" + $show "$mkdir $my_xdir" + $run $mkdir "$my_xdir" + exit_status=$? + if test "$exit_status" -ne 0 && test ! -d "$my_xdir"; then + exit $exit_status + fi + case $host in + *-darwin*) + $show "Extracting $my_xabs" + # Do not bother doing anything if just a dry run + if test -z "$run"; then + darwin_orig_dir=`pwd` + cd $my_xdir || exit $? + darwin_archive=$my_xabs + darwin_curdir=`pwd` + darwin_base_archive=`$echo "X$darwin_archive" | $Xsed -e 's%^.*/%%'` + darwin_arches=`lipo -info "$darwin_archive" 2>/dev/null | $EGREP Architectures 2>/dev/null` + if test -n "$darwin_arches"; then + darwin_arches=`echo "$darwin_arches" | $SED -e 's/.*are://'` + darwin_arch= + $show "$darwin_base_archive has multiple architectures $darwin_arches" + for darwin_arch in $darwin_arches ; do + mkdir -p "unfat-$$/${darwin_base_archive}-${darwin_arch}" + lipo -thin $darwin_arch -output "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" "${darwin_archive}" + cd "unfat-$$/${darwin_base_archive}-${darwin_arch}" + func_extract_an_archive "`pwd`" "${darwin_base_archive}" + cd "$darwin_curdir" + $rm "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" + done # $darwin_arches + ## Okay now we have a bunch of thin objects, gotta fatten them up :) + darwin_filelist=`find unfat-$$ -type f -name \*.o -print -o -name \*.lo -print| xargs basename | sort -u | $NL2SP` + darwin_file= + darwin_files= + for darwin_file in $darwin_filelist; do + darwin_files=`find unfat-$$ -name $darwin_file -print | $NL2SP` + lipo -create -output "$darwin_file" $darwin_files + done # $darwin_filelist + ${rm}r unfat-$$ + cd "$darwin_orig_dir" + else + cd "$darwin_orig_dir" + func_extract_an_archive "$my_xdir" "$my_xabs" + fi # $darwin_arches + fi # $run + ;; + *) + func_extract_an_archive "$my_xdir" "$my_xabs" + ;; + esac + my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | $NL2SP` + done + func_extract_archives_result="$my_oldobjs" +} +# End of Shell function definitions +##################################### + +# Darwin sucks +eval std_shrext=\"$shrext_cmds\" + +disable_libs=no + +# Parse our command line options once, thoroughly. +while test "$#" -gt 0 +do + arg="$1" + shift + + case $arg in + -*=*) optarg=`$echo "X$arg" | $Xsed -e 's/[-_a-zA-Z0-9]*=//'` ;; + *) optarg= ;; + esac + + # If the previous option needs an argument, assign it. + if test -n "$prev"; then + case $prev in + execute_dlfiles) + execute_dlfiles="$execute_dlfiles $arg" + ;; + tag) + tagname="$arg" + preserve_args="${preserve_args}=$arg" + + # Check whether tagname contains only valid characters + case $tagname in + *[!-_A-Za-z0-9,/]*) + $echo "$progname: invalid tag name: $tagname" 1>&2 + exit $EXIT_FAILURE + ;; + esac + + case $tagname in + CC) + # Don't test for the "default" C tag, as we know, it's there, but + # not specially marked. + ;; + *) + if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$" < "$progpath" > /dev/null; then + taglist="$taglist $tagname" + # Evaluate the configuration. + eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$tagname'$/,/^# ### END LIBTOOL TAG CONFIG: '$tagname'$/p' < $progpath`" + else + $echo "$progname: ignoring unknown tag $tagname" 1>&2 + fi + ;; + esac + ;; + *) + eval "$prev=\$arg" + ;; + esac + + prev= + prevopt= + continue + fi + + # Have we seen a non-optional argument yet? + case $arg in + --help) + show_help=yes + ;; + + --version) + $echo "$PROGRAM (GNU $PACKAGE) $VERSION$TIMESTAMP" + $echo + $echo "Copyright (C) 2005 Free Software Foundation, Inc." + $echo "This is free software; see the source for copying conditions. There is NO" + $echo "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + exit $? + ;; + + --config) + ${SED} -e '1,/^# ### BEGIN LIBTOOL CONFIG/d' -e '/^# ### END LIBTOOL CONFIG/,$d' $progpath + # Now print the configurations for the tags. + for tagname in $taglist; do + ${SED} -n -e "/^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$/,/^# ### END LIBTOOL TAG CONFIG: $tagname$/p" < "$progpath" + done + exit $? + ;; + + --debug) + $echo "$progname: enabling shell trace mode" + set -x + preserve_args="$preserve_args $arg" + ;; + + --dry-run | -n) + run=: + ;; + + --features) + $echo "host: $host" + if test "$build_libtool_libs" = yes; then + $echo "enable shared libraries" + else + $echo "disable shared libraries" + fi + if test "$build_old_libs" = yes; then + $echo "enable static libraries" + else + $echo "disable static libraries" + fi + exit $? + ;; + + --finish) mode="finish" ;; + + --mode) prevopt="--mode" prev=mode ;; + --mode=*) mode="$optarg" ;; + + --preserve-dup-deps) duplicate_deps="yes" ;; + + --quiet | --silent) + show=: + preserve_args="$preserve_args $arg" + ;; + + --tag) + prevopt="--tag" + prev=tag + preserve_args="$preserve_args --tag" + ;; + --tag=*) + set tag "$optarg" ${1+"$@"} + shift + prev=tag + preserve_args="$preserve_args --tag" + ;; + + -dlopen) + prevopt="-dlopen" + prev=execute_dlfiles + ;; + + -*) + $echo "$modename: unrecognized option \`$arg'" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + ;; + + *) + nonopt="$arg" + break + ;; + esac +done + +if test -n "$prevopt"; then + $echo "$modename: option \`$prevopt' requires an argument" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE +fi + +case $disable_libs in +no) + ;; +shared) + build_libtool_libs=no + build_old_libs=yes + ;; +static) + build_old_libs=`case $build_libtool_libs in yes) echo no;; *) echo yes;; esac` + ;; +esac + +# If this variable is set in any of the actions, the command in it +# will be execed at the end. This prevents here-documents from being +# left over by shells. +exec_cmd= + +if test -z "$show_help"; then + + # Infer the operation mode. + if test -z "$mode"; then + $echo "*** Warning: inferring the mode of operation is deprecated." 1>&2 + $echo "*** Future versions of Libtool will require --mode=MODE be specified." 1>&2 + case $nonopt in + *cc | cc* | *++ | gcc* | *-gcc* | g++* | xlc*) + mode=link + for arg + do + case $arg in + -c) + mode=compile + break + ;; + esac + done + ;; + *db | *dbx | *strace | *truss) + mode=execute + ;; + *install*|cp|mv) + mode=install + ;; + *rm) + mode=uninstall + ;; + *) + # If we have no mode, but dlfiles were specified, then do execute mode. + test -n "$execute_dlfiles" && mode=execute + + # Just use the default operation mode. + if test -z "$mode"; then + if test -n "$nonopt"; then + $echo "$modename: warning: cannot infer operation mode from \`$nonopt'" 1>&2 + else + $echo "$modename: warning: cannot infer operation mode without MODE-ARGS" 1>&2 + fi + fi + ;; + esac + fi + + # Only execute mode is allowed to have -dlopen flags. + if test -n "$execute_dlfiles" && test "$mode" != execute; then + $echo "$modename: unrecognized option \`-dlopen'" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + + # Change the help message to a mode-specific one. + generic_help="$help" + help="Try \`$modename --help --mode=$mode' for more information." + + # These modes are in order of execution frequency so that they run quickly. + case $mode in + # libtool compile mode + compile) + modename="$modename: compile" + # Get the compilation command and the source file. + base_compile= + srcfile="$nonopt" # always keep a non-empty value in "srcfile" + suppress_opt=yes + suppress_output= + arg_mode=normal + libobj= + later= + + for arg + do + case $arg_mode in + arg ) + # do not "continue". Instead, add this to base_compile + lastarg="$arg" + arg_mode=normal + ;; + + target ) + libobj="$arg" + arg_mode=normal + continue + ;; + + normal ) + # Accept any command-line options. + case $arg in + -o) + if test -n "$libobj" ; then + $echo "$modename: you cannot specify \`-o' more than once" 1>&2 + exit $EXIT_FAILURE + fi + arg_mode=target + continue + ;; + + -static | -prefer-pic | -prefer-non-pic) + later="$later $arg" + continue + ;; + + -no-suppress) + suppress_opt=no + continue + ;; + + -Xcompiler) + arg_mode=arg # the next one goes into the "base_compile" arg list + continue # The current "srcfile" will either be retained or + ;; # replaced later. I would guess that would be a bug. + + -Wc,*) + args=`$echo "X$arg" | $Xsed -e "s/^-Wc,//"` + lastarg= + save_ifs="$IFS"; IFS=',' + for arg in $args; do + IFS="$save_ifs" + + # Double-quote args containing other shell metacharacters. + # Many Bourne shells cannot handle close brackets correctly + # in scan sets, so we specify it separately. + case $arg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + arg="\"$arg\"" + ;; + esac + lastarg="$lastarg $arg" + done + IFS="$save_ifs" + lastarg=`$echo "X$lastarg" | $Xsed -e "s/^ //"` + + # Add the arguments to base_compile. + base_compile="$base_compile $lastarg" + continue + ;; + + * ) + # Accept the current argument as the source file. + # The previous "srcfile" becomes the current argument. + # + lastarg="$srcfile" + srcfile="$arg" + ;; + esac # case $arg + ;; + esac # case $arg_mode + + # Aesthetically quote the previous argument. + lastarg=`$echo "X$lastarg" | $Xsed -e "$sed_quote_subst"` + + case $lastarg in + # Double-quote args containing other shell metacharacters. + # Many Bourne shells cannot handle close brackets correctly + # in scan sets, and some SunOS ksh mistreat backslash-escaping + # in scan sets (worked around with variable expansion), + # and furthermore cannot handle '|' '&' '(' ')' in scan sets + # at all, so we specify them separately. + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + lastarg="\"$lastarg\"" + ;; + esac + + base_compile="$base_compile $lastarg" + done # for arg + + case $arg_mode in + arg) + $echo "$modename: you must specify an argument for -Xcompile" + exit $EXIT_FAILURE + ;; + target) + $echo "$modename: you must specify a target with \`-o'" 1>&2 + exit $EXIT_FAILURE + ;; + *) + # Get the name of the library object. + [ -z "$libobj" ] && libobj=`$echo "X$srcfile" | $Xsed -e 's%^.*/%%'` + ;; + esac + + # Recognize several different file suffixes. + # If the user specifies -o file.o, it is replaced with file.lo + xform='[cCFSifmso]' + case $libobj in + *.ada) xform=ada ;; + *.adb) xform=adb ;; + *.ads) xform=ads ;; + *.asm) xform=asm ;; + *.c++) xform=c++ ;; + *.cc) xform=cc ;; + *.ii) xform=ii ;; + *.class) xform=class ;; + *.cpp) xform=cpp ;; + *.cxx) xform=cxx ;; + *.f90) xform=f90 ;; + *.for) xform=for ;; + *.java) xform=java ;; + esac + + libobj=`$echo "X$libobj" | $Xsed -e "s/\.$xform$/.lo/"` + + case $libobj in + *.lo) obj=`$echo "X$libobj" | $Xsed -e "$lo2o"` ;; + *) + $echo "$modename: cannot determine name of library object from \`$libobj'" 1>&2 + exit $EXIT_FAILURE + ;; + esac + + func_infer_tag $base_compile + + for arg in $later; do + case $arg in + -static) + build_old_libs=yes + continue + ;; + + -prefer-pic) + pic_mode=yes + continue + ;; + + -prefer-non-pic) + pic_mode=no + continue + ;; + esac + done + + qlibobj=`$echo "X$libobj" | $Xsed -e "$sed_quote_subst"` + case $qlibobj in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + qlibobj="\"$qlibobj\"" ;; + esac + test "X$libobj" != "X$qlibobj" \ + && $echo "X$libobj" | grep '[]~#^*{};<>?"'"'"' &()|`$[]' \ + && $echo "$modename: libobj name \`$libobj' may not contain shell special characters." + objname=`$echo "X$obj" | $Xsed -e 's%^.*/%%'` + xdir=`$echo "X$obj" | $Xsed -e 's%/[^/]*$%%'` + if test "X$xdir" = "X$obj"; then + xdir= + else + xdir=$xdir/ + fi + lobj=${xdir}$objdir/$objname + + if test -z "$base_compile"; then + $echo "$modename: you must specify a compilation command" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + + # Delete any leftover library objects. + if test "$build_old_libs" = yes; then + removelist="$obj $lobj $libobj ${libobj}T" + else + removelist="$lobj $libobj ${libobj}T" + fi + + $run $rm $removelist + trap "$run $rm $removelist; exit $EXIT_FAILURE" 1 2 15 + + # On Cygwin there's no "real" PIC flag so we must build both object types + case $host_os in + cygwin* | mingw* | pw32* | os2*) + pic_mode=default + ;; + esac + if test "$pic_mode" = no && test "$deplibs_check_method" != pass_all; then + # non-PIC code in shared libraries is not supported + pic_mode=default + fi + + # Calculate the filename of the output object if compiler does + # not support -o with -c + if test "$compiler_c_o" = no; then + output_obj=`$echo "X$srcfile" | $Xsed -e 's%^.*/%%' -e 's%\.[^.]*$%%'`.${objext} + lockfile="$output_obj.lock" + removelist="$removelist $output_obj $lockfile" + trap "$run $rm $removelist; exit $EXIT_FAILURE" 1 2 15 + else + output_obj= + need_locks=no + lockfile= + fi + + # Lock this critical section if it is needed + # We use this script file to make the link, it avoids creating a new file + if test "$need_locks" = yes; then + until $run ln "$progpath" "$lockfile" 2>/dev/null; do + $show "Waiting for $lockfile to be removed" + sleep 2 + done + elif test "$need_locks" = warn; then + if test -f "$lockfile"; then + $echo "\ +*** ERROR, $lockfile exists and contains: +`cat $lockfile 2>/dev/null` + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support \`-c' and \`-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $run $rm $removelist + exit $EXIT_FAILURE + fi + $echo "$srcfile" > "$lockfile" + fi + + if test -n "$fix_srcfile_path"; then + eval srcfile=\"$fix_srcfile_path\" + fi + qsrcfile=`$echo "X$srcfile" | $Xsed -e "$sed_quote_subst"` + case $qsrcfile in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + qsrcfile="\"$qsrcfile\"" ;; + esac + + $run $rm "$libobj" "${libobj}T" + + # Create a libtool object file (analogous to a ".la" file), + # but don't create it if we're doing a dry run. + test -z "$run" && cat > ${libobj}T </dev/null`" != "X$srcfile"; then + $echo "\ +*** ERROR, $lockfile contains: +`cat $lockfile 2>/dev/null` + +but it should contain: +$srcfile + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support \`-c' and \`-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $run $rm $removelist + exit $EXIT_FAILURE + fi + + # Just move the object if needed, then go on to compile the next one + if test -n "$output_obj" && test "X$output_obj" != "X$lobj"; then + $show "$mv $output_obj $lobj" + if $run $mv $output_obj $lobj; then : + else + error=$? + $run $rm $removelist + exit $error + fi + fi + + # Append the name of the PIC object to the libtool object file. + test -z "$run" && cat >> ${libobj}T <> ${libobj}T </dev/null`" != "X$srcfile"; then + $echo "\ +*** ERROR, $lockfile contains: +`cat $lockfile 2>/dev/null` + +but it should contain: +$srcfile + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support \`-c' and \`-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $run $rm $removelist + exit $EXIT_FAILURE + fi + + # Just move the object if needed + if test -n "$output_obj" && test "X$output_obj" != "X$obj"; then + $show "$mv $output_obj $obj" + if $run $mv $output_obj $obj; then : + else + error=$? + $run $rm $removelist + exit $error + fi + fi + + # Append the name of the non-PIC object the libtool object file. + # Only append if the libtool object file exists. + test -z "$run" && cat >> ${libobj}T <> ${libobj}T <&2 + fi + if test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + prefer_static_libs=yes + else + if test -z "$pic_flag" && test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + prefer_static_libs=built + fi + build_libtool_libs=no + build_old_libs=yes + break + ;; + esac + done + + # See if our shared archives depend on static archives. + test -n "$old_archive_from_new_cmds" && build_old_libs=yes + + # Go through the arguments, transforming them on the way. + while test "$#" -gt 0; do + arg="$1" + shift + case $arg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + qarg=\"`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`\" ### testsuite: skip nested quoting test + ;; + *) qarg=$arg ;; + esac + libtool_args="$libtool_args $qarg" + + # If the previous option needs an argument, assign it. + if test -n "$prev"; then + case $prev in + output) + compile_command="$compile_command @OUTPUT@" + finalize_command="$finalize_command @OUTPUT@" + ;; + esac + + case $prev in + dlfiles|dlprefiles) + if test "$preload" = no; then + # Add the symbol object into the linking commands. + compile_command="$compile_command @SYMFILE@" + finalize_command="$finalize_command @SYMFILE@" + preload=yes + fi + case $arg in + *.la | *.lo) ;; # We handle these cases below. + force) + if test "$dlself" = no; then + dlself=needless + export_dynamic=yes + fi + prev= + continue + ;; + self) + if test "$prev" = dlprefiles; then + dlself=yes + elif test "$prev" = dlfiles && test "$dlopen_self" != yes; then + dlself=yes + else + dlself=needless + export_dynamic=yes + fi + prev= + continue + ;; + *) + if test "$prev" = dlfiles; then + dlfiles="$dlfiles $arg" + else + dlprefiles="$dlprefiles $arg" + fi + prev= + continue + ;; + esac + ;; + expsyms) + export_symbols="$arg" + if test ! -f "$arg"; then + $echo "$modename: symbol file \`$arg' does not exist" + exit $EXIT_FAILURE + fi + prev= + continue + ;; + expsyms_regex) + export_symbols_regex="$arg" + prev= + continue + ;; + inst_prefix) + inst_prefix_dir="$arg" + prev= + continue + ;; + precious_regex) + precious_files_regex="$arg" + prev= + continue + ;; + release) + release="-$arg" + prev= + continue + ;; + objectlist) + if test -f "$arg"; then + save_arg=$arg + moreargs= + for fil in `cat $save_arg` + do +# moreargs="$moreargs $fil" + arg=$fil + # A libtool-controlled object. + + # Check to see that this really is a libtool object. + if (${SED} -e '2q' $arg | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then + pic_object= + non_pic_object= + + # Read the .lo file + # If there is no directory component, then add one. + case $arg in + */* | *\\*) . $arg ;; + *) . ./$arg ;; + esac + + if test -z "$pic_object" || \ + test -z "$non_pic_object" || + test "$pic_object" = none && \ + test "$non_pic_object" = none; then + $echo "$modename: cannot find name of object for \`$arg'" 1>&2 + exit $EXIT_FAILURE + fi + + # Extract subdirectory from the argument. + xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'` + if test "X$xdir" = "X$arg"; then + xdir= + else + xdir="$xdir/" + fi + + if test "$pic_object" != none; then + # Prepend the subdirectory the object is found in. + pic_object="$xdir$pic_object" + + if test "$prev" = dlfiles; then + if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then + dlfiles="$dlfiles $pic_object" + prev= + continue + else + # If libtool objects are unsupported, then we need to preload. + prev=dlprefiles + fi + fi + + # CHECK ME: I think I busted this. -Ossama + if test "$prev" = dlprefiles; then + # Preload the old-style object. + dlprefiles="$dlprefiles $pic_object" + prev= + fi + + # A PIC object. + libobjs="$libobjs $pic_object" + arg="$pic_object" + fi + + # Non-PIC object. + if test "$non_pic_object" != none; then + # Prepend the subdirectory the object is found in. + non_pic_object="$xdir$non_pic_object" + + # A standard non-PIC object + non_pic_objects="$non_pic_objects $non_pic_object" + if test -z "$pic_object" || test "$pic_object" = none ; then + arg="$non_pic_object" + fi + else + # If the PIC object exists, use it instead. + # $xdir was prepended to $pic_object above. + non_pic_object="$pic_object" + non_pic_objects="$non_pic_objects $non_pic_object" + fi + else + # Only an error if not doing a dry-run. + if test -z "$run"; then + $echo "$modename: \`$arg' is not a valid libtool object" 1>&2 + exit $EXIT_FAILURE + else + # Dry-run case. + + # Extract subdirectory from the argument. + xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'` + if test "X$xdir" = "X$arg"; then + xdir= + else + xdir="$xdir/" + fi + + pic_object=`$echo "X${xdir}${objdir}/${arg}" | $Xsed -e "$lo2o"` + non_pic_object=`$echo "X${xdir}${arg}" | $Xsed -e "$lo2o"` + libobjs="$libobjs $pic_object" + non_pic_objects="$non_pic_objects $non_pic_object" + fi + fi + done + else + $echo "$modename: link input file \`$save_arg' does not exist" + exit $EXIT_FAILURE + fi + arg=$save_arg + prev= + continue + ;; + rpath | xrpath) + # We need an absolute path. + case $arg in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + $echo "$modename: only absolute run-paths are allowed" 1>&2 + exit $EXIT_FAILURE + ;; + esac + if test "$prev" = rpath; then + case "$rpath " in + *" $arg "*) ;; + *) rpath="$rpath $arg" ;; + esac + else + case "$xrpath " in + *" $arg "*) ;; + *) xrpath="$xrpath $arg" ;; + esac + fi + prev= + continue + ;; + xcompiler) + compiler_flags="$compiler_flags $qarg" + prev= + compile_command="$compile_command $qarg" + finalize_command="$finalize_command $qarg" + continue + ;; + xlinker) + linker_flags="$linker_flags $qarg" + compiler_flags="$compiler_flags $wl$qarg" + prev= + compile_command="$compile_command $wl$qarg" + finalize_command="$finalize_command $wl$qarg" + continue + ;; + xcclinker) + linker_flags="$linker_flags $qarg" + compiler_flags="$compiler_flags $qarg" + prev= + compile_command="$compile_command $qarg" + finalize_command="$finalize_command $qarg" + continue + ;; + shrext) + shrext_cmds="$arg" + prev= + continue + ;; + darwin_framework|darwin_framework_skip) + test "$prev" = "darwin_framework" && compiler_flags="$compiler_flags $arg" + compile_command="$compile_command $arg" + finalize_command="$finalize_command $arg" + prev= + continue + ;; + *) + eval "$prev=\"\$arg\"" + prev= + continue + ;; + esac + fi # test -n "$prev" + + prevarg="$arg" + + case $arg in + -all-static) + if test -n "$link_static_flag"; then + compile_command="$compile_command $link_static_flag" + finalize_command="$finalize_command $link_static_flag" + fi + continue + ;; + + -allow-undefined) + # FIXME: remove this flag sometime in the future. + $echo "$modename: \`-allow-undefined' is deprecated because it is the default" 1>&2 + continue + ;; + + -avoid-version) + avoid_version=yes + continue + ;; + + -dlopen) + prev=dlfiles + continue + ;; + + -dlpreopen) + prev=dlprefiles + continue + ;; + + -export-dynamic) + export_dynamic=yes + continue + ;; + + -export-symbols | -export-symbols-regex) + if test -n "$export_symbols" || test -n "$export_symbols_regex"; then + $echo "$modename: more than one -exported-symbols argument is not allowed" + exit $EXIT_FAILURE + fi + if test "X$arg" = "X-export-symbols"; then + prev=expsyms + else + prev=expsyms_regex + fi + continue + ;; + + -framework|-arch|-isysroot) + case " $CC " in + *" ${arg} ${1} "* | *" ${arg} ${1} "*) + prev=darwin_framework_skip ;; + *) compiler_flags="$compiler_flags $arg" + prev=darwin_framework ;; + esac + compile_command="$compile_command $arg" + finalize_command="$finalize_command $arg" + continue + ;; + + -inst-prefix-dir) + prev=inst_prefix + continue + ;; + + # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:* + # so, if we see these flags be careful not to treat them like -L + -L[A-Z][A-Z]*:*) + case $with_gcc/$host in + no/*-*-irix* | /*-*-irix*) + compile_command="$compile_command $arg" + finalize_command="$finalize_command $arg" + ;; + esac + continue + ;; + + -L*) + dir=`$echo "X$arg" | $Xsed -e 's/^-L//'` + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + absdir=`cd "$dir" && pwd` + if test -z "$absdir"; then + $echo "$modename: cannot determine absolute directory name of \`$dir'" 1>&2 + absdir="$dir" + notinst_path="$notinst_path $dir" + fi + dir="$absdir" + ;; + esac + case "$deplibs " in + *" -L$dir "*) ;; + *) + deplibs="$deplibs -L$dir" + lib_search_path="$lib_search_path $dir" + ;; + esac + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*) + testbindir=`$echo "X$dir" | $Xsed -e 's*/lib$*/bin*'` + case :$dllsearchpath: in + *":$dir:"*) ;; + *) dllsearchpath="$dllsearchpath:$dir";; + esac + case :$dllsearchpath: in + *":$testbindir:"*) ;; + *) dllsearchpath="$dllsearchpath:$testbindir";; + esac + ;; + esac + continue + ;; + + -l*) + if test "X$arg" = "X-lc" || test "X$arg" = "X-lm"; then + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-beos*) + # These systems don't actually have a C or math library (as such) + continue + ;; + *-*-os2*) + # These systems don't actually have a C library (as such) + test "X$arg" = "X-lc" && continue + ;; + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) + # Do not include libc due to us having libc/libc_r. + test "X$arg" = "X-lc" && continue + ;; + *-*-rhapsody* | *-*-darwin1.[012]) + # Rhapsody C and math libraries are in the System framework + deplibs="$deplibs -framework System" + continue + ;; + *-*-sco3.2v5* | *-*-sco5v6*) + # Causes problems with __ctype + test "X$arg" = "X-lc" && continue + ;; + *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) + # Compiler inserts libc in the correct place for threads to work + test "X$arg" = "X-lc" && continue + ;; + esac + elif test "X$arg" = "X-lc_r"; then + case $host in + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) + # Do not include libc_r directly, use -pthread flag. + continue + ;; + esac + fi + deplibs="$deplibs $arg" + continue + ;; + + # Tru64 UNIX uses -model [arg] to determine the layout of C++ + # classes, name mangling, and exception handling. + -model) + compile_command="$compile_command $arg" + compiler_flags="$compiler_flags $arg" + finalize_command="$finalize_command $arg" + prev=xcompiler + continue + ;; + + -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe) + compiler_flags="$compiler_flags $arg" + compile_command="$compile_command $arg" + finalize_command="$finalize_command $arg" + continue + ;; + + -module) + module=yes + continue + ;; + + # -64, -mips[0-9] enable 64-bit mode on the SGI compiler + # -r[0-9][0-9]* specifies the processor on the SGI compiler + # -xarch=*, -xtarget=* enable 64-bit mode on the Sun compiler + # +DA*, +DD* enable 64-bit mode on the HP compiler + # -q* pass through compiler args for the IBM compiler + # -m* pass through architecture-specific compiler args for GCC + # -m*, -t[45]*, -txscale* pass through architecture-specific + # compiler args for GCC + # -pg pass through profiling flag for GCC + # @file GCC response files + -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*|-pg| \ + -t[45]*|-txscale*|@*) + + # Unknown arguments in both finalize_command and compile_command need + # to be aesthetically quoted because they are evaled later. + arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` + case $arg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + arg="\"$arg\"" + ;; + esac + compile_command="$compile_command $arg" + finalize_command="$finalize_command $arg" + compiler_flags="$compiler_flags $arg" + continue + ;; + + -shrext) + prev=shrext + continue + ;; + + -no-fast-install) + fast_install=no + continue + ;; + + -no-install) + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*) + # The PATH hackery in wrapper scripts is required on Windows + # in order for the loader to find any dlls it needs. + $echo "$modename: warning: \`-no-install' is ignored for $host" 1>&2 + $echo "$modename: warning: assuming \`-no-fast-install' instead" 1>&2 + fast_install=no + ;; + *) no_install=yes ;; + esac + continue + ;; + + -no-undefined) + allow_undefined=no + continue + ;; + + -objectlist) + prev=objectlist + continue + ;; + + -o) prev=output ;; + + -precious-files-regex) + prev=precious_regex + continue + ;; + + -release) + prev=release + continue + ;; + + -rpath) + prev=rpath + continue + ;; + + -R) + prev=xrpath + continue + ;; + + -R*) + dir=`$echo "X$arg" | $Xsed -e 's/^-R//'` + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + $echo "$modename: only absolute run-paths are allowed" 1>&2 + exit $EXIT_FAILURE + ;; + esac + case "$xrpath " in + *" $dir "*) ;; + *) xrpath="$xrpath $dir" ;; + esac + continue + ;; + + -static) + # The effects of -static are defined in a previous loop. + # We used to do the same as -all-static on platforms that + # didn't have a PIC flag, but the assumption that the effects + # would be equivalent was wrong. It would break on at least + # Digital Unix and AIX. + continue + ;; + + -thread-safe) + thread_safe=yes + continue + ;; + + -version-info) + prev=vinfo + continue + ;; + -version-number) + prev=vinfo + vinfo_number=yes + continue + ;; + + -Wc,*) + args=`$echo "X$arg" | $Xsed -e "$sed_quote_subst" -e 's/^-Wc,//'` + arg= + save_ifs="$IFS"; IFS=',' + for flag in $args; do + IFS="$save_ifs" + case $flag in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + flag="\"$flag\"" + ;; + esac + arg="$arg $wl$flag" + compiler_flags="$compiler_flags $flag" + done + IFS="$save_ifs" + arg=`$echo "X$arg" | $Xsed -e "s/^ //"` + ;; + + -Wl,*) + args=`$echo "X$arg" | $Xsed -e "$sed_quote_subst" -e 's/^-Wl,//'` + arg= + save_ifs="$IFS"; IFS=',' + for flag in $args; do + IFS="$save_ifs" + case $flag in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + flag="\"$flag\"" + ;; + esac + arg="$arg $wl$flag" + compiler_flags="$compiler_flags $wl$flag" + linker_flags="$linker_flags $flag" + done + IFS="$save_ifs" + arg=`$echo "X$arg" | $Xsed -e "s/^ //"` + ;; + + -Xcompiler) + prev=xcompiler + continue + ;; + + -Xlinker) + prev=xlinker + continue + ;; + + -XCClinker) + prev=xcclinker + continue + ;; + + # Some other compiler flag. + -* | +*) + # Unknown arguments in both finalize_command and compile_command need + # to be aesthetically quoted because they are evaled later. + arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` + case $arg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + arg="\"$arg\"" + ;; + esac + ;; + + *.$objext) + # A standard object. + objs="$objs $arg" + ;; + + *.lo) + # A libtool-controlled object. + + # Check to see that this really is a libtool object. + if (${SED} -e '2q' $arg | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then + pic_object= + non_pic_object= + + # Read the .lo file + # If there is no directory component, then add one. + case $arg in + */* | *\\*) . $arg ;; + *) . ./$arg ;; + esac + + if test -z "$pic_object" || \ + test -z "$non_pic_object" || + test "$pic_object" = none && \ + test "$non_pic_object" = none; then + $echo "$modename: cannot find name of object for \`$arg'" 1>&2 + exit $EXIT_FAILURE + fi + + # Extract subdirectory from the argument. + xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'` + if test "X$xdir" = "X$arg"; then + xdir= + else + xdir="$xdir/" + fi + + if test "$pic_object" != none; then + # Prepend the subdirectory the object is found in. + pic_object="$xdir$pic_object" + + if test "$prev" = dlfiles; then + if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then + dlfiles="$dlfiles $pic_object" + prev= + continue + else + # If libtool objects are unsupported, then we need to preload. + prev=dlprefiles + fi + fi + + # CHECK ME: I think I busted this. -Ossama + if test "$prev" = dlprefiles; then + # Preload the old-style object. + dlprefiles="$dlprefiles $pic_object" + prev= + fi + + # A PIC object. + libobjs="$libobjs $pic_object" + arg="$pic_object" + fi + + # Non-PIC object. + if test "$non_pic_object" != none; then + # Prepend the subdirectory the object is found in. + non_pic_object="$xdir$non_pic_object" + + # A standard non-PIC object + non_pic_objects="$non_pic_objects $non_pic_object" + if test -z "$pic_object" || test "$pic_object" = none ; then + arg="$non_pic_object" + fi + else + # If the PIC object exists, use it instead. + # $xdir was prepended to $pic_object above. + non_pic_object="$pic_object" + non_pic_objects="$non_pic_objects $non_pic_object" + fi + else + # Only an error if not doing a dry-run. + if test -z "$run"; then + $echo "$modename: \`$arg' is not a valid libtool object" 1>&2 + exit $EXIT_FAILURE + else + # Dry-run case. + + # Extract subdirectory from the argument. + xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'` + if test "X$xdir" = "X$arg"; then + xdir= + else + xdir="$xdir/" + fi + + pic_object=`$echo "X${xdir}${objdir}/${arg}" | $Xsed -e "$lo2o"` + non_pic_object=`$echo "X${xdir}${arg}" | $Xsed -e "$lo2o"` + libobjs="$libobjs $pic_object" + non_pic_objects="$non_pic_objects $non_pic_object" + fi + fi + ;; + + *.$libext) + # An archive. + deplibs="$deplibs $arg" + old_deplibs="$old_deplibs $arg" + continue + ;; + + *.la) + # A libtool-controlled library. + + if test "$prev" = dlfiles; then + # This library was specified with -dlopen. + dlfiles="$dlfiles $arg" + prev= + elif test "$prev" = dlprefiles; then + # The library was specified with -dlpreopen. + dlprefiles="$dlprefiles $arg" + prev= + else + deplibs="$deplibs $arg" + fi + continue + ;; + + # Some other compiler argument. + *) + # Unknown arguments in both finalize_command and compile_command need + # to be aesthetically quoted because they are evaled later. + arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` + case $arg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + arg="\"$arg\"" + ;; + esac + ;; + esac # arg + + # Now actually substitute the argument into the commands. + if test -n "$arg"; then + compile_command="$compile_command $arg" + finalize_command="$finalize_command $arg" + fi + done # argument parsing loop + + if test -n "$prev"; then + $echo "$modename: the \`$prevarg' option requires an argument" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + + if test "$export_dynamic" = yes && test -n "$export_dynamic_flag_spec"; then + eval arg=\"$export_dynamic_flag_spec\" + compile_command="$compile_command $arg" + finalize_command="$finalize_command $arg" + fi + + oldlibs= + # calculate the name of the file, without its directory + outputname=`$echo "X$output" | $Xsed -e 's%^.*/%%'` + libobjs_save="$libobjs" + + if test -n "$shlibpath_var"; then + # get the directories listed in $shlibpath_var + eval shlib_search_path=\`\$echo \"X\${$shlibpath_var}\" \| \$Xsed -e \'s/:/ /g\'\` + else + shlib_search_path= + fi + eval sys_lib_search_path=\"$sys_lib_search_path_spec\" + eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\" + + output_objdir=`$echo "X$output" | $Xsed -e 's%/[^/]*$%%'` + if test "X$output_objdir" = "X$output"; then + output_objdir="$objdir" + else + output_objdir="$output_objdir/$objdir" + fi + # Create the object directory. + if test ! -d "$output_objdir"; then + $show "$mkdir $output_objdir" + $run $mkdir $output_objdir + exit_status=$? + if test "$exit_status" -ne 0 && test ! -d "$output_objdir"; then + exit $exit_status + fi + fi + + # Determine the type of output + case $output in + "") + $echo "$modename: you must specify an output file" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + ;; + *.$libext) linkmode=oldlib ;; + *.lo | *.$objext) linkmode=obj ;; + *.la) linkmode=lib ;; + *) linkmode=prog ;; # Anything else should be a program. + esac + + case $host in + *cygwin* | *mingw* | *pw32*) + # don't eliminate duplications in $postdeps and $predeps + duplicate_compiler_generated_deps=yes + ;; + *) + duplicate_compiler_generated_deps=$duplicate_deps + ;; + esac + specialdeplibs= + + libs= + # Find all interdependent deplibs by searching for libraries + # that are linked more than once (e.g. -la -lb -la) + for deplib in $deplibs; do + if test "X$duplicate_deps" = "Xyes" ; then + case "$libs " in + *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; + esac + fi + libs="$libs $deplib" + done + + if test "$linkmode" = lib; then + libs="$predeps $libs $compiler_lib_search_path $postdeps" + + # Compute libraries that are listed more than once in $predeps + # $postdeps and mark them as special (i.e., whose duplicates are + # not to be eliminated). + pre_post_deps= + if test "X$duplicate_compiler_generated_deps" = "Xyes" ; then + for pre_post_dep in $predeps $postdeps; do + case "$pre_post_deps " in + *" $pre_post_dep "*) specialdeplibs="$specialdeplibs $pre_post_deps" ;; + esac + pre_post_deps="$pre_post_deps $pre_post_dep" + done + fi + pre_post_deps= + fi + + deplibs= + newdependency_libs= + newlib_search_path= + need_relink=no # whether we're linking any uninstalled libtool libraries + notinst_deplibs= # not-installed libtool libraries + case $linkmode in + lib) + passes="conv link" + for file in $dlfiles $dlprefiles; do + case $file in + *.la) ;; + *) + $echo "$modename: libraries can \`-dlopen' only libtool libraries: $file" 1>&2 + exit $EXIT_FAILURE + ;; + esac + done + ;; + prog) + compile_deplibs= + finalize_deplibs= + alldeplibs=no + newdlfiles= + newdlprefiles= + passes="conv scan dlopen dlpreopen link" + ;; + *) passes="conv" + ;; + esac + for pass in $passes; do + if test "$linkmode,$pass" = "lib,link" || + test "$linkmode,$pass" = "prog,scan"; then + libs="$deplibs" + deplibs= + fi + if test "$linkmode" = prog; then + case $pass in + dlopen) libs="$dlfiles" ;; + dlpreopen) libs="$dlprefiles" ;; + link) libs="$deplibs %DEPLIBS% $dependency_libs" ;; + esac + fi + if test "$pass" = dlopen; then + # Collect dlpreopened libraries + save_deplibs="$deplibs" + deplibs= + fi + for deplib in $libs; do + lib= + found=no + case $deplib in + -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe) + if test "$linkmode,$pass" = "prog,link"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + compiler_flags="$compiler_flags $deplib" + fi + continue + ;; + -l*) + if test "$linkmode" != lib && test "$linkmode" != prog; then + $echo "$modename: warning: \`-l' is ignored for archives/objects" 1>&2 + continue + fi + name=`$echo "X$deplib" | $Xsed -e 's/^-l//'` + for searchdir in $newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path; do + for search_ext in .la $std_shrext .so .a; do + # Search the libtool library + lib="$searchdir/lib${name}${search_ext}" + if test -f "$lib"; then + if test "$search_ext" = ".la"; then + found=yes + else + found=no + fi + break 2 + fi + done + done + if test "$found" != yes; then + # deplib doesn't seem to be a libtool library + if test "$linkmode,$pass" = "prog,link"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + deplibs="$deplib $deplibs" + test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs" + fi + continue + else # deplib is a libtool library + # If $allow_libtool_libs_with_static_runtimes && $deplib is a stdlib, + # We need to do some special things here, and not later. + if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then + case " $predeps $postdeps " in + *" $deplib "*) + if (${SED} -e '2q' $lib | + grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then + library_names= + old_library= + case $lib in + */* | *\\*) . $lib ;; + *) . ./$lib ;; + esac + for l in $old_library $library_names; do + ll="$l" + done + if test "X$ll" = "X$old_library" ; then # only static version available + found=no + ladir=`$echo "X$lib" | $Xsed -e 's%/[^/]*$%%'` + test "X$ladir" = "X$lib" && ladir="." + lib=$ladir/$old_library + if test "$linkmode,$pass" = "prog,link"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + deplibs="$deplib $deplibs" + test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs" + fi + continue + fi + fi + ;; + *) ;; + esac + fi + fi + ;; # -l + -L*) + case $linkmode in + lib) + deplibs="$deplib $deplibs" + test "$pass" = conv && continue + newdependency_libs="$deplib $newdependency_libs" + newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'` + ;; + prog) + if test "$pass" = conv; then + deplibs="$deplib $deplibs" + continue + fi + if test "$pass" = scan; then + deplibs="$deplib $deplibs" + else + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + fi + newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'` + ;; + *) + $echo "$modename: warning: \`-L' is ignored for archives/objects" 1>&2 + ;; + esac # linkmode + continue + ;; # -L + -R*) + if test "$pass" = link; then + dir=`$echo "X$deplib" | $Xsed -e 's/^-R//'` + # Make sure the xrpath contains only unique directories. + case "$xrpath " in + *" $dir "*) ;; + *) xrpath="$xrpath $dir" ;; + esac + fi + deplibs="$deplib $deplibs" + continue + ;; + *.la) lib="$deplib" ;; + *.$libext) + if test "$pass" = conv; then + deplibs="$deplib $deplibs" + continue + fi + case $linkmode in + lib) + valid_a_lib=no + case $deplibs_check_method in + match_pattern*) + set dummy $deplibs_check_method + match_pattern_regex=`expr "$deplibs_check_method" : "$2 \(.*\)"` + if eval $echo \"$deplib\" 2>/dev/null \ + | $SED 10q \ + | $EGREP "$match_pattern_regex" > /dev/null; then + valid_a_lib=yes + fi + ;; + pass_all) + valid_a_lib=yes + ;; + esac + if test "$valid_a_lib" != yes; then + $echo + $echo "*** Warning: Trying to link with static lib archive $deplib." + $echo "*** I have the capability to make that library automatically link in when" + $echo "*** you link to this library. But I can only do this if you have a" + $echo "*** shared version of the library, which you do not appear to have" + $echo "*** because the file extensions .$libext of this argument makes me believe" + $echo "*** that it is just a static archive that I should not used here." + else + $echo + $echo "*** Warning: Linking the shared library $output against the" + $echo "*** static library $deplib is not portable!" + deplibs="$deplib $deplibs" + fi + continue + ;; + prog) + if test "$pass" != link; then + deplibs="$deplib $deplibs" + else + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + fi + continue + ;; + esac # linkmode + ;; # *.$libext + *.lo | *.$objext) + if test "$pass" = conv; then + deplibs="$deplib $deplibs" + elif test "$linkmode" = prog; then + if test "$pass" = dlpreopen || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then + # If there is no dlopen support or we're linking statically, + # we need to preload. + newdlprefiles="$newdlprefiles $deplib" + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + newdlfiles="$newdlfiles $deplib" + fi + fi + continue + ;; + %DEPLIBS%) + alldeplibs=yes + continue + ;; + esac # case $deplib + if test "$found" = yes || test -f "$lib"; then : + else + $echo "$modename: cannot find the library \`$lib' or unhandled argument \`$deplib'" 1>&2 + exit $EXIT_FAILURE + fi + + # Check to see that this really is a libtool archive. + if (${SED} -e '2q' $lib | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then : + else + $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2 + exit $EXIT_FAILURE + fi + + ladir=`$echo "X$lib" | $Xsed -e 's%/[^/]*$%%'` + test "X$ladir" = "X$lib" && ladir="." + + dlname= + dlopen= + dlpreopen= + libdir= + library_names= + old_library= + # If the library was installed with an old release of libtool, + # it will not redefine variables installed, or shouldnotlink + installed=yes + shouldnotlink=no + avoidtemprpath= + + + # Read the .la file + case $lib in + */* | *\\*) . $lib ;; + *) . ./$lib ;; + esac + + if test "$linkmode,$pass" = "lib,link" || + test "$linkmode,$pass" = "prog,scan" || + { test "$linkmode" != prog && test "$linkmode" != lib; }; then + test -n "$dlopen" && dlfiles="$dlfiles $dlopen" + test -n "$dlpreopen" && dlprefiles="$dlprefiles $dlpreopen" + fi + + if test "$pass" = conv; then + # Only check for convenience libraries + deplibs="$lib $deplibs" + if test -z "$libdir"; then + if test -z "$old_library"; then + $echo "$modename: cannot find name of link library for \`$lib'" 1>&2 + exit $EXIT_FAILURE + fi + # It is a libtool convenience library, so add in its objects. + convenience="$convenience $ladir/$objdir/$old_library" + old_convenience="$old_convenience $ladir/$objdir/$old_library" + tmp_libs= + for deplib in $dependency_libs; do + deplibs="$deplib $deplibs" + if test "X$duplicate_deps" = "Xyes" ; then + case "$tmp_libs " in + *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; + esac + fi + tmp_libs="$tmp_libs $deplib" + done + elif test "$linkmode" != prog && test "$linkmode" != lib; then + $echo "$modename: \`$lib' is not a convenience library" 1>&2 + exit $EXIT_FAILURE + fi + continue + fi # $pass = conv + + + # Get the name of the library we link against. + linklib= + for l in $old_library $library_names; do + linklib="$l" + done + if test -z "$linklib"; then + $echo "$modename: cannot find name of link library for \`$lib'" 1>&2 + exit $EXIT_FAILURE + fi + + # This library was specified with -dlopen. + if test "$pass" = dlopen; then + if test -z "$libdir"; then + $echo "$modename: cannot -dlopen a convenience library: \`$lib'" 1>&2 + exit $EXIT_FAILURE + fi + if test -z "$dlname" || + test "$dlopen_support" != yes || + test "$build_libtool_libs" = no; then + # If there is no dlname, no dlopen support or we're linking + # statically, we need to preload. We also need to preload any + # dependent libraries so libltdl's deplib preloader doesn't + # bomb out in the load deplibs phase. + dlprefiles="$dlprefiles $lib $dependency_libs" + else + newdlfiles="$newdlfiles $lib" + fi + continue + fi # $pass = dlopen + + # We need an absolute path. + case $ladir in + [\\/]* | [A-Za-z]:[\\/]*) abs_ladir="$ladir" ;; + *) + abs_ladir=`cd "$ladir" && pwd` + if test -z "$abs_ladir"; then + $echo "$modename: warning: cannot determine absolute directory name of \`$ladir'" 1>&2 + $echo "$modename: passing it literally to the linker, although it might fail" 1>&2 + abs_ladir="$ladir" + fi + ;; + esac + laname=`$echo "X$lib" | $Xsed -e 's%^.*/%%'` + + # Find the relevant object directory and library name. + if test "X$installed" = Xyes; then + if test ! -f "$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then + $echo "$modename: warning: library \`$lib' was moved." 1>&2 + dir="$ladir" + absdir="$abs_ladir" + libdir="$abs_ladir" + else + dir="$libdir" + absdir="$libdir" + fi + test "X$hardcode_automatic" = Xyes && avoidtemprpath=yes + else + if test ! -f "$ladir/$objdir/$linklib" && test -f "$abs_ladir/$linklib"; then + dir="$ladir" + absdir="$abs_ladir" + # Remove this search path later + notinst_path="$notinst_path $abs_ladir" + else + dir="$ladir/$objdir" + absdir="$abs_ladir/$objdir" + # Remove this search path later + notinst_path="$notinst_path $abs_ladir" + fi + fi # $installed = yes + name=`$echo "X$laname" | $Xsed -e 's/\.la$//' -e 's/^lib//'` + + # This library was specified with -dlpreopen. + if test "$pass" = dlpreopen; then + if test -z "$libdir"; then + $echo "$modename: cannot -dlpreopen a convenience library: \`$lib'" 1>&2 + exit $EXIT_FAILURE + fi + # Prefer using a static library (so that no silly _DYNAMIC symbols + # are required to link). + if test -n "$old_library"; then + newdlprefiles="$newdlprefiles $dir/$old_library" + # Otherwise, use the dlname, so that lt_dlopen finds it. + elif test -n "$dlname"; then + newdlprefiles="$newdlprefiles $dir/$dlname" + else + newdlprefiles="$newdlprefiles $dir/$linklib" + fi + fi # $pass = dlpreopen + + if test -z "$libdir"; then + # Link the convenience library + if test "$linkmode" = lib; then + deplibs="$dir/$old_library $deplibs" + elif test "$linkmode,$pass" = "prog,link"; then + compile_deplibs="$dir/$old_library $compile_deplibs" + finalize_deplibs="$dir/$old_library $finalize_deplibs" + else + deplibs="$lib $deplibs" # used for prog,scan pass + fi + continue + fi + + + if test "$linkmode" = prog && test "$pass" != link; then + newlib_search_path="$newlib_search_path $ladir" + deplibs="$lib $deplibs" + + linkalldeplibs=no + if test "$link_all_deplibs" != no || test -z "$library_names" || + test "$build_libtool_libs" = no; then + linkalldeplibs=yes + fi + + tmp_libs= + for deplib in $dependency_libs; do + case $deplib in + -L*) newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'`;; ### testsuite: skip nested quoting test + esac + # Need to link against all dependency_libs? + if test "$linkalldeplibs" = yes; then + deplibs="$deplib $deplibs" + else + # Need to hardcode shared library paths + # or/and link against static libraries + newdependency_libs="$deplib $newdependency_libs" + fi + if test "X$duplicate_deps" = "Xyes" ; then + case "$tmp_libs " in + *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; + esac + fi + tmp_libs="$tmp_libs $deplib" + done # for deplib + continue + fi # $linkmode = prog... + + if test "$linkmode,$pass" = "prog,link"; then + if test -n "$library_names" && + { test "$prefer_static_libs" = no || test -z "$old_library"; }; then + # We need to hardcode the library path + if test -n "$shlibpath_var" && test -z "$avoidtemprpath" ; then + # Make sure the rpath contains only unique directories. + case "$temp_rpath " in + *" $dir "*) ;; + *" $absdir "*) ;; + *) temp_rpath="$temp_rpath $absdir" ;; + esac + fi + + # Hardcode the library path. + # Skip directories that are in the system default run-time + # search path. + case " $sys_lib_dlsearch_path " in + *" $absdir "*) ;; + *) + case "$compile_rpath " in + *" $absdir "*) ;; + *) compile_rpath="$compile_rpath $absdir" + esac + ;; + esac + case " $sys_lib_dlsearch_path " in + *" $libdir "*) ;; + *) + case "$finalize_rpath " in + *" $libdir "*) ;; + *) finalize_rpath="$finalize_rpath $libdir" + esac + ;; + esac + fi # $linkmode,$pass = prog,link... + + if test "$alldeplibs" = yes && + { test "$deplibs_check_method" = pass_all || + { test "$build_libtool_libs" = yes && + test -n "$library_names"; }; }; then + # We only need to search for static libraries + continue + fi + fi + + link_static=no # Whether the deplib will be linked statically + use_static_libs=$prefer_static_libs + if test "$use_static_libs" = built && test "$installed" = yes ; then + use_static_libs=no + fi + if test -n "$library_names" && + { test "$use_static_libs" = no || test -z "$old_library"; }; then + if test "$installed" = no; then + notinst_deplibs="$notinst_deplibs $lib" + need_relink=yes + fi + # This is a shared library + + # Warn about portability, can't link against -module's on + # some systems (darwin) + if test "$shouldnotlink" = yes && test "$pass" = link ; then + $echo + if test "$linkmode" = prog; then + $echo "*** Warning: Linking the executable $output against the loadable module" + else + $echo "*** Warning: Linking the shared library $output against the loadable module" + fi + $echo "*** $linklib is not portable!" + fi + if test "$linkmode" = lib && + test "$hardcode_into_libs" = yes; then + # Hardcode the library path. + # Skip directories that are in the system default run-time + # search path. + case " $sys_lib_dlsearch_path " in + *" $absdir "*) ;; + *) + case "$compile_rpath " in + *" $absdir "*) ;; + *) compile_rpath="$compile_rpath $absdir" + esac + ;; + esac + case " $sys_lib_dlsearch_path " in + *" $libdir "*) ;; + *) + case "$finalize_rpath " in + *" $libdir "*) ;; + *) finalize_rpath="$finalize_rpath $libdir" + esac + ;; + esac + fi + + if test -n "$old_archive_from_expsyms_cmds"; then + # figure out the soname + set dummy $library_names + realname="$2" + shift; shift + libname=`eval \\$echo \"$libname_spec\"` + # use dlname if we got it. it's perfectly good, no? + if test -n "$dlname"; then + soname="$dlname" + elif test -n "$soname_spec"; then + # bleh windows + case $host in + *cygwin* | mingw*) + major=`expr $current - $age` + versuffix="-$major" + ;; + esac + eval soname=\"$soname_spec\" + else + soname="$realname" + fi + + # Make a new name for the extract_expsyms_cmds to use + soroot="$soname" + soname=`$echo $soroot | ${SED} -e 's/^.*\///'` + newlib="libimp-`$echo $soname | ${SED} 's/^lib//;s/\.dll$//'`.a" + + # If the library has no export list, then create one now + if test -f "$output_objdir/$soname-def"; then : + else + $show "extracting exported symbol list from \`$soname'" + save_ifs="$IFS"; IFS='~' + cmds=$extract_expsyms_cmds + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + fi + + # Create $newlib + if test -f "$output_objdir/$newlib"; then :; else + $show "generating import library for \`$soname'" + save_ifs="$IFS"; IFS='~' + cmds=$old_archive_from_expsyms_cmds + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + fi + # make sure the library variables are pointing to the new library + dir=$output_objdir + linklib=$newlib + fi # test -n "$old_archive_from_expsyms_cmds" + + if test "$linkmode" = prog || test "$mode" != relink; then + add_shlibpath= + add_dir= + add= + lib_linked=yes + case $hardcode_action in + immediate | unsupported) + if test "$hardcode_direct" = no; then + add="$dir/$linklib" + case $host in + *-*-sco3.2v5.0.[024]*) add_dir="-L$dir" ;; + *-*-sysv4*uw2*) add_dir="-L$dir" ;; + *-*-sysv5OpenUNIX* | *-*-sysv5UnixWare7.[01].[10]* | \ + *-*-unixware7*) add_dir="-L$dir" ;; + *-*-darwin* ) + # if the lib is a module then we can not link against + # it, someone is ignoring the new warnings I added + if /usr/bin/file -L $add 2> /dev/null | + $EGREP ": [^:]* bundle" >/dev/null ; then + $echo "** Warning, lib $linklib is a module, not a shared library" + if test -z "$old_library" ; then + $echo + $echo "** And there doesn't seem to be a static archive available" + $echo "** The link will probably fail, sorry" + else + add="$dir/$old_library" + fi + fi + esac + elif test "$hardcode_minus_L" = no; then + case $host in + *-*-sunos*) add_shlibpath="$dir" ;; + esac + add_dir="-L$dir" + add="-l$name" + elif test "$hardcode_shlibpath_var" = no; then + add_shlibpath="$dir" + add="-l$name" + else + lib_linked=no + fi + ;; + relink) + if test "$hardcode_direct" = yes; then + add="$dir/$linklib" + elif test "$hardcode_minus_L" = yes; then + add_dir="-L$dir" + # Try looking first in the location we're being installed to. + if test -n "$inst_prefix_dir"; then + case $libdir in + [\\/]*) + add_dir="$add_dir -L$inst_prefix_dir$libdir" + ;; + esac + fi + add="-l$name" + elif test "$hardcode_shlibpath_var" = yes; then + add_shlibpath="$dir" + add="-l$name" + else + lib_linked=no + fi + ;; + *) lib_linked=no ;; + esac + + if test "$lib_linked" != yes; then + $echo "$modename: configuration error: unsupported hardcode properties" + exit $EXIT_FAILURE + fi + + if test -n "$add_shlibpath"; then + case :$compile_shlibpath: in + *":$add_shlibpath:"*) ;; + *) compile_shlibpath="$compile_shlibpath$add_shlibpath:" ;; + esac + fi + if test "$linkmode" = prog; then + test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs" + test -n "$add" && compile_deplibs="$add $compile_deplibs" + else + test -n "$add_dir" && deplibs="$add_dir $deplibs" + test -n "$add" && deplibs="$add $deplibs" + if test "$hardcode_direct" != yes && \ + test "$hardcode_minus_L" != yes && \ + test "$hardcode_shlibpath_var" = yes; then + case :$finalize_shlibpath: in + *":$libdir:"*) ;; + *) finalize_shlibpath="$finalize_shlibpath$libdir:" ;; + esac + fi + fi + fi + + if test "$linkmode" = prog || test "$mode" = relink; then + add_shlibpath= + add_dir= + add= + # Finalize command for both is simple: just hardcode it. + if test "$hardcode_direct" = yes; then + add="$libdir/$linklib" + elif test "$hardcode_minus_L" = yes; then + add_dir="-L$libdir" + add="-l$name" + elif test "$hardcode_shlibpath_var" = yes; then + case :$finalize_shlibpath: in + *":$libdir:"*) ;; + *) finalize_shlibpath="$finalize_shlibpath$libdir:" ;; + esac + add="-l$name" + elif test "$hardcode_automatic" = yes; then + if test -n "$inst_prefix_dir" && + test -f "$inst_prefix_dir$libdir/$linklib" ; then + add="$inst_prefix_dir$libdir/$linklib" + else + add="$libdir/$linklib" + fi + else + # We cannot seem to hardcode it, guess we'll fake it. + add_dir="-L$libdir" + # Try looking first in the location we're being installed to. + if test -n "$inst_prefix_dir"; then + case $libdir in + [\\/]*) + add_dir="$add_dir -L$inst_prefix_dir$libdir" + ;; + esac + fi + add="-l$name" + fi + + if test "$linkmode" = prog; then + test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs" + test -n "$add" && finalize_deplibs="$add $finalize_deplibs" + else + test -n "$add_dir" && deplibs="$add_dir $deplibs" + test -n "$add" && deplibs="$add $deplibs" + fi + fi + elif test "$linkmode" = prog; then + # Here we assume that one of hardcode_direct or hardcode_minus_L + # is not unsupported. This is valid on all known static and + # shared platforms. + if test "$hardcode_direct" != unsupported; then + test -n "$old_library" && linklib="$old_library" + compile_deplibs="$dir/$linklib $compile_deplibs" + finalize_deplibs="$dir/$linklib $finalize_deplibs" + else + compile_deplibs="-l$name -L$dir $compile_deplibs" + finalize_deplibs="-l$name -L$dir $finalize_deplibs" + fi + elif test "$build_libtool_libs" = yes; then + # Not a shared library + if test "$deplibs_check_method" != pass_all; then + # We're trying link a shared library against a static one + # but the system doesn't support it. + + # Just print a warning and add the library to dependency_libs so + # that the program can be linked against the static library. + $echo + $echo "*** Warning: This system can not link to static lib archive $lib." + $echo "*** I have the capability to make that library automatically link in when" + $echo "*** you link to this library. But I can only do this if you have a" + $echo "*** shared version of the library, which you do not appear to have." + if test "$module" = yes; then + $echo "*** But as you try to build a module library, libtool will still create " + $echo "*** a static module, that should work as long as the dlopening application" + $echo "*** is linked with the -dlopen flag to resolve symbols at runtime." + if test -z "$global_symbol_pipe"; then + $echo + $echo "*** However, this would only work if libtool was able to extract symbol" + $echo "*** lists from a program, using \`nm' or equivalent, but libtool could" + $echo "*** not find such a program. So, this module is probably useless." + $echo "*** \`nm' from GNU binutils and a full rebuild may help." + fi + if test "$build_old_libs" = no; then + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + fi + else + deplibs="$dir/$old_library $deplibs" + link_static=yes + fi + fi # link shared/static library? + + if test "$linkmode" = lib; then + if test -n "$dependency_libs" && + { test "$hardcode_into_libs" != yes || + test "$build_old_libs" = yes || + test "$link_static" = yes; }; then + # Extract -R from dependency_libs + temp_deplibs= + for libdir in $dependency_libs; do + case $libdir in + -R*) temp_xrpath=`$echo "X$libdir" | $Xsed -e 's/^-R//'` + case " $xrpath " in + *" $temp_xrpath "*) ;; + *) xrpath="$xrpath $temp_xrpath";; + esac;; + *) temp_deplibs="$temp_deplibs $libdir";; + esac + done + dependency_libs="$temp_deplibs" + fi + + newlib_search_path="$newlib_search_path $absdir" + # Link against this library + test "$link_static" = no && newdependency_libs="$abs_ladir/$laname $newdependency_libs" + # ... and its dependency_libs + tmp_libs= + for deplib in $dependency_libs; do + newdependency_libs="$deplib $newdependency_libs" + if test "X$duplicate_deps" = "Xyes" ; then + case "$tmp_libs " in + *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; + esac + fi + tmp_libs="$tmp_libs $deplib" + done + + if test "$link_all_deplibs" != no; then + # Add the search paths of all dependency libraries + for deplib in $dependency_libs; do + case $deplib in + -L*) path="$deplib" ;; + *.la) + dir=`$echo "X$deplib" | $Xsed -e 's%/[^/]*$%%'` + test "X$dir" = "X$deplib" && dir="." + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) absdir="$dir" ;; + *) + absdir=`cd "$dir" && pwd` + if test -z "$absdir"; then + $echo "$modename: warning: cannot determine absolute directory name of \`$dir'" 1>&2 + absdir="$dir" + fi + ;; + esac + if grep "^installed=no" $deplib > /dev/null; then + path="$absdir/$objdir" + else + eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` + if test -z "$libdir"; then + $echo "$modename: \`$deplib' is not a valid libtool archive" 1>&2 + exit $EXIT_FAILURE + fi + if test "$absdir" != "$libdir"; then + $echo "$modename: warning: \`$deplib' seems to be moved" 1>&2 + fi + path="$absdir" + fi + depdepl= + case $host in + *-*-darwin*) + # we do not want to link against static libs, + # but need to link against shared + eval deplibrary_names=`${SED} -n -e 's/^library_names=\(.*\)$/\1/p' $deplib` + if test -n "$deplibrary_names" ; then + for tmp in $deplibrary_names ; do + depdepl=$tmp + done + if test -f "$path/$depdepl" ; then + depdepl="$path/$depdepl" + fi + # do not add paths which are already there + case " $newlib_search_path " in + *" $path "*) ;; + *) newlib_search_path="$newlib_search_path $path";; + esac + fi + path="" + ;; + *) + path="-L$path" + ;; + esac + ;; + -l*) + case $host in + *-*-darwin*) + # Again, we only want to link against shared libraries + eval tmp_libs=`$echo "X$deplib" | $Xsed -e "s,^\-l,,"` + for tmp in $newlib_search_path ; do + if test -f "$tmp/lib$tmp_libs.dylib" ; then + eval depdepl="$tmp/lib$tmp_libs.dylib" + break + fi + done + path="" + ;; + *) continue ;; + esac + ;; + *) continue ;; + esac + case " $deplibs " in + *" $path "*) ;; + *) deplibs="$path $deplibs" ;; + esac + case " $deplibs " in + *" $depdepl "*) ;; + *) deplibs="$depdepl $deplibs" ;; + esac + done + fi # link_all_deplibs != no + fi # linkmode = lib + done # for deplib in $libs + dependency_libs="$newdependency_libs" + if test "$pass" = dlpreopen; then + # Link the dlpreopened libraries before other libraries + for deplib in $save_deplibs; do + deplibs="$deplib $deplibs" + done + fi + if test "$pass" != dlopen; then + if test "$pass" != conv; then + # Make sure lib_search_path contains only unique directories. + lib_search_path= + for dir in $newlib_search_path; do + case "$lib_search_path " in + *" $dir "*) ;; + *) lib_search_path="$lib_search_path $dir" ;; + esac + done + newlib_search_path= + fi + + if test "$linkmode,$pass" != "prog,link"; then + vars="deplibs" + else + vars="compile_deplibs finalize_deplibs" + fi + for var in $vars dependency_libs; do + # Add libraries to $var in reverse order + eval tmp_libs=\"\$$var\" + new_libs= + for deplib in $tmp_libs; do + # FIXME: Pedantically, this is the right thing to do, so + # that some nasty dependency loop isn't accidentally + # broken: + #new_libs="$deplib $new_libs" + # Pragmatically, this seems to cause very few problems in + # practice: + case $deplib in + -L*) new_libs="$deplib $new_libs" ;; + -R*) ;; + *) + # And here is the reason: when a library appears more + # than once as an explicit dependence of a library, or + # is implicitly linked in more than once by the + # compiler, it is considered special, and multiple + # occurrences thereof are not removed. Compare this + # with having the same library being listed as a + # dependency of multiple other libraries: in this case, + # we know (pedantically, we assume) the library does not + # need to be listed more than once, so we keep only the + # last copy. This is not always right, but it is rare + # enough that we require users that really mean to play + # such unportable linking tricks to link the library + # using -Wl,-lname, so that libtool does not consider it + # for duplicate removal. + case " $specialdeplibs " in + *" $deplib "*) new_libs="$deplib $new_libs" ;; + *) + case " $new_libs " in + *" $deplib "*) ;; + *) new_libs="$deplib $new_libs" ;; + esac + ;; + esac + ;; + esac + done + tmp_libs= + for deplib in $new_libs; do + case $deplib in + -L*) + case " $tmp_libs " in + *" $deplib "*) ;; + *) tmp_libs="$tmp_libs $deplib" ;; + esac + ;; + *) tmp_libs="$tmp_libs $deplib" ;; + esac + done + eval $var=\"$tmp_libs\" + done # for var + fi + # Last step: remove runtime libs from dependency_libs + # (they stay in deplibs) + tmp_libs= + for i in $dependency_libs ; do + case " $predeps $postdeps $compiler_lib_search_path " in + *" $i "*) + i="" + ;; + esac + if test -n "$i" ; then + tmp_libs="$tmp_libs $i" + fi + done + dependency_libs=$tmp_libs + done # for pass + if test "$linkmode" = prog; then + dlfiles="$newdlfiles" + dlprefiles="$newdlprefiles" + fi + + case $linkmode in + oldlib) + if test -n "$deplibs"; then + $echo "$modename: warning: \`-l' and \`-L' are ignored for archives" 1>&2 + fi + + if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then + $echo "$modename: warning: \`-dlopen' is ignored for archives" 1>&2 + fi + + if test -n "$rpath"; then + $echo "$modename: warning: \`-rpath' is ignored for archives" 1>&2 + fi + + if test -n "$xrpath"; then + $echo "$modename: warning: \`-R' is ignored for archives" 1>&2 + fi + + if test -n "$vinfo"; then + $echo "$modename: warning: \`-version-info/-version-number' is ignored for archives" 1>&2 + fi + + if test -n "$release"; then + $echo "$modename: warning: \`-release' is ignored for archives" 1>&2 + fi + + if test -n "$export_symbols" || test -n "$export_symbols_regex"; then + $echo "$modename: warning: \`-export-symbols' is ignored for archives" 1>&2 + fi + + # Now set the variables for building old libraries. + build_libtool_libs=no + oldlibs="$output" + objs="$objs$old_deplibs" + ;; + + lib) + # Make sure we only generate libraries of the form `libNAME.la'. + case $outputname in + lib*) + name=`$echo "X$outputname" | $Xsed -e 's/\.la$//' -e 's/^lib//'` + eval shared_ext=\"$shrext_cmds\" + eval libname=\"$libname_spec\" + ;; + *) + if test "$module" = no; then + $echo "$modename: libtool library \`$output' must begin with \`lib'" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + if test "$need_lib_prefix" != no; then + # Add the "lib" prefix for modules if required + name=`$echo "X$outputname" | $Xsed -e 's/\.la$//'` + eval shared_ext=\"$shrext_cmds\" + eval libname=\"$libname_spec\" + else + libname=`$echo "X$outputname" | $Xsed -e 's/\.la$//'` + fi + ;; + esac + + if test -n "$objs"; then + if test "$deplibs_check_method" != pass_all; then + $echo "$modename: cannot build libtool library \`$output' from non-libtool objects on this host:$objs" 2>&1 + exit $EXIT_FAILURE + else + $echo + $echo "*** Warning: Linking the shared library $output against the non-libtool" + $echo "*** objects $objs is not portable!" + libobjs="$libobjs $objs" + fi + fi + + if test "$dlself" != no; then + $echo "$modename: warning: \`-dlopen self' is ignored for libtool libraries" 1>&2 + fi + + set dummy $rpath + if test "$#" -gt 2; then + $echo "$modename: warning: ignoring multiple \`-rpath's for a libtool library" 1>&2 + fi + install_libdir="$2" + + oldlibs= + if test -z "$rpath"; then + if test "$build_libtool_libs" = yes; then + # Building a libtool convenience library. + # Some compilers have problems with a `.al' extension so + # convenience libraries should have the same extension an + # archive normally would. + oldlibs="$output_objdir/$libname.$libext $oldlibs" + build_libtool_libs=convenience + build_old_libs=yes + fi + + if test -n "$vinfo"; then + $echo "$modename: warning: \`-version-info/-version-number' is ignored for convenience libraries" 1>&2 + fi + + if test -n "$release"; then + $echo "$modename: warning: \`-release' is ignored for convenience libraries" 1>&2 + fi + else + + # Parse the version information argument. + save_ifs="$IFS"; IFS=':' + set dummy $vinfo 0 0 0 + IFS="$save_ifs" + + if test -n "$8"; then + $echo "$modename: too many parameters to \`-version-info'" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + + # convert absolute version numbers to libtool ages + # this retains compatibility with .la files and attempts + # to make the code below a bit more comprehensible + + case $vinfo_number in + yes) + number_major="$2" + number_minor="$3" + number_revision="$4" + # + # There are really only two kinds -- those that + # use the current revision as the major version + # and those that subtract age and use age as + # a minor version. But, then there is irix + # which has an extra 1 added just for fun + # + case $version_type in + darwin|linux|osf|windows) + current=`expr $number_major + $number_minor` + age="$number_minor" + revision="$number_revision" + ;; + freebsd-aout|freebsd-elf|sunos) + current="$number_major" + revision="$number_minor" + age="0" + ;; + irix|nonstopux) + current=`expr $number_major + $number_minor - 1` + age="$number_minor" + revision="$number_minor" + ;; + esac + ;; + no) + current="$2" + revision="$3" + age="$4" + ;; + esac + + # Check that each of the things are valid numbers. + case $current in + 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; + *) + $echo "$modename: CURRENT \`$current' must be a nonnegative integer" 1>&2 + $echo "$modename: \`$vinfo' is not valid version information" 1>&2 + exit $EXIT_FAILURE + ;; + esac + + case $revision in + 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; + *) + $echo "$modename: REVISION \`$revision' must be a nonnegative integer" 1>&2 + $echo "$modename: \`$vinfo' is not valid version information" 1>&2 + exit $EXIT_FAILURE + ;; + esac + + case $age in + 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; + *) + $echo "$modename: AGE \`$age' must be a nonnegative integer" 1>&2 + $echo "$modename: \`$vinfo' is not valid version information" 1>&2 + exit $EXIT_FAILURE + ;; + esac + + if test "$age" -gt "$current"; then + $echo "$modename: AGE \`$age' is greater than the current interface number \`$current'" 1>&2 + $echo "$modename: \`$vinfo' is not valid version information" 1>&2 + exit $EXIT_FAILURE + fi + + # Calculate the version variables. + major= + versuffix= + verstring= + case $version_type in + none) ;; + + darwin) + # Like Linux, but with the current version available in + # verstring for coding it into the library header + major=.`expr $current - $age` + versuffix="$major.$age.$revision" + # Darwin ld doesn't like 0 for these options... + minor_current=`expr $current + 1` + verstring="${wl}-compatibility_version ${wl}$minor_current ${wl}-current_version ${wl}$minor_current.$revision" + ;; + + freebsd-aout) + major=".$current" + versuffix=".$current.$revision"; + ;; + + freebsd-elf) + major=".$current" + versuffix=".$current"; + ;; + + irix | nonstopux) + major=`expr $current - $age + 1` + + case $version_type in + nonstopux) verstring_prefix=nonstopux ;; + *) verstring_prefix=sgi ;; + esac + verstring="$verstring_prefix$major.$revision" + + # Add in all the interfaces that we are compatible with. + loop=$revision + while test "$loop" -ne 0; do + iface=`expr $revision - $loop` + loop=`expr $loop - 1` + verstring="$verstring_prefix$major.$iface:$verstring" + done + + # Before this point, $major must not contain `.'. + major=.$major + versuffix="$major.$revision" + ;; + + linux) + major=.`expr $current - $age` + versuffix="$major.$age.$revision" + ;; + + osf) + major=.`expr $current - $age` + versuffix=".$current.$age.$revision" + verstring="$current.$age.$revision" + + # Add in all the interfaces that we are compatible with. + loop=$age + while test "$loop" -ne 0; do + iface=`expr $current - $loop` + loop=`expr $loop - 1` + verstring="$verstring:${iface}.0" + done + + # Make executables depend on our current version. + verstring="$verstring:${current}.0" + ;; + + sunos) + major=".$current" + versuffix=".$current.$revision" + ;; + + windows) + # Use '-' rather than '.', since we only want one + # extension on DOS 8.3 filesystems. + major=`expr $current - $age` + versuffix="-$major" + ;; + + *) + $echo "$modename: unknown library version type \`$version_type'" 1>&2 + $echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2 + exit $EXIT_FAILURE + ;; + esac + + # Clear the version info if we defaulted, and they specified a release. + if test -z "$vinfo" && test -n "$release"; then + major= + case $version_type in + darwin) + # we can't check for "0.0" in archive_cmds due to quoting + # problems, so we reset it completely + verstring= + ;; + *) + verstring="0.0" + ;; + esac + if test "$need_version" = no; then + versuffix= + else + versuffix=".0.0" + fi + fi + + # Remove version info from name if versioning should be avoided + if test "$avoid_version" = yes && test "$need_version" = no; then + major= + versuffix= + verstring="" + fi + + # Check to see if the archive will have undefined symbols. + if test "$allow_undefined" = yes; then + if test "$allow_undefined_flag" = unsupported; then + $echo "$modename: warning: undefined symbols not allowed in $host shared libraries" 1>&2 + build_libtool_libs=no + build_old_libs=yes + fi + else + # Don't allow undefined symbols. + allow_undefined_flag="$no_undefined_flag" + fi + fi + + if test "$mode" != relink; then + # Remove our outputs, but don't remove object files since they + # may have been created when compiling PIC objects. + removelist= + tempremovelist=`$echo "$output_objdir/*"` + for p in $tempremovelist; do + case $p in + *.$objext) + ;; + $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/${libname}${release}.*) + if test "X$precious_files_regex" != "X"; then + if echo $p | $EGREP -e "$precious_files_regex" >/dev/null 2>&1 + then + continue + fi + fi + removelist="$removelist $p" + ;; + *) ;; + esac + done + if test -n "$removelist"; then + $show "${rm}r $removelist" + $run ${rm}r $removelist + fi + fi + + # Now set the variables for building old libraries. + if test "$build_old_libs" = yes && test "$build_libtool_libs" != convenience ; then + oldlibs="$oldlibs $output_objdir/$libname.$libext" + + # Transform .lo files to .o files. + oldobjs="$objs "`$echo "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}'$/d' -e "$lo2o" | $NL2SP` + fi + + # Eliminate all temporary directories. + for path in $notinst_path; do + lib_search_path=`$echo "$lib_search_path " | ${SED} -e "s% $path % %g"` + deplibs=`$echo "$deplibs " | ${SED} -e "s% -L$path % %g"` + dependency_libs=`$echo "$dependency_libs " | ${SED} -e "s% -L$path % %g"` + done + + if test -n "$xrpath"; then + # If the user specified any rpath flags, then add them. + temp_xrpath= + for libdir in $xrpath; do + temp_xrpath="$temp_xrpath -R$libdir" + case "$finalize_rpath " in + *" $libdir "*) ;; + *) finalize_rpath="$finalize_rpath $libdir" ;; + esac + done + if test "$hardcode_into_libs" != yes || test "$build_old_libs" = yes; then + dependency_libs="$temp_xrpath $dependency_libs" + fi + fi + + # Make sure dlfiles contains only unique files that won't be dlpreopened + old_dlfiles="$dlfiles" + dlfiles= + for lib in $old_dlfiles; do + case " $dlprefiles $dlfiles " in + *" $lib "*) ;; + *) dlfiles="$dlfiles $lib" ;; + esac + done + + # Make sure dlprefiles contains only unique files + old_dlprefiles="$dlprefiles" + dlprefiles= + for lib in $old_dlprefiles; do + case "$dlprefiles " in + *" $lib "*) ;; + *) dlprefiles="$dlprefiles $lib" ;; + esac + done + + if test "$build_libtool_libs" = yes; then + if test -n "$rpath"; then + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos*) + # these systems don't actually have a c library (as such)! + ;; + *-*-rhapsody* | *-*-darwin1.[012]) + # Rhapsody C library is in the System framework + deplibs="$deplibs -framework System" + ;; + *-*-netbsd*) + # Don't link with libc until the a.out ld.so is fixed. + ;; + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) + # Do not include libc due to us having libc/libc_r. + ;; + *-*-sco3.2v5* | *-*-sco5v6*) + # Causes problems with __ctype + ;; + *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) + # Compiler inserts libc in the correct place for threads to work + ;; + *) + # Add libc to deplibs on all other systems if necessary. + if test "$build_libtool_need_lc" = "yes"; then + deplibs="$deplibs -lc" + fi + ;; + esac + fi + + # Transform deplibs into only deplibs that can be linked in shared. + name_save=$name + libname_save=$libname + release_save=$release + versuffix_save=$versuffix + major_save=$major + # I'm not sure if I'm treating the release correctly. I think + # release should show up in the -l (ie -lgmp5) so we don't want to + # add it in twice. Is that correct? + release="" + versuffix="" + major="" + newdeplibs= + droppeddeps=no + case $deplibs_check_method in + pass_all) + # Don't check for shared/static. Everything works. + # This might be a little naive. We might want to check + # whether the library exists or not. But this is on + # osf3 & osf4 and I'm not really sure... Just + # implementing what was already the behavior. + newdeplibs=$deplibs + ;; + test_compile) + # This code stresses the "libraries are programs" paradigm to its + # limits. Maybe even breaks it. We compile a program, linking it + # against the deplibs as a proxy for the library. Then we can check + # whether they linked in statically or dynamically with ldd. + $rm conftest.c + cat > conftest.c </dev/null` + for potent_lib in $potential_libs; do + # Follow soft links. + if ls -lLd "$potent_lib" 2>/dev/null \ + | grep " -> " >/dev/null; then + continue + fi + # The statement above tries to avoid entering an + # endless loop below, in case of cyclic links. + # We might still enter an endless loop, since a link + # loop can be closed while we follow links, + # but so what? + potlib="$potent_lib" + while test -h "$potlib" 2>/dev/null; do + potliblink=`ls -ld $potlib | ${SED} 's/.* -> //'` + case $potliblink in + [\\/]* | [A-Za-z]:[\\/]*) potlib="$potliblink";; + *) potlib=`$echo "X$potlib" | $Xsed -e 's,[^/]*$,,'`"$potliblink";; + esac + done + if eval $file_magic_cmd \"\$potlib\" 2>/dev/null \ + | ${SED} 10q \ + | $EGREP "$file_magic_regex" > /dev/null; then + newdeplibs="$newdeplibs $a_deplib" + a_deplib="" + break 2 + fi + done + done + fi + if test -n "$a_deplib" ; then + droppeddeps=yes + $echo + $echo "*** Warning: linker path does not have real file for library $a_deplib." + $echo "*** I have the capability to make that library automatically link in when" + $echo "*** you link to this library. But I can only do this if you have a" + $echo "*** shared version of the library, which you do not appear to have" + $echo "*** because I did check the linker path looking for a file starting" + if test -z "$potlib" ; then + $echo "*** with $libname but no candidates were found. (...for file magic test)" + else + $echo "*** with $libname and none of the candidates passed a file format test" + $echo "*** using a file magic. Last file checked: $potlib" + fi + fi + else + # Add a -L argument. + newdeplibs="$newdeplibs $a_deplib" + fi + done # Gone through all deplibs. + ;; + match_pattern*) + set dummy $deplibs_check_method + match_pattern_regex=`expr "$deplibs_check_method" : "$2 \(.*\)"` + for a_deplib in $deplibs; do + name=`expr $a_deplib : '-l\(.*\)'` + # If $name is empty we are operating on a -L argument. + if test -n "$name" && test "$name" != "0"; then + if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then + case " $predeps $postdeps " in + *" $a_deplib "*) + newdeplibs="$newdeplibs $a_deplib" + a_deplib="" + ;; + esac + fi + if test -n "$a_deplib" ; then + libname=`eval \\$echo \"$libname_spec\"` + for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do + potential_libs=`ls $i/$libname[.-]* 2>/dev/null` + for potent_lib in $potential_libs; do + potlib="$potent_lib" # see symlink-check above in file_magic test + if eval $echo \"$potent_lib\" 2>/dev/null \ + | ${SED} 10q \ + | $EGREP "$match_pattern_regex" > /dev/null; then + newdeplibs="$newdeplibs $a_deplib" + a_deplib="" + break 2 + fi + done + done + fi + if test -n "$a_deplib" ; then + droppeddeps=yes + $echo + $echo "*** Warning: linker path does not have real file for library $a_deplib." + $echo "*** I have the capability to make that library automatically link in when" + $echo "*** you link to this library. But I can only do this if you have a" + $echo "*** shared version of the library, which you do not appear to have" + $echo "*** because I did check the linker path looking for a file starting" + if test -z "$potlib" ; then + $echo "*** with $libname but no candidates were found. (...for regex pattern test)" + else + $echo "*** with $libname and none of the candidates passed a file format test" + $echo "*** using a regex pattern. Last file checked: $potlib" + fi + fi + else + # Add a -L argument. + newdeplibs="$newdeplibs $a_deplib" + fi + done # Gone through all deplibs. + ;; + none | unknown | *) + newdeplibs="" + tmp_deplibs=`$echo "X $deplibs" | $Xsed -e 's/ -lc$//' \ + -e 's/ -[LR][^ ]*//g'` + if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then + for i in $predeps $postdeps ; do + # can't use Xsed below, because $i might contain '/' + tmp_deplibs=`$echo "X $tmp_deplibs" | ${SED} -e "1s,^X,," -e "s,$i,,"` + done + fi + if $echo "X $tmp_deplibs" | $Xsed -e 's/[ ]//g' \ + | grep . >/dev/null; then + $echo + if test "X$deplibs_check_method" = "Xnone"; then + $echo "*** Warning: inter-library dependencies are not supported in this platform." + else + $echo "*** Warning: inter-library dependencies are not known to be supported." + fi + $echo "*** All declared inter-library dependencies are being dropped." + droppeddeps=yes + fi + ;; + esac + versuffix=$versuffix_save + major=$major_save + release=$release_save + libname=$libname_save + name=$name_save + + case $host in + *-*-rhapsody* | *-*-darwin1.[012]) + # On Rhapsody replace the C library is the System framework + newdeplibs=`$echo "X $newdeplibs" | $Xsed -e 's/ -lc / -framework System /'` + ;; + esac + + if test "$droppeddeps" = yes; then + if test "$module" = yes; then + $echo + $echo "*** Warning: libtool could not satisfy all declared inter-library" + $echo "*** dependencies of module $libname. Therefore, libtool will create" + $echo "*** a static module, that should work as long as the dlopening" + $echo "*** application is linked with the -dlopen flag." + if test -z "$global_symbol_pipe"; then + $echo + $echo "*** However, this would only work if libtool was able to extract symbol" + $echo "*** lists from a program, using \`nm' or equivalent, but libtool could" + $echo "*** not find such a program. So, this module is probably useless." + $echo "*** \`nm' from GNU binutils and a full rebuild may help." + fi + if test "$build_old_libs" = no; then + oldlibs="$output_objdir/$libname.$libext" + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + else + $echo "*** The inter-library dependencies that have been dropped here will be" + $echo "*** automatically added whenever a program is linked with this library" + $echo "*** or is declared to -dlopen it." + + if test "$allow_undefined" = no; then + $echo + $echo "*** Since this library must not contain undefined symbols," + $echo "*** because either the platform does not support them or" + $echo "*** it was explicitly requested with -no-undefined," + $echo "*** libtool will only create a static version of it." + if test "$build_old_libs" = no; then + oldlibs="$output_objdir/$libname.$libext" + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + fi + fi + fi + # Done checking deplibs! + deplibs=$newdeplibs + fi + + + # move library search paths that coincide with paths to not yet + # installed libraries to the beginning of the library search list + new_libs= + for path in $notinst_path; do + case " $new_libs " in + *" -L$path/$objdir "*) ;; + *) + case " $deplibs " in + *" -L$path/$objdir "*) + new_libs="$new_libs -L$path/$objdir" ;; + esac + ;; + esac + done + for deplib in $deplibs; do + case $deplib in + -L*) + case " $new_libs " in + *" $deplib "*) ;; + *) new_libs="$new_libs $deplib" ;; + esac + ;; + *) new_libs="$new_libs $deplib" ;; + esac + done + deplibs="$new_libs" + + + # All the library-specific variables (install_libdir is set above). + library_names= + old_library= + dlname= + + # Test again, we may have decided not to build it any more + if test "$build_libtool_libs" = yes; then + if test "$hardcode_into_libs" = yes; then + # Hardcode the library paths + hardcode_libdirs= + dep_rpath= + rpath="$finalize_rpath" + test "$mode" != relink && rpath="$compile_rpath$rpath" + for libdir in $rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + if test -z "$hardcode_libdirs"; then + hardcode_libdirs="$libdir" + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + dep_rpath="$dep_rpath $flag" + fi + elif test -n "$runpath_var"; then + case "$perm_rpath " in + *" $libdir "*) ;; + *) perm_rpath="$perm_rpath $libdir" ;; + esac + fi + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir="$hardcode_libdirs" + if test -n "$hardcode_libdir_flag_spec_ld"; then + eval dep_rpath=\"$hardcode_libdir_flag_spec_ld\" + else + eval dep_rpath=\"$hardcode_libdir_flag_spec\" + fi + fi + if test -n "$runpath_var" && test -n "$perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $perm_rpath; do + rpath="$rpath$dir:" + done + eval "$runpath_var='$rpath\$$runpath_var'; export $runpath_var" + fi + test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs" + fi + + shlibpath="$finalize_shlibpath" + test "$mode" != relink && shlibpath="$compile_shlibpath$shlibpath" + if test -n "$shlibpath"; then + eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var" + fi + + # Get the real and link names of the library. + eval shared_ext=\"$shrext_cmds\" + eval library_names=\"$library_names_spec\" + set dummy $library_names + realname="$2" + shift; shift + + if test -n "$soname_spec"; then + eval soname=\"$soname_spec\" + else + soname="$realname" + fi + if test -z "$dlname"; then + dlname=$soname + fi + + lib="$output_objdir/$realname" + linknames= + for link + do + linknames="$linknames $link" + done + + # Use standard objects if they are pic + test -z "$pic_flag" && libobjs=`$echo "X$libobjs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` + + # Prepare the list of exported symbols + if test -z "$export_symbols"; then + if test "$always_export_symbols" = yes || test -n "$export_symbols_regex"; then + $show "generating symbol list for \`$libname.la'" + export_symbols="$output_objdir/$libname.exp" + $run $rm $export_symbols + cmds=$export_symbols_cmds + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + if len=`expr "X$cmd" : ".*"` && + test "$len" -le "$max_cmd_len" || test "$max_cmd_len" -le -1; then + $show "$cmd" + $run eval "$cmd" || exit $? + skipped_export=false + else + # The command line is too long to execute in one step. + $show "using reloadable object file for export list..." + skipped_export=: + # Break out early, otherwise skipped_export may be + # set to false by a later but shorter cmd. + break + fi + done + IFS="$save_ifs" + if test -n "$export_symbols_regex"; then + $show "$EGREP -e \"$export_symbols_regex\" \"$export_symbols\" > \"${export_symbols}T\"" + $run eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' + $show "$mv \"${export_symbols}T\" \"$export_symbols\"" + $run eval '$mv "${export_symbols}T" "$export_symbols"' + fi + fi + fi + + if test -n "$export_symbols" && test -n "$include_expsyms"; then + $run eval '$echo "X$include_expsyms" | $SP2NL >> "$export_symbols"' + fi + + tmp_deplibs= + for test_deplib in $deplibs; do + case " $convenience " in + *" $test_deplib "*) ;; + *) + tmp_deplibs="$tmp_deplibs $test_deplib" + ;; + esac + done + deplibs="$tmp_deplibs" + + if test -n "$convenience"; then + if test -n "$whole_archive_flag_spec"; then + save_libobjs=$libobjs + eval libobjs=\"\$libobjs $whole_archive_flag_spec\" + else + gentop="$output_objdir/${outputname}x" + generated="$generated $gentop" + + func_extract_archives $gentop $convenience + libobjs="$libobjs $func_extract_archives_result" + fi + fi + + if test "$thread_safe" = yes && test -n "$thread_safe_flag_spec"; then + eval flag=\"$thread_safe_flag_spec\" + linker_flags="$linker_flags $flag" + fi + + # Make a backup of the uninstalled library when relinking + if test "$mode" = relink; then + $run eval '(cd $output_objdir && $rm ${realname}U && $mv $realname ${realname}U)' || exit $? + fi + + # Do each of the archive commands. + if test "$module" = yes && test -n "$module_cmds" ; then + if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then + eval test_cmds=\"$module_expsym_cmds\" + cmds=$module_expsym_cmds + else + eval test_cmds=\"$module_cmds\" + cmds=$module_cmds + fi + else + if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then + eval test_cmds=\"$archive_expsym_cmds\" + cmds=$archive_expsym_cmds + else + eval test_cmds=\"$archive_cmds\" + cmds=$archive_cmds + fi + fi + + if test "X$skipped_export" != "X:" && + len=`expr "X$test_cmds" : ".*" 2>/dev/null` && + test "$len" -le "$max_cmd_len" || test "$max_cmd_len" -le -1; then + : + else + # The command line is too long to link in one step, link piecewise. + $echo "creating reloadable object files..." + + # Save the value of $output and $libobjs because we want to + # use them later. If we have whole_archive_flag_spec, we + # want to use save_libobjs as it was before + # whole_archive_flag_spec was expanded, because we can't + # assume the linker understands whole_archive_flag_spec. + # This may have to be revisited, in case too many + # convenience libraries get linked in and end up exceeding + # the spec. + if test -z "$convenience" || test -z "$whole_archive_flag_spec"; then + save_libobjs=$libobjs + fi + save_output=$output + output_la=`$echo "X$output" | $Xsed -e "$basename"` + + # Clear the reloadable object creation command queue and + # initialize k to one. + test_cmds= + concat_cmds= + objlist= + delfiles= + last_robj= + k=1 + output=$output_objdir/$output_la-${k}.$objext + # Loop over the list of objects to be linked. + for obj in $save_libobjs + do + eval test_cmds=\"$reload_cmds $objlist $last_robj\" + if test "X$objlist" = X || + { len=`expr "X$test_cmds" : ".*" 2>/dev/null` && + test "$len" -le "$max_cmd_len"; }; then + objlist="$objlist $obj" + else + # The command $test_cmds is almost too long, add a + # command to the queue. + if test "$k" -eq 1 ; then + # The first file doesn't have a previous command to add. + eval concat_cmds=\"$reload_cmds $objlist $last_robj\" + else + # All subsequent reloadable object files will link in + # the last one created. + eval concat_cmds=\"\$concat_cmds~$reload_cmds $objlist $last_robj\" + fi + last_robj=$output_objdir/$output_la-${k}.$objext + k=`expr $k + 1` + output=$output_objdir/$output_la-${k}.$objext + objlist=$obj + len=1 + fi + done + # Handle the remaining objects by creating one last + # reloadable object file. All subsequent reloadable object + # files will link in the last one created. + test -z "$concat_cmds" || concat_cmds=$concat_cmds~ + eval concat_cmds=\"\${concat_cmds}$reload_cmds $objlist $last_robj\" + + if ${skipped_export-false}; then + $show "generating symbol list for \`$libname.la'" + export_symbols="$output_objdir/$libname.exp" + $run $rm $export_symbols + libobjs=$output + # Append the command to create the export file. + eval concat_cmds=\"\$concat_cmds~$export_symbols_cmds\" + fi + + # Set up a command to remove the reloadable object files + # after they are used. + i=0 + while test "$i" -lt "$k" + do + i=`expr $i + 1` + delfiles="$delfiles $output_objdir/$output_la-${i}.$objext" + done + + $echo "creating a temporary reloadable object file: $output" + + # Loop through the commands generated above and execute them. + save_ifs="$IFS"; IFS='~' + for cmd in $concat_cmds; do + IFS="$save_ifs" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + + libobjs=$output + # Restore the value of output. + output=$save_output + + if test -n "$convenience" && test -n "$whole_archive_flag_spec"; then + eval libobjs=\"\$libobjs $whole_archive_flag_spec\" + fi + # Expand the library linking commands again to reset the + # value of $libobjs for piecewise linking. + + # Do each of the archive commands. + if test "$module" = yes && test -n "$module_cmds" ; then + if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then + cmds=$module_expsym_cmds + else + cmds=$module_cmds + fi + else + if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then + cmds=$archive_expsym_cmds + else + cmds=$archive_cmds + fi + fi + + # Append the command to remove the reloadable object files + # to the just-reset $cmds. + eval cmds=\"\$cmds~\$rm $delfiles\" + fi + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + $show "$cmd" + $run eval "$cmd" || { + lt_exit=$? + + # Restore the uninstalled library and exit + if test "$mode" = relink; then + $run eval '(cd $output_objdir && $rm ${realname}T && $mv ${realname}U $realname)' + fi + + exit $lt_exit + } + done + IFS="$save_ifs" + + # Restore the uninstalled library and exit + if test "$mode" = relink; then + $run eval '(cd $output_objdir && $rm ${realname}T && $mv $realname ${realname}T && $mv "$realname"U $realname)' || exit $? + + if test -n "$convenience"; then + if test -z "$whole_archive_flag_spec"; then + $show "${rm}r $gentop" + $run ${rm}r "$gentop" + fi + fi + + exit $EXIT_SUCCESS + fi + + # Create links to the real library. + for linkname in $linknames; do + if test "$realname" != "$linkname"; then + $show "(cd $output_objdir && $rm $linkname && $LN_S $realname $linkname)" + $run eval '(cd $output_objdir && $rm $linkname && $LN_S $realname $linkname)' || exit $? + fi + done + + # If -module or -export-dynamic was specified, set the dlname. + if test "$module" = yes || test "$export_dynamic" = yes; then + # On all known operating systems, these are identical. + dlname="$soname" + fi + fi + ;; + + obj) + if test -n "$deplibs"; then + $echo "$modename: warning: \`-l' and \`-L' are ignored for objects" 1>&2 + fi + + if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then + $echo "$modename: warning: \`-dlopen' is ignored for objects" 1>&2 + fi + + if test -n "$rpath"; then + $echo "$modename: warning: \`-rpath' is ignored for objects" 1>&2 + fi + + if test -n "$xrpath"; then + $echo "$modename: warning: \`-R' is ignored for objects" 1>&2 + fi + + if test -n "$vinfo"; then + $echo "$modename: warning: \`-version-info' is ignored for objects" 1>&2 + fi + + if test -n "$release"; then + $echo "$modename: warning: \`-release' is ignored for objects" 1>&2 + fi + + case $output in + *.lo) + if test -n "$objs$old_deplibs"; then + $echo "$modename: cannot build library object \`$output' from non-libtool objects" 1>&2 + exit $EXIT_FAILURE + fi + libobj="$output" + obj=`$echo "X$output" | $Xsed -e "$lo2o"` + ;; + *) + libobj= + obj="$output" + ;; + esac + + # Delete the old objects. + $run $rm $obj $libobj + + # Objects from convenience libraries. This assumes + # single-version convenience libraries. Whenever we create + # different ones for PIC/non-PIC, this we'll have to duplicate + # the extraction. + reload_conv_objs= + gentop= + # reload_cmds runs $LD directly, so let us get rid of + # -Wl from whole_archive_flag_spec + wl= + + if test -n "$convenience"; then + if test -n "$whole_archive_flag_spec"; then + eval reload_conv_objs=\"\$reload_objs $whole_archive_flag_spec\" + else + gentop="$output_objdir/${obj}x" + generated="$generated $gentop" + + func_extract_archives $gentop $convenience + reload_conv_objs="$reload_objs $func_extract_archives_result" + fi + fi + + # Create the old-style object. + reload_objs="$objs$old_deplibs "`$echo "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}$'/d' -e '/\.lib$/d' -e "$lo2o" | $NL2SP`" $reload_conv_objs" ### testsuite: skip nested quoting test + + output="$obj" + cmds=$reload_cmds + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + + # Exit if we aren't doing a library object file. + if test -z "$libobj"; then + if test -n "$gentop"; then + $show "${rm}r $gentop" + $run ${rm}r $gentop + fi + + exit $EXIT_SUCCESS + fi + + if test "$build_libtool_libs" != yes; then + if test -n "$gentop"; then + $show "${rm}r $gentop" + $run ${rm}r $gentop + fi + + # Create an invalid libtool object if no PIC, so that we don't + # accidentally link it into a program. + # $show "echo timestamp > $libobj" + # $run eval "echo timestamp > $libobj" || exit $? + exit $EXIT_SUCCESS + fi + + if test -n "$pic_flag" || test "$pic_mode" != default; then + # Only do commands if we really have different PIC objects. + reload_objs="$libobjs $reload_conv_objs" + output="$libobj" + cmds=$reload_cmds + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + fi + + if test -n "$gentop"; then + $show "${rm}r $gentop" + $run ${rm}r $gentop + fi + + exit $EXIT_SUCCESS + ;; + + prog) + case $host in + *cygwin*) output=`$echo $output | ${SED} -e 's,.exe$,,;s,$,.exe,'` ;; + esac + if test -n "$vinfo"; then + $echo "$modename: warning: \`-version-info' is ignored for programs" 1>&2 + fi + + if test -n "$release"; then + $echo "$modename: warning: \`-release' is ignored for programs" 1>&2 + fi + + if test "$preload" = yes; then + if test "$dlopen_support" = unknown && test "$dlopen_self" = unknown && + test "$dlopen_self_static" = unknown; then + $echo "$modename: warning: \`AC_LIBTOOL_DLOPEN' not used. Assuming no dlopen support." + fi + fi + + case $host in + *-*-rhapsody* | *-*-darwin1.[012]) + # On Rhapsody replace the C library is the System framework + compile_deplibs=`$echo "X $compile_deplibs" | $Xsed -e 's/ -lc / -framework System /'` + finalize_deplibs=`$echo "X $finalize_deplibs" | $Xsed -e 's/ -lc / -framework System /'` + ;; + esac + + case $host in + *darwin*) + # Don't allow lazy linking, it breaks C++ global constructors + if test "$tagname" = CXX ; then + compile_command="$compile_command ${wl}-bind_at_load" + finalize_command="$finalize_command ${wl}-bind_at_load" + fi + ;; + esac + + + # move library search paths that coincide with paths to not yet + # installed libraries to the beginning of the library search list + new_libs= + for path in $notinst_path; do + case " $new_libs " in + *" -L$path/$objdir "*) ;; + *) + case " $compile_deplibs " in + *" -L$path/$objdir "*) + new_libs="$new_libs -L$path/$objdir" ;; + esac + ;; + esac + done + for deplib in $compile_deplibs; do + case $deplib in + -L*) + case " $new_libs " in + *" $deplib "*) ;; + *) new_libs="$new_libs $deplib" ;; + esac + ;; + *) new_libs="$new_libs $deplib" ;; + esac + done + compile_deplibs="$new_libs" + + + compile_command="$compile_command $compile_deplibs" + finalize_command="$finalize_command $finalize_deplibs" + + if test -n "$rpath$xrpath"; then + # If the user specified any rpath flags, then add them. + for libdir in $rpath $xrpath; do + # This is the magic to use -rpath. + case "$finalize_rpath " in + *" $libdir "*) ;; + *) finalize_rpath="$finalize_rpath $libdir" ;; + esac + done + fi + + # Now hardcode the library paths + rpath= + hardcode_libdirs= + for libdir in $compile_rpath $finalize_rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + if test -z "$hardcode_libdirs"; then + hardcode_libdirs="$libdir" + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + rpath="$rpath $flag" + fi + elif test -n "$runpath_var"; then + case "$perm_rpath " in + *" $libdir "*) ;; + *) perm_rpath="$perm_rpath $libdir" ;; + esac + fi + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*) + testbindir=`$echo "X$libdir" | $Xsed -e 's*/lib$*/bin*'` + case :$dllsearchpath: in + *":$libdir:"*) ;; + *) dllsearchpath="$dllsearchpath:$libdir";; + esac + case :$dllsearchpath: in + *":$testbindir:"*) ;; + *) dllsearchpath="$dllsearchpath:$testbindir";; + esac + ;; + esac + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir="$hardcode_libdirs" + eval rpath=\" $hardcode_libdir_flag_spec\" + fi + compile_rpath="$rpath" + + rpath= + hardcode_libdirs= + for libdir in $finalize_rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + if test -z "$hardcode_libdirs"; then + hardcode_libdirs="$libdir" + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + rpath="$rpath $flag" + fi + elif test -n "$runpath_var"; then + case "$finalize_perm_rpath " in + *" $libdir "*) ;; + *) finalize_perm_rpath="$finalize_perm_rpath $libdir" ;; + esac + fi + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir="$hardcode_libdirs" + eval rpath=\" $hardcode_libdir_flag_spec\" + fi + finalize_rpath="$rpath" + + if test -n "$libobjs" && test "$build_old_libs" = yes; then + # Transform all the library objects into standard objects. + compile_command=`$echo "X$compile_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` + finalize_command=`$echo "X$finalize_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` + fi + + dlsyms= + if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then + if test -n "$NM" && test -n "$global_symbol_pipe"; then + dlsyms="${outputname}S.c" + else + $echo "$modename: not configured to extract global symbols from dlpreopened files" 1>&2 + fi + fi + + if test -n "$dlsyms"; then + case $dlsyms in + "") ;; + *.c) + # Discover the nlist of each of the dlfiles. + nlist="$output_objdir/${outputname}.nm" + + $show "$rm $nlist ${nlist}S ${nlist}T" + $run $rm "$nlist" "${nlist}S" "${nlist}T" + + # Parse the name list into a source file. + $show "creating $output_objdir/$dlsyms" + + test -z "$run" && $echo > "$output_objdir/$dlsyms" "\ +/* $dlsyms - symbol resolution table for \`$outputname' dlsym emulation. */ +/* Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP */ + +#ifdef __cplusplus +extern \"C\" { +#endif + +/* Prevent the only kind of declaration conflicts we can make. */ +#define lt_preloaded_symbols some_other_symbol + +/* External symbol declarations for the compiler. */\ +" + + if test "$dlself" = yes; then + $show "generating symbol list for \`$output'" + + test -z "$run" && $echo ': @PROGRAM@ ' > "$nlist" + + # Add our own program objects to the symbol list. + progfiles=`$echo "X$objs$old_deplibs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` + for arg in $progfiles; do + $show "extracting global C symbols from \`$arg'" + $run eval "$NM $arg | $global_symbol_pipe >> '$nlist'" + done + + if test -n "$exclude_expsyms"; then + $run eval '$EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T' + $run eval '$mv "$nlist"T "$nlist"' + fi + + if test -n "$export_symbols_regex"; then + $run eval '$EGREP -e "$export_symbols_regex" "$nlist" > "$nlist"T' + $run eval '$mv "$nlist"T "$nlist"' + fi + + # Prepare the list of exported symbols + if test -z "$export_symbols"; then + export_symbols="$output_objdir/$outputname.exp" + $run $rm $export_symbols + $run eval "${SED} -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"' + case $host in + *cygwin* | *mingw* ) + $run eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' + $run eval 'cat "$export_symbols" >> "$output_objdir/$outputname.def"' + ;; + esac + else + $run eval "${SED} -e 's/\([].[*^$]\)/\\\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$outputname.exp"' + $run eval 'grep -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T' + $run eval 'mv "$nlist"T "$nlist"' + case $host in + *cygwin* | *mingw* ) + $run eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' + $run eval 'cat "$nlist" >> "$output_objdir/$outputname.def"' + ;; + esac + fi + fi + + for arg in $dlprefiles; do + $show "extracting global C symbols from \`$arg'" + name=`$echo "$arg" | ${SED} -e 's%^.*/%%'` + $run eval '$echo ": $name " >> "$nlist"' + $run eval "$NM $arg | $global_symbol_pipe >> '$nlist'" + done + + if test -z "$run"; then + # Make sure we have at least an empty file. + test -f "$nlist" || : > "$nlist" + + if test -n "$exclude_expsyms"; then + $EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T + $mv "$nlist"T "$nlist" + fi + + # Try sorting and uniquifying the output. + if grep -v "^: " < "$nlist" | + if sort -k 3 /dev/null 2>&1; then + sort -k 3 + else + sort +2 + fi | + uniq > "$nlist"S; then + : + else + grep -v "^: " < "$nlist" > "$nlist"S + fi + + if test -f "$nlist"S; then + eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$dlsyms"' + else + $echo '/* NONE */' >> "$output_objdir/$dlsyms" + fi + + $echo >> "$output_objdir/$dlsyms" "\ + +#undef lt_preloaded_symbols + +#if defined (__STDC__) && __STDC__ +# define lt_ptr void * +#else +# define lt_ptr char * +# define const +#endif + +/* The mapping between symbol names and symbols. */ +" + + case $host in + *cygwin* | *mingw* ) + $echo >> "$output_objdir/$dlsyms" "\ +/* DATA imports from DLLs on WIN32 can't be const, because + runtime relocations are performed -- see ld's documentation + on pseudo-relocs */ +struct { +" + ;; + * ) + $echo >> "$output_objdir/$dlsyms" "\ +const struct { +" + ;; + esac + + + $echo >> "$output_objdir/$dlsyms" "\ + const char *name; + lt_ptr address; +} +lt_preloaded_symbols[] = +{\ +" + + eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$dlsyms" + + $echo >> "$output_objdir/$dlsyms" "\ + {0, (lt_ptr) 0} +}; + +/* This works around a problem in FreeBSD linker */ +#ifdef FREEBSD_WORKAROUND +static const void *lt_preloaded_setup() { + return lt_preloaded_symbols; +} +#endif + +#ifdef __cplusplus +} +#endif\ +" + fi + + pic_flag_for_symtable= + case $host in + # compiling the symbol table file with pic_flag works around + # a FreeBSD bug that causes programs to crash when -lm is + # linked before any other PIC object. But we must not use + # pic_flag when linking with -static. The problem exists in + # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1. + *-*-freebsd2*|*-*-freebsd3.0*|*-*-freebsdelf3.0*) + case "$compile_command " in + *" -static "*) ;; + *) pic_flag_for_symtable=" $pic_flag -DFREEBSD_WORKAROUND";; + esac;; + *-*-hpux*) + case "$compile_command " in + *" -static "*) ;; + *) pic_flag_for_symtable=" $pic_flag";; + esac + esac + + # Now compile the dynamic symbol file. + $show "(cd $output_objdir && $LTCC $LTCFLAGS -c$no_builtin_flag$pic_flag_for_symtable \"$dlsyms\")" + $run eval '(cd $output_objdir && $LTCC $LTCFLAGS -c$no_builtin_flag$pic_flag_for_symtable "$dlsyms")' || exit $? + + # Clean up the generated files. + $show "$rm $output_objdir/$dlsyms $nlist ${nlist}S ${nlist}T" + $run $rm "$output_objdir/$dlsyms" "$nlist" "${nlist}S" "${nlist}T" + + # Transform the symbol file into the correct name. + case $host in + *cygwin* | *mingw* ) + if test -f "$output_objdir/${outputname}.def" ; then + compile_command=`$echo "X$compile_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}.def $output_objdir/${outputname}S.${objext}%"` + finalize_command=`$echo "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}.def $output_objdir/${outputname}S.${objext}%"` + else + compile_command=`$echo "X$compile_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"` + finalize_command=`$echo "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"` + fi + ;; + * ) + compile_command=`$echo "X$compile_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"` + finalize_command=`$echo "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"` + ;; + esac + ;; + *) + $echo "$modename: unknown suffix for \`$dlsyms'" 1>&2 + exit $EXIT_FAILURE + ;; + esac + else + # We keep going just in case the user didn't refer to + # lt_preloaded_symbols. The linker will fail if global_symbol_pipe + # really was required. + + # Nullify the symbol file. + compile_command=`$echo "X$compile_command" | $Xsed -e "s% @SYMFILE@%%"` + finalize_command=`$echo "X$finalize_command" | $Xsed -e "s% @SYMFILE@%%"` + fi + + if test "$need_relink" = no || test "$build_libtool_libs" != yes; then + # Replace the output file specification. + compile_command=`$echo "X$compile_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'` + link_command="$compile_command$compile_rpath" + + # We have no uninstalled library dependencies, so finalize right now. + $show "$link_command" + $run eval "$link_command" + exit_status=$? + + # Delete the generated files. + if test -n "$dlsyms"; then + $show "$rm $output_objdir/${outputname}S.${objext}" + $run $rm "$output_objdir/${outputname}S.${objext}" + fi + + exit $exit_status + fi + + if test -n "$shlibpath_var"; then + # We should set the shlibpath_var + rpath= + for dir in $temp_rpath; do + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) + # Absolute path. + rpath="$rpath$dir:" + ;; + *) + # Relative path: add a thisdir entry. + rpath="$rpath\$thisdir/$dir:" + ;; + esac + done + temp_rpath="$rpath" + fi + + if test -n "$compile_shlibpath$finalize_shlibpath"; then + compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command" + fi + if test -n "$finalize_shlibpath"; then + finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command" + fi + + compile_var= + finalize_var= + if test -n "$runpath_var"; then + if test -n "$perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $perm_rpath; do + rpath="$rpath$dir:" + done + compile_var="$runpath_var=\"$rpath\$$runpath_var\" " + fi + if test -n "$finalize_perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $finalize_perm_rpath; do + rpath="$rpath$dir:" + done + finalize_var="$runpath_var=\"$rpath\$$runpath_var\" " + fi + fi + + if test "$no_install" = yes; then + # We don't need to create a wrapper script. + link_command="$compile_var$compile_command$compile_rpath" + # Replace the output file specification. + link_command=`$echo "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'` + # Delete the old output file. + $run $rm $output + # Link the executable and exit + $show "$link_command" + $run eval "$link_command" || exit $? + exit $EXIT_SUCCESS + fi + + if test "$hardcode_action" = relink; then + # Fast installation is not supported + link_command="$compile_var$compile_command$compile_rpath" + relink_command="$finalize_var$finalize_command$finalize_rpath" + + $echo "$modename: warning: this platform does not like uninstalled shared libraries" 1>&2 + $echo "$modename: \`$output' will be relinked during installation" 1>&2 + else + if test "$fast_install" != no; then + link_command="$finalize_var$compile_command$finalize_rpath" + if test "$fast_install" = yes; then + relink_command=`$echo "X$compile_var$compile_command$compile_rpath" | $Xsed -e 's%@OUTPUT@%\$progdir/\$file%g'` + else + # fast_install is set to needless + relink_command= + fi + else + link_command="$compile_var$compile_command$compile_rpath" + relink_command="$finalize_var$finalize_command$finalize_rpath" + fi + fi + + # Replace the output file specification. + link_command=`$echo "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'` + + # Delete the old output files. + $run $rm $output $output_objdir/$outputname $output_objdir/lt-$outputname + + $show "$link_command" + $run eval "$link_command" || exit $? + + # Now create the wrapper script. + $show "creating $output" + + # Quote the relink command for shipping. + if test -n "$relink_command"; then + # Preserve any variables that may affect compiler behavior + for var in $variables_saved_for_relink; do + if eval test -z \"\${$var+set}\"; then + relink_command="{ test -z \"\${$var+set}\" || unset $var || { $var=; export $var; }; }; $relink_command" + elif eval var_value=\$$var; test -z "$var_value"; then + relink_command="$var=; export $var; $relink_command" + else + var_value=`$echo "X$var_value" | $Xsed -e "$sed_quote_subst"` + relink_command="$var=\"$var_value\"; export $var; $relink_command" + fi + done + relink_command="(cd `pwd`; $relink_command)" + relink_command=`$echo "X$relink_command" | $Xsed -e "$sed_quote_subst"` + fi + + # Quote $echo for shipping. + if test "X$echo" = "X$SHELL $progpath --fallback-echo"; then + case $progpath in + [\\/]* | [A-Za-z]:[\\/]*) qecho="$SHELL $progpath --fallback-echo";; + *) qecho="$SHELL `pwd`/$progpath --fallback-echo";; + esac + qecho=`$echo "X$qecho" | $Xsed -e "$sed_quote_subst"` + else + qecho=`$echo "X$echo" | $Xsed -e "$sed_quote_subst"` + fi + + # Only actually do things if our run command is non-null. + if test -z "$run"; then + # win32 will think the script is a binary if it has + # a .exe suffix, so we strip it off here. + case $output in + *.exe) output=`$echo $output|${SED} 's,.exe$,,'` ;; + esac + # test for cygwin because mv fails w/o .exe extensions + case $host in + *cygwin*) + exeext=.exe + outputname=`$echo $outputname|${SED} 's,.exe$,,'` ;; + *) exeext= ;; + esac + case $host in + *cygwin* | *mingw* ) + output_name=`basename $output` + output_path=`dirname $output` + cwrappersource="$output_path/$objdir/lt-$output_name.c" + cwrapper="$output_path/$output_name.exe" + $rm $cwrappersource $cwrapper + trap "$rm $cwrappersource $cwrapper; exit $EXIT_FAILURE" 1 2 15 + + cat > $cwrappersource <> $cwrappersource<<"EOF" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(PATH_MAX) +# define LT_PATHMAX PATH_MAX +#elif defined(MAXPATHLEN) +# define LT_PATHMAX MAXPATHLEN +#else +# define LT_PATHMAX 1024 +#endif + +#ifndef DIR_SEPARATOR +# define DIR_SEPARATOR '/' +# define PATH_SEPARATOR ':' +#endif + +#if defined (_WIN32) || defined (__MSDOS__) || defined (__DJGPP__) || \ + defined (__OS2__) +# define HAVE_DOS_BASED_FILE_SYSTEM +# ifndef DIR_SEPARATOR_2 +# define DIR_SEPARATOR_2 '\\' +# endif +# ifndef PATH_SEPARATOR_2 +# define PATH_SEPARATOR_2 ';' +# endif +#endif + +#ifndef DIR_SEPARATOR_2 +# define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR) +#else /* DIR_SEPARATOR_2 */ +# define IS_DIR_SEPARATOR(ch) \ + (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2)) +#endif /* DIR_SEPARATOR_2 */ + +#ifndef PATH_SEPARATOR_2 +# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR) +#else /* PATH_SEPARATOR_2 */ +# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR_2) +#endif /* PATH_SEPARATOR_2 */ + +#define XMALLOC(type, num) ((type *) xmalloc ((num) * sizeof(type))) +#define XFREE(stale) do { \ + if (stale) { free ((void *) stale); stale = 0; } \ +} while (0) + +/* -DDEBUG is fairly common in CFLAGS. */ +#undef DEBUG +#if defined DEBUGWRAPPER +# define DEBUG(format, ...) fprintf(stderr, format, __VA_ARGS__) +#else +# define DEBUG(format, ...) +#endif + +const char *program_name = NULL; + +void * xmalloc (size_t num); +char * xstrdup (const char *string); +const char * base_name (const char *name); +char * find_executable(const char *wrapper); +int check_executable(const char *path); +char * strendzap(char *str, const char *pat); +void lt_fatal (const char *message, ...); + +int +main (int argc, char *argv[]) +{ + char **newargz; + int i; + + program_name = (char *) xstrdup (base_name (argv[0])); + DEBUG("(main) argv[0] : %s\n",argv[0]); + DEBUG("(main) program_name : %s\n",program_name); + newargz = XMALLOC(char *, argc+2); +EOF + + cat >> $cwrappersource <> $cwrappersource <<"EOF" + newargz[1] = find_executable(argv[0]); + if (newargz[1] == NULL) + lt_fatal("Couldn't find %s", argv[0]); + DEBUG("(main) found exe at : %s\n",newargz[1]); + /* we know the script has the same name, without the .exe */ + /* so make sure newargz[1] doesn't end in .exe */ + strendzap(newargz[1],".exe"); + for (i = 1; i < argc; i++) + newargz[i+1] = xstrdup(argv[i]); + newargz[argc+1] = NULL; + + for (i=0; i> $cwrappersource <> $cwrappersource <> $cwrappersource <<"EOF" + return 127; +} + +void * +xmalloc (size_t num) +{ + void * p = (void *) malloc (num); + if (!p) + lt_fatal ("Memory exhausted"); + + return p; +} + +char * +xstrdup (const char *string) +{ + return string ? strcpy ((char *) xmalloc (strlen (string) + 1), string) : NULL +; +} + +const char * +base_name (const char *name) +{ + const char *base; + +#if defined (HAVE_DOS_BASED_FILE_SYSTEM) + /* Skip over the disk name in MSDOS pathnames. */ + if (isalpha ((unsigned char)name[0]) && name[1] == ':') + name += 2; +#endif + + for (base = name; *name; name++) + if (IS_DIR_SEPARATOR (*name)) + base = name + 1; + return base; +} + +int +check_executable(const char * path) +{ + struct stat st; + + DEBUG("(check_executable) : %s\n", path ? (*path ? path : "EMPTY!") : "NULL!"); + if ((!path) || (!*path)) + return 0; + + if ((stat (path, &st) >= 0) && + ( + /* MinGW & native WIN32 do not support S_IXOTH or S_IXGRP */ +#if defined (S_IXOTH) + ((st.st_mode & S_IXOTH) == S_IXOTH) || +#endif +#if defined (S_IXGRP) + ((st.st_mode & S_IXGRP) == S_IXGRP) || +#endif + ((st.st_mode & S_IXUSR) == S_IXUSR)) + ) + return 1; + else + return 0; +} + +/* Searches for the full path of the wrapper. Returns + newly allocated full path name if found, NULL otherwise */ +char * +find_executable (const char* wrapper) +{ + int has_slash = 0; + const char* p; + const char* p_next; + /* static buffer for getcwd */ + char tmp[LT_PATHMAX + 1]; + int tmp_len; + char* concat_name; + + DEBUG("(find_executable) : %s\n", wrapper ? (*wrapper ? wrapper : "EMPTY!") : "NULL!"); + + if ((wrapper == NULL) || (*wrapper == '\0')) + return NULL; + + /* Absolute path? */ +#if defined (HAVE_DOS_BASED_FILE_SYSTEM) + if (isalpha ((unsigned char)wrapper[0]) && wrapper[1] == ':') + { + concat_name = xstrdup (wrapper); + if (check_executable(concat_name)) + return concat_name; + XFREE(concat_name); + } + else + { +#endif + if (IS_DIR_SEPARATOR (wrapper[0])) + { + concat_name = xstrdup (wrapper); + if (check_executable(concat_name)) + return concat_name; + XFREE(concat_name); + } +#if defined (HAVE_DOS_BASED_FILE_SYSTEM) + } +#endif + + for (p = wrapper; *p; p++) + if (*p == '/') + { + has_slash = 1; + break; + } + if (!has_slash) + { + /* no slashes; search PATH */ + const char* path = getenv ("PATH"); + if (path != NULL) + { + for (p = path; *p; p = p_next) + { + const char* q; + size_t p_len; + for (q = p; *q; q++) + if (IS_PATH_SEPARATOR(*q)) + break; + p_len = q - p; + p_next = (*q == '\0' ? q : q + 1); + if (p_len == 0) + { + /* empty path: current directory */ + if (getcwd (tmp, LT_PATHMAX) == NULL) + lt_fatal ("getcwd failed"); + tmp_len = strlen(tmp); + concat_name = XMALLOC(char, tmp_len + 1 + strlen(wrapper) + 1); + memcpy (concat_name, tmp, tmp_len); + concat_name[tmp_len] = '/'; + strcpy (concat_name + tmp_len + 1, wrapper); + } + else + { + concat_name = XMALLOC(char, p_len + 1 + strlen(wrapper) + 1); + memcpy (concat_name, p, p_len); + concat_name[p_len] = '/'; + strcpy (concat_name + p_len + 1, wrapper); + } + if (check_executable(concat_name)) + return concat_name; + XFREE(concat_name); + } + } + /* not found in PATH; assume curdir */ + } + /* Relative path | not found in path: prepend cwd */ + if (getcwd (tmp, LT_PATHMAX) == NULL) + lt_fatal ("getcwd failed"); + tmp_len = strlen(tmp); + concat_name = XMALLOC(char, tmp_len + 1 + strlen(wrapper) + 1); + memcpy (concat_name, tmp, tmp_len); + concat_name[tmp_len] = '/'; + strcpy (concat_name + tmp_len + 1, wrapper); + + if (check_executable(concat_name)) + return concat_name; + XFREE(concat_name); + return NULL; +} + +char * +strendzap(char *str, const char *pat) +{ + size_t len, patlen; + + assert(str != NULL); + assert(pat != NULL); + + len = strlen(str); + patlen = strlen(pat); + + if (patlen <= len) + { + str += len - patlen; + if (strcmp(str, pat) == 0) + *str = '\0'; + } + return str; +} + +static void +lt_error_core (int exit_status, const char * mode, + const char * message, va_list ap) +{ + fprintf (stderr, "%s: %s: ", program_name, mode); + vfprintf (stderr, message, ap); + fprintf (stderr, ".\n"); + + if (exit_status >= 0) + exit (exit_status); +} + +void +lt_fatal (const char *message, ...) +{ + va_list ap; + va_start (ap, message); + lt_error_core (EXIT_FAILURE, "FATAL", message, ap); + va_end (ap); +} +EOF + # we should really use a build-platform specific compiler + # here, but OTOH, the wrappers (shell script and this C one) + # are only useful if you want to execute the "real" binary. + # Since the "real" binary is built for $host, then this + # wrapper might as well be built for $host, too. + $run $LTCC $LTCFLAGS -s -o $cwrapper $cwrappersource + ;; + esac + $rm $output + trap "$rm $output; exit $EXIT_FAILURE" 1 2 15 + + $echo > $output "\ +#! $SHELL + +# $output - temporary wrapper script for $objdir/$outputname +# Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP +# +# The $output program cannot be directly executed until all the libtool +# libraries that it depends on are installed. +# +# This wrapper script should never be moved out of the build directory. +# If it is, it will not operate correctly. + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +Xsed='${SED} -e 1s/^X//' +sed_quote_subst='$sed_quote_subst' + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +relink_command=\"$relink_command\" + +# This environment variable determines our operation mode. +if test \"\$libtool_install_magic\" = \"$magic\"; then + # install mode needs the following variable: + notinst_deplibs='$notinst_deplibs' +else + # When we are sourced in execute mode, \$file and \$echo are already set. + if test \"\$libtool_execute_magic\" != \"$magic\"; then + echo=\"$qecho\" + file=\"\$0\" + # Make sure echo works. + if test \"X\$1\" = X--no-reexec; then + # Discard the --no-reexec flag, and continue. + shift + elif test \"X\`(\$echo '\t') 2>/dev/null\`\" = 'X\t'; then + # Yippee, \$echo works! + : + else + # Restart under the correct shell, and then maybe \$echo will work. + exec $SHELL \"\$0\" --no-reexec \${1+\"\$@\"} + fi + fi\ +" + $echo >> $output "\ + + # Find the directory that this script lives in. + thisdir=\`\$echo \"X\$file\" | \$Xsed -e 's%/[^/]*$%%'\` + test \"x\$thisdir\" = \"x\$file\" && thisdir=. + + # Follow symbolic links until we get to the real thisdir. + file=\`ls -ld \"\$file\" | ${SED} -n 's/.*-> //p'\` + while test -n \"\$file\"; do + destdir=\`\$echo \"X\$file\" | \$Xsed -e 's%/[^/]*\$%%'\` + + # If there was a directory component, then change thisdir. + if test \"x\$destdir\" != \"x\$file\"; then + case \"\$destdir\" in + [\\\\/]* | [A-Za-z]:[\\\\/]*) thisdir=\"\$destdir\" ;; + *) thisdir=\"\$thisdir/\$destdir\" ;; + esac + fi + + file=\`\$echo \"X\$file\" | \$Xsed -e 's%^.*/%%'\` + file=\`ls -ld \"\$thisdir/\$file\" | ${SED} -n 's/.*-> //p'\` + done + + # Try to get the absolute directory name. + absdir=\`cd \"\$thisdir\" && pwd\` + test -n \"\$absdir\" && thisdir=\"\$absdir\" +" + + if test "$fast_install" = yes; then + $echo >> $output "\ + program=lt-'$outputname'$exeext + progdir=\"\$thisdir/$objdir\" + + if test ! -f \"\$progdir/\$program\" || \\ + { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | ${SED} 1q\`; \\ + test \"X\$file\" != \"X\$progdir/\$program\"; }; then + + file=\"\$\$-\$program\" + + if test ! -d \"\$progdir\"; then + $mkdir \"\$progdir\" + else + $rm \"\$progdir/\$file\" + fi" + + $echo >> $output "\ + + # relink executable if necessary + if test -n \"\$relink_command\"; then + if relink_command_output=\`eval \$relink_command 2>&1\`; then : + else + $echo \"\$relink_command_output\" >&2 + $rm \"\$progdir/\$file\" + exit $EXIT_FAILURE + fi + fi + + $mv \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null || + { $rm \"\$progdir/\$program\"; + $mv \"\$progdir/\$file\" \"\$progdir/\$program\"; } + $rm \"\$progdir/\$file\" + fi" + else + $echo >> $output "\ + program='$outputname' + progdir=\"\$thisdir/$objdir\" +" + fi + + $echo >> $output "\ + + if test -f \"\$progdir/\$program\"; then" + + # Export our shlibpath_var if we have one. + if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then + $echo >> $output "\ + # Add our own library path to $shlibpath_var + $shlibpath_var=\"$temp_rpath\$$shlibpath_var\" + + # Some systems cannot cope with colon-terminated $shlibpath_var + # The second colon is a workaround for a bug in BeOS R4 sed + $shlibpath_var=\`\$echo \"X\$$shlibpath_var\" | \$Xsed -e 's/::*\$//'\` + + export $shlibpath_var +" + fi + + # fixup the dll searchpath if we need to. + if test -n "$dllsearchpath"; then + $echo >> $output "\ + # Add the dll search path components to the executable PATH + PATH=$dllsearchpath:\$PATH +" + fi + + $echo >> $output "\ + if test \"\$libtool_execute_magic\" != \"$magic\"; then + # Run the actual program with our arguments. +" + case $host in + # Backslashes separate directories on plain windows + *-*-mingw | *-*-os2*) + $echo >> $output "\ + exec \"\$progdir\\\\\$program\" \${1+\"\$@\"} +" + ;; + + *) + $echo >> $output "\ + exec \"\$progdir/\$program\" \${1+\"\$@\"} +" + ;; + esac + $echo >> $output "\ + \$echo \"\$0: cannot exec \$program \${1+\"\$@\"}\" + exit $EXIT_FAILURE + fi + else + # The program doesn't exist. + \$echo \"\$0: error: \\\`\$progdir/\$program' does not exist\" 1>&2 + \$echo \"This script is just a wrapper for \$program.\" 1>&2 + $echo \"See the $PACKAGE documentation for more information.\" 1>&2 + exit $EXIT_FAILURE + fi +fi\ +" + chmod +x $output + fi + exit $EXIT_SUCCESS + ;; + esac + + # See if we need to build an old-fashioned archive. + for oldlib in $oldlibs; do + + if test "$build_libtool_libs" = convenience; then + oldobjs="$libobjs_save" + addlibs="$convenience" + build_libtool_libs=no + else + if test "$build_libtool_libs" = module; then + oldobjs="$libobjs_save" + build_libtool_libs=no + else + oldobjs="$old_deplibs $non_pic_objects" + fi + addlibs="$old_convenience" + fi + + if test -n "$addlibs"; then + gentop="$output_objdir/${outputname}x" + generated="$generated $gentop" + + func_extract_archives $gentop $addlibs + oldobjs="$oldobjs $func_extract_archives_result" + fi + + # Do each command in the archive commands. + if test -n "$old_archive_from_new_cmds" && test "$build_libtool_libs" = yes; then + cmds=$old_archive_from_new_cmds + else + # POSIX demands no paths to be encoded in archives. We have + # to avoid creating archives with duplicate basenames if we + # might have to extract them afterwards, e.g., when creating a + # static archive out of a convenience library, or when linking + # the entirety of a libtool archive into another (currently + # not supported by libtool). + if (for obj in $oldobjs + do + $echo "X$obj" | $Xsed -e 's%^.*/%%' + done | sort | sort -uc >/dev/null 2>&1); then + : + else + $echo "copying selected object files to avoid basename conflicts..." + + if test -z "$gentop"; then + gentop="$output_objdir/${outputname}x" + generated="$generated $gentop" + + $show "${rm}r $gentop" + $run ${rm}r "$gentop" + $show "$mkdir $gentop" + $run $mkdir "$gentop" + exit_status=$? + if test "$exit_status" -ne 0 && test ! -d "$gentop"; then + exit $exit_status + fi + fi + + save_oldobjs=$oldobjs + oldobjs= + counter=1 + for obj in $save_oldobjs + do + objbase=`$echo "X$obj" | $Xsed -e 's%^.*/%%'` + case " $oldobjs " in + " ") oldobjs=$obj ;; + *[\ /]"$objbase "*) + while :; do + # Make sure we don't pick an alternate name that also + # overlaps. + newobj=lt$counter-$objbase + counter=`expr $counter + 1` + case " $oldobjs " in + *[\ /]"$newobj "*) ;; + *) if test ! -f "$gentop/$newobj"; then break; fi ;; + esac + done + $show "ln $obj $gentop/$newobj || cp $obj $gentop/$newobj" + $run ln "$obj" "$gentop/$newobj" || + $run cp "$obj" "$gentop/$newobj" + oldobjs="$oldobjs $gentop/$newobj" + ;; + *) oldobjs="$oldobjs $obj" ;; + esac + done + fi + + eval cmds=\"$old_archive_cmds\" + + if len=`expr "X$cmds" : ".*"` && + test "$len" -le "$max_cmd_len" || test "$max_cmd_len" -le -1; then + cmds=$old_archive_cmds + else + # the command line is too long to link in one step, link in parts + $echo "using piecewise archive linking..." + save_RANLIB=$RANLIB + RANLIB=: + objlist= + concat_cmds= + save_oldobjs=$oldobjs + + # Is there a better way of finding the last object in the list? + for obj in $save_oldobjs + do + last_oldobj=$obj + done + for obj in $save_oldobjs + do + oldobjs="$objlist $obj" + objlist="$objlist $obj" + eval test_cmds=\"$old_archive_cmds\" + if len=`expr "X$test_cmds" : ".*" 2>/dev/null` && + test "$len" -le "$max_cmd_len"; then + : + else + # the above command should be used before it gets too long + oldobjs=$objlist + if test "$obj" = "$last_oldobj" ; then + RANLIB=$save_RANLIB + fi + test -z "$concat_cmds" || concat_cmds=$concat_cmds~ + eval concat_cmds=\"\${concat_cmds}$old_archive_cmds\" + objlist= + fi + done + RANLIB=$save_RANLIB + oldobjs=$objlist + if test "X$oldobjs" = "X" ; then + eval cmds=\"\$concat_cmds\" + else + eval cmds=\"\$concat_cmds~\$old_archive_cmds\" + fi + fi + fi + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + eval cmd=\"$cmd\" + IFS="$save_ifs" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + done + + if test -n "$generated"; then + $show "${rm}r$generated" + $run ${rm}r$generated + fi + + # Now create the libtool archive. + case $output in + *.la) + old_library= + test "$build_old_libs" = yes && old_library="$libname.$libext" + $show "creating $output" + + # Preserve any variables that may affect compiler behavior + for var in $variables_saved_for_relink; do + if eval test -z \"\${$var+set}\"; then + relink_command="{ test -z \"\${$var+set}\" || unset $var || { $var=; export $var; }; }; $relink_command" + elif eval var_value=\$$var; test -z "$var_value"; then + relink_command="$var=; export $var; $relink_command" + else + var_value=`$echo "X$var_value" | $Xsed -e "$sed_quote_subst"` + relink_command="$var=\"$var_value\"; export $var; $relink_command" + fi + done + # Quote the link command for shipping. + relink_command="(cd `pwd`; $SHELL $progpath $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)" + relink_command=`$echo "X$relink_command" | $Xsed -e "$sed_quote_subst"` + if test "$hardcode_automatic" = yes ; then + relink_command= + fi + + + # Only create the output if not a dry run. + if test -z "$run"; then + for installed in no yes; do + if test "$installed" = yes; then + if test -z "$install_libdir"; then + break + fi + output="$output_objdir/$outputname"i + # Replace all uninstalled libtool libraries with the installed ones + newdependency_libs= + for deplib in $dependency_libs; do + case $deplib in + *.la) + name=`$echo "X$deplib" | $Xsed -e 's%^.*/%%'` + eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` + if test -z "$libdir"; then + $echo "$modename: \`$deplib' is not a valid libtool archive" 1>&2 + exit $EXIT_FAILURE + fi + newdependency_libs="$newdependency_libs $libdir/$name" + ;; + *) newdependency_libs="$newdependency_libs $deplib" ;; + esac + done + dependency_libs="$newdependency_libs" + newdlfiles= + for lib in $dlfiles; do + name=`$echo "X$lib" | $Xsed -e 's%^.*/%%'` + eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` + if test -z "$libdir"; then + $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2 + exit $EXIT_FAILURE + fi + newdlfiles="$newdlfiles $libdir/$name" + done + dlfiles="$newdlfiles" + newdlprefiles= + for lib in $dlprefiles; do + name=`$echo "X$lib" | $Xsed -e 's%^.*/%%'` + eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` + if test -z "$libdir"; then + $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2 + exit $EXIT_FAILURE + fi + newdlprefiles="$newdlprefiles $libdir/$name" + done + dlprefiles="$newdlprefiles" + else + newdlfiles= + for lib in $dlfiles; do + case $lib in + [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;; + *) abs=`pwd`"/$lib" ;; + esac + newdlfiles="$newdlfiles $abs" + done + dlfiles="$newdlfiles" + newdlprefiles= + for lib in $dlprefiles; do + case $lib in + [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;; + *) abs=`pwd`"/$lib" ;; + esac + newdlprefiles="$newdlprefiles $abs" + done + dlprefiles="$newdlprefiles" + fi + $rm $output + # place dlname in correct position for cygwin + tdlname=$dlname + case $host,$output,$installed,$module,$dlname in + *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll) tdlname=../bin/$dlname ;; + esac + $echo > $output "\ +# $outputname - a libtool library file +# Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP +# +# Please DO NOT delete this file! +# It is necessary for linking the library. + +# The name that we can dlopen(3). +dlname='$tdlname' + +# Names of this library. +library_names='$library_names' + +# The name of the static archive. +old_library='$old_library' + +# Libraries that this one depends upon. +dependency_libs='$dependency_libs' + +# Version information for $libname. +current=$current +age=$age +revision=$revision + +# Is this an already installed library? +installed=$installed + +# Should we warn about portability when linking against -modules? +shouldnotlink=$module + +# Files to dlopen/dlpreopen +dlopen='$dlfiles' +dlpreopen='$dlprefiles' + +# Directory that this library needs to be installed in: +libdir='$install_libdir'" + if test "$installed" = no && test "$need_relink" = yes; then + $echo >> $output "\ +relink_command=\"$relink_command\"" + fi + done + fi + + # Do a symbolic link so that the libtool archive can be found in + # LD_LIBRARY_PATH before the program is installed. + $show "(cd $output_objdir && $rm $outputname && $LN_S ../$outputname $outputname)" + $run eval '(cd $output_objdir && $rm $outputname && $LN_S ../$outputname $outputname)' || exit $? + ;; + esac + exit $EXIT_SUCCESS + ;; + + # libtool install mode + install) + modename="$modename: install" + + # There may be an optional sh(1) argument at the beginning of + # install_prog (especially on Windows NT). + if test "$nonopt" = "$SHELL" || test "$nonopt" = /bin/sh || + # Allow the use of GNU shtool's install command. + $echo "X$nonopt" | grep shtool > /dev/null; then + # Aesthetically quote it. + arg=`$echo "X$nonopt" | $Xsed -e "$sed_quote_subst"` + case $arg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + arg="\"$arg\"" + ;; + esac + install_prog="$arg " + arg="$1" + shift + else + install_prog= + arg=$nonopt + fi + + # The real first argument should be the name of the installation program. + # Aesthetically quote it. + arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` + case $arg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + arg="\"$arg\"" + ;; + esac + install_prog="$install_prog$arg" + + # We need to accept at least all the BSD install flags. + dest= + files= + opts= + prev= + install_type= + isdir=no + stripme= + for arg + do + if test -n "$dest"; then + files="$files $dest" + dest=$arg + continue + fi + + case $arg in + -d) isdir=yes ;; + -f) + case " $install_prog " in + *[\\\ /]cp\ *) ;; + *) prev=$arg ;; + esac + ;; + -g | -m | -o) prev=$arg ;; + -s) + stripme=" -s" + continue + ;; + -*) + ;; + *) + # If the previous option needed an argument, then skip it. + if test -n "$prev"; then + prev= + else + dest=$arg + continue + fi + ;; + esac + + # Aesthetically quote the argument. + arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` + case $arg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + arg="\"$arg\"" + ;; + esac + install_prog="$install_prog $arg" + done + + if test -z "$install_prog"; then + $echo "$modename: you must specify an install program" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + + if test -n "$prev"; then + $echo "$modename: the \`$prev' option requires an argument" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + + if test -z "$files"; then + if test -z "$dest"; then + $echo "$modename: no file or destination specified" 1>&2 + else + $echo "$modename: you must specify a destination" 1>&2 + fi + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + + # Strip any trailing slash from the destination. + dest=`$echo "X$dest" | $Xsed -e 's%/$%%'` + + # Check to see that the destination is a directory. + test -d "$dest" && isdir=yes + if test "$isdir" = yes; then + destdir="$dest" + destname= + else + destdir=`$echo "X$dest" | $Xsed -e 's%/[^/]*$%%'` + test "X$destdir" = "X$dest" && destdir=. + destname=`$echo "X$dest" | $Xsed -e 's%^.*/%%'` + + # Not a directory, so check to see that there is only one file specified. + set dummy $files + if test "$#" -gt 2; then + $echo "$modename: \`$dest' is not a directory" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + fi + case $destdir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + for file in $files; do + case $file in + *.lo) ;; + *) + $echo "$modename: \`$destdir' must be an absolute directory name" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + ;; + esac + done + ;; + esac + + # This variable tells wrapper scripts just to set variables rather + # than running their programs. + libtool_install_magic="$magic" + + staticlibs= + future_libdirs= + current_libdirs= + for file in $files; do + + # Do each installation. + case $file in + *.$libext) + # Do the static libraries later. + staticlibs="$staticlibs $file" + ;; + + *.la) + # Check to see that this really is a libtool archive. + if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then : + else + $echo "$modename: \`$file' is not a valid libtool archive" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + + library_names= + old_library= + relink_command= + # If there is no directory component, then add one. + case $file in + */* | *\\*) . $file ;; + *) . ./$file ;; + esac + + # Add the libdir to current_libdirs if it is the destination. + if test "X$destdir" = "X$libdir"; then + case "$current_libdirs " in + *" $libdir "*) ;; + *) current_libdirs="$current_libdirs $libdir" ;; + esac + else + # Note the libdir as a future libdir. + case "$future_libdirs " in + *" $libdir "*) ;; + *) future_libdirs="$future_libdirs $libdir" ;; + esac + fi + + dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`/ + test "X$dir" = "X$file/" && dir= + dir="$dir$objdir" + + if test -n "$relink_command"; then + # Determine the prefix the user has applied to our future dir. + inst_prefix_dir=`$echo "$destdir" | $SED "s%$libdir\$%%"` + + # Don't allow the user to place us outside of our expected + # location b/c this prevents finding dependent libraries that + # are installed to the same prefix. + # At present, this check doesn't affect windows .dll's that + # are installed into $libdir/../bin (currently, that works fine) + # but it's something to keep an eye on. + if test "$inst_prefix_dir" = "$destdir"; then + $echo "$modename: error: cannot install \`$file' to a directory not ending in $libdir" 1>&2 + exit $EXIT_FAILURE + fi + + if test -n "$inst_prefix_dir"; then + # Stick the inst_prefix_dir data into the link command. + relink_command=`$echo "$relink_command" | $SED "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"` + else + relink_command=`$echo "$relink_command" | $SED "s%@inst_prefix_dir@%%"` + fi + + $echo "$modename: warning: relinking \`$file'" 1>&2 + $show "$relink_command" + if $run eval "$relink_command"; then : + else + $echo "$modename: error: relink \`$file' with the above command before installing it" 1>&2 + exit $EXIT_FAILURE + fi + fi + + # See the names of the shared library. + set dummy $library_names + if test -n "$2"; then + realname="$2" + shift + shift + + srcname="$realname" + test -n "$relink_command" && srcname="$realname"T + + # Install the shared library and build the symlinks. + $show "$install_prog $dir/$srcname $destdir/$realname" + $run eval "$install_prog $dir/$srcname $destdir/$realname" || exit $? + if test -n "$stripme" && test -n "$striplib"; then + $show "$striplib $destdir/$realname" + $run eval "$striplib $destdir/$realname" || exit $? + fi + + if test "$#" -gt 0; then + # Delete the old symlinks, and create new ones. + # Try `ln -sf' first, because the `ln' binary might depend on + # the symlink we replace! Solaris /bin/ln does not understand -f, + # so we also need to try rm && ln -s. + for linkname + do + if test "$linkname" != "$realname"; then + $show "(cd $destdir && { $LN_S -f $realname $linkname || { $rm $linkname && $LN_S $realname $linkname; }; })" + $run eval "(cd $destdir && { $LN_S -f $realname $linkname || { $rm $linkname && $LN_S $realname $linkname; }; })" + fi + done + fi + + # Do each command in the postinstall commands. + lib="$destdir/$realname" + cmds=$postinstall_cmds + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + $show "$cmd" + $run eval "$cmd" || { + lt_exit=$? + + # Restore the uninstalled library and exit + if test "$mode" = relink; then + $run eval '(cd $output_objdir && $rm ${realname}T && $mv ${realname}U $realname)' + fi + + exit $lt_exit + } + done + IFS="$save_ifs" + fi + + # Install the pseudo-library for information purposes. + name=`$echo "X$file" | $Xsed -e 's%^.*/%%'` + instname="$dir/$name"i + $show "$install_prog $instname $destdir/$name" + $run eval "$install_prog $instname $destdir/$name" || exit $? + + # Maybe install the static library, too. + test -n "$old_library" && staticlibs="$staticlibs $dir/$old_library" + ;; + + *.lo) + # Install (i.e. copy) a libtool object. + + # Figure out destination file name, if it wasn't already specified. + if test -n "$destname"; then + destfile="$destdir/$destname" + else + destfile=`$echo "X$file" | $Xsed -e 's%^.*/%%'` + destfile="$destdir/$destfile" + fi + + # Deduce the name of the destination old-style object file. + case $destfile in + *.lo) + staticdest=`$echo "X$destfile" | $Xsed -e "$lo2o"` + ;; + *.$objext) + staticdest="$destfile" + destfile= + ;; + *) + $echo "$modename: cannot copy a libtool object to \`$destfile'" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + ;; + esac + + # Install the libtool object if requested. + if test -n "$destfile"; then + $show "$install_prog $file $destfile" + $run eval "$install_prog $file $destfile" || exit $? + fi + + # Install the old object if enabled. + if test "$build_old_libs" = yes; then + # Deduce the name of the old-style object file. + staticobj=`$echo "X$file" | $Xsed -e "$lo2o"` + + $show "$install_prog $staticobj $staticdest" + $run eval "$install_prog \$staticobj \$staticdest" || exit $? + fi + exit $EXIT_SUCCESS + ;; + + *) + # Figure out destination file name, if it wasn't already specified. + if test -n "$destname"; then + destfile="$destdir/$destname" + else + destfile=`$echo "X$file" | $Xsed -e 's%^.*/%%'` + destfile="$destdir/$destfile" + fi + + # If the file is missing, and there is a .exe on the end, strip it + # because it is most likely a libtool script we actually want to + # install + stripped_ext="" + case $file in + *.exe) + if test ! -f "$file"; then + file=`$echo $file|${SED} 's,.exe$,,'` + stripped_ext=".exe" + fi + ;; + esac + + # Do a test to see if this is really a libtool program. + case $host in + *cygwin*|*mingw*) + wrapper=`$echo $file | ${SED} -e 's,.exe$,,'` + ;; + *) + wrapper=$file + ;; + esac + if (${SED} -e '4q' $wrapper | grep "^# Generated by .*$PACKAGE")>/dev/null 2>&1; then + notinst_deplibs= + relink_command= + + # Note that it is not necessary on cygwin/mingw to append a dot to + # foo even if both foo and FILE.exe exist: automatic-append-.exe + # behavior happens only for exec(3), not for open(2)! Also, sourcing + # `FILE.' does not work on cygwin managed mounts. + # + # If there is no directory component, then add one. + case $wrapper in + */* | *\\*) . ${wrapper} ;; + *) . ./${wrapper} ;; + esac + + # Check the variables that should have been set. + if test -z "$notinst_deplibs"; then + $echo "$modename: invalid libtool wrapper script \`$wrapper'" 1>&2 + exit $EXIT_FAILURE + fi + + finalize=yes + for lib in $notinst_deplibs; do + # Check to see that each library is installed. + libdir= + if test -f "$lib"; then + # If there is no directory component, then add one. + case $lib in + */* | *\\*) . $lib ;; + *) . ./$lib ;; + esac + fi + libfile="$libdir/"`$echo "X$lib" | $Xsed -e 's%^.*/%%g'` ### testsuite: skip nested quoting test + if test -n "$libdir" && test ! -f "$libfile"; then + $echo "$modename: warning: \`$lib' has not been installed in \`$libdir'" 1>&2 + finalize=no + fi + done + + relink_command= + # Note that it is not necessary on cygwin/mingw to append a dot to + # foo even if both foo and FILE.exe exist: automatic-append-.exe + # behavior happens only for exec(3), not for open(2)! Also, sourcing + # `FILE.' does not work on cygwin managed mounts. + # + # If there is no directory component, then add one. + case $wrapper in + */* | *\\*) . ${wrapper} ;; + *) . ./${wrapper} ;; + esac + + outputname= + if test "$fast_install" = no && test -n "$relink_command"; then + if test "$finalize" = yes && test -z "$run"; then + tmpdir=`func_mktempdir` + file=`$echo "X$file$stripped_ext" | $Xsed -e 's%^.*/%%'` + outputname="$tmpdir/$file" + # Replace the output file specification. + relink_command=`$echo "X$relink_command" | $Xsed -e 's%@OUTPUT@%'"$outputname"'%g'` + + $show "$relink_command" + if $run eval "$relink_command"; then : + else + $echo "$modename: error: relink \`$file' with the above command before installing it" 1>&2 + ${rm}r "$tmpdir" + continue + fi + file="$outputname" + else + $echo "$modename: warning: cannot relink \`$file'" 1>&2 + fi + else + # Install the binary that we compiled earlier. + file=`$echo "X$file$stripped_ext" | $Xsed -e "s%\([^/]*\)$%$objdir/\1%"` + fi + fi + + # remove .exe since cygwin /usr/bin/install will append another + # one anyway + case $install_prog,$host in + */usr/bin/install*,*cygwin*) + case $file:$destfile in + *.exe:*.exe) + # this is ok + ;; + *.exe:*) + destfile=$destfile.exe + ;; + *:*.exe) + destfile=`$echo $destfile | ${SED} -e 's,.exe$,,'` + ;; + esac + ;; + esac + $show "$install_prog$stripme $file $destfile" + $run eval "$install_prog\$stripme \$file \$destfile" || exit $? + test -n "$outputname" && ${rm}r "$tmpdir" + ;; + esac + done + + for file in $staticlibs; do + name=`$echo "X$file" | $Xsed -e 's%^.*/%%'` + + # Set up the ranlib parameters. + oldlib="$destdir/$name" + + $show "$install_prog $file $oldlib" + $run eval "$install_prog \$file \$oldlib" || exit $? + + if test -n "$stripme" && test -n "$old_striplib"; then + $show "$old_striplib $oldlib" + $run eval "$old_striplib $oldlib" || exit $? + fi + + # Do each command in the postinstall commands. + cmds=$old_postinstall_cmds + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + done + + if test -n "$future_libdirs"; then + $echo "$modename: warning: remember to run \`$progname --finish$future_libdirs'" 1>&2 + fi + + if test -n "$current_libdirs"; then + # Maybe just do a dry run. + test -n "$run" && current_libdirs=" -n$current_libdirs" + exec_cmd='$SHELL $progpath $preserve_args --finish$current_libdirs' + else + exit $EXIT_SUCCESS + fi + ;; + + # libtool finish mode + finish) + modename="$modename: finish" + libdirs="$nonopt" + admincmds= + + if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then + for dir + do + libdirs="$libdirs $dir" + done + + for libdir in $libdirs; do + if test -n "$finish_cmds"; then + # Do each command in the finish commands. + cmds=$finish_cmds + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + $show "$cmd" + $run eval "$cmd" || admincmds="$admincmds + $cmd" + done + IFS="$save_ifs" + fi + if test -n "$finish_eval"; then + # Do the single finish_eval. + eval cmds=\"$finish_eval\" + $run eval "$cmds" || admincmds="$admincmds + $cmds" + fi + done + fi + + # Exit here if they wanted silent mode. + test "$show" = : && exit $EXIT_SUCCESS + + $echo "X----------------------------------------------------------------------" | $Xsed + $echo "Libraries have been installed in:" + for libdir in $libdirs; do + $echo " $libdir" + done + $echo + $echo "If you ever happen to want to link against installed libraries" + $echo "in a given directory, LIBDIR, you must either use libtool, and" + $echo "specify the full pathname of the library, or use the \`-LLIBDIR'" + $echo "flag during linking and do at least one of the following:" + if test -n "$shlibpath_var"; then + $echo " - add LIBDIR to the \`$shlibpath_var' environment variable" + $echo " during execution" + fi + if test -n "$runpath_var"; then + $echo " - add LIBDIR to the \`$runpath_var' environment variable" + $echo " during linking" + fi + if test -n "$hardcode_libdir_flag_spec"; then + libdir=LIBDIR + eval flag=\"$hardcode_libdir_flag_spec\" + + $echo " - use the \`$flag' linker flag" + fi + if test -n "$admincmds"; then + $echo " - have your system administrator run these commands:$admincmds" + fi + if test -f /etc/ld.so.conf; then + $echo " - have your system administrator add LIBDIR to \`/etc/ld.so.conf'" + fi + $echo + $echo "See any operating system documentation about shared libraries for" + $echo "more information, such as the ld(1) and ld.so(8) manual pages." + $echo "X----------------------------------------------------------------------" | $Xsed + exit $EXIT_SUCCESS + ;; + + # libtool execute mode + execute) + modename="$modename: execute" + + # The first argument is the command name. + cmd="$nonopt" + if test -z "$cmd"; then + $echo "$modename: you must specify a COMMAND" 1>&2 + $echo "$help" + exit $EXIT_FAILURE + fi + + # Handle -dlopen flags immediately. + for file in $execute_dlfiles; do + if test ! -f "$file"; then + $echo "$modename: \`$file' is not a file" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + + dir= + case $file in + *.la) + # Check to see that this really is a libtool archive. + if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then : + else + $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + + # Read the libtool library. + dlname= + library_names= + + # If there is no directory component, then add one. + case $file in + */* | *\\*) . $file ;; + *) . ./$file ;; + esac + + # Skip this library if it cannot be dlopened. + if test -z "$dlname"; then + # Warn if it was a shared library. + test -n "$library_names" && $echo "$modename: warning: \`$file' was not linked with \`-export-dynamic'" + continue + fi + + dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'` + test "X$dir" = "X$file" && dir=. + + if test -f "$dir/$objdir/$dlname"; then + dir="$dir/$objdir" + else + $echo "$modename: cannot find \`$dlname' in \`$dir' or \`$dir/$objdir'" 1>&2 + exit $EXIT_FAILURE + fi + ;; + + *.lo) + # Just add the directory containing the .lo file. + dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'` + test "X$dir" = "X$file" && dir=. + ;; + + *) + $echo "$modename: warning \`-dlopen' is ignored for non-libtool libraries and objects" 1>&2 + continue + ;; + esac + + # Get the absolute pathname. + absdir=`cd "$dir" && pwd` + test -n "$absdir" && dir="$absdir" + + # Now add the directory to shlibpath_var. + if eval "test -z \"\$$shlibpath_var\""; then + eval "$shlibpath_var=\"\$dir\"" + else + eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\"" + fi + done + + # This variable tells wrapper scripts just to set shlibpath_var + # rather than running their programs. + libtool_execute_magic="$magic" + + # Check if any of the arguments is a wrapper script. + args= + for file + do + case $file in + -*) ;; + *) + # Do a test to see if this is really a libtool program. + if (${SED} -e '4q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then + # If there is no directory component, then add one. + case $file in + */* | *\\*) . $file ;; + *) . ./$file ;; + esac + + # Transform arg to wrapped name. + file="$progdir/$program" + fi + ;; + esac + # Quote arguments (to preserve shell metacharacters). + file=`$echo "X$file" | $Xsed -e "$sed_quote_subst"` + args="$args \"$file\"" + done + + if test -z "$run"; then + if test -n "$shlibpath_var"; then + # Export the shlibpath_var. + eval "export $shlibpath_var" + fi + + # Restore saved environment variables + if test "${save_LC_ALL+set}" = set; then + LC_ALL="$save_LC_ALL"; export LC_ALL + fi + if test "${save_LANG+set}" = set; then + LANG="$save_LANG"; export LANG + fi + + # Now prepare to actually exec the command. + exec_cmd="\$cmd$args" + else + # Display what would be done. + if test -n "$shlibpath_var"; then + eval "\$echo \"\$shlibpath_var=\$$shlibpath_var\"" + $echo "export $shlibpath_var" + fi + $echo "$cmd$args" + exit $EXIT_SUCCESS + fi + ;; + + # libtool clean and uninstall mode + clean | uninstall) + modename="$modename: $mode" + rm="$nonopt" + files= + rmforce= + exit_status=0 + + # This variable tells wrapper scripts just to set variables rather + # than running their programs. + libtool_install_magic="$magic" + + for arg + do + case $arg in + -f) rm="$rm $arg"; rmforce=yes ;; + -*) rm="$rm $arg" ;; + *) files="$files $arg" ;; + esac + done + + if test -z "$rm"; then + $echo "$modename: you must specify an RM program" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + + rmdirs= + + origobjdir="$objdir" + for file in $files; do + dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'` + if test "X$dir" = "X$file"; then + dir=. + objdir="$origobjdir" + else + objdir="$dir/$origobjdir" + fi + name=`$echo "X$file" | $Xsed -e 's%^.*/%%'` + test "$mode" = uninstall && objdir="$dir" + + # Remember objdir for removal later, being careful to avoid duplicates + if test "$mode" = clean; then + case " $rmdirs " in + *" $objdir "*) ;; + *) rmdirs="$rmdirs $objdir" ;; + esac + fi + + # Don't error if the file doesn't exist and rm -f was used. + if (test -L "$file") >/dev/null 2>&1 \ + || (test -h "$file") >/dev/null 2>&1 \ + || test -f "$file"; then + : + elif test -d "$file"; then + exit_status=1 + continue + elif test "$rmforce" = yes; then + continue + fi + + rmfiles="$file" + + case $name in + *.la) + # Possibly a libtool archive, so verify it. + if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then + . $dir/$name + + # Delete the libtool libraries and symlinks. + for n in $library_names; do + rmfiles="$rmfiles $objdir/$n" + done + test -n "$old_library" && rmfiles="$rmfiles $objdir/$old_library" + + case "$mode" in + clean) + case " $library_names " in + # " " in the beginning catches empty $dlname + *" $dlname "*) ;; + *) rmfiles="$rmfiles $objdir/$dlname" ;; + esac + test -n "$libdir" && rmfiles="$rmfiles $objdir/$name $objdir/${name}i" + ;; + uninstall) + if test -n "$library_names"; then + # Do each command in the postuninstall commands. + cmds=$postuninstall_cmds + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + $show "$cmd" + $run eval "$cmd" + if test "$?" -ne 0 && test "$rmforce" != yes; then + exit_status=1 + fi + done + IFS="$save_ifs" + fi + + if test -n "$old_library"; then + # Do each command in the old_postuninstall commands. + cmds=$old_postuninstall_cmds + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + $show "$cmd" + $run eval "$cmd" + if test "$?" -ne 0 && test "$rmforce" != yes; then + exit_status=1 + fi + done + IFS="$save_ifs" + fi + # FIXME: should reinstall the best remaining shared library. + ;; + esac + fi + ;; + + *.lo) + # Possibly a libtool object, so verify it. + if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then + + # Read the .lo file + . $dir/$name + + # Add PIC object to the list of files to remove. + if test -n "$pic_object" \ + && test "$pic_object" != none; then + rmfiles="$rmfiles $dir/$pic_object" + fi + + # Add non-PIC object to the list of files to remove. + if test -n "$non_pic_object" \ + && test "$non_pic_object" != none; then + rmfiles="$rmfiles $dir/$non_pic_object" + fi + fi + ;; + + *) + if test "$mode" = clean ; then + noexename=$name + case $file in + *.exe) + file=`$echo $file|${SED} 's,.exe$,,'` + noexename=`$echo $name|${SED} 's,.exe$,,'` + # $file with .exe has already been added to rmfiles, + # add $file without .exe + rmfiles="$rmfiles $file" + ;; + esac + # Do a test to see if this is a libtool program. + if (${SED} -e '4q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then + relink_command= + . $dir/$noexename + + # note $name still contains .exe if it was in $file originally + # as does the version of $file that was added into $rmfiles + rmfiles="$rmfiles $objdir/$name $objdir/${name}S.${objext}" + if test "$fast_install" = yes && test -n "$relink_command"; then + rmfiles="$rmfiles $objdir/lt-$name" + fi + if test "X$noexename" != "X$name" ; then + rmfiles="$rmfiles $objdir/lt-${noexename}.c" + fi + fi + fi + ;; + esac + $show "$rm $rmfiles" + $run $rm $rmfiles || exit_status=1 + done + objdir="$origobjdir" + + # Try to remove the ${objdir}s in the directories where we deleted files + for dir in $rmdirs; do + if test -d "$dir"; then + $show "rmdir $dir" + $run rmdir $dir >/dev/null 2>&1 + fi + done + + exit $exit_status + ;; + + "") + $echo "$modename: you must specify a MODE" 1>&2 + $echo "$generic_help" 1>&2 + exit $EXIT_FAILURE + ;; + esac + + if test -z "$exec_cmd"; then + $echo "$modename: invalid operation mode \`$mode'" 1>&2 + $echo "$generic_help" 1>&2 + exit $EXIT_FAILURE + fi +fi # test -z "$show_help" + +if test -n "$exec_cmd"; then + eval exec $exec_cmd + exit $EXIT_FAILURE +fi + +# We need to display help for each of the modes. +case $mode in +"") $echo \ +"Usage: $modename [OPTION]... [MODE-ARG]... + +Provide generalized library-building support services. + + --config show all configuration variables + --debug enable verbose shell tracing +-n, --dry-run display commands without modifying any files + --features display basic configuration information and exit + --finish same as \`--mode=finish' + --help display this help message and exit + --mode=MODE use operation mode MODE [default=inferred from MODE-ARGS] + --quiet same as \`--silent' + --silent don't print informational messages + --tag=TAG use configuration variables from tag TAG + --version print version information + +MODE must be one of the following: + + clean remove files from the build directory + compile compile a source file into a libtool object + execute automatically set library path, then run a program + finish complete the installation of libtool libraries + install install libraries or executables + link create a library or an executable + uninstall remove libraries from an installed directory + +MODE-ARGS vary depending on the MODE. Try \`$modename --help --mode=MODE' for +a more detailed description of MODE. + +Report bugs to ." + exit $EXIT_SUCCESS + ;; + +clean) + $echo \ +"Usage: $modename [OPTION]... --mode=clean RM [RM-OPTION]... FILE... + +Remove files from the build directory. + +RM is the name of the program to use to delete files associated with each FILE +(typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed +to RM. + +If FILE is a libtool library, object or program, all the files associated +with it are deleted. Otherwise, only FILE itself is deleted using RM." + ;; + +compile) + $echo \ +"Usage: $modename [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE + +Compile a source file into a libtool library object. + +This mode accepts the following additional options: + + -o OUTPUT-FILE set the output file name to OUTPUT-FILE + -prefer-pic try to building PIC objects only + -prefer-non-pic try to building non-PIC objects only + -static always build a \`.o' file suitable for static linking + +COMPILE-COMMAND is a command to be used in creating a \`standard' object file +from the given SOURCEFILE. + +The output file name is determined by removing the directory component from +SOURCEFILE, then substituting the C source code suffix \`.c' with the +library object suffix, \`.lo'." + ;; + +execute) + $echo \ +"Usage: $modename [OPTION]... --mode=execute COMMAND [ARGS]... + +Automatically set library path, then run a program. + +This mode accepts the following additional options: + + -dlopen FILE add the directory containing FILE to the library path + +This mode sets the library path environment variable according to \`-dlopen' +flags. + +If any of the ARGS are libtool executable wrappers, then they are translated +into their corresponding uninstalled binary, and any of their required library +directories are added to the library path. + +Then, COMMAND is executed, with ARGS as arguments." + ;; + +finish) + $echo \ +"Usage: $modename [OPTION]... --mode=finish [LIBDIR]... + +Complete the installation of libtool libraries. + +Each LIBDIR is a directory that contains libtool libraries. + +The commands that this mode executes may require superuser privileges. Use +the \`--dry-run' option if you just want to see what would be executed." + ;; + +install) + $echo \ +"Usage: $modename [OPTION]... --mode=install INSTALL-COMMAND... + +Install executables or libraries. + +INSTALL-COMMAND is the installation command. The first component should be +either the \`install' or \`cp' program. + +The rest of the components are interpreted as arguments to that command (only +BSD-compatible install options are recognized)." + ;; + +link) + $echo \ +"Usage: $modename [OPTION]... --mode=link LINK-COMMAND... + +Link object files or libraries together to form another library, or to +create an executable program. + +LINK-COMMAND is a command using the C compiler that you would use to create +a program from several object files. + +The following components of LINK-COMMAND are treated specially: + + -all-static do not do any dynamic linking at all + -avoid-version do not add a version suffix if possible + -dlopen FILE \`-dlpreopen' FILE if it cannot be dlopened at runtime + -dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols + -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3) + -export-symbols SYMFILE + try to export only the symbols listed in SYMFILE + -export-symbols-regex REGEX + try to export only the symbols matching REGEX + -LLIBDIR search LIBDIR for required installed libraries + -lNAME OUTPUT-FILE requires the installed library libNAME + -module build a library that can dlopened + -no-fast-install disable the fast-install mode + -no-install link a not-installable executable + -no-undefined declare that a library does not refer to external symbols + -o OUTPUT-FILE create OUTPUT-FILE from the specified objects + -objectlist FILE Use a list of object files found in FILE to specify objects + -precious-files-regex REGEX + don't remove output files matching REGEX + -release RELEASE specify package release information + -rpath LIBDIR the created library will eventually be installed in LIBDIR + -R[ ]LIBDIR add LIBDIR to the runtime path of programs and libraries + -static do not do any dynamic linking of libtool libraries + -version-info CURRENT[:REVISION[:AGE]] + specify library version info [each variable defaults to 0] + +All other options (arguments beginning with \`-') are ignored. + +Every other argument is treated as a filename. Files ending in \`.la' are +treated as uninstalled libtool libraries, other files are standard or library +object files. + +If the OUTPUT-FILE ends in \`.la', then a libtool library is created, +only library objects (\`.lo' files) may be specified, and \`-rpath' is +required, except when creating a convenience library. + +If OUTPUT-FILE ends in \`.a' or \`.lib', then a standard library is created +using \`ar' and \`ranlib', or on Windows using \`lib'. + +If OUTPUT-FILE ends in \`.lo' or \`.${objext}', then a reloadable object file +is created, otherwise an executable program is created." + ;; + +uninstall) + $echo \ +"Usage: $modename [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE... + +Remove libraries from an installation directory. + +RM is the name of the program to use to delete files associated with each FILE +(typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed +to RM. + +If FILE is a libtool library, all the files associated with it are deleted. +Otherwise, only FILE itself is deleted using RM." + ;; + +*) + $echo "$modename: invalid operation mode \`$mode'" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + ;; +esac + +$echo +$echo "Try \`$modename --help' for more information about other modes." + +exit $? + +# The TAGs below are defined such that we never get into a situation +# in which we disable both kinds of libraries. Given conflicting +# choices, we go for a static library, that is the most portable, +# since we can't tell whether shared libraries were disabled because +# the user asked for that or because the platform doesn't support +# them. This is particularly important on AIX, because we don't +# support having both static and shared libraries enabled at the same +# time on that platform, so we default to a shared-only configuration. +# If a disable-shared tag is given, we'll fallback to a static-only +# configuration. But we'll never go from static-only to shared-only. + +# ### BEGIN LIBTOOL TAG CONFIG: disable-shared +disable_libs=shared +# ### END LIBTOOL TAG CONFIG: disable-shared + +# ### BEGIN LIBTOOL TAG CONFIG: disable-static +disable_libs=static +# ### END LIBTOOL TAG CONFIG: disable-static + +# Local Variables: +# mode:shell-script +# sh-indentation:2 +# End: diff --git a/libclamav/c++/llvm/autoconf/m4/bison.m4 b/libclamav/c++/llvm/autoconf/m4/bison.m4 new file mode 100644 index 000000000..48b83cc4a --- /dev/null +++ b/libclamav/c++/llvm/autoconf/m4/bison.m4 @@ -0,0 +1,15 @@ +# +# Check for Bison. +# +# This macro verifies that Bison is installed. If successful, then +# 1) YACC is set to bison -y (to emulate YACC calls) +# 2) BISON is set to bison +# +AC_DEFUN([AC_PROG_BISON], +[AC_CACHE_CHECK([],[llvm_cv_has_bison],[AC_PROG_YACC()]) +if test "$YACC" != "bison -y"; then + AC_SUBST(BISON,[]) + AC_MSG_WARN([bison not found, can't rebuild grammars]) +else + AC_SUBST(BISON,[bison]) +fi]) diff --git a/libclamav/c++/llvm/autoconf/m4/build_exeext.m4 b/libclamav/c++/llvm/autoconf/m4/build_exeext.m4 new file mode 100644 index 000000000..1bdecc1ba --- /dev/null +++ b/libclamav/c++/llvm/autoconf/m4/build_exeext.m4 @@ -0,0 +1,42 @@ +# Check for the extension used for executables on build platform. +# This is necessary for cross-compiling where the build platform +# may differ from the host platform. +AC_DEFUN([AC_BUILD_EXEEXT], +[ +AC_MSG_CHECKING([for executable suffix on build platform]) +AC_CACHE_VAL(ac_cv_build_exeext, +[if test "$CYGWIN" = yes || test "$MINGW32" = yes; then + ac_cv_build_exeext=.exe +else + ac_build_prefix=${build_alias}- + + AC_CHECK_PROG(BUILD_CC, ${ac_build_prefix}gcc, ${ac_build_prefix}gcc) + if test -z "$BUILD_CC"; then + AC_CHECK_PROG(BUILD_CC, gcc, gcc) + if test -z "$BUILD_CC"; then + AC_CHECK_PROG(BUILD_CC, cc, cc, , , /usr/ucb/cc) + fi + fi + test -z "$BUILD_CC" && AC_MSG_ERROR([no acceptable cc found in \$PATH]) + ac_build_link='${BUILD_CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&AS_MESSAGE_LOG_FD' + rm -f conftest* + echo 'int main () { return 0; }' > conftest.$ac_ext + ac_cv_build_exeext= + if AC_TRY_EVAL(ac_build_link); then + for file in conftest.*; do + case $file in + *.c | *.o | *.obj | *.dSYM) ;; + *) ac_cv_build_exeext=`echo $file | sed -e s/conftest//` ;; + esac + done + else + AC_MSG_ERROR([installation or configuration problem: compiler cannot create executables.]) + fi + rm -f conftest* + test x"${ac_cv_build_exeext}" = x && ac_cv_build_exeext=blank +fi]) +BUILD_EXEEXT="" +test x"${ac_cv_build_exeext}" != xblank && BUILD_EXEEXT=${ac_cv_build_exeext} +AC_MSG_RESULT(${ac_cv_build_exeext}) +ac_build_exeext=$BUILD_EXEEXT +AC_SUBST(BUILD_EXEEXT)]) diff --git a/libclamav/c++/llvm/autoconf/m4/c_printf_a.m4 b/libclamav/c++/llvm/autoconf/m4/c_printf_a.m4 new file mode 100644 index 000000000..61bac8c9d --- /dev/null +++ b/libclamav/c++/llvm/autoconf/m4/c_printf_a.m4 @@ -0,0 +1,31 @@ +# +# Determine if the printf() functions have the %a format character. +# This is modified from: +# http://www.gnu.org/software/ac-archive/htmldoc/ac_cxx_have_ext_slist.html +AC_DEFUN([AC_C_PRINTF_A], +[AC_CACHE_CHECK([if printf has the %a format character],[llvm_cv_c_printf_a], +[AC_LANG_PUSH([C]) + AC_RUN_IFELSE([ + AC_LANG_PROGRAM([[ +#include +#include +]],[[ +volatile double A, B; +char Buffer[100]; +A = 1; +A /= 10.0; +sprintf(Buffer, "%a", A); +B = atof(Buffer); +if (A != B) + return (1); +if (A != 0x1.999999999999ap-4) + return (1); +return (0);]])], + llvm_cv_c_printf_a=yes, + llvmac_cv_c_printf_a=no, + llvmac_cv_c_printf_a=no) + AC_LANG_POP([C])]) + if test "$llvm_cv_c_printf_a" = "yes"; then + AC_DEFINE([HAVE_PRINTF_A],[1],[Define to have the %a format string]) + fi +]) diff --git a/libclamav/c++/llvm/autoconf/m4/check_gnu_make.m4 b/libclamav/c++/llvm/autoconf/m4/check_gnu_make.m4 new file mode 100644 index 000000000..7355e1c85 --- /dev/null +++ b/libclamav/c++/llvm/autoconf/m4/check_gnu_make.m4 @@ -0,0 +1,26 @@ +# +# Check for GNU Make. This is originally from +# http://www.gnu.org/software/ac-archive/htmldoc/check_gnu_make.html +# +AC_DEFUN([AC_CHECK_GNU_MAKE], +[AC_CACHE_CHECK([for GNU make],[llvm_cv_gnu_make_command], +dnl Search all the common names for GNU make +[llvm_cv_gnu_make_command='' + for a in "$MAKE" make gmake gnumake ; do + if test -z "$a" ; then continue ; fi ; + if ( sh -c "$a --version" 2> /dev/null | grep GNU 2>&1 > /dev/null ) + then + llvm_cv_gnu_make_command=$a ; + break; + fi + done]) +dnl If there was a GNU version, then set @ifGNUmake@ to the empty string, +dnl '#' otherwise + if test "x$llvm_cv_gnu_make_command" != "x" ; then + ifGNUmake='' ; + else + ifGNUmake='#' ; + AC_MSG_RESULT("Not found"); + fi + AC_SUBST(ifGNUmake) +]) diff --git a/libclamav/c++/llvm/autoconf/m4/config_makefile.m4 b/libclamav/c++/llvm/autoconf/m4/config_makefile.m4 new file mode 100644 index 000000000..b1eaffdcd --- /dev/null +++ b/libclamav/c++/llvm/autoconf/m4/config_makefile.m4 @@ -0,0 +1,9 @@ +# +# Configure a Makefile without clobbering it if it exists and is not out of +# date. This macro is unique to LLVM. +# +AC_DEFUN([AC_CONFIG_MAKEFILE], +[AC_CONFIG_COMMANDS($1, + [${llvm_src}/autoconf/mkinstalldirs `dirname $1` + ${SHELL} ${llvm_src}/autoconf/install-sh -m 0644 -c ${srcdir}/$1 $1]) +]) diff --git a/libclamav/c++/llvm/autoconf/m4/config_project.m4 b/libclamav/c++/llvm/autoconf/m4/config_project.m4 new file mode 100644 index 000000000..eea7faf16 --- /dev/null +++ b/libclamav/c++/llvm/autoconf/m4/config_project.m4 @@ -0,0 +1,14 @@ +# +# Provide the arguments and other processing needed for an LLVM project +# +AC_DEFUN([LLVM_CONFIG_PROJECT], + [AC_ARG_WITH([llvmsrc], + AS_HELP_STRING([--with-llvmsrc],[Location of LLVM Source Code]), + [llvm_src="$withval"],[llvm_src="]$1["]) + AC_SUBST(LLVM_SRC,$llvm_src) + AC_ARG_WITH([llvmobj], + AS_HELP_STRING([--with-llvmobj],[Location of LLVM Object Code]), + [llvm_obj="$withval"],[llvm_obj="]$2["]) + AC_SUBST(LLVM_OBJ,$llvm_obj) + AC_CONFIG_COMMANDS([setup],,[llvm_src="${LLVM_SRC}"]) +]) diff --git a/libclamav/c++/llvm/autoconf/m4/cxx_bidi_iterator.m4 b/libclamav/c++/llvm/autoconf/m4/cxx_bidi_iterator.m4 new file mode 100644 index 000000000..d7de85630 --- /dev/null +++ b/libclamav/c++/llvm/autoconf/m4/cxx_bidi_iterator.m4 @@ -0,0 +1,22 @@ +# +# Check for bidirectional iterator extension. This is modified from +# http://www.gnu.org/software/ac-archive/htmldoc/ac_cxx_have_ext_hash_set.html +# +AC_DEFUN([AC_CXX_HAVE_BI_ITERATOR], +[AC_CACHE_CHECK(whether the compiler has the bidirectional iterator, +ac_cv_cxx_have_bi_iterator, +[AC_REQUIRE([AC_CXX_NAMESPACES]) + AC_LANG_PUSH([C++]) + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include +#ifdef HAVE_NAMESPACES +using namespace std; +#endif]], [[bidirectional_iterator t; return 0;]])],[ac_cv_cxx_have_bi_iterator=yes],[ac_cv_cxx_have_bi_iterator=no]) + AC_LANG_POP([C++]) +]) +if test "$ac_cv_cxx_have_bi_iterator" = yes +then + AC_DEFINE(HAVE_BI_ITERATOR,1,[Have bi-directional iterator]) +else + AC_DEFINE(HAVE_BI_ITERATOR,0,[Does not have bi-directional iterator]) +fi +]) diff --git a/libclamav/c++/llvm/autoconf/m4/cxx_flag_check.m4 b/libclamav/c++/llvm/autoconf/m4/cxx_flag_check.m4 new file mode 100644 index 000000000..ab09f2af5 --- /dev/null +++ b/libclamav/c++/llvm/autoconf/m4/cxx_flag_check.m4 @@ -0,0 +1,2 @@ +AC_DEFUN([CXX_FLAG_CHECK], + [AC_SUBST($1, `$CXX $2 -fsyntax-only -xc /dev/null 2>/dev/null && echo $2`)]) diff --git a/libclamav/c++/llvm/autoconf/m4/cxx_fwd_iterator.m4 b/libclamav/c++/llvm/autoconf/m4/cxx_fwd_iterator.m4 new file mode 100644 index 000000000..eb7660c7c --- /dev/null +++ b/libclamav/c++/llvm/autoconf/m4/cxx_fwd_iterator.m4 @@ -0,0 +1,22 @@ +# Check for forward iterator extension. This is modified from +# http://www.gnu.org/software/ac-archive/htmldoc/ac_cxx_have_ext_hash_set.html +AC_DEFUN([AC_CXX_HAVE_FWD_ITERATOR], +[AC_CACHE_CHECK(whether the compiler has forward iterators, +ac_cv_cxx_have_fwd_iterator, +[AC_REQUIRE([AC_CXX_NAMESPACES]) + AC_LANG_PUSH([C++]) + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include +#ifdef HAVE_NAMESPACES +using namespace std; +#endif]], [[forward_iterator t; return 0;]])],[ac_cv_cxx_have_fwd_iterator=yes],[ac_cv_cxx_have_fwd_iterator=no]) + AC_LANG_POP([C++]) +]) +if test "$ac_cv_cxx_have_fwd_iterator" = yes +then + AC_DEFINE(HAVE_FWD_ITERATOR,1,[Have forward iterator]) +else + AC_DEFINE(HAVE_FWD_ITERATOR,0,[Does not have forward iterator]) +fi +]) + + diff --git a/libclamav/c++/llvm/autoconf/m4/cxx_namespaces.m4 b/libclamav/c++/llvm/autoconf/m4/cxx_namespaces.m4 new file mode 100644 index 000000000..d8d650e4d --- /dev/null +++ b/libclamav/c++/llvm/autoconf/m4/cxx_namespaces.m4 @@ -0,0 +1,19 @@ +# Check for C++ namespace support. This is from +# http://www.gnu.org/software/ac-archive/htmldoc/ac_cxx_namespaces.html +# +AC_DEFUN([AC_CXX_NAMESPACES], +[AC_CACHE_CHECK(whether the compiler implements namespaces, +ac_cv_cxx_namespaces, +[AC_LANG_PUSH([C++]) + AC_COMPILE_IFELSE([AC_LANG_PROGRAM( + [[namespace Outer { namespace Inner { int i = 0; }}]], + [[using namespace Outer::Inner; return i;]])], + ac_cv_cxx_namespaces=yes, + ac_cv_cxx_namespaces=no) + AC_LANG_POP([C++]) +]) +if test "$ac_cv_cxx_namespaces" = yes; then + AC_DEFINE(HAVE_NAMESPACES,,[define if the compiler implements namespaces]) +fi +]) + diff --git a/libclamav/c++/llvm/autoconf/m4/cxx_std_iterator.m4 b/libclamav/c++/llvm/autoconf/m4/cxx_std_iterator.m4 new file mode 100644 index 000000000..38a611764 --- /dev/null +++ b/libclamav/c++/llvm/autoconf/m4/cxx_std_iterator.m4 @@ -0,0 +1,26 @@ +# Check for standard iterator extension. This is modified from +# http://www.gnu.org/software/ac-archive/htmldoc/ac_cxx_have_ext_hash_set.html +AC_DEFUN([AC_CXX_HAVE_STD_ITERATOR], +[AC_CACHE_CHECK(whether the compiler has the standard iterator, +ac_cv_cxx_have_std_iterator, +[AC_REQUIRE([AC_CXX_NAMESPACES]) + AC_LANG_PUSH([C++]) + AC_COMPILE_IFELSE([AC_LANG_PROGRAM( + [[#include +#ifdef HAVE_NAMESPACES +using namespace std; +#endif]], + [[iterator t; return 0;]])], + ac_cv_cxx_have_std_iterator=yes, + ac_cv_cxx_have_std_iterator=no) + AC_LANG_POP([C++]) +]) +if test "$ac_cv_cxx_have_std_iterator" = yes +then + AC_DEFINE(HAVE_STD_ITERATOR,1,[Have std namespace iterator]) +else + AC_DEFINE(HAVE_STD_ITERATOR,0,[Does not have std namespace iterator]) +fi +]) + + diff --git a/libclamav/c++/llvm/autoconf/m4/find_std_program.m4 b/libclamav/c++/llvm/autoconf/m4/find_std_program.m4 new file mode 100644 index 000000000..c789df8e6 --- /dev/null +++ b/libclamav/c++/llvm/autoconf/m4/find_std_program.m4 @@ -0,0 +1,118 @@ +dnl Check for a standard program that has a bin, include and lib directory +dnl +dnl Parameters: +dnl $1 - prefix directory to check +dnl $2 - program name to check +dnl $3 - header file to check +dnl $4 - library file to check +AC_DEFUN([CHECK_STD_PROGRAM], +[m4_define([allcapsname],translit($2,a-z,A-Z)) +if test -n "$1" -a -d "$1" -a -n "$2" -a -d "$1/bin" -a -x "$1/bin/$2" ; then + AC_SUBST([USE_]allcapsname(),["USE_]allcapsname()[ = 1"]) + AC_SUBST(allcapsname(),[$1/bin/$2]) + AC_SUBST(allcapsname()[_BIN],[$1/bin]) + AC_SUBST(allcapsname()[_DIR],[$1]) + if test -n "$3" -a -d "$1/include" -a -f "$1/include/$3" ; then + AC_SUBST(allcapsname()[_INC],[$1/include]) + fi + if test -n "$4" -a -d "$1/lib" -a -f "$1/lib/$4" ; then + AC_SUBST(allcapsname()[_LIB],[$1/lib]) + fi +fi +]) + +dnl Find a program via --with options, in the path, or well known places +dnl +dnl Parameters: +dnl $1 - program's executable name +dnl $2 - header file name to check (optional) +dnl $3 - library file name to check (optional) +dnl $4 - alternate (long) name for the program +AC_DEFUN([FIND_STD_PROGRAM], +[m4_define([allcapsname],translit($1,a-z,A-Z)) +m4_define([stdprog_long_name],ifelse($4,,translit($1,[ !@#$%^&*()-+={}[]:;"',./?],[-]),translit($4,[ !@#$%^&*()-+={}[]:;"',./?],[-]))) +AC_MSG_CHECKING([for ]stdprog_long_name()[ bin/lib/include locations]) +AC_ARG_WITH($1, + AS_HELP_STRING([--with-]stdprog_long_name()[=DIR], + [Specify that the ]stdprog_long_name()[ install prefix is DIR]), + $1[pfxdir=$withval],$1[pfxdir=nada]) +AC_ARG_WITH($1[-bin], + AS_HELP_STRING([--with-]stdprog_long_name()[-bin=DIR], + [Specify that the ]stdprog_long_name()[ binary is in DIR]), + $1[bindir=$withval],$1[bindir=nada]) +AC_ARG_WITH($1[-lib], + AS_HELP_STRING([--with-]stdprog_long_name()[-lib=DIR], + [Specify that ]stdprog_long_name()[ libraries are in DIR]), + $1[libdir=$withval],$1[libdir=nada]) +AC_ARG_WITH($1[-inc], + AS_HELP_STRING([--with-]stdprog_long_name()[-inc=DIR], + [Specify that the ]stdprog_long_name()[ includes are in DIR]), + $1[incdir=$withval],$1[incdir=nada]) +eval pfxval=\$\{$1pfxdir\} +eval binval=\$\{$1bindir\} +eval incval=\$\{$1incdir\} +eval libval=\$\{$1libdir\} +if test "${pfxval}" != "nada" ; then + CHECK_STD_PROGRAM(${pfxval},$1,$2,$3) +elif test "${binval}" != "nada" ; then + if test "${libval}" != "nada" ; then + if test "${incval}" != "nada" ; then + if test -d "${binval}" ; then + if test -d "${incval}" ; then + if test -d "${libval}" ; then + AC_SUBST(allcapsname(),${binval}/$1) + AC_SUBST(allcapsname()[_BIN],${binval}) + AC_SUBST(allcapsname()[_INC],${incval}) + AC_SUBST(allcapsname()[_LIB],${libval}) + AC_SUBST([USE_]allcapsname(),["USE_]allcapsname()[ = 1"]) + AC_MSG_RESULT([found via --with options]) + else + AC_MSG_RESULT([failed]) + AC_MSG_ERROR([The --with-]$1[-libdir value must be a directory]) + fi + else + AC_MSG_RESULT([failed]) + AC_MSG_ERROR([The --with-]$1[-incdir value must be a directory]) + fi + else + AC_MSG_RESULT([failed]) + AC_MSG_ERROR([The --with-]$1[-bindir value must be a directory]) + fi + else + AC_MSG_RESULT([failed]) + AC_MSG_ERROR([The --with-]$1[-incdir option must be specified]) + fi + else + AC_MSG_RESULT([failed]) + AC_MSG_ERROR([The --with-]$1[-libdir option must be specified]) + fi +else + tmppfxdir=`which $1 2>&1` + if test -n "$tmppfxdir" -a -d "${tmppfxdir%*$1}" -a \ + -d "${tmppfxdir%*$1}/.." ; then + tmppfxdir=`cd "${tmppfxdir%*$1}/.." ; pwd` + CHECK_STD_PROGRAM($tmppfxdir,$1,$2,$3) + AC_MSG_RESULT([found in PATH at ]$tmppfxdir) + else + checkresult="yes" + eval checkval=\$\{"USE_"allcapsname()\} + CHECK_STD_PROGRAM([/usr],$1,$2,$3) + if test -z "${checkval}" ; then + CHECK_STD_PROGRAM([/usr/local],$1,$2,$3) + if test -z "${checkval}" ; then + CHECK_STD_PROGRAM([/sw],$1,$2,$3) + if test -z "${checkval}" ; then + CHECK_STD_PROGRAM([/opt],$1,$2,$3) + if test -z "${checkval}" ; then + CHECK_STD_PROGRAM([/],$1,$2,$3) + if test -z "${checkval}" ; then + checkresult="no" + fi + fi + fi + fi + fi + AC_MSG_RESULT($checkresult) + fi +fi +]) diff --git a/libclamav/c++/llvm/autoconf/m4/flex.m4 b/libclamav/c++/llvm/autoconf/m4/flex.m4 new file mode 100644 index 000000000..5cb3dc4f8 --- /dev/null +++ b/libclamav/c++/llvm/autoconf/m4/flex.m4 @@ -0,0 +1,17 @@ +# +# Check for FLEX. +# +# This macro verifies that flex is installed. If successful, then +# 1) $LEX is set to "flex" (to emulate lex calls) +# 2) BISON is set to bison +AC_DEFUN([AC_PROG_FLEX], +[AC_CACHE_CHECK(, +ac_cv_has_flex, +[AC_PROG_LEX() +]) +if test "$LEX" != "flex"; then + AC_MSG_ERROR([flex not found but required]) +else + AC_SUBST(FLEX,[flex],[location of flex]) +fi +]) diff --git a/libclamav/c++/llvm/autoconf/m4/func_isinf.m4 b/libclamav/c++/llvm/autoconf/m4/func_isinf.m4 new file mode 100644 index 000000000..c936bf920 --- /dev/null +++ b/libclamav/c++/llvm/autoconf/m4/func_isinf.m4 @@ -0,0 +1,36 @@ +# +# This function determins if the the isinf function isavailable on this +# platform. +# +AC_DEFUN([AC_FUNC_ISINF],[ +AC_SINGLE_CXX_CHECK([ac_cv_func_isinf_in_math_h], + [isinf], [], + [float f; isinf(f);]) +if test "$ac_cv_func_isinf_in_math_h" = "yes" ; then + AC_DEFINE([HAVE_ISINF_IN_MATH_H],1,[Set to 1 if the isinf function is found in ]) +fi + +AC_SINGLE_CXX_CHECK([ac_cv_func_isinf_in_cmath], + [isinf], [], + [float f; isinf(f);]) +if test "$ac_cv_func_isinf_in_cmath" = "yes" ; then + AC_DEFINE([HAVE_ISINF_IN_CMATH],1,[Set to 1 if the isinf function is found in ]) +fi + +AC_SINGLE_CXX_CHECK([ac_cv_func_std_isinf_in_cmath], + [std::isinf], [], + [float f; std::isinf(f)}]) +if test "$ac_cv_func_std_isinf_in_cmath" = "yes" ; then + AC_DEFINE([HAVE_STD_ISINF_IN_CMATH],1,[Set to 1 if the std::isinf function is found in ]) +fi + +AC_SINGLE_CXX_CHECK([ac_cv_func_finite_in_ieeefp_h], + [finite], [], + [float f; finite(f);]) +if test "$ac_cv_func_finite_in_ieeefp_h" = "yes" ; then + AC_DEFINE([HAVE_FINITE_IN_IEEEFP_H],1,[Set to 1 if the finite function is found in ]) +fi + +]) + + diff --git a/libclamav/c++/llvm/autoconf/m4/func_isnan.m4 b/libclamav/c++/llvm/autoconf/m4/func_isnan.m4 new file mode 100644 index 000000000..eb5ca0dae --- /dev/null +++ b/libclamav/c++/llvm/autoconf/m4/func_isnan.m4 @@ -0,0 +1,27 @@ +# +# This function determines if the isnan function is available on this +# platform. +# +AC_DEFUN([AC_FUNC_ISNAN],[ +AC_SINGLE_CXX_CHECK([ac_cv_func_isnan_in_math_h], + [isnan], [], + [float f; isnan(f);]) + +if test "$ac_cv_func_isnan_in_math_h" = "yes" ; then + AC_DEFINE([HAVE_ISNAN_IN_MATH_H],1,[Set to 1 if the isnan function is found in ]) +fi + +AC_SINGLE_CXX_CHECK([ac_cv_func_isnan_in_cmath], + [isnan], [], + [float f; isnan(f);]) +if test "$ac_cv_func_isnan_in_cmath" = "yes" ; then + AC_DEFINE([HAVE_ISNAN_IN_CMATH],1,[Set to 1 if the isnan function is found in ]) +fi + +AC_SINGLE_CXX_CHECK([ac_cv_func_std_isnan_in_cmath], + [std::isnan], [], + [float f; std::isnan(f);]) +if test "$ac_cv_func_std_isnan_in_cmath" = "yes" ; then + AC_DEFINE([HAVE_STD_ISNAN_IN_CMATH],1,[Set to 1 if the std::isnan function is found in ]) +fi +]) diff --git a/libclamav/c++/llvm/autoconf/m4/func_mmap_file.m4 b/libclamav/c++/llvm/autoconf/m4/func_mmap_file.m4 new file mode 100644 index 000000000..372c87fbe --- /dev/null +++ b/libclamav/c++/llvm/autoconf/m4/func_mmap_file.m4 @@ -0,0 +1,26 @@ +# +# Check for the ability to mmap a file. +# +AC_DEFUN([AC_FUNC_MMAP_FILE], +[AC_CACHE_CHECK(for mmap of files, +ac_cv_func_mmap_file, +[ AC_LANG_PUSH([C]) + AC_RUN_IFELSE([ + AC_LANG_PROGRAM([[ +#include +#include +#include +]],[[ + int fd; + fd = creat ("foo",0777); + fd = (int) mmap (0, 1, PROT_READ, MAP_SHARED, fd, 0); + unlink ("foo"); + return (fd != (int) MAP_FAILED);]])], + [ac_cv_func_mmap_file=yes],[ac_cv_func_mmap_file=no],[ac_cv_func_mmap_file=no]) + AC_LANG_POP([C]) +]) +if test "$ac_cv_func_mmap_file" = yes; then + AC_DEFINE([HAVE_MMAP_FILE],[],[Define if mmap() can map files into memory]) + AC_SUBST(MMAP_FILE,[yes]) +fi +]) diff --git a/libclamav/c++/llvm/autoconf/m4/header_mmap_anonymous.m4 b/libclamav/c++/llvm/autoconf/m4/header_mmap_anonymous.m4 new file mode 100644 index 000000000..2270d2955 --- /dev/null +++ b/libclamav/c++/llvm/autoconf/m4/header_mmap_anonymous.m4 @@ -0,0 +1,21 @@ +# +# Check for anonymous mmap macros. This is modified from +# http://www.gnu.org/software/ac-archive/htmldoc/ac_cxx_have_ext_slist.html +# +AC_DEFUN([AC_HEADER_MMAP_ANONYMOUS], +[AC_CACHE_CHECK(for MAP_ANONYMOUS vs. MAP_ANON, +ac_cv_header_mmap_anon, +[ AC_LANG_PUSH([C]) + AC_COMPILE_IFELSE([AC_LANG_PROGRAM( + [[#include +#include +#include ]], + [[mmap (0, 1, PROT_READ, MAP_ANONYMOUS, -1, 0); return (0);]])], + ac_cv_header_mmap_anon=yes, + ac_cv_header_mmap_anon=no) + AC_LANG_POP([C]) +]) +if test "$ac_cv_header_mmap_anon" = yes; then + AC_DEFINE([HAVE_MMAP_ANONYMOUS],[1],[Define if mmap() uses MAP_ANONYMOUS to map anonymous pages, or undefine if it uses MAP_ANON]) +fi +]) diff --git a/libclamav/c++/llvm/autoconf/m4/huge_val.m4 b/libclamav/c++/llvm/autoconf/m4/huge_val.m4 new file mode 100644 index 000000000..fd94c11c8 --- /dev/null +++ b/libclamav/c++/llvm/autoconf/m4/huge_val.m4 @@ -0,0 +1,18 @@ +# +# This function determins if the the HUGE_VAL macro is compilable with the +# -pedantic switch or not. XCode < 2.4.1 doesn't get it right. +# +AC_DEFUN([AC_HUGE_VAL_CHECK],[ + AC_CACHE_CHECK([for HUGE_VAL sanity], [ac_cv_huge_val_sanity],[ + AC_LANG_PUSH([C++]) + CXXFLAGS=-pedantic + AC_RUN_IFELSE( + AC_LANG_PROGRAM( + [#include ], + [double x = HUGE_VAL; return x != x; ]), + [ac_cv_huge_val_sanity=yes],[ac_cv_huge_val_sanity=no], + [ac_cv_huge_val_sanity=yes]) + AC_LANG_POP([C++]) + ]) + AC_SUBST(HUGE_VAL_SANITY,$ac_cv_huge_val_sanity) +]) diff --git a/libclamav/c++/llvm/autoconf/m4/libtool.m4 b/libclamav/c++/llvm/autoconf/m4/libtool.m4 new file mode 100644 index 000000000..a8b5e6a94 --- /dev/null +++ b/libclamav/c++/llvm/autoconf/m4/libtool.m4 @@ -0,0 +1,6389 @@ +# libtool.m4 - Configure libtool for the host system. -*-Autoconf-*- +## Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005 +## Free Software Foundation, Inc. +## Originally by Gordon Matzigkeit , 1996 +## +## This file is free software; the Free Software Foundation gives +## unlimited permission to copy and/or distribute it, with or without +## modifications, as long as this notice is preserved. + +# serial 48 AC_PROG_LIBTOOL + + +# AC_PROVIDE_IFELSE(MACRO-NAME, IF-PROVIDED, IF-NOT-PROVIDED) +# ----------------------------------------------------------- +# If this macro is not defined by Autoconf, define it here. +m4_ifdef([AC_PROVIDE_IFELSE], + [], + [m4_define([AC_PROVIDE_IFELSE], + [m4_ifdef([AC_PROVIDE_$1], + [$2], [$3])])]) + + +# AC_PROG_LIBTOOL +# --------------- +AC_DEFUN([AC_PROG_LIBTOOL], +[AC_REQUIRE([_AC_PROG_LIBTOOL])dnl +dnl If AC_PROG_CXX has already been expanded, run AC_LIBTOOL_CXX +dnl immediately, otherwise, hook it in at the end of AC_PROG_CXX. + AC_PROVIDE_IFELSE([AC_PROG_CXX], + [AC_LIBTOOL_CXX], + [define([AC_PROG_CXX], defn([AC_PROG_CXX])[AC_LIBTOOL_CXX + ])]) +dnl And a similar setup for Fortran 77 support + AC_PROVIDE_IFELSE([AC_PROG_F77], + [AC_LIBTOOL_F77], + [define([AC_PROG_F77], defn([AC_PROG_F77])[AC_LIBTOOL_F77 +])]) + +dnl Quote A][M_PROG_GCJ so that aclocal doesn't bring it in needlessly. +dnl If either AC_PROG_GCJ or A][M_PROG_GCJ have already been expanded, run +dnl AC_LIBTOOL_GCJ immediately, otherwise, hook it in at the end of both. + AC_PROVIDE_IFELSE([AC_PROG_GCJ], + [AC_LIBTOOL_GCJ], + [AC_PROVIDE_IFELSE([A][M_PROG_GCJ], + [AC_LIBTOOL_GCJ], + [AC_PROVIDE_IFELSE([LT_AC_PROG_GCJ], + [AC_LIBTOOL_GCJ], + [ifdef([AC_PROG_GCJ], + [define([AC_PROG_GCJ], defn([AC_PROG_GCJ])[AC_LIBTOOL_GCJ])]) + ifdef([A][M_PROG_GCJ], + [define([A][M_PROG_GCJ], defn([A][M_PROG_GCJ])[AC_LIBTOOL_GCJ])]) + ifdef([LT_AC_PROG_GCJ], + [define([LT_AC_PROG_GCJ], + defn([LT_AC_PROG_GCJ])[AC_LIBTOOL_GCJ])])])]) +])])# AC_PROG_LIBTOOL + + +# _AC_PROG_LIBTOOL +# ---------------- +AC_DEFUN([_AC_PROG_LIBTOOL], +[AC_REQUIRE([AC_LIBTOOL_SETUP])dnl +AC_BEFORE([$0],[AC_LIBTOOL_CXX])dnl +AC_BEFORE([$0],[AC_LIBTOOL_F77])dnl +AC_BEFORE([$0],[AC_LIBTOOL_GCJ])dnl + +# This can be used to rebuild libtool when needed +LIBTOOL_DEPS="$ac_aux_dir/ltmain.sh" + +# Always use our own libtool. +LIBTOOL='$(SHELL) $(top_builddir)/mklib' +AC_SUBST(LIBTOOL)dnl + +# Prevent multiple expansion +define([AC_PROG_LIBTOOL], []) +])# _AC_PROG_LIBTOOL + + +# AC_LIBTOOL_SETUP +# ---------------- +AC_DEFUN([AC_LIBTOOL_SETUP], +[AC_PREREQ(2.60)dnl +AC_REQUIRE([AC_ENABLE_SHARED])dnl +AC_REQUIRE([AC_ENABLE_STATIC])dnl +AC_REQUIRE([AC_ENABLE_FAST_INSTALL])dnl +AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([AC_PROG_LD])dnl +AC_REQUIRE([AC_PROG_LD_RELOAD_FLAG])dnl +AC_REQUIRE([AC_PROG_NM])dnl + +AC_REQUIRE([AC_PROG_LN_S])dnl +AC_REQUIRE([AC_DEPLIBS_CHECK_METHOD])dnl +# Autoconf 2.13's AC_OBJEXT and AC_EXEEXT macros only works for C compilers! +AC_REQUIRE([AC_OBJEXT])dnl +AC_REQUIRE([AC_EXEEXT])dnl +dnl + +AC_LIBTOOL_SYS_MAX_CMD_LEN +AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE +AC_LIBTOOL_OBJDIR + +AC_REQUIRE([_LT_AC_SYS_COMPILER])dnl +_LT_AC_PROG_ECHO_BACKSLASH + +case $host_os in +aix3*) + # AIX sometimes has problems with the GCC collect2 program. For some + # reason, if we set the COLLECT_NAMES environment variable, the problems + # vanish in a puff of smoke. + if test "X${COLLECT_NAMES+set}" != Xset; then + COLLECT_NAMES= + export COLLECT_NAMES + fi + ;; +esac + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +Xsed='sed -e 1s/^X//' +[sed_quote_subst='s/\([\\"\\`$\\\\]\)/\\\1/g'] + +# Same as above, but do not quote variable references. +[double_quote_subst='s/\([\\"\\`\\\\]\)/\\\1/g'] + +# Sed substitution to delay expansion of an escaped shell variable in a +# double_quote_subst'ed string. +delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' + +# Sed substitution to avoid accidental globbing in evaled expressions +no_glob_subst='s/\*/\\\*/g' + +# Constants: +rm="rm -f" + +# Global variables: +default_ofile=mklib +can_build_shared=yes + +# All known linkers require a `.a' archive for static linking (except MSVC, +# which needs '.lib'). +libext=a +ltmain="$ac_aux_dir/ltmain.sh" +ofile="$default_ofile" +with_gnu_ld="$lt_cv_prog_gnu_ld" + +AC_CHECK_TOOL(AR, ar, false) +AC_CHECK_TOOL(RANLIB, ranlib, :) +AC_CHECK_TOOL(STRIP, strip, :) + +old_CC="$CC" +old_CFLAGS="$CFLAGS" + +# Set sane defaults for various variables +test -z "$AR" && AR=ar +test -z "$AR_FLAGS" && AR_FLAGS=cru +test -z "$AS" && AS=as +test -z "$CC" && CC=cc +test -z "$LTCC" && LTCC=$CC +test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS +test -z "$DLLTOOL" && DLLTOOL=dlltool +test -z "$LD" && LD=ld +test -z "$LN_S" && LN_S="ln -s" +test -z "$MAGIC_CMD" && MAGIC_CMD=file +test -z "$NM" && NM=nm +test -z "$SED" && SED=sed +test -z "$OBJDUMP" && OBJDUMP=objdump +test -z "$RANLIB" && RANLIB=: +test -z "$STRIP" && STRIP=: +test -z "$ac_objext" && ac_objext=o + +# Determine commands to create old-style static archives. +old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs$old_deplibs' +old_postinstall_cmds='chmod 644 $oldlib' +old_postuninstall_cmds= + +if test -n "$RANLIB"; then + case $host_os in + openbsd*) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$oldlib" + ;; + *) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$oldlib" + ;; + esac + old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib" +fi + +_LT_CC_BASENAME([$compiler]) + +# Only perform the check for file, if the check method requires it +case $deplibs_check_method in +file_magic*) + if test "$file_magic_cmd" = '$MAGIC_CMD'; then + AC_PATH_MAGIC + fi + ;; +esac + +AC_PROVIDE_IFELSE([AC_LIBTOOL_DLOPEN], enable_dlopen=yes, enable_dlopen=no) +AC_PROVIDE_IFELSE([AC_LIBTOOL_WIN32_DLL], +enable_win32_dll=yes, enable_win32_dll=no) + +AC_ARG_ENABLE([libtool-lock], + [AS_HELP_STRING([--disable-libtool-lock],[avoid locking (might break parallel builds)])]) +test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes + +AC_ARG_WITH([pic], + [AS_HELP_STRING([--with-pic],[try to use only PIC/non-PIC objects @<:@default=use both@:>@])], + [pic_mode="$withval"], + [pic_mode=default]) +test -z "$pic_mode" && pic_mode=default + +# Use C for the default configuration in the libtool script +tagname= +AC_LIBTOOL_LANG_C_CONFIG +_LT_AC_TAGCONFIG +])# AC_LIBTOOL_SETUP + + +# _LT_AC_SYS_COMPILER +# ------------------- +AC_DEFUN([_LT_AC_SYS_COMPILER], +[AC_REQUIRE([AC_PROG_CC])dnl + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC +])# _LT_AC_SYS_COMPILER + + +# _LT_CC_BASENAME(CC) +# ------------------- +# Calculate cc_basename. Skip known compiler wrappers and cross-prefix. +AC_DEFUN([_LT_CC_BASENAME], +[for cc_temp in $1""; do + case $cc_temp in + compile | *[[\\/]]compile | ccache | *[[\\/]]ccache ) ;; + distcc | *[[\\/]]distcc | purify | *[[\\/]]purify ) ;; + \-*) ;; + *) break;; + esac +done +cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` +]) + + +# _LT_COMPILER_BOILERPLATE +# ------------------------ +# Check for compiler boilerplate output or warnings with +# the simple compiler test code. +AC_DEFUN([_LT_COMPILER_BOILERPLATE], +[ac_outfile=conftest.$ac_objext +printf "$lt_simple_compile_test_code" >conftest.$ac_ext +eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_compiler_boilerplate=`cat conftest.err` +$rm conftest* +])# _LT_COMPILER_BOILERPLATE + + +# _LT_LINKER_BOILERPLATE +# ---------------------- +# Check for linker boilerplate output or warnings with +# the simple link test code. +AC_DEFUN([_LT_LINKER_BOILERPLATE], +[ac_outfile=conftest.$ac_objext +printf "$lt_simple_link_test_code" >conftest.$ac_ext +eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_linker_boilerplate=`cat conftest.err` +$rm conftest* +])# _LT_LINKER_BOILERPLATE + + +# _LT_AC_SYS_LIBPATH_AIX +# ---------------------- +# Links a minimal program and checks the executable +# for the system default hardcoded library path. In most cases, +# this is /usr/lib:/lib, but when the MPI compilers are used +# the location of the communication and MPI libs are included too. +# If we don't find anything, use the default library path according +# to the aix ld manual. +AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX], +[AC_LINK_IFELSE(AC_LANG_PROGRAM,[ +aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'` +# Check for a 64-bit object if we didn't find anything. +if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'`; fi],[]) +if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi +])# _LT_AC_SYS_LIBPATH_AIX + + +# _LT_AC_SHELL_INIT(ARG) +# ---------------------- +AC_DEFUN([_LT_AC_SHELL_INIT], +[ifdef([AC_DIVERSION_NOTICE], + [AC_DIVERT_PUSH(AC_DIVERSION_NOTICE)], + [AC_DIVERT_PUSH(NOTICE)]) +$1 +AC_DIVERT_POP +])# _LT_AC_SHELL_INIT + + +# _LT_AC_PROG_ECHO_BACKSLASH +# -------------------------- +# Add some code to the start of the generated configure script which +# will find an echo command which doesn't interpret backslashes. +AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH], +[_LT_AC_SHELL_INIT([ +# Check that we are running under the correct shell. +SHELL=${CONFIG_SHELL-/bin/sh} + +case X$ECHO in +X*--fallback-echo) + # Remove one level of quotation (which was required for Make). + ECHO=`echo "$ECHO" | sed 's,\\\\\[$]\\[$]0,'[$]0','` + ;; +esac + +echo=${ECHO-echo} +if test "X[$]1" = X--no-reexec; then + # Discard the --no-reexec flag, and continue. + shift +elif test "X[$]1" = X--fallback-echo; then + # Avoid inline document here, it may be left over + : +elif test "X`($echo '\t') 2>/dev/null`" = 'X\t' ; then + # Yippee, $echo works! + : +else + # Restart under the correct shell. + exec $SHELL "[$]0" --no-reexec ${1+"[$]@"} +fi + +if test "X[$]1" = X--fallback-echo; then + # used as fallback echo + shift + cat </dev/null 2>&1 && unset CDPATH + +if test -z "$ECHO"; then +if test "X${echo_test_string+set}" != Xset; then +# find a string as large as possible, as long as the shell can cope with it + for cmd in 'sed 50q "[$]0"' 'sed 20q "[$]0"' 'sed 10q "[$]0"' 'sed 2q "[$]0"' 'echo test'; do + # expected sizes: less than 2Kb, 1Kb, 512 bytes, 16 bytes, ... + if (echo_test_string=`eval $cmd`) 2>/dev/null && + echo_test_string=`eval $cmd` && + (test "X$echo_test_string" = "X$echo_test_string") 2>/dev/null + then + break + fi + done +fi + +if test "X`($echo '\t') 2>/dev/null`" = 'X\t' && + echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + : +else + # The Solaris, AIX, and Digital Unix default echo programs unquote + # backslashes. This makes it impossible to quote backslashes using + # echo "$something" | sed 's/\\/\\\\/g' + # + # So, first we look for a working echo in the user's PATH. + + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for dir in $PATH /usr/ucb; do + IFS="$lt_save_ifs" + if (test -f $dir/echo || test -f $dir/echo$ac_exeext) && + test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' && + echo_testing_string=`($dir/echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + echo="$dir/echo" + break + fi + done + IFS="$lt_save_ifs" + + if test "X$echo" = Xecho; then + # We didn't find a better echo, so look for alternatives. + if test "X`(print -r '\t') 2>/dev/null`" = 'X\t' && + echo_testing_string=`(print -r "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + # This shell has a builtin print -r that does the trick. + echo='print -r' + elif (test -f /bin/ksh || test -f /bin/ksh$ac_exeext) && + test "X$CONFIG_SHELL" != X/bin/ksh; then + # If we have ksh, try running configure again with it. + ORIGINAL_CONFIG_SHELL=${CONFIG_SHELL-/bin/sh} + export ORIGINAL_CONFIG_SHELL + CONFIG_SHELL=/bin/ksh + export CONFIG_SHELL + exec $CONFIG_SHELL "[$]0" --no-reexec ${1+"[$]@"} + else + # Try using printf. + echo='printf %s\n' + if test "X`($echo '\t') 2>/dev/null`" = 'X\t' && + echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + # Cool, printf works + : + elif echo_testing_string=`($ORIGINAL_CONFIG_SHELL "[$]0" --fallback-echo '\t') 2>/dev/null` && + test "X$echo_testing_string" = 'X\t' && + echo_testing_string=`($ORIGINAL_CONFIG_SHELL "[$]0" --fallback-echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + CONFIG_SHELL=$ORIGINAL_CONFIG_SHELL + export CONFIG_SHELL + SHELL="$CONFIG_SHELL" + export SHELL + echo="$CONFIG_SHELL [$]0 --fallback-echo" + elif echo_testing_string=`($CONFIG_SHELL "[$]0" --fallback-echo '\t') 2>/dev/null` && + test "X$echo_testing_string" = 'X\t' && + echo_testing_string=`($CONFIG_SHELL "[$]0" --fallback-echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + echo="$CONFIG_SHELL [$]0 --fallback-echo" + else + # maybe with a smaller string... + prev=: + + for cmd in 'echo test' 'sed 2q "[$]0"' 'sed 10q "[$]0"' 'sed 20q "[$]0"' 'sed 50q "[$]0"'; do + if (test "X$echo_test_string" = "X`eval $cmd`") 2>/dev/null + then + break + fi + prev="$cmd" + done + + if test "$prev" != 'sed 50q "[$]0"'; then + echo_test_string=`eval $prev` + export echo_test_string + exec ${ORIGINAL_CONFIG_SHELL-${CONFIG_SHELL-/bin/sh}} "[$]0" ${1+"[$]@"} + else + # Oops. We lost completely, so just stick with echo. + echo=echo + fi + fi + fi + fi +fi +fi + +# Copy echo and quote the copy suitably for passing to libtool from +# the Makefile, instead of quoting the original, which is used later. +ECHO=$echo +if test "X$ECHO" = "X$CONFIG_SHELL [$]0 --fallback-echo"; then + ECHO="$CONFIG_SHELL \\\$\[$]0 --fallback-echo" +fi + +AC_SUBST(ECHO) +])])# _LT_AC_PROG_ECHO_BACKSLASH + + +# _LT_AC_LOCK +# ----------- +AC_DEFUN([_LT_AC_LOCK], +[AC_ARG_ENABLE([libtool-lock], + [AS_HELP_STRING([--disable-libtool-lock],[avoid locking (might break parallel builds)])]) +test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes + +# Some flags need to be propagated to the compiler or linker for good +# libtool support. +case $host in +ia64-*-hpux*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.$ac_objext` in + *ELF-32*) + HPUX_IA64_MODE="32" + ;; + *ELF-64*) + HPUX_IA64_MODE="64" + ;; + esac + fi + rm -rf conftest* + ;; +*-*-irix6*) + # Find out which ABI we are using. + echo '[#]line __oline__ "configure"' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + if test "$lt_cv_prog_gnu_ld" = yes; then + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -melf32bsmip" + ;; + *N32*) + LD="${LD-ld} -melf32bmipn32" + ;; + *64-bit*) + LD="${LD-ld} -melf64bmip" + ;; + esac + else + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -32" + ;; + *N32*) + LD="${LD-ld} -n32" + ;; + *64-bit*) + LD="${LD-ld} -64" + ;; + esac + fi + fi + rm -rf conftest* + ;; + +x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*|s390*-*linux*|sparc*-*linux*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.o` in + *32-bit*) + case $host in + x86_64-*linux*) + LD="${LD-ld} -m elf_i386" + ;; + ppc64-*linux*|powerpc64-*linux*) + LD="${LD-ld} -m elf32ppclinux" + ;; + s390x-*linux*) + LD="${LD-ld} -m elf_s390" + ;; + sparc64-*linux*) + LD="${LD-ld} -m elf32_sparc" + ;; + esac + ;; + *64-bit*) + case $host in + x86_64-*linux*) + LD="${LD-ld} -m elf_x86_64" + ;; + ppc*-*linux*|powerpc*-*linux*) + LD="${LD-ld} -m elf64ppc" + ;; + s390*-*linux*) + LD="${LD-ld} -m elf64_s390" + ;; + sparc*-*linux*) + LD="${LD-ld} -m elf64_sparc" + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; + +*-*-sco3.2v5*) + # On SCO OpenServer 5, we need -belf to get full-featured binaries. + SAVE_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -belf" + AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf, + [AC_LANG_PUSH(C) + AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[]])],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no]) + AC_LANG_POP]) + if test x"$lt_cv_cc_needs_belf" != x"yes"; then + # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf + CFLAGS="$SAVE_CFLAGS" + fi + ;; +sparc*-*solaris*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.o` in + *64-bit*) + case $lt_cv_prog_gnu_ld in + yes*) LD="${LD-ld} -m elf64_sparc" ;; + *) LD="${LD-ld} -64" ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; + +AC_PROVIDE_IFELSE([AC_LIBTOOL_WIN32_DLL], +[*-*-cygwin* | *-*-mingw* | *-*-pw32*) + AC_CHECK_TOOL(DLLTOOL, dlltool, false) + AC_CHECK_TOOL(AS, as, false) + AC_CHECK_TOOL(OBJDUMP, objdump, false) + ;; + ]) +esac + +need_locks="$enable_libtool_lock" + +])# _LT_AC_LOCK + + +# AC_LIBTOOL_COMPILER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, +# [OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE]) +# ---------------------------------------------------------------- +# Check whether the given compiler option works +AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION], +[AC_REQUIRE([LT_AC_PROG_SED]) +AC_CACHE_CHECK([$1], [$2], + [$2=no + ifelse([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4]) + printf "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="$3" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:__oline__: $lt_compile\"" >&AS_MESSAGE_LOG_FD) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&AS_MESSAGE_LOG_FD + echo "$as_me:__oline__: \$? = $ac_status" >&AS_MESSAGE_LOG_FD + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings other than the usual output. + $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then + $2=yes + fi + fi + $rm conftest* +]) + +if test x"[$]$2" = xyes; then + ifelse([$5], , :, [$5]) +else + ifelse([$6], , :, [$6]) +fi +])# AC_LIBTOOL_COMPILER_OPTION + + +# AC_LIBTOOL_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, +# [ACTION-SUCCESS], [ACTION-FAILURE]) +# ------------------------------------------------------------ +# Check whether the given compiler option works +AC_DEFUN([AC_LIBTOOL_LINKER_OPTION], +[AC_CACHE_CHECK([$1], [$2], + [$2=no + save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS $3" + printf "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The linker can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&AS_MESSAGE_LOG_FD + $echo "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then + $2=yes + fi + else + $2=yes + fi + fi + $rm conftest* + LDFLAGS="$save_LDFLAGS" +]) + +if test x"[$]$2" = xyes; then + ifelse([$4], , :, [$4]) +else + ifelse([$5], , :, [$5]) +fi +])# AC_LIBTOOL_LINKER_OPTION + + +# AC_LIBTOOL_SYS_MAX_CMD_LEN +# -------------------------- +AC_DEFUN([AC_LIBTOOL_SYS_MAX_CMD_LEN], +[# find the maximum length of command line arguments +AC_MSG_CHECKING([the maximum length of command line arguments]) +AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl + i=0 + teststring="ABCD" + + case $build_os in + msdosdjgpp*) + # On DJGPP, this test can blow up pretty badly due to problems in libc + # (any single argument exceeding 2000 bytes causes a buffer overrun + # during glob expansion). Even if it were fixed, the result of this + # check would be larger than it should be. + lt_cv_sys_max_cmd_len=12288; # 12K is about right + ;; + + gnu*) + # Under GNU Hurd, this test is not required because there is + # no limit to the length of command line arguments. + # Libtool will interpret -1 as no limit whatsoever + lt_cv_sys_max_cmd_len=-1; + ;; + + cygwin* | mingw*) + # On Win9x/ME, this test blows up -- it succeeds, but takes + # about 5 minutes as the teststring grows exponentially. + # Worse, since 9x/ME are not pre-emptively multitasking, + # you end up with a "frozen" computer, even though with patience + # the test eventually succeeds (with a max line length of 256k). + # Instead, let's just punt: use the minimum linelength reported by + # all of the supported platforms: 8192 (on NT/2K/XP). + lt_cv_sys_max_cmd_len=8192; + ;; + + amigaos*) + # On AmigaOS with pdksh, this test takes hours, literally. + # So we just punt and use a minimum line length of 8192. + lt_cv_sys_max_cmd_len=8192; + ;; + + netbsd* | freebsd* | openbsd* | darwin* | dragonfly*) + # This has been around since 386BSD, at least. Likely further. + if test -x /sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` + elif test -x /usr/sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` + else + lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs + fi + # And add a safety zone + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + ;; + + interix*) + # We know the value 262144 and hardcode it with a safety zone (like BSD) + lt_cv_sys_max_cmd_len=196608 + ;; + + osf*) + # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure + # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not + # nice to cause kernel panics so lets avoid the loop below. + # First set a reasonable default. + lt_cv_sys_max_cmd_len=16384 + # + if test -x /sbin/sysconfig; then + case `/sbin/sysconfig -q proc exec_disable_arg_limit` in + *1*) lt_cv_sys_max_cmd_len=-1 ;; + esac + fi + ;; + sco3.2v5*) + lt_cv_sys_max_cmd_len=102400 + ;; + sysv5* | sco5v6* | sysv4.2uw2*) + kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` + if test -n "$kargmax"; then + lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[[ ]]//'` + else + lt_cv_sys_max_cmd_len=32768 + fi + ;; + *) + # If test is not a shell built-in, we'll probably end up computing a + # maximum length that is only half of the actual maximum length, but + # we can't tell. + SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} + while (test "X"`$SHELL [$]0 --fallback-echo "X$teststring" 2>/dev/null` \ + = "XX$teststring") >/dev/null 2>&1 && + new_result=`expr "X$teststring" : ".*" 2>&1` && + lt_cv_sys_max_cmd_len=$new_result && + test $i != 17 # 1/2 MB should be enough + do + i=`expr $i + 1` + teststring=$teststring$teststring + done + teststring= + # Add a significant safety factor because C++ compilers can tack on massive + # amounts of additional arguments before passing them to the linker. + # It appears as though 1/2 is a usable value. + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` + ;; + esac +]) +if test -n $lt_cv_sys_max_cmd_len ; then + AC_MSG_RESULT($lt_cv_sys_max_cmd_len) +else + AC_MSG_RESULT(none) +fi +])# AC_LIBTOOL_SYS_MAX_CMD_LEN + + +# _LT_AC_CHECK_DLFCN +# ------------------ +AC_DEFUN([_LT_AC_CHECK_DLFCN], +[AC_CHECK_HEADERS(dlfcn.h)dnl +])# _LT_AC_CHECK_DLFCN + + +# _LT_AC_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE, +# ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING) +# --------------------------------------------------------------------- +AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF], +[AC_REQUIRE([_LT_AC_CHECK_DLFCN])dnl +if test "$cross_compiling" = yes; then : + [$4] +else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext < +#endif + +#include + +#ifdef RTLD_GLOBAL +# define LT_DLGLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LT_DLGLOBAL DL_GLOBAL +# else +# define LT_DLGLOBAL 0 +# endif +#endif + +/* We may have to define LT_DLLAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LT_DLLAZY_OR_NOW +# ifdef RTLD_LAZY +# define LT_DLLAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LT_DLLAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LT_DLLAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LT_DLLAZY_OR_NOW DL_NOW +# else +# define LT_DLLAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +#ifdef __cplusplus +extern "C" void exit (int); +#endif + +void fnord() { int i=42;} +int main () +{ + void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); + int status = $lt_dlunknown; + + if (self) + { + if (dlsym (self,"fnord")) status = $lt_dlno_uscore; + else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + /* dlclose (self); */ + } + else + puts (dlerror ()); + + exit (status); +}] +EOF + if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext} 2>/dev/null; then + (./conftest; exit; ) >&AS_MESSAGE_LOG_FD 2>/dev/null + lt_status=$? + case x$lt_status in + x$lt_dlno_uscore) $1 ;; + x$lt_dlneed_uscore) $2 ;; + x$lt_dlunknown|x*) $3 ;; + esac + else : + # compilation failed + $3 + fi +fi +rm -fr conftest* +])# _LT_AC_TRY_DLOPEN_SELF + + +# AC_LIBTOOL_DLOPEN_SELF +# ---------------------- +AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF], +[AC_REQUIRE([_LT_AC_CHECK_DLFCN])dnl +if test "x$enable_dlopen" != xyes; then + enable_dlopen=unknown + enable_dlopen_self=unknown + enable_dlopen_self_static=unknown +else + lt_cv_dlopen=no + lt_cv_dlopen_libs= + + case $host_os in + beos*) + lt_cv_dlopen="load_add_on" + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ;; + + mingw* | pw32*) + lt_cv_dlopen="LoadLibrary" + lt_cv_dlopen_libs= + ;; + + cygwin*) + lt_cv_dlopen="dlopen" + lt_cv_dlopen_libs= + ;; + + darwin*) + # if libdl is installed we need to link against it + AC_CHECK_LIB([dl], [dlopen], + [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"],[ + lt_cv_dlopen="dyld" + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ]) + ;; + + *) + AC_CHECK_FUNC([shl_load], + [lt_cv_dlopen="shl_load"], + [AC_CHECK_LIB([dld], [shl_load], + [lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-dld"], + [AC_CHECK_FUNC([dlopen], + [lt_cv_dlopen="dlopen"], + [AC_CHECK_LIB([dl], [dlopen], + [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"], + [AC_CHECK_LIB([svld], [dlopen], + [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"], + [AC_CHECK_LIB([dld], [dld_link], + [lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-dld"]) + ]) + ]) + ]) + ]) + ]) + ;; + esac + + if test "x$lt_cv_dlopen" != xno; then + enable_dlopen=yes + else + enable_dlopen=no + fi + + case $lt_cv_dlopen in + dlopen) + save_CPPFLAGS="$CPPFLAGS" + test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" + + save_LDFLAGS="$LDFLAGS" + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" + + save_LIBS="$LIBS" + LIBS="$lt_cv_dlopen_libs $LIBS" + + AC_CACHE_CHECK([whether a program can dlopen itself], + lt_cv_dlopen_self, [dnl + _LT_AC_TRY_DLOPEN_SELF( + lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes, + lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross) + ]) + + if test "x$lt_cv_dlopen_self" = xyes; then + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" + AC_CACHE_CHECK([whether a statically linked program can dlopen itself], + lt_cv_dlopen_self_static, [dnl + _LT_AC_TRY_DLOPEN_SELF( + lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes, + lt_cv_dlopen_self_static=no, lt_cv_dlopen_self_static=cross) + ]) + fi + + CPPFLAGS="$save_CPPFLAGS" + LDFLAGS="$save_LDFLAGS" + LIBS="$save_LIBS" + ;; + esac + + case $lt_cv_dlopen_self in + yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; + *) enable_dlopen_self=unknown ;; + esac + + case $lt_cv_dlopen_self_static in + yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; + *) enable_dlopen_self_static=unknown ;; + esac +fi +])# AC_LIBTOOL_DLOPEN_SELF + + +# AC_LIBTOOL_PROG_CC_C_O([TAGNAME]) +# --------------------------------- +# Check to see if options -c and -o are simultaneously supported by compiler +AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O], +[AC_REQUIRE([_LT_AC_SYS_COMPILER])dnl +AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext], + [_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)], + [_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)=no + $rm -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + printf "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:__oline__: $lt_compile\"" >&AS_MESSAGE_LOG_FD) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&AS_MESSAGE_LOG_FD + echo "$as_me:__oline__: \$? = $ac_status" >&AS_MESSAGE_LOG_FD + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + _LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes + fi + fi + chmod u+w . 2>&AS_MESSAGE_LOG_FD + $rm conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $rm out/ii_files/* && rmdir out/ii_files + $rm out/* && rmdir out + cd .. + rmdir conftest + $rm conftest* +]) +])# AC_LIBTOOL_PROG_CC_C_O + + +# AC_LIBTOOL_SYS_HARD_LINK_LOCKS([TAGNAME]) +# ----------------------------------------- +# Check to see if we can do hard links to lock some files if needed +AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], +[AC_REQUIRE([_LT_AC_LOCK])dnl + +hard_links="nottested" +if test "$_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)" = no && test "$need_locks" != no; then + # do not overwrite the value of need_locks provided by the user + AC_MSG_CHECKING([if we can lock with hard links]) + hard_links=yes + $rm conftest* + ln conftest.a conftest.b 2>/dev/null && hard_links=no + touch conftest.a + ln conftest.a conftest.b 2>&5 || hard_links=no + ln conftest.a conftest.b 2>/dev/null && hard_links=no + AC_MSG_RESULT([$hard_links]) + if test "$hard_links" = no; then + AC_MSG_WARN([`$CC' does not support `-c -o', so `make -j' may be unsafe]) + need_locks=warn + fi +else + need_locks=no +fi +])# AC_LIBTOOL_SYS_HARD_LINK_LOCKS + + +# AC_LIBTOOL_OBJDIR +# ----------------- +AC_DEFUN([AC_LIBTOOL_OBJDIR], +[AC_CACHE_CHECK([for objdir], [lt_cv_objdir], +[rm -f .libs 2>/dev/null +mkdir .libs 2>/dev/null +if test -d .libs; then + lt_cv_objdir=.libs +else + # MS-DOS does not allow filenames that begin with a dot. + lt_cv_objdir=_libs +fi +rmdir .libs 2>/dev/null]) +objdir=$lt_cv_objdir +])# AC_LIBTOOL_OBJDIR + + +# AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH([TAGNAME]) +# ---------------------------------------------- +# Check hardcoding attributes. +AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], +[AC_MSG_CHECKING([how to hardcode library paths into programs]) +_LT_AC_TAGVAR(hardcode_action, $1)= +if test -n "$_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)" || \ + test -n "$_LT_AC_TAGVAR(runpath_var, $1)" || \ + test "X$_LT_AC_TAGVAR(hardcode_automatic, $1)" = "Xyes" ; then + + # We can hardcode non-existant directories. + if test "$_LT_AC_TAGVAR(hardcode_direct, $1)" != no && + # If the only mechanism to avoid hardcoding is shlibpath_var, we + # have to relink, otherwise we might link with an installed library + # when we should be linking with a yet-to-be-installed one + ## test "$_LT_AC_TAGVAR(hardcode_shlibpath_var, $1)" != no && + test "$_LT_AC_TAGVAR(hardcode_minus_L, $1)" != no; then + # Linking always hardcodes the temporary library directory. + _LT_AC_TAGVAR(hardcode_action, $1)=relink + else + # We can link without hardcoding, and we can hardcode nonexisting dirs. + _LT_AC_TAGVAR(hardcode_action, $1)=immediate + fi +else + # We cannot hardcode anything, or else we can only hardcode existing + # directories. + _LT_AC_TAGVAR(hardcode_action, $1)=unsupported +fi +AC_MSG_RESULT([$_LT_AC_TAGVAR(hardcode_action, $1)]) + +if test "$_LT_AC_TAGVAR(hardcode_action, $1)" = relink; then + # Fast installation is not supported + enable_fast_install=no +elif test "$shlibpath_overrides_runpath" = yes || + test "$enable_shared" = no; then + # Fast installation is not necessary + enable_fast_install=needless +fi +])# AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH + + +# AC_LIBTOOL_SYS_LIB_STRIP +# ------------------------ +AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP], +[striplib= +old_striplib= +AC_MSG_CHECKING([whether stripping libraries is possible]) +if test -n "$STRIP" && $STRIP -V 2>&1 | grep "GNU strip" >/dev/null; then + test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" + test -z "$striplib" && striplib="$STRIP --strip-unneeded" + AC_MSG_RESULT([yes]) +else +# FIXME - insert some real tests, host_os isn't really good enough + case $host_os in + darwin*) + if test -n "$STRIP" ; then + striplib="$STRIP -x" + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) +fi + ;; + *) + AC_MSG_RESULT([no]) + ;; + esac +fi +])# AC_LIBTOOL_SYS_LIB_STRIP + + +# AC_LIBTOOL_SYS_DYNAMIC_LINKER +# ----------------------------- +# PORTME Fill in your ld.so characteristics +AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER], +[AC_MSG_CHECKING([dynamic linker characteristics]) +library_names_spec= +libname_spec='lib$name' +soname_spec= +shrext_cmds=".so" +postinstall_cmds= +postuninstall_cmds= +finish_cmds= +finish_eval= +shlibpath_var= +shlibpath_overrides_runpath=unknown +version_type=none +dynamic_linker="$host_os ld.so" +sys_lib_dlsearch_path_spec="/lib /usr/lib" +if test "$GCC" = yes; then + sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` + if echo "$sys_lib_search_path_spec" | grep ';' >/dev/null ; then + # if the path contains ";" then we assume it to be the separator + # otherwise default to the standard path separator (i.e. ":") - it is + # assumed that no part of a normal pathname contains ";" but that should + # okay in the real world where ";" in dirpaths is itself problematic. + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi +else + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" +fi +need_lib_prefix=unknown +hardcode_into_libs=no + +# when you set need_version to no, make sure it does not cause -set_version +# flags to be left without arguments +need_version=unknown + +case $host_os in +aix3*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' + shlibpath_var=LIBPATH + + # AIX 3 has no versioning support, so we append a major version to the name. + soname_spec='${libname}${release}${shared_ext}$major' + ;; + +aix4* | aix5*) + version_type=linux + need_lib_prefix=no + need_version=no + hardcode_into_libs=yes + if test "$host_cpu" = ia64; then + # AIX 5 supports IA64 + library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + else + # With GCC up to 2.95.x, collect2 would create an import file + # for dependence libraries. The import file would start with + # the line `#! .'. This would cause the generated library to + # depend on `.', always an invalid library. This was fixed in + # development snapshots of GCC prior to 3.0. + case $host_os in + aix4 | aix4.[[01]] | aix4.[[01]].*) + if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' + echo ' yes ' + echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then + : + else + can_build_shared=no + fi + ;; + esac + # AIX (on Power*) has no versioning support, so currently we can not hardcode correct + # soname into executable. Probably we can add versioning support to + # collect2, so additional links can be useful in future. + if test "$aix_use_runtimelinking" = yes; then + # If using run time linking (on AIX 4.2 or later) use lib.so + # instead of lib.a to let people know that these are not + # typical AIX shared libraries. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + else + # We preserve .a as extension for shared libraries through AIX4.2 + # and later when we are not doing run time linking. + library_names_spec='${libname}${release}.a $libname.a' + soname_spec='${libname}${release}${shared_ext}$major' + fi + shlibpath_var=LIBPATH + fi + ;; + +amigaos*) + library_names_spec='$libname.ixlibrary $libname.a' + # Create ${libname}_ixlibrary.a entries in /sys/libs. + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' + ;; + +beos*) + library_names_spec='${libname}${shared_ext}' + dynamic_linker="$host_os ld.so" + shlibpath_var=LIBRARY_PATH + ;; + +bsdi[[45]]*) + version_type=linux + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" + sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" + # the default ld.so.conf also contains /usr/contrib/lib and + # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow + # libtool to hard-code these into programs + ;; + +cygwin* | mingw* | pw32*) + version_type=windows + shrext_cmds=".dll" + need_version=no + need_lib_prefix=no + + case $GCC,$host_os in + yes,cygwin* | yes,mingw* | yes,pw32*) + library_names_spec='$libname.dll.a' + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \${file}`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $rm \$dlpath' + shlibpath_overrides_runpath=yes + + case $host_os in + cygwin*) + # Cygwin DLLs use 'cyg' prefix rather than 'lib' + soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' + sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib" + ;; + mingw*) + # MinGW DLLs use traditional 'lib' prefix + soname_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' + sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` + if echo "$sys_lib_search_path_spec" | [grep ';[c-zC-Z]:/' >/dev/null]; then + # It is most probably a Windows format PATH printed by + # mingw gcc, but we are running on Cygwin. Gcc prints its search + # path with ; separators, and with drive letters. We can handle the + # drive letters (cygwin fileutils understands them), so leave them, + # especially as we might pass files found there to a mingw objdump, + # which wouldn't understand a cygwinified path. Ahh. + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi + ;; + pw32*) + # pw32 DLLs use 'pw' prefix rather than 'lib' + library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' + ;; + esac + ;; + + *) + library_names_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext} $libname.lib' + ;; + esac + dynamic_linker='Win32 ld.exe' + # FIXME: first we should search . and the directory the executable is in + shlibpath_var=PATH + ;; + +darwin* | rhapsody*) + dynamic_linker="$host_os dyld" + version_type=darwin + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext' + soname_spec='${libname}${release}${major}$shared_ext' + shlibpath_overrides_runpath=yes + shlibpath_var=DYLD_LIBRARY_PATH + shrext_cmds='.dylib' + # Apple's gcc prints 'gcc -print-search-dirs' doesn't operate the same. + if test "$GCC" = yes; then + sys_lib_search_path_spec=`$CC -print-search-dirs | tr "\n" "$PATH_SEPARATOR" | sed -e 's/libraries:/@libraries:/' | tr "@" "\n" | grep "^libraries:" | sed -e "s/^libraries://" -e "s,=/,/,g" -e "s,$PATH_SEPARATOR, ,g" -e "s,.*,& /lib /usr/lib /usr/local/lib,g"` + else + sys_lib_search_path_spec='/lib /usr/lib /usr/local/lib' + fi + sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' + ;; + +dgux*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +freebsd1*) + dynamic_linker=no + ;; + +kfreebsd*-gnu) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='GNU ld.so' + ;; + +freebsd* | dragonfly*) + # DragonFly does not have aout. When/if they implement a new + # versioning mechanism, adjust this. + if test -x /usr/bin/objformat; then + objformat=`/usr/bin/objformat` + else + case $host_os in + freebsd[[123]]*) objformat=aout ;; + *) objformat=elf ;; + esac + fi + version_type=freebsd-$objformat + case $version_type in + freebsd-elf*) + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + need_version=no + need_lib_prefix=no + ;; + freebsd-*) + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' + need_version=yes + ;; + esac + shlibpath_var=LD_LIBRARY_PATH + case $host_os in + freebsd2*) + shlibpath_overrides_runpath=yes + ;; + freebsd3.[[01]]* | freebsdelf3.[[01]]*) + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + freebsd3.[[2-9]]* | freebsdelf3.[[2-9]]* | \ + freebsd4.[[0-5]] | freebsdelf4.[[0-5]] | freebsd4.1.1 | freebsdelf4.1.1) + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + freebsd*) # from 4.6 on + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + esac + ;; + +gnu*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + hardcode_into_libs=yes + ;; + +hpux9* | hpux10* | hpux11*) + # Give a soname corresponding to the major version so that dld.sl refuses to + # link against other versions. + version_type=sunos + need_lib_prefix=no + need_version=no + case $host_cpu in + ia64*) + shrext_cmds='.so' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.so" + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + if test "X$HPUX_IA64_MODE" = X32; then + sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" + else + sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" + fi + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + hppa*64*) + shrext_cmds='.sl' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.sl" + shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + *) + shrext_cmds='.sl' + dynamic_linker="$host_os dld.sl" + shlibpath_var=SHLIB_PATH + shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + ;; + esac + # HP-UX runs *really* slowly unless shared libraries are mode 555. + postinstall_cmds='chmod 555 $lib' + ;; + +interix3*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +irix5* | irix6* | nonstopux*) + case $host_os in + nonstopux*) version_type=nonstopux ;; + *) + if test "$lt_cv_prog_gnu_ld" = yes; then + version_type=linux + else + version_type=irix + fi ;; + esac + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' + case $host_os in + irix5* | nonstopux*) + libsuff= shlibsuff= + ;; + *) + case $LD in # libtool.m4 will add one of these switches to LD + *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") + libsuff= shlibsuff= libmagic=32-bit;; + *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") + libsuff=32 shlibsuff=N32 libmagic=N32;; + *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") + libsuff=64 shlibsuff=64 libmagic=64-bit;; + *) libsuff= shlibsuff= libmagic=never-match;; + esac + ;; + esac + shlibpath_var=LD_LIBRARY${shlibsuff}_PATH + shlibpath_overrides_runpath=no + sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" + sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" + hardcode_into_libs=yes + ;; + +# No shared lib support for Linux oldld, aout, or coff. +linux*oldld* | linux*aout* | linux*coff*) + dynamic_linker=no + ;; + +# This must be Linux ELF. +linux*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + # Append ld.so.conf contents to the search path + if test -f /etc/ld.so.conf; then + lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '` + sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" + fi + + # We used to test for /lib/ld.so.1 and disable shared libraries on + # powerpc, because MkLinux only supported shared libraries with the + # GNU dynamic linker. Since this was broken with cross compilers, + # most powerpc-linux boxes support dynamic linking these days and + # people can always --disable-shared, the test was removed, and we + # assume the GNU/Linux dynamic linker is in use. + dynamic_linker='GNU/Linux ld.so' + ;; + +knetbsd*-gnu) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='GNU ld.so' + ;; + +netbsd*) + version_type=sunos + need_lib_prefix=no + need_version=no + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + dynamic_linker='NetBSD (a.out) ld.so' + else + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='NetBSD ld.elf_so' + fi + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + +newsos6) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +nto-qnx*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +openbsd*) + version_type=sunos + sys_lib_dlsearch_path_spec="/usr/lib" + need_lib_prefix=no + # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. + case $host_os in + openbsd3.3 | openbsd3.3.*) need_version=yes ;; + *) need_version=no ;; + esac + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + shlibpath_var=LD_LIBRARY_PATH + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + case $host_os in + openbsd2.[[89]] | openbsd2.[[89]].*) + shlibpath_overrides_runpath=no + ;; + *) + shlibpath_overrides_runpath=yes + ;; + esac + else + shlibpath_overrides_runpath=yes + fi + ;; + +os2*) + libname_spec='$name' + shrext_cmds=".dll" + need_lib_prefix=no + library_names_spec='$libname${shared_ext} $libname.a' + dynamic_linker='OS/2 ld.exe' + shlibpath_var=LIBPATH + ;; + +osf3* | osf4* | osf5*) + version_type=osf + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" + sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" + ;; + +solaris*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + # ldd complains unless libraries are executable + postinstall_cmds='chmod +x $lib' + ;; + +sunos4*) + version_type=sunos + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + if test "$with_gnu_ld" = yes; then + need_lib_prefix=no + fi + need_version=yes + ;; + +sysv4 | sysv4.3*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + case $host_vendor in + sni) + shlibpath_overrides_runpath=no + need_lib_prefix=no + export_dynamic_flag_spec='${wl}-Blargedynsym' + runpath_var=LD_RUN_PATH + ;; + siemens) + need_lib_prefix=no + ;; + motorola) + need_lib_prefix=no + need_version=no + shlibpath_overrides_runpath=no + sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' + ;; + esac + ;; + +sysv4*MP*) + if test -d /usr/nec ;then + version_type=linux + library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' + soname_spec='$libname${shared_ext}.$major' + shlibpath_var=LD_LIBRARY_PATH + fi + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + version_type=freebsd-elf + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + hardcode_into_libs=yes + if test "$with_gnu_ld" = yes; then + sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' + shlibpath_overrides_runpath=no + else + sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' + shlibpath_overrides_runpath=yes + case $host_os in + sco3.2v5*) + sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" + ;; + esac + fi + sys_lib_dlsearch_path_spec='/usr/lib' + ;; + +uts4*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +*) + dynamic_linker=no + ;; +esac +AC_MSG_RESULT([$dynamic_linker]) +test "$dynamic_linker" = no && can_build_shared=no + +variables_saved_for_relink="PATH $shlibpath_var $runpath_var" +if test "$GCC" = yes; then + variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" +fi +])# AC_LIBTOOL_SYS_DYNAMIC_LINKER + + +# _LT_AC_TAGCONFIG +# ---------------- +AC_DEFUN([_LT_AC_TAGCONFIG], +[AC_ARG_WITH([tags], + [AS_HELP_STRING([--with-tags@<:@=TAGS@:>@],[include additional configurations @<:@automatic@:>@])], + [tagnames="$withval"]) + +if test -f "$ltmain" && test -n "$tagnames"; then + if test ! -f "${ofile}"; then + AC_MSG_WARN([output file `$ofile' does not exist]) + fi + + if test -z "$LTCC"; then + eval "`$SHELL ${ofile} --config | grep '^LTCC='`" + if test -z "$LTCC"; then + AC_MSG_WARN([output file `$ofile' does not look like a libtool script]) + else + AC_MSG_WARN([using `LTCC=$LTCC', extracted from `$ofile']) + fi + fi + if test -z "$LTCFLAGS"; then + eval "`$SHELL ${ofile} --config | grep '^LTCFLAGS='`" + fi + + # Extract list of available tagged configurations in $ofile. + # Note that this assumes the entire list is on one line. + available_tags=`grep "^available_tags=" "${ofile}" | $SED -e 's/available_tags=\(.*$\)/\1/' -e 's/\"//g'` + + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for tagname in $tagnames; do + IFS="$lt_save_ifs" + # Check whether tagname contains only valid characters + case `$echo "X$tagname" | $Xsed -e 's:[[-_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890,/]]::g'` in + "") ;; + *) AC_MSG_ERROR([invalid tag name: $tagname]) + ;; + esac + + if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$" < "${ofile}" > /dev/null + then + AC_MSG_ERROR([tag name "$tagname" already exists]) + fi + + # Update the list of available tags. + if test -n "$tagname"; then + echo appending configuration tag \"$tagname\" to $ofile + + case $tagname in + CXX) + if test -n "$CXX" && ( test "X$CXX" != "Xno" && + ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) || + (test "X$CXX" != "Xg++"))) ; then + AC_LIBTOOL_LANG_CXX_CONFIG + else + tagname="" + fi + ;; + + F77) + if test -n "$F77" && test "X$F77" != "Xno"; then + AC_LIBTOOL_LANG_F77_CONFIG + else + tagname="" + fi + ;; + + GCJ) + if test -n "$GCJ" && test "X$GCJ" != "Xno"; then + AC_LIBTOOL_LANG_GCJ_CONFIG + else + tagname="" + fi + ;; + + RC) + AC_LIBTOOL_LANG_RC_CONFIG + ;; + + *) + AC_MSG_ERROR([Unsupported tag name: $tagname]) + ;; + esac + + # Append the new tag name to the list of available tags. + if test -n "$tagname" ; then + available_tags="$available_tags $tagname" + fi + fi + done + IFS="$lt_save_ifs" + + # Now substitute the updated list of available tags. + if eval "sed -e 's/^available_tags=.*\$/available_tags=\"$available_tags\"/' \"$ofile\" > \"${ofile}T\""; then + mv "${ofile}T" "$ofile" + chmod +x "$ofile" + else + rm -f "${ofile}T" + AC_MSG_ERROR([unable to update list of available tagged configurations.]) + fi +fi +])# _LT_AC_TAGCONFIG + + +# AC_LIBTOOL_DLOPEN +# ----------------- +# enable checks for dlopen support +AC_DEFUN([AC_LIBTOOL_DLOPEN], + [AC_BEFORE([$0],[AC_LIBTOOL_SETUP]) +])# AC_LIBTOOL_DLOPEN + + +# AC_LIBTOOL_WIN32_DLL +# -------------------- +# declare package support for building win32 DLLs +AC_DEFUN([AC_LIBTOOL_WIN32_DLL], +[AC_BEFORE([$0], [AC_LIBTOOL_SETUP]) +])# AC_LIBTOOL_WIN32_DLL + + +# AC_ENABLE_SHARED([DEFAULT]) +# --------------------------- +# implement the --enable-shared flag +# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. +AC_DEFUN([AC_ENABLE_SHARED], +[define([enable_shared_default], ifelse($1, no, no, yes))dnl +AC_ARG_ENABLE([shared], + AS_HELP_STRING([--enable-shared@<:@=PKGS@:>@],[build shared libraries @<:@default=enable_shared_default@:>@]), + [p=${PACKAGE-default} + case $enableval in + yes) enable_shared=yes ;; + no) enable_shared=no ;; + *) + enable_shared=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_shared=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac], + [enable_shared=]enable_shared_default) +])# AC_ENABLE_SHARED + + +# AC_DISABLE_SHARED +# ----------------- +# set the default shared flag to --disable-shared +AC_DEFUN([AC_DISABLE_SHARED], +[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl +AC_ENABLE_SHARED(no) +])# AC_DISABLE_SHARED + + +# AC_ENABLE_STATIC([DEFAULT]) +# --------------------------- +# implement the --enable-static flag +# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. +AC_DEFUN([AC_ENABLE_STATIC], +[define([enable_static_default], ifelse($1, no, no, yes))dnl +AC_ARG_ENABLE([static], + AS_HELP_STRING([--enable-static@<:@=PKGS@:>@],[build static libraries @<:@default=enable_static_default@:>@]), + [p=${PACKAGE-default} + case $enableval in + yes) enable_static=yes ;; + no) enable_static=no ;; + *) + enable_static=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_static=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac], + [enable_static=]enable_static_default) +])# AC_ENABLE_STATIC + + +# AC_DISABLE_STATIC +# ----------------- +# set the default static flag to --disable-static +AC_DEFUN([AC_DISABLE_STATIC], +[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl +AC_ENABLE_STATIC(no) +])# AC_DISABLE_STATIC + + +# AC_ENABLE_FAST_INSTALL([DEFAULT]) +# --------------------------------- +# implement the --enable-fast-install flag +# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. +AC_DEFUN([AC_ENABLE_FAST_INSTALL], +[define([enable_Fast_install_default], ifelse($1, no, no, yes))dnl +AC_ARG_ENABLE([fast-install], + AS_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@],[optimize for fast installation @<:@default=enable_Fast_install_default@:>@]), + [p=${PACKAGE-default} + case $enableval in + yes) enable_fast_install=yes ;; + no) enable_fast_install=no ;; + *) + enable_fast_install=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_fast_install=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac], + [enable_fast_install=]enable_Fast_install_default) +])# AC_ENABLE_FAST_INSTALL + + +# AC_DISABLE_FAST_INSTALL +# ----------------------- +# set the default to --disable-fast-install +AC_DEFUN([AC_DISABLE_FAST_INSTALL], +[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl +AC_ENABLE_FAST_INSTALL(no) +])# AC_DISABLE_FAST_INSTALL + + +# AC_LIBTOOL_PICMODE([MODE]) +# -------------------------- +# implement the --with-pic flag +# MODE is either `yes' or `no'. If omitted, it defaults to `both'. +AC_DEFUN([AC_LIBTOOL_PICMODE], +[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl +pic_mode=ifelse($#,1,$1,default) +])# AC_LIBTOOL_PICMODE + + +# AC_PROG_EGREP +# ------------- +# This is predefined starting with Autoconf 2.54, so this conditional +# definition can be removed once we require Autoconf 2.54 or later. +m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP], +[AC_CACHE_CHECK([for egrep], [ac_cv_prog_egrep], + [if echo a | (grep -E '(a|b)') >/dev/null 2>&1 + then ac_cv_prog_egrep='grep -E' + else ac_cv_prog_egrep='egrep' + fi]) + EGREP=$ac_cv_prog_egrep + AC_SUBST([EGREP]) +])]) + + +# AC_PATH_TOOL_PREFIX +# ------------------- +# find a file program which can recognise shared library +AC_DEFUN([AC_PATH_TOOL_PREFIX], +[AC_REQUIRE([AC_PROG_EGREP])dnl +AC_MSG_CHECKING([for $1]) +AC_CACHE_VAL(lt_cv_path_MAGIC_CMD, +[case $MAGIC_CMD in +[[\\/*] | ?:[\\/]*]) + lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. + ;; +*) + lt_save_MAGIC_CMD="$MAGIC_CMD" + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR +dnl $ac_dummy forces splitting on constant user-supplied paths. +dnl POSIX.2 word splitting is done only on the output of word expansions, +dnl not every word. This closes a longstanding sh security hole. + ac_dummy="ifelse([$2], , $PATH, [$2])" + for ac_dir in $ac_dummy; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$1; then + lt_cv_path_MAGIC_CMD="$ac_dir/$1" + if test -n "$file_magic_test_file"; then + case $deplibs_check_method in + "file_magic "*) + file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` + MAGIC_CMD="$lt_cv_path_MAGIC_CMD" + if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | + $EGREP "$file_magic_regex" > /dev/null; then + : + else + cat <&2 + +*** Warning: the command libtool uses to detect shared libraries, +*** $file_magic_cmd, produces output that libtool cannot recognize. +*** The result is that libtool may fail to recognize shared libraries +*** as such. This will affect the creation of libtool libraries that +*** depend on shared libraries, but programs linked with such libtool +*** libraries will work regardless of this problem. Nevertheless, you +*** may want to report the problem to your system manager and/or to +*** bug-libtool@gnu.org + +EOF + fi ;; + esac + fi + break + fi + done + IFS="$lt_save_ifs" + MAGIC_CMD="$lt_save_MAGIC_CMD" + ;; +esac]) +MAGIC_CMD="$lt_cv_path_MAGIC_CMD" +if test -n "$MAGIC_CMD"; then + AC_MSG_RESULT($MAGIC_CMD) +else + AC_MSG_RESULT(no) +fi +])# AC_PATH_TOOL_PREFIX + + +# AC_PATH_MAGIC +# ------------- +# find a file program which can recognise a shared library +AC_DEFUN([AC_PATH_MAGIC], +[AC_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH) +if test -z "$lt_cv_path_MAGIC_CMD"; then + if test -n "$ac_tool_prefix"; then + AC_PATH_TOOL_PREFIX(file, /usr/bin$PATH_SEPARATOR$PATH) + else + MAGIC_CMD=: + fi +fi +])# AC_PATH_MAGIC + + +# AC_PROG_LD +# ---------- +# find the pathname to the GNU or non-GNU linker +AC_DEFUN([AC_PROG_LD], +[AC_ARG_WITH([gnu-ld], + [AS_HELP_STRING([--with-gnu-ld],[assume the C compiler uses GNU ld @<:@default=no@:>@])], + [test "$withval" = no || with_gnu_ld=yes], + [with_gnu_ld=no]) +AC_REQUIRE([LT_AC_PROG_SED])dnl +AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +ac_prog=ld +if test "$GCC" = yes; then + # Check if gcc -print-prog-name=ld gives a path. + AC_MSG_CHECKING([for ld used by $CC]) + case $host in + *-*-mingw*) + # gcc leaves a trailing carriage return which upsets mingw + ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; + *) + ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; + esac + case $ac_prog in + # Accept absolute paths. + [[\\/]]* | ?:[[\\/]]*) + re_direlt='/[[^/]][[^/]]*/\.\./' + # Canonicalize the pathname of ld + ac_prog=`echo $ac_prog| $SED 's%\\\\%/%g'` + while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do + ac_prog=`echo $ac_prog| $SED "s%$re_direlt%/%"` + done + test -z "$LD" && LD="$ac_prog" + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test "$with_gnu_ld" = yes; then + AC_MSG_CHECKING([for GNU ld]) +else + AC_MSG_CHECKING([for non-GNU ld]) +fi +AC_CACHE_VAL(lt_cv_path_LD, +[if test -z "$LD"; then + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then + lt_cv_path_LD="$ac_dir/$ac_prog" + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some variants of GNU ld only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + case `"$lt_cv_path_LD" -v 2>&1 &1 /dev/null; then + case $host_cpu in + i*86 ) + # Not sure whether the presence of OpenBSD here was a mistake. + # Let's accept both of them until this is cleared up. + lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[[3-9]]86 (compact )?demand paged shared library' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` + ;; + esac + else + lt_cv_deplibs_check_method=pass_all + fi + ;; + +gnu*) + lt_cv_deplibs_check_method=pass_all + ;; + +hpux10.20* | hpux11*) + lt_cv_file_magic_cmd=/usr/bin/file + case $host_cpu in + ia64*) + lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64' + lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so + ;; + hppa*64*) + [lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - PA-RISC [0-9].[0-9]'] + lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl + ;; + *) + lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]].[[0-9]]) shared library' + lt_cv_file_magic_test_file=/usr/lib/libc.sl + ;; + esac + ;; + +interix3*) + # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|\.a)$' + ;; + +irix5* | irix6* | nonstopux*) + case $LD in + *-32|*"-32 ") libmagic=32-bit;; + *-n32|*"-n32 ") libmagic=N32;; + *-64|*"-64 ") libmagic=64-bit;; + *) libmagic=never-match;; + esac + lt_cv_deplibs_check_method=pass_all + ;; + +# This must be Linux ELF. +linux*) + lt_cv_deplibs_check_method=pass_all + ;; + +netbsd*) + if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|_pic\.a)$' + fi + ;; + +newos6*) + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=/usr/lib/libnls.so + ;; + +nto-qnx*) + lt_cv_deplibs_check_method=unknown + ;; + +openbsd*) + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|\.so|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' + fi + ;; + +osf3* | osf4* | osf5*) + lt_cv_deplibs_check_method=pass_all + ;; + +solaris*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv4 | sysv4.3*) + case $host_vendor in + motorola) + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]' + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` + ;; + ncr) + lt_cv_deplibs_check_method=pass_all + ;; + sequent) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )' + ;; + sni) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib" + lt_cv_file_magic_test_file=/lib/libc.so + ;; + siemens) + lt_cv_deplibs_check_method=pass_all + ;; + pc) + lt_cv_deplibs_check_method=pass_all + ;; + esac + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + lt_cv_deplibs_check_method=pass_all + ;; +esac +]) +file_magic_cmd=$lt_cv_file_magic_cmd +deplibs_check_method=$lt_cv_deplibs_check_method +test -z "$deplibs_check_method" && deplibs_check_method=unknown +])# AC_DEPLIBS_CHECK_METHOD + + +# AC_PROG_NM +# ---------- +# find the pathname to a BSD-compatible name lister +AC_DEFUN([AC_PROG_NM], +[AC_CACHE_CHECK([for BSD-compatible nm], lt_cv_path_NM, +[if test -n "$NM"; then + # Let the user override the test. + lt_cv_path_NM="$NM" +else + lt_nm_to_check="${ac_tool_prefix}nm" + if test -n "$ac_tool_prefix" && test "$build" = "$host"; then + lt_nm_to_check="$lt_nm_to_check nm" + fi + for lt_tmp_nm in $lt_nm_to_check; do + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + tmp_nm="$ac_dir/$lt_tmp_nm" + if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then + # Check to see if the nm accepts a BSD-compat flag. + # Adding the `sed 1q' prevents false positives on HP-UX, which says: + # nm: unknown option "B" ignored + # Tru64's nm complains that /dev/null is an invalid object file + case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in + */dev/null* | *'Invalid file or object type'*) + lt_cv_path_NM="$tmp_nm -B" + break + ;; + *) + case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in + */dev/null*) + lt_cv_path_NM="$tmp_nm -p" + break + ;; + *) + lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but + continue # so that we can try to find one that supports BSD flags + ;; + esac + ;; + esac + fi + done + IFS="$lt_save_ifs" + done + test -z "$lt_cv_path_NM" && lt_cv_path_NM=nm +fi]) +NM="$lt_cv_path_NM" +])# AC_PROG_NM + + +# AC_CHECK_LIBM +# ------------- +# check for math library +AC_DEFUN([AC_CHECK_LIBM], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +LIBM= +case $host in +*-*-beos* | *-*-cygwin* | *-*-pw32* | *-*-darwin*) + # These system don't have libm, or don't need it + ;; +*-ncr-sysv4.3*) + AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM="-lmw") + AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm") + ;; +*) + AC_CHECK_LIB(m, cos, LIBM="-lm") + ;; +esac +])# AC_CHECK_LIBM + + +# AC_LIBLTDL_CONVENIENCE([DIRECTORY]) +# ----------------------------------- +# sets LIBLTDL to the link flags for the libltdl convenience library and +# LTDLINCL to the include flags for the libltdl header and adds +# --enable-ltdl-convenience to the configure arguments. Note that +# AC_CONFIG_SUBDIRS is not called here. If DIRECTORY is not provided, +# it is assumed to be `libltdl'. LIBLTDL will be prefixed with +# '${top_builddir}/' and LTDLINCL will be prefixed with '${top_srcdir}/' +# (note the single quotes!). If your package is not flat and you're not +# using automake, define top_builddir and top_srcdir appropriately in +# the Makefiles. +AC_DEFUN([AC_LIBLTDL_CONVENIENCE], +[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl + case $enable_ltdl_convenience in + no) AC_MSG_ERROR([this package needs a convenience libltdl]) ;; + "") enable_ltdl_convenience=yes + ac_configure_args="$ac_configure_args --enable-ltdl-convenience" ;; + esac + LIBLTDL='${top_builddir}/'ifelse($#,1,[$1],['libltdl'])/libltdlc.la + LTDLINCL='-I${top_srcdir}/'ifelse($#,1,[$1],['libltdl']) + # For backwards non-gettext consistent compatibility... + INCLTDL="$LTDLINCL" +])# AC_LIBLTDL_CONVENIENCE + + +# AC_LIBLTDL_INSTALLABLE([DIRECTORY]) +# ----------------------------------- +# sets LIBLTDL to the link flags for the libltdl installable library and +# LTDLINCL to the include flags for the libltdl header and adds +# --enable-ltdl-install to the configure arguments. Note that +# AC_CONFIG_SUBDIRS is not called here. If DIRECTORY is not provided, +# and an installed libltdl is not found, it is assumed to be `libltdl'. +# LIBLTDL will be prefixed with '${top_builddir}/'# and LTDLINCL with +# '${top_srcdir}/' (note the single quotes!). If your package is not +# flat and you're not using automake, define top_builddir and top_srcdir +# appropriately in the Makefiles. +# In the future, this macro may have to be called after AC_PROG_LIBTOOL. +AC_DEFUN([AC_LIBLTDL_INSTALLABLE], +[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl + AC_CHECK_LIB(ltdl, lt_dlinit, + [test x"$enable_ltdl_install" != xyes && enable_ltdl_install=no], + [if test x"$enable_ltdl_install" = xno; then + AC_MSG_WARN([libltdl not installed, but installation disabled]) + else + enable_ltdl_install=yes + fi + ]) + if test x"$enable_ltdl_install" = x"yes"; then + ac_configure_args="$ac_configure_args --enable-ltdl-install" + LIBLTDL='${top_builddir}/'ifelse($#,1,[$1],['libltdl'])/libltdl.la + LTDLINCL='-I${top_srcdir}/'ifelse($#,1,[$1],['libltdl']) + else + ac_configure_args="$ac_configure_args --enable-ltdl-install=no" + LIBLTDL="-lltdl" + LTDLINCL= + fi + # For backwards non-gettext consistent compatibility... + INCLTDL="$LTDLINCL" +])# AC_LIBLTDL_INSTALLABLE + + +# AC_LIBTOOL_CXX +# -------------- +# enable support for C++ libraries +AC_DEFUN([AC_LIBTOOL_CXX], +[AC_REQUIRE([_LT_AC_LANG_CXX]) +])# AC_LIBTOOL_CXX + + +# _LT_AC_LANG_CXX +# --------------- +AC_DEFUN([_LT_AC_LANG_CXX], +[AC_REQUIRE([AC_PROG_CXX]) +AC_REQUIRE([_LT_AC_PROG_CXXCPP]) +_LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}CXX]) +])# _LT_AC_LANG_CXX + +# _LT_AC_PROG_CXXCPP +# ------------------ +AC_DEFUN([_LT_AC_PROG_CXXCPP], +[ +AC_REQUIRE([AC_PROG_CXX]) +if test -n "$CXX" && ( test "X$CXX" != "Xno" && + ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) || + (test "X$CXX" != "Xg++"))) ; then + AC_PROG_CXXCPP +fi +])# _LT_AC_PROG_CXXCPP + +# AC_LIBTOOL_F77 +# -------------- +# enable support for Fortran 77 libraries +AC_DEFUN([AC_LIBTOOL_F77], +[AC_REQUIRE([_LT_AC_LANG_F77]) +])# AC_LIBTOOL_F77 + + +# _LT_AC_LANG_F77 +# --------------- +AC_DEFUN([_LT_AC_LANG_F77], +[AC_REQUIRE([AC_PROG_F77]) +_LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}F77]) +])# _LT_AC_LANG_F77 + + +# AC_LIBTOOL_GCJ +# -------------- +# enable support for GCJ libraries +AC_DEFUN([AC_LIBTOOL_GCJ], +[AC_REQUIRE([_LT_AC_LANG_GCJ]) +])# AC_LIBTOOL_GCJ + + +# _LT_AC_LANG_GCJ +# --------------- +AC_DEFUN([_LT_AC_LANG_GCJ], +[AC_PROVIDE_IFELSE([AC_PROG_GCJ],[], + [AC_PROVIDE_IFELSE([A][M_PROG_GCJ],[], + [AC_PROVIDE_IFELSE([LT_AC_PROG_GCJ],[], + [ifdef([AC_PROG_GCJ],[AC_REQUIRE([AC_PROG_GCJ])], + [ifdef([A][M_PROG_GCJ],[AC_REQUIRE([A][M_PROG_GCJ])], + [AC_REQUIRE([A][C_PROG_GCJ_OR_A][M_PROG_GCJ])])])])])]) +_LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}GCJ]) +])# _LT_AC_LANG_GCJ + + +# AC_LIBTOOL_RC +# ------------- +# enable support for Windows resource files +AC_DEFUN([AC_LIBTOOL_RC], +[AC_REQUIRE([LT_AC_PROG_RC]) +_LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}RC]) +])# AC_LIBTOOL_RC + + +# AC_LIBTOOL_LANG_C_CONFIG +# ------------------------ +# Ensure that the configuration vars for the C compiler are +# suitably defined. Those variables are subsequently used by +# AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'. +AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG], [_LT_AC_LANG_C_CONFIG]) +AC_DEFUN([_LT_AC_LANG_C_CONFIG], +[lt_save_CC="$CC" +AC_LANG_PUSH(C) + +# Source file extension for C test sources. +ac_ext=c + +# Object file extension for compiled C test sources. +objext=o +_LT_AC_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="int some_variable = 0;\n" + +# Code to be used in simple link tests +lt_simple_link_test_code='int main(){return(0);}\n' + +_LT_AC_SYS_COMPILER + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +## CAVEAT EMPTOR: +## There is no encapsulation within the following macros, do not change +## the running order or otherwise move them around unless you know exactly +## what you are doing... +AC_LIBTOOL_PROG_COMPILER_NO_RTTI($1) +AC_LIBTOOL_PROG_COMPILER_PIC($1) +AC_LIBTOOL_PROG_CC_C_O($1) +AC_LIBTOOL_SYS_HARD_LINK_LOCKS($1) +AC_LIBTOOL_PROG_LD_SHLIBS($1) +AC_LIBTOOL_SYS_DYNAMIC_LINKER($1) +AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH($1) +AC_LIBTOOL_SYS_LIB_STRIP +AC_LIBTOOL_DLOPEN_SELF + +# Report which library types will actually be built +AC_MSG_CHECKING([if libtool supports shared libraries]) +AC_MSG_RESULT([$can_build_shared]) + +AC_MSG_CHECKING([whether to build shared libraries]) +test "$can_build_shared" = "no" && enable_shared=no + +# On AIX, shared libraries and static libraries use the same namespace, and +# are all built from PIC. +case $host_os in +aix3*) + test "$enable_shared" = yes && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + +aix4* | aix5*) + if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then + test "$enable_shared" = yes && enable_static=no + fi + ;; +esac +AC_MSG_RESULT([$enable_shared]) + +AC_MSG_CHECKING([whether to build static libraries]) +# Make sure either enable_shared or enable_static is yes. +test "$enable_shared" = yes || enable_static=yes +AC_MSG_RESULT([$enable_static]) + +AC_LIBTOOL_CONFIG($1) + +AC_LANG_POP +CC="$lt_save_CC" +])# AC_LIBTOOL_LANG_C_CONFIG + + +# AC_LIBTOOL_LANG_CXX_CONFIG +# -------------------------- +# Ensure that the configuration vars for the C compiler are +# suitably defined. Those variables are subsequently used by +# AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'. +AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG], [_LT_AC_LANG_CXX_CONFIG(CXX)]) +AC_DEFUN([_LT_AC_LANG_CXX_CONFIG], +[AC_LANG_PUSH(C++) +AC_REQUIRE([AC_PROG_CXX]) +AC_REQUIRE([_LT_AC_PROG_CXXCPP]) + +_LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no +_LT_AC_TAGVAR(allow_undefined_flag, $1)= +_LT_AC_TAGVAR(always_export_symbols, $1)=no +_LT_AC_TAGVAR(archive_expsym_cmds, $1)= +_LT_AC_TAGVAR(export_dynamic_flag_spec, $1)= +_LT_AC_TAGVAR(hardcode_direct, $1)=no +_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)= +_LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)= +_LT_AC_TAGVAR(hardcode_libdir_separator, $1)= +_LT_AC_TAGVAR(hardcode_minus_L, $1)=no +_LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported +_LT_AC_TAGVAR(hardcode_automatic, $1)=no +_LT_AC_TAGVAR(module_cmds, $1)= +_LT_AC_TAGVAR(module_expsym_cmds, $1)= +_LT_AC_TAGVAR(link_all_deplibs, $1)=unknown +_LT_AC_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_AC_TAGVAR(no_undefined_flag, $1)= +_LT_AC_TAGVAR(whole_archive_flag_spec, $1)= +_LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=no + +# Dependencies to place before and after the object being linked: +_LT_AC_TAGVAR(predep_objects, $1)= +_LT_AC_TAGVAR(postdep_objects, $1)= +_LT_AC_TAGVAR(predeps, $1)= +_LT_AC_TAGVAR(postdeps, $1)= +_LT_AC_TAGVAR(compiler_lib_search_path, $1)= + +# Source file extension for C++ test sources. +ac_ext=cpp + +# Object file extension for compiled C++ test sources. +objext=o +_LT_AC_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="int some_variable = 0;\n" + +# Code to be used in simple link tests +lt_simple_link_test_code='int main(int, char *[[]]) { return(0); }\n' + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. +_LT_AC_SYS_COMPILER + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +# Allow CC to be a program name with arguments. +lt_save_CC=$CC +lt_save_LD=$LD +lt_save_GCC=$GCC +GCC=$GXX +lt_save_with_gnu_ld=$with_gnu_ld +lt_save_path_LD=$lt_cv_path_LD +if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then + lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx +else + $as_unset lt_cv_prog_gnu_ld +fi +if test -n "${lt_cv_path_LDCXX+set}"; then + lt_cv_path_LD=$lt_cv_path_LDCXX +else + $as_unset lt_cv_path_LD +fi +test -z "${LDCXX+set}" || LD=$LDCXX +CC=${CXX-"c++"} +compiler=$CC +_LT_AC_TAGVAR(compiler, $1)=$CC +_LT_CC_BASENAME([$compiler]) + +# We don't want -fno-exception wen compiling C++ code, so set the +# no_builtin_flag separately +if test "$GXX" = yes; then + _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' +else + _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= +fi + +if test "$GXX" = yes; then + # Set up default GNU C++ configuration + + AC_PROG_LD + + # Check if GNU C++ uses GNU ld as the underlying linker, since the + # archiving commands below assume that GNU ld is being used. + if test "$with_gnu_ld" = yes; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + + # If archive_cmds runs LD, not CC, wlarc should be empty + # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to + # investigate it a little bit more. (MM) + wlarc='${wl}' + + # ancient GNU ld didn't support --whole-archive et. al. + if eval "`$CC -print-prog-name=ld` --help 2>&1" | \ + grep 'no-whole-archive' > /dev/null; then + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + else + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)= + fi + else + with_gnu_ld=no + wlarc= + + # A generic and very simple default shared library creation + # command for GNU C++ for the case where it uses the native + # linker, instead of GNU ld. If possible, this setting should + # overridden to take advantage of the native linker features on + # the platform it is being used on. + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' + fi + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"' + +else + GXX=no + with_gnu_ld=no + wlarc= +fi + +# PORTME: fill in a description of your system's C++ link characteristics +AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) +_LT_AC_TAGVAR(ld_shlibs, $1)=yes +case $host_os in + aix3*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + aix4* | aix5*) + if test "$host_cpu" = ia64; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag="" + else + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # need to do runtime linking. + case $host_os in aix4.[[23]]|aix4.[[23]].*|aix5*) + for ld_flag in $LDFLAGS; do + case $ld_flag in + *-brtl*) + aix_use_runtimelinking=yes + break + ;; + esac + done + ;; + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + _LT_AC_TAGVAR(archive_cmds, $1)='' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + + if test "$GXX" = yes; then + case $host_os in aix4.[[012]]|aix4.[[012]].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`${CC} -print-prog-name=collect2` + if test -f "$collect2name" && \ + strings "$collect2name" | grep resolve_lib_name >/dev/null + then + # We have reworked collect2 + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + else + # We have old collect2 + _LT_AC_TAGVAR(hardcode_direct, $1)=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)= + fi + ;; + esac + shared_flag='-shared' + if test "$aix_use_runtimelinking" = yes; then + shared_flag="$shared_flag "'${wl}-G' + fi + else + # not using gcc + if test "$host_cpu" = ia64; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test "$aix_use_runtimelinking" = yes; then + shared_flag='${wl}-G' + else + shared_flag='${wl}-bM:SRE' + fi + fi + fi + + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to export. + _LT_AC_TAGVAR(always_export_symbols, $1)=yes + if test "$aix_use_runtimelinking" = yes; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + _LT_AC_TAGVAR(allow_undefined_flag, $1)='-berok' + # Determine the default libpath from the value encoded in an empty executable. + _LT_AC_SYS_LIBPATH_AIX + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" + + _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" + else + if test "$host_cpu" = ia64; then + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib' + _LT_AC_TAGVAR(allow_undefined_flag, $1)="-z nodefs" + _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an empty executable. + _LT_AC_SYS_LIBPATH_AIX + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + _LT_AC_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok' + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok' + # Exported symbols can be pulled into shared objects from archives + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='$convenience' + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes + # This is similar to how AIX traditionally builds its shared libraries. + _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' + fi + fi + ;; + + beos*) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + chorus*) + case $cc_basename in + *) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + cygwin* | mingw* | pw32*) + # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, + # as there is no search path for DLLs. + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_AC_TAGVAR(always_export_symbols, $1)=no + _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + + if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file (1st line + # is EXPORTS), use it as is; otherwise, prepend... + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + darwin* | rhapsody*) + case $host_os in + rhapsody* | darwin1.[[012]]) + _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-undefined ${wl}suppress' + ;; + *) # Darwin 1.3 on + if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' + else + case ${MACOSX_DEPLOYMENT_TARGET} in + 10.[[012]]) + _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' + ;; + 10.*) + _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-undefined ${wl}dynamic_lookup' + ;; + esac + fi + ;; + esac + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_AC_TAGVAR(hardcode_direct, $1)=no + _LT_AC_TAGVAR(hardcode_automatic, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='' + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + + if test "$GXX" = yes ; then + lt_int_apple_cc_single_mod=no + output_verbose_link_cmd='echo' + if $CC -dumpspecs 2>&1 | $EGREP 'single_module' >/dev/null ; then + lt_int_apple_cc_single_mod=yes + fi + if test "X$lt_int_apple_cc_single_mod" = Xyes ; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -r -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring' + fi + _LT_AC_TAGVAR(module_cmds, $1)='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' + # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds + if test "X$lt_int_apple_cc_single_mod" = Xyes ; then + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + else + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -r -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + fi + _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + else + case $cc_basename in + xlc*) + output_verbose_link_cmd='echo' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj ${wl}-single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $verstring' + _LT_AC_TAGVAR(module_cmds, $1)='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' + # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj ${wl}-single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + ;; + *) + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + fi + ;; + + dgux*) + case $cc_basename in + ec++*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + ghcx*) + # Green Hills C++ Compiler + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + freebsd[[12]]*) + # C++ shared libraries reported to be fairly broken before switch to ELF + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + freebsd-elf*) + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + ;; + freebsd* | kfreebsd*-gnu | dragonfly*) + # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF + # conventions + _LT_AC_TAGVAR(ld_shlibs, $1)=yes + ;; + gnu*) + ;; + hpux9*) + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, + # but as the default + # location of the library. + + case $cc_basename in + CC*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + aCC*) + _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$CC -b ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | grep "[[-]]L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + ;; + *) + if test "$GXX" = yes; then + _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$CC -shared -nostdlib -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + else + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + hpux10*|hpux11*) + if test $with_gnu_ld = no; then + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + case $host_cpu in + hppa*64*|ia64*) + _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='+b $libdir' + ;; + *) + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + ;; + esac + fi + case $host_cpu in + hppa*64*|ia64*) + _LT_AC_TAGVAR(hardcode_direct, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + *) + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, + # but as the default + # location of the library. + ;; + esac + + case $cc_basename in + CC*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + aCC*) + case $host_cpu in + hppa*64*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + ia64*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + *) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + esac + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | grep "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + ;; + *) + if test "$GXX" = yes; then + if test $with_gnu_ld = no; then + case $host_cpu in + hppa*64*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + ia64*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + *) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + esac + fi + else + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + interix3*) + _LT_AC_TAGVAR(hardcode_direct, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + irix5* | irix6*) + case $cc_basename in + CC*) + # SGI C++ + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + + # Archives containing C++ object files must be created using + # "CC -ar", where "CC" is the IRIX C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs' + ;; + *) + if test "$GXX" = yes; then + if test "$with_gnu_ld" = no; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` -o $lib' + fi + fi + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + ;; + esac + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + ;; + linux*) + case $cc_basename in + KCC*) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + _LT_AC_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib ${wl}-retain-symbols-file,$export_symbols; mv \$templib $lib' + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | grep "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath,$libdir' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + + # Archives containing C++ object files must be created using + # "CC -Bstatic", where "CC" is the KAI C++ compiler. + _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' + ;; + icpc*) + # Intel C++ + with_gnu_ld=yes + # version 8.0 and above of icpc choke on multiply defined symbols + # if we add $predep_objects and $postdep_objects, however 7.1 and + # earlier do not add the objects themselves. + case `$CC -V 2>&1` in + *"Version 7."*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + ;; + *) # Version 8.0 or newer + tmp_idyn= + case $host_cpu in + ia64*) tmp_idyn=' -i_dynamic';; + esac + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + ;; + esac + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive' + ;; + pgCC*) + # Portland Group C++ compiler + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' + ;; + cxx*) + # Compaq C++ + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib ${wl}-retain-symbols-file $wl$export_symbols' + + runpath_var=LD_RUN_PATH + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + ;; + esac + ;; + lynxos*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + m88k*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + mvs*) + case $cc_basename in + cxx*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + netbsd*) + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags' + wlarc= + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + fi + # Workaround some broken pre-1.5 toolchains + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"' + ;; + openbsd2*) + # C++ shared libraries are fairly broken + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + openbsd*) + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file,$export_symbols -o $lib' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + fi + output_verbose_link_cmd='echo' + ;; + osf3*) + case $cc_basename in + KCC*) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + _LT_AC_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + # Archives containing C++ object files must be created using + # "CC -Bstatic", where "CC" is the KAI C++ compiler. + _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' + + ;; + RCC*) + # Rational C++ 2.4.1 + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + cxx*) + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && echo ${wl}-set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld" | grep -v "ld:"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + ;; + *) + if test "$GXX" = yes && test "$with_gnu_ld" = no; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"' + + else + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + osf4* | osf5*) + case $cc_basename in + KCC*) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + _LT_AC_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + # Archives containing C++ object files must be created using + # the KAI C++ compiler. + _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs' + ;; + RCC*) + # Rational C++ 2.4.1 + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + cxx*) + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ + echo "-hidden">> $lib.exp~ + $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname -Wl,-input -Wl,$lib.exp `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib~ + $rm $lib.exp' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld" | grep -v "ld:"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + ;; + *) + if test "$GXX" = yes && test "$with_gnu_ld" = no; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"' + + else + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + psos*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + sunos4*) + case $cc_basename in + CC*) + # Sun C++ 4.x + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + lcc*) + # Lucid + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + solaris*) + case $cc_basename in + CC*) + # Sun C++ 4.2, 5.x and Centerline C++ + _LT_AC_TAGVAR(archive_cmds_need_lc,$1)=yes + _LT_AC_TAGVAR(no_undefined_flag, $1)=' -zdefs' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $CC -G${allow_undefined_flag} ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + case $host_os in + solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; + *) + # The C++ compiler is used as linker so we must use $wl + # flag to pass the commands to the underlying system + # linker. We must also pass each convience library through + # to the system linker between allextract/defaultextract. + # The C++ compiler will combine linker options so we + # cannot just pass the convience library names through + # without $wl. + # Supported since Solaris 2.6 (maybe 2.5.1?) + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}-z ${wl}defaultextract' + ;; + esac + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + + output_verbose_link_cmd='echo' + + # Archives containing C++ object files must be created using + # "CC -xar", where "CC" is the Sun C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' + ;; + gcx*) + # Green Hills C++ Compiler + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' + + # The C++ compiler must be used to create the archive. + _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs' + ;; + *) + # GNU C++ compiler with Solaris linker + if test "$GXX" = yes && test "$with_gnu_ld" = no; then + _LT_AC_TAGVAR(no_undefined_flag, $1)=' ${wl}-z ${wl}defs' + if $CC --version | grep -v '^2\.7' > /dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $CC -shared -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp' + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd="$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep \"\-L\"" + else + # g++ 2.7 appears to require `-G' NOT `-shared' on this + # platform. + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $CC -G -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp' + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd="$CC -G $CFLAGS -v conftest.$objext 2>&1 | grep \"\-L\"" + fi + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $wl$libdir' + fi + ;; + esac + ;; + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) + _LT_AC_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var='LD_RUN_PATH' + + case $cc_basename in + CC*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + sysv5* | sco3.2v5* | sco5v6*) + # Note: We can NOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + # For security reasons, it is highly recommended that you always + # use absolute paths for naming shared libraries, and exclude the + # DT_RUNPATH tag from executables and libraries. But doing so + # requires that you compile everything twice, which is a pain. + # So that behaviour is only enabled if SCOABSPATH is set to a + # non-empty value in the environment. Most likely only useful for + # creating official distributions of packages. + # This is a hack until libtool officially supports absolute path + # names for shared libraries. + _LT_AC_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' + _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs' + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport' + runpath_var='LD_RUN_PATH' + + case $cc_basename in + CC*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + tandem*) + case $cc_basename in + NCC*) + # NonStop-UX NCC 3.20 + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + vxworks*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; +esac +AC_MSG_RESULT([$_LT_AC_TAGVAR(ld_shlibs, $1)]) +test "$_LT_AC_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no + +_LT_AC_TAGVAR(GCC, $1)="$GXX" +_LT_AC_TAGVAR(LD, $1)="$LD" + +## CAVEAT EMPTOR: +## There is no encapsulation within the following macros, do not change +## the running order or otherwise move them around unless you know exactly +## what you are doing... +AC_LIBTOOL_POSTDEP_PREDEP($1) +AC_LIBTOOL_PROG_COMPILER_PIC($1) +AC_LIBTOOL_PROG_CC_C_O($1) +AC_LIBTOOL_SYS_HARD_LINK_LOCKS($1) +AC_LIBTOOL_PROG_LD_SHLIBS($1) +AC_LIBTOOL_SYS_DYNAMIC_LINKER($1) +AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH($1) + +AC_LIBTOOL_CONFIG($1) + +AC_LANG_POP +CC=$lt_save_CC +LDCXX=$LD +LD=$lt_save_LD +GCC=$lt_save_GCC +with_gnu_ldcxx=$with_gnu_ld +with_gnu_ld=$lt_save_with_gnu_ld +lt_cv_path_LDCXX=$lt_cv_path_LD +lt_cv_path_LD=$lt_save_path_LD +lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld +lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld +])# AC_LIBTOOL_LANG_CXX_CONFIG + +# AC_LIBTOOL_POSTDEP_PREDEP([TAGNAME]) +# ------------------------------------ +# Figure out "hidden" library dependencies from verbose +# compiler output when linking a shared library. +# Parse the compiler output and extract the necessary +# objects, libraries and library flags. +AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP],[ +dnl we can't use the lt_simple_compile_test_code here, +dnl because it contains code intended for an executable, +dnl not a library. It's possible we should let each +dnl tag define a new lt_????_link_test_code variable, +dnl but it's only used here... +ifelse([$1],[],[cat > conftest.$ac_ext < conftest.$ac_ext < conftest.$ac_ext < conftest.$ac_ext <> "$cfgfile" +ifelse([$1], [], +[#! $SHELL + +# `$echo "$cfgfile" | sed 's%^.*/%%'` - Provide generalized library-building support services. +# Generated automatically by $PROGRAM (GNU $PACKAGE $VERSION$TIMESTAMP) +# NOTE: Changes made to this file will be lost: look at ltmain.sh. +# +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001 +# Free Software Foundation, Inc. +# +# This file is part of GNU Libtool: +# Originally by Gordon Matzigkeit , 1996 +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# A sed program that does not truncate output. +SED=$lt_SED + +# Sed that helps us avoid accidentally triggering echo(1) options like -n. +Xsed="$SED -e 1s/^X//" + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +# The names of the tagged configurations supported by this script. +available_tags= + +# ### BEGIN LIBTOOL CONFIG], +[# ### BEGIN LIBTOOL TAG CONFIG: $tagname]) + +# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: + +# Shell to use when invoking shell scripts. +SHELL=$lt_SHELL + +# Whether or not to build shared libraries. +build_libtool_libs=$enable_shared + +# Whether or not to build static libraries. +build_old_libs=$enable_static + +# Whether or not to add -lc for building shared libraries. +build_libtool_need_lc=$_LT_AC_TAGVAR(archive_cmds_need_lc, $1) + +# Whether or not to disallow shared libs when runtime libs are static +allow_libtool_libs_with_static_runtimes=$_LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1) + +# Whether or not to optimize for fast installation. +fast_install=$enable_fast_install + +# The host system. +host_alias=$host_alias +host=$host +host_os=$host_os + +# The build system. +build_alias=$build_alias +build=$build +build_os=$build_os + +# An echo program that does not interpret backslashes. +echo=$lt_echo + +# The archiver. +AR=$lt_AR +AR_FLAGS=$lt_AR_FLAGS + +# A C compiler. +LTCC=$lt_LTCC + +# LTCC compiler flags. +LTCFLAGS=$lt_LTCFLAGS + +# A language-specific compiler. +CC=$lt_[]_LT_AC_TAGVAR(compiler, $1) + +# Is the compiler the GNU C compiler? +with_gcc=$_LT_AC_TAGVAR(GCC, $1) + +# An ERE matcher. +EGREP=$lt_EGREP + +# The linker used to build libraries. +LD=$lt_[]_LT_AC_TAGVAR(LD, $1) + +# Whether we need hard or soft links. +LN_S=$lt_LN_S + +# A BSD-compatible nm program. +NM=$lt_NM + +# A symbol stripping program +STRIP=$lt_STRIP + +# Used to examine libraries when file_magic_cmd begins "file" +MAGIC_CMD=$MAGIC_CMD + +# Used on cygwin: DLL creation program. +DLLTOOL="$DLLTOOL" + +# Used on cygwin: object dumper. +OBJDUMP="$OBJDUMP" + +# Used on cygwin: assembler. +AS="$AS" + +# The name of the directory that contains temporary libtool files. +objdir=$objdir + +# How to create reloadable object files. +reload_flag=$lt_reload_flag +reload_cmds=$lt_reload_cmds + +# How to pass a linker flag through the compiler. +wl=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_wl, $1) + +# Object file suffix (normally "o"). +objext="$ac_objext" + +# Old archive suffix (normally "a"). +libext="$libext" + +# Shared library suffix (normally ".so"). +shrext_cmds='$shrext_cmds' + +# Executable file suffix (normally ""). +exeext="$exeext" + +# Additional compiler flags for building library objects. +pic_flag=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_pic, $1) +pic_mode=$pic_mode + +# What is the maximum length of a command? +max_cmd_len=$lt_cv_sys_max_cmd_len + +# Does compiler simultaneously support -c and -o options? +compiler_c_o=$lt_[]_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1) + +# Must we lock files when doing compilation? +need_locks=$lt_need_locks + +# Do we need the lib prefix for modules? +need_lib_prefix=$need_lib_prefix + +# Do we need a version for libraries? +need_version=$need_version + +# Whether dlopen is supported. +dlopen_support=$enable_dlopen + +# Whether dlopen of programs is supported. +dlopen_self=$enable_dlopen_self + +# Whether dlopen of statically linked programs is supported. +dlopen_self_static=$enable_dlopen_self_static + +# Compiler flag to prevent dynamic linking. +link_static_flag=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_static, $1) + +# Compiler flag to turn off builtin functions. +no_builtin_flag=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) + +# Compiler flag to allow reflexive dlopens. +export_dynamic_flag_spec=$lt_[]_LT_AC_TAGVAR(export_dynamic_flag_spec, $1) + +# Compiler flag to generate shared objects directly from archives. +whole_archive_flag_spec=$lt_[]_LT_AC_TAGVAR(whole_archive_flag_spec, $1) + +# Compiler flag to generate thread-safe objects. +thread_safe_flag_spec=$lt_[]_LT_AC_TAGVAR(thread_safe_flag_spec, $1) + +# Library versioning type. +version_type=$version_type + +# Format of library name prefix. +libname_spec=$lt_libname_spec + +# List of archive names. First name is the real one, the rest are links. +# The last name is the one that the linker finds with -lNAME. +library_names_spec=$lt_library_names_spec + +# The coded name of the library, if different from the real name. +soname_spec=$lt_soname_spec + +# Commands used to build and install an old-style archive. +RANLIB=$lt_RANLIB +old_archive_cmds=$lt_[]_LT_AC_TAGVAR(old_archive_cmds, $1) +old_postinstall_cmds=$lt_old_postinstall_cmds +old_postuninstall_cmds=$lt_old_postuninstall_cmds + +# Create an old-style archive from a shared archive. +old_archive_from_new_cmds=$lt_[]_LT_AC_TAGVAR(old_archive_from_new_cmds, $1) + +# Create a temporary old-style archive to link instead of a shared archive. +old_archive_from_expsyms_cmds=$lt_[]_LT_AC_TAGVAR(old_archive_from_expsyms_cmds, $1) + +# Commands used to build and install a shared archive. +archive_cmds=$lt_[]_LT_AC_TAGVAR(archive_cmds, $1) +archive_expsym_cmds=$lt_[]_LT_AC_TAGVAR(archive_expsym_cmds, $1) +postinstall_cmds=$lt_postinstall_cmds +postuninstall_cmds=$lt_postuninstall_cmds + +# Commands used to build a loadable module (assumed same as above if empty) +module_cmds=$lt_[]_LT_AC_TAGVAR(module_cmds, $1) +module_expsym_cmds=$lt_[]_LT_AC_TAGVAR(module_expsym_cmds, $1) + +# Commands to strip libraries. +old_striplib=$lt_old_striplib +striplib=$lt_striplib + +# Dependencies to place before the objects being linked to create a +# shared library. +predep_objects=$lt_[]_LT_AC_TAGVAR(predep_objects, $1) + +# Dependencies to place after the objects being linked to create a +# shared library. +postdep_objects=$lt_[]_LT_AC_TAGVAR(postdep_objects, $1) + +# Dependencies to place before the objects being linked to create a +# shared library. +predeps=$lt_[]_LT_AC_TAGVAR(predeps, $1) + +# Dependencies to place after the objects being linked to create a +# shared library. +postdeps=$lt_[]_LT_AC_TAGVAR(postdeps, $1) + +# The library search path used internally by the compiler when linking +# a shared library. +compiler_lib_search_path=$lt_[]_LT_AC_TAGVAR(compiler_lib_search_path, $1) + +# Method to check whether dependent libraries are shared objects. +deplibs_check_method=$lt_deplibs_check_method + +# Command to use when deplibs_check_method == file_magic. +file_magic_cmd=$lt_file_magic_cmd + +# Flag that allows shared libraries with undefined symbols to be built. +allow_undefined_flag=$lt_[]_LT_AC_TAGVAR(allow_undefined_flag, $1) + +# Flag that forces no undefined symbols. +no_undefined_flag=$lt_[]_LT_AC_TAGVAR(no_undefined_flag, $1) + +# Commands used to finish a libtool library installation in a directory. +finish_cmds=$lt_finish_cmds + +# Same as above, but a single script fragment to be evaled but not shown. +finish_eval=$lt_finish_eval + +# Take the output of nm and produce a listing of raw symbols and C names. +global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe + +# Transform the output of nm in a proper C declaration +global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl + +# Transform the output of nm in a C name address pair +global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address + +# This is the shared library runtime path variable. +runpath_var=$runpath_var + +# This is the shared library path variable. +shlibpath_var=$shlibpath_var + +# Is shlibpath searched before the hard-coded library search path? +shlibpath_overrides_runpath=$shlibpath_overrides_runpath + +# How to hardcode a shared library path into an executable. +hardcode_action=$_LT_AC_TAGVAR(hardcode_action, $1) + +# Whether we should hardcode library paths into libraries. +hardcode_into_libs=$hardcode_into_libs + +# Flag to hardcode \$libdir into a binary during linking. +# This must work even if \$libdir does not exist. +hardcode_libdir_flag_spec=$lt_[]_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1) + +# If ld is used when linking, flag to hardcode \$libdir into +# a binary during linking. This must work even if \$libdir does +# not exist. +hardcode_libdir_flag_spec_ld=$lt_[]_LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1) + +# Whether we need a single -rpath flag with a separated argument. +hardcode_libdir_separator=$lt_[]_LT_AC_TAGVAR(hardcode_libdir_separator, $1) + +# Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the +# resulting binary. +hardcode_direct=$_LT_AC_TAGVAR(hardcode_direct, $1) + +# Set to yes if using the -LDIR flag during linking hardcodes DIR into the +# resulting binary. +hardcode_minus_L=$_LT_AC_TAGVAR(hardcode_minus_L, $1) + +# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into +# the resulting binary. +hardcode_shlibpath_var=$_LT_AC_TAGVAR(hardcode_shlibpath_var, $1) + +# Set to yes if building a shared library automatically hardcodes DIR into the library +# and all subsequent libraries and executables linked against it. +hardcode_automatic=$_LT_AC_TAGVAR(hardcode_automatic, $1) + +# Variables whose values should be saved in libtool wrapper scripts and +# restored at relink time. +variables_saved_for_relink="$variables_saved_for_relink" + +# Whether libtool must link a program against all its dependency libraries. +link_all_deplibs=$_LT_AC_TAGVAR(link_all_deplibs, $1) + +# Compile-time system search path for libraries +sys_lib_search_path_spec=$lt_sys_lib_search_path_spec + +# Run-time system search path for libraries +sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec + +# Fix the shell variable \$srcfile for the compiler. +fix_srcfile_path="$_LT_AC_TAGVAR(fix_srcfile_path, $1)" + +# Set to yes if exported symbols are required. +always_export_symbols=$_LT_AC_TAGVAR(always_export_symbols, $1) + +# The commands to list exported symbols. +export_symbols_cmds=$lt_[]_LT_AC_TAGVAR(export_symbols_cmds, $1) + +# The commands to extract the exported symbol list from a shared archive. +extract_expsyms_cmds=$lt_extract_expsyms_cmds + +# Symbols that should not be listed in the preloaded symbols. +exclude_expsyms=$lt_[]_LT_AC_TAGVAR(exclude_expsyms, $1) + +# Symbols that must always be exported. +include_expsyms=$lt_[]_LT_AC_TAGVAR(include_expsyms, $1) + +ifelse([$1],[], +[# ### END LIBTOOL CONFIG], +[# ### END LIBTOOL TAG CONFIG: $tagname]) + +__EOF__ + +ifelse([$1],[], [ + case $host_os in + aix3*) + cat <<\EOF >> "$cfgfile" + +# AIX sometimes has problems with the GCC collect2 program. For some +# reason, if we set the COLLECT_NAMES environment variable, the problems +# vanish in a puff of smoke. +if test "X${COLLECT_NAMES+set}" != Xset; then + COLLECT_NAMES= + export COLLECT_NAMES +fi +EOF + ;; + esac + + # We use sed instead of cat because bash on DJGPP gets confused if + # if finds mixed CR/LF and LF-only lines. Since sed operates in + # text mode, it properly converts lines to CR/LF. This bash problem + # is reportedly fixed, but why not run on old versions too? + sed '$q' "$ltmain" >> "$cfgfile" || (rm -f "$cfgfile"; exit 1) + + mv -f "$cfgfile" "$ofile" || \ + (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") + chmod +x "$ofile" +]) +else + # If there is no Makefile yet, we rely on a make rule to execute + # `config.status --recheck' to rerun these tests and create the + # libtool script then. + ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'` + if test -f "$ltmain_in"; then + test -f Makefile && make "$ltmain" + fi +fi +])# AC_LIBTOOL_CONFIG + + +# AC_LIBTOOL_PROG_COMPILER_NO_RTTI([TAGNAME]) +# ------------------------------------------- +AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], +[AC_REQUIRE([_LT_AC_SYS_COMPILER])dnl + +_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= + +if test "$GCC" = yes; then + _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' + + AC_LIBTOOL_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions], + lt_cv_prog_compiler_rtti_exceptions, + [-fno-rtti -fno-exceptions], [], + [_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)="$_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) -fno-rtti -fno-exceptions"]) +fi +])# AC_LIBTOOL_PROG_COMPILER_NO_RTTI + + +# AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE +# --------------------------------- +AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], +[AC_REQUIRE([AC_CANONICAL_HOST]) +AC_REQUIRE([AC_PROG_NM]) +AC_REQUIRE([AC_OBJEXT]) +# Check for command to grab the raw symbol name followed by C symbol from nm. +AC_MSG_CHECKING([command to parse $NM output from $compiler object]) +AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe], +[ +# These are sane defaults that work on at least a few old systems. +# [They come from Ultrix. What could be older than Ultrix?!! ;)] + +# Character class describing NM global symbol codes. +symcode='[[BCDEGRST]]' + +# Regexp to match symbols that can be accessed directly from C. +sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)' + +# Transform an extracted symbol line into a proper C declaration +lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^. .* \(.*\)$/extern int \1;/p'" + +# Transform an extracted symbol line into symbol name and symbol address +lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" + +# Define system-specific variables. +case $host_os in +aix*) + symcode='[[BCDT]]' + ;; +cygwin* | mingw* | pw32*) + symcode='[[ABCDGISTW]]' + ;; +hpux*) # Its linker distinguishes data from code symbols + if test "$host_cpu" = ia64; then + symcode='[[ABCDEGRST]]' + fi + lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" + lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" + ;; +linux*) + if test "$host_cpu" = ia64; then + symcode='[[ABCDGIRSTW]]' + lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" + lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" + fi + ;; +irix* | nonstopux*) + symcode='[[BCDEGRST]]' + ;; +osf*) + symcode='[[BCDEGQRST]]' + ;; +solaris*) + symcode='[[BDRT]]' + ;; +sco3.2v5*) + symcode='[[DT]]' + ;; +sysv4.2uw2*) + symcode='[[DT]]' + ;; +sysv5* | sco5v6* | unixware* | OpenUNIX*) + symcode='[[ABDT]]' + ;; +sysv4) + symcode='[[DFNSTU]]' + ;; +esac + +# Handle CRLF in mingw tool chain +opt_cr= +case $build_os in +mingw*) + opt_cr=`echo 'x\{0,1\}' | tr x '\015'` # option cr in regexp + ;; +esac + +# If we're using GNU nm, then use its standard symbol codes. +case `$NM -V 2>&1` in +*GNU* | *'with BFD'*) + symcode='[[ABCDGIRSTW]]' ;; +esac + +# Try without a prefix undercore, then with it. +for ac_symprfx in "" "_"; do + + # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. + symxfrm="\\1 $ac_symprfx\\2 \\2" + + # Write the raw and C identifiers. + lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[ ]]\($symcode$symcode*\)[[ ]][[ ]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" + + # Check to see that the pipe works correctly. + pipe_works=no + + rm -f conftest* + cat > conftest.$ac_ext < $nlist) && test -s "$nlist"; then + # Try sorting and uniquifying the output. + if sort "$nlist" | uniq > "$nlist"T; then + mv -f "$nlist"T "$nlist" + else + rm -f "$nlist"T + fi + + # Make sure that we snagged all the symbols we need. + if grep ' nm_test_var$' "$nlist" >/dev/null; then + if grep ' nm_test_func$' "$nlist" >/dev/null; then + cat < conftest.$ac_ext +#ifdef __cplusplus +extern "C" { +#endif + +EOF + # Now generate the symbol file. + eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | grep -v main >> conftest.$ac_ext' + + cat <> conftest.$ac_ext +#if defined (__STDC__) && __STDC__ +# define lt_ptr_t void * +#else +# define lt_ptr_t char * +# define const +#endif + +/* The mapping between symbol names and symbols. */ +const struct { + const char *name; + lt_ptr_t address; +} +lt_preloaded_symbols[[]] = +{ +EOF + $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (lt_ptr_t) \&\2},/" < "$nlist" | grep -v main >> conftest.$ac_ext + cat <<\EOF >> conftest.$ac_ext + {0, (lt_ptr_t) 0} +}; + +#ifdef __cplusplus +} +#endif +EOF + # Now try linking the two files. + mv conftest.$ac_objext conftstm.$ac_objext + lt_save_LIBS="$LIBS" + lt_save_CFLAGS="$CFLAGS" + LIBS="conftstm.$ac_objext" + CFLAGS="$CFLAGS$_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)" + if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext}; then + pipe_works=yes + fi + LIBS="$lt_save_LIBS" + CFLAGS="$lt_save_CFLAGS" + else + echo "cannot find nm_test_func in $nlist" >&AS_MESSAGE_LOG_FD + fi + else + echo "cannot find nm_test_var in $nlist" >&AS_MESSAGE_LOG_FD + fi + else + echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD + fi + else + echo "$progname: failed program was:" >&AS_MESSAGE_LOG_FD + cat conftest.$ac_ext >&5 + fi + rm -f conftest* conftst* + + # Do not use the global_symbol_pipe unless it works. + if test "$pipe_works" = yes; then + break + else + lt_cv_sys_global_symbol_pipe= + fi +done +]) +if test -z "$lt_cv_sys_global_symbol_pipe"; then + lt_cv_sys_global_symbol_to_cdecl= +fi +if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then + AC_MSG_RESULT(failed) +else + AC_MSG_RESULT(ok) +fi +]) # AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE + + +# AC_LIBTOOL_PROG_COMPILER_PIC([TAGNAME]) +# --------------------------------------- +AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC], +[_LT_AC_TAGVAR(lt_prog_compiler_wl, $1)= +_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= +_LT_AC_TAGVAR(lt_prog_compiler_static, $1)= + +AC_MSG_CHECKING([for $compiler option to produce PIC]) + ifelse([$1],[CXX],[ + # C++ specific cases for pic, static, wl, etc. + if test "$GXX" = yes; then + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + ;; + amigaos*) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the `-m68020' flag to GCC prevents building anything better, + # like `-m68040'. + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' + ;; + beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + mingw* | os2* | pw32*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT' + ;; + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' + ;; + *djgpp*) + # DJGPP does not support shared libraries at all + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= + ;; + interix3*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + sysv4*MP*) + if test -d /usr/nec; then + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic + fi + ;; + hpux*) + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case $host_cpu in + hppa*64*|ia64*) + ;; + *) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + ;; + *) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + else + case $host_os in + aix4* | aix5*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + else + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' + fi + ;; + chorus*) + case $cc_basename in + cxch68*) + # Green Hills C++ Compiler + # _LT_AC_TAGVAR(lt_prog_compiler_static, $1)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a" + ;; + esac + ;; + darwin*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + case $cc_basename in + xlc*) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-qnocommon' + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + ;; + esac + ;; + dgux*) + case $cc_basename in + ec++*) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + ;; + ghcx*) + # Green Hills C++ Compiler + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + *) + ;; + esac + ;; + freebsd* | kfreebsd*-gnu | dragonfly*) + # FreeBSD uses GNU C++ + ;; + hpux9* | hpux10* | hpux11*) + case $cc_basename in + CC*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' + if test "$host_cpu" != ia64; then + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + fi + ;; + aCC*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + ;; + esac + ;; + *) + ;; + esac + ;; + interix*) + # This is c89, which is MS Visual C++ (no shared libs) + # Anyone wants to do a port? + ;; + irix5* | irix6* | nonstopux*) + case $cc_basename in + CC*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + # CC pic flag -KPIC is the default. + ;; + *) + ;; + esac + ;; + linux*) + case $cc_basename in + KCC*) + # KAI C++ Compiler + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + icpc* | ecpc*) + # Intel C++ + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + pgCC*) + # Portland Group C++ compiler. + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + cxx*) + # Compaq C++ + # Make sure the PIC flag is empty. It appears that all Alpha + # Linux and Compaq Tru64 Unix objects are PIC. + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + *) + ;; + esac + ;; + lynxos*) + ;; + m88k*) + ;; + mvs*) + case $cc_basename in + cxx*) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-W c,exportall' + ;; + *) + ;; + esac + ;; + netbsd*) + ;; + osf3* | osf4* | osf5*) + case $cc_basename in + KCC*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' + ;; + RCC*) + # Rational C++ 2.4.1 + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + cxx*) + # Digital/Compaq C++ + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # Make sure the PIC flag is empty. It appears that all Alpha + # Linux and Compaq Tru64 Unix objects are PIC. + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + *) + ;; + esac + ;; + psos*) + ;; + solaris*) + case $cc_basename in + CC*) + # Sun C++ 4.2, 5.x and Centerline C++ + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + ;; + gcx*) + # Green Hills C++ Compiler + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + ;; + *) + ;; + esac + ;; + sunos4*) + case $cc_basename in + CC*) + # Sun C++ 4.x + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + lcc*) + # Lucid + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + *) + ;; + esac + ;; + tandem*) + case $cc_basename in + NCC*) + # NonStop-UX NCC 3.20 + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + ;; + *) + ;; + esac + ;; + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + case $cc_basename in + CC*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + esac + ;; + vxworks*) + ;; + *) + _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + esac + fi +], +[ + if test "$GCC" = yes; then + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + ;; + + amigaos*) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the `-m68020' flag to GCC prevents building anything better, + # like `-m68040'. + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' + ;; + + beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + + mingw* | pw32* | os2*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT' + ;; + + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' + ;; + + interix3*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + + msdosdjgpp*) + # Just because we use GCC doesn't mean we suddenly get shared libraries + # on systems that don't support them. + _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + enable_shared=no + ;; + + sysv4*MP*) + if test -d /usr/nec; then + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic + fi + ;; + + hpux*) + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + ;; + + *) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + else + # PORTME Check for flag to pass linker flags through the system compiler. + case $host_os in + aix*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + else + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' + fi + ;; + darwin*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + case $cc_basename in + xlc*) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-qnocommon' + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + ;; + esac + ;; + + mingw* | pw32* | os2*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT' + ;; + + hpux9* | hpux10* | hpux11*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + ;; + esac + # Is there a better lt_prog_compiler_static that works with the bundled CC? + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' + ;; + + irix5* | irix6* | nonstopux*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # PIC (with -KPIC) is the default. + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + + newsos6) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + linux*) + case $cc_basename in + icc* | ecc*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + pgcc* | pgf77* | pgf90* | pgf95*) + # Portland Group compilers (*not* the Pentium gcc compiler, + # which looks to be a dead project) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + ccc*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # All Alpha code is PIC. + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + esac + ;; + + osf3* | osf4* | osf5*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # All OSF/1 code is PIC. + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + + solaris*) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + case $cc_basename in + f77* | f90* | f95*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ';; + *) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,';; + esac + ;; + + sunos4*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + sysv4 | sysv4.2uw2* | sysv4.3*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + sysv4*MP*) + if test -d /usr/nec ;then + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + ;; + + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + unicos*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + + uts4*) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + *) + _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + esac + fi +]) +AC_MSG_RESULT([$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)]) + +# +# Check to make sure the PIC flag actually works. +# +if test -n "$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)"; then + AC_LIBTOOL_COMPILER_OPTION([if $compiler PIC flag $_LT_AC_TAGVAR(lt_prog_compiler_pic, $1) works], + _LT_AC_TAGVAR(lt_prog_compiler_pic_works, $1), + [$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)ifelse([$1],[],[ -DPIC],[ifelse([$1],[CXX],[ -DPIC],[])])], [], + [case $_LT_AC_TAGVAR(lt_prog_compiler_pic, $1) in + "" | " "*) ;; + *) _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=" $_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)" ;; + esac], + [_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no]) +fi +case $host_os in + # For platforms which do not support PIC, -DPIC is meaningless: + *djgpp*) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= + ;; + *) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)ifelse([$1],[],[ -DPIC],[ifelse([$1],[CXX],[ -DPIC],[])])" + ;; +esac + +# +# Check to make sure the static flag actually works. +# +wl=$_LT_AC_TAGVAR(lt_prog_compiler_wl, $1) eval lt_tmp_static_flag=\"$_LT_AC_TAGVAR(lt_prog_compiler_static, $1)\" +AC_LIBTOOL_LINKER_OPTION([if $compiler static flag $lt_tmp_static_flag works], + _LT_AC_TAGVAR(lt_prog_compiler_static_works, $1), + $lt_tmp_static_flag, + [], + [_LT_AC_TAGVAR(lt_prog_compiler_static, $1)=]) +]) + + +# AC_LIBTOOL_PROG_LD_SHLIBS([TAGNAME]) +# ------------------------------------ +# See if the linker supports building shared libraries. +AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS], +[AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) +ifelse([$1],[CXX],[ + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + case $host_os in + aix4* | aix5*) + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to AIX nm, but means don't demangle with GNU nm + if $NM -V 2>&1 | grep 'GNU' > /dev/null; then + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols' + else + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols' + fi + ;; + pw32*) + _LT_AC_TAGVAR(export_symbols_cmds, $1)="$ltdll_cmds" + ;; + cygwin* | mingw*) + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]] /s/.* \([[^ ]]*\)/\1 DATA/;/^.* __nm__/s/^.* __nm__\([[^ ]]*\) [[^ ]]*/\1 DATA/;/^I /d;/^[[AITW]] /s/.* //'\'' | sort | uniq > $export_symbols' + ;; + *) + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + ;; + esac +],[ + runpath_var= + _LT_AC_TAGVAR(allow_undefined_flag, $1)= + _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=no + _LT_AC_TAGVAR(archive_cmds, $1)= + _LT_AC_TAGVAR(archive_expsym_cmds, $1)= + _LT_AC_TAGVAR(old_archive_From_new_cmds, $1)= + _LT_AC_TAGVAR(old_archive_from_expsyms_cmds, $1)= + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)= + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)= + _LT_AC_TAGVAR(thread_safe_flag_spec, $1)= + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)= + _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)= + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)= + _LT_AC_TAGVAR(hardcode_direct, $1)=no + _LT_AC_TAGVAR(hardcode_minus_L, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported + _LT_AC_TAGVAR(link_all_deplibs, $1)=unknown + _LT_AC_TAGVAR(hardcode_automatic, $1)=no + _LT_AC_TAGVAR(module_cmds, $1)= + _LT_AC_TAGVAR(module_expsym_cmds, $1)= + _LT_AC_TAGVAR(always_export_symbols, $1)=no + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + # include_expsyms should be a list of space-separated symbols to be *always* + # included in the symbol list + _LT_AC_TAGVAR(include_expsyms, $1)= + # exclude_expsyms can be an extended regexp of symbols to exclude + # it will be wrapped by ` (' and `)$', so one must not match beginning or + # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', + # as well as any symbol that contains `d'. + _LT_AC_TAGVAR(exclude_expsyms, $1)="_GLOBAL_OFFSET_TABLE_" + # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out + # platforms (ab)use it in PIC code, but their linkers get confused if + # the symbol is explicitly referenced. Since portable code cannot + # rely on this symbol name, it's probably fine to never include it in + # preloaded symbol tables. + extract_expsyms_cmds= + # Just being paranoid about ensuring that cc_basename is set. + _LT_CC_BASENAME([$compiler]) + case $host_os in + cygwin* | mingw* | pw32*) + # FIXME: the MSVC++ port hasn't been tested in a loooong time + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + if test "$GCC" != yes; then + with_gnu_ld=no + fi + ;; + interix*) + # we just hope/assume this is gcc and not c89 (= MSVC++) + with_gnu_ld=yes + ;; + openbsd*) + with_gnu_ld=no + ;; + esac + + _LT_AC_TAGVAR(ld_shlibs, $1)=yes + if test "$with_gnu_ld" = yes; then + # If archive_cmds runs LD, not CC, wlarc should be empty + wlarc='${wl}' + + # Set some defaults for GNU ld with shared library support. These + # are reset later if shared libraries are not supported. Putting them + # here allows them to be overridden if necessary. + runpath_var=LD_RUN_PATH + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + # ancient GNU ld didn't support --whole-archive et. al. + if $LD --help 2>&1 | grep 'no-whole-archive' > /dev/null; then + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + else + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)= + fi + supports_anon_versioning=no + case `$LD -v 2>/dev/null` in + *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11 + *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... + *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... + *\ 2.11.*) ;; # other 2.11 versions + *) supports_anon_versioning=yes ;; + esac + + # See if GNU ld supports shared libraries. + case $host_os in + aix3* | aix4* | aix5*) + # On AIX/PPC, the GNU linker is very broken + if test "$host_cpu" != ia64; then + _LT_AC_TAGVAR(ld_shlibs, $1)=no + cat <&2 + +*** Warning: the GNU linker, at least up to release 2.9.1, is reported +*** to be unable to reliably create shared libraries on AIX. +*** Therefore, libtool is disabling shared libraries support. If you +*** really care for shared libraries, you may want to modify your PATH +*** so that a non-GNU linker is found, and then restart. + +EOF + fi + ;; + + amigaos*) + _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + + # Samuel A. Falvo II reports + # that the semantics of dynamic libraries on AmigaOS, at least up + # to version 4, is to share data among multiple programs linked + # with the same dynamic library. Since this doesn't match the + # behavior of shared libraries on other platforms, we can't use + # them. + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + + beos*) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + cygwin* | mingw* | pw32*) + # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, + # as there is no search path for DLLs. + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_AC_TAGVAR(always_export_symbols, $1)=no + _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]] /s/.* \([[^ ]]*\)/\1 DATA/'\'' | $SED -e '\''/^[[AITW]] /s/.* //'\'' | sort | uniq > $export_symbols' + + if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file (1st line + # is EXPORTS), use it as is; otherwise, prepend... + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + interix3*) + _LT_AC_TAGVAR(hardcode_direct, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + + linux*) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + tmp_addflag= + case $cc_basename,$host_cpu in + pgcc*) # Portland Group C compiler + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' + tmp_addflag=' $pic_flag' + ;; + pgf77* | pgf90* | pgf95*) # Portland Group f77 and f90 compilers + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' + tmp_addflag=' $pic_flag -Mnomain' ;; + ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 + tmp_addflag=' -i_dynamic' ;; + efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 + tmp_addflag=' -i_dynamic -nofor_main' ;; + ifc* | ifort*) # Intel Fortran compiler + tmp_addflag=' -nofor_main' ;; + esac + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + + if test $supports_anon_versioning = yes; then + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + $echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' + fi + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' + wlarc= + else + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + fi + ;; + + solaris*) + if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then + _LT_AC_TAGVAR(ld_shlibs, $1)=no + cat <&2 + +*** Warning: The releases 2.8.* of the GNU linker cannot reliably +*** create shared libraries on Solaris systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.9.1 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +EOF + elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) + case `$LD -v 2>&1` in + *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.1[[0-5]].*) + _LT_AC_TAGVAR(ld_shlibs, $1)=no + cat <<_LT_EOF 1>&2 + +*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not +*** reliably create shared libraries on SCO systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.16.91.0.3 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + ;; + *) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='`test -z "$SCOABSPATH" && echo ${wl}-rpath,$libdir`' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname,-retain-symbols-file,$export_symbols -o $lib' + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + + sunos4*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' + wlarc= + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + *) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + + if test "$_LT_AC_TAGVAR(ld_shlibs, $1)" = no; then + runpath_var= + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)= + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)= + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)= + fi + else + # PORTME fill in a description of your system's linker (not GNU ld) + case $host_os in + aix3*) + _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_AC_TAGVAR(always_export_symbols, $1)=yes + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' + # Note: this linker hardcodes the directories in LIBPATH if there + # are no directories specified by -L. + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then + # Neither direct hardcoding nor static linking is supported with a + # broken collect2. + _LT_AC_TAGVAR(hardcode_direct, $1)=unsupported + fi + ;; + + aix4* | aix5*) + if test "$host_cpu" = ia64; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag="" + else + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to AIX nm, but means don't demangle with GNU nm + if $NM -V 2>&1 | grep 'GNU' > /dev/null; then + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols' + else + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols' + fi + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # need to do runtime linking. + case $host_os in aix4.[[23]]|aix4.[[23]].*|aix5*) + for ld_flag in $LDFLAGS; do + if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then + aix_use_runtimelinking=yes + break + fi + done + ;; + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + _LT_AC_TAGVAR(archive_cmds, $1)='' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + + if test "$GCC" = yes; then + case $host_os in aix4.[[012]]|aix4.[[012]].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`${CC} -print-prog-name=collect2` + if test -f "$collect2name" && \ + strings "$collect2name" | grep resolve_lib_name >/dev/null + then + # We have reworked collect2 + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + else + # We have old collect2 + _LT_AC_TAGVAR(hardcode_direct, $1)=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)= + fi + ;; + esac + shared_flag='-shared' + if test "$aix_use_runtimelinking" = yes; then + shared_flag="$shared_flag "'${wl}-G' + fi + else + # not using gcc + if test "$host_cpu" = ia64; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test "$aix_use_runtimelinking" = yes; then + shared_flag='${wl}-G' + else + shared_flag='${wl}-bM:SRE' + fi + fi + fi + + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to export. + _LT_AC_TAGVAR(always_export_symbols, $1)=yes + if test "$aix_use_runtimelinking" = yes; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + _LT_AC_TAGVAR(allow_undefined_flag, $1)='-berok' + # Determine the default libpath from the value encoded in an empty executable. + _LT_AC_SYS_LIBPATH_AIX + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" + _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" + else + if test "$host_cpu" = ia64; then + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib' + _LT_AC_TAGVAR(allow_undefined_flag, $1)="-z nodefs" + _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an empty executable. + _LT_AC_SYS_LIBPATH_AIX + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + _LT_AC_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok' + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok' + # Exported symbols can be pulled into shared objects from archives + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='$convenience' + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes + # This is similar to how AIX traditionally builds its shared libraries. + _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' + fi + fi + ;; + + amigaos*) + _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + # see comment about different semantics on the GNU ld section + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + + bsdi[[45]]*) + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic + ;; + + cygwin* | mingw* | pw32*) + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' + _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=".dll" + # FIXME: Setting linknames here is a bad hack. + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `echo "$deplibs" | $SED -e '\''s/ -lc$//'\''` -link -dll~linknames=' + # The linker will automatically build a .lib file if we build a DLL. + _LT_AC_TAGVAR(old_archive_From_new_cmds, $1)='true' + # FIXME: Should let the user specify the lib program. + _LT_AC_TAGVAR(old_archive_cmds, $1)='lib /OUT:$oldlib$oldobjs$old_deplibs' + _LT_AC_TAGVAR(fix_srcfile_path, $1)='`cygpath -w "$srcfile"`' + _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + ;; + + darwin* | rhapsody*) + case $host_os in + rhapsody* | darwin1.[[012]]) + _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-undefined ${wl}suppress' + ;; + *) # Darwin 1.3 on + if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' + else + case ${MACOSX_DEPLOYMENT_TARGET} in + 10.[[012]]) + _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' + ;; + 10.*) + _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-undefined ${wl}dynamic_lookup' + ;; + esac + fi + ;; + esac + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_AC_TAGVAR(hardcode_direct, $1)=no + _LT_AC_TAGVAR(hardcode_automatic, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='' + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + if test "$GCC" = yes ; then + output_verbose_link_cmd='echo' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring' + _LT_AC_TAGVAR(module_cmds, $1)='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' + # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + else + case $cc_basename in + xlc*) + output_verbose_link_cmd='echo' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $verstring' + _LT_AC_TAGVAR(module_cmds, $1)='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' + # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + ;; + *) + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + fi + ;; + + dgux*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + freebsd1*) + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + + # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor + # support. Future versions do this automatically, but an explicit c++rt0.o + # does not break anything, and helps significantly (at the cost of a little + # extra space). + freebsd2.2*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + # Unfortunately, older versions of FreeBSD 2 do not have this feature. + freebsd2*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + # FreeBSD 3 and greater uses gcc -shared to do shared libraries. + freebsd* | kfreebsd*-gnu | dragonfly*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + hpux9*) + if test "$GCC" = yes; then + _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + fi + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + ;; + + hpux10*) + if test "$GCC" = yes -a "$with_gnu_ld" = no; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' + fi + if test "$with_gnu_ld" = no; then + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + fi + ;; + + hpux11*) + if test "$GCC" = yes -a "$with_gnu_ld" = no; then + case $host_cpu in + hppa*64*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + else + case $host_cpu in + hppa*64*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + fi + if test "$with_gnu_ld" = no; then + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + case $host_cpu in + hppa*64*|ia64*) + _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='+b $libdir' + _LT_AC_TAGVAR(hardcode_direct, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + *) + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + ;; + esac + fi + ;; + + irix5* | irix6* | nonstopux*) + if test "$GCC" = yes; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='-rpath $libdir' + fi + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out + else + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF + fi + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + newsos6) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + openbsd*) + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + else + case $host_os in + openbsd[[01]].* | openbsd2.[[0-7]] | openbsd2.[[0-7]].*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + ;; + *) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + ;; + esac + fi + ;; + + os2*) + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_AC_TAGVAR(archive_cmds, $1)='$echo "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$echo DATA >> $output_objdir/$libname.def~$echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~$echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' + _LT_AC_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' + ;; + + osf3*) + if test "$GCC" = yes; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + fi + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + ;; + + osf4* | osf5*) # as osf3* with the addition of -msym flag + if test "$GCC" = yes; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + else + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; echo "-hidden">> $lib.exp~ + $LD -shared${allow_undefined_flag} -input $lib.exp $linker_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib~$rm $lib.exp' + + # Both c and cxx compiler support -rpath directly + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + fi + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + ;; + + solaris*) + _LT_AC_TAGVAR(no_undefined_flag, $1)=' -z text' + if test "$GCC" = yes; then + wlarc='${wl}' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $CC -shared ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$rm $lib.exp' + else + wlarc='' + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp' + fi + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + case $host_os in + solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; + *) + # The compiler driver will combine linker options so we + # cannot just pass the convience library names through + # without $wl, iff we do not link with $LD. + # Luckily, gcc supports the same syntax we need for Sun Studio. + # Supported since Solaris 2.6 (maybe 2.5.1?) + case $wlarc in + '') + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' ;; + *) + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}-z ${wl}defaultextract' ;; + esac ;; + esac + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + ;; + + sunos4*) + if test "x$host_vendor" = xsequent; then + # Use $CC to link under sequent, because it throws in some extra .o + # files that make .init and .fini sections work. + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' + fi + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + sysv4) + case $host_vendor in + sni) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes # is this really true??? + ;; + siemens) + ## LD is ld it makes a PLAMLIB + ## CC just makes a GrossModule. + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(reload_cmds, $1)='$CC -r -o $output$reload_objs' + _LT_AC_TAGVAR(hardcode_direct, $1)=no + ;; + motorola) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_direct, $1)=no #Motorola manual says yes, but my tests say they lie + ;; + esac + runpath_var='LD_RUN_PATH' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + sysv4.3*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='-Bexport' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var=LD_RUN_PATH + hardcode_runpath_var=yes + _LT_AC_TAGVAR(ld_shlibs, $1)=yes + fi + ;; + + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7*) + _LT_AC_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var='LD_RUN_PATH' + + if test "$GCC" = yes; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + sysv5* | sco3.2v5* | sco5v6*) + # Note: We can NOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + _LT_AC_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' + _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs' + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport' + runpath_var='LD_RUN_PATH' + + if test "$GCC" = yes; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + uts4*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + *) + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + fi +]) +AC_MSG_RESULT([$_LT_AC_TAGVAR(ld_shlibs, $1)]) +test "$_LT_AC_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no + +# +# Do we need to explicitly link libc? +# +case "x$_LT_AC_TAGVAR(archive_cmds_need_lc, $1)" in +x|xyes) + # Assume -lc should be added + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes + + if test "$enable_shared" = yes && test "$GCC" = yes; then + case $_LT_AC_TAGVAR(archive_cmds, $1) in + *'~'*) + # FIXME: we may have to deal with multi-command sequences. + ;; + '$CC '*) + # Test whether the compiler implicitly links with -lc since on some + # systems, -lgcc has to come before -lc. If gcc already passes -lc + # to ld, don't add -lc before -lgcc. + AC_MSG_CHECKING([whether -lc should be explicitly linked in]) + $rm conftest* + printf "$lt_simple_compile_test_code" > conftest.$ac_ext + + if AC_TRY_EVAL(ac_compile) 2>conftest.err; then + soname=conftest + lib=conftest + libobjs=conftest.$ac_objext + deplibs= + wl=$_LT_AC_TAGVAR(lt_prog_compiler_wl, $1) + pic_flag=$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1) + compiler_flags=-v + linker_flags=-v + verstring= + output_objdir=. + libname=conftest + lt_save_allow_undefined_flag=$_LT_AC_TAGVAR(allow_undefined_flag, $1) + _LT_AC_TAGVAR(allow_undefined_flag, $1)= + if AC_TRY_EVAL(_LT_AC_TAGVAR(archive_cmds, $1) 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1) + then + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + else + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes + fi + _LT_AC_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag + else + cat conftest.err 1>&5 + fi + $rm conftest* + AC_MSG_RESULT([$_LT_AC_TAGVAR(archive_cmds_need_lc, $1)]) + ;; + esac + fi + ;; +esac +])# AC_LIBTOOL_PROG_LD_SHLIBS + + +# _LT_AC_FILE_LTDLL_C +# ------------------- +# Be careful that the start marker always follows a newline. +AC_DEFUN([_LT_AC_FILE_LTDLL_C], [ +# /* ltdll.c starts here */ +# #define WIN32_LEAN_AND_MEAN +# #include +# #undef WIN32_LEAN_AND_MEAN +# #include +# +# #ifndef __CYGWIN__ +# # ifdef __CYGWIN32__ +# # define __CYGWIN__ __CYGWIN32__ +# # endif +# #endif +# +# #ifdef __cplusplus +# extern "C" { +# #endif +# BOOL APIENTRY DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved); +# #ifdef __cplusplus +# } +# #endif +# +# #ifdef __CYGWIN__ +# #include +# DECLARE_CYGWIN_DLL( DllMain ); +# #endif +# HINSTANCE __hDllInstance_base; +# +# BOOL APIENTRY +# DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved) +# { +# __hDllInstance_base = hInst; +# return TRUE; +# } +# /* ltdll.c ends here */ +])# _LT_AC_FILE_LTDLL_C + + +# _LT_AC_TAGVAR(VARNAME, [TAGNAME]) +# --------------------------------- +AC_DEFUN([_LT_AC_TAGVAR], [ifelse([$2], [], [$1], [$1_$2])]) + + +# old names +AC_DEFUN([AM_PROG_LIBTOOL], [AC_PROG_LIBTOOL]) +AC_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)]) +AC_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)]) +AC_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)]) +AC_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)]) +AC_DEFUN([AM_PROG_LD], [AC_PROG_LD]) +AC_DEFUN([AM_PROG_NM], [AC_PROG_NM]) + +# This is just to silence aclocal about the macro not being used +ifelse([AC_DISABLE_FAST_INSTALL]) + +AC_DEFUN([LT_AC_PROG_GCJ], +[AC_CHECK_TOOL(GCJ, gcj, no) + test "x${GCJFLAGS+set}" = xset || GCJFLAGS="-g -O2" + AC_SUBST(GCJFLAGS) +]) + +AC_DEFUN([LT_AC_PROG_RC], +[AC_CHECK_TOOL(RC, windres, no) +]) + +############################################################ +# NOTE: This macro has been submitted for inclusion into # +# GNU Autoconf as AC_PROG_SED. When it is available in # +# a released version of Autoconf we should remove this # +# macro and use it instead. # +############################################################ +# LT_AC_PROG_SED +# -------------- +# Check for a fully-functional sed program, that truncates +# as few characters as possible. Prefer GNU sed if found. +AC_DEFUN([LT_AC_PROG_SED], +[AC_MSG_CHECKING([for a sed that does not truncate output]) +AC_CACHE_VAL(lt_cv_path_SED, +[# Loop through the user's path and test for sed and gsed. +# Then use that list of sed's as ones to test for truncation. +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for lt_ac_prog in sed gsed; do + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then + lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext" + fi + done + done +done +lt_ac_max=0 +lt_ac_count=0 +# Add /usr/xpg4/bin/sed as it is typically found on Solaris +# along with /bin/sed that truncates output. +for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do + test ! -f $lt_ac_sed && continue + cat /dev/null > conftest.in + lt_ac_count=0 + echo $ECHO_N "0123456789$ECHO_C" >conftest.in + # Check for GNU sed and select it if it is found. + if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then + lt_cv_path_SED=$lt_ac_sed + break + fi + while true; do + cat conftest.in conftest.in >conftest.tmp + mv conftest.tmp conftest.in + cp conftest.in conftest.nl + echo >>conftest.nl + $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break + cmp -s conftest.out conftest.nl || break + # 10000 chars as input seems more than enough + test $lt_ac_count -gt 10 && break + lt_ac_count=`expr $lt_ac_count + 1` + if test $lt_ac_count -gt $lt_ac_max; then + lt_ac_max=$lt_ac_count + lt_cv_path_SED=$lt_ac_sed + fi + done +done +]) +SED=$lt_cv_path_SED +AC_MSG_RESULT([$SED]) +]) diff --git a/libclamav/c++/llvm/autoconf/m4/link_options.m4 b/libclamav/c++/llvm/autoconf/m4/link_options.m4 new file mode 100644 index 000000000..66036de43 --- /dev/null +++ b/libclamav/c++/llvm/autoconf/m4/link_options.m4 @@ -0,0 +1,41 @@ +# +# Determine if the system can handle the -R option being passed to the linker. +# +# This macro is specific to LLVM. +# +AC_DEFUN([AC_LINK_USE_R], +[AC_CACHE_CHECK([for compiler -Wl,-R option],[llvm_cv_link_use_r], +[ AC_LANG_PUSH([C]) + oldcflags="$CFLAGS" + CFLAGS="$CFLAGS -Wl,-R." + AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],[[int main() { return 0; }]])], + [llvm_cv_link_use_r=yes],[llvm_cv_link_use_r=no]) + CFLAGS="$oldcflags" + AC_LANG_POP([C]) +]) +if test "$llvm_cv_link_use_r" = yes ; then + AC_DEFINE([HAVE_LINK_R],[1],[Define if you can use -Wl,-R. to pass -R. to the linker, in order to add the current directory to the dynamic linker search path.]) + fi +]) + +# +# Determine if the system can handle the -R option being passed to the linker. +# +# This macro is specific to LLVM. +# +AC_DEFUN([AC_LINK_EXPORT_DYNAMIC], +[AC_CACHE_CHECK([for compiler -Wl,-export-dynamic option], + [llvm_cv_link_use_export_dynamic], +[ AC_LANG_PUSH([C]) + oldcflags="$CFLAGS" + CFLAGS="$CFLAGS -Wl,-export-dynamic" + AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],[[int main() { return 0; }]])], + [llvm_cv_link_use_export_dynamic=yes],[llvm_cv_link_use_export_dynamic=no]) + CFLAGS="$oldcflags" + AC_LANG_POP([C]) +]) +if test "$llvm_cv_link_use_export_dynamic" = yes ; then + AC_DEFINE([HAVE_LINK_EXPORT_DYNAMIC],[1],[Define if you can use -Wl,-export-dynamic.]) + fi +]) + diff --git a/libclamav/c++/llvm/autoconf/m4/linux_mixed_64_32.m4 b/libclamav/c++/llvm/autoconf/m4/linux_mixed_64_32.m4 new file mode 100644 index 000000000..123491f87 --- /dev/null +++ b/libclamav/c++/llvm/autoconf/m4/linux_mixed_64_32.m4 @@ -0,0 +1,17 @@ +# +# Some Linux machines run a 64-bit kernel with a 32-bit userspace. 'uname -m' +# shows these as x86_64. Ask the system 'gcc' what it thinks. +# +AC_DEFUN([AC_IS_LINUX_MIXED], +[AC_CACHE_CHECK(for 32-bit userspace on 64-bit system,llvm_cv_linux_mixed, +[ AC_LANG_PUSH([C]) + AC_COMPILE_IFELSE([AC_LANG_PROGRAM( + [[#ifndef __x86_64__ + error: Not x86-64 even if uname says so! + #endif + ]])], + [llvm_cv_linux_mixed=no], + [llvm_cv_linux_mixed=yes]) + AC_LANG_POP([C]) +]) +]) diff --git a/libclamav/c++/llvm/autoconf/m4/ltdl.m4 b/libclamav/c++/llvm/autoconf/m4/ltdl.m4 new file mode 100644 index 000000000..bc9e2ad24 --- /dev/null +++ b/libclamav/c++/llvm/autoconf/m4/ltdl.m4 @@ -0,0 +1,418 @@ +## ltdl.m4 - Configure ltdl for the target system. -*-Autoconf-*- +## Copyright (C) 1999-2000 Free Software Foundation, Inc. +## +## This file is free software; the Free Software Foundation gives +## unlimited permission to copy and/or distribute it, with or without +## modifications, as long as this notice is preserved. + +# serial 7 AC_LIB_LTDL + +# AC_WITH_LTDL +# ------------ +# Clients of libltdl can use this macro to allow the installer to +# choose between a shipped copy of the ltdl sources or a preinstalled +# version of the library. +AC_DEFUN([AC_WITH_LTDL], +[AC_REQUIRE([AC_LIB_LTDL]) +AC_SUBST([LIBLTDL]) +AC_SUBST([INCLTDL]) + +# Unless the user asks us to check, assume no installed ltdl exists. +use_installed_libltdl=no + +AC_ARG_WITH([included_ltdl], + [ --with-included-ltdl use the GNU ltdl sources included here]) + +if test "x$with_included_ltdl" != xyes; then + # We are not being forced to use the included libltdl sources, so + # decide whether there is a useful installed version we can use. + AC_CHECK_HEADER([ltdl.h], + [AC_CHECK_LIB([ltdl], [lt_dlcaller_register], + [with_included_ltdl=no], + [with_included_ltdl=yes]) + ]) +fi + +if test "x$enable_ltdl_install" != xyes; then + # If the user did not specify an installable libltdl, then default + # to a convenience lib. + AC_LIBLTDL_CONVENIENCE +fi + +if test "x$with_included_ltdl" = xno; then + # If the included ltdl is not to be used. then Use the + # preinstalled libltdl we found. + AC_DEFINE([HAVE_LTDL], [1], + [Define this if a modern libltdl is already installed]) + LIBLTDL=-lltdl +fi + +# Report our decision... +AC_MSG_CHECKING([whether to use included libltdl]) +AC_MSG_RESULT([$with_included_ltdl]) + +AC_CONFIG_SUBDIRS([libltdl]) +])# AC_WITH_LTDL + + +# AC_LIB_LTDL +# ----------- +# Perform all the checks necessary for compilation of the ltdl objects +# -- including compiler checks and header checks. +AC_DEFUN([AC_LIB_LTDL], +[AC_PREREQ(2.60) +AC_REQUIRE([AC_PROG_CC]) +AC_REQUIRE([AC_C_CONST]) +AC_REQUIRE([AC_HEADER_STDC]) +AC_REQUIRE([AC_HEADER_DIRENT]) +AC_REQUIRE([_LT_AC_CHECK_DLFCN]) +AC_REQUIRE([AC_LTDL_ENABLE_INSTALL]) +AC_REQUIRE([AC_LTDL_SHLIBEXT]) +AC_REQUIRE([AC_LTDL_SHLIBPATH]) +AC_REQUIRE([AC_LTDL_SYSSEARCHPATH]) +AC_REQUIRE([AC_LTDL_OBJDIR]) +AC_REQUIRE([AC_LTDL_DLPREOPEN]) +AC_REQUIRE([AC_LTDL_DLLIB]) +AC_REQUIRE([AC_LTDL_SYMBOL_USCORE]) +AC_REQUIRE([AC_LTDL_DLSYM_USCORE]) +AC_REQUIRE([AC_LTDL_SYS_DLOPEN_DEPLIBS]) +AC_REQUIRE([AC_LTDL_FUNC_ARGZ]) + +AC_CHECK_HEADERS([assert.h ctype.h errno.h malloc.h memory.h stdlib.h \ + stdio.h unistd.h]) +AC_CHECK_HEADERS([dl.h sys/dl.h dld.h mach-o/dyld.h]) +AC_CHECK_HEADERS([string.h strings.h], [break]) + +AC_CHECK_FUNCS([strchr index], [break]) +AC_CHECK_FUNCS([strrchr rindex], [break]) +AC_CHECK_FUNCS([memcpy bcopy], [break]) +AC_CHECK_FUNCS([memmove strcmp]) +AC_CHECK_FUNCS([closedir opendir readdir]) +])# AC_LIB_LTDL + + +# AC_LTDL_ENABLE_INSTALL +# ---------------------- +AC_DEFUN([AC_LTDL_ENABLE_INSTALL], +[AC_ARG_ENABLE([ltdl-install], + [AS_HELP_STRING([--enable-ltdl-install],[install libltdl])]) + +AM_CONDITIONAL(INSTALL_LTDL, test x"${enable_ltdl_install-no}" != xno) +AM_CONDITIONAL(CONVENIENCE_LTDL, test x"${enable_ltdl_convenience-no}" != xno) +])# AC_LTDL_ENABLE_INSTALL + + +# AC_LTDL_SYS_DLOPEN_DEPLIBS +# -------------------------- +AC_DEFUN([AC_LTDL_SYS_DLOPEN_DEPLIBS], +[AC_REQUIRE([AC_CANONICAL_HOST]) +AC_CACHE_CHECK([whether deplibs are loaded by dlopen], + [libltdl_cv_sys_dlopen_deplibs], + [# PORTME does your system automatically load deplibs for dlopen? + # or its logical equivalent (e.g. shl_load for HP-UX < 11) + # For now, we just catch OSes we know something about -- in the + # future, we'll try test this programmatically. + libltdl_cv_sys_dlopen_deplibs=unknown + case "$host_os" in + aix3*|aix4.1.*|aix4.2.*) + # Unknown whether this is true for these versions of AIX, but + # we want this `case' here to explicitly catch those versions. + libltdl_cv_sys_dlopen_deplibs=unknown + ;; + aix[[45]]*) + libltdl_cv_sys_dlopen_deplibs=yes + ;; + darwin*) + # Assuming the user has installed a libdl from somewhere, this is true + # If you are looking for one http://www.opendarwin.org/projects/dlcompat + libltdl_cv_sys_dlopen_deplibs=yes + ;; + gnu* | linux* | kfreebsd*-gnu | knetbsd*-gnu) + # GNU and its variants, using gnu ld.so (Glibc) + libltdl_cv_sys_dlopen_deplibs=yes + ;; + hpux10*|hpux11*) + libltdl_cv_sys_dlopen_deplibs=yes + ;; + interix*) + libltdl_cv_sys_dlopen_deplibs=yes + ;; + irix[[12345]]*|irix6.[[01]]*) + # Catch all versions of IRIX before 6.2, and indicate that we don't + # know how it worked for any of those versions. + libltdl_cv_sys_dlopen_deplibs=unknown + ;; + irix*) + # The case above catches anything before 6.2, and it's known that + # at 6.2 and later dlopen does load deplibs. + libltdl_cv_sys_dlopen_deplibs=yes + ;; + netbsd*) + libltdl_cv_sys_dlopen_deplibs=yes + ;; + openbsd*) + libltdl_cv_sys_dlopen_deplibs=yes + ;; + osf[[1234]]*) + # dlopen did load deplibs (at least at 4.x), but until the 5.x series, + # it did *not* use an RPATH in a shared library to find objects the + # library depends on, so we explictly say `no'. + libltdl_cv_sys_dlopen_deplibs=no + ;; + osf5.0|osf5.0a|osf5.1) + # dlopen *does* load deplibs and with the right loader patch applied + # it even uses RPATH in a shared library to search for shared objects + # that the library depends on, but there's no easy way to know if that + # patch is installed. Since this is the case, all we can really + # say is unknown -- it depends on the patch being installed. If + # it is, this changes to `yes'. Without it, it would be `no'. + libltdl_cv_sys_dlopen_deplibs=unknown + ;; + osf*) + # the two cases above should catch all versions of osf <= 5.1. Read + # the comments above for what we know about them. + # At > 5.1, deplibs are loaded *and* any RPATH in a shared library + # is used to find them so we can finally say `yes'. + libltdl_cv_sys_dlopen_deplibs=yes + ;; + solaris*) + libltdl_cv_sys_dlopen_deplibs=yes + ;; + sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + libltdl_cv_sys_dlopen_deplibs=yes + ;; + esac + ]) +if test "$libltdl_cv_sys_dlopen_deplibs" != yes; then + AC_DEFINE([LTDL_DLOPEN_DEPLIBS], [1], + [Define if the OS needs help to load dependent libraries for dlopen().]) +fi +])# AC_LTDL_SYS_DLOPEN_DEPLIBS + + +# AC_LTDL_SHLIBEXT +# ---------------- +AC_DEFUN([AC_LTDL_SHLIBEXT], +[AC_REQUIRE([AC_LIBTOOL_SYS_DYNAMIC_LINKER]) +AC_CACHE_CHECK([which extension is used for loadable modules], + [libltdl_cv_shlibext], +[ +module=yes +eval libltdl_cv_shlibext=$shrext_cmds + ]) +if test -n "$libltdl_cv_shlibext"; then + AC_DEFINE_UNQUOTED([LTDL_SHLIB_EXT], ["$libltdl_cv_shlibext"], + [Define to the extension used for shared libraries, say, ".so".]) +fi +])# AC_LTDL_SHLIBEXT + + +# AC_LTDL_SHLIBPATH +# ----------------- +AC_DEFUN([AC_LTDL_SHLIBPATH], +[AC_REQUIRE([AC_LIBTOOL_SYS_DYNAMIC_LINKER]) +AC_CACHE_CHECK([which variable specifies run-time library path], + [libltdl_cv_shlibpath_var], [libltdl_cv_shlibpath_var="$shlibpath_var"]) +if test -n "$libltdl_cv_shlibpath_var"; then + AC_DEFINE_UNQUOTED([LTDL_SHLIBPATH_VAR], ["$libltdl_cv_shlibpath_var"], + [Define to the name of the environment variable that determines the dynamic library search path.]) +fi +])# AC_LTDL_SHLIBPATH + + +# AC_LTDL_SYSSEARCHPATH +# --------------------- +AC_DEFUN([AC_LTDL_SYSSEARCHPATH], +[AC_REQUIRE([AC_LIBTOOL_SYS_DYNAMIC_LINKER]) +AC_CACHE_CHECK([for the default library search path], + [libltdl_cv_sys_search_path], + [libltdl_cv_sys_search_path="$sys_lib_dlsearch_path_spec"]) +if test -n "$libltdl_cv_sys_search_path"; then + sys_search_path= + for dir in $libltdl_cv_sys_search_path; do + if test -z "$sys_search_path"; then + sys_search_path="$dir" + else + sys_search_path="$sys_search_path$PATH_SEPARATOR$dir" + fi + done + AC_DEFINE_UNQUOTED([LTDL_SYSSEARCHPATH], ["$sys_search_path"], + [Define to the system default library search path.]) +fi +])# AC_LTDL_SYSSEARCHPATH + + +# AC_LTDL_OBJDIR +# -------------- +AC_DEFUN([AC_LTDL_OBJDIR], +[AC_CACHE_CHECK([for objdir], + [libltdl_cv_objdir], + [libltdl_cv_objdir="$objdir" + if test -n "$objdir"; then + : + else + rm -f .libs 2>/dev/null + mkdir .libs 2>/dev/null + if test -d .libs; then + libltdl_cv_objdir=.libs + else + # MS-DOS does not allow filenames that begin with a dot. + libltdl_cv_objdir=_libs + fi + rmdir .libs 2>/dev/null + fi + ]) +AC_DEFINE_UNQUOTED([LTDL_OBJDIR], ["$libltdl_cv_objdir/"], + [Define to the sub-directory in which libtool stores uninstalled libraries.]) +])# AC_LTDL_OBJDIR + + +# AC_LTDL_DLPREOPEN +# ----------------- +AC_DEFUN([AC_LTDL_DLPREOPEN], +[AC_REQUIRE([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE]) +AC_CACHE_CHECK([whether libtool supports -dlopen/-dlpreopen], + [libltdl_cv_preloaded_symbols], + [if test -n "$lt_cv_sys_global_symbol_pipe"; then + libltdl_cv_preloaded_symbols=yes + else + libltdl_cv_preloaded_symbols=no + fi + ]) +if test x"$libltdl_cv_preloaded_symbols" = xyes; then + AC_DEFINE([HAVE_PRELOADED_SYMBOLS], [1], + [Define if libtool can extract symbol lists from object files.]) +fi +])# AC_LTDL_DLPREOPEN + + +# AC_LTDL_DLLIB +# ------------- +AC_DEFUN([AC_LTDL_DLLIB], +[LIBADD_DL= +AC_SUBST(LIBADD_DL) +AC_LANG_PUSH([C]) + +AC_CHECK_FUNC([shl_load], + [AC_DEFINE([HAVE_SHL_LOAD], [1], + [Define if you have the shl_load function.])], + [AC_CHECK_LIB([dld], [shl_load], + [AC_DEFINE([HAVE_SHL_LOAD], [1], + [Define if you have the shl_load function.]) + LIBADD_DL="$LIBADD_DL -ldld"], + [AC_CHECK_LIB([dl], [dlopen], + [AC_DEFINE([HAVE_LIBDL], [1], + [Define if you have the libdl library or equivalent.]) + LIBADD_DL="-ldl" libltdl_cv_lib_dl_dlopen="yes"], + [AC_LINK_IFELSE([AC_LANG_PROGRAM([[#if HAVE_DLFCN_H +# include +#endif + ]], [[dlopen(0, 0);]])],[AC_DEFINE([HAVE_LIBDL], [1], + [Define if you have the libdl library or equivalent.]) libltdl_cv_func_dlopen="yes"],[AC_CHECK_LIB([svld], [dlopen], + [AC_DEFINE([HAVE_LIBDL], [1], + [Define if you have the libdl library or equivalent.]) + LIBADD_DL="-lsvld" libltdl_cv_func_dlopen="yes"], + [AC_CHECK_LIB([dld], [dld_link], + [AC_DEFINE([HAVE_DLD], [1], + [Define if you have the GNU dld library.]) + LIBADD_DL="$LIBADD_DL -ldld"], + [AC_CHECK_FUNC([_dyld_func_lookup], + [AC_DEFINE([HAVE_DYLD], [1], + [Define if you have the _dyld_func_lookup function.])]) + ]) + ]) + ]) + ]) + ]) +]) + +if test x"$libltdl_cv_func_dlopen" = xyes || test x"$libltdl_cv_lib_dl_dlopen" = xyes +then + lt_save_LIBS="$LIBS" + LIBS="$LIBS $LIBADD_DL" + AC_CHECK_FUNCS([dlerror]) + LIBS="$lt_save_LIBS" +fi +AC_LANG_POP +])# AC_LTDL_DLLIB + + +# AC_LTDL_SYMBOL_USCORE +# --------------------- +# does the compiler prefix global symbols with an underscore? +AC_DEFUN([AC_LTDL_SYMBOL_USCORE], +[AC_REQUIRE([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE]) +AC_CACHE_CHECK([for _ prefix in compiled symbols], + [ac_cv_sys_symbol_underscore], + [ac_cv_sys_symbol_underscore=no + cat > conftest.$ac_ext < $ac_nlist) && test -s "$ac_nlist"; then + # See whether the symbols have a leading underscore. + if grep '^. _nm_test_func' "$ac_nlist" >/dev/null; then + ac_cv_sys_symbol_underscore=yes + else + if grep '^. nm_test_func ' "$ac_nlist" >/dev/null; then + : + else + echo "configure: cannot find nm_test_func in $ac_nlist" >&AS_MESSAGE_LOG_FD + fi + fi + else + echo "configure: cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD + fi + else + echo "configure: failed program was:" >&AS_MESSAGE_LOG_FD + cat conftest.c >&AS_MESSAGE_LOG_FD + fi + rm -rf conftest* + ]) +])# AC_LTDL_SYMBOL_USCORE + + +# AC_LTDL_DLSYM_USCORE +# -------------------- +AC_DEFUN([AC_LTDL_DLSYM_USCORE], +[AC_REQUIRE([AC_LTDL_SYMBOL_USCORE]) +if test x"$ac_cv_sys_symbol_underscore" = xyes; then + if test x"$libltdl_cv_func_dlopen" = xyes || + test x"$libltdl_cv_lib_dl_dlopen" = xyes ; then + AC_CACHE_CHECK([whether we have to add an underscore for dlsym], + [libltdl_cv_need_uscore], + [libltdl_cv_need_uscore=unknown + save_LIBS="$LIBS" + LIBS="$LIBS $LIBADD_DL" + _LT_AC_TRY_DLOPEN_SELF( + [libltdl_cv_need_uscore=no], [libltdl_cv_need_uscore=yes], + [], [libltdl_cv_need_uscore=cross]) + LIBS="$save_LIBS" + ]) + fi +fi + +if test x"$libltdl_cv_need_uscore" = xyes; then + AC_DEFINE([NEED_USCORE], [1], + [Define if dlsym() requires a leading underscore in symbol names.]) +fi +])# AC_LTDL_DLSYM_USCORE + +# AC_LTDL_FUNC_ARGZ +# ----------------- +AC_DEFUN([AC_LTDL_FUNC_ARGZ], +[AC_CHECK_HEADERS([argz.h]) + +AC_CHECK_TYPES([error_t], + [], + [AC_DEFINE([error_t], [int], + [Define to a type to use for `error_t' if it is not otherwise available.])], + [#if HAVE_ARGZ_H +# include +#endif]) + +AC_CHECK_FUNCS([argz_append argz_create_sep argz_insert argz_next argz_stringify]) +])# AC_LTDL_FUNC_ARGZ diff --git a/libclamav/c++/llvm/autoconf/m4/need_dev_zero_for_mmap.m4 b/libclamav/c++/llvm/autoconf/m4/need_dev_zero_for_mmap.m4 new file mode 100644 index 000000000..57b322830 --- /dev/null +++ b/libclamav/c++/llvm/autoconf/m4/need_dev_zero_for_mmap.m4 @@ -0,0 +1,17 @@ +# +# When allocating RWX memory, check whether we need to use /dev/zero +# as the file descriptor or not. +# +AC_DEFUN([AC_NEED_DEV_ZERO_FOR_MMAP], +[AC_CACHE_CHECK([if /dev/zero is needed for mmap], +ac_cv_need_dev_zero_for_mmap, +[if test "$llvm_cv_os_type" = "Interix" ; then + ac_cv_need_dev_zero_for_mmap=yes + else + ac_cv_need_dev_zero_for_mmap=no + fi +]) +if test "$ac_cv_need_dev_zero_for_mmap" = yes; then + AC_DEFINE([NEED_DEV_ZERO_FOR_MMAP],[1], + [Define if /dev/zero should be used when mapping RWX memory, or undefine if its not necessary]) +fi]) diff --git a/libclamav/c++/llvm/autoconf/m4/path_perl.m4 b/libclamav/c++/llvm/autoconf/m4/path_perl.m4 new file mode 100644 index 000000000..406656cb0 --- /dev/null +++ b/libclamav/c++/llvm/autoconf/m4/path_perl.m4 @@ -0,0 +1,16 @@ +dnl Check for a reasonable version of Perl. +dnl $1 - Minimum Perl version. Typically 5.006. +dnl +AC_DEFUN([LLVM_PROG_PERL], [ +AC_PATH_PROG(PERL, [perl], [none]) +if test "$PERL" != "none"; then + AC_MSG_CHECKING(for Perl $1 or newer) + if $PERL -e 'use $1;' 2>&1 > /dev/null; then + AC_MSG_RESULT(yes) + else + PERL=none + AC_MSG_RESULT(not found) + fi +fi +]) + diff --git a/libclamav/c++/llvm/autoconf/m4/path_tclsh.m4 b/libclamav/c++/llvm/autoconf/m4/path_tclsh.m4 new file mode 100644 index 000000000..e0a9d067a --- /dev/null +++ b/libclamav/c++/llvm/autoconf/m4/path_tclsh.m4 @@ -0,0 +1,39 @@ +dnl This macro checks for tclsh which is required to run dejagnu. On some +dnl platforms (notably FreeBSD), tclsh is named tclshX.Y - this handles +dnl that for us so we can get the latest installed tclsh version. +dnl +AC_DEFUN([DJ_AC_PATH_TCLSH], [ +no_itcl=true +AC_MSG_CHECKING(for the tclsh program in tclinclude directory) +AC_ARG_WITH(tclinclude, + AS_HELP_STRING([--with-tclinclude], + [directory where tcl headers are]), + [with_tclinclude=${withval}],[with_tclinclude='']) +AC_CACHE_VAL(ac_cv_path_tclsh,[ +dnl first check to see if --with-itclinclude was specified +if test x"${with_tclinclude}" != x ; then + if test -f ${with_tclinclude}/tclsh ; then + ac_cv_path_tclsh=`(cd ${with_tclinclude}; pwd)` + elif test -f ${with_tclinclude}/src/tclsh ; then + ac_cv_path_tclsh=`(cd ${with_tclinclude}/src; pwd)` + else + AC_MSG_ERROR([${with_tclinclude} directory doesn't contain tclsh]) + fi +fi + +dnl see if one is installed +if test x"${ac_cv_path_tclsh}" = x ; then + AC_MSG_RESULT(none) + AC_PATH_PROGS([TCLSH],[tclsh8.4 tclsh8.4.8 tclsh8.4.7 tclsh8.4.6 tclsh8.4.5 tclsh8.4.4 tclsh8.4.3 tclsh8.4.2 tclsh8.4.1 tclsh8.4.0 tclsh8.3 tclsh8.3.5 tclsh8.3.4 tclsh8.3.3 tclsh8.3.2 tclsh8.3.1 tclsh8.3.0 tclsh]) + if test x"${TCLSH}" = x ; then + ac_cv_path_tclsh=''; + else + ac_cv_path_tclsh="${TCLSH}"; + fi +else + AC_MSG_RESULT(${ac_cv_path_tclsh}) + TCLSH="${ac_cv_path_tclsh}" + AC_SUBST(TCLSH) +fi +])]) + diff --git a/libclamav/c++/llvm/autoconf/m4/rand48.m4 b/libclamav/c++/llvm/autoconf/m4/rand48.m4 new file mode 100644 index 000000000..56705d85c --- /dev/null +++ b/libclamav/c++/llvm/autoconf/m4/rand48.m4 @@ -0,0 +1,12 @@ +# +# This function determins if the the srand48,drand48,lrand48 functions are +# available on this platform. +# +AC_DEFUN([AC_FUNC_RAND48],[ +AC_SINGLE_CXX_CHECK([ac_cv_func_rand48], + [srand48/lrand48/drand48], [], + [srand48(0);lrand48();drand48();]) +if test "$ac_cv_func_rand48" = "yes" ; then +AC_DEFINE([HAVE_RAND48],1,[Define to 1 if srand48/lrand48/drand48 exist in ]) +fi +]) diff --git a/libclamav/c++/llvm/autoconf/m4/sanity_check.m4 b/libclamav/c++/llvm/autoconf/m4/sanity_check.m4 new file mode 100644 index 000000000..639fccca2 --- /dev/null +++ b/libclamav/c++/llvm/autoconf/m4/sanity_check.m4 @@ -0,0 +1,31 @@ +dnl Check a program for version sanity. The test runs a program, passes it an +dnl argument to make it print out some identification string, and filters that +dnl output with a regular expression. If the output is non-empty, the program +dnl passes the sanity check. +dnl $1 - Name or full path of the program to run +dnl $2 - Argument to pass to print out identification string +dnl $3 - grep RE to match identification string +dnl $4 - set to 1 to make errors only a warning +AC_DEFUN([CHECK_PROGRAM_SANITY], +[ +AC_MSG_CHECKING([sanity for program ]$1) +sanity="0" +sanity_path=`which $1 2>/dev/null` +if test "$?" -eq 0 -a -x "$sanity_path" ; then + sanity=`$1 $2 2>&1 | grep "$3"` + if test -z "$sanity" ; then + AC_MSG_RESULT([no]) + sanity="0" + if test "$4" -eq 1 ; then + AC_MSG_WARN([Program ]$1[ failed to pass sanity check.]) + else + AC_MSG_ERROR([Program ]$1[ failed to pass sanity check.]) + fi + else + AC_MSG_RESULT([yes]) + sanity="1" + fi +else + AC_MSG_RESULT([not found]) +fi +]) diff --git a/libclamav/c++/llvm/autoconf/m4/single_cxx_check.m4 b/libclamav/c++/llvm/autoconf/m4/single_cxx_check.m4 new file mode 100644 index 000000000..21efa4bed --- /dev/null +++ b/libclamav/c++/llvm/autoconf/m4/single_cxx_check.m4 @@ -0,0 +1,10 @@ +dnl AC_SINGLE_CXX_CHECK(CACHEVAR, FUNCTION, HEADER, PROGRAM) +dnl $1, $2, $3, $4, +dnl +AC_DEFUN([AC_SINGLE_CXX_CHECK], + [AC_CACHE_CHECK([for $2 in $3], [$1], + [AC_LANG_PUSH([C++]) + AC_COMPILE_IFELSE(AC_LANG_PROGRAM([#include $3],[$4]),[$1=yes],[$1=no]) + AC_LANG_POP([C++])]) + ]) + diff --git a/libclamav/c++/llvm/autoconf/m4/visibility_inlines_hidden.m4 b/libclamav/c++/llvm/autoconf/m4/visibility_inlines_hidden.m4 new file mode 100644 index 000000000..42ddbe912 --- /dev/null +++ b/libclamav/c++/llvm/autoconf/m4/visibility_inlines_hidden.m4 @@ -0,0 +1,22 @@ +# +# Determine if the compiler accepts -fvisibility-inlines-hidden +# +# This macro is specific to LLVM. +# +AC_DEFUN([AC_CXX_USE_VISIBILITY_INLINES_HIDDEN], +[AC_CACHE_CHECK([for compiler -fvisibility-inlines-hidden option], + [llvm_cv_cxx_visibility_inlines_hidden], +[ AC_LANG_PUSH([C++]) + oldcxxflags="$CXXFLAGS" + CXXFLAGS="$CXXFLAGS -fvisibility-inlines-hidden" + AC_COMPILE_IFELSE([AC_LANG_PROGRAM()], + [llvm_cv_cxx_visibility_inlines_hidden=yes],[llvm_cv_cxx_visibility_inlines_hidden=no]) + CXXFLAGS="$oldcxxflags" + AC_LANG_POP([C++]) +]) +if test "$llvm_cv_cxx_visibility_inlines_hidden" = yes ; then + AC_SUBST([ENABLE_VISIBILITY_INLINES_HIDDEN],[1]) +else + AC_SUBST([ENABLE_VISIBILITY_INLINES_HIDDEN],[0]) +fi +]) diff --git a/libclamav/c++/llvm/autoconf/missing b/libclamav/c++/llvm/autoconf/missing new file mode 100755 index 000000000..64b5f901d --- /dev/null +++ b/libclamav/c++/llvm/autoconf/missing @@ -0,0 +1,353 @@ +#! /bin/sh +# Common stub for a few missing GNU programs while installing. + +scriptversion=2004-09-07.08 + +# Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003, 2004 +# Free Software Foundation, Inc. +# Originally by Fran,cois Pinard , 1996. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA. + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +if test $# -eq 0; then + echo 1>&2 "Try \`$0 --help' for more information" + exit 1 +fi + +run=: + +# In the cases where this matters, `missing' is being run in the +# srcdir already. +if test -f configure.ac; then + configure_ac=configure.ac +else + configure_ac=configure.in +fi + +msg="missing on your system" + +case "$1" in +--run) + # Try to run requested program, and just exit if it succeeds. + run= + shift + "$@" && exit 0 + # Exit code 63 means version mismatch. This often happens + # when the user try to use an ancient version of a tool on + # a file that requires a minimum version. In this case we + # we should proceed has if the program had been absent, or + # if --run hadn't been passed. + if test $? = 63; then + run=: + msg="probably too old" + fi + ;; + + -h|--h|--he|--hel|--help) + echo "\ +$0 [OPTION]... PROGRAM [ARGUMENT]... + +Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an +error status if there is no known handling for PROGRAM. + +Options: + -h, --help display this help and exit + -v, --version output version information and exit + --run try to run the given command, and emulate it if it fails + +Supported PROGRAM values: + aclocal touch file \`aclocal.m4' + autoconf touch file \`configure' + autoheader touch file \`config.h.in' + automake touch all \`Makefile.in' files + bison create \`y.tab.[ch]', if possible, from existing .[ch] + flex create \`lex.yy.c', if possible, from existing .c + help2man touch the output file + lex create \`lex.yy.c', if possible, from existing .c + makeinfo touch the output file + tar try tar, gnutar, gtar, then tar without non-portable flags + yacc create \`y.tab.[ch]', if possible, from existing .[ch] + +Send bug reports to ." + exit 0 + ;; + + -v|--v|--ve|--ver|--vers|--versi|--versio|--version) + echo "missing $scriptversion (GNU Automake)" + exit 0 + ;; + + -*) + echo 1>&2 "$0: Unknown \`$1' option" + echo 1>&2 "Try \`$0 --help' for more information" + exit 1 + ;; + +esac + +# Now exit if we have it, but it failed. Also exit now if we +# don't have it and --version was passed (most likely to detect +# the program). +case "$1" in + lex|yacc) + # Not GNU programs, they don't have --version. + ;; + + tar) + if test -n "$run"; then + echo 1>&2 "ERROR: \`tar' requires --run" + exit 1 + elif test "x$2" = "x--version" || test "x$2" = "x--help"; then + exit 1 + fi + ;; + + *) + if test -z "$run" && ($1 --version) > /dev/null 2>&1; then + # We have it, but it failed. + exit 1 + elif test "x$2" = "x--version" || test "x$2" = "x--help"; then + # Could not run --version or --help. This is probably someone + # running `$TOOL --version' or `$TOOL --help' to check whether + # $TOOL exists and not knowing $TOOL uses missing. + exit 1 + fi + ;; +esac + +# If it does not exist, or fails to run (possibly an outdated version), +# try to emulate it. +case "$1" in + aclocal*) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified \`acinclude.m4' or \`${configure_ac}'. You might want + to install the \`Automake' and \`Perl' packages. Grab them from + any GNU archive site." + touch aclocal.m4 + ;; + + autoconf) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified \`${configure_ac}'. You might want to install the + \`Autoconf' and \`GNU m4' packages. Grab them from any GNU + archive site." + touch configure + ;; + + autoheader) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified \`acconfig.h' or \`${configure_ac}'. You might want + to install the \`Autoconf' and \`GNU m4' packages. Grab them + from any GNU archive site." + files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}` + test -z "$files" && files="config.h" + touch_files= + for f in $files; do + case "$f" in + *:*) touch_files="$touch_files "`echo "$f" | + sed -e 's/^[^:]*://' -e 's/:.*//'`;; + *) touch_files="$touch_files $f.in";; + esac + done + touch $touch_files + ;; + + automake*) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'. + You might want to install the \`Automake' and \`Perl' packages. + Grab them from any GNU archive site." + find . -type f -name Makefile.am -print | + sed 's/\.am$/.in/' | + while read f; do touch "$f"; done + ;; + + autom4te) + echo 1>&2 "\ +WARNING: \`$1' is needed, but is $msg. + You might have modified some files without having the + proper tools for further handling them. + You can get \`$1' as part of \`Autoconf' from any GNU + archive site." + + file=`echo "$*" | sed -n 's/.*--output[ =]*\([^ ]*\).*/\1/p'` + test -z "$file" && file=`echo "$*" | sed -n 's/.*-o[ ]*\([^ ]*\).*/\1/p'` + if test -f "$file"; then + touch $file + else + test -z "$file" || exec >$file + echo "#! /bin/sh" + echo "# Created by GNU Automake missing as a replacement of" + echo "# $ $@" + echo "exit 0" + chmod +x $file + exit 1 + fi + ;; + + bison|yacc) + echo 1>&2 "\ +WARNING: \`$1' $msg. You should only need it if + you modified a \`.y' file. You may need the \`Bison' package + in order for those modifications to take effect. You can get + \`Bison' from any GNU archive site." + rm -f y.tab.c y.tab.h + if [ $# -ne 1 ]; then + eval LASTARG="\${$#}" + case "$LASTARG" in + *.y) + SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'` + if [ -f "$SRCFILE" ]; then + cp "$SRCFILE" y.tab.c + fi + SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'` + if [ -f "$SRCFILE" ]; then + cp "$SRCFILE" y.tab.h + fi + ;; + esac + fi + if [ ! -f y.tab.h ]; then + echo >y.tab.h + fi + if [ ! -f y.tab.c ]; then + echo 'main() { return 0; }' >y.tab.c + fi + ;; + + lex|flex) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified a \`.l' file. You may need the \`Flex' package + in order for those modifications to take effect. You can get + \`Flex' from any GNU archive site." + rm -f lex.yy.c + if [ $# -ne 1 ]; then + eval LASTARG="\${$#}" + case "$LASTARG" in + *.l) + SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'` + if [ -f "$SRCFILE" ]; then + cp "$SRCFILE" lex.yy.c + fi + ;; + esac + fi + if [ ! -f lex.yy.c ]; then + echo 'main() { return 0; }' >lex.yy.c + fi + ;; + + help2man) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified a dependency of a manual page. You may need the + \`Help2man' package in order for those modifications to take + effect. You can get \`Help2man' from any GNU archive site." + + file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'` + if test -z "$file"; then + file=`echo "$*" | sed -n 's/.*--output=\([^ ]*\).*/\1/p'` + fi + if [ -f "$file" ]; then + touch $file + else + test -z "$file" || exec >$file + echo ".ab help2man is required to generate this page" + exit 1 + fi + ;; + + makeinfo) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified a \`.texi' or \`.texinfo' file, or any other file + indirectly affecting the aspect of the manual. The spurious + call might also be the consequence of using a buggy \`make' (AIX, + DU, IRIX). You might want to install the \`Texinfo' package or + the \`GNU make' package. Grab either from any GNU archive site." + file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'` + if test -z "$file"; then + file=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'` + file=`sed -n '/^@setfilename/ { s/.* \([^ ]*\) *$/\1/; p; q; }' $file` + fi + touch $file + ;; + + tar) + shift + + # We have already tried tar in the generic part. + # Look for gnutar/gtar before invocation to avoid ugly error + # messages. + if (gnutar --version > /dev/null 2>&1); then + gnutar "$@" && exit 0 + fi + if (gtar --version > /dev/null 2>&1); then + gtar "$@" && exit 0 + fi + firstarg="$1" + if shift; then + case "$firstarg" in + *o*) + firstarg=`echo "$firstarg" | sed s/o//` + tar "$firstarg" "$@" && exit 0 + ;; + esac + case "$firstarg" in + *h*) + firstarg=`echo "$firstarg" | sed s/h//` + tar "$firstarg" "$@" && exit 0 + ;; + esac + fi + + echo 1>&2 "\ +WARNING: I can't seem to be able to run \`tar' with the given arguments. + You may want to install GNU tar or Free paxutils, or check the + command line arguments." + exit 1 + ;; + + *) + echo 1>&2 "\ +WARNING: \`$1' is needed, and is $msg. + You might have modified some files without having the + proper tools for further handling them. Check the \`README' file, + it often tells you about the needed prerequisites for installing + this package. You may also peek at any GNU archive site, in case + some other package would contain this missing \`$1' program." + exit 1 + ;; +esac + +exit 0 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-end: "$" +# End: diff --git a/libclamav/c++/llvm/autoconf/mkinstalldirs b/libclamav/c++/llvm/autoconf/mkinstalldirs new file mode 100755 index 000000000..1ee2d5801 --- /dev/null +++ b/libclamav/c++/llvm/autoconf/mkinstalldirs @@ -0,0 +1,150 @@ +#! /bin/sh +# mkinstalldirs --- make directory hierarchy + +scriptversion=2004-02-15.20 + +# Original author: Noah Friedman +# Created: 1993-05-16 +# Public domain. +# +# This file is maintained in Automake, please report +# bugs to or send patches to +# . + +errstatus=0 +dirmode="" + +usage="\ +Usage: mkinstalldirs [-h] [--help] [--version] [-m MODE] DIR ... + +Create each directory DIR (with mode MODE, if specified), including all +leading file name components. + +Report bugs to ." + +# process command line arguments +while test $# -gt 0 ; do + case $1 in + -h | --help | --h*) # -h for help + echo "$usage" + exit 0 + ;; + -m) # -m PERM arg + shift + test $# -eq 0 && { echo "$usage" 1>&2; exit 1; } + dirmode=$1 + shift + ;; + --version) + echo "$0 $scriptversion" + exit 0 + ;; + --) # stop option processing + shift + break + ;; + -*) # unknown option + echo "$usage" 1>&2 + exit 1 + ;; + *) # first non-opt arg + break + ;; + esac +done + +for file +do + if test -d "$file"; then + shift + else + break + fi +done + +case $# in + 0) exit 0 ;; +esac + +# Solaris 8's mkdir -p isn't thread-safe. If you mkdir -p a/b and +# mkdir -p a/c at the same time, both will detect that a is missing, +# one will create a, then the other will try to create a and die with +# a "File exists" error. This is a problem when calling mkinstalldirs +# from a parallel make. We use --version in the probe to restrict +# ourselves to GNU mkdir, which is thread-safe. +case $dirmode in + '') + if mkdir -p --version . >/dev/null 2>&1 && test ! -d ./--version; then + # echo "mkdir -p -- $*" + exec mkdir -p -- "$@" + else + # On NextStep and OpenStep, the `mkdir' command does not + # recognize any option. It will interpret all options as + # directories to create, and then abort because `.' already + # exists. + test -d ./-p && rmdir ./-p + test -d ./--version && rmdir ./--version + fi + ;; + *) + if mkdir -m "$dirmode" -p --version . >/dev/null 2>&1 && + test ! -d ./--version; then + # echo "mkdir -m $dirmode -p -- $*" + exec mkdir -m "$dirmode" -p -- "$@" + else + # Clean up after NextStep and OpenStep mkdir. + for d in ./-m ./-p ./--version "./$dirmode"; + do + test -d $d && rmdir $d + done + fi + ;; +esac + +for file +do + set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'` + shift + + pathcomp= + for d + do + pathcomp="$pathcomp$d" + case $pathcomp in + -*) pathcomp=./$pathcomp ;; + esac + + if test ! -d "$pathcomp"; then + # echo "mkdir $pathcomp" + + mkdir "$pathcomp" || lasterr=$? + + if test ! -d "$pathcomp"; then + errstatus=$lasterr + else + if test ! -z "$dirmode"; then + # echo "chmod $dirmode $pathcomp" + lasterr="" + chmod "$dirmode" "$pathcomp" || lasterr=$? + + if test ! -z "$lasterr"; then + errstatus=$lasterr + fi + fi + fi + fi + + pathcomp="$pathcomp/" + done +done + +exit $errstatus + +# Local Variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-end: "$" +# End: diff --git a/libclamav/c++/llvm/build-for-llvm-top.sh b/libclamav/c++/llvm/build-for-llvm-top.sh new file mode 100755 index 000000000..78e3ed87f --- /dev/null +++ b/libclamav/c++/llvm/build-for-llvm-top.sh @@ -0,0 +1,68 @@ +#!/bin/sh + +# This includes the Bourne shell library from llvm-top. Since this file is +# generally only used when building from llvm-top, it is safe to assume that +# llvm is checked out into llvm-top in which case .. just works. +. ../library.sh + +# Process the options passed in to us by the build script into standard +# variables. +process_arguments "$@" + +# First, see if the build directory is there. If not, create it. +build_dir="$LLVM_TOP/build.llvm" +if test ! -d "$build_dir" ; then + mkdir -p "$build_dir" +fi + +# See if we have previously been configured by sensing the presence +# of the config.status scripts +config_status="$build_dir/config.status" +if test ! -f "$config_status" -o "$config_status" -ot "$0" ; then + # We must configure so build a list of configure options + config_options="--prefix=$PREFIX --with-llvmgccdir=$PREFIX" + if test "$OPTIMIZED" -eq 1 ; then + config_options="$config_options --enable-optimized" + else + config_options="$config_options --disable-optimized" + fi + if test "$DEBUG" -eq 1 ; then + config_options="$config_options --enable-debug" + else + config_options="$config_options --disable-debug" + fi + if test "$ASSERTIONS" -eq 1 ; then + config_options="$config_options --enable-assertions" + else + config_options="$config_options --disable-assertions" + fi + if test "$CHECKING" -eq 1 ; then + config_options="$config_options --enable-expensive-checks" + else + config_options="$config_options --disable-expensive-checks" + fi + if test "$DOXYGEN" -eq 1 ; then + config_options="$config_options --enable-doxygen" + else + config_options="$config_options --disable-doxygen" + fi + if test "$THREADS" -eq 1 ; then + config_options="$config_options --enable-threads" + else + config_options="$config_options --disable-threads" + fi + config_options="$config_options $OPTIONS_DASH $OPTIONS_DASH_DASH" + src_dir=`pwd` + cd "$build_dir" + msg 0 Configuring $module with: + msg 0 " $src_dir/configure" $config_options + $src_dir/configure $config_options || \ + die $? "Configuring $module module failed" +else + msg 0 Module $module already configured, ignoring configure options. + cd "$build_dir" +fi + +msg 0 Building $module with: +msg 0 " make" $OPTIONS_ASSIGN tools-only +make $OPTIONS_ASSIGN tools-only diff --git a/libclamav/c++/llvm/cmake/README b/libclamav/c++/llvm/cmake/README new file mode 100644 index 000000000..4aafdbf32 --- /dev/null +++ b/libclamav/c++/llvm/cmake/README @@ -0,0 +1 @@ +See docs/CMake.html for instructions on how to build LLVM with CMake. diff --git a/libclamav/c++/llvm/cmake/config-ix.cmake b/libclamav/c++/llvm/cmake/config-ix.cmake new file mode 100755 index 000000000..3a2b91cc3 --- /dev/null +++ b/libclamav/c++/llvm/cmake/config-ix.cmake @@ -0,0 +1,270 @@ +include(CheckIncludeFile) +include(CheckLibraryExists) +include(CheckSymbolExists) +include(CheckFunctionExists) +include(CheckCXXSourceCompiles) + +if( UNIX ) + # Used by check_symbol_exists: + set(CMAKE_REQUIRED_LIBRARIES m) +endif() + +# Helper macros and functions +macro(add_cxx_include result files) + set(${result} "") + foreach (file_name ${files}) + set(${result} "${${result}}#include<${file_name}>\n") + endforeach() +endmacro(add_cxx_include files result) + +function(check_type_exists type files variable) + add_cxx_include(includes "${files}") + CHECK_CXX_SOURCE_COMPILES(" + ${includes} ${type} typeVar; + int main() { + return 0; + } + " ${variable}) +endfunction() + +# include checks +check_include_file(argz.h HAVE_ARGZ_H) +check_include_file(assert.h HAVE_ASSERT_H) +check_include_file(dirent.h HAVE_DIRENT_H) +check_include_file(dl.h HAVE_DL_H) +check_include_file(dld.h HAVE_DLD_H) +check_include_file(dlfcn.h HAVE_DLFCN_H) +check_include_file(errno.h HAVE_ERRNO_H) +check_include_file(execinfo.h HAVE_EXECINFO_H) +check_include_file(fcntl.h HAVE_FCNTL_H) +check_include_file(inttypes.h HAVE_INTTYPES_H) +check_include_file(limits.h HAVE_LIMITS_H) +check_include_file(link.h HAVE_LINK_H) +check_include_file(malloc.h HAVE_MALLOC_H) +check_include_file(malloc/malloc.h HAVE_MALLOC_MALLOC_H) +check_include_file(memory.h HAVE_MEMORY_H) +check_include_file(ndir.h HAVE_NDIR_H) +if( NOT LLVM_ON_WIN32 ) + check_include_file(pthread.h HAVE_PTHREAD_H) +endif() +check_include_file(setjmp.h HAVE_SETJMP_H) +check_include_file(signal.h HAVE_SIGNAL_H) +check_include_file(stdint.h HAVE_STDINT_H) +check_include_file(stdio.h HAVE_STDIO_H) +check_include_file(stdlib.h HAVE_STDLIB_H) +check_include_file(string.h HAVE_STRING_H) +check_include_file(sys/dir.h HAVE_SYS_DIR_H) +check_include_file(sys/dl.h HAVE_SYS_DL_H) +check_include_file(sys/ioctl.h HAVE_SYS_IOCTL_H) +check_include_file(sys/mman.h HAVE_SYS_MMAN_H) +check_include_file(sys/ndir.h HAVE_SYS_NDIR_H) +check_include_file(sys/param.h HAVE_SYS_PARAM_H) +check_include_file(sys/resource.h HAVE_SYS_RESOURCE_H) +check_include_file(sys/stat.h HAVE_SYS_STAT_H) +check_include_file(sys/time.h HAVE_SYS_TIME_H) +check_include_file(sys/types.h HAVE_SYS_TYPES_H) +check_include_file(sys/wait.h HAVE_SYS_WAIT_H) +check_include_file(termios.h HAVE_TERMIOS_H) +check_include_file(unistd.h HAVE_UNISTD_H) +check_include_file(utime.h HAVE_UTIME_H) +check_include_file(windows.h HAVE_WINDOWS_H) + +# library checks +if( NOT LLVM_ON_WIN32 ) + check_library_exists(pthread pthread_create "" HAVE_LIBPTHREAD) + check_library_exists(pthread pthread_getspecific "" HAVE_PTHREAD_GETSPECIFIC) + check_library_exists(pthread pthread_rwlock_init "" HAVE_PTHREAD_RWLOCK_INIT) + check_library_exists(dl dlopen "" HAVE_LIBDL) +endif() + +# function checks +check_symbol_exists(getpagesize unistd.h HAVE_GETPAGESIZE) +check_symbol_exists(getrusage sys/resource.h HAVE_GETRUSAGE) +check_symbol_exists(setrlimit sys/resource.h HAVE_SETRLIMIT) +check_function_exists(isatty HAVE_ISATTY) +check_symbol_exists(isinf cmath HAVE_ISINF_IN_CMATH) +check_symbol_exists(isinf math.h HAVE_ISINF_IN_MATH_H) +check_symbol_exists(finite ieeefp.h HAVE_FINITE_IN_IEEEFP_H) +check_symbol_exists(isnan cmath HAVE_ISNAN_IN_CMATH) +check_symbol_exists(isnan math.h HAVE_ISNAN_IN_MATH_H) +check_symbol_exists(ceilf math.h HAVE_CEILF) +check_symbol_exists(floorf math.h HAVE_FLOORF) +check_symbol_exists(nearbyintf math.h HAVE_NEARBYINTF) +check_symbol_exists(mallinfo malloc.h HAVE_MALLINFO) +check_symbol_exists(malloc_zone_statistics malloc/malloc.h + HAVE_MALLOC_ZONE_STATISTICS) +check_symbol_exists(mkdtemp "stdlib.h;unistd.h" HAVE_MKDTEMP) +check_symbol_exists(mkstemp "stdlib.h;unistd.h" HAVE_MKSTEMP) +check_symbol_exists(mktemp "stdlib.h;unistd.h" HAVE_MKTEMP) +if( NOT LLVM_ON_WIN32 ) + check_symbol_exists(pthread_mutex_lock pthread.h HAVE_PTHREAD_MUTEX_LOCK) +endif() +check_symbol_exists(sbrk unistd.h HAVE_SBRK) +check_symbol_exists(strtoll stdlib.h HAVE_STRTOLL) +check_symbol_exists(strerror string.h HAVE_STRERROR) +check_symbol_exists(strerror_r string.h HAVE_STRERROR_R) +check_symbol_exists(strerror_s string.h HAVE_STRERROR_S) +check_symbol_exists(setenv stdlib.h HAVE_SETENV) + +check_symbol_exists(__GLIBC__ stdio.h LLVM_USING_GLIBC) +if( LLVM_USING_GLIBC ) + add_llvm_definitions( -D_GNU_SOURCE ) +endif() + +# Type checks +check_type_exists(std::bidirectional_iterator "iterator;iostream" HAVE_BI_ITERATOR) +check_type_exists(std::iterator iterator HAVE_STD_ITERATOR) +check_type_exists(std::forward_iterator iterator HAVE_FWD_ITERATOR) + +set(headers "") +if (HAVE_SYS_TYPES_H) + set(headers ${headers} "sys/types.h") +endif() + +if (HAVE_INTTYPES_H) + set(headers ${headers} "inttypes.h") +endif() + +if (HAVE_STDINT_H) + set(headers ${headers} "stdint.h") +endif() + +check_type_exists(uint64_t "${headers}" HAVE_UINT64_T) +check_type_exists(u_int64_t "${headers}" HAVE_U_INT64_T) + +# available programs checks +function(llvm_find_program name) + string(TOUPPER ${name} NAME) + find_program(LLVM_PATH_${NAME} ${name}) + mark_as_advanced(LLVM_PATH_${NAME}) + if(LLVM_PATH_${NAME}) + set(HAVE_${NAME} 1 CACHE INTERNAL "Is ${name} available ?") + mark_as_advanced(HAVE_${NAME}) + else(LLVM_PATH_${NAME}) + set(HAVE_${NAME} "" CACHE INTERNAL "Is ${name} available ?") + endif(LLVM_PATH_${NAME}) +endfunction() + +llvm_find_program(gv) +llvm_find_program(circo) +llvm_find_program(twopi) +llvm_find_program(neato) +llvm_find_program(fdp) +llvm_find_program(dot) +llvm_find_program(dotty) + +# Define LLVM_MULTITHREADED if gcc atomic builtins exists. +include(CheckAtomic) + +include(CheckCXXCompilerFlag) +# On windows all code is position-independent and mingw warns if -fPIC +# is in the command-line. +if( NOT WIN32 ) + check_cxx_compiler_flag("-fPIC" SUPPORTS_FPIC_FLAG) +endif() + +include(GetTargetTriple) +get_target_triple(LLVM_HOSTTRIPLE) + +# FIXME: We don't distinguish the target and the host. :( +set(TARGET_TRIPLE "${LLVM_HOSTTRIPLE}") + +# Determine the native architecture. +string(TOLOWER "${LLVM_TARGET_ARCH}" LLVM_NATIVE_ARCH) +if( LLVM_NATIVE_ARCH STREQUAL "host" ) + string(REGEX MATCH "^[^-]*" LLVM_NATIVE_ARCH ${LLVM_HOSTTRIPLE}) +endif () + +if (LLVM_NATIVE_ARCH MATCHES "i[2-6]86") + set(LLVM_NATIVE_ARCH X86) +elseif (LLVM_NATIVE_ARCH STREQUAL "x86") + set(LLVM_NATIVE_ARCH X86) +elseif (LLVM_NATIVE_ARCH STREQUAL "amd64") + set(LLVM_NATIVE_ARCH X86) +elseif (LLVM_NATIVE_ARCH STREQUAL "x86_64") + set(LLVM_NATIVE_ARCH X86) +elseif (LLVM_NATIVE_ARCH MATCHES "sparc") + set(LLVM_NATIVE_ARCH Sparc) +elseif (LLVM_NATIVE_ARCH MATCHES "powerpc") + set(LLVM_NATIVE_ARCH PowerPC) +elseif (LLVM_NATIVE_ARCH MATCHES "alpha") + set(LLVM_NATIVE_ARCH Alpha) +elseif (LLVM_NATIVE_ARCH MATCHES "arm") + set(LLVM_NATIVE_ARCH ARM) +elseif (LLVM_NATIVE_ARCH MATCHES "mips") + set(LLVM_NATIVE_ARCH Mips) +elseif (LLVM_NATIVE_ARCH MATCHES "pic16") + set(LLVM_NATIVE_ARCH "PIC16") +elseif (LLVM_NATIVE_ARCH MATCHES "xcore") + set(LLVM_NATIVE_ARCH XCore) +elseif (LLVM_NATIVE_ARCH MATCHES "msp430") + set(LLVM_NATIVE_ARCH MSP430) +else () + message(STATUS + "Unknown architecture ${LLVM_NATIVE_ARCH}; lli will not JIT code") + set(LLVM_NATIVE_ARCH) +endif () + +if (LLVM_NATIVE_ARCH) + list(FIND LLVM_TARGETS_TO_BUILD ${LLVM_NATIVE_ARCH} NATIVE_ARCH_IDX) + if (NATIVE_ARCH_IDX EQUAL -1) + message(STATUS + "Native target ${LLVM_NATIVE_ARCH} is not selected; lli will not JIT code") + set(LLVM_NATIVE_ARCH) + else () + message(STATUS "Native target architecture is ${LLVM_NATIVE_ARCH}") + endif () +endif() + +if( MINGW ) + set(HAVE_LIBIMAGEHLP 1) + set(HAVE_LIBPSAPI 1) + # TODO: Check existence of libraries. + # include(CheckLibraryExists) + # CHECK_LIBRARY_EXISTS(imagehlp ??? . HAVE_LIBIMAGEHLP) +endif( MINGW ) + +if( MSVC ) + set(error_t int) + set(mode_t "unsigned short") + set(LTDL_SHLIBPATH_VAR "PATH") + set(LTDL_SYSSEARCHPATH "") + set(LTDL_DLOPEN_DEPLIBS 1) + set(SHLIBEXT ".lib") + set(LTDL_OBJDIR "_libs") + set(HAVE_STRTOLL 1) + set(strtoll "_strtoi64") + set(strtoull "_strtoui64") + set(stricmp "_stricmp") + set(strdup "_strdup") +else( MSVC ) + set(LTDL_SHLIBPATH_VAR "LD_LIBRARY_PATH") + set(LTDL_SYSSEARCHPATH "") # TODO + set(LTDL_DLOPEN_DEPLIBS 0) # TODO +endif( MSVC ) + +# FIXME: Signal handler return type, currently hardcoded to 'void' +set(RETSIGTYPE void) + +if( LLVM_ENABLE_THREADS ) + if( HAVE_PTHREAD_H OR WIN32 ) + set(ENABLE_THREADS 1) + endif() +endif() + +if( ENABLE_THREADS ) + message(STATUS "Threads enabled.") +else( ENABLE_THREADS ) + message(STATUS "Threads disabled.") +endif() + +configure_file( + ${LLVM_MAIN_INCLUDE_DIR}/llvm/Config/config.h.cmake + ${LLVM_BINARY_DIR}/include/llvm/Config/config.h + ) + +configure_file( + ${LLVM_MAIN_INCLUDE_DIR}/llvm/System/DataTypes.h.cmake + ${LLVM_BINARY_DIR}/include/llvm/System/DataTypes.h + ) + diff --git a/libclamav/c++/llvm/cmake/modules/AddLLVM.cmake b/libclamav/c++/llvm/cmake/modules/AddLLVM.cmake new file mode 100755 index 000000000..0ecd153c6 --- /dev/null +++ b/libclamav/c++/llvm/cmake/modules/AddLLVM.cmake @@ -0,0 +1,109 @@ +include(LLVMProcessSources) +include(LLVMConfig) + +macro(add_llvm_library name) + llvm_process_sources( ALL_FILES ${ARGN} ) + add_library( ${name} ${ALL_FILES} ) + set( llvm_libs ${llvm_libs} ${name} PARENT_SCOPE) + set( llvm_lib_targets ${llvm_lib_targets} ${name} PARENT_SCOPE ) + if( LLVM_COMMON_DEPENDS ) + add_dependencies( ${name} ${LLVM_COMMON_DEPENDS} ) + endif( LLVM_COMMON_DEPENDS ) + install(TARGETS ${name} + LIBRARY DESTINATION lib${LLVM_LIBDIR_SUFFIX} + ARCHIVE DESTINATION lib${LLVM_LIBDIR_SUFFIX}) + # The LLVM Target library shall be built before its sublibraries + # (asmprinter, etc) because those may use tablegenned files which + # generation is triggered by the main LLVM target library. Necessary + # for parallel builds: + if( CURRENT_LLVM_TARGET ) + add_dependencies(${name} ${CURRENT_LLVM_TARGET}) + endif() +endmacro(add_llvm_library name) + + +macro(add_llvm_loadable_module name) + if( NOT LLVM_ON_UNIX ) + message(STATUS "Loadable modules not supported on this platform. +${name} ignored.") + else() + llvm_process_sources( ALL_FILES ${ARGN} ) + add_library( ${name} MODULE ${ALL_FILES} ) + set_target_properties( ${name} PROPERTIES PREFIX "" ) + + if (APPLE) + # Darwin-specific linker flags for loadable modules. + set_target_properties(${name} PROPERTIES + LINK_FLAGS "-Wl,-flat_namespace -Wl,-undefined -Wl,suppress") + endif() + + install(TARGETS ${name} + LIBRARY DESTINATION lib${LLVM_LIBDIR_SUFFIX} + ARCHIVE DESTINATION lib${LLVM_LIBDIR_SUFFIX}) + endif() +endmacro(add_llvm_loadable_module name) + + +macro(add_llvm_executable name) + llvm_process_sources( ALL_FILES ${ARGN} ) + if( EXCLUDE_FROM_ALL ) + add_executable(${name} EXCLUDE_FROM_ALL ${ALL_FILES}) + else() + add_executable(${name} ${ALL_FILES}) + endif() + set(EXCLUDE_FROM_ALL OFF) + if( LLVM_USED_LIBS ) + foreach(lib ${LLVM_USED_LIBS}) + target_link_libraries( ${name} ${lib} ) + endforeach(lib) + endif( LLVM_USED_LIBS ) + if( LLVM_LINK_COMPONENTS ) + llvm_config(${name} ${LLVM_LINK_COMPONENTS}) + endif( LLVM_LINK_COMPONENTS ) + get_system_libs(llvm_system_libs) + if( llvm_system_libs ) + target_link_libraries(${name} ${llvm_system_libs}) + endif() + if( LLVM_COMMON_DEPENDS ) + add_dependencies( ${name} ${LLVM_COMMON_DEPENDS} ) + endif( LLVM_COMMON_DEPENDS ) +endmacro(add_llvm_executable name) + + +macro(add_llvm_tool name) + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${LLVM_TOOLS_BINARY_DIR}) + if( NOT LLVM_BUILD_TOOLS ) + set(EXCLUDE_FROM_ALL ON) + endif() + add_llvm_executable(${name} ${ARGN}) + if( LLVM_BUILD_TOOLS ) + install(TARGETS ${name} RUNTIME DESTINATION bin) + endif() +endmacro(add_llvm_tool name) + + +macro(add_llvm_example name) +# set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${LLVM_EXAMPLES_BINARY_DIR}) + if( NOT LLVM_BUILD_EXAMPLES ) + set(EXCLUDE_FROM_ALL ON) + endif() + add_llvm_executable(${name} ${ARGN}) + if( LLVM_BUILD_EXAMPLES ) + install(TARGETS ${name} RUNTIME DESTINATION examples) + endif() +endmacro(add_llvm_example name) + + +macro(add_llvm_target target_name) + if( TABLEGEN_OUTPUT ) + add_custom_target(${target_name}Table_gen + DEPENDS ${TABLEGEN_OUTPUT}) + add_dependencies(${target_name}Table_gen ${LLVM_COMMON_DEPENDS}) + endif( TABLEGEN_OUTPUT ) + include_directories(BEFORE ${CMAKE_CURRENT_BINARY_DIR}) + add_llvm_library(LLVM${target_name} ${ARGN} ${TABLEGEN_OUTPUT}) + if ( TABLEGEN_OUTPUT ) + add_dependencies(LLVM${target_name} ${target_name}Table_gen) + endif (TABLEGEN_OUTPUT) + set(CURRENT_LLVM_TARGET LLVM${target_name} PARENT_SCOPE) +endmacro(add_llvm_target) diff --git a/libclamav/c++/llvm/cmake/modules/AddLLVMDefinitions.cmake b/libclamav/c++/llvm/cmake/modules/AddLLVMDefinitions.cmake new file mode 100644 index 000000000..0f6d81f73 --- /dev/null +++ b/libclamav/c++/llvm/cmake/modules/AddLLVMDefinitions.cmake @@ -0,0 +1,11 @@ +# There is no clear way of keeping track of compiler command-line +# options chosen via `add_definitions', so we need our own method for +# using it on tools/llvm-config/CMakeLists.txt. + +# Beware that there is no implementation of remove_llvm_definitions. + +macro(add_llvm_definitions) + set(LLVM_DEFINITIONS "${LLVM_DEFINITIONS} ${ARGN}") + add_definitions( ${ARGN} ) +endmacro(add_llvm_definitions) + diff --git a/libclamav/c++/llvm/cmake/modules/CheckAtomic.cmake b/libclamav/c++/llvm/cmake/modules/CheckAtomic.cmake new file mode 100644 index 000000000..27bbaba69 --- /dev/null +++ b/libclamav/c++/llvm/cmake/modules/CheckAtomic.cmake @@ -0,0 +1,18 @@ +# atomic builtins are required for threading support. + +INCLUDE(CheckCXXSourceCompiles) + +CHECK_CXX_SOURCE_COMPILES(" +int main() { + volatile unsigned long val = 1; + __sync_synchronize(); + __sync_val_compare_and_swap(&val, 1, 0); + __sync_add_and_fetch(&val, 1); + __sync_sub_and_fetch(&val, 1); + return 0; + } +" LLVM_MULTITHREADED) + +if( NOT LLVM_MULTITHREADED ) + message(STATUS "Warning: LLVM will be built thread-unsafe because atomic builtins are missing") +endif() diff --git a/libclamav/c++/llvm/cmake/modules/CrossCompileLLVM.cmake b/libclamav/c++/llvm/cmake/modules/CrossCompileLLVM.cmake new file mode 100644 index 000000000..138ff0e9f --- /dev/null +++ b/libclamav/c++/llvm/cmake/modules/CrossCompileLLVM.cmake @@ -0,0 +1,26 @@ + +if( ${LLVM_TABLEGEN} STREQUAL "tblgen" ) + set(CX_NATIVE_TG_DIR "${CMAKE_BINARY_DIR}/native") + set(LLVM_TABLEGEN_EXE "${CX_NATIVE_TG_DIR}/bin/tblgen") + + add_custom_command(OUTPUT ${CX_NATIVE_TG_DIR} + COMMAND ${CMAKE_COMMAND} -E make_directory ${CX_NATIVE_TG_DIR} + COMMENT "Creating ${CX_NATIVE_TG_DIR}...") + + add_custom_command(OUTPUT ${CX_NATIVE_TG_DIR}/CMakeCache.txt + COMMAND ${CMAKE_COMMAND} -UMAKE_TOOLCHAIN_FILE -DCMAKE_BUILD_TYPE=Release ${CMAKE_SOURCE_DIR} + WORKING_DIRECTORY ${CX_NATIVE_TG_DIR} + DEPENDS ${CX_NATIVE_TG_DIR} + COMMENT "Configuring native TableGen...") + + add_custom_command(OUTPUT ${LLVM_TABLEGEN_EXE} + COMMAND ${CMAKE_BUILD_TOOL} + DEPENDS ${CX_NATIVE_TG_DIR}/CMakeCache.txt + WORKING_DIRECTORY ${CX_NATIVE_TG_DIR}/utils/TableGen + COMMENT "Building native TableGen...") + add_custom_target(NativeTableGen DEPENDS ${LLVM_TABLEGEN_EXE}) + + add_dependencies(tblgen NativeTableGen) + + set_directory_properties(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES ${CX_NATIVE_TG_DIR}) +endif() diff --git a/libclamav/c++/llvm/cmake/modules/FindBison.cmake b/libclamav/c++/llvm/cmake/modules/FindBison.cmake new file mode 100755 index 000000000..0320ae3ce --- /dev/null +++ b/libclamav/c++/llvm/cmake/modules/FindBison.cmake @@ -0,0 +1,52 @@ +# - Try to find Bison +# Once done this will define +# +# BISON_FOUND - system has Bison +# BISON_EXECUTABLE - path of the bison executable +# BISON_VERSION - the version string, like "2.5.31" +# + +MACRO(FIND_BISON) + FIND_PROGRAM(BISON_EXECUTABLE NAMES bison) + + IF(BISON_EXECUTABLE) + SET(BISON_FOUND TRUE) + + EXECUTE_PROCESS(COMMAND ${BISON_EXECUTABLE} --version + OUTPUT_VARIABLE _BISON_VERSION + ) + string (REGEX MATCH "[0-9]+\\.[0-9]+\\.[0-9]+" BISON_VERSION "${_bison_VERSION}") + ENDIF(BISON_EXECUTABLE) + + IF(BISON_FOUND) + IF(NOT Bison_FIND_QUIETLY) + MESSAGE(STATUS "Found Bison: ${BISON_EXECUTABLE}") + ENDIF(NOT Bison_FIND_QUIETLY) + ELSE(BISON_FOUND) + IF(Bison_FIND_REQUIRED) + MESSAGE(FATAL_ERROR "Could not find Bison") + ENDIF(Bison_FIND_REQUIRED) + ENDIF(BISON_FOUND) +ENDMACRO(FIND_BISON) + +MACRO(BISON_GENERATOR _PREFIX _Y_INPUT _H_OUTPUT _CPP_OUTPUT) + IF(BISON_EXECUTABLE) + GET_FILENAME_COMPONENT(_Y_DIR ${_Y_INPUT} PATH) + ADD_CUSTOM_COMMAND( + OUTPUT ${_CPP_OUTPUT} + OUTPUT ${_H_OUTPUT} + DEPENDS ${_Y_INPUT} + COMMAND ${BISON_EXECUTABLE} + ARGS + -p ${_PREFIX} -o"${_CPP_OUTPUT}" + --defines="${_H_OUTPUT}" ${_Y_INPUT} + WORKING_DIRECTORY ${_Y_DIR} + ) + SET_SOURCE_FILES_PROPERTIES( + ${_CPP_OUTPUT} ${_H_OUTPUT} + GENERATED + ) + ELSE(BISON_EXECUTABLE) + MESSAGE(SEND_ERROR "Can't find bison program, and it's required") + ENDIF(BISON_EXECUTABLE) +ENDMACRO(BISON_GENERATOR) diff --git a/libclamav/c++/llvm/cmake/modules/GetTargetTriple.cmake b/libclamav/c++/llvm/cmake/modules/GetTargetTriple.cmake new file mode 100644 index 000000000..ac0c00924 --- /dev/null +++ b/libclamav/c++/llvm/cmake/modules/GetTargetTriple.cmake @@ -0,0 +1,26 @@ +# Returns the host triple. +# Invokes config.guess + +function( get_target_triple var ) + if( MSVC ) + if( CMAKE_CL_64 ) + set( value "x86_64-pc-win32" ) + else() + set( value "i686-pc-win32" ) + endif() + elseif( MINGW AND NOT MSYS ) + set( value "i686-pc-mingw32" ) + else( MSVC ) + set(config_guess ${LLVM_MAIN_SRC_DIR}/autoconf/config.guess) + execute_process(COMMAND sh ${config_guess} + RESULT_VARIABLE TT_RV + OUTPUT_VARIABLE TT_OUT + OUTPUT_STRIP_TRAILING_WHITESPACE) + if( NOT TT_RV EQUAL 0 ) + message(FATAL_ERROR "Failed to execute ${config_guess}") + endif( NOT TT_RV EQUAL 0 ) + set( value ${TT_OUT} ) + endif( MSVC ) + set( ${var} ${value} PARENT_SCOPE ) + message(STATUS "Target triple: ${value}") +endfunction( get_target_triple var ) diff --git a/libclamav/c++/llvm/cmake/modules/LLVMConfig.cmake b/libclamav/c++/llvm/cmake/modules/LLVMConfig.cmake new file mode 100755 index 000000000..0744b50d6 --- /dev/null +++ b/libclamav/c++/llvm/cmake/modules/LLVMConfig.cmake @@ -0,0 +1,129 @@ +function(get_system_libs return_var) + # Returns in `return_var' a list of system libraries used by LLVM. + if( NOT MSVC ) + if( MINGW ) + set(system_libs ${system_libs} imagehlp psapi) + elseif( CMAKE_HOST_UNIX ) + if( HAVE_LIBDL ) + set(system_libs ${system_libs} ${CMAKE_DL_LIBS}) + endif() + if( LLVM_ENABLE_THREADS AND HAVE_LIBPTHREAD ) + set(system_libs ${system_libs} pthread) + endif() + endif( MINGW ) + endif( NOT MSVC ) + set(${return_var} ${system_libs} PARENT_SCOPE) +endfunction(get_system_libs) + + +macro(llvm_config executable) + explicit_llvm_config(${executable} ${ARGN}) +endmacro(llvm_config) + + +function(explicit_llvm_config executable) + set( link_components ${ARGN} ) + + explicit_map_components_to_libraries(LIBRARIES ${link_components}) + target_link_libraries(${executable} ${LIBRARIES}) +endfunction(explicit_llvm_config) + + +function(explicit_map_components_to_libraries out_libs) + set( link_components ${ARGN} ) + foreach(c ${link_components}) + # add codegen, asmprinter, asmparser, disassembler + list(FIND LLVM_TARGETS_TO_BUILD ${c} idx) + if( NOT idx LESS 0 ) + list(FIND llvm_libs "LLVM${c}CodeGen" idx) + if( NOT idx LESS 0 ) + list(APPEND expanded_components "LLVM${c}CodeGen") + else() + list(FIND llvm_libs "LLVM${c}" idx) + if( NOT idx LESS 0 ) + list(APPEND expanded_components "LLVM${c}") + else() + message(FATAL_ERROR "Target ${c} is not in the set of libraries.") + endif() + endif() + list(FIND llvm_libs "LLVM${c}AsmPrinter" asmidx) + if( NOT asmidx LESS 0 ) + list(APPEND expanded_components "LLVM${c}AsmPrinter") + endif() + list(FIND llvm_libs "LLVM${c}AsmParser" asmidx) + if( NOT asmidx LESS 0 ) + list(APPEND expanded_components "LLVM${c}AsmParser") + endif() + list(FIND llvm_libs "LLVM${c}Info" asmidx) + if( NOT asmidx LESS 0 ) + list(APPEND expanded_components "LLVM${c}Info") + endif() + list(FIND llvm_libs "LLVM${c}Disassembler" asmidx) + if( NOT asmidx LESS 0 ) + list(APPEND expanded_components "LLVM${c}Disassembler") + endif() + elseif( c STREQUAL "native" ) + list(APPEND expanded_components "LLVM${LLVM_NATIVE_ARCH}CodeGen") + elseif( c STREQUAL "nativecodegen" ) + list(APPEND expanded_components "LLVM${LLVM_NATIVE_ARCH}CodeGen") + elseif( c STREQUAL "backend" ) + # same case as in `native'. + elseif( c STREQUAL "engine" ) + # TODO: as we assume we are on X86, this is `jit'. + list(APPEND expanded_components "LLVMJIT") + elseif( c STREQUAL "all" ) + list(APPEND expanded_components ${llvm_libs}) + else( NOT idx LESS 0 ) + list(APPEND expanded_components LLVM${c}) + endif( NOT idx LESS 0 ) + endforeach(c) + # We must match capitalization. + string(TOUPPER "${llvm_libs}" capitalized_libs) + list(REMOVE_DUPLICATES expanded_components) + list(LENGTH expanded_components lst_size) + set(result "") + while( 0 LESS ${lst_size} ) + list(GET expanded_components 0 c) + string(TOUPPER "${c}" capitalized) + list(FIND capitalized_libs ${capitalized} idx) + if( idx LESS 0 ) + message(FATAL_ERROR "Library ${c} not found in list of llvm libraries.") + endif( idx LESS 0 ) + list(GET llvm_libs ${idx} canonical_lib) + list(REMOVE_ITEM result ${canonical_lib}) + list(APPEND result ${canonical_lib}) + foreach(c ${MSVC_LIB_DEPS_${canonical_lib}}) + list(REMOVE_ITEM expanded_components ${c}) + endforeach() + list(APPEND expanded_components ${MSVC_LIB_DEPS_${canonical_lib}}) + list(REMOVE_AT expanded_components 0) + list(LENGTH expanded_components lst_size) + endwhile( 0 LESS ${lst_size} ) + set(${out_libs} ${result} PARENT_SCOPE) +endfunction(explicit_map_components_to_libraries) + + +# The library dependency data is contained in the file +# LLVMLibDeps.cmake on this directory. It is automatically generated +# by tools/llvm-config/CMakeLists.txt when the build comprises all the +# targets and we are on a environment Posix enough to build the +# llvm-config script. This, in practice, just excludes MSVC. + +# When you remove or rename a library from the build, be sure to +# remove its file from lib/ as well, or the GenLibDeps.pl script will +# include it on its analysis! + +# The format generated by GenLibDeps.pl + +# LLVMARMAsmPrinter.o: LLVMARMCodeGen.o libLLVMAsmPrinter.a libLLVMCodeGen.a libLLVMCore.a libLLVMSupport.a libLLVMTarget.a + +# is translated to: + +# set(MSVC_LIB_DEPS_LLVMARMAsmPrinter LLVMARMCodeGen LLVMAsmPrinter LLVMCodeGen LLVMCore LLVMSupport LLVMTarget) + +# It is necessary to remove the `lib' prefix and the `.a'. + +# This 'sed' script should do the trick: +# sed -e s'#\.a##g' -e 's#libLLVM#LLVM#g' -e 's#: # #' -e 's#\(.*\)#set(MSVC_LIB_DEPS_\1)#' ~/llvm/tools/llvm-config/LibDeps.txt + +include(LLVMLibDeps) diff --git a/libclamav/c++/llvm/cmake/modules/LLVMLibDeps.cmake b/libclamav/c++/llvm/cmake/modules/LLVMLibDeps.cmake new file mode 100644 index 000000000..f38925063 --- /dev/null +++ b/libclamav/c++/llvm/cmake/modules/LLVMLibDeps.cmake @@ -0,0 +1,66 @@ +set(MSVC_LIB_DEPS_LLVMARMAsmParser LLVMARMInfo LLVMMC) +set(MSVC_LIB_DEPS_LLVMARMAsmPrinter LLVMARMCodeGen LLVMARMInfo LLVMAsmPrinter LLVMCodeGen LLVMCore LLVMMC LLVMSupport LLVMSystem LLVMTarget) +set(MSVC_LIB_DEPS_LLVMARMCodeGen LLVMARMInfo LLVMCodeGen LLVMCore LLVMMC LLVMSelectionDAG LLVMSupport LLVMSystem LLVMTarget) +set(MSVC_LIB_DEPS_LLVMARMInfo LLVMSupport) +set(MSVC_LIB_DEPS_LLVMAlphaAsmPrinter LLVMAlphaCodeGen LLVMAlphaInfo LLVMAsmPrinter LLVMCodeGen LLVMCore LLVMMC LLVMSupport LLVMSystem LLVMTarget) +set(MSVC_LIB_DEPS_LLVMAlphaCodeGen LLVMAlphaInfo LLVMCodeGen LLVMCore LLVMMC LLVMSelectionDAG LLVMSupport LLVMSystem LLVMTarget) +set(MSVC_LIB_DEPS_LLVMAlphaInfo LLVMSupport) +set(MSVC_LIB_DEPS_LLVMAnalysis LLVMCore LLVMSupport LLVMSystem LLVMTarget) +set(MSVC_LIB_DEPS_LLVMArchive LLVMBitReader LLVMCore LLVMSupport LLVMSystem) +set(MSVC_LIB_DEPS_LLVMAsmParser LLVMCore LLVMSupport LLVMSystem) +set(MSVC_LIB_DEPS_LLVMAsmPrinter LLVMAnalysis LLVMCodeGen LLVMCore LLVMMC LLVMSupport LLVMSystem LLVMTarget) +set(MSVC_LIB_DEPS_LLVMBitReader LLVMCore LLVMSupport LLVMSystem) +set(MSVC_LIB_DEPS_LLVMBitWriter LLVMCore LLVMSupport LLVMSystem) +set(MSVC_LIB_DEPS_LLVMBlackfinAsmPrinter LLVMAsmPrinter LLVMBlackfinCodeGen LLVMBlackfinInfo LLVMCodeGen LLVMCore LLVMMC LLVMSupport LLVMSystem LLVMTarget) +set(MSVC_LIB_DEPS_LLVMBlackfinCodeGen LLVMBlackfinInfo LLVMCodeGen LLVMCore LLVMMC LLVMSelectionDAG LLVMSupport LLVMTarget) +set(MSVC_LIB_DEPS_LLVMBlackfinInfo LLVMSupport) +set(MSVC_LIB_DEPS_LLVMCBackend LLVMAnalysis LLVMCBackendInfo LLVMCodeGen LLVMCore LLVMScalarOpts LLVMSupport LLVMSystem LLVMTarget LLVMTransformUtils LLVMipa) +set(MSVC_LIB_DEPS_LLVMCBackendInfo LLVMSupport) +set(MSVC_LIB_DEPS_LLVMCellSPUAsmPrinter LLVMAsmPrinter LLVMCellSPUCodeGen LLVMCellSPUInfo LLVMCodeGen LLVMCore LLVMMC LLVMSupport LLVMSystem LLVMTarget) +set(MSVC_LIB_DEPS_LLVMCellSPUCodeGen LLVMCellSPUInfo LLVMCodeGen LLVMCore LLVMMC LLVMSelectionDAG LLVMSupport LLVMTarget) +set(MSVC_LIB_DEPS_LLVMCellSPUInfo LLVMSupport) +set(MSVC_LIB_DEPS_LLVMCodeGen LLVMAnalysis LLVMCore LLVMMC LLVMScalarOpts LLVMSupport LLVMSystem LLVMTarget LLVMTransformUtils) +set(MSVC_LIB_DEPS_LLVMCore LLVMSupport LLVMSystem) +set(MSVC_LIB_DEPS_LLVMCppBackend LLVMCore LLVMCppBackendInfo LLVMSupport LLVMSystem LLVMTarget) +set(MSVC_LIB_DEPS_LLVMCppBackendInfo LLVMSupport) +set(MSVC_LIB_DEPS_LLVMExecutionEngine LLVMCore LLVMSupport LLVMSystem LLVMTarget) +set(MSVC_LIB_DEPS_LLVMInstrumentation LLVMAnalysis LLVMCore LLVMScalarOpts LLVMSupport LLVMSystem LLVMTransformUtils) +set(MSVC_LIB_DEPS_LLVMInterpreter LLVMCodeGen LLVMCore LLVMExecutionEngine LLVMSupport LLVMSystem LLVMTarget) +set(MSVC_LIB_DEPS_LLVMJIT LLVMCodeGen LLVMCore LLVMExecutionEngine LLVMMC LLVMSupport LLVMSystem LLVMTarget) +set(MSVC_LIB_DEPS_LLVMLinker LLVMArchive LLVMBitReader LLVMCore LLVMSupport LLVMSystem) +set(MSVC_LIB_DEPS_LLVMMC LLVMSupport LLVMSystem) +set(MSVC_LIB_DEPS_LLVMMSIL LLVMAnalysis LLVMCodeGen LLVMCore LLVMMSILInfo LLVMScalarOpts LLVMSupport LLVMSystem LLVMTarget LLVMTransformUtils LLVMipa) +set(MSVC_LIB_DEPS_LLVMMSILInfo LLVMSupport) +set(MSVC_LIB_DEPS_LLVMMSP430AsmPrinter LLVMAsmPrinter LLVMCodeGen LLVMCore LLVMMC LLVMMSP430CodeGen LLVMMSP430Info LLVMSupport LLVMSystem LLVMTarget) +set(MSVC_LIB_DEPS_LLVMMSP430CodeGen LLVMCodeGen LLVMCore LLVMMC LLVMMSP430Info LLVMSelectionDAG LLVMSupport LLVMSystem LLVMTarget) +set(MSVC_LIB_DEPS_LLVMMSP430Info LLVMSupport) +set(MSVC_LIB_DEPS_LLVMMipsAsmPrinter LLVMAsmPrinter LLVMCodeGen LLVMCore LLVMMC LLVMMipsCodeGen LLVMMipsInfo LLVMSupport LLVMSystem LLVMTarget) +set(MSVC_LIB_DEPS_LLVMMipsCodeGen LLVMCodeGen LLVMCore LLVMMC LLVMMipsInfo LLVMSelectionDAG LLVMSupport LLVMSystem LLVMTarget) +set(MSVC_LIB_DEPS_LLVMMipsInfo LLVMSupport) +set(MSVC_LIB_DEPS_LLVMPIC16 LLVMAnalysis LLVMCodeGen LLVMCore LLVMMC LLVMPIC16Info LLVMSelectionDAG LLVMSupport LLVMSystem LLVMTarget) +set(MSVC_LIB_DEPS_LLVMPIC16AsmPrinter LLVMAsmPrinter LLVMCodeGen LLVMCore LLVMMC LLVMPIC16 LLVMPIC16Info LLVMSupport LLVMSystem LLVMTarget) +set(MSVC_LIB_DEPS_LLVMPIC16Info LLVMSupport) +set(MSVC_LIB_DEPS_LLVMPowerPCAsmPrinter LLVMAsmPrinter LLVMCodeGen LLVMCore LLVMMC LLVMPowerPCCodeGen LLVMPowerPCInfo LLVMSupport LLVMSystem LLVMTarget) +set(MSVC_LIB_DEPS_LLVMPowerPCCodeGen LLVMCodeGen LLVMCore LLVMMC LLVMPowerPCInfo LLVMSelectionDAG LLVMSupport LLVMSystem LLVMTarget) +set(MSVC_LIB_DEPS_LLVMPowerPCInfo LLVMSupport) +set(MSVC_LIB_DEPS_LLVMScalarOpts LLVMAnalysis LLVMCore LLVMSupport LLVMSystem LLVMTarget LLVMTransformUtils) +set(MSVC_LIB_DEPS_LLVMSelectionDAG LLVMAnalysis LLVMAsmPrinter LLVMCodeGen LLVMCore LLVMSupport LLVMSystem LLVMTarget) +set(MSVC_LIB_DEPS_LLVMSparcAsmPrinter LLVMAsmPrinter LLVMCodeGen LLVMCore LLVMMC LLVMSparcCodeGen LLVMSparcInfo LLVMSupport LLVMSystem LLVMTarget) +set(MSVC_LIB_DEPS_LLVMSparcCodeGen LLVMCodeGen LLVMCore LLVMMC LLVMSelectionDAG LLVMSparcInfo LLVMSupport LLVMSystem LLVMTarget) +set(MSVC_LIB_DEPS_LLVMSparcInfo LLVMSupport) +set(MSVC_LIB_DEPS_LLVMSupport LLVMSystem) +set(MSVC_LIB_DEPS_LLVMSystem ) +set(MSVC_LIB_DEPS_LLVMSystemZAsmPrinter LLVMAsmPrinter LLVMCodeGen LLVMCore LLVMMC LLVMSupport LLVMSystem LLVMSystemZCodeGen LLVMSystemZInfo LLVMTarget) +set(MSVC_LIB_DEPS_LLVMSystemZCodeGen LLVMCodeGen LLVMCore LLVMMC LLVMSelectionDAG LLVMSupport LLVMSystemZInfo LLVMTarget) +set(MSVC_LIB_DEPS_LLVMSystemZInfo LLVMSupport) +set(MSVC_LIB_DEPS_LLVMTarget LLVMCore LLVMMC LLVMSupport LLVMSystem) +set(MSVC_LIB_DEPS_LLVMTransformUtils LLVMAnalysis LLVMCore LLVMSupport LLVMSystem LLVMTarget LLVMipa) +set(MSVC_LIB_DEPS_LLVMX86AsmParser LLVMMC LLVMX86Info) +set(MSVC_LIB_DEPS_LLVMX86AsmPrinter LLVMAsmPrinter LLVMCodeGen LLVMCore LLVMMC LLVMSupport LLVMSystem LLVMTarget LLVMX86CodeGen LLVMX86Info) +set(MSVC_LIB_DEPS_LLVMX86CodeGen LLVMCodeGen LLVMCore LLVMMC LLVMSelectionDAG LLVMSupport LLVMSystem LLVMTarget LLVMX86Info) +set(MSVC_LIB_DEPS_LLVMX86Info LLVMSupport) +set(MSVC_LIB_DEPS_LLVMXCore LLVMCodeGen LLVMCore LLVMMC LLVMSelectionDAG LLVMSupport LLVMSystem LLVMTarget LLVMXCoreInfo) +set(MSVC_LIB_DEPS_LLVMXCoreAsmPrinter LLVMAsmPrinter LLVMCodeGen LLVMCore LLVMMC LLVMSupport LLVMSystem LLVMTarget LLVMXCore LLVMXCoreInfo) +set(MSVC_LIB_DEPS_LLVMXCoreInfo LLVMSupport) +set(MSVC_LIB_DEPS_LLVMipa LLVMAnalysis LLVMCore LLVMSupport LLVMSystem) +set(MSVC_LIB_DEPS_LLVMipo LLVMAnalysis LLVMCore LLVMSupport LLVMSystem LLVMTarget LLVMTransformUtils LLVMipa) diff --git a/libclamav/c++/llvm/cmake/modules/LLVMProcessSources.cmake b/libclamav/c++/llvm/cmake/modules/LLVMProcessSources.cmake new file mode 100644 index 000000000..b753735cd --- /dev/null +++ b/libclamav/c++/llvm/cmake/modules/LLVMProcessSources.cmake @@ -0,0 +1,54 @@ +include(AddFileDependencies) + + +macro(add_td_sources srcs) + file(GLOB tds *.td) + if( tds ) + source_group("TableGen descriptions" FILES ${tds}) + set_source_files_properties(${tds} PROPERTIES HEADER_FILE_ONLY ON) + list(APPEND ${srcs} ${tds}) + endif() +endmacro(add_td_sources) + + +macro(add_header_files srcs) + file(GLOB hds *.h) + if( hds ) + set_source_files_properties(${hds} PROPERTIES HEADER_FILE_ONLY ON) + list(APPEND ${srcs} ${hds}) + endif() +endmacro(add_header_files) + + +function(llvm_process_sources OUT_VAR) + set( sources ${ARGN} ) + llvm_check_source_file_list( ${sources} ) + # Create file dependencies on the tablegenned files, if any. Seems + # that this is not strictly needed, as dependencies of the .cpp + # sources on the tablegenned .inc files are detected and handled, + # but just in case... + foreach( s ${sources} ) + set( f ${CMAKE_CURRENT_SOURCE_DIR}/${s} ) + add_file_dependencies( ${f} ${TABLEGEN_OUTPUT} ) + endforeach(s) + if( MSVC_IDE ) + # This adds .td and .h files to the Visual Studio solution: + add_td_sources(sources) + add_header_files(sources) + endif() + set( ${OUT_VAR} ${sources} PARENT_SCOPE ) +endfunction(llvm_process_sources) + + +function(llvm_check_source_file_list) + set(listed ${ARGN}) + file(GLOB globbed *.cpp) + foreach(g ${globbed}) + get_filename_component(fn ${g} NAME) + list(FIND listed ${fn} idx) + if( idx LESS 0 ) + message(SEND_ERROR "Found unknown source file ${g} +Please update ${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt\n") + endif() + endforeach() +endfunction(llvm_check_source_file_list) diff --git a/libclamav/c++/llvm/cmake/modules/TableGen.cmake b/libclamav/c++/llvm/cmake/modules/TableGen.cmake new file mode 100644 index 000000000..f6da1b83c --- /dev/null +++ b/libclamav/c++/llvm/cmake/modules/TableGen.cmake @@ -0,0 +1,20 @@ +# LLVM_TARGET_DEFINITIONS must contain the name of the .td file to process. +# Extra parameters for `tblgen' may come after `ofn' parameter. +# Adds the name of the generated file to TABLEGEN_OUTPUT. + +macro(tablegen ofn) + file(GLOB local_tds "*.td") + file(GLOB_RECURSE global_tds "${LLVM_MAIN_SRC_DIR}/include/llvm/*.td") + + add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${ofn} + COMMAND ${LLVM_TABLEGEN_EXE} ${ARGN} -I ${CMAKE_CURRENT_SOURCE_DIR} + -I ${LLVM_MAIN_SRC_DIR}/lib/Target -I ${LLVM_MAIN_INCLUDE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/${LLVM_TARGET_DEFINITIONS} + -o ${CMAKE_CURRENT_BINARY_DIR}/${ofn} + DEPENDS tblgen ${local_tds} ${global_tds} + COMMENT "Building ${ofn}..." + ) + set(TABLEGEN_OUTPUT ${TABLEGEN_OUTPUT} ${CMAKE_CURRENT_BINARY_DIR}/${ofn}) + set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/${ofn} + PROPERTIES GENERATED 1) +endmacro(tablegen) diff --git a/libclamav/c++/llvm/configure b/libclamav/c++/llvm/configure new file mode 100755 index 000000000..4ef693fa6 --- /dev/null +++ b/libclamav/c++/llvm/configure @@ -0,0 +1,36965 @@ +#! /bin/sh +# Guess values for system-dependent variables and create Makefiles. +# Generated by GNU Autoconf 2.60 for llvm 2.7svn. +# +# Report bugs to . +# +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, +# 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. +# +# Copyright (c) 2003-2009 University of Illinois at Urbana-Champaign. +## --------------------- ## +## M4sh Initialization. ## +## --------------------- ## + +# Be Bourne compatible +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac +fi +BIN_SH=xpg4; export BIN_SH # for Tru64 +DUALCASE=1; export DUALCASE # for MKS sh + + +# PATH needs CR +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + echo "#! /bin/sh" >conf$$.sh + echo "exit 0" >>conf$$.sh + chmod +x conf$$.sh + if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then + PATH_SEPARATOR=';' + else + PATH_SEPARATOR=: + fi + rm -f conf$$.sh +fi + +# Support unset when possible. +if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then + as_unset=unset +else + as_unset=false +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +as_nl=' +' +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +case $0 in + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break +done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + { (exit 1); exit 1; } +fi + +# Work around bugs in pre-3.0 UWIN ksh. +for as_var in ENV MAIL MAILPATH +do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +for as_var in \ + LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ + LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ + LC_TELEPHONE LC_TIME +do + if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then + eval $as_var=C; export $as_var + else + ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var + fi +done + +# Required to use basename. +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + + +# Name of the executable. +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# CDPATH. +$as_unset CDPATH + + +if test "x$CONFIG_SHELL" = x; then + if (eval ":") 2>/dev/null; then + as_have_required=yes +else + as_have_required=no +fi + + if test $as_have_required = yes && (eval ": +(as_func_return () { + (exit \$1) +} +as_func_success () { + as_func_return 0 +} +as_func_failure () { + as_func_return 1 +} +as_func_ret_success () { + return 0 +} +as_func_ret_failure () { + return 1 +} + +exitcode=0 +if as_func_success; then + : +else + exitcode=1 + echo as_func_success failed. +fi + +if as_func_failure; then + exitcode=1 + echo as_func_failure succeeded. +fi + +if as_func_ret_success; then + : +else + exitcode=1 + echo as_func_ret_success failed. +fi + +if as_func_ret_failure; then + exitcode=1 + echo as_func_ret_failure succeeded. +fi + +if ( set x; as_func_ret_success y && test x = \"\$1\" ); then + : +else + exitcode=1 + echo positional parameters were not saved. +fi + +test \$exitcode = 0) || { (exit 1); exit 1; } + +( + as_lineno_1=\$LINENO + as_lineno_2=\$LINENO + test \"x\$as_lineno_1\" != \"x\$as_lineno_2\" && + test \"x\`expr \$as_lineno_1 + 1\`\" = \"x\$as_lineno_2\") || { (exit 1); exit 1; } +") 2> /dev/null; then + : +else + as_candidate_shells= + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in /usr/bin/posix$PATH_SEPARATOR/bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + case $as_dir in + /*) + for as_base in sh bash ksh sh5; do + as_candidate_shells="$as_candidate_shells $as_dir/$as_base" + done;; + esac +done +IFS=$as_save_IFS + + + for as_shell in $as_candidate_shells $SHELL; do + # Try only shells that exist, to save several forks. + if { test -f "$as_shell" || test -f "$as_shell.exe"; } && + { ("$as_shell") 2> /dev/null <<\_ASEOF +# Be Bourne compatible +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac +fi +BIN_SH=xpg4; export BIN_SH # for Tru64 +DUALCASE=1; export DUALCASE # for MKS sh + +: +_ASEOF +}; then + CONFIG_SHELL=$as_shell + as_have_required=yes + if { "$as_shell" 2> /dev/null <<\_ASEOF +# Be Bourne compatible +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac +fi +BIN_SH=xpg4; export BIN_SH # for Tru64 +DUALCASE=1; export DUALCASE # for MKS sh + +: +(as_func_return () { + (exit $1) +} +as_func_success () { + as_func_return 0 +} +as_func_failure () { + as_func_return 1 +} +as_func_ret_success () { + return 0 +} +as_func_ret_failure () { + return 1 +} + +exitcode=0 +if as_func_success; then + : +else + exitcode=1 + echo as_func_success failed. +fi + +if as_func_failure; then + exitcode=1 + echo as_func_failure succeeded. +fi + +if as_func_ret_success; then + : +else + exitcode=1 + echo as_func_ret_success failed. +fi + +if as_func_ret_failure; then + exitcode=1 + echo as_func_ret_failure succeeded. +fi + +if ( set x; as_func_ret_success y && test x = "$1" ); then + : +else + exitcode=1 + echo positional parameters were not saved. +fi + +test $exitcode = 0) || { (exit 1); exit 1; } + +( + as_lineno_1=$LINENO + as_lineno_2=$LINENO + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2") || { (exit 1); exit 1; } + +_ASEOF +}; then + break +fi + +fi + + done + + if test "x$CONFIG_SHELL" != x; then + for as_var in BASH_ENV ENV + do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var + done + export CONFIG_SHELL + exec "$CONFIG_SHELL" "$as_myself" ${1+"$@"} +fi + + + if test $as_have_required = no; then + echo This script requires a shell more modern than all the + echo shells that I found on your system. Please install a + echo modern shell, or manually run the script under such a + echo shell if you do have one. + { (exit 1); exit 1; } +fi + + +fi + +fi + + + +(eval "as_func_return () { + (exit \$1) +} +as_func_success () { + as_func_return 0 +} +as_func_failure () { + as_func_return 1 +} +as_func_ret_success () { + return 0 +} +as_func_ret_failure () { + return 1 +} + +exitcode=0 +if as_func_success; then + : +else + exitcode=1 + echo as_func_success failed. +fi + +if as_func_failure; then + exitcode=1 + echo as_func_failure succeeded. +fi + +if as_func_ret_success; then + : +else + exitcode=1 + echo as_func_ret_success failed. +fi + +if as_func_ret_failure; then + exitcode=1 + echo as_func_ret_failure succeeded. +fi + +if ( set x; as_func_ret_success y && test x = \"\$1\" ); then + : +else + exitcode=1 + echo positional parameters were not saved. +fi + +test \$exitcode = 0") || { + echo No shell found that supports shell functions. + echo Please tell autoconf@gnu.org about your system, + echo including any error possibly output before this + echo message +} + + + + as_lineno_1=$LINENO + as_lineno_2=$LINENO + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || { + + # Create $as_me.lineno as a copy of $as_myself, but with $LINENO + # uniformly replaced by the line number. The first 'sed' inserts a + # line-number line after each line using $LINENO; the second 'sed' + # does the real work. The second script uses 'N' to pair each + # line-number line with the line containing $LINENO, and appends + # trailing '-' during substitution so that $LINENO is not a special + # case at line end. + # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the + # scripts with optimization help from Paolo Bonzini. Blame Lee + # E. McMahon (1931-1989) for sed's syntax. :-) + sed -n ' + p + /[$]LINENO/= + ' <$as_myself | + sed ' + s/[$]LINENO.*/&-/ + t lineno + b + :lineno + N + :loop + s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ + t loop + s/-\n.*// + ' >$as_me.lineno && + chmod +x "$as_me.lineno" || + { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2 + { (exit 1); exit 1; }; } + + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensitive to this). + . "./$as_me.lineno" + # Exit status is that of the last command. + exit +} + + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in +-n*) + case `echo 'x\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + *) ECHO_C='\c';; + esac;; +*) + ECHO_N='-n';; +esac + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir +fi +echo >conf$$.file +if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -p'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -p' +elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln +else + as_ln_s='cp -p' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + +if mkdir -p . 2>/dev/null; then + as_mkdir_p=: +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +# Find out whether ``test -x'' works. Don't use a zero-byte file, as +# systems may use methods other than mode bits to determine executability. +cat >conf$$.file <<_ASEOF +#! /bin/sh +exit 0 +_ASEOF +chmod +x conf$$.file +if test -x conf$$.file >/dev/null 2>&1; then + as_executable_p="test -x" +else + as_executable_p=: +fi +rm -f conf$$.file + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + + + +# Check that we are running under the correct shell. +SHELL=${CONFIG_SHELL-/bin/sh} + +case X$ECHO in +X*--fallback-echo) + # Remove one level of quotation (which was required for Make). + ECHO=`echo "$ECHO" | sed 's,\\\\\$\\$0,'$0','` + ;; +esac + +echo=${ECHO-echo} +if test "X$1" = X--no-reexec; then + # Discard the --no-reexec flag, and continue. + shift +elif test "X$1" = X--fallback-echo; then + # Avoid inline document here, it may be left over + : +elif test "X`($echo '\t') 2>/dev/null`" = 'X\t' ; then + # Yippee, $echo works! + : +else + # Restart under the correct shell. + exec $SHELL "$0" --no-reexec ${1+"$@"} +fi + +if test "X$1" = X--fallback-echo; then + # used as fallback echo + shift + cat </dev/null 2>&1 && unset CDPATH + +if test -z "$ECHO"; then +if test "X${echo_test_string+set}" != Xset; then +# find a string as large as possible, as long as the shell can cope with it + for cmd in 'sed 50q "$0"' 'sed 20q "$0"' 'sed 10q "$0"' 'sed 2q "$0"' 'echo test'; do + # expected sizes: less than 2Kb, 1Kb, 512 bytes, 16 bytes, ... + if (echo_test_string=`eval $cmd`) 2>/dev/null && + echo_test_string=`eval $cmd` && + (test "X$echo_test_string" = "X$echo_test_string") 2>/dev/null + then + break + fi + done +fi + +if test "X`($echo '\t') 2>/dev/null`" = 'X\t' && + echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + : +else + # The Solaris, AIX, and Digital Unix default echo programs unquote + # backslashes. This makes it impossible to quote backslashes using + # echo "$something" | sed 's/\\/\\\\/g' + # + # So, first we look for a working echo in the user's PATH. + + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for dir in $PATH /usr/ucb; do + IFS="$lt_save_ifs" + if (test -f $dir/echo || test -f $dir/echo$ac_exeext) && + test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' && + echo_testing_string=`($dir/echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + echo="$dir/echo" + break + fi + done + IFS="$lt_save_ifs" + + if test "X$echo" = Xecho; then + # We didn't find a better echo, so look for alternatives. + if test "X`(print -r '\t') 2>/dev/null`" = 'X\t' && + echo_testing_string=`(print -r "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + # This shell has a builtin print -r that does the trick. + echo='print -r' + elif (test -f /bin/ksh || test -f /bin/ksh$ac_exeext) && + test "X$CONFIG_SHELL" != X/bin/ksh; then + # If we have ksh, try running configure again with it. + ORIGINAL_CONFIG_SHELL=${CONFIG_SHELL-/bin/sh} + export ORIGINAL_CONFIG_SHELL + CONFIG_SHELL=/bin/ksh + export CONFIG_SHELL + exec $CONFIG_SHELL "$0" --no-reexec ${1+"$@"} + else + # Try using printf. + echo='printf %s\n' + if test "X`($echo '\t') 2>/dev/null`" = 'X\t' && + echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + # Cool, printf works + : + elif echo_testing_string=`($ORIGINAL_CONFIG_SHELL "$0" --fallback-echo '\t') 2>/dev/null` && + test "X$echo_testing_string" = 'X\t' && + echo_testing_string=`($ORIGINAL_CONFIG_SHELL "$0" --fallback-echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + CONFIG_SHELL=$ORIGINAL_CONFIG_SHELL + export CONFIG_SHELL + SHELL="$CONFIG_SHELL" + export SHELL + echo="$CONFIG_SHELL $0 --fallback-echo" + elif echo_testing_string=`($CONFIG_SHELL "$0" --fallback-echo '\t') 2>/dev/null` && + test "X$echo_testing_string" = 'X\t' && + echo_testing_string=`($CONFIG_SHELL "$0" --fallback-echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + echo="$CONFIG_SHELL $0 --fallback-echo" + else + # maybe with a smaller string... + prev=: + + for cmd in 'echo test' 'sed 2q "$0"' 'sed 10q "$0"' 'sed 20q "$0"' 'sed 50q "$0"'; do + if (test "X$echo_test_string" = "X`eval $cmd`") 2>/dev/null + then + break + fi + prev="$cmd" + done + + if test "$prev" != 'sed 50q "$0"'; then + echo_test_string=`eval $prev` + export echo_test_string + exec ${ORIGINAL_CONFIG_SHELL-${CONFIG_SHELL-/bin/sh}} "$0" ${1+"$@"} + else + # Oops. We lost completely, so just stick with echo. + echo=echo + fi + fi + fi + fi +fi +fi + +# Copy echo and quote the copy suitably for passing to libtool from +# the Makefile, instead of quoting the original, which is used later. +ECHO=$echo +if test "X$ECHO" = "X$CONFIG_SHELL $0 --fallback-echo"; then + ECHO="$CONFIG_SHELL \\\$\$0 --fallback-echo" +fi + + + + +tagnames=${tagnames+${tagnames},}CXX + +tagnames=${tagnames+${tagnames},}F77 + +exec 7<&0 &1 + +# Name of the host. +# hostname on some systems (SVR3.2, Linux) returns a bogus exit status, +# so uname gets run too. +ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` + +# +# Initializations. +# +ac_default_prefix=/usr/local +ac_clean_files= +ac_config_libobj_dir=. +LIBOBJS= +cross_compiling=no +subdirs= +MFLAGS= +MAKEFLAGS= +SHELL=${CONFIG_SHELL-/bin/sh} + +# Identity of this package. +PACKAGE_NAME='llvm' +PACKAGE_TARNAME='-llvm-' +PACKAGE_VERSION='2.7svn' +PACKAGE_STRING='llvm 2.7svn' +PACKAGE_BUGREPORT='llvmbugs@cs.uiuc.edu' + +ac_unique_file="lib/VMCore/Module.cpp" +# Factoring default headers for most tests. +ac_includes_default="\ +#include +#if HAVE_SYS_TYPES_H +# include +#endif +#if HAVE_SYS_STAT_H +# include +#endif +#if STDC_HEADERS +# include +# include +#else +# if HAVE_STDLIB_H +# include +# endif +#endif +#if HAVE_STRING_H +# if !STDC_HEADERS && HAVE_MEMORY_H +# include +# endif +# include +#endif +#if HAVE_STRINGS_H +# include +#endif +#if HAVE_INTTYPES_H +# include +#endif +#if HAVE_STDINT_H +# include +#endif +#if HAVE_UNISTD_H +# include +#endif" + +ac_subst_vars='SHELL +PATH_SEPARATOR +PACKAGE_NAME +PACKAGE_TARNAME +PACKAGE_VERSION +PACKAGE_STRING +PACKAGE_BUGREPORT +exec_prefix +prefix +program_transform_name +bindir +sbindir +libexecdir +datarootdir +datadir +sysconfdir +sharedstatedir +localstatedir +includedir +oldincludedir +docdir +infodir +htmldir +dvidir +pdfdir +psdir +libdir +localedir +mandir +DEFS +ECHO_C +ECHO_N +ECHO_T +LIBS +build_alias +host_alias +target_alias +LLVM_COPYRIGHT +subdirs +build +build_cpu +build_vendor +build_os +host +host_cpu +host_vendor +host_os +target +target_cpu +target_vendor +target_os +OS +HOST_OS +TARGET_OS +LINKALL +NOLINKALL +LLVM_ON_UNIX +LLVM_ON_WIN32 +ARCH +ENDIAN +CC +CFLAGS +LDFLAGS +CPPFLAGS +ac_ct_CC +EXEEXT +OBJEXT +CPP +GREP +EGREP +LLVM_CROSS_COMPILING +BUILD_CC +BUILD_EXEEXT +BUILD_CXX +CVSBUILD +ENABLE_OPTIMIZED +ENABLE_PROFILING +DISABLE_ASSERTIONS +ENABLE_EXPENSIVE_CHECKS +EXPENSIVE_CHECKS +DEBUG_RUNTIME +DEBUG_SYMBOLS +JIT +TARGET_HAS_JIT +ENABLE_DOXYGEN +ENABLE_THREADS +ENABLE_PIC +TARGETS_TO_BUILD +LLVM_ENUM_TARGETS +LLVM_ENUM_ASM_PRINTERS +LLVM_ENUM_ASM_PARSERS +LLVM_ENUM_DISASSEMBLERS +ENABLE_CBE_PRINTF_A +OPTIMIZE_OPTION +EXTRA_OPTIONS +BINUTILS_INCDIR +ENABLE_LLVMC_DYNAMIC +ENABLE_LLVMC_DYNAMIC_PLUGINS +CXX +CXXFLAGS +ac_ct_CXX +NM +ifGNUmake +LN_S +CMP +CP +DATE +FIND +MKDIR +MV +RANLIB +RM +SED +TAR +BINPWD +GRAPHVIZ +DOT +FDP +NEATO +TWOPI +CIRCO +GV +DOTTY +PERL +HAVE_PERL +INSTALL_PROGRAM +INSTALL_SCRIPT +INSTALL_DATA +BZIP2 +DOXYGEN +GROFF +GZIP +POD2HTML +POD2MAN +RUNTEST +TCLSH +ZIP +OCAMLC +OCAMLOPT +OCAMLDEP +OCAMLDOC +GAS +INSTALL_LTDL_TRUE +INSTALL_LTDL_FALSE +CONVENIENCE_LTDL_TRUE +CONVENIENCE_LTDL_FALSE +LIBADD_DL +ECHO +AR +STRIP +CXXCPP +F77 +FFLAGS +ac_ct_F77 +LIBTOOL +LLVMGCCCOMMAND +LLVMGXXCOMMAND +LLVMGCC +LLVMGXX +NO_VARIADIC_MACROS +NO_MISSING_FIELD_INITIALIZERS +USE_UDIS86 +USE_OPROFILE +HAVE_PTHREAD +HUGE_VAL_SANITY +ALLOCA +MMAP_FILE +LLVMCC1 +LLVMCC1PLUS +LLVMGCCDIR +LLVMGCCLIBEXEC +LLVMGCC_VERSION +LLVMGCC_MAJVERS +LLVMGCC_LANGS +SHLIBEXT +LLVM_PREFIX +LLVM_BINDIR +LLVM_LIBDIR +LLVM_DATADIR +LLVM_DOCSDIR +LLVM_ETCDIR +LLVM_INCLUDEDIR +LLVM_INFODIR +LLVM_MANDIR +LLVM_CONFIGTIME +BINDINGS_TO_BUILD +ALL_BINDINGS +OCAML_LIBDIR +ENABLE_VISIBILITY_INLINES_HIDDEN +RPATH +RDYNAMIC +LIBOBJS +LTLIBOBJS' +ac_subst_files='' + ac_precious_vars='build_alias +host_alias +target_alias +CC +CFLAGS +LDFLAGS +CPPFLAGS +CPP +CXX +CXXFLAGS +CCC +CXXCPP +F77 +FFLAGS' +ac_subdirs_all='projects/sample +projects/privbracket +projects/llvm-stacker +projects/llvm-test +projects/test-suite +projects/llvm-reopt +projects/llvm-gcc +projects/llvm-java +projects/llvm-tv +projects/llvm-poolalloc +projects/poolalloc +projects/llvm-kernel' + +# Initialize some variables set by options. +ac_init_help= +ac_init_version=false +# The variables have the same names as the options, with +# dashes changed to underlines. +cache_file=/dev/null +exec_prefix=NONE +no_create= +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +verbose= +x_includes=NONE +x_libraries=NONE + +# Installation directory options. +# These are left unexpanded so users can "make install exec_prefix=/foo" +# and all the variables that are supposed to be based on exec_prefix +# by default will actually change. +# Use braces instead of parens because sh, perl, etc. also accept them. +# (The list follows the same order as the GNU Coding Standards.) +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datarootdir='${prefix}/share' +datadir='${datarootdir}' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +includedir='${prefix}/include' +oldincludedir='/usr/include' +docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' +infodir='${datarootdir}/info' +htmldir='${docdir}' +dvidir='${docdir}' +pdfdir='${docdir}' +psdir='${docdir}' +libdir='${exec_prefix}/lib' +localedir='${datarootdir}/locale' +mandir='${datarootdir}/man' + +ac_prev= +ac_dashdash= +for ac_option +do + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval $ac_prev=\$ac_option + ac_prev= + continue + fi + + case $ac_option in + *=*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; + *) ac_optarg=yes ;; + esac + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case $ac_dashdash$ac_option in + --) + ac_dashdash=yes ;; + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir=$ac_optarg ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build_alias ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build_alias=$ac_optarg ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file=$ac_optarg ;; + + --config-cache | -C) + cache_file=config.cache ;; + + -datadir | --datadir | --datadi | --datad) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=*) + datadir=$ac_optarg ;; + + -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ + | --dataroo | --dataro | --datar) + ac_prev=datarootdir ;; + -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ + | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) + datarootdir=$ac_optarg ;; + + -disable-* | --disable-*) + ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid feature name: $ac_feature" >&2 + { (exit 1); exit 1; }; } + ac_feature=`echo $ac_feature | sed 's/-/_/g'` + eval enable_$ac_feature=no ;; + + -docdir | --docdir | --docdi | --doc | --do) + ac_prev=docdir ;; + -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) + docdir=$ac_optarg ;; + + -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) + ac_prev=dvidir ;; + -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) + dvidir=$ac_optarg ;; + + -enable-* | --enable-*) + ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid feature name: $ac_feature" >&2 + { (exit 1); exit 1; }; } + ac_feature=`echo $ac_feature | sed 's/-/_/g'` + eval enable_$ac_feature=\$ac_optarg ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix=$ac_optarg ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he | -h) + ac_init_help=long ;; + -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) + ac_init_help=recursive ;; + -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) + ac_init_help=short ;; + + -host | --host | --hos | --ho) + ac_prev=host_alias ;; + -host=* | --host=* | --hos=* | --ho=*) + host_alias=$ac_optarg ;; + + -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) + ac_prev=htmldir ;; + -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ + | --ht=*) + htmldir=$ac_optarg ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir=$ac_optarg ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir=$ac_optarg ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir=$ac_optarg ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir=$ac_optarg ;; + + -localedir | --localedir | --localedi | --localed | --locale) + ac_prev=localedir ;; + -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) + localedir=$ac_optarg ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst | --locals) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) + localstatedir=$ac_optarg ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir=$ac_optarg ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c | -n) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir=$ac_optarg ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix=$ac_optarg ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix=$ac_optarg ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix=$ac_optarg ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name=$ac_optarg ;; + + -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) + ac_prev=pdfdir ;; + -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) + pdfdir=$ac_optarg ;; + + -psdir | --psdir | --psdi | --psd | --ps) + ac_prev=psdir ;; + -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) + psdir=$ac_optarg ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir=$ac_optarg ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir=$ac_optarg ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site=$ac_optarg ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir=$ac_optarg ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir=$ac_optarg ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target_alias ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target_alias=$ac_optarg ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers | -V) + ac_init_version=: ;; + + -with-* | --with-*) + ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid package name: $ac_package" >&2 + { (exit 1); exit 1; }; } + ac_package=`echo $ac_package| sed 's/-/_/g'` + eval with_$ac_package=\$ac_optarg ;; + + -without-* | --without-*) + ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid package name: $ac_package" >&2 + { (exit 1); exit 1; }; } + ac_package=`echo $ac_package | sed 's/-/_/g'` + eval with_$ac_package=no ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes=$ac_optarg ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries=$ac_optarg ;; + + -*) { echo "$as_me: error: unrecognized option: $ac_option +Try \`$0 --help' for more information." >&2 + { (exit 1); exit 1; }; } + ;; + + *=*) + ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` + # Reject names that are not valid shell variable names. + expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid variable name: $ac_envvar" >&2 + { (exit 1); exit 1; }; } + eval $ac_envvar=\$ac_optarg + export $ac_envvar ;; + + *) + # FIXME: should be removed in autoconf 3.0. + echo "$as_me: WARNING: you should use --build, --host, --target" >&2 + expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && + echo "$as_me: WARNING: invalid host type: $ac_option" >&2 + : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option} + ;; + + esac +done + +if test -n "$ac_prev"; then + ac_option=--`echo $ac_prev | sed 's/_/-/g'` + { echo "$as_me: error: missing argument to $ac_option" >&2 + { (exit 1); exit 1; }; } +fi + +# Be sure to have absolute directory names. +for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ + datadir sysconfdir sharedstatedir localstatedir includedir \ + oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ + libdir localedir mandir +do + eval ac_val=\$$ac_var + case $ac_val in + [\\/$]* | ?:[\\/]* ) continue;; + NONE | '' ) case $ac_var in *prefix ) continue;; esac;; + esac + { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 + { (exit 1); exit 1; }; } +done + +# There might be people who depend on the old broken behavior: `$host' +# used to hold the argument of --host etc. +# FIXME: To remove some day. +build=$build_alias +host=$host_alias +target=$target_alias + +# FIXME: To remove some day. +if test "x$host_alias" != x; then + if test "x$build_alias" = x; then + cross_compiling=maybe + echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host. + If a cross compiler is detected then cross compile mode will be used." >&2 + elif test "x$build_alias" != "x$host_alias"; then + cross_compiling=yes + fi +fi + +ac_tool_prefix= +test -n "$host_alias" && ac_tool_prefix=$host_alias- + +test "$silent" = yes && exec 6>/dev/null + + +ac_pwd=`pwd` && test -n "$ac_pwd" && +ac_ls_di=`ls -di .` && +ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || + { echo "$as_me: error: Working directory cannot be determined" >&2 + { (exit 1); exit 1; }; } +test "X$ac_ls_di" = "X$ac_pwd_ls_di" || + { echo "$as_me: error: pwd does not report name of working directory" >&2 + { (exit 1); exit 1; }; } + + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then the parent directory. + ac_confdir=`$as_dirname -- "$0" || +$as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$0" : 'X\(//\)[^/]' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +echo X"$0" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + srcdir=$ac_confdir + if test ! -r "$srcdir/$ac_unique_file"; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r "$srcdir/$ac_unique_file"; then + test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." + { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2 + { (exit 1); exit 1; }; } +fi +ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" +ac_abs_confdir=`( + cd "$srcdir" && test -r "./$ac_unique_file" || { echo "$as_me: error: $ac_msg" >&2 + { (exit 1); exit 1; }; } + pwd)` +# When building in place, set srcdir=. +if test "$ac_abs_confdir" = "$ac_pwd"; then + srcdir=. +fi +# Remove unnecessary trailing slashes from srcdir. +# Double slashes in file names in object file debugging info +# mess up M-x gdb in Emacs. +case $srcdir in +*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; +esac +for ac_var in $ac_precious_vars; do + eval ac_env_${ac_var}_set=\${${ac_var}+set} + eval ac_env_${ac_var}_value=\$${ac_var} + eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} + eval ac_cv_env_${ac_var}_value=\$${ac_var} +done + +# +# Report the --help message. +# +if test "$ac_init_help" = "long"; then + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat <<_ACEOF +\`configure' configures llvm 2.7svn to adapt to many kinds of systems. + +Usage: $0 [OPTION]... [VAR=VALUE]... + +To assign environment variables (e.g., CC, CFLAGS...), specify them as +VAR=VALUE. See below for descriptions of some of the useful variables. + +Defaults for the options are specified in brackets. + +Configuration: + -h, --help display this help and exit + --help=short display options specific to this package + --help=recursive display the short help of all the included packages + -V, --version display version information and exit + -q, --quiet, --silent do not print \`checking...' messages + --cache-file=FILE cache test results in FILE [disabled] + -C, --config-cache alias for \`--cache-file=config.cache' + -n, --no-create do not create output files + --srcdir=DIR find the sources in DIR [configure dir or \`..'] + +Installation directories: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [PREFIX] + +By default, \`make install' will install all the files in +\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify +an installation prefix other than \`$ac_default_prefix' using \`--prefix', +for instance \`--prefix=\$HOME'. + +For better control, use the options below. + +Fine tuning of the installation directories: + --bindir=DIR user executables [EPREFIX/bin] + --sbindir=DIR system admin executables [EPREFIX/sbin] + --libexecdir=DIR program executables [EPREFIX/libexec] + --sysconfdir=DIR read-only single-machine data [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] + --localstatedir=DIR modifiable single-machine data [PREFIX/var] + --libdir=DIR object code libraries [EPREFIX/lib] + --includedir=DIR C header files [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc [/usr/include] + --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] + --datadir=DIR read-only architecture-independent data [DATAROOTDIR] + --infodir=DIR info documentation [DATAROOTDIR/info] + --localedir=DIR locale-dependent data [DATAROOTDIR/locale] + --mandir=DIR man documentation [DATAROOTDIR/man] + --docdir=DIR documentation root [DATAROOTDIR/doc/-llvm-] + --htmldir=DIR html documentation [DOCDIR] + --dvidir=DIR dvi documentation [DOCDIR] + --pdfdir=DIR pdf documentation [DOCDIR] + --psdir=DIR ps documentation [DOCDIR] +_ACEOF + + cat <<\_ACEOF + +System types: + --build=BUILD configure for building on BUILD [guessed] + --host=HOST cross-compile to build programs to run on HOST [BUILD] + --target=TARGET configure for building compilers for TARGET [HOST] +_ACEOF +fi + +if test -n "$ac_init_help"; then + case $ac_init_help in + short | recursive ) echo "Configuration of llvm 2.7svn:";; + esac + cat <<\_ACEOF + +Optional Features: + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --enable-optimized Compile with optimizations enabled (default is NO) + --enable-profiling Compile with profiling enabled (default is NO) + --enable-assertions Compile with assertion checks enabled (default is + YES) + --enable-expensive-checks + Compile with expensive debug checks enabled (default + is NO) + --enable-debug-runtime Build runtime libs with debug symbols (default is + NO) + --enable-debug-symbols Build compiler with debug symbols (default is NO if + optimization is on and YES if it's off) + --enable-jit Enable Just In Time Compiling (default is YES) + --enable-doxygen Build doxygen documentation (default is NO) + --enable-threads Use threads if available (default is YES) + --enable-pic Build LLVM with Position Independent Code (default + is YES) + --enable-targets Build specific host targets: all or + target1,target2,... Valid targets are: host, x86, + x86_64, sparc, powerpc, alpha, arm, mips, spu, + pic16, xcore, msp430, systemz, blackfin, cbe, msil, + and cpp (default=all) + --enable-cbe-printf-a Enable C Backend output with hex floating point via + %a (default is YES) + --enable-bindings Build specific language bindings: + all,auto,none,{binding-name} (default=auto) + --enable-libffi Check for the presence of libffi (default is YES) + --enable-llvmc-dynamic Link LLVMC dynamically (default is NO, unless on + Win32) + --enable-llvmc-dynamic-plugins + Enable dynamic LLVMC plugins (default is YES) + --enable-ltdl-install install libltdl + --enable-shared[=PKGS] build shared libraries + [default=yes] + --enable-static[=PKGS] build static libraries + [default=yes] + --enable-fast-install[=PKGS] + optimize for fast installation + [default=yes] + --disable-libtool-lock avoid locking (might break parallel builds) + +Optional Packages: + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --with-llvmgccdir Specify location of llvm-gcc install dir (default + searches PATH) + --with-llvmgcc Specify location of llvm-gcc driver (default + searches PATH) + --with-llvmgxx Specify location of llvm-g++ driver (default + searches PATH) + --with-optimize-option Select the compiler options to use for optimized + builds + --with-extra-options Specify additional options to compile LLVM with + --with-ocaml-libdir Specify install location for ocaml bindings (default + is stdlib) + --with-c-include-dirs Colon separated list of directories clang will + search for headers + --with-cxx-include-root Directory with the libstdc++ headers. + --with-cxx-include-arch Architecture of the libstdc++ headers. + --with-cxx-include-32bit-dir + 32 bit multilib dir. + --with-cxx-include-64bit-dir + 64 bit multilib directory. + --with-binutils-include Specify path to binutils/include/ containing + plugin-api.h file for gold plugin. + --with-tclinclude directory where tcl headers are + --with-gnu-ld assume the C compiler uses GNU ld [default=no] + --with-pic try to use only PIC/non-PIC objects [default=use + both] + --with-tags[=TAGS] include additional configurations [automatic] + --with-udis86= Use udis86 external x86 disassembler library + --with-oprofile= + Tell OProfile >= 0.9.4 how to symbolize JIT output + +Some influential environment variables: + CC C compiler command + CFLAGS C compiler flags + LDFLAGS linker flags, e.g. -L if you have libraries in a + nonstandard directory + CPPFLAGS C/C++/Objective C preprocessor flags, e.g. -I if + you have headers in a nonstandard directory + CPP C preprocessor + CXX C++ compiler command + CXXFLAGS C++ compiler flags + CXXCPP C++ preprocessor + F77 Fortran 77 compiler command + FFLAGS Fortran 77 compiler flags + +Use these variables to override the choices made by `configure' or to help +it to find libraries and programs with nonstandard names/locations. + +Report bugs to . +_ACEOF +ac_status=$? +fi + +if test "$ac_init_help" = "recursive"; then + # If there are subdirs, report their specific --help. + for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue + test -d "$ac_dir" || continue + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,/..,g;s,/,,'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + cd "$ac_dir" || { ac_status=$?; continue; } + # Check for guested configure. + if test -f "$ac_srcdir/configure.gnu"; then + echo && + $SHELL "$ac_srcdir/configure.gnu" --help=recursive + elif test -f "$ac_srcdir/configure"; then + echo && + $SHELL "$ac_srcdir/configure" --help=recursive + else + echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 + fi || ac_status=$? + cd "$ac_pwd" || { ac_status=$?; break; } + done +fi + +test -n "$ac_init_help" && exit $ac_status +if $ac_init_version; then + cat <<\_ACEOF +llvm configure 2.7svn +generated by GNU Autoconf 2.60 + +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, +2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. +This configure script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it. + +Copyright (c) 2003-2009 University of Illinois at Urbana-Champaign. +_ACEOF + exit +fi +cat >config.log <<_ACEOF +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. + +It was created by llvm $as_me 2.7svn, which was +generated by GNU Autoconf 2.60. Invocation command line was + + $ $0 $@ + +_ACEOF +exec 5>>config.log +{ +cat <<_ASUNAME +## --------- ## +## Platform. ## +## --------- ## + +hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` + +/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` +/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` +/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` +/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` + +_ASUNAME + +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + echo "PATH: $as_dir" +done +IFS=$as_save_IFS + +} >&5 + +cat >&5 <<_ACEOF + + +## ----------- ## +## Core tests. ## +## ----------- ## + +_ACEOF + + +# Keep a trace of the command line. +# Strip out --no-create and --no-recursion so they do not pile up. +# Strip out --silent because we don't want to record it for future runs. +# Also quote any args containing shell meta-characters. +# Make two passes to allow for proper duplicate-argument suppression. +ac_configure_args= +ac_configure_args0= +ac_configure_args1= +ac_must_keep_next=false +for ac_pass in 1 2 +do + for ac_arg + do + case $ac_arg in + -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + continue ;; + *\'*) + ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + case $ac_pass in + 1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;; + 2) + ac_configure_args1="$ac_configure_args1 '$ac_arg'" + if test $ac_must_keep_next = true; then + ac_must_keep_next=false # Got value, back to normal. + else + case $ac_arg in + *=* | --config-cache | -C | -disable-* | --disable-* \ + | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ + | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ + | -with-* | --with-* | -without-* | --without-* | --x) + case "$ac_configure_args0 " in + "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; + esac + ;; + -* ) ac_must_keep_next=true ;; + esac + fi + ac_configure_args="$ac_configure_args '$ac_arg'" + ;; + esac + done +done +$as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; } +$as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; } + +# When interrupted or exit'd, cleanup temporary files, and complete +# config.log. We remove comments because anyway the quotes in there +# would cause problems or look ugly. +# WARNING: Use '\'' to represent an apostrophe within the trap. +# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. +trap 'exit_status=$? + # Save into config.log some information that might help in debugging. + { + echo + + cat <<\_ASBOX +## ---------------- ## +## Cache variables. ## +## ---------------- ## +_ASBOX + echo + # The following way of writing the cache mishandles newlines in values, +( + for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5 +echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + *) $as_unset $ac_var ;; + esac ;; + esac + done + (set) 2>&1 | + case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + sed -n \ + "s/'\''/'\''\\\\'\'''\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" + ;; #( + *) + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) + echo + + cat <<\_ASBOX +## ----------------- ## +## Output variables. ## +## ----------------- ## +_ASBOX + echo + for ac_var in $ac_subst_vars + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + echo "$ac_var='\''$ac_val'\''" + done | sort + echo + + if test -n "$ac_subst_files"; then + cat <<\_ASBOX +## ------------------- ## +## File substitutions. ## +## ------------------- ## +_ASBOX + echo + for ac_var in $ac_subst_files + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + echo "$ac_var='\''$ac_val'\''" + done | sort + echo + fi + + if test -s confdefs.h; then + cat <<\_ASBOX +## ----------- ## +## confdefs.h. ## +## ----------- ## +_ASBOX + echo + cat confdefs.h + echo + fi + test "$ac_signal" != 0 && + echo "$as_me: caught signal $ac_signal" + echo "$as_me: exit $exit_status" + } >&5 + rm -f core *.core core.conftest.* && + rm -f -r conftest* confdefs* conf$$* $ac_clean_files && + exit $exit_status +' 0 +for ac_signal in 1 2 13 15; do + trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal +done +ac_signal=0 + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -f -r conftest* confdefs.h + +# Predefined preprocessor variables. + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_NAME "$PACKAGE_NAME" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_TARNAME "$PACKAGE_TARNAME" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_VERSION "$PACKAGE_VERSION" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_STRING "$PACKAGE_STRING" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" +_ACEOF + + +# Let the site file select an alternate cache file if it wants to. +# Prefer explicitly selected file to automatically selected ones. +if test -n "$CONFIG_SITE"; then + set x "$CONFIG_SITE" +elif test "x$prefix" != xNONE; then + set x "$prefix/share/config.site" "$prefix/etc/config.site" +else + set x "$ac_default_prefix/share/config.site" \ + "$ac_default_prefix/etc/config.site" +fi +shift +for ac_site_file +do + if test -r "$ac_site_file"; then + { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5 +echo "$as_me: loading site script $ac_site_file" >&6;} + sed 's/^/| /' "$ac_site_file" >&5 + . "$ac_site_file" + fi +done + +if test -r "$cache_file"; then + # Some versions of bash will fail to source /dev/null (special + # files actually), so we avoid doing that. + if test -f "$cache_file"; then + { echo "$as_me:$LINENO: loading cache $cache_file" >&5 +echo "$as_me: loading cache $cache_file" >&6;} + case $cache_file in + [\\/]* | ?:[\\/]* ) . "$cache_file";; + *) . "./$cache_file";; + esac + fi +else + { echo "$as_me:$LINENO: creating cache $cache_file" >&5 +echo "$as_me: creating cache $cache_file" >&6;} + >$cache_file +fi + +# Check that the precious variables saved in the cache have kept the same +# value. +ac_cache_corrupted=false +for ac_var in $ac_precious_vars; do + eval ac_old_set=\$ac_cv_env_${ac_var}_set + eval ac_new_set=\$ac_env_${ac_var}_set + eval ac_old_val=\$ac_cv_env_${ac_var}_value + eval ac_new_val=\$ac_env_${ac_var}_value + case $ac_old_set,$ac_new_set in + set,) + { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 +echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,set) + { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5 +echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,);; + *) + if test "x$ac_old_val" != "x$ac_new_val"; then + { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5 +echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} + { echo "$as_me:$LINENO: former value: $ac_old_val" >&5 +echo "$as_me: former value: $ac_old_val" >&2;} + { echo "$as_me:$LINENO: current value: $ac_new_val" >&5 +echo "$as_me: current value: $ac_new_val" >&2;} + ac_cache_corrupted=: + fi;; + esac + # Pass precious variables to config.status. + if test "$ac_new_set" = set; then + case $ac_new_val in + *\'*) ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; + *) ac_arg=$ac_var=$ac_new_val ;; + esac + case " $ac_configure_args " in + *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. + *) ac_configure_args="$ac_configure_args '$ac_arg'" ;; + esac + fi +done +if $ac_cache_corrupted; then + { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5 +echo "$as_me: error: changes in the environment can compromise the build" >&2;} + { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5 +echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;} + { (exit 1); exit 1; }; } +fi + + + + + + + + + + + + + + + + + + + + + + + + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + +LLVM_COPYRIGHT="Copyright (c) 2003-2009 University of Illinois at Urbana-Champaign." + + + + + + + +ac_aux_dir= +for ac_dir in autoconf "$srcdir"/autoconf; do + if test -f "$ac_dir/install-sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f "$ac_dir/install.sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + elif test -f "$ac_dir/shtool"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/shtool install -c" + break + fi +done +if test -z "$ac_aux_dir"; then + { { echo "$as_me:$LINENO: error: cannot find install-sh or install.sh in autoconf \"$srcdir\"/autoconf" >&5 +echo "$as_me: error: cannot find install-sh or install.sh in autoconf \"$srcdir\"/autoconf" >&2;} + { (exit 1); exit 1; }; } +fi + +# These three variables are undocumented and unsupported, +# and are intended to be withdrawn in a future Autoconf release. +# They can cause serious problems if a builder's source tree is in a directory +# whose full name contains unusual characters. +ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. +ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. +ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. + + + +if test ${srcdir} != "." ; then + if test -f ${srcdir}/include/llvm/Config/config.h ; then + { { echo "$as_me:$LINENO: error: Already configured in ${srcdir}" >&5 +echo "$as_me: error: Already configured in ${srcdir}" >&2;} + { (exit 1); exit 1; }; } + fi +fi + +for i in `ls ${srcdir}/projects` +do + if test -d ${srcdir}/projects/${i} ; then + case ${i} in + CVS) ;; + sample) subdirs="$subdirs projects/sample" + ;; + privbracket) subdirs="$subdirs projects/privbracket" + ;; + llvm-stacker) subdirs="$subdirs projects/llvm-stacker" + ;; + # llvm-test is the old name of the test-suite, kept here for backwards + # compatibility + llvm-test) subdirs="$subdirs projects/llvm-test" + ;; + test-suite) subdirs="$subdirs projects/test-suite" + ;; + llvm-reopt) subdirs="$subdirs projects/llvm-reopt" +;; + llvm-gcc) subdirs="$subdirs projects/llvm-gcc" + ;; + llvm-java) subdirs="$subdirs projects/llvm-java" + ;; + llvm-tv) subdirs="$subdirs projects/llvm-tv" + ;; + llvm-poolalloc) subdirs="$subdirs projects/llvm-poolalloc" + ;; + poolalloc) subdirs="$subdirs projects/poolalloc" + ;; + llvm-kernel) subdirs="$subdirs projects/llvm-kernel" + ;; + *) + { echo "$as_me:$LINENO: WARNING: Unknown project (${i}) won't be configured automatically" >&5 +echo "$as_me: WARNING: Unknown project (${i}) won't be configured automatically" >&2;} + ;; + esac + fi +done + + +# Make sure we can run config.sub. +$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || + { { echo "$as_me:$LINENO: error: cannot run $SHELL $ac_aux_dir/config.sub" >&5 +echo "$as_me: error: cannot run $SHELL $ac_aux_dir/config.sub" >&2;} + { (exit 1); exit 1; }; } + +{ echo "$as_me:$LINENO: checking build system type" >&5 +echo $ECHO_N "checking build system type... $ECHO_C" >&6; } +if test "${ac_cv_build+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_build_alias=$build_alias +test "x$ac_build_alias" = x && + ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"` +test "x$ac_build_alias" = x && + { { echo "$as_me:$LINENO: error: cannot guess build type; you must specify one" >&5 +echo "$as_me: error: cannot guess build type; you must specify one" >&2;} + { (exit 1); exit 1; }; } +ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` || + { { echo "$as_me:$LINENO: error: $SHELL $ac_aux_dir/config.sub $ac_build_alias failed" >&5 +echo "$as_me: error: $SHELL $ac_aux_dir/config.sub $ac_build_alias failed" >&2;} + { (exit 1); exit 1; }; } + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_build" >&5 +echo "${ECHO_T}$ac_cv_build" >&6; } +case $ac_cv_build in +*-*-*) ;; +*) { { echo "$as_me:$LINENO: error: invalid value of canonical build" >&5 +echo "$as_me: error: invalid value of canonical build" >&2;} + { (exit 1); exit 1; }; };; +esac +build=$ac_cv_build +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_build +shift +build_cpu=$1 +build_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +build_os=$* +IFS=$ac_save_IFS +case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac + + +{ echo "$as_me:$LINENO: checking host system type" >&5 +echo $ECHO_N "checking host system type... $ECHO_C" >&6; } +if test "${ac_cv_host+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test "x$host_alias" = x; then + ac_cv_host=$ac_cv_build +else + ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` || + { { echo "$as_me:$LINENO: error: $SHELL $ac_aux_dir/config.sub $host_alias failed" >&5 +echo "$as_me: error: $SHELL $ac_aux_dir/config.sub $host_alias failed" >&2;} + { (exit 1); exit 1; }; } +fi + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_host" >&5 +echo "${ECHO_T}$ac_cv_host" >&6; } +case $ac_cv_host in +*-*-*) ;; +*) { { echo "$as_me:$LINENO: error: invalid value of canonical host" >&5 +echo "$as_me: error: invalid value of canonical host" >&2;} + { (exit 1); exit 1; }; };; +esac +host=$ac_cv_host +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_host +shift +host_cpu=$1 +host_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +host_os=$* +IFS=$ac_save_IFS +case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac + + +{ echo "$as_me:$LINENO: checking target system type" >&5 +echo $ECHO_N "checking target system type... $ECHO_C" >&6; } +if test "${ac_cv_target+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test "x$target_alias" = x; then + ac_cv_target=$ac_cv_host +else + ac_cv_target=`$SHELL "$ac_aux_dir/config.sub" $target_alias` || + { { echo "$as_me:$LINENO: error: $SHELL $ac_aux_dir/config.sub $target_alias failed" >&5 +echo "$as_me: error: $SHELL $ac_aux_dir/config.sub $target_alias failed" >&2;} + { (exit 1); exit 1; }; } +fi + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_target" >&5 +echo "${ECHO_T}$ac_cv_target" >&6; } +case $ac_cv_target in +*-*-*) ;; +*) { { echo "$as_me:$LINENO: error: invalid value of canonical target" >&5 +echo "$as_me: error: invalid value of canonical target" >&2;} + { (exit 1); exit 1; }; };; +esac +target=$ac_cv_target +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_target +shift +target_cpu=$1 +target_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +target_os=$* +IFS=$ac_save_IFS +case $target_os in *\ *) target_os=`echo "$target_os" | sed 's/ /-/g'`;; esac + + +# The aliases save the names the user supplied, while $host etc. +# will get canonicalized. +test -n "$target_alias" && + test "$program_prefix$program_suffix$program_transform_name" = \ + NONENONEs,x,x, && + program_prefix=${target_alias}- + +{ echo "$as_me:$LINENO: checking type of operating system we're going to host on" >&5 +echo $ECHO_N "checking type of operating system we're going to host on... $ECHO_C" >&6; } +if test "${llvm_cv_os_type+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $host in + *-*-aix*) + llvm_cv_link_all_option="-Wl,--whole-archive" + llvm_cv_no_link_all_option="-Wl,--no-whole-archive" + llvm_cv_os_type="AIX" + llvm_cv_platform_type="Unix" ;; + *-*-irix*) + llvm_cv_link_all_option="-Wl,--whole-archive" + llvm_cv_no_link_all_option="-Wl,--no-whole-archive" + llvm_cv_os_type="IRIX" + llvm_cv_platform_type="Unix" ;; + *-*-cygwin*) + llvm_cv_link_all_option="-Wl,--whole-archive" + llvm_cv_no_link_all_option="-Wl,--no-whole-archive" + llvm_cv_os_type="Cygwin" + llvm_cv_platform_type="Unix" ;; + *-*-darwin*) + llvm_cv_link_all_option="-Wl,-all_load" + llvm_cv_no_link_all_option="-Wl,-noall_load" + llvm_cv_os_type="Darwin" + llvm_cv_platform_type="Unix" ;; + *-*-freebsd*) + llvm_cv_link_all_option="-Wl,--whole-archive" + llvm_cv_no_link_all_option="-Wl,--no-whole-archive" + llvm_cv_os_type="FreeBSD" + llvm_cv_platform_type="Unix" ;; + *-*-openbsd*) + llvm_cv_link_all_option="-Wl,--whole-archive" + llvm_cv_no_link_all_option="-Wl,--no-whole-archive" + llvm_cv_os_type="OpenBSD" + llvm_cv_platform_type="Unix" ;; + *-*-netbsd*) + llvm_cv_link_all_option="-Wl,--whole-archive" + llvm_cv_no_link_all_option="-Wl,--no-whole-archive" + llvm_cv_os_type="NetBSD" + llvm_cv_platform_type="Unix" ;; + *-*-dragonfly*) + llvm_cv_link_all_option="-Wl,--whole-archive" + llvm_cv_no_link_all_option="-Wl,--no-whole-archive" + llvm_cv_os_type="DragonFly" + llvm_cv_platform_type="Unix" ;; + *-*-hpux*) + llvm_cv_link_all_option="-Wl,--whole-archive" + llvm_cv_no_link_all_option="-Wl,--no-whole-archive" + llvm_cv_os_type="HP-UX" + llvm_cv_platform_type="Unix" ;; + *-*-interix*) + llvm_cv_link_all_option="-Wl,--whole-archive" + llvm_cv_no_link_all_option="-Wl,--no-whole-archive" + llvm_cv_os_type="Interix" + llvm_cv_platform_type="Unix" ;; + *-*-linux*) + llvm_cv_link_all_option="-Wl,--whole-archive" + llvm_cv_no_link_all_option="-Wl,--no-whole-archive" + llvm_cv_os_type="Linux" + llvm_cv_platform_type="Unix" ;; + *-*-solaris*) + llvm_cv_link_all_option="-Wl,-z,allextract" + llvm_cv_no_link_all_option="-Wl,-z,defaultextract" + llvm_cv_os_type="SunOS" + llvm_cv_platform_type="Unix" ;; + *-*-auroraux*) + llvm_cv_link_all_option="-Wl,-z,allextract" + llvm_cv_link_all_option="-Wl,-z,defaultextract" + llvm_cv_os_type="AuroraUX" + llvm_cv_platform_type="Unix" ;; + *-*-win32*) + llvm_cv_link_all_option="-Wl,--whole-archive" + llvm_cv_no_link_all_option="-Wl,--no-whole-archive" + llvm_cv_os_type="Win32" + llvm_cv_platform_type="Win32" ;; + *-*-mingw*) + llvm_cv_link_all_option="-Wl,--whole-archive" + llvm_cv_no_link_all_option="-Wl,--no-whole-archive" + llvm_cv_os_type="MingW" + llvm_cv_platform_type="Win32" ;; + *-*-haiku*) + llvm_cv_link_all_option="-Wl,--whole-archive" + llvm_cv_no_link_all_option="-Wl,--no-whole-archive" + llvm_cv_os_type="Haiku" + llvm_cv_platform_type="Unix" ;; + *-unknown-eabi*) + llvm_cv_link_all_option="-Wl,--whole-archive" + llvm_cv_no_link_all_option="-Wl,--no-whole-archive" + llvm_cv_os_type="Freestanding" + llvm_cv_platform_type="Unix" ;; + *-unknown-elf*) + llvm_cv_link_all_option="-Wl,--whole-archive" + llvm_cv_no_link_all_option="-Wl,--no-whole-archive" + llvm_cv_os_type="Freestanding" + llvm_cv_platform_type="Unix" ;; + *) + llvm_cv_link_all_option="" + llvm_cv_no_link_all_option="" + llvm_cv_os_type="Unknown" + llvm_cv_platform_type="Unknown" ;; +esac +fi +{ echo "$as_me:$LINENO: result: $llvm_cv_os_type" >&5 +echo "${ECHO_T}$llvm_cv_os_type" >&6; } + +{ echo "$as_me:$LINENO: checking type of operating system we're going to target" >&5 +echo $ECHO_N "checking type of operating system we're going to target... $ECHO_C" >&6; } +if test "${llvm_cv_target_os_type+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $target in + *-*-aix*) + llvm_cv_target_os_type="AIX" ;; + *-*-irix*) + llvm_cv_target_os_type="IRIX" ;; + *-*-cygwin*) + llvm_cv_target_os_type="Cygwin" ;; + *-*-darwin*) + llvm_cv_target_os_type="Darwin" ;; + *-*-freebsd*) + llvm_cv_target_os_type="FreeBSD" ;; + *-*-openbsd*) + llvm_cv_target_os_type="OpenBSD" ;; + *-*-netbsd*) + llvm_cv_target_os_type="NetBSD" ;; + *-*-dragonfly*) + llvm_cv_target_os_type="DragonFly" ;; + *-*-hpux*) + llvm_cv_target_os_type="HP-UX" ;; + *-*-interix*) + llvm_cv_target_os_type="Interix" ;; + *-*-linux*) + llvm_cv_target_os_type="Linux" ;; + *-*-solaris*) + llvm_cv_target_os_type="SunOS" ;; + *-*-auroraux*) + llvm_cv_target_os_type="AuroraUX" ;; + *-*-win32*) + llvm_cv_target_os_type="Win32" ;; + *-*-mingw*) + llvm_cv_target_os_type="MingW" ;; + *-*-haiku*) + llvm_cv_target_os_type="Haiku" ;; + *-unknown-eabi*) + llvm_cv_target_os_type="Freestanding" ;; + *) + llvm_cv_target_os_type="Unknown" ;; +esac +fi +{ echo "$as_me:$LINENO: result: $llvm_cv_target_os_type" >&5 +echo "${ECHO_T}$llvm_cv_target_os_type" >&6; } + +if test "$llvm_cv_os_type" = "Unknown" ; then + { { echo "$as_me:$LINENO: error: Operating system is unknown, configure can't continue" >&5 +echo "$as_me: error: Operating system is unknown, configure can't continue" >&2;} + { (exit 1); exit 1; }; } +fi + +OS=$llvm_cv_os_type + +HOST_OS=$llvm_cv_os_type + +TARGET_OS=$llvm_cv_target_os_type + + +LINKALL=$llvm_cv_link_all_option + +NOLINKALL=$llvm_cv_no_link_all_option + + +case $llvm_cv_platform_type in + Unix) + +cat >>confdefs.h <<\_ACEOF +#define LLVM_ON_UNIX 1 +_ACEOF + + LLVM_ON_UNIX=1 + + LLVM_ON_WIN32=0 + + ;; + Win32) + +cat >>confdefs.h <<\_ACEOF +#define LLVM_ON_WIN32 1 +_ACEOF + + LLVM_ON_UNIX=0 + + LLVM_ON_WIN32=1 + + ;; +esac + +{ echo "$as_me:$LINENO: checking target architecture" >&5 +echo $ECHO_N "checking target architecture... $ECHO_C" >&6; } +if test "${llvm_cv_target_arch+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $target in + i?86-*) llvm_cv_target_arch="x86" ;; + amd64-* | x86_64-*) llvm_cv_target_arch="x86_64" ;; + sparc*-*) llvm_cv_target_arch="Sparc" ;; + powerpc*-*) llvm_cv_target_arch="PowerPC" ;; + alpha*-*) llvm_cv_target_arch="Alpha" ;; + arm*-*) llvm_cv_target_arch="ARM" ;; + mips-*) llvm_cv_target_arch="Mips" ;; + pic16-*) llvm_cv_target_arch="PIC16" ;; + xcore-*) llvm_cv_target_arch="XCore" ;; + msp430-*) llvm_cv_target_arch="MSP430" ;; + s390x-*) llvm_cv_target_arch="SystemZ" ;; + bfin-*) llvm_cv_target_arch="Blackfin" ;; + *) llvm_cv_target_arch="Unknown" ;; +esac +fi +{ echo "$as_me:$LINENO: result: $llvm_cv_target_arch" >&5 +echo "${ECHO_T}$llvm_cv_target_arch" >&6; } + +if test "$llvm_cv_target_arch" = "Unknown" ; then + { echo "$as_me:$LINENO: WARNING: Configuring LLVM for an unknown target archicture" >&5 +echo "$as_me: WARNING: Configuring LLVM for an unknown target archicture" >&2;} +fi + +# Determine the LLVM native architecture for the target +case "$llvm_cv_target_arch" in + x86) LLVM_NATIVE_ARCH="X86" ;; + x86_64) LLVM_NATIVE_ARCH="X86" ;; + *) LLVM_NATIVE_ARCH="$llvm_cv_target_arch" ;; +esac + +ARCH=$llvm_cv_target_arch + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. +set dummy ${ac_tool_prefix}gcc; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CC="${ac_tool_prefix}gcc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_ac_ct_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_CC="gcc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 +echo "${ECHO_T}$ac_ct_CC" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&5 +echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +else + CC="$ac_cv_prog_CC" +fi + +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. +set dummy ${ac_tool_prefix}cc; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CC="${ac_tool_prefix}cc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + fi +fi +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + ac_prog_rejected=no +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# != 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" + fi +fi +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +fi +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + for ac_prog in cl.exe + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CC="$ac_tool_prefix$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + test -n "$CC" && break + done +fi +if test -z "$CC"; then + ac_ct_CC=$CC + for ac_prog in cl.exe +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_ac_ct_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_CC="$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 +echo "${ECHO_T}$ac_ct_CC" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + test -n "$ac_ct_CC" && break +done + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&5 +echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +fi + +fi + + +test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH +See \`config.log' for more details." >&5 +echo "$as_me: error: no acceptable C compiler found in \$PATH +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } + +# Provide some information about the compiler. +echo "$as_me:$LINENO: checking for C compiler version" >&5 +ac_compiler=`set X $ac_compile; echo $2` +{ (ac_try="$ac_compiler --version >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compiler --version >&5") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (ac_try="$ac_compiler -v >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compiler -v >&5") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (ac_try="$ac_compiler -V >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compiler -V >&5") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files a.out a.exe b.out" +# Try to create an executable without -o first, disregard a.out. +# It will help us diagnose broken compilers, and finding out an intuition +# of exeext. +{ echo "$as_me:$LINENO: checking for C compiler default output file name" >&5 +echo $ECHO_N "checking for C compiler default output file name... $ECHO_C" >&6; } +ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` +# +# List of possible output files, starting from the most likely. +# The algorithm is not robust to junk in `.', hence go to wildcards (a.*) +# only as a last resort. b.out is created by i960 compilers. +ac_files='a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out' +# +# The IRIX 6 linker writes into existing files which may not be +# executable, retaining their permissions. Remove them first so a +# subsequent execution test works. +ac_rmfiles= +for ac_file in $ac_files +do + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj ) ;; + * ) ac_rmfiles="$ac_rmfiles $ac_file";; + esac +done +rm -f $ac_rmfiles + +if { (ac_try="$ac_link_default" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link_default") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. +# So ignore a value of `no', otherwise this would lead to `EXEEXT = no' +# in a Makefile. We should not override ac_cv_exeext if it was cached, +# so that the user can short-circuit this test for compilers unknown to +# Autoconf. +for ac_file in $ac_files +do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj ) + ;; + [ab].out ) + # We found the default executable, but exeext='' is most + # certainly right. + break;; + *.* ) + if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; + then :; else + ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + fi + # We set ac_cv_exeext here because the later test for it is not + # safe: cross compilers may not add the suffix if given an `-o' + # argument, so we may need to know it at that point already. + # Even if this section looks crufty: it has the advantage of + # actually working. + break;; + * ) + break;; + esac +done +test "$ac_cv_exeext" = no && ac_cv_exeext= + +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { echo "$as_me:$LINENO: error: C compiler cannot create executables +See \`config.log' for more details." >&5 +echo "$as_me: error: C compiler cannot create executables +See \`config.log' for more details." >&2;} + { (exit 77); exit 77; }; } +fi + +ac_exeext=$ac_cv_exeext +{ echo "$as_me:$LINENO: result: $ac_file" >&5 +echo "${ECHO_T}$ac_file" >&6; } + +# Check that the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +{ echo "$as_me:$LINENO: checking whether the C compiler works" >&5 +echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6; } +# FIXME: These cross compiler hacks should be removed for Autoconf 3.0 +# If not cross compiling, check that we can run a simple program. +if test "$cross_compiling" != yes; then + if { ac_try='./$ac_file' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + cross_compiling=no + else + if test "$cross_compiling" = maybe; then + cross_compiling=yes + else + { { echo "$as_me:$LINENO: error: cannot run C compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot run C compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } + fi + fi +fi +{ echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6; } + +rm -f a.out a.exe conftest$ac_cv_exeext b.out +ac_clean_files=$ac_clean_files_save +# Check that the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +{ echo "$as_me:$LINENO: checking whether we are cross compiling" >&5 +echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6; } +{ echo "$as_me:$LINENO: result: $cross_compiling" >&5 +echo "${ECHO_T}$cross_compiling" >&6; } + +{ echo "$as_me:$LINENO: checking for suffix of executables" >&5 +echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6; } +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + # If both `conftest.exe' and `conftest' are `present' (well, observable) +# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will +# work properly (i.e., refer to `conftest.exe'), while it won't with +# `rm'. +for ac_file in conftest.exe conftest conftest.*; do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj ) ;; + *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + break;; + * ) break;; + esac +done +else + { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi + +rm -f conftest$ac_cv_exeext +{ echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5 +echo "${ECHO_T}$ac_cv_exeext" >&6; } + +rm -f conftest.$ac_ext +EXEEXT=$ac_cv_exeext +ac_exeext=$EXEEXT +{ echo "$as_me:$LINENO: checking for suffix of object files" >&5 +echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6; } +if test "${ac_cv_objext+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.o conftest.obj +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + for ac_file in conftest.o conftest.obj conftest.*; do + test -f "$ac_file" || continue; + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf ) ;; + *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` + break;; + esac +done +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot compute suffix of object files: cannot compile +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi + +rm -f conftest.$ac_cv_objext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ac_cv_objext" >&5 +echo "${ECHO_T}$ac_cv_objext" >&6; } +OBJEXT=$ac_cv_objext +ac_objext=$OBJEXT +{ echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5 +echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6; } +if test "${ac_cv_c_compiler_gnu+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_compiler_gnu=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_compiler_gnu=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_c_compiler_gnu=$ac_compiler_gnu + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5 +echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6; } +GCC=`test $ac_compiler_gnu = yes && echo yes` +ac_test_CFLAGS=${CFLAGS+set} +ac_save_CFLAGS=$CFLAGS +{ echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5 +echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6; } +if test "${ac_cv_prog_cc_g+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_save_c_werror_flag=$ac_c_werror_flag + ac_c_werror_flag=yes + ac_cv_prog_cc_g=no + CFLAGS="-g" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_prog_cc_g=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + CFLAGS="" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_c_werror_flag=$ac_save_c_werror_flag + CFLAGS="-g" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_prog_cc_g=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_c_werror_flag=$ac_save_c_werror_flag +fi +{ echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5 +echo "${ECHO_T}$ac_cv_prog_cc_g" >&6; } +if test "$ac_test_CFLAGS" = set; then + CFLAGS=$ac_save_CFLAGS +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi +{ echo "$as_me:$LINENO: checking for $CC option to accept ISO C89" >&5 +echo $ECHO_N "checking for $CC option to accept ISO C89... $ECHO_C" >&6; } +if test "${ac_cv_prog_cc_c89+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_prog_cc_c89=no +ac_save_CC=$CC +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include +#include +#include +/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ +struct buf { int x; }; +FILE * (*rcsopen) (struct buf *, struct stat *, int); +static char *e (p, i) + char **p; + int i; +{ + return p[i]; +} +static char *f (char * (*g) (char **, int), char **p, ...) +{ + char *s; + va_list v; + va_start (v,p); + s = g (p, va_arg (v,int)); + va_end (v); + return s; +} + +/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has + function prototypes and stuff, but not '\xHH' hex character constants. + These don't provoke an error unfortunately, instead are silently treated + as 'x'. The following induces an error, until -std is added to get + proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an + array size at least. It's necessary to write '\x00'==0 to get something + that's true only with -std. */ +int osf4_cc_array ['\x00' == 0 ? 1 : -1]; + +/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters + inside strings and character constants. */ +#define FOO(x) 'x' +int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; + +int test (int i, double x); +struct s1 {int (*f) (int a);}; +struct s2 {int (*f) (double a);}; +int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); +int argc; +char **argv; +int +main () +{ +return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; + ; + return 0; +} +_ACEOF +for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ + -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" +do + CC="$ac_save_CC $ac_arg" + rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_prog_cc_c89=$ac_arg +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext + test "x$ac_cv_prog_cc_c89" != "xno" && break +done +rm -f conftest.$ac_ext +CC=$ac_save_CC + +fi +# AC_CACHE_VAL +case "x$ac_cv_prog_cc_c89" in + x) + { echo "$as_me:$LINENO: result: none needed" >&5 +echo "${ECHO_T}none needed" >&6; } ;; + xno) + { echo "$as_me:$LINENO: result: unsupported" >&5 +echo "${ECHO_T}unsupported" >&6; } ;; + *) + CC="$CC $ac_cv_prog_cc_c89" + { echo "$as_me:$LINENO: result: $ac_cv_prog_cc_c89" >&5 +echo "${ECHO_T}$ac_cv_prog_cc_c89" >&6; } ;; +esac + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +{ echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5 +echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6; } +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then + if test "${ac_cv_prog_CPP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + # Double quotes because CPP needs to be expanded + for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" + do + ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Broken: fails on valid input. +continue +fi + +rm -f conftest.err conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + # Broken: success on invalid input. +continue +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Passes both tests. +ac_preproc_ok=: +break +fi + +rm -f conftest.err conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.err conftest.$ac_ext +if $ac_preproc_ok; then + break +fi + + done + ac_cv_prog_CPP=$CPP + +fi + CPP=$ac_cv_prog_CPP +else + ac_cv_prog_CPP=$CPP +fi +{ echo "$as_me:$LINENO: result: $CPP" >&5 +echo "${ECHO_T}$CPP" >&6; } +ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Broken: fails on valid input. +continue +fi + +rm -f conftest.err conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + # Broken: success on invalid input. +continue +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Passes both tests. +ac_preproc_ok=: +break +fi + +rm -f conftest.err conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.err conftest.$ac_ext +if $ac_preproc_ok; then + : +else + { { echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details." >&5 +echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +{ echo "$as_me:$LINENO: checking for grep that handles long lines and -e" >&5 +echo $ECHO_N "checking for grep that handles long lines and -e... $ECHO_C" >&6; } +if test "${ac_cv_path_GREP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + # Extract the first word of "grep ggrep" to use in msg output +if test -z "$GREP"; then +set dummy grep ggrep; ac_prog_name=$2 +if test "${ac_cv_path_GREP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_path_GREP_found=false +# Loop through the user's path and test for each of PROGNAME-LIST +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in grep ggrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" + { test -f "$ac_path_GREP" && $as_executable_p "$ac_path_GREP"; } || continue + # Check for GNU ac_path_GREP and select it if it is found. + # Check for GNU $ac_path_GREP +case `"$ac_path_GREP" --version 2>&1` in +*GNU*) + ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; +*) + ac_count=0 + echo $ECHO_N "0123456789$ECHO_C" >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + echo 'GREP' >> "conftest.nl" + "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + ac_count=`expr $ac_count + 1` + if test $ac_count -gt ${ac_path_GREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_GREP="$ac_path_GREP" + ac_path_GREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + + $ac_path_GREP_found && break 3 + done +done + +done +IFS=$as_save_IFS + + +fi + +GREP="$ac_cv_path_GREP" +if test -z "$GREP"; then + { { echo "$as_me:$LINENO: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&5 +echo "$as_me: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&2;} + { (exit 1); exit 1; }; } +fi + +else + ac_cv_path_GREP=$GREP +fi + + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_path_GREP" >&5 +echo "${ECHO_T}$ac_cv_path_GREP" >&6; } + GREP="$ac_cv_path_GREP" + + +{ echo "$as_me:$LINENO: checking for egrep" >&5 +echo $ECHO_N "checking for egrep... $ECHO_C" >&6; } +if test "${ac_cv_path_EGREP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 + then ac_cv_path_EGREP="$GREP -E" + else + # Extract the first word of "egrep" to use in msg output +if test -z "$EGREP"; then +set dummy egrep; ac_prog_name=$2 +if test "${ac_cv_path_EGREP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_path_EGREP_found=false +# Loop through the user's path and test for each of PROGNAME-LIST +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in egrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" + { test -f "$ac_path_EGREP" && $as_executable_p "$ac_path_EGREP"; } || continue + # Check for GNU ac_path_EGREP and select it if it is found. + # Check for GNU $ac_path_EGREP +case `"$ac_path_EGREP" --version 2>&1` in +*GNU*) + ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; +*) + ac_count=0 + echo $ECHO_N "0123456789$ECHO_C" >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + echo 'EGREP' >> "conftest.nl" + "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + ac_count=`expr $ac_count + 1` + if test $ac_count -gt ${ac_path_EGREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_EGREP="$ac_path_EGREP" + ac_path_EGREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + + $ac_path_EGREP_found && break 3 + done +done + +done +IFS=$as_save_IFS + + +fi + +EGREP="$ac_cv_path_EGREP" +if test -z "$EGREP"; then + { { echo "$as_me:$LINENO: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&5 +echo "$as_me: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&2;} + { (exit 1); exit 1; }; } +fi + +else + ac_cv_path_EGREP=$EGREP +fi + + + fi +fi +{ echo "$as_me:$LINENO: result: $ac_cv_path_EGREP" >&5 +echo "${ECHO_T}$ac_cv_path_EGREP" >&6; } + EGREP="$ac_cv_path_EGREP" + + +{ echo "$as_me:$LINENO: checking for ANSI C header files" >&5 +echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6; } +if test "${ac_cv_header_stdc+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include +#include +#include + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_header_stdc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_header_stdc=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "memchr" >/dev/null 2>&1; then + : +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "free" >/dev/null 2>&1; then + : +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. + if test "$cross_compiling" = yes; then + : +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include +#if ((' ' & 0x0FF) == 0x020) +# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#else +# define ISLOWER(c) \ + (('a' <= (c) && (c) <= 'i') \ + || ('j' <= (c) && (c) <= 'r') \ + || ('s' <= (c) && (c) <= 'z')) +# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) +#endif + +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int +main () +{ + int i; + for (i = 0; i < 256; i++) + if (XOR (islower (i), ISLOWER (i)) + || toupper (i) != TOUPPER (i)) + return 2; + return 0; +} +_ACEOF +rm -f conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + : +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +ac_cv_header_stdc=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + + +fi +fi +{ echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5 +echo "${ECHO_T}$ac_cv_header_stdc" >&6; } +if test $ac_cv_header_stdc = yes; then + +cat >>confdefs.h <<\_ACEOF +#define STDC_HEADERS 1 +_ACEOF + +fi + +# On IRIX 5.3, sys/types and inttypes.h are conflicting. + + + + + + + + + +for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ + inttypes.h stdint.h unistd.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +{ echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default + +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_Header=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_Header=no" +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + +{ echo "$as_me:$LINENO: checking whether byte ordering is bigendian" >&5 +echo $ECHO_N "checking whether byte ordering is bigendian... $ECHO_C" >&6; } +if test "${ac_cv_c_bigendian+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + # See if sys/param.h defines the BYTE_ORDER macro. +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include + +int +main () +{ +#if !BYTE_ORDER || !BIG_ENDIAN || !LITTLE_ENDIAN + bogus endian macros +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + # It does; now see whether it defined to BIG_ENDIAN or not. +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include + +int +main () +{ +#if BYTE_ORDER != BIG_ENDIAN + not big endian +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_c_bigendian=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_c_bigendian=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # It does not; compile a test program. +if test "$cross_compiling" = yes; then + # try to guess the endianness by grepping values into an object file + ac_cv_c_bigendian=unknown + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +short int ascii_mm[] = { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 }; +short int ascii_ii[] = { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 }; +void _ascii () { char *s = (char *) ascii_mm; s = (char *) ascii_ii; } +short int ebcdic_ii[] = { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 }; +short int ebcdic_mm[] = { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 }; +void _ebcdic () { char *s = (char *) ebcdic_mm; s = (char *) ebcdic_ii; } +int +main () +{ + _ascii (); _ebcdic (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + if grep BIGenDianSyS conftest.$ac_objext >/dev/null ; then + ac_cv_c_bigendian=yes +fi +if grep LiTTleEnDian conftest.$ac_objext >/dev/null ; then + if test "$ac_cv_c_bigendian" = unknown; then + ac_cv_c_bigendian=no + else + # finding both strings is unlikely to happen, but who knows? + ac_cv_c_bigendian=unknown + fi +fi +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ + + /* Are we little or big endian? From Harbison&Steele. */ + union + { + long int l; + char c[sizeof (long int)]; + } u; + u.l = 1; + return u.c[sizeof (long int) - 1] == 1; + + ; + return 0; +} +_ACEOF +rm -f conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_c_bigendian=no +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +ac_cv_c_bigendian=yes +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + + +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ac_cv_c_bigendian" >&5 +echo "${ECHO_T}$ac_cv_c_bigendian" >&6; } +case $ac_cv_c_bigendian in + yes) + ENDIAN=big + ;; + no) + ENDIAN=little + ;; + *) + { { echo "$as_me:$LINENO: error: unknown endianness +presetting ac_cv_c_bigendian=no (or yes) will help" >&5 +echo "$as_me: error: unknown endianness +presetting ac_cv_c_bigendian=no (or yes) will help" >&2;} + { (exit 1); exit 1; }; } ;; +esac + + +if test "$cross_compiling" = yes; then + LLVM_CROSS_COMPILING=1 + + +{ echo "$as_me:$LINENO: checking for executable suffix on build platform" >&5 +echo $ECHO_N "checking for executable suffix on build platform... $ECHO_C" >&6; } +if test "${ac_cv_build_exeext+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test "$CYGWIN" = yes || test "$MINGW32" = yes; then + ac_cv_build_exeext=.exe +else + ac_build_prefix=${build_alias}- + + # Extract the first word of "${ac_build_prefix}gcc", so it can be a program name with args. +set dummy ${ac_build_prefix}gcc; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_BUILD_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$BUILD_CC"; then + ac_cv_prog_BUILD_CC="$BUILD_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_BUILD_CC="${ac_build_prefix}gcc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +BUILD_CC=$ac_cv_prog_BUILD_CC +if test -n "$BUILD_CC"; then + { echo "$as_me:$LINENO: result: $BUILD_CC" >&5 +echo "${ECHO_T}$BUILD_CC" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + if test -z "$BUILD_CC"; then + # Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_BUILD_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$BUILD_CC"; then + ac_cv_prog_BUILD_CC="$BUILD_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_BUILD_CC="gcc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +BUILD_CC=$ac_cv_prog_BUILD_CC +if test -n "$BUILD_CC"; then + { echo "$as_me:$LINENO: result: $BUILD_CC" >&5 +echo "${ECHO_T}$BUILD_CC" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + if test -z "$BUILD_CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_BUILD_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$BUILD_CC"; then + ac_cv_prog_BUILD_CC="$BUILD_CC" # Let the user override the test. +else + ac_prog_rejected=no +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_BUILD_CC="cc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_BUILD_CC + shift + if test $# != 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set BUILD_CC to just the basename; use the full file name. + shift + ac_cv_prog_BUILD_CC="$as_dir/$ac_word${1+' '}$@" + fi +fi +fi +fi +BUILD_CC=$ac_cv_prog_BUILD_CC +if test -n "$BUILD_CC"; then + { echo "$as_me:$LINENO: result: $BUILD_CC" >&5 +echo "${ECHO_T}$BUILD_CC" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + fi + fi + test -z "$BUILD_CC" && { { echo "$as_me:$LINENO: error: no acceptable cc found in \$PATH" >&5 +echo "$as_me: error: no acceptable cc found in \$PATH" >&2;} + { (exit 1); exit 1; }; } + ac_build_link='${BUILD_CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' + rm -f conftest* + echo 'int main () { return 0; }' > conftest.$ac_ext + ac_cv_build_exeext= + if { (eval echo "$as_me:$LINENO: \"$ac_build_link\"") >&5 + (eval $ac_build_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + for file in conftest.*; do + case $file in + *.c | *.o | *.obj | *.dSYM) ;; + *) ac_cv_build_exeext=`echo $file | sed -e s/conftest//` ;; + esac + done + else + { { echo "$as_me:$LINENO: error: installation or configuration problem: compiler cannot create executables." >&5 +echo "$as_me: error: installation or configuration problem: compiler cannot create executables." >&2;} + { (exit 1); exit 1; }; } + fi + rm -f conftest* + test x"${ac_cv_build_exeext}" = x && ac_cv_build_exeext=blank +fi +fi + +BUILD_EXEEXT="" +test x"${ac_cv_build_exeext}" != xblank && BUILD_EXEEXT=${ac_cv_build_exeext} +{ echo "$as_me:$LINENO: result: ${ac_cv_build_exeext}" >&5 +echo "${ECHO_T}${ac_cv_build_exeext}" >&6; } +ac_build_exeext=$BUILD_EXEEXT + + ac_build_prefix=${build_alias}- + # Extract the first word of "${ac_build_prefix}g++", so it can be a program name with args. +set dummy ${ac_build_prefix}g++; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_BUILD_CXX+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$BUILD_CXX"; then + ac_cv_prog_BUILD_CXX="$BUILD_CXX" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_BUILD_CXX="${ac_build_prefix}g++" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +BUILD_CXX=$ac_cv_prog_BUILD_CXX +if test -n "$BUILD_CXX"; then + { echo "$as_me:$LINENO: result: $BUILD_CXX" >&5 +echo "${ECHO_T}$BUILD_CXX" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + if test -z "$BUILD_CXX"; then + # Extract the first word of "g++", so it can be a program name with args. +set dummy g++; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_BUILD_CXX+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$BUILD_CXX"; then + ac_cv_prog_BUILD_CXX="$BUILD_CXX" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_BUILD_CXX="g++" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +BUILD_CXX=$ac_cv_prog_BUILD_CXX +if test -n "$BUILD_CXX"; then + { echo "$as_me:$LINENO: result: $BUILD_CXX" >&5 +echo "${ECHO_T}$BUILD_CXX" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + if test -z "$BUILD_CXX"; then + # Extract the first word of "c++", so it can be a program name with args. +set dummy c++; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_BUILD_CXX+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$BUILD_CXX"; then + ac_cv_prog_BUILD_CXX="$BUILD_CXX" # Let the user override the test. +else + ac_prog_rejected=no +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/c++"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_BUILD_CXX="c++" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_BUILD_CXX + shift + if test $# != 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set BUILD_CXX to just the basename; use the full file name. + shift + ac_cv_prog_BUILD_CXX="$as_dir/$ac_word${1+' '}$@" + fi +fi +fi +fi +BUILD_CXX=$ac_cv_prog_BUILD_CXX +if test -n "$BUILD_CXX"; then + { echo "$as_me:$LINENO: result: $BUILD_CXX" >&5 +echo "${ECHO_T}$BUILD_CXX" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + fi + fi +else + LLVM_CROSS_COMPILING=0 + +fi + +if test -d "CVS" -o -d "${srcdir}/CVS" -o -d ".svn" -o -d "${srcdir}/.svn" -o -d ".git" -o -d "${srcdir}/.git"; then + cvsbuild="yes" + optimize="no" + CVSBUILD=CVSBUILD=1 + +else + cvsbuild="no" + optimize="yes" +fi + + +# Check whether --enable-optimized was given. +if test "${enable_optimized+set}" = set; then + enableval=$enable_optimized; +else + enableval=$optimize +fi + +if test ${enableval} = "no" ; then + ENABLE_OPTIMIZED= + +else + ENABLE_OPTIMIZED=ENABLE_OPTIMIZED=1 + +fi + +# Check whether --enable-profiling was given. +if test "${enable_profiling+set}" = set; then + enableval=$enable_profiling; +else + enableval="no" +fi + +if test ${enableval} = "no" ; then + ENABLE_PROFILING= + +else + ENABLE_PROFILING=ENABLE_PROFILING=1 + +fi + +# Check whether --enable-assertions was given. +if test "${enable_assertions+set}" = set; then + enableval=$enable_assertions; +else + enableval="yes" +fi + +if test ${enableval} = "yes" ; then + DISABLE_ASSERTIONS= + +else + DISABLE_ASSERTIONS=DISABLE_ASSERTIONS=1 + +fi + +# Check whether --enable-expensive-checks was given. +if test "${enable_expensive_checks+set}" = set; then + enableval=$enable_expensive_checks; +else + enableval="no" +fi + +if test ${enableval} = "yes" ; then + ENABLE_EXPENSIVE_CHECKS=ENABLE_EXPENSIVE_CHECKS=1 + + EXPENSIVE_CHECKS=yes + +else + ENABLE_EXPENSIVE_CHECKS= + + EXPENSIVE_CHECKS=no + +fi + +# Check whether --enable-debug-runtime was given. +if test "${enable_debug_runtime+set}" = set; then + enableval=$enable_debug_runtime; +else + enableval=no +fi + +if test ${enableval} = "no" ; then + DEBUG_RUNTIME= + +else + DEBUG_RUNTIME=DEBUG_RUNTIME=1 + +fi + +# Check whether --enable-debug-symbols was given. +if test "${enable_debug_symbols+set}" = set; then + enableval=$enable_debug_symbols; +else + enableval=no +fi + +if test ${enableval} = "no" ; then + DEBUG_SYMBOLS= + +else + DEBUG_SYMBOLS=DEBUG_SYMBOLS=1 + +fi + +# Check whether --enable-jit was given. +if test "${enable_jit+set}" = set; then + enableval=$enable_jit; +else + enableval=default +fi + +if test ${enableval} = "no" +then + JIT= + +else + case "$llvm_cv_target_arch" in + x86) TARGET_HAS_JIT=1 + ;; + Sparc) TARGET_HAS_JIT=0 + ;; + PowerPC) TARGET_HAS_JIT=1 + ;; + x86_64) TARGET_HAS_JIT=1 + ;; + Alpha) TARGET_HAS_JIT=1 + ;; + ARM) TARGET_HAS_JIT=1 + ;; + Mips) TARGET_HAS_JIT=0 + ;; + PIC16) TARGET_HAS_JIT=0 + ;; + XCore) TARGET_HAS_JIT=0 + ;; + MSP430) TARGET_HAS_JIT=0 + ;; + SystemZ) TARGET_HAS_JIT=0 + ;; + Blackfin) TARGET_HAS_JIT=0 + ;; + *) TARGET_HAS_JIT=0 + ;; + esac +fi + +# Check whether --enable-doxygen was given. +if test "${enable_doxygen+set}" = set; then + enableval=$enable_doxygen; +else + enableval=default +fi + +case "$enableval" in + yes) ENABLE_DOXYGEN=1 + ;; + no) ENABLE_DOXYGEN=0 + ;; + default) ENABLE_DOXYGEN=0 + ;; + *) { { echo "$as_me:$LINENO: error: Invalid setting for --enable-doxygen. Use \"yes\" or \"no\"" >&5 +echo "$as_me: error: Invalid setting for --enable-doxygen. Use \"yes\" or \"no\"" >&2;} + { (exit 1); exit 1; }; } ;; +esac + +# Check whether --enable-threads was given. +if test "${enable_threads+set}" = set; then + enableval=$enable_threads; +else + enableval=default +fi + +case "$enableval" in + yes) ENABLE_THREADS=1 + ;; + no) ENABLE_THREADS=0 + ;; + default) ENABLE_THREADS=1 + ;; + *) { { echo "$as_me:$LINENO: error: Invalid setting for --enable-threads. Use \"yes\" or \"no\"" >&5 +echo "$as_me: error: Invalid setting for --enable-threads. Use \"yes\" or \"no\"" >&2;} + { (exit 1); exit 1; }; } ;; +esac + +cat >>confdefs.h <<_ACEOF +#define ENABLE_THREADS $ENABLE_THREADS +_ACEOF + + +# Check whether --enable-pic was given. +if test "${enable_pic+set}" = set; then + enableval=$enable_pic; +else + enableval=default +fi + +case "$enableval" in + yes) ENABLE_PIC=1 + ;; + no) ENABLE_PIC=0 + ;; + default) ENABLE_PIC=1 + ;; + *) { { echo "$as_me:$LINENO: error: Invalid setting for --enable-pic. Use \"yes\" or \"no\"" >&5 +echo "$as_me: error: Invalid setting for --enable-pic. Use \"yes\" or \"no\"" >&2;} + { (exit 1); exit 1; }; } ;; +esac + +cat >>confdefs.h <<_ACEOF +#define ENABLE_PIC $ENABLE_PIC +_ACEOF + + +TARGETS_TO_BUILD="" +# Check whether --enable-targets was given. +if test "${enable_targets+set}" = set; then + enableval=$enable_targets; +else + enableval=all +fi + +if test "$enableval" = host-only ; then + enableval=host +fi +case "$enableval" in + all) TARGETS_TO_BUILD="X86 Sparc PowerPC Alpha ARM Mips CellSPU PIC16 XCore MSP430 SystemZ Blackfin CBackend MSIL CppBackend" ;; + *)for a_target in `echo $enableval|sed -e 's/,/ /g' ` ; do + case "$a_target" in + x86) TARGETS_TO_BUILD="X86 $TARGETS_TO_BUILD" ;; + x86_64) TARGETS_TO_BUILD="X86 $TARGETS_TO_BUILD" ;; + sparc) TARGETS_TO_BUILD="Sparc $TARGETS_TO_BUILD" ;; + powerpc) TARGETS_TO_BUILD="PowerPC $TARGETS_TO_BUILD" ;; + alpha) TARGETS_TO_BUILD="Alpha $TARGETS_TO_BUILD" ;; + arm) TARGETS_TO_BUILD="ARM $TARGETS_TO_BUILD" ;; + mips) TARGETS_TO_BUILD="Mips $TARGETS_TO_BUILD" ;; + spu) TARGETS_TO_BUILD="CellSPU $TARGETS_TO_BUILD" ;; + pic16) TARGETS_TO_BUILD="PIC16 $TARGETS_TO_BUILD" ;; + xcore) TARGETS_TO_BUILD="XCore $TARGETS_TO_BUILD" ;; + msp430) TARGETS_TO_BUILD="MSP430 $TARGETS_TO_BUILD" ;; + systemz) TARGETS_TO_BUILD="SystemZ $TARGETS_TO_BUILD" ;; + blackfin) TARGETS_TO_BUILD="Blackfin $TARGETS_TO_BUILD" ;; + cbe) TARGETS_TO_BUILD="CBackend $TARGETS_TO_BUILD" ;; + msil) TARGETS_TO_BUILD="MSIL $TARGETS_TO_BUILD" ;; + cpp) TARGETS_TO_BUILD="CppBackend $TARGETS_TO_BUILD" ;; + host) case "$llvm_cv_target_arch" in + x86) TARGETS_TO_BUILD="X86 $TARGETS_TO_BUILD" ;; + x86_64) TARGETS_TO_BUILD="X86 $TARGETS_TO_BUILD" ;; + Sparc) TARGETS_TO_BUILD="Sparc $TARGETS_TO_BUILD" ;; + PowerPC) TARGETS_TO_BUILD="PowerPC $TARGETS_TO_BUILD" ;; + Alpha) TARGETS_TO_BUILD="Alpha $TARGETS_TO_BUILD" ;; + ARM) TARGETS_TO_BUILD="ARM $TARGETS_TO_BUILD" ;; + Mips) TARGETS_TO_BUILD="Mips $TARGETS_TO_BUILD" ;; + CellSPU|SPU) TARGETS_TO_BUILD="CellSPU $TARGETS_TO_BUILD" ;; + PIC16) TARGETS_TO_BUILD="PIC16 $TARGETS_TO_BUILD" ;; + XCore) TARGETS_TO_BUILD="XCore $TARGETS_TO_BUILD" ;; + MSP430) TARGETS_TO_BUILD="MSP430 $TARGETS_TO_BUILD" ;; + SystemZ) TARGETS_TO_BUILD="SystemZ $TARGETS_TO_BUILD" ;; + Blackfin) TARGETS_TO_BUILD="Blackfin $TARGETS_TO_BUILD" ;; + *) { { echo "$as_me:$LINENO: error: Can not set target to build" >&5 +echo "$as_me: error: Can not set target to build" >&2;} + { (exit 1); exit 1; }; } ;; + esac ;; + *) { { echo "$as_me:$LINENO: error: Unrecognized target $a_target" >&5 +echo "$as_me: error: Unrecognized target $a_target" >&2;} + { (exit 1); exit 1; }; } ;; + esac + done + ;; +esac +TARGETS_TO_BUILD=$TARGETS_TO_BUILD + + +# Determine whether we are building LLVM support for the native architecture. +# If so, define LLVM_NATIVE_ARCH to that LLVM target. +for a_target in $TARGETS_TO_BUILD; do + if test "$a_target" = "$LLVM_NATIVE_ARCH"; then + LLVM_NATIVE_ARCHTARGET="${LLVM_NATIVE_ARCH}Target" + +cat >>confdefs.h <<_ACEOF +#define LLVM_NATIVE_ARCH $LLVM_NATIVE_ARCHTARGET +_ACEOF + + fi +done + +# Build the LLVM_TARGET and LLVM_... macros for Targets.def and the individual +# target feature def files. +LLVM_ENUM_TARGETS="" +LLVM_ENUM_ASM_PRINTERS="" +LLVM_ENUM_ASM_PARSERS="" +LLVM_ENUM_DISASSEMBLERS="" +for target_to_build in $TARGETS_TO_BUILD; do + LLVM_ENUM_TARGETS="LLVM_TARGET($target_to_build) $LLVM_ENUM_TARGETS" + if test -f ${srcdir}/lib/Target/${target_to_build}/AsmPrinter/Makefile ; then + LLVM_ENUM_ASM_PRINTERS="LLVM_ASM_PRINTER($target_to_build) $LLVM_ENUM_ASM_PRINTERS"; + fi + if test -f ${srcdir}/lib/Target/${target_to_build}/AsmParser/Makefile ; then + LLVM_ENUM_ASM_PARSERS="LLVM_ASM_PARSER($target_to_build) $LLVM_ENUM_ASM_PARSERS"; + fi + if test -f ${srcdir}/lib/Target/${target_to_build}/Disassembler/Makefile ; then + LLVM_ENUM_DISASSEMBLERS="LLVM_DISASSEMBLER($target_to_build) $LLVM_ENUM_DISASSEMBLERS"; + fi +done + + + + + +# Check whether --enable-cbe-printf-a was given. +if test "${enable_cbe_printf_a+set}" = set; then + enableval=$enable_cbe_printf_a; +else + enableval=default +fi + +case "$enableval" in + yes) ENABLE_CBE_PRINTF_A=1 + ;; + no) ENABLE_CBE_PRINTF_A=0 + ;; + default) ENABLE_CBE_PRINTF_A=1 + ;; + *) { { echo "$as_me:$LINENO: error: Invalid setting for --enable-cbe-printf-a. Use \"yes\" or \"no\"" >&5 +echo "$as_me: error: Invalid setting for --enable-cbe-printf-a. Use \"yes\" or \"no\"" >&2;} + { (exit 1); exit 1; }; } ;; +esac + +cat >>confdefs.h <<_ACEOF +#define ENABLE_CBE_PRINTF_A $ENABLE_CBE_PRINTF_A +_ACEOF + + + +# Check whether --with-llvmgccdir was given. +if test "${with_llvmgccdir+set}" = set; then + withval=$with_llvmgccdir; +else + withval=default +fi + +case "$withval" in + default) WITH_LLVMGCCDIR=default ;; + /* | [A-Za-z]:[\\/]*) WITH_LLVMGCCDIR=$withval ;; + *) { { echo "$as_me:$LINENO: error: Invalid path for --with-llvmgccdir. Provide full path" >&5 +echo "$as_me: error: Invalid path for --with-llvmgccdir. Provide full path" >&2;} + { (exit 1); exit 1; }; } ;; +esac + + +# Check whether --with-llvmgcc was given. +if test "${with_llvmgcc+set}" = set; then + withval=$with_llvmgcc; LLVMGCC=$with_llvmgcc + WITH_LLVMGCCDIR="" +fi + + + +# Check whether --with-llvmgxx was given. +if test "${with_llvmgxx+set}" = set; then + withval=$with_llvmgxx; LLVMGXX=$with_llvmgxx + WITH_LLVMGCCDIR="" +fi + + +if test -n "$LLVMGCC"; then + LLVMGCCCOMMAND="$LLVMGCC" +fi + +if test -n "$LLVMGXX"; then + LLVMGXXCOMMAND="$LLVMGXX" +fi + +if test -n "$LLVMGCC" && test -z "$LLVMGXX"; then + { { echo "$as_me:$LINENO: error: Invalid llvm-g++. Use --with-llvmgxx when --with-llvmgcc is used" >&5 +echo "$as_me: error: Invalid llvm-g++. Use --with-llvmgxx when --with-llvmgcc is used" >&2;} + { (exit 1); exit 1; }; }; +fi + +if test -n "$LLVMGXX" && test -z "$LLVMGCC"; then + { { echo "$as_me:$LINENO: error: Invalid llvm-gcc. Use --with-llvmgcc when --with-llvmgxx is used" >&5 +echo "$as_me: error: Invalid llvm-gcc. Use --with-llvmgcc when --with-llvmgxx is used" >&2;} + { (exit 1); exit 1; }; }; +fi + + +# Check whether --with-optimize-option was given. +if test "${with_optimize_option+set}" = set; then + withval=$with_optimize_option; +else + withval=default +fi + +{ echo "$as_me:$LINENO: checking optimization flags" >&5 +echo $ECHO_N "checking optimization flags... $ECHO_C" >&6; } +case "$withval" in + default) + case "$llvm_cv_os_type" in + MingW) optimize_option=-O3 ;; + *) optimize_option=-O2 ;; + esac ;; + *) optimize_option="$withval" ;; +esac +OPTIMIZE_OPTION=$optimize_option + +{ echo "$as_me:$LINENO: result: $optimize_option" >&5 +echo "${ECHO_T}$optimize_option" >&6; } + + +# Check whether --with-extra-options was given. +if test "${with_extra_options+set}" = set; then + withval=$with_extra_options; +else + withval=default +fi + +case "$withval" in + default) EXTRA_OPTIONS= ;; + *) EXTRA_OPTIONS=$withval ;; +esac +EXTRA_OPTIONS=$EXTRA_OPTIONS + + +# Check whether --enable-bindings was given. +if test "${enable_bindings+set}" = set; then + enableval=$enable_bindings; +else + enableval=default +fi + +BINDINGS_TO_BUILD="" +case "$enableval" in + yes | default | auto) BINDINGS_TO_BUILD="auto" ;; + all ) BINDINGS_TO_BUILD="ocaml" ;; + none | no) BINDINGS_TO_BUILD="" ;; + *)for a_binding in `echo $enableval|sed -e 's/,/ /g' ` ; do + case "$a_binding" in + ocaml) BINDINGS_TO_BUILD="ocaml $BINDINGS_TO_BUILD" ;; + *) { { echo "$as_me:$LINENO: error: Unrecognized binding $a_binding" >&5 +echo "$as_me: error: Unrecognized binding $a_binding" >&2;} + { (exit 1); exit 1; }; } ;; + esac + done + ;; +esac + + +# Check whether --with-ocaml-libdir was given. +if test "${with_ocaml_libdir+set}" = set; then + withval=$with_ocaml_libdir; +else + withval=auto +fi + +case "$withval" in + auto) with_ocaml_libdir="$withval" ;; + /* | [A-Za-z]:[\\/]*) with_ocaml_libdir="$withval" ;; + *) { { echo "$as_me:$LINENO: error: Invalid path for --with-ocaml-libdir. Provide full path" >&5 +echo "$as_me: error: Invalid path for --with-ocaml-libdir. Provide full path" >&2;} + { (exit 1); exit 1; }; } ;; +esac + + +# Check whether --with-c-include-dir was given. +if test "${with_c_include_dir+set}" = set; then + withval=$with_c_include_dir; +else + withval="" +fi + + +cat >>confdefs.h <<_ACEOF +#define C_INCLUDE_DIRS "$withval" +_ACEOF + + + +# Check whether --with-cxx-include-root was given. +if test "${with_cxx_include_root+set}" = set; then + withval=$with_cxx_include_root; +else + withval="" +fi + + +cat >>confdefs.h <<_ACEOF +#define CXX_INCLUDE_ROOT "$withval" +_ACEOF + + + +# Check whether --with-cxx-include-arch was given. +if test "${with_cxx_include_arch+set}" = set; then + withval=$with_cxx_include_arch; +else + withval="" +fi + + +cat >>confdefs.h <<_ACEOF +#define CXX_INCLUDE_ARCH "$withval" +_ACEOF + + + +# Check whether --with-cxx-include-32bit-dir was given. +if test "${with_cxx_include_32bit_dir+set}" = set; then + withval=$with_cxx_include_32bit_dir; +else + withval="" +fi + + +cat >>confdefs.h <<_ACEOF +#define CXX_INCLUDE_32BIT_DIR "$withval" +_ACEOF + + + +# Check whether --with-cxx-include-64bit-dir was given. +if test "${with_cxx_include_64bit_dir+set}" = set; then + withval=$with_cxx_include_64bit_dir; +else + withval="" +fi + + +cat >>confdefs.h <<_ACEOF +#define CXX_INCLUDE_64BIT_DIR "$withval" +_ACEOF + + + +# Check whether --with-binutils-include was given. +if test "${with_binutils_include+set}" = set; then + withval=$with_binutils_include; +else + withval=default +fi + +case "$withval" in + default) WITH_BINUTILS_INCDIR=default ;; + /* | [A-Za-z]:[\\/]*) WITH_BINUTILS_INCDIR=$withval ;; + *) { { echo "$as_me:$LINENO: error: Invalid path for --with-binutils-include. Provide full path" >&5 +echo "$as_me: error: Invalid path for --with-binutils-include. Provide full path" >&2;} + { (exit 1); exit 1; }; } ;; +esac +if test "x$WITH_BINUTILS_INCDIR" != xdefault ; then + BINUTILS_INCDIR=$WITH_BINUTILS_INCDIR + + if test ! -f "$WITH_BINUTILS_INCDIR/plugin-api.h"; then + echo "$WITH_BINUTILS_INCDIR/plugin-api.h" + { { echo "$as_me:$LINENO: error: Invalid path to directory containing plugin-api.h." >&5 +echo "$as_me: error: Invalid path to directory containing plugin-api.h." >&2;} + { (exit 1); exit 1; }; }; + fi +fi + +# Check whether --enable-libffi was given. +if test "${enable_libffi+set}" = set; then + enableval=$enable_libffi; +else + enableval=yes +fi + +case "$enableval" in + yes) llvm_cv_enable_libffi="yes" ;; + no) llvm_cv_enable_libffi="no" ;; + *) { { echo "$as_me:$LINENO: error: Invalid setting for --enable-libffi. Use \"yes\" or \"no\"" >&5 +echo "$as_me: error: Invalid setting for --enable-libffi. Use \"yes\" or \"no\"" >&2;} + { (exit 1); exit 1; }; } ;; +esac + +if test "$llvm_cv_os_type" = "Win32" ; then + llvmc_dynamic="yes" +else + llvmc_dynamic="no" +fi + +# Check whether --enable-llvmc-dynamic was given. +if test "${enable_llvmc_dynamic+set}" = set; then + enableval=$enable_llvmc_dynamic; +else + enableval=$llvmc_dynamic +fi + +if test ${enableval} = "yes" && test "$ENABLE_PIC" -eq 1 ; then + ENABLE_LLVMC_DYNAMIC=ENABLE_LLVMC_DYNAMIC=1 + +else + ENABLE_LLVMC_DYNAMIC= + +fi + +# Check whether --enable-llvmc-dynamic-plugins was given. +if test "${enable_llvmc_dynamic_plugins+set}" = set; then + enableval=$enable_llvmc_dynamic_plugins; +else + enableval=yes +fi + +if test ${enableval} = "yes" ; then + ENABLE_LLVMC_DYNAMIC_PLUGINS=ENABLE_LLVMC_DYNAMIC_PLUGINS=1 + +else + ENABLE_LLVMC_DYNAMIC_PLUGINS= + +fi + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +{ echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5 +echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6; } +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then + if test "${ac_cv_prog_CPP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + # Double quotes because CPP needs to be expanded + for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" + do + ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Broken: fails on valid input. +continue +fi + +rm -f conftest.err conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + # Broken: success on invalid input. +continue +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Passes both tests. +ac_preproc_ok=: +break +fi + +rm -f conftest.err conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.err conftest.$ac_ext +if $ac_preproc_ok; then + break +fi + + done + ac_cv_prog_CPP=$CPP + +fi + CPP=$ac_cv_prog_CPP +else + ac_cv_prog_CPP=$CPP +fi +{ echo "$as_me:$LINENO: result: $CPP" >&5 +echo "${ECHO_T}$CPP" >&6; } +ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Broken: fails on valid input. +continue +fi + +rm -f conftest.err conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + # Broken: success on invalid input. +continue +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Passes both tests. +ac_preproc_ok=: +break +fi + +rm -f conftest.err conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.err conftest.$ac_ext +if $ac_preproc_ok; then + : +else + { { echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details." >&5 +echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +if test -n "$ac_tool_prefix"; then + for ac_prog in gcc + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CC="$ac_tool_prefix$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + test -n "$CC" && break + done +fi +if test -z "$CC"; then + ac_ct_CC=$CC + for ac_prog in gcc +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_ac_ct_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_CC="$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 +echo "${ECHO_T}$ac_ct_CC" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + test -n "$ac_ct_CC" && break +done + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&5 +echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +fi + + +test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH +See \`config.log' for more details." >&5 +echo "$as_me: error: no acceptable C compiler found in \$PATH +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } + +# Provide some information about the compiler. +echo "$as_me:$LINENO: checking for C compiler version" >&5 +ac_compiler=`set X $ac_compile; echo $2` +{ (ac_try="$ac_compiler --version >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compiler --version >&5") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (ac_try="$ac_compiler -v >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compiler -v >&5") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (ac_try="$ac_compiler -V >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compiler -V >&5") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + +{ echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5 +echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6; } +if test "${ac_cv_c_compiler_gnu+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_compiler_gnu=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_compiler_gnu=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_c_compiler_gnu=$ac_compiler_gnu + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5 +echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6; } +GCC=`test $ac_compiler_gnu = yes && echo yes` +ac_test_CFLAGS=${CFLAGS+set} +ac_save_CFLAGS=$CFLAGS +{ echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5 +echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6; } +if test "${ac_cv_prog_cc_g+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_save_c_werror_flag=$ac_c_werror_flag + ac_c_werror_flag=yes + ac_cv_prog_cc_g=no + CFLAGS="-g" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_prog_cc_g=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + CFLAGS="" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_c_werror_flag=$ac_save_c_werror_flag + CFLAGS="-g" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_prog_cc_g=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_c_werror_flag=$ac_save_c_werror_flag +fi +{ echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5 +echo "${ECHO_T}$ac_cv_prog_cc_g" >&6; } +if test "$ac_test_CFLAGS" = set; then + CFLAGS=$ac_save_CFLAGS +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi +{ echo "$as_me:$LINENO: checking for $CC option to accept ISO C89" >&5 +echo $ECHO_N "checking for $CC option to accept ISO C89... $ECHO_C" >&6; } +if test "${ac_cv_prog_cc_c89+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_prog_cc_c89=no +ac_save_CC=$CC +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include +#include +#include +/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ +struct buf { int x; }; +FILE * (*rcsopen) (struct buf *, struct stat *, int); +static char *e (p, i) + char **p; + int i; +{ + return p[i]; +} +static char *f (char * (*g) (char **, int), char **p, ...) +{ + char *s; + va_list v; + va_start (v,p); + s = g (p, va_arg (v,int)); + va_end (v); + return s; +} + +/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has + function prototypes and stuff, but not '\xHH' hex character constants. + These don't provoke an error unfortunately, instead are silently treated + as 'x'. The following induces an error, until -std is added to get + proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an + array size at least. It's necessary to write '\x00'==0 to get something + that's true only with -std. */ +int osf4_cc_array ['\x00' == 0 ? 1 : -1]; + +/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters + inside strings and character constants. */ +#define FOO(x) 'x' +int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; + +int test (int i, double x); +struct s1 {int (*f) (int a);}; +struct s2 {int (*f) (double a);}; +int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); +int argc; +char **argv; +int +main () +{ +return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; + ; + return 0; +} +_ACEOF +for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ + -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" +do + CC="$ac_save_CC $ac_arg" + rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_prog_cc_c89=$ac_arg +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext + test "x$ac_cv_prog_cc_c89" != "xno" && break +done +rm -f conftest.$ac_ext +CC=$ac_save_CC + +fi +# AC_CACHE_VAL +case "x$ac_cv_prog_cc_c89" in + x) + { echo "$as_me:$LINENO: result: none needed" >&5 +echo "${ECHO_T}none needed" >&6; } ;; + xno) + { echo "$as_me:$LINENO: result: unsupported" >&5 +echo "${ECHO_T}unsupported" >&6; } ;; + *) + CC="$CC $ac_cv_prog_cc_c89" + { echo "$as_me:$LINENO: result: $ac_cv_prog_cc_c89" >&5 +echo "${ECHO_T}$ac_cv_prog_cc_c89" >&6; } ;; +esac + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu +if test -z "$CXX"; then + if test -n "$CCC"; then + CXX=$CCC + else + if test -n "$ac_tool_prefix"; then + for ac_prog in g++ + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_CXX+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CXX"; then + ac_cv_prog_CXX="$CXX" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CXX="$ac_tool_prefix$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +CXX=$ac_cv_prog_CXX +if test -n "$CXX"; then + { echo "$as_me:$LINENO: result: $CXX" >&5 +echo "${ECHO_T}$CXX" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + test -n "$CXX" && break + done +fi +if test -z "$CXX"; then + ac_ct_CXX=$CXX + for ac_prog in g++ +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_ac_ct_CXX+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_CXX"; then + ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_CXX="$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +ac_ct_CXX=$ac_cv_prog_ac_ct_CXX +if test -n "$ac_ct_CXX"; then + { echo "$as_me:$LINENO: result: $ac_ct_CXX" >&5 +echo "${ECHO_T}$ac_ct_CXX" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + test -n "$ac_ct_CXX" && break +done + + if test "x$ac_ct_CXX" = x; then + CXX="g++" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&5 +echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&2;} +ac_tool_warned=yes ;; +esac + CXX=$ac_ct_CXX + fi +fi + + fi +fi +# Provide some information about the compiler. +echo "$as_me:$LINENO: checking for C++ compiler version" >&5 +ac_compiler=`set X $ac_compile; echo $2` +{ (ac_try="$ac_compiler --version >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compiler --version >&5") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (ac_try="$ac_compiler -v >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compiler -v >&5") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (ac_try="$ac_compiler -V >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compiler -V >&5") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + +{ echo "$as_me:$LINENO: checking whether we are using the GNU C++ compiler" >&5 +echo $ECHO_N "checking whether we are using the GNU C++ compiler... $ECHO_C" >&6; } +if test "${ac_cv_cxx_compiler_gnu+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_compiler_gnu=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_compiler_gnu=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_cxx_compiler_gnu=$ac_compiler_gnu + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_cxx_compiler_gnu" >&5 +echo "${ECHO_T}$ac_cv_cxx_compiler_gnu" >&6; } +GXX=`test $ac_compiler_gnu = yes && echo yes` +ac_test_CXXFLAGS=${CXXFLAGS+set} +ac_save_CXXFLAGS=$CXXFLAGS +{ echo "$as_me:$LINENO: checking whether $CXX accepts -g" >&5 +echo $ECHO_N "checking whether $CXX accepts -g... $ECHO_C" >&6; } +if test "${ac_cv_prog_cxx_g+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_save_cxx_werror_flag=$ac_cxx_werror_flag + ac_cxx_werror_flag=yes + ac_cv_prog_cxx_g=no + CXXFLAGS="-g" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_prog_cxx_g=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + CXXFLAGS="" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cxx_werror_flag=$ac_save_cxx_werror_flag + CXXFLAGS="-g" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_prog_cxx_g=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_cxx_werror_flag=$ac_save_cxx_werror_flag +fi +{ echo "$as_me:$LINENO: result: $ac_cv_prog_cxx_g" >&5 +echo "${ECHO_T}$ac_cv_prog_cxx_g" >&6; } +if test "$ac_test_CXXFLAGS" = set; then + CXXFLAGS=$ac_save_CXXFLAGS +elif test $ac_cv_prog_cxx_g = yes; then + if test "$GXX" = yes; then + CXXFLAGS="-g -O2" + else + CXXFLAGS="-g" + fi +else + if test "$GXX" = yes; then + CXXFLAGS="-O2" + else + CXXFLAGS= + fi +fi +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +{ echo "$as_me:$LINENO: checking for BSD-compatible nm" >&5 +echo $ECHO_N "checking for BSD-compatible nm... $ECHO_C" >&6; } +if test "${lt_cv_path_NM+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$NM"; then + # Let the user override the test. + lt_cv_path_NM="$NM" +else + lt_nm_to_check="${ac_tool_prefix}nm" + if test -n "$ac_tool_prefix" && test "$build" = "$host"; then + lt_nm_to_check="$lt_nm_to_check nm" + fi + for lt_tmp_nm in $lt_nm_to_check; do + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + tmp_nm="$ac_dir/$lt_tmp_nm" + if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then + # Check to see if the nm accepts a BSD-compat flag. + # Adding the `sed 1q' prevents false positives on HP-UX, which says: + # nm: unknown option "B" ignored + # Tru64's nm complains that /dev/null is an invalid object file + case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in + */dev/null* | *'Invalid file or object type'*) + lt_cv_path_NM="$tmp_nm -B" + break + ;; + *) + case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in + */dev/null*) + lt_cv_path_NM="$tmp_nm -p" + break + ;; + *) + lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but + continue # so that we can try to find one that supports BSD flags + ;; + esac + ;; + esac + fi + done + IFS="$lt_save_ifs" + done + test -z "$lt_cv_path_NM" && lt_cv_path_NM=nm +fi +fi +{ echo "$as_me:$LINENO: result: $lt_cv_path_NM" >&5 +echo "${ECHO_T}$lt_cv_path_NM" >&6; } +NM="$lt_cv_path_NM" + + + +{ echo "$as_me:$LINENO: checking for GNU make" >&5 +echo $ECHO_N "checking for GNU make... $ECHO_C" >&6; } +if test "${llvm_cv_gnu_make_command+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + llvm_cv_gnu_make_command='' + for a in "$MAKE" make gmake gnumake ; do + if test -z "$a" ; then continue ; fi ; + if ( sh -c "$a --version" 2> /dev/null | grep GNU 2>&1 > /dev/null ) + then + llvm_cv_gnu_make_command=$a ; + break; + fi + done +fi +{ echo "$as_me:$LINENO: result: $llvm_cv_gnu_make_command" >&5 +echo "${ECHO_T}$llvm_cv_gnu_make_command" >&6; } + if test "x$llvm_cv_gnu_make_command" != "x" ; then + ifGNUmake='' ; + else + ifGNUmake='#' ; + { echo "$as_me:$LINENO: result: \"Not found\"" >&5 +echo "${ECHO_T}\"Not found\"" >&6; }; + fi + + +{ echo "$as_me:$LINENO: checking whether ln -s works" >&5 +echo $ECHO_N "checking whether ln -s works... $ECHO_C" >&6; } +LN_S=$as_ln_s +if test "$LN_S" = "ln -s"; then + { echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6; } +else + { echo "$as_me:$LINENO: result: no, using $LN_S" >&5 +echo "${ECHO_T}no, using $LN_S" >&6; } +fi + +# Extract the first word of "cmp", so it can be a program name with args. +set dummy cmp; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_CMP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $CMP in + [\\/]* | ?:[\\/]*) + ac_cv_path_CMP="$CMP" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_CMP="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + test -z "$ac_cv_path_CMP" && ac_cv_path_CMP="cmp" + ;; +esac +fi +CMP=$ac_cv_path_CMP +if test -n "$CMP"; then + { echo "$as_me:$LINENO: result: $CMP" >&5 +echo "${ECHO_T}$CMP" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +# Extract the first word of "cp", so it can be a program name with args. +set dummy cp; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_CP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $CP in + [\\/]* | ?:[\\/]*) + ac_cv_path_CP="$CP" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_CP="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + test -z "$ac_cv_path_CP" && ac_cv_path_CP="cp" + ;; +esac +fi +CP=$ac_cv_path_CP +if test -n "$CP"; then + { echo "$as_me:$LINENO: result: $CP" >&5 +echo "${ECHO_T}$CP" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +# Extract the first word of "date", so it can be a program name with args. +set dummy date; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_DATE+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $DATE in + [\\/]* | ?:[\\/]*) + ac_cv_path_DATE="$DATE" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_DATE="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + test -z "$ac_cv_path_DATE" && ac_cv_path_DATE="date" + ;; +esac +fi +DATE=$ac_cv_path_DATE +if test -n "$DATE"; then + { echo "$as_me:$LINENO: result: $DATE" >&5 +echo "${ECHO_T}$DATE" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +# Extract the first word of "find", so it can be a program name with args. +set dummy find; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_FIND+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $FIND in + [\\/]* | ?:[\\/]*) + ac_cv_path_FIND="$FIND" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_FIND="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + test -z "$ac_cv_path_FIND" && ac_cv_path_FIND="find" + ;; +esac +fi +FIND=$ac_cv_path_FIND +if test -n "$FIND"; then + { echo "$as_me:$LINENO: result: $FIND" >&5 +echo "${ECHO_T}$FIND" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +# Extract the first word of "grep", so it can be a program name with args. +set dummy grep; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_GREP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $GREP in + [\\/]* | ?:[\\/]*) + ac_cv_path_GREP="$GREP" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_GREP="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + test -z "$ac_cv_path_GREP" && ac_cv_path_GREP="grep" + ;; +esac +fi +GREP=$ac_cv_path_GREP +if test -n "$GREP"; then + { echo "$as_me:$LINENO: result: $GREP" >&5 +echo "${ECHO_T}$GREP" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +# Extract the first word of "mkdir", so it can be a program name with args. +set dummy mkdir; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_MKDIR+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $MKDIR in + [\\/]* | ?:[\\/]*) + ac_cv_path_MKDIR="$MKDIR" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_MKDIR="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + test -z "$ac_cv_path_MKDIR" && ac_cv_path_MKDIR="mkdir" + ;; +esac +fi +MKDIR=$ac_cv_path_MKDIR +if test -n "$MKDIR"; then + { echo "$as_me:$LINENO: result: $MKDIR" >&5 +echo "${ECHO_T}$MKDIR" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +# Extract the first word of "mv", so it can be a program name with args. +set dummy mv; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_MV+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $MV in + [\\/]* | ?:[\\/]*) + ac_cv_path_MV="$MV" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_MV="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + test -z "$ac_cv_path_MV" && ac_cv_path_MV="mv" + ;; +esac +fi +MV=$ac_cv_path_MV +if test -n "$MV"; then + { echo "$as_me:$LINENO: result: $MV" >&5 +echo "${ECHO_T}$MV" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. +set dummy ${ac_tool_prefix}ranlib; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_RANLIB+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$RANLIB"; then + ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +RANLIB=$ac_cv_prog_RANLIB +if test -n "$RANLIB"; then + { echo "$as_me:$LINENO: result: $RANLIB" >&5 +echo "${ECHO_T}$RANLIB" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_RANLIB"; then + ac_ct_RANLIB=$RANLIB + # Extract the first word of "ranlib", so it can be a program name with args. +set dummy ranlib; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_RANLIB"; then + ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_RANLIB="ranlib" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB +if test -n "$ac_ct_RANLIB"; then + { echo "$as_me:$LINENO: result: $ac_ct_RANLIB" >&5 +echo "${ECHO_T}$ac_ct_RANLIB" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + if test "x$ac_ct_RANLIB" = x; then + RANLIB=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&5 +echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&2;} +ac_tool_warned=yes ;; +esac + RANLIB=$ac_ct_RANLIB + fi +else + RANLIB="$ac_cv_prog_RANLIB" +fi + +# Extract the first word of "rm", so it can be a program name with args. +set dummy rm; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_RM+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $RM in + [\\/]* | ?:[\\/]*) + ac_cv_path_RM="$RM" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_RM="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + test -z "$ac_cv_path_RM" && ac_cv_path_RM="rm" + ;; +esac +fi +RM=$ac_cv_path_RM +if test -n "$RM"; then + { echo "$as_me:$LINENO: result: $RM" >&5 +echo "${ECHO_T}$RM" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +# Extract the first word of "sed", so it can be a program name with args. +set dummy sed; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_SED+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $SED in + [\\/]* | ?:[\\/]*) + ac_cv_path_SED="$SED" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_SED="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + test -z "$ac_cv_path_SED" && ac_cv_path_SED="sed" + ;; +esac +fi +SED=$ac_cv_path_SED +if test -n "$SED"; then + { echo "$as_me:$LINENO: result: $SED" >&5 +echo "${ECHO_T}$SED" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +# Extract the first word of "tar", so it can be a program name with args. +set dummy tar; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_TAR+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $TAR in + [\\/]* | ?:[\\/]*) + ac_cv_path_TAR="$TAR" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_TAR="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + test -z "$ac_cv_path_TAR" && ac_cv_path_TAR="gtar" + ;; +esac +fi +TAR=$ac_cv_path_TAR +if test -n "$TAR"; then + { echo "$as_me:$LINENO: result: $TAR" >&5 +echo "${ECHO_T}$TAR" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +# Extract the first word of "pwd", so it can be a program name with args. +set dummy pwd; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_BINPWD+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $BINPWD in + [\\/]* | ?:[\\/]*) + ac_cv_path_BINPWD="$BINPWD" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_BINPWD="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + test -z "$ac_cv_path_BINPWD" && ac_cv_path_BINPWD="pwd" + ;; +esac +fi +BINPWD=$ac_cv_path_BINPWD +if test -n "$BINPWD"; then + { echo "$as_me:$LINENO: result: $BINPWD" >&5 +echo "${ECHO_T}$BINPWD" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + +# Extract the first word of "Graphviz", so it can be a program name with args. +set dummy Graphviz; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_GRAPHVIZ+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $GRAPHVIZ in + [\\/]* | ?:[\\/]*) + ac_cv_path_GRAPHVIZ="$GRAPHVIZ" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_GRAPHVIZ="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + test -z "$ac_cv_path_GRAPHVIZ" && ac_cv_path_GRAPHVIZ="echo Graphviz" + ;; +esac +fi +GRAPHVIZ=$ac_cv_path_GRAPHVIZ +if test -n "$GRAPHVIZ"; then + { echo "$as_me:$LINENO: result: $GRAPHVIZ" >&5 +echo "${ECHO_T}$GRAPHVIZ" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +if test "$GRAPHVIZ" != "echo Graphviz" ; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_GRAPHVIZ 1 +_ACEOF + + if test "$llvm_cv_os_type" = "MingW" ; then + GRAPHVIZ=`echo $GRAPHVIZ | sed 's/^\/\([A-Za-z]\)\//\1:\//' ` + fi + +cat >>confdefs.h <<_ACEOF +#define LLVM_PATH_GRAPHVIZ "$GRAPHVIZ${EXEEXT}" +_ACEOF + +fi +# Extract the first word of "dot", so it can be a program name with args. +set dummy dot; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_DOT+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $DOT in + [\\/]* | ?:[\\/]*) + ac_cv_path_DOT="$DOT" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_DOT="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + test -z "$ac_cv_path_DOT" && ac_cv_path_DOT="echo dot" + ;; +esac +fi +DOT=$ac_cv_path_DOT +if test -n "$DOT"; then + { echo "$as_me:$LINENO: result: $DOT" >&5 +echo "${ECHO_T}$DOT" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +if test "$DOT" != "echo dot" ; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_DOT 1 +_ACEOF + + if test "$llvm_cv_os_type" = "MingW" ; then + DOT=`echo $DOT | sed 's/^\/\([A-Za-z]\)\//\1:\//' ` + fi + +cat >>confdefs.h <<_ACEOF +#define LLVM_PATH_DOT "$DOT${EXEEXT}" +_ACEOF + +fi +# Extract the first word of "fdp", so it can be a program name with args. +set dummy fdp; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_FDP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $FDP in + [\\/]* | ?:[\\/]*) + ac_cv_path_FDP="$FDP" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_FDP="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + test -z "$ac_cv_path_FDP" && ac_cv_path_FDP="echo fdp" + ;; +esac +fi +FDP=$ac_cv_path_FDP +if test -n "$FDP"; then + { echo "$as_me:$LINENO: result: $FDP" >&5 +echo "${ECHO_T}$FDP" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +if test "$FDP" != "echo fdp" ; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_FDP 1 +_ACEOF + + if test "$llvm_cv_os_type" = "MingW" ; then + FDP=`echo $FDP | sed 's/^\/\([A-Za-z]\)\//\1:\//' ` + fi + +cat >>confdefs.h <<_ACEOF +#define LLVM_PATH_FDP "$FDP${EXEEXT}" +_ACEOF + +fi +# Extract the first word of "neato", so it can be a program name with args. +set dummy neato; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_NEATO+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $NEATO in + [\\/]* | ?:[\\/]*) + ac_cv_path_NEATO="$NEATO" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_NEATO="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + test -z "$ac_cv_path_NEATO" && ac_cv_path_NEATO="echo neato" + ;; +esac +fi +NEATO=$ac_cv_path_NEATO +if test -n "$NEATO"; then + { echo "$as_me:$LINENO: result: $NEATO" >&5 +echo "${ECHO_T}$NEATO" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +if test "$NEATO" != "echo neato" ; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_NEATO 1 +_ACEOF + + if test "$llvm_cv_os_type" = "MingW" ; then + NEATO=`echo $NEATO | sed 's/^\/\([A-Za-z]\)\//\1:\//' ` + fi + +cat >>confdefs.h <<_ACEOF +#define LLVM_PATH_NEATO "$NEATO${EXEEXT}" +_ACEOF + +fi +# Extract the first word of "twopi", so it can be a program name with args. +set dummy twopi; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_TWOPI+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $TWOPI in + [\\/]* | ?:[\\/]*) + ac_cv_path_TWOPI="$TWOPI" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_TWOPI="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + test -z "$ac_cv_path_TWOPI" && ac_cv_path_TWOPI="echo twopi" + ;; +esac +fi +TWOPI=$ac_cv_path_TWOPI +if test -n "$TWOPI"; then + { echo "$as_me:$LINENO: result: $TWOPI" >&5 +echo "${ECHO_T}$TWOPI" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +if test "$TWOPI" != "echo twopi" ; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_TWOPI 1 +_ACEOF + + if test "$llvm_cv_os_type" = "MingW" ; then + TWOPI=`echo $TWOPI | sed 's/^\/\([A-Za-z]\)\//\1:\//' ` + fi + +cat >>confdefs.h <<_ACEOF +#define LLVM_PATH_TWOPI "$TWOPI${EXEEXT}" +_ACEOF + +fi +# Extract the first word of "circo", so it can be a program name with args. +set dummy circo; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_CIRCO+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $CIRCO in + [\\/]* | ?:[\\/]*) + ac_cv_path_CIRCO="$CIRCO" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_CIRCO="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + test -z "$ac_cv_path_CIRCO" && ac_cv_path_CIRCO="echo circo" + ;; +esac +fi +CIRCO=$ac_cv_path_CIRCO +if test -n "$CIRCO"; then + { echo "$as_me:$LINENO: result: $CIRCO" >&5 +echo "${ECHO_T}$CIRCO" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +if test "$CIRCO" != "echo circo" ; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_CIRCO 1 +_ACEOF + + if test "$llvm_cv_os_type" = "MingW" ; then + CIRCO=`echo $CIRCO | sed 's/^\/\([A-Za-z]\)\//\1:\//' ` + fi + +cat >>confdefs.h <<_ACEOF +#define LLVM_PATH_CIRCO "$CIRCO${EXEEXT}" +_ACEOF + +fi +for ac_prog in gv gsview32 +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_GV+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $GV in + [\\/]* | ?:[\\/]*) + ac_cv_path_GV="$GV" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_GV="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + ;; +esac +fi +GV=$ac_cv_path_GV +if test -n "$GV"; then + { echo "$as_me:$LINENO: result: $GV" >&5 +echo "${ECHO_T}$GV" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + test -n "$GV" && break +done +test -n "$GV" || GV="echo gv" + +if test "$GV" != "echo gv" ; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_GV 1 +_ACEOF + + if test "$llvm_cv_os_type" = "MingW" ; then + GV=`echo $GV | sed 's/^\/\([A-Za-z]\)\//\1:\//' ` + fi + +cat >>confdefs.h <<_ACEOF +#define LLVM_PATH_GV "$GV${EXEEXT}" +_ACEOF + +fi +# Extract the first word of "dotty", so it can be a program name with args. +set dummy dotty; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_DOTTY+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $DOTTY in + [\\/]* | ?:[\\/]*) + ac_cv_path_DOTTY="$DOTTY" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_DOTTY="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + test -z "$ac_cv_path_DOTTY" && ac_cv_path_DOTTY="echo dotty" + ;; +esac +fi +DOTTY=$ac_cv_path_DOTTY +if test -n "$DOTTY"; then + { echo "$as_me:$LINENO: result: $DOTTY" >&5 +echo "${ECHO_T}$DOTTY" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +if test "$DOTTY" != "echo dotty" ; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_DOTTY 1 +_ACEOF + + if test "$llvm_cv_os_type" = "MingW" ; then + DOTTY=`echo $DOTTY | sed 's/^\/\([A-Za-z]\)\//\1:\//' ` + fi + +cat >>confdefs.h <<_ACEOF +#define LLVM_PATH_DOTTY "$DOTTY${EXEEXT}" +_ACEOF + +fi + + +# Extract the first word of "perl", so it can be a program name with args. +set dummy perl; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_PERL+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $PERL in + [\\/]* | ?:[\\/]*) + ac_cv_path_PERL="$PERL" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_PERL="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + test -z "$ac_cv_path_PERL" && ac_cv_path_PERL="none" + ;; +esac +fi +PERL=$ac_cv_path_PERL +if test -n "$PERL"; then + { echo "$as_me:$LINENO: result: $PERL" >&5 +echo "${ECHO_T}$PERL" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +if test "$PERL" != "none"; then + { echo "$as_me:$LINENO: checking for Perl 5.006 or newer" >&5 +echo $ECHO_N "checking for Perl 5.006 or newer... $ECHO_C" >&6; } + if $PERL -e 'use 5.006;' 2>&1 > /dev/null; then + { echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6; } + else + PERL=none + { echo "$as_me:$LINENO: result: not found" >&5 +echo "${ECHO_T}not found" >&6; } + fi +fi + + +if test x"$PERL" = xnone; then + HAVE_PERL=0 + + { { echo "$as_me:$LINENO: error: perl is required but was not found, please install it" >&5 +echo "$as_me: error: perl is required but was not found, please install it" >&2;} + { (exit 1); exit 1; }; } +else + HAVE_PERL=1 + +fi + +# Find a good install program. We prefer a C program (faster), +# so one script is as good as another. But avoid the broken or +# incompatible versions: +# SysV /etc/install, /usr/sbin/install +# SunOS /usr/etc/install +# IRIX /sbin/install +# AIX /bin/install +# AmigaOS /C/install, which installs bootblocks on floppy discs +# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag +# AFS /usr/afsws/bin/install, which mishandles nonexistent args +# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# OS/2's system install, which has a completely different semantic +# ./install, which can be erroneously created by make from ./install.sh. +{ echo "$as_me:$LINENO: checking for a BSD-compatible install" >&5 +echo $ECHO_N "checking for a BSD-compatible install... $ECHO_C" >&6; } +if test -z "$INSTALL"; then +if test "${ac_cv_path_install+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + # Account for people who put trailing slashes in PATH elements. +case $as_dir/ in + ./ | .// | /cC/* | \ + /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ + ?:\\/os2\\/install\\/* | ?:\\/OS2\\/INSTALL\\/* | \ + /usr/ucb/* ) ;; + *) + # OSF1 and SCO ODT 3.0 have their own names for install. + # Don't use installbsd from OSF since it installs stuff as root + # by default. + for ac_prog in ginstall scoinst install; do + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_executable_p "$as_dir/$ac_prog$ac_exec_ext"; }; then + if test $ac_prog = install && + grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # AIX install. It has an incompatible calling convention. + : + elif test $ac_prog = install && + grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # program-specific install script used by HP pwplus--don't use. + : + else + ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" + break 3 + fi + fi + done + done + ;; +esac +done +IFS=$as_save_IFS + + +fi + if test "${ac_cv_path_install+set}" = set; then + INSTALL=$ac_cv_path_install + else + # As a last resort, use the slow shell script. Don't cache a + # value for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the value is a relative name. + INSTALL=$ac_install_sh + fi +fi +{ echo "$as_me:$LINENO: result: $INSTALL" >&5 +echo "${ECHO_T}$INSTALL" >&6; } + +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' + +test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' + +test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' + + +# Extract the first word of "bzip2", so it can be a program name with args. +set dummy bzip2; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_BZIP2+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $BZIP2 in + [\\/]* | ?:[\\/]*) + ac_cv_path_BZIP2="$BZIP2" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_BZIP2="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + ;; +esac +fi +BZIP2=$ac_cv_path_BZIP2 +if test -n "$BZIP2"; then + { echo "$as_me:$LINENO: result: $BZIP2" >&5 +echo "${ECHO_T}$BZIP2" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +# Extract the first word of "doxygen", so it can be a program name with args. +set dummy doxygen; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_DOXYGEN+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $DOXYGEN in + [\\/]* | ?:[\\/]*) + ac_cv_path_DOXYGEN="$DOXYGEN" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_DOXYGEN="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + ;; +esac +fi +DOXYGEN=$ac_cv_path_DOXYGEN +if test -n "$DOXYGEN"; then + { echo "$as_me:$LINENO: result: $DOXYGEN" >&5 +echo "${ECHO_T}$DOXYGEN" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +# Extract the first word of "groff", so it can be a program name with args. +set dummy groff; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_GROFF+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $GROFF in + [\\/]* | ?:[\\/]*) + ac_cv_path_GROFF="$GROFF" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_GROFF="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + ;; +esac +fi +GROFF=$ac_cv_path_GROFF +if test -n "$GROFF"; then + { echo "$as_me:$LINENO: result: $GROFF" >&5 +echo "${ECHO_T}$GROFF" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +# Extract the first word of "gzip", so it can be a program name with args. +set dummy gzip; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_GZIP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $GZIP in + [\\/]* | ?:[\\/]*) + ac_cv_path_GZIP="$GZIP" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_GZIP="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + ;; +esac +fi +GZIP=$ac_cv_path_GZIP +if test -n "$GZIP"; then + { echo "$as_me:$LINENO: result: $GZIP" >&5 +echo "${ECHO_T}$GZIP" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +# Extract the first word of "pod2html", so it can be a program name with args. +set dummy pod2html; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_POD2HTML+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $POD2HTML in + [\\/]* | ?:[\\/]*) + ac_cv_path_POD2HTML="$POD2HTML" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_POD2HTML="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + ;; +esac +fi +POD2HTML=$ac_cv_path_POD2HTML +if test -n "$POD2HTML"; then + { echo "$as_me:$LINENO: result: $POD2HTML" >&5 +echo "${ECHO_T}$POD2HTML" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +# Extract the first word of "pod2man", so it can be a program name with args. +set dummy pod2man; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_POD2MAN+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $POD2MAN in + [\\/]* | ?:[\\/]*) + ac_cv_path_POD2MAN="$POD2MAN" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_POD2MAN="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + ;; +esac +fi +POD2MAN=$ac_cv_path_POD2MAN +if test -n "$POD2MAN"; then + { echo "$as_me:$LINENO: result: $POD2MAN" >&5 +echo "${ECHO_T}$POD2MAN" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +# Extract the first word of "runtest", so it can be a program name with args. +set dummy runtest; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_RUNTEST+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $RUNTEST in + [\\/]* | ?:[\\/]*) + ac_cv_path_RUNTEST="$RUNTEST" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_RUNTEST="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + ;; +esac +fi +RUNTEST=$ac_cv_path_RUNTEST +if test -n "$RUNTEST"; then + { echo "$as_me:$LINENO: result: $RUNTEST" >&5 +echo "${ECHO_T}$RUNTEST" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + +no_itcl=true +{ echo "$as_me:$LINENO: checking for the tclsh program in tclinclude directory" >&5 +echo $ECHO_N "checking for the tclsh program in tclinclude directory... $ECHO_C" >&6; } + +# Check whether --with-tclinclude was given. +if test "${with_tclinclude+set}" = set; then + withval=$with_tclinclude; with_tclinclude=${withval} +else + with_tclinclude='' +fi + +if test "${ac_cv_path_tclsh+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + +if test x"${with_tclinclude}" != x ; then + if test -f ${with_tclinclude}/tclsh ; then + ac_cv_path_tclsh=`(cd ${with_tclinclude}; pwd)` + elif test -f ${with_tclinclude}/src/tclsh ; then + ac_cv_path_tclsh=`(cd ${with_tclinclude}/src; pwd)` + else + { { echo "$as_me:$LINENO: error: ${with_tclinclude} directory doesn't contain tclsh" >&5 +echo "$as_me: error: ${with_tclinclude} directory doesn't contain tclsh" >&2;} + { (exit 1); exit 1; }; } + fi +fi + +if test x"${ac_cv_path_tclsh}" = x ; then + { echo "$as_me:$LINENO: result: none" >&5 +echo "${ECHO_T}none" >&6; } + for ac_prog in tclsh8.4 tclsh8.4.8 tclsh8.4.7 tclsh8.4.6 tclsh8.4.5 tclsh8.4.4 tclsh8.4.3 tclsh8.4.2 tclsh8.4.1 tclsh8.4.0 tclsh8.3 tclsh8.3.5 tclsh8.3.4 tclsh8.3.3 tclsh8.3.2 tclsh8.3.1 tclsh8.3.0 tclsh +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_TCLSH+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $TCLSH in + [\\/]* | ?:[\\/]*) + ac_cv_path_TCLSH="$TCLSH" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_TCLSH="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + ;; +esac +fi +TCLSH=$ac_cv_path_TCLSH +if test -n "$TCLSH"; then + { echo "$as_me:$LINENO: result: $TCLSH" >&5 +echo "${ECHO_T}$TCLSH" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + test -n "$TCLSH" && break +done + + if test x"${TCLSH}" = x ; then + ac_cv_path_tclsh=''; + else + ac_cv_path_tclsh="${TCLSH}"; + fi +else + { echo "$as_me:$LINENO: result: ${ac_cv_path_tclsh}" >&5 +echo "${ECHO_T}${ac_cv_path_tclsh}" >&6; } + TCLSH="${ac_cv_path_tclsh}" + +fi + +fi + +# Extract the first word of "zip", so it can be a program name with args. +set dummy zip; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_ZIP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $ZIP in + [\\/]* | ?:[\\/]*) + ac_cv_path_ZIP="$ZIP" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_ZIP="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + ;; +esac +fi +ZIP=$ac_cv_path_ZIP +if test -n "$ZIP"; then + { echo "$as_me:$LINENO: result: $ZIP" >&5 +echo "${ECHO_T}$ZIP" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +for ac_prog in ocamlc +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_OCAMLC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $OCAMLC in + [\\/]* | ?:[\\/]*) + ac_cv_path_OCAMLC="$OCAMLC" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_OCAMLC="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + ;; +esac +fi +OCAMLC=$ac_cv_path_OCAMLC +if test -n "$OCAMLC"; then + { echo "$as_me:$LINENO: result: $OCAMLC" >&5 +echo "${ECHO_T}$OCAMLC" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + test -n "$OCAMLC" && break +done + +for ac_prog in ocamlopt +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_OCAMLOPT+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $OCAMLOPT in + [\\/]* | ?:[\\/]*) + ac_cv_path_OCAMLOPT="$OCAMLOPT" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_OCAMLOPT="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + ;; +esac +fi +OCAMLOPT=$ac_cv_path_OCAMLOPT +if test -n "$OCAMLOPT"; then + { echo "$as_me:$LINENO: result: $OCAMLOPT" >&5 +echo "${ECHO_T}$OCAMLOPT" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + test -n "$OCAMLOPT" && break +done + +for ac_prog in ocamldep +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_OCAMLDEP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $OCAMLDEP in + [\\/]* | ?:[\\/]*) + ac_cv_path_OCAMLDEP="$OCAMLDEP" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_OCAMLDEP="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + ;; +esac +fi +OCAMLDEP=$ac_cv_path_OCAMLDEP +if test -n "$OCAMLDEP"; then + { echo "$as_me:$LINENO: result: $OCAMLDEP" >&5 +echo "${ECHO_T}$OCAMLDEP" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + test -n "$OCAMLDEP" && break +done + +for ac_prog in ocamldoc +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_OCAMLDOC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $OCAMLDOC in + [\\/]* | ?:[\\/]*) + ac_cv_path_OCAMLDOC="$OCAMLDOC" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_OCAMLDOC="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + ;; +esac +fi +OCAMLDOC=$ac_cv_path_OCAMLDOC +if test -n "$OCAMLDOC"; then + { echo "$as_me:$LINENO: result: $OCAMLDOC" >&5 +echo "${ECHO_T}$OCAMLDOC" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + test -n "$OCAMLDOC" && break +done + +for ac_prog in gas as +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_GAS+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $GAS in + [\\/]* | ?:[\\/]*) + ac_cv_path_GAS="$GAS" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_GAS="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + ;; +esac +fi +GAS=$ac_cv_path_GAS +if test -n "$GAS"; then + { echo "$as_me:$LINENO: result: $GAS" >&5 +echo "${ECHO_T}$GAS" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + test -n "$GAS" && break +done + + +{ echo "$as_me:$LINENO: checking for compiler -Wl,-R option" >&5 +echo $ECHO_N "checking for compiler -Wl,-R option... $ECHO_C" >&6; } +if test "${llvm_cv_link_use_r+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + oldcflags="$CFLAGS" + CFLAGS="$CFLAGS -Wl,-R." + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ +int main() { return 0; } + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + llvm_cv_link_use_r=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + llvm_cv_link_use_r=no +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CFLAGS="$oldcflags" + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +fi +{ echo "$as_me:$LINENO: result: $llvm_cv_link_use_r" >&5 +echo "${ECHO_T}$llvm_cv_link_use_r" >&6; } +if test "$llvm_cv_link_use_r" = yes ; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_LINK_R 1 +_ACEOF + + fi + + +{ echo "$as_me:$LINENO: checking for compiler -Wl,-export-dynamic option" >&5 +echo $ECHO_N "checking for compiler -Wl,-export-dynamic option... $ECHO_C" >&6; } +if test "${llvm_cv_link_use_export_dynamic+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + oldcflags="$CFLAGS" + CFLAGS="$CFLAGS -Wl,-export-dynamic" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ +int main() { return 0; } + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + llvm_cv_link_use_export_dynamic=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + llvm_cv_link_use_export_dynamic=no +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CFLAGS="$oldcflags" + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +fi +{ echo "$as_me:$LINENO: result: $llvm_cv_link_use_export_dynamic" >&5 +echo "${ECHO_T}$llvm_cv_link_use_export_dynamic" >&6; } +if test "$llvm_cv_link_use_export_dynamic" = yes ; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_LINK_EXPORT_DYNAMIC 1 +_ACEOF + + fi + + + + +{ echo "$as_me:$LINENO: checking for an ANSI C-conforming const" >&5 +echo $ECHO_N "checking for an ANSI C-conforming const... $ECHO_C" >&6; } +if test "${ac_cv_c_const+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ +/* FIXME: Include the comments suggested by Paul. */ +#ifndef __cplusplus + /* Ultrix mips cc rejects this. */ + typedef int charset[2]; + const charset x; + /* SunOS 4.1.1 cc rejects this. */ + char const *const *ccp; + char **p; + /* NEC SVR4.0.2 mips cc rejects this. */ + struct point {int x, y;}; + static struct point const zero = {0,0}; + /* AIX XL C 1.02.0.0 rejects this. + It does not let you subtract one const X* pointer from another in + an arm of an if-expression whose if-part is not a constant + expression */ + const char *g = "string"; + ccp = &g + (g ? g-g : 0); + /* HPUX 7.0 cc rejects these. */ + ++ccp; + p = (char**) ccp; + ccp = (char const *const *) p; + { /* SCO 3.2v4 cc rejects this. */ + char *t; + char const *s = 0 ? (char *) 0 : (char const *) 0; + + *t++ = 0; + if (s) return 0; + } + { /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */ + int x[] = {25, 17}; + const int *foo = &x[0]; + ++foo; + } + { /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */ + typedef const int *iptr; + iptr p = 0; + ++p; + } + { /* AIX XL C 1.02.0.0 rejects this saying + "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */ + struct s { int j; const int *ap[3]; }; + struct s *b; b->j = 5; + } + { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */ + const int foo = 10; + if (!foo) return 0; + } + return !x[0] && !zero.x; +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_c_const=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_c_const=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ac_cv_c_const" >&5 +echo "${ECHO_T}$ac_cv_c_const" >&6; } +if test $ac_cv_c_const = no; then + +cat >>confdefs.h <<\_ACEOF +#define const +_ACEOF + +fi + + + + + + +ac_header_dirent=no +for ac_hdr in dirent.h sys/ndir.h sys/dir.h ndir.h; do + as_ac_Header=`echo "ac_cv_header_dirent_$ac_hdr" | $as_tr_sh` +{ echo "$as_me:$LINENO: checking for $ac_hdr that defines DIR" >&5 +echo $ECHO_N "checking for $ac_hdr that defines DIR... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include <$ac_hdr> + +int +main () +{ +if ((DIR *) 0) +return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_Header=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_Header=no" +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_hdr" | $as_tr_cpp` 1 +_ACEOF + +ac_header_dirent=$ac_hdr; break +fi + +done +# Two versions of opendir et al. are in -ldir and -lx on SCO Xenix. +if test $ac_header_dirent = dirent.h; then + { echo "$as_me:$LINENO: checking for library containing opendir" >&5 +echo $ECHO_N "checking for library containing opendir... $ECHO_C" >&6; } +if test "${ac_cv_search_opendir+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_func_search_save_LIBS=$LIBS +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char opendir (); +int +main () +{ +return opendir (); + ; + return 0; +} +_ACEOF +for ac_lib in '' dir; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_search_opendir=$ac_res +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if test "${ac_cv_search_opendir+set}" = set; then + break +fi +done +if test "${ac_cv_search_opendir+set}" = set; then + : +else + ac_cv_search_opendir=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_search_opendir" >&5 +echo "${ECHO_T}$ac_cv_search_opendir" >&6; } +ac_res=$ac_cv_search_opendir +if test "$ac_res" != no; then + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +fi + +else + { echo "$as_me:$LINENO: checking for library containing opendir" >&5 +echo $ECHO_N "checking for library containing opendir... $ECHO_C" >&6; } +if test "${ac_cv_search_opendir+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_func_search_save_LIBS=$LIBS +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char opendir (); +int +main () +{ +return opendir (); + ; + return 0; +} +_ACEOF +for ac_lib in '' x; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_search_opendir=$ac_res +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if test "${ac_cv_search_opendir+set}" = set; then + break +fi +done +if test "${ac_cv_search_opendir+set}" = set; then + : +else + ac_cv_search_opendir=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_search_opendir" >&5 +echo "${ECHO_T}$ac_cv_search_opendir" >&6; } +ac_res=$ac_cv_search_opendir +if test "$ac_res" != no; then + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +fi + +fi + + +for ac_header in dlfcn.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + { echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +else + # Is the header compilable? +{ echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6; } + +# Is the header present? +{ echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -f conftest.err conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + ( cat <<\_ASBOX +## ----------------------------------- ## +## Report this to llvmbugs@cs.uiuc.edu ## +## ----------------------------------- ## +_ASBOX + ) | sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +{ echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + +# Check whether --enable-ltdl-install was given. +if test "${enable_ltdl_install+set}" = set; then + enableval=$enable_ltdl_install; +fi + + + + +if test x"${enable_ltdl_install-no}" != xno; then + INSTALL_LTDL_TRUE= + INSTALL_LTDL_FALSE='#' +else + INSTALL_LTDL_TRUE='#' + INSTALL_LTDL_FALSE= +fi + + + +if test x"${enable_ltdl_convenience-no}" != xno; then + CONVENIENCE_LTDL_TRUE= + CONVENIENCE_LTDL_FALSE='#' +else + CONVENIENCE_LTDL_TRUE='#' + CONVENIENCE_LTDL_FALSE= +fi + + +{ echo "$as_me:$LINENO: checking dynamic linker characteristics" >&5 +echo $ECHO_N "checking dynamic linker characteristics... $ECHO_C" >&6; } +library_names_spec= +libname_spec='lib$name' +soname_spec= +shrext_cmds=".so" +postinstall_cmds= +postuninstall_cmds= +finish_cmds= +finish_eval= +shlibpath_var= +shlibpath_overrides_runpath=unknown +version_type=none +dynamic_linker="$host_os ld.so" +sys_lib_dlsearch_path_spec="/lib /usr/lib" +if test "$GCC" = yes; then + sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` + if echo "$sys_lib_search_path_spec" | grep ';' >/dev/null ; then + # if the path contains ";" then we assume it to be the separator + # otherwise default to the standard path separator (i.e. ":") - it is + # assumed that no part of a normal pathname contains ";" but that should + # okay in the real world where ";" in dirpaths is itself problematic. + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi +else + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" +fi +need_lib_prefix=unknown +hardcode_into_libs=no + +# when you set need_version to no, make sure it does not cause -set_version +# flags to be left without arguments +need_version=unknown + +case $host_os in +aix3*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' + shlibpath_var=LIBPATH + + # AIX 3 has no versioning support, so we append a major version to the name. + soname_spec='${libname}${release}${shared_ext}$major' + ;; + +aix4* | aix5*) + version_type=linux + need_lib_prefix=no + need_version=no + hardcode_into_libs=yes + if test "$host_cpu" = ia64; then + # AIX 5 supports IA64 + library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + else + # With GCC up to 2.95.x, collect2 would create an import file + # for dependence libraries. The import file would start with + # the line `#! .'. This would cause the generated library to + # depend on `.', always an invalid library. This was fixed in + # development snapshots of GCC prior to 3.0. + case $host_os in + aix4 | aix4.[01] | aix4.[01].*) + if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' + echo ' yes ' + echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then + : + else + can_build_shared=no + fi + ;; + esac + # AIX (on Power*) has no versioning support, so currently we can not hardcode correct + # soname into executable. Probably we can add versioning support to + # collect2, so additional links can be useful in future. + if test "$aix_use_runtimelinking" = yes; then + # If using run time linking (on AIX 4.2 or later) use lib.so + # instead of lib.a to let people know that these are not + # typical AIX shared libraries. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + else + # We preserve .a as extension for shared libraries through AIX4.2 + # and later when we are not doing run time linking. + library_names_spec='${libname}${release}.a $libname.a' + soname_spec='${libname}${release}${shared_ext}$major' + fi + shlibpath_var=LIBPATH + fi + ;; + +amigaos*) + library_names_spec='$libname.ixlibrary $libname.a' + # Create ${libname}_ixlibrary.a entries in /sys/libs. + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' + ;; + +beos*) + library_names_spec='${libname}${shared_ext}' + dynamic_linker="$host_os ld.so" + shlibpath_var=LIBRARY_PATH + ;; + +bsdi[45]*) + version_type=linux + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" + sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" + # the default ld.so.conf also contains /usr/contrib/lib and + # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow + # libtool to hard-code these into programs + ;; + +cygwin* | mingw* | pw32*) + version_type=windows + shrext_cmds=".dll" + need_version=no + need_lib_prefix=no + + case $GCC,$host_os in + yes,cygwin* | yes,mingw* | yes,pw32*) + library_names_spec='$libname.dll.a' + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \${file}`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $rm \$dlpath' + shlibpath_overrides_runpath=yes + + case $host_os in + cygwin*) + # Cygwin DLLs use 'cyg' prefix rather than 'lib' + soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib" + ;; + mingw*) + # MinGW DLLs use traditional 'lib' prefix + soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` + if echo "$sys_lib_search_path_spec" | grep ';[c-zC-Z]:/' >/dev/null; then + # It is most probably a Windows format PATH printed by + # mingw gcc, but we are running on Cygwin. Gcc prints its search + # path with ; separators, and with drive letters. We can handle the + # drive letters (cygwin fileutils understands them), so leave them, + # especially as we might pass files found there to a mingw objdump, + # which wouldn't understand a cygwinified path. Ahh. + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi + ;; + pw32*) + # pw32 DLLs use 'pw' prefix rather than 'lib' + library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + ;; + esac + ;; + + *) + library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib' + ;; + esac + dynamic_linker='Win32 ld.exe' + # FIXME: first we should search . and the directory the executable is in + shlibpath_var=PATH + ;; + +darwin* | rhapsody*) + dynamic_linker="$host_os dyld" + version_type=darwin + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext' + soname_spec='${libname}${release}${major}$shared_ext' + shlibpath_overrides_runpath=yes + shlibpath_var=DYLD_LIBRARY_PATH + shrext_cmds='.dylib' + # Apple's gcc prints 'gcc -print-search-dirs' doesn't operate the same. + if test "$GCC" = yes; then + sys_lib_search_path_spec=`$CC -print-search-dirs | tr "\n" "$PATH_SEPARATOR" | sed -e 's/libraries:/@libraries:/' | tr "@" "\n" | grep "^libraries:" | sed -e "s/^libraries://" -e "s,=/,/,g" -e "s,$PATH_SEPARATOR, ,g" -e "s,.*,& /lib /usr/lib /usr/local/lib,g"` + else + sys_lib_search_path_spec='/lib /usr/lib /usr/local/lib' + fi + sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' + ;; + +dgux*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +freebsd1*) + dynamic_linker=no + ;; + +kfreebsd*-gnu) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='GNU ld.so' + ;; + +freebsd* | dragonfly*) + # DragonFly does not have aout. When/if they implement a new + # versioning mechanism, adjust this. + if test -x /usr/bin/objformat; then + objformat=`/usr/bin/objformat` + else + case $host_os in + freebsd[123]*) objformat=aout ;; + *) objformat=elf ;; + esac + fi + version_type=freebsd-$objformat + case $version_type in + freebsd-elf*) + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + need_version=no + need_lib_prefix=no + ;; + freebsd-*) + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' + need_version=yes + ;; + esac + shlibpath_var=LD_LIBRARY_PATH + case $host_os in + freebsd2*) + shlibpath_overrides_runpath=yes + ;; + freebsd3.[01]* | freebsdelf3.[01]*) + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ + freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + freebsd*) # from 4.6 on + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + esac + ;; + +gnu*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + hardcode_into_libs=yes + ;; + +hpux9* | hpux10* | hpux11*) + # Give a soname corresponding to the major version so that dld.sl refuses to + # link against other versions. + version_type=sunos + need_lib_prefix=no + need_version=no + case $host_cpu in + ia64*) + shrext_cmds='.so' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.so" + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + if test "X$HPUX_IA64_MODE" = X32; then + sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" + else + sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" + fi + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + hppa*64*) + shrext_cmds='.sl' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.sl" + shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + *) + shrext_cmds='.sl' + dynamic_linker="$host_os dld.sl" + shlibpath_var=SHLIB_PATH + shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + ;; + esac + # HP-UX runs *really* slowly unless shared libraries are mode 555. + postinstall_cmds='chmod 555 $lib' + ;; + +interix3*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +irix5* | irix6* | nonstopux*) + case $host_os in + nonstopux*) version_type=nonstopux ;; + *) + if test "$lt_cv_prog_gnu_ld" = yes; then + version_type=linux + else + version_type=irix + fi ;; + esac + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' + case $host_os in + irix5* | nonstopux*) + libsuff= shlibsuff= + ;; + *) + case $LD in # libtool.m4 will add one of these switches to LD + *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") + libsuff= shlibsuff= libmagic=32-bit;; + *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") + libsuff=32 shlibsuff=N32 libmagic=N32;; + *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") + libsuff=64 shlibsuff=64 libmagic=64-bit;; + *) libsuff= shlibsuff= libmagic=never-match;; + esac + ;; + esac + shlibpath_var=LD_LIBRARY${shlibsuff}_PATH + shlibpath_overrides_runpath=no + sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" + sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" + hardcode_into_libs=yes + ;; + +# No shared lib support for Linux oldld, aout, or coff. +linux*oldld* | linux*aout* | linux*coff*) + dynamic_linker=no + ;; + +# This must be Linux ELF. +linux*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + # Append ld.so.conf contents to the search path + if test -f /etc/ld.so.conf; then + lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '` + sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" + fi + + # We used to test for /lib/ld.so.1 and disable shared libraries on + # powerpc, because MkLinux only supported shared libraries with the + # GNU dynamic linker. Since this was broken with cross compilers, + # most powerpc-linux boxes support dynamic linking these days and + # people can always --disable-shared, the test was removed, and we + # assume the GNU/Linux dynamic linker is in use. + dynamic_linker='GNU/Linux ld.so' + ;; + +knetbsd*-gnu) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='GNU ld.so' + ;; + +netbsd*) + version_type=sunos + need_lib_prefix=no + need_version=no + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + dynamic_linker='NetBSD (a.out) ld.so' + else + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='NetBSD ld.elf_so' + fi + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + +newsos6) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +nto-qnx*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +openbsd*) + version_type=sunos + sys_lib_dlsearch_path_spec="/usr/lib" + need_lib_prefix=no + # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. + case $host_os in + openbsd3.3 | openbsd3.3.*) need_version=yes ;; + *) need_version=no ;; + esac + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + shlibpath_var=LD_LIBRARY_PATH + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + case $host_os in + openbsd2.[89] | openbsd2.[89].*) + shlibpath_overrides_runpath=no + ;; + *) + shlibpath_overrides_runpath=yes + ;; + esac + else + shlibpath_overrides_runpath=yes + fi + ;; + +os2*) + libname_spec='$name' + shrext_cmds=".dll" + need_lib_prefix=no + library_names_spec='$libname${shared_ext} $libname.a' + dynamic_linker='OS/2 ld.exe' + shlibpath_var=LIBPATH + ;; + +osf3* | osf4* | osf5*) + version_type=osf + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" + sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" + ;; + +solaris*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + # ldd complains unless libraries are executable + postinstall_cmds='chmod +x $lib' + ;; + +sunos4*) + version_type=sunos + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + if test "$with_gnu_ld" = yes; then + need_lib_prefix=no + fi + need_version=yes + ;; + +sysv4 | sysv4.3*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + case $host_vendor in + sni) + shlibpath_overrides_runpath=no + need_lib_prefix=no + export_dynamic_flag_spec='${wl}-Blargedynsym' + runpath_var=LD_RUN_PATH + ;; + siemens) + need_lib_prefix=no + ;; + motorola) + need_lib_prefix=no + need_version=no + shlibpath_overrides_runpath=no + sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' + ;; + esac + ;; + +sysv4*MP*) + if test -d /usr/nec ;then + version_type=linux + library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' + soname_spec='$libname${shared_ext}.$major' + shlibpath_var=LD_LIBRARY_PATH + fi + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + version_type=freebsd-elf + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + hardcode_into_libs=yes + if test "$with_gnu_ld" = yes; then + sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' + shlibpath_overrides_runpath=no + else + sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' + shlibpath_overrides_runpath=yes + case $host_os in + sco3.2v5*) + sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" + ;; + esac + fi + sys_lib_dlsearch_path_spec='/usr/lib' + ;; + +uts4*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +*) + dynamic_linker=no + ;; +esac +{ echo "$as_me:$LINENO: result: $dynamic_linker" >&5 +echo "${ECHO_T}$dynamic_linker" >&6; } +test "$dynamic_linker" = no && can_build_shared=no + +variables_saved_for_relink="PATH $shlibpath_var $runpath_var" +if test "$GCC" = yes; then + variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" +fi + + +{ echo "$as_me:$LINENO: checking which extension is used for loadable modules" >&5 +echo $ECHO_N "checking which extension is used for loadable modules... $ECHO_C" >&6; } +if test "${libltdl_cv_shlibext+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + +module=yes +eval libltdl_cv_shlibext=$shrext_cmds + +fi +{ echo "$as_me:$LINENO: result: $libltdl_cv_shlibext" >&5 +echo "${ECHO_T}$libltdl_cv_shlibext" >&6; } +if test -n "$libltdl_cv_shlibext"; then + +cat >>confdefs.h <<_ACEOF +#define LTDL_SHLIB_EXT "$libltdl_cv_shlibext" +_ACEOF + +fi + + +{ echo "$as_me:$LINENO: checking which variable specifies run-time library path" >&5 +echo $ECHO_N "checking which variable specifies run-time library path... $ECHO_C" >&6; } +if test "${libltdl_cv_shlibpath_var+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + libltdl_cv_shlibpath_var="$shlibpath_var" +fi +{ echo "$as_me:$LINENO: result: $libltdl_cv_shlibpath_var" >&5 +echo "${ECHO_T}$libltdl_cv_shlibpath_var" >&6; } +if test -n "$libltdl_cv_shlibpath_var"; then + +cat >>confdefs.h <<_ACEOF +#define LTDL_SHLIBPATH_VAR "$libltdl_cv_shlibpath_var" +_ACEOF + +fi + + +{ echo "$as_me:$LINENO: checking for the default library search path" >&5 +echo $ECHO_N "checking for the default library search path... $ECHO_C" >&6; } +if test "${libltdl_cv_sys_search_path+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + libltdl_cv_sys_search_path="$sys_lib_dlsearch_path_spec" +fi +{ echo "$as_me:$LINENO: result: $libltdl_cv_sys_search_path" >&5 +echo "${ECHO_T}$libltdl_cv_sys_search_path" >&6; } +if test -n "$libltdl_cv_sys_search_path"; then + sys_search_path= + for dir in $libltdl_cv_sys_search_path; do + if test -z "$sys_search_path"; then + sys_search_path="$dir" + else + sys_search_path="$sys_search_path$PATH_SEPARATOR$dir" + fi + done + +cat >>confdefs.h <<_ACEOF +#define LTDL_SYSSEARCHPATH "$sys_search_path" +_ACEOF + +fi + +{ echo "$as_me:$LINENO: checking for objdir" >&5 +echo $ECHO_N "checking for objdir... $ECHO_C" >&6; } +if test "${libltdl_cv_objdir+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + libltdl_cv_objdir="$objdir" + if test -n "$objdir"; then + : + else + rm -f .libs 2>/dev/null + mkdir .libs 2>/dev/null + if test -d .libs; then + libltdl_cv_objdir=.libs + else + # MS-DOS does not allow filenames that begin with a dot. + libltdl_cv_objdir=_libs + fi + rmdir .libs 2>/dev/null + fi + +fi +{ echo "$as_me:$LINENO: result: $libltdl_cv_objdir" >&5 +echo "${ECHO_T}$libltdl_cv_objdir" >&6; } + +cat >>confdefs.h <<_ACEOF +#define LTDL_OBJDIR "$libltdl_cv_objdir/" +_ACEOF + + + + + + +# Check for command to grab the raw symbol name followed by C symbol from nm. +{ echo "$as_me:$LINENO: checking command to parse $NM output from $compiler object" >&5 +echo $ECHO_N "checking command to parse $NM output from $compiler object... $ECHO_C" >&6; } +if test "${lt_cv_sys_global_symbol_pipe+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + +# These are sane defaults that work on at least a few old systems. +# [They come from Ultrix. What could be older than Ultrix?!! ;)] + +# Character class describing NM global symbol codes. +symcode='[BCDEGRST]' + +# Regexp to match symbols that can be accessed directly from C. +sympat='\([_A-Za-z][_A-Za-z0-9]*\)' + +# Transform an extracted symbol line into a proper C declaration +lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^. .* \(.*\)$/extern int \1;/p'" + +# Transform an extracted symbol line into symbol name and symbol address +lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode \([^ ]*\) \([^ ]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" + +# Define system-specific variables. +case $host_os in +aix*) + symcode='[BCDT]' + ;; +cygwin* | mingw* | pw32*) + symcode='[ABCDGISTW]' + ;; +hpux*) # Its linker distinguishes data from code symbols + if test "$host_cpu" = ia64; then + symcode='[ABCDEGRST]' + fi + lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" + lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" + ;; +linux*) + if test "$host_cpu" = ia64; then + symcode='[ABCDGIRSTW]' + lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" + lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" + fi + ;; +irix* | nonstopux*) + symcode='[BCDEGRST]' + ;; +osf*) + symcode='[BCDEGQRST]' + ;; +solaris*) + symcode='[BDRT]' + ;; +sco3.2v5*) + symcode='[DT]' + ;; +sysv4.2uw2*) + symcode='[DT]' + ;; +sysv5* | sco5v6* | unixware* | OpenUNIX*) + symcode='[ABDT]' + ;; +sysv4) + symcode='[DFNSTU]' + ;; +esac + +# Handle CRLF in mingw tool chain +opt_cr= +case $build_os in +mingw*) + opt_cr=`echo 'x\{0,1\}' | tr x '\015'` # option cr in regexp + ;; +esac + +# If we're using GNU nm, then use its standard symbol codes. +case `$NM -V 2>&1` in +*GNU* | *'with BFD'*) + symcode='[ABCDGIRSTW]' ;; +esac + +# Try without a prefix undercore, then with it. +for ac_symprfx in "" "_"; do + + # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. + symxfrm="\\1 $ac_symprfx\\2 \\2" + + # Write the raw and C identifiers. + lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[ ]\($symcode$symcode*\)[ ][ ]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" + + # Check to see that the pipe works correctly. + pipe_works=no + + rm -f conftest* + cat > conftest.$ac_ext <&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + # Now try to grab the symbols. + nlist=conftest.nm + if { (eval echo "$as_me:$LINENO: \"$NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist\"") >&5 + (eval $NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && test -s "$nlist"; then + # Try sorting and uniquifying the output. + if sort "$nlist" | uniq > "$nlist"T; then + mv -f "$nlist"T "$nlist" + else + rm -f "$nlist"T + fi + + # Make sure that we snagged all the symbols we need. + if grep ' nm_test_var$' "$nlist" >/dev/null; then + if grep ' nm_test_func$' "$nlist" >/dev/null; then + cat < conftest.$ac_ext +#ifdef __cplusplus +extern "C" { +#endif + +EOF + # Now generate the symbol file. + eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | grep -v main >> conftest.$ac_ext' + + cat <> conftest.$ac_ext +#if defined (__STDC__) && __STDC__ +# define lt_ptr_t void * +#else +# define lt_ptr_t char * +# define const +#endif + +/* The mapping between symbol names and symbols. */ +const struct { + const char *name; + lt_ptr_t address; +} +lt_preloaded_symbols[] = +{ +EOF + $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (lt_ptr_t) \&\2},/" < "$nlist" | grep -v main >> conftest.$ac_ext + cat <<\EOF >> conftest.$ac_ext + {0, (lt_ptr_t) 0} +}; + +#ifdef __cplusplus +} +#endif +EOF + # Now try linking the two files. + mv conftest.$ac_objext conftstm.$ac_objext + lt_save_LIBS="$LIBS" + lt_save_CFLAGS="$CFLAGS" + LIBS="conftstm.$ac_objext" + CFLAGS="$CFLAGS$lt_prog_compiler_no_builtin_flag" + if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && test -s conftest${ac_exeext}; then + pipe_works=yes + fi + LIBS="$lt_save_LIBS" + CFLAGS="$lt_save_CFLAGS" + else + echo "cannot find nm_test_func in $nlist" >&5 + fi + else + echo "cannot find nm_test_var in $nlist" >&5 + fi + else + echo "cannot run $lt_cv_sys_global_symbol_pipe" >&5 + fi + else + echo "$progname: failed program was:" >&5 + cat conftest.$ac_ext >&5 + fi + rm -f conftest* conftst* + + # Do not use the global_symbol_pipe unless it works. + if test "$pipe_works" = yes; then + break + else + lt_cv_sys_global_symbol_pipe= + fi +done + +fi + +if test -z "$lt_cv_sys_global_symbol_pipe"; then + lt_cv_sys_global_symbol_to_cdecl= +fi +if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then + { echo "$as_me:$LINENO: result: failed" >&5 +echo "${ECHO_T}failed" >&6; } +else + { echo "$as_me:$LINENO: result: ok" >&5 +echo "${ECHO_T}ok" >&6; } +fi + + +{ echo "$as_me:$LINENO: checking whether libtool supports -dlopen/-dlpreopen" >&5 +echo $ECHO_N "checking whether libtool supports -dlopen/-dlpreopen... $ECHO_C" >&6; } +if test "${libltdl_cv_preloaded_symbols+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$lt_cv_sys_global_symbol_pipe"; then + libltdl_cv_preloaded_symbols=yes + else + libltdl_cv_preloaded_symbols=no + fi + +fi +{ echo "$as_me:$LINENO: result: $libltdl_cv_preloaded_symbols" >&5 +echo "${ECHO_T}$libltdl_cv_preloaded_symbols" >&6; } +if test x"$libltdl_cv_preloaded_symbols" = xyes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_PRELOADED_SYMBOLS 1 +_ACEOF + +fi + +LIBADD_DL= + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +{ echo "$as_me:$LINENO: checking for shl_load" >&5 +echo $ECHO_N "checking for shl_load... $ECHO_C" >&6; } +if test "${ac_cv_func_shl_load+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define shl_load to an innocuous variant, in case declares shl_load. + For example, HP-UX 11i declares gettimeofday. */ +#define shl_load innocuous_shl_load + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char shl_load (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef shl_load + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char shl_load (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_shl_load || defined __stub___shl_load +choke me +#endif + +int +main () +{ +return shl_load (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_shl_load=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_func_shl_load=no +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ac_cv_func_shl_load" >&5 +echo "${ECHO_T}$ac_cv_func_shl_load" >&6; } +if test $ac_cv_func_shl_load = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_SHL_LOAD 1 +_ACEOF + +else + { echo "$as_me:$LINENO: checking for shl_load in -ldld" >&5 +echo $ECHO_N "checking for shl_load in -ldld... $ECHO_C" >&6; } +if test "${ac_cv_lib_dld_shl_load+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldld $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char shl_load (); +int +main () +{ +return shl_load (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_dld_shl_load=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_dld_shl_load=no +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_dld_shl_load" >&5 +echo "${ECHO_T}$ac_cv_lib_dld_shl_load" >&6; } +if test $ac_cv_lib_dld_shl_load = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_SHL_LOAD 1 +_ACEOF + + LIBADD_DL="$LIBADD_DL -ldld" +else + { echo "$as_me:$LINENO: checking for dlopen in -ldl" >&5 +echo $ECHO_N "checking for dlopen in -ldl... $ECHO_C" >&6; } +if test "${ac_cv_lib_dl_dlopen+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldl $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dlopen (); +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_dl_dlopen=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_dl_dlopen=no +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_dl_dlopen" >&5 +echo "${ECHO_T}$ac_cv_lib_dl_dlopen" >&6; } +if test $ac_cv_lib_dl_dlopen = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_LIBDL 1 +_ACEOF + + LIBADD_DL="-ldl" libltdl_cv_lib_dl_dlopen="yes" +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#if HAVE_DLFCN_H +# include +#endif + +int +main () +{ +dlopen(0, 0); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_LIBDL 1 +_ACEOF + libltdl_cv_func_dlopen="yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + { echo "$as_me:$LINENO: checking for dlopen in -lsvld" >&5 +echo $ECHO_N "checking for dlopen in -lsvld... $ECHO_C" >&6; } +if test "${ac_cv_lib_svld_dlopen+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lsvld $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dlopen (); +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_svld_dlopen=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_svld_dlopen=no +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_svld_dlopen" >&5 +echo "${ECHO_T}$ac_cv_lib_svld_dlopen" >&6; } +if test $ac_cv_lib_svld_dlopen = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_LIBDL 1 +_ACEOF + + LIBADD_DL="-lsvld" libltdl_cv_func_dlopen="yes" +else + { echo "$as_me:$LINENO: checking for dld_link in -ldld" >&5 +echo $ECHO_N "checking for dld_link in -ldld... $ECHO_C" >&6; } +if test "${ac_cv_lib_dld_dld_link+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldld $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dld_link (); +int +main () +{ +return dld_link (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_dld_dld_link=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_dld_dld_link=no +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_dld_dld_link" >&5 +echo "${ECHO_T}$ac_cv_lib_dld_dld_link" >&6; } +if test $ac_cv_lib_dld_dld_link = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_DLD 1 +_ACEOF + + LIBADD_DL="$LIBADD_DL -ldld" +else + { echo "$as_me:$LINENO: checking for _dyld_func_lookup" >&5 +echo $ECHO_N "checking for _dyld_func_lookup... $ECHO_C" >&6; } +if test "${ac_cv_func__dyld_func_lookup+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define _dyld_func_lookup to an innocuous variant, in case declares _dyld_func_lookup. + For example, HP-UX 11i declares gettimeofday. */ +#define _dyld_func_lookup innocuous__dyld_func_lookup + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char _dyld_func_lookup (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef _dyld_func_lookup + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char _dyld_func_lookup (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub__dyld_func_lookup || defined __stub____dyld_func_lookup +choke me +#endif + +int +main () +{ +return _dyld_func_lookup (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func__dyld_func_lookup=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_func__dyld_func_lookup=no +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ac_cv_func__dyld_func_lookup" >&5 +echo "${ECHO_T}$ac_cv_func__dyld_func_lookup" >&6; } +if test $ac_cv_func__dyld_func_lookup = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_DYLD 1 +_ACEOF + +fi + + +fi + + +fi + + +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + +fi + + +fi + + +fi + + +if test x"$libltdl_cv_func_dlopen" = xyes || test x"$libltdl_cv_lib_dl_dlopen" = xyes +then + lt_save_LIBS="$LIBS" + LIBS="$LIBS $LIBADD_DL" + +for ac_func in dlerror +do +as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` +{ echo "$as_me:$LINENO: checking for $ac_func" >&5 +echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; } +if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case declares $ac_func. + For example, HP-UX 11i declares gettimeofday. */ +#define $ac_func innocuous_$ac_func + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $ac_func + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $ac_func (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$ac_func || defined __stub___$ac_func +choke me +#endif + +int +main () +{ +return $ac_func (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_var=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_var=no" +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +ac_res=`eval echo '${'$as_ac_var'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +if test `eval echo '${'$as_ac_var'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + LIBS="$lt_save_LIBS" +fi +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + +{ echo "$as_me:$LINENO: checking for _ prefix in compiled symbols" >&5 +echo $ECHO_N "checking for _ prefix in compiled symbols... $ECHO_C" >&6; } +if test "${ac_cv_sys_symbol_underscore+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_sys_symbol_underscore=no + cat > conftest.$ac_ext <&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + # Now try to grab the symbols. + ac_nlist=conftest.nm + if { (eval echo "$as_me:$LINENO: \"$NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $ac_nlist\"") >&5 + (eval $NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $ac_nlist) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && test -s "$ac_nlist"; then + # See whether the symbols have a leading underscore. + if grep '^. _nm_test_func' "$ac_nlist" >/dev/null; then + ac_cv_sys_symbol_underscore=yes + else + if grep '^. nm_test_func ' "$ac_nlist" >/dev/null; then + : + else + echo "configure: cannot find nm_test_func in $ac_nlist" >&5 + fi + fi + else + echo "configure: cannot run $lt_cv_sys_global_symbol_pipe" >&5 + fi + else + echo "configure: failed program was:" >&5 + cat conftest.c >&5 + fi + rm -rf conftest* + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_sys_symbol_underscore" >&5 +echo "${ECHO_T}$ac_cv_sys_symbol_underscore" >&6; } + + +if test x"$ac_cv_sys_symbol_underscore" = xyes; then + if test x"$libltdl_cv_func_dlopen" = xyes || + test x"$libltdl_cv_lib_dl_dlopen" = xyes ; then + { echo "$as_me:$LINENO: checking whether we have to add an underscore for dlsym" >&5 +echo $ECHO_N "checking whether we have to add an underscore for dlsym... $ECHO_C" >&6; } +if test "${libltdl_cv_need_uscore+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + libltdl_cv_need_uscore=unknown + save_LIBS="$LIBS" + LIBS="$LIBS $LIBADD_DL" + if test "$cross_compiling" = yes; then : + libltdl_cv_need_uscore=cross +else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext < +#endif + +#include + +#ifdef RTLD_GLOBAL +# define LT_DLGLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LT_DLGLOBAL DL_GLOBAL +# else +# define LT_DLGLOBAL 0 +# endif +#endif + +/* We may have to define LT_DLLAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LT_DLLAZY_OR_NOW +# ifdef RTLD_LAZY +# define LT_DLLAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LT_DLLAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LT_DLLAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LT_DLLAZY_OR_NOW DL_NOW +# else +# define LT_DLLAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +#ifdef __cplusplus +extern "C" void exit (int); +#endif + +void fnord() { int i=42;} +int main () +{ + void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); + int status = $lt_dlunknown; + + if (self) + { + if (dlsym (self,"fnord")) status = $lt_dlno_uscore; + else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + /* dlclose (self); */ + } + else + puts (dlerror ()); + + exit (status); +} +EOF + if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && test -s conftest${ac_exeext} 2>/dev/null; then + (./conftest; exit; ) >&5 2>/dev/null + lt_status=$? + case x$lt_status in + x$lt_dlno_uscore) libltdl_cv_need_uscore=no ;; + x$lt_dlneed_uscore) libltdl_cv_need_uscore=yes ;; + x$lt_dlunknown|x*) ;; + esac + else : + # compilation failed + + fi +fi +rm -fr conftest* + + LIBS="$save_LIBS" + +fi +{ echo "$as_me:$LINENO: result: $libltdl_cv_need_uscore" >&5 +echo "${ECHO_T}$libltdl_cv_need_uscore" >&6; } + fi +fi + +if test x"$libltdl_cv_need_uscore" = xyes; then + +cat >>confdefs.h <<\_ACEOF +#define NEED_USCORE 1 +_ACEOF + +fi + + +{ echo "$as_me:$LINENO: checking whether deplibs are loaded by dlopen" >&5 +echo $ECHO_N "checking whether deplibs are loaded by dlopen... $ECHO_C" >&6; } +if test "${libltdl_cv_sys_dlopen_deplibs+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + # PORTME does your system automatically load deplibs for dlopen? + # or its logical equivalent (e.g. shl_load for HP-UX < 11) + # For now, we just catch OSes we know something about -- in the + # future, we'll try test this programmatically. + libltdl_cv_sys_dlopen_deplibs=unknown + case "$host_os" in + aix3*|aix4.1.*|aix4.2.*) + # Unknown whether this is true for these versions of AIX, but + # we want this `case' here to explicitly catch those versions. + libltdl_cv_sys_dlopen_deplibs=unknown + ;; + aix[45]*) + libltdl_cv_sys_dlopen_deplibs=yes + ;; + darwin*) + # Assuming the user has installed a libdl from somewhere, this is true + # If you are looking for one http://www.opendarwin.org/projects/dlcompat + libltdl_cv_sys_dlopen_deplibs=yes + ;; + gnu* | linux* | kfreebsd*-gnu | knetbsd*-gnu) + # GNU and its variants, using gnu ld.so (Glibc) + libltdl_cv_sys_dlopen_deplibs=yes + ;; + hpux10*|hpux11*) + libltdl_cv_sys_dlopen_deplibs=yes + ;; + interix*) + libltdl_cv_sys_dlopen_deplibs=yes + ;; + irix[12345]*|irix6.[01]*) + # Catch all versions of IRIX before 6.2, and indicate that we don't + # know how it worked for any of those versions. + libltdl_cv_sys_dlopen_deplibs=unknown + ;; + irix*) + # The case above catches anything before 6.2, and it's known that + # at 6.2 and later dlopen does load deplibs. + libltdl_cv_sys_dlopen_deplibs=yes + ;; + netbsd*) + libltdl_cv_sys_dlopen_deplibs=yes + ;; + openbsd*) + libltdl_cv_sys_dlopen_deplibs=yes + ;; + osf[1234]*) + # dlopen did load deplibs (at least at 4.x), but until the 5.x series, + # it did *not* use an RPATH in a shared library to find objects the + # library depends on, so we explictly say `no'. + libltdl_cv_sys_dlopen_deplibs=no + ;; + osf5.0|osf5.0a|osf5.1) + # dlopen *does* load deplibs and with the right loader patch applied + # it even uses RPATH in a shared library to search for shared objects + # that the library depends on, but there's no easy way to know if that + # patch is installed. Since this is the case, all we can really + # say is unknown -- it depends on the patch being installed. If + # it is, this changes to `yes'. Without it, it would be `no'. + libltdl_cv_sys_dlopen_deplibs=unknown + ;; + osf*) + # the two cases above should catch all versions of osf <= 5.1. Read + # the comments above for what we know about them. + # At > 5.1, deplibs are loaded *and* any RPATH in a shared library + # is used to find them so we can finally say `yes'. + libltdl_cv_sys_dlopen_deplibs=yes + ;; + solaris*) + libltdl_cv_sys_dlopen_deplibs=yes + ;; + sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + libltdl_cv_sys_dlopen_deplibs=yes + ;; + esac + +fi +{ echo "$as_me:$LINENO: result: $libltdl_cv_sys_dlopen_deplibs" >&5 +echo "${ECHO_T}$libltdl_cv_sys_dlopen_deplibs" >&6; } +if test "$libltdl_cv_sys_dlopen_deplibs" != yes; then + +cat >>confdefs.h <<\_ACEOF +#define LTDL_DLOPEN_DEPLIBS 1 +_ACEOF + +fi + + +for ac_header in argz.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + { echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +else + # Is the header compilable? +{ echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6; } + +# Is the header present? +{ echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -f conftest.err conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + ( cat <<\_ASBOX +## ----------------------------------- ## +## Report this to llvmbugs@cs.uiuc.edu ## +## ----------------------------------- ## +_ASBOX + ) | sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +{ echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + +{ echo "$as_me:$LINENO: checking for error_t" >&5 +echo $ECHO_N "checking for error_t... $ECHO_C" >&6; } +if test "${ac_cv_type_error_t+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#if HAVE_ARGZ_H +# include +#endif + +typedef error_t ac__type_new_; +int +main () +{ +if ((ac__type_new_ *) 0) + return 0; +if (sizeof (ac__type_new_)) + return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_type_error_t=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_type_error_t=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ac_cv_type_error_t" >&5 +echo "${ECHO_T}$ac_cv_type_error_t" >&6; } +if test $ac_cv_type_error_t = yes; then + +cat >>confdefs.h <<_ACEOF +#define HAVE_ERROR_T 1 +_ACEOF + + +else + +cat >>confdefs.h <<\_ACEOF +#define error_t int +_ACEOF + +fi + + + + + + + +for ac_func in argz_append argz_create_sep argz_insert argz_next argz_stringify +do +as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` +{ echo "$as_me:$LINENO: checking for $ac_func" >&5 +echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; } +if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case declares $ac_func. + For example, HP-UX 11i declares gettimeofday. */ +#define $ac_func innocuous_$ac_func + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $ac_func + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $ac_func (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$ac_func || defined __stub___$ac_func +choke me +#endif + +int +main () +{ +return $ac_func (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_var=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_var=no" +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +ac_res=`eval echo '${'$as_ac_var'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +if test `eval echo '${'$as_ac_var'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + + + + + + + + + + + + + + + + + + + + + + + + + + + +for ac_header in assert.h ctype.h errno.h malloc.h memory.h stdlib.h \ + stdio.h unistd.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + { echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +else + # Is the header compilable? +{ echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6; } + +# Is the header present? +{ echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -f conftest.err conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + ( cat <<\_ASBOX +## ----------------------------------- ## +## Report this to llvmbugs@cs.uiuc.edu ## +## ----------------------------------- ## +_ASBOX + ) | sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +{ echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + + + + +for ac_header in dl.h sys/dl.h dld.h mach-o/dyld.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + { echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +else + # Is the header compilable? +{ echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6; } + +# Is the header present? +{ echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -f conftest.err conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + ( cat <<\_ASBOX +## ----------------------------------- ## +## Report this to llvmbugs@cs.uiuc.edu ## +## ----------------------------------- ## +_ASBOX + ) | sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +{ echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + + +for ac_header in string.h strings.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + { echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +else + # Is the header compilable? +{ echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6; } + +# Is the header present? +{ echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -f conftest.err conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + ( cat <<\_ASBOX +## ----------------------------------- ## +## Report this to llvmbugs@cs.uiuc.edu ## +## ----------------------------------- ## +_ASBOX + ) | sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +{ echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + break +fi + +done + + + + +for ac_func in strchr index +do +as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` +{ echo "$as_me:$LINENO: checking for $ac_func" >&5 +echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; } +if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case declares $ac_func. + For example, HP-UX 11i declares gettimeofday. */ +#define $ac_func innocuous_$ac_func + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $ac_func + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $ac_func (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$ac_func || defined __stub___$ac_func +choke me +#endif + +int +main () +{ +return $ac_func (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_var=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_var=no" +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +ac_res=`eval echo '${'$as_ac_var'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +if test `eval echo '${'$as_ac_var'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + break +fi +done + + + +for ac_func in strrchr rindex +do +as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` +{ echo "$as_me:$LINENO: checking for $ac_func" >&5 +echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; } +if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case declares $ac_func. + For example, HP-UX 11i declares gettimeofday. */ +#define $ac_func innocuous_$ac_func + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $ac_func + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $ac_func (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$ac_func || defined __stub___$ac_func +choke me +#endif + +int +main () +{ +return $ac_func (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_var=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_var=no" +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +ac_res=`eval echo '${'$as_ac_var'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +if test `eval echo '${'$as_ac_var'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + break +fi +done + + + +for ac_func in memcpy bcopy +do +as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` +{ echo "$as_me:$LINENO: checking for $ac_func" >&5 +echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; } +if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case declares $ac_func. + For example, HP-UX 11i declares gettimeofday. */ +#define $ac_func innocuous_$ac_func + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $ac_func + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $ac_func (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$ac_func || defined __stub___$ac_func +choke me +#endif + +int +main () +{ +return $ac_func (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_var=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_var=no" +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +ac_res=`eval echo '${'$as_ac_var'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +if test `eval echo '${'$as_ac_var'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + break +fi +done + + + +for ac_func in memmove strcmp +do +as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` +{ echo "$as_me:$LINENO: checking for $ac_func" >&5 +echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; } +if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case declares $ac_func. + For example, HP-UX 11i declares gettimeofday. */ +#define $ac_func innocuous_$ac_func + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $ac_func + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $ac_func (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$ac_func || defined __stub___$ac_func +choke me +#endif + +int +main () +{ +return $ac_func (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_var=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_var=no" +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +ac_res=`eval echo '${'$as_ac_var'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +if test `eval echo '${'$as_ac_var'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + + + +for ac_func in closedir opendir readdir +do +as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` +{ echo "$as_me:$LINENO: checking for $ac_func" >&5 +echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; } +if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case declares $ac_func. + For example, HP-UX 11i declares gettimeofday. */ +#define $ac_func innocuous_$ac_func + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $ac_func + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $ac_func (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$ac_func || defined __stub___$ac_func +choke me +#endif + +int +main () +{ +return $ac_func (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_var=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_var=no" +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +ac_res=`eval echo '${'$as_ac_var'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +if test `eval echo '${'$as_ac_var'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + +# Check whether --enable-shared was given. +if test "${enable_shared+set}" = set; then + enableval=$enable_shared; p=${PACKAGE-default} + case $enableval in + yes) enable_shared=yes ;; + no) enable_shared=no ;; + *) + enable_shared=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_shared=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac +else + enable_shared=yes +fi + + +# Check whether --enable-static was given. +if test "${enable_static+set}" = set; then + enableval=$enable_static; p=${PACKAGE-default} + case $enableval in + yes) enable_static=yes ;; + no) enable_static=no ;; + *) + enable_static=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_static=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac +else + enable_static=yes +fi + + +# Check whether --enable-fast-install was given. +if test "${enable_fast_install+set}" = set; then + enableval=$enable_fast_install; p=${PACKAGE-default} + case $enableval in + yes) enable_fast_install=yes ;; + no) enable_fast_install=no ;; + *) + enable_fast_install=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_fast_install=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac +else + enable_fast_install=yes +fi + + +{ echo "$as_me:$LINENO: checking for a sed that does not truncate output" >&5 +echo $ECHO_N "checking for a sed that does not truncate output... $ECHO_C" >&6; } +if test "${lt_cv_path_SED+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + # Loop through the user's path and test for sed and gsed. +# Then use that list of sed's as ones to test for truncation. +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for lt_ac_prog in sed gsed; do + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then + lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext" + fi + done + done +done +lt_ac_max=0 +lt_ac_count=0 +# Add /usr/xpg4/bin/sed as it is typically found on Solaris +# along with /bin/sed that truncates output. +for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do + test ! -f $lt_ac_sed && continue + cat /dev/null > conftest.in + lt_ac_count=0 + echo $ECHO_N "0123456789$ECHO_C" >conftest.in + # Check for GNU sed and select it if it is found. + if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then + lt_cv_path_SED=$lt_ac_sed + break + fi + while true; do + cat conftest.in conftest.in >conftest.tmp + mv conftest.tmp conftest.in + cp conftest.in conftest.nl + echo >>conftest.nl + $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break + cmp -s conftest.out conftest.nl || break + # 10000 chars as input seems more than enough + test $lt_ac_count -gt 10 && break + lt_ac_count=`expr $lt_ac_count + 1` + if test $lt_ac_count -gt $lt_ac_max; then + lt_ac_max=$lt_ac_count + lt_cv_path_SED=$lt_ac_sed + fi + done +done + +fi + +SED=$lt_cv_path_SED +{ echo "$as_me:$LINENO: result: $SED" >&5 +echo "${ECHO_T}$SED" >&6; } + + +# Check whether --with-gnu-ld was given. +if test "${with_gnu_ld+set}" = set; then + withval=$with_gnu_ld; test "$withval" = no || with_gnu_ld=yes +else + with_gnu_ld=no +fi + +ac_prog=ld +if test "$GCC" = yes; then + # Check if gcc -print-prog-name=ld gives a path. + { echo "$as_me:$LINENO: checking for ld used by $CC" >&5 +echo $ECHO_N "checking for ld used by $CC... $ECHO_C" >&6; } + case $host in + *-*-mingw*) + # gcc leaves a trailing carriage return which upsets mingw + ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; + *) + ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; + esac + case $ac_prog in + # Accept absolute paths. + [\\/]* | ?:[\\/]*) + re_direlt='/[^/][^/]*/\.\./' + # Canonicalize the pathname of ld + ac_prog=`echo $ac_prog| $SED 's%\\\\%/%g'` + while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do + ac_prog=`echo $ac_prog| $SED "s%$re_direlt%/%"` + done + test -z "$LD" && LD="$ac_prog" + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test "$with_gnu_ld" = yes; then + { echo "$as_me:$LINENO: checking for GNU ld" >&5 +echo $ECHO_N "checking for GNU ld... $ECHO_C" >&6; } +else + { echo "$as_me:$LINENO: checking for non-GNU ld" >&5 +echo $ECHO_N "checking for non-GNU ld... $ECHO_C" >&6; } +fi +if test "${lt_cv_path_LD+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -z "$LD"; then + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then + lt_cv_path_LD="$ac_dir/$ac_prog" + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some variants of GNU ld only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + case `"$lt_cv_path_LD" -v 2>&1 &5 +echo "${ECHO_T}$LD" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi +test -z "$LD" && { { echo "$as_me:$LINENO: error: no acceptable ld found in \$PATH" >&5 +echo "$as_me: error: no acceptable ld found in \$PATH" >&2;} + { (exit 1); exit 1; }; } +{ echo "$as_me:$LINENO: checking if the linker ($LD) is GNU ld" >&5 +echo $ECHO_N "checking if the linker ($LD) is GNU ld... $ECHO_C" >&6; } +if test "${lt_cv_prog_gnu_ld+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + # I'd rather use --version here, but apparently some GNU lds only accept -v. +case `$LD -v 2>&1 &5 +echo "${ECHO_T}$lt_cv_prog_gnu_ld" >&6; } +with_gnu_ld=$lt_cv_prog_gnu_ld + + +{ echo "$as_me:$LINENO: checking for $LD option to reload object files" >&5 +echo $ECHO_N "checking for $LD option to reload object files... $ECHO_C" >&6; } +if test "${lt_cv_ld_reload_flag+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + lt_cv_ld_reload_flag='-r' +fi +{ echo "$as_me:$LINENO: result: $lt_cv_ld_reload_flag" >&5 +echo "${ECHO_T}$lt_cv_ld_reload_flag" >&6; } +reload_flag=$lt_cv_ld_reload_flag +case $reload_flag in +"" | " "*) ;; +*) reload_flag=" $reload_flag" ;; +esac +reload_cmds='$LD$reload_flag -o $output$reload_objs' +case $host_os in + darwin*) + if test "$GCC" = yes; then + reload_cmds='$LTCC $LTCFLAGS -nostdlib ${wl}-r $compiler_flags -o $output$reload_objs' + else + reload_cmds='$LD$reload_flag -o $output$reload_objs' + fi + ;; +esac + +{ echo "$as_me:$LINENO: checking how to recognise dependent libraries" >&5 +echo $ECHO_N "checking how to recognise dependent libraries... $ECHO_C" >&6; } +if test "${lt_cv_deplibs_check_method+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + lt_cv_file_magic_cmd='$MAGIC_CMD' +lt_cv_file_magic_test_file= +lt_cv_deplibs_check_method='unknown' +# Need to set the preceding variable on all platforms that support +# interlibrary dependencies. +# 'none' -- dependencies not supported. +# `unknown' -- same as none, but documents that we really don't know. +# 'pass_all' -- all dependencies passed with no checks. +# 'test_compile' -- check by making test program. +# 'file_magic [[regex]]' -- check by looking for files in library path +# which responds to the $file_magic_cmd with a given extended regex. +# If you have `file' or equivalent on your system and you're not sure +# whether `pass_all' will *always* work, you probably want this one. + +case $host_os in +aix4* | aix5*) + lt_cv_deplibs_check_method=pass_all + ;; + +beos*) + lt_cv_deplibs_check_method=pass_all + ;; + +bsdi[45]*) + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)' + lt_cv_file_magic_cmd='/usr/bin/file -L' + lt_cv_file_magic_test_file=/shlib/libc.so + ;; + +cygwin*) + # func_win32_libid is a shell function defined in ltmain.sh + lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' + lt_cv_file_magic_cmd='func_win32_libid' + ;; + +mingw* | pw32*) + # Base MSYS/MinGW do not provide the 'file' command needed by + # func_win32_libid shell function, so use a weaker test based on 'objdump'. + lt_cv_deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?' + lt_cv_file_magic_cmd='$OBJDUMP -f' + ;; + +darwin* | rhapsody*) + lt_cv_deplibs_check_method=pass_all + ;; + +freebsd* | kfreebsd*-gnu | dragonfly*) + if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then + case $host_cpu in + i*86 ) + # Not sure whether the presence of OpenBSD here was a mistake. + # Let's accept both of them until this is cleared up. + lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[3-9]86 (compact )?demand paged shared library' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` + ;; + esac + else + lt_cv_deplibs_check_method=pass_all + fi + ;; + +gnu*) + lt_cv_deplibs_check_method=pass_all + ;; + +hpux10.20* | hpux11*) + lt_cv_file_magic_cmd=/usr/bin/file + case $host_cpu in + ia64*) + lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - IA64' + lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so + ;; + hppa*64*) + lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - PA-RISC [0-9].[0-9]' + lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl + ;; + *) + lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9].[0-9]) shared library' + lt_cv_file_magic_test_file=/usr/lib/libc.sl + ;; + esac + ;; + +interix3*) + # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|\.a)$' + ;; + +irix5* | irix6* | nonstopux*) + case $LD in + *-32|*"-32 ") libmagic=32-bit;; + *-n32|*"-n32 ") libmagic=N32;; + *-64|*"-64 ") libmagic=64-bit;; + *) libmagic=never-match;; + esac + lt_cv_deplibs_check_method=pass_all + ;; + +# This must be Linux ELF. +linux*) + lt_cv_deplibs_check_method=pass_all + ;; + +netbsd*) + if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|_pic\.a)$' + fi + ;; + +newos6*) + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (executable|dynamic lib)' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=/usr/lib/libnls.so + ;; + +nto-qnx*) + lt_cv_deplibs_check_method=unknown + ;; + +openbsd*) + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|\.so|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' + fi + ;; + +osf3* | osf4* | osf5*) + lt_cv_deplibs_check_method=pass_all + ;; + +solaris*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv4 | sysv4.3*) + case $host_vendor in + motorola) + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]' + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` + ;; + ncr) + lt_cv_deplibs_check_method=pass_all + ;; + sequent) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )' + ;; + sni) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method="file_magic ELF [0-9][0-9]*-bit [LM]SB dynamic lib" + lt_cv_file_magic_test_file=/lib/libc.so + ;; + siemens) + lt_cv_deplibs_check_method=pass_all + ;; + pc) + lt_cv_deplibs_check_method=pass_all + ;; + esac + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + lt_cv_deplibs_check_method=pass_all + ;; +esac + +fi +{ echo "$as_me:$LINENO: result: $lt_cv_deplibs_check_method" >&5 +echo "${ECHO_T}$lt_cv_deplibs_check_method" >&6; } +file_magic_cmd=$lt_cv_file_magic_cmd +deplibs_check_method=$lt_cv_deplibs_check_method +test -z "$deplibs_check_method" && deplibs_check_method=unknown + + + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC + +# Check whether --enable-libtool-lock was given. +if test "${enable_libtool_lock+set}" = set; then + enableval=$enable_libtool_lock; +fi + +test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes + +# Some flags need to be propagated to the compiler or linker for good +# libtool support. +case $host in +ia64-*-hpux*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + case `/usr/bin/file conftest.$ac_objext` in + *ELF-32*) + HPUX_IA64_MODE="32" + ;; + *ELF-64*) + HPUX_IA64_MODE="64" + ;; + esac + fi + rm -rf conftest* + ;; +*-*-irix6*) + # Find out which ABI we are using. + echo '#line 13267 "configure"' > conftest.$ac_ext + if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + if test "$lt_cv_prog_gnu_ld" = yes; then + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -melf32bsmip" + ;; + *N32*) + LD="${LD-ld} -melf32bmipn32" + ;; + *64-bit*) + LD="${LD-ld} -melf64bmip" + ;; + esac + else + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -32" + ;; + *N32*) + LD="${LD-ld} -n32" + ;; + *64-bit*) + LD="${LD-ld} -64" + ;; + esac + fi + fi + rm -rf conftest* + ;; + +x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*|s390*-*linux*|sparc*-*linux*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + case `/usr/bin/file conftest.o` in + *32-bit*) + case $host in + x86_64-*linux*) + LD="${LD-ld} -m elf_i386" + ;; + ppc64-*linux*|powerpc64-*linux*) + LD="${LD-ld} -m elf32ppclinux" + ;; + s390x-*linux*) + LD="${LD-ld} -m elf_s390" + ;; + sparc64-*linux*) + LD="${LD-ld} -m elf32_sparc" + ;; + esac + ;; + *64-bit*) + case $host in + x86_64-*linux*) + LD="${LD-ld} -m elf_x86_64" + ;; + ppc*-*linux*|powerpc*-*linux*) + LD="${LD-ld} -m elf64ppc" + ;; + s390*-*linux*) + LD="${LD-ld} -m elf64_s390" + ;; + sparc*-*linux*) + LD="${LD-ld} -m elf64_sparc" + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; + +*-*-sco3.2v5*) + # On SCO OpenServer 5, we need -belf to get full-featured binaries. + SAVE_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -belf" + { echo "$as_me:$LINENO: checking whether the C compiler needs -belf" >&5 +echo $ECHO_N "checking whether the C compiler needs -belf... $ECHO_C" >&6; } +if test "${lt_cv_cc_needs_belf+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + lt_cv_cc_needs_belf=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + lt_cv_cc_needs_belf=no +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +fi +{ echo "$as_me:$LINENO: result: $lt_cv_cc_needs_belf" >&5 +echo "${ECHO_T}$lt_cv_cc_needs_belf" >&6; } + if test x"$lt_cv_cc_needs_belf" != x"yes"; then + # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf + CFLAGS="$SAVE_CFLAGS" + fi + ;; +sparc*-*solaris*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + case `/usr/bin/file conftest.o` in + *64-bit*) + case $lt_cv_prog_gnu_ld in + yes*) LD="${LD-ld} -m elf64_sparc" ;; + *) LD="${LD-ld} -64" ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; + + +esac + +need_locks="$enable_libtool_lock" + + + + +if test -n "$CXX" && ( test "X$CXX" != "Xno" && + ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) || + (test "X$CXX" != "Xg++"))) ; then + ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu +{ echo "$as_me:$LINENO: checking how to run the C++ preprocessor" >&5 +echo $ECHO_N "checking how to run the C++ preprocessor... $ECHO_C" >&6; } +if test -z "$CXXCPP"; then + if test "${ac_cv_prog_CXXCPP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + # Double quotes because CXXCPP needs to be expanded + for CXXCPP in "$CXX -E" "/lib/cpp" + do + ac_preproc_ok=false +for ac_cxx_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_cxx_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_cxx_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Broken: fails on valid input. +continue +fi + +rm -f conftest.err conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_cxx_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_cxx_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + # Broken: success on invalid input. +continue +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Passes both tests. +ac_preproc_ok=: +break +fi + +rm -f conftest.err conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.err conftest.$ac_ext +if $ac_preproc_ok; then + break +fi + + done + ac_cv_prog_CXXCPP=$CXXCPP + +fi + CXXCPP=$ac_cv_prog_CXXCPP +else + ac_cv_prog_CXXCPP=$CXXCPP +fi +{ echo "$as_me:$LINENO: result: $CXXCPP" >&5 +echo "${ECHO_T}$CXXCPP" >&6; } +ac_preproc_ok=false +for ac_cxx_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_cxx_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_cxx_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Broken: fails on valid input. +continue +fi + +rm -f conftest.err conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_cxx_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_cxx_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + # Broken: success on invalid input. +continue +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Passes both tests. +ac_preproc_ok=: +break +fi + +rm -f conftest.err conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.err conftest.$ac_ext +if $ac_preproc_ok; then + : +else + { { echo "$as_me:$LINENO: error: C++ preprocessor \"$CXXCPP\" fails sanity check +See \`config.log' for more details." >&5 +echo "$as_me: error: C++ preprocessor \"$CXXCPP\" fails sanity check +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi + +ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + +fi + + +ac_ext=f +ac_compile='$F77 -c $FFLAGS conftest.$ac_ext >&5' +ac_link='$F77 -o conftest$ac_exeext $FFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_f77_compiler_gnu +if test -n "$ac_tool_prefix"; then + for ac_prog in g77 f77 xlf frt pgf77 cf77 fort77 fl32 af77 f90 xlf90 pgf90 pghpf epcf90 gfortran g95 f95 fort xlf95 ifort ifc efc pgf95 lf95 ftn + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_F77+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$F77"; then + ac_cv_prog_F77="$F77" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_F77="$ac_tool_prefix$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +F77=$ac_cv_prog_F77 +if test -n "$F77"; then + { echo "$as_me:$LINENO: result: $F77" >&5 +echo "${ECHO_T}$F77" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + test -n "$F77" && break + done +fi +if test -z "$F77"; then + ac_ct_F77=$F77 + for ac_prog in g77 f77 xlf frt pgf77 cf77 fort77 fl32 af77 f90 xlf90 pgf90 pghpf epcf90 gfortran g95 f95 fort xlf95 ifort ifc efc pgf95 lf95 ftn +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_ac_ct_F77+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_F77"; then + ac_cv_prog_ac_ct_F77="$ac_ct_F77" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_F77="$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +ac_ct_F77=$ac_cv_prog_ac_ct_F77 +if test -n "$ac_ct_F77"; then + { echo "$as_me:$LINENO: result: $ac_ct_F77" >&5 +echo "${ECHO_T}$ac_ct_F77" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + test -n "$ac_ct_F77" && break +done + + if test "x$ac_ct_F77" = x; then + F77="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&5 +echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&2;} +ac_tool_warned=yes ;; +esac + F77=$ac_ct_F77 + fi +fi + + +# Provide some information about the compiler. +echo "$as_me:$LINENO: checking for Fortran 77 compiler version" >&5 +ac_compiler=`set X $ac_compile; echo $2` +{ (ac_try="$ac_compiler --version >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compiler --version >&5") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (ac_try="$ac_compiler -v >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compiler -v >&5") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (ac_try="$ac_compiler -V >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compiler -V >&5") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +rm -f a.out + +# If we don't use `.F' as extension, the preprocessor is not run on the +# input file. (Note that this only needs to work for GNU compilers.) +ac_save_ext=$ac_ext +ac_ext=F +{ echo "$as_me:$LINENO: checking whether we are using the GNU Fortran 77 compiler" >&5 +echo $ECHO_N "checking whether we are using the GNU Fortran 77 compiler... $ECHO_C" >&6; } +if test "${ac_cv_f77_compiler_gnu+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF + program main +#ifndef __GNUC__ + choke me +#endif + + end +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_f77_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_compiler_gnu=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_compiler_gnu=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_f77_compiler_gnu=$ac_compiler_gnu + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_f77_compiler_gnu" >&5 +echo "${ECHO_T}$ac_cv_f77_compiler_gnu" >&6; } +ac_ext=$ac_save_ext +ac_test_FFLAGS=${FFLAGS+set} +ac_save_FFLAGS=$FFLAGS +FFLAGS= +{ echo "$as_me:$LINENO: checking whether $F77 accepts -g" >&5 +echo $ECHO_N "checking whether $F77 accepts -g... $ECHO_C" >&6; } +if test "${ac_cv_prog_f77_g+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + FFLAGS=-g +cat >conftest.$ac_ext <<_ACEOF + program main + + end +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_f77_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_prog_f77_g=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_prog_f77_g=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_prog_f77_g" >&5 +echo "${ECHO_T}$ac_cv_prog_f77_g" >&6; } +if test "$ac_test_FFLAGS" = set; then + FFLAGS=$ac_save_FFLAGS +elif test $ac_cv_prog_f77_g = yes; then + if test "x$ac_cv_f77_compiler_gnu" = xyes; then + FFLAGS="-g -O2" + else + FFLAGS="-g" + fi +else + if test "x$ac_cv_f77_compiler_gnu" = xyes; then + FFLAGS="-O2" + else + FFLAGS= + fi +fi + +G77=`test $ac_compiler_gnu = yes && echo yes` +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + +# Autoconf 2.13's AC_OBJEXT and AC_EXEEXT macros only works for C compilers! + +# find the maximum length of command line arguments +{ echo "$as_me:$LINENO: checking the maximum length of command line arguments" >&5 +echo $ECHO_N "checking the maximum length of command line arguments... $ECHO_C" >&6; } +if test "${lt_cv_sys_max_cmd_len+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + i=0 + teststring="ABCD" + + case $build_os in + msdosdjgpp*) + # On DJGPP, this test can blow up pretty badly due to problems in libc + # (any single argument exceeding 2000 bytes causes a buffer overrun + # during glob expansion). Even if it were fixed, the result of this + # check would be larger than it should be. + lt_cv_sys_max_cmd_len=12288; # 12K is about right + ;; + + gnu*) + # Under GNU Hurd, this test is not required because there is + # no limit to the length of command line arguments. + # Libtool will interpret -1 as no limit whatsoever + lt_cv_sys_max_cmd_len=-1; + ;; + + cygwin* | mingw*) + # On Win9x/ME, this test blows up -- it succeeds, but takes + # about 5 minutes as the teststring grows exponentially. + # Worse, since 9x/ME are not pre-emptively multitasking, + # you end up with a "frozen" computer, even though with patience + # the test eventually succeeds (with a max line length of 256k). + # Instead, let's just punt: use the minimum linelength reported by + # all of the supported platforms: 8192 (on NT/2K/XP). + lt_cv_sys_max_cmd_len=8192; + ;; + + amigaos*) + # On AmigaOS with pdksh, this test takes hours, literally. + # So we just punt and use a minimum line length of 8192. + lt_cv_sys_max_cmd_len=8192; + ;; + + netbsd* | freebsd* | openbsd* | darwin* | dragonfly*) + # This has been around since 386BSD, at least. Likely further. + if test -x /sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` + elif test -x /usr/sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` + else + lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs + fi + # And add a safety zone + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + ;; + + interix*) + # We know the value 262144 and hardcode it with a safety zone (like BSD) + lt_cv_sys_max_cmd_len=196608 + ;; + + osf*) + # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure + # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not + # nice to cause kernel panics so lets avoid the loop below. + # First set a reasonable default. + lt_cv_sys_max_cmd_len=16384 + # + if test -x /sbin/sysconfig; then + case `/sbin/sysconfig -q proc exec_disable_arg_limit` in + *1*) lt_cv_sys_max_cmd_len=-1 ;; + esac + fi + ;; + sco3.2v5*) + lt_cv_sys_max_cmd_len=102400 + ;; + sysv5* | sco5v6* | sysv4.2uw2*) + kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` + if test -n "$kargmax"; then + lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[ ]//'` + else + lt_cv_sys_max_cmd_len=32768 + fi + ;; + *) + # If test is not a shell built-in, we'll probably end up computing a + # maximum length that is only half of the actual maximum length, but + # we can't tell. + SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} + while (test "X"`$SHELL $0 --fallback-echo "X$teststring" 2>/dev/null` \ + = "XX$teststring") >/dev/null 2>&1 && + new_result=`expr "X$teststring" : ".*" 2>&1` && + lt_cv_sys_max_cmd_len=$new_result && + test $i != 17 # 1/2 MB should be enough + do + i=`expr $i + 1` + teststring=$teststring$teststring + done + teststring= + # Add a significant safety factor because C++ compilers can tack on massive + # amounts of additional arguments before passing them to the linker. + # It appears as though 1/2 is a usable value. + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` + ;; + esac + +fi + +if test -n $lt_cv_sys_max_cmd_len ; then + { echo "$as_me:$LINENO: result: $lt_cv_sys_max_cmd_len" >&5 +echo "${ECHO_T}$lt_cv_sys_max_cmd_len" >&6; } +else + { echo "$as_me:$LINENO: result: none" >&5 +echo "${ECHO_T}none" >&6; } +fi + + + + +# Check for command to grab the raw symbol name followed by C symbol from nm. +{ echo "$as_me:$LINENO: checking command to parse $NM output from $compiler object" >&5 +echo $ECHO_N "checking command to parse $NM output from $compiler object... $ECHO_C" >&6; } +if test "${lt_cv_sys_global_symbol_pipe+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + +# These are sane defaults that work on at least a few old systems. +# [They come from Ultrix. What could be older than Ultrix?!! ;)] + +# Character class describing NM global symbol codes. +symcode='[BCDEGRST]' + +# Regexp to match symbols that can be accessed directly from C. +sympat='\([_A-Za-z][_A-Za-z0-9]*\)' + +# Transform an extracted symbol line into a proper C declaration +lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^. .* \(.*\)$/extern int \1;/p'" + +# Transform an extracted symbol line into symbol name and symbol address +lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode \([^ ]*\) \([^ ]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" + +# Define system-specific variables. +case $host_os in +aix*) + symcode='[BCDT]' + ;; +cygwin* | mingw* | pw32*) + symcode='[ABCDGISTW]' + ;; +hpux*) # Its linker distinguishes data from code symbols + if test "$host_cpu" = ia64; then + symcode='[ABCDEGRST]' + fi + lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" + lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" + ;; +linux*) + if test "$host_cpu" = ia64; then + symcode='[ABCDGIRSTW]' + lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" + lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" + fi + ;; +irix* | nonstopux*) + symcode='[BCDEGRST]' + ;; +osf*) + symcode='[BCDEGQRST]' + ;; +solaris*) + symcode='[BDRT]' + ;; +sco3.2v5*) + symcode='[DT]' + ;; +sysv4.2uw2*) + symcode='[DT]' + ;; +sysv5* | sco5v6* | unixware* | OpenUNIX*) + symcode='[ABDT]' + ;; +sysv4) + symcode='[DFNSTU]' + ;; +esac + +# Handle CRLF in mingw tool chain +opt_cr= +case $build_os in +mingw*) + opt_cr=`echo 'x\{0,1\}' | tr x '\015'` # option cr in regexp + ;; +esac + +# If we're using GNU nm, then use its standard symbol codes. +case `$NM -V 2>&1` in +*GNU* | *'with BFD'*) + symcode='[ABCDGIRSTW]' ;; +esac + +# Try without a prefix undercore, then with it. +for ac_symprfx in "" "_"; do + + # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. + symxfrm="\\1 $ac_symprfx\\2 \\2" + + # Write the raw and C identifiers. + lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[ ]\($symcode$symcode*\)[ ][ ]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" + + # Check to see that the pipe works correctly. + pipe_works=no + + rm -f conftest* + cat > conftest.$ac_ext <&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + # Now try to grab the symbols. + nlist=conftest.nm + if { (eval echo "$as_me:$LINENO: \"$NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist\"") >&5 + (eval $NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && test -s "$nlist"; then + # Try sorting and uniquifying the output. + if sort "$nlist" | uniq > "$nlist"T; then + mv -f "$nlist"T "$nlist" + else + rm -f "$nlist"T + fi + + # Make sure that we snagged all the symbols we need. + if grep ' nm_test_var$' "$nlist" >/dev/null; then + if grep ' nm_test_func$' "$nlist" >/dev/null; then + cat < conftest.$ac_ext +#ifdef __cplusplus +extern "C" { +#endif + +EOF + # Now generate the symbol file. + eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | grep -v main >> conftest.$ac_ext' + + cat <> conftest.$ac_ext +#if defined (__STDC__) && __STDC__ +# define lt_ptr_t void * +#else +# define lt_ptr_t char * +# define const +#endif + +/* The mapping between symbol names and symbols. */ +const struct { + const char *name; + lt_ptr_t address; +} +lt_preloaded_symbols[] = +{ +EOF + $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (lt_ptr_t) \&\2},/" < "$nlist" | grep -v main >> conftest.$ac_ext + cat <<\EOF >> conftest.$ac_ext + {0, (lt_ptr_t) 0} +}; + +#ifdef __cplusplus +} +#endif +EOF + # Now try linking the two files. + mv conftest.$ac_objext conftstm.$ac_objext + lt_save_LIBS="$LIBS" + lt_save_CFLAGS="$CFLAGS" + LIBS="conftstm.$ac_objext" + CFLAGS="$CFLAGS$lt_prog_compiler_no_builtin_flag" + if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && test -s conftest${ac_exeext}; then + pipe_works=yes + fi + LIBS="$lt_save_LIBS" + CFLAGS="$lt_save_CFLAGS" + else + echo "cannot find nm_test_func in $nlist" >&5 + fi + else + echo "cannot find nm_test_var in $nlist" >&5 + fi + else + echo "cannot run $lt_cv_sys_global_symbol_pipe" >&5 + fi + else + echo "$progname: failed program was:" >&5 + cat conftest.$ac_ext >&5 + fi + rm -f conftest* conftst* + + # Do not use the global_symbol_pipe unless it works. + if test "$pipe_works" = yes; then + break + else + lt_cv_sys_global_symbol_pipe= + fi +done + +fi + +if test -z "$lt_cv_sys_global_symbol_pipe"; then + lt_cv_sys_global_symbol_to_cdecl= +fi +if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then + { echo "$as_me:$LINENO: result: failed" >&5 +echo "${ECHO_T}failed" >&6; } +else + { echo "$as_me:$LINENO: result: ok" >&5 +echo "${ECHO_T}ok" >&6; } +fi + +{ echo "$as_me:$LINENO: checking for objdir" >&5 +echo $ECHO_N "checking for objdir... $ECHO_C" >&6; } +if test "${lt_cv_objdir+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + rm -f .libs 2>/dev/null +mkdir .libs 2>/dev/null +if test -d .libs; then + lt_cv_objdir=.libs +else + # MS-DOS does not allow filenames that begin with a dot. + lt_cv_objdir=_libs +fi +rmdir .libs 2>/dev/null +fi +{ echo "$as_me:$LINENO: result: $lt_cv_objdir" >&5 +echo "${ECHO_T}$lt_cv_objdir" >&6; } +objdir=$lt_cv_objdir + + + + + +case $host_os in +aix3*) + # AIX sometimes has problems with the GCC collect2 program. For some + # reason, if we set the COLLECT_NAMES environment variable, the problems + # vanish in a puff of smoke. + if test "X${COLLECT_NAMES+set}" != Xset; then + COLLECT_NAMES= + export COLLECT_NAMES + fi + ;; +esac + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +Xsed='sed -e 1s/^X//' +sed_quote_subst='s/\([\\"\\`$\\\\]\)/\\\1/g' + +# Same as above, but do not quote variable references. +double_quote_subst='s/\([\\"\\`\\\\]\)/\\\1/g' + +# Sed substitution to delay expansion of an escaped shell variable in a +# double_quote_subst'ed string. +delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' + +# Sed substitution to avoid accidental globbing in evaled expressions +no_glob_subst='s/\*/\\\*/g' + +# Constants: +rm="rm -f" + +# Global variables: +default_ofile=mklib +can_build_shared=yes + +# All known linkers require a `.a' archive for static linking (except MSVC, +# which needs '.lib'). +libext=a +ltmain="$ac_aux_dir/ltmain.sh" +ofile="$default_ofile" +with_gnu_ld="$lt_cv_prog_gnu_ld" + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args. +set dummy ${ac_tool_prefix}ar; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_AR+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$AR"; then + ac_cv_prog_AR="$AR" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_AR="${ac_tool_prefix}ar" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +AR=$ac_cv_prog_AR +if test -n "$AR"; then + { echo "$as_me:$LINENO: result: $AR" >&5 +echo "${ECHO_T}$AR" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_AR"; then + ac_ct_AR=$AR + # Extract the first word of "ar", so it can be a program name with args. +set dummy ar; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_ac_ct_AR+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_AR"; then + ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_AR="ar" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +ac_ct_AR=$ac_cv_prog_ac_ct_AR +if test -n "$ac_ct_AR"; then + { echo "$as_me:$LINENO: result: $ac_ct_AR" >&5 +echo "${ECHO_T}$ac_ct_AR" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + if test "x$ac_ct_AR" = x; then + AR="false" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&5 +echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&2;} +ac_tool_warned=yes ;; +esac + AR=$ac_ct_AR + fi +else + AR="$ac_cv_prog_AR" +fi + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. +set dummy ${ac_tool_prefix}ranlib; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_RANLIB+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$RANLIB"; then + ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +RANLIB=$ac_cv_prog_RANLIB +if test -n "$RANLIB"; then + { echo "$as_me:$LINENO: result: $RANLIB" >&5 +echo "${ECHO_T}$RANLIB" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_RANLIB"; then + ac_ct_RANLIB=$RANLIB + # Extract the first word of "ranlib", so it can be a program name with args. +set dummy ranlib; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_RANLIB"; then + ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_RANLIB="ranlib" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB +if test -n "$ac_ct_RANLIB"; then + { echo "$as_me:$LINENO: result: $ac_ct_RANLIB" >&5 +echo "${ECHO_T}$ac_ct_RANLIB" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + if test "x$ac_ct_RANLIB" = x; then + RANLIB=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&5 +echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&2;} +ac_tool_warned=yes ;; +esac + RANLIB=$ac_ct_RANLIB + fi +else + RANLIB="$ac_cv_prog_RANLIB" +fi + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. +set dummy ${ac_tool_prefix}strip; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_STRIP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$STRIP"; then + ac_cv_prog_STRIP="$STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_STRIP="${ac_tool_prefix}strip" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +STRIP=$ac_cv_prog_STRIP +if test -n "$STRIP"; then + { echo "$as_me:$LINENO: result: $STRIP" >&5 +echo "${ECHO_T}$STRIP" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_STRIP"; then + ac_ct_STRIP=$STRIP + # Extract the first word of "strip", so it can be a program name with args. +set dummy strip; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_ac_ct_STRIP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_STRIP"; then + ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_STRIP="strip" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP +if test -n "$ac_ct_STRIP"; then + { echo "$as_me:$LINENO: result: $ac_ct_STRIP" >&5 +echo "${ECHO_T}$ac_ct_STRIP" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + if test "x$ac_ct_STRIP" = x; then + STRIP=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&5 +echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&2;} +ac_tool_warned=yes ;; +esac + STRIP=$ac_ct_STRIP + fi +else + STRIP="$ac_cv_prog_STRIP" +fi + + +old_CC="$CC" +old_CFLAGS="$CFLAGS" + +# Set sane defaults for various variables +test -z "$AR" && AR=ar +test -z "$AR_FLAGS" && AR_FLAGS=cru +test -z "$AS" && AS=as +test -z "$CC" && CC=cc +test -z "$LTCC" && LTCC=$CC +test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS +test -z "$DLLTOOL" && DLLTOOL=dlltool +test -z "$LD" && LD=ld +test -z "$LN_S" && LN_S="ln -s" +test -z "$MAGIC_CMD" && MAGIC_CMD=file +test -z "$NM" && NM=nm +test -z "$SED" && SED=sed +test -z "$OBJDUMP" && OBJDUMP=objdump +test -z "$RANLIB" && RANLIB=: +test -z "$STRIP" && STRIP=: +test -z "$ac_objext" && ac_objext=o + +# Determine commands to create old-style static archives. +old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs$old_deplibs' +old_postinstall_cmds='chmod 644 $oldlib' +old_postuninstall_cmds= + +if test -n "$RANLIB"; then + case $host_os in + openbsd*) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$oldlib" + ;; + *) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$oldlib" + ;; + esac + old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib" +fi + +for cc_temp in $compiler""; do + case $cc_temp in + compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; + distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; + \-*) ;; + *) break;; + esac +done +cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` + + +# Only perform the check for file, if the check method requires it +case $deplibs_check_method in +file_magic*) + if test "$file_magic_cmd" = '$MAGIC_CMD'; then + { echo "$as_me:$LINENO: checking for ${ac_tool_prefix}file" >&5 +echo $ECHO_N "checking for ${ac_tool_prefix}file... $ECHO_C" >&6; } +if test "${lt_cv_path_MAGIC_CMD+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $MAGIC_CMD in +[\\/*] | ?:[\\/]*) + lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. + ;; +*) + lt_save_MAGIC_CMD="$MAGIC_CMD" + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" + for ac_dir in $ac_dummy; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/${ac_tool_prefix}file; then + lt_cv_path_MAGIC_CMD="$ac_dir/${ac_tool_prefix}file" + if test -n "$file_magic_test_file"; then + case $deplibs_check_method in + "file_magic "*) + file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` + MAGIC_CMD="$lt_cv_path_MAGIC_CMD" + if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | + $EGREP "$file_magic_regex" > /dev/null; then + : + else + cat <&2 + +*** Warning: the command libtool uses to detect shared libraries, +*** $file_magic_cmd, produces output that libtool cannot recognize. +*** The result is that libtool may fail to recognize shared libraries +*** as such. This will affect the creation of libtool libraries that +*** depend on shared libraries, but programs linked with such libtool +*** libraries will work regardless of this problem. Nevertheless, you +*** may want to report the problem to your system manager and/or to +*** bug-libtool@gnu.org + +EOF + fi ;; + esac + fi + break + fi + done + IFS="$lt_save_ifs" + MAGIC_CMD="$lt_save_MAGIC_CMD" + ;; +esac +fi + +MAGIC_CMD="$lt_cv_path_MAGIC_CMD" +if test -n "$MAGIC_CMD"; then + { echo "$as_me:$LINENO: result: $MAGIC_CMD" >&5 +echo "${ECHO_T}$MAGIC_CMD" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + +if test -z "$lt_cv_path_MAGIC_CMD"; then + if test -n "$ac_tool_prefix"; then + { echo "$as_me:$LINENO: checking for file" >&5 +echo $ECHO_N "checking for file... $ECHO_C" >&6; } +if test "${lt_cv_path_MAGIC_CMD+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $MAGIC_CMD in +[\\/*] | ?:[\\/]*) + lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. + ;; +*) + lt_save_MAGIC_CMD="$MAGIC_CMD" + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" + for ac_dir in $ac_dummy; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/file; then + lt_cv_path_MAGIC_CMD="$ac_dir/file" + if test -n "$file_magic_test_file"; then + case $deplibs_check_method in + "file_magic "*) + file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` + MAGIC_CMD="$lt_cv_path_MAGIC_CMD" + if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | + $EGREP "$file_magic_regex" > /dev/null; then + : + else + cat <&2 + +*** Warning: the command libtool uses to detect shared libraries, +*** $file_magic_cmd, produces output that libtool cannot recognize. +*** The result is that libtool may fail to recognize shared libraries +*** as such. This will affect the creation of libtool libraries that +*** depend on shared libraries, but programs linked with such libtool +*** libraries will work regardless of this problem. Nevertheless, you +*** may want to report the problem to your system manager and/or to +*** bug-libtool@gnu.org + +EOF + fi ;; + esac + fi + break + fi + done + IFS="$lt_save_ifs" + MAGIC_CMD="$lt_save_MAGIC_CMD" + ;; +esac +fi + +MAGIC_CMD="$lt_cv_path_MAGIC_CMD" +if test -n "$MAGIC_CMD"; then + { echo "$as_me:$LINENO: result: $MAGIC_CMD" >&5 +echo "${ECHO_T}$MAGIC_CMD" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + else + MAGIC_CMD=: + fi +fi + + fi + ;; +esac + +enable_dlopen=yes +enable_win32_dll=no + +# Check whether --enable-libtool-lock was given. +if test "${enable_libtool_lock+set}" = set; then + enableval=$enable_libtool_lock; +fi + +test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes + + +# Check whether --with-pic was given. +if test "${with_pic+set}" = set; then + withval=$with_pic; pic_mode="$withval" +else + pic_mode=default +fi + +test -z "$pic_mode" && pic_mode=default + +# Use C for the default configuration in the libtool script +tagname= +lt_save_CC="$CC" +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +# Source file extension for C test sources. +ac_ext=c + +# Object file extension for compiled C test sources. +objext=o +objext=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="int some_variable = 0;\n" + +# Code to be used in simple link tests +lt_simple_link_test_code='int main(){return(0);}\n' + + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC + + +# save warnings/boilerplate of simple test code +ac_outfile=conftest.$ac_objext +printf "$lt_simple_compile_test_code" >conftest.$ac_ext +eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_compiler_boilerplate=`cat conftest.err` +$rm conftest* + +ac_outfile=conftest.$ac_objext +printf "$lt_simple_link_test_code" >conftest.$ac_ext +eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_linker_boilerplate=`cat conftest.err` +$rm conftest* + + + +lt_prog_compiler_no_builtin_flag= + +if test "$GCC" = yes; then + lt_prog_compiler_no_builtin_flag=' -fno-builtin' + + +{ echo "$as_me:$LINENO: checking if $compiler supports -fno-rtti -fno-exceptions" >&5 +echo $ECHO_N "checking if $compiler supports -fno-rtti -fno-exceptions... $ECHO_C" >&6; } +if test "${lt_cv_prog_compiler_rtti_exceptions+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + lt_cv_prog_compiler_rtti_exceptions=no + ac_outfile=conftest.$ac_objext + printf "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="-fno-rtti -fno-exceptions" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:14985: $lt_compile\"" >&5) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&5 + echo "$as_me:14989: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings other than the usual output. + $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler_rtti_exceptions=yes + fi + fi + $rm conftest* + +fi +{ echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_rtti_exceptions" >&5 +echo "${ECHO_T}$lt_cv_prog_compiler_rtti_exceptions" >&6; } + +if test x"$lt_cv_prog_compiler_rtti_exceptions" = xyes; then + lt_prog_compiler_no_builtin_flag="$lt_prog_compiler_no_builtin_flag -fno-rtti -fno-exceptions" +else + : +fi + +fi + +lt_prog_compiler_wl= +lt_prog_compiler_pic= +lt_prog_compiler_static= + +{ echo "$as_me:$LINENO: checking for $compiler option to produce PIC" >&5 +echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6; } + + if test "$GCC" = yes; then + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_static='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + lt_prog_compiler_static='-Bstatic' + fi + ;; + + amigaos*) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the `-m68020' flag to GCC prevents building anything better, + # like `-m68040'. + lt_prog_compiler_pic='-m68020 -resident32 -malways-restore-a4' + ;; + + beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + + mingw* | pw32* | os2*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + lt_prog_compiler_pic='-DDLL_EXPORT' + ;; + + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + lt_prog_compiler_pic='-fno-common' + ;; + + interix3*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + + msdosdjgpp*) + # Just because we use GCC doesn't mean we suddenly get shared libraries + # on systems that don't support them. + lt_prog_compiler_can_build_shared=no + enable_shared=no + ;; + + sysv4*MP*) + if test -d /usr/nec; then + lt_prog_compiler_pic=-Kconform_pic + fi + ;; + + hpux*) + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + lt_prog_compiler_pic='-fPIC' + ;; + esac + ;; + + *) + lt_prog_compiler_pic='-fPIC' + ;; + esac + else + # PORTME Check for flag to pass linker flags through the system compiler. + case $host_os in + aix*) + lt_prog_compiler_wl='-Wl,' + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + lt_prog_compiler_static='-Bstatic' + else + lt_prog_compiler_static='-bnso -bI:/lib/syscalls.exp' + fi + ;; + darwin*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + case $cc_basename in + xlc*) + lt_prog_compiler_pic='-qnocommon' + lt_prog_compiler_wl='-Wl,' + ;; + esac + ;; + + mingw* | pw32* | os2*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + lt_prog_compiler_pic='-DDLL_EXPORT' + ;; + + hpux9* | hpux10* | hpux11*) + lt_prog_compiler_wl='-Wl,' + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + lt_prog_compiler_pic='+Z' + ;; + esac + # Is there a better lt_prog_compiler_static that works with the bundled CC? + lt_prog_compiler_static='${wl}-a ${wl}archive' + ;; + + irix5* | irix6* | nonstopux*) + lt_prog_compiler_wl='-Wl,' + # PIC (with -KPIC) is the default. + lt_prog_compiler_static='-non_shared' + ;; + + newsos6) + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + ;; + + linux*) + case $cc_basename in + icc* | ecc*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-static' + ;; + pgcc* | pgf77* | pgf90* | pgf95*) + # Portland Group compilers (*not* the Pentium gcc compiler, + # which looks to be a dead project) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-fpic' + lt_prog_compiler_static='-Bstatic' + ;; + ccc*) + lt_prog_compiler_wl='-Wl,' + # All Alpha code is PIC. + lt_prog_compiler_static='-non_shared' + ;; + esac + ;; + + osf3* | osf4* | osf5*) + lt_prog_compiler_wl='-Wl,' + # All OSF/1 code is PIC. + lt_prog_compiler_static='-non_shared' + ;; + + solaris*) + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + case $cc_basename in + f77* | f90* | f95*) + lt_prog_compiler_wl='-Qoption ld ';; + *) + lt_prog_compiler_wl='-Wl,';; + esac + ;; + + sunos4*) + lt_prog_compiler_wl='-Qoption ld ' + lt_prog_compiler_pic='-PIC' + lt_prog_compiler_static='-Bstatic' + ;; + + sysv4 | sysv4.2uw2* | sysv4.3*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + ;; + + sysv4*MP*) + if test -d /usr/nec ;then + lt_prog_compiler_pic='-Kconform_pic' + lt_prog_compiler_static='-Bstatic' + fi + ;; + + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + ;; + + unicos*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_can_build_shared=no + ;; + + uts4*) + lt_prog_compiler_pic='-pic' + lt_prog_compiler_static='-Bstatic' + ;; + + *) + lt_prog_compiler_can_build_shared=no + ;; + esac + fi + +{ echo "$as_me:$LINENO: result: $lt_prog_compiler_pic" >&5 +echo "${ECHO_T}$lt_prog_compiler_pic" >&6; } + +# +# Check to make sure the PIC flag actually works. +# +if test -n "$lt_prog_compiler_pic"; then + +{ echo "$as_me:$LINENO: checking if $compiler PIC flag $lt_prog_compiler_pic works" >&5 +echo $ECHO_N "checking if $compiler PIC flag $lt_prog_compiler_pic works... $ECHO_C" >&6; } +if test "${lt_prog_compiler_pic_works+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + lt_prog_compiler_pic_works=no + ac_outfile=conftest.$ac_objext + printf "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="$lt_prog_compiler_pic -DPIC" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:15253: $lt_compile\"" >&5) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&5 + echo "$as_me:15257: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings other than the usual output. + $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then + lt_prog_compiler_pic_works=yes + fi + fi + $rm conftest* + +fi +{ echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_works" >&5 +echo "${ECHO_T}$lt_prog_compiler_pic_works" >&6; } + +if test x"$lt_prog_compiler_pic_works" = xyes; then + case $lt_prog_compiler_pic in + "" | " "*) ;; + *) lt_prog_compiler_pic=" $lt_prog_compiler_pic" ;; + esac +else + lt_prog_compiler_pic= + lt_prog_compiler_can_build_shared=no +fi + +fi +case $host_os in + # For platforms which do not support PIC, -DPIC is meaningless: + *djgpp*) + lt_prog_compiler_pic= + ;; + *) + lt_prog_compiler_pic="$lt_prog_compiler_pic -DPIC" + ;; +esac + +# +# Check to make sure the static flag actually works. +# +wl=$lt_prog_compiler_wl eval lt_tmp_static_flag=\"$lt_prog_compiler_static\" +{ echo "$as_me:$LINENO: checking if $compiler static flag $lt_tmp_static_flag works" >&5 +echo $ECHO_N "checking if $compiler static flag $lt_tmp_static_flag works... $ECHO_C" >&6; } +if test "${lt_prog_compiler_static_works+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + lt_prog_compiler_static_works=no + save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS $lt_tmp_static_flag" + printf "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The linker can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&5 + $echo "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then + lt_prog_compiler_static_works=yes + fi + else + lt_prog_compiler_static_works=yes + fi + fi + $rm conftest* + LDFLAGS="$save_LDFLAGS" + +fi +{ echo "$as_me:$LINENO: result: $lt_prog_compiler_static_works" >&5 +echo "${ECHO_T}$lt_prog_compiler_static_works" >&6; } + +if test x"$lt_prog_compiler_static_works" = xyes; then + : +else + lt_prog_compiler_static= +fi + + +{ echo "$as_me:$LINENO: checking if $compiler supports -c -o file.$ac_objext" >&5 +echo $ECHO_N "checking if $compiler supports -c -o file.$ac_objext... $ECHO_C" >&6; } +if test "${lt_cv_prog_compiler_c_o+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + lt_cv_prog_compiler_c_o=no + $rm -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + printf "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:15357: $lt_compile\"" >&5) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&5 + echo "$as_me:15361: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + lt_cv_prog_compiler_c_o=yes + fi + fi + chmod u+w . 2>&5 + $rm conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $rm out/ii_files/* && rmdir out/ii_files + $rm out/* && rmdir out + cd .. + rmdir conftest + $rm conftest* + +fi +{ echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_c_o" >&5 +echo "${ECHO_T}$lt_cv_prog_compiler_c_o" >&6; } + + +hard_links="nottested" +if test "$lt_cv_prog_compiler_c_o" = no && test "$need_locks" != no; then + # do not overwrite the value of need_locks provided by the user + { echo "$as_me:$LINENO: checking if we can lock with hard links" >&5 +echo $ECHO_N "checking if we can lock with hard links... $ECHO_C" >&6; } + hard_links=yes + $rm conftest* + ln conftest.a conftest.b 2>/dev/null && hard_links=no + touch conftest.a + ln conftest.a conftest.b 2>&5 || hard_links=no + ln conftest.a conftest.b 2>/dev/null && hard_links=no + { echo "$as_me:$LINENO: result: $hard_links" >&5 +echo "${ECHO_T}$hard_links" >&6; } + if test "$hard_links" = no; then + { echo "$as_me:$LINENO: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5 +echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;} + need_locks=warn + fi +else + need_locks=no +fi + +{ echo "$as_me:$LINENO: checking whether the $compiler linker ($LD) supports shared libraries" >&5 +echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared libraries... $ECHO_C" >&6; } + + runpath_var= + allow_undefined_flag= + enable_shared_with_static_runtimes=no + archive_cmds= + archive_expsym_cmds= + old_archive_From_new_cmds= + old_archive_from_expsyms_cmds= + export_dynamic_flag_spec= + whole_archive_flag_spec= + thread_safe_flag_spec= + hardcode_libdir_flag_spec= + hardcode_libdir_flag_spec_ld= + hardcode_libdir_separator= + hardcode_direct=no + hardcode_minus_L=no + hardcode_shlibpath_var=unsupported + link_all_deplibs=unknown + hardcode_automatic=no + module_cmds= + module_expsym_cmds= + always_export_symbols=no + export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + # include_expsyms should be a list of space-separated symbols to be *always* + # included in the symbol list + include_expsyms= + # exclude_expsyms can be an extended regexp of symbols to exclude + # it will be wrapped by ` (' and `)$', so one must not match beginning or + # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', + # as well as any symbol that contains `d'. + exclude_expsyms="_GLOBAL_OFFSET_TABLE_" + # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out + # platforms (ab)use it in PIC code, but their linkers get confused if + # the symbol is explicitly referenced. Since portable code cannot + # rely on this symbol name, it's probably fine to never include it in + # preloaded symbol tables. + extract_expsyms_cmds= + # Just being paranoid about ensuring that cc_basename is set. + for cc_temp in $compiler""; do + case $cc_temp in + compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; + distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; + \-*) ;; + *) break;; + esac +done +cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` + + case $host_os in + cygwin* | mingw* | pw32*) + # FIXME: the MSVC++ port hasn't been tested in a loooong time + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + if test "$GCC" != yes; then + with_gnu_ld=no + fi + ;; + interix*) + # we just hope/assume this is gcc and not c89 (= MSVC++) + with_gnu_ld=yes + ;; + openbsd*) + with_gnu_ld=no + ;; + esac + + ld_shlibs=yes + if test "$with_gnu_ld" = yes; then + # If archive_cmds runs LD, not CC, wlarc should be empty + wlarc='${wl}' + + # Set some defaults for GNU ld with shared library support. These + # are reset later if shared libraries are not supported. Putting them + # here allows them to be overridden if necessary. + runpath_var=LD_RUN_PATH + hardcode_libdir_flag_spec='${wl}--rpath ${wl}$libdir' + export_dynamic_flag_spec='${wl}--export-dynamic' + # ancient GNU ld didn't support --whole-archive et. al. + if $LD --help 2>&1 | grep 'no-whole-archive' > /dev/null; then + whole_archive_flag_spec="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + else + whole_archive_flag_spec= + fi + supports_anon_versioning=no + case `$LD -v 2>/dev/null` in + *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11 + *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... + *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... + *\ 2.11.*) ;; # other 2.11 versions + *) supports_anon_versioning=yes ;; + esac + + # See if GNU ld supports shared libraries. + case $host_os in + aix3* | aix4* | aix5*) + # On AIX/PPC, the GNU linker is very broken + if test "$host_cpu" != ia64; then + ld_shlibs=no + cat <&2 + +*** Warning: the GNU linker, at least up to release 2.9.1, is reported +*** to be unable to reliably create shared libraries on AIX. +*** Therefore, libtool is disabling shared libraries support. If you +*** really care for shared libraries, you may want to modify your PATH +*** so that a non-GNU linker is found, and then restart. + +EOF + fi + ;; + + amigaos*) + archive_cmds='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + + # Samuel A. Falvo II reports + # that the semantics of dynamic libraries on AmigaOS, at least up + # to version 4, is to share data among multiple programs linked + # with the same dynamic library. Since this doesn't match the + # behavior of shared libraries on other platforms, we can't use + # them. + ld_shlibs=no + ;; + + beos*) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + allow_undefined_flag=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + else + ld_shlibs=no + fi + ;; + + cygwin* | mingw* | pw32*) + # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, ) is actually meaningless, + # as there is no search path for DLLs. + hardcode_libdir_flag_spec='-L$libdir' + allow_undefined_flag=unsupported + always_export_symbols=no + enable_shared_with_static_runtimes=yes + export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS] /s/.* \([^ ]*\)/\1 DATA/'\'' | $SED -e '\''/^[AITW] /s/.* //'\'' | sort | uniq > $export_symbols' + + if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file (1st line + # is EXPORTS), use it as is; otherwise, prepend... + archive_expsym_cmds='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + ld_shlibs=no + fi + ;; + + interix3*) + hardcode_direct=no + hardcode_shlibpath_var=no + hardcode_libdir_flag_spec='${wl}-rpath,$libdir' + export_dynamic_flag_spec='${wl}-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + archive_expsym_cmds='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + + linux*) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + tmp_addflag= + case $cc_basename,$host_cpu in + pgcc*) # Portland Group C compiler + whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' + tmp_addflag=' $pic_flag' + ;; + pgf77* | pgf90* | pgf95*) # Portland Group f77 and f90 compilers + whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' + tmp_addflag=' $pic_flag -Mnomain' ;; + ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 + tmp_addflag=' -i_dynamic' ;; + efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 + tmp_addflag=' -i_dynamic -nofor_main' ;; + ifc* | ifort*) # Intel Fortran compiler + tmp_addflag=' -nofor_main' ;; + esac + archive_cmds='$CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + + if test $supports_anon_versioning = yes; then + archive_expsym_cmds='$echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + $echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' + fi + else + ld_shlibs=no + fi + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' + wlarc= + else + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + fi + ;; + + solaris*) + if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then + ld_shlibs=no + cat <&2 + +*** Warning: The releases 2.8.* of the GNU linker cannot reliably +*** create shared libraries on Solaris systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.9.1 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +EOF + elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + ld_shlibs=no + fi + ;; + + sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) + case `$LD -v 2>&1` in + *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*) + ld_shlibs=no + cat <<_LT_EOF 1>&2 + +*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not +*** reliably create shared libraries on SCO systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.16.91.0.3 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + ;; + *) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + hardcode_libdir_flag_spec='`test -z "$SCOABSPATH" && echo ${wl}-rpath,$libdir`' + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib' + archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname,-retain-symbols-file,$export_symbols -o $lib' + else + ld_shlibs=no + fi + ;; + esac + ;; + + sunos4*) + archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' + wlarc= + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + *) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + ld_shlibs=no + fi + ;; + esac + + if test "$ld_shlibs" = no; then + runpath_var= + hardcode_libdir_flag_spec= + export_dynamic_flag_spec= + whole_archive_flag_spec= + fi + else + # PORTME fill in a description of your system's linker (not GNU ld) + case $host_os in + aix3*) + allow_undefined_flag=unsupported + always_export_symbols=yes + archive_expsym_cmds='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' + # Note: this linker hardcodes the directories in LIBPATH if there + # are no directories specified by -L. + hardcode_minus_L=yes + if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then + # Neither direct hardcoding nor static linking is supported with a + # broken collect2. + hardcode_direct=unsupported + fi + ;; + + aix4* | aix5*) + if test "$host_cpu" = ia64; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag="" + else + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to AIX nm, but means don't demangle with GNU nm + if $NM -V 2>&1 | grep 'GNU' > /dev/null; then + export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols' + else + export_symbols_cmds='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols' + fi + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # need to do runtime linking. + case $host_os in aix4.[23]|aix4.[23].*|aix5*) + for ld_flag in $LDFLAGS; do + if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then + aix_use_runtimelinking=yes + break + fi + done + ;; + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + archive_cmds='' + hardcode_direct=yes + hardcode_libdir_separator=':' + link_all_deplibs=yes + + if test "$GCC" = yes; then + case $host_os in aix4.[012]|aix4.[012].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`${CC} -print-prog-name=collect2` + if test -f "$collect2name" && \ + strings "$collect2name" | grep resolve_lib_name >/dev/null + then + # We have reworked collect2 + hardcode_direct=yes + else + # We have old collect2 + hardcode_direct=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + hardcode_minus_L=yes + hardcode_libdir_flag_spec='-L$libdir' + hardcode_libdir_separator= + fi + ;; + esac + shared_flag='-shared' + if test "$aix_use_runtimelinking" = yes; then + shared_flag="$shared_flag "'${wl}-G' + fi + else + # not using gcc + if test "$host_cpu" = ia64; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test "$aix_use_runtimelinking" = yes; then + shared_flag='${wl}-G' + else + shared_flag='${wl}-bM:SRE' + fi + fi + fi + + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to export. + always_export_symbols=yes + if test "$aix_use_runtimelinking" = yes; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + allow_undefined_flag='-berok' + # Determine the default libpath from the value encoded in an empty executable. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + +aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'` +# Check for a 64-bit object if we didn't find anything. +if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'`; fi +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi + + hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" + archive_expsym_cmds="\$CC"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" + else + if test "$host_cpu" = ia64; then + hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib' + allow_undefined_flag="-z nodefs" + archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an empty executable. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + +aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'` +# Check for a 64-bit object if we didn't find anything. +if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'`; fi +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi + + hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + no_undefined_flag=' ${wl}-bernotok' + allow_undefined_flag=' ${wl}-berok' + # Exported symbols can be pulled into shared objects from archives + whole_archive_flag_spec='$convenience' + archive_cmds_need_lc=yes + # This is similar to how AIX traditionally builds its shared libraries. + archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' + fi + fi + ;; + + amigaos*) + archive_cmds='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + # see comment about different semantics on the GNU ld section + ld_shlibs=no + ;; + + bsdi[45]*) + export_dynamic_flag_spec=-rdynamic + ;; + + cygwin* | mingw* | pw32*) + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + hardcode_libdir_flag_spec=' ' + allow_undefined_flag=unsupported + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=".dll" + # FIXME: Setting linknames here is a bad hack. + archive_cmds='$CC -o $lib $libobjs $compiler_flags `echo "$deplibs" | $SED -e '\''s/ -lc$//'\''` -link -dll~linknames=' + # The linker will automatically build a .lib file if we build a DLL. + old_archive_From_new_cmds='true' + # FIXME: Should let the user specify the lib program. + old_archive_cmds='lib /OUT:$oldlib$oldobjs$old_deplibs' + fix_srcfile_path='`cygpath -w "$srcfile"`' + enable_shared_with_static_runtimes=yes + ;; + + darwin* | rhapsody*) + case $host_os in + rhapsody* | darwin1.[012]) + allow_undefined_flag='${wl}-undefined ${wl}suppress' + ;; + *) # Darwin 1.3 on + if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then + allow_undefined_flag='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' + else + case ${MACOSX_DEPLOYMENT_TARGET} in + 10.[012]) + allow_undefined_flag='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' + ;; + 10.*) + allow_undefined_flag='${wl}-undefined ${wl}dynamic_lookup' + ;; + esac + fi + ;; + esac + archive_cmds_need_lc=no + hardcode_direct=no + hardcode_automatic=yes + hardcode_shlibpath_var=unsupported + whole_archive_flag_spec='' + link_all_deplibs=yes + if test "$GCC" = yes ; then + output_verbose_link_cmd='echo' + archive_cmds='$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring' + module_cmds='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' + # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds + archive_expsym_cmds='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + module_expsym_cmds='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + else + case $cc_basename in + xlc*) + output_verbose_link_cmd='echo' + archive_cmds='$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $verstring' + module_cmds='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' + # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds + archive_expsym_cmds='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + module_expsym_cmds='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + ;; + *) + ld_shlibs=no + ;; + esac + fi + ;; + + dgux*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_shlibpath_var=no + ;; + + freebsd1*) + ld_shlibs=no + ;; + + # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor + # support. Future versions do this automatically, but an explicit c++rt0.o + # does not break anything, and helps significantly (at the cost of a little + # extra space). + freebsd2.2*) + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + # Unfortunately, older versions of FreeBSD 2 do not have this feature. + freebsd2*) + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=yes + hardcode_minus_L=yes + hardcode_shlibpath_var=no + ;; + + # FreeBSD 3 and greater uses gcc -shared to do shared libraries. + freebsd* | kfreebsd*-gnu | dragonfly*) + archive_cmds='$CC -shared -o $lib $libobjs $deplibs $compiler_flags' + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + hpux9*) + if test "$GCC" = yes; then + archive_cmds='$rm $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + else + archive_cmds='$rm $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + fi + hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' + hardcode_libdir_separator=: + hardcode_direct=yes + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L=yes + export_dynamic_flag_spec='${wl}-E' + ;; + + hpux10*) + if test "$GCC" = yes -a "$with_gnu_ld" = no; then + archive_cmds='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' + fi + if test "$with_gnu_ld" = no; then + hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' + hardcode_libdir_separator=: + + hardcode_direct=yes + export_dynamic_flag_spec='${wl}-E' + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L=yes + fi + ;; + + hpux11*) + if test "$GCC" = yes -a "$with_gnu_ld" = no; then + case $host_cpu in + hppa*64*) + archive_cmds='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + archive_cmds='$CC -shared ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + archive_cmds='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + else + case $host_cpu in + hppa*64*) + archive_cmds='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + fi + if test "$with_gnu_ld" = no; then + hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' + hardcode_libdir_separator=: + + case $host_cpu in + hppa*64*|ia64*) + hardcode_libdir_flag_spec_ld='+b $libdir' + hardcode_direct=no + hardcode_shlibpath_var=no + ;; + *) + hardcode_direct=yes + export_dynamic_flag_spec='${wl}-E' + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L=yes + ;; + esac + fi + ;; + + irix5* | irix6* | nonstopux*) + if test "$GCC" = yes; then + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + archive_cmds='$LD -shared $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + hardcode_libdir_flag_spec_ld='-rpath $libdir' + fi + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator=: + link_all_deplibs=yes + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out + else + archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF + fi + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + newsos6) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=yes + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator=: + hardcode_shlibpath_var=no + ;; + + openbsd*) + hardcode_direct=yes + hardcode_shlibpath_var=no + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' + hardcode_libdir_flag_spec='${wl}-rpath,$libdir' + export_dynamic_flag_spec='${wl}-E' + else + case $host_os in + openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*) + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec='-R$libdir' + ;; + *) + archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + hardcode_libdir_flag_spec='${wl}-rpath,$libdir' + ;; + esac + fi + ;; + + os2*) + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + allow_undefined_flag=unsupported + archive_cmds='$echo "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$echo DATA >> $output_objdir/$libname.def~$echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~$echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' + old_archive_From_new_cmds='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' + ;; + + osf3*) + if test "$GCC" = yes; then + allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' + archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + allow_undefined_flag=' -expect_unresolved \*' + archive_cmds='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + fi + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator=: + ;; + + osf4* | osf5*) # as osf3* with the addition of -msym flag + if test "$GCC" = yes; then + allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' + archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + else + allow_undefined_flag=' -expect_unresolved \*' + archive_cmds='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + archive_expsym_cmds='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; echo "-hidden">> $lib.exp~ + $LD -shared${allow_undefined_flag} -input $lib.exp $linker_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib~$rm $lib.exp' + + # Both c and cxx compiler support -rpath directly + hardcode_libdir_flag_spec='-rpath $libdir' + fi + hardcode_libdir_separator=: + ;; + + solaris*) + no_undefined_flag=' -z text' + if test "$GCC" = yes; then + wlarc='${wl}' + archive_cmds='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $CC -shared ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$rm $lib.exp' + else + wlarc='' + archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' + archive_expsym_cmds='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp' + fi + hardcode_libdir_flag_spec='-R$libdir' + hardcode_shlibpath_var=no + case $host_os in + solaris2.[0-5] | solaris2.[0-5].*) ;; + *) + # The compiler driver will combine linker options so we + # cannot just pass the convience library names through + # without $wl, iff we do not link with $LD. + # Luckily, gcc supports the same syntax we need for Sun Studio. + # Supported since Solaris 2.6 (maybe 2.5.1?) + case $wlarc in + '') + whole_archive_flag_spec='-z allextract$convenience -z defaultextract' ;; + *) + whole_archive_flag_spec='${wl}-z ${wl}allextract`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}-z ${wl}defaultextract' ;; + esac ;; + esac + link_all_deplibs=yes + ;; + + sunos4*) + if test "x$host_vendor" = xsequent; then + # Use $CC to link under sequent, because it throws in some extra .o + # files that make .init and .fini sections work. + archive_cmds='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' + fi + hardcode_libdir_flag_spec='-L$libdir' + hardcode_direct=yes + hardcode_minus_L=yes + hardcode_shlibpath_var=no + ;; + + sysv4) + case $host_vendor in + sni) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=yes # is this really true??? + ;; + siemens) + ## LD is ld it makes a PLAMLIB + ## CC just makes a GrossModule. + archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags' + reload_cmds='$CC -r -o $output$reload_objs' + hardcode_direct=no + ;; + motorola) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=no #Motorola manual says yes, but my tests say they lie + ;; + esac + runpath_var='LD_RUN_PATH' + hardcode_shlibpath_var=no + ;; + + sysv4.3*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_shlibpath_var=no + export_dynamic_flag_spec='-Bexport' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_shlibpath_var=no + runpath_var=LD_RUN_PATH + hardcode_runpath_var=yes + ld_shlibs=yes + fi + ;; + + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7*) + no_undefined_flag='${wl}-z,text' + archive_cmds_need_lc=no + hardcode_shlibpath_var=no + runpath_var='LD_RUN_PATH' + + if test "$GCC" = yes; then + archive_cmds='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + sysv5* | sco3.2v5* | sco5v6*) + # Note: We can NOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + no_undefined_flag='${wl}-z,text' + allow_undefined_flag='${wl}-z,nodefs' + archive_cmds_need_lc=no + hardcode_shlibpath_var=no + hardcode_libdir_flag_spec='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`' + hardcode_libdir_separator=':' + link_all_deplibs=yes + export_dynamic_flag_spec='${wl}-Bexport' + runpath_var='LD_RUN_PATH' + + if test "$GCC" = yes; then + archive_cmds='$CC -shared ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$CC -G ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + uts4*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_shlibpath_var=no + ;; + + *) + ld_shlibs=no + ;; + esac + fi + +{ echo "$as_me:$LINENO: result: $ld_shlibs" >&5 +echo "${ECHO_T}$ld_shlibs" >&6; } +test "$ld_shlibs" = no && can_build_shared=no + +# +# Do we need to explicitly link libc? +# +case "x$archive_cmds_need_lc" in +x|xyes) + # Assume -lc should be added + archive_cmds_need_lc=yes + + if test "$enable_shared" = yes && test "$GCC" = yes; then + case $archive_cmds in + *'~'*) + # FIXME: we may have to deal with multi-command sequences. + ;; + '$CC '*) + # Test whether the compiler implicitly links with -lc since on some + # systems, -lgcc has to come before -lc. If gcc already passes -lc + # to ld, don't add -lc before -lgcc. + { echo "$as_me:$LINENO: checking whether -lc should be explicitly linked in" >&5 +echo $ECHO_N "checking whether -lc should be explicitly linked in... $ECHO_C" >&6; } + $rm conftest* + printf "$lt_simple_compile_test_code" > conftest.$ac_ext + + if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } 2>conftest.err; then + soname=conftest + lib=conftest + libobjs=conftest.$ac_objext + deplibs= + wl=$lt_prog_compiler_wl + pic_flag=$lt_prog_compiler_pic + compiler_flags=-v + linker_flags=-v + verstring= + output_objdir=. + libname=conftest + lt_save_allow_undefined_flag=$allow_undefined_flag + allow_undefined_flag= + if { (eval echo "$as_me:$LINENO: \"$archive_cmds 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1\"") >&5 + (eval $archive_cmds 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + then + archive_cmds_need_lc=no + else + archive_cmds_need_lc=yes + fi + allow_undefined_flag=$lt_save_allow_undefined_flag + else + cat conftest.err 1>&5 + fi + $rm conftest* + { echo "$as_me:$LINENO: result: $archive_cmds_need_lc" >&5 +echo "${ECHO_T}$archive_cmds_need_lc" >&6; } + ;; + esac + fi + ;; +esac + +{ echo "$as_me:$LINENO: checking dynamic linker characteristics" >&5 +echo $ECHO_N "checking dynamic linker characteristics... $ECHO_C" >&6; } +library_names_spec= +libname_spec='lib$name' +soname_spec= +shrext_cmds=".so" +postinstall_cmds= +postuninstall_cmds= +finish_cmds= +finish_eval= +shlibpath_var= +shlibpath_overrides_runpath=unknown +version_type=none +dynamic_linker="$host_os ld.so" +sys_lib_dlsearch_path_spec="/lib /usr/lib" +if test "$GCC" = yes; then + sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` + if echo "$sys_lib_search_path_spec" | grep ';' >/dev/null ; then + # if the path contains ";" then we assume it to be the separator + # otherwise default to the standard path separator (i.e. ":") - it is + # assumed that no part of a normal pathname contains ";" but that should + # okay in the real world where ";" in dirpaths is itself problematic. + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi +else + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" +fi +need_lib_prefix=unknown +hardcode_into_libs=no + +# when you set need_version to no, make sure it does not cause -set_version +# flags to be left without arguments +need_version=unknown + +case $host_os in +aix3*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' + shlibpath_var=LIBPATH + + # AIX 3 has no versioning support, so we append a major version to the name. + soname_spec='${libname}${release}${shared_ext}$major' + ;; + +aix4* | aix5*) + version_type=linux + need_lib_prefix=no + need_version=no + hardcode_into_libs=yes + if test "$host_cpu" = ia64; then + # AIX 5 supports IA64 + library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + else + # With GCC up to 2.95.x, collect2 would create an import file + # for dependence libraries. The import file would start with + # the line `#! .'. This would cause the generated library to + # depend on `.', always an invalid library. This was fixed in + # development snapshots of GCC prior to 3.0. + case $host_os in + aix4 | aix4.[01] | aix4.[01].*) + if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' + echo ' yes ' + echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then + : + else + can_build_shared=no + fi + ;; + esac + # AIX (on Power*) has no versioning support, so currently we can not hardcode correct + # soname into executable. Probably we can add versioning support to + # collect2, so additional links can be useful in future. + if test "$aix_use_runtimelinking" = yes; then + # If using run time linking (on AIX 4.2 or later) use lib.so + # instead of lib.a to let people know that these are not + # typical AIX shared libraries. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + else + # We preserve .a as extension for shared libraries through AIX4.2 + # and later when we are not doing run time linking. + library_names_spec='${libname}${release}.a $libname.a' + soname_spec='${libname}${release}${shared_ext}$major' + fi + shlibpath_var=LIBPATH + fi + ;; + +amigaos*) + library_names_spec='$libname.ixlibrary $libname.a' + # Create ${libname}_ixlibrary.a entries in /sys/libs. + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' + ;; + +beos*) + library_names_spec='${libname}${shared_ext}' + dynamic_linker="$host_os ld.so" + shlibpath_var=LIBRARY_PATH + ;; + +bsdi[45]*) + version_type=linux + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" + sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" + # the default ld.so.conf also contains /usr/contrib/lib and + # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow + # libtool to hard-code these into programs + ;; + +cygwin* | mingw* | pw32*) + version_type=windows + shrext_cmds=".dll" + need_version=no + need_lib_prefix=no + + case $GCC,$host_os in + yes,cygwin* | yes,mingw* | yes,pw32*) + library_names_spec='$libname.dll.a' + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \${file}`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $rm \$dlpath' + shlibpath_overrides_runpath=yes + + case $host_os in + cygwin*) + # Cygwin DLLs use 'cyg' prefix rather than 'lib' + soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib" + ;; + mingw*) + # MinGW DLLs use traditional 'lib' prefix + soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` + if echo "$sys_lib_search_path_spec" | grep ';[c-zC-Z]:/' >/dev/null; then + # It is most probably a Windows format PATH printed by + # mingw gcc, but we are running on Cygwin. Gcc prints its search + # path with ; separators, and with drive letters. We can handle the + # drive letters (cygwin fileutils understands them), so leave them, + # especially as we might pass files found there to a mingw objdump, + # which wouldn't understand a cygwinified path. Ahh. + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi + ;; + pw32*) + # pw32 DLLs use 'pw' prefix rather than 'lib' + library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + ;; + esac + ;; + + *) + library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib' + ;; + esac + dynamic_linker='Win32 ld.exe' + # FIXME: first we should search . and the directory the executable is in + shlibpath_var=PATH + ;; + +darwin* | rhapsody*) + dynamic_linker="$host_os dyld" + version_type=darwin + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext' + soname_spec='${libname}${release}${major}$shared_ext' + shlibpath_overrides_runpath=yes + shlibpath_var=DYLD_LIBRARY_PATH + shrext_cmds='.dylib' + # Apple's gcc prints 'gcc -print-search-dirs' doesn't operate the same. + if test "$GCC" = yes; then + sys_lib_search_path_spec=`$CC -print-search-dirs | tr "\n" "$PATH_SEPARATOR" | sed -e 's/libraries:/@libraries:/' | tr "@" "\n" | grep "^libraries:" | sed -e "s/^libraries://" -e "s,=/,/,g" -e "s,$PATH_SEPARATOR, ,g" -e "s,.*,& /lib /usr/lib /usr/local/lib,g"` + else + sys_lib_search_path_spec='/lib /usr/lib /usr/local/lib' + fi + sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' + ;; + +dgux*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +freebsd1*) + dynamic_linker=no + ;; + +kfreebsd*-gnu) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='GNU ld.so' + ;; + +freebsd* | dragonfly*) + # DragonFly does not have aout. When/if they implement a new + # versioning mechanism, adjust this. + if test -x /usr/bin/objformat; then + objformat=`/usr/bin/objformat` + else + case $host_os in + freebsd[123]*) objformat=aout ;; + *) objformat=elf ;; + esac + fi + version_type=freebsd-$objformat + case $version_type in + freebsd-elf*) + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + need_version=no + need_lib_prefix=no + ;; + freebsd-*) + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' + need_version=yes + ;; + esac + shlibpath_var=LD_LIBRARY_PATH + case $host_os in + freebsd2*) + shlibpath_overrides_runpath=yes + ;; + freebsd3.[01]* | freebsdelf3.[01]*) + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ + freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + freebsd*) # from 4.6 on + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + esac + ;; + +gnu*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + hardcode_into_libs=yes + ;; + +hpux9* | hpux10* | hpux11*) + # Give a soname corresponding to the major version so that dld.sl refuses to + # link against other versions. + version_type=sunos + need_lib_prefix=no + need_version=no + case $host_cpu in + ia64*) + shrext_cmds='.so' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.so" + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + if test "X$HPUX_IA64_MODE" = X32; then + sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" + else + sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" + fi + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + hppa*64*) + shrext_cmds='.sl' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.sl" + shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + *) + shrext_cmds='.sl' + dynamic_linker="$host_os dld.sl" + shlibpath_var=SHLIB_PATH + shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + ;; + esac + # HP-UX runs *really* slowly unless shared libraries are mode 555. + postinstall_cmds='chmod 555 $lib' + ;; + +interix3*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +irix5* | irix6* | nonstopux*) + case $host_os in + nonstopux*) version_type=nonstopux ;; + *) + if test "$lt_cv_prog_gnu_ld" = yes; then + version_type=linux + else + version_type=irix + fi ;; + esac + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' + case $host_os in + irix5* | nonstopux*) + libsuff= shlibsuff= + ;; + *) + case $LD in # libtool.m4 will add one of these switches to LD + *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") + libsuff= shlibsuff= libmagic=32-bit;; + *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") + libsuff=32 shlibsuff=N32 libmagic=N32;; + *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") + libsuff=64 shlibsuff=64 libmagic=64-bit;; + *) libsuff= shlibsuff= libmagic=never-match;; + esac + ;; + esac + shlibpath_var=LD_LIBRARY${shlibsuff}_PATH + shlibpath_overrides_runpath=no + sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" + sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" + hardcode_into_libs=yes + ;; + +# No shared lib support for Linux oldld, aout, or coff. +linux*oldld* | linux*aout* | linux*coff*) + dynamic_linker=no + ;; + +# This must be Linux ELF. +linux*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + # Append ld.so.conf contents to the search path + if test -f /etc/ld.so.conf; then + lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '` + sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" + fi + + # We used to test for /lib/ld.so.1 and disable shared libraries on + # powerpc, because MkLinux only supported shared libraries with the + # GNU dynamic linker. Since this was broken with cross compilers, + # most powerpc-linux boxes support dynamic linking these days and + # people can always --disable-shared, the test was removed, and we + # assume the GNU/Linux dynamic linker is in use. + dynamic_linker='GNU/Linux ld.so' + ;; + +knetbsd*-gnu) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='GNU ld.so' + ;; + +netbsd*) + version_type=sunos + need_lib_prefix=no + need_version=no + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + dynamic_linker='NetBSD (a.out) ld.so' + else + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='NetBSD ld.elf_so' + fi + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + +newsos6) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +nto-qnx*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +openbsd*) + version_type=sunos + sys_lib_dlsearch_path_spec="/usr/lib" + need_lib_prefix=no + # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. + case $host_os in + openbsd3.3 | openbsd3.3.*) need_version=yes ;; + *) need_version=no ;; + esac + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + shlibpath_var=LD_LIBRARY_PATH + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + case $host_os in + openbsd2.[89] | openbsd2.[89].*) + shlibpath_overrides_runpath=no + ;; + *) + shlibpath_overrides_runpath=yes + ;; + esac + else + shlibpath_overrides_runpath=yes + fi + ;; + +os2*) + libname_spec='$name' + shrext_cmds=".dll" + need_lib_prefix=no + library_names_spec='$libname${shared_ext} $libname.a' + dynamic_linker='OS/2 ld.exe' + shlibpath_var=LIBPATH + ;; + +osf3* | osf4* | osf5*) + version_type=osf + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" + sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" + ;; + +solaris*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + # ldd complains unless libraries are executable + postinstall_cmds='chmod +x $lib' + ;; + +sunos4*) + version_type=sunos + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + if test "$with_gnu_ld" = yes; then + need_lib_prefix=no + fi + need_version=yes + ;; + +sysv4 | sysv4.3*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + case $host_vendor in + sni) + shlibpath_overrides_runpath=no + need_lib_prefix=no + export_dynamic_flag_spec='${wl}-Blargedynsym' + runpath_var=LD_RUN_PATH + ;; + siemens) + need_lib_prefix=no + ;; + motorola) + need_lib_prefix=no + need_version=no + shlibpath_overrides_runpath=no + sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' + ;; + esac + ;; + +sysv4*MP*) + if test -d /usr/nec ;then + version_type=linux + library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' + soname_spec='$libname${shared_ext}.$major' + shlibpath_var=LD_LIBRARY_PATH + fi + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + version_type=freebsd-elf + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + hardcode_into_libs=yes + if test "$with_gnu_ld" = yes; then + sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' + shlibpath_overrides_runpath=no + else + sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' + shlibpath_overrides_runpath=yes + case $host_os in + sco3.2v5*) + sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" + ;; + esac + fi + sys_lib_dlsearch_path_spec='/usr/lib' + ;; + +uts4*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +*) + dynamic_linker=no + ;; +esac +{ echo "$as_me:$LINENO: result: $dynamic_linker" >&5 +echo "${ECHO_T}$dynamic_linker" >&6; } +test "$dynamic_linker" = no && can_build_shared=no + +variables_saved_for_relink="PATH $shlibpath_var $runpath_var" +if test "$GCC" = yes; then + variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" +fi + +{ echo "$as_me:$LINENO: checking how to hardcode library paths into programs" >&5 +echo $ECHO_N "checking how to hardcode library paths into programs... $ECHO_C" >&6; } +hardcode_action= +if test -n "$hardcode_libdir_flag_spec" || \ + test -n "$runpath_var" || \ + test "X$hardcode_automatic" = "Xyes" ; then + + # We can hardcode non-existant directories. + if test "$hardcode_direct" != no && + # If the only mechanism to avoid hardcoding is shlibpath_var, we + # have to relink, otherwise we might link with an installed library + # when we should be linking with a yet-to-be-installed one + ## test "$_LT_AC_TAGVAR(hardcode_shlibpath_var, )" != no && + test "$hardcode_minus_L" != no; then + # Linking always hardcodes the temporary library directory. + hardcode_action=relink + else + # We can link without hardcoding, and we can hardcode nonexisting dirs. + hardcode_action=immediate + fi +else + # We cannot hardcode anything, or else we can only hardcode existing + # directories. + hardcode_action=unsupported +fi +{ echo "$as_me:$LINENO: result: $hardcode_action" >&5 +echo "${ECHO_T}$hardcode_action" >&6; } + +if test "$hardcode_action" = relink; then + # Fast installation is not supported + enable_fast_install=no +elif test "$shlibpath_overrides_runpath" = yes || + test "$enable_shared" = no; then + # Fast installation is not necessary + enable_fast_install=needless +fi + +striplib= +old_striplib= +{ echo "$as_me:$LINENO: checking whether stripping libraries is possible" >&5 +echo $ECHO_N "checking whether stripping libraries is possible... $ECHO_C" >&6; } +if test -n "$STRIP" && $STRIP -V 2>&1 | grep "GNU strip" >/dev/null; then + test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" + test -z "$striplib" && striplib="$STRIP --strip-unneeded" + { echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6; } +else +# FIXME - insert some real tests, host_os isn't really good enough + case $host_os in + darwin*) + if test -n "$STRIP" ; then + striplib="$STRIP -x" + { echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6; } + else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + ;; + *) + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } + ;; + esac +fi + +if test "x$enable_dlopen" != xyes; then + enable_dlopen=unknown + enable_dlopen_self=unknown + enable_dlopen_self_static=unknown +else + lt_cv_dlopen=no + lt_cv_dlopen_libs= + + case $host_os in + beos*) + lt_cv_dlopen="load_add_on" + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ;; + + mingw* | pw32*) + lt_cv_dlopen="LoadLibrary" + lt_cv_dlopen_libs= + ;; + + cygwin*) + lt_cv_dlopen="dlopen" + lt_cv_dlopen_libs= + ;; + + darwin*) + # if libdl is installed we need to link against it + { echo "$as_me:$LINENO: checking for dlopen in -ldl" >&5 +echo $ECHO_N "checking for dlopen in -ldl... $ECHO_C" >&6; } +if test "${ac_cv_lib_dl_dlopen+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldl $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dlopen (); +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_dl_dlopen=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_dl_dlopen=no +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_dl_dlopen" >&5 +echo "${ECHO_T}$ac_cv_lib_dl_dlopen" >&6; } +if test $ac_cv_lib_dl_dlopen = yes; then + lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" +else + + lt_cv_dlopen="dyld" + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + +fi + + ;; + + *) + { echo "$as_me:$LINENO: checking for shl_load" >&5 +echo $ECHO_N "checking for shl_load... $ECHO_C" >&6; } +if test "${ac_cv_func_shl_load+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define shl_load to an innocuous variant, in case declares shl_load. + For example, HP-UX 11i declares gettimeofday. */ +#define shl_load innocuous_shl_load + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char shl_load (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef shl_load + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char shl_load (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_shl_load || defined __stub___shl_load +choke me +#endif + +int +main () +{ +return shl_load (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_shl_load=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_func_shl_load=no +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ac_cv_func_shl_load" >&5 +echo "${ECHO_T}$ac_cv_func_shl_load" >&6; } +if test $ac_cv_func_shl_load = yes; then + lt_cv_dlopen="shl_load" +else + { echo "$as_me:$LINENO: checking for shl_load in -ldld" >&5 +echo $ECHO_N "checking for shl_load in -ldld... $ECHO_C" >&6; } +if test "${ac_cv_lib_dld_shl_load+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldld $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char shl_load (); +int +main () +{ +return shl_load (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_dld_shl_load=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_dld_shl_load=no +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_dld_shl_load" >&5 +echo "${ECHO_T}$ac_cv_lib_dld_shl_load" >&6; } +if test $ac_cv_lib_dld_shl_load = yes; then + lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-dld" +else + { echo "$as_me:$LINENO: checking for dlopen" >&5 +echo $ECHO_N "checking for dlopen... $ECHO_C" >&6; } +if test "${ac_cv_func_dlopen+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define dlopen to an innocuous variant, in case declares dlopen. + For example, HP-UX 11i declares gettimeofday. */ +#define dlopen innocuous_dlopen + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char dlopen (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef dlopen + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dlopen (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_dlopen || defined __stub___dlopen +choke me +#endif + +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_dlopen=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_func_dlopen=no +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ac_cv_func_dlopen" >&5 +echo "${ECHO_T}$ac_cv_func_dlopen" >&6; } +if test $ac_cv_func_dlopen = yes; then + lt_cv_dlopen="dlopen" +else + { echo "$as_me:$LINENO: checking for dlopen in -ldl" >&5 +echo $ECHO_N "checking for dlopen in -ldl... $ECHO_C" >&6; } +if test "${ac_cv_lib_dl_dlopen+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldl $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dlopen (); +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_dl_dlopen=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_dl_dlopen=no +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_dl_dlopen" >&5 +echo "${ECHO_T}$ac_cv_lib_dl_dlopen" >&6; } +if test $ac_cv_lib_dl_dlopen = yes; then + lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" +else + { echo "$as_me:$LINENO: checking for dlopen in -lsvld" >&5 +echo $ECHO_N "checking for dlopen in -lsvld... $ECHO_C" >&6; } +if test "${ac_cv_lib_svld_dlopen+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lsvld $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dlopen (); +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_svld_dlopen=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_svld_dlopen=no +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_svld_dlopen" >&5 +echo "${ECHO_T}$ac_cv_lib_svld_dlopen" >&6; } +if test $ac_cv_lib_svld_dlopen = yes; then + lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld" +else + { echo "$as_me:$LINENO: checking for dld_link in -ldld" >&5 +echo $ECHO_N "checking for dld_link in -ldld... $ECHO_C" >&6; } +if test "${ac_cv_lib_dld_dld_link+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldld $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dld_link (); +int +main () +{ +return dld_link (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_dld_dld_link=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_dld_dld_link=no +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_dld_dld_link" >&5 +echo "${ECHO_T}$ac_cv_lib_dld_dld_link" >&6; } +if test $ac_cv_lib_dld_dld_link = yes; then + lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-dld" +fi + + +fi + + +fi + + +fi + + +fi + + +fi + + ;; + esac + + if test "x$lt_cv_dlopen" != xno; then + enable_dlopen=yes + else + enable_dlopen=no + fi + + case $lt_cv_dlopen in + dlopen) + save_CPPFLAGS="$CPPFLAGS" + test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" + + save_LDFLAGS="$LDFLAGS" + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" + + save_LIBS="$LIBS" + LIBS="$lt_cv_dlopen_libs $LIBS" + + { echo "$as_me:$LINENO: checking whether a program can dlopen itself" >&5 +echo $ECHO_N "checking whether a program can dlopen itself... $ECHO_C" >&6; } +if test "${lt_cv_dlopen_self+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test "$cross_compiling" = yes; then : + lt_cv_dlopen_self=cross +else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext < +#endif + +#include + +#ifdef RTLD_GLOBAL +# define LT_DLGLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LT_DLGLOBAL DL_GLOBAL +# else +# define LT_DLGLOBAL 0 +# endif +#endif + +/* We may have to define LT_DLLAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LT_DLLAZY_OR_NOW +# ifdef RTLD_LAZY +# define LT_DLLAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LT_DLLAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LT_DLLAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LT_DLLAZY_OR_NOW DL_NOW +# else +# define LT_DLLAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +#ifdef __cplusplus +extern "C" void exit (int); +#endif + +void fnord() { int i=42;} +int main () +{ + void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); + int status = $lt_dlunknown; + + if (self) + { + if (dlsym (self,"fnord")) status = $lt_dlno_uscore; + else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + /* dlclose (self); */ + } + else + puts (dlerror ()); + + exit (status); +} +EOF + if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && test -s conftest${ac_exeext} 2>/dev/null; then + (./conftest; exit; ) >&5 2>/dev/null + lt_status=$? + case x$lt_status in + x$lt_dlno_uscore) lt_cv_dlopen_self=yes ;; + x$lt_dlneed_uscore) lt_cv_dlopen_self=yes ;; + x$lt_dlunknown|x*) lt_cv_dlopen_self=no ;; + esac + else : + # compilation failed + lt_cv_dlopen_self=no + fi +fi +rm -fr conftest* + + +fi +{ echo "$as_me:$LINENO: result: $lt_cv_dlopen_self" >&5 +echo "${ECHO_T}$lt_cv_dlopen_self" >&6; } + + if test "x$lt_cv_dlopen_self" = xyes; then + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" + { echo "$as_me:$LINENO: checking whether a statically linked program can dlopen itself" >&5 +echo $ECHO_N "checking whether a statically linked program can dlopen itself... $ECHO_C" >&6; } +if test "${lt_cv_dlopen_self_static+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test "$cross_compiling" = yes; then : + lt_cv_dlopen_self_static=cross +else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext < +#endif + +#include + +#ifdef RTLD_GLOBAL +# define LT_DLGLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LT_DLGLOBAL DL_GLOBAL +# else +# define LT_DLGLOBAL 0 +# endif +#endif + +/* We may have to define LT_DLLAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LT_DLLAZY_OR_NOW +# ifdef RTLD_LAZY +# define LT_DLLAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LT_DLLAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LT_DLLAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LT_DLLAZY_OR_NOW DL_NOW +# else +# define LT_DLLAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +#ifdef __cplusplus +extern "C" void exit (int); +#endif + +void fnord() { int i=42;} +int main () +{ + void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); + int status = $lt_dlunknown; + + if (self) + { + if (dlsym (self,"fnord")) status = $lt_dlno_uscore; + else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + /* dlclose (self); */ + } + else + puts (dlerror ()); + + exit (status); +} +EOF + if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && test -s conftest${ac_exeext} 2>/dev/null; then + (./conftest; exit; ) >&5 2>/dev/null + lt_status=$? + case x$lt_status in + x$lt_dlno_uscore) lt_cv_dlopen_self_static=yes ;; + x$lt_dlneed_uscore) lt_cv_dlopen_self_static=yes ;; + x$lt_dlunknown|x*) lt_cv_dlopen_self_static=no ;; + esac + else : + # compilation failed + lt_cv_dlopen_self_static=no + fi +fi +rm -fr conftest* + + +fi +{ echo "$as_me:$LINENO: result: $lt_cv_dlopen_self_static" >&5 +echo "${ECHO_T}$lt_cv_dlopen_self_static" >&6; } + fi + + CPPFLAGS="$save_CPPFLAGS" + LDFLAGS="$save_LDFLAGS" + LIBS="$save_LIBS" + ;; + esac + + case $lt_cv_dlopen_self in + yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; + *) enable_dlopen_self=unknown ;; + esac + + case $lt_cv_dlopen_self_static in + yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; + *) enable_dlopen_self_static=unknown ;; + esac +fi + + +# Report which library types will actually be built +{ echo "$as_me:$LINENO: checking if libtool supports shared libraries" >&5 +echo $ECHO_N "checking if libtool supports shared libraries... $ECHO_C" >&6; } +{ echo "$as_me:$LINENO: result: $can_build_shared" >&5 +echo "${ECHO_T}$can_build_shared" >&6; } + +{ echo "$as_me:$LINENO: checking whether to build shared libraries" >&5 +echo $ECHO_N "checking whether to build shared libraries... $ECHO_C" >&6; } +test "$can_build_shared" = "no" && enable_shared=no + +# On AIX, shared libraries and static libraries use the same namespace, and +# are all built from PIC. +case $host_os in +aix3*) + test "$enable_shared" = yes && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + +aix4* | aix5*) + if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then + test "$enable_shared" = yes && enable_static=no + fi + ;; +esac +{ echo "$as_me:$LINENO: result: $enable_shared" >&5 +echo "${ECHO_T}$enable_shared" >&6; } + +{ echo "$as_me:$LINENO: checking whether to build static libraries" >&5 +echo $ECHO_N "checking whether to build static libraries... $ECHO_C" >&6; } +# Make sure either enable_shared or enable_static is yes. +test "$enable_shared" = yes || enable_static=yes +{ echo "$as_me:$LINENO: result: $enable_static" >&5 +echo "${ECHO_T}$enable_static" >&6; } + +# The else clause should only fire when bootstrapping the +# libtool distribution, otherwise you forgot to ship ltmain.sh +# with your package, and you will get complaints that there are +# no rules to generate ltmain.sh. +if test -f "$ltmain"; then + # See if we are running on zsh, and set the options which allow our commands through + # without removal of \ escapes. + if test -n "${ZSH_VERSION+set}" ; then + setopt NO_GLOB_SUBST + fi + # Now quote all the things that may contain metacharacters while being + # careful not to overquote the AC_SUBSTed values. We take copies of the + # variables and quote the copies for generation of the libtool script. + for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC LTCFLAGS NM \ + SED SHELL STRIP \ + libname_spec library_names_spec soname_spec extract_expsyms_cmds \ + old_striplib striplib file_magic_cmd finish_cmds finish_eval \ + deplibs_check_method reload_flag reload_cmds need_locks \ + lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \ + lt_cv_sys_global_symbol_to_c_name_address \ + sys_lib_search_path_spec sys_lib_dlsearch_path_spec \ + old_postinstall_cmds old_postuninstall_cmds \ + compiler \ + CC \ + LD \ + lt_prog_compiler_wl \ + lt_prog_compiler_pic \ + lt_prog_compiler_static \ + lt_prog_compiler_no_builtin_flag \ + export_dynamic_flag_spec \ + thread_safe_flag_spec \ + whole_archive_flag_spec \ + enable_shared_with_static_runtimes \ + old_archive_cmds \ + old_archive_from_new_cmds \ + predep_objects \ + postdep_objects \ + predeps \ + postdeps \ + compiler_lib_search_path \ + archive_cmds \ + archive_expsym_cmds \ + postinstall_cmds \ + postuninstall_cmds \ + old_archive_from_expsyms_cmds \ + allow_undefined_flag \ + no_undefined_flag \ + export_symbols_cmds \ + hardcode_libdir_flag_spec \ + hardcode_libdir_flag_spec_ld \ + hardcode_libdir_separator \ + hardcode_automatic \ + module_cmds \ + module_expsym_cmds \ + lt_cv_prog_compiler_c_o \ + exclude_expsyms \ + include_expsyms; do + + case $var in + old_archive_cmds | \ + old_archive_from_new_cmds | \ + archive_cmds | \ + archive_expsym_cmds | \ + module_cmds | \ + module_expsym_cmds | \ + old_archive_from_expsyms_cmds | \ + export_symbols_cmds | \ + extract_expsyms_cmds | reload_cmds | finish_cmds | \ + postinstall_cmds | postuninstall_cmds | \ + old_postinstall_cmds | old_postuninstall_cmds | \ + sys_lib_search_path_spec | sys_lib_dlsearch_path_spec) + # Double-quote double-evaled strings. + eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\"" + ;; + *) + eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\"" + ;; + esac + done + + case $lt_echo in + *'\$0 --fallback-echo"') + lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'` + ;; + esac + +cfgfile="${ofile}T" + trap "$rm \"$cfgfile\"; exit 1" 1 2 15 + $rm -f "$cfgfile" + { echo "$as_me:$LINENO: creating $ofile" >&5 +echo "$as_me: creating $ofile" >&6;} + + cat <<__EOF__ >> "$cfgfile" +#! $SHELL + +# `$echo "$cfgfile" | sed 's%^.*/%%'` - Provide generalized library-building support services. +# Generated automatically by $PROGRAM (GNU $PACKAGE $VERSION$TIMESTAMP) +# NOTE: Changes made to this file will be lost: look at ltmain.sh. +# +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001 +# Free Software Foundation, Inc. +# +# This file is part of GNU Libtool: +# Originally by Gordon Matzigkeit , 1996 +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# A sed program that does not truncate output. +SED=$lt_SED + +# Sed that helps us avoid accidentally triggering echo(1) options like -n. +Xsed="$SED -e 1s/^X//" + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +# The names of the tagged configurations supported by this script. +available_tags= + +# ### BEGIN LIBTOOL CONFIG + +# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: + +# Shell to use when invoking shell scripts. +SHELL=$lt_SHELL + +# Whether or not to build shared libraries. +build_libtool_libs=$enable_shared + +# Whether or not to build static libraries. +build_old_libs=$enable_static + +# Whether or not to add -lc for building shared libraries. +build_libtool_need_lc=$archive_cmds_need_lc + +# Whether or not to disallow shared libs when runtime libs are static +allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes + +# Whether or not to optimize for fast installation. +fast_install=$enable_fast_install + +# The host system. +host_alias=$host_alias +host=$host +host_os=$host_os + +# The build system. +build_alias=$build_alias +build=$build +build_os=$build_os + +# An echo program that does not interpret backslashes. +echo=$lt_echo + +# The archiver. +AR=$lt_AR +AR_FLAGS=$lt_AR_FLAGS + +# A C compiler. +LTCC=$lt_LTCC + +# LTCC compiler flags. +LTCFLAGS=$lt_LTCFLAGS + +# A language-specific compiler. +CC=$lt_compiler + +# Is the compiler the GNU C compiler? +with_gcc=$GCC + +# An ERE matcher. +EGREP=$lt_EGREP + +# The linker used to build libraries. +LD=$lt_LD + +# Whether we need hard or soft links. +LN_S=$lt_LN_S + +# A BSD-compatible nm program. +NM=$lt_NM + +# A symbol stripping program +STRIP=$lt_STRIP + +# Used to examine libraries when file_magic_cmd begins "file" +MAGIC_CMD=$MAGIC_CMD + +# Used on cygwin: DLL creation program. +DLLTOOL="$DLLTOOL" + +# Used on cygwin: object dumper. +OBJDUMP="$OBJDUMP" + +# Used on cygwin: assembler. +AS="$AS" + +# The name of the directory that contains temporary libtool files. +objdir=$objdir + +# How to create reloadable object files. +reload_flag=$lt_reload_flag +reload_cmds=$lt_reload_cmds + +# How to pass a linker flag through the compiler. +wl=$lt_lt_prog_compiler_wl + +# Object file suffix (normally "o"). +objext="$ac_objext" + +# Old archive suffix (normally "a"). +libext="$libext" + +# Shared library suffix (normally ".so"). +shrext_cmds='$shrext_cmds' + +# Executable file suffix (normally ""). +exeext="$exeext" + +# Additional compiler flags for building library objects. +pic_flag=$lt_lt_prog_compiler_pic +pic_mode=$pic_mode + +# What is the maximum length of a command? +max_cmd_len=$lt_cv_sys_max_cmd_len + +# Does compiler simultaneously support -c and -o options? +compiler_c_o=$lt_lt_cv_prog_compiler_c_o + +# Must we lock files when doing compilation? +need_locks=$lt_need_locks + +# Do we need the lib prefix for modules? +need_lib_prefix=$need_lib_prefix + +# Do we need a version for libraries? +need_version=$need_version + +# Whether dlopen is supported. +dlopen_support=$enable_dlopen + +# Whether dlopen of programs is supported. +dlopen_self=$enable_dlopen_self + +# Whether dlopen of statically linked programs is supported. +dlopen_self_static=$enable_dlopen_self_static + +# Compiler flag to prevent dynamic linking. +link_static_flag=$lt_lt_prog_compiler_static + +# Compiler flag to turn off builtin functions. +no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag + +# Compiler flag to allow reflexive dlopens. +export_dynamic_flag_spec=$lt_export_dynamic_flag_spec + +# Compiler flag to generate shared objects directly from archives. +whole_archive_flag_spec=$lt_whole_archive_flag_spec + +# Compiler flag to generate thread-safe objects. +thread_safe_flag_spec=$lt_thread_safe_flag_spec + +# Library versioning type. +version_type=$version_type + +# Format of library name prefix. +libname_spec=$lt_libname_spec + +# List of archive names. First name is the real one, the rest are links. +# The last name is the one that the linker finds with -lNAME. +library_names_spec=$lt_library_names_spec + +# The coded name of the library, if different from the real name. +soname_spec=$lt_soname_spec + +# Commands used to build and install an old-style archive. +RANLIB=$lt_RANLIB +old_archive_cmds=$lt_old_archive_cmds +old_postinstall_cmds=$lt_old_postinstall_cmds +old_postuninstall_cmds=$lt_old_postuninstall_cmds + +# Create an old-style archive from a shared archive. +old_archive_from_new_cmds=$lt_old_archive_from_new_cmds + +# Create a temporary old-style archive to link instead of a shared archive. +old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds + +# Commands used to build and install a shared archive. +archive_cmds=$lt_archive_cmds +archive_expsym_cmds=$lt_archive_expsym_cmds +postinstall_cmds=$lt_postinstall_cmds +postuninstall_cmds=$lt_postuninstall_cmds + +# Commands used to build a loadable module (assumed same as above if empty) +module_cmds=$lt_module_cmds +module_expsym_cmds=$lt_module_expsym_cmds + +# Commands to strip libraries. +old_striplib=$lt_old_striplib +striplib=$lt_striplib + +# Dependencies to place before the objects being linked to create a +# shared library. +predep_objects=$lt_predep_objects + +# Dependencies to place after the objects being linked to create a +# shared library. +postdep_objects=$lt_postdep_objects + +# Dependencies to place before the objects being linked to create a +# shared library. +predeps=$lt_predeps + +# Dependencies to place after the objects being linked to create a +# shared library. +postdeps=$lt_postdeps + +# The library search path used internally by the compiler when linking +# a shared library. +compiler_lib_search_path=$lt_compiler_lib_search_path + +# Method to check whether dependent libraries are shared objects. +deplibs_check_method=$lt_deplibs_check_method + +# Command to use when deplibs_check_method == file_magic. +file_magic_cmd=$lt_file_magic_cmd + +# Flag that allows shared libraries with undefined symbols to be built. +allow_undefined_flag=$lt_allow_undefined_flag + +# Flag that forces no undefined symbols. +no_undefined_flag=$lt_no_undefined_flag + +# Commands used to finish a libtool library installation in a directory. +finish_cmds=$lt_finish_cmds + +# Same as above, but a single script fragment to be evaled but not shown. +finish_eval=$lt_finish_eval + +# Take the output of nm and produce a listing of raw symbols and C names. +global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe + +# Transform the output of nm in a proper C declaration +global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl + +# Transform the output of nm in a C name address pair +global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address + +# This is the shared library runtime path variable. +runpath_var=$runpath_var + +# This is the shared library path variable. +shlibpath_var=$shlibpath_var + +# Is shlibpath searched before the hard-coded library search path? +shlibpath_overrides_runpath=$shlibpath_overrides_runpath + +# How to hardcode a shared library path into an executable. +hardcode_action=$hardcode_action + +# Whether we should hardcode library paths into libraries. +hardcode_into_libs=$hardcode_into_libs + +# Flag to hardcode \$libdir into a binary during linking. +# This must work even if \$libdir does not exist. +hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec + +# If ld is used when linking, flag to hardcode \$libdir into +# a binary during linking. This must work even if \$libdir does +# not exist. +hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld + +# Whether we need a single -rpath flag with a separated argument. +hardcode_libdir_separator=$lt_hardcode_libdir_separator + +# Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the +# resulting binary. +hardcode_direct=$hardcode_direct + +# Set to yes if using the -LDIR flag during linking hardcodes DIR into the +# resulting binary. +hardcode_minus_L=$hardcode_minus_L + +# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into +# the resulting binary. +hardcode_shlibpath_var=$hardcode_shlibpath_var + +# Set to yes if building a shared library automatically hardcodes DIR into the library +# and all subsequent libraries and executables linked against it. +hardcode_automatic=$hardcode_automatic + +# Variables whose values should be saved in libtool wrapper scripts and +# restored at relink time. +variables_saved_for_relink="$variables_saved_for_relink" + +# Whether libtool must link a program against all its dependency libraries. +link_all_deplibs=$link_all_deplibs + +# Compile-time system search path for libraries +sys_lib_search_path_spec=$lt_sys_lib_search_path_spec + +# Run-time system search path for libraries +sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec + +# Fix the shell variable \$srcfile for the compiler. +fix_srcfile_path="$fix_srcfile_path" + +# Set to yes if exported symbols are required. +always_export_symbols=$always_export_symbols + +# The commands to list exported symbols. +export_symbols_cmds=$lt_export_symbols_cmds + +# The commands to extract the exported symbol list from a shared archive. +extract_expsyms_cmds=$lt_extract_expsyms_cmds + +# Symbols that should not be listed in the preloaded symbols. +exclude_expsyms=$lt_exclude_expsyms + +# Symbols that must always be exported. +include_expsyms=$lt_include_expsyms + +# ### END LIBTOOL CONFIG + +__EOF__ + + + case $host_os in + aix3*) + cat <<\EOF >> "$cfgfile" + +# AIX sometimes has problems with the GCC collect2 program. For some +# reason, if we set the COLLECT_NAMES environment variable, the problems +# vanish in a puff of smoke. +if test "X${COLLECT_NAMES+set}" != Xset; then + COLLECT_NAMES= + export COLLECT_NAMES +fi +EOF + ;; + esac + + # We use sed instead of cat because bash on DJGPP gets confused if + # if finds mixed CR/LF and LF-only lines. Since sed operates in + # text mode, it properly converts lines to CR/LF. This bash problem + # is reportedly fixed, but why not run on old versions too? + sed '$q' "$ltmain" >> "$cfgfile" || (rm -f "$cfgfile"; exit 1) + + mv -f "$cfgfile" "$ofile" || \ + (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") + chmod +x "$ofile" + +else + # If there is no Makefile yet, we rely on a make rule to execute + # `config.status --recheck' to rerun these tests and create the + # libtool script then. + ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'` + if test -f "$ltmain_in"; then + test -f Makefile && make "$ltmain" + fi +fi + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +CC="$lt_save_CC" + + +# Check whether --with-tags was given. +if test "${with_tags+set}" = set; then + withval=$with_tags; tagnames="$withval" +fi + + +if test -f "$ltmain" && test -n "$tagnames"; then + if test ! -f "${ofile}"; then + { echo "$as_me:$LINENO: WARNING: output file \`$ofile' does not exist" >&5 +echo "$as_me: WARNING: output file \`$ofile' does not exist" >&2;} + fi + + if test -z "$LTCC"; then + eval "`$SHELL ${ofile} --config | grep '^LTCC='`" + if test -z "$LTCC"; then + { echo "$as_me:$LINENO: WARNING: output file \`$ofile' does not look like a libtool script" >&5 +echo "$as_me: WARNING: output file \`$ofile' does not look like a libtool script" >&2;} + else + { echo "$as_me:$LINENO: WARNING: using \`LTCC=$LTCC', extracted from \`$ofile'" >&5 +echo "$as_me: WARNING: using \`LTCC=$LTCC', extracted from \`$ofile'" >&2;} + fi + fi + if test -z "$LTCFLAGS"; then + eval "`$SHELL ${ofile} --config | grep '^LTCFLAGS='`" + fi + + # Extract list of available tagged configurations in $ofile. + # Note that this assumes the entire list is on one line. + available_tags=`grep "^available_tags=" "${ofile}" | $SED -e 's/available_tags=\(.*$\)/\1/' -e 's/\"//g'` + + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for tagname in $tagnames; do + IFS="$lt_save_ifs" + # Check whether tagname contains only valid characters + case `$echo "X$tagname" | $Xsed -e 's:[-_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890,/]::g'` in + "") ;; + *) { { echo "$as_me:$LINENO: error: invalid tag name: $tagname" >&5 +echo "$as_me: error: invalid tag name: $tagname" >&2;} + { (exit 1); exit 1; }; } + ;; + esac + + if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$" < "${ofile}" > /dev/null + then + { { echo "$as_me:$LINENO: error: tag name \"$tagname\" already exists" >&5 +echo "$as_me: error: tag name \"$tagname\" already exists" >&2;} + { (exit 1); exit 1; }; } + fi + + # Update the list of available tags. + if test -n "$tagname"; then + echo appending configuration tag \"$tagname\" to $ofile + + case $tagname in + CXX) + if test -n "$CXX" && ( test "X$CXX" != "Xno" && + ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) || + (test "X$CXX" != "Xg++"))) ; then + ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + + + +archive_cmds_need_lc_CXX=no +allow_undefined_flag_CXX= +always_export_symbols_CXX=no +archive_expsym_cmds_CXX= +export_dynamic_flag_spec_CXX= +hardcode_direct_CXX=no +hardcode_libdir_flag_spec_CXX= +hardcode_libdir_flag_spec_ld_CXX= +hardcode_libdir_separator_CXX= +hardcode_minus_L_CXX=no +hardcode_shlibpath_var_CXX=unsupported +hardcode_automatic_CXX=no +module_cmds_CXX= +module_expsym_cmds_CXX= +link_all_deplibs_CXX=unknown +old_archive_cmds_CXX=$old_archive_cmds +no_undefined_flag_CXX= +whole_archive_flag_spec_CXX= +enable_shared_with_static_runtimes_CXX=no + +# Dependencies to place before and after the object being linked: +predep_objects_CXX= +postdep_objects_CXX= +predeps_CXX= +postdeps_CXX= +compiler_lib_search_path_CXX= + +# Source file extension for C++ test sources. +ac_ext=cpp + +# Object file extension for compiled C++ test sources. +objext=o +objext_CXX=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="int some_variable = 0;\n" + +# Code to be used in simple link tests +lt_simple_link_test_code='int main(int, char *[]) { return(0); }\n' + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC + + +# save warnings/boilerplate of simple test code +ac_outfile=conftest.$ac_objext +printf "$lt_simple_compile_test_code" >conftest.$ac_ext +eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_compiler_boilerplate=`cat conftest.err` +$rm conftest* + +ac_outfile=conftest.$ac_objext +printf "$lt_simple_link_test_code" >conftest.$ac_ext +eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_linker_boilerplate=`cat conftest.err` +$rm conftest* + + +# Allow CC to be a program name with arguments. +lt_save_CC=$CC +lt_save_LD=$LD +lt_save_GCC=$GCC +GCC=$GXX +lt_save_with_gnu_ld=$with_gnu_ld +lt_save_path_LD=$lt_cv_path_LD +if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then + lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx +else + $as_unset lt_cv_prog_gnu_ld +fi +if test -n "${lt_cv_path_LDCXX+set}"; then + lt_cv_path_LD=$lt_cv_path_LDCXX +else + $as_unset lt_cv_path_LD +fi +test -z "${LDCXX+set}" || LD=$LDCXX +CC=${CXX-"c++"} +compiler=$CC +compiler_CXX=$CC +for cc_temp in $compiler""; do + case $cc_temp in + compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; + distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; + \-*) ;; + *) break;; + esac +done +cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` + + +# We don't want -fno-exception wen compiling C++ code, so set the +# no_builtin_flag separately +if test "$GXX" = yes; then + lt_prog_compiler_no_builtin_flag_CXX=' -fno-builtin' +else + lt_prog_compiler_no_builtin_flag_CXX= +fi + +if test "$GXX" = yes; then + # Set up default GNU C++ configuration + + +# Check whether --with-gnu-ld was given. +if test "${with_gnu_ld+set}" = set; then + withval=$with_gnu_ld; test "$withval" = no || with_gnu_ld=yes +else + with_gnu_ld=no +fi + +ac_prog=ld +if test "$GCC" = yes; then + # Check if gcc -print-prog-name=ld gives a path. + { echo "$as_me:$LINENO: checking for ld used by $CC" >&5 +echo $ECHO_N "checking for ld used by $CC... $ECHO_C" >&6; } + case $host in + *-*-mingw*) + # gcc leaves a trailing carriage return which upsets mingw + ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; + *) + ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; + esac + case $ac_prog in + # Accept absolute paths. + [\\/]* | ?:[\\/]*) + re_direlt='/[^/][^/]*/\.\./' + # Canonicalize the pathname of ld + ac_prog=`echo $ac_prog| $SED 's%\\\\%/%g'` + while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do + ac_prog=`echo $ac_prog| $SED "s%$re_direlt%/%"` + done + test -z "$LD" && LD="$ac_prog" + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test "$with_gnu_ld" = yes; then + { echo "$as_me:$LINENO: checking for GNU ld" >&5 +echo $ECHO_N "checking for GNU ld... $ECHO_C" >&6; } +else + { echo "$as_me:$LINENO: checking for non-GNU ld" >&5 +echo $ECHO_N "checking for non-GNU ld... $ECHO_C" >&6; } +fi +if test "${lt_cv_path_LD+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -z "$LD"; then + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then + lt_cv_path_LD="$ac_dir/$ac_prog" + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some variants of GNU ld only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + case `"$lt_cv_path_LD" -v 2>&1 &5 +echo "${ECHO_T}$LD" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi +test -z "$LD" && { { echo "$as_me:$LINENO: error: no acceptable ld found in \$PATH" >&5 +echo "$as_me: error: no acceptable ld found in \$PATH" >&2;} + { (exit 1); exit 1; }; } +{ echo "$as_me:$LINENO: checking if the linker ($LD) is GNU ld" >&5 +echo $ECHO_N "checking if the linker ($LD) is GNU ld... $ECHO_C" >&6; } +if test "${lt_cv_prog_gnu_ld+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + # I'd rather use --version here, but apparently some GNU lds only accept -v. +case `$LD -v 2>&1 &5 +echo "${ECHO_T}$lt_cv_prog_gnu_ld" >&6; } +with_gnu_ld=$lt_cv_prog_gnu_ld + + + + # Check if GNU C++ uses GNU ld as the underlying linker, since the + # archiving commands below assume that GNU ld is being used. + if test "$with_gnu_ld" = yes; then + archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + + hardcode_libdir_flag_spec_CXX='${wl}--rpath ${wl}$libdir' + export_dynamic_flag_spec_CXX='${wl}--export-dynamic' + + # If archive_cmds runs LD, not CC, wlarc should be empty + # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to + # investigate it a little bit more. (MM) + wlarc='${wl}' + + # ancient GNU ld didn't support --whole-archive et. al. + if eval "`$CC -print-prog-name=ld` --help 2>&1" | \ + grep 'no-whole-archive' > /dev/null; then + whole_archive_flag_spec_CXX="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + else + whole_archive_flag_spec_CXX= + fi + else + with_gnu_ld=no + wlarc= + + # A generic and very simple default shared library creation + # command for GNU C++ for the case where it uses the native + # linker, instead of GNU ld. If possible, this setting should + # overridden to take advantage of the native linker features on + # the platform it is being used on. + archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' + fi + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"' + +else + GXX=no + with_gnu_ld=no + wlarc= +fi + +# PORTME: fill in a description of your system's C++ link characteristics +{ echo "$as_me:$LINENO: checking whether the $compiler linker ($LD) supports shared libraries" >&5 +echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared libraries... $ECHO_C" >&6; } +ld_shlibs_CXX=yes +case $host_os in + aix3*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + aix4* | aix5*) + if test "$host_cpu" = ia64; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag="" + else + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # need to do runtime linking. + case $host_os in aix4.[23]|aix4.[23].*|aix5*) + for ld_flag in $LDFLAGS; do + case $ld_flag in + *-brtl*) + aix_use_runtimelinking=yes + break + ;; + esac + done + ;; + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + archive_cmds_CXX='' + hardcode_direct_CXX=yes + hardcode_libdir_separator_CXX=':' + link_all_deplibs_CXX=yes + + if test "$GXX" = yes; then + case $host_os in aix4.[012]|aix4.[012].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`${CC} -print-prog-name=collect2` + if test -f "$collect2name" && \ + strings "$collect2name" | grep resolve_lib_name >/dev/null + then + # We have reworked collect2 + hardcode_direct_CXX=yes + else + # We have old collect2 + hardcode_direct_CXX=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + hardcode_minus_L_CXX=yes + hardcode_libdir_flag_spec_CXX='-L$libdir' + hardcode_libdir_separator_CXX= + fi + ;; + esac + shared_flag='-shared' + if test "$aix_use_runtimelinking" = yes; then + shared_flag="$shared_flag "'${wl}-G' + fi + else + # not using gcc + if test "$host_cpu" = ia64; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test "$aix_use_runtimelinking" = yes; then + shared_flag='${wl}-G' + else + shared_flag='${wl}-bM:SRE' + fi + fi + fi + + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to export. + always_export_symbols_CXX=yes + if test "$aix_use_runtimelinking" = yes; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + allow_undefined_flag_CXX='-berok' + # Determine the default libpath from the value encoded in an empty executable. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + +aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'` +# Check for a 64-bit object if we didn't find anything. +if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'`; fi +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi + + hardcode_libdir_flag_spec_CXX='${wl}-blibpath:$libdir:'"$aix_libpath" + + archive_expsym_cmds_CXX="\$CC"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" + else + if test "$host_cpu" = ia64; then + hardcode_libdir_flag_spec_CXX='${wl}-R $libdir:/usr/lib:/lib' + allow_undefined_flag_CXX="-z nodefs" + archive_expsym_cmds_CXX="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an empty executable. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + +aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'` +# Check for a 64-bit object if we didn't find anything. +if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'`; fi +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi + + hardcode_libdir_flag_spec_CXX='${wl}-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + no_undefined_flag_CXX=' ${wl}-bernotok' + allow_undefined_flag_CXX=' ${wl}-berok' + # Exported symbols can be pulled into shared objects from archives + whole_archive_flag_spec_CXX='$convenience' + archive_cmds_need_lc_CXX=yes + # This is similar to how AIX traditionally builds its shared libraries. + archive_expsym_cmds_CXX="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' + fi + fi + ;; + + beos*) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + allow_undefined_flag_CXX=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + archive_cmds_CXX='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + else + ld_shlibs_CXX=no + fi + ;; + + chorus*) + case $cc_basename in + *) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + esac + ;; + + cygwin* | mingw* | pw32*) + # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, CXX) is actually meaningless, + # as there is no search path for DLLs. + hardcode_libdir_flag_spec_CXX='-L$libdir' + allow_undefined_flag_CXX=unsupported + always_export_symbols_CXX=no + enable_shared_with_static_runtimes_CXX=yes + + if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then + archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file (1st line + # is EXPORTS), use it as is; otherwise, prepend... + archive_expsym_cmds_CXX='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + ld_shlibs_CXX=no + fi + ;; + darwin* | rhapsody*) + case $host_os in + rhapsody* | darwin1.[012]) + allow_undefined_flag_CXX='${wl}-undefined ${wl}suppress' + ;; + *) # Darwin 1.3 on + if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then + allow_undefined_flag_CXX='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' + else + case ${MACOSX_DEPLOYMENT_TARGET} in + 10.[012]) + allow_undefined_flag_CXX='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' + ;; + 10.*) + allow_undefined_flag_CXX='${wl}-undefined ${wl}dynamic_lookup' + ;; + esac + fi + ;; + esac + archive_cmds_need_lc_CXX=no + hardcode_direct_CXX=no + hardcode_automatic_CXX=yes + hardcode_shlibpath_var_CXX=unsupported + whole_archive_flag_spec_CXX='' + link_all_deplibs_CXX=yes + + if test "$GXX" = yes ; then + lt_int_apple_cc_single_mod=no + output_verbose_link_cmd='echo' + if $CC -dumpspecs 2>&1 | $EGREP 'single_module' >/dev/null ; then + lt_int_apple_cc_single_mod=yes + fi + if test "X$lt_int_apple_cc_single_mod" = Xyes ; then + archive_cmds_CXX='$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring' + else + archive_cmds_CXX='$CC -r -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring' + fi + module_cmds_CXX='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' + # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds + if test "X$lt_int_apple_cc_single_mod" = Xyes ; then + archive_expsym_cmds_CXX='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + else + archive_expsym_cmds_CXX='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -r -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + fi + module_expsym_cmds_CXX='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + else + case $cc_basename in + xlc*) + output_verbose_link_cmd='echo' + archive_cmds_CXX='$CC -qmkshrobj ${wl}-single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $verstring' + module_cmds_CXX='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' + # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds + archive_expsym_cmds_CXX='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj ${wl}-single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + module_expsym_cmds_CXX='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + ;; + *) + ld_shlibs_CXX=no + ;; + esac + fi + ;; + + dgux*) + case $cc_basename in + ec++*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + ghcx*) + # Green Hills C++ Compiler + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + *) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + esac + ;; + freebsd[12]*) + # C++ shared libraries reported to be fairly broken before switch to ELF + ld_shlibs_CXX=no + ;; + freebsd-elf*) + archive_cmds_need_lc_CXX=no + ;; + freebsd* | kfreebsd*-gnu | dragonfly*) + # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF + # conventions + ld_shlibs_CXX=yes + ;; + gnu*) + ;; + hpux9*) + hardcode_libdir_flag_spec_CXX='${wl}+b ${wl}$libdir' + hardcode_libdir_separator_CXX=: + export_dynamic_flag_spec_CXX='${wl}-E' + hardcode_direct_CXX=yes + hardcode_minus_L_CXX=yes # Not in the search PATH, + # but as the default + # location of the library. + + case $cc_basename in + CC*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + aCC*) + archive_cmds_CXX='$rm $output_objdir/$soname~$CC -b ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | grep "[-]L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + ;; + *) + if test "$GXX" = yes; then + archive_cmds_CXX='$rm $output_objdir/$soname~$CC -shared -nostdlib -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + else + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + fi + ;; + esac + ;; + hpux10*|hpux11*) + if test $with_gnu_ld = no; then + hardcode_libdir_flag_spec_CXX='${wl}+b ${wl}$libdir' + hardcode_libdir_separator_CXX=: + + case $host_cpu in + hppa*64*|ia64*) + hardcode_libdir_flag_spec_ld_CXX='+b $libdir' + ;; + *) + export_dynamic_flag_spec_CXX='${wl}-E' + ;; + esac + fi + case $host_cpu in + hppa*64*|ia64*) + hardcode_direct_CXX=no + hardcode_shlibpath_var_CXX=no + ;; + *) + hardcode_direct_CXX=yes + hardcode_minus_L_CXX=yes # Not in the search PATH, + # but as the default + # location of the library. + ;; + esac + + case $cc_basename in + CC*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + aCC*) + case $host_cpu in + hppa*64*) + archive_cmds_CXX='$CC -b ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + ia64*) + archive_cmds_CXX='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + *) + archive_cmds_CXX='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + esac + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | grep "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + ;; + *) + if test "$GXX" = yes; then + if test $with_gnu_ld = no; then + case $host_cpu in + hppa*64*) + archive_cmds_CXX='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + ia64*) + archive_cmds_CXX='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + *) + archive_cmds_CXX='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + esac + fi + else + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + fi + ;; + esac + ;; + interix3*) + hardcode_direct_CXX=no + hardcode_shlibpath_var_CXX=no + hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' + export_dynamic_flag_spec_CXX='${wl}-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + archive_cmds_CXX='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + archive_expsym_cmds_CXX='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + irix5* | irix6*) + case $cc_basename in + CC*) + # SGI C++ + archive_cmds_CXX='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + + # Archives containing C++ object files must be created using + # "CC -ar", where "CC" is the IRIX C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + old_archive_cmds_CXX='$CC -ar -WR,-u -o $oldlib $oldobjs' + ;; + *) + if test "$GXX" = yes; then + if test "$with_gnu_ld" = no; then + archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` -o $lib' + fi + fi + link_all_deplibs_CXX=yes + ;; + esac + hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator_CXX=: + ;; + linux*) + case $cc_basename in + KCC*) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + archive_expsym_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib ${wl}-retain-symbols-file,$export_symbols; mv \$templib $lib' + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | grep "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + + hardcode_libdir_flag_spec_CXX='${wl}--rpath,$libdir' + export_dynamic_flag_spec_CXX='${wl}--export-dynamic' + + # Archives containing C++ object files must be created using + # "CC -Bstatic", where "CC" is the KAI C++ compiler. + old_archive_cmds_CXX='$CC -Bstatic -o $oldlib $oldobjs' + ;; + icpc*) + # Intel C++ + with_gnu_ld=yes + # version 8.0 and above of icpc choke on multiply defined symbols + # if we add $predep_objects and $postdep_objects, however 7.1 and + # earlier do not add the objects themselves. + case `$CC -V 2>&1` in + *"Version 7."*) + archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + ;; + *) # Version 8.0 or newer + tmp_idyn= + case $host_cpu in + ia64*) tmp_idyn=' -i_dynamic';; + esac + archive_cmds_CXX='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds_CXX='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + ;; + esac + archive_cmds_need_lc_CXX=no + hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' + export_dynamic_flag_spec_CXX='${wl}--export-dynamic' + whole_archive_flag_spec_CXX='${wl}--whole-archive$convenience ${wl}--no-whole-archive' + ;; + pgCC*) + # Portland Group C++ compiler + archive_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' + archive_expsym_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' + + hardcode_libdir_flag_spec_CXX='${wl}--rpath ${wl}$libdir' + export_dynamic_flag_spec_CXX='${wl}--export-dynamic' + whole_archive_flag_spec_CXX='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' + ;; + cxx*) + # Compaq C++ + archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib ${wl}-retain-symbols-file $wl$export_symbols' + + runpath_var=LD_RUN_PATH + hardcode_libdir_flag_spec_CXX='-rpath $libdir' + hardcode_libdir_separator_CXX=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + ;; + esac + ;; + lynxos*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + m88k*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + mvs*) + case $cc_basename in + cxx*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + *) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + esac + ;; + netbsd*) + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + archive_cmds_CXX='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags' + wlarc= + hardcode_libdir_flag_spec_CXX='-R$libdir' + hardcode_direct_CXX=yes + hardcode_shlibpath_var_CXX=no + fi + # Workaround some broken pre-1.5 toolchains + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"' + ;; + openbsd2*) + # C++ shared libraries are fairly broken + ld_shlibs_CXX=no + ;; + openbsd*) + hardcode_direct_CXX=yes + hardcode_shlibpath_var_CXX=no + archive_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' + hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + archive_expsym_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file,$export_symbols -o $lib' + export_dynamic_flag_spec_CXX='${wl}-E' + whole_archive_flag_spec_CXX="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + fi + output_verbose_link_cmd='echo' + ;; + osf3*) + case $cc_basename in + KCC*) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + + hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' + hardcode_libdir_separator_CXX=: + + # Archives containing C++ object files must be created using + # "CC -Bstatic", where "CC" is the KAI C++ compiler. + old_archive_cmds_CXX='$CC -Bstatic -o $oldlib $oldobjs' + + ;; + RCC*) + # Rational C++ 2.4.1 + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + cxx*) + allow_undefined_flag_CXX=' ${wl}-expect_unresolved ${wl}\*' + archive_cmds_CXX='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && echo ${wl}-set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + + hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator_CXX=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld" | grep -v "ld:"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + ;; + *) + if test "$GXX" = yes && test "$with_gnu_ld" = no; then + allow_undefined_flag_CXX=' ${wl}-expect_unresolved ${wl}\*' + archive_cmds_CXX='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + + hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator_CXX=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"' + + else + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + fi + ;; + esac + ;; + osf4* | osf5*) + case $cc_basename in + KCC*) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + + hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' + hardcode_libdir_separator_CXX=: + + # Archives containing C++ object files must be created using + # the KAI C++ compiler. + old_archive_cmds_CXX='$CC -o $oldlib $oldobjs' + ;; + RCC*) + # Rational C++ 2.4.1 + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + cxx*) + allow_undefined_flag_CXX=' -expect_unresolved \*' + archive_cmds_CXX='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + archive_expsym_cmds_CXX='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ + echo "-hidden">> $lib.exp~ + $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname -Wl,-input -Wl,$lib.exp `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib~ + $rm $lib.exp' + + hardcode_libdir_flag_spec_CXX='-rpath $libdir' + hardcode_libdir_separator_CXX=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld" | grep -v "ld:"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + ;; + *) + if test "$GXX" = yes && test "$with_gnu_ld" = no; then + allow_undefined_flag_CXX=' ${wl}-expect_unresolved ${wl}\*' + archive_cmds_CXX='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + + hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator_CXX=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"' + + else + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + fi + ;; + esac + ;; + psos*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + sunos4*) + case $cc_basename in + CC*) + # Sun C++ 4.x + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + lcc*) + # Lucid + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + *) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + esac + ;; + solaris*) + case $cc_basename in + CC*) + # Sun C++ 4.2, 5.x and Centerline C++ + archive_cmds_need_lc_CXX=yes + no_undefined_flag_CXX=' -zdefs' + archive_cmds_CXX='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + archive_expsym_cmds_CXX='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $CC -G${allow_undefined_flag} ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp' + + hardcode_libdir_flag_spec_CXX='-R$libdir' + hardcode_shlibpath_var_CXX=no + case $host_os in + solaris2.[0-5] | solaris2.[0-5].*) ;; + *) + # The C++ compiler is used as linker so we must use $wl + # flag to pass the commands to the underlying system + # linker. We must also pass each convience library through + # to the system linker between allextract/defaultextract. + # The C++ compiler will combine linker options so we + # cannot just pass the convience library names through + # without $wl. + # Supported since Solaris 2.6 (maybe 2.5.1?) + whole_archive_flag_spec_CXX='${wl}-z ${wl}allextract`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}-z ${wl}defaultextract' + ;; + esac + link_all_deplibs_CXX=yes + + output_verbose_link_cmd='echo' + + # Archives containing C++ object files must be created using + # "CC -xar", where "CC" is the Sun C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + old_archive_cmds_CXX='$CC -xar -o $oldlib $oldobjs' + ;; + gcx*) + # Green Hills C++ Compiler + archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' + + # The C++ compiler must be used to create the archive. + old_archive_cmds_CXX='$CC $LDFLAGS -archive -o $oldlib $oldobjs' + ;; + *) + # GNU C++ compiler with Solaris linker + if test "$GXX" = yes && test "$with_gnu_ld" = no; then + no_undefined_flag_CXX=' ${wl}-z ${wl}defs' + if $CC --version | grep -v '^2\.7' > /dev/null; then + archive_cmds_CXX='$CC -shared -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' + archive_expsym_cmds_CXX='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $CC -shared -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp' + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd="$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep \"\-L\"" + else + # g++ 2.7 appears to require `-G' NOT `-shared' on this + # platform. + archive_cmds_CXX='$CC -G -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' + archive_expsym_cmds_CXX='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $CC -G -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp' + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd="$CC -G $CFLAGS -v conftest.$objext 2>&1 | grep \"\-L\"" + fi + + hardcode_libdir_flag_spec_CXX='${wl}-R $wl$libdir' + fi + ;; + esac + ;; + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) + no_undefined_flag_CXX='${wl}-z,text' + archive_cmds_need_lc_CXX=no + hardcode_shlibpath_var_CXX=no + runpath_var='LD_RUN_PATH' + + case $cc_basename in + CC*) + archive_cmds_CXX='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_CXX='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + archive_cmds_CXX='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_CXX='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + sysv5* | sco3.2v5* | sco5v6*) + # Note: We can NOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + # For security reasons, it is highly recommended that you always + # use absolute paths for naming shared libraries, and exclude the + # DT_RUNPATH tag from executables and libraries. But doing so + # requires that you compile everything twice, which is a pain. + # So that behaviour is only enabled if SCOABSPATH is set to a + # non-empty value in the environment. Most likely only useful for + # creating official distributions of packages. + # This is a hack until libtool officially supports absolute path + # names for shared libraries. + no_undefined_flag_CXX='${wl}-z,text' + allow_undefined_flag_CXX='${wl}-z,nodefs' + archive_cmds_need_lc_CXX=no + hardcode_shlibpath_var_CXX=no + hardcode_libdir_flag_spec_CXX='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`' + hardcode_libdir_separator_CXX=':' + link_all_deplibs_CXX=yes + export_dynamic_flag_spec_CXX='${wl}-Bexport' + runpath_var='LD_RUN_PATH' + + case $cc_basename in + CC*) + archive_cmds_CXX='$CC -G ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_CXX='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + archive_cmds_CXX='$CC -shared ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_CXX='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + tandem*) + case $cc_basename in + NCC*) + # NonStop-UX NCC 3.20 + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + *) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + esac + ;; + vxworks*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + *) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; +esac +{ echo "$as_me:$LINENO: result: $ld_shlibs_CXX" >&5 +echo "${ECHO_T}$ld_shlibs_CXX" >&6; } +test "$ld_shlibs_CXX" = no && can_build_shared=no + +GCC_CXX="$GXX" +LD_CXX="$LD" + + +cat > conftest.$ac_ext <&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + # Parse the compiler output and extract the necessary + # objects, libraries and library flags. + + # Sentinel used to keep track of whether or not we are before + # the conftest object file. + pre_test_object_deps_done=no + + # The `*' in the case matches for architectures that use `case' in + # $output_verbose_cmd can trigger glob expansion during the loop + # eval without this substitution. + output_verbose_link_cmd=`$echo "X$output_verbose_link_cmd" | $Xsed -e "$no_glob_subst"` + + for p in `eval $output_verbose_link_cmd`; do + case $p in + + -L* | -R* | -l*) + # Some compilers place space between "-{L,R}" and the path. + # Remove the space. + if test $p = "-L" \ + || test $p = "-R"; then + prev=$p + continue + else + prev= + fi + + if test "$pre_test_object_deps_done" = no; then + case $p in + -L* | -R*) + # Internal compiler library paths should come after those + # provided the user. The postdeps already come after the + # user supplied libs so there is no need to process them. + if test -z "$compiler_lib_search_path_CXX"; then + compiler_lib_search_path_CXX="${prev}${p}" + else + compiler_lib_search_path_CXX="${compiler_lib_search_path_CXX} ${prev}${p}" + fi + ;; + # The "-l" case would never come before the object being + # linked, so don't bother handling this case. + esac + else + if test -z "$postdeps_CXX"; then + postdeps_CXX="${prev}${p}" + else + postdeps_CXX="${postdeps_CXX} ${prev}${p}" + fi + fi + ;; + + *.$objext) + # This assumes that the test object file only shows up + # once in the compiler output. + if test "$p" = "conftest.$objext"; then + pre_test_object_deps_done=yes + continue + fi + + if test "$pre_test_object_deps_done" = no; then + if test -z "$predep_objects_CXX"; then + predep_objects_CXX="$p" + else + predep_objects_CXX="$predep_objects_CXX $p" + fi + else + if test -z "$postdep_objects_CXX"; then + postdep_objects_CXX="$p" + else + postdep_objects_CXX="$postdep_objects_CXX $p" + fi + fi + ;; + + *) ;; # Ignore the rest. + + esac + done + + # Clean up. + rm -f a.out a.exe +else + echo "libtool.m4: error: problem compiling CXX test program" +fi + +$rm -f confest.$objext + +# PORTME: override above test on systems where it is broken +case $host_os in +interix3*) + # Interix 3.5 installs completely hosed .la files for C++, so rather than + # hack all around it, let's just trust "g++" to DTRT. + predep_objects_CXX= + postdep_objects_CXX= + postdeps_CXX= + ;; + +solaris*) + case $cc_basename in + CC*) + # Adding this requires a known-good setup of shared libraries for + # Sun compiler versions before 5.6, else PIC objects from an old + # archive will be linked into the output, leading to subtle bugs. + postdeps_CXX='-lCstd -lCrun' + ;; + esac + ;; +esac + + +case " $postdeps_CXX " in +*" -lc "*) archive_cmds_need_lc_CXX=no ;; +esac + +lt_prog_compiler_wl_CXX= +lt_prog_compiler_pic_CXX= +lt_prog_compiler_static_CXX= + +{ echo "$as_me:$LINENO: checking for $compiler option to produce PIC" >&5 +echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6; } + + # C++ specific cases for pic, static, wl, etc. + if test "$GXX" = yes; then + lt_prog_compiler_wl_CXX='-Wl,' + lt_prog_compiler_static_CXX='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + lt_prog_compiler_static_CXX='-Bstatic' + fi + ;; + amigaos*) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the `-m68020' flag to GCC prevents building anything better, + # like `-m68040'. + lt_prog_compiler_pic_CXX='-m68020 -resident32 -malways-restore-a4' + ;; + beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + mingw* | os2* | pw32*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + lt_prog_compiler_pic_CXX='-DDLL_EXPORT' + ;; + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + lt_prog_compiler_pic_CXX='-fno-common' + ;; + *djgpp*) + # DJGPP does not support shared libraries at all + lt_prog_compiler_pic_CXX= + ;; + interix3*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + sysv4*MP*) + if test -d /usr/nec; then + lt_prog_compiler_pic_CXX=-Kconform_pic + fi + ;; + hpux*) + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case $host_cpu in + hppa*64*|ia64*) + ;; + *) + lt_prog_compiler_pic_CXX='-fPIC' + ;; + esac + ;; + *) + lt_prog_compiler_pic_CXX='-fPIC' + ;; + esac + else + case $host_os in + aix4* | aix5*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + lt_prog_compiler_static_CXX='-Bstatic' + else + lt_prog_compiler_static_CXX='-bnso -bI:/lib/syscalls.exp' + fi + ;; + chorus*) + case $cc_basename in + cxch68*) + # Green Hills C++ Compiler + # _LT_AC_TAGVAR(lt_prog_compiler_static, CXX)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a" + ;; + esac + ;; + darwin*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + case $cc_basename in + xlc*) + lt_prog_compiler_pic_CXX='-qnocommon' + lt_prog_compiler_wl_CXX='-Wl,' + ;; + esac + ;; + dgux*) + case $cc_basename in + ec++*) + lt_prog_compiler_pic_CXX='-KPIC' + ;; + ghcx*) + # Green Hills C++ Compiler + lt_prog_compiler_pic_CXX='-pic' + ;; + *) + ;; + esac + ;; + freebsd* | kfreebsd*-gnu | dragonfly*) + # FreeBSD uses GNU C++ + ;; + hpux9* | hpux10* | hpux11*) + case $cc_basename in + CC*) + lt_prog_compiler_wl_CXX='-Wl,' + lt_prog_compiler_static_CXX='${wl}-a ${wl}archive' + if test "$host_cpu" != ia64; then + lt_prog_compiler_pic_CXX='+Z' + fi + ;; + aCC*) + lt_prog_compiler_wl_CXX='-Wl,' + lt_prog_compiler_static_CXX='${wl}-a ${wl}archive' + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + lt_prog_compiler_pic_CXX='+Z' + ;; + esac + ;; + *) + ;; + esac + ;; + interix*) + # This is c89, which is MS Visual C++ (no shared libs) + # Anyone wants to do a port? + ;; + irix5* | irix6* | nonstopux*) + case $cc_basename in + CC*) + lt_prog_compiler_wl_CXX='-Wl,' + lt_prog_compiler_static_CXX='-non_shared' + # CC pic flag -KPIC is the default. + ;; + *) + ;; + esac + ;; + linux*) + case $cc_basename in + KCC*) + # KAI C++ Compiler + lt_prog_compiler_wl_CXX='--backend -Wl,' + lt_prog_compiler_pic_CXX='-fPIC' + ;; + icpc* | ecpc*) + # Intel C++ + lt_prog_compiler_wl_CXX='-Wl,' + lt_prog_compiler_pic_CXX='-KPIC' + lt_prog_compiler_static_CXX='-static' + ;; + pgCC*) + # Portland Group C++ compiler. + lt_prog_compiler_wl_CXX='-Wl,' + lt_prog_compiler_pic_CXX='-fpic' + lt_prog_compiler_static_CXX='-Bstatic' + ;; + cxx*) + # Compaq C++ + # Make sure the PIC flag is empty. It appears that all Alpha + # Linux and Compaq Tru64 Unix objects are PIC. + lt_prog_compiler_pic_CXX= + lt_prog_compiler_static_CXX='-non_shared' + ;; + *) + ;; + esac + ;; + lynxos*) + ;; + m88k*) + ;; + mvs*) + case $cc_basename in + cxx*) + lt_prog_compiler_pic_CXX='-W c,exportall' + ;; + *) + ;; + esac + ;; + netbsd*) + ;; + osf3* | osf4* | osf5*) + case $cc_basename in + KCC*) + lt_prog_compiler_wl_CXX='--backend -Wl,' + ;; + RCC*) + # Rational C++ 2.4.1 + lt_prog_compiler_pic_CXX='-pic' + ;; + cxx*) + # Digital/Compaq C++ + lt_prog_compiler_wl_CXX='-Wl,' + # Make sure the PIC flag is empty. It appears that all Alpha + # Linux and Compaq Tru64 Unix objects are PIC. + lt_prog_compiler_pic_CXX= + lt_prog_compiler_static_CXX='-non_shared' + ;; + *) + ;; + esac + ;; + psos*) + ;; + solaris*) + case $cc_basename in + CC*) + # Sun C++ 4.2, 5.x and Centerline C++ + lt_prog_compiler_pic_CXX='-KPIC' + lt_prog_compiler_static_CXX='-Bstatic' + lt_prog_compiler_wl_CXX='-Qoption ld ' + ;; + gcx*) + # Green Hills C++ Compiler + lt_prog_compiler_pic_CXX='-PIC' + ;; + *) + ;; + esac + ;; + sunos4*) + case $cc_basename in + CC*) + # Sun C++ 4.x + lt_prog_compiler_pic_CXX='-pic' + lt_prog_compiler_static_CXX='-Bstatic' + ;; + lcc*) + # Lucid + lt_prog_compiler_pic_CXX='-pic' + ;; + *) + ;; + esac + ;; + tandem*) + case $cc_basename in + NCC*) + # NonStop-UX NCC 3.20 + lt_prog_compiler_pic_CXX='-KPIC' + ;; + *) + ;; + esac + ;; + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + case $cc_basename in + CC*) + lt_prog_compiler_wl_CXX='-Wl,' + lt_prog_compiler_pic_CXX='-KPIC' + lt_prog_compiler_static_CXX='-Bstatic' + ;; + esac + ;; + vxworks*) + ;; + *) + lt_prog_compiler_can_build_shared_CXX=no + ;; + esac + fi + +{ echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_CXX" >&5 +echo "${ECHO_T}$lt_prog_compiler_pic_CXX" >&6; } + +# +# Check to make sure the PIC flag actually works. +# +if test -n "$lt_prog_compiler_pic_CXX"; then + +{ echo "$as_me:$LINENO: checking if $compiler PIC flag $lt_prog_compiler_pic_CXX works" >&5 +echo $ECHO_N "checking if $compiler PIC flag $lt_prog_compiler_pic_CXX works... $ECHO_C" >&6; } +if test "${lt_prog_compiler_pic_works_CXX+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + lt_prog_compiler_pic_works_CXX=no + ac_outfile=conftest.$ac_objext + printf "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="$lt_prog_compiler_pic_CXX -DPIC" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:20277: $lt_compile\"" >&5) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&5 + echo "$as_me:20281: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings other than the usual output. + $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then + lt_prog_compiler_pic_works_CXX=yes + fi + fi + $rm conftest* + +fi +{ echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_works_CXX" >&5 +echo "${ECHO_T}$lt_prog_compiler_pic_works_CXX" >&6; } + +if test x"$lt_prog_compiler_pic_works_CXX" = xyes; then + case $lt_prog_compiler_pic_CXX in + "" | " "*) ;; + *) lt_prog_compiler_pic_CXX=" $lt_prog_compiler_pic_CXX" ;; + esac +else + lt_prog_compiler_pic_CXX= + lt_prog_compiler_can_build_shared_CXX=no +fi + +fi +case $host_os in + # For platforms which do not support PIC, -DPIC is meaningless: + *djgpp*) + lt_prog_compiler_pic_CXX= + ;; + *) + lt_prog_compiler_pic_CXX="$lt_prog_compiler_pic_CXX -DPIC" + ;; +esac + +# +# Check to make sure the static flag actually works. +# +wl=$lt_prog_compiler_wl_CXX eval lt_tmp_static_flag=\"$lt_prog_compiler_static_CXX\" +{ echo "$as_me:$LINENO: checking if $compiler static flag $lt_tmp_static_flag works" >&5 +echo $ECHO_N "checking if $compiler static flag $lt_tmp_static_flag works... $ECHO_C" >&6; } +if test "${lt_prog_compiler_static_works_CXX+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + lt_prog_compiler_static_works_CXX=no + save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS $lt_tmp_static_flag" + printf "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The linker can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&5 + $echo "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then + lt_prog_compiler_static_works_CXX=yes + fi + else + lt_prog_compiler_static_works_CXX=yes + fi + fi + $rm conftest* + LDFLAGS="$save_LDFLAGS" + +fi +{ echo "$as_me:$LINENO: result: $lt_prog_compiler_static_works_CXX" >&5 +echo "${ECHO_T}$lt_prog_compiler_static_works_CXX" >&6; } + +if test x"$lt_prog_compiler_static_works_CXX" = xyes; then + : +else + lt_prog_compiler_static_CXX= +fi + + +{ echo "$as_me:$LINENO: checking if $compiler supports -c -o file.$ac_objext" >&5 +echo $ECHO_N "checking if $compiler supports -c -o file.$ac_objext... $ECHO_C" >&6; } +if test "${lt_cv_prog_compiler_c_o_CXX+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + lt_cv_prog_compiler_c_o_CXX=no + $rm -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + printf "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:20381: $lt_compile\"" >&5) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&5 + echo "$as_me:20385: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + lt_cv_prog_compiler_c_o_CXX=yes + fi + fi + chmod u+w . 2>&5 + $rm conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $rm out/ii_files/* && rmdir out/ii_files + $rm out/* && rmdir out + cd .. + rmdir conftest + $rm conftest* + +fi +{ echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_c_o_CXX" >&5 +echo "${ECHO_T}$lt_cv_prog_compiler_c_o_CXX" >&6; } + + +hard_links="nottested" +if test "$lt_cv_prog_compiler_c_o_CXX" = no && test "$need_locks" != no; then + # do not overwrite the value of need_locks provided by the user + { echo "$as_me:$LINENO: checking if we can lock with hard links" >&5 +echo $ECHO_N "checking if we can lock with hard links... $ECHO_C" >&6; } + hard_links=yes + $rm conftest* + ln conftest.a conftest.b 2>/dev/null && hard_links=no + touch conftest.a + ln conftest.a conftest.b 2>&5 || hard_links=no + ln conftest.a conftest.b 2>/dev/null && hard_links=no + { echo "$as_me:$LINENO: result: $hard_links" >&5 +echo "${ECHO_T}$hard_links" >&6; } + if test "$hard_links" = no; then + { echo "$as_me:$LINENO: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5 +echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;} + need_locks=warn + fi +else + need_locks=no +fi + +{ echo "$as_me:$LINENO: checking whether the $compiler linker ($LD) supports shared libraries" >&5 +echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared libraries... $ECHO_C" >&6; } + + export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + case $host_os in + aix4* | aix5*) + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to AIX nm, but means don't demangle with GNU nm + if $NM -V 2>&1 | grep 'GNU' > /dev/null; then + export_symbols_cmds_CXX='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols' + else + export_symbols_cmds_CXX='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols' + fi + ;; + pw32*) + export_symbols_cmds_CXX="$ltdll_cmds" + ;; + cygwin* | mingw*) + export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS] /s/.* \([^ ]*\)/\1 DATA/;/^.* __nm__/s/^.* __nm__\([^ ]*\) [^ ]*/\1 DATA/;/^I /d;/^[AITW] /s/.* //'\'' | sort | uniq > $export_symbols' + ;; + *) + export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + ;; + esac + +{ echo "$as_me:$LINENO: result: $ld_shlibs_CXX" >&5 +echo "${ECHO_T}$ld_shlibs_CXX" >&6; } +test "$ld_shlibs_CXX" = no && can_build_shared=no + +# +# Do we need to explicitly link libc? +# +case "x$archive_cmds_need_lc_CXX" in +x|xyes) + # Assume -lc should be added + archive_cmds_need_lc_CXX=yes + + if test "$enable_shared" = yes && test "$GCC" = yes; then + case $archive_cmds_CXX in + *'~'*) + # FIXME: we may have to deal with multi-command sequences. + ;; + '$CC '*) + # Test whether the compiler implicitly links with -lc since on some + # systems, -lgcc has to come before -lc. If gcc already passes -lc + # to ld, don't add -lc before -lgcc. + { echo "$as_me:$LINENO: checking whether -lc should be explicitly linked in" >&5 +echo $ECHO_N "checking whether -lc should be explicitly linked in... $ECHO_C" >&6; } + $rm conftest* + printf "$lt_simple_compile_test_code" > conftest.$ac_ext + + if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } 2>conftest.err; then + soname=conftest + lib=conftest + libobjs=conftest.$ac_objext + deplibs= + wl=$lt_prog_compiler_wl_CXX + pic_flag=$lt_prog_compiler_pic_CXX + compiler_flags=-v + linker_flags=-v + verstring= + output_objdir=. + libname=conftest + lt_save_allow_undefined_flag=$allow_undefined_flag_CXX + allow_undefined_flag_CXX= + if { (eval echo "$as_me:$LINENO: \"$archive_cmds_CXX 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1\"") >&5 + (eval $archive_cmds_CXX 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + then + archive_cmds_need_lc_CXX=no + else + archive_cmds_need_lc_CXX=yes + fi + allow_undefined_flag_CXX=$lt_save_allow_undefined_flag + else + cat conftest.err 1>&5 + fi + $rm conftest* + { echo "$as_me:$LINENO: result: $archive_cmds_need_lc_CXX" >&5 +echo "${ECHO_T}$archive_cmds_need_lc_CXX" >&6; } + ;; + esac + fi + ;; +esac + +{ echo "$as_me:$LINENO: checking dynamic linker characteristics" >&5 +echo $ECHO_N "checking dynamic linker characteristics... $ECHO_C" >&6; } +library_names_spec= +libname_spec='lib$name' +soname_spec= +shrext_cmds=".so" +postinstall_cmds= +postuninstall_cmds= +finish_cmds= +finish_eval= +shlibpath_var= +shlibpath_overrides_runpath=unknown +version_type=none +dynamic_linker="$host_os ld.so" +sys_lib_dlsearch_path_spec="/lib /usr/lib" +if test "$GCC" = yes; then + sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` + if echo "$sys_lib_search_path_spec" | grep ';' >/dev/null ; then + # if the path contains ";" then we assume it to be the separator + # otherwise default to the standard path separator (i.e. ":") - it is + # assumed that no part of a normal pathname contains ";" but that should + # okay in the real world where ";" in dirpaths is itself problematic. + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi +else + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" +fi +need_lib_prefix=unknown +hardcode_into_libs=no + +# when you set need_version to no, make sure it does not cause -set_version +# flags to be left without arguments +need_version=unknown + +case $host_os in +aix3*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' + shlibpath_var=LIBPATH + + # AIX 3 has no versioning support, so we append a major version to the name. + soname_spec='${libname}${release}${shared_ext}$major' + ;; + +aix4* | aix5*) + version_type=linux + need_lib_prefix=no + need_version=no + hardcode_into_libs=yes + if test "$host_cpu" = ia64; then + # AIX 5 supports IA64 + library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + else + # With GCC up to 2.95.x, collect2 would create an import file + # for dependence libraries. The import file would start with + # the line `#! .'. This would cause the generated library to + # depend on `.', always an invalid library. This was fixed in + # development snapshots of GCC prior to 3.0. + case $host_os in + aix4 | aix4.[01] | aix4.[01].*) + if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' + echo ' yes ' + echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then + : + else + can_build_shared=no + fi + ;; + esac + # AIX (on Power*) has no versioning support, so currently we can not hardcode correct + # soname into executable. Probably we can add versioning support to + # collect2, so additional links can be useful in future. + if test "$aix_use_runtimelinking" = yes; then + # If using run time linking (on AIX 4.2 or later) use lib.so + # instead of lib.a to let people know that these are not + # typical AIX shared libraries. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + else + # We preserve .a as extension for shared libraries through AIX4.2 + # and later when we are not doing run time linking. + library_names_spec='${libname}${release}.a $libname.a' + soname_spec='${libname}${release}${shared_ext}$major' + fi + shlibpath_var=LIBPATH + fi + ;; + +amigaos*) + library_names_spec='$libname.ixlibrary $libname.a' + # Create ${libname}_ixlibrary.a entries in /sys/libs. + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' + ;; + +beos*) + library_names_spec='${libname}${shared_ext}' + dynamic_linker="$host_os ld.so" + shlibpath_var=LIBRARY_PATH + ;; + +bsdi[45]*) + version_type=linux + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" + sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" + # the default ld.so.conf also contains /usr/contrib/lib and + # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow + # libtool to hard-code these into programs + ;; + +cygwin* | mingw* | pw32*) + version_type=windows + shrext_cmds=".dll" + need_version=no + need_lib_prefix=no + + case $GCC,$host_os in + yes,cygwin* | yes,mingw* | yes,pw32*) + library_names_spec='$libname.dll.a' + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \${file}`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $rm \$dlpath' + shlibpath_overrides_runpath=yes + + case $host_os in + cygwin*) + # Cygwin DLLs use 'cyg' prefix rather than 'lib' + soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib" + ;; + mingw*) + # MinGW DLLs use traditional 'lib' prefix + soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` + if echo "$sys_lib_search_path_spec" | grep ';[c-zC-Z]:/' >/dev/null; then + # It is most probably a Windows format PATH printed by + # mingw gcc, but we are running on Cygwin. Gcc prints its search + # path with ; separators, and with drive letters. We can handle the + # drive letters (cygwin fileutils understands them), so leave them, + # especially as we might pass files found there to a mingw objdump, + # which wouldn't understand a cygwinified path. Ahh. + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi + ;; + pw32*) + # pw32 DLLs use 'pw' prefix rather than 'lib' + library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + ;; + esac + ;; + + *) + library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib' + ;; + esac + dynamic_linker='Win32 ld.exe' + # FIXME: first we should search . and the directory the executable is in + shlibpath_var=PATH + ;; + +darwin* | rhapsody*) + dynamic_linker="$host_os dyld" + version_type=darwin + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext' + soname_spec='${libname}${release}${major}$shared_ext' + shlibpath_overrides_runpath=yes + shlibpath_var=DYLD_LIBRARY_PATH + shrext_cmds='.dylib' + # Apple's gcc prints 'gcc -print-search-dirs' doesn't operate the same. + if test "$GCC" = yes; then + sys_lib_search_path_spec=`$CC -print-search-dirs | tr "\n" "$PATH_SEPARATOR" | sed -e 's/libraries:/@libraries:/' | tr "@" "\n" | grep "^libraries:" | sed -e "s/^libraries://" -e "s,=/,/,g" -e "s,$PATH_SEPARATOR, ,g" -e "s,.*,& /lib /usr/lib /usr/local/lib,g"` + else + sys_lib_search_path_spec='/lib /usr/lib /usr/local/lib' + fi + sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' + ;; + +dgux*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +freebsd1*) + dynamic_linker=no + ;; + +kfreebsd*-gnu) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='GNU ld.so' + ;; + +freebsd* | dragonfly*) + # DragonFly does not have aout. When/if they implement a new + # versioning mechanism, adjust this. + if test -x /usr/bin/objformat; then + objformat=`/usr/bin/objformat` + else + case $host_os in + freebsd[123]*) objformat=aout ;; + *) objformat=elf ;; + esac + fi + version_type=freebsd-$objformat + case $version_type in + freebsd-elf*) + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + need_version=no + need_lib_prefix=no + ;; + freebsd-*) + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' + need_version=yes + ;; + esac + shlibpath_var=LD_LIBRARY_PATH + case $host_os in + freebsd2*) + shlibpath_overrides_runpath=yes + ;; + freebsd3.[01]* | freebsdelf3.[01]*) + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ + freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + freebsd*) # from 4.6 on + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + esac + ;; + +gnu*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + hardcode_into_libs=yes + ;; + +hpux9* | hpux10* | hpux11*) + # Give a soname corresponding to the major version so that dld.sl refuses to + # link against other versions. + version_type=sunos + need_lib_prefix=no + need_version=no + case $host_cpu in + ia64*) + shrext_cmds='.so' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.so" + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + if test "X$HPUX_IA64_MODE" = X32; then + sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" + else + sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" + fi + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + hppa*64*) + shrext_cmds='.sl' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.sl" + shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + *) + shrext_cmds='.sl' + dynamic_linker="$host_os dld.sl" + shlibpath_var=SHLIB_PATH + shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + ;; + esac + # HP-UX runs *really* slowly unless shared libraries are mode 555. + postinstall_cmds='chmod 555 $lib' + ;; + +interix3*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +irix5* | irix6* | nonstopux*) + case $host_os in + nonstopux*) version_type=nonstopux ;; + *) + if test "$lt_cv_prog_gnu_ld" = yes; then + version_type=linux + else + version_type=irix + fi ;; + esac + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' + case $host_os in + irix5* | nonstopux*) + libsuff= shlibsuff= + ;; + *) + case $LD in # libtool.m4 will add one of these switches to LD + *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") + libsuff= shlibsuff= libmagic=32-bit;; + *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") + libsuff=32 shlibsuff=N32 libmagic=N32;; + *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") + libsuff=64 shlibsuff=64 libmagic=64-bit;; + *) libsuff= shlibsuff= libmagic=never-match;; + esac + ;; + esac + shlibpath_var=LD_LIBRARY${shlibsuff}_PATH + shlibpath_overrides_runpath=no + sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" + sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" + hardcode_into_libs=yes + ;; + +# No shared lib support for Linux oldld, aout, or coff. +linux*oldld* | linux*aout* | linux*coff*) + dynamic_linker=no + ;; + +# This must be Linux ELF. +linux*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + # Append ld.so.conf contents to the search path + if test -f /etc/ld.so.conf; then + lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '` + sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" + fi + + # We used to test for /lib/ld.so.1 and disable shared libraries on + # powerpc, because MkLinux only supported shared libraries with the + # GNU dynamic linker. Since this was broken with cross compilers, + # most powerpc-linux boxes support dynamic linking these days and + # people can always --disable-shared, the test was removed, and we + # assume the GNU/Linux dynamic linker is in use. + dynamic_linker='GNU/Linux ld.so' + ;; + +knetbsd*-gnu) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='GNU ld.so' + ;; + +netbsd*) + version_type=sunos + need_lib_prefix=no + need_version=no + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + dynamic_linker='NetBSD (a.out) ld.so' + else + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='NetBSD ld.elf_so' + fi + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + +newsos6) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +nto-qnx*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +openbsd*) + version_type=sunos + sys_lib_dlsearch_path_spec="/usr/lib" + need_lib_prefix=no + # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. + case $host_os in + openbsd3.3 | openbsd3.3.*) need_version=yes ;; + *) need_version=no ;; + esac + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + shlibpath_var=LD_LIBRARY_PATH + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + case $host_os in + openbsd2.[89] | openbsd2.[89].*) + shlibpath_overrides_runpath=no + ;; + *) + shlibpath_overrides_runpath=yes + ;; + esac + else + shlibpath_overrides_runpath=yes + fi + ;; + +os2*) + libname_spec='$name' + shrext_cmds=".dll" + need_lib_prefix=no + library_names_spec='$libname${shared_ext} $libname.a' + dynamic_linker='OS/2 ld.exe' + shlibpath_var=LIBPATH + ;; + +osf3* | osf4* | osf5*) + version_type=osf + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" + sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" + ;; + +solaris*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + # ldd complains unless libraries are executable + postinstall_cmds='chmod +x $lib' + ;; + +sunos4*) + version_type=sunos + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + if test "$with_gnu_ld" = yes; then + need_lib_prefix=no + fi + need_version=yes + ;; + +sysv4 | sysv4.3*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + case $host_vendor in + sni) + shlibpath_overrides_runpath=no + need_lib_prefix=no + export_dynamic_flag_spec='${wl}-Blargedynsym' + runpath_var=LD_RUN_PATH + ;; + siemens) + need_lib_prefix=no + ;; + motorola) + need_lib_prefix=no + need_version=no + shlibpath_overrides_runpath=no + sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' + ;; + esac + ;; + +sysv4*MP*) + if test -d /usr/nec ;then + version_type=linux + library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' + soname_spec='$libname${shared_ext}.$major' + shlibpath_var=LD_LIBRARY_PATH + fi + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + version_type=freebsd-elf + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + hardcode_into_libs=yes + if test "$with_gnu_ld" = yes; then + sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' + shlibpath_overrides_runpath=no + else + sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' + shlibpath_overrides_runpath=yes + case $host_os in + sco3.2v5*) + sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" + ;; + esac + fi + sys_lib_dlsearch_path_spec='/usr/lib' + ;; + +uts4*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +*) + dynamic_linker=no + ;; +esac +{ echo "$as_me:$LINENO: result: $dynamic_linker" >&5 +echo "${ECHO_T}$dynamic_linker" >&6; } +test "$dynamic_linker" = no && can_build_shared=no + +variables_saved_for_relink="PATH $shlibpath_var $runpath_var" +if test "$GCC" = yes; then + variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" +fi + +{ echo "$as_me:$LINENO: checking how to hardcode library paths into programs" >&5 +echo $ECHO_N "checking how to hardcode library paths into programs... $ECHO_C" >&6; } +hardcode_action_CXX= +if test -n "$hardcode_libdir_flag_spec_CXX" || \ + test -n "$runpath_var_CXX" || \ + test "X$hardcode_automatic_CXX" = "Xyes" ; then + + # We can hardcode non-existant directories. + if test "$hardcode_direct_CXX" != no && + # If the only mechanism to avoid hardcoding is shlibpath_var, we + # have to relink, otherwise we might link with an installed library + # when we should be linking with a yet-to-be-installed one + ## test "$_LT_AC_TAGVAR(hardcode_shlibpath_var, CXX)" != no && + test "$hardcode_minus_L_CXX" != no; then + # Linking always hardcodes the temporary library directory. + hardcode_action_CXX=relink + else + # We can link without hardcoding, and we can hardcode nonexisting dirs. + hardcode_action_CXX=immediate + fi +else + # We cannot hardcode anything, or else we can only hardcode existing + # directories. + hardcode_action_CXX=unsupported +fi +{ echo "$as_me:$LINENO: result: $hardcode_action_CXX" >&5 +echo "${ECHO_T}$hardcode_action_CXX" >&6; } + +if test "$hardcode_action_CXX" = relink; then + # Fast installation is not supported + enable_fast_install=no +elif test "$shlibpath_overrides_runpath" = yes || + test "$enable_shared" = no; then + # Fast installation is not necessary + enable_fast_install=needless +fi + + +# The else clause should only fire when bootstrapping the +# libtool distribution, otherwise you forgot to ship ltmain.sh +# with your package, and you will get complaints that there are +# no rules to generate ltmain.sh. +if test -f "$ltmain"; then + # See if we are running on zsh, and set the options which allow our commands through + # without removal of \ escapes. + if test -n "${ZSH_VERSION+set}" ; then + setopt NO_GLOB_SUBST + fi + # Now quote all the things that may contain metacharacters while being + # careful not to overquote the AC_SUBSTed values. We take copies of the + # variables and quote the copies for generation of the libtool script. + for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC LTCFLAGS NM \ + SED SHELL STRIP \ + libname_spec library_names_spec soname_spec extract_expsyms_cmds \ + old_striplib striplib file_magic_cmd finish_cmds finish_eval \ + deplibs_check_method reload_flag reload_cmds need_locks \ + lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \ + lt_cv_sys_global_symbol_to_c_name_address \ + sys_lib_search_path_spec sys_lib_dlsearch_path_spec \ + old_postinstall_cmds old_postuninstall_cmds \ + compiler_CXX \ + CC_CXX \ + LD_CXX \ + lt_prog_compiler_wl_CXX \ + lt_prog_compiler_pic_CXX \ + lt_prog_compiler_static_CXX \ + lt_prog_compiler_no_builtin_flag_CXX \ + export_dynamic_flag_spec_CXX \ + thread_safe_flag_spec_CXX \ + whole_archive_flag_spec_CXX \ + enable_shared_with_static_runtimes_CXX \ + old_archive_cmds_CXX \ + old_archive_from_new_cmds_CXX \ + predep_objects_CXX \ + postdep_objects_CXX \ + predeps_CXX \ + postdeps_CXX \ + compiler_lib_search_path_CXX \ + archive_cmds_CXX \ + archive_expsym_cmds_CXX \ + postinstall_cmds_CXX \ + postuninstall_cmds_CXX \ + old_archive_from_expsyms_cmds_CXX \ + allow_undefined_flag_CXX \ + no_undefined_flag_CXX \ + export_symbols_cmds_CXX \ + hardcode_libdir_flag_spec_CXX \ + hardcode_libdir_flag_spec_ld_CXX \ + hardcode_libdir_separator_CXX \ + hardcode_automatic_CXX \ + module_cmds_CXX \ + module_expsym_cmds_CXX \ + lt_cv_prog_compiler_c_o_CXX \ + exclude_expsyms_CXX \ + include_expsyms_CXX; do + + case $var in + old_archive_cmds_CXX | \ + old_archive_from_new_cmds_CXX | \ + archive_cmds_CXX | \ + archive_expsym_cmds_CXX | \ + module_cmds_CXX | \ + module_expsym_cmds_CXX | \ + old_archive_from_expsyms_cmds_CXX | \ + export_symbols_cmds_CXX | \ + extract_expsyms_cmds | reload_cmds | finish_cmds | \ + postinstall_cmds | postuninstall_cmds | \ + old_postinstall_cmds | old_postuninstall_cmds | \ + sys_lib_search_path_spec | sys_lib_dlsearch_path_spec) + # Double-quote double-evaled strings. + eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\"" + ;; + *) + eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\"" + ;; + esac + done + + case $lt_echo in + *'\$0 --fallback-echo"') + lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'` + ;; + esac + +cfgfile="$ofile" + + cat <<__EOF__ >> "$cfgfile" +# ### BEGIN LIBTOOL TAG CONFIG: $tagname + +# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: + +# Shell to use when invoking shell scripts. +SHELL=$lt_SHELL + +# Whether or not to build shared libraries. +build_libtool_libs=$enable_shared + +# Whether or not to build static libraries. +build_old_libs=$enable_static + +# Whether or not to add -lc for building shared libraries. +build_libtool_need_lc=$archive_cmds_need_lc_CXX + +# Whether or not to disallow shared libs when runtime libs are static +allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes_CXX + +# Whether or not to optimize for fast installation. +fast_install=$enable_fast_install + +# The host system. +host_alias=$host_alias +host=$host +host_os=$host_os + +# The build system. +build_alias=$build_alias +build=$build +build_os=$build_os + +# An echo program that does not interpret backslashes. +echo=$lt_echo + +# The archiver. +AR=$lt_AR +AR_FLAGS=$lt_AR_FLAGS + +# A C compiler. +LTCC=$lt_LTCC + +# LTCC compiler flags. +LTCFLAGS=$lt_LTCFLAGS + +# A language-specific compiler. +CC=$lt_compiler_CXX + +# Is the compiler the GNU C compiler? +with_gcc=$GCC_CXX + +# An ERE matcher. +EGREP=$lt_EGREP + +# The linker used to build libraries. +LD=$lt_LD_CXX + +# Whether we need hard or soft links. +LN_S=$lt_LN_S + +# A BSD-compatible nm program. +NM=$lt_NM + +# A symbol stripping program +STRIP=$lt_STRIP + +# Used to examine libraries when file_magic_cmd begins "file" +MAGIC_CMD=$MAGIC_CMD + +# Used on cygwin: DLL creation program. +DLLTOOL="$DLLTOOL" + +# Used on cygwin: object dumper. +OBJDUMP="$OBJDUMP" + +# Used on cygwin: assembler. +AS="$AS" + +# The name of the directory that contains temporary libtool files. +objdir=$objdir + +# How to create reloadable object files. +reload_flag=$lt_reload_flag +reload_cmds=$lt_reload_cmds + +# How to pass a linker flag through the compiler. +wl=$lt_lt_prog_compiler_wl_CXX + +# Object file suffix (normally "o"). +objext="$ac_objext" + +# Old archive suffix (normally "a"). +libext="$libext" + +# Shared library suffix (normally ".so"). +shrext_cmds='$shrext_cmds' + +# Executable file suffix (normally ""). +exeext="$exeext" + +# Additional compiler flags for building library objects. +pic_flag=$lt_lt_prog_compiler_pic_CXX +pic_mode=$pic_mode + +# What is the maximum length of a command? +max_cmd_len=$lt_cv_sys_max_cmd_len + +# Does compiler simultaneously support -c and -o options? +compiler_c_o=$lt_lt_cv_prog_compiler_c_o_CXX + +# Must we lock files when doing compilation? +need_locks=$lt_need_locks + +# Do we need the lib prefix for modules? +need_lib_prefix=$need_lib_prefix + +# Do we need a version for libraries? +need_version=$need_version + +# Whether dlopen is supported. +dlopen_support=$enable_dlopen + +# Whether dlopen of programs is supported. +dlopen_self=$enable_dlopen_self + +# Whether dlopen of statically linked programs is supported. +dlopen_self_static=$enable_dlopen_self_static + +# Compiler flag to prevent dynamic linking. +link_static_flag=$lt_lt_prog_compiler_static_CXX + +# Compiler flag to turn off builtin functions. +no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_CXX + +# Compiler flag to allow reflexive dlopens. +export_dynamic_flag_spec=$lt_export_dynamic_flag_spec_CXX + +# Compiler flag to generate shared objects directly from archives. +whole_archive_flag_spec=$lt_whole_archive_flag_spec_CXX + +# Compiler flag to generate thread-safe objects. +thread_safe_flag_spec=$lt_thread_safe_flag_spec_CXX + +# Library versioning type. +version_type=$version_type + +# Format of library name prefix. +libname_spec=$lt_libname_spec + +# List of archive names. First name is the real one, the rest are links. +# The last name is the one that the linker finds with -lNAME. +library_names_spec=$lt_library_names_spec + +# The coded name of the library, if different from the real name. +soname_spec=$lt_soname_spec + +# Commands used to build and install an old-style archive. +RANLIB=$lt_RANLIB +old_archive_cmds=$lt_old_archive_cmds_CXX +old_postinstall_cmds=$lt_old_postinstall_cmds +old_postuninstall_cmds=$lt_old_postuninstall_cmds + +# Create an old-style archive from a shared archive. +old_archive_from_new_cmds=$lt_old_archive_from_new_cmds_CXX + +# Create a temporary old-style archive to link instead of a shared archive. +old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds_CXX + +# Commands used to build and install a shared archive. +archive_cmds=$lt_archive_cmds_CXX +archive_expsym_cmds=$lt_archive_expsym_cmds_CXX +postinstall_cmds=$lt_postinstall_cmds +postuninstall_cmds=$lt_postuninstall_cmds + +# Commands used to build a loadable module (assumed same as above if empty) +module_cmds=$lt_module_cmds_CXX +module_expsym_cmds=$lt_module_expsym_cmds_CXX + +# Commands to strip libraries. +old_striplib=$lt_old_striplib +striplib=$lt_striplib + +# Dependencies to place before the objects being linked to create a +# shared library. +predep_objects=$lt_predep_objects_CXX + +# Dependencies to place after the objects being linked to create a +# shared library. +postdep_objects=$lt_postdep_objects_CXX + +# Dependencies to place before the objects being linked to create a +# shared library. +predeps=$lt_predeps_CXX + +# Dependencies to place after the objects being linked to create a +# shared library. +postdeps=$lt_postdeps_CXX + +# The library search path used internally by the compiler when linking +# a shared library. +compiler_lib_search_path=$lt_compiler_lib_search_path_CXX + +# Method to check whether dependent libraries are shared objects. +deplibs_check_method=$lt_deplibs_check_method + +# Command to use when deplibs_check_method == file_magic. +file_magic_cmd=$lt_file_magic_cmd + +# Flag that allows shared libraries with undefined symbols to be built. +allow_undefined_flag=$lt_allow_undefined_flag_CXX + +# Flag that forces no undefined symbols. +no_undefined_flag=$lt_no_undefined_flag_CXX + +# Commands used to finish a libtool library installation in a directory. +finish_cmds=$lt_finish_cmds + +# Same as above, but a single script fragment to be evaled but not shown. +finish_eval=$lt_finish_eval + +# Take the output of nm and produce a listing of raw symbols and C names. +global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe + +# Transform the output of nm in a proper C declaration +global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl + +# Transform the output of nm in a C name address pair +global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address + +# This is the shared library runtime path variable. +runpath_var=$runpath_var + +# This is the shared library path variable. +shlibpath_var=$shlibpath_var + +# Is shlibpath searched before the hard-coded library search path? +shlibpath_overrides_runpath=$shlibpath_overrides_runpath + +# How to hardcode a shared library path into an executable. +hardcode_action=$hardcode_action_CXX + +# Whether we should hardcode library paths into libraries. +hardcode_into_libs=$hardcode_into_libs + +# Flag to hardcode \$libdir into a binary during linking. +# This must work even if \$libdir does not exist. +hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_CXX + +# If ld is used when linking, flag to hardcode \$libdir into +# a binary during linking. This must work even if \$libdir does +# not exist. +hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld_CXX + +# Whether we need a single -rpath flag with a separated argument. +hardcode_libdir_separator=$lt_hardcode_libdir_separator_CXX + +# Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the +# resulting binary. +hardcode_direct=$hardcode_direct_CXX + +# Set to yes if using the -LDIR flag during linking hardcodes DIR into the +# resulting binary. +hardcode_minus_L=$hardcode_minus_L_CXX + +# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into +# the resulting binary. +hardcode_shlibpath_var=$hardcode_shlibpath_var_CXX + +# Set to yes if building a shared library automatically hardcodes DIR into the library +# and all subsequent libraries and executables linked against it. +hardcode_automatic=$hardcode_automatic_CXX + +# Variables whose values should be saved in libtool wrapper scripts and +# restored at relink time. +variables_saved_for_relink="$variables_saved_for_relink" + +# Whether libtool must link a program against all its dependency libraries. +link_all_deplibs=$link_all_deplibs_CXX + +# Compile-time system search path for libraries +sys_lib_search_path_spec=$lt_sys_lib_search_path_spec + +# Run-time system search path for libraries +sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec + +# Fix the shell variable \$srcfile for the compiler. +fix_srcfile_path="$fix_srcfile_path_CXX" + +# Set to yes if exported symbols are required. +always_export_symbols=$always_export_symbols_CXX + +# The commands to list exported symbols. +export_symbols_cmds=$lt_export_symbols_cmds_CXX + +# The commands to extract the exported symbol list from a shared archive. +extract_expsyms_cmds=$lt_extract_expsyms_cmds + +# Symbols that should not be listed in the preloaded symbols. +exclude_expsyms=$lt_exclude_expsyms_CXX + +# Symbols that must always be exported. +include_expsyms=$lt_include_expsyms_CXX + +# ### END LIBTOOL TAG CONFIG: $tagname + +__EOF__ + + +else + # If there is no Makefile yet, we rely on a make rule to execute + # `config.status --recheck' to rerun these tests and create the + # libtool script then. + ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'` + if test -f "$ltmain_in"; then + test -f Makefile && make "$ltmain" + fi +fi + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +CC=$lt_save_CC +LDCXX=$LD +LD=$lt_save_LD +GCC=$lt_save_GCC +with_gnu_ldcxx=$with_gnu_ld +with_gnu_ld=$lt_save_with_gnu_ld +lt_cv_path_LDCXX=$lt_cv_path_LD +lt_cv_path_LD=$lt_save_path_LD +lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld +lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld + + else + tagname="" + fi + ;; + + F77) + if test -n "$F77" && test "X$F77" != "Xno"; then + +ac_ext=f +ac_compile='$F77 -c $FFLAGS conftest.$ac_ext >&5' +ac_link='$F77 -o conftest$ac_exeext $FFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_f77_compiler_gnu + + +archive_cmds_need_lc_F77=no +allow_undefined_flag_F77= +always_export_symbols_F77=no +archive_expsym_cmds_F77= +export_dynamic_flag_spec_F77= +hardcode_direct_F77=no +hardcode_libdir_flag_spec_F77= +hardcode_libdir_flag_spec_ld_F77= +hardcode_libdir_separator_F77= +hardcode_minus_L_F77=no +hardcode_automatic_F77=no +module_cmds_F77= +module_expsym_cmds_F77= +link_all_deplibs_F77=unknown +old_archive_cmds_F77=$old_archive_cmds +no_undefined_flag_F77= +whole_archive_flag_spec_F77= +enable_shared_with_static_runtimes_F77=no + +# Source file extension for f77 test sources. +ac_ext=f + +# Object file extension for compiled f77 test sources. +objext=o +objext_F77=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code=" subroutine t\n return\n end\n" + +# Code to be used in simple link tests +lt_simple_link_test_code=" program t\n end\n" + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC + + +# save warnings/boilerplate of simple test code +ac_outfile=conftest.$ac_objext +printf "$lt_simple_compile_test_code" >conftest.$ac_ext +eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_compiler_boilerplate=`cat conftest.err` +$rm conftest* + +ac_outfile=conftest.$ac_objext +printf "$lt_simple_link_test_code" >conftest.$ac_ext +eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_linker_boilerplate=`cat conftest.err` +$rm conftest* + + +# Allow CC to be a program name with arguments. +lt_save_CC="$CC" +CC=${F77-"f77"} +compiler=$CC +compiler_F77=$CC +for cc_temp in $compiler""; do + case $cc_temp in + compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; + distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; + \-*) ;; + *) break;; + esac +done +cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` + + +{ echo "$as_me:$LINENO: checking if libtool supports shared libraries" >&5 +echo $ECHO_N "checking if libtool supports shared libraries... $ECHO_C" >&6; } +{ echo "$as_me:$LINENO: result: $can_build_shared" >&5 +echo "${ECHO_T}$can_build_shared" >&6; } + +{ echo "$as_me:$LINENO: checking whether to build shared libraries" >&5 +echo $ECHO_N "checking whether to build shared libraries... $ECHO_C" >&6; } +test "$can_build_shared" = "no" && enable_shared=no + +# On AIX, shared libraries and static libraries use the same namespace, and +# are all built from PIC. +case $host_os in +aix3*) + test "$enable_shared" = yes && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; +aix4* | aix5*) + if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then + test "$enable_shared" = yes && enable_static=no + fi + ;; +esac +{ echo "$as_me:$LINENO: result: $enable_shared" >&5 +echo "${ECHO_T}$enable_shared" >&6; } + +{ echo "$as_me:$LINENO: checking whether to build static libraries" >&5 +echo $ECHO_N "checking whether to build static libraries... $ECHO_C" >&6; } +# Make sure either enable_shared or enable_static is yes. +test "$enable_shared" = yes || enable_static=yes +{ echo "$as_me:$LINENO: result: $enable_static" >&5 +echo "${ECHO_T}$enable_static" >&6; } + +GCC_F77="$G77" +LD_F77="$LD" + +lt_prog_compiler_wl_F77= +lt_prog_compiler_pic_F77= +lt_prog_compiler_static_F77= + +{ echo "$as_me:$LINENO: checking for $compiler option to produce PIC" >&5 +echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6; } + + if test "$GCC" = yes; then + lt_prog_compiler_wl_F77='-Wl,' + lt_prog_compiler_static_F77='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + lt_prog_compiler_static_F77='-Bstatic' + fi + ;; + + amigaos*) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the `-m68020' flag to GCC prevents building anything better, + # like `-m68040'. + lt_prog_compiler_pic_F77='-m68020 -resident32 -malways-restore-a4' + ;; + + beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + + mingw* | pw32* | os2*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + lt_prog_compiler_pic_F77='-DDLL_EXPORT' + ;; + + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + lt_prog_compiler_pic_F77='-fno-common' + ;; + + interix3*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + + msdosdjgpp*) + # Just because we use GCC doesn't mean we suddenly get shared libraries + # on systems that don't support them. + lt_prog_compiler_can_build_shared_F77=no + enable_shared=no + ;; + + sysv4*MP*) + if test -d /usr/nec; then + lt_prog_compiler_pic_F77=-Kconform_pic + fi + ;; + + hpux*) + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + lt_prog_compiler_pic_F77='-fPIC' + ;; + esac + ;; + + *) + lt_prog_compiler_pic_F77='-fPIC' + ;; + esac + else + # PORTME Check for flag to pass linker flags through the system compiler. + case $host_os in + aix*) + lt_prog_compiler_wl_F77='-Wl,' + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + lt_prog_compiler_static_F77='-Bstatic' + else + lt_prog_compiler_static_F77='-bnso -bI:/lib/syscalls.exp' + fi + ;; + darwin*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + case $cc_basename in + xlc*) + lt_prog_compiler_pic_F77='-qnocommon' + lt_prog_compiler_wl_F77='-Wl,' + ;; + esac + ;; + + mingw* | pw32* | os2*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + lt_prog_compiler_pic_F77='-DDLL_EXPORT' + ;; + + hpux9* | hpux10* | hpux11*) + lt_prog_compiler_wl_F77='-Wl,' + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + lt_prog_compiler_pic_F77='+Z' + ;; + esac + # Is there a better lt_prog_compiler_static that works with the bundled CC? + lt_prog_compiler_static_F77='${wl}-a ${wl}archive' + ;; + + irix5* | irix6* | nonstopux*) + lt_prog_compiler_wl_F77='-Wl,' + # PIC (with -KPIC) is the default. + lt_prog_compiler_static_F77='-non_shared' + ;; + + newsos6) + lt_prog_compiler_pic_F77='-KPIC' + lt_prog_compiler_static_F77='-Bstatic' + ;; + + linux*) + case $cc_basename in + icc* | ecc*) + lt_prog_compiler_wl_F77='-Wl,' + lt_prog_compiler_pic_F77='-KPIC' + lt_prog_compiler_static_F77='-static' + ;; + pgcc* | pgf77* | pgf90* | pgf95*) + # Portland Group compilers (*not* the Pentium gcc compiler, + # which looks to be a dead project) + lt_prog_compiler_wl_F77='-Wl,' + lt_prog_compiler_pic_F77='-fpic' + lt_prog_compiler_static_F77='-Bstatic' + ;; + ccc*) + lt_prog_compiler_wl_F77='-Wl,' + # All Alpha code is PIC. + lt_prog_compiler_static_F77='-non_shared' + ;; + esac + ;; + + osf3* | osf4* | osf5*) + lt_prog_compiler_wl_F77='-Wl,' + # All OSF/1 code is PIC. + lt_prog_compiler_static_F77='-non_shared' + ;; + + solaris*) + lt_prog_compiler_pic_F77='-KPIC' + lt_prog_compiler_static_F77='-Bstatic' + case $cc_basename in + f77* | f90* | f95*) + lt_prog_compiler_wl_F77='-Qoption ld ';; + *) + lt_prog_compiler_wl_F77='-Wl,';; + esac + ;; + + sunos4*) + lt_prog_compiler_wl_F77='-Qoption ld ' + lt_prog_compiler_pic_F77='-PIC' + lt_prog_compiler_static_F77='-Bstatic' + ;; + + sysv4 | sysv4.2uw2* | sysv4.3*) + lt_prog_compiler_wl_F77='-Wl,' + lt_prog_compiler_pic_F77='-KPIC' + lt_prog_compiler_static_F77='-Bstatic' + ;; + + sysv4*MP*) + if test -d /usr/nec ;then + lt_prog_compiler_pic_F77='-Kconform_pic' + lt_prog_compiler_static_F77='-Bstatic' + fi + ;; + + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + lt_prog_compiler_wl_F77='-Wl,' + lt_prog_compiler_pic_F77='-KPIC' + lt_prog_compiler_static_F77='-Bstatic' + ;; + + unicos*) + lt_prog_compiler_wl_F77='-Wl,' + lt_prog_compiler_can_build_shared_F77=no + ;; + + uts4*) + lt_prog_compiler_pic_F77='-pic' + lt_prog_compiler_static_F77='-Bstatic' + ;; + + *) + lt_prog_compiler_can_build_shared_F77=no + ;; + esac + fi + +{ echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_F77" >&5 +echo "${ECHO_T}$lt_prog_compiler_pic_F77" >&6; } + +# +# Check to make sure the PIC flag actually works. +# +if test -n "$lt_prog_compiler_pic_F77"; then + +{ echo "$as_me:$LINENO: checking if $compiler PIC flag $lt_prog_compiler_pic_F77 works" >&5 +echo $ECHO_N "checking if $compiler PIC flag $lt_prog_compiler_pic_F77 works... $ECHO_C" >&6; } +if test "${lt_prog_compiler_pic_works_F77+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + lt_prog_compiler_pic_works_F77=no + ac_outfile=conftest.$ac_objext + printf "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="$lt_prog_compiler_pic_F77" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:21951: $lt_compile\"" >&5) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&5 + echo "$as_me:21955: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings other than the usual output. + $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then + lt_prog_compiler_pic_works_F77=yes + fi + fi + $rm conftest* + +fi +{ echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_works_F77" >&5 +echo "${ECHO_T}$lt_prog_compiler_pic_works_F77" >&6; } + +if test x"$lt_prog_compiler_pic_works_F77" = xyes; then + case $lt_prog_compiler_pic_F77 in + "" | " "*) ;; + *) lt_prog_compiler_pic_F77=" $lt_prog_compiler_pic_F77" ;; + esac +else + lt_prog_compiler_pic_F77= + lt_prog_compiler_can_build_shared_F77=no +fi + +fi +case $host_os in + # For platforms which do not support PIC, -DPIC is meaningless: + *djgpp*) + lt_prog_compiler_pic_F77= + ;; + *) + lt_prog_compiler_pic_F77="$lt_prog_compiler_pic_F77" + ;; +esac + +# +# Check to make sure the static flag actually works. +# +wl=$lt_prog_compiler_wl_F77 eval lt_tmp_static_flag=\"$lt_prog_compiler_static_F77\" +{ echo "$as_me:$LINENO: checking if $compiler static flag $lt_tmp_static_flag works" >&5 +echo $ECHO_N "checking if $compiler static flag $lt_tmp_static_flag works... $ECHO_C" >&6; } +if test "${lt_prog_compiler_static_works_F77+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + lt_prog_compiler_static_works_F77=no + save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS $lt_tmp_static_flag" + printf "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The linker can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&5 + $echo "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then + lt_prog_compiler_static_works_F77=yes + fi + else + lt_prog_compiler_static_works_F77=yes + fi + fi + $rm conftest* + LDFLAGS="$save_LDFLAGS" + +fi +{ echo "$as_me:$LINENO: result: $lt_prog_compiler_static_works_F77" >&5 +echo "${ECHO_T}$lt_prog_compiler_static_works_F77" >&6; } + +if test x"$lt_prog_compiler_static_works_F77" = xyes; then + : +else + lt_prog_compiler_static_F77= +fi + + +{ echo "$as_me:$LINENO: checking if $compiler supports -c -o file.$ac_objext" >&5 +echo $ECHO_N "checking if $compiler supports -c -o file.$ac_objext... $ECHO_C" >&6; } +if test "${lt_cv_prog_compiler_c_o_F77+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + lt_cv_prog_compiler_c_o_F77=no + $rm -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + printf "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:22055: $lt_compile\"" >&5) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&5 + echo "$as_me:22059: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + lt_cv_prog_compiler_c_o_F77=yes + fi + fi + chmod u+w . 2>&5 + $rm conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $rm out/ii_files/* && rmdir out/ii_files + $rm out/* && rmdir out + cd .. + rmdir conftest + $rm conftest* + +fi +{ echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_c_o_F77" >&5 +echo "${ECHO_T}$lt_cv_prog_compiler_c_o_F77" >&6; } + + +hard_links="nottested" +if test "$lt_cv_prog_compiler_c_o_F77" = no && test "$need_locks" != no; then + # do not overwrite the value of need_locks provided by the user + { echo "$as_me:$LINENO: checking if we can lock with hard links" >&5 +echo $ECHO_N "checking if we can lock with hard links... $ECHO_C" >&6; } + hard_links=yes + $rm conftest* + ln conftest.a conftest.b 2>/dev/null && hard_links=no + touch conftest.a + ln conftest.a conftest.b 2>&5 || hard_links=no + ln conftest.a conftest.b 2>/dev/null && hard_links=no + { echo "$as_me:$LINENO: result: $hard_links" >&5 +echo "${ECHO_T}$hard_links" >&6; } + if test "$hard_links" = no; then + { echo "$as_me:$LINENO: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5 +echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;} + need_locks=warn + fi +else + need_locks=no +fi + +{ echo "$as_me:$LINENO: checking whether the $compiler linker ($LD) supports shared libraries" >&5 +echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared libraries... $ECHO_C" >&6; } + + runpath_var= + allow_undefined_flag_F77= + enable_shared_with_static_runtimes_F77=no + archive_cmds_F77= + archive_expsym_cmds_F77= + old_archive_From_new_cmds_F77= + old_archive_from_expsyms_cmds_F77= + export_dynamic_flag_spec_F77= + whole_archive_flag_spec_F77= + thread_safe_flag_spec_F77= + hardcode_libdir_flag_spec_F77= + hardcode_libdir_flag_spec_ld_F77= + hardcode_libdir_separator_F77= + hardcode_direct_F77=no + hardcode_minus_L_F77=no + hardcode_shlibpath_var_F77=unsupported + link_all_deplibs_F77=unknown + hardcode_automatic_F77=no + module_cmds_F77= + module_expsym_cmds_F77= + always_export_symbols_F77=no + export_symbols_cmds_F77='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + # include_expsyms should be a list of space-separated symbols to be *always* + # included in the symbol list + include_expsyms_F77= + # exclude_expsyms can be an extended regexp of symbols to exclude + # it will be wrapped by ` (' and `)$', so one must not match beginning or + # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', + # as well as any symbol that contains `d'. + exclude_expsyms_F77="_GLOBAL_OFFSET_TABLE_" + # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out + # platforms (ab)use it in PIC code, but their linkers get confused if + # the symbol is explicitly referenced. Since portable code cannot + # rely on this symbol name, it's probably fine to never include it in + # preloaded symbol tables. + extract_expsyms_cmds= + # Just being paranoid about ensuring that cc_basename is set. + for cc_temp in $compiler""; do + case $cc_temp in + compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; + distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; + \-*) ;; + *) break;; + esac +done +cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` + + case $host_os in + cygwin* | mingw* | pw32*) + # FIXME: the MSVC++ port hasn't been tested in a loooong time + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + if test "$GCC" != yes; then + with_gnu_ld=no + fi + ;; + interix*) + # we just hope/assume this is gcc and not c89 (= MSVC++) + with_gnu_ld=yes + ;; + openbsd*) + with_gnu_ld=no + ;; + esac + + ld_shlibs_F77=yes + if test "$with_gnu_ld" = yes; then + # If archive_cmds runs LD, not CC, wlarc should be empty + wlarc='${wl}' + + # Set some defaults for GNU ld with shared library support. These + # are reset later if shared libraries are not supported. Putting them + # here allows them to be overridden if necessary. + runpath_var=LD_RUN_PATH + hardcode_libdir_flag_spec_F77='${wl}--rpath ${wl}$libdir' + export_dynamic_flag_spec_F77='${wl}--export-dynamic' + # ancient GNU ld didn't support --whole-archive et. al. + if $LD --help 2>&1 | grep 'no-whole-archive' > /dev/null; then + whole_archive_flag_spec_F77="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + else + whole_archive_flag_spec_F77= + fi + supports_anon_versioning=no + case `$LD -v 2>/dev/null` in + *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11 + *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... + *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... + *\ 2.11.*) ;; # other 2.11 versions + *) supports_anon_versioning=yes ;; + esac + + # See if GNU ld supports shared libraries. + case $host_os in + aix3* | aix4* | aix5*) + # On AIX/PPC, the GNU linker is very broken + if test "$host_cpu" != ia64; then + ld_shlibs_F77=no + cat <&2 + +*** Warning: the GNU linker, at least up to release 2.9.1, is reported +*** to be unable to reliably create shared libraries on AIX. +*** Therefore, libtool is disabling shared libraries support. If you +*** really care for shared libraries, you may want to modify your PATH +*** so that a non-GNU linker is found, and then restart. + +EOF + fi + ;; + + amigaos*) + archive_cmds_F77='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + hardcode_libdir_flag_spec_F77='-L$libdir' + hardcode_minus_L_F77=yes + + # Samuel A. Falvo II reports + # that the semantics of dynamic libraries on AmigaOS, at least up + # to version 4, is to share data among multiple programs linked + # with the same dynamic library. Since this doesn't match the + # behavior of shared libraries on other platforms, we can't use + # them. + ld_shlibs_F77=no + ;; + + beos*) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + allow_undefined_flag_F77=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + archive_cmds_F77='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + else + ld_shlibs_F77=no + fi + ;; + + cygwin* | mingw* | pw32*) + # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, F77) is actually meaningless, + # as there is no search path for DLLs. + hardcode_libdir_flag_spec_F77='-L$libdir' + allow_undefined_flag_F77=unsupported + always_export_symbols_F77=no + enable_shared_with_static_runtimes_F77=yes + export_symbols_cmds_F77='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS] /s/.* \([^ ]*\)/\1 DATA/'\'' | $SED -e '\''/^[AITW] /s/.* //'\'' | sort | uniq > $export_symbols' + + if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then + archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file (1st line + # is EXPORTS), use it as is; otherwise, prepend... + archive_expsym_cmds_F77='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + ld_shlibs_F77=no + fi + ;; + + interix3*) + hardcode_direct_F77=no + hardcode_shlibpath_var_F77=no + hardcode_libdir_flag_spec_F77='${wl}-rpath,$libdir' + export_dynamic_flag_spec_F77='${wl}-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + archive_cmds_F77='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + archive_expsym_cmds_F77='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + + linux*) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + tmp_addflag= + case $cc_basename,$host_cpu in + pgcc*) # Portland Group C compiler + whole_archive_flag_spec_F77='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' + tmp_addflag=' $pic_flag' + ;; + pgf77* | pgf90* | pgf95*) # Portland Group f77 and f90 compilers + whole_archive_flag_spec_F77='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' + tmp_addflag=' $pic_flag -Mnomain' ;; + ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 + tmp_addflag=' -i_dynamic' ;; + efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 + tmp_addflag=' -i_dynamic -nofor_main' ;; + ifc* | ifort*) # Intel Fortran compiler + tmp_addflag=' -nofor_main' ;; + esac + archive_cmds_F77='$CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + + if test $supports_anon_versioning = yes; then + archive_expsym_cmds_F77='$echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + $echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' + fi + else + ld_shlibs_F77=no + fi + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + archive_cmds_F77='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' + wlarc= + else + archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + fi + ;; + + solaris*) + if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then + ld_shlibs_F77=no + cat <&2 + +*** Warning: The releases 2.8.* of the GNU linker cannot reliably +*** create shared libraries on Solaris systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.9.1 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +EOF + elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + ld_shlibs_F77=no + fi + ;; + + sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) + case `$LD -v 2>&1` in + *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*) + ld_shlibs_F77=no + cat <<_LT_EOF 1>&2 + +*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not +*** reliably create shared libraries on SCO systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.16.91.0.3 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + ;; + *) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + hardcode_libdir_flag_spec_F77='`test -z "$SCOABSPATH" && echo ${wl}-rpath,$libdir`' + archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib' + archive_expsym_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname,-retain-symbols-file,$export_symbols -o $lib' + else + ld_shlibs_F77=no + fi + ;; + esac + ;; + + sunos4*) + archive_cmds_F77='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' + wlarc= + hardcode_direct_F77=yes + hardcode_shlibpath_var_F77=no + ;; + + *) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + ld_shlibs_F77=no + fi + ;; + esac + + if test "$ld_shlibs_F77" = no; then + runpath_var= + hardcode_libdir_flag_spec_F77= + export_dynamic_flag_spec_F77= + whole_archive_flag_spec_F77= + fi + else + # PORTME fill in a description of your system's linker (not GNU ld) + case $host_os in + aix3*) + allow_undefined_flag_F77=unsupported + always_export_symbols_F77=yes + archive_expsym_cmds_F77='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' + # Note: this linker hardcodes the directories in LIBPATH if there + # are no directories specified by -L. + hardcode_minus_L_F77=yes + if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then + # Neither direct hardcoding nor static linking is supported with a + # broken collect2. + hardcode_direct_F77=unsupported + fi + ;; + + aix4* | aix5*) + if test "$host_cpu" = ia64; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag="" + else + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to AIX nm, but means don't demangle with GNU nm + if $NM -V 2>&1 | grep 'GNU' > /dev/null; then + export_symbols_cmds_F77='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols' + else + export_symbols_cmds_F77='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols' + fi + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # need to do runtime linking. + case $host_os in aix4.[23]|aix4.[23].*|aix5*) + for ld_flag in $LDFLAGS; do + if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then + aix_use_runtimelinking=yes + break + fi + done + ;; + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + archive_cmds_F77='' + hardcode_direct_F77=yes + hardcode_libdir_separator_F77=':' + link_all_deplibs_F77=yes + + if test "$GCC" = yes; then + case $host_os in aix4.[012]|aix4.[012].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`${CC} -print-prog-name=collect2` + if test -f "$collect2name" && \ + strings "$collect2name" | grep resolve_lib_name >/dev/null + then + # We have reworked collect2 + hardcode_direct_F77=yes + else + # We have old collect2 + hardcode_direct_F77=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + hardcode_minus_L_F77=yes + hardcode_libdir_flag_spec_F77='-L$libdir' + hardcode_libdir_separator_F77= + fi + ;; + esac + shared_flag='-shared' + if test "$aix_use_runtimelinking" = yes; then + shared_flag="$shared_flag "'${wl}-G' + fi + else + # not using gcc + if test "$host_cpu" = ia64; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test "$aix_use_runtimelinking" = yes; then + shared_flag='${wl}-G' + else + shared_flag='${wl}-bM:SRE' + fi + fi + fi + + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to export. + always_export_symbols_F77=yes + if test "$aix_use_runtimelinking" = yes; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + allow_undefined_flag_F77='-berok' + # Determine the default libpath from the value encoded in an empty executable. + cat >conftest.$ac_ext <<_ACEOF + program main + + end +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_f77_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + +aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'` +# Check for a 64-bit object if we didn't find anything. +if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'`; fi +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi + + hardcode_libdir_flag_spec_F77='${wl}-blibpath:$libdir:'"$aix_libpath" + archive_expsym_cmds_F77="\$CC"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" + else + if test "$host_cpu" = ia64; then + hardcode_libdir_flag_spec_F77='${wl}-R $libdir:/usr/lib:/lib' + allow_undefined_flag_F77="-z nodefs" + archive_expsym_cmds_F77="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an empty executable. + cat >conftest.$ac_ext <<_ACEOF + program main + + end +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_f77_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + +aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'` +# Check for a 64-bit object if we didn't find anything. +if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'`; fi +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi + + hardcode_libdir_flag_spec_F77='${wl}-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + no_undefined_flag_F77=' ${wl}-bernotok' + allow_undefined_flag_F77=' ${wl}-berok' + # Exported symbols can be pulled into shared objects from archives + whole_archive_flag_spec_F77='$convenience' + archive_cmds_need_lc_F77=yes + # This is similar to how AIX traditionally builds its shared libraries. + archive_expsym_cmds_F77="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' + fi + fi + ;; + + amigaos*) + archive_cmds_F77='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + hardcode_libdir_flag_spec_F77='-L$libdir' + hardcode_minus_L_F77=yes + # see comment about different semantics on the GNU ld section + ld_shlibs_F77=no + ;; + + bsdi[45]*) + export_dynamic_flag_spec_F77=-rdynamic + ;; + + cygwin* | mingw* | pw32*) + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + hardcode_libdir_flag_spec_F77=' ' + allow_undefined_flag_F77=unsupported + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=".dll" + # FIXME: Setting linknames here is a bad hack. + archive_cmds_F77='$CC -o $lib $libobjs $compiler_flags `echo "$deplibs" | $SED -e '\''s/ -lc$//'\''` -link -dll~linknames=' + # The linker will automatically build a .lib file if we build a DLL. + old_archive_From_new_cmds_F77='true' + # FIXME: Should let the user specify the lib program. + old_archive_cmds_F77='lib /OUT:$oldlib$oldobjs$old_deplibs' + fix_srcfile_path_F77='`cygpath -w "$srcfile"`' + enable_shared_with_static_runtimes_F77=yes + ;; + + darwin* | rhapsody*) + case $host_os in + rhapsody* | darwin1.[012]) + allow_undefined_flag_F77='${wl}-undefined ${wl}suppress' + ;; + *) # Darwin 1.3 on + if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then + allow_undefined_flag_F77='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' + else + case ${MACOSX_DEPLOYMENT_TARGET} in + 10.[012]) + allow_undefined_flag_F77='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' + ;; + 10.*) + allow_undefined_flag_F77='${wl}-undefined ${wl}dynamic_lookup' + ;; + esac + fi + ;; + esac + archive_cmds_need_lc_F77=no + hardcode_direct_F77=no + hardcode_automatic_F77=yes + hardcode_shlibpath_var_F77=unsupported + whole_archive_flag_spec_F77='' + link_all_deplibs_F77=yes + if test "$GCC" = yes ; then + output_verbose_link_cmd='echo' + archive_cmds_F77='$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring' + module_cmds_F77='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' + # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds + archive_expsym_cmds_F77='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + module_expsym_cmds_F77='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + else + case $cc_basename in + xlc*) + output_verbose_link_cmd='echo' + archive_cmds_F77='$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $verstring' + module_cmds_F77='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' + # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds + archive_expsym_cmds_F77='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + module_expsym_cmds_F77='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + ;; + *) + ld_shlibs_F77=no + ;; + esac + fi + ;; + + dgux*) + archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec_F77='-L$libdir' + hardcode_shlibpath_var_F77=no + ;; + + freebsd1*) + ld_shlibs_F77=no + ;; + + # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor + # support. Future versions do this automatically, but an explicit c++rt0.o + # does not break anything, and helps significantly (at the cost of a little + # extra space). + freebsd2.2*) + archive_cmds_F77='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' + hardcode_libdir_flag_spec_F77='-R$libdir' + hardcode_direct_F77=yes + hardcode_shlibpath_var_F77=no + ;; + + # Unfortunately, older versions of FreeBSD 2 do not have this feature. + freebsd2*) + archive_cmds_F77='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct_F77=yes + hardcode_minus_L_F77=yes + hardcode_shlibpath_var_F77=no + ;; + + # FreeBSD 3 and greater uses gcc -shared to do shared libraries. + freebsd* | kfreebsd*-gnu | dragonfly*) + archive_cmds_F77='$CC -shared -o $lib $libobjs $deplibs $compiler_flags' + hardcode_libdir_flag_spec_F77='-R$libdir' + hardcode_direct_F77=yes + hardcode_shlibpath_var_F77=no + ;; + + hpux9*) + if test "$GCC" = yes; then + archive_cmds_F77='$rm $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + else + archive_cmds_F77='$rm $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + fi + hardcode_libdir_flag_spec_F77='${wl}+b ${wl}$libdir' + hardcode_libdir_separator_F77=: + hardcode_direct_F77=yes + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L_F77=yes + export_dynamic_flag_spec_F77='${wl}-E' + ;; + + hpux10*) + if test "$GCC" = yes -a "$with_gnu_ld" = no; then + archive_cmds_F77='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds_F77='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' + fi + if test "$with_gnu_ld" = no; then + hardcode_libdir_flag_spec_F77='${wl}+b ${wl}$libdir' + hardcode_libdir_separator_F77=: + + hardcode_direct_F77=yes + export_dynamic_flag_spec_F77='${wl}-E' + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L_F77=yes + fi + ;; + + hpux11*) + if test "$GCC" = yes -a "$with_gnu_ld" = no; then + case $host_cpu in + hppa*64*) + archive_cmds_F77='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + archive_cmds_F77='$CC -shared ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + archive_cmds_F77='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + else + case $host_cpu in + hppa*64*) + archive_cmds_F77='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + archive_cmds_F77='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + archive_cmds_F77='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + fi + if test "$with_gnu_ld" = no; then + hardcode_libdir_flag_spec_F77='${wl}+b ${wl}$libdir' + hardcode_libdir_separator_F77=: + + case $host_cpu in + hppa*64*|ia64*) + hardcode_libdir_flag_spec_ld_F77='+b $libdir' + hardcode_direct_F77=no + hardcode_shlibpath_var_F77=no + ;; + *) + hardcode_direct_F77=yes + export_dynamic_flag_spec_F77='${wl}-E' + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L_F77=yes + ;; + esac + fi + ;; + + irix5* | irix6* | nonstopux*) + if test "$GCC" = yes; then + archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + archive_cmds_F77='$LD -shared $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + hardcode_libdir_flag_spec_ld_F77='-rpath $libdir' + fi + hardcode_libdir_flag_spec_F77='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator_F77=: + link_all_deplibs_F77=yes + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + archive_cmds_F77='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out + else + archive_cmds_F77='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF + fi + hardcode_libdir_flag_spec_F77='-R$libdir' + hardcode_direct_F77=yes + hardcode_shlibpath_var_F77=no + ;; + + newsos6) + archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct_F77=yes + hardcode_libdir_flag_spec_F77='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator_F77=: + hardcode_shlibpath_var_F77=no + ;; + + openbsd*) + hardcode_direct_F77=yes + hardcode_shlibpath_var_F77=no + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + archive_cmds_F77='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_F77='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' + hardcode_libdir_flag_spec_F77='${wl}-rpath,$libdir' + export_dynamic_flag_spec_F77='${wl}-E' + else + case $host_os in + openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*) + archive_cmds_F77='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec_F77='-R$libdir' + ;; + *) + archive_cmds_F77='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + hardcode_libdir_flag_spec_F77='${wl}-rpath,$libdir' + ;; + esac + fi + ;; + + os2*) + hardcode_libdir_flag_spec_F77='-L$libdir' + hardcode_minus_L_F77=yes + allow_undefined_flag_F77=unsupported + archive_cmds_F77='$echo "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$echo DATA >> $output_objdir/$libname.def~$echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~$echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' + old_archive_From_new_cmds_F77='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' + ;; + + osf3*) + if test "$GCC" = yes; then + allow_undefined_flag_F77=' ${wl}-expect_unresolved ${wl}\*' + archive_cmds_F77='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + allow_undefined_flag_F77=' -expect_unresolved \*' + archive_cmds_F77='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + fi + hardcode_libdir_flag_spec_F77='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator_F77=: + ;; + + osf4* | osf5*) # as osf3* with the addition of -msym flag + if test "$GCC" = yes; then + allow_undefined_flag_F77=' ${wl}-expect_unresolved ${wl}\*' + archive_cmds_F77='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + hardcode_libdir_flag_spec_F77='${wl}-rpath ${wl}$libdir' + else + allow_undefined_flag_F77=' -expect_unresolved \*' + archive_cmds_F77='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + archive_expsym_cmds_F77='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; echo "-hidden">> $lib.exp~ + $LD -shared${allow_undefined_flag} -input $lib.exp $linker_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib~$rm $lib.exp' + + # Both c and cxx compiler support -rpath directly + hardcode_libdir_flag_spec_F77='-rpath $libdir' + fi + hardcode_libdir_separator_F77=: + ;; + + solaris*) + no_undefined_flag_F77=' -z text' + if test "$GCC" = yes; then + wlarc='${wl}' + archive_cmds_F77='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_F77='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $CC -shared ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$rm $lib.exp' + else + wlarc='' + archive_cmds_F77='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' + archive_expsym_cmds_F77='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp' + fi + hardcode_libdir_flag_spec_F77='-R$libdir' + hardcode_shlibpath_var_F77=no + case $host_os in + solaris2.[0-5] | solaris2.[0-5].*) ;; + *) + # The compiler driver will combine linker options so we + # cannot just pass the convience library names through + # without $wl, iff we do not link with $LD. + # Luckily, gcc supports the same syntax we need for Sun Studio. + # Supported since Solaris 2.6 (maybe 2.5.1?) + case $wlarc in + '') + whole_archive_flag_spec_F77='-z allextract$convenience -z defaultextract' ;; + *) + whole_archive_flag_spec_F77='${wl}-z ${wl}allextract`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}-z ${wl}defaultextract' ;; + esac ;; + esac + link_all_deplibs_F77=yes + ;; + + sunos4*) + if test "x$host_vendor" = xsequent; then + # Use $CC to link under sequent, because it throws in some extra .o + # files that make .init and .fini sections work. + archive_cmds_F77='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds_F77='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' + fi + hardcode_libdir_flag_spec_F77='-L$libdir' + hardcode_direct_F77=yes + hardcode_minus_L_F77=yes + hardcode_shlibpath_var_F77=no + ;; + + sysv4) + case $host_vendor in + sni) + archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct_F77=yes # is this really true??? + ;; + siemens) + ## LD is ld it makes a PLAMLIB + ## CC just makes a GrossModule. + archive_cmds_F77='$LD -G -o $lib $libobjs $deplibs $linker_flags' + reload_cmds_F77='$CC -r -o $output$reload_objs' + hardcode_direct_F77=no + ;; + motorola) + archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct_F77=no #Motorola manual says yes, but my tests say they lie + ;; + esac + runpath_var='LD_RUN_PATH' + hardcode_shlibpath_var_F77=no + ;; + + sysv4.3*) + archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_shlibpath_var_F77=no + export_dynamic_flag_spec_F77='-Bexport' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_shlibpath_var_F77=no + runpath_var=LD_RUN_PATH + hardcode_runpath_var=yes + ld_shlibs_F77=yes + fi + ;; + + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7*) + no_undefined_flag_F77='${wl}-z,text' + archive_cmds_need_lc_F77=no + hardcode_shlibpath_var_F77=no + runpath_var='LD_RUN_PATH' + + if test "$GCC" = yes; then + archive_cmds_F77='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_F77='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds_F77='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_F77='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + sysv5* | sco3.2v5* | sco5v6*) + # Note: We can NOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + no_undefined_flag_F77='${wl}-z,text' + allow_undefined_flag_F77='${wl}-z,nodefs' + archive_cmds_need_lc_F77=no + hardcode_shlibpath_var_F77=no + hardcode_libdir_flag_spec_F77='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`' + hardcode_libdir_separator_F77=':' + link_all_deplibs_F77=yes + export_dynamic_flag_spec_F77='${wl}-Bexport' + runpath_var='LD_RUN_PATH' + + if test "$GCC" = yes; then + archive_cmds_F77='$CC -shared ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_F77='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds_F77='$CC -G ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_F77='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + uts4*) + archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec_F77='-L$libdir' + hardcode_shlibpath_var_F77=no + ;; + + *) + ld_shlibs_F77=no + ;; + esac + fi + +{ echo "$as_me:$LINENO: result: $ld_shlibs_F77" >&5 +echo "${ECHO_T}$ld_shlibs_F77" >&6; } +test "$ld_shlibs_F77" = no && can_build_shared=no + +# +# Do we need to explicitly link libc? +# +case "x$archive_cmds_need_lc_F77" in +x|xyes) + # Assume -lc should be added + archive_cmds_need_lc_F77=yes + + if test "$enable_shared" = yes && test "$GCC" = yes; then + case $archive_cmds_F77 in + *'~'*) + # FIXME: we may have to deal with multi-command sequences. + ;; + '$CC '*) + # Test whether the compiler implicitly links with -lc since on some + # systems, -lgcc has to come before -lc. If gcc already passes -lc + # to ld, don't add -lc before -lgcc. + { echo "$as_me:$LINENO: checking whether -lc should be explicitly linked in" >&5 +echo $ECHO_N "checking whether -lc should be explicitly linked in... $ECHO_C" >&6; } + $rm conftest* + printf "$lt_simple_compile_test_code" > conftest.$ac_ext + + if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } 2>conftest.err; then + soname=conftest + lib=conftest + libobjs=conftest.$ac_objext + deplibs= + wl=$lt_prog_compiler_wl_F77 + pic_flag=$lt_prog_compiler_pic_F77 + compiler_flags=-v + linker_flags=-v + verstring= + output_objdir=. + libname=conftest + lt_save_allow_undefined_flag=$allow_undefined_flag_F77 + allow_undefined_flag_F77= + if { (eval echo "$as_me:$LINENO: \"$archive_cmds_F77 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1\"") >&5 + (eval $archive_cmds_F77 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + then + archive_cmds_need_lc_F77=no + else + archive_cmds_need_lc_F77=yes + fi + allow_undefined_flag_F77=$lt_save_allow_undefined_flag + else + cat conftest.err 1>&5 + fi + $rm conftest* + { echo "$as_me:$LINENO: result: $archive_cmds_need_lc_F77" >&5 +echo "${ECHO_T}$archive_cmds_need_lc_F77" >&6; } + ;; + esac + fi + ;; +esac + +{ echo "$as_me:$LINENO: checking dynamic linker characteristics" >&5 +echo $ECHO_N "checking dynamic linker characteristics... $ECHO_C" >&6; } +library_names_spec= +libname_spec='lib$name' +soname_spec= +shrext_cmds=".so" +postinstall_cmds= +postuninstall_cmds= +finish_cmds= +finish_eval= +shlibpath_var= +shlibpath_overrides_runpath=unknown +version_type=none +dynamic_linker="$host_os ld.so" +sys_lib_dlsearch_path_spec="/lib /usr/lib" +if test "$GCC" = yes; then + sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` + if echo "$sys_lib_search_path_spec" | grep ';' >/dev/null ; then + # if the path contains ";" then we assume it to be the separator + # otherwise default to the standard path separator (i.e. ":") - it is + # assumed that no part of a normal pathname contains ";" but that should + # okay in the real world where ";" in dirpaths is itself problematic. + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi +else + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" +fi +need_lib_prefix=unknown +hardcode_into_libs=no + +# when you set need_version to no, make sure it does not cause -set_version +# flags to be left without arguments +need_version=unknown + +case $host_os in +aix3*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' + shlibpath_var=LIBPATH + + # AIX 3 has no versioning support, so we append a major version to the name. + soname_spec='${libname}${release}${shared_ext}$major' + ;; + +aix4* | aix5*) + version_type=linux + need_lib_prefix=no + need_version=no + hardcode_into_libs=yes + if test "$host_cpu" = ia64; then + # AIX 5 supports IA64 + library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + else + # With GCC up to 2.95.x, collect2 would create an import file + # for dependence libraries. The import file would start with + # the line `#! .'. This would cause the generated library to + # depend on `.', always an invalid library. This was fixed in + # development snapshots of GCC prior to 3.0. + case $host_os in + aix4 | aix4.[01] | aix4.[01].*) + if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' + echo ' yes ' + echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then + : + else + can_build_shared=no + fi + ;; + esac + # AIX (on Power*) has no versioning support, so currently we can not hardcode correct + # soname into executable. Probably we can add versioning support to + # collect2, so additional links can be useful in future. + if test "$aix_use_runtimelinking" = yes; then + # If using run time linking (on AIX 4.2 or later) use lib.so + # instead of lib.a to let people know that these are not + # typical AIX shared libraries. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + else + # We preserve .a as extension for shared libraries through AIX4.2 + # and later when we are not doing run time linking. + library_names_spec='${libname}${release}.a $libname.a' + soname_spec='${libname}${release}${shared_ext}$major' + fi + shlibpath_var=LIBPATH + fi + ;; + +amigaos*) + library_names_spec='$libname.ixlibrary $libname.a' + # Create ${libname}_ixlibrary.a entries in /sys/libs. + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' + ;; + +beos*) + library_names_spec='${libname}${shared_ext}' + dynamic_linker="$host_os ld.so" + shlibpath_var=LIBRARY_PATH + ;; + +bsdi[45]*) + version_type=linux + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" + sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" + # the default ld.so.conf also contains /usr/contrib/lib and + # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow + # libtool to hard-code these into programs + ;; + +cygwin* | mingw* | pw32*) + version_type=windows + shrext_cmds=".dll" + need_version=no + need_lib_prefix=no + + case $GCC,$host_os in + yes,cygwin* | yes,mingw* | yes,pw32*) + library_names_spec='$libname.dll.a' + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \${file}`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $rm \$dlpath' + shlibpath_overrides_runpath=yes + + case $host_os in + cygwin*) + # Cygwin DLLs use 'cyg' prefix rather than 'lib' + soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib" + ;; + mingw*) + # MinGW DLLs use traditional 'lib' prefix + soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` + if echo "$sys_lib_search_path_spec" | grep ';[c-zC-Z]:/' >/dev/null; then + # It is most probably a Windows format PATH printed by + # mingw gcc, but we are running on Cygwin. Gcc prints its search + # path with ; separators, and with drive letters. We can handle the + # drive letters (cygwin fileutils understands them), so leave them, + # especially as we might pass files found there to a mingw objdump, + # which wouldn't understand a cygwinified path. Ahh. + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi + ;; + pw32*) + # pw32 DLLs use 'pw' prefix rather than 'lib' + library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + ;; + esac + ;; + + *) + library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib' + ;; + esac + dynamic_linker='Win32 ld.exe' + # FIXME: first we should search . and the directory the executable is in + shlibpath_var=PATH + ;; + +darwin* | rhapsody*) + dynamic_linker="$host_os dyld" + version_type=darwin + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext' + soname_spec='${libname}${release}${major}$shared_ext' + shlibpath_overrides_runpath=yes + shlibpath_var=DYLD_LIBRARY_PATH + shrext_cmds='.dylib' + # Apple's gcc prints 'gcc -print-search-dirs' doesn't operate the same. + if test "$GCC" = yes; then + sys_lib_search_path_spec=`$CC -print-search-dirs | tr "\n" "$PATH_SEPARATOR" | sed -e 's/libraries:/@libraries:/' | tr "@" "\n" | grep "^libraries:" | sed -e "s/^libraries://" -e "s,=/,/,g" -e "s,$PATH_SEPARATOR, ,g" -e "s,.*,& /lib /usr/lib /usr/local/lib,g"` + else + sys_lib_search_path_spec='/lib /usr/lib /usr/local/lib' + fi + sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' + ;; + +dgux*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +freebsd1*) + dynamic_linker=no + ;; + +kfreebsd*-gnu) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='GNU ld.so' + ;; + +freebsd* | dragonfly*) + # DragonFly does not have aout. When/if they implement a new + # versioning mechanism, adjust this. + if test -x /usr/bin/objformat; then + objformat=`/usr/bin/objformat` + else + case $host_os in + freebsd[123]*) objformat=aout ;; + *) objformat=elf ;; + esac + fi + version_type=freebsd-$objformat + case $version_type in + freebsd-elf*) + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + need_version=no + need_lib_prefix=no + ;; + freebsd-*) + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' + need_version=yes + ;; + esac + shlibpath_var=LD_LIBRARY_PATH + case $host_os in + freebsd2*) + shlibpath_overrides_runpath=yes + ;; + freebsd3.[01]* | freebsdelf3.[01]*) + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ + freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + freebsd*) # from 4.6 on + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + esac + ;; + +gnu*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + hardcode_into_libs=yes + ;; + +hpux9* | hpux10* | hpux11*) + # Give a soname corresponding to the major version so that dld.sl refuses to + # link against other versions. + version_type=sunos + need_lib_prefix=no + need_version=no + case $host_cpu in + ia64*) + shrext_cmds='.so' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.so" + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + if test "X$HPUX_IA64_MODE" = X32; then + sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" + else + sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" + fi + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + hppa*64*) + shrext_cmds='.sl' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.sl" + shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + *) + shrext_cmds='.sl' + dynamic_linker="$host_os dld.sl" + shlibpath_var=SHLIB_PATH + shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + ;; + esac + # HP-UX runs *really* slowly unless shared libraries are mode 555. + postinstall_cmds='chmod 555 $lib' + ;; + +interix3*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +irix5* | irix6* | nonstopux*) + case $host_os in + nonstopux*) version_type=nonstopux ;; + *) + if test "$lt_cv_prog_gnu_ld" = yes; then + version_type=linux + else + version_type=irix + fi ;; + esac + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' + case $host_os in + irix5* | nonstopux*) + libsuff= shlibsuff= + ;; + *) + case $LD in # libtool.m4 will add one of these switches to LD + *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") + libsuff= shlibsuff= libmagic=32-bit;; + *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") + libsuff=32 shlibsuff=N32 libmagic=N32;; + *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") + libsuff=64 shlibsuff=64 libmagic=64-bit;; + *) libsuff= shlibsuff= libmagic=never-match;; + esac + ;; + esac + shlibpath_var=LD_LIBRARY${shlibsuff}_PATH + shlibpath_overrides_runpath=no + sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" + sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" + hardcode_into_libs=yes + ;; + +# No shared lib support for Linux oldld, aout, or coff. +linux*oldld* | linux*aout* | linux*coff*) + dynamic_linker=no + ;; + +# This must be Linux ELF. +linux*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + # Append ld.so.conf contents to the search path + if test -f /etc/ld.so.conf; then + lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '` + sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" + fi + + # We used to test for /lib/ld.so.1 and disable shared libraries on + # powerpc, because MkLinux only supported shared libraries with the + # GNU dynamic linker. Since this was broken with cross compilers, + # most powerpc-linux boxes support dynamic linking these days and + # people can always --disable-shared, the test was removed, and we + # assume the GNU/Linux dynamic linker is in use. + dynamic_linker='GNU/Linux ld.so' + ;; + +knetbsd*-gnu) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='GNU ld.so' + ;; + +netbsd*) + version_type=sunos + need_lib_prefix=no + need_version=no + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + dynamic_linker='NetBSD (a.out) ld.so' + else + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='NetBSD ld.elf_so' + fi + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + +newsos6) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +nto-qnx*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +openbsd*) + version_type=sunos + sys_lib_dlsearch_path_spec="/usr/lib" + need_lib_prefix=no + # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. + case $host_os in + openbsd3.3 | openbsd3.3.*) need_version=yes ;; + *) need_version=no ;; + esac + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + shlibpath_var=LD_LIBRARY_PATH + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + case $host_os in + openbsd2.[89] | openbsd2.[89].*) + shlibpath_overrides_runpath=no + ;; + *) + shlibpath_overrides_runpath=yes + ;; + esac + else + shlibpath_overrides_runpath=yes + fi + ;; + +os2*) + libname_spec='$name' + shrext_cmds=".dll" + need_lib_prefix=no + library_names_spec='$libname${shared_ext} $libname.a' + dynamic_linker='OS/2 ld.exe' + shlibpath_var=LIBPATH + ;; + +osf3* | osf4* | osf5*) + version_type=osf + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" + sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" + ;; + +solaris*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + # ldd complains unless libraries are executable + postinstall_cmds='chmod +x $lib' + ;; + +sunos4*) + version_type=sunos + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + if test "$with_gnu_ld" = yes; then + need_lib_prefix=no + fi + need_version=yes + ;; + +sysv4 | sysv4.3*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + case $host_vendor in + sni) + shlibpath_overrides_runpath=no + need_lib_prefix=no + export_dynamic_flag_spec='${wl}-Blargedynsym' + runpath_var=LD_RUN_PATH + ;; + siemens) + need_lib_prefix=no + ;; + motorola) + need_lib_prefix=no + need_version=no + shlibpath_overrides_runpath=no + sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' + ;; + esac + ;; + +sysv4*MP*) + if test -d /usr/nec ;then + version_type=linux + library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' + soname_spec='$libname${shared_ext}.$major' + shlibpath_var=LD_LIBRARY_PATH + fi + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + version_type=freebsd-elf + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + hardcode_into_libs=yes + if test "$with_gnu_ld" = yes; then + sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' + shlibpath_overrides_runpath=no + else + sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' + shlibpath_overrides_runpath=yes + case $host_os in + sco3.2v5*) + sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" + ;; + esac + fi + sys_lib_dlsearch_path_spec='/usr/lib' + ;; + +uts4*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +*) + dynamic_linker=no + ;; +esac +{ echo "$as_me:$LINENO: result: $dynamic_linker" >&5 +echo "${ECHO_T}$dynamic_linker" >&6; } +test "$dynamic_linker" = no && can_build_shared=no + +variables_saved_for_relink="PATH $shlibpath_var $runpath_var" +if test "$GCC" = yes; then + variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" +fi + +{ echo "$as_me:$LINENO: checking how to hardcode library paths into programs" >&5 +echo $ECHO_N "checking how to hardcode library paths into programs... $ECHO_C" >&6; } +hardcode_action_F77= +if test -n "$hardcode_libdir_flag_spec_F77" || \ + test -n "$runpath_var_F77" || \ + test "X$hardcode_automatic_F77" = "Xyes" ; then + + # We can hardcode non-existant directories. + if test "$hardcode_direct_F77" != no && + # If the only mechanism to avoid hardcoding is shlibpath_var, we + # have to relink, otherwise we might link with an installed library + # when we should be linking with a yet-to-be-installed one + ## test "$_LT_AC_TAGVAR(hardcode_shlibpath_var, F77)" != no && + test "$hardcode_minus_L_F77" != no; then + # Linking always hardcodes the temporary library directory. + hardcode_action_F77=relink + else + # We can link without hardcoding, and we can hardcode nonexisting dirs. + hardcode_action_F77=immediate + fi +else + # We cannot hardcode anything, or else we can only hardcode existing + # directories. + hardcode_action_F77=unsupported +fi +{ echo "$as_me:$LINENO: result: $hardcode_action_F77" >&5 +echo "${ECHO_T}$hardcode_action_F77" >&6; } + +if test "$hardcode_action_F77" = relink; then + # Fast installation is not supported + enable_fast_install=no +elif test "$shlibpath_overrides_runpath" = yes || + test "$enable_shared" = no; then + # Fast installation is not necessary + enable_fast_install=needless +fi + + +# The else clause should only fire when bootstrapping the +# libtool distribution, otherwise you forgot to ship ltmain.sh +# with your package, and you will get complaints that there are +# no rules to generate ltmain.sh. +if test -f "$ltmain"; then + # See if we are running on zsh, and set the options which allow our commands through + # without removal of \ escapes. + if test -n "${ZSH_VERSION+set}" ; then + setopt NO_GLOB_SUBST + fi + # Now quote all the things that may contain metacharacters while being + # careful not to overquote the AC_SUBSTed values. We take copies of the + # variables and quote the copies for generation of the libtool script. + for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC LTCFLAGS NM \ + SED SHELL STRIP \ + libname_spec library_names_spec soname_spec extract_expsyms_cmds \ + old_striplib striplib file_magic_cmd finish_cmds finish_eval \ + deplibs_check_method reload_flag reload_cmds need_locks \ + lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \ + lt_cv_sys_global_symbol_to_c_name_address \ + sys_lib_search_path_spec sys_lib_dlsearch_path_spec \ + old_postinstall_cmds old_postuninstall_cmds \ + compiler_F77 \ + CC_F77 \ + LD_F77 \ + lt_prog_compiler_wl_F77 \ + lt_prog_compiler_pic_F77 \ + lt_prog_compiler_static_F77 \ + lt_prog_compiler_no_builtin_flag_F77 \ + export_dynamic_flag_spec_F77 \ + thread_safe_flag_spec_F77 \ + whole_archive_flag_spec_F77 \ + enable_shared_with_static_runtimes_F77 \ + old_archive_cmds_F77 \ + old_archive_from_new_cmds_F77 \ + predep_objects_F77 \ + postdep_objects_F77 \ + predeps_F77 \ + postdeps_F77 \ + compiler_lib_search_path_F77 \ + archive_cmds_F77 \ + archive_expsym_cmds_F77 \ + postinstall_cmds_F77 \ + postuninstall_cmds_F77 \ + old_archive_from_expsyms_cmds_F77 \ + allow_undefined_flag_F77 \ + no_undefined_flag_F77 \ + export_symbols_cmds_F77 \ + hardcode_libdir_flag_spec_F77 \ + hardcode_libdir_flag_spec_ld_F77 \ + hardcode_libdir_separator_F77 \ + hardcode_automatic_F77 \ + module_cmds_F77 \ + module_expsym_cmds_F77 \ + lt_cv_prog_compiler_c_o_F77 \ + exclude_expsyms_F77 \ + include_expsyms_F77; do + + case $var in + old_archive_cmds_F77 | \ + old_archive_from_new_cmds_F77 | \ + archive_cmds_F77 | \ + archive_expsym_cmds_F77 | \ + module_cmds_F77 | \ + module_expsym_cmds_F77 | \ + old_archive_from_expsyms_cmds_F77 | \ + export_symbols_cmds_F77 | \ + extract_expsyms_cmds | reload_cmds | finish_cmds | \ + postinstall_cmds | postuninstall_cmds | \ + old_postinstall_cmds | old_postuninstall_cmds | \ + sys_lib_search_path_spec | sys_lib_dlsearch_path_spec) + # Double-quote double-evaled strings. + eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\"" + ;; + *) + eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\"" + ;; + esac + done + + case $lt_echo in + *'\$0 --fallback-echo"') + lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'` + ;; + esac + +cfgfile="$ofile" + + cat <<__EOF__ >> "$cfgfile" +# ### BEGIN LIBTOOL TAG CONFIG: $tagname + +# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: + +# Shell to use when invoking shell scripts. +SHELL=$lt_SHELL + +# Whether or not to build shared libraries. +build_libtool_libs=$enable_shared + +# Whether or not to build static libraries. +build_old_libs=$enable_static + +# Whether or not to add -lc for building shared libraries. +build_libtool_need_lc=$archive_cmds_need_lc_F77 + +# Whether or not to disallow shared libs when runtime libs are static +allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes_F77 + +# Whether or not to optimize for fast installation. +fast_install=$enable_fast_install + +# The host system. +host_alias=$host_alias +host=$host +host_os=$host_os + +# The build system. +build_alias=$build_alias +build=$build +build_os=$build_os + +# An echo program that does not interpret backslashes. +echo=$lt_echo + +# The archiver. +AR=$lt_AR +AR_FLAGS=$lt_AR_FLAGS + +# A C compiler. +LTCC=$lt_LTCC + +# LTCC compiler flags. +LTCFLAGS=$lt_LTCFLAGS + +# A language-specific compiler. +CC=$lt_compiler_F77 + +# Is the compiler the GNU C compiler? +with_gcc=$GCC_F77 + +# An ERE matcher. +EGREP=$lt_EGREP + +# The linker used to build libraries. +LD=$lt_LD_F77 + +# Whether we need hard or soft links. +LN_S=$lt_LN_S + +# A BSD-compatible nm program. +NM=$lt_NM + +# A symbol stripping program +STRIP=$lt_STRIP + +# Used to examine libraries when file_magic_cmd begins "file" +MAGIC_CMD=$MAGIC_CMD + +# Used on cygwin: DLL creation program. +DLLTOOL="$DLLTOOL" + +# Used on cygwin: object dumper. +OBJDUMP="$OBJDUMP" + +# Used on cygwin: assembler. +AS="$AS" + +# The name of the directory that contains temporary libtool files. +objdir=$objdir + +# How to create reloadable object files. +reload_flag=$lt_reload_flag +reload_cmds=$lt_reload_cmds + +# How to pass a linker flag through the compiler. +wl=$lt_lt_prog_compiler_wl_F77 + +# Object file suffix (normally "o"). +objext="$ac_objext" + +# Old archive suffix (normally "a"). +libext="$libext" + +# Shared library suffix (normally ".so"). +shrext_cmds='$shrext_cmds' + +# Executable file suffix (normally ""). +exeext="$exeext" + +# Additional compiler flags for building library objects. +pic_flag=$lt_lt_prog_compiler_pic_F77 +pic_mode=$pic_mode + +# What is the maximum length of a command? +max_cmd_len=$lt_cv_sys_max_cmd_len + +# Does compiler simultaneously support -c and -o options? +compiler_c_o=$lt_lt_cv_prog_compiler_c_o_F77 + +# Must we lock files when doing compilation? +need_locks=$lt_need_locks + +# Do we need the lib prefix for modules? +need_lib_prefix=$need_lib_prefix + +# Do we need a version for libraries? +need_version=$need_version + +# Whether dlopen is supported. +dlopen_support=$enable_dlopen + +# Whether dlopen of programs is supported. +dlopen_self=$enable_dlopen_self + +# Whether dlopen of statically linked programs is supported. +dlopen_self_static=$enable_dlopen_self_static + +# Compiler flag to prevent dynamic linking. +link_static_flag=$lt_lt_prog_compiler_static_F77 + +# Compiler flag to turn off builtin functions. +no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_F77 + +# Compiler flag to allow reflexive dlopens. +export_dynamic_flag_spec=$lt_export_dynamic_flag_spec_F77 + +# Compiler flag to generate shared objects directly from archives. +whole_archive_flag_spec=$lt_whole_archive_flag_spec_F77 + +# Compiler flag to generate thread-safe objects. +thread_safe_flag_spec=$lt_thread_safe_flag_spec_F77 + +# Library versioning type. +version_type=$version_type + +# Format of library name prefix. +libname_spec=$lt_libname_spec + +# List of archive names. First name is the real one, the rest are links. +# The last name is the one that the linker finds with -lNAME. +library_names_spec=$lt_library_names_spec + +# The coded name of the library, if different from the real name. +soname_spec=$lt_soname_spec + +# Commands used to build and install an old-style archive. +RANLIB=$lt_RANLIB +old_archive_cmds=$lt_old_archive_cmds_F77 +old_postinstall_cmds=$lt_old_postinstall_cmds +old_postuninstall_cmds=$lt_old_postuninstall_cmds + +# Create an old-style archive from a shared archive. +old_archive_from_new_cmds=$lt_old_archive_from_new_cmds_F77 + +# Create a temporary old-style archive to link instead of a shared archive. +old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds_F77 + +# Commands used to build and install a shared archive. +archive_cmds=$lt_archive_cmds_F77 +archive_expsym_cmds=$lt_archive_expsym_cmds_F77 +postinstall_cmds=$lt_postinstall_cmds +postuninstall_cmds=$lt_postuninstall_cmds + +# Commands used to build a loadable module (assumed same as above if empty) +module_cmds=$lt_module_cmds_F77 +module_expsym_cmds=$lt_module_expsym_cmds_F77 + +# Commands to strip libraries. +old_striplib=$lt_old_striplib +striplib=$lt_striplib + +# Dependencies to place before the objects being linked to create a +# shared library. +predep_objects=$lt_predep_objects_F77 + +# Dependencies to place after the objects being linked to create a +# shared library. +postdep_objects=$lt_postdep_objects_F77 + +# Dependencies to place before the objects being linked to create a +# shared library. +predeps=$lt_predeps_F77 + +# Dependencies to place after the objects being linked to create a +# shared library. +postdeps=$lt_postdeps_F77 + +# The library search path used internally by the compiler when linking +# a shared library. +compiler_lib_search_path=$lt_compiler_lib_search_path_F77 + +# Method to check whether dependent libraries are shared objects. +deplibs_check_method=$lt_deplibs_check_method + +# Command to use when deplibs_check_method == file_magic. +file_magic_cmd=$lt_file_magic_cmd + +# Flag that allows shared libraries with undefined symbols to be built. +allow_undefined_flag=$lt_allow_undefined_flag_F77 + +# Flag that forces no undefined symbols. +no_undefined_flag=$lt_no_undefined_flag_F77 + +# Commands used to finish a libtool library installation in a directory. +finish_cmds=$lt_finish_cmds + +# Same as above, but a single script fragment to be evaled but not shown. +finish_eval=$lt_finish_eval + +# Take the output of nm and produce a listing of raw symbols and C names. +global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe + +# Transform the output of nm in a proper C declaration +global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl + +# Transform the output of nm in a C name address pair +global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address + +# This is the shared library runtime path variable. +runpath_var=$runpath_var + +# This is the shared library path variable. +shlibpath_var=$shlibpath_var + +# Is shlibpath searched before the hard-coded library search path? +shlibpath_overrides_runpath=$shlibpath_overrides_runpath + +# How to hardcode a shared library path into an executable. +hardcode_action=$hardcode_action_F77 + +# Whether we should hardcode library paths into libraries. +hardcode_into_libs=$hardcode_into_libs + +# Flag to hardcode \$libdir into a binary during linking. +# This must work even if \$libdir does not exist. +hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_F77 + +# If ld is used when linking, flag to hardcode \$libdir into +# a binary during linking. This must work even if \$libdir does +# not exist. +hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld_F77 + +# Whether we need a single -rpath flag with a separated argument. +hardcode_libdir_separator=$lt_hardcode_libdir_separator_F77 + +# Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the +# resulting binary. +hardcode_direct=$hardcode_direct_F77 + +# Set to yes if using the -LDIR flag during linking hardcodes DIR into the +# resulting binary. +hardcode_minus_L=$hardcode_minus_L_F77 + +# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into +# the resulting binary. +hardcode_shlibpath_var=$hardcode_shlibpath_var_F77 + +# Set to yes if building a shared library automatically hardcodes DIR into the library +# and all subsequent libraries and executables linked against it. +hardcode_automatic=$hardcode_automatic_F77 + +# Variables whose values should be saved in libtool wrapper scripts and +# restored at relink time. +variables_saved_for_relink="$variables_saved_for_relink" + +# Whether libtool must link a program against all its dependency libraries. +link_all_deplibs=$link_all_deplibs_F77 + +# Compile-time system search path for libraries +sys_lib_search_path_spec=$lt_sys_lib_search_path_spec + +# Run-time system search path for libraries +sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec + +# Fix the shell variable \$srcfile for the compiler. +fix_srcfile_path="$fix_srcfile_path_F77" + +# Set to yes if exported symbols are required. +always_export_symbols=$always_export_symbols_F77 + +# The commands to list exported symbols. +export_symbols_cmds=$lt_export_symbols_cmds_F77 + +# The commands to extract the exported symbol list from a shared archive. +extract_expsyms_cmds=$lt_extract_expsyms_cmds + +# Symbols that should not be listed in the preloaded symbols. +exclude_expsyms=$lt_exclude_expsyms_F77 + +# Symbols that must always be exported. +include_expsyms=$lt_include_expsyms_F77 + +# ### END LIBTOOL TAG CONFIG: $tagname + +__EOF__ + + +else + # If there is no Makefile yet, we rely on a make rule to execute + # `config.status --recheck' to rerun these tests and create the + # libtool script then. + ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'` + if test -f "$ltmain_in"; then + test -f Makefile && make "$ltmain" + fi +fi + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +CC="$lt_save_CC" + + else + tagname="" + fi + ;; + + GCJ) + if test -n "$GCJ" && test "X$GCJ" != "Xno"; then + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +# Source file extension for Java test sources. +ac_ext=java + +# Object file extension for compiled Java test sources. +objext=o +objext_GCJ=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="class foo {}\n" + +# Code to be used in simple link tests +lt_simple_link_test_code='public class conftest { public static void main(String[] argv) {}; }\n' + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC + + +# save warnings/boilerplate of simple test code +ac_outfile=conftest.$ac_objext +printf "$lt_simple_compile_test_code" >conftest.$ac_ext +eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_compiler_boilerplate=`cat conftest.err` +$rm conftest* + +ac_outfile=conftest.$ac_objext +printf "$lt_simple_link_test_code" >conftest.$ac_ext +eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_linker_boilerplate=`cat conftest.err` +$rm conftest* + + +# Allow CC to be a program name with arguments. +lt_save_CC="$CC" +CC=${GCJ-"gcj"} +compiler=$CC +compiler_GCJ=$CC +for cc_temp in $compiler""; do + case $cc_temp in + compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; + distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; + \-*) ;; + *) break;; + esac +done +cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` + + +# GCJ did not exist at the time GCC didn't implicitly link libc in. +archive_cmds_need_lc_GCJ=no + +old_archive_cmds_GCJ=$old_archive_cmds + + +lt_prog_compiler_no_builtin_flag_GCJ= + +if test "$GCC" = yes; then + lt_prog_compiler_no_builtin_flag_GCJ=' -fno-builtin' + + +{ echo "$as_me:$LINENO: checking if $compiler supports -fno-rtti -fno-exceptions" >&5 +echo $ECHO_N "checking if $compiler supports -fno-rtti -fno-exceptions... $ECHO_C" >&6; } +if test "${lt_cv_prog_compiler_rtti_exceptions+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + lt_cv_prog_compiler_rtti_exceptions=no + ac_outfile=conftest.$ac_objext + printf "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="-fno-rtti -fno-exceptions" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:24290: $lt_compile\"" >&5) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&5 + echo "$as_me:24294: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings other than the usual output. + $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler_rtti_exceptions=yes + fi + fi + $rm conftest* + +fi +{ echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_rtti_exceptions" >&5 +echo "${ECHO_T}$lt_cv_prog_compiler_rtti_exceptions" >&6; } + +if test x"$lt_cv_prog_compiler_rtti_exceptions" = xyes; then + lt_prog_compiler_no_builtin_flag_GCJ="$lt_prog_compiler_no_builtin_flag_GCJ -fno-rtti -fno-exceptions" +else + : +fi + +fi + +lt_prog_compiler_wl_GCJ= +lt_prog_compiler_pic_GCJ= +lt_prog_compiler_static_GCJ= + +{ echo "$as_me:$LINENO: checking for $compiler option to produce PIC" >&5 +echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6; } + + if test "$GCC" = yes; then + lt_prog_compiler_wl_GCJ='-Wl,' + lt_prog_compiler_static_GCJ='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + lt_prog_compiler_static_GCJ='-Bstatic' + fi + ;; + + amigaos*) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the `-m68020' flag to GCC prevents building anything better, + # like `-m68040'. + lt_prog_compiler_pic_GCJ='-m68020 -resident32 -malways-restore-a4' + ;; + + beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + + mingw* | pw32* | os2*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + lt_prog_compiler_pic_GCJ='-DDLL_EXPORT' + ;; + + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + lt_prog_compiler_pic_GCJ='-fno-common' + ;; + + interix3*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + + msdosdjgpp*) + # Just because we use GCC doesn't mean we suddenly get shared libraries + # on systems that don't support them. + lt_prog_compiler_can_build_shared_GCJ=no + enable_shared=no + ;; + + sysv4*MP*) + if test -d /usr/nec; then + lt_prog_compiler_pic_GCJ=-Kconform_pic + fi + ;; + + hpux*) + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + lt_prog_compiler_pic_GCJ='-fPIC' + ;; + esac + ;; + + *) + lt_prog_compiler_pic_GCJ='-fPIC' + ;; + esac + else + # PORTME Check for flag to pass linker flags through the system compiler. + case $host_os in + aix*) + lt_prog_compiler_wl_GCJ='-Wl,' + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + lt_prog_compiler_static_GCJ='-Bstatic' + else + lt_prog_compiler_static_GCJ='-bnso -bI:/lib/syscalls.exp' + fi + ;; + darwin*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + case $cc_basename in + xlc*) + lt_prog_compiler_pic_GCJ='-qnocommon' + lt_prog_compiler_wl_GCJ='-Wl,' + ;; + esac + ;; + + mingw* | pw32* | os2*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + lt_prog_compiler_pic_GCJ='-DDLL_EXPORT' + ;; + + hpux9* | hpux10* | hpux11*) + lt_prog_compiler_wl_GCJ='-Wl,' + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + lt_prog_compiler_pic_GCJ='+Z' + ;; + esac + # Is there a better lt_prog_compiler_static that works with the bundled CC? + lt_prog_compiler_static_GCJ='${wl}-a ${wl}archive' + ;; + + irix5* | irix6* | nonstopux*) + lt_prog_compiler_wl_GCJ='-Wl,' + # PIC (with -KPIC) is the default. + lt_prog_compiler_static_GCJ='-non_shared' + ;; + + newsos6) + lt_prog_compiler_pic_GCJ='-KPIC' + lt_prog_compiler_static_GCJ='-Bstatic' + ;; + + linux*) + case $cc_basename in + icc* | ecc*) + lt_prog_compiler_wl_GCJ='-Wl,' + lt_prog_compiler_pic_GCJ='-KPIC' + lt_prog_compiler_static_GCJ='-static' + ;; + pgcc* | pgf77* | pgf90* | pgf95*) + # Portland Group compilers (*not* the Pentium gcc compiler, + # which looks to be a dead project) + lt_prog_compiler_wl_GCJ='-Wl,' + lt_prog_compiler_pic_GCJ='-fpic' + lt_prog_compiler_static_GCJ='-Bstatic' + ;; + ccc*) + lt_prog_compiler_wl_GCJ='-Wl,' + # All Alpha code is PIC. + lt_prog_compiler_static_GCJ='-non_shared' + ;; + esac + ;; + + osf3* | osf4* | osf5*) + lt_prog_compiler_wl_GCJ='-Wl,' + # All OSF/1 code is PIC. + lt_prog_compiler_static_GCJ='-non_shared' + ;; + + solaris*) + lt_prog_compiler_pic_GCJ='-KPIC' + lt_prog_compiler_static_GCJ='-Bstatic' + case $cc_basename in + f77* | f90* | f95*) + lt_prog_compiler_wl_GCJ='-Qoption ld ';; + *) + lt_prog_compiler_wl_GCJ='-Wl,';; + esac + ;; + + sunos4*) + lt_prog_compiler_wl_GCJ='-Qoption ld ' + lt_prog_compiler_pic_GCJ='-PIC' + lt_prog_compiler_static_GCJ='-Bstatic' + ;; + + sysv4 | sysv4.2uw2* | sysv4.3*) + lt_prog_compiler_wl_GCJ='-Wl,' + lt_prog_compiler_pic_GCJ='-KPIC' + lt_prog_compiler_static_GCJ='-Bstatic' + ;; + + sysv4*MP*) + if test -d /usr/nec ;then + lt_prog_compiler_pic_GCJ='-Kconform_pic' + lt_prog_compiler_static_GCJ='-Bstatic' + fi + ;; + + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + lt_prog_compiler_wl_GCJ='-Wl,' + lt_prog_compiler_pic_GCJ='-KPIC' + lt_prog_compiler_static_GCJ='-Bstatic' + ;; + + unicos*) + lt_prog_compiler_wl_GCJ='-Wl,' + lt_prog_compiler_can_build_shared_GCJ=no + ;; + + uts4*) + lt_prog_compiler_pic_GCJ='-pic' + lt_prog_compiler_static_GCJ='-Bstatic' + ;; + + *) + lt_prog_compiler_can_build_shared_GCJ=no + ;; + esac + fi + +{ echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_GCJ" >&5 +echo "${ECHO_T}$lt_prog_compiler_pic_GCJ" >&6; } + +# +# Check to make sure the PIC flag actually works. +# +if test -n "$lt_prog_compiler_pic_GCJ"; then + +{ echo "$as_me:$LINENO: checking if $compiler PIC flag $lt_prog_compiler_pic_GCJ works" >&5 +echo $ECHO_N "checking if $compiler PIC flag $lt_prog_compiler_pic_GCJ works... $ECHO_C" >&6; } +if test "${lt_prog_compiler_pic_works_GCJ+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + lt_prog_compiler_pic_works_GCJ=no + ac_outfile=conftest.$ac_objext + printf "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="$lt_prog_compiler_pic_GCJ" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:24558: $lt_compile\"" >&5) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&5 + echo "$as_me:24562: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings other than the usual output. + $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then + lt_prog_compiler_pic_works_GCJ=yes + fi + fi + $rm conftest* + +fi +{ echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_works_GCJ" >&5 +echo "${ECHO_T}$lt_prog_compiler_pic_works_GCJ" >&6; } + +if test x"$lt_prog_compiler_pic_works_GCJ" = xyes; then + case $lt_prog_compiler_pic_GCJ in + "" | " "*) ;; + *) lt_prog_compiler_pic_GCJ=" $lt_prog_compiler_pic_GCJ" ;; + esac +else + lt_prog_compiler_pic_GCJ= + lt_prog_compiler_can_build_shared_GCJ=no +fi + +fi +case $host_os in + # For platforms which do not support PIC, -DPIC is meaningless: + *djgpp*) + lt_prog_compiler_pic_GCJ= + ;; + *) + lt_prog_compiler_pic_GCJ="$lt_prog_compiler_pic_GCJ" + ;; +esac + +# +# Check to make sure the static flag actually works. +# +wl=$lt_prog_compiler_wl_GCJ eval lt_tmp_static_flag=\"$lt_prog_compiler_static_GCJ\" +{ echo "$as_me:$LINENO: checking if $compiler static flag $lt_tmp_static_flag works" >&5 +echo $ECHO_N "checking if $compiler static flag $lt_tmp_static_flag works... $ECHO_C" >&6; } +if test "${lt_prog_compiler_static_works_GCJ+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + lt_prog_compiler_static_works_GCJ=no + save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS $lt_tmp_static_flag" + printf "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The linker can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&5 + $echo "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then + lt_prog_compiler_static_works_GCJ=yes + fi + else + lt_prog_compiler_static_works_GCJ=yes + fi + fi + $rm conftest* + LDFLAGS="$save_LDFLAGS" + +fi +{ echo "$as_me:$LINENO: result: $lt_prog_compiler_static_works_GCJ" >&5 +echo "${ECHO_T}$lt_prog_compiler_static_works_GCJ" >&6; } + +if test x"$lt_prog_compiler_static_works_GCJ" = xyes; then + : +else + lt_prog_compiler_static_GCJ= +fi + + +{ echo "$as_me:$LINENO: checking if $compiler supports -c -o file.$ac_objext" >&5 +echo $ECHO_N "checking if $compiler supports -c -o file.$ac_objext... $ECHO_C" >&6; } +if test "${lt_cv_prog_compiler_c_o_GCJ+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + lt_cv_prog_compiler_c_o_GCJ=no + $rm -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + printf "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:24662: $lt_compile\"" >&5) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&5 + echo "$as_me:24666: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + lt_cv_prog_compiler_c_o_GCJ=yes + fi + fi + chmod u+w . 2>&5 + $rm conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $rm out/ii_files/* && rmdir out/ii_files + $rm out/* && rmdir out + cd .. + rmdir conftest + $rm conftest* + +fi +{ echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_c_o_GCJ" >&5 +echo "${ECHO_T}$lt_cv_prog_compiler_c_o_GCJ" >&6; } + + +hard_links="nottested" +if test "$lt_cv_prog_compiler_c_o_GCJ" = no && test "$need_locks" != no; then + # do not overwrite the value of need_locks provided by the user + { echo "$as_me:$LINENO: checking if we can lock with hard links" >&5 +echo $ECHO_N "checking if we can lock with hard links... $ECHO_C" >&6; } + hard_links=yes + $rm conftest* + ln conftest.a conftest.b 2>/dev/null && hard_links=no + touch conftest.a + ln conftest.a conftest.b 2>&5 || hard_links=no + ln conftest.a conftest.b 2>/dev/null && hard_links=no + { echo "$as_me:$LINENO: result: $hard_links" >&5 +echo "${ECHO_T}$hard_links" >&6; } + if test "$hard_links" = no; then + { echo "$as_me:$LINENO: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5 +echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;} + need_locks=warn + fi +else + need_locks=no +fi + +{ echo "$as_me:$LINENO: checking whether the $compiler linker ($LD) supports shared libraries" >&5 +echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared libraries... $ECHO_C" >&6; } + + runpath_var= + allow_undefined_flag_GCJ= + enable_shared_with_static_runtimes_GCJ=no + archive_cmds_GCJ= + archive_expsym_cmds_GCJ= + old_archive_From_new_cmds_GCJ= + old_archive_from_expsyms_cmds_GCJ= + export_dynamic_flag_spec_GCJ= + whole_archive_flag_spec_GCJ= + thread_safe_flag_spec_GCJ= + hardcode_libdir_flag_spec_GCJ= + hardcode_libdir_flag_spec_ld_GCJ= + hardcode_libdir_separator_GCJ= + hardcode_direct_GCJ=no + hardcode_minus_L_GCJ=no + hardcode_shlibpath_var_GCJ=unsupported + link_all_deplibs_GCJ=unknown + hardcode_automatic_GCJ=no + module_cmds_GCJ= + module_expsym_cmds_GCJ= + always_export_symbols_GCJ=no + export_symbols_cmds_GCJ='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + # include_expsyms should be a list of space-separated symbols to be *always* + # included in the symbol list + include_expsyms_GCJ= + # exclude_expsyms can be an extended regexp of symbols to exclude + # it will be wrapped by ` (' and `)$', so one must not match beginning or + # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', + # as well as any symbol that contains `d'. + exclude_expsyms_GCJ="_GLOBAL_OFFSET_TABLE_" + # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out + # platforms (ab)use it in PIC code, but their linkers get confused if + # the symbol is explicitly referenced. Since portable code cannot + # rely on this symbol name, it's probably fine to never include it in + # preloaded symbol tables. + extract_expsyms_cmds= + # Just being paranoid about ensuring that cc_basename is set. + for cc_temp in $compiler""; do + case $cc_temp in + compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; + distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; + \-*) ;; + *) break;; + esac +done +cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` + + case $host_os in + cygwin* | mingw* | pw32*) + # FIXME: the MSVC++ port hasn't been tested in a loooong time + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + if test "$GCC" != yes; then + with_gnu_ld=no + fi + ;; + interix*) + # we just hope/assume this is gcc and not c89 (= MSVC++) + with_gnu_ld=yes + ;; + openbsd*) + with_gnu_ld=no + ;; + esac + + ld_shlibs_GCJ=yes + if test "$with_gnu_ld" = yes; then + # If archive_cmds runs LD, not CC, wlarc should be empty + wlarc='${wl}' + + # Set some defaults for GNU ld with shared library support. These + # are reset later if shared libraries are not supported. Putting them + # here allows them to be overridden if necessary. + runpath_var=LD_RUN_PATH + hardcode_libdir_flag_spec_GCJ='${wl}--rpath ${wl}$libdir' + export_dynamic_flag_spec_GCJ='${wl}--export-dynamic' + # ancient GNU ld didn't support --whole-archive et. al. + if $LD --help 2>&1 | grep 'no-whole-archive' > /dev/null; then + whole_archive_flag_spec_GCJ="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + else + whole_archive_flag_spec_GCJ= + fi + supports_anon_versioning=no + case `$LD -v 2>/dev/null` in + *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11 + *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... + *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... + *\ 2.11.*) ;; # other 2.11 versions + *) supports_anon_versioning=yes ;; + esac + + # See if GNU ld supports shared libraries. + case $host_os in + aix3* | aix4* | aix5*) + # On AIX/PPC, the GNU linker is very broken + if test "$host_cpu" != ia64; then + ld_shlibs_GCJ=no + cat <&2 + +*** Warning: the GNU linker, at least up to release 2.9.1, is reported +*** to be unable to reliably create shared libraries on AIX. +*** Therefore, libtool is disabling shared libraries support. If you +*** really care for shared libraries, you may want to modify your PATH +*** so that a non-GNU linker is found, and then restart. + +EOF + fi + ;; + + amigaos*) + archive_cmds_GCJ='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + hardcode_libdir_flag_spec_GCJ='-L$libdir' + hardcode_minus_L_GCJ=yes + + # Samuel A. Falvo II reports + # that the semantics of dynamic libraries on AmigaOS, at least up + # to version 4, is to share data among multiple programs linked + # with the same dynamic library. Since this doesn't match the + # behavior of shared libraries on other platforms, we can't use + # them. + ld_shlibs_GCJ=no + ;; + + beos*) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + allow_undefined_flag_GCJ=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + archive_cmds_GCJ='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + else + ld_shlibs_GCJ=no + fi + ;; + + cygwin* | mingw* | pw32*) + # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, GCJ) is actually meaningless, + # as there is no search path for DLLs. + hardcode_libdir_flag_spec_GCJ='-L$libdir' + allow_undefined_flag_GCJ=unsupported + always_export_symbols_GCJ=no + enable_shared_with_static_runtimes_GCJ=yes + export_symbols_cmds_GCJ='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS] /s/.* \([^ ]*\)/\1 DATA/'\'' | $SED -e '\''/^[AITW] /s/.* //'\'' | sort | uniq > $export_symbols' + + if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then + archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file (1st line + # is EXPORTS), use it as is; otherwise, prepend... + archive_expsym_cmds_GCJ='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + ld_shlibs_GCJ=no + fi + ;; + + interix3*) + hardcode_direct_GCJ=no + hardcode_shlibpath_var_GCJ=no + hardcode_libdir_flag_spec_GCJ='${wl}-rpath,$libdir' + export_dynamic_flag_spec_GCJ='${wl}-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + archive_cmds_GCJ='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + archive_expsym_cmds_GCJ='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + + linux*) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + tmp_addflag= + case $cc_basename,$host_cpu in + pgcc*) # Portland Group C compiler + whole_archive_flag_spec_GCJ='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' + tmp_addflag=' $pic_flag' + ;; + pgf77* | pgf90* | pgf95*) # Portland Group f77 and f90 compilers + whole_archive_flag_spec_GCJ='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' + tmp_addflag=' $pic_flag -Mnomain' ;; + ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 + tmp_addflag=' -i_dynamic' ;; + efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 + tmp_addflag=' -i_dynamic -nofor_main' ;; + ifc* | ifort*) # Intel Fortran compiler + tmp_addflag=' -nofor_main' ;; + esac + archive_cmds_GCJ='$CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + + if test $supports_anon_versioning = yes; then + archive_expsym_cmds_GCJ='$echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + $echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' + fi + else + ld_shlibs_GCJ=no + fi + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + archive_cmds_GCJ='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' + wlarc= + else + archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + fi + ;; + + solaris*) + if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then + ld_shlibs_GCJ=no + cat <&2 + +*** Warning: The releases 2.8.* of the GNU linker cannot reliably +*** create shared libraries on Solaris systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.9.1 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +EOF + elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + ld_shlibs_GCJ=no + fi + ;; + + sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) + case `$LD -v 2>&1` in + *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*) + ld_shlibs_GCJ=no + cat <<_LT_EOF 1>&2 + +*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not +*** reliably create shared libraries on SCO systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.16.91.0.3 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + ;; + *) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + hardcode_libdir_flag_spec_GCJ='`test -z "$SCOABSPATH" && echo ${wl}-rpath,$libdir`' + archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib' + archive_expsym_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname,-retain-symbols-file,$export_symbols -o $lib' + else + ld_shlibs_GCJ=no + fi + ;; + esac + ;; + + sunos4*) + archive_cmds_GCJ='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' + wlarc= + hardcode_direct_GCJ=yes + hardcode_shlibpath_var_GCJ=no + ;; + + *) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + ld_shlibs_GCJ=no + fi + ;; + esac + + if test "$ld_shlibs_GCJ" = no; then + runpath_var= + hardcode_libdir_flag_spec_GCJ= + export_dynamic_flag_spec_GCJ= + whole_archive_flag_spec_GCJ= + fi + else + # PORTME fill in a description of your system's linker (not GNU ld) + case $host_os in + aix3*) + allow_undefined_flag_GCJ=unsupported + always_export_symbols_GCJ=yes + archive_expsym_cmds_GCJ='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' + # Note: this linker hardcodes the directories in LIBPATH if there + # are no directories specified by -L. + hardcode_minus_L_GCJ=yes + if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then + # Neither direct hardcoding nor static linking is supported with a + # broken collect2. + hardcode_direct_GCJ=unsupported + fi + ;; + + aix4* | aix5*) + if test "$host_cpu" = ia64; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag="" + else + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to AIX nm, but means don't demangle with GNU nm + if $NM -V 2>&1 | grep 'GNU' > /dev/null; then + export_symbols_cmds_GCJ='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols' + else + export_symbols_cmds_GCJ='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols' + fi + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # need to do runtime linking. + case $host_os in aix4.[23]|aix4.[23].*|aix5*) + for ld_flag in $LDFLAGS; do + if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then + aix_use_runtimelinking=yes + break + fi + done + ;; + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + archive_cmds_GCJ='' + hardcode_direct_GCJ=yes + hardcode_libdir_separator_GCJ=':' + link_all_deplibs_GCJ=yes + + if test "$GCC" = yes; then + case $host_os in aix4.[012]|aix4.[012].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`${CC} -print-prog-name=collect2` + if test -f "$collect2name" && \ + strings "$collect2name" | grep resolve_lib_name >/dev/null + then + # We have reworked collect2 + hardcode_direct_GCJ=yes + else + # We have old collect2 + hardcode_direct_GCJ=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + hardcode_minus_L_GCJ=yes + hardcode_libdir_flag_spec_GCJ='-L$libdir' + hardcode_libdir_separator_GCJ= + fi + ;; + esac + shared_flag='-shared' + if test "$aix_use_runtimelinking" = yes; then + shared_flag="$shared_flag "'${wl}-G' + fi + else + # not using gcc + if test "$host_cpu" = ia64; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test "$aix_use_runtimelinking" = yes; then + shared_flag='${wl}-G' + else + shared_flag='${wl}-bM:SRE' + fi + fi + fi + + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to export. + always_export_symbols_GCJ=yes + if test "$aix_use_runtimelinking" = yes; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + allow_undefined_flag_GCJ='-berok' + # Determine the default libpath from the value encoded in an empty executable. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + +aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'` +# Check for a 64-bit object if we didn't find anything. +if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'`; fi +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi + + hardcode_libdir_flag_spec_GCJ='${wl}-blibpath:$libdir:'"$aix_libpath" + archive_expsym_cmds_GCJ="\$CC"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" + else + if test "$host_cpu" = ia64; then + hardcode_libdir_flag_spec_GCJ='${wl}-R $libdir:/usr/lib:/lib' + allow_undefined_flag_GCJ="-z nodefs" + archive_expsym_cmds_GCJ="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an empty executable. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + +aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'` +# Check for a 64-bit object if we didn't find anything. +if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'`; fi +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi + + hardcode_libdir_flag_spec_GCJ='${wl}-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + no_undefined_flag_GCJ=' ${wl}-bernotok' + allow_undefined_flag_GCJ=' ${wl}-berok' + # Exported symbols can be pulled into shared objects from archives + whole_archive_flag_spec_GCJ='$convenience' + archive_cmds_need_lc_GCJ=yes + # This is similar to how AIX traditionally builds its shared libraries. + archive_expsym_cmds_GCJ="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' + fi + fi + ;; + + amigaos*) + archive_cmds_GCJ='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + hardcode_libdir_flag_spec_GCJ='-L$libdir' + hardcode_minus_L_GCJ=yes + # see comment about different semantics on the GNU ld section + ld_shlibs_GCJ=no + ;; + + bsdi[45]*) + export_dynamic_flag_spec_GCJ=-rdynamic + ;; + + cygwin* | mingw* | pw32*) + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + hardcode_libdir_flag_spec_GCJ=' ' + allow_undefined_flag_GCJ=unsupported + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=".dll" + # FIXME: Setting linknames here is a bad hack. + archive_cmds_GCJ='$CC -o $lib $libobjs $compiler_flags `echo "$deplibs" | $SED -e '\''s/ -lc$//'\''` -link -dll~linknames=' + # The linker will automatically build a .lib file if we build a DLL. + old_archive_From_new_cmds_GCJ='true' + # FIXME: Should let the user specify the lib program. + old_archive_cmds_GCJ='lib /OUT:$oldlib$oldobjs$old_deplibs' + fix_srcfile_path_GCJ='`cygpath -w "$srcfile"`' + enable_shared_with_static_runtimes_GCJ=yes + ;; + + darwin* | rhapsody*) + case $host_os in + rhapsody* | darwin1.[012]) + allow_undefined_flag_GCJ='${wl}-undefined ${wl}suppress' + ;; + *) # Darwin 1.3 on + if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then + allow_undefined_flag_GCJ='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' + else + case ${MACOSX_DEPLOYMENT_TARGET} in + 10.[012]) + allow_undefined_flag_GCJ='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' + ;; + 10.*) + allow_undefined_flag_GCJ='${wl}-undefined ${wl}dynamic_lookup' + ;; + esac + fi + ;; + esac + archive_cmds_need_lc_GCJ=no + hardcode_direct_GCJ=no + hardcode_automatic_GCJ=yes + hardcode_shlibpath_var_GCJ=unsupported + whole_archive_flag_spec_GCJ='' + link_all_deplibs_GCJ=yes + if test "$GCC" = yes ; then + output_verbose_link_cmd='echo' + archive_cmds_GCJ='$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring' + module_cmds_GCJ='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' + # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds + archive_expsym_cmds_GCJ='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + module_expsym_cmds_GCJ='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + else + case $cc_basename in + xlc*) + output_verbose_link_cmd='echo' + archive_cmds_GCJ='$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $verstring' + module_cmds_GCJ='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' + # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds + archive_expsym_cmds_GCJ='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + module_expsym_cmds_GCJ='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + ;; + *) + ld_shlibs_GCJ=no + ;; + esac + fi + ;; + + dgux*) + archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec_GCJ='-L$libdir' + hardcode_shlibpath_var_GCJ=no + ;; + + freebsd1*) + ld_shlibs_GCJ=no + ;; + + # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor + # support. Future versions do this automatically, but an explicit c++rt0.o + # does not break anything, and helps significantly (at the cost of a little + # extra space). + freebsd2.2*) + archive_cmds_GCJ='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' + hardcode_libdir_flag_spec_GCJ='-R$libdir' + hardcode_direct_GCJ=yes + hardcode_shlibpath_var_GCJ=no + ;; + + # Unfortunately, older versions of FreeBSD 2 do not have this feature. + freebsd2*) + archive_cmds_GCJ='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct_GCJ=yes + hardcode_minus_L_GCJ=yes + hardcode_shlibpath_var_GCJ=no + ;; + + # FreeBSD 3 and greater uses gcc -shared to do shared libraries. + freebsd* | kfreebsd*-gnu | dragonfly*) + archive_cmds_GCJ='$CC -shared -o $lib $libobjs $deplibs $compiler_flags' + hardcode_libdir_flag_spec_GCJ='-R$libdir' + hardcode_direct_GCJ=yes + hardcode_shlibpath_var_GCJ=no + ;; + + hpux9*) + if test "$GCC" = yes; then + archive_cmds_GCJ='$rm $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + else + archive_cmds_GCJ='$rm $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + fi + hardcode_libdir_flag_spec_GCJ='${wl}+b ${wl}$libdir' + hardcode_libdir_separator_GCJ=: + hardcode_direct_GCJ=yes + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L_GCJ=yes + export_dynamic_flag_spec_GCJ='${wl}-E' + ;; + + hpux10*) + if test "$GCC" = yes -a "$with_gnu_ld" = no; then + archive_cmds_GCJ='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds_GCJ='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' + fi + if test "$with_gnu_ld" = no; then + hardcode_libdir_flag_spec_GCJ='${wl}+b ${wl}$libdir' + hardcode_libdir_separator_GCJ=: + + hardcode_direct_GCJ=yes + export_dynamic_flag_spec_GCJ='${wl}-E' + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L_GCJ=yes + fi + ;; + + hpux11*) + if test "$GCC" = yes -a "$with_gnu_ld" = no; then + case $host_cpu in + hppa*64*) + archive_cmds_GCJ='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + archive_cmds_GCJ='$CC -shared ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + archive_cmds_GCJ='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + else + case $host_cpu in + hppa*64*) + archive_cmds_GCJ='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + archive_cmds_GCJ='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + archive_cmds_GCJ='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + fi + if test "$with_gnu_ld" = no; then + hardcode_libdir_flag_spec_GCJ='${wl}+b ${wl}$libdir' + hardcode_libdir_separator_GCJ=: + + case $host_cpu in + hppa*64*|ia64*) + hardcode_libdir_flag_spec_ld_GCJ='+b $libdir' + hardcode_direct_GCJ=no + hardcode_shlibpath_var_GCJ=no + ;; + *) + hardcode_direct_GCJ=yes + export_dynamic_flag_spec_GCJ='${wl}-E' + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L_GCJ=yes + ;; + esac + fi + ;; + + irix5* | irix6* | nonstopux*) + if test "$GCC" = yes; then + archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + archive_cmds_GCJ='$LD -shared $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + hardcode_libdir_flag_spec_ld_GCJ='-rpath $libdir' + fi + hardcode_libdir_flag_spec_GCJ='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator_GCJ=: + link_all_deplibs_GCJ=yes + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + archive_cmds_GCJ='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out + else + archive_cmds_GCJ='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF + fi + hardcode_libdir_flag_spec_GCJ='-R$libdir' + hardcode_direct_GCJ=yes + hardcode_shlibpath_var_GCJ=no + ;; + + newsos6) + archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct_GCJ=yes + hardcode_libdir_flag_spec_GCJ='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator_GCJ=: + hardcode_shlibpath_var_GCJ=no + ;; + + openbsd*) + hardcode_direct_GCJ=yes + hardcode_shlibpath_var_GCJ=no + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + archive_cmds_GCJ='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_GCJ='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' + hardcode_libdir_flag_spec_GCJ='${wl}-rpath,$libdir' + export_dynamic_flag_spec_GCJ='${wl}-E' + else + case $host_os in + openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*) + archive_cmds_GCJ='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec_GCJ='-R$libdir' + ;; + *) + archive_cmds_GCJ='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + hardcode_libdir_flag_spec_GCJ='${wl}-rpath,$libdir' + ;; + esac + fi + ;; + + os2*) + hardcode_libdir_flag_spec_GCJ='-L$libdir' + hardcode_minus_L_GCJ=yes + allow_undefined_flag_GCJ=unsupported + archive_cmds_GCJ='$echo "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$echo DATA >> $output_objdir/$libname.def~$echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~$echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' + old_archive_From_new_cmds_GCJ='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' + ;; + + osf3*) + if test "$GCC" = yes; then + allow_undefined_flag_GCJ=' ${wl}-expect_unresolved ${wl}\*' + archive_cmds_GCJ='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + allow_undefined_flag_GCJ=' -expect_unresolved \*' + archive_cmds_GCJ='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + fi + hardcode_libdir_flag_spec_GCJ='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator_GCJ=: + ;; + + osf4* | osf5*) # as osf3* with the addition of -msym flag + if test "$GCC" = yes; then + allow_undefined_flag_GCJ=' ${wl}-expect_unresolved ${wl}\*' + archive_cmds_GCJ='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + hardcode_libdir_flag_spec_GCJ='${wl}-rpath ${wl}$libdir' + else + allow_undefined_flag_GCJ=' -expect_unresolved \*' + archive_cmds_GCJ='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + archive_expsym_cmds_GCJ='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; echo "-hidden">> $lib.exp~ + $LD -shared${allow_undefined_flag} -input $lib.exp $linker_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib~$rm $lib.exp' + + # Both c and cxx compiler support -rpath directly + hardcode_libdir_flag_spec_GCJ='-rpath $libdir' + fi + hardcode_libdir_separator_GCJ=: + ;; + + solaris*) + no_undefined_flag_GCJ=' -z text' + if test "$GCC" = yes; then + wlarc='${wl}' + archive_cmds_GCJ='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_GCJ='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $CC -shared ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$rm $lib.exp' + else + wlarc='' + archive_cmds_GCJ='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' + archive_expsym_cmds_GCJ='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp' + fi + hardcode_libdir_flag_spec_GCJ='-R$libdir' + hardcode_shlibpath_var_GCJ=no + case $host_os in + solaris2.[0-5] | solaris2.[0-5].*) ;; + *) + # The compiler driver will combine linker options so we + # cannot just pass the convience library names through + # without $wl, iff we do not link with $LD. + # Luckily, gcc supports the same syntax we need for Sun Studio. + # Supported since Solaris 2.6 (maybe 2.5.1?) + case $wlarc in + '') + whole_archive_flag_spec_GCJ='-z allextract$convenience -z defaultextract' ;; + *) + whole_archive_flag_spec_GCJ='${wl}-z ${wl}allextract`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}-z ${wl}defaultextract' ;; + esac ;; + esac + link_all_deplibs_GCJ=yes + ;; + + sunos4*) + if test "x$host_vendor" = xsequent; then + # Use $CC to link under sequent, because it throws in some extra .o + # files that make .init and .fini sections work. + archive_cmds_GCJ='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds_GCJ='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' + fi + hardcode_libdir_flag_spec_GCJ='-L$libdir' + hardcode_direct_GCJ=yes + hardcode_minus_L_GCJ=yes + hardcode_shlibpath_var_GCJ=no + ;; + + sysv4) + case $host_vendor in + sni) + archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct_GCJ=yes # is this really true??? + ;; + siemens) + ## LD is ld it makes a PLAMLIB + ## CC just makes a GrossModule. + archive_cmds_GCJ='$LD -G -o $lib $libobjs $deplibs $linker_flags' + reload_cmds_GCJ='$CC -r -o $output$reload_objs' + hardcode_direct_GCJ=no + ;; + motorola) + archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct_GCJ=no #Motorola manual says yes, but my tests say they lie + ;; + esac + runpath_var='LD_RUN_PATH' + hardcode_shlibpath_var_GCJ=no + ;; + + sysv4.3*) + archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_shlibpath_var_GCJ=no + export_dynamic_flag_spec_GCJ='-Bexport' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_shlibpath_var_GCJ=no + runpath_var=LD_RUN_PATH + hardcode_runpath_var=yes + ld_shlibs_GCJ=yes + fi + ;; + + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7*) + no_undefined_flag_GCJ='${wl}-z,text' + archive_cmds_need_lc_GCJ=no + hardcode_shlibpath_var_GCJ=no + runpath_var='LD_RUN_PATH' + + if test "$GCC" = yes; then + archive_cmds_GCJ='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_GCJ='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds_GCJ='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_GCJ='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + sysv5* | sco3.2v5* | sco5v6*) + # Note: We can NOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + no_undefined_flag_GCJ='${wl}-z,text' + allow_undefined_flag_GCJ='${wl}-z,nodefs' + archive_cmds_need_lc_GCJ=no + hardcode_shlibpath_var_GCJ=no + hardcode_libdir_flag_spec_GCJ='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`' + hardcode_libdir_separator_GCJ=':' + link_all_deplibs_GCJ=yes + export_dynamic_flag_spec_GCJ='${wl}-Bexport' + runpath_var='LD_RUN_PATH' + + if test "$GCC" = yes; then + archive_cmds_GCJ='$CC -shared ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_GCJ='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds_GCJ='$CC -G ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_GCJ='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + uts4*) + archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec_GCJ='-L$libdir' + hardcode_shlibpath_var_GCJ=no + ;; + + *) + ld_shlibs_GCJ=no + ;; + esac + fi + +{ echo "$as_me:$LINENO: result: $ld_shlibs_GCJ" >&5 +echo "${ECHO_T}$ld_shlibs_GCJ" >&6; } +test "$ld_shlibs_GCJ" = no && can_build_shared=no + +# +# Do we need to explicitly link libc? +# +case "x$archive_cmds_need_lc_GCJ" in +x|xyes) + # Assume -lc should be added + archive_cmds_need_lc_GCJ=yes + + if test "$enable_shared" = yes && test "$GCC" = yes; then + case $archive_cmds_GCJ in + *'~'*) + # FIXME: we may have to deal with multi-command sequences. + ;; + '$CC '*) + # Test whether the compiler implicitly links with -lc since on some + # systems, -lgcc has to come before -lc. If gcc already passes -lc + # to ld, don't add -lc before -lgcc. + { echo "$as_me:$LINENO: checking whether -lc should be explicitly linked in" >&5 +echo $ECHO_N "checking whether -lc should be explicitly linked in... $ECHO_C" >&6; } + $rm conftest* + printf "$lt_simple_compile_test_code" > conftest.$ac_ext + + if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } 2>conftest.err; then + soname=conftest + lib=conftest + libobjs=conftest.$ac_objext + deplibs= + wl=$lt_prog_compiler_wl_GCJ + pic_flag=$lt_prog_compiler_pic_GCJ + compiler_flags=-v + linker_flags=-v + verstring= + output_objdir=. + libname=conftest + lt_save_allow_undefined_flag=$allow_undefined_flag_GCJ + allow_undefined_flag_GCJ= + if { (eval echo "$as_me:$LINENO: \"$archive_cmds_GCJ 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1\"") >&5 + (eval $archive_cmds_GCJ 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + then + archive_cmds_need_lc_GCJ=no + else + archive_cmds_need_lc_GCJ=yes + fi + allow_undefined_flag_GCJ=$lt_save_allow_undefined_flag + else + cat conftest.err 1>&5 + fi + $rm conftest* + { echo "$as_me:$LINENO: result: $archive_cmds_need_lc_GCJ" >&5 +echo "${ECHO_T}$archive_cmds_need_lc_GCJ" >&6; } + ;; + esac + fi + ;; +esac + +{ echo "$as_me:$LINENO: checking dynamic linker characteristics" >&5 +echo $ECHO_N "checking dynamic linker characteristics... $ECHO_C" >&6; } +library_names_spec= +libname_spec='lib$name' +soname_spec= +shrext_cmds=".so" +postinstall_cmds= +postuninstall_cmds= +finish_cmds= +finish_eval= +shlibpath_var= +shlibpath_overrides_runpath=unknown +version_type=none +dynamic_linker="$host_os ld.so" +sys_lib_dlsearch_path_spec="/lib /usr/lib" +if test "$GCC" = yes; then + sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` + if echo "$sys_lib_search_path_spec" | grep ';' >/dev/null ; then + # if the path contains ";" then we assume it to be the separator + # otherwise default to the standard path separator (i.e. ":") - it is + # assumed that no part of a normal pathname contains ";" but that should + # okay in the real world where ";" in dirpaths is itself problematic. + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi +else + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" +fi +need_lib_prefix=unknown +hardcode_into_libs=no + +# when you set need_version to no, make sure it does not cause -set_version +# flags to be left without arguments +need_version=unknown + +case $host_os in +aix3*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' + shlibpath_var=LIBPATH + + # AIX 3 has no versioning support, so we append a major version to the name. + soname_spec='${libname}${release}${shared_ext}$major' + ;; + +aix4* | aix5*) + version_type=linux + need_lib_prefix=no + need_version=no + hardcode_into_libs=yes + if test "$host_cpu" = ia64; then + # AIX 5 supports IA64 + library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + else + # With GCC up to 2.95.x, collect2 would create an import file + # for dependence libraries. The import file would start with + # the line `#! .'. This would cause the generated library to + # depend on `.', always an invalid library. This was fixed in + # development snapshots of GCC prior to 3.0. + case $host_os in + aix4 | aix4.[01] | aix4.[01].*) + if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' + echo ' yes ' + echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then + : + else + can_build_shared=no + fi + ;; + esac + # AIX (on Power*) has no versioning support, so currently we can not hardcode correct + # soname into executable. Probably we can add versioning support to + # collect2, so additional links can be useful in future. + if test "$aix_use_runtimelinking" = yes; then + # If using run time linking (on AIX 4.2 or later) use lib.so + # instead of lib.a to let people know that these are not + # typical AIX shared libraries. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + else + # We preserve .a as extension for shared libraries through AIX4.2 + # and later when we are not doing run time linking. + library_names_spec='${libname}${release}.a $libname.a' + soname_spec='${libname}${release}${shared_ext}$major' + fi + shlibpath_var=LIBPATH + fi + ;; + +amigaos*) + library_names_spec='$libname.ixlibrary $libname.a' + # Create ${libname}_ixlibrary.a entries in /sys/libs. + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' + ;; + +beos*) + library_names_spec='${libname}${shared_ext}' + dynamic_linker="$host_os ld.so" + shlibpath_var=LIBRARY_PATH + ;; + +bsdi[45]*) + version_type=linux + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" + sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" + # the default ld.so.conf also contains /usr/contrib/lib and + # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow + # libtool to hard-code these into programs + ;; + +cygwin* | mingw* | pw32*) + version_type=windows + shrext_cmds=".dll" + need_version=no + need_lib_prefix=no + + case $GCC,$host_os in + yes,cygwin* | yes,mingw* | yes,pw32*) + library_names_spec='$libname.dll.a' + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \${file}`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $rm \$dlpath' + shlibpath_overrides_runpath=yes + + case $host_os in + cygwin*) + # Cygwin DLLs use 'cyg' prefix rather than 'lib' + soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib" + ;; + mingw*) + # MinGW DLLs use traditional 'lib' prefix + soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` + if echo "$sys_lib_search_path_spec" | grep ';[c-zC-Z]:/' >/dev/null; then + # It is most probably a Windows format PATH printed by + # mingw gcc, but we are running on Cygwin. Gcc prints its search + # path with ; separators, and with drive letters. We can handle the + # drive letters (cygwin fileutils understands them), so leave them, + # especially as we might pass files found there to a mingw objdump, + # which wouldn't understand a cygwinified path. Ahh. + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi + ;; + pw32*) + # pw32 DLLs use 'pw' prefix rather than 'lib' + library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + ;; + esac + ;; + + *) + library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib' + ;; + esac + dynamic_linker='Win32 ld.exe' + # FIXME: first we should search . and the directory the executable is in + shlibpath_var=PATH + ;; + +darwin* | rhapsody*) + dynamic_linker="$host_os dyld" + version_type=darwin + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext' + soname_spec='${libname}${release}${major}$shared_ext' + shlibpath_overrides_runpath=yes + shlibpath_var=DYLD_LIBRARY_PATH + shrext_cmds='.dylib' + # Apple's gcc prints 'gcc -print-search-dirs' doesn't operate the same. + if test "$GCC" = yes; then + sys_lib_search_path_spec=`$CC -print-search-dirs | tr "\n" "$PATH_SEPARATOR" | sed -e 's/libraries:/@libraries:/' | tr "@" "\n" | grep "^libraries:" | sed -e "s/^libraries://" -e "s,=/,/,g" -e "s,$PATH_SEPARATOR, ,g" -e "s,.*,& /lib /usr/lib /usr/local/lib,g"` + else + sys_lib_search_path_spec='/lib /usr/lib /usr/local/lib' + fi + sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' + ;; + +dgux*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +freebsd1*) + dynamic_linker=no + ;; + +kfreebsd*-gnu) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='GNU ld.so' + ;; + +freebsd* | dragonfly*) + # DragonFly does not have aout. When/if they implement a new + # versioning mechanism, adjust this. + if test -x /usr/bin/objformat; then + objformat=`/usr/bin/objformat` + else + case $host_os in + freebsd[123]*) objformat=aout ;; + *) objformat=elf ;; + esac + fi + version_type=freebsd-$objformat + case $version_type in + freebsd-elf*) + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + need_version=no + need_lib_prefix=no + ;; + freebsd-*) + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' + need_version=yes + ;; + esac + shlibpath_var=LD_LIBRARY_PATH + case $host_os in + freebsd2*) + shlibpath_overrides_runpath=yes + ;; + freebsd3.[01]* | freebsdelf3.[01]*) + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ + freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + freebsd*) # from 4.6 on + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + esac + ;; + +gnu*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + hardcode_into_libs=yes + ;; + +hpux9* | hpux10* | hpux11*) + # Give a soname corresponding to the major version so that dld.sl refuses to + # link against other versions. + version_type=sunos + need_lib_prefix=no + need_version=no + case $host_cpu in + ia64*) + shrext_cmds='.so' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.so" + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + if test "X$HPUX_IA64_MODE" = X32; then + sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" + else + sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" + fi + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + hppa*64*) + shrext_cmds='.sl' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.sl" + shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + *) + shrext_cmds='.sl' + dynamic_linker="$host_os dld.sl" + shlibpath_var=SHLIB_PATH + shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + ;; + esac + # HP-UX runs *really* slowly unless shared libraries are mode 555. + postinstall_cmds='chmod 555 $lib' + ;; + +interix3*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +irix5* | irix6* | nonstopux*) + case $host_os in + nonstopux*) version_type=nonstopux ;; + *) + if test "$lt_cv_prog_gnu_ld" = yes; then + version_type=linux + else + version_type=irix + fi ;; + esac + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' + case $host_os in + irix5* | nonstopux*) + libsuff= shlibsuff= + ;; + *) + case $LD in # libtool.m4 will add one of these switches to LD + *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") + libsuff= shlibsuff= libmagic=32-bit;; + *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") + libsuff=32 shlibsuff=N32 libmagic=N32;; + *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") + libsuff=64 shlibsuff=64 libmagic=64-bit;; + *) libsuff= shlibsuff= libmagic=never-match;; + esac + ;; + esac + shlibpath_var=LD_LIBRARY${shlibsuff}_PATH + shlibpath_overrides_runpath=no + sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" + sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" + hardcode_into_libs=yes + ;; + +# No shared lib support for Linux oldld, aout, or coff. +linux*oldld* | linux*aout* | linux*coff*) + dynamic_linker=no + ;; + +# This must be Linux ELF. +linux*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + # Append ld.so.conf contents to the search path + if test -f /etc/ld.so.conf; then + lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '` + sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" + fi + + # We used to test for /lib/ld.so.1 and disable shared libraries on + # powerpc, because MkLinux only supported shared libraries with the + # GNU dynamic linker. Since this was broken with cross compilers, + # most powerpc-linux boxes support dynamic linking these days and + # people can always --disable-shared, the test was removed, and we + # assume the GNU/Linux dynamic linker is in use. + dynamic_linker='GNU/Linux ld.so' + ;; + +knetbsd*-gnu) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='GNU ld.so' + ;; + +netbsd*) + version_type=sunos + need_lib_prefix=no + need_version=no + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + dynamic_linker='NetBSD (a.out) ld.so' + else + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='NetBSD ld.elf_so' + fi + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + +newsos6) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +nto-qnx*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +openbsd*) + version_type=sunos + sys_lib_dlsearch_path_spec="/usr/lib" + need_lib_prefix=no + # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. + case $host_os in + openbsd3.3 | openbsd3.3.*) need_version=yes ;; + *) need_version=no ;; + esac + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + shlibpath_var=LD_LIBRARY_PATH + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + case $host_os in + openbsd2.[89] | openbsd2.[89].*) + shlibpath_overrides_runpath=no + ;; + *) + shlibpath_overrides_runpath=yes + ;; + esac + else + shlibpath_overrides_runpath=yes + fi + ;; + +os2*) + libname_spec='$name' + shrext_cmds=".dll" + need_lib_prefix=no + library_names_spec='$libname${shared_ext} $libname.a' + dynamic_linker='OS/2 ld.exe' + shlibpath_var=LIBPATH + ;; + +osf3* | osf4* | osf5*) + version_type=osf + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" + sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" + ;; + +solaris*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + # ldd complains unless libraries are executable + postinstall_cmds='chmod +x $lib' + ;; + +sunos4*) + version_type=sunos + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + if test "$with_gnu_ld" = yes; then + need_lib_prefix=no + fi + need_version=yes + ;; + +sysv4 | sysv4.3*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + case $host_vendor in + sni) + shlibpath_overrides_runpath=no + need_lib_prefix=no + export_dynamic_flag_spec='${wl}-Blargedynsym' + runpath_var=LD_RUN_PATH + ;; + siemens) + need_lib_prefix=no + ;; + motorola) + need_lib_prefix=no + need_version=no + shlibpath_overrides_runpath=no + sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' + ;; + esac + ;; + +sysv4*MP*) + if test -d /usr/nec ;then + version_type=linux + library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' + soname_spec='$libname${shared_ext}.$major' + shlibpath_var=LD_LIBRARY_PATH + fi + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + version_type=freebsd-elf + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + hardcode_into_libs=yes + if test "$with_gnu_ld" = yes; then + sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' + shlibpath_overrides_runpath=no + else + sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' + shlibpath_overrides_runpath=yes + case $host_os in + sco3.2v5*) + sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" + ;; + esac + fi + sys_lib_dlsearch_path_spec='/usr/lib' + ;; + +uts4*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +*) + dynamic_linker=no + ;; +esac +{ echo "$as_me:$LINENO: result: $dynamic_linker" >&5 +echo "${ECHO_T}$dynamic_linker" >&6; } +test "$dynamic_linker" = no && can_build_shared=no + +variables_saved_for_relink="PATH $shlibpath_var $runpath_var" +if test "$GCC" = yes; then + variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" +fi + +{ echo "$as_me:$LINENO: checking how to hardcode library paths into programs" >&5 +echo $ECHO_N "checking how to hardcode library paths into programs... $ECHO_C" >&6; } +hardcode_action_GCJ= +if test -n "$hardcode_libdir_flag_spec_GCJ" || \ + test -n "$runpath_var_GCJ" || \ + test "X$hardcode_automatic_GCJ" = "Xyes" ; then + + # We can hardcode non-existant directories. + if test "$hardcode_direct_GCJ" != no && + # If the only mechanism to avoid hardcoding is shlibpath_var, we + # have to relink, otherwise we might link with an installed library + # when we should be linking with a yet-to-be-installed one + ## test "$_LT_AC_TAGVAR(hardcode_shlibpath_var, GCJ)" != no && + test "$hardcode_minus_L_GCJ" != no; then + # Linking always hardcodes the temporary library directory. + hardcode_action_GCJ=relink + else + # We can link without hardcoding, and we can hardcode nonexisting dirs. + hardcode_action_GCJ=immediate + fi +else + # We cannot hardcode anything, or else we can only hardcode existing + # directories. + hardcode_action_GCJ=unsupported +fi +{ echo "$as_me:$LINENO: result: $hardcode_action_GCJ" >&5 +echo "${ECHO_T}$hardcode_action_GCJ" >&6; } + +if test "$hardcode_action_GCJ" = relink; then + # Fast installation is not supported + enable_fast_install=no +elif test "$shlibpath_overrides_runpath" = yes || + test "$enable_shared" = no; then + # Fast installation is not necessary + enable_fast_install=needless +fi + + +# The else clause should only fire when bootstrapping the +# libtool distribution, otherwise you forgot to ship ltmain.sh +# with your package, and you will get complaints that there are +# no rules to generate ltmain.sh. +if test -f "$ltmain"; then + # See if we are running on zsh, and set the options which allow our commands through + # without removal of \ escapes. + if test -n "${ZSH_VERSION+set}" ; then + setopt NO_GLOB_SUBST + fi + # Now quote all the things that may contain metacharacters while being + # careful not to overquote the AC_SUBSTed values. We take copies of the + # variables and quote the copies for generation of the libtool script. + for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC LTCFLAGS NM \ + SED SHELL STRIP \ + libname_spec library_names_spec soname_spec extract_expsyms_cmds \ + old_striplib striplib file_magic_cmd finish_cmds finish_eval \ + deplibs_check_method reload_flag reload_cmds need_locks \ + lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \ + lt_cv_sys_global_symbol_to_c_name_address \ + sys_lib_search_path_spec sys_lib_dlsearch_path_spec \ + old_postinstall_cmds old_postuninstall_cmds \ + compiler_GCJ \ + CC_GCJ \ + LD_GCJ \ + lt_prog_compiler_wl_GCJ \ + lt_prog_compiler_pic_GCJ \ + lt_prog_compiler_static_GCJ \ + lt_prog_compiler_no_builtin_flag_GCJ \ + export_dynamic_flag_spec_GCJ \ + thread_safe_flag_spec_GCJ \ + whole_archive_flag_spec_GCJ \ + enable_shared_with_static_runtimes_GCJ \ + old_archive_cmds_GCJ \ + old_archive_from_new_cmds_GCJ \ + predep_objects_GCJ \ + postdep_objects_GCJ \ + predeps_GCJ \ + postdeps_GCJ \ + compiler_lib_search_path_GCJ \ + archive_cmds_GCJ \ + archive_expsym_cmds_GCJ \ + postinstall_cmds_GCJ \ + postuninstall_cmds_GCJ \ + old_archive_from_expsyms_cmds_GCJ \ + allow_undefined_flag_GCJ \ + no_undefined_flag_GCJ \ + export_symbols_cmds_GCJ \ + hardcode_libdir_flag_spec_GCJ \ + hardcode_libdir_flag_spec_ld_GCJ \ + hardcode_libdir_separator_GCJ \ + hardcode_automatic_GCJ \ + module_cmds_GCJ \ + module_expsym_cmds_GCJ \ + lt_cv_prog_compiler_c_o_GCJ \ + exclude_expsyms_GCJ \ + include_expsyms_GCJ; do + + case $var in + old_archive_cmds_GCJ | \ + old_archive_from_new_cmds_GCJ | \ + archive_cmds_GCJ | \ + archive_expsym_cmds_GCJ | \ + module_cmds_GCJ | \ + module_expsym_cmds_GCJ | \ + old_archive_from_expsyms_cmds_GCJ | \ + export_symbols_cmds_GCJ | \ + extract_expsyms_cmds | reload_cmds | finish_cmds | \ + postinstall_cmds | postuninstall_cmds | \ + old_postinstall_cmds | old_postuninstall_cmds | \ + sys_lib_search_path_spec | sys_lib_dlsearch_path_spec) + # Double-quote double-evaled strings. + eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\"" + ;; + *) + eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\"" + ;; + esac + done + + case $lt_echo in + *'\$0 --fallback-echo"') + lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'` + ;; + esac + +cfgfile="$ofile" + + cat <<__EOF__ >> "$cfgfile" +# ### BEGIN LIBTOOL TAG CONFIG: $tagname + +# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: + +# Shell to use when invoking shell scripts. +SHELL=$lt_SHELL + +# Whether or not to build shared libraries. +build_libtool_libs=$enable_shared + +# Whether or not to build static libraries. +build_old_libs=$enable_static + +# Whether or not to add -lc for building shared libraries. +build_libtool_need_lc=$archive_cmds_need_lc_GCJ + +# Whether or not to disallow shared libs when runtime libs are static +allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes_GCJ + +# Whether or not to optimize for fast installation. +fast_install=$enable_fast_install + +# The host system. +host_alias=$host_alias +host=$host +host_os=$host_os + +# The build system. +build_alias=$build_alias +build=$build +build_os=$build_os + +# An echo program that does not interpret backslashes. +echo=$lt_echo + +# The archiver. +AR=$lt_AR +AR_FLAGS=$lt_AR_FLAGS + +# A C compiler. +LTCC=$lt_LTCC + +# LTCC compiler flags. +LTCFLAGS=$lt_LTCFLAGS + +# A language-specific compiler. +CC=$lt_compiler_GCJ + +# Is the compiler the GNU C compiler? +with_gcc=$GCC_GCJ + +# An ERE matcher. +EGREP=$lt_EGREP + +# The linker used to build libraries. +LD=$lt_LD_GCJ + +# Whether we need hard or soft links. +LN_S=$lt_LN_S + +# A BSD-compatible nm program. +NM=$lt_NM + +# A symbol stripping program +STRIP=$lt_STRIP + +# Used to examine libraries when file_magic_cmd begins "file" +MAGIC_CMD=$MAGIC_CMD + +# Used on cygwin: DLL creation program. +DLLTOOL="$DLLTOOL" + +# Used on cygwin: object dumper. +OBJDUMP="$OBJDUMP" + +# Used on cygwin: assembler. +AS="$AS" + +# The name of the directory that contains temporary libtool files. +objdir=$objdir + +# How to create reloadable object files. +reload_flag=$lt_reload_flag +reload_cmds=$lt_reload_cmds + +# How to pass a linker flag through the compiler. +wl=$lt_lt_prog_compiler_wl_GCJ + +# Object file suffix (normally "o"). +objext="$ac_objext" + +# Old archive suffix (normally "a"). +libext="$libext" + +# Shared library suffix (normally ".so"). +shrext_cmds='$shrext_cmds' + +# Executable file suffix (normally ""). +exeext="$exeext" + +# Additional compiler flags for building library objects. +pic_flag=$lt_lt_prog_compiler_pic_GCJ +pic_mode=$pic_mode + +# What is the maximum length of a command? +max_cmd_len=$lt_cv_sys_max_cmd_len + +# Does compiler simultaneously support -c and -o options? +compiler_c_o=$lt_lt_cv_prog_compiler_c_o_GCJ + +# Must we lock files when doing compilation? +need_locks=$lt_need_locks + +# Do we need the lib prefix for modules? +need_lib_prefix=$need_lib_prefix + +# Do we need a version for libraries? +need_version=$need_version + +# Whether dlopen is supported. +dlopen_support=$enable_dlopen + +# Whether dlopen of programs is supported. +dlopen_self=$enable_dlopen_self + +# Whether dlopen of statically linked programs is supported. +dlopen_self_static=$enable_dlopen_self_static + +# Compiler flag to prevent dynamic linking. +link_static_flag=$lt_lt_prog_compiler_static_GCJ + +# Compiler flag to turn off builtin functions. +no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_GCJ + +# Compiler flag to allow reflexive dlopens. +export_dynamic_flag_spec=$lt_export_dynamic_flag_spec_GCJ + +# Compiler flag to generate shared objects directly from archives. +whole_archive_flag_spec=$lt_whole_archive_flag_spec_GCJ + +# Compiler flag to generate thread-safe objects. +thread_safe_flag_spec=$lt_thread_safe_flag_spec_GCJ + +# Library versioning type. +version_type=$version_type + +# Format of library name prefix. +libname_spec=$lt_libname_spec + +# List of archive names. First name is the real one, the rest are links. +# The last name is the one that the linker finds with -lNAME. +library_names_spec=$lt_library_names_spec + +# The coded name of the library, if different from the real name. +soname_spec=$lt_soname_spec + +# Commands used to build and install an old-style archive. +RANLIB=$lt_RANLIB +old_archive_cmds=$lt_old_archive_cmds_GCJ +old_postinstall_cmds=$lt_old_postinstall_cmds +old_postuninstall_cmds=$lt_old_postuninstall_cmds + +# Create an old-style archive from a shared archive. +old_archive_from_new_cmds=$lt_old_archive_from_new_cmds_GCJ + +# Create a temporary old-style archive to link instead of a shared archive. +old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds_GCJ + +# Commands used to build and install a shared archive. +archive_cmds=$lt_archive_cmds_GCJ +archive_expsym_cmds=$lt_archive_expsym_cmds_GCJ +postinstall_cmds=$lt_postinstall_cmds +postuninstall_cmds=$lt_postuninstall_cmds + +# Commands used to build a loadable module (assumed same as above if empty) +module_cmds=$lt_module_cmds_GCJ +module_expsym_cmds=$lt_module_expsym_cmds_GCJ + +# Commands to strip libraries. +old_striplib=$lt_old_striplib +striplib=$lt_striplib + +# Dependencies to place before the objects being linked to create a +# shared library. +predep_objects=$lt_predep_objects_GCJ + +# Dependencies to place after the objects being linked to create a +# shared library. +postdep_objects=$lt_postdep_objects_GCJ + +# Dependencies to place before the objects being linked to create a +# shared library. +predeps=$lt_predeps_GCJ + +# Dependencies to place after the objects being linked to create a +# shared library. +postdeps=$lt_postdeps_GCJ + +# The library search path used internally by the compiler when linking +# a shared library. +compiler_lib_search_path=$lt_compiler_lib_search_path_GCJ + +# Method to check whether dependent libraries are shared objects. +deplibs_check_method=$lt_deplibs_check_method + +# Command to use when deplibs_check_method == file_magic. +file_magic_cmd=$lt_file_magic_cmd + +# Flag that allows shared libraries with undefined symbols to be built. +allow_undefined_flag=$lt_allow_undefined_flag_GCJ + +# Flag that forces no undefined symbols. +no_undefined_flag=$lt_no_undefined_flag_GCJ + +# Commands used to finish a libtool library installation in a directory. +finish_cmds=$lt_finish_cmds + +# Same as above, but a single script fragment to be evaled but not shown. +finish_eval=$lt_finish_eval + +# Take the output of nm and produce a listing of raw symbols and C names. +global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe + +# Transform the output of nm in a proper C declaration +global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl + +# Transform the output of nm in a C name address pair +global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address + +# This is the shared library runtime path variable. +runpath_var=$runpath_var + +# This is the shared library path variable. +shlibpath_var=$shlibpath_var + +# Is shlibpath searched before the hard-coded library search path? +shlibpath_overrides_runpath=$shlibpath_overrides_runpath + +# How to hardcode a shared library path into an executable. +hardcode_action=$hardcode_action_GCJ + +# Whether we should hardcode library paths into libraries. +hardcode_into_libs=$hardcode_into_libs + +# Flag to hardcode \$libdir into a binary during linking. +# This must work even if \$libdir does not exist. +hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_GCJ + +# If ld is used when linking, flag to hardcode \$libdir into +# a binary during linking. This must work even if \$libdir does +# not exist. +hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld_GCJ + +# Whether we need a single -rpath flag with a separated argument. +hardcode_libdir_separator=$lt_hardcode_libdir_separator_GCJ + +# Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the +# resulting binary. +hardcode_direct=$hardcode_direct_GCJ + +# Set to yes if using the -LDIR flag during linking hardcodes DIR into the +# resulting binary. +hardcode_minus_L=$hardcode_minus_L_GCJ + +# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into +# the resulting binary. +hardcode_shlibpath_var=$hardcode_shlibpath_var_GCJ + +# Set to yes if building a shared library automatically hardcodes DIR into the library +# and all subsequent libraries and executables linked against it. +hardcode_automatic=$hardcode_automatic_GCJ + +# Variables whose values should be saved in libtool wrapper scripts and +# restored at relink time. +variables_saved_for_relink="$variables_saved_for_relink" + +# Whether libtool must link a program against all its dependency libraries. +link_all_deplibs=$link_all_deplibs_GCJ + +# Compile-time system search path for libraries +sys_lib_search_path_spec=$lt_sys_lib_search_path_spec + +# Run-time system search path for libraries +sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec + +# Fix the shell variable \$srcfile for the compiler. +fix_srcfile_path="$fix_srcfile_path_GCJ" + +# Set to yes if exported symbols are required. +always_export_symbols=$always_export_symbols_GCJ + +# The commands to list exported symbols. +export_symbols_cmds=$lt_export_symbols_cmds_GCJ + +# The commands to extract the exported symbol list from a shared archive. +extract_expsyms_cmds=$lt_extract_expsyms_cmds + +# Symbols that should not be listed in the preloaded symbols. +exclude_expsyms=$lt_exclude_expsyms_GCJ + +# Symbols that must always be exported. +include_expsyms=$lt_include_expsyms_GCJ + +# ### END LIBTOOL TAG CONFIG: $tagname + +__EOF__ + + +else + # If there is no Makefile yet, we rely on a make rule to execute + # `config.status --recheck' to rerun these tests and create the + # libtool script then. + ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'` + if test -f "$ltmain_in"; then + test -f Makefile && make "$ltmain" + fi +fi + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +CC="$lt_save_CC" + + else + tagname="" + fi + ;; + + RC) + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +# Source file extension for RC test sources. +ac_ext=rc + +# Object file extension for compiled RC test sources. +objext=o +objext_RC=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }\n' + +# Code to be used in simple link tests +lt_simple_link_test_code="$lt_simple_compile_test_code" + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC + + +# save warnings/boilerplate of simple test code +ac_outfile=conftest.$ac_objext +printf "$lt_simple_compile_test_code" >conftest.$ac_ext +eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_compiler_boilerplate=`cat conftest.err` +$rm conftest* + +ac_outfile=conftest.$ac_objext +printf "$lt_simple_link_test_code" >conftest.$ac_ext +eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_linker_boilerplate=`cat conftest.err` +$rm conftest* + + +# Allow CC to be a program name with arguments. +lt_save_CC="$CC" +CC=${RC-"windres"} +compiler=$CC +compiler_RC=$CC +for cc_temp in $compiler""; do + case $cc_temp in + compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; + distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; + \-*) ;; + *) break;; + esac +done +cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` + +lt_cv_prog_compiler_c_o_RC=yes + +# The else clause should only fire when bootstrapping the +# libtool distribution, otherwise you forgot to ship ltmain.sh +# with your package, and you will get complaints that there are +# no rules to generate ltmain.sh. +if test -f "$ltmain"; then + # See if we are running on zsh, and set the options which allow our commands through + # without removal of \ escapes. + if test -n "${ZSH_VERSION+set}" ; then + setopt NO_GLOB_SUBST + fi + # Now quote all the things that may contain metacharacters while being + # careful not to overquote the AC_SUBSTed values. We take copies of the + # variables and quote the copies for generation of the libtool script. + for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC LTCFLAGS NM \ + SED SHELL STRIP \ + libname_spec library_names_spec soname_spec extract_expsyms_cmds \ + old_striplib striplib file_magic_cmd finish_cmds finish_eval \ + deplibs_check_method reload_flag reload_cmds need_locks \ + lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \ + lt_cv_sys_global_symbol_to_c_name_address \ + sys_lib_search_path_spec sys_lib_dlsearch_path_spec \ + old_postinstall_cmds old_postuninstall_cmds \ + compiler_RC \ + CC_RC \ + LD_RC \ + lt_prog_compiler_wl_RC \ + lt_prog_compiler_pic_RC \ + lt_prog_compiler_static_RC \ + lt_prog_compiler_no_builtin_flag_RC \ + export_dynamic_flag_spec_RC \ + thread_safe_flag_spec_RC \ + whole_archive_flag_spec_RC \ + enable_shared_with_static_runtimes_RC \ + old_archive_cmds_RC \ + old_archive_from_new_cmds_RC \ + predep_objects_RC \ + postdep_objects_RC \ + predeps_RC \ + postdeps_RC \ + compiler_lib_search_path_RC \ + archive_cmds_RC \ + archive_expsym_cmds_RC \ + postinstall_cmds_RC \ + postuninstall_cmds_RC \ + old_archive_from_expsyms_cmds_RC \ + allow_undefined_flag_RC \ + no_undefined_flag_RC \ + export_symbols_cmds_RC \ + hardcode_libdir_flag_spec_RC \ + hardcode_libdir_flag_spec_ld_RC \ + hardcode_libdir_separator_RC \ + hardcode_automatic_RC \ + module_cmds_RC \ + module_expsym_cmds_RC \ + lt_cv_prog_compiler_c_o_RC \ + exclude_expsyms_RC \ + include_expsyms_RC; do + + case $var in + old_archive_cmds_RC | \ + old_archive_from_new_cmds_RC | \ + archive_cmds_RC | \ + archive_expsym_cmds_RC | \ + module_cmds_RC | \ + module_expsym_cmds_RC | \ + old_archive_from_expsyms_cmds_RC | \ + export_symbols_cmds_RC | \ + extract_expsyms_cmds | reload_cmds | finish_cmds | \ + postinstall_cmds | postuninstall_cmds | \ + old_postinstall_cmds | old_postuninstall_cmds | \ + sys_lib_search_path_spec | sys_lib_dlsearch_path_spec) + # Double-quote double-evaled strings. + eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\"" + ;; + *) + eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\"" + ;; + esac + done + + case $lt_echo in + *'\$0 --fallback-echo"') + lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'` + ;; + esac + +cfgfile="$ofile" + + cat <<__EOF__ >> "$cfgfile" +# ### BEGIN LIBTOOL TAG CONFIG: $tagname + +# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: + +# Shell to use when invoking shell scripts. +SHELL=$lt_SHELL + +# Whether or not to build shared libraries. +build_libtool_libs=$enable_shared + +# Whether or not to build static libraries. +build_old_libs=$enable_static + +# Whether or not to add -lc for building shared libraries. +build_libtool_need_lc=$archive_cmds_need_lc_RC + +# Whether or not to disallow shared libs when runtime libs are static +allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes_RC + +# Whether or not to optimize for fast installation. +fast_install=$enable_fast_install + +# The host system. +host_alias=$host_alias +host=$host +host_os=$host_os + +# The build system. +build_alias=$build_alias +build=$build +build_os=$build_os + +# An echo program that does not interpret backslashes. +echo=$lt_echo + +# The archiver. +AR=$lt_AR +AR_FLAGS=$lt_AR_FLAGS + +# A C compiler. +LTCC=$lt_LTCC + +# LTCC compiler flags. +LTCFLAGS=$lt_LTCFLAGS + +# A language-specific compiler. +CC=$lt_compiler_RC + +# Is the compiler the GNU C compiler? +with_gcc=$GCC_RC + +# An ERE matcher. +EGREP=$lt_EGREP + +# The linker used to build libraries. +LD=$lt_LD_RC + +# Whether we need hard or soft links. +LN_S=$lt_LN_S + +# A BSD-compatible nm program. +NM=$lt_NM + +# A symbol stripping program +STRIP=$lt_STRIP + +# Used to examine libraries when file_magic_cmd begins "file" +MAGIC_CMD=$MAGIC_CMD + +# Used on cygwin: DLL creation program. +DLLTOOL="$DLLTOOL" + +# Used on cygwin: object dumper. +OBJDUMP="$OBJDUMP" + +# Used on cygwin: assembler. +AS="$AS" + +# The name of the directory that contains temporary libtool files. +objdir=$objdir + +# How to create reloadable object files. +reload_flag=$lt_reload_flag +reload_cmds=$lt_reload_cmds + +# How to pass a linker flag through the compiler. +wl=$lt_lt_prog_compiler_wl_RC + +# Object file suffix (normally "o"). +objext="$ac_objext" + +# Old archive suffix (normally "a"). +libext="$libext" + +# Shared library suffix (normally ".so"). +shrext_cmds='$shrext_cmds' + +# Executable file suffix (normally ""). +exeext="$exeext" + +# Additional compiler flags for building library objects. +pic_flag=$lt_lt_prog_compiler_pic_RC +pic_mode=$pic_mode + +# What is the maximum length of a command? +max_cmd_len=$lt_cv_sys_max_cmd_len + +# Does compiler simultaneously support -c and -o options? +compiler_c_o=$lt_lt_cv_prog_compiler_c_o_RC + +# Must we lock files when doing compilation? +need_locks=$lt_need_locks + +# Do we need the lib prefix for modules? +need_lib_prefix=$need_lib_prefix + +# Do we need a version for libraries? +need_version=$need_version + +# Whether dlopen is supported. +dlopen_support=$enable_dlopen + +# Whether dlopen of programs is supported. +dlopen_self=$enable_dlopen_self + +# Whether dlopen of statically linked programs is supported. +dlopen_self_static=$enable_dlopen_self_static + +# Compiler flag to prevent dynamic linking. +link_static_flag=$lt_lt_prog_compiler_static_RC + +# Compiler flag to turn off builtin functions. +no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_RC + +# Compiler flag to allow reflexive dlopens. +export_dynamic_flag_spec=$lt_export_dynamic_flag_spec_RC + +# Compiler flag to generate shared objects directly from archives. +whole_archive_flag_spec=$lt_whole_archive_flag_spec_RC + +# Compiler flag to generate thread-safe objects. +thread_safe_flag_spec=$lt_thread_safe_flag_spec_RC + +# Library versioning type. +version_type=$version_type + +# Format of library name prefix. +libname_spec=$lt_libname_spec + +# List of archive names. First name is the real one, the rest are links. +# The last name is the one that the linker finds with -lNAME. +library_names_spec=$lt_library_names_spec + +# The coded name of the library, if different from the real name. +soname_spec=$lt_soname_spec + +# Commands used to build and install an old-style archive. +RANLIB=$lt_RANLIB +old_archive_cmds=$lt_old_archive_cmds_RC +old_postinstall_cmds=$lt_old_postinstall_cmds +old_postuninstall_cmds=$lt_old_postuninstall_cmds + +# Create an old-style archive from a shared archive. +old_archive_from_new_cmds=$lt_old_archive_from_new_cmds_RC + +# Create a temporary old-style archive to link instead of a shared archive. +old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds_RC + +# Commands used to build and install a shared archive. +archive_cmds=$lt_archive_cmds_RC +archive_expsym_cmds=$lt_archive_expsym_cmds_RC +postinstall_cmds=$lt_postinstall_cmds +postuninstall_cmds=$lt_postuninstall_cmds + +# Commands used to build a loadable module (assumed same as above if empty) +module_cmds=$lt_module_cmds_RC +module_expsym_cmds=$lt_module_expsym_cmds_RC + +# Commands to strip libraries. +old_striplib=$lt_old_striplib +striplib=$lt_striplib + +# Dependencies to place before the objects being linked to create a +# shared library. +predep_objects=$lt_predep_objects_RC + +# Dependencies to place after the objects being linked to create a +# shared library. +postdep_objects=$lt_postdep_objects_RC + +# Dependencies to place before the objects being linked to create a +# shared library. +predeps=$lt_predeps_RC + +# Dependencies to place after the objects being linked to create a +# shared library. +postdeps=$lt_postdeps_RC + +# The library search path used internally by the compiler when linking +# a shared library. +compiler_lib_search_path=$lt_compiler_lib_search_path_RC + +# Method to check whether dependent libraries are shared objects. +deplibs_check_method=$lt_deplibs_check_method + +# Command to use when deplibs_check_method == file_magic. +file_magic_cmd=$lt_file_magic_cmd + +# Flag that allows shared libraries with undefined symbols to be built. +allow_undefined_flag=$lt_allow_undefined_flag_RC + +# Flag that forces no undefined symbols. +no_undefined_flag=$lt_no_undefined_flag_RC + +# Commands used to finish a libtool library installation in a directory. +finish_cmds=$lt_finish_cmds + +# Same as above, but a single script fragment to be evaled but not shown. +finish_eval=$lt_finish_eval + +# Take the output of nm and produce a listing of raw symbols and C names. +global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe + +# Transform the output of nm in a proper C declaration +global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl + +# Transform the output of nm in a C name address pair +global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address + +# This is the shared library runtime path variable. +runpath_var=$runpath_var + +# This is the shared library path variable. +shlibpath_var=$shlibpath_var + +# Is shlibpath searched before the hard-coded library search path? +shlibpath_overrides_runpath=$shlibpath_overrides_runpath + +# How to hardcode a shared library path into an executable. +hardcode_action=$hardcode_action_RC + +# Whether we should hardcode library paths into libraries. +hardcode_into_libs=$hardcode_into_libs + +# Flag to hardcode \$libdir into a binary during linking. +# This must work even if \$libdir does not exist. +hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_RC + +# If ld is used when linking, flag to hardcode \$libdir into +# a binary during linking. This must work even if \$libdir does +# not exist. +hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld_RC + +# Whether we need a single -rpath flag with a separated argument. +hardcode_libdir_separator=$lt_hardcode_libdir_separator_RC + +# Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the +# resulting binary. +hardcode_direct=$hardcode_direct_RC + +# Set to yes if using the -LDIR flag during linking hardcodes DIR into the +# resulting binary. +hardcode_minus_L=$hardcode_minus_L_RC + +# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into +# the resulting binary. +hardcode_shlibpath_var=$hardcode_shlibpath_var_RC + +# Set to yes if building a shared library automatically hardcodes DIR into the library +# and all subsequent libraries and executables linked against it. +hardcode_automatic=$hardcode_automatic_RC + +# Variables whose values should be saved in libtool wrapper scripts and +# restored at relink time. +variables_saved_for_relink="$variables_saved_for_relink" + +# Whether libtool must link a program against all its dependency libraries. +link_all_deplibs=$link_all_deplibs_RC + +# Compile-time system search path for libraries +sys_lib_search_path_spec=$lt_sys_lib_search_path_spec + +# Run-time system search path for libraries +sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec + +# Fix the shell variable \$srcfile for the compiler. +fix_srcfile_path="$fix_srcfile_path_RC" + +# Set to yes if exported symbols are required. +always_export_symbols=$always_export_symbols_RC + +# The commands to list exported symbols. +export_symbols_cmds=$lt_export_symbols_cmds_RC + +# The commands to extract the exported symbol list from a shared archive. +extract_expsyms_cmds=$lt_extract_expsyms_cmds + +# Symbols that should not be listed in the preloaded symbols. +exclude_expsyms=$lt_exclude_expsyms_RC + +# Symbols that must always be exported. +include_expsyms=$lt_include_expsyms_RC + +# ### END LIBTOOL TAG CONFIG: $tagname + +__EOF__ + + +else + # If there is no Makefile yet, we rely on a make rule to execute + # `config.status --recheck' to rerun these tests and create the + # libtool script then. + ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'` + if test -f "$ltmain_in"; then + test -f Makefile && make "$ltmain" + fi +fi + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +CC="$lt_save_CC" + + ;; + + *) + { { echo "$as_me:$LINENO: error: Unsupported tag name: $tagname" >&5 +echo "$as_me: error: Unsupported tag name: $tagname" >&2;} + { (exit 1); exit 1; }; } + ;; + esac + + # Append the new tag name to the list of available tags. + if test -n "$tagname" ; then + available_tags="$available_tags $tagname" + fi + fi + done + IFS="$lt_save_ifs" + + # Now substitute the updated list of available tags. + if eval "sed -e 's/^available_tags=.*\$/available_tags=\"$available_tags\"/' \"$ofile\" > \"${ofile}T\""; then + mv "${ofile}T" "$ofile" + chmod +x "$ofile" + else + rm -f "${ofile}T" + { { echo "$as_me:$LINENO: error: unable to update list of available tagged configurations." >&5 +echo "$as_me: error: unable to update list of available tagged configurations." >&2;} + { (exit 1); exit 1; }; } + fi +fi + + + +# This can be used to rebuild libtool when needed +LIBTOOL_DEPS="$ac_aux_dir/ltmain.sh" + +# Always use our own libtool. +LIBTOOL='$(SHELL) $(top_builddir)/mklib' + +# Prevent multiple expansion + + + + + + + + + + + + + + + + + + + + + +if test "$lt_cv_dlopen_self" = "yes" ; then + +cat >>confdefs.h <<\_ACEOF +#define CAN_DLOPEN_SELF 1 +_ACEOF + +fi + + +if test "$WITH_LLVMGCCDIR" = "default" ; then + LLVMGCC="llvm-gcc${EXEEXT}" + LLVMGXX="llvm-g++${EXEEXT}" + LLVMGCCCOMMAND="$LLVMGCC" + LLVMGXXCOMMAND="$LLVMGXX" + LLVMGCCCOMMAND=$LLVMGCCCOMMAND + + LLVMGXXCOMMAND=$LLVMGXXCOMMAND + + # Extract the first word of "$LLVMGCC", so it can be a program name with args. +set dummy $LLVMGCC; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_LLVMGCC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $LLVMGCC in + [\\/]* | ?:[\\/]*) + ac_cv_path_LLVMGCC="$LLVMGCC" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_LLVMGCC="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + ;; +esac +fi +LLVMGCC=$ac_cv_path_LLVMGCC +if test -n "$LLVMGCC"; then + { echo "$as_me:$LINENO: result: $LLVMGCC" >&5 +echo "${ECHO_T}$LLVMGCC" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + # Extract the first word of "$LLVMGXX", so it can be a program name with args. +set dummy $LLVMGXX; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_LLVMGXX+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $LLVMGXX in + [\\/]* | ?:[\\/]*) + ac_cv_path_LLVMGXX="$LLVMGXX" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_LLVMGXX="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + ;; +esac +fi +LLVMGXX=$ac_cv_path_LLVMGXX +if test -n "$LLVMGXX"; then + { echo "$as_me:$LINENO: result: $LLVMGXX" >&5 +echo "${ECHO_T}$LLVMGXX" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +else + if test -z "$LLVMGCC"; then + LLVMGCC="$WITH_LLVMGCCDIR/bin/llvm-gcc${EXEEXT}" + LLVMGCCCOMMAND="$LLVMGCC" + fi + if test -z "$LLVMGXX"; then + LLVMGXX="$WITH_LLVMGCCDIR/bin/llvm-g++${EXEEXT}" + LLVMGXXCOMMAND="$LLVMGXX" + fi + + LLVMGCC=$LLVMGCC + + LLVMGXX=$LLVMGXX + + LLVMGCCCOMMAND=$LLVMGCCCOMMAND + + LLVMGXXCOMMAND=$LLVMGXXCOMMAND + +fi + + +{ echo "$as_me:$LINENO: checking tool compatibility" >&5 +echo $ECHO_N "checking tool compatibility... $ECHO_C" >&6; } + +ICC=no +IXX=no +case $CC in + icc*|icpc*) + ICC=yes + IXX=yes + ;; + *) + ;; +esac + +if test "$GCC" != "yes" && test "$ICC" != "yes" +then + { { echo "$as_me:$LINENO: error: gcc|icc required but not found" >&5 +echo "$as_me: error: gcc|icc required but not found" >&2;} + { (exit 1); exit 1; }; } +fi + +if test "$GXX" != "yes" && test "$IXX" != "yes" +then + { { echo "$as_me:$LINENO: error: g++|icc required but not found" >&5 +echo "$as_me: error: g++|icc required but not found" >&2;} + { (exit 1); exit 1; }; } +fi + +if test "$GCC" = "yes" +then + cat >conftest.$ac_ext <<_ACEOF +#if !defined(__GNUC__) || __GNUC__ < 3 +#error Unsupported GCC version +#endif + +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + { { echo "$as_me:$LINENO: error: gcc 3.x required, but you have a lower version" >&5 +echo "$as_me: error: gcc 3.x required, but you have a lower version" >&2;} + { (exit 1); exit 1; }; } +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi + +if test -z "$llvm_cv_gnu_make_command" +then + { { echo "$as_me:$LINENO: error: GNU Make required but not found" >&5 +echo "$as_me: error: GNU Make required but not found" >&2;} + { (exit 1); exit 1; }; } +fi + +{ echo "$as_me:$LINENO: result: ok" >&5 +echo "${ECHO_T}ok" >&6; } + +{ echo "$as_me:$LINENO: checking optional compiler flags" >&5 +echo $ECHO_N "checking optional compiler flags... $ECHO_C" >&6; } +NO_VARIADIC_MACROS=`$CXX -Wno-variadic-macros -fsyntax-only -xc /dev/null 2>/dev/null && echo -Wno-variadic-macros` + +NO_MISSING_FIELD_INITIALIZERS=`$CXX -Wno-missing-field-initializers -fsyntax-only -xc /dev/null 2>/dev/null && echo -Wno-missing-field-initializers` + +{ echo "$as_me:$LINENO: result: $NO_VARIADIC_MACROS $NO_MISSING_FIELD_INITIALIZERS" >&5 +echo "${ECHO_T}$NO_VARIADIC_MACROS $NO_MISSING_FIELD_INITIALIZERS" >&6; } + + + +{ echo "$as_me:$LINENO: checking for sin in -lm" >&5 +echo $ECHO_N "checking for sin in -lm... $ECHO_C" >&6; } +if test "${ac_cv_lib_m_sin+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lm $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char sin (); +int +main () +{ +return sin (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_m_sin=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_m_sin=no +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_m_sin" >&5 +echo "${ECHO_T}$ac_cv_lib_m_sin" >&6; } +if test $ac_cv_lib_m_sin = yes; then + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBM 1 +_ACEOF + + LIBS="-lm $LIBS" + +fi + +if test "$llvm_cv_os_type" = "MingW" ; then + +{ echo "$as_me:$LINENO: checking for main in -limagehlp" >&5 +echo $ECHO_N "checking for main in -limagehlp... $ECHO_C" >&6; } +if test "${ac_cv_lib_imagehlp_main+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-limagehlp $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + + +int +main () +{ +return main (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_imagehlp_main=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_imagehlp_main=no +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_imagehlp_main" >&5 +echo "${ECHO_T}$ac_cv_lib_imagehlp_main" >&6; } +if test $ac_cv_lib_imagehlp_main = yes; then + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBIMAGEHLP 1 +_ACEOF + + LIBS="-limagehlp $LIBS" + +fi + + +{ echo "$as_me:$LINENO: checking for main in -lpsapi" >&5 +echo $ECHO_N "checking for main in -lpsapi... $ECHO_C" >&6; } +if test "${ac_cv_lib_psapi_main+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lpsapi $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + + +int +main () +{ +return main (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_psapi_main=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_psapi_main=no +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_psapi_main" >&5 +echo "${ECHO_T}$ac_cv_lib_psapi_main" >&6; } +if test $ac_cv_lib_psapi_main = yes; then + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBPSAPI 1 +_ACEOF + + LIBS="-lpsapi $LIBS" + +fi + +fi + +{ echo "$as_me:$LINENO: checking for library containing dlopen" >&5 +echo $ECHO_N "checking for library containing dlopen... $ECHO_C" >&6; } +if test "${ac_cv_search_dlopen+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_func_search_save_LIBS=$LIBS +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dlopen (); +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +for ac_lib in '' dl; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_search_dlopen=$ac_res +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if test "${ac_cv_search_dlopen+set}" = set; then + break +fi +done +if test "${ac_cv_search_dlopen+set}" = set; then + : +else + ac_cv_search_dlopen=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_search_dlopen" >&5 +echo "${ECHO_T}$ac_cv_search_dlopen" >&6; } +ac_res=$ac_cv_search_dlopen +if test "$ac_res" != no; then + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +cat >>confdefs.h <<\_ACEOF +#define HAVE_DLOPEN 1 +_ACEOF + +else + { echo "$as_me:$LINENO: WARNING: dlopen() not found - disabling plugin support" >&5 +echo "$as_me: WARNING: dlopen() not found - disabling plugin support" >&2;} +fi + + +if test "$llvm_cv_enable_libffi" = "yes" ; then + { echo "$as_me:$LINENO: checking for library containing ffi_call" >&5 +echo $ECHO_N "checking for library containing ffi_call... $ECHO_C" >&6; } +if test "${ac_cv_search_ffi_call+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_func_search_save_LIBS=$LIBS +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char ffi_call (); +int +main () +{ +return ffi_call (); + ; + return 0; +} +_ACEOF +for ac_lib in '' ffi; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_search_ffi_call=$ac_res +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if test "${ac_cv_search_ffi_call+set}" = set; then + break +fi +done +if test "${ac_cv_search_ffi_call+set}" = set; then + : +else + ac_cv_search_ffi_call=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_search_ffi_call" >&5 +echo "${ECHO_T}$ac_cv_search_ffi_call" >&6; } +ac_res=$ac_cv_search_ffi_call +if test "$ac_res" != no; then + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +cat >>confdefs.h <<\_ACEOF +#define HAVE_FFI_CALL 1 +_ACEOF + +else + { echo "$as_me:$LINENO: WARNING: libffi not found - disabling external calls from interpreter" >&5 +echo "$as_me: WARNING: libffi not found - disabling external calls from interpreter" >&2;} +fi + +fi + +{ echo "$as_me:$LINENO: checking for library containing mallinfo" >&5 +echo $ECHO_N "checking for library containing mallinfo... $ECHO_C" >&6; } +if test "${ac_cv_search_mallinfo+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_func_search_save_LIBS=$LIBS +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char mallinfo (); +int +main () +{ +return mallinfo (); + ; + return 0; +} +_ACEOF +for ac_lib in '' malloc; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_search_mallinfo=$ac_res +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if test "${ac_cv_search_mallinfo+set}" = set; then + break +fi +done +if test "${ac_cv_search_mallinfo+set}" = set; then + : +else + ac_cv_search_mallinfo=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_search_mallinfo" >&5 +echo "${ECHO_T}$ac_cv_search_mallinfo" >&6; } +ac_res=$ac_cv_search_mallinfo +if test "$ac_res" != no; then + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +cat >>confdefs.h <<\_ACEOF +#define HAVE_MALLINFO 1 +_ACEOF + +fi + + +if test "$ENABLE_THREADS" -eq 1 ; then + +{ echo "$as_me:$LINENO: checking for pthread_mutex_init in -lpthread" >&5 +echo $ECHO_N "checking for pthread_mutex_init in -lpthread... $ECHO_C" >&6; } +if test "${ac_cv_lib_pthread_pthread_mutex_init+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lpthread $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char pthread_mutex_init (); +int +main () +{ +return pthread_mutex_init (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_pthread_pthread_mutex_init=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_pthread_pthread_mutex_init=no +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_pthread_pthread_mutex_init" >&5 +echo "${ECHO_T}$ac_cv_lib_pthread_pthread_mutex_init" >&6; } +if test $ac_cv_lib_pthread_pthread_mutex_init = yes; then + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBPTHREAD 1 +_ACEOF + + LIBS="-lpthread $LIBS" + +fi + + { echo "$as_me:$LINENO: checking for library containing pthread_mutex_lock" >&5 +echo $ECHO_N "checking for library containing pthread_mutex_lock... $ECHO_C" >&6; } +if test "${ac_cv_search_pthread_mutex_lock+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_func_search_save_LIBS=$LIBS +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char pthread_mutex_lock (); +int +main () +{ +return pthread_mutex_lock (); + ; + return 0; +} +_ACEOF +for ac_lib in '' pthread; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_search_pthread_mutex_lock=$ac_res +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if test "${ac_cv_search_pthread_mutex_lock+set}" = set; then + break +fi +done +if test "${ac_cv_search_pthread_mutex_lock+set}" = set; then + : +else + ac_cv_search_pthread_mutex_lock=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_search_pthread_mutex_lock" >&5 +echo "${ECHO_T}$ac_cv_search_pthread_mutex_lock" >&6; } +ac_res=$ac_cv_search_pthread_mutex_lock +if test "$ac_res" != no; then + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +cat >>confdefs.h <<\_ACEOF +#define HAVE_PTHREAD_MUTEX_LOCK 1 +_ACEOF + +fi + + { echo "$as_me:$LINENO: checking for library containing pthread_rwlock_init" >&5 +echo $ECHO_N "checking for library containing pthread_rwlock_init... $ECHO_C" >&6; } +if test "${ac_cv_search_pthread_rwlock_init+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_func_search_save_LIBS=$LIBS +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char pthread_rwlock_init (); +int +main () +{ +return pthread_rwlock_init (); + ; + return 0; +} +_ACEOF +for ac_lib in '' pthread; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_search_pthread_rwlock_init=$ac_res +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if test "${ac_cv_search_pthread_rwlock_init+set}" = set; then + break +fi +done +if test "${ac_cv_search_pthread_rwlock_init+set}" = set; then + : +else + ac_cv_search_pthread_rwlock_init=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_search_pthread_rwlock_init" >&5 +echo "${ECHO_T}$ac_cv_search_pthread_rwlock_init" >&6; } +ac_res=$ac_cv_search_pthread_rwlock_init +if test "$ac_res" != no; then + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +cat >>confdefs.h <<\_ACEOF +#define HAVE_PTHREAD_RWLOCK_INIT 1 +_ACEOF + +fi + + { echo "$as_me:$LINENO: checking for library containing pthread_getspecific" >&5 +echo $ECHO_N "checking for library containing pthread_getspecific... $ECHO_C" >&6; } +if test "${ac_cv_search_pthread_getspecific+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_func_search_save_LIBS=$LIBS +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char pthread_getspecific (); +int +main () +{ +return pthread_getspecific (); + ; + return 0; +} +_ACEOF +for ac_lib in '' pthread; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_search_pthread_getspecific=$ac_res +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if test "${ac_cv_search_pthread_getspecific+set}" = set; then + break +fi +done +if test "${ac_cv_search_pthread_getspecific+set}" = set; then + : +else + ac_cv_search_pthread_getspecific=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_search_pthread_getspecific" >&5 +echo "${ECHO_T}$ac_cv_search_pthread_getspecific" >&6; } +ac_res=$ac_cv_search_pthread_getspecific +if test "$ac_res" != no; then + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +cat >>confdefs.h <<\_ACEOF +#define HAVE_PTHREAD_GETSPECIFIC 1 +_ACEOF + +fi + +fi + + +# Check whether --with-udis86 was given. +if test "${with_udis86+set}" = set; then + withval=$with_udis86; + USE_UDIS86=1 + + case "$withval" in + /usr/lib|yes) ;; + *) LDFLAGS="$LDFLAGS -L${withval}" ;; + esac + +{ echo "$as_me:$LINENO: checking for ud_init in -ludis86" >&5 +echo $ECHO_N "checking for ud_init in -ludis86... $ECHO_C" >&6; } +if test "${ac_cv_lib_udis86_ud_init+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ludis86 $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char ud_init (); +int +main () +{ +return ud_init (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_udis86_ud_init=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_udis86_ud_init=no +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_udis86_ud_init" >&5 +echo "${ECHO_T}$ac_cv_lib_udis86_ud_init" >&6; } +if test $ac_cv_lib_udis86_ud_init = yes; then + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBUDIS86 1 +_ACEOF + + LIBS="-ludis86 $LIBS" + +else + + echo "Error! You need to have libudis86 around." + exit -1 + +fi + + +else + USE_UDIS86=0 + +fi + + +cat >>confdefs.h <<_ACEOF +#define USE_UDIS86 $USE_UDIS86 +_ACEOF + + + +# Check whether --with-oprofile was given. +if test "${with_oprofile+set}" = set; then + withval=$with_oprofile; + USE_OPROFILE=1 + + case "$withval" in + /usr|yes) llvm_cv_oppath=/usr/lib/oprofile ;; + no) llvm_cv_oppath= + USE_OPROFILE=0 + ;; + *) llvm_cv_oppath="${withval}/lib/oprofile" + CPPFLAGS="-I${withval}/include";; + esac + if test -n "$llvm_cv_oppath" ; then + LIBS="$LIBS -L${llvm_cv_oppath} -Wl,-rpath,${llvm_cv_oppath}" + { echo "$as_me:$LINENO: checking for library containing bfd_init" >&5 +echo $ECHO_N "checking for library containing bfd_init... $ECHO_C" >&6; } +if test "${ac_cv_search_bfd_init+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_func_search_save_LIBS=$LIBS +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char bfd_init (); +int +main () +{ +return bfd_init (); + ; + return 0; +} +_ACEOF +for ac_lib in '' bfd; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_search_bfd_init=$ac_res +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if test "${ac_cv_search_bfd_init+set}" = set; then + break +fi +done +if test "${ac_cv_search_bfd_init+set}" = set; then + : +else + ac_cv_search_bfd_init=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_search_bfd_init" >&5 +echo "${ECHO_T}$ac_cv_search_bfd_init" >&6; } +ac_res=$ac_cv_search_bfd_init +if test "$ac_res" != no; then + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +fi + + { echo "$as_me:$LINENO: checking for library containing op_open_agent" >&5 +echo $ECHO_N "checking for library containing op_open_agent... $ECHO_C" >&6; } +if test "${ac_cv_search_op_open_agent+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_func_search_save_LIBS=$LIBS +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char op_open_agent (); +int +main () +{ +return op_open_agent (); + ; + return 0; +} +_ACEOF +for ac_lib in '' opagent; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_search_op_open_agent=$ac_res +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if test "${ac_cv_search_op_open_agent+set}" = set; then + break +fi +done +if test "${ac_cv_search_op_open_agent+set}" = set; then + : +else + ac_cv_search_op_open_agent=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_search_op_open_agent" >&5 +echo "${ECHO_T}$ac_cv_search_op_open_agent" >&6; } +ac_res=$ac_cv_search_op_open_agent +if test "$ac_res" != no; then + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +else + + echo "Error! You need to have libopagent around." + exit -1 + +fi + + if test "${ac_cv_header_opagent_h+set}" = set; then + { echo "$as_me:$LINENO: checking for opagent.h" >&5 +echo $ECHO_N "checking for opagent.h... $ECHO_C" >&6; } +if test "${ac_cv_header_opagent_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +{ echo "$as_me:$LINENO: result: $ac_cv_header_opagent_h" >&5 +echo "${ECHO_T}$ac_cv_header_opagent_h" >&6; } +else + # Is the header compilable? +{ echo "$as_me:$LINENO: checking opagent.h usability" >&5 +echo $ECHO_N "checking opagent.h usability... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6; } + +# Is the header present? +{ echo "$as_me:$LINENO: checking opagent.h presence" >&5 +echo $ECHO_N "checking opagent.h presence... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -f conftest.err conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: opagent.h: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: opagent.h: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: opagent.h: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: opagent.h: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: opagent.h: present but cannot be compiled" >&5 +echo "$as_me: WARNING: opagent.h: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: opagent.h: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: opagent.h: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: opagent.h: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: opagent.h: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: opagent.h: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: opagent.h: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: opagent.h: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: opagent.h: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: opagent.h: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: opagent.h: in the future, the compiler will take precedence" >&2;} + ( cat <<\_ASBOX +## ----------------------------------- ## +## Report this to llvmbugs@cs.uiuc.edu ## +## ----------------------------------- ## +_ASBOX + ) | sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +{ echo "$as_me:$LINENO: checking for opagent.h" >&5 +echo $ECHO_N "checking for opagent.h... $ECHO_C" >&6; } +if test "${ac_cv_header_opagent_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_header_opagent_h=$ac_header_preproc +fi +{ echo "$as_me:$LINENO: result: $ac_cv_header_opagent_h" >&5 +echo "${ECHO_T}$ac_cv_header_opagent_h" >&6; } + +fi +if test $ac_cv_header_opagent_h = yes; then + : +else + + echo "Error! You need to have opagent.h around." + exit -1 + +fi + + + fi + +else + + USE_OPROFILE=0 + + +fi + + +cat >>confdefs.h <<_ACEOF +#define USE_OPROFILE $USE_OPROFILE +_ACEOF + + + + + + + + +ac_header_dirent=no +for ac_hdr in dirent.h sys/ndir.h sys/dir.h ndir.h; do + as_ac_Header=`echo "ac_cv_header_dirent_$ac_hdr" | $as_tr_sh` +{ echo "$as_me:$LINENO: checking for $ac_hdr that defines DIR" >&5 +echo $ECHO_N "checking for $ac_hdr that defines DIR... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include <$ac_hdr> + +int +main () +{ +if ((DIR *) 0) +return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_Header=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_Header=no" +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_hdr" | $as_tr_cpp` 1 +_ACEOF + +ac_header_dirent=$ac_hdr; break +fi + +done +# Two versions of opendir et al. are in -ldir and -lx on SCO Xenix. +if test $ac_header_dirent = dirent.h; then + { echo "$as_me:$LINENO: checking for library containing opendir" >&5 +echo $ECHO_N "checking for library containing opendir... $ECHO_C" >&6; } +if test "${ac_cv_search_opendir+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_func_search_save_LIBS=$LIBS +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char opendir (); +int +main () +{ +return opendir (); + ; + return 0; +} +_ACEOF +for ac_lib in '' dir; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_search_opendir=$ac_res +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if test "${ac_cv_search_opendir+set}" = set; then + break +fi +done +if test "${ac_cv_search_opendir+set}" = set; then + : +else + ac_cv_search_opendir=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_search_opendir" >&5 +echo "${ECHO_T}$ac_cv_search_opendir" >&6; } +ac_res=$ac_cv_search_opendir +if test "$ac_res" != no; then + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +fi + +else + { echo "$as_me:$LINENO: checking for library containing opendir" >&5 +echo $ECHO_N "checking for library containing opendir... $ECHO_C" >&6; } +if test "${ac_cv_search_opendir+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_func_search_save_LIBS=$LIBS +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char opendir (); +int +main () +{ +return opendir (); + ; + return 0; +} +_ACEOF +for ac_lib in '' x; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_search_opendir=$ac_res +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if test "${ac_cv_search_opendir+set}" = set; then + break +fi +done +if test "${ac_cv_search_opendir+set}" = set; then + : +else + ac_cv_search_opendir=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_search_opendir" >&5 +echo "${ECHO_T}$ac_cv_search_opendir" >&6; } +ac_res=$ac_cv_search_opendir +if test "$ac_res" != no; then + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +fi + +fi + +{ echo "$as_me:$LINENO: checking for MAP_ANONYMOUS vs. MAP_ANON" >&5 +echo $ECHO_N "checking for MAP_ANONYMOUS vs. MAP_ANON... $ECHO_C" >&6; } +if test "${ac_cv_header_mmap_anon+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include +#include +int +main () +{ +mmap (0, 1, PROT_READ, MAP_ANONYMOUS, -1, 0); return (0); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_header_mmap_anon=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_header_mmap_anon=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_header_mmap_anon" >&5 +echo "${ECHO_T}$ac_cv_header_mmap_anon" >&6; } +if test "$ac_cv_header_mmap_anon" = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_MMAP_ANONYMOUS 1 +_ACEOF + +fi + +{ echo "$as_me:$LINENO: checking whether stat file-mode macros are broken" >&5 +echo $ECHO_N "checking whether stat file-mode macros are broken... $ECHO_C" >&6; } +if test "${ac_cv_header_stat_broken+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include + +#if defined S_ISBLK && defined S_IFDIR +# if S_ISBLK (S_IFDIR) +You lose. +# endif +#endif + +#if defined S_ISBLK && defined S_IFCHR +# if S_ISBLK (S_IFCHR) +You lose. +# endif +#endif + +#if defined S_ISLNK && defined S_IFREG +# if S_ISLNK (S_IFREG) +You lose. +# endif +#endif + +#if defined S_ISSOCK && defined S_IFREG +# if S_ISSOCK (S_IFREG) +You lose. +# endif +#endif + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "You lose" >/dev/null 2>&1; then + ac_cv_header_stat_broken=yes +else + ac_cv_header_stat_broken=no +fi +rm -f conftest* + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_header_stat_broken" >&5 +echo "${ECHO_T}$ac_cv_header_stat_broken" >&6; } +if test $ac_cv_header_stat_broken = yes; then + +cat >>confdefs.h <<\_ACEOF +#define STAT_MACROS_BROKEN 1 +_ACEOF + +fi + +{ echo "$as_me:$LINENO: checking for ANSI C header files" >&5 +echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6; } +if test "${ac_cv_header_stdc+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include +#include +#include + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_header_stdc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_header_stdc=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "memchr" >/dev/null 2>&1; then + : +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "free" >/dev/null 2>&1; then + : +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. + if test "$cross_compiling" = yes; then + : +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include +#if ((' ' & 0x0FF) == 0x020) +# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#else +# define ISLOWER(c) \ + (('a' <= (c) && (c) <= 'i') \ + || ('j' <= (c) && (c) <= 'r') \ + || ('s' <= (c) && (c) <= 'z')) +# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) +#endif + +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int +main () +{ + int i; + for (i = 0; i < 256; i++) + if (XOR (islower (i), ISLOWER (i)) + || toupper (i) != TOUPPER (i)) + return 2; + return 0; +} +_ACEOF +rm -f conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + : +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +ac_cv_header_stdc=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + + +fi +fi +{ echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5 +echo "${ECHO_T}$ac_cv_header_stdc" >&6; } +if test $ac_cv_header_stdc = yes; then + +cat >>confdefs.h <<\_ACEOF +#define STDC_HEADERS 1 +_ACEOF + +fi + +{ echo "$as_me:$LINENO: checking for sys/wait.h that is POSIX.1 compatible" >&5 +echo $ECHO_N "checking for sys/wait.h that is POSIX.1 compatible... $ECHO_C" >&6; } +if test "${ac_cv_header_sys_wait_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include +#ifndef WEXITSTATUS +# define WEXITSTATUS(stat_val) ((unsigned int) (stat_val) >> 8) +#endif +#ifndef WIFEXITED +# define WIFEXITED(stat_val) (((stat_val) & 255) == 0) +#endif + +int +main () +{ + int s; + wait (&s); + s = WIFEXITED (s) ? WEXITSTATUS (s) : 1; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_header_sys_wait_h=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_header_sys_wait_h=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ac_cv_header_sys_wait_h" >&5 +echo "${ECHO_T}$ac_cv_header_sys_wait_h" >&6; } +if test $ac_cv_header_sys_wait_h = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_SYS_WAIT_H 1 +_ACEOF + +fi + +{ echo "$as_me:$LINENO: checking whether time.h and sys/time.h may both be included" >&5 +echo $ECHO_N "checking whether time.h and sys/time.h may both be included... $ECHO_C" >&6; } +if test "${ac_cv_header_time+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include +#include + +int +main () +{ +if ((struct tm *) 0) +return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_header_time=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_header_time=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ac_cv_header_time" >&5 +echo "${ECHO_T}$ac_cv_header_time" >&6; } +if test $ac_cv_header_time = yes; then + +cat >>confdefs.h <<\_ACEOF +#define TIME_WITH_SYS_TIME 1 +_ACEOF + +fi + + + + + + + + +for ac_header in dlfcn.h execinfo.h fcntl.h inttypes.h limits.h link.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + { echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +else + # Is the header compilable? +{ echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6; } + +# Is the header present? +{ echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -f conftest.err conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + ( cat <<\_ASBOX +## ----------------------------------- ## +## Report this to llvmbugs@cs.uiuc.edu ## +## ----------------------------------- ## +_ASBOX + ) | sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +{ echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + + + + + + +for ac_header in malloc.h setjmp.h signal.h stdint.h termios.h unistd.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + { echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +else + # Is the header compilable? +{ echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6; } + +# Is the header present? +{ echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -f conftest.err conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + ( cat <<\_ASBOX +## ----------------------------------- ## +## Report this to llvmbugs@cs.uiuc.edu ## +## ----------------------------------- ## +_ASBOX + ) | sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +{ echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + + +for ac_header in utime.h windows.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + { echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +else + # Is the header compilable? +{ echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6; } + +# Is the header present? +{ echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -f conftest.err conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + ( cat <<\_ASBOX +## ----------------------------------- ## +## Report this to llvmbugs@cs.uiuc.edu ## +## ----------------------------------- ## +_ASBOX + ) | sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +{ echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + + + + +for ac_header in sys/mman.h sys/param.h sys/resource.h sys/time.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + { echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +else + # Is the header compilable? +{ echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6; } + +# Is the header present? +{ echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -f conftest.err conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + ( cat <<\_ASBOX +## ----------------------------------- ## +## Report this to llvmbugs@cs.uiuc.edu ## +## ----------------------------------- ## +_ASBOX + ) | sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +{ echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + + + + +for ac_header in sys/types.h sys/ioctl.h malloc/malloc.h mach/mach.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + { echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +else + # Is the header compilable? +{ echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6; } + +# Is the header present? +{ echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -f conftest.err conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + ( cat <<\_ASBOX +## ----------------------------------- ## +## Report this to llvmbugs@cs.uiuc.edu ## +## ----------------------------------- ## +_ASBOX + ) | sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +{ echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + +if test "$ENABLE_THREADS" -eq 1 ; then + +for ac_header in pthread.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + { echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +else + # Is the header compilable? +{ echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6; } + +# Is the header present? +{ echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -f conftest.err conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + ( cat <<\_ASBOX +## ----------------------------------- ## +## Report this to llvmbugs@cs.uiuc.edu ## +## ----------------------------------- ## +_ASBOX + ) | sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +{ echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + HAVE_PTHREAD=1 + +else + HAVE_PTHREAD=0 + +fi + +done + +else + HAVE_PTHREAD=0 + +fi + +if test "$llvm_cv_enable_libffi" = "yes" ; then + + +for ac_header in ffi.h ffi/ffi.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + { echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +else + # Is the header compilable? +{ echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6; } + +# Is the header present? +{ echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -f conftest.err conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + ( cat <<\_ASBOX +## ----------------------------------- ## +## Report this to llvmbugs@cs.uiuc.edu ## +## ----------------------------------- ## +_ASBOX + ) | sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +{ echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + +fi + + + + { echo "$as_me:$LINENO: checking for HUGE_VAL sanity" >&5 +echo $ECHO_N "checking for HUGE_VAL sanity... $ECHO_C" >&6; } +if test "${ac_cv_huge_val_sanity+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + CXXFLAGS=-pedantic + if test "$cross_compiling" = yes; then + ac_cv_huge_val_sanity=yes +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +int +main () +{ +double x = HUGE_VAL; return x != x; + ; + return 0; +} +_ACEOF +rm -f conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_huge_val_sanity=yes +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +ac_cv_huge_val_sanity=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + + + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_huge_val_sanity" >&5 +echo "${ECHO_T}$ac_cv_huge_val_sanity" >&6; } + HUGE_VAL_SANITY=$ac_cv_huge_val_sanity + + +{ echo "$as_me:$LINENO: checking for pid_t" >&5 +echo $ECHO_N "checking for pid_t... $ECHO_C" >&6; } +if test "${ac_cv_type_pid_t+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +typedef pid_t ac__type_new_; +int +main () +{ +if ((ac__type_new_ *) 0) + return 0; +if (sizeof (ac__type_new_)) + return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_type_pid_t=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_type_pid_t=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ac_cv_type_pid_t" >&5 +echo "${ECHO_T}$ac_cv_type_pid_t" >&6; } +if test $ac_cv_type_pid_t = yes; then + : +else + +cat >>confdefs.h <<_ACEOF +#define pid_t int +_ACEOF + +fi + +{ echo "$as_me:$LINENO: checking for size_t" >&5 +echo $ECHO_N "checking for size_t... $ECHO_C" >&6; } +if test "${ac_cv_type_size_t+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +typedef size_t ac__type_new_; +int +main () +{ +if ((ac__type_new_ *) 0) + return 0; +if (sizeof (ac__type_new_)) + return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_type_size_t=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_type_size_t=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ac_cv_type_size_t" >&5 +echo "${ECHO_T}$ac_cv_type_size_t" >&6; } +if test $ac_cv_type_size_t = yes; then + : +else + +cat >>confdefs.h <<_ACEOF +#define size_t unsigned int +_ACEOF + +fi + +{ echo "$as_me:$LINENO: checking return type of signal handlers" >&5 +echo $ECHO_N "checking return type of signal handlers... $ECHO_C" >&6; } +if test "${ac_cv_type_signal+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include + +int +main () +{ +return *(signal (0, 0)) (0) == 1; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_type_signal=int +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_type_signal=void +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ac_cv_type_signal" >&5 +echo "${ECHO_T}$ac_cv_type_signal" >&6; } + +cat >>confdefs.h <<_ACEOF +#define RETSIGTYPE $ac_cv_type_signal +_ACEOF + + +{ echo "$as_me:$LINENO: checking whether struct tm is in sys/time.h or time.h" >&5 +echo $ECHO_N "checking whether struct tm is in sys/time.h or time.h... $ECHO_C" >&6; } +if test "${ac_cv_struct_tm+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include + +int +main () +{ +struct tm *tp; tp->tm_sec; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_struct_tm=time.h +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_struct_tm=sys/time.h +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ac_cv_struct_tm" >&5 +echo "${ECHO_T}$ac_cv_struct_tm" >&6; } +if test $ac_cv_struct_tm = sys/time.h; then + +cat >>confdefs.h <<\_ACEOF +#define TM_IN_SYS_TIME 1 +_ACEOF + +fi + +{ echo "$as_me:$LINENO: checking for int64_t" >&5 +echo $ECHO_N "checking for int64_t... $ECHO_C" >&6; } +if test "${ac_cv_type_int64_t+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +typedef int64_t ac__type_new_; +int +main () +{ +if ((ac__type_new_ *) 0) + return 0; +if (sizeof (ac__type_new_)) + return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_type_int64_t=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_type_int64_t=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ac_cv_type_int64_t" >&5 +echo "${ECHO_T}$ac_cv_type_int64_t" >&6; } +if test $ac_cv_type_int64_t = yes; then + +cat >>confdefs.h <<_ACEOF +#define HAVE_INT64_T 1 +_ACEOF + + +else + { { echo "$as_me:$LINENO: error: Type int64_t required but not found" >&5 +echo "$as_me: error: Type int64_t required but not found" >&2;} + { (exit 1); exit 1; }; } +fi + +{ echo "$as_me:$LINENO: checking for uint64_t" >&5 +echo $ECHO_N "checking for uint64_t... $ECHO_C" >&6; } +if test "${ac_cv_type_uint64_t+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +typedef uint64_t ac__type_new_; +int +main () +{ +if ((ac__type_new_ *) 0) + return 0; +if (sizeof (ac__type_new_)) + return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_type_uint64_t=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_type_uint64_t=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ac_cv_type_uint64_t" >&5 +echo "${ECHO_T}$ac_cv_type_uint64_t" >&6; } +if test $ac_cv_type_uint64_t = yes; then + +cat >>confdefs.h <<_ACEOF +#define HAVE_UINT64_T 1 +_ACEOF + + +else + { echo "$as_me:$LINENO: checking for u_int64_t" >&5 +echo $ECHO_N "checking for u_int64_t... $ECHO_C" >&6; } +if test "${ac_cv_type_u_int64_t+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +typedef u_int64_t ac__type_new_; +int +main () +{ +if ((ac__type_new_ *) 0) + return 0; +if (sizeof (ac__type_new_)) + return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_type_u_int64_t=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_type_u_int64_t=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ac_cv_type_u_int64_t" >&5 +echo "${ECHO_T}$ac_cv_type_u_int64_t" >&6; } +if test $ac_cv_type_u_int64_t = yes; then + +cat >>confdefs.h <<_ACEOF +#define HAVE_U_INT64_T 1 +_ACEOF + + +else + { { echo "$as_me:$LINENO: error: Type uint64_t or u_int64_t required but not found" >&5 +echo "$as_me: error: Type uint64_t or u_int64_t required but not found" >&2;} + { (exit 1); exit 1; }; } +fi + +fi + + + + + + + + + + +for ac_func in backtrace ceilf floorf roundf rintf nearbyintf getcwd +do +as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` +{ echo "$as_me:$LINENO: checking for $ac_func" >&5 +echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; } +if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case declares $ac_func. + For example, HP-UX 11i declares gettimeofday. */ +#define $ac_func innocuous_$ac_func + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $ac_func + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $ac_func (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$ac_func || defined __stub___$ac_func +choke me +#endif + +int +main () +{ +return $ac_func (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_var=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_var=no" +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +ac_res=`eval echo '${'$as_ac_var'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +if test `eval echo '${'$as_ac_var'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + + + + +for ac_func in powf fmodf strtof round +do +as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` +{ echo "$as_me:$LINENO: checking for $ac_func" >&5 +echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; } +if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case declares $ac_func. + For example, HP-UX 11i declares gettimeofday. */ +#define $ac_func innocuous_$ac_func + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $ac_func + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $ac_func (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$ac_func || defined __stub___$ac_func +choke me +#endif + +int +main () +{ +return $ac_func (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_var=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_var=no" +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +ac_res=`eval echo '${'$as_ac_var'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +if test `eval echo '${'$as_ac_var'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + + + + + +for ac_func in getpagesize getrusage getrlimit setrlimit gettimeofday +do +as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` +{ echo "$as_me:$LINENO: checking for $ac_func" >&5 +echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; } +if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case declares $ac_func. + For example, HP-UX 11i declares gettimeofday. */ +#define $ac_func innocuous_$ac_func + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $ac_func + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $ac_func (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$ac_func || defined __stub___$ac_func +choke me +#endif + +int +main () +{ +return $ac_func (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_var=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_var=no" +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +ac_res=`eval echo '${'$as_ac_var'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +if test `eval echo '${'$as_ac_var'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + + + +for ac_func in isatty mkdtemp mkstemp +do +as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` +{ echo "$as_me:$LINENO: checking for $ac_func" >&5 +echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; } +if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case declares $ac_func. + For example, HP-UX 11i declares gettimeofday. */ +#define $ac_func innocuous_$ac_func + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $ac_func + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $ac_func (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$ac_func || defined __stub___$ac_func +choke me +#endif + +int +main () +{ +return $ac_func (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_var=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_var=no" +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +ac_res=`eval echo '${'$as_ac_var'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +if test `eval echo '${'$as_ac_var'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + + + + + +for ac_func in mktemp realpath sbrk setrlimit strdup +do +as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` +{ echo "$as_me:$LINENO: checking for $ac_func" >&5 +echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; } +if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case declares $ac_func. + For example, HP-UX 11i declares gettimeofday. */ +#define $ac_func innocuous_$ac_func + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $ac_func + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $ac_func (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$ac_func || defined __stub___$ac_func +choke me +#endif + +int +main () +{ +return $ac_func (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_var=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_var=no" +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +ac_res=`eval echo '${'$as_ac_var'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +if test `eval echo '${'$as_ac_var'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + + + + +for ac_func in strerror strerror_r strerror_s setenv +do +as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` +{ echo "$as_me:$LINENO: checking for $ac_func" >&5 +echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; } +if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case declares $ac_func. + For example, HP-UX 11i declares gettimeofday. */ +#define $ac_func innocuous_$ac_func + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $ac_func + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $ac_func (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$ac_func || defined __stub___$ac_func +choke me +#endif + +int +main () +{ +return $ac_func (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_var=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_var=no" +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +ac_res=`eval echo '${'$as_ac_var'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +if test `eval echo '${'$as_ac_var'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + + + + +for ac_func in strtoll strtoq sysconf malloc_zone_statistics +do +as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` +{ echo "$as_me:$LINENO: checking for $ac_func" >&5 +echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; } +if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case declares $ac_func. + For example, HP-UX 11i declares gettimeofday. */ +#define $ac_func innocuous_$ac_func + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $ac_func + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $ac_func (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$ac_func || defined __stub___$ac_func +choke me +#endif + +int +main () +{ +return $ac_func (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_var=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_var=no" +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +ac_res=`eval echo '${'$as_ac_var'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +if test `eval echo '${'$as_ac_var'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + + + + +for ac_func in setjmp longjmp sigsetjmp siglongjmp +do +as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` +{ echo "$as_me:$LINENO: checking for $ac_func" >&5 +echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; } +if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case declares $ac_func. + For example, HP-UX 11i declares gettimeofday. */ +#define $ac_func innocuous_$ac_func + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $ac_func + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $ac_func (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$ac_func || defined __stub___$ac_func +choke me +#endif + +int +main () +{ +return $ac_func (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_var=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_var=no" +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +ac_res=`eval echo '${'$as_ac_var'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +if test `eval echo '${'$as_ac_var'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + +{ echo "$as_me:$LINENO: checking if printf has the %a format character" >&5 +echo $ECHO_N "checking if printf has the %a format character... $ECHO_C" >&6; } +if test "${llvm_cv_c_printf_a+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + if test "$cross_compiling" = yes; then + llvmac_cv_c_printf_a=no +else + cat >conftest.$ac_ext <<_ACEOF + + /* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +#include +#include + +int +main () +{ + +volatile double A, B; +char Buffer[100]; +A = 1; +A /= 10.0; +sprintf(Buffer, "%a", A); +B = atof(Buffer); +if (A != B) + return (1); +if (A != 0x1.999999999999ap-4) + return (1); +return (0); + ; + return 0; +} +_ACEOF +rm -f conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + llvm_cv_c_printf_a=yes +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +llvmac_cv_c_printf_a=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + + + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +fi +{ echo "$as_me:$LINENO: result: $llvm_cv_c_printf_a" >&5 +echo "${ECHO_T}$llvm_cv_c_printf_a" >&6; } + if test "$llvm_cv_c_printf_a" = "yes"; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_PRINTF_A 1 +_ACEOF + + fi + +# The Ultrix 4.2 mips builtin alloca declared by alloca.h only works +# for constant arguments. Useless! +{ echo "$as_me:$LINENO: checking for working alloca.h" >&5 +echo $ECHO_N "checking for working alloca.h... $ECHO_C" >&6; } +if test "${ac_cv_working_alloca_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +int +main () +{ +char *p = (char *) alloca (2 * sizeof (int)); + if (p) return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_working_alloca_h=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_working_alloca_h=no +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ac_cv_working_alloca_h" >&5 +echo "${ECHO_T}$ac_cv_working_alloca_h" >&6; } +if test $ac_cv_working_alloca_h = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_ALLOCA_H 1 +_ACEOF + +fi + +{ echo "$as_me:$LINENO: checking for alloca" >&5 +echo $ECHO_N "checking for alloca... $ECHO_C" >&6; } +if test "${ac_cv_func_alloca_works+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#ifdef __GNUC__ +# define alloca __builtin_alloca +#else +# ifdef _MSC_VER +# include +# define alloca _alloca +# else +# if HAVE_ALLOCA_H +# include +# else +# ifdef _AIX + #pragma alloca +# else +# ifndef alloca /* predefined by HP cc +Olibcalls */ +char *alloca (); +# endif +# endif +# endif +# endif +#endif + +int +main () +{ +char *p = (char *) alloca (1); + if (p) return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_alloca_works=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_func_alloca_works=no +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ac_cv_func_alloca_works" >&5 +echo "${ECHO_T}$ac_cv_func_alloca_works" >&6; } + +if test $ac_cv_func_alloca_works = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_ALLOCA 1 +_ACEOF + +else + # The SVR3 libPW and SVR4 libucb both contain incompatible functions +# that cause trouble. Some versions do not even contain alloca or +# contain a buggy version. If you still want to use their alloca, +# use ar to extract alloca.o from them instead of compiling alloca.c. + +ALLOCA=\${LIBOBJDIR}alloca.$ac_objext + +cat >>confdefs.h <<\_ACEOF +#define C_ALLOCA 1 +_ACEOF + + +{ echo "$as_me:$LINENO: checking whether \`alloca.c' needs Cray hooks" >&5 +echo $ECHO_N "checking whether \`alloca.c' needs Cray hooks... $ECHO_C" >&6; } +if test "${ac_cv_os_cray+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#if defined CRAY && ! defined CRAY2 +webecray +#else +wenotbecray +#endif + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "webecray" >/dev/null 2>&1; then + ac_cv_os_cray=yes +else + ac_cv_os_cray=no +fi +rm -f conftest* + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_os_cray" >&5 +echo "${ECHO_T}$ac_cv_os_cray" >&6; } +if test $ac_cv_os_cray = yes; then + for ac_func in _getb67 GETB67 getb67; do + as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` +{ echo "$as_me:$LINENO: checking for $ac_func" >&5 +echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; } +if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case declares $ac_func. + For example, HP-UX 11i declares gettimeofday. */ +#define $ac_func innocuous_$ac_func + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $ac_func + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $ac_func (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$ac_func || defined __stub___$ac_func +choke me +#endif + +int +main () +{ +return $ac_func (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_var=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_var=no" +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +ac_res=`eval echo '${'$as_ac_var'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +if test `eval echo '${'$as_ac_var'}'` = yes; then + +cat >>confdefs.h <<_ACEOF +#define CRAY_STACKSEG_END $ac_func +_ACEOF + + break +fi + + done +fi + +{ echo "$as_me:$LINENO: checking stack direction for C alloca" >&5 +echo $ECHO_N "checking stack direction for C alloca... $ECHO_C" >&6; } +if test "${ac_cv_c_stack_direction+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test "$cross_compiling" = yes; then + ac_cv_c_stack_direction=0 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +find_stack_direction () +{ + static char *addr = 0; + auto char dummy; + if (addr == 0) + { + addr = &dummy; + return find_stack_direction (); + } + else + return (&dummy > addr) ? 1 : -1; +} + +int +main () +{ + return find_stack_direction () < 0; +} +_ACEOF +rm -f conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_c_stack_direction=1 +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +ac_cv_c_stack_direction=-1 +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_c_stack_direction" >&5 +echo "${ECHO_T}$ac_cv_c_stack_direction" >&6; } + +cat >>confdefs.h <<_ACEOF +#define STACK_DIRECTION $ac_cv_c_stack_direction +_ACEOF + + +fi + + +{ echo "$as_me:$LINENO: checking for srand48/lrand48/drand48 in " >&5 +echo $ECHO_N "checking for srand48/lrand48/drand48 in ... $ECHO_C" >&6; } +if test "${ac_cv_func_rand48+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +int +main () +{ +srand48(0);lrand48();drand48(); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_rand48=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_func_rand48=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_func_rand48" >&5 +echo "${ECHO_T}$ac_cv_func_rand48" >&6; } + +if test "$ac_cv_func_rand48" = "yes" ; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_RAND48 1 +_ACEOF + +fi + + +{ echo "$as_me:$LINENO: checking whether the compiler implements namespaces" >&5 +echo $ECHO_N "checking whether the compiler implements namespaces... $ECHO_C" >&6; } +if test "${ac_cv_cxx_namespaces+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +namespace Outer { namespace Inner { int i = 0; }} +int +main () +{ +using namespace Outer::Inner; return i; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_cxx_namespaces=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_cxx_namespaces=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_cxx_namespaces" >&5 +echo "${ECHO_T}$ac_cv_cxx_namespaces" >&6; } +if test "$ac_cv_cxx_namespaces" = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_NAMESPACES +_ACEOF + +fi + +{ echo "$as_me:$LINENO: checking whether the compiler has the standard iterator" >&5 +echo $ECHO_N "checking whether the compiler has the standard iterator... $ECHO_C" >&6; } +if test "${ac_cv_cxx_have_std_iterator+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#ifdef HAVE_NAMESPACES +using namespace std; +#endif +int +main () +{ +iterator t; return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_cxx_have_std_iterator=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_cxx_have_std_iterator=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_cxx_have_std_iterator" >&5 +echo "${ECHO_T}$ac_cv_cxx_have_std_iterator" >&6; } +if test "$ac_cv_cxx_have_std_iterator" = yes +then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_STD_ITERATOR 1 +_ACEOF + +else + +cat >>confdefs.h <<\_ACEOF +#define HAVE_STD_ITERATOR 0 +_ACEOF + +fi + +{ echo "$as_me:$LINENO: checking whether the compiler has the bidirectional iterator" >&5 +echo $ECHO_N "checking whether the compiler has the bidirectional iterator... $ECHO_C" >&6; } +if test "${ac_cv_cxx_have_bi_iterator+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#ifdef HAVE_NAMESPACES +using namespace std; +#endif +int +main () +{ +bidirectional_iterator t; return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_cxx_have_bi_iterator=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_cxx_have_bi_iterator=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_cxx_have_bi_iterator" >&5 +echo "${ECHO_T}$ac_cv_cxx_have_bi_iterator" >&6; } +if test "$ac_cv_cxx_have_bi_iterator" = yes +then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_BI_ITERATOR 1 +_ACEOF + +else + +cat >>confdefs.h <<\_ACEOF +#define HAVE_BI_ITERATOR 0 +_ACEOF + +fi + +{ echo "$as_me:$LINENO: checking whether the compiler has forward iterators" >&5 +echo $ECHO_N "checking whether the compiler has forward iterators... $ECHO_C" >&6; } +if test "${ac_cv_cxx_have_fwd_iterator+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#ifdef HAVE_NAMESPACES +using namespace std; +#endif +int +main () +{ +forward_iterator t; return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_cxx_have_fwd_iterator=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_cxx_have_fwd_iterator=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_cxx_have_fwd_iterator" >&5 +echo "${ECHO_T}$ac_cv_cxx_have_fwd_iterator" >&6; } +if test "$ac_cv_cxx_have_fwd_iterator" = yes +then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_FWD_ITERATOR 1 +_ACEOF + +else + +cat >>confdefs.h <<\_ACEOF +#define HAVE_FWD_ITERATOR 0 +_ACEOF + +fi + + +{ echo "$as_me:$LINENO: checking for isnan in " >&5 +echo $ECHO_N "checking for isnan in ... $ECHO_C" >&6; } +if test "${ac_cv_func_isnan_in_math_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +int +main () +{ +float f; isnan(f); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_isnan_in_math_h=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_func_isnan_in_math_h=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_func_isnan_in_math_h" >&5 +echo "${ECHO_T}$ac_cv_func_isnan_in_math_h" >&6; } + + +if test "$ac_cv_func_isnan_in_math_h" = "yes" ; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_ISNAN_IN_MATH_H 1 +_ACEOF + +fi + +{ echo "$as_me:$LINENO: checking for isnan in " >&5 +echo $ECHO_N "checking for isnan in ... $ECHO_C" >&6; } +if test "${ac_cv_func_isnan_in_cmath+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +int +main () +{ +float f; isnan(f); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_isnan_in_cmath=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_func_isnan_in_cmath=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_func_isnan_in_cmath" >&5 +echo "${ECHO_T}$ac_cv_func_isnan_in_cmath" >&6; } + +if test "$ac_cv_func_isnan_in_cmath" = "yes" ; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_ISNAN_IN_CMATH 1 +_ACEOF + +fi + +{ echo "$as_me:$LINENO: checking for std::isnan in " >&5 +echo $ECHO_N "checking for std::isnan in ... $ECHO_C" >&6; } +if test "${ac_cv_func_std_isnan_in_cmath+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +int +main () +{ +float f; std::isnan(f); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_std_isnan_in_cmath=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_func_std_isnan_in_cmath=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_func_std_isnan_in_cmath" >&5 +echo "${ECHO_T}$ac_cv_func_std_isnan_in_cmath" >&6; } + +if test "$ac_cv_func_std_isnan_in_cmath" = "yes" ; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_STD_ISNAN_IN_CMATH 1 +_ACEOF + +fi + + +{ echo "$as_me:$LINENO: checking for isinf in " >&5 +echo $ECHO_N "checking for isinf in ... $ECHO_C" >&6; } +if test "${ac_cv_func_isinf_in_math_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +int +main () +{ +float f; isinf(f); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_isinf_in_math_h=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_func_isinf_in_math_h=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_func_isinf_in_math_h" >&5 +echo "${ECHO_T}$ac_cv_func_isinf_in_math_h" >&6; } + +if test "$ac_cv_func_isinf_in_math_h" = "yes" ; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_ISINF_IN_MATH_H 1 +_ACEOF + +fi + +{ echo "$as_me:$LINENO: checking for isinf in " >&5 +echo $ECHO_N "checking for isinf in ... $ECHO_C" >&6; } +if test "${ac_cv_func_isinf_in_cmath+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +int +main () +{ +float f; isinf(f); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_isinf_in_cmath=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_func_isinf_in_cmath=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_func_isinf_in_cmath" >&5 +echo "${ECHO_T}$ac_cv_func_isinf_in_cmath" >&6; } + +if test "$ac_cv_func_isinf_in_cmath" = "yes" ; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_ISINF_IN_CMATH 1 +_ACEOF + +fi + +{ echo "$as_me:$LINENO: checking for std::isinf in " >&5 +echo $ECHO_N "checking for std::isinf in ... $ECHO_C" >&6; } +if test "${ac_cv_func_std_isinf_in_cmath+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +int +main () +{ +float f; std::isinf(f)} + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_std_isinf_in_cmath=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_func_std_isinf_in_cmath=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_func_std_isinf_in_cmath" >&5 +echo "${ECHO_T}$ac_cv_func_std_isinf_in_cmath" >&6; } + +if test "$ac_cv_func_std_isinf_in_cmath" = "yes" ; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_STD_ISINF_IN_CMATH 1 +_ACEOF + +fi + +{ echo "$as_me:$LINENO: checking for finite in " >&5 +echo $ECHO_N "checking for finite in ... $ECHO_C" >&6; } +if test "${ac_cv_func_finite_in_ieeefp_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +int +main () +{ +float f; finite(f); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_finite_in_ieeefp_h=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_func_finite_in_ieeefp_h=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_func_finite_in_ieeefp_h" >&5 +echo "${ECHO_T}$ac_cv_func_finite_in_ieeefp_h" >&6; } + +if test "$ac_cv_func_finite_in_ieeefp_h" = "yes" ; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_FINITE_IN_IEEEFP_H 1 +_ACEOF + +fi + + + +if test "$llvm_cv_platform_type" = "Unix" ; then + + +for ac_header in stdlib.h unistd.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + { echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +else + # Is the header compilable? +{ echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6; } + +# Is the header present? +{ echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -f conftest.err conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + ( cat <<\_ASBOX +## ----------------------------------- ## +## Report this to llvmbugs@cs.uiuc.edu ## +## ----------------------------------- ## +_ASBOX + ) | sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +{ echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + +for ac_func in getpagesize +do +as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` +{ echo "$as_me:$LINENO: checking for $ac_func" >&5 +echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; } +if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case declares $ac_func. + For example, HP-UX 11i declares gettimeofday. */ +#define $ac_func innocuous_$ac_func + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $ac_func + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $ac_func (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$ac_func || defined __stub___$ac_func +choke me +#endif + +int +main () +{ +return $ac_func (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_var=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_var=no" +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +ac_res=`eval echo '${'$as_ac_var'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +if test `eval echo '${'$as_ac_var'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + +{ echo "$as_me:$LINENO: checking for working mmap" >&5 +echo $ECHO_N "checking for working mmap... $ECHO_C" >&6; } +if test "${ac_cv_func_mmap_fixed_mapped+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test "$cross_compiling" = yes; then + ac_cv_func_mmap_fixed_mapped=no +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +/* malloc might have been renamed as rpl_malloc. */ +#undef malloc + +/* Thanks to Mike Haertel and Jim Avera for this test. + Here is a matrix of mmap possibilities: + mmap private not fixed + mmap private fixed at somewhere currently unmapped + mmap private fixed at somewhere already mapped + mmap shared not fixed + mmap shared fixed at somewhere currently unmapped + mmap shared fixed at somewhere already mapped + For private mappings, we should verify that changes cannot be read() + back from the file, nor mmap's back from the file at a different + address. (There have been systems where private was not correctly + implemented like the infamous i386 svr4.0, and systems where the + VM page cache was not coherent with the file system buffer cache + like early versions of FreeBSD and possibly contemporary NetBSD.) + For shared mappings, we should conversely verify that changes get + propagated back to all the places they're supposed to be. + + Grep wants private fixed already mapped. + The main things grep needs to know about mmap are: + * does it exist and is it safe to write into the mmap'd area + * how to use it (BSD variants) */ + +#include +#include + +#if !STDC_HEADERS && !HAVE_STDLIB_H +char *malloc (); +#endif + +/* This mess was copied from the GNU getpagesize.h. */ +#if !HAVE_GETPAGESIZE +/* Assume that all systems that can run configure have sys/param.h. */ +# if !HAVE_SYS_PARAM_H +# define HAVE_SYS_PARAM_H 1 +# endif + +# ifdef _SC_PAGESIZE +# define getpagesize() sysconf(_SC_PAGESIZE) +# else /* no _SC_PAGESIZE */ +# if HAVE_SYS_PARAM_H +# include +# ifdef EXEC_PAGESIZE +# define getpagesize() EXEC_PAGESIZE +# else /* no EXEC_PAGESIZE */ +# ifdef NBPG +# define getpagesize() NBPG * CLSIZE +# ifndef CLSIZE +# define CLSIZE 1 +# endif /* no CLSIZE */ +# else /* no NBPG */ +# ifdef NBPC +# define getpagesize() NBPC +# else /* no NBPC */ +# ifdef PAGESIZE +# define getpagesize() PAGESIZE +# endif /* PAGESIZE */ +# endif /* no NBPC */ +# endif /* no NBPG */ +# endif /* no EXEC_PAGESIZE */ +# else /* no HAVE_SYS_PARAM_H */ +# define getpagesize() 8192 /* punt totally */ +# endif /* no HAVE_SYS_PARAM_H */ +# endif /* no _SC_PAGESIZE */ + +#endif /* no HAVE_GETPAGESIZE */ + +int +main () +{ + char *data, *data2, *data3; + int i, pagesize; + int fd; + + pagesize = getpagesize (); + + /* First, make a file with some known garbage in it. */ + data = (char *) malloc (pagesize); + if (!data) + return 1; + for (i = 0; i < pagesize; ++i) + *(data + i) = rand (); + umask (0); + fd = creat ("conftest.mmap", 0600); + if (fd < 0) + return 1; + if (write (fd, data, pagesize) != pagesize) + return 1; + close (fd); + + /* Next, try to mmap the file at a fixed address which already has + something else allocated at it. If we can, also make sure that + we see the same garbage. */ + fd = open ("conftest.mmap", O_RDWR); + if (fd < 0) + return 1; + data2 = (char *) malloc (2 * pagesize); + if (!data2) + return 1; + data2 += (pagesize - ((long int) data2 & (pagesize - 1))) & (pagesize - 1); + if (data2 != mmap (data2, pagesize, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_FIXED, fd, 0L)) + return 1; + for (i = 0; i < pagesize; ++i) + if (*(data + i) != *(data2 + i)) + return 1; + + /* Finally, make sure that changes to the mapped area do not + percolate back to the file as seen by read(). (This is a bug on + some variants of i386 svr4.0.) */ + for (i = 0; i < pagesize; ++i) + *(data2 + i) = *(data2 + i) + 1; + data3 = (char *) malloc (pagesize); + if (!data3) + return 1; + if (read (fd, data3, pagesize) != pagesize) + return 1; + for (i = 0; i < pagesize; ++i) + if (*(data + i) != *(data3 + i)) + return 1; + close (fd); + return 0; +} +_ACEOF +rm -f conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_mmap_fixed_mapped=yes +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +ac_cv_func_mmap_fixed_mapped=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_func_mmap_fixed_mapped" >&5 +echo "${ECHO_T}$ac_cv_func_mmap_fixed_mapped" >&6; } +if test $ac_cv_func_mmap_fixed_mapped = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_MMAP 1 +_ACEOF + +fi +rm -f conftest.mmap + + { echo "$as_me:$LINENO: checking for mmap of files" >&5 +echo $ECHO_N "checking for mmap of files... $ECHO_C" >&6; } +if test "${ac_cv_func_mmap_file+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + if test "$cross_compiling" = yes; then + ac_cv_func_mmap_file=no +else + cat >conftest.$ac_ext <<_ACEOF + + /* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +#include +#include +#include + +int +main () +{ + + int fd; + fd = creat ("foo",0777); + fd = (int) mmap (0, 1, PROT_READ, MAP_SHARED, fd, 0); + unlink ("foo"); + return (fd != (int) MAP_FAILED); + ; + return 0; +} +_ACEOF +rm -f conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_mmap_file=yes +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +ac_cv_func_mmap_file=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + + + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_func_mmap_file" >&5 +echo "${ECHO_T}$ac_cv_func_mmap_file" >&6; } +if test "$ac_cv_func_mmap_file" = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_MMAP_FILE +_ACEOF + + MMAP_FILE=yes + +fi + + { echo "$as_me:$LINENO: checking if /dev/zero is needed for mmap" >&5 +echo $ECHO_N "checking if /dev/zero is needed for mmap... $ECHO_C" >&6; } +if test "${ac_cv_need_dev_zero_for_mmap+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test "$llvm_cv_os_type" = "Interix" ; then + ac_cv_need_dev_zero_for_mmap=yes + else + ac_cv_need_dev_zero_for_mmap=no + fi + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_need_dev_zero_for_mmap" >&5 +echo "${ECHO_T}$ac_cv_need_dev_zero_for_mmap" >&6; } +if test "$ac_cv_need_dev_zero_for_mmap" = yes; then + +cat >>confdefs.h <<\_ACEOF +#define NEED_DEV_ZERO_FOR_MMAP 1 +_ACEOF + +fi + + if test "$ac_cv_func_mmap_fixed_mapped" = "no" + then + { echo "$as_me:$LINENO: WARNING: mmap() of a fixed address required but not supported" >&5 +echo "$as_me: WARNING: mmap() of a fixed address required but not supported" >&2;} + fi + if test "$ac_cv_func_mmap_file" = "no" + then + { echo "$as_me:$LINENO: WARNING: mmap() of files required but not found" >&5 +echo "$as_me: WARNING: mmap() of files required but not found" >&2;} + fi +fi + +{ echo "$as_me:$LINENO: checking for GCC atomic builtins" >&5 +echo $ECHO_N "checking for GCC atomic builtins... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +int main() { + volatile unsigned long val = 1; + __sync_synchronize(); + __sync_val_compare_and_swap(&val, 1, 0); + __sync_add_and_fetch(&val, 1); + __sync_sub_and_fetch(&val, 1); + return 0; + } + +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + { echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6; } + +cat >>confdefs.h <<\_ACEOF +#define LLVM_MULTITHREADED 1 +_ACEOF + +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } + +cat >>confdefs.h <<\_ACEOF +#define LLVM_MULTITHREADED 0 +_ACEOF + + { echo "$as_me:$LINENO: WARNING: LLVM will be built thread-unsafe because atomic builtins are missing" >&5 +echo "$as_me: WARNING: LLVM will be built thread-unsafe because atomic builtins are missing" >&2;} +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + + + +if test "$llvm_cv_os_type" = "Linux" -a "$llvm_cv_target_arch" = "x86_64" ; then + { echo "$as_me:$LINENO: checking for 32-bit userspace on 64-bit system" >&5 +echo $ECHO_N "checking for 32-bit userspace on 64-bit system... $ECHO_C" >&6; } +if test "${llvm_cv_linux_mixed+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#ifndef __x86_64__ + error: Not x86-64 even if uname says so! + #endif + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + llvm_cv_linux_mixed=no +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + llvm_cv_linux_mixed=yes +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +fi +{ echo "$as_me:$LINENO: result: $llvm_cv_linux_mixed" >&5 +echo "${ECHO_T}$llvm_cv_linux_mixed" >&6; } + + if test "$llvm_cv_linux_mixed" = "yes"; then + llvm_cv_target_arch="x86" + ARCH="x86" + fi +fi + + +for ac_func in __dso_handle +do +as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` +{ echo "$as_me:$LINENO: checking for $ac_func" >&5 +echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; } +if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case declares $ac_func. + For example, HP-UX 11i declares gettimeofday. */ +#define $ac_func innocuous_$ac_func + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $ac_func + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $ac_func (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$ac_func || defined __stub___$ac_func +choke me +#endif + +int +main () +{ +return $ac_func (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_var=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_var=no" +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +ac_res=`eval echo '${'$as_ac_var'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +if test `eval echo '${'$as_ac_var'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + +{ echo "$as_me:$LINENO: checking whether llvm-gcc is sane" >&5 +echo $ECHO_N "checking whether llvm-gcc is sane... $ECHO_C" >&6; } +if test "${llvm_cv_llvmgcc_sanity+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + llvm_cv_llvmgcc_sanity="no" +if test -x "$LLVMGCC" ; then + cp /dev/null conftest.c + "$LLVMGCC" -emit-llvm -S -o - conftest.c | \ + grep 'target datalayout =' > /dev/null 2>&1 + if test $? -eq 0 ; then + llvm_cv_llvmgcc_sanity="yes" + fi + rm conftest.c +fi +fi +{ echo "$as_me:$LINENO: result: $llvm_cv_llvmgcc_sanity" >&5 +echo "${ECHO_T}$llvm_cv_llvmgcc_sanity" >&6; } + +if test "$llvm_cv_llvmgcc_sanity" = "yes" ; then + { echo "$as_me:$LINENO: checking llvm-gcc component support" >&5 +echo $ECHO_N "checking llvm-gcc component support... $ECHO_C" >&6; } + llvmcc1path=`"$LLVMGCC" --print-prog-name=cc1` + LLVMCC1=$llvmcc1path + + llvmcc1pluspath=`"$LLVMGCC" --print-prog-name=cc1plus` + LLVMCC1PLUS=$llvmcc1pluspath + + llvmgccdir=`echo "$llvmcc1path" | sed 's,/libexec/.*,,'` + LLVMGCCDIR=$llvmgccdir + + llvmgcclibexec=`echo "$llvmcc1path" | sed 's,/cc1,,'` + LLVMGCCLIBEXEC=$llvmgcclibexec + + llvmgccversion=`"$LLVMGCC" -dumpversion 2>&1 | sed 's/^\([0-9.]*\).*/\1/'` + llvmgccmajvers=`echo $llvmgccversion | sed 's/^\([0-9]\).*/\1/'` + LLVMGCC_VERSION=$llvmgccversion + + LLVMGCC_MAJVERS=$llvmgccmajvers + + llvmgcclangs=`"$LLVMGCC" -v --help 2>&1 | grep '^Configured with:' | sed 's/^.*--enable-languages=\([^ ]*\).*/\1/'` + LLVMGCC_LANGS=$llvmgcclangs + + { echo "$as_me:$LINENO: result: ok" >&5 +echo "${ECHO_T}ok" >&6; } +fi + +SHLIBEXT=$libltdl_cv_shlibext + + +# Translate the various configuration directories and other basic +# information into substitutions that will end up in Makefile.config.in +# that these configured values can be used by the makefiles +if test "${prefix}" = "NONE" ; then + prefix="/usr/local" +fi +eval LLVM_PREFIX="${prefix}"; +eval LLVM_BINDIR="${prefix}/bin"; +eval LLVM_LIBDIR="${prefix}/lib"; +eval LLVM_DATADIR="${prefix}/share/llvm"; +eval LLVM_DOCSDIR="${prefix}/docs/llvm"; +eval LLVM_ETCDIR="${prefix}/etc/llvm"; +eval LLVM_INCLUDEDIR="${prefix}/include"; +eval LLVM_INFODIR="${prefix}/info"; +eval LLVM_MANDIR="${prefix}/man"; +LLVM_CONFIGTIME=`date` + + + + + + + + + + + +# Place the various directores into the config.h file as #defines so that we +# can know about the installation paths within LLVM. + +cat >>confdefs.h <<_ACEOF +#define LLVM_PREFIX "$LLVM_PREFIX" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define LLVM_BINDIR "$LLVM_BINDIR" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define LLVM_LIBDIR "$LLVM_LIBDIR" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define LLVM_DATADIR "$LLVM_DATADIR" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define LLVM_DOCSDIR "$LLVM_DOCSDIR" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define LLVM_ETCDIR "$LLVM_ETCDIR" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define LLVM_INCLUDEDIR "$LLVM_INCLUDEDIR" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define LLVM_INFODIR "$LLVM_INFODIR" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define LLVM_MANDIR "$LLVM_MANDIR" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define LLVM_CONFIGTIME "$LLVM_CONFIGTIME" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define LLVM_HOSTTRIPLE "$host" +_ACEOF + + +# Determine which bindings to build. +if test "$BINDINGS_TO_BUILD" = auto ; then + BINDINGS_TO_BUILD="" + if test "x$OCAMLC" != x -a "x$OCAMLDEP" != x ; then + BINDINGS_TO_BUILD="ocaml $BINDINGS_TO_BUILD" + fi +fi +BINDINGS_TO_BUILD=$BINDINGS_TO_BUILD + + +# This isn't really configurey, but it avoids having to repeat the list in +# other files. +ALL_BINDINGS=ocaml + + +# Do any work necessary to ensure that bindings have what they need. +binding_prereqs_failed=0 +for a_binding in $BINDINGS_TO_BUILD ; do + case "$a_binding" in + ocaml) + if test "x$OCAMLC" = x ; then + { echo "$as_me:$LINENO: WARNING: --enable-bindings=ocaml specified, but ocamlc not found. Try configure OCAMLC=/path/to/ocamlc" >&5 +echo "$as_me: WARNING: --enable-bindings=ocaml specified, but ocamlc not found. Try configure OCAMLC=/path/to/ocamlc" >&2;} + binding_prereqs_failed=1 + fi + if test "x$OCAMLDEP" = x ; then + { echo "$as_me:$LINENO: WARNING: --enable-bindings=ocaml specified, but ocamldep not found. Try configure OCAMLDEP=/path/to/ocamldep" >&5 +echo "$as_me: WARNING: --enable-bindings=ocaml specified, but ocamldep not found. Try configure OCAMLDEP=/path/to/ocamldep" >&2;} + binding_prereqs_failed=1 + fi + if test "x$OCAMLOPT" = x ; then + { echo "$as_me:$LINENO: WARNING: --enable-bindings=ocaml specified, but ocamlopt not found. Try configure OCAMLOPT=/path/to/ocamlopt" >&5 +echo "$as_me: WARNING: --enable-bindings=ocaml specified, but ocamlopt not found. Try configure OCAMLOPT=/path/to/ocamlopt" >&2;} + fi + if test "x$with_ocaml_libdir" != xauto ; then + OCAML_LIBDIR=$with_ocaml_libdir + + else + ocaml_stdlib="`"$OCAMLC" -where`" + if test "$LLVM_PREFIX" '<' "$ocaml_stdlib" -a "$ocaml_stdlib" '<' "$LLVM_PREFIX~" + then + # ocaml stdlib is beneath our prefix; use stdlib + OCAML_LIBDIR=$ocaml_stdlib + + else + # ocaml stdlib is outside our prefix; use libdir/ocaml + OCAML_LIBDIR=$LLVM_LIBDIR/ocaml + + fi + fi + ;; + esac +done +if test "$binding_prereqs_failed" = 1 ; then + { { echo "$as_me:$LINENO: error: Prequisites for bindings not satisfied. Fix them or use configure --disable-bindings." >&5 +echo "$as_me: error: Prequisites for bindings not satisfied. Fix them or use configure --disable-bindings." >&2;} + { (exit 1); exit 1; }; } +fi + +{ echo "$as_me:$LINENO: checking for compiler -fvisibility-inlines-hidden option" >&5 +echo $ECHO_N "checking for compiler -fvisibility-inlines-hidden option... $ECHO_C" >&6; } +if test "${llvm_cv_cxx_visibility_inlines_hidden+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + oldcxxflags="$CXXFLAGS" + CXXFLAGS="$CXXFLAGS -fvisibility-inlines-hidden" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + llvm_cv_cxx_visibility_inlines_hidden=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + llvm_cv_cxx_visibility_inlines_hidden=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + CXXFLAGS="$oldcxxflags" + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +fi +{ echo "$as_me:$LINENO: result: $llvm_cv_cxx_visibility_inlines_hidden" >&5 +echo "${ECHO_T}$llvm_cv_cxx_visibility_inlines_hidden" >&6; } +if test "$llvm_cv_cxx_visibility_inlines_hidden" = yes ; then + ENABLE_VISIBILITY_INLINES_HIDDEN=1 + +else + ENABLE_VISIBILITY_INLINES_HIDDEN=0 + +fi + + +if test "$llvm_cv_link_use_r" = "yes" ; then + RPATH="-Wl,-R" +else + RPATH="-Wl,-rpath" +fi + + +if test "$llvm_cv_link_use_export_dynamic" = "yes" ; then + RDYNAMIC="-Wl,-export-dynamic" +else + RDYNAMIC="" +fi + + + +ac_config_headers="$ac_config_headers include/llvm/Config/config.h" + +ac_config_files="$ac_config_files include/llvm/Config/Targets.def" + +ac_config_files="$ac_config_files include/llvm/Config/AsmPrinters.def" + +ac_config_files="$ac_config_files include/llvm/Config/AsmParsers.def" + +ac_config_files="$ac_config_files include/llvm/Config/Disassemblers.def" + +ac_config_headers="$ac_config_headers include/llvm/System/DataTypes.h" + + +ac_config_files="$ac_config_files Makefile.config" + + +ac_config_files="$ac_config_files llvm.spec" + + +ac_config_files="$ac_config_files docs/doxygen.cfg" + + +ac_config_files="$ac_config_files tools/llvmc/plugins/Base/Base.td" + + +ac_config_files="$ac_config_files tools/llvm-config/llvm-config.in" + + +ac_config_commands="$ac_config_commands setup" + +ac_config_commands="$ac_config_commands Makefile" + + +ac_config_commands="$ac_config_commands Makefile.common" + + +ac_config_commands="$ac_config_commands examples/Makefile" + + +ac_config_commands="$ac_config_commands lib/Makefile" + + +ac_config_commands="$ac_config_commands runtime/Makefile" + + +ac_config_commands="$ac_config_commands test/Makefile" + + +ac_config_commands="$ac_config_commands test/Makefile.tests" + + +ac_config_commands="$ac_config_commands unittests/Makefile" + + +ac_config_commands="$ac_config_commands tools/Makefile" + + +ac_config_commands="$ac_config_commands utils/Makefile" + + +ac_config_commands="$ac_config_commands projects/Makefile" + + +ac_config_commands="$ac_config_commands bindings/Makefile" + + +ac_config_commands="$ac_config_commands bindings/ocaml/Makefile.ocaml" + + + +cat >confcache <<\_ACEOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs, see configure's option --config-cache. +# It is not useful on other systems. If it contains results you don't +# want to keep, you may remove or edit it. +# +# config.status only pays attention to the cache file if you give it +# the --recheck option to rerun configure. +# +# `ac_cv_env_foo' variables (set or unset) will be overridden when +# loading this file, other *unset* `ac_cv_foo' will be assigned the +# following values. + +_ACEOF + +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, we kill variables containing newlines. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +( + for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5 +echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + *) $as_unset $ac_var ;; + esac ;; + esac + done + + (set) 2>&1 | + case $as_nl`(ac_space=' '; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + # `set' does not quote correctly, so add quotes (double-quote + # substitution turns \\\\ into \\, and sed turns \\ into \). + sed -n \ + "s/'/'\\\\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" + ;; #( + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) | + sed ' + /^ac_cv_env_/b end + t clear + :clear + s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ + t end + s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ + :end' >>confcache +if diff "$cache_file" confcache >/dev/null 2>&1; then :; else + if test -w "$cache_file"; then + test "x$cache_file" != "x/dev/null" && + { echo "$as_me:$LINENO: updating cache $cache_file" >&5 +echo "$as_me: updating cache $cache_file" >&6;} + cat confcache >$cache_file + else + { echo "$as_me:$LINENO: not updating unwritable cache $cache_file" >&5 +echo "$as_me: not updating unwritable cache $cache_file" >&6;} + fi +fi +rm -f confcache + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +DEFS=-DHAVE_CONFIG_H + +ac_libobjs= +ac_ltlibobjs= +for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue + # 1. Remove the extension, and $U if already installed. + ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' + ac_i=`echo "$ac_i" | sed "$ac_script"` + # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR + # will be set to the directory where LIBOBJS objects are built. + ac_libobjs="$ac_libobjs \${LIBOBJDIR}$ac_i\$U.$ac_objext" + ac_ltlibobjs="$ac_ltlibobjs \${LIBOBJDIR}$ac_i"'$U.lo' +done +LIBOBJS=$ac_libobjs + +LTLIBOBJS=$ac_ltlibobjs + + +if test -z "${INSTALL_LTDL_TRUE}" && test -z "${INSTALL_LTDL_FALSE}"; then + { { echo "$as_me:$LINENO: error: conditional \"INSTALL_LTDL\" was never defined. +Usually this means the macro was only invoked conditionally." >&5 +echo "$as_me: error: conditional \"INSTALL_LTDL\" was never defined. +Usually this means the macro was only invoked conditionally." >&2;} + { (exit 1); exit 1; }; } +fi +if test -z "${CONVENIENCE_LTDL_TRUE}" && test -z "${CONVENIENCE_LTDL_FALSE}"; then + { { echo "$as_me:$LINENO: error: conditional \"CONVENIENCE_LTDL\" was never defined. +Usually this means the macro was only invoked conditionally." >&5 +echo "$as_me: error: conditional \"CONVENIENCE_LTDL\" was never defined. +Usually this means the macro was only invoked conditionally." >&2;} + { (exit 1); exit 1; }; } +fi + +: ${CONFIG_STATUS=./config.status} +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files $CONFIG_STATUS" +{ echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5 +echo "$as_me: creating $CONFIG_STATUS" >&6;} +cat >$CONFIG_STATUS <<_ACEOF +#! $SHELL +# Generated by $as_me. +# Run this file to recreate the current configuration. +# Compiler output produced by configure, useful for debugging +# configure, is in config.log if it exists. + +debug=false +ac_cs_recheck=false +ac_cs_silent=false +SHELL=\${CONFIG_SHELL-$SHELL} +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF +## --------------------- ## +## M4sh Initialization. ## +## --------------------- ## + +# Be Bourne compatible +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac +fi +BIN_SH=xpg4; export BIN_SH # for Tru64 +DUALCASE=1; export DUALCASE # for MKS sh + + +# PATH needs CR +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + echo "#! /bin/sh" >conf$$.sh + echo "exit 0" >>conf$$.sh + chmod +x conf$$.sh + if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then + PATH_SEPARATOR=';' + else + PATH_SEPARATOR=: + fi + rm -f conf$$.sh +fi + +# Support unset when possible. +if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then + as_unset=unset +else + as_unset=false +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +as_nl=' +' +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +case $0 in + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break +done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + { (exit 1); exit 1; } +fi + +# Work around bugs in pre-3.0 UWIN ksh. +for as_var in ENV MAIL MAILPATH +do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +for as_var in \ + LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ + LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ + LC_TELEPHONE LC_TIME +do + if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then + eval $as_var=C; export $as_var + else + ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var + fi +done + +# Required to use basename. +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + + +# Name of the executable. +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# CDPATH. +$as_unset CDPATH + + + + as_lineno_1=$LINENO + as_lineno_2=$LINENO + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || { + + # Create $as_me.lineno as a copy of $as_myself, but with $LINENO + # uniformly replaced by the line number. The first 'sed' inserts a + # line-number line after each line using $LINENO; the second 'sed' + # does the real work. The second script uses 'N' to pair each + # line-number line with the line containing $LINENO, and appends + # trailing '-' during substitution so that $LINENO is not a special + # case at line end. + # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the + # scripts with optimization help from Paolo Bonzini. Blame Lee + # E. McMahon (1931-1989) for sed's syntax. :-) + sed -n ' + p + /[$]LINENO/= + ' <$as_myself | + sed ' + s/[$]LINENO.*/&-/ + t lineno + b + :lineno + N + :loop + s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ + t loop + s/-\n.*// + ' >$as_me.lineno && + chmod +x "$as_me.lineno" || + { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2 + { (exit 1); exit 1; }; } + + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensitive to this). + . "./$as_me.lineno" + # Exit status is that of the last command. + exit +} + + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in +-n*) + case `echo 'x\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + *) ECHO_C='\c';; + esac;; +*) + ECHO_N='-n';; +esac + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir +fi +echo >conf$$.file +if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -p'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -p' +elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln +else + as_ln_s='cp -p' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + +if mkdir -p . 2>/dev/null; then + as_mkdir_p=: +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +# Find out whether ``test -x'' works. Don't use a zero-byte file, as +# systems may use methods other than mode bits to determine executability. +cat >conf$$.file <<_ASEOF +#! /bin/sh +exit 0 +_ASEOF +chmod +x conf$$.file +if test -x conf$$.file >/dev/null 2>&1; then + as_executable_p="test -x" +else + as_executable_p=: +fi +rm -f conf$$.file + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +exec 6>&1 + +# Save the log message, to keep $[0] and so on meaningful, and to +# report actual input values of CONFIG_FILES etc. instead of their +# values after options handling. +ac_log=" +This file was extended by llvm $as_me 2.7svn, which was +generated by GNU Autoconf 2.60. Invocation command line was + + CONFIG_FILES = $CONFIG_FILES + CONFIG_HEADERS = $CONFIG_HEADERS + CONFIG_LINKS = $CONFIG_LINKS + CONFIG_COMMANDS = $CONFIG_COMMANDS + $ $0 $@ + +on `(hostname || uname -n) 2>/dev/null | sed 1q` +" + +_ACEOF + +cat >>$CONFIG_STATUS <<_ACEOF +# Files that config.status was made for. +config_files="$ac_config_files" +config_headers="$ac_config_headers" +config_commands="$ac_config_commands" + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF +ac_cs_usage="\ +\`$as_me' instantiates files from templates according to the +current configuration. + +Usage: $0 [OPTIONS] [FILE]... + + -h, --help print this help, then exit + -V, --version print version number, then exit + -q, --quiet do not print progress messages + -d, --debug don't remove temporary files + --recheck update $as_me by reconfiguring in the same conditions + --file=FILE[:TEMPLATE] + instantiate the configuration file FILE + --header=FILE[:TEMPLATE] + instantiate the configuration header FILE + +Configuration files: +$config_files + +Configuration headers: +$config_headers + +Configuration commands: +$config_commands + +Report bugs to ." + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF +ac_cs_version="\\ +llvm config.status 2.7svn +configured by $0, generated by GNU Autoconf 2.60, + with options \\"`echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\" + +Copyright (C) 2006 Free Software Foundation, Inc. +This config.status script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it." + +ac_pwd='$ac_pwd' +srcdir='$srcdir' +INSTALL='$INSTALL' +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF +# If no file are specified by the user, then we need to provide default +# value. By we need to know if files were specified by the user. +ac_need_defaults=: +while test $# != 0 +do + case $1 in + --*=*) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` + ac_shift=: + ;; + *) + ac_option=$1 + ac_optarg=$2 + ac_shift=shift + ;; + esac + + case $ac_option in + # Handling of the options. + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + ac_cs_recheck=: ;; + --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) + echo "$ac_cs_version"; exit ;; + --debug | --debu | --deb | --de | --d | -d ) + debug=: ;; + --file | --fil | --fi | --f ) + $ac_shift + CONFIG_FILES="$CONFIG_FILES $ac_optarg" + ac_need_defaults=false;; + --header | --heade | --head | --hea ) + $ac_shift + CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg" + ac_need_defaults=false;; + --he | --h) + # Conflict between --help and --header + { echo "$as_me: error: ambiguous option: $1 +Try \`$0 --help' for more information." >&2 + { (exit 1); exit 1; }; };; + --help | --hel | -h ) + echo "$ac_cs_usage"; exit ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil | --si | --s) + ac_cs_silent=: ;; + + # This is an error. + -*) { echo "$as_me: error: unrecognized option: $1 +Try \`$0 --help' for more information." >&2 + { (exit 1); exit 1; }; } ;; + + *) ac_config_targets="$ac_config_targets $1" + ac_need_defaults=false ;; + + esac + shift +done + +ac_configure_extra_args= + +if $ac_cs_silent; then + exec 6>/dev/null + ac_configure_extra_args="$ac_configure_extra_args --silent" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF +if \$ac_cs_recheck; then + echo "running CONFIG_SHELL=$SHELL $SHELL $0 "$ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6 + CONFIG_SHELL=$SHELL + export CONFIG_SHELL + exec $SHELL "$0"$ac_configure_args \$ac_configure_extra_args --no-create --no-recursion +fi + +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF +exec 5>>config.log +{ + echo + sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX +## Running $as_me. ## +_ASBOX + echo "$ac_log" +} >&5 + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF +# +# INIT-COMMANDS +# +llvm_src="${srcdir}" + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF + +# Handling of arguments. +for ac_config_target in $ac_config_targets +do + case $ac_config_target in + "include/llvm/Config/config.h") CONFIG_HEADERS="$CONFIG_HEADERS include/llvm/Config/config.h" ;; + "include/llvm/Config/Targets.def") CONFIG_FILES="$CONFIG_FILES include/llvm/Config/Targets.def" ;; + "include/llvm/Config/AsmPrinters.def") CONFIG_FILES="$CONFIG_FILES include/llvm/Config/AsmPrinters.def" ;; + "include/llvm/Config/AsmParsers.def") CONFIG_FILES="$CONFIG_FILES include/llvm/Config/AsmParsers.def" ;; + "include/llvm/Config/Disassemblers.def") CONFIG_FILES="$CONFIG_FILES include/llvm/Config/Disassemblers.def" ;; + "include/llvm/System/DataTypes.h") CONFIG_HEADERS="$CONFIG_HEADERS include/llvm/System/DataTypes.h" ;; + "Makefile.config") CONFIG_FILES="$CONFIG_FILES Makefile.config" ;; + "llvm.spec") CONFIG_FILES="$CONFIG_FILES llvm.spec" ;; + "docs/doxygen.cfg") CONFIG_FILES="$CONFIG_FILES docs/doxygen.cfg" ;; + "tools/llvmc/plugins/Base/Base.td") CONFIG_FILES="$CONFIG_FILES tools/llvmc/plugins/Base/Base.td" ;; + "tools/llvm-config/llvm-config.in") CONFIG_FILES="$CONFIG_FILES tools/llvm-config/llvm-config.in" ;; + "setup") CONFIG_COMMANDS="$CONFIG_COMMANDS setup" ;; + "Makefile") CONFIG_COMMANDS="$CONFIG_COMMANDS Makefile" ;; + "Makefile.common") CONFIG_COMMANDS="$CONFIG_COMMANDS Makefile.common" ;; + "examples/Makefile") CONFIG_COMMANDS="$CONFIG_COMMANDS examples/Makefile" ;; + "lib/Makefile") CONFIG_COMMANDS="$CONFIG_COMMANDS lib/Makefile" ;; + "runtime/Makefile") CONFIG_COMMANDS="$CONFIG_COMMANDS runtime/Makefile" ;; + "test/Makefile") CONFIG_COMMANDS="$CONFIG_COMMANDS test/Makefile" ;; + "test/Makefile.tests") CONFIG_COMMANDS="$CONFIG_COMMANDS test/Makefile.tests" ;; + "unittests/Makefile") CONFIG_COMMANDS="$CONFIG_COMMANDS unittests/Makefile" ;; + "tools/Makefile") CONFIG_COMMANDS="$CONFIG_COMMANDS tools/Makefile" ;; + "utils/Makefile") CONFIG_COMMANDS="$CONFIG_COMMANDS utils/Makefile" ;; + "projects/Makefile") CONFIG_COMMANDS="$CONFIG_COMMANDS projects/Makefile" ;; + "bindings/Makefile") CONFIG_COMMANDS="$CONFIG_COMMANDS bindings/Makefile" ;; + "bindings/ocaml/Makefile.ocaml") CONFIG_COMMANDS="$CONFIG_COMMANDS bindings/ocaml/Makefile.ocaml" ;; + + *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5 +echo "$as_me: error: invalid argument: $ac_config_target" >&2;} + { (exit 1); exit 1; }; };; + esac +done + + +# If the user did not use the arguments to specify the items to instantiate, +# then the envvar interface is used. Set only those that are not. +# We use the long form for the default assignment because of an extremely +# bizarre bug on SunOS 4.1.3. +if $ac_need_defaults; then + test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files + test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers + test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands +fi + +# Have a temporary directory for convenience. Make it in the build tree +# simply because there is no reason against having it here, and in addition, +# creating and moving files from /tmp can sometimes cause problems. +# Hook for its removal unless debugging. +# Note that there is a small window in which the directory will not be cleaned: +# after its creation but before its name has been assigned to `$tmp'. +$debug || +{ + tmp= + trap 'exit_status=$? + { test -z "$tmp" || test ! -d "$tmp" || rm -fr "$tmp"; } && exit $exit_status +' 0 + trap '{ (exit 1); exit 1; }' 1 2 13 15 +} +# Create a (secure) tmp directory for tmp files. + +{ + tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && + test -n "$tmp" && test -d "$tmp" +} || +{ + tmp=./conf$$-$RANDOM + (umask 077 && mkdir "$tmp") +} || +{ + echo "$me: cannot create a temporary directory in ." >&2 + { (exit 1); exit 1; } +} + +# +# Set up the sed scripts for CONFIG_FILES section. +# + +# No need to generate the scripts if there are no CONFIG_FILES. +# This happens for instance when ./config.status config.h +if test -n "$CONFIG_FILES"; then + +_ACEOF + + + +ac_delim='%!_!# ' +for ac_last_try in false false false false false :; do + cat >conf$$subs.sed <<_ACEOF +SHELL!$SHELL$ac_delim +PATH_SEPARATOR!$PATH_SEPARATOR$ac_delim +PACKAGE_NAME!$PACKAGE_NAME$ac_delim +PACKAGE_TARNAME!$PACKAGE_TARNAME$ac_delim +PACKAGE_VERSION!$PACKAGE_VERSION$ac_delim +PACKAGE_STRING!$PACKAGE_STRING$ac_delim +PACKAGE_BUGREPORT!$PACKAGE_BUGREPORT$ac_delim +exec_prefix!$exec_prefix$ac_delim +prefix!$prefix$ac_delim +program_transform_name!$program_transform_name$ac_delim +bindir!$bindir$ac_delim +sbindir!$sbindir$ac_delim +libexecdir!$libexecdir$ac_delim +datarootdir!$datarootdir$ac_delim +datadir!$datadir$ac_delim +sysconfdir!$sysconfdir$ac_delim +sharedstatedir!$sharedstatedir$ac_delim +localstatedir!$localstatedir$ac_delim +includedir!$includedir$ac_delim +oldincludedir!$oldincludedir$ac_delim +docdir!$docdir$ac_delim +infodir!$infodir$ac_delim +htmldir!$htmldir$ac_delim +dvidir!$dvidir$ac_delim +pdfdir!$pdfdir$ac_delim +psdir!$psdir$ac_delim +libdir!$libdir$ac_delim +localedir!$localedir$ac_delim +mandir!$mandir$ac_delim +DEFS!$DEFS$ac_delim +ECHO_C!$ECHO_C$ac_delim +ECHO_N!$ECHO_N$ac_delim +ECHO_T!$ECHO_T$ac_delim +LIBS!$LIBS$ac_delim +build_alias!$build_alias$ac_delim +host_alias!$host_alias$ac_delim +target_alias!$target_alias$ac_delim +LLVM_COPYRIGHT!$LLVM_COPYRIGHT$ac_delim +subdirs!$subdirs$ac_delim +build!$build$ac_delim +build_cpu!$build_cpu$ac_delim +build_vendor!$build_vendor$ac_delim +build_os!$build_os$ac_delim +host!$host$ac_delim +host_cpu!$host_cpu$ac_delim +host_vendor!$host_vendor$ac_delim +host_os!$host_os$ac_delim +target!$target$ac_delim +target_cpu!$target_cpu$ac_delim +target_vendor!$target_vendor$ac_delim +target_os!$target_os$ac_delim +OS!$OS$ac_delim +HOST_OS!$HOST_OS$ac_delim +TARGET_OS!$TARGET_OS$ac_delim +LINKALL!$LINKALL$ac_delim +NOLINKALL!$NOLINKALL$ac_delim +LLVM_ON_UNIX!$LLVM_ON_UNIX$ac_delim +LLVM_ON_WIN32!$LLVM_ON_WIN32$ac_delim +ARCH!$ARCH$ac_delim +ENDIAN!$ENDIAN$ac_delim +CC!$CC$ac_delim +CFLAGS!$CFLAGS$ac_delim +LDFLAGS!$LDFLAGS$ac_delim +CPPFLAGS!$CPPFLAGS$ac_delim +ac_ct_CC!$ac_ct_CC$ac_delim +EXEEXT!$EXEEXT$ac_delim +OBJEXT!$OBJEXT$ac_delim +CPP!$CPP$ac_delim +GREP!$GREP$ac_delim +EGREP!$EGREP$ac_delim +LLVM_CROSS_COMPILING!$LLVM_CROSS_COMPILING$ac_delim +BUILD_CC!$BUILD_CC$ac_delim +BUILD_EXEEXT!$BUILD_EXEEXT$ac_delim +BUILD_CXX!$BUILD_CXX$ac_delim +CVSBUILD!$CVSBUILD$ac_delim +ENABLE_OPTIMIZED!$ENABLE_OPTIMIZED$ac_delim +ENABLE_PROFILING!$ENABLE_PROFILING$ac_delim +DISABLE_ASSERTIONS!$DISABLE_ASSERTIONS$ac_delim +ENABLE_EXPENSIVE_CHECKS!$ENABLE_EXPENSIVE_CHECKS$ac_delim +EXPENSIVE_CHECKS!$EXPENSIVE_CHECKS$ac_delim +DEBUG_RUNTIME!$DEBUG_RUNTIME$ac_delim +DEBUG_SYMBOLS!$DEBUG_SYMBOLS$ac_delim +JIT!$JIT$ac_delim +TARGET_HAS_JIT!$TARGET_HAS_JIT$ac_delim +ENABLE_DOXYGEN!$ENABLE_DOXYGEN$ac_delim +ENABLE_THREADS!$ENABLE_THREADS$ac_delim +ENABLE_PIC!$ENABLE_PIC$ac_delim +TARGETS_TO_BUILD!$TARGETS_TO_BUILD$ac_delim +LLVM_ENUM_TARGETS!$LLVM_ENUM_TARGETS$ac_delim +LLVM_ENUM_ASM_PRINTERS!$LLVM_ENUM_ASM_PRINTERS$ac_delim +LLVM_ENUM_ASM_PARSERS!$LLVM_ENUM_ASM_PARSERS$ac_delim +LLVM_ENUM_DISASSEMBLERS!$LLVM_ENUM_DISASSEMBLERS$ac_delim +ENABLE_CBE_PRINTF_A!$ENABLE_CBE_PRINTF_A$ac_delim +OPTIMIZE_OPTION!$OPTIMIZE_OPTION$ac_delim +EXTRA_OPTIONS!$EXTRA_OPTIONS$ac_delim +BINUTILS_INCDIR!$BINUTILS_INCDIR$ac_delim +ENABLE_LLVMC_DYNAMIC!$ENABLE_LLVMC_DYNAMIC$ac_delim +_ACEOF + + if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 97; then + break + elif $ac_last_try; then + { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5 +echo "$as_me: error: could not make $CONFIG_STATUS" >&2;} + { (exit 1); exit 1; }; } + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done + +ac_eof=`sed -n '/^CEOF[0-9]*$/s/CEOF/0/p' conf$$subs.sed` +if test -n "$ac_eof"; then + ac_eof=`echo "$ac_eof" | sort -nru | sed 1q` + ac_eof=`expr $ac_eof + 1` +fi + +cat >>$CONFIG_STATUS <<_ACEOF +cat >"\$tmp/subs-1.sed" <<\CEOF$ac_eof +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b +_ACEOF +sed ' +s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g +s/^/s,@/; s/!/@,|#_!!_#|/ +:n +t n +s/'"$ac_delim"'$/,g/; t +s/$/\\/; p +N; s/^.*\n//; s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g; b n +' >>$CONFIG_STATUS >$CONFIG_STATUS <<_ACEOF +CEOF$ac_eof +_ACEOF + + +ac_delim='%!_!# ' +for ac_last_try in false false false false false :; do + cat >conf$$subs.sed <<_ACEOF +ENABLE_LLVMC_DYNAMIC_PLUGINS!$ENABLE_LLVMC_DYNAMIC_PLUGINS$ac_delim +CXX!$CXX$ac_delim +CXXFLAGS!$CXXFLAGS$ac_delim +ac_ct_CXX!$ac_ct_CXX$ac_delim +NM!$NM$ac_delim +ifGNUmake!$ifGNUmake$ac_delim +LN_S!$LN_S$ac_delim +CMP!$CMP$ac_delim +CP!$CP$ac_delim +DATE!$DATE$ac_delim +FIND!$FIND$ac_delim +MKDIR!$MKDIR$ac_delim +MV!$MV$ac_delim +RANLIB!$RANLIB$ac_delim +RM!$RM$ac_delim +SED!$SED$ac_delim +TAR!$TAR$ac_delim +BINPWD!$BINPWD$ac_delim +GRAPHVIZ!$GRAPHVIZ$ac_delim +DOT!$DOT$ac_delim +FDP!$FDP$ac_delim +NEATO!$NEATO$ac_delim +TWOPI!$TWOPI$ac_delim +CIRCO!$CIRCO$ac_delim +GV!$GV$ac_delim +DOTTY!$DOTTY$ac_delim +PERL!$PERL$ac_delim +HAVE_PERL!$HAVE_PERL$ac_delim +INSTALL_PROGRAM!$INSTALL_PROGRAM$ac_delim +INSTALL_SCRIPT!$INSTALL_SCRIPT$ac_delim +INSTALL_DATA!$INSTALL_DATA$ac_delim +BZIP2!$BZIP2$ac_delim +DOXYGEN!$DOXYGEN$ac_delim +GROFF!$GROFF$ac_delim +GZIP!$GZIP$ac_delim +POD2HTML!$POD2HTML$ac_delim +POD2MAN!$POD2MAN$ac_delim +RUNTEST!$RUNTEST$ac_delim +TCLSH!$TCLSH$ac_delim +ZIP!$ZIP$ac_delim +OCAMLC!$OCAMLC$ac_delim +OCAMLOPT!$OCAMLOPT$ac_delim +OCAMLDEP!$OCAMLDEP$ac_delim +OCAMLDOC!$OCAMLDOC$ac_delim +GAS!$GAS$ac_delim +INSTALL_LTDL_TRUE!$INSTALL_LTDL_TRUE$ac_delim +INSTALL_LTDL_FALSE!$INSTALL_LTDL_FALSE$ac_delim +CONVENIENCE_LTDL_TRUE!$CONVENIENCE_LTDL_TRUE$ac_delim +CONVENIENCE_LTDL_FALSE!$CONVENIENCE_LTDL_FALSE$ac_delim +LIBADD_DL!$LIBADD_DL$ac_delim +ECHO!$ECHO$ac_delim +AR!$AR$ac_delim +STRIP!$STRIP$ac_delim +CXXCPP!$CXXCPP$ac_delim +F77!$F77$ac_delim +FFLAGS!$FFLAGS$ac_delim +ac_ct_F77!$ac_ct_F77$ac_delim +LIBTOOL!$LIBTOOL$ac_delim +LLVMGCCCOMMAND!$LLVMGCCCOMMAND$ac_delim +LLVMGXXCOMMAND!$LLVMGXXCOMMAND$ac_delim +LLVMGCC!$LLVMGCC$ac_delim +LLVMGXX!$LLVMGXX$ac_delim +NO_VARIADIC_MACROS!$NO_VARIADIC_MACROS$ac_delim +NO_MISSING_FIELD_INITIALIZERS!$NO_MISSING_FIELD_INITIALIZERS$ac_delim +USE_UDIS86!$USE_UDIS86$ac_delim +USE_OPROFILE!$USE_OPROFILE$ac_delim +HAVE_PTHREAD!$HAVE_PTHREAD$ac_delim +HUGE_VAL_SANITY!$HUGE_VAL_SANITY$ac_delim +ALLOCA!$ALLOCA$ac_delim +MMAP_FILE!$MMAP_FILE$ac_delim +LLVMCC1!$LLVMCC1$ac_delim +LLVMCC1PLUS!$LLVMCC1PLUS$ac_delim +LLVMGCCDIR!$LLVMGCCDIR$ac_delim +LLVMGCCLIBEXEC!$LLVMGCCLIBEXEC$ac_delim +LLVMGCC_VERSION!$LLVMGCC_VERSION$ac_delim +LLVMGCC_MAJVERS!$LLVMGCC_MAJVERS$ac_delim +LLVMGCC_LANGS!$LLVMGCC_LANGS$ac_delim +SHLIBEXT!$SHLIBEXT$ac_delim +LLVM_PREFIX!$LLVM_PREFIX$ac_delim +LLVM_BINDIR!$LLVM_BINDIR$ac_delim +LLVM_LIBDIR!$LLVM_LIBDIR$ac_delim +LLVM_DATADIR!$LLVM_DATADIR$ac_delim +LLVM_DOCSDIR!$LLVM_DOCSDIR$ac_delim +LLVM_ETCDIR!$LLVM_ETCDIR$ac_delim +LLVM_INCLUDEDIR!$LLVM_INCLUDEDIR$ac_delim +LLVM_INFODIR!$LLVM_INFODIR$ac_delim +LLVM_MANDIR!$LLVM_MANDIR$ac_delim +LLVM_CONFIGTIME!$LLVM_CONFIGTIME$ac_delim +BINDINGS_TO_BUILD!$BINDINGS_TO_BUILD$ac_delim +ALL_BINDINGS!$ALL_BINDINGS$ac_delim +OCAML_LIBDIR!$OCAML_LIBDIR$ac_delim +ENABLE_VISIBILITY_INLINES_HIDDEN!$ENABLE_VISIBILITY_INLINES_HIDDEN$ac_delim +RPATH!$RPATH$ac_delim +RDYNAMIC!$RDYNAMIC$ac_delim +LIBOBJS!$LIBOBJS$ac_delim +LTLIBOBJS!$LTLIBOBJS$ac_delim +_ACEOF + + if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 96; then + break + elif $ac_last_try; then + { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5 +echo "$as_me: error: could not make $CONFIG_STATUS" >&2;} + { (exit 1); exit 1; }; } + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done + +ac_eof=`sed -n '/^CEOF[0-9]*$/s/CEOF/0/p' conf$$subs.sed` +if test -n "$ac_eof"; then + ac_eof=`echo "$ac_eof" | sort -nru | sed 1q` + ac_eof=`expr $ac_eof + 1` +fi + +cat >>$CONFIG_STATUS <<_ACEOF +cat >"\$tmp/subs-2.sed" <<\CEOF$ac_eof +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b +_ACEOF +sed ' +s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g +s/^/s,@/; s/!/@,|#_!!_#|/ +:n +t n +s/'"$ac_delim"'$/,g/; t +s/$/\\/; p +N; s/^.*\n//; s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g; b n +' >>$CONFIG_STATUS >$CONFIG_STATUS <<_ACEOF +CEOF$ac_eof +_ACEOF + + +# VPATH may cause trouble with some makes, so we remove $(srcdir), +# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and +# trailing colons and then remove the whole line if VPATH becomes empty +# (actually we leave an empty line to preserve line numbers). +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=/{ +s/:*\$(srcdir):*/:/ +s/:*\${srcdir}:*/:/ +s/:*@srcdir@:*/:/ +s/^\([^=]*=[ ]*\):*/\1/ +s/:*$// +s/^[^=]*=[ ]*$// +}' +fi + +cat >>$CONFIG_STATUS <<\_ACEOF +fi # test -n "$CONFIG_FILES" + + +for ac_tag in :F $CONFIG_FILES :H $CONFIG_HEADERS :C $CONFIG_COMMANDS +do + case $ac_tag in + :[FHLC]) ac_mode=$ac_tag; continue;; + esac + case $ac_mode$ac_tag in + :[FHL]*:*);; + :L* | :C*:*) { { echo "$as_me:$LINENO: error: Invalid tag $ac_tag." >&5 +echo "$as_me: error: Invalid tag $ac_tag." >&2;} + { (exit 1); exit 1; }; };; + :[FH]-) ac_tag=-:-;; + :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; + esac + ac_save_IFS=$IFS + IFS=: + set x $ac_tag + IFS=$ac_save_IFS + shift + ac_file=$1 + shift + + case $ac_mode in + :L) ac_source=$1;; + :[FH]) + ac_file_inputs= + for ac_f + do + case $ac_f in + -) ac_f="$tmp/stdin";; + *) # Look for the file first in the build tree, then in the source tree + # (if the path is not absolute). The absolute path cannot be DOS-style, + # because $ac_f cannot contain `:'. + test -f "$ac_f" || + case $ac_f in + [\\/$]*) false;; + *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; + esac || + { { echo "$as_me:$LINENO: error: cannot find input file: $ac_f" >&5 +echo "$as_me: error: cannot find input file: $ac_f" >&2;} + { (exit 1); exit 1; }; };; + esac + ac_file_inputs="$ac_file_inputs $ac_f" + done + + # Let's still pretend it is `configure' which instantiates (i.e., don't + # use $as_me), people would be surprised to read: + # /* config.h. Generated by config.status. */ + configure_input="Generated from "`IFS=: + echo $* | sed 's|^[^:]*/||;s|:[^:]*/|, |g'`" by configure." + if test x"$ac_file" != x-; then + configure_input="$ac_file. $configure_input" + { echo "$as_me:$LINENO: creating $ac_file" >&5 +echo "$as_me: creating $ac_file" >&6;} + fi + + case $ac_tag in + *:-:* | *:-) cat >"$tmp/stdin";; + esac + ;; + esac + + ac_dir=`$as_dirname -- "$ac_file" || +$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || +echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + { as_dir="$ac_dir" + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || { $as_mkdir_p && mkdir -p "$as_dir"; } || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || { { echo "$as_me:$LINENO: error: cannot create directory $as_dir" >&5 +echo "$as_me: error: cannot create directory $as_dir" >&2;} + { (exit 1); exit 1; }; }; } + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,/..,g;s,/,,'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + + case $ac_mode in + :F) + # + # CONFIG_FILE + # + + case $INSTALL in + [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; + *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; + esac +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF +# If the template does not know about datarootdir, expand it. +# FIXME: This hack should be removed a few years after 2.60. +ac_datarootdir_hack=; ac_datarootdir_seen= + +case `sed -n '/datarootdir/ { + p + q +} +/@datadir@/p +/@docdir@/p +/@infodir@/p +/@localedir@/p +/@mandir@/p +' $ac_file_inputs` in +*datarootdir*) ac_datarootdir_seen=yes;; +*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) + { echo "$as_me:$LINENO: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 +echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF + ac_datarootdir_hack=' + s&@datadir@&$datadir&g + s&@docdir@&$docdir&g + s&@infodir@&$infodir&g + s&@localedir@&$localedir&g + s&@mandir@&$mandir&g + s&\\\${datarootdir}&$datarootdir&g' ;; +esac +_ACEOF + +# Neutralize VPATH when `$srcdir' = `.'. +# Shell code in configure.ac might set extrasub. +# FIXME: do we really want to maintain this feature? +cat >>$CONFIG_STATUS <<_ACEOF + sed "$ac_vpsub +$extrasub +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF +:t +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b +s&@configure_input@&$configure_input&;t t +s&@top_builddir@&$ac_top_builddir_sub&;t t +s&@srcdir@&$ac_srcdir&;t t +s&@abs_srcdir@&$ac_abs_srcdir&;t t +s&@top_srcdir@&$ac_top_srcdir&;t t +s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t +s&@builddir@&$ac_builddir&;t t +s&@abs_builddir@&$ac_abs_builddir&;t t +s&@abs_top_builddir@&$ac_abs_top_builddir&;t t +s&@INSTALL@&$ac_INSTALL&;t t +$ac_datarootdir_hack +" $ac_file_inputs | sed -f "$tmp/subs-1.sed" | sed -f "$tmp/subs-2.sed" | sed 's/|#_!!_#|//g' >$tmp/out + +test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && + { ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } && + { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' "$tmp/out"`; test -z "$ac_out"; } && + { echo "$as_me:$LINENO: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined." >&5 +echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined." >&2;} + + rm -f "$tmp/stdin" + case $ac_file in + -) cat "$tmp/out"; rm -f "$tmp/out";; + *) rm -f "$ac_file"; mv "$tmp/out" $ac_file;; + esac + ;; + :H) + # + # CONFIG_HEADER + # +_ACEOF + +# Transform confdefs.h into a sed script `conftest.defines', that +# substitutes the proper values into config.h.in to produce config.h. +rm -f conftest.defines conftest.tail +# First, append a space to every undef/define line, to ease matching. +echo 's/$/ /' >conftest.defines +# Then, protect against being on the right side of a sed subst, or in +# an unquoted here document, in config.status. If some macros were +# called several times there might be several #defines for the same +# symbol, which is useless. But do not sort them, since the last +# AC_DEFINE must be honored. +ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* +# These sed commands are passed to sed as "A NAME B PARAMS C VALUE D", where +# NAME is the cpp macro being defined, VALUE is the value it is being given. +# PARAMS is the parameter list in the macro definition--in most cases, it's +# just an empty string. +ac_dA='s,^\\([ #]*\\)[^ ]*\\([ ]*' +ac_dB='\\)[ (].*,\\1define\\2' +ac_dC=' ' +ac_dD=' ,' + +uniq confdefs.h | + sed -n ' + t rset + :rset + s/^[ ]*#[ ]*define[ ][ ]*// + t ok + d + :ok + s/[\\&,]/\\&/g + s/^\('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/ '"$ac_dA"'\1'"$ac_dB"'\2'"${ac_dC}"'\3'"$ac_dD"'/p + s/^\('"$ac_word_re"'\)[ ]*\(.*\)/'"$ac_dA"'\1'"$ac_dB$ac_dC"'\2'"$ac_dD"'/p + ' >>conftest.defines + +# Remove the space that was appended to ease matching. +# Then replace #undef with comments. This is necessary, for +# example, in the case of _POSIX_SOURCE, which is predefined and required +# on some systems where configure will not decide to define it. +# (The regexp can be short, since the line contains either #define or #undef.) +echo 's/ $// +s,^[ #]*u.*,/* & */,' >>conftest.defines + +# Break up conftest.defines: +ac_max_sed_lines=50 + +# First sed command is: sed -f defines.sed $ac_file_inputs >"$tmp/out1" +# Second one is: sed -f defines.sed "$tmp/out1" >"$tmp/out2" +# Third one will be: sed -f defines.sed "$tmp/out2" >"$tmp/out1" +# et cetera. +ac_in='$ac_file_inputs' +ac_out='"$tmp/out1"' +ac_nxt='"$tmp/out2"' + +while : +do + # Write a here document: + cat >>$CONFIG_STATUS <<_ACEOF + # First, check the format of the line: + cat >"\$tmp/defines.sed" <<\\CEOF +/^[ ]*#[ ]*undef[ ][ ]*$ac_word_re[ ]*\$/b def +/^[ ]*#[ ]*define[ ][ ]*$ac_word_re[( ]/b def +b +:def +_ACEOF + sed ${ac_max_sed_lines}q conftest.defines >>$CONFIG_STATUS + echo 'CEOF + sed -f "$tmp/defines.sed"' "$ac_in >$ac_out" >>$CONFIG_STATUS + ac_in=$ac_out; ac_out=$ac_nxt; ac_nxt=$ac_in + sed 1,${ac_max_sed_lines}d conftest.defines >conftest.tail + grep . conftest.tail >/dev/null || break + rm -f conftest.defines + mv conftest.tail conftest.defines +done +rm -f conftest.defines conftest.tail + +echo "ac_result=$ac_in" >>$CONFIG_STATUS +cat >>$CONFIG_STATUS <<\_ACEOF + if test x"$ac_file" != x-; then + echo "/* $configure_input */" >"$tmp/config.h" + cat "$ac_result" >>"$tmp/config.h" + if diff $ac_file "$tmp/config.h" >/dev/null 2>&1; then + { echo "$as_me:$LINENO: $ac_file is unchanged" >&5 +echo "$as_me: $ac_file is unchanged" >&6;} + else + rm -f $ac_file + mv "$tmp/config.h" $ac_file + fi + else + echo "/* $configure_input */" + cat "$ac_result" + fi + rm -f "$tmp/out12" + ;; + + :C) { echo "$as_me:$LINENO: executing $ac_file commands" >&5 +echo "$as_me: executing $ac_file commands" >&6;} + ;; + esac + + + case $ac_file$ac_mode in + "Makefile":C) ${llvm_src}/autoconf/mkinstalldirs `dirname Makefile` + ${SHELL} ${llvm_src}/autoconf/install-sh -m 0644 -c ${srcdir}/Makefile Makefile ;; + "Makefile.common":C) ${llvm_src}/autoconf/mkinstalldirs `dirname Makefile.common` + ${SHELL} ${llvm_src}/autoconf/install-sh -m 0644 -c ${srcdir}/Makefile.common Makefile.common ;; + "examples/Makefile":C) ${llvm_src}/autoconf/mkinstalldirs `dirname examples/Makefile` + ${SHELL} ${llvm_src}/autoconf/install-sh -m 0644 -c ${srcdir}/examples/Makefile examples/Makefile ;; + "lib/Makefile":C) ${llvm_src}/autoconf/mkinstalldirs `dirname lib/Makefile` + ${SHELL} ${llvm_src}/autoconf/install-sh -m 0644 -c ${srcdir}/lib/Makefile lib/Makefile ;; + "runtime/Makefile":C) ${llvm_src}/autoconf/mkinstalldirs `dirname runtime/Makefile` + ${SHELL} ${llvm_src}/autoconf/install-sh -m 0644 -c ${srcdir}/runtime/Makefile runtime/Makefile ;; + "test/Makefile":C) ${llvm_src}/autoconf/mkinstalldirs `dirname test/Makefile` + ${SHELL} ${llvm_src}/autoconf/install-sh -m 0644 -c ${srcdir}/test/Makefile test/Makefile ;; + "test/Makefile.tests":C) ${llvm_src}/autoconf/mkinstalldirs `dirname test/Makefile.tests` + ${SHELL} ${llvm_src}/autoconf/install-sh -m 0644 -c ${srcdir}/test/Makefile.tests test/Makefile.tests ;; + "unittests/Makefile":C) ${llvm_src}/autoconf/mkinstalldirs `dirname unittests/Makefile` + ${SHELL} ${llvm_src}/autoconf/install-sh -m 0644 -c ${srcdir}/unittests/Makefile unittests/Makefile ;; + "tools/Makefile":C) ${llvm_src}/autoconf/mkinstalldirs `dirname tools/Makefile` + ${SHELL} ${llvm_src}/autoconf/install-sh -m 0644 -c ${srcdir}/tools/Makefile tools/Makefile ;; + "utils/Makefile":C) ${llvm_src}/autoconf/mkinstalldirs `dirname utils/Makefile` + ${SHELL} ${llvm_src}/autoconf/install-sh -m 0644 -c ${srcdir}/utils/Makefile utils/Makefile ;; + "projects/Makefile":C) ${llvm_src}/autoconf/mkinstalldirs `dirname projects/Makefile` + ${SHELL} ${llvm_src}/autoconf/install-sh -m 0644 -c ${srcdir}/projects/Makefile projects/Makefile ;; + "bindings/Makefile":C) ${llvm_src}/autoconf/mkinstalldirs `dirname bindings/Makefile` + ${SHELL} ${llvm_src}/autoconf/install-sh -m 0644 -c ${srcdir}/bindings/Makefile bindings/Makefile ;; + "bindings/ocaml/Makefile.ocaml":C) ${llvm_src}/autoconf/mkinstalldirs `dirname bindings/ocaml/Makefile.ocaml` + ${SHELL} ${llvm_src}/autoconf/install-sh -m 0644 -c ${srcdir}/bindings/ocaml/Makefile.ocaml bindings/ocaml/Makefile.ocaml ;; + + esac +done # for ac_tag + + +{ (exit 0); exit 0; } +_ACEOF +chmod +x $CONFIG_STATUS +ac_clean_files=$ac_clean_files_save + + +# configure is writing to config.log, and then calls config.status. +# config.status does its own redirection, appending to config.log. +# Unfortunately, on DOS this fails, as config.log is still kept open +# by configure, so config.status won't be able to write to it; its +# output is simply discarded. So we exec the FD to /dev/null, +# effectively closing config.log, so it can be properly (re)opened and +# appended to by config.status. When coming back to configure, we +# need to make the FD available again. +if test "$no_create" != yes; then + ac_cs_success=: + ac_config_status_args= + test "$silent" = yes && + ac_config_status_args="$ac_config_status_args --quiet" + exec 5>/dev/null + $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false + exec 5>>config.log + # Use ||, not &&, to avoid exiting from the if with $? = 1, which + # would make configure fail if this is the last instruction. + $ac_cs_success || { (exit 1); exit 1; } +fi + +# +# CONFIG_SUBDIRS section. +# +if test "$no_recursion" != yes; then + + # Remove --cache-file and --srcdir arguments so they do not pile up. + ac_sub_configure_args= + ac_prev= + eval "set x $ac_configure_args" + shift + for ac_arg + do + if test -n "$ac_prev"; then + ac_prev= + continue + fi + case $ac_arg in + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* \ + | --c=*) + ;; + --config-cache | -C) + ;; + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + ;; + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + ;; + *) + case $ac_arg in + *\'*) ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + ac_sub_configure_args="$ac_sub_configure_args '$ac_arg'" ;; + esac + done + + # Always prepend --prefix to ensure using the same prefix + # in subdir configurations. + ac_arg="--prefix=$prefix" + case $ac_arg in + *\'*) ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + ac_sub_configure_args="$ac_arg $ac_sub_configure_args" + + ac_popdir=`pwd` + for ac_dir in : $subdirs; do test "x$ac_dir" = x: && continue + + # Do not complain, so a configure script can configure whichever + # parts of a large source tree are present. + test -d "$srcdir/$ac_dir" || continue + + ac_msg="=== configuring in $ac_dir (`pwd`/$ac_dir)" + echo "$as_me:$LINENO: $ac_msg" >&5 + echo "$ac_msg" >&6 + { as_dir="$ac_dir" + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || { $as_mkdir_p && mkdir -p "$as_dir"; } || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || { { echo "$as_me:$LINENO: error: cannot create directory $as_dir" >&5 +echo "$as_me: error: cannot create directory $as_dir" >&2;} + { (exit 1); exit 1; }; }; } + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,/..,g;s,/,,'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + + cd "$ac_dir" + + # Check for guested configure; otherwise get Cygnus style configure. + if test -f "$ac_srcdir/configure.gnu"; then + ac_sub_configure=$ac_srcdir/configure.gnu + elif test -f "$ac_srcdir/configure"; then + ac_sub_configure=$ac_srcdir/configure + elif test -f "$ac_srcdir/configure.in"; then + # This should be Cygnus configure. + ac_sub_configure=$ac_aux_dir/configure + else + { echo "$as_me:$LINENO: WARNING: no configuration information is in $ac_dir" >&5 +echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2;} + ac_sub_configure= + fi + + # The recursion is here. + if test -n "$ac_sub_configure"; then + # Make the cache file name correct relative to the subdirectory. + case $cache_file in + [\\/]* | ?:[\\/]* ) ac_sub_cache_file=$cache_file ;; + *) # Relative name. + ac_sub_cache_file=$ac_top_build_prefix$cache_file ;; + esac + + { echo "$as_me:$LINENO: running $SHELL $ac_sub_configure $ac_sub_configure_args --cache-file=$ac_sub_cache_file --srcdir=$ac_srcdir" >&5 +echo "$as_me: running $SHELL $ac_sub_configure $ac_sub_configure_args --cache-file=$ac_sub_cache_file --srcdir=$ac_srcdir" >&6;} + # The eval makes quoting arguments work. + eval "\$SHELL \"\$ac_sub_configure\" $ac_sub_configure_args \ + --cache-file=\"\$ac_sub_cache_file\" --srcdir=\"\$ac_srcdir\"" || + { { echo "$as_me:$LINENO: error: $ac_sub_configure failed for $ac_dir" >&5 +echo "$as_me: error: $ac_sub_configure failed for $ac_dir" >&2;} + { (exit 1); exit 1; }; } + fi + + cd "$ac_popdir" + done +fi + diff --git a/libclamav/c++/llvm/docs/AliasAnalysis.html b/libclamav/c++/llvm/docs/AliasAnalysis.html new file mode 100644 index 000000000..ebf638689 --- /dev/null +++ b/libclamav/c++/llvm/docs/AliasAnalysis.html @@ -0,0 +1,956 @@ + + + + LLVM Alias Analysis Infrastructure + + + + +
+ LLVM Alias Analysis Infrastructure +
+ +
    +
  1. Introduction
  2. + +
  3. AliasAnalysis Class Overview + +
  4. + +
  5. Writing a new AliasAnalysis Implementation + +
  6. + +
  7. Using alias analysis results + +
  8. + +
  9. Existing alias analysis implementations and clients + +
  10. +
  11. Memory Dependence Analysis
  12. +
+ +
+

Written by Chris Lattner

+
+ + + + + +
+ +

Alias Analysis (aka Pointer Analysis) is a class of techniques which attempt +to determine whether or not two pointers ever can point to the same object in +memory. There are many different algorithms for alias analysis and many +different ways of classifying them: flow-sensitive vs flow-insensitive, +context-sensitive vs context-insensitive, field-sensitive vs field-insensitive, +unification-based vs subset-based, etc. Traditionally, alias analyses respond +to a query with a Must, May, or No alias response, +indicating that two pointers always point to the same object, might point to the +same object, or are known to never point to the same object.

+ +

The LLVM AliasAnalysis +class is the primary interface used by clients and implementations of alias +analyses in the LLVM system. This class is the common interface between clients +of alias analysis information and the implementations providing it, and is +designed to support a wide range of implementations and clients (but currently +all clients are assumed to be flow-insensitive). In addition to simple alias +analysis information, this class exposes Mod/Ref information from those +implementations which can provide it, allowing for powerful analyses and +transformations to work well together.

+ +

This document contains information necessary to successfully implement this +interface, use it, and to test both sides. It also explains some of the finer +points about what exactly results mean. If you feel that something is unclear +or should be added, please let me +know.

+ +
+ + + + + +
+ +

The AliasAnalysis +class defines the interface that the various alias analysis implementations +should support. This class exports two important enums: AliasResult +and ModRefResult which represent the result of an alias query or a +mod/ref query, respectively.

+ +

The AliasAnalysis interface exposes information about memory, +represented in several different ways. In particular, memory objects are +represented as a starting address and size, and function calls are represented +as the actual call or invoke instructions that performs the +call. The AliasAnalysis interface also exposes some helper methods +which allow you to get mod/ref information for arbitrary instructions.

+ +
+ + + + +
+ +

Most importantly, the AliasAnalysis class provides several methods +which are used to query whether or not two memory objects alias, whether +function calls can modify or read a memory object, etc. For all of these +queries, memory objects are represented as a pair of their starting address (a +symbolic LLVM Value*) and a static size.

+ +

Representing memory objects as a starting address and a size is critically +important for correct Alias Analyses. For example, consider this (silly, but +possible) C code:

+ +
+
+int i;
+char C[2];
+char A[10]; 
+/* ... */
+for (i = 0; i != 10; ++i) {
+  C[0] = A[i];          /* One byte store */
+  C[1] = A[9-i];        /* One byte store */
+}
+
+
+ +

In this case, the basicaa pass will disambiguate the stores to +C[0] and C[1] because they are accesses to two distinct +locations one byte apart, and the accesses are each one byte. In this case, the +LICM pass can use store motion to remove the stores from the loop. In +constrast, the following code:

+ +
+
+int i;
+char C[2];
+char A[10]; 
+/* ... */
+for (i = 0; i != 10; ++i) {
+  ((short*)C)[0] = A[i];  /* Two byte store! */
+  C[1] = A[9-i];          /* One byte store */
+}
+
+
+ +

In this case, the two stores to C do alias each other, because the access to +the &C[0] element is a two byte access. If size information wasn't +available in the query, even the first case would have to conservatively assume +that the accesses alias.

+ +
+ + + + +
+The alias method is the primary interface used to determine whether or +not two memory objects alias each other. It takes two memory objects as input +and returns MustAlias, MayAlias, or NoAlias as appropriate. +
+ + + + +
+

The NoAlias response is used when the two pointers refer to distinct objects, +regardless of whether the pointers compare equal. For example, freed pointers +don't alias any pointers that were allocated afterwards. As a degenerate case, +pointers returned by malloc(0) have no bytes for an object, and are considered +NoAlias even when malloc returns the same pointer. The same rule applies to +NULL pointers.

+ +

The MayAlias response is used whenever the two pointers might refer to the +same object. If the two memory objects overlap, but do not start at the same +location, return MayAlias.

+ +

The MustAlias response may only be returned if the two memory objects are +guaranteed to always start at exactly the same location. A MustAlias response +implies that the pointers compare equal.

+ +
+ + + + +
+ +

The getModRefInfo methods return information about whether the +execution of an instruction can read or modify a memory location. Mod/Ref +information is always conservative: if an instruction might read or write +a location, ModRef is returned.

+ +

The AliasAnalysis class also provides a getModRefInfo +method for testing dependencies between function calls. This method takes two +call sites (CS1 & CS2), returns NoModRef if the two calls refer to disjoint +memory locations, Ref if CS1 reads memory written by CS2, Mod if CS1 writes to +memory read or written by CS2, or ModRef if CS1 might read or write memory +accessed by CS2. Note that this relation is not commutative.

+ +
+ + + + + +
+ +

+Several other tidbits of information are often collected by various alias +analysis implementations and can be put to good use by various clients. +

+ +
+ + +
+ The pointsToConstantMemory method +
+ +
+ +

The pointsToConstantMemory method returns true if and only if the +analysis can prove that the pointer only points to unchanging memory locations +(functions, constant global variables, and the null pointer). This information +can be used to refine mod/ref information: it is impossible for an unchanging +memory location to be modified.

+ +
+ + + + +
+ +

These methods are used to provide very simple mod/ref information for +function calls. The doesNotAccessMemory method returns true for a +function if the analysis can prove that the function never reads or writes to +memory, or if the function only reads from constant memory. Functions with this +property are side-effect free and only depend on their input arguments, allowing +them to be eliminated if they form common subexpressions or be hoisted out of +loops. Many common functions behave this way (e.g., sin and +cos) but many others do not (e.g., acos, which modifies the +errno variable).

+ +

The onlyReadsMemory method returns true for a function if analysis +can prove that (at most) the function only reads from non-volatile memory. +Functions with this property are side-effect free, only depending on their input +arguments and the state of memory when they are called. This property allows +calls to these functions to be eliminated and moved around, as long as there is +no store instruction that changes the contents of memory. Note that all +functions that satisfy the doesNotAccessMemory method also satisfies +onlyReadsMemory.

+ +
+ + + + + +
+ +

Writing a new alias analysis implementation for LLVM is quite +straight-forward. There are already several implementations that you can use +for examples, and the following information should help fill in any details. +For a examples, take a look at the various alias analysis +implementations included with LLVM.

+ +
+ + + + +
+ +

The first step to determining what type of LLVM pass you need to use for your Alias +Analysis. As is the case with most other analyses and transformations, the +answer should be fairly obvious from what type of problem you are trying to +solve:

+ +
    +
  1. If you require interprocedural analysis, it should be a + Pass.
  2. +
  3. If you are a function-local analysis, subclass FunctionPass.
  4. +
  5. If you don't need to look at the program at all, subclass + ImmutablePass.
  6. +
+ +

In addition to the pass that you subclass, you should also inherit from the +AliasAnalysis interface, of course, and use the +RegisterAnalysisGroup template to register as an implementation of +AliasAnalysis.

+ +
+ + + + +
+ +

Your subclass of AliasAnalysis is required to invoke two methods on +the AliasAnalysis base class: getAnalysisUsage and +InitializeAliasAnalysis. In particular, your implementation of +getAnalysisUsage should explicitly call into the +AliasAnalysis::getAnalysisUsage method in addition to doing any +declaring any pass dependencies your pass has. Thus you should have something +like this:

+ +
+
+void getAnalysisUsage(AnalysisUsage &AU) const {
+  AliasAnalysis::getAnalysisUsage(AU);
+  // declare your dependencies here.
+}
+
+
+ +

Additionally, your must invoke the InitializeAliasAnalysis method +from your analysis run method (run for a Pass, +runOnFunction for a FunctionPass, or InitializePass +for an ImmutablePass). For example (as part of a Pass):

+ +
+
+bool run(Module &M) {
+  InitializeAliasAnalysis(this);
+  // Perform analysis here...
+  return false;
+}
+
+
+ +
+ + + + +
+ +

All of the AliasAnalysis +virtual methods default to providing chaining to another +alias analysis implementation, which ends up returning conservatively correct +information (returning "May" Alias and "Mod/Ref" for alias and mod/ref queries +respectively). Depending on the capabilities of the analysis you are +implementing, you just override the interfaces you can improve.

+ +
+ + + + + + +
+ +

With only two special exceptions (the basicaa and no-aa +passes) every alias analysis pass chains to another alias analysis +implementation (for example, the user can specify "-basicaa -ds-aa +-anders-aa -licm" to get the maximum benefit from the three alias +analyses). The alias analysis class automatically takes care of most of this +for methods that you don't override. For methods that you do override, in code +paths that return a conservative MayAlias or Mod/Ref result, simply return +whatever the superclass computes. For example:

+ +
+
+AliasAnalysis::AliasResult alias(const Value *V1, unsigned V1Size,
+                                 const Value *V2, unsigned V2Size) {
+  if (...)
+    return NoAlias;
+  ...
+
+  // Couldn't determine a must or no-alias result.
+  return AliasAnalysis::alias(V1, V1Size, V2, V2Size);
+}
+
+
+ +

In addition to analysis queries, you must make sure to unconditionally pass +LLVM update notification methods to the superclass as +well if you override them, which allows all alias analyses in a change to be +updated.

+ +
+ + + + + +
+

+Alias analysis information is initially computed for a static snapshot of the +program, but clients will use this information to make transformations to the +code. All but the most trivial forms of alias analysis will need to have their +analysis results updated to reflect the changes made by these transformations. +

+ +

+The AliasAnalysis interface exposes two methods which are used to +communicate program changes from the clients to the analysis implementations. +Various alias analysis implementations should use these methods to ensure that +their internal data structures are kept up-to-date as the program changes (for +example, when an instruction is deleted), and clients of alias analysis must be +sure to call these interfaces appropriately. +

+
+ + +
The deleteValue method
+ +
+The deleteValue method is called by transformations when they remove an +instruction or any other value from the program (including values that do not +use pointers). Typically alias analyses keep data structures that have entries +for each value in the program. When this method is called, they should remove +any entries for the specified value, if they exist. +
+ + +
The copyValue method
+ +
+The copyValue method is used when a new value is introduced into the +program. There is no way to introduce a value into the program that did not +exist before (this doesn't make sense for a safe compiler transformation), so +this is the only way to introduce a new value. This method indicates that the +new value has exactly the same properties as the value being copied. +
+ + +
The replaceWithNewValue method
+ +
+This method is a simple helper method that is provided to make clients easier to +use. It is implemented by copying the old analysis information to the new +value, then deleting the old value. This method cannot be overridden by alias +analysis implementations. +
+ + + + +
+ +

From the LLVM perspective, the only thing you need to do to provide an +efficient alias analysis is to make sure that alias analysis queries are +serviced quickly. The actual calculation of the alias analysis results (the +"run" method) is only performed once, but many (perhaps duplicate) queries may +be performed. Because of this, try to move as much computation to the run +method as possible (within reason).

+ +
+ + + + + +
+ +

There are several different ways to use alias analysis results. In order of +preference, these are...

+ +
+ + + + +
+ +

The memdep pass uses alias analysis to provide high-level dependence +information about memory-using instructions. This will tell you which store +feeds into a load, for example. It uses caching and other techniques to be +efficient, and is used by Dead Store Elimination, GVN, and memcpy optimizations. +

+ +
+ + + + +
+ +

Many transformations need information about alias sets that are active +in some scope, rather than information about pairwise aliasing. The AliasSetTracker class +is used to efficiently build these Alias Sets from the pairwise alias analysis +information provided by the AliasAnalysis interface.

+ +

First you initialize the AliasSetTracker by using the "add" methods +to add information about various potentially aliasing instructions in the scope +you are interested in. Once all of the alias sets are completed, your pass +should simply iterate through the constructed alias sets, using the +AliasSetTracker begin()/end() methods.

+ +

The AliasSets formed by the AliasSetTracker are guaranteed +to be disjoint, calculate mod/ref information and volatility for the set, and +keep track of whether or not all of the pointers in the set are Must aliases. +The AliasSetTracker also makes sure that sets are properly folded due to call +instructions, and can provide a list of pointers in each set.

+ +

As an example user of this, the Loop +Invariant Code Motion pass uses AliasSetTrackers to calculate alias +sets for each loop nest. If an AliasSet in a loop is not modified, +then all load instructions from that set may be hoisted out of the loop. If any +alias sets are stored to and are must alias sets, then the stores may be +sunk to outside of the loop, promoting the memory location to a register for the +duration of the loop nest. Both of these transformations only apply if the +pointer argument is loop-invariant.

+ +
+ + +
+ The AliasSetTracker implementation +
+ +
+ +

The AliasSetTracker class is implemented to be as efficient as possible. It +uses the union-find algorithm to efficiently merge AliasSets when a pointer is +inserted into the AliasSetTracker that aliases multiple sets. The primary data +structure is a hash table mapping pointers to the AliasSet they are in.

+ +

The AliasSetTracker class must maintain a list of all of the LLVM Value*'s +that are in each AliasSet. Since the hash table already has entries for each +LLVM Value* of interest, the AliasesSets thread the linked list through these +hash-table nodes to avoid having to allocate memory unnecessarily, and to make +merging alias sets extremely efficient (the linked list merge is constant time). +

+ +

You shouldn't need to understand these details if you are just a client of +the AliasSetTracker, but if you look at the code, hopefully this brief +description will help make sense of why things are designed the way they +are.

+ +
+ + + + +
+ +

If neither of these utility class are what your pass needs, you should use +the interfaces exposed by the AliasAnalysis class directly. Try to use +the higher-level methods when possible (e.g., use mod/ref information instead of +the alias method directly if possible) to get the +best precision and efficiency.

+ +
+ + + + + +
+ +

If you're going to be working with the LLVM alias analysis infrastructure, +you should know what clients and implementations of alias analysis are +available. In particular, if you are implementing an alias analysis, you should +be aware of the the clients that are useful +for monitoring and evaluating different implementations.

+ +
+ + + + +
+ +

This section lists the various implementations of the AliasAnalysis +interface. With the exception of the -no-aa and +-basicaa implementations, all of these chain to other alias analysis implementations.

+ +
+ + + + +
+ +

The -no-aa pass is just like what it sounds: an alias analysis that +never returns any useful information. This pass can be useful if you think that +alias analysis is doing something wrong and are trying to narrow down a +problem.

+ +
+ + + + +
+ +

The -basicaa pass is the default LLVM alias analysis. It is an +aggressive local analysis that "knows" many important facts:

+ +
    +
  • Distinct globals, stack allocations, and heap allocations can never + alias.
  • +
  • Globals, stack allocations, and heap allocations never alias the null + pointer.
  • +
  • Different fields of a structure do not alias.
  • +
  • Indexes into arrays with statically differing subscripts cannot alias.
  • +
  • Many common standard C library functions never access memory or only read memory.
  • +
  • Pointers that obviously point to constant globals + "pointToConstantMemory".
  • +
  • Function calls can not modify or references stack allocations if they never + escape from the function that allocates them (a common case for automatic + arrays).
  • +
+ +
+ + + + +
+ +

This pass implements a simple context-sensitive mod/ref and alias analysis +for internal global variables that don't "have their address taken". If a +global does not have its address taken, the pass knows that no pointers alias +the global. This pass also keeps track of functions that it knows never access +memory or never read memory. This allows certain optimizations (e.g. GVN) to +eliminate call instructions entirely. +

+ +

The real power of this pass is that it provides context-sensitive mod/ref +information for call instructions. This allows the optimizer to know that +calls to a function do not clobber or read the value of the global, allowing +loads and stores to be eliminated.

+ +

Note that this pass is somewhat limited in its scope (only support +non-address taken globals), but is very quick analysis.

+
+ + + + +
+ +

The -anders-aa pass implements the well-known "Andersen's algorithm" +for interprocedural alias analysis. This algorithm is a subset-based, +flow-insensitive, context-insensitive, and field-insensitive alias analysis that +is widely believed to be fairly precise. Unfortunately, this algorithm is also +O(N3). The LLVM implementation currently does not implement any of +the refinements (such as "online cycle elimination" or "offline variable +substitution") to improve its efficiency, so it can be quite slow in common +cases. +

+ +
+ + + + +
+ +

The -steens-aa pass implements a variation on the well-known +"Steensgaard's algorithm" for interprocedural alias analysis. Steensgaard's +algorithm is a unification-based, flow-insensitive, context-insensitive, and +field-insensitive alias analysis that is also very scalable (effectively linear +time).

+ +

The LLVM -steens-aa pass implements a "speculatively +field-sensitive" version of Steensgaard's algorithm using the Data +Structure Analysis framework. This gives it substantially more precision than +the standard algorithm while maintaining excellent analysis scalability.

+ +

Note that -steens-aa is available in the optional "poolalloc" +module, it is not part of the LLVM core.

+ +
+ + + + +
+ +

The -ds-aa pass implements the full Data Structure Analysis +algorithm. Data Structure Analysis is a modular unification-based, +flow-insensitive, context-sensitive, and speculatively +field-sensitive alias analysis that is also quite scalable, usually at +O(n*log(n)).

+ +

This algorithm is capable of responding to a full variety of alias analysis +queries, and can provide context-sensitive mod/ref information as well. The +only major facility not implemented so far is support for must-alias +information.

+ +

Note that -ds-aa is available in the optional "poolalloc" +module, it is not part of the LLVM core.

+ +
+ + + + + +
+LLVM includes several alias-analysis driven transformations which can be used +with any of the implementations above. +
+ + + + +
+ +

The -adce pass, which implements Aggressive Dead Code Elimination +uses the AliasAnalysis interface to delete calls to functions that do +not have side-effects and are not used.

+ +
+ + + + + +
+ +

The -licm pass implements various Loop Invariant Code Motion related +transformations. It uses the AliasAnalysis interface for several +different transformations:

+ +
    +
  • It uses mod/ref information to hoist or sink load instructions out of loops +if there are no instructions in the loop that modifies the memory loaded.
  • + +
  • It uses mod/ref information to hoist function calls out of loops that do not +write to memory and are loop-invariant.
  • + +
  • If uses alias information to promote memory objects that are loaded and +stored to in loops to live in a register instead. It can do this if there are +no may aliases to the loaded/stored memory location.
  • +
+ +
+ + + + +
+

+The -argpromotion pass promotes by-reference arguments to be passed in +by-value instead. In particular, if pointer arguments are only loaded from it +passes in the value loaded instead of the address to the function. This pass +uses alias information to make sure that the value loaded from the argument +pointer is not modified between the entry of the function and any load of the +pointer.

+
+ + + + +
+ +

These passes use AliasAnalysis information to reason about loads and stores. +

+ +
+ + + + +
+ +

These passes are useful for evaluating the various alias analysis +implementations. You can use them with commands like 'opt -anders-aa -ds-aa +-aa-eval foo.bc -disable-output -stats'.

+ +
+ + + + +
+ +

The -print-alias-sets pass is exposed as part of the +opt tool to print out the Alias Sets formed by the AliasSetTracker class. This is useful if you're using +the AliasSetTracker class. To use it, use something like:

+ +
+
+% opt -ds-aa -print-alias-sets -disable-output
+
+
+ +
+ + + + + +
+ +

The -count-aa pass is useful to see how many queries a particular +pass is making and what responses are returned by the alias analysis. As an +example,

+ +
+
+% opt -basicaa -count-aa -ds-aa -count-aa -licm
+
+
+ +

will print out how many queries (and what responses are returned) by the +-licm pass (of the -ds-aa pass) and how many queries are made +of the -basicaa pass by the -ds-aa pass. This can be useful +when debugging a transformation or an alias analysis implementation.

+ +
+ + + + +
+ +

The -aa-eval pass simply iterates through all pairs of pointers in a +function and asks an alias analysis whether or not the pointers alias. This +gives an indication of the precision of the alias analysis. Statistics are +printed indicating the percent of no/may/must aliases found (a more precise +algorithm will have a lower number of may aliases).

+ +
+ + + + + +
+ +

If you're just looking to be a client of alias analysis information, consider +using the Memory Dependence Analysis interface instead. MemDep is a lazy, +caching layer on top of alias analysis that is able to answer the question of +what preceding memory operations a given instruction depends on, either at an +intra- or inter-block level. Because of its laziness and caching +policy, using MemDep can be a significant performance win over accessing alias +analysis directly.

+ +
+ + + +
+
+ Valid CSS + Valid HTML 4.01 + + Chris Lattner
+ LLVM Compiler Infrastructure
+ Last modified: $Date$ +
+ + + diff --git a/libclamav/c++/llvm/docs/BitCodeFormat.html b/libclamav/c++/llvm/docs/BitCodeFormat.html new file mode 100644 index 000000000..655d7f69b --- /dev/null +++ b/libclamav/c++/llvm/docs/BitCodeFormat.html @@ -0,0 +1,1164 @@ + + + + + LLVM Bitcode File Format + + + +
LLVM Bitcode File Format
+
    +
  1. Abstract
  2. +
  3. Overview
  4. +
  5. Bitstream Format +
      +
    1. Magic Numbers
    2. +
    3. Primitives
    4. +
    5. Abbreviation IDs
    6. +
    7. Blocks
    8. +
    9. Data Records
    10. +
    11. Abbreviations
    12. +
    13. Standard Blocks
    14. +
    +
  6. +
  7. Bitcode Wrapper Format +
  8. +
  9. LLVM IR Encoding +
      +
    1. Basics
    2. +
    3. MODULE_BLOCK Contents
    4. +
    5. PARAMATTR_BLOCK Contents
    6. +
    7. TYPE_BLOCK Contents
    8. +
    9. CONSTANTS_BLOCK Contents
    10. +
    11. FUNCTION_BLOCK Contents
    12. +
    13. TYPE_SYMTAB_BLOCK Contents
    14. +
    15. VALUE_SYMTAB_BLOCK Contents
    16. +
    17. METADATA_BLOCK Contents
    18. +
    19. METADATA_ATTACHMENT Contents
    20. +
    +
  10. +
+
+

Written by Chris Lattner + and Joshua Haberman. +

+
+ + + + + +
+ +

This document describes the LLVM bitstream file format and the encoding of +the LLVM IR into it.

+ +
+ + + + + +
+ +

+What is commonly known as the LLVM bitcode file format (also, sometimes +anachronistically known as bytecode) is actually two things: a bitstream container format +and an encoding of LLVM IR into the container format.

+ +

+The bitstream format is an abstract encoding of structured data, very +similar to XML in some ways. Like XML, bitstream files contain tags, and nested +structures, and you can parse the file without having to understand the tags. +Unlike XML, the bitstream format is a binary encoding, and unlike XML it +provides a mechanism for the file to self-describe "abbreviations", which are +effectively size optimizations for the content.

+ +

LLVM IR files may be optionally embedded into a wrapper structure that makes it easy to embed extra data +along with LLVM IR files.

+ +

This document first describes the LLVM bitstream format, describes the +wrapper format, then describes the record structure used by LLVM IR files. +

+ +
+ + + + + +
+ +

+The bitstream format is literally a stream of bits, with a very simple +structure. This structure consists of the following concepts: +

+ +
    +
  • A "magic number" that identifies the contents of + the stream.
  • +
  • Encoding primitives like variable bit-rate + integers.
  • +
  • Blocks, which define nested content.
  • +
  • Data Records, which describe entities within the + file.
  • +
  • Abbreviations, which specify compression optimizations for the file.
  • +
+ +

Note that the llvm-bcanalyzer tool can be +used to dump and inspect arbitrary bitstreams, which is very useful for +understanding the encoding.

+ +
+ + + + +
+ +

The first two bytes of a bitcode file are 'BC' (0x42, 0x43). +The second two bytes are an application-specific magic number. Generic +bitcode tools can look at only the first two bytes to verify the file is +bitcode, while application-specific programs will want to look at all four.

+ +
+ + + + +
+ +

+A bitstream literally consists of a stream of bits, which are read in order +starting with the least significant bit of each byte. The stream is made up of a +number of primitive values that encode a stream of unsigned integer values. +These +integers are are encoded in two ways: either as Fixed +Width Integers or as Variable Width +Integers. +

+ +
+ + + + +
+ +

Fixed-width integer values have their low bits emitted directly to the file. + For example, a 3-bit integer value encodes 1 as 001. Fixed width integers + are used when there are a well-known number of options for a field. For + example, boolean values are usually encoded with a 1-bit wide integer. +

+ +
+ + + + +
+ +

Variable-width integer (VBR) values encode values of arbitrary size, +optimizing for the case where the values are small. Given a 4-bit VBR field, +any 3-bit value (0 through 7) is encoded directly, with the high bit set to +zero. Values larger than N-1 bits emit their bits in a series of N-1 bit +chunks, where all but the last set the high bit.

+ +

For example, the value 27 (0x1B) is encoded as 1011 0011 when emitted as a +vbr4 value. The first set of four bits indicates the value 3 (011) with a +continuation piece (indicated by a high bit of 1). The next word indicates a +value of 24 (011 << 3) with no continuation. The sum (3+24) yields the value +27. +

+ +
+ + + + +
+ +

6-bit characters encode common characters into a fixed 6-bit field. They +represent the following characters with the following 6-bit values:

+ +
+
+'a' .. 'z' —  0 .. 25
+'A' .. 'Z' — 26 .. 51
+'0' .. '9' — 52 .. 61
+       '.' — 62
+       '_' — 63
+
+
+ +

This encoding is only suitable for encoding characters and strings that +consist only of the above characters. It is completely incapable of encoding +characters not in the set.

+ +
+ + + + +
+ +

Occasionally, it is useful to emit zero bits until the bitstream is a +multiple of 32 bits. This ensures that the bit position in the stream can be +represented as a multiple of 32-bit words.

+ +
+ + + + + +
+ +

+A bitstream is a sequential series of Blocks and +Data Records. Both of these start with an +abbreviation ID encoded as a fixed-bitwidth field. The width is specified by +the current block, as described below. The value of the abbreviation ID +specifies either a builtin ID (which have special meanings, defined below) or +one of the abbreviation IDs defined for the current block by the stream itself. +

+ +

+The set of builtin abbrev IDs is: +

+ +
    +
  • 0 - END_BLOCK — This abbrev ID marks + the end of the current block.
  • +
  • 1 - ENTER_SUBBLOCK — This + abbrev ID marks the beginning of a new block.
  • +
  • 2 - DEFINE_ABBREV — This defines + a new abbreviation.
  • +
  • 3 - UNABBREV_RECORD — This ID + specifies the definition of an unabbreviated record.
  • +
+ +

Abbreviation IDs 4 and above are defined by the stream itself, and specify +an abbreviated record encoding.

+ +
+ + + + +
+ +

+Blocks in a bitstream denote nested regions of the stream, and are identified by +a content-specific id number (for example, LLVM IR uses an ID of 12 to represent +function bodies). Block IDs 0-7 are reserved for standard blocks +whose meaning is defined by Bitcode; block IDs 8 and greater are +application specific. Nested blocks capture the hierarchical structure of the data +encoded in it, and various properties are associated with blocks as the file is +parsed. Block definitions allow the reader to efficiently skip blocks +in constant time if the reader wants a summary of blocks, or if it wants to +efficiently skip data it does not understand. The LLVM IR reader uses this +mechanism to skip function bodies, lazily reading them on demand. +

+ +

+When reading and encoding the stream, several properties are maintained for the +block. In particular, each block maintains: +

+ +
    +
  1. A current abbrev id width. This value starts at 2 at the beginning of + the stream, and is set every time a + block record is entered. The block entry specifies the abbrev id width for + the body of the block.
  2. + +
  3. A set of abbreviations. Abbreviations may be defined within a block, in + which case they are only defined in that block (neither subblocks nor + enclosing blocks see the abbreviation). Abbreviations can also be defined + inside a BLOCKINFO block, in which case + they are defined in all blocks that match the ID that the BLOCKINFO block is + describing. +
  4. +
+ +

+As sub blocks are entered, these properties are saved and the new sub-block has +its own set of abbreviations, and its own abbrev id width. When a sub-block is +popped, the saved values are restored. +

+ +
+ + + + +
+ +

[ENTER_SUBBLOCK, blockidvbr8, newabbrevlenvbr4, + <align32bits>, blocklen32]

+ +

+The ENTER_SUBBLOCK abbreviation ID specifies the start of a new block +record. The blockid value is encoded as an 8-bit VBR identifier, and +indicates the type of block being entered, which can be +a standard block or an application-specific block. +The newabbrevlen value is a 4-bit VBR, which specifies the abbrev id +width for the sub-block. The blocklen value is a 32-bit aligned value +that specifies the size of the subblock in 32-bit words. This value allows the +reader to skip over the entire block in one jump. +

+ +
+ + + + +
+ +

[END_BLOCK, <align32bits>]

+ +

+The END_BLOCK abbreviation ID specifies the end of the current block +record. Its end is aligned to 32-bits to ensure that the size of the block is +an even multiple of 32-bits. +

+ +
+ + + + + + +
+

+Data records consist of a record code and a number of (up to) 64-bit +integer values. The interpretation of the code and values is +application specific and may vary between different block types. +Records can be encoded either using an unabbrev record, or with an +abbreviation. In the LLVM IR format, for example, there is a record +which encodes the target triple of a module. The code is +MODULE_CODE_TRIPLE, and the values of the record are the +ASCII codes for the characters in the string. +

+ +
+ + + + +
+ +

[UNABBREV_RECORD, codevbr6, numopsvbr6, + op0vbr6, op1vbr6, ...]

+ +

+An UNABBREV_RECORD provides a default fallback encoding, which is both +completely general and extremely inefficient. It can describe an arbitrary +record by emitting the code and operands as VBRs. +

+ +

+For example, emitting an LLVM IR target triple as an unabbreviated record +requires emitting the UNABBREV_RECORD abbrevid, a vbr6 for the +MODULE_CODE_TRIPLE code, a vbr6 for the length of the string, which is +equal to the number of operands, and a vbr6 for each character. Because there +are no letters with values less than 32, each letter would need to be emitted as +at least a two-part VBR, which means that each letter would require at least 12 +bits. This is not an efficient encoding, but it is fully general. +

+ +
+ + + + +
+ +

[<abbrevid>, fields...]

+ +

+An abbreviated record is a abbreviation id followed by a set of fields that are +encoded according to the abbreviation definition. +This allows records to be encoded significantly more densely than records +encoded with the UNABBREV_RECORD type, +and allows the abbreviation types to be specified in the stream itself, which +allows the files to be completely self describing. The actual encoding of +abbreviations is defined below. +

+ +

The record code, which is the first field of an abbreviated record, +may be encoded in the abbreviation definition (as a literal +operand) or supplied in the abbreviated record (as a Fixed or VBR +operand value).

+ +
+ + + + +
+

+Abbreviations are an important form of compression for bitstreams. The idea is +to specify a dense encoding for a class of records once, then use that encoding +to emit many records. It takes space to emit the encoding into the file, but +the space is recouped (hopefully plus some) when the records that use it are +emitted. +

+ +

+Abbreviations can be determined dynamically per client, per file. Because the +abbreviations are stored in the bitstream itself, different streams of the same +format can contain different sets of abbreviations according to the needs +of the specific stream. +As a concrete example, LLVM IR files usually emit an abbreviation +for binary operators. If a specific LLVM module contained no or few binary +operators, the abbreviation does not need to be emitted. +

+
+ + + + +
+ +

[DEFINE_ABBREV, numabbrevopsvbr5, abbrevop0, abbrevop1, + ...]

+ +

+A DEFINE_ABBREV record adds an abbreviation to the list of currently +defined abbreviations in the scope of this block. This definition only exists +inside this immediate block — it is not visible in subblocks or enclosing +blocks. Abbreviations are implicitly assigned IDs sequentially starting from 4 +(the first application-defined abbreviation ID). Any abbreviations defined in a +BLOCKINFO record for the particular block type +receive IDs first, in order, followed by any +abbreviations defined within the block itself. Abbreviated data records +reference this ID to indicate what abbreviation they are invoking. +

+ +

+An abbreviation definition consists of the DEFINE_ABBREV abbrevid +followed by a VBR that specifies the number of abbrev operands, then the abbrev +operands themselves. Abbreviation operands come in three forms. They all start +with a single bit that indicates whether the abbrev operand is a literal operand +(when the bit is 1) or an encoding operand (when the bit is 0). +

+ +
    +
  1. Literal operands — [11, litvaluevbr8] +— Literal operands specify that the value in the result is always a single +specific value. This specific value is emitted as a vbr8 after the bit +indicating that it is a literal operand.
  2. +
  3. Encoding info without data — [01, + encoding3] — Operand encodings that do not have extra + data are just emitted as their code. +
  4. +
  5. Encoding info with data — [01, encoding3, +valuevbr5] — Operand encodings that do have extra data are +emitted as their code, followed by the extra data. +
  6. +
+ +

The possible operand encodings are:

+ +
    +
  • Fixed (code 1): The field should be emitted as + a fixed-width value, whose width is specified by + the operand's extra data.
  • +
  • VBR (code 2): The field should be emitted as + a variable-width value, whose width is + specified by the operand's extra data.
  • +
  • Array (code 3): This field is an array of values. The array operand + has no extra data, but expects another operand to follow it, indicating + the element type of the array. When reading an array in an abbreviated + record, the first integer is a vbr6 that indicates the array length, + followed by the encoded elements of the array. An array may only occur as + the last operand of an abbreviation (except for the one final operand that + gives the array's type).
  • +
  • Char6 (code 4): This field should be emitted as + a char6-encoded value. This operand type takes no + extra data. Char6 encoding is normally used as an array element type. +
  • +
  • Blob (code 5): This field is emitted as a vbr6, followed by padding to a + 32-bit boundary (for alignment) and an array of 8-bit objects. The array of + bytes is further followed by tail padding to ensure that its total length is + a multiple of 4 bytes. This makes it very efficient for the reader to + decode the data without having to make a copy of it: it can use a pointer to + the data in the mapped in file and poke directly at it. A blob may only + occur as the last operand of an abbreviation.
  • +
+ +

+For example, target triples in LLVM modules are encoded as a record of the +form [TRIPLE, 'a', 'b', 'c', 'd']. Consider if the bitstream emitted +the following abbrev entry: +

+ +
+
+[0, Fixed, 4]
+[0, Array]
+[0, Char6]
+
+
+ +

+When emitting a record with this abbreviation, the above entry would be emitted +as: +

+ +
+

+[4abbrevwidth, 24, 4vbr6, 06, +16, 26, 36] +

+
+ +

These values are:

+ +
    +
  1. The first value, 4, is the abbreviation ID for this abbreviation.
  2. +
  3. The second value, 2, is the record code for TRIPLE records within LLVM IR file MODULE_BLOCK blocks.
  4. +
  5. The third value, 4, is the length of the array.
  6. +
  7. The rest of the values are the char6 encoded values + for "abcd".
  8. +
+ +

+With this abbreviation, the triple is emitted with only 37 bits (assuming a +abbrev id width of 3). Without the abbreviation, significantly more space would +be required to emit the target triple. Also, because the TRIPLE value +is not emitted as a literal in the abbreviation, the abbreviation can also be +used for any other string value. +

+ +
+ + + + +
+ +

+In addition to the basic block structure and record encodings, the bitstream +also defines specific built-in block types. These block types specify how the +stream is to be decoded or other metadata. In the future, new standard blocks +may be added. Block IDs 0-7 are reserved for standard blocks. +

+ +
+ + + + +
+ +

+The BLOCKINFO block allows the description of metadata for other +blocks. The currently specified records are: +

+ +
+
+[SETBID (#1), blockid]
+[DEFINE_ABBREV, ...]
+[BLOCKNAME, ...name...]
+[SETRECORDNAME, RecordID, ...name...]
+
+
+ +

+The SETBID record (code 1) indicates which block ID is being +described. SETBID records can occur multiple times throughout the +block to change which block ID is being described. There must be +a SETBID record prior to any other records. +

+ +

+Standard DEFINE_ABBREV records can occur inside BLOCKINFO +blocks, but unlike their occurrence in normal blocks, the abbreviation is +defined for blocks matching the block ID we are describing, not the +BLOCKINFO block itself. The abbreviations defined +in BLOCKINFO blocks receive abbreviation IDs as described +in DEFINE_ABBREV. +

+ +

The BLOCKNAME record (code 2) can optionally occur in this block. The elements of +the record are the bytes of the string name of the block. llvm-bcanalyzer can use +this to dump out bitcode files symbolically.

+ +

The SETRECORDNAME record (code 3) can also optionally occur in this block. The +first operand value is a record ID number, and the rest of the elements of the record are +the bytes for the string name of the record. llvm-bcanalyzer can use +this to dump out bitcode files symbolically.

+ +

+Note that although the data in BLOCKINFO blocks is described as +"metadata," the abbreviations they contain are essential for parsing records +from the corresponding blocks. It is not safe to skip them. +

+ +
+ + + + + +
+ +

+Bitcode files for LLVM IR may optionally be wrapped in a simple wrapper +structure. This structure contains a simple header that indicates the offset +and size of the embedded BC file. This allows additional information to be +stored alongside the BC file. The structure of this file header is: +

+ +
+

+[Magic32, Version32, Offset32, +Size32, CPUType32] +

+
+ +

+Each of the fields are 32-bit fields stored in little endian form (as with +the rest of the bitcode file fields). The Magic number is always +0x0B17C0DE and the version is currently always 0. The Offset +field is the offset in bytes to the start of the bitcode stream in the file, and +the Size field is the size in bytes of the stream. CPUType is a target-specific +value that can be used to encode the CPU of the target. +

+ +
+ + + + + +
+ +

+LLVM IR is encoded into a bitstream by defining blocks and records. It uses +blocks for things like constant pools, functions, symbol tables, etc. It uses +records for things like instructions, global variable descriptors, type +descriptions, etc. This document does not describe the set of abbreviations +that the writer uses, as these are fully self-described in the file, and the +reader is not allowed to build in any knowledge of this. +

+ +
+ + + + + + + +
+ +

+The magic number for LLVM IR files is: +

+ +
+

+[0x04, 0xC4, 0xE4, 0xD4] +

+
+ +

+When combined with the bitcode magic number and viewed as bytes, this is +"BC 0xC0DE". +

+ +
+ + + + +
+ +

+Variable Width Integer encoding is an efficient way to +encode arbitrary sized unsigned values, but is an extremely inefficient for +encoding signed values, as signed values are otherwise treated as maximally large +unsigned values. +

+ +

+As such, signed VBR values of a specific width are emitted as follows: +

+ +
    +
  • Positive values are emitted as VBRs of the specified width, but with their + value shifted left by one.
  • +
  • Negative values are emitted as VBRs of the specified width, but the negated + value is shifted left by one, and the low bit is set.
  • +
+ +

+With this encoding, small positive and small negative values can both +be emitted efficiently. Signed VBR encoding is used in +CST_CODE_INTEGER and CST_CODE_WIDE_INTEGER records +within CONSTANTS_BLOCK blocks. +

+ +
+ + + + + +
+ +

+LLVM IR is defined with the following blocks: +

+ +
    +
  • 8 — MODULE_BLOCK — This is the top-level block that + contains the entire module, and describes a variety of per-module + information.
  • +
  • 9 — PARAMATTR_BLOCK — This enumerates the parameter + attributes.
  • +
  • 10 — TYPE_BLOCK — This describes all of the types in + the module.
  • +
  • 11 — CONSTANTS_BLOCK — This describes constants for a + module or function.
  • +
  • 12 — FUNCTION_BLOCK — This describes a function + body.
  • +
  • 13 — TYPE_SYMTAB_BLOCK — This describes the type symbol + table.
  • +
  • 14 — VALUE_SYMTAB_BLOCK — This describes a value symbol + table.
  • +
  • 15 — METADATA_BLOCK — This describes metadata items.
  • +
  • 16 — METADATA_ATTACHMENT — This contains records associating metadata with function instruction values.
  • +
+ +
+ + + + +
+ +

The MODULE_BLOCK block (id 8) is the top-level block for LLVM +bitcode files, and each bitcode file must contain exactly one. In +addition to records (described below) containing information +about the module, a MODULE_BLOCK block may contain the +following sub-blocks: +

+ + + +
+ + + + +
+ +

[VERSION, version#]

+ +

The VERSION record (code 1) contains a single value +indicating the format version. Only version 0 is supported at this +time.

+
+ + + + +
+

[TRIPLE, ...string...]

+ +

The TRIPLE record (code 2) contains a variable number of +values representing the bytes of the target triple +specification string.

+
+ + + + +
+

[DATALAYOUT, ...string...]

+ +

The DATALAYOUT record (code 3) contains a variable number of +values representing the bytes of the target datalayout +specification string.

+
+ + + + +
+

[ASM, ...string...]

+ +

The ASM record (code 4) contains a variable number of +values representing the bytes of module asm strings, with +individual assembly blocks separated by newline (ASCII 10) characters.

+
+ + + + +
+

[SECTIONNAME, ...string...]

+ +

The SECTIONNAME record (code 5) contains a variable number +of values representing the bytes of a single section name +string. There should be one SECTIONNAME record for each +section name referenced (e.g., in global variable or function +section attributes) within the module. These records can be +referenced by the 1-based index in the section fields of +GLOBALVAR or FUNCTION records.

+
+ + + + +
+

[DEPLIB, ...string...]

+ +

The DEPLIB record (code 6) contains a variable number of +values representing the bytes of a single dependent library name +string, one of the libraries mentioned in a deplibs +declaration. There should be one DEPLIB record for each +library name referenced.

+
+ + + + +
+

[GLOBALVAR, pointer type, isconst, initid, linkage, alignment, section, visibility, threadlocal]

+ +

The GLOBALVAR record (code 7) marks the declaration or +definition of a global variable. The operand fields are:

+ +
    +
  • pointer type: The type index of the pointer type used to point to +this global variable
  • + +
  • isconst: Non-zero if the variable is treated as constant within +the module, or zero if it is not
  • + +
  • initid: If non-zero, the value index of the initializer for this +variable, plus 1.
  • + +
  • linkage: An encoding of the linkage +type for this variable: +
      +
    • external: code 0
    • +
    • weak: code 1
    • +
    • appending: code 2
    • +
    • internal: code 3
    • +
    • linkonce: code 4
    • +
    • dllimport: code 5
    • +
    • dllexport: code 6
    • +
    • extern_weak: code 7
    • +
    • common: code 8
    • +
    • private: code 9
    • +
    • weak_odr: code 10
    • +
    • linkonce_odr: code 11
    • +
    • available_externally: code 12
    • +
    • linker_private: code 13
    • +
    +
  • + +
  • alignment: The logarithm base 2 of the variable's requested +alignment, plus 1
  • + +
  • section: If non-zero, the 1-based section index in the +table of MODULE_CODE_SECTIONNAME +entries.
  • + +
  • visibility: If present, an +encoding of the visibility of this variable: +
      +
    • default: code 0
    • +
    • hidden: code 1
    • +
    • protected: code 2
    • +
    +
  • + +
  • threadlocal: If present and non-zero, indicates that the variable +is thread_local
  • + +
+
+ + + + +
+ +

[FUNCTION, type, callingconv, isproto, linkage, paramattr, alignment, section, visibility, gc]

+ +

The FUNCTION record (code 8) marks the declaration or +definition of a function. The operand fields are:

+ +
    +
  • type: The type index of the function type describing this function
  • + +
  • callingconv: The calling convention number: +
      +
    • ccc: code 0
    • +
    • fastcc: code 8
    • +
    • coldcc: code 9
    • +
    • x86_stdcallcc: code 64
    • +
    • x86_fastcallcc: code 65
    • +
    • arm_apcscc: code 66
    • +
    • arm_aapcscc: code 67
    • +
    • arm_aapcs_vfpcc: code 68
    • +
    +
  • + +
  • isproto: Non-zero if this entry represents a declaration +rather than a definition
  • + +
  • linkage: An encoding of the linkage type +for this function
  • + +
  • paramattr: If nonzero, the 1-based parameter attribute index +into the table of PARAMATTR_CODE_ENTRY +entries.
  • + +
  • alignment: The logarithm base 2 of the function's requested +alignment, plus 1
  • + +
  • section: If non-zero, the 1-based section index in the +table of MODULE_CODE_SECTIONNAME +entries.
  • + +
  • visibility: An encoding of the visibility + of this function
  • + +
  • gc: If present and nonzero, the 1-based garbage collector +index in the table of +MODULE_CODE_GCNAME entries.
  • +
+
+ + + + +
+ +

[ALIAS, alias type, aliasee val#, linkage, visibility]

+ +

The ALIAS record (code 9) marks the definition of an +alias. The operand fields are

+ +
    +
  • alias type: The type index of the alias
  • + +
  • aliasee val#: The value index of the aliased value
  • + +
  • linkage: An encoding of the linkage type +for this alias
  • + +
  • visibility: If present, an encoding of the +visibility of the alias
  • + +
+
+ + + + +
+

[PURGEVALS, numvals]

+ +

The PURGEVALS record (code 10) resets the module-level +value list to the size given by the single operand value. Module-level +value list items are added by GLOBALVAR, FUNCTION, +and ALIAS records. After a PURGEVALS record is seen, +new value indices will start from the given numvals value.

+
+ + + + +
+

[GCNAME, ...string...]

+ +

The GCNAME record (code 11) contains a variable number of +values representing the bytes of a single garbage collector name +string. There should be one GCNAME record for each garbage +collector name referenced in function gc attributes within +the module. These records can be referenced by 1-based index in the gc +fields of FUNCTION records.

+
+ + + + +
+ +

The PARAMATTR_BLOCK block (id 9) ... +

+ +
+ + + + + +
+ +

[ENTRY, paramidx0, attr0, paramidx1, attr1...]

+ +

The ENTRY record (code 1) ... +

+
+ + + + +
+ +

The TYPE_BLOCK block (id 10) ... +

+ +
+ + + + + +
+ +

The CONSTANTS_BLOCK block (id 11) ... +

+ +
+ + + + + +
+ +

The FUNCTION_BLOCK block (id 12) ... +

+ +

In addition to the record types described below, a +FUNCTION_BLOCK block may contain the following sub-blocks: +

+ + + +
+ + + + + +
+ +

The TYPE_SYMTAB_BLOCK block (id 13) ... +

+ +
+ + + + + +
+ +

The VALUE_SYMTAB_BLOCK block (id 14) ... +

+ +
+ + + + + +
+ +

The METADATA_BLOCK block (id 15) ... +

+ +
+ + + + + +
+ +

The METADATA_ATTACHMENT block (id 16) ... +

+ +
+ + + +
+
Valid CSS +Valid HTML 4.01 + Chris Lattner
+The LLVM Compiler Infrastructure
+Last modified: $Date$ +
+ + diff --git a/libclamav/c++/llvm/docs/Bugpoint.html b/libclamav/c++/llvm/docs/Bugpoint.html new file mode 100644 index 000000000..bf75b5ba4 --- /dev/null +++ b/libclamav/c++/llvm/docs/Bugpoint.html @@ -0,0 +1,250 @@ + + + + LLVM bugpoint tool: design and usage + + + +
+ LLVM bugpoint tool: design and usage +
+ + + +
+

Written by Chris Lattner

+
+ + + + + +
+ +

bugpoint narrows down the source of problems in LLVM tools and +passes. It can be used to debug three types of failures: optimizer crashes, +miscompilations by optimizers, or bad native code generation (including problems +in the static and JIT compilers). It aims to reduce large test cases to small, +useful ones. For example, if opt crashes while optimizing a +file, it will identify the optimization (or combination of optimizations) that +causes the crash, and reduce the file down to a small example which triggers the +crash.

+ +

For detailed case scenarios, such as debugging opt, +llvm-ld, or one of the LLVM code generators, see How To Submit a Bug Report document.

+ +
+ + + + + +
+ +

bugpoint is designed to be a useful tool without requiring any +hooks into the LLVM infrastructure at all. It works with any and all LLVM +passes and code generators, and does not need to "know" how they work. Because +of this, it may appear to do stupid things or miss obvious +simplifications. bugpoint is also designed to trade off programmer +time for computer time in the compiler-debugging process; consequently, it may +take a long period of (unattended) time to reduce a test case, but we feel it +is still worth it. Note that bugpoint is generally very quick unless +debugging a miscompilation where each test of the program (which requires +executing it) takes a long time.

+ +
+ + + + +
+ +

bugpoint reads each .bc or .ll file specified on +the command line and links them together into a single module, called the test +program. If any LLVM passes are specified on the command line, it runs these +passes on the test program. If any of the passes crash, or if they produce +malformed output (which causes the verifier to abort), bugpoint starts +the crash debugger.

+ +

Otherwise, if the -output option was not specified, +bugpoint runs the test program with the C backend (which is assumed to +generate good code) to generate a reference output. Once bugpoint has +a reference output for the test program, it tries executing it with the +selected code generator. If the selected code generator crashes, +bugpoint starts the crash debugger on the +code generator. Otherwise, if the resulting output differs from the reference +output, it assumes the difference resulted from a code generator failure, and +starts the code generator debugger.

+ +

Finally, if the output of the selected code generator matches the reference +output, bugpoint runs the test program after all of the LLVM passes +have been applied to it. If its output differs from the reference output, it +assumes the difference resulted from a failure in one of the LLVM passes, and +enters the miscompilation debugger. +Otherwise, there is no problem bugpoint can debug.

+ +
+ + + + +
+ +

If an optimizer or code generator crashes, bugpoint will try as hard +as it can to reduce the list of passes (for optimizer crashes) and the size of +the test program. First, bugpoint figures out which combination of +optimizer passes triggers the bug. This is useful when debugging a problem +exposed by opt, for example, because it runs over 38 passes.

+ +

Next, bugpoint tries removing functions from the test program, to +reduce its size. Usually it is able to reduce a test program to a single +function, when debugging intraprocedural optimizations. Once the number of +functions has been reduced, it attempts to delete various edges in the control +flow graph, to reduce the size of the function as much as possible. Finally, +bugpoint deletes any individual LLVM instructions whose absence does +not eliminate the failure. At the end, bugpoint should tell you what +passes crash, give you a bitcode file, and give you instructions on how to +reproduce the failure with opt or llc.

+ +
+ + + + +
+ +

The code generator debugger attempts to narrow down the amount of code that +is being miscompiled by the selected code generator. To do this, it takes the +test program and partitions it into two pieces: one piece which it compiles +with the C backend (into a shared object), and one piece which it runs with +either the JIT or the static LLC compiler. It uses several techniques to +reduce the amount of code pushed through the LLVM code generator, to reduce the +potential scope of the problem. After it is finished, it emits two bitcode +files (called "test" [to be compiled with the code generator] and "safe" [to be +compiled with the C backend], respectively), and instructions for reproducing +the problem. The code generator debugger assumes that the C backend produces +good code.

+ +
+ + + + +
+ +

The miscompilation debugger works similarly to the code generator debugger. +It works by splitting the test program into two pieces, running the +optimizations specified on one piece, linking the two pieces back together, and +then executing the result. It attempts to narrow down the list of passes to +the one (or few) which are causing the miscompilation, then reduce the portion +of the test program which is being miscompiled. The miscompilation debugger +assumes that the selected code generator is working properly.

+ +
+ + + + + +
+ +bugpoint can be a remarkably useful tool, but it sometimes works in +non-obvious ways. Here are some hints and tips:

+ +

    +
  1. In the code generator and miscompilation debuggers, bugpoint only + works with programs that have deterministic output. Thus, if the program + outputs argv[0], the date, time, or any other "random" data, + bugpoint may misinterpret differences in these data, when output, + as the result of a miscompilation. Programs should be temporarily modified + to disable outputs that are likely to vary from run to run. + +
  2. In the code generator and miscompilation debuggers, debugging will go + faster if you manually modify the program or its inputs to reduce the + runtime, but still exhibit the problem. + +
  3. bugpoint is extremely useful when working on a new optimization: + it helps track down regressions quickly. To avoid having to relink + bugpoint every time you change your optimization however, have + bugpoint dynamically load your optimization with the + -load option. + +
  4. bugpoint can generate a lot of output and run for a long period + of time. It is often useful to capture the output of the program to file. + For example, in the C shell, you can run:

    + +
    +

    bugpoint ... |& tee bugpoint.log

    +
    + +

    to get a copy of bugpoint's output in the file + bugpoint.log, as well as on your terminal.

    + +
  5. bugpoint cannot debug problems with the LLVM linker. If + bugpoint crashes before you see its "All input ok" message, + you might try llvm-link -v on the same set of input files. If + that also crashes, you may be experiencing a linker bug. + +
  6. bugpoint is useful for proactively finding bugs in LLVM. + Invoking bugpoint with the -find-bugs option will cause + the list of specified optimizations to be randomized and applied to the + program. This process will repeat until a bug is found or the user + kills bugpoint. + +
  7. bugpoint does not understand the -O option + that is used to specify optimization level to opt. You + can use e.g.

    + +
    +

    opt -O2 -debug-pass=Arguments foo.bc -disable-output

    +
    + +

    to get a list of passes that are used with -O2 and + then pass this list to bugpoint.

    + +
+ +
+ + + +
+
+ Valid CSS + Valid HTML 4.01 + + Chris Lattner
+ LLVM Compiler Infrastructure
+ Last modified: $Date$ +
+ + + diff --git a/libclamav/c++/llvm/docs/CFEBuildInstrs.html b/libclamav/c++/llvm/docs/CFEBuildInstrs.html new file mode 100644 index 000000000..ed2f295b7 --- /dev/null +++ b/libclamav/c++/llvm/docs/CFEBuildInstrs.html @@ -0,0 +1,29 @@ + + + + + + Building the LLVM C/C++ Front-End + + + +
+This page has moved here. +
+ + + +
+
+ Valid CSS + Valid HTML 4.01 + + LLVM Compiler Infrastructure
+ Last modified: $Date: 2008-02-13 17:46:10 +0100 (Wed, 13 Feb 2008) $ +
+ + + diff --git a/libclamav/c++/llvm/docs/CMake.html b/libclamav/c++/llvm/docs/CMake.html new file mode 100644 index 000000000..2b7fda344 --- /dev/null +++ b/libclamav/c++/llvm/docs/CMake.html @@ -0,0 +1,373 @@ + + + + Building LLVM with CMake + + + +
+ Building LLVM with CMake +
+ + + +
+

Written by Oscar Fuentes

+
+ + + + + +
+ +

CMake is a cross-platform + build-generator tool. CMake does not build the project, it generates + the files needed by your build tool (GNU make, Visual Studio, etc) for + building LLVM.

+ +

If you are really anxious about getting a functional LLVM build, + go to the Quick start section. If you + are a CMake novice, start on Basic CMake + usage and then go back to the Quick + start once you know what you are + doing. The Options and variables section + is a reference for customizing your build. If you already have + experience with CMake, this is the recommended starting point. +

+ + + + + +
+ +

We use here the command-line, non-interactive CMake interface

+ +
    + +
  1. Download + and install CMake. Version 2.6.2 is the minimum required.

    + +
  2. Open a shell. Your development tools must be reachable from this + shell through the PATH environment variable.

    + +
  3. Create a directory for containing the build. It is not + supported to build LLVM on the source directory. cd to this + directory:

    +
    +

    mkdir mybuilddir

    +

    cd mybuilddir

    +
    + +
  4. Execute this command on the shell + replacing path/to/llvm/source/root with the path to the + root of your LLVM source tree:

    +
    +

    cmake path/to/llvm/source/root

    +
    + +

    CMake will detect your development environment, perform a + series of test and generate the files required for building + LLVM. CMake will use default values for all build + parameters. See the Options and variables + section for fine-tuning your build

    + +

    This can fail if CMake can't detect your toolset, or if it + thinks that the environment is not sane enough. On this case + make sure that the toolset that you intend to use is the only + one reachable from the shell and that the shell itself is the + correct one for you development environment. CMake will refuse + to build MinGW makefiles if you have a POSIX shell reachable + through the PATH environment variable, for instance. You can + force CMake to use a given build tool, see + the Usage section.

    + +
+ +
+ + + + + +
+ +

This section explains basic aspects of CMake, mostly for + explaining those options which you may need on your day-to-day + usage.

+ +

CMake comes with extensive documentation in the form of html + files and on the cmake executable itself. Execute cmake + --help for further help options.

+ +

CMake requires to know for which build tool it shall generate + files (GNU make, Visual Studio, Xcode, etc). If not specified on + the command line, it tries to guess it based on you + environment. Once identified the build tool, CMake uses the + corresponding Generator for creating files for your build + tool. You can explicitly specify the generator with the command + line option -G "Name of the generator". For knowing the + available generators on your platform, execute

+ +
+

cmake --help

+
+ +

This will list the generator's names at the end of the help + text. Generator's names are case-sensitive. Example:

+ +
+

cmake -G "Visual Studio 8 2005" path/to/llvm/source/root

+
+ +

For a given development platform there can be more than one + adequate generator. If you use Visual Studio "NMake Makefiles" + is a generator you can use for building with NMake. By default, + CMake chooses the more specific generator supported by your + development environment. If you want an alternative generator, + you must tell this to CMake with the -G option.

+ +

TODO: explain variables and cache. Move explanation here from + #options section.

+ +
+ + + + + +
+ +

Variables customize how the build will be generated. Options are + boolean variables, with possible values ON/OFF. Options and + variables are defined on the CMake command line like this:

+ +
+

cmake -DVARIABLE=value path/to/llvm/source

+
+ +

You can set a variable after the initial CMake invocation for + changing its value. You can also undefine a variable:

+ +
+

cmake -UVARIABLE path/to/llvm/source

+
+ +

Variables are stored on the CMake cache. This is a file + named CMakeCache.txt on the root of the build + directory. Do not hand-edit it.

+ +

Variables are listed here appending its type after a colon. It is + correct to write the variable and the type on the CMake command + line:

+ +
+

cmake -DVARIABLE:TYPE=value path/to/llvm/source

+
+ +
+ + + + +
+ +

Here are listed some of the CMake variables that are used often, + along with a brief explanation and LLVM-specific notes. For full + documentation, check the CMake docs or execute cmake + --help-variable VARIABLE_NAME.

+ +
+
CMAKE_BUILD_TYPE:STRING
+ +
Sets the build type for make based generators. Possible + values are Release, Debug, RelWithDebInfo and MinSizeRel. On + systems like Visual Studio the user sets the build type with the IDE + settings.
+ +
CMAKE_INSTALL_PREFIX:PATH
+
Path where LLVM will be installed if "make install" is invoked + or the "INSTALL" target is built.
+ +
LLVM_LIBDIR_SUFFIX:STRING
+
Extra suffix to append to the directory where libraries are to + be installed. On a 64-bit architecture, one could use + -DLLVM_LIBDIR_SUFFIX=64 to install libraries to /usr/lib64.
+ +
CMAKE_C_FLAGS:STRING
+
Extra flags to use when compiling C source files.
+ +
CMAKE_CXX_FLAGS:STRING
+
Extra flags to use when compiling C++ source files.
+ +
BUILD_SHARED_LIBS:BOOL
+
Flag indicating is shared libraries will be built. Its default + value is OFF. Shared libraries are not supported on Windows and + not recommended in the other OSes.
+
+ +
+ + + + +
+ +
+
LLVM_TARGETS_TO_BUILD:STRING
+
Semicolon-separated list of targets to build, or all for + building all targets. Case-sensitive. For Visual C++ defaults + to X86. On the other cases defaults to all. Example: + -DLLVM_TARGETS_TO_BUILD="X86;PowerPC;Alpha".
+ +
LLVM_BUILD_TOOLS:BOOL
+
Build LLVM tools. Defaults to ON. Targets for building each tool + are generated in any case. You can build an tool separately by + invoking its target. For example, you can build llvm-as + with a makefile-based system executing make llvm-as on the + root of your build directory.
+ +
LLVM_BUILD_EXAMPLES:BOOL
+
Build LLVM examples. Defaults to OFF. Targets for building each + example are generated in any case. See documentation + for LLVM_BUILD_TOOLS above for more details.
+ +
LLVM_ENABLE_THREADS:BOOL
+
Build with threads support, if available. Defaults to ON.
+ +
LLVM_ENABLE_ASSERTIONS:BOOL
+
Enables code assertions. Defaults to OFF if and only if + CMAKE_BUILD_TYPE is Release.
+ +
LLVM_ENABLE_PIC:BOOL
+
Add the -fPIC flag for the compiler command-line, if the + compiler supports this flag. Some systems, like Windows, do not + need this flag. Defaults to ON.
+ +
LLVM_BUILD_32_BITS:BOOL
+
Build 32-bits executables and libraries on 64-bits systems. This + option is available only on some 64-bits unix systems. Defaults to + OFF.
+ +
LLVM_TARGET_ARCH:STRING
+
LLVM target to use for native code generation. This is required + for JIT generation. It defaults to "host", meaning that it shall + pick the architecture of the machine where LLVM is being built. If + you are cross-compiling, set it to the target architecture + name.
+ +
LLVM_TABLEGEN:STRING
+
Full path to a native TableGen executable (usually + named tblgen). This is intented for cross-compiling: if the + user sets this variable, no native TableGen will be created.
+
+ +
+ + + + + +
+ +

LLVM testing is not supported on Visual Studio.

+ +

TODO

+ +
+ + + + + +
+ +

See this + wiki page for generic instructions on how to cross-compile + with CMake. It goes into detailed explanations and may seem + daunting, but it is not. On the wiki page there are several + examples including toolchain files. Go directly to + this + section for a quick solution.

+ +

Also see the LLVM-specific variables + section for variables used when cross-compiling.

+ +
+ + + + + +
+ +

TODO

+ +
+ + + + + + + +
+ +

Notes for specific compilers and/or platforms.

+ +
+ + + +
+
+ Valid CSS + Valid HTML 4.01 + + Oscar Fuentes
+ LLVM Compiler Infrastructure
+ Last modified: $Date: 2008-12-31 03:59:36 +0100 (Wed, 31 Dec 2008) $ +
+ + + diff --git a/libclamav/c++/llvm/docs/CodeGenerator.html b/libclamav/c++/llvm/docs/CodeGenerator.html new file mode 100644 index 000000000..cc3a541e9 --- /dev/null +++ b/libclamav/c++/llvm/docs/CodeGenerator.html @@ -0,0 +1,2128 @@ + + + + + The LLVM Target-Independent Code Generator + + + + +
+ The LLVM Target-Independent Code Generator +
+ +
    +
  1. Introduction + +
  2. +
  3. Target description classes + +
  4. +
  5. Machine code description classes + +
  6. +
  7. Target-independent code generation algorithms + +
  8. +
  9. Target-specific Implementation Notes +
  10. + +
+ + + +
+

Warning: This is a work in progress.

+
+ + + + + +
+ +

The LLVM target-independent code generator is a framework that provides a + suite of reusable components for translating the LLVM internal representation + to the machine code for a specified target—either in assembly form + (suitable for a static compiler) or in binary machine code format (usable for + a JIT compiler). The LLVM target-independent code generator consists of five + main components:

+ +
    +
  1. Abstract target description interfaces which + capture important properties about various aspects of the machine, + independently of how they will be used. These interfaces are defined in + include/llvm/Target/.
  2. + +
  3. Classes used to represent the machine code + being generated for a target. These classes are intended to be abstract + enough to represent the machine code for any target machine. These + classes are defined in include/llvm/CodeGen/.
  4. + +
  5. Target-independent algorithms used to implement + various phases of native code generation (register allocation, scheduling, + stack frame representation, etc). This code lives + in lib/CodeGen/.
  6. + +
  7. Implementations of the abstract target description + interfaces for particular targets. These machine descriptions make + use of the components provided by LLVM, and can optionally provide custom + target-specific passes, to build complete code generators for a specific + target. Target descriptions live in lib/Target/.
  8. + +
  9. The target-independent JIT components. The LLVM JIT is + completely target independent (it uses the TargetJITInfo + structure to interface for target-specific issues. The code for the + target-independent JIT lives in lib/ExecutionEngine/JIT.
  10. +
+ +

Depending on which part of the code generator you are interested in working + on, different pieces of this will be useful to you. In any case, you should + be familiar with the target description + and machine code representation classes. If you + want to add a backend for a new target, you will need + to implement the target description classes for + your new target and understand the LLVM code + representation. If you are interested in implementing a + new code generation algorithm, it should only + depend on the target-description and machine code representation classes, + ensuring that it is portable.

+ +
+ + + + +
+ +

The two pieces of the LLVM code generator are the high-level interface to the + code generator and the set of reusable components that can be used to build + target-specific backends. The two most important interfaces + (TargetMachine + and TargetData) are the only ones that are + required to be defined for a backend to fit into the LLVM system, but the + others must be defined if the reusable code generator components are going to + be used.

+ +

This design has two important implications. The first is that LLVM can + support completely non-traditional code generation targets. For example, the + C backend does not require register allocation, instruction selection, or any + of the other standard components provided by the system. As such, it only + implements these two interfaces, and does its own thing. Another example of + a code generator like this is a (purely hypothetical) backend that converts + LLVM to the GCC RTL form and uses GCC to emit machine code for a target.

+ +

This design also implies that it is possible to design and implement + radically different code generators in the LLVM system that do not make use + of any of the built-in components. Doing so is not recommended at all, but + could be required for radically different targets that do not fit into the + LLVM machine description model: FPGAs for example.

+ +
+ + + + +
+ +

The LLVM target-independent code generator is designed to support efficient + and quality code generation for standard register-based microprocessors. + Code generation in this model is divided into the following stages:

+ +
    +
  1. Instruction Selection — This phase + determines an efficient way to express the input LLVM code in the target + instruction set. This stage produces the initial code for the program in + the target instruction set, then makes use of virtual registers in SSA + form and physical registers that represent any required register + assignments due to target constraints or calling conventions. This step + turns the LLVM code into a DAG of target instructions.
  2. + +
  3. Scheduling and Formation — + This phase takes the DAG of target instructions produced by the + instruction selection phase, determines an ordering of the instructions, + then emits the instructions + as MachineInstrs with that ordering. + Note that we describe this in the instruction + selection section because it operates on + a SelectionDAG.
  4. + +
  5. SSA-based Machine Code Optimizations — + This optional stage consists of a series of machine-code optimizations + that operate on the SSA-form produced by the instruction selector. + Optimizations like modulo-scheduling or peephole optimization work + here.
  6. + +
  7. Register Allocation — The target code + is transformed from an infinite virtual register file in SSA form to the + concrete register file used by the target. This phase introduces spill + code and eliminates all virtual register references from the program.
  8. + +
  9. Prolog/Epilog Code Insertion — Once + the machine code has been generated for the function and the amount of + stack space required is known (used for LLVM alloca's and spill slots), + the prolog and epilog code for the function can be inserted and "abstract + stack location references" can be eliminated. This stage is responsible + for implementing optimizations like frame-pointer elimination and stack + packing.
  10. + +
  11. Late Machine Code Optimizations — + Optimizations that operate on "final" machine code can go here, such as + spill code scheduling and peephole optimizations.
  12. + +
  13. Code Emission — The final stage + actually puts out the code for the current function, either in the target + assembler format or in machine code.
  14. +
+ +

The code generator is based on the assumption that the instruction selector + will use an optimal pattern matching selector to create high-quality + sequences of native instructions. Alternative code generator designs based + on pattern expansion and aggressive iterative peephole optimization are much + slower. This design permits efficient compilation (important for JIT + environments) and aggressive optimization (used when generating code offline) + by allowing components of varying levels of sophistication to be used for any + step of compilation.

+ +

In addition to these stages, target implementations can insert arbitrary + target-specific passes into the flow. For example, the X86 target uses a + special pass to handle the 80x87 floating point stack architecture. Other + targets with unusual requirements can be supported with custom passes as + needed.

+ +
+ + + + +
+ +

The target description classes require a detailed description of the target + architecture. These target descriptions often have a large amount of common + information (e.g., an add instruction is almost identical to a + sub instruction). In order to allow the maximum amount of + commonality to be factored out, the LLVM code generator uses + the TableGen tool to describe big + chunks of the target machine, which allows the use of domain-specific and + target-specific abstractions to reduce the amount of repetition.

+ +

As LLVM continues to be developed and refined, we plan to move more and more + of the target description to the .td form. Doing so gives us a + number of advantages. The most important is that it makes it easier to port + LLVM because it reduces the amount of C++ code that has to be written, and + the surface area of the code generator that needs to be understood before + someone can get something working. Second, it makes it easier to change + things. In particular, if tables and other things are all emitted + by tblgen, we only need a change in one place (tblgen) to + update all of the targets to a new interface.

+ +
+ + + + + +
+ +

The LLVM target description classes (located in the + include/llvm/Target directory) provide an abstract description of + the target machine independent of any particular client. These classes are + designed to capture the abstract properties of the target (such as the + instructions and registers it has), and do not incorporate any particular + pieces of code generation algorithms.

+ +

All of the target description classes (except the + TargetData class) are designed to be + subclassed by the concrete target implementation, and have virtual methods + implemented. To get to these implementations, the + TargetMachine class provides accessors + that should be implemented by the target.

+ +
+ + + + +
+ +

The TargetMachine class provides virtual methods that are used to + access the target-specific implementations of the various target description + classes via the get*Info methods (getInstrInfo, + getRegisterInfo, getFrameInfo, etc.). This class is + designed to be specialized by a concrete target implementation + (e.g., X86TargetMachine) which implements the various virtual + methods. The only required target description class is + the TargetData class, but if the code + generator components are to be used, the other interfaces should be + implemented as well.

+ +
+ + + + +
+ +

The TargetData class is the only required target description class, + and it is the only class that is not extensible (you cannot derived a new + class from it). TargetData specifies information about how the + target lays out memory for structures, the alignment requirements for various + data types, the size of pointers in the target, and whether the target is + little-endian or big-endian.

+ +
+ + + + +
+ +

The TargetLowering class is used by SelectionDAG based instruction + selectors primarily to describe how LLVM code should be lowered to + SelectionDAG operations. Among other things, this class indicates:

+ +
    +
  • an initial register class to use for various ValueTypes,
  • + +
  • which operations are natively supported by the target machine,
  • + +
  • the return type of setcc operations,
  • + +
  • the type to use for shift amounts, and
  • + +
  • various high-level characteristics, like whether it is profitable to turn + division by a constant into a multiplication sequence
  • +
+ +
+ + + + +
+ +

The TargetRegisterInfo class is used to describe the register file + of the target and any interactions between the registers.

+ +

Registers in the code generator are represented in the code generator by + unsigned integers. Physical registers (those that actually exist in the + target description) are unique small numbers, and virtual registers are + generally large. Note that register #0 is reserved as a flag value.

+ +

Each register in the processor description has an associated + TargetRegisterDesc entry, which provides a textual name for the + register (used for assembly output and debugging dumps) and a set of aliases + (used to indicate whether one register overlaps with another).

+ +

In addition to the per-register description, the TargetRegisterInfo + class exposes a set of processor specific register classes (instances of the + TargetRegisterClass class). Each register class contains sets of + registers that have the same properties (for example, they are all 32-bit + integer registers). Each SSA virtual register created by the instruction + selector has an associated register class. When the register allocator runs, + it replaces virtual registers with a physical register in the set.

+ +

The target-specific implementations of these classes is auto-generated from + a TableGen description of the + register file.

+ +
+ + + + +
+ +

The TargetInstrInfo class is used to describe the machine + instructions supported by the target. It is essentially an array of + TargetInstrDescriptor objects, each of which describes one + instruction the target supports. Descriptors define things like the mnemonic + for the opcode, the number of operands, the list of implicit register uses + and defs, whether the instruction has certain target-independent properties + (accesses memory, is commutable, etc), and holds any target-specific + flags.

+ +
+ + + + +
+ +

The TargetFrameInfo class is used to provide information about the + stack frame layout of the target. It holds the direction of stack growth, the + known stack alignment on entry to each function, and the offset to the local + area. The offset to the local area is the offset from the stack pointer on + function entry to the first location where function data (local variables, + spill locations) can be stored.

+ +
+ + + + +
+ +

The TargetSubtarget class is used to provide information about the + specific chip set being targeted. A sub-target informs code generation of + which instructions are supported, instruction latencies and instruction + execution itinerary; i.e., which processing units are used, in what order, + and for how long.

+ +
+ + + + + +
+ +

The TargetJITInfo class exposes an abstract interface used by the + Just-In-Time code generator to perform target-specific activities, such as + emitting stubs. If a TargetMachine supports JIT code generation, it + should provide one of these objects through the getJITInfo + method.

+ +
+ + + + + +
+ +

At the high-level, LLVM code is translated to a machine specific + representation formed out of + MachineFunction, + MachineBasicBlock, + and MachineInstr instances (defined + in include/llvm/CodeGen). This representation is completely target + agnostic, representing instructions in their most abstract form: an opcode + and a series of operands. This representation is designed to support both an + SSA representation for machine code, as well as a register allocated, non-SSA + form.

+ +
+ + + + +
+ +

Target machine instructions are represented as instances of the + MachineInstr class. This class is an extremely abstract way of + representing machine instructions. In particular, it only keeps track of an + opcode number and a set of operands.

+ +

The opcode number is a simple unsigned integer that only has meaning to a + specific backend. All of the instructions for a target should be defined in + the *InstrInfo.td file for the target. The opcode enum values are + auto-generated from this description. The MachineInstr class does + not have any information about how to interpret the instruction (i.e., what + the semantics of the instruction are); for that you must refer to the + TargetInstrInfo class.

+ +

The operands of a machine instruction can be of several different types: a + register reference, a constant integer, a basic block reference, etc. In + addition, a machine operand should be marked as a def or a use of the value + (though only registers are allowed to be defs).

+ +

By convention, the LLVM code generator orders instruction operands so that + all register definitions come before the register uses, even on architectures + that are normally printed in other orders. For example, the SPARC add + instruction: "add %i1, %i2, %i3" adds the "%i1", and "%i2" registers + and stores the result into the "%i3" register. In the LLVM code generator, + the operands should be stored as "%i3, %i1, %i2": with the + destination first.

+ +

Keeping destination (definition) operands at the beginning of the operand + list has several advantages. In particular, the debugging printer will print + the instruction like this:

+ +
+
+%r3 = add %i1, %i2
+
+
+ +

Also if the first operand is a def, it is easier to create + instructions whose only def is the first operand.

+ +
+ + + + +
+ +

Machine instructions are created by using the BuildMI functions, + located in the include/llvm/CodeGen/MachineInstrBuilder.h file. The + BuildMI functions make it easy to build arbitrary machine + instructions. Usage of the BuildMI functions look like this:

+ +
+
+// Create a 'DestReg = mov 42' (rendered in X86 assembly as 'mov DestReg, 42')
+// instruction.  The '1' specifies how many operands will be added.
+MachineInstr *MI = BuildMI(X86::MOV32ri, 1, DestReg).addImm(42);
+
+// Create the same instr, but insert it at the end of a basic block.
+MachineBasicBlock &MBB = ...
+BuildMI(MBB, X86::MOV32ri, 1, DestReg).addImm(42);
+
+// Create the same instr, but insert it before a specified iterator point.
+MachineBasicBlock::iterator MBBI = ...
+BuildMI(MBB, MBBI, X86::MOV32ri, 1, DestReg).addImm(42);
+
+// Create a 'cmp Reg, 0' instruction, no destination reg.
+MI = BuildMI(X86::CMP32ri, 2).addReg(Reg).addImm(0);
+// Create an 'sahf' instruction which takes no operands and stores nothing.
+MI = BuildMI(X86::SAHF, 0);
+
+// Create a self looping branch instruction.
+BuildMI(MBB, X86::JNE, 1).addMBB(&MBB);
+
+
+ +

The key thing to remember with the BuildMI functions is that you + have to specify the number of operands that the machine instruction will + take. This allows for efficient memory allocation. You also need to specify + if operands default to be uses of values, not definitions. If you need to + add a definition operand (other than the optional destination register), you + must explicitly mark it as such:

+ +
+
+MI.addReg(Reg, RegState::Define);
+
+
+ +
+ + + + +
+ +

One important issue that the code generator needs to be aware of is the + presence of fixed registers. In particular, there are often places in the + instruction stream where the register allocator must arrange for a + particular value to be in a particular register. This can occur due to + limitations of the instruction set (e.g., the X86 can only do a 32-bit divide + with the EAX/EDX registers), or external factors like + calling conventions. In any case, the instruction selector should emit code + that copies a virtual register into or out of a physical register when + needed.

+ +

For example, consider this simple LLVM example:

+ +
+
+define i32 @test(i32 %X, i32 %Y) {
+  %Z = udiv i32 %X, %Y
+  ret i32 %Z
+}
+
+
+ +

The X86 instruction selector produces this machine code for the div + and ret (use "llc X.bc -march=x86 -print-machineinstrs" to + get this):

+ +
+
+;; Start of div
+%EAX = mov %reg1024           ;; Copy X (in reg1024) into EAX
+%reg1027 = sar %reg1024, 31
+%EDX = mov %reg1027           ;; Sign extend X into EDX
+idiv %reg1025                 ;; Divide by Y (in reg1025)
+%reg1026 = mov %EAX           ;; Read the result (Z) out of EAX
+
+;; Start of ret
+%EAX = mov %reg1026           ;; 32-bit return value goes in EAX
+ret
+
+
+ +

By the end of code generation, the register allocator has coalesced the + registers and deleted the resultant identity moves producing the following + code:

+ +
+
+;; X is in EAX, Y is in ECX
+mov %EAX, %EDX
+sar %EDX, 31
+idiv %ECX
+ret 
+
+
+ +

This approach is extremely general (if it can handle the X86 architecture, it + can handle anything!) and allows all of the target specific knowledge about + the instruction stream to be isolated in the instruction selector. Note that + physical registers should have a short lifetime for good code generation, and + all physical registers are assumed dead on entry to and exit from basic + blocks (before register allocation). Thus, if you need a value to be live + across basic block boundaries, it must live in a virtual + register.

+ +
+ + + + +
+ +

MachineInstr's are initially selected in SSA-form, and are + maintained in SSA-form until register allocation happens. For the most part, + this is trivially simple since LLVM is already in SSA form; LLVM PHI nodes + become machine code PHI nodes, and virtual registers are only allowed to have + a single definition.

+ +

After register allocation, machine code is no longer in SSA-form because + there are no virtual registers left in the code.

+ +
+ + + + +
+ +

The MachineBasicBlock class contains a list of machine instructions + (MachineInstr instances). It roughly + corresponds to the LLVM code input to the instruction selector, but there can + be a one-to-many mapping (i.e. one LLVM basic block can map to multiple + machine basic blocks). The MachineBasicBlock class has a + "getBasicBlock" method, which returns the LLVM basic block that it + comes from.

+ +
+ + + + +
+ +

The MachineFunction class contains a list of machine basic blocks + (MachineBasicBlock instances). It + corresponds one-to-one with the LLVM function input to the instruction + selector. In addition to a list of basic blocks, + the MachineFunction contains a a MachineConstantPool, + a MachineFrameInfo, a MachineFunctionInfo, and a + MachineRegisterInfo. See + include/llvm/CodeGen/MachineFunction.h for more information.

+ +
+ + + + + +
+ +

This section documents the phases described in the + high-level design of the code generator. + It explains how they work and some of the rationale behind their design.

+ +
+ + + + +
+ +

Instruction Selection is the process of translating LLVM code presented to + the code generator into target-specific machine instructions. There are + several well-known ways to do this in the literature. LLVM uses a + SelectionDAG based instruction selector.

+ +

Portions of the DAG instruction selector are generated from the target + description (*.td) files. Our goal is for the entire instruction + selector to be generated from these .td files, though currently + there are still things that require custom C++ code.

+ +
+ + + + +
+ +

The SelectionDAG provides an abstraction for code representation in a way + that is amenable to instruction selection using automatic techniques + (e.g. dynamic-programming based optimal pattern matching selectors). It is + also well-suited to other phases of code generation; in particular, + instruction scheduling (SelectionDAG's are very close to scheduling DAGs + post-selection). Additionally, the SelectionDAG provides a host + representation where a large variety of very-low-level (but + target-independent) optimizations may be + performed; ones which require extensive information about the instructions + efficiently supported by the target.

+ +

The SelectionDAG is a Directed-Acyclic-Graph whose nodes are instances of the + SDNode class. The primary payload of the SDNode is its + operation code (Opcode) that indicates what operation the node performs and + the operands to the operation. The various operation node types are + described at the top of the include/llvm/CodeGen/SelectionDAGNodes.h + file.

+ +

Although most operations define a single value, each node in the graph may + define multiple values. For example, a combined div/rem operation will + define both the dividend and the remainder. Many other situations require + multiple values as well. Each node also has some number of operands, which + are edges to the node defining the used value. Because nodes may define + multiple values, edges are represented by instances of the SDValue + class, which is a <SDNode, unsigned> pair, indicating the node + and result value being used, respectively. Each value produced by + an SDNode has an associated MVT (Machine Value Type) + indicating what the type of the value is.

+ +

SelectionDAGs contain two different kinds of values: those that represent + data flow and those that represent control flow dependencies. Data values + are simple edges with an integer or floating point value type. Control edges + are represented as "chain" edges which are of type MVT::Other. + These edges provide an ordering between nodes that have side effects (such as + loads, stores, calls, returns, etc). All nodes that have side effects should + take a token chain as input and produce a new one as output. By convention, + token chain inputs are always operand #0, and chain results are always the + last value produced by an operation.

+ +

A SelectionDAG has designated "Entry" and "Root" nodes. The Entry node is + always a marker node with an Opcode of ISD::EntryToken. The Root + node is the final side-effecting node in the token chain. For example, in a + single basic block function it would be the return node.

+ +

One important concept for SelectionDAGs is the notion of a "legal" vs. + "illegal" DAG. A legal DAG for a target is one that only uses supported + operations and supported types. On a 32-bit PowerPC, for example, a DAG with + a value of type i1, i8, i16, or i64 would be illegal, as would a DAG that + uses a SREM or UREM operation. The + legalize types and + legalize operations phases are + responsible for turning an illegal DAG into a legal DAG.

+ +
+ + + + +
+ +

SelectionDAG-based instruction selection consists of the following steps:

+ +
    +
  1. Build initial DAG — This stage + performs a simple translation from the input LLVM code to an illegal + SelectionDAG.
  2. + +
  3. Optimize SelectionDAG — This + stage performs simple optimizations on the SelectionDAG to simplify it, + and recognize meta instructions (like rotates + and div/rem pairs) for targets that support these meta + operations. This makes the resultant code more efficient and + the select instructions from DAG phase + (below) simpler.
  4. + +
  5. Legalize SelectionDAG Types + — This stage transforms SelectionDAG nodes to eliminate any types + that are unsupported on the target.
  6. + +
  7. Optimize SelectionDAG — The + SelectionDAG optimizer is run to clean up redundancies exposed by type + legalization.
  8. + +
  9. Legalize SelectionDAG Types — + This stage transforms SelectionDAG nodes to eliminate any types that are + unsupported on the target.
  10. + +
  11. Optimize SelectionDAG — The + SelectionDAG optimizer is run to eliminate inefficiencies introduced by + operation legalization.
  12. + +
  13. Select instructions from DAG — + Finally, the target instruction selector matches the DAG operations to + target instructions. This process translates the target-independent input + DAG into another DAG of target instructions.
  14. + +
  15. SelectionDAG Scheduling and Formation + — The last phase assigns a linear order to the instructions in the + target-instruction DAG and emits them into the MachineFunction being + compiled. This step uses traditional prepass scheduling techniques.
  16. +
+ +

After all of these steps are complete, the SelectionDAG is destroyed and the + rest of the code generation passes are run.

+ +

One great way to visualize what is going on here is to take advantage of a + few LLC command line options. The following options pop up a window + displaying the SelectionDAG at specific times (if you only get errors printed + to the console while using this, you probably + need to configure your system + to add support for it).

+ +
    +
  • -view-dag-combine1-dags displays the DAG after being built, + before the first optimization pass.
  • + +
  • -view-legalize-dags displays the DAG before Legalization.
  • + +
  • -view-dag-combine2-dags displays the DAG before the second + optimization pass.
  • + +
  • -view-isel-dags displays the DAG before the Select phase.
  • + +
  • -view-sched-dags displays the DAG before Scheduling.
  • +
+ +

The -view-sunit-dags displays the Scheduler's dependency graph. + This graph is based on the final SelectionDAG, with nodes that must be + scheduled together bundled into a single scheduling-unit node, and with + immediate operands and other nodes that aren't relevant for scheduling + omitted.

+ +
+ + + + +
+ +

The initial SelectionDAG is naïvely peephole expanded from the LLVM + input by the SelectionDAGLowering class in the + lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp file. The intent of + this pass is to expose as much low-level, target-specific details to the + SelectionDAG as possible. This pass is mostly hard-coded (e.g. an + LLVM add turns into an SDNode add while a + getelementptr is expanded into the obvious arithmetic). This pass + requires target-specific hooks to lower calls, returns, varargs, etc. For + these features, the TargetLowering + interface is used.

+ +
+ + + + +
+ +

The Legalize phase is in charge of converting a DAG to only use the types + that are natively supported by the target.

+ +

There are two main ways of converting values of unsupported scalar types to + values of supported types: converting small types to larger types + ("promoting"), and breaking up large integer types into smaller ones + ("expanding"). For example, a target might require that all f32 values are + promoted to f64 and that all i1/i8/i16 values are promoted to i32. The same + target might require that all i64 values be expanded into pairs of i32 + values. These changes can insert sign and zero extensions as needed to make + sure that the final code has the same behavior as the input.

+ +

There are two main ways of converting values of unsupported vector types to + value of supported types: splitting vector types, multiple times if + necessary, until a legal type is found, and extending vector types by adding + elements to the end to round them out to legal types ("widening"). If a + vector gets split all the way down to single-element parts with no supported + vector type being found, the elements are converted to scalars + ("scalarizing").

+ +

A target implementation tells the legalizer which types are supported (and + which register class to use for them) by calling the + addRegisterClass method in its TargetLowering constructor.

+ +
+ + + + +
+ +

The Legalize phase is in charge of converting a DAG to only use the + operations that are natively supported by the target.

+ +

Targets often have weird constraints, such as not supporting every operation + on every supported datatype (e.g. X86 does not support byte conditional moves + and PowerPC does not support sign-extending loads from a 16-bit memory + location). Legalize takes care of this by open-coding another sequence of + operations to emulate the operation ("expansion"), by promoting one type to a + larger type that supports the operation ("promotion"), or by using a + target-specific hook to implement the legalization ("custom").

+ +

A target implementation tells the legalizer which operations are not + supported (and which of the above three actions to take) by calling the + setOperationAction method in its TargetLowering + constructor.

+ +

Prior to the existence of the Legalize passes, we required that every target + selector supported and handled every + operator and type even if they are not natively supported. The introduction + of the Legalize phases allows all of the canonicalization patterns to be + shared across targets, and makes it very easy to optimize the canonicalized + code because it is still in the form of a DAG.

+ +
+ + + + +
+ +

The SelectionDAG optimization phase is run multiple times for code + generation, immediately after the DAG is built and once after each + legalization. The first run of the pass allows the initial code to be + cleaned up (e.g. performing optimizations that depend on knowing that the + operators have restricted type inputs). Subsequent runs of the pass clean up + the messy code generated by the Legalize passes, which allows Legalize to be + very simple (it can focus on making code legal instead of focusing on + generating good and legal code).

+ +

One important class of optimizations performed is optimizing inserted sign + and zero extension instructions. We currently use ad-hoc techniques, but + could move to more rigorous techniques in the future. Here are some good + papers on the subject:

+ +

"Widening + integer arithmetic"
+ Kevin Redwine and Norman Ramsey
+ International Conference on Compiler Construction (CC) 2004

+ +

"Effective + sign extension elimination"
+ Motohiro Kawahito, Hideaki Komatsu, and Toshio Nakatani
+ Proceedings of the ACM SIGPLAN 2002 Conference on Programming Language Design + and Implementation.

+ +
+ + + + +
+ +

The Select phase is the bulk of the target-specific code for instruction + selection. This phase takes a legal SelectionDAG as input, pattern matches + the instructions supported by the target to this DAG, and produces a new DAG + of target code. For example, consider the following LLVM fragment:

+ +
+
+%t1 = add float %W, %X
+%t2 = mul float %t1, %Y
+%t3 = add float %t2, %Z
+
+
+ +

This LLVM code corresponds to a SelectionDAG that looks basically like + this:

+ +
+
+(fadd:f32 (fmul:f32 (fadd:f32 W, X), Y), Z)
+
+
+ +

If a target supports floating point multiply-and-add (FMA) operations, one of + the adds can be merged with the multiply. On the PowerPC, for example, the + output of the instruction selector might look like this DAG:

+ +
+
+(FMADDS (FADDS W, X), Y, Z)
+
+
+ +

The FMADDS instruction is a ternary instruction that multiplies its +first two operands and adds the third (as single-precision floating-point +numbers). The FADDS instruction is a simple binary single-precision +add instruction. To perform this pattern match, the PowerPC backend includes +the following instruction definitions:

+ +
+
+def FMADDS : AForm_1<59, 29,
+                    (ops F4RC:$FRT, F4RC:$FRA, F4RC:$FRC, F4RC:$FRB),
+                    "fmadds $FRT, $FRA, $FRC, $FRB",
+                    [(set F4RC:$FRT, (fadd (fmul F4RC:$FRA, F4RC:$FRC),
+                                           F4RC:$FRB))]>;
+def FADDS : AForm_2<59, 21,
+                    (ops F4RC:$FRT, F4RC:$FRA, F4RC:$FRB),
+                    "fadds $FRT, $FRA, $FRB",
+                    [(set F4RC:$FRT, (fadd F4RC:$FRA, F4RC:$FRB))]>;
+
+
+ +

The portion of the instruction definition in bold indicates the pattern used + to match the instruction. The DAG operators + (like fmul/fadd) are defined in + the lib/Target/TargetSelectionDAG.td file. "F4RC" is the + register class of the input and result values.

+ +

The TableGen DAG instruction selector generator reads the instruction + patterns in the .td file and automatically builds parts of the + pattern matching code for your target. It has the following strengths:

+ +
    +
  • At compiler-compiler time, it analyzes your instruction patterns and tells + you if your patterns make sense or not.
  • + +
  • It can handle arbitrary constraints on operands for the pattern match. In + particular, it is straight-forward to say things like "match any immediate + that is a 13-bit sign-extended value". For examples, see the + immSExt16 and related tblgen classes in the PowerPC + backend.
  • + +
  • It knows several important identities for the patterns defined. For + example, it knows that addition is commutative, so it allows the + FMADDS pattern above to match "(fadd X, (fmul Y, Z))" as + well as "(fadd (fmul X, Y), Z)", without the target author having + to specially handle this case.
  • + +
  • It has a full-featured type-inferencing system. In particular, you should + rarely have to explicitly tell the system what type parts of your patterns + are. In the FMADDS case above, we didn't have to tell + tblgen that all of the nodes in the pattern are of type 'f32'. + It was able to infer and propagate this knowledge from the fact that + F4RC has type 'f32'.
  • + +
  • Targets can define their own (and rely on built-in) "pattern fragments". + Pattern fragments are chunks of reusable patterns that get inlined into + your patterns during compiler-compiler time. For example, the integer + "(not x)" operation is actually defined as a pattern fragment + that expands as "(xor x, -1)", since the SelectionDAG does not + have a native 'not' operation. Targets can define their own + short-hand fragments as they see fit. See the definition of + 'not' and 'ineg' for examples.
  • + +
  • In addition to instructions, targets can specify arbitrary patterns that + map to one or more instructions using the 'Pat' class. For example, the + PowerPC has no way to load an arbitrary integer immediate into a register + in one instruction. To tell tblgen how to do this, it defines: +
    +
    +
    +
    +// Arbitrary immediate support.  Implement in terms of LIS/ORI.
    +def : Pat<(i32 imm:$imm),
    +          (ORI (LIS (HI16 imm:$imm)), (LO16 imm:$imm))>;
    +
    +
    +
    + If none of the single-instruction patterns for loading an immediate into a + register match, this will be used. This rule says "match an arbitrary i32 + immediate, turning it into an ORI ('or a 16-bit immediate') and + an LIS ('load 16-bit immediate, where the immediate is shifted to + the left 16 bits') instruction". To make this work, the + LO16/HI16 node transformations are used to manipulate + the input immediate (in this case, take the high or low 16-bits of the + immediate).
  • + +
  • While the system does automate a lot, it still allows you to write custom + C++ code to match special cases if there is something that is hard to + express.
  • +
+ +

While it has many strengths, the system currently has some limitations, + primarily because it is a work in progress and is not yet finished:

+ +
    +
  • Overall, there is no way to define or match SelectionDAG nodes that define + multiple values (e.g. SMUL_LOHI, LOAD, CALL, + etc). This is the biggest reason that you currently still have + to write custom C++ code for your instruction selector.
  • + +
  • There is no great way to support matching complex addressing modes yet. + In the future, we will extend pattern fragments to allow them to define + multiple values (e.g. the four operands of the X86 + addressing mode, which are currently matched with custom C++ code). + In addition, we'll extend fragments so that a fragment can match multiple + different patterns.
  • + +
  • We don't automatically infer flags like isStore/isLoad yet.
  • + +
  • We don't automatically generate the set of supported registers and + operations for the Legalizer + yet.
  • + +
  • We don't have a way of tying in custom legalized nodes yet.
  • +
+ +

Despite these limitations, the instruction selector generator is still quite + useful for most of the binary and logical operations in typical instruction + sets. If you run into any problems or can't figure out how to do something, + please let Chris know!

+ +
+ + + + +
+ +

The scheduling phase takes the DAG of target instructions from the selection + phase and assigns an order. The scheduler can pick an order depending on + various constraints of the machines (i.e. order for minimal register pressure + or try to cover instruction latencies). Once an order is established, the + DAG is converted to a list + of MachineInstrs and the SelectionDAG is + destroyed.

+ +

Note that this phase is logically separate from the instruction selection + phase, but is tied to it closely in the code because it operates on + SelectionDAGs.

+ +
+ + + + +
+ +
    +
  1. Optional function-at-a-time selection.
  2. + +
  3. Auto-generate entire selector from .td file.
  4. +
+ +
+ + + +

To Be Written

+ + + + +
+ +

Live Intervals are the ranges (intervals) where a variable is live. + They are used by some register allocator passes to + determine if two or more virtual registers which require the same physical + register are live at the same point in the program (i.e., they conflict). + When this situation occurs, one virtual register must be spilled.

+ +
+ + + + +
+ +

The first step in determining the live intervals of variables is to calculate + the set of registers that are immediately dead after the instruction (i.e., + the instruction calculates the value, but it is never used) and the set of + registers that are used by the instruction, but are never used after the + instruction (i.e., they are killed). Live variable information is computed + for each virtual register and register allocatable physical + register in the function. This is done in a very efficient manner because it + uses SSA to sparsely compute lifetime information for virtual registers + (which are in SSA form) and only has to track physical registers within a + block. Before register allocation, LLVM can assume that physical registers + are only live within a single basic block. This allows it to do a single, + local analysis to resolve physical register lifetimes within each basic + block. If a physical register is not register allocatable (e.g., a stack + pointer or condition codes), it is not tracked.

+ +

Physical registers may be live in to or out of a function. Live in values are + typically arguments in registers. Live out values are typically return values + in registers. Live in values are marked as such, and are given a dummy + "defining" instruction during live intervals analysis. If the last basic + block of a function is a return, then it's marked as using all live + out values in the function.

+ +

PHI nodes need to be handled specially, because the calculation of + the live variable information from a depth first traversal of the CFG of the + function won't guarantee that a virtual register used by the PHI + node is defined before it's used. When a PHI node is encountered, + only the definition is handled, because the uses will be handled in other + basic blocks.

+ +

For each PHI node of the current basic block, we simulate an + assignment at the end of the current basic block and traverse the successor + basic blocks. If a successor basic block has a PHI node and one of + the PHI node's operands is coming from the current basic block, then + the variable is marked as alive within the current basic block and all + of its predecessor basic blocks, until the basic block with the defining + instruction is encountered.

+ +
+ + + + +
+ +

We now have the information available to perform the live intervals analysis + and build the live intervals themselves. We start off by numbering the basic + blocks and machine instructions. We then handle the "live-in" values. These + are in physical registers, so the physical register is assumed to be killed + by the end of the basic block. Live intervals for virtual registers are + computed for some ordering of the machine instructions [1, N]. A + live interval is an interval [i, j), where 1 <= i <= j + < N, for which a variable is live.

+ +

More to come...

+ +
+ + + + +
+ +

The Register Allocation problem consists in mapping a program + Pv, that can use an unbounded number of virtual registers, + to a program Pp that contains a finite (possibly small) + number of physical registers. Each target architecture has a different number + of physical registers. If the number of physical registers is not enough to + accommodate all the virtual registers, some of them will have to be mapped + into memory. These virtuals are called spilled virtuals.

+ +
+ + + + + +
+ +

In LLVM, physical registers are denoted by integer numbers that normally + range from 1 to 1023. To see how this numbering is defined for a particular + architecture, you can read the GenRegisterNames.inc file for that + architecture. For instance, by + inspecting lib/Target/X86/X86GenRegisterNames.inc we see that the + 32-bit register EAX is denoted by 15, and the MMX register + MM0 is mapped to 48.

+ +

Some architectures contain registers that share the same physical location. A + notable example is the X86 platform. For instance, in the X86 architecture, + the registers EAX, AX and AL share the first eight + bits. These physical registers are marked as aliased in LLVM. Given a + particular architecture, you can check which registers are aliased by + inspecting its RegisterInfo.td file. Moreover, the method + TargetRegisterInfo::getAliasSet(p_reg) returns an array containing + all the physical registers aliased to the register p_reg.

+ +

Physical registers, in LLVM, are grouped in Register Classes. + Elements in the same register class are functionally equivalent, and can be + interchangeably used. Each virtual register can only be mapped to physical + registers of a particular class. For instance, in the X86 architecture, some + virtuals can only be allocated to 8 bit registers. A register class is + described by TargetRegisterClass objects. To discover if a virtual + register is compatible with a given physical, this code can be used:

+ +
+
+bool RegMapping_Fer::compatible_class(MachineFunction &mf,
+                                      unsigned v_reg,
+                                      unsigned p_reg) {
+  assert(TargetRegisterInfo::isPhysicalRegister(p_reg) &&
+         "Target register must be physical");
+  const TargetRegisterClass *trc = mf.getRegInfo().getRegClass(v_reg);
+  return trc->contains(p_reg);
+}
+
+
+ +

Sometimes, mostly for debugging purposes, it is useful to change the number + of physical registers available in the target architecture. This must be done + statically, inside the TargetRegsterInfo.td file. Just grep + for RegisterClass, the last parameter of which is a list of + registers. Just commenting some out is one simple way to avoid them being + used. A more polite way is to explicitly exclude some registers from + the allocation order. See the definition of the GR8 register + class in lib/Target/X86/X86RegisterInfo.td for an example of this. +

+ +

Virtual registers are also denoted by integer numbers. Contrary to physical + registers, different virtual registers never share the same number. The + smallest virtual register is normally assigned the number 1024. This may + change, so, in order to know which is the first virtual register, you should + access TargetRegisterInfo::FirstVirtualRegister. Any register whose + number is greater than or equal + to TargetRegisterInfo::FirstVirtualRegister is considered a virtual + register. Whereas physical registers are statically defined in + a TargetRegisterInfo.td file and cannot be created by the + application developer, that is not the case with virtual registers. In order + to create new virtual registers, use the + method MachineRegisterInfo::createVirtualRegister(). This method + will return a virtual register with the highest code.

+ +

Before register allocation, the operands of an instruction are mostly virtual + registers, although physical registers may also be used. In order to check if + a given machine operand is a register, use the boolean + function MachineOperand::isRegister(). To obtain the integer code of + a register, use MachineOperand::getReg(). An instruction may define + or use a register. For instance, ADD reg:1026 := reg:1025 reg:1024 + defines the registers 1024, and uses registers 1025 and 1026. Given a + register operand, the method MachineOperand::isUse() informs if that + register is being used by the instruction. The + method MachineOperand::isDef() informs if that registers is being + defined.

+ +

We will call physical registers present in the LLVM bitcode before register + allocation pre-colored registers. Pre-colored registers are used in + many different situations, for instance, to pass parameters of functions + calls, and to store results of particular instructions. There are two types + of pre-colored registers: the ones implicitly defined, and + those explicitly defined. Explicitly defined registers are normal + operands, and can be accessed + with MachineInstr::getOperand(int)::getReg(). In order to check + which registers are implicitly defined by an instruction, use + the TargetInstrInfo::get(opcode)::ImplicitDefs, + where opcode is the opcode of the target instruction. One important + difference between explicit and implicit physical registers is that the + latter are defined statically for each instruction, whereas the former may + vary depending on the program being compiled. For example, an instruction + that represents a function call will always implicitly define or use the same + set of physical registers. To read the registers implicitly used by an + instruction, + use TargetInstrInfo::get(opcode)::ImplicitUses. Pre-colored + registers impose constraints on any register allocation algorithm. The + register allocator must make sure that none of them is been overwritten by + the values of virtual registers while still alive.

+ +
+ + + + + +
+ +

There are two ways to map virtual registers to physical registers (or to + memory slots). The first way, that we will call direct mapping, is + based on the use of methods of the classes TargetRegisterInfo, + and MachineOperand. The second way, that we will call indirect + mapping, relies on the VirtRegMap class in order to insert loads + and stores sending and getting values to and from memory.

+ +

The direct mapping provides more flexibility to the developer of the register + allocator; however, it is more error prone, and demands more implementation + work. Basically, the programmer will have to specify where load and store + instructions should be inserted in the target function being compiled in + order to get and store values in memory. To assign a physical register to a + virtual register present in a given operand, + use MachineOperand::setReg(p_reg). To insert a store instruction, + use TargetRegisterInfo::storeRegToStackSlot(...), and to insert a + load instruction, use TargetRegisterInfo::loadRegFromStackSlot.

+ +

The indirect mapping shields the application developer from the complexities + of inserting load and store instructions. In order to map a virtual register + to a physical one, use VirtRegMap::assignVirt2Phys(vreg, preg). In + order to map a certain virtual register to memory, + use VirtRegMap::assignVirt2StackSlot(vreg). This method will return + the stack slot where vreg's value will be located. If it is + necessary to map another virtual register to the same stack slot, + use VirtRegMap::assignVirt2StackSlot(vreg, stack_location). One + important point to consider when using the indirect mapping, is that even if + a virtual register is mapped to memory, it still needs to be mapped to a + physical register. This physical register is the location where the virtual + register is supposed to be found before being stored or after being + reloaded.

+ +

If the indirect strategy is used, after all the virtual registers have been + mapped to physical registers or stack slots, it is necessary to use a spiller + object to place load and store instructions in the code. Every virtual that + has been mapped to a stack slot will be stored to memory after been defined + and will be loaded before being used. The implementation of the spiller tries + to recycle load/store instructions, avoiding unnecessary instructions. For an + example of how to invoke the spiller, + see RegAllocLinearScan::runOnMachineFunction + in lib/CodeGen/RegAllocLinearScan.cpp.

+ +
+ + + + +
+ +

With very rare exceptions (e.g., function calls), the LLVM machine code + instructions are three address instructions. That is, each instruction is + expected to define at most one register, and to use at most two registers. + However, some architectures use two address instructions. In this case, the + defined register is also one of the used register. For instance, an + instruction such as ADD %EAX, %EBX, in X86 is actually equivalent + to %EAX = %EAX + %EBX.

+ +

In order to produce correct code, LLVM must convert three address + instructions that represent two address instructions into true two address + instructions. LLVM provides the pass TwoAddressInstructionPass for + this specific purpose. It must be run before register allocation takes + place. After its execution, the resulting code may no longer be in SSA + form. This happens, for instance, in situations where an instruction such + as %a = ADD %b %c is converted to two instructions such as:

+ +
+
+%a = MOVE %b
+%a = ADD %a %c
+
+
+ +

Notice that, internally, the second instruction is represented as + ADD %a[def/use] %c. I.e., the register operand %a is both + used and defined by the instruction.

+ +
+ + + + +
+ +

An important transformation that happens during register allocation is called + the SSA Deconstruction Phase. The SSA form simplifies many analyses + that are performed on the control flow graph of programs. However, + traditional instruction sets do not implement PHI instructions. Thus, in + order to generate executable code, compilers must replace PHI instructions + with other instructions that preserve their semantics.

+ +

There are many ways in which PHI instructions can safely be removed from the + target code. The most traditional PHI deconstruction algorithm replaces PHI + instructions with copy instructions. That is the strategy adopted by + LLVM. The SSA deconstruction algorithm is implemented + in lib/CodeGen/PHIElimination.cpp. In order to invoke this pass, the + identifier PHIEliminationID must be marked as required in the code + of the register allocator.

+ +
+ + + + +
+ +

Instruction folding is an optimization performed during register + allocation that removes unnecessary copy instructions. For instance, a + sequence of instructions such as:

+ +
+
+%EBX = LOAD %mem_address
+%EAX = COPY %EBX
+
+
+ +

can be safely substituted by the single instruction:

+ +
+
+%EAX = LOAD %mem_address
+
+
+ +

Instructions can be folded with + the TargetRegisterInfo::foldMemoryOperand(...) method. Care must be + taken when folding instructions; a folded instruction can be quite different + from the original + instruction. See LiveIntervals::addIntervalsForSpills + in lib/CodeGen/LiveIntervalAnalysis.cpp for an example of its + use.

+ +
+ + + + + +
+ +

The LLVM infrastructure provides the application developer with three + different register allocators:

+ +
    +
  • Simple — This is a very simple implementation that does not + keep values in registers across instructions. This register allocator + immediately spills every value right after it is computed, and reloads all + used operands from memory to temporary registers before each + instruction.
  • + +
  • Local — This register allocator is an improvement on the + Simple implementation. It allocates registers on a basic block + level, attempting to keep values in registers and reusing registers as + appropriate.
  • + +
  • Linear ScanThe default allocator. This is the + well-know linear scan register allocator. Whereas the + Simple and Local algorithms use a direct mapping + implementation technique, the Linear Scan implementation + uses a spiller in order to place load and stores.
  • +
+ +

The type of register allocator used in llc can be chosen with the + command line option -regalloc=...:

+ +
+
+$ llc -regalloc=simple file.bc -o sp.s;
+$ llc -regalloc=local file.bc -o lc.s;
+$ llc -regalloc=linearscan file.bc -o ln.s;
+
+
+ +
+ + + +

To Be Written

+ + +

To Be Written

+ + +

To Be Written

+ + +

To Be Written

+ + + +
+

For the JIT or .o file writer

+
+ + + + + + +
+ +

This section of the document explains features or design decisions that are + specific to the code generator for a particular target.

+ +
+ + + + +
+ +

Tail call optimization, callee reusing the stack of the caller, is currently + supported on x86/x86-64 and PowerPC. It is performed if:

+ +
    +
  • Caller and callee have the calling convention fastcc.
  • + +
  • The call is a tail call - in tail position (ret immediately follows call + and ret uses value of call or is void).
  • + +
  • Option -tailcallopt is enabled.
  • + +
  • Platform specific constraints are met.
  • +
+ +

x86/x86-64 constraints:

+ +
    +
  • No variable argument lists are used.
  • + +
  • On x86-64 when generating GOT/PIC code only module-local calls (visibility + = hidden or protected) are supported.
  • +
+ +

PowerPC constraints:

+ +
    +
  • No variable argument lists are used.
  • + +
  • No byval parameters are used.
  • + +
  • On ppc32/64 GOT/PIC only module-local calls (visibility = hidden or protected) are supported.
  • +
+ +

Example:

+ +

Call as llc -tailcallopt test.ll.

+ +
+
+declare fastcc i32 @tailcallee(i32 inreg %a1, i32 inreg %a2, i32 %a3, i32 %a4)
+
+define fastcc i32 @tailcaller(i32 %in1, i32 %in2) {
+  %l1 = add i32 %in1, %in2
+  %tmp = tail call fastcc i32 @tailcallee(i32 %in1 inreg, i32 %in2 inreg, i32 %in1, i32 %l1)
+  ret i32 %tmp
+}
+
+
+ +

Implications of -tailcallopt:

+ +

To support tail call optimization in situations where the callee has more + arguments than the caller a 'callee pops arguments' convention is used. This + currently causes each fastcc call that is not tail call optimized + (because one or more of above constraints are not met) to be followed by a + readjustment of the stack. So performance might be worse in such cases.

+ +

On x86 and x86-64 one register is reserved for indirect tail calls (e.g via a + function pointer). So there is one less register for integer argument + passing. For x86 this means 2 registers (if inreg parameter + attribute is used) and for x86-64 this means 5 register are used.

+ +
+ + + +
+ +

The X86 code generator lives in the lib/Target/X86 directory. This + code generator is capable of targeting a variety of x86-32 and x86-64 + processors, and includes support for ISA extensions such as MMX and SSE.

+ +
+ + + + +
+ +

The following are the known target triples that are supported by the X86 + backend. This is not an exhaustive list, and it would be useful to add those + that people test.

+ +
    +
  • i686-pc-linux-gnu — Linux
  • + +
  • i386-unknown-freebsd5.3 — FreeBSD 5.3
  • + +
  • i686-pc-cygwin — Cygwin on Win32
  • + +
  • i686-pc-mingw32 — MingW on Win32
  • + +
  • i386-pc-mingw32msvc — MingW crosscompiler on Linux
  • + +
  • i686-apple-darwin* — Apple Darwin on X86
  • + +
  • x86_64-unknown-linux-gnu — Linux
  • +
+ +
+ + + + + +
+ +

The following target-specific calling conventions are known to backend:

+ +
    +
  • x86_StdCall — stdcall calling convention seen on Microsoft + Windows platform (CC ID = 64).
  • + +
  • x86_FastCall — fastcall calling convention seen on Microsoft + Windows platform (CC ID = 65).
  • +
+ +
+ + + + +
+ +

The x86 has a very flexible way of accessing memory. It is capable of + forming memory addresses of the following expression directly in integer + instructions (which use ModR/M addressing):

+ +
+
+SegmentReg: Base + [1,2,4,8] * IndexReg + Disp32
+
+
+ +

In order to represent this, LLVM tracks no less than 5 operands for each + memory operand of this form. This means that the "load" form of + 'mov' has the following MachineOperands in this order:

+ +
+
+Index:        0     |    1        2       3           4          5
+Meaning:   DestReg, | BaseReg,  Scale, IndexReg, Displacement Segment
+OperandTy: VirtReg, | VirtReg, UnsImm, VirtReg,   SignExtImm  PhysReg
+
+
+ +

Stores, and all other instructions, treat the four memory operands in the + same way and in the same order. If the segment register is unspecified + (regno = 0), then no segment override is generated. "Lea" operations do not + have a segment register specified, so they only have 4 operands for their + memory reference.

+ +
+ + + + +
+ +

x86 has an experimental feature which provides + the ability to perform loads and stores to different address spaces + via the x86 segment registers. A segment override prefix byte on an + instruction causes the instruction's memory access to go to the specified + segment. LLVM address space 0 is the default address space, which includes + the stack, and any unqualified memory accesses in a program. Address spaces + 1-255 are currently reserved for user-defined code. The GS-segment is + represented by address space 256, while the FS-segment is represented by + address space 257. Other x86 segments have yet to be allocated address space + numbers.

+ +

While these address spaces may seem similar to TLS via the + thread_local keyword, and often use the same underlying hardware, + there are some fundamental differences.

+ +

The thread_local keyword applies to global variables and + specifies that they are to be allocated in thread-local memory. There are + no type qualifiers involved, and these variables can be pointed to with + normal pointers and accessed with normal loads and stores. + The thread_local keyword is target-independent at the LLVM IR + level (though LLVM doesn't yet have implementations of it for some + configurations).

+ +

Special address spaces, in contrast, apply to static types. Every + load and store has a particular address space in its address operand type, + and this is what determines which address space is accessed. + LLVM ignores these special address space qualifiers on global variables, + and does not provide a way to directly allocate storage in them. + At the LLVM IR level, the behavior of these special address spaces depends + in part on the underlying OS or runtime environment, and they are specific + to x86 (and LLVM doesn't yet handle them correctly in some cases).

+ +

Some operating systems and runtime environments use (or may in the future + use) the FS/GS-segment registers for various low-level purposes, so care + should be taken when considering them.

+ +
+ + + + +
+ +

An instruction name consists of the base name, a default operand size, and a + a character per operand with an optional special size. For example:

+ +
+
+ADD8rr      -> add, 8-bit register, 8-bit register
+IMUL16rmi   -> imul, 16-bit register, 16-bit memory, 16-bit immediate
+IMUL16rmi8  -> imul, 16-bit register, 16-bit memory, 8-bit immediate
+MOVSX32rm16 -> movsx, 32-bit register, 16-bit memory
+
+
+ +
+ + + + +
+ +

The PowerPC code generator lives in the lib/Target/PowerPC directory. The + code generation is retargetable to several variations or subtargets of + the PowerPC ISA; including ppc32, ppc64 and altivec.

+ +
+ + + + +
+ +

LLVM follows the AIX PowerPC ABI, with two deviations. LLVM uses a PC + relative (PIC) or static addressing for accessing global values, so no TOC + (r2) is used. Second, r31 is used as a frame pointer to allow dynamic growth + of a stack frame. LLVM takes advantage of having no TOC to provide space to + save the frame pointer in the PowerPC linkage area of the caller frame. + Other details of PowerPC ABI can be found at PowerPC ABI. Note: This link describes the 32 bit ABI. The 64 bit ABI + is similar except space for GPRs are 8 bytes wide (not 4) and r13 is reserved + for system use.

+ +
+ + + + +
+ +

The size of a PowerPC frame is usually fixed for the duration of a + function's invocation. Since the frame is fixed size, all references + into the frame can be accessed via fixed offsets from the stack pointer. The + exception to this is when dynamic alloca or variable sized arrays are + present, then a base pointer (r31) is used as a proxy for the stack pointer + and stack pointer is free to grow or shrink. A base pointer is also used if + llvm-gcc is not passed the -fomit-frame-pointer flag. The stack pointer is + always aligned to 16 bytes, so that space allocated for altivec vectors will + be properly aligned.

+ +

An invocation frame is laid out as follows (low memory at top);

+ + + + + + + + + + + + + + + + + + + + + + + +
Linkage

Parameter area

Dynamic area

Locals area

Saved registers area


Previous Frame

+ +

The linkage area is used by a callee to save special registers prior + to allocating its own frame. Only three entries are relevant to LLVM. The + first entry is the previous stack pointer (sp), aka link. This allows + probing tools like gdb or exception handlers to quickly scan the frames in + the stack. A function epilog can also use the link to pop the frame from the + stack. The third entry in the linkage area is used to save the return + address from the lr register. Finally, as mentioned above, the last entry is + used to save the previous frame pointer (r31.) The entries in the linkage + area are the size of a GPR, thus the linkage area is 24 bytes long in 32 bit + mode and 48 bytes in 64 bit mode.

+ +

32 bit linkage area

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
0Saved SP (r1)
4Saved CR
8Saved LR
12Reserved
16Reserved
20Saved FP (r31)
+ +

64 bit linkage area

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
0Saved SP (r1)
8Saved CR
16Saved LR
24Reserved
32Reserved
40Saved FP (r31)
+ +

The parameter area is used to store arguments being passed to a callee + function. Following the PowerPC ABI, the first few arguments are actually + passed in registers, with the space in the parameter area unused. However, + if there are not enough registers or the callee is a thunk or vararg + function, these register arguments can be spilled into the parameter area. + Thus, the parameter area must be large enough to store all the parameters for + the largest call sequence made by the caller. The size must also be + minimally large enough to spill registers r3-r10. This allows callees blind + to the call signature, such as thunks and vararg functions, enough space to + cache the argument registers. Therefore, the parameter area is minimally 32 + bytes (64 bytes in 64 bit mode.) Also note that since the parameter area is + a fixed offset from the top of the frame, that a callee can access its spilt + arguments using fixed offsets from the stack pointer (or base pointer.)

+ +

Combining the information about the linkage, parameter areas and alignment. A + stack frame is minimally 64 bytes in 32 bit mode and 128 bytes in 64 bit + mode.

+ +

The dynamic area starts out as size zero. If a function uses dynamic + alloca then space is added to the stack, the linkage and parameter areas are + shifted to top of stack, and the new space is available immediately below the + linkage and parameter areas. The cost of shifting the linkage and parameter + areas is minor since only the link value needs to be copied. The link value + can be easily fetched by adding the original frame size to the base pointer. + Note that allocations in the dynamic space need to observe 16 byte + alignment.

+ +

The locals area is where the llvm compiler reserves space for local + variables.

+ +

The saved registers area is where the llvm compiler spills callee + saved registers on entry to the callee.

+ +
+ + + + +
+ +

The llvm prolog and epilog are the same as described in the PowerPC ABI, with + the following exceptions. Callee saved registers are spilled after the frame + is created. This allows the llvm epilog/prolog support to be common with + other targets. The base pointer callee saved register r31 is saved in the + TOC slot of linkage area. This simplifies allocation of space for the base + pointer and makes it convenient to locate programatically and during + debugging.

+ +
+ + + + +
+ +

TODO - More to come.

+ +
+ + + +
+
+ Valid CSS + Valid HTML 4.01 + + Chris Lattner
+ The LLVM Compiler Infrastructure
+ Last modified: $Date$ +
+ + + diff --git a/libclamav/c++/llvm/docs/CodingStandards.html b/libclamav/c++/llvm/docs/CodingStandards.html new file mode 100644 index 000000000..ee9443d16 --- /dev/null +++ b/libclamav/c++/llvm/docs/CodingStandards.html @@ -0,0 +1,1353 @@ + + + + + LLVM Coding Standards + + + +
+ LLVM Coding Standards +
+ +
    +
  1. Introduction
  2. +
  3. Mechanical Source Issues +
      +
    1. Source Code Formatting +
        +
      1. Commenting
      2. +
      3. Comment Formatting
      4. +
      5. #include Style
      6. +
      7. Source Code Width
      8. +
      9. Use Spaces Instead of Tabs
      10. +
      11. Indent Code Consistently
      12. +
    2. +
    3. Compiler Issues +
        +
      1. Treat Compiler Warnings Like + Errors
      2. +
      3. Write Portable Code
      4. +
      5. Use of class/struct Keywords
      6. +
    4. +
  4. +
  5. Style Issues +
      +
    1. The High Level Issues +
        +
      1. A Public Header File is a + Module
      2. +
      3. #include as Little as Possible
      4. +
      5. Keep "internal" Headers + Private
      6. +
      7. Use Early Exits and 'continue' to Simplify + Code
      8. +
      9. Don't use "else" after a + return
      10. +
      11. Turn Predicate Loops into Predicate + Functions
      12. +
    2. +
    3. The Low Level Issues +
        +
      1. Assert Liberally
      2. +
      3. Do not use 'using namespace std'
      4. +
      5. Provide a virtual method anchor for + classes in headers
      6. +
      7. Don't evaluate end() every time through a + loop
      8. +
      9. #include <iostream> is + forbidden
      10. +
      11. Avoid std::endl
      12. +
      13. Use raw_ostream +
    4. + +
    5. Microscopic Details +
        +
      1. Spaces Before Parentheses
      2. +
      3. Prefer Preincrement
      4. +
      5. Namespace Indentation
      6. +
      7. Anonymous Namespaces
      8. +
    6. + + +
  6. +
  7. See Also
  8. +
+ +
+

Written by Chris Lattner

+
+ + + + + + +
+ +

This document attempts to describe a few coding standards that are being used +in the LLVM source tree. Although no coding standards should be regarded as +absolute requirements to be followed in all instances, coding standards can be +useful.

+ +

This document intentionally does not prescribe fixed standards for religious +issues such as brace placement and space usage. For issues like this, follow +the golden rule:

+ +
+ +

If you are adding a significant body of source to a +project, feel free to use whatever style you are most comfortable with. If you +are extending, enhancing, or bug fixing already implemented code, use the style +that is already being used so that the source is uniform and easy to +follow.

+ +
+ +

The ultimate goal of these guidelines is the increase readability and +maintainability of our common source base. If you have suggestions for topics to +be included, please mail them to Chris.

+ +
+ + + + + + + + + + + +
+ +

Comments are one critical part of readability and maintainability. Everyone +knows they should comment, so should you. When writing comments, write them as +English prose, which means they should use proper capitalization, punctuation, +etc. Although we all should probably +comment our code more than we do, there are a few very critical places that +documentation is very useful:

+ +File Headers + +

Every source file should have a header on it that describes the basic +purpose of the file. If a file does not have a header, it should not be +checked into Subversion. Most source trees will probably have a standard +file header format. The standard format for the LLVM source tree looks like +this:

+ +
+
+//===-- llvm/Instruction.h - Instruction class definition -------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains the declaration of the Instruction class, which is the
+// base class for all of the VM instructions.
+//
+//===----------------------------------------------------------------------===//
+
+
+ +

A few things to note about this particular format: The "-*- C++ +-*-" string on the first line is there to tell Emacs that the source file +is a C++ file, not a C file (Emacs assumes .h files are C files by default). +Note that this tag is not necessary in .cpp files. The name of the file is also +on the first line, along with a very short description of the purpose of the +file. This is important when printing out code and flipping though lots of +pages.

+ +

The next section in the file is a concise note that defines the license +that the file is released under. This makes it perfectly clear what terms the +source code can be distributed under and should not be modified in any way.

+ +

The main body of the description does not have to be very long in most cases. +Here it's only two lines. If an algorithm is being implemented or something +tricky is going on, a reference to the paper where it is published should be +included, as well as any notes or "gotchas" in the code to watch out for.

+ +Class overviews + +

Classes are one fundamental part of a good object oriented design. As such, +a class definition should have a comment block that explains what the class is +used for... if it's not obvious. If it's so completely obvious your grandma +could figure it out, it's probably safe to leave it out. Naming classes +something sane goes a long ways towards avoiding writing documentation.

+ + +Method information + +

Methods defined in a class (as well as any global functions) should also be +documented properly. A quick note about what it does any a description of the +borderline behaviour is all that is necessary here (unless something +particularly tricky or insideous is going on). The hope is that people can +figure out how to use your interfaces without reading the code itself... that is +the goal metric.

+ +

Good things to talk about here are what happens when something unexpected +happens: does the method return null? Abort? Format your hard disk?

+ +
+ + + + +
+ +

In general, prefer C++ style (//) comments. They take less space, +require less typing, don't have nesting problems, etc. There are a few cases +when it is useful to use C style (/* */) comments however:

+ +
    +
  1. When writing a C code: Obviously if you are writing C code, use C style + comments.
  2. +
  3. When writing a header file that may be #included by a C source + file.
  4. +
  5. When writing a source file that is used by a tool that only accepts C + style comments.
  6. +
+ +

To comment out a large block of code, use #if 0 and #endif. +These nest properly and are better behaved in general than C style comments.

+ +
+ + + + +
+ +

Immediately after the header file comment (and +include guards if working on a header file), the minimal list of #includes required by the +file should be listed. We prefer these #includes to be listed in this +order:

+ +
    +
  1. Main Module header
  2. +
  3. Local/Private Headers
  4. +
  5. llvm/*
  6. +
  7. llvm/Analysis/*
  8. +
  9. llvm/Assembly/*
  10. +
  11. llvm/Bytecode/*
  12. +
  13. llvm/CodeGen/*
  14. +
  15. ...
  16. +
  17. Support/*
  18. +
  19. Config/*
  20. +
  21. System #includes
  22. +
+ +

... and each category should be sorted by name.

+ +

The "Main Module Header" file applies to .cpp file +which implement an interface defined by a .h file. This #include +should always be included first regardless of where it lives on the file +system. By including a header file first in the .cpp files that implement the +interfaces, we ensure that the header does not have any hidden dependencies +which are not explicitly #included in the header, but should be. It is also a +form of documentation in the .cpp file to indicate where the interfaces it +implements are defined.

+ +
+ + + + +
+ +

Write your code to fit within 80 columns of text. This helps those of us who +like to print out code and look at your code in an xterm without resizing +it.

+ +

The longer answer is that there must be some limit to the width of the code +in order to reasonably allow developers to have multiple files side-by-side in +windows on a modest display. If you are going to pick a width limit, it is +somewhat arbitrary but you might as well pick something standard. Going with +90 columns (for example) instead of 80 columns wouldn't add any significant +value and would be detrimental to printing out code. Also many other projects +have standardized on 80 columns, so some people have already configured their +editors for it (vs something else, like 90 columns).

+ +

This is one of many contentious issues in coding standards, but is not up +for debate.

+ +
+ + + + +
+ +

In all cases, prefer spaces to tabs in source files. People have different +preferred indentation levels, and different styles of indentation that they +like... this is fine. What isn't is that different editors/viewers expand tabs +out to different tab stops. This can cause your code to look completely +unreadable, and it is not worth dealing with.

+ +

As always, follow the Golden Rule above: follow the +style of existing code if your are modifying and extending it. If you like four +spaces of indentation, DO NOT do that in the middle of a chunk of code +with two spaces of indentation. Also, do not reindent a whole source file: it +makes for incredible diffs that are absolutely worthless.

+ +
+ + + + +
+ +

Okay, your first year of programming you were told that indentation is +important. If you didn't believe and internalize this then, now is the time. +Just do it.

+ +
+ + + + + + + + + +
+ +

If your code has compiler warnings in it, something is wrong: you aren't +casting values correctly, your have "questionable" constructs in your code, or +you are doing something legitimately wrong. Compiler warnings can cover up +legitimate errors in output and make dealing with a translation unit +difficult.

+ +

It is not possible to prevent all warnings from all compilers, nor is it +desirable. Instead, pick a standard compiler (like gcc) that provides +a good thorough set of warnings, and stick to them. At least in the case of +gcc, it is possible to work around any spurious errors by changing the +syntax of the code slightly. For example, an warning that annoys me occurs when +I write code like this:

+ +
+
+if (V = getValue()) {
+  ...
+}
+
+
+ +

gcc will warn me that I probably want to use the == +operator, and that I probably mistyped it. In most cases, I haven't, and I +really don't want the spurious errors. To fix this particular problem, I +rewrite the code like this:

+ +
+
+if ((V = getValue())) {
+  ...
+}
+
+
+ +

...which shuts gcc up. Any gcc warning that annoys you can +be fixed by massaging the code appropriately.

+ +

These are the gcc warnings that I prefer to enable: -Wall +-Winline -W -Wwrite-strings -Wno-unused

+ +
+ + + + +
+ +

In almost all cases, it is possible and within reason to write completely +portable code. If there are cases where it isn't possible to write portable +code, isolate it behind a well defined (and well documented) interface.

+ +

In practice, this means that you shouldn't assume much about the host +compiler, including its support for "high tech" features like partial +specialization of templates. If these features are used, they should only be +an implementation detail of a library which has a simple exposed API.

+ +
+ + + +
+ +

In C++, the class and struct keywords can be used almost +interchangeably. The only difference is when they are used to declare a class: +class makes all members private by default while struct makes +all members public by default.

+ +

Unfortunately, not all compilers follow the rules and some will generate +different symbols based on whether class or struct was used to +declare the symbol. This can lead to problems at link time.

+ +

So, the rule for LLVM is to always use the class keyword, unless +all members are public and the type is a C++ "POD" type, in which case +struct is allowed.

+ +
+ + + + + + + + + + + + + + +
+ +

C++ doesn't do too well in the modularity department. There is no real +encapsulation or data hiding (unless you use expensive protocol classes), but it +is what we have to work with. When you write a public header file (in the LLVM +source tree, they live in the top level "include" directory), you are defining a +module of functionality.

+ +

Ideally, modules should be completely independent of each other, and their +header files should only include the absolute minimum number of headers +possible. A module is not just a class, a function, or a namespace: it's a collection +of these that defines an interface. This interface may be several +functions, classes or data structures, but the important issue is how they work +together.

+ +

In general, a module should be implemented with one or more .cpp +files. Each of these .cpp files should include the header that defines +their interface first. This ensure that all of the dependences of the module +header have been properly added to the module header itself, and are not +implicit. System headers should be included after user headers for a +translation unit.

+ +
+ + + + +
+ +

#include hurts compile time performance. Don't do it unless you +have to, especially in header files.

+ +

But wait, sometimes you need to have the definition of a class to use it, or +to inherit from it. In these cases go ahead and #include that header +file. Be aware however that there are many cases where you don't need to have +the full definition of a class. If you are using a pointer or reference to a +class, you don't need the header file. If you are simply returning a class +instance from a prototyped function or method, you don't need it. In fact, for +most cases, you simply don't need the definition of a class... and not +#include'ing speeds up compilation.

+ +

It is easy to try to go too overboard on this recommendation, however. You +must include all of the header files that you are using -- you can +include them either directly +or indirectly (through another header file). To make sure that you don't +accidentally forget to include a header file in your module header, make sure to +include your module header first in the implementation file (as mentioned +above). This way there won't be any hidden dependencies that you'll find out +about later...

+ +
+ + + + +
+ +

Many modules have a complex implementation that causes them to use more than +one implementation (.cpp) file. It is often tempting to put the +internal communication interface (helper classes, extra functions, etc) in the +public module header file. Don't do this.

+ +

If you really need to do something like this, put a private header file in +the same directory as the source files, and include it locally. This ensures +that your private interface remains private and undisturbed by outsiders.

+ +

Note however, that it's okay to put extra implementation methods a public +class itself... just make them private (or protected), and all is well.

+ +
+ + + + +
+ +

When reading code, keep in mind how much state and how many previous +decisions have to be remembered by the reader to understand a block of code. +Aim to reduce indentation where possible when it doesn't make it more difficult +to understand the code. One great way to do this is by making use of early +exits and the 'continue' keyword in long loops. As an example of using an early +exit from a function, consider this "bad" code:

+ +
+
+Value *DoSomething(Instruction *I) {
+  if (!isa<TerminatorInst>(I) &&
+      I->hasOneUse() && SomeOtherThing(I)) {
+    ... some long code ....
+  }
+  
+  return 0;
+}
+
+
+ +

This code has several problems if the body of the 'if' is large. When you're +looking at the top of the function, it isn't immediately clear that this +only does interesting things with non-terminator instructions, and only +applies to things with the other predicates. Second, it is relatively difficult +to describe (in comments) why these predicates are important because the if +statement makes it difficult to lay out the comments. Third, when you're deep +within the body of the code, it is indented an extra level. Finally, when +reading the top of the function, it isn't clear what the result is if the +predicate isn't true, you have to read to the end of the function to know that +it returns null.

+ +

It is much preferred to format the code like this:

+ +
+
+Value *DoSomething(Instruction *I) {
+  // Terminators never need 'something' done to them because, ... 
+  if (isa<TerminatorInst>(I))
+    return 0;
+
+  // We conservatively avoid transforming instructions with multiple uses
+  // because goats like cheese.
+  if (!I->hasOneUse())
+    return 0;
+
+  // This is really just here for example.
+  if (!SomeOtherThing(I))
+    return 0;
+    
+  ... some long code ....
+}
+
+
+ +

This fixes these problems. A similar problem frequently happens in for +loops. A silly example is something like this:

+ +
+
+  for (BasicBlock::iterator II = BB->begin(), E = BB->end(); II != E; ++II) {
+    if (BinaryOperator *BO = dyn_cast<BinaryOperator>(II)) {
+      Value *LHS = BO->getOperand(0);
+      Value *RHS = BO->getOperand(1);
+      if (LHS != RHS) {
+        ...
+      }
+    }
+  }
+
+
+ +

When you have very very small loops, this sort of structure is fine, but if +it exceeds more than 10-15 lines, it becomes difficult for people to read and +understand at a glance. +The problem with this sort of code is that it gets very nested very quickly, +meaning that the reader of the code has to keep a lot of context in their brain +to remember what is going immediately on in the loop, because they don't know +if/when the if conditions will have elses etc. It is strongly preferred to +structure the loop like this:

+ +
+
+  for (BasicBlock::iterator II = BB->begin(), E = BB->end(); II != E; ++II) {
+    BinaryOperator *BO = dyn_cast<BinaryOperator>(II);
+    if (!BO) continue;
+    
+    Value *LHS = BO->getOperand(0);
+    Value *RHS = BO->getOperand(1);
+    if (LHS == RHS) continue;
+  }
+
+
+ +

This has all the benefits of using early exits from functions: it reduces +nesting of the loop, it makes it easier to describe why the conditions are true, +and it makes it obvious to the reader that there is no "else" coming up that +they have to push context into their brain for. If a loop is large, this can +be a big understandability win.

+ +
+ + + + +
+ +

For similar reasons above (reduction of indentation and easier reading), + please do not use "else" or "else if" after something that interrupts + control flow like return, break, continue, goto, etc. For example, this is + "bad":

+ +
+
+  case 'J': {
+    if (Signed) {
+      Type = Context.getsigjmp_bufType();
+      if (Type.isNull()) {
+        Error = ASTContext::GE_Missing_sigjmp_buf;
+        return QualType();
+      } else {
+        break;
+      }
+    } else {
+      Type = Context.getjmp_bufType();
+      if (Type.isNull()) {
+        Error = ASTContext::GE_Missing_jmp_buf;
+        return QualType();
+      } else {
+        break;
+      }
+    }
+  }
+  }
+
+
+ +

It is better to write this something like:

+ +
+
+  case 'J':
+    if (Signed) {
+      Type = Context.getsigjmp_bufType();
+      if (Type.isNull()) {
+        Error = ASTContext::GE_Missing_sigjmp_buf;
+        return QualType();
+      }
+    } else {
+      Type = Context.getjmp_bufType();
+      if (Type.isNull()) {
+        Error = ASTContext::GE_Missing_jmp_buf;
+        return QualType();
+      }
+    }
+    break;
+
+
+ +

Or better yet (in this case), as:

+ +
+
+  case 'J':
+    if (Signed)
+      Type = Context.getsigjmp_bufType();
+    else
+      Type = Context.getjmp_bufType();
+    
+    if (Type.isNull()) {
+      Error = Signed ? ASTContext::GE_Missing_sigjmp_buf :
+                       ASTContext::GE_Missing_jmp_buf;
+      return QualType();
+    }
+    break;
+
+
+ +

The idea is to reduce indentation and the amount of code you have to keep + track of when reading the code.

+ +
+ + + + +
+ +

It is very common to write small loops that just compute a boolean + value. There are a number of ways that people commonly write these, but an + example of this sort of thing is:

+ +
+
+  bool FoundFoo = false;
+  for (unsigned i = 0, e = BarList.size(); i != e; ++i)
+    if (BarList[i]->isFoo()) {
+      FoundFoo = true;
+      break;
+    }
+    
+  if (FoundFoo) {
+    ...
+  }
+
+
+ +

This sort of code is awkward to write, and is almost always a bad sign. +Instead of this sort of loop, we strongly prefer to use a predicate function +(which may be static) that uses +early exits to compute the predicate. We prefer +the code to be structured like this: +

+ + +
+
+/// ListContainsFoo - Return true if the specified list has an element that is
+/// a foo.
+static bool ListContainsFoo(const std::vector<Bar*> &List) {
+  for (unsigned i = 0, e = List.size(); i != e; ++i)
+    if (List[i]->isFoo())
+      return true;
+  return false;
+}
+...
+
+  if (ListContainsFoo(BarList)) {
+    ...
+  }
+
+
+ +

There are many reasons for doing this: it reduces indentation and factors out +code which can often be shared by other code that checks for the same predicate. +More importantly, it forces you to pick a name for the function, and +forces you to write a comment for it. In this silly example, this doesn't add +much value. However, if the condition is complex, this can make it a lot easier +for the reader to understand the code that queries for this predicate. Instead +of being faced with the in-line details of how we check to see if the BarList +contains a foo, we can trust the function name and continue reading with better +locality.

+ +
+ + + + + + + + + + +
+ +

Use the "assert" function to its fullest. Check all of your +preconditions and assumptions, you never know when a bug (not necessarily even +yours) might be caught early by an assertion, which reduces debugging time +dramatically. The "<cassert>" header file is probably already +included by the header files you are using, so it doesn't cost anything to use +it.

+ +

To further assist with debugging, make sure to put some kind of error message +in the assertion statement (which is printed if the assertion is tripped). This +helps the poor debugging make sense of why an assertion is being made and +enforced, and hopefully what to do about it. Here is one complete example:

+ +
+
+inline Value *getOperand(unsigned i) { 
+  assert(i < Operands.size() && "getOperand() out of range!");
+  return Operands[i]; 
+}
+
+
+ +

Here are some examples:

+ +
+
+assert(Ty->isPointerType() && "Can't allocate a non pointer type!");
+
+assert((Opcode == Shl || Opcode == Shr) && "ShiftInst Opcode invalid!");
+
+assert(idx < getNumSuccessors() && "Successor # out of range!");
+
+assert(V1.getType() == V2.getType() && "Constant types must be identical!");
+
+assert(isa<PHINode>(Succ->front()) && "Only works on PHId BBs!");
+
+
+ +

You get the idea...

+ +

Please be aware when adding assert statements that not all compilers are aware of +the semantics of the assert. In some places, asserts are used to indicate a piece of +code that should not be reached. These are typically of the form:

+ +
+
+assert(0 && "Some helpful error message");
+
+
+ +

When used in a function that returns a value, they should be followed with a return +statement and a comment indicating that this line is never reached. This will prevent +a compiler which is unable to deduce that the assert statement never returns from +generating a warning.

+ +
+
+assert(0 && "Some helpful error message");
+// Not reached
+return 0;
+
+
+ +
+ + + + +
+

In LLVM, we prefer to explicitly prefix all identifiers from the standard +namespace with an "std::" prefix, rather than rely on +"using namespace std;".

+ +

In header files, adding a 'using namespace XXX' directive pollutes +the namespace of any source file that #includes the header. This is +clearly a bad thing.

+ +

In implementation files (e.g. .cpp files), the rule is more of a stylistic +rule, but is still important. Basically, using explicit namespace prefixes +makes the code clearer, because it is immediately obvious what facilities +are being used and where they are coming from, and more portable, because +namespace clashes cannot occur between LLVM code and other namespaces. The +portability rule is important because different standard library implementations +expose different symbols (potentially ones they shouldn't), and future revisions +to the C++ standard will add more symbols to the std namespace. As +such, we never use 'using namespace std;' in LLVM.

+ +

The exception to the general rule (i.e. it's not an exception for +the std namespace) is for implementation files. For example, all of +the code in the LLVM project implements code that lives in the 'llvm' namespace. +As such, it is ok, and actually clearer, for the .cpp files to have a 'using +namespace llvm' directive at their top, after the #includes. The +general form of this rule is that any .cpp file that implements code in any +namespace may use that namespace (and its parents'), but should not use any +others.

+ +
+ + + + +
+ +

If a class is defined in a header file and has a v-table (either it has +virtual methods or it derives from classes with virtual methods), it must +always have at least one out-of-line virtual method in the class. Without +this, the compiler will copy the vtable and RTTI into every .o file +that #includes the header, bloating .o file sizes and +increasing link times.

+ +
+ + + + +
+ +

Because C++ doesn't have a standard "foreach" loop (though it can be emulated +with macros and may be coming in C++'0x) we end up writing a lot of loops that +manually iterate from begin to end on a variety of containers or through other +data structures. One common mistake is to write a loop in this style:

+ +
+
+  BasicBlock *BB = ...
+  for (BasicBlock::iterator I = BB->begin(); I != BB->end(); ++I)
+     ... use I ...
+
+
+ +

The problem with this construct is that it evaluates "BB->end()" +every time through the loop. Instead of writing the loop like this, we strongly +prefer loops to be written so that they evaluate it once before the loop starts. +A convenient way to do this is like so:

+ +
+
+  BasicBlock *BB = ...
+  for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ++I)
+     ... use I ...
+
+
+ +

The observant may quickly point out that these two loops may have different +semantics: if the container (a basic block in this case) is being mutated, then +"BB->end()" may change its value every time through the loop and the +second loop may not in fact be correct. If you actually do depend on this +behavior, please write the loop in the first form and add a comment indicating +that you did it intentionally.

+ +

Why do we prefer the second form (when correct)? Writing the loop in the +first form has two problems: First it may be less efficient than evaluating it +at the start of the loop. In this case, the cost is probably minor: a few extra +loads every time through the loop. However, if the base expression is more +complex, then the cost can rise quickly. I've seen loops where the end +expression was actually something like: "SomeMap[x]->end()" and map +lookups really aren't cheap. By writing it in the second form consistently, you +eliminate the issue entirely and don't even have to think about it.

+ +

The second (even bigger) issue is that writing the loop in the first form +hints to the reader that the loop is mutating the container (a fact that a +comment would handily confirm!). If you write the loop in the second form, it +is immediately obvious without even looking at the body of the loop that the +container isn't being modified, which makes it easier to read the code and +understand what it does.

+ +

While the second form of the loop is a few extra keystrokes, we do strongly +prefer it.

+ +
+ + + + +
+ +

The use of #include <iostream> in library files is +hereby forbidden. The primary reason for doing this is to +support clients using LLVM libraries as part of larger systems. In particular, +we statically link LLVM into some dynamic libraries. Even if LLVM isn't used, +the static c'tors are run whenever an application start up that uses the dynamic +library. There are two problems with this:

+ +
    +
  1. The time to run the static c'tors impacts startup time of + applications—a critical time for GUI apps.
  2. +
  3. The static c'tors cause the app to pull many extra pages of memory off the + disk: both the code for the static c'tors in each .o file and the + small amount of data that gets touched. In addition, touched/dirty pages + put more pressure on the VM system on low-memory machines.
  4. +
+ +

Note that using the other stream headers (<sstream> for +example) is not problematic in this regard (just <iostream>). +However, raw_ostream provides various APIs that are better performing for almost +every use than std::ostream style APIs, so you should just use it for new +code.

+ +

New code should always +use raw_ostream for writing, or +the llvm::MemoryBuffer API for reading files.

+ +
+ + + + + +
+ +

The std::endl modifier, when used with iostreams outputs a newline +to the output stream specified. In addition to doing this, however, it also +flushes the output stream. In other words, these are equivalent:

+ +
+
+std::cout << std::endl;
+std::cout << '\n' << std::flush;
+
+
+ +

Most of the time, you probably have no reason to flush the output stream, so +it's better to use a literal '\n'.

+ +
+ + + + + +
+ +

LLVM includes a lightweight, simple, and efficient stream implementation +in llvm/Support/raw_ostream.h which provides all of the common features +of std::ostream. All new code should use raw_ostream instead +of ostream.

+ +

Unlike std::ostream, raw_ostream is not a template and can +be forward declared as class raw_ostream. Public headers should +generally not include the raw_ostream header, but use forward +declarations and constant references to raw_ostream instances.

+ +
+ + + + + + +

This section describes preferred low-level formatting guidelines along with +reasoning on why we prefer them.

+ + + + +
+ +

We prefer to put a space before a parentheses only in control flow +statements, but not in normal function call expressions and function-like +macros. For example, this is good:

+ +
+
+  if (x) ...
+  for (i = 0; i != 100; ++i) ...
+  while (llvm_rocks) ...
+
+  somefunc(42);
+  assert(3 != 4 && "laws of math are failing me");
+  
+  a = foo(42, 92) + bar(x);
+  
+
+ +

... and this is bad:

+ +
+
+  if(x) ...
+  for(i = 0; i != 100; ++i) ...
+  while(llvm_rocks) ...
+
+  somefunc (42);
+  assert (3 != 4 && "laws of math are failing me");
+  
+  a = foo (42, 92) + bar (x);
+
+
+ +

The reason for doing this is not completely arbitrary. This style makes + control flow operators stand out more, and makes expressions flow better. The + function call operator binds very tightly as a postfix operator. Putting + a space after a function name (as in the last example) makes it appear that + the code might bind the arguments of the left-hand-side of a binary operator + with the argument list of a function and the name of the right side. More + specifically, it is easy to misread the "a" example as:

+ +
+
+  a = foo ((42, 92) + bar) (x);
+
+
+ +

... when skimming through the code. By avoiding a space in a function, we +avoid this misinterpretation.

+ +
+ + + + +
+ +

Hard fast rule: Preincrement (++X) may be no slower than +postincrement (X++) and could very well be a lot faster than it. Use +preincrementation whenever possible.

+ +

The semantics of postincrement include making a copy of the value being +incremented, returning it, and then preincrementing the "work value". For +primitive types, this isn't a big deal... but for iterators, it can be a huge +issue (for example, some iterators contains stack and set objects in them... +copying an iterator could invoke the copy ctor's of these as well). In general, +get in the habit of always using preincrement, and you won't have a problem.

+ +
+ + + + +
+ +

+In general, we strive to reduce indentation where ever possible. This is useful +because we want code to fit into 80 columns without +wrapping horribly, but also because it makes it easier to understand the code. +Namespaces are a funny thing: they are often large, and we often desire to put +lots of stuff into them (so they can be large). Other times they are tiny, +because they just hold an enum or something similar. In order to balance this, +we use different approaches for small versus large namespaces. +

+ +

+If a namespace definition is small and easily fits on a screen (say, +less than 35 lines of code), then you should indent its body. Here's an +example: +

+ +
+
+namespace llvm {
+  namespace X86 {
+    /// RelocationType - An enum for the x86 relocation codes. Note that
+    /// the terminology here doesn't follow x86 convention - word means
+    /// 32-bit and dword means 64-bit.
+    enum RelocationType {
+      /// reloc_pcrel_word - PC relative relocation, add the relocated value to
+      /// the value already in memory, after we adjust it for where the PC is.
+      reloc_pcrel_word = 0,
+
+      /// reloc_picrel_word - PIC base relative relocation, add the relocated
+      /// value to the value already in memory, after we adjust it for where the
+      /// PIC base is.
+      reloc_picrel_word = 1,
+      
+      /// reloc_absolute_word, reloc_absolute_dword - Absolute relocation, just
+      /// add the relocated value to the value already in memory.
+      reloc_absolute_word = 2,
+      reloc_absolute_dword = 3
+    };
+  }
+}
+
+
+ +

Since the body is small, indenting adds value because it makes it very clear +where the namespace starts and ends, and it is easy to take the whole thing in +in one "gulp" when reading the code. If the blob of code in the namespace is +larger (as it typically is in a header in the llvm or clang namespaces), do not +indent the code, and add a comment indicating what namespace is being closed. +For example:

+ +
+
+namespace llvm {
+namespace knowledge {
+
+/// Grokable - This class represents things that Smith can have an intimate
+/// understanding of and contains the data associated with it.
+class Grokable {
+...
+public:
+  explicit Grokable() { ... }
+  virtual ~Grokable() = 0;
+  
+  ...
+
+};
+
+} // end namespace knowledge
+} // end namespace llvm
+
+
+ +

Because the class is large, we don't expect that the reader can easily +understand the entire concept in a glance, and the end of the file (where the +namespaces end) may be a long ways away from the place they open. As such, +indenting the contents of the namespace doesn't add any value, and detracts from +the readability of the class. In these cases it is best to not indent +the contents of the namespace.

+ +
+ + + + +
+ +

After talking about namespaces in general, you may be wondering about +anonymous namespaces in particular. +Anonymous namespaces are a great language feature that tells the C++ compiler +that the contents of the namespace are only visible within the current +translation unit, allowing more aggressive optimization and eliminating the +possibility of symbol name collisions. Anonymous namespaces are to C++ as +"static" is to C functions and global variables. While "static" is available +in C++, anonymous namespaces are more general: they can make entire classes +private to a file.

+ +

The problem with anonymous namespaces is that they naturally want to +encourage indentation of their body, and they reduce locality of reference: if +you see a random function definition in a C++ file, it is easy to see if it is +marked static, but seeing if it is in an anonymous namespace requires scanning +a big chunk of the file.

+ +

Because of this, we have a simple guideline: make anonymous namespaces as +small as possible, and only use them for class declarations. For example, this +is good:

+ +
+
+namespace {
+  class StringSort {
+  ...
+  public:
+    StringSort(...)
+    bool operator<(const char *RHS) const;
+  };
+} // end anonymous namespace
+
+static void Helper() { 
+  ... 
+}
+
+bool StringSort::operator<(const char *RHS) const {
+  ...
+}
+
+
+
+ +

This is bad:

+ + +
+
+namespace {
+class StringSort {
+...
+public:
+  StringSort(...)
+  bool operator<(const char *RHS) const;
+};
+
+void Helper() { 
+  ... 
+}
+
+bool StringSort::operator<(const char *RHS) const {
+  ...
+}
+
+} // end anonymous namespace
+
+
+
+ + +

This is bad specifically because if you're looking at "Helper" in the middle +of a large C++ file, that you have no immediate way to tell if it is local to +the file. When it is marked static explicitly, this is immediately obvious. +Also, there is no reason to enclose the definition of "operator<" in the +namespace just because it was declared there. +

+ +
+ + + + + + + +
+ +

A lot of these comments and recommendations have been culled for other +sources. Two particularly important books for our work are:

+ +
    + +
  1. Effective +C++ by Scott Meyers. Also +interesting and useful are "More Effective C++" and "Effective STL" by the same +author.
  2. + +
  3. Large-Scale C++ Software Design by John Lakos
  4. + +
+ +

If you get some free time, and you haven't read them: do so, you might learn +something.

+ +
+ + + +
+
+ Valid CSS + Valid HTML 4.01 + + Chris Lattner
+ LLVM Compiler Infrastructure
+ Last modified: $Date$ +
+ + + diff --git a/libclamav/c++/llvm/docs/CommandGuide/FileCheck.pod b/libclamav/c++/llvm/docs/CommandGuide/FileCheck.pod new file mode 100644 index 000000000..32516ad87 --- /dev/null +++ b/libclamav/c++/llvm/docs/CommandGuide/FileCheck.pod @@ -0,0 +1,245 @@ + +=pod + +=head1 NAME + +FileCheck - Flexible pattern matching file verifier + +=head1 SYNOPSIS + +B I [I<--check-prefix=XXX>] [I<--strict-whitespace>] + +=head1 DESCRIPTION + +B reads two files (one from standard input, and one specified on the +command line) and uses one to verify the other. This behavior is particularly +useful for the testsuite, which wants to verify that the output of some tool +(e.g. llc) contains the expected information (for example, a movsd from esp or +whatever is interesting). This is similar to using grep, but it is optimized +for matching multiple different inputs in one file in a specific order. + +The I file specifies the file that contains the patterns to +match. The file to verify is always read from standard input. + +=head1 OPTIONS + +=over + +=item B<--help> + +Print a summary of command line options. + +=item B<--check-prefix> I + +FileCheck searches the contents of I for patterns to match. By +default, these patterns are prefixed with "CHECK:". If you'd like to use a +different prefix (e.g. because the same input file is checking multiple +different tool or options), the B<--check-prefix> argument allows you to specify +a specific prefix to match. + +=item B<--strict-whitespace> + +By default, FileCheck canonicalizes input horizontal whitespace (spaces and +tabs) which causes it to ignore these differences (a space will match a tab). +The --strict-whitespace argument disables this behavior. + +=item B<-version> + +Show the version number of this program. + +=back + +=head1 EXIT STATUS + +If B verifies that the file matches the expected contents, it exits +with 0. Otherwise, if not, or if an error occurs, it will exit with a non-zero +value. + +=head1 TUTORIAL + +FileCheck is typically used from LLVM regression tests, being invoked on the RUN +line of the test. A simple example of using FileCheck from a RUN line looks +like this: + + ; RUN: llvm-as < %s | llc -march=x86-64 | FileCheck %s + +This syntax says to pipe the current file ("%s") into llvm-as, pipe that into +llc, then pipe the output of llc into FileCheck. This means that FileCheck will +be verifying its standard input (the llc output) against the filename argument +specified (the original .ll file specified by "%s"). To see how this works, +lets look at the rest of the .ll file (after the RUN line): + + define void @sub1(i32* %p, i32 %v) { + entry: + ; CHECK: sub1: + ; CHECK: subl + %0 = tail call i32 @llvm.atomic.load.sub.i32.p0i32(i32* %p, i32 %v) + ret void + } + + define void @inc4(i64* %p) { + entry: + ; CHECK: inc4: + ; CHECK: incq + %0 = tail call i64 @llvm.atomic.load.add.i64.p0i64(i64* %p, i64 1) + ret void + } + +Here you can see some "CHECK:" lines specified in comments. Now you can see +how the file is piped into llvm-as, then llc, and the machine code output is +what we are verifying. FileCheck checks the machine code output to verify that +it matches what the "CHECK:" lines specify. + +The syntax of the CHECK: lines is very simple: they are fixed strings that +must occur in order. FileCheck defaults to ignoring horizontal whitespace +differences (e.g. a space is allowed to match a tab) but otherwise, the contents +of the CHECK: line is required to match some thing in the test file exactly. + +One nice thing about FileCheck (compared to grep) is that it allows merging +test cases together into logical groups. For example, because the test above +is checking for the "sub1:" and "inc4:" labels, it will not match unless there +is a "subl" in between those labels. If it existed somewhere else in the file, +that would not count: "grep subl" matches if subl exists anywhere in the +file. + + + +=head2 The FileCheck -check-prefix option + +The FileCheck -check-prefix option allows multiple test configurations to be +driven from one .ll file. This is useful in many circumstances, for example, +testing different architectural variants with llc. Here's a simple example: + + ; RUN: llvm-as < %s | llc -mtriple=i686-apple-darwin9 -mattr=sse41 \ + ; RUN: | FileCheck %s -check-prefix=X32 + ; RUN: llvm-as < %s | llc -mtriple=x86_64-apple-darwin9 -mattr=sse41 \ + ; RUN: | FileCheck %s -check-prefix=X64 + + define <4 x i32> @pinsrd_1(i32 %s, <4 x i32> %tmp) nounwind { + %tmp1 = insertelement <4 x i32>; %tmp, i32 %s, i32 1 + ret <4 x i32> %tmp1 + ; X32: pinsrd_1: + ; X32: pinsrd $1, 4(%esp), %xmm0 + + ; X64: pinsrd_1: + ; X64: pinsrd $1, %edi, %xmm0 + } + +In this case, we're testing that we get the expected code generation with +both 32-bit and 64-bit code generation. + + + +=head2 The "CHECK-NEXT:" directive + +Sometimes you want to match lines and would like to verify that matches +happen on exactly consequtive lines with no other lines in between them. In +this case, you can use CHECK: and CHECK-NEXT: directives to specify this. If +you specified a custom check prefix, just use "-NEXT:". For +example, something like this works as you'd expect: + + define void @t2(<2 x double>* %r, <2 x double>* %A, double %B) { + %tmp3 = load <2 x double>* %A, align 16 + %tmp7 = insertelement <2 x double> undef, double %B, i32 0 + %tmp9 = shufflevector <2 x double> %tmp3, + <2 x double> %tmp7, + <2 x i32> < i32 0, i32 2 > + store <2 x double> %tmp9, <2 x double>* %r, align 16 + ret void + + ; CHECK: t2: + ; CHECK: movl 8(%esp), %eax + ; CHECK-NEXT: movapd (%eax), %xmm0 + ; CHECK-NEXT: movhpd 12(%esp), %xmm0 + ; CHECK-NEXT: movl 4(%esp), %eax + ; CHECK-NEXT: movapd %xmm0, (%eax) + ; CHECK-NEXT: ret + } + +CHECK-NEXT: directives reject the input unless there is exactly one newline +between it an the previous directive. A CHECK-NEXT cannot be the first +directive in a file. + + + +=head2 The "CHECK-NOT:" directive + +The CHECK-NOT: directive is used to verify that a string doesn't occur +between two matches (or the first match and the beginning of the file). For +example, to verify that a load is removed by a transformation, a test like this +can be used: + + define i8 @coerce_offset0(i32 %V, i32* %P) { + store i32 %V, i32* %P + + %P2 = bitcast i32* %P to i8* + %P3 = getelementptr i8* %P2, i32 2 + + %A = load i8* %P3 + ret i8 %A + ; CHECK: @coerce_offset0 + ; CHECK-NOT: load + ; CHECK: ret i8 + } + + + +=head2 FileCheck Pattern Matching Syntax + +The CHECK: and CHECK-NOT: directives both take a pattern to match. For most +uses of FileCheck, fixed string matching is perfectly sufficient. For some +things, a more flexible form of matching is desired. To support this, FileCheck +allows you to specify regular expressions in matching strings, surrounded by +double braces: B<{{yourregex}}>. Because we want to use fixed string +matching for a majority of what we do, FileCheck has been designed to support +mixing and matching fixed string matching with regular expressions. This allows +you to write things like this: + + ; CHECK: movhpd {{[0-9]+}}(%esp), {{%xmm[0-7]}} + +In this case, any offset from the ESP register will be allowed, and any xmm +register will be allowed. + +Because regular expressions are enclosed with double braces, they are +visually distinct, and you don't need to use escape characters within the double +braces like you would in C. In the rare case that you want to match double +braces explicitly from the input, you can use something ugly like +B<{{[{][{]}}> as your pattern. + + + +=head2 FileCheck Variables + +It is often useful to match a pattern and then verify that it occurs again +later in the file. For codegen tests, this can be useful to allow any register, +but verify that that register is used consistently later. To do this, FileCheck +allows named variables to be defined and substituted into patterns. Here is a +simple example: + + ; CHECK: test5: + ; CHECK: notw [[REGISTER:%[a-z]+]] + ; CHECK: andw {{.*}}[[REGISTER]] + +The first check line matches a regex (%[a-z]+) and captures it into +the variables "REGISTER". The second line verifies that whatever is in REGISTER +occurs later in the file after an "andw". FileCheck variable references are +always contained in [[ ]] pairs, are named, and their names can be +formed with the regex "[a-zA-Z_][a-zA-Z0-9_]*". If a colon follows the +name, then it is a definition of the variable, if not, it is a use. + +FileCheck variables can be defined multiple times, and uses always get the +latest value. Note that variables are all read at the start of a "CHECK" line +and are all defined at the end. This means that if you have something like +"CHECK: [[XYZ:.*]]x[[XYZ]]" that the check line will read the previous +value of the XYZ variable and define a new one after the match is performed. If +you need to do something like this you can probably take advantage of the fact +that FileCheck is not actually line-oriented when it matches, this allows you to +define two separate CHECK lines that match on the same line. + + + +=head1 AUTHORS + +Maintained by The LLVM Team (L). + +=cut diff --git a/libclamav/c++/llvm/docs/CommandGuide/Makefile b/libclamav/c++/llvm/docs/CommandGuide/Makefile new file mode 100644 index 000000000..3b6518310 --- /dev/null +++ b/libclamav/c++/llvm/docs/CommandGuide/Makefile @@ -0,0 +1,103 @@ +##===- docs/CommandGuide/Makefile --------------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +ifdef BUILD_FOR_WEBSITE +# This special case is for keeping the CommandGuide on the LLVM web site +# up to date automatically as the documents are checked in. It must build +# the POD files to HTML only and keep them in the src directories. It must also +# build in an unconfigured tree, hence the ifdef. To use this, run +# make -s BUILD_FOR_WEBSITE=1 inside the cvs commit script. +SRC_DOC_DIR= +DST_HTML_DIR=html/ +DST_MAN_DIR=man/man1/ +DST_PS_DIR=ps/ + +# If we are in BUILD_FOR_WEBSITE mode, default to the all target. +all:: html man ps + +clean: + rm -f pod2htm*.*~~ $(HTML) $(MAN) $(PS) + +# To create other directories, as needed, and timestamp their creation +%/.dir: + -mkdir $* > /dev/null + date > $@ + +else + +# Otherwise, if not in BUILD_FOR_WEBSITE mode, use the project info. +LEVEL := ../.. +include $(LEVEL)/Makefile.common + +SRC_DOC_DIR=$(PROJ_SRC_DIR)/ +DST_HTML_DIR=$(PROJ_OBJ_DIR)/ +DST_MAN_DIR=$(PROJ_OBJ_DIR)/ +DST_PS_DIR=$(PROJ_OBJ_DIR)/ + +endif + + +POD := $(wildcard $(SRC_DOC_DIR)*.pod) +HTML := $(patsubst $(SRC_DOC_DIR)%.pod, $(DST_HTML_DIR)%.html, $(POD)) +MAN := $(patsubst $(SRC_DOC_DIR)%.pod, $(DST_MAN_DIR)%.1, $(POD)) +PS := $(patsubst $(SRC_DOC_DIR)%.pod, $(DST_PS_DIR)%.ps, $(POD)) + +# The set of man pages we will not install +NO_INSTALL_MANS = $(DST_MAN_DIR)FileCheck.1 + +# The set of man pages that we will install +INSTALL_MANS = $(filter-out $(NO_INSTALL_MANS), $(MAN)) + +.SUFFIXES: +.SUFFIXES: .html .pod .1 .ps + +$(DST_HTML_DIR)%.html: %.pod $(DST_HTML_DIR)/.dir + pod2html --css=manpage.css --htmlroot=. \ + --podpath=. --noindex --infile=$< --outfile=$@ --title=$* + +$(DST_MAN_DIR)%.1: %.pod $(DST_MAN_DIR)/.dir + pod2man --release=CVS --center="LLVM Command Guide" $< $@ + +$(DST_PS_DIR)%.ps: $(DST_MAN_DIR)%.1 $(DST_PS_DIR)/.dir + groff -Tps -man $< > $@ + + +html: $(HTML) +man: $(MAN) +ps: $(PS) + +EXTRA_DIST := $(POD) index.html + +clean-local:: + $(Verb) $(RM) -f pod2htm*.*~~ $(HTML) $(MAN) $(PS) + +HTML_DIR := $(PROJ_docsdir)/html/CommandGuide +MAN_DIR := $(PROJ_mandir)/man1 +PS_DIR := $(PROJ_docsdir)/ps + +install-local:: $(HTML) $(INSTALL_MANS) $(PS) + $(Echo) Installing HTML CommandGuide Documentation + $(Verb) $(MKDIR) $(HTML_DIR) + $(Verb) $(DataInstall) $(HTML) $(HTML_DIR) + $(Verb) $(DataInstall) $(PROJ_SRC_DIR)/index.html $(HTML_DIR) + $(Verb) $(DataInstall) $(PROJ_SRC_DIR)/manpage.css $(HTML_DIR) + $(Echo) Installing MAN CommandGuide Documentation + $(Verb) $(MKDIR) $(MAN_DIR) + $(Verb) $(DataInstall) $(INSTALL_MANS) $(MAN_DIR) + $(Echo) Installing PS CommandGuide Documentation + $(Verb) $(MKDIR) $(PS_DIR) + $(Verb) $(DataInstall) $(PS) $(PS_DIR) + +uninstall-local:: + $(Echo) Uninstalling CommandGuide Documentation + $(Verb) $(RM) -rf $(HTML_DIR) $(MAN_DIR) $(PS_DIR) + +printvars:: + $(Echo) "POD : " '$(POD)' + $(Echo) "HTML : " '$(HTML)' diff --git a/libclamav/c++/llvm/docs/CommandGuide/bugpoint.pod b/libclamav/c++/llvm/docs/CommandGuide/bugpoint.pod new file mode 100644 index 000000000..204ea4d3d --- /dev/null +++ b/libclamav/c++/llvm/docs/CommandGuide/bugpoint.pod @@ -0,0 +1,167 @@ +=pod + +=head1 NAME + +bugpoint - automatic test case reduction tool + +=head1 SYNOPSIS + +B [I] [I] [I] B<--args> +I + +=head1 DESCRIPTION + +B narrows down the source of problems in LLVM tools and passes. It +can be used to debug three types of failures: optimizer crashes, miscompilations +by optimizers, or bad native code generation (including problems in the static +and JIT compilers). It aims to reduce large test cases to small, useful ones. +For more information on the design and inner workings of B, as well as +advice for using bugpoint, see F in the LLVM +distribution. + +=head1 OPTIONS + +=over + +=item B<--additional-so> F + +Load the dynamic shared object F into the test program whenever it is +run. This is useful if you are debugging programs which depend on non-LLVM +libraries (such as the X or curses libraries) to run. + +=item B<--append-exit-code>=I<{true,false}> + +Append the test programs exit code to the output file so that a change in exit +code is considered a test failure. Defaults to false. + +=item B<--args> I + +Pass all arguments specified after -args to the test program whenever it runs. +Note that if any of the I start with a '-', you should use: + + bugpoint [bugpoint args] --args -- [program args] + +The "--" right after the B<--args> option tells B to consider any +options starting with C<-> to be part of the B<--args> option, not as options to +B itself. + +=item B<--tool-args> I + +Pass all arguments specified after --tool-args to the LLVM tool under test +(B, B, etc.) whenever it runs. You should use this option in the +following way: + + bugpoint [bugpoint args] --tool-args -- [tool args] + +The "--" right after the B<--tool-args> option tells B to consider any +options starting with C<-> to be part of the B<--tool-args> option, not as +options to B itself. (See B<--args>, above.) + +=item B<--safe-tool-args> I + +Pass all arguments specified after B<--safe-tool-args> to the "safe" execution +tool. + +=item B<--gcc-tool-args> I + +Pass all arguments specified after B<--gcc-tool-args> to the invocation of +B. + +=item B<--disable-{dce,simplifycfg}> + +Do not run the specified passes to clean up and reduce the size of the test +program. By default, B uses these passes internally when attempting to +reduce test programs. If you're trying to find a bug in one of these passes, +B may crash. + +=item B<--enable-valgrind> + +Use valgrind to find faults in the optimization phase. This will allow +bugpoint to find otherwise asymptomatic problems caused by memory +mis-management. + +=item B<-find-bugs> + +Continually randomize the specified passes and run them on the test program +until a bug is found or the user kills B. + +=item B<--help> + +Print a summary of command line options. + +=item B<--input> F + +Open F and redirect the standard input of the test program, whenever +it runs, to come from that file. + +=item B<--load> F + +Load the dynamic object F into B itself. This object should +register new optimization passes. Once loaded, the object will add new command +line options to enable various optimizations. To see the new complete list of +optimizations, use the B<--help> and B<--load> options together; for example: + + bugpoint --load myNewPass.so --help + +=item B<--mlimit> F + +Specifies an upper limit on memory usage of the optimization and codegen. Set +to zero to disable the limit. + +=item B<--output> F + +Whenever the test program produces output on its standard output stream, it +should match the contents of F (the "reference output"). If you +do not use this option, B will attempt to generate a reference output +by compiling the program with the "safe" backend and running it. + +=item B<--profile-info-file> F + +Profile file loaded by B<--profile-loader>. + +=item B<--run-{int,jit,llc,cbe,custom}> + +Whenever the test program is compiled, B should generate code for it +using the specified code generator. These options allow you to choose the +interpreter, the JIT compiler, the static native code compiler, the C +backend, or a custom command (see B<--exec-command>) respectively. + +=item B<--safe-{llc,cbe,custom}> + +When debugging a code generator, B should use the specified code +generator as the "safe" code generator. This is a known-good code generator +used to generate the "reference output" if it has not been provided, and to +compile portions of the program that as they are excluded from the testcase. +These options allow you to choose the +static native code compiler, the C backend, or a custom command, +(see B<--exec-command>) respectively. The interpreter and the JIT backends +cannot currently be used as the "safe" backends. + +=item B<--exec-command> I + +This option defines the command to use with the B<--run-custom> and +B<--safe-custom> options to execute the bitcode testcase. This can +be useful for cross-compilation. + +=item B<--safe-path> I + +This option defines the path to the command to execute with the +B<--safe-{int,jit,llc,cbe,custom}> +option. + +=back + +=head1 EXIT STATUS + +If B succeeds in finding a problem, it will exit with 0. Otherwise, +if an error occurs, it will exit with a non-zero value. + +=head1 SEE ALSO + +L + +=head1 AUTHOR + +Maintained by the LLVM Team (L). + +=cut diff --git a/libclamav/c++/llvm/docs/CommandGuide/html/manpage.css b/libclamav/c++/llvm/docs/CommandGuide/html/manpage.css new file mode 100644 index 000000000..b20034349 --- /dev/null +++ b/libclamav/c++/llvm/docs/CommandGuide/html/manpage.css @@ -0,0 +1,256 @@ +/* Based on http://www.perldoc.com/css/perldoc.css */ + +@import url("../llvm.css"); + +body { font-family: Arial,Helvetica; } + +blockquote { margin: 10pt; } + +h1, a { color: #336699; } + + +/*** Top menu style ****/ +.mmenuon { + font-family: Arial,Helvetica; font-weight: bold; text-decoration: none; + color: #ff6600; font-size: 10pt; + } +.mmenuoff { + font-family: Arial,Helvetica; font-weight: bold; text-decoration: none; + color: #ffffff; font-size: 10pt; +} +.cpyright { + font-family: Arial,Helvetica; font-weight: bold; text-decoration: none; + color: #ffffff; font-size: xx-small; +} +.cpyrightText { + font-family: Arial,Helvetica; font-weight: bold; text-decoration: none; + color: #ffffff; font-size: xx-small; +} +.sections { + font-family: Arial,Helvetica; font-weight: bold; text-decoration: none; + color: #336699; font-size: 11pt; +} +.dsections { + font-family: Arial,Helvetica; font-weight: bold; text-decoration: none; + color: #336699; font-size: 12pt; +} +.slink { + font-family: Arial,Helvetica; font-weight: normal; text-decoration: none; + color: #000000; font-size: 9pt; +} + +.slink2 { font-family: Arial,Helvetica; text-decoration: none; color: #336699; } + +.maintitle { + font-family: Arial,Helvetica; font-weight: bold; text-decoration: none; + color: #336699; font-size: 18pt; +} +.dblArrow { + font-family: Arial,Helvetica; font-weight: bold; text-decoration: none; + color: #336699; font-size: small; +} +.menuSec { + font-family: Arial,Helvetica; font-weight: bold; text-decoration: none; + color: #336699; font-size: small; +} + +.newstext { + font-family: Arial,Helvetica; font-size: small; +} + +.linkmenu { + font-family: Arial,Helvetica; color: #000000; font-weight: bold; + text-decoration: none; +} + +P { + font-family: Arial,Helvetica; +} + +PRE { + font-size: 10pt; +} +.quote { + font-family: Times; text-decoration: none; + color: #000000; font-size: 9pt; font-style: italic; +} +.smstd { font-family: Arial,Helvetica; color: #000000; font-size: x-small; } +.std { font-family: Arial,Helvetica; color: #000000; } +.meerkatTitle { + font-family: sans-serif; font-size: x-small; color: black; } + +.meerkatDescription { font-family: sans-serif; font-size: 10pt; color: black } +.meerkatCategory { + font-family: sans-serif; font-size: 9pt; font-weight: bold; font-style: italic; + color: brown; } +.meerkatChannel { + font-family: sans-serif; font-size: 9pt; font-style: italic; color: brown; } +.meerkatDate { font-family: sans-serif; font-size: xx-small; color: #336699; } + +.tocTitle { + font-family: Arial,Helvetica; font-weight: bold; text-decoration: none; + color: #333333; font-size: 10pt; +} + +.toc-item { + font-family: Arial,Helvetica; font-weight: bold; + color: #336699; font-size: 10pt; text-decoration: underline; +} + +.perlVersion { + font-family: Arial,Helvetica; font-weight: bold; + color: #336699; font-size: 10pt; text-decoration: none; +} + +.podTitle { + font-family: Arial,Helvetica; font-weight: bold; text-decoration: none; + color: #000000; +} + +.docTitle { + font-family: Arial,Helvetica; font-weight: bold; text-decoration: none; + color: #000000; font-size: 10pt; +} +.dotDot { + font-family: Arial,Helvetica; font-weight: bold; + color: #000000; font-size: 9pt; +} + +.docSec { + font-family: Arial,Helvetica; font-weight: normal; + color: #333333; font-size: 9pt; +} +.docVersion { + font-family: Arial,Helvetica; font-weight: bold; text-decoration: none; + color: #336699; font-size: 10pt; +} + +.docSecs-on { + font-family: Arial,Helvetica; font-weight: normal; text-decoration: none; + color: #ff0000; font-size: 10pt; +} +.docSecs-off { + font-family: Arial,Helvetica; font-weight: normal; text-decoration: none; + color: #333333; font-size: 10pt; +} + +h2 { + font-family: Arial,Helvetica; font-weight: bold; text-decoration: none; + color: #336699; font-size: medium; +} +h1 { + font-family: Verdana,Arial,Helvetica; font-weight: bold; text-decoration: none; + color: #336699; font-size: large; +} + +DL { + font-family: Arial,Helvetica; font-weight: normal; text-decoration: none; + color: #333333; font-size: 10pt; +} + +UL > LI > A { + font-family: Arial,Helvetica; font-weight: bold; + color: #336699; font-size: 10pt; +} + +.moduleInfo { + font-family: Arial,Helvetica; font-weight: bold; text-decoration: none; + color: #333333; font-size: 11pt; +} + +.moduleInfoSec { + font-family: Arial,Helvetica; font-weight: bold; text-decoration: none; + color: #336699; font-size: 10pt; +} + +.moduleInfoVal { + font-family: Arial,Helvetica; font-weight: normal; text-decoration: underline; + color: #000000; font-size: 10pt; +} + +.cpanNavTitle { + font-family: Arial,Helvetica; font-weight: bold; + color: #ffffff; font-size: 10pt; +} +.cpanNavLetter { + font-family: Arial,Helvetica; font-weight: bold; text-decoration: none; + color: #333333; font-size: 9pt; +} +.cpanCat { + font-family: Arial,Helvetica; font-weight: bold; text-decoration: none; + color: #336699; font-size: 9pt; +} + +.bttndrkblue-bkgd-top { + background-color: #225688; + background-image: url(/global/mvc_objects/images/bttndrkblue_bgtop.gif); +} +.bttndrkblue-bkgd-left { + background-color: #225688; + background-image: url(/global/mvc_objects/images/bttndrkblue_bgleft.gif); +} +.bttndrkblue-bkgd { + padding-top: 0px; + padding-bottom: 0px; + margin-bottom: 0px; + margin-top: 0px; + background-repeat: no-repeat; + background-color: #225688; + background-image: url(/global/mvc_objects/images/bttndrkblue_bgmiddle.gif); + vertical-align: top; +} +.bttndrkblue-bkgd-right { + background-color: #225688; + background-image: url(/global/mvc_objects/images/bttndrkblue_bgright.gif); +} +.bttndrkblue-bkgd-bottom { + background-color: #225688; + background-image: url(/global/mvc_objects/images/bttndrkblue_bgbottom.gif); +} +.bttndrkblue-text a { + color: #ffffff; + text-decoration: none; +} +a.bttndrkblue-text:hover { + color: #ffDD3C; + text-decoration: none; +} +.bg-ltblue { + background-color: #f0f5fa; +} + +.border-left-b { + background: #f0f5fa url(/i/corner-leftline.gif) repeat-y; +} + +.border-right-b { + background: #f0f5fa url(/i/corner-rightline.gif) repeat-y; +} + +.border-top-b { + background: #f0f5fa url(/i/corner-topline.gif) repeat-x; +} + +.border-bottom-b { + background: #f0f5fa url(/i/corner-botline.gif) repeat-x; +} + +.border-right-w { + background: #ffffff url(/i/corner-rightline.gif) repeat-y; +} + +.border-top-w { + background: #ffffff url(/i/corner-topline.gif) repeat-x; +} + +.border-bottom-w { + background: #ffffff url(/i/corner-botline.gif) repeat-x; +} + +.bg-white { + background-color: #ffffff; +} + +.border-left-w { + background: #ffffff url(/i/corner-leftline.gif) repeat-y; +} diff --git a/libclamav/c++/llvm/docs/CommandGuide/index.html b/libclamav/c++/llvm/docs/CommandGuide/index.html new file mode 100644 index 000000000..9516d075b --- /dev/null +++ b/libclamav/c++/llvm/docs/CommandGuide/index.html @@ -0,0 +1,155 @@ + + + + LLVM Command Guide + + + + +
+ LLVM Command Guide +
+ +
+ +

These documents are HTML versions of the man pages +for all of the LLVM tools. These pages describe how to use the LLVM commands +and what their options are. Note that these pages do not describe all of the +options available for all tools. To get a complete listing, pass the +--help (general options) or --help-hidden (general+debugging +options) arguments to the tool you are interested in.

+ +
+ + + + + +
+ +
    + +
  • llvm-as - + assemble a human-readable .ll file into bytecode
  • + +
  • llvm-dis - + disassemble a bytecode file into a human-readable .ll file
  • + +
  • opt - + run a series of LLVM-to-LLVM optimizations on a bytecode file
  • + +
  • llc - + generate native machine code for a bytecode file
  • + +
  • lli - + directly run a program compiled to bytecode using a JIT compiler or + interpreter
  • + +
  • llvm-link - + link several bytecode files into one
  • + +
  • llvm-ar - + archive bytecode files
  • + +
  • llvm-ranlib - + create an index for archives made with llvm-ar
  • + +
  • llvm-nm - + print out the names and types of symbols in a bytecode file
  • + +
  • llvm-prof - + format raw `llvmprof.out' data into a human-readable report
  • + +
  • llvm-ld - + general purpose linker with loadable runtime optimization support
  • + +
  • llvm-config - + print out LLVM compilation options, libraries, etc. as configured
  • + +
  • llvmc - + a generic customizable compiler driver
  • + +
+ +
+ + + + + +
+
    + +
  • llvm-gcc - + GCC-based C front-end for LLVM + +
  • llvm-g++ - + GCC-based C++ front-end for LLVM
  • + +
+ +
+ + + + + + +
+ +
    + +
  • bugpoint - + automatic test-case reducer
  • + +
  • llvm-extract - + extract a function from an LLVM bytecode file
  • + +
  • llvm-bcanalyzer - + bytecode analyzer (analyzes the binary encoding itself, not the program it + represents)
  • + +
+
+ + + + + +
+
    + +
  • FileCheck - + Flexible file verifier used extensively by the testing harness
  • +
  • tblgen - + target description reader and generator
  • +
  • lit - + LLVM Integrated Tester, for running tests
  • + +
+
+ + + +
+
+ Valid CSS + Valid HTML 4.01 + + LLVM Compiler Infrastructure
+ Last modified: $Date$ +
+ + + diff --git a/libclamav/c++/llvm/docs/CommandGuide/lit.pod b/libclamav/c++/llvm/docs/CommandGuide/lit.pod new file mode 100644 index 000000000..246fc66aa --- /dev/null +++ b/libclamav/c++/llvm/docs/CommandGuide/lit.pod @@ -0,0 +1,354 @@ +=pod + +=head1 NAME + +lit - LLVM Integrated Tester + +=head1 SYNOPSIS + +B [I] [I] + +=head1 DESCRIPTION + +B is a portable tool for executing LLVM and Clang style test suites, +summarizing their results, and providing indication of failures. B is +designed to be a lightweight testing tool with as simple a user interface as +possible. + +B should be run with one or more I to run specified on the command +line. Tests can be either individual test files or directories to search for +tests (see L<"TEST DISCOVERY">). + +Each specified test will be executed (potentially in parallel) and once all +tests have been run B will print summary information on the number of tests +which passed or failed (see L<"TEST STATUS RESULTS">). The B program will +execute with a non-zero exit code if any tests fail. + +By default B will use a succinct progress display and will only print +summary information for test failures. See L<"OUTPUT OPTIONS"> for options +controlling the B progress display and output. + +B also includes a number of options for controlling how tests are exected +(specific features may depend on the particular test format). See L<"EXECUTION +OPTIONS"> for more information. + +Finally, B also supports additional options for only running a subset of +the options specified on the command line, see L<"SELECTION OPTIONS"> for +more information. + +Users interested in the B architecture or designing a B testing +implementation should see L<"LIT ARCHITECTURE"> + +=head1 GENERAL OPTIONS + +=over + +=item B<-h>, B<--help> + +Show the B help message. + +=item B<-j> I, B<--threads>=I + +Run I tests in parallel. By default, this is automatically chose to match the +number of detected available CPUs. + +=item B<--config-prefix>=I + +Search for I and I when searching for test suites, +instead I and I. + +=item B<--param> I, B<--param> I=I + +Add a user defined parameter I with the given I (or the empty +string if not given). The meaning and use of these parameters is test suite +dependent. + +=back + +=head1 OUTPUT OPTIONS + +=over + +=item B<-q>, B<--quiet> + +Suppress any output except for test failures. + +=item B<-s>, B<--succinct> + +Show less output, for example don't show information on tests that pass. + +=item B<-v>, B<--verbose> + +Show more information on test failures, for example the entire test output +instead of just the test result. + +=item B<--no-progress-bar> + +Do not use curses based progress bar. + +=back + +=head1 EXECUTION OPTIONS + +=over + +=item B<--path>=I + +Specify an addition I to use when searching for executables in tests. + +=item B<--vg> + +Run individual tests under valgrind (using the memcheck tool). The +I<--error-exitcode> argument for valgrind is used so that valgrind failures will +cause the program to exit with a non-zero status. + +=item B<--vg-arg>=I + +When I<--vg> is used, specify an additional argument to pass to valgrind itself. + +=item B<--time-tests> + +Track the wall time individual tests take to execute and includes the results in +the summary output. This is useful for determining which tests in a test suite +take the most time to execute. Note that this option is most useful with I<-j +1>. + +=back + +=head1 SELECTION OPTIONS + +=over + +=item B<--max-tests>=I + +Run at most I tests and then terminate. + +=item B<--max-time>=I + +Spend at most I seconds (approximately) running tests and then terminate. + +=item B<--shuffle> + +Run the tests in a random order. + +=back + +=head1 ADDITIONAL OPTIONS + +=over + +=item B<--debug> + +Run B in debug mode, for debugging configuration issues and B itself. + +=item B<--show-suites> + +List the discovered test suites as part of the standard output. + +=item B<--no-tcl-as-sh> + +Run Tcl scripts internally (instead of converting to shell scripts). + +=item B<--repeat>=I + +Run each test I times. Currently this is primarily useful for timing tests, +other results are not collated in any reasonable fashion. + +=back + +=head1 EXIT STATUS + +B will exit with an exit code of 1 if there are any FAIL or XPASS +results. Otherwise, it will exit with the status 0. Other exit codes used for +non-test related failures (for example a user error or an internal program +error). + +=head1 TEST DISCOVERY + +The inputs passed to B can be either individual tests, or entire +directories or hierarchies of tests to run. When B starts up, the first +thing it does is convert the inputs into a complete list of tests to run as part +of I. + +In the B model, every test must exist inside some I. B +resolves the inputs specified on the command line to test suites by searching +upwards from the input path until it finds a I or I +file. These files serve as both a marker of test suites and as configuration +files which B loads in order to understand how to find and run the tests +inside the test suite. + +Once B has mapped the inputs into test suites it traverses the list of +inputs adding tests for individual files and recursively searching for tests in +directories. + +This behavior makes it easy to specify a subset of tests to run, while still +allowing the test suite configuration to control exactly how tests are +interpreted. In addition, B always identifies tests by the test suite they +are in, and their relative path inside the test suite. For appropriately +configured projects, this allows B to provide convenient and flexible +support for out-of-tree builds. + +=head1 TEST STATUS RESULTS + +Each test ultimately produces one of the following six results: + +=over + +=item B + +The test succeeded. + +=item B + +The test failed, but that is expected. This is used for test formats which allow +specifying that a test does not currently work, but wish to leave it in the test +suite. + +=item B + +The test succeeded, but it was expected to fail. This is used for tests which +were specified as expected to fail, but are now succeeding (generally because +the feautre they test was broken and has been fixed). + +=item B + +The test failed. + +=item B + +The test result could not be determined. For example, this occurs when the test +could not be run, the test itself is invalid, or the test was interrupted. + +=item B + +The test is not supported in this environment. This is used by test formats +which can report unsupported tests. + +=back + +Depending on the test format tests may produce additional information about +their status (generally only for failures). See the L +section for more information. + +=head1 LIT INFRASTRUCTURE + +This section describes the B testing architecture for users interested in +creating a new B testing implementation, or extending an existing one. + +B proper is primarily an infrastructure for discovering and running +arbitrary tests, and to expose a single convenient interface to these +tests. B itself doesn't contain know how to run tests, rather this logic is +defined by I. + +=head2 TEST SUITES + +As described in L<"TEST DISCOVERY">, tests are always located inside a I. Test suites serve to define the format of the tests they contain, the +logic for finding those tests, and any additional information to run the tests. + +B identifies test suites as directories containing I or +I files (see also B<--config-prefix>. Test suites are initially +discovered by recursively searching up the directory hierarchy for all the input +files passed on the command line. You can use B<--show-suites> to display the +discovered test suites at startup. + +Once a test suite is discovered, its config file is loaded. Config files +themselves are just Python modules which will be executed. When the config file +is executed, two important global variables are predefined: + +=over + +=item B + +The global B configuration object (a I instance), which defines +the builtin test formats, global configuration parameters, and other helper +routines for implementing test configurations. + +=item B + +This is the config object (a I instance) for the test suite, +which the config file is expected to populate. The following variables are also +available on the I object, some of which must be set by the config and +others are optional or predefined: + +B I<[required]> The name of the test suite, for use in reports and +diagnostics. + +B I<[required]> The test format object which will be used to +discover and run tests in the test suite. Generally this will be a builtin test +format available from the I module. + +B The filesystem path to the test suite root. For out-of-dir +builds this is the directory that will be scanned for tests. + +B For out-of-dir builds, the path to the test suite root inside +the object directory. This is where tests will be run and temporary output files +places. + +B A dictionary representing the environment to use when executing +tests in the suite. + +B For B test formats which scan directories for tests, this +variable as a list of suffixes to identify test files. Used by: I, +I. + +B For B test formats which substitute variables into a test +script, the list of substitutions to perform. Used by: I, I. + +B Mark an unsupported directory, all tests within it will be +reported as unsupported. Used by: I, I. + +B The parent configuration, this is the config object for the directory +containing the test suite, or None. + +B The config is actually cloned for every subdirectory inside a test +suite, to allow local configuration on a per-directory basis. The I +variable can be set to a Python function which will be called whenever a +configuration is cloned (for a subdirectory). The function should takes three +arguments: (1) the parent configuration, (2) the new configuration (which the +I function will generally modify), and (3) the test path to the new +directory being scanned. + +=back + +=head2 TEST DISCOVERY + +Once test suites are located, B recursively traverses the source directory +(following I) looking for tests. When B enters a +sub-directory, it first checks to see if a nest test suite is defined in that +directory. If so, it loads that test suite recursively, otherwise it +instantiates a local test config for the directory (see L<"LOCAL CONFIGURATION +FILES">). + +Tests are identified by the test suite they are contained within, and the +relative path inside that suite. Note that the relative path may not refer to an +actual file on disk; some test formats (such as I) define "virtual +tests" which have a path that contains both the path to the actual test file and +a subpath to identify the virtual test. + +=head2 LOCAL CONFIGURATION FILES + +When B loads a subdirectory in a test suite, it instantiates a local test +configuration by cloning the configuration for the parent direction -- the root +of this configuration chain will always be a test suite. Once the test +configuration is cloned B checks for a I file in the +subdirectory. If present, this file will be loaded and can be used to specialize +the configuration for each individual directory. This facility can be used to +define subdirectories of optional tests, or to change other configuration +parameters -- for example, to change the test format, or the suffixes which +identify test files. + +=head2 LIT EXAMPLE TESTS + +The B distribution contains several example implementations of test suites +in the I directory. + +=head1 SEE ALSO + +L + +=head1 AUTHOR + +Written by Daniel Dunbar and maintained by the LLVM Team (L). + +=cut diff --git a/libclamav/c++/llvm/docs/CommandGuide/llc.pod b/libclamav/c++/llvm/docs/CommandGuide/llc.pod new file mode 100644 index 000000000..8adfb682b --- /dev/null +++ b/libclamav/c++/llvm/docs/CommandGuide/llc.pod @@ -0,0 +1,193 @@ +=pod + +=head1 NAME + +llc - LLVM static compiler + +=head1 SYNOPSIS + +B [I] [I] + +=head1 DESCRIPTION + +The B command compiles LLVM source inputs into assembly language for a +specified architecture. The assembly language output can then be passed through +a native assembler and linker to generate a native executable. + +The choice of architecture for the output assembly code is automatically +determined from the input file, unless the B<-march> option is used to override +the default. + +=head1 OPTIONS + +If I is - or omitted, B reads from standard input. Otherwise, it +will from I. Inputs can be in either the LLVM assembly language +format (.ll) or the LLVM bitcode format (.bc). + +If the B<-o> option is omitted, then B will send its output to standard +output if the input is from standard input. If the B<-o> option specifies -, +then the output will also be sent to standard output. + +If no B<-o> option is specified and an input file other than - is specified, +then B creates the output filename by taking the input filename, +removing any existing F<.bc> extension, and adding a F<.s> suffix. + +Other B options are as follows: + +=head2 End-user Options + +=over + +=item B<--help> + +Print a summary of command line options. + +=item B<-O>=I + +Generate code at different optimization levels. These correspond to the I<-O0>, +I<-O1>, I<-O2>, I<-O3>, and I<-O4> optimization levels used by B and +B. + +=item B<-mtriple>=I + +Override the target triple specified in the input file with the specified +string. + +=item B<-march>=I + +Specify the architecture for which to generate assembly, overriding the target +encoded in the input file. See the output of B for a list of +valid architectures. By default this is inferred from the target triple or +autodetected to the current architecture. + +=item B<-mcpu>=I + +Specify a specific chip in the current architecture to generate code for. +By default this is inferred from the target triple and autodetected to +the current architecture. For a list of available CPUs, use: +B /dev/null | llc -march=xyz -mcpu=help> + +=item B<-mattr>=I + +Override or control specific attributes of the target, such as whether SIMD +operations are enabled or not. The default set of attributes is set by the +current CPU. For a list of available attributes, use: +B /dev/null | llc -march=xyz -mattr=help> + +=item B<--disable-fp-elim> + +Disable frame pointer elimination optimization. + +=item B<--disable-excess-fp-precision> + +Disable optimizations that may produce excess precision for floating point. +Note that this option can dramatically slow down code on some systems +(e.g. X86). + +=item B<--enable-unsafe-fp-math> + +Enable optimizations that make unsafe assumptions about IEEE math (e.g. that +addition is associative) or may not work for all input ranges. These +optimizations allow the code generator to make use of some instructions which +would otherwise not be usable (such as fsin on X86). + +=item B<--enable-correct-eh-support> + +Instruct the B pass to insert code for correct exception handling +support. This is expensive and is by default omitted for efficiency. + +=item B<--stats> + +Print statistics recorded by code-generation passes. + +=item B<--time-passes> + +Record the amount of time needed for each pass and print a report to standard +error. + +=item B<--load>=F + +Dynamically load F (a path to a dynamically shared object) that +implements an LLVM target. This will permit the target name to be used with the +B<-march> option so that code can be generated for that target. + +=back + +=head2 Tuning/Configuration Options + +=over + +=item B<--print-machineinstrs> + +Print generated machine code between compilation phases (useful for debugging). + +=item B<--regalloc>=I + +Specify the register allocator to use. The default I is I. +Valid register allocators are: + +=over + +=item I + +Very simple "always spill" register allocator + +=item I + +Local register allocator + +=item I + +Linear scan global register allocator + +=item I + +Iterative scan global register allocator + +=back + +=item B<--spiller>=I + +Specify the spiller to use for register allocators that support it. Currently +this option is used only by the linear scan register allocator. The default +I is I. Valid spillers are: + +=over + +=item I + +Simple spiller + +=item I + +Local spiller + +=back + +=back + +=head2 Intel IA-32-specific Options + +=over + +=item B<--x86-asm-syntax=att|intel> + +Specify whether to emit assembly code in AT&T syntax (the default) or intel +syntax. + +=back + +=head1 EXIT STATUS + +If B succeeds, it will exit with 0. Otherwise, if an error occurs, +it will exit with a non-zero value. + +=head1 SEE ALSO + +L + +=head1 AUTHORS + +Maintained by the LLVM Team (L). + +=cut diff --git a/libclamav/c++/llvm/docs/CommandGuide/lli.pod b/libclamav/c++/llvm/docs/CommandGuide/lli.pod new file mode 100644 index 000000000..e9fdf74fe --- /dev/null +++ b/libclamav/c++/llvm/docs/CommandGuide/lli.pod @@ -0,0 +1,216 @@ +=pod + +=head1 NAME + +lli - directly execute programs from LLVM bitcode + +=head1 SYNOPSIS + +B [I] [I] [I] + +=head1 DESCRIPTION + +B directly executes programs in LLVM bitcode format. It takes a program +in LLVM bitcode format and executes it using a just-in-time compiler, if one is +available for the current architecture, or an interpreter. B takes all of +the same code generator options as L, but they are only effective when +B is using the just-in-time compiler. + +If I is not specified, then B reads the LLVM bitcode for the +program from standard input. + +The optional I specified on the command line are passed to the program as +arguments. + +=head1 GENERAL OPTIONS + +=over + +=item B<-fake-argv0>=I + +Override the C value passed into the executing program. + +=item B<-force-interpreter>=I<{false,true}> + +If set to true, use the interpreter even if a just-in-time compiler is available +for this architecture. Defaults to false. + +=item B<-help> + +Print a summary of command line options. + +=item B<-load>=I + +Causes B to load the plugin (shared object) named I and use +it for optimization. + +=item B<-stats> + +Print statistics from the code-generation passes. This is only meaningful for +the just-in-time compiler, at present. + +=item B<-time-passes> + +Record the amount of time needed for each code-generation pass and print it to +standard error. + +=item B<-version> + +Print out the version of B and exit without doing anything else. + +=back + +=head1 TARGET OPTIONS + +=over + +=item B<-mtriple>=I + +Override the target triple specified in the input bitcode file with the +specified string. This may result in a crash if you pick an +architecture which is not compatible with the current system. + +=item B<-march>=I + +Specify the architecture for which to generate assembly, overriding the target +encoded in the bitcode file. See the output of B for a list of +valid architectures. By default this is inferred from the target triple or +autodetected to the current architecture. + +=item B<-mcpu>=I + +Specify a specific chip in the current architecture to generate code for. +By default this is inferred from the target triple and autodetected to +the current architecture. For a list of available CPUs, use: +B /dev/null | llc -march=xyz -mcpu=help> + +=item B<-mattr>=I + +Override or control specific attributes of the target, such as whether SIMD +operations are enabled or not. The default set of attributes is set by the +current CPU. For a list of available attributes, use: +B /dev/null | llc -march=xyz -mattr=help> + +=back + + +=head1 FLOATING POINT OPTIONS + +=over + +=item B<-disable-excess-fp-precision> + +Disable optimizations that may increase floating point precision. + +=item B<-enable-finite-only-fp-math> + +Enable optimizations that assumes only finite floating point math. That is, +there is no NAN or Inf values. + +=item B<-enable-unsafe-fp-math> + +Causes B to enable optimizations that may decrease floating point +precision. + +=item B<-soft-float> + +Causes B to generate software floating point library calls instead of +equivalent hardware instructions. + +=back + +=head1 CODE GENERATION OPTIONS + +=over + +=item B<-code-model>=I + +Choose the code model from: + + default: Target default code model + small: Small code model + kernel: Kernel code model + medium: Medium code model + large: Large code model + +=item B<-disable-post-RA-scheduler> + +Disable scheduling after register allocation. + +=item B<-disable-spill-fusing> + +Disable fusing of spill code into instructions. + +=item B<-enable-correct-eh-support> + +Make the -lowerinvoke pass insert expensive, but correct, EH code. + +=item B<-enable-eh> + +Exception handling should be emitted. + +=item B<-join-liveintervals> + +Coalesce copies (default=true). + +=item B<-nozero-initialized-in-bss> +Don't place zero-initialized symbols into the BSS section. + +=item B<-pre-RA-sched>=I + +Instruction schedulers available (before register allocation): + + =default: Best scheduler for the target + =none: No scheduling: breadth first sequencing + =simple: Simple two pass scheduling: minimize critical path and maximize processor utilization + =simple-noitin: Simple two pass scheduling: Same as simple except using generic latency + =list-burr: Bottom-up register reduction list scheduling + =list-tdrr: Top-down register reduction list scheduling + =list-td: Top-down list scheduler -print-machineinstrs - Print generated machine code + +=item B<-regalloc>=I + +Register allocator to use: (default = linearscan) + + =bigblock: Big-block register allocator + =linearscan: linear scan register allocator =local - local register allocator + =simple: simple register allocator + +=item B<-relocation-model>=I + +Choose relocation model from: + + =default: Target default relocation model + =static: Non-relocatable code =pic - Fully relocatable, position independent code + =dynamic-no-pic: Relocatable external references, non-relocatable code + +=item B<-spiller> + +Spiller to use: (default: local) + + =simple: simple spiller + =local: local spiller + +=item B<-x86-asm-syntax>=I + +Choose style of code to emit from X86 backend: + + =att: Emit AT&T-style assembly + =intel: Emit Intel-style assembly + +=back + +=head1 EXIT STATUS + +If B fails to load the program, it will exit with an exit code of 1. +Otherwise, it will return the exit code of the program it executes. + +=head1 SEE ALSO + +L + +=head1 AUTHOR + +Maintained by the LLVM Team (L). + +=cut diff --git a/libclamav/c++/llvm/docs/CommandGuide/llvm-ar.pod b/libclamav/c++/llvm/docs/CommandGuide/llvm-ar.pod new file mode 100644 index 000000000..63ba43f6f --- /dev/null +++ b/libclamav/c++/llvm/docs/CommandGuide/llvm-ar.pod @@ -0,0 +1,406 @@ +=pod + +=head1 NAME + +llvm-ar - LLVM archiver + +=head1 SYNOPSIS + +B [-]{dmpqrtx}[Rabfikouz] [relpos] [count] [files...] + + +=head1 DESCRIPTION + +The B command is similar to the common Unix utility, C. It +archives several files together into a single file. The intent for this is +to produce archive libraries by LLVM bitcode that can be linked into an +LLVM program. However, the archive can contain any kind of file. By default, +B generates a symbol table that makes linking faster because +only the symbol table needs to be consulted, not each individual file member +of the archive. + +The B command can be used to I both SVR4 and BSD style archive +files. However, it cannot be used to write them. While the B command +produces files that are I identical to the format used by other C +implementations, it has two significant departures in order to make the +archive appropriate for LLVM. The first departure is that B only +uses BSD4.4 style long path names (stored immediately after the header) and +never contains a string table for long names. The second departure is that the +symbol table is formated for efficient construction of an in-memory data +structure that permits rapid (red-black tree) lookups. Consequently, archives +produced with B usually won't be readable or editable with any +C implementation or useful for linking. Using the C modifier to flatten +file names will make the archive readable by other C implementations +but not for linking because the symbol table format for LLVM is unique. If an +SVR4 or BSD style archive is used with the C (replace) or C (quick +update) operations, the archive will be reconstructed in LLVM format. This +means that the string table will be dropped (in deference to BSD 4.4 long names) +and an LLVM symbol table will be added (by default). The system symbol table +will be retained. + +Here's where B departs from previous C implementations: + +=over + +=item I + +Since B is intended to archive bitcode files, the symbol table +won't make much sense to anything but LLVM. Consequently, the symbol table's +format has been simplified. It consists simply of a sequence of pairs +of a file member index number as an LSB 4byte integer and a null-terminated +string. + +=item I + +Some C implementations (SVR4) use a separate file member to record long +path names (> 15 characters). B takes the BSD 4.4 and Mac OS X +approach which is to simply store the full path name immediately preceding +the data for the file. The path name is null terminated and may contain the +slash (/) character. + +=item I + +B can compress the members of an archive to save space. The +compression used depends on what's available on the platform and what choices +the LLVM Compressor utility makes. It generally favors bzip2 but will select +between "no compression" or bzip2 depending on what makes sense for the +file's content. + +=item I + +Most C implementations do not recurse through directories but simply +ignore directories if they are presented to the program in the F +option. B, however, can recurse through directory structures and +add all the files under a directory, if requested. + +=item I + +When B prints out the verbose table of contents (C option), it +precedes the usual output with a character indicating the basic kind of +content in the file. A blank means the file is a regular file. A 'Z' means +the file is compressed. A 'B' means the file is an LLVM bitcode file. An +'S' means the file is the symbol table. + +=back + +=head1 OPTIONS + +The options to B are compatible with other C implementations. +However, there are a few modifiers (F) that are not found in other +Cs. The options to B specify a single basic operation to +perform on the archive, a variety of modifiers for that operation, the +name of the archive file, and an optional list of file names. These options +are used to determine how B should process the archive file. + +The Operations and Modifiers are explained in the sections below. The minimal +set of options is at least one operator and the name of the archive. Typically +archive files end with a C<.a> suffix, but this is not required. Following +the F comes a list of F that indicate the specific members +of the archive to operate on. If the F option is not specified, it +generally means either "none" or "all" members, depending on the operation. + +=head2 Operations + +=over + +=item d + +Delete files from the archive. No modifiers are applicable to this operation. +The F options specify which members should be removed from the +archive. It is not an error if a specified file does not appear in the archive. +If no F are specified, the archive is not modified. + +=item m[abi] + +Move files from one location in the archive to another. The F, F, and +F modifiers apply to this operation. The F will all be moved +to the location given by the modifiers. If no modifiers are used, the files +will be moved to the end of the archive. If no F are specified, the +archive is not modified. + +=item p[k] + +Print files to the standard output. The F modifier applies to this +operation. This operation simply prints the F indicated to the +standard output. If no F are specified, the entire archive is printed. +Printing bitcode files is ill-advised as they might confuse your terminal +settings. The F

operation is used. This modifier defeats the default and allows the +bitcode members to be printed. + +=item [N] + +This option is ignored by B but provided for compatibility. + +=item [o] + +When extracting files, this option will cause B to preserve the +original modification times of the files it writes. + +=item [P] + +use full path names when matching + +=item [R] + +This modifier instructions the F option to recursively process directories. +Without F, directories are ignored and only those F that refer to +files will be added to the archive. When F is used, any directories specified +with F will be scanned (recursively) to find files to be added to the +archive. Any file whose name begins with a dot will not be added. + +=item [u] + +When replacing existing files in the archive, only replace those files that have +a time stamp than the time stamp of the member in the archive. + +=item [z] + +When inserting or replacing any file in the archive, compress the file first. +This +modifier is safe to use when (previously) compressed bitcode files are added to +the archive; the compressed bitcode files will not be doubly compressed. + +=back + +=head2 Modifiers (generic) + +The modifiers below may be applied to any operation. + +=over + +=item [c] + +For all operations, B will always create the archive if it doesn't +exist. Normally, B will print a warning message indicating that the +archive is being created. Using this modifier turns off that warning. + +=item [s] + +This modifier requests that an archive index (or symbol table) be added to the +archive. This is the default mode of operation. The symbol table will contain +all the externally visible functions and global variables defined by all the +bitcode files in the archive. Using this modifier is more efficient that using +L which also creates the symbol table. + +=item [S] + +This modifier is the opposite of the F modifier. It instructs B to +not build the symbol table. If both F and F are used, the last modifier to +occur in the options will prevail. + +=item [v] + +This modifier instructs B to be verbose about what it is doing. Each +editing operation taken against the archive will produce a line of output saying +what is being done. + +=back + +=head1 STANDARDS + +The B utility is intended to provide a superset of the IEEE Std 1003.2 +(POSIX.2) functionality for C. B can read both SVR4 and BSD4.4 (or +Mac OS X) archives. If the C modifier is given to the C or C operations +then B will write SVR4 compatible archives. Without this modifier, +B will write BSD4.4 compatible archives that have long names +immediately after the header and indicated using the "#1/ddd" notation for the +name in the header. + +=head1 FILE FORMAT + +The file format for LLVM Archive files is similar to that of BSD 4.4 or Mac OSX +archive files. In fact, except for the symbol table, the C commands on those +operating systems should be able to read LLVM archive files. The details of the +file format follow. + +Each archive begins with the archive magic number which is the eight printable +characters "!\n" where \n represents the newline character (0x0A). +Following the magic number, the file is composed of even length members that +begin with an archive header and end with a \n padding character if necessary +(to make the length even). Each file member is composed of a header (defined +below), an optional newline-terminated "long file name" and the contents of +the file. + +The fields of the header are described in the items below. All fields of the +header contain only ASCII characters, are left justified and are right padded +with space characters. + +=over + +=item name - char[16] + +This field of the header provides the name of the archive member. If the name is +longer than 15 characters or contains a slash (/) character, then this field +contains C<#1/nnn> where C provides the length of the name and the C<#1/> +is literal. In this case, the actual name of the file is provided in the C +bytes immediately following the header. If the name is 15 characters or less, it +is contained directly in this field and terminated with a slash (/) character. + +=item date - char[12] + +This field provides the date of modification of the file in the form of a +decimal encoded number that provides the number of seconds since the epoch +(since 00:00:00 Jan 1, 1970) per Posix specifications. + +=item uid - char[6] + +This field provides the user id of the file encoded as a decimal ASCII string. +This field might not make much sense on non-Unix systems. On Unix, it is the +same value as the st_uid field of the stat structure returned by the stat(2) +operating system call. + +=item gid - char[6] + +This field provides the group id of the file encoded as a decimal ASCII string. +This field might not make much sense on non-Unix systems. On Unix, it is the +same value as the st_gid field of the stat structure returned by the stat(2) +operating system call. + +=item mode - char[8] + +This field provides the access mode of the file encoded as an octal ASCII +string. This field might not make much sense on non-Unix systems. On Unix, it +is the same value as the st_mode field of the stat structure returned by the +stat(2) operating system call. + +=item size - char[10] + +This field provides the size of the file, in bytes, encoded as a decimal ASCII +string. If the size field is negative (starts with a minus sign, 0x02D), then +the archive member is stored in compressed form. The first byte of the archive +member's data indicates the compression type used. A value of 0 (0x30) indicates +that no compression was used. A value of 2 (0x32) indicates that bzip2 +compression was used. + +=item fmag - char[2] + +This field is the archive file member magic number. Its content is always the +two characters back tick (0x60) and newline (0x0A). This provides some measure +utility in identifying archive files that have been corrupted. + +=back + +The LLVM symbol table has the special name "#_LLVM_SYM_TAB_#". It is presumed +that no regular archive member file will want this name. The LLVM symbol table +is simply composed of a sequence of triplets: byte offset, length of symbol, +and the symbol itself. Symbols are not null or newline terminated. Here are +the details on each of these items: + +=over + +=item offset - vbr encoded 32-bit integer + +The offset item provides the offset into the archive file where the bitcode +member is stored that is associated with the symbol. The offset value is 0 +based at the start of the first "normal" file member. To derive the actual +file offset of the member, you must add the number of bytes occupied by the file +signature (8 bytes) and the symbol tables. The value of this item is encoded +using variable bit rate encoding to reduce the size of the symbol table. +Variable bit rate encoding uses the high bit (0x80) of each byte to indicate +if there are more bytes to follow. The remaining 7 bits in each byte carry bits +from the value. The final byte does not have the high bit set. + +=item length - vbr encoded 32-bit integer + +The length item provides the length of the symbol that follows. Like this +I item, the length is variable bit rate encoded. + +=item symbol - character array + +The symbol item provides the text of the symbol that is associated with the +I. The symbol is not terminated by any character. Its length is provided +by the I field. Note that is allowed (but unwise) to use non-printing +characters (even 0x00) in the symbol. This allows for multiple encodings of +symbol names. + +=back + +=head1 EXIT STATUS + +If B succeeds, it will exit with 0. A usage error, results +in an exit code of 1. A hard (file system typically) error results in an +exit code of 2. Miscellaneous or unknown errors result in an +exit code of 3. + +=head1 SEE ALSO + +L, ar(1) + +=head1 AUTHORS + +Maintained by the LLVM Team (L). + +=cut diff --git a/libclamav/c++/llvm/docs/CommandGuide/llvm-as.pod b/libclamav/c++/llvm/docs/CommandGuide/llvm-as.pod new file mode 100644 index 000000000..045a9245b --- /dev/null +++ b/libclamav/c++/llvm/docs/CommandGuide/llvm-as.pod @@ -0,0 +1,77 @@ +=pod + +=head1 NAME + +llvm-as - LLVM assembler + +=head1 SYNOPSIS + +B [I] [I] + +=head1 DESCRIPTION + +B is the LLVM assembler. It reads a file containing human-readable +LLVM assembly language, translates it to LLVM bitcode, and writes the result +into a file or to standard output. + +If F is omitted or is C<->, then B reads its input from +standard input. + +If an output file is not specified with the B<-o> option, then +B sends its output to a file or standard output by following +these rules: + +=over + +=item * + +If the input is standard input, then the output is standard output. + +=item * + +If the input is a file that ends with C<.ll>, then the output file is of +the same name, except that the suffix is changed to C<.bc>. + +=item * + +If the input is a file that does not end with the C<.ll> suffix, then the +output file has the same name as the input file, except that the C<.bc> +suffix is appended. + +=back + +=head1 OPTIONS + +=over + +=item B<-f> + +Enable binary output on terminals. Normally, B will refuse to +write raw bitcode output if the output stream is a terminal. With this option, +B will write raw bitcode regardless of the output device. + +=item B<--help> + +Print a summary of command line options. + +=item B<-o> F + +Specify the output file name. If F is C<->, then B +sends its output to standard output. + +=back + +=head1 EXIT STATUS + +If B succeeds, it will exit with 0. Otherwise, if an error +occurs, it will exit with a non-zero value. + +=head1 SEE ALSO + +L, L + +=head1 AUTHORS + +Maintained by the LLVM Team (L). + +=cut diff --git a/libclamav/c++/llvm/docs/CommandGuide/llvm-bcanalyzer.pod b/libclamav/c++/llvm/docs/CommandGuide/llvm-bcanalyzer.pod new file mode 100644 index 000000000..f60b51382 --- /dev/null +++ b/libclamav/c++/llvm/docs/CommandGuide/llvm-bcanalyzer.pod @@ -0,0 +1,315 @@ +=pod + +=head1 NAME + +llvm-bcanalyzer - LLVM bitcode analyzer + +=head1 SYNOPSIS + +B [I] [F] + +=head1 DESCRIPTION + +The B command is a small utility for analyzing bitcode files. +The tool reads a bitcode file (such as generated with the B tool) and +produces a statistical report on the contents of the bitcode file. The tool +can also dump a low level but human readable version of the bitcode file. +This tool is probably not of much interest or utility except for those working +directly with the bitcode file format. Most LLVM users can just ignore +this tool. + +If F is omitted or is C<->, then B reads its input +from standard input. This is useful for combining the tool into a pipeline. +Output is written to the standard output. + +=head1 OPTIONS + +=over + +=item B<-nodetails> + +Causes B to abbreviate its output by writing out only a module +level summary. The details for individual functions are not displayed. + +=item B<-dump> + +Causes B to dump the bitcode in a human readable format. This +format is significantly different from LLVM assembly and provides details about +the encoding of the bitcode file. + +=item B<-verify> + +Causes B to verify the module produced by reading the +bitcode. This ensures that the statistics generated are based on a consistent +module. + +=item B<--help> + +Print a summary of command line options. + +=back + +=head1 EXIT STATUS + +If B succeeds, it will exit with 0. Otherwise, if an error +occurs, it will exit with a non-zero value, usually 1. + +=head1 SUMMARY OUTPUT DEFINITIONS + +The following items are always printed by llvm-bcanalyzer. They comprize the +summary output. + +=over + +=item B + +This just provides the name of the module for which bitcode analysis is being +generated. + +=item B + +The bitcode version (not LLVM version) of the file read by the analyzer. + +=item B + +The size, in bytes, of the entire bitcode file. + +=item B + +The size, in bytes, of the module block. Percentage is relative to File Size. + +=item B + +The size, in bytes, of all the function blocks. Percentage is relative to File +Size. + +=item B + +The size, in bytes, of the Global Types Pool. Percentage is relative to File +Size. This is the size of the definitions of all types in the bitcode file. + +=item B + +The size, in bytes, of the Constant Pool Blocks Percentage is relative to File +Size. + +=item B + +Ths size, in bytes, of the Global Variable Definitions and their initializers. +Percentage is relative to File Size. + +=item B + +The size, in bytes, of all the instruction lists in all the functions. +Percentage is relative to File Size. Note that this value is also included in +the Function Bytes. + +=item B + +The size, in bytes, of all the compaction tables in all the functions. +Percentage is relative to File Size. Note that this value is also included in +the Function Bytes. + +=item B + +The size, in bytes, of all the symbol tables in all the functions. Percentage is +relative to File Size. Note that this value is also included in the Function +Bytes. + +=item B + +The size, in bytes, of the list of dependent libraries in the module. Percentage +is relative to File Size. Note that this value is also included in the Module +Global Bytes. + +=item B + +The total number of blocks of any kind in the bitcode file. + +=item B + +The total number of function definitions in the bitcode file. + +=item B + +The total number of types defined in the Global Types Pool. + +=item B + +The total number of constants (of any type) defined in the Constant Pool. + +=item B + +The total number of basic blocks defined in all functions in the bitcode file. + +=item B + +The total number of instructions defined in all functions in the bitcode file. + +=item B + +The total number of long instructions defined in all functions in the bitcode +file. Long instructions are those taking greater than 4 bytes. Typically long +instructions are GetElementPtr with several indices, PHI nodes, and calls to +functions with large numbers of arguments. + +=item B + +The total number of operands used in all instructions in the bitcode file. + +=item B + +The total number of compaction tables in all functions in the bitcode file. + +=item B + +The total number of symbol tables in all functions in the bitcode file. + +=item B + +The total number of dependent libraries found in the bitcode file. + +=item B + +The total size of the instructions in all functions in the bitcode file. + +=item B + +The average number of bytes per instruction across all functions in the bitcode +file. This value is computed by dividing Total Instruction Size by Number Of +Instructions. + +=item B + +The maximum value used for a type's slot number. Larger slot number values take +more bytes to encode. + +=item B + +The maximum value used for a value's slot number. Larger slot number values take +more bytes to encode. + +=item B + +The average size of a Value definition (of any type). This is computed by +dividing File Size by the total number of values of any type. + +=item B + +The average size of a global definition (constants and global variables). + +=item B + +The average number of bytes per function definition. This is computed by +dividing Function Bytes by Number Of Functions. + +=item B<# of VBR 32-bit Integers> + +The total number of 32-bit integers encoded using the Variable Bit Rate +encoding scheme. + +=item B<# of VBR 64-bit Integers> + +The total number of 64-bit integers encoded using the Variable Bit Rate encoding +scheme. + +=item B<# of VBR Compressed Bytes> + +The total number of bytes consumed by the 32-bit and 64-bit integers that use +the Variable Bit Rate encoding scheme. + +=item B<# of VBR Expanded Bytes> + +The total number of bytes that would have been consumed by the 32-bit and 64-bit +integers had they not been compressed with the Variable Bit Rage encoding +scheme. + +=item B + +The total number of bytes saved by using the Variable Bit Rate encoding scheme. +The percentage is relative to # of VBR Expanded Bytes. + +=back + +=head1 DETAILED OUTPUT DEFINITIONS + +The following definitions occur only if the -nodetails option was not given. +The detailed output provides additional information on a per-function basis. + +=over + +=item B + +The type signature of the function. + +=item B + +The total number of bytes in the function's block. + +=item B + +The number of basic blocks defined by the function. + +=item B + +The number of instructions defined by the function. + +=item B + +The number of instructions using the long instruction format in the function. + +=item B + +The number of operands used by all instructions in the function. + +=item B + +The number of bytes consumed by instructions in the function. + +=item B + +The average number of bytes consumed by the instructions in the funtion. This +value is computed by dividing Instruction Size by Instructions. + +=item B + +The average number of bytes used by the function per instruction. This value is +computed by dividing Byte Size by Instructions. Note that this is not the same +as Average Instruction Size. It computes a number relative to the total function +size not just the size of the instruction list. + +=item B + +The total number of 32-bit integers found in this function (for any use). + +=item B + +The total number of 64-bit integers found in this function (for any use). + +=item B + +The total number of bytes in this function consumed by the 32-bit and 64-bit +integers that use the Variable Bit Rate encoding scheme. + +=item B + +The total number of bytes in this function that would have been consumed by +the 32-bit and 64-bit integers had they not been compressed with the Variable +Bit Rate encoding scheme. + +=item B + +The total number of bytes saved in this function by using the Variable Bit +Rate encoding scheme. The percentage is relative to # of VBR Expanded Bytes. + +=back + +=head1 SEE ALSO + +L, L + +=head1 AUTHORS + +Maintained by the LLVM Team (L). + +=cut diff --git a/libclamav/c++/llvm/docs/CommandGuide/llvm-config.pod b/libclamav/c++/llvm/docs/CommandGuide/llvm-config.pod new file mode 100644 index 000000000..06f10de22 --- /dev/null +++ b/libclamav/c++/llvm/docs/CommandGuide/llvm-config.pod @@ -0,0 +1,131 @@ +=pod + +=head1 NAME + +llvm-config - Print LLVM compilation options + +=head1 SYNOPSIS + +B I

+ +
    +
  1. Introduction
  2. + +
  3. Quick Start Guide +
      +
    1. Boolean Arguments
    2. +
    3. Argument Aliases
    4. +
    5. Selecting an alternative from a + set of possibilities
    6. +
    7. Named alternatives
    8. +
    9. Parsing a list of options
    10. +
    11. Collecting options as a set of flags
    12. +
    13. Adding freeform text to help output
    14. +
  4. + +
  5. Reference Guide +
      +
    1. Positional Arguments +
    2. + +
    3. Internal vs External Storage
    4. + +
    5. Option Attributes
    6. + +
    7. Option Modifiers +
    8. + +
    9. Top-Level Classes and Functions +
    10. + +
    11. Builtin parsers +
    12. +
  6. +
  7. Extension Guide +
      +
    1. Writing a custom parser
    2. +
    3. Exploiting external storage
    4. +
    5. Dynamically adding command line + options
    6. +
  8. +
+ +
+

Written by Chris Lattner

+
+ + + + + +
+ +

This document describes the CommandLine argument processing library. It will +show you how to use it, and what it can do. The CommandLine library uses a +declarative approach to specifying the command line options that your program +takes. By default, these options declarations implicitly hold the value parsed +for the option declared (of course this can be +changed).

+ +

Although there are a lot of command line argument parsing libraries +out there in many different languages, none of them fit well with what I needed. +By looking at the features and problems of other libraries, I designed the +CommandLine library to have the following features:

+ +
    +
  1. Speed: The CommandLine library is very quick and uses little resources. The +parsing time of the library is directly proportional to the number of arguments +parsed, not the the number of options recognized. Additionally, command line +argument values are captured transparently into user defined global variables, +which can be accessed like any other variable (and with the same +performance).
  2. + +
  3. Type Safe: As a user of CommandLine, you don't have to worry about +remembering the type of arguments that you want (is it an int? a string? a +bool? an enum?) and keep casting it around. Not only does this help prevent +error prone constructs, it also leads to dramatically cleaner source code.
  4. + +
  5. No subclasses required: To use CommandLine, you instantiate variables that +correspond to the arguments that you would like to capture, you don't subclass a +parser. This means that you don't have to write any boilerplate +code.
  6. + +
  7. Globally accessible: Libraries can specify command line arguments that are +automatically enabled in any tool that links to the library. This is possible +because the application doesn't have to keep a list of arguments to pass to +the parser. This also makes supporting dynamically +loaded options trivial.
  8. + +
  9. Cleaner: CommandLine supports enum and other types directly, meaning that +there is less error and more security built into the library. You don't have to +worry about whether your integral command line argument accidentally got +assigned a value that is not valid for your enum type.
  10. + +
  11. Powerful: The CommandLine library supports many different types of +arguments, from simple boolean flags to scalars arguments (strings, integers, enums, doubles), to lists of +arguments. This is possible because CommandLine is...
  12. + +
  13. Extensible: It is very simple to add a new argument type to CommandLine. +Simply specify the parser that you want to use with the command line option when +you declare it. Custom parsers are no problem.
  14. + +
  15. Labor Saving: The CommandLine library cuts down on the amount of grunt work +that you, the user, have to do. For example, it automatically provides a +--help option that shows the available command line options for your +tool. Additionally, it does most of the basic correctness checking for +you.
  16. + +
  17. Capable: The CommandLine library can handle lots of different forms of +options often found in real programs. For example, positional arguments, ls style grouping options (to allow processing 'ls +-lad' naturally), ld style prefix +options (to parse '-lmalloc -L/usr/lib'), and interpreter style options.
  18. + +
+ +

This document will hopefully let you jump in and start using CommandLine in +your utility quickly and painlessly. Additionally it should be a simple +reference manual to figure out how stuff works. If it is failing in some area +(or you want an extension to the library), nag the author, Chris Lattner.

+ +
+ + + + + +
+ +

This section of the manual runs through a simple CommandLine'ification of a +basic compiler tool. This is intended to show you how to jump into using the +CommandLine library in your own program, and show you some of the cool things it +can do.

+ +

To start out, you need to include the CommandLine header file into your +program:

+ +
+  #include "llvm/Support/CommandLine.h"
+
+ +

Additionally, you need to add this as the first line of your main +program:

+ +
+int main(int argc, char **argv) {
+  cl::ParseCommandLineOptions(argc, argv);
+  ...
+}
+
+ +

... which actually parses the arguments and fills in the variable +declarations.

+ +

Now that you are ready to support command line arguments, we need to tell the +system which ones we want, and what type of arguments they are. The CommandLine +library uses a declarative syntax to model command line arguments with the +global variable declarations that capture the parsed values. This means that +for every command line option that you would like to support, there should be a +global variable declaration to capture the result. For example, in a compiler, +we would like to support the Unix-standard '-o <filename>' option +to specify where to put the output. With the CommandLine library, this is +represented like this:

+ + +
+cl::opt<string> OutputFilename("o", cl::desc("Specify output filename"), cl::value_desc("filename"));
+
+ +

This declares a global variable "OutputFilename" that is used to +capture the result of the "o" argument (first parameter). We specify +that this is a simple scalar option by using the "cl::opt" template (as opposed to the "cl::list template), and tell the CommandLine library +that the data type that we are parsing is a string.

+ +

The second and third parameters (which are optional) are used to specify what +to output for the "--help" option. In this case, we get a line that +looks like this:

+ +
+USAGE: compiler [options]
+
+OPTIONS:
+  -help             - display available options (--help-hidden for more)
+  -o <filename>     - Specify output filename
+
+ +

Because we specified that the command line option should parse using the +string data type, the variable declared is automatically usable as a +real string in all contexts that a normal C++ string object may be used. For +example:

+ +
+  ...
+  std::ofstream Output(OutputFilename.c_str());
+  if (Output.good()) ...
+  ...
+
+ +

There are many different options that you can use to customize the command +line option handling library, but the above example shows the general interface +to these options. The options can be specified in any order, and are specified +with helper functions like cl::desc(...), so +there are no positional dependencies to remember. The available options are +discussed in detail in the Reference Guide.

+ +

Continuing the example, we would like to have our compiler take an input +filename as well as an output filename, but we do not want the input filename to +be specified with a hyphen (ie, not -filename.c). To support this +style of argument, the CommandLine library allows for positional arguments to be specified for the program. +These positional arguments are filled with command line parameters that are not +in option form. We use this feature like this:

+ +
+cl::opt<string> InputFilename(cl::Positional, cl::desc("<input file>"), cl::init("-"));
+
+ +

This declaration indicates that the first positional argument should be +treated as the input filename. Here we use the cl::init option to specify an initial value for the +command line option, which is used if the option is not specified (if you do not +specify a cl::init modifier for an option, then +the default constructor for the data type is used to initialize the value). +Command line options default to being optional, so if we would like to require +that the user always specify an input filename, we would add the cl::Required flag, and we could eliminate the +cl::init modifier, like this:

+ +
+cl::opt<string> InputFilename(cl::Positional, cl::desc("<input file>"), cl::Required);
+
+ +

Again, the CommandLine library does not require the options to be specified +in any particular order, so the above declaration is equivalent to:

+ +
+cl::opt<string> InputFilename(cl::Positional, cl::Required, cl::desc("<input file>"));
+
+ +

By simply adding the cl::Required flag, +the CommandLine library will automatically issue an error if the argument is not +specified, which shifts all of the command line option verification code out of +your application into the library. This is just one example of how using flags +can alter the default behaviour of the library, on a per-option basis. By +adding one of the declarations above, the --help option synopsis is now +extended to:

+ +
+USAGE: compiler [options] <input file>
+
+OPTIONS:
+  -help             - display available options (--help-hidden for more)
+  -o <filename>     - Specify output filename
+
+ +

... indicating that an input filename is expected.

+ +
+ + + + +
+ +

In addition to input and output filenames, we would like the compiler example +to support three boolean flags: "-f" to force writing binary output to +a terminal, "--quiet" to enable quiet mode, and "-q" for +backwards compatibility with some of our users. We can support these by +declaring options of boolean type like this:

+ +
+cl::opt<bool> Force ("f", cl::desc("Enable binary output on terminals"));
+cl::opt<bool> Quiet ("quiet", cl::desc("Don't print informational messages"));
+cl::opt<bool> Quiet2("q", cl::desc("Don't print informational messages"), cl::Hidden);
+
+ +

This does what you would expect: it declares three boolean variables +("Force", "Quiet", and "Quiet2") to recognize these +options. Note that the "-q" option is specified with the "cl::Hidden" flag. This modifier prevents it +from being shown by the standard "--help" output (note that it is still +shown in the "--help-hidden" output).

+ +

The CommandLine library uses a different parser +for different data types. For example, in the string case, the argument passed +to the option is copied literally into the content of the string variable... we +obviously cannot do that in the boolean case, however, so we must use a smarter +parser. In the case of the boolean parser, it allows no options (in which case +it assigns the value of true to the variable), or it allows the values +"true" or "false" to be specified, allowing any of the +following inputs:

+ +
+ compiler -f          # No value, 'Force' == true
+ compiler -f=true     # Value specified, 'Force' == true
+ compiler -f=TRUE     # Value specified, 'Force' == true
+ compiler -f=FALSE    # Value specified, 'Force' == false
+
+ +

... you get the idea. The bool parser just turns +the string values into boolean values, and rejects things like 'compiler +-f=foo'. Similarly, the float, double, and int parsers work +like you would expect, using the 'strtol' and 'strtod' C +library calls to parse the string value into the specified data type.

+ +

With the declarations above, "compiler --help" emits this:

+ +
+USAGE: compiler [options] <input file>
+
+OPTIONS:
+  -f     - Enable binary output on terminals
+  -o     - Override output filename
+  -quiet - Don't print informational messages
+  -help  - display available options (--help-hidden for more)
+
+ +

and "compiler --help-hidden" prints this:

+ +
+USAGE: compiler [options] <input file>
+
+OPTIONS:
+  -f     - Enable binary output on terminals
+  -o     - Override output filename
+  -q     - Don't print informational messages
+  -quiet - Don't print informational messages
+  -help  - display available options (--help-hidden for more)
+
+ +

This brief example has shown you how to use the 'cl::opt' class to parse simple scalar command line +arguments. In addition to simple scalar arguments, the CommandLine library also +provides primitives to support CommandLine option aliases, +and lists of options.

+ +
+ + + + +
+ +

So far, the example works well, except for the fact that we need to check the +quiet condition like this now:

+ +
+...
+  if (!Quiet && !Quiet2) printInformationalMessage(...);
+...
+
+ +

... which is a real pain! Instead of defining two values for the same +condition, we can use the "cl::alias" class to make the "-q" +option an alias for the "-quiet" option, instead of providing +a value itself:

+ +
+cl::opt<bool> Force ("f", cl::desc("Overwrite output files"));
+cl::opt<bool> Quiet ("quiet", cl::desc("Don't print informational messages"));
+cl::alias     QuietA("q", cl::desc("Alias for -quiet"), cl::aliasopt(Quiet));
+
+ +

The third line (which is the only one we modified from above) defines a +"-q" alias that updates the "Quiet" variable (as specified by +the cl::aliasopt modifier) whenever it is +specified. Because aliases do not hold state, the only thing the program has to +query is the Quiet variable now. Another nice feature of aliases is +that they automatically hide themselves from the -help output +(although, again, they are still visible in the --help-hidden +output).

+ +

Now the application code can simply use:

+ +
+...
+  if (!Quiet) printInformationalMessage(...);
+...
+
+ +

... which is much nicer! The "cl::alias" +can be used to specify an alternative name for any variable type, and has many +uses.

+ +
+ + + + +
+ +

So far we have seen how the CommandLine library handles builtin types like +std::string, bool and int, but how does it handle +things it doesn't know about, like enums or 'int*'s?

+ +

The answer is that it uses a table-driven generic parser (unless you specify +your own parser, as described in the Extension +Guide). This parser maps literal strings to whatever type is required, and +requires you to tell it what this mapping should be.

+ +

Let's say that we would like to add four optimization levels to our +optimizer, using the standard flags "-g", "-O0", +"-O1", and "-O2". We could easily implement this with boolean +options like above, but there are several problems with this strategy:

+ +
    +
  1. A user could specify more than one of the options at a time, for example, +"compiler -O3 -O2". The CommandLine library would not be able to +catch this erroneous input for us.
  2. + +
  3. We would have to test 4 different variables to see which ones are set.
  4. + +
  5. This doesn't map to the numeric levels that we want... so we cannot easily +see if some level >= "-O1" is enabled.
  6. + +
+ +

To cope with these problems, we can use an enum value, and have the +CommandLine library fill it in with the appropriate level directly, which is +used like this:

+ +
+enum OptLevel {
+  g, O1, O2, O3
+};
+
+cl::opt<OptLevel> OptimizationLevel(cl::desc("Choose optimization level:"),
+  cl::values(
+    clEnumVal(g , "No optimizations, enable debugging"),
+    clEnumVal(O1, "Enable trivial optimizations"),
+    clEnumVal(O2, "Enable default optimizations"),
+    clEnumVal(O3, "Enable expensive optimizations"),
+   clEnumValEnd));
+
+...
+  if (OptimizationLevel >= O2) doPartialRedundancyElimination(...);
+...
+
+ +

This declaration defines a variable "OptimizationLevel" of the +"OptLevel" enum type. This variable can be assigned any of the values +that are listed in the declaration (Note that the declaration list must be +terminated with the "clEnumValEnd" argument!). The CommandLine +library enforces +that the user can only specify one of the options, and it ensure that only valid +enum values can be specified. The "clEnumVal" macros ensure that the +command line arguments matched the enum values. With this option added, our +help output now is:

+ +
+USAGE: compiler [options] <input file>
+
+OPTIONS:
+  Choose optimization level:
+    -g          - No optimizations, enable debugging
+    -O1         - Enable trivial optimizations
+    -O2         - Enable default optimizations
+    -O3         - Enable expensive optimizations
+  -f            - Enable binary output on terminals
+  -help         - display available options (--help-hidden for more)
+  -o <filename> - Specify output filename
+  -quiet        - Don't print informational messages
+
+ +

In this case, it is sort of awkward that flag names correspond directly to +enum names, because we probably don't want a enum definition named "g" +in our program. Because of this, we can alternatively write this example like +this:

+ +
+enum OptLevel {
+  Debug, O1, O2, O3
+};
+
+cl::opt<OptLevel> OptimizationLevel(cl::desc("Choose optimization level:"),
+  cl::values(
+   clEnumValN(Debug, "g", "No optimizations, enable debugging"),
+    clEnumVal(O1        , "Enable trivial optimizations"),
+    clEnumVal(O2        , "Enable default optimizations"),
+    clEnumVal(O3        , "Enable expensive optimizations"),
+   clEnumValEnd));
+
+...
+  if (OptimizationLevel == Debug) outputDebugInfo(...);
+...
+
+ +

By using the "clEnumValN" macro instead of "clEnumVal", we +can directly specify the name that the flag should get. In general a direct +mapping is nice, but sometimes you can't or don't want to preserve the mapping, +which is when you would use it.

+ +
+ + + + +
+ +

Another useful argument form is a named alternative style. We shall use this +style in our compiler to specify different debug levels that can be used. +Instead of each debug level being its own switch, we want to support the +following options, of which only one can be specified at a time: +"--debug-level=none", "--debug-level=quick", +"--debug-level=detailed". To do this, we use the exact same format as +our optimization level flags, but we also specify an option name. For this +case, the code looks like this:

+ +
+enum DebugLev {
+  nodebuginfo, quick, detailed
+};
+
+// Enable Debug Options to be specified on the command line
+cl::opt<DebugLev> DebugLevel("debug_level", cl::desc("Set the debugging level:"),
+  cl::values(
+    clEnumValN(nodebuginfo, "none", "disable debug information"),
+     clEnumVal(quick,               "enable quick debug information"),
+     clEnumVal(detailed,            "enable detailed debug information"),
+    clEnumValEnd));
+
+ +

This definition defines an enumerated command line variable of type "enum +DebugLev", which works exactly the same way as before. The difference here +is just the interface exposed to the user of your program and the help output by +the "--help" option:

+ +
+USAGE: compiler [options] <input file>
+
+OPTIONS:
+  Choose optimization level:
+    -g          - No optimizations, enable debugging
+    -O1         - Enable trivial optimizations
+    -O2         - Enable default optimizations
+    -O3         - Enable expensive optimizations
+  -debug_level  - Set the debugging level:
+    =none       - disable debug information
+    =quick      - enable quick debug information
+    =detailed   - enable detailed debug information
+  -f            - Enable binary output on terminals
+  -help         - display available options (--help-hidden for more)
+  -o <filename> - Specify output filename
+  -quiet        - Don't print informational messages
+
+ +

Again, the only structural difference between the debug level declaration and +the optimization level declaration is that the debug level declaration includes +an option name ("debug_level"), which automatically changes how the +library processes the argument. The CommandLine library supports both forms so +that you can choose the form most appropriate for your application.

+ +
+ + + + +
+ +

Now that we have the standard run-of-the-mill argument types out of the way, +lets get a little wild and crazy. Lets say that we want our optimizer to accept +a list of optimizations to perform, allowing duplicates. For example, we +might want to run: "compiler -dce -constprop -inline -dce -strip". In +this case, the order of the arguments and the number of appearances is very +important. This is what the "cl::list" +template is for. First, start by defining an enum of the optimizations that you +would like to perform:

+ +
+enum Opts {
+  // 'inline' is a C++ keyword, so name it 'inlining'
+  dce, constprop, inlining, strip
+};
+
+ +

Then define your "cl::list" variable:

+ +
+cl::list<Opts> OptimizationList(cl::desc("Available Optimizations:"),
+  cl::values(
+    clEnumVal(dce               , "Dead Code Elimination"),
+    clEnumVal(constprop         , "Constant Propagation"),
+   clEnumValN(inlining, "inline", "Procedure Integration"),
+    clEnumVal(strip             , "Strip Symbols"),
+  clEnumValEnd));
+
+ +

This defines a variable that is conceptually of the type +"std::vector<enum Opts>". Thus, you can access it with standard +vector methods:

+ +
+  for (unsigned i = 0; i != OptimizationList.size(); ++i)
+    switch (OptimizationList[i])
+       ...
+
+ +

... to iterate through the list of options specified.

+ +

Note that the "cl::list" template is +completely general and may be used with any data types or other arguments that +you can use with the "cl::opt" template. One +especially useful way to use a list is to capture all of the positional +arguments together if there may be more than one specified. In the case of a +linker, for example, the linker takes several '.o' files, and needs to +capture them into a list. This is naturally specified as:

+ +
+...
+cl::list<std::string> InputFilenames(cl::Positional, cl::desc("<Input files>"), cl::OneOrMore);
+...
+
+ +

This variable works just like a "vector<string>" object. As +such, accessing the list is simple, just like above. In this example, we used +the cl::OneOrMore modifier to inform the +CommandLine library that it is an error if the user does not specify any +.o files on our command line. Again, this just reduces the amount of +checking we have to do.

+ +
+ + + + +
+ +

Instead of collecting sets of options in a list, it is also possible to +gather information for enum values in a bit vector. The represention used by +the cl::bits class is an unsigned +integer. An enum value is represented by a 0/1 in the enum's ordinal value bit +position. 1 indicating that the enum was specified, 0 otherwise. As each +specified value is parsed, the resulting enum's bit is set in the option's bit +vector:

+ +
+  bits |= 1 << (unsigned)enum;
+
+ +

Options that are specified multiple times are redundant. Any instances after +the first are discarded.

+ +

Reworking the above list example, we could replace +cl::list with cl::bits:

+ +
+cl::bits<Opts> OptimizationBits(cl::desc("Available Optimizations:"),
+  cl::values(
+    clEnumVal(dce               , "Dead Code Elimination"),
+    clEnumVal(constprop         , "Constant Propagation"),
+   clEnumValN(inlining, "inline", "Procedure Integration"),
+    clEnumVal(strip             , "Strip Symbols"),
+  clEnumValEnd));
+
+ +

To test to see if constprop was specified, we can use the +cl:bits::isSet function:

+ +
+  if (OptimizationBits.isSet(constprop)) {
+    ...
+  }
+
+ +

It's also possible to get the raw bit vector using the +cl::bits::getBits function:

+ +
+  unsigned bits = OptimizationBits.getBits();
+
+ +

Finally, if external storage is used, then the location specified must be of +type unsigned. In all other ways a cl::bits option is equivalent to a cl::list option.

+ +
+ + + + + +
+ +

As our program grows and becomes more mature, we may decide to put summary +information about what it does into the help output. The help output is styled +to look similar to a Unix man page, providing concise information about +a program. Unix man pages, however often have a description about what +the program does. To add this to your CommandLine program, simply pass a third +argument to the cl::ParseCommandLineOptions +call in main. This additional argument is then printed as the overview +information for your program, allowing you to include any additional information +that you want. For example:

+ +
+int main(int argc, char **argv) {
+  cl::ParseCommandLineOptions(argc, argv, " CommandLine compiler example\n\n"
+                              "  This program blah blah blah...\n");
+  ...
+}
+
+ +

would yield the help output:

+ +
+OVERVIEW: CommandLine compiler example
+
+  This program blah blah blah...
+
+USAGE: compiler [options] <input file>
+
+OPTIONS:
+  ...
+  -help             - display available options (--help-hidden for more)
+  -o <filename>     - Specify output filename
+
+ +
+ + + + + + +
+ +

Now that you know the basics of how to use the CommandLine library, this +section will give you the detailed information you need to tune how command line +options work, as well as information on more "advanced" command line option +processing capabilities.

+ +
+ + + + +
+ +

Positional arguments are those arguments that are not named, and are not +specified with a hyphen. Positional arguments should be used when an option is +specified by its position alone. For example, the standard Unix grep +tool takes a regular expression argument, and an optional filename to search +through (which defaults to standard input if a filename is not specified). +Using the CommandLine library, this would be specified as:

+ +
+cl::opt<string> Regex   (cl::Positional, cl::desc("<regular expression>"), cl::Required);
+cl::opt<string> Filename(cl::Positional, cl::desc("<input file>"), cl::init("-"));
+
+ +

Given these two option declarations, the --help output for our grep +replacement would look like this:

+ +
+USAGE: spiffygrep [options] <regular expression> <input file>
+
+OPTIONS:
+  -help - display available options (--help-hidden for more)
+
+ +

... and the resultant program could be used just like the standard +grep tool.

+ +

Positional arguments are sorted by their order of construction. This means +that command line options will be ordered according to how they are listed in a +.cpp file, but will not have an ordering defined if the positional arguments +are defined in multiple .cpp files. The fix for this problem is simply to +define all of your positional arguments in one .cpp file.

+ +
+ + + + + +
+ +

Sometimes you may want to specify a value to your positional argument that +starts with a hyphen (for example, searching for '-foo' in a file). At +first, you will have trouble doing this, because it will try to find an argument +named '-foo', and will fail (and single quotes will not save you). +Note that the system grep has the same problem:

+ +
+  $ spiffygrep '-foo' test.txt
+  Unknown command line argument '-foo'.  Try: spiffygrep --help'
+
+  $ grep '-foo' test.txt
+  grep: illegal option -- f
+  grep: illegal option -- o
+  grep: illegal option -- o
+  Usage: grep -hblcnsviw pattern file . . .
+
+ +

The solution for this problem is the same for both your tool and the system +version: use the '--' marker. When the user specifies '--' on +the command line, it is telling the program that all options after the +'--' should be treated as positional arguments, not options. Thus, we +can use it like this:

+ +
+  $ spiffygrep -- -foo test.txt
+    ...output...
+
+ +
+ + + +
+

Sometimes an option can affect or modify the meaning of another option. For + example, consider gcc's -x LANG option. This tells + gcc to ignore the suffix of subsequent positional arguments and force + the file to be interpreted as if it contained source code in language + LANG. In order to handle this properly, you need to know the + absolute position of each argument, especially those in lists, so their + interaction(s) can be applied correctly. This is also useful for options like + -llibname which is actually a positional argument that starts with + a dash.

+

So, generally, the problem is that you have two cl::list variables + that interact in some way. To ensure the correct interaction, you can use the + cl::list::getPosition(optnum) method. This method returns the + absolute position (as found on the command line) of the optnum + item in the cl::list.

+

The idiom for usage is like this:

+ +
+  static cl::list<std::string> Files(cl::Positional, cl::OneOrMore);
+  static cl::list<std::string> Libraries("l", cl::ZeroOrMore);
+
+  int main(int argc, char**argv) {
+    // ...
+    std::vector<std::string>::iterator fileIt = Files.begin();
+    std::vector<std::string>::iterator libIt  = Libraries.begin();
+    unsigned libPos = 0, filePos = 0;
+    while ( 1 ) {
+      if ( libIt != Libraries.end() )
+        libPos = Libraries.getPosition( libIt - Libraries.begin() );
+      else
+        libPos = 0;
+      if ( fileIt != Files.end() )
+        filePos = Files.getPosition( fileIt - Files.begin() );
+      else
+        filePos = 0;
+
+      if ( filePos != 0 && (libPos == 0 || filePos < libPos) ) {
+        // Source File Is next
+        ++fileIt;
+      }
+      else if ( libPos != 0 && (filePos == 0 || libPos < filePos) ) {
+        // Library is next
+        ++libIt;
+      }
+      else
+        break; // we're done with the list
+    }
+  }
+ +

Note that, for compatibility reasons, the cl::opt also supports an + unsigned getPosition() option that will provide the absolute position + of that option. You can apply the same approach as above with a + cl::opt and a cl::list option as you can with two lists.

+
+ + + + +
+ +

The cl::ConsumeAfter formatting option is +used to construct programs that use "interpreter style" option processing. With +this style of option processing, all arguments specified after the last +positional argument are treated as special interpreter arguments that are not +interpreted by the command line argument.

+ +

As a concrete example, lets say we are developing a replacement for the +standard Unix Bourne shell (/bin/sh). To run /bin/sh, first +you specify options to the shell itself (like -x which turns on trace +output), then you specify the name of the script to run, then you specify +arguments to the script. These arguments to the script are parsed by the Bourne +shell command line option processor, but are not interpreted as options to the +shell itself. Using the CommandLine library, we would specify this as:

+ +
+cl::opt<string> Script(cl::Positional, cl::desc("<input script>"), cl::init("-"));
+cl::list<string>  Argv(cl::ConsumeAfter, cl::desc("<program arguments>..."));
+cl::opt<bool>    Trace("x", cl::desc("Enable trace output"));
+
+ +

which automatically provides the help output:

+ +
+USAGE: spiffysh [options] <input script> <program arguments>...
+
+OPTIONS:
+  -help - display available options (--help-hidden for more)
+  -x    - Enable trace output
+
+ +

At runtime, if we run our new shell replacement as `spiffysh -x test.sh +-a -x -y bar', the Trace variable will be set to true, the +Script variable will be set to "test.sh", and the +Argv list will contain ["-a", "-x", "-y", "bar"], because they +were specified after the last positional argument (which is the script +name).

+ +

There are several limitations to when cl::ConsumeAfter options can +be specified. For example, only one cl::ConsumeAfter can be specified +per program, there must be at least one positional +argument specified, there must not be any cl::list +positional arguments, and the cl::ConsumeAfter option should be a cl::list option.

+ +
+ + + + +
+ +

By default, all command line options automatically hold the value that they +parse from the command line. This is very convenient in the common case, +especially when combined with the ability to define command line options in the +files that use them. This is called the internal storage model.

+ +

Sometimes, however, it is nice to separate the command line option processing +code from the storage of the value parsed. For example, lets say that we have a +'-debug' option that we would like to use to enable debug information +across the entire body of our program. In this case, the boolean value +controlling the debug code should be globally accessible (in a header file, for +example) yet the command line option processing code should not be exposed to +all of these clients (requiring lots of .cpp files to #include +CommandLine.h).

+ +

To do this, set up your .h file with your option, like this for example:

+ +
+
+// DebugFlag.h - Get access to the '-debug' command line option
+//
+
+// DebugFlag - This boolean is set to true if the '-debug' command line option
+// is specified.  This should probably not be referenced directly, instead, use
+// the DEBUG macro below.
+//
+extern bool DebugFlag;
+
+// DEBUG macro - This macro should be used by code to emit debug information.
+// In the '-debug' option is specified on the command line, and if this is a
+// debug build, then the code specified as the option to the macro will be
+// executed.  Otherwise it will not be.
+#ifdef NDEBUG
+#define DEBUG(X)
+#else
+#define DEBUG(X) do { if (DebugFlag) { X; } } while (0)
+#endif
+
+
+ +

This allows clients to blissfully use the DEBUG() macro, or the +DebugFlag explicitly if they want to. Now we just need to be able to +set the DebugFlag boolean when the option is set. To do this, we pass +an additional argument to our command line argument processor, and we specify +where to fill in with the cl::location +attribute:

+ +
+
+bool DebugFlag;                  // the actual value
+static cl::opt<bool, true>       // The parser
+Debug("debug", cl::desc("Enable debug output"), cl::Hidden, cl::location(DebugFlag));
+
+
+ +

In the above example, we specify "true" as the second argument to +the cl::opt template, indicating that the +template should not maintain a copy of the value itself. In addition to this, +we specify the cl::location attribute, so +that DebugFlag is automatically set.

+ +
+ + + + +
+ +

This section describes the basic attributes that you can specify on +options.

+ +
    + +
  • The option name attribute (which is required for all options, except positional options) specifies what the option name is. +This option is specified in simple double quotes: + +
    +cl::opt<bool> Quiet("quiet");
    +
    + +
  • + +
  • The cl::desc attribute specifies a +description for the option to be shown in the --help output for the +program.
  • + +
  • The cl::value_desc attribute +specifies a string that can be used to fine tune the --help output for +a command line option. Look here for an +example.
  • + +
  • The cl::init attribute specifies an +initial value for a scalar option. If this attribute is +not specified then the command line option value defaults to the value created +by the default constructor for the type. Warning: If you specify both +cl::init and cl::location for an option, +you must specify cl::location first, so that when the +command-line parser sees cl::init, it knows where to put the +initial value. (You will get an error at runtime if you don't put them in +the right order.)
  • + +
  • The cl::location attribute where +to store the value for a parsed command line option if using external storage. +See the section on Internal vs External Storage for more +information.
  • + +
  • The cl::aliasopt attribute +specifies which option a cl::alias option is +an alias for.
  • + +
  • The cl::values attribute specifies +the string-to-value mapping to be used by the generic parser. It takes a +clEnumValEnd terminated list of (option, value, description) triplets +that +specify the option name, the value mapped to, and the description shown in the +--help for the tool. Because the generic parser is used most +frequently with enum values, two macros are often useful: + +
      + +
    1. The clEnumVal macro is used as a +nice simple way to specify a triplet for an enum. This macro automatically +makes the option name be the same as the enum name. The first option to the +macro is the enum, the second is the description for the command line +option.
    2. + +
    3. The clEnumValN macro is used to +specify macro options where the option name doesn't equal the enum name. For +this macro, the first argument is the enum value, the second is the flag name, +and the second is the description.
    4. + +
    + +You will get a compile time error if you try to use cl::values with a parser +that does not support it.
  • + +
  • The cl::multi_val +attribute specifies that this option takes has multiple values +(example: -sectalign segname sectname sectvalue). This +attribute takes one unsigned argument - the number of values for the +option. This attribute is valid only on cl::list options (and +will fail with compile error if you try to use it with other option +types). It is allowed to use all of the usual modifiers on +multi-valued options (besides cl::ValueDisallowed, +obviously).
  • + +
+ +
+ + + + +
+ +

Option modifiers are the flags and expressions that you pass into the +constructors for cl::opt and cl::list. These modifiers give you the ability to +tweak how options are parsed and how --help output is generated to fit +your application well.

+ +

These options fall into five main categories:

+ +
    +
  1. Hiding an option from --help output
  2. +
  3. Controlling the number of occurrences + required and allowed
  4. +
  5. Controlling whether or not a value must be + specified
  6. +
  7. Controlling other formatting options
  8. +
  9. Miscellaneous option modifiers
  10. +
+ +

It is not possible to specify two options from the same category (you'll get +a runtime error) to a single option, except for options in the miscellaneous +category. The CommandLine library specifies defaults for all of these settings +that are the most useful in practice and the most common, which mean that you +usually shouldn't have to worry about these.

+ +
+ + + + +
+ +

The cl::NotHidden, cl::Hidden, and +cl::ReallyHidden modifiers are used to control whether or not an option +appears in the --help and --help-hidden output for the +compiled program:

+ +
    + +
  • The cl::NotHidden modifier +(which is the default for cl::opt and cl::list options) indicates the option is to appear +in both help listings.
  • + +
  • The cl::Hidden modifier (which is the +default for cl::alias options) indicates that +the option should not appear in the --help output, but should appear in +the --help-hidden output.
  • + +
  • The cl::ReallyHidden modifier +indicates that the option should not appear in any help output.
  • + +
+ +
+ + + + +
+ +

This group of options is used to control how many time an option is allowed +(or required) to be specified on the command line of your program. Specifying a +value for this setting allows the CommandLine library to do error checking for +you.

+ +

The allowed values for this option group are:

+ +
    + +
  • The cl::Optional modifier (which +is the default for the cl::opt and cl::alias classes) indicates that your program will +allow either zero or one occurrence of the option to be specified.
  • + +
  • The cl::ZeroOrMore modifier +(which is the default for the cl::list class) +indicates that your program will allow the option to be specified zero or more +times.
  • + +
  • The cl::Required modifier +indicates that the specified option must be specified exactly one time.
  • + +
  • The cl::OneOrMore modifier +indicates that the option must be specified at least one time.
  • + +
  • The cl::ConsumeAfter modifier is described in the Positional arguments section.
  • + +
+ +

If an option is not specified, then the value of the option is equal to the +value specified by the cl::init attribute. If +the cl::init attribute is not specified, the +option value is initialized with the default constructor for the data type.

+ +

If an option is specified multiple times for an option of the cl::opt class, only the last value will be +retained.

+ +
+ + + + +
+ +

This group of options is used to control whether or not the option allows a +value to be present. In the case of the CommandLine library, a value is either +specified with an equal sign (e.g. '-index-depth=17') or as a trailing +string (e.g. '-o a.out').

+ +

The allowed values for this option group are:

+ +
    + +
  • The cl::ValueOptional modifier +(which is the default for bool typed options) specifies that it is +acceptable to have a value, or not. A boolean argument can be enabled just by +appearing on the command line, or it can have an explicit '-foo=true'. +If an option is specified with this mode, it is illegal for the value to be +provided without the equal sign. Therefore '-foo true' is illegal. To +get this behavior, you must use the cl::ValueRequired modifier.
  • + +
  • The cl::ValueRequired modifier +(which is the default for all other types except for unnamed alternatives using the generic parser) +specifies that a value must be provided. This mode informs the command line +library that if an option is not provides with an equal sign, that the next +argument provided must be the value. This allows things like '-o +a.out' to work.
  • + +
  • The cl::ValueDisallowed +modifier (which is the default for unnamed +alternatives using the generic parser) indicates that it is a runtime error +for the user to specify a value. This can be provided to disallow users from +providing options to boolean options (like '-foo=true').
  • + +
+ +

In general, the default values for this option group work just like you would +want them to. As mentioned above, you can specify the cl::ValueDisallowed modifier to a boolean +argument to restrict your command line parser. These options are mostly useful +when extending the library.

+ +
+ + + + +
+ +

The formatting option group is used to specify that the command line option +has special abilities and is otherwise different from other command line +arguments. As usual, you can only specify one of these arguments at most.

+ +
    + +
  • The cl::NormalFormatting +modifier (which is the default all options) specifies that this option is +"normal".
  • + +
  • The cl::Positional modifier +specifies that this is a positional argument that does not have a command line +option associated with it. See the Positional +Arguments section for more information.
  • + +
  • The cl::ConsumeAfter modifier +specifies that this option is used to capture "interpreter style" arguments. See this section for more information.
  • + +
  • The cl::Prefix modifier specifies +that this option prefixes its value. With 'Prefix' options, the equal sign does +not separate the value from the option name specified. Instead, the value is +everything after the prefix, including any equal sign if present. This is useful +for processing odd arguments like -lmalloc and -L/usr/lib in a +linker tool or -DNAME=value in a compiler tool. Here, the +'l', 'D' and 'L' options are normal string (or list) +options, that have the cl::Prefix +modifier added to allow the CommandLine library to recognize them. Note that +cl::Prefix options must not have the +cl::ValueDisallowed modifier +specified.
  • + +
  • The cl::Grouping modifier is used +to implement Unix-style tools (like ls) that have lots of single letter +arguments, but only require a single dash. For example, the 'ls -labF' +command actually enables four different options, all of which are single +letters. Note that cl::Grouping +options cannot have values.
  • + +
+ +

The CommandLine library does not restrict how you use the cl::Prefix or cl::Grouping modifiers, but it is possible to +specify ambiguous argument settings. Thus, it is possible to have multiple +letter options that are prefix or grouping options, and they will still work as +designed.

+ +

To do this, the CommandLine library uses a greedy algorithm to parse the +input option into (potentially multiple) prefix and grouping options. The +strategy basically looks like this:

+ +
parse(string OrigInput) { + +
    +
  1. string input = OrigInput; +
  2. if (isOption(input)) return getOption(input).parse();    // Normal option +
  3. while (!isOption(input) && !input.empty()) input.pop_back();    // Remove the last letter +
  4. if (input.empty()) return error();    // No matching option +
  5. if (getOption(input).isPrefix())
    +  return getOption(input).parse(input);
    +
  6. while (!input.empty()) {    // Must be grouping options
    +  getOption(input).parse();
    +  OrigInput.erase(OrigInput.begin(), OrigInput.begin()+input.length());
    +  input = OrigInput;
    +  while (!isOption(input) && !input.empty()) input.pop_back();
    +}
    +
  7. if (!OrigInput.empty()) error();
  8. +
+ +

}

+
+ +
+ + + + +
+ +

The miscellaneous option modifiers are the only flags where you can specify +more than one flag from the set: they are not mutually exclusive. These flags +specify boolean properties that modify the option.

+ +
    + +
  • The cl::CommaSeparated modifier +indicates that any commas specified for an option's value should be used to +split the value up into multiple values for the option. For example, these two +options are equivalent when cl::CommaSeparated is specified: +"-foo=a -foo=b -foo=c" and "-foo=a,b,c". This option only +makes sense to be used in a case where the option is allowed to accept one or +more values (i.e. it is a cl::list option).
  • + +
  • The +cl::PositionalEatsArgs modifier (which only applies to +positional arguments, and only makes sense for lists) indicates that positional +argument should consume any strings after it (including strings that start with +a "-") up until another recognized positional argument. For example, if you +have two "eating" positional arguments, "pos1" and "pos2", the +string "-pos1 -foo -bar baz -pos2 -bork" would cause the "-foo -bar +-baz" strings to be applied to the "-pos1" option and the +"-bork" string to be applied to the "-pos2" option.
  • + +
  • The cl::Sink modifier is +used to handle unknown options. If there is at least one option with +cl::Sink modifier specified, the parser passes +unrecognized option strings to it as values instead of signaling an +error. As with cl::CommaSeparated, this modifier +only makes sense with a cl::list option.
  • + +
+ +

So far, these are the only three miscellaneous option modifiers.

+ +
+ + + + +
+ +

Some systems, such as certain variants of Microsoft Windows and +some older Unices have a relatively low limit on command-line +length. It is therefore customary to use the so-called 'response +files' to circumvent this restriction. These files are mentioned on +the command-line (using the "@file") syntax. The program reads these +files and inserts the contents into argv, thereby working around the +command-line length limits. Response files are enabled by an optional +fourth argument to +cl::ParseEnvironmentOptions +and +cl::ParseCommandLineOptions. +

+ +
+ + + + + +
+ +

Despite all of the built-in flexibility, the CommandLine option library +really only consists of one function (cl::ParseCommandLineOptions) +and three main classes: cl::opt, cl::list, and cl::alias. This section describes these three +classes in detail.

+ +
+ + + + +
+ +

The cl::ParseCommandLineOptions function is designed to be called +directly from main, and is used to fill in the values of all of the +command line option variables once argc and argv are +available.

+ +

The cl::ParseCommandLineOptions function requires two parameters +(argc and argv), but may also take an optional third parameter +which holds additional extra text to emit when the +--help option is invoked, and a fourth boolean parameter that enables +response files.

+ +
+ + + + +
+ +

The cl::ParseEnvironmentOptions function has mostly the same effects +as cl::ParseCommandLineOptions, +except that it is designed to take values for options from an environment +variable, for those cases in which reading the command line is not convenient or +desired. It fills in the values of all the command line option variables just +like cl::ParseCommandLineOptions +does.

+ +

It takes four parameters: the name of the program (since argv may +not be available, it can't just look in argv[0]), the name of the +environment variable to examine, the optional +additional extra text to emit when the +--help option is invoked, and the boolean +switch that controls whether response files +should be read.

+ +

cl::ParseEnvironmentOptions will break the environment +variable's value up into words and then process them using +cl::ParseCommandLineOptions. +Note: Currently cl::ParseEnvironmentOptions does not support +quoting, so an environment variable containing -option "foo bar" will +be parsed as three words, -option, "foo, and bar", +which is different from what you would get from the shell with the same +input.

+ +
+ + + + +
+ +

The cl::SetVersionPrinter function is designed to be called +directly from main and before +cl::ParseCommandLineOptions. Its use is optional. It simply arranges +for a function to be called in response to the --version option instead +of having the CommandLine library print out the usual version string +for LLVM. This is useful for programs that are not part of LLVM but wish to use +the CommandLine facilities. Such programs should just define a small +function that takes no arguments and returns void and that prints out +whatever version information is appropriate for the program. Pass the address +of that function to cl::SetVersionPrinter to arrange for it to be +called when the --version option is given by the user.

+ +
+ + + +
+ +

The cl::opt class is the class used to represent scalar command line +options, and is the one used most of the time. It is a templated class which +can take up to three arguments (all except for the first have default values +though):

+ +
+namespace cl {
+  template <class DataType, bool ExternalStorage = false,
+            class ParserClass = parser<DataType> >
+  class opt;
+}
+
+ +

The first template argument specifies what underlying data type the command +line argument is, and is used to select a default parser implementation. The +second template argument is used to specify whether the option should contain +the storage for the option (the default) or whether external storage should be +used to contain the value parsed for the option (see Internal +vs External Storage for more information).

+ +

The third template argument specifies which parser to use. The default value +selects an instantiation of the parser class based on the underlying +data type of the option. In general, this default works well for most +applications, so this option is only used when using a custom parser.

+ +
+ + + + +
+ +

The cl::list class is the class used to represent a list of command +line options. It too is a templated class which can take up to three +arguments:

+ +
+namespace cl {
+  template <class DataType, class Storage = bool,
+            class ParserClass = parser<DataType> >
+  class list;
+}
+
+ +

This class works the exact same as the cl::opt class, except that the second argument is +the type of the external storage, not a boolean value. For this class, +the marker type 'bool' is used to indicate that internal storage should +be used.

+ +
+ + + + +
+ +

The cl::bits class is the class used to represent a list of command +line options in the form of a bit vector. It is also a templated class which +can take up to three arguments:

+ +
+namespace cl {
+  template <class DataType, class Storage = bool,
+            class ParserClass = parser<DataType> >
+  class bits;
+}
+
+ +

This class works the exact same as the cl::lists class, except that the second argument +must be of type unsigned if external storage is used.

+ +
+ + + + +
+ +

The cl::alias class is a nontemplated class that is used to form +aliases for other arguments.

+ +
+namespace cl {
+  class alias;
+}
+
+ +

The cl::aliasopt attribute should be +used to specify which option this is an alias for. Alias arguments default to +being Hidden, and use the aliased options parser to do +the conversion from string to data.

+ +
+ + + + +
+ +

The cl::extrahelp class is a nontemplated class that allows extra +help text to be printed out for the --help option.

+ +
+namespace cl {
+  struct extrahelp;
+}
+
+ +

To use the extrahelp, simply construct one with a const char* +parameter to the constructor. The text passed to the constructor will be printed +at the bottom of the help message, verbatim. Note that multiple +cl::extrahelp can be used, but this practice is discouraged. If +your tool needs to print additional help information, put all that help into a +single cl::extrahelp instance.

+

For example:

+
+  cl::extrahelp("\nADDITIONAL HELP:\n\n  This is the extra help\n");
+
+
+ + + + +
+ +

Parsers control how the string value taken from the command line is +translated into a typed value, suitable for use in a C++ program. By default, +the CommandLine library uses an instance of parser<type> if the +command line option specifies that it uses values of type 'type'. +Because of this, custom option processing is specified with specializations of +the 'parser' class.

+ +

The CommandLine library provides the following builtin parser +specializations, which are sufficient for most applications. It can, however, +also be extended to work with new data types and new ways of interpreting the +same data. See the Writing a Custom Parser for more +details on this type of library extension.

+ +
    + +
  • The generic parser<t> parser +can be used to map strings values to any data type, through the use of the cl::values property, which specifies the mapping +information. The most common use of this parser is for parsing enum values, +which allows you to use the CommandLine library for all of the error checking to +make sure that only valid enum values are specified (as opposed to accepting +arbitrary strings). Despite this, however, the generic parser class can be used +for any data type.
  • + +
  • The parser<bool> specialization +is used to convert boolean strings to a boolean value. Currently accepted +strings are "true", "TRUE", "True", "1", +"false", "FALSE", "False", and "0".
  • + +
  • The parser<boolOrDefault> + specialization is used for cases where the value is boolean, +but we also need to know whether the option was specified at all. boolOrDefault +is an enum with 3 values, BOU_UNSET, BOU_TRUE and BOU_FALSE. This parser accepts +the same strings as parser<bool>.
  • + +
  • The parser<string> +specialization simply stores the parsed string into the string value +specified. No conversion or modification of the data is performed.
  • + +
  • The parser<int> specialization +uses the C strtol function to parse the string input. As such, it will +accept a decimal number (with an optional '+' or '-' prefix) which must start +with a non-zero digit. It accepts octal numbers, which are identified with a +'0' prefix digit, and hexadecimal numbers with a prefix of +'0x' or '0X'.
  • + +
  • The parser<double> and +parser<float> specializations use the standard C +strtod function to convert floating point strings into floating point +values. As such, a broad range of string formats is supported, including +exponential notation (ex: 1.7e15) and properly supports locales. +
  • + +
+ +
+ + + + + +
+ +

Although the CommandLine library has a lot of functionality built into it +already (as discussed previously), one of its true strengths lie in its +extensibility. This section discusses how the CommandLine library works under +the covers and illustrates how to do some simple, common, extensions.

+ +
+ + + + +
+ +

One of the simplest and most common extensions is the use of a custom parser. +As discussed previously, parsers are the portion +of the CommandLine library that turns string input from the user into a +particular parsed data type, validating the input in the process.

+ +

There are two ways to use a new parser:

+ +
    + +
  1. + +

    Specialize the cl::parser template for +your custom data type.

    + +

    This approach has the advantage that users of your custom data type will +automatically use your custom parser whenever they define an option with a value +type of your data type. The disadvantage of this approach is that it doesn't +work if your fundamental data type is something that is already supported.

    + +
  2. + +
  3. + +

    Write an independent class, using it explicitly from options that need +it.

    + +

    This approach works well in situations where you would line to parse an +option using special syntax for a not-very-special data-type. The drawback of +this approach is that users of your parser have to be aware that they are using +your parser instead of the builtin ones.

    + +
  4. + +
+ +

To guide the discussion, we will discuss a custom parser that accepts file +sizes, specified with an optional unit after the numeric size. For example, we +would like to parse "102kb", "41M", "1G" into the appropriate integer value. In +this case, the underlying data type we want to parse into is +'unsigned'. We choose approach #2 above because we don't want to make +this the default for all unsigned options.

+ +

To start out, we declare our new FileSizeParser class:

+ +
+struct FileSizeParser : public cl::basic_parser<unsigned> {
+  // parse - Return true on error.
+  bool parse(cl::Option &O, const char *ArgName, const std::string &ArgValue,
+             unsigned &Val);
+};
+
+ +

Our new class inherits from the cl::basic_parser template class to +fill in the default, boiler plate code for us. We give it the data type that +we parse into, the last argument to the parse method, so that clients of +our custom parser know what object type to pass in to the parse method. (Here we +declare that we parse into 'unsigned' variables.)

+ +

For most purposes, the only method that must be implemented in a custom +parser is the parse method. The parse method is called +whenever the option is invoked, passing in the option itself, the option name, +the string to parse, and a reference to a return value. If the string to parse +is not well-formed, the parser should output an error message and return true. +Otherwise it should return false and set 'Val' to the parsed value. In +our example, we implement parse as:

+ +
+bool FileSizeParser::parse(cl::Option &O, const char *ArgName,
+                           const std::string &Arg, unsigned &Val) {
+  const char *ArgStart = Arg.c_str();
+  char *End;
+
+  // Parse integer part, leaving 'End' pointing to the first non-integer char
+  Val = (unsigned)strtol(ArgStart, &End, 0);
+
+  while (1) {
+    switch (*End++) {
+    case 0: return false;   // No error
+    case 'i':               // Ignore the 'i' in KiB if people use that
+    case 'b': case 'B':     // Ignore B suffix
+      break;
+
+    case 'g': case 'G': Val *= 1024*1024*1024; break;
+    case 'm': case 'M': Val *= 1024*1024;      break;
+    case 'k': case 'K': Val *= 1024;           break;
+
+    default:
+      // Print an error message if unrecognized character!
+      return O.error("'" + Arg + "' value invalid for file size argument!");
+    }
+  }
+}
+
+ +

This function implements a very simple parser for the kinds of strings we are +interested in. Although it has some holes (it allows "123KKK" for +example), it is good enough for this example. Note that we use the option +itself to print out the error message (the error method always returns +true) in order to get a nice error message (shown below). Now that we have our +parser class, we can use it like this:

+ +
+static cl::opt<unsigned, false, FileSizeParser>
+MFS("max-file-size", cl::desc("Maximum file size to accept"),
+    cl::value_desc("size"));
+
+ +

Which adds this to the output of our program:

+ +
+OPTIONS:
+  -help                 - display available options (--help-hidden for more)
+  ...
+  -max-file-size=<size> - Maximum file size to accept
+
+ +

And we can test that our parse works correctly now (the test program just +prints out the max-file-size argument value):

+ +
+$ ./test
+MFS: 0
+$ ./test -max-file-size=123MB
+MFS: 128974848
+$ ./test -max-file-size=3G
+MFS: 3221225472
+$ ./test -max-file-size=dog
+-max-file-size option: 'dog' value invalid for file size argument!
+
+ +

It looks like it works. The error message that we get is nice and helpful, +and we seem to accept reasonable file sizes. This wraps up the "custom parser" +tutorial.

+ +
+ + + + +
+

Several of the LLVM libraries define static cl::opt instances that + will automatically be included in any program that links with that library. + This is a feature. However, sometimes it is necessary to know the value of the + command line option outside of the library. In these cases the library does or + should provide an external storage location that is accessible to users of the + library. Examples of this include the llvm::DebugFlag exported by the + lib/Support/Debug.cpp file and the llvm::TimePassesIsEnabled + flag exported by the lib/VMCore/Pass.cpp file.

+ +

TODO: complete this section

+ +
+ + + + +
+ +

TODO: fill in this section

+ +
+ + + +
+
+ Valid CSS + Valid HTML 4.01 + + Chris Lattner
+ LLVM Compiler Infrastructure
+ Last modified: $Date$ +
+ + + diff --git a/libclamav/c++/llvm/docs/CompilerDriver.html b/libclamav/c++/llvm/docs/CompilerDriver.html new file mode 100644 index 000000000..761d6ee68 --- /dev/null +++ b/libclamav/c++/llvm/docs/CompilerDriver.html @@ -0,0 +1,735 @@ + + + + + + +Customizing LLVMC: Reference Manual + + + +
+

Customizing LLVMC: Reference Manual

+ + + +
+

Written by Mikhail Glushenkov

+
+

Introduction

+

LLVMC is a generic compiler driver, designed to be customizable and +extensible. It plays the same role for LLVM as the gcc program +does for GCC - LLVMC's job is essentially to transform a set of input +files into a set of targets depending on configuration rules and user +options. What makes LLVMC different is that these transformation rules +are completely customizable - in fact, LLVMC knows nothing about the +specifics of transformation (even the command-line options are mostly +not hard-coded) and regards the transformation structure as an +abstract graph. The structure of this graph is completely determined +by plugins, which can be either statically or dynamically linked. This +makes it possible to easily adapt LLVMC for other purposes - for +example, as a build tool for game resources.

+

Because LLVMC employs TableGen as its configuration language, you +need to be familiar with it to customize LLVMC.

+
+
+

Compiling with LLVMC

+

LLVMC tries hard to be as compatible with gcc as possible, +although there are some small differences. Most of the time, however, +you shouldn't be able to notice them:

+
+$ # This works as expected:
+$ llvmc -O3 -Wall hello.cpp
+$ ./a.out
+hello
+
+

One nice feature of LLVMC is that one doesn't have to distinguish between +different compilers for different languages (think g++ vs. gcc) - the +right toolchain is chosen automatically based on input language names (which +are, in turn, determined from file extensions). If you want to force files +ending with ".c" to compile as C++, use the -x option, just like you would +do it with gcc:

+
+$ # hello.c is really a C++ file
+$ llvmc -x c++ hello.c
+$ ./a.out
+hello
+
+

On the other hand, when using LLVMC as a linker to combine several C++ +object files you should provide the --linker option since it's +impossible for LLVMC to choose the right linker in that case:

+
+$ llvmc -c hello.cpp
+$ llvmc hello.o
+[A lot of link-time errors skipped]
+$ llvmc --linker=c++ hello.o
+$ ./a.out
+hello
+
+

By default, LLVMC uses llvm-gcc to compile the source code. It is also +possible to choose the clang compiler with the -clang option.

+
+
+

Predefined options

+

LLVMC has some built-in options that can't be overridden in the +configuration libraries:

+
    +
  • -o FILE - Output file name.
  • +
  • -x LANGUAGE - Specify the language of the following input files +until the next -x option.
  • +
  • -load PLUGIN_NAME - Load the specified plugin DLL. Example: +-load $LLVM_DIR/Release/lib/LLVMCSimple.so.
  • +
  • -v - Enable verbose mode, i.e. print out all executed commands.
  • +
  • --save-temps - Write temporary files to the current directory and do not +delete them on exit. This option can also take an argument: the +--save-temps=obj switch will write files into the directory specified with +the -o option. The --save-temps=cwd and --save-temps switches are +both synonyms for the default behaviour.
  • +
  • --temp-dir DIRECTORY - Store temporary files in the given directory. This +directory is deleted on exit unless --save-temps is specified. If +--save-temps=obj is also specified, --temp-dir is given the +precedence.
  • +
  • --check-graph - Check the compilation for common errors like mismatched +output/input language names, multiple default edges and cycles. Because of +plugins, these checks can't be performed at compile-time. Exit with code zero +if no errors were found, and return the number of found errors +otherwise. Hidden option, useful for debugging LLVMC plugins.
  • +
  • --view-graph - Show a graphical representation of the compilation graph +and exit. Requires that you have dot and gv programs installed. Hidden +option, useful for debugging LLVMC plugins.
  • +
  • --write-graph - Write a compilation-graph.dot file in the current +directory with the compilation graph description in Graphviz format (identical +to the file used by the --view-graph option). The -o option can be +used to set the output file name. Hidden option, useful for debugging LLVMC +plugins.
  • +
  • --help, --help-hidden, --version - These options have +their standard meaning.
  • +
+
+
+

Compiling LLVMC plugins

+

It's easiest to start working on your own LLVMC plugin by copying the +skeleton project which lives under $LLVMC_DIR/plugins/Simple:

+
+$ cd $LLVMC_DIR/plugins
+$ cp -r Simple MyPlugin
+$ cd MyPlugin
+$ ls
+Makefile PluginMain.cpp Simple.td
+
+

As you can see, our basic plugin consists of only two files (not +counting the build script). Simple.td contains TableGen +description of the compilation graph; its format is documented in the +following sections. PluginMain.cpp is just a helper file used to +compile the auto-generated C++ code produced from TableGen source. It +can also contain hook definitions (see below).

+

The first thing that you should do is to change the LLVMC_PLUGIN +variable in the Makefile to avoid conflicts (since this variable +is used to name the resulting library):

+
+LLVMC_PLUGIN=MyPlugin
+
+

It is also a good idea to rename Simple.td to something less +generic:

+
+$ mv Simple.td MyPlugin.td
+
+

To build your plugin as a dynamic library, just cd to its source +directory and run make. The resulting file will be called +plugin_llvmc_$(LLVMC_PLUGIN).$(DLL_EXTENSION) (in our case, +plugin_llvmc_MyPlugin.so). This library can be then loaded in with the +-load option. Example:

+
+$ cd $LLVMC_DIR/plugins/Simple
+$ make
+$ llvmc -load $LLVM_DIR/Release/lib/plugin_llvmc_Simple.so
+
+
+
+

Compiling standalone LLVMC-based drivers

+

By default, the llvmc executable consists of a driver core plus several +statically linked plugins (Base and Clang at the moment). You can +produce a standalone LLVMC-based driver executable by linking the core with your +own plugins. The recommended way to do this is by starting with the provided +Skeleton example ($LLVMC_DIR/example/Skeleton):

+
+$ cd $LLVMC_DIR/example/
+$ cp -r Skeleton mydriver
+$ cd mydriver
+$ vim Makefile
+[...]
+$ make
+
+

If you're compiling LLVM with different source and object directories, then you +must perform the following additional steps before running make:

+
+# LLVMC_SRC_DIR = $LLVM_SRC_DIR/tools/llvmc/
+# LLVMC_OBJ_DIR = $LLVM_OBJ_DIR/tools/llvmc/
+$ cp $LLVMC_SRC_DIR/example/mydriver/Makefile \
+  $LLVMC_OBJ_DIR/example/mydriver/
+$ cd $LLVMC_OBJ_DIR/example/mydriver
+$ make
+
+

Another way to do the same thing is by using the following command:

+
+$ cd $LLVMC_DIR
+$ make LLVMC_BUILTIN_PLUGINS=MyPlugin LLVMC_BASED_DRIVER_NAME=mydriver
+
+

This works with both srcdir == objdir and srcdir != objdir, but assumes that the +plugin source directory was placed under $LLVMC_DIR/plugins.

+

Sometimes, you will want a 'bare-bones' version of LLVMC that has no +built-in plugins. It can be compiled with the following command:

+
+$ cd $LLVMC_DIR
+$ make LLVMC_BUILTIN_PLUGINS=""
+
+
+
+

Customizing LLVMC: the compilation graph

+

Each TableGen configuration file should include the common +definitions:

+
+include "llvm/CompilerDriver/Common.td"
+
+

Internally, LLVMC stores information about possible source +transformations in form of a graph. Nodes in this graph represent +tools, and edges between two nodes represent a transformation path. A +special "root" node is used to mark entry points for the +transformations. LLVMC also assigns a weight to each edge (more on +this later) to choose between several alternative edges.

+

The definition of the compilation graph (see file +plugins/Base/Base.td for an example) is just a list of edges:

+
+def CompilationGraph : CompilationGraph<[
+    Edge<"root", "llvm_gcc_c">,
+    Edge<"root", "llvm_gcc_assembler">,
+    ...
+
+    Edge<"llvm_gcc_c", "llc">,
+    Edge<"llvm_gcc_cpp", "llc">,
+    ...
+
+    OptionalEdge<"llvm_gcc_c", "opt", (case (switch_on "opt"),
+                                      (inc_weight))>,
+    OptionalEdge<"llvm_gcc_cpp", "opt", (case (switch_on "opt"),
+                                              (inc_weight))>,
+    ...
+
+    OptionalEdge<"llvm_gcc_assembler", "llvm_gcc_cpp_linker",
+        (case (input_languages_contain "c++"), (inc_weight),
+              (or (parameter_equals "linker", "g++"),
+                  (parameter_equals "linker", "c++")), (inc_weight))>,
+    ...
+
+    ]>;
+
+

As you can see, the edges can be either default or optional, where +optional edges are differentiated by an additional case expression +used to calculate the weight of this edge. Notice also that we refer +to tools via their names (as strings). This makes it possible to add +edges to an existing compilation graph in plugins without having to +know about all tool definitions used in the graph.

+

The default edges are assigned a weight of 1, and optional edges get a +weight of 0 + 2*N where N is the number of tests that evaluated to +true in the case expression. It is also possible to provide an +integer parameter to inc_weight and dec_weight - in this case, +the weight is increased (or decreased) by the provided value instead +of the default 2. It is also possible to change the default weight of +an optional edge by using the default clause of the case +construct.

+

When passing an input file through the graph, LLVMC picks the edge +with the maximum weight. To avoid ambiguity, there should be only one +default edge between two nodes (with the exception of the root node, +which gets a special treatment - there you are allowed to specify one +default edge per language).

+

When multiple plugins are loaded, their compilation graphs are merged +together. Since multiple edges that have the same end nodes are not +allowed (i.e. the graph is not a multigraph), an edge defined in +several plugins will be replaced by the definition from the plugin +that was loaded last. Plugin load order can be controlled by using the +plugin priority feature described above.

+

To get a visual representation of the compilation graph (useful for +debugging), run llvmc --view-graph. You will need dot and +gsview installed for this to work properly.

+
+
+

Describing options

+

Command-line options that the plugin supports are defined by using an +OptionList:

+
+def Options : OptionList<[
+(switch_option "E", (help "Help string")),
+(alias_option "quiet", "q")
+...
+]>;
+
+

As you can see, the option list is just a list of DAGs, where each DAG +is an option description consisting of the option name and some +properties. A plugin can define more than one option list (they are +all merged together in the end), which can be handy if one wants to +separate option groups syntactically.

+
    +
  • Possible option types:

    +
    +
      +
    • switch_option - a simple boolean switch without arguments, for example +-O2 or -time. At most one occurrence is allowed.
    • +
    • parameter_option - option that takes one argument, for example +-std=c99. It is also allowed to use spaces instead of the equality +sign: -std c99. At most one occurrence is allowed.
    • +
    • parameter_list_option - same as the above, but more than one option +occurence is allowed.
    • +
    • prefix_option - same as the parameter_option, but the option name and +argument do not have to be separated. Example: -ofile. This can be also +specified as -o file; however, -o=file will be parsed incorrectly +(=file will be interpreted as option value). At most one occurrence is +allowed.
    • +
    • prefix_list_option - same as the above, but more than one occurence of +the option is allowed; example: -lm -lpthread.
    • +
    • alias_option - a special option type for creating aliases. Unlike other +option types, aliases are not allowed to have any properties besides the +aliased option name. Usage example: (alias_option "preprocess", "E")
    • +
    +
    +
  • +
  • Possible option properties:

    +
    +
      +
    • help - help string associated with this option. Used for --help +output.
    • +
    • required - this option must be specified exactly once (or, in case of +the list options without the multi_val property, at least +once). Incompatible with zero_or_one and one_or_more.
    • +
    • one_or_more - the option must be specified at least one time. Useful +only for list options in conjunction with multi_val; for ordinary lists +it is synonymous with required. Incompatible with required and +zero_or_one.
    • +
    • zero_or_one - the option can be specified zero or one times. Useful +only for list options in conjunction with multi_val. Incompatible with +required and one_or_more.
    • +
    • hidden - the description of this option will not appear in +the --help output (but will appear in the --help-hidden +output).
    • +
    • really_hidden - the option will not be mentioned in any help +output.
    • +
    • multi_val n - this option takes n arguments (can be useful in some +special cases). Usage example: (parameter_list_option "foo", (multi_val +3)); the command-line syntax is '-foo a b c'. Only list options can have +this attribute; you can, however, use the one_or_more, zero_or_one +and required properties.
    • +
    • init - this option has a default value, either a string (if it is a +parameter), or a boolean (if it is a switch; boolean constants are called +true and false). List options can't have this attribute. Usage +examples: (switch_option "foo", (init true)); (prefix_option "bar", +(init "baz")).
    • +
    • extern - this option is defined in some other plugin, see below.
    • +
    +
    +
  • +
+
+

External options

+

Sometimes, when linking several plugins together, one plugin needs to +access options defined in some other plugin. Because of the way +options are implemented, such options must be marked as +extern. This is what the extern option property is +for. Example:

+
+...
+(switch_option "E", (extern))
+...
+
+

If an external option has additional attributes besides 'extern', they are +ignored. See also the section on plugin priorities.

+
+
+
+

Conditional evaluation

+

The 'case' construct is the main means by which programmability is +achieved in LLVMC. It can be used to calculate edge weights, program +actions and modify the shell commands to be executed. The 'case' +expression is designed after the similarly-named construct in +functional languages and takes the form (case (test_1), statement_1, +(test_2), statement_2, ... (test_N), statement_N). The statements +are evaluated only if the corresponding tests evaluate to true.

+

Examples:

+
+// Edge weight calculation
+
+// Increases edge weight by 5 if "-A" is provided on the
+// command-line, and by 5 more if "-B" is also provided.
+(case
+    (switch_on "A"), (inc_weight 5),
+    (switch_on "B"), (inc_weight 5))
+
+
+// Tool command line specification
+
+// Evaluates to "cmdline1" if the option "-A" is provided on the
+// command line; to "cmdline2" if "-B" is provided;
+// otherwise to "cmdline3".
+
+(case
+    (switch_on "A"), "cmdline1",
+    (switch_on "B"), "cmdline2",
+    (default), "cmdline3")
+
+

Note the slight difference in 'case' expression handling in contexts +of edge weights and command line specification - in the second example +the value of the "B" switch is never checked when switch "A" is +enabled, and the whole expression always evaluates to "cmdline1" in +that case.

+

Case expressions can also be nested, i.e. the following is legal:

+
+(case (switch_on "E"), (case (switch_on "o"), ..., (default), ...)
+      (default), ...)
+
+

You should, however, try to avoid doing that because it hurts +readability. It is usually better to split tool descriptions and/or +use TableGen inheritance instead.

+
    +
  • Possible tests are:
      +
    • switch_on - Returns true if a given command-line switch is provided by +the user. Can be given a list as argument, in that case (switch_on ["foo", +"bar", "baz"]) is equivalent to (and (switch_on "foo"), (switch_on +"bar"), (switch_on "baz")). +Example: (switch_on "opt").
    • +
    • any_switch_on - Given a list of switch options, returns true if any of +the switches is turned on. +Example: (any_switch_on ["foo", "bar", "baz"]) is equivalent to (or +(switch_on "foo"), (switch_on "bar"), (switch_on "baz")).
    • +
    • parameter_equals - Returns true if a command-line parameter equals +a given value. +Example: (parameter_equals "W", "all").
    • +
    • element_in_list - Returns true if a command-line parameter +list contains a given value. +Example: (parameter_in_list "l", "pthread").
    • +
    • input_languages_contain - Returns true if a given language +belongs to the current input language set. +Example: (input_languages_contain "c++").
    • +
    • in_language - Evaluates to true if the input file language is equal to +the argument. At the moment works only with cmd_line and actions (on +non-join nodes). +Example: (in_language "c++").
    • +
    • not_empty - Returns true if a given option (which should be either a +parameter or a parameter list) is set by the user. Like switch_on, can +be also given a list as argument. +Example: (not_empty "o").
    • +
    • any_not_empty - Returns true if not_empty returns true for any of +the options in the list. +Example: (any_not_empty ["foo", "bar", "baz"]) is equivalent to (or +(not_empty "foo"), (not_empty "bar"), (not_empty "baz")).
    • +
    • empty - The opposite of not_empty. Equivalent to (not (not_empty +X)). Provided for convenience. Can be given a list as argument.
    • +
    • any_not_empty - Returns true if not_empty returns true for any of +the options in the list. +Example: (any_empty ["foo", "bar", "baz"]) is equivalent to (not (and +(not_empty "foo"), (not_empty "bar"), (not_empty "baz"))).
    • +
    • single_input_file - Returns true if there was only one input file +provided on the command-line. Used without arguments: +(single_input_file).
    • +
    • multiple_input_files - Equivalent to (not (single_input_file)) (the +case of zero input files is considered an error).
    • +
    • default - Always evaluates to true. Should always be the last +test in the case expression.
    • +
    • and - A standard binary logical combinator that returns true iff all of +its arguments return true. Used like this: (and (test1), (test2), +... (testN)). Nesting of and and or is allowed, but not +encouraged.
    • +
    • or - A binary logical combinator that returns true iff any of its +arguments returns true. Example: (or (test1), (test2), ... (testN)).
    • +
    • not - Standard unary logical combinator that negates its +argument. Example: (not (or (test1), (test2), ... (testN))).
    • +
    +
  • +
+
+
+

Writing a tool description

+

As was said earlier, nodes in the compilation graph represent tools, +which are described separately. A tool definition looks like this +(taken from the include/llvm/CompilerDriver/Tools.td file):

+
+def llvm_gcc_cpp : Tool<[
+    (in_language "c++"),
+    (out_language "llvm-assembler"),
+    (output_suffix "bc"),
+    (cmd_line "llvm-g++ -c $INFILE -o $OUTFILE -emit-llvm"),
+    (sink)
+    ]>;
+
+

This defines a new tool called llvm_gcc_cpp, which is an alias for +llvm-g++. As you can see, a tool definition is just a list of +properties; most of them should be self-explanatory. The sink +property means that this tool should be passed all command-line +options that aren't mentioned in the option list.

+

The complete list of all currently implemented tool properties follows.

+
    +
  • Possible tool properties:
      +
    • in_language - input language name. Can be either a string or a +list, in case the tool supports multiple input languages.
    • +
    • out_language - output language name. Multiple output languages are not +allowed.
    • +
    • output_suffix - output file suffix. Can also be changed +dynamically, see documentation on actions.
    • +
    • cmd_line - the actual command used to run the tool. You can +use $INFILE and $OUTFILE variables, output redirection +with >, hook invocations ($CALL), environment variables +(via $ENV) and the case construct.
    • +
    • join - this tool is a "join node" in the graph, i.e. it gets a +list of input files and joins them together. Used for linkers.
    • +
    • sink - all command-line options that are not handled by other +tools are passed to this tool.
    • +
    • actions - A single big case expression that specifies how +this tool reacts on command-line options (described in more detail +below).
    • +
    +
  • +
+
+

Actions

+

A tool often needs to react to command-line options, and this is +precisely what the actions property is for. The next example +illustrates this feature:

+
+def llvm_gcc_linker : Tool<[
+    (in_language "object-code"),
+    (out_language "executable"),
+    (output_suffix "out"),
+    (cmd_line "llvm-gcc $INFILE -o $OUTFILE"),
+    (join),
+    (actions (case (not_empty "L"), (forward "L"),
+                   (not_empty "l"), (forward "l"),
+                   (not_empty "dummy"),
+                             [(append_cmd "-dummy1"), (append_cmd "-dummy2")])
+    ]>;
+
+

The actions tool property is implemented on top of the omnipresent +case expression. It associates one or more different actions +with given conditions - in the example, the actions are forward, +which forwards a given option unchanged, and append_cmd, which +appends a given string to the tool execution command. Multiple actions +can be associated with a single condition by using a list of actions +(used in the example to append some dummy options). The same case +construct can also be used in the cmd_line property to modify the +tool command line.

+

The "join" property used in the example means that this tool behaves +like a linker.

+

The list of all possible actions follows.

+
    +
  • Possible actions:

    +
    +
      +
    • append_cmd - append a string to the tool invocation +command. +Example: (case (switch_on "pthread"), (append_cmd +"-lpthread"))
    • +
    • error - exit with error. +Example: (error "Mixing -c and -S is not allowed!").
    • +
    • warning - print a warning. +Example: (warning "Specifying both -O1 and -O2 is meaningless!").
    • +
    • forward - forward an option unchanged. Example: (forward "Wall").
    • +
    • forward_as - Change the name of an option, but forward the +argument unchanged. +Example: (forward_as "O0", "--disable-optimization").
    • +
    • output_suffix - modify the output suffix of this +tool. +Example: (output_suffix "i").
    • +
    • stop_compilation - stop compilation after this tool processes +its input. Used without arguments.
    • +
    • unpack_values - used for for splitting and forwarding +comma-separated lists of options, e.g. -Wa,-foo=bar,-baz is +converted to -foo=bar -baz and appended to the tool invocation +command. +Example: (unpack_values "Wa,").
    • +
    +
    +
  • +
+
+
+
+

Language map

+

If you are adding support for a new language to LLVMC, you'll need to +modify the language map, which defines mappings from file extensions +to language names. It is used to choose the proper toolchain(s) for a +given input file set. Language map definition looks like this:

+
+def LanguageMap : LanguageMap<
+    [LangToSuffixes<"c++", ["cc", "cp", "cxx", "cpp", "CPP", "c++", "C"]>,
+     LangToSuffixes<"c", ["c"]>,
+     ...
+    ]>;
+
+

For example, without those definitions the following command wouldn't work:

+
+$ llvmc hello.cpp
+llvmc: Unknown suffix: cpp
+
+

The language map entries should be added only for tools that are +linked with the root node. Since tools are not allowed to have +multiple output languages, for nodes "inside" the graph the input and +output languages should match. This is enforced at compile-time.

+
+
+

Option preprocessor

+

It is sometimes useful to run error-checking code before processing the +compilation graph. For example, if optimization options "-O1" and "-O2" are +implemented as switches, we might want to output a warning if the user invokes +the driver with both of these options enabled.

+

The OptionPreprocessor feature is reserved specially for these +occasions. Example (adapted from the built-in Base plugin):

+
+def Preprocess : OptionPreprocessor<
+(case (and (switch_on "O3"), (any_switch_on ["O0", "O1", "O2"])),
+           [(unset_option ["O0", "O1", "O2"]),
+            (warning "Multiple -O options specified, defaulted to -O3.")],
+      (and (switch_on "O2"), (any_switch_on ["O0", "O1"])),
+           (unset_option ["O0", "O1"]),
+      (and (switch_on "O1"), (switch_on "O0")),
+           (unset_option "O0"))
+>;
+
+

Here, OptionPreprocessor is used to unset all spurious optimization options +(so that they are not forwarded to the compiler).

+

OptionPreprocessor is basically a single big case expression, which is +evaluated only once right after the plugin is loaded. The only allowed actions +in OptionPreprocessor are error, warning and a special action +unset_option, which, as the name suggests, unsets a given option. For +convenience, unset_option also works on lists.

+
+
+

More advanced topics

+
+

Hooks and environment variables

+

Normally, LLVMC executes programs from the system PATH. Sometimes, +this is not sufficient: for example, we may want to specify tool paths +or names in the configuration file. This can be easily achieved via +the hooks mechanism. To write your own hooks, just add their +definitions to the PluginMain.cpp or drop a .cpp file into the +your plugin directory. Hooks should live in the hooks namespace +and have the signature std::string hooks::MyHookName ([const char* +Arg0 [ const char* Arg2 [, ...]]]). They can be used from the +cmd_line tool property:

+
+(cmd_line "$CALL(MyHook)/path/to/file -o $CALL(AnotherHook)")
+
+

To pass arguments to hooks, use the following syntax:

+
+(cmd_line "$CALL(MyHook, 'Arg1', 'Arg2', 'Arg # 3')/path/to/file -o1 -o2")
+
+

It is also possible to use environment variables in the same manner:

+
+(cmd_line "$ENV(VAR1)/path/to/file -o $ENV(VAR2)")
+
+

To change the command line string based on user-provided options use +the case expression (documented above):

+
+(cmd_line
+  (case
+    (switch_on "E"),
+       "llvm-g++ -E -x c $INFILE -o $OUTFILE",
+    (default),
+       "llvm-g++ -c -x c $INFILE -o $OUTFILE -emit-llvm"))
+
+
+
+

How plugins are loaded

+

It is possible for LLVMC plugins to depend on each other. For example, +one can create edges between nodes defined in some other plugin. To +make this work, however, that plugin should be loaded first. To +achieve this, the concept of plugin priority was introduced. By +default, every plugin has priority zero; to specify the priority +explicitly, put the following line in your plugin's TableGen file:

+
+def Priority : PluginPriority<$PRIORITY_VALUE>;
+# Where PRIORITY_VALUE is some integer > 0
+
+

Plugins are loaded in order of their (increasing) priority, starting +with 0. Therefore, the plugin with the highest priority value will be +loaded last.

+
+
+

Debugging

+

When writing LLVMC plugins, it can be useful to get a visual view of +the resulting compilation graph. This can be achieved via the command +line option --view-graph. This command assumes that Graphviz and +Ghostview are installed. There is also a --write-graph option that +creates a Graphviz source file (compilation-graph.dot) in the +current directory.

+

Another useful llvmc option is --check-graph. It checks the +compilation graph for common errors like mismatched output/input +language names, multiple default edges and cycles. These checks can't +be performed at compile-time because the plugins can load code +dynamically. When invoked with --check-graph, llvmc doesn't +perform any compilation tasks and returns the number of encountered +errors as its status code.

+
+
+

Conditioning on the executable name

+

For now, the executable name (the value passed to the driver in argv[0]) is +accessible only in the C++ code (i.e. hooks). Use the following code:

+
+namespace llvmc {
+extern const char* ProgramName;
+}
+
+std::string MyHook() {
+//...
+if (strcmp(ProgramName, "mydriver") == 0) {
+   //...
+
+}
+
+

In general, you're encouraged not to make the behaviour dependent on the +executable file name, and use command-line switches instead. See for example how +the Base plugin behaves when it needs to choose the correct linker options +(think g++ vs. gcc).

+
+
+ +Valid CSS + +Valid XHTML 1.0 Transitional + +Mikhail Glushenkov
+LLVM Compiler Infrastructure
+ +Last modified: $Date$ +
+
+
+ + diff --git a/libclamav/c++/llvm/docs/CompilerDriverTutorial.html b/libclamav/c++/llvm/docs/CompilerDriverTutorial.html new file mode 100644 index 000000000..317b1d127 --- /dev/null +++ b/libclamav/c++/llvm/docs/CompilerDriverTutorial.html @@ -0,0 +1,126 @@ + + + + + + +Tutorial - Using LLVMC + + + +
+

Tutorial - Using LLVMC

+ + + +
+

Written by Mikhail Glushenkov

+
+

Introduction

+

LLVMC is a generic compiler driver, which plays the same role for LLVM +as the gcc program does for GCC - the difference being that LLVMC +is designed to be more adaptable and easier to customize. Most of +LLVMC functionality is implemented via plugins, which can be loaded +dynamically or compiled in. This tutorial describes the basic usage +and configuration of LLVMC.

+
+
+

Compiling with LLVMC

+

In general, LLVMC tries to be command-line compatible with gcc as +much as possible, so most of the familiar options work:

+
+$ llvmc -O3 -Wall hello.cpp
+$ ./a.out
+hello
+
+

This will invoke llvm-g++ under the hood (you can see which +commands are executed by using the -v option). For further help on +command-line LLVMC usage, refer to the llvmc --help output.

+
+
+

Using LLVMC to generate toolchain drivers

+

LLVMC plugins are written mostly using TableGen, so you need to +be familiar with it to get anything done.

+

Start by compiling example/Simple, which is a primitive wrapper for +gcc:

+
+$ cd $LLVM_DIR/tools/llvmc
+$ cp -r example/Simple plugins/Simple
+
+  # NB: A less verbose way to compile standalone LLVMC-based drivers is
+  # described in the reference manual.
+
+$ make LLVMC_BASED_DRIVER_NAME=mygcc LLVMC_BUILTIN_PLUGINS=Simple
+$ cat > hello.c
+[...]
+$ mygcc hello.c
+$ ./hello.out
+Hello
+
+

Here we link our plugin with the LLVMC core statically to form an executable +file called mygcc. It is also possible to build our plugin as a dynamic +library to be loaded by the llvmc executable (or any other LLVMC-based +standalone driver); this is described in the reference manual.

+

Contents of the file Simple.td look like this:

+
+// Include common definitions
+include "llvm/CompilerDriver/Common.td"
+
+// Tool descriptions
+def gcc : Tool<
+[(in_language "c"),
+ (out_language "executable"),
+ (output_suffix "out"),
+ (cmd_line "gcc $INFILE -o $OUTFILE"),
+ (sink)
+]>;
+
+// Language map
+def LanguageMap : LanguageMap<[LangToSuffixes<"c", ["c"]>]>;
+
+// Compilation graph
+def CompilationGraph : CompilationGraph<[Edge<"root", "gcc">]>;
+
+

As you can see, this file consists of three parts: tool descriptions, +language map, and the compilation graph definition.

+

At the heart of LLVMC is the idea of a compilation graph: vertices in +this graph are tools, and edges represent a transformation path +between two tools (for example, assembly source produced by the +compiler can be transformed into executable code by an assembler). The +compilation graph is basically a list of edges; a special node named +root is used to mark graph entry points.

+

Tool descriptions are represented as property lists: most properties +in the example above should be self-explanatory; the sink property +means that all options lacking an explicit description should be +forwarded to this tool.

+

The LanguageMap associates a language name with a list of suffixes +and is used for deciding which toolchain corresponds to a given input +file.

+

To learn more about LLVMC customization, refer to the reference +manual and plugin source code in the plugins directory.

+
+
+ +Valid CSS + +Valid XHTML 1.0 Transitional + +Mikhail Glushenkov
+LLVM Compiler Infrastructure
+ +Last modified: $Date: 2008-12-11 11:34:48 -0600 (Thu, 11 Dec 2008) $ +
+
+ + diff --git a/libclamav/c++/llvm/docs/CompilerWriterInfo.html b/libclamav/c++/llvm/docs/CompilerWriterInfo.html new file mode 100644 index 000000000..5d071f732 --- /dev/null +++ b/libclamav/c++/llvm/docs/CompilerWriterInfo.html @@ -0,0 +1,263 @@ + + + + + Architecture/platform information for compiler writers + + + + + +
+ Architecture/platform information for compiler writers +
+ +
+

Note: This document is a work-in-progress. Additions and clarifications + are welcome.

+
+ +
    +
  1. Hardware +
      +
    1. Alpha
    2. +
    3. ARM
    4. +
    5. Itanium
    6. +
    7. MIPS
    8. +
    9. PowerPC
    10. +
    11. SPARC
    12. +
    13. X86
    14. +
    15. Other lists
    16. +
  2. +
  3. Application Binary Interface (ABI) +
      +
    1. Linux
    2. +
    3. OS X
    4. +
  4. +
  5. Miscellaneous resources
  6. +
+ +
+

Compiled by Misha Brukman

+
+ + + + + + + + +
+ +
+ + + + + + + + + + + + + + + + + + + + +
IBM - Official manuals and docs
+ + + + +
Other documents, collections, notes
+ + + + + + + + + + + + +
AMD - Official manuals and docs
+ + + + +
Intel - Official manuals and docs
+ + + + +
Other x86-specific information
+ + + + + + +
+ + + +
+ + + + + + + + + + + + + + + + + + + + + + + +
+
+ Valid CSS + Valid HTML 4.01 + + Misha Brukman
+ LLVM Compiler Infrastructure
+ Last modified: $Date$ +
+ + + diff --git a/libclamav/c++/llvm/docs/DebuggingJITedCode.html b/libclamav/c++/llvm/docs/DebuggingJITedCode.html new file mode 100644 index 000000000..92570f454 --- /dev/null +++ b/libclamav/c++/llvm/docs/DebuggingJITedCode.html @@ -0,0 +1,171 @@ + + + + Debugging JITed Code With GDB + + + + +
Debugging JITed Code With GDB
+
    +
  1. Introduction
  2. +
  3. Quickstart
  4. +
  5. Example with clang and lli
  6. +
+
Written by Reid Kleckner
+ + + + +
+ +

Without special runtime support, debugging dynamically generated code with +GDB (as well as most debuggers) can be quite painful. Debuggers generally read +debug information from the object file of the code, but for JITed code, there is +no such file to look for. +

+ +

Depending on the architecture, this can impact the debugging experience in +different ways. For example, on most 32-bit x86 architectures, you can simply +compile with -fno-omit-framepointer for GCC and -fdisable-fp-elim for LLVM. +When GDB creates a backtrace, it can properly unwind the stack, but the stack +frames owned by JITed code have ??'s instead of the appropriate symbol name. +However, on Linux x86_64 in particular, GDB relies on the DWARF CFA debug +information to unwind the stack, so even if you compile your program to leave +the frame pointer untouched, GDB will usually be unable to unwind the stack past +any JITed code stack frames. +

+ +

In order to communicate the necessary debug info to GDB, an interface for +registering JITed code with debuggers has been designed and implemented for +GDB and LLVM. At a high level, whenever LLVM generates new machine code, it +also generates an object file in memory containing the debug information. LLVM +then adds the object file to the global list of object files and calls a special +function (__jit_debug_register_code) marked noinline that GDB knows about. When +GDB attaches to a process, it puts a breakpoint in this function and loads all +of the object files in the global list. When LLVM calls the registration +function, GDB catches the breakpoint signal, loads the new object file from +LLVM's memory, and resumes the execution. In this way, GDB can get the +necessary debug information. +

+ +

At the time of this writing, LLVM only supports architectures that use ELF +object files and it only generates symbols and DWARF CFA information. However, +it would be easy to add more information to the object file, so we don't need to +coordinate with GDB to get better debug information. +

+
+ + + + +
+ +

In order to debug code JITed by LLVM, you need to install a recent version +of GDB. The interface was added on 2009-08-19, so you need a snapshot of GDB +more recent than that. Either download a snapshot of GDB or checkout CVS as +instructed here. Here +are the commands for doing a checkout and building the code: +

+ +
+$ cvs -z 3 -d :pserver:anoncvs@sourceware.org:/cvs/src co gdb
+$ mv src gdb   # You probably don't want this checkout called "src".
+$ cd gdb
+$ ./configure --prefix="$GDB_INSTALL"
+$ make
+$ make install
+
+ +

You can then use -jit-emit-debug in the LLVM command line arguments to enable +the interface. +

+
+ + + + +
+ +

For example, consider debugging running lli on the following C code in +foo.c: +

+ +
+#include <stdio.h>
+
+void foo() {
+    printf("%d\n", *(int*)NULL);  // Crash here
+}
+
+void bar() {
+    foo();
+}
+
+void baz() {
+    bar();
+}
+
+int main(int argc, char **argv) {
+    baz();
+}
+
+ +

Here are the commands to run that application under GDB and print the stack +trace at the crash: +

+ +
+# Compile foo.c to bitcode.  You can use either clang or llvm-gcc with this
+# command line.  Both require -fexceptions, or the calls are all marked
+# 'nounwind' which disables DWARF CFA info.
+$ clang foo.c -fexceptions -emit-llvm -c -o foo.bc
+
+# Run foo.bc under lli with -jit-emit-debug.  If you built lli in debug mode,
+# -jit-emit-debug defaults to true.
+$ $GDB_INSTALL/gdb --args lli -jit-emit-debug foo.bc
+...
+
+# Run the code.
+(gdb) run
+Starting program: /tmp/gdb/lli -jit-emit-debug foo.bc
+[Thread debugging using libthread_db enabled]
+
+Program received signal SIGSEGV, Segmentation fault.
+0x00007ffff7f55164 in foo ()
+
+# Print the backtrace, this time with symbols instead of ??.
+(gdb) bt
+#0  0x00007ffff7f55164 in foo ()
+#1  0x00007ffff7f550f9 in bar ()
+#2  0x00007ffff7f55099 in baz ()
+#3  0x00007ffff7f5502a in main ()
+#4  0x00000000007c0225 in llvm::JIT::runFunction(llvm::Function*,
+    std::vector<llvm::GenericValue,
+    std::allocator<llvm::GenericValue> > const&) ()
+#5  0x00000000007d6d98 in
+    llvm::ExecutionEngine::runFunctionAsMain(llvm::Function*,
+    std::vector<std::string,
+    std::allocator<std::string> > const&, char const* const*) ()
+#6  0x00000000004dab76 in main ()
+
+
+ +

As you can see, GDB can correctly unwind the stack and has the appropriate +function names. +

+ + +
+
+ Valid CSS + Valid HTML 4.01 + Reid Kleckner
+ The LLVM Compiler Infrastructure
+ Last modified: $Date: 2009-01-01 23:10:51 -0800 (Thu, 01 Jan 2009) $ +
+ + diff --git a/libclamav/c++/llvm/docs/DeveloperPolicy.html b/libclamav/c++/llvm/docs/DeveloperPolicy.html new file mode 100644 index 000000000..b11e48bee --- /dev/null +++ b/libclamav/c++/llvm/docs/DeveloperPolicy.html @@ -0,0 +1,607 @@ + + + + + LLVM Developer Policy + + + + +
LLVM Developer Policy
+
    +
  1. Introduction
  2. +
  3. Developer Policies +
      +
    1. Stay Informed
    2. +
    3. Making a Patch
    4. +
    5. Code Reviews
    6. +
    7. Code Owners
    8. +
    9. Test Cases
    10. +
    11. Quality
    12. +
    13. Obtaining Commit Access
    14. +
    15. Making a Major Change
    16. +
    17. Incremental Development
    18. +
    19. Attribution of Changes
    20. +
  4. +
  5. Copyright, License, and Patents +
      +
    1. Copyright
    2. +
    3. License
    4. +
    5. Patents
    6. +
    7. Developer Agreements
    8. +
  6. +
+
Written by the LLVM Oversight Team
+ + + + +
+

This document contains the LLVM Developer Policy which defines the project's + policy towards developers and their contributions. The intent of this policy + is to eliminate miscommunication, rework, and confusion that might arise from + the distributed nature of LLVM's development. By stating the policy in clear + terms, we hope each developer can know ahead of time what to expect when + making LLVM contributions.

+

This policy is also designed to accomplish the following objectives:

+ +
    +
  1. Attract both users and developers to the LLVM project.
  2. + +
  3. Make life as simple and easy for contributors as possible.
  4. + +
  5. Keep the top of Subversion trees as stable as possible.
  6. +
+ +

This policy is aimed at frequent contributors to LLVM. People interested in + contributing one-off patches can do so in an informal way by sending them to + the + llvm-commits + mailing list and engaging another developer to see it through the + process.

+
+ + + + +
+

This section contains policies that pertain to frequent LLVM developers. We + always welcome one-off patches from people who do not + routinely contribute to LLVM, but we expect more from frequent contributors + to keep the system as efficient as possible for everyone. Frequent LLVM + contributors are expected to meet the following requirements in order for + LLVM to maintain a high standard of quality.

+

+ + + +
+

Developers should stay informed by reading at least the + llvmdev email + list. If you are doing anything more than just casual work on LLVM, it is + suggested that you also subscribe to the + llvm-commits + list and pay attention to changes being made by others.

+ +

We recommend that active developers register an email account with + LLVM Bugzilla and preferably subscribe to + the llvm-bugs + email list to keep track of bugs and enhancements occurring in LLVM.

+
+ + + + +
+

When making a patch for review, the goal is to make it as easy for the + reviewer to read it as possible. As such, we recommend that you:

+ +
    +
  1. Make your patch against the Subversion trunk, not a branch, and not an old + version of LLVM. This makes it easy to apply the patch. For information + on how to check out SVN trunk, please see the Getting Started Guide.
  2. + +
  3. Similarly, patches should be submitted soon after they are generated. Old + patches may not apply correctly if the underlying code changes between the + time the patch was created and the time it is applied.
  4. + +
  5. Patches should be made with this command: +
    +
    +svn diff
    +
    +
    + or with the utility utils/mkpatch, which makes it easy to read + the diff.
  6. + +
  7. Patches should not include differences in generated code such as the code + generated by autoconf or tblgen. The + utils/mkpatch utility takes care of this for you.
  8. +
+ +

When sending a patch to a mailing list, it is a good idea to send it as an + attachment to the message, not embedded into the text of the + message. This ensures that your mailer will not mangle the patch when it + sends it (e.g. by making whitespace changes or by wrapping lines).

+ +

For Thunderbird users: Before submitting a patch, please open + Preferences → Advanced → General → Config Editor, + find the key mail.content_disposition_type, and set its value to + 1. Without this setting, Thunderbird sends your attachment using + Content-Disposition: inline rather than Content-Disposition: + attachment. Apple Mail gamely displays such a file inline, making it + difficult to work with for reviewers using that program.

+
+ + + +
+

LLVM has a code review policy. Code review is one way to increase the quality + of software. We generally follow these policies:

+ +
    +
  1. All developers are required to have significant changes reviewed before + they are committed to the repository.
  2. + +
  3. Code reviews are conducted by email, usually on the llvm-commits + list.
  4. + +
  5. Code can be reviewed either before it is committed or after. We expect + major changes to be reviewed before being committed, but smaller changes + (or changes where the developer owns the component) can be reviewed after + commit.
  6. + +
  7. The developer responsible for a code change is also responsible for making + all necessary review-related changes.
  8. + +
  9. Code review can be an iterative process, which continues until the patch + is ready to be committed.
  10. +
+ +

Developers should participate in code reviews as both reviewers and + reviewees. If someone is kind enough to review your code, you should return + the favor for someone else. Note that anyone is welcome to review and give + feedback on a patch, but only people with Subversion write access can approve + it.

+
+ + + +
+ +

The LLVM Project relies on two features of its process to maintain rapid + development in addition to the high quality of its source base: the + combination of code review plus post-commit review for trusted maintainers. + Having both is a great way for the project to take advantage of the fact that + most people do the right thing most of the time, and only commit patches + without pre-commit review when they are confident they are right.

+ +

The trick to this is that the project has to guarantee that all patches that + are committed are reviewed after they go in: you don't want everyone to + assume someone else will review it, allowing the patch to go unreviewed. To + solve this problem, we have a notion of an 'owner' for a piece of the code. + The sole responsibility of a code owner is to ensure that a commit to their + area of the code is appropriately reviewed, either by themself or by someone + else. The current code owners are:

+ +
    +
  1. Evan Cheng: Code generator and all targets.
  2. + +
  3. Doug Gregor: Clang Basic, Lex, Parse, and Sema Libraries.
  4. + +
  5. Anton Korobeynikov: Exception handling, debug information, and + Windows codegen.
  6. + +
  7. Ted Kremenek: Clang Static Analyzer.
  8. + +
  9. Chris Lattner: Everything not covered by someone else.
  10. + +
  11. Duncan Sands: llvm-gcc 4.2.
  12. +
+ +

Note that code ownership is completely different than reviewers: anyone can + review a piece of code, and we welcome code review from anyone who is + interested. Code owners are the "last line of defense" to guarantee that all + patches that are committed are actually reviewed.

+ +

Being a code owner is a somewhat unglamorous position, but it is incredibly + important for the ongoing success of the project. Because people get busy, + interests change, and unexpected things happen, code ownership is purely + opt-in, and anyone can choose to resign their "title" at any time. For now, + we do not have an official policy on how one gets elected to be a code + owner.

+
+ + + +
+

Developers are required to create test cases for any bugs fixed and any new + features added. Some tips for getting your testcase approved:

+ +
    +
  1. All feature and regression test cases are added to the + llvm/test directory. The appropriate sub-directory should be + selected (see the Testing Guide for + details).
  2. + +
  3. Test cases should be written in LLVM assembly + language unless the feature or regression being tested requires + another language (e.g. the bug being fixed or feature being implemented is + in the llvm-gcc C++ front-end, in which case it must be written in + C++).
  4. + +
  5. Test cases, especially for regressions, should be reduced as much as + possible, by bugpoint or manually. It is + unacceptable to place an entire failing program into llvm/test as + this creates a time-to-test burden on all developers. Please keep + them short.
  6. +
+ +

Note that llvm/test is designed for regression and small feature tests + only. More extensive test cases (e.g., entire applications, benchmarks, etc) + should be added to the llvm-test test suite. The llvm-test suite is + for coverage (correctness, performance, etc) testing, not feature or + regression testing.

+
+ + + +
+

The minimum quality standards that any change must satisfy before being + committed to the main development branch are:

+ +
    +
  1. Code must adhere to the LLVM Coding + Standards.
  2. + +
  3. Code must compile cleanly (no errors, no warnings) on at least one + platform.
  4. + +
  5. Bug fixes and new features should include a + testcase so we know if the fix/feature ever regresses in the + future.
  6. + +
  7. Code must pass the dejagnu (llvm/test) test suite.
  8. + +
  9. The code must not cause regressions on a reasonable subset of llvm-test, + where "reasonable" depends on the contributor's judgement and the scope of + the change (more invasive changes require more testing). A reasonable + subset might be something like + "llvm-test/MultiSource/Benchmarks".
  10. +
+ +

Additionally, the committer is responsible for addressing any problems found + in the future that the change is responsible for. For example:

+ +
    +
  • The code should compile cleanly on all supported platforms.
  • + +
  • The changes should not cause any correctness regressions in the + llvm-test suite and must not cause any major performance + regressions.
  • + +
  • The change set should not cause performance or correctness regressions for + the LLVM tools.
  • + +
  • The changes should not cause performance or correctness regressions in + code compiled by LLVM on all applicable targets.
  • + +
  • You are expected to address any bugzilla + bugs that result from your change.
  • +
+ +

We prefer for this to be handled before submission but understand that it + isn't possible to test all of this for every submission. Our build bots and + nightly testing infrastructure normally finds these problems. A good rule of + thumb is to check the nightly testers for regressions the day after your + change. Build bots will directly email you if a group of commits that + included yours caused a failure. You are expected to check the build bot + messages to see if they are your fault and, if so, fix the breakage.

+ +

Commits that violate these quality standards (e.g. are very broken) may be + reverted. This is necessary when the change blocks other developers from + making progress. The developer is welcome to re-commit the change after the + problem has been fixed.

+
+ + + +
+ +

We grant commit access to contributors with a track record of submitting high + quality patches. If you would like commit access, please send an email to + Chris with the following + information:

+ +
    +
  1. The user name you want to commit with, e.g. "hacker".
  2. + +
  3. The full name and email address you want message to llvm-commits to come + from, e.g. "J. Random Hacker <hacker@yoyodyne.com>".
  4. + +
  5. A "password hash" of the password you want to use, e.g. "2ACR96qjUqsyM". + Note that you don't ever tell us what your password is, you just give it + to us in an encrypted form. To get this, run "htpasswd" (a utility that + comes with apache) in crypt mode (often enabled with "-d"), or find a web + page that will do it for you.
  6. +
+ +

Once you've been granted commit access, you should be able to check out an + LLVM tree with an SVN URL of "https://username@llvm.org/..." instead of the + normal anonymous URL of "http://llvm.org/...". The first time you commit + you'll have to type in your password. Note that you may get a warning from + SVN about an untrusted key, you can ignore this. To verify that your commit + access works, please do a test commit (e.g. change a comment or add a blank + line). Your first commit to a repository may require the autogenerated email + to be approved by a mailing list. This is normal, and will be done when + the mailing list owner has time.

+ +

If you have recently been granted commit access, these policies apply:

+ +
    +
  1. You are granted commit-after-approval to all parts of LLVM. To get + approval, submit a patch to + llvm-commits. + When approved you may commit it yourself.
  2. + +
  3. You are allowed to commit patches without approval which you think are + obvious. This is clearly a subjective decision — we simply expect + you to use good judgement. Examples include: fixing build breakage, + reverting obviously broken patches, documentation/comment changes, any + other minor changes.
  4. + +
  5. You are allowed to commit patches without approval to those portions of + LLVM that you have contributed or maintain (i.e., have been assigned + responsibility for), with the proviso that such commits must not break the + build. This is a "trust but verify" policy and commits of this nature are + reviewed after they are committed.
  6. + +
  7. Multiple violations of these policies or a single egregious violation may + cause commit access to be revoked.
  8. +
+ +

In any case, your changes are still subject to code + review (either before or after they are committed, depending on the + nature of the change). You are encouraged to review other peoples' patches + as well, but you aren't required to.

+
+ + + +
+

When a developer begins a major new project with the aim of contributing it + back to LLVM, s/he should inform the community with an email to + the llvmdev + email list, to the extent possible. The reason for this is to: + +

    +
  1. keep the community informed about future changes to LLVM,
  2. + +
  3. avoid duplication of effort by preventing multiple parties working on the + same thing and not knowing about it, and
  4. + +
  5. ensure that any technical issues around the proposed work are discussed + and resolved before any significant work is done.
  6. +
+ +

The design of LLVM is carefully controlled to ensure that all the pieces fit + together well and are as consistent as possible. If you plan to make a major + change to the way LLVM works or want to add a major new extension, it is a + good idea to get consensus with the development community before you start + working on it.

+ +

Once the design of the new feature is finalized, the work itself should be + done as a series of incremental changes, not as a + long-term development branch.

+
+ + + +
+

In the LLVM project, we do all significant changes as a series of incremental + patches. We have a strong dislike for huge changes or long-term development + branches. Long-term development branches have a number of drawbacks:

+ +
    +
  1. Branches must have mainline merged into them periodically. If the branch + development and mainline development occur in the same pieces of code, + resolving merge conflicts can take a lot of time.
  2. + +
  3. Other people in the community tend to ignore work on branches.
  4. + +
  5. Huge changes (produced when a branch is merged back onto mainline) are + extremely difficult to code review.
  6. + +
  7. Branches are not routinely tested by our nightly tester + infrastructure.
  8. + +
  9. Changes developed as monolithic large changes often don't work until the + entire set of changes is done. Breaking it down into a set of smaller + changes increases the odds that any of the work will be committed to the + main repository.
  10. +
+ +

To address these problems, LLVM uses an incremental development style and we + require contributors to follow this practice when making a large/invasive + change. Some tips:

+ +
    +
  • Large/invasive changes usually have a number of secondary changes that are + required before the big change can be made (e.g. API cleanup, etc). These + sorts of changes can often be done before the major change is done, + independently of that work.
  • + +
  • The remaining inter-related work should be decomposed into unrelated sets + of changes if possible. Once this is done, define the first increment and + get consensus on what the end goal of the change is.
  • + +
  • Each change in the set can be stand alone (e.g. to fix a bug), or part of + a planned series of changes that works towards the development goal.
  • + +
  • Each change should be kept as small as possible. This simplifies your work + (into a logical progression), simplifies code review and reduces the + chance that you will get negative feedback on the change. Small increments + also facilitate the maintenance of a high quality code base.
  • + +
  • Often, an independent precursor to a big change is to add a new API and + slowly migrate clients to use the new API. Each change to use the new API + is often "obvious" and can be committed without review. Once the new API + is in place and used, it is much easier to replace the underlying + implementation of the API. This implementation change is logically + separate from the API change.
  • +
+ +

If you are interested in making a large change, and this scares you, please + make sure to first discuss the change/gather consensus + then ask about the best way to go about making the change.

+
+ + + +
+

We believe in correct attribution of contributions to their contributors. + However, we do not want the source code to be littered with random + attributions "this code written by J. Random Hacker" (this is noisy and + distracting). In practice, the revision control system keeps a perfect + history of who changed what, and the CREDITS.txt file describes higher-level + contributions. If you commit a patch for someone else, please say "patch + contributed by J. Random Hacker!" in the commit message.

+ +

Overall, please do not add contributor names to the source code.

+
+ + + + + +
+

This section addresses the issues of copyright, license and patents for the + LLVM project. Currently, the University of Illinois is the LLVM copyright + holder and the terms of its license to LLVM users and developers is the + University of + Illinois/NCSA Open Source License.

+ +
+

NOTE: This section deals with + legal matters but does not provide legal advice. We are not lawyers, please + seek legal counsel from an attorney.

+
+
+ + + +
+

For consistency and ease of management, the project requires the copyright + for all LLVM software to be held by a single copyright holder: the University + of Illinois (UIUC).

+ +

Although UIUC may eventually reassign the copyright of the software to + another entity (e.g. a dedicated non-profit "LLVM Organization") the intent + for the project is to always have a single entity hold the copyrights to LLVM + at any given time.

+ +

We believe that having a single copyright holder is in the best interests of + all developers and users as it greatly reduces the managerial burden for any + kind of administrative or technical decisions about LLVM. The goal of the + LLVM project is to always keep the code open and licensed + under a very liberal license.

+
+ + + +
+

We intend to keep LLVM perpetually open source and to use a liberal open + source license. The current license is the + University of + llinois/NCSA Open Source License, which boils down to this:

+ +
    +
  • You can freely distribute LLVM.
  • + +
  • You must retain the copyright notice if you redistribute LLVM.
  • + +
  • Binaries derived from LLVM must reproduce the copyright notice (e.g. in + an included readme file).
  • + +
  • You can't use our names to promote your LLVM derived products.
  • + +
  • There's no warranty on LLVM at all.
  • +
+ +

We believe this fosters the widest adoption of LLVM because it allows + commercial products to be derived from LLVM with few restrictions and + without a requirement for making any derived works also open source (i.e. + LLVM's license is not a "copyleft" license like the GPL). We suggest that you + read the License + if further clarification is needed.

+ +

Note that the LLVM Project does distribute llvm-gcc, which is GPL. + This means that anything "linked" into llvm-gcc must itself be compatible + with the GPL, and must be releasable under the terms of the GPL. This + implies that any code linked into llvm-gcc and distributed to others may + be subject to the viral aspects of the GPL (for example, a proprietary + code generator linked into llvm-gcc must be made available under the GPL). + This is not a problem for code already distributed under a more liberal + license (like the UIUC license), and does not affect code generated by + llvm-gcc. It may be a problem if you intend to base commercial development + on llvm-gcc without redistributing your source code.

+ +

We have no plans to change the license of LLVM. If you have questions or + comments about the license, please contact the + LLVM Oversight Group.

+
+ + + +
+

To the best of our knowledge, LLVM does not infringe on any patents (we have + actually removed code from LLVM in the past that was found to infringe). + Having code in LLVM that infringes on patents would violate an important goal + of the project by making it hard or impossible to reuse the code for + arbitrary purposes (including commercial use).

+ +

When contributing code, we expect contributors to notify us of any potential + for patent-related trouble with their changes. If you or your employer own + the rights to a patent and would like to contribute code to LLVM that relies + on it, we require that the copyright owner sign an agreement that allows any + other user of LLVM to freely use your patent. Please contact + the oversight group for more + details.

+
+ + + +
+

With regards to the LLVM copyright and licensing, developers agree to assign + their copyrights to UIUC for any contribution made so that the entire + software base can be managed by a single copyright holder. This implies that + any contributions can be licensed under the license that the project + uses.

+ +

When contributing code, you also affirm that you are legally entitled to + grant this copyright, personally or on behalf of your employer. If the code + belongs to some other entity, please raise this issue with the oversight + group before the code is committed.

+
+ + +
+
+ Valid CSS + Valid HTML 4.01 + Written by the + LLVM Oversight Group
+ The LLVM Compiler Infrastructure
+ Last modified: $Date$ +
+ + diff --git a/libclamav/c++/llvm/docs/ExceptionHandling.html b/libclamav/c++/llvm/docs/ExceptionHandling.html new file mode 100644 index 000000000..438edda6c --- /dev/null +++ b/libclamav/c++/llvm/docs/ExceptionHandling.html @@ -0,0 +1,587 @@ + + + + Exception Handling in LLVM + + + + + + + +
Exception Handling in LLVM
+ + + + +
+ +
+ +
+

Written by Jim Laskey

+
+ + + + + + +
+ +

This document is the central repository for all information pertaining to + exception handling in LLVM. It describes the format that LLVM exception + handling information takes, which is useful for those interested in creating + front-ends or dealing directly with the information. Further, this document + provides specific examples of what exception handling information is used for + in C/C++.

+ +
+ + + + +
+ +

Exception handling for most programming languages is designed to recover from + conditions that rarely occur during general use of an application. To that + end, exception handling should not interfere with the main flow of an + application's algorithm by performing checkpointing tasks, such as saving the + current pc or register state.

+ +

The Itanium ABI Exception Handling Specification defines a methodology for + providing outlying data in the form of exception tables without inlining + speculative exception handling code in the flow of an application's main + algorithm. Thus, the specification is said to add "zero-cost" to the normal + execution of an application.

+ +

A more complete description of the Itanium ABI exception handling runtime + support of can be found at + Itanium C++ ABI: + Exception Handling. A description of the exception frame format can be + found at + Exception + Frames, with details of the DWARF 3 specification at + DWARF 3 Standard. + A description for the C++ exception table formats can be found at + Exception Handling + Tables.

+ +
+ + + + +
+ +

Setjmp/Longjmp (SJLJ) based exception handling uses LLVM intrinsics + llvm.eh.sjlj.setjmp and + llvm.eh.sjlj.longjmp to + handle control flow for exception handling.

+ +

For each function which does exception processing, be it try/catch blocks + or cleanups, that function registers itself on a global frame list. When + exceptions are being unwound, the runtime uses this list to identify which + functions need processing.

+ +

Landing pad selection is encoded in the call site entry of the function + context. The runtime returns to the function via + llvm.eh.sjlj.longjmp, where + a switch table transfers control to the appropriate landing pad based on + the index stored in the function context.

+ +

In contrast to DWARF exception handling, which encodes exception regions + and frame information in out-of-line tables, SJLJ exception handling + builds and removes the unwind frame context at runtime. This results in + faster exception handling at the expense of slower execution when no + exceptions are thrown. As exceptions are, by their nature, intended for + uncommon code paths, DWARF exception handling is generally preferred to + SJLJ.

+
+ + + + +
+ +

When an exception is thrown in LLVM code, the runtime does its best to find a + handler suited to processing the circumstance.

+ +

The runtime first attempts to find an exception frame corresponding to + the function where the exception was thrown. If the programming language + (e.g. C++) supports exception handling, the exception frame contains a + reference to an exception table describing how to process the exception. If + the language (e.g. C) does not support exception handling, or if the + exception needs to be forwarded to a prior activation, the exception frame + contains information about how to unwind the current activation and restore + the state of the prior activation. This process is repeated until the + exception is handled. If the exception is not handled and no activations + remain, then the application is terminated with an appropriate error + message.

+ +

Because different programming languages have different behaviors when + handling exceptions, the exception handling ABI provides a mechanism for + supplying personalities. An exception handling personality is defined + by way of a personality function (e.g. __gxx_personality_v0 + in C++), which receives the context of the exception, an exception + structure containing the exception object type and value, and a reference + to the exception table for the current function. The personality function + for the current compile unit is specified in a common exception + frame.

+ +

The organization of an exception table is language dependent. For C++, an + exception table is organized as a series of code ranges defining what to do + if an exception occurs in that range. Typically, the information associated + with a range defines which types of exception objects (using C++ type + info) that are handled in that range, and an associated action that + should take place. Actions typically pass control to a landing + pad.

+ +

A landing pad corresponds to the code found in the catch portion of + a try/catch sequence. When execution resumes at a landing + pad, it receives the exception structure and a selector corresponding to + the type of exception thrown. The selector is then used to determine + which catch should actually process the exception.

+ +
+ + + + +
+ +

At the time of this writing, only C++ exception handling support is available + in LLVM. So the remainder of this document will be somewhat C++-centric.

+ +

From the C++ developers perspective, exceptions are defined in terms of the + throw and try/catch statements. In this section + we will describe the implementation of LLVM exception handling in terms of + C++ examples.

+ +
+ + +
+ Throw +
+ +
+ +

Languages that support exception handling typically provide a throw + operation to initiate the exception process. Internally, a throw operation + breaks down into two steps. First, a request is made to allocate exception + space for an exception structure. This structure needs to survive beyond the + current activation. This structure will contain the type and value of the + object being thrown. Second, a call is made to the runtime to raise the + exception, passing the exception structure as an argument.

+ +

In C++, the allocation of the exception structure is done by + the __cxa_allocate_exception runtime function. The exception + raising is handled by __cxa_throw. The type of the exception is + represented using a C++ RTTI structure.

+ +
+ + + + +
+ +

A call within the scope of a try statement can potentially raise an + exception. In those circumstances, the LLVM C++ front-end replaces the call + with an invoke instruction. Unlike a call, the invoke has + two potential continuation points: where to continue when the call succeeds + as per normal; and where to continue if the call raises an exception, either + by a throw or the unwinding of a throw.

+ +

The term used to define a the place where an invoke continues after + an exception is called a landing pad. LLVM landing pads are + conceptually alternative function entry points where an exception structure + reference and a type info index are passed in as arguments. The landing pad + saves the exception structure reference and then proceeds to select the catch + block that corresponds to the type info of the exception object.

+ +

Two LLVM intrinsic functions are used to convey information about the landing + pad to the back end.

+ +
    +
  1. llvm.eh.exception takes no + arguments and returns a pointer to the exception structure. This only + returns a sensible value if called after an invoke has branched + to a landing pad. Due to code generation limitations, it must currently + be called in the landing pad itself.
  2. + +
  3. llvm.eh.selector takes a minimum + of three arguments. The first argument is the reference to the exception + structure. The second argument is a reference to the personality function + to be used for this try/catch sequence. Each of the + remaining arguments is either a reference to the type info for + a catch statement, a filter + expression, or the number zero (0) representing + a cleanup. The exception is tested against the + arguments sequentially from first to last. The result of + the llvm.eh.selector is a + positive number if the exception matched a type info, a negative number if + it matched a filter, and zero if it matched a cleanup. If nothing is + matched, the behaviour of the program + is undefined. This only returns a sensible + value if called after an invoke has branched to a landing pad. + Due to codegen limitations, it must currently be called in the landing pad + itself. If a type info matched, then the selector value is the index of + the type info in the exception table, which can be obtained using the + llvm.eh.typeid.for + intrinsic.
  4. +
+ +

Once the landing pad has the type info selector, the code branches to the + code for the first catch. The catch then checks the value of the type info + selector against the index of type info for that catch. Since the type info + index is not known until all the type info have been gathered in the backend, + the catch code will call the + llvm.eh.typeid.for intrinsic + to determine the index for a given type info. If the catch fails to match + the selector then control is passed on to the next catch. Note: Since the + landing pad will not be used if there is no match in the list of type info on + the call to llvm.eh.selector, then + neither the last catch nor catch all need to perform the check + against the selector.

+ +

Finally, the entry and exit of catch code is bracketed with calls + to __cxa_begin_catch and __cxa_end_catch.

+ +
    +
  • __cxa_begin_catch takes a exception structure reference as an + argument and returns the value of the exception object.
  • + +
  • __cxa_end_catch takes no arguments. This function:

    +
      +
    1. Locates the most recently caught exception and decrements its handler + count,
    2. +
    3. Removes the exception from the "caught" stack if the handler count + goes to zero, and
    4. +
    5. Destroys the exception if the handler count goes to zero, and the + exception was not re-thrown by throw.
    6. +
    +

    Note: a rethrow from within the catch may replace this call with + a __cxa_rethrow.

  • +
+ +
+ + + + +
+ +

To handle destructors and cleanups in try code, control may not run + directly from a landing pad to the first catch. Control may actually flow + from the landing pad to clean up code and then to the first catch. Since the + required clean up for each invoke in a try may be different + (e.g. intervening constructor), there may be several landing pads for a given + try. If cleanups need to be run, an i32 0 should be passed as the + last llvm.eh.selector argument. + However, when using DWARF exception handling with C++, a i8* null + must be passed instead.

+ +
+ + + + +
+ +

C++ allows the specification of which exception types can be thrown from a + function. To represent this a top level landing pad may exist to filter out + invalid types. To express this in LLVM code the landing pad will + call llvm.eh.selector. The + arguments are a reference to the exception structure, a reference to the + personality function, the length of the filter expression (the number of type + infos plus one), followed by the type infos themselves. + llvm.eh.selector will return a + negative value if the exception does not match any of the type infos. If no + match is found then a call to __cxa_call_unexpected should be made, + otherwise _Unwind_Resume. Each of these functions requires a + reference to the exception structure. Note that the most general form of an + llvm.eh.selector call can contain + any number of type infos, filter expressions and cleanups (though having more + than one cleanup is pointless). The LLVM C++ front-end can generate such + llvm.eh.selector calls due to + inlining creating nested exception handling scopes.

+ +
+ + + + +
+ +

The semantics of the invoke instruction require that any exception that + unwinds through an invoke call should result in a branch to the invoke's + unwind label. However such a branch will only happen if the + llvm.eh.selector matches. Thus in + order to ensure correct operation, the front-end must only generate + llvm.eh.selector calls that are + guaranteed to always match whatever exception unwinds through the invoke. + For most languages it is enough to pass zero, indicating the presence of + a cleanup, as the + last llvm.eh.selector argument. + However for C++ this is not sufficient, because the C++ personality function + will terminate the program if it detects that unwinding the exception only + results in matches with cleanups. For C++ a null i8* should be + passed as the last llvm.eh.selector + argument instead. This is interpreted as a catch-all by the C++ personality + function, and will always match.

+ +
+ + + + +
+ +

LLVM uses several intrinsic functions (name prefixed with "llvm.eh") to + provide exception handling information at various points in generated + code.

+ +
+ + + + +
+ +
+  i8* %llvm.eh.exception( )
+
+ +

This intrinsic returns a pointer to the exception structure.

+ +
+ + + + +
+ +
+  i32 %llvm.eh.selector(i8*, i8*, i8*, ...)
+
+ +

This intrinsic is used to compare the exception with the given type infos, + filters and cleanups.

+ +

llvm.eh.selector takes a minimum of + three arguments. The first argument is the reference to the exception + structure. The second argument is a reference to the personality function to + be used for this try catch sequence. Each of the remaining arguments is + either a reference to the type info for a catch statement, + a filter expression, or the number zero + representing a cleanup. The exception is tested + against the arguments sequentially from first to last. The result of + the llvm.eh.selector is a positive + number if the exception matched a type info, a negative number if it matched + a filter, and zero if it matched a cleanup. If nothing is matched, the + behaviour of the program is undefined. If a type + info matched then the selector value is the index of the type info in the + exception table, which can be obtained using the + llvm.eh.typeid.for intrinsic.

+ +
+ + + + +
+ +
+  i32 %llvm.eh.typeid.for(i8*)
+
+ +

This intrinsic returns the type info index in the exception table of the + current function. This value can be used to compare against the result + of llvm.eh.selector. The single + argument is a reference to a type info.

+ +
+ + + + +
+ +
+  i32 %llvm.eh.sjlj.setjmp(i8*)
+
+ +

The SJLJ exception handling uses this intrinsic to force register saving for + the current function and to store the address of the following instruction + for use as a destination address by + llvm.eh.sjlj.longjmp. The buffer format and the overall + functioning of this intrinsic is compatible with the GCC + __builtin_setjmp implementation, allowing code built with the + two compilers to interoperate.

+ +

The single parameter is a pointer to a five word buffer in which the calling + context is saved. The front end places the frame pointer in the first word, + and the target implementation of this intrinsic should place the destination + address for a + llvm.eh.sjlj.longjmp in the + second word. The following three words are available for use in a + target-specific manner.

+ +
+ + + + +
+ +
+  i8* %llvm.eh.sjlj.lsda( )
+
+ +

Used for SJLJ based exception handling, the + llvm.eh.sjlj.lsda intrinsic returns the address of the Language + Specific Data Area (LSDA) for the current function. The SJLJ front-end code + stores this address in the exception handling function context for use by the + runtime.

+ +
+ + + + +
+ +

There are two tables that are used by the exception handling runtime to + determine which actions should take place when an exception is thrown.

+ +
+ + + + +
+ +

An exception handling frame eh_frame is very similar to the unwind + frame used by dwarf debug info. The frame contains all the information + necessary to tear down the current frame and restore the state of the prior + frame. There is an exception handling frame for each function in a compile + unit, plus a common exception handling frame that defines information common + to all functions in the unit.

+ +

Todo - Table details here.

+ +
+ + + + +
+ +

An exception table contains information about what actions to take when an + exception is thrown in a particular part of a function's code. There is one + exception table per function except leaf routines and functions that have + only calls to non-throwing functions will not need an exception table.

+ +

Todo - Table details here.

+ +
+ + +
+ ToDo +
+ +
+ +
    + +
  1. Testing/Testing/Testing.
  2. + +
+ +
+ + + +
+
+ Valid CSS + Valid HTML 4.01 + + Chris Lattner
+ LLVM Compiler Infrastructure
+ Last modified: $Date$ +
+ + + diff --git a/libclamav/c++/llvm/docs/ExtendedIntegerResults.txt b/libclamav/c++/llvm/docs/ExtendedIntegerResults.txt new file mode 100644 index 000000000..44e9fbf0e --- /dev/null +++ b/libclamav/c++/llvm/docs/ExtendedIntegerResults.txt @@ -0,0 +1,133 @@ +//===----------------------------------------------------------------------===// +// Representing sign/zero extension of function results +//===----------------------------------------------------------------------===// + +Mar 25, 2009 - Initial Revision + +Most ABIs specify that functions which return small integers do so in a +specific integer GPR. This is an efficient way to go, but raises the question: +if the returned value is smaller than the register, what do the high bits hold? + +There are three (interesting) possible answers: undefined, zero extended, or +sign extended. The number of bits in question depends on the data-type that +the front-end is referencing (typically i1/i8/i16/i32). + +Knowing the answer to this is important for two reasons: 1) we want to be able +to implement the ABI correctly. If we need to sign extend the result according +to the ABI, we really really do need to do this to preserve correctness. 2) +this information is often useful for optimization purposes, and we want the +mid-level optimizers to be able to process this (e.g. eliminate redundant +extensions). + +For example, lets pretend that X86 requires the caller to properly extend the +result of a return (I'm not sure this is the case, but the argument doesn't +depend on this). Given this, we should compile this: + +int a(); +short b() { return a(); } + +into: + +_b: + subl $12, %esp + call L_a$stub + addl $12, %esp + cwtl + ret + +An optimization example is that we should be able to eliminate the explicit +sign extension in this example: + +short y(); +int z() { + return ((int)y() << 16) >> 16; +} + +_z: + subl $12, %esp + call _y + ;; movswl %ax, %eax -> not needed because eax is already sext'd + addl $12, %esp + ret + +//===----------------------------------------------------------------------===// +// What we have right now. +//===----------------------------------------------------------------------===// + +Currently, these sorts of things are modelled by compiling a function to return +the small type and a signext/zeroext marker is used. For example, we compile +Z into: + +define i32 @z() nounwind { +entry: + %0 = tail call signext i16 (...)* @y() nounwind + %1 = sext i16 %0 to i32 + ret i32 %1 +} + +and b into: + +define signext i16 @b() nounwind { +entry: + %0 = tail call i32 (...)* @a() nounwind ; [#uses=1] + %retval12 = trunc i32 %0 to i16 ; [#uses=1] + ret i16 %retval12 +} + +This has some problems: 1) the actual precise semantics are really poorly +defined (see PR3779). 2) some targets might want the caller to extend, some +might want the callee to extend 3) the mid-level optimizer doesn't know the +size of the GPR, so it doesn't know that %0 is sign extended up to 32-bits +here, and even if it did, it could not eliminate the sext. 4) the code +generator has historically assumed that the result is extended to i32, which is +a problem on PIC16 (and is also probably wrong on alpha and other 64-bit +targets). + +//===----------------------------------------------------------------------===// +// The proposal +//===----------------------------------------------------------------------===// + +I suggest that we have the front-end fully lower out the ABI issues here to +LLVM IR. This makes it 100% explicit what is going on and means that there is +no cause for confusion. For example, the cases above should compile into: + +define i32 @z() nounwind { +entry: + %0 = tail call i32 (...)* @y() nounwind + %1 = trunc i32 %0 to i16 + %2 = sext i16 %1 to i32 + ret i32 %2 +} +define i32 @b() nounwind { +entry: + %0 = tail call i32 (...)* @a() nounwind + %retval12 = trunc i32 %0 to i16 + %tmp = sext i16 %retval12 to i32 + ret i32 %tmp +} + +In this model, no functions will return an i1/i8/i16 (and on a x86-64 target +that extends results to i64, no i32). This solves the ambiguity issue, allows us +to fully describe all possible ABIs, and now allows the optimizers to reason +about and eliminate these extensions. + +The one thing that is missing is the ability for the front-end and optimizer to +specify/infer the guarantees provided by the ABI to allow other optimizations. +For example, in the y/z case, since y is known to return a sign extended value, +the trunc/sext in z should be eliminable. + +This can be done by introducing new sext/zext attributes which mean "I know +that the result of the function is sign extended at least N bits. Given this, +and given that it is stuck on the y function, the mid-level optimizer could +easily eliminate the extensions etc with existing functionality. + +The major disadvantage of doing this sort of thing is that it makes the ABI +lowering stuff even more explicit in the front-end, and that we would like to +eventually move to having the code generator do more of this work. However, +the sad truth of the matter is that this is a) unlikely to happen anytime in +the near future, and b) this is no worse than we have now with the existing +attributes. + +C compilers fundamentally have to reason about the target in many ways. +This is ugly and horrible, but a fact of life. + diff --git a/libclamav/c++/llvm/docs/ExtendingLLVM.html b/libclamav/c++/llvm/docs/ExtendingLLVM.html new file mode 100644 index 000000000..647fa01d5 --- /dev/null +++ b/libclamav/c++/llvm/docs/ExtendingLLVM.html @@ -0,0 +1,391 @@ + + + + Extending LLVM: Adding instructions, intrinsics, types, etc. + + + + + +
+ Extending LLVM: Adding instructions, intrinsics, types, etc. +
+ +
    +
  1. Introduction and Warning
  2. +
  3. Adding a new intrinsic function
  4. +
  5. Adding a new instruction
  6. +
  7. Adding a new SelectionDAG node
  8. +
  9. Adding a new type +
      +
    1. Adding a new fundamental type
    2. +
    3. Adding a new derived type
    4. +
  10. +
+ +
+

Written by Misha Brukman, + Brad Jones, Nate Begeman, + and Chris Lattner

+
+ + + + + +
+ +

During the course of using LLVM, you may wish to customize it for your +research project or for experimentation. At this point, you may realize that +you need to add something to LLVM, whether it be a new fundamental type, a new +intrinsic function, or a whole new instruction.

+ +

When you come to this realization, stop and think. Do you really need to +extend LLVM? Is it a new fundamental capability that LLVM does not support at +its current incarnation or can it be synthesized from already pre-existing LLVM +elements? If you are not sure, ask on the LLVM-dev list. The +reason is that extending LLVM will get involved as you need to update all the +different passes that you intend to use with your extension, and there are +many LLVM analyses and transformations, so it may be quite a bit of +work.

+ +

Adding an intrinsic function is far easier than +adding an instruction, and is transparent to optimization passes. If your added +functionality can be expressed as a +function call, an intrinsic function is the method of choice for LLVM +extension.

+ +

Before you invest a significant amount of effort into a non-trivial +extension, ask on the list if what you are +looking to do can be done with already-existing infrastructure, or if maybe +someone else is already working on it. You will save yourself a lot of time and +effort by doing so.

+ +
+ + + + + +
+ +

Adding a new intrinsic function to LLVM is much easier than adding a new +instruction. Almost all extensions to LLVM should start as an intrinsic +function and then be turned into an instruction if warranted.

+ +
    +
  1. llvm/docs/LangRef.html: + Document the intrinsic. Decide whether it is code generator specific and + what the restrictions are. Talk to other people about it so that you are + sure it's a good idea.
  2. + +
  3. llvm/include/llvm/Intrinsics*.td: + Add an entry for your intrinsic. Describe its memory access characteristics + for optimization (this controls whether it will be DCE'd, CSE'd, etc). Note + that any intrinsic using the llvm_int_ty type for an argument will + be deemed by tblgen as overloaded and the corresponding suffix + will be required on the intrinsic's name.
  4. + +
  5. llvm/lib/Analysis/ConstantFolding.cpp: If it is possible to + constant fold your intrinsic, add support to it in the + canConstantFoldCallTo and ConstantFoldCall functions.
  6. + +
  7. llvm/test/Regression/*: Add test cases for your test cases to the + test suite
  8. +
+ +

Once the intrinsic has been added to the system, you must add code generator +support for it. Generally you must do the following steps:

+ +
+
Add support to the C backend in lib/Target/CBackend/
+ +
Depending on the intrinsic, there are a few ways to implement this. For + most intrinsics, it makes sense to add code to lower your intrinsic in + LowerIntrinsicCall in lib/CodeGen/IntrinsicLowering.cpp. + Second, if it makes sense to lower the intrinsic to an expanded sequence of + C code in all cases, just emit the expansion in visitCallInst in + Writer.cpp. If the intrinsic has some way to express it with GCC + (or any other compiler) extensions, it can be conditionally supported based + on the compiler compiling the CBE output (see llvm.prefetch for an + example). Third, if the intrinsic really has no way to be lowered, just + have the code generator emit code that prints an error message and calls + abort if executed.
+ +
Add support to the .td file for the target(s) of your choice in + lib/Target/*/*.td.
+ +
This is usually a matter of adding a pattern to the .td file that matches + the intrinsic, though it may obviously require adding the instructions you + want to generate as well. There are lots of examples in the PowerPC and X86 + backend to follow.
+
+ +
+ + + + + +
+ +

As with intrinsics, adding a new SelectionDAG node to LLVM is much easier +than adding a new instruction. New nodes are often added to help represent +instructions common to many targets. These nodes often map to an LLVM +instruction (add, sub) or intrinsic (byteswap, population count). In other +cases, new nodes have been added to allow many targets to perform a common task +(converting between floating point and integer representation) or capture more +complicated behavior in a single node (rotate).

+ +
    +
  1. include/llvm/CodeGen/SelectionDAGNodes.h: + Add an enum value for the new SelectionDAG node.
  2. +
  3. lib/CodeGen/SelectionDAG/SelectionDAG.cpp: + Add code to print the node to getOperationName. If your new node + can be evaluated at compile time when given constant arguments (such as an + add of a constant with another constant), find the getNode method + that takes the appropriate number of arguments, and add a case for your node + to the switch statement that performs constant folding for nodes that take + the same number of arguments as your new node.
  4. +
  5. lib/CodeGen/SelectionDAG/LegalizeDAG.cpp: + Add code to legalize, + promote, and expand the node as necessary. At a minimum, you will need + to add a case statement for your node in LegalizeOp which calls + LegalizeOp on the node's operands, and returns a new node if any of the + operands changed as a result of being legalized. It is likely that not all + targets supported by the SelectionDAG framework will natively support the + new node. In this case, you must also add code in your node's case + statement in LegalizeOp to Expand your node into simpler, legal + operations. The case for ISD::UREM for expanding a remainder into + a divide, multiply, and a subtract is a good example.
  6. +
  7. lib/CodeGen/SelectionDAG/LegalizeDAG.cpp: + If targets may support the new node being added only at certain sizes, you + will also need to add code to your node's case statement in + LegalizeOp to Promote your node's operands to a larger size, and + perform the correct operation. You will also need to add code to + PromoteOp to do this as well. For a good example, see + ISD::BSWAP, + which promotes its operand to a wider size, performs the byteswap, and then + shifts the correct bytes right to emulate the narrower byteswap in the + wider type.
  8. +
  9. lib/CodeGen/SelectionDAG/LegalizeDAG.cpp: + Add a case for your node in ExpandOp to teach the legalizer how to + perform the action represented by the new node on a value that has been + split into high and low halves. This case will be used to support your + node with a 64 bit operand on a 32 bit target.
  10. +
  11. lib/CodeGen/SelectionDAG/DAGCombiner.cpp: + If your node can be combined with itself, or other existing nodes in a + peephole-like fashion, add a visit function for it, and call that function + from . There are several good examples for simple combines you + can do; visitFABS and visitSRL are good starting places. +
  12. +
  13. lib/Target/PowerPC/PPCISelLowering.cpp: + Each target has an implementation of the TargetLowering class, + usually in its own file (although some targets include it in the same + file as the DAGToDAGISel). The default behavior for a target is to + assume that your new node is legal for all types that are legal for + that target. If this target does not natively support your node, then + tell the target to either Promote it (if it is supported at a larger + type) or Expand it. This will cause the code you wrote in + LegalizeOp above to decompose your new node into other legal + nodes for this target.
  14. +
  15. lib/Target/TargetSelectionDAG.td: + Most current targets supported by LLVM generate code using the DAGToDAG + method, where SelectionDAG nodes are pattern matched to target-specific + nodes, which represent individual instructions. In order for the targets + to match an instruction to your new node, you must add a def for that node + to the list in this file, with the appropriate type constraints. Look at + add, bswap, and fadd for examples.
  16. +
  17. lib/Target/PowerPC/PPCInstrInfo.td: + Each target has a tablegen file that describes the target's instruction + set. For targets that use the DAGToDAG instruction selection framework, + add a pattern for your new node that uses one or more target nodes. + Documentation for this is a bit sparse right now, but there are several + decent examples. See the patterns for rotl in + PPCInstrInfo.td.
  18. +
  19. TODO: document complex patterns.
  20. +
  21. llvm/test/Regression/CodeGen/*: Add test cases for your new node + to the test suite. llvm/test/Regression/CodeGen/X86/bswap.ll is + a good example.
  22. +
+ +
+ + + + + +
+ +

WARNING: adding instructions changes the bitcode +format, and it will take some effort to maintain compatibility with +the previous version. Only add an instruction if it is absolutely +necessary.

+ +
    + +
  1. llvm/include/llvm/Instruction.def: + add a number for your instruction and an enum name
  2. + +
  3. llvm/include/llvm/Instructions.h: + add a definition for the class that will represent your instruction
  4. + +
  5. llvm/include/llvm/Support/InstVisitor.h: + add a prototype for a visitor to your new instruction type
  6. + +
  7. llvm/lib/AsmParser/Lexer.l: + add a new token to parse your instruction from assembly text file
  8. + +
  9. llvm/lib/AsmParser/llvmAsmParser.y: + add the grammar on how your instruction can be read and what it will + construct as a result
  10. + +
  11. llvm/lib/Bitcode/Reader/Reader.cpp: + add a case for your instruction and how it will be parsed from bitcode
  12. + +
  13. llvm/lib/VMCore/Instruction.cpp: + add a case for how your instruction will be printed out to assembly
  14. + +
  15. llvm/lib/VMCore/Instructions.cpp: + implement the class you defined in + llvm/include/llvm/Instructions.h
  16. + +
  17. Test your instruction
  18. + +
  19. llvm/lib/Target/*: + Add support for your instruction to code generators, or add a lowering + pass.
  20. + +
  21. llvm/test/Regression/*: add your test cases to the test suite.
  22. + +
+ +

Also, you need to implement (or modify) any analyses or passes that you want +to understand this new instruction.

+ +
+ + + + + + +
+ +

WARNING: adding new types changes the bitcode +format, and will break compatibility with currently-existing LLVM +installations. Only add new types if it is absolutely necessary.

+ +
+ + + + +
+ +
    + +
  1. llvm/include/llvm/Type.h: + add enum for the new type; add static Type* for this type
  2. + +
  3. llvm/lib/VMCore/Type.cpp: + add mapping from TypeID => Type*; + initialize the static Type*
  4. + +
  5. llvm/lib/AsmReader/Lexer.l: + add ability to parse in the type from text assembly
  6. + +
  7. llvm/lib/AsmReader/llvmAsmParser.y: + add a token for that type
  8. + +
+ +
+ + + + +
+ +
    +
  1. llvm/include/llvm/Type.h: + add enum for the new type; add a forward declaration of the type + also
  2. + +
  3. llvm/include/llvm/DerivedTypes.h: + add new class to represent new class in the hierarchy; add forward + declaration to the TypeMap value type
  4. + +
  5. llvm/lib/VMCore/Type.cpp: + add support for derived type to: +
    +
    +std::string getTypeDescription(const Type &Ty,
    +  std::vector<const Type*> &TypeStack)
    +bool TypesEqual(const Type *Ty, const Type *Ty2,
    +  std::map<const Type*, const Type*> & EqTypes)
    +
    +
    + add necessary member functions for type, and factory methods
  6. + +
  7. llvm/lib/AsmReader/Lexer.l: + add ability to parse in the type from text assembly
  8. + +
  9. llvm/lib/BitCode/Writer/Writer.cpp: + modify void BitcodeWriter::outputType(const Type *T) to serialize + your type
  10. + +
  11. llvm/lib/BitCode/Reader/Reader.cpp: + modify const Type *BitcodeReader::ParseType() to read your data + type
  12. + +
  13. llvm/lib/VMCore/AsmWriter.cpp: + modify +
    +
    +void calcTypeName(const Type *Ty,
    +                  std::vector<const Type*> &TypeStack,
    +                  std::map<const Type*,std::string> &TypeNames,
    +                  std::string & Result)
    +
    +
    + to output the new derived type +
  14. + + +
+ +
+ + + +
+
+ Valid CSS + Valid HTML 4.01 + + The LLVM Compiler Infrastructure +
+ Last modified: $Date$ +
+ + + diff --git a/libclamav/c++/llvm/docs/FAQ.html b/libclamav/c++/llvm/docs/FAQ.html new file mode 100644 index 000000000..d62ffd715 --- /dev/null +++ b/libclamav/c++/llvm/docs/FAQ.html @@ -0,0 +1,938 @@ + + + + + LLVM: Frequently Asked Questions + + + + +
+ LLVM: Frequently Asked Questions +
+ +
    +
  1. License +
      +
    1. Why are the LLVM source code and the front-end distributed under + different licenses?
    2. + +
    3. Does the University of Illinois Open Source License really qualify as an + "open source" license?
    4. + +
    5. Can I modify LLVM source code and redistribute the modified source?
    6. + +
    7. Can I modify LLVM source code and redistribute binaries or other tools + based on it, without redistributing the source?
    8. +
  2. + +
  3. Source code +
      +
    1. In what language is LLVM written?
    2. + +
    3. How portable is the LLVM source code?
    4. +
  4. + +
  5. Build Problems +
      +
    1. When I run configure, it finds the wrong C compiler.
    2. + +
    3. The configure script finds the right C compiler, but it uses + the LLVM linker from a previous build. What do I do?
    4. + +
    5. When creating a dynamic library, I get a strange GLIBC error.
    6. + +
    7. I've updated my source tree from Subversion, and now my build is trying + to use a file/directory that doesn't exist.
    8. + +
    9. I've modified a Makefile in my source tree, but my build tree keeps + using the old version. What do I do?
    10. + +
    11. I've upgraded to a new version of LLVM, and I get strange build + errors.
    12. + +
    13. I've built LLVM and am testing it, but the tests freeze.
    14. + +
    15. Why do test results differ when I perform different types of + builds?
    16. + +
    17. Compiling LLVM with GCC 3.3.2 fails, what should I do?
    18. + +
    19. Compiling LLVM with GCC succeeds, but the resulting tools do not work, + what can be wrong?
    20. + +
    21. When I use the test suite, all of the C Backend tests fail. What is + wrong?
    22. + +
    23. After Subversion update, rebuilding gives the error "No rule to make + target".
    24. + +
    25. The llvmc program gives me errors/doesn't + work.
    26. + +
    27. When I compile LLVM-GCC with srcdir == objdir, + it fails. Why?
    28. +
  6. + +
  7. Source Languages +
      +
    1. What source languages are supported?
    2. + +
    3. I'd like to write a self-hosting LLVM compiler. How + should I interface with the LLVM middle-end optimizers and back-end code + generators?
    4. + +
    5. What support is there for higher level source + language constructs for building a compiler?
    6. + +
    7. I don't understand the GetElementPtr + instruction. Help!
    8. +
    + +
  8. Using the GCC Front End +
      +
    1. When I compile software that uses a configure script, the configure + script thinks my system has all of the header files and libraries it is + testing for. How do I get configure to work correctly?
    2. + +
    3. When I compile code using the LLVM GCC front end, it complains that it + cannot find libcrtend.a?
    4. + +
    5. How can I disable all optimizations when compiling code using the LLVM + GCC front end?
    6. + +
    7. Can I use LLVM to convert C++ code to C + code?
    8. + +
    9. Can I compile C or C++ code to + platform-independent LLVM bitcode?
    10. +
    +
  9. + +
  10. Questions about code generated by the GCC front-end +
      +
    1. What is this llvm.global_ctors and + _GLOBAL__I__tmp_webcompile... stuff that happens when I + #include <iostream>?
    2. + +
    3. Where did all of my code go??
    4. + +
    5. What is this "undef" thing that shows up in + my code?
    6. + +
    7. Why does instcombine + simplifycfg turn + a call to a function with a mismatched calling convention into "unreachable"? + Why not make the verifier reject it?
    8. +
    +
  11. +
+ +
+

Written by The LLVM Team

+
+ + + +
+ License +
+ + +
+

Why are the LLVM source code and the front-end distributed under different + licenses?

+
+ +
+

The C/C++ front-ends are based on GCC and must be distributed under the GPL. + Our aim is to distribute LLVM source code under a much less + restrictive license, in particular one that does not compel users who + distribute tools based on modifying the source to redistribute the modified + source code as well.

+
+ +
+

Does the University of Illinois Open Source License really qualify as an + "open source" license?

+
+ +
+

Yes, the license + is certified by + the Open Source Initiative (OSI).

+
+ +
+

Can I modify LLVM source code and redistribute the modified source?

+
+ +
+

Yes. The modified source distribution must retain the copyright notice and + follow the three bulletted conditions listed in + the LLVM + license.

+
+ +
+

Can I modify LLVM source code and redistribute binaries or other tools based + on it, without redistributing the source?

+
+ +
+

Yes. This is why we distribute LLVM under a less restrictive license than + GPL, as explained in the first question above.

+
+ + + + + +
+

In what language is LLVM written?

+
+ +
+

All of the LLVM tools and libraries are written in C++ with extensive use of + the STL.

+
+ +
+

How portable is the LLVM source code?

+
+ +
+

The LLVM source code should be portable to most modern UNIX-like operating +systems. Most of the code is written in standard C++ with operating system +services abstracted to a support library. The tools required to build and test +LLVM have been ported to a plethora of platforms.

+ +

Some porting problems may exist in the following areas:

+ +
    +
  • The GCC front end code is not as portable as the LLVM suite, so it may not + compile as well on unsupported platforms.
  • + +
  • The LLVM build system relies heavily on UNIX shell tools, like the Bourne + Shell and sed. Porting to systems without these tools (MacOS 9, Plan 9) + will require more effort.
  • +
+ +
+ + + + + +
+

When I run configure, it finds the wrong C compiler.

+
+ +
+

The configure script attempts to locate first gcc and then + cc, unless it finds compiler paths set in CC + and CXX for the C and C++ compiler, respectively.

+ +

If configure finds the wrong compiler, either adjust your + PATH environment variable or set CC and CXX + explicitly.

+ +
+ +
+

The configure script finds the right C compiler, but it uses the + LLVM linker from a previous build. What do I do?

+
+ +
+

The configure script uses the PATH to find executables, so + if it's grabbing the wrong linker/assembler/etc, there are two ways to fix + it:

+ +
    +
  1. Adjust your PATH environment variable so that the correct + program appears first in the PATH. This may work, but may not be + convenient when you want them first in your path for other + work.

  2. + +
  3. Run configure with an alternative PATH that is + correct. In a Borne compatible shell, the syntax would be:

    + +
    +% PATH=[the path without the bad program] ./configure ...
    +
    + +

    This is still somewhat inconvenient, but it allows configure + to do its work without having to adjust your PATH + permanently.

  4. +
+
+ +
+

When creating a dynamic library, I get a strange GLIBC error.

+
+ +
+

Under some operating systems (i.e. Linux), libtool does not work correctly if + GCC was compiled with the --disable-shared option. To work around this, + install your own version of GCC that has shared libraries enabled by + default.

+
+ +
+

I've updated my source tree from Subversion, and now my build is trying to + use a file/directory that doesn't exist.

+
+ +
+

You need to re-run configure in your object directory. When new Makefiles + are added to the source tree, they have to be copied over to the object tree + in order to be used by the build.

+
+ +
+

I've modified a Makefile in my source tree, but my build tree keeps using the + old version. What do I do?

+
+ +
+

If the Makefile already exists in your object tree, you can just run the + following command in the top level directory of your object tree:

+ +
+% ./config.status <relative path to Makefile>
+
+ +

If the Makefile is new, you will have to modify the configure script to copy + it over.

+
+ +
+

I've upgraded to a new version of LLVM, and I get strange build errors.

+
+ +
+ +

Sometimes, changes to the LLVM source code alters how the build system works. + Changes in libtool, autoconf, or header file dependencies are especially + prone to this sort of problem.

+ +

The best thing to try is to remove the old files and re-build. In most + cases, this takes care of the problem. To do this, just type make + clean and then make in the directory that fails to build.

+
+ +
+

I've built LLVM and am testing it, but the tests freeze.

+
+ +
+

This is most likely occurring because you built a profile or release + (optimized) build of LLVM and have not specified the same information on the + gmake command line.

+ +

For example, if you built LLVM with the command:

+ +
+% gmake ENABLE_PROFILING=1
+
+ +

...then you must run the tests with the following commands:

+ +
+% cd llvm/test
+% gmake ENABLE_PROFILING=1
+
+
+ +
+

Why do test results differ when I perform different types of builds?

+
+ +
+

The LLVM test suite is dependent upon several features of the LLVM tools and + libraries.

+ +

First, the debugging assertions in code are not enabled in optimized or + profiling builds. Hence, tests that used to fail may pass.

+ +

Second, some tests may rely upon debugging options or behavior that is only + available in the debug build. These tests will fail in an optimized or + profile build.

+
+ +
+

Compiling LLVM with GCC 3.3.2 fails, what should I do?

+
+ +
+

This is a bug in + GCC, and affects projects other than LLVM. Try upgrading or downgrading + your GCC.

+
+ +
+

Compiling LLVM with GCC succeeds, but the resulting tools do not work, what + can be wrong?

+
+ +
+

Several versions of GCC have shown a weakness in miscompiling the LLVM + codebase. Please consult your compiler version (gcc --version) to + find out whether it is broken. + If so, your only option is to upgrade GCC to a known good version.

+
+ +
+

After Subversion update, rebuilding gives the error "No rule to make + target".

+
+ +
+

If the error is of the form:

+ +
+gmake[2]: *** No rule to make target `/path/to/somefile', needed by
+`/path/to/another/file.d'.
+Stop. +
+ +

This may occur anytime files are moved within the Subversion repository or + removed entirely. In this case, the best solution is to erase all + .d files, which list dependencies for source files, and rebuild:

+ +
+% cd $LLVM_OBJ_DIR
+% rm -f `find . -name \*\.d` 
+% gmake 
+
+ +

In other cases, it may be necessary to run make clean before + rebuilding.

+
+ + + +
+

llvmc is experimental and isn't really supported. We suggest + using llvm-gcc instead.

+
+ + + +
+

The GNUmakefile in the top-level directory of LLVM-GCC is a special + Makefile used by Apple to invoke the build_gcc script after + setting up a special environment. This has the unforunate side-effect that + trying to build LLVM-GCC with srcdir == objdir in a "non-Apple way" invokes + the GNUmakefile instead of Makefile. Because the + environment isn't set up correctly to do this, the build fails.

+ +

People not building LLVM-GCC the "Apple way" need to build LLVM-GCC with + srcdir != objdir, or simply remove the GNUmakefile entirely.

+ +

We regret the inconvenience.

+
+ + + + + + +
+

LLVM currently has full support for C and C++ source languages. These are + available through a special version of GCC that LLVM calls the + C Front End

+ +

There is an incomplete version of a Java front end available in the + java module. There is no documentation on this yet so you'll need to + download the code, compile it, and try it.

+ +

The PyPy developers are working on integrating LLVM into the PyPy backend so + that PyPy language can translate to LLVM.

+
+ + + +
+

Your compiler front-end will communicate with LLVM by creating a module in + the LLVM intermediate representation (IR) format. Assuming you want to write + your language's compiler in the language itself (rather than C++), there are + 3 major ways to tackle generating LLVM IR from a front-end:

+ +
    +
  • Call into the LLVM libraries code using your language's FFI + (foreign function interface). + +
      +
    • for: best tracks changes to the LLVM IR, .ll syntax, and .bc + format
    • + +
    • for: enables running LLVM optimization passes without a + emit/parse overhead
    • + +
    • for: adapts well to a JIT context
    • + +
    • against: lots of ugly glue code to write
    • +
  • + +
  • Emit LLVM assembly from your compiler's native language. +
      +
    • for: very straightforward to get started
    • + +
    • against: the .ll parser is slower than the bitcode reader + when interfacing to the middle end
    • + +
    • against: you'll have to re-engineer the LLVM IR object model + and asm writer in your language
    • + +
    • against: it may be harder to track changes to the IR
    • +
  • + +
  • Emit LLVM bitcode from your compiler's native language. + +
      +
    • for: can use the more-efficient bitcode reader when + interfacing to the middle end
    • + +
    • against: you'll have to re-engineer the LLVM IR object + model and bitcode writer in your language
    • + +
    • against: it may be harder to track changes to the IR
    • +
  • +
+ +

If you go with the first option, the C bindings in include/llvm-c should help + a lot, since most languages have strong support for interfacing with C. The + most common hurdle with calling C from managed code is interfacing with the + garbage collector. The C interface was designed to require very little memory + management, and so is straightforward in this regard.

+
+ + + +
+

Currently, there isn't much. LLVM supports an intermediate representation + which is useful for code representation but will not support the high level + (abstract syntax tree) representation needed by most compilers. There are no + facilities for lexical nor semantic analysis. There is, however, a mostly + implemented configuration-driven + compiler driver which simplifies the task + of running optimizations, linking, and executable generation.

+
+ + + + + + + + +
+

When I compile software that uses a configure script, the configure script + thinks my system has all of the header files and libraries it is testing for. + How do I get configure to work correctly?

+
+ +
+

The configure script is getting things wrong because the LLVM linker allows + symbols to be undefined at link time (so that they can be resolved during JIT + or translation to the C back end). That is why configure thinks your system + "has everything."

+ +

To work around this, perform the following steps:

+ +
    +
  1. Make sure the CC and CXX environment variables contains the full path to + the LLVM GCC front end.
  2. + +
  3. Make sure that the regular C compiler is first in your PATH.
  4. + +
  5. Add the string "-Wl,-native" to your CFLAGS environment variable.
  6. +
+ +

This will allow the llvm-ld linker to create a native code + executable instead of shell script that runs the JIT. Creating native code + requires standard linkage, which in turn will allow the configure script to + find out if code is not linking on your system because the feature isn't + available on your system.

+
+ +
+

When I compile code using the LLVM GCC front end, it complains that it cannot + find libcrtend.a. +

+
+ +
+

The only way this can happen is if you haven't installed the runtime + library. To correct this, do:

+ +
+% cd llvm/runtime
+% make clean ; make install-bytecode
+
+
+ +
+

How can I disable all optimizations when compiling code using the LLVM GCC + front end?

+
+ +
+

Passing "-Wa,-disable-opt -Wl,-disable-opt" will disable *all* cleanup and + optimizations done at the llvm level, leaving you with the truly horrible + code that you desire.

+
+ + + + +
+

Yes, you can use LLVM to convert code from any language LLVM supports to C. + Note that the generated C code will be very low level (all loops are lowered + to gotos, etc) and not very pretty (comments are stripped, original source + formatting is totally lost, variables are renamed, expressions are + regrouped), so this may not be what you're looking for. Also, there are + several limitations noted below.

+ +

Use commands like this:

+ +
    +
  1. Compile your program as normal with llvm-g++:

    + +
    +% llvm-g++ x.cpp -o program
    +
    + +

    or:

    + +
    +% llvm-g++ a.cpp -c
    +% llvm-g++ b.cpp -c
    +% llvm-g++ a.o b.o -o program
    +
    + +

    With llvm-gcc3, this will generate program and program.bc. The .bc + file is the LLVM version of the program all linked together.

  2. + +
  3. Convert the LLVM code to C code, using the LLC tool with the C + backend:

    + +
    +% llc -march=c program.bc -o program.c
    +
  4. + +
  5. Finally, compile the C file:

    + +
    +% cc x.c
    +
  6. + +
+ +

Using LLVM does not eliminate the need for C++ library support. If you use + the llvm-g++ front-end, the generated code will depend on g++'s C++ support + libraries in the same way that code generated from g++ would. If you use + another C++ front-end, the generated code will depend on whatever library + that front-end would normally require.

+ +

If you are working on a platform that does not provide any C++ libraries, you + may be able to manually compile libstdc++ to LLVM bitcode, statically link it + into your program, then use the commands above to convert the whole result + into C code. Alternatively, you might compile the libraries and your + application into two different chunks of C code and link them.

+ +

Note that, by default, the C back end does not support exception handling. + If you want/need it for a certain program, you can enable it by passing + "-enable-correct-eh-support" to the llc program. The resultant code will use + setjmp/longjmp to implement exception support that is relatively slow, and + not C++-ABI-conforming on most platforms, but otherwise correct.

+ +

Also, there are a number of other limitations of the C backend that cause it + to produce code that does not fully conform to the C++ ABI on most + platforms. Some of the C++ programs in LLVM's test suite are known to fail + when compiled with the C back end because of ABI incompatibilities with + standard C++ libraries.

+
+ + + +
+

No. C and C++ are inherently platform-dependent languages. The most obvious + example of this is the preprocessor. A very common way that C code is made + portable is by using the preprocessor to include platform-specific code. In + practice, information about other platforms is lost after preprocessing, so + the result is inherently dependent on the platform that the preprocessing was + targeting.

+ +

Another example is sizeof. It's common for sizeof(long) to + vary between platforms. In most C front-ends, sizeof is expanded to + a constant immediately, thus hard-wiring a platform-specific detail.

+ +

Also, since many platforms define their ABIs in terms of C, and since LLVM is + lower-level than C, front-ends currently must emit platform-specific IR in + order to have the result conform to the platform ABI.

+
+ + + + + + +
+

If you #include the <iostream> header into a C++ + translation unit, the file will probably use + the std::cin/std::cout/... global objects. However, C++ + does not guarantee an order of initialization between static objects in + different translation units, so if a static ctor/dtor in your .cpp file + used std::cout, for example, the object would not necessarily be + automatically initialized before your use.

+ +

To make std::cout and friends work correctly in these scenarios, the + STL that we use declares a static object that gets created in every + translation unit that includes <iostream>. This object has a + static constructor and destructor that initializes and destroys the global + iostream objects before they could possibly be used in the file. The code + that you see in the .ll file corresponds to the constructor and destructor + registration code. +

+ +

If you would like to make it easier to understand the LLVM code + generated by the compiler in the demo page, consider using printf() + instead of iostreams to print values.

+
+ + + + + +
+

If you are using the LLVM demo page, you may often wonder what happened to + all of the code that you typed in. Remember that the demo script is running + the code through the LLVM optimizers, so if your code doesn't actually do + anything useful, it might all be deleted.

+ +

To prevent this, make sure that the code is actually needed. For example, if + you are computing some expression, return the value from the function instead + of leaving it in a local variable. If you really want to constrain the + optimizer, you can read from and assign to volatile global + variables.

+
+ + + + + +
+

undef is the LLVM way of + representing a value that is not defined. You can get these if you do not + initialize a variable before you use it. For example, the C function:

+ +
+int X() { int i; return i; }
+
+ +

Is compiled to "ret i32 undef" because "i" never has a + value specified for it.

+
+ + + + + +
+

This is a common problem run into by authors of front-ends that are using +custom calling conventions: you need to make sure to set the right calling +convention on both the function and on each call to the function. For example, +this code:

+ +
+define fastcc void @foo() {
+        ret void
+}
+define void @bar() {
+        call void @foo( )
+        ret void
+}
+
+ +

Is optimized to:

+ +
+define fastcc void @foo() {
+	ret void
+}
+define void @bar() {
+	unreachable
+}
+
+ +

... with "opt -instcombine -simplifycfg". This often bites people because +"all their code disappears". Setting the calling convention on the caller and +callee is required for indirect calls to work, so people often ask why not make +the verifier reject this sort of thing.

+ +

The answer is that this code has undefined behavior, but it is not illegal. +If we made it illegal, then every transformation that could potentially create +this would have to ensure that it doesn't, and there is valid code that can +create this sort of construct (in dead code). The sorts of things that can +cause this to happen are fairly contrived, but we still need to accept them. +Here's an example:

+ +
+define fastcc void @foo() {
+        ret void
+}
+define internal void @bar(void()* %FP, i1 %cond) {
+        br i1 %cond, label %T, label %F
+T:  
+        call void %FP()
+        ret void
+F:
+        call fastcc void %FP()
+        ret void
+}
+define void @test() {
+        %X = or i1 false, false
+        call void @bar(void()* @foo, i1 %X)
+        ret void
+} 
+
+ +

In this example, "test" always passes @foo/false into bar, which ensures that + it is dynamically called with the right calling conv (thus, the code is + perfectly well defined). If you run this through the inliner, you get this + (the explicit "or" is there so that the inliner doesn't dead code eliminate + a bunch of stuff): +

+ +
+define fastcc void @foo() {
+	ret void
+}
+define void @test() {
+	%X = or i1 false, false
+	br i1 %X, label %T.i, label %F.i
+T.i:
+	call void @foo()
+	br label %bar.exit
+F.i:
+	call fastcc void @foo()
+	br label %bar.exit
+bar.exit:
+	ret void
+}
+
+ +

Here you can see that the inlining pass made an undefined call to @foo with + the wrong calling convention. We really don't want to make the inliner have + to know about this sort of thing, so it needs to be valid code. In this case, + dead code elimination can trivially remove the undefined code. However, if %X + was an input argument to @test, the inliner would produce this: +

+ +
+define fastcc void @foo() {
+	ret void
+}
+
+define void @test(i1 %X) {
+	br i1 %X, label %T.i, label %F.i
+T.i:
+	call void @foo()
+	br label %bar.exit
+F.i:
+	call fastcc void @foo()
+	br label %bar.exit
+bar.exit:
+	ret void
+}
+
+ +

The interesting thing about this is that %X must be false for the +code to be well-defined, but no amount of dead code elimination will be able to +delete the broken call as unreachable. However, since instcombine/simplifycfg +turns the undefined call into unreachable, we end up with a branch on a +condition that goes to unreachable: a branch to unreachable can never happen, so +"-inline -instcombine -simplifycfg" is able to produce:

+ +
+define fastcc void @foo() {
+	ret void
+}
+define void @test(i1 %X) {
+F.i:
+	call fastcc void @foo()
+	ret void
+}
+
+ +
+ + + +
+
+ Valid CSS + Valid HTML 4.01 + + LLVM Compiler Infrastructure
+ Last modified: $Date$ +
+ + + diff --git a/libclamav/c++/llvm/docs/GCCFEBuildInstrs.html b/libclamav/c++/llvm/docs/GCCFEBuildInstrs.html new file mode 100644 index 000000000..b675ee76a --- /dev/null +++ b/libclamav/c++/llvm/docs/GCCFEBuildInstrs.html @@ -0,0 +1,279 @@ + + + + + + Building the LLVM GCC Front-End + + + +
+ Building the LLVM GCC Front-End +
+ +
    +
  1. Building llvm-gcc from Source
  2. +
  3. Building the Ada front-end
  4. +
  5. Building the Fortran front-end
  6. +
  7. License Information
  8. +
+ +
+

Written by the LLVM Team

+
+ + +

Building llvm-gcc from Source

+ + +
+ +

This section describes how to acquire and build llvm-gcc 4.2, which is based +on the GCC 4.2.1 front-end. Supported languages are Ada, C, C++, Fortran, +Objective-C and Objective-C++. Note that the instructions for building these +front-ends are completely different (and much easier!) than those for building +llvm-gcc3 in the past.

+ +
    +
  1. Retrieve the appropriate llvm-gcc-4.2-version.source.tar.gz + archive from the LLVM web + site.

    + +

    It is also possible to download the sources of the llvm-gcc front end + from a read-only mirror using subversion. To check out the 4.2 code + for first time use:

    + +
    +
    +svn co http://llvm.org/svn/llvm-project/llvm-gcc-4.2/trunk dst-directory
    +
    +
    + +

    After that, the code can be be updated in the destination directory + using:

    + +
    +
    svn update
    +
    + +

    The mirror is brought up to date every evening.

  2. + +
  3. Follow the directions in the top-level README.LLVM file for + up-to-date instructions on how to build llvm-gcc. See below for building + with support for Ada or Fortran. +
+ +
+ + +

Building the Ada front-end

+ + +
+

Building with support for Ada amounts to following the directions in the +top-level README.LLVM file, adding ",ada" to EXTRALANGS, for example: +EXTRALANGS=,ada

+ +

There are some complications however:

+ +
    +
  1. The only platform for which the Ada front-end is known to build is + 32 bit intel x86 running linux. It is unlikely to build for other + systems without some work.

  2. +
  3. The build requires having a compiler that supports Ada, C and C++. + The Ada front-end is written in Ada so an Ada compiler is needed to + build it. Compilers known to work with the + LLVM 2.5 release + are gcc-4.2 and the + 2005, 2006 and 2007 versions of the + GNAT GPL Edition. + GNAT GPL 2008, gcc-4.3 and later will not work. + The LLVM parts of llvm-gcc are written in C++ so a C++ compiler is + needed to build them. The rest of gcc is written in C. + Some linux distributions provide a version of gcc that supports all + three languages (the Ada part often comes as an add-on package to + the rest of gcc). Otherwise it is possible to combine two versions + of gcc, one that supports Ada and C (such as the + 2007 GNAT GPL Edition) + and another which supports C++, see below.

  4. +
  5. Because the Ada front-end is experimental, it is wise to build the + compiler with checking enabled. This causes it to run much slower, but + helps catch mistakes in the compiler (please report any problems using + LLVM bugzilla).

  6. +
  7. The Ada front-end fails to + bootstrap, due to lack of LLVM support for + setjmp/longjmp style exception handling (used + internally by the compiler), so you must specify + --disable-bootstrap.

  8. +
+ +

Supposing appropriate compilers are available, llvm-gcc with Ada support can + be built on an x86-32 linux box using the following recipe:

+ +
    +
  1. Download the LLVM source + and unpack it:

    + +
    +wget http://llvm.org/releases/2.5/llvm-2.5.tar.gz
    +tar xzf llvm-2.5.tar.gz
    +mv llvm-2.5 llvm
    +
    + +

    or check out the + latest version from subversion:

    + +
    svn co http://llvm.org/svn/llvm-project/llvm/trunk llvm
    + +
  2. + +
  3. Download the + llvm-gcc-4.2 source + and unpack it:

    + +
    +wget http://llvm.org/releases/2.5/llvm-gcc-4.2-2.5.source.tar.gz
    +tar xzf llvm-gcc-4.2-2.5.source.tar.gz
    +mv llvm-gcc4.2-2.5.source llvm-gcc-4.2
    +
    + +

    or check out the + latest version from subversion:

    + +
    +svn co http://llvm.org/svn/llvm-project/llvm-gcc-4.2/trunk llvm-gcc-4.2
    +
    +
  4. + +
  5. Make a build directory llvm-objects for llvm and make it the + current directory:

    + +
    +mkdir llvm-objects
    +cd llvm-objects
    +
    +
  6. + +
  7. Configure LLVM (here it is configured to install into /usr/local):

    + +
    +../llvm/configure --prefix=/usr/local --enable-optimized --enable-assertions
    +
    + +

    If you have a multi-compiler setup and the C++ compiler is not the + default, then you can configure like this:

    + +
    +CXX=PATH_TO_C++_COMPILER ../llvm/configure --prefix=/usr/local --enable-optimized --enable-assertions
    +
    + +

    To compile without checking (not recommended), replace + --enable-assertions with --disable-assertions.

    + +
  8. + +
  9. Build LLVM:

    + +
    +make
    +
    +
  10. + +
  11. Install LLVM (optional):

    + +
    +make install
    +
    +
  12. + +
  13. Make a build directory llvm-gcc-4.2-objects for llvm-gcc and make it the + current directory:

    + +
    +cd ..
    +mkdir llvm-gcc-4.2-objects
    +cd llvm-gcc-4.2-objects
    +
    +
  14. + +
  15. Configure llvm-gcc (here it is configured to install into /usr/local). + The --enable-checking flag turns on sanity checks inside the compiler. + To turn off these checks (not recommended), replace --enable-checking + with --disable-checking. + Additional languages can be appended to the --enable-languages switch, + for example --enable-languages=ada,c,c++.

    + +
    +../llvm-gcc-4.2/configure --prefix=/usr/local --enable-languages=ada,c \
    +                          --enable-checking --enable-llvm=$PWD/../llvm-objects \
    +			  --disable-bootstrap --disable-multilib
    +
    + +

    If you have a multi-compiler setup, then you can configure like this:

    + +
    +export CC=PATH_TO_C_AND_ADA_COMPILER
    +export CXX=PATH_TO_C++_COMPILER
    +../llvm-gcc-4.2/configure --prefix=/usr/local --enable-languages=ada,c \
    +                          --enable-checking --enable-llvm=$PWD/../llvm-objects \
    +			  --disable-bootstrap --disable-multilib
    +
    +
  16. + +
  17. Build and install the compiler:

    + +
    +make
    +make install
    +
    +
  18. +
+ +
+ + +

Building the Fortran front-end

+ + +
+

To build with support for Fortran, follow the directions in the top-level +README.LLVM file, adding ",fortran" to EXTRALANGS, for example:

+ +
+EXTRALANGS=,fortran
+
+ +
+ + +

License Information

+ + +
+

+The LLVM GCC frontend is licensed to you under the GNU General Public License +and the GNU Lesser General Public License. Please see the files COPYING and +COPYING.LIB for more details. +

+ +

+More information is available in the FAQ. +

+
+ + + +
+
+ Valid CSS + Valid HTML 4.01 + + LLVM Compiler Infrastructure
+ Last modified: $Date$ +
+ + + diff --git a/libclamav/c++/llvm/docs/GarbageCollection.html b/libclamav/c++/llvm/docs/GarbageCollection.html new file mode 100644 index 000000000..d0b651eb6 --- /dev/null +++ b/libclamav/c++/llvm/docs/GarbageCollection.html @@ -0,0 +1,1387 @@ + + + + + Accurate Garbage Collection with LLVM + + + + + +
+ Accurate Garbage Collection with LLVM +
+ +
    +
  1. Introduction + +
  2. + +
  3. Getting started + +
  4. + +
  5. Core support + +
  6. + +
  7. Compiler plugin interface + +
  8. + +
  9. Implementing a collector runtime + +
  10. + +
  11. References
  12. + +
+ +
+

Written by Chris Lattner and + Gordon Henriksen

+
+ + + + + +
+ +

Garbage collection is a widely used technique that frees the programmer from +having to know the lifetimes of heap objects, making software easier to produce +and maintain. Many programming languages rely on garbage collection for +automatic memory management. There are two primary forms of garbage collection: +conservative and accurate.

+ +

Conservative garbage collection often does not require any special support +from either the language or the compiler: it can handle non-type-safe +programming languages (such as C/C++) and does not require any special +information from the compiler. The +Boehm collector is +an example of a state-of-the-art conservative collector.

+ +

Accurate garbage collection requires the ability to identify all pointers in +the program at run-time (which requires that the source-language be type-safe in +most cases). Identifying pointers at run-time requires compiler support to +locate all places that hold live pointer variables at run-time, including the +processor stack and registers.

+ +

Conservative garbage collection is attractive because it does not require any +special compiler support, but it does have problems. In particular, because the +conservative garbage collector cannot know that a particular word in the +machine is a pointer, it cannot move live objects in the heap (preventing the +use of compacting and generational GC algorithms) and it can occasionally suffer +from memory leaks due to integer values that happen to point to objects in the +program. In addition, some aggressive compiler transformations can break +conservative garbage collectors (though these seem rare in practice).

+ +

Accurate garbage collectors do not suffer from any of these problems, but +they can suffer from degraded scalar optimization of the program. In particular, +because the runtime must be able to identify and update all pointers active in +the program, some optimizations are less effective. In practice, however, the +locality and performance benefits of using aggressive garbage collection +techniques dominates any low-level losses.

+ +

This document describes the mechanisms and interfaces provided by LLVM to +support accurate garbage collection.

+ +
+ + + + +
+ +

LLVM's intermediate representation provides garbage +collection intrinsics that offer support for a broad class of +collector models. For instance, the intrinsics permit:

+ +
    +
  • semi-space collectors
  • +
  • mark-sweep collectors
  • +
  • generational collectors
  • +
  • reference counting
  • +
  • incremental collectors
  • +
  • concurrent collectors
  • +
  • cooperative collectors
  • +
+ +

We hope that the primitive support built into the LLVM IR is sufficient to +support a broad class of garbage collected languages including Scheme, ML, Java, +C#, Perl, Python, Lua, Ruby, other scripting languages, and more.

+ +

However, LLVM does not itself provide a garbage collector—this should +be part of your language's runtime library. LLVM provides a framework for +compile time code generation plugins. The role of these +plugins is to generate code and data structures which conforms to the binary +interface specified by the runtime library. This is similar to the +relationship between LLVM and DWARF debugging info, for example. The +difference primarily lies in the lack of an established standard in the domain +of garbage collection—thus the plugins.

+ +

The aspects of the binary interface with which LLVM's GC support is +concerned are:

+ +
    +
  • Creation of GC-safe points within code where collection is allowed to + execute safely.
  • +
  • Computation of the stack map. For each safe point in the code, object + references within the stack frame must be identified so that the + collector may traverse and perhaps update them.
  • +
  • Write barriers when storing object references to the heap. These are + commonly used to optimize incremental scans in generational + collectors.
  • +
  • Emission of read barriers when loading object references. These are + useful for interoperating with concurrent collectors.
  • +
+ +

There are additional areas that LLVM does not directly address:

+ +
    +
  • Registration of global roots with the runtime.
  • +
  • Registration of stack map entries with the runtime.
  • +
  • The functions used by the program to allocate memory, trigger a + collection, etc.
  • +
  • Computation or compilation of type maps, or registration of them with + the runtime. These are used to crawl the heap for object + references.
  • +
+ +

In general, LLVM's support for GC does not include features which can be +adequately addressed with other features of the IR and does not specify a +particular binary interface. On the plus side, this means that you should be +able to integrate LLVM with an existing runtime. On the other hand, it leaves +a lot of work for the developer of a novel language. However, it's easy to get +started quickly and scale up to a more sophisticated implementation as your +compiler matures.

+ +
+ + + + + +
+ +

Using a GC with LLVM implies many things, for example:

+ +
    +
  • Write a runtime library or find an existing one which implements a GC + heap.
      +
    1. Implement a memory allocator.
    2. +
    3. Design a binary interface for the stack map, used to identify + references within a stack frame on the machine stack.*
    4. +
    5. Implement a stack crawler to discover functions on the call stack.*
    6. +
    7. Implement a registry for global roots.
    8. +
    9. Design a binary interface for type maps, used to identify references + within heap objects.
    10. +
    11. Implement a collection routine bringing together all of the above.
    12. +
  • +
  • Emit compatible code from your compiler.
      +
    • Initialization in the main function.
    • +
    • Use the gc "..." attribute to enable GC code generation + (or F.setGC("...")).
    • +
    • Use @llvm.gcroot to mark stack roots.
    • +
    • Use @llvm.gcread and/or @llvm.gcwrite to + manipulate GC references, if necessary.
    • +
    • Allocate memory using the GC allocation routine provided by the + runtime library.
    • +
    • Generate type maps according to your runtime's binary interface.
    • +
  • +
  • Write a compiler plugin to interface LLVM with the runtime library.*
      +
    • Lower @llvm.gcread and @llvm.gcwrite to appropriate + code sequences.*
    • +
    • Compile LLVM's stack map to the binary form expected by the + runtime.
    • +
  • +
  • Load the plugin into the compiler. Use llc -load or link the + plugin statically with your language's compiler.*
  • +
  • Link program executables with the runtime.
  • +
+ +

To help with several of these tasks (those indicated with a *), LLVM +includes a highly portable, built-in ShadowStack code generator. It is compiled +into llc and works even with the interpreter and C backends.

+ +
+ + + + +
+ +

To turn the shadow stack on for your functions, first call:

+ +
F.setGC("shadow-stack");
+ +

for each function your compiler emits. Since the shadow stack is built into +LLVM, you do not need to load a plugin.

+ +

Your compiler must also use @llvm.gcroot as documented. +Don't forget to create a root for each intermediate value that is generated +when evaluating an expression. In h(f(), g()), the result of +f() could easily be collected if evaluating g() triggers a +collection.

+ +

There's no need to use @llvm.gcread and @llvm.gcwrite over +plain load and store for now. You will need them when +switching to a more advanced GC.

+ +
+ + + + +
+ +

The shadow stack doesn't imply a memory allocation algorithm. A semispace +collector or building atop malloc are great places to start, and can +be implemented with very little code.

+ +

When it comes time to collect, however, your runtime needs to traverse the +stack roots, and for this it needs to integrate with the shadow stack. Luckily, +doing so is very simple. (This code is heavily commented to help you +understand the data structure, but there are only 20 lines of meaningful +code.)

+ +
+ +
/// @brief The map for a single function's stack frame. One of these is
+///        compiled as constant data into the executable for each function.
+/// 
+/// Storage of metadata values is elided if the %metadata parameter to
+/// @llvm.gcroot is null.
+struct FrameMap {
+  int32_t NumRoots;    //< Number of roots in stack frame.
+  int32_t NumMeta;     //< Number of metadata entries. May be < NumRoots.
+  const void *Meta[0]; //< Metadata for each root.
+};
+
+/// @brief A link in the dynamic shadow stack. One of these is embedded in the
+///        stack frame of each function on the call stack.
+struct StackEntry {
+  StackEntry *Next;    //< Link to next stack entry (the caller's).
+  const FrameMap *Map; //< Pointer to constant FrameMap.
+  void *Roots[0];      //< Stack roots (in-place array).
+};
+
+/// @brief The head of the singly-linked list of StackEntries. Functions push
+///        and pop onto this in their prologue and epilogue.
+/// 
+/// Since there is only a global list, this technique is not threadsafe.
+StackEntry *llvm_gc_root_chain;
+
+/// @brief Calls Visitor(root, meta) for each GC root on the stack.
+///        root and meta are exactly the values passed to
+///        @llvm.gcroot.
+/// 
+/// Visitor could be a function to recursively mark live objects. Or it
+/// might copy them to another heap or generation.
+/// 
+/// @param Visitor A function to invoke for every GC root on the stack.
+void visitGCRoots(void (*Visitor)(void **Root, const void *Meta)) {
+  for (StackEntry *R = llvm_gc_root_chain; R; R = R->Next) {
+    unsigned i = 0;
+    
+    // For roots [0, NumMeta), the metadata pointer is in the FrameMap.
+    for (unsigned e = R->Map->NumMeta; i != e; ++i)
+      Visitor(&R->Roots[i], R->Map->Meta[i]);
+    
+    // For roots [NumMeta, NumRoots), the metadata pointer is null.
+    for (unsigned e = R->Map->NumRoots; i != e; ++i)
+      Visitor(&R->Roots[i], NULL);
+  }
+}
+ + + + +
+ +

Unlike many GC algorithms which rely on a cooperative code generator to +compile stack maps, this algorithm carefully maintains a linked list of stack +roots [Henderson2002]. This so-called "shadow stack" +mirrors the machine stack. Maintaining this data structure is slower than using +a stack map compiled into the executable as constant data, but has a significant +portability advantage because it requires no special support from the target +code generator, and does not require tricky platform-specific code to crawl +the machine stack.

+ +

The tradeoff for this simplicity and portability is:

+ +
    +
  • High overhead per function call.
  • +
  • Not thread-safe.
  • +
+ +

Still, it's an easy way to get started. After your compiler and runtime are +up and running, writing a plugin will allow you to take +advantage of more advanced GC features of LLVM +in order to improve performance.

+ +
+ + + + + +
+ +

This section describes the garbage collection facilities provided by the +LLVM intermediate representation. The exact behavior +of these IR features is specified by the binary interface implemented by a +code generation plugin, not by this document.

+ +

These facilities are limited to those strictly necessary; they are not +intended to be a complete interface to any garbage collector. A program will +need to interface with the GC library using the facilities provided by that +program.

+ +
+ + + + +
+ define ty @name(...) gc "name" { ... +
+ +
+ +

The gc function attribute is used to specify the desired GC style +to the compiler. Its programmatic equivalent is the setGC method of +Function.

+ +

Setting gc "name" on a function triggers a search for a +matching code generation plugin "name"; it is that plugin which defines +the exact nature of the code generated to support GC. If none is found, the +compiler will raise an error.

+ +

Specifying the GC style on a per-function basis allows LLVM to link together +programs that use different garbage collection algorithms (or none at all).

+ +
+ + + + +
+ void @llvm.gcroot(i8** %ptrloc, i8* %metadata) +
+ +
+ +

The llvm.gcroot intrinsic is used to inform LLVM that a stack +variable references an object on the heap and is to be tracked for garbage +collection. The exact impact on generated code is specified by a compiler plugin.

+ +

A compiler which uses mem2reg to raise imperative code using alloca +into SSA form need only add a call to @llvm.gcroot for those variables +which a pointers into the GC heap.

+ +

It is also important to mark intermediate values with llvm.gcroot. +For example, consider h(f(), g()). Beware leaking the result of +f() in the case that g() triggers a collection.

+ +

The first argument must be a value referring to an alloca instruction +or a bitcast of an alloca. The second contains a pointer to metadata that +should be associated with the pointer, and must be a constant or global +value address. If your target collector uses tags, use a null pointer for +metadata.

+ +

The %metadata argument can be used to avoid requiring heap objects +to have 'isa' pointers or tag bits. [Appel89, Goldberg91, Tolmach94] If +specified, its value will be tracked along with the location of the pointer in +the stack frame.

+ +

Consider the following fragment of Java code:

+ +
+       {
+         Object X;   // A null-initialized reference to an object
+         ...
+       }
+
+ +

This block (which may be located in the middle of a function or in a loop +nest), could be compiled to this LLVM code:

+ +
+Entry:
+   ;; In the entry block for the function, allocate the
+   ;; stack space for X, which is an LLVM pointer.
+   %X = alloca %Object*
+   
+   ;; Tell LLVM that the stack space is a stack root.
+   ;; Java has type-tags on objects, so we pass null as metadata.
+   %tmp = bitcast %Object** %X to i8**
+   call void @llvm.gcroot(i8** %X, i8* null)
+   ...
+
+   ;; "CodeBlock" is the block corresponding to the start
+   ;;  of the scope above.
+CodeBlock:
+   ;; Java null-initializes pointers.
+   store %Object* null, %Object** %X
+
+   ...
+
+   ;; As the pointer goes out of scope, store a null value into
+   ;; it, to indicate that the value is no longer live.
+   store %Object* null, %Object** %X
+   ...
+
+ +
+ + + + +
+ +

Some collectors need to be informed when the mutator (the program that needs +garbage collection) either reads a pointer from or writes a pointer to a field +of a heap object. The code fragments inserted at these points are called +read barriers and write barriers, respectively. The amount of +code that needs to be executed is usually quite small and not on the critical +path of any computation, so the overall performance impact of the barrier is +tolerable.

+ +

Barriers often require access to the object pointer rather than the +derived pointer (which is a pointer to the field within the +object). Accordingly, these intrinsics take both pointers as separate arguments +for completeness. In this snippet, %object is the object pointer, and +%derived is the derived pointer:

+ +
+    ;; An array type.
+    %class.Array = type { %class.Object, i32, [0 x %class.Object*] }
+    ...
+
+    ;; Load the object pointer from a gcroot.
+    %object = load %class.Array** %object_addr
+
+    ;; Compute the derived pointer.
+    %derived = getelementptr %object, i32 0, i32 2, i32 %n
+ +

LLVM does not enforce this relationship between the object and derived +pointer (although a plugin might). However, it would be +an unusual collector that violated it.

+ +

The use of these intrinsics is naturally optional if the target GC does +require the corresponding barrier. Such a GC plugin will replace the intrinsic +calls with the corresponding load or store instruction if they +are used.

+ +
+ + + + +
+void @llvm.gcwrite(i8* %value, i8* %object, i8** %derived) +
+ +
+ +

For write barriers, LLVM provides the llvm.gcwrite intrinsic +function. It has exactly the same semantics as a non-volatile store to +the derived pointer (the third argument). The exact code generated is specified +by a compiler plugin.

+ +

Many important algorithms require write barriers, including generational +and concurrent collectors. Additionally, write barriers could be used to +implement reference counting.

+ +
+ + + + +
+i8* @llvm.gcread(i8* %object, i8** %derived)
+
+ +
+ +

For read barriers, LLVM provides the llvm.gcread intrinsic function. +It has exactly the same semantics as a non-volatile load from the +derived pointer (the second argument). The exact code generated is specified by +a compiler plugin.

+ +

Read barriers are needed by fewer algorithms than write barriers, and may +have a greater performance impact since pointer reads are more frequent than +writes.

+ +
+ + + + + +
+ +

User code specifies which GC code generation to use with the gc +function attribute or, equivalently, with the setGC method of +Function.

+ +

To implement a GC plugin, it is necessary to subclass +llvm::GCStrategy, which can be accomplished in a few lines of +boilerplate code. LLVM's infrastructure provides access to several important +algorithms. For an uncontroversial collector, all that remains may be to +compile LLVM's computed stack map to assembly code (using the binary +representation expected by the runtime library). This can be accomplished in +about 100 lines of code.

+ +

This is not the appropriate place to implement a garbage collected heap or a +garbage collector itself. That code should exist in the language's runtime +library. The compiler plugin is responsible for generating code which +conforms to the binary interface defined by library, most essentially the +stack map.

+ +

To subclass llvm::GCStrategy and register it with the compiler:

+ +
// lib/MyGC/MyGC.cpp - Example LLVM GC plugin
+
+#include "llvm/CodeGen/GCStrategy.h"
+#include "llvm/CodeGen/GCMetadata.h"
+#include "llvm/Support/Compiler.h"
+
+using namespace llvm;
+
+namespace {
+  class VISIBILITY_HIDDEN MyGC : public GCStrategy {
+  public:
+    MyGC() {}
+  };
+  
+  GCRegistry::Add<MyGC>
+  X("mygc", "My bespoke garbage collector.");
+}
+ +

This boilerplate collector does nothing. More specifically:

+ +
    +
  • llvm.gcread calls are replaced with the corresponding + load instruction.
  • +
  • llvm.gcwrite calls are replaced with the corresponding + store instruction.
  • +
  • No safe points are added to the code.
  • +
  • The stack map is not compiled into the executable.
  • +
+ +

Using the LLVM makefiles (like the sample +project), this code can be compiled as a plugin using a simple +makefile:

+ +
# lib/MyGC/Makefile
+
+LEVEL := ../..
+LIBRARYNAME = MyGC
+LOADABLE_MODULE = 1
+
+include $(LEVEL)/Makefile.common
+ +

Once the plugin is compiled, code using it may be compiled using llc +-load=MyGC.so (though MyGC.so may have some other +platform-specific extension):

+ +
$ cat sample.ll
+define void @f() gc "mygc" {
+entry:
+        ret void
+}
+$ llvm-as < sample.ll | llc -load=MyGC.so
+ +

It is also possible to statically link the collector plugin into tools, such +as a language-specific compiler front-end.

+ +
+ + + + +
+ +

GCStrategy provides a range of features through which a plugin +may do useful work. Some of these are callbacks, some are algorithms that can +be enabled, disabled, or customized. This matrix summarizes the supported (and +planned) features and correlates them with the collection techniques which +typically require them.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
AlgorithmDoneshadow stackrefcountmark-sweepcopyingincrementalthreadedconcurrent
stack map
initialize roots
derived pointersNO✘*✘*
custom lowering
gcroot
gcwrite
gcread
safe points
in calls
before calls
for loopsNO
before escape
emit code at safe pointsNO
output
assembly
JITNO
objNO
live analysisNO
register mapNO
+
* Derived pointers only pose a + hazard to copying collectors.
+
in gray denotes a feature which + could be utilized if available.
+
+ +

To be clear, the collection techniques above are defined as:

+ +
+
Shadow Stack
+
The mutator carefully maintains a linked list of stack roots.
+
Reference Counting
+
The mutator maintains a reference count for each object and frees an + object when its count falls to zero.
+
Mark-Sweep
+
When the heap is exhausted, the collector marks reachable objects starting + from the roots, then deallocates unreachable objects in a sweep + phase.
+
Copying
+
As reachability analysis proceeds, the collector copies objects from one + heap area to another, compacting them in the process. Copying collectors + enable highly efficient "bump pointer" allocation and can improve locality + of reference.
+
Incremental
+
(Including generational collectors.) Incremental collectors generally have + all the properties of a copying collector (regardless of whether the + mature heap is compacting), but bring the added complexity of requiring + write barriers.
+
Threaded
+
Denotes a multithreaded mutator; the collector must still stop the mutator + ("stop the world") before beginning reachability analysis. Stopping a + multithreaded mutator is a complicated problem. It generally requires + highly platform specific code in the runtime, and the production of + carefully designed machine code at safe points.
+
Concurrent
+
In this technique, the mutator and the collector run concurrently, with + the goal of eliminating pause times. In a cooperative collector, + the mutator further aids with collection should a pause occur, allowing + collection to take advantage of multiprocessor hosts. The "stop the world" + problem of threaded collectors is generally still present to a limited + extent. Sophisticated marking algorithms are necessary. Read barriers may + be necessary.
+
+ +

As the matrix indicates, LLVM's garbage collection infrastructure is already +suitable for a wide variety of collectors, but does not currently extend to +multithreaded programs. This will be added in the future as there is +interest.

+ +
+ + + + +
+ +

LLVM automatically computes a stack map. One of the most important features +of a GCStrategy is to compile this information into the executable in +the binary representation expected by the runtime library.

+ +

The stack map consists of the location and identity of each GC root in the +each function in the module. For each root:

+ +
    +
  • RootNum: The index of the root.
  • +
  • StackOffset: The offset of the object relative to the frame + pointer.
  • +
  • RootMetadata: The value passed as the %metadata + parameter to the @llvm.gcroot intrinsic.
  • +
+ +

Also, for the function as a whole:

+ +
    +
  • getFrameSize(): The overall size of the function's initial + stack frame, not accounting for any dynamic allocation.
  • +
  • roots_size(): The count of roots in the function.
  • +
+ +

To access the stack map, use GCFunctionMetadata::roots_begin() and +-end() from the GCMetadataPrinter:

+ +
for (iterator I = begin(), E = end(); I != E; ++I) {
+  GCFunctionInfo *FI = *I;
+  unsigned FrameSize = FI->getFrameSize();
+  size_t RootCount = FI->roots_size();
+
+  for (GCFunctionInfo::roots_iterator RI = FI->roots_begin(),
+                                      RE = FI->roots_end();
+                                      RI != RE; ++RI) {
+    int RootNum = RI->Num;
+    int RootStackOffset = RI->StackOffset;
+    Constant *RootMetadata = RI->Metadata;
+  }
+}
+ +

If the llvm.gcroot intrinsic is eliminated before code generation by +a custom lowering pass, LLVM will compute an empty stack map. This may be useful +for collector plugins which implement reference counting or a shadow stack.

+ +
+ + + + + +
+ +
MyGC::MyGC() {
+  InitRoots = true;
+}
+ +

When set, LLVM will automatically initialize each root to null upon +entry to the function. This prevents the GC's sweep phase from visiting +uninitialized pointers, which will almost certainly cause it to crash. This +initialization occurs before custom lowering, so the two may be used +together.

+ +

Since LLVM does not yet compute liveness information, there is no means of +distinguishing an uninitialized stack root from an initialized one. Therefore, +this feature should be used by all GC plugins. It is enabled by default.

+ +
+ + + + + +
+ +

For GCs which use barriers or unusual treatment of stack roots, these +flags allow the collector to perform arbitrary transformations of the LLVM +IR:

+ +
class MyGC : public GCStrategy {
+public:
+  MyGC() {
+    CustomRoots = true;
+    CustomReadBarriers = true;
+    CustomWriteBarriers = true;
+  }
+  
+  virtual bool initializeCustomLowering(Module &M);
+  virtual bool performCustomLowering(Function &F);
+};
+ +

If any of these flags are set, then LLVM suppresses its default lowering for +the corresponding intrinsics and instead calls +performCustomLowering.

+ +

LLVM's default action for each intrinsic is as follows:

+ +
    +
  • llvm.gcroot: Leave it alone. The code generator must see it + or the stack map will not be computed.
  • +
  • llvm.gcread: Substitute a load instruction.
  • +
  • llvm.gcwrite: Substitute a store instruction.
  • +
+ +

If CustomReadBarriers or CustomWriteBarriers are specified, +then performCustomLowering must eliminate the +corresponding barriers.

+ +

performCustomLowering must comply with the same restrictions as FunctionPass::runOnFunction. +Likewise, initializeCustomLowering has the same semantics as Pass::doInitialization(Module&).

+ +

The following can be used as a template:

+ +
#include "llvm/Module.h"
+#include "llvm/IntrinsicInst.h"
+
+bool MyGC::initializeCustomLowering(Module &M) {
+  return false;
+}
+
+bool MyGC::performCustomLowering(Function &F) {
+  bool MadeChange = false;
+  
+  for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB)
+    for (BasicBlock::iterator II = BB->begin(), E = BB->end(); II != E; )
+      if (IntrinsicInst *CI = dyn_cast<IntrinsicInst>(II++))
+        if (Function *F = CI->getCalledFunction())
+          switch (F->getIntrinsicID()) {
+          case Intrinsic::gcwrite:
+            // Handle llvm.gcwrite.
+            CI->eraseFromParent();
+            MadeChange = true;
+            break;
+          case Intrinsic::gcread:
+            // Handle llvm.gcread.
+            CI->eraseFromParent();
+            MadeChange = true;
+            break;
+          case Intrinsic::gcroot:
+            // Handle llvm.gcroot.
+            CI->eraseFromParent();
+            MadeChange = true;
+            break;
+          }
+  
+  return MadeChange;
+}
+ +
+ + + + + +
+ +

LLVM can compute four kinds of safe points:

+ +
namespace GC {
+  /// PointKind - The type of a collector-safe point.
+  /// 
+  enum PointKind {
+    Loop,    //< Instr is a loop (backwards branch).
+    Return,  //< Instr is a return instruction.
+    PreCall, //< Instr is a call instruction.
+    PostCall //< Instr is the return address of a call.
+  };
+}
+ +

A collector can request any combination of the four by setting the +NeededSafePoints mask:

+ +
MyGC::MyGC() {
+  NeededSafePoints = 1 << GC::Loop
+                   | 1 << GC::Return
+                   | 1 << GC::PreCall
+                   | 1 << GC::PostCall;
+}
+ +

It can then use the following routines to access safe points.

+ +
for (iterator I = begin(), E = end(); I != E; ++I) {
+  GCFunctionInfo *MD = *I;
+  size_t PointCount = MD->size();
+
+  for (GCFunctionInfo::iterator PI = MD->begin(),
+                                PE = MD->end(); PI != PE; ++PI) {
+    GC::PointKind PointKind = PI->Kind;
+    unsigned PointNum = PI->Num;
+  }
+}
+
+ +

Almost every collector requires PostCall safe points, since these +correspond to the moments when the function is suspended during a call to a +subroutine.

+ +

Threaded programs generally require Loop safe points to guarantee +that the application will reach a safe point within a bounded amount of time, +even if it is executing a long-running loop which contains no function +calls.

+ +

Threaded collectors may also require Return and PreCall +safe points to implement "stop the world" techniques using self-modifying code, +where it is important that the program not exit the function without reaching a +safe point (because only the topmost function has been patched).

+ +
+ + + + + +
+ +

LLVM allows a plugin to print arbitrary assembly code before and after the +rest of a module's assembly code. At the end of the module, the GC can compile +the LLVM stack map into assembly code. (At the beginning, this information is not +yet computed.)

+ +

Since AsmWriter and CodeGen are separate components of LLVM, a separate +abstract base class and registry is provided for printing assembly code, the +GCMetadaPrinter and GCMetadataPrinterRegistry. The AsmWriter +will look for such a subclass if the GCStrategy sets +UsesMetadata:

+ +
MyGC::MyGC() {
+  UsesMetadata = true;
+}
+ +

This separation allows JIT-only clients to be smaller.

+ +

Note that LLVM does not currently have analogous APIs to support code +generation in the JIT, nor using the object writers.

+ +
// lib/MyGC/MyGCPrinter.cpp - Example LLVM GC printer
+
+#include "llvm/CodeGen/GCMetadataPrinter.h"
+#include "llvm/Support/Compiler.h"
+
+using namespace llvm;
+
+namespace {
+  class VISIBILITY_HIDDEN MyGCPrinter : public GCMetadataPrinter {
+  public:
+    virtual void beginAssembly(std::ostream &OS, AsmPrinter &AP,
+                               const TargetAsmInfo &TAI);
+  
+    virtual void finishAssembly(std::ostream &OS, AsmPrinter &AP,
+                                const TargetAsmInfo &TAI);
+  };
+  
+  GCMetadataPrinterRegistry::Add<MyGCPrinter>
+  X("mygc", "My bespoke garbage collector.");
+}
+ +

The collector should use AsmPrinter and TargetAsmInfo to +print portable assembly code to the std::ostream. The collector itself +contains the stack map for the entire module, and may access the +GCFunctionInfo using its own begin() and end() +methods. Here's a realistic example:

+ +
#include "llvm/CodeGen/AsmPrinter.h"
+#include "llvm/Function.h"
+#include "llvm/Target/TargetMachine.h"
+#include "llvm/Target/TargetData.h"
+#include "llvm/Target/TargetAsmInfo.h"
+
+void MyGCPrinter::beginAssembly(std::ostream &OS, AsmPrinter &AP,
+                                const TargetAsmInfo &TAI) {
+  // Nothing to do.
+}
+
+void MyGCPrinter::finishAssembly(std::ostream &OS, AsmPrinter &AP,
+                                 const TargetAsmInfo &TAI) {
+  // Set up for emitting addresses.
+  const char *AddressDirective;
+  int AddressAlignLog;
+  if (AP.TM.getTargetData()->getPointerSize() == sizeof(int32_t)) {
+    AddressDirective = TAI.getData32bitsDirective();
+    AddressAlignLog = 2;
+  } else {
+    AddressDirective = TAI.getData64bitsDirective();
+    AddressAlignLog = 3;
+  }
+  
+  // Put this in the data section.
+  AP.SwitchToDataSection(TAI.getDataSection());
+  
+  // For each function...
+  for (iterator FI = begin(), FE = end(); FI != FE; ++FI) {
+    GCFunctionInfo &MD = **FI;
+    
+    // Emit this data structure:
+    // 
+    // struct {
+    //   int32_t PointCount;
+    //   struct {
+    //     void *SafePointAddress;
+    //     int32_t LiveCount;
+    //     int32_t LiveOffsets[LiveCount];
+    //   } Points[PointCount];
+    // } __gcmap_<FUNCTIONNAME>;
+    
+    // Align to address width.
+    AP.EmitAlignment(AddressAlignLog);
+    
+    // Emit the symbol by which the stack map entry can be found.
+    std::string Symbol;
+    Symbol += TAI.getGlobalPrefix();
+    Symbol += "__gcmap_";
+    Symbol += MD.getFunction().getName();
+    if (const char *GlobalDirective = TAI.getGlobalDirective())
+      OS << GlobalDirective << Symbol << "\n";
+    OS << TAI.getGlobalPrefix() << Symbol << ":\n";
+    
+    // Emit PointCount.
+    AP.EmitInt32(MD.size());
+    AP.EOL("safe point count");
+    
+    // And each safe point...
+    for (GCFunctionInfo::iterator PI = MD.begin(),
+                                     PE = MD.end(); PI != PE; ++PI) {
+      // Align to address width.
+      AP.EmitAlignment(AddressAlignLog);
+      
+      // Emit the address of the safe point.
+      OS << AddressDirective
+         << TAI.getPrivateGlobalPrefix() << "label" << PI->Num;
+      AP.EOL("safe point address");
+      
+      // Emit the stack frame size.
+      AP.EmitInt32(MD.getFrameSize());
+      AP.EOL("stack frame size");
+      
+      // Emit the number of live roots in the function.
+      AP.EmitInt32(MD.live_size(PI));
+      AP.EOL("live root count");
+      
+      // And for each live root...
+      for (GCFunctionInfo::live_iterator LI = MD.live_begin(PI),
+                                            LE = MD.live_end(PI);
+                                            LI != LE; ++LI) {
+        // Print its offset within the stack frame.
+        AP.EmitInt32(LI->StackOffset);
+        AP.EOL("stack offset");
+      }
+    }
+  }
+}
+
+ +
+ + + + + + +
+ +

[Appel89] Runtime Tags Aren't Necessary. Andrew +W. Appel. Lisp and Symbolic Computation 19(7):703-705, July 1989.

+ +

[Goldberg91] Tag-free garbage collection for +strongly typed programming languages. Benjamin Goldberg. ACM SIGPLAN +PLDI'91.

+ +

[Tolmach94] Tag-free garbage collection using +explicit type parameters. Andrew Tolmach. Proceedings of the 1994 ACM +conference on LISP and functional programming.

+ +

[Henderson2002] +Accurate Garbage Collection in an Uncooperative Environment. +Fergus Henderson. International Symposium on Memory Management 2002.

+ +
+ + + + +
+
+ Valid CSS + Valid HTML 4.01 + + Chris Lattner
+ LLVM Compiler Infrastructure
+ Last modified: $Date$ +
+ + + diff --git a/libclamav/c++/llvm/docs/GetElementPtr.html b/libclamav/c++/llvm/docs/GetElementPtr.html new file mode 100644 index 000000000..dd49ef7ec --- /dev/null +++ b/libclamav/c++/llvm/docs/GetElementPtr.html @@ -0,0 +1,371 @@ + + + + + The Often Misunderstood GEP Instruction + + + + + +
+ The Often Misunderstood GEP Instruction +
+ +
    +
  1. Introduction
  2. +
  3. The Questions +
      +
    1. Why is the extra 0 index required?
    2. +
    3. What is dereferenced by GEP?
    4. +
    5. Why can you index through the first pointer but not + subsequent ones?
    6. +
    7. Why don't GEP x,0,0,1 and GEP x,1 alias?
    8. +
    9. Why do GEP x,1,0,0 and GEP x,1 alias?
    10. +
  4. +
  5. Summary
  6. +
+ +
+

Written by: Reid Spencer.

+
+ + + + + +
+

This document seeks to dispel the mystery and confusion surrounding LLVM's + GetElementPtr (GEP) instruction. Questions about the wiley GEP instruction are + probably the most frequently occurring questions once a developer gets down to + coding with LLVM. Here we lay out the sources of confusion and show that the + GEP instruction is really quite simple. +

+
+ + + + +
+

When people are first confronted with the GEP instruction, they tend to + relate it to known concepts from other programming paradigms, most notably C + array indexing and field selection. However, GEP is a little different and + this leads to the following questions; all of which are answered in the + following sections.

+
    +
  1. What is the first index of the GEP instruction? +
  2. +
  3. Why is the extra 0 index required?
  4. +
  5. What is dereferenced by GEP?
  6. +
  7. Why don't GEP x,0,0,1 and GEP x,1 alias?
  8. +
  9. Why do GEP x,1,0,0 and GEP x,1 alias?
  10. +
+
+ + + +
+

Quick answer: The index stepping through the first operand.

+

The confusion with the first index usually arises from thinking about + the GetElementPtr instruction as if it was a C index operator. They aren't the + same. For example, when we write, in "C":

+ +
+
+AType *Foo;
+...
+X = &Foo->F;
+
+
+ +

it is natural to think that there is only one index, the selection of the + field F. However, in this example, Foo is a pointer. That + pointer must be indexed explicitly in LLVM. C, on the other hand, indexs + through it transparently. To arrive at the same address location as the C + code, you would provide the GEP instruction with two index operands. The + first operand indexes through the pointer; the second operand indexes the + field F of the structure, just as if you wrote:

+ +
+
+X = &Foo[0].F;
+
+
+ +

Sometimes this question gets rephrased as:

+

Why is it okay to index through the first pointer, but + subsequent pointers won't be dereferenced?

+

The answer is simply because memory does not have to be accessed to + perform the computation. The first operand to the GEP instruction must be a + value of a pointer type. The value of the pointer is provided directly to + the GEP instruction as an operand without any need for accessing memory. It + must, therefore be indexed and requires an index operand. Consider this + example:

+ +
+
+struct munger_struct {
+  int f1;
+  int f2;
+};
+void munge(struct munger_struct *P) {
+  P[0].f1 = P[1].f1 + P[2].f2;
+}
+...
+munger_struct Array[3];
+...
+munge(Array);
+
+
+ +

In this "C" example, the front end compiler (llvm-gcc) will generate three + GEP instructions for the three indices through "P" in the assignment + statement. The function argument P will be the first operand of each + of these GEP instructions. The second operand indexes through that pointer. + The third operand will be the field offset into the + struct munger_struct type, for either the f1 or + f2 field. So, in LLVM assembly the munge function looks + like:

+ +
+
+void %munge(%struct.munger_struct* %P) {
+entry:
+  %tmp = getelementptr %struct.munger_struct* %P, i32 1, i32 0
+  %tmp = load i32* %tmp
+  %tmp6 = getelementptr %struct.munger_struct* %P, i32 2, i32 1
+  %tmp7 = load i32* %tmp6
+  %tmp8 = add i32 %tmp7, %tmp
+  %tmp9 = getelementptr %struct.munger_struct* %P, i32 0, i32 0
+  store i32 %tmp8, i32* %tmp9
+  ret void
+}
+
+
+ +

In each case the first operand is the pointer through which the GEP + instruction starts. The same is true whether the first operand is an + argument, allocated memory, or a global variable.

+

To make this clear, let's consider a more obtuse example:

+ +
+
+%MyVar = unintialized global i32
+...
+%idx1 = getelementptr i32* %MyVar, i64 0
+%idx2 = getelementptr i32* %MyVar, i64 1
+%idx3 = getelementptr i32* %MyVar, i64 2
+
+
+ +

These GEP instructions are simply making address computations from the + base address of MyVar. They compute, as follows (using C syntax): +

+ +
+
+idx1 = (char*) &MyVar + 0
+idx2 = (char*) &MyVar + 4
+idx3 = (char*) &MyVar + 8
+
+
+ +

Since the type i32 is known to be four bytes long, the indices + 0, 1 and 2 translate into memory offsets of 0, 4, and 8, respectively. No + memory is accessed to make these computations because the address of + %MyVar is passed directly to the GEP instructions.

+

The obtuse part of this example is in the cases of %idx2 and + %idx3. They result in the computation of addresses that point to + memory past the end of the %MyVar global, which is only one + i32 long, not three i32s long. While this is legal in LLVM, + it is inadvisable because any load or store with the pointer that results + from these GEP instructions would produce undefined results.

+
+ + + + +
+

Quick answer: there are no superfluous indices.

+

This question arises most often when the GEP instruction is applied to a + global variable which is always a pointer type. For example, consider + this:

+ +
+
+%MyStruct = uninitialized global { float*, i32 }
+...
+%idx = getelementptr { float*, i32 }* %MyStruct, i64 0, i32 1
+
+
+ +

The GEP above yields an i32* by indexing the i32 typed + field of the structure %MyStruct. When people first look at it, they + wonder why the i64 0 index is needed. However, a closer inspection + of how globals and GEPs work reveals the need. Becoming aware of the following + facts will dispell the confusion:

+
    +
  1. The type of %MyStruct is not { float*, i32 } + but rather { float*, i32 }*. That is, %MyStruct is a + pointer to a structure containing a pointer to a float and an + i32.
  2. +
  3. Point #1 is evidenced by noticing the type of the first operand of + the GEP instruction (%MyStruct) which is + { float*, i32 }*.
  4. +
  5. The first index, i64 0 is required to step over the global + variable %MyStruct. Since the first argument to the GEP + instruction must always be a value of pointer type, the first index + steps through that pointer. A value of 0 means 0 elements offset from that + pointer.
  6. +
  7. The second index, i32 1 selects the second field of the + structure (the i32).
  8. +
+
+ + + +
+

Quick answer: nothing.

+

The GetElementPtr instruction dereferences nothing. That is, it doesn't + access memory in any way. That's what the Load and Store instructions are for. + GEP is only involved in the computation of addresses. For example, consider + this:

+ +
+
+%MyVar = uninitialized global { [40 x i32 ]* }
+...
+%idx = getelementptr { [40 x i32]* }* %MyVar, i64 0, i32 0, i64 0, i64 17
+
+
+ +

In this example, we have a global variable, %MyVar that is a + pointer to a structure containing a pointer to an array of 40 ints. The + GEP instruction seems to be accessing the 18th integer of the structure's + array of ints. However, this is actually an illegal GEP instruction. It + won't compile. The reason is that the pointer in the structure must + be dereferenced in order to index into the array of 40 ints. Since the + GEP instruction never accesses memory, it is illegal.

+

In order to access the 18th integer in the array, you would need to do the + following:

+ +
+
+%idx = getelementptr { [40 x i32]* }* %, i64 0, i32 0
+%arr = load [40 x i32]** %idx
+%idx = getelementptr [40 x i32]* %arr, i64 0, i64 17
+
+
+ +

In this case, we have to load the pointer in the structure with a load + instruction before we can index into the array. If the example was changed + to:

+ +
+
+%MyVar = uninitialized global { [40 x i32 ] }
+...
+%idx = getelementptr { [40 x i32] }*, i64 0, i32 0, i64 17
+
+
+ +

then everything works fine. In this case, the structure does not contain a + pointer and the GEP instruction can index through the global variable, + into the first field of the structure and access the 18th i32 in the + array there.

+
+ + + +
+

Quick Answer: They compute different address locations.

+

If you look at the first indices in these GEP + instructions you find that they are different (0 and 1), therefore the address + computation diverges with that index. Consider this example:

+ +
+
+%MyVar = global { [10 x i32 ] }
+%idx1 = getlementptr { [10 x i32 ] }* %MyVar, i64 0, i32 0, i64 1
+%idx2 = getlementptr { [10 x i32 ] }* %MyVar, i64 1
+
+
+ +

In this example, idx1 computes the address of the second integer + in the array that is in the structure in %MyVar, that is + MyVar+4. The type of idx1 is i32*. However, + idx2 computes the address of the next structure after + %MyVar. The type of idx2 is { [10 x i32] }* and its + value is equivalent to MyVar + 40 because it indexes past the ten + 4-byte integers in MyVar. Obviously, in such a situation, the + pointers don't alias.

+ +
+ + + +
+

Quick Answer: They compute the same address location.

+

These two GEP instructions will compute the same address because indexing + through the 0th element does not change the address. However, it does change + the type. Consider this example:

+ +
+
+%MyVar = global { [10 x i32 ] }
+%idx1 = getlementptr { [10 x i32 ] }* %MyVar, i64 1, i32 0, i64 0
+%idx2 = getlementptr { [10 x i32 ] }* %MyVar, i64 1
+
+
+ +

In this example, the value of %idx1 is %MyVar+40 and + its type is i32*. The value of %idx2 is also + MyVar+40 but its type is { [10 x i32] }*.

+
+ + + + + +
+

In summary, here's some things to always remember about the GetElementPtr + instruction:

+
    +
  1. The GEP instruction never accesses memory, it only provides pointer + computations.
  2. +
  3. The first operand to the GEP instruction is always a pointer and it must + be indexed.
  4. +
  5. There are no superfluous indices for the GEP instruction.
  6. +
  7. Trailing zero indices are superfluous for pointer aliasing, but not for + the types of the pointers.
  8. +
  9. Leading zero indices are not superfluous for pointer aliasing nor the + types of the pointers.
  10. +
+
+ + + +
+
+ Valid CSS + Valid HTML 4.01 + The LLVM Compiler Infrastructure
+ Last modified: $Date$ +
+ + diff --git a/libclamav/c++/llvm/docs/GettingStarted.html b/libclamav/c++/llvm/docs/GettingStarted.html new file mode 100644 index 000000000..851bfb6b5 --- /dev/null +++ b/libclamav/c++/llvm/docs/GettingStarted.html @@ -0,0 +1,1642 @@ + + + + + Getting Started with LLVM System + + + + +
+ Getting Started with the LLVM System +
+ + + +
+

Written by: + John Criswell, + Chris Lattner, + Misha Brukman, + Vikram Adve, and + Guochun Shi. +

+
+ + + + + + +
+ +

Welcome to LLVM! In order to get started, you first need to know some +basic information.

+ +

First, LLVM comes in two pieces. The first piece is the LLVM suite. This +contains all of the tools, libraries, and header files needed to use the low +level virtual machine. It contains an assembler, disassembler, bitcode +analyzer and bitcode optimizer. It also contains a test suite that can be +used to test the LLVM tools and the GCC front end.

+ +

The second piece is the GCC front end. This component provides a version of +GCC that compiles C and C++ code into LLVM bitcode. Currently, the GCC front +end uses the GCC parser to convert code to LLVM. Once +compiled into LLVM bitcode, a program can be manipulated with the LLVM tools +from the LLVM suite.

+ +

+There is a third, optional piece called llvm-test. It is a suite of programs +with a testing harness that can be used to further test LLVM's functionality +and performance. +

+ +
+ + + + + +
+ +

Here's the short story for getting up and running quickly with LLVM:

+ +
    +
  1. Read the documentation.
  2. +
  3. Read the documentation.
  4. +
  5. Remember that you were warned twice about reading the documentation.
  6. +
  7. Install the llvm-gcc-4.2 front end if you intend to compile C or C++: +
      +
    1. cd where-you-want-the-C-front-end-to-live
    2. +
    3. gunzip --stdout llvm-gcc-4.2-version-platform.tar.gz | tar -xvf - +
    4. +
    5. Note: If the binary extension is ".bz" use bunzip2 instead of gunzip.
    6. +
    7. Add llvm-gcc's "bin" directory to your PATH variable.
    8. +
  8. + +
  9. Get the LLVM Source Code +
      +
    • With the distributed files (or use SVN): +
        +
      1. cd where-you-want-llvm-to-live +
      2. gunzip --stdout llvm-version.tar.gz | tar -xvf - +
    • + +
  10. + +
  11. [Optional] Get the Test Suite Source Code +
      +
    • With the distributed files (or use SVN): +
        +
      1. cd where-you-want-llvm-to-live +
      2. cd llvm/projects +
      3. gunzip --stdout llvm-test-version.tar.gz | tar -xvf - +
    • + +
  12. + + +
  13. Configure the LLVM Build Environment +
      +
    1. cd where-you-want-to-build-llvm
    2. +
    3. /path/to/llvm/configure [options]
      + Some common options: + +
        +
      • --prefix=directory +

        Specify for directory the full pathname of where you + want the LLVM tools and libraries to be installed (default + /usr/local).

      • +
      • --with-llvmgccdir=directory +

        Optionally, specify for directory the full pathname of the + C/C++ front end installation to use with this LLVM configuration. If + not specified, the PATH will be searched. This is only needed if you + want to run the testsuite or do some special kinds of LLVM builds.

      • +
      • --enable-spec2000=directory +

        Enable the SPEC2000 benchmarks for testing. The SPEC2000 + benchmarks should be available in + directory.

      • +
      +
  14. + +
  15. Build the LLVM Suite: +
      +
    1. gmake -k |& tee gnumake.out +    # this is csh or tcsh syntax
    2. +
    3. If you get an "internal compiler error (ICE)" or test failures, see + below.
    4. +
    + +
+ +

Consult the Getting Started with LLVM section for +detailed information on configuring and compiling LLVM. See Setting Up Your Environment for tips that simplify +working with the GCC front end and LLVM tools. Go to Program +Layout to learn about the layout of the source code tree.

+ +
+ + + + + +
+ +

Before you begin to use the LLVM system, review the requirements given below. +This may save you some trouble by knowing ahead of time what hardware and +software you will need.

+ +
+ + + + +
+ +

LLVM is known to work on the following platforms:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OSArchCompilers
AuroraUXx861GCC
Linuxx861GCC
Linuxamd64GCC
SolarisV9 (Ultrasparc)GCC
FreeBSDx861GCC
MacOS X2PowerPCGCC
MacOS X2,9x86GCC
Cygwin/Win32x861,8GCC 3.4.X, binutils 2.15
MinGW/Win32x861,6, + 8, 10GCC 3.4.X, binutils 2.15
+ +

LLVM has partial support for the following platforms:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OSArchCompilers
Windowsx861Visual Studio 2005 SP1 or higher4,5
AIX3,4PowerPCGCC
Linux3,5PowerPCGCC
Linux7AlphaGCC
Linux7Itanium (IA-64)GCC
HP-UX7Itanium (IA-64)HP aCC
+ +

Notes:

+ +
+
    +
  1. Code generation supported for Pentium processors and +up
  2. +
  3. Code generation supported for 32-bit ABI only
  4. +
  5. No native code generation
  6. +
  7. Build is not complete: one or more tools do not link or function
  8. +
  9. The GCC-based C/C++ frontend does not build
  10. +
  11. The port is done using the MSYS shell.
  12. +
  13. Native code generation exists but is not complete.
  14. +
  15. Binutils up to post-2.17 has bug in bfd/cofflink.c + preventing LLVM from building correctly. Several workarounds have been + introduced into LLVM build system, but the bug can occur anytime in the + future. We highly recommend that you rebuild your current binutils with the + patch from + Binutils bugzilla, if it wasn't already applied.
  16. +
  17. XCode 2.5 and gcc 4.0.1 (Apple Build 5370) will trip + internal LLVM assert messages when compiled for Release at optimization + levels greater than 0 (i.e., "-O1" and higher). + Add OPTIMIZE_OPTION="-O0" to the build command line + if compiling for LLVM Release or bootstrapping the LLVM toolchain.
  18. +
  19. For MSYS/MinGW on Windows, be sure to install the MSYS + version of the perl package, and be sure it appears in your path + before any Windows-based versions such as Strawberry Perl and + ActivePerl, as these have Windows-specifics that will cause the + build to fail.
  20. +
+
+ +

Note that you will need about 1-3 GB of space for a full LLVM build in Debug +mode, depending on the system (it is so large because of all the debugging +information and the fact that the libraries are statically linked into multiple +tools). If you do not need many of the tools and you are space-conscious, you +can pass ONLY_TOOLS="tools you need" to make. The Release build +requires considerably less space.

+ +

The LLVM suite may compile on other platforms, but it is not +guaranteed to do so. If compilation is successful, the LLVM utilities should be +able to assemble, disassemble, analyze, and optimize LLVM bitcode. Code +generation should work as well, although the generated native code may not work +on your platform.

+ +

The GCC front end is not very portable at the moment. If you want to get it +to work on another platform, you can download a copy of the source and try to compile it on your platform.

+ +
+ + + +
+

Compiling LLVM requires that you have several software packages + installed. The table below lists those required packages. The Package column + is the usual name for the software package that LLVM depends on. The Version + column provides "known to work" versions of the package. The Notes column + describes how LLVM uses the package and provides other details.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PackageVersionNotes
GNU Make3.79, 3.79.1Makefile/build processor
GCC3.4.2C/C++ compiler1
TeXinfo4.5For building the CFE
SVN≥1.3Subversion access to LLVM2
DejaGnu1.4.2Automated test suite3
tcl8.3, 8.4Automated test suite3
expect5.38.0Automated test suite3
perl≥5.6.0Nightly tester, utilities
GNU M4 + 1.4Macro processor for configuration4
GNU Autoconf2.60Configuration script builder4
GNU Automake1.9.6aclocal macro generator4
libtool1.5.22Shared library manager4
+ +

Notes:

+ + +

Additionally, your compilation host is expected to have the usual + plethora of Unix utilities. Specifically:

+
    +
  • ar - archive library builder
  • +
  • bzip2* - bzip2 command for distribution generation
  • +
  • bunzip2* - bunzip2 command for distribution checking
  • +
  • chmod - change permissions on a file
  • +
  • cat - output concatenation utility
  • +
  • cp - copy files
  • +
  • date - print the current date/time
  • +
  • echo - print to standard output
  • +
  • egrep - extended regular expression search utility
  • +
  • find - find files/dirs in a file system
  • +
  • grep - regular expression search utility
  • +
  • gzip* - gzip command for distribution generation
  • +
  • gunzip* - gunzip command for distribution checking
  • +
  • install - install directories/files
  • +
  • mkdir - create a directory
  • +
  • mv - move (rename) files
  • +
  • ranlib - symbol table builder for archive libraries
  • +
  • rm - remove (delete) files and directories
  • +
  • sed - stream editor for transforming output
  • +
  • sh - Bourne shell for make build scripts
  • +
  • tar - tape archive for distribution generation
  • +
  • test - test things in file system
  • +
  • unzip* - unzip command for distribution checking
  • +
  • zip* - zip command for distribution generation
  • +
+
+ + + + +
+ +

LLVM is very demanding of the host C++ compiler, and as such tends to expose +bugs in the compiler. In particular, several versions of GCC crash when trying +to compile LLVM. We routinely use GCC 3.3.3, 3.4.0, and Apple 4.0.1 +successfully with them (however, see important notes below). Other versions +of GCC will probably work as well. GCC versions listed +here are known to not work. If you are using one of these versions, please try +to upgrade your GCC to something more recent. If you run into a problem with a +version of GCC not listed here, please let +us know. Please use the "gcc -v" command to find out which version +of GCC you are using. +

+ +

GCC versions prior to 3.0: GCC 2.96.x and before had several +problems in the STL that effectively prevent it from compiling LLVM. +

+ +

GCC 3.2.2 and 3.2.3: These versions of GCC fails to compile LLVM with +a bogus template error. This was fixed in later GCCs.

+ +

GCC 3.3.2: This version of GCC suffered from a serious bug which causes it to crash in +the "convert_from_eh_region_ranges_1" GCC function.

+ +

Cygwin GCC 3.3.3: The version of GCC 3.3.3 commonly shipped with + Cygwin does not work. Please upgrade + to a newer version if possible.

+

SuSE GCC 3.3.3: The version of GCC 3.3.3 shipped with SuSE 9.1 (and + possibly others) does not compile LLVM correctly (it appears that exception + handling is broken in some cases). Please download the FSF 3.3.3 or upgrade + to a newer version of GCC.

+

GCC 3.4.0 on linux/x86 (32-bit): GCC miscompiles portions of the + code generator, causing an infinite loop in the llvm-gcc build when built + with optimizations enabled (i.e. a release build).

+

GCC 3.4.2 on linux/x86 (32-bit): GCC miscompiles portions of the + code generator at -O3, as with 3.4.0. However gcc 3.4.2 (unlike 3.4.0) + correctly compiles LLVM at -O2. A work around is to build release LLVM + builds with "make ENABLE_OPTIMIZED=1 OPTIMIZE_OPTION=-O2 ..."

+

GCC 3.4.x on X86-64/amd64: GCC + miscompiles portions of LLVM.

+

GCC 3.4.4 (CodeSourcery ARM 2005q3-2): this compiler miscompiles LLVM + when building with optimizations enabled. It appears to work with + "make ENABLE_OPTIMIZED=1 OPTIMIZE_OPTION=-O1" or build a debug + build.

+

IA-64 GCC 4.0.0: The IA-64 version of GCC 4.0.0 is known to + miscompile LLVM.

+

Apple Xcode 2.3: GCC crashes when compiling LLVM at -O3 (which is the + default with ENABLE_OPTIMIZED=1. To work around this, build with + "ENABLE_OPTIMIZED=1 OPTIMIZE_OPTION=-O2".

+

GCC 4.1.1: GCC fails to build LLVM with template concept check errors + compiling some files. At the time of this writing, GCC mainline (4.2) + did not share the problem.

+

GCC 4.1.1 on X86-64/amd64: GCC + miscompiles portions of LLVM when compiling llvm itself into 64-bit + code. LLVM will appear to mostly work but will be buggy, e.g. failing + portions of its testsuite.

+

GCC 4.1.2 on OpenSUSE: Seg faults during libstdc++ build and on x86_64 +platforms compiling md5.c gets a mangled constant.

+

GCC 4.1.2 (20061115 (prerelease) (Debian 4.1.1-21)) on Debian: Appears +to miscompile parts of LLVM 2.4. One symptom is ValueSymbolTable complaining +about symbols remaining in the table on destruction.

+

GCC 4.1.2 20071124 (Red Hat 4.1.2-42): Suffers from the same symptoms +as the previous one. It appears to work with ENABLE_OPTIMIZED=0 (the default).

+

Cygwin GCC 4.3.2 20080827 (beta) 2: + Users reported various problems related + with link errors when using this GCC version.

+

Debian GCC 4.3.2 on X86: Crashes building some files in LLVM 2.6.

+

GCC 4.3.3 (Debian 4.3.3-10) on ARM: Miscompiles parts of LLVM 2.6 +when optimizations are turned on. The symptom is an infinite loop in +FoldingSetImpl::RemoveNode while running the code generator.

+

GNU ld 2.16.X. Some 2.16.X versions of the ld linker will produce very +long warning messages complaining that some ".gnu.linkonce.t.*" symbol was +defined in a discarded section. You can safely ignore these messages as they are +erroneous and the linkage is correct. These messages disappear using ld +2.17.

+ +

GNU binutils 2.17: Binutils 2.17 contains a bug which +causes huge link times (minutes instead of seconds) when building LLVM. We +recommend upgrading to a newer version (2.17.50.0.4 or later).

+ +

GNU Binutils 2.19.1 Gold: This version of Gold contained +a bug +which causes intermittent failures when building LLVM with position independent +code. The symptom is an error about cyclic dependencies. We recommend +upgrading to a newer version of Gold.

+ +
+ + + + + + + +
+ +

The remainder of this guide is meant to get you up and running with +LLVM and to give you some basic information about the LLVM environment.

+ +

The later sections of this guide describe the general layout of the the LLVM source tree, a simple example using the LLVM tool chain, and links to find more information about LLVM or to get +help via e-mail.

+
+ + + + +
+ +

Throughout this manual, the following names are used to denote paths +specific to the local system and working environment. These are not +environment variables you need to set but just strings used in the rest +of this document below. In any of the examples below, simply replace +each of these names with the appropriate pathname on your local system. +All these paths are absolute:

+ +
+
SRC_ROOT +
+ This is the top level directory of the LLVM source tree. +

+ +
OBJ_ROOT +
+ This is the top level directory of the LLVM object tree (i.e. the + tree where object files and compiled programs will be placed. It + can be the same as SRC_ROOT). +

+ +
LLVMGCCDIR +
+ This is where the LLVM GCC Front End is installed. +

+ For the pre-built GCC front end binaries, the LLVMGCCDIR is + llvm-gcc/platform/llvm-gcc. +

+ +
+ + + + +
+ +

+In order to compile and use LLVM, you may need to set some environment +variables. + +

+
LLVM_LIB_SEARCH_PATH=/path/to/your/bitcode/libs
+
[Optional] This environment variable helps LLVM linking tools find the + locations of your bitcode libraries. It is provided only as a + convenience since you can specify the paths using the -L options of the + tools and the C/C++ front-end will automatically use the bitcode files + installed in its + lib directory.
+
+ +
+ + + + +
+ +

+If you have the LLVM distribution, you will need to unpack it before you +can begin to compile it. LLVM is distributed as a set of two files: the LLVM +suite and the LLVM GCC front end compiled for your platform. There is an +additional test suite that is optional. Each file is a TAR archive that is +compressed with the gzip program. +

+ +

The files are as follows, with x.y marking the version number: +

+
llvm-x.y.tar.gz
+
Source release for the LLVM libraries and tools.
+ +
llvm-test-x.y.tar.gz
+
Source release for the LLVM test suite.
+ +
llvm-gcc-4.2-x.y.source.tar.gz
+
Source release of the llvm-gcc-4.2 front end. See README.LLVM in the root + directory for build instructions.
+ +
llvm-gcc-4.2-x.y-platform.tar.gz
+
Binary release of the llvm-gcc-4.2 front end for a specific platform.
+ +
+ +
+ + + + +
+ +

If you have access to our Subversion repository, you can get a fresh copy of +the entire source code. All you need to do is check it out from Subversion as +follows:

+ +
    +
  • cd where-you-want-llvm-to-live
  • +
  • Read-Only: svn co http://llvm.org/svn/llvm-project/llvm/trunk llvm
  • +
  • Read-Write:svn co https://user@llvm.org/svn/llvm-project/llvm/trunk + llvm
  • +
+ + +

This will create an 'llvm' directory in the current +directory and fully populate it with the LLVM source code, Makefiles, +test directories, and local copies of documentation files.

+ +

If you want to get a specific release (as opposed to the most recent +revision), you can checkout it from the 'tags' directory (instead of +'trunk'). The following releases are located in the following +subdirectories of the 'tags' directory:

+ +
    +
  • Release 2.6: RELEASE_26
  • +
  • Release 2.5: RELEASE_25
  • +
  • Release 2.4: RELEASE_24
  • +
  • Release 2.3: RELEASE_23
  • +
  • Release 2.2: RELEASE_22
  • +
  • Release 2.1: RELEASE_21
  • +
  • Release 2.0: RELEASE_20
  • +
  • Release 1.9: RELEASE_19
  • +
  • Release 1.8: RELEASE_18
  • +
  • Release 1.7: RELEASE_17
  • +
  • Release 1.6: RELEASE_16
  • +
  • Release 1.5: RELEASE_15
  • +
  • Release 1.4: RELEASE_14
  • +
  • Release 1.3: RELEASE_13
  • +
  • Release 1.2: RELEASE_12
  • +
  • Release 1.1: RELEASE_11
  • +
  • Release 1.0: RELEASE_1
  • +
+ +

If you would like to get the LLVM test suite (a separate package as of 1.4), +you get it from the Subversion repository:

+ +
+
+% cd llvm/projects
+% svn co http://llvm.org/svn/llvm-project/test-suite/trunk llvm-test
+
+
+ +

By placing it in the llvm/projects, it will be automatically +configured by the LLVM configure script as well as automatically updated when +you run svn update.

+ +

If you would like to get the GCC front end source code, you can also get it +and build it yourself. Please follow these +instructions to successfully get and build the LLVM GCC front-end.

+ +
+ + + + +
+ +

Before configuring and compiling the LLVM suite, you can optionally extract the +LLVM GCC front end from the binary distribution. It is used for running the +llvm-test testsuite and for compiling C/C++ programs. Note that you can optionally +build llvm-gcc yourself after building the +main LLVM repository.

+ +

To install the GCC front end, do the following:

+ +
    +
  1. cd where-you-want-the-front-end-to-live
  2. +
  3. gunzip --stdout llvm-gcc-4.2-version-platform.tar.gz | tar -xvf + -
  4. +
+ +

Once the binary is uncompressed, you should add a symlink for llvm-gcc and +llvm-g++ to some directory in your path. When you configure LLVM, it will +automatically detect llvm-gcc's presence (if it is in your path) enabling its +use in llvm-test. Note that you can always build or install llvm-gcc at any +pointer after building the main LLVM repository: just reconfigure llvm and +llvm-test will pick it up. +

+ +

The binary versions of the GCC front end may not suit all of your needs. For +example, the binary distribution may include an old version of a system header +file, not "fix" a header file that needs to be fixed for GCC, or it may be +linked with libraries not available on your system.

+ +

In cases like these, you may want to try building the GCC front end from source. This is +much easier now than it was in the past.

+ +
+ + + + +
+ +

Once checked out from the Subversion repository, the LLVM suite source + code must be +configured via the configure script. This script sets variables in the +various *.in files, most notably llvm/Makefile.config and +llvm/include/Config/config.h. It also populates OBJ_ROOT with +the Makefiles needed to begin building LLVM.

+ +

The following environment variables are used by the configure +script to configure the build system:

+ + + + + + + + + + + +
VariablePurpose
CCTells configure which C compiler to use. By default, + configure will look for the first GCC C compiler in + PATH. Use this variable to override + configure's default behavior.
CXXTells configure which C++ compiler to use. By default, + configure will look for the first GCC C++ compiler in + PATH. Use this variable to override + configure's default behavior.
+ +

The following options can be used to set or enable LLVM specific options:

+ +
+
--with-llvmgccdir
+
Path to the LLVM C/C++ FrontEnd to be used with this LLVM configuration. + The value of this option should specify the full pathname of the C/C++ Front + End to be used. If this option is not provided, the PATH will be searched for + a program named llvm-gcc and the C/C++ FrontEnd install directory will + be inferred from the path found. If the option is not given, and no llvm-gcc + can be found in the path then a warning will be produced by + configure indicating this situation. LLVM may still be built with + the tools-only target but attempting to build the runtime libraries + will fail as these libraries require llvm-gcc and llvm-g++. See + Install the GCC Front End for details on installing + the C/C++ Front End. See + Bootstrapping the LLVM C/C++ Front-End + for details on building the C/C++ Front End.
+
--with-tclinclude
+
Path to the tcl include directory under which tclsh can be + found. Use this if you have multiple tcl installations on your machine and you + want to use a specific one (8.x) for LLVM. LLVM only uses tcl for running the + dejagnu based test suite in llvm/test. If you don't specify this + option, the LLVM configure script will search for the tcl 8.4 and 8.3 + releases. +

+
+
--enable-optimized
+
+ Enables optimized compilation (debugging symbols are removed + and GCC optimization flags are enabled). Note that this is the default + setting if you are using the LLVM distribution. The default behavior + of an Subversion checkout is to use an unoptimized build (also known as a + debug build). +

+
+
--enable-debug-runtime
+
+ Enables debug symbols in the runtime libraries. The default is to strip + debug symbols from the runtime libraries. +
+
--enable-jit
+
+ Compile the Just In Time (JIT) compiler functionality. This is not + available + on all platforms. The default is dependent on platform, so it is best + to explicitly enable it if you want it. +

+
+
--enable-targets=target-option
+
Controls which targets will be built and linked into llc. The default + value for target_options is "all" which builds and links all + available targets. The value "host-only" can be specified to build only a + native compiler (no cross-compiler targets available). The "native" target is + selected as the target of the build host. You can also specify a comma + separated list of target names that you want available in llc. The target + names use all lower case. The current set of targets is:
+ alpha, ia64, powerpc, skeleton, sparc, x86. +

+
--enable-doxygen
+
Look for the doxygen program and enable construction of doxygen based + documentation from the source code. This is disabled by default because + generating the documentation can take a long time and producess 100s of + megabytes of output.
+
--with-udis86
+
LLVM can use external disassembler library for various purposes (now it's + used only for examining code produced by JIT). This option will enable usage + of udis86 x86 (both 32 and 64 + bits) disassembler library.
+
+ +

To configure LLVM, follow these steps:

+ +
    +
  1. Change directory into the object root directory:

    + +
    % cd OBJ_ROOT
  2. + +
  3. Run the configure script located in the LLVM source + tree:

    + +
    +
    % SRC_ROOT/configure --prefix=/install/path [other options]
    +
  4. +
+ +
+ + + + +
+ +

Once you have configured LLVM, you can build it. There are three types of +builds:

+ +
+
Debug Builds +
+ These builds are the default when one is using an Subversion checkout and + types gmake (unless the --enable-optimized option was + used during configuration). The build system will compile the tools and + libraries with debugging information. To get a Debug Build using the + LLVM distribution the --disable-optimized option must be passed + to configure. +

+ +
Release (Optimized) Builds +
+ These builds are enabled with the --enable-optimized option to + configure or by specifying ENABLE_OPTIMIZED=1 on the + gmake command line. For these builds, the build system will + compile the tools and libraries with GCC optimizations enabled and strip + debugging information from the libraries and executables it generates. + Note that Release Builds are default when using an LLVM distribution. +

+ +
Profile Builds +
+ These builds are for use with profiling. They compile profiling + information into the code for use with programs like gprof. + Profile builds must be started by specifying ENABLE_PROFILING=1 + on the gmake command line. +
+ +

Once you have LLVM configured, you can build it by entering the +OBJ_ROOT directory and issuing the following command:

+ +
% gmake
+ +

If the build fails, please check here to see if you +are using a version of GCC that is known not to compile LLVM.

+ +

+If you have multiple processors in your machine, you may wish to use some of +the parallel build options provided by GNU Make. For example, you could use the +command:

+ +
% gmake -j2
+ +

There are several special targets which are useful when working with the LLVM +source code:

+ +
+
gmake clean +
+ Removes all files generated by the build. This includes object files, + generated C/C++ files, libraries, and executables. +

+ +
gmake dist-clean +
+ Removes everything that gmake clean does, but also removes files + generated by configure. It attempts to return the source tree to the + original state in which it was shipped. +

+ +
gmake install +
+ Installs LLVM header files, libraries, tools, and documentation in a + hierarchy + under $PREFIX, specified with ./configure --prefix=[dir], which + defaults to /usr/local. +

+ +
gmake -C runtime install-bytecode +
+ Assuming you built LLVM into $OBJDIR, when this command is run, it will + install bitcode libraries into the GCC front end's bitcode library + directory. If you need to update your bitcode libraries, + this is the target to use once you've built them. +

+
+ +

Please see the Makefile Guide for further +details on these make targets and descriptions of other targets +available.

+ +

It is also possible to override default values from configure by +declaring variables on the command line. The following are some examples:

+ +
+
gmake ENABLE_OPTIMIZED=1 +
+ Perform a Release (Optimized) build. +

+ +
gmake ENABLE_OPTIMIZED=1 DISABLE_ASSERTIONS=1 +
+ Perform a Release (Optimized) build without assertions enabled. +

+ +
gmake ENABLE_OPTIMIZED=0 +
+ Perform a Debug build. +

+ +
gmake ENABLE_PROFILING=1 +
+ Perform a Profiling build. +

+ +
gmake VERBOSE=1 +
+ Print what gmake is doing on standard output. +

+ +
gmake TOOL_VERBOSE=1
+
Ask each tool invoked by the makefiles to print out what it is doing on + the standard output. This also implies VERBOSE=1. +

+
+ +

Every directory in the LLVM object tree includes a Makefile to build +it and any subdirectories that it contains. Entering any directory inside the +LLVM object tree and typing gmake should rebuild anything in or below +that directory that is out of date.

+ +
+ + + + +
+

It is possible to cross-compile LLVM itself. That is, you can create LLVM + executables and libraries to be hosted on a platform different from the + platform where they are build (a Canadian Cross build). To configure a + cross-compile, supply the configure script with --build and + --host options that are different. The values of these options must + be legal target triples that your GCC compiler supports.

+ +

The result of such a build is executables that are not runnable on + on the build host (--build option) but can be executed on the compile host + (--host option).

+
+ + + + +
+ +

The LLVM build system is capable of sharing a single LLVM source tree among +several LLVM builds. Hence, it is possible to build LLVM for several different +platforms or configurations using the same source tree.

+ +

This is accomplished in the typical autoconf manner:

+ +
    +
  • Change directory to where the LLVM object files should live:

    + +
    % cd OBJ_ROOT
  • + +
  • Run the configure script found in the LLVM source + directory:

    + +
    % SRC_ROOT/configure
  • +
+ +

The LLVM build will place files underneath OBJ_ROOT in directories +named after the build type:

+ +
+
Debug Builds +
+
+
Tools +
OBJ_ROOT/Debug/bin +
Libraries +
OBJ_ROOT/Debug/lib +
+

+ +
Release Builds +
+
+
Tools +
OBJ_ROOT/Release/bin +
Libraries +
OBJ_ROOT/Release/lib +
+

+ +
Profile Builds +
+
+
Tools +
OBJ_ROOT/Profile/bin +
Libraries +
OBJ_ROOT/Profile/lib +
+
+ +
+ + + + +
+ +

+If you're running on a Linux system that supports the "binfmt_misc" +module, and you have root access on the system, you can set your system up to +execute LLVM bitcode files directly. To do this, use commands like this (the +first command may not be required if you are already using the module):

+ +
+
+$ mount -t binfmt_misc none /proc/sys/fs/binfmt_misc
+$ echo ':llvm:M::BC::/path/to/lli:' > /proc/sys/fs/binfmt_misc/register
+$ chmod u+x hello.bc   (if needed)
+$ ./hello.bc
+
+
+ +

+This allows you to execute LLVM bitcode files directly. Thanks to Jack +Cummings for pointing this out! +

+ +
+ + + + + + +
+ +

One useful source of information about the LLVM source base is the LLVM doxygen documentation available at http://llvm.org/doxygen/. +The following is a brief introduction to code layout:

+ +
+ + + +
+

This directory contains some simple examples of how to use the LLVM IR and + JIT.

+
+ + + +
+ +

This directory contains public header files exported from the LLVM +library. The three main subdirectories of this directory are:

+ +
+
llvm/include/llvm
+
This directory contains all of the LLVM specific header files. This + directory also has subdirectories for different portions of LLVM: + Analysis, CodeGen, Target, Transforms, + etc...
+ +
llvm/include/llvm/Support
+
This directory contains generic support libraries that are provided with + LLVM but not necessarily specific to LLVM. For example, some C++ STL utilities + and a Command Line option processing library store their header files here. +
+ +
llvm/include/llvm/Config
+
This directory contains header files configured by the configure + script. They wrap "standard" UNIX and C header files. Source code can + include these header files which automatically take care of the conditional + #includes that the configure script generates.
+
+
+ + + +
+ +

This directory contains most of the source files of the LLVM system. In LLVM, +almost all code exists in libraries, making it very easy to share code among the +different tools.

+ +
+
llvm/lib/VMCore/
+
This directory holds the core LLVM source files that implement core + classes like Instruction and BasicBlock.
+ +
llvm/lib/AsmParser/
+
This directory holds the source code for the LLVM assembly language parser + library.
+ +
llvm/lib/BitCode/
+
This directory holds code for reading and write LLVM bitcode.
+ +
llvm/lib/Analysis/
This directory contains a variety of + different program analyses, such as Dominator Information, Call Graphs, + Induction Variables, Interval Identification, Natural Loop Identification, + etc.
+ +
llvm/lib/Transforms/
+
This directory contains the source code for the LLVM to LLVM program + transformations, such as Aggressive Dead Code Elimination, Sparse Conditional + Constant Propagation, Inlining, Loop Invariant Code Motion, Dead Global + Elimination, and many others.
+ +
llvm/lib/Target/
+
This directory contains files that describe various target architectures + for code generation. For example, the llvm/lib/Target/X86 + directory holds the X86 machine description while + llvm/lib/Target/CBackend implements the LLVM-to-C converter.
+ +
llvm/lib/CodeGen/
+
This directory contains the major parts of the code generator: Instruction + Selector, Instruction Scheduling, and Register Allocation.
+ +
llvm/lib/Debugger/
+
This directory contains the source level debugger library that makes + it possible to instrument LLVM programs so that a debugger could identify + source code locations at which the program is executing.
+ +
llvm/lib/ExecutionEngine/
+
This directory contains libraries for executing LLVM bitcode directly + at runtime in both interpreted and JIT compiled fashions.
+ +
llvm/lib/Support/
+
This directory contains the source code that corresponds to the header + files located in llvm/include/Support/.
+ +
llvm/lib/System/
+
This directory contains the operating system abstraction layer that + shields LLVM from platform-specific coding.
+
+ +
+ + + +
+

This directory contains projects that are not strictly part of LLVM but are + shipped with LLVM. This is also the directory where you should create your own + LLVM-based projects. See llvm/projects/sample for an example of how + to set up your own project.

+
+ + + +
+ +

This directory contains libraries which are compiled into LLVM bitcode and +used when linking programs with the GCC front end. Most of these libraries are +skeleton versions of real libraries; for example, libc is a stripped down +version of glibc.

+ +

Unlike the rest of the LLVM suite, this directory needs the LLVM GCC front +end to compile.

+ +
+ + + +
+

This directory contains feature and regression tests and other basic sanity + checks on the LLVM infrastructure. These are intended to run quickly and cover + a lot of territory without being exhaustive.

+
+ + + +
+

This is not a directory in the normal llvm module; it is a separate + Subversion + module that must be checked out (usually to projects/test-suite). + This + module contains a comprehensive correctness, performance, and benchmarking + test + suite for LLVM. It is a separate Subversion module because not every LLVM + user is + interested in downloading or building such a comprehensive test suite. For + further details on this test suite, please see the + Testing Guide document.

+
+ + + +
+ +

The tools directory contains the executables built out of the +libraries above, which form the main part of the user interface. You can +always get help for a tool by typing tool_name --help. The +following is a brief introduction to the most important tools. More detailed +information is in the Command Guide.

+ +
+ +
bugpoint
+
bugpoint is used to debug + optimization passes or code generation backends by narrowing down the + given test case to the minimum number of passes and/or instructions that + still cause a problem, whether it is a crash or miscompilation. See HowToSubmitABug.html for more information + on using bugpoint.
+ +
llvmc
+
The LLVM Compiler Driver. This program can + be configured to utilize both LLVM and non-LLVM compilation tools to enable + pre-processing, translation, optimization, assembly, and linking of programs + all from one command line. llvmc also takes care of processing the + dependent libraries found in bitcode. This reduces the need to get the + traditional -l<name> options right on the command line. Please + note that this tool, while functional, is still experimental and not feature + complete.
+ +
llvm-ar
+
The archiver produces an archive containing + the given LLVM bitcode files, optionally with an index for faster + lookup.
+ +
llvm-as
+
The assembler transforms the human readable LLVM assembly to LLVM + bitcode.
+ +
llvm-dis
+
The disassembler transforms the LLVM bitcode to human readable + LLVM assembly.
+ +
llvm-ld
+
llvm-ld is a general purpose and extensible linker for LLVM. + This is the linker invoked by llvmc. It performsn standard link time + optimizations and allows optimization modules to be loaded and run so that + language specific optimizations can be applied at link time.
+ +
llvm-link
+
llvm-link, not surprisingly, links multiple LLVM modules into + a single program.
+ +
lli
+
lli is the LLVM interpreter, which + can directly execute LLVM bitcode (although very slowly...). For architectures + that support it (currently x86, Sparc, and PowerPC), by default, lli + will function as a Just-In-Time compiler (if the functionality was compiled + in), and will execute the code much faster than the interpreter.
+ +
llc
+
llc is the LLVM backend compiler, which + translates LLVM bitcode to a native code assembly file or to C code (with + the -march=c option).
+ +
llvm-gcc
+
llvm-gcc is a GCC-based C frontend that has been retargeted to + use LLVM as its backend instead of GCC's RTL backend. It can also emit LLVM + bitcode or assembly (with the -emit-llvm option) instead of the + usual machine code output. It works just like any other GCC compiler, + taking the typical -c, -S, -E, -o options that are typically used. + Additionally, the the source code for llvm-gcc is available as a + separate Subversion module.
+ +
opt
+
opt reads LLVM bitcode, applies a series of LLVM to LLVM + transformations (which are specified on the command line), and then outputs + the resultant bitcode. The 'opt --help' command is a good way to + get a list of the program transformations available in LLVM.
+
opt can also be used to run a specific analysis on an input + LLVM bitcode file and print out the results. It is primarily useful for + debugging analyses, or familiarizing yourself with what an analysis does.
+
+
+ + + +
+ +

This directory contains utilities for working with LLVM source code, and some +of the utilities are actually required as part of the build process because they +are code generators for parts of LLVM infrastructure.

+ +
+
codegen-diff
codegen-diff is a script + that finds differences between code that LLC generates and code that LLI + generates. This is a useful tool if you are debugging one of them, + assuming that the other generates correct output. For the full user + manual, run `perldoc codegen-diff'.

+ +
emacs/
The emacs directory contains + syntax-highlighting files which will work with Emacs and XEmacs editors, + providing syntax highlighting support for LLVM assembly files and TableGen + description files. For information on how to use the syntax files, consult + the README file in that directory.

+ +
getsrcs.sh
The getsrcs.sh script finds + and outputs all non-generated source files, which is useful if one wishes + to do a lot of development across directories and does not want to + individually find each file. One way to use it is to run, for example: + xemacs `utils/getsources.sh` from the top of your LLVM source + tree.

+ +
llvmgrep
+
This little tool performs an "egrep -H -n" on each source file in LLVM and + passes to it a regular expression provided on llvmgrep's command + line. This is a very efficient way of searching the source base for a + particular regular expression.
+ +
makellvm
The makellvm script compiles all + files in the current directory and then compiles and links the tool that + is the first argument. For example, assuming you are in the directory + llvm/lib/Target/Sparc, if makellvm is in your path, + simply running makellvm llc will make a build of the current + directory, switch to directory llvm/tools/llc and build it, + causing a re-linking of LLC.

+ +
NewNightlyTest.pl and + NightlyTestTemplate.html
These files are used in a + cron script to generate nightly status reports of the functionality of + tools, and the results can be seen by following the appropriate link on + the LLVM homepage.

+ +
TableGen/
The TableGen directory contains + the tool used to generate register descriptions, instruction set + descriptions, and even assemblers from common TableGen description + files.

+ +
vim/
The vim directory contains + syntax-highlighting files which will work with the VIM editor, providing + syntax highlighting support for LLVM assembly files and TableGen + description files. For information on how to use the syntax files, consult + the README file in that directory.

+ +
+ +
+ + + +
+

This directory contains build scripts and project files for use with + Visual C++. This allows developers on Windows to build LLVM without the need + for Cygwin. The contents of this directory should be considered experimental + at this time. +

+
+ + + + +
+

This section gives an example of using LLVM. llvm-gcc3 is now obsolete, +so we only include instructions for llvm-gcc4. +

+ +

Note: The gcc4 frontend's invocation is considerably different +from the previous gcc3 frontend. In particular, the gcc4 frontend does not +create bitcode by default: gcc4 produces native code. As the example below illustrates, +the '--emit-llvm' flag is needed to produce LLVM bitcode output. For makefiles and +configure scripts, the CFLAGS variable needs '--emit-llvm' to produce bitcode +output.

+
+ + + + +
+ +
    +
  1. First, create a simple C file, name it 'hello.c':

    + +
    +
    +#include <stdio.h>
    +
    +int main() {
    +  printf("hello world\n");
    +  return 0;
    +}
    +
  2. + +
  3. Next, compile the C file into a native executable:

    + +
    % llvm-gcc hello.c -o hello
    + +

    Note that llvm-gcc works just like GCC by default. The standard -S and + -c arguments work as usual (producing a native .s or .o file, + respectively).

  4. + +
  5. Next, compile the C file into a LLVM bitcode file:

    + +
    +
    % llvm-gcc -O3 -emit-llvm hello.c -c -o hello.bc
    + +

    The -emit-llvm option can be used with the -S or -c options to emit an + LLVM ".ll" or ".bc" file (respectively) for the code. This allows you + to use the standard LLVM tools on + the bitcode file.

    + +

    Unlike llvm-gcc3, llvm-gcc4 correctly responds to -O[0123] arguments. +

  6. + +
  7. Run the program in both forms. To run the program, use:

    + +
    % ./hello
    + +

    and

    + +
    % lli hello.bc
    + +

    The second examples shows how to invoke the LLVM JIT, lli.

  8. + +
  9. Use the llvm-dis utility to take a look at the LLVM assembly + code:

    + +
    +
    llvm-dis < hello.bc | less
    +
  10. + +
  11. Compile the program to native assembly using the LLC code + generator:

    + +
    % llc hello.bc -o hello.s
  12. + +
  13. Assemble the native assembly language file into a program:

    + +
    +
    +Solaris: % /opt/SUNWspro/bin/cc -xarch=v9 hello.s -o hello.native
    +
    +Others:  % gcc hello.s -o hello.native
    +
    +
  14. + +
  15. Execute the native code program:

    + +
    % ./hello.native
    + +

    Note that using llvm-gcc to compile directly to native code (i.e. when + the -emit-llvm option is not present) does steps 6/7/8 for you.

    +
  16. + +
+ +
+ + + + + + +
+ +

If you are having problems building or using LLVM, or if you have any other +general questions about LLVM, please consult the Frequently +Asked Questions page.

+ +
+ + +
+ Links +
+ + +
+ +

This document is just an introduction on how to use LLVM to do +some simple things... there are many more interesting and complicated things +that you can do that aren't documented here (but we'll gladly accept a patch +if you want to write something up!). For more information about LLVM, check +out:

+ + + +
+ + + +
+
+ Valid CSS + Valid HTML 4.01 + + Chris Lattner
+ Reid Spencer
+ The LLVM Compiler Infrastructure
+ Last modified: $Date$ +
+ + diff --git a/libclamav/c++/llvm/docs/GettingStartedVS.html b/libclamav/c++/llvm/docs/GettingStartedVS.html new file mode 100644 index 000000000..5a86199f7 --- /dev/null +++ b/libclamav/c++/llvm/docs/GettingStartedVS.html @@ -0,0 +1,417 @@ + + + + + Getting Started with LLVM System for Microsoft Visual Studio + + + + +
+ Getting Started with the LLVM System using Microsoft Visual Studio +
+ + + +
+

Written by: + Jeff Cohen +

+
+ + + + + + +
+ +

The Visual Studio port at this time is experimental. It is suitable for + use only if you are writing your own compiler front end or otherwise have a + need to dynamically generate machine code. The JIT and interpreter are + functional, but it is currently not possible to generate assembly code which + is then assembled into an executable. You can indirectly create executables + by using the C back end.

+ +

To emphasize, there is no C/C++ front end currently available. + llvm-gcc is based on GCC, which cannot be bootstrapped using VC++. + Eventually there should be a llvm-gcc based on Cygwin or MinGW that + is usable. There is also the option of generating bitcode files on Unix and + copying them over to Windows. But be aware the odds of linking C++ code + compiled with llvm-gcc with code compiled with VC++ is essentially + zero.

+ +

The LLVM test suite cannot be run on the Visual Studio port at this + time.

+ +

Most of the tools build and work. bugpoint does build, but does + not work. The other tools 'should' work, but have not been fully tested.

+ +

Additional information about the LLVM directory structure and tool chain + can be found on the main Getting Started + page.

+ +
+ + + + + +
+ +

Here's the short story for getting up and running quickly with LLVM:

+ +
    +
  1. Read the documentation.
  2. +
  3. Seriously, read the documentation.
  4. +
  5. Remember that you were warned twice about reading the documentation.
  6. + +
  7. Get the Source Code +
      +
    • With the distributed files: +
        +
      1. cd where-you-want-llvm-to-live +
      2. gunzip --stdout llvm-version.tar.gz | tar -xvf - +       or use WinZip +
      3. cd llvm
      4. +
    • + +
    • With anonymous Subversion access: +
        +
      1. cd where-you-want-llvm-to-live
      2. +
      3. svn co http://llvm.org/svn/llvm-project/llvm-top/trunk llvm-top +
      4. +
      5. make checkout MODULE=llvm +
      6. cd llvm
      7. +
    • +
  8. + +
  9. Use CMake to generate up-to-date + project files: +
    • This step is currently optional as LLVM does still come with a + normal Visual Studio solution file, but it is not always kept up-to-date + and will soon be deprecated in favor of the multi-platform generator + CMake.
    • +
    • If CMake is installed then the most simple way is to just start the + CMake GUI, select the directory where you have LLVM extracted to, and + the default options should all be fine. The one option you may really + want to change, regardless of anything else, might be the + CMAKE_INSTALL_PREFIX setting to select a directory to INSTALL to once + compiling is complete.
    • +
    • If you use CMake to generate the Visual Studio solution and project + files, then the Solution will have a few extra options compared to the + current included one. The projects may still be built individually, but + to build them all do not just select all of them in batch build (as some + are meant as configuration projects), but rather select and build just + the ALL_BUILD project to build everything, or the INSTALL project, which + first builds the ALL_BUILD project, then installs the LLVM headers, libs, + and other useful things to the directory set by the CMAKE_INSTALL_PREFIX + setting when you first configured CMake.
    • +
    +
  10. + +
  11. Start Visual Studio +
      +
    • If you did not use CMake, then simply double click on the solution + file llvm/win32/llvm.sln.
    • +
    • If you used CMake, then the directory you created the project files, + the root directory will have an llvm.sln file, just + double-click on that to open Visual Studio.
    • +
  12. + +
  13. Build the LLVM Suite: +
      +
    • Simply build the solution.
    • +
    • The Fibonacci project is a sample program that uses the JIT. Modify + the project's debugging properties to provide a numeric command line + argument. The program will print the corresponding fibonacci value.
    • +
  14. + +
+ +

It is strongly encouraged that you get the latest version from Subversion as +changes are continually making the VS support better.

+ +
+ + + + + +
+ +

Before you begin to use the LLVM system, review the requirements given + below. This may save you some trouble by knowing ahead of time what hardware + and software you will need.

+ +
+ + + + +
+ +

Any system that can adequately run Visual Studio .NET 2005 SP1 is fine. + The LLVM source tree and object files, libraries and executables will consume + approximately 3GB.

+ +
+ + + +
+ +

You will need Visual Studio .NET 2005 SP1 or higher. The VS2005 SP1 + beta and the normal VS2005 still have bugs that are not completely + compatible. VS2003 would work except (at last check) it has a bug with + friend classes that you can work-around with some minor code rewriting + (and please submit a patch if you do). Earlier versions of Visual Studio + do not support the C++ standard well enough and will not work.

+ +

You will also need the CMake build + system since it generates the project files you will use to build with.

+ +

+ Do not install the LLVM directory tree into a path containing spaces (e.g. + C:\Documents and Settings\...) as the configure step will fail.

+ +
+ + + + + +
+ +

The remainder of this guide is meant to get you up and running with +LLVM using Visual Studio and to give you some basic information about the LLVM +environment.

+ +
+ + + + +
+ +

Throughout this manual, the following names are used to denote paths +specific to the local system and working environment. These are not +environment variables you need to set but just strings used in the rest +of this document below. In any of the examples below, simply replace +each of these names with the appropriate pathname on your local system. +All these paths are absolute:

+ +
+
SRC_ROOT
+

This is the top level directory of the LLVM source tree.

+ +
OBJ_ROOT
+

This is the top level directory of the LLVM object tree (i.e. the + tree where object files and compiled programs will be placed. It is + fixed at SRC_ROOT/win32).

+
+ +
+ + + + +
+ +

The object files are placed under OBJ_ROOT/Debug for debug builds + and OBJ_ROOT/Release for release (optimized) builds. These include + both executables and libararies that your application can link against.

+ +

The files that configure would create when building on Unix are + created by the Configure project and placed in + OBJ_ROOT/llvm. You application must have OBJ_ROOT in its include + search path just before SRC_ROOT/include.

+ +
+ + + + + +
+ +
    +
  1. First, create a simple C file, name it 'hello.c':

    + +
    +
    +#include <stdio.h>
    +int main() {
    +  printf("hello world\n");
    +  return 0;
    +}
    +
  2. + +
  3. Next, compile the C file into a LLVM bitcode file:

    + +
    +
    +% llvm-gcc -c hello.c -emit-llvm -o hello.bc
    +
    +
    + +

    This will create the result file hello.bc which is the LLVM + bitcode that corresponds the the compiled program and the library + facilities that it required. You can execute this file directly using + lli tool, compile it to native assembly with the llc, + optimize or analyze it further with the opt tool, etc.

    + +

    Note: while you cannot do this step on Windows, you can do it on a + Unix system and transfer hello.bc to Windows. Important: + transfer as a binary file!

  4. + +
  5. Run the program using the just-in-time compiler:

    + +
    +
    +% lli hello.bc
    +
    +
    + +

    Note: this will only work for trivial C programs. Non-trivial programs + (and any C++ program) will have dependencies on the GCC runtime that + won't be satisfied by the Microsoft runtime libraries.

  6. + +
  7. Use the llvm-dis utility to take a look at the LLVM assembly + code:

    + +
    +
    +% llvm-dis < hello.bc | more
    +
    +
  8. + +
  9. Compile the program to C using the LLC code generator:

    + +
    +
    +% llc -march=c hello.bc
    +
    +
  10. + +
  11. Compile to binary using Microsoft C:

    + +
    +
    +% cl hello.cbe.c
    +
    +
    + +

    Note: this will only work for trivial C programs. Non-trivial programs + (and any C++ program) will have dependencies on the GCC runtime that won't + be satisfied by the Microsoft runtime libraries.

  12. + +
  13. Execute the native code program:

    + +
    +
    +% hello.cbe.exe
    +
    +
  14. +
+ +
+ + + + + +
+ +
    +
  • In Visual C++, if you are linking with the x86 target statically, the + linker will remove the x86 target library from your generated executable or + shared library because there are no references to it. You can force the + linker to include these references by using + "/INCLUDE:_X86TargetMachineModule" when linking. In the Visual + Studio IDE, this can be added in +Project Properties->Linker->Input->Force Symbol References. +
  • +
+ +

If you are having problems building or using LLVM, or if you have any other +general questions about LLVM, please consult the Frequently +Asked Questions page.

+ +
+ + +
+ Links +
+ + +
+ +

This document is just an introduction to how to use LLVM to do +some simple things... there are many more interesting and complicated things +that you can do that aren't documented here (but we'll gladly accept a patch +if you want to write something up!). For more information about LLVM, check +out:

+ + + +
+ + + +
+
+ Valid CSS + Valid HTML 4.01 + + Jeff Cohen
+ The LLVM Compiler Infrastructure
+ Last modified: $Date$ +
+ + diff --git a/libclamav/c++/llvm/docs/GoldPlugin.html b/libclamav/c++/llvm/docs/GoldPlugin.html new file mode 100644 index 000000000..77a417f57 --- /dev/null +++ b/libclamav/c++/llvm/docs/GoldPlugin.html @@ -0,0 +1,200 @@ + + + + LLVM gold plugin + + + + +
LLVM gold plugin
+
    +
  1. Introduction
  2. +
  3. How to build it
  4. +
  5. Usage +
  6. +
  7. Licensing
  8. +
+
Written by Nick Lewycky
+ + + + +
+

Building with link time optimization requires cooperation from the +system linker. LTO support on Linux systems requires that you use +the gold linker which supports +LTO via plugins. This is the same system used by the upcoming +GCC LTO +project.

+

The LLVM gold plugin implements the +gold plugin interface +on top of +libLTO. +The same plugin can also be used by other tools such as ar and +nm. +

+ + + +
+

You need to build gold with plugin support and build the LLVMgold +plugin.

+
    +
  • Build gold with plugin support: +
    +mkdir binutils
    +cd binutils
    +cvs -z 9 -d :pserver:anoncvs@sourceware.org:/cvs/src login
    +{enter "anoncvs" as the password}
    +cvs -z 9 -d :pserver:anoncvs@sourceware.org:/cvs/src co src
    +mkdir build
    +cd build
    +../src/configure --enable-gold --enable-plugins
    +make all-gold
    +
    + That should leave you with binutils/build/gold/ld-new which supports the +-plugin option. + +
  • Build the LLVMgold plugin: Configure LLVM with + --with-binutils-include=/path/to/binutils/src/include and run + make. +
+
+ + + +
+

The linker takes a -plugin option that points to the path of + the plugin .so file. To find out what link command gcc + would run in a given situation, run gcc -v [...] and look + for the line where it runs collect2. Replace that with + ld-new -plugin /path/to/LLVMgold.so to test it out. Once you're + ready to switch to using gold, backup your existing /usr/bin/ld + then replace it with ld-new.

+

You can produce bitcode files from llvm-gcc using + -emit-llvm or -flto, or the -O4 flag which is + synonymous with -O3 -flto.

+

llvm-gcc has a -use-gold-plugin option which looks + for the gold plugin in the same directories as it looks for cc1 and + passes the -plugin option to ld. It will not look for an alternate + linker, which is why you need gold to be the installed system linker in your + path.

+
+ + + + +
+

The following example shows a worked example of the gold plugin mixing + LLVM bitcode and native code. +

+--- a.c ---
+#include <stdio.h>
+
+extern void foo1(void);
+extern void foo4(void);
+
+void foo2(void) {
+  printf("Foo2\n");
+}
+
+void foo3(void) {
+  foo4();
+}
+
+int main(void) {
+  foo1();
+}
+
+--- b.c ---
+#include <stdio.h>
+
+extern void foo2(void);
+
+void foo1(void) {
+  foo2();
+}
+
+void foo4(void) {
+  printf("Foo4");
+}
+
+--- command lines ---
+$ llvm-gcc -flto a.c -c -o a.o              # <-- a.o is LLVM bitcode file
+$ ar q a.a a.o                              # <-- a.a is an archive with LLVM bitcode
+$ llvm-gcc b.c -c -o b.o                    # <-- b.o is native object file
+$ llvm-gcc -use-gold-plugin a.a b.o -o main # <-- link with LLVMgold plugin
+
+

Gold informs the plugin that foo3 is never referenced outside the IR, + leading LLVM to delete that function. However, unlike in the + libLTO + example gold does not currently eliminate foo4.

+
+ + + + +
+

gold, ar and nm all support plugins now, so everything should be + in place for an easy to use LTO build of autotooled projects:

+
    +
  • Follow the instructions on how to build libLLVMgold.so.
  • +
  • Install the newly built binutils to $PREFIX
  • +
  • Copy Release/lib/libLLVMgold.so to + $PREFIX/libexec/gcc/x86_64-unknown-linux-gnu/4.2.1/ and + $PREFIX/lib/bfd-plugins/
  • +
  • Set environment variables ($PREFIX is where you installed llvm-gcc and + binutils): +
    +export CC="$PREFIX/bin/llvm-gcc -use-gold-plugin"
    +export CXX="$PREFIX/bin/llvm-g++ -use-gold-plugin"
    +export AR="$PREFIX/bin/ar"
    +export NM="$PREFIX/bin/nm"
    +export RANLIB=/bin/true #ranlib is not needed, and doesn't support .bc files in .a
    +export CFLAGS="-O4"
    +
    +
  • +
  • Or you can just set your path: +
    +export PATH="$PREFIX/bin:$PATH"
    +export CC="llvm-gcc -use-gold-plugin"
    +export CXX="llvm-g++ -use-gold-plugin"
    +export RANLIB=/bin/true
    +export CFLAGS="-O4"
    +
    +
  • +
  • Configure & build the project as usual: ./configure && make && make check
  • +
+

The environment variable settings may work for non-autotooled projects + too, but you may need to set the LD environment variable as well.

+
+ + + + +
+

Gold is licensed under the GPLv3. LLVMgold uses the interface file +plugin-api.h from gold which means that the resulting LLVMgold.so +binary is also GPLv3. This can still be used to link non-GPLv3 programs just +as much as gold could without the plugin.

+
+ + +
+
+ Valid CSS + Valid HTML 4.01 + Nick Lewycky
+ The LLVM Compiler Infrastructure
+ Last modified: $Date: 2009-01-01 23:10:51 -0800 (Thu, 01 Jan 2009) $ +
+ + diff --git a/libclamav/c++/llvm/docs/HistoricalNotes/2000-11-18-EarlyDesignIdeas.txt b/libclamav/c++/llvm/docs/HistoricalNotes/2000-11-18-EarlyDesignIdeas.txt new file mode 100644 index 000000000..f08618119 --- /dev/null +++ b/libclamav/c++/llvm/docs/HistoricalNotes/2000-11-18-EarlyDesignIdeas.txt @@ -0,0 +1,74 @@ +Date: Sat, 18 Nov 2000 09:19:35 -0600 (CST) +From: Vikram Adve +To: Chris Lattner +Subject: a few thoughts + +I've been mulling over the virtual machine problem and I had some +thoughts about some things for us to think about discuss: + +1. We need to be clear on our goals for the VM. Do we want to emphasize + portability and safety like the Java VM? Or shall we focus on the + architecture interface first (i.e., consider the code generation and + processor issues), since the architecture interface question is also + important for portable Java-type VMs? + + This is important because the audiences for these two goals are very + different. Architects and many compiler people care much more about + the second question. The Java compiler and OS community care much more + about the first one. + + Also, while the architecture interface question is important for + Java-type VMs, the design constraints are very different. + + +2. Design issues to consider (an initial list that we should continue + to modify). Note that I'm not trying to suggest actual solutions here, + but just various directions we can pursue: + + a. A single-assignment VM, which we've both already been thinking about. + + b. A strongly-typed VM. One question is do we need the types to be + explicitly declared or should they be inferred by the dynamic compiler? + + c. How do we get more high-level information into the VM while keeping + to a low-level VM design? + + o Explicit array references as operands? An alternative is + to have just an array type, and let the index computations be + separate 3-operand instructions. + + o Explicit instructions to handle aliasing, e.g.s: + -- an instruction to say "I speculate that these two values are not + aliased, but check at runtime", like speculative execution in + EPIC? + -- or an instruction to check whether two values are aliased and + execute different code depending on the answer, somewhat like + predicated code in EPIC + + o (This one is a difficult but powerful idea.) + A "thread-id" field on every instruction that allows the static + compiler to generate a set of parallel threads, and then have + the runtime compiler and hardware do what they please with it. + This has very powerful uses, but thread-id on every instruction + is expensive in terms of instruction size and code size. + We would need to compactly encode it somehow. + + Also, this will require some reading on at least two other + projects: + -- Multiscalar architecture from Wisconsin + -- Simultaneous multithreading architecture from Washington + + o Or forget all this and stick to a traditional instruction set? + + +BTW, on an unrelated note, after the meeting yesterday, I did remember +that you had suggested doing instruction scheduling on SSA form instead +of a dependence DAG earlier in the semester. When we talked about +it yesterday, I didn't remember where the idea had come from but I +remembered later. Just giving credit where its due... + +Perhaps you can save the above as a file under RCS so you and I can +continue to expand on this. + +--Vikram + diff --git a/libclamav/c++/llvm/docs/HistoricalNotes/2000-11-18-EarlyDesignIdeasResp.txt b/libclamav/c++/llvm/docs/HistoricalNotes/2000-11-18-EarlyDesignIdeasResp.txt new file mode 100644 index 000000000..1c725f5aa --- /dev/null +++ b/libclamav/c++/llvm/docs/HistoricalNotes/2000-11-18-EarlyDesignIdeasResp.txt @@ -0,0 +1,199 @@ +Date: Sun, 19 Nov 2000 16:23:57 -0600 (CST) +From: Chris Lattner +To: Vikram Adve +Subject: Re: a few thoughts + +Okay... here are a few of my thoughts on this (it's good to know that we +think so alike!): + +> 1. We need to be clear on our goals for the VM. Do we want to emphasize +> portability and safety like the Java VM? Or shall we focus on the +> architecture interface first (i.e., consider the code generation and +> processor issues), since the architecture interface question is also +> important for portable Java-type VMs? + +I forsee the architecture looking kinda like this: (which is completely +subject to change) + +1. The VM code is NOT guaranteed safe in a java sense. Doing so makes it + basically impossible to support C like languages. Besides that, + certifying a register based language as safe at run time would be a + pretty expensive operation to have to do. Additionally, we would like + to be able to statically eliminate many bounds checks in Java + programs... for example. + + 2. Instead, we can do the following (eventually): + * Java bytecode is used as our "safe" representation (to avoid + reinventing something that we don't add much value to). When the + user chooses to execute Java bytecodes directly (ie, not + precompiled) the runtime compiler can do some very simple + transformations (JIT style) to convert it into valid input for our + VM. Performance is not wonderful, but it works right. + * The file is scheduled to be compiled (rigorously) at a later + time. This could be done by some background process or by a second + processor in the system during idle time or something... + * To keep things "safe" ie to enforce a sandbox on Java/foreign code, + we could sign the generated VM code with a host specific private + key. Then before the code is executed/loaded, we can check to see if + the trusted compiler generated the code. This would be much quicker + than having to validate consistency (especially if bounds checks have + been removed, for example) + +> This is important because the audiences for these two goals are very +> different. Architects and many compiler people care much more about +> the second question. The Java compiler and OS community care much more +> about the first one. + +3. By focusing on a more low level virtual machine, we have much more room + for value add. The nice safe "sandbox" VM can be provided as a layer + on top of it. It also lets us focus on the more interesting compilers + related projects. + +> 2. Design issues to consider (an initial list that we should continue +> to modify). Note that I'm not trying to suggest actual solutions here, +> but just various directions we can pursue: + +Understood. :) + +> a. A single-assignment VM, which we've both already been thinking +> about. + +Yup, I think that this makes a lot of sense. I am still intrigued, +however, by the prospect of a minimally allocated VM representation... I +think that it could have definate advantages for certain applications +(think very small machines, like PDAs). I don't, however, think that our +initial implementations should focus on this. :) + +Here are some other auxilliary goals that I think we should consider: + +1. Primary goal: Support a high performance dynamic compilation + system. This means that we have an "ideal" division of labor between + the runtime and static compilers. Of course, the other goals of the + system somewhat reduce the importance of this point (f.e. portability + reduces performance, but hopefully not much) +2. Portability to different processors. Since we are most familiar with + x86 and solaris, I think that these two are excellent candidates when + we get that far... +3. Support for all languages & styles of programming (general purpose + VM). This is the point that disallows java style bytecodes, where all + array refs are checked for bounds, etc... +4. Support linking between different language families. For example, call + C functions directly from Java without using the nasty/slow/gross JNI + layer. This involves several subpoints: + A. Support for languages that require garbage collectors and integration + with languages that don't. As a base point, we could insist on + always using a conservative GC, but implement free as a noop, f.e. + +> b. A strongly-typed VM. One question is do we need the types to be +> explicitly declared or should they be inferred by the dynamic +> compiler? + + B. This is kind of similar to another idea that I have: make OOP + constructs (virtual function tables, class heirarchies, etc) explicit + in the VM representation. I believe that the number of additional + constructs would be fairly low, but would give us lots of important + information... something else that would/could be important is to + have exceptions as first class types so that they would be handled in + a uniform way for the entire VM... so that C functions can call Java + functions for example... + +> c. How do we get more high-level information into the VM while keeping +> to a low-level VM design? +> o Explicit array references as operands? An alternative is +> to have just an array type, and let the index computations be +> separate 3-operand instructions. + + C. In the model I was thinking of (subject to change of course), we + would just have an array type (distinct from the pointer + types). This would allow us to have arbitrarily complex index + expressions, while still distinguishing "load" from "Array load", + for example. Perhaps also, switch jump tables would be first class + types as well? This would allow better reasoning about the program. + +5. Support dynamic loading of code from various sources. Already + mentioned above was the example of loading java bytecodes, but we want + to support dynamic loading of VM code as well. This makes the job of + the runtime compiler much more interesting: it can do interprocedural + optimizations that the static compiler can't do, because it doesn't + have all of the required information (for example, inlining from + shared libraries, etc...) + +6. Define a set of generally useful annotations to add to the VM + representation. For example, a function can be analysed to see if it + has any sideeffects when run... also, the MOD/REF sets could be + calculated, etc... we would have to determine what is reasonable. This + would generally be used to make IP optimizations cheaper for the + runtime compiler... + +> o Explicit instructions to handle aliasing, e.g.s: +> -- an instruction to say "I speculate that these two values are not +> aliased, but check at runtime", like speculative execution in +> EPIC? +> -- or an instruction to check whether two values are aliased and +> execute different code depending on the answer, somewhat like +> predicated code in EPIC + +These are also very good points... if this can be determined at compile +time. I think that an epic style of representation (not the instruction +packing, just the information presented) could be a very interesting model +to use... more later... + +> o (This one is a difficult but powerful idea.) +> A "thread-id" field on every instruction that allows the static +> compiler to generate a set of parallel threads, and then have +> the runtime compiler and hardware do what they please with it. +> This has very powerful uses, but thread-id on every instruction +> is expensive in terms of instruction size and code size. +> We would need to compactly encode it somehow. + +Yes yes yes! :) I think it would be *VERY* useful to include this kind +of information (which EPIC architectures *implicitly* encode. The trend +that we are seeing supports this greatly: + +1. Commodity processors are getting massive SIMD support: + * Intel/Amd MMX/MMX2 + * AMD's 3Dnow! + * Intel's SSE/SSE2 + * Sun's VIS +2. SMP is becoming much more common, especially in the server space. +3. Multiple processors on a die are right around the corner. + +If nothing else, not designing this in would severely limit our future +expansion of the project... + +> Also, this will require some reading on at least two other +> projects: +> -- Multiscalar architecture from Wisconsin +> -- Simultaneous multithreading architecture from Washington +> +> o Or forget all this and stick to a traditional instruction set? + +Heh... :) Well, from a pure research point of view, it is almost more +attactive to go with the most extreme/different ISA possible. On one axis +you get safety and conservatism, and on the other you get degree of +influence that the results have. Of course the problem with pure research +is that often times there is no concrete product of the research... :) + +> BTW, on an unrelated note, after the meeting yesterday, I did remember +> that you had suggested doing instruction scheduling on SSA form instead +> of a dependence DAG earlier in the semester. When we talked about +> it yesterday, I didn't remember where the idea had come from but I +> remembered later. Just giving credit where its due... + +:) Thanks. + +> Perhaps you can save the above as a file under RCS so you and I can +> continue to expand on this. + +I think it makes sense to do so when we get our ideas more formalized and +bounce it back and forth a couple of times... then I'll do a more formal +writeup of our goals and ideas. Obviously our first implementation will +not want to do all of the stuff that I pointed out above... be we will +want to design the project so that we do not artificially limit ourselves +at sometime in the future... + +Anyways, let me know what you think about these ideas... and if they sound +reasonable... + +-Chris + diff --git a/libclamav/c++/llvm/docs/HistoricalNotes/2000-12-06-EncodingIdea.txt b/libclamav/c++/llvm/docs/HistoricalNotes/2000-12-06-EncodingIdea.txt new file mode 100644 index 000000000..8c452924d --- /dev/null +++ b/libclamav/c++/llvm/docs/HistoricalNotes/2000-12-06-EncodingIdea.txt @@ -0,0 +1,30 @@ +From: Chris Lattner [mailto:sabre@nondot.org] +Sent: Wednesday, December 06, 2000 6:41 PM +To: Vikram S. Adve +Subject: Additional idea with respect to encoding + +Here's another idea with respect to keeping the common case instruction +size down (less than 32 bits ideally): + +Instead of encoding an instruction to operate on two register numbers, +have it operate on two negative offsets based on the current register +number. Therefore, instead of using: + +r57 = add r55, r56 (r57 is the implicit dest register, of course) + +We could use: + +r57 = add -2, -1 + +My guess is that most SSA references are to recent values (especially if +they correspond to expressions like (x+y*z+p*q/ ...), so the negative +numbers would tend to stay small, even at the end of the procedure (where +the implicit register destination number could be quite large). Of course +the negative sign is reduntant, so you would be storing small integers +almost all of the time, and 5-6 bits worth of register number would be +plenty for most cases... + +What do you think? + +-Chris + diff --git a/libclamav/c++/llvm/docs/HistoricalNotes/2000-12-06-MeetingSummary.txt b/libclamav/c++/llvm/docs/HistoricalNotes/2000-12-06-MeetingSummary.txt new file mode 100644 index 000000000..b66e18556 --- /dev/null +++ b/libclamav/c++/llvm/docs/HistoricalNotes/2000-12-06-MeetingSummary.txt @@ -0,0 +1,83 @@ +SUMMARY +------- + +We met to discuss the LLVM instruction format and bytecode representation: + +ISSUES RESOLVED +--------------- + +1. We decided that we shall use a flat namespace to represent our + variables in SSA form, as opposed to having a two dimensional namespace + of the original variable and the SSA instance subscript. + +ARGUMENT AGAINST: + * A two dimensional namespace would be valuable when doing alias + analysis because the extra information can help limit the scope of + analysis. + +ARGUMENT FOR: + * Including this information would require that all users of the LLVM + bytecode would have to parse and handle it. This would slow down the + common case and inflate the instruction representation with another + infinite variable space. + +REASONING: + * It was decided that because original variable sources could be + reconstructed from SSA form in linear time, that it would be an + unjustified expense for the common case to include the extra + information for one optimization. Alias analysis itself is typically + greater than linear in asymptotic complexity, so this extra analaysis + would not affect the runtime of the optimization in a significant + way. Additionally, this would be an unlikely optimization to do at + runtime. + + +IDEAS TO CONSIDER +----------------- + +1. Including dominator information in the LLVM bytecode + representation. This is one example of an analysis result that may be + packaged with the bytecodes themselves. As a conceptual implementation + idea, we could include an immediate dominator number for each basic block + in the LLVM bytecode program. Basic blocks could be numbered according + to the order of occurance in the bytecode representation. + +2. Including loop header and body information. This would facilitate + detection of intervals and natural loops. + +UNRESOLVED ISSUES +----------------- + +1. Will oSUIF provide enough of an infrastructure to support the research + that we will be doing? We know that it has less than stellar + performance, but hope that this will be of little importance for our + static compiler. This could affect us if we decided to do some IP + research. Also we do not yet understand the level of exception support + currently implemented. + +2. Should we consider the requirements of a direct hardware implementation + of the LLVM when we design it? If so, several design issues should + have their priorities shifted. The other option is to focus on a + software layer interpreting the LLVM in all cases. + +3. Should we use some form of packetized format to improve forward + compatibility? For example, we could design the system to encode a + packet type and length field before analysis information, to allow a + runtime to skip information that it didn't understand in a bytecode + stream. The obvious benefit would be for compatibility, the drawback + is that it would tend to splinter that 'standard' LLVM definition. + +4. Should we use fixed length instructions or variable length + instructions? Fetching variable length instructions is expensive (for + either hardware or software based LLVM runtimes), but we have several + 'infinite' spaces that instructions operate in (SSA register numbers, + type spaces, or packet length [if packets were implemented]). Several + options were mentioned including: + A. Using 16 or 32 bit numbers, which would be 'big enough' + B. A scheme similar to how UTF-8 works, to encode infinite numbers + while keeping small number small. + C. Use something similar to Huffman encoding, so that the most common + numbers are the smallest. + +-Chris + diff --git a/libclamav/c++/llvm/docs/HistoricalNotes/2001-01-31-UniversalIRIdea.txt b/libclamav/c++/llvm/docs/HistoricalNotes/2001-01-31-UniversalIRIdea.txt new file mode 100644 index 000000000..111706a34 --- /dev/null +++ b/libclamav/c++/llvm/docs/HistoricalNotes/2001-01-31-UniversalIRIdea.txt @@ -0,0 +1,39 @@ +Date: Wed, 31 Jan 2001 12:04:33 -0600 +From: Vikram S. Adve +To: Chris Lattner +Subject: another thought + +I have a budding idea about making LLVM a little more ambitious: a +customizable runtime system that can be used to implement language-specific +virtual machines for many different languages. E.g., a C vm, a C++ vm, a +Java vm, a Lisp vm, .. + +The idea would be that LLVM would provide a standard set of runtime features +(some low-level like standard assembly instructions with code generation and +static and runtime optimization; some higher-level like type-safety and +perhaps a garbage collection library). Each language vm would select the +runtime features needed for that language, extending or customizing them as +needed. Most of the machine-dependent code-generation and optimization +features as well as low-level machine-independent optimizations (like PRE) +could be provided by LLVM and should be sufficient for any language, +simplifying the language compiler. (This would also help interoperability +between languages.) Also, some or most of the higher-level +machine-independent features like type-safety and access safety should be +reusable by different languages, with minor extensions. The language +compiler could then focus on language-specific analyses and optimizations. + +The risk is that this sounds like a universal IR -- something that the +compiler community has tried and failed to develop for decades, and is +universally skeptical about. No matter what we say, we won't be able to +convince anyone that we have a universal IR that will work. We need to +think about whether LLVM is different or if has something novel that might +convince people. E.g., the idea of providing a package of separable +features that different languages select from. Also, using SSA with or +without type-safety as the intermediate representation. + +One interesting starting point would be to discuss how a JVM would be +implemented on top of LLVM a bit more. That might give us clues on how to +structure LLVM to support one or more language VMs. + +--Vikram + diff --git a/libclamav/c++/llvm/docs/HistoricalNotes/2001-02-06-TypeNotationDebate.txt b/libclamav/c++/llvm/docs/HistoricalNotes/2001-02-06-TypeNotationDebate.txt new file mode 100644 index 000000000..c09cf1f03 --- /dev/null +++ b/libclamav/c++/llvm/docs/HistoricalNotes/2001-02-06-TypeNotationDebate.txt @@ -0,0 +1,67 @@ +Date: Tue, 6 Feb 2001 20:27:37 -0600 (CST) +From: Chris Lattner +To: Vikram S. Adve +Subject: Type notation debate... + +This is the way that I am currently planning on implementing types: + +Primitive Types: +type ::= void|bool|sbyte|ubyte|short|ushort|int|uint|long|ulong + +Method: +typelist ::= typelisth | /*empty*/ +typelisth ::= type | typelisth ',' type +type ::= type (typelist) + +Arrays (without and with size): +type ::= '[' type ']' | '[' INT ',' type ']' + +Pointer: +type ::= type '*' + +Structure: +type ::= '{' typelist '}' + +Packed: +type ::= '<' INT ',' type '>' + +Simple examples: + +[[ %4, int ]] - array of (array of 4 (int)) +[ { int, int } ] - Array of structure +[ < %4, int > ] - Array of 128 bit SIMD packets +int (int, [[int, %4]]) - Method taking a 2d array and int, returning int + + +Okay before you comment, please look at: + +http://www.research.att.com/~bs/devXinterview.html + +Search for "In another interview, you defined the C declarator syntax as +an experiment that failed. However, this syntactic construct has been +around for 27 years and perhaps more; why do you consider it problematic +(except for its cumbersome syntax)?" and read that response for me. :) + +Now with this syntax, his example would be represented as: + +[ %10, bool (int, int) * ] * + +vs + +bool (*(*)[10])(int, int) + +in C. + +Basically, my argument for this type construction system is that it is +VERY simple to use and understand (although it IS different than C, it is +very simple and straightforward, which C is NOT). In fact, I would assert +that most programmers TODAY do not understand pointers to member +functions, and have to look up an example when they have to write them. + +In my opinion, it is critically important to have clear and concise type +specifications, because types are going to be all over the programs. + +Let me know your thoughts on this. :) + +-Chris + diff --git a/libclamav/c++/llvm/docs/HistoricalNotes/2001-02-06-TypeNotationDebateResp1.txt b/libclamav/c++/llvm/docs/HistoricalNotes/2001-02-06-TypeNotationDebateResp1.txt new file mode 100644 index 000000000..8bfefbf69 --- /dev/null +++ b/libclamav/c++/llvm/docs/HistoricalNotes/2001-02-06-TypeNotationDebateResp1.txt @@ -0,0 +1,75 @@ +Date: Thu, 8 Feb 2001 08:42:04 -0600 +From: Vikram S. Adve +To: Chris Lattner +Subject: RE: Type notation debate... + +Chris, + +> Okay before you comment, please look at: +> +> http://www.research.att.com/~bs/devXinterview.html + +I read this argument. Even before that, I was already in agreement with you +and him that the C declarator syntax is difficult and confusing. + +But in fact, if you read the entire answer carefully, he came to the same +conclusion I do: that you have to go with familiar syntax over logical +syntax because familiarity is such a strong force: + + "However, familiarity is a strong force. To compare, in English, we +live +more or less happily with the absurd rules for "to be" (am, are, is, been, +was, were, ...) and all attempts to simplify are treated with contempt or +(preferably) humor. It be a curious world and it always beed." + +> Basically, my argument for this type construction system is that it is +> VERY simple to use and understand (although it IS different than C, it is +> very simple and straightforward, which C is NOT). In fact, I would assert +> that most programmers TODAY do not understand pointers to member +> functions, and have to look up an example when they have to write them. + +Again, I don't disagree with this at all. But to some extent this +particular problem is inherently difficult. Your syntax for the above +example may be easier for you to read because this is the way you have been +thinking about it. Honestly, I don't find it much easier than the C syntax. +In either case, I would have to look up an example to write pointers to +member functions. + +But pointers to member functions are nowhere near as common as arrays. And +the old array syntax: + type [ int, int, ...] +is just much more familiar and clear to people than anything new you +introduce, no matter how logical it is. Introducing a new syntax that may +make function pointers easier but makes arrays much more difficult seems +very risky to me. + +> In my opinion, it is critically important to have clear and concise type +> specifications, because types are going to be all over the programs. + +I absolutely agree. But the question is, what is more clear and concise? +The syntax programmers are used to out of years of experience or a new +syntax that they have never seen that has a more logical structure. I think +the answer is the former. Sometimes, you have to give up a better idea +because you can't overcome sociological barriers to it. Qwerty keyboards +and Windows are two classic examples of bad technology that are difficult to +root out. + +P.S. Also, while I agree that most your syntax is more logical, there is +one part that isn't: + +Arrays (without and with size): +type ::= '[' type ']' | '[' INT ',' type ']'. + +The arrays with size lists the dimensions and the type in a single list. +That is just too confusing: + [10, 40, int] +This seems to be a 3-D array where the third dimension is something strange. +It is too confusing to have a list of 3 things, some of which are dimensions +and one is a type. Either of the following would be better: + + array [10, 40] of int +or + int [10, 40] + +--Vikram + diff --git a/libclamav/c++/llvm/docs/HistoricalNotes/2001-02-06-TypeNotationDebateResp2.txt b/libclamav/c++/llvm/docs/HistoricalNotes/2001-02-06-TypeNotationDebateResp2.txt new file mode 100644 index 000000000..6e9784158 --- /dev/null +++ b/libclamav/c++/llvm/docs/HistoricalNotes/2001-02-06-TypeNotationDebateResp2.txt @@ -0,0 +1,53 @@ +Date: Thu, 8 Feb 2001 14:31:05 -0600 (CST) +From: Chris Lattner +To: Vikram S. Adve +Subject: RE: Type notation debate... + +> Arrays (without and with size): +> type ::= '[' type ']' | '[' INT ',' type ']'. +> +> The arrays with size lists the dimensions and the type in a single list. +> That is just too confusing: + +> [10, 40, int] +> This seems to be a 3-D array where the third dimension is something strange. +> It is too confusing to have a list of 3 things, some of which are dimensions +> and one is a type. + +The above grammar indicates that there is only one integer parameter, ie +the upper bound. The lower bound is always implied to be zero, for +several reasons: + +* As a low level VM, we want to expose addressing computations + explicitly. Since the lower bound must always be known in a high level + language statically, the language front end can do the translation + automatically. +* This fits more closely with what Java needs, ie what we need in the + short term. Java arrays are always zero based. + +If a two element list is too confusing, I would recommend an alternate +syntax of: + +type ::= '[' type ']' | '[' INT 'x' type ']'. + +For example: + [12 x int] + [12x int] + [ 12 x [ 4x int ]] + +Which is syntactically nicer, and more explicit. + +> Either of the following would be better: +> array [10, 40] of int + +I considered this approach for arrays in general (ie array of int/ array +of 12 int), but found that it made declarations WAY too long. Remember +that because of the nature of llvm, you get a lot of types strewn all over +the program, and using the 'typedef' like facility is not a wonderful +option, because then types aren't explicit anymore. + +I find this email interesting, because you contradict the previous email +you sent, where you recommend that we stick to C syntax.... + +-Chris + diff --git a/libclamav/c++/llvm/docs/HistoricalNotes/2001-02-06-TypeNotationDebateResp4.txt b/libclamav/c++/llvm/docs/HistoricalNotes/2001-02-06-TypeNotationDebateResp4.txt new file mode 100644 index 000000000..7b9032742 --- /dev/null +++ b/libclamav/c++/llvm/docs/HistoricalNotes/2001-02-06-TypeNotationDebateResp4.txt @@ -0,0 +1,89 @@ +> But in fact, if you read the entire answer carefully, he came to the same +> conclusion I do: that you have to go with familiar syntax over logical +> syntax because familiarity is such a strong force: +> "However, familiarity is a strong force. To compare, in English, we +live +> more or less happily with the absurd rules for "to be" (am, are, is, been, +> was, were, ...) and all attempts to simplify are treated with contempt or +> (preferably) humor. It be a curious world and it always beed." + +Although you have to remember that his situation was considerably +different than ours. He was in a position where he was designing a high +level language that had to be COMPATIBLE with C. Our language is such +that a new person would have to learn the new, different, syntax +anyways. Making them learn about the type system does not seem like much +of a stretch from learning the opcodes and how SSA form works, and how +everything ties together... + +> > Basically, my argument for this type construction system is that it is +> > VERY simple to use and understand (although it IS different than C, it is +> > very simple and straightforward, which C is NOT). In fact, I would assert +> > that most programmers TODAY do not understand pointers to member +> > functions, and have to look up an example when they have to write them. + +> Again, I don't disagree with this at all. But to some extent this +> particular problem is inherently difficult. Your syntax for the above +> example may be easier for you to read because this is the way you have been +> thinking about it. Honestly, I don't find it much easier than the C syntax. +> In either case, I would have to look up an example to write pointers to +> member functions. + +I would argue that because the lexical structure of the language is self +consistent, any person who spent a significant amount of time programming +in LLVM directly would understand how to do it without looking it up in a +manual. The reason this does not work for C is because you rarely have to +declare these pointers, and the syntax is inconsistent with the method +declaration and calling syntax. + +> But pointers to member functions are nowhere near as common as arrays. + +Very true. If you're implementing an object oriented language, however, +remember that you have to do all the pointer to member function stuff +yourself.... so everytime you invoke a virtual method one is involved +(instead of having C++ hide it for you behind "syntactic sugar"). + +> And the old array syntax: +> type [ int, int, ...] +> is just much more familiar and clear to people than anything new you +> introduce, no matter how logical it is. + +Erm... excuse me but how is this the "old array syntax"? If you are +arguing for consistency with C, you should be asking for 'type int []', +which is significantly different than the above (beside the above +introduces a new operator and duplicates information +needlessly). Basically what I am suggesting is exactly the above without +the fluff. So instead of: + + type [ int, int, ...] + +you use: + + type [ int ] + +> Introducing a new syntax that may +> make function pointers easier but makes arrays much more difficult seems +> very risky to me. + +This is not about function pointers. This is about consistency in the +type system, and consistency with the rest of the language. The point +above does not make arrays any more difficult to use, and makes the +structure of types much more obvious than the "c way". + +> > In my opinion, it is critically important to have clear and concise type +> > specifications, because types are going to be all over the programs. +> +> I absolutely agree. But the question is, what is more clear and concise? +> The syntax programmers are used to out of years of experience or a new +> syntax that they have never seen that has a more logical structure. I think +> the answer is the former. Sometimes, you have to give up a better idea +> because you can't overcome sociological barriers to it. Qwerty keyboards +> and Windows are two classic examples of bad technology that are difficult to +> root out. + +Very true, but you seem to be advocating a completely different Type +system than C has, in addition to it not offering the advantages of clear +structure that the system I recommended does... so you seem to not have a +problem with changing this, just with what I change it to. :) + +-Chris + diff --git a/libclamav/c++/llvm/docs/HistoricalNotes/2001-02-09-AdveComments.txt b/libclamav/c++/llvm/docs/HistoricalNotes/2001-02-09-AdveComments.txt new file mode 100644 index 000000000..5503233c1 --- /dev/null +++ b/libclamav/c++/llvm/docs/HistoricalNotes/2001-02-09-AdveComments.txt @@ -0,0 +1,120 @@ +Ok, here are my comments and suggestions about the LLVM instruction set. +We should discuss some now, but can discuss many of them later, when we +revisit synchronization, type inference, and other issues. +(We have discussed some of the comments already.) + + +o We should consider eliminating the type annotation in cases where it is + essentially obvious from the instruction type, e.g., in br, it is obvious + that the first arg. should be a bool and the other args should be labels: + + br bool , label , label + + I think your point was that making all types explicit improves clarity + and readability. I agree to some extent, but it also comes at the cost + of verbosity. And when the types are obvious from people's experience + (e.g., in the br instruction), it doesn't seem to help as much. + + +o On reflection, I really like your idea of having the two different switch + types (even though they encode implementation techniques rather than + semantics). It should simplify building the CFG and my guess is it could + enable some significant optimizations, though we should think about which. + + +o In the lookup-indirect form of the switch, is there a reason not to make + the val-type uint? Most HLL switch statements (including Java and C++) + require that anyway. And it would also make the val-type uniform + in the two forms of the switch. + + I did see the switch-on-bool examples and, while cute, we can just use + the branch instructions in that particular case. + + +o I agree with your comment that we don't need 'neg'. + + +o There's a trade-off with the cast instruction: + + it avoids having to define all the upcasts and downcasts that are + valid for the operands of each instruction (you probably have thought + of other benefits also) + - it could make the bytecode significantly larger because there could + be a lot of cast operations + + +o Making the second arg. to 'shl' a ubyte seems good enough to me. + 255 positions seems adequate for several generations of machines + and is more compact than uint. + + +o I still have some major concerns about including malloc and free in the + language (either as builtin functions or instructions). LLVM must be + able to represent code from many different languages. Languages such as + C, C++ Java and Fortran 90 would not be able to use our malloc anyway + because each of them will want to provide a library implementation of it. + + This gets even worse when code from different languages is linked + into a single executable (which is fairly common in large apps). + Having a single malloc would just not suffice, and instead would simply + complicate the picture further because it adds an extra variant in + addition to the one each language provides. + + Instead, providing a default library version of malloc and free + (and perhaps a malloc_gc with garbage collection instead of free) + would make a good implementation available to anyone who wants it. + + I don't recall all your arguments in favor so let's discuss this again, + and soon. + + +o 'alloca' on the other hand sounds like a good idea, and the + implementation seems fairly language-independent so it doesn't have the + problems with malloc listed above. + + +o About indirect call: + Your option #2 sounded good to me. I'm not sure I understand your + concern about an explicit 'icall' instruction? + + +o A pair of important synchronization instr'ns to think about: + load-linked + store-conditional + + +o Other classes of instructions that are valuable for pipeline performance: + conditional-move + predicated instructions + + +o I believe tail calls are relatively easy to identify; do you know why + .NET has a tailcall instruction? + + +o I agree that we need a static data space. Otherwise, emulating global + data gets unnecessarily complex. + + +o About explicit parallelism: + + We once talked about adding a symbolic thread-id field to each + instruction. (It could be optional so single-threaded codes are + not penalized.) This could map well to multi-threaded architectures + while providing easy ILP for single-threaded onces. But it is probably + too radical an idea to include in a base version of LLVM. Instead, it + could a great topic for a separate study. + + What is the semantics of the IA64 stop bit? + + + + +o And finally, another thought about the syntax for arrays :-) + + Although this syntax: + array of + is verbose, it will be used only in the human-readable assembly code so + size should not matter. I think we should consider it because I find it + to be the clearest syntax. It could even make arrays of function + pointers somewhat readable. + diff --git a/libclamav/c++/llvm/docs/HistoricalNotes/2001-02-09-AdveCommentsResponse.txt b/libclamav/c++/llvm/docs/HistoricalNotes/2001-02-09-AdveCommentsResponse.txt new file mode 100644 index 000000000..5c87330fb --- /dev/null +++ b/libclamav/c++/llvm/docs/HistoricalNotes/2001-02-09-AdveCommentsResponse.txt @@ -0,0 +1,245 @@ +From: Chris Lattner +To: "Vikram S. Adve" +Subject: Re: LLVM Feedback + +I've included your feedback in the /home/vadve/lattner/llvm/docs directory +so that it will live in CVS eventually with the rest of LLVM. I've +significantly updated the documentation to reflect the changes you +suggested, as specified below: + +> We should consider eliminating the type annotation in cases where it is +> essentially obvious from the instruction type: +> br bool , label , label +> I think your point was that making all types explicit improves clarity +> and readability. I agree to some extent, but it also comes at the +> cost of verbosity. And when the types are obvious from people's +> experience (e.g., in the br instruction), it doesn't seem to help as +> much. + +Very true. We should discuss this more, but my reasoning is more of a +consistency argument. There are VERY few instructions that can have all +of the types eliminated, and doing so when available unnecesarily makes +the language more difficult to handle. Especially when you see 'int +%this' and 'bool %that' all over the place, I think it would be +disorienting to see: + + br %predicate, %iftrue, %iffalse + +for branches. Even just typing that once gives me the creeps. ;) Like I +said, we should probably discuss this further in person... + +> On reflection, I really like your idea of having the two different +> switch types (even though they encode implementation techniques rather +> than semantics). It should simplify building the CFG and my guess is it +> could enable some significant optimizations, though we should think +> about which. + +Great. I added a note to the switch section commenting on how the VM +should just use the instruction type as a hint, and that the +implementation may choose altermate representations (such as predicated +branches). + +> In the lookup-indirect form of the switch, is there a reason not to +> make the val-type uint? + +No. This was something I was debating for a while, and didn't really feel +strongly about either way. It is common to switch on other types in HLL's +(for example signed int's are particually common), but in this case, all +that will be added is an additional 'cast' instruction. I removed that +from the spec. + +> I agree with your comment that we don't need 'neg' + +Removed. + +> There's a trade-off with the cast instruction: +> + it avoids having to define all the upcasts and downcasts that are +> valid for the operands of each instruction (you probably have +> thought of other benefits also) +> - it could make the bytecode significantly larger because there could +> be a lot of cast operations + + + You NEED casts to represent things like: + void foo(float); + ... + int x; + ... + foo(x); + in a language like C. Even in a Java like language, you need upcasts + and some way to implement dynamic downcasts. + + Not all forms of instructions take every type (for example you can't + shift by a floating point number of bits), thus SOME programs will need + implicit casts. + +To be efficient and to avoid your '-' point above, we just have to be +careful to specify that the instructions shall operate on all common +types, therefore casting should be relatively uncommon. For example all +of the arithmetic operations work on almost all data types. + +> Making the second arg. to 'shl' a ubyte seems good enough to me. +> 255 positions seems adequate for several generations of machines + +Okay, that comment is removed. + +> and is more compact than uint. + +No, it isn't. Remember that the bytecode encoding saves value slots into +the bytecode instructions themselves, not constant values. This is +another case where we may introduce more cast instructions (but we will +also reduce the number of opcode variants that must be supported by a +virtual machine). Because most shifts are by constant values, I don't +think that we'll have to cast many shifts. :) + +> I still have some major concerns about including malloc and free in the +> language (either as builtin functions or instructions). + +Agreed. How about this proposal: + +malloc/free are either built in functions or actual opcodes. They provide +all of the type safety that the document would indicate, blah blah +blah. :) + +Now, because of all of the excellent points that you raised, an +implementation may want to override the default malloc/free behavior of +the program. To do this, they simply implement a "malloc" and +"free" function. The virtual machine will then be defined to use the user +defined malloc/free function (which return/take void*'s, not type'd +pointers like the builtin function would) if one is available, otherwise +fall back on a system malloc/free. + +Does this sound like a good compromise? It would give us all of the +typesafety/elegance in the language while still allowing the user to do +all the cool stuff they want to... + +> 'alloca' on the other hand sounds like a good idea, and the +> implementation seems fairly language-independent so it doesn't have the +> problems with malloc listed above. + +Okay, once we get the above stuff figured out, I'll put it all in the +spec. + +> About indirect call: +> Your option #2 sounded good to me. I'm not sure I understand your +> concern about an explicit 'icall' instruction? + +I worry too much. :) The other alternative has been removed. 'icall' is +now up in the instruction list next to 'call'. + +> I believe tail calls are relatively easy to identify; do you know why +> .NET has a tailcall instruction? + +Although I am just guessing, I believe it probably has to do with the fact +that they want languages like Haskell and lisp to be efficiently runnable +on their VM. Of course this means that the VM MUST implement tail calls +'correctly', or else life will suck. :) I would put this into a future +feature bin, because it could be pretty handy... + +> A pair of important synchronization instr'ns to think about: +> load-linked +> store-conditional + +What is 'load-linked'? I think that (at least for now) I should add these +to the 'possible extensions' section, because they are not immediately +needed... + +> Other classes of instructions that are valuable for pipeline +> performance: +> conditional-move +> predicated instructions + +Conditional move is effectly a special case of a predicated +instruction... and I think that all predicated instructions can possibly +be implemented later in LLVM. It would significantly change things, and +it doesn't seem to be very necessary right now. It would seem to +complicate flow control analysis a LOT in the virtual machine. I would +tend to prefer that a predicated architecture like IA64 convert from a +"basic block" representation to a predicated rep as part of it's dynamic +complication phase. Also, if a basic block contains ONLY a move, then +that can be trivally translated into a conditional move... + +> I agree that we need a static data space. Otherwise, emulating global +> data gets unnecessarily complex. + +Definately. Also a later item though. :) + +> We once talked about adding a symbolic thread-id field to each +> .. +> Instead, it could a great topic for a separate study. + +Agreed. :) + +> What is the semantics of the IA64 stop bit? + +Basically, the IA64 writes instructions like this: +mov ... +add ... +sub ... +op xxx +op xxx +;; +mov ... +add ... +sub ... +op xxx +op xxx +;; + +Where the ;; delimits a group of instruction with no dependencies between +them, which can all be executed concurrently (to the limits of the +available functional units). The ;; gets translated into a bit set in one +of the opcodes. + +The advantages of this representation is that you don't have to do some +kind of 'thread id scheduling' pass by having to specify ahead of time how +many threads to use, and the representation doesn't have a per instruction +overhead... + +> And finally, another thought about the syntax for arrays :-) +> Although this syntax: +> array of +> is verbose, it will be used only in the human-readable assembly code so +> size should not matter. I think we should consider it because I find it +> to be the clearest syntax. It could even make arrays of function +> pointers somewhat readable. + +My only comment will be to give you an example of why this is a bad +idea. :) + +Here is an example of using the switch statement (with my recommended +syntax): + +switch uint %val, label %otherwise, + [%3 x {uint, label}] [ { uint %57, label %l1 }, + { uint %20, label %l2 }, + { uint %14, label %l3 } ] + +Here it is with the syntax you are proposing: + +switch uint %val, label %otherwise, + array %3 of {uint, label} + array of {uint, label} + { uint %57, label %l1 }, + { uint %20, label %l2 }, + { uint %14, label %l3 } + +Which is ambiguous and very verbose. It would be possible to specify +constants with [] brackets as in my syntax, which would look like this: + +switch uint %val, label %otherwise, + array %3 of {uint, label} [ { uint %57, label %l1 }, + { uint %20, label %l2 }, + { uint %14, label %l3 } ] + +But then the syntax is inconsistent between type definition and constant +definition (why do []'s enclose the constants but not the types??). + +Anyways, I'm sure that there is much debate still to be had over +this... :) + +-Chris + +http://www.nondot.org/~sabre/os/ +http://www.nondot.org/MagicStats/ +http://korbit.sourceforge.net/ + + diff --git a/libclamav/c++/llvm/docs/HistoricalNotes/2001-02-13-Reference-Memory.txt b/libclamav/c++/llvm/docs/HistoricalNotes/2001-02-13-Reference-Memory.txt new file mode 100644 index 000000000..2c7534d9d --- /dev/null +++ b/libclamav/c++/llvm/docs/HistoricalNotes/2001-02-13-Reference-Memory.txt @@ -0,0 +1,39 @@ +Date: Tue, 13 Feb 2001 13:29:52 -0600 (CST) +From: Chris Lattner +To: Vikram S. Adve +Subject: LLVM Concerns... + + +I've updated the documentation to include load store and allocation +instructions (please take a look and let me know if I'm on the right +track): + +file:/home/vadve/lattner/llvm/docs/LangRef.html#memoryops + +I have a couple of concerns I would like to bring up: + +1. Reference types + Right now, I've spec'd out the language to have a pointer type, which + works fine for lots of stuff... except that Java really has + references: constrained pointers that cannot be manipulated: added and + subtracted, moved, etc... Do we want to have a type like this? It + could be very nice for analysis (pointer always points to the start of + an object, etc...) and more closely matches Java semantics. The + pointer type would be kept for C++ like semantics. Through analysis, + C++ pointers could be promoted to references in the LLVM + representation. + +2. Our "implicit" memory references in assembly language: + After thinking about it, this model has two problems: + A. If you do pointer analysis and realize that two stores are + independent and can share the same memory source object, there is + no way to represent this in either the bytecode or assembly. + B. When parsing assembly/bytecode, we effectively have to do a full + SSA generation/PHI node insertion pass to build the dependencies + when we don't want the "pinned" representation. This is not + cool. + I'm tempted to make memory references explicit in both the assembly and + bytecode to get around this... what do you think? + +-Chris + diff --git a/libclamav/c++/llvm/docs/HistoricalNotes/2001-02-13-Reference-MemoryResponse.txt b/libclamav/c++/llvm/docs/HistoricalNotes/2001-02-13-Reference-MemoryResponse.txt new file mode 100644 index 000000000..505343378 --- /dev/null +++ b/libclamav/c++/llvm/docs/HistoricalNotes/2001-02-13-Reference-MemoryResponse.txt @@ -0,0 +1,47 @@ +Date: Tue, 13 Feb 2001 18:25:42 -0600 +From: Vikram S. Adve +To: Chris Lattner +Subject: RE: LLVM Concerns... + +> 1. Reference types +> Right now, I've spec'd out the language to have a pointer type, which +> works fine for lots of stuff... except that Java really has +> references: constrained pointers that cannot be manipulated: added and +> subtracted, moved, etc... Do we want to have a type like this? It +> could be very nice for analysis (pointer always points to the start of +> an object, etc...) and more closely matches Java semantics. The +> pointer type would be kept for C++ like semantics. Through analysis, +> C++ pointers could be promoted to references in the LLVM +> representation. + + +You're right, having references would be useful. Even for C++ the *static* +compiler could generate references instead of pointers with fairly +straightforward analysis. Let's include a reference type for now. But I'm +also really concerned that LLVM is becoming big and complex and (perhaps) +too high-level. After we get some initial performance results, we may have +a clearer idea of what our goals should be and we should revisit this +question then. + +> 2. Our "implicit" memory references in assembly language: +> After thinking about it, this model has two problems: +> A. If you do pointer analysis and realize that two stores are +> independent and can share the same memory source object, + +not sure what you meant by "share the same memory source object" + +> there is +> no way to represent this in either the bytecode or assembly. +> B. When parsing assembly/bytecode, we effectively have to do a full +> SSA generation/PHI node insertion pass to build the dependencies +> when we don't want the "pinned" representation. This is not +> cool. + +I understand the concern. But again, let's focus on the performance first +and then look at the language design issues. E.g., it would be good to know +how big the bytecode files are before expanding them further. I am pretty +keen to explore the implications of LLVM for mobile devices. Both bytecode +size and power consumption are important to consider there. + +--Vikram + diff --git a/libclamav/c++/llvm/docs/HistoricalNotes/2001-04-16-DynamicCompilation.txt b/libclamav/c++/llvm/docs/HistoricalNotes/2001-04-16-DynamicCompilation.txt new file mode 100644 index 000000000..5f7843ab5 --- /dev/null +++ b/libclamav/c++/llvm/docs/HistoricalNotes/2001-04-16-DynamicCompilation.txt @@ -0,0 +1,49 @@ +By Chris: + +LLVM has been designed with two primary goals in mind. First we strive to +enable the best possible division of labor between static and dynamic +compilers, and second, we need a flexible and powerful interface +between these two complementary stages of compilation. We feel that +providing a solution to these two goals will yield an excellent solution +to the performance problem faced by modern architectures and programming +languages. + +A key insight into current compiler and runtime systems is that a +compiler may fall in anywhere in a "continuum of compilation" to do its +job. On one side, scripting languages statically compile nothing and +dynamically compile (or equivalently, interpret) everything. On the far +other side, traditional static compilers process everything statically and +nothing dynamically. These approaches have typically been seen as a +tradeoff between performance and portability. On a deeper level, however, +there are two reasons that optimal system performance may be obtained by a +system somewhere in between these two extremes: Dynamic application +behavior and social constraints. + +From a technical perspective, pure static compilation cannot ever give +optimal performance in all cases, because applications have varying dynamic +behavior that the static compiler cannot take into consideration. Even +compilers that support profile guided optimization generate poor code in +the real world, because using such optimization tunes that application +to one particular usage pattern, whereas real programs (as opposed to +benchmarks) often have several different usage patterns. + +On a social level, static compilation is a very shortsighted solution to +the performance problem. Instruction set architectures (ISAs) continuously +evolve, and each implementation of an ISA (a processor) must choose a set +of tradeoffs that make sense in the market context that it is designed for. +With every new processor introduced, the vendor faces two fundamental +problems: First, there is a lag time between when a processor is introduced +to when compilers generate quality code for the architecture. Secondly, +even when compilers catch up to the new architecture there is often a large +body of legacy code that was compiled for previous generations and will +not or can not be upgraded. Thus a large percentage of code running on a +processor may be compiled quite sub-optimally for the current +characteristics of the dynamic execution environment. + +For these reasons, LLVM has been designed from the beginning as a long-term +solution to these problems. Its design allows the large body of platform +independent, static, program optimizations currently in compilers to be +reused unchanged in their current form. It also provides important static +type information to enable powerful dynamic and link time optimizations +to be performed quickly and efficiently. This combination enables an +increase in effective system performance for real world environments. diff --git a/libclamav/c++/llvm/docs/HistoricalNotes/2001-05-18-ExceptionHandling.txt b/libclamav/c++/llvm/docs/HistoricalNotes/2001-05-18-ExceptionHandling.txt new file mode 100644 index 000000000..b546301d3 --- /dev/null +++ b/libclamav/c++/llvm/docs/HistoricalNotes/2001-05-18-ExceptionHandling.txt @@ -0,0 +1,202 @@ +Meeting notes: Implementation idea: Exception Handling in C++/Java + +The 5/18/01 meeting discussed ideas for implementing exceptions in LLVM. +We decided that the best solution requires a set of library calls provided by +the VM, as well as an extension to the LLVM function invocation syntax. + +The LLVM function invocation instruction previously looks like this (ignoring +types): + + call func(arg1, arg2, arg3) + +The extension discussed today adds an optional "with" clause that +associates a label with the call site. The new syntax looks like this: + + call func(arg1, arg2, arg3) with funcCleanup + +This funcHandler always stays tightly associated with the call site (being +encoded directly into the call opcode itself), and should be used whenever +there is cleanup work that needs to be done for the current function if +an exception is thrown by func (or if we are in a try block). + +To support this, the VM/Runtime provide the following simple library +functions (all syntax in this document is very abstract): + +typedef struct { something } %frame; + The VM must export a "frame type", that is an opaque structure used to + implement different types of stack walking that may be used by various + language runtime libraries. We imagine that it would be typical to + represent a frame with a PC and frame pointer pair, although that is not + required. + +%frame getStackCurrentFrame(); + Get a frame object for the current function. Note that if the current + function was inlined into its caller, the "current" frame will belong to + the "caller". + +bool isFirstFrame(%frame f); + Returns true if the specified frame is the top level (first activated) frame + for this thread. For the main thread, this corresponds to the main() + function, for a spawned thread, it corresponds to the thread function. + +%frame getNextFrame(%frame f); + Return the previous frame on the stack. This function is undefined if f + satisfies the predicate isFirstFrame(f). + +Label *getFrameLabel(%frame f); + If a label was associated with f (as discussed below), this function returns + it. Otherwise, it returns a null pointer. + +doNonLocalBranch(Label *L); + At this point, it is not clear whether this should be a function or + intrinsic. It should probably be an intrinsic in LLVM, but we'll deal with + this issue later. + + +Here is a motivating example that illustrates how these facilities could be +used to implement the C++ exception model: + +void TestFunction(...) { + A a; B b; + foo(); // Any function call may throw + bar(); + C c; + + try { + D d; + baz(); + } catch (int) { + ...int Stuff... + // execution continues after the try block: the exception is consumed + } catch (double) { + ...double stuff... + throw; // Exception is propogated + } +} + +This function would compile to approximately the following code (heavy +pseudo code follows): + +Func: + %a = alloca A + A::A(%a) // These ctors & dtors could throw, but we ignore this + %b = alloca B // minor detail for this example + B::B(%b) + + call foo() with fooCleanup // An exception in foo is propogated to fooCleanup + call bar() with barCleanup // An exception in bar is propogated to barCleanup + + %c = alloca C + C::C(c) + %d = alloca D + D::D(d) + call baz() with bazCleanup // An exception in baz is propogated to bazCleanup + d->~D(); +EndTry: // This label corresponds to the end of the try block + c->~C() // These could also throw, these are also ignored + b->~B() + a->~A() + return + +Note that this is a very straight forward and literal translation: exactly +what we want for zero cost (when unused) exception handling. Especially on +platforms with many registers (ie, the IA64) setjmp/longjmp style exception +handling is *very* impractical. Also, the "with" clauses describe the +control flow paths explicitly so that analysis is not adversly effected. + +The foo/barCleanup labels are implemented as: + +TryCleanup: // Executed if an exception escapes the try block + c->~C() +barCleanup: // Executed if an exception escapes from bar() + // fall through +fooCleanup: // Executed if an exception escapes from foo() + b->~B() + a->~A() + Exception *E = getThreadLocalException() + call throw(E) // Implemented by the C++ runtime, described below + +Which does the work one would expect. getThreadLocalException is a function +implemented by the C++ support library. It returns the current exception +object for the current thread. Note that we do not attempt to recycle the +shutdown code from before, because performance of the mainline code is +critically important. Also, obviously fooCleanup and barCleanup may be +merged and one of them eliminated. This just shows how the code generator +would most likely emit code. + +The bazCleanup label is more interesting. Because the exception may be caught +by the try block, we must dispatch to its handler... but it does not exist +on the call stack (it does not have a VM Call->Label mapping installed), so +we must dispatch statically with a goto. The bazHandler thus appears as: + +bazHandler: + d->~D(); // destruct D as it goes out of scope when entering catch clauses + goto TryHandler + +In general, TryHandler is not the same as bazHandler, because multiple +function calls could be made from the try block. In this case, trivial +optimization could merge the two basic blocks. TryHandler is the code +that actually determines the type of exception, based on the Exception object +itself. For this discussion, assume that the exception object contains *at +least*: + +1. A pointer to the RTTI info for the contained object +2. A pointer to the dtor for the contained object +3. The contained object itself + +Note that it is necessary to maintain #1 & #2 in the exception object itself +because objects without virtual function tables may be thrown (as in this +example). Assuming this, TryHandler would look something like this: + +TryHandler: + Exception *E = getThreadLocalException(); + switch (E->RTTIType) { + case IntRTTIInfo: + ...int Stuff... // The action to perform from the catch block + break; + case DoubleRTTIInfo: + ...double Stuff... // The action to perform from the catch block + goto TryCleanup // This catch block rethrows the exception + break; // Redundant, eliminated by the optimizer + default: + goto TryCleanup // Exception not caught, rethrow + } + + // Exception was consumed + if (E->dtor) + E->dtor(E->object) // Invoke the dtor on the object if it exists + goto EndTry // Continue mainline code... + +And that is all there is to it. + +The throw(E) function would then be implemented like this (which may be +inlined into the caller through standard optimization): + +function throw(Exception *E) { + // Get the start of the stack trace... + %frame %f = call getStackCurrentFrame() + + // Get the label information that corresponds to it + label * %L = call getFrameLabel(%f) + while (%L == 0 && !isFirstFrame(%f)) { + // Loop until a cleanup handler is found + %f = call getNextFrame(%f) + %L = call getFrameLabel(%f) + } + + if (%L != 0) { + call setThreadLocalException(E) // Allow handlers access to this... + call doNonLocalBranch(%L) + } + // No handler found! + call BlowUp() // Ends up calling the terminate() method in use +} + +That's a brief rundown of how C++ exception handling could be implemented in +llvm. Java would be very similar, except it only uses destructors to unlock +synchronized blocks, not to destroy data. Also, it uses two stack walks: a +nondestructive walk that builds a stack trace, then a destructive walk that +unwinds the stack as shown here. + +It would be trivial to get exception interoperability between C++ and Java. + diff --git a/libclamav/c++/llvm/docs/HistoricalNotes/2001-05-19-ExceptionResponse.txt b/libclamav/c++/llvm/docs/HistoricalNotes/2001-05-19-ExceptionResponse.txt new file mode 100644 index 000000000..3375365f5 --- /dev/null +++ b/libclamav/c++/llvm/docs/HistoricalNotes/2001-05-19-ExceptionResponse.txt @@ -0,0 +1,45 @@ +Date: Sat, 19 May 2001 19:09:13 -0500 (CDT) +From: Chris Lattner +To: Vikram S. Adve +Subject: RE: Meeting writeup + +> I read it through and it looks great! + +Thanks! + +> The finally clause in Java may need more thought. The code for this clause +> is like a subroutine because it needs to be entered from many points (end of +> try block and beginning of each catch block), and then needs to *return to +> the place from where the code was entered*. That's why JVM has the +> jsr/jsr_w instruction. + +Hrm... I guess that is an implementation decision. It can either be +modelled as a subroutine (as java bytecodes do), which is really +gross... or it can be modelled as code duplication (emitted once inline, +then once in the exception path). Because this could, at worst, +slightly less than double the amount of code in a function (it is +bounded) I don't think this is a big deal. One of the really nice things +about the LLVM representation is that it still allows for runtime code +generation for exception paths (exceptions paths are not compiled until +needed). Obviously a static compiler couldn't do this though. :) + +In this case, only one copy of the code would be compiled... until the +other one is needed on demand. Also this strategy fits with the "zero +cost" exception model... the standard case is not burdened with extra +branches or "call"s. + +> I suppose you could save the return address in a particular register +> (specific to this finally block), jump to the finally block, and then at the +> end of the finally block, jump back indirectly through this register. It +> will complicate building the CFG but I suppose that can be handled. It is +> also unsafe in terms of checking where control returns (which is I suppose +> why the JVM doesn't use this). + +I think that a code duplication method would be cleaner, and would avoid +the caveats that you mention. Also, it does not slow down the normal case +with an indirect branch... + +Like everything, we can probably defer a final decision until later. :) + +-Chris + diff --git a/libclamav/c++/llvm/docs/HistoricalNotes/2001-06-01-GCCOptimizations.txt b/libclamav/c++/llvm/docs/HistoricalNotes/2001-06-01-GCCOptimizations.txt new file mode 100644 index 000000000..97af16a2d --- /dev/null +++ b/libclamav/c++/llvm/docs/HistoricalNotes/2001-06-01-GCCOptimizations.txt @@ -0,0 +1,63 @@ +Date: Fri, 1 Jun 2001 16:38:17 -0500 (CDT) +From: Chris Lattner +To: Vikram S. Adve +Subject: Interesting: GCC passes + + +Take a look at this document (which describes the order of optimizations +that GCC performs): + +http://gcc.gnu.org/onlinedocs/gcc_17.html + +The rundown is that after RTL generation, the following happens: + +1 . [t] jump optimization (jumps to jumps, etc) +2 . [t] Delete unreachable code +3 . Compute live ranges for CSE +4 . [t] Jump threading (jumps to jumps with identical or inverse conditions) +5 . [t] CSE +6 . *** Conversion to SSA +7 . [t] SSA Based DCE +8 . *** Conversion to LLVM +9 . UnSSA +10. GCSE +11. LICM +12. Strength Reduction +13. Loop unrolling +14. [t] CSE +15. [t] DCE +16. Instruction combination, register movement, scheduling... etc. + +I've marked optimizations with a [t] to indicate things that I believe to +be relatively trivial to implement in LLVM itself. The time consuming +things to reimplement would be SSA based PRE, Strength reduction & loop +unrolling... these would be the major things we would miss out on if we +did LLVM creation from tree code [inlining and other high level +optimizations are done on the tree representation]. + +Given the lack of "strong" optimizations that would take a long time to +reimplement, I am leaning a bit more towards creating LLVM from the tree +code. Especially given that SGI has GPL'd their compiler, including many +SSA based optimizations that could be adapted (besides the fact that their +code looks MUCH nicer than GCC :) + +Even if we choose to do LLVM code emission from RTL, we will almost +certainly want to move LLVM emission from step 8 down until at least CSE +has been rerun... which causes me to wonder if the SSA generation code +will still work (due to global variable dependencies and stuff). I assume +that it can be made to work, but might be a little more involved than we +would like. + +I'm continuing to look at the Tree -> RTL code. It is pretty gross +because they do some of the translation a statement at a time, and some +of it a function at a time... I'm not quite clear why and how the +distinction is drawn, but it does not appear that there is a wonderful +place to attach extra info. + +Anyways, I'm proceeding with the RTL -> LLVM conversion phase for now. We +can talk about this more on Monday. + +Wouldn't it be nice if there were a obvious decision to be made? :) + +-Chris + diff --git a/libclamav/c++/llvm/docs/HistoricalNotes/2001-06-01-GCCOptimizations2.txt b/libclamav/c++/llvm/docs/HistoricalNotes/2001-06-01-GCCOptimizations2.txt new file mode 100644 index 000000000..6c9e0971a --- /dev/null +++ b/libclamav/c++/llvm/docs/HistoricalNotes/2001-06-01-GCCOptimizations2.txt @@ -0,0 +1,71 @@ +Date: Fri, 1 Jun 2001 17:08:44 -0500 (CDT) +From: Chris Lattner +To: Vikram S. Adve +Subject: RE: Interesting: GCC passes + +> That is very interesting. I agree that some of these could be done on LLVM +> at link-time, but it is the extra time required that concerns me. Link-time +> optimization is severely time-constrained. + +If we were to reimplement any of these optimizations, I assume that we +could do them a translation unit at a time, just as GCC does now. This +would lead to a pipeline like this: + +Static optimizations, xlation unit at a time: +.c --GCC--> .llvm --llvmopt--> .llvm + +Link time optimizations: +.llvm --llvm-ld--> .llvm --llvm-link-opt--> .llvm + +Of course, many optimizations could be shared between llvmopt and +llvm-link-opt, but the wouldn't need to be shared... Thus compile time +could be faster, because we are using a "smarter" IR (SSA based). + +> BTW, about SGI, "borrowing" SSA-based optimizations from one compiler and +> putting it into another is not necessarily easier than re-doing it. +> Optimization code is usually heavily tied in to the specific IR they use. + +Understood. The only reason that I brought this up is because SGI's IR is +more similar to LLVM than it is different in many respects (SSA based, +relatively low level, etc), and could be easily adapted. Also their +optimizations are written in C++ and are actually somewhat +structured... of course it would be no walk in the park, but it would be +much less time consuming to adapt, say, SSA-PRE than to rewrite it. + +> But your larger point is valid that adding SSA based optimizations is +> feasible and should be fun. (Again, link time cost is the issue.) + +Assuming linktime cost wasn't an issue, the question is: +Does using GCC's backend buy us anything? + +> It also occurs to me that GCC is probably doing quite a bit of back-end +> optimization (step 16 in your list). Do you have a breakdown of that? + +Not really. The irritating part of GCC is that it mixes it all up and +doesn't have a clean seperation of concerns. A lot of the "back end +optimization" happens right along with other data optimizations (ie, CSE +of machine specific things). + +As far as REAL back end optimizations go, it looks something like this: + +1. Instruction combination: try to make CISCy instructions, if available +2. Register movement: try to get registers in the right places for the +architecture to avoid register to register moves. For example, try to get +the first argument of a function to naturally land in %o0 for sparc. +3. Instruction scheduling: 'nuff said :) +4. Register class preferencing: ?? +5. Local register allocation +6. global register allocation +7. Spilling +8. Local regalloc +9. Jump optimization +10. Delay slot scheduling +11. Branch shorting for CISC machines +12. Instruction selection & peephole optimization +13. Debug info output + +But none of this would be usable for LLVM anyways, unless we were using +GCC as a static compiler. + +-Chris + diff --git a/libclamav/c++/llvm/docs/HistoricalNotes/2001-06-20-.NET-Differences.txt b/libclamav/c++/llvm/docs/HistoricalNotes/2001-06-20-.NET-Differences.txt new file mode 100644 index 000000000..1bc2eae74 --- /dev/null +++ b/libclamav/c++/llvm/docs/HistoricalNotes/2001-06-20-.NET-Differences.txt @@ -0,0 +1,30 @@ +Date: Wed, 20 Jun 2001 12:32:22 -0500 +From: Vikram Adve +To: Chris Lattner +Subject: .NET vs. our VM + +One significant difference between .NET CLR and our VM is that the CLR +includes full information about classes and inheritance. In fact, I just +sat through the paper on adding templates to .NET CLR, and the speaker +indicated that the goal seems to be to do simple static compilation (very +little lowering or optimization). Also, the templates implementation in CLR +"relies on dynamic class loading and JIT compilation". + +This is an important difference because I think there are some significant +advantages to have a much lower level VM layer, and do significant static +analysis and optimization. + +I also talked to the lead guy for KAI's C++ compiler (Arch Robison) and he +said that SGI and other commercial compilers have included options to export +their *IR* next to the object code (i.e., .il files) and use them for +link-time code generation. In fact, he said that the .o file was nearly +empty and was entirely generated from the .il at link-time. But he agreed +that this limited the link-time interprocedural optimization to modules +compiled by the same compiler, whereas our approach allows us to link and +optimize modules from multiple different compilers. (Also, of course, they +don't do anything for runtime optimization). + +All issues to bring up in Related Work. + +--Vikram + diff --git a/libclamav/c++/llvm/docs/HistoricalNotes/2001-07-06-LoweringIRForCodeGen.txt b/libclamav/c++/llvm/docs/HistoricalNotes/2001-07-06-LoweringIRForCodeGen.txt new file mode 100644 index 000000000..3e10416fe --- /dev/null +++ b/libclamav/c++/llvm/docs/HistoricalNotes/2001-07-06-LoweringIRForCodeGen.txt @@ -0,0 +1,31 @@ +Date: Fri, 6 Jul 2001 16:56:56 -0500 +From: Vikram S. Adve +To: Chris Lattner +Subject: lowering the IR + +BTW, I do think that we should consider lowering the IR as you said. I +didn't get time to raise it today, but it comes up with the SPARC +move-conditional instruction. I don't think we want to put that in the core +VM -- it is a little too specialized. But without a corresponding +conditional move instruction in the VM, it is pretty difficult to maintain a +close mapping between VM and machine code. Other architectures may have +other such instructions. + +What I was going to suggest was that for a particular processor, we define +additional VM instructions that match some of the unusual opcodes on the +processor but have VM semantics otherwise, i.e., all operands are in SSA +form and typed. This means that we can re-generate core VM code from the +more specialized code any time we want (so that portability is not lost). + +Typically, a static compiler like gcc would generate just the core VM, which +is relatively portable. Anyone (an offline tool, the linker, etc., or even +the static compiler itself if it chooses) can transform that into more +specialized target-specific VM code for a particular architecture. If the +linker does it, it can do it after all machine-independent optimizations. +This would be the most convenient, but not necessary. + +The main benefit of lowering will be that we will be able to retain a close +mapping between VM and machine code. + +--Vikram + diff --git a/libclamav/c++/llvm/docs/HistoricalNotes/2001-09-18-OptimizeExceptions.txt b/libclamav/c++/llvm/docs/HistoricalNotes/2001-09-18-OptimizeExceptions.txt new file mode 100644 index 000000000..937908101 --- /dev/null +++ b/libclamav/c++/llvm/docs/HistoricalNotes/2001-09-18-OptimizeExceptions.txt @@ -0,0 +1,56 @@ +Date: Tue, 18 Sep 2001 00:38:37 -0500 (CDT) +From: Chris Lattner +To: Vikram S. Adve +Subject: Idea for a simple, useful link time optimization + + +In C++ programs, exceptions suck, and here's why: + +1. In virtually all function calls, you must assume that the function + throws an exception, unless it is defined as 'nothrow'. This means + that every function call has to have code to invoke dtors on objects + locally if one is thrown by the function. Most functions don't throw + exceptions, so this code is dead [with all the bad effects of dead + code, including icache pollution]. +2. Declaring a function nothrow causes catch blocks to be added to every + call that isnot provably nothrow. This makes them very slow. +3. Extra extraneous exception edges reduce the opportunity for code + motion. +4. EH is typically implemented with large lookup tables. Ours is going to + be much smaller (than the "standard" way of doing it) to start with, + but eliminating it entirely would be nice. :) +5. It is physically impossible to correctly put (accurate, correct) + exception specifications on generic, templated code. But it is trivial + to analyze instantiations of said code. +6. Most large C++ programs throw few exceptions. Most well designed + programs only throw exceptions in specific planned portions of the + code. + +Given our _planned_ model of handling exceptions, all of this would be +pretty trivial to eliminate through some pretty simplistic interprocedural +analysis. The DCE factor alone could probably be pretty significant. The +extra code motion opportunities could also be exploited though... + +Additionally, this optimization can be implemented in a straight forward +conservative manner, allowing libraries to be optimized or individual +files even (if there are leaf functions visible in the translation unit +that are called). + +I think it's a reasonable optimization that hasn't really been addressed +(because assembly is way too low level for this), and could have decent +payoffs... without being a overly complex optimization. + +After I wrote all of that, I found this page that is talking about +basically the same thing I just wrote, except that it is translation unit +at a time, tree based approach: +http://www.ocston.org/~jls/ehopt.html + +but is very useful from "expected gain" and references perspective. Note +that their compiler is apparently unable to inline functions that use +exceptions, so there numbers are pretty worthless... also our results +would (hopefully) be better because it's interprocedural... + +What do you think? + +-Chris + diff --git a/libclamav/c++/llvm/docs/HistoricalNotes/2002-05-12-InstListChange.txt b/libclamav/c++/llvm/docs/HistoricalNotes/2002-05-12-InstListChange.txt new file mode 100644 index 000000000..004edb068 --- /dev/null +++ b/libclamav/c++/llvm/docs/HistoricalNotes/2002-05-12-InstListChange.txt @@ -0,0 +1,55 @@ +Date: Sun, 12 May 2002 17:12:53 -0500 (CDT) +From: Chris Lattner +To: "Vikram S. Adve" +Subject: LLVM change + +There is a fairly fundemental change that I would like to make to the LLVM +infrastructure, but I'd like to know if you see any drawbacks that I +don't... + +Basically right now at the basic block level, each basic block contains an +instruction list (returned by getInstList()) that is a ValueHolder of +instructions. To iterate over instructions, we must actually iterate over +the instlist, and access the instructions through the instlist. + +To add or remove an instruction from a basic block, we need to get an +iterator to an instruction, which, given just an Instruction*, requires a +linear search of the basic block the instruction is contained in... just +to insert an instruction before another instruction, or to delete an +instruction! This complicates algorithms that should be very simple (like +simple constant propogation), because they aren't actually sparse anymore, +they have to traverse basic blocks to remove constant propogated +instructions. + +Additionally, adding or removing instructions to a basic block +_invalidates all iterators_ pointing into that block, which is really +irritating. + +To fix these problems (and others), I would like to make the ordering of +the instructions be represented with a doubly linked list in the +instructions themselves, instead of an external data structure. This is +how many other representations do it, and frankly I can't remember why I +originally implemented it the way I did. + +Long term, all of the code that depends on the nasty features in the +instruction list (which can be found by grep'ing for getInstList()) will +be changed to do nice local transformations. In the short term, I'll +change the representation, but preserve the interface (including +getInstList()) so that all of the code doesn't have to change. + +Iteration over the instructions in a basic block remains the simple: +for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ++I) ... + +But we will also support: +for (Instruction *I = BB->front(); I; I = I->getNext()) ... + +After converting instructions over, I'll convert basic blocks and +functions to have a similar interface. + +The only negative aspect of this change that I see is that it increases +the amount of memory consumed by one pointer per instruction. Given the +benefits, I think this is a very reasonable tradeoff. + +What do you think? + +-Chris diff --git a/libclamav/c++/llvm/docs/HistoricalNotes/2002-06-25-MegaPatchInfo.txt b/libclamav/c++/llvm/docs/HistoricalNotes/2002-06-25-MegaPatchInfo.txt new file mode 100644 index 000000000..2ca46117c --- /dev/null +++ b/libclamav/c++/llvm/docs/HistoricalNotes/2002-06-25-MegaPatchInfo.txt @@ -0,0 +1,72 @@ +Changes: +* Change the casting code to be const correct. Now, doing this is invalid: + const Value *V = ...; + Instruction *I = dyn_cast(V); + instead, the second line should be: + const Instruction *I = dyn_cast(V); + +* Change the casting code to allow casting a reference value thus: + const Value &V = ...; + Instruction &I = cast(V); + + dyn_cast does not work with references, because it must return a null pointer + on failure. + +* Fundamentally change how instructions and other values are represented. + Before, every llvm container was an instance of the ValueHolder template, + instantiated for each container type. This ValueHolder was effectively a + wrapper around a vector of pointers to the sub-objects. + + Now, instead of having a vector to pointers of objects, the objects are + maintained in a doubly linked list of values (ie each Instruction now has + Next & Previous fields). The containers are now instances of ilist (intrusive + linked list class), which use the next and previous fields to chain them + together. The advantage of this implementation is that iterators can be + formed directly from pointers to the LLVM value, and invalidation is much + easier to handle. + +* As part of the above change, dereferencing an iterator (for example: + BasicBlock::iterator) now produces a reference to the underlying type (same + example: Instruction&) instead of a pointer to the underlying object. This + makes it much easier to write nested loops that iterator over things, changing + this: + + for (Function::iterator BI = Func->begin(); BI != Func->end(); ++BI) + for (BasicBlock::iterator II = (*BI)->begin(); II != (*BI)->end(); ++II) + (*II)->dump(); + + into: + + for (Function::iterator BI = Func->begin(); BI != Func->end(); ++BI) + for (BasicBlock::iterator II = BI->begin(); II != BI->end(); ++II) + II->dump(); + + which is much more natural and what users expect. + +* Simplification of #include's: Before, it was necessary for a .cpp file to + include every .h file that it used. Now things are batched a little bit more + to make it easier to use. Specifically, the include graph now includes these + edges: + Module.h -> Function.h, GlobalVariable.h + Function.h -> BasicBlock.h, Argument.h + BasicBlock.h -> Instruction.h + + Which means that #including Function.h is usually sufficient for getting the + lower level #includes. + +* Printing out a Value* has now changed: Printing a Value* will soon print out + the address of the value instead of the contents of the Value. To print out + the contents, you must convert it to a reference with (for example) + 'cout << *I' instead of 'cout << I;'. This conversion is not yet complete, + but will be eventually. In the mean time, both forms print out the contents. + +* References are used much more throughout the code base. In general, if a + pointer is known to never be null, it is passed in as a reference instead of a + pointer. For example, the instruction visitor class uses references instead + of pointers, and that Pass subclasses now all receive references to Values + instead of pointers, because they may never be null. + +* The Function class now has helper functions for accessing the Arguments list. + Instead of having to go through getArgumentList for simple things like + iterator over the arguments, now the a*() methods can be used to access them. + diff --git a/libclamav/c++/llvm/docs/HistoricalNotes/2003-01-23-CygwinNotes.txt b/libclamav/c++/llvm/docs/HistoricalNotes/2003-01-23-CygwinNotes.txt new file mode 100644 index 000000000..fbe811d62 --- /dev/null +++ b/libclamav/c++/llvm/docs/HistoricalNotes/2003-01-23-CygwinNotes.txt @@ -0,0 +1,28 @@ +Date: Mon, 20 Jan 2003 00:00:28 -0600 +From: Brian R. Gaeke +Subject: windows vs. llvm + +If you're interested, here are some of the major problems compiling LLVM +under Cygwin and/or Mingw. + +1. Cygwin doesn't have or , so all the INT*_MAX + symbols and standard int*_t types are off in limbo somewhere. Mingw has + , but Cygwin doesn't like it. + +2. Mingw doesn't have (because Windows doesn't have it.) + +3. SA_SIGINFO and friends are not around; only signal() seems to work. + +4. Relink, aka ld -r, doesn't work (probably an ld bug); you need + DONT_BUILD_RELINKED. This breaks all the tools makefiles; you just need to + change them to have .a's. + +5. There isn't a . + +6. There isn't a mallinfo() (or, at least, it's documented, but it doesn't seem + to link). + +7. The version of Bison that cygwin (and newer Linux versions) comes with + does not like = signs in rules. Burg's gram.yc source file uses them. I think + you can just take them out. + diff --git a/libclamav/c++/llvm/docs/HistoricalNotes/2003-06-25-Reoptimizer1.txt b/libclamav/c++/llvm/docs/HistoricalNotes/2003-06-25-Reoptimizer1.txt new file mode 100644 index 000000000..a74578463 --- /dev/null +++ b/libclamav/c++/llvm/docs/HistoricalNotes/2003-06-25-Reoptimizer1.txt @@ -0,0 +1,137 @@ +Wed Jun 25 15:13:51 CDT 2003 + +First-level instrumentation +--------------------------- + +We use opt to do Bytecode-to-bytecode instrumentation. Look at +back-edges and insert llvm_first_trigger() function call which takes +no arguments and no return value. This instrumentation is designed to +be easy to remove, for instance by writing a NOP over the function +call instruction. + +Keep count of every call to llvm_first_trigger(), and maintain +counters in a map indexed by return address. If the trigger count +exceeds a threshold, we identify a hot loop and perform second-level +instrumentation on the hot loop region (the instructions between the +target of the back-edge and the branch that causes the back-edge). We +do not move code across basic-block boundaries. + + +Second-level instrumentation +--------------------------- + +We remove the first-level instrumentation by overwriting the CALL to +llvm_first_trigger() with a NOP. + +The reoptimizer maintains a map between machine-code basic blocks and +LLVM BasicBlock*s. We only keep track of paths that start at the +first machine-code basic block of the hot loop region. + +How do we keep track of which edges to instrument, and which edges are +exits from the hot region? 3 step process. + +1) Do a DFS from the first machine-code basic block of the hot loop +region and mark reachable edges. + +2) Do a DFS from the last machine-code basic block of the hot loop +region IGNORING back edges, and mark the edges which are reachable in +1) and also in 2) (i.e., must be reachable from both the start BB and +the end BB of the hot region). + +3) Mark BBs which end in edges that exit the hot region; we need to +instrument these differently. + +Assume that there is 1 free register. On SPARC we use %g1, which LLC +has agreed not to use. Shift a 1 into it at the beginning. At every +edge which corresponds to a conditional branch, we shift 0 for not +taken and 1 for taken into a register. This uniquely numbers the paths +through the hot region. Silently fail if we need more than 64 bits. + +At the end BB we call countPath and increment the counter based on %g1 +and the return address of the countPath call. We keep track of the +number of iterations and the number of paths. We only run this +version 30 or 40 times. + +Find the BBs that total 90% or more of execution, and aggregate them +together to form our trace. But we do not allow more than 5 paths; if +we have more than 5 we take the ones that are executed the most. We +verify our assumption that we picked a hot back-edge in first-level +instrumentation, by making sure that the number of times we took an +exit edge from the hot trace is less than 10% of the number of +iterations. + +LLC has been taught to recognize llvm_first_trigger() calls and NOT +generate saves and restores of caller-saved registers around these +calls. + + +Phase behavior +-------------- + +We turn off llvm_first_trigger() calls with NOPs, but this would hide +phase behavior from us (when some funcs/traces stop being hot and +others become hot.) + +We have a SIGALRM timer that counts time for us. Every time we get a +SIGALRM we look at our priority queue of locations where we have +removed llvm_first_trigger() calls. Each location is inserted along +with a time when we will next turn instrumentation back on for that +call site. If the time has arrived for a particular call site, we pop +that off the prio. queue and turn instrumentation back on for that +call site. + + +Generating traces +----------------- + +When we finally generate an optimized trace we first copy the code +into the trace cache. This leaves us with 3 copies of the code: the +original code, the instrumented code, and the optimized trace. The +optimized trace does not have instrumentation. The original code and +the instrumented code are modified to have a branch to the trace +cache, where the optimized traces are kept. + +We copy the code from the original to the instrumentation version +by tracing the LLVM-to-Machine code basic block map and then copying +each machine code basic block we think is in the hot region into the +trace cache. Then we instrument that code. The process is similar for +generating the final optimized trace; we copy the same basic blocks +because we might need to put in fixup code for exit BBs. + +LLVM basic blocks are not typically used in the Reoptimizer except +for the mapping information. + +We are restricted to using single instructions to branch between the +original code, trace, and instrumented code. So we have to keep the +code copies in memory near the original code (they can't be far enough +away that a single pc-relative branch would not work.) Malloc() or +data region space is too far away. this impacts the design of the +trace cache. + +We use a dummy function that is full of a bunch of for loops which we +overwrite with trace-cache code. The trace manager keeps track of +whether or not we have enough space in the trace cache, etc. + +The trace insertion routine takes an original start address, a vector +of machine instructions representing the trace, index of branches and +their corresponding absolute targets, and index of calls and their +corresponding absolute targets. + +The trace insertion routine is responsible for inserting branches from +the beginning of the original code to the beginning of the optimized +trace. This is because at some point the trace cache may run out of +space and it may have to evict a trace, at which point the branch to +the trace would also have to be removed. It uses a round-robin +replacement policy; we have found that this is almost as good as LRU +and better than random (especially because of problems fitting the new +trace in.) + +We cannot deal with discontiguous trace cache areas. The trace cache +is supposed to be cache-line-aligned, but it is not page-aligned. + +We generate instrumentation traces and optimized traces into separate +trace caches. We keep the instrumented code around because you don't +want to delete a trace when you still might have to return to it +(i.e., return from a llvm_first_trigger() or countPath() call.) + + diff --git a/libclamav/c++/llvm/docs/HistoricalNotes/2003-06-26-Reoptimizer2.txt b/libclamav/c++/llvm/docs/HistoricalNotes/2003-06-26-Reoptimizer2.txt new file mode 100644 index 000000000..ec4b93fea --- /dev/null +++ b/libclamav/c++/llvm/docs/HistoricalNotes/2003-06-26-Reoptimizer2.txt @@ -0,0 +1,110 @@ +Thu Jun 26 14:43:04 CDT 2003 + +Information about BinInterface +------------------------------ + +Take in a set of instructions with some particular register +allocation. It allows you to add, modify, or delete some instructions, +in SSA form (kind of like LLVM's MachineInstrs.) Then re-allocate +registers. It assumes that the transformations you are doing are safe. +It does not update the mapping information or the LLVM representation +for the modified trace (so it would not, for instance, support +multiple optimization passes; passes have to be aware of and update +manually the mapping information.) + +The way you use it is you take the original code and provide it to +BinInterface; then you do optimizations to it, then you put it in the +trace cache. + +The BinInterface tries to find live-outs for traces so that it can do +register allocation on just the trace, and stitch the trace back into +the original code. It has to preserve the live-ins and live-outs when +it does its register allocation. (On exits from the trace we have +epilogues that copy live-outs back into the right registers, but +live-ins have to be in the right registers.) + + +Limitations of BinInterface +--------------------------- + +It does copy insertions for PHIs, which it infers from the machine +code. The mapping info inserted by LLC is not sufficient to determine +the PHIs. + +It does not handle integer or floating-point condition codes and it +does not handle floating-point register allocation. + +It is not aggressively able to use lots of registers. + +There is a problem with alloca: we cannot find our spill space for +spilling registers, normally allocated on the stack, if the trace +follows an alloca(). What might be an acceptable solution would be to +disable trace generation on functions that have variable-sized +alloca()s. Variable-sized allocas in the trace would also probably +screw things up. + +Because of the FP and alloca limitations, the BinInterface is +completely disabled right now. + + +Demo +---- + +This is a demo of the Ball & Larus version that does NOT use 2-level +profiling. + +1. Compile program with llvm-gcc. +2. Run opt -lowerswitch -paths -emitfuncs on the bytecode. + -lowerswitch change switch statements to branches + -paths Ball & Larus path-profiling algorithm + -emitfuncs emit the table of functions +3. Run llc to generate SPARC assembly code for the result of step 2. +4. Use g++ to link the (instrumented) assembly code. + +We use a script to do all this: +------------------------------------------------------------------------------ +#!/bin/sh +llvm-gcc $1.c -o $1 +opt -lowerswitch -paths -emitfuncs $1.bc > $1.run.bc +llc -f $1.run.bc +LIBS=$HOME/llvm_sparc/lib/Debug +GXX=/usr/dcs/software/evaluation/bin/g++ +$GXX -g -L $LIBS $1.run.s -o $1.run.llc \ +$LIBS/tracecache.o \ +$LIBS/mapinfo.o \ +$LIBS/trigger.o \ +$LIBS/profpaths.o \ +$LIBS/bininterface.o \ +$LIBS/support.o \ +$LIBS/vmcore.o \ +$LIBS/transformutils.o \ +$LIBS/bcreader.o \ +-lscalaropts -lscalaropts -lanalysis \ +-lmalloc -lcpc -lm -ldl +------------------------------------------------------------------------------ + +5. Run the resulting binary. You will see output from BinInterface +(described below) intermixed with the output from the program. + + +Output from BinInterface +------------------------ + +BinInterface's debugging code prints out the following stuff in order: + +1. Initial code provided to BinInterface with original register +allocation. + +2. Section 0 is the trace prolog, consisting mainly of live-ins and +register saves which will be restored in epilogs. + +3. Section 1 is the trace itself, in SSA form used by BinInterface, +along with the PHIs that are inserted. +PHIs are followed by the copies that implement them. +Each branch (i.e., out of the trace) is annotated with the +section number that represents the epilog it branches to. + +4. All the other sections starting with Section 2 are trace epilogs. +Every branch from the trace has to go to some epilog. + +5. After the last section is the register allocation output. diff --git a/libclamav/c++/llvm/docs/HistoricalNotes/2007-OriginalClangReadme.txt b/libclamav/c++/llvm/docs/HistoricalNotes/2007-OriginalClangReadme.txt new file mode 100644 index 000000000..611dc9d2c --- /dev/null +++ b/libclamav/c++/llvm/docs/HistoricalNotes/2007-OriginalClangReadme.txt @@ -0,0 +1,178 @@ +//===----------------------------------------------------------------------===// +// C Language Family Front-end +//===----------------------------------------------------------------------===// + Chris Lattner + +I. Introduction: + + clang: noun + 1. A loud, resonant, metallic sound. + 2. The strident call of a crane or goose. + 3. C-language family front-end toolkit. + + The world needs better compiler tools, tools which are built as libraries. This + design point allows reuse of the tools in new and novel ways. However, building + the tools as libraries isn't enough: they must have clean APIs, be as + decoupled from each other as possible, and be easy to modify/extend. This + requires clean layering, decent design, and avoiding tying the libraries to a + specific use. Oh yeah, did I mention that we want the resultant libraries to + be as fast as possible? :) + + This front-end is built as a component of the LLVM toolkit that can be used + with the LLVM backend or independently of it. In this spirit, the API has been + carefully designed as the following components: + + libsupport - Basic support library, reused from LLVM. + + libsystem - System abstraction library, reused from LLVM. + + libbasic - Diagnostics, SourceLocations, SourceBuffer abstraction, + file system caching for input source files. This depends on + libsupport and libsystem. + + libast - Provides classes to represent the C AST, the C type system, + builtin functions, and various helpers for analyzing and + manipulating the AST (visitors, pretty printers, etc). This + library depends on libbasic. + + + liblex - C/C++/ObjC lexing and preprocessing, identifier hash table, + pragma handling, tokens, and macros. This depends on libbasic. + + libparse - C (for now) parsing and local semantic analysis. This library + invokes coarse-grained 'Actions' provided by the client to do + stuff (e.g. libsema builds ASTs). This depends on liblex. + + libsema - Provides a set of parser actions to build a standardized AST + for programs. AST's are 'streamed' out a top-level declaration + at a time, allowing clients to use decl-at-a-time processing, + build up entire translation units, or even build 'whole + program' ASTs depending on how they use the APIs. This depends + on libast and libparse. + + librewrite - Fast, scalable rewriting of source code. This operates on + the raw syntactic text of source code, allowing a client + to insert and delete text in very large source files using + the same source location information embedded in ASTs. This + is intended to be a low-level API that is useful for + higher-level clients and libraries such as code refactoring. + + libanalysis - Source-level dataflow analysis useful for performing analyses + such as computing live variables. It also includes a + path-sensitive "graph-reachability" engine for writing + analyses that reason about different possible paths of + execution through source code. This is currently being + employed to write a set of checks for finding bugs in software. + + libcodegen - Lower the AST to LLVM IR for optimization & codegen. Depends + on libast. + + clang - An example driver, client of the libraries at various levels. + This depends on all these libraries, and on LLVM VMCore. + + This front-end has been intentionally built as a DAG of libraries, making it + easy to reuse individual parts or replace pieces if desired. For example, to + build a preprocessor, you take the Basic and Lexer libraries. If you want an + indexer, you take those plus the Parser library and provide some actions for + indexing. If you want a refactoring, static analysis, or source-to-source + compiler tool, it makes sense to take those plus the AST building and semantic + analyzer library. Finally, if you want to use this with the LLVM backend, + you'd take these components plus the AST to LLVM lowering code. + + In the future I hope this toolkit will grow to include new and interesting + components, including a C++ front-end, ObjC support, and a whole lot of other + things. + + Finally, it should be pointed out that the goal here is to build something that + is high-quality and industrial-strength: all the obnoxious features of the C + family must be correctly supported (trigraphs, preprocessor arcana, K&R-style + prototypes, GCC/MS extensions, etc). It cannot be used if it is not 'real'. + + +II. Usage of clang driver: + + * Basic Command-Line Options: + - Help: clang --help + - Standard GCC options accepted: -E, -I*, -i*, -pedantic, -std=c90, etc. + - To make diagnostics more gcc-like: -fno-caret-diagnostics -fno-show-column + - Enable metric printing: -stats + + * -fsyntax-only is currently the default mode. + + * -E mode works the same way as GCC. + + * -Eonly mode does all preprocessing, but does not print the output, + useful for timing the preprocessor. + + * -fsyntax-only is currently partially implemented, lacking some + semantic analysis (some errors and warnings are not produced). + + * -parse-noop parses code without building an AST. This is useful + for timing the cost of the parser without including AST building + time. + + * -parse-ast builds ASTs, but doesn't print them. This is most + useful for timing AST building vs -parse-noop. + + * -parse-ast-print pretty prints most expression and statements nodes. + + * -parse-ast-check checks that diagnostic messages that are expected + are reported and that those which are reported are expected. + + * -dump-cfg builds ASTs and then CFGs. CFGs are then pretty-printed. + + * -view-cfg builds ASTs and then CFGs. CFGs are then visualized by + invoking Graphviz. + + For more information on getting Graphviz to work with clang/LLVM, + see: http://llvm.org/docs/ProgrammersManual.html#ViewGraph + + +III. Current advantages over GCC: + + * Column numbers are fully tracked (no 256 col limit, no GCC-style pruning). + * All diagnostics have column numbers, includes 'caret diagnostics', and they + highlight regions of interesting code (e.g. the LHS and RHS of a binop). + * Full diagnostic customization by client (can format diagnostics however they + like, e.g. in an IDE or refactoring tool) through DiagnosticClient interface. + * Built as a framework, can be reused by multiple tools. + * All languages supported linked into same library (no cc1,cc1obj, ...). + * mmap's code in read-only, does not dirty the pages like GCC (mem footprint). + * LLVM License, can be linked into non-GPL projects. + * Full diagnostic control, per diagnostic. Diagnostics are identified by ID. + * Significantly faster than GCC at semantic analysis, parsing, preprocessing + and lexing. + * Defers exposing platform-specific stuff to as late as possible, tracks use of + platform-specific features (e.g. #ifdef PPC) to allow 'portable bytecodes'. + * The lexer doesn't rely on the "lexer hack": it has no notion of scope and + does not categorize identifiers as types or variables -- this is up to the + parser to decide. + +Potential Future Features: + + * Fine grained diag control within the source (#pragma enable/disable warning). + * Better token tracking within macros? (Token came from this line, which is + a macro argument instantiated here, recursively instantiated here). + * Fast #import with a module system. + * Dependency tracking: change to header file doesn't recompile every function + that texually depends on it: recompile only those functions that need it. + This is aka 'incremental parsing'. + + +IV. Missing Functionality / Improvements + +Lexer: + * Source character mapping. GCC supports ASCII and UTF-8. + See GCC options: -ftarget-charset and -ftarget-wide-charset. + * Universal character support. Experimental in GCC, enabled with + -fextended-identifiers. + * -fpreprocessed mode. + +Preprocessor: + * #assert/#unassert + * MSExtension: "L#param" stringizes to a wide string literal. + * Add support for -M* + +Traditional Preprocessor: + * Currently, we have none. :) + diff --git a/libclamav/c++/llvm/docs/HowToReleaseLLVM.html b/libclamav/c++/llvm/docs/HowToReleaseLLVM.html new file mode 100644 index 000000000..7f1844050 --- /dev/null +++ b/libclamav/c++/llvm/docs/HowToReleaseLLVM.html @@ -0,0 +1,524 @@ + + + + How To Release LLVM To The Public + + + + +
How To Release LLVM To The Public
+
    +
  1. Introduction
  2. +
  3. Qualification Criteria
  4. +
  5. Release Timeline
  6. +
  7. Release Process
  8. +
+
+

Written by Tanya Lattner, + Reid Spencer, + John Criswell +

+
+ + + + + +
+

+ This document collects information about successfully releasing LLVM + (including subprojects llvm-gcc and Clang) to the public. + It is the release manager's responsibility to ensure that a high quality + build of LLVM is released. +

+
+ + + + +
+

LLVM is released on a time based schedule (currently every 6 months). We + do not have dot releases because of the nature of LLVM incremental + development philosophy. The release schedule is roughly as follows: +

+
    +
  1. Set code freeze and branch creation date for 6 months after last code freeze +date. Announce release schedule to the LLVM community and update the website.
  2. +
  3. Create release branch and begin release process.
  4. +
  5. Send out pre-release for first round of testing. Testing will last 7-10 days. +During the first round of testing, regressions should be found and fixed. Patches +are merged from mainline to the release branch.
  6. +
  7. Generate and send out second pre-release. Bugs found during this time will +not be fixed unless absolutely critical. Bugs introduce by patches merged in +will be fixed and if so, a 3rd round of testing is needed.
  8. +
  9. The release notes should be updated during the first and second round of +pre-release testing.
  10. +
  11. Finally, release!
  12. +
+
+ + + + + + + + + + + +
+This section describes a few administrative tasks that need to be done for the +release process to begin. Specifically, it involves creating the release branch, + resetting version numbers, and creating the release tarballs for the release + team to begin testing. +
+ + + +
+

Branch the Subversion HEAD using the following procedure:

+
    +
  1. +

    Verify that the current Subversion HEAD is in decent shape by examining + nightly tester or buildbot results.

  2. +
  3. +

    Request all developers to refrain from committing. Offenders get commit + rights taken away (temporarily).

  4. +
  5. +

    Create the release branch for llvm, llvm-gcc4.2, + clang, and the test-suite. The branch name will be + release_XX,where XX is the major and minor release numbers. + Clang will have a different release number than llvm/ + llvm-gcc4 since its first release was years later + (still deciding if this will be true or not). These branches + can be created without checking out anything from subversion. +

    + +
    +
    +svn copy https://llvm.org/svn/llvm-project/llvm/trunk \
    +         https://llvm.org/svn/llvm-project/llvm/branches/release_XX
    +svn copy https://llvm.org/svn/llvm-project/llvm-gcc-4.2/trunk \
    +         https://llvm.org/svn/llvm-project/llvm-gcc-4.2/branches/release_XX
    +svn copy https://llvm.org/svn/llvm-project/test-suite/trunk \
    +         https://llvm.org/svn/llvm-project/test-suite/branches/release_XX
    +svn copy https://llvm.org/svn/llvm-project/cfe/trunk \
    +         https://llvm.org/svn/llvm-project/cfe/branches/release_XX
    +
    +
    + +
  6. +

    Advise developers they can work on Subversion HEAD again.

  7. + +
  8. +

    The Release Manager should switch to the release branch (as all changes + to the release will now be done in the branch). The easiest way to do this + is to grab another working copy using the following commands:

    + +
    +
    +svn co https://llvm.org/svn/llvm-project/llvm/branches/release_XX
    +svn co https://llvm.org/svn/llvm-project/llvm-gcc-4.2/branches/release_XX
    +svn co https://llvm.org/svn/llvm-project/test-suite/branches/release_XX
    +svn co https://llvm.org/svn/llvm-project/cfe/branches/release_XX
    +
    +
  9. + +
+
+ + + +
+

+ After creating the LLVM release branch, update the release branches' + autoconf/configure.ac version from X.Xsvn to just X.X. Update it on mainline + as well to be the next version (X.X+1svn). Regenerated the configure script + for both. This must be done for both llvm and the + test-suite. +

+

FIXME: Add a note about clang.

+

In addition, the version number of all the Bugzilla components must be + updated for the next release. +

+
+ + + +
+

+ Create source distributions for LLVM, LLVM-GCC, + clang, and the llvm test-suite by exporting the source from + Subversion and archiving it. This can be done with the following commands: +

+ +
+
+svn export https://llvm.org/svn/llvm-project/llvm/branches/release_XX llvm-X.X
+svn export https://llvm.org/svn/llvm-project/llvm-gcc-4.2/branches/release_XX llvm-gcc4.2-X.X.source
+svn export https://llvm.org/svn/llvm-project/test-suite/branches/release_XX llvm-test-X.X
+svn export https://llvm.org/svn/llvm-project/cfe/branches/release_XX clang-X.X
+tar -czvf - llvm-X.X          | gzip > llvm-X.X.tar.gz
+tar -czvf - llvm-test-X.X     | gzip > llvm-test-X.X.tar.gz
+tar -czvf - llvm-gcc4.2-X.X.source | gzip > llvm-gcc-4.2-X.X.source.tar.gz
+tar -czvf - clang-X.X | gzip > clang-X.X.tar.gz
+
+
+
+ + + + +
+The build of llvm, llvm-gcc, and clang must be free +of errors and warnings in both debug, release, and release-asserts builds. +If all builds are clean, then the release passes build qualification. + +
    +
  1. debug: ENABLE_OPTIMIZED=0
  2. +
  3. release: ENABLE_OPTIMIZED=1
  4. +
  5. release-asserts: ENABLE_OPTIMIZED=1 DISABLE_ASSERTIONS=1
  6. +
+
+ + + +
+

+ Build both debug, release (optimized), and release-asserts versions of + LLVM on all supported platforms. Direction to build llvm are + here. +

+
+ + + +
+

+ Creating the LLVM GCC binary distribution (release/optimized) requires + performing the following steps for each supported platform: +

+ +
    +
  1. + Build the LLVM GCC front-end by following the directions in the README.LLVM + file. The frontend must be compiled with c, c++, objc (mac only), + objc++ (mac only) and fortran support.
  2. +
  3. Please boostrap as well.
  4. +
  5. Be sure to build with LLVM_VERSION_INFO=X.X, where X is the major and + minor release numbers. +
  6. + +
  7. + Copy the installation directory to a directory named for the specific target. + For example on Red Hat Enterprise Linux, the directory would be named + llvm-gcc4.2-2.6-x86-linux-RHEL4. Archive and compress the new directory. +
  8. +
+
+ + + +
+

+ Creating the Clang binary distribution (debug/release/release-asserts) requires + performing the following steps for each supported platform: +

+ +
    +
  1. + Build clang according to the directions + here. +
  2. + +
  3. Build both a debug and release version of clang, but the binary + will be a release build.
  4. + +
  5. + Package clang (details to follow). +
  6. +
+
+ + + + +
+

+ The table below specifies which compilers are used for each arch/os combination + when qualifying the build of llvm, llvm-gcc, clang. +

+ +

+ + + + + + + + + + +
ArchitectureOScompiler
x86-32Mac OS 10.5gcc 4.0.1
x86-32Linuxgcc 4.2.X, gcc 4.3.X
x86-32FreeBSDgcc 4.2.X
x86-32mingwgcc 3.4.5
x86-64Mac OS 10.5gcc 4.0.1
x86-64Linuxgcc 4.2.X, gcc 4.3.X
x86-64FreeBSDgcc 4.2.X
+

+ +
+ + + + + +
+ A release is qualified when it has no regressions from the previous + release (or baseline). Regressions are related to correctness only and not + performance at this time. Regressions are new failures in the set of tests that + are used to qualify each product and only include things on the list. + Ultimately, there is no end to the number of possible bugs in a release. We + need a very concrete and definitive release criteria that ensures we have + monotonically improving quality on some metric. The metric we use is + described below. This doesn't mean that we don't care about other things, + but this are things that must be satisfied before a release can go out +
+ + + + +
+

+ LLVM is qualified when it has a clean dejagnu test run without a frontend and + it has no regressions when using either llvm-gcc or clang + with the test-suite from the previous release. +

+
+ + + +
+

+ LLVM-GCC is qualified when front-end specific tests in the + llvm dejagnu test suite all pass and there are no regressions in + the test-suite.

+

We do not use the gcc dejagnu test suite as release criteria.

+
+ + + +
+ Clang is qualified when front-end specific tests in the + llvm dejagnu test suite all pass, clang's own test suite passes + cleanly, and there are no regressions in the test-suite.

+
+ + + +
+

+ + + + + + + + +
ArchitectureOSllvm-gcc baselineclang baseline + tests
x86-32Mac OS 10.5last releasenonellvm dejagnu, clang tests, test-suite (including spec)
x86-32Linuxlast releasenonellvm dejagnu, clang tests, test-suite (including spec)
x86-32FreeBSDnonenonellvm dejagnu, clang tests, test-suite
x86-32mingwlast releasenoneQT
x86-64Mac OS 10.5last releasenonellvm dejagnu, clang tests, test-suite (including spec)
x86-64Linuxlast releasenonellvm dejagnu, clang tests, test-suite (including spec)
x86-64FreeBSDnonenonellvm dejagnu, clang tests, test-suite

+
+ + + +
+

+ Once all testing has been completed and appropriate bugs filed, the pre-release + tar balls may be put on the website and the LLVM community is notified. Ask that + all LLVM developers test the release in 2 ways:

+
    +
  1. Download llvm-X.X, llvm-test-X.X, and the appropriate llvm-gcc4 + and/or clang binary. Build LLVM. + Run "make check" and the full llvm-test suite (make TEST=nightly report).
  2. +
  3. Download llvm-X.X, llvm-test-X.X, and the llvm-gcc4 and/or clang source. + Compile everything. Run "make check" and the full llvm-test suite (make TEST=nightly + report).
  4. +
+

Ask LLVM developers to submit the report and make check results to the list. + Attempt to verify that there are no regressions from the previous release. + The results are not used to qualify a release, but to spot other potential + problems. For unsupported targets, verify that make check at least is + clean.

+ +

During the first round of testing time, + all regressions must be fixed before the second pre-release is created.

+ +

If this is the second round of testing, this is only to ensure the bug + fixes previously merged in have not created new major problems. This is not + the time to solve additional and unrelated bugs. If no patches are merged in, + the release is determined to be ready and the release manager may move onto + the next step. +

+
+ + + +
+

+ Below are the rules regarding patching the release branch.

+

+

  • Patches applied to the release branch are only applied by the release + manager.
  • +
  • During the first round of testing, patches that fix regressions or that + are small and relatively risk free (verified by the appropriate code owner) + are applied to the branch. Code owners are asked to be very conservative in + approving patches for the branch and we reserve the right to reject any patch + that does not fix a regression as previously defined.
  • +
  • During the remaining rounds of testing, only patches that fix regressions + may be applied.
  • + +

    +
    + + + + +
    +

    + The final stages of the release process involving taging the release branch, + updating documentation that refers to the release, and updating the demo + page.

    +

    FIXME: Add a note if anything needs to be done to the clang website. + Eventually the websites will be merged hopefully.

    +
    + + + + +
    +

    + Review the documentation and ensure that it is up to date. The Release Notes + must be updated to reflect bug fixes, new known issues, and changes in the + list of supported platforms. The Getting Started Guide should be updated to + reflect the new release version number tag avaiable from Subversion and + changes in basic system requirements. Merge both changes from mainline into + the release branch. +

    +
    + + + +
    +

    Tag the release branch using the following procedure:

    +
    +
    +svn copy https://llvm.org/svn/llvm-project/llvm/branches/release_XX \
    +         https://llvm.org/svn/llvm-project/llvm/tags/RELEASE_XX
    +svn copy https://llvm.org/svn/llvm-project/llvm-gcc-4.2/branches/release_XX \
    +         https://llvm.org/svn/llvm-project/llvm-gcc-4.2/tags/RELEASE_XX
    +svn copy https://llvm.org/svn/llvm-project/test-suite/branches/release_XX \
    +         https://llvm.org/svn/llvm-project/test-suite/tags/RELEASE_XX
    +
    +
    +
    + + + + + +
    +

    + The LLVM demo page must be updated to use the new release. This consists of + using the llvm-gcc binary and building LLVM. Update the website demo page + configuration to use the new release.

    +
    + + + +
    +

    + The website must be updated before the release announcement is sent out. Here is + what to do:

    +
      +
    1. Check out the website module from CVS.
    2. +
    3. Create a new subdirectory X.X in the releases directory.
    4. +
    5. Commit the llvm, test-suite, llvm-gcc source, + clang source, clang binaries, + and llvm-gcc binaries in this new directory.
    6. +
    7. Copy and commit the llvm/docs and LICENSE.txt + files into this new directory. The docs should be built with BUILD_FOR_WEBSITE=1.
    8. +
    9. Commit the index.html to the release/X.X directory to redirect (use from previous + release.
    10. +
    11. Update the releases/download.html file with the new release.
    12. +
    13. Update the releases/index.html with the new release and link to + release documentation.
    14. +
    15. Finally, update the main page (index.html and sidebar) to + point to the new release and release announcement. Make sure this all gets + committed back into Subversion.
    16. +
    +
    + + + +
    +

    Have Chris send out the release announcement when everything is finished.

    +
    + + +
    +
    + Valid CSS + Valid HTML 4.01 + The LLVM Compiler Infrastructure +
    + Last modified: $Date$ +
    + + diff --git a/libclamav/c++/llvm/docs/HowToSubmitABug.html b/libclamav/c++/llvm/docs/HowToSubmitABug.html new file mode 100644 index 000000000..0815b88cf --- /dev/null +++ b/libclamav/c++/llvm/docs/HowToSubmitABug.html @@ -0,0 +1,355 @@ + + + + How to submit an LLVM bug report + + + + +
    + How to submit an LLVM bug report +
    + + + + + + +
    +
      +
    1. Introduction - Got bugs?
    2. +
    3. Crashing Bugs +
    4. +
    5. Miscompilations
    6. +
    7. Incorrect code generation (JIT and LLC)
    8. +
    +
    +

    Written by Chris Lattner and + Misha Brukman

    +
    +
    + Debugging +
    + + + + + +
    + +

    If you're working with LLVM and run into a bug, we definitely want to know +about it. This document describes what you can do to increase the odds of +getting it fixed quickly.

    + +

    Basically you have to do two things at a minimum. First, decide whether the +bug crashes the compiler (or an LLVM pass), or if the +compiler is miscompiling the program (i.e., the +compiler successfully produces an executable, but it doesn't run right). Based +on +what type of bug it is, follow the instructions in the linked section to narrow +down the bug so that the person who fixes it will be able to find the problem +more easily.

    + +

    Once you have a reduced test-case, go to the LLVM Bug Tracking +System and fill out the form with the necessary details (note that you don't +need to pick a category, just use the "new-bugs" category if you're not sure). +The bug description should contain the following +information:

    + +
      +
    • All information necessary to reproduce the problem.
    • +
    • The reduced test-case that triggers the bug.
    • +
    • The location where you obtained LLVM (if not from our Subversion + repository).
    • +
    + +

    Thanks for helping us make LLVM better!

    + +
    + + + + + +
    + +

    More often than not, bugs in the compiler cause it to crash—often due +to an assertion failure of some sort. The most important +piece of the puzzle is to figure out if it is crashing in the GCC front-end +or if it is one of the LLVM libraries (e.g. the optimizer or code generator) +that has problems.

    + +

    To figure out which component is crashing (the front-end, +optimizer or code generator), run the +llvm-gcc command line as you were when the crash occurred, but +with the following extra command line options:

    + +
      +
    • -O0 -emit-llvm: If llvm-gcc still crashes when + passed these options (which disable the optimizer and code generator), then + the crash is in the front-end. Jump ahead to the section on front-end bugs.
    • + +
    • -emit-llvm: If llvm-gcc crashes with this option + (which disables the code generator), you found an optimizer bug. Jump ahead + to compile-time optimization bugs.
    • + +
    • Otherwise, you have a code generator crash. Jump ahead to code generator bugs.
    • + +
    + +
    + + + + +
    + +

    If the problem is in the front-end, you should re-run the same +llvm-gcc command that resulted in the crash, but add the +-save-temps option. The compiler will crash again, but it will leave +behind a foo.i file (containing preprocessed C source code) and +possibly foo.s for each +compiled foo.c file. Send us the foo.i file, +along with the options you passed to llvm-gcc, and a brief description of the +error it caused.

    + +

    The delta tool helps to reduce the +preprocessed file down to the smallest amount of code that still replicates the +problem. You're encouraged to use delta to reduce the code to make the +developers' lives easier. This website +has instructions on the best way to use delta.

    + +
    + + + + +
    + +

    If you find that a bug crashes in the optimizer, compile your test-case to a +.bc file by passing "-emit-llvm -O0 -c -o foo.bc". +Then run:

    + +
    +

    opt -std-compile-opts -debug-pass=Arguments foo.bc + -disable-output

    +
    + +

    This command should do two things: it should print out a list of passes, and +then it should crash in the same was as llvm-gcc. If it doesn't crash, please +follow the instructions for a front-end bug.

    + +

    If this does crash, then you should be able to debug this with the following +bugpoint command:

    + +
    +

    bugpoint foo.bc <list of passes printed by +opt>

    +
    + +

    Please run this, then file a bug with the instructions and reduced .bc files +that bugpoint emits. If something goes wrong with bugpoint, please submit the +"foo.bc" file and the list of passes printed by opt.

    + +
    + + + + +
    + +

    If you find a bug that crashes llvm-gcc in the code generator, compile your +source file to a .bc file by passing "-emit-llvm -c -o foo.bc" +to llvm-gcc (in addition to the options you already pass). Once your have +foo.bc, one of the following commands should fail:

    + +
      +
    1. llc foo.bc
    2. +
    3. llc foo.bc -relocation-model=pic
    4. +
    5. llc foo.bc -relocation-model=static
    6. +
    7. llc foo.bc -enable-eh
    8. +
    9. llc foo.bc -relocation-model=pic -enable-eh
    10. +
    11. llc foo.bc -relocation-model=static -enable-eh
    12. +
    + +

    If none of these crash, please follow the instructions for a +front-end bug. If one of these do crash, you should +be able to reduce this with one of the following bugpoint command lines (use +the one corresponding to the command above that failed):

    + +
      +
    1. bugpoint -run-llc foo.bc
    2. +
    3. bugpoint -run-llc foo.bc --tool-args + -relocation-model=pic
    4. +
    5. bugpoint -run-llc foo.bc --tool-args + -relocation-model=static
    6. +
    7. bugpoint -run-llc foo.bc --tool-args -enable-eh
    8. +
    9. bugpoint -run-llc foo.bc --tool-args + -relocation-model=pic -enable-eh
    10. +
    11. bugpoint -run-llc foo.bc --tool-args + -relocation-model=static -enable-eh
    12. +
    + +

    Please run this, then file a bug with the instructions and reduced .bc file +that bugpoint emits. If something goes wrong with bugpoint, please submit the +"foo.bc" file and the option that llc crashes with.

    + +
    + + + + + +
    + +

    If llvm-gcc successfully produces an executable, but that executable doesn't +run right, this is either a bug in the code or a bug in the +compiler. The first thing to check is to make sure it is not using undefined +behavior (e.g. reading a variable before it is defined). In particular, check +to see if the program valgrinds clean, +passes purify, or some other memory checker tool. Many of the "LLVM bugs" that +we have chased down ended up being bugs in the program being compiled, not + LLVM.

    + +

    Once you determine that the program itself is not buggy, you should choose +which code generator you wish to compile the program with (e.g. C backend, the +JIT, or LLC) and optionally a series of LLVM passes to run. For example:

    + +
    +

    +bugpoint -run-cbe [... optzn passes ...] file-to-test.bc --args -- [program arguments]

    +
    + +

    bugpoint will try to narrow down your list of passes to the one pass +that causes an error, and simplify the bitcode file as much as it can to assist +you. It will print a message letting you know how to reproduce the resulting +error.

    + +
    + + + + + +
    + +

    Similarly to debugging incorrect compilation by mis-behaving passes, you can +debug incorrect code generation by either LLC or the JIT, using +bugpoint. The process bugpoint follows in this case is to try +to narrow the code down to a function that is miscompiled by one or the other +method, but since for correctness, the entire program must be run, +bugpoint will compile the code it deems to not be affected with the C +Backend, and then link in the shared object it generates.

    + +

    To debug the JIT:

    + +
    +
    +bugpoint -run-jit -output=[correct output file] [bitcode file]  \
    +         --tool-args -- [arguments to pass to lli]              \
    +         --args -- [program arguments]
    +
    +
    + +

    Similarly, to debug the LLC, one would run:

    + +
    +
    +bugpoint -run-llc -output=[correct output file] [bitcode file]  \
    +         --tool-args -- [arguments to pass to llc]              \
    +         --args -- [program arguments]
    +
    +
    + +

    Special note: if you are debugging MultiSource or SPEC tests that +already exist in the llvm/test hierarchy, there is an easier way to +debug the JIT, LLC, and CBE, using the pre-written Makefile targets, which +will pass the program options specified in the Makefiles:

    + +
    +

    +cd llvm/test/../../program
    +make bugpoint-jit +

    +
    + +

    At the end of a successful bugpoint run, you will be presented +with two bitcode files: a safe file which can be compiled with the C +backend and the test file which either LLC or the JIT +mis-codegenerates, and thus causes the error.

    + +

    To reproduce the error that bugpoint found, it is sufficient to do +the following:

    + +
      + +
    1. Regenerate the shared object from the safe bitcode file:

      + +
      +

      +llc -march=c safe.bc -o safe.c
      +gcc -shared safe.c -o safe.so +

      +
    2. + +
    3. If debugging LLC, compile test bitcode native and link with the shared + object:

      + +
      +

      +llc test.bc -o test.s
      +gcc test.s safe.so -o test.llc
      +./test.llc [program options] +

      +
    4. + +
    5. If debugging the JIT, load the shared object and supply the test + bitcode:

      + +
      +

      lli -load=safe.so test.bc [program options]

      +
    6. + +
    + +
    + + +
    +
    + Valid CSS + Valid HTML 4.01 + + Chris Lattner
    + The LLVM Compiler Infrastructure +
    + Last modified: $Date$ +
    + + + diff --git a/libclamav/c++/llvm/docs/LangRef.html b/libclamav/c++/llvm/docs/LangRef.html new file mode 100644 index 000000000..ab656d89a --- /dev/null +++ b/libclamav/c++/llvm/docs/LangRef.html @@ -0,0 +1,7292 @@ + + + + LLVM Assembly Language Reference Manual + + + + + + + + +
    LLVM Language Reference Manual
    +
      +
    1. Abstract
    2. +
    3. Introduction
    4. +
    5. Identifiers
    6. +
    7. High Level Structure +
        +
      1. Module Structure
      2. +
      3. Linkage Types +
          +
        1. 'private' Linkage
        2. +
        3. 'linker_private' Linkage
        4. +
        5. 'internal' Linkage
        6. +
        7. 'available_externally' Linkage
        8. +
        9. 'linkonce' Linkage
        10. +
        11. 'common' Linkage
        12. +
        13. 'weak' Linkage
        14. +
        15. 'appending' Linkage
        16. +
        17. 'extern_weak' Linkage
        18. +
        19. 'linkonce_odr' Linkage
        20. +
        21. 'weak_odr' Linkage
        22. +
        23. 'externally visible' Linkage
        24. +
        25. 'dllimport' Linkage
        26. +
        27. 'dllexport' Linkage
        28. +
        +
      4. +
      5. Calling Conventions
      6. +
      7. Named Types
      8. +
      9. Global Variables
      10. +
      11. Functions
      12. +
      13. Aliases
      14. +
      15. Parameter Attributes
      16. +
      17. Function Attributes
      18. +
      19. Garbage Collector Names
      20. +
      21. Module-Level Inline Assembly
      22. +
      23. Data Layout
      24. +
      25. Pointer Aliasing Rules
      26. +
      +
    8. +
    9. Type System +
        +
      1. Type Classifications
      2. +
      3. Primitive Types +
          +
        1. Integer Type
        2. +
        3. Floating Point Types
        4. +
        5. Void Type
        6. +
        7. Label Type
        8. +
        9. Metadata Type
        10. +
        +
      4. +
      5. Derived Types +
          +
        1. Array Type
        2. +
        3. Function Type
        4. +
        5. Pointer Type
        6. +
        7. Structure Type
        8. +
        9. Packed Structure Type
        10. +
        11. Vector Type
        12. +
        13. Opaque Type
        14. +
        +
      6. +
      7. Type Up-references
      8. +
      +
    10. +
    11. Constants +
        +
      1. Simple Constants
      2. +
      3. Complex Constants
      4. +
      5. Global Variable and Function Addresses
      6. +
      7. Undefined Values
      8. +
      9. Addresses of Basic Blocks
      10. +
      11. Constant Expressions
      12. +
      13. Embedded Metadata
      14. +
      +
    12. +
    13. Other Values +
        +
      1. Inline Assembler Expressions
      2. +
      +
    14. +
    15. Intrinsic Global Variables +
        +
      1. The 'llvm.used' Global Variable
      2. +
      3. The 'llvm.compiler.used' + Global Variable
      4. +
      5. The 'llvm.global_ctors' + Global Variable
      6. +
      7. The 'llvm.global_dtors' + Global Variable
      8. +
      +
    16. +
    17. Instruction Reference +
        +
      1. Terminator Instructions +
          +
        1. 'ret' Instruction
        2. +
        3. 'br' Instruction
        4. +
        5. 'switch' Instruction
        6. +
        7. 'indirectbr' Instruction
        8. +
        9. 'invoke' Instruction
        10. +
        11. 'unwind' Instruction
        12. +
        13. 'unreachable' Instruction
        14. +
        +
      2. +
      3. Binary Operations +
          +
        1. 'add' Instruction
        2. +
        3. 'fadd' Instruction
        4. +
        5. 'sub' Instruction
        6. +
        7. 'fsub' Instruction
        8. +
        9. 'mul' Instruction
        10. +
        11. 'fmul' Instruction
        12. +
        13. 'udiv' Instruction
        14. +
        15. 'sdiv' Instruction
        16. +
        17. 'fdiv' Instruction
        18. +
        19. 'urem' Instruction
        20. +
        21. 'srem' Instruction
        22. +
        23. 'frem' Instruction
        24. +
        +
      4. +
      5. Bitwise Binary Operations +
          +
        1. 'shl' Instruction
        2. +
        3. 'lshr' Instruction
        4. +
        5. 'ashr' Instruction
        6. +
        7. 'and' Instruction
        8. +
        9. 'or' Instruction
        10. +
        11. 'xor' Instruction
        12. +
        +
      6. +
      7. Vector Operations +
          +
        1. 'extractelement' Instruction
        2. +
        3. 'insertelement' Instruction
        4. +
        5. 'shufflevector' Instruction
        6. +
        +
      8. +
      9. Aggregate Operations +
          +
        1. 'extractvalue' Instruction
        2. +
        3. 'insertvalue' Instruction
        4. +
        +
      10. +
      11. Memory Access and Addressing Operations +
          +
        1. 'alloca' Instruction
        2. +
        3. 'load' Instruction
        4. +
        5. 'store' Instruction
        6. +
        7. 'getelementptr' Instruction
        8. +
        +
      12. +
      13. Conversion Operations +
          +
        1. 'trunc .. to' Instruction
        2. +
        3. 'zext .. to' Instruction
        4. +
        5. 'sext .. to' Instruction
        6. +
        7. 'fptrunc .. to' Instruction
        8. +
        9. 'fpext .. to' Instruction
        10. +
        11. 'fptoui .. to' Instruction
        12. +
        13. 'fptosi .. to' Instruction
        14. +
        15. 'uitofp .. to' Instruction
        16. +
        17. 'sitofp .. to' Instruction
        18. +
        19. 'ptrtoint .. to' Instruction
        20. +
        21. 'inttoptr .. to' Instruction
        22. +
        23. 'bitcast .. to' Instruction
        24. +
        +
      14. +
      15. Other Operations +
          +
        1. 'icmp' Instruction
        2. +
        3. 'fcmp' Instruction
        4. +
        5. 'phi' Instruction
        6. +
        7. 'select' Instruction
        8. +
        9. 'call' Instruction
        10. +
        11. 'va_arg' Instruction
        12. +
        +
      16. +
      +
    18. +
    19. Intrinsic Functions +
        +
      1. Variable Argument Handling Intrinsics +
          +
        1. 'llvm.va_start' Intrinsic
        2. +
        3. 'llvm.va_end' Intrinsic
        4. +
        5. 'llvm.va_copy' Intrinsic
        6. +
        +
      2. +
      3. Accurate Garbage Collection Intrinsics +
          +
        1. 'llvm.gcroot' Intrinsic
        2. +
        3. 'llvm.gcread' Intrinsic
        4. +
        5. 'llvm.gcwrite' Intrinsic
        6. +
        +
      4. +
      5. Code Generator Intrinsics +
          +
        1. 'llvm.returnaddress' Intrinsic
        2. +
        3. 'llvm.frameaddress' Intrinsic
        4. +
        5. 'llvm.stacksave' Intrinsic
        6. +
        7. 'llvm.stackrestore' Intrinsic
        8. +
        9. 'llvm.prefetch' Intrinsic
        10. +
        11. 'llvm.pcmarker' Intrinsic
        12. +
        13. llvm.readcyclecounter' Intrinsic
        14. +
        +
      6. +
      7. Standard C Library Intrinsics +
          +
        1. 'llvm.memcpy.*' Intrinsic
        2. +
        3. 'llvm.memmove.*' Intrinsic
        4. +
        5. 'llvm.memset.*' Intrinsic
        6. +
        7. 'llvm.sqrt.*' Intrinsic
        8. +
        9. 'llvm.powi.*' Intrinsic
        10. +
        11. 'llvm.sin.*' Intrinsic
        12. +
        13. 'llvm.cos.*' Intrinsic
        14. +
        15. 'llvm.pow.*' Intrinsic
        16. +
        +
      8. +
      9. Bit Manipulation Intrinsics +
          +
        1. 'llvm.bswap.*' Intrinsics
        2. +
        3. 'llvm.ctpop.*' Intrinsic
        4. +
        5. 'llvm.ctlz.*' Intrinsic
        6. +
        7. 'llvm.cttz.*' Intrinsic
        8. +
        +
      10. +
      11. Arithmetic with Overflow Intrinsics +
          +
        1. 'llvm.sadd.with.overflow.* Intrinsics
        2. +
        3. 'llvm.uadd.with.overflow.* Intrinsics
        4. +
        5. 'llvm.ssub.with.overflow.* Intrinsics
        6. +
        7. 'llvm.usub.with.overflow.* Intrinsics
        8. +
        9. 'llvm.smul.with.overflow.* Intrinsics
        10. +
        11. 'llvm.umul.with.overflow.* Intrinsics
        12. +
        +
      12. +
      13. Debugger intrinsics
      14. +
      15. Exception Handling intrinsics
      16. +
      17. Trampoline Intrinsic +
          +
        1. 'llvm.init.trampoline' Intrinsic
        2. +
        +
      18. +
      19. Atomic intrinsics +
          +
        1. llvm.memory_barrier
        2. +
        3. llvm.atomic.cmp.swap
        4. +
        5. llvm.atomic.swap
        6. +
        7. llvm.atomic.load.add
        8. +
        9. llvm.atomic.load.sub
        10. +
        11. llvm.atomic.load.and
        12. +
        13. llvm.atomic.load.nand
        14. +
        15. llvm.atomic.load.or
        16. +
        17. llvm.atomic.load.xor
        18. +
        19. llvm.atomic.load.max
        20. +
        21. llvm.atomic.load.min
        22. +
        23. llvm.atomic.load.umax
        24. +
        25. llvm.atomic.load.umin
        26. +
        +
      20. +
      21. Memory Use Markers +
          +
        1. llvm.lifetime.start
        2. +
        3. llvm.lifetime.end
        4. +
        5. llvm.invariant.start
        6. +
        7. llvm.invariant.end
        8. +
        +
      22. +
      23. General intrinsics +
          +
        1. + 'llvm.var.annotation' Intrinsic
        2. +
        3. + 'llvm.annotation.*' Intrinsic
        4. +
        5. + 'llvm.trap' Intrinsic
        6. +
        7. + 'llvm.stackprotector' Intrinsic
        8. +
        +
      24. +
      +
    20. +
    + +
    +

    Written by Chris Lattner + and Vikram Adve

    +
    + + + + + +
    + +

    This document is a reference manual for the LLVM assembly language. LLVM is + a Static Single Assignment (SSA) based representation that provides type + safety, low-level operations, flexibility, and the capability of representing + 'all' high-level languages cleanly. It is the common code representation + used throughout all phases of the LLVM compilation strategy.

    + +
    + + + + + +
    + +

    The LLVM code representation is designed to be used in three different forms: + as an in-memory compiler IR, as an on-disk bitcode representation (suitable + for fast loading by a Just-In-Time compiler), and as a human readable + assembly language representation. This allows LLVM to provide a powerful + intermediate representation for efficient compiler transformations and + analysis, while providing a natural means to debug and visualize the + transformations. The three different forms of LLVM are all equivalent. This + document describes the human readable representation and notation.

    + +

    The LLVM representation aims to be light-weight and low-level while being + expressive, typed, and extensible at the same time. It aims to be a + "universal IR" of sorts, by being at a low enough level that high-level ideas + may be cleanly mapped to it (similar to how microprocessors are "universal + IR's", allowing many source languages to be mapped to them). By providing + type information, LLVM can be used as the target of optimizations: for + example, through pointer analysis, it can be proven that a C automatic + variable is never accessed outside of the current function, allowing it to + be promoted to a simple SSA value instead of a memory location.

    + +
    + + + + +
    + +

    It is important to note that this document describes 'well formed' LLVM + assembly language. There is a difference between what the parser accepts and + what is considered 'well formed'. For example, the following instruction is + syntactically okay, but not well formed:

    + +
    +
    +%x = add i32 1, %x
    +
    +
    + +

    because the definition of %x does not dominate all of its uses. The + LLVM infrastructure provides a verification pass that may be used to verify + that an LLVM module is well formed. This pass is automatically run by the + parser after parsing input assembly and by the optimizer before it outputs + bitcode. The violations pointed out by the verifier pass indicate bugs in + transformation passes or input to the parser.

    + +
    + + + + + + + +
    + +

    LLVM identifiers come in two basic types: global and local. Global + identifiers (functions, global variables) begin with the '@' + character. Local identifiers (register names, types) begin with + the '%' character. Additionally, there are three different formats + for identifiers, for different purposes:

    + +
      +
    1. Named values are represented as a string of characters with their prefix. + For example, %foo, @DivisionByZero, + %a.really.long.identifier. The actual regular expression used is + '[%@][a-zA-Z$._][a-zA-Z$._0-9]*'. Identifiers which require + other characters in their names can be surrounded with quotes. Special + characters may be escaped using "\xx" where xx is the + ASCII code for the character in hexadecimal. In this way, any character + can be used in a name value, even quotes themselves.
    2. + +
    3. Unnamed values are represented as an unsigned numeric value with their + prefix. For example, %12, @2, %44.
    4. + +
    5. Constants, which are described in a section about + constants, below.
    6. +
    + +

    LLVM requires that values start with a prefix for two reasons: Compilers + don't need to worry about name clashes with reserved words, and the set of + reserved words may be expanded in the future without penalty. Additionally, + unnamed identifiers allow a compiler to quickly come up with a temporary + variable without having to avoid symbol table conflicts.

    + +

    Reserved words in LLVM are very similar to reserved words in other + languages. There are keywords for different opcodes + ('add', + 'bitcast', + 'ret', etc...), for primitive type names + ('void', + 'i32', etc...), and others. These + reserved words cannot conflict with variable names, because none of them + start with a prefix character ('%' or '@').

    + +

    Here is an example of LLVM code to multiply the integer variable + '%X' by 8:

    + +

    The easy way:

    + +
    +
    +%result = mul i32 %X, 8
    +
    +
    + +

    After strength reduction:

    + +
    +
    +%result = shl i32 %X, i8 3
    +
    +
    + +

    And the hard way:

    + +
    +
    +%0 = add i32 %X, %X           ; yields {i32}:%0
    +%1 = add i32 %0, %0           ; yields {i32}:%1
    +%result = add i32 %1, %1
    +
    +
    + +

    This last way of multiplying %X by 8 illustrates several important + lexical features of LLVM:

    + +
      +
    1. Comments are delimited with a ';' and go until the end of + line.
    2. + +
    3. Unnamed temporaries are created when the result of a computation is not + assigned to a named value.
    4. + +
    5. Unnamed temporaries are numbered sequentially
    6. +
    + +

    It also shows a convention that we follow in this document. When + demonstrating instructions, we will follow an instruction with a comment that + defines the type and name of value produced. Comments are shown in italic + text.

    + +
    + + + + + + + + +
    + +

    LLVM programs are composed of "Module"s, each of which is a translation unit + of the input programs. Each module consists of functions, global variables, + and symbol table entries. Modules may be combined together with the LLVM + linker, which merges function (and global variable) definitions, resolves + forward declarations, and merges symbol table entries. Here is an example of + the "hello world" module:

    + +
    +
    +; Declare the string constant as a global constant.
    +@.LC0 = internal constant [13 x i8] c"hello world\0A\00"    ; [13 x i8]*
    +
    +; External declaration of the puts function
    +declare i32 @puts(i8 *)                                     ; i32(i8 *)* 
    +
    +; Definition of main function
    +define i32 @main() {                                        ; i32()* 
    +  ; Convert [13 x i8]* to i8  *...
    +  %cast210 = getelementptr [13 x i8]* @.LC0, i64 0, i64 0   ; i8 *
    +
    +  ; Call puts function to write out the string to stdout.
    +  call i32 @puts(i8 * %cast210)                             ; i32
    +  ret i32 0
    }
    +
    +
    + +

    This example is made up of a global variable named + ".LC0", an external declaration of the "puts" function, and + a function definition for + "main".

    + +

    In general, a module is made up of a list of global values, where both + functions and global variables are global values. Global values are + represented by a pointer to a memory location (in this case, a pointer to an + array of char, and a pointer to a function), and have one of the + following linkage types.

    + +
    + + + + +
    + +

    All Global Variables and Functions have one of the following types of + linkage:

    + +
    +
    private
    +
    Global values with private linkage are only directly accessible by objects + in the current module. In particular, linking code into a module with an + private global value may cause the private to be renamed as necessary to + avoid collisions. Because the symbol is private to the module, all + references can be updated. This doesn't show up in any symbol table in the + object file.
    + +
    linker_private
    +
    Similar to private, but the symbol is passed through the assembler and + removed by the linker after evaluation. Note that (unlike private + symbols) linker_private symbols are subject to coalescing by the linker: + weak symbols get merged and redefinitions are rejected. However, unlike + normal strong symbols, they are removed by the linker from the final + linked image (executable or dynamic library).
    + +
    internal
    +
    Similar to private, but the value shows as a local symbol + (STB_LOCAL in the case of ELF) in the object file. This + corresponds to the notion of the 'static' keyword in C.
    + +
    available_externally
    +
    Globals with "available_externally" linkage are never emitted + into the object file corresponding to the LLVM module. They exist to + allow inlining and other optimizations to take place given knowledge of + the definition of the global, which is known to be somewhere outside the + module. Globals with available_externally linkage are allowed to + be discarded at will, and are otherwise the same as linkonce_odr. + This linkage type is only allowed on definitions, not declarations.
    + +
    linkonce
    +
    Globals with "linkonce" linkage are merged with other globals of + the same name when linkage occurs. This is typically used to implement + inline functions, templates, or other code which must be generated in each + translation unit that uses it. Unreferenced linkonce globals are + allowed to be discarded.
    + +
    weak
    +
    "weak" linkage has the same merging semantics as + linkonce linkage, except that unreferenced globals with + weak linkage may not be discarded. This is used for globals that + are declared "weak" in C source code.
    + +
    common
    +
    "common" linkage is most similar to "weak" linkage, but + they are used for tentative definitions in C, such as "int X;" at + global scope. + Symbols with "common" linkage are merged in the same way as + weak symbols, and they may not be deleted if unreferenced. + common symbols may not have an explicit section, + must have a zero initializer, and may not be marked 'constant'. Functions and aliases may not + have common linkage.
    + + +
    appending
    +
    "appending" linkage may only be applied to global variables of + pointer to array type. When two global variables with appending linkage + are linked together, the two global arrays are appended together. This is + the LLVM, typesafe, equivalent of having the system linker append together + "sections" with identical names when .o files are linked.
    + +
    extern_weak
    +
    The semantics of this linkage follow the ELF object file model: the symbol + is weak until linked, if not linked, the symbol becomes null instead of + being an undefined reference.
    + +
    linkonce_odr
    +
    weak_odr
    +
    Some languages allow differing globals to be merged, such as two functions + with different semantics. Other languages, such as C++, ensure + that only equivalent globals are ever merged (the "one definition rule" - + "ODR"). Such languages can use the linkonce_odr + and weak_odr linkage types to indicate that the global will only + be merged with equivalent globals. These linkage types are otherwise the + same as their non-odr versions.
    + +
    externally visible:
    +
    If none of the above identifiers are used, the global is externally + visible, meaning that it participates in linkage and can be used to + resolve external symbol references.
    +
    + +

    The next two types of linkage are targeted for Microsoft Windows platform + only. They are designed to support importing (exporting) symbols from (to) + DLLs (Dynamic Link Libraries).

    + +
    +
    dllimport
    +
    "dllimport" linkage causes the compiler to reference a function + or variable via a global pointer to a pointer that is set up by the DLL + exporting the symbol. On Microsoft Windows targets, the pointer name is + formed by combining __imp_ and the function or variable + name.
    + +
    dllexport
    +
    "dllexport" linkage causes the compiler to provide a global + pointer to a pointer in a DLL, so that it can be referenced with the + dllimport attribute. On Microsoft Windows targets, the pointer + name is formed by combining __imp_ and the function or + variable name.
    +
    + +

    For example, since the ".LC0" variable is defined to be internal, if + another module defined a ".LC0" variable and was linked with this + one, one of the two would be renamed, preventing a collision. Since + "main" and "puts" are external (i.e., lacking any linkage + declarations), they are accessible outside of the current module.

    + +

    It is illegal for a function declaration to have any linkage type + other than "externally visible", dllimport + or extern_weak.

    + +

    Aliases can have only external, internal, weak + or weak_odr linkages.

    + +
    + + + + +
    + +

    LLVM functions, calls + and invokes can all have an optional calling + convention specified for the call. The calling convention of any pair of + dynamic caller/callee must match, or the behavior of the program is + undefined. The following calling conventions are supported by LLVM, and more + may be added in the future:

    + +
    +
    "ccc" - The C calling convention:
    +
    This calling convention (the default if no other calling convention is + specified) matches the target C calling conventions. This calling + convention supports varargs function calls and tolerates some mismatch in + the declared prototype and implemented declaration of the function (as + does normal C).
    + +
    "fastcc" - The fast calling convention:
    +
    This calling convention attempts to make calls as fast as possible + (e.g. by passing things in registers). This calling convention allows the + target to use whatever tricks it wants to produce fast code for the + target, without having to conform to an externally specified ABI + (Application Binary Interface). Implementations of this convention should + allow arbitrary tail call + optimization to be supported. This calling convention does not + support varargs and requires the prototype of all callees to exactly match + the prototype of the function definition.
    + +
    "coldcc" - The cold calling convention:
    +
    This calling convention attempts to make code in the caller as efficient + as possible under the assumption that the call is not commonly executed. + As such, these calls often preserve all registers so that the call does + not break any live ranges in the caller side. This calling convention + does not support varargs and requires the prototype of all callees to + exactly match the prototype of the function definition.
    + +
    "cc <n>" - Numbered convention:
    +
    Any calling convention may be specified by number, allowing + target-specific calling conventions to be used. Target specific calling + conventions start at 64.
    +
    + +

    More calling conventions can be added/defined on an as-needed basis, to + support Pascal conventions or any other well-known target-independent + convention.

    + +
    + + + + +
    + +

    All Global Variables and Functions have one of the following visibility + styles:

    + +
    +
    "default" - Default style:
    +
    On targets that use the ELF object file format, default visibility means + that the declaration is visible to other modules and, in shared libraries, + means that the declared entity may be overridden. On Darwin, default + visibility means that the declaration is visible to other modules. Default + visibility corresponds to "external linkage" in the language.
    + +
    "hidden" - Hidden style:
    +
    Two declarations of an object with hidden visibility refer to the same + object if they are in the same shared object. Usually, hidden visibility + indicates that the symbol will not be placed into the dynamic symbol + table, so no other module (executable or shared library) can reference it + directly.
    + +
    "protected" - Protected style:
    +
    On ELF, protected visibility indicates that the symbol will be placed in + the dynamic symbol table, but that references within the defining module + will bind to the local symbol. That is, the symbol cannot be overridden by + another module.
    +
    + +
    + + + + +
    + +

    LLVM IR allows you to specify name aliases for certain types. This can make + it easier to read the IR and make the IR more condensed (particularly when + recursive types are involved). An example of a name specification is:

    + +
    +
    +%mytype = type { %mytype*, i32 }
    +
    +
    + +

    You may give a name to any type except + "void". Type name aliases may be used anywhere a type + is expected with the syntax "%mytype".

    + +

    Note that type names are aliases for the structural type that they indicate, + and that you can therefore specify multiple names for the same type. This + often leads to confusing behavior when dumping out a .ll file. Since LLVM IR + uses structural typing, the name is not part of the type. When printing out + LLVM IR, the printer will pick one name to render all types of a + particular shape. This means that if you have code where two different + source types end up having the same LLVM type, that the dumper will sometimes + print the "wrong" or unexpected type. This is an important design point and + isn't going to change.

    + +
    + + + + +
    + +

    Global variables define regions of memory allocated at compilation time + instead of run-time. Global variables may optionally be initialized, may + have an explicit section to be placed in, and may have an optional explicit + alignment specified. A variable may be defined as "thread_local", which + means that it will not be shared by threads (each thread will have a + separated copy of the variable). A variable may be defined as a global + "constant," which indicates that the contents of the variable + will never be modified (enabling better optimization, allowing the + global data to be placed in the read-only section of an executable, etc). + Note that variables that need runtime initialization cannot be marked + "constant" as there is a store to the variable.

    + +

    LLVM explicitly allows declarations of global variables to be marked + constant, even if the final definition of the global is not. This capability + can be used to enable slightly better optimization of the program, but + requires the language definition to guarantee that optimizations based on the + 'constantness' are valid for the translation units that do not include the + definition.

    + +

    As SSA values, global variables define pointer values that are in scope + (i.e. they dominate) all basic blocks in the program. Global variables + always define a pointer to their "content" type because they describe a + region of memory, and all memory objects in LLVM are accessed through + pointers.

    + +

    A global variable may be declared to reside in a target-specific numbered + address space. For targets that support them, address spaces may affect how + optimizations are performed and/or what target instructions are used to + access the variable. The default address space is zero. The address space + qualifier must precede any other attributes.

    + +

    LLVM allows an explicit section to be specified for globals. If the target + supports it, it will emit globals to the section specified.

    + +

    An explicit alignment may be specified for a global. If not present, or if + the alignment is set to zero, the alignment of the global is set by the + target to whatever it feels convenient. If an explicit alignment is + specified, the global is forced to have at least that much alignment. All + alignments must be a power of 2.

    + +

    For example, the following defines a global in a numbered address space with + an initializer, section, and alignment:

    + +
    +
    +@G = addrspace(5) constant float 1.0, section "foo", align 4
    +
    +
    + +
    + + + + + +
    + +

    LLVM function definitions consist of the "define" keyord, an + optional linkage type, an optional + visibility style, an optional + calling convention, a return type, an optional + parameter attribute for the return type, a function + name, a (possibly empty) argument list (each with optional + parameter attributes), optional + function attributes, an optional section, an optional + alignment, an optional garbage collector name, an opening + curly brace, a list of basic blocks, and a closing curly brace.

    + +

    LLVM function declarations consist of the "declare" keyword, an + optional linkage type, an optional + visibility style, an optional + calling convention, a return type, an optional + parameter attribute for the return type, a function + name, a possibly empty list of arguments, an optional alignment, and an + optional garbage collector name.

    + +

    A function definition contains a list of basic blocks, forming the CFG + (Control Flow Graph) for the function. Each basic block may optionally start + with a label (giving the basic block a symbol table entry), contains a list + of instructions, and ends with a terminator + instruction (such as a branch or function return).

    + +

    The first basic block in a function is special in two ways: it is immediately + executed on entrance to the function, and it is not allowed to have + predecessor basic blocks (i.e. there can not be any branches to the entry + block of a function). Because the block can have no predecessors, it also + cannot have any PHI nodes.

    + +

    LLVM allows an explicit section to be specified for functions. If the target + supports it, it will emit functions to the section specified.

    + +

    An explicit alignment may be specified for a function. If not present, or if + the alignment is set to zero, the alignment of the function is set by the + target to whatever it feels convenient. If an explicit alignment is + specified, the function is forced to have at least that much alignment. All + alignments must be a power of 2.

    + +
    Syntax:
    +
    +
    +define [linkage] [visibility]
    +       [cconv] [ret attrs]
    +       <ResultType> @<FunctionName> ([argument list])
    +       [fn Attrs] [section "name"] [align N]
    +       [gc] { ... }
    +
    +
    + +
    + + +
    + Aliases +
    + +
    + +

    Aliases act as "second name" for the aliasee value (which can be either + function, global variable, another alias or bitcast of global value). Aliases + may have an optional linkage type, and an + optional visibility style.

    + +
    Syntax:
    +
    +
    +@<Name> = alias [Linkage] [Visibility] <AliaseeTy> @<Aliasee>
    +
    +
    + +
    + + + + +
    + +

    The return type and each parameter of a function type may have a set of + parameter attributes associated with them. Parameter attributes are + used to communicate additional information about the result or parameters of + a function. Parameter attributes are considered to be part of the function, + not of the function type, so functions with different parameter attributes + can have the same function type.

    + +

    Parameter attributes are simple keywords that follow the type specified. If + multiple parameter attributes are needed, they are space separated. For + example:

    + +
    +
    +declare i32 @printf(i8* noalias nocapture, ...)
    +declare i32 @atoi(i8 zeroext)
    +declare signext i8 @returns_signed_char()
    +
    +
    + +

    Note that any attributes for the function result (nounwind, + readonly) come immediately after the argument list.

    + +

    Currently, only the following parameter attributes are defined:

    + +
    +
    zeroext
    +
    This indicates to the code generator that the parameter or return value + should be zero-extended to a 32-bit value by the caller (for a parameter) + or the callee (for a return value).
    + +
    signext
    +
    This indicates to the code generator that the parameter or return value + should be sign-extended to a 32-bit value by the caller (for a parameter) + or the callee (for a return value).
    + +
    inreg
    +
    This indicates that this parameter or return value should be treated in a + special target-dependent fashion during while emitting code for a function + call or return (usually, by putting it in a register as opposed to memory, + though some targets use it to distinguish between two different kinds of + registers). Use of this attribute is target-specific.
    + +
    byval
    +
    This indicates that the pointer parameter should really be passed by value + to the function. The attribute implies that a hidden copy of the pointee + is made between the caller and the callee, so the callee is unable to + modify the value in the callee. This attribute is only valid on LLVM + pointer arguments. It is generally used to pass structs and arrays by + value, but is also valid on pointers to scalars. The copy is considered + to belong to the caller not the callee (for example, + readonly functions should not write to + byval parameters). This is not a valid attribute for return + values. The byval attribute also supports specifying an alignment with + the align attribute. This has a target-specific effect on the code + generator that usually indicates a desired alignment for the synthesized + stack slot.
    + +
    sret
    +
    This indicates that the pointer parameter specifies the address of a + structure that is the return value of the function in the source program. + This pointer must be guaranteed by the caller to be valid: loads and + stores to the structure may be assumed by the callee to not to trap. This + may only be applied to the first parameter. This is not a valid attribute + for return values.
    + +
    noalias
    +
    This indicates that the pointer does not alias any global or any other + parameter. The caller is responsible for ensuring that this is the + case. On a function return value, noalias additionally indicates + that the pointer does not alias any other pointers visible to the + caller. For further details, please see the discussion of the NoAlias + response in + alias + analysis.
    + +
    nocapture
    +
    This indicates that the callee does not make any copies of the pointer + that outlive the callee itself. This is not a valid attribute for return + values.
    + +
    nest
    +
    This indicates that the pointer parameter can be excised using the + trampoline intrinsics. This is not a valid + attribute for return values.
    +
    + +
    + + + + +
    + +

    Each function may specify a garbage collector name, which is simply a + string:

    + +
    +
    +define void @f() gc "name" { ... }
    +
    +
    + +

    The compiler declares the supported values of name. Specifying a + collector which will cause the compiler to alter its output in order to + support the named garbage collection algorithm.

    + +
    + + + + +
    + +

    Function attributes are set to communicate additional information about a + function. Function attributes are considered to be part of the function, not + of the function type, so functions with different parameter attributes can + have the same function type.

    + +

    Function attributes are simple keywords that follow the type specified. If + multiple attributes are needed, they are space separated. For example:

    + +
    +
    +define void @f() noinline { ... }
    +define void @f() alwaysinline { ... }
    +define void @f() alwaysinline optsize { ... }
    +define void @f() optsize { ... }
    +
    +
    + +
    +
    alwaysinline
    +
    This attribute indicates that the inliner should attempt to inline this + function into callers whenever possible, ignoring any active inlining size + threshold for this caller.
    + +
    inlinehint
    +
    This attribute indicates that the source code contained a hint that inlining + this function is desirable (such as the "inline" keyword in C/C++). It + is just a hint; it imposes no requirements on the inliner.
    + +
    noinline
    +
    This attribute indicates that the inliner should never inline this + function in any situation. This attribute may not be used together with + the alwaysinline attribute.
    + +
    optsize
    +
    This attribute suggests that optimization passes and code generator passes + make choices that keep the code size of this function low, and otherwise + do optimizations specifically to reduce code size.
    + +
    noreturn
    +
    This function attribute indicates that the function never returns + normally. This produces undefined behavior at runtime if the function + ever does dynamically return.
    + +
    nounwind
    +
    This function attribute indicates that the function never returns with an + unwind or exceptional control flow. If the function does unwind, its + runtime behavior is undefined.
    + +
    readnone
    +
    This attribute indicates that the function computes its result (or decides + to unwind an exception) based strictly on its arguments, without + dereferencing any pointer arguments or otherwise accessing any mutable + state (e.g. memory, control registers, etc) visible to caller functions. + It does not write through any pointer arguments + (including byval arguments) and never + changes any state visible to callers. This means that it cannot unwind + exceptions by calling the C++ exception throwing methods, but + could use the unwind instruction.
    + +
    readonly
    +
    This attribute indicates that the function does not write through any + pointer arguments (including byval + arguments) or otherwise modify any state (e.g. memory, control registers, + etc) visible to caller functions. It may dereference pointer arguments + and read state that may be set in the caller. A readonly function always + returns the same value (or unwinds an exception identically) when called + with the same set of arguments and global state. It cannot unwind an + exception by calling the C++ exception throwing methods, but may + use the unwind instruction.
    + +
    ssp
    +
    This attribute indicates that the function should emit a stack smashing + protector. It is in the form of a "canary"—a random value placed on + the stack before the local variables that's checked upon return from the + function to see if it has been overwritten. A heuristic is used to + determine if a function needs stack protectors or not.
    +
    + If a function that has an ssp attribute is inlined into a + function that doesn't have an ssp attribute, then the resulting + function will have an ssp attribute.
    + +
    sspreq
    +
    This attribute indicates that the function should always emit a + stack smashing protector. This overrides + the ssp function attribute.
    +
    + If a function that has an sspreq attribute is inlined into a + function that doesn't have an sspreq attribute or which has + an ssp attribute, then the resulting function will have + an sspreq attribute.
    + +
    noredzone
    +
    This attribute indicates that the code generator should not use a red + zone, even if the target-specific ABI normally permits it.
    + +
    noimplicitfloat
    +
    This attributes disables implicit floating point instructions.
    + +
    naked
    +
    This attribute disables prologue / epilogue emission for the function. + This can have very system-specific consequences.
    +
    + +
    + + + + +
    + +

    Modules may contain "module-level inline asm" blocks, which corresponds to + the GCC "file scope inline asm" blocks. These blocks are internally + concatenated by LLVM and treated as a single unit, but may be separated in + the .ll file if desired. The syntax is very simple:

    + +
    +
    +module asm "inline asm code goes here"
    +module asm "more can go here"
    +
    +
    + +

    The strings can contain any character by escaping non-printable characters. + The escape sequence used is simply "\xx" where "xx" is the two digit hex code + for the number.

    + +

    The inline asm code is simply printed to the machine code .s file when + assembly code is generated.

    + +
    + + + + +
    + +

    A module may specify a target specific data layout string that specifies how + data is to be laid out in memory. The syntax for the data layout is + simply:

    + +
    +
    +target datalayout = "layout specification"
    +
    +
    + +

    The layout specification consists of a list of specifications + separated by the minus sign character ('-'). Each specification starts with + a letter and may include other information after the letter to define some + aspect of the data layout. The specifications accepted are as follows:

    + +
    +
    E
    +
    Specifies that the target lays out data in big-endian form. That is, the + bits with the most significance have the lowest address location.
    + +
    e
    +
    Specifies that the target lays out data in little-endian form. That is, + the bits with the least significance have the lowest address + location.
    + +
    p:size:abi:pref
    +
    This specifies the size of a pointer and its abi and + preferred alignments. All sizes are in bits. Specifying + the pref alignment is optional. If omitted, the + preceding : should be omitted too.
    + +
    isize:abi:pref
    +
    This specifies the alignment for an integer type of a given bit + size. The value of size must be in the range [1,2^23).
    + +
    vsize:abi:pref
    +
    This specifies the alignment for a vector type of a given bit + size.
    + +
    fsize:abi:pref
    +
    This specifies the alignment for a floating point type of a given bit + size. The value of size must be either 32 (float) or 64 + (double).
    + +
    asize:abi:pref
    +
    This specifies the alignment for an aggregate type of a given bit + size.
    + +
    ssize:abi:pref
    +
    This specifies the alignment for a stack object of a given bit + size.
    + +
    nsize1:size2:size3...
    +
    This specifies a set of native integer widths for the target CPU + in bits. For example, it might contain "n32" for 32-bit PowerPC, + "n32:64" for PowerPC 64, or "n8:16:32:64" for X86-64. Elements of + this set are considered to support most general arithmetic + operations efficiently.
    +
    + +

    When constructing the data layout for a given target, LLVM starts with a + default set of specifications which are then (possibly) overriden by the + specifications in the datalayout keyword. The default specifications + are given in this list:

    + +
      +
    • E - big endian
    • +
    • p:32:64:64 - 32-bit pointers with 64-bit alignment
    • +
    • i1:8:8 - i1 is 8-bit (byte) aligned
    • +
    • i8:8:8 - i8 is 8-bit (byte) aligned
    • +
    • i16:16:16 - i16 is 16-bit aligned
    • +
    • i32:32:32 - i32 is 32-bit aligned
    • +
    • i64:32:64 - i64 has ABI alignment of 32-bits but preferred + alignment of 64-bits
    • +
    • f32:32:32 - float is 32-bit aligned
    • +
    • f64:64:64 - double is 64-bit aligned
    • +
    • v64:64:64 - 64-bit vector is 64-bit aligned
    • +
    • v128:128:128 - 128-bit vector is 128-bit aligned
    • +
    • a0:0:1 - aggregates are 8-bit aligned
    • +
    • s0:64:64 - stack objects are 64-bit aligned
    • +
    + +

    When LLVM is determining the alignment for a given type, it uses the + following rules:

    + +
      +
    1. If the type sought is an exact match for one of the specifications, that + specification is used.
    2. + +
    3. If no match is found, and the type sought is an integer type, then the + smallest integer type that is larger than the bitwidth of the sought type + is used. If none of the specifications are larger than the bitwidth then + the the largest integer type is used. For example, given the default + specifications above, the i7 type will use the alignment of i8 (next + largest) while both i65 and i256 will use the alignment of i64 (largest + specified).
    4. + +
    5. If no match is found, and the type sought is a vector type, then the + largest vector type that is smaller than the sought vector type will be + used as a fall back. This happens because <128 x double> can be + implemented in terms of 64 <2 x double>, for example.
    6. +
    + +
    + + + + +
    + +

    Any memory access must be done through a pointer value associated +with an address range of the memory access, otherwise the behavior +is undefined. Pointer values are associated with address ranges +according to the following rules:

    + +
      +
    • A pointer value formed from a + getelementptr instruction + is associated with the addresses associated with the first operand + of the getelementptr.
    • +
    • An address of a global variable is associated with the address + range of the variable's storage.
    • +
    • The result value of an allocation instruction is associated with + the address range of the allocated storage.
    • +
    • A null pointer in the default address-space is associated with + no address.
    • +
    • A pointer value formed by an + inttoptr is associated with all + address ranges of all pointer values that contribute (directly or + indirectly) to the computation of the pointer's value.
    • +
    • The result value of a + bitcast is associated with all + addresses associated with the operand of the bitcast.
    • +
    • An integer constant other than zero or a pointer value returned + from a function not defined within LLVM may be associated with address + ranges allocated through mechanisms other than those provided by + LLVM. Such ranges shall not overlap with any ranges of addresses + allocated by mechanisms provided by LLVM.
    • +
    + +

    LLVM IR does not associate types with memory. The result type of a +load merely indicates the size and +alignment of the memory from which to load, as well as the +interpretation of the value. The first operand of a +store similarly only indicates the size +and alignment of the store.

    + +

    Consequently, type-based alias analysis, aka TBAA, aka +-fstrict-aliasing, is not applicable to general unadorned +LLVM IR. Metadata may be used to encode +additional information which specialized optimization passes may use +to implement type-based alias analysis.

    + +
    + + + + + +
    + +

    The LLVM type system is one of the most important features of the + intermediate representation. Being typed enables a number of optimizations + to be performed on the intermediate representation directly, without having + to do extra analyses on the side before the transformation. A strong type + system makes it easier to read the generated code and enables novel analyses + and transformations that are not feasible to perform on normal three address + code representations.

    + +
    + + + + +
    + +

    The types fall into a few useful classifications:

    + + + + + + + + + + + + + + + + + + + + + + + + + +
    ClassificationTypes
    integeri1, i2, i3, ... i8, ... i16, ... i32, ... i64, ...
    floating pointfloat, double, x86_fp80, fp128, ppc_fp128
    first classinteger, + floating point, + pointer, + vector, + structure, + array, + label, + metadata. +
    primitivelabel, + void, + floating point, + metadata.
    derivedinteger, + array, + function, + pointer, + structure, + packed structure, + vector, + opaque. +
    + +

    The first class types are perhaps the most + important. Values of these types are the only ones which can be produced by + instructions.

    + +
    + + + + +
    + +

    The primitive types are the fundamental building blocks of the LLVM + system.

    + +
    + + + + +
    + +
    Overview:
    +

    The integer type is a very simple type that simply specifies an arbitrary + bit width for the integer type desired. Any bit width from 1 bit to + 223-1 (about 8 million) can be specified.

    + +
    Syntax:
    +
    +  iN
    +
    + +

    The number of bits the integer will occupy is specified by the N + value.

    + +
    Examples:
    + + + + + + + + + + + + + +
    i1a single-bit integer.
    i32a 32-bit integer.
    i1942652a really big integer of over 1 million bits.
    + +

    Note that the code generator does not yet support large integer types to be + used as function return types. The specific limit on how large a return type + the code generator can currently handle is target-dependent; currently it's + often 64 bits for 32-bit targets and 128 bits for 64-bit targets.

    + +
    + + + + +
    + + + + + + + + + + +
    TypeDescription
    float32-bit floating point value
    double64-bit floating point value
    fp128128-bit floating point value (112-bit mantissa)
    x86_fp8080-bit floating point value (X87)
    ppc_fp128128-bit floating point value (two 64-bits)
    + +
    + + + + +
    + +
    Overview:
    +

    The void type does not represent any value and has no size.

    + +
    Syntax:
    +
    +  void
    +
    + +
    + + + + +
    + +
    Overview:
    +

    The label type represents code labels.

    + +
    Syntax:
    +
    +  label
    +
    + +
    + + + + +
    + +
    Overview:
    +

    The metadata type represents embedded metadata. No derived types may be + created from metadata except for function + arguments. + +

    Syntax:
    +
    +  metadata
    +
    + +
    + + + + + +
    + +

    The real power in LLVM comes from the derived types in the system. This is + what allows a programmer to represent arrays, functions, pointers, and other + useful types. Each of these types contain one or more element types which + may be a primitive type, or another derived type. For example, it is + possible to have a two dimensional array, using an array as the element type + of another array.

    + +
    + + + + +
    + +
    Overview:
    +

    The array type is a very simple derived type that arranges elements + sequentially in memory. The array type requires a size (number of elements) + and an underlying data type.

    + +
    Syntax:
    +
    +  [<# elements> x <elementtype>]
    +
    + +

    The number of elements is a constant integer value; elementtype may + be any type with a size.

    + +
    Examples:
    + + + + + + + + + + + + + +
    [40 x i32]Array of 40 32-bit integer values.
    [41 x i32]Array of 41 32-bit integer values.
    [4 x i8]Array of 4 8-bit integer values.
    +

    Here are some examples of multidimensional arrays:

    + + + + + + + + + + + + + +
    [3 x [4 x i32]]3x4 array of 32-bit integer values.
    [12 x [10 x float]]12x10 array of single precision floating point values.
    [2 x [3 x [4 x i16]]]2x3x4 array of 16-bit integer values.
    + +

    There is no restriction on indexing beyond the end of the array implied by + a static type (though there are restrictions on indexing beyond the bounds + of an allocated object in some cases). This means that single-dimension + 'variable sized array' addressing can be implemented in LLVM with a zero + length array type. An implementation of 'pascal style arrays' in LLVM could + use the type "{ i32, [0 x float]}", for example.

    + +

    Note that the code generator does not yet support large aggregate types to be + used as function return types. The specific limit on how large an aggregate + return type the code generator can currently handle is target-dependent, and + also dependent on the aggregate element types.

    + +
    + + + + +
    + +
    Overview:
    +

    The function type can be thought of as a function signature. It consists of + a return type and a list of formal parameter types. The return type of a + function type is a scalar type, a void type, or a struct type. If the return + type is a struct type then all struct elements must be of first class types, + and the struct must have at least one element.

    + +
    Syntax:
    +
    +  <returntype> (<parameter list>)
    +
    + +

    ...where '<parameter list>' is a comma-separated list of type + specifiers. Optionally, the parameter list may include a type ..., + which indicates that the function takes a variable number of arguments. + Variable argument functions can access their arguments with + the variable argument handling intrinsic + functions. '<returntype>' is a any type except + label.

    + +
    Examples:
    + + + + + + + + + + + + + + +
    i32 (i32)function taking an i32, returning an i32 +
    float (i16 signext, i32 *) * + Pointer to a function that takes + an i16 that should be sign extended and a + pointer to i32, returning + float. +
    i32 (i8*, ...)A vararg function that takes at least one + pointer to i8 (char in C), + which returns an integer. This is the signature for printf in + LLVM. +
    {i32, i32} (i32)A function taking an i32, returning a + structure containing two i32 values +
    + +
    + + + + +
    + +
    Overview:
    +

    The structure type is used to represent a collection of data members together + in memory. The packing of the field types is defined to match the ABI of the + underlying processor. The elements of a structure may be any type that has a + size.

    + +

    Structures are accessed using 'load and + 'store' by getting a pointer to a field with + the 'getelementptr' instruction.

    + +
    Syntax:
    +
    +  { <type list> }
    +
    + +
    Examples:
    + + + + + + + + +
    { i32, i32, i32 }A triple of three i32 values
    { float, i32 (i32) * }A pair, where the first element is a float and the + second element is a pointer to a + function that takes an i32, returning + an i32.
    + +

    Note that the code generator does not yet support large aggregate types to be + used as function return types. The specific limit on how large an aggregate + return type the code generator can currently handle is target-dependent, and + also dependent on the aggregate element types.

    + +
    + + + + +
    + +
    Overview:
    +

    The packed structure type is used to represent a collection of data members + together in memory. There is no padding between fields. Further, the + alignment of a packed structure is 1 byte. The elements of a packed + structure may be any type that has a size.

    + +

    Structures are accessed using 'load and + 'store' by getting a pointer to a field with + the 'getelementptr' instruction.

    + +
    Syntax:
    +
    +  < { <type list> } >
    +
    + +
    Examples:
    + + + + + + + + +
    < { i32, i32, i32 } >A triple of three i32 values
    +< { float, i32 (i32)* } >A pair, where the first element is a float and the + second element is a pointer to a + function that takes an i32, returning + an i32.
    + +
    + + + + +
    + +
    Overview:
    +

    As in many languages, the pointer type represents a pointer or reference to + another object, which must live in memory. Pointer types may have an optional + address space attribute defining the target-specific numbered address space + where the pointed-to object resides. The default address space is zero.

    + +

    Note that LLVM does not permit pointers to void (void*) nor does it + permit pointers to labels (label*). Use i8* instead.

    + +
    Syntax:
    +
    +  <type> *
    +
    + +
    Examples:
    + + + + + + + + + + + + + +
    [4 x i32]*A pointer to array of four i32 values.
    i32 (i32 *) * A pointer to a function that takes an i32*, returning an + i32.
    i32 addrspace(5)*A pointer to an i32 value + that resides in address space #5.
    + +
    + + + + +
    + +
    Overview:
    +

    A vector type is a simple derived type that represents a vector of elements. + Vector types are used when multiple primitive data are operated in parallel + using a single instruction (SIMD). A vector type requires a size (number of + elements) and an underlying primitive data type. Vectors must have a power + of two length (1, 2, 4, 8, 16 ...). Vector types are considered + first class.

    + +
    Syntax:
    +
    +  < <# elements> x <elementtype> >
    +
    + +

    The number of elements is a constant integer value; elementtype may be any + integer or floating point type.

    + +
    Examples:
    + + + + + + + + + + + + + +
    <4 x i32>Vector of 4 32-bit integer values.
    <8 x float>Vector of 8 32-bit floating-point values.
    <2 x i64>Vector of 2 64-bit integer values.
    + +

    Note that the code generator does not yet support large vector types to be + used as function return types. The specific limit on how large a vector + return type codegen can currently handle is target-dependent; currently it's + often a few times longer than a hardware vector register.

    + +
    + + + +
    + +
    Overview:
    +

    Opaque types are used to represent unknown types in the system. This + corresponds (for example) to the C notion of a forward declared structure + type. In LLVM, opaque types can eventually be resolved to any type (not just + a structure type).

    + +
    Syntax:
    +
    +  opaque
    +
    + +
    Examples:
    + + + + + +
    opaqueAn opaque type.
    + +
    + + + + +
    + +
    Overview:
    +

    An "up reference" allows you to refer to a lexically enclosing type without + requiring it to have a name. For instance, a structure declaration may + contain a pointer to any of the types it is lexically a member of. Example + of up references (with their equivalent as named type declarations) + include:

    + +
    +   { \2 * }                %x = type { %x* }
    +   { \2 }*                 %y = type { %y }*
    +   \1*                     %z = type %z*
    +
    + +

    An up reference is needed by the asmprinter for printing out cyclic types + when there is no declared name for a type in the cycle. Because the + asmprinter does not want to print out an infinite type string, it needs a + syntax to handle recursive types that have no names (all names are optional + in llvm IR).

    + +
    Syntax:
    +
    +   \<level>
    +
    + +

    The level is the count of the lexical type that is being referred to.

    + +
    Examples:
    + + + + + + + + + +
    \1*Self-referential pointer.
    { { \3*, i8 }, i32 }Recursive structure where the upref refers to the out-most + structure.
    + +
    + + + + + +
    + +

    LLVM has several different basic types of constants. This section describes + them all and their syntax.

    + +
    + + + + +
    + +
    +
    Boolean constants
    +
    The two strings 'true' and 'false' are both valid + constants of the i1 type.
    + +
    Integer constants
    +
    Standard integers (such as '4') are constants of + the integer type. Negative numbers may be used + with integer types.
    + +
    Floating point constants
    +
    Floating point constants use standard decimal notation (e.g. 123.421), + exponential notation (e.g. 1.23421e+2), or a more precise hexadecimal + notation (see below). The assembler requires the exact decimal value of a + floating-point constant. For example, the assembler accepts 1.25 but + rejects 1.3 because 1.3 is a repeating decimal in binary. Floating point + constants must have a floating point type.
    + +
    Null pointer constants
    +
    The identifier 'null' is recognized as a null pointer constant + and must be of pointer type.
    +
    + +

    The one non-intuitive notation for constants is the hexadecimal form of + floating point constants. For example, the form 'double + 0x432ff973cafa8000' is equivalent to (but harder to read than) + 'double 4.5e+15'. The only time hexadecimal floating point + constants are required (and the only time that they are generated by the + disassembler) is when a floating point constant must be emitted but it cannot + be represented as a decimal floating point number in a reasonable number of + digits. For example, NaN's, infinities, and other special values are + represented in their IEEE hexadecimal format so that assembly and disassembly + do not cause any bits to change in the constants.

    + +

    When using the hexadecimal form, constants of types float and double are + represented using the 16-digit form shown above (which matches the IEEE754 + representation for double); float values must, however, be exactly + representable as IEE754 single precision. Hexadecimal format is always used + for long double, and there are three forms of long double. The 80-bit format + used by x86 is represented as 0xK followed by 20 hexadecimal digits. + The 128-bit format used by PowerPC (two adjacent doubles) is represented + by 0xM followed by 32 hexadecimal digits. The IEEE 128-bit format + is represented by 0xL followed by 32 hexadecimal digits; no + currently supported target uses this format. Long doubles will only work if + they match the long double format on your target. All hexadecimal formats + are big-endian (sign bit at the left).

    + +
    + + + + +
    + +

    Complex constants are a (potentially recursive) combination of simple + constants and smaller complex constants.

    + +
    +
    Structure constants
    +
    Structure constants are represented with notation similar to structure + type definitions (a comma separated list of elements, surrounded by braces + ({})). For example: "{ i32 4, float 17.0, i32* @G }", + where "@G" is declared as "@G = external global i32". + Structure constants must have structure type, and + the number and types of elements must match those specified by the + type.
    + +
    Array constants
    +
    Array constants are represented with notation similar to array type + definitions (a comma separated list of elements, surrounded by square + brackets ([])). For example: "[ i32 42, i32 11, i32 74 + ]". Array constants must have array type, and + the number and types of elements must match those specified by the + type.
    + +
    Vector constants
    +
    Vector constants are represented with notation similar to vector type + definitions (a comma separated list of elements, surrounded by + less-than/greater-than's (<>)). For example: "< i32 + 42, i32 11, i32 74, i32 100 >". Vector constants must + have vector type, and the number and types of + elements must match those specified by the type.
    + +
    Zero initialization
    +
    The string 'zeroinitializer' can be used to zero initialize a + value to zero of any type, including scalar and aggregate types. + This is often used to avoid having to print large zero initializers + (e.g. for large arrays) and is always exactly equivalent to using explicit + zero initializers.
    + +
    Metadata node
    +
    A metadata node is a structure-like constant with + metadata type. For example: "metadata !{ + i32 0, metadata !"test" }". Unlike other constants that are meant to + be interpreted as part of the instruction stream, metadata is a place to + attach additional information such as debug info.
    +
    + +
    + + + + +
    + +

    The addresses of global variables + and functions are always implicitly valid + (link-time) constants. These constants are explicitly referenced when + the identifier for the global is used and always + have pointer type. For example, the following is a + legal LLVM file:

    + +
    +
    +@X = global i32 17
    +@Y = global i32 42
    +@Z = global [2 x i32*] [ i32* @X, i32* @Y ]
    +
    +
    + +
    + + + +
    + +

    The string 'undef' can be used anywhere a constant is expected, and + indicates that the user of the value may receive an unspecified bit-pattern. + Undefined values may be of any type (other than label or void) and be used + anywhere a constant is permitted.

    + +

    Undefined values are useful because they indicate to the compiler that the + program is well defined no matter what value is used. This gives the + compiler more freedom to optimize. Here are some examples of (potentially + surprising) transformations that are valid (in pseudo IR):

    + + +
    +
    +  %A = add %X, undef
    +  %B = sub %X, undef
    +  %C = xor %X, undef
    +Safe:
    +  %A = undef
    +  %B = undef
    +  %C = undef
    +
    +
    + +

    This is safe because all of the output bits are affected by the undef bits. +Any output bit can have a zero or one depending on the input bits.

    + +
    +
    +  %A = or %X, undef
    +  %B = and %X, undef
    +Safe:
    +  %A = -1
    +  %B = 0
    +Unsafe:
    +  %A = undef
    +  %B = undef
    +
    +
    + +

    These logical operations have bits that are not always affected by the input. +For example, if "%X" has a zero bit, then the output of the 'and' operation will +always be a zero, no matter what the corresponding bit from the undef is. As +such, it is unsafe to optimize or assume that the result of the and is undef. +However, it is safe to assume that all bits of the undef could be 0, and +optimize the and to 0. Likewise, it is safe to assume that all the bits of +the undef operand to the or could be set, allowing the or to be folded to +-1.

    + +
    +
    +  %A = select undef, %X, %Y
    +  %B = select undef, 42, %Y
    +  %C = select %X, %Y, undef
    +Safe:
    +  %A = %X     (or %Y)
    +  %B = 42     (or %Y)
    +  %C = %Y
    +Unsafe:
    +  %A = undef
    +  %B = undef
    +  %C = undef
    +
    +
    + +

    This set of examples show that undefined select (and conditional branch) +conditions can go "either way" but they have to come from one of the two +operands. In the %A example, if %X and %Y were both known to have a clear low +bit, then %A would have to have a cleared low bit. However, in the %C example, +the optimizer is allowed to assume that the undef operand could be the same as +%Y, allowing the whole select to be eliminated.

    + + +
    +
    +  %A = xor undef, undef
    +  
    +  %B = undef
    +  %C = xor %B, %B
    +
    +  %D = undef
    +  %E = icmp lt %D, 4
    +  %F = icmp gte %D, 4
    +
    +Safe:
    +  %A = undef
    +  %B = undef
    +  %C = undef
    +  %D = undef
    +  %E = undef
    +  %F = undef
    +
    +
    + +

    This example points out that two undef operands are not necessarily the same. +This can be surprising to people (and also matches C semantics) where they +assume that "X^X" is always zero, even if X is undef. This isn't true for a +number of reasons, but the short answer is that an undef "variable" can +arbitrarily change its value over its "live range". This is true because the +"variable" doesn't actually have a live range. Instead, the value is +logically read from arbitrary registers that happen to be around when needed, +so the value is not necessarily consistent over time. In fact, %A and %C need +to have the same semantics or the core LLVM "replace all uses with" concept +would not hold.

    + +
    +
    +  %A = fdiv undef, %X
    +  %B = fdiv %X, undef
    +Safe:
    +  %A = undef
    +b: unreachable
    +
    +
    + +

    These examples show the crucial difference between an undefined +value and undefined behavior. An undefined value (like undef) is +allowed to have an arbitrary bit-pattern. This means that the %A operation +can be constant folded to undef because the undef could be an SNaN, and fdiv is +not (currently) defined on SNaN's. However, in the second example, we can make +a more aggressive assumption: because the undef is allowed to be an arbitrary +value, we are allowed to assume that it could be zero. Since a divide by zero +has undefined behavior, we are allowed to assume that the operation +does not execute at all. This allows us to delete the divide and all code after +it: since the undefined operation "can't happen", the optimizer can assume that +it occurs in dead code. +

    + +
    +
    +a:  store undef -> %X
    +b:  store %X -> undef
    +Safe:
    +a: <deleted>
    +b: unreachable
    +
    +
    + +

    These examples reiterate the fdiv example: a store "of" an undefined value +can be assumed to not have any effect: we can assume that the value is +overwritten with bits that happen to match what was already there. However, a +store "to" an undefined location could clobber arbitrary memory, therefore, it +has undefined behavior.

    + +
    + + + +
    + +

    blockaddress(@function, %block)

    + +

    The 'blockaddress' constant computes the address of the specified + basic block in the specified function, and always has an i8* type. Taking + the address of the entry block is illegal.

    + +

    This value only has defined behavior when used as an operand to the + 'indirectbr' instruction or for comparisons + against null. Pointer equality tests between labels addresses is undefined + behavior - though, again, comparison against null is ok, and no label is + equal to the null pointer. This may also be passed around as an opaque + pointer sized value as long as the bits are not inspected. This allows + ptrtoint and arithmetic to be performed on these values so long as + the original value is reconstituted before the indirectbr.

    + +

    Finally, some targets may provide defined semantics when + using the value as the operand to an inline assembly, but that is target + specific. +

    + +
    + + + + + +
    + +

    Constant expressions are used to allow expressions involving other constants + to be used as constants. Constant expressions may be of + any first class type and may involve any LLVM + operation that does not have side effects (e.g. load and call are not + supported). The following is the syntax for constant expressions:

    + +
    +
    trunc ( CST to TYPE )
    +
    Truncate a constant to another type. The bit size of CST must be larger + than the bit size of TYPE. Both types must be integers.
    + +
    zext ( CST to TYPE )
    +
    Zero extend a constant to another type. The bit size of CST must be + smaller or equal to the bit size of TYPE. Both types must be + integers.
    + +
    sext ( CST to TYPE )
    +
    Sign extend a constant to another type. The bit size of CST must be + smaller or equal to the bit size of TYPE. Both types must be + integers.
    + +
    fptrunc ( CST to TYPE )
    +
    Truncate a floating point constant to another floating point type. The + size of CST must be larger than the size of TYPE. Both types must be + floating point.
    + +
    fpext ( CST to TYPE )
    +
    Floating point extend a constant to another type. The size of CST must be + smaller or equal to the size of TYPE. Both types must be floating + point.
    + +
    fptoui ( CST to TYPE )
    +
    Convert a floating point constant to the corresponding unsigned integer + constant. TYPE must be a scalar or vector integer type. CST must be of + scalar or vector floating point type. Both CST and TYPE must be scalars, + or vectors of the same number of elements. If the value won't fit in the + integer type, the results are undefined.
    + +
    fptosi ( CST to TYPE )
    +
    Convert a floating point constant to the corresponding signed integer + constant. TYPE must be a scalar or vector integer type. CST must be of + scalar or vector floating point type. Both CST and TYPE must be scalars, + or vectors of the same number of elements. If the value won't fit in the + integer type, the results are undefined.
    + +
    uitofp ( CST to TYPE )
    +
    Convert an unsigned integer constant to the corresponding floating point + constant. TYPE must be a scalar or vector floating point type. CST must be + of scalar or vector integer type. Both CST and TYPE must be scalars, or + vectors of the same number of elements. If the value won't fit in the + floating point type, the results are undefined.
    + +
    sitofp ( CST to TYPE )
    +
    Convert a signed integer constant to the corresponding floating point + constant. TYPE must be a scalar or vector floating point type. CST must be + of scalar or vector integer type. Both CST and TYPE must be scalars, or + vectors of the same number of elements. If the value won't fit in the + floating point type, the results are undefined.
    + +
    ptrtoint ( CST to TYPE )
    +
    Convert a pointer typed constant to the corresponding integer constant + TYPE must be an integer type. CST must be of pointer + type. The CST value is zero extended, truncated, or unchanged to + make it fit in TYPE.
    + +
    inttoptr ( CST to TYPE )
    +
    Convert a integer constant to a pointer constant. TYPE must be a pointer + type. CST must be of integer type. The CST value is zero extended, + truncated, or unchanged to make it fit in a pointer size. This one is + really dangerous!
    + +
    bitcast ( CST to TYPE )
    +
    Convert a constant, CST, to another TYPE. The constraints of the operands + are the same as those for the bitcast + instruction.
    + +
    getelementptr ( CSTPTR, IDX0, IDX1, ... )
    +
    getelementptr inbounds ( CSTPTR, IDX0, IDX1, ... )
    +
    Perform the getelementptr operation on + constants. As with the getelementptr + instruction, the index list may have zero or more indexes, which are + required to make sense for the type of "CSTPTR".
    + +
    select ( COND, VAL1, VAL2 )
    +
    Perform the select operation on constants.
    + +
    icmp COND ( VAL1, VAL2 )
    +
    Performs the icmp operation on constants.
    + +
    fcmp COND ( VAL1, VAL2 )
    +
    Performs the fcmp operation on constants.
    + +
    extractelement ( VAL, IDX )
    +
    Perform the extractelement operation on + constants.
    + +
    insertelement ( VAL, ELT, IDX )
    +
    Perform the insertelement operation on + constants.
    + +
    shufflevector ( VEC1, VEC2, IDXMASK )
    +
    Perform the shufflevector operation on + constants.
    + +
    OPCODE ( LHS, RHS )
    +
    Perform the specified operation of the LHS and RHS constants. OPCODE may + be any of the binary + or bitwise binary operations. The constraints + on operands are the same as those for the corresponding instruction + (e.g. no bitwise operations on floating point values are allowed).
    +
    + +
    + + + + +
    + +

    Embedded metadata provides a way to attach arbitrary data to the instruction + stream without affecting the behaviour of the program. There are two + metadata primitives, strings and nodes. All metadata has the + metadata type and is identified in syntax by a preceding exclamation + point ('!').

    + +

    A metadata string is a string surrounded by double quotes. It can contain + any character by escaping non-printable characters with "\xx" where "xx" is + the two digit hex code. For example: "!"test\00"".

    + +

    Metadata nodes are represented with notation similar to structure constants + (a comma separated list of elements, surrounded by braces and preceded by an + exclamation point). For example: "!{ metadata !"test\00", i32 + 10}".

    + +

    A metadata node will attempt to track changes to the values it holds. In the + event that a value is deleted, it will be replaced with a typeless + "null", such as "metadata !{null, i32 10}".

    + +

    Optimizations may rely on metadata to provide additional information about + the program that isn't available in the instructions, or that isn't easily + computable. Similarly, the code generator may expect a certain metadata + format to be used to express debugging information.

    + +
    + + + + + + + + +
    + +

    LLVM supports inline assembler expressions (as opposed + to Module-Level Inline Assembly) through the use of + a special value. This value represents the inline assembler as a string + (containing the instructions to emit), a list of operand constraints (stored + as a string), a flag that indicates whether or not the inline asm + expression has side effects, and a flag indicating whether the function + containing the asm needs to align its stack conservatively. An example + inline assembler expression is:

    + +
    +
    +i32 (i32) asm "bswap $0", "=r,r"
    +
    +
    + +

    Inline assembler expressions may only be used as the callee operand of + a call instruction. Thus, typically we + have:

    + +
    +
    +%X = call i32 asm "bswap $0", "=r,r"(i32 %Y)
    +
    +
    + +

    Inline asms with side effects not visible in the constraint list must be + marked as having side effects. This is done through the use of the + 'sideeffect' keyword, like so:

    + +
    +
    +call void asm sideeffect "eieio", ""()
    +
    +
    + +

    In some cases inline asms will contain code that will not work unless the + stack is aligned in some way, such as calls or SSE instructions on x86, + yet will not contain code that does that alignment within the asm. + The compiler should make conservative assumptions about what the asm might + contain and should generate its usual stack alignment code in the prologue + if the 'alignstack' keyword is present:

    + +
    +
    +call void asm alignstack "eieio", ""()
    +
    +
    + +

    If both keywords appear the 'sideeffect' keyword must come + first.

    + +

    TODO: The format of the asm and constraints string still need to be + documented here. Constraints on what can be done (e.g. duplication, moving, + etc need to be documented). This is probably best done by reference to + another document that covers inline asm from a holistic perspective.

    + +
    + + + + + + +

    LLVM has a number of "magic" global variables that contain data that affect +code generation or other IR semantics. These are documented here. All globals +of this sort should have a section specified as "llvm.metadata". This +section and all globals that start with "llvm." are reserved for use +by LLVM.

    + + + + +
    + +

    The @llvm.used global is an array with i8* element type which has appending linkage. This array contains a list of +pointers to global variables and functions which may optionally have a pointer +cast formed of bitcast or getelementptr. For example, a legal use of it is:

    + +
    +  @X = global i8 4
    +  @Y = global i32 123
    +
    +  @llvm.used = appending global [2 x i8*] [
    +     i8* @X,
    +     i8* bitcast (i32* @Y to i8*)
    +  ], section "llvm.metadata"
    +
    + +

    If a global variable appears in the @llvm.used list, then the +compiler, assembler, and linker are required to treat the symbol as if there is +a reference to the global that it cannot see. For example, if a variable has +internal linkage and no references other than that from the @llvm.used +list, it cannot be deleted. This is commonly used to represent references from +inline asms and other things the compiler cannot "see", and corresponds to +"attribute((used))" in GNU C.

    + +

    On some targets, the code generator must emit a directive to the assembler or +object file to prevent the assembler and linker from molesting the symbol.

    + +
    + + + + +
    + +

    The @llvm.compiler.used directive is the same as the +@llvm.used directive, except that it only prevents the compiler from +touching the symbol. On targets that support it, this allows an intelligent +linker to optimize references to the symbol without being impeded as it would be +by @llvm.used.

    + +

    This is a rare construct that should only be used in rare circumstances, and +should not be exposed to source languages.

    + +
    + + + + +
    + +

    TODO: Describe this.

    + +
    + + + + +
    + +

    TODO: Describe this.

    + +
    + + + + + + +
    + +

    The LLVM instruction set consists of several different classifications of + instructions: terminator + instructions, binary instructions, + bitwise binary instructions, + memory instructions, and + other instructions.

    + +
    + + + + +
    + +

    As mentioned previously, every basic block + in a program ends with a "Terminator" instruction, which indicates which + block should be executed after the current block is finished. These + terminator instructions typically yield a 'void' value: they produce + control flow, not values (the one exception being the + 'invoke' instruction).

    + +

    There are six different terminator instructions: the + 'ret' instruction, the + 'br' instruction, the + 'switch' instruction, the + ''indirectbr' Instruction, the + 'invoke' instruction, the + 'unwind' instruction, and the + 'unreachable' instruction.

    + +
    + + + + +
    + +
    Syntax:
    +
    +  ret <type> <value>       ; Return a value from a non-void function
    +  ret void                 ; Return from void function
    +
    + +
    Overview:
    +

    The 'ret' instruction is used to return control flow (and optionally + a value) from a function back to the caller.

    + +

    There are two forms of the 'ret' instruction: one that returns a + value and then causes control flow, and one that just causes control flow to + occur.

    + +
    Arguments:
    +

    The 'ret' instruction optionally accepts a single argument, the + return value. The type of the return value must be a + 'first class' type.

    + +

    A function is not well formed if it it has a + non-void return type and contains a 'ret' instruction with no return + value or a return value with a type that does not match its type, or if it + has a void return type and contains a 'ret' instruction with a + return value.

    + +
    Semantics:
    +

    When the 'ret' instruction is executed, control flow returns back to + the calling function's context. If the caller is a + "call" instruction, execution continues at the + instruction after the call. If the caller was an + "invoke" instruction, execution continues at + the beginning of the "normal" destination block. If the instruction returns + a value, that value shall set the call or invoke instruction's return + value.

    + +
    Example:
    +
    +  ret i32 5                       ; Return an integer value of 5
    +  ret void                        ; Return from a void function
    +  ret { i32, i8 } { i32 4, i8 2 } ; Return a struct of values 4 and 2
    +
    + +

    Note that the code generator does not yet fully support large + return values. The specific sizes that are currently supported are + dependent on the target. For integers, on 32-bit targets the limit + is often 64 bits, and on 64-bit targets the limit is often 128 bits. + For aggregate types, the current limits are dependent on the element + types; for example targets are often limited to 2 total integer + elements and 2 total floating-point elements.

    + +
    + + + +
    + +
    Syntax:
    +
    +  br i1 <cond>, label <iftrue>, label <iffalse>
    br label <dest> ; Unconditional branch +
    + +
    Overview:
    +

    The 'br' instruction is used to cause control flow to transfer to a + different basic block in the current function. There are two forms of this + instruction, corresponding to a conditional branch and an unconditional + branch.

    + +
    Arguments:
    +

    The conditional branch form of the 'br' instruction takes a single + 'i1' value and two 'label' values. The unconditional form + of the 'br' instruction takes a single 'label' value as a + target.

    + +
    Semantics:
    +

    Upon execution of a conditional 'br' instruction, the 'i1' + argument is evaluated. If the value is true, control flows to the + 'iftrue' label argument. If "cond" is false, + control flows to the 'iffalse' label argument.

    + +
    Example:
    +
    +Test:
    +  %cond = icmp eq i32 %a, %b
    +  br i1 %cond, label %IfEqual, label %IfUnequal
    +IfEqual:
    +  ret i32 1
    +IfUnequal:
    +  ret i32 0
    +
    + +
    + + + + +
    + +
    Syntax:
    +
    +  switch <intty> <value>, label <defaultdest> [ <intty> <val>, label <dest> ... ]
    +
    + +
    Overview:
    +

    The 'switch' instruction is used to transfer control flow to one of + several different places. It is a generalization of the 'br' + instruction, allowing a branch to occur to one of many possible + destinations.

    + +
    Arguments:
    +

    The 'switch' instruction uses three parameters: an integer + comparison value 'value', a default 'label' destination, + and an array of pairs of comparison value constants and 'label's. + The table is not allowed to contain duplicate constant entries.

    + +
    Semantics:
    +

    The switch instruction specifies a table of values and + destinations. When the 'switch' instruction is executed, this table + is searched for the given value. If the value is found, control flow is + transferred to the corresponding destination; otherwise, control flow is + transferred to the default destination.

    + +
    Implementation:
    +

    Depending on properties of the target machine and the particular + switch instruction, this instruction may be code generated in + different ways. For example, it could be generated as a series of chained + conditional branches or with a lookup table.

    + +
    Example:
    +
    + ; Emulate a conditional br instruction
    + %Val = zext i1 %value to i32
    + switch i32 %Val, label %truedest [ i32 0, label %falsedest ]
    +
    + ; Emulate an unconditional br instruction
    + switch i32 0, label %dest [ ]
    +
    + ; Implement a jump table:
    + switch i32 %val, label %otherwise [ i32 0, label %onzero
    +                                     i32 1, label %onone
    +                                     i32 2, label %ontwo ]
    +
    + +
    + + + + + +
    + +
    Syntax:
    +
    +  indirectbr <somety>* <address>, [ label <dest1>, label <dest2>, ... ]
    +
    + +
    Overview:
    + +

    The 'indirectbr' instruction implements an indirect branch to a label + within the current function, whose address is specified by + "address". Address must be derived from a blockaddress constant.

    + +
    Arguments:
    + +

    The 'address' argument is the address of the label to jump to. The + rest of the arguments indicate the full set of possible destinations that the + address may point to. Blocks are allowed to occur multiple times in the + destination list, though this isn't particularly useful.

    + +

    This destination list is required so that dataflow analysis has an accurate + understanding of the CFG.

    + +
    Semantics:
    + +

    Control transfers to the block specified in the address argument. All + possible destination blocks must be listed in the label list, otherwise this + instruction has undefined behavior. This implies that jumps to labels + defined in other functions have undefined behavior as well.

    + +
    Implementation:
    + +

    This is typically implemented with a jump through a register.

    + +
    Example:
    +
    + indirectbr i8* %Addr, [ label %bb1, label %bb2, label %bb3 ]
    +
    + +
    + + + + + +
    + +
    Syntax:
    +
    +  <result> = invoke [cconv] [ret attrs] <ptr to function ty> <function ptr val>(<function args>) [fn attrs]
    +                to label <normal label> unwind label <exception label>
    +
    + +
    Overview:
    +

    The 'invoke' instruction causes control to transfer to a specified + function, with the possibility of control flow transfer to either the + 'normal' label or the 'exception' label. If the callee + function returns with the "ret" instruction, + control flow will return to the "normal" label. If the callee (or any + indirect callees) returns with the "unwind" + instruction, control is interrupted and continued at the dynamically nearest + "exception" label.

    + +
    Arguments:
    +

    This instruction requires several arguments:

    + +
      +
    1. The optional "cconv" marker indicates which calling + convention the call should use. If none is specified, the call + defaults to using C calling conventions.
    2. + +
    3. The optional Parameter Attributes list for + return values. Only 'zeroext', 'signext', and + 'inreg' attributes are valid here.
    4. + +
    5. 'ptr to function ty': shall be the signature of the pointer to + function value being invoked. In most cases, this is a direct function + invocation, but indirect invokes are just as possible, branching + off an arbitrary pointer to function value.
    6. + +
    7. 'function ptr val': An LLVM value containing a pointer to a + function to be invoked.
    8. + +
    9. 'function args': argument list whose types match the function + signature argument types. If the function signature indicates the + function accepts a variable number of arguments, the extra arguments can + be specified.
    10. + +
    11. 'normal label': the label reached when the called function + executes a 'ret' instruction.
    12. + +
    13. 'exception label': the label reached when a callee returns with + the unwind instruction.
    14. + +
    15. The optional function attributes list. Only + 'noreturn', 'nounwind', 'readonly' and + 'readnone' attributes are valid here.
    16. +
    + +
    Semantics:
    +

    This instruction is designed to operate as a standard + 'call' instruction in most regards. The + primary difference is that it establishes an association with a label, which + is used by the runtime library to unwind the stack.

    + +

    This instruction is used in languages with destructors to ensure that proper + cleanup is performed in the case of either a longjmp or a thrown + exception. Additionally, this is important for implementation of + 'catch' clauses in high-level languages that support them.

    + +

    For the purposes of the SSA form, the definition of the value returned by the + 'invoke' instruction is deemed to occur on the edge from the current + block to the "normal" label. If the callee unwinds then no return value is + available.

    + +
    Example:
    +
    +  %retval = invoke i32 @Test(i32 15) to label %Continue
    +              unwind label %TestCleanup              ; {i32}:retval set
    +  %retval = invoke coldcc i32 %Testfnptr(i32 15) to label %Continue
    +              unwind label %TestCleanup              ; {i32}:retval set
    +
    + +
    + + + + + +
    + +
    Syntax:
    +
    +  unwind
    +
    + +
    Overview:
    +

    The 'unwind' instruction unwinds the stack, continuing control flow + at the first callee in the dynamic call stack which used + an invoke instruction to perform the call. + This is primarily used to implement exception handling.

    + +
    Semantics:
    +

    The 'unwind' instruction causes execution of the current function to + immediately halt. The dynamic call stack is then searched for the + first invoke instruction on the call stack. + Once found, execution continues at the "exceptional" destination block + specified by the invoke instruction. If there is no invoke + instruction in the dynamic call chain, undefined behavior results.

    + +
    + + + + + +
    + +
    Syntax:
    +
    +  unreachable
    +
    + +
    Overview:
    +

    The 'unreachable' instruction has no defined semantics. This + instruction is used to inform the optimizer that a particular portion of the + code is not reachable. This can be used to indicate that the code after a + no-return function cannot be reached, and other facts.

    + +
    Semantics:
    +

    The 'unreachable' instruction has no defined semantics.

    + +
    + + + + +
    + +

    Binary operators are used to do most of the computation in a program. They + require two operands of the same type, execute an operation on them, and + produce a single value. The operands might represent multiple data, as is + the case with the vector data type. The result value + has the same type as its operands.

    + +

    There are several different binary operators:

    + +
    + + + + +
    + +
    Syntax:
    +
    +  <result> = add <ty> <op1>, <op2>          ; yields {ty}:result
    +  <result> = add nuw <ty> <op1>, <op2>      ; yields {ty}:result
    +  <result> = add nsw <ty> <op1>, <op2>      ; yields {ty}:result
    +  <result> = add nuw nsw <ty> <op1>, <op2>  ; yields {ty}:result
    +
    + +
    Overview:
    +

    The 'add' instruction returns the sum of its two operands.

    + +
    Arguments:
    +

    The two arguments to the 'add' instruction must + be integer or vector of + integer values. Both arguments must have identical types.

    + +
    Semantics:
    +

    The value produced is the integer sum of the two operands.

    + +

    If the sum has unsigned overflow, the result returned is the mathematical + result modulo 2n, where n is the bit width of the result.

    + +

    Because LLVM integers use a two's complement representation, this instruction + is appropriate for both signed and unsigned integers.

    + +

    nuw and nsw stand for "No Unsigned Wrap" + and "No Signed Wrap", respectively. If the nuw and/or + nsw keywords are present, the result value of the add + is undefined if unsigned and/or signed overflow, respectively, occurs.

    + +
    Example:
    +
    +  <result> = add i32 4, %var          ; yields {i32}:result = 4 + %var
    +
    + +
    + + + + +
    + +
    Syntax:
    +
    +  <result> = fadd <ty> <op1>, <op2>   ; yields {ty}:result
    +
    + +
    Overview:
    +

    The 'fadd' instruction returns the sum of its two operands.

    + +
    Arguments:
    +

    The two arguments to the 'fadd' instruction must be + floating point or vector of + floating point values. Both arguments must have identical types.

    + +
    Semantics:
    +

    The value produced is the floating point sum of the two operands.

    + +
    Example:
    +
    +  <result> = fadd float 4.0, %var          ; yields {float}:result = 4.0 + %var
    +
    + +
    + + + + +
    + +
    Syntax:
    +
    +  <result> = sub <ty> <op1>, <op2>          ; yields {ty}:result
    +  <result> = sub nuw <ty> <op1>, <op2>      ; yields {ty}:result
    +  <result> = sub nsw <ty> <op1>, <op2>      ; yields {ty}:result
    +  <result> = sub nuw nsw <ty> <op1>, <op2>  ; yields {ty}:result
    +
    + +
    Overview:
    +

    The 'sub' instruction returns the difference of its two + operands.

    + +

    Note that the 'sub' instruction is used to represent the + 'neg' instruction present in most other intermediate + representations.

    + +
    Arguments:
    +

    The two arguments to the 'sub' instruction must + be integer or vector of + integer values. Both arguments must have identical types.

    + +
    Semantics:
    +

    The value produced is the integer difference of the two operands.

    + +

    If the difference has unsigned overflow, the result returned is the + mathematical result modulo 2n, where n is the bit width of the + result.

    + +

    Because LLVM integers use a two's complement representation, this instruction + is appropriate for both signed and unsigned integers.

    + +

    nuw and nsw stand for "No Unsigned Wrap" + and "No Signed Wrap", respectively. If the nuw and/or + nsw keywords are present, the result value of the sub + is undefined if unsigned and/or signed overflow, respectively, occurs.

    + +
    Example:
    +
    +  <result> = sub i32 4, %var          ; yields {i32}:result = 4 - %var
    +  <result> = sub i32 0, %val          ; yields {i32}:result = -%var
    +
    + +
    + + + + +
    + +
    Syntax:
    +
    +  <result> = fsub <ty> <op1>, <op2>   ; yields {ty}:result
    +
    + +
    Overview:
    +

    The 'fsub' instruction returns the difference of its two + operands.

    + +

    Note that the 'fsub' instruction is used to represent the + 'fneg' instruction present in most other intermediate + representations.

    + +
    Arguments:
    +

    The two arguments to the 'fsub' instruction must be + floating point or vector of + floating point values. Both arguments must have identical types.

    + +
    Semantics:
    +

    The value produced is the floating point difference of the two operands.

    + +
    Example:
    +
    +  <result> = fsub float 4.0, %var           ; yields {float}:result = 4.0 - %var
    +  <result> = fsub float -0.0, %val          ; yields {float}:result = -%var
    +
    + +
    + + + + +
    + +
    Syntax:
    +
    +  <result> = mul <ty> <op1>, <op2>          ; yields {ty}:result
    +  <result> = mul nuw <ty> <op1>, <op2>      ; yields {ty}:result
    +  <result> = mul nsw <ty> <op1>, <op2>      ; yields {ty}:result
    +  <result> = mul nuw nsw <ty> <op1>, <op2>  ; yields {ty}:result
    +
    + +
    Overview:
    +

    The 'mul' instruction returns the product of its two operands.

    + +
    Arguments:
    +

    The two arguments to the 'mul' instruction must + be integer or vector of + integer values. Both arguments must have identical types.

    + +
    Semantics:
    +

    The value produced is the integer product of the two operands.

    + +

    If the result of the multiplication has unsigned overflow, the result + returned is the mathematical result modulo 2n, where n is the bit + width of the result.

    + +

    Because LLVM integers use a two's complement representation, and the result + is the same width as the operands, this instruction returns the correct + result for both signed and unsigned integers. If a full product + (e.g. i32xi32->i64) is needed, the operands should + be sign-extended or zero-extended as appropriate to the width of the full + product.

    + +

    nuw and nsw stand for "No Unsigned Wrap" + and "No Signed Wrap", respectively. If the nuw and/or + nsw keywords are present, the result value of the mul + is undefined if unsigned and/or signed overflow, respectively, occurs.

    + +
    Example:
    +
    +  <result> = mul i32 4, %var          ; yields {i32}:result = 4 * %var
    +
    + +
    + + + + +
    + +
    Syntax:
    +
    +  <result> = fmul <ty> <op1>, <op2>   ; yields {ty}:result
    +
    + +
    Overview:
    +

    The 'fmul' instruction returns the product of its two operands.

    + +
    Arguments:
    +

    The two arguments to the 'fmul' instruction must be + floating point or vector of + floating point values. Both arguments must have identical types.

    + +
    Semantics:
    +

    The value produced is the floating point product of the two operands.

    + +
    Example:
    +
    +  <result> = fmul float 4.0, %var          ; yields {float}:result = 4.0 * %var
    +
    + +
    + + + + +
    + +
    Syntax:
    +
    +  <result> = udiv <ty> <op1>, <op2>   ; yields {ty}:result
    +
    + +
    Overview:
    +

    The 'udiv' instruction returns the quotient of its two operands.

    + +
    Arguments:
    +

    The two arguments to the 'udiv' instruction must be + integer or vector of integer + values. Both arguments must have identical types.

    + +
    Semantics:
    +

    The value produced is the unsigned integer quotient of the two operands.

    + +

    Note that unsigned integer division and signed integer division are distinct + operations; for signed integer division, use 'sdiv'.

    + +

    Division by zero leads to undefined behavior.

    + +
    Example:
    +
    +  <result> = udiv i32 4, %var          ; yields {i32}:result = 4 / %var
    +
    + +
    + + + + +
    + +
    Syntax:
    +
    +  <result> = sdiv <ty> <op1>, <op2>         ; yields {ty}:result
    +  <result> = sdiv exact <ty> <op1>, <op2>   ; yields {ty}:result
    +
    + +
    Overview:
    +

    The 'sdiv' instruction returns the quotient of its two operands.

    + +
    Arguments:
    +

    The two arguments to the 'sdiv' instruction must be + integer or vector of integer + values. Both arguments must have identical types.

    + +
    Semantics:
    +

    The value produced is the signed integer quotient of the two operands rounded + towards zero.

    + +

    Note that signed integer division and unsigned integer division are distinct + operations; for unsigned integer division, use 'udiv'.

    + +

    Division by zero leads to undefined behavior. Overflow also leads to + undefined behavior; this is a rare case, but can occur, for example, by doing + a 32-bit division of -2147483648 by -1.

    + +

    If the exact keyword is present, the result value of the + sdiv is undefined if the result would be rounded or if overflow + would occur.

    + +
    Example:
    +
    +  <result> = sdiv i32 4, %var          ; yields {i32}:result = 4 / %var
    +
    + +
    + + + + +
    + +
    Syntax:
    +
    +  <result> = fdiv <ty> <op1>, <op2>   ; yields {ty}:result
    +
    + +
    Overview:
    +

    The 'fdiv' instruction returns the quotient of its two operands.

    + +
    Arguments:
    +

    The two arguments to the 'fdiv' instruction must be + floating point or vector of + floating point values. Both arguments must have identical types.

    + +
    Semantics:
    +

    The value produced is the floating point quotient of the two operands.

    + +
    Example:
    +
    +  <result> = fdiv float 4.0, %var          ; yields {float}:result = 4.0 / %var
    +
    + +
    + + + + +
    + +
    Syntax:
    +
    +  <result> = urem <ty> <op1>, <op2>   ; yields {ty}:result
    +
    + +
    Overview:
    +

    The 'urem' instruction returns the remainder from the unsigned + division of its two arguments.

    + +
    Arguments:
    +

    The two arguments to the 'urem' instruction must be + integer or vector of integer + values. Both arguments must have identical types.

    + +
    Semantics:
    +

    This instruction returns the unsigned integer remainder of a division. + This instruction always performs an unsigned division to get the + remainder.

    + +

    Note that unsigned integer remainder and signed integer remainder are + distinct operations; for signed integer remainder, use 'srem'.

    + +

    Taking the remainder of a division by zero leads to undefined behavior.

    + +
    Example:
    +
    +  <result> = urem i32 4, %var          ; yields {i32}:result = 4 % %var
    +
    + +
    + + + + +
    + +
    Syntax:
    +
    +  <result> = srem <ty> <op1>, <op2>   ; yields {ty}:result
    +
    + +
    Overview:
    +

    The 'srem' instruction returns the remainder from the signed + division of its two operands. This instruction can also take + vector versions of the values in which case the + elements must be integers.

    + +
    Arguments:
    +

    The two arguments to the 'srem' instruction must be + integer or vector of integer + values. Both arguments must have identical types.

    + +
    Semantics:
    +

    This instruction returns the remainder of a division (where the result + has the same sign as the dividend, op1), not the modulo + operator (where the result has the same sign as the divisor, op2) of + a value. For more information about the difference, + see The + Math Forum. For a table of how this is implemented in various languages, + please see + Wikipedia: modulo operation.

    + +

    Note that signed integer remainder and unsigned integer remainder are + distinct operations; for unsigned integer remainder, use 'urem'.

    + +

    Taking the remainder of a division by zero leads to undefined behavior. + Overflow also leads to undefined behavior; this is a rare case, but can + occur, for example, by taking the remainder of a 32-bit division of + -2147483648 by -1. (The remainder doesn't actually overflow, but this rule + lets srem be implemented using instructions that return both the result of + the division and the remainder.)

    + +
    Example:
    +
    +  <result> = srem i32 4, %var          ; yields {i32}:result = 4 % %var
    +
    + +
    + + + + +
    + +
    Syntax:
    +
    +  <result> = frem <ty> <op1>, <op2>   ; yields {ty}:result
    +
    + +
    Overview:
    +

    The 'frem' instruction returns the remainder from the division of + its two operands.

    + +
    Arguments:
    +

    The two arguments to the 'frem' instruction must be + floating point or vector of + floating point values. Both arguments must have identical types.

    + +
    Semantics:
    +

    This instruction returns the remainder of a division. The remainder + has the same sign as the dividend.

    + +
    Example:
    +
    +  <result> = frem float 4.0, %var          ; yields {float}:result = 4.0 % %var
    +
    + +
    + + + + +
    + +

    Bitwise binary operators are used to do various forms of bit-twiddling in a + program. They are generally very efficient instructions and can commonly be + strength reduced from other instructions. They require two operands of the + same type, execute an operation on them, and produce a single value. The + resulting value is the same type as its operands.

    + +
    + + + + +
    + +
    Syntax:
    +
    +  <result> = shl <ty> <op1>, <op2>   ; yields {ty}:result
    +
    + +
    Overview:
    +

    The 'shl' instruction returns the first operand shifted to the left + a specified number of bits.

    + +
    Arguments:
    +

    Both arguments to the 'shl' instruction must be the + same integer or vector of + integer type. 'op2' is treated as an unsigned value.

    + +
    Semantics:
    +

    The value produced is op1 * 2op2 mod + 2n, where n is the width of the result. If op2 + is (statically or dynamically) negative or equal to or larger than the number + of bits in op1, the result is undefined. If the arguments are + vectors, each vector element of op1 is shifted by the corresponding + shift amount in op2.

    + +
    Example:
    +
    +  <result> = shl i32 4, %var   ; yields {i32}: 4 << %var
    +  <result> = shl i32 4, 2      ; yields {i32}: 16
    +  <result> = shl i32 1, 10     ; yields {i32}: 1024
    +  <result> = shl i32 1, 32     ; undefined
    +  <result> = shl <2 x i32> < i32 1, i32 1>, < i32 1, i32 2>   ; yields: result=<2 x i32> < i32 2, i32 4>
    +
    + +
    + + + + +
    + +
    Syntax:
    +
    +  <result> = lshr <ty> <op1>, <op2>   ; yields {ty}:result
    +
    + +
    Overview:
    +

    The 'lshr' instruction (logical shift right) returns the first + operand shifted to the right a specified number of bits with zero fill.

    + +
    Arguments:
    +

    Both arguments to the 'lshr' instruction must be the same + integer or vector of integer + type. 'op2' is treated as an unsigned value.

    + +
    Semantics:
    +

    This instruction always performs a logical shift right operation. The most + significant bits of the result will be filled with zero bits after the shift. + If op2 is (statically or dynamically) equal to or larger than the + number of bits in op1, the result is undefined. If the arguments are + vectors, each vector element of op1 is shifted by the corresponding + shift amount in op2.

    + +
    Example:
    +
    +  <result> = lshr i32 4, 1   ; yields {i32}:result = 2
    +  <result> = lshr i32 4, 2   ; yields {i32}:result = 1
    +  <result> = lshr i8  4, 3   ; yields {i8}:result = 0
    +  <result> = lshr i8 -2, 1   ; yields {i8}:result = 0x7FFFFFFF 
    +  <result> = lshr i32 1, 32  ; undefined
    +  <result> = lshr <2 x i32> < i32 -2, i32 4>, < i32 1, i32 2>   ; yields: result=<2 x i32> < i32 0x7FFFFFFF, i32 1>
    +
    + +
    + + + +
    + +
    Syntax:
    +
    +  <result> = ashr <ty> <op1>, <op2>   ; yields {ty}:result
    +
    + +
    Overview:
    +

    The 'ashr' instruction (arithmetic shift right) returns the first + operand shifted to the right a specified number of bits with sign + extension.

    + +
    Arguments:
    +

    Both arguments to the 'ashr' instruction must be the same + integer or vector of integer + type. 'op2' is treated as an unsigned value.

    + +
    Semantics:
    +

    This instruction always performs an arithmetic shift right operation, The + most significant bits of the result will be filled with the sign bit + of op1. If op2 is (statically or dynamically) equal to or + larger than the number of bits in op1, the result is undefined. If + the arguments are vectors, each vector element of op1 is shifted by + the corresponding shift amount in op2.

    + +
    Example:
    +
    +  <result> = ashr i32 4, 1   ; yields {i32}:result = 2
    +  <result> = ashr i32 4, 2   ; yields {i32}:result = 1
    +  <result> = ashr i8  4, 3   ; yields {i8}:result = 0
    +  <result> = ashr i8 -2, 1   ; yields {i8}:result = -1
    +  <result> = ashr i32 1, 32  ; undefined
    +  <result> = ashr <2 x i32> < i32 -2, i32 4>, < i32 1, i32 3>   ; yields: result=<2 x i32> < i32 -1, i32 0>
    +
    + +
    + + + + +
    + +
    Syntax:
    +
    +  <result> = and <ty> <op1>, <op2>   ; yields {ty}:result
    +
    + +
    Overview:
    +

    The 'and' instruction returns the bitwise logical and of its two + operands.

    + +
    Arguments:
    +

    The two arguments to the 'and' instruction must be + integer or vector of integer + values. Both arguments must have identical types.

    + +
    Semantics:
    +

    The truth table used for the 'and' instruction is:

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    In0In1Out
    000
    010
    100
    111
    + +
    Example:
    +
    +  <result> = and i32 4, %var         ; yields {i32}:result = 4 & %var
    +  <result> = and i32 15, 40          ; yields {i32}:result = 8
    +  <result> = and i32 4, 8            ; yields {i32}:result = 0
    +
    +
    + + + +
    + +
    Syntax:
    +
    +  <result> = or <ty> <op1>, <op2>   ; yields {ty}:result
    +
    + +
    Overview:
    +

    The 'or' instruction returns the bitwise logical inclusive or of its + two operands.

    + +
    Arguments:
    +

    The two arguments to the 'or' instruction must be + integer or vector of integer + values. Both arguments must have identical types.

    + +
    Semantics:
    +

    The truth table used for the 'or' instruction is:

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    In0In1Out
    000
    011
    101
    111
    + +
    Example:
    +
    +  <result> = or i32 4, %var         ; yields {i32}:result = 4 | %var
    +  <result> = or i32 15, 40          ; yields {i32}:result = 47
    +  <result> = or i32 4, 8            ; yields {i32}:result = 12
    +
    + +
    + + + + +
    + +
    Syntax:
    +
    +  <result> = xor <ty> <op1>, <op2>   ; yields {ty}:result
    +
    + +
    Overview:
    +

    The 'xor' instruction returns the bitwise logical exclusive or of + its two operands. The xor is used to implement the "one's + complement" operation, which is the "~" operator in C.

    + +
    Arguments:
    +

    The two arguments to the 'xor' instruction must be + integer or vector of integer + values. Both arguments must have identical types.

    + +
    Semantics:
    +

    The truth table used for the 'xor' instruction is:

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    In0In1Out
    000
    011
    101
    110
    + +
    Example:
    +
    +  <result> = xor i32 4, %var         ; yields {i32}:result = 4 ^ %var
    +  <result> = xor i32 15, 40          ; yields {i32}:result = 39
    +  <result> = xor i32 4, 8            ; yields {i32}:result = 12
    +  <result> = xor i32 %V, -1          ; yields {i32}:result = ~%V
    +
    + +
    + + + + +
    + +

    LLVM supports several instructions to represent vector operations in a + target-independent manner. These instructions cover the element-access and + vector-specific operations needed to process vectors effectively. While LLVM + does directly support these vector operations, many sophisticated algorithms + will want to use target-specific intrinsics to take full advantage of a + specific target.

    + +
    + + + + +
    + +
    Syntax:
    +
    +  <result> = extractelement <n x <ty>> <val>, i32 <idx>    ; yields <ty>
    +
    + +
    Overview:
    +

    The 'extractelement' instruction extracts a single scalar element + from a vector at a specified index.

    + + +
    Arguments:
    +

    The first operand of an 'extractelement' instruction is a value + of vector type. The second operand is an index + indicating the position from which to extract the element. The index may be + a variable.

    + +
    Semantics:
    +

    The result is a scalar of the same type as the element type of + val. Its value is the value at position idx of + val. If idx exceeds the length of val, the + results are undefined.

    + +
    Example:
    +
    +  <result> = extractelement <4 x i32> %vec, i32 0    ; yields i32
    +
    + +
    + + + + +
    + +
    Syntax:
    +
    +  <result> = insertelement <n x <ty>> <val>, <ty> <elt>, i32 <idx>    ; yields <n x <ty>>
    +
    + +
    Overview:
    +

    The 'insertelement' instruction inserts a scalar element into a + vector at a specified index.

    + +
    Arguments:
    +

    The first operand of an 'insertelement' instruction is a value + of vector type. The second operand is a scalar value + whose type must equal the element type of the first operand. The third + operand is an index indicating the position at which to insert the value. + The index may be a variable.

    + +
    Semantics:
    +

    The result is a vector of the same type as val. Its element values + are those of val except at position idx, where it gets the + value elt. If idx exceeds the length of val, the + results are undefined.

    + +
    Example:
    +
    +  <result> = insertelement <4 x i32> %vec, i32 1, i32 0    ; yields <4 x i32>
    +
    + +
    + + + + +
    + +
    Syntax:
    +
    +  <result> = shufflevector <n x <ty>> <v1>, <n x <ty>> <v2>, <m x i32> <mask>    ; yields <m x <ty>>
    +
    + +
    Overview:
    +

    The 'shufflevector' instruction constructs a permutation of elements + from two input vectors, returning a vector with the same element type as the + input and length that is the same as the shuffle mask.

    + +
    Arguments:
    +

    The first two operands of a 'shufflevector' instruction are vectors + with types that match each other. The third argument is a shuffle mask whose + element type is always 'i32'. The result of the instruction is a vector + whose length is the same as the shuffle mask and whose element type is the + same as the element type of the first two operands.

    + +

    The shuffle mask operand is required to be a constant vector with either + constant integer or undef values.

    + +
    Semantics:
    +

    The elements of the two input vectors are numbered from left to right across + both of the vectors. The shuffle mask operand specifies, for each element of + the result vector, which element of the two input vectors the result element + gets. The element selector may be undef (meaning "don't care") and the + second operand may be undef if performing a shuffle from only one vector.

    + +
    Example:
    +
    +  <result> = shufflevector <4 x i32> %v1, <4 x i32> %v2, 
    +                          <4 x i32> <i32 0, i32 4, i32 1, i32 5>  ; yields <4 x i32>
    +  <result> = shufflevector <4 x i32> %v1, <4 x i32> undef, 
    +                          <4 x i32> <i32 0, i32 1, i32 2, i32 3>  ; yields <4 x i32> - Identity shuffle.
    +  <result> = shufflevector <8 x i32> %v1, <8 x i32> undef, 
    +                          <4 x i32> <i32 0, i32 1, i32 2, i32 3>  ; yields <4 x i32>
    +  <result> = shufflevector <4 x i32> %v1, <4 x i32> %v2, 
    +                          <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7 >  ; yields <8 x i32>
    +
    + +
    + + + + +
    + +

    LLVM supports several instructions for working with aggregate values.

    + +
    + + + + +
    + +
    Syntax:
    +
    +  <result> = extractvalue <aggregate type> <val>, <idx>{, <idx>}*
    +
    + +
    Overview:
    +

    The 'extractvalue' instruction extracts the value of a struct field + or array element from an aggregate value.

    + +
    Arguments:
    +

    The first operand of an 'extractvalue' instruction is a value + of struct or array type. The + operands are constant indices to specify which value to extract in a similar + manner as indices in a + 'getelementptr' instruction.

    + +
    Semantics:
    +

    The result is the value at the position in the aggregate specified by the + index operands.

    + +
    Example:
    +
    +  <result> = extractvalue {i32, float} %agg, 0    ; yields i32
    +
    + +
    + + + + +
    + +
    Syntax:
    +
    +  <result> = insertvalue <aggregate type> <val>, <ty> <val>, <idx>    ; yields <n x <ty>>
    +
    + +
    Overview:
    +

    The 'insertvalue' instruction inserts a value into a struct field or + array element in an aggregate.

    + + +
    Arguments:
    +

    The first operand of an 'insertvalue' instruction is a value + of struct or array type. The + second operand is a first-class value to insert. The following operands are + constant indices indicating the position at which to insert the value in a + similar manner as indices in a + 'getelementptr' instruction. The + value to insert must have the same type as the value identified by the + indices.

    + +
    Semantics:
    +

    The result is an aggregate of the same type as val. Its value is + that of val except that the value at the position specified by the + indices is that of elt.

    + +
    Example:
    +
    +  <result> = insertvalue {i32, float} %agg, i32 1, 0    ; yields {i32, float}
    +
    + +
    + + + + + +
    + +

    A key design point of an SSA-based representation is how it represents + memory. In LLVM, no memory locations are in SSA form, which makes things + very simple. This section describes how to read, write, and allocate + memory in LLVM.

    + +
    + + + + +
    + +
    Syntax:
    +
    +  <result> = alloca <type>[, i32 <NumElements>][, align <alignment>]     ; yields {type*}:result
    +
    + +
    Overview:
    +

    The 'alloca' instruction allocates memory on the stack frame of the + currently executing function, to be automatically released when this function + returns to its caller. The object is always allocated in the generic address + space (address space zero).

    + +
    Arguments:
    +

    The 'alloca' instruction + allocates sizeof(<type>)*NumElements bytes of memory on the + runtime stack, returning a pointer of the appropriate type to the program. + If "NumElements" is specified, it is the number of elements allocated, + otherwise "NumElements" is defaulted to be one. If a constant alignment is + specified, the value result of the allocation is guaranteed to be aligned to + at least that boundary. If not specified, or if zero, the target can choose + to align the allocation on any convenient boundary compatible with the + type.

    + +

    'type' may be any sized type.

    + +
    Semantics:
    +

    Memory is allocated; a pointer is returned. The operation is undefined if + there is insufficient stack space for the allocation. 'alloca'd + memory is automatically released when the function returns. The + 'alloca' instruction is commonly used to represent automatic + variables that must have an address available. When the function returns + (either with the ret + or unwind instructions), the memory is + reclaimed. Allocating zero bytes is legal, but the result is undefined.

    + +
    Example:
    +
    +  %ptr = alloca i32                             ; yields {i32*}:ptr
    +  %ptr = alloca i32, i32 4                      ; yields {i32*}:ptr
    +  %ptr = alloca i32, i32 4, align 1024          ; yields {i32*}:ptr
    +  %ptr = alloca i32, align 1024                 ; yields {i32*}:ptr
    +
    + +
    + + + + +
    + +
    Syntax:
    +
    +  <result> = load <ty>* <pointer>[, align <alignment>]
    +  <result> = volatile load <ty>* <pointer>[, align <alignment>]
    +
    + +
    Overview:
    +

    The 'load' instruction is used to read from memory.

    + +
    Arguments:
    +

    The argument to the 'load' instruction specifies the memory address + from which to load. The pointer must point to + a first class type. If the load is + marked as volatile, then the optimizer is not allowed to modify the + number or order of execution of this load with other + volatile load and store + instructions.

    + +

    The optional constant "align" argument specifies the alignment of the + operation (that is, the alignment of the memory address). A value of 0 or an + omitted "align" argument means that the operation has the preferential + alignment for the target. It is the responsibility of the code emitter to + ensure that the alignment information is correct. Overestimating the + alignment results in an undefined behavior. Underestimating the alignment may + produce less efficient code. An alignment of 1 is always safe.

    + +
    Semantics:
    +

    The location of memory pointed to is loaded. If the value being loaded is of + scalar type then the number of bytes read does not exceed the minimum number + of bytes needed to hold all bits of the type. For example, loading an + i24 reads at most three bytes. When loading a value of a type like + i20 with a size that is not an integral number of bytes, the result + is undefined if the value was not originally written using a store of the + same type.

    + +
    Examples:
    +
    +  %ptr = alloca i32                               ; yields {i32*}:ptr
    +  store i32 3, i32* %ptr                          ; yields {void}
    +  %val = load i32* %ptr                           ; yields {i32}:val = i32 3
    +
    + +
    + + + + +
    + +
    Syntax:
    +
    +  store <ty> <value>, <ty>* <pointer>[, align <alignment>]                   ; yields {void}
    +  volatile store <ty> <value>, <ty>* <pointer>[, align <alignment>]          ; yields {void}
    +
    + +
    Overview:
    +

    The 'store' instruction is used to write to memory.

    + +
    Arguments:
    +

    There are two arguments to the 'store' instruction: a value to store + and an address at which to store it. The type of the + '<pointer>' operand must be a pointer to + the first class type of the + '<value>' operand. If the store is marked + as volatile, then the optimizer is not allowed to modify the number + or order of execution of this store with other + volatile load and store + instructions.

    + +

    The optional constant "align" argument specifies the alignment of the + operation (that is, the alignment of the memory address). A value of 0 or an + omitted "align" argument means that the operation has the preferential + alignment for the target. It is the responsibility of the code emitter to + ensure that the alignment information is correct. Overestimating the + alignment results in an undefined behavior. Underestimating the alignment may + produce less efficient code. An alignment of 1 is always safe.

    + +
    Semantics:
    +

    The contents of memory are updated to contain '<value>' at the + location specified by the '<pointer>' operand. If + '<value>' is of scalar type then the number of bytes written + does not exceed the minimum number of bytes needed to hold all bits of the + type. For example, storing an i24 writes at most three bytes. When + writing a value of a type like i20 with a size that is not an + integral number of bytes, it is unspecified what happens to the extra bits + that do not belong to the type, but they will typically be overwritten.

    + +
    Example:
    +
    +  %ptr = alloca i32                               ; yields {i32*}:ptr
    +  store i32 3, i32* %ptr                          ; yields {void}
    +  %val = load i32* %ptr                           ; yields {i32}:val = i32 3
    +
    + +
    + + + + +
    + +
    Syntax:
    +
    +  <result> = getelementptr <pty>* <ptrval>{, <ty> <idx>}*
    +  <result> = getelementptr inbounds <pty>* <ptrval>{, <ty> <idx>}*
    +
    + +
    Overview:
    +

    The 'getelementptr' instruction is used to get the address of a + subelement of an aggregate data structure. It performs address calculation + only and does not access memory.

    + +
    Arguments:
    +

    The first argument is always a pointer, and forms the basis of the + calculation. The remaining arguments are indices that indicate which of the + elements of the aggregate object are indexed. The interpretation of each + index is dependent on the type being indexed into. The first index always + indexes the pointer value given as the first argument, the second index + indexes a value of the type pointed to (not necessarily the value directly + pointed to, since the first index can be non-zero), etc. The first type + indexed into must be a pointer value, subsequent types can be arrays, vectors + and structs. Note that subsequent types being indexed into can never be + pointers, since that would require loading the pointer before continuing + calculation.

    + +

    The type of each index argument depends on the type it is indexing into. + When indexing into a (optionally packed) structure, only i32 integer + constants are allowed. When indexing into an array, pointer or + vector, integers of any width are allowed, and they are not required to be + constant.

    + +

    For example, let's consider a C code fragment and how it gets compiled to + LLVM:

    + +
    +
    +struct RT {
    +  char A;
    +  int B[10][20];
    +  char C;
    +};
    +struct ST {
    +  int X;
    +  double Y;
    +  struct RT Z;
    +};
    +
    +int *foo(struct ST *s) {
    +  return &s[1].Z.B[5][13];
    +}
    +
    +
    + +

    The LLVM code generated by the GCC frontend is:

    + +
    +
    +%RT = type { i8 , [10 x [20 x i32]], i8  }
    +%ST = type { i32, double, %RT }
    +
    +define i32* @foo(%ST* %s) {
    +entry:
    +  %reg = getelementptr %ST* %s, i32 1, i32 2, i32 1, i32 5, i32 13
    +  ret i32* %reg
    +}
    +
    +
    + +
    Semantics:
    +

    In the example above, the first index is indexing into the '%ST*' + type, which is a pointer, yielding a '%ST' = '{ i32, double, %RT + }' type, a structure. The second index indexes into the third element + of the structure, yielding a '%RT' = '{ i8 , [10 x [20 x i32]], + i8 }' type, another structure. The third index indexes into the second + element of the structure, yielding a '[10 x [20 x i32]]' type, an + array. The two dimensions of the array are subscripted into, yielding an + 'i32' type. The 'getelementptr' instruction returns a + pointer to this element, thus computing a value of 'i32*' type.

    + +

    Note that it is perfectly legal to index partially through a structure, + returning a pointer to an inner element. Because of this, the LLVM code for + the given testcase is equivalent to:

    + +
    +  define i32* @foo(%ST* %s) {
    +    %t1 = getelementptr %ST* %s, i32 1                        ; yields %ST*:%t1
    +    %t2 = getelementptr %ST* %t1, i32 0, i32 2                ; yields %RT*:%t2
    +    %t3 = getelementptr %RT* %t2, i32 0, i32 1                ; yields [10 x [20 x i32]]*:%t3
    +    %t4 = getelementptr [10 x [20 x i32]]* %t3, i32 0, i32 5  ; yields [20 x i32]*:%t4
    +    %t5 = getelementptr [20 x i32]* %t4, i32 0, i32 13        ; yields i32*:%t5
    +    ret i32* %t5
    +  }
    +
    + +

    If the inbounds keyword is present, the result value of the + getelementptr is undefined if the base pointer is not an + in bounds address of an allocated object, or if any of the addresses + that would be formed by successive addition of the offsets implied by the + indices to the base address with infinitely precise arithmetic are not an + in bounds address of that allocated object. + The in bounds addresses for an allocated object are all the addresses + that point into the object, plus the address one byte past the end.

    + +

    If the inbounds keyword is not present, the offsets are added to + the base address with silently-wrapping two's complement arithmetic, and + the result value of the getelementptr may be outside the object + pointed to by the base pointer. The result value may not necessarily be + used to access memory though, even if it happens to point into allocated + storage. See the Pointer Aliasing Rules + section for more information.

    + +

    The getelementptr instruction is often confusing. For some more insight into + how it works, see the getelementptr FAQ.

    + +
    Example:
    +
    +    ; yields [12 x i8]*:aptr
    +    %aptr = getelementptr {i32, [12 x i8]}* %saptr, i64 0, i32 1
    +    ; yields i8*:vptr
    +    %vptr = getelementptr {i32, <2 x i8>}* %svptr, i64 0, i32 1, i32 1
    +    ; yields i8*:eptr
    +    %eptr = getelementptr [12 x i8]* %aptr, i64 0, i32 1
    +    ; yields i32*:iptr
    +    %iptr = getelementptr [10 x i32]* @arr, i16 0, i16 0
    +
    + +
    + + + + +
    + +

    The instructions in this category are the conversion instructions (casting) + which all take a single operand and a type. They perform various bit + conversions on the operand.

    + +
    + + + +
    + +
    Syntax:
    +
    +  <result> = trunc <ty> <value> to <ty2>             ; yields ty2
    +
    + +
    Overview:
    +

    The 'trunc' instruction truncates its operand to the + type ty2.

    + +
    Arguments:
    +

    The 'trunc' instruction takes a value to trunc, which must + be an integer type, and a type that specifies the + size and type of the result, which must be + an integer type. The bit size of value must + be larger than the bit size of ty2. Equal sized types are not + allowed.

    + +
    Semantics:
    +

    The 'trunc' instruction truncates the high order bits + in value and converts the remaining bits to ty2. Since the + source size must be larger than the destination size, trunc cannot + be a no-op cast. It will always truncate bits.

    + +
    Example:
    +
    +  %X = trunc i32 257 to i8              ; yields i8:1
    +  %Y = trunc i32 123 to i1              ; yields i1:true
    +  %Z = trunc i32 122 to i1              ; yields i1:false
    +
    + +
    + + + +
    + +
    Syntax:
    +
    +  <result> = zext <ty> <value> to <ty2>             ; yields ty2
    +
    + +
    Overview:
    +

    The 'zext' instruction zero extends its operand to type + ty2.

    + + +
    Arguments:
    +

    The 'zext' instruction takes a value to cast, which must be of + integer type, and a type to cast it to, which must + also be of integer type. The bit size of the + value must be smaller than the bit size of the destination type, + ty2.

    + +
    Semantics:
    +

    The zext fills the high order bits of the value with zero + bits until it reaches the size of the destination type, ty2.

    + +

    When zero extending from i1, the result will always be either 0 or 1.

    + +
    Example:
    +
    +  %X = zext i32 257 to i64              ; yields i64:257
    +  %Y = zext i1 true to i32              ; yields i32:1
    +
    + +
    + + + +
    + +
    Syntax:
    +
    +  <result> = sext <ty> <value> to <ty2>             ; yields ty2
    +
    + +
    Overview:
    +

    The 'sext' sign extends value to the type ty2.

    + +
    Arguments:
    +

    The 'sext' instruction takes a value to cast, which must be of + integer type, and a type to cast it to, which must + also be of integer type. The bit size of the + value must be smaller than the bit size of the destination type, + ty2.

    + +
    Semantics:
    +

    The 'sext' instruction performs a sign extension by copying the sign + bit (highest order bit) of the value until it reaches the bit size + of the type ty2.

    + +

    When sign extending from i1, the extension always results in -1 or 0.

    + +
    Example:
    +
    +  %X = sext i8  -1 to i16              ; yields i16   :65535
    +  %Y = sext i1 true to i32             ; yields i32:-1
    +
    + +
    + + + + +
    + +
    Syntax:
    +
    +  <result> = fptrunc <ty> <value> to <ty2>             ; yields ty2
    +
    + +
    Overview:
    +

    The 'fptrunc' instruction truncates value to type + ty2.

    + +
    Arguments:
    +

    The 'fptrunc' instruction takes a floating + point value to cast and a floating point type + to cast it to. The size of value must be larger than the size of + ty2. This implies that fptrunc cannot be used to make a + no-op cast.

    + +
    Semantics:
    +

    The 'fptrunc' instruction truncates a value from a larger + floating point type to a smaller + floating point type. If the value cannot fit + within the destination type, ty2, then the results are + undefined.

    + +
    Example:
    +
    +  %X = fptrunc double 123.0 to float         ; yields float:123.0
    +  %Y = fptrunc double 1.0E+300 to float      ; yields undefined
    +
    + +
    + + + +
    + +
    Syntax:
    +
    +  <result> = fpext <ty> <value> to <ty2>             ; yields ty2
    +
    + +
    Overview:
    +

    The 'fpext' extends a floating point value to a larger + floating point value.

    + +
    Arguments:
    +

    The 'fpext' instruction takes a + floating point value to cast, and + a floating point type to cast it to. The source + type must be smaller than the destination type.

    + +
    Semantics:
    +

    The 'fpext' instruction extends the value from a smaller + floating point type to a larger + floating point type. The fpext cannot be + used to make a no-op cast because it always changes bits. Use + bitcast to make a no-op cast for a floating point cast.

    + +
    Example:
    +
    +  %X = fpext float 3.1415 to double        ; yields double:3.1415
    +  %Y = fpext float 1.0 to float            ; yields float:1.0 (no-op)
    +
    + +
    + + + +
    + +
    Syntax:
    +
    +  <result> = fptoui <ty> <value> to <ty2>             ; yields ty2
    +
    + +
    Overview:
    +

    The 'fptoui' converts a floating point value to its + unsigned integer equivalent of type ty2.

    + +
    Arguments:
    +

    The 'fptoui' instruction takes a value to cast, which must be a + scalar or vector floating point value, and a type + to cast it to ty2, which must be an integer + type. If ty is a vector floating point type, ty2 must be a + vector integer type with the same number of elements as ty

    + +
    Semantics:
    +

    The 'fptoui' instruction converts its + floating point operand into the nearest (rounding + towards zero) unsigned integer value. If the value cannot fit + in ty2, the results are undefined.

    + +
    Example:
    +
    +  %X = fptoui double 123.0 to i32      ; yields i32:123
    +  %Y = fptoui float 1.0E+300 to i1     ; yields undefined:1
    +  %Z = fptoui float 1.04E+17 to i8     ; yields undefined:1
    +
    + +
    + + + +
    + +
    Syntax:
    +
    +  <result> = fptosi <ty> <value> to <ty2>             ; yields ty2
    +
    + +
    Overview:
    +

    The 'fptosi' instruction converts + floating point value to + type ty2.

    + +
    Arguments:
    +

    The 'fptosi' instruction takes a value to cast, which must be a + scalar or vector floating point value, and a type + to cast it to ty2, which must be an integer + type. If ty is a vector floating point type, ty2 must be a + vector integer type with the same number of elements as ty

    + +
    Semantics:
    +

    The 'fptosi' instruction converts its + floating point operand into the nearest (rounding + towards zero) signed integer value. If the value cannot fit in ty2, + the results are undefined.

    + +
    Example:
    +
    +  %X = fptosi double -123.0 to i32      ; yields i32:-123
    +  %Y = fptosi float 1.0E-247 to i1      ; yields undefined:1
    +  %Z = fptosi float 1.04E+17 to i8      ; yields undefined:1
    +
    + +
    + + + +
    + +
    Syntax:
    +
    +  <result> = uitofp <ty> <value> to <ty2>             ; yields ty2
    +
    + +
    Overview:
    +

    The 'uitofp' instruction regards value as an unsigned + integer and converts that value to the ty2 type.

    + +
    Arguments:
    +

    The 'uitofp' instruction takes a value to cast, which must be a + scalar or vector integer value, and a type to cast + it to ty2, which must be an floating point + type. If ty is a vector integer type, ty2 must be a vector + floating point type with the same number of elements as ty

    + +
    Semantics:
    +

    The 'uitofp' instruction interprets its operand as an unsigned + integer quantity and converts it to the corresponding floating point + value. If the value cannot fit in the floating point value, the results are + undefined.

    + +
    Example:
    +
    +  %X = uitofp i32 257 to float         ; yields float:257.0
    +  %Y = uitofp i8 -1 to double          ; yields double:255.0
    +
    + +
    + + + +
    + +
    Syntax:
    +
    +  <result> = sitofp <ty> <value> to <ty2>             ; yields ty2
    +
    + +
    Overview:
    +

    The 'sitofp' instruction regards value as a signed integer + and converts that value to the ty2 type.

    + +
    Arguments:
    +

    The 'sitofp' instruction takes a value to cast, which must be a + scalar or vector integer value, and a type to cast + it to ty2, which must be an floating point + type. If ty is a vector integer type, ty2 must be a vector + floating point type with the same number of elements as ty

    + +
    Semantics:
    +

    The 'sitofp' instruction interprets its operand as a signed integer + quantity and converts it to the corresponding floating point value. If the + value cannot fit in the floating point value, the results are undefined.

    + +
    Example:
    +
    +  %X = sitofp i32 257 to float         ; yields float:257.0
    +  %Y = sitofp i8 -1 to double          ; yields double:-1.0
    +
    + +
    + + + +
    + +
    Syntax:
    +
    +  <result> = ptrtoint <ty> <value> to <ty2>             ; yields ty2
    +
    + +
    Overview:
    +

    The 'ptrtoint' instruction converts the pointer value to + the integer type ty2.

    + +
    Arguments:
    +

    The 'ptrtoint' instruction takes a value to cast, which + must be a pointer value, and a type to cast it to + ty2, which must be an integer type.

    + +
    Semantics:
    +

    The 'ptrtoint' instruction converts value to integer type + ty2 by interpreting the pointer value as an integer and either + truncating or zero extending that value to the size of the integer type. If + value is smaller than ty2 then a zero extension is done. If + value is larger than ty2 then a truncation is done. If they + are the same size, then nothing is done (no-op cast) other than a type + change.

    + +
    Example:
    +
    +  %X = ptrtoint i32* %X to i8           ; yields truncation on 32-bit architecture
    +  %Y = ptrtoint i32* %x to i64          ; yields zero extension on 32-bit architecture
    +
    + +
    + + + +
    + +
    Syntax:
    +
    +  <result> = inttoptr <ty> <value> to <ty2>             ; yields ty2
    +
    + +
    Overview:
    +

    The 'inttoptr' instruction converts an integer value to a + pointer type, ty2.

    + +
    Arguments:
    +

    The 'inttoptr' instruction takes an integer + value to cast, and a type to cast it to, which must be a + pointer type.

    + +
    Semantics:
    +

    The 'inttoptr' instruction converts value to type + ty2 by applying either a zero extension or a truncation depending on + the size of the integer value. If value is larger than the + size of a pointer then a truncation is done. If value is smaller + than the size of a pointer then a zero extension is done. If they are the + same size, nothing is done (no-op cast).

    + +
    Example:
    +
    +  %X = inttoptr i32 255 to i32*          ; yields zero extension on 64-bit architecture
    +  %Y = inttoptr i32 255 to i32*          ; yields no-op on 32-bit architecture
    +  %Z = inttoptr i64 0 to i32*            ; yields truncation on 32-bit architecture
    +
    + +
    + + + +
    + +
    Syntax:
    +
    +  <result> = bitcast <ty> <value> to <ty2>             ; yields ty2
    +
    + +
    Overview:
    +

    The 'bitcast' instruction converts value to type + ty2 without changing any bits.

    + +
    Arguments:
    +

    The 'bitcast' instruction takes a value to cast, which must be a + non-aggregate first class value, and a type to cast it to, which must also be + a non-aggregate first class type. The bit sizes + of value and the destination type, ty2, must be + identical. If the source type is a pointer, the destination type must also be + a pointer. This instruction supports bitwise conversion of vectors to + integers and to vectors of other types (as long as they have the same + size).

    + +
    Semantics:
    +

    The 'bitcast' instruction converts value to type + ty2. It is always a no-op cast because no bits change with + this conversion. The conversion is done as if the value had been + stored to memory and read back as type ty2. Pointer types may only + be converted to other pointer types with this instruction. To convert + pointers to other types, use the inttoptr or + ptrtoint instructions first.

    + +
    Example:
    +
    +  %X = bitcast i8 255 to i8              ; yields i8 :-1
    +  %Y = bitcast i32* %x to sint*          ; yields sint*:%x
    +  %Z = bitcast <2 x int> %V to i64;      ; yields i64: %V   
    +
    + +
    + + + + +
    + +

    The instructions in this category are the "miscellaneous" instructions, which + defy better classification.

    + +
    + + + + +
    + +
    Syntax:
    +
    +  <result> = icmp <cond> <ty> <op1>, <op2>   ; yields {i1} or {<N x i1>}:result
    +
    + +
    Overview:
    +

    The 'icmp' instruction returns a boolean value or a vector of + boolean values based on comparison of its two integer, integer vector, or + pointer operands.

    + +
    Arguments:
    +

    The 'icmp' instruction takes three operands. The first operand is + the condition code indicating the kind of comparison to perform. It is not a + value, just a keyword. The possible condition code are:

    + +
      +
    1. eq: equal
    2. +
    3. ne: not equal
    4. +
    5. ugt: unsigned greater than
    6. +
    7. uge: unsigned greater or equal
    8. +
    9. ult: unsigned less than
    10. +
    11. ule: unsigned less or equal
    12. +
    13. sgt: signed greater than
    14. +
    15. sge: signed greater or equal
    16. +
    17. slt: signed less than
    18. +
    19. sle: signed less or equal
    20. +
    + +

    The remaining two arguments must be integer or + pointer or integer vector + typed. They must also be identical types.

    + +
    Semantics:
    +

    The 'icmp' compares op1 and op2 according to the + condition code given as cond. The comparison performed always yields + either an i1 or vector of i1 + result, as follows:

    + +
      +
    1. eq: yields true if the operands are equal, + false otherwise. No sign interpretation is necessary or + performed.
    2. + +
    3. ne: yields true if the operands are unequal, + false otherwise. No sign interpretation is necessary or + performed.
    4. + +
    5. ugt: interprets the operands as unsigned values and yields + true if op1 is greater than op2.
    6. + +
    7. uge: interprets the operands as unsigned values and yields + true if op1 is greater than or equal + to op2.
    8. + +
    9. ult: interprets the operands as unsigned values and yields + true if op1 is less than op2.
    10. + +
    11. ule: interprets the operands as unsigned values and yields + true if op1 is less than or equal to op2.
    12. + +
    13. sgt: interprets the operands as signed values and yields + true if op1 is greater than op2.
    14. + +
    15. sge: interprets the operands as signed values and yields + true if op1 is greater than or equal + to op2.
    16. + +
    17. slt: interprets the operands as signed values and yields + true if op1 is less than op2.
    18. + +
    19. sle: interprets the operands as signed values and yields + true if op1 is less than or equal to op2.
    20. +
    + +

    If the operands are pointer typed, the pointer + values are compared as if they were integers.

    + +

    If the operands are integer vectors, then they are compared element by + element. The result is an i1 vector with the same number of elements + as the values being compared. Otherwise, the result is an i1.

    + +
    Example:
    +
    +  <result> = icmp eq i32 4, 5          ; yields: result=false
    +  <result> = icmp ne float* %X, %X     ; yields: result=false
    +  <result> = icmp ult i16  4, 5        ; yields: result=true
    +  <result> = icmp sgt i16  4, 5        ; yields: result=false
    +  <result> = icmp ule i16 -4, 5        ; yields: result=false
    +  <result> = icmp sge i16  4, 5        ; yields: result=false
    +
    + +

    Note that the code generator does not yet support vector types with + the icmp instruction.

    + +
    + + + + +
    + +
    Syntax:
    +
    +  <result> = fcmp <cond> <ty> <op1>, <op2>     ; yields {i1} or {<N x i1>}:result
    +
    + +
    Overview:
    +

    The 'fcmp' instruction returns a boolean value or vector of boolean + values based on comparison of its operands.

    + +

    If the operands are floating point scalars, then the result type is a boolean +(i1).

    + +

    If the operands are floating point vectors, then the result type is a vector + of boolean with the same number of elements as the operands being + compared.

    + +
    Arguments:
    +

    The 'fcmp' instruction takes three operands. The first operand is + the condition code indicating the kind of comparison to perform. It is not a + value, just a keyword. The possible condition code are:

    + +
      +
    1. false: no comparison, always returns false
    2. +
    3. oeq: ordered and equal
    4. +
    5. ogt: ordered and greater than
    6. +
    7. oge: ordered and greater than or equal
    8. +
    9. olt: ordered and less than
    10. +
    11. ole: ordered and less than or equal
    12. +
    13. one: ordered and not equal
    14. +
    15. ord: ordered (no nans)
    16. +
    17. ueq: unordered or equal
    18. +
    19. ugt: unordered or greater than
    20. +
    21. uge: unordered or greater than or equal
    22. +
    23. ult: unordered or less than
    24. +
    25. ule: unordered or less than or equal
    26. +
    27. une: unordered or not equal
    28. +
    29. uno: unordered (either nans)
    30. +
    31. true: no comparison, always returns true
    32. +
    + +

    Ordered means that neither operand is a QNAN while + unordered means that either operand may be a QNAN.

    + +

    Each of val1 and val2 arguments must be either + a floating point type or + a vector of floating point type. They must have + identical types.

    + +
    Semantics:
    +

    The 'fcmp' instruction compares op1 and op2 + according to the condition code given as cond. If the operands are + vectors, then the vectors are compared element by element. Each comparison + performed always yields an i1 result, as + follows:

    + +
      +
    1. false: always yields false, regardless of operands.
    2. + +
    3. oeq: yields true if both operands are not a QNAN and + op1 is equal to op2.
    4. + +
    5. ogt: yields true if both operands are not a QNAN and + op1 is greather than op2.
    6. + +
    7. oge: yields true if both operands are not a QNAN and + op1 is greater than or equal to op2.
    8. + +
    9. olt: yields true if both operands are not a QNAN and + op1 is less than op2.
    10. + +
    11. ole: yields true if both operands are not a QNAN and + op1 is less than or equal to op2.
    12. + +
    13. one: yields true if both operands are not a QNAN and + op1 is not equal to op2.
    14. + +
    15. ord: yields true if both operands are not a QNAN.
    16. + +
    17. ueq: yields true if either operand is a QNAN or + op1 is equal to op2.
    18. + +
    19. ugt: yields true if either operand is a QNAN or + op1 is greater than op2.
    20. + +
    21. uge: yields true if either operand is a QNAN or + op1 is greater than or equal to op2.
    22. + +
    23. ult: yields true if either operand is a QNAN or + op1 is less than op2.
    24. + +
    25. ule: yields true if either operand is a QNAN or + op1 is less than or equal to op2.
    26. + +
    27. une: yields true if either operand is a QNAN or + op1 is not equal to op2.
    28. + +
    29. uno: yields true if either operand is a QNAN.
    30. + +
    31. true: always yields true, regardless of operands.
    32. +
    + +
    Example:
    +
    +  <result> = fcmp oeq float 4.0, 5.0    ; yields: result=false
    +  <result> = fcmp one float 4.0, 5.0    ; yields: result=true
    +  <result> = fcmp olt float 4.0, 5.0    ; yields: result=true
    +  <result> = fcmp ueq double 1.0, 2.0   ; yields: result=false
    +
    + +

    Note that the code generator does not yet support vector types with + the fcmp instruction.

    + +
    + + + + +
    + +
    Syntax:
    +
    +  <result> = phi <ty> [ <val0>, <label0>], ...
    +
    + +
    Overview:
    +

    The 'phi' instruction is used to implement the φ node in the + SSA graph representing the function.

    + +
    Arguments:
    +

    The type of the incoming values is specified with the first type field. After + this, the 'phi' instruction takes a list of pairs as arguments, with + one pair for each predecessor basic block of the current block. Only values + of first class type may be used as the value + arguments to the PHI node. Only labels may be used as the label + arguments.

    + +

    There must be no non-phi instructions between the start of a basic block and + the PHI instructions: i.e. PHI instructions must be first in a basic + block.

    + +

    For the purposes of the SSA form, the use of each incoming value is deemed to + occur on the edge from the corresponding predecessor block to the current + block (but after any definition of an 'invoke' instruction's return + value on the same edge).

    + +
    Semantics:
    +

    At runtime, the 'phi' instruction logically takes on the value + specified by the pair corresponding to the predecessor basic block that + executed just prior to the current block.

    + +
    Example:
    +
    +Loop:       ; Infinite loop that counts from 0 on up...
    +  %indvar = phi i32 [ 0, %LoopHeader ], [ %nextindvar, %Loop ]
    +  %nextindvar = add i32 %indvar, 1
    +  br label %Loop
    +
    + +
    + + + + +
    + +
    Syntax:
    +
    +  <result> = select selty <cond>, <ty> <val1>, <ty> <val2>             ; yields ty
    +
    +  selty is either i1 or {<N x i1>}
    +
    + +
    Overview:
    +

    The 'select' instruction is used to choose one value based on a + condition, without branching.

    + + +
    Arguments:
    +

    The 'select' instruction requires an 'i1' value or a vector of 'i1' + values indicating the condition, and two values of the + same first class type. If the val1/val2 are + vectors and the condition is a scalar, then entire vectors are selected, not + individual elements.

    + +
    Semantics:
    +

    If the condition is an i1 and it evaluates to 1, the instruction returns the + first value argument; otherwise, it returns the second value argument.

    + +

    If the condition is a vector of i1, then the value arguments must be vectors + of the same size, and the selection is done element by element.

    + +
    Example:
    +
    +  %X = select i1 true, i8 17, i8 42          ; yields i8:17
    +
    + +

    Note that the code generator does not yet support conditions + with vector type.

    + +
    + + + + +
    + +
    Syntax:
    +
    +  <result> = [tail] call [cconv] [ret attrs] <ty> [<fnty>*] <fnptrval>(<function args>) [fn attrs]
    +
    + +
    Overview:
    +

    The 'call' instruction represents a simple function call.

    + +
    Arguments:
    +

    This instruction requires several arguments:

    + +
      +
    1. The optional "tail" marker indicates whether the callee function accesses + any allocas or varargs in the caller. If the "tail" marker is present, + the function call is eligible for tail call optimization. Note that calls + may be marked "tail" even if they do not occur before + a ret instruction.
    2. + +
    3. The optional "cconv" marker indicates which calling + convention the call should use. If none is specified, the call + defaults to using C calling conventions.
    4. + +
    5. The optional Parameter Attributes list for + return values. Only 'zeroext', 'signext', and + 'inreg' attributes are valid here.
    6. + +
    7. 'ty': the type of the call instruction itself which is also the + type of the return value. Functions that return no value are marked + void.
    8. + +
    9. 'fnty': shall be the signature of the pointer to function value + being invoked. The argument types must match the types implied by this + signature. This type can be omitted if the function is not varargs and if + the function type does not return a pointer to a function.
    10. + +
    11. 'fnptrval': An LLVM value containing a pointer to a function to + be invoked. In most cases, this is a direct function invocation, but + indirect calls are just as possible, calling an arbitrary pointer + to function value.
    12. + +
    13. 'function args': argument list whose types match the function + signature argument types. All arguments must be of + first class type. If the function signature + indicates the function accepts a variable number of arguments, the extra + arguments can be specified.
    14. + +
    15. The optional function attributes list. Only + 'noreturn', 'nounwind', 'readonly' and + 'readnone' attributes are valid here.
    16. +
    + +
    Semantics:
    +

    The 'call' instruction is used to cause control flow to transfer to + a specified function, with its incoming arguments bound to the specified + values. Upon a 'ret' instruction in the called + function, control flow continues with the instruction after the function + call, and the return value of the function is bound to the result + argument.

    + +
    Example:
    +
    +  %retval = call i32 @test(i32 %argc)
    +  call i32 (i8 *, ...)* @printf(i8 * %msg, i32 12, i8 42)      ; yields i32
    +  %X = tail call i32 @foo()                                    ; yields i32
    +  %Y = tail call fastcc i32 @foo()  ; yields i32
    +  call void %foo(i8 97 signext)
    +
    +  %struct.A = type { i32, i8 }
    +  %r = call %struct.A @foo()                        ; yields { 32, i8 }
    +  %gr = extractvalue %struct.A %r, 0                ; yields i32
    +  %gr1 = extractvalue %struct.A %r, 1               ; yields i8
    +  %Z = call void @foo() noreturn                    ; indicates that %foo never returns normally
    +  %ZZ = call zeroext i32 @bar()                     ; Return value is %zero extended
    +
    + +

    llvm treats calls to some functions with names and arguments that match the +standard C99 library as being the C99 library functions, and may perform +optimizations or generate code for them under that assumption. This is +something we'd like to change in the future to provide better support for +freestanding environments and non-C-based langauges.

    + +
    + + + + +
    + +
    Syntax:
    +
    +  <resultval> = va_arg <va_list*> <arglist>, <argty>
    +
    + +
    Overview:
    +

    The 'va_arg' instruction is used to access arguments passed through + the "variable argument" area of a function call. It is used to implement the + va_arg macro in C.

    + +
    Arguments:
    +

    This instruction takes a va_list* value and the type of the + argument. It returns a value of the specified argument type and increments + the va_list to point to the next argument. The actual type + of va_list is target specific.

    + +
    Semantics:
    +

    The 'va_arg' instruction loads an argument of the specified type + from the specified va_list and causes the va_list to point + to the next argument. For more information, see the variable argument + handling Intrinsic Functions.

    + +

    It is legal for this instruction to be called in a function which does not + take a variable number of arguments, for example, the vfprintf + function.

    + +

    va_arg is an LLVM instruction instead of + an intrinsic function because it takes a type as an + argument.

    + +
    Example:
    +

    See the variable argument processing section.

    + +

    Note that the code generator does not yet fully support va_arg on many + targets. Also, it does not currently support va_arg with aggregate types on + any target.

    + +
    + + + + + +
    + +

    LLVM supports the notion of an "intrinsic function". These functions have + well known names and semantics and are required to follow certain + restrictions. Overall, these intrinsics represent an extension mechanism for + the LLVM language that does not require changing all of the transformations + in LLVM when adding to the language (or the bitcode reader/writer, the + parser, etc...).

    + +

    Intrinsic function names must all start with an "llvm." prefix. This + prefix is reserved in LLVM for intrinsic names; thus, function names may not + begin with this prefix. Intrinsic functions must always be external + functions: you cannot define the body of intrinsic functions. Intrinsic + functions may only be used in call or invoke instructions: it is illegal to + take the address of an intrinsic function. Additionally, because intrinsic + functions are part of the LLVM language, it is required if any are added that + they be documented here.

    + +

    Some intrinsic functions can be overloaded, i.e., the intrinsic represents a + family of functions that perform the same operation but on different data + types. Because LLVM can represent over 8 million different integer types, + overloading is used commonly to allow an intrinsic function to operate on any + integer type. One or more of the argument types or the result type can be + overloaded to accept any integer type. Argument types may also be defined as + exactly matching a previous argument's type or the result type. This allows + an intrinsic function which accepts multiple arguments, but needs all of them + to be of the same type, to only be overloaded with respect to a single + argument or the result.

    + +

    Overloaded intrinsics will have the names of its overloaded argument types + encoded into its function name, each preceded by a period. Only those types + which are overloaded result in a name suffix. Arguments whose type is matched + against another type do not. For example, the llvm.ctpop function + can take an integer of any width and returns an integer of exactly the same + integer width. This leads to a family of functions such as + i8 @llvm.ctpop.i8(i8 %val) and i29 @llvm.ctpop.i29(i29 + %val). Only one type, the return type, is overloaded, and only one type + suffix is required. Because the argument's type is matched against the return + type, it does not require its own name suffix.

    + +

    To learn how to add an intrinsic function, please see the + Extending LLVM Guide.

    + +
    + + + + +
    + +

    Variable argument support is defined in LLVM with + the va_arg instruction and these three + intrinsic functions. These functions are related to the similarly named + macros defined in the <stdarg.h> header file.

    + +

    All of these functions operate on arguments that use a target-specific value + type "va_list". The LLVM assembly language reference manual does + not define what this type is, so all transformations should be prepared to + handle these functions regardless of the type used.

    + +

    This example shows how the va_arg + instruction and the variable argument handling intrinsic functions are + used.

    + +
    +
    +define i32 @test(i32 %X, ...) {
    +  ; Initialize variable argument processing
    +  %ap = alloca i8*
    +  %ap2 = bitcast i8** %ap to i8*
    +  call void @llvm.va_start(i8* %ap2)
    +
    +  ; Read a single integer argument
    +  %tmp = va_arg i8** %ap, i32
    +
    +  ; Demonstrate usage of llvm.va_copy and llvm.va_end
    +  %aq = alloca i8*
    +  %aq2 = bitcast i8** %aq to i8*
    +  call void @llvm.va_copy(i8* %aq2, i8* %ap2)
    +  call void @llvm.va_end(i8* %aq2)
    +
    +  ; Stop processing of arguments.
    +  call void @llvm.va_end(i8* %ap2)
    +  ret i32 %tmp
    +}
    +
    +declare void @llvm.va_start(i8*)
    +declare void @llvm.va_copy(i8*, i8*)
    +declare void @llvm.va_end(i8*)
    +
    +
    + +
    + + + + + +
    + +
    Syntax:
    +
    +  declare void %llvm.va_start(i8* <arglist>)
    +
    + +
    Overview:
    +

    The 'llvm.va_start' intrinsic initializes *<arglist> + for subsequent use by va_arg.

    + +
    Arguments:
    +

    The argument is a pointer to a va_list element to initialize.

    + +
    Semantics:
    +

    The 'llvm.va_start' intrinsic works just like the va_start + macro available in C. In a target-dependent way, it initializes + the va_list element to which the argument points, so that the next + call to va_arg will produce the first variable argument passed to + the function. Unlike the C va_start macro, this intrinsic does not + need to know the last argument of the function as the compiler can figure + that out.

    + +
    + + + + +
    + +
    Syntax:
    +
    +  declare void @llvm.va_end(i8* <arglist>)
    +
    + +
    Overview:
    +

    The 'llvm.va_end' intrinsic destroys *<arglist>, + which has been initialized previously + with llvm.va_start + or llvm.va_copy.

    + +
    Arguments:
    +

    The argument is a pointer to a va_list to destroy.

    + +
    Semantics:
    +

    The 'llvm.va_end' intrinsic works just like the va_end + macro available in C. In a target-dependent way, it destroys + the va_list element to which the argument points. Calls + to llvm.va_start + and llvm.va_copy must be matched exactly + with calls to llvm.va_end.

    + +
    + + + + +
    + +
    Syntax:
    +
    +  declare void @llvm.va_copy(i8* <destarglist>, i8* <srcarglist>)
    +
    + +
    Overview:
    +

    The 'llvm.va_copy' intrinsic copies the current argument position + from the source argument list to the destination argument list.

    + +
    Arguments:
    +

    The first argument is a pointer to a va_list element to initialize. + The second argument is a pointer to a va_list element to copy + from.

    + +
    Semantics:
    +

    The 'llvm.va_copy' intrinsic works just like the va_copy + macro available in C. In a target-dependent way, it copies the + source va_list element into the destination va_list + element. This intrinsic is necessary because + the llvm.va_start intrinsic may be + arbitrarily complex and require, for example, memory allocation.

    + +
    + + + + +
    + +

    LLVM support for Accurate Garbage +Collection (GC) requires the implementation and generation of these +intrinsics. These intrinsics allow identification of GC +roots on the stack, as well as garbage collector implementations that +require read and write +barriers. Front-ends for type-safe garbage collected languages should generate +these intrinsics to make use of the LLVM garbage collectors. For more details, +see Accurate Garbage Collection with +LLVM.

    + +

    The garbage collection intrinsics only operate on objects in the generic + address space (address space zero).

    + +
    + + + + +
    + +
    Syntax:
    +
    +  declare void @llvm.gcroot(i8** %ptrloc, i8* %metadata)
    +
    + +
    Overview:
    +

    The 'llvm.gcroot' intrinsic declares the existence of a GC root to + the code generator, and allows some metadata to be associated with it.

    + +
    Arguments:
    +

    The first argument specifies the address of a stack object that contains the + root pointer. The second pointer (which must be either a constant or a + global value address) contains the meta-data to be associated with the + root.

    + +
    Semantics:
    +

    At runtime, a call to this intrinsic stores a null pointer into the "ptrloc" + location. At compile-time, the code generator generates information to allow + the runtime to find the pointer at GC safe points. The 'llvm.gcroot' + intrinsic may only be used in a function which specifies a GC + algorithm.

    + +
    + + + + +
    + +
    Syntax:
    +
    +  declare i8* @llvm.gcread(i8* %ObjPtr, i8** %Ptr)
    +
    + +
    Overview:
    +

    The 'llvm.gcread' intrinsic identifies reads of references from heap + locations, allowing garbage collector implementations that require read + barriers.

    + +
    Arguments:
    +

    The second argument is the address to read from, which should be an address + allocated from the garbage collector. The first object is a pointer to the + start of the referenced object, if needed by the language runtime (otherwise + null).

    + +
    Semantics:
    +

    The 'llvm.gcread' intrinsic has the same semantics as a load + instruction, but may be replaced with substantially more complex code by the + garbage collector runtime, as needed. The 'llvm.gcread' intrinsic + may only be used in a function which specifies a GC + algorithm.

    + +
    + + + + +
    + +
    Syntax:
    +
    +  declare void @llvm.gcwrite(i8* %P1, i8* %Obj, i8** %P2)
    +
    + +
    Overview:
    +

    The 'llvm.gcwrite' intrinsic identifies writes of references to heap + locations, allowing garbage collector implementations that require write + barriers (such as generational or reference counting collectors).

    + +
    Arguments:
    +

    The first argument is the reference to store, the second is the start of the + object to store it to, and the third is the address of the field of Obj to + store to. If the runtime does not require a pointer to the object, Obj may + be null.

    + +
    Semantics:
    +

    The 'llvm.gcwrite' intrinsic has the same semantics as a store + instruction, but may be replaced with substantially more complex code by the + garbage collector runtime, as needed. The 'llvm.gcwrite' intrinsic + may only be used in a function which specifies a GC + algorithm.

    + +
    + + + + +
    + +

    These intrinsics are provided by LLVM to expose special features that may + only be implemented with code generator support.

    + +
    + + + + +
    + +
    Syntax:
    +
    +  declare i8  *@llvm.returnaddress(i32 <level>)
    +
    + +
    Overview:
    +

    The 'llvm.returnaddress' intrinsic attempts to compute a + target-specific value indicating the return address of the current function + or one of its callers.

    + +
    Arguments:
    +

    The argument to this intrinsic indicates which function to return the address + for. Zero indicates the calling function, one indicates its caller, etc. + The argument is required to be a constant integer value.

    + +
    Semantics:
    +

    The 'llvm.returnaddress' intrinsic either returns a pointer + indicating the return address of the specified call frame, or zero if it + cannot be identified. The value returned by this intrinsic is likely to be + incorrect or 0 for arguments other than zero, so it should only be used for + debugging purposes.

    + +

    Note that calling this intrinsic does not prevent function inlining or other + aggressive transformations, so the value returned may not be that of the + obvious source-language caller.

    + +
    + + + + +
    + +
    Syntax:
    +
    +  declare i8 *@llvm.frameaddress(i32 <level>)
    +
    + +
    Overview:
    +

    The 'llvm.frameaddress' intrinsic attempts to return the + target-specific frame pointer value for the specified stack frame.

    + +
    Arguments:
    +

    The argument to this intrinsic indicates which function to return the frame + pointer for. Zero indicates the calling function, one indicates its caller, + etc. The argument is required to be a constant integer value.

    + +
    Semantics:
    +

    The 'llvm.frameaddress' intrinsic either returns a pointer + indicating the frame address of the specified call frame, or zero if it + cannot be identified. The value returned by this intrinsic is likely to be + incorrect or 0 for arguments other than zero, so it should only be used for + debugging purposes.

    + +

    Note that calling this intrinsic does not prevent function inlining or other + aggressive transformations, so the value returned may not be that of the + obvious source-language caller.

    + +
    + + + + +
    + +
    Syntax:
    +
    +  declare i8 *@llvm.stacksave()
    +
    + +
    Overview:
    +

    The 'llvm.stacksave' intrinsic is used to remember the current state + of the function stack, for use + with llvm.stackrestore. This is + useful for implementing language features like scoped automatic variable + sized arrays in C99.

    + +
    Semantics:
    +

    This intrinsic returns a opaque pointer value that can be passed + to llvm.stackrestore. When + an llvm.stackrestore intrinsic is executed with a value saved + from llvm.stacksave, it effectively restores the state of the stack + to the state it was in when the llvm.stacksave intrinsic executed. + In practice, this pops any alloca blocks from the + stack that were allocated after the llvm.stacksave was executed.

    + +
    + + + + +
    + +
    Syntax:
    +
    +  declare void @llvm.stackrestore(i8 * %ptr)
    +
    + +
    Overview:
    +

    The 'llvm.stackrestore' intrinsic is used to restore the state of + the function stack to the state it was in when the + corresponding llvm.stacksave intrinsic + executed. This is useful for implementing language features like scoped + automatic variable sized arrays in C99.

    + +
    Semantics:
    +

    See the description + for llvm.stacksave.

    + +
    + + + + +
    + +
    Syntax:
    +
    +  declare void @llvm.prefetch(i8* <address>, i32 <rw>, i32 <locality>)
    +
    + +
    Overview:
    +

    The 'llvm.prefetch' intrinsic is a hint to the code generator to + insert a prefetch instruction if supported; otherwise, it is a noop. + Prefetches have no effect on the behavior of the program but can change its + performance characteristics.

    + +
    Arguments:
    +

    address is the address to be prefetched, rw is the + specifier determining if the fetch should be for a read (0) or write (1), + and locality is a temporal locality specifier ranging from (0) - no + locality, to (3) - extremely local keep in cache. The rw + and locality arguments must be constant integers.

    + +
    Semantics:
    +

    This intrinsic does not modify the behavior of the program. In particular, + prefetches cannot trap and do not produce a value. On targets that support + this intrinsic, the prefetch can provide hints to the processor cache for + better performance.

    + +
    + + + + +
    + +
    Syntax:
    +
    +  declare void @llvm.pcmarker(i32 <id>)
    +
    + +
    Overview:
    +

    The 'llvm.pcmarker' intrinsic is a method to export a Program + Counter (PC) in a region of code to simulators and other tools. The method + is target specific, but it is expected that the marker will use exported + symbols to transmit the PC of the marker. The marker makes no guarantees + that it will remain with any specific instruction after optimizations. It is + possible that the presence of a marker will inhibit optimizations. The + intended use is to be inserted after optimizations to allow correlations of + simulation runs.

    + +
    Arguments:
    +

    id is a numerical id identifying the marker.

    + +
    Semantics:
    +

    This intrinsic does not modify the behavior of the program. Backends that do + not support this intrinisic may ignore it.

    + +
    + + + + +
    + +
    Syntax:
    +
    +  declare i64 @llvm.readcyclecounter( )
    +
    + +
    Overview:
    +

    The 'llvm.readcyclecounter' intrinsic provides access to the cycle + counter register (or similar low latency, high accuracy clocks) on those + targets that support it. On X86, it should map to RDTSC. On Alpha, it + should map to RPCC. As the backing counters overflow quickly (on the order + of 9 seconds on alpha), this should only be used for small timings.

    + +
    Semantics:
    +

    When directly supported, reading the cycle counter should not modify any + memory. Implementations are allowed to either return a application specific + value or a system wide value. On backends without support, this is lowered + to a constant 0.

    + +
    + + + + +
    + +

    LLVM provides intrinsics for a few important standard C library functions. + These intrinsics allow source-language front-ends to pass information about + the alignment of the pointer arguments to the code generator, providing + opportunity for more efficient code generation.

    + +
    + + + + +
    + +
    Syntax:
    +

    This is an overloaded intrinsic. You can use llvm.memcpy on any + integer bit width. Not all targets support all bit widths however.

    + +
    +  declare void @llvm.memcpy.i8(i8 * <dest>, i8 * <src>,
    +                               i8 <len>, i32 <align>)
    +  declare void @llvm.memcpy.i16(i8 * <dest>, i8 * <src>,
    +                                i16 <len>, i32 <align>)
    +  declare void @llvm.memcpy.i32(i8 * <dest>, i8 * <src>,
    +                                i32 <len>, i32 <align>)
    +  declare void @llvm.memcpy.i64(i8 * <dest>, i8 * <src>,
    +                                i64 <len>, i32 <align>)
    +
    + +
    Overview:
    +

    The 'llvm.memcpy.*' intrinsics copy a block of memory from the + source location to the destination location.

    + +

    Note that, unlike the standard libc function, the llvm.memcpy.* + intrinsics do not return a value, and takes an extra alignment argument.

    + +
    Arguments:
    +

    The first argument is a pointer to the destination, the second is a pointer + to the source. The third argument is an integer argument specifying the + number of bytes to copy, and the fourth argument is the alignment of the + source and destination locations.

    + +

    If the call to this intrinisic has an alignment value that is not 0 or 1, + then the caller guarantees that both the source and destination pointers are + aligned to that boundary.

    + +
    Semantics:
    +

    The 'llvm.memcpy.*' intrinsics copy a block of memory from the + source location to the destination location, which are not allowed to + overlap. It copies "len" bytes of memory over. If the argument is known to + be aligned to some boundary, this can be specified as the fourth argument, + otherwise it should be set to 0 or 1.

    + +
    + + + + +
    + +
    Syntax:
    +

    This is an overloaded intrinsic. You can use llvm.memmove on any integer bit + width. Not all targets support all bit widths however.

    + +
    +  declare void @llvm.memmove.i8(i8 * <dest>, i8 * <src>,
    +                                i8 <len>, i32 <align>)
    +  declare void @llvm.memmove.i16(i8 * <dest>, i8 * <src>,
    +                                 i16 <len>, i32 <align>)
    +  declare void @llvm.memmove.i32(i8 * <dest>, i8 * <src>,
    +                                 i32 <len>, i32 <align>)
    +  declare void @llvm.memmove.i64(i8 * <dest>, i8 * <src>,
    +                                 i64 <len>, i32 <align>)
    +
    + +
    Overview:
    +

    The 'llvm.memmove.*' intrinsics move a block of memory from the + source location to the destination location. It is similar to the + 'llvm.memcpy' intrinsic but allows the two memory locations to + overlap.

    + +

    Note that, unlike the standard libc function, the llvm.memmove.* + intrinsics do not return a value, and takes an extra alignment argument.

    + +
    Arguments:
    +

    The first argument is a pointer to the destination, the second is a pointer + to the source. The third argument is an integer argument specifying the + number of bytes to copy, and the fourth argument is the alignment of the + source and destination locations.

    + +

    If the call to this intrinisic has an alignment value that is not 0 or 1, + then the caller guarantees that the source and destination pointers are + aligned to that boundary.

    + +
    Semantics:
    +

    The 'llvm.memmove.*' intrinsics copy a block of memory from the + source location to the destination location, which may overlap. It copies + "len" bytes of memory over. If the argument is known to be aligned to some + boundary, this can be specified as the fourth argument, otherwise it should + be set to 0 or 1.

    + +
    + + + + +
    + +
    Syntax:
    +

    This is an overloaded intrinsic. You can use llvm.memset on any integer bit + width. Not all targets support all bit widths however.

    + +
    +  declare void @llvm.memset.i8(i8 * <dest>, i8 <val>,
    +                               i8 <len>, i32 <align>)
    +  declare void @llvm.memset.i16(i8 * <dest>, i8 <val>,
    +                                i16 <len>, i32 <align>)
    +  declare void @llvm.memset.i32(i8 * <dest>, i8 <val>,
    +                                i32 <len>, i32 <align>)
    +  declare void @llvm.memset.i64(i8 * <dest>, i8 <val>,
    +                                i64 <len>, i32 <align>)
    +
    + +
    Overview:
    +

    The 'llvm.memset.*' intrinsics fill a block of memory with a + particular byte value.

    + +

    Note that, unlike the standard libc function, the llvm.memset + intrinsic does not return a value, and takes an extra alignment argument.

    + +
    Arguments:
    +

    The first argument is a pointer to the destination to fill, the second is the + byte value to fill it with, the third argument is an integer argument + specifying the number of bytes to fill, and the fourth argument is the known + alignment of destination location.

    + +

    If the call to this intrinisic has an alignment value that is not 0 or 1, + then the caller guarantees that the destination pointer is aligned to that + boundary.

    + +
    Semantics:
    +

    The 'llvm.memset.*' intrinsics fill "len" bytes of memory starting + at the destination location. If the argument is known to be aligned to some + boundary, this can be specified as the fourth argument, otherwise it should + be set to 0 or 1.

    + +
    + + + + +
    + +
    Syntax:
    +

    This is an overloaded intrinsic. You can use llvm.sqrt on any + floating point or vector of floating point type. Not all targets support all + types however.

    + +
    +  declare float     @llvm.sqrt.f32(float %Val)
    +  declare double    @llvm.sqrt.f64(double %Val)
    +  declare x86_fp80  @llvm.sqrt.f80(x86_fp80 %Val)
    +  declare fp128     @llvm.sqrt.f128(fp128 %Val)
    +  declare ppc_fp128 @llvm.sqrt.ppcf128(ppc_fp128 %Val)
    +
    + +
    Overview:
    +

    The 'llvm.sqrt' intrinsics return the sqrt of the specified operand, + returning the same value as the libm 'sqrt' functions would. + Unlike sqrt in libm, however, llvm.sqrt has undefined + behavior for negative numbers other than -0.0 (which allows for better + optimization, because there is no need to worry about errno being + set). llvm.sqrt(-0.0) is defined to return -0.0 like IEEE sqrt.

    + +
    Arguments:
    +

    The argument and return value are floating point numbers of the same + type.

    + +
    Semantics:
    +

    This function returns the sqrt of the specified operand if it is a + nonnegative floating point number.

    + +
    + + + + +
    + +
    Syntax:
    +

    This is an overloaded intrinsic. You can use llvm.powi on any + floating point or vector of floating point type. Not all targets support all + types however.

    + +
    +  declare float     @llvm.powi.f32(float  %Val, i32 %power)
    +  declare double    @llvm.powi.f64(double %Val, i32 %power)
    +  declare x86_fp80  @llvm.powi.f80(x86_fp80  %Val, i32 %power)
    +  declare fp128     @llvm.powi.f128(fp128 %Val, i32 %power)
    +  declare ppc_fp128 @llvm.powi.ppcf128(ppc_fp128  %Val, i32 %power)
    +
    + +
    Overview:
    +

    The 'llvm.powi.*' intrinsics return the first operand raised to the + specified (positive or negative) power. The order of evaluation of + multiplications is not defined. When a vector of floating point type is + used, the second argument remains a scalar integer value.

    + +
    Arguments:
    +

    The second argument is an integer power, and the first is a value to raise to + that power.

    + +
    Semantics:
    +

    This function returns the first value raised to the second power with an + unspecified sequence of rounding operations.

    + +
    + + + + +
    + +
    Syntax:
    +

    This is an overloaded intrinsic. You can use llvm.sin on any + floating point or vector of floating point type. Not all targets support all + types however.

    + +
    +  declare float     @llvm.sin.f32(float  %Val)
    +  declare double    @llvm.sin.f64(double %Val)
    +  declare x86_fp80  @llvm.sin.f80(x86_fp80  %Val)
    +  declare fp128     @llvm.sin.f128(fp128 %Val)
    +  declare ppc_fp128 @llvm.sin.ppcf128(ppc_fp128  %Val)
    +
    + +
    Overview:
    +

    The 'llvm.sin.*' intrinsics return the sine of the operand.

    + +
    Arguments:
    +

    The argument and return value are floating point numbers of the same + type.

    + +
    Semantics:
    +

    This function returns the sine of the specified operand, returning the same + values as the libm sin functions would, and handles error conditions + in the same way.

    + +
    + + + + +
    + +
    Syntax:
    +

    This is an overloaded intrinsic. You can use llvm.cos on any + floating point or vector of floating point type. Not all targets support all + types however.

    + +
    +  declare float     @llvm.cos.f32(float  %Val)
    +  declare double    @llvm.cos.f64(double %Val)
    +  declare x86_fp80  @llvm.cos.f80(x86_fp80  %Val)
    +  declare fp128     @llvm.cos.f128(fp128 %Val)
    +  declare ppc_fp128 @llvm.cos.ppcf128(ppc_fp128  %Val)
    +
    + +
    Overview:
    +

    The 'llvm.cos.*' intrinsics return the cosine of the operand.

    + +
    Arguments:
    +

    The argument and return value are floating point numbers of the same + type.

    + +
    Semantics:
    +

    This function returns the cosine of the specified operand, returning the same + values as the libm cos functions would, and handles error conditions + in the same way.

    + +
    + + + + +
    + +
    Syntax:
    +

    This is an overloaded intrinsic. You can use llvm.pow on any + floating point or vector of floating point type. Not all targets support all + types however.

    + +
    +  declare float     @llvm.pow.f32(float  %Val, float %Power)
    +  declare double    @llvm.pow.f64(double %Val, double %Power)
    +  declare x86_fp80  @llvm.pow.f80(x86_fp80  %Val, x86_fp80 %Power)
    +  declare fp128     @llvm.pow.f128(fp128 %Val, fp128 %Power)
    +  declare ppc_fp128 @llvm.pow.ppcf128(ppc_fp128  %Val, ppc_fp128 Power)
    +
    + +
    Overview:
    +

    The 'llvm.pow.*' intrinsics return the first operand raised to the + specified (positive or negative) power.

    + +
    Arguments:
    +

    The second argument is a floating point power, and the first is a value to + raise to that power.

    + +
    Semantics:
    +

    This function returns the first value raised to the second power, returning + the same values as the libm pow functions would, and handles error + conditions in the same way.

    + +
    + + + + +
    + +

    LLVM provides intrinsics for a few important bit manipulation operations. + These allow efficient code generation for some algorithms.

    + +
    + + + + +
    + +
    Syntax:
    +

    This is an overloaded intrinsic function. You can use bswap on any integer + type that is an even number of bytes (i.e. BitWidth % 16 == 0).

    + +
    +  declare i16 @llvm.bswap.i16(i16 <id>)
    +  declare i32 @llvm.bswap.i32(i32 <id>)
    +  declare i64 @llvm.bswap.i64(i64 <id>)
    +
    + +
    Overview:
    +

    The 'llvm.bswap' family of intrinsics is used to byte swap integer + values with an even number of bytes (positive multiple of 16 bits). These + are useful for performing operations on data that is not in the target's + native byte order.

    + +
    Semantics:
    +

    The llvm.bswap.i16 intrinsic returns an i16 value that has the high + and low byte of the input i16 swapped. Similarly, + the llvm.bswap.i32 intrinsic returns an i32 value that has the four + bytes of the input i32 swapped, so that if the input bytes are numbered 0, 1, + 2, 3 then the returned i32 will have its bytes in 3, 2, 1, 0 order. + The llvm.bswap.i48, llvm.bswap.i64 and other intrinsics + extend this concept to additional even-byte lengths (6 bytes, 8 bytes and + more, respectively).

    + +
    + + + + +
    + +
    Syntax:
    +

    This is an overloaded intrinsic. You can use llvm.ctpop on any integer bit + width. Not all targets support all bit widths however.

    + +
    +  declare i8 @llvm.ctpop.i8(i8  <src>)
    +  declare i16 @llvm.ctpop.i16(i16 <src>)
    +  declare i32 @llvm.ctpop.i32(i32 <src>)
    +  declare i64 @llvm.ctpop.i64(i64 <src>)
    +  declare i256 @llvm.ctpop.i256(i256 <src>)
    +
    + +
    Overview:
    +

    The 'llvm.ctpop' family of intrinsics counts the number of bits set + in a value.

    + +
    Arguments:
    +

    The only argument is the value to be counted. The argument may be of any + integer type. The return type must match the argument type.

    + +
    Semantics:
    +

    The 'llvm.ctpop' intrinsic counts the 1's in a variable.

    + +
    + + + + +
    + +
    Syntax:
    +

    This is an overloaded intrinsic. You can use llvm.ctlz on any + integer bit width. Not all targets support all bit widths however.

    + +
    +  declare i8 @llvm.ctlz.i8 (i8  <src>)
    +  declare i16 @llvm.ctlz.i16(i16 <src>)
    +  declare i32 @llvm.ctlz.i32(i32 <src>)
    +  declare i64 @llvm.ctlz.i64(i64 <src>)
    +  declare i256 @llvm.ctlz.i256(i256 <src>)
    +
    + +
    Overview:
    +

    The 'llvm.ctlz' family of intrinsic functions counts the number of + leading zeros in a variable.

    + +
    Arguments:
    +

    The only argument is the value to be counted. The argument may be of any + integer type. The return type must match the argument type.

    + +
    Semantics:
    +

    The 'llvm.ctlz' intrinsic counts the leading (most significant) + zeros in a variable. If the src == 0 then the result is the size in bits of + the type of src. For example, llvm.ctlz(i32 2) = 30.

    + +
    + + + + +
    + +
    Syntax:
    +

    This is an overloaded intrinsic. You can use llvm.cttz on any + integer bit width. Not all targets support all bit widths however.

    + +
    +  declare i8 @llvm.cttz.i8 (i8  <src>)
    +  declare i16 @llvm.cttz.i16(i16 <src>)
    +  declare i32 @llvm.cttz.i32(i32 <src>)
    +  declare i64 @llvm.cttz.i64(i64 <src>)
    +  declare i256 @llvm.cttz.i256(i256 <src>)
    +
    + +
    Overview:
    +

    The 'llvm.cttz' family of intrinsic functions counts the number of + trailing zeros.

    + +
    Arguments:
    +

    The only argument is the value to be counted. The argument may be of any + integer type. The return type must match the argument type.

    + +
    Semantics:
    +

    The 'llvm.cttz' intrinsic counts the trailing (least significant) + zeros in a variable. If the src == 0 then the result is the size in bits of + the type of src. For example, llvm.cttz(2) = 1.

    + +
    + + + + +
    + +

    LLVM provides intrinsics for some arithmetic with overflow operations.

    + +
    + + + + +
    + +
    Syntax:
    +

    This is an overloaded intrinsic. You can use llvm.sadd.with.overflow + on any integer bit width.

    + +
    +  declare {i16, i1} @llvm.sadd.with.overflow.i16(i16 %a, i16 %b)
    +  declare {i32, i1} @llvm.sadd.with.overflow.i32(i32 %a, i32 %b)
    +  declare {i64, i1} @llvm.sadd.with.overflow.i64(i64 %a, i64 %b)
    +
    + +
    Overview:
    +

    The 'llvm.sadd.with.overflow' family of intrinsic functions perform + a signed addition of the two arguments, and indicate whether an overflow + occurred during the signed summation.

    + +
    Arguments:
    +

    The arguments (%a and %b) and the first element of the result structure may + be of integer types of any bit width, but they must have the same bit + width. The second element of the result structure must be of + type i1. %a and %b are the two values that will + undergo signed addition.

    + +
    Semantics:
    +

    The 'llvm.sadd.with.overflow' family of intrinsic functions perform + a signed addition of the two variables. They return a structure — the + first element of which is the signed summation, and the second element of + which is a bit specifying if the signed summation resulted in an + overflow.

    + +
    Examples:
    +
    +  %res = call {i32, i1} @llvm.sadd.with.overflow.i32(i32 %a, i32 %b)
    +  %sum = extractvalue {i32, i1} %res, 0
    +  %obit = extractvalue {i32, i1} %res, 1
    +  br i1 %obit, label %overflow, label %normal
    +
    + +
    + + + + +
    + +
    Syntax:
    +

    This is an overloaded intrinsic. You can use llvm.uadd.with.overflow + on any integer bit width.

    + +
    +  declare {i16, i1} @llvm.uadd.with.overflow.i16(i16 %a, i16 %b)
    +  declare {i32, i1} @llvm.uadd.with.overflow.i32(i32 %a, i32 %b)
    +  declare {i64, i1} @llvm.uadd.with.overflow.i64(i64 %a, i64 %b)
    +
    + +
    Overview:
    +

    The 'llvm.uadd.with.overflow' family of intrinsic functions perform + an unsigned addition of the two arguments, and indicate whether a carry + occurred during the unsigned summation.

    + +
    Arguments:
    +

    The arguments (%a and %b) and the first element of the result structure may + be of integer types of any bit width, but they must have the same bit + width. The second element of the result structure must be of + type i1. %a and %b are the two values that will + undergo unsigned addition.

    + +
    Semantics:
    +

    The 'llvm.uadd.with.overflow' family of intrinsic functions perform + an unsigned addition of the two arguments. They return a structure — + the first element of which is the sum, and the second element of which is a + bit specifying if the unsigned summation resulted in a carry.

    + +
    Examples:
    +
    +  %res = call {i32, i1} @llvm.uadd.with.overflow.i32(i32 %a, i32 %b)
    +  %sum = extractvalue {i32, i1} %res, 0
    +  %obit = extractvalue {i32, i1} %res, 1
    +  br i1 %obit, label %carry, label %normal
    +
    + +
    + + + + +
    + +
    Syntax:
    +

    This is an overloaded intrinsic. You can use llvm.ssub.with.overflow + on any integer bit width.

    + +
    +  declare {i16, i1} @llvm.ssub.with.overflow.i16(i16 %a, i16 %b)
    +  declare {i32, i1} @llvm.ssub.with.overflow.i32(i32 %a, i32 %b)
    +  declare {i64, i1} @llvm.ssub.with.overflow.i64(i64 %a, i64 %b)
    +
    + +
    Overview:
    +

    The 'llvm.ssub.with.overflow' family of intrinsic functions perform + a signed subtraction of the two arguments, and indicate whether an overflow + occurred during the signed subtraction.

    + +
    Arguments:
    +

    The arguments (%a and %b) and the first element of the result structure may + be of integer types of any bit width, but they must have the same bit + width. The second element of the result structure must be of + type i1. %a and %b are the two values that will + undergo signed subtraction.

    + +
    Semantics:
    +

    The 'llvm.ssub.with.overflow' family of intrinsic functions perform + a signed subtraction of the two arguments. They return a structure — + the first element of which is the subtraction, and the second element of + which is a bit specifying if the signed subtraction resulted in an + overflow.

    + +
    Examples:
    +
    +  %res = call {i32, i1} @llvm.ssub.with.overflow.i32(i32 %a, i32 %b)
    +  %sum = extractvalue {i32, i1} %res, 0
    +  %obit = extractvalue {i32, i1} %res, 1
    +  br i1 %obit, label %overflow, label %normal
    +
    + +
    + + + + +
    + +
    Syntax:
    +

    This is an overloaded intrinsic. You can use llvm.usub.with.overflow + on any integer bit width.

    + +
    +  declare {i16, i1} @llvm.usub.with.overflow.i16(i16 %a, i16 %b)
    +  declare {i32, i1} @llvm.usub.with.overflow.i32(i32 %a, i32 %b)
    +  declare {i64, i1} @llvm.usub.with.overflow.i64(i64 %a, i64 %b)
    +
    + +
    Overview:
    +

    The 'llvm.usub.with.overflow' family of intrinsic functions perform + an unsigned subtraction of the two arguments, and indicate whether an + overflow occurred during the unsigned subtraction.

    + +
    Arguments:
    +

    The arguments (%a and %b) and the first element of the result structure may + be of integer types of any bit width, but they must have the same bit + width. The second element of the result structure must be of + type i1. %a and %b are the two values that will + undergo unsigned subtraction.

    + +
    Semantics:
    +

    The 'llvm.usub.with.overflow' family of intrinsic functions perform + an unsigned subtraction of the two arguments. They return a structure — + the first element of which is the subtraction, and the second element of + which is a bit specifying if the unsigned subtraction resulted in an + overflow.

    + +
    Examples:
    +
    +  %res = call {i32, i1} @llvm.usub.with.overflow.i32(i32 %a, i32 %b)
    +  %sum = extractvalue {i32, i1} %res, 0
    +  %obit = extractvalue {i32, i1} %res, 1
    +  br i1 %obit, label %overflow, label %normal
    +
    + +
    + + + + +
    + +
    Syntax:
    +

    This is an overloaded intrinsic. You can use llvm.smul.with.overflow + on any integer bit width.

    + +
    +  declare {i16, i1} @llvm.smul.with.overflow.i16(i16 %a, i16 %b)
    +  declare {i32, i1} @llvm.smul.with.overflow.i32(i32 %a, i32 %b)
    +  declare {i64, i1} @llvm.smul.with.overflow.i64(i64 %a, i64 %b)
    +
    + +
    Overview:
    + +

    The 'llvm.smul.with.overflow' family of intrinsic functions perform + a signed multiplication of the two arguments, and indicate whether an + overflow occurred during the signed multiplication.

    + +
    Arguments:
    +

    The arguments (%a and %b) and the first element of the result structure may + be of integer types of any bit width, but they must have the same bit + width. The second element of the result structure must be of + type i1. %a and %b are the two values that will + undergo signed multiplication.

    + +
    Semantics:
    +

    The 'llvm.smul.with.overflow' family of intrinsic functions perform + a signed multiplication of the two arguments. They return a structure — + the first element of which is the multiplication, and the second element of + which is a bit specifying if the signed multiplication resulted in an + overflow.

    + +
    Examples:
    +
    +  %res = call {i32, i1} @llvm.smul.with.overflow.i32(i32 %a, i32 %b)
    +  %sum = extractvalue {i32, i1} %res, 0
    +  %obit = extractvalue {i32, i1} %res, 1
    +  br i1 %obit, label %overflow, label %normal
    +
    + +
    + + + + +
    + +
    Syntax:
    +

    This is an overloaded intrinsic. You can use llvm.umul.with.overflow + on any integer bit width.

    + +
    +  declare {i16, i1} @llvm.umul.with.overflow.i16(i16 %a, i16 %b)
    +  declare {i32, i1} @llvm.umul.with.overflow.i32(i32 %a, i32 %b)
    +  declare {i64, i1} @llvm.umul.with.overflow.i64(i64 %a, i64 %b)
    +
    + +
    Overview:
    +

    The 'llvm.umul.with.overflow' family of intrinsic functions perform + a unsigned multiplication of the two arguments, and indicate whether an + overflow occurred during the unsigned multiplication.

    + +
    Arguments:
    +

    The arguments (%a and %b) and the first element of the result structure may + be of integer types of any bit width, but they must have the same bit + width. The second element of the result structure must be of + type i1. %a and %b are the two values that will + undergo unsigned multiplication.

    + +
    Semantics:
    +

    The 'llvm.umul.with.overflow' family of intrinsic functions perform + an unsigned multiplication of the two arguments. They return a structure + — the first element of which is the multiplication, and the second + element of which is a bit specifying if the unsigned multiplication resulted + in an overflow.

    + +
    Examples:
    +
    +  %res = call {i32, i1} @llvm.umul.with.overflow.i32(i32 %a, i32 %b)
    +  %sum = extractvalue {i32, i1} %res, 0
    +  %obit = extractvalue {i32, i1} %res, 1
    +  br i1 %obit, label %overflow, label %normal
    +
    + +
    + + + + +
    + +

    The LLVM debugger intrinsics (which all start with llvm.dbg. + prefix), are described in + the LLVM Source + Level Debugging document.

    + +
    + + + + +
    + +

    The LLVM exception handling intrinsics (which all start with + llvm.eh. prefix), are described in + the LLVM Exception + Handling document.

    + +
    + + + + +
    + +

    This intrinsic makes it possible to excise one parameter, marked with + the nest attribute, from a function. The result is a callable + function pointer lacking the nest parameter - the caller does not need to + provide a value for it. Instead, the value to use is stored in advance in a + "trampoline", a block of memory usually allocated on the stack, which also + contains code to splice the nest value into the argument list. This is used + to implement the GCC nested function address extension.

    + +

    For example, if the function is + i32 f(i8* nest %c, i32 %x, i32 %y) then the resulting function + pointer has signature i32 (i32, i32)*. It can be created as + follows:

    + +
    +
    +  %tramp = alloca [10 x i8], align 4 ; size and alignment only correct for X86
    +  %tramp1 = getelementptr [10 x i8]* %tramp, i32 0, i32 0
    +  %p = call i8* @llvm.init.trampoline( i8* %tramp1, i8* bitcast (i32 (i8* nest , i32, i32)* @f to i8*), i8* %nval )
    +  %fp = bitcast i8* %p to i32 (i32, i32)*
    +
    +
    + +

    The call %val = call i32 %fp( i32 %x, i32 %y ) is then equivalent + to %val = call i32 %f( i8* %nval, i32 %x, i32 %y ).

    + +
    + + + + +
    + +
    Syntax:
    +
    +  declare i8* @llvm.init.trampoline(i8* <tramp>, i8* <func>, i8* <nval>)
    +
    + +
    Overview:
    +

    This fills the memory pointed to by tramp with code and returns a + function pointer suitable for executing it.

    + +
    Arguments:
    +

    The llvm.init.trampoline intrinsic takes three arguments, all + pointers. The tramp argument must point to a sufficiently large and + sufficiently aligned block of memory; this memory is written to by the + intrinsic. Note that the size and the alignment are target-specific - LLVM + currently provides no portable way of determining them, so a front-end that + generates this intrinsic needs to have some target-specific knowledge. + The func argument must hold a function bitcast to + an i8*.

    + +
    Semantics:
    +

    The block of memory pointed to by tramp is filled with target + dependent code, turning it into a function. A pointer to this function is + returned, but needs to be bitcast to an appropriate + function pointer type before being called. The new function's signature + is the same as that of func with any arguments marked with + the nest attribute removed. At most one such nest argument + is allowed, and it must be of pointer type. Calling the new function is + equivalent to calling func with the same argument list, but + with nval used for the missing nest argument. If, after + calling llvm.init.trampoline, the memory pointed to + by tramp is modified, then the effect of any later call to the + returned function pointer is undefined.

    + +
    + + + + +
    + +

    These intrinsic functions expand the "universal IR" of LLVM to represent + hardware constructs for atomic operations and memory synchronization. This + provides an interface to the hardware, not an interface to the programmer. It + is aimed at a low enough level to allow any programming models or APIs + (Application Programming Interfaces) which need atomic behaviors to map + cleanly onto it. It is also modeled primarily on hardware behavior. Just as + hardware provides a "universal IR" for source languages, it also provides a + starting point for developing a "universal" atomic operation and + synchronization IR.

    + +

    These do not form an API such as high-level threading libraries, + software transaction memory systems, atomic primitives, and intrinsic + functions as found in BSD, GNU libc, atomic_ops, APR, and other system and + application libraries. The hardware interface provided by LLVM should allow + a clean implementation of all of these APIs and parallel programming models. + No one model or paradigm should be selected above others unless the hardware + itself ubiquitously does so.

    + +
    + + + +
    +
    Syntax:
    +
    +  declare void @llvm.memory.barrier( i1 <ll>, i1 <ls>, i1 <sl>, i1 <ss>, i1 <device> )
    +
    + +
    Overview:
    +

    The llvm.memory.barrier intrinsic guarantees ordering between + specific pairs of memory access types.

    + +
    Arguments:
    +

    The llvm.memory.barrier intrinsic requires five boolean arguments. + The first four arguments enables a specific barrier as listed below. The + fith argument specifies that the barrier applies to io or device or uncached + memory.

    + +
      +
    • ll: load-load barrier
    • +
    • ls: load-store barrier
    • +
    • sl: store-load barrier
    • +
    • ss: store-store barrier
    • +
    • device: barrier applies to device and uncached memory also.
    • +
    + +
    Semantics:
    +

    This intrinsic causes the system to enforce some ordering constraints upon + the loads and stores of the program. This barrier does not + indicate when any events will occur, it only enforces + an order in which they occur. For any of the specified pairs of load + and store operations (f.ex. load-load, or store-load), all of the first + operations preceding the barrier will complete before any of the second + operations succeeding the barrier begin. Specifically the semantics for each + pairing is as follows:

    + +
      +
    • ll: All loads before the barrier must complete before any load + after the barrier begins.
    • +
    • ls: All loads before the barrier must complete before any + store after the barrier begins.
    • +
    • ss: All stores before the barrier must complete before any + store after the barrier begins.
    • +
    • sl: All stores before the barrier must complete before any + load after the barrier begins.
    • +
    + +

    These semantics are applied with a logical "and" behavior when more than one + is enabled in a single memory barrier intrinsic.

    + +

    Backends may implement stronger barriers than those requested when they do + not support as fine grained a barrier as requested. Some architectures do + not need all types of barriers and on such architectures, these become + noops.

    + +
    Example:
    +
    +%mallocP  = tail call i8* @malloc(i32 ptrtoint (i32* getelementptr (i32* null, i32 1) to i32))
    +%ptr      = bitcast i8* %mallocP to i32*
    +            store i32 4, %ptr
    +
    +%result1  = load i32* %ptr      ; yields {i32}:result1 = 4
    +            call void @llvm.memory.barrier( i1 false, i1 true, i1 false, i1 false )
    +                                ; guarantee the above finishes
    +            store i32 8, %ptr   ; before this begins
    +
    + +
    + + + + +
    + +
    Syntax:
    +

    This is an overloaded intrinsic. You can use llvm.atomic.cmp.swap on + any integer bit width and for different address spaces. Not all targets + support all bit widths however.

    + +
    +  declare i8 @llvm.atomic.cmp.swap.i8.p0i8( i8* <ptr>, i8 <cmp>, i8 <val> )
    +  declare i16 @llvm.atomic.cmp.swap.i16.p0i16( i16* <ptr>, i16 <cmp>, i16 <val> )
    +  declare i32 @llvm.atomic.cmp.swap.i32.p0i32( i32* <ptr>, i32 <cmp>, i32 <val> )
    +  declare i64 @llvm.atomic.cmp.swap.i64.p0i64( i64* <ptr>, i64 <cmp>, i64 <val> )
    +
    + +
    Overview:
    +

    This loads a value in memory and compares it to a given value. If they are + equal, it stores a new value into the memory.

    + +
    Arguments:
    +

    The llvm.atomic.cmp.swap intrinsic takes three arguments. The result + as well as both cmp and val must be integer values with the + same bit width. The ptr argument must be a pointer to a value of + this integer type. While any bit width integer may be used, targets may only + lower representations they support in hardware.

    + +
    Semantics:
    +

    This entire intrinsic must be executed atomically. It first loads the value + in memory pointed to by ptr and compares it with the + value cmp. If they are equal, val is stored into the + memory. The loaded value is yielded in all cases. This provides the + equivalent of an atomic compare-and-swap operation within the SSA + framework.

    + +
    Examples:
    +
    +%mallocP  = tail call i8* @malloc(i32 ptrtoint (i32* getelementptr (i32* null, i32 1) to i32))
    +%ptr      = bitcast i8* %mallocP to i32*
    +            store i32 4, %ptr
    +
    +%val1     = add i32 4, 4
    +%result1  = call i32 @llvm.atomic.cmp.swap.i32.p0i32( i32* %ptr, i32 4, %val1 )
    +                                          ; yields {i32}:result1 = 4
    +%stored1  = icmp eq i32 %result1, 4       ; yields {i1}:stored1 = true
    +%memval1  = load i32* %ptr                ; yields {i32}:memval1 = 8
    +
    +%val2     = add i32 1, 1
    +%result2  = call i32 @llvm.atomic.cmp.swap.i32.p0i32( i32* %ptr, i32 5, %val2 )
    +                                          ; yields {i32}:result2 = 8
    +%stored2  = icmp eq i32 %result2, 5       ; yields {i1}:stored2 = false
    +
    +%memval2  = load i32* %ptr                ; yields {i32}:memval2 = 8
    +
    + +
    + + + +
    +
    Syntax:
    + +

    This is an overloaded intrinsic. You can use llvm.atomic.swap on any + integer bit width. Not all targets support all bit widths however.

    + +
    +  declare i8 @llvm.atomic.swap.i8.p0i8( i8* <ptr>, i8 <val> )
    +  declare i16 @llvm.atomic.swap.i16.p0i16( i16* <ptr>, i16 <val> )
    +  declare i32 @llvm.atomic.swap.i32.p0i32( i32* <ptr>, i32 <val> )
    +  declare i64 @llvm.atomic.swap.i64.p0i64( i64* <ptr>, i64 <val> )
    +
    + +
    Overview:
    +

    This intrinsic loads the value stored in memory at ptr and yields + the value from memory. It then stores the value in val in the memory + at ptr.

    + +
    Arguments:
    +

    The llvm.atomic.swap intrinsic takes two arguments. Both + the val argument and the result must be integers of the same bit + width. The first argument, ptr, must be a pointer to a value of this + integer type. The targets may only lower integer representations they + support.

    + +
    Semantics:
    +

    This intrinsic loads the value pointed to by ptr, yields it, and + stores val back into ptr atomically. This provides the + equivalent of an atomic swap operation within the SSA framework.

    + +
    Examples:
    +
    +%mallocP  = tail call i8* @malloc(i32 ptrtoint (i32* getelementptr (i32* null, i32 1) to i32))
    +%ptr      = bitcast i8* %mallocP to i32*
    +            store i32 4, %ptr
    +
    +%val1     = add i32 4, 4
    +%result1  = call i32 @llvm.atomic.swap.i32.p0i32( i32* %ptr, i32 %val1 )
    +                                        ; yields {i32}:result1 = 4
    +%stored1  = icmp eq i32 %result1, 4     ; yields {i1}:stored1 = true
    +%memval1  = load i32* %ptr              ; yields {i32}:memval1 = 8
    +
    +%val2     = add i32 1, 1
    +%result2  = call i32 @llvm.atomic.swap.i32.p0i32( i32* %ptr, i32 %val2 )
    +                                        ; yields {i32}:result2 = 8
    +
    +%stored2  = icmp eq i32 %result2, 8     ; yields {i1}:stored2 = true
    +%memval2  = load i32* %ptr              ; yields {i32}:memval2 = 2
    +
    + +
    + + + + +
    + +
    Syntax:
    +

    This is an overloaded intrinsic. You can use llvm.atomic.load.add on + any integer bit width. Not all targets support all bit widths however.

    + +
    +  declare i8 @llvm.atomic.load.add.i8..p0i8( i8* <ptr>, i8 <delta> )
    +  declare i16 @llvm.atomic.load.add.i16..p0i16( i16* <ptr>, i16 <delta> )
    +  declare i32 @llvm.atomic.load.add.i32..p0i32( i32* <ptr>, i32 <delta> )
    +  declare i64 @llvm.atomic.load.add.i64..p0i64( i64* <ptr>, i64 <delta> )
    +
    + +
    Overview:
    +

    This intrinsic adds delta to the value stored in memory + at ptr. It yields the original value at ptr.

    + +
    Arguments:
    +

    The intrinsic takes two arguments, the first a pointer to an integer value + and the second an integer value. The result is also an integer value. These + integer types can have any bit width, but they must all have the same bit + width. The targets may only lower integer representations they support.

    + +
    Semantics:
    +

    This intrinsic does a series of operations atomically. It first loads the + value stored at ptr. It then adds delta, stores the result + to ptr. It yields the original value stored at ptr.

    + +
    Examples:
    +
    +%mallocP  = tail call i8* @malloc(i32 ptrtoint (i32* getelementptr (i32* null, i32 1) to i32))
    +%ptr      = bitcast i8* %mallocP to i32*
    +            store i32 4, %ptr
    +%result1  = call i32 @llvm.atomic.load.add.i32.p0i32( i32* %ptr, i32 4 )
    +                                ; yields {i32}:result1 = 4
    +%result2  = call i32 @llvm.atomic.load.add.i32.p0i32( i32* %ptr, i32 2 )
    +                                ; yields {i32}:result2 = 8
    +%result3  = call i32 @llvm.atomic.load.add.i32.p0i32( i32* %ptr, i32 5 )
    +                                ; yields {i32}:result3 = 10
    +%memval1  = load i32* %ptr      ; yields {i32}:memval1 = 15
    +
    + +
    + + + + +
    + +
    Syntax:
    +

    This is an overloaded intrinsic. You can use llvm.atomic.load.sub on + any integer bit width and for different address spaces. Not all targets + support all bit widths however.

    + +
    +  declare i8 @llvm.atomic.load.sub.i8.p0i32( i8* <ptr>, i8 <delta> )
    +  declare i16 @llvm.atomic.load.sub.i16.p0i32( i16* <ptr>, i16 <delta> )
    +  declare i32 @llvm.atomic.load.sub.i32.p0i32( i32* <ptr>, i32 <delta> )
    +  declare i64 @llvm.atomic.load.sub.i64.p0i32( i64* <ptr>, i64 <delta> )
    +
    + +
    Overview:
    +

    This intrinsic subtracts delta to the value stored in memory at + ptr. It yields the original value at ptr.

    + +
    Arguments:
    +

    The intrinsic takes two arguments, the first a pointer to an integer value + and the second an integer value. The result is also an integer value. These + integer types can have any bit width, but they must all have the same bit + width. The targets may only lower integer representations they support.

    + +
    Semantics:
    +

    This intrinsic does a series of operations atomically. It first loads the + value stored at ptr. It then subtracts delta, stores the + result to ptr. It yields the original value stored + at ptr.

    + +
    Examples:
    +
    +%mallocP  = tail call i8* @malloc(i32 ptrtoint (i32* getelementptr (i32* null, i32 1) to i32))
    +%ptr      = bitcast i8* %mallocP to i32*
    +            store i32 8, %ptr
    +%result1  = call i32 @llvm.atomic.load.sub.i32.p0i32( i32* %ptr, i32 4 )
    +                                ; yields {i32}:result1 = 8
    +%result2  = call i32 @llvm.atomic.load.sub.i32.p0i32( i32* %ptr, i32 2 )
    +                                ; yields {i32}:result2 = 4
    +%result3  = call i32 @llvm.atomic.load.sub.i32.p0i32( i32* %ptr, i32 5 )
    +                                ; yields {i32}:result3 = 2
    +%memval1  = load i32* %ptr      ; yields {i32}:memval1 = -3
    +
    + +
    + + + + +
    + +
    Syntax:
    +

    These are overloaded intrinsics. You can + use llvm.atomic.load_and, llvm.atomic.load_nand, + llvm.atomic.load_or, and llvm.atomic.load_xor on any integer + bit width and for different address spaces. Not all targets support all bit + widths however.

    + +
    +  declare i8 @llvm.atomic.load.and.i8.p0i8( i8* <ptr>, i8 <delta> )
    +  declare i16 @llvm.atomic.load.and.i16.p0i16( i16* <ptr>, i16 <delta> )
    +  declare i32 @llvm.atomic.load.and.i32.p0i32( i32* <ptr>, i32 <delta> )
    +  declare i64 @llvm.atomic.load.and.i64.p0i64( i64* <ptr>, i64 <delta> )
    +
    + +
    +  declare i8 @llvm.atomic.load.or.i8.p0i8( i8* <ptr>, i8 <delta> )
    +  declare i16 @llvm.atomic.load.or.i16.p0i16( i16* <ptr>, i16 <delta> )
    +  declare i32 @llvm.atomic.load.or.i32.p0i32( i32* <ptr>, i32 <delta> )
    +  declare i64 @llvm.atomic.load.or.i64.p0i64( i64* <ptr>, i64 <delta> )
    +
    + +
    +  declare i8 @llvm.atomic.load.nand.i8.p0i32( i8* <ptr>, i8 <delta> )
    +  declare i16 @llvm.atomic.load.nand.i16.p0i32( i16* <ptr>, i16 <delta> )
    +  declare i32 @llvm.atomic.load.nand.i32.p0i32( i32* <ptr>, i32 <delta> )
    +  declare i64 @llvm.atomic.load.nand.i64.p0i32( i64* <ptr>, i64 <delta> )
    +
    + +
    +  declare i8 @llvm.atomic.load.xor.i8.p0i32( i8* <ptr>, i8 <delta> )
    +  declare i16 @llvm.atomic.load.xor.i16.p0i32( i16* <ptr>, i16 <delta> )
    +  declare i32 @llvm.atomic.load.xor.i32.p0i32( i32* <ptr>, i32 <delta> )
    +  declare i64 @llvm.atomic.load.xor.i64.p0i32( i64* <ptr>, i64 <delta> )
    +
    + +
    Overview:
    +

    These intrinsics bitwise the operation (and, nand, or, xor) delta to + the value stored in memory at ptr. It yields the original value + at ptr.

    + +
    Arguments:
    +

    These intrinsics take two arguments, the first a pointer to an integer value + and the second an integer value. The result is also an integer value. These + integer types can have any bit width, but they must all have the same bit + width. The targets may only lower integer representations they support.

    + +
    Semantics:
    +

    These intrinsics does a series of operations atomically. They first load the + value stored at ptr. They then do the bitwise + operation delta, store the result to ptr. They yield the + original value stored at ptr.

    + +
    Examples:
    +
    +%mallocP  = tail call i8* @malloc(i32 ptrtoint (i32* getelementptr (i32* null, i32 1) to i32))
    +%ptr      = bitcast i8* %mallocP to i32*
    +            store i32 0x0F0F, %ptr
    +%result0  = call i32 @llvm.atomic.load.nand.i32.p0i32( i32* %ptr, i32 0xFF )
    +                                ; yields {i32}:result0 = 0x0F0F
    +%result1  = call i32 @llvm.atomic.load.and.i32.p0i32( i32* %ptr, i32 0xFF )
    +                                ; yields {i32}:result1 = 0xFFFFFFF0
    +%result2  = call i32 @llvm.atomic.load.or.i32.p0i32( i32* %ptr, i32 0F )
    +                                ; yields {i32}:result2 = 0xF0
    +%result3  = call i32 @llvm.atomic.load.xor.i32.p0i32( i32* %ptr, i32 0F )
    +                                ; yields {i32}:result3 = FF
    +%memval1  = load i32* %ptr      ; yields {i32}:memval1 = F0
    +
    + +
    + + + + +
    + +
    Syntax:
    +

    These are overloaded intrinsics. You can use llvm.atomic.load_max, + llvm.atomic.load_min, llvm.atomic.load_umax, and + llvm.atomic.load_umin on any integer bit width and for different + address spaces. Not all targets support all bit widths however.

    + +
    +  declare i8 @llvm.atomic.load.max.i8.p0i8( i8* <ptr>, i8 <delta> )
    +  declare i16 @llvm.atomic.load.max.i16.p0i16( i16* <ptr>, i16 <delta> )
    +  declare i32 @llvm.atomic.load.max.i32.p0i32( i32* <ptr>, i32 <delta> )
    +  declare i64 @llvm.atomic.load.max.i64.p0i64( i64* <ptr>, i64 <delta> )
    +
    + +
    +  declare i8 @llvm.atomic.load.min.i8.p0i8( i8* <ptr>, i8 <delta> )
    +  declare i16 @llvm.atomic.load.min.i16.p0i16( i16* <ptr>, i16 <delta> )
    +  declare i32 @llvm.atomic.load.min.i32..p0i32( i32* <ptr>, i32 <delta> )
    +  declare i64 @llvm.atomic.load.min.i64..p0i64( i64* <ptr>, i64 <delta> )
    +
    + +
    +  declare i8 @llvm.atomic.load.umax.i8.p0i8( i8* <ptr>, i8 <delta> )
    +  declare i16 @llvm.atomic.load.umax.i16.p0i16( i16* <ptr>, i16 <delta> )
    +  declare i32 @llvm.atomic.load.umax.i32.p0i32( i32* <ptr>, i32 <delta> )
    +  declare i64 @llvm.atomic.load.umax.i64.p0i64( i64* <ptr>, i64 <delta> )
    +
    + +
    +  declare i8 @llvm.atomic.load.umin.i8..p0i8( i8* <ptr>, i8 <delta> )
    +  declare i16 @llvm.atomic.load.umin.i16.p0i16( i16* <ptr>, i16 <delta> )
    +  declare i32 @llvm.atomic.load.umin.i32..p0i32( i32* <ptr>, i32 <delta> )
    +  declare i64 @llvm.atomic.load.umin.i64..p0i64( i64* <ptr>, i64 <delta> )
    +
    + +
    Overview:
    +

    These intrinsics takes the signed or unsigned minimum or maximum of + delta and the value stored in memory at ptr. It yields the + original value at ptr.

    + +
    Arguments:
    +

    These intrinsics take two arguments, the first a pointer to an integer value + and the second an integer value. The result is also an integer value. These + integer types can have any bit width, but they must all have the same bit + width. The targets may only lower integer representations they support.

    + +
    Semantics:
    +

    These intrinsics does a series of operations atomically. They first load the + value stored at ptr. They then do the signed or unsigned min or + max delta and the value, store the result to ptr. They + yield the original value stored at ptr.

    + +
    Examples:
    +
    +%mallocP  = tail call i8* @malloc(i32 ptrtoint (i32* getelementptr (i32* null, i32 1) to i32))
    +%ptr      = bitcast i8* %mallocP to i32*
    +            store i32 7, %ptr
    +%result0  = call i32 @llvm.atomic.load.min.i32.p0i32( i32* %ptr, i32 -2 )
    +                                ; yields {i32}:result0 = 7
    +%result1  = call i32 @llvm.atomic.load.max.i32.p0i32( i32* %ptr, i32 8 )
    +                                ; yields {i32}:result1 = -2
    +%result2  = call i32 @llvm.atomic.load.umin.i32.p0i32( i32* %ptr, i32 10 )
    +                                ; yields {i32}:result2 = 8
    +%result3  = call i32 @llvm.atomic.load.umax.i32.p0i32( i32* %ptr, i32 30 )
    +                                ; yields {i32}:result3 = 8
    +%memval1  = load i32* %ptr      ; yields {i32}:memval1 = 30
    +
    + +
    + + + + + +
    + +

    This class of intrinsics exists to information about the lifetime of memory + objects and ranges where variables are immutable.

    + +
    + + + + +
    + +
    Syntax:
    +
    +  declare void @llvm.lifetime.start(i64 <size>, i8* nocapture <ptr>)
    +
    + +
    Overview:
    +

    The 'llvm.lifetime.start' intrinsic specifies the start of a memory + object's lifetime.

    + +
    Arguments:
    +

    The first argument is a constant integer representing the size of the + object, or -1 if it is variable sized. The second argument is a pointer to + the object.

    + +
    Semantics:
    +

    This intrinsic indicates that before this point in the code, the value of the + memory pointed to by ptr is dead. This means that it is known to + never be used and has an undefined value. A load from the pointer that + precedes this intrinsic can be replaced with + 'undef'.

    + +
    + + + + +
    + +
    Syntax:
    +
    +  declare void @llvm.lifetime.end(i64 <size>, i8* nocapture <ptr>)
    +
    + +
    Overview:
    +

    The 'llvm.lifetime.end' intrinsic specifies the end of a memory + object's lifetime.

    + +
    Arguments:
    +

    The first argument is a constant integer representing the size of the + object, or -1 if it is variable sized. The second argument is a pointer to + the object.

    + +
    Semantics:
    +

    This intrinsic indicates that after this point in the code, the value of the + memory pointed to by ptr is dead. This means that it is known to + never be used and has an undefined value. Any stores into the memory object + following this intrinsic may be removed as dead. + +

    + + + + +
    + +
    Syntax:
    +
    +  declare {}* @llvm.invariant.start(i64 <size>, i8* nocapture <ptr>) readonly
    +
    + +
    Overview:
    +

    The 'llvm.invariant.start' intrinsic specifies that the contents of + a memory object will not change.

    + +
    Arguments:
    +

    The first argument is a constant integer representing the size of the + object, or -1 if it is variable sized. The second argument is a pointer to + the object.

    + +
    Semantics:
    +

    This intrinsic indicates that until an llvm.invariant.end that uses + the return value, the referenced memory location is constant and + unchanging.

    + +
    + + + + +
    + +
    Syntax:
    +
    +  declare void @llvm.invariant.end({}* <start>, i64 <size>, i8* nocapture <ptr>)
    +
    + +
    Overview:
    +

    The 'llvm.invariant.end' intrinsic specifies that the contents of + a memory object are mutable.

    + +
    Arguments:
    +

    The first argument is the matching llvm.invariant.start intrinsic. + The second argument is a constant integer representing the size of the + object, or -1 if it is variable sized and the third argument is a pointer + to the object.

    + +
    Semantics:
    +

    This intrinsic indicates that the memory is mutable again.

    + +
    + + + + +
    + +

    This class of intrinsics is designed to be generic and has no specific + purpose.

    + +
    + + + + +
    + +
    Syntax:
    +
    +  declare void @llvm.var.annotation(i8* <val>, i8* <str>, i8* <str>, i32  <int> )
    +
    + +
    Overview:
    +

    The 'llvm.var.annotation' intrinsic.

    + +
    Arguments:
    +

    The first argument is a pointer to a value, the second is a pointer to a + global string, the third is a pointer to a global string which is the source + file name, and the last argument is the line number.

    + +
    Semantics:
    +

    This intrinsic allows annotation of local variables with arbitrary strings. + This can be useful for special purpose optimizations that want to look for + these annotations. These have no other defined use, they are ignored by code + generation and optimization.

    + +
    + + + + +
    + +
    Syntax:
    +

    This is an overloaded intrinsic. You can use 'llvm.annotation' on + any integer bit width.

    + +
    +  declare i8 @llvm.annotation.i8(i8 <val>, i8* <str>, i8* <str>, i32  <int> )
    +  declare i16 @llvm.annotation.i16(i16 <val>, i8* <str>, i8* <str>, i32  <int> )
    +  declare i32 @llvm.annotation.i32(i32 <val>, i8* <str>, i8* <str>, i32  <int> )
    +  declare i64 @llvm.annotation.i64(i64 <val>, i8* <str>, i8* <str>, i32  <int> )
    +  declare i256 @llvm.annotation.i256(i256 <val>, i8* <str>, i8* <str>, i32  <int> )
    +
    + +
    Overview:
    +

    The 'llvm.annotation' intrinsic.

    + +
    Arguments:
    +

    The first argument is an integer value (result of some expression), the + second is a pointer to a global string, the third is a pointer to a global + string which is the source file name, and the last argument is the line + number. It returns the value of the first argument.

    + +
    Semantics:
    +

    This intrinsic allows annotations to be put on arbitrary expressions with + arbitrary strings. This can be useful for special purpose optimizations that + want to look for these annotations. These have no other defined use, they + are ignored by code generation and optimization.

    + +
    + + + + +
    + +
    Syntax:
    +
    +  declare void @llvm.trap()
    +
    + +
    Overview:
    +

    The 'llvm.trap' intrinsic.

    + +
    Arguments:
    +

    None.

    + +
    Semantics:
    +

    This intrinsics is lowered to the target dependent trap instruction. If the + target does not have a trap instruction, this intrinsic will be lowered to + the call of the abort() function.

    + +
    + + + + +
    + +
    Syntax:
    +
    +  declare void @llvm.stackprotector( i8* <guard>, i8** <slot> )
    +
    + +
    Overview:
    +

    The llvm.stackprotector intrinsic takes the guard and + stores it onto the stack at slot. The stack slot is adjusted to + ensure that it is placed on the stack before local variables.

    + +
    Arguments:
    +

    The llvm.stackprotector intrinsic requires two pointer + arguments. The first argument is the value loaded from the stack + guard @__stack_chk_guard. The second variable is an alloca + that has enough space to hold the value of the guard.

    + +
    Semantics:
    +

    This intrinsic causes the prologue/epilogue inserter to force the position of + the AllocaInst stack slot to be before local variables on the + stack. This is to ensure that if a local variable on the stack is + overwritten, it will destroy the value of the guard. When the function exits, + the guard on the stack is checked against the original guard. If they're + different, then the program aborts by calling the __stack_chk_fail() + function.

    + +
    + + +
    +
    + Valid CSS + Valid HTML 4.01 + + Chris Lattner
    + The LLVM Compiler Infrastructure
    + Last modified: $Date$ +
    + + + diff --git a/libclamav/c++/llvm/docs/Lexicon.html b/libclamav/c++/llvm/docs/Lexicon.html new file mode 100644 index 000000000..820fdd6f0 --- /dev/null +++ b/libclamav/c++/llvm/docs/Lexicon.html @@ -0,0 +1,263 @@ + + + + + The LLVM Lexicon + + + + + +
    The LLVM Lexicon
    +

    NOTE: This document is a work in progress!

    + +
    Table Of Contents
    + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    - A -
    ADCE
    - B -
    BURS
    - C -
    CSE
    - D -
    DAGDerived PointerDSADSE
    - G -
    GC
    - I -
    IPAIPOISel
    - L -
    LCSSALICMLoad-VN
    - O -
    Object Pointer
    - P -
    PRE
    - R -
    RAUWReassociationRoot
    - S -
    Safe PointSCCSCCPSDISelSRoAStack Map
    +
    + + +
    Definitions
    + + + +
    +
    +
    ADCE
    +
    Aggressive Dead Code Elimination
    +
    +
    + + +
    +
    +
    BURS
    +
    Bottom Up Rewriting System—A method of instruction selection for + code generation. An example is the BURG tool.
    +
    +
    + + +
    +
    +
    CSE
    +
    Common Subexpression Elimination. An optimization that removes common + subexpression compuation. For example (a+b)*(a+b) has two + subexpressions that are the same: (a+b). This optimization would + perform the addition only once and then perform the multiply (but only if + it's compulationally correct/safe). +
    +
    + + +
    +
    +
    DAG
    +
    Directed Acyclic Graph
    +
    Derived Pointer
    +
    A pointer to the interior of an object, such that a garbage collector + is unable to use the pointer for reachability analysis. While a derived + pointer is live, the corresponding object pointer must be kept in a root, + otherwise the collector might free the referenced object. With copying + collectors, derived pointers pose an additional hazard that they may be + invalidated at any safe point. This term is used in + opposition to object pointer.
    +
    DSA
    +
    Data Structure Analysis
    +
    DSE
    +
    Dead Store Elimination
    +
    +
    + + +
    +
    +
    GC
    +
    Garbage Collection. The practice of using reachability analysis instead + of explicit memory management to reclaim unused memory.
    +
    +
    + + +
    +
    +
    Heap
    +
    In garbage collection, the region of memory which is managed using + reachability analysis.
    +
    +
    + + +
    +
    +
    IPA
    +
    Inter-Procedural Analysis. Refers to any variety of code analysis that + occurs between procedures, functions or compilation units (modules).
    +
    IPO
    +
    Inter-Procedural Optimization. Refers to any variety of code + optimization that occurs between procedures, functions or compilation units + (modules).
    +
    ISel
    +
    Instruction Selection.
    +
    +
    + + +
    +
    +
    LCSSA
    +
    Loop-Closed Static Single Assignment Form
    +
    LICM
    +
    Loop Invariant Code Motion
    +
    Load-VN
    +
    Load Value Numbering
    +
    +
    + + + +
    +
    +
    Object Pointer
    +
    A pointer to an object such that the garbage collector is able to trace + references contained within the object. This term is used in opposition to + derived pointer.
    +
    +
    + + + +
    +
    +
    PRE
    +
    Partial Redundancy Elimination
    +
    +
    + + + +
    +
    +
    RAUW
    An abbreviation for Replace + All Uses With. The functions User::replaceUsesOfWith(), + Value::replaceAllUsesWith(), and Constant::replaceUsesOfWithOnConstant() + implement the replacement of one Value with another by iterating over its + def/use chain and fixing up all of the pointers to point to the new value. + See also def/use chains. +
    +
    Reassociation
    Rearranging + associative expressions to promote better redundancy elimination and other + optimization. For example, changing (A+B-A) into (B+A-A), permitting it to + be optimized into (B+0) then (B).
    +
    Root
    In garbage collection, a + pointer variable lying outside of the heap from which + the collector begins its reachability analysis. In the context of code + generation, "root" almost always refers to a "stack root" -- a local or + temporary variable within an executing function.
    +
    +
    + + + +
    +
    +
    Safe Point
    +
    In garbage collection, it is necessary to identify stack + roots so that reachability analysis may proceed. It may be infeasible to + provide this information for every instruction, so instead the information + may is calculated only at designated safe points. With a copying collector, + derived pointers must not be retained across + safe points and object pointers must be + reloaded from stack roots.
    +
    SDISel
    +
    Selection DAG Instruction Selection.
    +
    SCC
    +
    Strongly Connected Component
    +
    SCCP
    +
    Sparse Conditional Constant Propagation
    +
    SRoA
    +
    Scalar Replacement of Aggregates
    +
    SSA
    +
    Static Single Assignment
    +
    Stack Map
    +
    In garbage collection, metadata emitted by the code generator which + identifies roots within the stack frame of an executing + function.
    +
    +
    + +
    +
    Valid CSSValid HTML 4.01The LLVM Team
    +The LLVM Compiler Infrastructure
    +Last modified: $Date$ +
    + + + diff --git a/libclamav/c++/llvm/docs/LinkTimeOptimization.html b/libclamav/c++/llvm/docs/LinkTimeOptimization.html new file mode 100644 index 000000000..524a4e83f --- /dev/null +++ b/libclamav/c++/llvm/docs/LinkTimeOptimization.html @@ -0,0 +1,390 @@ + + + + LLVM Link Time Optimization: Design and Implementation + + + +
    + LLVM Link Time Optimization: Design and Implementation +
    + + + +
    +

    Written by Devang Patel and Nick Kledzik

    +
    + + + + + +
    +

    +LLVM features powerful intermodular optimizations which can be used at link +time. Link Time Optimization (LTO) is another name for intermodular optimization +when performed during the link stage. This document describes the interface +and design between the LTO optimizer and the linker.

    +
    + + + + + +
    +

    +The LLVM Link Time Optimizer provides complete transparency, while doing +intermodular optimization, in the compiler tool chain. Its main goal is to let +the developer take advantage of intermodular optimizations without making any +significant changes to the developer's makefiles or build system. This is +achieved through tight integration with the linker. In this model, the linker +treates LLVM bitcode files like native object files and allows mixing and +matching among them. The linker uses libLTO, a shared +object, to handle LLVM bitcode files. This tight integration between +the linker and LLVM optimizer helps to do optimizations that are not possible +in other models. The linker input allows the optimizer to avoid relying on +conservative escape analysis. +

    +
    + + + + +
    +

    The following example illustrates the advantages of LTO's integrated + approach and clean interface. This example requires a system linker which + supports LTO through the interface described in this document. Here, + llvm-gcc transparently invokes system linker.

    +
      +
    • Input source file a.c is compiled into LLVM bitcode form. +
    • Input source file main.c is compiled into native object code. +
    +
    +--- a.h ---
    +extern int foo1(void);
    +extern void foo2(void);
    +extern void foo4(void);
    +--- a.c ---
    +#include "a.h"
    +
    +static signed int i = 0;
    +
    +void foo2(void) {
    + i = -1;
    +}
    +
    +static int foo3() {
    +foo4();
    +return 10;
    +}
    +
    +int foo1(void) {
    +int data = 0;
    +
    +if (i < 0) { data = foo3(); }
    +
    +data = data + 42;
    +return data;
    +}
    +
    +--- main.c ---
    +#include <stdio.h>
    +#include "a.h"
    +
    +void foo4(void) {
    + printf ("Hi\n");
    +}
    +
    +int main() {
    + return foo1();
    +}
    +
    +--- command lines ---
    +$ llvm-gcc --emit-llvm -c a.c -o a.o  # <-- a.o is LLVM bitcode file
    +$ llvm-gcc -c main.c -o main.o # <-- main.o is native object file
    +$ llvm-gcc a.o main.o -o main # <-- standard link command without any modifications
    +
    +

    In this example, the linker recognizes that foo2() is an + externally visible symbol defined in LLVM bitcode file. The linker completes + its usual symbol resolution + pass and finds that foo2() is not used anywhere. This information + is used by the LLVM optimizer and it removes foo2(). As soon as + foo2() is removed, the optimizer recognizes that condition + i < 0 is always false, which means foo3() is never + used. Hence, the optimizer removes foo3(), also. And this in turn, + enables linker to remove foo4(). This example illustrates the + advantage of tight integration with the linker. Here, the optimizer can not + remove foo3() without the linker's input. +

    +
    + + + + +
    +
    +
    Compiler driver invokes link time optimizer separately.
    +
    In this model the link time optimizer is not able to take advantage of + information collected during the linker's normal symbol resolution phase. + In the above example, the optimizer can not remove foo2() without + the linker's input because it is externally visible. This in turn prohibits + the optimizer from removing foo3().
    +
    Use separate tool to collect symbol information from all object + files.
    +
    In this model, a new, separate, tool or library replicates the linker's + capability to collect information for link time optimization. Not only is + this code duplication difficult to justify, but it also has several other + disadvantages. For example, the linking semantics and the features + provided by the linker on various platform are not unique. This means, + this new tool needs to support all such features and platforms in one + super tool or a separate tool per platform is required. This increases + maintenance cost for link time optimizer significantly, which is not + necessary. This approach also requires staying synchronized with linker + developements on various platforms, which is not the main focus of the link + time optimizer. Finally, this approach increases end user's build time due + to the duplication of work done by this separate tool and the linker itself. +
    +
    +
    + + + + +
    +

    The linker collects information about symbol defininitions and uses in + various link objects which is more accurate than any information collected + by other tools during typical build cycles. The linker collects this + information by looking at the definitions and uses of symbols in native .o + files and using symbol visibility information. The linker also uses + user-supplied information, such as a list of exported symbols. LLVM + optimizer collects control flow information, data flow information and knows + much more about program structure from the optimizer's point of view. + Our goal is to take advantage of tight integration between the linker and + the optimizer by sharing this information during various linking phases. +

    +
    + + + + +
    +

    The linker first reads all object files in natural order and collects + symbol information. This includes native object files as well as LLVM bitcode + files. To minimize the cost to the linker in the case that all .o files + are native object files, the linker only calls lto_module_create() + when a supplied object file is found to not be a native object file. If + lto_module_create() returns that the file is an LLVM bitcode file, + the linker + then iterates over the module using lto_module_get_symbol_name() and + lto_module_get_symbol_attribute() to get all symbols defined and + referenced. + This information is added to the linker's global symbol table. +

    +

    The lto* functions are all implemented in a shared object libLTO. This + allows the LLVM LTO code to be updated independently of the linker tool. + On platforms that support it, the shared object is lazily loaded. +

    +
    + + + + +
    +

    In this stage, the linker resolves symbols using global symbol table. + It may report undefined symbol errors, read archive members, replace + weak symbols, etc. The linker is able to do this seamlessly even though it + does not know the exact content of input LLVM bitcode files. If dead code + stripping is enabled then the linker collects the list of live symbols. +

    +
    + + + +
    +

    After symbol resolution, the linker tells the LTO shared object which + symbols are needed by native object files. In the example above, the linker + reports that only foo1() is used by native object files using + lto_codegen_add_must_preserve_symbol(). Next the linker invokes + the LLVM optimizer and code generators using lto_codegen_compile() + which returns a native object file creating by merging the LLVM bitcode files + and applying various optimization passes. +

    +
    + + + + +
    +

    In this phase, the linker reads optimized a native object file and + updates the internal global symbol table to reflect any changes. The linker + also collects information about any changes in use of external symbols by + LLVM bitcode files. In the examle above, the linker notes that + foo4() is not used any more. If dead code stripping is enabled then + the linker refreshes the live symbol information appropriately and performs + dead code stripping.

    +

    After this phase, the linker continues linking as if it never saw LLVM + bitcode files.

    +
    + + +
    +libLTO +
    + +
    +

    libLTO is a shared object that is part of the LLVM tools, and + is intended for use by a linker. libLTO provides an abstract C + interface to use the LLVM interprocedural optimizer without exposing details + of LLVM's internals. The intention is to keep the interface as stable as + possible even when the LLVM optimizer continues to evolve. It should even + be possible for a completely different compilation technology to provide + a different libLTO that works with their object files and the standard + linker tool.

    +
    + + + + +
    + +

    A non-native object file is handled via an lto_module_t. +The following functions allow the linker to check if a file (on disk +or in a memory buffer) is a file which libLTO can process:

    + +
    +lto_module_is_object_file(const char*)
    +lto_module_is_object_file_for_target(const char*, const char*)
    +lto_module_is_object_file_in_memory(const void*, size_t)
    +lto_module_is_object_file_in_memory_for_target(const void*, size_t, const char*)
    +
    + +

    If the object file can be processed by libLTO, the linker creates a +lto_module_t by using one of

    + +
    +lto_module_create(const char*)
    +lto_module_create_from_memory(const void*, size_t)
    +
    + +

    and when done, the handle is released via

    + +
    +lto_module_dispose(lto_module_t)
    +
    + +

    The linker can introspect the non-native object file by getting the number of +symbols and getting the name and attributes of each symbol via:

    + +
    +lto_module_get_num_symbols(lto_module_t)
    +lto_module_get_symbol_name(lto_module_t, unsigned int)
    +lto_module_get_symbol_attribute(lto_module_t, unsigned int)
    +
    + +

    The attributes of a symbol include the alignment, visibility, and kind.

    +
    + + + + +
    + +

    Once the linker has loaded each non-native object files into an +lto_module_t, it can request libLTO to process them all and +generate a native object file. This is done in a couple of steps. +First, a code generator is created with:

    + +
    lto_codegen_create()
    + +

    Then, each non-native object file is added to the code generator with:

    + +
    +lto_codegen_add_module(lto_code_gen_t, lto_module_t)
    +
    + +

    The linker then has the option of setting some codegen options. Whether or +not to generate DWARF debug info is set with:

    + +
    lto_codegen_set_debug_model(lto_code_gen_t)
    + +

    Which kind of position independence is set with:

    + +
    lto_codegen_set_pic_model(lto_code_gen_t) 
    + +

    And each symbol that is referenced by a native object file or otherwise must +not be optimized away is set with:

    + +
    +lto_codegen_add_must_preserve_symbol(lto_code_gen_t, const char*)
    +
    + +

    After all these settings are done, the linker requests that a native object +file be created from the modules with the settings using:

    + +
    lto_codegen_compile(lto_code_gen_t, size*)
    + +

    which returns a pointer to a buffer containing the generated native +object file. The linker then parses that and links it with the rest +of the native object files.

    + +
    + + + +
    +
    + Valid CSS + Valid HTML 4.01 + + Devang Patel and Nick Kledzik
    + LLVM Compiler Infrastructure
    + Last modified: $Date$ +
    + + + + diff --git a/libclamav/c++/llvm/docs/Makefile b/libclamav/c++/llvm/docs/Makefile new file mode 100644 index 000000000..310c4bd5f --- /dev/null +++ b/libclamav/c++/llvm/docs/Makefile @@ -0,0 +1,125 @@ +##===- docs/Makefile ---------------------------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LEVEL := .. +DIRS := CommandGuide tutorial + +ifdef BUILD_FOR_WEBSITE +PROJ_OBJ_DIR = . +DOXYGEN = doxygen + +$(PROJ_OBJ_DIR)/doxygen.cfg: doxygen.cfg.in + cat $< | sed \ + -e 's/@abs_top_srcdir@/../g' \ + -e 's/@DOT@/dot/g' \ + -e 's/@PACKAGE_VERSION@/mainline/' \ + -e 's/@abs_top_builddir@/../g' > $@ +endif + +include $(LEVEL)/Makefile.common + +HTML := $(wildcard $(PROJ_SRC_DIR)/*.html) \ + $(wildcard $(PROJ_SRC_DIR)/*.css) +IMAGES := $(wildcard $(PROJ_SRC_DIR)/img/*.*) +DOXYFILES := doxygen.cfg.in doxygen.css doxygen.footer doxygen.header \ + doxygen.intro +EXTRA_DIST := $(HTML) $(DOXYFILES) llvm.css CommandGuide img + +.PHONY: install-html install-doxygen doxygen install-ocamldoc ocamldoc generated + +install_targets := install-html +ifeq ($(ENABLE_DOXYGEN),1) +install_targets += install-doxygen +endif +ifneq (,$(filter ocaml,$(BINDINGS_TO_BUILD))) +install_targets += install-ocamldoc +endif +install-local:: $(install_targets) + +# Live documentation is generated for the web site using this target: +# 'make generated BUILD_FOR_WEBSITE=1' +generated:: doxygen ocamldoc + +install-html: $(PROJ_OBJ_DIR)/html.tar.gz + $(Echo) Installing HTML documentation + $(Verb) $(MKDIR) $(PROJ_docsdir)/html + $(Verb) $(MKDIR) $(PROJ_docsdir)/html/img + $(Verb) $(DataInstall) $(HTML) $(PROJ_docsdir)/html + $(Verb) $(DataInstall) $(IMAGES) $(PROJ_docsdir)/html/img + $(Verb) $(DataInstall) $(PROJ_OBJ_DIR)/html.tar.gz $(PROJ_docsdir) + +$(PROJ_OBJ_DIR)/html.tar.gz: $(HTML) + $(Echo) Packaging HTML documentation + $(Verb) $(RM) -rf $@ $(PROJ_OBJ_DIR)/html.tar + $(Verb) cd $(PROJ_SRC_DIR) && \ + $(TAR) cf $(PROJ_OBJ_DIR)/html.tar *.html + $(Verb) $(GZIP) $(PROJ_OBJ_DIR)/html.tar + +install-doxygen: doxygen + $(Echo) Installing doxygen documentation + $(Verb) $(MKDIR) $(PROJ_docsdir)/html/doxygen + $(Verb) $(DataInstall) $(PROJ_OBJ_DIR)/doxygen.tar.gz $(PROJ_docsdir) + $(Verb) cd $(PROJ_OBJ_DIR)/doxygen && \ + $(FIND) . -type f -exec \ + $(DataInstall) {} $(PROJ_docsdir)/html/doxygen \; + +doxygen: regendoc $(PROJ_OBJ_DIR)/doxygen.tar.gz + +regendoc: + $(Echo) Building doxygen documentation + $(Verb) if test -e $(PROJ_OBJ_DIR)/doxygen ; then \ + $(RM) -rf $(PROJ_OBJ_DIR)/doxygen ; \ + fi + $(Verb) $(DOXYGEN) $(PROJ_OBJ_DIR)/doxygen.cfg + +$(PROJ_OBJ_DIR)/doxygen.tar.gz: $(DOXYFILES) $(PROJ_OBJ_DIR)/doxygen.cfg + $(Echo) Packaging doxygen documentation + $(Verb) $(RM) -rf $@ $(PROJ_OBJ_DIR)/doxygen.tar + $(Verb) $(TAR) cf $(PROJ_OBJ_DIR)/doxygen.tar doxygen + $(Verb) $(GZIP) $(PROJ_OBJ_DIR)/doxygen.tar + $(Verb) $(CP) $(PROJ_OBJ_DIR)/doxygen.tar.gz $(PROJ_OBJ_DIR)/doxygen/html/ + +userloc: $(LLVM_SRC_ROOT)/docs/userloc.html + +$(LLVM_SRC_ROOT)/docs/userloc.html: + $(Echo) Making User LOC Table + $(Verb) cd $(LLVM_SRC_ROOT) ; ./utils/userloc.pl -details -recurse \ + -html lib include tools runtime utils examples autoconf test > docs/userloc.html + +install-ocamldoc: ocamldoc + $(Echo) Installing ocamldoc documentation + $(Verb) $(MKDIR) $(PROJ_docsdir)/ocamldoc/html + $(Verb) $(DataInstall) $(PROJ_OBJ_DIR)/ocamldoc.tar.gz $(PROJ_docsdir) + $(Verb) cd $(PROJ_OBJ_DIR)/ocamldoc && \ + $(FIND) . -type f -exec \ + $(DataInstall) {} $(PROJ_docsdir)/ocamldoc/html \; + +ocamldoc: regen-ocamldoc $(PROJ_OBJ_DIR)/ocamldoc.tar.gz + +regen-ocamldoc: + $(Echo) Building ocamldoc documentation + $(Verb) if test -e $(PROJ_OBJ_DIR)/ocamldoc ; then \ + $(RM) -rf $(PROJ_OBJ_DIR)/ocamldoc ; \ + fi + $(Verb) $(MAKE) -C $(LEVEL)/bindings/ocaml ocamldoc + $(Verb) $(MKDIR) $(PROJ_OBJ_DIR)/ocamldoc/html + $(Verb) \ + $(OCAMLDOC) -d $(PROJ_OBJ_DIR)/ocamldoc/html -sort -colorize-code -html \ + `$(FIND) $(LEVEL)/bindings/ocaml -name "*.odoc" -exec echo -load '{}' ';'` + +$(PROJ_OBJ_DIR)/ocamldoc.tar.gz: + $(Echo) Packaging ocamldoc documentation + $(Verb) $(RM) -rf $@ $(PROJ_OBJ_DIR)/ocamldoc.tar + $(Verb) $(TAR) cf $(PROJ_OBJ_DIR)/ocamldoc.tar ocamldoc + $(Verb) $(GZIP) $(PROJ_OBJ_DIR)/ocamldoc.tar + $(Verb) $(CP) $(PROJ_OBJ_DIR)/ocamldoc.tar.gz $(PROJ_OBJ_DIR)/ocamldoc/html/ + +uninstall-local:: + $(Echo) Uninstalling Documentation + $(Verb) $(RM) -rf $(PROJ_docsdir) diff --git a/libclamav/c++/llvm/docs/MakefileGuide.html b/libclamav/c++/llvm/docs/MakefileGuide.html new file mode 100644 index 000000000..a9c0725f2 --- /dev/null +++ b/libclamav/c++/llvm/docs/MakefileGuide.html @@ -0,0 +1,1027 @@ + + + + + LLVM Makefile Guide + + + + +
    LLVM Makefile Guide
    + +
      +
    1. Introduction
    2. +
    3. General Concepts +
        +
      1. Projects
      2. +
      3. Variable Values
      4. +
      5. Including Makefiles +
          +
        1. Makefile
        2. +
        3. Makefile.common
        4. +
        5. Makefile.config
        6. +
        7. Makefile.rules
        8. +
        +
      6. +
      7. Comments
      8. +
      +
    4. +
    5. Tutorial +
        +
      1. Libraries +
          +
        1. Bitcode Modules
        2. +
        3. Loadable Modules
        4. +
        +
      2. +
      3. Tools +
          +
        1. JIT Tools
        2. +
        +
      4. +
      5. Projects
      6. +
      +
    6. +
    7. Targets Supported +
        +
      1. all
      2. +
      3. all-local
      4. +
      5. check
      6. +
      7. check-local
      8. +
      9. clean
      10. +
      11. clean-local
      12. +
      13. dist
      14. +
      15. dist-check
      16. +
      17. dist-clean
      18. +
      19. install
      20. +
      21. preconditions
      22. +
      23. printvars
      24. +
      25. reconfigure
      26. +
      27. spotless
      28. +
      29. tags
      30. +
      31. uninstall
      32. +
      +
    8. +
    9. Using Variables +
        +
      1. Control Variables
      2. +
      3. Override Variables
      4. +
      5. Readable Variables
      6. +
      7. Internal Variables
      8. +
      +
    10. +
    + +
    +

    Written by Reid Spencer

    +
    + + + + + +
    +

    This document provides usage information about the LLVM makefile + system. While loosely patterned after the BSD makefile system, LLVM has taken + a departure from BSD in order to implement additional features needed by LLVM. + Although makefile systems such as automake were attempted at one point, it + has become clear that the features needed by LLVM and the Makefile norm are + too great to use a more limited tool. Consequently, LLVM requires simply GNU + Make 3.79, a widely portable makefile processor. LLVM unabashedly makes heavy + use of the features of GNU Make so the dependency on GNU Make is firm. If + you're not familiar with make, it is recommended that you read the + GNU Makefile + Manual.

    +

    While this document is rightly part of the + LLVM Programmer's Manual, it is treated + separately here because of the volume of content and because it is often an + early source of bewilderment for new developers.

    +
    + + + + + +
    +

    The LLVM Makefile System is the component of LLVM that is responsible for + building the software, testing it, generating distributions, checking those + distributions, installing and uninstalling, etc. It consists of a several + files throughout the source tree. These files and other general concepts are + described in this section.

    +
    + + + +
    +

    The LLVM Makefile System is quite generous. It not only builds its own + software, but it can build yours too. Built into the system is knowledge of + the llvm/projects directory. Any directory under projects + that has both a configure script and a Makefile is assumed + to be a project that uses the LLVM Makefile system. Building software that + uses LLVM does not require the LLVM Makefile System nor even placement in the + llvm/projects directory. However, doing so will allow your project + to get up and running quickly by utilizing the built-in features that are used + to compile LLVM. LLVM compiles itself using the same features of the makefile + system as used for projects.

    +

    For complete details on setting up your projects configuration, simply + mimic the llvm/projects/sample project or for further details, + consult the Projects.html page.

    +
    + + + +
    +

    To use the makefile system, you simply create a file named + Makefile in your directory and declare values for certain variables. + The variables and values that you select determine what the makefile system + will do. These variables enable rules and processing in the makefile system + that automatically Do The Right Thing™. +

    + + + +
    +

    Setting variables alone is not enough. You must include into your Makefile + additional files that provide the rules of the LLVM Makefile system. The + various files involved are described in the sections that follow.

    +
    + + + +
    +

    Each directory to participate in the build needs to have a file named + Makefile. This is the file first read by make. It has three + sections:

    +
      +
    1. Settable Variables - Required that must be set + first.
    2. +
    3. include $(LEVEL)/Makefile.common + - include the LLVM Makefile system. +
    4. Override Variables - Override variables set by + the LLVM Makefile system. +
    +
    + + + +
    +

    Every project must have a Makefile.common file at its top source + directory. This file serves three purposes:

    +
      +
    1. It includes the project's configuration makefile to obtain values + determined by the configure script. This is done by including the + $(LEVEL)/Makefile.config file.
    2. +
    3. It specifies any other (static) values that are needed throughout the + project. Only values that are used in all or a large proportion of the + project's directories should be placed here.
    4. +
    5. It includes the standard rules for the LLVM Makefile system, + $(LLVM_SRC_ROOT)/Makefile.rules. + This file is the "guts" of the LLVM Makefile system.
    6. +
    +
    + + + +
    +

    Every project must have a Makefile.config at the top of its + build directory. This file is generated by the + configure script from the pattern provided by the + Makefile.config.in file located at the top of the project's + source directory. The contents of this file depend largely on what + configuration items the project uses, however most projects can get what they + need by just relying on LLVM's configuration found in + $(LLVM_OBJ_ROOT)/Makefile.config. +

    + + + +
    +

    This file, located at $(LLVM_SRC_ROOT)/Makefile.rules is the heart + of the LLVM Makefile System. It provides all the logic, dependencies, and + rules for building the targets supported by the system. What it does largely + depends on the values of make variables that + have been set before Makefile.rules is included. +

    + + + +
    +

    User Makefiles need not have comments in them unless the construction is + unusual or it does not strictly follow the rules and patterns of the LLVM + makefile system. Makefile comments are invoked with the pound (#) character. + The # character and any text following it, to the end of the line, are ignored + by make.

    +
    + + + + +
    +

    This section provides some examples of the different kinds of modules you + can build with the LLVM makefile system. In general, each directory you + provide will build a single object although that object may be composed of + additionally compiled components.

    +
    + + + +
    +

    Only a few variable definitions are needed to build a regular library. + Normally, the makefile system will build all the software into a single + libname.o (pre-linked) object. This means the library is not + searchable and that the distinction between compilation units has been + dissolved. Optionally, you can ask for a shared library (.so) or archive + library (.a) built. Archive libraries are the default. For example:

    +
    
    +      LIBRARYNAME = mylib
    +      SHARED_LIBRARY = 1
    +      ARCHIVE_LIBRARY = 1
    +  
    +

    says to build a library named "mylib" with both a shared library + (mylib.so) and an archive library (mylib.a) version. The + contents of all the + libraries produced will be the same, they are just constructed differently. + Note that you normally do not need to specify the sources involved. The LLVM + Makefile system will infer the source files from the contents of the source + directory.

    +

    The LOADABLE_MODULE=1 directive can be used in conjunction with + SHARED_LIBRARY=1 to indicate that the resulting shared library should + be openable with the dlopen function and searchable with the + dlsym function (or your operating system's equivalents). While this + isn't strictly necessary on Linux and a few other platforms, it is required + on systems like HP-UX and Darwin. You should use LOADABLE_MODULE for + any shared library that you intend to be loaded into an tool via the + -load option. See the + WritingAnLLVMPass.html document + for an example of why you might want to do this. +

    + + + +
    +

    In some situations, it is desirable to build a single bitcode module from + a variety of sources, instead of an archive, shared library, or bitcode + library. Bitcode modules can be specified in addition to any of the other + types of libraries by defining the MODULE_NAME + variable. For example:

    +
    
    +      LIBRARYNAME = mylib
    +      BYTECODE_LIBRARY = 1
    +      MODULE_NAME = mymod
    +  
    +

    will build a module named mymod.bc from the sources in the + directory. This module will be an aggregation of all the bitcode modules + derived from the sources. The example will also build a bitcode archive + containing a bitcode module for each compiled source file. The difference is + subtle, but important depending on how the module or library is to be linked. +

    +
    + + + +
    +

    In some situations, you need to create a loadable module. Loadable modules + can be loaded into programs like opt or llc to specify + additional passes to run or targets to support. Loadable modules are also + useful for debugging a pass or providing a pass with another package if that + pass can't be included in LLVM.

    +

    LLVM provides complete support for building such a module. All you need to + do is use the LOADABLE_MODULE variable in your Makefile. For example, to + build a loadable module named MyMod that uses the LLVM libraries + LLVMSupport.a and LLVMSystem.a, you would specify:

    +
    
    +     LIBRARYNAME := MyMod
    +     LOADABLE_MODULE := 1
    +     LINK_COMPONENTS := support system
    +  
    +

    Use of the LOADABLE_MODULE facility implies several things:

    +
      +
    1. There will be no "lib" prefix on the module. This differentiates it from + a standard shared library of the same name.
    2. +
    3. The SHARED_LIBRARY variable is turned + on.
    4. +
    5. The LINK_LIBS_IN_SHARED variable + is turned on.
    6. +
    +

    A loadable module is loaded by LLVM via the facilities of libtool's libltdl + library which is part of lib/System implementation.

    +
    + + + +
    +

    For building executable programs (tools), you must provide the name of the + tool and the names of the libraries you wish to link with the tool. For + example:

    +
    
    +      TOOLNAME = mytool
    +      USEDLIBS = mylib
    +      LINK_COMPONENTS = support system
    +  
    +

    says that we are to build a tool name mytool and that it requires + three libraries: mylib, LLVMSupport.a and + LLVMSystem.a.

    +

    Note that two different variables are use to indicate which libraries are + linked: USEDLIBS and LLVMLIBS. This distinction is necessary + to support projects. LLVMLIBS refers to the LLVM libraries found in + the LLVM object directory. USEDLIBS refers to the libraries built by + your project. In the case of building LLVM tools, USEDLIBS and + LLVMLIBS can be used interchangeably since the "project" is LLVM + itself and USEDLIBS refers to the same place as LLVMLIBS. +

    +

    Also note that there are two different ways of specifying a library: with a + .a suffix and without. Without the suffix, the entry refers to the + re-linked (.o) file which will include all symbols of the library. + This is useful, for example, to include all passes from a library of passes. + If the .a suffix is used then the library is linked as a searchable + library (with the -l option). In this case, only the symbols that are + unresolved at that point will be resolved from the library, if they + exist. Other (unreferenced) symbols will not be included when the .a + syntax is used. Note that in order to use the .a suffix, the library + in question must have been built with the ARCHIVE_LIBRARY option set. +

    +
    + + + +
    +

    Many tools will want to use the JIT features of LLVM. To do this, you + simply specify that you want an execution 'engine', and the makefiles will + automatically link in the appropriate JIT for the host or an interpreter + if none is available:

    +
    
    +      TOOLNAME = my_jit_tool
    +      USEDLIBS = mylib
    +      LINK_COMPONENTS = engine
    +  
    +

    Of course, any additional libraries may be listed as other components. To + get a full understanding of how this changes the linker command, it is + recommended that you:

    +
    
    +      cd examples/Fibonacci
    +      make VERBOSE=1
    +  
    +
    + + + + + +
    +

    This section describes each of the targets that can be built using the LLVM + Makefile system. Any target can be invoked from any directory but not all are + applicable to a given directory (e.g. "check", "dist" and "install" will + always operate as if invoked from the top level directory).

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Target NameImplied TargetsTarget Description
    allCompile the software recursively. Default target. +
    all-localCompile the software in the local directory only. +
    checkChange to the test directory in a project and run the + test suite there. +
    check-localRun a local test suite. Generally this is only defined in the + Makefile of the project's test directory. +
    cleanRemove built objects recursively. +
    clean-localRemove built objects from the local directory only. +
    distallPrepare a source distribution tarball. +
    dist-checkallPrepare a source distribution tarball and check that it builds. +
    dist-cleancleanClean source distribution tarball temporary files. +
    installallCopy built objects to installation directory. +
    preconditionsallCheck to make sure configuration and makefiles are up to date. +
    printvarsallPrints variables defined by the makefile system (for debugging). +
    tagsMake C and C++ tags files for emacs and vi. +
    uninstallRemove built objects from installation directory. +
    +
    + + + +
    +

    When you invoke make with no arguments, you are implicitly + instructing it to seek the "all" target (goal). This target is used for + building the software recursively and will do different things in different + directories. For example, in a lib directory, the "all" target will + compile source files and generate libraries. But, in a tools + directory, it will link libraries and generate executables.

    +
    + + + +
    +

    This target is the same as all but it operates only on + the current directory instead of recursively.

    +
    + + + +
    +

    This target can be invoked from anywhere within a project's directories + but always invokes the check-local target + in the project's test directory, if it exists and has a + Makefile. A warning is produced otherwise. If + TESTSUITE is defined on the make + command line, it will be passed down to the invocation of + make check-local in the test directory. The intended usage + for this is to assist in running specific suites of tests. If + TESTSUITE is not set, the implementation of check-local + should run all normal tests. It is up to the project to define what + different values for TESTSUTE will do. See the + TestingGuide for further details.

    +
    + + + +
    +

    This target should be implemented by the Makefile in the project's + test directory. It is invoked by the check target elsewhere. + Each project is free to define the actions of check-local as + appropriate for that project. The LLVM project itself uses dejagnu to run a + suite of feature and regresson tests. Other projects may choose to use + dejagnu or any other testing mechanism.

    +
    + + + +
    +

    This target cleans the build directory, recursively removing all things + that the Makefile builds. The cleaning rules have been made guarded so they + shouldn't go awry (via rm -f $(UNSET_VARIABLE)/* which will attempt + to erase the entire directory structure.

    +
    + + + +
    +

    This target does the same thing as clean but only for the current + (local) directory.

    +
    + + + +
    +

    This target builds a distribution tarball. It first builds the entire + project using the all target and then tars up the necessary files and + compresses it. The generated tarball is sufficient for a casual source + distribution, but probably not for a release (see dist-check).

    +
    + + + +
    +

    This target does the same thing as the dist target but also checks + the distribution tarball. The check is made by unpacking the tarball to a new + directory, configuring it, building it, installing it, and then verifying that + the installation results are correct (by comparing to the original build). + This target can take a long time to run but should be done before a release + goes out to make sure that the distributed tarball can actually be built into + a working release.

    +
    + + + +
    +

    This is a special form of the clean clean target. It performs a + normal clean but also removes things pertaining to building the + distribution.

    +
    + + + +
    +

    This target finalizes shared objects and executables and copies all + libraries, headers, executables and documentation to the directory given + with the --prefix option to configure. When completed, + the prefix directory will have everything needed to use LLVM.

    +

    The LLVM makefiles can generate complete internal documentation + for all the classes by using doxygen. By default, this feature is + not enabled because it takes a long time and generates a massive + amount of data (>100MB). If you want this feature, you must configure LLVM + with the --enable-doxygen switch and ensure that a modern version of doxygen + (1.3.7 or later) is available in your PATH. You can download + doxygen from + + here. +

    + + + +
    +

    This utility target checks to see if the Makefile in the object + directory is older than the Makefile in the source directory and + copies it if so. It also reruns the configure script if that needs to + be done and rebuilds the Makefile.config file similarly. Users may + overload this target to ensure that sanity checks are run before any + building of targets as all the targets depend on preconditions.

    +
    + + + +
    +

    This utility target just causes the LLVM makefiles to print out some of + the makefile variables so that you can double check how things are set.

    +
    + + + +
    +

    This utility target will force a reconfigure of LLVM or your project. It + simply runs $(PROJ_OBJ_ROOT)/config.status --recheck to rerun the + configuration tests and rebuild the configured files. This isn't generally + useful as the makefiles will reconfigure themselves whenever its necessary. +

    +
    + + + +
    +

    This utility target, only available when $(PROJ_OBJ_ROOT) is not + the same as $(PROJ_SRC_ROOT), will completely clean the + $(PROJ_OBJ_ROOT) directory by removing its content entirely and + reconfiguring the directory. This returns the $(PROJ_OBJ_ROOT) + directory to a completely fresh state. All content in the directory except + configured files and top-level makefiles will be lost.

    +

    Use with caution.

    +
    + + + +
    +

    This target will generate a TAGS file in the top-level source + directory. It is meant for use with emacs, XEmacs, or ViM. The TAGS file + provides an index of symbol definitions so that the editor can jump you to the + definition quickly.

    +
    + + + +
    +

    This target is the opposite of the install target. It removes the + header, library and executable files from the installation directories. Note + that the directories themselves are not removed because it is not guaranteed + that LLVM is the only thing installing there (e.g. --prefix=/usr).

    +
    + + + + +
    +

    Variables are used to tell the LLVM Makefile System what to do and to + obtain information from it. Variables are also used internally by the LLVM + Makefile System. Variable names that contain only the upper case alphabetic + letters and underscore are intended for use by the end user. All other + variables are internal to the LLVM Makefile System and should not be relied + upon nor modified. The sections below describe how to use the LLVM Makefile + variables.

    +
    + + + +
    +

    Variables listed in the table below should be set before the + inclusion of $(LEVEL)/Makefile.common. + These variables provide input to the LLVM make system that tell it what to do + for the current directory.

    +
    +
    BUILD_ARCHIVE
    +
    If set to any value, causes an archive (.a) library to be built.
    +
    BUILT_SOURCES
    +
    Specifies a set of source files that are generated from other source + files. These sources will be built before any other target processing to + ensure they are present.
    +
    BYTECODE_LIBRARY
    +
    If set to any value, causes a bitcode library (.bc) to be built.
    +
    CONFIG_FILES
    +
    Specifies a set of configuration files to be installed.
    +
    DEBUG_SYMBOLS
    +
    If set to any value, causes the build to include debugging + symbols even in optimized objects, libraries and executables. This + alters the flags specified to the compilers and linkers. Debugging + isn't fun in an optimized build, but it is possible.
    +
    DIRS
    +
    Specifies a set of directories, usually children of the current + directory, that should also be made using the same goal. These directories + will be built serially.
    +
    DISABLE_AUTO_DEPENDENCIES
    +
    If set to any value, causes the makefiles to not automatically + generate dependencies when running the compiler. Use of this feature is + discouraged and it may be removed at a later date.
    +
    ENABLE_OPTIMIZED
    +
    If set to any value, causes the build to generate optimized objects, + libraries and executables. This alters the flags specified to the compilers + and linkers. Generally debugging won't be a fun experience with an optimized + build.
    +
    ENABLE_PROFILING
    +
    If set to any value, causes the build to generate both optimized and + profiled objects, libraries and executables. This alters the flags specified + to the compilers and linkers to ensure that profile data can be collected + from the tools built. Use the gprof tool to analyze the output from + the profiled tools (gmon.out).
    +
    DISABLE_ASSERTIONS
    +
    If set to any value, causes the build to disable assertions, even if + building a release or profile build. This will exclude all assertion check + code from the build. LLVM will execute faster, but with little help when + things go wrong.
    +
    EXPERIMENTAL_DIRS
    +
    Specify a set of directories that should be built, but if they fail, it + should not cause the build to fail. Note that this should only be used + temporarily while code is being written.
    +
    EXPORTED_SYMBOL_FILE
    +
    Specifies the name of a single file that contains a list of the + symbols to be exported by the linker. One symbol per line.
    +
    EXPORTED_SYMBOL_LIST
    +
    Specifies a set of symbols to be exported by the linker.
    +
    EXTRA_DIST
    +
    Specifies additional files that should be distributed with LLVM. All + source files, all built sources, all Makefiles, and most documentation files + will be automatically distributed. Use this variable to distribute any + files that are not automatically distributed.
    +
    KEEP_SYMBOLS
    +
    If set to any value, specifies that when linking executables the + makefiles should retain debug symbols in the executable. Normally, symbols + are stripped from the executable.
    +
    LEVEL(required)
    +
    Specify the level of nesting from the top level. This variable must be + set in each makefile as it is used to find the top level and thus the other + makefiles.
    +
    LIBRARYNAME
    +
    Specify the name of the library to be built. (Required For + Libraries)
    +
    LINK_COMPONENTS
    +
    When specified for building a tool, the value of this variable will be + passed to the llvm-config tool to generate a link line for the + tool. Unlike USEDLIBS and LLVMLIBS, not all libraries need + to be specified. The llvm-config tool will figure out the library + dependencies and add any libraries that are needed. The USEDLIBS + variable can still be used in conjunction with LINK_COMPONENTS so + that additional project-specific libraries can be linked with the LLVM + libraries specified by LINK_COMPONENTS
    +
    LINK_LIBS_IN_SHARED
    +
    By default, shared library linking will ignore any libraries specified + with the LLVMLIBS or USEDLIBS. + This prevents shared libs from including things that will be in the LLVM + tool the shared library will be loaded into. However, sometimes it is useful + to link certain libraries into your shared library and this option enables + that feature.
    +
    LLVMLIBS
    +
    Specifies the set of libraries from the LLVM $(ObjDir) that will be + linked into the tool or library.
    +
    LOADABLE_MODULE
    +
    If set to any value, causes the shared library being built to also be + a loadable module. Loadable modules can be opened with the dlopen() function + and searched with dlsym (or the operating system's equivalent). Note that + setting this variable without also setting SHARED_LIBRARY will have + no effect.
    +
    MODULE_NAME
    +
    Specifies the name of a bitcode module to be created. A bitcode + module can be specified in conjunction with other kinds of library builds + or by itself. It constructs from the sources a single linked bitcode + file.
    +
    NO_INSTALL
    +
    Specifies that the build products of the directory should not be + installed but should be built even if the install target is given. + This is handy for directories that build libraries or tools that are only + used as part of the build process, such as code generators (e.g. + tblgen).
    +
    OPTIONAL_DIRS
    +
    Specify a set of directories that may be built, if they exist, but its + not an error for them not to exist.
    +
    PARALLEL_DIRS
    +
    Specify a set of directories to build recursively and in parallel if + the -j option was used with make.
    +
    SHARED_LIBRARY
    +
    If set to any value, causes a shared library (.so) to be built in + addition to any other kinds of libraries. Note that this option will cause + all source files to be built twice: once with options for position + independent code and once without. Use it only where you really need a + shared library.
    +
    SOURCES(optional)
    +
    Specifies the list of source files in the current directory to be + built. Source files of any type may be specified (programs, documentation, + config files, etc.). If not specified, the makefile system will infer the + set of source files from the files present in the current directory.
    +
    SUFFIXES
    +
    Specifies a set of filename suffixes that occur in suffix match rules. + Only set this if your local Makefile specifies additional suffix + match rules.
    +
    TARGET
    +
    Specifies the name of the LLVM code generation target that the + current directory builds. Setting this variable enables additional rules to + build .inc files from .td files.
    +
    TESTSUITE
    +
    Specifies the directory of tests to run in llvm/test.
    +
    TOOLNAME
    +
    Specifies the name of the tool that the current directory should + build.
    +
    TOOL_VERBOSE
    +
    Implies VERBOSE and also tells each tool invoked to be verbose. This is + handy when you're trying to see the sub-tools invoked by each tool invoked + by the makefile. For example, this will pass -v to the GCC + compilers which causes it to print out the command lines it uses to invoke + sub-tools (compiler, assembler, linker).
    +
    USEDLIBS
    +
    Specifies the list of project libraries that will be linked into the + tool or library.
    +
    VERBOSE
    +
    Tells the Makefile system to produce detailed output of what it is doing + instead of just summary comments. This will generate a LOT of output.
    +
    +
    + + + +
    +

    Override variables can be used to override the default + values provided by the LLVM makefile system. These variables can be set in + several ways:

    +
      +
    • In the environment (e.g. setenv, export) -- not recommended.
    • +
    • On the make command line -- recommended.
    • +
    • On the configure command line
    • +
    • In the Makefile (only after the inclusion of $(LEVEL)/Makefile.common).
    • +
    +

    The override variables are given below:

    +
    +
    AR (defaulted)
    +
    Specifies the path to the ar tool.
    +
    PROJ_OBJ_DIR
    +
    The directory into which the products of build rules will be placed. + This might be the same as + PROJ_SRC_DIR but typically is + not.
    +
    PROJ_SRC_DIR
    +
    The directory which contains the source files to be built.
    +
    BZIP2(configured)
    +
    The path to the bzip2 tool.
    +
    CC(configured)
    +
    The path to the 'C' compiler.
    +
    CFLAGS
    +
    Additional flags to be passed to the 'C' compiler.
    +
    CXX
    +
    Specifies the path to the C++ compiler.
    +
    CXXFLAGS
    +
    Additional flags to be passed to the C++ compiler.
    +
    DATE(configured)
    +
    Specifies the path to the date program or any program that can + generate the current date and time on its standard output
    +
    DOT(configured)
    +
    Specifies the path to the dot tool or false if there + isn't one.
    +
    ECHO(configured)
    +
    Specifies the path to the echo tool for printing output.
    +
    EXEEXT(configured)
    +
    Provides the extension to be used on executables built by the makefiles. + The value may be empty on platforms that do not use file extensions for + executables (e.g. Unix).
    +
    INSTALL(configured)
    +
    Specifies the path to the install tool.
    +
    LDFLAGS(configured)
    +
    Allows users to specify additional flags to pass to the linker.
    +
    LIBS(configured)
    +
    The list of libraries that should be linked with each tool.
    +
    LIBTOOL(configured)
    +
    Specifies the path to the libtool tool. This tool is renamed + mklib by the configure script and always located in the +
    LLVMAS(defaulted)
    +
    Specifies the path to the llvm-as tool.
    +
    LLVMGCC(defaulted)
    +
    Specifies the path to the LLVM version of the GCC 'C' Compiler
    +
    LLVMGXX(defaulted)
    +
    Specifies the path to the LLVM version of the GCC C++ Compiler
    +
    LLVMLD(defaulted)
    +
    Specifies the path to the LLVM bitcode linker tool
    +
    LLVM_OBJ_ROOT(configured) +
    +
    Specifies the top directory into which the output of the build is + placed.
    +
    LLVM_SRC_ROOT(configured) +
    +
    Specifies the top directory in which the sources are found.
    +
    LLVM_TARBALL_NAME + (configured)
    +
    Specifies the name of the distribution tarball to create. This is + configured from the name of the project and its version number.
    +
    MKDIR(defaulted)
    +
    Specifies the path to the mkdir tool that creates + directories.
    +
    ONLY_TOOLS
    +
    If set, specifies the list of tools to build.
    +
    PLATFORMSTRIPOPTS
    +
    The options to provide to the linker to specify that a stripped (no + symbols) executable should be built.
    +
    RANLIB(defaulted)
    +
    Specifies the path to the ranlib tool.
    +
    RM(defaulted)
    +
    Specifies the path to the rm tool.
    +
    SED(defaulted)
    +
    Specifies the path to the sed tool.
    +
    SHLIBEXT(configured)
    +
    Provides the filename extension to use for shared libraries.
    +
    TBLGEN(defaulted)
    +
    Specifies the path to the tblgen tool.
    +
    TAR(defaulted)
    +
    Specifies the path to the tar tool.
    +
    ZIP(defaulted)
    +
    Specifies the path to the zip tool.
    +
    +
    + + + +
    +

    Variables listed in the table below can be used by the user's Makefile but + should not be changed. Changing the value will generally cause the build to go + wrong, so don't do it.

    +
    +
    bindir
    +
    The directory into which executables will ultimately be installed. This + value is derived from the --prefix option given to + configure.
    +
    BuildMode
    +
    The name of the type of build being performed: Debug, Release, or + Profile
    +
    bytecode_libdir
    +
    The directory into which bitcode libraries will ultimately be + installed. This value is derived from the --prefix option given to + configure.
    +
    ConfigureScriptFLAGS
    +
    Additional flags given to the configure script when + reconfiguring.
    +
    DistDir
    +
    The current directory for which a distribution copy is being + made.
    +
    Echo
    +
    The LLVM Makefile System output command. This provides the + llvm[n] prefix and starts with @ so the command itself is not + printed by make.
    +
    EchoCmd
    +
    Same as Echo but without the leading @. +
    +
    includedir
    +
    The directory into which include files will ultimately be installed. + This value is derived from the --prefix option given to + configure.
    +
    libdir
    +
    The directory into which native libraries will ultimately be installed. + This value is derived from the --prefix option given to + configure.
    +
    LibDir
    +
    The configuration specific directory into which libraries are placed + before installation.
    +
    MakefileConfig
    +
    Full path of the Makefile.config file.
    +
    MakefileConfigIn
    +
    Full path of the Makefile.config.in file.
    +
    ObjDir
    +
    The configuration and directory specific directory where build objects + (compilation results) are placed.
    +
    SubDirs
    +
    The complete list of sub-directories of the current directory as + specified by other variables.
    +
    Sources
    +
    The complete list of source files.
    +
    sysconfdir
    +
    The directory into which configuration files will ultimately be + installed. This value is derived from the --prefix option given to + configure.
    +
    ToolDir
    +
    The configuration specific directory into which executables are placed + before they are installed.
    +
    TopDistDir
    +
    The top most directory into which the distribution files are copied. +
    +
    Verb
    +
    Use this as the first thing on your build script lines to enable or + disable verbose mode. It expands to either an @ (quiet mode) or nothing + (verbose mode).
    +
    +
    + + + +
    +

    Variables listed below are used by the LLVM Makefile System + and considered internal. You should not use these variables under any + circumstances.

    +

    + Archive + AR.Flags + BaseNameSources + BCCompile.C + BCCompile.CXX + BCLinkLib + C.Flags + Compile.C + CompileCommonOpts + Compile.CXX + ConfigStatusScript + ConfigureScript + CPP.Flags + CPP.Flags + CXX.Flags + DependFiles + DestArchiveLib + DestBitcodeLib + DestModule + DestSharedLib + DestTool + DistAlways + DistCheckDir + DistCheckTop + DistFiles + DistName + DistOther + DistSources + DistSubDirs + DistTarBZ2 + DistTarGZip + DistZip + ExtraLibs + FakeSources + INCFiles + InternalTargets + LD.Flags + LibName.A + LibName.BC + LibName.LA + LibName.O + LibTool.Flags + Link + LinkModule + LLVMLibDir + LLVMLibsOptions + LLVMLibsPaths + LLVMToolDir + LLVMUsedLibs + LocalTargets + Module + ObjectsBC + ObjectsLO + ObjectsO + ObjMakefiles + ParallelTargets + PreConditions + ProjLibsOptions + ProjLibsPaths + ProjUsedLibs + Ranlib + RecursiveTargets + SrcMakefiles + Strip + StripWarnMsg + TableGen + TDFiles + ToolBuildPath + TopLevelTargets + UserTargets +

    +
    + + +
    +
    + Valid CSS + Valid HTML 4.01 + + Reid Spencer
    + The LLVM Compiler Infrastructure
    + Last modified: $Date$ +
    + + diff --git a/libclamav/c++/llvm/docs/Passes.html b/libclamav/c++/llvm/docs/Passes.html new file mode 100644 index 000000000..bbf6b3dc9 --- /dev/null +++ b/libclamav/c++/llvm/docs/Passes.html @@ -0,0 +1,1855 @@ + + + + LLVM's Analysis and Transform Passes + + + + + + + +
    LLVM's Analysis and Transform Passes
    + +
      +
    1. Introduction
    2. +
    3. Analysis Passes +
    4. Transform Passes
    5. +
    6. Utility Passes
    7. +
    + +
    +

    Written by Reid Spencer + and Gordon Henriksen

    +
    + + + +
    +

    This document serves as a high level summary of the optimization features + that LLVM provides. Optimizations are implemented as Passes that traverse some + portion of a program to either collect information or transform the program. + The table below divides the passes that LLVM provides into three categories. + Analysis passes compute information that other passes can use or for debugging + or program visualization purposes. Transform passes can use (or invalidate) + the analysis passes. Transform passes all mutate the program in some way. + Utility passes provides some utility but don't otherwise fit categorization. + For example passes to extract functions to bitcode or write a module to + bitcode are neither analysis nor transform passes. +

    The table below provides a quick summary of each pass and links to the more + complete pass description later in the document.

    +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    ANALYSIS PASSES
    OptionName
    -aa-evalExhaustive Alias Analysis Precision Evaluator
    -anders-aaAndersen's Interprocedural Alias Analysis
    -basicaaBasic Alias Analysis (default AA impl)
    -basiccgBasic CallGraph Construction
    -codegenprepareOptimize for code generation
    -count-aaCount Alias Analysis Query Responses
    -debug-aaAA use debugger
    -domfrontierDominance Frontier Construction
    -domtreeDominator Tree Construction
    -dot-callgraphPrint Call Graph to 'dot' file
    -dot-cfgPrint CFG of function to 'dot' file
    -dot-cfg-onlyPrint CFG of function to 'dot' file (with no function bodies)
    -globalsmodref-aaSimple mod/ref analysis for globals
    -instcountCounts the various types of Instructions
    -intervalsInterval Partition Construction
    -loopsNatural Loop Construction
    -memdepMemory Dependence Analysis
    -no-aaNo Alias Analysis (always returns 'may' alias)
    -no-profileNo Profile Information
    -postdomfrontierPost-Dominance Frontier Construction
    -postdomtreePost-Dominator Tree Construction
    -print-alias-setsAlias Set Printer
    -print-callgraphPrint a call graph
    -print-callgraph-sccsPrint SCCs of the Call Graph
    -print-cfg-sccsPrint SCCs of each function CFG
    -print-externalfnconstantsPrint external fn callsites passed constants
    -print-functionPrint function to stderr
    -print-modulePrint module to stderr
    -print-used-typesFind Used Types
    -profile-loaderLoad profile information from llvmprof.out
    -scalar-evolutionScalar Evolution Analysis
    -targetdataTarget Data Layout
    TRANSFORM PASSES
    OptionName
    -adceAggressive Dead Code Elimination
    -argpromotionPromote 'by reference' arguments to scalars
    -block-placementProfile Guided Basic Block Placement
    -break-crit-edgesBreak critical edges in CFG
    -codegenpreparePrepare a function for code generation
    -condpropConditional Propagation
    -constmergeMerge Duplicate Global Constants
    -constpropSimple constant propagation
    -dceDead Code Elimination
    -deadargelimDead Argument Elimination
    -deadtypeelimDead Type Elimination
    -dieDead Instruction Elimination
    -dseDead Store Elimination
    -globaldceDead Global Elimination
    -globaloptGlobal Variable Optimizer
    -gvnGlobal Value Numbering
    -indmemremIndirect Malloc and Free Removal
    -indvarsCanonicalize Induction Variables
    -inlineFunction Integration/Inlining
    -insert-block-profilingInsert instrumentation for block profiling
    -insert-edge-profilingInsert instrumentation for edge profiling
    -insert-function-profilingInsert instrumentation for function profiling
    -insert-null-profiling-rsMeasure profiling framework overhead
    -insert-rs-profiling-frameworkInsert random sampling instrumentation framework
    -instcombineCombine redundant instructions
    -internalizeInternalize Global Symbols
    -ipconstpropInterprocedural constant propagation
    -ipsccpInterprocedural Sparse Conditional Constant Propagation
    -jump-threadingThread control through conditional blocks
    -lcssaLoop-Closed SSA Form Pass
    -licmLoop Invariant Code Motion
    -loop-deletionDead Loop Deletion Pass
    -loop-extractExtract loops into new functions
    -loop-extract-singleExtract at most one loop into a new function
    -loop-index-splitIndex Split Loops
    -loop-reduceLoop Strength Reduction
    -loop-rotateRotate Loops
    -loop-unrollUnroll loops
    -loop-unswitchUnswitch loops
    -loopsimplifyCanonicalize natural loops
    -lowerallocsLower allocations from instructions to calls
    -lowerinvokeLower invoke and unwind, for unwindless code generators
    -lowersetjmpLower Set Jump
    -lowerswitchLower SwitchInst's to branches
    -mem2regPromote Memory to Register
    -memcpyoptOptimize use of memcpy and friends
    -mergereturnUnify function exit nodes
    -prune-ehRemove unused exception handling info
    -reassociateReassociate expressions
    -reg2memDemote all values to stack slots
    -scalarreplScalar Replacement of Aggregates
    -sccpSparse Conditional Constant Propagation
    -simplify-libcallsSimplify well-known library calls
    -simplifycfgSimplify the CFG
    -stripStrip all symbols from a module
    -strip-dead-prototypesRemove unused function declarations
    -sretpromotionPromote sret arguments
    -tailcallelimTail Call Elimination
    -tailduplicateTail Duplication
    UTILITY PASSES
    OptionName
    -deadarghaX0rDead Argument Hacking (BUGPOINT USE ONLY; DO NOT USE)
    -extract-blocksExtract Basic Blocks From Module (for bugpoint use)
    -preverifyPreliminary module verification
    -verifyModule Verifier
    -view-cfgView CFG of function
    -view-cfg-onlyView CFG of function (with no function bodies)
    +
    + + + +
    +

    This section describes the LLVM Analysis Passes.

    +
    + + + +
    +

    This is a simple N^2 alias analysis accuracy evaluator. + Basically, for each function in the program, it simply queries to see how the + alias analysis implementation answers alias queries between each pair of + pointers in the function.

    + +

    This is inspired and adapted from code by: Naveen Neelakantam, Francesco + Spadini, and Wojciech Stryjewski.

    +
    + + + +
    +

    + This is an implementation of Andersen's interprocedural alias + analysis +

    + +

    + In pointer analysis terms, this is a subset-based, flow-insensitive, + field-sensitive, and context-insensitive algorithm pointer algorithm. +

    + +

    + This algorithm is implemented as three stages: +

    + +
      +
    1. Object identification.
    2. +
    3. Inclusion constraint identification.
    4. +
    5. Offline constraint graph optimization.
    6. +
    7. Inclusion constraint solving.
    8. +
    + +

    + The object identification stage identifies all of the memory objects in the + program, which includes globals, heap allocated objects, and stack allocated + objects. +

    + +

    + The inclusion constraint identification stage finds all inclusion constraints + in the program by scanning the program, looking for pointer assignments and + other statements that effect the points-to graph. For a statement like + A = B, this statement is processed to + indicate that A can point to anything that B can point + to. Constraints can handle copies, loads, and stores, and address taking. +

    + +

    + The offline constraint graph optimization portion includes offline variable + substitution algorithms intended to computer pointer and location + equivalences. Pointer equivalences are those pointers that will have the + same points-to sets, and location equivalences are those variables that + always appear together in points-to sets. +

    + +

    + The inclusion constraint solving phase iteratively propagates the inclusion + constraints until a fixed point is reached. This is an O(n³) + algorithm. +

    + +

    + Function constraints are handled as if they were structs with X + fields. Thus, an access to argument X of function Y is + an access to node index getNode(Y) + X. + This representation allows handling of indirect calls without any issues. To + wit, an indirect call Y(a,b) is + equivalent to *(Y + 1) = a, *(Y + 2) = + b. The return node for a function F is always + located at getNode(F) + CallReturnPos. The arguments + start at getNode(F) + CallArgPos. +

    + +

    + Please keep in mind that the current andersen's pass has many known + problems and bugs. It should be considered "research quality". +

    + +
    + + + +
    +

    + This is the default implementation of the Alias Analysis interface + that simply implements a few identities (two different globals cannot alias, + etc), but otherwise does no analysis. +

    +
    + + + +
    +

    Yet to be written.

    +
    + + + +
    +

    + This pass munges the code in the input function to better prepare it for + SelectionDAG-based code generation. This works around limitations in it's + basic-block-at-a-time approach. It should eventually be removed. +

    +
    + + + +
    +

    + A pass which can be used to count how many alias queries + are being made and how the alias analysis implementation being used responds. +

    +
    + + + +
    +

    + This simple pass checks alias analysis users to ensure that if they + create a new value, they do not query AA without informing it of the value. + It acts as a shim over any other AA pass you want. +

    + +

    + Yes keeping track of every value in the program is expensive, but this is + a debugging pass. +

    +
    + + + +
    +

    + This pass is a simple dominator construction algorithm for finding forward + dominator frontiers. +

    +
    + + + +
    +

    + This pass is a simple dominator construction algorithm for finding forward + dominators. +

    +
    + + + +
    +

    + This pass, only available in opt, prints the call graph into a + .dot graph. This graph can then be processed with the "dot" tool + to convert it to postscript or some other suitable format. +

    +
    + + + +
    +

    + This pass, only available in opt, prints the control flow graph + into a .dot graph. This graph can then be processed with the + "dot" tool to convert it to postscript or some other suitable format. +

    +
    + + + +
    +

    + This pass, only available in opt, prints the control flow graph + into a .dot graph, omitting the function bodies. This graph can + then be processed with the "dot" tool to convert it to postscript or some + other suitable format. +

    +
    + + + +
    +

    + This simple pass provides alias and mod/ref information for global values + that do not have their address taken, and keeps track of whether functions + read or write memory (are "pure"). For this simple (but very common) case, + we can provide pretty accurate and useful information. +

    +
    + + + +
    +

    + This pass collects the count of all instructions and reports them +

    +
    + + + +
    +

    + This analysis calculates and represents the interval partition of a function, + or a preexisting interval partition. +

    + +

    + In this way, the interval partition may be used to reduce a flow graph down + to its degenerate single node interval partition (unless it is irreducible). +

    +
    + + + +
    +

    + This analysis is used to identify natural loops and determine the loop depth + of various nodes of the CFG. Note that the loops identified may actually be + several natural loops that share the same header node... not just a single + natural loop. +

    +
    + + + +
    +

    + An analysis that determines, for a given memory operation, what preceding + memory operations it depends on. It builds on alias analysis information, and + tries to provide a lazy, caching interface to a common kind of alias + information query. +

    +
    + + + +
    +

    + Always returns "I don't know" for alias queries. NoAA is unlike other alias + analysis implementations, in that it does not chain to a previous analysis. As + such it doesn't follow many of the rules that other alias analyses must. +

    +
    + + + +
    +

    + The default "no profile" implementation of the abstract + ProfileInfo interface. +

    +
    + + + +
    +

    + This pass is a simple post-dominator construction algorithm for finding + post-dominator frontiers. +

    +
    + + + +
    +

    + This pass is a simple post-dominator construction algorithm for finding + post-dominators. +

    +
    + + + +
    +

    Yet to be written.

    +
    + + + +
    +

    + This pass, only available in opt, prints the call graph to + standard output in a human-readable form. +

    +
    + + + +
    +

    + This pass, only available in opt, prints the SCCs of the call + graph to standard output in a human-readable form. +

    +
    + + + +
    +

    + This pass, only available in opt, prints the SCCs of each + function CFG to standard output in a human-readable form. +

    +
    + + + +
    +

    + This pass, only available in opt, prints out call sites to + external functions that are called with constant arguments. This can be + useful when looking for standard library functions we should constant fold + or handle in alias analyses. +

    +
    + + + +
    +

    + The PrintFunctionPass class is designed to be pipelined with + other FunctionPasses, and prints out the functions of the module + as they are processed. +

    +
    + + + +
    +

    + This pass simply prints out the entire module when it is executed. +

    +
    + + + +
    +

    + This pass is used to seek out all of the types in use by the program. Note + that this analysis explicitly does not include types only used by the symbol + table. +

    + + + +
    +

    + A concrete implementation of profiling information that loads the information + from a profile dump file. +

    +
    + + + +
    +

    + The ScalarEvolution analysis can be used to analyze and + catagorize scalar expressions in loops. It specializes in recognizing general + induction variables, representing them with the abstract and opaque + SCEV class. Given this analysis, trip counts of loops and other + important properties can be obtained. +

    + +

    + This analysis is primarily useful for induction variable substitution and + strength reduction. +

    +
    + + + +
    +

    Provides other passes access to information on how the size and alignment + required by the the target ABI for various data types.

    +
    + + + +
    +

    This section describes the LLVM Transform Passes.

    +
    + + + +
    +

    ADCE aggressively tries to eliminate code. This pass is similar to + DCE but it assumes that values are dead until proven + otherwise. This is similar to SCCP, except applied to + the liveness of values.

    +
    + + + +
    +

    + This pass promotes "by reference" arguments to be "by value" arguments. In + practice, this means looking for internal functions that have pointer + arguments. If it can prove, through the use of alias analysis, that an + argument is *only* loaded, then it can pass the value into the function + instead of the address of the value. This can cause recursive simplification + of code and lead to the elimination of allocas (especially in C++ template + code like the STL). +

    + +

    + This pass also handles aggregate arguments that are passed into a function, + scalarizing them if the elements of the aggregate are only loaded. Note that + it refuses to scalarize aggregates which would require passing in more than + three operands to the function, because passing thousands of operands for a + large array or structure is unprofitable! +

    + +

    + Note that this transformation could also be done for arguments that are only + stored to (returning the value instead), but does not currently. This case + would be best handled when and if LLVM starts supporting multiple return + values from functions. +

    +
    + + + +
    +

    This pass is a very simple profile guided basic block placement algorithm. + The idea is to put frequently executed blocks together at the start of the + function and hopefully increase the number of fall-through conditional + branches. If there is no profile information for a particular function, this + pass basically orders blocks in depth-first order.

    +
    + + + +
    +

    + Break all of the critical edges in the CFG by inserting a dummy basic block. + It may be "required" by passes that cannot deal with critical edges. This + transformation obviously invalidates the CFG, but can update forward dominator + (set, immediate dominators, tree, and frontier) information. +

    +
    + + + +
    + This pass munges the code in the input function to better prepare it for + SelectionDAG-based code generation. This works around limitations in it's + basic-block-at-a-time approach. It should eventually be removed. +
    + + + +
    +

    This pass propagates information about conditional expressions through the + program, allowing it to eliminate conditional branches in some cases.

    +
    + + + +
    +

    + Merges duplicate global constants together into a single constant that is + shared. This is useful because some passes (ie TraceValues) insert a lot of + string constants into the program, regardless of whether or not an existing + string is available. +

    +
    + + + +
    +

    This file implements constant propagation and merging. It looks for + instructions involving only constant operands and replaces them with a + constant value instead of an instruction. For example:

    +
    add i32 1, 2
    +

    becomes

    +
    i32 3
    +

    NOTE: this pass has a habit of making definitions be dead. It is a good + idea to to run a DIE (Dead Instruction Elimination) pass + sometime after running this pass.

    +
    + + + +
    +

    + Dead code elimination is similar to dead instruction + elimination, but it rechecks instructions that were used by removed + instructions to see if they are newly dead. +

    +
    + + + +
    +

    + This pass deletes dead arguments from internal functions. Dead argument + elimination removes arguments which are directly dead, as well as arguments + only passed into function calls as dead arguments of other functions. This + pass also deletes dead arguments in a similar way. +

    + +

    + This pass is often useful as a cleanup pass to run after aggressive + interprocedural passes, which add possibly-dead arguments. +

    +
    + + + +
    +

    + This pass is used to cleanup the output of GCC. It eliminate names for types + that are unused in the entire translation unit, using the find used types pass. +

    +
    + + + +
    +

    + Dead instruction elimination performs a single pass over the function, + removing instructions that are obviously dead. +

    +
    + + + +
    +

    + A trivial dead store elimination that only considers basic-block local + redundant stores. +

    +
    + + + +
    +

    + This transform is designed to eliminate unreachable internal globals from the + program. It uses an aggressive algorithm, searching out globals that are + known to be alive. After it finds all of the globals which are needed, it + deletes whatever is left over. This allows it to delete recursive chunks of + the program which are unreachable. +

    +
    + + + +
    +

    + This pass transforms simple global variables that never have their address + taken. If obviously true, it marks read/write globals as constant, deletes + variables only stored to, etc. +

    +
    + + + +
    +

    + This pass performs global value numbering to eliminate fully and partially + redundant instructions. It also performs redundant load elimination. +

    +
    + + + + +
    +

    + This pass finds places where memory allocation functions may escape into + indirect land. Some transforms are much easier (aka possible) only if free + or malloc are not called indirectly. +

    + +

    + Thus find places where the address of memory functions are taken and construct + bounce functions with direct calls of those functions. +

    +
    + + + +
    +

    + This transformation analyzes and transforms the induction variables (and + computations derived from them) into simpler forms suitable for subsequent + analysis and transformation. +

    + +

    + This transformation makes the following changes to each loop with an + identifiable induction variable: +

    + +
      +
    1. All loops are transformed to have a single canonical + induction variable which starts at zero and steps by one.
    2. +
    3. The canonical induction variable is guaranteed to be the first PHI node + in the loop header block.
    4. +
    5. Any pointer arithmetic recurrences are raised to use array + subscripts.
    6. +
    + +

    + If the trip count of a loop is computable, this pass also makes the following + changes: +

    + +
      +
    1. The exit condition for the loop is canonicalized to compare the + induction value against the exit value. This turns loops like: +
      for (i = 7; i*i < 1000; ++i)
      + into +
      for (i = 0; i != 25; ++i)
    2. +
    3. Any use outside of the loop of an expression derived from the indvar + is changed to compute the derived value outside of the loop, eliminating + the dependence on the exit value of the induction variable. If the only + purpose of the loop is to compute the exit value of some derived + expression, this transformation will make the loop dead.
    4. +
    + +

    + This transformation should be followed by strength reduction after all of the + desired loop transformations have been performed. Additionally, on targets + where it is profitable, the loop could be transformed to count down to zero + (the "do loop" optimization). +

    +
    + + + +
    +

    + Bottom-up inlining of functions into callees. +

    +
    + + + +
    +

    + This pass instruments the specified program with counters for basic block + profiling, which counts the number of times each basic block executes. This + is the most basic form of profiling, which can tell which blocks are hot, but + cannot reliably detect hot paths through the CFG. +

    + +

    + Note that this implementation is very naïve. Control equivalent regions of + the CFG should not require duplicate counters, but it does put duplicate + counters in. +

    +
    + + + +
    +

    + This pass instruments the specified program with counters for edge profiling. + Edge profiling can give a reasonable approximation of the hot paths through a + program, and is used for a wide variety of program transformations. +

    + +

    + Note that this implementation is very naïve. It inserts a counter for + every edge in the program, instead of using control flow information + to prune the number of counters inserted. +

    +
    + + + +
    +

    + This pass instruments the specified program with counters for function + profiling, which counts the number of times each function is called. +

    +
    + + + +
    +

    + The basic profiler that does nothing. It is the default profiler and thus + terminates RSProfiler chains. It is useful for measuring + framework overhead. +

    +
    + + + +
    +

    + The second stage of the random-sampling instrumentation framework, duplicates + all instructions in a function, ignoring the profiling code, then connects the + two versions together at the entry and at backedges. At each connection point + a choice is made as to whether to jump to the profiled code (take a sample) or + execute the unprofiled code. +

    + +

    + After this pass, it is highly recommended to runmem2reg + and adce. instcombine, + load-vn, gdce, and + dse also are good to run afterwards. +

    +
    + + + +
    +

    + Combine instructions to form fewer, simple + instructions. This pass does not modify the CFG This pass is where algebraic + simplification happens. +

    + +

    + This pass combines things like: +

    + +
    %Y = add i32 %X, 1
    +%Z = add i32 %Y, 1
    + +

    + into: +

    + +
    %Z = add i32 %X, 2
    + +

    + This is a simple worklist driven algorithm. +

    + +

    + This pass guarantees that the following canonicalizations are performed on + the program: +

    + +
      +
    • If a binary operator has a constant operand, it is moved to the right- + hand side.
    • +
    • Bitwise operators with constant operands are always grouped so that + shifts are performed first, then ors, then + ands, then xors.
    • +
    • Compare instructions are converted from <, + >, , or to + = or if possible.
    • +
    • All cmp instructions on boolean values are replaced with + logical operations.
    • +
    • add X, X is represented as + mul X, 2shl X, 1
    • +
    • Multiplies with a constant power-of-two argument are transformed into + shifts.
    • +
    • … etc.
    • +
    +
    + + + +
    +

    + This pass loops over all of the functions in the input module, looking for a + main function. If a main function is found, all other functions and all + global variables with initializers are marked as internal. +

    +
    + + + +
    +

    + This pass implements an extremely simple interprocedural constant + propagation pass. It could certainly be improved in many different ways, + like using a worklist. This pass makes arguments dead, but does not remove + them. The existing dead argument elimination pass should be run after this + to clean up the mess. +

    +
    + + + +
    +

    + An interprocedural variant of Sparse Conditional Constant + Propagation. +

    +
    + + + +
    +

    + Jump threading tries to find distinct threads of control flow running through + a basic block. This pass looks at blocks that have multiple predecessors and + multiple successors. If one or more of the predecessors of the block can be + proven to always cause a jump to one of the successors, we forward the edge + from the predecessor to the successor by duplicating the contents of this + block. +

    +

    + An example of when this can occur is code like this: +

    + +
    if () { ...
    +  X = 4;
    +}
    +if (X < 3) {
    + +

    + In this case, the unconditional branch at the end of the first if can be + revectored to the false side of the second if. +

    +
    + + + +
    +

    + This pass transforms loops by placing phi nodes at the end of the loops for + all values that are live across the loop boundary. For example, it turns + the left into the right code: +

    + +
    for (...)                for (...)
    +  if (c)                   if (c)
    +    X1 = ...                 X1 = ...
    +  else                     else
    +    X2 = ...                 X2 = ...
    +  X3 = phi(X1, X2)         X3 = phi(X1, X2)
    +... = X3 + 4              X4 = phi(X3)
    +                          ... = X4 + 4
    + +

    + This is still valid LLVM; the extra phi nodes are purely redundant, and will + be trivially eliminated by InstCombine. The major benefit of + this transformation is that it makes many other loop optimizations, such as + LoopUnswitching, simpler. +

    +
    + + + +
    +

    + This pass performs loop invariant code motion, attempting to remove as much + code from the body of a loop as possible. It does this by either hoisting + code into the preheader block, or by sinking code to the exit blocks if it is + safe. This pass also promotes must-aliased memory locations in the loop to + live in registers, thus hoisting and sinking "invariant" loads and stores. +

    + +

    + This pass uses alias analysis for two purposes: +

    + +
      +
    • Moving loop invariant loads and calls out of loops. If we can determine + that a load or call inside of a loop never aliases anything stored to, + we can hoist it or sink it like any other instruction.
    • +
    • Scalar Promotion of Memory - If there is a store instruction inside of + the loop, we try to move the store to happen AFTER the loop instead of + inside of the loop. This can only happen if a few conditions are true: +
        +
      • The pointer stored through is loop invariant.
      • +
      • There are no stores or loads in the loop which may alias + the pointer. There are no calls in the loop which mod/ref the + pointer.
      • +
      + If these conditions are true, we can promote the loads and stores in the + loop of the pointer to use a temporary alloca'd variable. We then use + the mem2reg functionality to construct the appropriate SSA form for the + variable.
    • +
    +
    + + +
    +

    + This file implements the Dead Loop Deletion Pass. This pass is responsible + for eliminating loops with non-infinite computable trip counts that have no + side effects or volatile instructions, and do not contribute to the + computation of the function's return value. +

    +
    + + + +
    +

    + A pass wrapper around the ExtractLoop() scalar transformation to + extract each top-level loop into its own new function. If the loop is the + only loop in a given function, it is not touched. This is a pass most + useful for debugging via bugpoint. +

    +
    + + + +
    +

    + Similar to Extract loops into new functions, + this pass extracts one natural loop from the program into a function if it + can. This is used by bugpoint. +

    +
    + + + +
    +

    + This pass divides loop's iteration range by spliting loop such that each + individual loop is executed efficiently. +

    +
    + + + +
    +

    + This pass performs a strength reduction on array references inside loops that + have as one or more of their components the loop induction variable. This is + accomplished by creating a new value to hold the initial value of the array + access for the first iteration, and then creating a new GEP instruction in + the loop to increment the value by the appropriate amount. +

    +
    + + + +
    +

    A simple loop rotation transformation.

    +
    + + + +
    +

    + This pass implements a simple loop unroller. It works best when loops have + been canonicalized by the -indvars pass, + allowing it to determine the trip counts of loops easily. +

    +
    + + + +
    +

    + This pass transforms loops that contain branches on loop-invariant conditions + to have multiple loops. For example, it turns the left into the right code: +

    + +
    for (...)                  if (lic)
    +  A                          for (...)
    +  if (lic)                     A; B; C
    +    B                      else
    +  C                          for (...)
    +                               A; C
    + +

    + This can increase the size of the code exponentially (doubling it every time + a loop is unswitched) so we only unswitch if the resultant code will be + smaller than a threshold. +

    + +

    + This pass expects LICM to be run before it to hoist invariant conditions out + of the loop, to make the unswitching opportunity obvious. +

    +
    + + + +
    +

    + This pass performs several transformations to transform natural loops into a + simpler form, which makes subsequent analyses and transformations simpler and + more effective. +

    + +

    + Loop pre-header insertion guarantees that there is a single, non-critical + entry edge from outside of the loop to the loop header. This simplifies a + number of analyses and transformations, such as LICM. +

    + +

    + Loop exit-block insertion guarantees that all exit blocks from the loop + (blocks which are outside of the loop that have predecessors inside of the + loop) only have predecessors from inside of the loop (and are thus dominated + by the loop header). This simplifies transformations such as store-sinking + that are built into LICM. +

    + +

    + This pass also guarantees that loops will have exactly one backedge. +

    + +

    + Note that the simplifycfg pass will clean up blocks which are split out but + end up being unnecessary, so usage of this pass should not pessimize + generated code. +

    + +

    + This pass obviously modifies the CFG, but updates loop information and + dominator information. +

    +
    + + + +
    +

    + Turn malloc and free instructions into @malloc and + @free calls. +

    + +

    + This is a target-dependent tranformation because it depends on the size of + data types and alignment constraints. +

    +
    + + + +
    +

    + This transformation is designed for use by code generators which do not yet + support stack unwinding. This pass supports two models of exception handling + lowering, the 'cheap' support and the 'expensive' support. +

    + +

    + 'Cheap' exception handling support gives the program the ability to execute + any program which does not "throw an exception", by turning 'invoke' + instructions into calls and by turning 'unwind' instructions into calls to + abort(). If the program does dynamically use the unwind instruction, the + program will print a message then abort. +

    + +

    + 'Expensive' exception handling support gives the full exception handling + support to the program at the cost of making the 'invoke' instruction + really expensive. It basically inserts setjmp/longjmp calls to emulate the + exception handling as necessary. +

    + +

    + Because the 'expensive' support slows down programs a lot, and EH is only + used for a subset of the programs, it must be specifically enabled by the + -enable-correct-eh-support option. +

    + +

    + Note that after this pass runs the CFG is not entirely accurate (exceptional + control flow edges are not correct anymore) so only very simple things should + be done after the lowerinvoke pass has run (like generation of native code). + This should not be used as a general purpose "my LLVM-to-LLVM pass doesn't + support the invoke instruction yet" lowering pass. +

    +
    + + + +
    +

    + Lowers setjmp and longjmp to use the LLVM invoke and unwind + instructions as necessary. +

    + +

    + Lowering of longjmp is fairly trivial. We replace the call with a + call to the LLVM library function __llvm_sjljeh_throw_longjmp(). + This unwinds the stack for us calling all of the destructors for + objects allocated on the stack. +

    + +

    + At a setjmp call, the basic block is split and the setjmp + removed. The calls in a function that have a setjmp are converted to + invoke where the except part checks to see if it's a longjmp + exception and, if so, if it's handled in the function. If it is, then it gets + the value returned by the longjmp and goes to where the basic block + was split. invoke instructions are handled in a similar fashion with + the original except block being executed if it isn't a longjmp + except that is handled by that function. +

    +
    + + + +
    +

    + Rewrites switch instructions with a sequence of branches, which + allows targets to get away with not implementing the switch instruction until + it is convenient. +

    +
    + + + +
    +

    + This file promotes memory references to be register references. It promotes + alloca instructions which only have loads and + stores as uses. An alloca is transformed by using dominator + frontiers to place phi nodes, then traversing the function in + depth-first order to rewrite loads and stores as + appropriate. This is just the standard SSA construction algorithm to construct + "pruned" SSA form. +

    +
    + + + +
    +

    + This pass performs various transformations related to eliminating memcpy + calls, or transforming sets of stores into memset's. +

    +
    + + + +
    +

    + Ensure that functions have at most one ret instruction in them. + Additionally, it keeps track of which node is the new exit node of the CFG. +

    +
    + + + +
    +

    + This file implements a simple interprocedural pass which walks the call-graph, + turning invoke instructions into call instructions if and + only if the callee cannot throw an exception. It implements this as a + bottom-up traversal of the call-graph. +

    +
    + + + +
    +

    + This pass reassociates commutative expressions in an order that is designed + to promote better constant propagation, GCSE, LICM, PRE, etc. +

    + +

    + For example: 4 + (x + 5) ⇒ x + (4 + 5) +

    + +

    + In the implementation of this algorithm, constants are assigned rank = 0, + function arguments are rank = 1, and other values are assigned ranks + corresponding to the reverse post order traversal of current function + (starting at 2), which effectively gives values in deep loops higher rank + than values not in loops. +

    +
    + + + +
    +

    + This file demotes all registers to memory references. It is intented to be + the inverse of -mem2reg. By converting to + load instructions, the only values live across basic blocks are + alloca instructions and load instructions before + phi nodes. It is intended that this should make CFG hacking much + easier. To make later hacking easier, the entry block is split into two, such + that all introduced alloca instructions (and nothing else) are in the + entry block. +

    +
    + + + +
    +

    + The well-known scalar replacement of aggregates transformation. This + transform breaks up alloca instructions of aggregate type (structure + or array) into individual alloca instructions for each member if + possible. Then, if possible, it transforms the individual alloca + instructions into nice clean scalar SSA form. +

    + +

    + This combines a simple scalar replacement of aggregates algorithm with the mem2reg algorithm because often interact, + especially for C++ programs. As such, iterating between scalarrepl, + then mem2reg until we run out of things to + promote works well. +

    +
    + + + +
    +

    + Sparse conditional constant propagation and merging, which can be summarized + as: +

    + +
      +
    1. Assumes values are constant unless proven otherwise
    2. +
    3. Assumes BasicBlocks are dead unless proven otherwise
    4. +
    5. Proves values to be constant, and replaces them with constants
    6. +
    7. Proves conditional branches to be unconditional
    8. +
    + +

    + Note that this pass has a habit of making definitions be dead. It is a good + idea to to run a DCE pass sometime after running this pass. +

    +
    + + + +
    +

    + Applies a variety of small optimizations for calls to specific well-known + function calls (e.g. runtime library functions). For example, a call + exit(3) that occurs within the main() function can be + transformed into simply return 3. +

    +
    + + + +
    +

    + Performs dead code elimination and basic block merging. Specifically: +

    + +
      +
    1. Removes basic blocks with no predecessors.
    2. +
    3. Merges a basic block into its predecessor if there is only one and the + predecessor only has one successor.
    4. +
    5. Eliminates PHI nodes for basic blocks with a single predecessor.
    6. +
    7. Eliminates a basic block that only contains an unconditional + branch.
    8. +
    +
    + + + +
    +

    + Performs code stripping. This transformation can delete: +

    + +
      +
    1. names for virtual registers
    2. +
    3. symbols for internal globals and functions
    4. +
    5. debug information
    6. +
    + +

    + Note that this transformation makes code much less readable, so it should + only be used in situations where the strip utility would be used, + such as reducing code size or making it harder to reverse engineer code. +

    +
    + + + +
    +

    + This pass loops over all of the functions in the input module, looking for + dead declarations and removes them. Dead declarations are declarations of + functions for which no implementation is available (i.e., declarations for + unused library functions). +

    +
    + + + +
    +

    + This pass finds functions that return a struct (using a pointer to the struct + as the first argument of the function, marked with the 'sret' attribute) and + replaces them with a new function that simply returns each of the elements of + that struct (using multiple return values). +

    + +

    + This pass works under a number of conditions: +

    + +
      +
    • The returned struct must not contain other structs
    • +
    • The returned struct must only be used to load values from
    • +
    • The placeholder struct passed in is the result of an alloca
    • +
    +
    + + + +
    +

    + This file transforms calls of the current function (self recursion) followed + by a return instruction with a branch to the entry of the function, creating + a loop. This pass also implements the following extensions to the basic + algorithm: +

    + +
      +
    • Trivial instructions between the call and return do not prevent the + transformation from taking place, though currently the analysis cannot + support moving any really useful instructions (only dead ones). +
    • This pass transforms functions that are prevented from being tail + recursive by an associative expression to use an accumulator variable, + thus compiling the typical naive factorial or fib implementation + into efficient code. +
    • TRE is performed if the function returns void, if the return + returns the result returned by the call, or if the function returns a + run-time constant on all exits from the function. It is possible, though + unlikely, that the return returns something else (like constant 0), and + can still be TRE'd. It can be TRE'd if all other return + instructions in the function return the exact same value. +
    • If it can prove that callees do not access theier caller stack frame, + they are marked as eligible for tail call elimination (by the code + generator). +
    +
    + + + +
    +

    + This pass performs a limited form of tail duplication, intended to simplify + CFGs by removing some unconditional branches. This pass is necessary to + straighten out loops created by the C front-end, but also is capable of + making other code nicer. After this pass is run, the CFG simplify pass + should be run to clean up the mess. +

    +
    + + + +
    +

    This section describes the LLVM Utility Passes.

    +
    + + + +
    +

    + Same as dead argument elimination, but deletes arguments to functions which + are external. This is only for use by bugpoint.

    +
    + + + +
    +

    + This pass is used by bugpoint to extract all blocks from the module into their + own functions.

    +
    + + + +
    +

    + Ensures that the module is in the form required by the Module Verifier pass. +

    + +

    + Running the verifier runs this pass automatically, so there should be no need + to use it directly. +

    +
    + + + +
    +

    + Verifies an LLVM IR code. This is useful to run after an optimization which is + undergoing testing. Note that llvm-as verifies its input before + emitting bitcode, and also that malformed bitcode is likely to make LLVM + crash. All language front-ends are therefore encouraged to verify their output + before performing optimizing transformations. +

    + +
      +
    • Both of a binary operator's parameters are of the same type.
    • +
    • Verify that the indices of mem access instructions match other + operands.
    • +
    • Verify that arithmetic and other things are only performed on + first-class types. Verify that shifts and logicals only happen on + integrals f.e.
    • +
    • All of the constants in a switch statement are of the correct type.
    • +
    • The code is in valid SSA form.
    • +
    • It is illegal to put a label into any other type (like a structure) or + to return one.
    • +
    • Only phi nodes can be self referential: %x = add i32 %x, %x is + invalid.
    • +
    • PHI nodes must have an entry for each predecessor, with no extras.
    • +
    • PHI nodes must be the first thing in a basic block, all grouped + together.
    • +
    • PHI nodes must have at least one entry.
    • +
    • All basic blocks should only end with terminator insts, not contain + them.
    • +
    • The entry node to a function must not have predecessors.
    • +
    • All Instructions must be embedded into a basic block.
    • +
    • Functions cannot take a void-typed parameter.
    • +
    • Verify that a function's argument list agrees with its declared + type.
    • +
    • It is illegal to specify a name for a void value.
    • +
    • It is illegal to have a internal global value with no initializer.
    • +
    • It is illegal to have a ret instruction that returns a value that does + not agree with the function return value type.
    • +
    • Function call argument types match the function prototype.
    • +
    • All other things that are tested by asserts spread about the code.
    • +
    + +

    + Note that this does not provide full security verification (like Java), but + instead just tries to ensure that code is well-formed. +

    +
    + + + +
    +

    + Displays the control flow graph using the GraphViz tool. +

    +
    + + + +
    +

    + Displays the control flow graph using the GraphViz tool, but omitting function + bodies. +

    +
    + + + +
    +
    + Valid CSS + Valid HTML 4.01 + + Reid Spencer
    + LLVM Compiler Infrastructure
    + Last modified: $Date$ +
    + + + diff --git a/libclamav/c++/llvm/docs/ProgrammersManual.html b/libclamav/c++/llvm/docs/ProgrammersManual.html new file mode 100644 index 000000000..e4e3dc29c --- /dev/null +++ b/libclamav/c++/llvm/docs/ProgrammersManual.html @@ -0,0 +1,3879 @@ + + + + + LLVM Programmer's Manual + + + + +
    + LLVM Programmer's Manual +
    + +
      +
    1. Introduction
    2. +
    3. General Information + +
    4. +
    5. Important and useful LLVM APIs + +
    6. +
    7. Picking the Right Data Structure for a Task + +
    8. +
    9. Helpful Hints for Common Operations + +
    10. + +
    11. Threads and LLVM + +
    12. + +
    13. Advanced Topics +
    14. + +
    15. The Core LLVM Class Hierarchy Reference + +
    16. +
    + + + + + + + +
    + +

    This document is meant to highlight some of the important classes and +interfaces available in the LLVM source-base. This manual is not +intended to explain what LLVM is, how it works, and what LLVM code looks +like. It assumes that you know the basics of LLVM and are interested +in writing transformations or otherwise analyzing or manipulating the +code.

    + +

    This document should get you oriented so that you can find your +way in the continuously growing source code that makes up the LLVM +infrastructure. Note that this manual is not intended to serve as a +replacement for reading the source code, so if you think there should be +a method in one of these classes to do something, but it's not listed, +check the source. Links to the doxygen sources +are provided to make this as easy as possible.

    + +

    The first section of this document describes general information that is +useful to know when working in the LLVM infrastructure, and the second describes +the Core LLVM classes. In the future this manual will be extended with +information describing how to use extension libraries, such as dominator +information, CFG traversal routines, and useful utilities like the InstVisitor template.

    + +
    + + + + + +
    + +

    This section contains general information that is useful if you are working +in the LLVM source-base, but that isn't specific to any particular API.

    + +
    + + + + +
    + +

    LLVM makes heavy use of the C++ Standard Template Library (STL), +perhaps much more than you are used to, or have seen before. Because of +this, you might want to do a little background reading in the +techniques used and capabilities of the library. There are many good +pages that discuss the STL, and several books on the subject that you +can get, so it will not be discussed in this document.

    + +

    Here are some useful links:

    + +
      + +
    1. Dinkumware C++ Library +reference - an excellent reference for the STL and other parts of the +standard C++ library.
    2. + +
    3. C++ In a Nutshell - This is an +O'Reilly book in the making. It has a decent Standard Library +Reference that rivals Dinkumware's, and is unfortunately no longer free since the +book has been published.
    4. + +
    5. C++ Frequently Asked +Questions
    6. + +
    7. SGI's STL Programmer's Guide - +Contains a useful Introduction to the +STL.
    8. + +
    9. Bjarne Stroustrup's C++ +Page
    10. + +
    11. +Bruce Eckel's Thinking in C++, 2nd ed. Volume 2 Revision 4.0 (even better, get +the book).
    12. + +
    + +

    You are also encouraged to take a look at the LLVM Coding Standards guide which focuses on how +to write maintainable code more than where to put your curly braces.

    + +
    + + + + + + + + + + +
    + +

    Here we highlight some LLVM APIs that are generally useful and good to +know about when writing transformations.

    + +
    + + + + +
    + +

    The LLVM source-base makes extensive use of a custom form of RTTI. +These templates have many similarities to the C++ dynamic_cast<> +operator, but they don't have some drawbacks (primarily stemming from +the fact that dynamic_cast<> only works on classes that +have a v-table). Because they are used so often, you must know what they +do and how they work. All of these templates are defined in the llvm/Support/Casting.h +file (note that you very rarely have to include this file directly).

    + +
    +
    isa<>:
    + +

    The isa<> operator works exactly like the Java + "instanceof" operator. It returns true or false depending on whether + a reference or pointer points to an instance of the specified class. This can + be very useful for constraint checking of various sorts (example below).

    +
    + +
    cast<>:
    + +

    The cast<> operator is a "checked cast" operation. It + converts a pointer or reference from a base class to a derived class, causing + an assertion failure if it is not really an instance of the right type. This + should be used in cases where you have some information that makes you believe + that something is of the right type. An example of the isa<> + and cast<> template is:

    + +
    +
    +static bool isLoopInvariant(const Value *V, const Loop *L) {
    +  if (isa<Constant>(V) || isa<Argument>(V) || isa<GlobalValue>(V))
    +    return true;
    +
    +  // Otherwise, it must be an instruction...
    +  return !L->contains(cast<Instruction>(V)->getParent());
    +}
    +
    +
    + +

    Note that you should not use an isa<> test followed + by a cast<>, for that use the dyn_cast<> + operator.

    + +
    + +
    dyn_cast<>:
    + +

    The dyn_cast<> operator is a "checking cast" operation. + It checks to see if the operand is of the specified type, and if so, returns a + pointer to it (this operator does not work with references). If the operand is + not of the correct type, a null pointer is returned. Thus, this works very + much like the dynamic_cast<> operator in C++, and should be + used in the same circumstances. Typically, the dyn_cast<> + operator is used in an if statement or some other flow control + statement like this:

    + +
    +
    +if (AllocationInst *AI = dyn_cast<AllocationInst>(Val)) {
    +  // ...
    +}
    +
    +
    + +

    This form of the if statement effectively combines together a call + to isa<> and a call to cast<> into one + statement, which is very convenient.

    + +

    Note that the dyn_cast<> operator, like C++'s + dynamic_cast<> or Java's instanceof operator, can be + abused. In particular, you should not use big chained if/then/else + blocks to check for lots of different variants of classes. If you find + yourself wanting to do this, it is much cleaner and more efficient to use the + InstVisitor class to dispatch over the instruction type directly.

    + +
    + +
    cast_or_null<>:
    + +

    The cast_or_null<> operator works just like the + cast<> operator, except that it allows for a null pointer as an + argument (which it then propagates). This can sometimes be useful, allowing + you to combine several null checks into one.

    + +
    dyn_cast_or_null<>:
    + +

    The dyn_cast_or_null<> operator works just like the + dyn_cast<> operator, except that it allows for a null pointer + as an argument (which it then propagates). This can sometimes be useful, + allowing you to combine several null checks into one.

    + +
    + +

    These five templates can be used with any classes, whether they have a +v-table or not. To add support for these templates, you simply need to add +classof static methods to the class you are interested casting +to. Describing this is currently outside the scope of this document, but there +are lots of examples in the LLVM source base.

    + +
    + + + + + +
    + +

    Although LLVM generally does not do much string manipulation, we do have +several important APIs which take strings. Two important examples are the +Value class -- which has names for instructions, functions, etc. -- and the +StringMap class which is used extensively in LLVM and Clang.

    + +

    These are generic classes, and they need to be able to accept strings which +may have embedded null characters. Therefore, they cannot simply take +a const char *, and taking a const std::string& requires +clients to perform a heap allocation which is usually unnecessary. Instead, +many LLVM APIs use a const StringRef& or a const +Twine& for passing strings efficiently.

    + +
    + + + + +
    + +

    The StringRef data type represents a reference to a constant string +(a character array and a length) and supports the common operations available +on std:string, but does not require heap allocation.

    + +

    It can be implicitly constructed using a C style null-terminated string, +an std::string, or explicitly with a character pointer and length. +For example, the StringRef find function is declared as:

    + +
    + iterator find(const StringRef &Key); +
    + +

    and clients can call it using any one of:

    + +
    +
    +  Map.find("foo");                 // Lookup "foo"
    +  Map.find(std::string("bar"));    // Lookup "bar"
    +  Map.find(StringRef("\0baz", 4)); // Lookup "\0baz"
    +
    +
    + +

    Similarly, APIs which need to return a string may return a StringRef +instance, which can be used directly or converted to an std::string +using the str member function. See +"llvm/ADT/StringRef.h" +for more information.

    + +

    You should rarely use the StringRef class directly, because it contains +pointers to external memory it is not generally safe to store an instance of the +class (unless you know that the external storage will not be freed).

    + +
    + + + + +
    + +

    The Twine class is an efficient way for APIs to accept concatenated +strings. For example, a common LLVM paradigm is to name one instruction based on +the name of another instruction with a suffix, for example:

    + +
    +
    +    New = CmpInst::Create(..., SO->getName() + ".cmp");
    +
    +
    + +

    The Twine class is effectively a +lightweight rope +which points to temporary (stack allocated) objects. Twines can be implicitly +constructed as the result of the plus operator applied to strings (i.e., a C +strings, an std::string, or a StringRef). The twine delays the +actual concatentation of strings until it is actually required, at which point +it can be efficiently rendered directly into a character array. This avoids +unnecessary heap allocation involved in constructing the temporary results of +string concatenation. See +"llvm/ADT/Twine.h" +for more information.

    + +

    As with a StringRef, Twine objects point to external memory +and should almost never be stored or mentioned directly. They are intended +solely for use when defining a function which should be able to efficiently +accept concatenated strings.

    + +
    + + + + + +
    + +

    Often when working on your pass you will put a bunch of debugging printouts +and other code into your pass. After you get it working, you want to remove +it, but you may need it again in the future (to work out new bugs that you run +across).

    + +

    Naturally, because of this, you don't want to delete the debug printouts, +but you don't want them to always be noisy. A standard compromise is to comment +them out, allowing you to enable them if you need them in the future.

    + +

    The "llvm/Support/Debug.h" +file provides a macro named DEBUG() that is a much nicer solution to +this problem. Basically, you can put arbitrary code into the argument of the +DEBUG macro, and it is only executed if 'opt' (or any other +tool) is run with the '-debug' command line argument:

    + +
    +
    +DEBUG(errs() << "I am here!\n");
    +
    +
    + +

    Then you can run your pass like this:

    + +
    +
    +$ opt < a.bc > /dev/null -mypass
    +<no output>
    +$ opt < a.bc > /dev/null -mypass -debug
    +I am here!
    +
    +
    + +

    Using the DEBUG() macro instead of a home-brewed solution allows you +to not have to create "yet another" command line option for the debug output for +your pass. Note that DEBUG() macros are disabled for optimized builds, +so they do not cause a performance impact at all (for the same reason, they +should also not contain side-effects!).

    + +

    One additional nice thing about the DEBUG() macro is that you can +enable or disable it directly in gdb. Just use "set DebugFlag=0" or +"set DebugFlag=1" from the gdb if the program is running. If the +program hasn't been started yet, you can always just run it with +-debug.

    + +
    + + + + +
    + +

    Sometimes you may find yourself in a situation where enabling -debug +just turns on too much information (such as when working on the code +generator). If you want to enable debug information with more fine-grained +control, you define the DEBUG_TYPE macro and the -debug only +option as follows:

    + +
    +
    +#undef  DEBUG_TYPE
    +DEBUG(errs() << "No debug type\n");
    +#define DEBUG_TYPE "foo"
    +DEBUG(errs() << "'foo' debug type\n");
    +#undef  DEBUG_TYPE
    +#define DEBUG_TYPE "bar"
    +DEBUG(errs() << "'bar' debug type\n"));
    +#undef  DEBUG_TYPE
    +#define DEBUG_TYPE ""
    +DEBUG(errs() << "No debug type (2)\n");
    +
    +
    + +

    Then you can run your pass like this:

    + +
    +
    +$ opt < a.bc > /dev/null -mypass
    +<no output>
    +$ opt < a.bc > /dev/null -mypass -debug
    +No debug type
    +'foo' debug type
    +'bar' debug type
    +No debug type (2)
    +$ opt < a.bc > /dev/null -mypass -debug-only=foo
    +'foo' debug type
    +$ opt < a.bc > /dev/null -mypass -debug-only=bar
    +'bar' debug type
    +
    +
    + +

    Of course, in practice, you should only set DEBUG_TYPE at the top of +a file, to specify the debug type for the entire module (if you do this before +you #include "llvm/Support/Debug.h", you don't have to insert the ugly +#undef's). Also, you should use names more meaningful than "foo" and +"bar", because there is no system in place to ensure that names do not +conflict. If two different modules use the same string, they will all be turned +on when the name is specified. This allows, for example, all debug information +for instruction scheduling to be enabled with -debug-type=InstrSched, +even if the source lives in multiple files.

    + +

    The DEBUG_WITH_TYPE macro is also available for situations where you +would like to set DEBUG_TYPE, but only for one specific DEBUG +statement. It takes an additional first parameter, which is the type to use. For +example, the preceding example could be written as:

    + + +
    +
    +DEBUG_WITH_TYPE("", errs() << "No debug type\n");
    +DEBUG_WITH_TYPE("foo", errs() << "'foo' debug type\n");
    +DEBUG_WITH_TYPE("bar", errs() << "'bar' debug type\n"));
    +DEBUG_WITH_TYPE("", errs() << "No debug type (2)\n");
    +
    +
    + +
    + + + + +
    + +

    The "llvm/ADT/Statistic.h" file +provides a class named Statistic that is used as a unified way to +keep track of what the LLVM compiler is doing and how effective various +optimizations are. It is useful to see what optimizations are contributing to +making a particular program run faster.

    + +

    Often you may run your pass on some big program, and you're interested to see +how many times it makes a certain transformation. Although you can do this with +hand inspection, or some ad-hoc method, this is a real pain and not very useful +for big programs. Using the Statistic class makes it very easy to +keep track of this information, and the calculated information is presented in a +uniform manner with the rest of the passes being executed.

    + +

    There are many examples of Statistic uses, but the basics of using +it are as follows:

    + +
      +
    1. Define your statistic like this:

      + +
      +
      +#define DEBUG_TYPE "mypassname"   // This goes before any #includes.
      +STATISTIC(NumXForms, "The # of times I did stuff");
      +
      +
      + +

      The STATISTIC macro defines a static variable, whose name is + specified by the first argument. The pass name is taken from the DEBUG_TYPE + macro, and the description is taken from the second argument. The variable + defined ("NumXForms" in this case) acts like an unsigned integer.

    2. + +
    3. Whenever you make a transformation, bump the counter:

      + +
      +
      +++NumXForms;   // I did stuff!
      +
      +
      + +
    4. +
    + +

    That's all you have to do. To get 'opt' to print out the + statistics gathered, use the '-stats' option:

    + +
    +
    +$ opt -stats -mypassname < program.bc > /dev/null
    +... statistics output ...
    +
    +
    + +

    When running opt on a C file from the SPEC benchmark +suite, it gives a report that looks like this:

    + +
    +
    +   7646 bitcodewriter   - Number of normal instructions
    +    725 bitcodewriter   - Number of oversized instructions
    + 129996 bitcodewriter   - Number of bitcode bytes written
    +   2817 raise           - Number of insts DCEd or constprop'd
    +   3213 raise           - Number of cast-of-self removed
    +   5046 raise           - Number of expression trees converted
    +     75 raise           - Number of other getelementptr's formed
    +    138 raise           - Number of load/store peepholes
    +     42 deadtypeelim    - Number of unused typenames removed from symtab
    +    392 funcresolve     - Number of varargs functions resolved
    +     27 globaldce       - Number of global variables removed
    +      2 adce            - Number of basic blocks removed
    +    134 cee             - Number of branches revectored
    +     49 cee             - Number of setcc instruction eliminated
    +    532 gcse            - Number of loads removed
    +   2919 gcse            - Number of instructions removed
    +     86 indvars         - Number of canonical indvars added
    +     87 indvars         - Number of aux indvars removed
    +     25 instcombine     - Number of dead inst eliminate
    +    434 instcombine     - Number of insts combined
    +    248 licm            - Number of load insts hoisted
    +   1298 licm            - Number of insts hoisted to a loop pre-header
    +      3 licm            - Number of insts hoisted to multiple loop preds (bad, no loop pre-header)
    +     75 mem2reg         - Number of alloca's promoted
    +   1444 cfgsimplify     - Number of blocks simplified
    +
    +
    + +

    Obviously, with so many optimizations, having a unified framework for this +stuff is very nice. Making your pass fit well into the framework makes it more +maintainable and useful.

    + +
    + + + + +
    + +

    Several of the important data structures in LLVM are graphs: for example +CFGs made out of LLVM BasicBlocks, CFGs made out of +LLVM MachineBasicBlocks, and +Instruction Selection +DAGs. In many cases, while debugging various parts of the compiler, it is +nice to instantly visualize these graphs.

    + +

    LLVM provides several callbacks that are available in a debug build to do +exactly that. If you call the Function::viewCFG() method, for example, +the current LLVM tool will pop up a window containing the CFG for the function +where each basic block is a node in the graph, and each node contains the +instructions in the block. Similarly, there also exists +Function::viewCFGOnly() (does not include the instructions), the +MachineFunction::viewCFG() and MachineFunction::viewCFGOnly(), +and the SelectionDAG::viewGraph() methods. Within GDB, for example, +you can usually use something like call DAG.viewGraph() to pop +up a window. Alternatively, you can sprinkle calls to these functions in your +code in places you want to debug.

    + +

    Getting this to work requires a small amount of configuration. On Unix +systems with X11, install the graphviz +toolkit, and make sure 'dot' and 'gv' are in your path. If you are running on +Mac OS/X, download and install the Mac OS/X Graphviz program, and add +/Applications/Graphviz.app/Contents/MacOS/ (or wherever you install +it) to your path. Once in your system and path are set up, rerun the LLVM +configure script and rebuild LLVM to enable this functionality.

    + +

    SelectionDAG has been extended to make it easier to locate +interesting nodes in large complex graphs. From gdb, if you +call DAG.setGraphColor(node, "color"), then the +next call DAG.viewGraph() would highlight the node in the +specified color (choices of colors can be found at colors.) More +complex node attributes can be provided with call +DAG.setGraphAttrs(node, "attributes") (choices can be +found at Graph +Attributes.) If you want to restart and clear all the current graph +attributes, then you can call DAG.clearGraphAttrs().

    + +
    + + + + + +
    + +

    LLVM has a plethora of data structures in the llvm/ADT/ directory, + and we commonly use STL data structures. This section describes the trade-offs + you should consider when you pick one.

    + +

    +The first step is a choose your own adventure: do you want a sequential +container, a set-like container, or a map-like container? The most important +thing when choosing a container is the algorithmic properties of how you plan to +access the container. Based on that, you should use:

    + +
      +
    • a map-like container if you need efficient look-up + of an value based on another value. Map-like containers also support + efficient queries for containment (whether a key is in the map). Map-like + containers generally do not support efficient reverse mapping (values to + keys). If you need that, use two maps. Some map-like containers also + support efficient iteration through the keys in sorted order. Map-like + containers are the most expensive sort, only use them if you need one of + these capabilities.
    • + +
    • a set-like container if you need to put a bunch of + stuff into a container that automatically eliminates duplicates. Some + set-like containers support efficient iteration through the elements in + sorted order. Set-like containers are more expensive than sequential + containers. +
    • + +
    • a sequential container provides + the most efficient way to add elements and keeps track of the order they are + added to the collection. They permit duplicates and support efficient + iteration, but do not support efficient look-up based on a key. +
    • + +
    • a string container is a specialized sequential + container or reference structure that is used for character or byte + arrays.
    • + +
    • a bit container provides an efficient way to store and + perform set operations on sets of numeric id's, while automatically + eliminating duplicates. Bit containers require a maximum of 1 bit for each + identifier you want to store. +
    • +
    + +

    +Once the proper category of container is determined, you can fine tune the +memory use, constant factors, and cache behaviors of access by intelligently +picking a member of the category. Note that constant factors and cache behavior +can be a big deal. If you have a vector that usually only contains a few +elements (but could contain many), for example, it's much better to use +SmallVector than vector +. Doing so avoids (relatively) expensive malloc/free calls, which dwarf the +cost of adding the elements to the container.

    + +
    + + + + +
    +There are a variety of sequential containers available for you, based on your +needs. Pick the first in this section that will do what you want. +
    + + + + +
    +

    Fixed size arrays are very simple and very fast. They are good if you know +exactly how many elements you have, or you have a (low) upper bound on how many +you have.

    +
    + + + + +
    +

    Heap allocated arrays (new[] + delete[]) are also simple. They are good if +the number of elements is variable, if you know how many elements you will need +before the array is allocated, and if the array is usually large (if not, +consider a SmallVector). The cost of a heap +allocated array is the cost of the new/delete (aka malloc/free). Also note that +if you are allocating an array of a type with a constructor, the constructor and +destructors will be run for every element in the array (re-sizable vectors only +construct those elements actually used).

    +
    + + + + +
    +

    SmallVector<Type, N> is a simple class that looks and smells +just like vector<Type>: +it supports efficient iteration, lays out elements in memory order (so you can +do pointer arithmetic between elements), supports efficient push_back/pop_back +operations, supports efficient random access to its elements, etc.

    + +

    The advantage of SmallVector is that it allocates space for +some number of elements (N) in the object itself. Because of this, if +the SmallVector is dynamically smaller than N, no malloc is performed. This can +be a big win in cases where the malloc/free call is far more expensive than the +code that fiddles around with the elements.

    + +

    This is good for vectors that are "usually small" (e.g. the number of +predecessors/successors of a block is usually less than 8). On the other hand, +this makes the size of the SmallVector itself large, so you don't want to +allocate lots of them (doing so will waste a lot of space). As such, +SmallVectors are most useful when on the stack.

    + +

    SmallVector also provides a nice portable and efficient replacement for +alloca.

    + +
    + + + + +
    +

    +std::vector is well loved and respected. It is useful when SmallVector isn't: +when the size of the vector is often large (thus the small optimization will +rarely be a benefit) or if you will be allocating many instances of the vector +itself (which would waste space for elements that aren't in the container). +vector is also useful when interfacing with code that expects vectors :). +

    + +

    One worthwhile note about std::vector: avoid code like this:

    + +
    +
    +for ( ... ) {
    +   std::vector<foo> V;
    +   use V;
    +}
    +
    +
    + +

    Instead, write this as:

    + +
    +
    +std::vector<foo> V;
    +for ( ... ) {
    +   use V;
    +   V.clear();
    +}
    +
    +
    + +

    Doing so will save (at least) one heap allocation and free per iteration of +the loop.

    + +
    + + +
    + <deque> +
    + +
    +

    std::deque is, in some senses, a generalized version of std::vector. Like +std::vector, it provides constant time random access and other similar +properties, but it also provides efficient access to the front of the list. It +does not guarantee continuity of elements within memory.

    + +

    In exchange for this extra flexibility, std::deque has significantly higher +constant factor costs than std::vector. If possible, use std::vector or +something cheaper.

    +
    + + +
    + <list> +
    + +
    +

    std::list is an extremely inefficient class that is rarely useful. +It performs a heap allocation for every element inserted into it, thus having an +extremely high constant factor, particularly for small data types. std::list +also only supports bidirectional iteration, not random access iteration.

    + +

    In exchange for this high cost, std::list supports efficient access to both +ends of the list (like std::deque, but unlike std::vector or SmallVector). In +addition, the iterator invalidation characteristics of std::list are stronger +than that of a vector class: inserting or removing an element into the list does +not invalidate iterator or pointers to other elements in the list.

    +
    + + + + +
    +

    ilist<T> implements an 'intrusive' doubly-linked list. It is +intrusive, because it requires the element to store and provide access to the +prev/next pointers for the list.

    + +

    ilist has the same drawbacks as std::list, and additionally +requires an ilist_traits implementation for the element type, but it +provides some novel characteristics. In particular, it can efficiently store +polymorphic objects, the traits class is informed when an element is inserted or +removed from the list, and ilists are guaranteed to support a +constant-time splice operation.

    + +

    These properties are exactly what we want for things like +Instructions and basic blocks, which is why these are implemented with +ilists.

    + +Related classes of interest are explained in the following subsections: + +
    + + + + +
    +

    ilist_traits<T> is ilist<T>'s customization +mechanism. iplist<T> (and consequently ilist<T>) +publicly derive from this traits class.

    +
    + + +
    + iplist +
    + +
    +

    iplist<T> is ilist<T>'s base and as such +supports a slightly narrower interface. Notably, inserters from +T& are absent.

    + +

    ilist_traits<T> is a public base of this class and can be +used for a wide variety of customizations.

    +
    + + + + +
    +

    ilist_node<T> implements a the forward and backward links +that are expected by the ilist<T> (and analogous containers) +in the default manner.

    + +

    ilist_node<T>s are meant to be embedded in the node type +T, usually T publicly derives from +ilist_node<T>.

    +
    + + + + +
    +

    ilists have another speciality that must be considered. To be a good +citizen in the C++ ecosystem, it needs to support the standard container +operations, such as begin and end iterators, etc. Also, the +operator-- must work correctly on the end iterator in the +case of non-empty ilists.

    + +

    The only sensible solution to this problem is to allocate a so-called +sentinel along with the intrusive list, which serves as the end +iterator, providing the back-link to the last element. However conforming to the +C++ convention it is illegal to operator++ beyond the sentinel and it +also must not be dereferenced.

    + +

    These constraints allow for some implementation freedom to the ilist +how to allocate and store the sentinel. The corresponding policy is dictated +by ilist_traits<T>. By default a T gets heap-allocated +whenever the need for a sentinel arises.

    + +

    While the default policy is sufficient in most cases, it may break down when +T does not provide a default constructor. Also, in the case of many +instances of ilists, the memory overhead of the associated sentinels +is wasted. To alleviate the situation with numerous and voluminous +T-sentinels, sometimes a trick is employed, leading to ghostly +sentinels.

    + +

    Ghostly sentinels are obtained by specially-crafted ilist_traits<T> +which superpose the sentinel with the ilist instance in memory. Pointer +arithmetic is used to obtain the sentinel, which is relative to the +ilist's this pointer. The ilist is augmented by an +extra pointer, which serves as the back-link of the sentinel. This is the only +field in the ghostly sentinel which can be legally accessed.

    +
    + + + + +
    +

    Other STL containers are available, such as std::string.

    + +

    There are also various STL adapter classes such as std::queue, +std::priority_queue, std::stack, etc. These provide simplified access to an +underlying container but don't affect the cost of the container itself.

    + +
    + + + + + +
    + +

    Set-like containers are useful when you need to canonicalize multiple values +into a single representation. There are several different choices for how to do +this, providing various trade-offs.

    + +
    + + + + + +
    + +

    If you intend to insert a lot of elements, then do a lot of queries, a +great approach is to use a vector (or other sequential container) with +std::sort+std::unique to remove duplicates. This approach works really well if +your usage pattern has these two distinct phases (insert then query), and can be +coupled with a good choice of sequential container. +

    + +

    +This combination provides the several nice properties: the result data is +contiguous in memory (good for cache locality), has few allocations, is easy to +address (iterators in the final vector are just indices or pointers), and can be +efficiently queried with a standard binary or radix search.

    + +
    + + + + +
    + +

    If you have a set-like data structure that is usually small and whose elements +are reasonably small, a SmallSet<Type, N> is a good choice. This set +has space for N elements in place (thus, if the set is dynamically smaller than +N, no malloc traffic is required) and accesses them with a simple linear search. +When the set grows beyond 'N' elements, it allocates a more expensive representation that +guarantees efficient access (for most types, it falls back to std::set, but for +pointers it uses something far better, SmallPtrSet).

    + +

    The magic of this class is that it handles small sets extremely efficiently, +but gracefully handles extremely large sets without loss of efficiency. The +drawback is that the interface is quite small: it supports insertion, queries +and erasing, but does not support iteration.

    + +
    + + + + +
    + +

    SmallPtrSet has all the advantages of SmallSet (and a SmallSet of pointers is +transparently implemented with a SmallPtrSet), but also supports iterators. If +more than 'N' insertions are performed, a single quadratically +probed hash table is allocated and grows as needed, providing extremely +efficient access (constant time insertion/deleting/queries with low constant +factors) and is very stingy with malloc traffic.

    + +

    Note that, unlike std::set, the iterators of SmallPtrSet are invalidated +whenever an insertion occurs. Also, the values visited by the iterators are not +visited in sorted order.

    + +
    + + + + +
    + +

    +DenseSet is a simple quadratically probed hash table. It excels at supporting +small values: it uses a single allocation to hold all of the pairs that +are currently inserted in the set. DenseSet is a great way to unique small +values that are not simple pointers (use SmallPtrSet for pointers). Note that DenseSet has +the same requirements for the value type that DenseMap has. +

    + +
    + + + + +
    + +

    +FoldingSet is an aggregate class that is really good at uniquing +expensive-to-create or polymorphic objects. It is a combination of a chained +hash table with intrusive links (uniqued objects are required to inherit from +FoldingSetNode) that uses SmallVector as part of +its ID process.

    + +

    Consider a case where you want to implement a "getOrCreateFoo" method for +a complex object (for example, a node in the code generator). The client has a +description of *what* it wants to generate (it knows the opcode and all the +operands), but we don't want to 'new' a node, then try inserting it into a set +only to find out it already exists, at which point we would have to delete it +and return the node that already exists. +

    + +

    To support this style of client, FoldingSet perform a query with a +FoldingSetNodeID (which wraps SmallVector) that can be used to describe the +element that we want to query for. The query either returns the element +matching the ID or it returns an opaque ID that indicates where insertion should +take place. Construction of the ID usually does not require heap traffic.

    + +

    Because FoldingSet uses intrusive links, it can support polymorphic objects +in the set (for example, you can have SDNode instances mixed with LoadSDNodes). +Because the elements are individually allocated, pointers to the elements are +stable: inserting or removing elements does not invalidate any pointers to other +elements. +

    + +
    + + +
    + <set> +
    + +
    + +

    std::set is a reasonable all-around set class, which is decent at +many things but great at nothing. std::set allocates memory for each element +inserted (thus it is very malloc intensive) and typically stores three pointers +per element in the set (thus adding a large amount of per-element space +overhead). It offers guaranteed log(n) performance, which is not particularly +fast from a complexity standpoint (particularly if the elements of the set are +expensive to compare, like strings), and has extremely high constant factors for +lookup, insertion and removal.

    + +

    The advantages of std::set are that its iterators are stable (deleting or +inserting an element from the set does not affect iterators or pointers to other +elements) and that iteration over the set is guaranteed to be in sorted order. +If the elements in the set are large, then the relative overhead of the pointers +and malloc traffic is not a big deal, but if the elements of the set are small, +std::set is almost never a good choice.

    + +
    + + + + +
    +

    LLVM's SetVector<Type> is an adapter class that combines your choice of +a set-like container along with a Sequential +Container. The important property +that this provides is efficient insertion with uniquing (duplicate elements are +ignored) with iteration support. It implements this by inserting elements into +both a set-like container and the sequential container, using the set-like +container for uniquing and the sequential container for iteration. +

    + +

    The difference between SetVector and other sets is that the order of +iteration is guaranteed to match the order of insertion into the SetVector. +This property is really important for things like sets of pointers. Because +pointer values are non-deterministic (e.g. vary across runs of the program on +different machines), iterating over the pointers in the set will +not be in a well-defined order.

    + +

    +The drawback of SetVector is that it requires twice as much space as a normal +set and has the sum of constant factors from the set-like container and the +sequential container that it uses. Use it *only* if you need to iterate over +the elements in a deterministic order. SetVector is also expensive to delete +elements out of (linear time), unless you use it's "pop_back" method, which is +faster. +

    + +

    SetVector is an adapter class that defaults to using std::vector and std::set +for the underlying containers, so it is quite expensive. However, +"llvm/ADT/SetVector.h" also provides a SmallSetVector class, which +defaults to using a SmallVector and SmallSet of a specified size. If you use +this, and if your sets are dynamically smaller than N, you will save a lot of +heap traffic.

    + +
    + + + + +
    + +

    +UniqueVector is similar to SetVector, but it +retains a unique ID for each element inserted into the set. It internally +contains a map and a vector, and it assigns a unique ID for each value inserted +into the set.

    + +

    UniqueVector is very expensive: its cost is the sum of the cost of +maintaining both the map and vector, it has high complexity, high constant +factors, and produces a lot of malloc traffic. It should be avoided.

    + +
    + + + + + +
    + +

    +The STL provides several other options, such as std::multiset and the various +"hash_set" like containers (whether from C++ TR1 or from the SGI library). We +never use hash_set and unordered_set because they are generally very expensive +(each insertion requires a malloc) and very non-portable. +

    + +

    std::multiset is useful if you're not interested in elimination of +duplicates, but has all the drawbacks of std::set. A sorted vector (where you +don't delete duplicate entries) or some other approach is almost always +better.

    + +
    + + + + +
    +Map-like containers are useful when you want to associate data to a key. As +usual, there are a lot of different ways to do this. :) +
    + + + + +
    + +

    +If your usage pattern follows a strict insert-then-query approach, you can +trivially use the same approach as sorted vectors +for set-like containers. The only difference is that your query function +(which uses std::lower_bound to get efficient log(n) lookup) should only compare +the key, not both the key and value. This yields the same advantages as sorted +vectors for sets. +

    +
    + + + + +
    + +

    +Strings are commonly used as keys in maps, and they are difficult to support +efficiently: they are variable length, inefficient to hash and compare when +long, expensive to copy, etc. StringMap is a specialized container designed to +cope with these issues. It supports mapping an arbitrary range of bytes to an +arbitrary other object.

    + +

    The StringMap implementation uses a quadratically-probed hash table, where +the buckets store a pointer to the heap allocated entries (and some other +stuff). The entries in the map must be heap allocated because the strings are +variable length. The string data (key) and the element object (value) are +stored in the same allocation with the string data immediately after the element +object. This container guarantees the "(char*)(&Value+1)" points +to the key string for a value.

    + +

    The StringMap is very fast for several reasons: quadratic probing is very +cache efficient for lookups, the hash value of strings in buckets is not +recomputed when lookup up an element, StringMap rarely has to touch the +memory for unrelated objects when looking up a value (even when hash collisions +happen), hash table growth does not recompute the hash values for strings +already in the table, and each pair in the map is store in a single allocation +(the string data is stored in the same allocation as the Value of a pair).

    + +

    StringMap also provides query methods that take byte ranges, so it only ever +copies a string if a value is inserted into the table.

    +
    + + + + +
    +

    +IndexedMap is a specialized container for mapping small dense integers (or +values that can be mapped to small dense integers) to some other type. It is +internally implemented as a vector with a mapping function that maps the keys to +the dense integer range. +

    + +

    +This is useful for cases like virtual registers in the LLVM code generator: they +have a dense mapping that is offset by a compile-time constant (the first +virtual register ID).

    + +
    + + + + +
    + +

    +DenseMap is a simple quadratically probed hash table. It excels at supporting +small keys and values: it uses a single allocation to hold all of the pairs that +are currently inserted in the map. DenseMap is a great way to map pointers to +pointers, or map other small types to each other. +

    + +

    +There are several aspects of DenseMap that you should be aware of, however. The +iterators in a densemap are invalidated whenever an insertion occurs, unlike +map. Also, because DenseMap allocates space for a large number of key/value +pairs (it starts with 64 by default), it will waste a lot of space if your keys +or values are large. Finally, you must implement a partial specialization of +DenseMapInfo for the key that you want, if it isn't already supported. This +is required to tell DenseMap about two special marker values (which can never be +inserted into the map) that it needs internally.

    + +
    + + + + +
    + +

    +ValueMap is a wrapper around a DenseMap mapping +Value*s (or subclasses) to another type. When a Value is deleted or RAUW'ed, +ValueMap will update itself so the new version of the key is mapped to the same +value, just as if the key were a WeakVH. You can configure exactly how this +happens, and what else happens on these two events, by passing +a Config parameter to the ValueMap template.

    + +
    + + +
    + <map> +
    + +
    + +

    +std::map has similar characteristics to std::set: it uses +a single allocation per pair inserted into the map, it offers log(n) lookup with +an extremely large constant factor, imposes a space penalty of 3 pointers per +pair in the map, etc.

    + +

    std::map is most useful when your keys or values are very large, if you need +to iterate over the collection in sorted order, or if you need stable iterators +into the map (i.e. they don't get invalidated if an insertion or deletion of +another element takes place).

    + +
    + + + + +
    + +

    +The STL provides several other options, such as std::multimap and the various +"hash_map" like containers (whether from C++ TR1 or from the SGI library). We +never use hash_set and unordered_set because they are generally very expensive +(each insertion requires a malloc) and very non-portable.

    + +

    std::multimap is useful if you want to map a key to multiple values, but has +all the drawbacks of std::map. A sorted vector or some other approach is almost +always better.

    + +
    + + + + +
    + +

    +TODO: const char* vs stringref vs smallstring vs std::string. Describe twine, +xref to #string_apis. +

    + +
    + + + + +
    +

    Unlike the other containers, there are only two bit storage containers, and +choosing when to use each is relatively straightforward.

    + +

    One additional option is +std::vector<bool>: we discourage its use for two reasons 1) the +implementation in many common compilers (e.g. commonly available versions of +GCC) is extremely inefficient and 2) the C++ standards committee is likely to +deprecate this container and/or change it significantly somehow. In any case, +please don't use it.

    +
    + + + + +
    +

    The BitVector container provides a fixed size set of bits for manipulation. +It supports individual bit setting/testing, as well as set operations. The set +operations take time O(size of bitvector), but operations are performed one word +at a time, instead of one bit at a time. This makes the BitVector very fast for +set operations compared to other containers. Use the BitVector when you expect +the number of set bits to be high (IE a dense set). +

    +
    + + + + +
    +

    The SparseBitVector container is much like BitVector, with one major +difference: Only the bits that are set, are stored. This makes the +SparseBitVector much more space efficient than BitVector when the set is sparse, +as well as making set operations O(number of set bits) instead of O(size of +universe). The downside to the SparseBitVector is that setting and testing of random bits is O(N), and on large SparseBitVectors, this can be slower than BitVector. In our implementation, setting or testing bits in sorted order +(either forwards or reverse) is O(1) worst case. Testing and setting bits within 128 bits (depends on size) of the current bit is also O(1). As a general statement, testing/setting bits in a SparseBitVector is O(distance away from last set bit). +

    +
    + + + + + +
    + +

    This section describes how to perform some very simple transformations of +LLVM code. This is meant to give examples of common idioms used, showing the +practical side of LLVM transformations.

    Because this is a "how-to" section, +you should also read about the main classes that you will be working with. The +Core LLVM Class Hierarchy Reference contains details +and descriptions of the main classes that you should know about.

    + +
    + + + + + +
    + +

    The LLVM compiler infrastructure have many different data structures that may +be traversed. Following the example of the C++ standard template library, the +techniques used to traverse these various data structures are all basically the +same. For a enumerable sequence of values, the XXXbegin() function (or +method) returns an iterator to the start of the sequence, the XXXend() +function returns an iterator pointing to one past the last valid element of the +sequence, and there is some XXXiterator data type that is common +between the two operations.

    + +

    Because the pattern for iteration is common across many different aspects of +the program representation, the standard template library algorithms may be used +on them, and it is easier to remember how to iterate. First we show a few common +examples of the data structures that need to be traversed. Other data +structures are traversed in very similar ways.

    + +
    + + + + +
    + +

    It's quite common to have a Function instance that you'd like to +transform in some way; in particular, you'd like to manipulate its +BasicBlocks. To facilitate this, you'll need to iterate over all of +the BasicBlocks that constitute the Function. The following is +an example that prints the name of a BasicBlock and the number of +Instructions it contains:

    + +
    +
    +// func is a pointer to a Function instance
    +for (Function::iterator i = func->begin(), e = func->end(); i != e; ++i)
    +  // Print out the name of the basic block if it has one, and then the
    +  // number of instructions that it contains
    +  errs() << "Basic block (name=" << i->getName() << ") has "
    +             << i->size() << " instructions.\n";
    +
    +
    + +

    Note that i can be used as if it were a pointer for the purposes of +invoking member functions of the Instruction class. This is +because the indirection operator is overloaded for the iterator +classes. In the above code, the expression i->size() is +exactly equivalent to (*i).size() just like you'd expect.

    + +
    + + + + +
    + +

    Just like when dealing with BasicBlocks in Functions, it's +easy to iterate over the individual instructions that make up +BasicBlocks. Here's a code snippet that prints out each instruction in +a BasicBlock:

    + +
    +
    +// blk is a pointer to a BasicBlock instance
    +for (BasicBlock::iterator i = blk->begin(), e = blk->end(); i != e; ++i)
    +   // The next statement works since operator<<(ostream&,...)
    +   // is overloaded for Instruction&
    +   errs() << *i << "\n";
    +
    +
    + +

    However, this isn't really the best way to print out the contents of a +BasicBlock! Since the ostream operators are overloaded for virtually +anything you'll care about, you could have just invoked the print routine on the +basic block itself: errs() << *blk << "\n";.

    + +
    + + + + +
    + +

    If you're finding that you commonly iterate over a Function's +BasicBlocks and then that BasicBlock's Instructions, +InstIterator should be used instead. You'll need to include llvm/Support/InstIterator.h, +and then instantiate InstIterators explicitly in your code. Here's a +small example that shows how to dump all instructions in a function to the standard error stream:

    + +

    +
    +#include "llvm/Support/InstIterator.h"
    +
    +// F is a pointer to a Function instance
    +for (inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I)
    +  errs() << *I << "\n";
    +
    +
    + +

    Easy, isn't it? You can also use InstIterators to fill a +work list with its initial contents. For example, if you wanted to +initialize a work list to contain all instructions in a Function +F, all you would need to do is something like:

    + +
    +
    +std::set<Instruction*> worklist;
    +// or better yet, SmallPtrSet<Instruction*, 64> worklist;
    +
    +for (inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I)
    +   worklist.insert(&*I);
    +
    +
    + +

    The STL set worklist would now contain all instructions in the +Function pointed to by F.

    + +
    + + + + +
    + +

    Sometimes, it'll be useful to grab a reference (or pointer) to a class +instance when all you've got at hand is an iterator. Well, extracting +a reference or a pointer from an iterator is very straight-forward. +Assuming that i is a BasicBlock::iterator and j +is a BasicBlock::const_iterator:

    + +
    +
    +Instruction& inst = *i;   // Grab reference to instruction reference
    +Instruction* pinst = &*i; // Grab pointer to instruction reference
    +const Instruction& inst = *j;
    +
    +
    + +

    However, the iterators you'll be working with in the LLVM framework are +special: they will automatically convert to a ptr-to-instance type whenever they +need to. Instead of dereferencing the iterator and then taking the address of +the result, you can simply assign the iterator to the proper pointer type and +you get the dereference and address-of operation as a result of the assignment +(behind the scenes, this is a result of overloading casting mechanisms). Thus +the last line of the last example,

    + +
    +
    +Instruction *pinst = &*i;
    +
    +
    + +

    is semantically equivalent to

    + +
    +
    +Instruction *pinst = i;
    +
    +
    + +

    It's also possible to turn a class pointer into the corresponding iterator, +and this is a constant time operation (very efficient). The following code +snippet illustrates use of the conversion constructors provided by LLVM +iterators. By using these, you can explicitly grab the iterator of something +without actually obtaining it via iteration over some structure:

    + +
    +
    +void printNextInstruction(Instruction* inst) {
    +  BasicBlock::iterator it(inst);
    +  ++it; // After this line, it refers to the instruction after *inst
    +  if (it != inst->getParent()->end()) errs() << *it << "\n";
    +}
    +
    +
    + +
    + + + + +
    + +

    Say that you're writing a FunctionPass and would like to count all the +locations in the entire module (that is, across every Function) where a +certain function (i.e., some Function*) is already in scope. As you'll +learn later, you may want to use an InstVisitor to accomplish this in a +much more straight-forward manner, but this example will allow us to explore how +you'd do it if you didn't have InstVisitor around. In pseudo-code, this +is what we want to do:

    + +
    +
    +initialize callCounter to zero
    +for each Function f in the Module
    +  for each BasicBlock b in f
    +    for each Instruction i in b
    +      if (i is a CallInst and calls the given function)
    +        increment callCounter
    +
    +
    + +

    And the actual code is (remember, because we're writing a +FunctionPass, our FunctionPass-derived class simply has to +override the runOnFunction method):

    + +
    +
    +Function* targetFunc = ...;
    +
    +class OurFunctionPass : public FunctionPass {
    +  public:
    +    OurFunctionPass(): callCounter(0) { }
    +
    +    virtual runOnFunction(Function& F) {
    +      for (Function::iterator b = F.begin(), be = F.end(); b != be; ++b) {
    +        for (BasicBlock::iterator i = b->begin(), ie = b->end(); i != ie; ++i) {
    +          if (CallInst* callInst = dyn_cast<CallInst>(&*i)) {
    +            // We know we've encountered a call instruction, so we
    +            // need to determine if it's a call to the
    +            // function pointed to by m_func or not.
    +            if (callInst->getCalledFunction() == targetFunc)
    +              ++callCounter;
    +          }
    +        }
    +      }
    +    }
    +
    +  private:
    +    unsigned callCounter;
    +};
    +
    +
    + +
    + + + + +
    + +

    You may have noticed that the previous example was a bit oversimplified in +that it did not deal with call sites generated by 'invoke' instructions. In +this, and in other situations, you may find that you want to treat +CallInsts and InvokeInsts the same way, even though their +most-specific common base class is Instruction, which includes lots of +less closely-related things. For these cases, LLVM provides a handy wrapper +class called CallSite. +It is essentially a wrapper around an Instruction pointer, with some +methods that provide functionality common to CallInsts and +InvokeInsts.

    + +

    This class has "value semantics": it should be passed by value, not by +reference and it should not be dynamically allocated or deallocated using +operator new or operator delete. It is efficiently copyable, +assignable and constructable, with costs equivalents to that of a bare pointer. +If you look at its definition, it has only a single pointer member.

    + +
    + + + + +
    + +

    Frequently, we might have an instance of the Value Class and we want to +determine which Users use the Value. The list of all +Users of a particular Value is called a def-use chain. +For example, let's say we have a Function* named F to a +particular function foo. Finding all of the instructions that +use foo is as simple as iterating over the def-use chain +of F:

    + +
    +
    +Function *F = ...;
    +
    +for (Value::use_iterator i = F->use_begin(), e = F->use_end(); i != e; ++i)
    +  if (Instruction *Inst = dyn_cast<Instruction>(*i)) {
    +    errs() << "F is used in instruction:\n";
    +    errs() << *Inst << "\n";
    +  }
    +
    +
    + +

    Alternately, it's common to have an instance of the User Class and need to know what +Values are used by it. The list of all Values used by a +User is known as a use-def chain. Instances of class +Instruction are common Users, so we might want to iterate over +all of the values that a particular instruction uses (that is, the operands of +the particular Instruction):

    + +
    +
    +Instruction *pi = ...;
    +
    +for (User::op_iterator i = pi->op_begin(), e = pi->op_end(); i != e; ++i) {
    +  Value *v = *i;
    +  // ...
    +}
    +
    +
    + + + +
    + + + + +
    + +

    Iterating over the predecessors and successors of a block is quite easy +with the routines defined in "llvm/Support/CFG.h". Just use code like +this to iterate over all predecessors of BB:

    + +
    +
    +#include "llvm/Support/CFG.h"
    +BasicBlock *BB = ...;
    +
    +for (pred_iterator PI = pred_begin(BB), E = pred_end(BB); PI != E; ++PI) {
    +  BasicBlock *Pred = *PI;
    +  // ...
    +}
    +
    +
    + +

    Similarly, to iterate over successors use +succ_iterator/succ_begin/succ_end.

    + +
    + + + + + +
    + +

    There are some primitive transformation operations present in the LLVM +infrastructure that are worth knowing about. When performing +transformations, it's fairly common to manipulate the contents of basic +blocks. This section describes some of the common methods for doing so +and gives example code.

    + +
    + + + + +
    + +

    Instantiating Instructions

    + +

    Creation of Instructions is straight-forward: simply call the +constructor for the kind of instruction to instantiate and provide the necessary +parameters. For example, an AllocaInst only requires a +(const-ptr-to) Type. Thus:

    + +
    +
    +AllocaInst* ai = new AllocaInst(Type::Int32Ty);
    +
    +
    + +

    will create an AllocaInst instance that represents the allocation of +one integer in the current stack frame, at run time. Each Instruction +subclass is likely to have varying default parameters which change the semantics +of the instruction, so refer to the doxygen documentation for the subclass of +Instruction that you're interested in instantiating.

    + +

    Naming values

    + +

    It is very useful to name the values of instructions when you're able to, as +this facilitates the debugging of your transformations. If you end up looking +at generated LLVM machine code, you definitely want to have logical names +associated with the results of instructions! By supplying a value for the +Name (default) parameter of the Instruction constructor, you +associate a logical name with the result of the instruction's execution at +run time. For example, say that I'm writing a transformation that dynamically +allocates space for an integer on the stack, and that integer is going to be +used as some kind of index by some other code. To accomplish this, I place an +AllocaInst at the first point in the first BasicBlock of some +Function, and I'm intending to use it within the same +Function. I might do:

    + +
    +
    +AllocaInst* pa = new AllocaInst(Type::Int32Ty, 0, "indexLoc");
    +
    +
    + +

    where indexLoc is now the logical name of the instruction's +execution value, which is a pointer to an integer on the run time stack.

    + +

    Inserting instructions

    + +

    There are essentially two ways to insert an Instruction +into an existing sequence of instructions that form a BasicBlock:

    + +
      +
    • Insertion into an explicit instruction list + +

      Given a BasicBlock* pb, an Instruction* pi within that + BasicBlock, and a newly-created instruction we wish to insert + before *pi, we do the following:

      + +
      +
      +BasicBlock *pb = ...;
      +Instruction *pi = ...;
      +Instruction *newInst = new Instruction(...);
      +
      +pb->getInstList().insert(pi, newInst); // Inserts newInst before pi in pb
      +
      +
      + +

      Appending to the end of a BasicBlock is so common that + the Instruction class and Instruction-derived + classes provide constructors which take a pointer to a + BasicBlock to be appended to. For example code that + looked like:

      + +
      +
      +BasicBlock *pb = ...;
      +Instruction *newInst = new Instruction(...);
      +
      +pb->getInstList().push_back(newInst); // Appends newInst to pb
      +
      +
      + +

      becomes:

      + +
      +
      +BasicBlock *pb = ...;
      +Instruction *newInst = new Instruction(..., pb);
      +
      +
      + +

      which is much cleaner, especially if you are creating + long instruction streams.

    • + +
    • Insertion into an implicit instruction list + +

      Instruction instances that are already in BasicBlocks + are implicitly associated with an existing instruction list: the instruction + list of the enclosing basic block. Thus, we could have accomplished the same + thing as the above code without being given a BasicBlock by doing: +

      + +
      +
      +Instruction *pi = ...;
      +Instruction *newInst = new Instruction(...);
      +
      +pi->getParent()->getInstList().insert(pi, newInst);
      +
      +
      + +

      In fact, this sequence of steps occurs so frequently that the + Instruction class and Instruction-derived classes provide + constructors which take (as a default parameter) a pointer to an + Instruction which the newly-created Instruction should + precede. That is, Instruction constructors are capable of + inserting the newly-created instance into the BasicBlock of a + provided instruction, immediately before that instruction. Using an + Instruction constructor with a insertBefore (default) + parameter, the above code becomes:

      + +
      +
      +Instruction* pi = ...;
      +Instruction* newInst = new Instruction(..., pi);
      +
      +
      + +

      which is much cleaner, especially if you're creating a lot of + instructions and adding them to BasicBlocks.

    • +
    + +
    + + + + +
    + +

    Deleting an instruction from an existing sequence of instructions that form a +BasicBlock is very straight-forward. First, +you must have a pointer to the instruction that you wish to delete. Second, you +need to obtain the pointer to that instruction's basic block. You use the +pointer to the basic block to get its list of instructions and then use the +erase function to remove your instruction. For example:

    + +
    +
    +Instruction *I = .. ;
    +I->eraseFromParent();
    +
    +
    + +
    + + + + +
    + +

    Replacing individual instructions

    + +

    Including "llvm/Transforms/Utils/BasicBlockUtils.h" +permits use of two very useful replace functions: ReplaceInstWithValue +and ReplaceInstWithInst.

    + +

    Deleting Instructions

    + +
      +
    • ReplaceInstWithValue + +

      This function replaces all uses of a given instruction with a value, + and then removes the original instruction. The following example + illustrates the replacement of the result of a particular + AllocaInst that allocates memory for a single integer with a null + pointer to an integer.

      + +
      +
      +AllocaInst* instToReplace = ...;
      +BasicBlock::iterator ii(instToReplace);
      +
      +ReplaceInstWithValue(instToReplace->getParent()->getInstList(), ii,
      +                     Constant::getNullValue(PointerType::getUnqual(Type::Int32Ty)));
      +
    • + +
    • ReplaceInstWithInst + +

      This function replaces a particular instruction with another + instruction, inserting the new instruction into the basic block at the + location where the old instruction was, and replacing any uses of the old + instruction with the new instruction. The following example illustrates + the replacement of one AllocaInst with another.

      + +
      +
      +AllocaInst* instToReplace = ...;
      +BasicBlock::iterator ii(instToReplace);
      +
      +ReplaceInstWithInst(instToReplace->getParent()->getInstList(), ii,
      +                    new AllocaInst(Type::Int32Ty, 0, "ptrToReplacedInt"));
      +
    • +
    + +

    Replacing multiple uses of Users and Values

    + +

    You can use Value::replaceAllUsesWith and +User::replaceUsesOfWith to change more than one use at a time. See the +doxygen documentation for the Value Class +and User Class, respectively, for more +information.

    + + + +
    + + + + +
    + +

    Deleting a global variable from a module is just as easy as deleting an +Instruction. First, you must have a pointer to the global variable that you wish + to delete. You use this pointer to erase it from its parent, the module. + For example:

    + +
    +
    +GlobalVariable *GV = .. ;
    +
    +GV->eraseFromParent();
    +
    +
    + +
    + + + + +
    + +

    In generating IR, you may need some complex types. If you know these types +statically, you can use TypeBuilder<...>::get(), defined +in llvm/Support/TypeBuilder.h, to retrieve them. TypeBuilder +has two forms depending on whether you're building types for cross-compilation +or native library use. TypeBuilder<T, true> requires +that T be independent of the host environment, meaning that it's built +out of types from +the llvm::types +namespace and pointers, functions, arrays, etc. built of +those. TypeBuilder<T, false> additionally allows native C types +whose size may depend on the host compiler. For example,

    + +
    +
    +FunctionType *ft = TypeBuilder<types::i<8>(types::i<32>*), true>::get();
    +
    +
    + +

    is easier to read and write than the equivalent

    + +
    +
    +std::vector<const Type*> params;
    +params.push_back(PointerType::getUnqual(Type::Int32Ty));
    +FunctionType *ft = FunctionType::get(Type::Int8Ty, params, false);
    +
    +
    + +

    See the class +comment for more details.

    + +
    + + + + + +
    +

    +This section describes the interaction of the LLVM APIs with multithreading, +both on the part of client applications, and in the JIT, in the hosted +application. +

    + +

    +Note that LLVM's support for multithreading is still relatively young. Up +through version 2.5, the execution of threaded hosted applications was +supported, but not threaded client access to the APIs. While this use case is +now supported, clients must adhere to the guidelines specified below to +ensure proper operation in multithreaded mode. +

    + +

    +Note that, on Unix-like platforms, LLVM requires the presence of GCC's atomic +intrinsics in order to support threaded operation. If you need a +multhreading-capable LLVM on a platform without a suitably modern system +compiler, consider compiling LLVM and LLVM-GCC in single-threaded mode, and +using the resultant compiler to build a copy of LLVM with multithreading +support. +

    +
    + + + + +
    + +

    +In order to properly protect its internal data structures while avoiding +excessive locking overhead in the single-threaded case, the LLVM must intialize +certain data structures necessary to provide guards around its internals. To do +so, the client program must invoke llvm_start_multithreaded() before +making any concurrent LLVM API calls. To subsequently tear down these +structures, use the llvm_stop_multithreaded() call. You can also use +the llvm_is_multithreaded() call to check the status of multithreaded +mode. +

    + +

    +Note that both of these calls must be made in isolation. That is to +say that no other LLVM API calls may be executing at any time during the +execution of llvm_start_multithreaded() or llvm_stop_multithreaded +. It's is the client's responsibility to enforce this isolation. +

    + +

    +The return value of llvm_start_multithreaded() indicates the success or +failure of the initialization. Failure typically indicates that your copy of +LLVM was built without multithreading support, typically because GCC atomic +intrinsics were not found in your system compiler. In this case, the LLVM API +will not be safe for concurrent calls. However, it will be safe for +hosting threaded applications in the JIT, though care must be taken to ensure +that side exits and the like do not accidentally result in concurrent LLVM API +calls. +

    +
    + + + + +
    +

    +When you are done using the LLVM APIs, you should call llvm_shutdown() +to deallocate memory used for internal structures. This will also invoke +llvm_stop_multithreaded() if LLVM is operating in multithreaded mode. +As such, llvm_shutdown() requires the same isolation guarantees as +llvm_stop_multithreaded(). +

    + +

    +Note that, if you use scope-based shutdown, you can use the +llvm_shutdown_obj class, which calls llvm_shutdown() in its +destructor. +

    + + + + +
    +

    +ManagedStatic is a utility class in LLVM used to implement static +initialization of static resources, such as the global type tables. Before the +invocation of llvm_shutdown(), it implements a simple lazy +initialization scheme. Once llvm_start_multithreaded() returns, +however, it uses double-checked locking to implement thread-safe lazy +initialization. +

    + +

    +Note that, because no other threads are allowed to issue LLVM API calls before +llvm_start_multithreaded() returns, it is possible to have +ManagedStatics of llvm::sys::Mutexs. +

    + +

    +The llvm_acquire_global_lock() and llvm_release_global_lock +APIs provide access to the global lock used to implement the double-checked +locking for lazy initialization. These should only be used internally to LLVM, +and only if you know what you're doing! +

    +
    + + + + +
    +

    +LLVMContext is an opaque class in the LLVM API which clients can use +to operate multiple, isolated instances of LLVM concurrently within the same +address space. For instance, in a hypothetical compile-server, the compilation +of an individual translation unit is conceptually independent from all the +others, and it would be desirable to be able to compile incoming translation +units concurrently on independent server threads. Fortunately, +LLVMContext exists to enable just this kind of scenario! +

    + +

    +Conceptually, LLVMContext provides isolation. Every LLVM entity +(Modules, Values, Types, Constants, etc.) +in LLVM's in-memory IR belongs to an LLVMContext. Entities in +different contexts cannot interact with each other: Modules in +different contexts cannot be linked together, Functions cannot be added +to Modules in different contexts, etc. What this means is that is is +safe to compile on multiple threads simultaneously, as long as no two threads +operate on entities within the same context. +

    + +

    +In practice, very few places in the API require the explicit specification of a +LLVMContext, other than the Type creation/lookup APIs. +Because every Type carries a reference to its owning context, most +other entities can determine what context they belong to by looking at their +own Type. If you are adding new entities to LLVM IR, please try to +maintain this interface design. +

    + +

    +For clients that do not require the benefits of isolation, LLVM +provides a convenience API getGlobalContext(). This returns a global, +lazily initialized LLVMContext that may be used in situations where +isolation is not a concern. +

    +
    + + + + + +
    +

    +This section describes some of the advanced or obscure API's that most clients +do not need to be aware of. These API's tend manage the inner workings of the +LLVM system, and only need to be accessed in unusual circumstances. +

    +
    + + + + +
    + +

    +The LLVM type system has a very simple goal: allow clients to compare types for +structural equality with a simple pointer comparison (aka a shallow compare). +This goal makes clients much simpler and faster, and is used throughout the LLVM +system. +

    + +

    +Unfortunately achieving this goal is not a simple matter. In particular, +recursive types and late resolution of opaque types makes the situation very +difficult to handle. Fortunately, for the most part, our implementation makes +most clients able to be completely unaware of the nasty internal details. The +primary case where clients are exposed to the inner workings of it are when +building a recursive type. In addition to this case, the LLVM bitcode reader, +assembly parser, and linker also have to be aware of the inner workings of this +system. +

    + +

    +For our purposes below, we need three concepts. First, an "Opaque Type" is +exactly as defined in the language +reference. Second an "Abstract Type" is any type which includes an +opaque type as part of its type graph (for example "{ opaque, i32 }"). +Third, a concrete type is a type that is not an abstract type (e.g. "{ i32, +float }"). +

    + +
    + + + + +
    + +

    +Because the most common question is "how do I build a recursive type with LLVM", +we answer it now and explain it as we go. Here we include enough to cause this +to be emitted to an output .ll file: +

    + +
    +
    +%mylist = type { %mylist*, i32 }
    +
    +
    + +

    +To build this, use the following LLVM APIs: +

    + +
    +
    +// Create the initial outer struct
    +PATypeHolder StructTy = OpaqueType::get();
    +std::vector<const Type*> Elts;
    +Elts.push_back(PointerType::getUnqual(StructTy));
    +Elts.push_back(Type::Int32Ty);
    +StructType *NewSTy = StructType::get(Elts);
    +
    +// At this point, NewSTy = "{ opaque*, i32 }". Tell VMCore that
    +// the struct and the opaque type are actually the same.
    +cast<OpaqueType>(StructTy.get())->refineAbstractTypeTo(NewSTy);
    +
    +// NewSTy is potentially invalidated, but StructTy (a PATypeHolder) is
    +// kept up-to-date
    +NewSTy = cast<StructType>(StructTy.get());
    +
    +// Add a name for the type to the module symbol table (optional)
    +MyModule->addTypeName("mylist", NewSTy);
    +
    +
    + +

    +This code shows the basic approach used to build recursive types: build a +non-recursive type using 'opaque', then use type unification to close the cycle. +The type unification step is performed by the refineAbstractTypeTo method, which is +described next. After that, we describe the PATypeHolder class. +

    + +
    + + + + +
    +

    +The refineAbstractTypeTo method starts the type unification process. +While this method is actually a member of the DerivedType class, it is most +often used on OpaqueType instances. Type unification is actually a recursive +process. After unification, types can become structurally isomorphic to +existing types, and all duplicates are deleted (to preserve pointer equality). +

    + +

    +In the example above, the OpaqueType object is definitely deleted. +Additionally, if there is an "{ \2*, i32}" type already created in the system, +the pointer and struct type created are also deleted. Obviously whenever +a type is deleted, any "Type*" pointers in the program are invalidated. As +such, it is safest to avoid having any "Type*" pointers to abstract types +live across a call to refineAbstractTypeTo (note that non-abstract +types can never move or be deleted). To deal with this, the PATypeHolder class is used to maintain a stable +reference to a possibly refined type, and the AbstractTypeUser class is used to update more +complex datastructures. +

    + +
    + + + + +
    +

    +PATypeHolder is a form of a "smart pointer" for Type objects. When VMCore +happily goes about nuking types that become isomorphic to existing types, it +automatically updates all PATypeHolder objects to point to the new type. In the +example above, this allows the code to maintain a pointer to the resultant +resolved recursive type, even though the Type*'s are potentially invalidated. +

    + +

    +PATypeHolder is an extremely light-weight object that uses a lazy union-find +implementation to update pointers. For example the pointer from a Value to its +Type is maintained by PATypeHolder objects. +

    + +
    + + + + +
    + +

    +Some data structures need more to perform more complex updates when types get +resolved. To support this, a class can derive from the AbstractTypeUser class. +This class +allows it to get callbacks when certain types are resolved. To register to get +callbacks for a particular type, the DerivedType::{add/remove}AbstractTypeUser +methods can be called on a type. Note that these methods only work for + abstract types. Concrete types (those that do not include any opaque +objects) can never be refined. +

    +
    + + + + + +
    +

    The +ValueSymbolTable class provides a symbol table that the Function and +Module classes use for naming value definitions. The symbol table +can provide a name for any Value. +The +TypeSymbolTable class is used by the Module class to store +names for types.

    + +

    Note that the SymbolTable class should not be directly accessed +by most clients. It should only be used when iteration over the symbol table +names themselves are required, which is very special purpose. Note that not +all LLVM +Values have names, and those without names (i.e. they have +an empty name) do not exist in the symbol table. +

    + +

    These symbol tables support iteration over the values/types in the symbol +table with begin/end/iterator and supports querying to see if a +specific name is in the symbol table (with lookup). The +ValueSymbolTable class exposes no public mutator methods, instead, +simply call setName on a value, which will autoinsert it into the +appropriate symbol table. For types, use the Module::addTypeName method to +insert entries into the symbol table.

    + +
    + + + + + + +
    +

    The +User class provides a basis for expressing the ownership of User +towards other +Values. The +Use helper class is employed to do the bookkeeping and to facilitate O(1) +addition and removal.

    + + + + +
    +

    +A subclass of User can choose between incorporating its Use objects +or refer to them out-of-line by means of a pointer. A mixed variant +(some Uses inline others hung off) is impractical and breaks the invariant +that the Use objects belonging to the same User form a contiguous array. +

    +
    + +

    +We have 2 different layouts in the User (sub)classes: +

      +
    • Layout a) +The Use object(s) are inside (resp. at fixed offset) of the User +object and there are a fixed number of them.

      + +
    • Layout b) +The Use object(s) are referenced by a pointer to an +array from the User object and there may be a variable +number of them.

      +
    +

    +As of v2.4 each layout still possesses a direct pointer to the +start of the array of Uses. Though not mandatory for layout a), +we stick to this redundancy for the sake of simplicity. +The User object also stores the number of Use objects it +has. (Theoretically this information can also be calculated +given the scheme presented below.)

    +

    +Special forms of allocation operators (operator new) +enforce the following memory layouts:

    + +
      +
    • Layout a) is modelled by prepending the User object by the Use[] array.

      + +
      +...---.---.---.---.-------...
      +  | P | P | P | P | User
      +'''---'---'---'---'-------'''
      +
      + +
    • Layout b) is modelled by pointing at the Use[] array.

      +
      +.-------...
      +| User
      +'-------'''
      +    |
      +    v
      +    .---.---.---.---...
      +    | P | P | P | P |
      +    '---'---'---'---'''
      +
      +
    +(In the above figures 'P' stands for the Use** that + is stored in each Use object in the member Use::Prev) + + + + +
    +

    +Since the Use objects are deprived of the direct (back)pointer to +their User objects, there must be a fast and exact method to +recover it. This is accomplished by the following scheme:

    +
    + +A bit-encoding in the 2 LSBits (least significant bits) of the Use::Prev allows to find the +start of the User object: +
      +
    • 00 —> binary digit 0
    • +
    • 01 —> binary digit 1
    • +
    • 10 —> stop and calculate (s)
    • +
    • 11 —> full stop (S)
    • +
    +

    +Given a Use*, all we have to do is to walk till we get +a stop and we either have a User immediately behind or +we have to walk to the next stop picking up digits +and calculating the offset:

    +
    +.---.---.---.---.---.---.---.---.---.---.---.---.---.---.---.---.----------------
    +| 1 | s | 1 | 0 | 1 | 0 | s | 1 | 1 | 0 | s | 1 | 1 | s | 1 | S | User (or User*)
    +'---'---'---'---'---'---'---'---'---'---'---'---'---'---'---'---'----------------
    +    |+15                |+10            |+6         |+3     |+1
    +    |                   |               |           |       |__>
    +    |                   |               |           |__________>
    +    |                   |               |______________________>
    +    |                   |______________________________________>
    +    |__________________________________________________________>
    +
    +

    +Only the significant number of bits need to be stored between the +stops, so that the worst case is 20 memory accesses when there are +1000 Use objects associated with a User.

    + + + + +
    +

    +The following literate Haskell fragment demonstrates the concept:

    +
    + +
    +
    +> import Test.QuickCheck
    +> 
    +> digits :: Int -> [Char] -> [Char]
    +> digits 0 acc = '0' : acc
    +> digits 1 acc = '1' : acc
    +> digits n acc = digits (n `div` 2) $ digits (n `mod` 2) acc
    +> 
    +> dist :: Int -> [Char] -> [Char]
    +> dist 0 [] = ['S']
    +> dist 0 acc = acc
    +> dist 1 acc = let r = dist 0 acc in 's' : digits (length r) r
    +> dist n acc = dist (n - 1) $ dist 1 acc
    +> 
    +> takeLast n ss = reverse $ take n $ reverse ss
    +> 
    +> test = takeLast 40 $ dist 20 []
    +> 
    +
    +
    +

    +Printing <test> gives: "1s100000s11010s10100s1111s1010s110s11s1S"

    +

    +The reverse algorithm computes the length of the string just by examining +a certain prefix:

    + +
    +
    +> pref :: [Char] -> Int
    +> pref "S" = 1
    +> pref ('s':'1':rest) = decode 2 1 rest
    +> pref (_:rest) = 1 + pref rest
    +> 
    +> decode walk acc ('0':rest) = decode (walk + 1) (acc * 2) rest
    +> decode walk acc ('1':rest) = decode (walk + 1) (acc * 2 + 1) rest
    +> decode walk acc _ = walk + acc
    +> 
    +
    +
    +

    +Now, as expected, printing <pref test> gives 40.

    +

    +We can quickCheck this with following property:

    + +
    +
    +> testcase = dist 2000 []
    +> testcaseLength = length testcase
    +> 
    +> identityProp n = n > 0 && n <= testcaseLength ==> length arr == pref arr
    +>     where arr = takeLast n testcase
    +> 
    +
    +
    +

    +As expected <quickCheck identityProp> gives:

    + +
    +*Main> quickCheck identityProp
    +OK, passed 100 tests.
    +
    +

    +Let's be a bit more exhaustive:

    + +
    +
    +> 
    +> deepCheck p = check (defaultConfig { configMaxTest = 500 }) p
    +> 
    +
    +
    +

    +And here is the result of <deepCheck identityProp>:

    + +
    +*Main> deepCheck identityProp
    +OK, passed 500 tests.
    +
    + + + + +

    +To maintain the invariant that the 2 LSBits of each Use** in Use +never change after being set up, setters of Use::Prev must re-tag the +new Use** on every modification. Accordingly getters must strip the +tag bits.

    +

    +For layout b) instead of the User we find a pointer (User* with LSBit set). +Following this pointer brings us to the User. A portable trick ensures +that the first bytes of User (if interpreted as a pointer) never has +the LSBit set. (Portability is relying on the fact that all known compilers place the +vptr in the first word of the instances.)

    + +
    + + + + + +
    +

    #include "llvm/Type.h" +
    doxygen info: Type Class

    + +

    The Core LLVM classes are the primary means of representing the program +being inspected or transformed. The core LLVM classes are defined in +header files in the include/llvm/ directory, and implemented in +the lib/VMCore directory.

    + +
    + + + + +
    + +

    Type is a superclass of all type classes. Every Value has + a Type. Type cannot be instantiated directly but only + through its subclasses. Certain primitive types (VoidType, + LabelType, FloatType and DoubleType) have hidden + subclasses. They are hidden because they offer no useful functionality beyond + what the Type class offers except to distinguish themselves from + other subclasses of Type.

    +

    All other types are subclasses of DerivedType. Types can be + named, but this is not a requirement. There exists exactly + one instance of a given shape at any one time. This allows type equality to + be performed with address equality of the Type Instance. That is, given two + Type* values, the types are identical if the pointers are identical. +

    +
    + + + + +
    + +
      +
    • bool isInteger() const: Returns true for any integer type.
    • + +
    • bool isFloatingPoint(): Return true if this is one of the two + floating point types.
    • + +
    • bool isAbstract(): Return true if the type is abstract (contains + an OpaqueType anywhere in its definition).
    • + +
    • bool isSized(): Return true if the type has known size. Things + that don't have a size are abstract types, labels and void.
    • + +
    +
    + + + +
    +
    +
    IntegerType
    +
    Subclass of DerivedType that represents integer types of any bit width. + Any bit width between IntegerType::MIN_INT_BITS (1) and + IntegerType::MAX_INT_BITS (~8 million) can be represented. +
      +
    • static const IntegerType* get(unsigned NumBits): get an integer + type of a specific bit width.
    • +
    • unsigned getBitWidth() const: Get the bit width of an integer + type.
    • +
    +
    +
    SequentialType
    +
    This is subclassed by ArrayType and PointerType +
      +
    • const Type * getElementType() const: Returns the type of each + of the elements in the sequential type.
    • +
    +
    +
    ArrayType
    +
    This is a subclass of SequentialType and defines the interface for array + types. +
      +
    • unsigned getNumElements() const: Returns the number of + elements in the array.
    • +
    +
    +
    PointerType
    +
    Subclass of SequentialType for pointer types.
    +
    VectorType
    +
    Subclass of SequentialType for vector types. A + vector type is similar to an ArrayType but is distinguished because it is + a first class type whereas ArrayType is not. Vector types are used for + vector operations and are usually small vectors of of an integer or floating + point type.
    +
    StructType
    +
    Subclass of DerivedTypes for struct types.
    +
    FunctionType
    +
    Subclass of DerivedTypes for function types. +
      +
    • bool isVarArg() const: Returns true if its a vararg + function
    • +
    • const Type * getReturnType() const: Returns the + return type of the function.
    • +
    • const Type * getParamType (unsigned i): Returns + the type of the ith parameter.
    • +
    • const unsigned getNumParams() const: Returns the + number of formal parameters.
    • +
    +
    +
    OpaqueType
    +
    Sublcass of DerivedType for abstract types. This class + defines no content and is used as a placeholder for some other type. Note + that OpaqueType is used (temporarily) during type resolution for forward + references of types. Once the referenced type is resolved, the OpaqueType + is replaced with the actual type. OpaqueType can also be used for data + abstraction. At link time opaque types can be resolved to actual types + of the same name.
    +
    +
    + + + + + + +
    + +

    #include "llvm/Module.h"
    doxygen info: +Module Class

    + +

    The Module class represents the top level structure present in LLVM +programs. An LLVM module is effectively either a translation unit of the +original program or a combination of several translation units merged by the +linker. The Module class keeps track of a list of Functions, a list of GlobalVariables, and a SymbolTable. Additionally, it contains a few +helpful member functions that try to make common operations easy.

    + +
    + + + + +
    + +
      +
    • Module::Module(std::string name = "")
    • +
    + +

    Constructing a Module is easy. You can optionally +provide a name for it (probably based on the name of the translation unit).

    + +
      +
    • Module::iterator - Typedef for function list iterator
      + Module::const_iterator - Typedef for const_iterator.
      + + begin(), end() + size(), empty() + +

      These are forwarding methods that make it easy to access the contents of + a Module object's Function + list.

    • + +
    • Module::FunctionListType &getFunctionList() + +

      Returns the list of Functions. This is + necessary to use when you need to update the list or perform a complex + action that doesn't have a forwarding method.

      + +

    • +
    + +
    + +
      +
    • Module::global_iterator - Typedef for global variable list iterator
      + + Module::const_global_iterator - Typedef for const_iterator.
      + + global_begin(), global_end() + global_size(), global_empty() + +

      These are forwarding methods that make it easy to access the contents of + a Module object's GlobalVariable list.

    • + +
    • Module::GlobalListType &getGlobalList() + +

      Returns the list of GlobalVariables. This is necessary to + use when you need to update the list or perform a complex action that + doesn't have a forwarding method.

      + +

    • +
    + +
    + + + +
    + +
      +
    • Function *getFunction(const std::string + &Name, const FunctionType *Ty) + +

      Look up the specified function in the Module SymbolTable. If it does not exist, return + null.

    • + +
    • Function *getOrInsertFunction(const + std::string &Name, const FunctionType *T) + +

      Look up the specified function in the Module SymbolTable. If it does not exist, add an + external declaration for the function and return it.

    • + +
    • std::string getTypeName(const Type *Ty) + +

      If there is at least one entry in the SymbolTable for the specified Type, return it. Otherwise return the empty + string.

    • + +
    • bool addTypeName(const std::string &Name, const Type *Ty) + +

      Insert an entry in the SymbolTable + mapping Name to Ty. If there is already an entry for this + name, true is returned and the SymbolTable is not modified.

    • +
    + +
    + + + + + +
    + +

    #include "llvm/Value.h" +
    +doxygen info: Value Class

    + +

    The Value class is the most important class in the LLVM Source +base. It represents a typed value that may be used (among other things) as an +operand to an instruction. There are many different types of Values, +such as Constants,Arguments. Even Instructions and Functions are Values.

    + +

    A particular Value may be used many times in the LLVM representation +for a program. For example, an incoming argument to a function (represented +with an instance of the Argument class) is "used" by +every instruction in the function that references the argument. To keep track +of this relationship, the Value class keeps a list of all of the Users that is using it (the User class is a base class for all nodes in the LLVM +graph that can refer to Values). This use list is how LLVM represents +def-use information in the program, and is accessible through the use_* +methods, shown below.

    + +

    Because LLVM is a typed representation, every LLVM Value is typed, +and this Type is available through the getType() +method. In addition, all LLVM values can be named. The "name" of the +Value is a symbolic string printed in the LLVM code:

    + +
    +
    +%foo = add i32 1, 2
    +
    +
    + +

    The name of this instruction is "foo". NOTE +that the name of any value may be missing (an empty string), so names should +ONLY be used for debugging (making the source code easier to read, +debugging printouts), they should not be used to keep track of values or map +between them. For this purpose, use a std::map of pointers to the +Value itself instead.

    + +

    One important aspect of LLVM is that there is no distinction between an SSA +variable and the operation that produces it. Because of this, any reference to +the value produced by an instruction (or the value available as an incoming +argument, for example) is represented as a direct pointer to the instance of +the class that +represents this value. Although this may take some getting used to, it +simplifies the representation and makes it easier to manipulate.

    + +
    + + + + +
    + +
      +
    • Value::use_iterator - Typedef for iterator over the +use-list
      + Value::use_const_iterator - Typedef for const_iterator over +the use-list
      + unsigned use_size() - Returns the number of users of the +value.
      + bool use_empty() - Returns true if there are no users.
      + use_iterator use_begin() - Get an iterator to the start of +the use-list.
      + use_iterator use_end() - Get an iterator to the end of the +use-list.
      + User *use_back() - Returns the last +element in the list. +

      These methods are the interface to access the def-use +information in LLVM. As with all other iterators in LLVM, the naming +conventions follow the conventions defined by the STL.

      +
    • +
    • Type *getType() const +

      This method returns the Type of the Value.

      +
    • +
    • bool hasName() const
      + std::string getName() const
      + void setName(const std::string &Name) +

      This family of methods is used to access and assign a name to a Value, +be aware of the precaution above.

      +
    • +
    • void replaceAllUsesWith(Value *V) + +

      This method traverses the use list of a Value changing all Users of the current value to refer to + "V" instead. For example, if you detect that an instruction always + produces a constant value (for example through constant folding), you can + replace all uses of the instruction with the constant like this:

      + +
      +
      +Inst->replaceAllUsesWith(ConstVal);
      +
      +
      + +
    + +
    + + + + +
    + +

    +#include "llvm/User.h"
    +doxygen info: User Class
    +Superclass: Value

    + +

    The User class is the common base class of all LLVM nodes that may +refer to Values. It exposes a list of "Operands" +that are all of the Values that the User is +referring to. The User class itself is a subclass of +Value.

    + +

    The operands of a User point directly to the LLVM Value that it refers to. Because LLVM uses Static +Single Assignment (SSA) form, there can only be one definition referred to, +allowing this direct connection. This connection provides the use-def +information in LLVM.

    + +
    + + + + +
    + +

    The User class exposes the operand list in two ways: through +an index access interface and through an iterator based interface.

    + +
      +
    • Value *getOperand(unsigned i)
      + unsigned getNumOperands() +

      These two methods expose the operands of the User in a +convenient form for direct access.

    • + +
    • User::op_iterator - Typedef for iterator over the operand +list
      + op_iterator op_begin() - Get an iterator to the start of +the operand list.
      + op_iterator op_end() - Get an iterator to the end of the +operand list. +

      Together, these methods make up the iterator based interface to +the operands of a User.

    • +
    + +
    + + + + +
    + +

    #include "llvm/Instruction.h"
    +doxygen info: Instruction Class
    +Superclasses: User, Value

    + +

    The Instruction class is the common base class for all LLVM +instructions. It provides only a few methods, but is a very commonly used +class. The primary data tracked by the Instruction class itself is the +opcode (instruction type) and the parent BasicBlock the Instruction is embedded +into. To represent a specific type of instruction, one of many subclasses of +Instruction are used.

    + +

    Because the Instruction class subclasses the User class, its operands can be accessed in the same +way as for other Users (with the +getOperand()/getNumOperands() and +op_begin()/op_end() methods).

    An important file for +the Instruction class is the llvm/Instruction.def file. This +file contains some meta-data about the various different types of instructions +in LLVM. It describes the enum values that are used as opcodes (for example +Instruction::Add and Instruction::ICmp), as well as the +concrete sub-classes of Instruction that implement the instruction (for +example BinaryOperator and CmpInst). Unfortunately, the use of macros in +this file confuses doxygen, so these enum values don't show up correctly in the +doxygen output.

    + +
    + + + +
    +
      +
    • BinaryOperator +

      This subclasses represents all two operand instructions whose operands + must be the same type, except for the comparison instructions.

    • +
    • CastInst +

      This subclass is the parent of the 12 casting instructions. It provides + common operations on cast instructions.

      +
    • CmpInst +

      This subclass respresents the two comparison instructions, + ICmpInst (integer opreands), and + FCmpInst (floating point operands).

      +
    • TerminatorInst +

      This subclass is the parent of all terminator instructions (those which + can terminate a block).

      +
    +
    + + + + +
    + +
      +
    • BasicBlock *getParent() +

      Returns the BasicBlock that +this Instruction is embedded into.

    • +
    • bool mayWriteToMemory() +

      Returns true if the instruction writes to memory, i.e. it is a + call,free,invoke, or store.

    • +
    • unsigned getOpcode() +

      Returns the opcode for the Instruction.

    • +
    • Instruction *clone() const +

      Returns another instance of the specified instruction, identical +in all ways to the original except that the instruction has no parent +(ie it's not embedded into a BasicBlock), +and it has no name

    • +
    + +
    + + + + +
    + +

    Constant represents a base class for different types of constants. It +is subclassed by ConstantInt, ConstantArray, etc. for representing +the various types of Constants. GlobalValue is also +a subclass, which represents the address of a global variable or function. +

    + +
    + + +
    Important Subclasses of Constant
    +
    +
      +
    • ConstantInt : This subclass of Constant represents an integer constant of + any width. +
        +
      • const APInt& getValue() const: Returns the underlying + value of this constant, an APInt value.
      • +
      • int64_t getSExtValue() const: Converts the underlying APInt + value to an int64_t via sign extension. If the value (not the bit width) + of the APInt is too large to fit in an int64_t, an assertion will result. + For this reason, use of this method is discouraged.
      • +
      • uint64_t getZExtValue() const: Converts the underlying APInt + value to a uint64_t via zero extension. IF the value (not the bit width) + of the APInt is too large to fit in a uint64_t, an assertion will result. + For this reason, use of this method is discouraged.
      • +
      • static ConstantInt* get(const APInt& Val): Returns the + ConstantInt object that represents the value provided by Val. + The type is implied as the IntegerType that corresponds to the bit width + of Val.
      • +
      • static ConstantInt* get(const Type *Ty, uint64_t Val): + Returns the ConstantInt object that represents the value provided by + Val for integer type Ty.
      • +
      +
    • +
    • ConstantFP : This class represents a floating point constant. +
        +
      • double getValue() const: Returns the underlying value of + this constant.
      • +
      +
    • +
    • ConstantArray : This represents a constant array. +
        +
      • const std::vector<Use> &getValues() const: Returns + a vector of component constants that makeup this array.
      • +
      +
    • +
    • ConstantStruct : This represents a constant struct. +
        +
      • const std::vector<Use> &getValues() const: Returns + a vector of component constants that makeup this array.
      • +
      +
    • +
    • GlobalValue : This represents either a global variable or a function. In + either case, the value is a constant fixed address (after linking). +
    • +
    +
    + + + + + +
    + +

    #include "llvm/GlobalValue.h"
    +doxygen info: GlobalValue +Class
    +Superclasses: Constant, +User, Value

    + +

    Global values (GlobalVariables or Functions) are the only LLVM values that are +visible in the bodies of all Functions. +Because they are visible at global scope, they are also subject to linking with +other globals defined in different translation units. To control the linking +process, GlobalValues know their linkage rules. Specifically, +GlobalValues know whether they have internal or external linkage, as +defined by the LinkageTypes enumeration.

    + +

    If a GlobalValue has internal linkage (equivalent to being +static in C), it is not visible to code outside the current translation +unit, and does not participate in linking. If it has external linkage, it is +visible to external code, and does participate in linking. In addition to +linkage information, GlobalValues keep track of which Module they are currently part of.

    + +

    Because GlobalValues are memory objects, they are always referred to +by their address. As such, the Type of a +global is always a pointer to its contents. It is important to remember this +when using the GetElementPtrInst instruction because this pointer must +be dereferenced first. For example, if you have a GlobalVariable (a +subclass of GlobalValue) that is an array of 24 ints, type [24 x +i32], then the GlobalVariable is a pointer to that array. Although +the address of the first element of this array and the value of the +GlobalVariable are the same, they have different types. The +GlobalVariable's type is [24 x i32]. The first element's type +is i32. Because of this, accessing a global value requires you to +dereference the pointer with GetElementPtrInst first, then its elements +can be accessed. This is explained in the LLVM +Language Reference Manual.

    + +
    + + + + +
    + +
      +
    • bool hasInternalLinkage() const
      + bool hasExternalLinkage() const
      + void setInternalLinkage(bool HasInternalLinkage) +

      These methods manipulate the linkage characteristics of the GlobalValue.

      +

      +
    • +
    • Module *getParent() +

      This returns the Module that the +GlobalValue is currently embedded into.

    • +
    + +
    + + + + +
    + +

    #include "llvm/Function.h"
    doxygen +info: Function Class
    +Superclasses: GlobalValue, +Constant, +User, +Value

    + +

    The Function class represents a single procedure in LLVM. It is +actually one of the more complex classes in the LLVM hierarchy because it must +keep track of a large amount of data. The Function class keeps track +of a list of BasicBlocks, a list of formal +Arguments, and a +SymbolTable.

    + +

    The list of BasicBlocks is the most +commonly used part of Function objects. The list imposes an implicit +ordering of the blocks in the function, which indicate how the code will be +laid out by the backend. Additionally, the first BasicBlock is the implicit entry node for the +Function. It is not legal in LLVM to explicitly branch to this initial +block. There are no implicit exit nodes, and in fact there may be multiple exit +nodes from a single Function. If the BasicBlock list is empty, this indicates that +the Function is actually a function declaration: the actual body of the +function hasn't been linked in yet.

    + +

    In addition to a list of BasicBlocks, the +Function class also keeps track of the list of formal Arguments that the function receives. This +container manages the lifetime of the Argument +nodes, just like the BasicBlock list does for +the BasicBlocks.

    + +

    The SymbolTable is a very rarely used +LLVM feature that is only used when you have to look up a value by name. Aside +from that, the SymbolTable is used +internally to make sure that there are not conflicts between the names of Instructions, BasicBlocks, or Arguments in the function body.

    + +

    Note that Function is a GlobalValue +and therefore also a Constant. The value of the function +is its address (after linking) which is guaranteed to be constant.

    +
    + + + + +
    + +
      +
    • Function(const FunctionType + *Ty, LinkageTypes Linkage, const std::string &N = "", Module* Parent = 0) + +

      Constructor used when you need to create new Functions to add + the the program. The constructor must specify the type of the function to + create and what type of linkage the function should have. The FunctionType argument + specifies the formal arguments and return value for the function. The same + FunctionType value can be used to + create multiple functions. The Parent argument specifies the Module + in which the function is defined. If this argument is provided, the function + will automatically be inserted into that module's list of + functions.

    • + +
    • bool isDeclaration() + +

      Return whether or not the Function has a body defined. If the + function is "external", it does not have a body, and thus must be resolved + by linking with a function defined in a different translation unit.

    • + +
    • Function::iterator - Typedef for basic block list iterator
      + Function::const_iterator - Typedef for const_iterator.
      + + begin(), end() + size(), empty() + +

      These are forwarding methods that make it easy to access the contents of + a Function object's BasicBlock + list.

    • + +
    • Function::BasicBlockListType &getBasicBlockList() + +

      Returns the list of BasicBlocks. This + is necessary to use when you need to update the list or perform a complex + action that doesn't have a forwarding method.

    • + +
    • Function::arg_iterator - Typedef for the argument list +iterator
      + Function::const_arg_iterator - Typedef for const_iterator.
      + + arg_begin(), arg_end() + arg_size(), arg_empty() + +

      These are forwarding methods that make it easy to access the contents of + a Function object's Argument + list.

    • + +
    • Function::ArgumentListType &getArgumentList() + +

      Returns the list of Arguments. This is + necessary to use when you need to update the list or perform a complex + action that doesn't have a forwarding method.

    • + +
    • BasicBlock &getEntryBlock() + +

      Returns the entry BasicBlock for the + function. Because the entry block for the function is always the first + block, this returns the first block of the Function.

    • + +
    • Type *getReturnType()
      + FunctionType *getFunctionType() + +

      This traverses the Type of the + Function and returns the return type of the function, or the FunctionType of the actual + function.

    • + +
    • SymbolTable *getSymbolTable() + +

      Return a pointer to the SymbolTable + for this Function.

    • +
    + +
    + + + + +
    + +

    #include "llvm/GlobalVariable.h" +
    +doxygen info: GlobalVariable + Class
    +Superclasses: GlobalValue, +Constant, +User, +Value

    + +

    Global variables are represented with the (surprise surprise) +GlobalVariable class. Like functions, GlobalVariables are also +subclasses of GlobalValue, and as such are +always referenced by their address (global values must live in memory, so their +"name" refers to their constant address). See +GlobalValue for more on this. Global +variables may have an initial value (which must be a +Constant), and if they have an initializer, +they may be marked as "constant" themselves (indicating that their contents +never change at runtime).

    +
    + + + + +
    + +
      +
    • GlobalVariable(const Type *Ty, bool + isConstant, LinkageTypes& Linkage, Constant + *Initializer = 0, const std::string &Name = "", Module* Parent = 0) + +

      Create a new global variable of the specified type. If + isConstant is true then the global variable will be marked as + unchanging for the program. The Linkage parameter specifies the type of + linkage (internal, external, weak, linkonce, appending) for the variable. + If the linkage is InternalLinkage, WeakAnyLinkage, WeakODRLinkage, + LinkOnceAnyLinkage or LinkOnceODRLinkage,  then the resultant + global variable will have internal linkage. AppendingLinkage concatenates + together all instances (in different translation units) of the variable + into a single variable but is only applicable to arrays.  See + the LLVM Language Reference for + further details on linkage types. Optionally an initializer, a name, and the + module to put the variable into may be specified for the global variable as + well.

    • + +
    • bool isConstant() const + +

      Returns true if this is a global variable that is known not to + be modified at runtime.

    • + +
    • bool hasInitializer() + +

      Returns true if this GlobalVariable has an intializer.

    • + +
    • Constant *getInitializer() + +

      Returns the initial value for a GlobalVariable. It is not legal + to call this method if there is no initializer.

    • +
    + +
    + + + + + +
    + +

    #include "llvm/BasicBlock.h"
    +doxygen info: BasicBlock +Class
    +Superclass: Value

    + +

    This class represents a single entry multiple exit section of the code, +commonly known as a basic block by the compiler community. The +BasicBlock class maintains a list of Instructions, which form the body of the block. +Matching the language definition, the last element of this list of instructions +is always a terminator instruction (a subclass of the TerminatorInst class).

    + +

    In addition to tracking the list of instructions that make up the block, the +BasicBlock class also keeps track of the Function that it is embedded into.

    + +

    Note that BasicBlocks themselves are Values, because they are referenced by instructions +like branches and can go in the switch tables. BasicBlocks have type +label.

    + +
    + + + + +
    +
      + +
    • BasicBlock(const std::string &Name = "", Function *Parent = 0) + +

      The BasicBlock constructor is used to create new basic blocks for +insertion into a function. The constructor optionally takes a name for the new +block, and a Function to insert it into. If +the Parent parameter is specified, the new BasicBlock is +automatically inserted at the end of the specified Function, if not specified, the BasicBlock must be +manually inserted into the Function.

    • + +
    • BasicBlock::iterator - Typedef for instruction list iterator
      +BasicBlock::const_iterator - Typedef for const_iterator.
      +begin(), end(), front(), back(), +size(), empty() +STL-style functions for accessing the instruction list. + +

      These methods and typedefs are forwarding functions that have the same +semantics as the standard library methods of the same names. These methods +expose the underlying instruction list of a basic block in a way that is easy to +manipulate. To get the full complement of container operations (including +operations to update the list), you must use the getInstList() +method.

    • + +
    • BasicBlock::InstListType &getInstList() + +

      This method is used to get access to the underlying container that actually +holds the Instructions. This method must be used when there isn't a forwarding +function in the BasicBlock class for the operation that you would like +to perform. Because there are no forwarding functions for "updating" +operations, you need to use this if you want to update the contents of a +BasicBlock.

    • + +
    • Function *getParent() + +

      Returns a pointer to Function the block is +embedded into, or a null pointer if it is homeless.

    • + +
    • TerminatorInst *getTerminator() + +

      Returns a pointer to the terminator instruction that appears at the end of +the BasicBlock. If there is no terminator instruction, or if the last +instruction in the block is not a terminator, then a null pointer is +returned.

    • + +
    + +
    + + + + + +
    + +

    This subclass of Value defines the interface for incoming formal +arguments to a function. A Function maintains a list of its formal +arguments. An argument has a pointer to the parent Function.

    + +
    + + +
    +
    + Valid CSS + Valid HTML 4.01 Strict + + Dinakar Dhurjati and + Chris Lattner
    + The LLVM Compiler Infrastructure
    + Last modified: $Date$ +
    + + + diff --git a/libclamav/c++/llvm/docs/Projects.html b/libclamav/c++/llvm/docs/Projects.html new file mode 100644 index 000000000..ada6196be --- /dev/null +++ b/libclamav/c++/llvm/docs/Projects.html @@ -0,0 +1,460 @@ + + + + Creating an LLVM Project + + + + +
    Creating an LLVM Project
    + +
      +
    1. Overview
    2. +
    3. Create a project from the Sample Project
    4. +
    5. Source tree layout
    6. +
    7. Writing LLVM-style Makefiles +
        +
      1. Required Variables
      2. +
      3. Variables for Building Subdirectories
      4. +
      5. Variables for Building Libraries
      6. +
      7. Variables for Building Programs
      8. +
      9. Miscellaneous Variables
      10. +
    8. +
    9. Placement of object code
    10. +
    11. Further help
    12. +
    + +
    +

    Written by John Criswell

    +
    + + + + + +
    + +

    The LLVM build system is designed to facilitate the building of third party +projects that use LLVM header files, libraries, and tools. In order to use +these facilities, a Makefile from a project must do the following things:

    + +
      +
    1. Set make variables. There are several variables that a Makefile + needs to set to use the LLVM build system: +
        +
      • PROJECT_NAME - The name by which your project is known.
      • +
      • LLVM_SRC_ROOT - The root of the LLVM source tree.
      • +
      • LLVM_OBJ_ROOT - The root of the LLVM object tree.
      • +
      • PROJ_SRC_ROOT - The root of the project's source tree.
      • +
      • PROJ_OBJ_ROOT - The root of the project's object tree.
      • +
      • PROJ_INSTALL_ROOT - The root installation directory.
      • +
      • LEVEL - The relative path from the current directory to the + project's root ($PROJ_OBJ_ROOT).
      • +
    2. +
    3. Include Makefile.config from $(LLVM_OBJ_ROOT).
    4. +
    5. Include Makefile.rules from $(LLVM_SRC_ROOT).
    6. +
    + +

    There are two ways that you can set all of these variables:

    +
      +
    1. You can write your own Makefiles which hard-code these values.
    2. +
    3. You can use the pre-made LLVM sample project. This sample project + includes Makefiles, a configure script that can be used to configure the + location of LLVM, and the ability to support multiple object directories + from a single source directory.
    4. +
    + +

    This document assumes that you will base your project on the LLVM sample +project found in llvm/projects/sample. If you want to devise your own +build system, studying the sample project and LLVM Makefiles will probably +provide enough information on how to write your own Makefiles.

    + +
    + + + + + +
    + +

    Follow these simple steps to start your project:

    + +
      +
    1. Copy the llvm/projects/sample directory to any place of your +choosing. You can place it anywhere you like. Rename the directory to match +the name of your project.
    2. + +
    3. +If you downloaded LLVM using Subversion, remove all the directories named .svn +(and all the files therein) from your project's new source tree. This will +keep Subversion from thinking that your project is inside +llvm/trunk/projects/sample.
    4. + +
    5. Add your source code and Makefiles to your source tree.
    6. + +
    7. If you want your project to be configured with the configure script +then you need to edit autoconf/configure.ac as follows: +
        +
      • AC_INIT. Place the name of your project, its version number and + a contact email address for your project as the arguments to this macro
      • +
      • AC_CONFIG_AUX_DIR. If your project isn't in the + llvm/projects directory then you might need to adjust this so that + it specifies a relative path to the llvm/autoconf directory.
      • +
      • LLVM_CONFIG_PROJECT. Just leave this alone.
      • +
      • AC_CONFIG_SRCDIR. Specify a path to a file name that identifies + your project; or just leave it at Makefile.common.in
      • +
      • AC_CONFIG_FILES. Do not change.
      • +
      • AC_CONFIG_MAKEFILE. Use one of these macros for each Makefile + that your project uses. This macro arranges for your makefiles to be copied + from the source directory, unmodified, to the build directory.
      • +
      +
    8. + +
    9. After updating autoconf/configure.ac, regenerate the +configure script with these commands: + +
      +

      % cd autoconf
      + % ./AutoRegen.sh

      +
      + +

      You must be using Autoconf version 2.59 or later and your aclocal version +should be 1.9 or later.

    10. + +
    11. Run configure in the directory in which you want to place +object code. Use the following options to tell your project where it +can find LLVM: + +
      +
      --with-llvmsrc=<directory>
      +
      Tell your project where the LLVM source tree is located.
      +

      --with-llvmobj=<directory>
      +
      Tell your project where the LLVM object tree is located.
      +

      --prefix=<directory>
      +
      Tell your project where it should get installed.
      +
      +
    + +

    That's it! Now all you have to do is type gmake (or make +if your on a GNU/Linux system) in the root of your object directory, and your +project should build.

    + +
    + + + + + +
    + +

    In order to use the LLVM build system, you will want to organize your +source code so that it can benefit from the build system's features. +Mainly, you want your source tree layout to look similar to the LLVM +source tree layout. The best way to do this is to just copy the +project tree from llvm/projects/sample and modify it to meet +your needs, but you can certainly add to it if you want.

    + +

    Underneath your top level directory, you should have the following +directories:

    + +
    +
    lib +
    + This subdirectory should contain all of your library source + code. For each library that you build, you will have one + directory in lib that will contain that library's source + code. + +

    + Libraries can be object files, archives, or dynamic libraries. + The lib directory is just a convenient place for libraries + as it places them all in a directory from which they can be linked + later. + +

    include +
    + This subdirectory should contain any header files that are + global to your project. By global, we mean that they are used + by more than one library or executable of your project. +

    + By placing your header files in include, they will be + found automatically by the LLVM build system. For example, if + you have a file include/jazz/note.h, then your source + files can include it simply with #include "jazz/note.h". + +

    tools +
    + This subdirectory should contain all of your source + code for executables. For each program that you build, you + will have one directory in tools that will contain that + program's source code. +

    + +

    test +
    + This subdirectory should contain tests that verify that your code + works correctly. Automated tests are especially useful. +

    + Currently, the LLVM build system provides basic support for tests. + The LLVM system provides the following: +

      +
    • + LLVM provides a tcl procedure that is used by Dejagnu to run + tests. It can be found in llvm/lib/llvm-dg.exp. This + test procedure uses RUN lines in the actual test case to determine + how to run the test. See the TestingGuide for more details. You + can easily write Makefile support similar to the Makefiles in + llvm/test to use Dejagnu to run your project's tests.
    • +
    • + LLVM contains an optional package called llvm-test + which provides benchmarks and programs that are known to compile with the + LLVM GCC front ends. You can use these + programs to test your code, gather statistics information, and + compare it to the current LLVM performance statistics. +
      Currently, there is no way to hook your tests directly into the + llvm/test testing harness. You will simply + need to find a way to use the source provided within that directory + on your own. +
    +
    + +

    Typically, you will want to build your lib directory first followed by +your tools directory.

    + +
    + + + + + +
    + +

    The LLVM build system provides a convenient way to build libraries and +executables. Most of your project Makefiles will only need to define a few +variables. Below is a list of the variables one can set and what they can +do:

    + +
    + + + + +
    + +
    +
    LEVEL +
    + This variable is the relative path from this Makefile to the + top directory of your project's source code. For example, if + your source code is in /tmp/src, then the Makefile in + /tmp/src/jump/high would set LEVEL to "../..". +
    + +
    + + + + +
    + +
    +
    DIRS +
    + This is a space separated list of subdirectories that should be + built. They will be built, one at a time, in the order + specified. +

    + +

    PARALLEL_DIRS +
    + This is a list of directories that can be built in parallel. + These will be built after the directories in DIRS have been + built. +

    + +

    OPTIONAL_DIRS +
    + This is a list of directories that can be built if they exist, + but will not cause an error if they do not exist. They are + built serially in the order in which they are listed. +
    + +
    + + + + +
    + +
    +
    LIBRARYNAME +
    + This variable contains the base name of the library that will + be built. For example, to build a library named + libsample.a, LIBRARYNAME should be set to + sample. +

    + +

    BUILD_ARCHIVE +
    + By default, a library is a .o file that is linked + directly into a program. To build an archive (also known as + a static library), set the BUILD_ARCHIVE variable. +

    + +

    SHARED_LIBRARY +
    + If SHARED_LIBRARY is defined in your Makefile, a shared + (or dynamic) library will be built. +
    + +
    + + + + +
    + +
    +
    TOOLNAME +
    + This variable contains the name of the program that will + be built. For example, to build an executable named + sample, TOOLNAME should be set to sample. +

    + +

    USEDLIBS +
    + This variable holds a space separated list of libraries that + should be linked into the program. These libraries must either + be LLVM libraries or libraries that come from your lib + directory. The libraries must be specified by their base name. + For example, to link libsample.a, you would set USEDLIBS to + sample. +

    + Note that this works only for statically linked libraries. +

    + +

    LIBS +
    + To link dynamic libraries, add -l<library base name> to + the LIBS variable. The LLVM build system will look in the same places + for dynamic libraries as it does for static libraries. +

    + For example, to link libsample.so, you would have the + following line in your Makefile: +

    + + LIBS += -lsample + +

    + +
    + + + + +
    + +
    +
    ExtraSource +
    + This variable contains a space separated list of extra source + files that need to be built. It is useful for including the + output of Lex and Yacc programs. +

    + +

    CFLAGS +
    CPPFLAGS +
    + This variable can be used to add options to the C and C++ + compiler, respectively. It is typically used to add options + that tell the compiler the location of additional directories + to search for header files. +

    + It is highly suggested that you append to CFLAGS and CPPFLAGS as + opposed to overwriting them. The master Makefiles may already + have useful options in them that you may not want to overwrite. +

    +

    + +
    + + + + + +
    + +

    The final location of built libraries and executables will depend upon +whether you do a Debug, Release, or Profile build.

    + +
    +
    Libraries +
    + All libraries (static and dynamic) will be stored in + PROJ_OBJ_ROOT/<type>/lib, where type is Debug, + Release, or Profile for a debug, optimized, or + profiled build, respectively.

    + +

    Executables +
    All executables will be stored in + PROJ_OBJ_ROOT/<type>/bin, where type is Debug, + Release, or Profile for a debug, optimized, or profiled + build, respectively. +
    + +
    + + + + + +
    + +

    If you have any questions or need any help creating an LLVM project, +the LLVM team would be more than happy to help. You can always post your +questions to the LLVM Developers +Mailing List.

    + +
    + + +
    +
    + Valid CSS + Valid HTML 4.01 + + John Criswell
    + The LLVM Compiler Infrastructure +
    + Last modified: $Date$ +
    + + + diff --git a/libclamav/c++/llvm/docs/ReleaseNotes.html b/libclamav/c++/llvm/docs/ReleaseNotes.html new file mode 100644 index 000000000..5a5a01ae8 --- /dev/null +++ b/libclamav/c++/llvm/docs/ReleaseNotes.html @@ -0,0 +1,1355 @@ + + + + + + LLVM 2.6 Release Notes + + + +
    LLVM 2.6 Release Notes
    + +
      +
    1. Introduction
    2. +
    3. Sub-project Status Update
    4. +
    5. External Projects Using LLVM 2.6
    6. +
    7. What's New in LLVM 2.6?
    8. +
    9. Installation Instructions
    10. +
    11. Portability and Supported Platforms
    12. +
    13. Known Problems
    14. +
    15. Additional Information
    16. +
    + +
    +

    Written by the LLVM Team

    +
    + + + + + +
    + +

    This document contains the release notes for the LLVM Compiler +Infrastructure, release 2.6. Here we describe the status of LLVM, including +major improvements from the previous release and significant known problems. +All LLVM releases may be downloaded from the LLVM releases web site.

    + +

    For more information about LLVM, including information about the latest +release, please check out the main LLVM +web site. If you have questions or comments, the LLVM Developer's Mailing +List is a good place to send them.

    + +

    Note that if you are reading this file from a Subversion checkout or the +main LLVM web page, this document applies to the next release, not the +current one. To see the release notes for a specific release, please see the +releases page.

    + +
    + + + + + + + + + + + + + +
    +

    +The LLVM 2.6 distribution currently consists of code from the core LLVM +repository (which roughly includes the LLVM optimizers, code generators +and supporting tools), the Clang repository and the llvm-gcc repository. In +addition to this code, the LLVM Project includes other sub-projects that are in +development. Here we include updates on these subprojects. +

    + +
    + + + + + +
    + +

    The Clang project is an effort to build +a set of new 'LLVM native' front-end technologies for the C family of languages. +LLVM 2.6 is the first release to officially include Clang, and it provides a +production quality C and Objective-C compiler. If you are interested in fast compiles and +good diagnostics, we +encourage you to try it out. Clang currently compiles typical Objective-C code +3x faster than GCC and compiles C code about 30% faster than GCC at -O0 -g +(which is when the most pressure is on the frontend).

    + +

    In addition to supporting these languages, C++ support is also well under way, and mainline +Clang is able to parse the libstdc++ 4.2 headers and even codegen simple apps. +If you are interested in Clang C++ support or any other Clang feature, we +strongly encourage you to get involved on the Clang front-end mailing +list.

    + +

    In the LLVM 2.6 time-frame, the Clang team has made many improvements:

    + +
      +
    • C and Objective-C support are now considered production quality.
    • +
    • AuroraUX, FreeBSD and OpenBSD are now supported.
    • +
    • Most of Objective-C 2.0 is now supported with the GNU runtime.
    • +
    • Many many bugs are fixed and lots of features have been added.
    • +
    +
    + + + + +
    + +

    Previously announced in the 2.4 and 2.5 LLVM releases, the Clang project also +includes an early stage static source code analysis tool for automatically finding bugs +in C and Objective-C programs. The tool performs checks to find +bugs that occur on a specific path within a program.

    + +

    In the LLVM 2.6 time-frame, the analyzer core has undergone several important +improvements and cleanups and now includes a new Checker interface that +is intended to eventually serve as a basis for domain-specific checks. Further, +in addition to generating HTML files for reporting analysis results, the +analyzer can now also emit bug reports in a structured XML format that is +intended to be easily readable by other programs.

    + +

    The set of checks performed by the static analyzer continues to expand, and +future plans for the tool include full source-level inter-procedural analysis +and deeper checks such as buffer overrun detection. There are many opportunities +to extend and enhance the static analyzer, and anyone interested in working on +this project is encouraged to get involved!

    + +
    + + + + +
    +

    +The VMKit project is an implementation of +a JVM and a CLI Virtual Machine (Microsoft .NET is an +implementation of the CLI) using LLVM for static and just-in-time +compilation.

    + +

    +VMKit version 0.26 builds with LLVM 2.6 and you can find it on its +web page. The release includes +bug fixes, cleanup and new features. The major changes are:

    + +
      + +
    • A new llcj tool to generate shared libraries or executables of Java + files.
    • +
    • Cooperative garbage collection.
    • +
    • Fast subtype checking (paper from Click et al [JGI'02]).
    • +
    • Implementation of a two-word header for Java objects instead of the original + three-word header.
    • +
    • Better Java specification-compliance: division by zero checks, stack + overflow checks, finalization and references support.
    • + +
    +
    + + + + + +
    +

    +The new LLVM compiler-rt project +is a simple library that provides an implementation of the low-level +target-specific hooks required by code generation and other runtime components. +For example, when compiling for a 32-bit target, converting a double to a 64-bit +unsigned integer is compiled into a runtime call to the "__fixunsdfdi" +function. The compiler-rt library provides highly optimized implementations of +this and other low-level routines (some are 3x faster than the equivalent +libgcc routines).

    + +

    +All of the code in the compiler-rt project is available under the standard LLVM +License, a "BSD-style" license.

    + +
    + + + + +
    +

    +The new LLVM KLEE project is a symbolic +execution framework for programs in LLVM bitcode form. KLEE tries to +symbolically evaluate "all" paths through the application and records state +transitions that lead to fault states. This allows it to construct testcases +that lead to faults and can even be used to verify algorithms. For more +details, please see the OSDI 2008 paper about +KLEE.

    + +
    + + + + +
    +

    +The goal of DragonEgg is to make +gcc-4.5 act like llvm-gcc without requiring any gcc modifications whatsoever. +DragonEgg is a shared library (dragonegg.so) +that is loaded by gcc at runtime. It uses the new gcc plugin architecture to +disable the GCC optimizers and code generators, and schedule the LLVM optimizers +and code generators (or direct output of LLVM IR) instead. Currently only Linux +and Darwin are supported, and only on x86-32 and x86-64. It should be easy to +add additional unix-like architectures and other processor families. In theory +it should be possible to use DragonEgg +with any language supported by gcc, however only C and Fortran work well for the +moment. Ada and C++ work to some extent, while Java, Obj-C and Obj-C++ are so +far entirely untested. Since gcc-4.5 has not yet been released, neither has +DragonEgg. To build +DragonEgg you will need to check out the +development versions of gcc, +llvm and +DragonEgg from their respective +subversion repositories, and follow the instructions in the +DragonEgg README. +

    + +
    + + + + + +
    +

    +The LLVM Machine Code (MC) Toolkit project is a (very early) effort to build +better tools for dealing with machine code, object file formats, etc. The idea +is to be able to generate most of the target specific details of assemblers and +disassemblers from existing LLVM target .td files (with suitable enhancements), +and to build infrastructure for reading and writing common object file formats. +One of the first deliverables is to build a full assembler and integrate it into +the compiler, which is predicted to substantially reduce compile time in some +scenarios. +

    + +

    In the LLVM 2.6 timeframe, the MC framework has grown to the point where it +can reliably parse and pretty print (with some encoding information) a +darwin/x86 .s file successfully, and has the very early phases of a Mach-O +assembler in progress. Beyond the MC framework itself, major refactoring of the +LLVM code generator has started. The idea is to make the code generator reason +about the code it is producing in a much more semantic way, rather than a +textual way. For example, the code generator now uses MCSection objects to +represent section assignments, instead of text strings that print to .section +directives.

    + +

    MC is an early and ongoing project that will hopefully continue to lead to +many improvements in the code generator and build infrastructure useful for many +other situations. +

    + +
    + + + + + + +
    + +

    An exciting aspect of LLVM is that it is used as an enabling technology for + a lot of other language and tools projects. This section lists some of the + projects that have already been updated to work with LLVM 2.6.

    +
    + + + + + +
    +

    Rubinius is an environment +for running Ruby code which strives to write as much of the core class +implementation in Ruby as possible. Combined with a bytecode interpreting VM, it +uses LLVM to optimize and compile ruby code down to machine code. Techniques +such as type feedback, method inlining, and uncommon traps are all used to +remove dynamism from ruby execution and increase performance.

    + +

    Since LLVM 2.5, Rubinius has made several major leaps forward, implementing +a counter based JIT, type feedback and speculative method inlining. +

    + +
    + + + + +
    + +

    +MacRuby is an implementation of Ruby on top of +core Mac OS X technologies, such as the Objective-C common runtime and garbage +collector and the CoreFoundation framework. It is principally developed by +Apple and aims at enabling the creation of full-fledged Mac OS X applications. +

    + +

    +MacRuby uses LLVM for optimization passes, JIT and AOT compilation of Ruby +expressions. It also uses zero-cost DWARF exceptions to implement Ruby exception +handling.

    + +
    + + + +
    +Pure +
    + +
    +

    +Pure +is an algebraic/functional programming language based on term rewriting. +Programs are collections of equations which are used to evaluate expressions in +a symbolic fashion. Pure offers dynamic typing, eager and lazy evaluation, +lexical closures, a hygienic macro system (also based on term rewriting), +built-in list and matrix support (including list and matrix comprehensions) and +an easy-to-use C interface. The interpreter uses LLVM as a backend to + JIT-compile Pure programs to fast native code.

    + +

    Pure versions 0.31 and later have been tested and are known to work with +LLVM 2.6 (and continue to work with older LLVM releases >= 2.3 as well). +

    +
    + + + + + +
    +

    +LDC is an implementation of +the D Programming Language using the LLVM optimizer and code generator. +The LDC project works great with the LLVM 2.6 release. General improvements in +this +cycle have included new inline asm constraint handling, better debug info +support, general bug fixes and better x86-64 support. This has allowed +some major improvements in LDC, getting it much closer to being as +fully featured as the original DMD compiler from DigitalMars. +

    +
    + + + + +
    +

    +Roadsend PHP (rphp) is an open +source implementation of the PHP programming +language that uses LLVM for its optimizer, JIT and static compiler. This is a +reimplementation of an earlier project that is now based on LLVM.

    +
    + + + + +
    +

    +Unladen Swallow is a +branch of Python intended to be fully +compatible and significantly faster. It uses LLVM's optimization passes and JIT +compiler.

    +
    + + + + +
    +

    +LLVM-Lua uses LLVM to add JIT +and static compiling support to the Lua VM. Lua bytecode is analyzed to +remove type checks, then LLVM is used to compile the bytecode down to machine +code.

    +
    + + + + +
    +

    +IcedTea provides a +harness to build OpenJDK using only free software build tools and to provide +replacements for the not-yet free parts of OpenJDK. One of the extensions that +IcedTea provides is a new JIT compiler named Shark which uses LLVM +to provide native code generation without introducing processor-dependent +code. +

    +
    + + + + + + + +
    + +

    This release includes a huge number of bug fixes, performance tweaks and +minor improvements. Some of the major improvements and new features are listed +in this section. +

    + +
    + + + + +
    + +

    LLVM 2.6 includes several major new capabilities:

    + +
      +
    • New compiler-rt, KLEE + and machine code toolkit sub-projects.
    • +
    • Debug information now includes line numbers when optimizations are enabled. + This allows statistical sampling tools like OProfile and Shark to map + samples back to source lines.
    • +
    • LLVM now includes new experimental backends to support the MSP430, SystemZ + and BlackFin architectures.
    • +
    • LLVM supports a new Gold Linker Plugin which + enables support for transparent + link-time optimization on ELF targets when used with the Gold binutils + linker.
    • +
    • LLVM now supports doing optimization and code generation on multiple + threads. Please see the LLVM + Programmer's Manual for more information.
    • +
    • LLVM now has experimental support for embedded + metadata in LLVM IR, though the implementation is not guaranteed to be + final and the .bc file format may change in future releases. Debug info + does not yet use this format in LLVM 2.6.
    • +
    + +
    + + + + +
    +

    LLVM IR has several new features for better support of new targets and that +expose new optimization opportunities:

    + +
      +
    • The add, sub and mul + instructions have been split into integer and floating point versions (like + divide and remainder), introducing new fadd, fsub, + and fmul instructions.
    • +
    • The add, sub and mul + instructions now support optional "nsw" and "nuw" bits which indicate that + the operation is guaranteed to not overflow (in the signed or + unsigned case, respectively). This gives the optimizer more information and + can be used for things like C signed integer values, which are undefined on + overflow.
    • +
    • The sdiv instruction now supports an + optional "exact" flag which indicates that the result of the division is + guaranteed to have a remainder of zero. This is useful for optimizing pointer + subtraction in C.
    • +
    • The getelementptr instruction now + supports arbitrary integer index values for array/pointer indices. This + allows for better code generation on 16-bit pointer targets like PIC16.
    • +
    • The getelementptr instruction now + supports an "inbounds" optimization hint that tells the optimizer that the + pointer is guaranteed to be within its allocated object.
    • +
    • LLVM now support a series of new linkage types for global values which allow + for better optimization and new capabilities: +
        +
      • linkonce_odr and + weak_odr have the same linkage + semantics as the non-"odr" linkage types. The difference is that these + linkage types indicate that all definitions of the specified function + are guaranteed to have the same semantics. This allows inlining + templates functions in C++ but not inlining weak functions in C, + which previously both got the same linkage type.
      • +
      • available_externally + is a new linkage type that gives the optimizer visibility into the + definition of a function (allowing inlining and side effect analysis) + but that does not cause code to be generated. This allows better + optimization of "GNU inline" functions, extern templates, etc.
      • +
      • linker_private is a + new linkage type (which is only useful on Mac OS X) that is used for + some metadata generation and other obscure things.
      • +
    • +
    • Finally, target-specific intrinsics can now return multiple values, which + is useful for modeling target operations with multiple results.
    • +
    + +
    + + + + +
    + +

    In addition to a large array of minor performance tweaks and bug fixes, this +release includes a few major enhancements and additions to the optimizers:

    + +
      + +
    • The Scalar Replacement of Aggregates + pass has many improvements that allow it to better promote vector unions, + variables which are memset, and much more strange code that can happen to + do bitfield accesses to register operations. An interesting change is that + it now produces "unusual" integer sizes (like i1704) in some cases and lets + other optimizers clean things up.
    • +
    • The Loop Strength Reduction pass now + promotes small integer induction variables to 64-bit on 64-bit targets, + which provides a major performance boost for much numerical code. It also + promotes shorts to int on 32-bit hosts, etc. LSR now also analyzes pointer + expressions (e.g. getelementptrs), as well as integers.
    • +
    • The GVN pass now eliminates partial + redundancies of loads in simple cases.
    • +
    • The Inliner now reuses stack space when + inlining similar arrays from multiple callees into one caller.
    • +
    • LLVM includes a new experimental Static Single Information (SSI) + construction pass.
    • + +
    + +
    + + + + + +
    + +
      +
    • LLVM has a new "EngineBuilder" class which makes it more obvious how to + set up and configure an ExecutionEngine (a JIT or interpreter).
    • +
    • The JIT now supports generating more than 16M of code.
    • +
    • When configured with --with-oprofile, the JIT can now inform + OProfile about JIT'd code, allowing OProfile to get line number and function + name information for JIT'd functions.
    • +
    • When "libffi" is available, the LLVM interpreter now uses it, which supports + calling almost arbitrary external (natively compiled) functions.
    • +
    • Clients of the JIT can now register a 'JITEventListener' object to receive + callbacks when the JIT emits or frees machine code. The OProfile support + uses this mechanism.
    • +
    + +
    + + + + +
    + +

    We have put a significant amount of work into the code generator +infrastructure, which allows us to implement more aggressive algorithms and make +it run faster:

    + +
      + +
    • The llc -asm-verbose option (exposed from llvm-gcc as -dA + and clang as -fverbose-asm or -dA) now adds a lot of + useful information in comments to + the generated .s file. This information includes location information (if + built with -g) and loop nest information.
    • +
    • The code generator now supports a new MachineVerifier pass which is useful + for finding bugs in targets and codegen passes.
    • +
    • The Machine LICM is now enabled by default. It hoists instructions out of + loops (such as constant pool loads, loads from read-only stubs, vector + constant synthesization code, etc.) and is currently configured to only do + so when the hoisted operation can be rematerialized.
    • +
    • The Machine Sinking pass is now enabled by default. This pass moves + side-effect free operations down the CFG so that they are executed on fewer + paths through a function.
    • +
    • The code generator now performs "stack slot coloring" of register spills, + which allows spill slots to be reused. This leads to smaller stack frames + in cases where there are lots of register spills.
    • +
    • The register allocator has many improvements to take better advantage of + commutable operations, various spiller peephole optimizations, and can now + coalesce cross-register-class copies.
    • +
    • Tblgen now supports multiclass inheritance and a number of new string and + list operations like !(subst), !(foreach), !car, + !cdr, !null, !if, !cast. + These make the .td files more expressive and allow more aggressive factoring + of duplication across instruction patterns.
    • +
    • Target-specific intrinsics can now be added without having to hack VMCore to + add them. This makes it easier to maintain out-of-tree targets.
    • +
    • The instruction selector is better at propagating information about values + (such as whether they are sign/zero extended etc.) across basic block + boundaries.
    • +
    • The SelectionDAG datastructure has new nodes for representing buildvector + and vector shuffle operations. This + makes operations and pattern matching more efficient and easier to get + right.
    • +
    • The Prolog/Epilog Insertion Pass now has experimental support for performing + the "shrink wrapping" optimization, which moves spills and reloads around in + the CFG to avoid doing saves on paths that don't need them.
    • +
    • LLVM includes new experimental support for writing ELF .o files directly + from the compiler. It works well for many simple C testcases, but doesn't + support exception handling, debug info, inline assembly, etc.
    • +
    • Targets can now specify register allocation hints through + MachineRegisterInfo::setRegAllocationHint. A regalloc hint consists + of hint type and physical register number. A hint type of zero specifies a + register allocation preference. Other hint type values are target specific + which are resolved by TargetRegisterInfo::ResolveRegAllocHint. An + example is the ARM target which uses register hints to request that the + register allocator provide an even / odd register pair to two virtual + registers.
    • +
    +
    + + + + +
    +

    New features of the X86 target include: +

    + +
      + +
    • SSE 4.2 builtins are now supported.
    • +
    • GCC-compatible soft float modes are now supported, which are typically used + by OS kernels.
    • +
    • X86-64 now models implicit zero extensions better, which allows the code + generator to remove a lot of redundant zexts. It also models the 8-bit "H" + registers as subregs, which allows them to be used in some tricky + situations.
    • +
    • X86-64 now supports the "local exec" and "initial exec" thread local storage + model.
    • +
    • The vector forms of the icmp and fcmp instructions now select to efficient + SSE operations.
    • +
    • Support for the win64 calling conventions have improved. The primary + missing feature is support for varargs function definitions. It seems to + work well for many win64 JIT purposes.
    • +
    • The X86 backend has preliminary support for mapping address spaces to segment + register references. This allows you to write GS or FS relative memory + accesses directly in LLVM IR for cases where you know exactly what you're + doing (such as in an OS kernel). There are some known problems with this + support, but it works in simple cases.
    • +
    • The X86 code generator has been refactored to move all global variable + reference logic to one place + (X86Subtarget::ClassifyGlobalReference) which + makes it easier to reason about.
    • + +
    + +
    + + + + +
    +

    New features of the PIC16 target include: +

    + +
      +
    • Support for floating-point, indirect function calls, and + passing/returning aggregate types to functions. +
    • The code generator is able to generate debug info into output COFF files. +
    • Support for placing an object into a specific section or at a specific + address in memory.
    • +
    + +

    Things not yet supported:

    + +
      +
    • Variable arguments.
    • +
    • Interrupts/programs.
    • +
    + +
    + + + + +
    +

    New features of the ARM target include: +

    + +
      + +
    • Preliminary support for processors, such as the Cortex-A8 and Cortex-A9, +that implement version v7-A of the ARM architecture. The ARM backend now +supports both the Thumb2 and Advanced SIMD (Neon) instruction sets.
    • + +
    • The AAPCS-VFP "hard float" calling conventions are also supported with the +-float-abi=hard flag.
    • + +
    • The ARM calling convention code is now tblgen generated instead of resorting + to C++ code.
    • +
    + +

    These features are still somewhat experimental +and subject to change. The Neon intrinsics, in particular, may change in future +releases of LLVM. ARMv7 support has progressed a lot on top of tree since 2.6 +branched.

    + + +
    + + + + +
    +

    New features of other targets include: +

    + +
      +
    • Mips now supports O32 Calling Convention.
    • +
    • Many improvements to the 32-bit PowerPC SVR4 ABI (used on powerpc-linux) + support, lots of bugs fixed.
    • +
    • Added support for the 64-bit PowerPC SVR4 ABI (used on powerpc64-linux). + Needs more testing.
    • +
    + +
    + + + + +
    + +

    This release includes a number of new APIs that are used internally, which + may also be useful for external clients. +

    + +
      +
    • New + PrettyStackTrace class allows crashes of llvm tools (and applications + that integrate them) to provide more detailed indication of what the + compiler was doing at the time of the crash (e.g. running a pass). + At the top level for each LLVM tool, it includes the command line arguments. +
    • +
    • New StringRef + and Twine classes + make operations on character ranges and + string concatenation to be more efficient. StringRef is just a const + char* with a length, Twine is a light-weight rope.
    • +
    • LLVM has new WeakVH, AssertingVH and CallbackVH + classes, which make it easier to write LLVM IR transformations. WeakVH + is automatically drops to null when the referenced Value is deleted, + and is updated across a replaceAllUsesWith operation. + AssertingVH aborts the program if the + referenced value is destroyed while it is being referenced. CallbackVH + is a customizable class for handling value references. See ValueHandle.h + for more information.
    • +
    • The new 'Triple + ' class centralizes a lot of logic that reasons about target + triples.
    • +
    • The new ' + llvm_report_error()' set of APIs allows tools to embed the LLVM + optimizer and backend and recover from previously unrecoverable errors.
    • +
    • LLVM has new abstractions for atomic operations + and reader/writer + locks.
    • +
    • LLVM has new + SourceMgr and SMLoc classes which implement caret + diagnostics and basic include stack processing for simple parsers. It is + used by tablegen, llvm-mc, the .ll parser and FileCheck.
    • +
    + + +
    + + + + +
    +

    Other miscellaneous features include:

    + +
      +
    • LLVM now includes a new internal 'FileCheck' tool which allows + writing much more accurate regression tests that run faster. Please see the + FileCheck section of the Testing + Guide for more information.
    • +
    • LLVM profile information support has been significantly improved to produce +correct use counts, and has support for edge profiling with reduced runtime +overhead. Combined, the generated profile information is both more correct and +imposes about half as much overhead (2.6. from 12% to 6% overhead on SPEC +CPU2000).
    • +
    • The C bindings (in the llvm/include/llvm-c directory) include many newly + supported APIs.
    • +
    • LLVM 2.6 includes a brand new experimental LLVM bindings to the Ada2005 + programming language.
    • + +
    • The LLVMC driver has several new features: +
        +
      • Dynamic plugins now work on Windows.
      • +
      • New option property: init. Makes possible to provide default values for + options defined in plugins (interface to cl::init).
      • +
      • New example: Skeleton, shows how to create a standalone LLVMC-based + driver.
      • +
      • New example: mcc16, a driver for the PIC16 toolchain.
      • +
      +
    • + +
    + +
    + + + + + +
    + +

    If you're already an LLVM user or developer with out-of-tree changes based +on LLVM 2.5, this section lists some "gotchas" that you may run into upgrading +from the previous release.

    + +
      +
    • The Itanium (IA64) backend has been removed. It was not actively supported + and had bitrotted.
    • +
    • The BigBlock register allocator has been removed, it had also bitrotted.
    • +
    • The C Backend (-march=c) is no longer considered part of the LLVM release +criteria. We still want it to work, but no one is maintaining it and it lacks +support for arbitrary precision integers and other important IR features.
    • + +
    • All LLVM tools now default to overwriting their output file, behaving more + like standard unix tools. Previously, this only happened with the '-f' + option.
    • +
    • LLVM build now builds all libraries as .a files instead of some + libraries as relinked .o files. This requires some APIs like + InitializeAllTargets.h. +
    • +
    + + +

    In addition, many APIs have changed in this release. Some of the major LLVM +API changes are:

    + +
      +
    • All uses of hash_set and hash_map have been removed from + the LLVM tree and the wrapper headers have been removed.
    • +
    • The llvm/Streams.h and DOUT member of Debug.h have been removed. The + llvm::Ostream class has been completely removed and replaced with + uses of raw_ostream.
    • +
    • LLVM's global uniquing tables for Types and Constants have + been privatized into members of an LLVMContext. A number of APIs + now take an LLVMContext as a parameter. To smooth the transition + for clients that will only ever use a single context, the new + getGlobalContext() API can be used to access a default global + context which can be passed in any and all cases where a context is + required. +
    • The getABITypeSize methods are now called getAllocSize.
    • +
    • The Add, Sub and Mul operators are no longer + overloaded for floating-point types. Floating-point addition, subtraction + and multiplication are now represented with new operators FAdd, + FSub and FMul. In the IRBuilder API, + CreateAdd, CreateSub, CreateMul and + CreateNeg should only be used for integer arithmetic now; + CreateFAdd, CreateFSub, CreateFMul and + CreateFNeg should now be used for floating-point arithmetic.
    • +
    • The DynamicLibrary class can no longer be constructed, its functionality has + moved to static member functions.
    • +
    • raw_fd_ostream's constructor for opening a given filename now + takes an extra Force argument. If Force is set to + false, an error will be reported if a file with the given name + already exists. If Force is set to true, the file will + be silently truncated (which is the behavior before this flag was + added).
    • +
    • SCEVHandle no longer exists, because reference counting is no + longer done for SCEV* objects, instead const SCEV* + should be used.
    • + +
    • Many APIs, notably llvm::Value, now use the StringRef +and Twine classes instead of passing const char* +or std::string, as described in +the Programmer's Manual. Most +clients should be unaffected by this transition, unless they are used to +Value::getName() returning a string. Here are some tips on updating to +2.6: +
        +
      • getNameStr() is still available, and matches the old + behavior. Replacing getName() calls with this is an safe option, + although more efficient alternatives are now possible.
      • + +
      • If you were just relying on getName() being able to be sent to + a std::ostream, consider migrating + to llvm::raw_ostream.
      • + +
      • If you were using getName().c_str() to get a const + char* pointer to the name, you can use getName().data(). + Note that this string (as before), may not be the entire name if the + name contains embedded null characters.
      • + +
      • If you were using operator + on the result of getName() and + treating the result as an std::string, you can either + use Twine::str to get the result as an std::string, or + could move to a Twine based design.
      • + +
      • isName() should be replaced with comparison + against getName() (this is now efficient). +
      +
    • + +
    • The registration interfaces for backend Targets has changed (what was +previously TargetMachineRegistry). For backend authors, see the Writing An LLVM Backend +guide. For clients, the notable API changes are: +
        +
      • TargetMachineRegistry has been renamed + to TargetRegistry.
      • + +
      • Clients should move to using the TargetRegistry::lookupTarget() + function to find targets.
      • +
      +
    • +
    + +
    + + + + + + + +
    + +

    LLVM is known to work on the following platforms:

    + +
      +
    • Intel and AMD machines (IA32, X86-64, AMD64, EMT-64) running Red Hat + Linux, Fedora Core, FreeBSD and AuroraUX (and probably other unix-like + systems).
    • +
    • PowerPC and X86-based Mac OS X systems, running 10.3 and above in 32-bit + and 64-bit modes.
    • +
    • Intel and AMD machines running on Win32 using MinGW libraries (native).
    • +
    • Intel and AMD machines running on Win32 with the Cygwin libraries (limited + support is available for native builds with Visual C++).
    • +
    • Sun x86 and AMD64 machines running Solaris 10, OpenSolaris 0906.
    • +
    • Alpha-based machines running Debian GNU/Linux.
    • +
    + +

    The core LLVM infrastructure uses GNU autoconf to adapt itself +to the machine and operating system on which it is built. However, minor +porting may be required to get LLVM to work on new platforms. We welcome your +portability patches and reports of successful builds or error messages.

    + +
    + + + + + +
    + +

    This section contains significant known problems with the LLVM system, +listed by component. If you run into a problem, please check the LLVM bug database and submit a bug if +there isn't already one.

    + +
      +
    • The llvm-gcc bootstrap will fail with some versions of binutils (e.g. 2.15) + with a message of "Error: can not do 8 + byte pc-relative relocation" when building C++ code. We intend to + fix this on mainline, but a workaround for 2.6 is to upgrade to binutils + 2.17 or later.
    • + +
    • LLVM will not correctly compile on Solaris and/or OpenSolaris +using the stock GCC 3.x.x series 'out the box', +See: Broken versions of GCC and other tools. +However, A Modern GCC Build +for x86/x86-64 has been made available from the third party AuroraUX Project +that has been meticulously tested for bootstrapping LLVM & Clang.
    • +
    + +
    + + + + +
    + +

    The following components of this LLVM release are either untested, known to +be broken or unreliable, or are in early development. These components should +not be relied on, and bugs should not be filed against them, but they may be +useful to some people. In particular, if you would like to work on one of these +components, please contact us on the LLVMdev list.

    + +
      +
    • The MSIL, Alpha, SPU, MIPS, PIC16, Blackfin, MSP430 and SystemZ backends are + experimental.
    • +
    • The llc "-filetype=asm" (the default) is the only + supported value for this option. The ELF writer is experimental.
    • +
    • The implementation of Andersen's Alias Analysis has many known bugs.
    • +
    + +
    + + + + +
    + +
      +
    • The X86 backend does not yet support + all inline assembly that uses the X86 + floating point stack. It supports the 'f' and 't' constraints, but not + 'u'.
    • +
    • The X86 backend generates inefficient floating point code when configured + to generate code for systems that don't have SSE2.
    • +
    • Win64 code generation wasn't widely tested. Everything should work, but we + expect small issues to happen. Also, llvm-gcc cannot build the mingw64 + runtime currently due + to several + bugs and due to lack of support for + the + 'u' inline assembly constraint and for X87 floating point inline assembly.
    • +
    • The X86-64 backend does not yet support the LLVM IR instruction + va_arg. Currently, the llvm-gcc and front-ends support variadic + argument constructs on X86-64 by lowering them manually.
    • +
    + +
    + + + + +
    + +
      +
    • The Linux PPC32/ABI support needs testing for the interpreter and static +compilation, and lacks support for debug information.
    • +
    + +
    + + + + +
    + +
      +
    • Support for the Advanced SIMD (Neon) instruction set is still incomplete +and not well tested. Some features may not work at all, and the code quality +may be poor in some cases.
    • +
    • Thumb mode works only on ARMv6 or higher processors. On sub-ARMv6 +processors, thumb programs can crash or produce wrong +results (PR1388).
    • +
    • Compilation for ARM Linux OABI (old ABI) is supported but not fully tested. +
    • +
    + +
    + + + + +
    + +
      +
    • The SPARC backend only supports the 32-bit SPARC ABI (-m32); it does not + support the 64-bit SPARC ABI (-m64).
    • +
    + +
    + + + + +
    + +
      +
    • 64-bit MIPS targets are not supported yet.
    • +
    + +
    + + + + +
    + +
      + +
    • On 21164s, some rare FP arithmetic sequences which may trap do not have the +appropriate nops inserted to ensure restartability.
    • + +
    +
    + + + + +
    + + + +
    + + + + + +
    + +

    The only major language feature of GCC not supported by llvm-gcc is + the __builtin_apply family of builtins. However, some extensions + are only supported on some targets. For example, trampolines are only + supported on some targets (these are used when you take the address of a + nested function).

    + +

    If you run into GCC extensions which are not supported, please let us know. +

    + +
    + + + + +
    + +

    The C++ front-end is considered to be fully +tested and works for a number of non-trivial programs, including LLVM +itself, Qt, Mozilla, etc.

    + +
      +
    • Exception handling works well on the X86 and PowerPC targets. Currently + only Linux and Darwin targets are supported (both 32 and 64 bit).
    • +
    + +
    + + + + +
    +
      +
    • Fortran support generally works, but there are still several unresolved bugs + in Bugzilla. Please see the + tools/gfortran component for details.
    • +
    +
    + + + + +
    +The llvm-gcc 4.2 Ada compiler works fairly well; however, this is not a mature +technology, and problems should be expected. +
      +
    • The Ada front-end currently only builds on X86-32. This is mainly due +to lack of trampoline support (pointers to nested functions) on other platforms. +However, it also fails to build on X86-64 +which does support trampolines.
    • +
    • The Ada front-end fails to bootstrap. +This is due to lack of LLVM support for setjmp/longjmp style +exception handling, which is used internally by the compiler. +Workaround: configure with --disable-bootstrap.
    • +
    • The c380004, c393010 +and cxg2021 ACATS tests fail +(c380004 also fails with gcc-4.2 mainline). +If the compiler is built with checks disabled then c393010 +causes the compiler to go into an infinite loop, using up all system memory.
    • +
    • Some GCC specific Ada tests continue to crash the compiler.
    • +
    • The -E binder option (exception backtraces) +does not work and will result in programs +crashing if an exception is raised. Workaround: do not use -E.
    • +
    • Only discrete types are allowed to start +or finish at a non-byte offset in a record. Workaround: do not pack records +or use representation clauses that result in a field of a non-discrete type +starting or finishing in the middle of a byte.
    • +
    • The lli interpreter considers +'main' as generated by the Ada binder to be invalid. +Workaround: hand edit the file to use pointers for argv and +envp rather than integers.
    • +
    • The -fstack-check option is +ignored.
    • +
    +
    + + + + +
    + +

    The Llvm.Linkage module is broken, and has incorrect values. Only +Llvm.Linkage.External, Llvm.Linkage.Available_externally, and +Llvm.Linkage.Link_once will be correct. If you need any of the other linkage +modes, you'll have to write an external C library in order to expose the +functionality. This has been fixed in the trunk.

    +
    + + + + + +
    + +

    A wide variety of additional information is available on the LLVM web page, in particular in the documentation section. The web page also +contains versions of the API documentation which is up-to-date with the +Subversion version of the source code. +You can access versions of these documents specific to this release by going +into the "llvm/doc/" directory in the LLVM tree.

    + +

    If you have any questions or comments about LLVM, please feel free to contact +us via the mailing +lists.

    + +
    + + + +
    +
    + Valid CSS + Valid HTML 4.01 + + LLVM Compiler Infrastructure
    + Last modified: $Date$ +
    + + + diff --git a/libclamav/c++/llvm/docs/SourceLevelDebugging.html b/libclamav/c++/llvm/docs/SourceLevelDebugging.html new file mode 100644 index 000000000..c4055753e --- /dev/null +++ b/libclamav/c++/llvm/docs/SourceLevelDebugging.html @@ -0,0 +1,1719 @@ + + + + + Source Level Debugging with LLVM + + + + +
    Source Level Debugging with LLVM
    + + + + + +
    + + +A leafy and green bug eater +
    + +
    +

    Written by Chris Lattner + and Jim Laskey

    +
    + + + + + + +
    + +

    This document is the central repository for all information pertaining to + debug information in LLVM. It describes the actual format + that the LLVM debug information takes, which is useful for those + interested in creating front-ends or dealing directly with the information. + Further, this document provides specific examples of what debug information + for C/C++.

    + +
    + + + + +
    + +

    The idea of the LLVM debugging information is to capture how the important + pieces of the source-language's Abstract Syntax Tree map onto LLVM code. + Several design aspects have shaped the solution that appears here. The + important ones are:

    + +
      +
    • Debugging information should have very little impact on the rest of the + compiler. No transformations, analyses, or code generators should need to + be modified because of debugging information.
    • + +
    • LLVM optimizations should interact in well-defined and + easily described ways with the debugging information.
    • + +
    • Because LLVM is designed to support arbitrary programming languages, + LLVM-to-LLVM tools should not need to know anything about the semantics of + the source-level-language.
    • + +
    • Source-level languages are often widely different from one another. + LLVM should not put any restrictions of the flavor of the source-language, + and the debugging information should work with any language.
    • + +
    • With code generator support, it should be possible to use an LLVM compiler + to compile a program to native machine code and standard debugging + formats. This allows compatibility with traditional machine-code level + debuggers, like GDB or DBX.
    • +
    + +

    The approach used by the LLVM implementation is to use a small set + of intrinsic functions to define a + mapping between LLVM program objects and the source-level objects. The + description of the source-level program is maintained in LLVM metadata + in an implementation-defined format + (the C/C++ front-end currently uses working draft 7 of + the DWARF 3 + standard).

    + +

    When a program is being debugged, a debugger interacts with the user and + turns the stored debug information into source-language specific information. + As such, a debugger must be aware of the source-language, and is thus tied to + a specific language or family of languages.

    + +
    + + + + +
    + +

    The role of debug information is to provide meta information normally + stripped away during the compilation process. This meta information provides + an LLVM user a relationship between generated code and the original program + source code.

    + +

    Currently, debug information is consumed by the DwarfWriter to produce dwarf + information used by the gdb debugger. Other targets could use the same + information to produce stabs or other debug forms.

    + +

    It would also be reasonable to use debug information to feed profiling tools + for analysis of generated code, or, tools for reconstructing the original + source from generated code.

    + +

    TODO - expound a bit more.

    + +
    + + + + +
    + +

    An extremely high priority of LLVM debugging information is to make it + interact well with optimizations and analysis. In particular, the LLVM debug + information provides the following guarantees:

    + +
      +
    • LLVM debug information always provides information to accurately read + the source-level state of the program, regardless of which LLVM + optimizations have been run, and without any modification to the + optimizations themselves. However, some optimizations may impact the + ability to modify the current state of the program with a debugger, such + as setting program variables, or calling functions that have been + deleted.
    • + +
    • LLVM optimizations gracefully interact with debugging information. If + they are not aware of debug information, they are automatically disabled + as necessary in the cases that would invalidate the debug info. This + retains the LLVM features, making it easy to write new + transformations.
    • + +
    • As desired, LLVM optimizations can be upgraded to be aware of the LLVM + debugging information, allowing them to update the debugging information + as they perform aggressive optimizations. This means that, with effort, + the LLVM optimizers could optimize debug code just as well as non-debug + code.
    • + +
    • LLVM debug information does not prevent many important optimizations from + happening (for example inlining, basic block reordering/merging/cleanup, + tail duplication, etc), further reducing the amount of the compiler that + eventually is "aware" of debugging information.
    • + +
    • LLVM debug information is automatically optimized along with the rest of + the program, using existing facilities. For example, duplicate + information is automatically merged by the linker, and unused information + is automatically removed.
    • +
    + +

    Basically, the debug information allows you to compile a program with + "-O0 -g" and get full debug information, allowing you to arbitrarily + modify the program as it executes from a debugger. Compiling a program with + "-O3 -g" gives you full debug information that is always available + and accurate for reading (e.g., you get accurate stack traces despite tail + call elimination and inlining), but you might lose the ability to modify the + program and call functions where were optimized out of the program, or + inlined away completely.

    + +

    LLVM test suite provides a + framework to test optimizer's handling of debugging information. It can be + run like this:

    + +
    +
    +% cd llvm/projects/test-suite/MultiSource/Benchmarks  # or some other level
    +% make TEST=dbgopt
    +
    +
    + +

    This will test impact of debugging information on optimization passes. If + debugging information influences optimization passes then it will be reported + as a failure. See TestingGuide for more + information on LLVM test infrastructure and how to run various tests.

    + +
    + + + + + +
    + +

    LLVM debugging information has been carefully designed to make it possible + for the optimizer to optimize the program and debugging information without + necessarily having to know anything about debugging information. In + particular, te use of metadadta avoids duplicated dubgging information from + the beginning, and the global dead code elimination pass automatically + deletes debugging information for a function if it decides to delete the + function.

    + +

    To do this, most of the debugging information (descriptors for types, + variables, functions, source files, etc) is inserted by the language + front-end in the form of LLVM metadata.

    + +

    Debug information is designed to be agnostic about the target debugger and + debugging information representation (e.g. DWARF/Stabs/etc). It uses a + generic pass to decode the information that represents variables, types, + functions, namespaces, etc: this allows for arbitrary source-language + semantics and type-systems to be used, as long as there is a module + written for the target debugger to interpret the information.

    + +

    To provide basic functionality, the LLVM debugger does have to make some + assumptions about the source-level language being debugged, though it keeps + these to a minimum. The only common features that the LLVM debugger assumes + exist are source files, + and program objects. These abstract + objects are used by a debugger to form stack traces, show information about + local variables, etc.

    + +

    This section of the documentation first describes the representation aspects + common to any source-language. The next section + describes the data layout conventions used by the C and C++ front-ends.

    + +
    + + + + +
    + +

    In consideration of the complexity and volume of debug information, LLVM + provides a specification for well formed debug descriptors.

    + +

    Consumers of LLVM debug information expect the descriptors for program + objects to start in a canonical format, but the descriptors can include + additional information appended at the end that is source-language + specific. All LLVM debugging information is versioned, allowing backwards + compatibility in the case that the core structures need to change in some + way. Also, all debugging information objects start with a tag to indicate + what type of object it is. The source-language is allowed to define its own + objects, by using unreserved tag numbers. We recommend using with tags in + the range 0x1000 through 0x2000 (there is a defined enum DW_TAG_user_base = + 0x1000.)

    + +

    The fields of debug descriptors used internally by LLVM + are restricted to only the simple data types int, uint, + bool, float, double, mdstring and + mdnode.

    + +
    +
    +!1 = metadata !{
    +  uint,   ;; A tag
    +  ...
    +}
    +
    +
    + +

    The first field of a descriptor is always an + uint containing a tag value identifying the content of the + descriptor. The remaining fields are specific to the descriptor. The values + of tags are loosely bound to the tag values of DWARF information entries. + However, that does not restrict the use of the information supplied to DWARF + targets. To facilitate versioning of debug information, the tag is augmented + with the current debug version (LLVMDebugVersion = 7 << 16 or 0x70000 or + 458752.)

    + +

    The details of the various descriptors follow.

    + +
    + + + + +
    + +
    +
    +!0 = metadata !{
    +  i32,       ;; Tag = 17 + LLVMDebugVersion 
    +             ;; (DW_TAG_compile_unit)
    +  i32,       ;; Unused field. 
    +  i32,       ;; DWARF language identifier (ex. DW_LANG_C89) 
    +  metadata,  ;; Source file name
    +  metadata,  ;; Source file directory (includes trailing slash)
    +  metadata   ;; Producer (ex. "4.0.1 LLVM (LLVM research group)")
    +  i1,        ;; True if this is a main compile unit. 
    +  i1,        ;; True if this is optimized.
    +  metadata,  ;; Flags
    +  i32        ;; Runtime version
    +}
    +
    +
    + +

    These descriptors contain a source language ID for the file (we use the DWARF + 3.0 ID numbers, such as DW_LANG_C89, DW_LANG_C_plus_plus, + DW_LANG_Cobol74, etc), three strings describing the filename, + working directory of the compiler, and an identifier string for the compiler + that produced it.

    + +

    Compile unit descriptors provide the root context for objects declared in a + specific source file. Global variables and top level functions would be + defined using this context. Compile unit descriptors also provide context + for source line correspondence.

    + +

    Each input file is encoded as a separate compile unit in LLVM debugging + information output. However, many target specific tool chains prefer to + encode only one compile unit in an object file. In this situation, the LLVM + code generator will include debugging information entities in the compile + unit that is marked as main compile unit. The code generator accepts maximum + one main compile unit per module. If a module does not contain any main + compile unit then the code generator will emit multiple compile units in the + output object file.

    + +
    + + + + +
    + +
    +
    +!1 = metadata !{
    +  i32,      ;; Tag = 52 + LLVMDebugVersion 
    +            ;; (DW_TAG_variable)
    +  i32,      ;; Unused field.
    +  metadata, ;; Reference to context descriptor
    +  metadata, ;; Name
    +  metadata, ;; Display name (fully qualified C++ name)
    +  metadata, ;; MIPS linkage name (for C++)
    +  metadata, ;; Reference to compile unit where defined
    +  i32,      ;; Line number where defined
    +  metadata, ;; Reference to type descriptor
    +  i1,       ;; True if the global is local to compile unit (static)
    +  i1,       ;; True if the global is defined in the compile unit (not extern)
    +  {  }*     ;; Reference to the global variable
    +}
    +
    +
    + +

    These descriptors provide debug information about globals variables. The +provide details such as name, type and where the variable is defined.

    + +
    + + + + +
    + +
    +
    +!2 = metadata !{
    +  i32,      ;; Tag = 46 + LLVMDebugVersion
    +            ;; (DW_TAG_subprogram)
    +  i32,      ;; Unused field.
    +  metadata, ;; Reference to context descriptor
    +  metadata, ;; Name
    +  metadata, ;; Display name (fully qualified C++ name)
    +  metadata, ;; MIPS linkage name (for C++)
    +  metadata, ;; Reference to compile unit where defined
    +  i32,      ;; Line number where defined
    +  metadata, ;; Reference to type descriptor
    +  i1,       ;; True if the global is local to compile unit (static)
    +  i1        ;; True if the global is defined in the compile unit (not extern)
    +}
    +
    +
    + +

    These descriptors provide debug information about functions, methods and + subprograms. They provide details such as name, return types and the source + location where the subprogram is defined.

    + +
    + + + + +
    + +
    +
    +!3 = metadata !{
    +  i32,     ;; Tag = 13 + LLVMDebugVersion (DW_TAG_lexical_block)
    +  metadata ;; Reference to context descriptor
    +}
    +
    +
    + +

    These descriptors provide debug information about nested blocks within a + subprogram. The array of member descriptors is used to define local + variables and deeper nested blocks.

    + +
    + + + + +
    + +
    +
    +!4 = metadata !{
    +  i32,      ;; Tag = 36 + LLVMDebugVersion 
    +            ;; (DW_TAG_base_type)
    +  metadata, ;; Reference to context (typically a compile unit)
    +  metadata, ;; Name (may be "" for anonymous types)
    +  metadata, ;; Reference to compile unit where defined (may be NULL)
    +  i32,      ;; Line number where defined (may be 0)
    +  i64,      ;; Size in bits
    +  i64,      ;; Alignment in bits
    +  i64,      ;; Offset in bits
    +  i32,      ;; Flags
    +  i32       ;; DWARF type encoding
    +}
    +
    +
    + +

    These descriptors define primitive types used in the code. Example int, bool + and float. The context provides the scope of the type, which is usually the + top level. Since basic types are not usually user defined the compile unit + and line number can be left as NULL and 0. The size, alignment and offset + are expressed in bits and can be 64 bit values. The alignment is used to + round the offset when embedded in a + composite type (example to keep float + doubles on 64 bit boundaries.) The offset is the bit offset if embedded in + a composite type.

    + +

    The type encoding provides the details of the type. The values are typically + one of the following:

    + +
    +
    +DW_ATE_address       = 1
    +DW_ATE_boolean       = 2
    +DW_ATE_float         = 4
    +DW_ATE_signed        = 5
    +DW_ATE_signed_char   = 6
    +DW_ATE_unsigned      = 7
    +DW_ATE_unsigned_char = 8
    +
    +
    + +
    + + + + +
    + +
    +
    +!5 = metadata !{
    +  i32,      ;; Tag (see below)
    +  metadata, ;; Reference to context
    +  metadata, ;; Name (may be "" for anonymous types)
    +  metadata, ;; Reference to compile unit where defined (may be NULL)
    +  i32,      ;; Line number where defined (may be 0)
    +  i32,      ;; Size in bits
    +  i32,      ;; Alignment in bits
    +  i32,      ;; Offset in bits
    +  metadata  ;; Reference to type derived from
    +}
    +
    +
    + +

    These descriptors are used to define types derived from other types. The +value of the tag varies depending on the meaning. The following are possible +tag values:

    + +
    +
    +DW_TAG_formal_parameter = 5
    +DW_TAG_member           = 13
    +DW_TAG_pointer_type     = 15
    +DW_TAG_reference_type   = 16
    +DW_TAG_typedef          = 22
    +DW_TAG_const_type       = 38
    +DW_TAG_volatile_type    = 53
    +DW_TAG_restrict_type    = 55
    +
    +
    + +

    DW_TAG_member is used to define a member of + a composite type + or subprogram. The type of the member is + the derived + type. DW_TAG_formal_parameter is used to define a member which + is a formal argument of a subprogram.

    + +

    DW_TAG_typedef is used to provide a name for the derived type.

    + +

    DW_TAG_pointer_type,DW_TAG_reference_type, + DW_TAG_const_type, DW_TAG_volatile_type + and DW_TAG_restrict_type are used to qualify + the derived type.

    + +

    Derived type location can be determined + from the compile unit and line number. The size, alignment and offset are + expressed in bits and can be 64 bit values. The alignment is used to round + the offset when embedded in a composite + type (example to keep float doubles on 64 bit boundaries.) The offset is + the bit offset if embedded in a composite + type.

    + +

    Note that the void * type is expressed as a + llvm.dbg.derivedtype.type with tag of DW_TAG_pointer_type + and NULL derived type.

    + +
    + + + + +
    + +
    +
    +!6 = metadata !{
    +  i32,      ;; Tag (see below)
    +  metadata, ;; Reference to context
    +  metadata, ;; Name (may be "" for anonymous types)
    +  metadata, ;; Reference to compile unit where defined (may be NULL)
    +  i32,      ;; Line number where defined (may be 0)
    +  i64,      ;; Size in bits
    +  i64,      ;; Alignment in bits
    +  i64,      ;; Offset in bits
    +  i32,      ;; Flags
    +  metadata, ;; Reference to type derived from
    +  metadata, ;; Reference to array of member descriptors
    +  i32       ;; Runtime languages
    +}
    +
    +
    + +

    These descriptors are used to define types that are composed of 0 or more +elements. The value of the tag varies depending on the meaning. The following +are possible tag values:

    + +
    +
    +DW_TAG_array_type       = 1
    +DW_TAG_enumeration_type = 4
    +DW_TAG_structure_type   = 19
    +DW_TAG_union_type       = 23
    +DW_TAG_vector_type      = 259
    +DW_TAG_subroutine_type  = 21
    +DW_TAG_inheritance      = 28
    +
    +
    + +

    The vector flag indicates that an array type is a native packed vector.

    + +

    The members of array types (tag = DW_TAG_array_type) or vector types + (tag = DW_TAG_vector_type) are subrange + descriptors, each representing the range of subscripts at that level of + indexing.

    + +

    The members of enumeration types (tag = DW_TAG_enumeration_type) are + enumerator descriptors, each representing + the definition of enumeration value for the set.

    + +

    The members of structure (tag = DW_TAG_structure_type) or union (tag + = DW_TAG_union_type) types are any one of + the basic, + derived + or composite type descriptors, each + representing a field member of the structure or union.

    + +

    For C++ classes (tag = DW_TAG_structure_type), member descriptors + provide information about base classes, static members and member + functions. If a member is a derived type + descriptor and has a tag of DW_TAG_inheritance, then the type + represents a base class. If the member of is + a global variable descriptor then it + represents a static member. And, if the member is + a subprogram descriptor then it represents + a member function. For static members and member + functions, getName() returns the members link or the C++ mangled + name. getDisplayName() the simplied version of the name.

    + +

    The first member of subroutine (tag = DW_TAG_subroutine_type) type + elements is the return type for the subroutine. The remaining elements are + the formal arguments to the subroutine.

    + +

    Composite type location can be + determined from the compile unit and line number. The size, alignment and + offset are expressed in bits and can be 64 bit values. The alignment is used + to round the offset when embedded in + a composite type (as an example, to keep + float doubles on 64 bit boundaries.) The offset is the bit offset if embedded + in a composite type.

    + +
    + + + + +
    + +
    +
    +%llvm.dbg.subrange.type = type {
    +  i32,    ;; Tag = 33 + LLVMDebugVersion (DW_TAG_subrange_type)
    +  i64,    ;; Low value
    +  i64     ;; High value
    +}
    +
    +
    + +

    These descriptors are used to define ranges of array subscripts for an array + composite type. The low value defines + the lower bounds typically zero for C/C++. The high value is the upper + bounds. Values are 64 bit. High - low + 1 is the size of the array. If low + == high the array will be unbounded.

    + +
    + + + + +
    + +
    +
    +!6 = metadata !{
    +  i32,      ;; Tag = 40 + LLVMDebugVersion 
    +            ;; (DW_TAG_enumerator)
    +  metadata, ;; Name
    +  i64       ;; Value
    +}
    +
    +
    + +

    These descriptors are used to define members of an + enumeration composite type, it + associates the name to the value.

    + +
    + + + + +
    + +
    +
    +!7 = metadata !{
    +  i32,      ;; Tag (see below)
    +  metadata, ;; Context
    +  metadata, ;; Name
    +  metadata, ;; Reference to compile unit where defined
    +  i32,      ;; Line number where defined
    +  metadata  ;; Type descriptor
    +}
    +
    +
    + +

    These descriptors are used to define variables local to a sub program. The + value of the tag depends on the usage of the variable:

    + +
    +
    +DW_TAG_auto_variable   = 256
    +DW_TAG_arg_variable    = 257
    +DW_TAG_return_variable = 258
    +
    +
    + +

    An auto variable is any variable declared in the body of the function. An + argument variable is any variable that appears as a formal argument to the + function. A return variable is used to track the result of a function and + has no source correspondent.

    + +

    The context is either the subprogram or block where the variable is defined. + Name the source variable name. Compile unit and line indicate where the + variable was defined. Type descriptor defines the declared type of the + variable.

    + +
    + + + + +
    + +

    LLVM uses several intrinsic functions (name prefixed with "llvm.dbg") to + provide debug information at various points in generated code.

    + +
    + + + + +
    +
    +  void %llvm.dbg.declare( { } *, metadata )
    +
    + +

    This intrinsic provides information about a local element (ex. variable.) The + first argument is the alloca for the variable, cast to a { }*. The + second argument is + the %llvm.dbg.variable containing + the description of the variable.

    + +
    + + + + +
    +

    In many languages, the local variables in functions can have their lifetime + or scope limited to a subset of a function. In the C family of languages, + for example, variables are only live (readable and writable) within the + source block that they are defined in. In functional languages, values are + only readable after they have been defined. Though this is a very obvious + concept, it is also non-trivial to model in LLVM, because it has no notion of + scoping in this sense, and does not want to be tied to a language's scoping + rules.

    + +

    In order to handle this, the LLVM debug format uses the metadata attached + with llvm instructions to encode line nuber and scoping information. + Consider the following C fragment, for example:

    + +
    +
    +1.  void foo() {
    +2.    int X = 21;
    +3.    int Y = 22;
    +4.    {
    +5.      int Z = 23;
    +6.      Z = X;
    +7.    }
    +8.    X = Y;
    +9.  }
    +
    +
    + +

    Compiled to LLVM, this function would be represented like this:

    + +
    +
    +nounwind ssp {
    +entry:
    +  %X = alloca i32, align 4                        ;  [#uses=4]
    +  %Y = alloca i32, align 4                        ;  [#uses=4]
    +  %Z = alloca i32, align 4                        ;  [#uses=3]
    +  %0 = bitcast i32* %X to { }*                    ; <{ }*> [#uses=1]
    +  call void @llvm.dbg.declare({ }* %0, metadata !0), !dbg !7
    +  store i32 21, i32* %X, !dbg !8
    +  %1 = bitcast i32* %Y to { }*                    ; <{ }*> [#uses=1]
    +  call void @llvm.dbg.declare({ }* %1, metadata !9), !dbg !10
    +  store i32 22, i32* %Y, !dbg !11
    +  %2 = bitcast i32* %Z to { }*                    ; <{ }*> [#uses=1]
    +  call void @llvm.dbg.declare({ }* %2, metadata !12), !dbg !14
    +  store i32 23, i32* %Z, !dbg !15
    +  %tmp = load i32* %X, !dbg !16                   ;  [#uses=1]
    +  %tmp1 = load i32* %Y, !dbg !16                  ;  [#uses=1]
    +  %add = add nsw i32 %tmp, %tmp1, !dbg !16        ;  [#uses=1]
    +  store i32 %add, i32* %Z, !dbg !16
    +  %tmp2 = load i32* %Y, !dbg !17                  ;  [#uses=1]
    +  store i32 %tmp2, i32* %X, !dbg !17
    +  ret void, !dbg !18
    +}
    +
    +declare void @llvm.dbg.declare({ }*, metadata) nounwind readnone
    +
    +!0 = metadata !{i32 459008, metadata !1, metadata !"X", 
    +                metadata !3, i32 2, metadata !6}; [ DW_TAG_auto_variable ]
    +!1 = metadata !{i32 458763, metadata !2}; [DW_TAG_lexical_block ]
    +!2 = metadata !{i32 458798, i32 0, metadata !3, metadata !"foo", metadata !"foo", 
    +               metadata !"foo", metadata !3, i32 1, metadata !4, 
    +               i1 false, i1 true}; [DW_TAG_subprogram ]
    +!3 = metadata !{i32 458769, i32 0, i32 12, metadata !"foo.c", 
    +                metadata !"/private/tmp", metadata !"clang 1.1", i1 true, 
    +                i1 false, metadata !"", i32 0}; [DW_TAG_compile_unit ]
    +!4 = metadata !{i32 458773, metadata !3, metadata !"", null, i32 0, i64 0, i64 0, 
    +                i64 0, i32 0, null, metadata !5, i32 0}; [DW_TAG_subroutine_type ]
    +!5 = metadata !{null}
    +!6 = metadata !{i32 458788, metadata !3, metadata !"int", metadata !3, i32 0, 
    +                i64 32, i64 32, i64 0, i32 0, i32 5}; [DW_TAG_base_type ]
    +!7 = metadata !{i32 2, i32 7, metadata !1, null}
    +!8 = metadata !{i32 2, i32 3, metadata !1, null}
    +!9 = metadata !{i32 459008, metadata !1, metadata !"Y", metadata !3, i32 3, 
    +                metadata !6}; [ DW_TAG_auto_variable ]
    +!10 = metadata !{i32 3, i32 7, metadata !1, null}
    +!11 = metadata !{i32 3, i32 3, metadata !1, null}
    +!12 = metadata !{i32 459008, metadata !13, metadata !"Z", metadata !3, i32 5, 
    +                 metadata !6}; [ DW_TAG_auto_variable ]
    +!13 = metadata !{i32 458763, metadata !1}; [DW_TAG_lexical_block ]
    +!14 = metadata !{i32 5, i32 9, metadata !13, null}
    +!15 = metadata !{i32 5, i32 5, metadata !13, null}
    +!16 = metadata !{i32 6, i32 5, metadata !13, null}
    +!17 = metadata !{i32 8, i32 3, metadata !1, null}
    +!18 = metadata !{i32 9, i32 1, metadata !2, null}
    +
    +
    + +

    This example illustrates a few important details about the LLVM debugging + information. In particular, it shows how the llvm.dbg.declare intrinsic + and location information, attached with an instruction, are applied + together to allow a debugger to analyze the relationship between statements, + variable definitions, and the code used to implement the function.

    + +
    +
     
    +     call void @llvm.dbg.declare({ }* %0, metadata !0), !dbg !7   
    +   
    +
    +

    This first intrinsic + %llvm.dbg.declare + encodes debugging information for variable X. The metadata, + !dbg !7 attached with the intrinsic provides scope information for + the variable X.

    +
    +
    +     !7 = metadata !{i32 2, i32 7, metadata !1, null}
    +     !1 = metadata !{i32 458763, metadata !2}; [DW_TAG_lexical_block ]
    +     !2 = metadata !{i32 458798, i32 0, metadata !3, metadata !"foo", 
    +                     metadata !"foo", metadata !"foo", metadata !3, i32 1, 
    +                     metadata !4, i1 false, i1 true}; [DW_TAG_subprogram ]   
    +   
    +
    + +

    Here !7 is a metadata providing location information. It has four + fields : line number, column number, scope and original scope. The original + scope represents inline location if this instruction is inlined inside + a caller. It is null otherwise. In this example scope is encoded by + !1. !1 represents a lexical block inside the scope + !2, where !2 is a + subprogram descriptor. + This way the location information attched with the intrinsics indicates + that the variable X is declared at line number 2 at a function level + scope in function foo.

    + +

    Now lets take another example.

    + +
    +
     
    +     call void @llvm.dbg.declare({ }* %2, metadata !12), !dbg !14
    +   
    +
    +

    This intrinsic + %llvm.dbg.declare + encodes debugging information for variable Z. The metadata, + !dbg !14 attached with the intrinsic provides scope information for + the variable Z.

    +
    +
    +     !13 = metadata !{i32 458763, metadata !1}; [DW_TAG_lexical_block ]
    +     !14 = metadata !{i32 5, i32 9, metadata !13, null}
    +   
    +
    + +

    Here !14 indicates that Z is declaread at line number 5, + column number 9 inside a lexical scope !13. This lexical scope + itself resides inside lexcial scope !1 described above.

    + +

    The scope information attached with each instruction provides a straight + forward way to find instructions covered by a scope.

    +
    + + + + + +
    + +

    The C and C++ front-ends represent information about the program in a format + that is effectively identical + to DWARF 3.0 in + terms of information content. This allows code generators to trivially + support native debuggers by generating standard dwarf information, and + contains enough information for non-dwarf targets to translate it as + needed.

    + +

    This section describes the forms used to represent C and C++ programs. Other + languages could pattern themselves after this (which itself is tuned to + representing programs in the same way that DWARF 3 does), or they could + choose to provide completely different forms if they don't fit into the DWARF + model. As support for debugging information gets added to the various LLVM + source-language front-ends, the information used should be documented + here.

    + +

    The following sections provide examples of various C/C++ constructs and the + debug information that would best describe those constructs.

    + +
    + + + + +
    + +

    Given the source files MySource.cpp and MyHeader.h located + in the directory /Users/mine/sources, the following code:

    + +
    +
    +#include "MyHeader.h"
    +
    +int main(int argc, char *argv[]) {
    +  return 0;
    +}
    +
    +
    + +

    a C/C++ front-end would generate the following descriptors:

    + +
    +
    +...
    +;;
    +;; Define the compile unit for the source file "/Users/mine/sources/MySource.cpp".
    +;;
    +!3 = metadata !{
    +  i32 458769,    ;; Tag
    +  i32 0,         ;; Unused
    +  i32 4,         ;; Language Id
    +  metadata !"MySource.cpp", 
    +  metadata !"/Users/mine/sources", 
    +  metadata !"4.2.1 (Based on Apple Inc. build 5649) (LLVM build 00)", 
    +  i1 true,       ;; Main Compile Unit
    +  i1 false,      ;; Optimized compile unit
    +  metadata !"",  ;; Compiler flags
    +  i32 0}         ;; Runtime version
    +
    +;;
    +;; Define the compile unit for the header file "/Users/mine/sources/MyHeader.h".
    +;;
    +!1 = metadata !{
    +  i32 458769,    ;; Tag
    +  i32 0,         ;; Unused
    +  i32 4,         ;; Language Id
    +  metadata !"MyHeader.h", 
    +  metadata !"/Users/mine/sources", 
    +  metadata !"4.2.1 (Based on Apple Inc. build 5649) (LLVM build 00)", 
    +  i1 false,      ;; Main Compile Unit
    +  i1 false,      ;; Optimized compile unit
    +  metadata !"",  ;; Compiler flags
    +  i32 0}         ;; Runtime version
    +
    +...
    +
    +
    + +
    + + + + +
    + +

    Given an integer global variable declared as follows:

    + +
    +
    +int MyGlobal = 100;
    +
    +
    + +

    a C/C++ front-end would generate the following descriptors:

    + +
    +
    +;;
    +;; Define the global itself.
    +;;
    +%MyGlobal = global int 100
    +...
    +;;
    +;; List of debug info of globals
    +;;
    +!llvm.dbg.gv = !{!0}
    +
    +;;
    +;; Define the global variable descriptor.  Note the reference to the global
    +;; variable anchor and the global variable itself.
    +;;
    +!0 = metadata !{
    +  i32 458804,              ;; Tag
    +  i32 0,                   ;; Unused
    +  metadata !1,             ;; Context
    +  metadata !"MyGlobal",    ;; Name
    +  metadata !"MyGlobal",    ;; Display Name
    +  metadata !"MyGlobal",    ;; Linkage Name
    +  metadata !1,             ;; Compile Unit
    +  i32 1,                   ;; Line Number
    +  metadata !2,             ;; Type
    +  i1 false,                ;; Is a local variable
    +  i1 true,                 ;; Is this a definition
    +  i32* @MyGlobal           ;; The global variable
    +}
    +
    +;;
    +;; Define the basic type of 32 bit signed integer.  Note that since int is an
    +;; intrinsic type the source file is NULL and line 0.
    +;;    
    +!2 = metadata !{
    +  i32 458788,              ;; Tag
    +  metadata !1,             ;; Context
    +  metadata !"int",         ;; Name
    +  metadata !1,             ;; Compile Unit
    +  i32 0,                   ;; Line number
    +  i64 32,                  ;; Size in Bits
    +  i64 32,                  ;; Align in Bits
    +  i64 0,                   ;; Offset in Bits
    +  i32 0,                   ;; Flags
    +  i32 5                    ;; Encoding
    +}
    +
    +
    +
    + +
    + + + + +
    + +

    Given a function declared as follows:

    + +
    +
    +int main(int argc, char *argv[]) {
    +  return 0;
    +}
    +
    +
    + +

    a C/C++ front-end would generate the following descriptors:

    + +
    +
    +;;
    +;; Define the anchor for subprograms.  Note that the second field of the
    +;; anchor is 46, which is the same as the tag for subprograms
    +;; (46 = DW_TAG_subprogram.)
    +;;
    +!0 = metadata !{
    +  i32 458798,        ;; Tag
    +  i32 0,             ;; Unused
    +  metadata !1,       ;; Context
    +  metadata !"main",  ;; Name
    +  metadata !"main",  ;; Display name
    +  metadata !"main",  ;; Linkage name
    +  metadata !1,       ;; Compile unit
    +  i32 1,             ;; Line number
    +  metadata !2,       ;; Type
    +  i1 false,          ;; Is local 
    +  i1 true            ;; Is definition
    +}
    +;;
    +;; Define the subprogram itself.
    +;;
    +define i32 @main(i32 %argc, i8** %argv) {
    +...
    +}
    +
    +
    + +
    + + + + +
    + +

    The following are the basic type descriptors for C/C++ core types:

    + +
    + + +
    + bool +
    + +
    + +
    +
    +!2 = metadata !{
    +  i32 458788,        ;; Tag
    +  metadata !1,       ;; Context
    +  metadata !"bool",  ;; Name
    +  metadata !1,       ;; Compile Unit
    +  i32 0,             ;; Line number
    +  i64 8,             ;; Size in Bits
    +  i64 8,             ;; Align in Bits
    +  i64 0,             ;; Offset in Bits
    +  i32 0,             ;; Flags
    +  i32 2              ;; Encoding
    +}
    +
    +
    + +
    + + +
    + char +
    + +
    + +
    +
    +!2 = metadata !{
    +  i32 458788,        ;; Tag
    +  metadata !1,       ;; Context
    +  metadata !"char",  ;; Name
    +  metadata !1,       ;; Compile Unit
    +  i32 0,             ;; Line number
    +  i64 8,             ;; Size in Bits
    +  i64 8,             ;; Align in Bits
    +  i64 0,             ;; Offset in Bits
    +  i32 0,             ;; Flags
    +  i32 6              ;; Encoding
    +}
    +
    +
    + +
    + + + + +
    + +
    +
    +!2 = metadata !{
    +  i32 458788,        ;; Tag
    +  metadata !1,       ;; Context
    +  metadata !"unsigned char", 
    +  metadata !1,       ;; Compile Unit
    +  i32 0,             ;; Line number
    +  i64 8,             ;; Size in Bits
    +  i64 8,             ;; Align in Bits
    +  i64 0,             ;; Offset in Bits
    +  i32 0,             ;; Flags
    +  i32 8              ;; Encoding
    +}
    +
    +
    + +
    + + +
    + short +
    + +
    + +
    +
    +!2 = metadata !{
    +  i32 458788,        ;; Tag
    +  metadata !1,       ;; Context
    +  metadata !"short int",
    +  metadata !1,       ;; Compile Unit
    +  i32 0,             ;; Line number
    +  i64 16,            ;; Size in Bits
    +  i64 16,            ;; Align in Bits
    +  i64 0,             ;; Offset in Bits
    +  i32 0,             ;; Flags
    +  i32 5              ;; Encoding
    +}
    +
    +
    + +
    + + + + +
    + +
    +
    +!2 = metadata !{
    +  i32 458788,        ;; Tag
    +  metadata !1,       ;; Context
    +  metadata !"short unsigned int",
    +  metadata !1,       ;; Compile Unit
    +  i32 0,             ;; Line number
    +  i64 16,            ;; Size in Bits
    +  i64 16,            ;; Align in Bits
    +  i64 0,             ;; Offset in Bits
    +  i32 0,             ;; Flags
    +  i32 7              ;; Encoding
    +}
    +
    +
    + +
    + + +
    + int +
    + +
    + +
    +
    +!2 = metadata !{
    +  i32 458788,        ;; Tag
    +  metadata !1,       ;; Context
    +  metadata !"int",   ;; Name
    +  metadata !1,       ;; Compile Unit
    +  i32 0,             ;; Line number
    +  i64 32,            ;; Size in Bits
    +  i64 32,            ;; Align in Bits
    +  i64 0,             ;; Offset in Bits
    +  i32 0,             ;; Flags
    +  i32 5              ;; Encoding
    +}
    +
    + +
    + + + + +
    + +
    +
    +!2 = metadata !{
    +  i32 458788,        ;; Tag
    +  metadata !1,       ;; Context
    +  metadata !"unsigned int",
    +  metadata !1,       ;; Compile Unit
    +  i32 0,             ;; Line number
    +  i64 32,            ;; Size in Bits
    +  i64 32,            ;; Align in Bits
    +  i64 0,             ;; Offset in Bits
    +  i32 0,             ;; Flags
    +  i32 7              ;; Encoding
    +}
    +
    +
    + +
    + + + + +
    + +
    +
    +!2 = metadata !{
    +  i32 458788,        ;; Tag
    +  metadata !1,       ;; Context
    +  metadata !"long long int",
    +  metadata !1,       ;; Compile Unit
    +  i32 0,             ;; Line number
    +  i64 64,            ;; Size in Bits
    +  i64 64,            ;; Align in Bits
    +  i64 0,             ;; Offset in Bits
    +  i32 0,             ;; Flags
    +  i32 5              ;; Encoding
    +}
    +
    +
    + +
    + + + + +
    + +
    +
    +!2 = metadata !{
    +  i32 458788,        ;; Tag
    +  metadata !1,       ;; Context
    +  metadata !"long long unsigned int",
    +  metadata !1,       ;; Compile Unit
    +  i32 0,             ;; Line number
    +  i64 64,            ;; Size in Bits
    +  i64 64,            ;; Align in Bits
    +  i64 0,             ;; Offset in Bits
    +  i32 0,             ;; Flags
    +  i32 7              ;; Encoding
    +}
    +
    +
    + +
    + + +
    + float +
    + +
    + +
    +
    +!2 = metadata !{
    +  i32 458788,        ;; Tag
    +  metadata !1,       ;; Context
    +  metadata !"float",
    +  metadata !1,       ;; Compile Unit
    +  i32 0,             ;; Line number
    +  i64 32,            ;; Size in Bits
    +  i64 32,            ;; Align in Bits
    +  i64 0,             ;; Offset in Bits
    +  i32 0,             ;; Flags
    +  i32 4              ;; Encoding
    +}
    +
    +
    + +
    + + +
    + double +
    + +
    + +
    +
    +!2 = metadata !{
    +  i32 458788,        ;; Tag
    +  metadata !1,       ;; Context
    +  metadata !"double",;; Name
    +  metadata !1,       ;; Compile Unit
    +  i32 0,             ;; Line number
    +  i64 64,            ;; Size in Bits
    +  i64 64,            ;; Align in Bits
    +  i64 0,             ;; Offset in Bits
    +  i32 0,             ;; Flags
    +  i32 4              ;; Encoding
    +}
    +
    +
    + +
    + + + + +
    + +

    Given the following as an example of C/C++ derived type:

    + +
    +
    +typedef const int *IntPtr;
    +
    +
    + +

    a C/C++ front-end would generate the following descriptors:

    + +
    +
    +;;
    +;; Define the typedef "IntPtr".
    +;;
    +!2 = metadata !{
    +  i32 458774,          ;; Tag
    +  metadata !1,         ;; Context
    +  metadata !"IntPtr",  ;; Name
    +  metadata !3,         ;; Compile unit
    +  i32 0,               ;; Line number
    +  i64 0,               ;; Size in bits
    +  i64 0,               ;; Align in bits
    +  i64 0,               ;; Offset in bits
    +  i32 0,               ;; Flags
    +  metadata !4          ;; Derived From type
    +}
    +
    +;;
    +;; Define the pointer type.
    +;;
    +!4 = metadata !{
    +  i32 458767,          ;; Tag
    +  metadata !1,         ;; Context
    +  metadata !"",        ;; Name
    +  metadata !1,         ;; Compile unit
    +  i32 0,               ;; Line number
    +  i64 64,              ;; Size in bits
    +  i64 64,              ;; Align in bits
    +  i64 0,               ;; Offset in bits
    +  i32 0,               ;; Flags
    +  metadata !5          ;; Derived From type
    +}
    +;;
    +;; Define the const type.
    +;;
    +!5 = metadata !{
    +  i32 458790,          ;; Tag
    +  metadata !1,         ;; Context
    +  metadata !"",        ;; Name
    +  metadata !1,         ;; Compile unit
    +  i32 0,               ;; Line number
    +  i64 32,              ;; Size in bits
    +  i64 32,              ;; Align in bits
    +  i64 0,               ;; Offset in bits
    +  i32 0,               ;; Flags
    +  metadata !6          ;; Derived From type
    +}
    +;;
    +;; Define the int type.
    +;;
    +!6 = metadata !{
    +  i32 458788,          ;; Tag
    +  metadata !1,         ;; Context
    +  metadata !"int",     ;; Name
    +  metadata !1,         ;; Compile unit
    +  i32 0,               ;; Line number
    +  i64 32,              ;; Size in bits
    +  i64 32,              ;; Align in bits
    +  i64 0,               ;; Offset in bits
    +  i32 0,               ;; Flags
    +  5                    ;; Encoding
    +}
    +
    +
    + +
    + + + + +
    + +

    Given the following as an example of C/C++ struct type:

    + +
    +
    +struct Color {
    +  unsigned Red;
    +  unsigned Green;
    +  unsigned Blue;
    +};
    +
    +
    + +

    a C/C++ front-end would generate the following descriptors:

    + +
    +
    +;;
    +;; Define basic type for unsigned int.
    +;;
    +!5 = metadata !{
    +  i32 458788,        ;; Tag
    +  metadata !1,       ;; Context
    +  metadata !"unsigned int",
    +  metadata !1,       ;; Compile Unit
    +  i32 0,             ;; Line number
    +  i64 32,            ;; Size in Bits
    +  i64 32,            ;; Align in Bits
    +  i64 0,             ;; Offset in Bits
    +  i32 0,             ;; Flags
    +  i32 7              ;; Encoding
    +}
    +;;
    +;; Define composite type for struct Color.
    +;;
    +!2 = metadata !{
    +  i32 458771,        ;; Tag
    +  metadata !1,       ;; Context
    +  metadata !"Color", ;; Name
    +  metadata !1,       ;; Compile unit
    +  i32 1,             ;; Line number
    +  i64 96,            ;; Size in bits
    +  i64 32,            ;; Align in bits
    +  i64 0,             ;; Offset in bits
    +  i32 0,             ;; Flags
    +  null,              ;; Derived From
    +  metadata !3,       ;; Elements
    +  i32 0              ;; Runtime Language
    +}
    +
    +;;
    +;; Define the Red field.
    +;;
    +!4 = metadata !{
    +  i32 458765,        ;; Tag
    +  metadata !1,       ;; Context
    +  metadata !"Red",   ;; Name
    +  metadata !1,       ;; Compile Unit
    +  i32 2,             ;; Line number
    +  i64 32,            ;; Size in bits
    +  i64 32,            ;; Align in bits
    +  i64 0,             ;; Offset in bits
    +  i32 0,             ;; Flags
    +  metadata !5        ;; Derived From type
    +}
    +
    +;;
    +;; Define the Green field.
    +;;
    +!6 = metadata !{
    +  i32 458765,        ;; Tag
    +  metadata !1,       ;; Context
    +  metadata !"Green", ;; Name
    +  metadata !1,       ;; Compile Unit
    +  i32 3,             ;; Line number
    +  i64 32,            ;; Size in bits
    +  i64 32,            ;; Align in bits
    +  i64 32,             ;; Offset in bits
    +  i32 0,             ;; Flags
    +  metadata !5        ;; Derived From type
    +}
    +
    +;;
    +;; Define the Blue field.
    +;;
    +!7 = metadata !{
    +  i32 458765,        ;; Tag
    +  metadata !1,       ;; Context
    +  metadata !"Blue",  ;; Name
    +  metadata !1,       ;; Compile Unit
    +  i32 4,             ;; Line number
    +  i64 32,            ;; Size in bits
    +  i64 32,            ;; Align in bits
    +  i64 64,             ;; Offset in bits
    +  i32 0,             ;; Flags
    +  metadata !5        ;; Derived From type
    +}
    +
    +;;
    +;; Define the array of fields used by the composite type Color.
    +;;
    +!3 = metadata !{metadata !4, metadata !6, metadata !7}
    +
    +
    + +
    + + + + +
    + +

    Given the following as an example of C/C++ enumeration type:

    + +
    +
    +enum Trees {
    +  Spruce = 100,
    +  Oak = 200,
    +  Maple = 300
    +};
    +
    +
    + +

    a C/C++ front-end would generate the following descriptors:

    + +
    +
    +;;
    +;; Define composite type for enum Trees
    +;;
    +!2 = metadata !{
    +  i32 458756,        ;; Tag
    +  metadata !1,       ;; Context
    +  metadata !"Trees", ;; Name
    +  metadata !1,       ;; Compile unit
    +  i32 1,             ;; Line number
    +  i64 32,            ;; Size in bits
    +  i64 32,            ;; Align in bits
    +  i64 0,             ;; Offset in bits
    +  i32 0,             ;; Flags
    +  null,              ;; Derived From type
    +  metadata !3,       ;; Elements
    +  i32 0              ;; Runtime language
    +}
    +
    +;;
    +;; Define the array of enumerators used by composite type Trees.
    +;;
    +!3 = metadata !{metadata !4, metadata !5, metadata !6}
    +
    +;;
    +;; Define Spruce enumerator.
    +;;
    +!4 = metadata !{i32 458792, metadata !"Spruce", i64 100}
    +
    +;;
    +;; Define Oak enumerator.
    +;;
    +!5 = metadata !{i32 458792, metadata !"Oak", i64 200}
    +
    +;;
    +;; Define Maple enumerator.
    +;;
    +!6 = metadata !{i32 458792, metadata !"Maple", i64 300}
    +
    +
    +
    + +
    + + + +
    +
    + Valid CSS + Valid HTML 4.01 + + Chris Lattner
    + LLVM Compiler Infrastructure
    + Last modified: $Date$ +
    + + + diff --git a/libclamav/c++/llvm/docs/SystemLibrary.html b/libclamav/c++/llvm/docs/SystemLibrary.html new file mode 100644 index 000000000..0289a5541 --- /dev/null +++ b/libclamav/c++/llvm/docs/SystemLibrary.html @@ -0,0 +1,319 @@ + + + + System Library + + + + +
    System Library
    + + +
    +

    Written by Reid Spencer

    +
    + + + + +
    +

    This document provides some details on LLVM's System Library, located in + the source at lib/System and include/llvm/System. The + library's purpose is to shield LLVM from the differences between operating + systems for the few services LLVM needs from the operating system. Much of + LLVM is written using portability features of standard C++. However, in a few + areas, system dependent facilities are needed and the System Library is the + wrapper around those system calls.

    +

    By centralizing LLVM's use of operating system interfaces, we make it + possible for the LLVM tool chain and runtime libraries to be more easily + ported to new platforms since (theoretically) only lib/System needs + to be ported. This library also unclutters the rest of LLVM from #ifdef use + and special cases for specific operating systems. Such uses are replaced + with simple calls to the interfaces provided in include/llvm/System. +

    +

    Note that the System Library is not intended to be a complete operating + system wrapper (such as the Adaptive Communications Environment (ACE) or + Apache Portable Runtime (APR)), but only provides the functionality necessary + to support LLVM. +

    The System Library was written by Reid Spencer who formulated the + design based on similar work originating from the eXtensible Programming + System (XPS). Several people helped with the effort; especially, + Jeff Cohen and Henrik Bach on the Win32 port.

    +
    + + + +
    +

    In order to keep LLVM portable, LLVM developers should adhere to a set of + portability rules associated with the System Library. Adherence to these rules + should help the System Library achieve its goal of shielding LLVM from the + variations in operating system interfaces and doing so efficiently. The + following sections define the rules needed to fulfill this objective.

    +
    + + + +
    +

    Except in lib/System, no LLVM source code should directly + #include a system header. Care has been taken to remove all such + #includes from LLVM while lib/System was being + developed. Specifically this means that header files like "unistd.h", + "windows.h", "stdio.h", and "string.h" are forbidden to be included by LLVM + source code outside the implementation of lib/System.

    +

    To obtain system-dependent functionality, existing interfaces to the system + found in include/llvm/System should be used. If an appropriate + interface is not available, it should be added to include/llvm/System + and implemented in lib/System for all supported platforms.

    +
    + + + +
    +

    The System Library must shield LLVM from all system headers. To + obtain system level functionality, LLVM source must + #include "llvm/System/Thing.h" and nothing else. This means that + Thing.h cannot expose any system header files. This protects LLVM + from accidentally using system specific functionality and only allows it + via the lib/System interface.

    +
    + + + +
    +

    The standard C headers (the ones beginning with "c") are allowed + to be exposed through the lib/System interface. These headers and + the things they declare are considered to be platform agnostic. LLVM source + files may include them directly or obtain their inclusion through + lib/System interfaces.

    +
    + + + +
    +

    The standard C++ headers from the standard C++ library and + standard template library may be exposed through the lib/System + interface. These headers and the things they declare are considered to be + platform agnostic. LLVM source files may include them or obtain their + inclusion through lib/System interfaces.

    +
    + + + +
    +

    The entry points specified in the interface of lib/System must be aimed at + completing some reasonably high level task needed by LLVM. We do not want to + simply wrap each operating system call. It would be preferable to wrap several + operating system calls that are always used in conjunction with one another by + LLVM.

    +

    For example, consider what is needed to execute a program, wait for it to + complete, and return its result code. On Unix, this involves the following + operating system calls: getenv, fork, execve, and wait. The + correct thing for lib/System to provide is a function, say + ExecuteProgramAndWait, that implements the functionality completely. + what we don't want is wrappers for the operating system calls involved.

    +

    There must not be a one-to-one relationship between operating + system calls and the System library's interface. Any such interface function + will be suspicious.

    +
    + + + +
    +

    There must be no functionality specified in the interface of lib/System + that isn't actually used by LLVM. We're not writing a general purpose + operating system wrapper here, just enough to satisfy LLVM's needs. And, LLVM + doesn't need much. This design goal aims to keep the lib/System interface + small and understandable which should foster its actual use and adoption.

    +
    + + + +
    +

    The implementation of a function for a given platform must be written + exactly once. This implies that it must be possible to apply a function's + implementation to multiple operating systems if those operating systems can + share the same implementation. This rule applies to the set of operating + systems supported for a given class of operating system (e.g. Unix, Win32). +

    +
    + + + +
    +

    The System Library interfaces can be called quite frequently by LLVM. In + order to make those calls as efficient as possible, we discourage the use of + virtual methods. There is no need to use inheritance for implementation + differences, it just adds complexity. The #include mechanism works + just fine.

    +
    + + + +
    +

    Any functions defined by system libraries (i.e. not defined by lib/System) + must not be exposed through the lib/System interface, even if the header file + for that function is not exposed. This prevents inadvertent use of system + specific functionality.

    +

    For example, the stat system call is notorious for having + variations in the data it provides. lib/System must not declare + stat nor allow it to be declared. Instead it should provide its own + interface to discovering information about files and directories. Those + interfaces may be implemented in terms of stat but that is strictly + an implementation detail. The interface provided by the System Library must + be implemented on all platforms (even those without stat).

    +
    + + + +
    +

    Any data defined by system libraries (i.e. not defined by lib/System) must + not be exposed through the lib/System interface, even if the header file for + that function is not exposed. As with functions, this prevents inadvertent use + of data that might not exist on all platforms.

    +
    + + + +
    +

    Operating system interfaces will generally provide error results for every + little thing that could go wrong. In almost all cases, you can divide these + error results into two groups: normal/good/soft and abnormal/bad/hard. That + is, some of the errors are simply information like "file not found", + "insufficient privileges", etc. while other errors are much harder like + "out of space", "bad disk sector", or "system call interrupted". We'll call + the first group "soft" errors and the second group "hard" + errors.

    +

    lib/System must always attempt to minimize soft errors. + This is a design requirement because the + minimization of soft errors can affect the granularity and the nature of the + interface. In general, if you find that you're wanting to throw soft errors, + you must review the granularity of the interface because it is likely you're + trying to implement something that is too low level. The rule of thumb is to + provide interface functions that can't fail, except when faced with + hard errors.

    +

    For a trivial example, suppose we wanted to add an "OpenFileForWriting" + function. For many operating systems, if the file doesn't exist, attempting + to open the file will produce an error. However, lib/System should not + simply throw that error if it occurs because its a soft error. The problem + is that the interface function, OpenFileForWriting is too low level. It should + be OpenOrCreateFileForWriting. In the case of the soft "doesn't exist" error, + this function would just create it and then open it for writing.

    +

    This design principle needs to be maintained in lib/System because it + avoids the propagation of soft error handling throughout the rest of LLVM. + Hard errors will generally just cause a termination for an LLVM tool so don't + be bashful about throwing them.

    +

    Rules of thumb:

    +
      +
    1. Don't throw soft errors, only hard errors.
    2. +
    3. If you're tempted to throw a soft error, re-think the interface.
    4. +
    5. Handle internally the most common normal/good/soft error conditions + so the rest of LLVM doesn't have to.
    6. +
    +
    + + + +
    +

    None of the lib/System interface functions may be declared with C++ + throw() specifications on them. This requirement makes sure that the + compiler does not insert additional exception handling code into the interface + functions. This is a performance consideration: lib/System functions are at + the bottom of many call chains and as such can be frequently called. We + need them to be as efficient as possible. However, no routines in the + system library should actually throw exceptions.

    +
    + + + +
    +

    Implementations of the System Library interface are separated by their + general class of operating system. Currently only Unix and Win32 classes are + defined but more could be added for other operating system classifications. + To distinguish which implementation to compile, the code in lib/System uses + the LLVM_ON_UNIX and LLVM_ON_WIN32 #defines provided via configure through the + llvm/Config/config.h file. Each source file in lib/System, after implementing + the generic (operating system independent) functionality needs to include the + correct implementation using a set of #if defined(LLVM_ON_XYZ) + directives. For example, if we had lib/System/File.cpp, we'd expect to see in + that file:

    +
    
    +  #if defined(LLVM_ON_UNIX)
    +  #include "Unix/File.cpp"
    +  #endif
    +  #if defined(LLVM_ON_WIN32)
    +  #include "Win32/File.cpp"
    +  #endif
    +  
    +

    The implementation in lib/System/Unix/File.cpp should handle all Unix + variants. The implementation in lib/System/Win32/File.cpp should handle all + Win32 variants. What this does is quickly differentiate the basic class of + operating system that will provide the implementation. The specific details + for a given platform must still be determined through the use of + #ifdef.

    +
    + + + +
    +

    The implementation of a lib/System interface can vary drastically between + platforms. That's okay as long as the end result of the interface function + is the same. For example, a function to create a directory is pretty straight + forward on all operating system. System V IPC on the other hand isn't even + supported on all platforms. Instead of "supporting" System V IPC, lib/System + should provide an interface to the basic concept of inter-process + communications. The implementations might use System V IPC if that was + available or named pipes, or whatever gets the job done effectively for a + given operating system. In all cases, the interface and the implementation + must be semantically consistent.

    +
    + + + +
    +

    See bug 351 + for further details on the progress of this work

    +
    + + + +
    +
    + Valid CSS + Valid HTML 4.01 + + Reid Spencer
    + LLVM Compiler Infrastructure
    + Last modified: $Date$ +
    + + diff --git a/libclamav/c++/llvm/docs/TableGenFundamentals.html b/libclamav/c++/llvm/docs/TableGenFundamentals.html new file mode 100644 index 000000000..ade4bf67d --- /dev/null +++ b/libclamav/c++/llvm/docs/TableGenFundamentals.html @@ -0,0 +1,801 @@ + + + + TableGen Fundamentals + + + + +
    TableGen Fundamentals
    + + + +
    +

    Written by Chris Lattner

    +
    + + + + + +
    + +

    TableGen's purpose is to help a human develop and maintain records of +domain-specific information. Because there may be a large number of these +records, it is specifically designed to allow writing flexible descriptions and +for common features of these records to be factored out. This reduces the +amount of duplication in the description, reduces the chance of error, and +makes it easier to structure domain specific information.

    + +

    The core part of TableGen parses a file, instantiates +the declarations, and hands the result off to a domain-specific "TableGen backend" for processing. The current major user +of TableGen is the LLVM code generator.

    + +

    Note that if you work on TableGen much, and use emacs or vim, that you can +find an emacs "TableGen mode" and a vim language file in the +llvm/utils/emacs and llvm/utils/vim directories of your LLVM +distribution, respectively.

    + +
    + + + + +
    + +

    TableGen files consist of two key parts: 'classes' and 'definitions', both +of which are considered 'records'.

    + +

    TableGen records have a unique name, a list of values, and a list of +superclasses. The list of values is the main data that TableGen builds for each +record; it is this that holds the domain specific information for the +application. The interpretation of this data is left to a specific TableGen backend, but the structure and format rules are +taken care of and are fixed by TableGen.

    + +

    TableGen definitions are the concrete form of 'records'. These +generally do not have any undefined values, and are marked with the +'def' keyword.

    + +

    TableGen classes are abstract records that are used to build and +describe other records. These 'classes' allow the end-user to build +abstractions for either the domain they are targeting (such as "Register", +"RegisterClass", and "Instruction" in the LLVM code generator) or for the +implementor to help factor out common properties of records (such as "FPInst", +which is used to represent floating point instructions in the X86 backend). +TableGen keeps track of all of the classes that are used to build up a +definition, so the backend can find all definitions of a particular class, such +as "Instruction".

    + +

    TableGen multiclasses are groups of abstract records that are +instantiated all at once. Each instantiation can result in multiple +TableGen definitions. If a multiclass inherits from another multiclass, +the definitions in the sub-multiclass become part of the current +multiclass, as if they were declared in the current multiclass.

    + +
    + + + + +
    + +

    With no other arguments, TableGen parses the specified file and prints out +all of the classes, then all of the definitions. This is a good way to see what +the various definitions expand to fully. Running this on the X86.td +file prints this (at the time of this writing):

    + +
    +
    +...
    +def ADD32rr {   // Instruction X86Inst I
    +  string Namespace = "X86";
    +  dag OutOperandList = (outs GR32:$dst);
    +  dag InOperandList = (ins GR32:$src1, GR32:$src2);
    +  string AsmString = "add{l}\t{$src2, $dst|$dst, $src2}";
    +  list<dag> Pattern = [(set GR32:$dst, (add GR32:$src1, GR32:$src2))];
    +  list<Register> Uses = [];
    +  list<Register> Defs = [EFLAGS];
    +  list<Predicate> Predicates = [];
    +  int CodeSize = 3;
    +  int AddedComplexity = 0;
    +  bit isReturn = 0;
    +  bit isBranch = 0;
    +  bit isIndirectBranch = 0;
    +  bit isBarrier = 0;
    +  bit isCall = 0;
    +  bit canFoldAsLoad = 0;
    +  bit mayLoad = 0;
    +  bit mayStore = 0;
    +  bit isImplicitDef = 0;
    +  bit isTwoAddress = 1;
    +  bit isConvertibleToThreeAddress = 1;
    +  bit isCommutable = 1;
    +  bit isTerminator = 0;
    +  bit isReMaterializable = 0;
    +  bit isPredicable = 0;
    +  bit hasDelaySlot = 0;
    +  bit usesCustomInserter = 0;
    +  bit hasCtrlDep = 0;
    +  bit isNotDuplicable = 0;
    +  bit hasSideEffects = 0;
    +  bit mayHaveSideEffects = 0;
    +  bit neverHasSideEffects = 0;
    +  InstrItinClass Itinerary = NoItinerary;
    +  string Constraints = "";
    +  string DisableEncoding = "";
    +  bits<8> Opcode = { 0, 0, 0, 0, 0, 0, 0, 1 };
    +  Format Form = MRMDestReg;
    +  bits<6> FormBits = { 0, 0, 0, 0, 1, 1 };
    +  ImmType ImmT = NoImm;
    +  bits<3> ImmTypeBits = { 0, 0, 0 };
    +  bit hasOpSizePrefix = 0;
    +  bit hasAdSizePrefix = 0;
    +  bits<4> Prefix = { 0, 0, 0, 0 };
    +  bit hasREX_WPrefix = 0;
    +  FPFormat FPForm = ?;
    +  bits<3> FPFormBits = { 0, 0, 0 };
    +}
    +...
    +
    +
    + +

    This definition corresponds to a 32-bit register-register add instruction in +the X86. The string after the 'def' string indicates the name of the +record—"ADD32rr" in this case—and the comment at the end of +the line indicates the superclasses of the definition. The body of the record +contains all of the data that TableGen assembled for the record, indicating that +the instruction is part of the "X86" namespace, the pattern indicating how the +the instruction should be emitted into the assembly file, that it is a +two-address instruction, has a particular encoding, etc. The contents and +semantics of the information in the record is specific to the needs of the X86 +backend, and is only shown as an example.

    + +

    As you can see, a lot of information is needed for every instruction +supported by the code generator, and specifying it all manually would be +unmaintainble, prone to bugs, and tiring to do in the first place. Because we +are using TableGen, all of the information was derived from the following +definition:

    + +
    +
    +let Defs = [EFLAGS],
    +    isCommutable = 1,                  // X = ADD Y,Z --> X = ADD Z,Y
    +    isConvertibleToThreeAddress = 1 in // Can transform into LEA.
    +def ADD32rr  : I<0x01, MRMDestReg, (outs GR32:$dst),
    +                                   (ins GR32:$src1, GR32:$src2),
    +                 "add{l}\t{$src2, $dst|$dst, $src2}",
    +                 [(set GR32:$dst, (add GR32:$src1, GR32:$src2))]>;
    +
    +
    + +

    This definition makes use of the custom class I (extended from the +custom class X86Inst), which is defined in the X86-specific TableGen +file, to factor out the common features that instructions of its class share. A +key feature of TableGen is that it allows the end-user to define the +abstractions they prefer to use when describing their information.

    + +
    + + + + +
    + +

    TableGen runs just like any other LLVM tool. The first (optional) argument +specifies the file to read. If a filename is not specified, tblgen +reads from standard input.

    + +

    To be useful, one of the TableGen backends must be +used. These backends are selectable on the command line (type 'tblgen +-help' for a list). For example, to get a list of all of the definitions +that subclass a particular type (which can be useful for building up an enum +list of these records), use the -print-enums option:

    + +
    +
    +$ tblgen X86.td -print-enums -class=Register
    +AH, AL, AX, BH, BL, BP, BPL, BX, CH, CL, CX, DH, DI, DIL, DL, DX, EAX, EBP, EBX,
    +ECX, EDI, EDX, EFLAGS, EIP, ESI, ESP, FP0, FP1, FP2, FP3, FP4, FP5, FP6, IP,
    +MM0, MM1, MM2, MM3, MM4, MM5, MM6, MM7, R10, R10B, R10D, R10W, R11, R11B, R11D,
    +R11W, R12, R12B, R12D, R12W, R13, R13B, R13D, R13W, R14, R14B, R14D, R14W, R15,
    +R15B, R15D, R15W, R8, R8B, R8D, R8W, R9, R9B, R9D, R9W, RAX, RBP, RBX, RCX, RDI,
    +RDX, RIP, RSI, RSP, SI, SIL, SP, SPL, ST0, ST1, ST2, ST3, ST4, ST5, ST6, ST7,
    +XMM0, XMM1, XMM10, XMM11, XMM12, XMM13, XMM14, XMM15, XMM2, XMM3, XMM4, XMM5,
    +XMM6, XMM7, XMM8, XMM9,
    +
    +$ tblgen X86.td -print-enums -class=Instruction 
    +ABS_F, ABS_Fp32, ABS_Fp64, ABS_Fp80, ADC32mi, ADC32mi8, ADC32mr, ADC32ri,
    +ADC32ri8, ADC32rm, ADC32rr, ADC64mi32, ADC64mi8, ADC64mr, ADC64ri32, ADC64ri8,
    +ADC64rm, ADC64rr, ADD16mi, ADD16mi8, ADD16mr, ADD16ri, ADD16ri8, ADD16rm,
    +ADD16rr, ADD32mi, ADD32mi8, ADD32mr, ADD32ri, ADD32ri8, ADD32rm, ADD32rr,
    +ADD64mi32, ADD64mi8, ADD64mr, ADD64ri32, ...
    +
    +
    + +

    The default backend prints out all of the records, as described above.

    + +

    If you plan to use TableGen, you will most likely have to write a backend that extracts the information specific to +what you need and formats it in the appropriate way.

    + +
    + + + + + + +
    + +

    TableGen doesn't care about the meaning of data (that is up to the backend to +define), but it does care about syntax, and it enforces a simple type system. +This section describes the syntax and the constructs allowed in a TableGen file. +

    + +
    + + + + + + + +
    + +

    TableGen supports BCPL style "//" comments, which run to the end of +the line, and it also supports nestable "/* */" comments.

    + +
    + + + + +
    + +

    TableGen files are strongly typed, in a simple (but complete) type-system. +These types are used to perform automatic conversions, check for errors, and to +help interface designers constrain the input that they allow. Every value definition is required to have an associated type. +

    + +

    TableGen supports a mixture of very low-level types (such as bit) +and very high-level types (such as dag). This flexibility is what +allows it to describe a wide range of information conveniently and compactly. +The TableGen types are:

    + +
    +
    bit
    +
    A 'bit' is a boolean value that can hold either 0 or 1.
    + +
    int
    +
    The 'int' type represents a simple 32-bit integer value, such as 5.
    + +
    string
    +
    The 'string' type represents an ordered sequence of characters of + arbitrary length.
    + +
    bits<n>
    +
    A 'bits' type is an arbitrary, but fixed, size integer that is broken up + into individual bits. This type is useful because it can handle some bits + being defined while others are undefined.
    + +
    list<ty>
    +
    This type represents a list whose elements are some other type. The + contained type is arbitrary: it can even be another list type.
    + +
    Class type
    +
    Specifying a class name in a type context means that the defined value + must be a subclass of the specified class. This is useful in conjunction with + the list type, for example, to constrain the elements of the + list to a common base class (e.g., a list<Register> can + only contain definitions derived from the "Register" class).
    + +
    dag
    +
    This type represents a nestable directed graph of elements.
    + +
    code
    +
    This represents a big hunk of text. NOTE: I don't remember why this is + distinct from string!
    +
    + +

    To date, these types have been sufficient for describing things that +TableGen has been used for, but it is straight-forward to extend this list if +needed.

    + +
    + + + + +
    + +

    TableGen allows for a pretty reasonable number of different expression forms +when building up values. These forms allow the TableGen file to be written in a +natural syntax and flavor for the application. The current expression forms +supported include:

    + +
    +
    ?
    +
    uninitialized field
    +
    0b1001011
    +
    binary integer value
    +
    07654321
    +
    octal integer value (indicated by a leading 0)
    +
    7
    +
    decimal integer value
    +
    0x7F
    +
    hexadecimal integer value
    +
    "foo"
    +
    string value
    +
    [{ ... }]
    +
    code fragment
    +
    [ X, Y, Z ]<type>
    +
    list value. <type> is the type of the list +element and is usually optional. In rare cases, +TableGen is unable to deduce the element type in +which case the user must specify it explicitly.
    +
    { a, b, c }
    +
    initializer for a "bits<3>" value
    +
    value
    +
    value reference
    +
    value{17}
    +
    access to one bit of a value
    +
    value{15-17}
    +
    access to multiple bits of a value
    +
    DEF
    +
    reference to a record definition
    +
    CLASS<val list>
    +
    reference to a new anonymous definition of CLASS with the specified + template arguments.
    +
    X.Y
    +
    reference to the subfield of a value
    +
    list[4-7,17,2-3]
    +
    A slice of the 'list' list, including elements 4,5,6,7,17,2, and 3 from + it. Elements may be included multiple times.
    +
    (DEF a, b)
    +
    a dag value. The first element is required to be a record definition, the + remaining elements in the list may be arbitrary other values, including nested + `dag' values.
    +
    !strconcat(a, b)
    +
    A string value that is the result of concatenating the 'a' and 'b' + strings.
    +
    !cast<type>(a)
    +
    A symbol of type type obtained by looking up the string 'a' in +the symbol table. If the type of 'a' does not match type, TableGen +aborts with an error. !cast<string> is a special case in that the argument must +be an object defined by a 'def' construct.
    +
    !nameconcat<type>(a, b)
    +
    Shorthand for !cast<type>(!strconcat(a, b))
    +
    !subst(a, b, c)
    +
    If 'a' and 'b' are of string type or are symbol references, substitute +'b' for 'a' in 'c.' This operation is analogous to $(subst) in GNU make.
    +
    !foreach(a, b, c)
    +
    For each member 'b' of dag or list 'a' apply operator 'c.' 'b' is a +dummy variable that should be declared as a member variable of an instantiated +class. This operation is analogous to $(foreach) in GNU make.
    +
    !car(a)
    +
    The first element of list 'a.'
    +
    !cdr(a)
    +
    The 2nd-N elements of list 'a.'
    +
    !null(a)
    +
    An integer {0,1} indicating whether list 'a' is empty.
    +
    !if(a,b,c)
    +
    'b' if the result of integer operator 'a' is nonzero, 'c' otherwise.
    +
    + +

    Note that all of the values have rules specifying how they convert to values +for different types. These rules allow you to assign a value like "7" +to a "bits<4>" value, for example.

    + +
    + + + + +
    + +

    As mentioned in the intro, classes and definitions +(collectively known as 'records') in TableGen are the main high-level unit of +information that TableGen collects. Records are defined with a def or +class keyword, the record name, and an optional list of "template arguments". If the record has superclasses, +they are specified as a comma separated list that starts with a colon character +(":"). If value definitions or let expressions are needed for the class, they are +enclosed in curly braces ("{}"); otherwise, the record ends with a +semicolon.

    + +

    Here is a simple TableGen file:

    + +
    +
    +class C { bit V = 1; }
    +def X : C;
    +def Y : C {
    +  string Greeting = "hello";
    +}
    +
    +
    + +

    This example defines two definitions, X and Y, both of +which derive from the C class. Because of this, they both get the +V bit value. The Y definition also gets the Greeting member +as well.

    + +

    In general, classes are useful for collecting together the commonality +between a group of records and isolating it in a single place. Also, classes +permit the specification of default values for their subclasses, allowing the +subclasses to override them as they wish.

    + +
    + + + + +
    + +

    Value definitions define named entries in records. A value must be defined +before it can be referred to as the operand for another value definition or +before the value is reset with a let expression. A +value is defined by specifying a TableGen type and a name. +If an initial value is available, it may be specified after the type with an +equal sign. Value definitions require terminating semicolons.

    + +
    + + + + +
    + +

    A record-level let expression is used to change the value of a value +definition in a record. This is primarily useful when a superclass defines a +value that a derived class or definition wants to override. Let expressions +consist of the 'let' keyword followed by a value name, an equal sign +("="), and a new value. For example, a new class could be added to the +example above, redefining the V field for all of its subclasses:

    + +
    +
    +class D : C { let V = 0; }
    +def Z : D;
    +
    +
    + +

    In this case, the Z definition will have a zero value for its "V" +value, despite the fact that it derives (indirectly) from the C class, +because the D class overrode its value.

    + +
    + + + + +
    + +

    TableGen permits the definition of parameterized classes as well as normal +concrete classes. Parameterized TableGen classes specify a list of variable +bindings (which may optionally have defaults) that are bound when used. Here is +a simple example:

    + +
    +
    +class FPFormat<bits<3> val> {
    +  bits<3> Value = val;
    +}
    +def NotFP      : FPFormat<0>;
    +def ZeroArgFP  : FPFormat<1>;
    +def OneArgFP   : FPFormat<2>;
    +def OneArgFPRW : FPFormat<3>;
    +def TwoArgFP   : FPFormat<4>;
    +def CompareFP  : FPFormat<5>;
    +def CondMovFP  : FPFormat<6>;
    +def SpecialFP  : FPFormat<7>;
    +
    +
    + +

    In this case, template arguments are used as a space efficient way to specify +a list of "enumeration values", each with a "Value" field set to the +specified integer.

    + +

    The more esoteric forms of TableGen expressions are +useful in conjunction with template arguments. As an example:

    + +
    +
    +class ModRefVal<bits<2> val> {
    +  bits<2> Value = val;
    +}
    +
    +def None   : ModRefVal<0>;
    +def Mod    : ModRefVal<1>;
    +def Ref    : ModRefVal<2>;
    +def ModRef : ModRefVal<3>;
    +
    +class Value<ModRefVal MR> {
    +  // Decode some information into a more convenient format, while providing
    +  // a nice interface to the user of the "Value" class.
    +  bit isMod = MR.Value{0};
    +  bit isRef = MR.Value{1};
    +
    +  // other stuff...
    +}
    +
    +// Example uses
    +def bork : Value<Mod>;
    +def zork : Value<Ref>;
    +def hork : Value<ModRef>;
    +
    +
    + +

    This is obviously a contrived example, but it shows how template arguments +can be used to decouple the interface provided to the user of the class from the +actual internal data representation expected by the class. In this case, +running tblgen on the example prints the following definitions:

    + +
    +
    +def bork {      // Value
    +  bit isMod = 1;
    +  bit isRef = 0;
    +}
    +def hork {      // Value
    +  bit isMod = 1;
    +  bit isRef = 1;
    +}
    +def zork {      // Value
    +  bit isMod = 0;
    +  bit isRef = 1;
    +}
    +
    +
    + +

    This shows that TableGen was able to dig into the argument and extract a +piece of information that was requested by the designer of the "Value" class. +For more realistic examples, please see existing users of TableGen, such as the +X86 backend.

    + +
    + + + + +
    + +

    +While classes with template arguments are a good way to factor commonality +between two instances of a definition, multiclasses allow a convenient notation +for defining multiple definitions at once (instances of implicitly constructed +classes). For example, consider an 3-address instruction set whose instructions +come in two forms: "reg = reg op reg" and "reg = reg op imm" +(e.g. SPARC). In this case, you'd like to specify in one place that this +commonality exists, then in a separate place indicate what all the ops are. +

    + +

    +Here is an example TableGen fragment that shows this idea: +

    + +
    +
    +def ops;
    +def GPR;
    +def Imm;
    +class inst<int opc, string asmstr, dag operandlist>;
    +
    +multiclass ri_inst<int opc, string asmstr> {
    +  def _rr : inst<opc, !strconcat(asmstr, " $dst, $src1, $src2"),
    +                 (ops GPR:$dst, GPR:$src1, GPR:$src2)>;
    +  def _ri : inst<opc, !strconcat(asmstr, " $dst, $src1, $src2"),
    +                 (ops GPR:$dst, GPR:$src1, Imm:$src2)>;
    +}
    +
    +// Instantiations of the ri_inst multiclass.
    +defm ADD : ri_inst<0b111, "add">;
    +defm SUB : ri_inst<0b101, "sub">;
    +defm MUL : ri_inst<0b100, "mul">;
    +...
    +
    +
    + +

    The name of the resultant definitions has the multidef fragment names + appended to them, so this defines ADD_rr, ADD_ri, + SUB_rr, etc. A defm may inherit from multiple multiclasses, + instantiating definitions from each multiclass. Using a multiclass + this way is exactly equivalent to instantiating the classes multiple + times yourself, e.g. by writing:

    + +
    +
    +def ops;
    +def GPR;
    +def Imm;
    +class inst<int opc, string asmstr, dag operandlist>;
    +
    +class rrinst<int opc, string asmstr>
    +  : inst<opc, !strconcat(asmstr, " $dst, $src1, $src2"),
    +         (ops GPR:$dst, GPR:$src1, GPR:$src2)>;
    +
    +class riinst<int opc, string asmstr>
    +  : inst<opc, !strconcat(asmstr, " $dst, $src1, $src2"),
    +         (ops GPR:$dst, GPR:$src1, Imm:$src2)>;
    +
    +// Instantiations of the ri_inst multiclass.
    +def ADD_rr : rrinst<0b111, "add">;
    +def ADD_ri : riinst<0b111, "add">;
    +def SUB_rr : rrinst<0b101, "sub">;
    +def SUB_ri : riinst<0b101, "sub">;
    +def MUL_rr : rrinst<0b100, "mul">;
    +def MUL_ri : riinst<0b100, "mul">;
    +...
    +
    +
    + +
    + + + + + + + +
    +

    TableGen supports the 'include' token, which textually substitutes +the specified file in place of the include directive. The filename should be +specified as a double quoted string immediately after the 'include' +keyword. Example:

    + +
    +
    +include "foo.td"
    +
    +
    + +
    + + + + +
    + +

    "Let" expressions at file scope are similar to "let" +expressions within a record, except they can specify a value binding for +multiple records at a time, and may be useful in certain other cases. +File-scope let expressions are really just another way that TableGen allows the +end-user to factor out commonality from the records.

    + +

    File-scope "let" expressions take a comma-separated list of bindings to +apply, and one or more records to bind the values in. Here are some +examples:

    + +
    +
    +let isTerminator = 1, isReturn = 1, isBarrier = 1, hasCtrlDep = 1 in
    +  def RET : I<0xC3, RawFrm, (outs), (ins), "ret", [(X86retflag 0)]>;
    +
    +let isCall = 1 in
    +  // All calls clobber the non-callee saved registers...
    +  let Defs = [EAX, ECX, EDX, FP0, FP1, FP2, FP3, FP4, FP5, FP6, ST0,
    +              MM0, MM1, MM2, MM3, MM4, MM5, MM6, MM7,
    +              XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6, XMM7, EFLAGS] in {
    +    def CALLpcrel32 : Ii32<0xE8, RawFrm, (outs), (ins i32imm:$dst,variable_ops),
    +                           "call\t${dst:call}", []>;
    +    def CALL32r     : I<0xFF, MRM2r, (outs), (ins GR32:$dst, variable_ops),
    +                        "call\t{*}$dst", [(X86call GR32:$dst)]>;
    +    def CALL32m     : I<0xFF, MRM2m, (outs), (ins i32mem:$dst, variable_ops),
    +                        "call\t{*}$dst", []>;
    +  }
    +
    +
    + +

    File-scope "let" expressions are often useful when a couple of definitions +need to be added to several records, and the records do not otherwise need to be +opened, as in the case with the CALL* instructions above.

    + +
    + + + + + +

    Expressions used by code generator to describe instructions and isel +patterns:

    + +
    + +
    (implicit a)
    +
    an implicitly defined physical register. This tells the dag instruction + selection emitter the input pattern's extra definitions matches implicit + physical register definitions.
    +
    (parallel (a), (b))
    +
    a list of dags specifying parallel operations which map to the same + instruction.
    + +
    + + + + + +
    + +

    TODO: How they work, how to write one. This section should not contain +details about any particular backend, except maybe -print-enums as an example. +This should highlight the APIs in TableGen/Record.h.

    + +
    + + + +
    +
    + Valid CSS + Valid HTML 4.01 + + Chris Lattner
    + LLVM Compiler Infrastructure
    + Last modified: $Date$ +
    + + + diff --git a/libclamav/c++/llvm/docs/TestingGuide.html b/libclamav/c++/llvm/docs/TestingGuide.html new file mode 100644 index 000000000..43c414d4c --- /dev/null +++ b/libclamav/c++/llvm/docs/TestingGuide.html @@ -0,0 +1,1223 @@ + + + + LLVM Testing Infrastructure Guide + + + + +
    + LLVM Testing Infrastructure Guide +
    + +
      +
    1. Overview
    2. +
    3. Requirements
    4. +
    5. LLVM testing infrastructure organization + +
    6. +
    7. Quick start + +
    8. +
    9. DejaGNU structure + +
    10. +
    11. Test suite structure
    12. +
    13. Running the test suite + +
    14. +
    15. Running the nightly tester
    16. +
    + +
    +

    Written by John T. Criswell, Reid Spencer, and Tanya Lattner

    +
    + + + + + +
    + +

    This document is the reference manual for the LLVM testing infrastructure. It documents +the structure of the LLVM testing infrastructure, the tools needed to use it, +and how to add and run tests.

    + +
    + + + + + +
    + +

    In order to use the LLVM testing infrastructure, you will need all of the software +required to build LLVM, plus the following:

    + +
    +
    DejaGNU
    +
    The Feature and Regressions tests are organized and run by DejaGNU.
    +
    Expect
    +
    Expect is required by DejaGNU.
    +
    tcl
    +
    Tcl is required by DejaGNU.
    +
    + +
    + + + + + +
    + +

    The LLVM testing infrastructure contains two major categories of tests: code +fragments and whole programs. Code fragments are referred to as the "DejaGNU +tests" and are in the llvm module in subversion under the +llvm/test directory. The whole programs tests are referred to as the +"Test suite" and are in the test-suite module in subversion. +

    + +
    + + + + + +
    + +

    Code fragments are small pieces of code that test a specific +feature of LLVM or trigger a specific bug in LLVM. They are usually +written in LLVM assembly language, but can be written in other +languages if the test targets a particular language front end (and the +appropriate --with-llvmgcc options were used +at configure time of the llvm module). These tests +are driven by the DejaGNU testing framework, which is hidden behind a +few simple makefiles.

    + +

    These code fragments are not complete programs. The code generated +from them is never executed to determine correct behavior.

    + +

    These code fragment tests are located in the llvm/test +directory.

    + +

    Typically when a bug is found in LLVM, a regression test containing +just enough code to reproduce the problem should be written and placed +somewhere underneath this directory. In most cases, this will be a small +piece of LLVM assembly language code, often distilled from an actual +application or benchmark.

    + +
    + + + + + +
    + +

    The test suite contains whole programs, which are pieces of +code which can be compiled and linked into a stand-alone program that can be +executed. These programs are generally written in high level languages such as +C or C++, but sometimes they are written straight in LLVM assembly.

    + +

    These programs are compiled and then executed using several different +methods (native compiler, LLVM C backend, LLVM JIT, LLVM native code generation, +etc). The output of these programs is compared to ensure that LLVM is compiling +the program correctly.

    + +

    In addition to compiling and executing programs, whole program tests serve as +a way of benchmarking LLVM performance, both in terms of the efficiency of the +programs generated as well as the speed with which LLVM compiles, optimizes, and +generates code.

    + +

    The test-suite is located in the test-suite Subversion module.

    + +
    + + + + + +
    + +

    The tests are located in two separate Subversion modules. The + DejaGNU tests are in the main "llvm" module under the directory + llvm/test (so you get these tests for free with the main llvm tree). + The more comprehensive test suite that includes whole +programs in C and C++ is in the test-suite module. This module should +be checked out to the llvm/projects directory (don't use another name +then the default "test-suite", for then the test suite will be run every time +you run make in the main llvm directory). +When you configure the llvm module, +the test-suite directory will be automatically configured. +Alternatively, you can configure the test-suite module manually.

    + + + + +

    To run all of the simple tests in LLVM using DejaGNU, use the master Makefile + in the llvm/test directory:

    + +
    +
    +% gmake -C llvm/test
    +
    +
    + +

    or

    + +
    +
    +% gmake check
    +
    +
    + +

    To run only a subdirectory of tests in llvm/test using DejaGNU (ie. +Transforms), just set the TESTSUITE variable to the path of the +subdirectory (relative to llvm/test):

    + +
    +
    +% gmake TESTSUITE=Transforms check
    +
    +
    + +

    Note: If you are running the tests with objdir != subdir, you +must have run the complete testsuite before you can specify a +subdirectory.

    + +

    To run only a single test, set TESTONE to its path (relative to +llvm/test) and make the check-one target:

    + +
    +
    +% gmake TESTONE=Feature/basictest.ll check-one
    +
    +
    + +

    To run the tests with Valgrind (Memcheck by default), just append +VG=1 to the commands above, e.g.:

    + +
    +
    +% gmake check VG=1
    +
    +
    + + + + + +

    To run the comprehensive test suite (tests that compile and execute whole +programs), first checkout and setup the test-suite module:

    + +
    +
    +% cd llvm/projects
    +% svn co http://llvm.org/svn/llvm-project/test-suite/trunk test-suite
    +% cd ..
    +% ./configure --with-llvmgccdir=$LLVM_GCC_DIR
    +
    +
    + +

    where $LLVM_GCC_DIR is the directory where +you installed llvm-gcc, not it's src or obj +dir. The --with-llvmgccdir option assumes that +the llvm-gcc-4.2 module was configured with +--program-prefix=llvm-, and therefore that the C and C++ +compiler drivers are called llvm-gcc and llvm-g++ +respectively. If this is not the case, +use --with-llvmgcc/--with-llvmgxx to specify each +executable's location.

    + +

    Then, run the entire test suite by running make in the test-suite +directory:

    + +
    +
    +% cd projects/test-suite
    +% gmake
    +
    +
    + +

    Usually, running the "nightly" set of tests is a good idea, and you can also +let it generate a report by running:

    + +
    +
    +% cd projects/test-suite
    +% gmake TEST=nightly report report.html
    +
    +
    + +

    Any of the above commands can also be run in a subdirectory of +projects/test-suite to run the specified test only on the programs in +that subdirectory.

    + +
    + + + + +
    +

    The LLVM DejaGNU tests are driven by DejaGNU together with GNU Make and are + located in the llvm/test directory. + +

    This directory contains a large array of small tests + that exercise various features of LLVM and to ensure that regressions do not + occur. The directory is broken into several sub-directories, each focused on + a particular area of LLVM. A few of the important ones are:

    + +
      +
    • Analysis: checks Analysis passes.
    • +
    • Archive: checks the Archive library.
    • +
    • Assembler: checks Assembly reader/writer functionality.
    • +
    • Bitcode: checks Bitcode reader/writer functionality.
    • +
    • CodeGen: checks code generation and each target.
    • +
    • Features: checks various features of the LLVM language.
    • +
    • Linker: tests bitcode linking.
    • +
    • Transforms: tests each of the scalar, IPO, and utility + transforms to ensure they make the right transformations.
    • +
    • Verifier: tests the IR verifier.
    • +
    + +
    + + + + +
    +

    The DejaGNU structure is very simple, but does require some information to + be set. This information is gathered via configure and is written + to a file, site.exp in llvm/test. The llvm/test + Makefile does this work for you.

    + +

    In order for DejaGNU to work, each directory of tests must have a + dg.exp file. DejaGNU looks for this file to determine how to run the + tests. This file is just a Tcl script and it can do anything you want, but + we've standardized it for the LLVM regression tests. If you're adding a + directory of tests, just copy dg.exp from another directory to get + running. The standard dg.exp simply loads a Tcl + library (test/lib/llvm.exp) and calls the llvm_runtests + function defined in that library with a list of file names to run. The names + are obtained by using Tcl's glob command. Any directory that contains only + directories does not need the dg.exp file.

    + +

    The llvm-runtests function lookas at each file that is passed to + it and gathers any lines together that match "RUN:". This are the "RUN" lines + that specify how the test is to be run. So, each test script must contain + RUN lines if it is to do anything. If there are no RUN lines, the + llvm-runtests function will issue an error and the test will + fail.

    + +

    RUN lines are specified in the comments of the test program using the + keyword RUN followed by a colon, and lastly the command (pipeline) + to execute. Together, these lines form the "script" that + llvm-runtests executes to run the test case. The syntax of the + RUN lines is similar to a shell's syntax for pipelines including I/O + redirection and variable substitution. However, even though these lines + may look like a shell script, they are not. RUN lines are interpreted + directly by the Tcl exec command. They are never executed by a + shell. Consequently the syntax differs from normal shell script syntax in a + few ways. You can specify as many RUN lines as needed.

    + +

    Each RUN line is executed on its own, distinct from other lines unless + its last character is \. This continuation character causes the RUN + line to be concatenated with the next one. In this way you can build up long + pipelines of commands without making huge line lengths. The lines ending in + \ are concatenated until a RUN line that doesn't end in \ is + found. This concatenated set of RUN lines then constitutes one execution. + Tcl will substitute variables and arrange for the pipeline to be executed. If + any process in the pipeline fails, the entire line (and test case) fails too. +

    + +

    Below is an example of legal RUN lines in a .ll file:

    + +
    +
    +; RUN: llvm-as < %s | llvm-dis > %t1
    +; RUN: llvm-dis < %s.bc-13 > %t2
    +; RUN: diff %t1 %t2
    +
    +
    + +

    As with a Unix shell, the RUN: lines permit pipelines and I/O redirection + to be used. However, the usage is slightly different than for Bash. To check + what's legal, see the documentation for the + Tcl exec + command and the + tutorial. + The major differences are:

    +
      +
    • You can't do 2>&1. That will cause Tcl to write to a + file named &1. Usually this is done to get stderr to go through + a pipe. You can do that in tcl with |& so replace this idiom: + ... 2>&1 | grep with ... |& grep
    • +
    • You can only redirect to a file, not to another descriptor and not from + a here document.
    • +
    • tcl supports redirecting to open files with the @ syntax but you + shouldn't use that here.
    • +
    + +

    There are some quoting rules that you must pay attention to when writing + your RUN lines. In general nothing needs to be quoted. Tcl won't strip off any + ' or " so they will get passed to the invoked program. For example:

    + +
    +
    +... | grep 'find this string'
    +
    +
    + +

    This will fail because the ' characters are passed to grep. This would + instruction grep to look for 'find in the files this and + string'. To avoid this use curly braces to tell Tcl that it should + treat everything enclosed as one value. So our example would become:

    + +
    +
    +... | grep {find this string}
    +
    +
    + +

    Additionally, the characters [ and ] are treated + specially by Tcl. They tell Tcl to interpret the content as a command to + execute. Since these characters are often used in regular expressions this can + have disastrous results and cause the entire test run in a directory to fail. + For example, a common idiom is to look for some basicblock number:

    + +
    +
    +... | grep bb[2-8]
    +
    +
    + +

    This, however, will cause Tcl to fail because its going to try to execute + a program named "2-8". Instead, what you want is this:

    + +
    +
    +... | grep {bb\[2-8\]}
    +
    +
    + +

    Finally, if you need to pass the \ character down to a program, + then it must be doubled. This is another Tcl special character. So, suppose + you had: + +

    +
    +... | grep 'i32\*'
    +
    +
    + +

    This will fail to match what you want (a pointer to i32). First, the + ' do not get stripped off. Second, the \ gets stripped off + by Tcl so what grep sees is: 'i32*'. That's not likely to match + anything. To resolve this you must use \\ and the {}, like + this:

    + +
    +
    +... | grep {i32\\*}
    +
    +
    + +

    If your system includes GNU grep, make sure +that GREP_OPTIONS is not set in your environment. Otherwise, +you may get invalid results (both false positives and false +negatives).

    + +
    + + + + + +
    + +

    A powerful feature of the RUN: lines is that it allows any arbitrary commands + to be executed as part of the test harness. While standard (portable) unix + tools like 'grep' work fine on run lines, as you see above, there are a lot + of caveats due to interaction with Tcl syntax, and we want to make sure the + run lines are portable to a wide range of systems. Another major problem is + that grep is not very good at checking to verify that the output of a tools + contains a series of different output in a specific order. The FileCheck + tool was designed to help with these problems.

    + +

    FileCheck (whose basic command line arguments are described in the FileCheck man page is + designed to read a file to check from standard input, and the set of things + to verify from a file specified as a command line argument. A simple example + of using FileCheck from a RUN line looks like this:

    + +
    +
    +; RUN: llvm-as < %s | llc -march=x86-64 | FileCheck %s
    +
    +
    + +

    This syntax says to pipe the current file ("%s") into llvm-as, pipe that into +llc, then pipe the output of llc into FileCheck. This means that FileCheck will +be verifying its standard input (the llc output) against the filename argument +specified (the original .ll file specified by "%s"). To see how this works, +lets look at the rest of the .ll file (after the RUN line):

    + +
    +
    +define void @sub1(i32* %p, i32 %v) {
    +entry:
    +; CHECK: sub1:
    +; CHECK: subl
    +        %0 = tail call i32 @llvm.atomic.load.sub.i32.p0i32(i32* %p, i32 %v)
    +        ret void
    +}
    +
    +define void @inc4(i64* %p) {
    +entry:
    +; CHECK: inc4:
    +; CHECK: incq
    +        %0 = tail call i64 @llvm.atomic.load.add.i64.p0i64(i64* %p, i64 1)
    +        ret void
    +}
    +
    +
    + +

    Here you can see some "CHECK:" lines specified in comments. Now you can see +how the file is piped into llvm-as, then llc, and the machine code output is +what we are verifying. FileCheck checks the machine code output to verify that +it matches what the "CHECK:" lines specify.

    + +

    The syntax of the CHECK: lines is very simple: they are fixed strings that +must occur in order. FileCheck defaults to ignoring horizontal whitespace +differences (e.g. a space is allowed to match a tab) but otherwise, the contents +of the CHECK: line is required to match some thing in the test file exactly.

    + +

    One nice thing about FileCheck (compared to grep) is that it allows merging +test cases together into logical groups. For example, because the test above +is checking for the "sub1:" and "inc4:" labels, it will not match unless there +is a "subl" in between those labels. If it existed somewhere else in the file, +that would not count: "grep subl" matches if subl exists anywhere in the +file.

    + +
    + + + + +
    + +

    The FileCheck -check-prefix option allows multiple test configurations to be +driven from one .ll file. This is useful in many circumstances, for example, +testing different architectural variants with llc. Here's a simple example:

    + +
    +
    +; RUN: llvm-as < %s | llc -mtriple=i686-apple-darwin9 -mattr=sse41 \
    +; RUN:              | FileCheck %s -check-prefix=X32
    +; RUN: llvm-as < %s | llc -mtriple=x86_64-apple-darwin9 -mattr=sse41 \
    +; RUN:              | FileCheck %s -check-prefix=X64
    +
    +define <4 x i32> @pinsrd_1(i32 %s, <4 x i32> %tmp) nounwind {
    +        %tmp1 = insertelement <4 x i32> %tmp, i32 %s, i32 1
    +        ret <4 x i32> %tmp1
    +; X32: pinsrd_1:
    +; X32:    pinsrd $1, 4(%esp), %xmm0
    +
    +; X64: pinsrd_1:
    +; X64:    pinsrd $1, %edi, %xmm0
    +}
    +
    +
    + +

    In this case, we're testing that we get the expected code generation with +both 32-bit and 64-bit code generation.

    + +
    + + + + +
    + +

    Sometimes you want to match lines and would like to verify that matches +happen on exactly consequtive lines with no other lines in between them. In +this case, you can use CHECK: and CHECK-NEXT: directives to specify this. If +you specified a custom check prefix, just use "<PREFIX>-NEXT:". For +example, something like this works as you'd expect:

    + +
    +
    +define void @t2(<2 x double>* %r, <2 x double>* %A, double %B) {
    +	%tmp3 = load <2 x double>* %A, align 16
    +	%tmp7 = insertelement <2 x double> undef, double %B, i32 0
    +	%tmp9 = shufflevector <2 x double> %tmp3,
    +                              <2 x double> %tmp7,
    +                              <2 x i32> < i32 0, i32 2 >
    +	store <2 x double> %tmp9, <2 x double>* %r, align 16
    +	ret void
    +        
    +; CHECK: t2:
    +; CHECK: 	movl	8(%esp), %eax
    +; CHECK-NEXT: 	movapd	(%eax), %xmm0
    +; CHECK-NEXT: 	movhpd	12(%esp), %xmm0
    +; CHECK-NEXT: 	movl	4(%esp), %eax
    +; CHECK-NEXT: 	movapd	%xmm0, (%eax)
    +; CHECK-NEXT: 	ret
    +}
    +
    +
    + +

    CHECK-NEXT: directives reject the input unless there is exactly one newline +between it an the previous directive. A CHECK-NEXT cannot be the first +directive in a file.

    + +
    + + + + +
    + +

    The CHECK-NOT: directive is used to verify that a string doesn't occur +between two matches (or the first match and the beginning of the file). For +example, to verify that a load is removed by a transformation, a test like this +can be used:

    + +
    +
    +define i8 @coerce_offset0(i32 %V, i32* %P) {
    +  store i32 %V, i32* %P
    +   
    +  %P2 = bitcast i32* %P to i8*
    +  %P3 = getelementptr i8* %P2, i32 2
    +
    +  %A = load i8* %P3
    +  ret i8 %A
    +; CHECK: @coerce_offset0
    +; CHECK-NOT: load
    +; CHECK: ret i8
    +}
    +
    +
    + +
    + + + + +
    + +

    The CHECK: and CHECK-NOT: directives both take a pattern to match. For most +uses of FileCheck, fixed string matching is perfectly sufficient. For some +things, a more flexible form of matching is desired. To support this, FileCheck +allows you to specify regular expressions in matching strings, surrounded by +double braces: {{yourregex}}. Because we want to use fixed string +matching for a majority of what we do, FileCheck has been designed to support +mixing and matching fixed string matching with regular expressions. This allows +you to write things like this:

    + +
    +
    +; CHECK: movhpd	{{[0-9]+}}(%esp), {{%xmm[0-7]}}
    +
    +
    + +

    In this case, any offset from the ESP register will be allowed, and any xmm +register will be allowed.

    + +

    Because regular expressions are enclosed with double braces, they are +visually distinct, and you don't need to use escape characters within the double +braces like you would in C. In the rare case that you want to match double +braces explicitly from the input, you can use something ugly like +{{[{][{]}} as your pattern.

    + +
    + + + + +
    + +

    It is often useful to match a pattern and then verify that it occurs again +later in the file. For codegen tests, this can be useful to allow any register, +but verify that that register is used consistently later. To do this, FileCheck +allows named variables to be defined and substituted into patterns. Here is a +simple example:

    + +
    +
    +; CHECK: test5:
    +; CHECK:    notw	[[REGISTER:%[a-z]+]]
    +; CHECK:    andw	{{.*}}[[REGISTER]]
    +
    +
    + +

    The first check line matches a regex (%[a-z]+) and captures it into +the variables "REGISTER". The second line verifies that whatever is in REGISTER +occurs later in the file after an "andw". FileCheck variable references are +always contained in [[ ]] pairs, are named, and their names can be +formed with the regex "[a-zA-Z][a-zA-Z0-9]*". If a colon follows the +name, then it is a definition of the variable, if not, it is a use.

    + +

    FileCheck variables can be defined multiple times, and uses always get the +latest value. Note that variables are all read at the start of a "CHECK" line +and are all defined at the end. This means that if you have something like +"CHECK: [[XYZ:.*]]x[[XYZ]]" that the check line will read the previous +value of the XYZ variable and define a new one after the match is performed. If +you need to do something like this you can probably take advantage of the fact +that FileCheck is not actually line-oriented when it matches, this allows you to +define two separate CHECK lines that match on the same line. +

    + + + +
    + + + + +
    +

    With a RUN line there are a number of substitutions that are permitted. In + general, any Tcl variable that is available in the substitute + function (in test/lib/llvm.exp) can be substituted into a RUN line. + To make a substitution just write the variable's name preceded by a $. + Additionally, for compatibility reasons with previous versions of the test + library, certain names can be accessed with an alternate syntax: a % prefix. + These alternates are deprecated and may go away in a future version. +

    +

    Here are the available variable names. The alternate syntax is listed in + parentheses.

    + +
    +
    $test (%s)
    +
    The full path to the test case's source. This is suitable for passing + on the command line as the input to an llvm tool.
    + +
    $srcdir
    +
    The source directory from where the "make check" was run.
    + +
    objdir
    +
    The object directory that corresponds to the $srcdir.
    + +
    subdir
    +
    A partial path from the test directory that contains the + sub-directory that contains the test source being executed.
    + +
    srcroot
    +
    The root directory of the LLVM src tree.
    + +
    objroot
    +
    The root directory of the LLVM object tree. This could be the same + as the srcroot.
    + +
    path
    +
    The path to the directory that contains the test case source. This is + for locating any supporting files that are not generated by the test, but + used by the test.
    + +
    tmp
    +
    The path to a temporary file name that could be used for this test case. + The file name won't conflict with other test cases. You can append to it if + you need multiple temporaries. This is useful as the destination of some + redirected output.
    + +
    llvmlibsdir (%llvmlibsdir)
    +
    The directory where the LLVM libraries are located.
    + +
    target_triplet (%target_triplet)
    +
    The target triplet that corresponds to the current host machine (the one + running the test cases). This should probably be called "host".
    + +
    llvmgcc (%llvmgcc)
    +
    The full path to the llvm-gcc executable as specified in the + configured LLVM environment
    + +
    llvmgxx (%llvmgxx)
    +
    The full path to the llvm-gxx executable as specified in the + configured LLVM environment
    + +
    llvmgcc_version (%llvmgcc_version)
    +
    The full version number of the llvm-gcc executable.
    + +
    llvmgccmajvers (%llvmgccmajvers)
    +
    The major version number of the llvm-gcc executable.
    + +
    gccpath
    +
    The full path to the C compiler used to build LLVM. Note that + this might not be gcc.
    + +
    gxxpath
    +
    The full path to the C++ compiler used to build LLVM. Note that + this might not be g++.
    + +
    compile_c (%compile_c)
    +
    The full command line used to compile LLVM C source code. This has all + the configured -I, -D and optimization options.
    + +
    compile_cxx (%compile_cxx)
    +
    The full command used to compile LLVM C++ source code. This has + all the configured -I, -D and optimization options.
    + +
    link (%link)
    +
    This full link command used to link LLVM executables. This has all the + configured -I, -L and -l options.
    + +
    shlibext (%shlibext)
    +
    The suffix for the host platforms share library (dll) files. This + includes the period as the first character.
    +
    +

    To add more variables, two things need to be changed. First, add a line in + the test/Makefile that creates the site.exp file. This will + "set" the variable as a global in the site.exp file. Second, in the + test/lib/llvm.exp file, in the substitute proc, add the variable name + to the list of "global" declarations at the beginning of the proc. That's it, + the variable can then be used in test scripts.

    +
    + + + + +
    +

    To make RUN line writing easier, there are several shell scripts located + in the llvm/test/Scripts directory. This directory is in the PATH + when running tests, so you can just call these scripts using their name. For + example:

    +
    +
    ignore
    +
    This script runs its arguments and then always returns 0. This is useful + in cases where the test needs to cause a tool to generate an error (e.g. to + check the error output). However, any program in a pipeline that returns a + non-zero result will cause the test to fail. This script overcomes that + issue and nicely documents that the test case is purposefully ignoring the + result code of the tool
    + +
    not
    +
    This script runs its arguments and then inverts the result code from + it. Zero result codes become 1. Non-zero result codes become 0. This is + useful to invert the result of a grep. For example "not grep X" means + succeed only if you don't find X in the input.
    +
    + +

    Sometimes it is necessary to mark a test case as "expected fail" or XFAIL. + You can easily mark a test as XFAIL just by including XFAIL: on a + line near the top of the file. This signals that the test case should succeed + if the test fails. Such test cases are counted separately by DejaGnu. To + specify an expected fail, use the XFAIL keyword in the comments of the test + program followed by a colon and one or more regular expressions (separated by + a comma). The regular expressions allow you to XFAIL the test conditionally + by host platform. The regular expressions following the : are matched against + the target triplet or llvmgcc version number for the host machine. If there is + a match, the test is expected to fail. If not, the test is expected to + succeed. To XFAIL everywhere just specify XFAIL: *. When matching + the llvm-gcc version, you can specify the major (e.g. 3) or full version + (i.e. 3.4) number. Here is an example of an XFAIL line:

    + +
    +
    +; XFAIL: darwin,sun,llvmgcc4
    +
    +
    + +

    To make the output more useful, the llvm_runtest function wil + scan the lines of the test case for ones that contain a pattern that matches + PR[0-9]+. This is the syntax for specifying a PR (Problem Report) number that + is related to the test case. The number after "PR" specifies the LLVM bugzilla + number. When a PR number is specified, it will be used in the pass/fail + reporting. This is useful to quickly get some context when a test fails.

    + +

    Finally, any line that contains "END." will cause the special + interpretation of lines to terminate. This is generally done right after the + last RUN: line. This has two side effects: (a) it prevents special + interpretation of lines that are part of the test program, not the + instructions to the test case, and (b) it speeds things up for really big test + cases by avoiding interpretation of the remainder of the file.

    + +
    + + + + + +
    + +

    The test-suite module contains a number of programs that can be compiled +with LLVM and executed. These programs are compiled using the native compiler +and various LLVM backends. The output from the program compiled with the +native compiler is assumed correct; the results from the other programs are +compared to the native program output and pass if they match.

    + +

    When executing tests, it is usually a good idea to start out with a subset of +the available tests or programs. This makes test run times smaller at first and +later on this is useful to investigate individual test failures. To run some +test only on a subset of programs, simply change directory to the programs you +want tested and run gmake there. Alternatively, you can run a different +test using the TEST variable to change what tests or run on the +selected programs (see below for more info).

    + +

    In addition for testing correctness, the llvm-test directory also +performs timing tests of various LLVM optimizations. It also records +compilation times for the compilers and the JIT. This information can be +used to compare the effectiveness of LLVM's optimizations and code +generation.

    + +

    llvm-test tests are divided into three types of tests: MultiSource, +SingleSource, and External.

    + +
      +
    • llvm-test/SingleSource +

      The SingleSource directory contains test programs that are only a single +source file in size. These are usually small benchmark programs or small +programs that calculate a particular value. Several such programs are grouped +together in each directory.

    • + +
    • llvm-test/MultiSource +

      The MultiSource directory contains subdirectories which contain entire +programs with multiple source files. Large benchmarks and whole applications +go here.

    • + +
    • llvm-test/External +

      The External directory contains Makefiles for building code that is external +to (i.e., not distributed with) LLVM. The most prominent members of this +directory are the SPEC 95 and SPEC 2000 benchmark suites. The External +directory does not contain these actual tests, but only the Makefiles that know +how to properly compile these programs from somewhere else. The presence and +location of these external programs is configured by the llvm-test +configure script.

    • +
    + +

    Each tree is then subdivided into several categories, including applications, +benchmarks, regression tests, code that is strange grammatically, etc. These +organizations should be relatively self explanatory.

    + +

    Some tests are known to fail. Some are bugs that we have not fixed yet; +others are features that we haven't added yet (or may never add). In DejaGNU, +the result for such tests will be XFAIL (eXpected FAILure). In this way, you +can tell the difference between an expected and unexpected failure.

    + +

    The tests in the test suite have no such feature at this time. If the +test passes, only warnings and other miscellaneous output will be generated. If +a test fails, a large <program> FAILED message will be displayed. This +will help you separate benign warnings from actual test failures.

    + +
    + + + + + +
    + +

    First, all tests are executed within the LLVM object directory tree. They +are not executed inside of the LLVM source tree. This is because the +test suite creates temporary files during execution.

    + +

    To run the test suite, you need to use the following steps:

    + +
      +
    1. cd into the llvm/projects directory in your source tree. +
    2. + +
    3. Check out the test-suite module with:

      + +
      +
      +% svn co http://llvm.org/svn/llvm-project/test-suite/trunk test-suite
      +
      +
      +

      This will get the test suite into llvm/projects/test-suite.

      +
    4. +
    5. Configure and build llvm.

    6. +
    7. Configure and build llvm-gcc.

    8. +
    9. Install llvm-gcc somewhere.

    10. +
    11. Re-configure llvm from the top level of + each build tree (LLVM object directory tree) in which you want + to run the test suite, just as you do before building LLVM.

      +

      During the re-configuration, you must either: (1) + have llvm-gcc you just built in your path, or (2) + specify the directory where your just-built llvm-gcc is + installed using --with-llvmgccdir=$LLVM_GCC_DIR.

      +

      You must also tell the configure machinery that the test suite + is available so it can be configured for your build tree:

      +
      +
      +% cd $LLVM_OBJ_ROOT ; $LLVM_SRC_ROOT/configure [--with-llvmgccdir=$LLVM_GCC_DIR]
      +
      +
      +

      [Remember that $LLVM_GCC_DIR is the directory where you + installed llvm-gcc, not its src or obj directory.]

      +
    12. + +
    13. You can now run the test suite from your build tree as follows:

      +
      +
      +% cd $LLVM_OBJ_ROOT/projects/test-suite
      +% make
      +
      +
      +
    14. +
    +

    Note that the second and third steps only need to be done once. After you +have the suite checked out and configured, you don't need to do it again (unless +the test code or configure script changes).

    + +
    + + + + + +
    +

    In order to run the External tests in the test-suite + module, you must specify --with-externals. This + must be done during the re-configuration step (see above), + and the llvm re-configuration must recognize the + previously-built llvm-gcc. If any of these is missing or + neglected, the External tests won't work.

    +
    +
    --with-externals
    +
    --with-externals=<directory>
    +
    + This tells LLVM where to find any external tests. They are expected to be + in specifically named subdirectories of <directory>. + If directory is left unspecified, + configure uses the default value + /home/vadve/shared/benchmarks/speccpu2000/benchspec. + Subdirectory names known to LLVM include: +
    +
    spec95
    +
    speccpu2000
    +
    speccpu2006
    +
    povray31
    +
    + Others are added from time to time, and can be determined from + configure. +
    + + + + +
    +

    In addition to the regular "whole program" tests, the test-suite +module also provides a mechanism for compiling the programs in different ways. +If the variable TEST is defined on the gmake command line, the test system will +include a Makefile named TEST.<value of TEST variable>.Makefile. +This Makefile can modify build rules to yield different results.

    + +

    For example, the LLVM nightly tester uses TEST.nightly.Makefile to +create the nightly test reports. To run the nightly tests, run gmake +TEST=nightly.

    + +

    There are several TEST Makefiles available in the tree. Some of them are +designed for internal LLVM research and will not work outside of the LLVM +research group. They may still be valuable, however, as a guide to writing your +own TEST Makefile for any optimization or analysis passes that you develop with +LLVM.

    + +
    + + + + +
    +

    There are a number of ways to run the tests and generate output. The most + simple one is simply running gmake with no arguments. This will + compile and run all programs in the tree using a number of different methods + and compare results. Any failures are reported in the output, but are likely + drowned in the other output. Passes are not reported explicitely.

    + +

    Somewhat better is running gmake TEST=sometest test, which runs + the specified test and usually adds per-program summaries to the output + (depending on which sometest you use). For example, the nightly test + explicitely outputs TEST-PASS or TEST-FAIL for every test after each program. + Though these lines are still drowned in the output, it's easy to grep the + output logs in the Output directories.

    + +

    Even better are the report and report.format targets + (where format is one of html, csv, text or + graphs). The exact contents of the report are dependent on which + TEST you are running, but the text results are always shown at the + end of the run and the results are always stored in the + report.<type>.format file (when running with + TEST=<type>). + + The report also generate a file called + report.<type>.raw.out containing the output of the entire test + run. +

    + + + + + +
    + +

    Assuming you can run the test suite, (e.g. "gmake TEST=nightly report" +should work), it is really easy to run optimizations or code generator +components against every program in the tree, collecting statistics or running +custom checks for correctness. At base, this is how the nightly tester works, +it's just one example of a general framework.

    + +

    Lets say that you have an LLVM optimization pass, and you want to see how +many times it triggers. First thing you should do is add an LLVM +statistic to your pass, which +will tally counts of things you care about.

    + +

    Following this, you can set up a test and a report that collects these and +formats them for easy viewing. This consists of two files, an +"test-suite/TEST.XXX.Makefile" fragment (where XXX is the name of your +test) and an "llvm-test/TEST.XXX.report" file that indicates how to +format the output into a table. There are many example reports of various +levels of sophistication included with the test suite, and the framework is very +general.

    + +

    If you are interested in testing an optimization pass, check out the +"libcalls" test as an example. It can be run like this:

    + +

    +
    +% cd llvm/projects/test-suite/MultiSource/Benchmarks  # or some other level
    +% make TEST=libcalls report
    +
    +
    + +

    This will do a bunch of stuff, then eventually print a table like this:

    + +
    +
    +Name                                  | total | #exit |
    +...
    +FreeBench/analyzer/analyzer           | 51    | 6     | 
    +FreeBench/fourinarow/fourinarow       | 1     | 1     | 
    +FreeBench/neural/neural               | 19    | 9     | 
    +FreeBench/pifft/pifft                 | 5     | 3     | 
    +MallocBench/cfrac/cfrac               | 1     | *     | 
    +MallocBench/espresso/espresso         | 52    | 12    | 
    +MallocBench/gs/gs                     | 4     | *     | 
    +Prolangs-C/TimberWolfMC/timberwolfmc  | 302   | *     | 
    +Prolangs-C/agrep/agrep                | 33    | 12    | 
    +Prolangs-C/allroots/allroots          | *     | *     | 
    +Prolangs-C/assembler/assembler        | 47    | *     | 
    +Prolangs-C/bison/mybison              | 74    | *     | 
    +...
    +
    +
    + +

    This basically is grepping the -stats output and displaying it in a table. +You can also use the "TEST=libcalls report.html" target to get the table in HTML +form, similarly for report.csv and report.tex.

    + +

    The source for this is in test-suite/TEST.libcalls.*. The format is pretty +simple: the Makefile indicates how to run the test (in this case, +"opt -simplify-libcalls -stats"), and the report contains one line for +each column of the output. The first value is the header for the column and the +second is the regex to grep the output of the command for. There are lots of +example reports that can do fancy stuff.

    + +
    + + + + + + +
    + +

    +The LLVM Nightly Testers +automatically check out an LLVM tree, build it, run the "nightly" +program test (described above), run all of the DejaGNU tests, +delete the checked out tree, and then submit the results to +http://llvm.org/nightlytest/. +After test results are submitted to +http://llvm.org/nightlytest/, +they are processed and displayed on the tests page. An email to + +llvm-testresults@cs.uiuc.edu summarizing the results is also generated. +This testing scheme is designed to ensure that programs don't break as well +as keep track of LLVM's progress over time.

    + +

    If you'd like to set up an instance of the nightly tester to run on your +machine, take a look at the comments at the top of the +utils/NewNightlyTest.pl file. If you decide to set up a nightly tester +please choose a unique nickname and invoke utils/NewNightlyTest.pl +with the "-nickname [yournickname]" command line option. + +

    You can create a shell script to encapsulate the running of the script. +The optimized x86 Linux nightly test is run from just such a script:

    + +
    +
    +#!/bin/bash
    +BASE=/proj/work/llvm/nightlytest
    +export BUILDDIR=$BASE/build 
    +export WEBDIR=$BASE/testresults 
    +export LLVMGCCDIR=/proj/work/llvm/cfrontend/install
    +export PATH=/proj/install/bin:$LLVMGCCDIR/bin:$PATH
    +export LD_LIBRARY_PATH=/proj/install/lib
    +cd $BASE
    +cp /proj/work/llvm/llvm/utils/NewNightlyTest.pl .
    +nice ./NewNightlyTest.pl -nice -release -verbose -parallel -enable-linscan \
    +   -nickname NightlyTester -noexternals > output.log 2>&1 
    +
    +
    + +

    It is also possible to specify the the location your nightly test results +are submitted. You can do this by passing the command line option +"-submit-server [server_address]" and "-submit-script [script_on_server]" to +utils/NewNightlyTest.pl. For example, to submit to the llvm.org +nightly test results page, you would invoke the nightly test script with +"-submit-server llvm.org -submit-script /nightlytest/NightlyTestAccept.cgi". +If these options are not specified, the nightly test script sends the results +to the llvm.org nightly test results page.

    + +

    Take a look at the NewNightlyTest.pl file to see what all of the +flags and strings do. If you start running the nightly tests, please let us +know. Thanks!

    + +
    + + + +
    +
    + Valid CSS + Valid HTML 4.01 + + John T. Criswell, Reid Spencer, and Tanya Lattner
    + The LLVM Compiler Infrastructure
    + Last modified: $Date$ +
    + + diff --git a/libclamav/c++/llvm/docs/UsingLibraries.html b/libclamav/c++/llvm/docs/UsingLibraries.html new file mode 100644 index 000000000..b1a3b4de6 --- /dev/null +++ b/libclamav/c++/llvm/docs/UsingLibraries.html @@ -0,0 +1,439 @@ + + + + Using The LLVM Libraries + + + +
    Using The LLVM Libraries
    +
      +
    1. Abstract
    2. +
    3. Introduction
    4. +
    5. Library Descriptions
    6. +
    7. Library Dependencies
    8. +
    9. Linkage Rules Of Thumb +
        +
      1. Always link LLVMCore, LLVMSupport, LLVMSystem +
      2. Never link both archive and re-linked +
      +
    10. +
    + +
    +

    Written by Reid Spencer

    +
    + +

    Warning: This document is out of date, please see llvm-config for more information.

    + + + +
    +

    Amongst other things, LLVM is a toolkit for building compilers, linkers, + runtime executives, virtual machines, and other program execution related + tools. In addition to the LLVM tool set, the functionality of LLVM is + available through a set of libraries. To use LLVM as a toolkit for + constructing tools, a developer needs to understand what is contained in the + various libraries, what they depend on, and how to use them. Fortunately, + there is a tool, llvm-config to aid with this. This document + describes the contents of the libraries and how to use llvm-config + to generate command line options. +

    +
    + + + +
    +

    If you're writing a compiler, virtual machine, or any other utility based + on LLVM, you'll need to figure out which of the many libraries files you will + need to link with to be successful. An understanding of the contents of these + libraries will be useful in coming up with an optimal specification for the + libraries to link with. The purpose of this document is to reduce some of + the trial and error that the author experienced in using LLVM.

    +

    LLVM produces two types of libraries: archives (ending in .a) and + objects (ending in .o). However, both are libraries. Libraries ending + in .o are known as re-linked libraries because they contain all the + compilation units of the library linked together as a single .o file. + Furthermore, several of the libraries have both forms of library. The + re-linked libraries are used whenever you want to include all symbols from the + library. The archive libraries are used whenever you want to only resolve + outstanding symbols at that point in the link without including everything in + the library.

    +

    If you're using the LLVM Makefile system to link your tools,you will use + the LLVMLIBS make variable. + (see the Makefile Guide for + details). This variable specifies which LLVM libraries to link into your tool + and the order in which they will be linked. You specify re-linked libraries by + naming the library without a suffix. You specify archive libraries by naming + the library with a .a suffix but without the lib prefix. The + order in which the libraries appear in the LLVMLIBS variable + definition is the order in which they will be linked. Getting this order + correct for your tool can sometimes be challenging. +

    + +
    Library Descriptions
    +
    +

    The table below categorizes each library + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    LibraryFormsDescription
    Core Libraries
    LLVMArchive.aLLVM archive reading and writing
    LLVMAsmParser.aLLVM assembly parsing
    LLVMBCReader.aLLVM bitcode reading
    LLVMBCWriter.aLLVM bitcode writing
    LLVMCore.aLLVM core intermediate representation
    LLVMDebugger.aSource level debugging support
    LLVMLinker.aBitcode and archive linking interface
    LLVMSupport.aGeneral support utilities
    LLVMSystem.aOperating system abstraction layer
    LLVMbzip2.aBZip2 compression library
    Analysis Libraries
    LLVMAnalysis.aVarious analysis passes.
    LLVMDataStructure.oData structure analysis passes.
    LLVMipa.aInter-procedural analysis passes.
    Transformation Libraries
    LLVMInstrumentation.aInstrumentation passes.
    LLVMipo.aAll inter-procedural optimization passes.
    LLVMScalarOpts.aAll scalar optimization passes.
    LLVMTransformUtils.aTransformation utilities used by many passes.
    Code Generation Libraries
    LLVMCodeGen.oNative code generation infrastructure
    LLVMSelectionDAG.oAggressive instruction selector for directed acyclic graphs
    Target Libraries
    LLVMAlpha.oCode generation for Alpha architecture
    LLVMARM.oCode generation for ARM architecture
    LLVMCBackend.o'C' language code generator.
    LLVMPowerPC.oCode generation for PowerPC architecture
    LLVMSparc.oCode generation for Sparc architecture
    LLVMTarget.aGeneric code generation utilities.
    LLVMX86.oCode generation for Intel x86 architecture
    Runtime Libraries
    LLVMInterpreter.oBitcode Interpreter
    LLVMJIT.oBitcode JIT Compiler
    LLVMExecutionEngine.oVirtual machine engine
    +

    + + +
    Using llvm-config
    +
    +

    The llvm-config tool is a perl script that produces on its output + various kinds of information. For example, the source or object directories + used to build LLVM can be accessed by passing options to llvm-config. + For complete details on this tool, please see the + manual page.

    +

    To understand the relationships between libraries, the llvm-config + can be very useful. If all you know is that you want certain libraries to + be available, you can generate the complete set of libraries to link with + using one of four options, as below:

    +
      +
    1. --ldflags. This generates the command line options necessary to + be passed to the ld tool in order to link with LLVM. Most notably, + the -L option is provided to specify a library search directory + that contains the LLVM libraries.
    2. +
    3. --libs. This generates command line options suitable for + use with a gcc-style linker. That is, libraries are given with a -l option + and object files are given with a full path.
    4. +
    5. --libnames. This generates a list of just the library file + names. If you know the directory in which these files reside (see --ldflags) + then you can find the libraries there.
    6. +
    7. --libfiles. This generates the full path names of the + LLVM library files.
    8. +
    +

    If you wish to delve further into how llvm-config generates the + correct order (based on library dependencies), please see the tool named + GenLibDeps.pl in the utils source directory of LLVM.

    + + + + + + + +

    Dependency Relationships Of Libraries

    +

    This graph shows the dependency of archive libraries on other archive + libraries or objects. Where a library has both archive and object forms, only + the archive form is shown.

    + Library Dependencies +

    Dependency Relationships Of Object Files

    +

    This graph shows the dependency of object files on archive libraries or + other objects. Where a library has both object and archive forms, only the + dependency to the archive form is shown.

    + Object File Dependencies +

    The following list shows the dependency relationships between libraries in + textual form. The information is the same as shown on the graphs but arranged + alphabetically.

    +
    +
    libLLVMAnalysis.a
      +
    • libLLVMCore.a
    • +
    • libLLVMSupport.a
    • +
    • libLLVMSystem.a
    • +
    • libLLVMTarget.a
    • +
    +
    libLLVMArchive.a
      +
    • libLLVMBCReader.a
    • +
    • libLLVMCore.a
    • +
    • libLLVMSupport.a
    • +
    • libLLVMSystem.a
    • +
    +
    libLLVMAsmParser.a
      +
    • libLLVMCore.a
    • +
    • libLLVMSystem.a
    • +
    +
    libLLVMBCReader.a
      +
    • libLLVMCore.a
    • +
    • libLLVMSupport.a
    • +
    • libLLVMSystem.a
    • +
    +
    libLLVMBCWriter.a
      +
    • libLLVMCore.a
    • +
    • libLLVMSupport.a
    • +
    • libLLVMSystem.a
    • +
    +
    libLLVMCodeGen.a
      +
    • libLLVMAnalysis.a
    • +
    • libLLVMCore.a
    • +
    • libLLVMScalarOpts.a
    • +
    • libLLVMSupport.a
    • +
    • libLLVMSystem.a
    • +
    • libLLVMTarget.a
    • +
    • libLLVMTransformUtils.a
    • +
    +
    libLLVMCore.a
      +
    • libLLVMSupport.a
    • +
    • libLLVMSystem.a
    • +
    +
    libLLVMDebugger.a
      +
    • libLLVMBCReader.a
    • +
    • libLLVMCore.a
    • +
    • libLLVMSupport.a
    • +
    • libLLVMSystem.a
    • +
    +
    libLLVMInstrumentation.a
      +
    • libLLVMCore.a
    • +
    • libLLVMScalarOpts.a
    • +
    • libLLVMSupport.a
    • +
    • libLLVMTransformUtils.a
    • +
    +
    libLLVMLinker.a
      +
    • libLLVMArchive.a
    • +
    • libLLVMBCReader.a
    • +
    • libLLVMCore.a
    • +
    • libLLVMSupport.a
    • +
    • libLLVMSystem.a
    • +
    +
    libLLVMScalarOpts.a
      +
    • libLLVMAnalysis.a
    • +
    • libLLVMCore.a
    • +
    • libLLVMSupport.a
    • +
    • libLLVMSystem.a
    • +
    • libLLVMTarget.a
    • +
    • libLLVMTransformUtils.a
    • +
    +
    libLLVMSelectionDAG.a
      +
    • libLLVMAnalysis.a
    • +
    • libLLVMCodeGen.a
    • +
    • libLLVMCore.a
    • +
    • libLLVMSupport.a
    • +
    • libLLVMSystem.a
    • +
    • libLLVMTarget.a
    • +
    • libLLVMTransformUtils.a
    • +
    +
    libLLVMSupport.a
      +
    • libLLVMSystem.a
    • +
    • libLLVMbzip2.a
    • +
    +
    libLLVMSystem.a
      +
    +
    libLLVMTarget.a
      +
    • libLLVMCore.a
    • +
    • libLLVMSupport.a
    • +
    • libLLVMSystem.a
    • +
    +
    libLLVMTransformUtils.a
      +
    • libLLVMAnalysis.a
    • +
    • libLLVMCore.a
    • +
    • libLLVMSupport.a
    • +
    • libLLVMSystem.a
    • +
    • libLLVMTarget.a
    • +
    • libLLVMipa.a
    • +
    +
    libLLVMbzip2.a
      +
    +
    libLLVMipa.a
      +
    • libLLVMAnalysis.a
    • +
    • libLLVMCore.a
    • +
    • libLLVMSupport.a
    • +
    • libLLVMSystem.a
    • +
    +
    libLLVMipo.a
      +
    • libLLVMAnalysis.a
    • +
    • libLLVMCore.a
    • +
    • libLLVMSupport.a
    • +
    • libLLVMSystem.a
    • +
    • libLLVMTarget.a
    • +
    • libLLVMTransformUtils.a
    • +
    • libLLVMipa.a
    • +
    +
    libLLVMlto.a
      +
    • libLLVMAnalysis.a
    • +
    • libLLVMBCReader.a
    • +
    • libLLVMBCWriter.a
    • +
    • libLLVMCore.a
    • +
    • libLLVMLinker.a
    • +
    • libLLVMScalarOpts.a
    • +
    • libLLVMSupport.a
    • +
    • libLLVMSystem.a
    • +
    • libLLVMTarget.a
    • +
    • libLLVMipa.a
    • +
    • libLLVMipo.a
    • +
    +
    LLVMARM.o
      +
    • libLLVMCodeGen.a
    • +
    • libLLVMCore.a
    • +
    • libLLVMSelectionDAG.a
    • +
    • libLLVMSupport.a
    • +
    • libLLVMSystem.a
    • +
    • libLLVMTarget.a
    • +
    +
    LLVMAlpha.o
      +
    • libLLVMCodeGen.a
    • +
    • libLLVMCore.a
    • +
    • libLLVMSelectionDAG.a
    • +
    • libLLVMSupport.a
    • +
    • libLLVMSystem.a
    • +
    • libLLVMTarget.a
    • +
    +
    LLVMCBackend.o
      +
    • libLLVMAnalysis.a
    • +
    • libLLVMCodeGen.a
    • +
    • libLLVMCore.a
    • +
    • libLLVMScalarOpts.a
    • +
    • libLLVMSupport.a
    • +
    • libLLVMSystem.a
    • +
    • libLLVMTarget.a
    • +
    • libLLVMTransformUtils.a
    • +
    • libLLVMipa.a
    • +
    +
    LLVMExecutionEngine.o
      +
    • libLLVMCore.a
    • +
    • libLLVMSupport.a
    • +
    • libLLVMSystem.a
    • +
    • libLLVMTarget.a
    • +
    +
    LLVMInterpreter.o
      +
    • LLVMExecutionEngine.o
    • +
    • libLLVMCodeGen.a
    • +
    • libLLVMCore.a
    • +
    • libLLVMSupport.a
    • +
    • libLLVMSystem.a
    • +
    • libLLVMTarget.a
    • +
    +
    LLVMJIT.o
      +
    • LLVMExecutionEngine.o
    • +
    • libLLVMCore.a
    • +
    • libLLVMSupport.a
    • +
    • libLLVMSystem.a
    • +
    • libLLVMTarget.a
    • +
    +
    LLVMPowerPC.o
      +
    • libLLVMCodeGen.a
    • +
    • libLLVMCore.a
    • +
    • libLLVMSelectionDAG.a
    • +
    • libLLVMSupport.a
    • +
    • libLLVMSystem.a
    • +
    • libLLVMTarget.a
    • +
    +
    LLVMSparc.o
      +
    • libLLVMCodeGen.a
    • +
    • libLLVMCore.a
    • +
    • libLLVMSelectionDAG.a
    • +
    • libLLVMSupport.a
    • +
    • libLLVMSystem.a
    • +
    • libLLVMTarget.a
    • +
    +
    LLVMX86.o
      +
    • libLLVMCodeGen.a
    • +
    • libLLVMCore.a
    • +
    • libLLVMSelectionDAG.a
    • +
    • libLLVMSupport.a
    • +
    • libLLVMSystem.a
    • +
    • libLLVMTarget.a
    • +
    +
    +
    + + + +
    +

    This section contains various "rules of thumb" about what files you + should link into your programs.

    +
    + + +
    +

    No matter what you do with LLVM, the last three entries in the value of + your LLVMLIBS make variable should always be: + LLVMCore LLVMSupport.a LLVMSystem.a. There are no LLVM + programs that don't depend on these three.

    +
    + + +
    +

    There is never any point to linking both the re-linked (.o) and + the archive (.a) versions of a library. Since the re-linked version + includes the entire library, the archive version will not resolve any symbols. + You could even end up with link error if you place the archive version before + the re-linked version on the linker's command line.

    +
    + +
    + + + + diff --git a/libclamav/c++/llvm/docs/WritingAnLLVMBackend.html b/libclamav/c++/llvm/docs/WritingAnLLVMBackend.html new file mode 100644 index 000000000..c0d6a129e --- /dev/null +++ b/libclamav/c++/llvm/docs/WritingAnLLVMBackend.html @@ -0,0 +1,2570 @@ + + + + + Writing an LLVM Compiler Backend + + + + + +
    + Writing an LLVM Compiler Backend +
    + +
      +
    1. Introduction + +
    2. Target Machine
    3. +
    4. Target Registration
    5. +
    6. Register Set and Register Classes +
    7. +
    8. Instruction Set +
    9. +
    10. Instruction Selector +
    11. +
    12. Assembly Printer
    13. +
    14. Subtarget Support
    15. +
    16. JIT Support +
    17. +
    + +
    +

    Written by Mason Woo and + Misha Brukman

    +
    + + + + + +
    + +

    +This document describes techniques for writing compiler backends that convert +the LLVM Intermediate Representation (IR) to code for a specified machine or +other languages. Code intended for a specific machine can take the form of +either assembly code or binary code (usable for a JIT compiler). +

    + +

    +The backend of LLVM features a target-independent code generator that may create +output for several types of target CPUs — including X86, PowerPC, Alpha, +and SPARC. The backend may also be used to generate code targeted at SPUs of the +Cell processor or GPUs to support the execution of compute kernels. +

    + +

    +The document focuses on existing examples found in subdirectories +of llvm/lib/Target in a downloaded LLVM release. In particular, this +document focuses on the example of creating a static compiler (one that emits +text assembly) for a SPARC target, because SPARC has fairly standard +characteristics, such as a RISC instruction set and straightforward calling +conventions. +

    + +
    + + + +
    + +

    +The audience for this document is anyone who needs to write an LLVM backend to +generate code for a specific hardware or software target. +

    + +
    + + + +
    + +

    +These essential documents must be read before reading this document: +

    + +
      +
    • LLVM Language Reference + Manual — a reference manual for the LLVM assembly language.
    • + +
    • The LLVM + Target-Independent Code Generator — a guide to the components + (classes and code generation algorithms) for translating the LLVM internal + representation into machine code for a specified target. Pay particular + attention to the descriptions of code generation stages: Instruction + Selection, Scheduling and Formation, SSA-based Optimization, Register + Allocation, Prolog/Epilog Code Insertion, Late Machine Code Optimizations, + and Code Emission.
    • + +
    • TableGen + Fundamentals —a document that describes the TableGen + (tblgen) application that manages domain-specific information to + support LLVM code generation. TableGen processes input from a target + description file (.td suffix) and generates C++ code that can be + used for code generation.
    • + +
    • Writing an LLVM + Pass — The assembly printer is a FunctionPass, as are + several SelectionDAG processing steps.
    • +
    + +

    +To follow the SPARC examples in this document, have a copy of +The SPARC Architecture +Manual, Version 8 for reference. For details about the ARM instruction +set, refer to the ARM Architecture +Reference Manual. For more about the GNU Assembler format +(GAS), see +Using As, +especially for the assembly printer. Using As contains a list of target +machine dependent features. +

    + +
    + + + +
    + +

    +To write a compiler backend for LLVM that converts the LLVM IR to code for a +specified target (machine or other language), follow these steps: +

    + +
      +
    • Create a subclass of the TargetMachine class that describes characteristics + of your target machine. Copy existing examples of specific TargetMachine + class and header files; for example, start with + SparcTargetMachine.cpp and SparcTargetMachine.h, but + change the file names for your target. Similarly, change code that + references "Sparc" to reference your target.
    • + +
    • Describe the register set of the target. Use TableGen to generate code for + register definition, register aliases, and register classes from a + target-specific RegisterInfo.td input file. You should also write + additional code for a subclass of the TargetRegisterInfo class that + represents the class register file data used for register allocation and + also describes the interactions between registers.
    • + +
    • Describe the instruction set of the target. Use TableGen to generate code + for target-specific instructions from target-specific versions of + TargetInstrFormats.td and TargetInstrInfo.td. You should + write additional code for a subclass of the TargetInstrInfo class to + represent machine instructions supported by the target machine.
    • + +
    • Describe the selection and conversion of the LLVM IR from a Directed Acyclic + Graph (DAG) representation of instructions to native target-specific + instructions. Use TableGen to generate code that matches patterns and + selects instructions based on additional information in a target-specific + version of TargetInstrInfo.td. Write code + for XXXISelDAGToDAG.cpp, where XXX identifies the specific target, + to perform pattern matching and DAG-to-DAG instruction selection. Also write + code in XXXISelLowering.cpp to replace or remove operations and + data types that are not supported natively in a SelectionDAG.
    • + +
    • Write code for an assembly printer that converts LLVM IR to a GAS format for + your target machine. You should add assembly strings to the instructions + defined in your target-specific version of TargetInstrInfo.td. You + should also write code for a subclass of AsmPrinter that performs the + LLVM-to-assembly conversion and a trivial subclass of TargetAsmInfo.
    • + +
    • Optionally, add support for subtargets (i.e., variants with different + capabilities). You should also write code for a subclass of the + TargetSubtarget class, which allows you to use the -mcpu= + and -mattr= command-line options.
    • + +
    • Optionally, add JIT support and create a machine code emitter (subclass of + TargetJITInfo) that is used to emit binary code directly into memory.
    • +
    + +

    +In the .cpp and .h. files, initially stub up these methods and +then implement them later. Initially, you may not know which private members +that the class will need and which components will need to be subclassed. +

    + +
    + + + +
    + +

    +To actually create your compiler backend, you need to create and modify a few +files. The absolute minimum is discussed here. But to actually use the LLVM +target-independent code generator, you must perform the steps described in +the LLVM +Target-Independent Code Generator document. +

    + +

    +First, you should create a subdirectory under lib/Target to hold all +the files related to your target. If your target is called "Dummy," create the +directory lib/Target/Dummy. +

    + +

    +In this new +directory, create a Makefile. It is easiest to copy a +Makefile of another target and modify it. It should at least contain +the LEVEL, LIBRARYNAME and TARGET variables, and then +include $(LEVEL)/Makefile.common. The library can be +named LLVMDummy (for example, see the MIPS target). Alternatively, you +can split the library into LLVMDummyCodeGen +and LLVMDummyAsmPrinter, the latter of which should be implemented in a +subdirectory below lib/Target/Dummy (for example, see the PowerPC +target). +

    + +

    +Note that these two naming schemes are hardcoded into llvm-config. +Using any other naming scheme will confuse llvm-config and produce a +lot of (seemingly unrelated) linker errors when linking llc. +

    + +

    +To make your target actually do something, you need to implement a subclass of +TargetMachine. This implementation should typically be in the file +lib/Target/DummyTargetMachine.cpp, but any file in +the lib/Target directory will be built and should work. To use LLVM's +target independent code generator, you should do what all current machine +backends do: create a subclass of LLVMTargetMachine. (To create a +target from scratch, create a subclass of TargetMachine.) +

    + +

    +To get LLVM to actually build and link your target, you need to add it to +the TARGETS_TO_BUILD variable. To do this, you modify the configure +script to know about your target when parsing the --enable-targets +option. Search the configure script for TARGETS_TO_BUILD, add your +target to the lists there (some creativity required), and then +reconfigure. Alternatively, you can change autotools/configure.ac and +regenerate configure by running ./autoconf/AutoRegen.sh. +

    + +
    + + + + + +
    + +

    +LLVMTargetMachine is designed as a base class for targets implemented +with the LLVM target-independent code generator. The LLVMTargetMachine +class should be specialized by a concrete target class that implements the +various virtual methods. LLVMTargetMachine is defined as a subclass of +TargetMachine in include/llvm/Target/TargetMachine.h. The +TargetMachine class implementation (TargetMachine.cpp) also +processes numerous command-line options. +

    + +

    +To create a concrete target-specific subclass of LLVMTargetMachine, +start by copying an existing TargetMachine class and header. You +should name the files that you create to reflect your specific target. For +instance, for the SPARC target, name the files SparcTargetMachine.h and +SparcTargetMachine.cpp. +

    + +

    +For a target machine XXX, the implementation of +XXXTargetMachine must have access methods to obtain objects that +represent target components. These methods are named get*Info, and are +intended to obtain the instruction set (getInstrInfo), register set +(getRegisterInfo), stack frame layout (getFrameInfo), and +similar information. XXXTargetMachine must also implement the +getTargetData method to access an object with target-specific data +characteristics, such as data type size and alignment requirements. +

    + +

    +For instance, for the SPARC target, the header file +SparcTargetMachine.h declares prototypes for several get*Info +and getTargetData methods that simply return a class member. +

    + +
    +
    +namespace llvm {
    +
    +class Module;
    +
    +class SparcTargetMachine : public LLVMTargetMachine {
    +  const TargetData DataLayout;       // Calculates type size & alignment
    +  SparcSubtarget Subtarget;
    +  SparcInstrInfo InstrInfo;
    +  TargetFrameInfo FrameInfo;
    +  
    +protected:
    +  virtual const TargetAsmInfo *createTargetAsmInfo() const;
    +  
    +public:
    +  SparcTargetMachine(const Module &M, const std::string &FS);
    +
    +  virtual const SparcInstrInfo *getInstrInfo() const {return &InstrInfo; }
    +  virtual const TargetFrameInfo *getFrameInfo() const {return &FrameInfo; }
    +  virtual const TargetSubtarget *getSubtargetImpl() const{return &Subtarget; }
    +  virtual const TargetRegisterInfo *getRegisterInfo() const {
    +    return &InstrInfo.getRegisterInfo();
    +  }
    +  virtual const TargetData *getTargetData() const { return &DataLayout; }
    +  static unsigned getModuleMatchQuality(const Module &M);
    +
    +  // Pass Pipeline Configuration
    +  virtual bool addInstSelector(PassManagerBase &PM, bool Fast);
    +  virtual bool addPreEmitPass(PassManagerBase &PM, bool Fast);
    +  virtual bool addAssemblyEmitter(PassManagerBase &PM, bool Fast, 
    +                                  std::ostream &Out);
    +};
    +
    +} // end namespace llvm
    +
    +
    + +
    + + +
    + +
      +
    • getInstrInfo()
    • +
    • getRegisterInfo()
    • +
    • getFrameInfo()
    • +
    • getTargetData()
    • +
    • getSubtargetImpl()
    • +
    + +

    For some targets, you also need to support the following methods:

    + +
      +
    • getTargetLowering()
    • +
    • getJITInfo()
    • +
    + +

    +In addition, the XXXTargetMachine constructor should specify a +TargetDescription string that determines the data layout for the target +machine, including characteristics such as pointer size, alignment, and +endianness. For example, the constructor for SparcTargetMachine contains the +following: +

    + +
    +
    +SparcTargetMachine::SparcTargetMachine(const Module &M, const std::string &FS)
    +  : DataLayout("E-p:32:32-f128:128:128"),
    +    Subtarget(M, FS), InstrInfo(Subtarget),
    +    FrameInfo(TargetFrameInfo::StackGrowsDown, 8, 0) {
    +}
    +
    +
    + +
    + +
    + +

    Hyphens separate portions of the TargetDescription string.

    + +
      +
    • An upper-case "E" in the string indicates a big-endian target data + model. a lower-case "e" indicates little-endian.
    • + +
    • "p:" is followed by pointer information: size, ABI alignment, and + preferred alignment. If only two figures follow "p:", then the + first value is pointer size, and the second value is both ABI and preferred + alignment.
    • + +
    • Then a letter for numeric type alignment: "i", "f", + "v", or "a" (corresponding to integer, floating point, + vector, or aggregate). "i", "v", or "a" are + followed by ABI alignment and preferred alignment. "f" is followed + by three values: the first indicates the size of a long double, then ABI + alignment, and then ABI preferred alignment.
    • +
    + +
    + + + + + +
    + +

    +You must also register your target with the TargetRegistry, which is +what other LLVM tools use to be able to lookup and use your target at +runtime. The TargetRegistry can be used directly, but for most targets +there are helper templates which should take care of the work for you.

    + +

    +All targets should declare a global Target object which is used to +represent the target during registration. Then, in the target's TargetInfo +library, the target should define that object and use +the RegisterTarget template to register the target. For example, the Sparc registration code looks like this: +

    + +
    +
    +Target llvm::TheSparcTarget;
    +
    +extern "C" void LLVMInitializeSparcTargetInfo() { 
    +  RegisterTarget<Triple::sparc, /*HasJIT=*/false>
    +    X(TheSparcTarget, "sparc", "Sparc");
    +}
    +
    +
    + +

    +This allows the TargetRegistry to look up the target by name or by +target triple. In addition, most targets will also register additional features +which are available in separate libraries. These registration steps are +separate, because some clients may wish to only link in some parts of the target +-- the JIT code generator does not require the use of the assembler printer, for +example. Here is an example of registering the Sparc assembly printer: +

    + +
    +
    +extern "C" void LLVMInitializeSparcAsmPrinter() { 
    +  RegisterAsmPrinter<SparcAsmPrinter> X(TheSparcTarget);
    +}
    +
    +
    + +

    +For more information, see +"llvm/Target/TargetRegistry.h". +

    + +
    + + + + + +
    + +

    +You should describe a concrete target-specific class that represents the +register file of a target machine. This class is called XXXRegisterInfo +(where XXX identifies the target) and represents the class register +file data that is used for register allocation. It also describes the +interactions between registers. +

    + +

    +You also need to define register classes to categorize related registers. A +register class should be added for groups of registers that are all treated the +same way for some instruction. Typical examples are register classes for +integer, floating-point, or vector registers. A register allocator allows an +instruction to use any register in a specified register class to perform the +instruction in a similar manner. Register classes allocate virtual registers to +instructions from these sets, and register classes let the target-independent +register allocator automatically choose the actual registers. +

    + +

    +Much of the code for registers, including register definition, register aliases, +and register classes, is generated by TableGen from XXXRegisterInfo.td +input files and placed in XXXGenRegisterInfo.h.inc and +XXXGenRegisterInfo.inc output files. Some of the code in the +implementation of XXXRegisterInfo requires hand-coding. +

    + +
    + + + + +
    + +

    +The XXXRegisterInfo.td file typically starts with register definitions +for a target machine. The Register class (specified +in Target.td) is used to define an object for each register. The +specified string n becomes the Name of the register. The +basic Register object does not have any subregisters and does not +specify any aliases. +

    + +
    +
    +class Register<string n> {
    +  string Namespace = "";
    +  string AsmName = n;
    +  string Name = n;
    +  int SpillSize = 0;
    +  int SpillAlignment = 0;
    +  list<Register> Aliases = [];
    +  list<Register> SubRegs = [];
    +  list<int> DwarfNumbers = [];
    +}
    +
    +
    + +

    +For example, in the X86RegisterInfo.td file, there are register +definitions that utilize the Register class, such as: +

    + +
    +
    +def AL : Register<"AL">, DwarfRegNum<[0, 0, 0]>;
    +
    +
    + +

    +This defines the register AL and assigns it values (with +DwarfRegNum) that are used by gcc, gdb, or a debug +information writer (such as DwarfWriter +in llvm/lib/CodeGen/AsmPrinter) to identify a register. For register +AL, DwarfRegNum takes an array of 3 values representing 3 +different modes: the first element is for X86-64, the second for exception +handling (EH) on X86-32, and the third is generic. -1 is a special Dwarf number +that indicates the gcc number is undefined, and -2 indicates the register number +is invalid for this mode. +

    + +

    +From the previously described line in the X86RegisterInfo.td file, +TableGen generates this code in the X86GenRegisterInfo.inc file: +

    + +
    +
    +static const unsigned GR8[] = { X86::AL, ... };
    +
    +const unsigned AL_AliasSet[] = { X86::AX, X86::EAX, X86::RAX, 0 };
    +
    +const TargetRegisterDesc RegisterDescriptors[] = { 
    +  ...
    +{ "AL", "AL", AL_AliasSet, Empty_SubRegsSet, Empty_SubRegsSet, AL_SuperRegsSet }, ...
    +
    +
    + +

    +From the register info file, TableGen generates a TargetRegisterDesc +object for each register. TargetRegisterDesc is defined in +include/llvm/Target/TargetRegisterInfo.h with the following fields: +

    + +
    +
    +struct TargetRegisterDesc {
    +  const char     *AsmName;      // Assembly language name for the register
    +  const char     *Name;         // Printable name for the reg (for debugging)
    +  const unsigned *AliasSet;     // Register Alias Set
    +  const unsigned *SubRegs;      // Sub-register set
    +  const unsigned *ImmSubRegs;   // Immediate sub-register set
    +  const unsigned *SuperRegs;    // Super-register set
    +};
    +
    + +

    +TableGen uses the entire target description file (.td) to determine +text names for the register (in the AsmName and Name fields of +TargetRegisterDesc) and the relationships of other registers to the +defined register (in the other TargetRegisterDesc fields). In this +example, other definitions establish the registers "AX", +"EAX", and "RAX" as aliases for one another, so TableGen +generates a null-terminated array (AL_AliasSet) for this register alias +set. +

    + +

    +The Register class is commonly used as a base class for more complex +classes. In Target.td, the Register class is the base for the +RegisterWithSubRegs class that is used to define registers that need to +specify subregisters in the SubRegs list, as shown here: +

    + +
    +
    +class RegisterWithSubRegs<string n,
    +list<Register> subregs> : Register<n> {
    +  let SubRegs = subregs;
    +}
    +
    +
    + +

    +In SparcRegisterInfo.td, additional register classes are defined for +SPARC: a Register subclass, SparcReg, and further subclasses: Ri, +Rf, and Rd. SPARC registers are identified by 5-bit ID +numbers, which is a feature common to these subclasses. Note the use of +'let' expressions to override values that are initially defined in a +superclass (such as SubRegs field in the Rd class). +

    + +
    +
    +class SparcReg<string n> : Register<n> {
    +  field bits<5> Num;
    +  let Namespace = "SP";
    +}
    +// Ri - 32-bit integer registers
    +class Ri<bits<5> num, string n> :
    +SparcReg<n> {
    +  let Num = num;
    +}
    +// Rf - 32-bit floating-point registers
    +class Rf<bits<5> num, string n> :
    +SparcReg<n> {
    +  let Num = num;
    +}
    +// Rd - Slots in the FP register file for 64-bit
    +floating-point values.
    +class Rd<bits<5> num, string n,
    +list<Register> subregs> : SparcReg<n> {
    +  let Num = num;
    +  let SubRegs = subregs;
    +}
    +
    +
    + +

    +In the SparcRegisterInfo.td file, there are register definitions that +utilize these subclasses of Register, such as: +

    + +
    +
    +def G0 : Ri< 0, "G0">,
    +DwarfRegNum<[0]>;
    +def G1 : Ri< 1, "G1">, DwarfRegNum<[1]>;
    +...
    +def F0 : Rf< 0, "F0">,
    +DwarfRegNum<[32]>;
    +def F1 : Rf< 1, "F1">,
    +DwarfRegNum<[33]>;
    +...
    +def D0 : Rd< 0, "F0", [F0, F1]>,
    +DwarfRegNum<[32]>;
    +def D1 : Rd< 2, "F2", [F2, F3]>,
    +DwarfRegNum<[34]>;
    +
    +
    + +

    +The last two registers shown above (D0 and D1) are +double-precision floating-point registers that are aliases for pairs of +single-precision floating-point sub-registers. In addition to aliases, the +sub-register and super-register relationships of the defined register are in +fields of a register's TargetRegisterDesc. +

    + +
    + + + + +
    + +

    +The RegisterClass class (specified in Target.td) is used to +define an object that represents a group of related registers and also defines +the default allocation order of the registers. A target description file +XXXRegisterInfo.td that uses Target.td can construct register +classes using the following class: +

    + +
    +
    +class RegisterClass<string namespace,
    +list<ValueType> regTypes, int alignment,
    +                    list<Register> regList> {
    +  string Namespace = namespace;
    +  list<ValueType> RegTypes = regTypes;
    +  int Size = 0;  // spill size, in bits; zero lets tblgen pick the size
    +  int Alignment = alignment;
    +
    +  // CopyCost is the cost of copying a value between two registers
    +  // default value 1 means a single instruction
    +  // A negative value means copying is extremely expensive or impossible
    +  int CopyCost = 1;  
    +  list<Register> MemberList = regList;
    +  
    +  // for register classes that are subregisters of this class
    +  list<RegisterClass> SubRegClassList = [];  
    +  
    +  code MethodProtos = [{}];  // to insert arbitrary code
    +  code MethodBodies = [{}];
    +}
    +
    +
    + +

    To define a RegisterClass, use the following 4 arguments:

    + +
      +
    • The first argument of the definition is the name of the namespace.
    • + +
    • The second argument is a list of ValueType register type values + that are defined in include/llvm/CodeGen/ValueTypes.td. Defined + values include integer types (such as i16, i32, + and i1 for Boolean), floating-point types + (f32, f64), and vector types (for example, v8i16 + for an 8 x i16 vector). All registers in a RegisterClass + must have the same ValueType, but some registers may store vector + data in different configurations. For example a register that can process a + 128-bit vector may be able to handle 16 8-bit integer elements, 8 16-bit + integers, 4 32-bit integers, and so on.
    • + +
    • The third argument of the RegisterClass definition specifies the + alignment required of the registers when they are stored or loaded to + memory.
    • + +
    • The final argument, regList, specifies which registers are in this + class. If an allocation_order_* method is not specified, + then regList also defines the order of allocation used by the + register allocator.
    • +
    + +

    +In SparcRegisterInfo.td, three RegisterClass objects are defined: +FPRegs, DFPRegs, and IntRegs. For all three register +classes, the first argument defines the namespace with the string +'SP'. FPRegs defines a group of 32 single-precision +floating-point registers (F0 to F31); DFPRegs defines +a group of 16 double-precision registers +(D0-D15). For IntRegs, the MethodProtos +and MethodBodies methods are used by TableGen to insert the specified +code into generated output. +

    + +
    +
    +def FPRegs : RegisterClass<"SP", [f32], 32,
    +  [F0, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, F13, F14, F15,
    +   F16, F17, F18, F19, F20, F21, F22, F23, F24, F25, F26, F27, F28, F29, F30, F31]>;
    +
    +def DFPRegs : RegisterClass<"SP", [f64], 64,
    +  [D0, D1, D2, D3, D4, D5, D6, D7, D8, D9, D10, D11, D12, D13, D14, D15]>;
    + 
    +def IntRegs : RegisterClass<"SP", [i32], 32,
    +    [L0, L1, L2, L3, L4, L5, L6, L7,
    +     I0, I1, I2, I3, I4, I5,
    +     O0, O1, O2, O3, O4, O5, O7,
    +     G1,
    +     // Non-allocatable regs:
    +     G2, G3, G4, 
    +     O6,        // stack ptr
    +    I6,        // frame ptr
    +     I7,        // return address
    +     G0,        // constant zero
    +     G5, G6, G7 // reserved for kernel
    +    ]> {
    +  let MethodProtos = [{
    +    iterator allocation_order_end(const MachineFunction &MF) const;
    +  }];
    +  let MethodBodies = [{
    +    IntRegsClass::iterator
    +    IntRegsClass::allocation_order_end(const MachineFunction &MF) const {
    +      return end() - 10  // Don't allocate special registers
    +         -1;
    +    }
    +  }];
    +}
    +
    +
    + +

    +Using SparcRegisterInfo.td with TableGen generates several output files +that are intended for inclusion in other source code that you write. +SparcRegisterInfo.td generates SparcGenRegisterInfo.h.inc, +which should be included in the header file for the implementation of the SPARC +register implementation that you write (SparcRegisterInfo.h). In +SparcGenRegisterInfo.h.inc a new structure is defined called +SparcGenRegisterInfo that uses TargetRegisterInfo as its +base. It also specifies types, based upon the defined register +classes: DFPRegsClass, FPRegsClass, and IntRegsClass. +

    + +

    +SparcRegisterInfo.td also generates SparcGenRegisterInfo.inc, +which is included at the bottom of SparcRegisterInfo.cpp, the SPARC +register implementation. The code below shows only the generated integer +registers and associated register classes. The order of registers +in IntRegs reflects the order in the definition of IntRegs in +the target description file. Take special note of the use +of MethodBodies in SparcRegisterInfo.td to create code in +SparcGenRegisterInfo.inc. MethodProtos generates similar code +in SparcGenRegisterInfo.h.inc. +

    + +
    +
      // IntRegs Register Class...
    +  static const unsigned IntRegs[] = {
    +    SP::L0, SP::L1, SP::L2, SP::L3, SP::L4, SP::L5,
    +    SP::L6, SP::L7, SP::I0, SP::I1, SP::I2, SP::I3,
    +    SP::I4, SP::I5, SP::O0, SP::O1, SP::O2, SP::O3,
    +    SP::O4, SP::O5, SP::O7, SP::G1, SP::G2, SP::G3,
    +    SP::G4, SP::O6, SP::I6, SP::I7, SP::G0, SP::G5,
    +    SP::G6, SP::G7, 
    +  };
    +
    +  // IntRegsVTs Register Class Value Types...
    +  static const MVT::ValueType IntRegsVTs[] = {
    +    MVT::i32, MVT::Other
    +  };
    +
    +namespace SP {   // Register class instances
    +  DFPRegsClass    DFPRegsRegClass;
    +  FPRegsClass     FPRegsRegClass;
    +  IntRegsClass    IntRegsRegClass;
    +...
    +  // IntRegs Sub-register Classess...
    +  static const TargetRegisterClass* const IntRegsSubRegClasses [] = {
    +    NULL
    +  };
    +...
    +  // IntRegs Super-register Classess...
    +  static const TargetRegisterClass* const IntRegsSuperRegClasses [] = {
    +    NULL
    +  };
    +...
    +  // IntRegs Register Class sub-classes...
    +  static const TargetRegisterClass* const IntRegsSubclasses [] = {
    +    NULL
    +  };
    +...
    +  // IntRegs Register Class super-classes...
    +  static const TargetRegisterClass* const IntRegsSuperclasses [] = {
    +    NULL
    +  };
    +...
    +  IntRegsClass::iterator
    +  IntRegsClass::allocation_order_end(const MachineFunction &MF) const {
    +     return end()-10  // Don't allocate special registers
    +         -1;
    +  }
    +  
    +  IntRegsClass::IntRegsClass() : TargetRegisterClass(IntRegsRegClassID, 
    +    IntRegsVTs, IntRegsSubclasses, IntRegsSuperclasses, IntRegsSubRegClasses, 
    +    IntRegsSuperRegClasses, 4, 4, 1, IntRegs, IntRegs + 32) {}
    +}
    +
    +
    + +
    + + + + +
    + +

    +The final step is to hand code portions of XXXRegisterInfo, which +implements the interface described in TargetRegisterInfo.h. These +functions return 0, NULL, or false, unless +overridden. Here is a list of functions that are overridden for the SPARC +implementation in SparcRegisterInfo.cpp: +

    + +
      +
    • getCalleeSavedRegs — Returns a list of callee-saved registers + in the order of the desired callee-save stack frame offset.
    • + +
    • getCalleeSavedRegClasses — Returns a list of preferred + register classes with which to spill each callee saved register.
    • + +
    • getReservedRegs — Returns a bitset indexed by physical + register numbers, indicating if a particular register is unavailable.
    • + +
    • hasFP — Return a Boolean indicating if a function should have + a dedicated frame pointer register.
    • + +
    • eliminateCallFramePseudoInstr — If call frame setup or + destroy pseudo instructions are used, this can be called to eliminate + them.
    • + +
    • eliminateFrameIndex — Eliminate abstract frame indices from + instructions that may use them.
    • + +
    • emitPrologue — Insert prologue code into the function.
    • + +
    • emitEpilogue — Insert epilogue code into the function.
    • +
    + +
    + + + + + +
    + +

    +During the early stages of code generation, the LLVM IR code is converted to a +SelectionDAG with nodes that are instances of the SDNode class +containing target instructions. An SDNode has an opcode, operands, type +requirements, and operation properties. For example, is an operation +commutative, does an operation load from memory. The various operation node +types are described in the include/llvm/CodeGen/SelectionDAGNodes.h +file (values of the NodeType enum in the ISD namespace). +

    + +

    +TableGen uses the following target description (.td) input files to +generate much of the code for instruction definition: +

    + +
      +
    • Target.td — Where the Instruction, Operand, + InstrInfo, and other fundamental classes are defined.
    • + +
    • TargetSelectionDAG.td— Used by SelectionDAG + instruction selection generators, contains SDTC* classes (selection + DAG type constraint), definitions of SelectionDAG nodes (such as + imm, cond, bb, add, fadd, + sub), and pattern support (Pattern, Pat, + PatFrag, PatLeaf, ComplexPattern.
    • + +
    • XXXInstrFormats.td — Patterns for definitions of + target-specific instructions.
    • + +
    • XXXInstrInfo.td — Target-specific definitions of instruction + templates, condition codes, and instructions of an instruction set. For + architecture modifications, a different file name may be used. For example, + for Pentium with SSE instruction, this file is X86InstrSSE.td, and + for Pentium with MMX, this file is X86InstrMMX.td.
    • +
    + +

    +There is also a target-specific XXX.td file, where XXX is the +name of the target. The XXX.td file includes the other .td +input files, but its contents are only directly important for subtargets. +

    + +

    +You should describe a concrete target-specific class XXXInstrInfo that +represents machine instructions supported by a target machine. +XXXInstrInfo contains an array of XXXInstrDescriptor objects, +each of which describes one instruction. An instruction descriptor defines:

    + +
      +
    • Opcode mnemonic
    • + +
    • Number of operands
    • + +
    • List of implicit register definitions and uses
    • + +
    • Target-independent properties (such as memory access, is commutable)
    • + +
    • Target-specific flags
    • +
    + +

    +The Instruction class (defined in Target.td) is mostly used as a base +for more complex instruction classes. +

    + +
    +
    class Instruction {
    +  string Namespace = "";
    +  dag OutOperandList;       // An dag containing the MI def operand list.
    +  dag InOperandList;        // An dag containing the MI use operand list.
    +  string AsmString = "";    // The .s format to print the instruction with.
    +  list<dag> Pattern;  // Set to the DAG pattern for this instruction
    +  list<Register> Uses = []; 
    +  list<Register> Defs = [];
    +  list<Predicate> Predicates = [];  // predicates turned into isel match code
    +  ... remainder not shown for space ...
    +}
    +
    +
    + +

    +A SelectionDAG node (SDNode) should contain an object +representing a target-specific instruction that is defined +in XXXInstrInfo.td. The instruction objects should represent +instructions from the architecture manual of the target machine (such as the +SPARC Architecture Manual for the SPARC target). +

    + +

    +A single instruction from the architecture manual is often modeled as multiple +target instructions, depending upon its operands. For example, a manual might +describe an add instruction that takes a register or an immediate operand. An +LLVM target could model this with two instructions named ADDri and +ADDrr. +

    + +

    +You should define a class for each instruction category and define each opcode +as a subclass of the category with appropriate parameters such as the fixed +binary encoding of opcodes and extended opcodes. You should map the register +bits to the bits of the instruction in which they are encoded (for the +JIT). Also you should specify how the instruction should be printed when the +automatic assembly printer is used. +

    + +

    +As is described in the SPARC Architecture Manual, Version 8, there are three +major 32-bit formats for instructions. Format 1 is only for the CALL +instruction. Format 2 is for branch on condition codes and SETHI (set +high bits of a register) instructions. Format 3 is for other instructions. +

    + +

    +Each of these formats has corresponding classes in SparcInstrFormat.td. +InstSP is a base class for other instruction classes. Additional base +classes are specified for more precise formats: for example +in SparcInstrFormat.td, F2_1 is for SETHI, +and F2_2 is for branches. There are three other base +classes: F3_1 for register/register operations, F3_2 for +register/immediate operations, and F3_3 for floating-point +operations. SparcInstrInfo.td also adds the base class Pseudo for +synthetic SPARC instructions. +

    + +

    +SparcInstrInfo.td largely consists of operand and instruction +definitions for the SPARC target. In SparcInstrInfo.td, the following +target description file entry, LDrr, defines the Load Integer +instruction for a Word (the LD SPARC opcode) from a memory address to a +register. The first parameter, the value 3 (112), is the +operation value for this category of operation. The second parameter +(0000002) is the specific operation value +for LD/Load Word. The third parameter is the output destination, which +is a register operand and defined in the Register target description +file (IntRegs). +

    + +
    +
    def LDrr : F3_1 <3, 0b000000, (outs IntRegs:$dst), (ins MEMrr:$addr),
    +                 "ld [$addr], $dst",
    +                 [(set IntRegs:$dst, (load ADDRrr:$addr))]>;
    +
    +
    + +

    +The fourth parameter is the input source, which uses the address +operand MEMrr that is defined earlier in SparcInstrInfo.td: +

    + +
    +
    def MEMrr : Operand<i32> {
    +  let PrintMethod = "printMemOperand";
    +  let MIOperandInfo = (ops IntRegs, IntRegs);
    +}
    +
    +
    + +

    +The fifth parameter is a string that is used by the assembly printer and can be +left as an empty string until the assembly printer interface is implemented. The +sixth and final parameter is the pattern used to match the instruction during +the SelectionDAG Select Phase described in +(The LLVM +Target-Independent Code Generator). This parameter is detailed in the next +section, Instruction Selector. +

    + +

    +Instruction class definitions are not overloaded for different operand types, so +separate versions of instructions are needed for register, memory, or immediate +value operands. For example, to perform a Load Integer instruction for a Word +from an immediate operand to a register, the following instruction class is +defined: +

    + +
    +
    def LDri : F3_2 <3, 0b000000, (outs IntRegs:$dst), (ins MEMri:$addr),
    +                 "ld [$addr], $dst",
    +                 [(set IntRegs:$dst, (load ADDRri:$addr))]>;
    +
    +
    + +

    +Writing these definitions for so many similar instructions can involve a lot of +cut and paste. In td files, the multiclass directive enables the +creation of templates to define several instruction classes at once (using +the defm directive). For example in SparcInstrInfo.td, the +multiclass pattern F3_12 is defined to create 2 instruction +classes each time F3_12 is invoked: +

    + +
    +
    multiclass F3_12 <string OpcStr, bits<6> Op3Val, SDNode OpNode> {
    +  def rr  : F3_1 <2, Op3Val, 
    +                 (outs IntRegs:$dst), (ins IntRegs:$b, IntRegs:$c),
    +                 !strconcat(OpcStr, " $b, $c, $dst"),
    +                 [(set IntRegs:$dst, (OpNode IntRegs:$b, IntRegs:$c))]>;
    +  def ri  : F3_2 <2, Op3Val,
    +                 (outs IntRegs:$dst), (ins IntRegs:$b, i32imm:$c),
    +                 !strconcat(OpcStr, " $b, $c, $dst"),
    +                 [(set IntRegs:$dst, (OpNode IntRegs:$b, simm13:$c))]>;
    +}
    +
    +
    + +

    +So when the defm directive is used for the XOR +and ADD instructions, as seen below, it creates four instruction +objects: XORrr, XORri, ADDrr, and ADDri. +

    + +
    +
    +defm XOR   : F3_12<"xor", 0b000011, xor>;
    +defm ADD   : F3_12<"add", 0b000000, add>;
    +
    +
    + +

    +SparcInstrInfo.td also includes definitions for condition codes that +are referenced by branch instructions. The following definitions +in SparcInstrInfo.td indicate the bit location of the SPARC condition +code. For example, the 10th bit represents the 'greater than' +condition for integers, and the 22nd bit represents the 'greater +than' condition for floats. +

    + +
    +
    +def ICC_NE  : ICC_VAL< 9>;  // Not Equal
    +def ICC_E   : ICC_VAL< 1>;  // Equal
    +def ICC_G   : ICC_VAL<10>;  // Greater
    +...
    +def FCC_U   : FCC_VAL<23>;  // Unordered
    +def FCC_G   : FCC_VAL<22>;  // Greater
    +def FCC_UG  : FCC_VAL<21>;  // Unordered or Greater
    +...
    +
    +
    + +

    +(Note that Sparc.h also defines enums that correspond to the same SPARC +condition codes. Care must be taken to ensure the values in Sparc.h +correspond to the values in SparcInstrInfo.td. I.e., +SPCC::ICC_NE = 9, SPCC::FCC_U = 23 and so on.) +

    + +
    + + + + +
    + +

    +The code generator backend maps instruction operands to fields in the +instruction. Operands are assigned to unbound fields in the instruction in the +order they are defined. Fields are bound when they are assigned a value. For +example, the Sparc target defines the XNORrr instruction as +a F3_1 format instruction having three operands. +

    + +
    +
    +def XNORrr  : F3_1<2, 0b000111,
    +                   (outs IntRegs:$dst), (ins IntRegs:$b, IntRegs:$c),
    +                   "xnor $b, $c, $dst",
    +                   [(set IntRegs:$dst, (not (xor IntRegs:$b, IntRegs:$c)))]>;
    +
    +
    + +

    +The instruction templates in SparcInstrFormats.td show the base class +for F3_1 is InstSP. +

    + +
    +
    +class InstSP<dag outs, dag ins, string asmstr, list<dag> pattern> : Instruction {
    +  field bits<32> Inst;
    +  let Namespace = "SP";
    +  bits<2> op;
    +  let Inst{31-30} = op;       
    +  dag OutOperandList = outs;
    +  dag InOperandList = ins;
    +  let AsmString   = asmstr;
    +  let Pattern = pattern;
    +}
    +
    +
    + +

    InstSP leaves the op field unbound.

    + +
    +
    +class F3<dag outs, dag ins, string asmstr, list<dag> pattern>
    +    : InstSP<outs, ins, asmstr, pattern> {
    +  bits<5> rd;
    +  bits<6> op3;
    +  bits<5> rs1;
    +  let op{1} = 1;   // Op = 2 or 3
    +  let Inst{29-25} = rd;
    +  let Inst{24-19} = op3;
    +  let Inst{18-14} = rs1;
    +}
    +
    +
    + +

    +F3 binds the op field and defines the rd, +op3, and rs1 fields. F3 format instructions will +bind the operands rd, op3, and rs1 fields. +

    + +
    +
    +class F3_1<bits<2> opVal, bits<6> op3val, dag outs, dag ins,
    +           string asmstr, list<dag> pattern> : F3<outs, ins, asmstr, pattern> {
    +  bits<8> asi = 0; // asi not currently used
    +  bits<5> rs2;
    +  let op         = opVal;
    +  let op3        = op3val;
    +  let Inst{13}   = 0;     // i field = 0
    +  let Inst{12-5} = asi;   // address space identifier
    +  let Inst{4-0}  = rs2;
    +}
    +
    +
    + +

    +F3_1 binds the op3 field and defines the rs2 +fields. F3_1 format instructions will bind the operands to the rd, +rs1, and rs2 fields. This results in the XNORrr +instruction binding $dst, $b, and $c operands to +the rd, rs1, and rs2 fields respectively. +

    + +
    + + + + +
    + +

    +The final step is to hand code portions of XXXInstrInfo, which +implements the interface described in TargetInstrInfo.h. These +functions return 0 or a Boolean or they assert, unless +overridden. Here's a list of functions that are overridden for the SPARC +implementation in SparcInstrInfo.cpp: +

    + +
      +
    • isMoveInstr — Return true if the instruction is a register to + register move; false, otherwise.
    • + +
    • isLoadFromStackSlot — If the specified machine instruction is + a direct load from a stack slot, return the register number of the + destination and the FrameIndex of the stack slot.
    • + +
    • isStoreToStackSlot — If the specified machine instruction is + a direct store to a stack slot, return the register number of the + destination and the FrameIndex of the stack slot.
    • + +
    • copyRegToReg — Copy values between a pair of registers.
    • + +
    • storeRegToStackSlot — Store a register value to a stack + slot.
    • + +
    • loadRegFromStackSlot — Load a register value from a stack + slot.
    • + +
    • storeRegToAddr — Store a register value to memory.
    • + +
    • loadRegFromAddr — Load a register value from memory.
    • + +
    • foldMemoryOperand — Attempt to combine instructions of any + load or store instruction for the specified operand(s).
    • +
    + +
    + + + +
    + +

    +Performance can be improved by combining instructions or by eliminating +instructions that are never reached. The AnalyzeBranch method +in XXXInstrInfo may be implemented to examine conditional instructions +and remove unnecessary instructions. AnalyzeBranch looks at the end of +a machine basic block (MBB) for opportunities for improvement, such as branch +folding and if conversion. The BranchFolder and IfConverter +machine function passes (see the source files BranchFolding.cpp and +IfConversion.cpp in the lib/CodeGen directory) call +AnalyzeBranch to improve the control flow graph that represents the +instructions. +

    + +

    +Several implementations of AnalyzeBranch (for ARM, Alpha, and X86) can +be examined as models for your own AnalyzeBranch implementation. Since +SPARC does not implement a useful AnalyzeBranch, the ARM target +implementation is shown below. +

    + +

    AnalyzeBranch returns a Boolean value and takes four parameters:

    + +
      +
    • MachineBasicBlock &MBB — The incoming block to be + examined.
    • + +
    • MachineBasicBlock *&TBB — A destination block that is + returned. For a conditional branch that evaluates to true, TBB is + the destination.
    • + +
    • MachineBasicBlock *&FBB — For a conditional branch that + evaluates to false, FBB is returned as the destination.
    • + +
    • std::vector<MachineOperand> &Cond — List of + operands to evaluate a condition for a conditional branch.
    • +
    + +

    +In the simplest case, if a block ends without a branch, then it falls through to +the successor block. No destination blocks are specified for either TBB +or FBB, so both parameters return NULL. The start of +the AnalyzeBranch (see code below for the ARM target) shows the +function parameters and the code for the simplest case. +

    + +
    +
    bool ARMInstrInfo::AnalyzeBranch(MachineBasicBlock &MBB,
    +        MachineBasicBlock *&TBB, MachineBasicBlock *&FBB,
    +        std::vector<MachineOperand> &Cond) const
    +{
    +  MachineBasicBlock::iterator I = MBB.end();
    +  if (I == MBB.begin() || !isUnpredicatedTerminator(--I))
    +    return false;
    +
    +
    + +

    +If a block ends with a single unconditional branch instruction, then +AnalyzeBranch (shown below) should return the destination of that +branch in the TBB parameter. +

    + +
    +
    +  if (LastOpc == ARM::B || LastOpc == ARM::tB) {
    +    TBB = LastInst->getOperand(0).getMBB();
    +    return false;
    +  }
    +
    +
    + +

    +If a block ends with two unconditional branches, then the second branch is never +reached. In that situation, as shown below, remove the last branch instruction +and return the penultimate branch in the TBB parameter. +

    + +
    +
    +  if ((SecondLastOpc == ARM::B || SecondLastOpc==ARM::tB) &&
    +      (LastOpc == ARM::B || LastOpc == ARM::tB)) {
    +    TBB = SecondLastInst->getOperand(0).getMBB();
    +    I = LastInst;
    +    I->eraseFromParent();
    +    return false;
    +  }
    +
    +
    + +

    +A block may end with a single conditional branch instruction that falls through +to successor block if the condition evaluates to false. In that case, +AnalyzeBranch (shown below) should return the destination of that +conditional branch in the TBB parameter and a list of operands in +the Cond parameter to evaluate the condition. +

    + +
    +
    +  if (LastOpc == ARM::Bcc || LastOpc == ARM::tBcc) {
    +    // Block ends with fall-through condbranch.
    +    TBB = LastInst->getOperand(0).getMBB();
    +    Cond.push_back(LastInst->getOperand(1));
    +    Cond.push_back(LastInst->getOperand(2));
    +    return false;
    +  }
    +
    +
    + +

    +If a block ends with both a conditional branch and an ensuing unconditional +branch, then AnalyzeBranch (shown below) should return the conditional +branch destination (assuming it corresponds to a conditional evaluation of +'true') in the TBB parameter and the unconditional branch +destination in the FBB (corresponding to a conditional evaluation of +'false'). A list of operands to evaluate the condition should be +returned in the Cond parameter. +

    + +
    +
    +  unsigned SecondLastOpc = SecondLastInst->getOpcode();
    +
    +  if ((SecondLastOpc == ARM::Bcc && LastOpc == ARM::B) ||
    +      (SecondLastOpc == ARM::tBcc && LastOpc == ARM::tB)) {
    +    TBB =  SecondLastInst->getOperand(0).getMBB();
    +    Cond.push_back(SecondLastInst->getOperand(1));
    +    Cond.push_back(SecondLastInst->getOperand(2));
    +    FBB = LastInst->getOperand(0).getMBB();
    +    return false;
    +  }
    +
    +
    + +

    +For the last two cases (ending with a single conditional branch or ending with +one conditional and one unconditional branch), the operands returned in +the Cond parameter can be passed to methods of other instructions to +create new branches or perform other operations. An implementation +of AnalyzeBranch requires the helper methods RemoveBranch +and InsertBranch to manage subsequent operations. +

    + +

    +AnalyzeBranch should return false indicating success in most circumstances. +AnalyzeBranch should only return true when the method is stumped about what to +do, for example, if a block has three terminating branches. AnalyzeBranch may +return true if it encounters a terminator it cannot handle, such as an indirect +branch. +

    + +
    + + + + + +
    + +

    +LLVM uses a SelectionDAG to represent LLVM IR instructions, and nodes +of the SelectionDAG ideally represent native target +instructions. During code generation, instruction selection passes are performed +to convert non-native DAG instructions into native target-specific +instructions. The pass described in XXXISelDAGToDAG.cpp is used to +match patterns and perform DAG-to-DAG instruction selection. Optionally, a pass +may be defined (in XXXBranchSelector.cpp) to perform similar DAG-to-DAG +operations for branch instructions. Later, the code in +XXXISelLowering.cpp replaces or removes operations and data types not +supported natively (legalizes) in a SelectionDAG. +

    + +

    +TableGen generates code for instruction selection using the following target +description input files: +

    + +
      +
    • XXXInstrInfo.td — Contains definitions of instructions in a + target-specific instruction set, generates XXXGenDAGISel.inc, which + is included in XXXISelDAGToDAG.cpp.
    • + +
    • XXXCallingConv.td — Contains the calling and return value + conventions for the target architecture, and it generates + XXXGenCallingConv.inc, which is included in + XXXISelLowering.cpp.
    • +
    + +

    +The implementation of an instruction selection pass must include a header that +declares the FunctionPass class or a subclass of FunctionPass. In +XXXTargetMachine.cpp, a Pass Manager (PM) should add each instruction +selection pass into the queue of passes to run. +

    + +

    +The LLVM static compiler (llc) is an excellent tool for visualizing the +contents of DAGs. To display the SelectionDAG before or after specific +processing phases, use the command line options for llc, described +at +SelectionDAG Instruction Selection Process. +

    + +

    +To describe instruction selector behavior, you should add patterns for lowering +LLVM code into a SelectionDAG as the last parameter of the instruction +definitions in XXXInstrInfo.td. For example, in +SparcInstrInfo.td, this entry defines a register store operation, and +the last parameter describes a pattern with the store DAG operator. +

    + +
    +
    +def STrr  : F3_1< 3, 0b000100, (outs), (ins MEMrr:$addr, IntRegs:$src),
    +                 "st $src, [$addr]", [(store IntRegs:$src, ADDRrr:$addr)]>;
    +
    +
    + +

    +ADDRrr is a memory mode that is also defined in +SparcInstrInfo.td: +

    + +
    +
    +def ADDRrr : ComplexPattern<i32, 2, "SelectADDRrr", [], []>;
    +
    +
    + +

    +The definition of ADDRrr refers to SelectADDRrr, which is a +function defined in an implementation of the Instructor Selector (such +as SparcISelDAGToDAG.cpp). +

    + +

    +In lib/Target/TargetSelectionDAG.td, the DAG operator for store is +defined below: +

    + +
    +
    +def store : PatFrag<(ops node:$val, node:$ptr),
    +                    (st node:$val, node:$ptr), [{
    +  if (StoreSDNode *ST = dyn_cast<StoreSDNode>(N))
    +    return !ST->isTruncatingStore() && 
    +           ST->getAddressingMode() == ISD::UNINDEXED;
    +  return false;
    +}]>;
    +
    +
    + +

    +XXXInstrInfo.td also generates (in XXXGenDAGISel.inc) the +SelectCode method that is used to call the appropriate processing +method for an instruction. In this example, SelectCode +calls Select_ISD_STORE for the ISD::STORE opcode. +

    + +
    +
    +SDNode *SelectCode(SDValue N) {
    +  ... 
    +  MVT::ValueType NVT = N.getNode()->getValueType(0);
    +  switch (N.getOpcode()) {
    +  case ISD::STORE: {
    +    switch (NVT) {
    +    default:
    +      return Select_ISD_STORE(N);
    +      break;
    +    }
    +    break;
    +  }
    +  ...
    +
    +
    + +

    +The pattern for STrr is matched, so elsewhere in +XXXGenDAGISel.inc, code for STrr is created for +Select_ISD_STORE. The Emit_22 method is also generated +in XXXGenDAGISel.inc to complete the processing of this +instruction. +

    + +
    +
    +SDNode *Select_ISD_STORE(const SDValue &N) {
    +  SDValue Chain = N.getOperand(0);
    +  if (Predicate_store(N.getNode())) {
    +    SDValue N1 = N.getOperand(1);
    +    SDValue N2 = N.getOperand(2);
    +    SDValue CPTmp0;
    +    SDValue CPTmp1;
    +
    +    // Pattern: (st:void IntRegs:i32:$src, 
    +    //           ADDRrr:i32:$addr)<<P:Predicate_store>>
    +    // Emits: (STrr:void ADDRrr:i32:$addr, IntRegs:i32:$src)
    +    // Pattern complexity = 13  cost = 1  size = 0
    +    if (SelectADDRrr(N, N2, CPTmp0, CPTmp1) &&
    +        N1.getNode()->getValueType(0) == MVT::i32 &&
    +        N2.getNode()->getValueType(0) == MVT::i32) {
    +      return Emit_22(N, SP::STrr, CPTmp0, CPTmp1);
    +    }
    +...
    +
    +
    + +
    + + + + +
    + +

    +The Legalize phase converts a DAG to use types and operations that are natively +supported by the target. For natively unsupported types and operations, you need +to add code to the target-specific XXXTargetLowering implementation to convert +unsupported types and operations to supported ones. +

    + +

    +In the constructor for the XXXTargetLowering class, first use the +addRegisterClass method to specify which types are supports and which +register classes are associated with them. The code for the register classes are +generated by TableGen from XXXRegisterInfo.td and placed +in XXXGenRegisterInfo.h.inc. For example, the implementation of the +constructor for the SparcTargetLowering class (in +SparcISelLowering.cpp) starts with the following code: +

    + +
    +
    +addRegisterClass(MVT::i32, SP::IntRegsRegisterClass);
    +addRegisterClass(MVT::f32, SP::FPRegsRegisterClass);
    +addRegisterClass(MVT::f64, SP::DFPRegsRegisterClass); 
    +
    +
    + +

    +You should examine the node types in the ISD namespace +(include/llvm/CodeGen/SelectionDAGNodes.h) and determine which +operations the target natively supports. For operations that do not have +native support, add a callback to the constructor for the XXXTargetLowering +class, so the instruction selection process knows what to do. The TargetLowering +class callback methods (declared in llvm/Target/TargetLowering.h) are: +

    + +
      +
    • setOperationAction — General operation.
    • + +
    • setLoadExtAction — Load with extension.
    • + +
    • setTruncStoreAction — Truncating store.
    • + +
    • setIndexedLoadAction — Indexed load.
    • + +
    • setIndexedStoreAction — Indexed store.
    • + +
    • setConvertAction — Type conversion.
    • + +
    • setCondCodeAction — Support for a given condition code.
    • +
    + +

    +Note: on older releases, setLoadXAction is used instead +of setLoadExtAction. Also, on older releases, +setCondCodeAction may not be supported. Examine your release +to see what methods are specifically supported. +

    + +

    +These callbacks are used to determine that an operation does or does not work +with a specified type (or types). And in all cases, the third parameter is +a LegalAction type enum value: Promote, Expand, +Custom, or Legal. SparcISelLowering.cpp +contains examples of all four LegalAction values. +

    + +
    + + +
    + Promote +
    + +
    + +

    +For an operation without native support for a given type, the specified type may +be promoted to a larger type that is supported. For example, SPARC does not +support a sign-extending load for Boolean values (i1 type), so +in SparcISelLowering.cpp the third parameter below, Promote, +changes i1 type values to a large type before loading. +

    + +
    +
    +setLoadExtAction(ISD::SEXTLOAD, MVT::i1, Promote);
    +
    +
    + +
    + + +
    + Expand +
    + +
    + +

    +For a type without native support, a value may need to be broken down further, +rather than promoted. For an operation without native support, a combination of +other operations may be used to similar effect. In SPARC, the floating-point +sine and cosine trig operations are supported by expansion to other operations, +as indicated by the third parameter, Expand, to +setOperationAction: +

    + +
    +
    +setOperationAction(ISD::FSIN, MVT::f32, Expand);
    +setOperationAction(ISD::FCOS, MVT::f32, Expand);
    +
    +
    + +
    + + +
    + Custom +
    + +
    + +

    +For some operations, simple type promotion or operation expansion may be +insufficient. In some cases, a special intrinsic function must be implemented. +

    + +

    +For example, a constant value may require special treatment, or an operation may +require spilling and restoring registers in the stack and working with register +allocators. +

    + +

    +As seen in SparcISelLowering.cpp code below, to perform a type +conversion from a floating point value to a signed integer, first the +setOperationAction should be called with Custom as the third +parameter: +

    + +
    +
    +setOperationAction(ISD::FP_TO_SINT, MVT::i32, Custom);
    +
    +
    + +

    +In the LowerOperation method, for each Custom operation, a +case statement should be added to indicate what function to call. In the +following code, an FP_TO_SINT opcode will call +the LowerFP_TO_SINT method: +

    + +
    +
    +SDValue SparcTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) {
    +  switch (Op.getOpcode()) {
    +  case ISD::FP_TO_SINT: return LowerFP_TO_SINT(Op, DAG);
    +  ...
    +  }
    +}
    +
    +
    + +

    +Finally, the LowerFP_TO_SINT method is implemented, using an FP +register to convert the floating-point value to an integer. +

    + +
    +
    +static SDValue LowerFP_TO_SINT(SDValue Op, SelectionDAG &DAG) {
    +  assert(Op.getValueType() == MVT::i32);
    +  Op = DAG.getNode(SPISD::FTOI, MVT::f32, Op.getOperand(0));
    +  return DAG.getNode(ISD::BIT_CONVERT, MVT::i32, Op);
    +}
    +
    +
    + +
    + + +
    + Legal +
    + +
    + +

    +The Legal LegalizeAction enum value simply indicates that an +operation is natively supported. Legal represents the default +condition, so it is rarely used. In SparcISelLowering.cpp, the action +for CTPOP (an operation to count the bits set in an integer) is +natively supported only for SPARC v9. The following code enables +the Expand conversion technique for non-v9 SPARC implementations. +

    + +
    +
    +setOperationAction(ISD::CTPOP, MVT::i32, Expand);
    +...
    +if (TM.getSubtarget<SparcSubtarget>().isV9())
    +  setOperationAction(ISD::CTPOP, MVT::i32, Legal);
    +  case ISD::SETULT: return SPCC::ICC_CS;
    +  case ISD::SETULE: return SPCC::ICC_LEU;
    +  case ISD::SETUGT: return SPCC::ICC_GU;
    +  case ISD::SETUGE: return SPCC::ICC_CC;
    +  }
    +}
    +
    +
    + +
    + + + + +
    + +

    +To support target-specific calling conventions, XXXGenCallingConv.td +uses interfaces (such as CCIfType and CCAssignToReg) that are defined in +lib/Target/TargetCallingConv.td. TableGen can take the target +descriptor file XXXGenCallingConv.td and generate the header +file XXXGenCallingConv.inc, which is typically included +in XXXISelLowering.cpp. You can use the interfaces in +TargetCallingConv.td to specify: +

    + +
      +
    • The order of parameter allocation.
    • + +
    • Where parameters and return values are placed (that is, on the stack or in + registers).
    • + +
    • Which registers may be used.
    • + +
    • Whether the caller or callee unwinds the stack.
    • +
    + +

    +The following example demonstrates the use of the CCIfType and +CCAssignToReg interfaces. If the CCIfType predicate is true +(that is, if the current argument is of type f32 or f64), then +the action is performed. In this case, the CCAssignToReg action assigns +the argument value to the first available register: either R0 +or R1. +

    + +
    +
    +CCIfType<[f32,f64], CCAssignToReg<[R0, R1]>>
    +
    +
    + +

    +SparcCallingConv.td contains definitions for a target-specific +return-value calling convention (RetCC_Sparc32) and a basic 32-bit C calling +convention (CC_Sparc32). The definition of RetCC_Sparc32 +(shown below) indicates which registers are used for specified scalar return +types. A single-precision float is returned to register F0, and a +double-precision float goes to register D0. A 32-bit integer is +returned in register I0 or I1. +

    + +
    +
    +def RetCC_Sparc32 : CallingConv<[
    +  CCIfType<[i32], CCAssignToReg<[I0, I1]>>,
    +  CCIfType<[f32], CCAssignToReg<[F0]>>,
    +  CCIfType<[f64], CCAssignToReg<[D0]>>
    +]>;
    +
    +
    + +

    +The definition of CC_Sparc32 in SparcCallingConv.td introduces +CCAssignToStack, which assigns the value to a stack slot with the +specified size and alignment. In the example below, the first parameter, 4, +indicates the size of the slot, and the second parameter, also 4, indicates the +stack alignment along 4-byte units. (Special cases: if size is zero, then the +ABI size is used; if alignment is zero, then the ABI alignment is used.) +

    + +
    +
    +def CC_Sparc32 : CallingConv<[
    +  // All arguments get passed in integer registers if there is space.
    +  CCIfType<[i32, f32, f64], CCAssignToReg<[I0, I1, I2, I3, I4, I5]>>,
    +  CCAssignToStack<4, 4>
    +]>;
    +
    +
    + +

    +CCDelegateTo is another commonly used interface, which tries to find a +specified sub-calling convention, and, if a match is found, it is invoked. In +the following example (in X86CallingConv.td), the definition of +RetCC_X86_32_C ends with CCDelegateTo. After the current value +is assigned to the register ST0 or ST1, +the RetCC_X86Common is invoked. +

    + +
    +
    +def RetCC_X86_32_C : CallingConv<[
    +  CCIfType<[f32], CCAssignToReg<[ST0, ST1]>>,
    +  CCIfType<[f64], CCAssignToReg<[ST0, ST1]>>,
    +  CCDelegateTo<RetCC_X86Common>
    +]>;
    +
    +
    + +

    +CCIfCC is an interface that attempts to match the given name to the +current calling convention. If the name identifies the current calling +convention, then a specified action is invoked. In the following example (in +X86CallingConv.td), if the Fast calling convention is in use, +then RetCC_X86_32_Fast is invoked. If the SSECall calling +convention is in use, then RetCC_X86_32_SSE is invoked. +

    + +
    +
    +def RetCC_X86_32 : CallingConv<[
    +  CCIfCC<"CallingConv::Fast", CCDelegateTo<RetCC_X86_32_Fast>>,
    +  CCIfCC<"CallingConv::X86_SSECall", CCDelegateTo<RetCC_X86_32_SSE>>,
    +  CCDelegateTo<RetCC_X86_32_C>
    +]>;
    +
    +
    + +

    Other calling convention interfaces include:

    + +
      +
    • CCIf <predicate, action> — If the predicate matches, + apply the action.
    • + +
    • CCIfInReg <action> — If the argument is marked with the + 'inreg' attribute, then apply the action.
    • + +
    • CCIfNest <action> — Inf the argument is marked with the + 'nest' attribute, then apply the action.
    • + +
    • CCIfNotVarArg <action> — If the current function does + not take a variable number of arguments, apply the action.
    • + +
    • CCAssignToRegWithShadow <registerList, shadowList> — + similar to CCAssignToReg, but with a shadow list of registers.
    • + +
    • CCPassByVal <size, align> — Assign value to a stack + slot with the minimum specified size and alignment.
    • + +
    • CCPromoteToType <type> — Promote the current value to + the specified type.
    • + +
    • CallingConv <[actions]> — Define each calling + convention that is supported.
    • +
    + +
    + + + + + +
    + +

    +During the code emission stage, the code generator may utilize an LLVM pass to +produce assembly output. To do this, you want to implement the code for a +printer that converts LLVM IR to a GAS-format assembly language for your target +machine, using the following steps: +

    + +
      +
    • Define all the assembly strings for your target, adding them to the + instructions defined in the XXXInstrInfo.td file. + (See Instruction Set.) TableGen will produce + an output file (XXXGenAsmWriter.inc) with an implementation of + the printInstruction method for the XXXAsmPrinter class.
    • + +
    • Write XXXTargetAsmInfo.h, which contains the bare-bones declaration + of the XXXTargetAsmInfo class (a subclass + of TargetAsmInfo).
    • + +
    • Write XXXTargetAsmInfo.cpp, which contains target-specific values + for TargetAsmInfo properties and sometimes new implementations for + methods.
    • + +
    • Write XXXAsmPrinter.cpp, which implements the AsmPrinter + class that performs the LLVM-to-assembly conversion.
    • +
    + +

    +The code in XXXTargetAsmInfo.h is usually a trivial declaration of the +XXXTargetAsmInfo class for use in XXXTargetAsmInfo.cpp. +Similarly, XXXTargetAsmInfo.cpp usually has a few declarations of +XXXTargetAsmInfo replacement values that override the default values +in TargetAsmInfo.cpp. For example in SparcTargetAsmInfo.cpp: +

    + +
    +
    +SparcTargetAsmInfo::SparcTargetAsmInfo(const SparcTargetMachine &TM) {
    +  Data16bitsDirective = "\t.half\t";
    +  Data32bitsDirective = "\t.word\t";
    +  Data64bitsDirective = 0;  // .xword is only supported by V9.
    +  ZeroDirective = "\t.skip\t";
    +  CommentString = "!";
    +  ConstantPoolSection = "\t.section \".rodata\",#alloc\n";
    +}
    +
    +
    + +

    +The X86 assembly printer implementation (X86TargetAsmInfo) is an +example where the target specific TargetAsmInfo class uses an +overridden methods: ExpandInlineAsm. +

    + +

    +A target-specific implementation of AsmPrinter is written in +XXXAsmPrinter.cpp, which implements the AsmPrinter class that +converts the LLVM to printable assembly. The implementation must include the +following headers that have declarations for the AsmPrinter and +MachineFunctionPass classes. The MachineFunctionPass is a +subclass of FunctionPass. +

    + +
    +
    +#include "llvm/CodeGen/AsmPrinter.h"
    +#include "llvm/CodeGen/MachineFunctionPass.h" 
    +
    +
    + +

    +As a FunctionPass, AsmPrinter first +calls doInitialization to set up the AsmPrinter. In +SparcAsmPrinter, a Mangler object is instantiated to process +variable names. +

    + +

    +In XXXAsmPrinter.cpp, the runOnMachineFunction method +(declared in MachineFunctionPass) must be implemented +for XXXAsmPrinter. In MachineFunctionPass, +the runOnFunction method invokes runOnMachineFunction. +Target-specific implementations of runOnMachineFunction differ, but +generally do the following to process each machine function: +

    + +
      +
    • Call SetupMachineFunction to perform initialization.
    • + +
    • Call EmitConstantPool to print out (to the output stream) constants + which have been spilled to memory.
    • + +
    • Call EmitJumpTableInfo to print out jump tables used by the current + function.
    • + +
    • Print out the label for the current function.
    • + +
    • Print out the code for the function, including basic block labels and the + assembly for the instruction (using printInstruction)
    • +
    + +

    +The XXXAsmPrinter implementation must also include the code generated +by TableGen that is output in the XXXGenAsmWriter.inc file. The code +in XXXGenAsmWriter.inc contains an implementation of the +printInstruction method that may call these methods: +

    + +
      +
    • printOperand
    • + +
    • printMemOperand
    • + +
    • printCCOperand (for conditional statements)
    • + +
    • printDataDirective
    • + +
    • printDeclare
    • + +
    • printImplicitDef
    • + +
    • printInlineAsm
    • + +
    • printLabel
    • + +
    • printPICJumpTableEntry
    • + +
    • printPICJumpTableSetLabel
    • +
    + +

    +The implementations of printDeclare, printImplicitDef, +printInlineAsm, and printLabel in AsmPrinter.cpp are +generally adequate for printing assembly and do not need to be +overridden. +

    + +

    +The printOperand method is implemented with a long switch/case +statement for the type of operand: register, immediate, basic block, external +symbol, global address, constant pool index, or jump table index. For an +instruction with a memory address operand, the printMemOperand method +should be implemented to generate the proper output. Similarly, +printCCOperand should be used to print a conditional operand. +

    + +

    doFinalization should be overridden in XXXAsmPrinter, and +it should be called to shut down the assembly printer. During +doFinalization, global variables and constants are printed to +output. +

    + +
    + + + + + +
    + +

    +Subtarget support is used to inform the code generation process of instruction +set variations for a given chip set. For example, the LLVM SPARC implementation +provided covers three major versions of the SPARC microprocessor architecture: +Version 8 (V8, which is a 32-bit architecture), Version 9 (V9, a 64-bit +architecture), and the UltraSPARC architecture. V8 has 16 double-precision +floating-point registers that are also usable as either 32 single-precision or 8 +quad-precision registers. V8 is also purely big-endian. V9 has 32 +double-precision floating-point registers that are also usable as 16 +quad-precision registers, but cannot be used as single-precision registers. The +UltraSPARC architecture combines V9 with UltraSPARC Visual Instruction Set +extensions. +

    + +

    +If subtarget support is needed, you should implement a target-specific +XXXSubtarget class for your architecture. This class should process the +command-line options -mcpu= and -mattr=. +

    + +

    +TableGen uses definitions in the Target.td and Sparc.td files +to generate code in SparcGenSubtarget.inc. In Target.td, shown +below, the SubtargetFeature interface is defined. The first 4 string +parameters of the SubtargetFeature interface are a feature name, an +attribute set by the feature, the value of the attribute, and a description of +the feature. (The fifth parameter is a list of features whose presence is +implied, and its default value is an empty array.) +

    + +
    +
    +class SubtargetFeature<string n, string a,  string v, string d,
    +                       list<SubtargetFeature> i = []> {
    +  string Name = n;
    +  string Attribute = a;
    +  string Value = v;
    +  string Desc = d;
    +  list<SubtargetFeature> Implies = i;
    +}
    +
    +
    + +

    +In the Sparc.td file, the SubtargetFeature is used to define the +following features. +

    + +
    +
    +def FeatureV9 : SubtargetFeature<"v9", "IsV9", "true",
    +                     "Enable SPARC-V9 instructions">;
    +def FeatureV8Deprecated : SubtargetFeature<"deprecated-v8", 
    +                     "V8DeprecatedInsts", "true",
    +                     "Enable deprecated V8 instructions in V9 mode">;
    +def FeatureVIS : SubtargetFeature<"vis", "IsVIS", "true",
    +                     "Enable UltraSPARC Visual Instruction Set extensions">;
    +
    +
    + +

    +Elsewhere in Sparc.td, the Proc class is defined and then is used to +define particular SPARC processor subtypes that may have the previously +described features. +

    + +
    +
    +class Proc<string Name, list<SubtargetFeature> Features>
    +  : Processor<Name, NoItineraries, Features>;
    + 
    +def : Proc<"generic",         []>;
    +def : Proc<"v8",              []>;
    +def : Proc<"supersparc",      []>;
    +def : Proc<"sparclite",       []>;
    +def : Proc<"f934",            []>;
    +def : Proc<"hypersparc",      []>;
    +def : Proc<"sparclite86x",    []>;
    +def : Proc<"sparclet",        []>;
    +def : Proc<"tsc701",          []>;
    +def : Proc<"v9",              [FeatureV9]>;
    +def : Proc<"ultrasparc",      [FeatureV9, FeatureV8Deprecated]>;
    +def : Proc<"ultrasparc3",     [FeatureV9, FeatureV8Deprecated]>;
    +def : Proc<"ultrasparc3-vis", [FeatureV9, FeatureV8Deprecated, FeatureVIS]>;
    +
    +
    + +

    +From Target.td and Sparc.td files, the resulting +SparcGenSubtarget.inc specifies enum values to identify the features, arrays of +constants to represent the CPU features and CPU subtypes, and the +ParseSubtargetFeatures method that parses the features string that sets +specified subtarget options. The generated SparcGenSubtarget.inc file +should be included in the SparcSubtarget.cpp. The target-specific +implementation of the XXXSubtarget method should follow this pseudocode: +

    + +
    +
    +XXXSubtarget::XXXSubtarget(const Module &M, const std::string &FS) {
    +  // Set the default features
    +  // Determine default and user specified characteristics of the CPU
    +  // Call ParseSubtargetFeatures(FS, CPU) to parse the features string
    +  // Perform any additional operations
    +}
    +
    +
    + +
    + + + + + +
    + +

    +The implementation of a target machine optionally includes a Just-In-Time (JIT) +code generator that emits machine code and auxiliary structures as binary output +that can be written directly to memory. To do this, implement JIT code +generation by performing the following steps: +

    + +
      +
    • Write an XXXCodeEmitter.cpp file that contains a machine function + pass that transforms target-machine instructions into relocatable machine + code.
    • + +
    • Write an XXXJITInfo.cpp file that implements the JIT interfaces for + target-specific code-generation activities, such as emitting machine code + and stubs.
    • + +
    • Modify XXXTargetMachine so that it provides a + TargetJITInfo object through its getJITInfo method.
    • +
    + +

    +There are several different approaches to writing the JIT support code. For +instance, TableGen and target descriptor files may be used for creating a JIT +code generator, but are not mandatory. For the Alpha and PowerPC target +machines, TableGen is used to generate XXXGenCodeEmitter.inc, which +contains the binary coding of machine instructions and the +getBinaryCodeForInstr method to access those codes. Other JIT +implementations do not. +

    + +

    +Both XXXJITInfo.cpp and XXXCodeEmitter.cpp must include the +llvm/CodeGen/MachineCodeEmitter.h header file that defines the +MachineCodeEmitter class containing code for several callback functions +that write data (in bytes, words, strings, etc.) to the output stream. +

    + +
    + + + + +
    + +

    +In XXXCodeEmitter.cpp, a target-specific of the Emitter class +is implemented as a function pass (subclass +of MachineFunctionPass). The target-specific implementation +of runOnMachineFunction (invoked by +runOnFunction in MachineFunctionPass) iterates through the +MachineBasicBlock calls emitInstruction to process each +instruction and emit binary code. emitInstruction is largely +implemented with case statements on the instruction types defined in +XXXInstrInfo.h. For example, in X86CodeEmitter.cpp, +the emitInstruction method is built around the following switch/case +statements: +

    + +
    +
    +switch (Desc->TSFlags & X86::FormMask) {
    +case X86II::Pseudo:  // for not yet implemented instructions 
    +   ...               // or pseudo-instructions
    +   break;
    +case X86II::RawFrm:  // for instructions with a fixed opcode value
    +   ...
    +   break;
    +case X86II::AddRegFrm: // for instructions that have one register operand 
    +   ...                 // added to their opcode
    +   break;
    +case X86II::MRMDestReg:// for instructions that use the Mod/RM byte
    +   ...                 // to specify a destination (register)
    +   break;
    +case X86II::MRMDestMem:// for instructions that use the Mod/RM byte
    +   ...                 // to specify a destination (memory)
    +   break;
    +case X86II::MRMSrcReg: // for instructions that use the Mod/RM byte
    +   ...                 // to specify a source (register)
    +   break;
    +case X86II::MRMSrcMem: // for instructions that use the Mod/RM byte
    +   ...                 // to specify a source (memory)
    +   break;
    +case X86II::MRM0r: case X86II::MRM1r:  // for instructions that operate on 
    +case X86II::MRM2r: case X86II::MRM3r:  // a REGISTER r/m operand and
    +case X86II::MRM4r: case X86II::MRM5r:  // use the Mod/RM byte and a field
    +case X86II::MRM6r: case X86II::MRM7r:  // to hold extended opcode data
    +   ...  
    +   break;
    +case X86II::MRM0m: case X86II::MRM1m:  // for instructions that operate on
    +case X86II::MRM2m: case X86II::MRM3m:  // a MEMORY r/m operand and
    +case X86II::MRM4m: case X86II::MRM5m:  // use the Mod/RM byte and a field
    +case X86II::MRM6m: case X86II::MRM7m:  // to hold extended opcode data
    +   ...  
    +   break;
    +case X86II::MRMInitReg: // for instructions whose source and
    +   ...                  // destination are the same register
    +   break;
    +}
    +
    +
    + +

    +The implementations of these case statements often first emit the opcode and +then get the operand(s). Then depending upon the operand, helper methods may be +called to process the operand(s). For example, in X86CodeEmitter.cpp, +for the X86II::AddRegFrm case, the first data emitted +(by emitByte) is the opcode added to the register operand. Then an +object representing the machine operand, MO1, is extracted. The helper +methods such as isImmediate, +isGlobalAddress, isExternalSymbol, isConstantPoolIndex, and +isJumpTableIndex determine the operand +type. (X86CodeEmitter.cpp also has private methods such +as emitConstant, emitGlobalAddress, +emitExternalSymbolAddress, emitConstPoolAddress, +and emitJumpTableAddress that emit the data into the output stream.) +

    + +
    +
    +case X86II::AddRegFrm:
    +  MCE.emitByte(BaseOpcode + getX86RegNum(MI.getOperand(CurOp++).getReg()));
    +  
    +  if (CurOp != NumOps) {
    +    const MachineOperand &MO1 = MI.getOperand(CurOp++);
    +    unsigned Size = X86InstrInfo::sizeOfImm(Desc);
    +    if (MO1.isImmediate())
    +      emitConstant(MO1.getImm(), Size);
    +    else {
    +      unsigned rt = Is64BitMode ? X86::reloc_pcrel_word
    +        : (IsPIC ? X86::reloc_picrel_word : X86::reloc_absolute_word);
    +      if (Opcode == X86::MOV64ri) 
    +        rt = X86::reloc_absolute_dword;  // FIXME: add X86II flag?
    +      if (MO1.isGlobalAddress()) {
    +        bool NeedStub = isa<Function>(MO1.getGlobal());
    +        bool isLazy = gvNeedsLazyPtr(MO1.getGlobal());
    +        emitGlobalAddress(MO1.getGlobal(), rt, MO1.getOffset(), 0,
    +                          NeedStub, isLazy);
    +      } else if (MO1.isExternalSymbol())
    +        emitExternalSymbolAddress(MO1.getSymbolName(), rt);
    +      else if (MO1.isConstantPoolIndex())
    +        emitConstPoolAddress(MO1.getIndex(), rt);
    +      else if (MO1.isJumpTableIndex())
    +        emitJumpTableAddress(MO1.getIndex(), rt);
    +    }
    +  }
    +  break;
    +
    +
    + +

    +In the previous example, XXXCodeEmitter.cpp uses the +variable rt, which is a RelocationType enum that may be used to +relocate addresses (for example, a global address with a PIC base offset). The +RelocationType enum for that target is defined in the short +target-specific XXXRelocations.h file. The RelocationType is used by +the relocate method defined in XXXJITInfo.cpp to rewrite +addresses for referenced global symbols. +

    + +

    +For example, X86Relocations.h specifies the following relocation types +for the X86 addresses. In all four cases, the relocated value is added to the +value already in memory. For reloc_pcrel_word +and reloc_picrel_word, there is an additional initial adjustment. +

    + +
    +
    +enum RelocationType {
    +  reloc_pcrel_word = 0,    // add reloc value after adjusting for the PC loc
    +  reloc_picrel_word = 1,   // add reloc value after adjusting for the PIC base
    +  reloc_absolute_word = 2, // absolute relocation; no additional adjustment 
    +  reloc_absolute_dword = 3 // absolute relocation; no additional adjustment
    +};
    +
    +
    + +
    + + + + +
    + +

    +XXXJITInfo.cpp implements the JIT interfaces for target-specific +code-generation activities, such as emitting machine code and stubs. At minimum, +a target-specific version of XXXJITInfo implements the following: +

    + +
      +
    • getLazyResolverFunction — Initializes the JIT, gives the + target a function that is used for compilation.
    • + +
    • emitFunctionStub — Returns a native function with a specified + address for a callback function.
    • + +
    • relocate — Changes the addresses of referenced globals, based + on relocation types.
    • + +
    • Callback function that are wrappers to a function stub that is used when the + real target is not initially known.
    • +
    + +

    +getLazyResolverFunction is generally trivial to implement. It makes the +incoming parameter as the global JITCompilerFunction and returns the +callback function that will be used a function wrapper. For the Alpha target +(in AlphaJITInfo.cpp), the getLazyResolverFunction +implementation is simply: +

    + +
    +
    +TargetJITInfo::LazyResolverFn AlphaJITInfo::getLazyResolverFunction(  
    +                                            JITCompilerFn F) {
    +  JITCompilerFunction = F;
    +  return AlphaCompilationCallback;
    +}
    +
    +
    + +

    +For the X86 target, the getLazyResolverFunction implementation is a +little more complication, because it returns a different callback function for +processors with SSE instructions and XMM registers. +

    + +

    +The callback function initially saves and later restores the callee register +values, incoming arguments, and frame and return address. The callback function +needs low-level access to the registers or stack, so it is typically implemented +with assembler. +

    + +
    + + + +
    +
    + Valid CSS + Valid HTML 4.01 + + Mason Woo and Misha Brukman
    + The LLVM Compiler Infrastructure +
    + Last modified: $Date$ +
    + + + diff --git a/libclamav/c++/llvm/docs/WritingAnLLVMPass.html b/libclamav/c++/llvm/docs/WritingAnLLVMPass.html new file mode 100644 index 000000000..f531a74a6 --- /dev/null +++ b/libclamav/c++/llvm/docs/WritingAnLLVMPass.html @@ -0,0 +1,1836 @@ + + + + + Writing an LLVM Pass + + + + +
    + Writing an LLVM Pass +
    + +
      +
    1. Introduction - What is a pass?
    2. +
    3. Quick Start - Writing hello world +
    4. +
    5. Pass classes and requirements + +
    6. Pass Registration +
    7. +
    8. Specifying interactions between passes +
    9. +
    10. Implementing Analysis Groups +
    11. +
    12. Pass Statistics +
    13. What PassManager does +
    14. +
    15. Registering dynamically loaded passes +
    16. +
    17. Using GDB with dynamically loaded passes +
    18. +
    19. Future extensions planned +
    20. +
    + +
    +

    Written by Chris Lattner and + Jim Laskey

    +
    + + + + + +
    + +

    The LLVM Pass Framework is an important part of the LLVM system, because LLVM +passes are where most of the interesting parts of the compiler exist. Passes +perform the transformations and optimizations that make up the compiler, they +build the analysis results that are used by these transformations, and they are, +above all, a structuring technique for compiler code.

    + +

    All LLVM passes are subclasses of the Pass +class, which implement functionality by overriding virtual methods inherited +from Pass. Depending on how your pass works, you should inherit from +the ModulePass, CallGraphSCCPass, FunctionPass, or LoopPass, or BasicBlockPass classes, which gives the system +more information about what your pass does, and how it can be combined with +other passes. One of the main features of the LLVM Pass Framework is that it +schedules passes to run in an efficient way based on the constraints that your +pass meets (which are indicated by which class they derive from).

    + +

    We start by showing you how to construct a pass, everything from setting up +the code, to compiling, loading, and executing it. After the basics are down, +more advanced features are discussed.

    + +
    + + + + + +
    + +

    Here we describe how to write the "hello world" of passes. The "Hello" pass +is designed to simply print out the name of non-external functions that exist in +the program being compiled. It does not modify the program at all, it just +inspects it. The source code and files for this pass are available in the LLVM +source tree in the lib/Transforms/Hello directory.

    + +
    + + + + +
    + +

    First, you need to create a new directory somewhere in the LLVM source + base. For this example, we'll assume that you made + lib/Transforms/Hello. Next, you must set up a build script + (Makefile) that will compile the source code for the new pass. To do this, + copy the following into Makefile:

    +
    + +
    +# Makefile for hello pass
    +
    +# Path to top level of LLVM hierarchy
    +LEVEL = ../../..
    +
    +# Name of the library to build
    +LIBRARYNAME = Hello
    +
    +# Make the shared library become a loadable module so the tools can 
    +# dlopen/dlsym on the resulting library.
    +LOADABLE_MODULE = 1
    +
    +# Tell the build system which LLVM libraries your pass needs. You'll probably
    +# need at least LLVMSystem.a, LLVMSupport.a, LLVMCore.a but possibly several
    +# others too.
    +LLVMLIBS = LLVMCore.a LLVMSupport.a LLVMSystem.a
    +
    +# Include the makefile implementation stuff
    +include $(LEVEL)/Makefile.common
    +
    + +

    This makefile specifies that all of the .cpp files in the current +directory are to be compiled and linked together into a +Debug/lib/Hello.so shared object that can be dynamically loaded by +the opt or bugpoint tools via their -load options. +If your operating system uses a suffix other than .so (such as windows or +Mac OS/X), the appropriate extension will be used.

    + +

    Now that we have the build scripts set up, we just need to write the code for +the pass itself.

    + +
    + + + + +
    + +

    Now that we have a way to compile our new pass, we just have to write it. +Start out with:

    + +
    +#include "llvm/Pass.h"
    +#include "llvm/Function.h"
    +#include "llvm/Support/raw_ostream.h"
    +
    + +

    Which are needed because we are writing a Pass, +we are operating on Function's, +and we will be doing some printing.

    + +

    Next we have:

    +
    +using namespace llvm;
    +
    +

    ... which is required because the functions from the include files +live in the llvm namespace. +

    + +

    Next we have:

    + +
    +namespace {
    +
    + +

    ... which starts out an anonymous namespace. Anonymous namespaces are to C++ +what the "static" keyword is to C (at global scope). It makes the +things declared inside of the anonymous namespace only visible to the current +file. If you're not familiar with them, consult a decent C++ book for more +information.

    + +

    Next, we declare our pass itself:

    + +
    +  struct Hello : public FunctionPass {
    +

    + +

    This declares a "Hello" class that is a subclass of FunctionPass. +The different builtin pass subclasses are described in detail later, but for now, know that FunctionPass's operate a function at a +time.

    + +
    +     static char ID;
    +     Hello() : FunctionPass(&ID) {}
    +

    + +

    This declares pass identifier used by LLVM to identify pass. This allows LLVM to +avoid using expensive C++ runtime information.

    + +
    +    virtual bool runOnFunction(Function &F) {
    +      errs() << "Hello: " << F.getName() << "\n";
    +      return false;
    +    }
    +  };  // end of struct Hello
    +
    + +

    We declare a "runOnFunction" method, +which overloads an abstract virtual method inherited from FunctionPass. This is where we are supposed +to do our thing, so we just print out our message with the name of each +function.

    + +
    +  char Hello::ID = 0;
    +
    + +

    We initialize pass ID here. LLVM uses ID's address to identify pass so +initialization value is not important.

    + +
    +  RegisterPass<Hello> X("hello", "Hello World Pass",
    +                        false /* Only looks at CFG */,
    +                        false /* Analysis Pass */);
    +}  // end of anonymous namespace
    +
    + +

    Lastly, we register our class Hello, +giving it a command line +argument "hello", and a name "Hello World Pass". +Last two RegisterPass arguments are optional. Their default value is false. +If a pass walks CFG without modifying it then third argument is set to true. +If a pass is an analysis pass, for example dominator tree pass, then true +is supplied as fourth argument.

    + +

    As a whole, the .cpp file looks like:

    + +
    +#include "llvm/Pass.h"
    +#include "llvm/Function.h"
    +#include "llvm/Support/raw_ostream.h"
    +
    +using namespace llvm;
    +
    +namespace {
    +  struct Hello : public FunctionPass {
    +    
    +    static char ID;
    +    Hello() : FunctionPass(&ID) {}
    +
    +    virtual bool runOnFunction(Function &F) {
    +      errs() << "Hello: " << F.getName() << "\n";
    +      return false;
    +    }
    +  };
    +  
    +  char Hello::ID = 0;
    +  RegisterPass<Hello> X("hello", "Hello World Pass");
    +}
    +
    + +

    Now that it's all together, compile the file with a simple "gmake" +command in the local directory and you should get a new +"Debug/lib/Hello.so file. Note that everything in this file is +contained in an anonymous namespace: this reflects the fact that passes are self +contained units that do not need external interfaces (although they can have +them) to be useful.

    + +
    + + + + +
    + +

    Now that you have a brand new shiny shared object file, we can use the +opt command to run an LLVM program through your pass. Because you +registered your pass with the RegisterPass template, you will be able to +use the opt tool to access it, once loaded.

    + +

    To test it, follow the example at the end of the Getting Started Guide to compile "Hello World" to +LLVM. We can now run the bitcode file (hello.bc) for the program +through our transformation like this (or course, any bitcode file will +work):

    + +
    +$ opt -load ../../../Debug/lib/Hello.so -hello < hello.bc > /dev/null
    +Hello: __main
    +Hello: puts
    +Hello: main
    +
    + +

    The '-load' option specifies that 'opt' should load your +pass as a shared object, which makes '-hello' a valid command line +argument (which is one reason you need to register your +pass). Because the hello pass does not modify the program in any +interesting way, we just throw away the result of opt (sending it to +/dev/null).

    + +

    To see what happened to the other string you registered, try running +opt with the --help option:

    + +
    +$ opt -load ../../../Debug/lib/Hello.so --help
    +OVERVIEW: llvm .bc -> .bc modular optimizer
    +
    +USAGE: opt [options] <input bitcode>
    +
    +OPTIONS:
    +  Optimizations available:
    +...
    +    -funcresolve    - Resolve Functions
    +    -gcse           - Global Common Subexpression Elimination
    +    -globaldce      - Dead Global Elimination
    +    -hello          - Hello World Pass
    +    -indvars        - Canonicalize Induction Variables
    +    -inline         - Function Integration/Inlining
    +    -instcombine    - Combine redundant instructions
    +...
    +
    + +

    The pass name get added as the information string for your pass, giving some +documentation to users of opt. Now that you have a working pass, you +would go ahead and make it do the cool transformations you want. Once you get +it all working and tested, it may become useful to find out how fast your pass +is. The PassManager provides a nice command +line option (--time-passes) that allows you to get information about +the execution time of your pass along with the other passes you queue up. For +example:

    + +
    +$ opt -load ../../../Debug/lib/Hello.so -hello -time-passes < hello.bc > /dev/null
    +Hello: __main
    +Hello: puts
    +Hello: main
    +===============================================================================
    +                      ... Pass execution timing report ...
    +===============================================================================
    +  Total Execution Time: 0.02 seconds (0.0479059 wall clock)
    +
    +   ---User Time---   --System Time--   --User+System--   ---Wall Time---  --- Pass Name ---
    +   0.0100 (100.0%)   0.0000 (  0.0%)   0.0100 ( 50.0%)   0.0402 ( 84.0%)  Bitcode Writer
    +   0.0000 (  0.0%)   0.0100 (100.0%)   0.0100 ( 50.0%)   0.0031 (  6.4%)  Dominator Set Construction
    +   0.0000 (  0.0%)   0.0000 (  0.0%)   0.0000 (  0.0%)   0.0013 (  2.7%)  Module Verifier
    +   0.0000 (  0.0%)   0.0000 (  0.0%)   0.0000 (  0.0%)   0.0033 (  6.9%)  Hello World Pass
    +   0.0100 (100.0%)   0.0100 (100.0%)   0.0200 (100.0%)   0.0479 (100.0%)  TOTAL
    +
    + +

    As you can see, our implementation above is pretty fast :). The additional +passes listed are automatically inserted by the 'opt' tool to verify +that the LLVM emitted by your pass is still valid and well formed LLVM, which +hasn't been broken somehow.

    + +

    Now that you have seen the basics of the mechanics behind passes, we can talk +about some more details of how they work and how to use them.

    + +
    + + + + + +
    + +

    One of the first things that you should do when designing a new pass is to +decide what class you should subclass for your pass. The Hello World example uses the FunctionPass class for its implementation, but we +did not discuss why or when this should occur. Here we talk about the classes +available, from the most general to the most specific.

    + +

    When choosing a superclass for your Pass, you should choose the most +specific class possible, while still being able to meet the requirements +listed. This gives the LLVM Pass Infrastructure information necessary to +optimize how passes are run, so that the resultant compiler isn't unnecessarily +slow.

    + +
    + + + + +
    + +

    The most plain and boring type of pass is the "ImmutablePass" +class. This pass type is used for passes that do not have to be run, do not +change state, and never need to be updated. This is not a normal type of +transformation or analysis, but can provide information about the current +compiler configuration.

    + +

    Although this pass class is very infrequently used, it is important for +providing information about the current target machine being compiled for, and +other static information that can affect the various transformations.

    + +

    ImmutablePasses never invalidate other transformations, are never +invalidated, and are never "run".

    + +
    + + + + +
    + +

    The "ModulePass" +class is the most general of all superclasses that you can use. Deriving from +ModulePass indicates that your pass uses the entire program as a unit, +referring to function bodies in no predictable order, or adding and removing +functions. Because nothing is known about the behavior of ModulePass +subclasses, no optimization can be done for their execution.

    + +

    A module pass can use function level passes (e.g. dominators) using +the getAnalysis interface +getAnalysis<DominatorTree>(llvm::Function *) to provide the +function to retrieve analysis result for, if the function pass does not require +any module or immutable passes. Note that this can only be done for functions for which the +analysis ran, e.g. in the case of dominators you should only ask for the +DominatorTree for function definitions, not declarations.

    + +

    To write a correct ModulePass subclass, derive from +ModulePass and overload the runOnModule method with the +following signature:

    + +
    + + + + +
    + +
    +  virtual bool runOnModule(Module &M) = 0;
    +
    + +

    The runOnModule method performs the interesting work of the pass. +It should return true if the module was modified by the transformation and +false otherwise.

    + +
    + + + + +
    + +

    The "CallGraphSCCPass" +is used by passes that need to traverse the program bottom-up on the call graph +(callees before callers). Deriving from CallGraphSCCPass provides some +mechanics for building and traversing the CallGraph, but also allows the system +to optimize execution of CallGraphSCCPass's. If your pass meets the +requirements outlined below, and doesn't meet the requirements of a FunctionPass or BasicBlockPass, you should derive from +CallGraphSCCPass.

    + +

    TODO: explain briefly what SCC, Tarjan's algo, and B-U mean.

    + +

    To be explicit, CallGraphSCCPass subclasses are:

    + +
      + +
    1. ... not allowed to modify any Functions that are not in +the current SCC.
    2. + +
    3. ... not allowed to inspect any Function's other than those in the +current SCC and the direct callees of the SCC.
    4. + +
    5. ... required to preserve the current CallGraph object, updating it +to reflect any changes made to the program.
    6. + +
    7. ... not allowed to add or remove SCC's from the current Module, +though they may change the contents of an SCC.
    8. + +
    9. ... allowed to add or remove global variables from the current +Module.
    10. + +
    11. ... allowed to maintain state across invocations of + runOnSCC (including global data).
    12. +
    + +

    Implementing a CallGraphSCCPass is slightly tricky in some cases +because it has to handle SCCs with more than one node in it. All of the virtual +methods described below should return true if they modified the program, or +false if they didn't.

    + +
    + + + + +
    + +
    +  virtual bool doInitialization(CallGraph &CG);
    +
    + +

    The doIninitialize method is allowed to do most of the things that +CallGraphSCCPass's are not allowed to do. They can add and remove +functions, get pointers to functions, etc. The doInitialization method +is designed to do simple initialization type of stuff that does not depend on +the SCCs being processed. The doInitialization method call is not +scheduled to overlap with any other pass executions (thus it should be very +fast).

    + +
    + + + + +
    + +
    +  virtual bool runOnSCC(const std::vector<CallGraphNode *> &SCCM) = 0;
    +
    + +

    The runOnSCC method performs the interesting work of the pass, and +should return true if the module was modified by the transformation, false +otherwise.

    + +
    + + + + +
    + +
    +  virtual bool doFinalization(CallGraph &CG);
    +
    + +

    The doFinalization method is an infrequently used method that is +called when the pass framework has finished calling runOnFunction for every function in the +program being compiled.

    + +
    + + + + +
    + +

    In contrast to ModulePass subclasses, FunctionPass +subclasses do have a predictable, local behavior that can be expected by the +system. All FunctionPass execute on each function in the program +independent of all of the other functions in the program. +FunctionPass's do not require that they are executed in a particular +order, and FunctionPass's do not modify external functions.

    + +

    To be explicit, FunctionPass subclasses are not allowed to:

    + +
      +
    1. Modify a Function other than the one currently being processed.
    2. +
    3. Add or remove Function's from the current Module.
    4. +
    5. Add or remove global variables from the current Module.
    6. +
    7. Maintain state across invocations of + runOnFunction (including global data)
    8. +
    + +

    Implementing a FunctionPass is usually straightforward (See the Hello World pass for example). FunctionPass's +may overload three virtual methods to do their work. All of these methods +should return true if they modified the program, or false if they didn't.

    + +
    + + + + +
    + +
    +  virtual bool doInitialization(Module &M);
    +
    + +

    The doIninitialize method is allowed to do most of the things that +FunctionPass's are not allowed to do. They can add and remove +functions, get pointers to functions, etc. The doInitialization method +is designed to do simple initialization type of stuff that does not depend on +the functions being processed. The doInitialization method call is not +scheduled to overlap with any other pass executions (thus it should be very +fast).

    + +

    A good example of how this method should be used is the LowerAllocations +pass. This pass converts malloc and free instructions into +platform dependent malloc() and free() function calls. It +uses the doInitialization method to get a reference to the malloc and +free functions that it needs, adding prototypes to the module if necessary.

    + +
    + + + + +
    + +
    +  virtual bool runOnFunction(Function &F) = 0;
    +

    + +

    The runOnFunction method must be implemented by your subclass to do +the transformation or analysis work of your pass. As usual, a true value should +be returned if the function is modified.

    + +
    + + + + +
    + +
    +  virtual bool doFinalization(Module &M);
    +
    + +

    The doFinalization method is an infrequently used method that is +called when the pass framework has finished calling runOnFunction for every function in the +program being compiled.

    + +
    + + + + +
    + +

    All LoopPass execute on each loop in the function independent of +all of the other loops in the function. LoopPass processes loops in +loop nest order such that outer most loop is processed last.

    + +

    LoopPass subclasses are allowed to update loop nest using +LPPassManager interface. Implementing a loop pass is usually +straightforward. Looppass's may overload three virtual methods to +do their work. All these methods should return true if they modified the +program, or false if they didn't.

    +
    + + + + +
    + +
    +  virtual bool doInitialization(Loop *, LPPassManager &LPM);
    +
    + +

    The doInitialization method is designed to do simple initialization +type of stuff that does not depend on the functions being processed. The +doInitialization method call is not scheduled to overlap with any +other pass executions (thus it should be very fast). LPPassManager +interface should be used to access Function or Module level analysis +information.

    + +
    + + + + + +
    + +
    +  virtual bool runOnLoop(Loop *, LPPassManager &LPM) = 0;
    +

    + +

    The runOnLoop method must be implemented by your subclass to do +the transformation or analysis work of your pass. As usual, a true value should +be returned if the function is modified. LPPassManager interface +should be used to update loop nest.

    + +
    + + + + +
    + +
    +  virtual bool doFinalization();
    +
    + +

    The doFinalization method is an infrequently used method that is +called when the pass framework has finished calling runOnLoop for every loop in the +program being compiled.

    + +
    + + + + + + +
    + +

    BasicBlockPass's are just like FunctionPass's, except that they must limit +their scope of inspection and modification to a single basic block at a time. +As such, they are not allowed to do any of the following:

    + +
      +
    1. Modify or inspect any basic blocks outside of the current one
    2. +
    3. Maintain state across invocations of + runOnBasicBlock
    4. +
    5. Modify the control flow graph (by altering terminator instructions)
    6. +
    7. Any of the things forbidden for + FunctionPasses.
    8. +
    + +

    BasicBlockPasses are useful for traditional local and "peephole" +optimizations. They may override the same doInitialization(Module &) and doFinalization(Module &) methods that FunctionPass's have, but also have the following virtual methods that may also be implemented:

    + +
    + + + + +
    + +
    +  virtual bool doInitialization(Function &F);
    +
    + +

    The doIninitialize method is allowed to do most of the things that +BasicBlockPass's are not allowed to do, but that +FunctionPass's can. The doInitialization method is designed +to do simple initialization that does not depend on the +BasicBlocks being processed. The doInitialization method call is not +scheduled to overlap with any other pass executions (thus it should be very +fast).

    + +
    + + + + +
    + +
    +  virtual bool runOnBasicBlock(BasicBlock &BB) = 0;
    +
    + +

    Override this function to do the work of the BasicBlockPass. This +function is not allowed to inspect or modify basic blocks other than the +parameter, and are not allowed to modify the CFG. A true value must be returned +if the basic block is modified.

    + +
    + + + + +
    + +
    +  virtual bool doFinalization(Function &F);
    +
    + +

    The doFinalization method is an infrequently used method that is +called when the pass framework has finished calling runOnBasicBlock for every BasicBlock in the +program being compiled. This can be used to perform per-function +finalization.

    + +
    + + + + +
    + +

    A MachineFunctionPass is a part of the LLVM code generator that +executes on the machine-dependent representation of each LLVM function in the +program. A MachineFunctionPass is also a FunctionPass, so all +the restrictions that apply to a FunctionPass also apply to it. +MachineFunctionPasses also have additional restrictions. In particular, +MachineFunctionPasses are not allowed to do any of the following:

    + +
      +
    1. Modify any LLVM Instructions, BasicBlocks or Functions.
    2. +
    3. Modify a MachineFunction other than the one currently being processed.
    4. +
    5. Add or remove MachineFunctions from the current Module.
    6. +
    7. Add or remove global variables from the current Module.
    8. +
    9. Maintain state across invocations of runOnMachineFunction (including global +data)
    10. +
    + +
    + + + + +
    + +
    +  virtual bool runOnMachineFunction(MachineFunction &MF) = 0;
    +
    + +

    runOnMachineFunction can be considered the main entry point of a +MachineFunctionPass; that is, you should override this method to do the +work of your MachineFunctionPass.

    + +

    The runOnMachineFunction method is called on every +MachineFunction in a Module, so that the +MachineFunctionPass may perform optimizations on the machine-dependent +representation of the function. If you want to get at the LLVM Function +for the MachineFunction you're working on, use +MachineFunction's getFunction() accessor method -- but +remember, you may not modify the LLVM Function or its contents from a +MachineFunctionPass.

    + +
    + + + + + +
    + +

    In the Hello World example pass we illustrated how +pass registration works, and discussed some of the reasons that it is used and +what it does. Here we discuss how and why passes are registered.

    + +

    As we saw above, passes are registered with the RegisterPass +template, which requires you to pass at least two +parameters. The first parameter is the name of the pass that is to be used on +the command line to specify that the pass should be added to a program (for +example, with opt or bugpoint). The second argument is the +name of the pass, which is to be used for the --help output of +programs, as +well as for debug output generated by the --debug-pass option.

    + +

    If you want your pass to be easily dumpable, you should +implement the virtual print method:

    + +
    + + + + +
    + +
    +  virtual void print(std::ostream &O, const Module *M) const;
    +
    + +

    The print method must be implemented by "analyses" in order to print +a human readable version of the analysis results. This is useful for debugging +an analysis itself, as well as for other people to figure out how an analysis +works. Use the opt -analyze argument to invoke this method.

    + +

    The llvm::OStream parameter specifies the stream to write the results on, +and the Module parameter gives a pointer to the top level module of the +program that has been analyzed. Note however that this pointer may be null in +certain circumstances (such as calling the Pass::dump() from a +debugger), so it should only be used to enhance debug output, it should not be +depended on.

    + +
    + + + + + +
    + +

    One of the main responsibilities of the PassManager is to make sure +that passes interact with each other correctly. Because PassManager +tries to optimize the execution of passes it must +know how the passes interact with each other and what dependencies exist between +the various passes. To track this, each pass can declare the set of passes that +are required to be executed before the current pass, and the passes which are +invalidated by the current pass.

    + +

    Typically this functionality is used to require that analysis results are +computed before your pass is run. Running arbitrary transformation passes can +invalidate the computed analysis results, which is what the invalidation set +specifies. If a pass does not implement the getAnalysisUsage method, it defaults to not +having any prerequisite passes, and invalidating all other passes.

    + +
    + + + + +
    + +
    +  virtual void getAnalysisUsage(AnalysisUsage &Info) const;
    +
    + +

    By implementing the getAnalysisUsage method, the required and +invalidated sets may be specified for your transformation. The implementation +should fill in the AnalysisUsage +object with information about which passes are required and not invalidated. To +do this, a pass may call any of the following methods on the AnalysisUsage +object:

    +
    + + + + +
    +

    +If your pass requires a previous pass to be executed (an analysis for example), +it can use one of these methods to arrange for it to be run before your pass. +LLVM has many different types of analyses and passes that can be required, +spanning the range from DominatorSet to BreakCriticalEdges. +Requiring BreakCriticalEdges, for example, guarantees that there will +be no critical edges in the CFG when your pass has been run. +

    + +

    +Some analyses chain to other analyses to do their job. For example, an AliasAnalysis implementation is required to chain to other alias analysis passes. In +cases where analyses chain, the addRequiredTransitive method should be +used instead of the addRequired method. This informs the PassManager +that the transitively required pass should be alive as long as the requiring +pass is. +

    +
    + + + + +
    +

    +One of the jobs of the PassManager is to optimize how and when analyses are run. +In particular, it attempts to avoid recomputing data unless it needs to. For +this reason, passes are allowed to declare that they preserve (i.e., they don't +invalidate) an existing analysis if it's available. For example, a simple +constant folding pass would not modify the CFG, so it can't possibly affect the +results of dominator analysis. By default, all passes are assumed to invalidate +all others. +

    + +

    +The AnalysisUsage class provides several methods which are useful in +certain circumstances that are related to addPreserved. In particular, +the setPreservesAll method can be called to indicate that the pass does +not modify the LLVM program at all (which is true for analyses), and the +setPreservesCFG method can be used by transformations that change +instructions in the program but do not modify the CFG or terminator instructions +(note that this property is implicitly set for BasicBlockPass's). +

    + +

    +addPreserved is particularly useful for transformations like +BreakCriticalEdges. This pass knows how to update a small set of loop +and dominator related analyses if they exist, so it can preserve them, despite +the fact that it hacks on the CFG. +

    +
    + + + + +
    + +
    +  // This is an example implementation from an analysis, which does not modify
    +  // the program at all, yet has a prerequisite.
    +  void PostDominanceFrontier::getAnalysisUsage(AnalysisUsage &AU) const {
    +    AU.setPreservesAll();
    +    AU.addRequired<PostDominatorTree>();
    +  }
    +
    + +

    and:

    + +
    +  // This example modifies the program, but does not modify the CFG
    +  void LICM::getAnalysisUsage(AnalysisUsage &AU) const {
    +    AU.setPreservesCFG();
    +    AU.addRequired<LoopInfo>();
    +  }
    +
    + +
    + + + + +
    + +

    The Pass::getAnalysis<> method is automatically inherited by +your class, providing you with access to the passes that you declared that you +required with the getAnalysisUsage +method. It takes a single template argument that specifies which pass class you +want, and returns a reference to that pass. For example:

    + +
    +   bool LICM::runOnFunction(Function &F) {
    +     LoopInfo &LI = getAnalysis<LoopInfo>();
    +     ...
    +   }
    +
    + +

    This method call returns a reference to the pass desired. You may get a +runtime assertion failure if you attempt to get an analysis that you did not +declare as required in your getAnalysisUsage implementation. This +method can be called by your run* method implementation, or by any +other local method invoked by your run* method. + +A module level pass can use function level analysis info using this interface. +For example:

    + +
    +   bool ModuleLevelPass::runOnModule(Module &M) {
    +     ...
    +     DominatorTree &DT = getAnalysis<DominatorTree>(Func);
    +     ...
    +   }
    +
    + +

    In above example, runOnFunction for DominatorTree is called by pass manager +before returning a reference to the desired pass.

    + +

    +If your pass is capable of updating analyses if they exist (e.g., +BreakCriticalEdges, as described above), you can use the +getAnalysisIfAvailable method, which returns a pointer to the analysis +if it is active. For example:

    + +
    +  ...
    +  if (DominatorSet *DS = getAnalysisIfAvailable<DominatorSet>()) {
    +    // A DominatorSet is active.  This code will update it.
    +  }
    +  ...
    +
    + +
    + + + + + +
    + +

    Now that we understand the basics of how passes are defined, how they are +used, and how they are required from other passes, it's time to get a little bit +fancier. All of the pass relationships that we have seen so far are very +simple: one pass depends on one other specific pass to be run before it can run. +For many applications, this is great, for others, more flexibility is +required.

    + +

    In particular, some analyses are defined such that there is a single simple +interface to the analysis results, but multiple ways of calculating them. +Consider alias analysis for example. The most trivial alias analysis returns +"may alias" for any alias query. The most sophisticated analysis a +flow-sensitive, context-sensitive interprocedural analysis that can take a +significant amount of time to execute (and obviously, there is a lot of room +between these two extremes for other implementations). To cleanly support +situations like this, the LLVM Pass Infrastructure supports the notion of +Analysis Groups.

    + +
    + + + + +
    + +

    An Analysis Group is a single simple interface that may be implemented by +multiple different passes. Analysis Groups can be given human readable names +just like passes, but unlike passes, they need not derive from the Pass +class. An analysis group may have one or more implementations, one of which is +the "default" implementation.

    + +

    Analysis groups are used by client passes just like other passes are: the +AnalysisUsage::addRequired() and Pass::getAnalysis() methods. +In order to resolve this requirement, the PassManager +scans the available passes to see if any implementations of the analysis group +are available. If none is available, the default implementation is created for +the pass to use. All standard rules for interaction +between passes still apply.

    + +

    Although Pass Registration is optional for normal +passes, all analysis group implementations must be registered, and must use the +RegisterAnalysisGroup template to join the +implementation pool. Also, a default implementation of the interface +must be registered with RegisterAnalysisGroup.

    + +

    As a concrete example of an Analysis Group in action, consider the AliasAnalysis +analysis group. The default implementation of the alias analysis interface (the +basicaa +pass) just does a few simple checks that don't require significant analysis to +compute (such as: two different globals can never alias each other, etc). +Passes that use the AliasAnalysis +interface (for example the gcse pass), do +not care which implementation of alias analysis is actually provided, they just +use the designated interface.

    + +

    From the user's perspective, commands work just like normal. Issuing the +command 'opt -gcse ...' will cause the basicaa class to be +instantiated and added to the pass sequence. Issuing the command 'opt +-somefancyaa -gcse ...' will cause the gcse pass to use the +somefancyaa alias analysis (which doesn't actually exist, it's just a +hypothetical example) instead.

    + +
    + + + + +
    + +

    The RegisterAnalysisGroup template is used to register the analysis +group itself as well as add pass implementations to the analysis group. First, +an analysis should be registered, with a human readable name provided for it. +Unlike registration of passes, there is no command line argument to be specified +for the Analysis Group Interface itself, because it is "abstract":

    + +
    +  static RegisterAnalysisGroup<AliasAnalysis> A("Alias Analysis");
    +
    + +

    Once the analysis is registered, passes can declare that they are valid +implementations of the interface by using the following code:

    + +
    +namespace {
    +  // Analysis Group implementations must be registered normally...
    +  RegisterPass<FancyAA>
    +  B("somefancyaa", "A more complex alias analysis implementation");
    +
    +  // Declare that we implement the AliasAnalysis interface
    +  RegisterAnalysisGroup<AliasAnalysis> C(B);
    +}
    +
    + +

    This just shows a class FancyAA that is registered normally, then +uses the RegisterAnalysisGroup template to "join" the AliasAnalysis +analysis group. Every implementation of an analysis group should join using +this template. A single pass may join multiple different analysis groups with +no problem.

    + +
    +namespace {
    +  // Analysis Group implementations must be registered normally...
    +  RegisterPass<BasicAliasAnalysis>
    +  D("basicaa", "Basic Alias Analysis (default AA impl)");
    +
    +  // Declare that we implement the AliasAnalysis interface
    +  RegisterAnalysisGroup<AliasAnalysis, true> E(D);
    +}
    +
    + +

    Here we show how the default implementation is specified (using the extra +argument to the RegisterAnalysisGroup template). There must be exactly +one default implementation available at all times for an Analysis Group to be +used. Only default implementation can derive from ImmutablePass. +Here we declare that the + BasicAliasAnalysis +pass is the default implementation for the interface.

    + +
    + + + + + +
    +

    The Statistic +class is designed to be an easy way to expose various success +metrics from passes. These statistics are printed at the end of a +run, when the -stats command line option is enabled on the command +line. See the Statistics section in the Programmer's Manual for details. + +

    + + + + + + +
    + +

    The PassManager +class +takes a list of passes, ensures their prerequisites +are set up correctly, and then schedules passes to run efficiently. All of the +LLVM tools that run passes use the PassManager for execution of these +passes.

    + +

    The PassManager does two main things to try to reduce the execution +time of a series of passes:

    + +
      +
    1. Share analysis results - The PassManager attempts to avoid +recomputing analysis results as much as possible. This means keeping track of +which analyses are available already, which analyses get invalidated, and which +analyses are needed to be run for a pass. An important part of work is that the +PassManager tracks the exact lifetime of all analysis results, allowing +it to free memory allocated to holding analysis +results as soon as they are no longer needed.
    2. + +
    3. Pipeline the execution of passes on the program - The +PassManager attempts to get better cache and memory usage behavior out +of a series of passes by pipelining the passes together. This means that, given +a series of consequtive FunctionPass's, it +will execute all of the FunctionPass's on +the first function, then all of the FunctionPasses on the second function, +etc... until the entire program has been run through the passes. + +

      This improves the cache behavior of the compiler, because it is only touching +the LLVM program representation for a single function at a time, instead of +traversing the entire program. It reduces the memory consumption of compiler, +because, for example, only one DominatorSet +needs to be calculated at a time. This also makes it possible to implement +some interesting enhancements in the future.

    4. + +
    + +

    The effectiveness of the PassManager is influenced directly by how +much information it has about the behaviors of the passes it is scheduling. For +example, the "preserved" set is intentionally conservative in the face of an +unimplemented getAnalysisUsage method. +Not implementing when it should be implemented will have the effect of not +allowing any analysis results to live across the execution of your pass.

    + +

    The PassManager class exposes a --debug-pass command line +options that is useful for debugging pass execution, seeing how things work, and +diagnosing when you should be preserving more analyses than you currently are +(To get information about all of the variants of the --debug-pass +option, just type 'opt --help-hidden').

    + +

    By using the --debug-pass=Structure option, for example, we can see +how our Hello World pass interacts with other passes. +Lets try it out with the gcse and licm passes:

    + +
    +$ opt -load ../../../Debug/lib/Hello.so -gcse -licm --debug-pass=Structure < hello.bc > /dev/null
    +Module Pass Manager
    +  Function Pass Manager
    +    Dominator Set Construction
    +    Immediate Dominators Construction
    +    Global Common Subexpression Elimination
    +--  Immediate Dominators Construction
    +--  Global Common Subexpression Elimination
    +    Natural Loop Construction
    +    Loop Invariant Code Motion
    +--  Natural Loop Construction
    +--  Loop Invariant Code Motion
    +    Module Verifier
    +--  Dominator Set Construction
    +--  Module Verifier
    +  Bitcode Writer
    +--Bitcode Writer
    +
    + +

    This output shows us when passes are constructed and when the analysis +results are known to be dead (prefixed with '--'). Here we see that +GCSE uses dominator and immediate dominator information to do its job. The LICM +pass uses natural loop information, which uses dominator sets, but not immediate +dominators. Because immediate dominators are no longer useful after the GCSE +pass, it is immediately destroyed. The dominator sets are then reused to +compute natural loop information, which is then used by the LICM pass.

    + +

    After the LICM pass, the module verifier runs (which is automatically added +by the 'opt' tool), which uses the dominator set to check that the +resultant LLVM code is well formed. After it finishes, the dominator set +information is destroyed, after being computed once, and shared by three +passes.

    + +

    Lets see how this changes when we run the Hello +World pass in between the two passes:

    + +
    +$ opt -load ../../../Debug/lib/Hello.so -gcse -hello -licm --debug-pass=Structure < hello.bc > /dev/null
    +Module Pass Manager
    +  Function Pass Manager
    +    Dominator Set Construction
    +    Immediate Dominators Construction
    +    Global Common Subexpression Elimination
    +--  Dominator Set Construction
    +--  Immediate Dominators Construction
    +--  Global Common Subexpression Elimination
    +    Hello World Pass
    +--  Hello World Pass
    +    Dominator Set Construction
    +    Natural Loop Construction
    +    Loop Invariant Code Motion
    +--  Natural Loop Construction
    +--  Loop Invariant Code Motion
    +    Module Verifier
    +--  Dominator Set Construction
    +--  Module Verifier
    +  Bitcode Writer
    +--Bitcode Writer
    +Hello: __main
    +Hello: puts
    +Hello: main
    +
    + +

    Here we see that the Hello World pass has killed the +Dominator Set pass, even though it doesn't modify the code at all! To fix this, +we need to add the following getAnalysisUsage method to our pass:

    + +
    +    // We don't modify the program, so we preserve all analyses
    +    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
    +      AU.setPreservesAll();
    +    }
    +
    + +

    Now when we run our pass, we get this output:

    + +
    +$ opt -load ../../../Debug/lib/Hello.so -gcse -hello -licm --debug-pass=Structure < hello.bc > /dev/null
    +Pass Arguments:  -gcse -hello -licm
    +Module Pass Manager
    +  Function Pass Manager
    +    Dominator Set Construction
    +    Immediate Dominators Construction
    +    Global Common Subexpression Elimination
    +--  Immediate Dominators Construction
    +--  Global Common Subexpression Elimination
    +    Hello World Pass
    +--  Hello World Pass
    +    Natural Loop Construction
    +    Loop Invariant Code Motion
    +--  Loop Invariant Code Motion
    +--  Natural Loop Construction
    +    Module Verifier
    +--  Dominator Set Construction
    +--  Module Verifier
    +  Bitcode Writer
    +--Bitcode Writer
    +Hello: __main
    +Hello: puts
    +Hello: main
    +
    + +

    Which shows that we don't accidentally invalidate dominator information +anymore, and therefore do not have to compute it twice.

    + +
    + + + + +
    + +
    +  virtual void releaseMemory();
    +
    + +

    The PassManager automatically determines when to compute analysis +results, and how long to keep them around for. Because the lifetime of the pass +object itself is effectively the entire duration of the compilation process, we +need some way to free analysis results when they are no longer useful. The +releaseMemory virtual method is the way to do this.

    + +

    If you are writing an analysis or any other pass that retains a significant +amount of state (for use by another pass which "requires" your pass and uses the +getAnalysis method) you should implement +releaseMemory to, well, release the memory allocated to maintain this +internal state. This method is called after the run* method for the +class, before the next call of run* in your pass.

    + +
    + + + + + +
    + +

    Size matters when constructing production quality tools using llvm, +both for the purposes of distribution, and for regulating the resident code size +when running on the target system. Therefore, it becomes desirable to +selectively use some passes, while omitting others and maintain the flexibility +to change configurations later on. You want to be able to do all this, and, +provide feedback to the user. This is where pass registration comes into +play.

    + +

    The fundamental mechanisms for pass registration are the +MachinePassRegistry class and subclasses of +MachinePassRegistryNode.

    + +

    An instance of MachinePassRegistry is used to maintain a list of +MachinePassRegistryNode objects. This instance maintains the list and +communicates additions and deletions to the command line interface.

    + +

    An instance of MachinePassRegistryNode subclass is used to maintain +information provided about a particular pass. This information includes the +command line name, the command help string and the address of the function used +to create an instance of the pass. A global static constructor of one of these +instances registers with a corresponding MachinePassRegistry, +the static destructor unregisters. Thus a pass that is statically linked +in the tool will be registered at start up. A dynamically loaded pass will +register on load and unregister at unload.

    + +
    + + + + +
    + +

    There are predefined registries to track instruction scheduling +(RegisterScheduler) and register allocation (RegisterRegAlloc) +machine passes. Here we will describe how to register a register +allocator machine pass.

    + +

    Implement your register allocator machine pass. In your register allocator +.cpp file add the following include;

    + +
    +  #include "llvm/CodeGen/RegAllocRegistry.h"
    +
    + +

    Also in your register allocator .cpp file, define a creator function in the +form;

    + +
    +  FunctionPass *createMyRegisterAllocator() {
    +    return new MyRegisterAllocator();
    +  }
    +
    + +

    Note that the signature of this function should match the type of +RegisterRegAlloc::FunctionPassCtor. In the same file add the +"installing" declaration, in the form;

    + +
    +  static RegisterRegAlloc myRegAlloc("myregalloc",
    +    "  my register allocator help string",
    +    createMyRegisterAllocator);
    +
    + +

    Note the two spaces prior to the help string produces a tidy result on the +--help query.

    + +
    +$ llc --help
    +  ...
    +  -regalloc                    - Register allocator to use: (default = linearscan)
    +    =linearscan                -   linear scan register allocator
    +    =local                     -   local register allocator
    +    =simple                    -   simple register allocator
    +    =myregalloc                -   my register allocator help string
    +  ...
    +
    + +

    And that's it. The user is now free to use -regalloc=myregalloc as +an option. Registering instruction schedulers is similar except use the +RegisterScheduler class. Note that the +RegisterScheduler::FunctionPassCtor is significantly different from +RegisterRegAlloc::FunctionPassCtor.

    + +

    To force the load/linking of your register allocator into the llc/lli tools, +add your creator function's global declaration to "Passes.h" and add a "pseudo" +call line to llvm/Codegen/LinkAllCodegenComponents.h.

    + +
    + + + + + +
    + +

    The easiest way to get started is to clone one of the existing registries; we +recommend llvm/CodeGen/RegAllocRegistry.h. The key things to modify +are the class name and the FunctionPassCtor type.

    + +

    Then you need to declare the registry. Example: if your pass registry is +RegisterMyPasses then define;

    + +
    +MachinePassRegistry RegisterMyPasses::Registry;
    +
    + +

    And finally, declare the command line option for your passes. Example:

    + +
    +  cl::opt<RegisterMyPasses::FunctionPassCtor, false,
    +          RegisterPassParser<RegisterMyPasses> >
    +  MyPassOpt("mypass",
    +            cl::init(&createDefaultMyPass),
    +            cl::desc("my pass option help")); 
    +
    + +

    Here the command option is "mypass", with createDefaultMyPass as the default +creator.

    + +
    + + + + + +
    + +

    Unfortunately, using GDB with dynamically loaded passes is not as easy as it +should be. First of all, you can't set a breakpoint in a shared object that has +not been loaded yet, and second of all there are problems with inlined functions +in shared objects. Here are some suggestions to debugging your pass with +GDB.

    + +

    For sake of discussion, I'm going to assume that you are debugging a +transformation invoked by opt, although nothing described here depends +on that.

    + +
    + + + + +
    + +

    First thing you do is start gdb on the opt process:

    + +
    +$ gdb opt
    +GNU gdb 5.0
    +Copyright 2000 Free Software Foundation, Inc.
    +GDB is free software, covered by the GNU General Public License, and you are
    +welcome to change it and/or distribute copies of it under certain conditions.
    +Type "show copying" to see the conditions.
    +There is absolutely no warranty for GDB.  Type "show warranty" for details.
    +This GDB was configured as "sparc-sun-solaris2.6"...
    +(gdb)
    +
    + +

    Note that opt has a lot of debugging information in it, so it takes +time to load. Be patient. Since we cannot set a breakpoint in our pass yet +(the shared object isn't loaded until runtime), we must execute the process, and +have it stop before it invokes our pass, but after it has loaded the shared +object. The most foolproof way of doing this is to set a breakpoint in +PassManager::run and then run the process with the arguments you +want:

    + +
    +(gdb) break llvm::PassManager::run
    +Breakpoint 1 at 0x2413bc: file Pass.cpp, line 70.
    +(gdb) run test.bc -load $(LLVMTOP)/llvm/Debug/lib/[libname].so -[passoption]
    +Starting program: opt test.bc -load $(LLVMTOP)/llvm/Debug/lib/[libname].so -[passoption]
    +Breakpoint 1, PassManager::run (this=0xffbef174, M=@0x70b298) at Pass.cpp:70
    +70      bool PassManager::run(Module &M) { return PM->run(M); }
    +(gdb)
    +
    + +

    Once the opt stops in the PassManager::run method you are +now free to set breakpoints in your pass so that you can trace through execution +or do other standard debugging stuff.

    + +
    + + + + +
    + +

    Once you have the basics down, there are a couple of problems that GDB has, +some with solutions, some without.

    + +
      +
    • Inline functions have bogus stack information. In general, GDB does a +pretty good job getting stack traces and stepping through inline functions. +When a pass is dynamically loaded however, it somehow completely loses this +capability. The only solution I know of is to de-inline a function (move it +from the body of a class to a .cpp file).
    • + +
    • Restarting the program breaks breakpoints. After following the information +above, you have succeeded in getting some breakpoints planted in your pass. Nex +thing you know, you restart the program (i.e., you type 'run' again), +and you start getting errors about breakpoints being unsettable. The only way I +have found to "fix" this problem is to delete the breakpoints that are +already set in your pass, run the program, and re-set the breakpoints once +execution stops in PassManager::run.
    • + +
    + +

    Hopefully these tips will help with common case debugging situations. If +you'd like to contribute some tips of your own, just contact Chris.

    + +
    + + + + + +
    + +

    Although the LLVM Pass Infrastructure is very capable as it stands, and does +some nifty stuff, there are things we'd like to add in the future. Here is +where we are going:

    + +
    + + + + +
    + +

    Multiple CPU machines are becoming more common and compilation can never be +fast enough: obviously we should allow for a multithreaded compiler. Because of +the semantics defined for passes above (specifically they cannot maintain state +across invocations of their run* methods), a nice clean way to +implement a multithreaded compiler would be for the PassManager class +to create multiple instances of each pass object, and allow the separate +instances to be hacking on different parts of the program at the same time.

    + +

    This implementation would prevent each of the passes from having to implement +multithreaded constructs, requiring only the LLVM core to have locking in a few +places (for global resources). Although this is a simple extension, we simply +haven't had time (or multiprocessor machines, thus a reason) to implement this. +Despite that, we have kept the LLVM passes SMP ready, and you should too.

    + +
    + + +
    +
    + Valid CSS + Valid HTML 4.01 + + Chris Lattner
    + The LLVM Compiler Infrastructure
    + Last modified: $Date$ +
    + + + diff --git a/libclamav/c++/llvm/docs/doxygen.cfg.in b/libclamav/c++/llvm/docs/doxygen.cfg.in new file mode 100644 index 000000000..45b8f42e5 --- /dev/null +++ b/libclamav/c++/llvm/docs/doxygen.cfg.in @@ -0,0 +1,1419 @@ +# Doxyfile 1.5.6 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project +# +# All text after a hash (#) is considered a comment and will be ignored +# The format is: +# TAG = value [value, ...] +# For lists items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (" ") + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the config file +# that follow. The default is UTF-8 which is also the encoding used for all +# text before the first occurrence of this tag. Doxygen uses libiconv (or the +# iconv built into libc) for the transcoding. See +# http://www.gnu.org/software/libiconv for the list of possible encodings. + +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded +# by quotes) that should identify the project. + +PROJECT_NAME = LLVM + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. +# This could be handy for archiving the generated documentation or +# if some version control system is used. + +PROJECT_NUMBER = @PACKAGE_VERSION@ + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) +# base path where the generated documentation will be put. +# If a relative path is entered, it will be relative to the location +# where doxygen was started. If left blank the current directory will be used. + +OUTPUT_DIRECTORY = @abs_top_builddir@/docs/doxygen + +# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create +# 4096 sub-directories (in 2 levels) under the output directory of each output +# format and will distribute the generated files over these directories. +# Enabling this option can be useful when feeding doxygen a huge amount of +# source files, where putting all generated files in the same directory would +# otherwise cause performance problems for the file system. + +CREATE_SUBDIRS = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# The default language is English, other supported languages are: +# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, +# Croatian, Czech, Danish, Dutch, Farsi, Finnish, French, German, Greek, +# Hungarian, Italian, Japanese, Japanese-en (Japanese with English messages), +# Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, Polish, +# Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish, Swedish, +# and Ukrainian. + +OUTPUT_LANGUAGE = English + +# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will +# include brief member descriptions after the members that are listed in +# the file and class documentation (similar to JavaDoc). +# Set to NO to disable this. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend +# the brief description of a member or function before the detailed description. +# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator +# that is used to form the text in various listings. Each string +# in this list, if found as the leading text of the brief description, will be +# stripped from the text and the result after processing the whole list, is +# used as the annotated text. Otherwise, the brief description is used as-is. +# If left blank, the following values are used ("$name" is automatically +# replaced with the name of the entity): "The $name class" "The $name widget" +# "The $name file" "is" "provides" "specifies" "contains" +# "represents" "a" "an" "the" + +ABBREVIATE_BRIEF = + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# Doxygen will generate a detailed section even if there is only a brief +# description. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full +# path before files name in the file list and in the header files. If set +# to NO the shortest path that makes the file name unique will be used. + +FULL_PATH_NAMES = NO + +# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag +# can be used to strip a user-defined part of the path. Stripping is +# only done if one of the specified strings matches the left-hand part of +# the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the +# path to strip. + +STRIP_FROM_PATH = ../.. + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of +# the path mentioned in the documentation of a class, which tells +# the reader which header file to include in order to use a class. +# If left blank only the name of the header file containing the class +# definition is used. Otherwise one should specify the include paths that +# are normally passed to the compiler using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter +# (but less readable) file names. This can be useful is your file systems +# doesn't support long names like on DOS, Mac, or CD-ROM. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen +# will interpret the first line (until the first dot) of a JavaDoc-style +# comment as the brief description. If set to NO, the JavaDoc +# comments will behave just like regular Qt-style comments +# (thus requiring an explicit @brief command for a brief description.) + +JAVADOC_AUTOBRIEF = NO + +# If the QT_AUTOBRIEF tag is set to YES then Doxygen will +# interpret the first line (until the first dot) of a Qt-style +# comment as the brief description. If set to NO, the comments +# will behave just like regular Qt-style comments (thus requiring +# an explicit \brief command for a brief description.) + +QT_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen +# treat a multi-line C++ special comment block (i.e. a block of //! or /// +# comments) as a brief description. This used to be the default behaviour. +# The new default is to treat a multi-line C++ comment block as a detailed +# description. Set this tag to YES if you prefer the old behaviour instead. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the DETAILS_AT_TOP tag is set to YES then Doxygen +# will output the detailed description near the top, like JavaDoc. +# If set to NO, the detailed description appears after the member +# documentation. + +DETAILS_AT_TOP = NO + +# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented +# member inherits the documentation from any documented member that it +# re-implements. + +INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce +# a new page for each member. If set to NO, the documentation of a member will +# be part of the file/class/namespace that contains it. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. +# Doxygen uses this value to replace tabs by spaces in code fragments. + +TAB_SIZE = 2 + +# This tag can be used to specify a number of aliases that acts +# as commands in the documentation. An alias has the form "name=value". +# For example adding "sideeffect=\par Side Effects:\n" will allow you to +# put the command \sideeffect (or @sideeffect) in the documentation, which +# will result in a user-defined paragraph with heading "Side Effects:". +# You can put \n's in the value part of an alias to insert newlines. + +ALIASES = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C +# sources only. Doxygen will then generate output that is more tailored for C. +# For instance, some of the names that are used will be different. The list +# of all members will be omitted, etc. + +OPTIMIZE_OUTPUT_FOR_C = NO + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java +# sources only. Doxygen will then generate output that is more tailored for +# Java. For instance, namespaces will be presented as packages, qualified +# scopes will look different, etc. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran +# sources only. Doxygen will then generate output that is more tailored for +# Fortran. + +OPTIMIZE_FOR_FORTRAN = NO + +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL +# sources. Doxygen will then generate output that is tailored for +# VHDL. + +OPTIMIZE_OUTPUT_VHDL = NO + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want +# to include (a tag file for) the STL sources as input, then you should +# set this tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. +# func(std::string) {}). This also make the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. + +BUILTIN_STL_SUPPORT = NO + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. + +CPP_CLI_SUPPORT = NO + +# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. +# Doxygen will parse them like normal C++ but will assume all classes use public +# instead of private inheritance when no explicit protection keyword is present. + +SIP_SUPPORT = NO + +# For Microsoft's IDL there are propget and propput attributes to indicate getter +# and setter methods for a property. Setting this option to YES (the default) +# will make doxygen to replace the get and set methods by a property in the +# documentation. This will only work if the methods are indeed getting or +# setting a simple type. If this is not the case, or you want to show the +# methods anyway, you should set this option to NO. + +IDL_PROPERTY_SUPPORT = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. + +DISTRIBUTE_GROUP_DOC = NO + +# Set the SUBGROUPING tag to YES (the default) to allow class member groups of +# the same type (for instance a group of public functions) to be put as a +# subgroup of that type (e.g. under the Public Functions section). Set it to +# NO to prevent subgrouping. Alternatively, this can be done per class using +# the \nosubgrouping command. + +SUBGROUPING = YES + +# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum +# is documented as struct, union, or enum with the name of the typedef. So +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct +# with name TypeT. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named TypeS. This can typically +# be useful for C code in case the coding convention dictates that all compound +# types are typedef'ed and only the typedef is referenced, never the tag name. + +TYPEDEF_HIDES_STRUCT = NO + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. +# Private class members and static file members will be hidden unless +# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES + +EXTRACT_ALL = YES + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class +# will be included in the documentation. + +EXTRACT_PRIVATE = NO + +# If the EXTRACT_STATIC tag is set to YES all static members of a file +# will be included in the documentation. + +EXTRACT_STATIC = YES + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) +# defined locally in source files will be included in the documentation. +# If set to NO only classes defined in header files are included. + +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. When set to YES local +# methods, which are defined in the implementation section but not in +# the interface are included in the documentation. +# If set to NO (the default) only methods in the interface are included. + +EXTRACT_LOCAL_METHODS = NO + +# If this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base +# name of the file that contains the anonymous namespace. By default +# anonymous namespace are hidden. + +EXTRACT_ANON_NSPACES = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all +# undocumented members of documented classes, files or namespaces. +# If set to NO (the default) these members will be included in the +# various overviews, but no documentation section is generated. +# This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. +# If set to NO (the default) these classes will be included in the various +# overviews. This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all +# friend (class|struct|union) declarations. +# If set to NO (the default) these declarations will be included in the +# documentation. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any +# documentation blocks found inside the body of a function. +# If set to NO (the default) these blocks will be appended to the +# function's detailed documentation block. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation +# that is typed after a \internal command is included. If the tag is set +# to NO (the default) then the documentation will be excluded. +# Set it to YES to include the internal documentation. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate +# file names in lower-case letters. If set to YES upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# and Mac users are advised to set this option to NO. + +CASE_SENSE_NAMES = YES + +# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen +# will show members with their full class and namespace scopes in the +# documentation. If set to YES the scope will be hidden. + +HIDE_SCOPE_NAMES = NO + +# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen +# will put a list of the files that are included by a file in the documentation +# of that file. + +SHOW_INCLUDE_FILES = YES + +# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] +# is inserted in the documentation for inline members. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen +# will sort the (detailed) documentation of file and class members +# alphabetically by member name. If set to NO the members will appear in +# declaration order. + +SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the +# brief documentation of file, namespace and class members alphabetically +# by member name. If set to NO (the default) the members will appear in +# declaration order. + +SORT_BRIEF_DOCS = NO + +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the +# hierarchy of group names into alphabetical order. If set to NO (the default) +# the group names will appear in their defined order. + +SORT_GROUP_NAMES = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be +# sorted by fully-qualified names, including namespaces. If set to +# NO (the default), the class list will be sorted only by class name, +# not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the +# alphabetical list. + +SORT_BY_SCOPE_NAME = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or +# disable (NO) the todo list. This list is created by putting \todo +# commands in the documentation. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or +# disable (NO) the test list. This list is created by putting \test +# commands in the documentation. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable (YES) or +# disable (NO) the bug list. This list is created by putting \bug +# commands in the documentation. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or +# disable (NO) the deprecated list. This list is created by putting +# \deprecated commands in the documentation. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional +# documentation sections, marked by \if sectionname ... \endif. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines +# the initial value of a variable or define consists of for it to appear in +# the documentation. If the initializer consists of more lines than specified +# here it will be hidden. Use a value of 0 to hide initializers completely. +# The appearance of the initializer of individual variables and defines in the +# documentation can be controlled using \showinitializer or \hideinitializer +# command in the documentation regardless of this setting. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated +# at the bottom of the documentation of classes and structs. If set to YES the +# list will mention the files that were used to generate the documentation. + +SHOW_USED_FILES = YES + +# If the sources in your project are distributed over multiple directories +# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy +# in the documentation. The default is NO. + +SHOW_DIRECTORIES = YES + +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. +# This will remove the Files entry from the Quick Index and from the +# Folder Tree View (if specified). The default is YES. + +SHOW_FILES = YES + +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the +# Namespaces page. This will remove the Namespaces entry from the Quick Index +# and from the Folder Tree View (if specified). The default is YES. + +SHOW_NAMESPACES = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from +# the version control system). Doxygen will invoke the program by executing (via +# popen()) the command , where is the value of +# the FILE_VERSION_FILTER tag, and is the name of an input file +# provided by doxygen. Whatever the program writes to standard output +# is used as the file version. See the manual for examples. + +FILE_VERSION_FILTER = + +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated +# by doxygen. Possible values are YES and NO. If left blank NO is used. + +QUIET = NO + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated by doxygen. Possible values are YES and NO. If left blank +# NO is used. + +WARNINGS = NO + +# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings +# for undocumented members. If EXTRACT_ALL is set to YES then this flag will +# automatically be disabled. + +WARN_IF_UNDOCUMENTED = NO + +# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some +# parameters in a documented function, or documenting parameters that +# don't exist or using markup commands wrongly. + +WARN_IF_DOC_ERROR = YES + +# This WARN_NO_PARAMDOC option can be abled to get warnings for +# functions that are documented, but have no documentation for their parameters +# or return value. If set to NO (the default) doxygen will only warn about +# wrong or incomplete parameter documentation, but not about the absence of +# documentation. + +WARN_NO_PARAMDOC = NO + +# The WARN_FORMAT tag determines the format of the warning messages that +# doxygen can produce. The string should contain the $file, $line, and $text +# tags, which will be replaced by the file and line number from which the +# warning originated and the warning text. Optionally the format may contain +# $version, which will be replaced by the version of the file (if it could +# be obtained via FILE_VERSION_FILTER) + +WARN_FORMAT = + +# The WARN_LOGFILE tag can be used to specify a file to which warning +# and error messages should be written. If left blank the output is written +# to stderr. + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag can be used to specify the files and/or directories that contain +# documented source files. You may enter file names like "myfile.cpp" or +# directories like "/usr/src/myproject". Separate the files or directories +# with spaces. + +INPUT = @abs_top_srcdir@/include \ + @abs_top_srcdir@/lib \ + @abs_top_srcdir@/docs/doxygen.intro + +# This tag can be used to specify the character encoding of the source files +# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is +# also the default input encoding. Doxygen uses libiconv (or the iconv built +# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for +# the list of possible encodings. + +INPUT_ENCODING = UTF-8 + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank the following patterns are tested: +# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx +# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90 + +FILE_PATTERNS = + +# The RECURSIVE tag can be used to turn specify whether or not subdirectories +# should be searched for input files as well. Possible values are YES and NO. +# If left blank NO is used. + +RECURSIVE = YES + +# The EXCLUDE tag can be used to specify files and/or directories that should +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. + +EXCLUDE = + +# The EXCLUDE_SYMLINKS tag can be used select whether or not files or +# directories that are symbolic links (a Unix filesystem feature) are excluded +# from the input. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. Note that the wildcards are matched +# against the file with absolute path, so to exclude all test directories +# for example use the pattern */test/* + +EXCLUDE_PATTERNS = + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, +# AClass::ANamespace, ANamespace::*Test + +EXCLUDE_SYMBOLS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or +# directories that contain example code fragments that are included (see +# the \include command). + +EXAMPLE_PATH = @abs_top_srcdir@/examples + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank all files are included. + +EXAMPLE_PATTERNS = + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude +# commands irrespective of the value of the RECURSIVE tag. +# Possible values are YES and NO. If left blank NO is used. + +EXAMPLE_RECURSIVE = YES + +# The IMAGE_PATH tag can be used to specify one or more files or +# directories that contain image that are included in the documentation (see +# the \image command). + +IMAGE_PATH = @abs_top_srcdir@/docs/img + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command , where +# is the value of the INPUT_FILTER tag, and is the name of an +# input file. Doxygen will then use the output that the filter program writes +# to standard output. If FILTER_PATTERNS is specified, this tag will be +# ignored. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. The filters are a list of the form: +# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further +# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER +# is applied to all files. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will be used to filter the input files when producing source +# files to browse (i.e. when SOURCE_BROWSER is set to YES). + +FILTER_SOURCE_FILES = NO + +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will +# be generated. Documented entities will be cross-referenced with these sources. +# Note: To get rid of all source code in the generated output, make sure also +# VERBATIM_HEADERS is set to NO. + +SOURCE_BROWSER = YES + +# Setting the INLINE_SOURCES tag to YES will include the body +# of functions and classes directly in the documentation. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct +# doxygen to hide any special comment blocks from generated source code +# fragments. Normal C and C++ comments will always remain visible. + +STRIP_CODE_COMMENTS = NO + +# If the REFERENCED_BY_RELATION tag is set to YES +# then for each documented function all documented +# functions referencing it will be listed. + +REFERENCED_BY_RELATION = YES + +# If the REFERENCES_RELATION tag is set to YES +# then for each documented function all documented entities +# called/used by that function will be listed. + +REFERENCES_RELATION = YES + +# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) +# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from +# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will +# link to the source code. Otherwise they will link to the documentstion. + +REFERENCES_LINK_SOURCE = YES + +# If the USE_HTAGS tag is set to YES then the references to source code +# will point to the HTML generated by the htags(1) tool instead of doxygen +# built-in source browser. The htags tool is part of GNU's global source +# tagging system (see http://www.gnu.org/software/global/global.html). You +# will need version 4.8.6 or higher. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen +# will generate a verbatim copy of the header file for each class for +# which an include is specified. Set to NO to disable this. + +VERBATIM_HEADERS = YES + +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index +# of all compounds will be generated. Enable this if the project +# contains a lot of classes, structs, unions or interfaces. + +ALPHABETICAL_INDEX = YES + +# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then +# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns +# in which this list will be split (can be a number in the range [1..20]) + +COLS_IN_ALPHA_INDEX = 4 + +# In case all classes in a project start with a common prefix, all +# classes will be put under the same header in the alphabetical index. +# The IGNORE_PREFIX tag can be used to specify one or more prefixes that +# should be ignored while generating the index headers. + +IGNORE_PREFIX = llvm:: + +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES (the default) Doxygen will +# generate HTML output. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `html' will be used as the default path. + +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for +# each generated HTML page (for example: .htm,.php,.asp). If it is left blank +# doxygen will generate files with .html extension. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a personal HTML header for +# each generated HTML page. If it is left blank doxygen will generate a +# standard header. + +HTML_HEADER = @abs_top_srcdir@/docs/doxygen.header + +# The HTML_FOOTER tag can be used to specify a personal HTML footer for +# each generated HTML page. If it is left blank doxygen will generate a +# standard footer. + +HTML_FOOTER = @abs_top_srcdir@/docs/doxygen.footer + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading +# style sheet that is used by each HTML page. It can be used to +# fine-tune the look of the HTML output. If the tag is left blank doxygen +# will generate a default style sheet. Note that doxygen will try to copy +# the style sheet file to the HTML output directory, so don't put your own +# stylesheet in the HTML output directory as well, or it will be erased! + +HTML_STYLESHEET = @abs_top_srcdir@/docs/doxygen.css + +# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, +# files or namespaces will be aligned in HTML using tables. If set to +# NO a bullet list will be used. + +HTML_ALIGN_MEMBERS = YES + +# If the GENERATE_HTMLHELP tag is set to YES, additional index files +# will be generated that can be used as input for tools like the +# Microsoft HTML help workshop to generate a compiled HTML help file (.chm) +# of the generated HTML documentation. + +GENERATE_HTMLHELP = NO + +# If the GENERATE_DOCSET tag is set to YES, additional index files +# will be generated that can be used as input for Apple's Xcode 3 +# integrated development environment, introduced with OSX 10.5 (Leopard). +# To create a documentation set, doxygen will generate a Makefile in the +# HTML output directory. Running make will produce the docset in that +# directory and running "make install" will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find +# it at startup. + +GENERATE_DOCSET = NO + +# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the +# feed. A documentation feed provides an umbrella under which multiple +# documentation sets from a single provider (such as a company or product suite) +# can be grouped. + +DOCSET_FEEDNAME = "Doxygen generated docs" + +# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that +# should uniquely identify the documentation set bundle. This should be a +# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen +# will append .docset to the name. + +DOCSET_BUNDLE_ID = org.doxygen.Project + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. For this to work a browser that supports +# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox +# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). + +HTML_DYNAMIC_SECTIONS = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can +# be used to specify the file name of the resulting .chm file. You +# can add a path in front of the file if the result should not be +# written to the html output directory. + +CHM_FILE = + +# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can +# be used to specify the location (absolute path including file name) of +# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run +# the HTML help compiler on the generated index.hhp. + +HHC_LOCATION = + +# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag +# controls if a separate .chi index file is generated (YES) or that +# it should be included in the master .chm file (NO). + +GENERATE_CHI = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING +# is used to encode HtmlHelp index (hhk), content (hhc) and project file +# content. + +CHM_INDEX_ENCODING = + +# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag +# controls whether a binary table of contents is generated (YES) or a +# normal table of contents (NO) in the .chm file. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members +# to the contents of the HTML help documentation and to the tree view. + +TOC_EXPAND = NO + +# The DISABLE_INDEX tag can be used to turn on/off the condensed index at +# top of each HTML page. The value NO (the default) enables the index and +# the value YES disables it. + +DISABLE_INDEX = NO + +# This tag can be used to set the number of enum values (range [1..20]) +# that doxygen will group on one line in the generated HTML documentation. + +ENUM_VALUES_PER_LINE = 4 + +# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index +# structure should be generated to display hierarchical information. +# If the tag value is set to FRAME, a side panel will be generated +# containing a tree-like index structure (just like the one that +# is generated for HTML Help). For this to work a browser that supports +# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, +# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are +# probably better off using the HTML help feature. Other possible values +# for this tag are: HIERARCHIES, which will generate the Groups, Directories, +# and Class Hiererachy pages using a tree view instead of an ordered list; +# ALL, which combines the behavior of FRAME and HIERARCHIES; and NONE, which +# disables this behavior completely. For backwards compatibility with previous +# releases of Doxygen, the values YES and NO are equivalent to FRAME and NONE +# respectively. + +GENERATE_TREEVIEW = NO + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be +# used to set the initial width (in pixels) of the frame in which the tree +# is shown. + +TREEVIEW_WIDTH = 250 + +# Use this tag to change the font size of Latex formulas included +# as images in the HTML documentation. The default is 10. Note that +# when you change the font size after a successful doxygen run you need +# to manually remove any form_*.png images from the HTML output directory +# to force them to be regenerated. + +FORMULA_FONTSIZE = 10 + +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- + +# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will +# generate Latex output. + +GENERATE_LATEX = NO + +# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `latex' will be used as the default path. + +LATEX_OUTPUT = + +# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be +# invoked. If left blank `latex' will be used as the default command name. + +LATEX_CMD_NAME = latex + +# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to +# generate index for LaTeX. If left blank `makeindex' will be used as the +# default command name. + +MAKEINDEX_CMD_NAME = makeindex + +# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact +# LaTeX documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_LATEX = NO + +# The PAPER_TYPE tag can be used to set the paper type that is used +# by the printer. Possible values are: a4, a4wide, letter, legal and +# executive. If left blank a4wide will be used. + +PAPER_TYPE = letter + +# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX +# packages that should be included in the LaTeX output. + +EXTRA_PACKAGES = + +# The LATEX_HEADER tag can be used to specify a personal LaTeX header for +# the generated latex document. The header should contain everything until +# the first chapter. If it is left blank doxygen will generate a +# standard header. Notice: only use this tag if you know what you are doing! + +LATEX_HEADER = + +# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated +# is prepared for conversion to pdf (using ps2pdf). The pdf file will +# contain links (just like the HTML output) instead of page references +# This makes the output suitable for online browsing using a pdf viewer. + +PDF_HYPERLINKS = NO + +# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of +# plain latex in the generated Makefile. Set this option to YES to get a +# higher quality PDF documentation. + +USE_PDFLATEX = NO + +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. +# command to the generated LaTeX files. This will instruct LaTeX to keep +# running if errors occur, instead of asking the user for help. +# This option is also used when generating formulas in HTML. + +LATEX_BATCHMODE = NO + +# If LATEX_HIDE_INDICES is set to YES then doxygen will not +# include the index chapters (such as File Index, Compound Index, etc.) +# in the output. + +LATEX_HIDE_INDICES = NO + +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- + +# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output +# The RTF output is optimized for Word 97 and may not look very pretty with +# other RTF readers or editors. + +GENERATE_RTF = NO + +# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `rtf' will be used as the default path. + +RTF_OUTPUT = + +# If the COMPACT_RTF tag is set to YES Doxygen generates more compact +# RTF documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_RTF = NO + +# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated +# will contain hyperlink fields. The RTF file will +# contain links (just like the HTML output) instead of page references. +# This makes the output suitable for online browsing using WORD or other +# programs which support those fields. +# Note: wordpad (write) and others do not support links. + +RTF_HYPERLINKS = NO + +# Load stylesheet definitions from file. Syntax is similar to doxygen's +# config file, i.e. a series of assignments. You only have to provide +# replacements, missing definitions are set to their default value. + +RTF_STYLESHEET_FILE = + +# Set optional variables used in the generation of an rtf document. +# Syntax is similar to doxygen's config file. + +RTF_EXTENSIONS_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- + +# If the GENERATE_MAN tag is set to YES (the default) Doxygen will +# generate man pages + +GENERATE_MAN = NO + +# The MAN_OUTPUT tag is used to specify where the man pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `man' will be used as the default path. + +MAN_OUTPUT = + +# The MAN_EXTENSION tag determines the extension that is added to +# the generated man pages (default is the subroutine's section .3) + +MAN_EXTENSION = + +# If the MAN_LINKS tag is set to YES and Doxygen generates man output, +# then it will generate one additional man file for each entity +# documented in the real man page(s). These additional files +# only source the real man page, but without them the man command +# would be unable to find the correct page. The default is NO. + +MAN_LINKS = NO + +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- + +# If the GENERATE_XML tag is set to YES Doxygen will +# generate an XML file that captures the structure of +# the code including all documentation. + +GENERATE_XML = NO + +# The XML_OUTPUT tag is used to specify where the XML pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `xml' will be used as the default path. + +XML_OUTPUT = xml + +# The XML_SCHEMA tag can be used to specify an XML schema, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_SCHEMA = + +# The XML_DTD tag can be used to specify an XML DTD, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_DTD = + +# If the XML_PROGRAMLISTING tag is set to YES Doxygen will +# dump the program listings (including syntax highlighting +# and cross-referencing information) to the XML output. Note that +# enabling this will significantly increase the size of the XML output. + +XML_PROGRAMLISTING = YES + +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- + +# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will +# generate an AutoGen Definitions (see autogen.sf.net) file +# that captures the structure of the code including all +# documentation. Note that this feature is still experimental +# and incomplete at the moment. + +GENERATE_AUTOGEN_DEF = NO + +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- + +# If the GENERATE_PERLMOD tag is set to YES Doxygen will +# generate a Perl module file that captures the structure of +# the code including all documentation. Note that this +# feature is still experimental and incomplete at the +# moment. + +GENERATE_PERLMOD = NO + +# If the PERLMOD_LATEX tag is set to YES Doxygen will generate +# the necessary Makefile rules, Perl scripts and LaTeX code to be able +# to generate PDF and DVI output from the Perl module output. + +PERLMOD_LATEX = NO + +# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be +# nicely formatted so it can be parsed by a human reader. This is useful +# if you want to understand what is going on. On the other hand, if this +# tag is set to NO the size of the Perl module output will be much smaller +# and Perl will parse it just the same. + +PERLMOD_PRETTY = YES + +# The names of the make variables in the generated doxyrules.make file +# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. +# This is useful so different doxyrules.make files included by the same +# Makefile don't overwrite each other's variables. + +PERLMOD_MAKEVAR_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- + +# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will +# evaluate all C-preprocessor directives found in the sources and include +# files. + +ENABLE_PREPROCESSING = YES + +# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro +# names in the source code. If set to NO (the default) only conditional +# compilation will be performed. Macro expansion can be done in a controlled +# way by setting EXPAND_ONLY_PREDEF to YES. + +MACRO_EXPANSION = NO + +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES +# then the macro expansion is limited to the macros specified with the +# PREDEFINED and EXPAND_AS_DEFINED tags. + +EXPAND_ONLY_PREDEF = NO + +# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files +# in the INCLUDE_PATH (see below) will be search if a #include is found. + +SEARCH_INCLUDES = YES + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by +# the preprocessor. + +INCLUDE_PATH = ../include + +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard +# patterns (like *.h and *.hpp) to filter out the header-files in the +# directories. If left blank, the patterns specified with FILE_PATTERNS will +# be used. + +INCLUDE_FILE_PATTERNS = + +# The PREDEFINED tag can be used to specify one or more macro names that +# are defined before the preprocessor is started (similar to the -D option of +# gcc). The argument of the tag is a list of macros of the form: name +# or name=definition (no spaces). If the definition and the = are +# omitted =1 is assumed. To prevent a macro definition from being +# undefined via #undef or recursively expanded use the := operator +# instead of the = operator. + +PREDEFINED = + +# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then +# this tag can be used to specify a list of macro names that should be expanded. +# The macro definition that is found in the sources will be used. +# Use the PREDEFINED tag if you want to use a different macro definition. + +EXPAND_AS_DEFINED = + +# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then +# doxygen's preprocessor will remove all function-like macros that are alone +# on a line, have an all uppercase name, and do not end with a semicolon. Such +# function macros are typically used for boiler-plate code, and will confuse +# the parser if not removed. + +SKIP_FUNCTION_MACROS = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- + +# The TAGFILES option can be used to specify one or more tagfiles. +# Optionally an initial location of the external documentation +# can be added for each tagfile. The format of a tag file without +# this location is as follows: +# TAGFILES = file1 file2 ... +# Adding location for the tag files is done as follows: +# TAGFILES = file1=loc1 "file2 = loc2" ... +# where "loc1" and "loc2" can be relative or absolute paths or +# URLs. If a location is present for each tag, the installdox tool +# does not have to be run to correct the links. +# Note that each tag file must have a unique name +# (where the name does NOT include the path) +# If a tag file is not located in the directory in which doxygen +# is run, you must also specify the path to the tagfile here. + +TAGFILES = + +# When a file name is specified after GENERATE_TAGFILE, doxygen will create +# a tag file that is based on the input files it reads. + +GENERATE_TAGFILE = + +# If the ALLEXTERNALS tag is set to YES all external classes will be listed +# in the class index. If set to NO only the inherited external classes +# will be listed. + +ALLEXTERNALS = YES + +# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed +# in the modules index. If set to NO, only the current project's groups will +# be listed. + +EXTERNAL_GROUPS = YES + +# The PERL_PATH should be the absolute path and name of the perl script +# interpreter (i.e. the result of `which perl'). + +PERL_PATH = + +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- + +# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will +# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base +# or super classes. Setting the tag to NO turns the diagrams off. Note that +# this option is superseded by the HAVE_DOT option below. This is only a +# fallback. It is recommended to install and use dot, since it yields more +# powerful graphs. + +CLASS_DIAGRAMS = YES + +# You can define message sequence charts within doxygen comments using the \msc +# command. Doxygen will then run the mscgen tool (see +# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the +# documentation. The MSCGEN_PATH tag allows you to specify the directory where +# the mscgen tool resides. If left empty the tool is assumed to be found in the +# default search path. + +MSCGEN_PATH = + +# If set to YES, the inheritance and collaboration graphs will hide +# inheritance and usage relations if the target is undocumented +# or is not a class. + +HIDE_UNDOC_RELATIONS = NO + +# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# available from the path. This tool is part of Graphviz, a graph visualization +# toolkit from AT&T and Lucent Bell Labs. The other options in this section +# have no effect if this option is set to NO (the default) + +HAVE_DOT = YES + +# By default doxygen will write a font called FreeSans.ttf to the output +# directory and reference it in all dot files that doxygen generates. This +# font does not include all possible unicode characters however, so when you need +# these (or just want a differently looking font) you can specify the font name +# using DOT_FONTNAME. You need need to make sure dot is able to find the font, +# which can be done by putting it in a standard location or by setting the +# DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory +# containing the font. + +DOT_FONTNAME = FreeSans + +# By default doxygen will tell dot to use the output directory to look for the +# FreeSans.ttf font (which doxygen will put there itself). If you specify a +# different font using DOT_FONTNAME you can set the path where dot +# can find it using this tag. + +DOT_FONTPATH = + +# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect inheritance relations. Setting this tag to YES will force the +# the CLASS_DIAGRAMS tag to NO. + +CLASS_GRAPH = YES + +# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect implementation dependencies (inheritance, containment, and +# class references variables) of the class with other documented classes. + +COLLABORATION_GRAPH = YES + +# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for groups, showing the direct groups dependencies + +GROUP_GRAPHS = YES + +# If the UML_LOOK tag is set to YES doxygen will generate inheritance and +# collaboration diagrams in a style similar to the OMG's Unified Modeling +# Language. + +UML_LOOK = NO + +# If set to YES, the inheritance and collaboration graphs will show the +# relations between templates and their instances. + +TEMPLATE_RELATIONS = YES + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT +# tags are set to YES then doxygen will generate a graph for each documented +# file showing the direct and indirect include dependencies of the file with +# other documented files. + +INCLUDE_GRAPH = YES + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and +# HAVE_DOT tags are set to YES then doxygen will generate a graph for each +# documented header file showing the documented files that directly or +# indirectly include this file. + +INCLUDED_BY_GRAPH = YES + +# If the CALL_GRAPH and HAVE_DOT options are set to YES then +# doxygen will generate a call dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable call graphs +# for selected functions only using the \callgraph command. + +CALL_GRAPH = NO + +# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then +# doxygen will generate a caller dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable caller +# graphs for selected functions only using the \callergraph command. + +CALLER_GRAPH = NO + +# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen +# will graphical hierarchy of all classes instead of a textual one. + +GRAPHICAL_HIERARCHY = YES + +# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES +# then doxygen will show the dependencies a directory has on other directories +# in a graphical way. The dependency relations are determined by the #include +# relations between the files in the directories. + +DIRECTORY_GRAPH = YES + +# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images +# generated by dot. Possible values are png, jpg, or gif +# If left blank png will be used. + +DOT_IMAGE_FORMAT = png + +# The tag DOT_PATH can be used to specify the path where the dot tool can be +# found. If left blank, it is assumed the dot tool can be found in the path. + +DOT_PATH = @DOT@ + +# The DOTFILE_DIRS tag can be used to specify one or more directories that +# contain dot files that are included in the documentation (see the +# \dotfile command). + +DOTFILE_DIRS = + +# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of +# nodes that will be shown in the graph. If the number of nodes in a graph +# becomes larger than this value, doxygen will truncate the graph, which is +# visualized by representing a node as a red box. Note that doxygen if the +# number of direct children of the root node in a graph is already larger than +# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note +# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. + +DOT_GRAPH_MAX_NODES = 50 + +# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the +# graphs generated by dot. A depth value of 3 means that only nodes reachable +# from the root by following a path via at most 3 edges will be shown. Nodes +# that lay further from the root node will be omitted. Note that setting this +# option to 1 or 2 may greatly reduce the computation time needed for large +# code bases. Also note that the size of a graph can be further restricted by +# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. + +MAX_DOT_GRAPH_DEPTH = 0 + +# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent +# background. This is enabled by default, which results in a transparent +# background. Warning: Depending on the platform used, enabling this option +# may lead to badly anti-aliased labels on the edges of a graph (i.e. they +# become hard to read). + +DOT_TRANSPARENT = YES + +# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output +# files in one run (i.e. multiple -o and -T options on the command line). This +# makes dot run faster, but since only newer versions of dot (>1.8.10) +# support this, this feature is disabled by default. + +DOT_MULTI_TARGETS = NO + +# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will +# generate a legend page explaining the meaning of the various boxes and +# arrows in the dot generated graphs. + +GENERATE_LEGEND = YES + +# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will +# remove the intermediate dot files that are used to generate +# the various graphs. + +DOT_CLEANUP = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to the search engine +#--------------------------------------------------------------------------- + +# The SEARCHENGINE tag specifies whether or not a search engine should be +# used. If set to NO the values of all tags below this one will be ignored. + +SEARCHENGINE = NO diff --git a/libclamav/c++/llvm/docs/doxygen.css b/libclamav/c++/llvm/docs/doxygen.css new file mode 100644 index 000000000..83b049b5f --- /dev/null +++ b/libclamav/c++/llvm/docs/doxygen.css @@ -0,0 +1,378 @@ +BODY,H1,H2,H3,H4,H5,H6,P,CENTER,TD,TH,UL,DL,DIV { + font-family: Verdana,Geneva,Arial,Helvetica,sans-serif; +} +BODY,TD { + font-size: 90%; +} +H1 { + text-align: center; + font-size: 140%; + font-weight: bold; +} +H2 { + font-size: 120%; + font-style: italic; +} +H3 { + font-size: 100%; +} +CAPTION { font-weight: bold } +DIV.qindex { + width: 100%; + background-color: #eeeeff; + border: 1px solid #b0b0b0; + text-align: center; + margin: 2px; + padding: 2px; + line-height: 140%; +} +DIV.nav { + width: 100%; + background-color: #eeeeff; + border: 1px solid #b0b0b0; + text-align: center; + margin: 2px; + padding: 2px; + line-height: 140%; +} +DIV.navtab { + background-color: #eeeeff; + border: 1px solid #b0b0b0; + text-align: center; + margin: 2px; + margin-right: 15px; + padding: 2px; +} +TD.navtab { + font-size: 70%; +} +A.qindex { + text-decoration: none; + font-weight: bold; + color: #1A419D; +} +A.qindex:visited { + text-decoration: none; + font-weight: bold; + color: #1A419D +} +A.qindex:hover { + text-decoration: none; + background-color: #ddddff; +} +A.qindexHL { + text-decoration: none; + font-weight: bold; + background-color: #6666cc; + color: #ffffff; + border: 1px double #9295C2; +} +A.qindexHL:hover { + text-decoration: none; + background-color: #6666cc; + color: #ffffff; +} +A.qindexHL:visited { + text-decoration: none; background-color: #6666cc; color: #ffffff } +A.el { text-decoration: none; font-weight: bold } +A.elRef { font-weight: bold } +A.code:link { text-decoration: none; font-weight: normal; color: #0000FF} +A.code:visited { text-decoration: none; font-weight: normal; color: #0000FF} +A.codeRef:link { font-weight: normal; color: #0000FF} +A.codeRef:visited { font-weight: normal; color: #0000FF} +A:hover { text-decoration: none; background-color: #f2f2ff } +DL.el { margin-left: -1cm } +.fragment { + font-family: Fixed, monospace; + font-size: 95%; +} +PRE.fragment { + border: 1px solid #CCCCCC; + background-color: #f5f5f5; + margin-top: 4px; + margin-bottom: 4px; + margin-left: 2px; + margin-right: 8px; + padding-left: 6px; + padding-right: 6px; + padding-top: 4px; + padding-bottom: 4px; +} +DIV.ah { background-color: black; font-weight: bold; color: #ffffff; margin-bottom: 3px; margin-top: 3px } +TD.md { background-color: #F4F4FB; font-weight: bold; } +TD.mdPrefix { + background-color: #F4F4FB; + color: #606060; + font-size: 80%; +} +TD.mdname1 { background-color: #F4F4FB; font-weight: bold; color: #602020; } +TD.mdname { background-color: #F4F4FB; font-weight: bold; color: #602020; width: 600px; } +DIV.groupHeader { + margin-left: 16px; + margin-top: 12px; + margin-bottom: 6px; + font-weight: bold; +} +DIV.groupText { margin-left: 16px; font-style: italic; font-size: 90% } +BODY { + background: white; + color: black; + margin-right: 20px; + margin-left: 20px; +} +TD.indexkey { + background-color: #eeeeff; + font-weight: bold; + padding-right : 10px; + padding-top : 2px; + padding-left : 10px; + padding-bottom : 2px; + margin-left : 0px; + margin-right : 0px; + margin-top : 2px; + margin-bottom : 2px; + border: 1px solid #CCCCCC; +} +TD.indexvalue { + background-color: #eeeeff; + font-style: italic; + padding-right : 10px; + padding-top : 2px; + padding-left : 10px; + padding-bottom : 2px; + margin-left : 0px; + margin-right : 0px; + margin-top : 2px; + margin-bottom : 2px; + border: 1px solid #CCCCCC; +} +TR.memlist { + background-color: #f0f0f0; +} +P.formulaDsp { text-align: center; } +IMG.formulaDsp { } +IMG.formulaInl { vertical-align: middle; } +SPAN.keyword { color: #008000 } +SPAN.keywordtype { color: #604020 } +SPAN.keywordflow { color: #e08000 } +SPAN.comment { color: #800000 } +SPAN.preprocessor { color: #806020 } +SPAN.stringliteral { color: #002080 } +SPAN.charliteral { color: #008080 } +.mdTable { + border: 1px solid #868686; + background-color: #F4F4FB; +} +.mdRow { + padding: 8px 10px; +} +.mdescLeft { + padding: 0px 8px 4px 8px; + font-size: 80%; + font-style: italic; + background-color: #FAFAFA; + border-top: 1px none #E0E0E0; + border-right: 1px none #E0E0E0; + border-bottom: 1px none #E0E0E0; + border-left: 1px none #E0E0E0; + margin: 0px; +} +.mdescRight { + padding: 0px 8px 4px 8px; + font-size: 80%; + font-style: italic; + background-color: #FAFAFA; + border-top: 1px none #E0E0E0; + border-right: 1px none #E0E0E0; + border-bottom: 1px none #E0E0E0; + border-left: 1px none #E0E0E0; + margin: 0px; +} +.memItemLeft { + padding: 1px 0px 0px 8px; + margin: 4px; + border-top-width: 1px; + border-right-width: 1px; + border-bottom-width: 1px; + border-left-width: 1px; + border-top-color: #E0E0E0; + border-right-color: #E0E0E0; + border-bottom-color: #E0E0E0; + border-left-color: #E0E0E0; + border-top-style: solid; + border-right-style: none; + border-bottom-style: none; + border-left-style: none; + background-color: #FAFAFA; + font-size: 80%; +} +.memItemRight { + padding: 1px 8px 0px 8px; + margin: 4px; + border-top-width: 1px; + border-right-width: 1px; + border-bottom-width: 1px; + border-left-width: 1px; + border-top-color: #E0E0E0; + border-right-color: #E0E0E0; + border-bottom-color: #E0E0E0; + border-left-color: #E0E0E0; + border-top-style: solid; + border-right-style: none; + border-bottom-style: none; + border-left-style: none; + background-color: #FAFAFA; + font-size: 80%; +} +.memTemplItemLeft { + padding: 1px 0px 0px 8px; + margin: 4px; + border-top-width: 1px; + border-right-width: 1px; + border-bottom-width: 1px; + border-left-width: 1px; + border-top-color: #E0E0E0; + border-right-color: #E0E0E0; + border-bottom-color: #E0E0E0; + border-left-color: #E0E0E0; + border-top-style: none; + border-right-style: none; + border-bottom-style: none; + border-left-style: none; + background-color: #FAFAFA; + font-size: 80%; +} +.memTemplItemRight { + padding: 1px 8px 0px 8px; + margin: 4px; + border-top-width: 1px; + border-right-width: 1px; + border-bottom-width: 1px; + border-left-width: 1px; + border-top-color: #E0E0E0; + border-right-color: #E0E0E0; + border-bottom-color: #E0E0E0; + border-left-color: #E0E0E0; + border-top-style: none; + border-right-style: none; + border-bottom-style: none; + border-left-style: none; + background-color: #FAFAFA; + font-size: 80%; +} +.memTemplParams { + padding: 1px 0px 0px 8px; + margin: 4px; + border-top-width: 1px; + border-right-width: 1px; + border-bottom-width: 1px; + border-left-width: 1px; + border-top-color: #E0E0E0; + border-right-color: #E0E0E0; + border-bottom-color: #E0E0E0; + border-left-color: #E0E0E0; + border-top-style: solid; + border-right-style: none; + border-bottom-style: none; + border-left-style: none; + color: #606060; + background-color: #FAFAFA; + font-size: 80%; +} +.search { color: #003399; + font-weight: bold; +} +FORM.search { + margin-bottom: 0px; + margin-top: 0px; +} +INPUT.search { font-size: 75%; + color: #000080; + font-weight: normal; + background-color: #eeeeff; +} +TD.tiny { font-size: 75%; +} +a { + color: #252E78; +} +a:visited { + color: #3D2185; +} +.dirtab { padding: 4px; + border-collapse: collapse; + border: 1px solid #b0b0b0; +} +TH.dirtab { background: #eeeeff; + font-weight: bold; +} +HR { height: 1px; + border: none; + border-top: 1px solid black; +} + +/* + * LLVM Modifications. + * Note: Everything above here is generated with "doxygen -w htlm" command. See + * "doxygen --help" for details. What follows are CSS overrides for LLVM + * specific formatting. We want to keep the above so it can be replaced with + * subsequent doxygen upgrades. + */ + +.footer { + font-size: 80%; + font-weight: bold; + text-align: center; + vertical-align: middle; +} +.title { + font-size: 25pt; + color: black; background: url("../img/lines.gif"); + font-weight: bold; + border-width: 1px; + border-style: solid none solid none; + text-align: center; + vertical-align: middle; + padding-left: 8pt; + padding-top: 1px; + padding-bottom: 2px +} +A:link { + cursor: pointer; + text-decoration: none; + font-weight: bolder; +} +A:visited { + cursor: pointer; + text-decoration: underline; + font-weight: bolder; +} +A:hover { + cursor: pointer; + text-decoration: underline; + font-weight: bolder; +} +A:active { + cursor: pointer; + text-decoration: underline; + font-weight: bolder; + font-style: italic; +} +H1 { + text-align: center; + font-size: 140%; + font-weight: bold; +} +H2 { + font-size: 120%; + font-style: italic; +} +H3 { + font-size: 100%; +} +A.qindex {} +A.qindexRef {} +A.el { text-decoration: none; font-weight: bold } +A.elRef { font-weight: bold } +A.code { text-decoration: none; font-weight: normal; color: #4444ee } +A.codeRef { font-weight: normal; color: #4444ee } diff --git a/libclamav/c++/llvm/docs/doxygen.footer b/libclamav/c++/llvm/docs/doxygen.footer new file mode 100644 index 000000000..d75fff5e4 --- /dev/null +++ b/libclamav/c++/llvm/docs/doxygen.footer @@ -0,0 +1,13 @@ +
    + + +
    + + + + diff --git a/libclamav/c++/llvm/docs/doxygen.header b/libclamav/c++/llvm/docs/doxygen.header new file mode 100644 index 000000000..a520434d6 --- /dev/null +++ b/libclamav/c++/llvm/docs/doxygen.header @@ -0,0 +1,9 @@ + + + + + +LLVM: $title + + +

    LLVM API Documentation

    diff --git a/libclamav/c++/llvm/docs/doxygen.intro b/libclamav/c++/llvm/docs/doxygen.intro new file mode 100644 index 000000000..547730cba --- /dev/null +++ b/libclamav/c++/llvm/docs/doxygen.intro @@ -0,0 +1,18 @@ +/// @mainpage Low Level Virtual Machine +/// +/// @section main_intro Introduction +/// Welcome to the Low Level Virtual Machine (LLVM). +/// +/// This documentation describes the @b internal software that makes +/// up LLVM, not the @b external use of LLVM. There are no instructions +/// here on how to use LLVM, only the APIs that make up the software. For usage +/// instructions, please see the programmer's guide or reference manual. +/// +/// @section main_caveat Caveat +/// This documentation is generated directly from the source code with doxygen. +/// Since LLVM is constantly under active development, what you're about to +/// read is out of date! However, it may still be useful since certain portions +/// of LLVM are very stable. +/// +/// @section main_changelog Change Log +/// - Original content written 12/30/2003 by Reid Spencer diff --git a/libclamav/c++/llvm/docs/img/Debugging.gif b/libclamav/c++/llvm/docs/img/Debugging.gif new file mode 100644 index 000000000..662d35a67 Binary files /dev/null and b/libclamav/c++/llvm/docs/img/Debugging.gif differ diff --git a/libclamav/c++/llvm/docs/img/libdeps.gif b/libclamav/c++/llvm/docs/img/libdeps.gif new file mode 100644 index 000000000..c5c0ed4c4 Binary files /dev/null and b/libclamav/c++/llvm/docs/img/libdeps.gif differ diff --git a/libclamav/c++/llvm/docs/img/lines.gif b/libclamav/c++/llvm/docs/img/lines.gif new file mode 100644 index 000000000..88f491edc Binary files /dev/null and b/libclamav/c++/llvm/docs/img/lines.gif differ diff --git a/libclamav/c++/llvm/docs/img/objdeps.gif b/libclamav/c++/llvm/docs/img/objdeps.gif new file mode 100644 index 000000000..57c3e2e60 Binary files /dev/null and b/libclamav/c++/llvm/docs/img/objdeps.gif differ diff --git a/libclamav/c++/llvm/docs/img/venusflytrap.jpg b/libclamav/c++/llvm/docs/img/venusflytrap.jpg new file mode 100644 index 000000000..59340ef3e Binary files /dev/null and b/libclamav/c++/llvm/docs/img/venusflytrap.jpg differ diff --git a/libclamav/c++/llvm/docs/index.html b/libclamav/c++/llvm/docs/index.html new file mode 100644 index 000000000..5c50c411c --- /dev/null +++ b/libclamav/c++/llvm/docs/index.html @@ -0,0 +1,287 @@ + + + + Documentation for the LLVM System + + + + +
    Documentation for the LLVM System
    + + + +
    +

    Written by The LLVM Team

    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      +
    • The +LLVM Announcements List: This is a low volume list that provides important +announcements regarding LLVM. It gets email about once a month.
    • + +
    • The Developer's +List: This list is for people who want to be included in technical +discussions of LLVM. People post to this list when they have questions about +writing code for or using the LLVM tools. It is relatively low volume.
    • + +
    • The Bugs & +Patches Archive: This list gets emailed every time a bug is opened and +closed, and when people submit patches to be included in LLVM. It is higher +volume than the LLVMdev list.
    • + +
    • The Commits +Archive: This list contains all commit messages that are made when LLVM +developers commit code changes to the repository. It is useful for those who +want to stay on the bleeding edge of LLVM development. This list is very high +volume.
    • + +
    • The +Test Results Archive: A message is automatically sent to this list by every +active nightly tester when it completes. As such, this list gets email several +times each day, making it a high volume list.
    • + +
    + + + +
    +
    + Valid CSS + Valid HTML 4.01 + + LLVM Compiler Infrastructure
    + Last modified: $Date$ +
    + + diff --git a/libclamav/c++/llvm/docs/llvm.css b/libclamav/c++/llvm/docs/llvm.css new file mode 100644 index 000000000..f572b5e57 --- /dev/null +++ b/libclamav/c++/llvm/docs/llvm.css @@ -0,0 +1,100 @@ +/* + * LLVM documentation style sheet + */ + +/* Common styles */ +.body { color: black; background: white; margin: 0 0 0 0 } + +/* No borders on image links */ +a:link img, a:visited img { border-style: none } + +address img { float: right; width: 88px; height: 31px; } +address { clear: right; } + +table { text-align: center; border: 2px solid black; + border-collapse: collapse; margin-top: 1em; margin-left: 1em; + margin-right: 1em; margin-bottom: 1em; } +tr, td { border: 2px solid gray; padding: 4pt 4pt 2pt 2pt; } +th { border: 2px solid gray; font-weight: bold; font-size: 105%; + background: url("img/lines.gif"); + font-family: "Georgia,Palatino,Times,Roman,SanSerif"; + text-align: center; vertical-align: middle; } +/* + * Documentation + */ +/* Common for title and header */ +.doc_title, .doc_section, .doc_subsection, h1, h2 { + color: black; background: url("img/lines.gif"); + font-family: "Georgia,Palatino,Times,Roman,SanSerif"; font-weight: bold; + border-width: 1px; + border-style: solid none solid none; + text-align: center; + vertical-align: middle; + padding-left: 8pt; + padding-top: 1px; + padding-bottom: 2px +} + +h1, .doc_section { text-align: center; font-size: 22pt; + margin: 20pt 0pt 5pt 0pt; } + +.doc_title, .title { text-align: left; font-size: 25pt } + +h2, .doc_subsection { width: 75%; + text-align: left; font-size: 12pt; + padding: 4pt 4pt 4pt 4pt; + margin: 1.5em 0.5em 0.5em 0.5em } + +h3, .doc_subsubsection { margin: 2.0em 0.5em 0.5em 0.5em; + font-weight: bold; font-style: oblique; + border-bottom: 1px solid #999999; font-size: 12pt; + width: 75%; } + +.doc_author { text-align: left; font-weight: bold; padding-left: 20pt } +.doc_text { text-align: left; padding-left: 20pt; padding-right: 10pt } + +.doc_footer { text-align: left; padding: 0 0 0 0 } + +.doc_hilite { color: blue; font-weight: bold; } + +.doc_table { text-align: center; width: 90%; + padding: 1px 1px 1px 1px; border: 1px; } + +.doc_warning { color: red; font-weight: bold } + +/*
    would use this class, and
    adds more padding */ +.doc_code, .literal-block + { border: solid 1px gray; background: #eeeeee; + margin: 0 1em 0 1em; + padding: 0 1em 0 1em; + display: table; + } + +/* It is preferrable to use
     everywhere instead of the
    + * 
    ...
    construct. + * + * Once all docs use
     for code regions, this style can  be merged with the
    + * one above, and we can drop the [pre] qualifier.
    + */
    +pre.doc_code, .literal-block { padding: 1em 2em 1em 1em }
    +
    +.doc_notes      { background: #fafafa; border: 1px solid #cecece;
    +                  display: table; padding: 0 1em 0 .1em }
    +
    +table.layout    { text-align: left; border: none; border-collapse: collapse;
    +                  padding: 4px 4px 4px 4px; }
    +tr.layout, td.layout, td.left, td.right
    +                { border: none; padding: 4pt 4pt 2pt 2pt; vertical-align: top; }
    +td.left         { text-align: left }
    +td.right        { text-align: right }
    +th.layout       { border: none; font-weight: bold; font-size: 105%;
    +                  text-align: center; vertical-align: middle; }
    +
    +/* Left align table cell */
    +.td_left        { border: 2px solid gray; text-align: left; }
    +
    +/* ReST-specific */
    +.title { margin-top: 0 }
    +.topic-title{ display: none }
    +div.contents ul { list-style-type: decimal }
    +.toc-backref    { color: black; text-decoration: none; }
    diff --git a/libclamav/c++/llvm/docs/re_format.7 b/libclamav/c++/llvm/docs/re_format.7
    new file mode 100644
    index 000000000..0c0928716
    --- /dev/null
    +++ b/libclamav/c++/llvm/docs/re_format.7
    @@ -0,0 +1,756 @@
    +.\"	$OpenBSD: re_format.7,v 1.14 2007/05/31 19:19:30 jmc Exp $
    +.\"
    +.\" Copyright (c) 1997, Phillip F Knaack. All rights reserved.
    +.\"
    +.\" Copyright (c) 1992, 1993, 1994 Henry Spencer.
    +.\" Copyright (c) 1992, 1993, 1994
    +.\"	The Regents of the University of California.  All rights reserved.
    +.\"
    +.\" This code is derived from software contributed to Berkeley by
    +.\" Henry Spencer.
    +.\"
    +.\" Redistribution and use in source and binary forms, with or without
    +.\" modification, are permitted provided that the following conditions
    +.\" are met:
    +.\" 1. Redistributions of source code must retain the above copyright
    +.\"    notice, this list of conditions and the following disclaimer.
    +.\" 2. Redistributions in binary form must reproduce the above copyright
    +.\"    notice, this list of conditions and the following disclaimer in the
    +.\"    documentation and/or other materials provided with the distribution.
    +.\" 3. Neither the name of the University nor the names of its contributors
    +.\"    may be used to endorse or promote products derived from this software
    +.\"    without specific prior written permission.
    +.\"
    +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
    +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    +.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
    +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
    +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
    +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
    +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
    +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
    +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
    +.\" SUCH DAMAGE.
    +.\"
    +.\"	@(#)re_format.7	8.3 (Berkeley) 3/20/94
    +.\"
    +.Dd $Mdocdate: May 31 2007 $
    +.Dt RE_FORMAT 7
    +.Os
    +.Sh NAME
    +.Nm re_format
    +.Nd POSIX regular expressions
    +.Sh DESCRIPTION
    +Regular expressions (REs),
    +as defined in
    +.St -p1003.1-2004 ,
    +come in two forms:
    +basic regular expressions
    +(BREs)
    +and extended regular expressions
    +(EREs).
    +Both forms of regular expressions are supported
    +by the interfaces described in
    +.Xr regex 3 .
    +Applications dealing with regular expressions
    +may use one or the other form
    +(or indeed both).
    +For example,
    +.Xr ed 1
    +uses BREs,
    +whilst
    +.Xr egrep 1
    +talks EREs.
    +Consult the manual page for the specific application to find out which
    +it uses.
    +.Pp
    +POSIX leaves some aspects of RE syntax and semantics open;
    +.Sq **
    +marks decisions on these aspects that
    +may not be fully portable to other POSIX implementations.
    +.Pp
    +This manual page first describes regular expressions in general,
    +specifically extended regular expressions,
    +and then discusses differences between them and basic regular expressions.
    +.Sh EXTENDED REGULAR EXPRESSIONS
    +An ERE is one** or more non-empty**
    +.Em branches ,
    +separated by
    +.Sq \*(Ba .
    +It matches anything that matches one of the branches.
    +.Pp
    +A branch is one** or more
    +.Em pieces ,
    +concatenated.
    +It matches a match for the first, followed by a match for the second, etc.
    +.Pp
    +A piece is an
    +.Em atom
    +possibly followed by a single**
    +.Sq * ,
    +.Sq + ,
    +.Sq ?\& ,
    +or
    +.Em bound .
    +An atom followed by
    +.Sq *
    +matches a sequence of 0 or more matches of the atom.
    +An atom followed by
    +.Sq +
    +matches a sequence of 1 or more matches of the atom.
    +An atom followed by
    +.Sq ?\&
    +matches a sequence of 0 or 1 matches of the atom.
    +.Pp
    +A bound is
    +.Sq {
    +followed by an unsigned decimal integer,
    +possibly followed by
    +.Sq ,\&
    +possibly followed by another unsigned decimal integer,
    +always followed by
    +.Sq } .
    +The integers must lie between 0 and
    +.Dv RE_DUP_MAX
    +(255**) inclusive,
    +and if there are two of them, the first may not exceed the second.
    +An atom followed by a bound containing one integer
    +.Ar i
    +and no comma matches
    +a sequence of exactly
    +.Ar i
    +matches of the atom.
    +An atom followed by a bound
    +containing one integer
    +.Ar i
    +and a comma matches
    +a sequence of
    +.Ar i
    +or more matches of the atom.
    +An atom followed by a bound
    +containing two integers
    +.Ar i
    +and
    +.Ar j
    +matches a sequence of
    +.Ar i
    +through
    +.Ar j
    +(inclusive) matches of the atom.
    +.Pp
    +An atom is a regular expression enclosed in
    +.Sq ()
    +(matching a part of the regular expression),
    +an empty set of
    +.Sq ()
    +(matching the null string)**,
    +a
    +.Em bracket expression
    +(see below),
    +.Sq .\&
    +(matching any single character),
    +.Sq ^
    +(matching the null string at the beginning of a line),
    +.Sq $
    +(matching the null string at the end of a line),
    +a
    +.Sq \e
    +followed by one of the characters
    +.Sq ^.[$()|*+?{\e
    +(matching that character taken as an ordinary character),
    +a
    +.Sq \e
    +followed by any other character**
    +(matching that character taken as an ordinary character,
    +as if the
    +.Sq \e
    +had not been present**),
    +or a single character with no other significance (matching that character).
    +A
    +.Sq {
    +followed by a character other than a digit is an ordinary character,
    +not the beginning of a bound**.
    +It is illegal to end an RE with
    +.Sq \e .
    +.Pp
    +A bracket expression is a list of characters enclosed in
    +.Sq [] .
    +It normally matches any single character from the list (but see below).
    +If the list begins with
    +.Sq ^ ,
    +it matches any single character
    +.Em not
    +from the rest of the list
    +(but see below).
    +If two characters in the list are separated by
    +.Sq - ,
    +this is shorthand for the full
    +.Em range
    +of characters between those two (inclusive) in the
    +collating sequence, e.g.\&
    +.Sq [0-9]
    +in ASCII matches any decimal digit.
    +It is illegal** for two ranges to share an endpoint, e.g.\&
    +.Sq a-c-e .
    +Ranges are very collating-sequence-dependent,
    +and portable programs should avoid relying on them.
    +.Pp
    +To include a literal
    +.Sq ]\&
    +in the list, make it the first character
    +(following a possible
    +.Sq ^ ) .
    +To include a literal
    +.Sq - ,
    +make it the first or last character,
    +or the second endpoint of a range.
    +To use a literal
    +.Sq -
    +as the first endpoint of a range,
    +enclose it in
    +.Sq [.
    +and
    +.Sq .]
    +to make it a collating element (see below).
    +With the exception of these and some combinations using
    +.Sq [
    +(see next paragraphs),
    +all other special characters, including
    +.Sq \e ,
    +lose their special significance within a bracket expression.
    +.Pp
    +Within a bracket expression, a collating element
    +(a character,
    +a multi-character sequence that collates as if it were a single character,
    +or a collating-sequence name for either)
    +enclosed in
    +.Sq [.
    +and
    +.Sq .]
    +stands for the sequence of characters of that collating element.
    +The sequence is a single element of the bracket expression's list.
    +A bracket expression containing a multi-character collating element
    +can thus match more than one character,
    +e.g. if the collating sequence includes a
    +.Sq ch
    +collating element,
    +then the RE
    +.Sq [[.ch.]]*c
    +matches the first five characters of
    +.Sq chchcc .
    +.Pp
    +Within a bracket expression, a collating element enclosed in
    +.Sq [=
    +and
    +.Sq =]
    +is an equivalence class, standing for the sequences of characters
    +of all collating elements equivalent to that one, including itself.
    +(If there are no other equivalent collating elements,
    +the treatment is as if the enclosing delimiters were
    +.Sq [.
    +and
    +.Sq .] . )
    +For example, if
    +.Sq x
    +and
    +.Sq y
    +are the members of an equivalence class,
    +then
    +.Sq [[=x=]] ,
    +.Sq [[=y=]] ,
    +and
    +.Sq [xy]
    +are all synonymous.
    +An equivalence class may not** be an endpoint of a range.
    +.Pp
    +Within a bracket expression, the name of a
    +.Em character class
    +enclosed
    +in
    +.Sq [:
    +and
    +.Sq :]
    +stands for the list of all characters belonging to that class.
    +Standard character class names are:
    +.Bd -literal -offset indent
    +alnum	digit	punct
    +alpha	graph	space
    +blank	lower	upper
    +cntrl	print	xdigit
    +.Ed
    +.Pp
    +These stand for the character classes defined in
    +.Xr ctype 3 .
    +A locale may provide others.
    +A character class may not be used as an endpoint of a range.
    +.Pp
    +There are two special cases** of bracket expressions:
    +the bracket expressions
    +.Sq [[:<:]]
    +and
    +.Sq [[:>:]]
    +match the null string at the beginning and end of a word, respectively.
    +A word is defined as a sequence of
    +characters starting and ending with a word character
    +which is neither preceded nor followed by
    +word characters.
    +A word character is an
    +.Em alnum
    +character (as defined by
    +.Xr ctype 3 )
    +or an underscore.
    +This is an extension,
    +compatible with but not specified by POSIX,
    +and should be used with
    +caution in software intended to be portable to other systems.
    +.Pp
    +In the event that an RE could match more than one substring of a given
    +string,
    +the RE matches the one starting earliest in the string.
    +If the RE could match more than one substring starting at that point,
    +it matches the longest.
    +Subexpressions also match the longest possible substrings, subject to
    +the constraint that the whole match be as long as possible,
    +with subexpressions starting earlier in the RE taking priority over
    +ones starting later.
    +Note that higher-level subexpressions thus take priority over
    +their lower-level component subexpressions.
    +.Pp
    +Match lengths are measured in characters, not collating elements.
    +A null string is considered longer than no match at all.
    +For example,
    +.Sq bb*
    +matches the three middle characters of
    +.Sq abbbc ;
    +.Sq (wee|week)(knights|nights)
    +matches all ten characters of
    +.Sq weeknights ;
    +when
    +.Sq (.*).*
    +is matched against
    +.Sq abc ,
    +the parenthesized subexpression matches all three characters;
    +and when
    +.Sq (a*)*
    +is matched against
    +.Sq bc ,
    +both the whole RE and the parenthesized subexpression match the null string.
    +.Pp
    +If case-independent matching is specified,
    +the effect is much as if all case distinctions had vanished from the
    +alphabet.
    +When an alphabetic that exists in multiple cases appears as an
    +ordinary character outside a bracket expression, it is effectively
    +transformed into a bracket expression containing both cases,
    +e.g.\&
    +.Sq x
    +becomes
    +.Sq [xX] .
    +When it appears inside a bracket expression,
    +all case counterparts of it are added to the bracket expression,
    +so that, for example,
    +.Sq [x]
    +becomes
    +.Sq [xX]
    +and
    +.Sq [^x]
    +becomes
    +.Sq [^xX] .
    +.Pp
    +No particular limit is imposed on the length of REs**.
    +Programs intended to be portable should not employ REs longer
    +than 256 bytes,
    +as an implementation can refuse to accept such REs and remain
    +POSIX-compliant.
    +.Pp
    +The following is a list of extended regular expressions:
    +.Bl -tag -width Ds
    +.It Ar c
    +Any character
    +.Ar c
    +not listed below matches itself.
    +.It \e Ns Ar c
    +Any backslash-escaped character
    +.Ar c
    +matches itself.
    +.It \&.
    +Matches any single character that is not a newline
    +.Pq Sq \en .
    +.It Bq Ar char-class
    +Matches any single character in
    +.Ar char-class .
    +To include a
    +.Ql \&]
    +in
    +.Ar char-class ,
    +it must be the first character.
    +A range of characters may be specified by separating the end characters
    +of the range with a
    +.Ql - ;
    +e.g.\&
    +.Ar a-z
    +specifies the lower case characters.
    +The following literal expressions can also be used in
    +.Ar char-class
    +to specify sets of characters:
    +.Bd -unfilled -offset indent
    +[:alnum:] [:cntrl:] [:lower:] [:space:]
    +[:alpha:] [:digit:] [:print:] [:upper:]
    +[:blank:] [:graph:] [:punct:] [:xdigit:]
    +.Ed
    +.Pp
    +If
    +.Ql -
    +appears as the first or last character of
    +.Ar char-class ,
    +then it matches itself.
    +All other characters in
    +.Ar char-class
    +match themselves.
    +.Pp
    +Patterns in
    +.Ar char-class
    +of the form
    +.Eo [.
    +.Ar col-elm
    +.Ec .]\&
    +or
    +.Eo [=
    +.Ar col-elm
    +.Ec =]\& ,
    +where
    +.Ar col-elm
    +is a collating element, are interpreted according to
    +.Xr setlocale 3
    +.Pq not currently supported .
    +.It Bq ^ Ns Ar char-class
    +Matches any single character, other than newline, not in
    +.Ar char-class .
    +.Ar char-class
    +is defined as above.
    +.It ^
    +If
    +.Sq ^
    +is the first character of a regular expression, then it
    +anchors the regular expression to the beginning of a line.
    +Otherwise, it matches itself.
    +.It $
    +If
    +.Sq $
    +is the last character of a regular expression,
    +it anchors the regular expression to the end of a line.
    +Otherwise, it matches itself.
    +.It [[:<:]]
    +Anchors the single character regular expression or subexpression
    +immediately following it to the beginning of a word.
    +.It [[:>:]]
    +Anchors the single character regular expression or subexpression
    +immediately following it to the end of a word.
    +.It Pq Ar re
    +Defines a subexpression
    +.Ar re .
    +Any set of characters enclosed in parentheses
    +matches whatever the set of characters without parentheses matches
    +(that is a long-winded way of saying the constructs
    +.Sq (re)
    +and
    +.Sq re
    +match identically).
    +.It *
    +Matches the single character regular expression or subexpression
    +immediately preceding it zero or more times.
    +If
    +.Sq *
    +is the first character of a regular expression or subexpression,
    +then it matches itself.
    +The
    +.Sq *
    +operator sometimes yields unexpected results.
    +For example, the regular expression
    +.Ar b*
    +matches the beginning of the string
    +.Qq abbb
    +(as opposed to the substring
    +.Qq bbb ) ,
    +since a null match is the only leftmost match.
    +.It +
    +Matches the singular character regular expression
    +or subexpression immediately preceding it
    +one or more times.
    +.It ?
    +Matches the singular character regular expression
    +or subexpression immediately preceding it
    +0 or 1 times.
    +.Sm off
    +.It Xo
    +.Pf { Ar n , m No }\ \&
    +.Pf { Ar n , No }\ \&
    +.Pf { Ar n No }
    +.Xc
    +.Sm on
    +Matches the single character regular expression or subexpression
    +immediately preceding it at least
    +.Ar n
    +and at most
    +.Ar m
    +times.
    +If
    +.Ar m
    +is omitted, then it matches at least
    +.Ar n
    +times.
    +If the comma is also omitted, then it matches exactly
    +.Ar n
    +times.
    +.It \*(Ba
    +Used to separate patterns.
    +For example,
    +the pattern
    +.Sq cat\*(Badog
    +matches either
    +.Sq cat
    +or
    +.Sq dog .
    +.El
    +.Sh BASIC REGULAR EXPRESSIONS
    +Basic regular expressions differ in several respects:
    +.Bl -bullet -offset 3n
    +.It
    +.Sq \*(Ba ,
    +.Sq + ,
    +and
    +.Sq ?\&
    +are ordinary characters and there is no equivalent
    +for their functionality.
    +.It
    +The delimiters for bounds are
    +.Sq \e{
    +and
    +.Sq \e} ,
    +with
    +.Sq {
    +and
    +.Sq }
    +by themselves ordinary characters.
    +.It
    +The parentheses for nested subexpressions are
    +.Sq \e(
    +and
    +.Sq \e) ,
    +with
    +.Sq (
    +and
    +.Sq )\&
    +by themselves ordinary characters.
    +.It
    +.Sq ^
    +is an ordinary character except at the beginning of the
    +RE or** the beginning of a parenthesized subexpression.
    +.It
    +.Sq $
    +is an ordinary character except at the end of the
    +RE or** the end of a parenthesized subexpression.
    +.It
    +.Sq *
    +is an ordinary character if it appears at the beginning of the
    +RE or the beginning of a parenthesized subexpression
    +(after a possible leading
    +.Sq ^ ) .
    +.It
    +Finally, there is one new type of atom, a
    +.Em back-reference :
    +.Sq \e
    +followed by a non-zero decimal digit
    +.Ar d
    +matches the same sequence of characters matched by the
    +.Ar d Ns th
    +parenthesized subexpression
    +(numbering subexpressions by the positions of their opening parentheses,
    +left to right),
    +so that, for example,
    +.Sq \e([bc]\e)\e1
    +matches
    +.Sq bb\&
    +or
    +.Sq cc
    +but not
    +.Sq bc .
    +.El
    +.Pp
    +The following is a list of basic regular expressions:
    +.Bl -tag -width Ds
    +.It Ar c
    +Any character
    +.Ar c
    +not listed below matches itself.
    +.It \e Ns Ar c
    +Any backslash-escaped character
    +.Ar c ,
    +except for
    +.Sq { ,
    +.Sq } ,
    +.Sq \&( ,
    +and
    +.Sq \&) ,
    +matches itself.
    +.It \&.
    +Matches any single character that is not a newline
    +.Pq Sq \en .
    +.It Bq Ar char-class
    +Matches any single character in
    +.Ar char-class .
    +To include a
    +.Ql \&]
    +in
    +.Ar char-class ,
    +it must be the first character.
    +A range of characters may be specified by separating the end characters
    +of the range with a
    +.Ql - ;
    +e.g.\&
    +.Ar a-z
    +specifies the lower case characters.
    +The following literal expressions can also be used in
    +.Ar char-class
    +to specify sets of characters:
    +.Bd -unfilled -offset indent
    +[:alnum:] [:cntrl:] [:lower:] [:space:]
    +[:alpha:] [:digit:] [:print:] [:upper:]
    +[:blank:] [:graph:] [:punct:] [:xdigit:]
    +.Ed
    +.Pp
    +If
    +.Ql -
    +appears as the first or last character of
    +.Ar char-class ,
    +then it matches itself.
    +All other characters in
    +.Ar char-class
    +match themselves.
    +.Pp
    +Patterns in
    +.Ar char-class
    +of the form
    +.Eo [.
    +.Ar col-elm
    +.Ec .]\&
    +or
    +.Eo [=
    +.Ar col-elm
    +.Ec =]\& ,
    +where
    +.Ar col-elm
    +is a collating element, are interpreted according to
    +.Xr setlocale 3
    +.Pq not currently supported .
    +.It Bq ^ Ns Ar char-class
    +Matches any single character, other than newline, not in
    +.Ar char-class .
    +.Ar char-class
    +is defined as above.
    +.It ^
    +If
    +.Sq ^
    +is the first character of a regular expression, then it
    +anchors the regular expression to the beginning of a line.
    +Otherwise, it matches itself.
    +.It $
    +If
    +.Sq $
    +is the last character of a regular expression,
    +it anchors the regular expression to the end of a line.
    +Otherwise, it matches itself.
    +.It [[:<:]]
    +Anchors the single character regular expression or subexpression
    +immediately following it to the beginning of a word.
    +.It [[:>:]]
    +Anchors the single character regular expression or subexpression
    +immediately following it to the end of a word.
    +.It \e( Ns Ar re Ns \e)
    +Defines a subexpression
    +.Ar re .
    +Subexpressions may be nested.
    +A subsequent backreference of the form
    +.Pf \e Ns Ar n ,
    +where
    +.Ar n
    +is a number in the range [1,9], expands to the text matched by the
    +.Ar n Ns th
    +subexpression.
    +For example, the regular expression
    +.Ar \e(.*\e)\e1
    +matches any string consisting of identical adjacent substrings.
    +Subexpressions are ordered relative to their left delimiter.
    +.It *
    +Matches the single character regular expression or subexpression
    +immediately preceding it zero or more times.
    +If
    +.Sq *
    +is the first character of a regular expression or subexpression,
    +then it matches itself.
    +The
    +.Sq *
    +operator sometimes yields unexpected results.
    +For example, the regular expression
    +.Ar b*
    +matches the beginning of the string
    +.Qq abbb
    +(as opposed to the substring
    +.Qq bbb ) ,
    +since a null match is the only leftmost match.
    +.Sm off
    +.It Xo
    +.Pf \e{ Ar n , m No \e}\ \&
    +.Pf \e{ Ar n , No \e}\ \&
    +.Pf \e{ Ar n No \e}
    +.Xc
    +.Sm on
    +Matches the single character regular expression or subexpression
    +immediately preceding it at least
    +.Ar n
    +and at most
    +.Ar m
    +times.
    +If
    +.Ar m
    +is omitted, then it matches at least
    +.Ar n
    +times.
    +If the comma is also omitted, then it matches exactly
    +.Ar n
    +times.
    +.El
    +.Sh SEE ALSO
    +.Xr ctype 3 ,
    +.Xr regex 3
    +.Sh STANDARDS
    +.St -p1003.1-2004 :
    +Base Definitions, Chapter 9 (Regular Expressions).
    +.Sh BUGS
    +Having two kinds of REs is a botch.
    +.Pp
    +The current POSIX spec says that
    +.Sq )\&
    +is an ordinary character in the absence of an unmatched
    +.Sq ( ;
    +this was an unintentional result of a wording error,
    +and change is likely.
    +Avoid relying on it.
    +.Pp
    +Back-references are a dreadful botch,
    +posing major problems for efficient implementations.
    +They are also somewhat vaguely defined
    +(does
    +.Sq a\e(\e(b\e)*\e2\e)*d
    +match
    +.Sq abbbd ? ) .
    +Avoid using them.
    +.Pp
    +POSIX's specification of case-independent matching is vague.
    +The
    +.Dq one case implies all cases
    +definition given above
    +is the current consensus among implementors as to the right interpretation.
    +.Pp
    +The syntax for word boundaries is incredibly ugly.
    diff --git a/libclamav/c++/llvm/docs/tutorial/JITTutorial1.html b/libclamav/c++/llvm/docs/tutorial/JITTutorial1.html
    new file mode 100644
    index 000000000..3b7b8dea1
    --- /dev/null
    +++ b/libclamav/c++/llvm/docs/tutorial/JITTutorial1.html
    @@ -0,0 +1,207 @@
    +
    +
    +
    +
    +  LLVM Tutorial 1: A First Function
    +  
    +  
    +  
    +  
    +
    +
    +
    +
    +
    LLVM Tutorial 1: A First Function
    + +
    +

    Written by Owen Anderson

    +
    + + + + + +
    + +

    For starters, let's consider a relatively straightforward function that takes three integer parameters and returns an arithmetic combination of them. This is nice and simple, especially since it involves no control flow:

    + +
    +
    +int mul_add(int x, int y, int z) {
    +  return x * y + z;
    +}
    +
    +
    + +

    As a preview, the LLVM IR we’re going to end up generating for this function will look like:

    + +
    +
    +define i32 @mul_add(i32 %x, i32 %y, i32 %z) {
    +entry:
    +  %tmp = mul i32 %x, %y
    +  %tmp2 = add i32 %tmp, %z
    +  ret i32 %tmp2
    +}
    +
    +
    + +

    If you're unsure what the above code says, skim through the LLVM Language Reference Manual and convince yourself that the above LLVM IR is actually equivalent to the original function. Once you’re satisfied with that, let's move on to actually generating it programmatically!

    + +

    Of course, before we can start, we need to #include the appropriate LLVM header files:

    + +
    +
    +#include "llvm/Module.h"
    +#include "llvm/Function.h"
    +#include "llvm/PassManager.h"
    +#include "llvm/CallingConv.h"
    +#include "llvm/Analysis/Verifier.h"
    +#include "llvm/Assembly/PrintModulePass.h"
    +#include "llvm/Support/IRBuilder.h"
    +#include "llvm/Support/raw_ostream.h"
    +
    +
    + +

    Now, let's get started on our real program. Here's what our basic main() will look like:

    + +
    +
    +using namespace llvm;
    +
    +Module* makeLLVMModule();
    +
    +int main(int argc, char**argv) {
    +  Module* Mod = makeLLVMModule();
    +
    +  verifyModule(*Mod, PrintMessageAction);
    +
    +  PassManager PM;
    +  PM.add(createPrintModulePass(&outs()));
    +  PM.run(*Mod);
    +
    +  delete Mod;
    +  return 0;
    +}
    +
    +
    + +

    The first segment is pretty simple: it creates an LLVM “module.” In LLVM, a module represents a single unit of code that is to be processed together. A module contains things like global variables, function declarations, and implementations. Here we’ve declared a makeLLVMModule() function to do the real work of creating the module. Don’t worry, we’ll be looking at that one next!

    + +

    The second segment runs the LLVM module verifier on our newly created module. While this probably isn’t really necessary for a simple module like this one, it's always a good idea, especially if you’re generating LLVM IR based on some input. The verifier will print an error message if your LLVM module is malformed in any way.

    + +

    Finally, we instantiate an LLVM PassManager and run +the PrintModulePass on our module. LLVM uses an explicit pass +infrastructure to manage optimizations and various other things. +A PassManager, as should be obvious from its name, manages passes: +it is responsible for scheduling them, invoking them, and ensuring the proper +disposal after we’re done with them. For this example, we’re just using a +trivial pass that prints out our module in textual form.

    + +

    Now onto the interesting part: creating and populating a module. Here's the +first chunk of our makeLLVMModule():

    + +
    +
    +Module* makeLLVMModule() {
    +  // Module Construction
    +  Module* mod = new Module("test", getGlobalContext());
    +
    +
    + +

    Exciting, isn’t it!? All we’re doing here is instantiating a module and giving it a name. The name isn’t particularly important unless you’re going to be dealing with multiple modules at once.

    + +
    +
    +  Constant* c = mod->getOrInsertFunction("mul_add",
    +  /*ret type*/                           IntegerType::get(32),
    +  /*args*/                               IntegerType::get(32),
    +                                         IntegerType::get(32),
    +                                         IntegerType::get(32),
    +  /*varargs terminated with null*/       NULL);
    +  
    +  Function* mul_add = cast<Function>(c);
    +  mul_add->setCallingConv(CallingConv::C);
    +
    +
    + +

    We construct our Function by calling getOrInsertFunction() on our module, passing in the name, return type, and argument types of the function. In the case of our mul_add function, that means one 32-bit integer for the return value and three 32-bit integers for the arguments.

    + +

    You'll notice that getOrInsertFunction() doesn't actually return a Function*. This is because getOrInsertFunction() will return a cast of the existing function if the function already existed with a different prototype. Since we know that there's not already a mul_add function, we can safely just cast c to a Function*. + +

    In addition, we set the calling convention for our new function to be the C +calling convention. This isn’t strictly necessary, but it ensures that our new +function will interoperate properly with C code, which is a good thing.

    + +
    +
    +  Function::arg_iterator args = mul_add->arg_begin();
    +  Value* x = args++;
    +  x->setName("x");
    +  Value* y = args++;
    +  y->setName("y");
    +  Value* z = args++;
    +  z->setName("z");
    +
    +
    + +

    While we’re setting up our function, let's also give names to the parameters. This also isn’t strictly necessary (LLVM will generate names for them if you don’t specify them), but it’ll make looking at our output somewhat more pleasant. To name the parameters, we iterate over the arguments of our function and call setName() on them. We’ll also keep the pointer to x, y, and z around, since we’ll need them when we get around to creating instructions.

    + +

    Great! We have a function now. But what good is a function if it has no body? Before we start working on a body for our new function, we need to recall some details of the LLVM IR. The IR, being an abstract assembly language, represents control flow using jumps (we call them branches), both conditional and unconditional. The straight-line sequences of code between branches are called basic blocks, or just blocks. To create a body for our function, we fill it with blocks:

    + +
    +
    +  BasicBlock* block = BasicBlock::Create(getGlobalContext(), "entry", mul_add);
    +  IRBuilder<> builder(block);
    +
    +
    + +

    We create a new basic block, as you might expect, by calling its constructor. All we need to tell it is its name and the function to which it belongs. In addition, we’re creating an IRBuilder object, which is a convenience interface for creating instructions and appending them to the end of a block. Instructions can be created through their constructors as well, but some of their interfaces are quite complicated. Unless you need a lot of control, using IRBuilder will make your life simpler.

    + +
    +
    +  Value* tmp = builder.CreateBinOp(Instruction::Mul,
    +                                   x, y, "tmp");
    +  Value* tmp2 = builder.CreateBinOp(Instruction::Add,
    +                                    tmp, z, "tmp2");
    +
    +  builder.CreateRet(tmp2);
    +  
    +  return mod;
    +}
    +
    +
    + +

    The final step in creating our function is to create the instructions that make it up. Our mul_add function is composed of just three instructions: a multiply, an add, and a return. IRBuilder gives us a simple interface for constructing these instructions and appending them to the “entry” block. Each of the calls to IRBuilder returns a Value* that represents the value yielded by the instruction. You’ll also notice that, above, x, y, and z are also Value*'s, so it's clear that instructions operate on Value*'s.

    + +

    And that's it! Now you can compile and run your code, and get a wonderful textual print out of the LLVM IR we saw at the beginning. To compile, use the following command line as a guide:

    + +
    +
    +# c++ -g tut1.cpp `llvm-config --cxxflags --ldflags --libs core` -o tut1
    +# ./tut1
    +
    +
    + +

    The llvm-config utility is used to obtain the necessary GCC-compatible compiler flags for linking with LLVM. For this example, we only need the 'core' library. We'll use others once we start adding optimizers and the JIT engine.

    + +Next: A More Complicated Function +
    + + +
    +
    + Valid CSS! + Valid HTML 4.01! + + Owen Anderson
    + The LLVM Compiler Infrastructure
    + Last modified: $Date: 2009-07-21 11:05:13 -0700 (Tue, 21 Jul 2009) $ +
    + + + diff --git a/libclamav/c++/llvm/docs/tutorial/JITTutorial2-1.png b/libclamav/c++/llvm/docs/tutorial/JITTutorial2-1.png new file mode 100644 index 000000000..eb21695f6 Binary files /dev/null and b/libclamav/c++/llvm/docs/tutorial/JITTutorial2-1.png differ diff --git a/libclamav/c++/llvm/docs/tutorial/JITTutorial2.html b/libclamav/c++/llvm/docs/tutorial/JITTutorial2.html new file mode 100644 index 000000000..504d96597 --- /dev/null +++ b/libclamav/c++/llvm/docs/tutorial/JITTutorial2.html @@ -0,0 +1,200 @@ + + + + + LLVM Tutorial 2: A More Complicated Function + + + + + + + + +
    LLVM Tutorial 2: A More Complicated Function
    + +
    +

    Written by Owen Anderson

    +
    + + + + + +
    + +

    Now that we understand the basics of creating functions in LLVM, let's move on to a more complicated example: something with control flow. As an example, let's consider Euclid's Greatest Common Denominator (GCD) algorithm:

    + +
    +
    +unsigned gcd(unsigned x, unsigned y) {
    +  if(x == y) {
    +    return x;
    +  } else if(x < y) {
    +    return gcd(x, y - x);
    +  } else {
    +    return gcd(x - y, y);
    +  }
    +}
    +
    +
    + +

    With this example, we'll learn how to create functions with multiple blocks and control flow, and how to make function calls within your LLVM code. For starters, consider the diagram below.

    + +
    GCD CFG
    + +

    This is a graphical representation of a program in LLVM IR. It places each basic block on a node of a graph and uses directed edges to indicate flow control. These blocks will be serialized when written to a text or bitcode file, but it is often useful conceptually to think of them as a graph. Again, if you are unsure about the code in the diagram, you should skim through the LLVM Language Reference Manual and convince yourself that it is, in fact, the GCD algorithm.

    + +

    The first part of our code is practically the same as from the first tutorial. The same basic setup is required: creating a module, verifying it, and running the PrintModulePass on it. Even the first segment of makeLLVMModule() looks essentially the same, except that gcd takes one fewer parameter than mul_add.

    + +
    +
    +#include "llvm/Module.h"
    +#include "llvm/Function.h"
    +#include "llvm/PassManager.h"
    +#include "llvm/Analysis/Verifier.h"
    +#include "llvm/Assembly/PrintModulePass.h"
    +#include "llvm/Support/IRBuilder.h"
    +#include "llvm/Support/raw_ostream.h"
    +
    +using namespace llvm;
    +
    +Module* makeLLVMModule();
    +
    +int main(int argc, char**argv) {
    +  Module* Mod = makeLLVMModule();
    +  
    +  verifyModule(*Mod, PrintMessageAction);
    +  
    +  PassManager PM;
    +  PM.add(createPrintModulePass(&outs()));
    +  PM.run(*Mod);
    +
    +  delete Mod;  
    +  return 0;
    +}
    +
    +Module* makeLLVMModule() {
    +  Module* mod = new Module("tut2");
    +  
    +  Constant* c = mod->getOrInsertFunction("gcd",
    +                                         IntegerType::get(32),
    +                                         IntegerType::get(32),
    +                                         IntegerType::get(32),
    +                                         NULL);
    +  Function* gcd = cast<Function>(c);
    +  
    +  Function::arg_iterator args = gcd->arg_begin();
    +  Value* x = args++;
    +  x->setName("x");
    +  Value* y = args++;
    +  y->setName("y");
    +
    +
    + +

    Here, however, is where our code begins to diverge from the first tutorial. Because gcd has control flow, it is composed of multiple blocks interconnected by branching (br) instructions. For those familiar with assembly language, a block is similar to a labeled set of instructions. For those not familiar with assembly language, a block is basically a set of instructions that can be branched to and is executed linearly until the block is terminated by one of a small number of control flow instructions, such as br or ret.

    + +

    Blocks correspond to the nodes in the diagram we looked at in the beginning of this tutorial. From the diagram, we can see that this function contains five blocks, so we'll go ahead and create them. Note that we're making use of LLVM's automatic name uniquing in this code sample, since we're giving two blocks the same name.

    + +
    +
    +  BasicBlock* entry = BasicBlock::Create(getGlobalContext(), ("entry", gcd);
    +  BasicBlock* ret = BasicBlock::Create(getGlobalContext(), ("return", gcd);
    +  BasicBlock* cond_false = BasicBlock::Create(getGlobalContext(), ("cond_false", gcd);
    +  BasicBlock* cond_true = BasicBlock::Create(getGlobalContext(), ("cond_true", gcd);
    +  BasicBlock* cond_false_2 = BasicBlock::Create(getGlobalContext(), ("cond_false", gcd);
    +
    +
    + +

    Now we're ready to begin generating code! We'll start with the entry block. This block corresponds to the top-level if-statement in the original C code, so we need to compare x and y. To achieve this, we perform an explicit comparison using ICmpEQ. ICmpEQ stands for an integer comparison for equality and returns a 1-bit integer result. This 1-bit result is then used as the input to a conditional branch, with ret as the true and cond_false as the false case.

    + +
    +
    +  IRBuilder<> builder(entry);
    +  Value* xEqualsY = builder.CreateICmpEQ(x, y, "tmp");
    +  builder.CreateCondBr(xEqualsY, ret, cond_false);
    +
    +
    + +

    Our next block, ret, is pretty simple: it just returns the value of x. Recall that this block is only reached if x == y, so this is the correct behavior. Notice that instead of creating a new IRBuilder for each block, we can use SetInsertPoint to retarget our existing one. This saves on construction and memory allocation costs.

    + +
    +
    +  builder.SetInsertPoint(ret);
    +  builder.CreateRet(x);
    +
    +
    + +

    cond_false is a more interesting block: we now know that x +!= y, so we must branch again to determine which of x +and y is larger. This is achieved using the ICmpULT +instruction, which stands for integer comparison for unsigned +less-than. In LLVM, integer types do not carry sign; a 32-bit integer +pseudo-register can be interpreted as signed or unsigned without casting. +Whether a signed or unsigned interpretation is desired is specified in the +instruction. This is why several instructions in the LLVM IR, such as integer +less-than, include a specifier for signed or unsigned.

    + +

    Also note that we're again making use of LLVM's automatic name uniquing, this time at a register level. We've deliberately chosen to name every instruction "tmp" to illustrate that LLVM will give them all unique names without getting confused.

    + +
    +
    +  builder.SetInsertPoint(cond_false);
    +  Value* xLessThanY = builder.CreateICmpULT(x, y, "tmp");
    +  builder.CreateCondBr(xLessThanY, cond_true, cond_false_2);
    +
    +
    + +

    Our last two blocks are quite similar; they're both recursive calls to gcd with different parameters. To create a call instruction, we have to create a vector (or any other container with InputInterators) to hold the arguments. We then pass in the beginning and ending iterators for this vector.

    + +
    +
    +  builder.SetInsertPoint(cond_true);
    +  Value* yMinusX = builder.CreateSub(y, x, "tmp");
    +  std::vector<Value*> args1;
    +  args1.push_back(x);
    +  args1.push_back(yMinusX);
    +  Value* recur_1 = builder.CreateCall(gcd, args1.begin(), args1.end(), "tmp");
    +  builder.CreateRet(recur_1);
    +  
    +  builder.SetInsertPoint(cond_false_2);
    +  Value* xMinusY = builder.CreateSub(x, y, "tmp");
    +  std::vector<Value*> args2;
    +  args2.push_back(xMinusY);
    +  args2.push_back(y);
    +  Value* recur_2 = builder.CreateCall(gcd, args2.begin(), args2.end(), "tmp");
    +  builder.CreateRet(recur_2);
    +  
    +  return mod;
    +}
    +
    +
    + +

    And that's it! You can compile and execute your code in the same way as before, by doing:

    + +
    +
    +# c++ -g tut2.cpp `llvm-config --cxxflags --ldflags --libs core` -o tut2
    +# ./tut2
    +
    +
    + +
    + + +
    +
    + Valid CSS! + Valid HTML 4.01! + + Owen Anderson
    + The LLVM Compiler Infrastructure
    + Last modified: $Date: 2007-10-17 11:05:13 -0700 (Wed, 17 Oct 2007) $ +
    + + + diff --git a/libclamav/c++/llvm/docs/tutorial/LangImpl1.html b/libclamav/c++/llvm/docs/tutorial/LangImpl1.html new file mode 100644 index 000000000..5e1786cb0 --- /dev/null +++ b/libclamav/c++/llvm/docs/tutorial/LangImpl1.html @@ -0,0 +1,348 @@ + + + + + Kaleidoscope: Tutorial Introduction and the Lexer + + + + + + + +
    Kaleidoscope: Tutorial Introduction and the Lexer
    + + + +
    +

    Written by Chris Lattner

    +
    + + + + + +
    + +

    Welcome to the "Implementing a language with LLVM" tutorial. This tutorial +runs through the implementation of a simple language, showing how fun and +easy it can be. This tutorial will get you up and started as well as help to +build a framework you can extend to other languages. The code in this tutorial +can also be used as a playground to hack on other LLVM specific things. +

    + +

    +The goal of this tutorial is to progressively unveil our language, describing +how it is built up over time. This will let us cover a fairly broad range of +language design and LLVM-specific usage issues, showing and explaining the code +for it all along the way, without overwhelming you with tons of details up +front.

    + +

    It is useful to point out ahead of time that this tutorial is really about +teaching compiler techniques and LLVM specifically, not about teaching +modern and sane software engineering principles. In practice, this means that +we'll take a number of shortcuts to simplify the exposition. For example, the +code leaks memory, uses global variables all over the place, doesn't use nice +design patterns like visitors, etc... but it +is very simple. If you dig in and use the code as a basis for future projects, +fixing these deficiencies shouldn't be hard.

    + +

    I've tried to put this tutorial together in a way that makes chapters easy to +skip over if you are already familiar with or are uninterested in the various +pieces. The structure of the tutorial is: +

    + +
      +
    • Chapter #1: Introduction to the Kaleidoscope +language, and the definition of its Lexer - This shows where we are going +and the basic functionality that we want it to do. In order to make this +tutorial maximally understandable and hackable, we choose to implement +everything in C++ instead of using lexer and parser generators. LLVM obviously +works just fine with such tools, feel free to use one if you prefer.
    • +
    • Chapter #2: Implementing a Parser and +AST - With the lexer in place, we can talk about parsing techniques and +basic AST construction. This tutorial describes recursive descent parsing and +operator precedence parsing. Nothing in Chapters 1 or 2 is LLVM-specific, +the code doesn't even link in LLVM at this point. :)
    • +
    • Chapter #3: Code generation to LLVM IR - +With the AST ready, we can show off how easy generation of LLVM IR really +is.
    • +
    • Chapter #4: Adding JIT and Optimizer +Support - Because a lot of people are interested in using LLVM as a JIT, +we'll dive right into it and show you the 3 lines it takes to add JIT support. +LLVM is also useful in many other ways, but this is one simple and "sexy" way +to shows off its power. :)
    • +
    • Chapter #5: Extending the Language: Control +Flow - With the language up and running, we show how to extend it with +control flow operations (if/then/else and a 'for' loop). This gives us a chance +to talk about simple SSA construction and control flow.
    • +
    • Chapter #6: Extending the Language: +User-defined Operators - This is a silly but fun chapter that talks about +extending the language to let the user program define their own arbitrary +unary and binary operators (with assignable precedence!). This lets us build a +significant piece of the "language" as library routines.
    • +
    • Chapter #7: Extending the Language: Mutable +Variables - This chapter talks about adding user-defined local variables +along with an assignment operator. The interesting part about this is how +easy and trivial it is to construct SSA form in LLVM: no, LLVM does not +require your front-end to construct SSA form!
    • +
    • Chapter #8: Conclusion and other useful LLVM +tidbits - This chapter wraps up the series by talking about potential +ways to extend the language, but also includes a bunch of pointers to info about +"special topics" like adding garbage collection support, exceptions, debugging, +support for "spaghetti stacks", and a bunch of other tips and tricks.
    • + +
    + +

    By the end of the tutorial, we'll have written a bit less than 700 lines of +non-comment, non-blank, lines of code. With this small amount of code, we'll +have built up a very reasonable compiler for a non-trivial language including +a hand-written lexer, parser, AST, as well as code generation support with a JIT +compiler. While other systems may have interesting "hello world" tutorials, +I think the breadth of this tutorial is a great testament to the strengths of +LLVM and why you should consider it if you're interested in language or compiler +design.

    + +

    A note about this tutorial: we expect you to extend the language and play +with it on your own. Take the code and go crazy hacking away at it, compilers +don't need to be scary creatures - it can be a lot of fun to play with +languages!

    + +
    + + + + + +
    + +

    This tutorial will be illustrated with a toy language that we'll call +"Kaleidoscope" (derived +from "meaning beautiful, form, and view"). +Kaleidoscope is a procedural language that allows you to define functions, use +conditionals, math, etc. Over the course of the tutorial, we'll extend +Kaleidoscope to support the if/then/else construct, a for loop, user defined +operators, JIT compilation with a simple command line interface, etc.

    + +

    Because we want to keep things simple, the only datatype in Kaleidoscope is a +64-bit floating point type (aka 'double' in C parlance). As such, all values +are implicitly double precision and the language doesn't require type +declarations. This gives the language a very nice and simple syntax. For +example, the following simple example computes Fibonacci numbers:

    + +
    +
    +# Compute the x'th fibonacci number.
    +def fib(x)
    +  if x < 3 then
    +    1
    +  else
    +    fib(x-1)+fib(x-2)
    +
    +# This expression will compute the 40th number.
    +fib(40)
    +
    +
    + +

    We also allow Kaleidoscope to call into standard library functions (the LLVM +JIT makes this completely trivial). This means that you can use the 'extern' +keyword to define a function before you use it (this is also useful for mutually +recursive functions). For example:

    + +
    +
    +extern sin(arg);
    +extern cos(arg);
    +extern atan2(arg1 arg2);
    +
    +atan2(sin(.4), cos(42))
    +
    +
    + +

    A more interesting example is included in Chapter 6 where we write a little +Kaleidoscope application that displays +a Mandelbrot Set at various levels of magnification.

    + +

    Lets dive into the implementation of this language!

    + +
    + + + + + +
    + +

    When it comes to implementing a language, the first thing needed is +the ability to process a text file and recognize what it says. The traditional +way to do this is to use a "lexer" (aka 'scanner') +to break the input up into "tokens". Each token returned by the lexer includes +a token code and potentially some metadata (e.g. the numeric value of a number). +First, we define the possibilities: +

    + +
    +
    +// The lexer returns tokens [0-255] if it is an unknown character, otherwise one
    +// of these for known things.
    +enum Token {
    +  tok_eof = -1,
    +
    +  // commands
    +  tok_def = -2, tok_extern = -3,
    +
    +  // primary
    +  tok_identifier = -4, tok_number = -5,
    +};
    +
    +static std::string IdentifierStr;  // Filled in if tok_identifier
    +static double NumVal;              // Filled in if tok_number
    +
    +
    + +

    Each token returned by our lexer will either be one of the Token enum values +or it will be an 'unknown' character like '+', which is returned as its ASCII +value. If the current token is an identifier, the IdentifierStr +global variable holds the name of the identifier. If the current token is a +numeric literal (like 1.0), NumVal holds its value. Note that we use +global variables for simplicity, this is not the best choice for a real language +implementation :). +

    + +

    The actual implementation of the lexer is a single function named +gettok. The gettok function is called to return the next token +from standard input. Its definition starts as:

    + +
    +
    +/// gettok - Return the next token from standard input.
    +static int gettok() {
    +  static int LastChar = ' ';
    +
    +  // Skip any whitespace.
    +  while (isspace(LastChar))
    +    LastChar = getchar();
    +
    +
    + +

    +gettok works by calling the C getchar() function to read +characters one at a time from standard input. It eats them as it recognizes +them and stores the last character read, but not processed, in LastChar. The +first thing that it has to do is ignore whitespace between tokens. This is +accomplished with the loop above.

    + +

    The next thing gettok needs to do is recognize identifiers and +specific keywords like "def". Kaleidoscope does this with this simple loop:

    + +
    +
    +  if (isalpha(LastChar)) { // identifier: [a-zA-Z][a-zA-Z0-9]*
    +    IdentifierStr = LastChar;
    +    while (isalnum((LastChar = getchar())))
    +      IdentifierStr += LastChar;
    +
    +    if (IdentifierStr == "def") return tok_def;
    +    if (IdentifierStr == "extern") return tok_extern;
    +    return tok_identifier;
    +  }
    +
    +
    + +

    Note that this code sets the 'IdentifierStr' global whenever it +lexes an identifier. Also, since language keywords are matched by the same +loop, we handle them here inline. Numeric values are similar:

    + +
    +
    +  if (isdigit(LastChar) || LastChar == '.') {   // Number: [0-9.]+
    +    std::string NumStr;
    +    do {
    +      NumStr += LastChar;
    +      LastChar = getchar();
    +    } while (isdigit(LastChar) || LastChar == '.');
    +
    +    NumVal = strtod(NumStr.c_str(), 0);
    +    return tok_number;
    +  }
    +
    +
    + +

    This is all pretty straight-forward code for processing input. When reading +a numeric value from input, we use the C strtod function to convert it +to a numeric value that we store in NumVal. Note that this isn't doing +sufficient error checking: it will incorrectly read "1.23.45.67" and handle it as +if you typed in "1.23". Feel free to extend it :). Next we handle comments: +

    + +
    +
    +  if (LastChar == '#') {
    +    // Comment until end of line.
    +    do LastChar = getchar();
    +    while (LastChar != EOF && LastChar != '\n' && LastChar != '\r');
    +    
    +    if (LastChar != EOF)
    +      return gettok();
    +  }
    +
    +
    + +

    We handle comments by skipping to the end of the line and then return the +next token. Finally, if the input doesn't match one of the above cases, it is +either an operator character like '+' or the end of the file. These are handled +with this code:

    + +
    +
    +  // Check for end of file.  Don't eat the EOF.
    +  if (LastChar == EOF)
    +    return tok_eof;
    +  
    +  // Otherwise, just return the character as its ascii value.
    +  int ThisChar = LastChar;
    +  LastChar = getchar();
    +  return ThisChar;
    +}
    +
    +
    + +

    With this, we have the complete lexer for the basic Kaleidoscope language +(the full code listing for the Lexer is +available in the next chapter of the tutorial). +Next we'll build a simple parser that uses this to +build an Abstract Syntax Tree. When we have that, we'll include a driver +so that you can use the lexer and parser together. +

    + +Next: Implementing a Parser and AST +
    + + +
    +
    + Valid CSS! + Valid HTML 4.01! + + Chris Lattner
    + The LLVM Compiler Infrastructure
    + Last modified: $Date: 2007-10-17 11:05:13 -0700 (Wed, 17 Oct 2007) $ +
    + + diff --git a/libclamav/c++/llvm/docs/tutorial/LangImpl2.html b/libclamav/c++/llvm/docs/tutorial/LangImpl2.html new file mode 100644 index 000000000..5bcd0dd2c --- /dev/null +++ b/libclamav/c++/llvm/docs/tutorial/LangImpl2.html @@ -0,0 +1,1233 @@ + + + + + Kaleidoscope: Implementing a Parser and AST + + + + + + + +
    Kaleidoscope: Implementing a Parser and AST
    + + + +
    +

    Written by Chris Lattner

    +
    + + + + + +
    + +

    Welcome to Chapter 2 of the "Implementing a language +with LLVM" tutorial. This chapter shows you how to use the lexer, built in +Chapter 1, to build a full parser for +our Kaleidoscope language. Once we have a parser, we'll define and build an Abstract Syntax +Tree (AST).

    + +

    The parser we will build uses a combination of Recursive Descent +Parsing and Operator-Precedence +Parsing to parse the Kaleidoscope language (the latter for +binary expressions and the former for everything else). Before we get to +parsing though, lets talk about the output of the parser: the Abstract Syntax +Tree.

    + +
    + + + + + +
    + +

    The AST for a program captures its behavior in such a way that it is easy for +later stages of the compiler (e.g. code generation) to interpret. We basically +want one object for each construct in the language, and the AST should closely +model the language. In Kaleidoscope, we have expressions, a prototype, and a +function object. We'll start with expressions first:

    + +
    +
    +/// ExprAST - Base class for all expression nodes.
    +class ExprAST {
    +public:
    +  virtual ~ExprAST() {}
    +};
    +
    +/// NumberExprAST - Expression class for numeric literals like "1.0".
    +class NumberExprAST : public ExprAST {
    +  double Val;
    +public:
    +  NumberExprAST(double val) : Val(val) {}
    +};
    +
    +
    + +

    The code above shows the definition of the base ExprAST class and one +subclass which we use for numeric literals. The important thing to note about +this code is that the NumberExprAST class captures the numeric value of the +literal as an instance variable. This allows later phases of the compiler to +know what the stored numeric value is.

    + +

    Right now we only create the AST, so there are no useful accessor methods on +them. It would be very easy to add a virtual method to pretty print the code, +for example. Here are the other expression AST node definitions that we'll use +in the basic form of the Kaleidoscope language: +

    + +
    +
    +/// VariableExprAST - Expression class for referencing a variable, like "a".
    +class VariableExprAST : public ExprAST {
    +  std::string Name;
    +public:
    +  VariableExprAST(const std::string &name) : Name(name) {}
    +};
    +
    +/// BinaryExprAST - Expression class for a binary operator.
    +class BinaryExprAST : public ExprAST {
    +  char Op;
    +  ExprAST *LHS, *RHS;
    +public:
    +  BinaryExprAST(char op, ExprAST *lhs, ExprAST *rhs) 
    +    : Op(op), LHS(lhs), RHS(rhs) {}
    +};
    +
    +/// CallExprAST - Expression class for function calls.
    +class CallExprAST : public ExprAST {
    +  std::string Callee;
    +  std::vector<ExprAST*> Args;
    +public:
    +  CallExprAST(const std::string &callee, std::vector<ExprAST*> &args)
    +    : Callee(callee), Args(args) {}
    +};
    +
    +
    + +

    This is all (intentionally) rather straight-forward: variables capture the +variable name, binary operators capture their opcode (e.g. '+'), and calls +capture a function name as well as a list of any argument expressions. One thing +that is nice about our AST is that it captures the language features without +talking about the syntax of the language. Note that there is no discussion about +precedence of binary operators, lexical structure, etc.

    + +

    For our basic language, these are all of the expression nodes we'll define. +Because it doesn't have conditional control flow, it isn't Turing-complete; +we'll fix that in a later installment. The two things we need next are a way +to talk about the interface to a function, and a way to talk about functions +themselves:

    + +
    +
    +/// PrototypeAST - This class represents the "prototype" for a function,
    +/// which captures its name, and its argument names (thus implicitly the number
    +/// of arguments the function takes).
    +class PrototypeAST {
    +  std::string Name;
    +  std::vector<std::string> Args;
    +public:
    +  PrototypeAST(const std::string &name, const std::vector<std::string> &args)
    +    : Name(name), Args(args) {}
    +};
    +
    +/// FunctionAST - This class represents a function definition itself.
    +class FunctionAST {
    +  PrototypeAST *Proto;
    +  ExprAST *Body;
    +public:
    +  FunctionAST(PrototypeAST *proto, ExprAST *body)
    +    : Proto(proto), Body(body) {}
    +};
    +
    +
    + +

    In Kaleidoscope, functions are typed with just a count of their arguments. +Since all values are double precision floating point, the type of each argument +doesn't need to be stored anywhere. In a more aggressive and realistic +language, the "ExprAST" class would probably have a type field.

    + +

    With this scaffolding, we can now talk about parsing expressions and function +bodies in Kaleidoscope.

    + +
    + + + + + +
    + +

    Now that we have an AST to build, we need to define the parser code to build +it. The idea here is that we want to parse something like "x+y" (which is +returned as three tokens by the lexer) into an AST that could be generated with +calls like this:

    + +
    +
    +  ExprAST *X = new VariableExprAST("x");
    +  ExprAST *Y = new VariableExprAST("y");
    +  ExprAST *Result = new BinaryExprAST('+', X, Y);
    +
    +
    + +

    In order to do this, we'll start by defining some basic helper routines:

    + +
    +
    +/// CurTok/getNextToken - Provide a simple token buffer.  CurTok is the current
    +/// token the parser is looking at.  getNextToken reads another token from the
    +/// lexer and updates CurTok with its results.
    +static int CurTok;
    +static int getNextToken() {
    +  return CurTok = gettok();
    +}
    +
    +
    + +

    +This implements a simple token buffer around the lexer. This allows +us to look one token ahead at what the lexer is returning. Every function in +our parser will assume that CurTok is the current token that needs to be +parsed.

    + +
    +
    +
    +/// Error* - These are little helper functions for error handling.
    +ExprAST *Error(const char *Str) { fprintf(stderr, "Error: %s\n", Str);return 0;}
    +PrototypeAST *ErrorP(const char *Str) { Error(Str); return 0; }
    +FunctionAST *ErrorF(const char *Str) { Error(Str); return 0; }
    +
    +
    + +

    +The Error routines are simple helper routines that our parser will use +to handle errors. The error recovery in our parser will not be the best and +is not particular user-friendly, but it will be enough for our tutorial. These +routines make it easier to handle errors in routines that have various return +types: they always return null.

    + +

    With these basic helper functions, we can implement the first +piece of our grammar: numeric literals.

    + +
    + + + + + +
    + +

    We start with numeric literals, because they are the simplest to process. +For each production in our grammar, we'll define a function which parses that +production. For numeric literals, we have: +

    + +
    +
    +/// numberexpr ::= number
    +static ExprAST *ParseNumberExpr() {
    +  ExprAST *Result = new NumberExprAST(NumVal);
    +  getNextToken(); // consume the number
    +  return Result;
    +}
    +
    +
    + +

    This routine is very simple: it expects to be called when the current token +is a tok_number token. It takes the current number value, creates +a NumberExprAST node, advances the lexer to the next token, and finally +returns.

    + +

    There are some interesting aspects to this. The most important one is that +this routine eats all of the tokens that correspond to the production and +returns the lexer buffer with the next token (which is not part of the grammar +production) ready to go. This is a fairly standard way to go for recursive +descent parsers. For a better example, the parenthesis operator is defined like +this:

    + +
    +
    +/// parenexpr ::= '(' expression ')'
    +static ExprAST *ParseParenExpr() {
    +  getNextToken();  // eat (.
    +  ExprAST *V = ParseExpression();
    +  if (!V) return 0;
    +  
    +  if (CurTok != ')')
    +    return Error("expected ')'");
    +  getNextToken();  // eat ).
    +  return V;
    +}
    +
    +
    + +

    This function illustrates a number of interesting things about the +parser:

    + +

    +1) It shows how we use the Error routines. When called, this function expects +that the current token is a '(' token, but after parsing the subexpression, it +is possible that there is no ')' waiting. For example, if the user types in +"(4 x" instead of "(4)", the parser should emit an error. Because errors can +occur, the parser needs a way to indicate that they happened: in our parser, we +return null on an error.

    + +

    2) Another interesting aspect of this function is that it uses recursion by +calling ParseExpression (we will soon see that ParseExpression can call +ParseParenExpr). This is powerful because it allows us to handle +recursive grammars, and keeps each production very simple. Note that +parentheses do not cause construction of AST nodes themselves. While we could +do it this way, the most important role of parentheses are to guide the parser +and provide grouping. Once the parser constructs the AST, parentheses are not +needed.

    + +

    The next simple production is for handling variable references and function +calls:

    + +
    +
    +/// identifierexpr
    +///   ::= identifier
    +///   ::= identifier '(' expression* ')'
    +static ExprAST *ParseIdentifierExpr() {
    +  std::string IdName = IdentifierStr;
    +  
    +  getNextToken();  // eat identifier.
    +  
    +  if (CurTok != '(') // Simple variable ref.
    +    return new VariableExprAST(IdName);
    +  
    +  // Call.
    +  getNextToken();  // eat (
    +  std::vector<ExprAST*> Args;
    +  if (CurTok != ')') {
    +    while (1) {
    +      ExprAST *Arg = ParseExpression();
    +      if (!Arg) return 0;
    +      Args.push_back(Arg);
    +
    +      if (CurTok == ')') break;
    +
    +      if (CurTok != ',')
    +        return Error("Expected ')' or ',' in argument list");
    +      getNextToken();
    +    }
    +  }
    +
    +  // Eat the ')'.
    +  getNextToken();
    +  
    +  return new CallExprAST(IdName, Args);
    +}
    +
    +
    + +

    This routine follows the same style as the other routines. (It expects to be +called if the current token is a tok_identifier token). It also has +recursion and error handling. One interesting aspect of this is that it uses +look-ahead to determine if the current identifier is a stand alone +variable reference or if it is a function call expression. It handles this by +checking to see if the token after the identifier is a '(' token, constructing +either a VariableExprAST or CallExprAST node as appropriate. +

    + +

    Now that we have all of our simple expression-parsing logic in place, we can +define a helper function to wrap it together into one entry point. We call this +class of expressions "primary" expressions, for reasons that will become more +clear later in the tutorial. In order to +parse an arbitrary primary expression, we need to determine what sort of +expression it is:

    + +
    +
    +/// primary
    +///   ::= identifierexpr
    +///   ::= numberexpr
    +///   ::= parenexpr
    +static ExprAST *ParsePrimary() {
    +  switch (CurTok) {
    +  default: return Error("unknown token when expecting an expression");
    +  case tok_identifier: return ParseIdentifierExpr();
    +  case tok_number:     return ParseNumberExpr();
    +  case '(':            return ParseParenExpr();
    +  }
    +}
    +
    +
    + +

    Now that you see the definition of this function, it is more obvious why we +can assume the state of CurTok in the various functions. This uses look-ahead +to determine which sort of expression is being inspected, and then parses it +with a function call.

    + +

    Now that basic expressions are handled, we need to handle binary expressions. +They are a bit more complex.

    + +
    + + + + + +
    + +

    Binary expressions are significantly harder to parse because they are often +ambiguous. For example, when given the string "x+y*z", the parser can choose +to parse it as either "(x+y)*z" or "x+(y*z)". With common definitions from +mathematics, we expect the later parse, because "*" (multiplication) has +higher precedence than "+" (addition).

    + +

    There are many ways to handle this, but an elegant and efficient way is to +use Operator-Precedence +Parsing. This parsing technique uses the precedence of binary operators to +guide recursion. To start with, we need a table of precedences:

    + +
    +
    +/// BinopPrecedence - This holds the precedence for each binary operator that is
    +/// defined.
    +static std::map<char, int> BinopPrecedence;
    +
    +/// GetTokPrecedence - Get the precedence of the pending binary operator token.
    +static int GetTokPrecedence() {
    +  if (!isascii(CurTok))
    +    return -1;
    +    
    +  // Make sure it's a declared binop.
    +  int TokPrec = BinopPrecedence[CurTok];
    +  if (TokPrec <= 0) return -1;
    +  return TokPrec;
    +}
    +
    +int main() {
    +  // Install standard binary operators.
    +  // 1 is lowest precedence.
    +  BinopPrecedence['<'] = 10;
    +  BinopPrecedence['+'] = 20;
    +  BinopPrecedence['-'] = 20;
    +  BinopPrecedence['*'] = 40;  // highest.
    +  ...
    +}
    +
    +
    + +

    For the basic form of Kaleidoscope, we will only support 4 binary operators +(this can obviously be extended by you, our brave and intrepid reader). The +GetTokPrecedence function returns the precedence for the current token, +or -1 if the token is not a binary operator. Having a map makes it easy to add +new operators and makes it clear that the algorithm doesn't depend on the +specific operators involved, but it would be easy enough to eliminate the map +and do the comparisons in the GetTokPrecedence function. (Or just use +a fixed-size array).

    + +

    With the helper above defined, we can now start parsing binary expressions. +The basic idea of operator precedence parsing is to break down an expression +with potentially ambiguous binary operators into pieces. Consider ,for example, +the expression "a+b+(c+d)*e*f+g". Operator precedence parsing considers this +as a stream of primary expressions separated by binary operators. As such, +it will first parse the leading primary expression "a", then it will see the +pairs [+, b] [+, (c+d)] [*, e] [*, f] and [+, g]. Note that because parentheses +are primary expressions, the binary expression parser doesn't need to worry +about nested subexpressions like (c+d) at all. +

    + +

    +To start, an expression is a primary expression potentially followed by a +sequence of [binop,primaryexpr] pairs:

    + +
    +
    +/// expression
    +///   ::= primary binoprhs
    +///
    +static ExprAST *ParseExpression() {
    +  ExprAST *LHS = ParsePrimary();
    +  if (!LHS) return 0;
    +  
    +  return ParseBinOpRHS(0, LHS);
    +}
    +
    +
    + +

    ParseBinOpRHS is the function that parses the sequence of pairs for +us. It takes a precedence and a pointer to an expression for the part that has been +parsed so far. Note that "x" is a perfectly valid expression: As such, "binoprhs" is +allowed to be empty, in which case it returns the expression that is passed into +it. In our example above, the code passes the expression for "a" into +ParseBinOpRHS and the current token is "+".

    + +

    The precedence value passed into ParseBinOpRHS indicates the +minimal operator precedence that the function is allowed to eat. For +example, if the current pair stream is [+, x] and ParseBinOpRHS is +passed in a precedence of 40, it will not consume any tokens (because the +precedence of '+' is only 20). With this in mind, ParseBinOpRHS starts +with:

    + +
    +
    +/// binoprhs
    +///   ::= ('+' primary)*
    +static ExprAST *ParseBinOpRHS(int ExprPrec, ExprAST *LHS) {
    +  // If this is a binop, find its precedence.
    +  while (1) {
    +    int TokPrec = GetTokPrecedence();
    +    
    +    // If this is a binop that binds at least as tightly as the current binop,
    +    // consume it, otherwise we are done.
    +    if (TokPrec < ExprPrec)
    +      return LHS;
    +
    +
    + +

    This code gets the precedence of the current token and checks to see if if is +too low. Because we defined invalid tokens to have a precedence of -1, this +check implicitly knows that the pair-stream ends when the token stream runs out +of binary operators. If this check succeeds, we know that the token is a binary +operator and that it will be included in this expression:

    + +
    +
    +    // Okay, we know this is a binop.
    +    int BinOp = CurTok;
    +    getNextToken();  // eat binop
    +    
    +    // Parse the primary expression after the binary operator.
    +    ExprAST *RHS = ParsePrimary();
    +    if (!RHS) return 0;
    +
    +
    + +

    As such, this code eats (and remembers) the binary operator and then parses +the primary expression that follows. This builds up the whole pair, the first of +which is [+, b] for the running example.

    + +

    Now that we parsed the left-hand side of an expression and one pair of the +RHS sequence, we have to decide which way the expression associates. In +particular, we could have "(a+b) binop unparsed" or "a + (b binop unparsed)". +To determine this, we look ahead at "binop" to determine its precedence and +compare it to BinOp's precedence (which is '+' in this case):

    + +
    +
    +    // If BinOp binds less tightly with RHS than the operator after RHS, let
    +    // the pending operator take RHS as its LHS.
    +    int NextPrec = GetTokPrecedence();
    +    if (TokPrec < NextPrec) {
    +
    +
    + +

    If the precedence of the binop to the right of "RHS" is lower or equal to the +precedence of our current operator, then we know that the parentheses associate +as "(a+b) binop ...". In our example, the current operator is "+" and the next +operator is "+", we know that they have the same precedence. In this case we'll +create the AST node for "a+b", and then continue parsing:

    + +
    +
    +      ... if body omitted ...
    +    }
    +    
    +    // Merge LHS/RHS.
    +    LHS = new BinaryExprAST(BinOp, LHS, RHS);
    +  }  // loop around to the top of the while loop.
    +}
    +
    +
    + +

    In our example above, this will turn "a+b+" into "(a+b)" and execute the next +iteration of the loop, with "+" as the current token. The code above will eat, +remember, and parse "(c+d)" as the primary expression, which makes the +current pair equal to [+, (c+d)]. It will then evaluate the 'if' conditional above with +"*" as the binop to the right of the primary. In this case, the precedence of "*" is +higher than the precedence of "+" so the if condition will be entered.

    + +

    The critical question left here is "how can the if condition parse the right +hand side in full"? In particular, to build the AST correctly for our example, +it needs to get all of "(c+d)*e*f" as the RHS expression variable. The code to +do this is surprisingly simple (code from the above two blocks duplicated for +context):

    + +
    +
    +    // If BinOp binds less tightly with RHS than the operator after RHS, let
    +    // the pending operator take RHS as its LHS.
    +    int NextPrec = GetTokPrecedence();
    +    if (TokPrec < NextPrec) {
    +      RHS = ParseBinOpRHS(TokPrec+1, RHS);
    +      if (RHS == 0) return 0;
    +    }
    +    // Merge LHS/RHS.
    +    LHS = new BinaryExprAST(BinOp, LHS, RHS);
    +  }  // loop around to the top of the while loop.
    +}
    +
    +
    + +

    At this point, we know that the binary operator to the RHS of our primary +has higher precedence than the binop we are currently parsing. As such, we know +that any sequence of pairs whose operators are all higher precedence than "+" +should be parsed together and returned as "RHS". To do this, we recursively +invoke the ParseBinOpRHS function specifying "TokPrec+1" as the minimum +precedence required for it to continue. In our example above, this will cause +it to return the AST node for "(c+d)*e*f" as RHS, which is then set as the RHS +of the '+' expression.

    + +

    Finally, on the next iteration of the while loop, the "+g" piece is parsed +and added to the AST. With this little bit of code (14 non-trivial lines), we +correctly handle fully general binary expression parsing in a very elegant way. +This was a whirlwind tour of this code, and it is somewhat subtle. I recommend +running through it with a few tough examples to see how it works. +

    + +

    This wraps up handling of expressions. At this point, we can point the +parser at an arbitrary token stream and build an expression from it, stopping +at the first token that is not part of the expression. Next up we need to +handle function definitions, etc.

    + +
    + + + + + +
    + +

    +The next thing missing is handling of function prototypes. In Kaleidoscope, +these are used both for 'extern' function declarations as well as function body +definitions. The code to do this is straight-forward and not very interesting +(once you've survived expressions): +

    + +
    +
    +/// prototype
    +///   ::= id '(' id* ')'
    +static PrototypeAST *ParsePrototype() {
    +  if (CurTok != tok_identifier)
    +    return ErrorP("Expected function name in prototype");
    +
    +  std::string FnName = IdentifierStr;
    +  getNextToken();
    +  
    +  if (CurTok != '(')
    +    return ErrorP("Expected '(' in prototype");
    +  
    +  // Read the list of argument names.
    +  std::vector<std::string> ArgNames;
    +  while (getNextToken() == tok_identifier)
    +    ArgNames.push_back(IdentifierStr);
    +  if (CurTok != ')')
    +    return ErrorP("Expected ')' in prototype");
    +  
    +  // success.
    +  getNextToken();  // eat ')'.
    +  
    +  return new PrototypeAST(FnName, ArgNames);
    +}
    +
    +
    + +

    Given this, a function definition is very simple, just a prototype plus +an expression to implement the body:

    + +
    +
    +/// definition ::= 'def' prototype expression
    +static FunctionAST *ParseDefinition() {
    +  getNextToken();  // eat def.
    +  PrototypeAST *Proto = ParsePrototype();
    +  if (Proto == 0) return 0;
    +
    +  if (ExprAST *E = ParseExpression())
    +    return new FunctionAST(Proto, E);
    +  return 0;
    +}
    +
    +
    + +

    In addition, we support 'extern' to declare functions like 'sin' and 'cos' as +well as to support forward declaration of user functions. These 'extern's are just +prototypes with no body:

    + +
    +
    +/// external ::= 'extern' prototype
    +static PrototypeAST *ParseExtern() {
    +  getNextToken();  // eat extern.
    +  return ParsePrototype();
    +}
    +
    +
    + +

    Finally, we'll also let the user type in arbitrary top-level expressions and +evaluate them on the fly. We will handle this by defining anonymous nullary +(zero argument) functions for them:

    + +
    +
    +/// toplevelexpr ::= expression
    +static FunctionAST *ParseTopLevelExpr() {
    +  if (ExprAST *E = ParseExpression()) {
    +    // Make an anonymous proto.
    +    PrototypeAST *Proto = new PrototypeAST("", std::vector<std::string>());
    +    return new FunctionAST(Proto, E);
    +  }
    +  return 0;
    +}
    +
    +
    + +

    Now that we have all the pieces, let's build a little driver that will let us +actually execute this code we've built!

    + +
    + + + + + +
    + +

    The driver for this simply invokes all of the parsing pieces with a top-level +dispatch loop. There isn't much interesting here, so I'll just include the +top-level loop. See below for full code in the "Top-Level +Parsing" section.

    + +
    +
    +/// top ::= definition | external | expression | ';'
    +static void MainLoop() {
    +  while (1) {
    +    fprintf(stderr, "ready> ");
    +    switch (CurTok) {
    +    case tok_eof:    return;
    +    case ';':        getNextToken(); break;  // ignore top-level semicolons.
    +    case tok_def:    HandleDefinition(); break;
    +    case tok_extern: HandleExtern(); break;
    +    default:         HandleTopLevelExpression(); break;
    +    }
    +  }
    +}
    +
    +
    + +

    The most interesting part of this is that we ignore top-level semicolons. +Why is this, you ask? The basic reason is that if you type "4 + 5" at the +command line, the parser doesn't know whether that is the end of what you will type +or not. For example, on the next line you could type "def foo..." in which case +4+5 is the end of a top-level expression. Alternatively you could type "* 6", +which would continue the expression. Having top-level semicolons allows you to +type "4+5;", and the parser will know you are done.

    + +
    + + + + + +
    + +

    With just under 400 lines of commented code (240 lines of non-comment, +non-blank code), we fully defined our minimal language, including a lexer, +parser, and AST builder. With this done, the executable will validate +Kaleidoscope code and tell us if it is grammatically invalid. For +example, here is a sample interaction:

    + +
    +
    +$ ./a.out
    +ready> def foo(x y) x+foo(y, 4.0);
    +Parsed a function definition.
    +ready> def foo(x y) x+y y;
    +Parsed a function definition.
    +Parsed a top-level expr
    +ready> def foo(x y) x+y );
    +Parsed a function definition.
    +Error: unknown token when expecting an expression
    +ready> extern sin(a);
    +ready> Parsed an extern
    +ready> ^D
    +$ 
    +
    +
    + +

    There is a lot of room for extension here. You can define new AST nodes, +extend the language in many ways, etc. In the next +installment, we will describe how to generate LLVM Intermediate +Representation (IR) from the AST.

    + +
    + + + + + +
    + +

    +Here is the complete code listing for this and the previous chapter. +Note that it is fully self-contained: you don't need LLVM or any external +libraries at all for this. (Besides the C and C++ standard libraries, of +course.) To build this, just compile with:

    + +
    +
    +   # Compile
    +   g++ -g -O3 toy.cpp 
    +   # Run
    +   ./a.out 
    +
    +
    + +

    Here is the code:

    + +
    +
    +#include <cstdio>
    +#include <cstdlib>
    +#include <string>
    +#include <map>
    +#include <vector>
    +
    +//===----------------------------------------------------------------------===//
    +// Lexer
    +//===----------------------------------------------------------------------===//
    +
    +// The lexer returns tokens [0-255] if it is an unknown character, otherwise one
    +// of these for known things.
    +enum Token {
    +  tok_eof = -1,
    +
    +  // commands
    +  tok_def = -2, tok_extern = -3,
    +
    +  // primary
    +  tok_identifier = -4, tok_number = -5
    +};
    +
    +static std::string IdentifierStr;  // Filled in if tok_identifier
    +static double NumVal;              // Filled in if tok_number
    +
    +/// gettok - Return the next token from standard input.
    +static int gettok() {
    +  static int LastChar = ' ';
    +
    +  // Skip any whitespace.
    +  while (isspace(LastChar))
    +    LastChar = getchar();
    +
    +  if (isalpha(LastChar)) { // identifier: [a-zA-Z][a-zA-Z0-9]*
    +    IdentifierStr = LastChar;
    +    while (isalnum((LastChar = getchar())))
    +      IdentifierStr += LastChar;
    +
    +    if (IdentifierStr == "def") return tok_def;
    +    if (IdentifierStr == "extern") return tok_extern;
    +    return tok_identifier;
    +  }
    +
    +  if (isdigit(LastChar) || LastChar == '.') {   // Number: [0-9.]+
    +    std::string NumStr;
    +    do {
    +      NumStr += LastChar;
    +      LastChar = getchar();
    +    } while (isdigit(LastChar) || LastChar == '.');
    +
    +    NumVal = strtod(NumStr.c_str(), 0);
    +    return tok_number;
    +  }
    +
    +  if (LastChar == '#') {
    +    // Comment until end of line.
    +    do LastChar = getchar();
    +    while (LastChar != EOF && LastChar != '\n' && LastChar != '\r');
    +    
    +    if (LastChar != EOF)
    +      return gettok();
    +  }
    +  
    +  // Check for end of file.  Don't eat the EOF.
    +  if (LastChar == EOF)
    +    return tok_eof;
    +
    +  // Otherwise, just return the character as its ascii value.
    +  int ThisChar = LastChar;
    +  LastChar = getchar();
    +  return ThisChar;
    +}
    +
    +//===----------------------------------------------------------------------===//
    +// Abstract Syntax Tree (aka Parse Tree)
    +//===----------------------------------------------------------------------===//
    +
    +/// ExprAST - Base class for all expression nodes.
    +class ExprAST {
    +public:
    +  virtual ~ExprAST() {}
    +};
    +
    +/// NumberExprAST - Expression class for numeric literals like "1.0".
    +class NumberExprAST : public ExprAST {
    +  double Val;
    +public:
    +  NumberExprAST(double val) : Val(val) {}
    +};
    +
    +/// VariableExprAST - Expression class for referencing a variable, like "a".
    +class VariableExprAST : public ExprAST {
    +  std::string Name;
    +public:
    +  VariableExprAST(const std::string &name) : Name(name) {}
    +};
    +
    +/// BinaryExprAST - Expression class for a binary operator.
    +class BinaryExprAST : public ExprAST {
    +  char Op;
    +  ExprAST *LHS, *RHS;
    +public:
    +  BinaryExprAST(char op, ExprAST *lhs, ExprAST *rhs) 
    +    : Op(op), LHS(lhs), RHS(rhs) {}
    +};
    +
    +/// CallExprAST - Expression class for function calls.
    +class CallExprAST : public ExprAST {
    +  std::string Callee;
    +  std::vector<ExprAST*> Args;
    +public:
    +  CallExprAST(const std::string &callee, std::vector<ExprAST*> &args)
    +    : Callee(callee), Args(args) {}
    +};
    +
    +/// PrototypeAST - This class represents the "prototype" for a function,
    +/// which captures its name, and its argument names (thus implicitly the number
    +/// of arguments the function takes).
    +class PrototypeAST {
    +  std::string Name;
    +  std::vector<std::string> Args;
    +public:
    +  PrototypeAST(const std::string &name, const std::vector<std::string> &args)
    +    : Name(name), Args(args) {}
    +  
    +};
    +
    +/// FunctionAST - This class represents a function definition itself.
    +class FunctionAST {
    +  PrototypeAST *Proto;
    +  ExprAST *Body;
    +public:
    +  FunctionAST(PrototypeAST *proto, ExprAST *body)
    +    : Proto(proto), Body(body) {}
    +  
    +};
    +
    +//===----------------------------------------------------------------------===//
    +// Parser
    +//===----------------------------------------------------------------------===//
    +
    +/// CurTok/getNextToken - Provide a simple token buffer.  CurTok is the current
    +/// token the parser is looking at.  getNextToken reads another token from the
    +/// lexer and updates CurTok with its results.
    +static int CurTok;
    +static int getNextToken() {
    +  return CurTok = gettok();
    +}
    +
    +/// BinopPrecedence - This holds the precedence for each binary operator that is
    +/// defined.
    +static std::map<char, int> BinopPrecedence;
    +
    +/// GetTokPrecedence - Get the precedence of the pending binary operator token.
    +static int GetTokPrecedence() {
    +  if (!isascii(CurTok))
    +    return -1;
    +  
    +  // Make sure it's a declared binop.
    +  int TokPrec = BinopPrecedence[CurTok];
    +  if (TokPrec <= 0) return -1;
    +  return TokPrec;
    +}
    +
    +/// Error* - These are little helper functions for error handling.
    +ExprAST *Error(const char *Str) { fprintf(stderr, "Error: %s\n", Str);return 0;}
    +PrototypeAST *ErrorP(const char *Str) { Error(Str); return 0; }
    +FunctionAST *ErrorF(const char *Str) { Error(Str); return 0; }
    +
    +static ExprAST *ParseExpression();
    +
    +/// identifierexpr
    +///   ::= identifier
    +///   ::= identifier '(' expression* ')'
    +static ExprAST *ParseIdentifierExpr() {
    +  std::string IdName = IdentifierStr;
    +  
    +  getNextToken();  // eat identifier.
    +  
    +  if (CurTok != '(') // Simple variable ref.
    +    return new VariableExprAST(IdName);
    +  
    +  // Call.
    +  getNextToken();  // eat (
    +  std::vector<ExprAST*> Args;
    +  if (CurTok != ')') {
    +    while (1) {
    +      ExprAST *Arg = ParseExpression();
    +      if (!Arg) return 0;
    +      Args.push_back(Arg);
    +
    +      if (CurTok == ')') break;
    +
    +      if (CurTok != ',')
    +        return Error("Expected ')' or ',' in argument list");
    +      getNextToken();
    +    }
    +  }
    +
    +  // Eat the ')'.
    +  getNextToken();
    +  
    +  return new CallExprAST(IdName, Args);
    +}
    +
    +/// numberexpr ::= number
    +static ExprAST *ParseNumberExpr() {
    +  ExprAST *Result = new NumberExprAST(NumVal);
    +  getNextToken(); // consume the number
    +  return Result;
    +}
    +
    +/// parenexpr ::= '(' expression ')'
    +static ExprAST *ParseParenExpr() {
    +  getNextToken();  // eat (.
    +  ExprAST *V = ParseExpression();
    +  if (!V) return 0;
    +  
    +  if (CurTok != ')')
    +    return Error("expected ')'");
    +  getNextToken();  // eat ).
    +  return V;
    +}
    +
    +/// primary
    +///   ::= identifierexpr
    +///   ::= numberexpr
    +///   ::= parenexpr
    +static ExprAST *ParsePrimary() {
    +  switch (CurTok) {
    +  default: return Error("unknown token when expecting an expression");
    +  case tok_identifier: return ParseIdentifierExpr();
    +  case tok_number:     return ParseNumberExpr();
    +  case '(':            return ParseParenExpr();
    +  }
    +}
    +
    +/// binoprhs
    +///   ::= ('+' primary)*
    +static ExprAST *ParseBinOpRHS(int ExprPrec, ExprAST *LHS) {
    +  // If this is a binop, find its precedence.
    +  while (1) {
    +    int TokPrec = GetTokPrecedence();
    +    
    +    // If this is a binop that binds at least as tightly as the current binop,
    +    // consume it, otherwise we are done.
    +    if (TokPrec < ExprPrec)
    +      return LHS;
    +    
    +    // Okay, we know this is a binop.
    +    int BinOp = CurTok;
    +    getNextToken();  // eat binop
    +    
    +    // Parse the primary expression after the binary operator.
    +    ExprAST *RHS = ParsePrimary();
    +    if (!RHS) return 0;
    +    
    +    // If BinOp binds less tightly with RHS than the operator after RHS, let
    +    // the pending operator take RHS as its LHS.
    +    int NextPrec = GetTokPrecedence();
    +    if (TokPrec < NextPrec) {
    +      RHS = ParseBinOpRHS(TokPrec+1, RHS);
    +      if (RHS == 0) return 0;
    +    }
    +    
    +    // Merge LHS/RHS.
    +    LHS = new BinaryExprAST(BinOp, LHS, RHS);
    +  }
    +}
    +
    +/// expression
    +///   ::= primary binoprhs
    +///
    +static ExprAST *ParseExpression() {
    +  ExprAST *LHS = ParsePrimary();
    +  if (!LHS) return 0;
    +  
    +  return ParseBinOpRHS(0, LHS);
    +}
    +
    +/// prototype
    +///   ::= id '(' id* ')'
    +static PrototypeAST *ParsePrototype() {
    +  if (CurTok != tok_identifier)
    +    return ErrorP("Expected function name in prototype");
    +
    +  std::string FnName = IdentifierStr;
    +  getNextToken();
    +  
    +  if (CurTok != '(')
    +    return ErrorP("Expected '(' in prototype");
    +  
    +  std::vector<std::string> ArgNames;
    +  while (getNextToken() == tok_identifier)
    +    ArgNames.push_back(IdentifierStr);
    +  if (CurTok != ')')
    +    return ErrorP("Expected ')' in prototype");
    +  
    +  // success.
    +  getNextToken();  // eat ')'.
    +  
    +  return new PrototypeAST(FnName, ArgNames);
    +}
    +
    +/// definition ::= 'def' prototype expression
    +static FunctionAST *ParseDefinition() {
    +  getNextToken();  // eat def.
    +  PrototypeAST *Proto = ParsePrototype();
    +  if (Proto == 0) return 0;
    +
    +  if (ExprAST *E = ParseExpression())
    +    return new FunctionAST(Proto, E);
    +  return 0;
    +}
    +
    +/// toplevelexpr ::= expression
    +static FunctionAST *ParseTopLevelExpr() {
    +  if (ExprAST *E = ParseExpression()) {
    +    // Make an anonymous proto.
    +    PrototypeAST *Proto = new PrototypeAST("", std::vector<std::string>());
    +    return new FunctionAST(Proto, E);
    +  }
    +  return 0;
    +}
    +
    +/// external ::= 'extern' prototype
    +static PrototypeAST *ParseExtern() {
    +  getNextToken();  // eat extern.
    +  return ParsePrototype();
    +}
    +
    +//===----------------------------------------------------------------------===//
    +// Top-Level parsing
    +//===----------------------------------------------------------------------===//
    +
    +static void HandleDefinition() {
    +  if (ParseDefinition()) {
    +    fprintf(stderr, "Parsed a function definition.\n");
    +  } else {
    +    // Skip token for error recovery.
    +    getNextToken();
    +  }
    +}
    +
    +static void HandleExtern() {
    +  if (ParseExtern()) {
    +    fprintf(stderr, "Parsed an extern\n");
    +  } else {
    +    // Skip token for error recovery.
    +    getNextToken();
    +  }
    +}
    +
    +static void HandleTopLevelExpression() {
    +  // Evaluate a top-level expression into an anonymous function.
    +  if (ParseTopLevelExpr()) {
    +    fprintf(stderr, "Parsed a top-level expr\n");
    +  } else {
    +    // Skip token for error recovery.
    +    getNextToken();
    +  }
    +}
    +
    +/// top ::= definition | external | expression | ';'
    +static void MainLoop() {
    +  while (1) {
    +    fprintf(stderr, "ready> ");
    +    switch (CurTok) {
    +    case tok_eof:    return;
    +    case ';':        getNextToken(); break;  // ignore top-level semicolons.
    +    case tok_def:    HandleDefinition(); break;
    +    case tok_extern: HandleExtern(); break;
    +    default:         HandleTopLevelExpression(); break;
    +    }
    +  }
    +}
    +
    +//===----------------------------------------------------------------------===//
    +// Main driver code.
    +//===----------------------------------------------------------------------===//
    +
    +int main() {
    +  // Install standard binary operators.
    +  // 1 is lowest precedence.
    +  BinopPrecedence['<'] = 10;
    +  BinopPrecedence['+'] = 20;
    +  BinopPrecedence['-'] = 20;
    +  BinopPrecedence['*'] = 40;  // highest.
    +
    +  // Prime the first token.
    +  fprintf(stderr, "ready> ");
    +  getNextToken();
    +
    +  // Run the main "interpreter loop" now.
    +  MainLoop();
    +
    +  return 0;
    +}
    +
    +
    +Next: Implementing Code Generation to LLVM IR +
    + + +
    +
    + Valid CSS! + Valid HTML 4.01! + + Chris Lattner
    + The LLVM Compiler Infrastructure
    + Last modified: $Date: 2007-10-17 11:05:13 -0700 (Wed, 17 Oct 2007) $ +
    + + diff --git a/libclamav/c++/llvm/docs/tutorial/LangImpl3.html b/libclamav/c++/llvm/docs/tutorial/LangImpl3.html new file mode 100644 index 000000000..e3d2117c4 --- /dev/null +++ b/libclamav/c++/llvm/docs/tutorial/LangImpl3.html @@ -0,0 +1,1269 @@ + + + + + Kaleidoscope: Implementing code generation to LLVM IR + + + + + + + +
    Kaleidoscope: Code generation to LLVM IR
    + + + +
    +

    Written by Chris Lattner

    +
    + + + + + +
    + +

    Welcome to Chapter 3 of the "Implementing a language +with LLVM" tutorial. This chapter shows you how to transform the Abstract Syntax Tree, built in Chapter 2, into LLVM IR. +This will teach you a little bit about how LLVM does things, as well as +demonstrate how easy it is to use. It's much more work to build a lexer and +parser than it is to generate LLVM IR code. :) +

    + +

    Please note: the code in this chapter and later require LLVM 2.2 or +later. LLVM 2.1 and before will not work with it. Also note that you need +to use a version of this tutorial that matches your LLVM release: If you are +using an official LLVM release, use the version of the documentation included +with your release or on the llvm.org +releases page.

    + +
    + + + + + +
    + +

    +In order to generate LLVM IR, we want some simple setup to get started. First +we define virtual code generation (codegen) methods in each AST class:

    + +
    +
    +/// ExprAST - Base class for all expression nodes.
    +class ExprAST {
    +public:
    +  virtual ~ExprAST() {}
    +  virtual Value *Codegen() = 0;
    +};
    +
    +/// NumberExprAST - Expression class for numeric literals like "1.0".
    +class NumberExprAST : public ExprAST {
    +  double Val;
    +public:
    +  NumberExprAST(double val) : Val(val) {}
    +  virtual Value *Codegen();
    +};
    +...
    +
    +
    + +

    The Codegen() method says to emit IR for that AST node along with all the things it +depends on, and they all return an LLVM Value object. +"Value" is the class used to represent a "Static Single +Assignment (SSA) register" or "SSA value" in LLVM. The most distinct aspect +of SSA values is that their value is computed as the related instruction +executes, and it does not get a new value until (and if) the instruction +re-executes. In other words, there is no way to "change" an SSA value. For +more information, please read up on Static Single +Assignment - the concepts are really quite natural once you grok them.

    + +

    Note that instead of adding virtual methods to the ExprAST class hierarchy, +it could also make sense to use a visitor pattern or some +other way to model this. Again, this tutorial won't dwell on good software +engineering practices: for our purposes, adding a virtual method is +simplest.

    + +

    The +second thing we want is an "Error" method like we used for the parser, which will +be used to report errors found during code generation (for example, use of an +undeclared parameter):

    + +
    +
    +Value *ErrorV(const char *Str) { Error(Str); return 0; }
    +
    +static Module *TheModule;
    +static IRBuilder<> Builder(getGlobalContext());
    +static std::map<std::string, Value*> NamedValues;
    +
    +
    + +

    The static variables will be used during code generation. TheModule +is the LLVM construct that contains all of the functions and global variables in +a chunk of code. In many ways, it is the top-level structure that the LLVM IR +uses to contain code.

    + +

    The Builder object is a helper object that makes it easy to generate +LLVM instructions. Instances of the IRBuilder +class template keep track of the current place to insert instructions and has +methods to create new instructions.

    + +

    The NamedValues map keeps track of which values are defined in the +current scope and what their LLVM representation is. (In other words, it is a +symbol table for the code). In this form of Kaleidoscope, the only things that +can be referenced are function parameters. As such, function parameters will +be in this map when generating code for their function body.

    + +

    +With these basics in place, we can start talking about how to generate code for +each expression. Note that this assumes that the Builder has been set +up to generate code into something. For now, we'll assume that this +has already been done, and we'll just use it to emit code. +

    + +
    + + + + + +
    + +

    Generating LLVM code for expression nodes is very straightforward: less +than 45 lines of commented code for all four of our expression nodes. First +we'll do numeric literals:

    + +
    +
    +Value *NumberExprAST::Codegen() {
    +  return ConstantFP::get(getGlobalContext(), APFloat(Val));
    +}
    +
    +
    + +

    In the LLVM IR, numeric constants are represented with the +ConstantFP class, which holds the numeric value in an APFloat +internally (APFloat has the capability of holding floating point +constants of Arbitrary Precision). This code basically just +creates and returns a ConstantFP. Note that in the LLVM IR +that constants are all uniqued together and shared. For this reason, the API +uses "the Context.get..." idiom instead of "new foo(..)" or "foo::Create(..)".

    + +
    +
    +Value *VariableExprAST::Codegen() {
    +  // Look this variable up in the function.
    +  Value *V = NamedValues[Name];
    +  return V ? V : ErrorV("Unknown variable name");
    +}
    +
    +
    + +

    References to variables are also quite simple using LLVM. In the simple version +of Kaleidoscope, we assume that the variable has already been emitted somewhere +and its value is available. In practice, the only values that can be in the +NamedValues map are function arguments. This +code simply checks to see that the specified name is in the map (if not, an +unknown variable is being referenced) and returns the value for it. In future +chapters, we'll add support for loop induction +variables in the symbol table, and for local variables.

    + +
    +
    +Value *BinaryExprAST::Codegen() {
    +  Value *L = LHS->Codegen();
    +  Value *R = RHS->Codegen();
    +  if (L == 0 || R == 0) return 0;
    +  
    +  switch (Op) {
    +  case '+': return Builder.CreateAdd(L, R, "addtmp");
    +  case '-': return Builder.CreateSub(L, R, "subtmp");
    +  case '*': return Builder.CreateMul(L, R, "multmp");
    +  case '<':
    +    L = Builder.CreateFCmpULT(L, R, "cmptmp");
    +    // Convert bool 0/1 to double 0.0 or 1.0
    +    return Builder.CreateUIToFP(L, Type::getDoubleTy(getGlobalContext()),
    +                                "booltmp");
    +  default: return ErrorV("invalid binary operator");
    +  }
    +}
    +
    +
    + +

    Binary operators start to get more interesting. The basic idea here is that +we recursively emit code for the left-hand side of the expression, then the +right-hand side, then we compute the result of the binary expression. In this +code, we do a simple switch on the opcode to create the right LLVM instruction. +

    + +

    In the example above, the LLVM builder class is starting to show its value. +IRBuilder knows where to insert the newly created instruction, all you have to +do is specify what instruction to create (e.g. with CreateAdd), which +operands to use (L and R here) and optionally provide a name +for the generated instruction.

    + +

    One nice thing about LLVM is that the name is just a hint. For instance, if +the code above emits multiple "addtmp" variables, LLVM will automatically +provide each one with an increasing, unique numeric suffix. Local value names +for instructions are purely optional, but it makes it much easier to read the +IR dumps.

    + +

    LLVM instructions are constrained by +strict rules: for example, the Left and Right operators of +an add instruction must have the same +type, and the result type of the add must match the operand types. Because +all values in Kaleidoscope are doubles, this makes for very simple code for add, +sub and mul.

    + +

    On the other hand, LLVM specifies that the fcmp instruction always returns an 'i1' value +(a one bit integer). The problem with this is that Kaleidoscope wants the value to be a 0.0 or 1.0 value. In order to get these semantics, we combine the fcmp instruction with +a uitofp instruction. This instruction +converts its input integer into a floating point value by treating the input +as an unsigned value. In contrast, if we used the sitofp instruction, the Kaleidoscope '<' +operator would return 0.0 and -1.0, depending on the input value.

    + +
    +
    +Value *CallExprAST::Codegen() {
    +  // Look up the name in the global module table.
    +  Function *CalleeF = TheModule->getFunction(Callee);
    +  if (CalleeF == 0)
    +    return ErrorV("Unknown function referenced");
    +  
    +  // If argument mismatch error.
    +  if (CalleeF->arg_size() != Args.size())
    +    return ErrorV("Incorrect # arguments passed");
    +
    +  std::vector<Value*> ArgsV;
    +  for (unsigned i = 0, e = Args.size(); i != e; ++i) {
    +    ArgsV.push_back(Args[i]->Codegen());
    +    if (ArgsV.back() == 0) return 0;
    +  }
    +  
    +  return Builder.CreateCall(CalleeF, ArgsV.begin(), ArgsV.end(), "calltmp");
    +}
    +
    +
    + +

    Code generation for function calls is quite straightforward with LLVM. The +code above initially does a function name lookup in the LLVM Module's symbol +table. Recall that the LLVM Module is the container that holds all of the +functions we are JIT'ing. By giving each function the same name as what the +user specifies, we can use the LLVM symbol table to resolve function names for +us.

    + +

    Once we have the function to call, we recursively codegen each argument that +is to be passed in, and create an LLVM call +instruction. Note that LLVM uses the native C calling conventions by +default, allowing these calls to also call into standard library functions like +"sin" and "cos", with no additional effort.

    + +

    This wraps up our handling of the four basic expressions that we have so far +in Kaleidoscope. Feel free to go in and add some more. For example, by +browsing the LLVM language reference you'll find +several other interesting instructions that are really easy to plug into our +basic framework.

    + +
    + + + + + +
    + +

    Code generation for prototypes and functions must handle a number of +details, which make their code less beautiful than expression code +generation, but allows us to illustrate some important points. First, lets +talk about code generation for prototypes: they are used both for function +bodies and external function declarations. The code starts with:

    + +
    +
    +Function *PrototypeAST::Codegen() {
    +  // Make the function type:  double(double,double) etc.
    +  std::vector<const Type*> Doubles(Args.size(),
    +                                   Type::getDoubleTy(getGlobalContext()));
    +  FunctionType *FT = FunctionType::get(Type::getDoubleTy(getGlobalContext()),
    +                                       Doubles, false);
    +  
    +  Function *F = Function::Create(FT, Function::ExternalLinkage, Name, TheModule);
    +
    +
    + +

    This code packs a lot of power into a few lines. Note first that this +function returns a "Function*" instead of a "Value*". Because a "prototype" +really talks about the external interface for a function (not the value computed +by an expression), it makes sense for it to return the LLVM Function it +corresponds to when codegen'd.

    + +

    The call to Context.get creates +the FunctionType that should be used for a given Prototype. Since all +function arguments in Kaleidoscope are of type double, the first line creates +a vector of "N" LLVM double types. It then uses the Context.get +method to create a function type that takes "N" doubles as arguments, returns +one double as a result, and that is not vararg (the false parameter indicates +this). Note that Types in LLVM are uniqued just like Constants are, so you +don't "new" a type, you "get" it.

    + +

    The final line above actually creates the function that the prototype will +correspond to. This indicates the type, linkage and name to use, as well as which +module to insert into. "external linkage" +means that the function may be defined outside the current module and/or that it +is callable by functions outside the module. The Name passed in is the name the +user specified: since "TheModule" is specified, this name is registered +in "TheModule"s symbol table, which is used by the function call code +above.

    + +
    +
    +  // If F conflicted, there was already something named 'Name'.  If it has a
    +  // body, don't allow redefinition or reextern.
    +  if (F->getName() != Name) {
    +    // Delete the one we just made and get the existing one.
    +    F->eraseFromParent();
    +    F = TheModule->getFunction(Name);
    +
    +
    + +

    The Module symbol table works just like the Function symbol table when it +comes to name conflicts: if a new function is created with a name was previously +added to the symbol table, it will get implicitly renamed when added to the +Module. The code above exploits this fact to determine if there was a previous +definition of this function.

    + +

    In Kaleidoscope, I choose to allow redefinitions of functions in two cases: +first, we want to allow 'extern'ing a function more than once, as long as the +prototypes for the externs match (since all arguments have the same type, we +just have to check that the number of arguments match). Second, we want to +allow 'extern'ing a function and then defining a body for it. This is useful +when defining mutually recursive functions.

    + +

    In order to implement this, the code above first checks to see if there is +a collision on the name of the function. If so, it deletes the function we just +created (by calling eraseFromParent) and then calling +getFunction to get the existing function with the specified name. Note +that many APIs in LLVM have "erase" forms and "remove" forms. The "remove" form +unlinks the object from its parent (e.g. a Function from a Module) and returns +it. The "erase" form unlinks the object and then deletes it.

    + +
    +
    +    // If F already has a body, reject this.
    +    if (!F->empty()) {
    +      ErrorF("redefinition of function");
    +      return 0;
    +    }
    +    
    +    // If F took a different number of args, reject.
    +    if (F->arg_size() != Args.size()) {
    +      ErrorF("redefinition of function with different # args");
    +      return 0;
    +    }
    +  }
    +
    +
    + +

    In order to verify the logic above, we first check to see if the pre-existing +function is "empty". In this case, empty means that it has no basic blocks in +it, which means it has no body. If it has no body, it is a forward +declaration. Since we don't allow anything after a full definition of the +function, the code rejects this case. If the previous reference to a function +was an 'extern', we simply verify that the number of arguments for that +definition and this one match up. If not, we emit an error.

    + +
    +
    +  // Set names for all arguments.
    +  unsigned Idx = 0;
    +  for (Function::arg_iterator AI = F->arg_begin(); Idx != Args.size();
    +       ++AI, ++Idx) {
    +    AI->setName(Args[Idx]);
    +    
    +    // Add arguments to variable symbol table.
    +    NamedValues[Args[Idx]] = AI;
    +  }
    +  return F;
    +}
    +
    +
    + +

    The last bit of code for prototypes loops over all of the arguments in the +function, setting the name of the LLVM Argument objects to match, and registering +the arguments in the NamedValues map for future use by the +VariableExprAST AST node. Once this is set up, it returns the Function +object to the caller. Note that we don't check for conflicting +argument names here (e.g. "extern foo(a b a)"). Doing so would be very +straight-forward with the mechanics we have already used above.

    + +
    +
    +Function *FunctionAST::Codegen() {
    +  NamedValues.clear();
    +  
    +  Function *TheFunction = Proto->Codegen();
    +  if (TheFunction == 0)
    +    return 0;
    +
    +
    + +

    Code generation for function definitions starts out simply enough: we just +codegen the prototype (Proto) and verify that it is ok. We then clear out the +NamedValues map to make sure that there isn't anything in it from the +last function we compiled. Code generation of the prototype ensures that there +is an LLVM Function object that is ready to go for us.

    + +
    +
    +  // Create a new basic block to start insertion into.
    +  BasicBlock *BB = BasicBlock::Create(getGlobalContext(), "entry", TheFunction);
    +  Builder.SetInsertPoint(BB);
    +  
    +  if (Value *RetVal = Body->Codegen()) {
    +
    +
    + +

    Now we get to the point where the Builder is set up. The first +line creates a new basic +block (named "entry"), which is inserted into TheFunction. The +second line then tells the builder that new instructions should be inserted into +the end of the new basic block. Basic blocks in LLVM are an important part +of functions that define the Control Flow Graph. +Since we don't have any control flow, our functions will only contain one +block at this point. We'll fix this in Chapter 5 :).

    + +
    +
    +  if (Value *RetVal = Body->Codegen()) {
    +    // Finish off the function.
    +    Builder.CreateRet(RetVal);
    +
    +    // Validate the generated code, checking for consistency.
    +    verifyFunction(*TheFunction);
    +
    +    return TheFunction;
    +  }
    +
    +
    + +

    Once the insertion point is set up, we call the CodeGen() method for +the root expression of the function. If no error happens, this emits code to +compute the expression into the entry block and returns the value that was +computed. Assuming no error, we then create an LLVM ret instruction, which completes the function. +Once the function is built, we call verifyFunction, which +is provided by LLVM. This function does a variety of consistency checks on the +generated code, to determine if our compiler is doing everything right. Using +this is important: it can catch a lot of bugs. Once the function is finished +and validated, we return it.

    + +
    +
    +  // Error reading body, remove function.
    +  TheFunction->eraseFromParent();
    +  return 0;
    +}
    +
    +
    + +

    The only piece left here is handling of the error case. For simplicity, we +handle this by merely deleting the function we produced with the +eraseFromParent method. This allows the user to redefine a function +that they incorrectly typed in before: if we didn't delete it, it would live in +the symbol table, with a body, preventing future redefinition.

    + +

    This code does have a bug, though. Since the PrototypeAST::Codegen +can return a previously defined forward declaration, our code can actually delete +a forward declaration. There are a number of ways to fix this bug, see what you +can come up with! Here is a testcase:

    + +
    +
    +extern foo(a b);     # ok, defines foo.
    +def foo(a b) c;      # error, 'c' is invalid.
    +def bar() foo(1, 2); # error, unknown function "foo"
    +
    +
    + +
    + + + + + +
    + +

    +For now, code generation to LLVM doesn't really get us much, except that we can +look at the pretty IR calls. The sample code inserts calls to Codegen into the +"HandleDefinition", "HandleExtern" etc functions, and then +dumps out the LLVM IR. This gives a nice way to look at the LLVM IR for simple +functions. For example: +

    + +
    +
    +ready> 4+5;
    +Read top-level expression:
    +define double @""() {
    +entry:
    +        %addtmp = add double 4.000000e+00, 5.000000e+00
    +        ret double %addtmp
    +}
    +
    +
    + +

    Note how the parser turns the top-level expression into anonymous functions +for us. This will be handy when we add JIT +support in the next chapter. Also note that the code is very literally +transcribed, no optimizations are being performed. We will +add optimizations explicitly in +the next chapter.

    + +
    +
    +ready> def foo(a b) a*a + 2*a*b + b*b;
    +Read function definition:
    +define double @foo(double %a, double %b) {
    +entry:
    +        %multmp = mul double %a, %a
    +        %multmp1 = mul double 2.000000e+00, %a
    +        %multmp2 = mul double %multmp1, %b
    +        %addtmp = add double %multmp, %multmp2
    +        %multmp3 = mul double %b, %b
    +        %addtmp4 = add double %addtmp, %multmp3
    +        ret double %addtmp4
    +}
    +
    +
    + +

    This shows some simple arithmetic. Notice the striking similarity to the +LLVM builder calls that we use to create the instructions.

    + +
    +
    +ready> def bar(a) foo(a, 4.0) + bar(31337);
    +Read function definition:
    +define double @bar(double %a) {
    +entry:
    +        %calltmp = call double @foo( double %a, double 4.000000e+00 )
    +        %calltmp1 = call double @bar( double 3.133700e+04 )
    +        %addtmp = add double %calltmp, %calltmp1
    +        ret double %addtmp
    +}
    +
    +
    + +

    This shows some function calls. Note that this function will take a long +time to execute if you call it. In the future we'll add conditional control +flow to actually make recursion useful :).

    + +
    +
    +ready> extern cos(x);
    +Read extern: 
    +declare double @cos(double)
    +
    +ready> cos(1.234);
    +Read top-level expression:
    +define double @""() {
    +entry:
    +        %calltmp = call double @cos( double 1.234000e+00 )
    +        ret double %calltmp
    +}
    +
    +
    + +

    This shows an extern for the libm "cos" function, and a call to it.

    + + +
    +
    +ready> ^D
    +; ModuleID = 'my cool jit'
    +
    +define double @""() {
    +entry:
    +        %addtmp = add double 4.000000e+00, 5.000000e+00
    +        ret double %addtmp
    +}
    +
    +define double @foo(double %a, double %b) {
    +entry:
    +        %multmp = mul double %a, %a
    +        %multmp1 = mul double 2.000000e+00, %a
    +        %multmp2 = mul double %multmp1, %b
    +        %addtmp = add double %multmp, %multmp2
    +        %multmp3 = mul double %b, %b
    +        %addtmp4 = add double %addtmp, %multmp3
    +        ret double %addtmp4
    +}
    +
    +define double @bar(double %a) {
    +entry:
    +        %calltmp = call double @foo( double %a, double 4.000000e+00 )
    +        %calltmp1 = call double @bar( double 3.133700e+04 )
    +        %addtmp = add double %calltmp, %calltmp1
    +        ret double %addtmp
    +}
    +
    +declare double @cos(double)
    +
    +define double @""() {
    +entry:
    +        %calltmp = call double @cos( double 1.234000e+00 )
    +        ret double %calltmp
    +}
    +
    +
    + +

    When you quit the current demo, it dumps out the IR for the entire module +generated. Here you can see the big picture with all the functions referencing +each other.

    + +

    This wraps up the third chapter of the Kaleidoscope tutorial. Up next, we'll +describe how to add JIT codegen and optimizer +support to this so we can actually start running code!

    + +
    + + + + + + +
    + +

    +Here is the complete code listing for our running example, enhanced with the +LLVM code generator. Because this uses the LLVM libraries, we need to link +them in. To do this, we use the llvm-config tool to inform +our makefile/command line about which options to use:

    + +
    +
    +   # Compile
    +   g++ -g -O3 toy.cpp `llvm-config --cppflags --ldflags --libs core` -o toy
    +   # Run
    +   ./toy
    +
    +
    + +

    Here is the code:

    + +
    +
    +// To build this:
    +// See example below.
    +
    +#include "llvm/DerivedTypes.h"
    +#include "llvm/LLVMContext.h"
    +#include "llvm/Module.h"
    +#include "llvm/Analysis/Verifier.h"
    +#include "llvm/Support/IRBuilder.h"
    +#include <cstdio>
    +#include <string>
    +#include <map>
    +#include <vector>
    +using namespace llvm;
    +
    +//===----------------------------------------------------------------------===//
    +// Lexer
    +//===----------------------------------------------------------------------===//
    +
    +// The lexer returns tokens [0-255] if it is an unknown character, otherwise one
    +// of these for known things.
    +enum Token {
    +  tok_eof = -1,
    +
    +  // commands
    +  tok_def = -2, tok_extern = -3,
    +
    +  // primary
    +  tok_identifier = -4, tok_number = -5
    +};
    +
    +static std::string IdentifierStr;  // Filled in if tok_identifier
    +static double NumVal;              // Filled in if tok_number
    +
    +/// gettok - Return the next token from standard input.
    +static int gettok() {
    +  static int LastChar = ' ';
    +
    +  // Skip any whitespace.
    +  while (isspace(LastChar))
    +    LastChar = getchar();
    +
    +  if (isalpha(LastChar)) { // identifier: [a-zA-Z][a-zA-Z0-9]*
    +    IdentifierStr = LastChar;
    +    while (isalnum((LastChar = getchar())))
    +      IdentifierStr += LastChar;
    +
    +    if (IdentifierStr == "def") return tok_def;
    +    if (IdentifierStr == "extern") return tok_extern;
    +    return tok_identifier;
    +  }
    +
    +  if (isdigit(LastChar) || LastChar == '.') {   // Number: [0-9.]+
    +    std::string NumStr;
    +    do {
    +      NumStr += LastChar;
    +      LastChar = getchar();
    +    } while (isdigit(LastChar) || LastChar == '.');
    +
    +    NumVal = strtod(NumStr.c_str(), 0);
    +    return tok_number;
    +  }
    +
    +  if (LastChar == '#') {
    +    // Comment until end of line.
    +    do LastChar = getchar();
    +    while (LastChar != EOF && LastChar != '\n' && LastChar != '\r');
    +    
    +    if (LastChar != EOF)
    +      return gettok();
    +  }
    +  
    +  // Check for end of file.  Don't eat the EOF.
    +  if (LastChar == EOF)
    +    return tok_eof;
    +
    +  // Otherwise, just return the character as its ascii value.
    +  int ThisChar = LastChar;
    +  LastChar = getchar();
    +  return ThisChar;
    +}
    +
    +//===----------------------------------------------------------------------===//
    +// Abstract Syntax Tree (aka Parse Tree)
    +//===----------------------------------------------------------------------===//
    +
    +/// ExprAST - Base class for all expression nodes.
    +class ExprAST {
    +public:
    +  virtual ~ExprAST() {}
    +  virtual Value *Codegen() = 0;
    +};
    +
    +/// NumberExprAST - Expression class for numeric literals like "1.0".
    +class NumberExprAST : public ExprAST {
    +  double Val;
    +public:
    +  NumberExprAST(double val) : Val(val) {}
    +  virtual Value *Codegen();
    +};
    +
    +/// VariableExprAST - Expression class for referencing a variable, like "a".
    +class VariableExprAST : public ExprAST {
    +  std::string Name;
    +public:
    +  VariableExprAST(const std::string &name) : Name(name) {}
    +  virtual Value *Codegen();
    +};
    +
    +/// BinaryExprAST - Expression class for a binary operator.
    +class BinaryExprAST : public ExprAST {
    +  char Op;
    +  ExprAST *LHS, *RHS;
    +public:
    +  BinaryExprAST(char op, ExprAST *lhs, ExprAST *rhs) 
    +    : Op(op), LHS(lhs), RHS(rhs) {}
    +  virtual Value *Codegen();
    +};
    +
    +/// CallExprAST - Expression class for function calls.
    +class CallExprAST : public ExprAST {
    +  std::string Callee;
    +  std::vector<ExprAST*> Args;
    +public:
    +  CallExprAST(const std::string &callee, std::vector<ExprAST*> &args)
    +    : Callee(callee), Args(args) {}
    +  virtual Value *Codegen();
    +};
    +
    +/// PrototypeAST - This class represents the "prototype" for a function,
    +/// which captures its name, and its argument names (thus implicitly the number
    +/// of arguments the function takes).
    +class PrototypeAST {
    +  std::string Name;
    +  std::vector<std::string> Args;
    +public:
    +  PrototypeAST(const std::string &name, const std::vector<std::string> &args)
    +    : Name(name), Args(args) {}
    +  
    +  Function *Codegen();
    +};
    +
    +/// FunctionAST - This class represents a function definition itself.
    +class FunctionAST {
    +  PrototypeAST *Proto;
    +  ExprAST *Body;
    +public:
    +  FunctionAST(PrototypeAST *proto, ExprAST *body)
    +    : Proto(proto), Body(body) {}
    +  
    +  Function *Codegen();
    +};
    +
    +//===----------------------------------------------------------------------===//
    +// Parser
    +//===----------------------------------------------------------------------===//
    +
    +/// CurTok/getNextToken - Provide a simple token buffer.  CurTok is the current
    +/// token the parser is looking at.  getNextToken reads another token from the
    +/// lexer and updates CurTok with its results.
    +static int CurTok;
    +static int getNextToken() {
    +  return CurTok = gettok();
    +}
    +
    +/// BinopPrecedence - This holds the precedence for each binary operator that is
    +/// defined.
    +static std::map<char, int> BinopPrecedence;
    +
    +/// GetTokPrecedence - Get the precedence of the pending binary operator token.
    +static int GetTokPrecedence() {
    +  if (!isascii(CurTok))
    +    return -1;
    +  
    +  // Make sure it's a declared binop.
    +  int TokPrec = BinopPrecedence[CurTok];
    +  if (TokPrec <= 0) return -1;
    +  return TokPrec;
    +}
    +
    +/// Error* - These are little helper functions for error handling.
    +ExprAST *Error(const char *Str) { fprintf(stderr, "Error: %s\n", Str);return 0;}
    +PrototypeAST *ErrorP(const char *Str) { Error(Str); return 0; }
    +FunctionAST *ErrorF(const char *Str) { Error(Str); return 0; }
    +
    +static ExprAST *ParseExpression();
    +
    +/// identifierexpr
    +///   ::= identifier
    +///   ::= identifier '(' expression* ')'
    +static ExprAST *ParseIdentifierExpr() {
    +  std::string IdName = IdentifierStr;
    +  
    +  getNextToken();  // eat identifier.
    +  
    +  if (CurTok != '(') // Simple variable ref.
    +    return new VariableExprAST(IdName);
    +  
    +  // Call.
    +  getNextToken();  // eat (
    +  std::vector<ExprAST*> Args;
    +  if (CurTok != ')') {
    +    while (1) {
    +      ExprAST *Arg = ParseExpression();
    +      if (!Arg) return 0;
    +      Args.push_back(Arg);
    +
    +      if (CurTok == ')') break;
    +
    +      if (CurTok != ',')
    +        return Error("Expected ')' or ',' in argument list");
    +      getNextToken();
    +    }
    +  }
    +
    +  // Eat the ')'.
    +  getNextToken();
    +  
    +  return new CallExprAST(IdName, Args);
    +}
    +
    +/// numberexpr ::= number
    +static ExprAST *ParseNumberExpr() {
    +  ExprAST *Result = new NumberExprAST(NumVal);
    +  getNextToken(); // consume the number
    +  return Result;
    +}
    +
    +/// parenexpr ::= '(' expression ')'
    +static ExprAST *ParseParenExpr() {
    +  getNextToken();  // eat (.
    +  ExprAST *V = ParseExpression();
    +  if (!V) return 0;
    +  
    +  if (CurTok != ')')
    +    return Error("expected ')'");
    +  getNextToken();  // eat ).
    +  return V;
    +}
    +
    +/// primary
    +///   ::= identifierexpr
    +///   ::= numberexpr
    +///   ::= parenexpr
    +static ExprAST *ParsePrimary() {
    +  switch (CurTok) {
    +  default: return Error("unknown token when expecting an expression");
    +  case tok_identifier: return ParseIdentifierExpr();
    +  case tok_number:     return ParseNumberExpr();
    +  case '(':            return ParseParenExpr();
    +  }
    +}
    +
    +/// binoprhs
    +///   ::= ('+' primary)*
    +static ExprAST *ParseBinOpRHS(int ExprPrec, ExprAST *LHS) {
    +  // If this is a binop, find its precedence.
    +  while (1) {
    +    int TokPrec = GetTokPrecedence();
    +    
    +    // If this is a binop that binds at least as tightly as the current binop,
    +    // consume it, otherwise we are done.
    +    if (TokPrec < ExprPrec)
    +      return LHS;
    +    
    +    // Okay, we know this is a binop.
    +    int BinOp = CurTok;
    +    getNextToken();  // eat binop
    +    
    +    // Parse the primary expression after the binary operator.
    +    ExprAST *RHS = ParsePrimary();
    +    if (!RHS) return 0;
    +    
    +    // If BinOp binds less tightly with RHS than the operator after RHS, let
    +    // the pending operator take RHS as its LHS.
    +    int NextPrec = GetTokPrecedence();
    +    if (TokPrec < NextPrec) {
    +      RHS = ParseBinOpRHS(TokPrec+1, RHS);
    +      if (RHS == 0) return 0;
    +    }
    +    
    +    // Merge LHS/RHS.
    +    LHS = new BinaryExprAST(BinOp, LHS, RHS);
    +  }
    +}
    +
    +/// expression
    +///   ::= primary binoprhs
    +///
    +static ExprAST *ParseExpression() {
    +  ExprAST *LHS = ParsePrimary();
    +  if (!LHS) return 0;
    +  
    +  return ParseBinOpRHS(0, LHS);
    +}
    +
    +/// prototype
    +///   ::= id '(' id* ')'
    +static PrototypeAST *ParsePrototype() {
    +  if (CurTok != tok_identifier)
    +    return ErrorP("Expected function name in prototype");
    +
    +  std::string FnName = IdentifierStr;
    +  getNextToken();
    +  
    +  if (CurTok != '(')
    +    return ErrorP("Expected '(' in prototype");
    +  
    +  std::vector<std::string> ArgNames;
    +  while (getNextToken() == tok_identifier)
    +    ArgNames.push_back(IdentifierStr);
    +  if (CurTok != ')')
    +    return ErrorP("Expected ')' in prototype");
    +  
    +  // success.
    +  getNextToken();  // eat ')'.
    +  
    +  return new PrototypeAST(FnName, ArgNames);
    +}
    +
    +/// definition ::= 'def' prototype expression
    +static FunctionAST *ParseDefinition() {
    +  getNextToken();  // eat def.
    +  PrototypeAST *Proto = ParsePrototype();
    +  if (Proto == 0) return 0;
    +
    +  if (ExprAST *E = ParseExpression())
    +    return new FunctionAST(Proto, E);
    +  return 0;
    +}
    +
    +/// toplevelexpr ::= expression
    +static FunctionAST *ParseTopLevelExpr() {
    +  if (ExprAST *E = ParseExpression()) {
    +    // Make an anonymous proto.
    +    PrototypeAST *Proto = new PrototypeAST("", std::vector<std::string>());
    +    return new FunctionAST(Proto, E);
    +  }
    +  return 0;
    +}
    +
    +/// external ::= 'extern' prototype
    +static PrototypeAST *ParseExtern() {
    +  getNextToken();  // eat extern.
    +  return ParsePrototype();
    +}
    +
    +//===----------------------------------------------------------------------===//
    +// Code Generation
    +//===----------------------------------------------------------------------===//
    +
    +static Module *TheModule;
    +static IRBuilder<> Builder(getGlobalContext());
    +static std::map<std::string, Value*> NamedValues;
    +
    +Value *ErrorV(const char *Str) { Error(Str); return 0; }
    +
    +Value *NumberExprAST::Codegen() {
    +  return ConstantFP::get(getGlobalContext(), APFloat(Val));
    +}
    +
    +Value *VariableExprAST::Codegen() {
    +  // Look this variable up in the function.
    +  Value *V = NamedValues[Name];
    +  return V ? V : ErrorV("Unknown variable name");
    +}
    +
    +Value *BinaryExprAST::Codegen() {
    +  Value *L = LHS->Codegen();
    +  Value *R = RHS->Codegen();
    +  if (L == 0 || R == 0) return 0;
    +  
    +  switch (Op) {
    +  case '+': return Builder.CreateAdd(L, R, "addtmp");
    +  case '-': return Builder.CreateSub(L, R, "subtmp");
    +  case '*': return Builder.CreateMul(L, R, "multmp");
    +  case '<':
    +    L = Builder.CreateFCmpULT(L, R, "cmptmp");
    +    // Convert bool 0/1 to double 0.0 or 1.0
    +    return Builder.CreateUIToFP(L, Type::getDoubleTy(getGlobalContext()),
    +                                "booltmp");
    +  default: return ErrorV("invalid binary operator");
    +  }
    +}
    +
    +Value *CallExprAST::Codegen() {
    +  // Look up the name in the global module table.
    +  Function *CalleeF = TheModule->getFunction(Callee);
    +  if (CalleeF == 0)
    +    return ErrorV("Unknown function referenced");
    +  
    +  // If argument mismatch error.
    +  if (CalleeF->arg_size() != Args.size())
    +    return ErrorV("Incorrect # arguments passed");
    +
    +  std::vector<Value*> ArgsV;
    +  for (unsigned i = 0, e = Args.size(); i != e; ++i) {
    +    ArgsV.push_back(Args[i]->Codegen());
    +    if (ArgsV.back() == 0) return 0;
    +  }
    +  
    +  return Builder.CreateCall(CalleeF, ArgsV.begin(), ArgsV.end(), "calltmp");
    +}
    +
    +Function *PrototypeAST::Codegen() {
    +  // Make the function type:  double(double,double) etc.
    +  std::vector<const Type*> Doubles(Args.size(),
    +                                   Type::getDoubleTy(getGlobalContext()));
    +  FunctionType *FT = FunctionType::get(Type::getDoubleTy(getGlobalContext()),
    +                                       Doubles, false);
    +  
    +  Function *F = Function::Create(FT, Function::ExternalLinkage, Name, TheModule);
    +  
    +  // If F conflicted, there was already something named 'Name'.  If it has a
    +  // body, don't allow redefinition or reextern.
    +  if (F->getName() != Name) {
    +    // Delete the one we just made and get the existing one.
    +    F->eraseFromParent();
    +    F = TheModule->getFunction(Name);
    +    
    +    // If F already has a body, reject this.
    +    if (!F->empty()) {
    +      ErrorF("redefinition of function");
    +      return 0;
    +    }
    +    
    +    // If F took a different number of args, reject.
    +    if (F->arg_size() != Args.size()) {
    +      ErrorF("redefinition of function with different # args");
    +      return 0;
    +    }
    +  }
    +  
    +  // Set names for all arguments.
    +  unsigned Idx = 0;
    +  for (Function::arg_iterator AI = F->arg_begin(); Idx != Args.size();
    +       ++AI, ++Idx) {
    +    AI->setName(Args[Idx]);
    +    
    +    // Add arguments to variable symbol table.
    +    NamedValues[Args[Idx]] = AI;
    +  }
    +  
    +  return F;
    +}
    +
    +Function *FunctionAST::Codegen() {
    +  NamedValues.clear();
    +  
    +  Function *TheFunction = Proto->Codegen();
    +  if (TheFunction == 0)
    +    return 0;
    +  
    +  // Create a new basic block to start insertion into.
    +  BasicBlock *BB = BasicBlock::Create(getGlobalContext(), "entry", TheFunction);
    +  Builder.SetInsertPoint(BB);
    +  
    +  if (Value *RetVal = Body->Codegen()) {
    +    // Finish off the function.
    +    Builder.CreateRet(RetVal);
    +
    +    // Validate the generated code, checking for consistency.
    +    verifyFunction(*TheFunction);
    +
    +    return TheFunction;
    +  }
    +  
    +  // Error reading body, remove function.
    +  TheFunction->eraseFromParent();
    +  return 0;
    +}
    +
    +//===----------------------------------------------------------------------===//
    +// Top-Level parsing and JIT Driver
    +//===----------------------------------------------------------------------===//
    +
    +static void HandleDefinition() {
    +  if (FunctionAST *F = ParseDefinition()) {
    +    if (Function *LF = F->Codegen()) {
    +      fprintf(stderr, "Read function definition:");
    +      LF->dump();
    +    }
    +  } else {
    +    // Skip token for error recovery.
    +    getNextToken();
    +  }
    +}
    +
    +static void HandleExtern() {
    +  if (PrototypeAST *P = ParseExtern()) {
    +    if (Function *F = P->Codegen()) {
    +      fprintf(stderr, "Read extern: ");
    +      F->dump();
    +    }
    +  } else {
    +    // Skip token for error recovery.
    +    getNextToken();
    +  }
    +}
    +
    +static void HandleTopLevelExpression() {
    +  // Evaluate a top-level expression into an anonymous function.
    +  if (FunctionAST *F = ParseTopLevelExpr()) {
    +    if (Function *LF = F->Codegen()) {
    +      fprintf(stderr, "Read top-level expression:");
    +      LF->dump();
    +    }
    +  } else {
    +    // Skip token for error recovery.
    +    getNextToken();
    +  }
    +}
    +
    +/// top ::= definition | external | expression | ';'
    +static void MainLoop() {
    +  while (1) {
    +    fprintf(stderr, "ready> ");
    +    switch (CurTok) {
    +    case tok_eof:    return;
    +    case ';':        getNextToken(); break;  // ignore top-level semicolons.
    +    case tok_def:    HandleDefinition(); break;
    +    case tok_extern: HandleExtern(); break;
    +    default:         HandleTopLevelExpression(); break;
    +    }
    +  }
    +}
    +
    +//===----------------------------------------------------------------------===//
    +// "Library" functions that can be "extern'd" from user code.
    +//===----------------------------------------------------------------------===//
    +
    +/// putchard - putchar that takes a double and returns 0.
    +extern "C" 
    +double putchard(double X) {
    +  putchar((char)X);
    +  return 0;
    +}
    +
    +//===----------------------------------------------------------------------===//
    +// Main driver code.
    +//===----------------------------------------------------------------------===//
    +
    +int main() {
    +  LLVMContext &Context = getGlobalContext();
    +
    +  // Install standard binary operators.
    +  // 1 is lowest precedence.
    +  BinopPrecedence['<'] = 10;
    +  BinopPrecedence['+'] = 20;
    +  BinopPrecedence['-'] = 20;
    +  BinopPrecedence['*'] = 40;  // highest.
    +
    +  // Prime the first token.
    +  fprintf(stderr, "ready> ");
    +  getNextToken();
    +
    +  // Make the module, which holds all the code.
    +  TheModule = new Module("my cool jit", Context);
    +
    +  // Run the main "interpreter loop" now.
    +  MainLoop();
    +
    +  // Print out all of the generated code.
    +  TheModule->dump();
    +
    +  return 0;
    +}
    +
    +
    +Next: Adding JIT and Optimizer Support +
    + + +
    +
    + Valid CSS! + Valid HTML 4.01! + + Chris Lattner
    + The LLVM Compiler Infrastructure
    + Last modified: $Date: 2009-07-21 11:05:13 -0700 (Tue, 21 Jul 2009) $ +
    + + diff --git a/libclamav/c++/llvm/docs/tutorial/LangImpl4.html b/libclamav/c++/llvm/docs/tutorial/LangImpl4.html new file mode 100644 index 000000000..728d518a4 --- /dev/null +++ b/libclamav/c++/llvm/docs/tutorial/LangImpl4.html @@ -0,0 +1,1141 @@ + + + + + Kaleidoscope: Adding JIT and Optimizer Support + + + + + + + +
    Kaleidoscope: Adding JIT and Optimizer Support
    + + + +
    +

    Written by Chris Lattner

    +
    + + + + + +
    + +

    Welcome to Chapter 4 of the "Implementing a language +with LLVM" tutorial. Chapters 1-3 described the implementation of a simple +language and added support for generating LLVM IR. This chapter describes +two new techniques: adding optimizer support to your language, and adding JIT +compiler support. These additions will demonstrate how to get nice, efficient code +for the Kaleidoscope language.

    + +
    + + + + + +
    + +

    +Our demonstration for Chapter 3 is elegant and easy to extend. Unfortunately, +it does not produce wonderful code. The IRBuilder, however, does give us +obvious optimizations when compiling simple code:

    + +
    +
    +ready> def test(x) 1+2+x;
    +Read function definition:
    +define double @test(double %x) {
    +entry:
    +        %addtmp = add double 3.000000e+00, %x
    +        ret double %addtmp
    +}
    +
    +
    + +

    This code is not a literal transcription of the AST built by parsing the +input. That would be: + +

    +
    +ready> def test(x) 1+2+x;
    +Read function definition:
    +define double @test(double %x) {
    +entry:
    +        %addtmp = add double 2.000000e+00, 1.000000e+00
    +        %addtmp1 = add double %addtmp, %x
    +        ret double %addtmp1
    +}
    +
    +
    + +

    Constant folding, as seen above, in particular, is a very common and very +important optimization: so much so that many language implementors implement +constant folding support in their AST representation.

    + +

    With LLVM, you don't need this support in the AST. Since all calls to build +LLVM IR go through the LLVM IR builder, the builder itself checked to see if +there was a constant folding opportunity when you call it. If so, it just does +the constant fold and return the constant instead of creating an instruction. + +

    Well, that was easy :). In practice, we recommend always using +IRBuilder when generating code like this. It has no +"syntactic overhead" for its use (you don't have to uglify your compiler with +constant checks everywhere) and it can dramatically reduce the amount of +LLVM IR that is generated in some cases (particular for languages with a macro +preprocessor or that use a lot of constants).

    + +

    On the other hand, the IRBuilder is limited by the fact +that it does all of its analysis inline with the code as it is built. If you +take a slightly more complex example:

    + +
    +
    +ready> def test(x) (1+2+x)*(x+(1+2));
    +ready> Read function definition:
    +define double @test(double %x) {
    +entry:
    +        %addtmp = add double 3.000000e+00, %x
    +        %addtmp1 = add double %x, 3.000000e+00
    +        %multmp = mul double %addtmp, %addtmp1
    +        ret double %multmp
    +}
    +
    +
    + +

    In this case, the LHS and RHS of the multiplication are the same value. We'd +really like to see this generate "tmp = x+3; result = tmp*tmp;" instead +of computing "x+3" twice.

    + +

    Unfortunately, no amount of local analysis will be able to detect and correct +this. This requires two transformations: reassociation of expressions (to +make the add's lexically identical) and Common Subexpression Elimination (CSE) +to delete the redundant add instruction. Fortunately, LLVM provides a broad +range of optimizations that you can use, in the form of "passes".

    + +
    + + + + + +
    + +

    LLVM provides many optimization passes, which do many different sorts of +things and have different tradeoffs. Unlike other systems, LLVM doesn't hold +to the mistaken notion that one set of optimizations is right for all languages +and for all situations. LLVM allows a compiler implementor to make complete +decisions about what optimizations to use, in which order, and in what +situation.

    + +

    As a concrete example, LLVM supports both "whole module" passes, which look +across as large of body of code as they can (often a whole file, but if run +at link time, this can be a substantial portion of the whole program). It also +supports and includes "per-function" passes which just operate on a single +function at a time, without looking at other functions. For more information +on passes and how they are run, see the How +to Write a Pass document and the List of LLVM +Passes.

    + +

    For Kaleidoscope, we are currently generating functions on the fly, one at +a time, as the user types them in. We aren't shooting for the ultimate +optimization experience in this setting, but we also want to catch the easy and +quick stuff where possible. As such, we will choose to run a few per-function +optimizations as the user types the function in. If we wanted to make a "static +Kaleidoscope compiler", we would use exactly the code we have now, except that +we would defer running the optimizer until the entire file has been parsed.

    + +

    In order to get per-function optimizations going, we need to set up a +FunctionPassManager to hold and +organize the LLVM optimizations that we want to run. Once we have that, we can +add a set of optimizations to run. The code looks like this:

    + +
    +
    +  ExistingModuleProvider *OurModuleProvider =
    +      new ExistingModuleProvider(TheModule);
    +
    +  FunctionPassManager OurFPM(OurModuleProvider);
    +
    +  // Set up the optimizer pipeline.  Start with registering info about how the
    +  // target lays out data structures.
    +  OurFPM.add(new TargetData(*TheExecutionEngine->getTargetData()));
    +  // Do simple "peephole" optimizations and bit-twiddling optzns.
    +  OurFPM.add(createInstructionCombiningPass());
    +  // Reassociate expressions.
    +  OurFPM.add(createReassociatePass());
    +  // Eliminate Common SubExpressions.
    +  OurFPM.add(createGVNPass());
    +  // Simplify the control flow graph (deleting unreachable blocks, etc).
    +  OurFPM.add(createCFGSimplificationPass());
    +
    +  OurFPM.doInitialization();
    +
    +  // Set the global so the code gen can use this.
    +  TheFPM = &OurFPM;
    +
    +  // Run the main "interpreter loop" now.
    +  MainLoop();
    +
    +
    + +

    This code defines two objects, an ExistingModuleProvider and a +FunctionPassManager. The former is basically a wrapper around our +Module that the PassManager requires. It provides certain flexibility +that we're not going to take advantage of here, so I won't dive into any details +about it.

    + +

    The meat of the matter here, is the definition of "OurFPM". It +requires a pointer to the Module (through the ModuleProvider) +to construct itself. Once it is set up, we use a series of "add" calls to add +a bunch of LLVM passes. The first pass is basically boilerplate, it adds a pass +so that later optimizations know how the data structures in the program are +laid out. The "TheExecutionEngine" variable is related to the JIT, +which we will get to in the next section.

    + +

    In this case, we choose to add 4 optimization passes. The passes we chose +here are a pretty standard set of "cleanup" optimizations that are useful for +a wide variety of code. I won't delve into what they do but, believe me, +they are a good starting place :).

    + +

    Once the PassManager is set up, we need to make use of it. We do this by +running it after our newly created function is constructed (in +FunctionAST::Codegen), but before it is returned to the client:

    + +
    +
    +  if (Value *RetVal = Body->Codegen()) {
    +    // Finish off the function.
    +    Builder.CreateRet(RetVal);
    +
    +    // Validate the generated code, checking for consistency.
    +    verifyFunction(*TheFunction);
    +
    +    // Optimize the function.
    +    TheFPM->run(*TheFunction);
    +    
    +    return TheFunction;
    +  }
    +
    +
    + +

    As you can see, this is pretty straightforward. The +FunctionPassManager optimizes and updates the LLVM Function* in place, +improving (hopefully) its body. With this in place, we can try our test above +again:

    + +
    +
    +ready> def test(x) (1+2+x)*(x+(1+2));
    +ready> Read function definition:
    +define double @test(double %x) {
    +entry:
    +        %addtmp = add double %x, 3.000000e+00
    +        %multmp = mul double %addtmp, %addtmp
    +        ret double %multmp
    +}
    +
    +
    + +

    As expected, we now get our nicely optimized code, saving a floating point +add instruction from every execution of this function.

    + +

    LLVM provides a wide variety of optimizations that can be used in certain +circumstances. Some documentation about the various +passes is available, but it isn't very complete. Another good source of +ideas can come from looking at the passes that llvm-gcc or +llvm-ld run to get started. The "opt" tool allows you to +experiment with passes from the command line, so you can see if they do +anything.

    + +

    Now that we have reasonable code coming out of our front-end, lets talk about +executing it!

    + +
    + + + + + +
    + +

    Code that is available in LLVM IR can have a wide variety of tools +applied to it. For example, you can run optimizations on it (as we did above), +you can dump it out in textual or binary forms, you can compile the code to an +assembly file (.s) for some target, or you can JIT compile it. The nice thing +about the LLVM IR representation is that it is the "common currency" between +many different parts of the compiler. +

    + +

    In this section, we'll add JIT compiler support to our interpreter. The +basic idea that we want for Kaleidoscope is to have the user enter function +bodies as they do now, but immediately evaluate the top-level expressions they +type in. For example, if they type in "1 + 2;", we should evaluate and print +out 3. If they define a function, they should be able to call it from the +command line.

    + +

    In order to do this, we first declare and initialize the JIT. This is done +by adding a global variable and a call in main:

    + +
    +
    +static ExecutionEngine *TheExecutionEngine;
    +...
    +int main() {
    +  ..
    +  // Create the JIT.  This takes ownership of the module and module provider.
    +  TheExecutionEngine = EngineBuilder(OurModuleProvider).create();
    +  ..
    +}
    +
    +
    + +

    This creates an abstract "Execution Engine" which can be either a JIT +compiler or the LLVM interpreter. LLVM will automatically pick a JIT compiler +for you if one is available for your platform, otherwise it will fall back to +the interpreter.

    + +

    Once the ExecutionEngine is created, the JIT is ready to be used. +There are a variety of APIs that are useful, but the simplest one is the +"getPointerToFunction(F)" method. This method JIT compiles the +specified LLVM Function and returns a function pointer to the generated machine +code. In our case, this means that we can change the code that parses a +top-level expression to look like this:

    + +
    +
    +static void HandleTopLevelExpression() {
    +  // Evaluate a top-level expression into an anonymous function.
    +  if (FunctionAST *F = ParseTopLevelExpr()) {
    +    if (Function *LF = F->Codegen()) {
    +      LF->dump();  // Dump the function for exposition purposes.
    +    
    +      // JIT the function, returning a function pointer.
    +      void *FPtr = TheExecutionEngine->getPointerToFunction(LF);
    +      
    +      // Cast it to the right type (takes no arguments, returns a double) so we
    +      // can call it as a native function.
    +      double (*FP)() = (double (*)())(intptr_t)FPtr;
    +      fprintf(stderr, "Evaluated to %f\n", FP());
    +    }
    +
    +
    + +

    Recall that we compile top-level expressions into a self-contained LLVM +function that takes no arguments and returns the computed double. Because the +LLVM JIT compiler matches the native platform ABI, this means that you can just +cast the result pointer to a function pointer of that type and call it directly. +This means, there is no difference between JIT compiled code and native machine +code that is statically linked into your application.

    + +

    With just these two changes, lets see how Kaleidoscope works now!

    + +
    +
    +ready> 4+5;
    +define double @""() {
    +entry:
    +        ret double 9.000000e+00
    +}
    +
    +Evaluated to 9.000000
    +
    +
    + +

    Well this looks like it is basically working. The dump of the function +shows the "no argument function that always returns double" that we synthesize +for each top-level expression that is typed in. This demonstrates very basic +functionality, but can we do more?

    + +
    +
    +ready> def testfunc(x y) x + y*2;  
    +Read function definition:
    +define double @testfunc(double %x, double %y) {
    +entry:
    +        %multmp = mul double %y, 2.000000e+00
    +        %addtmp = add double %multmp, %x
    +        ret double %addtmp
    +}
    +
    +ready> testfunc(4, 10);
    +define double @""() {
    +entry:
    +        %calltmp = call double @testfunc( double 4.000000e+00, double 1.000000e+01 )
    +        ret double %calltmp
    +}
    +
    +Evaluated to 24.000000
    +
    +
    + +

    This illustrates that we can now call user code, but there is something a bit +subtle going on here. Note that we only invoke the JIT on the anonymous +functions that call testfunc, but we never invoked it +on testfunc itself. What actually happened here is that the JIT +scanned for all non-JIT'd functions transitively called from the anonymous +function and compiled all of them before returning +from getPointerToFunction().

    + +

    The JIT provides a number of other more advanced interfaces for things like +freeing allocated machine code, rejit'ing functions to update them, etc. +However, even with this simple code, we get some surprisingly powerful +capabilities - check this out (I removed the dump of the anonymous functions, +you should get the idea by now :) :

    + +
    +
    +ready> extern sin(x);
    +Read extern: 
    +declare double @sin(double)
    +
    +ready> extern cos(x);
    +Read extern: 
    +declare double @cos(double)
    +
    +ready> sin(1.0);
    +Evaluated to 0.841471
    +
    +ready> def foo(x) sin(x)*sin(x) + cos(x)*cos(x);
    +Read function definition:
    +define double @foo(double %x) {
    +entry:
    +        %calltmp = call double @sin( double %x )
    +        %multmp = mul double %calltmp, %calltmp
    +        %calltmp2 = call double @cos( double %x )
    +        %multmp4 = mul double %calltmp2, %calltmp2
    +        %addtmp = add double %multmp, %multmp4
    +        ret double %addtmp
    +}
    +
    +ready> foo(4.0);
    +Evaluated to 1.000000
    +
    +
    + +

    Whoa, how does the JIT know about sin and cos? The answer is surprisingly +simple: in this +example, the JIT started execution of a function and got to a function call. It +realized that the function was not yet JIT compiled and invoked the standard set +of routines to resolve the function. In this case, there is no body defined +for the function, so the JIT ended up calling "dlsym("sin")" on the +Kaleidoscope process itself. +Since "sin" is defined within the JIT's address space, it simply +patches up calls in the module to call the libm version of sin +directly.

    + +

    The LLVM JIT provides a number of interfaces (look in the +ExecutionEngine.h file) for controlling how unknown functions get +resolved. It allows you to establish explicit mappings between IR objects and +addresses (useful for LLVM global variables that you want to map to static +tables, for example), allows you to dynamically decide on the fly based on the +function name, and even allows you to have the JIT compile functions lazily the +first time they're called.

    + +

    One interesting application of this is that we can now extend the language +by writing arbitrary C++ code to implement operations. For example, if we add: +

    + +
    +
    +/// putchard - putchar that takes a double and returns 0.
    +extern "C" 
    +double putchard(double X) {
    +  putchar((char)X);
    +  return 0;
    +}
    +
    +
    + +

    Now we can produce simple output to the console by using things like: +"extern putchard(x); putchard(120);", which prints a lowercase 'x' on +the console (120 is the ASCII code for 'x'). Similar code could be used to +implement file I/O, console input, and many other capabilities in +Kaleidoscope.

    + +

    This completes the JIT and optimizer chapter of the Kaleidoscope tutorial. At +this point, we can compile a non-Turing-complete programming language, optimize +and JIT compile it in a user-driven way. Next up we'll look into extending the language with control flow constructs, +tackling some interesting LLVM IR issues along the way.

    + +
    + + + + + +
    + +

    +Here is the complete code listing for our running example, enhanced with the +LLVM JIT and optimizer. To build this example, use: +

    + +
    +
    +   # Compile
    +   g++ -g toy.cpp `llvm-config --cppflags --ldflags --libs core jit interpreter native` -O3 -o toy
    +   # Run
    +   ./toy
    +
    +
    + +

    +If you are compiling this on Linux, make sure to add the "-rdynamic" option +as well. This makes sure that the external functions are resolved properly +at runtime.

    + +

    Here is the code:

    + +
    +
    +#include "llvm/DerivedTypes.h"
    +#include "llvm/ExecutionEngine/ExecutionEngine.h"
    +#include "llvm/ExecutionEngine/Interpreter.h"
    +#include "llvm/ExecutionEngine/JIT.h"
    +#include "llvm/LLVMContext.h"
    +#include "llvm/Module.h"
    +#include "llvm/ModuleProvider.h"
    +#include "llvm/PassManager.h"
    +#include "llvm/Analysis/Verifier.h"
    +#include "llvm/Target/TargetData.h"
    +#include "llvm/Target/TargetSelect.h"
    +#include "llvm/Transforms/Scalar.h"
    +#include "llvm/Support/IRBuilder.h"
    +#include <cstdio>
    +#include <string>
    +#include <map>
    +#include <vector>
    +using namespace llvm;
    +
    +//===----------------------------------------------------------------------===//
    +// Lexer
    +//===----------------------------------------------------------------------===//
    +
    +// The lexer returns tokens [0-255] if it is an unknown character, otherwise one
    +// of these for known things.
    +enum Token {
    +  tok_eof = -1,
    +
    +  // commands
    +  tok_def = -2, tok_extern = -3,
    +
    +  // primary
    +  tok_identifier = -4, tok_number = -5
    +};
    +
    +static std::string IdentifierStr;  // Filled in if tok_identifier
    +static double NumVal;              // Filled in if tok_number
    +
    +/// gettok - Return the next token from standard input.
    +static int gettok() {
    +  static int LastChar = ' ';
    +
    +  // Skip any whitespace.
    +  while (isspace(LastChar))
    +    LastChar = getchar();
    +
    +  if (isalpha(LastChar)) { // identifier: [a-zA-Z][a-zA-Z0-9]*
    +    IdentifierStr = LastChar;
    +    while (isalnum((LastChar = getchar())))
    +      IdentifierStr += LastChar;
    +
    +    if (IdentifierStr == "def") return tok_def;
    +    if (IdentifierStr == "extern") return tok_extern;
    +    return tok_identifier;
    +  }
    +
    +  if (isdigit(LastChar) || LastChar == '.') {   // Number: [0-9.]+
    +    std::string NumStr;
    +    do {
    +      NumStr += LastChar;
    +      LastChar = getchar();
    +    } while (isdigit(LastChar) || LastChar == '.');
    +
    +    NumVal = strtod(NumStr.c_str(), 0);
    +    return tok_number;
    +  }
    +
    +  if (LastChar == '#') {
    +    // Comment until end of line.
    +    do LastChar = getchar();
    +    while (LastChar != EOF && LastChar != '\n' && LastChar != '\r');
    +    
    +    if (LastChar != EOF)
    +      return gettok();
    +  }
    +  
    +  // Check for end of file.  Don't eat the EOF.
    +  if (LastChar == EOF)
    +    return tok_eof;
    +
    +  // Otherwise, just return the character as its ascii value.
    +  int ThisChar = LastChar;
    +  LastChar = getchar();
    +  return ThisChar;
    +}
    +
    +//===----------------------------------------------------------------------===//
    +// Abstract Syntax Tree (aka Parse Tree)
    +//===----------------------------------------------------------------------===//
    +
    +/// ExprAST - Base class for all expression nodes.
    +class ExprAST {
    +public:
    +  virtual ~ExprAST() {}
    +  virtual Value *Codegen() = 0;
    +};
    +
    +/// NumberExprAST - Expression class for numeric literals like "1.0".
    +class NumberExprAST : public ExprAST {
    +  double Val;
    +public:
    +  NumberExprAST(double val) : Val(val) {}
    +  virtual Value *Codegen();
    +};
    +
    +/// VariableExprAST - Expression class for referencing a variable, like "a".
    +class VariableExprAST : public ExprAST {
    +  std::string Name;
    +public:
    +  VariableExprAST(const std::string &name) : Name(name) {}
    +  virtual Value *Codegen();
    +};
    +
    +/// BinaryExprAST - Expression class for a binary operator.
    +class BinaryExprAST : public ExprAST {
    +  char Op;
    +  ExprAST *LHS, *RHS;
    +public:
    +  BinaryExprAST(char op, ExprAST *lhs, ExprAST *rhs) 
    +    : Op(op), LHS(lhs), RHS(rhs) {}
    +  virtual Value *Codegen();
    +};
    +
    +/// CallExprAST - Expression class for function calls.
    +class CallExprAST : public ExprAST {
    +  std::string Callee;
    +  std::vector<ExprAST*> Args;
    +public:
    +  CallExprAST(const std::string &callee, std::vector<ExprAST*> &args)
    +    : Callee(callee), Args(args) {}
    +  virtual Value *Codegen();
    +};
    +
    +/// PrototypeAST - This class represents the "prototype" for a function,
    +/// which captures its name, and its argument names (thus implicitly the number
    +/// of arguments the function takes).
    +class PrototypeAST {
    +  std::string Name;
    +  std::vector<std::string> Args;
    +public:
    +  PrototypeAST(const std::string &name, const std::vector<std::string> &args)
    +    : Name(name), Args(args) {}
    +  
    +  Function *Codegen();
    +};
    +
    +/// FunctionAST - This class represents a function definition itself.
    +class FunctionAST {
    +  PrototypeAST *Proto;
    +  ExprAST *Body;
    +public:
    +  FunctionAST(PrototypeAST *proto, ExprAST *body)
    +    : Proto(proto), Body(body) {}
    +  
    +  Function *Codegen();
    +};
    +
    +//===----------------------------------------------------------------------===//
    +// Parser
    +//===----------------------------------------------------------------------===//
    +
    +/// CurTok/getNextToken - Provide a simple token buffer.  CurTok is the current
    +/// token the parser is looking at.  getNextToken reads another token from the
    +/// lexer and updates CurTok with its results.
    +static int CurTok;
    +static int getNextToken() {
    +  return CurTok = gettok();
    +}
    +
    +/// BinopPrecedence - This holds the precedence for each binary operator that is
    +/// defined.
    +static std::map<char, int> BinopPrecedence;
    +
    +/// GetTokPrecedence - Get the precedence of the pending binary operator token.
    +static int GetTokPrecedence() {
    +  if (!isascii(CurTok))
    +    return -1;
    +  
    +  // Make sure it's a declared binop.
    +  int TokPrec = BinopPrecedence[CurTok];
    +  if (TokPrec <= 0) return -1;
    +  return TokPrec;
    +}
    +
    +/// Error* - These are little helper functions for error handling.
    +ExprAST *Error(const char *Str) { fprintf(stderr, "Error: %s\n", Str);return 0;}
    +PrototypeAST *ErrorP(const char *Str) { Error(Str); return 0; }
    +FunctionAST *ErrorF(const char *Str) { Error(Str); return 0; }
    +
    +static ExprAST *ParseExpression();
    +
    +/// identifierexpr
    +///   ::= identifier
    +///   ::= identifier '(' expression* ')'
    +static ExprAST *ParseIdentifierExpr() {
    +  std::string IdName = IdentifierStr;
    +  
    +  getNextToken();  // eat identifier.
    +  
    +  if (CurTok != '(') // Simple variable ref.
    +    return new VariableExprAST(IdName);
    +  
    +  // Call.
    +  getNextToken();  // eat (
    +  std::vector<ExprAST*> Args;
    +  if (CurTok != ')') {
    +    while (1) {
    +      ExprAST *Arg = ParseExpression();
    +      if (!Arg) return 0;
    +      Args.push_back(Arg);
    +
    +      if (CurTok == ')') break;
    +
    +      if (CurTok != ',')
    +        return Error("Expected ')' or ',' in argument list");
    +      getNextToken();
    +    }
    +  }
    +
    +  // Eat the ')'.
    +  getNextToken();
    +  
    +  return new CallExprAST(IdName, Args);
    +}
    +
    +/// numberexpr ::= number
    +static ExprAST *ParseNumberExpr() {
    +  ExprAST *Result = new NumberExprAST(NumVal);
    +  getNextToken(); // consume the number
    +  return Result;
    +}
    +
    +/// parenexpr ::= '(' expression ')'
    +static ExprAST *ParseParenExpr() {
    +  getNextToken();  // eat (.
    +  ExprAST *V = ParseExpression();
    +  if (!V) return 0;
    +  
    +  if (CurTok != ')')
    +    return Error("expected ')'");
    +  getNextToken();  // eat ).
    +  return V;
    +}
    +
    +/// primary
    +///   ::= identifierexpr
    +///   ::= numberexpr
    +///   ::= parenexpr
    +static ExprAST *ParsePrimary() {
    +  switch (CurTok) {
    +  default: return Error("unknown token when expecting an expression");
    +  case tok_identifier: return ParseIdentifierExpr();
    +  case tok_number:     return ParseNumberExpr();
    +  case '(':            return ParseParenExpr();
    +  }
    +}
    +
    +/// binoprhs
    +///   ::= ('+' primary)*
    +static ExprAST *ParseBinOpRHS(int ExprPrec, ExprAST *LHS) {
    +  // If this is a binop, find its precedence.
    +  while (1) {
    +    int TokPrec = GetTokPrecedence();
    +    
    +    // If this is a binop that binds at least as tightly as the current binop,
    +    // consume it, otherwise we are done.
    +    if (TokPrec < ExprPrec)
    +      return LHS;
    +    
    +    // Okay, we know this is a binop.
    +    int BinOp = CurTok;
    +    getNextToken();  // eat binop
    +    
    +    // Parse the primary expression after the binary operator.
    +    ExprAST *RHS = ParsePrimary();
    +    if (!RHS) return 0;
    +    
    +    // If BinOp binds less tightly with RHS than the operator after RHS, let
    +    // the pending operator take RHS as its LHS.
    +    int NextPrec = GetTokPrecedence();
    +    if (TokPrec < NextPrec) {
    +      RHS = ParseBinOpRHS(TokPrec+1, RHS);
    +      if (RHS == 0) return 0;
    +    }
    +    
    +    // Merge LHS/RHS.
    +    LHS = new BinaryExprAST(BinOp, LHS, RHS);
    +  }
    +}
    +
    +/// expression
    +///   ::= primary binoprhs
    +///
    +static ExprAST *ParseExpression() {
    +  ExprAST *LHS = ParsePrimary();
    +  if (!LHS) return 0;
    +  
    +  return ParseBinOpRHS(0, LHS);
    +}
    +
    +/// prototype
    +///   ::= id '(' id* ')'
    +static PrototypeAST *ParsePrototype() {
    +  if (CurTok != tok_identifier)
    +    return ErrorP("Expected function name in prototype");
    +
    +  std::string FnName = IdentifierStr;
    +  getNextToken();
    +  
    +  if (CurTok != '(')
    +    return ErrorP("Expected '(' in prototype");
    +  
    +  std::vector<std::string> ArgNames;
    +  while (getNextToken() == tok_identifier)
    +    ArgNames.push_back(IdentifierStr);
    +  if (CurTok != ')')
    +    return ErrorP("Expected ')' in prototype");
    +  
    +  // success.
    +  getNextToken();  // eat ')'.
    +  
    +  return new PrototypeAST(FnName, ArgNames);
    +}
    +
    +/// definition ::= 'def' prototype expression
    +static FunctionAST *ParseDefinition() {
    +  getNextToken();  // eat def.
    +  PrototypeAST *Proto = ParsePrototype();
    +  if (Proto == 0) return 0;
    +
    +  if (ExprAST *E = ParseExpression())
    +    return new FunctionAST(Proto, E);
    +  return 0;
    +}
    +
    +/// toplevelexpr ::= expression
    +static FunctionAST *ParseTopLevelExpr() {
    +  if (ExprAST *E = ParseExpression()) {
    +    // Make an anonymous proto.
    +    PrototypeAST *Proto = new PrototypeAST("", std::vector<std::string>());
    +    return new FunctionAST(Proto, E);
    +  }
    +  return 0;
    +}
    +
    +/// external ::= 'extern' prototype
    +static PrototypeAST *ParseExtern() {
    +  getNextToken();  // eat extern.
    +  return ParsePrototype();
    +}
    +
    +//===----------------------------------------------------------------------===//
    +// Code Generation
    +//===----------------------------------------------------------------------===//
    +
    +static Module *TheModule;
    +static IRBuilder<> Builder(getGlobalContext());
    +static std::map<std::string, Value*> NamedValues;
    +static FunctionPassManager *TheFPM;
    +
    +Value *ErrorV(const char *Str) { Error(Str); return 0; }
    +
    +Value *NumberExprAST::Codegen() {
    +  return ConstantFP::get(getGlobalContext(), APFloat(Val));
    +}
    +
    +Value *VariableExprAST::Codegen() {
    +  // Look this variable up in the function.
    +  Value *V = NamedValues[Name];
    +  return V ? V : ErrorV("Unknown variable name");
    +}
    +
    +Value *BinaryExprAST::Codegen() {
    +  Value *L = LHS->Codegen();
    +  Value *R = RHS->Codegen();
    +  if (L == 0 || R == 0) return 0;
    +  
    +  switch (Op) {
    +  case '+': return Builder.CreateAdd(L, R, "addtmp");
    +  case '-': return Builder.CreateSub(L, R, "subtmp");
    +  case '*': return Builder.CreateMul(L, R, "multmp");
    +  case '<':
    +    L = Builder.CreateFCmpULT(L, R, "cmptmp");
    +    // Convert bool 0/1 to double 0.0 or 1.0
    +    return Builder.CreateUIToFP(L, Type::getDoubleTy(getGlobalContext()),
    +                                "booltmp");
    +  default: return ErrorV("invalid binary operator");
    +  }
    +}
    +
    +Value *CallExprAST::Codegen() {
    +  // Look up the name in the global module table.
    +  Function *CalleeF = TheModule->getFunction(Callee);
    +  if (CalleeF == 0)
    +    return ErrorV("Unknown function referenced");
    +  
    +  // If argument mismatch error.
    +  if (CalleeF->arg_size() != Args.size())
    +    return ErrorV("Incorrect # arguments passed");
    +
    +  std::vector<Value*> ArgsV;
    +  for (unsigned i = 0, e = Args.size(); i != e; ++i) {
    +    ArgsV.push_back(Args[i]->Codegen());
    +    if (ArgsV.back() == 0) return 0;
    +  }
    +  
    +  return Builder.CreateCall(CalleeF, ArgsV.begin(), ArgsV.end(), "calltmp");
    +}
    +
    +Function *PrototypeAST::Codegen() {
    +  // Make the function type:  double(double,double) etc.
    +  std::vector<const Type*> Doubles(Args.size(),
    +                                   Type::getDoubleTy(getGlobalContext()));
    +  FunctionType *FT = FunctionType::get(Type::getDoubleTy(getGlobalContext()),
    +                                       Doubles, false);
    +  
    +  Function *F = Function::Create(FT, Function::ExternalLinkage, Name, TheModule);
    +  
    +  // If F conflicted, there was already something named 'Name'.  If it has a
    +  // body, don't allow redefinition or reextern.
    +  if (F->getName() != Name) {
    +    // Delete the one we just made and get the existing one.
    +    F->eraseFromParent();
    +    F = TheModule->getFunction(Name);
    +    
    +    // If F already has a body, reject this.
    +    if (!F->empty()) {
    +      ErrorF("redefinition of function");
    +      return 0;
    +    }
    +    
    +    // If F took a different number of args, reject.
    +    if (F->arg_size() != Args.size()) {
    +      ErrorF("redefinition of function with different # args");
    +      return 0;
    +    }
    +  }
    +  
    +  // Set names for all arguments.
    +  unsigned Idx = 0;
    +  for (Function::arg_iterator AI = F->arg_begin(); Idx != Args.size();
    +       ++AI, ++Idx) {
    +    AI->setName(Args[Idx]);
    +    
    +    // Add arguments to variable symbol table.
    +    NamedValues[Args[Idx]] = AI;
    +  }
    +  
    +  return F;
    +}
    +
    +Function *FunctionAST::Codegen() {
    +  NamedValues.clear();
    +  
    +  Function *TheFunction = Proto->Codegen();
    +  if (TheFunction == 0)
    +    return 0;
    +  
    +  // Create a new basic block to start insertion into.
    +  BasicBlock *BB = BasicBlock::Create(getGlobalContext(), "entry", TheFunction);
    +  Builder.SetInsertPoint(BB);
    +  
    +  if (Value *RetVal = Body->Codegen()) {
    +    // Finish off the function.
    +    Builder.CreateRet(RetVal);
    +
    +    // Validate the generated code, checking for consistency.
    +    verifyFunction(*TheFunction);
    +
    +    // Optimize the function.
    +    TheFPM->run(*TheFunction);
    +    
    +    return TheFunction;
    +  }
    +  
    +  // Error reading body, remove function.
    +  TheFunction->eraseFromParent();
    +  return 0;
    +}
    +
    +//===----------------------------------------------------------------------===//
    +// Top-Level parsing and JIT Driver
    +//===----------------------------------------------------------------------===//
    +
    +static ExecutionEngine *TheExecutionEngine;
    +
    +static void HandleDefinition() {
    +  if (FunctionAST *F = ParseDefinition()) {
    +    if (Function *LF = F->Codegen()) {
    +      fprintf(stderr, "Read function definition:");
    +      LF->dump();
    +    }
    +  } else {
    +    // Skip token for error recovery.
    +    getNextToken();
    +  }
    +}
    +
    +static void HandleExtern() {
    +  if (PrototypeAST *P = ParseExtern()) {
    +    if (Function *F = P->Codegen()) {
    +      fprintf(stderr, "Read extern: ");
    +      F->dump();
    +    }
    +  } else {
    +    // Skip token for error recovery.
    +    getNextToken();
    +  }
    +}
    +
    +static void HandleTopLevelExpression() {
    +  // Evaluate a top-level expression into an anonymous function.
    +  if (FunctionAST *F = ParseTopLevelExpr()) {
    +    if (Function *LF = F->Codegen()) {
    +      // JIT the function, returning a function pointer.
    +      void *FPtr = TheExecutionEngine->getPointerToFunction(LF);
    +      
    +      // Cast it to the right type (takes no arguments, returns a double) so we
    +      // can call it as a native function.
    +      double (*FP)() = (double (*)())(intptr_t)FPtr;
    +      fprintf(stderr, "Evaluated to %f\n", FP());
    +    }
    +  } else {
    +    // Skip token for error recovery.
    +    getNextToken();
    +  }
    +}
    +
    +/// top ::= definition | external | expression | ';'
    +static void MainLoop() {
    +  while (1) {
    +    fprintf(stderr, "ready> ");
    +    switch (CurTok) {
    +    case tok_eof:    return;
    +    case ';':        getNextToken(); break;  // ignore top-level semicolons.
    +    case tok_def:    HandleDefinition(); break;
    +    case tok_extern: HandleExtern(); break;
    +    default:         HandleTopLevelExpression(); break;
    +    }
    +  }
    +}
    +
    +//===----------------------------------------------------------------------===//
    +// "Library" functions that can be "extern'd" from user code.
    +//===----------------------------------------------------------------------===//
    +
    +/// putchard - putchar that takes a double and returns 0.
    +extern "C" 
    +double putchard(double X) {
    +  putchar((char)X);
    +  return 0;
    +}
    +
    +//===----------------------------------------------------------------------===//
    +// Main driver code.
    +//===----------------------------------------------------------------------===//
    +
    +int main() {
    +  InitializeNativeTarget();
    +  LLVMContext &Context = getGlobalContext();
    +
    +  // Install standard binary operators.
    +  // 1 is lowest precedence.
    +  BinopPrecedence['<'] = 10;
    +  BinopPrecedence['+'] = 20;
    +  BinopPrecedence['-'] = 20;
    +  BinopPrecedence['*'] = 40;  // highest.
    +
    +  // Prime the first token.
    +  fprintf(stderr, "ready> ");
    +  getNextToken();
    +
    +  // Make the module, which holds all the code.
    +  TheModule = new Module("my cool jit", Context);
    +
    +  ExistingModuleProvider *OurModuleProvider =
    +      new ExistingModuleProvider(TheModule);
    +
    +  // Create the JIT.  This takes ownership of the module and module provider.
    +  TheExecutionEngine = EngineBuilder(OurModuleProvider).create();
    +
    +  FunctionPassManager OurFPM(OurModuleProvider);
    +
    +  // Set up the optimizer pipeline.  Start with registering info about how the
    +  // target lays out data structures.
    +  OurFPM.add(new TargetData(*TheExecutionEngine->getTargetData()));
    +  // Do simple "peephole" optimizations and bit-twiddling optzns.
    +  OurFPM.add(createInstructionCombiningPass());
    +  // Reassociate expressions.
    +  OurFPM.add(createReassociatePass());
    +  // Eliminate Common SubExpressions.
    +  OurFPM.add(createGVNPass());
    +  // Simplify the control flow graph (deleting unreachable blocks, etc).
    +  OurFPM.add(createCFGSimplificationPass());
    +
    +  OurFPM.doInitialization();
    +
    +  // Set the global so the code gen can use this.
    +  TheFPM = &OurFPM;
    +
    +  // Run the main "interpreter loop" now.
    +  MainLoop();
    +
    +  TheFPM = 0;
    +
    +  // Print out all of the generated code.
    +  TheModule->dump();
    +
    +  return 0;
    +}
    +
    +
    + +Next: Extending the language: control flow +
    + + +
    +
    + Valid CSS! + Valid HTML 4.01! + + Chris Lattner
    + The LLVM Compiler Infrastructure
    + Last modified: $Date: 2007-10-17 11:05:13 -0700 (Wed, 17 Oct 2007) $ +
    + + diff --git a/libclamav/c++/llvm/docs/tutorial/LangImpl5-cfg.png b/libclamav/c++/llvm/docs/tutorial/LangImpl5-cfg.png new file mode 100644 index 000000000..cdba92ff6 Binary files /dev/null and b/libclamav/c++/llvm/docs/tutorial/LangImpl5-cfg.png differ diff --git a/libclamav/c++/llvm/docs/tutorial/LangImpl5.html b/libclamav/c++/llvm/docs/tutorial/LangImpl5.html new file mode 100644 index 000000000..f93b59be0 --- /dev/null +++ b/libclamav/c++/llvm/docs/tutorial/LangImpl5.html @@ -0,0 +1,1777 @@ + + + + + Kaleidoscope: Extending the Language: Control Flow + + + + + + + +
    Kaleidoscope: Extending the Language: Control Flow
    + + + +
    +

    Written by Chris Lattner

    +
    + + + + + +
    + +

    Welcome to Chapter 5 of the "Implementing a language +with LLVM" tutorial. Parts 1-4 described the implementation of the simple +Kaleidoscope language and included support for generating LLVM IR, followed by +optimizations and a JIT compiler. Unfortunately, as presented, Kaleidoscope is +mostly useless: it has no control flow other than call and return. This means +that you can't have conditional branches in the code, significantly limiting its +power. In this episode of "build that compiler", we'll extend Kaleidoscope to +have an if/then/else expression plus a simple 'for' loop.

    + +
    + + + + + +
    + +

    +Extending Kaleidoscope to support if/then/else is quite straightforward. It +basically requires adding lexer support for this "new" concept to the lexer, +parser, AST, and LLVM code emitter. This example is nice, because it shows how +easy it is to "grow" a language over time, incrementally extending it as new +ideas are discovered.

    + +

    Before we get going on "how" we add this extension, lets talk about "what" we +want. The basic idea is that we want to be able to write this sort of thing: +

    + +
    +
    +def fib(x)
    +  if x < 3 then
    +    1
    +  else
    +    fib(x-1)+fib(x-2);
    +
    +
    + +

    In Kaleidoscope, every construct is an expression: there are no statements. +As such, the if/then/else expression needs to return a value like any other. +Since we're using a mostly functional form, we'll have it evaluate its +conditional, then return the 'then' or 'else' value based on how the condition +was resolved. This is very similar to the C "?:" expression.

    + +

    The semantics of the if/then/else expression is that it evaluates the +condition to a boolean equality value: 0.0 is considered to be false and +everything else is considered to be true. +If the condition is true, the first subexpression is evaluated and returned, if +the condition is false, the second subexpression is evaluated and returned. +Since Kaleidoscope allows side-effects, this behavior is important to nail down. +

    + +

    Now that we know what we "want", lets break this down into its constituent +pieces.

    + +
    + + + + + + +
    + +

    The lexer extensions are straightforward. First we add new enum values +for the relevant tokens:

    + +
    +
    +  // control
    +  tok_if = -6, tok_then = -7, tok_else = -8,
    +
    +
    + +

    Once we have that, we recognize the new keywords in the lexer. This is pretty simple +stuff:

    + +
    +
    +    ...
    +    if (IdentifierStr == "def") return tok_def;
    +    if (IdentifierStr == "extern") return tok_extern;
    +    if (IdentifierStr == "if") return tok_if;
    +    if (IdentifierStr == "then") return tok_then;
    +    if (IdentifierStr == "else") return tok_else;
    +    return tok_identifier;
    +
    +
    + +
    + + + + + +
    + +

    To represent the new expression we add a new AST node for it:

    + +
    +
    +/// IfExprAST - Expression class for if/then/else.
    +class IfExprAST : public ExprAST {
    +  ExprAST *Cond, *Then, *Else;
    +public:
    +  IfExprAST(ExprAST *cond, ExprAST *then, ExprAST *_else)
    +    : Cond(cond), Then(then), Else(_else) {}
    +  virtual Value *Codegen();
    +};
    +
    +
    + +

    The AST node just has pointers to the various subexpressions.

    + +
    + + + + + +
    + +

    Now that we have the relevant tokens coming from the lexer and we have the +AST node to build, our parsing logic is relatively straightforward. First we +define a new parsing function:

    + +
    +
    +/// ifexpr ::= 'if' expression 'then' expression 'else' expression
    +static ExprAST *ParseIfExpr() {
    +  getNextToken();  // eat the if.
    +  
    +  // condition.
    +  ExprAST *Cond = ParseExpression();
    +  if (!Cond) return 0;
    +  
    +  if (CurTok != tok_then)
    +    return Error("expected then");
    +  getNextToken();  // eat the then
    +  
    +  ExprAST *Then = ParseExpression();
    +  if (Then == 0) return 0;
    +  
    +  if (CurTok != tok_else)
    +    return Error("expected else");
    +  
    +  getNextToken();
    +  
    +  ExprAST *Else = ParseExpression();
    +  if (!Else) return 0;
    +  
    +  return new IfExprAST(Cond, Then, Else);
    +}
    +
    +
    + +

    Next we hook it up as a primary expression:

    + +
    +
    +static ExprAST *ParsePrimary() {
    +  switch (CurTok) {
    +  default: return Error("unknown token when expecting an expression");
    +  case tok_identifier: return ParseIdentifierExpr();
    +  case tok_number:     return ParseNumberExpr();
    +  case '(':            return ParseParenExpr();
    +  case tok_if:         return ParseIfExpr();
    +  }
    +}
    +
    +
    + +
    + + + + + +
    + +

    Now that we have it parsing and building the AST, the final piece is adding +LLVM code generation support. This is the most interesting part of the +if/then/else example, because this is where it starts to introduce new concepts. +All of the code above has been thoroughly described in previous chapters. +

    + +

    To motivate the code we want to produce, lets take a look at a simple +example. Consider:

    + +
    +
    +extern foo();
    +extern bar();
    +def baz(x) if x then foo() else bar();
    +
    +
    + +

    If you disable optimizations, the code you'll (soon) get from Kaleidoscope +looks like this:

    + +
    +
    +declare double @foo()
    +
    +declare double @bar()
    +
    +define double @baz(double %x) {
    +entry:
    +	%ifcond = fcmp one double %x, 0.000000e+00
    +	br i1 %ifcond, label %then, label %else
    +
    +then:		; preds = %entry
    +	%calltmp = call double @foo()
    +	br label %ifcont
    +
    +else:		; preds = %entry
    +	%calltmp1 = call double @bar()
    +	br label %ifcont
    +
    +ifcont:		; preds = %else, %then
    +	%iftmp = phi double [ %calltmp, %then ], [ %calltmp1, %else ]
    +	ret double %iftmp
    +}
    +
    +
    + +

    To visualize the control flow graph, you can use a nifty feature of the LLVM +'opt' tool. If you put this LLVM IR +into "t.ll" and run "llvm-as < t.ll | opt -analyze -view-cfg", a window will pop up and you'll +see this graph:

    + +
    Example CFG
    + +

    Another way to get this is to call "F->viewCFG()" or +"F->viewCFGOnly()" (where F is a "Function*") either by +inserting actual calls into the code and recompiling or by calling these in the +debugger. LLVM has many nice features for visualizing various graphs.

    + +

    Getting back to the generated code, it is fairly simple: the entry block +evaluates the conditional expression ("x" in our case here) and compares the +result to 0.0 with the "fcmp one" +instruction ('one' is "Ordered and Not Equal"). Based on the result of this +expression, the code jumps to either the "then" or "else" blocks, which contain +the expressions for the true/false cases.

    + +

    Once the then/else blocks are finished executing, they both branch back to the +'ifcont' block to execute the code that happens after the if/then/else. In this +case the only thing left to do is to return to the caller of the function. The +question then becomes: how does the code know which expression to return?

    + +

    The answer to this question involves an important SSA operation: the +Phi +operation. If you're not familiar with SSA, the wikipedia +article is a good introduction and there are various other introductions to +it available on your favorite search engine. The short version is that +"execution" of the Phi operation requires "remembering" which block control came +from. The Phi operation takes on the value corresponding to the input control +block. In this case, if control comes in from the "then" block, it gets the +value of "calltmp". If control comes from the "else" block, it gets the value +of "calltmp1".

    + +

    At this point, you are probably starting to think "Oh no! This means my +simple and elegant front-end will have to start generating SSA form in order to +use LLVM!". Fortunately, this is not the case, and we strongly advise +not implementing an SSA construction algorithm in your front-end +unless there is an amazingly good reason to do so. In practice, there are two +sorts of values that float around in code written for your average imperative +programming language that might need Phi nodes:

    + +
      +
    1. Code that involves user variables: x = 1; x = x + 1;
    2. +
    3. Values that are implicit in the structure of your AST, such as the Phi node +in this case.
    4. +
    + +

    In Chapter 7 of this tutorial ("mutable +variables"), we'll talk about #1 +in depth. For now, just believe me that you don't need SSA construction to +handle this case. For #2, you have the choice of using the techniques that we will +describe for #1, or you can insert Phi nodes directly, if convenient. In this +case, it is really really easy to generate the Phi node, so we choose to do it +directly.

    + +

    Okay, enough of the motivation and overview, lets generate code!

    + +
    + + + + + +
    + +

    In order to generate code for this, we implement the Codegen method +for IfExprAST:

    + +
    +
    +Value *IfExprAST::Codegen() {
    +  Value *CondV = Cond->Codegen();
    +  if (CondV == 0) return 0;
    +  
    +  // Convert condition to a bool by comparing equal to 0.0.
    +  CondV = Builder.CreateFCmpONE(CondV, 
    +                              ConstantFP::get(getGlobalContext(), APFloat(0.0)),
    +                                "ifcond");
    +
    +
    + +

    This code is straightforward and similar to what we saw before. We emit the +expression for the condition, then compare that value to zero to get a truth +value as a 1-bit (bool) value.

    + +
    +
    +  Function *TheFunction = Builder.GetInsertBlock()->getParent();
    +  
    +  // Create blocks for the then and else cases.  Insert the 'then' block at the
    +  // end of the function.
    +  BasicBlock *ThenBB = BasicBlock::Create(getGlobalContext(), "then", TheFunction);
    +  BasicBlock *ElseBB = BasicBlock::Create(getGlobalContext(), "else");
    +  BasicBlock *MergeBB = BasicBlock::Create(getGlobalContext(), "ifcont");
    +
    +  Builder.CreateCondBr(CondV, ThenBB, ElseBB);
    +
    +
    + +

    This code creates the basic blocks that are related to the if/then/else +statement, and correspond directly to the blocks in the example above. The +first line gets the current Function object that is being built. It +gets this by asking the builder for the current BasicBlock, and asking that +block for its "parent" (the function it is currently embedded into).

    + +

    Once it has that, it creates three blocks. Note that it passes "TheFunction" +into the constructor for the "then" block. This causes the constructor to +automatically insert the new block into the end of the specified function. The +other two blocks are created, but aren't yet inserted into the function.

    + +

    Once the blocks are created, we can emit the conditional branch that chooses +between them. Note that creating new blocks does not implicitly affect the +IRBuilder, so it is still inserting into the block that the condition +went into. Also note that it is creating a branch to the "then" block and the +"else" block, even though the "else" block isn't inserted into the function yet. +This is all ok: it is the standard way that LLVM supports forward +references.

    + +
    +
    +  // Emit then value.
    +  Builder.SetInsertPoint(ThenBB);
    +  
    +  Value *ThenV = Then->Codegen();
    +  if (ThenV == 0) return 0;
    +  
    +  Builder.CreateBr(MergeBB);
    +  // Codegen of 'Then' can change the current block, update ThenBB for the PHI.
    +  ThenBB = Builder.GetInsertBlock();
    +
    +
    + +

    After the conditional branch is inserted, we move the builder to start +inserting into the "then" block. Strictly speaking, this call moves the +insertion point to be at the end of the specified block. However, since the +"then" block is empty, it also starts out by inserting at the beginning of the +block. :)

    + +

    Once the insertion point is set, we recursively codegen the "then" expression +from the AST. To finish off the "then" block, we create an unconditional branch +to the merge block. One interesting (and very important) aspect of the LLVM IR +is that it requires all basic blocks +to be "terminated" with a control flow +instruction such as return or branch. This means that all control flow, +including fall throughs must be made explicit in the LLVM IR. If you +violate this rule, the verifier will emit an error.

    + +

    The final line here is quite subtle, but is very important. The basic issue +is that when we create the Phi node in the merge block, we need to set up the +block/value pairs that indicate how the Phi will work. Importantly, the Phi +node expects to have an entry for each predecessor of the block in the CFG. Why +then, are we getting the current block when we just set it to ThenBB 5 lines +above? The problem is that the "Then" expression may actually itself change the +block that the Builder is emitting into if, for example, it contains a nested +"if/then/else" expression. Because calling Codegen recursively could +arbitrarily change the notion of the current block, we are required to get an +up-to-date value for code that will set up the Phi node.

    + +
    +
    +  // Emit else block.
    +  TheFunction->getBasicBlockList().push_back(ElseBB);
    +  Builder.SetInsertPoint(ElseBB);
    +  
    +  Value *ElseV = Else->Codegen();
    +  if (ElseV == 0) return 0;
    +  
    +  Builder.CreateBr(MergeBB);
    +  // Codegen of 'Else' can change the current block, update ElseBB for the PHI.
    +  ElseBB = Builder.GetInsertBlock();
    +
    +
    + +

    Code generation for the 'else' block is basically identical to codegen for +the 'then' block. The only significant difference is the first line, which adds +the 'else' block to the function. Recall previously that the 'else' block was +created, but not added to the function. Now that the 'then' and 'else' blocks +are emitted, we can finish up with the merge code:

    + +
    +
    +  // Emit merge block.
    +  TheFunction->getBasicBlockList().push_back(MergeBB);
    +  Builder.SetInsertPoint(MergeBB);
    +  PHINode *PN = Builder.CreatePHI(Type::getDoubleTy(getGlobalContext()),
    +                                  "iftmp");
    +  
    +  PN->addIncoming(ThenV, ThenBB);
    +  PN->addIncoming(ElseV, ElseBB);
    +  return PN;
    +}
    +
    +
    + +

    The first two lines here are now familiar: the first adds the "merge" block +to the Function object (it was previously floating, like the else block above). +The second block changes the insertion point so that newly created code will go +into the "merge" block. Once that is done, we need to create the PHI node and +set up the block/value pairs for the PHI.

    + +

    Finally, the CodeGen function returns the phi node as the value computed by +the if/then/else expression. In our example above, this returned value will +feed into the code for the top-level function, which will create the return +instruction.

    + +

    Overall, we now have the ability to execute conditional code in +Kaleidoscope. With this extension, Kaleidoscope is a fairly complete language +that can calculate a wide variety of numeric functions. Next up we'll add +another useful expression that is familiar from non-functional languages...

    + +
    + + + + + +
    + +

    Now that we know how to add basic control flow constructs to the language, +we have the tools to add more powerful things. Lets add something more +aggressive, a 'for' expression:

    + +
    +
    + extern putchard(char)
    + def printstar(n)
    +   for i = 1, i < n, 1.0 in
    +     putchard(42);  # ascii 42 = '*'
    +     
    + # print 100 '*' characters
    + printstar(100);
    +
    +
    + +

    This expression defines a new variable ("i" in this case) which iterates from +a starting value, while the condition ("i < n" in this case) is true, +incrementing by an optional step value ("1.0" in this case). If the step value +is omitted, it defaults to 1.0. While the loop is true, it executes its +body expression. Because we don't have anything better to return, we'll just +define the loop as always returning 0.0. In the future when we have mutable +variables, it will get more useful.

    + +

    As before, lets talk about the changes that we need to Kaleidoscope to +support this.

    + +
    + + + + + +
    + +

    The lexer extensions are the same sort of thing as for if/then/else:

    + +
    +
    +  ... in enum Token ...
    +  // control
    +  tok_if = -6, tok_then = -7, tok_else = -8,
    +  tok_for = -9, tok_in = -10
    +
    +  ... in gettok ...
    +  if (IdentifierStr == "def") return tok_def;
    +  if (IdentifierStr == "extern") return tok_extern;
    +  if (IdentifierStr == "if") return tok_if;
    +  if (IdentifierStr == "then") return tok_then;
    +  if (IdentifierStr == "else") return tok_else;
    +  if (IdentifierStr == "for") return tok_for;
    +  if (IdentifierStr == "in") return tok_in;
    +  return tok_identifier;
    +
    +
    + +
    + + + + + +
    + +

    The AST node is just as simple. It basically boils down to capturing +the variable name and the constituent expressions in the node.

    + +
    +
    +/// ForExprAST - Expression class for for/in.
    +class ForExprAST : public ExprAST {
    +  std::string VarName;
    +  ExprAST *Start, *End, *Step, *Body;
    +public:
    +  ForExprAST(const std::string &varname, ExprAST *start, ExprAST *end,
    +             ExprAST *step, ExprAST *body)
    +    : VarName(varname), Start(start), End(end), Step(step), Body(body) {}
    +  virtual Value *Codegen();
    +};
    +
    +
    + +
    + + + + + +
    + +

    The parser code is also fairly standard. The only interesting thing here is +handling of the optional step value. The parser code handles it by checking to +see if the second comma is present. If not, it sets the step value to null in +the AST node:

    + +
    +
    +/// forexpr ::= 'for' identifier '=' expr ',' expr (',' expr)? 'in' expression
    +static ExprAST *ParseForExpr() {
    +  getNextToken();  // eat the for.
    +
    +  if (CurTok != tok_identifier)
    +    return Error("expected identifier after for");
    +  
    +  std::string IdName = IdentifierStr;
    +  getNextToken();  // eat identifier.
    +  
    +  if (CurTok != '=')
    +    return Error("expected '=' after for");
    +  getNextToken();  // eat '='.
    +  
    +  
    +  ExprAST *Start = ParseExpression();
    +  if (Start == 0) return 0;
    +  if (CurTok != ',')
    +    return Error("expected ',' after for start value");
    +  getNextToken();
    +  
    +  ExprAST *End = ParseExpression();
    +  if (End == 0) return 0;
    +  
    +  // The step value is optional.
    +  ExprAST *Step = 0;
    +  if (CurTok == ',') {
    +    getNextToken();
    +    Step = ParseExpression();
    +    if (Step == 0) return 0;
    +  }
    +  
    +  if (CurTok != tok_in)
    +    return Error("expected 'in' after for");
    +  getNextToken();  // eat 'in'.
    +  
    +  ExprAST *Body = ParseExpression();
    +  if (Body == 0) return 0;
    +
    +  return new ForExprAST(IdName, Start, End, Step, Body);
    +}
    +
    +
    + +
    + + + + + +
    + +

    Now we get to the good part: the LLVM IR we want to generate for this thing. +With the simple example above, we get this LLVM IR (note that this dump is +generated with optimizations disabled for clarity): +

    + +
    +
    +declare double @putchard(double)
    +
    +define double @printstar(double %n) {
    +entry:
    +        ; initial value = 1.0 (inlined into phi)
    +	br label %loop
    +
    +loop:		; preds = %loop, %entry
    +	%i = phi double [ 1.000000e+00, %entry ], [ %nextvar, %loop ]
    +        ; body
    +	%calltmp = call double @putchard( double 4.200000e+01 )
    +        ; increment
    +	%nextvar = add double %i, 1.000000e+00
    +
    +        ; termination test
    +	%cmptmp = fcmp ult double %i, %n
    +	%booltmp = uitofp i1 %cmptmp to double
    +	%loopcond = fcmp one double %booltmp, 0.000000e+00
    +	br i1 %loopcond, label %loop, label %afterloop
    +
    +afterloop:		; preds = %loop
    +        ; loop always returns 0.0
    +	ret double 0.000000e+00
    +}
    +
    +
    + +

    This loop contains all the same constructs we saw before: a phi node, several +expressions, and some basic blocks. Lets see how this fits together.

    + +
    + + + + + +
    + +

    The first part of Codegen is very simple: we just output the start expression +for the loop value:

    + +
    +
    +Value *ForExprAST::Codegen() {
    +  // Emit the start code first, without 'variable' in scope.
    +  Value *StartVal = Start->Codegen();
    +  if (StartVal == 0) return 0;
    +
    +
    + +

    With this out of the way, the next step is to set up the LLVM basic block +for the start of the loop body. In the case above, the whole loop body is one +block, but remember that the body code itself could consist of multiple blocks +(e.g. if it contains an if/then/else or a for/in expression).

    + +
    +
    +  // Make the new basic block for the loop header, inserting after current
    +  // block.
    +  Function *TheFunction = Builder.GetInsertBlock()->getParent();
    +  BasicBlock *PreheaderBB = Builder.GetInsertBlock();
    +  BasicBlock *LoopBB = BasicBlock::Create(getGlobalContext(), "loop", TheFunction);
    +  
    +  // Insert an explicit fall through from the current block to the LoopBB.
    +  Builder.CreateBr(LoopBB);
    +
    +
    + +

    This code is similar to what we saw for if/then/else. Because we will need +it to create the Phi node, we remember the block that falls through into the +loop. Once we have that, we create the actual block that starts the loop and +create an unconditional branch for the fall-through between the two blocks.

    + +
    +
    +  // Start insertion in LoopBB.
    +  Builder.SetInsertPoint(LoopBB);
    +  
    +  // Start the PHI node with an entry for Start.
    +  PHINode *Variable = Builder.CreatePHI(Type::getDoubleTy(getGlobalContext()), VarName.c_str());
    +  Variable->addIncoming(StartVal, PreheaderBB);
    +
    +
    + +

    Now that the "preheader" for the loop is set up, we switch to emitting code +for the loop body. To begin with, we move the insertion point and create the +PHI node for the loop induction variable. Since we already know the incoming +value for the starting value, we add it to the Phi node. Note that the Phi will +eventually get a second value for the backedge, but we can't set it up yet +(because it doesn't exist!).

    + +
    +
    +  // Within the loop, the variable is defined equal to the PHI node.  If it
    +  // shadows an existing variable, we have to restore it, so save it now.
    +  Value *OldVal = NamedValues[VarName];
    +  NamedValues[VarName] = Variable;
    +  
    +  // Emit the body of the loop.  This, like any other expr, can change the
    +  // current BB.  Note that we ignore the value computed by the body, but don't
    +  // allow an error.
    +  if (Body->Codegen() == 0)
    +    return 0;
    +
    +
    + +

    Now the code starts to get more interesting. Our 'for' loop introduces a new +variable to the symbol table. This means that our symbol table can now contain +either function arguments or loop variables. To handle this, before we codegen +the body of the loop, we add the loop variable as the current value for its +name. Note that it is possible that there is a variable of the same name in the +outer scope. It would be easy to make this an error (emit an error and return +null if there is already an entry for VarName) but we choose to allow shadowing +of variables. In order to handle this correctly, we remember the Value that +we are potentially shadowing in OldVal (which will be null if there is +no shadowed variable).

    + +

    Once the loop variable is set into the symbol table, the code recursively +codegen's the body. This allows the body to use the loop variable: any +references to it will naturally find it in the symbol table.

    + +
    +
    +  // Emit the step value.
    +  Value *StepVal;
    +  if (Step) {
    +    StepVal = Step->Codegen();
    +    if (StepVal == 0) return 0;
    +  } else {
    +    // If not specified, use 1.0.
    +    StepVal = ConstantFP::get(getGlobalContext(), APFloat(1.0));
    +  }
    +  
    +  Value *NextVar = Builder.CreateAdd(Variable, StepVal, "nextvar");
    +
    +
    + +

    Now that the body is emitted, we compute the next value of the iteration +variable by adding the step value, or 1.0 if it isn't present. 'NextVar' +will be the value of the loop variable on the next iteration of the loop.

    + +
    +
    +  // Compute the end condition.
    +  Value *EndCond = End->Codegen();
    +  if (EndCond == 0) return EndCond;
    +  
    +  // Convert condition to a bool by comparing equal to 0.0.
    +  EndCond = Builder.CreateFCmpONE(EndCond, 
    +                              ConstantFP::get(getGlobalContext(), APFloat(0.0)),
    +                                  "loopcond");
    +
    +
    + +

    Finally, we evaluate the exit value of the loop, to determine whether the +loop should exit. This mirrors the condition evaluation for the if/then/else +statement.

    + +
    +
    +  // Create the "after loop" block and insert it.
    +  BasicBlock *LoopEndBB = Builder.GetInsertBlock();
    +  BasicBlock *AfterBB = BasicBlock::Create(getGlobalContext(), "afterloop", TheFunction);
    +  
    +  // Insert the conditional branch into the end of LoopEndBB.
    +  Builder.CreateCondBr(EndCond, LoopBB, AfterBB);
    +  
    +  // Any new code will be inserted in AfterBB.
    +  Builder.SetInsertPoint(AfterBB);
    +
    +
    + +

    With the code for the body of the loop complete, we just need to finish up +the control flow for it. This code remembers the end block (for the phi node), then creates the block for the loop exit ("afterloop"). Based on the value of the +exit condition, it creates a conditional branch that chooses between executing +the loop again and exiting the loop. Any future code is emitted in the +"afterloop" block, so it sets the insertion position to it.

    + +
    +
    +  // Add a new entry to the PHI node for the backedge.
    +  Variable->addIncoming(NextVar, LoopEndBB);
    +  
    +  // Restore the unshadowed variable.
    +  if (OldVal)
    +    NamedValues[VarName] = OldVal;
    +  else
    +    NamedValues.erase(VarName);
    +  
    +  // for expr always returns 0.0.
    +  return Constant::getNullValue(Type::getDoubleTy(getGlobalContext()));
    +}
    +
    +
    + +

    The final code handles various cleanups: now that we have the "NextVar" +value, we can add the incoming value to the loop PHI node. After that, we +remove the loop variable from the symbol table, so that it isn't in scope after +the for loop. Finally, code generation of the for loop always returns 0.0, so +that is what we return from ForExprAST::Codegen.

    + +

    With this, we conclude the "adding control flow to Kaleidoscope" chapter of +the tutorial. In this chapter we added two control flow constructs, and used them to motivate a couple of aspects of the LLVM IR that are important for front-end implementors +to know. In the next chapter of our saga, we will get a bit crazier and add +user-defined operators to our poor innocent +language.

    + +
    + + + + + +
    + +

    +Here is the complete code listing for our running example, enhanced with the +if/then/else and for expressions.. To build this example, use: +

    + +
    +
    +   # Compile
    +   g++ -g toy.cpp `llvm-config --cppflags --ldflags --libs core jit native` -O3 -o toy
    +   # Run
    +   ./toy
    +
    +
    + +

    Here is the code:

    + +
    +
    +#include "llvm/DerivedTypes.h"
    +#include "llvm/ExecutionEngine/ExecutionEngine.h"
    +#include "llvm/ExecutionEngine/Interpreter.h"
    +#include "llvm/ExecutionEngine/JIT.h"
    +#include "llvm/LLVMContext.h"
    +#include "llvm/Module.h"
    +#include "llvm/ModuleProvider.h"
    +#include "llvm/PassManager.h"
    +#include "llvm/Analysis/Verifier.h"
    +#include "llvm/Target/TargetData.h"
    +#include "llvm/Target/TargetSelect.h"
    +#include "llvm/Transforms/Scalar.h"
    +#include "llvm/Support/IRBuilder.h"
    +#include <cstdio>
    +#include <string>
    +#include <map>
    +#include <vector>
    +using namespace llvm;
    +
    +//===----------------------------------------------------------------------===//
    +// Lexer
    +//===----------------------------------------------------------------------===//
    +
    +// The lexer returns tokens [0-255] if it is an unknown character, otherwise one
    +// of these for known things.
    +enum Token {
    +  tok_eof = -1,
    +
    +  // commands
    +  tok_def = -2, tok_extern = -3,
    +
    +  // primary
    +  tok_identifier = -4, tok_number = -5,
    +  
    +  // control
    +  tok_if = -6, tok_then = -7, tok_else = -8,
    +  tok_for = -9, tok_in = -10
    +};
    +
    +static std::string IdentifierStr;  // Filled in if tok_identifier
    +static double NumVal;              // Filled in if tok_number
    +
    +/// gettok - Return the next token from standard input.
    +static int gettok() {
    +  static int LastChar = ' ';
    +
    +  // Skip any whitespace.
    +  while (isspace(LastChar))
    +    LastChar = getchar();
    +
    +  if (isalpha(LastChar)) { // identifier: [a-zA-Z][a-zA-Z0-9]*
    +    IdentifierStr = LastChar;
    +    while (isalnum((LastChar = getchar())))
    +      IdentifierStr += LastChar;
    +
    +    if (IdentifierStr == "def") return tok_def;
    +    if (IdentifierStr == "extern") return tok_extern;
    +    if (IdentifierStr == "if") return tok_if;
    +    if (IdentifierStr == "then") return tok_then;
    +    if (IdentifierStr == "else") return tok_else;
    +    if (IdentifierStr == "for") return tok_for;
    +    if (IdentifierStr == "in") return tok_in;
    +    return tok_identifier;
    +  }
    +
    +  if (isdigit(LastChar) || LastChar == '.') {   // Number: [0-9.]+
    +    std::string NumStr;
    +    do {
    +      NumStr += LastChar;
    +      LastChar = getchar();
    +    } while (isdigit(LastChar) || LastChar == '.');
    +
    +    NumVal = strtod(NumStr.c_str(), 0);
    +    return tok_number;
    +  }
    +
    +  if (LastChar == '#') {
    +    // Comment until end of line.
    +    do LastChar = getchar();
    +    while (LastChar != EOF && LastChar != '\n' && LastChar != '\r');
    +    
    +    if (LastChar != EOF)
    +      return gettok();
    +  }
    +  
    +  // Check for end of file.  Don't eat the EOF.
    +  if (LastChar == EOF)
    +    return tok_eof;
    +
    +  // Otherwise, just return the character as its ascii value.
    +  int ThisChar = LastChar;
    +  LastChar = getchar();
    +  return ThisChar;
    +}
    +
    +//===----------------------------------------------------------------------===//
    +// Abstract Syntax Tree (aka Parse Tree)
    +//===----------------------------------------------------------------------===//
    +
    +/// ExprAST - Base class for all expression nodes.
    +class ExprAST {
    +public:
    +  virtual ~ExprAST() {}
    +  virtual Value *Codegen() = 0;
    +};
    +
    +/// NumberExprAST - Expression class for numeric literals like "1.0".
    +class NumberExprAST : public ExprAST {
    +  double Val;
    +public:
    +  NumberExprAST(double val) : Val(val) {}
    +  virtual Value *Codegen();
    +};
    +
    +/// VariableExprAST - Expression class for referencing a variable, like "a".
    +class VariableExprAST : public ExprAST {
    +  std::string Name;
    +public:
    +  VariableExprAST(const std::string &name) : Name(name) {}
    +  virtual Value *Codegen();
    +};
    +
    +/// BinaryExprAST - Expression class for a binary operator.
    +class BinaryExprAST : public ExprAST {
    +  char Op;
    +  ExprAST *LHS, *RHS;
    +public:
    +  BinaryExprAST(char op, ExprAST *lhs, ExprAST *rhs) 
    +    : Op(op), LHS(lhs), RHS(rhs) {}
    +  virtual Value *Codegen();
    +};
    +
    +/// CallExprAST - Expression class for function calls.
    +class CallExprAST : public ExprAST {
    +  std::string Callee;
    +  std::vector<ExprAST*> Args;
    +public:
    +  CallExprAST(const std::string &callee, std::vector<ExprAST*> &args)
    +    : Callee(callee), Args(args) {}
    +  virtual Value *Codegen();
    +};
    +
    +/// IfExprAST - Expression class for if/then/else.
    +class IfExprAST : public ExprAST {
    +  ExprAST *Cond, *Then, *Else;
    +public:
    +  IfExprAST(ExprAST *cond, ExprAST *then, ExprAST *_else)
    +  : Cond(cond), Then(then), Else(_else) {}
    +  virtual Value *Codegen();
    +};
    +
    +/// ForExprAST - Expression class for for/in.
    +class ForExprAST : public ExprAST {
    +  std::string VarName;
    +  ExprAST *Start, *End, *Step, *Body;
    +public:
    +  ForExprAST(const std::string &varname, ExprAST *start, ExprAST *end,
    +             ExprAST *step, ExprAST *body)
    +    : VarName(varname), Start(start), End(end), Step(step), Body(body) {}
    +  virtual Value *Codegen();
    +};
    +
    +/// PrototypeAST - This class represents the "prototype" for a function,
    +/// which captures its name, and its argument names (thus implicitly the number
    +/// of arguments the function takes).
    +class PrototypeAST {
    +  std::string Name;
    +  std::vector<std::string> Args;
    +public:
    +  PrototypeAST(const std::string &name, const std::vector<std::string> &args)
    +    : Name(name), Args(args) {}
    +  
    +  Function *Codegen();
    +};
    +
    +/// FunctionAST - This class represents a function definition itself.
    +class FunctionAST {
    +  PrototypeAST *Proto;
    +  ExprAST *Body;
    +public:
    +  FunctionAST(PrototypeAST *proto, ExprAST *body)
    +    : Proto(proto), Body(body) {}
    +  
    +  Function *Codegen();
    +};
    +
    +//===----------------------------------------------------------------------===//
    +// Parser
    +//===----------------------------------------------------------------------===//
    +
    +/// CurTok/getNextToken - Provide a simple token buffer.  CurTok is the current
    +/// token the parser is looking at.  getNextToken reads another token from the
    +/// lexer and updates CurTok with its results.
    +static int CurTok;
    +static int getNextToken() {
    +  return CurTok = gettok();
    +}
    +
    +/// BinopPrecedence - This holds the precedence for each binary operator that is
    +/// defined.
    +static std::map<char, int> BinopPrecedence;
    +
    +/// GetTokPrecedence - Get the precedence of the pending binary operator token.
    +static int GetTokPrecedence() {
    +  if (!isascii(CurTok))
    +    return -1;
    +  
    +  // Make sure it's a declared binop.
    +  int TokPrec = BinopPrecedence[CurTok];
    +  if (TokPrec <= 0) return -1;
    +  return TokPrec;
    +}
    +
    +/// Error* - These are little helper functions for error handling.
    +ExprAST *Error(const char *Str) { fprintf(stderr, "Error: %s\n", Str);return 0;}
    +PrototypeAST *ErrorP(const char *Str) { Error(Str); return 0; }
    +FunctionAST *ErrorF(const char *Str) { Error(Str); return 0; }
    +
    +static ExprAST *ParseExpression();
    +
    +/// identifierexpr
    +///   ::= identifier
    +///   ::= identifier '(' expression* ')'
    +static ExprAST *ParseIdentifierExpr() {
    +  std::string IdName = IdentifierStr;
    +  
    +  getNextToken();  // eat identifier.
    +  
    +  if (CurTok != '(') // Simple variable ref.
    +    return new VariableExprAST(IdName);
    +  
    +  // Call.
    +  getNextToken();  // eat (
    +  std::vector<ExprAST*> Args;
    +  if (CurTok != ')') {
    +    while (1) {
    +      ExprAST *Arg = ParseExpression();
    +      if (!Arg) return 0;
    +      Args.push_back(Arg);
    +
    +      if (CurTok == ')') break;
    +
    +      if (CurTok != ',')
    +        return Error("Expected ')' or ',' in argument list");
    +      getNextToken();
    +    }
    +  }
    +
    +  // Eat the ')'.
    +  getNextToken();
    +  
    +  return new CallExprAST(IdName, Args);
    +}
    +
    +/// numberexpr ::= number
    +static ExprAST *ParseNumberExpr() {
    +  ExprAST *Result = new NumberExprAST(NumVal);
    +  getNextToken(); // consume the number
    +  return Result;
    +}
    +
    +/// parenexpr ::= '(' expression ')'
    +static ExprAST *ParseParenExpr() {
    +  getNextToken();  // eat (.
    +  ExprAST *V = ParseExpression();
    +  if (!V) return 0;
    +  
    +  if (CurTok != ')')
    +    return Error("expected ')'");
    +  getNextToken();  // eat ).
    +  return V;
    +}
    +
    +/// ifexpr ::= 'if' expression 'then' expression 'else' expression
    +static ExprAST *ParseIfExpr() {
    +  getNextToken();  // eat the if.
    +  
    +  // condition.
    +  ExprAST *Cond = ParseExpression();
    +  if (!Cond) return 0;
    +  
    +  if (CurTok != tok_then)
    +    return Error("expected then");
    +  getNextToken();  // eat the then
    +  
    +  ExprAST *Then = ParseExpression();
    +  if (Then == 0) return 0;
    +  
    +  if (CurTok != tok_else)
    +    return Error("expected else");
    +  
    +  getNextToken();
    +  
    +  ExprAST *Else = ParseExpression();
    +  if (!Else) return 0;
    +  
    +  return new IfExprAST(Cond, Then, Else);
    +}
    +
    +/// forexpr ::= 'for' identifier '=' expr ',' expr (',' expr)? 'in' expression
    +static ExprAST *ParseForExpr() {
    +  getNextToken();  // eat the for.
    +
    +  if (CurTok != tok_identifier)
    +    return Error("expected identifier after for");
    +  
    +  std::string IdName = IdentifierStr;
    +  getNextToken();  // eat identifier.
    +  
    +  if (CurTok != '=')
    +    return Error("expected '=' after for");
    +  getNextToken();  // eat '='.
    +  
    +  
    +  ExprAST *Start = ParseExpression();
    +  if (Start == 0) return 0;
    +  if (CurTok != ',')
    +    return Error("expected ',' after for start value");
    +  getNextToken();
    +  
    +  ExprAST *End = ParseExpression();
    +  if (End == 0) return 0;
    +  
    +  // The step value is optional.
    +  ExprAST *Step = 0;
    +  if (CurTok == ',') {
    +    getNextToken();
    +    Step = ParseExpression();
    +    if (Step == 0) return 0;
    +  }
    +  
    +  if (CurTok != tok_in)
    +    return Error("expected 'in' after for");
    +  getNextToken();  // eat 'in'.
    +  
    +  ExprAST *Body = ParseExpression();
    +  if (Body == 0) return 0;
    +
    +  return new ForExprAST(IdName, Start, End, Step, Body);
    +}
    +
    +/// primary
    +///   ::= identifierexpr
    +///   ::= numberexpr
    +///   ::= parenexpr
    +///   ::= ifexpr
    +///   ::= forexpr
    +static ExprAST *ParsePrimary() {
    +  switch (CurTok) {
    +  default: return Error("unknown token when expecting an expression");
    +  case tok_identifier: return ParseIdentifierExpr();
    +  case tok_number:     return ParseNumberExpr();
    +  case '(':            return ParseParenExpr();
    +  case tok_if:         return ParseIfExpr();
    +  case tok_for:        return ParseForExpr();
    +  }
    +}
    +
    +/// binoprhs
    +///   ::= ('+' primary)*
    +static ExprAST *ParseBinOpRHS(int ExprPrec, ExprAST *LHS) {
    +  // If this is a binop, find its precedence.
    +  while (1) {
    +    int TokPrec = GetTokPrecedence();
    +    
    +    // If this is a binop that binds at least as tightly as the current binop,
    +    // consume it, otherwise we are done.
    +    if (TokPrec < ExprPrec)
    +      return LHS;
    +    
    +    // Okay, we know this is a binop.
    +    int BinOp = CurTok;
    +    getNextToken();  // eat binop
    +    
    +    // Parse the primary expression after the binary operator.
    +    ExprAST *RHS = ParsePrimary();
    +    if (!RHS) return 0;
    +    
    +    // If BinOp binds less tightly with RHS than the operator after RHS, let
    +    // the pending operator take RHS as its LHS.
    +    int NextPrec = GetTokPrecedence();
    +    if (TokPrec < NextPrec) {
    +      RHS = ParseBinOpRHS(TokPrec+1, RHS);
    +      if (RHS == 0) return 0;
    +    }
    +    
    +    // Merge LHS/RHS.
    +    LHS = new BinaryExprAST(BinOp, LHS, RHS);
    +  }
    +}
    +
    +/// expression
    +///   ::= primary binoprhs
    +///
    +static ExprAST *ParseExpression() {
    +  ExprAST *LHS = ParsePrimary();
    +  if (!LHS) return 0;
    +  
    +  return ParseBinOpRHS(0, LHS);
    +}
    +
    +/// prototype
    +///   ::= id '(' id* ')'
    +static PrototypeAST *ParsePrototype() {
    +  if (CurTok != tok_identifier)
    +    return ErrorP("Expected function name in prototype");
    +
    +  std::string FnName = IdentifierStr;
    +  getNextToken();
    +  
    +  if (CurTok != '(')
    +    return ErrorP("Expected '(' in prototype");
    +  
    +  std::vector<std::string> ArgNames;
    +  while (getNextToken() == tok_identifier)
    +    ArgNames.push_back(IdentifierStr);
    +  if (CurTok != ')')
    +    return ErrorP("Expected ')' in prototype");
    +  
    +  // success.
    +  getNextToken();  // eat ')'.
    +  
    +  return new PrototypeAST(FnName, ArgNames);
    +}
    +
    +/// definition ::= 'def' prototype expression
    +static FunctionAST *ParseDefinition() {
    +  getNextToken();  // eat def.
    +  PrototypeAST *Proto = ParsePrototype();
    +  if (Proto == 0) return 0;
    +
    +  if (ExprAST *E = ParseExpression())
    +    return new FunctionAST(Proto, E);
    +  return 0;
    +}
    +
    +/// toplevelexpr ::= expression
    +static FunctionAST *ParseTopLevelExpr() {
    +  if (ExprAST *E = ParseExpression()) {
    +    // Make an anonymous proto.
    +    PrototypeAST *Proto = new PrototypeAST("", std::vector<std::string>());
    +    return new FunctionAST(Proto, E);
    +  }
    +  return 0;
    +}
    +
    +/// external ::= 'extern' prototype
    +static PrototypeAST *ParseExtern() {
    +  getNextToken();  // eat extern.
    +  return ParsePrototype();
    +}
    +
    +//===----------------------------------------------------------------------===//
    +// Code Generation
    +//===----------------------------------------------------------------------===//
    +
    +static Module *TheModule;
    +static IRBuilder<> Builder(getGlobalContext());
    +static std::map<std::string, Value*> NamedValues;
    +static FunctionPassManager *TheFPM;
    +
    +Value *ErrorV(const char *Str) { Error(Str); return 0; }
    +
    +Value *NumberExprAST::Codegen() {
    +  return ConstantFP::get(getGlobalContext(), APFloat(Val));
    +}
    +
    +Value *VariableExprAST::Codegen() {
    +  // Look this variable up in the function.
    +  Value *V = NamedValues[Name];
    +  return V ? V : ErrorV("Unknown variable name");
    +}
    +
    +Value *BinaryExprAST::Codegen() {
    +  Value *L = LHS->Codegen();
    +  Value *R = RHS->Codegen();
    +  if (L == 0 || R == 0) return 0;
    +  
    +  switch (Op) {
    +  case '+': return Builder.CreateAdd(L, R, "addtmp");
    +  case '-': return Builder.CreateSub(L, R, "subtmp");
    +  case '*': return Builder.CreateMul(L, R, "multmp");
    +  case '<':
    +    L = Builder.CreateFCmpULT(L, R, "cmptmp");
    +    // Convert bool 0/1 to double 0.0 or 1.0
    +    return Builder.CreateUIToFP(L, Type::getDoubleTy(getGlobalContext()),
    +                                "booltmp");
    +  default: return ErrorV("invalid binary operator");
    +  }
    +}
    +
    +Value *CallExprAST::Codegen() {
    +  // Look up the name in the global module table.
    +  Function *CalleeF = TheModule->getFunction(Callee);
    +  if (CalleeF == 0)
    +    return ErrorV("Unknown function referenced");
    +  
    +  // If argument mismatch error.
    +  if (CalleeF->arg_size() != Args.size())
    +    return ErrorV("Incorrect # arguments passed");
    +
    +  std::vector<Value*> ArgsV;
    +  for (unsigned i = 0, e = Args.size(); i != e; ++i) {
    +    ArgsV.push_back(Args[i]->Codegen());
    +    if (ArgsV.back() == 0) return 0;
    +  }
    +  
    +  return Builder.CreateCall(CalleeF, ArgsV.begin(), ArgsV.end(), "calltmp");
    +}
    +
    +Value *IfExprAST::Codegen() {
    +  Value *CondV = Cond->Codegen();
    +  if (CondV == 0) return 0;
    +  
    +  // Convert condition to a bool by comparing equal to 0.0.
    +  CondV = Builder.CreateFCmpONE(CondV, 
    +                              ConstantFP::get(getGlobalContext(), APFloat(0.0)),
    +                                "ifcond");
    +  
    +  Function *TheFunction = Builder.GetInsertBlock()->getParent();
    +  
    +  // Create blocks for the then and else cases.  Insert the 'then' block at the
    +  // end of the function.
    +  BasicBlock *ThenBB = BasicBlock::Create(getGlobalContext(), "then", TheFunction);
    +  BasicBlock *ElseBB = BasicBlock::Create(getGlobalContext(), "else");
    +  BasicBlock *MergeBB = BasicBlock::Create(getGlobalContext(), "ifcont");
    +  
    +  Builder.CreateCondBr(CondV, ThenBB, ElseBB);
    +  
    +  // Emit then value.
    +  Builder.SetInsertPoint(ThenBB);
    +  
    +  Value *ThenV = Then->Codegen();
    +  if (ThenV == 0) return 0;
    +  
    +  Builder.CreateBr(MergeBB);
    +  // Codegen of 'Then' can change the current block, update ThenBB for the PHI.
    +  ThenBB = Builder.GetInsertBlock();
    +  
    +  // Emit else block.
    +  TheFunction->getBasicBlockList().push_back(ElseBB);
    +  Builder.SetInsertPoint(ElseBB);
    +  
    +  Value *ElseV = Else->Codegen();
    +  if (ElseV == 0) return 0;
    +  
    +  Builder.CreateBr(MergeBB);
    +  // Codegen of 'Else' can change the current block, update ElseBB for the PHI.
    +  ElseBB = Builder.GetInsertBlock();
    +  
    +  // Emit merge block.
    +  TheFunction->getBasicBlockList().push_back(MergeBB);
    +  Builder.SetInsertPoint(MergeBB);
    +  PHINode *PN = Builder.CreatePHI(Type::getDoubleTy(getGlobalContext()),
    +                                  "iftmp");
    +  
    +  PN->addIncoming(ThenV, ThenBB);
    +  PN->addIncoming(ElseV, ElseBB);
    +  return PN;
    +}
    +
    +Value *ForExprAST::Codegen() {
    +  // Output this as:
    +  //   ...
    +  //   start = startexpr
    +  //   goto loop
    +  // loop: 
    +  //   variable = phi [start, loopheader], [nextvariable, loopend]
    +  //   ...
    +  //   bodyexpr
    +  //   ...
    +  // loopend:
    +  //   step = stepexpr
    +  //   nextvariable = variable + step
    +  //   endcond = endexpr
    +  //   br endcond, loop, endloop
    +  // outloop:
    +  
    +  // Emit the start code first, without 'variable' in scope.
    +  Value *StartVal = Start->Codegen();
    +  if (StartVal == 0) return 0;
    +  
    +  // Make the new basic block for the loop header, inserting after current
    +  // block.
    +  Function *TheFunction = Builder.GetInsertBlock()->getParent();
    +  BasicBlock *PreheaderBB = Builder.GetInsertBlock();
    +  BasicBlock *LoopBB = BasicBlock::Create(getGlobalContext(), "loop", TheFunction);
    +  
    +  // Insert an explicit fall through from the current block to the LoopBB.
    +  Builder.CreateBr(LoopBB);
    +
    +  // Start insertion in LoopBB.
    +  Builder.SetInsertPoint(LoopBB);
    +  
    +  // Start the PHI node with an entry for Start.
    +  PHINode *Variable = Builder.CreatePHI(Type::getDoubleTy(getGlobalContext()), VarName.c_str());
    +  Variable->addIncoming(StartVal, PreheaderBB);
    +  
    +  // Within the loop, the variable is defined equal to the PHI node.  If it
    +  // shadows an existing variable, we have to restore it, so save it now.
    +  Value *OldVal = NamedValues[VarName];
    +  NamedValues[VarName] = Variable;
    +  
    +  // Emit the body of the loop.  This, like any other expr, can change the
    +  // current BB.  Note that we ignore the value computed by the body, but don't
    +  // allow an error.
    +  if (Body->Codegen() == 0)
    +    return 0;
    +  
    +  // Emit the step value.
    +  Value *StepVal;
    +  if (Step) {
    +    StepVal = Step->Codegen();
    +    if (StepVal == 0) return 0;
    +  } else {
    +    // If not specified, use 1.0.
    +    StepVal = ConstantFP::get(getGlobalContext(), APFloat(1.0));
    +  }
    +  
    +  Value *NextVar = Builder.CreateAdd(Variable, StepVal, "nextvar");
    +
    +  // Compute the end condition.
    +  Value *EndCond = End->Codegen();
    +  if (EndCond == 0) return EndCond;
    +  
    +  // Convert condition to a bool by comparing equal to 0.0.
    +  EndCond = Builder.CreateFCmpONE(EndCond, 
    +                              ConstantFP::get(getGlobalContext(), APFloat(0.0)),
    +                                  "loopcond");
    +  
    +  // Create the "after loop" block and insert it.
    +  BasicBlock *LoopEndBB = Builder.GetInsertBlock();
    +  BasicBlock *AfterBB = BasicBlock::Create(getGlobalContext(), "afterloop", TheFunction);
    +  
    +  // Insert the conditional branch into the end of LoopEndBB.
    +  Builder.CreateCondBr(EndCond, LoopBB, AfterBB);
    +  
    +  // Any new code will be inserted in AfterBB.
    +  Builder.SetInsertPoint(AfterBB);
    +  
    +  // Add a new entry to the PHI node for the backedge.
    +  Variable->addIncoming(NextVar, LoopEndBB);
    +  
    +  // Restore the unshadowed variable.
    +  if (OldVal)
    +    NamedValues[VarName] = OldVal;
    +  else
    +    NamedValues.erase(VarName);
    +
    +  
    +  // for expr always returns 0.0.
    +  return Constant::getNullValue(Type::getDoubleTy(getGlobalContext()));
    +}
    +
    +Function *PrototypeAST::Codegen() {
    +  // Make the function type:  double(double,double) etc.
    +  std::vector<const Type*> Doubles(Args.size(),
    +                                   Type::getDoubleTy(getGlobalContext()));
    +  FunctionType *FT = FunctionType::get(Type::getDoubleTy(getGlobalContext()),
    +                                       Doubles, false);
    +  
    +  Function *F = Function::Create(FT, Function::ExternalLinkage, Name, TheModule);
    +  
    +  // If F conflicted, there was already something named 'Name'.  If it has a
    +  // body, don't allow redefinition or reextern.
    +  if (F->getName() != Name) {
    +    // Delete the one we just made and get the existing one.
    +    F->eraseFromParent();
    +    F = TheModule->getFunction(Name);
    +    
    +    // If F already has a body, reject this.
    +    if (!F->empty()) {
    +      ErrorF("redefinition of function");
    +      return 0;
    +    }
    +    
    +    // If F took a different number of args, reject.
    +    if (F->arg_size() != Args.size()) {
    +      ErrorF("redefinition of function with different # args");
    +      return 0;
    +    }
    +  }
    +  
    +  // Set names for all arguments.
    +  unsigned Idx = 0;
    +  for (Function::arg_iterator AI = F->arg_begin(); Idx != Args.size();
    +       ++AI, ++Idx) {
    +    AI->setName(Args[Idx]);
    +    
    +    // Add arguments to variable symbol table.
    +    NamedValues[Args[Idx]] = AI;
    +  }
    +  
    +  return F;
    +}
    +
    +Function *FunctionAST::Codegen() {
    +  NamedValues.clear();
    +  
    +  Function *TheFunction = Proto->Codegen();
    +  if (TheFunction == 0)
    +    return 0;
    +  
    +  // Create a new basic block to start insertion into.
    +  BasicBlock *BB = BasicBlock::Create(getGlobalContext(), "entry", TheFunction);
    +  Builder.SetInsertPoint(BB);
    +  
    +  if (Value *RetVal = Body->Codegen()) {
    +    // Finish off the function.
    +    Builder.CreateRet(RetVal);
    +
    +    // Validate the generated code, checking for consistency.
    +    verifyFunction(*TheFunction);
    +
    +    // Optimize the function.
    +    TheFPM->run(*TheFunction);
    +    
    +    return TheFunction;
    +  }
    +  
    +  // Error reading body, remove function.
    +  TheFunction->eraseFromParent();
    +  return 0;
    +}
    +
    +//===----------------------------------------------------------------------===//
    +// Top-Level parsing and JIT Driver
    +//===----------------------------------------------------------------------===//
    +
    +static ExecutionEngine *TheExecutionEngine;
    +
    +static void HandleDefinition() {
    +  if (FunctionAST *F = ParseDefinition()) {
    +    if (Function *LF = F->Codegen()) {
    +      fprintf(stderr, "Read function definition:");
    +      LF->dump();
    +    }
    +  } else {
    +    // Skip token for error recovery.
    +    getNextToken();
    +  }
    +}
    +
    +static void HandleExtern() {
    +  if (PrototypeAST *P = ParseExtern()) {
    +    if (Function *F = P->Codegen()) {
    +      fprintf(stderr, "Read extern: ");
    +      F->dump();
    +    }
    +  } else {
    +    // Skip token for error recovery.
    +    getNextToken();
    +  }
    +}
    +
    +static void HandleTopLevelExpression() {
    +  // Evaluate a top-level expression into an anonymous function.
    +  if (FunctionAST *F = ParseTopLevelExpr()) {
    +    if (Function *LF = F->Codegen()) {
    +      // JIT the function, returning a function pointer.
    +      void *FPtr = TheExecutionEngine->getPointerToFunction(LF);
    +      
    +      // Cast it to the right type (takes no arguments, returns a double) so we
    +      // can call it as a native function.
    +      double (*FP)() = (double (*)())(intptr_t)FPtr;
    +      fprintf(stderr, "Evaluated to %f\n", FP());
    +    }
    +  } else {
    +    // Skip token for error recovery.
    +    getNextToken();
    +  }
    +}
    +
    +/// top ::= definition | external | expression | ';'
    +static void MainLoop() {
    +  while (1) {
    +    fprintf(stderr, "ready> ");
    +    switch (CurTok) {
    +    case tok_eof:    return;
    +    case ';':        getNextToken(); break;  // ignore top-level semicolons.
    +    case tok_def:    HandleDefinition(); break;
    +    case tok_extern: HandleExtern(); break;
    +    default:         HandleTopLevelExpression(); break;
    +    }
    +  }
    +}
    +
    +//===----------------------------------------------------------------------===//
    +// "Library" functions that can be "extern'd" from user code.
    +//===----------------------------------------------------------------------===//
    +
    +/// putchard - putchar that takes a double and returns 0.
    +extern "C" 
    +double putchard(double X) {
    +  putchar((char)X);
    +  return 0;
    +}
    +
    +//===----------------------------------------------------------------------===//
    +// Main driver code.
    +//===----------------------------------------------------------------------===//
    +
    +int main() {
    +  InitializeNativeTarget();
    +  LLVMContext &Context = getGlobalContext();
    +
    +  // Install standard binary operators.
    +  // 1 is lowest precedence.
    +  BinopPrecedence['<'] = 10;
    +  BinopPrecedence['+'] = 20;
    +  BinopPrecedence['-'] = 20;
    +  BinopPrecedence['*'] = 40;  // highest.
    +
    +  // Prime the first token.
    +  fprintf(stderr, "ready> ");
    +  getNextToken();
    +
    +  // Make the module, which holds all the code.
    +  TheModule = new Module("my cool jit", Context);
    +
    +  ExistingModuleProvider *OurModuleProvider =
    +      new ExistingModuleProvider(TheModule);
    +
    +  // Create the JIT.  This takes ownership of the module and module provider.
    +  TheExecutionEngine = EngineBuilder(OurModuleProvider).create();
    +
    +  FunctionPassManager OurFPM(OurModuleProvider);
    +
    +  // Set up the optimizer pipeline.  Start with registering info about how the
    +  // target lays out data structures.
    +  OurFPM.add(new TargetData(*TheExecutionEngine->getTargetData()));
    +  // Do simple "peephole" optimizations and bit-twiddling optzns.
    +  OurFPM.add(createInstructionCombiningPass());
    +  // Reassociate expressions.
    +  OurFPM.add(createReassociatePass());
    +  // Eliminate Common SubExpressions.
    +  OurFPM.add(createGVNPass());
    +  // Simplify the control flow graph (deleting unreachable blocks, etc).
    +  OurFPM.add(createCFGSimplificationPass());
    +
    +  OurFPM.doInitialization();
    +
    +  // Set the global so the code gen can use this.
    +  TheFPM = &OurFPM;
    +
    +  // Run the main "interpreter loop" now.
    +  MainLoop();
    +
    +  TheFPM = 0;
    +
    +  // Print out all of the generated code.
    +  TheModule->dump();
    +
    +  return 0;
    +}
    +
    +
    + +Next: Extending the language: user-defined operators +
    + + +
    +
    + Valid CSS! + Valid HTML 4.01! + + Chris Lattner
    + The LLVM Compiler Infrastructure
    + Last modified: $Date: 2007-10-17 11:05:13 -0700 (Wed, 17 Oct 2007) $ +
    + + diff --git a/libclamav/c++/llvm/docs/tutorial/LangImpl6.html b/libclamav/c++/llvm/docs/tutorial/LangImpl6.html new file mode 100644 index 000000000..f113e9665 --- /dev/null +++ b/libclamav/c++/llvm/docs/tutorial/LangImpl6.html @@ -0,0 +1,1814 @@ + + + + + Kaleidoscope: Extending the Language: User-defined Operators + + + + + + + +
    Kaleidoscope: Extending the Language: User-defined Operators
    + + + +
    +

    Written by Chris Lattner

    +
    + + + + + +
    + +

    Welcome to Chapter 6 of the "Implementing a language +with LLVM" tutorial. At this point in our tutorial, we now have a fully +functional language that is fairly minimal, but also useful. There +is still one big problem with it, however. Our language doesn't have many +useful operators (like division, logical negation, or even any comparisons +besides less-than).

    + +

    This chapter of the tutorial takes a wild digression into adding user-defined +operators to the simple and beautiful Kaleidoscope language. This digression now gives +us a simple and ugly language in some ways, but also a powerful one at the same time. +One of the great things about creating your own language is that you get to +decide what is good or bad. In this tutorial we'll assume that it is okay to +use this as a way to show some interesting parsing techniques.

    + +

    At the end of this tutorial, we'll run through an example Kaleidoscope +application that renders the Mandelbrot set. This gives +an example of what you can build with Kaleidoscope and its feature set.

    + +
    + + + + + +
    + +

    +The "operator overloading" that we will add to Kaleidoscope is more general than +languages like C++. In C++, you are only allowed to redefine existing +operators: you can't programatically change the grammar, introduce new +operators, change precedence levels, etc. In this chapter, we will add this +capability to Kaleidoscope, which will let the user round out the set of +operators that are supported.

    + +

    The point of going into user-defined operators in a tutorial like this is to +show the power and flexibility of using a hand-written parser. Thus far, the parser +we have been implementing uses recursive descent for most parts of the grammar and +operator precedence parsing for the expressions. See Chapter 2 for details. Without using operator +precedence parsing, it would be very difficult to allow the programmer to +introduce new operators into the grammar: the grammar is dynamically extensible +as the JIT runs.

    + +

    The two specific features we'll add are programmable unary operators (right +now, Kaleidoscope has no unary operators at all) as well as binary operators. +An example of this is:

    + +
    +
    +# Logical unary not.
    +def unary!(v)
    +  if v then
    +    0
    +  else
    +    1;
    +
    +# Define > with the same precedence as <.
    +def binary> 10 (LHS RHS)
    +  RHS < LHS;
    +
    +# Binary "logical or", (note that it does not "short circuit")
    +def binary| 5 (LHS RHS)
    +  if LHS then
    +    1
    +  else if RHS then
    +    1
    +  else
    +    0;
    +
    +# Define = with slightly lower precedence than relationals.
    +def binary= 9 (LHS RHS)
    +  !(LHS < RHS | LHS > RHS);
    +
    +
    + +

    Many languages aspire to being able to implement their standard runtime +library in the language itself. In Kaleidoscope, we can implement significant +parts of the language in the library!

    + +

    We will break down implementation of these features into two parts: +implementing support for user-defined binary operators and adding unary +operators.

    + +
    + + + + + +
    + +

    Adding support for user-defined binary operators is pretty simple with our +current framework. We'll first add support for the unary/binary keywords:

    + +
    +
    +enum Token {
    +  ...
    +  // operators
    +  tok_binary = -11, tok_unary = -12
    +};
    +...
    +static int gettok() {
    +...
    +    if (IdentifierStr == "for") return tok_for;
    +    if (IdentifierStr == "in") return tok_in;
    +    if (IdentifierStr == "binary") return tok_binary;
    +    if (IdentifierStr == "unary") return tok_unary;
    +    return tok_identifier;
    +
    +
    + +

    This just adds lexer support for the unary and binary keywords, like we +did in previous chapters. One nice thing +about our current AST, is that we represent binary operators with full generalisation +by using their ASCII code as the opcode. For our extended operators, we'll use this +same representation, so we don't need any new AST or parser support.

    + +

    On the other hand, we have to be able to represent the definitions of these +new operators, in the "def binary| 5" part of the function definition. In our +grammar so far, the "name" for the function definition is parsed as the +"prototype" production and into the PrototypeAST AST node. To +represent our new user-defined operators as prototypes, we have to extend +the PrototypeAST AST node like this:

    + +
    +
    +/// PrototypeAST - This class represents the "prototype" for a function,
    +/// which captures its argument names as well as if it is an operator.
    +class PrototypeAST {
    +  std::string Name;
    +  std::vector<std::string> Args;
    +  bool isOperator;
    +  unsigned Precedence;  // Precedence if a binary op.
    +public:
    +  PrototypeAST(const std::string &name, const std::vector<std::string> &args,
    +               bool isoperator = false, unsigned prec = 0)
    +  : Name(name), Args(args), isOperator(isoperator), Precedence(prec) {}
    +  
    +  bool isUnaryOp() const { return isOperator && Args.size() == 1; }
    +  bool isBinaryOp() const { return isOperator && Args.size() == 2; }
    +  
    +  char getOperatorName() const {
    +    assert(isUnaryOp() || isBinaryOp());
    +    return Name[Name.size()-1];
    +  }
    +  
    +  unsigned getBinaryPrecedence() const { return Precedence; }
    +  
    +  Function *Codegen();
    +};
    +
    +
    + +

    Basically, in addition to knowing a name for the prototype, we now keep track +of whether it was an operator, and if it was, what precedence level the operator +is at. The precedence is only used for binary operators (as you'll see below, +it just doesn't apply for unary operators). Now that we have a way to represent +the prototype for a user-defined operator, we need to parse it:

    + +
    +
    +/// prototype
    +///   ::= id '(' id* ')'
    +///   ::= binary LETTER number? (id, id)
    +static PrototypeAST *ParsePrototype() {
    +  std::string FnName;
    +  
    +  unsigned Kind = 0;  // 0 = identifier, 1 = unary, 2 = binary.
    +  unsigned BinaryPrecedence = 30;
    +  
    +  switch (CurTok) {
    +  default:
    +    return ErrorP("Expected function name in prototype");
    +  case tok_identifier:
    +    FnName = IdentifierStr;
    +    Kind = 0;
    +    getNextToken();
    +    break;
    +  case tok_binary:
    +    getNextToken();
    +    if (!isascii(CurTok))
    +      return ErrorP("Expected binary operator");
    +    FnName = "binary";
    +    FnName += (char)CurTok;
    +    Kind = 2;
    +    getNextToken();
    +    
    +    // Read the precedence if present.
    +    if (CurTok == tok_number) {
    +      if (NumVal < 1 || NumVal > 100)
    +        return ErrorP("Invalid precedecnce: must be 1..100");
    +      BinaryPrecedence = (unsigned)NumVal;
    +      getNextToken();
    +    }
    +    break;
    +  }
    +  
    +  if (CurTok != '(')
    +    return ErrorP("Expected '(' in prototype");
    +  
    +  std::vector<std::string> ArgNames;
    +  while (getNextToken() == tok_identifier)
    +    ArgNames.push_back(IdentifierStr);
    +  if (CurTok != ')')
    +    return ErrorP("Expected ')' in prototype");
    +  
    +  // success.
    +  getNextToken();  // eat ')'.
    +  
    +  // Verify right number of names for operator.
    +  if (Kind && ArgNames.size() != Kind)
    +    return ErrorP("Invalid number of operands for operator");
    +  
    +  return new PrototypeAST(FnName, ArgNames, Kind != 0, BinaryPrecedence);
    +}
    +
    +
    + +

    This is all fairly straightforward parsing code, and we have already seen +a lot of similar code in the past. One interesting part about the code above is +the couple lines that set up FnName for binary operators. This builds names +like "binary@" for a newly defined "@" operator. This then takes advantage of the +fact that symbol names in the LLVM symbol table are allowed to have any character in +them, including embedded nul characters.

    + +

    The next interesting thing to add, is codegen support for these binary operators. +Given our current structure, this is a simple addition of a default case for our +existing binary operator node:

    + +
    +
    +Value *BinaryExprAST::Codegen() {
    +  Value *L = LHS->Codegen();
    +  Value *R = RHS->Codegen();
    +  if (L == 0 || R == 0) return 0;
    +  
    +  switch (Op) {
    +  case '+': return Builder.CreateAdd(L, R, "addtmp");
    +  case '-': return Builder.CreateSub(L, R, "subtmp");
    +  case '*': return Builder.CreateMul(L, R, "multmp");
    +  case '<':
    +    L = Builder.CreateFCmpULT(L, R, "cmptmp");
    +    // Convert bool 0/1 to double 0.0 or 1.0
    +    return Builder.CreateUIToFP(L, Type::getDoubleTy(getGlobalContext()),
    +                                "booltmp");
    +  default: break;
    +  }
    +  
    +  // If it wasn't a builtin binary operator, it must be a user defined one. Emit
    +  // a call to it.
    +  Function *F = TheModule->getFunction(std::string("binary")+Op);
    +  assert(F && "binary operator not found!");
    +  
    +  Value *Ops[] = { L, R };
    +  return Builder.CreateCall(F, Ops, Ops+2, "binop");
    +}
    +
    +
    +
    + +

    As you can see above, the new code is actually really simple. It just does +a lookup for the appropriate operator in the symbol table and generates a +function call to it. Since user-defined operators are just built as normal +functions (because the "prototype" boils down to a function with the right +name) everything falls into place.

    + +

    The final piece of code we are missing, is a bit of top-level magic:

    + +
    +
    +Function *FunctionAST::Codegen() {
    +  NamedValues.clear();
    +  
    +  Function *TheFunction = Proto->Codegen();
    +  if (TheFunction == 0)
    +    return 0;
    +  
    +  // If this is an operator, install it.
    +  if (Proto->isBinaryOp())
    +    BinopPrecedence[Proto->getOperatorName()] = Proto->getBinaryPrecedence();
    +  
    +  // Create a new basic block to start insertion into.
    +  BasicBlock *BB = BasicBlock::Create(getGlobalContext(), "entry", TheFunction);
    +  Builder.SetInsertPoint(BB);
    +  
    +  if (Value *RetVal = Body->Codegen()) {
    +    ...
    +
    +
    + +

    Basically, before codegening a function, if it is a user-defined operator, we +register it in the precedence table. This allows the binary operator parsing +logic we already have in place to handle it. Since we are working on a fully-general operator precedence parser, this is all we need to do to "extend the grammar".

    + +

    Now we have useful user-defined binary operators. This builds a lot +on the previous framework we built for other operators. Adding unary operators +is a bit more challenging, because we don't have any framework for it yet - lets +see what it takes.

    + +
    + + + + + +
    + +

    Since we don't currently support unary operators in the Kaleidoscope +language, we'll need to add everything to support them. Above, we added simple +support for the 'unary' keyword to the lexer. In addition to that, we need an +AST node:

    + +
    +
    +/// UnaryExprAST - Expression class for a unary operator.
    +class UnaryExprAST : public ExprAST {
    +  char Opcode;
    +  ExprAST *Operand;
    +public:
    +  UnaryExprAST(char opcode, ExprAST *operand) 
    +    : Opcode(opcode), Operand(operand) {}
    +  virtual Value *Codegen();
    +};
    +
    +
    + +

    This AST node is very simple and obvious by now. It directly mirrors the +binary operator AST node, except that it only has one child. With this, we +need to add the parsing logic. Parsing a unary operator is pretty simple: we'll +add a new function to do it:

    + +
    +
    +/// unary
    +///   ::= primary
    +///   ::= '!' unary
    +static ExprAST *ParseUnary() {
    +  // If the current token is not an operator, it must be a primary expr.
    +  if (!isascii(CurTok) || CurTok == '(' || CurTok == ',')
    +    return ParsePrimary();
    +  
    +  // If this is a unary operator, read it.
    +  int Opc = CurTok;
    +  getNextToken();
    +  if (ExprAST *Operand = ParseUnary())
    +    return new UnaryExprAST(Opc, Operand);
    +  return 0;
    +}
    +
    +
    + +

    The grammar we add is pretty straightforward here. If we see a unary +operator when parsing a primary operator, we eat the operator as a prefix and +parse the remaining piece as another unary operator. This allows us to handle +multiple unary operators (e.g. "!!x"). Note that unary operators can't have +ambiguous parses like binary operators can, so there is no need for precedence +information.

    + +

    The problem with this function, is that we need to call ParseUnary from somewhere. +To do this, we change previous callers of ParsePrimary to call ParseUnary +instead:

    + +
    +
    +/// binoprhs
    +///   ::= ('+' unary)*
    +static ExprAST *ParseBinOpRHS(int ExprPrec, ExprAST *LHS) {
    +  ...
    +    // Parse the unary expression after the binary operator.
    +    ExprAST *RHS = ParseUnary();
    +    if (!RHS) return 0;
    +  ...
    +}
    +/// expression
    +///   ::= unary binoprhs
    +///
    +static ExprAST *ParseExpression() {
    +  ExprAST *LHS = ParseUnary();
    +  if (!LHS) return 0;
    +  
    +  return ParseBinOpRHS(0, LHS);
    +}
    +
    +
    + +

    With these two simple changes, we are now able to parse unary operators and build the +AST for them. Next up, we need to add parser support for prototypes, to parse +the unary operator prototype. We extend the binary operator code above +with:

    + +
    +
    +/// prototype
    +///   ::= id '(' id* ')'
    +///   ::= binary LETTER number? (id, id)
    +///   ::= unary LETTER (id)
    +static PrototypeAST *ParsePrototype() {
    +  std::string FnName;
    +  
    +  unsigned Kind = 0;  // 0 = identifier, 1 = unary, 2 = binary.
    +  unsigned BinaryPrecedence = 30;
    +  
    +  switch (CurTok) {
    +  default:
    +    return ErrorP("Expected function name in prototype");
    +  case tok_identifier:
    +    FnName = IdentifierStr;
    +    Kind = 0;
    +    getNextToken();
    +    break;
    +  case tok_unary:
    +    getNextToken();
    +    if (!isascii(CurTok))
    +      return ErrorP("Expected unary operator");
    +    FnName = "unary";
    +    FnName += (char)CurTok;
    +    Kind = 1;
    +    getNextToken();
    +    break;
    +  case tok_binary:
    +    ...
    +
    +
    + +

    As with binary operators, we name unary operators with a name that includes +the operator character. This assists us at code generation time. Speaking of, +the final piece we need to add is codegen support for unary operators. It looks +like this:

    + +
    +
    +Value *UnaryExprAST::Codegen() {
    +  Value *OperandV = Operand->Codegen();
    +  if (OperandV == 0) return 0;
    +  
    +  Function *F = TheModule->getFunction(std::string("unary")+Opcode);
    +  if (F == 0)
    +    return ErrorV("Unknown unary operator");
    +  
    +  return Builder.CreateCall(F, OperandV, "unop");
    +}
    +
    +
    + +

    This code is similar to, but simpler than, the code for binary operators. It +is simpler primarily because it doesn't need to handle any predefined operators. +

    + +
    + + + + + +
    + +

    It is somewhat hard to believe, but with a few simple extensions we've +covered in the last chapters, we have grown a real-ish language. With this, we +can do a lot of interesting things, including I/O, math, and a bunch of other +things. For example, we can now add a nice sequencing operator (printd is +defined to print out the specified value and a newline):

    + +
    +
    +ready> extern printd(x);
    +Read extern: declare double @printd(double)
    +ready> def binary : 1 (x y) 0;  # Low-precedence operator that ignores operands.
    +..
    +ready> printd(123) : printd(456) : printd(789);
    +123.000000
    +456.000000
    +789.000000
    +Evaluated to 0.000000
    +
    +
    + +

    We can also define a bunch of other "primitive" operations, such as:

    + +
    +
    +# Logical unary not.
    +def unary!(v)
    +  if v then
    +    0
    +  else
    +    1;
    +    
    +# Unary negate.
    +def unary-(v)
    +  0-v;
    +
    +# Define > with the same precedence as >.
    +def binary> 10 (LHS RHS)
    +  RHS < LHS;
    +
    +# Binary logical or, which does not short circuit. 
    +def binary| 5 (LHS RHS)
    +  if LHS then
    +    1
    +  else if RHS then
    +    1
    +  else
    +    0;
    +
    +# Binary logical and, which does not short circuit. 
    +def binary& 6 (LHS RHS)
    +  if !LHS then
    +    0
    +  else
    +    !!RHS;
    +
    +# Define = with slightly lower precedence than relationals.
    +def binary = 9 (LHS RHS)
    +  !(LHS < RHS | LHS > RHS);
    +
    +
    +
    + + +

    Given the previous if/then/else support, we can also define interesting +functions for I/O. For example, the following prints out a character whose +"density" reflects the value passed in: the lower the value, the denser the +character:

    + +
    +
    +ready>
    +
    +extern putchard(char)
    +def printdensity(d)
    +  if d > 8 then
    +    putchard(32)  # ' '
    +  else if d > 4 then
    +    putchard(46)  # '.'
    +  else if d > 2 then
    +    putchard(43)  # '+'
    +  else
    +    putchard(42); # '*'
    +...
    +ready> printdensity(1): printdensity(2): printdensity(3) : 
    +          printdensity(4): printdensity(5): printdensity(9): putchard(10);
    +*++.. 
    +Evaluated to 0.000000
    +
    +
    + +

    Based on these simple primitive operations, we can start to define more +interesting things. For example, here's a little function that solves for the +number of iterations it takes a function in the complex plane to +converge:

    + +
    +
    +# determine whether the specific location diverges.
    +# Solve for z = z^2 + c in the complex plane.
    +def mandleconverger(real imag iters creal cimag)
    +  if iters > 255 | (real*real + imag*imag > 4) then
    +    iters
    +  else
    +    mandleconverger(real*real - imag*imag + creal,
    +                    2*real*imag + cimag,
    +                    iters+1, creal, cimag);
    +
    +# return the number of iterations required for the iteration to escape
    +def mandleconverge(real imag)
    +  mandleconverger(real, imag, 0, real, imag);
    +
    +
    + +

    This "z = z2 + c" function is a beautiful little creature that is the basis +for computation of the Mandelbrot Set. Our +mandelconverge function returns the number of iterations that it takes +for a complex orbit to escape, saturating to 255. This is not a very useful +function by itself, but if you plot its value over a two-dimensional plane, +you can see the Mandelbrot set. Given that we are limited to using putchard +here, our amazing graphical output is limited, but we can whip together +something using the density plotter above:

    + +
    +
    +# compute and plot the mandlebrot set with the specified 2 dimensional range
    +# info.
    +def mandelhelp(xmin xmax xstep   ymin ymax ystep)
    +  for y = ymin, y < ymax, ystep in (
    +    (for x = xmin, x < xmax, xstep in
    +       printdensity(mandleconverge(x,y)))
    +    : putchard(10)
    +  )
    + 
    +# mandel - This is a convenient helper function for ploting the mandelbrot set
    +# from the specified position with the specified Magnification.
    +def mandel(realstart imagstart realmag imagmag) 
    +  mandelhelp(realstart, realstart+realmag*78, realmag,
    +             imagstart, imagstart+imagmag*40, imagmag);
    +
    +
    + +

    Given this, we can try plotting out the mandlebrot set! Lets try it out:

    + +
    +
    +ready> mandel(-2.3, -1.3, 0.05, 0.07);
    +*******************************+++++++++++*************************************
    +*************************+++++++++++++++++++++++*******************************
    +**********************+++++++++++++++++++++++++++++****************************
    +*******************+++++++++++++++++++++.. ...++++++++*************************
    +*****************++++++++++++++++++++++.... ...+++++++++***********************
    +***************+++++++++++++++++++++++.....   ...+++++++++*********************
    +**************+++++++++++++++++++++++....     ....+++++++++********************
    +*************++++++++++++++++++++++......      .....++++++++*******************
    +************+++++++++++++++++++++.......       .......+++++++******************
    +***********+++++++++++++++++++....                ... .+++++++*****************
    +**********+++++++++++++++++.......                     .+++++++****************
    +*********++++++++++++++...........                    ...+++++++***************
    +********++++++++++++............                      ...++++++++**************
    +********++++++++++... ..........                        .++++++++**************
    +*******+++++++++.....                                   .+++++++++*************
    +*******++++++++......                                  ..+++++++++*************
    +*******++++++.......                                   ..+++++++++*************
    +*******+++++......                                     ..+++++++++*************
    +*******.... ....                                      ...+++++++++*************
    +*******.... .                                         ...+++++++++*************
    +*******+++++......                                    ...+++++++++*************
    +*******++++++.......                                   ..+++++++++*************
    +*******++++++++......                                   .+++++++++*************
    +*******+++++++++.....                                  ..+++++++++*************
    +********++++++++++... ..........                        .++++++++**************
    +********++++++++++++............                      ...++++++++**************
    +*********++++++++++++++..........                     ...+++++++***************
    +**********++++++++++++++++........                     .+++++++****************
    +**********++++++++++++++++++++....                ... ..+++++++****************
    +***********++++++++++++++++++++++.......       .......++++++++*****************
    +************+++++++++++++++++++++++......      ......++++++++******************
    +**************+++++++++++++++++++++++....      ....++++++++********************
    +***************+++++++++++++++++++++++.....   ...+++++++++*********************
    +*****************++++++++++++++++++++++....  ...++++++++***********************
    +*******************+++++++++++++++++++++......++++++++*************************
    +*********************++++++++++++++++++++++.++++++++***************************
    +*************************+++++++++++++++++++++++*******************************
    +******************************+++++++++++++************************************
    +*******************************************************************************
    +*******************************************************************************
    +*******************************************************************************
    +Evaluated to 0.000000
    +ready> mandel(-2, -1, 0.02, 0.04);
    +**************************+++++++++++++++++++++++++++++++++++++++++++++++++++++
    +***********************++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    +*********************+++++++++++++++++++++++++++++++++++++++++++++++++++++++++.
    +*******************+++++++++++++++++++++++++++++++++++++++++++++++++++++++++...
    +*****************+++++++++++++++++++++++++++++++++++++++++++++++++++++++++.....
    +***************++++++++++++++++++++++++++++++++++++++++++++++++++++++++........
    +**************++++++++++++++++++++++++++++++++++++++++++++++++++++++...........
    +************+++++++++++++++++++++++++++++++++++++++++++++++++++++..............
    +***********++++++++++++++++++++++++++++++++++++++++++++++++++........        . 
    +**********++++++++++++++++++++++++++++++++++++++++++++++.............          
    +********+++++++++++++++++++++++++++++++++++++++++++..................          
    +*******+++++++++++++++++++++++++++++++++++++++.......................          
    +******+++++++++++++++++++++++++++++++++++...........................           
    +*****++++++++++++++++++++++++++++++++............................              
    +*****++++++++++++++++++++++++++++...............................               
    +****++++++++++++++++++++++++++......   .........................               
    +***++++++++++++++++++++++++.........     ......    ...........                 
    +***++++++++++++++++++++++............                                          
    +**+++++++++++++++++++++..............                                          
    +**+++++++++++++++++++................                                          
    +*++++++++++++++++++.................                                           
    +*++++++++++++++++............ ...                                              
    +*++++++++++++++..............                                                  
    +*+++....++++................                                                   
    +*..........  ...........                                                       
    +*                                                                              
    +*..........  ...........                                                       
    +*+++....++++................                                                   
    +*++++++++++++++..............                                                  
    +*++++++++++++++++............ ...                                              
    +*++++++++++++++++++.................                                           
    +**+++++++++++++++++++................                                          
    +**+++++++++++++++++++++..............                                          
    +***++++++++++++++++++++++............                                          
    +***++++++++++++++++++++++++.........     ......    ...........                 
    +****++++++++++++++++++++++++++......   .........................               
    +*****++++++++++++++++++++++++++++...............................               
    +*****++++++++++++++++++++++++++++++++............................              
    +******+++++++++++++++++++++++++++++++++++...........................           
    +*******+++++++++++++++++++++++++++++++++++++++.......................          
    +********+++++++++++++++++++++++++++++++++++++++++++..................          
    +Evaluated to 0.000000
    +ready> mandel(-0.9, -1.4, 0.02, 0.03);
    +*******************************************************************************
    +*******************************************************************************
    +*******************************************************************************
    +**********+++++++++++++++++++++************************************************
    +*+++++++++++++++++++++++++++++++++++++++***************************************
    ++++++++++++++++++++++++++++++++++++++++++++++**********************************
    +++++++++++++++++++++++++++++++++++++++++++++++++++*****************************
    +++++++++++++++++++++++++++++++++++++++++++++++++++++++*************************
    ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++**********************
    ++++++++++++++++++++++++++++++++++.........++++++++++++++++++*******************
    ++++++++++++++++++++++++++++++++....   ......+++++++++++++++++++****************
    ++++++++++++++++++++++++++++++.......  ........+++++++++++++++++++**************
    +++++++++++++++++++++++++++++........   ........++++++++++++++++++++************
    ++++++++++++++++++++++++++++.........     ..  ...+++++++++++++++++++++**********
    +++++++++++++++++++++++++++...........        ....++++++++++++++++++++++********
    +++++++++++++++++++++++++.............       .......++++++++++++++++++++++******
    ++++++++++++++++++++++++.............        ........+++++++++++++++++++++++****
    +++++++++++++++++++++++...........           ..........++++++++++++++++++++++***
    +++++++++++++++++++++...........                .........++++++++++++++++++++++*
    +++++++++++++++++++............                  ...........++++++++++++++++++++
    +++++++++++++++++...............                 .............++++++++++++++++++
    +++++++++++++++.................                 ...............++++++++++++++++
    +++++++++++++..................                  .................++++++++++++++
    ++++++++++..................                      .................+++++++++++++
    +++++++........        .                               .........  ..++++++++++++
    +++............                                         ......    ....++++++++++
    +..............                                                    ...++++++++++
    +..............                                                    ....+++++++++
    +..............                                                    .....++++++++
    +.............                                                    ......++++++++
    +...........                                                     .......++++++++
    +.........                                                       ........+++++++
    +.........                                                       ........+++++++
    +.........                                                           ....+++++++
    +........                                                             ...+++++++
    +.......                                                              ...+++++++
    +                                                                    ....+++++++
    +                                                                   .....+++++++
    +                                                                    ....+++++++
    +                                                                    ....+++++++
    +                                                                    ....+++++++
    +Evaluated to 0.000000
    +ready> ^D
    +
    +
    + +

    At this point, you may be starting to realize that Kaleidoscope is a real +and powerful language. It may not be self-similar :), but it can be used to +plot things that are!

    + +

    With this, we conclude the "adding user-defined operators" chapter of the +tutorial. We have successfully augmented our language, adding the ability to extend the +language in the library, and we have shown how this can be used to build a simple but +interesting end-user application in Kaleidoscope. At this point, Kaleidoscope +can build a variety of applications that are functional and can call functions +with side-effects, but it can't actually define and mutate a variable itself. +

    + +

    Strikingly, variable mutation is an important feature of some +languages, and it is not at all obvious how to add +support for mutable variables without having to add an "SSA construction" +phase to your front-end. In the next chapter, we will describe how you can +add variable mutation without building SSA in your front-end.

    + +
    + + + + + +
    + +

    +Here is the complete code listing for our running example, enhanced with the +if/then/else and for expressions.. To build this example, use: +

    + +
    +
    +   # Compile
    +   g++ -g toy.cpp `llvm-config --cppflags --ldflags --libs core jit native` -O3 -o toy
    +   # Run
    +   ./toy
    +
    +
    + +

    Here is the code:

    + +
    +
    +#include "llvm/DerivedTypes.h"
    +#include "llvm/ExecutionEngine/ExecutionEngine.h"
    +#include "llvm/ExecutionEngine/Interpreter.h"
    +#include "llvm/ExecutionEngine/JIT.h"
    +#include "llvm/LLVMContext.h"
    +#include "llvm/Module.h"
    +#include "llvm/ModuleProvider.h"
    +#include "llvm/PassManager.h"
    +#include "llvm/Analysis/Verifier.h"
    +#include "llvm/Target/TargetData.h"
    +#include "llvm/Target/TargetSelect.h"
    +#include "llvm/Transforms/Scalar.h"
    +#include "llvm/Support/IRBuilder.h"
    +#include <cstdio>
    +#include <string>
    +#include <map>
    +#include <vector>
    +using namespace llvm;
    +
    +//===----------------------------------------------------------------------===//
    +// Lexer
    +//===----------------------------------------------------------------------===//
    +
    +// The lexer returns tokens [0-255] if it is an unknown character, otherwise one
    +// of these for known things.
    +enum Token {
    +  tok_eof = -1,
    +
    +  // commands
    +  tok_def = -2, tok_extern = -3,
    +
    +  // primary
    +  tok_identifier = -4, tok_number = -5,
    +  
    +  // control
    +  tok_if = -6, tok_then = -7, tok_else = -8,
    +  tok_for = -9, tok_in = -10,
    +  
    +  // operators
    +  tok_binary = -11, tok_unary = -12
    +};
    +
    +static std::string IdentifierStr;  // Filled in if tok_identifier
    +static double NumVal;              // Filled in if tok_number
    +
    +/// gettok - Return the next token from standard input.
    +static int gettok() {
    +  static int LastChar = ' ';
    +
    +  // Skip any whitespace.
    +  while (isspace(LastChar))
    +    LastChar = getchar();
    +
    +  if (isalpha(LastChar)) { // identifier: [a-zA-Z][a-zA-Z0-9]*
    +    IdentifierStr = LastChar;
    +    while (isalnum((LastChar = getchar())))
    +      IdentifierStr += LastChar;
    +
    +    if (IdentifierStr == "def") return tok_def;
    +    if (IdentifierStr == "extern") return tok_extern;
    +    if (IdentifierStr == "if") return tok_if;
    +    if (IdentifierStr == "then") return tok_then;
    +    if (IdentifierStr == "else") return tok_else;
    +    if (IdentifierStr == "for") return tok_for;
    +    if (IdentifierStr == "in") return tok_in;
    +    if (IdentifierStr == "binary") return tok_binary;
    +    if (IdentifierStr == "unary") return tok_unary;
    +    return tok_identifier;
    +  }
    +
    +  if (isdigit(LastChar) || LastChar == '.') {   // Number: [0-9.]+
    +    std::string NumStr;
    +    do {
    +      NumStr += LastChar;
    +      LastChar = getchar();
    +    } while (isdigit(LastChar) || LastChar == '.');
    +
    +    NumVal = strtod(NumStr.c_str(), 0);
    +    return tok_number;
    +  }
    +
    +  if (LastChar == '#') {
    +    // Comment until end of line.
    +    do LastChar = getchar();
    +    while (LastChar != EOF && LastChar != '\n' && LastChar != '\r');
    +    
    +    if (LastChar != EOF)
    +      return gettok();
    +  }
    +  
    +  // Check for end of file.  Don't eat the EOF.
    +  if (LastChar == EOF)
    +    return tok_eof;
    +
    +  // Otherwise, just return the character as its ascii value.
    +  int ThisChar = LastChar;
    +  LastChar = getchar();
    +  return ThisChar;
    +}
    +
    +//===----------------------------------------------------------------------===//
    +// Abstract Syntax Tree (aka Parse Tree)
    +//===----------------------------------------------------------------------===//
    +
    +/// ExprAST - Base class for all expression nodes.
    +class ExprAST {
    +public:
    +  virtual ~ExprAST() {}
    +  virtual Value *Codegen() = 0;
    +};
    +
    +/// NumberExprAST - Expression class for numeric literals like "1.0".
    +class NumberExprAST : public ExprAST {
    +  double Val;
    +public:
    +  NumberExprAST(double val) : Val(val) {}
    +  virtual Value *Codegen();
    +};
    +
    +/// VariableExprAST - Expression class for referencing a variable, like "a".
    +class VariableExprAST : public ExprAST {
    +  std::string Name;
    +public:
    +  VariableExprAST(const std::string &name) : Name(name) {}
    +  virtual Value *Codegen();
    +};
    +
    +/// UnaryExprAST - Expression class for a unary operator.
    +class UnaryExprAST : public ExprAST {
    +  char Opcode;
    +  ExprAST *Operand;
    +public:
    +  UnaryExprAST(char opcode, ExprAST *operand) 
    +    : Opcode(opcode), Operand(operand) {}
    +  virtual Value *Codegen();
    +};
    +
    +/// BinaryExprAST - Expression class for a binary operator.
    +class BinaryExprAST : public ExprAST {
    +  char Op;
    +  ExprAST *LHS, *RHS;
    +public:
    +  BinaryExprAST(char op, ExprAST *lhs, ExprAST *rhs) 
    +    : Op(op), LHS(lhs), RHS(rhs) {}
    +  virtual Value *Codegen();
    +};
    +
    +/// CallExprAST - Expression class for function calls.
    +class CallExprAST : public ExprAST {
    +  std::string Callee;
    +  std::vector<ExprAST*> Args;
    +public:
    +  CallExprAST(const std::string &callee, std::vector<ExprAST*> &args)
    +    : Callee(callee), Args(args) {}
    +  virtual Value *Codegen();
    +};
    +
    +/// IfExprAST - Expression class for if/then/else.
    +class IfExprAST : public ExprAST {
    +  ExprAST *Cond, *Then, *Else;
    +public:
    +  IfExprAST(ExprAST *cond, ExprAST *then, ExprAST *_else)
    +  : Cond(cond), Then(then), Else(_else) {}
    +  virtual Value *Codegen();
    +};
    +
    +/// ForExprAST - Expression class for for/in.
    +class ForExprAST : public ExprAST {
    +  std::string VarName;
    +  ExprAST *Start, *End, *Step, *Body;
    +public:
    +  ForExprAST(const std::string &varname, ExprAST *start, ExprAST *end,
    +             ExprAST *step, ExprAST *body)
    +    : VarName(varname), Start(start), End(end), Step(step), Body(body) {}
    +  virtual Value *Codegen();
    +};
    +
    +/// PrototypeAST - This class represents the "prototype" for a function,
    +/// which captures its name, and its argument names (thus implicitly the number
    +/// of arguments the function takes), as well as if it is an operator.
    +class PrototypeAST {
    +  std::string Name;
    +  std::vector<std::string> Args;
    +  bool isOperator;
    +  unsigned Precedence;  // Precedence if a binary op.
    +public:
    +  PrototypeAST(const std::string &name, const std::vector<std::string> &args,
    +               bool isoperator = false, unsigned prec = 0)
    +  : Name(name), Args(args), isOperator(isoperator), Precedence(prec) {}
    +  
    +  bool isUnaryOp() const { return isOperator && Args.size() == 1; }
    +  bool isBinaryOp() const { return isOperator && Args.size() == 2; }
    +  
    +  char getOperatorName() const {
    +    assert(isUnaryOp() || isBinaryOp());
    +    return Name[Name.size()-1];
    +  }
    +  
    +  unsigned getBinaryPrecedence() const { return Precedence; }
    +  
    +  Function *Codegen();
    +};
    +
    +/// FunctionAST - This class represents a function definition itself.
    +class FunctionAST {
    +  PrototypeAST *Proto;
    +  ExprAST *Body;
    +public:
    +  FunctionAST(PrototypeAST *proto, ExprAST *body)
    +    : Proto(proto), Body(body) {}
    +  
    +  Function *Codegen();
    +};
    +
    +//===----------------------------------------------------------------------===//
    +// Parser
    +//===----------------------------------------------------------------------===//
    +
    +/// CurTok/getNextToken - Provide a simple token buffer.  CurTok is the current
    +/// token the parser is looking at.  getNextToken reads another token from the
    +/// lexer and updates CurTok with its results.
    +static int CurTok;
    +static int getNextToken() {
    +  return CurTok = gettok();
    +}
    +
    +/// BinopPrecedence - This holds the precedence for each binary operator that is
    +/// defined.
    +static std::map<char, int> BinopPrecedence;
    +
    +/// GetTokPrecedence - Get the precedence of the pending binary operator token.
    +static int GetTokPrecedence() {
    +  if (!isascii(CurTok))
    +    return -1;
    +  
    +  // Make sure it's a declared binop.
    +  int TokPrec = BinopPrecedence[CurTok];
    +  if (TokPrec <= 0) return -1;
    +  return TokPrec;
    +}
    +
    +/// Error* - These are little helper functions for error handling.
    +ExprAST *Error(const char *Str) { fprintf(stderr, "Error: %s\n", Str);return 0;}
    +PrototypeAST *ErrorP(const char *Str) { Error(Str); return 0; }
    +FunctionAST *ErrorF(const char *Str) { Error(Str); return 0; }
    +
    +static ExprAST *ParseExpression();
    +
    +/// identifierexpr
    +///   ::= identifier
    +///   ::= identifier '(' expression* ')'
    +static ExprAST *ParseIdentifierExpr() {
    +  std::string IdName = IdentifierStr;
    +  
    +  getNextToken();  // eat identifier.
    +  
    +  if (CurTok != '(') // Simple variable ref.
    +    return new VariableExprAST(IdName);
    +  
    +  // Call.
    +  getNextToken();  // eat (
    +  std::vector<ExprAST*> Args;
    +  if (CurTok != ')') {
    +    while (1) {
    +      ExprAST *Arg = ParseExpression();
    +      if (!Arg) return 0;
    +      Args.push_back(Arg);
    +
    +      if (CurTok == ')') break;
    +
    +      if (CurTok != ',')
    +        return Error("Expected ')' or ',' in argument list");
    +      getNextToken();
    +    }
    +  }
    +
    +  // Eat the ')'.
    +  getNextToken();
    +  
    +  return new CallExprAST(IdName, Args);
    +}
    +
    +/// numberexpr ::= number
    +static ExprAST *ParseNumberExpr() {
    +  ExprAST *Result = new NumberExprAST(NumVal);
    +  getNextToken(); // consume the number
    +  return Result;
    +}
    +
    +/// parenexpr ::= '(' expression ')'
    +static ExprAST *ParseParenExpr() {
    +  getNextToken();  // eat (.
    +  ExprAST *V = ParseExpression();
    +  if (!V) return 0;
    +  
    +  if (CurTok != ')')
    +    return Error("expected ')'");
    +  getNextToken();  // eat ).
    +  return V;
    +}
    +
    +/// ifexpr ::= 'if' expression 'then' expression 'else' expression
    +static ExprAST *ParseIfExpr() {
    +  getNextToken();  // eat the if.
    +  
    +  // condition.
    +  ExprAST *Cond = ParseExpression();
    +  if (!Cond) return 0;
    +  
    +  if (CurTok != tok_then)
    +    return Error("expected then");
    +  getNextToken();  // eat the then
    +  
    +  ExprAST *Then = ParseExpression();
    +  if (Then == 0) return 0;
    +  
    +  if (CurTok != tok_else)
    +    return Error("expected else");
    +  
    +  getNextToken();
    +  
    +  ExprAST *Else = ParseExpression();
    +  if (!Else) return 0;
    +  
    +  return new IfExprAST(Cond, Then, Else);
    +}
    +
    +/// forexpr ::= 'for' identifier '=' expr ',' expr (',' expr)? 'in' expression
    +static ExprAST *ParseForExpr() {
    +  getNextToken();  // eat the for.
    +
    +  if (CurTok != tok_identifier)
    +    return Error("expected identifier after for");
    +  
    +  std::string IdName = IdentifierStr;
    +  getNextToken();  // eat identifier.
    +  
    +  if (CurTok != '=')
    +    return Error("expected '=' after for");
    +  getNextToken();  // eat '='.
    +  
    +  
    +  ExprAST *Start = ParseExpression();
    +  if (Start == 0) return 0;
    +  if (CurTok != ',')
    +    return Error("expected ',' after for start value");
    +  getNextToken();
    +  
    +  ExprAST *End = ParseExpression();
    +  if (End == 0) return 0;
    +  
    +  // The step value is optional.
    +  ExprAST *Step = 0;
    +  if (CurTok == ',') {
    +    getNextToken();
    +    Step = ParseExpression();
    +    if (Step == 0) return 0;
    +  }
    +  
    +  if (CurTok != tok_in)
    +    return Error("expected 'in' after for");
    +  getNextToken();  // eat 'in'.
    +  
    +  ExprAST *Body = ParseExpression();
    +  if (Body == 0) return 0;
    +
    +  return new ForExprAST(IdName, Start, End, Step, Body);
    +}
    +
    +/// primary
    +///   ::= identifierexpr
    +///   ::= numberexpr
    +///   ::= parenexpr
    +///   ::= ifexpr
    +///   ::= forexpr
    +static ExprAST *ParsePrimary() {
    +  switch (CurTok) {
    +  default: return Error("unknown token when expecting an expression");
    +  case tok_identifier: return ParseIdentifierExpr();
    +  case tok_number:     return ParseNumberExpr();
    +  case '(':            return ParseParenExpr();
    +  case tok_if:         return ParseIfExpr();
    +  case tok_for:        return ParseForExpr();
    +  }
    +}
    +
    +/// unary
    +///   ::= primary
    +///   ::= '!' unary
    +static ExprAST *ParseUnary() {
    +  // If the current token is not an operator, it must be a primary expr.
    +  if (!isascii(CurTok) || CurTok == '(' || CurTok == ',')
    +    return ParsePrimary();
    +  
    +  // If this is a unary operator, read it.
    +  int Opc = CurTok;
    +  getNextToken();
    +  if (ExprAST *Operand = ParseUnary())
    +    return new UnaryExprAST(Opc, Operand);
    +  return 0;
    +}
    +
    +/// binoprhs
    +///   ::= ('+' unary)*
    +static ExprAST *ParseBinOpRHS(int ExprPrec, ExprAST *LHS) {
    +  // If this is a binop, find its precedence.
    +  while (1) {
    +    int TokPrec = GetTokPrecedence();
    +    
    +    // If this is a binop that binds at least as tightly as the current binop,
    +    // consume it, otherwise we are done.
    +    if (TokPrec < ExprPrec)
    +      return LHS;
    +    
    +    // Okay, we know this is a binop.
    +    int BinOp = CurTok;
    +    getNextToken();  // eat binop
    +    
    +    // Parse the unary expression after the binary operator.
    +    ExprAST *RHS = ParseUnary();
    +    if (!RHS) return 0;
    +    
    +    // If BinOp binds less tightly with RHS than the operator after RHS, let
    +    // the pending operator take RHS as its LHS.
    +    int NextPrec = GetTokPrecedence();
    +    if (TokPrec < NextPrec) {
    +      RHS = ParseBinOpRHS(TokPrec+1, RHS);
    +      if (RHS == 0) return 0;
    +    }
    +    
    +    // Merge LHS/RHS.
    +    LHS = new BinaryExprAST(BinOp, LHS, RHS);
    +  }
    +}
    +
    +/// expression
    +///   ::= unary binoprhs
    +///
    +static ExprAST *ParseExpression() {
    +  ExprAST *LHS = ParseUnary();
    +  if (!LHS) return 0;
    +  
    +  return ParseBinOpRHS(0, LHS);
    +}
    +
    +/// prototype
    +///   ::= id '(' id* ')'
    +///   ::= binary LETTER number? (id, id)
    +///   ::= unary LETTER (id)
    +static PrototypeAST *ParsePrototype() {
    +  std::string FnName;
    +  
    +  unsigned Kind = 0; // 0 = identifier, 1 = unary, 2 = binary.
    +  unsigned BinaryPrecedence = 30;
    +  
    +  switch (CurTok) {
    +  default:
    +    return ErrorP("Expected function name in prototype");
    +  case tok_identifier:
    +    FnName = IdentifierStr;
    +    Kind = 0;
    +    getNextToken();
    +    break;
    +  case tok_unary:
    +    getNextToken();
    +    if (!isascii(CurTok))
    +      return ErrorP("Expected unary operator");
    +    FnName = "unary";
    +    FnName += (char)CurTok;
    +    Kind = 1;
    +    getNextToken();
    +    break;
    +  case tok_binary:
    +    getNextToken();
    +    if (!isascii(CurTok))
    +      return ErrorP("Expected binary operator");
    +    FnName = "binary";
    +    FnName += (char)CurTok;
    +    Kind = 2;
    +    getNextToken();
    +    
    +    // Read the precedence if present.
    +    if (CurTok == tok_number) {
    +      if (NumVal < 1 || NumVal > 100)
    +        return ErrorP("Invalid precedecnce: must be 1..100");
    +      BinaryPrecedence = (unsigned)NumVal;
    +      getNextToken();
    +    }
    +    break;
    +  }
    +  
    +  if (CurTok != '(')
    +    return ErrorP("Expected '(' in prototype");
    +  
    +  std::vector<std::string> ArgNames;
    +  while (getNextToken() == tok_identifier)
    +    ArgNames.push_back(IdentifierStr);
    +  if (CurTok != ')')
    +    return ErrorP("Expected ')' in prototype");
    +  
    +  // success.
    +  getNextToken();  // eat ')'.
    +  
    +  // Verify right number of names for operator.
    +  if (Kind && ArgNames.size() != Kind)
    +    return ErrorP("Invalid number of operands for operator");
    +  
    +  return new PrototypeAST(FnName, ArgNames, Kind != 0, BinaryPrecedence);
    +}
    +
    +/// definition ::= 'def' prototype expression
    +static FunctionAST *ParseDefinition() {
    +  getNextToken();  // eat def.
    +  PrototypeAST *Proto = ParsePrototype();
    +  if (Proto == 0) return 0;
    +
    +  if (ExprAST *E = ParseExpression())
    +    return new FunctionAST(Proto, E);
    +  return 0;
    +}
    +
    +/// toplevelexpr ::= expression
    +static FunctionAST *ParseTopLevelExpr() {
    +  if (ExprAST *E = ParseExpression()) {
    +    // Make an anonymous proto.
    +    PrototypeAST *Proto = new PrototypeAST("", std::vector<std::string>());
    +    return new FunctionAST(Proto, E);
    +  }
    +  return 0;
    +}
    +
    +/// external ::= 'extern' prototype
    +static PrototypeAST *ParseExtern() {
    +  getNextToken();  // eat extern.
    +  return ParsePrototype();
    +}
    +
    +//===----------------------------------------------------------------------===//
    +// Code Generation
    +//===----------------------------------------------------------------------===//
    +
    +static Module *TheModule;
    +static IRBuilder<> Builder(getGlobalContext());
    +static std::map<std::string, Value*> NamedValues;
    +static FunctionPassManager *TheFPM;
    +
    +Value *ErrorV(const char *Str) { Error(Str); return 0; }
    +
    +Value *NumberExprAST::Codegen() {
    +  return ConstantFP::get(getGlobalContext(), APFloat(Val));
    +}
    +
    +Value *VariableExprAST::Codegen() {
    +  // Look this variable up in the function.
    +  Value *V = NamedValues[Name];
    +  return V ? V : ErrorV("Unknown variable name");
    +}
    +
    +Value *UnaryExprAST::Codegen() {
    +  Value *OperandV = Operand->Codegen();
    +  if (OperandV == 0) return 0;
    +  
    +  Function *F = TheModule->getFunction(std::string("unary")+Opcode);
    +  if (F == 0)
    +    return ErrorV("Unknown unary operator");
    +  
    +  return Builder.CreateCall(F, OperandV, "unop");
    +}
    +
    +Value *BinaryExprAST::Codegen() {
    +  Value *L = LHS->Codegen();
    +  Value *R = RHS->Codegen();
    +  if (L == 0 || R == 0) return 0;
    +  
    +  switch (Op) {
    +  case '+': return Builder.CreateAdd(L, R, "addtmp");
    +  case '-': return Builder.CreateSub(L, R, "subtmp");
    +  case '*': return Builder.CreateMul(L, R, "multmp");
    +  case '<':
    +    L = Builder.CreateFCmpULT(L, R, "cmptmp");
    +    // Convert bool 0/1 to double 0.0 or 1.0
    +    return Builder.CreateUIToFP(L, Type::getDoubleTy(getGlobalContext()),
    +                                "booltmp");
    +  default: break;
    +  }
    +  
    +  // If it wasn't a builtin binary operator, it must be a user defined one. Emit
    +  // a call to it.
    +  Function *F = TheModule->getFunction(std::string("binary")+Op);
    +  assert(F && "binary operator not found!");
    +  
    +  Value *Ops[] = { L, R };
    +  return Builder.CreateCall(F, Ops, Ops+2, "binop");
    +}
    +
    +Value *CallExprAST::Codegen() {
    +  // Look up the name in the global module table.
    +  Function *CalleeF = TheModule->getFunction(Callee);
    +  if (CalleeF == 0)
    +    return ErrorV("Unknown function referenced");
    +  
    +  // If argument mismatch error.
    +  if (CalleeF->arg_size() != Args.size())
    +    return ErrorV("Incorrect # arguments passed");
    +
    +  std::vector<Value*> ArgsV;
    +  for (unsigned i = 0, e = Args.size(); i != e; ++i) {
    +    ArgsV.push_back(Args[i]->Codegen());
    +    if (ArgsV.back() == 0) return 0;
    +  }
    +  
    +  return Builder.CreateCall(CalleeF, ArgsV.begin(), ArgsV.end(), "calltmp");
    +}
    +
    +Value *IfExprAST::Codegen() {
    +  Value *CondV = Cond->Codegen();
    +  if (CondV == 0) return 0;
    +  
    +  // Convert condition to a bool by comparing equal to 0.0.
    +  CondV = Builder.CreateFCmpONE(CondV, 
    +                              ConstantFP::get(getGlobalContext(), APFloat(0.0)),
    +                                "ifcond");
    +  
    +  Function *TheFunction = Builder.GetInsertBlock()->getParent();
    +  
    +  // Create blocks for the then and else cases.  Insert the 'then' block at the
    +  // end of the function.
    +  BasicBlock *ThenBB = BasicBlock::Create(getGlobalContext(), "then", TheFunction);
    +  BasicBlock *ElseBB = BasicBlock::Create(getGlobalContext(), "else");
    +  BasicBlock *MergeBB = BasicBlock::Create(getGlobalContext(), "ifcont");
    +  
    +  Builder.CreateCondBr(CondV, ThenBB, ElseBB);
    +  
    +  // Emit then value.
    +  Builder.SetInsertPoint(ThenBB);
    +  
    +  Value *ThenV = Then->Codegen();
    +  if (ThenV == 0) return 0;
    +  
    +  Builder.CreateBr(MergeBB);
    +  // Codegen of 'Then' can change the current block, update ThenBB for the PHI.
    +  ThenBB = Builder.GetInsertBlock();
    +  
    +  // Emit else block.
    +  TheFunction->getBasicBlockList().push_back(ElseBB);
    +  Builder.SetInsertPoint(ElseBB);
    +  
    +  Value *ElseV = Else->Codegen();
    +  if (ElseV == 0) return 0;
    +  
    +  Builder.CreateBr(MergeBB);
    +  // Codegen of 'Else' can change the current block, update ElseBB for the PHI.
    +  ElseBB = Builder.GetInsertBlock();
    +  
    +  // Emit merge block.
    +  TheFunction->getBasicBlockList().push_back(MergeBB);
    +  Builder.SetInsertPoint(MergeBB);
    +  PHINode *PN = Builder.CreatePHI(Type::getDoubleTy(getGlobalContext()),
    +                                  "iftmp");
    +  
    +  PN->addIncoming(ThenV, ThenBB);
    +  PN->addIncoming(ElseV, ElseBB);
    +  return PN;
    +}
    +
    +Value *ForExprAST::Codegen() {
    +  // Output this as:
    +  //   ...
    +  //   start = startexpr
    +  //   goto loop
    +  // loop: 
    +  //   variable = phi [start, loopheader], [nextvariable, loopend]
    +  //   ...
    +  //   bodyexpr
    +  //   ...
    +  // loopend:
    +  //   step = stepexpr
    +  //   nextvariable = variable + step
    +  //   endcond = endexpr
    +  //   br endcond, loop, endloop
    +  // outloop:
    +  
    +  // Emit the start code first, without 'variable' in scope.
    +  Value *StartVal = Start->Codegen();
    +  if (StartVal == 0) return 0;
    +  
    +  // Make the new basic block for the loop header, inserting after current
    +  // block.
    +  Function *TheFunction = Builder.GetInsertBlock()->getParent();
    +  BasicBlock *PreheaderBB = Builder.GetInsertBlock();
    +  BasicBlock *LoopBB = BasicBlock::Create(getGlobalContext(), "loop", TheFunction);
    +  
    +  // Insert an explicit fall through from the current block to the LoopBB.
    +  Builder.CreateBr(LoopBB);
    +
    +  // Start insertion in LoopBB.
    +  Builder.SetInsertPoint(LoopBB);
    +  
    +  // Start the PHI node with an entry for Start.
    +  PHINode *Variable = Builder.CreatePHI(Type::getDoubleTy(getGlobalContext()), VarName.c_str());
    +  Variable->addIncoming(StartVal, PreheaderBB);
    +  
    +  // Within the loop, the variable is defined equal to the PHI node.  If it
    +  // shadows an existing variable, we have to restore it, so save it now.
    +  Value *OldVal = NamedValues[VarName];
    +  NamedValues[VarName] = Variable;
    +  
    +  // Emit the body of the loop.  This, like any other expr, can change the
    +  // current BB.  Note that we ignore the value computed by the body, but don't
    +  // allow an error.
    +  if (Body->Codegen() == 0)
    +    return 0;
    +  
    +  // Emit the step value.
    +  Value *StepVal;
    +  if (Step) {
    +    StepVal = Step->Codegen();
    +    if (StepVal == 0) return 0;
    +  } else {
    +    // If not specified, use 1.0.
    +    StepVal = ConstantFP::get(getGlobalContext(), APFloat(1.0));
    +  }
    +  
    +  Value *NextVar = Builder.CreateAdd(Variable, StepVal, "nextvar");
    +
    +  // Compute the end condition.
    +  Value *EndCond = End->Codegen();
    +  if (EndCond == 0) return EndCond;
    +  
    +  // Convert condition to a bool by comparing equal to 0.0.
    +  EndCond = Builder.CreateFCmpONE(EndCond, 
    +                              ConstantFP::get(getGlobalContext(), APFloat(0.0)),
    +                                  "loopcond");
    +  
    +  // Create the "after loop" block and insert it.
    +  BasicBlock *LoopEndBB = Builder.GetInsertBlock();
    +  BasicBlock *AfterBB = BasicBlock::Create(getGlobalContext(), "afterloop", TheFunction);
    +  
    +  // Insert the conditional branch into the end of LoopEndBB.
    +  Builder.CreateCondBr(EndCond, LoopBB, AfterBB);
    +  
    +  // Any new code will be inserted in AfterBB.
    +  Builder.SetInsertPoint(AfterBB);
    +  
    +  // Add a new entry to the PHI node for the backedge.
    +  Variable->addIncoming(NextVar, LoopEndBB);
    +  
    +  // Restore the unshadowed variable.
    +  if (OldVal)
    +    NamedValues[VarName] = OldVal;
    +  else
    +    NamedValues.erase(VarName);
    +
    +  
    +  // for expr always returns 0.0.
    +  return Constant::getNullValue(Type::getDoubleTy(getGlobalContext()));
    +}
    +
    +Function *PrototypeAST::Codegen() {
    +  // Make the function type:  double(double,double) etc.
    +  std::vector<const Type*> Doubles(Args.size(),
    +                                   Type::getDoubleTy(getGlobalContext()));
    +  FunctionType *FT = FunctionType::get(Type::getDoubleTy(getGlobalContext()),
    +                                       Doubles, false);
    +  
    +  Function *F = Function::Create(FT, Function::ExternalLinkage, Name, TheModule);
    +  
    +  // If F conflicted, there was already something named 'Name'.  If it has a
    +  // body, don't allow redefinition or reextern.
    +  if (F->getName() != Name) {
    +    // Delete the one we just made and get the existing one.
    +    F->eraseFromParent();
    +    F = TheModule->getFunction(Name);
    +    
    +    // If F already has a body, reject this.
    +    if (!F->empty()) {
    +      ErrorF("redefinition of function");
    +      return 0;
    +    }
    +    
    +    // If F took a different number of args, reject.
    +    if (F->arg_size() != Args.size()) {
    +      ErrorF("redefinition of function with different # args");
    +      return 0;
    +    }
    +  }
    +  
    +  // Set names for all arguments.
    +  unsigned Idx = 0;
    +  for (Function::arg_iterator AI = F->arg_begin(); Idx != Args.size();
    +       ++AI, ++Idx) {
    +    AI->setName(Args[Idx]);
    +    
    +    // Add arguments to variable symbol table.
    +    NamedValues[Args[Idx]] = AI;
    +  }
    +  
    +  return F;
    +}
    +
    +Function *FunctionAST::Codegen() {
    +  NamedValues.clear();
    +  
    +  Function *TheFunction = Proto->Codegen();
    +  if (TheFunction == 0)
    +    return 0;
    +  
    +  // If this is an operator, install it.
    +  if (Proto->isBinaryOp())
    +    BinopPrecedence[Proto->getOperatorName()] = Proto->getBinaryPrecedence();
    +  
    +  // Create a new basic block to start insertion into.
    +  BasicBlock *BB = BasicBlock::Create(getGlobalContext(), "entry", TheFunction);
    +  Builder.SetInsertPoint(BB);
    +  
    +  if (Value *RetVal = Body->Codegen()) {
    +    // Finish off the function.
    +    Builder.CreateRet(RetVal);
    +
    +    // Validate the generated code, checking for consistency.
    +    verifyFunction(*TheFunction);
    +
    +    // Optimize the function.
    +    TheFPM->run(*TheFunction);
    +    
    +    return TheFunction;
    +  }
    +  
    +  // Error reading body, remove function.
    +  TheFunction->eraseFromParent();
    +
    +  if (Proto->isBinaryOp())
    +    BinopPrecedence.erase(Proto->getOperatorName());
    +  return 0;
    +}
    +
    +//===----------------------------------------------------------------------===//
    +// Top-Level parsing and JIT Driver
    +//===----------------------------------------------------------------------===//
    +
    +static ExecutionEngine *TheExecutionEngine;
    +
    +static void HandleDefinition() {
    +  if (FunctionAST *F = ParseDefinition()) {
    +    if (Function *LF = F->Codegen()) {
    +      fprintf(stderr, "Read function definition:");
    +      LF->dump();
    +    }
    +  } else {
    +    // Skip token for error recovery.
    +    getNextToken();
    +  }
    +}
    +
    +static void HandleExtern() {
    +  if (PrototypeAST *P = ParseExtern()) {
    +    if (Function *F = P->Codegen()) {
    +      fprintf(stderr, "Read extern: ");
    +      F->dump();
    +    }
    +  } else {
    +    // Skip token for error recovery.
    +    getNextToken();
    +  }
    +}
    +
    +static void HandleTopLevelExpression() {
    +  // Evaluate a top-level expression into an anonymous function.
    +  if (FunctionAST *F = ParseTopLevelExpr()) {
    +    if (Function *LF = F->Codegen()) {
    +      // JIT the function, returning a function pointer.
    +      void *FPtr = TheExecutionEngine->getPointerToFunction(LF);
    +      
    +      // Cast it to the right type (takes no arguments, returns a double) so we
    +      // can call it as a native function.
    +      double (*FP)() = (double (*)())(intptr_t)FPtr;
    +      fprintf(stderr, "Evaluated to %f\n", FP());
    +    }
    +  } else {
    +    // Skip token for error recovery.
    +    getNextToken();
    +  }
    +}
    +
    +/// top ::= definition | external | expression | ';'
    +static void MainLoop() {
    +  while (1) {
    +    fprintf(stderr, "ready> ");
    +    switch (CurTok) {
    +    case tok_eof:    return;
    +    case ';':        getNextToken(); break;  // ignore top-level semicolons.
    +    case tok_def:    HandleDefinition(); break;
    +    case tok_extern: HandleExtern(); break;
    +    default:         HandleTopLevelExpression(); break;
    +    }
    +  }
    +}
    +
    +//===----------------------------------------------------------------------===//
    +// "Library" functions that can be "extern'd" from user code.
    +//===----------------------------------------------------------------------===//
    +
    +/// putchard - putchar that takes a double and returns 0.
    +extern "C" 
    +double putchard(double X) {
    +  putchar((char)X);
    +  return 0;
    +}
    +
    +/// printd - printf that takes a double prints it as "%f\n", returning 0.
    +extern "C" 
    +double printd(double X) {
    +  printf("%f\n", X);
    +  return 0;
    +}
    +
    +//===----------------------------------------------------------------------===//
    +// Main driver code.
    +//===----------------------------------------------------------------------===//
    +
    +int main() {
    +  InitializeNativeTarget();
    +  LLVMContext &Context = getGlobalContext();
    +
    +  // Install standard binary operators.
    +  // 1 is lowest precedence.
    +  BinopPrecedence['<'] = 10;
    +  BinopPrecedence['+'] = 20;
    +  BinopPrecedence['-'] = 20;
    +  BinopPrecedence['*'] = 40;  // highest.
    +
    +  // Prime the first token.
    +  fprintf(stderr, "ready> ");
    +  getNextToken();
    +
    +  // Make the module, which holds all the code.
    +  TheModule = new Module("my cool jit", Context);
    +
    +  ExistingModuleProvider *OurModuleProvider =
    +      new ExistingModuleProvider(TheModule);
    +
    +  // Create the JIT.  This takes ownership of the module and module provider.
    +  TheExecutionEngine = EngineBuilder(OurModuleProvider).create();
    +
    +  FunctionPassManager OurFPM(OurModuleProvider);
    +
    +  // Set up the optimizer pipeline.  Start with registering info about how the
    +  // target lays out data structures.
    +  OurFPM.add(new TargetData(*TheExecutionEngine->getTargetData()));
    +  // Do simple "peephole" optimizations and bit-twiddling optzns.
    +  OurFPM.add(createInstructionCombiningPass());
    +  // Reassociate expressions.
    +  OurFPM.add(createReassociatePass());
    +  // Eliminate Common SubExpressions.
    +  OurFPM.add(createGVNPass());
    +  // Simplify the control flow graph (deleting unreachable blocks, etc).
    +  OurFPM.add(createCFGSimplificationPass());
    +
    +  OurFPM.doInitialization();
    +
    +  // Set the global so the code gen can use this.
    +  TheFPM = &OurFPM;
    +
    +  // Run the main "interpreter loop" now.
    +  MainLoop();
    +
    +  TheFPM = 0;
    +
    +  // Print out all of the generated code.
    +  TheModule->dump();
    +
    +  return 0;
    +}
    +
    +
    + +Next: Extending the language: mutable variables / SSA construction +
    + + +
    +
    + Valid CSS! + Valid HTML 4.01! + + Chris Lattner
    + The LLVM Compiler Infrastructure
    + Last modified: $Date: 2007-10-17 11:05:13 -0700 (Wed, 17 Oct 2007) $ +
    + + diff --git a/libclamav/c++/llvm/docs/tutorial/LangImpl7.html b/libclamav/c++/llvm/docs/tutorial/LangImpl7.html new file mode 100644 index 000000000..ec07fa88d --- /dev/null +++ b/libclamav/c++/llvm/docs/tutorial/LangImpl7.html @@ -0,0 +1,2164 @@ + + + + + Kaleidoscope: Extending the Language: Mutable Variables / SSA + construction + + + + + + + +
    Kaleidoscope: Extending the Language: Mutable Variables
    + + + +
    +

    Written by Chris Lattner

    +
    + + + + + +
    + +

    Welcome to Chapter 7 of the "Implementing a language +with LLVM" tutorial. In chapters 1 through 6, we've built a very +respectable, albeit simple, functional +programming language. In our journey, we learned some parsing techniques, +how to build and represent an AST, how to build LLVM IR, and how to optimize +the resultant code as well as JIT compile it.

    + +

    While Kaleidoscope is interesting as a functional language, the fact that it +is functional makes it "too easy" to generate LLVM IR for it. In particular, a +functional language makes it very easy to build LLVM IR directly in SSA form. +Since LLVM requires that the input code be in SSA form, this is a very nice +property and it is often unclear to newcomers how to generate code for an +imperative language with mutable variables.

    + +

    The short (and happy) summary of this chapter is that there is no need for +your front-end to build SSA form: LLVM provides highly tuned and well tested +support for this, though the way it works is a bit unexpected for some.

    + +
    + + + + + +
    + +

    +To understand why mutable variables cause complexities in SSA construction, +consider this extremely simple C example: +

    + +
    +
    +int G, H;
    +int test(_Bool Condition) {
    +  int X;
    +  if (Condition)
    +    X = G;
    +  else
    +    X = H;
    +  return X;
    +}
    +
    +
    + +

    In this case, we have the variable "X", whose value depends on the path +executed in the program. Because there are two different possible values for X +before the return instruction, a PHI node is inserted to merge the two values. +The LLVM IR that we want for this example looks like this:

    + +
    +
    +@G = weak global i32 0   ; type of @G is i32*
    +@H = weak global i32 0   ; type of @H is i32*
    +
    +define i32 @test(i1 %Condition) {
    +entry:
    +	br i1 %Condition, label %cond_true, label %cond_false
    +
    +cond_true:
    +	%X.0 = load i32* @G
    +	br label %cond_next
    +
    +cond_false:
    +	%X.1 = load i32* @H
    +	br label %cond_next
    +
    +cond_next:
    +	%X.2 = phi i32 [ %X.1, %cond_false ], [ %X.0, %cond_true ]
    +	ret i32 %X.2
    +}
    +
    +
    + +

    In this example, the loads from the G and H global variables are explicit in +the LLVM IR, and they live in the then/else branches of the if statement +(cond_true/cond_false). In order to merge the incoming values, the X.2 phi node +in the cond_next block selects the right value to use based on where control +flow is coming from: if control flow comes from the cond_false block, X.2 gets +the value of X.1. Alternatively, if control flow comes from cond_true, it gets +the value of X.0. The intent of this chapter is not to explain the details of +SSA form. For more information, see one of the many online +references.

    + +

    The question for this article is "who places the phi nodes when lowering +assignments to mutable variables?". The issue here is that LLVM +requires that its IR be in SSA form: there is no "non-ssa" mode for it. +However, SSA construction requires non-trivial algorithms and data structures, +so it is inconvenient and wasteful for every front-end to have to reproduce this +logic.

    + +
    + + + + + +
    + +

    The 'trick' here is that while LLVM does require all register values to be +in SSA form, it does not require (or permit) memory objects to be in SSA form. +In the example above, note that the loads from G and H are direct accesses to +G and H: they are not renamed or versioned. This differs from some other +compiler systems, which do try to version memory objects. In LLVM, instead of +encoding dataflow analysis of memory into the LLVM IR, it is handled with Analysis Passes which are computed on +demand.

    + +

    +With this in mind, the high-level idea is that we want to make a stack variable +(which lives in memory, because it is on the stack) for each mutable object in +a function. To take advantage of this trick, we need to talk about how LLVM +represents stack variables. +

    + +

    In LLVM, all memory accesses are explicit with load/store instructions, and +it is carefully designed not to have (or need) an "address-of" operator. Notice +how the type of the @G/@H global variables is actually "i32*" even though the +variable is defined as "i32". What this means is that @G defines space +for an i32 in the global data area, but its name actually refers to the +address for that space. Stack variables work the same way, except that instead of +being declared with global variable definitions, they are declared with the +LLVM alloca instruction:

    + +
    +
    +define i32 @example() {
    +entry:
    +	%X = alloca i32           ; type of %X is i32*.
    +	...
    +	%tmp = load i32* %X       ; load the stack value %X from the stack.
    +	%tmp2 = add i32 %tmp, 1   ; increment it
    +	store i32 %tmp2, i32* %X  ; store it back
    +	...
    +
    +
    + +

    This code shows an example of how you can declare and manipulate a stack +variable in the LLVM IR. Stack memory allocated with the alloca instruction is +fully general: you can pass the address of the stack slot to functions, you can +store it in other variables, etc. In our example above, we could rewrite the +example to use the alloca technique to avoid using a PHI node:

    + +
    +
    +@G = weak global i32 0   ; type of @G is i32*
    +@H = weak global i32 0   ; type of @H is i32*
    +
    +define i32 @test(i1 %Condition) {
    +entry:
    +	%X = alloca i32           ; type of %X is i32*.
    +	br i1 %Condition, label %cond_true, label %cond_false
    +
    +cond_true:
    +	%X.0 = load i32* @G
    +        store i32 %X.0, i32* %X   ; Update X
    +	br label %cond_next
    +
    +cond_false:
    +	%X.1 = load i32* @H
    +        store i32 %X.1, i32* %X   ; Update X
    +	br label %cond_next
    +
    +cond_next:
    +	%X.2 = load i32* %X       ; Read X
    +	ret i32 %X.2
    +}
    +
    +
    + +

    With this, we have discovered a way to handle arbitrary mutable variables +without the need to create Phi nodes at all:

    + +
      +
    1. Each mutable variable becomes a stack allocation.
    2. +
    3. Each read of the variable becomes a load from the stack.
    4. +
    5. Each update of the variable becomes a store to the stack.
    6. +
    7. Taking the address of a variable just uses the stack address directly.
    8. +
    + +

    While this solution has solved our immediate problem, it introduced another +one: we have now apparently introduced a lot of stack traffic for very simple +and common operations, a major performance problem. Fortunately for us, the +LLVM optimizer has a highly-tuned optimization pass named "mem2reg" that handles +this case, promoting allocas like this into SSA registers, inserting Phi nodes +as appropriate. If you run this example through the pass, for example, you'll +get:

    + +
    +
    +$ llvm-as < example.ll | opt -mem2reg | llvm-dis
    +@G = weak global i32 0
    +@H = weak global i32 0
    +
    +define i32 @test(i1 %Condition) {
    +entry:
    +	br i1 %Condition, label %cond_true, label %cond_false
    +
    +cond_true:
    +	%X.0 = load i32* @G
    +	br label %cond_next
    +
    +cond_false:
    +	%X.1 = load i32* @H
    +	br label %cond_next
    +
    +cond_next:
    +	%X.01 = phi i32 [ %X.1, %cond_false ], [ %X.0, %cond_true ]
    +	ret i32 %X.01
    +}
    +
    +
    + +

    The mem2reg pass implements the standard "iterated dominance frontier" +algorithm for constructing SSA form and has a number of optimizations that speed +up (very common) degenerate cases. The mem2reg optimization pass is the answer to dealing +with mutable variables, and we highly recommend that you depend on it. Note that +mem2reg only works on variables in certain circumstances:

    + +
      +
    1. mem2reg is alloca-driven: it looks for allocas and if it can handle them, it +promotes them. It does not apply to global variables or heap allocations.
    2. + +
    3. mem2reg only looks for alloca instructions in the entry block of the +function. Being in the entry block guarantees that the alloca is only executed +once, which makes analysis simpler.
    4. + +
    5. mem2reg only promotes allocas whose uses are direct loads and stores. If +the address of the stack object is passed to a function, or if any funny pointer +arithmetic is involved, the alloca will not be promoted.
    6. + +
    7. mem2reg only works on allocas of first class +values (such as pointers, scalars and vectors), and only if the array size +of the allocation is 1 (or missing in the .ll file). mem2reg is not capable of +promoting structs or arrays to registers. Note that the "scalarrepl" pass is +more powerful and can promote structs, "unions", and arrays in many cases.
    8. + +
    + +

    +All of these properties are easy to satisfy for most imperative languages, and +we'll illustrate it below with Kaleidoscope. The final question you may be +asking is: should I bother with this nonsense for my front-end? Wouldn't it be +better if I just did SSA construction directly, avoiding use of the mem2reg +optimization pass? In short, we strongly recommend that you use this technique +for building SSA form, unless there is an extremely good reason not to. Using +this technique is:

    + +
      +
    • Proven and well tested: llvm-gcc and clang both use this technique for local +mutable variables. As such, the most common clients of LLVM are using this to +handle a bulk of their variables. You can be sure that bugs are found fast and +fixed early.
    • + +
    • Extremely Fast: mem2reg has a number of special cases that make it fast in +common cases as well as fully general. For example, it has fast-paths for +variables that are only used in a single block, variables that only have one +assignment point, good heuristics to avoid insertion of unneeded phi nodes, etc. +
    • + +
    • Needed for debug info generation: +Debug information in LLVM relies on having the address of the variable +exposed so that debug info can be attached to it. This technique dovetails +very naturally with this style of debug info.
    • +
    + +

    If nothing else, this makes it much easier to get your front-end up and +running, and is very simple to implement. Lets extend Kaleidoscope with mutable +variables now! +

    + +
    + + + + + +
    + +

    Now that we know the sort of problem we want to tackle, lets see what this +looks like in the context of our little Kaleidoscope language. We're going to +add two features:

    + +
      +
    1. The ability to mutate variables with the '=' operator.
    2. +
    3. The ability to define new variables.
    4. +
    + +

    While the first item is really what this is about, we only have variables +for incoming arguments as well as for induction variables, and redefining those only +goes so far :). Also, the ability to define new variables is a +useful thing regardless of whether you will be mutating them. Here's a +motivating example that shows how we could use these:

    + +
    +
    +# Define ':' for sequencing: as a low-precedence operator that ignores operands
    +# and just returns the RHS.
    +def binary : 1 (x y) y;
    +
    +# Recursive fib, we could do this before.
    +def fib(x)
    +  if (x < 3) then
    +    1
    +  else
    +    fib(x-1)+fib(x-2);
    +
    +# Iterative fib.
    +def fibi(x)
    +  var a = 1, b = 1, c in
    +  (for i = 3, i < x in 
    +     c = a + b :
    +     a = b :
    +     b = c) :
    +  b;
    +
    +# Call it. 
    +fibi(10);
    +
    +
    + +

    +In order to mutate variables, we have to change our existing variables to use +the "alloca trick". Once we have that, we'll add our new operator, then extend +Kaleidoscope to support new variable definitions. +

    + +
    + + + + + +
    + +

    +The symbol table in Kaleidoscope is managed at code generation time by the +'NamedValues' map. This map currently keeps track of the LLVM "Value*" +that holds the double value for the named variable. In order to support +mutation, we need to change this slightly, so that it NamedValues holds +the memory location of the variable in question. Note that this +change is a refactoring: it changes the structure of the code, but does not +(by itself) change the behavior of the compiler. All of these changes are +isolated in the Kaleidoscope code generator.

    + +

    +At this point in Kaleidoscope's development, it only supports variables for two +things: incoming arguments to functions and the induction variable of 'for' +loops. For consistency, we'll allow mutation of these variables in addition to +other user-defined variables. This means that these will both need memory +locations. +

    + +

    To start our transformation of Kaleidoscope, we'll change the NamedValues +map so that it maps to AllocaInst* instead of Value*. Once we do this, the C++ +compiler will tell us what parts of the code we need to update:

    + +
    +
    +static std::map<std::string, AllocaInst*> NamedValues;
    +
    +
    + +

    Also, since we will need to create these alloca's, we'll use a helper +function that ensures that the allocas are created in the entry block of the +function:

    + +
    +
    +/// CreateEntryBlockAlloca - Create an alloca instruction in the entry block of
    +/// the function.  This is used for mutable variables etc.
    +static AllocaInst *CreateEntryBlockAlloca(Function *TheFunction,
    +                                          const std::string &VarName) {
    +  IRBuilder<> TmpB(&TheFunction->getEntryBlock(),
    +                 TheFunction->getEntryBlock().begin());
    +  return TmpB.CreateAlloca(Type::getDoubleTy(getGlobalContext()), 0,
    +                           VarName.c_str());
    +}
    +
    +
    + +

    This funny looking code creates an IRBuilder object that is pointing at +the first instruction (.begin()) of the entry block. It then creates an alloca +with the expected name and returns it. Because all values in Kaleidoscope are +doubles, there is no need to pass in a type to use.

    + +

    With this in place, the first functionality change we want to make is to +variable references. In our new scheme, variables live on the stack, so code +generating a reference to them actually needs to produce a load from the stack +slot:

    + +
    +
    +Value *VariableExprAST::Codegen() {
    +  // Look this variable up in the function.
    +  Value *V = NamedValues[Name];
    +  if (V == 0) return ErrorV("Unknown variable name");
    +
    +  // Load the value.
    +  return Builder.CreateLoad(V, Name.c_str());
    +}
    +
    +
    + +

    As you can see, this is pretty straightforward. Now we need to update the +things that define the variables to set up the alloca. We'll start with +ForExprAST::Codegen (see the full code listing for +the unabridged code):

    + +
    +
    +  Function *TheFunction = Builder.GetInsertBlock()->getParent();
    +
    +  // Create an alloca for the variable in the entry block.
    +  AllocaInst *Alloca = CreateEntryBlockAlloca(TheFunction, VarName);
    +  
    +    // Emit the start code first, without 'variable' in scope.
    +  Value *StartVal = Start->Codegen();
    +  if (StartVal == 0) return 0;
    +  
    +  // Store the value into the alloca.
    +  Builder.CreateStore(StartVal, Alloca);
    +  ...
    +
    +  // Compute the end condition.
    +  Value *EndCond = End->Codegen();
    +  if (EndCond == 0) return EndCond;
    +  
    +  // Reload, increment, and restore the alloca.  This handles the case where
    +  // the body of the loop mutates the variable.
    +  Value *CurVar = Builder.CreateLoad(Alloca);
    +  Value *NextVar = Builder.CreateAdd(CurVar, StepVal, "nextvar");
    +  Builder.CreateStore(NextVar, Alloca);
    +  ...
    +
    +
    + +

    This code is virtually identical to the code before we allowed mutable variables. The +big difference is that we no longer have to construct a PHI node, and we use +load/store to access the variable as needed.

    + +

    To support mutable argument variables, we need to also make allocas for them. +The code for this is also pretty simple:

    + +
    +
    +/// CreateArgumentAllocas - Create an alloca for each argument and register the
    +/// argument in the symbol table so that references to it will succeed.
    +void PrototypeAST::CreateArgumentAllocas(Function *F) {
    +  Function::arg_iterator AI = F->arg_begin();
    +  for (unsigned Idx = 0, e = Args.size(); Idx != e; ++Idx, ++AI) {
    +    // Create an alloca for this variable.
    +    AllocaInst *Alloca = CreateEntryBlockAlloca(F, Args[Idx]);
    +
    +    // Store the initial value into the alloca.
    +    Builder.CreateStore(AI, Alloca);
    +
    +    // Add arguments to variable symbol table.
    +    NamedValues[Args[Idx]] = Alloca;
    +  }
    +}
    +
    +
    + +

    For each argument, we make an alloca, store the input value to the function +into the alloca, and register the alloca as the memory location for the +argument. This method gets invoked by FunctionAST::Codegen right after +it sets up the entry block for the function.

    + +

    The final missing piece is adding the mem2reg pass, which allows us to get +good codegen once again:

    + +
    +
    +    // Set up the optimizer pipeline.  Start with registering info about how the
    +    // target lays out data structures.
    +    OurFPM.add(new TargetData(*TheExecutionEngine->getTargetData()));
    +    // Promote allocas to registers.
    +    OurFPM.add(createPromoteMemoryToRegisterPass());
    +    // Do simple "peephole" optimizations and bit-twiddling optzns.
    +    OurFPM.add(createInstructionCombiningPass());
    +    // Reassociate expressions.
    +    OurFPM.add(createReassociatePass());
    +
    +
    + +

    It is interesting to see what the code looks like before and after the +mem2reg optimization runs. For example, this is the before/after code for our +recursive fib function. Before the optimization:

    + +
    +
    +define double @fib(double %x) {
    +entry:
    +	%x1 = alloca double
    +	store double %x, double* %x1
    +	%x2 = load double* %x1
    +	%cmptmp = fcmp ult double %x2, 3.000000e+00
    +	%booltmp = uitofp i1 %cmptmp to double
    +	%ifcond = fcmp one double %booltmp, 0.000000e+00
    +	br i1 %ifcond, label %then, label %else
    +
    +then:		; preds = %entry
    +	br label %ifcont
    +
    +else:		; preds = %entry
    +	%x3 = load double* %x1
    +	%subtmp = sub double %x3, 1.000000e+00
    +	%calltmp = call double @fib( double %subtmp )
    +	%x4 = load double* %x1
    +	%subtmp5 = sub double %x4, 2.000000e+00
    +	%calltmp6 = call double @fib( double %subtmp5 )
    +	%addtmp = add double %calltmp, %calltmp6
    +	br label %ifcont
    +
    +ifcont:		; preds = %else, %then
    +	%iftmp = phi double [ 1.000000e+00, %then ], [ %addtmp, %else ]
    +	ret double %iftmp
    +}
    +
    +
    + +

    Here there is only one variable (x, the input argument) but you can still +see the extremely simple-minded code generation strategy we are using. In the +entry block, an alloca is created, and the initial input value is stored into +it. Each reference to the variable does a reload from the stack. Also, note +that we didn't modify the if/then/else expression, so it still inserts a PHI +node. While we could make an alloca for it, it is actually easier to create a +PHI node for it, so we still just make the PHI.

    + +

    Here is the code after the mem2reg pass runs:

    + +
    +
    +define double @fib(double %x) {
    +entry:
    +	%cmptmp = fcmp ult double %x, 3.000000e+00
    +	%booltmp = uitofp i1 %cmptmp to double
    +	%ifcond = fcmp one double %booltmp, 0.000000e+00
    +	br i1 %ifcond, label %then, label %else
    +
    +then:
    +	br label %ifcont
    +
    +else:
    +	%subtmp = sub double %x, 1.000000e+00
    +	%calltmp = call double @fib( double %subtmp )
    +	%subtmp5 = sub double %x, 2.000000e+00
    +	%calltmp6 = call double @fib( double %subtmp5 )
    +	%addtmp = add double %calltmp, %calltmp6
    +	br label %ifcont
    +
    +ifcont:		; preds = %else, %then
    +	%iftmp = phi double [ 1.000000e+00, %then ], [ %addtmp, %else ]
    +	ret double %iftmp
    +}
    +
    +
    + +

    This is a trivial case for mem2reg, since there are no redefinitions of the +variable. The point of showing this is to calm your tension about inserting +such blatent inefficiencies :).

    + +

    After the rest of the optimizers run, we get:

    + +
    +
    +define double @fib(double %x) {
    +entry:
    +	%cmptmp = fcmp ult double %x, 3.000000e+00
    +	%booltmp = uitofp i1 %cmptmp to double
    +	%ifcond = fcmp ueq double %booltmp, 0.000000e+00
    +	br i1 %ifcond, label %else, label %ifcont
    +
    +else:
    +	%subtmp = sub double %x, 1.000000e+00
    +	%calltmp = call double @fib( double %subtmp )
    +	%subtmp5 = sub double %x, 2.000000e+00
    +	%calltmp6 = call double @fib( double %subtmp5 )
    +	%addtmp = add double %calltmp, %calltmp6
    +	ret double %addtmp
    +
    +ifcont:
    +	ret double 1.000000e+00
    +}
    +
    +
    + +

    Here we see that the simplifycfg pass decided to clone the return instruction +into the end of the 'else' block. This allowed it to eliminate some branches +and the PHI node.

    + +

    Now that all symbol table references are updated to use stack variables, +we'll add the assignment operator.

    + +
    + + + + + +
    + +

    With our current framework, adding a new assignment operator is really +simple. We will parse it just like any other binary operator, but handle it +internally (instead of allowing the user to define it). The first step is to +set a precedence:

    + +
    +
    + int main() {
    +   // Install standard binary operators.
    +   // 1 is lowest precedence.
    +   BinopPrecedence['='] = 2;
    +   BinopPrecedence['<'] = 10;
    +   BinopPrecedence['+'] = 20;
    +   BinopPrecedence['-'] = 20;
    +
    +
    + +

    Now that the parser knows the precedence of the binary operator, it takes +care of all the parsing and AST generation. We just need to implement codegen +for the assignment operator. This looks like:

    + +
    +
    +Value *BinaryExprAST::Codegen() {
    +  // Special case '=' because we don't want to emit the LHS as an expression.
    +  if (Op == '=') {
    +    // Assignment requires the LHS to be an identifier.
    +    VariableExprAST *LHSE = dynamic_cast<VariableExprAST*>(LHS);
    +    if (!LHSE)
    +      return ErrorV("destination of '=' must be a variable");
    +
    +
    + +

    Unlike the rest of the binary operators, our assignment operator doesn't +follow the "emit LHS, emit RHS, do computation" model. As such, it is handled +as a special case before the other binary operators are handled. The other +strange thing is that it requires the LHS to be a variable. It is invalid to +have "(x+1) = expr" - only things like "x = expr" are allowed. +

    + +
    +
    +    // Codegen the RHS.
    +    Value *Val = RHS->Codegen();
    +    if (Val == 0) return 0;
    +
    +    // Look up the name.
    +    Value *Variable = NamedValues[LHSE->getName()];
    +    if (Variable == 0) return ErrorV("Unknown variable name");
    +
    +    Builder.CreateStore(Val, Variable);
    +    return Val;
    +  }
    +  ...  
    +
    +
    + +

    Once we have the variable, codegen'ing the assignment is straightforward: +we emit the RHS of the assignment, create a store, and return the computed +value. Returning a value allows for chained assignments like "X = (Y = Z)".

    + +

    Now that we have an assignment operator, we can mutate loop variables and +arguments. For example, we can now run code like this:

    + +
    +
    +# Function to print a double.
    +extern printd(x);
    +
    +# Define ':' for sequencing: as a low-precedence operator that ignores operands
    +# and just returns the RHS.
    +def binary : 1 (x y) y;
    +
    +def test(x)
    +  printd(x) :
    +  x = 4 :
    +  printd(x);
    +
    +test(123);
    +
    +
    + +

    When run, this example prints "123" and then "4", showing that we did +actually mutate the value! Okay, we have now officially implemented our goal: +getting this to work requires SSA construction in the general case. However, +to be really useful, we want the ability to define our own local variables, lets +add this next! +

    + +
    + + + + + +
    + +

    Adding var/in is just like any other other extensions we made to +Kaleidoscope: we extend the lexer, the parser, the AST and the code generator. +The first step for adding our new 'var/in' construct is to extend the lexer. +As before, this is pretty trivial, the code looks like this:

    + +
    +
    +enum Token {
    +  ...
    +  // var definition
    +  tok_var = -13
    +...
    +}
    +...
    +static int gettok() {
    +...
    +    if (IdentifierStr == "in") return tok_in;
    +    if (IdentifierStr == "binary") return tok_binary;
    +    if (IdentifierStr == "unary") return tok_unary;
    +    if (IdentifierStr == "var") return tok_var;
    +    return tok_identifier;
    +...
    +
    +
    + +

    The next step is to define the AST node that we will construct. For var/in, +it looks like this:

    + +
    +
    +/// VarExprAST - Expression class for var/in
    +class VarExprAST : public ExprAST {
    +  std::vector<std::pair<std::string, ExprAST*> > VarNames;
    +  ExprAST *Body;
    +public:
    +  VarExprAST(const std::vector<std::pair<std::string, ExprAST*> > &varnames,
    +             ExprAST *body)
    +  : VarNames(varnames), Body(body) {}
    +  
    +  virtual Value *Codegen();
    +};
    +
    +
    + +

    var/in allows a list of names to be defined all at once, and each name can +optionally have an initializer value. As such, we capture this information in +the VarNames vector. Also, var/in has a body, this body is allowed to access +the variables defined by the var/in.

    + +

    With this in place, we can define the parser pieces. The first thing we do is add +it as a primary expression:

    + +
    +
    +/// primary
    +///   ::= identifierexpr
    +///   ::= numberexpr
    +///   ::= parenexpr
    +///   ::= ifexpr
    +///   ::= forexpr
    +///   ::= varexpr
    +static ExprAST *ParsePrimary() {
    +  switch (CurTok) {
    +  default: return Error("unknown token when expecting an expression");
    +  case tok_identifier: return ParseIdentifierExpr();
    +  case tok_number:     return ParseNumberExpr();
    +  case '(':            return ParseParenExpr();
    +  case tok_if:         return ParseIfExpr();
    +  case tok_for:        return ParseForExpr();
    +  case tok_var:        return ParseVarExpr();
    +  }
    +}
    +
    +
    + +

    Next we define ParseVarExpr:

    + +
    +
    +/// varexpr ::= 'var' identifier ('=' expression)? 
    +//                    (',' identifier ('=' expression)?)* 'in' expression
    +static ExprAST *ParseVarExpr() {
    +  getNextToken();  // eat the var.
    +
    +  std::vector<std::pair<std::string, ExprAST*> > VarNames;
    +
    +  // At least one variable name is required.
    +  if (CurTok != tok_identifier)
    +    return Error("expected identifier after var");
    +
    +
    + +

    The first part of this code parses the list of identifier/expr pairs into the +local VarNames vector. + +

    +
    +  while (1) {
    +    std::string Name = IdentifierStr;
    +    getNextToken();  // eat identifier.
    +
    +    // Read the optional initializer.
    +    ExprAST *Init = 0;
    +    if (CurTok == '=') {
    +      getNextToken(); // eat the '='.
    +      
    +      Init = ParseExpression();
    +      if (Init == 0) return 0;
    +    }
    +    
    +    VarNames.push_back(std::make_pair(Name, Init));
    +    
    +    // End of var list, exit loop.
    +    if (CurTok != ',') break;
    +    getNextToken(); // eat the ','.
    +    
    +    if (CurTok != tok_identifier)
    +      return Error("expected identifier list after var");
    +  }
    +
    +
    + +

    Once all the variables are parsed, we then parse the body and create the +AST node:

    + +
    +
    +  // At this point, we have to have 'in'.
    +  if (CurTok != tok_in)
    +    return Error("expected 'in' keyword after 'var'");
    +  getNextToken();  // eat 'in'.
    +  
    +  ExprAST *Body = ParseExpression();
    +  if (Body == 0) return 0;
    +  
    +  return new VarExprAST(VarNames, Body);
    +}
    +
    +
    + +

    Now that we can parse and represent the code, we need to support emission of +LLVM IR for it. This code starts out with:

    + +
    +
    +Value *VarExprAST::Codegen() {
    +  std::vector<AllocaInst *> OldBindings;
    +  
    +  Function *TheFunction = Builder.GetInsertBlock()->getParent();
    +
    +  // Register all variables and emit their initializer.
    +  for (unsigned i = 0, e = VarNames.size(); i != e; ++i) {
    +    const std::string &VarName = VarNames[i].first;
    +    ExprAST *Init = VarNames[i].second;
    +
    +
    + +

    Basically it loops over all the variables, installing them one at a time. +For each variable we put into the symbol table, we remember the previous value +that we replace in OldBindings.

    + +
    +
    +    // Emit the initializer before adding the variable to scope, this prevents
    +    // the initializer from referencing the variable itself, and permits stuff
    +    // like this:
    +    //  var a = 1 in
    +    //    var a = a in ...   # refers to outer 'a'.
    +    Value *InitVal;
    +    if (Init) {
    +      InitVal = Init->Codegen();
    +      if (InitVal == 0) return 0;
    +    } else { // If not specified, use 0.0.
    +      InitVal = ConstantFP::get(getGlobalContext(), APFloat(0.0));
    +    }
    +    
    +    AllocaInst *Alloca = CreateEntryBlockAlloca(TheFunction, VarName);
    +    Builder.CreateStore(InitVal, Alloca);
    +
    +    // Remember the old variable binding so that we can restore the binding when
    +    // we unrecurse.
    +    OldBindings.push_back(NamedValues[VarName]);
    +    
    +    // Remember this binding.
    +    NamedValues[VarName] = Alloca;
    +  }
    +
    +
    + +

    There are more comments here than code. The basic idea is that we emit the +initializer, create the alloca, then update the symbol table to point to it. +Once all the variables are installed in the symbol table, we evaluate the body +of the var/in expression:

    + +
    +
    +  // Codegen the body, now that all vars are in scope.
    +  Value *BodyVal = Body->Codegen();
    +  if (BodyVal == 0) return 0;
    +
    +
    + +

    Finally, before returning, we restore the previous variable bindings:

    + +
    +
    +  // Pop all our variables from scope.
    +  for (unsigned i = 0, e = VarNames.size(); i != e; ++i)
    +    NamedValues[VarNames[i].first] = OldBindings[i];
    +
    +  // Return the body computation.
    +  return BodyVal;
    +}
    +
    +
    + +

    The end result of all of this is that we get properly scoped variable +definitions, and we even (trivially) allow mutation of them :).

    + +

    With this, we completed what we set out to do. Our nice iterative fib +example from the intro compiles and runs just fine. The mem2reg pass optimizes +all of our stack variables into SSA registers, inserting PHI nodes where needed, +and our front-end remains simple: no "iterated dominance frontier" computation +anywhere in sight.

    + +
    + + + + + +
    + +

    +Here is the complete code listing for our running example, enhanced with mutable +variables and var/in support. To build this example, use: +

    + +
    +
    +   # Compile
    +   g++ -g toy.cpp `llvm-config --cppflags --ldflags --libs core jit native` -O3 -o toy
    +   # Run
    +   ./toy
    +
    +
    + +

    Here is the code:

    + +
    +
    +#include "llvm/DerivedTypes.h"
    +#include "llvm/ExecutionEngine/ExecutionEngine.h"
    +#include "llvm/ExecutionEngine/Interpreter.h"
    +#include "llvm/ExecutionEngine/JIT.h"
    +#include "llvm/LLVMContext.h"
    +#include "llvm/Module.h"
    +#include "llvm/ModuleProvider.h"
    +#include "llvm/PassManager.h"
    +#include "llvm/Analysis/Verifier.h"
    +#include "llvm/Target/TargetData.h"
    +#include "llvm/Target/TargetSelect.h"
    +#include "llvm/Transforms/Scalar.h"
    +#include "llvm/Support/IRBuilder.h"
    +#include <cstdio>
    +#include <string>
    +#include <map>
    +#include <vector>
    +using namespace llvm;
    +
    +//===----------------------------------------------------------------------===//
    +// Lexer
    +//===----------------------------------------------------------------------===//
    +
    +// The lexer returns tokens [0-255] if it is an unknown character, otherwise one
    +// of these for known things.
    +enum Token {
    +  tok_eof = -1,
    +
    +  // commands
    +  tok_def = -2, tok_extern = -3,
    +
    +  // primary
    +  tok_identifier = -4, tok_number = -5,
    +  
    +  // control
    +  tok_if = -6, tok_then = -7, tok_else = -8,
    +  tok_for = -9, tok_in = -10,
    +  
    +  // operators
    +  tok_binary = -11, tok_unary = -12,
    +  
    +  // var definition
    +  tok_var = -13
    +};
    +
    +static std::string IdentifierStr;  // Filled in if tok_identifier
    +static double NumVal;              // Filled in if tok_number
    +
    +/// gettok - Return the next token from standard input.
    +static int gettok() {
    +  static int LastChar = ' ';
    +
    +  // Skip any whitespace.
    +  while (isspace(LastChar))
    +    LastChar = getchar();
    +
    +  if (isalpha(LastChar)) { // identifier: [a-zA-Z][a-zA-Z0-9]*
    +    IdentifierStr = LastChar;
    +    while (isalnum((LastChar = getchar())))
    +      IdentifierStr += LastChar;
    +
    +    if (IdentifierStr == "def") return tok_def;
    +    if (IdentifierStr == "extern") return tok_extern;
    +    if (IdentifierStr == "if") return tok_if;
    +    if (IdentifierStr == "then") return tok_then;
    +    if (IdentifierStr == "else") return tok_else;
    +    if (IdentifierStr == "for") return tok_for;
    +    if (IdentifierStr == "in") return tok_in;
    +    if (IdentifierStr == "binary") return tok_binary;
    +    if (IdentifierStr == "unary") return tok_unary;
    +    if (IdentifierStr == "var") return tok_var;
    +    return tok_identifier;
    +  }
    +
    +  if (isdigit(LastChar) || LastChar == '.') {   // Number: [0-9.]+
    +    std::string NumStr;
    +    do {
    +      NumStr += LastChar;
    +      LastChar = getchar();
    +    } while (isdigit(LastChar) || LastChar == '.');
    +
    +    NumVal = strtod(NumStr.c_str(), 0);
    +    return tok_number;
    +  }
    +
    +  if (LastChar == '#') {
    +    // Comment until end of line.
    +    do LastChar = getchar();
    +    while (LastChar != EOF && LastChar != '\n' && LastChar != '\r');
    +    
    +    if (LastChar != EOF)
    +      return gettok();
    +  }
    +  
    +  // Check for end of file.  Don't eat the EOF.
    +  if (LastChar == EOF)
    +    return tok_eof;
    +
    +  // Otherwise, just return the character as its ascii value.
    +  int ThisChar = LastChar;
    +  LastChar = getchar();
    +  return ThisChar;
    +}
    +
    +//===----------------------------------------------------------------------===//
    +// Abstract Syntax Tree (aka Parse Tree)
    +//===----------------------------------------------------------------------===//
    +
    +/// ExprAST - Base class for all expression nodes.
    +class ExprAST {
    +public:
    +  virtual ~ExprAST() {}
    +  virtual Value *Codegen() = 0;
    +};
    +
    +/// NumberExprAST - Expression class for numeric literals like "1.0".
    +class NumberExprAST : public ExprAST {
    +  double Val;
    +public:
    +  NumberExprAST(double val) : Val(val) {}
    +  virtual Value *Codegen();
    +};
    +
    +/// VariableExprAST - Expression class for referencing a variable, like "a".
    +class VariableExprAST : public ExprAST {
    +  std::string Name;
    +public:
    +  VariableExprAST(const std::string &name) : Name(name) {}
    +  const std::string &getName() const { return Name; }
    +  virtual Value *Codegen();
    +};
    +
    +/// UnaryExprAST - Expression class for a unary operator.
    +class UnaryExprAST : public ExprAST {
    +  char Opcode;
    +  ExprAST *Operand;
    +public:
    +  UnaryExprAST(char opcode, ExprAST *operand) 
    +    : Opcode(opcode), Operand(operand) {}
    +  virtual Value *Codegen();
    +};
    +
    +/// BinaryExprAST - Expression class for a binary operator.
    +class BinaryExprAST : public ExprAST {
    +  char Op;
    +  ExprAST *LHS, *RHS;
    +public:
    +  BinaryExprAST(char op, ExprAST *lhs, ExprAST *rhs) 
    +    : Op(op), LHS(lhs), RHS(rhs) {}
    +  virtual Value *Codegen();
    +};
    +
    +/// CallExprAST - Expression class for function calls.
    +class CallExprAST : public ExprAST {
    +  std::string Callee;
    +  std::vector<ExprAST*> Args;
    +public:
    +  CallExprAST(const std::string &callee, std::vector<ExprAST*> &args)
    +    : Callee(callee), Args(args) {}
    +  virtual Value *Codegen();
    +};
    +
    +/// IfExprAST - Expression class for if/then/else.
    +class IfExprAST : public ExprAST {
    +  ExprAST *Cond, *Then, *Else;
    +public:
    +  IfExprAST(ExprAST *cond, ExprAST *then, ExprAST *_else)
    +  : Cond(cond), Then(then), Else(_else) {}
    +  virtual Value *Codegen();
    +};
    +
    +/// ForExprAST - Expression class for for/in.
    +class ForExprAST : public ExprAST {
    +  std::string VarName;
    +  ExprAST *Start, *End, *Step, *Body;
    +public:
    +  ForExprAST(const std::string &varname, ExprAST *start, ExprAST *end,
    +             ExprAST *step, ExprAST *body)
    +    : VarName(varname), Start(start), End(end), Step(step), Body(body) {}
    +  virtual Value *Codegen();
    +};
    +
    +/// VarExprAST - Expression class for var/in
    +class VarExprAST : public ExprAST {
    +  std::vector<std::pair<std::string, ExprAST*> > VarNames;
    +  ExprAST *Body;
    +public:
    +  VarExprAST(const std::vector<std::pair<std::string, ExprAST*> > &varnames,
    +             ExprAST *body)
    +  : VarNames(varnames), Body(body) {}
    +  
    +  virtual Value *Codegen();
    +};
    +
    +/// PrototypeAST - This class represents the "prototype" for a function,
    +/// which captures its name, and its argument names (thus implicitly the number
    +/// of arguments the function takes), as well as if it is an operator.
    +class PrototypeAST {
    +  std::string Name;
    +  std::vector<std::string> Args;
    +  bool isOperator;
    +  unsigned Precedence;  // Precedence if a binary op.
    +public:
    +  PrototypeAST(const std::string &name, const std::vector<std::string> &args,
    +               bool isoperator = false, unsigned prec = 0)
    +  : Name(name), Args(args), isOperator(isoperator), Precedence(prec) {}
    +  
    +  bool isUnaryOp() const { return isOperator && Args.size() == 1; }
    +  bool isBinaryOp() const { return isOperator && Args.size() == 2; }
    +  
    +  char getOperatorName() const {
    +    assert(isUnaryOp() || isBinaryOp());
    +    return Name[Name.size()-1];
    +  }
    +  
    +  unsigned getBinaryPrecedence() const { return Precedence; }
    +  
    +  Function *Codegen();
    +  
    +  void CreateArgumentAllocas(Function *F);
    +};
    +
    +/// FunctionAST - This class represents a function definition itself.
    +class FunctionAST {
    +  PrototypeAST *Proto;
    +  ExprAST *Body;
    +public:
    +  FunctionAST(PrototypeAST *proto, ExprAST *body)
    +    : Proto(proto), Body(body) {}
    +  
    +  Function *Codegen();
    +};
    +
    +//===----------------------------------------------------------------------===//
    +// Parser
    +//===----------------------------------------------------------------------===//
    +
    +/// CurTok/getNextToken - Provide a simple token buffer.  CurTok is the current
    +/// token the parser is looking at.  getNextToken reads another token from the
    +/// lexer and updates CurTok with its results.
    +static int CurTok;
    +static int getNextToken() {
    +  return CurTok = gettok();
    +}
    +
    +/// BinopPrecedence - This holds the precedence for each binary operator that is
    +/// defined.
    +static std::map<char, int> BinopPrecedence;
    +
    +/// GetTokPrecedence - Get the precedence of the pending binary operator token.
    +static int GetTokPrecedence() {
    +  if (!isascii(CurTok))
    +    return -1;
    +  
    +  // Make sure it's a declared binop.
    +  int TokPrec = BinopPrecedence[CurTok];
    +  if (TokPrec <= 0) return -1;
    +  return TokPrec;
    +}
    +
    +/// Error* - These are little helper functions for error handling.
    +ExprAST *Error(const char *Str) { fprintf(stderr, "Error: %s\n", Str);return 0;}
    +PrototypeAST *ErrorP(const char *Str) { Error(Str); return 0; }
    +FunctionAST *ErrorF(const char *Str) { Error(Str); return 0; }
    +
    +static ExprAST *ParseExpression();
    +
    +/// identifierexpr
    +///   ::= identifier
    +///   ::= identifier '(' expression* ')'
    +static ExprAST *ParseIdentifierExpr() {
    +  std::string IdName = IdentifierStr;
    +  
    +  getNextToken();  // eat identifier.
    +  
    +  if (CurTok != '(') // Simple variable ref.
    +    return new VariableExprAST(IdName);
    +  
    +  // Call.
    +  getNextToken();  // eat (
    +  std::vector<ExprAST*> Args;
    +  if (CurTok != ')') {
    +    while (1) {
    +      ExprAST *Arg = ParseExpression();
    +      if (!Arg) return 0;
    +      Args.push_back(Arg);
    +
    +      if (CurTok == ')') break;
    +
    +      if (CurTok != ',')
    +        return Error("Expected ')' or ',' in argument list");
    +      getNextToken();
    +    }
    +  }
    +
    +  // Eat the ')'.
    +  getNextToken();
    +  
    +  return new CallExprAST(IdName, Args);
    +}
    +
    +/// numberexpr ::= number
    +static ExprAST *ParseNumberExpr() {
    +  ExprAST *Result = new NumberExprAST(NumVal);
    +  getNextToken(); // consume the number
    +  return Result;
    +}
    +
    +/// parenexpr ::= '(' expression ')'
    +static ExprAST *ParseParenExpr() {
    +  getNextToken();  // eat (.
    +  ExprAST *V = ParseExpression();
    +  if (!V) return 0;
    +  
    +  if (CurTok != ')')
    +    return Error("expected ')'");
    +  getNextToken();  // eat ).
    +  return V;
    +}
    +
    +/// ifexpr ::= 'if' expression 'then' expression 'else' expression
    +static ExprAST *ParseIfExpr() {
    +  getNextToken();  // eat the if.
    +  
    +  // condition.
    +  ExprAST *Cond = ParseExpression();
    +  if (!Cond) return 0;
    +  
    +  if (CurTok != tok_then)
    +    return Error("expected then");
    +  getNextToken();  // eat the then
    +  
    +  ExprAST *Then = ParseExpression();
    +  if (Then == 0) return 0;
    +  
    +  if (CurTok != tok_else)
    +    return Error("expected else");
    +  
    +  getNextToken();
    +  
    +  ExprAST *Else = ParseExpression();
    +  if (!Else) return 0;
    +  
    +  return new IfExprAST(Cond, Then, Else);
    +}
    +
    +/// forexpr ::= 'for' identifier '=' expr ',' expr (',' expr)? 'in' expression
    +static ExprAST *ParseForExpr() {
    +  getNextToken();  // eat the for.
    +
    +  if (CurTok != tok_identifier)
    +    return Error("expected identifier after for");
    +  
    +  std::string IdName = IdentifierStr;
    +  getNextToken();  // eat identifier.
    +  
    +  if (CurTok != '=')
    +    return Error("expected '=' after for");
    +  getNextToken();  // eat '='.
    +  
    +  
    +  ExprAST *Start = ParseExpression();
    +  if (Start == 0) return 0;
    +  if (CurTok != ',')
    +    return Error("expected ',' after for start value");
    +  getNextToken();
    +  
    +  ExprAST *End = ParseExpression();
    +  if (End == 0) return 0;
    +  
    +  // The step value is optional.
    +  ExprAST *Step = 0;
    +  if (CurTok == ',') {
    +    getNextToken();
    +    Step = ParseExpression();
    +    if (Step == 0) return 0;
    +  }
    +  
    +  if (CurTok != tok_in)
    +    return Error("expected 'in' after for");
    +  getNextToken();  // eat 'in'.
    +  
    +  ExprAST *Body = ParseExpression();
    +  if (Body == 0) return 0;
    +
    +  return new ForExprAST(IdName, Start, End, Step, Body);
    +}
    +
    +/// varexpr ::= 'var' identifier ('=' expression)? 
    +//                    (',' identifier ('=' expression)?)* 'in' expression
    +static ExprAST *ParseVarExpr() {
    +  getNextToken();  // eat the var.
    +
    +  std::vector<std::pair<std::string, ExprAST*> > VarNames;
    +
    +  // At least one variable name is required.
    +  if (CurTok != tok_identifier)
    +    return Error("expected identifier after var");
    +  
    +  while (1) {
    +    std::string Name = IdentifierStr;
    +    getNextToken();  // eat identifier.
    +
    +    // Read the optional initializer.
    +    ExprAST *Init = 0;
    +    if (CurTok == '=') {
    +      getNextToken(); // eat the '='.
    +      
    +      Init = ParseExpression();
    +      if (Init == 0) return 0;
    +    }
    +    
    +    VarNames.push_back(std::make_pair(Name, Init));
    +    
    +    // End of var list, exit loop.
    +    if (CurTok != ',') break;
    +    getNextToken(); // eat the ','.
    +    
    +    if (CurTok != tok_identifier)
    +      return Error("expected identifier list after var");
    +  }
    +  
    +  // At this point, we have to have 'in'.
    +  if (CurTok != tok_in)
    +    return Error("expected 'in' keyword after 'var'");
    +  getNextToken();  // eat 'in'.
    +  
    +  ExprAST *Body = ParseExpression();
    +  if (Body == 0) return 0;
    +  
    +  return new VarExprAST(VarNames, Body);
    +}
    +
    +/// primary
    +///   ::= identifierexpr
    +///   ::= numberexpr
    +///   ::= parenexpr
    +///   ::= ifexpr
    +///   ::= forexpr
    +///   ::= varexpr
    +static ExprAST *ParsePrimary() {
    +  switch (CurTok) {
    +  default: return Error("unknown token when expecting an expression");
    +  case tok_identifier: return ParseIdentifierExpr();
    +  case tok_number:     return ParseNumberExpr();
    +  case '(':            return ParseParenExpr();
    +  case tok_if:         return ParseIfExpr();
    +  case tok_for:        return ParseForExpr();
    +  case tok_var:        return ParseVarExpr();
    +  }
    +}
    +
    +/// unary
    +///   ::= primary
    +///   ::= '!' unary
    +static ExprAST *ParseUnary() {
    +  // If the current token is not an operator, it must be a primary expr.
    +  if (!isascii(CurTok) || CurTok == '(' || CurTok == ',')
    +    return ParsePrimary();
    +  
    +  // If this is a unary operator, read it.
    +  int Opc = CurTok;
    +  getNextToken();
    +  if (ExprAST *Operand = ParseUnary())
    +    return new UnaryExprAST(Opc, Operand);
    +  return 0;
    +}
    +
    +/// binoprhs
    +///   ::= ('+' unary)*
    +static ExprAST *ParseBinOpRHS(int ExprPrec, ExprAST *LHS) {
    +  // If this is a binop, find its precedence.
    +  while (1) {
    +    int TokPrec = GetTokPrecedence();
    +    
    +    // If this is a binop that binds at least as tightly as the current binop,
    +    // consume it, otherwise we are done.
    +    if (TokPrec < ExprPrec)
    +      return LHS;
    +    
    +    // Okay, we know this is a binop.
    +    int BinOp = CurTok;
    +    getNextToken();  // eat binop
    +    
    +    // Parse the unary expression after the binary operator.
    +    ExprAST *RHS = ParseUnary();
    +    if (!RHS) return 0;
    +    
    +    // If BinOp binds less tightly with RHS than the operator after RHS, let
    +    // the pending operator take RHS as its LHS.
    +    int NextPrec = GetTokPrecedence();
    +    if (TokPrec < NextPrec) {
    +      RHS = ParseBinOpRHS(TokPrec+1, RHS);
    +      if (RHS == 0) return 0;
    +    }
    +    
    +    // Merge LHS/RHS.
    +    LHS = new BinaryExprAST(BinOp, LHS, RHS);
    +  }
    +}
    +
    +/// expression
    +///   ::= unary binoprhs
    +///
    +static ExprAST *ParseExpression() {
    +  ExprAST *LHS = ParseUnary();
    +  if (!LHS) return 0;
    +  
    +  return ParseBinOpRHS(0, LHS);
    +}
    +
    +/// prototype
    +///   ::= id '(' id* ')'
    +///   ::= binary LETTER number? (id, id)
    +///   ::= unary LETTER (id)
    +static PrototypeAST *ParsePrototype() {
    +  std::string FnName;
    +  
    +  unsigned Kind = 0; // 0 = identifier, 1 = unary, 2 = binary.
    +  unsigned BinaryPrecedence = 30;
    +  
    +  switch (CurTok) {
    +  default:
    +    return ErrorP("Expected function name in prototype");
    +  case tok_identifier:
    +    FnName = IdentifierStr;
    +    Kind = 0;
    +    getNextToken();
    +    break;
    +  case tok_unary:
    +    getNextToken();
    +    if (!isascii(CurTok))
    +      return ErrorP("Expected unary operator");
    +    FnName = "unary";
    +    FnName += (char)CurTok;
    +    Kind = 1;
    +    getNextToken();
    +    break;
    +  case tok_binary:
    +    getNextToken();
    +    if (!isascii(CurTok))
    +      return ErrorP("Expected binary operator");
    +    FnName = "binary";
    +    FnName += (char)CurTok;
    +    Kind = 2;
    +    getNextToken();
    +    
    +    // Read the precedence if present.
    +    if (CurTok == tok_number) {
    +      if (NumVal < 1 || NumVal > 100)
    +        return ErrorP("Invalid precedecnce: must be 1..100");
    +      BinaryPrecedence = (unsigned)NumVal;
    +      getNextToken();
    +    }
    +    break;
    +  }
    +  
    +  if (CurTok != '(')
    +    return ErrorP("Expected '(' in prototype");
    +  
    +  std::vector<std::string> ArgNames;
    +  while (getNextToken() == tok_identifier)
    +    ArgNames.push_back(IdentifierStr);
    +  if (CurTok != ')')
    +    return ErrorP("Expected ')' in prototype");
    +  
    +  // success.
    +  getNextToken();  // eat ')'.
    +  
    +  // Verify right number of names for operator.
    +  if (Kind && ArgNames.size() != Kind)
    +    return ErrorP("Invalid number of operands for operator");
    +  
    +  return new PrototypeAST(FnName, ArgNames, Kind != 0, BinaryPrecedence);
    +}
    +
    +/// definition ::= 'def' prototype expression
    +static FunctionAST *ParseDefinition() {
    +  getNextToken();  // eat def.
    +  PrototypeAST *Proto = ParsePrototype();
    +  if (Proto == 0) return 0;
    +
    +  if (ExprAST *E = ParseExpression())
    +    return new FunctionAST(Proto, E);
    +  return 0;
    +}
    +
    +/// toplevelexpr ::= expression
    +static FunctionAST *ParseTopLevelExpr() {
    +  if (ExprAST *E = ParseExpression()) {
    +    // Make an anonymous proto.
    +    PrototypeAST *Proto = new PrototypeAST("", std::vector<std::string>());
    +    return new FunctionAST(Proto, E);
    +  }
    +  return 0;
    +}
    +
    +/// external ::= 'extern' prototype
    +static PrototypeAST *ParseExtern() {
    +  getNextToken();  // eat extern.
    +  return ParsePrototype();
    +}
    +
    +//===----------------------------------------------------------------------===//
    +// Code Generation
    +//===----------------------------------------------------------------------===//
    +
    +static Module *TheModule;
    +static IRBuilder<> Builder(getGlobalContext());
    +static std::map<std::string, AllocaInst*> NamedValues;
    +static FunctionPassManager *TheFPM;
    +
    +Value *ErrorV(const char *Str) { Error(Str); return 0; }
    +
    +/// CreateEntryBlockAlloca - Create an alloca instruction in the entry block of
    +/// the function.  This is used for mutable variables etc.
    +static AllocaInst *CreateEntryBlockAlloca(Function *TheFunction,
    +                                          const std::string &VarName) {
    +  IRBuilder<> TmpB(&TheFunction->getEntryBlock(),
    +                 TheFunction->getEntryBlock().begin());
    +  return TmpB.CreateAlloca(Type::getDoubleTy(getGlobalContext()), 0,
    +                           VarName.c_str());
    +}
    +
    +Value *NumberExprAST::Codegen() {
    +  return ConstantFP::get(getGlobalContext(), APFloat(Val));
    +}
    +
    +Value *VariableExprAST::Codegen() {
    +  // Look this variable up in the function.
    +  Value *V = NamedValues[Name];
    +  if (V == 0) return ErrorV("Unknown variable name");
    +
    +  // Load the value.
    +  return Builder.CreateLoad(V, Name.c_str());
    +}
    +
    +Value *UnaryExprAST::Codegen() {
    +  Value *OperandV = Operand->Codegen();
    +  if (OperandV == 0) return 0;
    +  
    +  Function *F = TheModule->getFunction(std::string("unary")+Opcode);
    +  if (F == 0)
    +    return ErrorV("Unknown unary operator");
    +  
    +  return Builder.CreateCall(F, OperandV, "unop");
    +}
    +
    +Value *BinaryExprAST::Codegen() {
    +  // Special case '=' because we don't want to emit the LHS as an expression.
    +  if (Op == '=') {
    +    // Assignment requires the LHS to be an identifier.
    +    VariableExprAST *LHSE = dynamic_cast<VariableExprAST*>(LHS);
    +    if (!LHSE)
    +      return ErrorV("destination of '=' must be a variable");
    +    // Codegen the RHS.
    +    Value *Val = RHS->Codegen();
    +    if (Val == 0) return 0;
    +
    +    // Look up the name.
    +    Value *Variable = NamedValues[LHSE->getName()];
    +    if (Variable == 0) return ErrorV("Unknown variable name");
    +
    +    Builder.CreateStore(Val, Variable);
    +    return Val;
    +  }
    +  
    +  Value *L = LHS->Codegen();
    +  Value *R = RHS->Codegen();
    +  if (L == 0 || R == 0) return 0;
    +  
    +  switch (Op) {
    +  case '+': return Builder.CreateAdd(L, R, "addtmp");
    +  case '-': return Builder.CreateSub(L, R, "subtmp");
    +  case '*': return Builder.CreateMul(L, R, "multmp");
    +  case '<':
    +    L = Builder.CreateFCmpULT(L, R, "cmptmp");
    +    // Convert bool 0/1 to double 0.0 or 1.0
    +    return Builder.CreateUIToFP(L, Type::getDoubleTy(getGlobalContext()),
    +                                "booltmp");
    +  default: break;
    +  }
    +  
    +  // If it wasn't a builtin binary operator, it must be a user defined one. Emit
    +  // a call to it.
    +  Function *F = TheModule->getFunction(std::string("binary")+Op);
    +  assert(F && "binary operator not found!");
    +  
    +  Value *Ops[] = { L, R };
    +  return Builder.CreateCall(F, Ops, Ops+2, "binop");
    +}
    +
    +Value *CallExprAST::Codegen() {
    +  // Look up the name in the global module table.
    +  Function *CalleeF = TheModule->getFunction(Callee);
    +  if (CalleeF == 0)
    +    return ErrorV("Unknown function referenced");
    +  
    +  // If argument mismatch error.
    +  if (CalleeF->arg_size() != Args.size())
    +    return ErrorV("Incorrect # arguments passed");
    +
    +  std::vector<Value*> ArgsV;
    +  for (unsigned i = 0, e = Args.size(); i != e; ++i) {
    +    ArgsV.push_back(Args[i]->Codegen());
    +    if (ArgsV.back() == 0) return 0;
    +  }
    +  
    +  return Builder.CreateCall(CalleeF, ArgsV.begin(), ArgsV.end(), "calltmp");
    +}
    +
    +Value *IfExprAST::Codegen() {
    +  Value *CondV = Cond->Codegen();
    +  if (CondV == 0) return 0;
    +  
    +  // Convert condition to a bool by comparing equal to 0.0.
    +  CondV = Builder.CreateFCmpONE(CondV, 
    +                              ConstantFP::get(getGlobalContext(), APFloat(0.0)),
    +                                "ifcond");
    +  
    +  Function *TheFunction = Builder.GetInsertBlock()->getParent();
    +  
    +  // Create blocks for the then and else cases.  Insert the 'then' block at the
    +  // end of the function.
    +  BasicBlock *ThenBB = BasicBlock::Create(getGlobalContext(), "then", TheFunction);
    +  BasicBlock *ElseBB = BasicBlock::Create(getGlobalContext(), "else");
    +  BasicBlock *MergeBB = BasicBlock::Create(getGlobalContext(), "ifcont");
    +  
    +  Builder.CreateCondBr(CondV, ThenBB, ElseBB);
    +  
    +  // Emit then value.
    +  Builder.SetInsertPoint(ThenBB);
    +  
    +  Value *ThenV = Then->Codegen();
    +  if (ThenV == 0) return 0;
    +  
    +  Builder.CreateBr(MergeBB);
    +  // Codegen of 'Then' can change the current block, update ThenBB for the PHI.
    +  ThenBB = Builder.GetInsertBlock();
    +  
    +  // Emit else block.
    +  TheFunction->getBasicBlockList().push_back(ElseBB);
    +  Builder.SetInsertPoint(ElseBB);
    +  
    +  Value *ElseV = Else->Codegen();
    +  if (ElseV == 0) return 0;
    +  
    +  Builder.CreateBr(MergeBB);
    +  // Codegen of 'Else' can change the current block, update ElseBB for the PHI.
    +  ElseBB = Builder.GetInsertBlock();
    +  
    +  // Emit merge block.
    +  TheFunction->getBasicBlockList().push_back(MergeBB);
    +  Builder.SetInsertPoint(MergeBB);
    +  PHINode *PN = Builder.CreatePHI(Type::getDoubleTy(getGlobalContext()),
    +                                  "iftmp");
    +  
    +  PN->addIncoming(ThenV, ThenBB);
    +  PN->addIncoming(ElseV, ElseBB);
    +  return PN;
    +}
    +
    +Value *ForExprAST::Codegen() {
    +  // Output this as:
    +  //   var = alloca double
    +  //   ...
    +  //   start = startexpr
    +  //   store start -> var
    +  //   goto loop
    +  // loop: 
    +  //   ...
    +  //   bodyexpr
    +  //   ...
    +  // loopend:
    +  //   step = stepexpr
    +  //   endcond = endexpr
    +  //
    +  //   curvar = load var
    +  //   nextvar = curvar + step
    +  //   store nextvar -> var
    +  //   br endcond, loop, endloop
    +  // outloop:
    +  
    +  Function *TheFunction = Builder.GetInsertBlock()->getParent();
    +
    +  // Create an alloca for the variable in the entry block.
    +  AllocaInst *Alloca = CreateEntryBlockAlloca(TheFunction, VarName);
    +  
    +  // Emit the start code first, without 'variable' in scope.
    +  Value *StartVal = Start->Codegen();
    +  if (StartVal == 0) return 0;
    +  
    +  // Store the value into the alloca.
    +  Builder.CreateStore(StartVal, Alloca);
    +  
    +  // Make the new basic block for the loop header, inserting after current
    +  // block.
    +  BasicBlock *LoopBB = BasicBlock::Create(getGlobalContext(), "loop", TheFunction);
    +  
    +  // Insert an explicit fall through from the current block to the LoopBB.
    +  Builder.CreateBr(LoopBB);
    +
    +  // Start insertion in LoopBB.
    +  Builder.SetInsertPoint(LoopBB);
    +  
    +  // Within the loop, the variable is defined equal to the PHI node.  If it
    +  // shadows an existing variable, we have to restore it, so save it now.
    +  AllocaInst *OldVal = NamedValues[VarName];
    +  NamedValues[VarName] = Alloca;
    +  
    +  // Emit the body of the loop.  This, like any other expr, can change the
    +  // current BB.  Note that we ignore the value computed by the body, but don't
    +  // allow an error.
    +  if (Body->Codegen() == 0)
    +    return 0;
    +  
    +  // Emit the step value.
    +  Value *StepVal;
    +  if (Step) {
    +    StepVal = Step->Codegen();
    +    if (StepVal == 0) return 0;
    +  } else {
    +    // If not specified, use 1.0.
    +    StepVal = ConstantFP::get(getGlobalContext(), APFloat(1.0));
    +  }
    +  
    +  // Compute the end condition.
    +  Value *EndCond = End->Codegen();
    +  if (EndCond == 0) return EndCond;
    +  
    +  // Reload, increment, and restore the alloca.  This handles the case where
    +  // the body of the loop mutates the variable.
    +  Value *CurVar = Builder.CreateLoad(Alloca, VarName.c_str());
    +  Value *NextVar = Builder.CreateAdd(CurVar, StepVal, "nextvar");
    +  Builder.CreateStore(NextVar, Alloca);
    +  
    +  // Convert condition to a bool by comparing equal to 0.0.
    +  EndCond = Builder.CreateFCmpONE(EndCond, 
    +                              ConstantFP::get(getGlobalContext(), APFloat(0.0)),
    +                                  "loopcond");
    +  
    +  // Create the "after loop" block and insert it.
    +  BasicBlock *AfterBB = BasicBlock::Create(getGlobalContext(), "afterloop", TheFunction);
    +  
    +  // Insert the conditional branch into the end of LoopEndBB.
    +  Builder.CreateCondBr(EndCond, LoopBB, AfterBB);
    +  
    +  // Any new code will be inserted in AfterBB.
    +  Builder.SetInsertPoint(AfterBB);
    +  
    +  // Restore the unshadowed variable.
    +  if (OldVal)
    +    NamedValues[VarName] = OldVal;
    +  else
    +    NamedValues.erase(VarName);
    +
    +  
    +  // for expr always returns 0.0.
    +  return Constant::getNullValue(Type::getDoubleTy(getGlobalContext()));
    +}
    +
    +Value *VarExprAST::Codegen() {
    +  std::vector<AllocaInst *> OldBindings;
    +  
    +  Function *TheFunction = Builder.GetInsertBlock()->getParent();
    +
    +  // Register all variables and emit their initializer.
    +  for (unsigned i = 0, e = VarNames.size(); i != e; ++i) {
    +    const std::string &VarName = VarNames[i].first;
    +    ExprAST *Init = VarNames[i].second;
    +    
    +    // Emit the initializer before adding the variable to scope, this prevents
    +    // the initializer from referencing the variable itself, and permits stuff
    +    // like this:
    +    //  var a = 1 in
    +    //    var a = a in ...   # refers to outer 'a'.
    +    Value *InitVal;
    +    if (Init) {
    +      InitVal = Init->Codegen();
    +      if (InitVal == 0) return 0;
    +    } else { // If not specified, use 0.0.
    +      InitVal = ConstantFP::get(getGlobalContext(), APFloat(0.0));
    +    }
    +    
    +    AllocaInst *Alloca = CreateEntryBlockAlloca(TheFunction, VarName);
    +    Builder.CreateStore(InitVal, Alloca);
    +
    +    // Remember the old variable binding so that we can restore the binding when
    +    // we unrecurse.
    +    OldBindings.push_back(NamedValues[VarName]);
    +    
    +    // Remember this binding.
    +    NamedValues[VarName] = Alloca;
    +  }
    +  
    +  // Codegen the body, now that all vars are in scope.
    +  Value *BodyVal = Body->Codegen();
    +  if (BodyVal == 0) return 0;
    +  
    +  // Pop all our variables from scope.
    +  for (unsigned i = 0, e = VarNames.size(); i != e; ++i)
    +    NamedValues[VarNames[i].first] = OldBindings[i];
    +
    +  // Return the body computation.
    +  return BodyVal;
    +}
    +
    +Function *PrototypeAST::Codegen() {
    +  // Make the function type:  double(double,double) etc.
    +  std::vector<const Type*> Doubles(Args.size(),
    +                                   Type::getDoubleTy(getGlobalContext()));
    +  FunctionType *FT = FunctionType::get(Type::getDoubleTy(getGlobalContext()),
    +                                       Doubles, false);
    +  
    +  Function *F = Function::Create(FT, Function::ExternalLinkage, Name, TheModule);
    +  
    +  // If F conflicted, there was already something named 'Name'.  If it has a
    +  // body, don't allow redefinition or reextern.
    +  if (F->getName() != Name) {
    +    // Delete the one we just made and get the existing one.
    +    F->eraseFromParent();
    +    F = TheModule->getFunction(Name);
    +    
    +    // If F already has a body, reject this.
    +    if (!F->empty()) {
    +      ErrorF("redefinition of function");
    +      return 0;
    +    }
    +    
    +    // If F took a different number of args, reject.
    +    if (F->arg_size() != Args.size()) {
    +      ErrorF("redefinition of function with different # args");
    +      return 0;
    +    }
    +  }
    +  
    +  // Set names for all arguments.
    +  unsigned Idx = 0;
    +  for (Function::arg_iterator AI = F->arg_begin(); Idx != Args.size();
    +       ++AI, ++Idx)
    +    AI->setName(Args[Idx]);
    +    
    +  return F;
    +}
    +
    +/// CreateArgumentAllocas - Create an alloca for each argument and register the
    +/// argument in the symbol table so that references to it will succeed.
    +void PrototypeAST::CreateArgumentAllocas(Function *F) {
    +  Function::arg_iterator AI = F->arg_begin();
    +  for (unsigned Idx = 0, e = Args.size(); Idx != e; ++Idx, ++AI) {
    +    // Create an alloca for this variable.
    +    AllocaInst *Alloca = CreateEntryBlockAlloca(F, Args[Idx]);
    +
    +    // Store the initial value into the alloca.
    +    Builder.CreateStore(AI, Alloca);
    +
    +    // Add arguments to variable symbol table.
    +    NamedValues[Args[Idx]] = Alloca;
    +  }
    +}
    +
    +Function *FunctionAST::Codegen() {
    +  NamedValues.clear();
    +  
    +  Function *TheFunction = Proto->Codegen();
    +  if (TheFunction == 0)
    +    return 0;
    +  
    +  // If this is an operator, install it.
    +  if (Proto->isBinaryOp())
    +    BinopPrecedence[Proto->getOperatorName()] = Proto->getBinaryPrecedence();
    +  
    +  // Create a new basic block to start insertion into.
    +  BasicBlock *BB = BasicBlock::Create(getGlobalContext(), "entry", TheFunction);
    +  Builder.SetInsertPoint(BB);
    +  
    +  // Add all arguments to the symbol table and create their allocas.
    +  Proto->CreateArgumentAllocas(TheFunction);
    +
    +  if (Value *RetVal = Body->Codegen()) {
    +    // Finish off the function.
    +    Builder.CreateRet(RetVal);
    +
    +    // Validate the generated code, checking for consistency.
    +    verifyFunction(*TheFunction);
    +
    +    // Optimize the function.
    +    TheFPM->run(*TheFunction);
    +    
    +    return TheFunction;
    +  }
    +  
    +  // Error reading body, remove function.
    +  TheFunction->eraseFromParent();
    +
    +  if (Proto->isBinaryOp())
    +    BinopPrecedence.erase(Proto->getOperatorName());
    +  return 0;
    +}
    +
    +//===----------------------------------------------------------------------===//
    +// Top-Level parsing and JIT Driver
    +//===----------------------------------------------------------------------===//
    +
    +static ExecutionEngine *TheExecutionEngine;
    +
    +static void HandleDefinition() {
    +  if (FunctionAST *F = ParseDefinition()) {
    +    if (Function *LF = F->Codegen()) {
    +      fprintf(stderr, "Read function definition:");
    +      LF->dump();
    +    }
    +  } else {
    +    // Skip token for error recovery.
    +    getNextToken();
    +  }
    +}
    +
    +static void HandleExtern() {
    +  if (PrototypeAST *P = ParseExtern()) {
    +    if (Function *F = P->Codegen()) {
    +      fprintf(stderr, "Read extern: ");
    +      F->dump();
    +    }
    +  } else {
    +    // Skip token for error recovery.
    +    getNextToken();
    +  }
    +}
    +
    +static void HandleTopLevelExpression() {
    +  // Evaluate a top-level expression into an anonymous function.
    +  if (FunctionAST *F = ParseTopLevelExpr()) {
    +    if (Function *LF = F->Codegen()) {
    +      // JIT the function, returning a function pointer.
    +      void *FPtr = TheExecutionEngine->getPointerToFunction(LF);
    +      
    +      // Cast it to the right type (takes no arguments, returns a double) so we
    +      // can call it as a native function.
    +      double (*FP)() = (double (*)())(intptr_t)FPtr;
    +      fprintf(stderr, "Evaluated to %f\n", FP());
    +    }
    +  } else {
    +    // Skip token for error recovery.
    +    getNextToken();
    +  }
    +}
    +
    +/// top ::= definition | external | expression | ';'
    +static void MainLoop() {
    +  while (1) {
    +    fprintf(stderr, "ready> ");
    +    switch (CurTok) {
    +    case tok_eof:    return;
    +    case ';':        getNextToken(); break;  // ignore top-level semicolons.
    +    case tok_def:    HandleDefinition(); break;
    +    case tok_extern: HandleExtern(); break;
    +    default:         HandleTopLevelExpression(); break;
    +    }
    +  }
    +}
    +
    +//===----------------------------------------------------------------------===//
    +// "Library" functions that can be "extern'd" from user code.
    +//===----------------------------------------------------------------------===//
    +
    +/// putchard - putchar that takes a double and returns 0.
    +extern "C" 
    +double putchard(double X) {
    +  putchar((char)X);
    +  return 0;
    +}
    +
    +/// printd - printf that takes a double prints it as "%f\n", returning 0.
    +extern "C" 
    +double printd(double X) {
    +  printf("%f\n", X);
    +  return 0;
    +}
    +
    +//===----------------------------------------------------------------------===//
    +// Main driver code.
    +//===----------------------------------------------------------------------===//
    +
    +int main() {
    +  InitializeNativeTarget();
    +  LLVMContext &Context = getGlobalContext();
    +
    +  // Install standard binary operators.
    +  // 1 is lowest precedence.
    +  BinopPrecedence['='] = 2;
    +  BinopPrecedence['<'] = 10;
    +  BinopPrecedence['+'] = 20;
    +  BinopPrecedence['-'] = 20;
    +  BinopPrecedence['*'] = 40;  // highest.
    +
    +  // Prime the first token.
    +  fprintf(stderr, "ready> ");
    +  getNextToken();
    +
    +  // Make the module, which holds all the code.
    +  TheModule = new Module("my cool jit", Context);
    +
    +  ExistingModuleProvider *OurModuleProvider =
    +      new ExistingModuleProvider(TheModule);
    +
    +  // Create the JIT.  This takes ownership of the module and module provider.
    +  TheExecutionEngine = EngineBuilder(OurModuleProvider).create();
    +
    +  FunctionPassManager OurFPM(OurModuleProvider);
    +
    +  // Set up the optimizer pipeline.  Start with registering info about how the
    +  // target lays out data structures.
    +  OurFPM.add(new TargetData(*TheExecutionEngine->getTargetData()));
    +  // Promote allocas to registers.
    +  OurFPM.add(createPromoteMemoryToRegisterPass());
    +  // Do simple "peephole" optimizations and bit-twiddling optzns.
    +  OurFPM.add(createInstructionCombiningPass());
    +  // Reassociate expressions.
    +  OurFPM.add(createReassociatePass());
    +  // Eliminate Common SubExpressions.
    +  OurFPM.add(createGVNPass());
    +  // Simplify the control flow graph (deleting unreachable blocks, etc).
    +  OurFPM.add(createCFGSimplificationPass());
    +
    +  OurFPM.doInitialization();
    +
    +  // Set the global so the code gen can use this.
    +  TheFPM = &OurFPM;
    +
    +  // Run the main "interpreter loop" now.
    +  MainLoop();
    +
    +  TheFPM = 0;
    +
    +  // Print out all of the generated code.
    +  TheModule->dump();
    +
    +  return 0;
    +}
    +
    +
    + +Next: Conclusion and other useful LLVM tidbits +
    + + +
    +
    + Valid CSS! + Valid HTML 4.01! + + Chris Lattner
    + The LLVM Compiler Infrastructure
    + Last modified: $Date: 2007-10-17 11:05:13 -0700 (Wed, 17 Oct 2007) $ +
    + + diff --git a/libclamav/c++/llvm/docs/tutorial/LangImpl8.html b/libclamav/c++/llvm/docs/tutorial/LangImpl8.html new file mode 100644 index 000000000..855b8f369 --- /dev/null +++ b/libclamav/c++/llvm/docs/tutorial/LangImpl8.html @@ -0,0 +1,365 @@ + + + + + Kaleidoscope: Conclusion and other useful LLVM tidbits + + + + + + + +
    Kaleidoscope: Conclusion and other useful LLVM + tidbits
    + + + + +
    +

    Written by Chris Lattner

    +
    + + + + + +
    + +

    Welcome to the the final chapter of the "Implementing a +language with LLVM" tutorial. In the course of this tutorial, we have grown +our little Kaleidoscope language from being a useless toy, to being a +semi-interesting (but probably still useless) toy. :)

    + +

    It is interesting to see how far we've come, and how little code it has +taken. We built the entire lexer, parser, AST, code generator, and an +interactive run-loop (with a JIT!) by-hand in under 700 lines of +(non-comment/non-blank) code.

    + +

    Our little language supports a couple of interesting features: it supports +user defined binary and unary operators, it uses JIT compilation for immediate +evaluation, and it supports a few control flow constructs with SSA construction. +

    + +

    Part of the idea of this tutorial was to show you how easy and fun it can be +to define, build, and play with languages. Building a compiler need not be a +scary or mystical process! Now that you've seen some of the basics, I strongly +encourage you to take the code and hack on it. For example, try adding:

    + +
      +
    • global variables - While global variables have questional value in +modern software engineering, they are often useful when putting together quick +little hacks like the Kaleidoscope compiler itself. Fortunately, our current +setup makes it very easy to add global variables: just have value lookup check +to see if an unresolved variable is in the global variable symbol table before +rejecting it. To create a new global variable, make an instance of the LLVM +GlobalVariable class.
    • + +
    • typed variables - Kaleidoscope currently only supports variables of +type double. This gives the language a very nice elegance, because only +supporting one type means that you never have to specify types. Different +languages have different ways of handling this. The easiest way is to require +the user to specify types for every variable definition, and record the type +of the variable in the symbol table along with its Value*.
    • + +
    • arrays, structs, vectors, etc - Once you add types, you can start +extending the type system in all sorts of interesting ways. Simple arrays are +very easy and are quite useful for many different applications. Adding them is +mostly an exercise in learning how the LLVM getelementptr instruction works: it +is so nifty/unconventional, it has its own FAQ! If you add support +for recursive types (e.g. linked lists), make sure to read the section in the LLVM +Programmer's Manual that describes how to construct them.
    • + +
    • standard runtime - Our current language allows the user to access +arbitrary external functions, and we use it for things like "printd" and +"putchard". As you extend the language to add higher-level constructs, often +these constructs make the most sense if they are lowered to calls into a +language-supplied runtime. For example, if you add hash tables to the language, +it would probably make sense to add the routines to a runtime, instead of +inlining them all the way.
    • + +
    • memory management - Currently we can only access the stack in +Kaleidoscope. It would also be useful to be able to allocate heap memory, +either with calls to the standard libc malloc/free interface or with a garbage +collector. If you would like to use garbage collection, note that LLVM fully +supports Accurate Garbage Collection +including algorithms that move objects and need to scan/update the stack.
    • + +
    • debugger support - LLVM supports generation of DWARF Debug info which is understood by +common debuggers like GDB. Adding support for debug info is fairly +straightforward. The best way to understand it is to compile some C/C++ code +with "llvm-gcc -g -O0" and taking a look at what it produces.
    • + +
    • exception handling support - LLVM supports generation of zero cost exceptions which interoperate +with code compiled in other languages. You could also generate code by +implicitly making every function return an error value and checking it. You +could also make explicit use of setjmp/longjmp. There are many different ways +to go here.
    • + +
    • object orientation, generics, database access, complex numbers, +geometric programming, ... - Really, there is +no end of crazy features that you can add to the language.
    • + +
    • unusual domains - We've been talking about applying LLVM to a domain +that many people are interested in: building a compiler for a specific language. +However, there are many other domains that can use compiler technology that are +not typically considered. For example, LLVM has been used to implement OpenGL +graphics acceleration, translate C++ code to ActionScript, and many other +cute and clever things. Maybe you will be the first to JIT compile a regular +expression interpreter into native code with LLVM?
    • + +
    + +

    +Have fun - try doing something crazy and unusual. Building a language like +everyone else always has, is much less fun than trying something a little crazy +or off the wall and seeing how it turns out. If you get stuck or want to talk +about it, feel free to email the llvmdev mailing +list: it has lots of people who are interested in languages and are often +willing to help out. +

    + +

    Before we end this tutorial, I want to talk about some "tips and tricks" for generating +LLVM IR. These are some of the more subtle things that may not be obvious, but +are very useful if you want to take advantage of LLVM's capabilities.

    + +
    + + + + + +
    + +

    We have a couple common questions about code in the LLVM IR form - lets just +get these out of the way right now, shall we?

    + +
    + + + + + +
    + +

    Kaleidoscope is an example of a "portable language": any program written in +Kaleidoscope will work the same way on any target that it runs on. Many other +languages have this property, e.g. lisp, java, haskell, javascript, python, etc +(note that while these languages are portable, not all their libraries are).

    + +

    One nice aspect of LLVM is that it is often capable of preserving target +independence in the IR: you can take the LLVM IR for a Kaleidoscope-compiled +program and run it on any target that LLVM supports, even emitting C code and +compiling that on targets that LLVM doesn't support natively. You can trivially +tell that the Kaleidoscope compiler generates target-independent code because it +never queries for any target-specific information when generating code.

    + +

    The fact that LLVM provides a compact, target-independent, representation for +code gets a lot of people excited. Unfortunately, these people are usually +thinking about C or a language from the C family when they are asking questions +about language portability. I say "unfortunately", because there is really no +way to make (fully general) C code portable, other than shipping the source code +around (and of course, C source code is not actually portable in general +either - ever port a really old application from 32- to 64-bits?).

    + +

    The problem with C (again, in its full generality) is that it is heavily +laden with target specific assumptions. As one simple example, the preprocessor +often destructively removes target-independence from the code when it processes +the input text:

    + +
    +
    +#ifdef __i386__
    +  int X = 1;
    +#else
    +  int X = 42;
    +#endif
    +
    +
    + +

    While it is possible to engineer more and more complex solutions to problems +like this, it cannot be solved in full generality in a way that is better than shipping +the actual source code.

    + +

    That said, there are interesting subsets of C that can be made portable. If +you are willing to fix primitive types to a fixed size (say int = 32-bits, +and long = 64-bits), don't care about ABI compatibility with existing binaries, +and are willing to give up some other minor features, you can have portable +code. This can make sense for specialized domains such as an +in-kernel language.

    + +
    + + + + + +
    + +

    Many of the languages above are also "safe" languages: it is impossible for +a program written in Java to corrupt its address space and crash the process +(assuming the JVM has no bugs). +Safety is an interesting property that requires a combination of language +design, runtime support, and often operating system support.

    + +

    It is certainly possible to implement a safe language in LLVM, but LLVM IR +does not itself guarantee safety. The LLVM IR allows unsafe pointer casts, +use after free bugs, buffer over-runs, and a variety of other problems. Safety +needs to be implemented as a layer on top of LLVM and, conveniently, several +groups have investigated this. Ask on the llvmdev mailing +list if you are interested in more details.

    + +
    + + + + + +
    + +

    One thing about LLVM that turns off many people is that it does not solve all +the world's problems in one system (sorry 'world hunger', someone else will have +to solve you some other day). One specific complaint is that people perceive +LLVM as being incapable of performing high-level language-specific optimization: +LLVM "loses too much information".

    + +

    Unfortunately, this is really not the place to give you a full and unified +version of "Chris Lattner's theory of compiler design". Instead, I'll make a +few observations:

    + +

    First, you're right that LLVM does lose information. For example, as of this +writing, there is no way to distinguish in the LLVM IR whether an SSA-value came +from a C "int" or a C "long" on an ILP32 machine (other than debug info). Both +get compiled down to an 'i32' value and the information about what it came from +is lost. The more general issue here, is that the LLVM type system uses +"structural equivalence" instead of "name equivalence". Another place this +surprises people is if you have two types in a high-level language that have the +same structure (e.g. two different structs that have a single int field): these +types will compile down into a single LLVM type and it will be impossible to +tell what it came from.

    + +

    Second, while LLVM does lose information, LLVM is not a fixed target: we +continue to enhance and improve it in many different ways. In addition to +adding new features (LLVM did not always support exceptions or debug info), we +also extend the IR to capture important information for optimization (e.g. +whether an argument is sign or zero extended, information about pointers +aliasing, etc). Many of the enhancements are user-driven: people want LLVM to +include some specific feature, so they go ahead and extend it.

    + +

    Third, it is possible and easy to add language-specific +optimizations, and you have a number of choices in how to do it. As one trivial +example, it is easy to add language-specific optimization passes that +"know" things about code compiled for a language. In the case of the C family, +there is an optimization pass that "knows" about the standard C library +functions. If you call "exit(0)" in main(), it knows that it is safe to +optimize that into "return 0;" because C specifies what the 'exit' +function does.

    + +

    In addition to simple library knowledge, it is possible to embed a variety of +other language-specific information into the LLVM IR. If you have a specific +need and run into a wall, please bring the topic up on the llvmdev list. At the +very worst, you can always treat LLVM as if it were a "dumb code generator" and +implement the high-level optimizations you desire in your front-end, on the +language-specific AST. +

    + +
    + + + + + +
    + +

    There is a variety of useful tips and tricks that you come to know after +working on/with LLVM that aren't obvious at first glance. Instead of letting +everyone rediscover them, this section talks about some of these issues.

    + +
    + + + + + +
    + +

    One interesting thing that comes up, if you are trying to keep the code +generated by your compiler "target independent", is that you often need to know +the size of some LLVM type or the offset of some field in an llvm structure. +For example, you might need to pass the size of a type into a function that +allocates memory.

    + +

    Unfortunately, this can vary widely across targets: for example the width of +a pointer is trivially target-specific. However, there is a clever +way to use the getelementptr instruction that allows you to compute this +in a portable way.

    + +
    + + + + + +
    + +

    Some languages want to explicitly manage their stack frames, often so that +they are garbage collected or to allow easy implementation of closures. There +are often better ways to implement these features than explicit stack frames, +but LLVM +does support them, if you want. It requires your front-end to convert the +code into Continuation +Passing Style and the use of tail calls (which LLVM also supports).

    + +
    + + +
    +
    + Valid CSS! + Valid HTML 4.01! + + Chris Lattner
    + The LLVM Compiler Infrastructure
    + Last modified: $Date: 2007-10-17 11:05:13 -0700 (Wed, 17 Oct 2007) $ +
    + + diff --git a/libclamav/c++/llvm/docs/tutorial/Makefile b/libclamav/c++/llvm/docs/tutorial/Makefile new file mode 100644 index 000000000..6169bb824 --- /dev/null +++ b/libclamav/c++/llvm/docs/tutorial/Makefile @@ -0,0 +1,28 @@ +##===- docs/tutorial/Makefile ------------------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LEVEL := ../.. +include $(LEVEL)/Makefile.common + +HTML := $(wildcard $(PROJ_SRC_DIR)/*.html) +EXTRA_DIST := $(HTML) index.html +HTML_DIR := $(PROJ_docsdir)/html/tutorial + +install-local:: $(HTML) + $(Echo) Installing HTML Tutorial Documentation + $(Verb) $(MKDIR) $(HTML_DIR) + $(Verb) $(DataInstall) $(HTML) $(HTML_DIR) + $(Verb) $(DataInstall) $(PROJ_SRC_DIR)/index.html $(HTML_DIR) + +uninstall-local:: + $(Echo) Uninstalling Tutorial Documentation + $(Verb) $(RM) -rf $(HTML_DIR) + +printvars:: + $(Echo) "HTML : " '$(HTML)' diff --git a/libclamav/c++/llvm/docs/tutorial/OCamlLangImpl1.html b/libclamav/c++/llvm/docs/tutorial/OCamlLangImpl1.html new file mode 100644 index 000000000..3c0fd8b1c --- /dev/null +++ b/libclamav/c++/llvm/docs/tutorial/OCamlLangImpl1.html @@ -0,0 +1,365 @@ + + + + + Kaleidoscope: Tutorial Introduction and the Lexer + + + + + + + + +
    Kaleidoscope: Tutorial Introduction and the Lexer
    + + + +
    +

    + Written by Chris Lattner + and Erick Tryzelaar +

    +
    + + + + + +
    + +

    Welcome to the "Implementing a language with LLVM" tutorial. This tutorial +runs through the implementation of a simple language, showing how fun and +easy it can be. This tutorial will get you up and started as well as help to +build a framework you can extend to other languages. The code in this tutorial +can also be used as a playground to hack on other LLVM specific things. +

    + +

    +The goal of this tutorial is to progressively unveil our language, describing +how it is built up over time. This will let us cover a fairly broad range of +language design and LLVM-specific usage issues, showing and explaining the code +for it all along the way, without overwhelming you with tons of details up +front.

    + +

    It is useful to point out ahead of time that this tutorial is really about +teaching compiler techniques and LLVM specifically, not about teaching +modern and sane software engineering principles. In practice, this means that +we'll take a number of shortcuts to simplify the exposition. For example, the +code leaks memory, uses global variables all over the place, doesn't use nice +design patterns like visitors, etc... but it +is very simple. If you dig in and use the code as a basis for future projects, +fixing these deficiencies shouldn't be hard.

    + +

    I've tried to put this tutorial together in a way that makes chapters easy to +skip over if you are already familiar with or are uninterested in the various +pieces. The structure of the tutorial is: +

    + +
      +
    • Chapter #1: Introduction to the Kaleidoscope +language, and the definition of its Lexer - This shows where we are going +and the basic functionality that we want it to do. In order to make this +tutorial maximally understandable and hackable, we choose to implement +everything in Objective Caml instead of using lexer and parser generators. +LLVM obviously works just fine with such tools, feel free to use one if you +prefer.
    • +
    • Chapter #2: Implementing a Parser and +AST - With the lexer in place, we can talk about parsing techniques and +basic AST construction. This tutorial describes recursive descent parsing and +operator precedence parsing. Nothing in Chapters 1 or 2 is LLVM-specific, +the code doesn't even link in LLVM at this point. :)
    • +
    • Chapter #3: Code generation to LLVM +IR - With the AST ready, we can show off how easy generation of LLVM IR +really is.
    • +
    • Chapter #4: Adding JIT and Optimizer +Support - Because a lot of people are interested in using LLVM as a JIT, +we'll dive right into it and show you the 3 lines it takes to add JIT support. +LLVM is also useful in many other ways, but this is one simple and "sexy" way +to shows off its power. :)
    • +
    • Chapter #5: Extending the Language: +Control Flow - With the language up and running, we show how to extend it +with control flow operations (if/then/else and a 'for' loop). This gives us a +chance to talk about simple SSA construction and control flow.
    • +
    • Chapter #6: Extending the Language: +User-defined Operators - This is a silly but fun chapter that talks about +extending the language to let the user program define their own arbitrary +unary and binary operators (with assignable precedence!). This lets us build a +significant piece of the "language" as library routines.
    • +
    • Chapter #7: Extending the Language: +Mutable Variables - This chapter talks about adding user-defined local +variables along with an assignment operator. The interesting part about this +is how easy and trivial it is to construct SSA form in LLVM: no, LLVM does +not require your front-end to construct SSA form!
    • +
    • Chapter #8: Conclusion and other +useful LLVM tidbits - This chapter wraps up the series by talking about +potential ways to extend the language, but also includes a bunch of pointers to +info about "special topics" like adding garbage collection support, exceptions, +debugging, support for "spaghetti stacks", and a bunch of other tips and +tricks.
    • + +
    + +

    By the end of the tutorial, we'll have written a bit less than 700 lines of +non-comment, non-blank, lines of code. With this small amount of code, we'll +have built up a very reasonable compiler for a non-trivial language including +a hand-written lexer, parser, AST, as well as code generation support with a JIT +compiler. While other systems may have interesting "hello world" tutorials, +I think the breadth of this tutorial is a great testament to the strengths of +LLVM and why you should consider it if you're interested in language or compiler +design.

    + +

    A note about this tutorial: we expect you to extend the language and play +with it on your own. Take the code and go crazy hacking away at it, compilers +don't need to be scary creatures - it can be a lot of fun to play with +languages!

    + +
    + + + + + +
    + +

    This tutorial will be illustrated with a toy language that we'll call +"Kaleidoscope" (derived +from "meaning beautiful, form, and view"). +Kaleidoscope is a procedural language that allows you to define functions, use +conditionals, math, etc. Over the course of the tutorial, we'll extend +Kaleidoscope to support the if/then/else construct, a for loop, user defined +operators, JIT compilation with a simple command line interface, etc.

    + +

    Because we want to keep things simple, the only datatype in Kaleidoscope is a +64-bit floating point type (aka 'float' in O'Caml parlance). As such, all +values are implicitly double precision and the language doesn't require type +declarations. This gives the language a very nice and simple syntax. For +example, the following simple example computes Fibonacci numbers:

    + +
    +
    +# Compute the x'th fibonacci number.
    +def fib(x)
    +  if x < 3 then
    +    1
    +  else
    +    fib(x-1)+fib(x-2)
    +
    +# This expression will compute the 40th number.
    +fib(40)
    +
    +
    + +

    We also allow Kaleidoscope to call into standard library functions (the LLVM +JIT makes this completely trivial). This means that you can use the 'extern' +keyword to define a function before you use it (this is also useful for mutually +recursive functions). For example:

    + +
    +
    +extern sin(arg);
    +extern cos(arg);
    +extern atan2(arg1 arg2);
    +
    +atan2(sin(.4), cos(42))
    +
    +
    + +

    A more interesting example is included in Chapter 6 where we write a little +Kaleidoscope application that displays +a Mandelbrot Set at various levels of magnification.

    + +

    Lets dive into the implementation of this language!

    + +
    + + + + + +
    + +

    When it comes to implementing a language, the first thing needed is +the ability to process a text file and recognize what it says. The traditional +way to do this is to use a "lexer" (aka 'scanner') +to break the input up into "tokens". Each token returned by the lexer includes +a token code and potentially some metadata (e.g. the numeric value of a number). +First, we define the possibilities: +

    + +
    +
    +(* The lexer returns these 'Kwd' if it is an unknown character, otherwise one of
    + * these others for known things. *)
    +type token =
    +  (* commands *)
    +  | Def | Extern
    +
    +  (* primary *)
    +  | Ident of string | Number of float
    +
    +  (* unknown *)
    +  | Kwd of char
    +
    +
    + +

    Each token returned by our lexer will be one of the token variant values. +An unknown character like '+' will be returned as Token.Kwd '+'. If +the curr token is an identifier, the value will be Token.Ident s. If +the current token is a numeric literal (like 1.0), the value will be +Token.Number 1.0. +

    + +

    The actual implementation of the lexer is a collection of functions driven +by a function named Lexer.lex. The Lexer.lex function is +called to return the next token from standard input. We will use +Camlp4 +to simplify the tokenization of the standard input. Its definition starts +as:

    + +
    +
    +(*===----------------------------------------------------------------------===
    + * Lexer
    + *===----------------------------------------------------------------------===*)
    +
    +let rec lex = parser
    +  (* Skip any whitespace. *)
    +  | [< ' (' ' | '\n' | '\r' | '\t'); stream >] -> lex stream
    +
    +
    + +

    +Lexer.lex works by recursing over a char Stream.t to read +characters one at a time from the standard input. It eats them as it recognizes +them and stores them in in a Token.token variant. The first thing that +it has to do is ignore whitespace between tokens. This is accomplished with the +recursive call above.

    + +

    The next thing Lexer.lex needs to do is recognize identifiers and +specific keywords like "def". Kaleidoscope does this with a pattern match +and a helper function.

    + +

    +
    +  (* identifier: [a-zA-Z][a-zA-Z0-9] *)
    +  | [< ' ('A' .. 'Z' | 'a' .. 'z' as c); stream >] ->
    +      let buffer = Buffer.create 1 in
    +      Buffer.add_char buffer c;
    +      lex_ident buffer stream
    +
    +...
    +
    +and lex_ident buffer = parser
    +  | [< ' ('A' .. 'Z' | 'a' .. 'z' | '0' .. '9' as c); stream >] ->
    +      Buffer.add_char buffer c;
    +      lex_ident buffer stream
    +  | [< stream=lex >] ->
    +      match Buffer.contents buffer with
    +      | "def" -> [< 'Token.Def; stream >]
    +      | "extern" -> [< 'Token.Extern; stream >]
    +      | id -> [< 'Token.Ident id; stream >]
    +
    +
    + +

    Numeric values are similar:

    + +
    +
    +  (* number: [0-9.]+ *)
    +  | [< ' ('0' .. '9' as c); stream >] ->
    +      let buffer = Buffer.create 1 in
    +      Buffer.add_char buffer c;
    +      lex_number buffer stream
    +
    +...
    +
    +and lex_number buffer = parser
    +  | [< ' ('0' .. '9' | '.' as c); stream >] ->
    +      Buffer.add_char buffer c;
    +      lex_number buffer stream
    +  | [< stream=lex >] ->
    +      [< 'Token.Number (float_of_string (Buffer.contents buffer)); stream >]
    +
    +
    + +

    This is all pretty straight-forward code for processing input. When reading +a numeric value from input, we use the ocaml float_of_string function +to convert it to a numeric value that we store in Token.Number. Note +that this isn't doing sufficient error checking: it will raise Failure +if the string "1.23.45.67". Feel free to extend it :). Next we handle +comments: +

    + +
    +
    +  (* Comment until end of line. *)
    +  | [< ' ('#'); stream >] ->
    +      lex_comment stream
    +
    +...
    +
    +and lex_comment = parser
    +  | [< ' ('\n'); stream=lex >] -> stream
    +  | [< 'c; e=lex_comment >] -> e
    +  | [< >] -> [< >]
    +
    +
    + +

    We handle comments by skipping to the end of the line and then return the +next token. Finally, if the input doesn't match one of the above cases, it is +either an operator character like '+' or the end of the file. These are handled +with this code:

    + +
    +
    +  (* Otherwise, just return the character as its ascii value. *)
    +  | [< 'c; stream >] ->
    +      [< 'Token.Kwd c; lex stream >]
    +
    +  (* end of stream. *)
    +  | [< >] -> [< >]
    +
    +
    + +

    With this, we have the complete lexer for the basic Kaleidoscope language +(the full code listing for the Lexer is +available in the next chapter of the +tutorial). Next we'll build a simple parser that +uses this to build an Abstract Syntax Tree. When we have that, we'll +include a driver so that you can use the lexer and parser together. +

    + +Next: Implementing a Parser and AST +
    + + +
    +
    + Valid CSS! + Valid HTML 4.01! + + Chris Lattner
    + Erick Tryzelaar
    + The LLVM Compiler Infrastructure
    + Last modified: $Date: 2007-10-17 11:05:13 -0700 (Wed, 17 Oct 2007) $ +
    + + diff --git a/libclamav/c++/llvm/docs/tutorial/OCamlLangImpl2.html b/libclamav/c++/llvm/docs/tutorial/OCamlLangImpl2.html new file mode 100644 index 000000000..7d60aa6f9 --- /dev/null +++ b/libclamav/c++/llvm/docs/tutorial/OCamlLangImpl2.html @@ -0,0 +1,1045 @@ + + + + + Kaleidoscope: Implementing a Parser and AST + + + + + + + + +
    Kaleidoscope: Implementing a Parser and AST
    + + + +
    +

    + Written by Chris Lattner + and Erick Tryzelaar +

    +
    + + + + + +
    + +

    Welcome to Chapter 2 of the "Implementing a language +with LLVM in Objective Caml" tutorial. This chapter shows you how to use +the lexer, built in Chapter 1, to build a +full parser for our +Kaleidoscope language. Once we have a parser, we'll define and build an Abstract Syntax +Tree (AST).

    + +

    The parser we will build uses a combination of Recursive Descent +Parsing and Operator-Precedence +Parsing to parse the Kaleidoscope language (the latter for +binary expressions and the former for everything else). Before we get to +parsing though, lets talk about the output of the parser: the Abstract Syntax +Tree.

    + +
    + + + + + +
    + +

    The AST for a program captures its behavior in such a way that it is easy for +later stages of the compiler (e.g. code generation) to interpret. We basically +want one object for each construct in the language, and the AST should closely +model the language. In Kaleidoscope, we have expressions, a prototype, and a +function object. We'll start with expressions first:

    + +
    +
    +(* expr - Base type for all expression nodes. *)
    +type expr =
    +  (* variant for numeric literals like "1.0". *)
    +  | Number of float
    +
    +
    + +

    The code above shows the definition of the base ExprAST class and one +subclass which we use for numeric literals. The important thing to note about +this code is that the Number variant captures the numeric value of the +literal as an instance variable. This allows later phases of the compiler to +know what the stored numeric value is.

    + +

    Right now we only create the AST, so there are no useful functions on +them. It would be very easy to add a function to pretty print the code, +for example. Here are the other expression AST node definitions that we'll use +in the basic form of the Kaleidoscope language: +

    + +
    +
    +  (* variant for referencing a variable, like "a". *)
    +  | Variable of string
    +
    +  (* variant for a binary operator. *)
    +  | Binary of char * expr * expr
    +
    +  (* variant for function calls. *)
    +  | Call of string * expr array
    +
    +
    + +

    This is all (intentionally) rather straight-forward: variables capture the +variable name, binary operators capture their opcode (e.g. '+'), and calls +capture a function name as well as a list of any argument expressions. One thing +that is nice about our AST is that it captures the language features without +talking about the syntax of the language. Note that there is no discussion about +precedence of binary operators, lexical structure, etc.

    + +

    For our basic language, these are all of the expression nodes we'll define. +Because it doesn't have conditional control flow, it isn't Turing-complete; +we'll fix that in a later installment. The two things we need next are a way +to talk about the interface to a function, and a way to talk about functions +themselves:

    + +
    +
    +(* proto - This type represents the "prototype" for a function, which captures
    + * its name, and its argument names (thus implicitly the number of arguments the
    + * function takes). *)
    +type proto = Prototype of string * string array
    +
    +(* func - This type represents a function definition itself. *)
    +type func = Function of proto * expr
    +
    +
    + +

    In Kaleidoscope, functions are typed with just a count of their arguments. +Since all values are double precision floating point, the type of each argument +doesn't need to be stored anywhere. In a more aggressive and realistic +language, the "expr" variants would probably have a type field.

    + +

    With this scaffolding, we can now talk about parsing expressions and function +bodies in Kaleidoscope.

    + +
    + + + + + +
    + +

    Now that we have an AST to build, we need to define the parser code to build +it. The idea here is that we want to parse something like "x+y" (which is +returned as three tokens by the lexer) into an AST that could be generated with +calls like this:

    + +
    +
    +  let x = Variable "x" in
    +  let y = Variable "y" in
    +  let result = Binary ('+', x, y) in
    +  ...
    +
    +
    + +

    +The error handling routines make use of the builtin Stream.Failure and +Stream.Errors. Stream.Failure is raised when the parser is +unable to find any matching token in the first position of a pattern. +Stream.Error is raised when the first token matches, but the rest do +not. The error recovery in our parser will not be the best and is not +particular user-friendly, but it will be enough for our tutorial. These +exceptions make it easier to handle errors in routines that have various return +types.

    + +

    With these basic types and exceptions, we can implement the first +piece of our grammar: numeric literals.

    + +
    + + + + + +
    + +

    We start with numeric literals, because they are the simplest to process. +For each production in our grammar, we'll define a function which parses that +production. We call this class of expressions "primary" expressions, for +reasons that will become more clear +later in the tutorial. In order to parse an arbitrary primary expression, +we need to determine what sort of expression it is. For numeric literals, we +have:

    + +
    +
    +(* primary
    + *   ::= identifier
    + *   ::= numberexpr
    + *   ::= parenexpr *)
    +parse_primary = parser
    +  (* numberexpr ::= number *)
    +  | [< 'Token.Number n >] -> Ast.Number n
    +
    +
    + +

    This routine is very simple: it expects to be called when the current token +is a Token.Number token. It takes the current number value, creates +a Ast.Number node, advances the lexer to the next token, and finally +returns.

    + +

    There are some interesting aspects to this. The most important one is that +this routine eats all of the tokens that correspond to the production and +returns the lexer buffer with the next token (which is not part of the grammar +production) ready to go. This is a fairly standard way to go for recursive +descent parsers. For a better example, the parenthesis operator is defined like +this:

    + +
    +
    +  (* parenexpr ::= '(' expression ')' *)
    +  | [< 'Token.Kwd '('; e=parse_expr; 'Token.Kwd ')' ?? "expected ')'" >] -> e
    +
    +
    + +

    This function illustrates a number of interesting things about the +parser:

    + +

    +1) It shows how we use the Stream.Error exception. When called, this +function expects that the current token is a '(' token, but after parsing the +subexpression, it is possible that there is no ')' waiting. For example, if +the user types in "(4 x" instead of "(4)", the parser should emit an error. +Because errors can occur, the parser needs a way to indicate that they +happened. In our parser, we use the camlp4 shortcut syntax token ?? "parse +error", where if the token before the ?? does not match, then +Stream.Error "parse error" will be raised.

    + +

    2) Another interesting aspect of this function is that it uses recursion by +calling Parser.parse_primary (we will soon see that +Parser.parse_primary can call Parser.parse_primary). This is +powerful because it allows us to handle recursive grammars, and keeps each +production very simple. Note that parentheses do not cause construction of AST +nodes themselves. While we could do it this way, the most important role of +parentheses are to guide the parser and provide grouping. Once the parser +constructs the AST, parentheses are not needed.

    + +

    The next simple production is for handling variable references and function +calls:

    + +
    +
    +  (* identifierexpr
    +   *   ::= identifier
    +   *   ::= identifier '(' argumentexpr ')' *)
    +  | [< 'Token.Ident id; stream >] ->
    +      let rec parse_args accumulator = parser
    +        | [< e=parse_expr; stream >] ->
    +            begin parser
    +              | [< 'Token.Kwd ','; e=parse_args (e :: accumulator) >] -> e
    +              | [< >] -> e :: accumulator
    +            end stream
    +        | [< >] -> accumulator
    +      in
    +      let rec parse_ident id = parser
    +        (* Call. *)
    +        | [< 'Token.Kwd '(';
    +             args=parse_args [];
    +             'Token.Kwd ')' ?? "expected ')'">] ->
    +            Ast.Call (id, Array.of_list (List.rev args))
    +
    +        (* Simple variable ref. *)
    +        | [< >] -> Ast.Variable id
    +      in
    +      parse_ident id stream
    +
    +
    + +

    This routine follows the same style as the other routines. (It expects to be +called if the current token is a Token.Ident token). It also has +recursion and error handling. One interesting aspect of this is that it uses +look-ahead to determine if the current identifier is a stand alone +variable reference or if it is a function call expression. It handles this by +checking to see if the token after the identifier is a '(' token, constructing +either a Ast.Variable or Ast.Call node as appropriate. +

    + +

    We finish up by raising an exception if we received a token we didn't +expect:

    + +
    +
    +  | [< >] -> raise (Stream.Error "unknown token when expecting an expression.")
    +
    +
    + +

    Now that basic expressions are handled, we need to handle binary expressions. +They are a bit more complex.

    + +
    + + + + + +
    + +

    Binary expressions are significantly harder to parse because they are often +ambiguous. For example, when given the string "x+y*z", the parser can choose +to parse it as either "(x+y)*z" or "x+(y*z)". With common definitions from +mathematics, we expect the later parse, because "*" (multiplication) has +higher precedence than "+" (addition).

    + +

    There are many ways to handle this, but an elegant and efficient way is to +use Operator-Precedence +Parsing. This parsing technique uses the precedence of binary operators to +guide recursion. To start with, we need a table of precedences:

    + +
    +
    +(* binop_precedence - This holds the precedence for each binary operator that is
    + * defined *)
    +let binop_precedence:(char, int) Hashtbl.t = Hashtbl.create 10
    +
    +(* precedence - Get the precedence of the pending binary operator token. *)
    +let precedence c = try Hashtbl.find binop_precedence c with Not_found -> -1
    +
    +...
    +
    +let main () =
    +  (* Install standard binary operators.
    +   * 1 is the lowest precedence. *)
    +  Hashtbl.add Parser.binop_precedence '<' 10;
    +  Hashtbl.add Parser.binop_precedence '+' 20;
    +  Hashtbl.add Parser.binop_precedence '-' 20;
    +  Hashtbl.add Parser.binop_precedence '*' 40;    (* highest. *)
    +  ...
    +
    +
    + +

    For the basic form of Kaleidoscope, we will only support 4 binary operators +(this can obviously be extended by you, our brave and intrepid reader). The +Parser.precedence function returns the precedence for the current +token, or -1 if the token is not a binary operator. Having a Hashtbl.t +makes it easy to add new operators and makes it clear that the algorithm doesn't +depend on the specific operators involved, but it would be easy enough to +eliminate the Hashtbl.t and do the comparisons in the +Parser.precedence function. (Or just use a fixed-size array).

    + +

    With the helper above defined, we can now start parsing binary expressions. +The basic idea of operator precedence parsing is to break down an expression +with potentially ambiguous binary operators into pieces. Consider ,for example, +the expression "a+b+(c+d)*e*f+g". Operator precedence parsing considers this +as a stream of primary expressions separated by binary operators. As such, +it will first parse the leading primary expression "a", then it will see the +pairs [+, b] [+, (c+d)] [*, e] [*, f] and [+, g]. Note that because parentheses +are primary expressions, the binary expression parser doesn't need to worry +about nested subexpressions like (c+d) at all. +

    + +

    +To start, an expression is a primary expression potentially followed by a +sequence of [binop,primaryexpr] pairs:

    + +
    +
    +(* expression
    + *   ::= primary binoprhs *)
    +and parse_expr = parser
    +  | [< lhs=parse_primary; stream >] -> parse_bin_rhs 0 lhs stream
    +
    +
    + +

    Parser.parse_bin_rhs is the function that parses the sequence of +pairs for us. It takes a precedence and a pointer to an expression for the part +that has been parsed so far. Note that "x" is a perfectly valid expression: As +such, "binoprhs" is allowed to be empty, in which case it returns the expression +that is passed into it. In our example above, the code passes the expression for +"a" into Parser.parse_bin_rhs and the current token is "+".

    + +

    The precedence value passed into Parser.parse_bin_rhs indicates the +minimal operator precedence that the function is allowed to eat. For +example, if the current pair stream is [+, x] and Parser.parse_bin_rhs +is passed in a precedence of 40, it will not consume any tokens (because the +precedence of '+' is only 20). With this in mind, Parser.parse_bin_rhs +starts with:

    + +
    +
    +(* binoprhs
    + *   ::= ('+' primary)* *)
    +and parse_bin_rhs expr_prec lhs stream =
    +  match Stream.peek stream with
    +  (* If this is a binop, find its precedence. *)
    +  | Some (Token.Kwd c) when Hashtbl.mem binop_precedence c ->
    +      let token_prec = precedence c in
    +
    +      (* If this is a binop that binds at least as tightly as the current binop,
    +       * consume it, otherwise we are done. *)
    +      if token_prec < expr_prec then lhs else begin
    +
    +
    + +

    This code gets the precedence of the current token and checks to see if if is +too low. Because we defined invalid tokens to have a precedence of -1, this +check implicitly knows that the pair-stream ends when the token stream runs out +of binary operators. If this check succeeds, we know that the token is a binary +operator and that it will be included in this expression:

    + +
    +
    +        (* Eat the binop. *)
    +        Stream.junk stream;
    +
    +        (* Okay, we know this is a binop. *)
    +        let rhs =
    +          match Stream.peek stream with
    +          | Some (Token.Kwd c2) ->
    +
    +
    + +

    As such, this code eats (and remembers) the binary operator and then parses +the primary expression that follows. This builds up the whole pair, the first of +which is [+, b] for the running example.

    + +

    Now that we parsed the left-hand side of an expression and one pair of the +RHS sequence, we have to decide which way the expression associates. In +particular, we could have "(a+b) binop unparsed" or "a + (b binop unparsed)". +To determine this, we look ahead at "binop" to determine its precedence and +compare it to BinOp's precedence (which is '+' in this case):

    + +
    +
    +              (* If BinOp binds less tightly with rhs than the operator after
    +               * rhs, let the pending operator take rhs as its lhs. *)
    +              let next_prec = precedence c2 in
    +              if token_prec < next_prec
    +
    +
    + +

    If the precedence of the binop to the right of "RHS" is lower or equal to the +precedence of our current operator, then we know that the parentheses associate +as "(a+b) binop ...". In our example, the current operator is "+" and the next +operator is "+", we know that they have the same precedence. In this case we'll +create the AST node for "a+b", and then continue parsing:

    + +
    +
    +          ... if body omitted ...
    +        in
    +
    +        (* Merge lhs/rhs. *)
    +        let lhs = Ast.Binary (c, lhs, rhs) in
    +        parse_bin_rhs expr_prec lhs stream
    +      end
    +
    +
    + +

    In our example above, this will turn "a+b+" into "(a+b)" and execute the next +iteration of the loop, with "+" as the current token. The code above will eat, +remember, and parse "(c+d)" as the primary expression, which makes the +current pair equal to [+, (c+d)]. It will then evaluate the 'if' conditional above with +"*" as the binop to the right of the primary. In this case, the precedence of "*" is +higher than the precedence of "+" so the if condition will be entered.

    + +

    The critical question left here is "how can the if condition parse the right +hand side in full"? In particular, to build the AST correctly for our example, +it needs to get all of "(c+d)*e*f" as the RHS expression variable. The code to +do this is surprisingly simple (code from the above two blocks duplicated for +context):

    + +
    +
    +          match Stream.peek stream with
    +          | Some (Token.Kwd c2) ->
    +              (* If BinOp binds less tightly with rhs than the operator after
    +               * rhs, let the pending operator take rhs as its lhs. *)
    +              if token_prec < precedence c2
    +              then parse_bin_rhs (token_prec + 1) rhs stream
    +              else rhs
    +          | _ -> rhs
    +        in
    +
    +        (* Merge lhs/rhs. *)
    +        let lhs = Ast.Binary (c, lhs, rhs) in
    +        parse_bin_rhs expr_prec lhs stream
    +      end
    +
    +
    + +

    At this point, we know that the binary operator to the RHS of our primary +has higher precedence than the binop we are currently parsing. As such, we know +that any sequence of pairs whose operators are all higher precedence than "+" +should be parsed together and returned as "RHS". To do this, we recursively +invoke the Parser.parse_bin_rhs function specifying "token_prec+1" as +the minimum precedence required for it to continue. In our example above, this +will cause it to return the AST node for "(c+d)*e*f" as RHS, which is then set +as the RHS of the '+' expression.

    + +

    Finally, on the next iteration of the while loop, the "+g" piece is parsed +and added to the AST. With this little bit of code (14 non-trivial lines), we +correctly handle fully general binary expression parsing in a very elegant way. +This was a whirlwind tour of this code, and it is somewhat subtle. I recommend +running through it with a few tough examples to see how it works. +

    + +

    This wraps up handling of expressions. At this point, we can point the +parser at an arbitrary token stream and build an expression from it, stopping +at the first token that is not part of the expression. Next up we need to +handle function definitions, etc.

    + +
    + + + + + +
    + +

    +The next thing missing is handling of function prototypes. In Kaleidoscope, +these are used both for 'extern' function declarations as well as function body +definitions. The code to do this is straight-forward and not very interesting +(once you've survived expressions): +

    + +
    +
    +(* prototype
    + *   ::= id '(' id* ')' *)
    +let parse_prototype =
    +  let rec parse_args accumulator = parser
    +    | [< 'Token.Ident id; e=parse_args (id::accumulator) >] -> e
    +    | [< >] -> accumulator
    +  in
    +
    +  parser
    +  | [< 'Token.Ident id;
    +       'Token.Kwd '(' ?? "expected '(' in prototype";
    +       args=parse_args [];
    +       'Token.Kwd ')' ?? "expected ')' in prototype" >] ->
    +      (* success. *)
    +      Ast.Prototype (id, Array.of_list (List.rev args))
    +
    +  | [< >] ->
    +      raise (Stream.Error "expected function name in prototype")
    +
    +
    + +

    Given this, a function definition is very simple, just a prototype plus +an expression to implement the body:

    + +
    +
    +(* definition ::= 'def' prototype expression *)
    +let parse_definition = parser
    +  | [< 'Token.Def; p=parse_prototype; e=parse_expr >] ->
    +      Ast.Function (p, e)
    +
    +
    + +

    In addition, we support 'extern' to declare functions like 'sin' and 'cos' as +well as to support forward declaration of user functions. These 'extern's are just +prototypes with no body:

    + +
    +
    +(*  external ::= 'extern' prototype *)
    +let parse_extern = parser
    +  | [< 'Token.Extern; e=parse_prototype >] -> e
    +
    +
    + +

    Finally, we'll also let the user type in arbitrary top-level expressions and +evaluate them on the fly. We will handle this by defining anonymous nullary +(zero argument) functions for them:

    + +
    +
    +(* toplevelexpr ::= expression *)
    +let parse_toplevel = parser
    +  | [< e=parse_expr >] ->
    +      (* Make an anonymous proto. *)
    +      Ast.Function (Ast.Prototype ("", [||]), e)
    +
    +
    + +

    Now that we have all the pieces, let's build a little driver that will let us +actually execute this code we've built!

    + +
    + + + + + +
    + +

    The driver for this simply invokes all of the parsing pieces with a top-level +dispatch loop. There isn't much interesting here, so I'll just include the +top-level loop. See below for full code in the "Top-Level +Parsing" section.

    + +
    +
    +(* top ::= definition | external | expression | ';' *)
    +let rec main_loop stream =
    +  match Stream.peek stream with
    +  | None -> ()
    +
    +  (* ignore top-level semicolons. *)
    +  | Some (Token.Kwd ';') ->
    +      Stream.junk stream;
    +      main_loop stream
    +
    +  | Some token ->
    +      begin
    +        try match token with
    +        | Token.Def ->
    +            ignore(Parser.parse_definition stream);
    +            print_endline "parsed a function definition.";
    +        | Token.Extern ->
    +            ignore(Parser.parse_extern stream);
    +            print_endline "parsed an extern.";
    +        | _ ->
    +            (* Evaluate a top-level expression into an anonymous function. *)
    +            ignore(Parser.parse_toplevel stream);
    +            print_endline "parsed a top-level expr";
    +        with Stream.Error s ->
    +          (* Skip token for error recovery. *)
    +          Stream.junk stream;
    +          print_endline s;
    +      end;
    +      print_string "ready> "; flush stdout;
    +      main_loop stream
    +
    +
    + +

    The most interesting part of this is that we ignore top-level semicolons. +Why is this, you ask? The basic reason is that if you type "4 + 5" at the +command line, the parser doesn't know whether that is the end of what you will type +or not. For example, on the next line you could type "def foo..." in which case +4+5 is the end of a top-level expression. Alternatively you could type "* 6", +which would continue the expression. Having top-level semicolons allows you to +type "4+5;", and the parser will know you are done.

    + +
    + + + + + +
    + +

    With just under 300 lines of commented code (240 lines of non-comment, +non-blank code), we fully defined our minimal language, including a lexer, +parser, and AST builder. With this done, the executable will validate +Kaleidoscope code and tell us if it is grammatically invalid. For +example, here is a sample interaction:

    + +
    +
    +$ ./toy.byte
    +ready> def foo(x y) x+foo(y, 4.0);
    +Parsed a function definition.
    +ready> def foo(x y) x+y y;
    +Parsed a function definition.
    +Parsed a top-level expr
    +ready> def foo(x y) x+y );
    +Parsed a function definition.
    +Error: unknown token when expecting an expression
    +ready> extern sin(a);
    +ready> Parsed an extern
    +ready> ^D
    +$
    +
    +
    + +

    There is a lot of room for extension here. You can define new AST nodes, +extend the language in many ways, etc. In the +next installment, we will describe how to generate LLVM Intermediate +Representation (IR) from the AST.

    + +
    + + + + + +
    + +

    +Here is the complete code listing for this and the previous chapter. +Note that it is fully self-contained: you don't need LLVM or any external +libraries at all for this. (Besides the ocaml standard libraries, of +course.) To build this, just compile with:

    + +
    +
    +# Compile
    +ocamlbuild toy.byte
    +# Run
    +./toy.byte
    +
    +
    + +

    Here is the code:

    + +
    +
    _tags:
    +
    +
    +<{lexer,parser}.ml>: use_camlp4, pp(camlp4of)
    +
    +
    + +
    token.ml:
    +
    +
    +(*===----------------------------------------------------------------------===
    + * Lexer Tokens
    + *===----------------------------------------------------------------------===*)
    +
    +(* The lexer returns these 'Kwd' if it is an unknown character, otherwise one of
    + * these others for known things. *)
    +type token =
    +  (* commands *)
    +  | Def | Extern
    +
    +  (* primary *)
    +  | Ident of string | Number of float
    +
    +  (* unknown *)
    +  | Kwd of char
    +
    +
    + +
    lexer.ml:
    +
    +
    +(*===----------------------------------------------------------------------===
    + * Lexer
    + *===----------------------------------------------------------------------===*)
    +
    +let rec lex = parser
    +  (* Skip any whitespace. *)
    +  | [< ' (' ' | '\n' | '\r' | '\t'); stream >] -> lex stream
    +
    +  (* identifier: [a-zA-Z][a-zA-Z0-9] *)
    +  | [< ' ('A' .. 'Z' | 'a' .. 'z' as c); stream >] ->
    +      let buffer = Buffer.create 1 in
    +      Buffer.add_char buffer c;
    +      lex_ident buffer stream
    +
    +  (* number: [0-9.]+ *)
    +  | [< ' ('0' .. '9' as c); stream >] ->
    +      let buffer = Buffer.create 1 in
    +      Buffer.add_char buffer c;
    +      lex_number buffer stream
    +
    +  (* Comment until end of line. *)
    +  | [< ' ('#'); stream >] ->
    +      lex_comment stream
    +
    +  (* Otherwise, just return the character as its ascii value. *)
    +  | [< 'c; stream >] ->
    +      [< 'Token.Kwd c; lex stream >]
    +
    +  (* end of stream. *)
    +  | [< >] -> [< >]
    +
    +and lex_number buffer = parser
    +  | [< ' ('0' .. '9' | '.' as c); stream >] ->
    +      Buffer.add_char buffer c;
    +      lex_number buffer stream
    +  | [< stream=lex >] ->
    +      [< 'Token.Number (float_of_string (Buffer.contents buffer)); stream >]
    +
    +and lex_ident buffer = parser
    +  | [< ' ('A' .. 'Z' | 'a' .. 'z' | '0' .. '9' as c); stream >] ->
    +      Buffer.add_char buffer c;
    +      lex_ident buffer stream
    +  | [< stream=lex >] ->
    +      match Buffer.contents buffer with
    +      | "def" -> [< 'Token.Def; stream >]
    +      | "extern" -> [< 'Token.Extern; stream >]
    +      | id -> [< 'Token.Ident id; stream >]
    +
    +and lex_comment = parser
    +  | [< ' ('\n'); stream=lex >] -> stream
    +  | [< 'c; e=lex_comment >] -> e
    +  | [< >] -> [< >]
    +
    +
    + +
    ast.ml:
    +
    +
    +(*===----------------------------------------------------------------------===
    + * Abstract Syntax Tree (aka Parse Tree)
    + *===----------------------------------------------------------------------===*)
    +
    +(* expr - Base type for all expression nodes. *)
    +type expr =
    +  (* variant for numeric literals like "1.0". *)
    +  | Number of float
    +
    +  (* variant for referencing a variable, like "a". *)
    +  | Variable of string
    +
    +  (* variant for a binary operator. *)
    +  | Binary of char * expr * expr
    +
    +  (* variant for function calls. *)
    +  | Call of string * expr array
    +
    +(* proto - This type represents the "prototype" for a function, which captures
    + * its name, and its argument names (thus implicitly the number of arguments the
    + * function takes). *)
    +type proto = Prototype of string * string array
    +
    +(* func - This type represents a function definition itself. *)
    +type func = Function of proto * expr
    +
    +
    + +
    parser.ml:
    +
    +
    +(*===---------------------------------------------------------------------===
    + * Parser
    + *===---------------------------------------------------------------------===*)
    +
    +(* binop_precedence - This holds the precedence for each binary operator that is
    + * defined *)
    +let binop_precedence:(char, int) Hashtbl.t = Hashtbl.create 10
    +
    +(* precedence - Get the precedence of the pending binary operator token. *)
    +let precedence c = try Hashtbl.find binop_precedence c with Not_found -> -1
    +
    +(* primary
    + *   ::= identifier
    + *   ::= numberexpr
    + *   ::= parenexpr *)
    +let rec parse_primary = parser
    +  (* numberexpr ::= number *)
    +  | [< 'Token.Number n >] -> Ast.Number n
    +
    +  (* parenexpr ::= '(' expression ')' *)
    +  | [< 'Token.Kwd '('; e=parse_expr; 'Token.Kwd ')' ?? "expected ')'" >] -> e
    +
    +  (* identifierexpr
    +   *   ::= identifier
    +   *   ::= identifier '(' argumentexpr ')' *)
    +  | [< 'Token.Ident id; stream >] ->
    +      let rec parse_args accumulator = parser
    +        | [< e=parse_expr; stream >] ->
    +            begin parser
    +              | [< 'Token.Kwd ','; e=parse_args (e :: accumulator) >] -> e
    +              | [< >] -> e :: accumulator
    +            end stream
    +        | [< >] -> accumulator
    +      in
    +      let rec parse_ident id = parser
    +        (* Call. *)
    +        | [< 'Token.Kwd '(';
    +             args=parse_args [];
    +             'Token.Kwd ')' ?? "expected ')'">] ->
    +            Ast.Call (id, Array.of_list (List.rev args))
    +
    +        (* Simple variable ref. *)
    +        | [< >] -> Ast.Variable id
    +      in
    +      parse_ident id stream
    +
    +  | [< >] -> raise (Stream.Error "unknown token when expecting an expression.")
    +
    +(* binoprhs
    + *   ::= ('+' primary)* *)
    +and parse_bin_rhs expr_prec lhs stream =
    +  match Stream.peek stream with
    +  (* If this is a binop, find its precedence. *)
    +  | Some (Token.Kwd c) when Hashtbl.mem binop_precedence c ->
    +      let token_prec = precedence c in
    +
    +      (* If this is a binop that binds at least as tightly as the current binop,
    +       * consume it, otherwise we are done. *)
    +      if token_prec < expr_prec then lhs else begin
    +        (* Eat the binop. *)
    +        Stream.junk stream;
    +
    +        (* Parse the primary expression after the binary operator. *)
    +        let rhs = parse_primary stream in
    +
    +        (* Okay, we know this is a binop. *)
    +        let rhs =
    +          match Stream.peek stream with
    +          | Some (Token.Kwd c2) ->
    +              (* If BinOp binds less tightly with rhs than the operator after
    +               * rhs, let the pending operator take rhs as its lhs. *)
    +              let next_prec = precedence c2 in
    +              if token_prec < next_prec
    +              then parse_bin_rhs (token_prec + 1) rhs stream
    +              else rhs
    +          | _ -> rhs
    +        in
    +
    +        (* Merge lhs/rhs. *)
    +        let lhs = Ast.Binary (c, lhs, rhs) in
    +        parse_bin_rhs expr_prec lhs stream
    +      end
    +  | _ -> lhs
    +
    +(* expression
    + *   ::= primary binoprhs *)
    +and parse_expr = parser
    +  | [< lhs=parse_primary; stream >] -> parse_bin_rhs 0 lhs stream
    +
    +(* prototype
    + *   ::= id '(' id* ')' *)
    +let parse_prototype =
    +  let rec parse_args accumulator = parser
    +    | [< 'Token.Ident id; e=parse_args (id::accumulator) >] -> e
    +    | [< >] -> accumulator
    +  in
    +
    +  parser
    +  | [< 'Token.Ident id;
    +       'Token.Kwd '(' ?? "expected '(' in prototype";
    +       args=parse_args [];
    +       'Token.Kwd ')' ?? "expected ')' in prototype" >] ->
    +      (* success. *)
    +      Ast.Prototype (id, Array.of_list (List.rev args))
    +
    +  | [< >] ->
    +      raise (Stream.Error "expected function name in prototype")
    +
    +(* definition ::= 'def' prototype expression *)
    +let parse_definition = parser
    +  | [< 'Token.Def; p=parse_prototype; e=parse_expr >] ->
    +      Ast.Function (p, e)
    +
    +(* toplevelexpr ::= expression *)
    +let parse_toplevel = parser
    +  | [< e=parse_expr >] ->
    +      (* Make an anonymous proto. *)
    +      Ast.Function (Ast.Prototype ("", [||]), e)
    +
    +(*  external ::= 'extern' prototype *)
    +let parse_extern = parser
    +  | [< 'Token.Extern; e=parse_prototype >] -> e
    +
    +
    + +
    toplevel.ml:
    +
    +
    +(*===----------------------------------------------------------------------===
    + * Top-Level parsing and JIT Driver
    + *===----------------------------------------------------------------------===*)
    +
    +(* top ::= definition | external | expression | ';' *)
    +let rec main_loop stream =
    +  match Stream.peek stream with
    +  | None -> ()
    +
    +  (* ignore top-level semicolons. *)
    +  | Some (Token.Kwd ';') ->
    +      Stream.junk stream;
    +      main_loop stream
    +
    +  | Some token ->
    +      begin
    +        try match token with
    +        | Token.Def ->
    +            ignore(Parser.parse_definition stream);
    +            print_endline "parsed a function definition.";
    +        | Token.Extern ->
    +            ignore(Parser.parse_extern stream);
    +            print_endline "parsed an extern.";
    +        | _ ->
    +            (* Evaluate a top-level expression into an anonymous function. *)
    +            ignore(Parser.parse_toplevel stream);
    +            print_endline "parsed a top-level expr";
    +        with Stream.Error s ->
    +          (* Skip token for error recovery. *)
    +          Stream.junk stream;
    +          print_endline s;
    +      end;
    +      print_string "ready> "; flush stdout;
    +      main_loop stream
    +
    +
    + +
    toy.ml:
    +
    +
    +(*===----------------------------------------------------------------------===
    + * Main driver code.
    + *===----------------------------------------------------------------------===*)
    +
    +let main () =
    +  (* Install standard binary operators.
    +   * 1 is the lowest precedence. *)
    +  Hashtbl.add Parser.binop_precedence '<' 10;
    +  Hashtbl.add Parser.binop_precedence '+' 20;
    +  Hashtbl.add Parser.binop_precedence '-' 20;
    +  Hashtbl.add Parser.binop_precedence '*' 40;    (* highest. *)
    +
    +  (* Prime the first token. *)
    +  print_string "ready> "; flush stdout;
    +  let stream = Lexer.lex (Stream.of_channel stdin) in
    +
    +  (* Run the main "interpreter loop" now. *)
    +  Toplevel.main_loop stream;
    +;;
    +
    +main ()
    +
    +
    +
    + +Next: Implementing Code Generation to LLVM IR +
    + + +
    +
    + Valid CSS! + Valid HTML 4.01! + + Chris Lattner + Erick Tryzelaar
    + The LLVM Compiler Infrastructure
    + Last modified: $Date: 2007-10-17 11:05:13 -0700 (Wed, 17 Oct 2007) $ +
    + + diff --git a/libclamav/c++/llvm/docs/tutorial/OCamlLangImpl3.html b/libclamav/c++/llvm/docs/tutorial/OCamlLangImpl3.html new file mode 100644 index 000000000..a59887522 --- /dev/null +++ b/libclamav/c++/llvm/docs/tutorial/OCamlLangImpl3.html @@ -0,0 +1,1091 @@ + + + + + Kaleidoscope: Implementing code generation to LLVM IR + + + + + + + + +
    Kaleidoscope: Code generation to LLVM IR
    + + + +
    +

    + Written by Chris Lattner + and Erick Tryzelaar +

    +
    + + + + + +
    + +

    Welcome to Chapter 3 of the "Implementing a language +with LLVM" tutorial. This chapter shows you how to transform the Abstract Syntax Tree, built in Chapter 2, into +LLVM IR. This will teach you a little bit about how LLVM does things, as well +as demonstrate how easy it is to use. It's much more work to build a lexer and +parser than it is to generate LLVM IR code. :) +

    + +

    Please note: the code in this chapter and later require LLVM 2.3 or +LLVM SVN to work. LLVM 2.2 and before will not work with it.

    + +
    + + + + + +
    + +

    +In order to generate LLVM IR, we want some simple setup to get started. First +we define virtual code generation (codegen) methods in each AST class:

    + +
    +
    +let rec codegen_expr = function
    +  | Ast.Number n -> ...
    +  | Ast.Variable name -> ...
    +
    +
    + +

    The Codegen.codegen_expr function says to emit IR for that AST node +along with all the things it depends on, and they all return an LLVM Value +object. "Value" is the class used to represent a "Static Single +Assignment (SSA) register" or "SSA value" in LLVM. The most distinct aspect +of SSA values is that their value is computed as the related instruction +executes, and it does not get a new value until (and if) the instruction +re-executes. In other words, there is no way to "change" an SSA value. For +more information, please read up on Static Single +Assignment - the concepts are really quite natural once you grok them.

    + +

    The +second thing we want is an "Error" exception like we used for the parser, which +will be used to report errors found during code generation (for example, use of +an undeclared parameter):

    + +
    +
    +exception Error of string
    +
    +let the_module = create_module (global_context ()) "my cool jit"
    +let builder = builder (global_context ())
    +let named_values:(string, llvalue) Hashtbl.t = Hashtbl.create 10
    +
    +
    + +

    The static variables will be used during code generation. +Codgen.the_module is the LLVM construct that contains all of the +functions and global variables in a chunk of code. In many ways, it is the +top-level structure that the LLVM IR uses to contain code.

    + +

    The Codegen.builder object is a helper object that makes it easy to +generate LLVM instructions. Instances of the IRBuilder +class keep track of the current place to insert instructions and has methods to +create new instructions.

    + +

    The Codegen.named_values map keeps track of which values are defined +in the current scope and what their LLVM representation is. (In other words, it +is a symbol table for the code). In this form of Kaleidoscope, the only things +that can be referenced are function parameters. As such, function parameters +will be in this map when generating code for their function body.

    + +

    +With these basics in place, we can start talking about how to generate code for +each expression. Note that this assumes that the Codgen.builder has +been set up to generate code into something. For now, we'll assume +that this has already been done, and we'll just use it to emit code.

    + +
    + + + + + +
    + +

    Generating LLVM code for expression nodes is very straightforward: less +than 30 lines of commented code for all four of our expression nodes. First +we'll do numeric literals:

    + +
    +
    +  | Ast.Number n -> const_float double_type n
    +
    +
    + +

    In the LLVM IR, numeric constants are represented with the +ConstantFP class, which holds the numeric value in an APFloat +internally (APFloat has the capability of holding floating point +constants of Arbitrary Precision). This code basically just +creates and returns a ConstantFP. Note that in the LLVM IR +that constants are all uniqued together and shared. For this reason, the API +uses "the foo::get(..)" idiom instead of "new foo(..)" or "foo::Create(..)".

    + +
    +
    +  | Ast.Variable name ->
    +      (try Hashtbl.find named_values name with
    +        | Not_found -> raise (Error "unknown variable name"))
    +
    +
    + +

    References to variables are also quite simple using LLVM. In the simple +version of Kaleidoscope, we assume that the variable has already been emitted +somewhere and its value is available. In practice, the only values that can be +in the Codegen.named_values map are function arguments. This code +simply checks to see that the specified name is in the map (if not, an unknown +variable is being referenced) and returns the value for it. In future chapters, +we'll add support for loop induction variables +in the symbol table, and for local +variables.

    + +
    +
    +  | Ast.Binary (op, lhs, rhs) ->
    +      let lhs_val = codegen_expr lhs in
    +      let rhs_val = codegen_expr rhs in
    +      begin
    +        match op with
    +        | '+' -> build_add lhs_val rhs_val "addtmp" builder
    +        | '-' -> build_sub lhs_val rhs_val "subtmp" builder
    +        | '*' -> build_mul lhs_val rhs_val "multmp" builder
    +        | '<' ->
    +            (* Convert bool 0/1 to double 0.0 or 1.0 *)
    +            let i = build_fcmp Fcmp.Ult lhs_val rhs_val "cmptmp" builder in
    +            build_uitofp i double_type "booltmp" builder
    +        | _ -> raise (Error "invalid binary operator")
    +      end
    +
    +
    + +

    Binary operators start to get more interesting. The basic idea here is that +we recursively emit code for the left-hand side of the expression, then the +right-hand side, then we compute the result of the binary expression. In this +code, we do a simple switch on the opcode to create the right LLVM instruction. +

    + +

    In the example above, the LLVM builder class is starting to show its value. +IRBuilder knows where to insert the newly created instruction, all you have to +do is specify what instruction to create (e.g. with Llvm.create_add), +which operands to use (lhs and rhs here) and optionally +provide a name for the generated instruction.

    + +

    One nice thing about LLVM is that the name is just a hint. For instance, if +the code above emits multiple "addtmp" variables, LLVM will automatically +provide each one with an increasing, unique numeric suffix. Local value names +for instructions are purely optional, but it makes it much easier to read the +IR dumps.

    + +

    LLVM instructions are constrained by +strict rules: for example, the Left and Right operators of +an add instruction must have the same +type, and the result type of the add must match the operand types. Because +all values in Kaleidoscope are doubles, this makes for very simple code for add, +sub and mul.

    + +

    On the other hand, LLVM specifies that the fcmp instruction always returns an 'i1' value +(a one bit integer). The problem with this is that Kaleidoscope wants the value to be a 0.0 or 1.0 value. In order to get these semantics, we combine the fcmp instruction with +a uitofp instruction. This instruction +converts its input integer into a floating point value by treating the input +as an unsigned value. In contrast, if we used the sitofp instruction, the Kaleidoscope '<' +operator would return 0.0 and -1.0, depending on the input value.

    + +
    +
    +  | Ast.Call (callee, args) ->
    +      (* Look up the name in the module table. *)
    +      let callee =
    +        match lookup_function callee the_module with
    +        | Some callee -> callee
    +        | None -> raise (Error "unknown function referenced")
    +      in
    +      let params = params callee in
    +
    +      (* If argument mismatch error. *)
    +      if Array.length params == Array.length args then () else
    +        raise (Error "incorrect # arguments passed");
    +      let args = Array.map codegen_expr args in
    +      build_call callee args "calltmp" builder
    +
    +
    + +

    Code generation for function calls is quite straightforward with LLVM. The +code above initially does a function name lookup in the LLVM Module's symbol +table. Recall that the LLVM Module is the container that holds all of the +functions we are JIT'ing. By giving each function the same name as what the +user specifies, we can use the LLVM symbol table to resolve function names for +us.

    + +

    Once we have the function to call, we recursively codegen each argument that +is to be passed in, and create an LLVM call +instruction. Note that LLVM uses the native C calling conventions by +default, allowing these calls to also call into standard library functions like +"sin" and "cos", with no additional effort.

    + +

    This wraps up our handling of the four basic expressions that we have so far +in Kaleidoscope. Feel free to go in and add some more. For example, by +browsing the LLVM language reference you'll find +several other interesting instructions that are really easy to plug into our +basic framework.

    + +
    + + + + + +
    + +

    Code generation for prototypes and functions must handle a number of +details, which make their code less beautiful than expression code +generation, but allows us to illustrate some important points. First, lets +talk about code generation for prototypes: they are used both for function +bodies and external function declarations. The code starts with:

    + +
    +
    +let codegen_proto = function
    +  | Ast.Prototype (name, args) ->
    +      (* Make the function type: double(double,double) etc. *)
    +      let doubles = Array.make (Array.length args) double_type in
    +      let ft = function_type double_type doubles in
    +      let f =
    +        match lookup_function name the_module with
    +
    +
    + +

    This code packs a lot of power into a few lines. Note first that this +function returns a "Function*" instead of a "Value*" (although at the moment +they both are modeled by llvalue in ocaml). Because a "prototype" +really talks about the external interface for a function (not the value computed +by an expression), it makes sense for it to return the LLVM Function it +corresponds to when codegen'd.

    + +

    The call to Llvm.function_type creates the Llvm.llvalue +that should be used for a given Prototype. Since all function arguments in +Kaleidoscope are of type double, the first line creates a vector of "N" LLVM +double types. It then uses the Llvm.function_type method to create a +function type that takes "N" doubles as arguments, returns one double as a +result, and that is not vararg (that uses the function +Llvm.var_arg_function_type). Note that Types in LLVM are uniqued just +like Constants are, so you don't "new" a type, you "get" it.

    + +

    The final line above checks if the function has already been defined in +Codegen.the_module. If not, we will create it.

    + +
    +
    +        | None -> declare_function name ft the_module
    +
    +
    + +

    This indicates the type and name to use, as well as which module to insert +into. By default we assume a function has +Llvm.Linkage.ExternalLinkage. "external +linkage" means that the function may be defined outside the current module +and/or that it is callable by functions outside the module. The "name" +passed in is the name the user specified: this name is registered in +"Codegen.the_module"s symbol table, which is used by the function call +code above.

    + +

    In Kaleidoscope, I choose to allow redefinitions of functions in two cases: +first, we want to allow 'extern'ing a function more than once, as long as the +prototypes for the externs match (since all arguments have the same type, we +just have to check that the number of arguments match). Second, we want to +allow 'extern'ing a function and then defining a body for it. This is useful +when defining mutually recursive functions.

    + +
    +
    +        (* If 'f' conflicted, there was already something named 'name'. If it
    +         * has a body, don't allow redefinition or reextern. *)
    +        | Some f ->
    +            (* If 'f' already has a body, reject this. *)
    +            if Array.length (basic_blocks f) == 0 then () else
    +              raise (Error "redefinition of function");
    +
    +            (* If 'f' took a different number of arguments, reject. *)
    +            if Array.length (params f) == Array.length args then () else
    +              raise (Error "redefinition of function with different # args");
    +            f
    +      in
    +
    +
    + +

    In order to verify the logic above, we first check to see if the pre-existing +function is "empty". In this case, empty means that it has no basic blocks in +it, which means it has no body. If it has no body, it is a forward +declaration. Since we don't allow anything after a full definition of the +function, the code rejects this case. If the previous reference to a function +was an 'extern', we simply verify that the number of arguments for that +definition and this one match up. If not, we emit an error.

    + +
    +
    +      (* Set names for all arguments. *)
    +      Array.iteri (fun i a ->
    +        let n = args.(i) in
    +        set_value_name n a;
    +        Hashtbl.add named_values n a;
    +      ) (params f);
    +      f
    +
    +
    + +

    The last bit of code for prototypes loops over all of the arguments in the +function, setting the name of the LLVM Argument objects to match, and registering +the arguments in the Codegen.named_values map for future use by the +Ast.Variable variant. Once this is set up, it returns the Function +object to the caller. Note that we don't check for conflicting +argument names here (e.g. "extern foo(a b a)"). Doing so would be very +straight-forward with the mechanics we have already used above.

    + +
    +
    +let codegen_func = function
    +  | Ast.Function (proto, body) ->
    +      Hashtbl.clear named_values;
    +      let the_function = codegen_proto proto in
    +
    +
    + +

    Code generation for function definitions starts out simply enough: we just +codegen the prototype (Proto) and verify that it is ok. We then clear out the +Codegen.named_values map to make sure that there isn't anything in it +from the last function we compiled. Code generation of the prototype ensures +that there is an LLVM Function object that is ready to go for us.

    + +
    +
    +      (* Create a new basic block to start insertion into. *)
    +      let bb = append_block "entry" the_function in
    +      position_at_end bb builder;
    +
    +      try
    +        let ret_val = codegen_expr body in
    +
    +
    + +

    Now we get to the point where the Codegen.builder is set up. The +first line creates a new +basic block (named +"entry"), which is inserted into the_function. The second line then +tells the builder that new instructions should be inserted into the end of the +new basic block. Basic blocks in LLVM are an important part of functions that +define the Control Flow Graph. +Since we don't have any control flow, our functions will only contain one +block at this point. We'll fix this in Chapter +5 :).

    + +
    +
    +        let ret_val = codegen_expr body in
    +
    +        (* Finish off the function. *)
    +        let _ = build_ret ret_val builder in
    +
    +        (* Validate the generated code, checking for consistency. *)
    +        Llvm_analysis.assert_valid_function the_function;
    +
    +        the_function
    +
    +
    + +

    Once the insertion point is set up, we call the Codegen.codegen_func +method for the root expression of the function. If no error happens, this emits +code to compute the expression into the entry block and returns the value that +was computed. Assuming no error, we then create an LLVM ret instruction, which completes the function. +Once the function is built, we call +Llvm_analysis.assert_valid_function, which is provided by LLVM. This +function does a variety of consistency checks on the generated code, to +determine if our compiler is doing everything right. Using this is important: +it can catch a lot of bugs. Once the function is finished and validated, we +return it.

    + +
    +
    +      with e ->
    +        delete_function the_function;
    +        raise e
    +
    +
    + +

    The only piece left here is handling of the error case. For simplicity, we +handle this by merely deleting the function we produced with the +Llvm.delete_function method. This allows the user to redefine a +function that they incorrectly typed in before: if we didn't delete it, it +would live in the symbol table, with a body, preventing future redefinition.

    + +

    This code does have a bug, though. Since the Codegen.codegen_proto +can return a previously defined forward declaration, our code can actually delete +a forward declaration. There are a number of ways to fix this bug, see what you +can come up with! Here is a testcase:

    + +
    +
    +extern foo(a b);     # ok, defines foo.
    +def foo(a b) c;      # error, 'c' is invalid.
    +def bar() foo(1, 2); # error, unknown function "foo"
    +
    +
    + +
    + + + + + +
    + +

    +For now, code generation to LLVM doesn't really get us much, except that we can +look at the pretty IR calls. The sample code inserts calls to Codegen into the +"Toplevel.main_loop", and then dumps out the LLVM IR. This gives a +nice way to look at the LLVM IR for simple functions. For example: +

    + +
    +
    +ready> 4+5;
    +Read top-level expression:
    +define double @""() {
    +entry:
    +        %addtmp = add double 4.000000e+00, 5.000000e+00
    +        ret double %addtmp
    +}
    +
    +
    + +

    Note how the parser turns the top-level expression into anonymous functions +for us. This will be handy when we add JIT +support in the next chapter. Also note that the code is very literally +transcribed, no optimizations are being performed. We will +add optimizations explicitly +in the next chapter.

    + +
    +
    +ready> def foo(a b) a*a + 2*a*b + b*b;
    +Read function definition:
    +define double @foo(double %a, double %b) {
    +entry:
    +        %multmp = mul double %a, %a
    +        %multmp1 = mul double 2.000000e+00, %a
    +        %multmp2 = mul double %multmp1, %b
    +        %addtmp = add double %multmp, %multmp2
    +        %multmp3 = mul double %b, %b
    +        %addtmp4 = add double %addtmp, %multmp3
    +        ret double %addtmp4
    +}
    +
    +
    + +

    This shows some simple arithmetic. Notice the striking similarity to the +LLVM builder calls that we use to create the instructions.

    + +
    +
    +ready> def bar(a) foo(a, 4.0) + bar(31337);
    +Read function definition:
    +define double @bar(double %a) {
    +entry:
    +        %calltmp = call double @foo( double %a, double 4.000000e+00 )
    +        %calltmp1 = call double @bar( double 3.133700e+04 )
    +        %addtmp = add double %calltmp, %calltmp1
    +        ret double %addtmp
    +}
    +
    +
    + +

    This shows some function calls. Note that this function will take a long +time to execute if you call it. In the future we'll add conditional control +flow to actually make recursion useful :).

    + +
    +
    +ready> extern cos(x);
    +Read extern:
    +declare double @cos(double)
    +
    +ready> cos(1.234);
    +Read top-level expression:
    +define double @""() {
    +entry:
    +        %calltmp = call double @cos( double 1.234000e+00 )
    +        ret double %calltmp
    +}
    +
    +
    + +

    This shows an extern for the libm "cos" function, and a call to it.

    + + +
    +
    +ready> ^D
    +; ModuleID = 'my cool jit'
    +
    +define double @""() {
    +entry:
    +        %addtmp = add double 4.000000e+00, 5.000000e+00
    +        ret double %addtmp
    +}
    +
    +define double @foo(double %a, double %b) {
    +entry:
    +        %multmp = mul double %a, %a
    +        %multmp1 = mul double 2.000000e+00, %a
    +        %multmp2 = mul double %multmp1, %b
    +        %addtmp = add double %multmp, %multmp2
    +        %multmp3 = mul double %b, %b
    +        %addtmp4 = add double %addtmp, %multmp3
    +        ret double %addtmp4
    +}
    +
    +define double @bar(double %a) {
    +entry:
    +        %calltmp = call double @foo( double %a, double 4.000000e+00 )
    +        %calltmp1 = call double @bar( double 3.133700e+04 )
    +        %addtmp = add double %calltmp, %calltmp1
    +        ret double %addtmp
    +}
    +
    +declare double @cos(double)
    +
    +define double @""() {
    +entry:
    +        %calltmp = call double @cos( double 1.234000e+00 )
    +        ret double %calltmp
    +}
    +
    +
    + +

    When you quit the current demo, it dumps out the IR for the entire module +generated. Here you can see the big picture with all the functions referencing +each other.

    + +

    This wraps up the third chapter of the Kaleidoscope tutorial. Up next, we'll +describe how to add JIT codegen and optimizer +support to this so we can actually start running code!

    + +
    + + + + + + +
    + +

    +Here is the complete code listing for our running example, enhanced with the +LLVM code generator. Because this uses the LLVM libraries, we need to link +them in. To do this, we use the llvm-config tool to inform +our makefile/command line about which options to use:

    + +
    +
    +# Compile
    +ocamlbuild toy.byte
    +# Run
    +./toy.byte
    +
    +
    + +

    Here is the code:

    + +
    +
    _tags:
    +
    +
    +<{lexer,parser}.ml>: use_camlp4, pp(camlp4of)
    +<*.{byte,native}>: g++, use_llvm, use_llvm_analysis
    +
    +
    + +
    myocamlbuild.ml:
    +
    +
    +open Ocamlbuild_plugin;;
    +
    +ocaml_lib ~extern:true "llvm";;
    +ocaml_lib ~extern:true "llvm_analysis";;
    +
    +flag ["link"; "ocaml"; "g++"] (S[A"-cc"; A"g++"]);;
    +
    +
    + +
    token.ml:
    +
    +
    +(*===----------------------------------------------------------------------===
    + * Lexer Tokens
    + *===----------------------------------------------------------------------===*)
    +
    +(* The lexer returns these 'Kwd' if it is an unknown character, otherwise one of
    + * these others for known things. *)
    +type token =
    +  (* commands *)
    +  | Def | Extern
    +
    +  (* primary *)
    +  | Ident of string | Number of float
    +
    +  (* unknown *)
    +  | Kwd of char
    +
    +
    + +
    lexer.ml:
    +
    +
    +(*===----------------------------------------------------------------------===
    + * Lexer
    + *===----------------------------------------------------------------------===*)
    +
    +let rec lex = parser
    +  (* Skip any whitespace. *)
    +  | [< ' (' ' | '\n' | '\r' | '\t'); stream >] -> lex stream
    +
    +  (* identifier: [a-zA-Z][a-zA-Z0-9] *)
    +  | [< ' ('A' .. 'Z' | 'a' .. 'z' as c); stream >] ->
    +      let buffer = Buffer.create 1 in
    +      Buffer.add_char buffer c;
    +      lex_ident buffer stream
    +
    +  (* number: [0-9.]+ *)
    +  | [< ' ('0' .. '9' as c); stream >] ->
    +      let buffer = Buffer.create 1 in
    +      Buffer.add_char buffer c;
    +      lex_number buffer stream
    +
    +  (* Comment until end of line. *)
    +  | [< ' ('#'); stream >] ->
    +      lex_comment stream
    +
    +  (* Otherwise, just return the character as its ascii value. *)
    +  | [< 'c; stream >] ->
    +      [< 'Token.Kwd c; lex stream >]
    +
    +  (* end of stream. *)
    +  | [< >] -> [< >]
    +
    +and lex_number buffer = parser
    +  | [< ' ('0' .. '9' | '.' as c); stream >] ->
    +      Buffer.add_char buffer c;
    +      lex_number buffer stream
    +  | [< stream=lex >] ->
    +      [< 'Token.Number (float_of_string (Buffer.contents buffer)); stream >]
    +
    +and lex_ident buffer = parser
    +  | [< ' ('A' .. 'Z' | 'a' .. 'z' | '0' .. '9' as c); stream >] ->
    +      Buffer.add_char buffer c;
    +      lex_ident buffer stream
    +  | [< stream=lex >] ->
    +      match Buffer.contents buffer with
    +      | "def" -> [< 'Token.Def; stream >]
    +      | "extern" -> [< 'Token.Extern; stream >]
    +      | id -> [< 'Token.Ident id; stream >]
    +
    +and lex_comment = parser
    +  | [< ' ('\n'); stream=lex >] -> stream
    +  | [< 'c; e=lex_comment >] -> e
    +  | [< >] -> [< >]
    +
    +
    + +
    ast.ml:
    +
    +
    +(*===----------------------------------------------------------------------===
    + * Abstract Syntax Tree (aka Parse Tree)
    + *===----------------------------------------------------------------------===*)
    +
    +(* expr - Base type for all expression nodes. *)
    +type expr =
    +  (* variant for numeric literals like "1.0". *)
    +  | Number of float
    +
    +  (* variant for referencing a variable, like "a". *)
    +  | Variable of string
    +
    +  (* variant for a binary operator. *)
    +  | Binary of char * expr * expr
    +
    +  (* variant for function calls. *)
    +  | Call of string * expr array
    +
    +(* proto - This type represents the "prototype" for a function, which captures
    + * its name, and its argument names (thus implicitly the number of arguments the
    + * function takes). *)
    +type proto = Prototype of string * string array
    +
    +(* func - This type represents a function definition itself. *)
    +type func = Function of proto * expr
    +
    +
    + +
    parser.ml:
    +
    +
    +(*===---------------------------------------------------------------------===
    + * Parser
    + *===---------------------------------------------------------------------===*)
    +
    +(* binop_precedence - This holds the precedence for each binary operator that is
    + * defined *)
    +let binop_precedence:(char, int) Hashtbl.t = Hashtbl.create 10
    +
    +(* precedence - Get the precedence of the pending binary operator token. *)
    +let precedence c = try Hashtbl.find binop_precedence c with Not_found -> -1
    +
    +(* primary
    + *   ::= identifier
    + *   ::= numberexpr
    + *   ::= parenexpr *)
    +let rec parse_primary = parser
    +  (* numberexpr ::= number *)
    +  | [< 'Token.Number n >] -> Ast.Number n
    +
    +  (* parenexpr ::= '(' expression ')' *)
    +  | [< 'Token.Kwd '('; e=parse_expr; 'Token.Kwd ')' ?? "expected ')'" >] -> e
    +
    +  (* identifierexpr
    +   *   ::= identifier
    +   *   ::= identifier '(' argumentexpr ')' *)
    +  | [< 'Token.Ident id; stream >] ->
    +      let rec parse_args accumulator = parser
    +        | [< e=parse_expr; stream >] ->
    +            begin parser
    +              | [< 'Token.Kwd ','; e=parse_args (e :: accumulator) >] -> e
    +              | [< >] -> e :: accumulator
    +            end stream
    +        | [< >] -> accumulator
    +      in
    +      let rec parse_ident id = parser
    +        (* Call. *)
    +        | [< 'Token.Kwd '(';
    +             args=parse_args [];
    +             'Token.Kwd ')' ?? "expected ')'">] ->
    +            Ast.Call (id, Array.of_list (List.rev args))
    +
    +        (* Simple variable ref. *)
    +        | [< >] -> Ast.Variable id
    +      in
    +      parse_ident id stream
    +
    +  | [< >] -> raise (Stream.Error "unknown token when expecting an expression.")
    +
    +(* binoprhs
    + *   ::= ('+' primary)* *)
    +and parse_bin_rhs expr_prec lhs stream =
    +  match Stream.peek stream with
    +  (* If this is a binop, find its precedence. *)
    +  | Some (Token.Kwd c) when Hashtbl.mem binop_precedence c ->
    +      let token_prec = precedence c in
    +
    +      (* If this is a binop that binds at least as tightly as the current binop,
    +       * consume it, otherwise we are done. *)
    +      if token_prec < expr_prec then lhs else begin
    +        (* Eat the binop. *)
    +        Stream.junk stream;
    +
    +        (* Parse the primary expression after the binary operator. *)
    +        let rhs = parse_primary stream in
    +
    +        (* Okay, we know this is a binop. *)
    +        let rhs =
    +          match Stream.peek stream with
    +          | Some (Token.Kwd c2) ->
    +              (* If BinOp binds less tightly with rhs than the operator after
    +               * rhs, let the pending operator take rhs as its lhs. *)
    +              let next_prec = precedence c2 in
    +              if token_prec < next_prec
    +              then parse_bin_rhs (token_prec + 1) rhs stream
    +              else rhs
    +          | _ -> rhs
    +        in
    +
    +        (* Merge lhs/rhs. *)
    +        let lhs = Ast.Binary (c, lhs, rhs) in
    +        parse_bin_rhs expr_prec lhs stream
    +      end
    +  | _ -> lhs
    +
    +(* expression
    + *   ::= primary binoprhs *)
    +and parse_expr = parser
    +  | [< lhs=parse_primary; stream >] -> parse_bin_rhs 0 lhs stream
    +
    +(* prototype
    + *   ::= id '(' id* ')' *)
    +let parse_prototype =
    +  let rec parse_args accumulator = parser
    +    | [< 'Token.Ident id; e=parse_args (id::accumulator) >] -> e
    +    | [< >] -> accumulator
    +  in
    +
    +  parser
    +  | [< 'Token.Ident id;
    +       'Token.Kwd '(' ?? "expected '(' in prototype";
    +       args=parse_args [];
    +       'Token.Kwd ')' ?? "expected ')' in prototype" >] ->
    +      (* success. *)
    +      Ast.Prototype (id, Array.of_list (List.rev args))
    +
    +  | [< >] ->
    +      raise (Stream.Error "expected function name in prototype")
    +
    +(* definition ::= 'def' prototype expression *)
    +let parse_definition = parser
    +  | [< 'Token.Def; p=parse_prototype; e=parse_expr >] ->
    +      Ast.Function (p, e)
    +
    +(* toplevelexpr ::= expression *)
    +let parse_toplevel = parser
    +  | [< e=parse_expr >] ->
    +      (* Make an anonymous proto. *)
    +      Ast.Function (Ast.Prototype ("", [||]), e)
    +
    +(*  external ::= 'extern' prototype *)
    +let parse_extern = parser
    +  | [< 'Token.Extern; e=parse_prototype >] -> e
    +
    +
    + +
    codegen.ml:
    +
    +
    +(*===----------------------------------------------------------------------===
    + * Code Generation
    + *===----------------------------------------------------------------------===*)
    +
    +open Llvm
    +
    +exception Error of string
    +
    +let context = global_context ()
    +let the_module = create_module context "my cool jit"
    +let builder = builder context
    +let named_values:(string, llvalue) Hashtbl.t = Hashtbl.create 10
    +
    +let rec codegen_expr = function
    +  | Ast.Number n -> const_float double_type n
    +  | Ast.Variable name ->
    +      (try Hashtbl.find named_values name with
    +        | Not_found -> raise (Error "unknown variable name"))
    +  | Ast.Binary (op, lhs, rhs) ->
    +      let lhs_val = codegen_expr lhs in
    +      let rhs_val = codegen_expr rhs in
    +      begin
    +        match op with
    +        | '+' -> build_add lhs_val rhs_val "addtmp" builder
    +        | '-' -> build_sub lhs_val rhs_val "subtmp" builder
    +        | '*' -> build_mul lhs_val rhs_val "multmp" builder
    +        | '<' ->
    +            (* Convert bool 0/1 to double 0.0 or 1.0 *)
    +            let i = build_fcmp Fcmp.Ult lhs_val rhs_val "cmptmp" builder in
    +            build_uitofp i double_type "booltmp" builder
    +        | _ -> raise (Error "invalid binary operator")
    +      end
    +  | Ast.Call (callee, args) ->
    +      (* Look up the name in the module table. *)
    +      let callee =
    +        match lookup_function callee the_module with
    +        | Some callee -> callee
    +        | None -> raise (Error "unknown function referenced")
    +      in
    +      let params = params callee in
    +
    +      (* If argument mismatch error. *)
    +      if Array.length params == Array.length args then () else
    +        raise (Error "incorrect # arguments passed");
    +      let args = Array.map codegen_expr args in
    +      build_call callee args "calltmp" builder
    +
    +let codegen_proto = function
    +  | Ast.Prototype (name, args) ->
    +      (* Make the function type: double(double,double) etc. *)
    +      let doubles = Array.make (Array.length args) double_type in
    +      let ft = function_type double_type doubles in
    +      let f =
    +        match lookup_function name the_module with
    +        | None -> declare_function name ft the_module
    +
    +        (* If 'f' conflicted, there was already something named 'name'. If it
    +         * has a body, don't allow redefinition or reextern. *)
    +        | Some f ->
    +            (* If 'f' already has a body, reject this. *)
    +            if block_begin f <> At_end f then
    +              raise (Error "redefinition of function");
    +
    +            (* If 'f' took a different number of arguments, reject. *)
    +            if element_type (type_of f) <> ft then
    +              raise (Error "redefinition of function with different # args");
    +            f
    +      in
    +
    +      (* Set names for all arguments. *)
    +      Array.iteri (fun i a ->
    +        let n = args.(i) in
    +        set_value_name n a;
    +        Hashtbl.add named_values n a;
    +      ) (params f);
    +      f
    +
    +let codegen_func = function
    +  | Ast.Function (proto, body) ->
    +      Hashtbl.clear named_values;
    +      let the_function = codegen_proto proto in
    +
    +      (* Create a new basic block to start insertion into. *)
    +      let bb = append_block "entry" the_function in
    +      position_at_end bb builder;
    +
    +      try
    +        let ret_val = codegen_expr body in
    +
    +        (* Finish off the function. *)
    +        let _ = build_ret ret_val builder in
    +
    +        (* Validate the generated code, checking for consistency. *)
    +        Llvm_analysis.assert_valid_function the_function;
    +
    +        the_function
    +      with e ->
    +        delete_function the_function;
    +        raise e
    +
    +
    + +
    toplevel.ml:
    +
    +
    +(*===----------------------------------------------------------------------===
    + * Top-Level parsing and JIT Driver
    + *===----------------------------------------------------------------------===*)
    +
    +open Llvm
    +
    +(* top ::= definition | external | expression | ';' *)
    +let rec main_loop stream =
    +  match Stream.peek stream with
    +  | None -> ()
    +
    +  (* ignore top-level semicolons. *)
    +  | Some (Token.Kwd ';') ->
    +      Stream.junk stream;
    +      main_loop stream
    +
    +  | Some token ->
    +      begin
    +        try match token with
    +        | Token.Def ->
    +            let e = Parser.parse_definition stream in
    +            print_endline "parsed a function definition.";
    +            dump_value (Codegen.codegen_func e);
    +        | Token.Extern ->
    +            let e = Parser.parse_extern stream in
    +            print_endline "parsed an extern.";
    +            dump_value (Codegen.codegen_proto e);
    +        | _ ->
    +            (* Evaluate a top-level expression into an anonymous function. *)
    +            let e = Parser.parse_toplevel stream in
    +            print_endline "parsed a top-level expr";
    +            dump_value (Codegen.codegen_func e);
    +        with Stream.Error s | Codegen.Error s ->
    +          (* Skip token for error recovery. *)
    +          Stream.junk stream;
    +          print_endline s;
    +      end;
    +      print_string "ready> "; flush stdout;
    +      main_loop stream
    +
    +
    + +
    toy.ml:
    +
    +
    +(*===----------------------------------------------------------------------===
    + * Main driver code.
    + *===----------------------------------------------------------------------===*)
    +
    +open Llvm
    +
    +let main () =
    +  (* Install standard binary operators.
    +   * 1 is the lowest precedence. *)
    +  Hashtbl.add Parser.binop_precedence '<' 10;
    +  Hashtbl.add Parser.binop_precedence '+' 20;
    +  Hashtbl.add Parser.binop_precedence '-' 20;
    +  Hashtbl.add Parser.binop_precedence '*' 40;    (* highest. *)
    +
    +  (* Prime the first token. *)
    +  print_string "ready> "; flush stdout;
    +  let stream = Lexer.lex (Stream.of_channel stdin) in
    +
    +  (* Run the main "interpreter loop" now. *)
    +  Toplevel.main_loop stream;
    +
    +  (* Print out all the generated code. *)
    +  dump_module Codegen.the_module
    +;;
    +
    +main ()
    +
    +
    +
    + +Next: Adding JIT and Optimizer Support +
    + + +
    +
    + Valid CSS! + Valid HTML 4.01! + + Chris Lattner
    + Erick Tryzelaar
    + The LLVM Compiler Infrastructure
    + Last modified: $Date: 2007-10-17 11:05:13 -0700 (Wed, 17 Oct 2007) $ +
    + + diff --git a/libclamav/c++/llvm/docs/tutorial/OCamlLangImpl4.html b/libclamav/c++/llvm/docs/tutorial/OCamlLangImpl4.html new file mode 100644 index 000000000..543e12fe2 --- /dev/null +++ b/libclamav/c++/llvm/docs/tutorial/OCamlLangImpl4.html @@ -0,0 +1,1038 @@ + + + + + Kaleidoscope: Adding JIT and Optimizer Support + + + + + + + + +
    Kaleidoscope: Adding JIT and Optimizer Support
    + + + +
    +

    + Written by Chris Lattner + and Erick Tryzelaar +

    +
    + + + + + +
    + +

    Welcome to Chapter 4 of the "Implementing a language +with LLVM" tutorial. Chapters 1-3 described the implementation of a simple +language and added support for generating LLVM IR. This chapter describes +two new techniques: adding optimizer support to your language, and adding JIT +compiler support. These additions will demonstrate how to get nice, efficient code +for the Kaleidoscope language.

    + +
    + + + + + +
    + +

    Note: the default IRBuilder now always includes the constant +folding optimisations below.

    + +

    +Our demonstration for Chapter 3 is elegant and easy to extend. Unfortunately, +it does not produce wonderful code. For example, when compiling simple code, +we don't get obvious optimizations:

    + +
    +
    +ready> def test(x) 1+2+x;
    +Read function definition:
    +define double @test(double %x) {
    +entry:
    +        %addtmp = add double 1.000000e+00, 2.000000e+00
    +        %addtmp1 = add double %addtmp, %x
    +        ret double %addtmp1
    +}
    +
    +
    + +

    This code is a very, very literal transcription of the AST built by parsing +the input. As such, this transcription lacks optimizations like constant folding +(we'd like to get "add x, 3.0" in the example above) as well as other +more important optimizations. Constant folding, in particular, is a very common +and very important optimization: so much so that many language implementors +implement constant folding support in their AST representation.

    + +

    With LLVM, you don't need this support in the AST. Since all calls to build +LLVM IR go through the LLVM builder, it would be nice if the builder itself +checked to see if there was a constant folding opportunity when you call it. +If so, it could just do the constant fold and return the constant instead of +creating an instruction. This is exactly what the LLVMFoldingBuilder +class does. + +

    All we did was switch from LLVMBuilder to +LLVMFoldingBuilder. Though we change no other code, we now have all of our +instructions implicitly constant folded without us having to do anything +about it. For example, the input above now compiles to:

    + +
    +
    +ready> def test(x) 1+2+x;
    +Read function definition:
    +define double @test(double %x) {
    +entry:
    +        %addtmp = add double 3.000000e+00, %x
    +        ret double %addtmp
    +}
    +
    +
    + +

    Well, that was easy :). In practice, we recommend always using +LLVMFoldingBuilder when generating code like this. It has no +"syntactic overhead" for its use (you don't have to uglify your compiler with +constant checks everywhere) and it can dramatically reduce the amount of +LLVM IR that is generated in some cases (particular for languages with a macro +preprocessor or that use a lot of constants).

    + +

    On the other hand, the LLVMFoldingBuilder is limited by the fact +that it does all of its analysis inline with the code as it is built. If you +take a slightly more complex example:

    + +
    +
    +ready> def test(x) (1+2+x)*(x+(1+2));
    +ready> Read function definition:
    +define double @test(double %x) {
    +entry:
    +        %addtmp = add double 3.000000e+00, %x
    +        %addtmp1 = add double %x, 3.000000e+00
    +        %multmp = mul double %addtmp, %addtmp1
    +        ret double %multmp
    +}
    +
    +
    + +

    In this case, the LHS and RHS of the multiplication are the same value. We'd +really like to see this generate "tmp = x+3; result = tmp*tmp;" instead +of computing "x*3" twice.

    + +

    Unfortunately, no amount of local analysis will be able to detect and correct +this. This requires two transformations: reassociation of expressions (to +make the add's lexically identical) and Common Subexpression Elimination (CSE) +to delete the redundant add instruction. Fortunately, LLVM provides a broad +range of optimizations that you can use, in the form of "passes".

    + +
    + + + + + +
    + +

    LLVM provides many optimization passes, which do many different sorts of +things and have different tradeoffs. Unlike other systems, LLVM doesn't hold +to the mistaken notion that one set of optimizations is right for all languages +and for all situations. LLVM allows a compiler implementor to make complete +decisions about what optimizations to use, in which order, and in what +situation.

    + +

    As a concrete example, LLVM supports both "whole module" passes, which look +across as large of body of code as they can (often a whole file, but if run +at link time, this can be a substantial portion of the whole program). It also +supports and includes "per-function" passes which just operate on a single +function at a time, without looking at other functions. For more information +on passes and how they are run, see the How +to Write a Pass document and the List of LLVM +Passes.

    + +

    For Kaleidoscope, we are currently generating functions on the fly, one at +a time, as the user types them in. We aren't shooting for the ultimate +optimization experience in this setting, but we also want to catch the easy and +quick stuff where possible. As such, we will choose to run a few per-function +optimizations as the user types the function in. If we wanted to make a "static +Kaleidoscope compiler", we would use exactly the code we have now, except that +we would defer running the optimizer until the entire file has been parsed.

    + +

    In order to get per-function optimizations going, we need to set up a +Llvm.PassManager to hold and +organize the LLVM optimizations that we want to run. Once we have that, we can +add a set of optimizations to run. The code looks like this:

    + +
    +
    +  (* Create the JIT. *)
    +  let the_module_provider = ModuleProvider.create Codegen.the_module in
    +  let the_execution_engine = ExecutionEngine.create the_module_provider in
    +  let the_fpm = PassManager.create_function the_module_provider in
    +
    +  (* Set up the optimizer pipeline.  Start with registering info about how the
    +   * target lays out data structures. *)
    +  TargetData.add (ExecutionEngine.target_data the_execution_engine) the_fpm;
    +
    +  (* Do simple "peephole" optimizations and bit-twiddling optzn. *)
    +  add_instruction_combining the_fpm;
    +
    +  (* reassociate expressions. *)
    +  add_reassociation the_fpm;
    +
    +  (* Eliminate Common SubExpressions. *)
    +  add_gvn the_fpm;
    +
    +  (* Simplify the control flow graph (deleting unreachable blocks, etc). *)
    +  add_cfg_simplification the_fpm;
    +
    +  ignore (PassManager.initialize the_fpm);
    +
    +  (* Run the main "interpreter loop" now. *)
    +  Toplevel.main_loop the_fpm the_execution_engine stream;
    +
    +
    + +

    This code defines two values, an Llvm.llmoduleprovider and a +Llvm.PassManager.t. The former is basically a wrapper around our +Llvm.llmodule that the Llvm.PassManager.t requires. It +provides certain flexibility that we're not going to take advantage of here, +so I won't dive into any details about it.

    + +

    The meat of the matter here, is the definition of "the_fpm". It +requires a pointer to the the_module (through the +the_module_provider) to construct itself. Once it is set up, we use a +series of "add" calls to add a bunch of LLVM passes. The first pass is +basically boilerplate, it adds a pass so that later optimizations know how the +data structures in the program are laid out. The +"the_execution_engine" variable is related to the JIT, which we will +get to in the next section.

    + +

    In this case, we choose to add 4 optimization passes. The passes we chose +here are a pretty standard set of "cleanup" optimizations that are useful for +a wide variety of code. I won't delve into what they do but, believe me, +they are a good starting place :).

    + +

    Once the Llvm.PassManager. is set up, we need to make use of it. +We do this by running it after our newly created function is constructed (in +Codegen.codegen_func), but before it is returned to the client:

    + +
    +
    +let codegen_func the_fpm = function
    +      ...
    +      try
    +        let ret_val = codegen_expr body in
    +
    +        (* Finish off the function. *)
    +        let _ = build_ret ret_val builder in
    +
    +        (* Validate the generated code, checking for consistency. *)
    +        Llvm_analysis.assert_valid_function the_function;
    +
    +        (* Optimize the function. *)
    +        let _ = PassManager.run_function the_function the_fpm in
    +
    +        the_function
    +
    +
    + +

    As you can see, this is pretty straightforward. The the_fpm +optimizes and updates the LLVM Function* in place, improving (hopefully) its +body. With this in place, we can try our test above again:

    + +
    +
    +ready> def test(x) (1+2+x)*(x+(1+2));
    +ready> Read function definition:
    +define double @test(double %x) {
    +entry:
    +        %addtmp = add double %x, 3.000000e+00
    +        %multmp = mul double %addtmp, %addtmp
    +        ret double %multmp
    +}
    +
    +
    + +

    As expected, we now get our nicely optimized code, saving a floating point +add instruction from every execution of this function.

    + +

    LLVM provides a wide variety of optimizations that can be used in certain +circumstances. Some documentation about the various +passes is available, but it isn't very complete. Another good source of +ideas can come from looking at the passes that llvm-gcc or +llvm-ld run to get started. The "opt" tool allows you to +experiment with passes from the command line, so you can see if they do +anything.

    + +

    Now that we have reasonable code coming out of our front-end, lets talk about +executing it!

    + +
    + + + + + +
    + +

    Code that is available in LLVM IR can have a wide variety of tools +applied to it. For example, you can run optimizations on it (as we did above), +you can dump it out in textual or binary forms, you can compile the code to an +assembly file (.s) for some target, or you can JIT compile it. The nice thing +about the LLVM IR representation is that it is the "common currency" between +many different parts of the compiler. +

    + +

    In this section, we'll add JIT compiler support to our interpreter. The +basic idea that we want for Kaleidoscope is to have the user enter function +bodies as they do now, but immediately evaluate the top-level expressions they +type in. For example, if they type in "1 + 2;", we should evaluate and print +out 3. If they define a function, they should be able to call it from the +command line.

    + +

    In order to do this, we first declare and initialize the JIT. This is done +by adding a global variable and a call in main:

    + +
    +
    +...
    +let main () =
    +  ...
    +  (* Create the JIT. *)
    +  let the_module_provider = ModuleProvider.create Codegen.the_module in
    +  let the_execution_engine = ExecutionEngine.create the_module_provider in
    +  ...
    +
    +
    + +

    This creates an abstract "Execution Engine" which can be either a JIT +compiler or the LLVM interpreter. LLVM will automatically pick a JIT compiler +for you if one is available for your platform, otherwise it will fall back to +the interpreter.

    + +

    Once the Llvm_executionengine.ExecutionEngine.t is created, the JIT +is ready to be used. There are a variety of APIs that are useful, but the +simplest one is the "Llvm_executionengine.ExecutionEngine.run_function" +function. This method JIT compiles the specified LLVM Function and returns a +function pointer to the generated machine code. In our case, this means that we +can change the code that parses a top-level expression to look like this:

    + +
    +
    +            (* Evaluate a top-level expression into an anonymous function. *)
    +            let e = Parser.parse_toplevel stream in
    +            print_endline "parsed a top-level expr";
    +            let the_function = Codegen.codegen_func the_fpm e in
    +            dump_value the_function;
    +
    +            (* JIT the function, returning a function pointer. *)
    +            let result = ExecutionEngine.run_function the_function [||]
    +              the_execution_engine in
    +
    +            print_string "Evaluated to ";
    +            print_float (GenericValue.as_float double_type result);
    +            print_newline ();
    +
    +
    + +

    Recall that we compile top-level expressions into a self-contained LLVM +function that takes no arguments and returns the computed double. Because the +LLVM JIT compiler matches the native platform ABI, this means that you can just +cast the result pointer to a function pointer of that type and call it directly. +This means, there is no difference between JIT compiled code and native machine +code that is statically linked into your application.

    + +

    With just these two changes, lets see how Kaleidoscope works now!

    + +
    +
    +ready> 4+5;
    +define double @""() {
    +entry:
    +        ret double 9.000000e+00
    +}
    +
    +Evaluated to 9.000000
    +
    +
    + +

    Well this looks like it is basically working. The dump of the function +shows the "no argument function that always returns double" that we synthesize +for each top level expression that is typed in. This demonstrates very basic +functionality, but can we do more?

    + +
    +
    +ready> def testfunc(x y) x + y*2; 
    +Read function definition:
    +define double @testfunc(double %x, double %y) {
    +entry:
    +        %multmp = mul double %y, 2.000000e+00
    +        %addtmp = add double %multmp, %x
    +        ret double %addtmp
    +}
    +
    +ready> testfunc(4, 10);
    +define double @""() {
    +entry:
    +        %calltmp = call double @testfunc( double 4.000000e+00, double 1.000000e+01 )
    +        ret double %calltmp
    +}
    +
    +Evaluated to 24.000000
    +
    +
    + +

    This illustrates that we can now call user code, but there is something a bit +subtle going on here. Note that we only invoke the JIT on the anonymous +functions that call testfunc, but we never invoked it +on testfunc itself. What actually happened here is that the JIT +scanned for all non-JIT'd functions transitively called from the anonymous +function and compiled all of them before returning +from run_function.

    + +

    The JIT provides a number of other more advanced interfaces for things like +freeing allocated machine code, rejit'ing functions to update them, etc. +However, even with this simple code, we get some surprisingly powerful +capabilities - check this out (I removed the dump of the anonymous functions, +you should get the idea by now :) :

    + +
    +
    +ready> extern sin(x);
    +Read extern:
    +declare double @sin(double)
    +
    +ready> extern cos(x);
    +Read extern:
    +declare double @cos(double)
    +
    +ready> sin(1.0);
    +Evaluated to 0.841471
    +
    +ready> def foo(x) sin(x)*sin(x) + cos(x)*cos(x);
    +Read function definition:
    +define double @foo(double %x) {
    +entry:
    +        %calltmp = call double @sin( double %x )
    +        %multmp = mul double %calltmp, %calltmp
    +        %calltmp2 = call double @cos( double %x )
    +        %multmp4 = mul double %calltmp2, %calltmp2
    +        %addtmp = add double %multmp, %multmp4
    +        ret double %addtmp
    +}
    +
    +ready> foo(4.0);
    +Evaluated to 1.000000
    +
    +
    + +

    Whoa, how does the JIT know about sin and cos? The answer is surprisingly +simple: in this example, the JIT started execution of a function and got to a +function call. It realized that the function was not yet JIT compiled and +invoked the standard set of routines to resolve the function. In this case, +there is no body defined for the function, so the JIT ended up calling +"dlsym("sin")" on the Kaleidoscope process itself. Since +"sin" is defined within the JIT's address space, it simply patches up +calls in the module to call the libm version of sin directly.

    + +

    The LLVM JIT provides a number of interfaces (look in the +llvm_executionengine.mli file) for controlling how unknown functions +get resolved. It allows you to establish explicit mappings between IR objects +and addresses (useful for LLVM global variables that you want to map to static +tables, for example), allows you to dynamically decide on the fly based on the +function name, and even allows you to have the JIT compile functions lazily the +first time they're called.

    + +

    One interesting application of this is that we can now extend the language +by writing arbitrary C code to implement operations. For example, if we add: +

    + +
    +
    +/* putchard - putchar that takes a double and returns 0. */
    +extern "C"
    +double putchard(double X) {
    +  putchar((char)X);
    +  return 0;
    +}
    +
    +
    + +

    Now we can produce simple output to the console by using things like: +"extern putchard(x); putchard(120);", which prints a lowercase 'x' on +the console (120 is the ASCII code for 'x'). Similar code could be used to +implement file I/O, console input, and many other capabilities in +Kaleidoscope.

    + +

    This completes the JIT and optimizer chapter of the Kaleidoscope tutorial. At +this point, we can compile a non-Turing-complete programming language, optimize +and JIT compile it in a user-driven way. Next up we'll look into extending the language with control flow +constructs, tackling some interesting LLVM IR issues along the way.

    + +
    + + + + + +
    + +

    +Here is the complete code listing for our running example, enhanced with the +LLVM JIT and optimizer. To build this example, use: +

    + +
    +
    +# Compile
    +ocamlbuild toy.byte
    +# Run
    +./toy.byte
    +
    +
    + +

    Here is the code:

    + +
    +
    _tags:
    +
    +
    +<{lexer,parser}.ml>: use_camlp4, pp(camlp4of)
    +<*.{byte,native}>: g++, use_llvm, use_llvm_analysis
    +<*.{byte,native}>: use_llvm_executionengine, use_llvm_target
    +<*.{byte,native}>: use_llvm_scalar_opts, use_bindings
    +
    +
    + +
    myocamlbuild.ml:
    +
    +
    +open Ocamlbuild_plugin;;
    +
    +ocaml_lib ~extern:true "llvm";;
    +ocaml_lib ~extern:true "llvm_analysis";;
    +ocaml_lib ~extern:true "llvm_executionengine";;
    +ocaml_lib ~extern:true "llvm_target";;
    +ocaml_lib ~extern:true "llvm_scalar_opts";;
    +
    +flag ["link"; "ocaml"; "g++"] (S[A"-cc"; A"g++"]);;
    +dep ["link"; "ocaml"; "use_bindings"] ["bindings.o"];;
    +
    +
    + +
    token.ml:
    +
    +
    +(*===----------------------------------------------------------------------===
    + * Lexer Tokens
    + *===----------------------------------------------------------------------===*)
    +
    +(* The lexer returns these 'Kwd' if it is an unknown character, otherwise one of
    + * these others for known things. *)
    +type token =
    +  (* commands *)
    +  | Def | Extern
    +
    +  (* primary *)
    +  | Ident of string | Number of float
    +
    +  (* unknown *)
    +  | Kwd of char
    +
    +
    + +
    lexer.ml:
    +
    +
    +(*===----------------------------------------------------------------------===
    + * Lexer
    + *===----------------------------------------------------------------------===*)
    +
    +let rec lex = parser
    +  (* Skip any whitespace. *)
    +  | [< ' (' ' | '\n' | '\r' | '\t'); stream >] -> lex stream
    +
    +  (* identifier: [a-zA-Z][a-zA-Z0-9] *)
    +  | [< ' ('A' .. 'Z' | 'a' .. 'z' as c); stream >] ->
    +      let buffer = Buffer.create 1 in
    +      Buffer.add_char buffer c;
    +      lex_ident buffer stream
    +
    +  (* number: [0-9.]+ *)
    +  | [< ' ('0' .. '9' as c); stream >] ->
    +      let buffer = Buffer.create 1 in
    +      Buffer.add_char buffer c;
    +      lex_number buffer stream
    +
    +  (* Comment until end of line. *)
    +  | [< ' ('#'); stream >] ->
    +      lex_comment stream
    +
    +  (* Otherwise, just return the character as its ascii value. *)
    +  | [< 'c; stream >] ->
    +      [< 'Token.Kwd c; lex stream >]
    +
    +  (* end of stream. *)
    +  | [< >] -> [< >]
    +
    +and lex_number buffer = parser
    +  | [< ' ('0' .. '9' | '.' as c); stream >] ->
    +      Buffer.add_char buffer c;
    +      lex_number buffer stream
    +  | [< stream=lex >] ->
    +      [< 'Token.Number (float_of_string (Buffer.contents buffer)); stream >]
    +
    +and lex_ident buffer = parser
    +  | [< ' ('A' .. 'Z' | 'a' .. 'z' | '0' .. '9' as c); stream >] ->
    +      Buffer.add_char buffer c;
    +      lex_ident buffer stream
    +  | [< stream=lex >] ->
    +      match Buffer.contents buffer with
    +      | "def" -> [< 'Token.Def; stream >]
    +      | "extern" -> [< 'Token.Extern; stream >]
    +      | id -> [< 'Token.Ident id; stream >]
    +
    +and lex_comment = parser
    +  | [< ' ('\n'); stream=lex >] -> stream
    +  | [< 'c; e=lex_comment >] -> e
    +  | [< >] -> [< >]
    +
    +
    + +
    ast.ml:
    +
    +
    +(*===----------------------------------------------------------------------===
    + * Abstract Syntax Tree (aka Parse Tree)
    + *===----------------------------------------------------------------------===*)
    +
    +(* expr - Base type for all expression nodes. *)
    +type expr =
    +  (* variant for numeric literals like "1.0". *)
    +  | Number of float
    +
    +  (* variant for referencing a variable, like "a". *)
    +  | Variable of string
    +
    +  (* variant for a binary operator. *)
    +  | Binary of char * expr * expr
    +
    +  (* variant for function calls. *)
    +  | Call of string * expr array
    +
    +(* proto - This type represents the "prototype" for a function, which captures
    + * its name, and its argument names (thus implicitly the number of arguments the
    + * function takes). *)
    +type proto = Prototype of string * string array
    +
    +(* func - This type represents a function definition itself. *)
    +type func = Function of proto * expr
    +
    +
    + +
    parser.ml:
    +
    +
    +(*===---------------------------------------------------------------------===
    + * Parser
    + *===---------------------------------------------------------------------===*)
    +
    +(* binop_precedence - This holds the precedence for each binary operator that is
    + * defined *)
    +let binop_precedence:(char, int) Hashtbl.t = Hashtbl.create 10
    +
    +(* precedence - Get the precedence of the pending binary operator token. *)
    +let precedence c = try Hashtbl.find binop_precedence c with Not_found -> -1
    +
    +(* primary
    + *   ::= identifier
    + *   ::= numberexpr
    + *   ::= parenexpr *)
    +let rec parse_primary = parser
    +  (* numberexpr ::= number *)
    +  | [< 'Token.Number n >] -> Ast.Number n
    +
    +  (* parenexpr ::= '(' expression ')' *)
    +  | [< 'Token.Kwd '('; e=parse_expr; 'Token.Kwd ')' ?? "expected ')'" >] -> e
    +
    +  (* identifierexpr
    +   *   ::= identifier
    +   *   ::= identifier '(' argumentexpr ')' *)
    +  | [< 'Token.Ident id; stream >] ->
    +      let rec parse_args accumulator = parser
    +        | [< e=parse_expr; stream >] ->
    +            begin parser
    +              | [< 'Token.Kwd ','; e=parse_args (e :: accumulator) >] -> e
    +              | [< >] -> e :: accumulator
    +            end stream
    +        | [< >] -> accumulator
    +      in
    +      let rec parse_ident id = parser
    +        (* Call. *)
    +        | [< 'Token.Kwd '(';
    +             args=parse_args [];
    +             'Token.Kwd ')' ?? "expected ')'">] ->
    +            Ast.Call (id, Array.of_list (List.rev args))
    +
    +        (* Simple variable ref. *)
    +        | [< >] -> Ast.Variable id
    +      in
    +      parse_ident id stream
    +
    +  | [< >] -> raise (Stream.Error "unknown token when expecting an expression.")
    +
    +(* binoprhs
    + *   ::= ('+' primary)* *)
    +and parse_bin_rhs expr_prec lhs stream =
    +  match Stream.peek stream with
    +  (* If this is a binop, find its precedence. *)
    +  | Some (Token.Kwd c) when Hashtbl.mem binop_precedence c ->
    +      let token_prec = precedence c in
    +
    +      (* If this is a binop that binds at least as tightly as the current binop,
    +       * consume it, otherwise we are done. *)
    +      if token_prec < expr_prec then lhs else begin
    +        (* Eat the binop. *)
    +        Stream.junk stream;
    +
    +        (* Parse the primary expression after the binary operator. *)
    +        let rhs = parse_primary stream in
    +
    +        (* Okay, we know this is a binop. *)
    +        let rhs =
    +          match Stream.peek stream with
    +          | Some (Token.Kwd c2) ->
    +              (* If BinOp binds less tightly with rhs than the operator after
    +               * rhs, let the pending operator take rhs as its lhs. *)
    +              let next_prec = precedence c2 in
    +              if token_prec < next_prec
    +              then parse_bin_rhs (token_prec + 1) rhs stream
    +              else rhs
    +          | _ -> rhs
    +        in
    +
    +        (* Merge lhs/rhs. *)
    +        let lhs = Ast.Binary (c, lhs, rhs) in
    +        parse_bin_rhs expr_prec lhs stream
    +      end
    +  | _ -> lhs
    +
    +(* expression
    + *   ::= primary binoprhs *)
    +and parse_expr = parser
    +  | [< lhs=parse_primary; stream >] -> parse_bin_rhs 0 lhs stream
    +
    +(* prototype
    + *   ::= id '(' id* ')' *)
    +let parse_prototype =
    +  let rec parse_args accumulator = parser
    +    | [< 'Token.Ident id; e=parse_args (id::accumulator) >] -> e
    +    | [< >] -> accumulator
    +  in
    +
    +  parser
    +  | [< 'Token.Ident id;
    +       'Token.Kwd '(' ?? "expected '(' in prototype";
    +       args=parse_args [];
    +       'Token.Kwd ')' ?? "expected ')' in prototype" >] ->
    +      (* success. *)
    +      Ast.Prototype (id, Array.of_list (List.rev args))
    +
    +  | [< >] ->
    +      raise (Stream.Error "expected function name in prototype")
    +
    +(* definition ::= 'def' prototype expression *)
    +let parse_definition = parser
    +  | [< 'Token.Def; p=parse_prototype; e=parse_expr >] ->
    +      Ast.Function (p, e)
    +
    +(* toplevelexpr ::= expression *)
    +let parse_toplevel = parser
    +  | [< e=parse_expr >] ->
    +      (* Make an anonymous proto. *)
    +      Ast.Function (Ast.Prototype ("", [||]), e)
    +
    +(*  external ::= 'extern' prototype *)
    +let parse_extern = parser
    +  | [< 'Token.Extern; e=parse_prototype >] -> e
    +
    +
    + +
    codegen.ml:
    +
    +
    +(*===----------------------------------------------------------------------===
    + * Code Generation
    + *===----------------------------------------------------------------------===*)
    +
    +open Llvm
    +
    +exception Error of string
    +
    +let context = global_context ()
    +let the_module = create_module context "my cool jit"
    +let builder = builder context
    +let named_values:(string, llvalue) Hashtbl.t = Hashtbl.create 10
    +
    +let rec codegen_expr = function
    +  | Ast.Number n -> const_float double_type n
    +  | Ast.Variable name ->
    +      (try Hashtbl.find named_values name with
    +        | Not_found -> raise (Error "unknown variable name"))
    +  | Ast.Binary (op, lhs, rhs) ->
    +      let lhs_val = codegen_expr lhs in
    +      let rhs_val = codegen_expr rhs in
    +      begin
    +        match op with
    +        | '+' -> build_add lhs_val rhs_val "addtmp" builder
    +        | '-' -> build_sub lhs_val rhs_val "subtmp" builder
    +        | '*' -> build_mul lhs_val rhs_val "multmp" builder
    +        | '<' ->
    +            (* Convert bool 0/1 to double 0.0 or 1.0 *)
    +            let i = build_fcmp Fcmp.Ult lhs_val rhs_val "cmptmp" builder in
    +            build_uitofp i double_type "booltmp" builder
    +        | _ -> raise (Error "invalid binary operator")
    +      end
    +  | Ast.Call (callee, args) ->
    +      (* Look up the name in the module table. *)
    +      let callee =
    +        match lookup_function callee the_module with
    +        | Some callee -> callee
    +        | None -> raise (Error "unknown function referenced")
    +      in
    +      let params = params callee in
    +
    +      (* If argument mismatch error. *)
    +      if Array.length params == Array.length args then () else
    +        raise (Error "incorrect # arguments passed");
    +      let args = Array.map codegen_expr args in
    +      build_call callee args "calltmp" builder
    +
    +let codegen_proto = function
    +  | Ast.Prototype (name, args) ->
    +      (* Make the function type: double(double,double) etc. *)
    +      let doubles = Array.make (Array.length args) double_type in
    +      let ft = function_type double_type doubles in
    +      let f =
    +        match lookup_function name the_module with
    +        | None -> declare_function name ft the_module
    +
    +        (* If 'f' conflicted, there was already something named 'name'. If it
    +         * has a body, don't allow redefinition or reextern. *)
    +        | Some f ->
    +            (* If 'f' already has a body, reject this. *)
    +            if block_begin f <> At_end f then
    +              raise (Error "redefinition of function");
    +
    +            (* If 'f' took a different number of arguments, reject. *)
    +            if element_type (type_of f) <> ft then
    +              raise (Error "redefinition of function with different # args");
    +            f
    +      in
    +
    +      (* Set names for all arguments. *)
    +      Array.iteri (fun i a ->
    +        let n = args.(i) in
    +        set_value_name n a;
    +        Hashtbl.add named_values n a;
    +      ) (params f);
    +      f
    +
    +let codegen_func the_fpm = function
    +  | Ast.Function (proto, body) ->
    +      Hashtbl.clear named_values;
    +      let the_function = codegen_proto proto in
    +
    +      (* Create a new basic block to start insertion into. *)
    +      let bb = append_block "entry" the_function in
    +      position_at_end bb builder;
    +
    +      try
    +        let ret_val = codegen_expr body in
    +
    +        (* Finish off the function. *)
    +        let _ = build_ret ret_val builder in
    +
    +        (* Validate the generated code, checking for consistency. *)
    +        Llvm_analysis.assert_valid_function the_function;
    +
    +        (* Optimize the function. *)
    +        let _ = PassManager.run_function the_function the_fpm in
    +
    +        the_function
    +      with e ->
    +        delete_function the_function;
    +        raise e
    +
    +
    + +
    toplevel.ml:
    +
    +
    +(*===----------------------------------------------------------------------===
    + * Top-Level parsing and JIT Driver
    + *===----------------------------------------------------------------------===*)
    +
    +open Llvm
    +open Llvm_executionengine
    +
    +(* top ::= definition | external | expression | ';' *)
    +let rec main_loop the_fpm the_execution_engine stream =
    +  match Stream.peek stream with
    +  | None -> ()
    +
    +  (* ignore top-level semicolons. *)
    +  | Some (Token.Kwd ';') ->
    +      Stream.junk stream;
    +      main_loop the_fpm the_execution_engine stream
    +
    +  | Some token ->
    +      begin
    +        try match token with
    +        | Token.Def ->
    +            let e = Parser.parse_definition stream in
    +            print_endline "parsed a function definition.";
    +            dump_value (Codegen.codegen_func the_fpm e);
    +        | Token.Extern ->
    +            let e = Parser.parse_extern stream in
    +            print_endline "parsed an extern.";
    +            dump_value (Codegen.codegen_proto e);
    +        | _ ->
    +            (* Evaluate a top-level expression into an anonymous function. *)
    +            let e = Parser.parse_toplevel stream in
    +            print_endline "parsed a top-level expr";
    +            let the_function = Codegen.codegen_func the_fpm e in
    +            dump_value the_function;
    +
    +            (* JIT the function, returning a function pointer. *)
    +            let result = ExecutionEngine.run_function the_function [||]
    +              the_execution_engine in
    +
    +            print_string "Evaluated to ";
    +            print_float (GenericValue.as_float double_type result);
    +            print_newline ();
    +        with Stream.Error s | Codegen.Error s ->
    +          (* Skip token for error recovery. *)
    +          Stream.junk stream;
    +          print_endline s;
    +      end;
    +      print_string "ready> "; flush stdout;
    +      main_loop the_fpm the_execution_engine stream
    +
    +
    + +
    toy.ml:
    +
    +
    +(*===----------------------------------------------------------------------===
    + * Main driver code.
    + *===----------------------------------------------------------------------===*)
    +
    +open Llvm
    +open Llvm_executionengine
    +open Llvm_target
    +open Llvm_scalar_opts
    +
    +let main () =
    +  ignore (initialize_native_target ());
    +
    +  (* Install standard binary operators.
    +   * 1 is the lowest precedence. *)
    +  Hashtbl.add Parser.binop_precedence '<' 10;
    +  Hashtbl.add Parser.binop_precedence '+' 20;
    +  Hashtbl.add Parser.binop_precedence '-' 20;
    +  Hashtbl.add Parser.binop_precedence '*' 40;    (* highest. *)
    +
    +  (* Prime the first token. *)
    +  print_string "ready> "; flush stdout;
    +  let stream = Lexer.lex (Stream.of_channel stdin) in
    +
    +  (* Create the JIT. *)
    +  let the_module_provider = ModuleProvider.create Codegen.the_module in
    +  let the_execution_engine = ExecutionEngine.create the_module_provider in
    +  let the_fpm = PassManager.create_function the_module_provider in
    +
    +  (* Set up the optimizer pipeline.  Start with registering info about how the
    +   * target lays out data structures. *)
    +  TargetData.add (ExecutionEngine.target_data the_execution_engine) the_fpm;
    +
    +  (* Do simple "peephole" optimizations and bit-twiddling optzn. *)
    +  add_instruction_combining the_fpm;
    +
    +  (* reassociate expressions. *)
    +  add_reassociation the_fpm;
    +
    +  (* Eliminate Common SubExpressions. *)
    +  add_gvn the_fpm;
    +
    +  (* Simplify the control flow graph (deleting unreachable blocks, etc). *)
    +  add_cfg_simplification the_fpm;
    +
    +  ignore (PassManager.initialize the_fpm);
    +
    +  (* Run the main "interpreter loop" now. *)
    +  Toplevel.main_loop the_fpm the_execution_engine stream;
    +
    +  (* Print out all the generated code. *)
    +  dump_module Codegen.the_module
    +;;
    +
    +main ()
    +
    +
    + +
    bindings.c
    +
    +
    +#include <stdio.h>
    +
    +/* putchard - putchar that takes a double and returns 0. */
    +extern double putchard(double X) {
    +  putchar((char)X);
    +  return 0;
    +}
    +
    +
    +
    + +Next: Extending the language: control flow +
    + + +
    +
    + Valid CSS! + Valid HTML 4.01! + + Chris Lattner
    + Erick Tryzelaar
    + The LLVM Compiler Infrastructure
    + Last modified: $Date: 2007-10-17 11:05:13 -0700 (Wed, 17 Oct 2007) $ +
    + + diff --git a/libclamav/c++/llvm/docs/tutorial/OCamlLangImpl5.html b/libclamav/c++/llvm/docs/tutorial/OCamlLangImpl5.html new file mode 100644 index 000000000..f19e900c0 --- /dev/null +++ b/libclamav/c++/llvm/docs/tutorial/OCamlLangImpl5.html @@ -0,0 +1,1569 @@ + + + + + Kaleidoscope: Extending the Language: Control Flow + + + + + + + + +
    Kaleidoscope: Extending the Language: Control Flow
    + + + +
    +

    + Written by Chris Lattner + and Erick Tryzelaar +

    +
    + + + + + +
    + +

    Welcome to Chapter 5 of the "Implementing a language +with LLVM" tutorial. Parts 1-4 described the implementation of the simple +Kaleidoscope language and included support for generating LLVM IR, followed by +optimizations and a JIT compiler. Unfortunately, as presented, Kaleidoscope is +mostly useless: it has no control flow other than call and return. This means +that you can't have conditional branches in the code, significantly limiting its +power. In this episode of "build that compiler", we'll extend Kaleidoscope to +have an if/then/else expression plus a simple 'for' loop.

    + +
    + + + + + +
    + +

    +Extending Kaleidoscope to support if/then/else is quite straightforward. It +basically requires adding lexer support for this "new" concept to the lexer, +parser, AST, and LLVM code emitter. This example is nice, because it shows how +easy it is to "grow" a language over time, incrementally extending it as new +ideas are discovered.

    + +

    Before we get going on "how" we add this extension, lets talk about "what" we +want. The basic idea is that we want to be able to write this sort of thing: +

    + +
    +
    +def fib(x)
    +  if x < 3 then
    +    1
    +  else
    +    fib(x-1)+fib(x-2);
    +
    +
    + +

    In Kaleidoscope, every construct is an expression: there are no statements. +As such, the if/then/else expression needs to return a value like any other. +Since we're using a mostly functional form, we'll have it evaluate its +conditional, then return the 'then' or 'else' value based on how the condition +was resolved. This is very similar to the C "?:" expression.

    + +

    The semantics of the if/then/else expression is that it evaluates the +condition to a boolean equality value: 0.0 is considered to be false and +everything else is considered to be true. +If the condition is true, the first subexpression is evaluated and returned, if +the condition is false, the second subexpression is evaluated and returned. +Since Kaleidoscope allows side-effects, this behavior is important to nail down. +

    + +

    Now that we know what we "want", lets break this down into its constituent +pieces.

    + +
    + + + + + + +
    + +

    The lexer extensions are straightforward. First we add new variants +for the relevant tokens:

    + +
    +
    +  (* control *)
    +  | If | Then | Else | For | In
    +
    +
    + +

    Once we have that, we recognize the new keywords in the lexer. This is pretty simple +stuff:

    + +
    +
    +      ...
    +      match Buffer.contents buffer with
    +      | "def" -> [< 'Token.Def; stream >]
    +      | "extern" -> [< 'Token.Extern; stream >]
    +      | "if" -> [< 'Token.If; stream >]
    +      | "then" -> [< 'Token.Then; stream >]
    +      | "else" -> [< 'Token.Else; stream >]
    +      | "for" -> [< 'Token.For; stream >]
    +      | "in" -> [< 'Token.In; stream >]
    +      | id -> [< 'Token.Ident id; stream >]
    +
    +
    + +
    + + + + + +
    + +

    To represent the new expression we add a new AST variant for it:

    + +
    +
    +type expr =
    +  ...
    +  (* variant for if/then/else. *)
    +  | If of expr * expr * expr
    +
    +
    + +

    The AST variant just has pointers to the various subexpressions.

    + +
    + + + + + +
    + +

    Now that we have the relevant tokens coming from the lexer and we have the +AST node to build, our parsing logic is relatively straightforward. First we +define a new parsing function:

    + +
    +
    +let rec parse_primary = parser
    +  ...
    +  (* ifexpr ::= 'if' expr 'then' expr 'else' expr *)
    +  | [< 'Token.If; c=parse_expr;
    +       'Token.Then ?? "expected 'then'"; t=parse_expr;
    +       'Token.Else ?? "expected 'else'"; e=parse_expr >] ->
    +      Ast.If (c, t, e)
    +
    +
    + +

    Next we hook it up as a primary expression:

    + +
    +
    +let rec parse_primary = parser
    +  ...
    +  (* ifexpr ::= 'if' expr 'then' expr 'else' expr *)
    +  | [< 'Token.If; c=parse_expr;
    +       'Token.Then ?? "expected 'then'"; t=parse_expr;
    +       'Token.Else ?? "expected 'else'"; e=parse_expr >] ->
    +      Ast.If (c, t, e)
    +
    +
    + +
    + + + + + +
    + +

    Now that we have it parsing and building the AST, the final piece is adding +LLVM code generation support. This is the most interesting part of the +if/then/else example, because this is where it starts to introduce new concepts. +All of the code above has been thoroughly described in previous chapters. +

    + +

    To motivate the code we want to produce, lets take a look at a simple +example. Consider:

    + +
    +
    +extern foo();
    +extern bar();
    +def baz(x) if x then foo() else bar();
    +
    +
    + +

    If you disable optimizations, the code you'll (soon) get from Kaleidoscope +looks like this:

    + +
    +
    +declare double @foo()
    +
    +declare double @bar()
    +
    +define double @baz(double %x) {
    +entry:
    +  %ifcond = fcmp one double %x, 0.000000e+00
    +  br i1 %ifcond, label %then, label %else
    +
    +then:    ; preds = %entry
    +  %calltmp = call double @foo()
    +  br label %ifcont
    +
    +else:    ; preds = %entry
    +  %calltmp1 = call double @bar()
    +  br label %ifcont
    +
    +ifcont:    ; preds = %else, %then
    +  %iftmp = phi double [ %calltmp, %then ], [ %calltmp1, %else ]
    +  ret double %iftmp
    +}
    +
    +
    + +

    To visualize the control flow graph, you can use a nifty feature of the LLVM +'opt' tool. If you put this LLVM IR +into "t.ll" and run "llvm-as < t.ll | opt -analyze -view-cfg", a window will pop up and you'll +see this graph:

    + +
    Example CFG
    + +

    Another way to get this is to call "Llvm_analysis.view_function_cfg +f" or "Llvm_analysis.view_function_cfg_only f" (where f +is a "Function") either by inserting actual calls into the code and +recompiling or by calling these in the debugger. LLVM has many nice features +for visualizing various graphs.

    + +

    Getting back to the generated code, it is fairly simple: the entry block +evaluates the conditional expression ("x" in our case here) and compares the +result to 0.0 with the "fcmp one" +instruction ('one' is "Ordered and Not Equal"). Based on the result of this +expression, the code jumps to either the "then" or "else" blocks, which contain +the expressions for the true/false cases.

    + +

    Once the then/else blocks are finished executing, they both branch back to the +'ifcont' block to execute the code that happens after the if/then/else. In this +case the only thing left to do is to return to the caller of the function. The +question then becomes: how does the code know which expression to return?

    + +

    The answer to this question involves an important SSA operation: the +Phi +operation. If you're not familiar with SSA, the wikipedia +article is a good introduction and there are various other introductions to +it available on your favorite search engine. The short version is that +"execution" of the Phi operation requires "remembering" which block control came +from. The Phi operation takes on the value corresponding to the input control +block. In this case, if control comes in from the "then" block, it gets the +value of "calltmp". If control comes from the "else" block, it gets the value +of "calltmp1".

    + +

    At this point, you are probably starting to think "Oh no! This means my +simple and elegant front-end will have to start generating SSA form in order to +use LLVM!". Fortunately, this is not the case, and we strongly advise +not implementing an SSA construction algorithm in your front-end +unless there is an amazingly good reason to do so. In practice, there are two +sorts of values that float around in code written for your average imperative +programming language that might need Phi nodes:

    + +
      +
    1. Code that involves user variables: x = 1; x = x + 1;
    2. +
    3. Values that are implicit in the structure of your AST, such as the Phi node +in this case.
    4. +
    + +

    In Chapter 7 of this tutorial ("mutable +variables"), we'll talk about #1 +in depth. For now, just believe me that you don't need SSA construction to +handle this case. For #2, you have the choice of using the techniques that we will +describe for #1, or you can insert Phi nodes directly, if convenient. In this +case, it is really really easy to generate the Phi node, so we choose to do it +directly.

    + +

    Okay, enough of the motivation and overview, lets generate code!

    + +
    + + + + + +
    + +

    In order to generate code for this, we implement the Codegen method +for IfExprAST:

    + +
    +
    +let rec codegen_expr = function
    +  ...
    +  | Ast.If (cond, then_, else_) ->
    +      let cond = codegen_expr cond in
    +
    +      (* Convert condition to a bool by comparing equal to 0.0 *)
    +      let zero = const_float double_type 0.0 in
    +      let cond_val = build_fcmp Fcmp.One cond zero "ifcond" builder in
    +
    +
    + +

    This code is straightforward and similar to what we saw before. We emit the +expression for the condition, then compare that value to zero to get a truth +value as a 1-bit (bool) value.

    + +
    +
    +      (* Grab the first block so that we might later add the conditional branch
    +       * to it at the end of the function. *)
    +      let start_bb = insertion_block builder in
    +      let the_function = block_parent start_bb in
    +
    +      let then_bb = append_block "then" the_function in
    +      position_at_end then_bb builder;
    +
    +
    + +

    +As opposed to the C++ tutorial, we have to build +our basic blocks bottom up since we can't have dangling BasicBlocks. We start +off by saving a pointer to the first block (which might not be the entry +block), which we'll need to build a conditional branch later. We do this by +asking the builder for the current BasicBlock. The fourth line +gets the current Function object that is being built. It gets this by the +start_bb for its "parent" (the function it is currently embedded +into).

    + +

    Once it has that, it creates one block. It is automatically appended into +the function's list of blocks.

    + +
    +
    +      (* Emit 'then' value. *)
    +      position_at_end then_bb builder;
    +      let then_val = codegen_expr then_ in
    +
    +      (* Codegen of 'then' can change the current block, update then_bb for the
    +       * phi. We create a new name because one is used for the phi node, and the
    +       * other is used for the conditional branch. *)
    +      let new_then_bb = insertion_block builder in
    +
    +
    + +

    We move the builder to start inserting into the "then" block. Strictly +speaking, this call moves the insertion point to be at the end of the specified +block. However, since the "then" block is empty, it also starts out by +inserting at the beginning of the block. :)

    + +

    Once the insertion point is set, we recursively codegen the "then" expression +from the AST.

    + +

    The final line here is quite subtle, but is very important. The basic issue +is that when we create the Phi node in the merge block, we need to set up the +block/value pairs that indicate how the Phi will work. Importantly, the Phi +node expects to have an entry for each predecessor of the block in the CFG. Why +then, are we getting the current block when we just set it to ThenBB 5 lines +above? The problem is that the "Then" expression may actually itself change the +block that the Builder is emitting into if, for example, it contains a nested +"if/then/else" expression. Because calling Codegen recursively could +arbitrarily change the notion of the current block, we are required to get an +up-to-date value for code that will set up the Phi node.

    + +
    +
    +      (* Emit 'else' value. *)
    +      let else_bb = append_block "else" the_function in
    +      position_at_end else_bb builder;
    +      let else_val = codegen_expr else_ in
    +
    +      (* Codegen of 'else' can change the current block, update else_bb for the
    +       * phi. *)
    +      let new_else_bb = insertion_block builder in
    +
    +
    + +

    Code generation for the 'else' block is basically identical to codegen for +the 'then' block.

    + +
    +
    +      (* Emit merge block. *)
    +      let merge_bb = append_block "ifcont" the_function in
    +      position_at_end merge_bb builder;
    +      let incoming = [(then_val, new_then_bb); (else_val, new_else_bb)] in
    +      let phi = build_phi incoming "iftmp" builder in
    +
    +
    + +

    The first two lines here are now familiar: the first adds the "merge" block +to the Function object. The second block changes the insertion point so that +newly created code will go into the "merge" block. Once that is done, we need +to create the PHI node and set up the block/value pairs for the PHI.

    + +
    +
    +      (* Return to the start block to add the conditional branch. *)
    +      position_at_end start_bb builder;
    +      ignore (build_cond_br cond_val then_bb else_bb builder);
    +
    +
    + +

    Once the blocks are created, we can emit the conditional branch that chooses +between them. Note that creating new blocks does not implicitly affect the +IRBuilder, so it is still inserting into the block that the condition +went into. This is why we needed to save the "start" block.

    + +
    +
    +      (* Set a unconditional branch at the end of the 'then' block and the
    +       * 'else' block to the 'merge' block. *)
    +      position_at_end new_then_bb builder; ignore (build_br merge_bb builder);
    +      position_at_end new_else_bb builder; ignore (build_br merge_bb builder);
    +
    +      (* Finally, set the builder to the end of the merge block. *)
    +      position_at_end merge_bb builder;
    +
    +      phi
    +
    +
    + +

    To finish off the blocks, we create an unconditional branch +to the merge block. One interesting (and very important) aspect of the LLVM IR +is that it requires all basic blocks +to be "terminated" with a control flow +instruction such as return or branch. This means that all control flow, +including fall throughs must be made explicit in the LLVM IR. If you +violate this rule, the verifier will emit an error. + +

    Finally, the CodeGen function returns the phi node as the value computed by +the if/then/else expression. In our example above, this returned value will +feed into the code for the top-level function, which will create the return +instruction.

    + +

    Overall, we now have the ability to execute conditional code in +Kaleidoscope. With this extension, Kaleidoscope is a fairly complete language +that can calculate a wide variety of numeric functions. Next up we'll add +another useful expression that is familiar from non-functional languages...

    + +
    + + + + + +
    + +

    Now that we know how to add basic control flow constructs to the language, +we have the tools to add more powerful things. Lets add something more +aggressive, a 'for' expression:

    + +
    +
    + extern putchard(char);
    + def printstar(n)
    +   for i = 1, i < n, 1.0 in
    +     putchard(42);  # ascii 42 = '*'
    +
    + # print 100 '*' characters
    + printstar(100);
    +
    +
    + +

    This expression defines a new variable ("i" in this case) which iterates from +a starting value, while the condition ("i < n" in this case) is true, +incrementing by an optional step value ("1.0" in this case). If the step value +is omitted, it defaults to 1.0. While the loop is true, it executes its +body expression. Because we don't have anything better to return, we'll just +define the loop as always returning 0.0. In the future when we have mutable +variables, it will get more useful.

    + +

    As before, lets talk about the changes that we need to Kaleidoscope to +support this.

    + +
    + + + + + +
    + +

    The lexer extensions are the same sort of thing as for if/then/else:

    + +
    +
    +  ... in Token.token ...
    +  (* control *)
    +  | If | Then | Else
    +  | For | In
    +
    +  ... in Lexer.lex_ident...
    +      match Buffer.contents buffer with
    +      | "def" -> [< 'Token.Def; stream >]
    +      | "extern" -> [< 'Token.Extern; stream >]
    +      | "if" -> [< 'Token.If; stream >]
    +      | "then" -> [< 'Token.Then; stream >]
    +      | "else" -> [< 'Token.Else; stream >]
    +      | "for" -> [< 'Token.For; stream >]
    +      | "in" -> [< 'Token.In; stream >]
    +      | id -> [< 'Token.Ident id; stream >]
    +
    +
    + +
    + + + + + +
    + +

    The AST variant is just as simple. It basically boils down to capturing +the variable name and the constituent expressions in the node.

    + +
    +
    +type expr =
    +  ...
    +  (* variant for for/in. *)
    +  | For of string * expr * expr * expr option * expr
    +
    +
    + +
    + + + + + +
    + +

    The parser code is also fairly standard. The only interesting thing here is +handling of the optional step value. The parser code handles it by checking to +see if the second comma is present. If not, it sets the step value to null in +the AST node:

    + +
    +
    +let rec parse_primary = parser
    +  ...
    +  (* forexpr
    +        ::= 'for' identifier '=' expr ',' expr (',' expr)? 'in' expression *)
    +  | [< 'Token.For;
    +       'Token.Ident id ?? "expected identifier after for";
    +       'Token.Kwd '=' ?? "expected '=' after for";
    +       stream >] ->
    +      begin parser
    +        | [<
    +             start=parse_expr;
    +             'Token.Kwd ',' ?? "expected ',' after for";
    +             end_=parse_expr;
    +             stream >] ->
    +            let step =
    +              begin parser
    +              | [< 'Token.Kwd ','; step=parse_expr >] -> Some step
    +              | [< >] -> None
    +              end stream
    +            in
    +            begin parser
    +            | [< 'Token.In; body=parse_expr >] ->
    +                Ast.For (id, start, end_, step, body)
    +            | [< >] ->
    +                raise (Stream.Error "expected 'in' after for")
    +            end stream
    +        | [< >] ->
    +            raise (Stream.Error "expected '=' after for")
    +      end stream
    +
    +
    + +
    + + + + + +
    + +

    Now we get to the good part: the LLVM IR we want to generate for this thing. +With the simple example above, we get this LLVM IR (note that this dump is +generated with optimizations disabled for clarity): +

    + +
    +
    +declare double @putchard(double)
    +
    +define double @printstar(double %n) {
    +entry:
    +        ; initial value = 1.0 (inlined into phi)
    +  br label %loop
    +
    +loop:    ; preds = %loop, %entry
    +  %i = phi double [ 1.000000e+00, %entry ], [ %nextvar, %loop ]
    +        ; body
    +  %calltmp = call double @putchard( double 4.200000e+01 )
    +        ; increment
    +  %nextvar = add double %i, 1.000000e+00
    +
    +        ; termination test
    +  %cmptmp = fcmp ult double %i, %n
    +  %booltmp = uitofp i1 %cmptmp to double
    +  %loopcond = fcmp one double %booltmp, 0.000000e+00
    +  br i1 %loopcond, label %loop, label %afterloop
    +
    +afterloop:    ; preds = %loop
    +        ; loop always returns 0.0
    +  ret double 0.000000e+00
    +}
    +
    +
    + +

    This loop contains all the same constructs we saw before: a phi node, several +expressions, and some basic blocks. Lets see how this fits together.

    + +
    + + + + + +
    + +

    The first part of Codegen is very simple: we just output the start expression +for the loop value:

    + +
    +
    +let rec codegen_expr = function
    +  ...
    +  | Ast.For (var_name, start, end_, step, body) ->
    +      (* Emit the start code first, without 'variable' in scope. *)
    +      let start_val = codegen_expr start in
    +
    +
    + +

    With this out of the way, the next step is to set up the LLVM basic block +for the start of the loop body. In the case above, the whole loop body is one +block, but remember that the body code itself could consist of multiple blocks +(e.g. if it contains an if/then/else or a for/in expression).

    + +
    +
    +      (* Make the new basic block for the loop header, inserting after current
    +       * block. *)
    +      let preheader_bb = insertion_block builder in
    +      let the_function = block_parent preheader_bb in
    +      let loop_bb = append_block "loop" the_function in
    +
    +      (* Insert an explicit fall through from the current block to the
    +       * loop_bb. *)
    +      ignore (build_br loop_bb builder);
    +
    +
    + +

    This code is similar to what we saw for if/then/else. Because we will need +it to create the Phi node, we remember the block that falls through into the +loop. Once we have that, we create the actual block that starts the loop and +create an unconditional branch for the fall-through between the two blocks.

    + +
    +
    +      (* Start insertion in loop_bb. *)
    +      position_at_end loop_bb builder;
    +
    +      (* Start the PHI node with an entry for start. *)
    +      let variable = build_phi [(start_val, preheader_bb)] var_name builder in
    +
    +
    + +

    Now that the "preheader" for the loop is set up, we switch to emitting code +for the loop body. To begin with, we move the insertion point and create the +PHI node for the loop induction variable. Since we already know the incoming +value for the starting value, we add it to the Phi node. Note that the Phi will +eventually get a second value for the backedge, but we can't set it up yet +(because it doesn't exist!).

    + +
    +
    +      (* Within the loop, the variable is defined equal to the PHI node. If it
    +       * shadows an existing variable, we have to restore it, so save it
    +       * now. *)
    +      let old_val =
    +        try Some (Hashtbl.find named_values var_name) with Not_found -> None
    +      in
    +      Hashtbl.add named_values var_name variable;
    +
    +      (* Emit the body of the loop.  This, like any other expr, can change the
    +       * current BB.  Note that we ignore the value computed by the body, but
    +       * don't allow an error *)
    +      ignore (codegen_expr body);
    +
    +
    + +

    Now the code starts to get more interesting. Our 'for' loop introduces a new +variable to the symbol table. This means that our symbol table can now contain +either function arguments or loop variables. To handle this, before we codegen +the body of the loop, we add the loop variable as the current value for its +name. Note that it is possible that there is a variable of the same name in the +outer scope. It would be easy to make this an error (emit an error and return +null if there is already an entry for VarName) but we choose to allow shadowing +of variables. In order to handle this correctly, we remember the Value that +we are potentially shadowing in old_val (which will be None if there is +no shadowed variable).

    + +

    Once the loop variable is set into the symbol table, the code recursively +codegen's the body. This allows the body to use the loop variable: any +references to it will naturally find it in the symbol table.

    + +
    +
    +      (* Emit the step value. *)
    +      let step_val =
    +        match step with
    +        | Some step -> codegen_expr step
    +        (* If not specified, use 1.0. *)
    +        | None -> const_float double_type 1.0
    +      in
    +
    +      let next_var = build_add variable step_val "nextvar" builder in
    +
    +
    + +

    Now that the body is emitted, we compute the next value of the iteration +variable by adding the step value, or 1.0 if it isn't present. +'next_var' will be the value of the loop variable on the next iteration +of the loop.

    + +
    +
    +      (* Compute the end condition. *)
    +      let end_cond = codegen_expr end_ in
    +
    +      (* Convert condition to a bool by comparing equal to 0.0. *)
    +      let zero = const_float double_type 0.0 in
    +      let end_cond = build_fcmp Fcmp.One end_cond zero "loopcond" builder in
    +
    +
    + +

    Finally, we evaluate the exit value of the loop, to determine whether the +loop should exit. This mirrors the condition evaluation for the if/then/else +statement.

    + +
    +
    +      (* Create the "after loop" block and insert it. *)
    +      let loop_end_bb = insertion_block builder in
    +      let after_bb = append_block "afterloop" the_function in
    +
    +      (* Insert the conditional branch into the end of loop_end_bb. *)
    +      ignore (build_cond_br end_cond loop_bb after_bb builder);
    +
    +      (* Any new code will be inserted in after_bb. *)
    +      position_at_end after_bb builder;
    +
    +
    + +

    With the code for the body of the loop complete, we just need to finish up +the control flow for it. This code remembers the end block (for the phi node), then creates the block for the loop exit ("afterloop"). Based on the value of the +exit condition, it creates a conditional branch that chooses between executing +the loop again and exiting the loop. Any future code is emitted in the +"afterloop" block, so it sets the insertion position to it.

    + +
    +
    +      (* Add a new entry to the PHI node for the backedge. *)
    +      add_incoming (next_var, loop_end_bb) variable;
    +
    +      (* Restore the unshadowed variable. *)
    +      begin match old_val with
    +      | Some old_val -> Hashtbl.add named_values var_name old_val
    +      | None -> ()
    +      end;
    +
    +      (* for expr always returns 0.0. *)
    +      const_null double_type
    +
    +
    + +

    The final code handles various cleanups: now that we have the +"next_var" value, we can add the incoming value to the loop PHI node. +After that, we remove the loop variable from the symbol table, so that it isn't +in scope after the for loop. Finally, code generation of the for loop always +returns 0.0, so that is what we return from Codegen.codegen_expr.

    + +

    With this, we conclude the "adding control flow to Kaleidoscope" chapter of +the tutorial. In this chapter we added two control flow constructs, and used +them to motivate a couple of aspects of the LLVM IR that are important for +front-end implementors to know. In the next chapter of our saga, we will get +a bit crazier and add user-defined operators +to our poor innocent language.

    + +
    + + + + + +
    + +

    +Here is the complete code listing for our running example, enhanced with the +if/then/else and for expressions.. To build this example, use: +

    + +
    +
    +# Compile
    +ocamlbuild toy.byte
    +# Run
    +./toy.byte
    +
    +
    + +

    Here is the code:

    + +
    +
    _tags:
    +
    +
    +<{lexer,parser}.ml>: use_camlp4, pp(camlp4of)
    +<*.{byte,native}>: g++, use_llvm, use_llvm_analysis
    +<*.{byte,native}>: use_llvm_executionengine, use_llvm_target
    +<*.{byte,native}>: use_llvm_scalar_opts, use_bindings
    +
    +
    + +
    myocamlbuild.ml:
    +
    +
    +open Ocamlbuild_plugin;;
    +
    +ocaml_lib ~extern:true "llvm";;
    +ocaml_lib ~extern:true "llvm_analysis";;
    +ocaml_lib ~extern:true "llvm_executionengine";;
    +ocaml_lib ~extern:true "llvm_target";;
    +ocaml_lib ~extern:true "llvm_scalar_opts";;
    +
    +flag ["link"; "ocaml"; "g++"] (S[A"-cc"; A"g++"]);;
    +dep ["link"; "ocaml"; "use_bindings"] ["bindings.o"];;
    +
    +
    + +
    token.ml:
    +
    +
    +(*===----------------------------------------------------------------------===
    + * Lexer Tokens
    + *===----------------------------------------------------------------------===*)
    +
    +(* The lexer returns these 'Kwd' if it is an unknown character, otherwise one of
    + * these others for known things. *)
    +type token =
    +  (* commands *)
    +  | Def | Extern
    +
    +  (* primary *)
    +  | Ident of string | Number of float
    +
    +  (* unknown *)
    +  | Kwd of char
    +
    +  (* control *)
    +  | If | Then | Else
    +  | For | In
    +
    +
    + +
    lexer.ml:
    +
    +
    +(*===----------------------------------------------------------------------===
    + * Lexer
    + *===----------------------------------------------------------------------===*)
    +
    +let rec lex = parser
    +  (* Skip any whitespace. *)
    +  | [< ' (' ' | '\n' | '\r' | '\t'); stream >] -> lex stream
    +
    +  (* identifier: [a-zA-Z][a-zA-Z0-9] *)
    +  | [< ' ('A' .. 'Z' | 'a' .. 'z' as c); stream >] ->
    +      let buffer = Buffer.create 1 in
    +      Buffer.add_char buffer c;
    +      lex_ident buffer stream
    +
    +  (* number: [0-9.]+ *)
    +  | [< ' ('0' .. '9' as c); stream >] ->
    +      let buffer = Buffer.create 1 in
    +      Buffer.add_char buffer c;
    +      lex_number buffer stream
    +
    +  (* Comment until end of line. *)
    +  | [< ' ('#'); stream >] ->
    +      lex_comment stream
    +
    +  (* Otherwise, just return the character as its ascii value. *)
    +  | [< 'c; stream >] ->
    +      [< 'Token.Kwd c; lex stream >]
    +
    +  (* end of stream. *)
    +  | [< >] -> [< >]
    +
    +and lex_number buffer = parser
    +  | [< ' ('0' .. '9' | '.' as c); stream >] ->
    +      Buffer.add_char buffer c;
    +      lex_number buffer stream
    +  | [< stream=lex >] ->
    +      [< 'Token.Number (float_of_string (Buffer.contents buffer)); stream >]
    +
    +and lex_ident buffer = parser
    +  | [< ' ('A' .. 'Z' | 'a' .. 'z' | '0' .. '9' as c); stream >] ->
    +      Buffer.add_char buffer c;
    +      lex_ident buffer stream
    +  | [< stream=lex >] ->
    +      match Buffer.contents buffer with
    +      | "def" -> [< 'Token.Def; stream >]
    +      | "extern" -> [< 'Token.Extern; stream >]
    +      | "if" -> [< 'Token.If; stream >]
    +      | "then" -> [< 'Token.Then; stream >]
    +      | "else" -> [< 'Token.Else; stream >]
    +      | "for" -> [< 'Token.For; stream >]
    +      | "in" -> [< 'Token.In; stream >]
    +      | id -> [< 'Token.Ident id; stream >]
    +
    +and lex_comment = parser
    +  | [< ' ('\n'); stream=lex >] -> stream
    +  | [< 'c; e=lex_comment >] -> e
    +  | [< >] -> [< >]
    +
    +
    + +
    ast.ml:
    +
    +
    +(*===----------------------------------------------------------------------===
    + * Abstract Syntax Tree (aka Parse Tree)
    + *===----------------------------------------------------------------------===*)
    +
    +(* expr - Base type for all expression nodes. *)
    +type expr =
    +  (* variant for numeric literals like "1.0". *)
    +  | Number of float
    +
    +  (* variant for referencing a variable, like "a". *)
    +  | Variable of string
    +
    +  (* variant for a binary operator. *)
    +  | Binary of char * expr * expr
    +
    +  (* variant for function calls. *)
    +  | Call of string * expr array
    +
    +  (* variant for if/then/else. *)
    +  | If of expr * expr * expr
    +
    +  (* variant for for/in. *)
    +  | For of string * expr * expr * expr option * expr
    +
    +(* proto - This type represents the "prototype" for a function, which captures
    + * its name, and its argument names (thus implicitly the number of arguments the
    + * function takes). *)
    +type proto = Prototype of string * string array
    +
    +(* func - This type represents a function definition itself. *)
    +type func = Function of proto * expr
    +
    +
    + +
    parser.ml:
    +
    +
    +(*===---------------------------------------------------------------------===
    + * Parser
    + *===---------------------------------------------------------------------===*)
    +
    +(* binop_precedence - This holds the precedence for each binary operator that is
    + * defined *)
    +let binop_precedence:(char, int) Hashtbl.t = Hashtbl.create 10
    +
    +(* precedence - Get the precedence of the pending binary operator token. *)
    +let precedence c = try Hashtbl.find binop_precedence c with Not_found -> -1
    +
    +(* primary
    + *   ::= identifier
    + *   ::= numberexpr
    + *   ::= parenexpr
    + *   ::= ifexpr
    + *   ::= forexpr *)
    +let rec parse_primary = parser
    +  (* numberexpr ::= number *)
    +  | [< 'Token.Number n >] -> Ast.Number n
    +
    +  (* parenexpr ::= '(' expression ')' *)
    +  | [< 'Token.Kwd '('; e=parse_expr; 'Token.Kwd ')' ?? "expected ')'" >] -> e
    +
    +  (* identifierexpr
    +   *   ::= identifier
    +   *   ::= identifier '(' argumentexpr ')' *)
    +  | [< 'Token.Ident id; stream >] ->
    +      let rec parse_args accumulator = parser
    +        | [< e=parse_expr; stream >] ->
    +            begin parser
    +              | [< 'Token.Kwd ','; e=parse_args (e :: accumulator) >] -> e
    +              | [< >] -> e :: accumulator
    +            end stream
    +        | [< >] -> accumulator
    +      in
    +      let rec parse_ident id = parser
    +        (* Call. *)
    +        | [< 'Token.Kwd '(';
    +             args=parse_args [];
    +             'Token.Kwd ')' ?? "expected ')'">] ->
    +            Ast.Call (id, Array.of_list (List.rev args))
    +
    +        (* Simple variable ref. *)
    +        | [< >] -> Ast.Variable id
    +      in
    +      parse_ident id stream
    +
    +  (* ifexpr ::= 'if' expr 'then' expr 'else' expr *)
    +  | [< 'Token.If; c=parse_expr;
    +       'Token.Then ?? "expected 'then'"; t=parse_expr;
    +       'Token.Else ?? "expected 'else'"; e=parse_expr >] ->
    +      Ast.If (c, t, e)
    +
    +  (* forexpr
    +        ::= 'for' identifier '=' expr ',' expr (',' expr)? 'in' expression *)
    +  | [< 'Token.For;
    +       'Token.Ident id ?? "expected identifier after for";
    +       'Token.Kwd '=' ?? "expected '=' after for";
    +       stream >] ->
    +      begin parser
    +        | [<
    +             start=parse_expr;
    +             'Token.Kwd ',' ?? "expected ',' after for";
    +             end_=parse_expr;
    +             stream >] ->
    +            let step =
    +              begin parser
    +              | [< 'Token.Kwd ','; step=parse_expr >] -> Some step
    +              | [< >] -> None
    +              end stream
    +            in
    +            begin parser
    +            | [< 'Token.In; body=parse_expr >] ->
    +                Ast.For (id, start, end_, step, body)
    +            | [< >] ->
    +                raise (Stream.Error "expected 'in' after for")
    +            end stream
    +        | [< >] ->
    +            raise (Stream.Error "expected '=' after for")
    +      end stream
    +
    +  | [< >] -> raise (Stream.Error "unknown token when expecting an expression.")
    +
    +(* binoprhs
    + *   ::= ('+' primary)* *)
    +and parse_bin_rhs expr_prec lhs stream =
    +  match Stream.peek stream with
    +  (* If this is a binop, find its precedence. *)
    +  | Some (Token.Kwd c) when Hashtbl.mem binop_precedence c ->
    +      let token_prec = precedence c in
    +
    +      (* If this is a binop that binds at least as tightly as the current binop,
    +       * consume it, otherwise we are done. *)
    +      if token_prec < expr_prec then lhs else begin
    +        (* Eat the binop. *)
    +        Stream.junk stream;
    +
    +        (* Parse the primary expression after the binary operator. *)
    +        let rhs = parse_primary stream in
    +
    +        (* Okay, we know this is a binop. *)
    +        let rhs =
    +          match Stream.peek stream with
    +          | Some (Token.Kwd c2) ->
    +              (* If BinOp binds less tightly with rhs than the operator after
    +               * rhs, let the pending operator take rhs as its lhs. *)
    +              let next_prec = precedence c2 in
    +              if token_prec < next_prec
    +              then parse_bin_rhs (token_prec + 1) rhs stream
    +              else rhs
    +          | _ -> rhs
    +        in
    +
    +        (* Merge lhs/rhs. *)
    +        let lhs = Ast.Binary (c, lhs, rhs) in
    +        parse_bin_rhs expr_prec lhs stream
    +      end
    +  | _ -> lhs
    +
    +(* expression
    + *   ::= primary binoprhs *)
    +and parse_expr = parser
    +  | [< lhs=parse_primary; stream >] -> parse_bin_rhs 0 lhs stream
    +
    +(* prototype
    + *   ::= id '(' id* ')' *)
    +let parse_prototype =
    +  let rec parse_args accumulator = parser
    +    | [< 'Token.Ident id; e=parse_args (id::accumulator) >] -> e
    +    | [< >] -> accumulator
    +  in
    +
    +  parser
    +  | [< 'Token.Ident id;
    +       'Token.Kwd '(' ?? "expected '(' in prototype";
    +       args=parse_args [];
    +       'Token.Kwd ')' ?? "expected ')' in prototype" >] ->
    +      (* success. *)
    +      Ast.Prototype (id, Array.of_list (List.rev args))
    +
    +  | [< >] ->
    +      raise (Stream.Error "expected function name in prototype")
    +
    +(* definition ::= 'def' prototype expression *)
    +let parse_definition = parser
    +  | [< 'Token.Def; p=parse_prototype; e=parse_expr >] ->
    +      Ast.Function (p, e)
    +
    +(* toplevelexpr ::= expression *)
    +let parse_toplevel = parser
    +  | [< e=parse_expr >] ->
    +      (* Make an anonymous proto. *)
    +      Ast.Function (Ast.Prototype ("", [||]), e)
    +
    +(*  external ::= 'extern' prototype *)
    +let parse_extern = parser
    +  | [< 'Token.Extern; e=parse_prototype >] -> e
    +
    +
    + +
    codegen.ml:
    +
    +
    +(*===----------------------------------------------------------------------===
    + * Code Generation
    + *===----------------------------------------------------------------------===*)
    +
    +open Llvm
    +
    +exception Error of string
    +
    +let context = global_context ()
    +let the_module = create_module context "my cool jit"
    +let builder = builder context
    +let named_values:(string, llvalue) Hashtbl.t = Hashtbl.create 10
    +
    +let rec codegen_expr = function
    +  | Ast.Number n -> const_float double_type n
    +  | Ast.Variable name ->
    +      (try Hashtbl.find named_values name with
    +        | Not_found -> raise (Error "unknown variable name"))
    +  | Ast.Binary (op, lhs, rhs) ->
    +      let lhs_val = codegen_expr lhs in
    +      let rhs_val = codegen_expr rhs in
    +      begin
    +        match op with
    +        | '+' -> build_add lhs_val rhs_val "addtmp" builder
    +        | '-' -> build_sub lhs_val rhs_val "subtmp" builder
    +        | '*' -> build_mul lhs_val rhs_val "multmp" builder
    +        | '<' ->
    +            (* Convert bool 0/1 to double 0.0 or 1.0 *)
    +            let i = build_fcmp Fcmp.Ult lhs_val rhs_val "cmptmp" builder in
    +            build_uitofp i double_type "booltmp" builder
    +        | _ -> raise (Error "invalid binary operator")
    +      end
    +  | Ast.Call (callee, args) ->
    +      (* Look up the name in the module table. *)
    +      let callee =
    +        match lookup_function callee the_module with
    +        | Some callee -> callee
    +        | None -> raise (Error "unknown function referenced")
    +      in
    +      let params = params callee in
    +
    +      (* If argument mismatch error. *)
    +      if Array.length params == Array.length args then () else
    +        raise (Error "incorrect # arguments passed");
    +      let args = Array.map codegen_expr args in
    +      build_call callee args "calltmp" builder
    +  | Ast.If (cond, then_, else_) ->
    +      let cond = codegen_expr cond in
    +
    +      (* Convert condition to a bool by comparing equal to 0.0 *)
    +      let zero = const_float double_type 0.0 in
    +      let cond_val = build_fcmp Fcmp.One cond zero "ifcond" builder in
    +
    +      (* Grab the first block so that we might later add the conditional branch
    +       * to it at the end of the function. *)
    +      let start_bb = insertion_block builder in
    +      let the_function = block_parent start_bb in
    +
    +      let then_bb = append_block "then" the_function in
    +
    +      (* Emit 'then' value. *)
    +      position_at_end then_bb builder;
    +      let then_val = codegen_expr then_ in
    +
    +      (* Codegen of 'then' can change the current block, update then_bb for the
    +       * phi. We create a new name because one is used for the phi node, and the
    +       * other is used for the conditional branch. *)
    +      let new_then_bb = insertion_block builder in
    +
    +      (* Emit 'else' value. *)
    +      let else_bb = append_block "else" the_function in
    +      position_at_end else_bb builder;
    +      let else_val = codegen_expr else_ in
    +
    +      (* Codegen of 'else' can change the current block, update else_bb for the
    +       * phi. *)
    +      let new_else_bb = insertion_block builder in
    +
    +      (* Emit merge block. *)
    +      let merge_bb = append_block "ifcont" the_function in
    +      position_at_end merge_bb builder;
    +      let incoming = [(then_val, new_then_bb); (else_val, new_else_bb)] in
    +      let phi = build_phi incoming "iftmp" builder in
    +
    +      (* Return to the start block to add the conditional branch. *)
    +      position_at_end start_bb builder;
    +      ignore (build_cond_br cond_val then_bb else_bb builder);
    +
    +      (* Set a unconditional branch at the end of the 'then' block and the
    +       * 'else' block to the 'merge' block. *)
    +      position_at_end new_then_bb builder; ignore (build_br merge_bb builder);
    +      position_at_end new_else_bb builder; ignore (build_br merge_bb builder);
    +
    +      (* Finally, set the builder to the end of the merge block. *)
    +      position_at_end merge_bb builder;
    +
    +      phi
    +  | Ast.For (var_name, start, end_, step, body) ->
    +      (* Emit the start code first, without 'variable' in scope. *)
    +      let start_val = codegen_expr start in
    +
    +      (* Make the new basic block for the loop header, inserting after current
    +       * block. *)
    +      let preheader_bb = insertion_block builder in
    +      let the_function = block_parent preheader_bb in
    +      let loop_bb = append_block "loop" the_function in
    +
    +      (* Insert an explicit fall through from the current block to the
    +       * loop_bb. *)
    +      ignore (build_br loop_bb builder);
    +
    +      (* Start insertion in loop_bb. *)
    +      position_at_end loop_bb builder;
    +
    +      (* Start the PHI node with an entry for start. *)
    +      let variable = build_phi [(start_val, preheader_bb)] var_name builder in
    +
    +      (* Within the loop, the variable is defined equal to the PHI node. If it
    +       * shadows an existing variable, we have to restore it, so save it
    +       * now. *)
    +      let old_val =
    +        try Some (Hashtbl.find named_values var_name) with Not_found -> None
    +      in
    +      Hashtbl.add named_values var_name variable;
    +
    +      (* Emit the body of the loop.  This, like any other expr, can change the
    +       * current BB.  Note that we ignore the value computed by the body, but
    +       * don't allow an error *)
    +      ignore (codegen_expr body);
    +
    +      (* Emit the step value. *)
    +      let step_val =
    +        match step with
    +        | Some step -> codegen_expr step
    +        (* If not specified, use 1.0. *)
    +        | None -> const_float double_type 1.0
    +      in
    +
    +      let next_var = build_add variable step_val "nextvar" builder in
    +
    +      (* Compute the end condition. *)
    +      let end_cond = codegen_expr end_ in
    +
    +      (* Convert condition to a bool by comparing equal to 0.0. *)
    +      let zero = const_float double_type 0.0 in
    +      let end_cond = build_fcmp Fcmp.One end_cond zero "loopcond" builder in
    +
    +      (* Create the "after loop" block and insert it. *)
    +      let loop_end_bb = insertion_block builder in
    +      let after_bb = append_block "afterloop" the_function in
    +
    +      (* Insert the conditional branch into the end of loop_end_bb. *)
    +      ignore (build_cond_br end_cond loop_bb after_bb builder);
    +
    +      (* Any new code will be inserted in after_bb. *)
    +      position_at_end after_bb builder;
    +
    +      (* Add a new entry to the PHI node for the backedge. *)
    +      add_incoming (next_var, loop_end_bb) variable;
    +
    +      (* Restore the unshadowed variable. *)
    +      begin match old_val with
    +      | Some old_val -> Hashtbl.add named_values var_name old_val
    +      | None -> ()
    +      end;
    +
    +      (* for expr always returns 0.0. *)
    +      const_null double_type
    +
    +let codegen_proto = function
    +  | Ast.Prototype (name, args) ->
    +      (* Make the function type: double(double,double) etc. *)
    +      let doubles = Array.make (Array.length args) double_type in
    +      let ft = function_type double_type doubles in
    +      let f =
    +        match lookup_function name the_module with
    +        | None -> declare_function name ft the_module
    +
    +        (* If 'f' conflicted, there was already something named 'name'. If it
    +         * has a body, don't allow redefinition or reextern. *)
    +        | Some f ->
    +            (* If 'f' already has a body, reject this. *)
    +            if block_begin f <> At_end f then
    +              raise (Error "redefinition of function");
    +
    +            (* If 'f' took a different number of arguments, reject. *)
    +            if element_type (type_of f) <> ft then
    +              raise (Error "redefinition of function with different # args");
    +            f
    +      in
    +
    +      (* Set names for all arguments. *)
    +      Array.iteri (fun i a ->
    +        let n = args.(i) in
    +        set_value_name n a;
    +        Hashtbl.add named_values n a;
    +      ) (params f);
    +      f
    +
    +let codegen_func the_fpm = function
    +  | Ast.Function (proto, body) ->
    +      Hashtbl.clear named_values;
    +      let the_function = codegen_proto proto in
    +
    +      (* Create a new basic block to start insertion into. *)
    +      let bb = append_block "entry" the_function in
    +      position_at_end bb builder;
    +
    +      try
    +        let ret_val = codegen_expr body in
    +
    +        (* Finish off the function. *)
    +        let _ = build_ret ret_val builder in
    +
    +        (* Validate the generated code, checking for consistency. *)
    +        Llvm_analysis.assert_valid_function the_function;
    +
    +        (* Optimize the function. *)
    +        let _ = PassManager.run_function the_function the_fpm in
    +
    +        the_function
    +      with e ->
    +        delete_function the_function;
    +        raise e
    +
    +
    + +
    toplevel.ml:
    +
    +
    +(*===----------------------------------------------------------------------===
    + * Top-Level parsing and JIT Driver
    + *===----------------------------------------------------------------------===*)
    +
    +open Llvm
    +open Llvm_executionengine
    +
    +(* top ::= definition | external | expression | ';' *)
    +let rec main_loop the_fpm the_execution_engine stream =
    +  match Stream.peek stream with
    +  | None -> ()
    +
    +  (* ignore top-level semicolons. *)
    +  | Some (Token.Kwd ';') ->
    +      Stream.junk stream;
    +      main_loop the_fpm the_execution_engine stream
    +
    +  | Some token ->
    +      begin
    +        try match token with
    +        | Token.Def ->
    +            let e = Parser.parse_definition stream in
    +            print_endline "parsed a function definition.";
    +            dump_value (Codegen.codegen_func the_fpm e);
    +        | Token.Extern ->
    +            let e = Parser.parse_extern stream in
    +            print_endline "parsed an extern.";
    +            dump_value (Codegen.codegen_proto e);
    +        | _ ->
    +            (* Evaluate a top-level expression into an anonymous function. *)
    +            let e = Parser.parse_toplevel stream in
    +            print_endline "parsed a top-level expr";
    +            let the_function = Codegen.codegen_func the_fpm e in
    +            dump_value the_function;
    +
    +            (* JIT the function, returning a function pointer. *)
    +            let result = ExecutionEngine.run_function the_function [||]
    +              the_execution_engine in
    +
    +            print_string "Evaluated to ";
    +            print_float (GenericValue.as_float double_type result);
    +            print_newline ();
    +        with Stream.Error s | Codegen.Error s ->
    +          (* Skip token for error recovery. *)
    +          Stream.junk stream;
    +          print_endline s;
    +      end;
    +      print_string "ready> "; flush stdout;
    +      main_loop the_fpm the_execution_engine stream
    +
    +
    + +
    toy.ml:
    +
    +
    +(*===----------------------------------------------------------------------===
    + * Main driver code.
    + *===----------------------------------------------------------------------===*)
    +
    +open Llvm
    +open Llvm_executionengine
    +open Llvm_target
    +open Llvm_scalar_opts
    +
    +let main () =
    +  ignore (initialize_native_target ());
    +
    +  (* Install standard binary operators.
    +   * 1 is the lowest precedence. *)
    +  Hashtbl.add Parser.binop_precedence '<' 10;
    +  Hashtbl.add Parser.binop_precedence '+' 20;
    +  Hashtbl.add Parser.binop_precedence '-' 20;
    +  Hashtbl.add Parser.binop_precedence '*' 40;    (* highest. *)
    +
    +  (* Prime the first token. *)
    +  print_string "ready> "; flush stdout;
    +  let stream = Lexer.lex (Stream.of_channel stdin) in
    +
    +  (* Create the JIT. *)
    +  let the_module_provider = ModuleProvider.create Codegen.the_module in
    +  let the_execution_engine = ExecutionEngine.create the_module_provider in
    +  let the_fpm = PassManager.create_function the_module_provider in
    +
    +  (* Set up the optimizer pipeline.  Start with registering info about how the
    +   * target lays out data structures. *)
    +  TargetData.add (ExecutionEngine.target_data the_execution_engine) the_fpm;
    +
    +  (* Do simple "peephole" optimizations and bit-twiddling optzn. *)
    +  add_instruction_combining the_fpm;
    +
    +  (* reassociate expressions. *)
    +  add_reassociation the_fpm;
    +
    +  (* Eliminate Common SubExpressions. *)
    +  add_gvn the_fpm;
    +
    +  (* Simplify the control flow graph (deleting unreachable blocks, etc). *)
    +  add_cfg_simplification the_fpm;
    +
    +  ignore (PassManager.initialize the_fpm);
    +
    +  (* Run the main "interpreter loop" now. *)
    +  Toplevel.main_loop the_fpm the_execution_engine stream;
    +
    +  (* Print out all the generated code. *)
    +  dump_module Codegen.the_module
    +;;
    +
    +main ()
    +
    +
    + +
    bindings.c
    +
    +
    +#include <stdio.h>
    +
    +/* putchard - putchar that takes a double and returns 0. */
    +extern double putchard(double X) {
    +  putchar((char)X);
    +  return 0;
    +}
    +
    +
    +
    + +Next: Extending the language: user-defined +operators +
    + + +
    +
    + Valid CSS! + Valid HTML 4.01! + + Chris Lattner
    + Erick Tryzelaar
    + The LLVM Compiler Infrastructure
    + Last modified: $Date: 2007-10-17 11:05:13 -0700 (Wed, 17 Oct 2007) $ +
    + + diff --git a/libclamav/c++/llvm/docs/tutorial/OCamlLangImpl6.html b/libclamav/c++/llvm/docs/tutorial/OCamlLangImpl6.html new file mode 100644 index 000000000..2edb22edf --- /dev/null +++ b/libclamav/c++/llvm/docs/tutorial/OCamlLangImpl6.html @@ -0,0 +1,1574 @@ + + + + + Kaleidoscope: Extending the Language: User-defined Operators + + + + + + + + +
    Kaleidoscope: Extending the Language: User-defined Operators
    + + + +
    +

    + Written by Chris Lattner + and Erick Tryzelaar +

    +
    + + + + + +
    + +

    Welcome to Chapter 6 of the "Implementing a language +with LLVM" tutorial. At this point in our tutorial, we now have a fully +functional language that is fairly minimal, but also useful. There +is still one big problem with it, however. Our language doesn't have many +useful operators (like division, logical negation, or even any comparisons +besides less-than).

    + +

    This chapter of the tutorial takes a wild digression into adding user-defined +operators to the simple and beautiful Kaleidoscope language. This digression now +gives us a simple and ugly language in some ways, but also a powerful one at the +same time. One of the great things about creating your own language is that you +get to decide what is good or bad. In this tutorial we'll assume that it is +okay to use this as a way to show some interesting parsing techniques.

    + +

    At the end of this tutorial, we'll run through an example Kaleidoscope +application that renders the Mandelbrot set. This gives +an example of what you can build with Kaleidoscope and its feature set.

    + +
    + + + + + +
    + +

    +The "operator overloading" that we will add to Kaleidoscope is more general than +languages like C++. In C++, you are only allowed to redefine existing +operators: you can't programatically change the grammar, introduce new +operators, change precedence levels, etc. In this chapter, we will add this +capability to Kaleidoscope, which will let the user round out the set of +operators that are supported.

    + +

    The point of going into user-defined operators in a tutorial like this is to +show the power and flexibility of using a hand-written parser. Thus far, the parser +we have been implementing uses recursive descent for most parts of the grammar and +operator precedence parsing for the expressions. See Chapter 2 for details. Without using operator +precedence parsing, it would be very difficult to allow the programmer to +introduce new operators into the grammar: the grammar is dynamically extensible +as the JIT runs.

    + +

    The two specific features we'll add are programmable unary operators (right +now, Kaleidoscope has no unary operators at all) as well as binary operators. +An example of this is:

    + +
    +
    +# Logical unary not.
    +def unary!(v)
    +  if v then
    +    0
    +  else
    +    1;
    +
    +# Define > with the same precedence as <.
    +def binary> 10 (LHS RHS)
    +  RHS < LHS;
    +
    +# Binary "logical or", (note that it does not "short circuit")
    +def binary| 5 (LHS RHS)
    +  if LHS then
    +    1
    +  else if RHS then
    +    1
    +  else
    +    0;
    +
    +# Define = with slightly lower precedence than relationals.
    +def binary= 9 (LHS RHS)
    +  !(LHS < RHS | LHS > RHS);
    +
    +
    + +

    Many languages aspire to being able to implement their standard runtime +library in the language itself. In Kaleidoscope, we can implement significant +parts of the language in the library!

    + +

    We will break down implementation of these features into two parts: +implementing support for user-defined binary operators and adding unary +operators.

    + +
    + + + + + +
    + +

    Adding support for user-defined binary operators is pretty simple with our +current framework. We'll first add support for the unary/binary keywords:

    + +
    +
    +type token =
    +  ...
    +  (* operators *)
    +  | Binary | Unary
    +
    +...
    +
    +and lex_ident buffer = parser
    +  ...
    +      | "for" -> [< 'Token.For; stream >]
    +      | "in" -> [< 'Token.In; stream >]
    +      | "binary" -> [< 'Token.Binary; stream >]
    +      | "unary" -> [< 'Token.Unary; stream >]
    +
    +
    + +

    This just adds lexer support for the unary and binary keywords, like we +did in previous chapters. One nice +thing about our current AST, is that we represent binary operators with full +generalisation by using their ASCII code as the opcode. For our extended +operators, we'll use this same representation, so we don't need any new AST or +parser support.

    + +

    On the other hand, we have to be able to represent the definitions of these +new operators, in the "def binary| 5" part of the function definition. In our +grammar so far, the "name" for the function definition is parsed as the +"prototype" production and into the Ast.Prototype AST node. To +represent our new user-defined operators as prototypes, we have to extend +the Ast.Prototype AST node like this:

    + +
    +
    +(* proto - This type represents the "prototype" for a function, which captures
    + * its name, and its argument names (thus implicitly the number of arguments the
    + * function takes). *)
    +type proto =
    +  | Prototype of string * string array
    +  | BinOpPrototype of string * string array * int
    +
    +
    + +

    Basically, in addition to knowing a name for the prototype, we now keep track +of whether it was an operator, and if it was, what precedence level the operator +is at. The precedence is only used for binary operators (as you'll see below, +it just doesn't apply for unary operators). Now that we have a way to represent +the prototype for a user-defined operator, we need to parse it:

    + +
    +
    +(* prototype
    + *   ::= id '(' id* ')'
    + *   ::= binary LETTER number? (id, id)
    + *   ::= unary LETTER number? (id) *)
    +let parse_prototype =
    +  let rec parse_args accumulator = parser
    +    | [< 'Token.Ident id; e=parse_args (id::accumulator) >] -> e
    +    | [< >] -> accumulator
    +  in
    +  let parse_operator = parser
    +    | [< 'Token.Unary >] -> "unary", 1
    +    | [< 'Token.Binary >] -> "binary", 2
    +  in
    +  let parse_binary_precedence = parser
    +    | [< 'Token.Number n >] -> int_of_float n
    +    | [< >] -> 30
    +  in
    +  parser
    +  | [< 'Token.Ident id;
    +       'Token.Kwd '(' ?? "expected '(' in prototype";
    +       args=parse_args [];
    +       'Token.Kwd ')' ?? "expected ')' in prototype" >] ->
    +      (* success. *)
    +      Ast.Prototype (id, Array.of_list (List.rev args))
    +  | [< (prefix, kind)=parse_operator;
    +       'Token.Kwd op ?? "expected an operator";
    +       (* Read the precedence if present. *)
    +       binary_precedence=parse_binary_precedence;
    +       'Token.Kwd '(' ?? "expected '(' in prototype";
    +        args=parse_args [];
    +       'Token.Kwd ')' ?? "expected ')' in prototype" >] ->
    +      let name = prefix ^ (String.make 1 op) in
    +      let args = Array.of_list (List.rev args) in
    +
    +      (* Verify right number of arguments for operator. *)
    +      if Array.length args != kind
    +      then raise (Stream.Error "invalid number of operands for operator")
    +      else
    +        if kind == 1 then
    +          Ast.Prototype (name, args)
    +        else
    +          Ast.BinOpPrototype (name, args, binary_precedence)
    +  | [< >] ->
    +      raise (Stream.Error "expected function name in prototype")
    +
    +
    + +

    This is all fairly straightforward parsing code, and we have already seen +a lot of similar code in the past. One interesting part about the code above is +the couple lines that set up name for binary operators. This builds +names like "binary@" for a newly defined "@" operator. This then takes +advantage of the fact that symbol names in the LLVM symbol table are allowed to +have any character in them, including embedded nul characters.

    + +

    The next interesting thing to add, is codegen support for these binary +operators. Given our current structure, this is a simple addition of a default +case for our existing binary operator node:

    + +
    +
    +let codegen_expr = function
    +  ...
    +  | Ast.Binary (op, lhs, rhs) ->
    +      let lhs_val = codegen_expr lhs in
    +      let rhs_val = codegen_expr rhs in
    +      begin
    +        match op with
    +        | '+' -> build_add lhs_val rhs_val "addtmp" builder
    +        | '-' -> build_sub lhs_val rhs_val "subtmp" builder
    +        | '*' -> build_mul lhs_val rhs_val "multmp" builder
    +        | '<' ->
    +            (* Convert bool 0/1 to double 0.0 or 1.0 *)
    +            let i = build_fcmp Fcmp.Ult lhs_val rhs_val "cmptmp" builder in
    +            build_uitofp i double_type "booltmp" builder
    +        | _ ->
    +            (* If it wasn't a builtin binary operator, it must be a user defined
    +             * one. Emit a call to it. *)
    +            let callee = "binary" ^ (String.make 1 op) in
    +            let callee =
    +              match lookup_function callee the_module with
    +              | Some callee -> callee
    +              | None -> raise (Error "binary operator not found!")
    +            in
    +            build_call callee [|lhs_val; rhs_val|] "binop" builder
    +      end
    +
    +
    + +

    As you can see above, the new code is actually really simple. It just does +a lookup for the appropriate operator in the symbol table and generates a +function call to it. Since user-defined operators are just built as normal +functions (because the "prototype" boils down to a function with the right +name) everything falls into place.

    + +

    The final piece of code we are missing, is a bit of top level magic:

    + +
    +
    +let codegen_func the_fpm = function
    +  | Ast.Function (proto, body) ->
    +      Hashtbl.clear named_values;
    +      let the_function = codegen_proto proto in
    +
    +      (* If this is an operator, install it. *)
    +      begin match proto with
    +      | Ast.BinOpPrototype (name, args, prec) ->
    +          let op = name.[String.length name - 1] in
    +          Hashtbl.add Parser.binop_precedence op prec;
    +      | _ -> ()
    +      end;
    +
    +      (* Create a new basic block to start insertion into. *)
    +      let bb = append_block "entry" the_function in
    +      position_at_end bb builder;
    +      ...
    +
    +
    + +

    Basically, before codegening a function, if it is a user-defined operator, we +register it in the precedence table. This allows the binary operator parsing +logic we already have in place to handle it. Since we are working on a +fully-general operator precedence parser, this is all we need to do to "extend +the grammar".

    + +

    Now we have useful user-defined binary operators. This builds a lot +on the previous framework we built for other operators. Adding unary operators +is a bit more challenging, because we don't have any framework for it yet - lets +see what it takes.

    + +
    + + + + + +
    + +

    Since we don't currently support unary operators in the Kaleidoscope +language, we'll need to add everything to support them. Above, we added simple +support for the 'unary' keyword to the lexer. In addition to that, we need an +AST node:

    + +
    +
    +type expr =
    +  ...
    +  (* variant for a unary operator. *)
    +  | Unary of char * expr
    +  ...
    +
    +
    + +

    This AST node is very simple and obvious by now. It directly mirrors the +binary operator AST node, except that it only has one child. With this, we +need to add the parsing logic. Parsing a unary operator is pretty simple: we'll +add a new function to do it:

    + +
    +
    +(* unary
    + *   ::= primary
    + *   ::= '!' unary *)
    +and parse_unary = parser
    +  (* If this is a unary operator, read it. *)
    +  | [< 'Token.Kwd op when op != '(' && op != ')'; operand=parse_expr >] ->
    +      Ast.Unary (op, operand)
    +
    +  (* If the current token is not an operator, it must be a primary expr. *)
    +  | [< stream >] -> parse_primary stream
    +
    +
    + +

    The grammar we add is pretty straightforward here. If we see a unary +operator when parsing a primary operator, we eat the operator as a prefix and +parse the remaining piece as another unary operator. This allows us to handle +multiple unary operators (e.g. "!!x"). Note that unary operators can't have +ambiguous parses like binary operators can, so there is no need for precedence +information.

    + +

    The problem with this function, is that we need to call ParseUnary from +somewhere. To do this, we change previous callers of ParsePrimary to call +parse_unary instead:

    + +
    +
    +(* binoprhs
    + *   ::= ('+' primary)* *)
    +and parse_bin_rhs expr_prec lhs stream =
    +        ...
    +        (* Parse the unary expression after the binary operator. *)
    +        let rhs = parse_unary stream in
    +        ...
    +
    +...
    +
    +(* expression
    + *   ::= primary binoprhs *)
    +and parse_expr = parser
    +  | [< lhs=parse_unary; stream >] -> parse_bin_rhs 0 lhs stream
    +
    +
    + +

    With these two simple changes, we are now able to parse unary operators and build the +AST for them. Next up, we need to add parser support for prototypes, to parse +the unary operator prototype. We extend the binary operator code above +with:

    + +
    +
    +(* prototype
    + *   ::= id '(' id* ')'
    + *   ::= binary LETTER number? (id, id)
    + *   ::= unary LETTER number? (id) *)
    +let parse_prototype =
    +  let rec parse_args accumulator = parser
    +    | [< 'Token.Ident id; e=parse_args (id::accumulator) >] -> e
    +    | [< >] -> accumulator
    +  in
    +  let parse_operator = parser
    +    | [< 'Token.Unary >] -> "unary", 1
    +    | [< 'Token.Binary >] -> "binary", 2
    +  in
    +  let parse_binary_precedence = parser
    +    | [< 'Token.Number n >] -> int_of_float n
    +    | [< >] -> 30
    +  in
    +  parser
    +  | [< 'Token.Ident id;
    +       'Token.Kwd '(' ?? "expected '(' in prototype";
    +       args=parse_args [];
    +       'Token.Kwd ')' ?? "expected ')' in prototype" >] ->
    +      (* success. *)
    +      Ast.Prototype (id, Array.of_list (List.rev args))
    +  | [< (prefix, kind)=parse_operator;
    +       'Token.Kwd op ?? "expected an operator";
    +       (* Read the precedence if present. *)
    +       binary_precedence=parse_binary_precedence;
    +       'Token.Kwd '(' ?? "expected '(' in prototype";
    +        args=parse_args [];
    +       'Token.Kwd ')' ?? "expected ')' in prototype" >] ->
    +      let name = prefix ^ (String.make 1 op) in
    +      let args = Array.of_list (List.rev args) in
    +
    +      (* Verify right number of arguments for operator. *)
    +      if Array.length args != kind
    +      then raise (Stream.Error "invalid number of operands for operator")
    +      else
    +        if kind == 1 then
    +          Ast.Prototype (name, args)
    +        else
    +          Ast.BinOpPrototype (name, args, binary_precedence)
    +  | [< >] ->
    +      raise (Stream.Error "expected function name in prototype")
    +
    +
    + +

    As with binary operators, we name unary operators with a name that includes +the operator character. This assists us at code generation time. Speaking of, +the final piece we need to add is codegen support for unary operators. It looks +like this:

    + +
    +
    +let rec codegen_expr = function
    +  ...
    +  | Ast.Unary (op, operand) ->
    +      let operand = codegen_expr operand in
    +      let callee = "unary" ^ (String.make 1 op) in
    +      let callee =
    +        match lookup_function callee the_module with
    +        | Some callee -> callee
    +        | None -> raise (Error "unknown unary operator")
    +      in
    +      build_call callee [|operand|] "unop" builder
    +
    +
    + +

    This code is similar to, but simpler than, the code for binary operators. It +is simpler primarily because it doesn't need to handle any predefined operators. +

    + +
    + + + + + +
    + +

    It is somewhat hard to believe, but with a few simple extensions we've +covered in the last chapters, we have grown a real-ish language. With this, we +can do a lot of interesting things, including I/O, math, and a bunch of other +things. For example, we can now add a nice sequencing operator (printd is +defined to print out the specified value and a newline):

    + +
    +
    +ready> extern printd(x);
    +Read extern: declare double @printd(double)
    +ready> def binary : 1 (x y) 0;  # Low-precedence operator that ignores operands.
    +..
    +ready> printd(123) : printd(456) : printd(789);
    +123.000000
    +456.000000
    +789.000000
    +Evaluated to 0.000000
    +
    +
    + +

    We can also define a bunch of other "primitive" operations, such as:

    + +
    +
    +# Logical unary not.
    +def unary!(v)
    +  if v then
    +    0
    +  else
    +    1;
    +
    +# Unary negate.
    +def unary-(v)
    +  0-v;
    +
    +# Define > with the same precedence as >.
    +def binary> 10 (LHS RHS)
    +  RHS < LHS;
    +
    +# Binary logical or, which does not short circuit.
    +def binary| 5 (LHS RHS)
    +  if LHS then
    +    1
    +  else if RHS then
    +    1
    +  else
    +    0;
    +
    +# Binary logical and, which does not short circuit.
    +def binary& 6 (LHS RHS)
    +  if !LHS then
    +    0
    +  else
    +    !!RHS;
    +
    +# Define = with slightly lower precedence than relationals.
    +def binary = 9 (LHS RHS)
    +  !(LHS < RHS | LHS > RHS);
    +
    +
    +
    + + +

    Given the previous if/then/else support, we can also define interesting +functions for I/O. For example, the following prints out a character whose +"density" reflects the value passed in: the lower the value, the denser the +character:

    + +
    +
    +ready>
    +
    +extern putchard(char)
    +def printdensity(d)
    +  if d > 8 then
    +    putchard(32)  # ' '
    +  else if d > 4 then
    +    putchard(46)  # '.'
    +  else if d > 2 then
    +    putchard(43)  # '+'
    +  else
    +    putchard(42); # '*'
    +...
    +ready> printdensity(1): printdensity(2): printdensity(3) :
    +          printdensity(4): printdensity(5): printdensity(9): putchard(10);
    +*++..
    +Evaluated to 0.000000
    +
    +
    + +

    Based on these simple primitive operations, we can start to define more +interesting things. For example, here's a little function that solves for the +number of iterations it takes a function in the complex plane to +converge:

    + +
    +
    +# determine whether the specific location diverges.
    +# Solve for z = z^2 + c in the complex plane.
    +def mandleconverger(real imag iters creal cimag)
    +  if iters > 255 | (real*real + imag*imag > 4) then
    +    iters
    +  else
    +    mandleconverger(real*real - imag*imag + creal,
    +                    2*real*imag + cimag,
    +                    iters+1, creal, cimag);
    +
    +# return the number of iterations required for the iteration to escape
    +def mandleconverge(real imag)
    +  mandleconverger(real, imag, 0, real, imag);
    +
    +
    + +

    This "z = z2 + c" function is a beautiful little creature that is the basis +for computation of the Mandelbrot Set. Our +mandelconverge function returns the number of iterations that it takes +for a complex orbit to escape, saturating to 255. This is not a very useful +function by itself, but if you plot its value over a two-dimensional plane, +you can see the Mandelbrot set. Given that we are limited to using putchard +here, our amazing graphical output is limited, but we can whip together +something using the density plotter above:

    + +
    +
    +# compute and plot the mandlebrot set with the specified 2 dimensional range
    +# info.
    +def mandelhelp(xmin xmax xstep   ymin ymax ystep)
    +  for y = ymin, y < ymax, ystep in (
    +    (for x = xmin, x < xmax, xstep in
    +       printdensity(mandleconverge(x,y)))
    +    : putchard(10)
    +  )
    +
    +# mandel - This is a convenient helper function for ploting the mandelbrot set
    +# from the specified position with the specified Magnification.
    +def mandel(realstart imagstart realmag imagmag)
    +  mandelhelp(realstart, realstart+realmag*78, realmag,
    +             imagstart, imagstart+imagmag*40, imagmag);
    +
    +
    + +

    Given this, we can try plotting out the mandlebrot set! Lets try it out:

    + +
    +
    +ready> mandel(-2.3, -1.3, 0.05, 0.07);
    +*******************************+++++++++++*************************************
    +*************************+++++++++++++++++++++++*******************************
    +**********************+++++++++++++++++++++++++++++****************************
    +*******************+++++++++++++++++++++.. ...++++++++*************************
    +*****************++++++++++++++++++++++.... ...+++++++++***********************
    +***************+++++++++++++++++++++++.....   ...+++++++++*********************
    +**************+++++++++++++++++++++++....     ....+++++++++********************
    +*************++++++++++++++++++++++......      .....++++++++*******************
    +************+++++++++++++++++++++.......       .......+++++++******************
    +***********+++++++++++++++++++....                ... .+++++++*****************
    +**********+++++++++++++++++.......                     .+++++++****************
    +*********++++++++++++++...........                    ...+++++++***************
    +********++++++++++++............                      ...++++++++**************
    +********++++++++++... ..........                        .++++++++**************
    +*******+++++++++.....                                   .+++++++++*************
    +*******++++++++......                                  ..+++++++++*************
    +*******++++++.......                                   ..+++++++++*************
    +*******+++++......                                     ..+++++++++*************
    +*******.... ....                                      ...+++++++++*************
    +*******.... .                                         ...+++++++++*************
    +*******+++++......                                    ...+++++++++*************
    +*******++++++.......                                   ..+++++++++*************
    +*******++++++++......                                   .+++++++++*************
    +*******+++++++++.....                                  ..+++++++++*************
    +********++++++++++... ..........                        .++++++++**************
    +********++++++++++++............                      ...++++++++**************
    +*********++++++++++++++..........                     ...+++++++***************
    +**********++++++++++++++++........                     .+++++++****************
    +**********++++++++++++++++++++....                ... ..+++++++****************
    +***********++++++++++++++++++++++.......       .......++++++++*****************
    +************+++++++++++++++++++++++......      ......++++++++******************
    +**************+++++++++++++++++++++++....      ....++++++++********************
    +***************+++++++++++++++++++++++.....   ...+++++++++*********************
    +*****************++++++++++++++++++++++....  ...++++++++***********************
    +*******************+++++++++++++++++++++......++++++++*************************
    +*********************++++++++++++++++++++++.++++++++***************************
    +*************************+++++++++++++++++++++++*******************************
    +******************************+++++++++++++************************************
    +*******************************************************************************
    +*******************************************************************************
    +*******************************************************************************
    +Evaluated to 0.000000
    +ready> mandel(-2, -1, 0.02, 0.04);
    +**************************+++++++++++++++++++++++++++++++++++++++++++++++++++++
    +***********************++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    +*********************+++++++++++++++++++++++++++++++++++++++++++++++++++++++++.
    +*******************+++++++++++++++++++++++++++++++++++++++++++++++++++++++++...
    +*****************+++++++++++++++++++++++++++++++++++++++++++++++++++++++++.....
    +***************++++++++++++++++++++++++++++++++++++++++++++++++++++++++........
    +**************++++++++++++++++++++++++++++++++++++++++++++++++++++++...........
    +************+++++++++++++++++++++++++++++++++++++++++++++++++++++..............
    +***********++++++++++++++++++++++++++++++++++++++++++++++++++........        .
    +**********++++++++++++++++++++++++++++++++++++++++++++++.............
    +********+++++++++++++++++++++++++++++++++++++++++++..................
    +*******+++++++++++++++++++++++++++++++++++++++.......................
    +******+++++++++++++++++++++++++++++++++++...........................
    +*****++++++++++++++++++++++++++++++++............................
    +*****++++++++++++++++++++++++++++...............................
    +****++++++++++++++++++++++++++......   .........................
    +***++++++++++++++++++++++++.........     ......    ...........
    +***++++++++++++++++++++++............
    +**+++++++++++++++++++++..............
    +**+++++++++++++++++++................
    +*++++++++++++++++++.................
    +*++++++++++++++++............ ...
    +*++++++++++++++..............
    +*+++....++++................
    +*..........  ...........
    +*
    +*..........  ...........
    +*+++....++++................
    +*++++++++++++++..............
    +*++++++++++++++++............ ...
    +*++++++++++++++++++.................
    +**+++++++++++++++++++................
    +**+++++++++++++++++++++..............
    +***++++++++++++++++++++++............
    +***++++++++++++++++++++++++.........     ......    ...........
    +****++++++++++++++++++++++++++......   .........................
    +*****++++++++++++++++++++++++++++...............................
    +*****++++++++++++++++++++++++++++++++............................
    +******+++++++++++++++++++++++++++++++++++...........................
    +*******+++++++++++++++++++++++++++++++++++++++.......................
    +********+++++++++++++++++++++++++++++++++++++++++++..................
    +Evaluated to 0.000000
    +ready> mandel(-0.9, -1.4, 0.02, 0.03);
    +*******************************************************************************
    +*******************************************************************************
    +*******************************************************************************
    +**********+++++++++++++++++++++************************************************
    +*+++++++++++++++++++++++++++++++++++++++***************************************
    ++++++++++++++++++++++++++++++++++++++++++++++**********************************
    +++++++++++++++++++++++++++++++++++++++++++++++++++*****************************
    +++++++++++++++++++++++++++++++++++++++++++++++++++++++*************************
    ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++**********************
    ++++++++++++++++++++++++++++++++++.........++++++++++++++++++*******************
    ++++++++++++++++++++++++++++++++....   ......+++++++++++++++++++****************
    ++++++++++++++++++++++++++++++.......  ........+++++++++++++++++++**************
    +++++++++++++++++++++++++++++........   ........++++++++++++++++++++************
    ++++++++++++++++++++++++++++.........     ..  ...+++++++++++++++++++++**********
    +++++++++++++++++++++++++++...........        ....++++++++++++++++++++++********
    +++++++++++++++++++++++++.............       .......++++++++++++++++++++++******
    ++++++++++++++++++++++++.............        ........+++++++++++++++++++++++****
    +++++++++++++++++++++++...........           ..........++++++++++++++++++++++***
    +++++++++++++++++++++...........                .........++++++++++++++++++++++*
    +++++++++++++++++++............                  ...........++++++++++++++++++++
    +++++++++++++++++...............                 .............++++++++++++++++++
    +++++++++++++++.................                 ...............++++++++++++++++
    +++++++++++++..................                  .................++++++++++++++
    ++++++++++..................                      .................+++++++++++++
    +++++++........        .                               .........  ..++++++++++++
    +++............                                         ......    ....++++++++++
    +..............                                                    ...++++++++++
    +..............                                                    ....+++++++++
    +..............                                                    .....++++++++
    +.............                                                    ......++++++++
    +...........                                                     .......++++++++
    +.........                                                       ........+++++++
    +.........                                                       ........+++++++
    +.........                                                           ....+++++++
    +........                                                             ...+++++++
    +.......                                                              ...+++++++
    +                                                                    ....+++++++
    +                                                                   .....+++++++
    +                                                                    ....+++++++
    +                                                                    ....+++++++
    +                                                                    ....+++++++
    +Evaluated to 0.000000
    +ready> ^D
    +
    +
    + +

    At this point, you may be starting to realize that Kaleidoscope is a real +and powerful language. It may not be self-similar :), but it can be used to +plot things that are!

    + +

    With this, we conclude the "adding user-defined operators" chapter of the +tutorial. We have successfully augmented our language, adding the ability to +extend the language in the library, and we have shown how this can be used to +build a simple but interesting end-user application in Kaleidoscope. At this +point, Kaleidoscope can build a variety of applications that are functional and +can call functions with side-effects, but it can't actually define and mutate a +variable itself.

    + +

    Strikingly, variable mutation is an important feature of some +languages, and it is not at all obvious how to add +support for mutable variables without having to add an "SSA construction" +phase to your front-end. In the next chapter, we will describe how you can +add variable mutation without building SSA in your front-end.

    + +
    + + + + + + +
    + +

    +Here is the complete code listing for our running example, enhanced with the +if/then/else and for expressions.. To build this example, use: +

    + +
    +
    +# Compile
    +ocamlbuild toy.byte
    +# Run
    +./toy.byte
    +
    +
    + +

    Here is the code:

    + +
    +
    _tags:
    +
    +
    +<{lexer,parser}.ml>: use_camlp4, pp(camlp4of)
    +<*.{byte,native}>: g++, use_llvm, use_llvm_analysis
    +<*.{byte,native}>: use_llvm_executionengine, use_llvm_target
    +<*.{byte,native}>: use_llvm_scalar_opts, use_bindings
    +
    +
    + +
    myocamlbuild.ml:
    +
    +
    +open Ocamlbuild_plugin;;
    +
    +ocaml_lib ~extern:true "llvm";;
    +ocaml_lib ~extern:true "llvm_analysis";;
    +ocaml_lib ~extern:true "llvm_executionengine";;
    +ocaml_lib ~extern:true "llvm_target";;
    +ocaml_lib ~extern:true "llvm_scalar_opts";;
    +
    +flag ["link"; "ocaml"; "g++"] (S[A"-cc"; A"g++"]);;
    +dep ["link"; "ocaml"; "use_bindings"] ["bindings.o"];;
    +
    +
    + +
    token.ml:
    +
    +
    +(*===----------------------------------------------------------------------===
    + * Lexer Tokens
    + *===----------------------------------------------------------------------===*)
    +
    +(* The lexer returns these 'Kwd' if it is an unknown character, otherwise one of
    + * these others for known things. *)
    +type token =
    +  (* commands *)
    +  | Def | Extern
    +
    +  (* primary *)
    +  | Ident of string | Number of float
    +
    +  (* unknown *)
    +  | Kwd of char
    +
    +  (* control *)
    +  | If | Then | Else
    +  | For | In
    +
    +  (* operators *)
    +  | Binary | Unary
    +
    +
    + +
    lexer.ml:
    +
    +
    +(*===----------------------------------------------------------------------===
    + * Lexer
    + *===----------------------------------------------------------------------===*)
    +
    +let rec lex = parser
    +  (* Skip any whitespace. *)
    +  | [< ' (' ' | '\n' | '\r' | '\t'); stream >] -> lex stream
    +
    +  (* identifier: [a-zA-Z][a-zA-Z0-9] *)
    +  | [< ' ('A' .. 'Z' | 'a' .. 'z' as c); stream >] ->
    +      let buffer = Buffer.create 1 in
    +      Buffer.add_char buffer c;
    +      lex_ident buffer stream
    +
    +  (* number: [0-9.]+ *)
    +  | [< ' ('0' .. '9' as c); stream >] ->
    +      let buffer = Buffer.create 1 in
    +      Buffer.add_char buffer c;
    +      lex_number buffer stream
    +
    +  (* Comment until end of line. *)
    +  | [< ' ('#'); stream >] ->
    +      lex_comment stream
    +
    +  (* Otherwise, just return the character as its ascii value. *)
    +  | [< 'c; stream >] ->
    +      [< 'Token.Kwd c; lex stream >]
    +
    +  (* end of stream. *)
    +  | [< >] -> [< >]
    +
    +and lex_number buffer = parser
    +  | [< ' ('0' .. '9' | '.' as c); stream >] ->
    +      Buffer.add_char buffer c;
    +      lex_number buffer stream
    +  | [< stream=lex >] ->
    +      [< 'Token.Number (float_of_string (Buffer.contents buffer)); stream >]
    +
    +and lex_ident buffer = parser
    +  | [< ' ('A' .. 'Z' | 'a' .. 'z' | '0' .. '9' as c); stream >] ->
    +      Buffer.add_char buffer c;
    +      lex_ident buffer stream
    +  | [< stream=lex >] ->
    +      match Buffer.contents buffer with
    +      | "def" -> [< 'Token.Def; stream >]
    +      | "extern" -> [< 'Token.Extern; stream >]
    +      | "if" -> [< 'Token.If; stream >]
    +      | "then" -> [< 'Token.Then; stream >]
    +      | "else" -> [< 'Token.Else; stream >]
    +      | "for" -> [< 'Token.For; stream >]
    +      | "in" -> [< 'Token.In; stream >]
    +      | "binary" -> [< 'Token.Binary; stream >]
    +      | "unary" -> [< 'Token.Unary; stream >]
    +      | id -> [< 'Token.Ident id; stream >]
    +
    +and lex_comment = parser
    +  | [< ' ('\n'); stream=lex >] -> stream
    +  | [< 'c; e=lex_comment >] -> e
    +  | [< >] -> [< >]
    +
    +
    + +
    ast.ml:
    +
    +
    +(*===----------------------------------------------------------------------===
    + * Abstract Syntax Tree (aka Parse Tree)
    + *===----------------------------------------------------------------------===*)
    +
    +(* expr - Base type for all expression nodes. *)
    +type expr =
    +  (* variant for numeric literals like "1.0". *)
    +  | Number of float
    +
    +  (* variant for referencing a variable, like "a". *)
    +  | Variable of string
    +
    +  (* variant for a unary operator. *)
    +  | Unary of char * expr
    +
    +  (* variant for a binary operator. *)
    +  | Binary of char * expr * expr
    +
    +  (* variant for function calls. *)
    +  | Call of string * expr array
    +
    +  (* variant for if/then/else. *)
    +  | If of expr * expr * expr
    +
    +  (* variant for for/in. *)
    +  | For of string * expr * expr * expr option * expr
    +
    +(* proto - This type represents the "prototype" for a function, which captures
    + * its name, and its argument names (thus implicitly the number of arguments the
    + * function takes). *)
    +type proto =
    +  | Prototype of string * string array
    +  | BinOpPrototype of string * string array * int
    +
    +(* func - This type represents a function definition itself. *)
    +type func = Function of proto * expr
    +
    +
    + +
    parser.ml:
    +
    +
    +(*===---------------------------------------------------------------------===
    + * Parser
    + *===---------------------------------------------------------------------===*)
    +
    +(* binop_precedence - This holds the precedence for each binary operator that is
    + * defined *)
    +let binop_precedence:(char, int) Hashtbl.t = Hashtbl.create 10
    +
    +(* precedence - Get the precedence of the pending binary operator token. *)
    +let precedence c = try Hashtbl.find binop_precedence c with Not_found -> -1
    +
    +(* primary
    + *   ::= identifier
    + *   ::= numberexpr
    + *   ::= parenexpr
    + *   ::= ifexpr
    + *   ::= forexpr *)
    +let rec parse_primary = parser
    +  (* numberexpr ::= number *)
    +  | [< 'Token.Number n >] -> Ast.Number n
    +
    +  (* parenexpr ::= '(' expression ')' *)
    +  | [< 'Token.Kwd '('; e=parse_expr; 'Token.Kwd ')' ?? "expected ')'" >] -> e
    +
    +  (* identifierexpr
    +   *   ::= identifier
    +   *   ::= identifier '(' argumentexpr ')' *)
    +  | [< 'Token.Ident id; stream >] ->
    +      let rec parse_args accumulator = parser
    +        | [< e=parse_expr; stream >] ->
    +            begin parser
    +              | [< 'Token.Kwd ','; e=parse_args (e :: accumulator) >] -> e
    +              | [< >] -> e :: accumulator
    +            end stream
    +        | [< >] -> accumulator
    +      in
    +      let rec parse_ident id = parser
    +        (* Call. *)
    +        | [< 'Token.Kwd '(';
    +             args=parse_args [];
    +             'Token.Kwd ')' ?? "expected ')'">] ->
    +            Ast.Call (id, Array.of_list (List.rev args))
    +
    +        (* Simple variable ref. *)
    +        | [< >] -> Ast.Variable id
    +      in
    +      parse_ident id stream
    +
    +  (* ifexpr ::= 'if' expr 'then' expr 'else' expr *)
    +  | [< 'Token.If; c=parse_expr;
    +       'Token.Then ?? "expected 'then'"; t=parse_expr;
    +       'Token.Else ?? "expected 'else'"; e=parse_expr >] ->
    +      Ast.If (c, t, e)
    +
    +  (* forexpr
    +        ::= 'for' identifier '=' expr ',' expr (',' expr)? 'in' expression *)
    +  | [< 'Token.For;
    +       'Token.Ident id ?? "expected identifier after for";
    +       'Token.Kwd '=' ?? "expected '=' after for";
    +       stream >] ->
    +      begin parser
    +        | [<
    +             start=parse_expr;
    +             'Token.Kwd ',' ?? "expected ',' after for";
    +             end_=parse_expr;
    +             stream >] ->
    +            let step =
    +              begin parser
    +              | [< 'Token.Kwd ','; step=parse_expr >] -> Some step
    +              | [< >] -> None
    +              end stream
    +            in
    +            begin parser
    +            | [< 'Token.In; body=parse_expr >] ->
    +                Ast.For (id, start, end_, step, body)
    +            | [< >] ->
    +                raise (Stream.Error "expected 'in' after for")
    +            end stream
    +        | [< >] ->
    +            raise (Stream.Error "expected '=' after for")
    +      end stream
    +
    +  | [< >] -> raise (Stream.Error "unknown token when expecting an expression.")
    +
    +(* unary
    + *   ::= primary
    + *   ::= '!' unary *)
    +and parse_unary = parser
    +  (* If this is a unary operator, read it. *)
    +  | [< 'Token.Kwd op when op != '(' && op != ')'; operand=parse_expr >] ->
    +      Ast.Unary (op, operand)
    +
    +  (* If the current token is not an operator, it must be a primary expr. *)
    +  | [< stream >] -> parse_primary stream
    +
    +(* binoprhs
    + *   ::= ('+' primary)* *)
    +and parse_bin_rhs expr_prec lhs stream =
    +  match Stream.peek stream with
    +  (* If this is a binop, find its precedence. *)
    +  | Some (Token.Kwd c) when Hashtbl.mem binop_precedence c ->
    +      let token_prec = precedence c in
    +
    +      (* If this is a binop that binds at least as tightly as the current binop,
    +       * consume it, otherwise we are done. *)
    +      if token_prec < expr_prec then lhs else begin
    +        (* Eat the binop. *)
    +        Stream.junk stream;
    +
    +        (* Parse the unary expression after the binary operator. *)
    +        let rhs = parse_unary stream in
    +
    +        (* Okay, we know this is a binop. *)
    +        let rhs =
    +          match Stream.peek stream with
    +          | Some (Token.Kwd c2) ->
    +              (* If BinOp binds less tightly with rhs than the operator after
    +               * rhs, let the pending operator take rhs as its lhs. *)
    +              let next_prec = precedence c2 in
    +              if token_prec < next_prec
    +              then parse_bin_rhs (token_prec + 1) rhs stream
    +              else rhs
    +          | _ -> rhs
    +        in
    +
    +        (* Merge lhs/rhs. *)
    +        let lhs = Ast.Binary (c, lhs, rhs) in
    +        parse_bin_rhs expr_prec lhs stream
    +      end
    +  | _ -> lhs
    +
    +(* expression
    + *   ::= primary binoprhs *)
    +and parse_expr = parser
    +  | [< lhs=parse_unary; stream >] -> parse_bin_rhs 0 lhs stream
    +
    +(* prototype
    + *   ::= id '(' id* ')'
    + *   ::= binary LETTER number? (id, id)
    + *   ::= unary LETTER number? (id) *)
    +let parse_prototype =
    +  let rec parse_args accumulator = parser
    +    | [< 'Token.Ident id; e=parse_args (id::accumulator) >] -> e
    +    | [< >] -> accumulator
    +  in
    +  let parse_operator = parser
    +    | [< 'Token.Unary >] -> "unary", 1
    +    | [< 'Token.Binary >] -> "binary", 2
    +  in
    +  let parse_binary_precedence = parser
    +    | [< 'Token.Number n >] -> int_of_float n
    +    | [< >] -> 30
    +  in
    +  parser
    +  | [< 'Token.Ident id;
    +       'Token.Kwd '(' ?? "expected '(' in prototype";
    +       args=parse_args [];
    +       'Token.Kwd ')' ?? "expected ')' in prototype" >] ->
    +      (* success. *)
    +      Ast.Prototype (id, Array.of_list (List.rev args))
    +  | [< (prefix, kind)=parse_operator;
    +       'Token.Kwd op ?? "expected an operator";
    +       (* Read the precedence if present. *)
    +       binary_precedence=parse_binary_precedence;
    +       'Token.Kwd '(' ?? "expected '(' in prototype";
    +        args=parse_args [];
    +       'Token.Kwd ')' ?? "expected ')' in prototype" >] ->
    +      let name = prefix ^ (String.make 1 op) in
    +      let args = Array.of_list (List.rev args) in
    +
    +      (* Verify right number of arguments for operator. *)
    +      if Array.length args != kind
    +      then raise (Stream.Error "invalid number of operands for operator")
    +      else
    +        if kind == 1 then
    +          Ast.Prototype (name, args)
    +        else
    +          Ast.BinOpPrototype (name, args, binary_precedence)
    +  | [< >] ->
    +      raise (Stream.Error "expected function name in prototype")
    +
    +(* definition ::= 'def' prototype expression *)
    +let parse_definition = parser
    +  | [< 'Token.Def; p=parse_prototype; e=parse_expr >] ->
    +      Ast.Function (p, e)
    +
    +(* toplevelexpr ::= expression *)
    +let parse_toplevel = parser
    +  | [< e=parse_expr >] ->
    +      (* Make an anonymous proto. *)
    +      Ast.Function (Ast.Prototype ("", [||]), e)
    +
    +(*  external ::= 'extern' prototype *)
    +let parse_extern = parser
    +  | [< 'Token.Extern; e=parse_prototype >] -> e
    +
    +
    + +
    codegen.ml:
    +
    +
    +(*===----------------------------------------------------------------------===
    + * Code Generation
    + *===----------------------------------------------------------------------===*)
    +
    +open Llvm
    +
    +exception Error of string
    +
    +let context = global_context ()
    +let the_module = create_module context "my cool jit"
    +let builder = builder context
    +let named_values:(string, llvalue) Hashtbl.t = Hashtbl.create 10
    +
    +let rec codegen_expr = function
    +  | Ast.Number n -> const_float double_type n
    +  | Ast.Variable name ->
    +      (try Hashtbl.find named_values name with
    +        | Not_found -> raise (Error "unknown variable name"))
    +  | Ast.Unary (op, operand) ->
    +      let operand = codegen_expr operand in
    +      let callee = "unary" ^ (String.make 1 op) in
    +      let callee =
    +        match lookup_function callee the_module with
    +        | Some callee -> callee
    +        | None -> raise (Error "unknown unary operator")
    +      in
    +      build_call callee [|operand|] "unop" builder
    +  | Ast.Binary (op, lhs, rhs) ->
    +      let lhs_val = codegen_expr lhs in
    +      let rhs_val = codegen_expr rhs in
    +      begin
    +        match op with
    +        | '+' -> build_add lhs_val rhs_val "addtmp" builder
    +        | '-' -> build_sub lhs_val rhs_val "subtmp" builder
    +        | '*' -> build_mul lhs_val rhs_val "multmp" builder
    +        | '<' ->
    +            (* Convert bool 0/1 to double 0.0 or 1.0 *)
    +            let i = build_fcmp Fcmp.Ult lhs_val rhs_val "cmptmp" builder in
    +            build_uitofp i double_type "booltmp" builder
    +        | _ ->
    +            (* If it wasn't a builtin binary operator, it must be a user defined
    +             * one. Emit a call to it. *)
    +            let callee = "binary" ^ (String.make 1 op) in
    +            let callee =
    +              match lookup_function callee the_module with
    +              | Some callee -> callee
    +              | None -> raise (Error "binary operator not found!")
    +            in
    +            build_call callee [|lhs_val; rhs_val|] "binop" builder
    +      end
    +  | Ast.Call (callee, args) ->
    +      (* Look up the name in the module table. *)
    +      let callee =
    +        match lookup_function callee the_module with
    +        | Some callee -> callee
    +        | None -> raise (Error "unknown function referenced")
    +      in
    +      let params = params callee in
    +
    +      (* If argument mismatch error. *)
    +      if Array.length params == Array.length args then () else
    +        raise (Error "incorrect # arguments passed");
    +      let args = Array.map codegen_expr args in
    +      build_call callee args "calltmp" builder
    +  | Ast.If (cond, then_, else_) ->
    +      let cond = codegen_expr cond in
    +
    +      (* Convert condition to a bool by comparing equal to 0.0 *)
    +      let zero = const_float double_type 0.0 in
    +      let cond_val = build_fcmp Fcmp.One cond zero "ifcond" builder in
    +
    +      (* Grab the first block so that we might later add the conditional branch
    +       * to it at the end of the function. *)
    +      let start_bb = insertion_block builder in
    +      let the_function = block_parent start_bb in
    +
    +      let then_bb = append_block "then" the_function in
    +
    +      (* Emit 'then' value. *)
    +      position_at_end then_bb builder;
    +      let then_val = codegen_expr then_ in
    +
    +      (* Codegen of 'then' can change the current block, update then_bb for the
    +       * phi. We create a new name because one is used for the phi node, and the
    +       * other is used for the conditional branch. *)
    +      let new_then_bb = insertion_block builder in
    +
    +      (* Emit 'else' value. *)
    +      let else_bb = append_block "else" the_function in
    +      position_at_end else_bb builder;
    +      let else_val = codegen_expr else_ in
    +
    +      (* Codegen of 'else' can change the current block, update else_bb for the
    +       * phi. *)
    +      let new_else_bb = insertion_block builder in
    +
    +      (* Emit merge block. *)
    +      let merge_bb = append_block "ifcont" the_function in
    +      position_at_end merge_bb builder;
    +      let incoming = [(then_val, new_then_bb); (else_val, new_else_bb)] in
    +      let phi = build_phi incoming "iftmp" builder in
    +
    +      (* Return to the start block to add the conditional branch. *)
    +      position_at_end start_bb builder;
    +      ignore (build_cond_br cond_val then_bb else_bb builder);
    +
    +      (* Set a unconditional branch at the end of the 'then' block and the
    +       * 'else' block to the 'merge' block. *)
    +      position_at_end new_then_bb builder; ignore (build_br merge_bb builder);
    +      position_at_end new_else_bb builder; ignore (build_br merge_bb builder);
    +
    +      (* Finally, set the builder to the end of the merge block. *)
    +      position_at_end merge_bb builder;
    +
    +      phi
    +  | Ast.For (var_name, start, end_, step, body) ->
    +      (* Emit the start code first, without 'variable' in scope. *)
    +      let start_val = codegen_expr start in
    +
    +      (* Make the new basic block for the loop header, inserting after current
    +       * block. *)
    +      let preheader_bb = insertion_block builder in
    +      let the_function = block_parent preheader_bb in
    +      let loop_bb = append_block "loop" the_function in
    +
    +      (* Insert an explicit fall through from the current block to the
    +       * loop_bb. *)
    +      ignore (build_br loop_bb builder);
    +
    +      (* Start insertion in loop_bb. *)
    +      position_at_end loop_bb builder;
    +
    +      (* Start the PHI node with an entry for start. *)
    +      let variable = build_phi [(start_val, preheader_bb)] var_name builder in
    +
    +      (* Within the loop, the variable is defined equal to the PHI node. If it
    +       * shadows an existing variable, we have to restore it, so save it
    +       * now. *)
    +      let old_val =
    +        try Some (Hashtbl.find named_values var_name) with Not_found -> None
    +      in
    +      Hashtbl.add named_values var_name variable;
    +
    +      (* Emit the body of the loop.  This, like any other expr, can change the
    +       * current BB.  Note that we ignore the value computed by the body, but
    +       * don't allow an error *)
    +      ignore (codegen_expr body);
    +
    +      (* Emit the step value. *)
    +      let step_val =
    +        match step with
    +        | Some step -> codegen_expr step
    +        (* If not specified, use 1.0. *)
    +        | None -> const_float double_type 1.0
    +      in
    +
    +      let next_var = build_add variable step_val "nextvar" builder in
    +
    +      (* Compute the end condition. *)
    +      let end_cond = codegen_expr end_ in
    +
    +      (* Convert condition to a bool by comparing equal to 0.0. *)
    +      let zero = const_float double_type 0.0 in
    +      let end_cond = build_fcmp Fcmp.One end_cond zero "loopcond" builder in
    +
    +      (* Create the "after loop" block and insert it. *)
    +      let loop_end_bb = insertion_block builder in
    +      let after_bb = append_block "afterloop" the_function in
    +
    +      (* Insert the conditional branch into the end of loop_end_bb. *)
    +      ignore (build_cond_br end_cond loop_bb after_bb builder);
    +
    +      (* Any new code will be inserted in after_bb. *)
    +      position_at_end after_bb builder;
    +
    +      (* Add a new entry to the PHI node for the backedge. *)
    +      add_incoming (next_var, loop_end_bb) variable;
    +
    +      (* Restore the unshadowed variable. *)
    +      begin match old_val with
    +      | Some old_val -> Hashtbl.add named_values var_name old_val
    +      | None -> ()
    +      end;
    +
    +      (* for expr always returns 0.0. *)
    +      const_null double_type
    +
    +let codegen_proto = function
    +  | Ast.Prototype (name, args) | Ast.BinOpPrototype (name, args, _) ->
    +      (* Make the function type: double(double,double) etc. *)
    +      let doubles = Array.make (Array.length args) double_type in
    +      let ft = function_type double_type doubles in
    +      let f =
    +        match lookup_function name the_module with
    +        | None -> declare_function name ft the_module
    +
    +        (* If 'f' conflicted, there was already something named 'name'. If it
    +         * has a body, don't allow redefinition or reextern. *)
    +        | Some f ->
    +            (* If 'f' already has a body, reject this. *)
    +            if block_begin f <> At_end f then
    +              raise (Error "redefinition of function");
    +
    +            (* If 'f' took a different number of arguments, reject. *)
    +            if element_type (type_of f) <> ft then
    +              raise (Error "redefinition of function with different # args");
    +            f
    +      in
    +
    +      (* Set names for all arguments. *)
    +      Array.iteri (fun i a ->
    +        let n = args.(i) in
    +        set_value_name n a;
    +        Hashtbl.add named_values n a;
    +      ) (params f);
    +      f
    +
    +let codegen_func the_fpm = function
    +  | Ast.Function (proto, body) ->
    +      Hashtbl.clear named_values;
    +      let the_function = codegen_proto proto in
    +
    +      (* If this is an operator, install it. *)
    +      begin match proto with
    +      | Ast.BinOpPrototype (name, args, prec) ->
    +          let op = name.[String.length name - 1] in
    +          Hashtbl.add Parser.binop_precedence op prec;
    +      | _ -> ()
    +      end;
    +
    +      (* Create a new basic block to start insertion into. *)
    +      let bb = append_block "entry" the_function in
    +      position_at_end bb builder;
    +
    +      try
    +        let ret_val = codegen_expr body in
    +
    +        (* Finish off the function. *)
    +        let _ = build_ret ret_val builder in
    +
    +        (* Validate the generated code, checking for consistency. *)
    +        Llvm_analysis.assert_valid_function the_function;
    +
    +        (* Optimize the function. *)
    +        let _ = PassManager.run_function the_function the_fpm in
    +
    +        the_function
    +      with e ->
    +        delete_function the_function;
    +        raise e
    +
    +
    + +
    toplevel.ml:
    +
    +
    +(*===----------------------------------------------------------------------===
    + * Top-Level parsing and JIT Driver
    + *===----------------------------------------------------------------------===*)
    +
    +open Llvm
    +open Llvm_executionengine
    +
    +(* top ::= definition | external | expression | ';' *)
    +let rec main_loop the_fpm the_execution_engine stream =
    +  match Stream.peek stream with
    +  | None -> ()
    +
    +  (* ignore top-level semicolons. *)
    +  | Some (Token.Kwd ';') ->
    +      Stream.junk stream;
    +      main_loop the_fpm the_execution_engine stream
    +
    +  | Some token ->
    +      begin
    +        try match token with
    +        | Token.Def ->
    +            let e = Parser.parse_definition stream in
    +            print_endline "parsed a function definition.";
    +            dump_value (Codegen.codegen_func the_fpm e);
    +        | Token.Extern ->
    +            let e = Parser.parse_extern stream in
    +            print_endline "parsed an extern.";
    +            dump_value (Codegen.codegen_proto e);
    +        | _ ->
    +            (* Evaluate a top-level expression into an anonymous function. *)
    +            let e = Parser.parse_toplevel stream in
    +            print_endline "parsed a top-level expr";
    +            let the_function = Codegen.codegen_func the_fpm e in
    +            dump_value the_function;
    +
    +            (* JIT the function, returning a function pointer. *)
    +            let result = ExecutionEngine.run_function the_function [||]
    +              the_execution_engine in
    +
    +            print_string "Evaluated to ";
    +            print_float (GenericValue.as_float double_type result);
    +            print_newline ();
    +        with Stream.Error s | Codegen.Error s ->
    +          (* Skip token for error recovery. *)
    +          Stream.junk stream;
    +          print_endline s;
    +      end;
    +      print_string "ready> "; flush stdout;
    +      main_loop the_fpm the_execution_engine stream
    +
    +
    + +
    toy.ml:
    +
    +
    +(*===----------------------------------------------------------------------===
    + * Main driver code.
    + *===----------------------------------------------------------------------===*)
    +
    +open Llvm
    +open Llvm_executionengine
    +open Llvm_target
    +open Llvm_scalar_opts
    +
    +let main () =
    +  ignore (initialize_native_target ());
    +
    +  (* Install standard binary operators.
    +   * 1 is the lowest precedence. *)
    +  Hashtbl.add Parser.binop_precedence '<' 10;
    +  Hashtbl.add Parser.binop_precedence '+' 20;
    +  Hashtbl.add Parser.binop_precedence '-' 20;
    +  Hashtbl.add Parser.binop_precedence '*' 40;    (* highest. *)
    +
    +  (* Prime the first token. *)
    +  print_string "ready> "; flush stdout;
    +  let stream = Lexer.lex (Stream.of_channel stdin) in
    +
    +  (* Create the JIT. *)
    +  let the_module_provider = ModuleProvider.create Codegen.the_module in
    +  let the_execution_engine = ExecutionEngine.create the_module_provider in
    +  let the_fpm = PassManager.create_function the_module_provider in
    +
    +  (* Set up the optimizer pipeline.  Start with registering info about how the
    +   * target lays out data structures. *)
    +  TargetData.add (ExecutionEngine.target_data the_execution_engine) the_fpm;
    +
    +  (* Do simple "peephole" optimizations and bit-twiddling optzn. *)
    +  add_instruction_combining the_fpm;
    +
    +  (* reassociate expressions. *)
    +  add_reassociation the_fpm;
    +
    +  (* Eliminate Common SubExpressions. *)
    +  add_gvn the_fpm;
    +
    +  (* Simplify the control flow graph (deleting unreachable blocks, etc). *)
    +  add_cfg_simplification the_fpm;
    +
    +  ignore (PassManager.initialize the_fpm);
    +
    +  (* Run the main "interpreter loop" now. *)
    +  Toplevel.main_loop the_fpm the_execution_engine stream;
    +
    +  (* Print out all the generated code. *)
    +  dump_module Codegen.the_module
    +;;
    +
    +main ()
    +
    +
    + +
    bindings.c
    +
    +
    +#include <stdio.h>
    +
    +/* putchard - putchar that takes a double and returns 0. */
    +extern double putchard(double X) {
    +  putchar((char)X);
    +  return 0;
    +}
    +
    +/* printd - printf that takes a double prints it as "%f\n", returning 0. */
    +extern double printd(double X) {
    +  printf("%f\n", X);
    +  return 0;
    +}
    +
    +
    +
    + +Next: Extending the language: mutable variables / +SSA construction +
    + + +
    +
    + Valid CSS! + Valid HTML 4.01! + + Chris Lattner
    + Erick Tryzelaar
    + The LLVM Compiler Infrastructure
    + Last modified: $Date: 2007-10-17 11:05:13 -0700 (Wed, 17 Oct 2007) $ +
    + + diff --git a/libclamav/c++/llvm/docs/tutorial/OCamlLangImpl7.html b/libclamav/c++/llvm/docs/tutorial/OCamlLangImpl7.html new file mode 100644 index 000000000..07768214b --- /dev/null +++ b/libclamav/c++/llvm/docs/tutorial/OCamlLangImpl7.html @@ -0,0 +1,1907 @@ + + + + + Kaleidoscope: Extending the Language: Mutable Variables / SSA + construction + + + + + + + + +
    Kaleidoscope: Extending the Language: Mutable Variables
    + + + +
    +

    + Written by Chris Lattner + and Erick Tryzelaar +

    +
    + + + + + +
    + +

    Welcome to Chapter 7 of the "Implementing a language +with LLVM" tutorial. In chapters 1 through 6, we've built a very +respectable, albeit simple, functional +programming language. In our journey, we learned some parsing techniques, +how to build and represent an AST, how to build LLVM IR, and how to optimize +the resultant code as well as JIT compile it.

    + +

    While Kaleidoscope is interesting as a functional language, the fact that it +is functional makes it "too easy" to generate LLVM IR for it. In particular, a +functional language makes it very easy to build LLVM IR directly in SSA form. +Since LLVM requires that the input code be in SSA form, this is a very nice +property and it is often unclear to newcomers how to generate code for an +imperative language with mutable variables.

    + +

    The short (and happy) summary of this chapter is that there is no need for +your front-end to build SSA form: LLVM provides highly tuned and well tested +support for this, though the way it works is a bit unexpected for some.

    + +
    + + + + + +
    + +

    +To understand why mutable variables cause complexities in SSA construction, +consider this extremely simple C example: +

    + +
    +
    +int G, H;
    +int test(_Bool Condition) {
    +  int X;
    +  if (Condition)
    +    X = G;
    +  else
    +    X = H;
    +  return X;
    +}
    +
    +
    + +

    In this case, we have the variable "X", whose value depends on the path +executed in the program. Because there are two different possible values for X +before the return instruction, a PHI node is inserted to merge the two values. +The LLVM IR that we want for this example looks like this:

    + +
    +
    +@G = weak global i32 0   ; type of @G is i32*
    +@H = weak global i32 0   ; type of @H is i32*
    +
    +define i32 @test(i1 %Condition) {
    +entry:
    +  br i1 %Condition, label %cond_true, label %cond_false
    +
    +cond_true:
    +  %X.0 = load i32* @G
    +  br label %cond_next
    +
    +cond_false:
    +  %X.1 = load i32* @H
    +  br label %cond_next
    +
    +cond_next:
    +  %X.2 = phi i32 [ %X.1, %cond_false ], [ %X.0, %cond_true ]
    +  ret i32 %X.2
    +}
    +
    +
    + +

    In this example, the loads from the G and H global variables are explicit in +the LLVM IR, and they live in the then/else branches of the if statement +(cond_true/cond_false). In order to merge the incoming values, the X.2 phi node +in the cond_next block selects the right value to use based on where control +flow is coming from: if control flow comes from the cond_false block, X.2 gets +the value of X.1. Alternatively, if control flow comes from cond_true, it gets +the value of X.0. The intent of this chapter is not to explain the details of +SSA form. For more information, see one of the many online +references.

    + +

    The question for this article is "who places the phi nodes when lowering +assignments to mutable variables?". The issue here is that LLVM +requires that its IR be in SSA form: there is no "non-ssa" mode for it. +However, SSA construction requires non-trivial algorithms and data structures, +so it is inconvenient and wasteful for every front-end to have to reproduce this +logic.

    + +
    + + + + + +
    + +

    The 'trick' here is that while LLVM does require all register values to be +in SSA form, it does not require (or permit) memory objects to be in SSA form. +In the example above, note that the loads from G and H are direct accesses to +G and H: they are not renamed or versioned. This differs from some other +compiler systems, which do try to version memory objects. In LLVM, instead of +encoding dataflow analysis of memory into the LLVM IR, it is handled with Analysis Passes which are computed on +demand.

    + +

    +With this in mind, the high-level idea is that we want to make a stack variable +(which lives in memory, because it is on the stack) for each mutable object in +a function. To take advantage of this trick, we need to talk about how LLVM +represents stack variables. +

    + +

    In LLVM, all memory accesses are explicit with load/store instructions, and +it is carefully designed not to have (or need) an "address-of" operator. Notice +how the type of the @G/@H global variables is actually "i32*" even though the +variable is defined as "i32". What this means is that @G defines space +for an i32 in the global data area, but its name actually refers to the +address for that space. Stack variables work the same way, except that instead of +being declared with global variable definitions, they are declared with the +LLVM alloca instruction:

    + +
    +
    +define i32 @example() {
    +entry:
    +  %X = alloca i32           ; type of %X is i32*.
    +  ...
    +  %tmp = load i32* %X       ; load the stack value %X from the stack.
    +  %tmp2 = add i32 %tmp, 1   ; increment it
    +  store i32 %tmp2, i32* %X  ; store it back
    +  ...
    +
    +
    + +

    This code shows an example of how you can declare and manipulate a stack +variable in the LLVM IR. Stack memory allocated with the alloca instruction is +fully general: you can pass the address of the stack slot to functions, you can +store it in other variables, etc. In our example above, we could rewrite the +example to use the alloca technique to avoid using a PHI node:

    + +
    +
    +@G = weak global i32 0   ; type of @G is i32*
    +@H = weak global i32 0   ; type of @H is i32*
    +
    +define i32 @test(i1 %Condition) {
    +entry:
    +  %X = alloca i32           ; type of %X is i32*.
    +  br i1 %Condition, label %cond_true, label %cond_false
    +
    +cond_true:
    +  %X.0 = load i32* @G
    +        store i32 %X.0, i32* %X   ; Update X
    +  br label %cond_next
    +
    +cond_false:
    +  %X.1 = load i32* @H
    +        store i32 %X.1, i32* %X   ; Update X
    +  br label %cond_next
    +
    +cond_next:
    +  %X.2 = load i32* %X       ; Read X
    +  ret i32 %X.2
    +}
    +
    +
    + +

    With this, we have discovered a way to handle arbitrary mutable variables +without the need to create Phi nodes at all:

    + +
      +
    1. Each mutable variable becomes a stack allocation.
    2. +
    3. Each read of the variable becomes a load from the stack.
    4. +
    5. Each update of the variable becomes a store to the stack.
    6. +
    7. Taking the address of a variable just uses the stack address directly.
    8. +
    + +

    While this solution has solved our immediate problem, it introduced another +one: we have now apparently introduced a lot of stack traffic for very simple +and common operations, a major performance problem. Fortunately for us, the +LLVM optimizer has a highly-tuned optimization pass named "mem2reg" that handles +this case, promoting allocas like this into SSA registers, inserting Phi nodes +as appropriate. If you run this example through the pass, for example, you'll +get:

    + +
    +
    +$ llvm-as < example.ll | opt -mem2reg | llvm-dis
    +@G = weak global i32 0
    +@H = weak global i32 0
    +
    +define i32 @test(i1 %Condition) {
    +entry:
    +  br i1 %Condition, label %cond_true, label %cond_false
    +
    +cond_true:
    +  %X.0 = load i32* @G
    +  br label %cond_next
    +
    +cond_false:
    +  %X.1 = load i32* @H
    +  br label %cond_next
    +
    +cond_next:
    +  %X.01 = phi i32 [ %X.1, %cond_false ], [ %X.0, %cond_true ]
    +  ret i32 %X.01
    +}
    +
    +
    + +

    The mem2reg pass implements the standard "iterated dominance frontier" +algorithm for constructing SSA form and has a number of optimizations that speed +up (very common) degenerate cases. The mem2reg optimization pass is the answer +to dealing with mutable variables, and we highly recommend that you depend on +it. Note that mem2reg only works on variables in certain circumstances:

    + +
      +
    1. mem2reg is alloca-driven: it looks for allocas and if it can handle them, it +promotes them. It does not apply to global variables or heap allocations.
    2. + +
    3. mem2reg only looks for alloca instructions in the entry block of the +function. Being in the entry block guarantees that the alloca is only executed +once, which makes analysis simpler.
    4. + +
    5. mem2reg only promotes allocas whose uses are direct loads and stores. If +the address of the stack object is passed to a function, or if any funny pointer +arithmetic is involved, the alloca will not be promoted.
    6. + +
    7. mem2reg only works on allocas of first class +values (such as pointers, scalars and vectors), and only if the array size +of the allocation is 1 (or missing in the .ll file). mem2reg is not capable of +promoting structs or arrays to registers. Note that the "scalarrepl" pass is +more powerful and can promote structs, "unions", and arrays in many cases.
    8. + +
    + +

    +All of these properties are easy to satisfy for most imperative languages, and +we'll illustrate it below with Kaleidoscope. The final question you may be +asking is: should I bother with this nonsense for my front-end? Wouldn't it be +better if I just did SSA construction directly, avoiding use of the mem2reg +optimization pass? In short, we strongly recommend that you use this technique +for building SSA form, unless there is an extremely good reason not to. Using +this technique is:

    + +
      +
    • Proven and well tested: llvm-gcc and clang both use this technique for local +mutable variables. As such, the most common clients of LLVM are using this to +handle a bulk of their variables. You can be sure that bugs are found fast and +fixed early.
    • + +
    • Extremely Fast: mem2reg has a number of special cases that make it fast in +common cases as well as fully general. For example, it has fast-paths for +variables that are only used in a single block, variables that only have one +assignment point, good heuristics to avoid insertion of unneeded phi nodes, etc. +
    • + +
    • Needed for debug info generation: +Debug information in LLVM relies on having the address of the variable +exposed so that debug info can be attached to it. This technique dovetails +very naturally with this style of debug info.
    • +
    + +

    If nothing else, this makes it much easier to get your front-end up and +running, and is very simple to implement. Lets extend Kaleidoscope with mutable +variables now! +

    + +
    + + + + + +
    + +

    Now that we know the sort of problem we want to tackle, lets see what this +looks like in the context of our little Kaleidoscope language. We're going to +add two features:

    + +
      +
    1. The ability to mutate variables with the '=' operator.
    2. +
    3. The ability to define new variables.
    4. +
    + +

    While the first item is really what this is about, we only have variables +for incoming arguments as well as for induction variables, and redefining those only +goes so far :). Also, the ability to define new variables is a +useful thing regardless of whether you will be mutating them. Here's a +motivating example that shows how we could use these:

    + +
    +
    +# Define ':' for sequencing: as a low-precedence operator that ignores operands
    +# and just returns the RHS.
    +def binary : 1 (x y) y;
    +
    +# Recursive fib, we could do this before.
    +def fib(x)
    +  if (x < 3) then
    +    1
    +  else
    +    fib(x-1)+fib(x-2);
    +
    +# Iterative fib.
    +def fibi(x)
    +  var a = 1, b = 1, c in
    +  (for i = 3, i < x in
    +     c = a + b :
    +     a = b :
    +     b = c) :
    +  b;
    +
    +# Call it.
    +fibi(10);
    +
    +
    + +

    +In order to mutate variables, we have to change our existing variables to use +the "alloca trick". Once we have that, we'll add our new operator, then extend +Kaleidoscope to support new variable definitions. +

    + +
    + + + + + +
    + +

    +The symbol table in Kaleidoscope is managed at code generation time by the +'named_values' map. This map currently keeps track of the LLVM +"Value*" that holds the double value for the named variable. In order to +support mutation, we need to change this slightly, so that it +named_values holds the memory location of the variable in +question. Note that this change is a refactoring: it changes the structure of +the code, but does not (by itself) change the behavior of the compiler. All of +these changes are isolated in the Kaleidoscope code generator.

    + +

    +At this point in Kaleidoscope's development, it only supports variables for two +things: incoming arguments to functions and the induction variable of 'for' +loops. For consistency, we'll allow mutation of these variables in addition to +other user-defined variables. This means that these will both need memory +locations. +

    + +

    To start our transformation of Kaleidoscope, we'll change the +named_values map so that it maps to AllocaInst* instead of Value*. +Once we do this, the C++ compiler will tell us what parts of the code we need to +update:

    + +

    Note: the ocaml bindings currently model both Value*s and +AllocInst*s as Llvm.llvalues, but this may change in the +future to be more type safe.

    + +
    +
    +let named_values:(string, llvalue) Hashtbl.t = Hashtbl.create 10
    +
    +
    + +

    Also, since we will need to create these alloca's, we'll use a helper +function that ensures that the allocas are created in the entry block of the +function:

    + +
    +
    +(* Create an alloca instruction in the entry block of the function. This
    + * is used for mutable variables etc. *)
    +let create_entry_block_alloca the_function var_name =
    +  let builder = builder_at (instr_begin (entry_block the_function)) in
    +  build_alloca double_type var_name builder
    +
    +
    + +

    This funny looking code creates an Llvm.llbuilder object that is +pointing at the first instruction of the entry block. It then creates an alloca +with the expected name and returns it. Because all values in Kaleidoscope are +doubles, there is no need to pass in a type to use.

    + +

    With this in place, the first functionality change we want to make is to +variable references. In our new scheme, variables live on the stack, so code +generating a reference to them actually needs to produce a load from the stack +slot:

    + +
    +
    +let rec codegen_expr = function
    +  ...
    +  | Ast.Variable name ->
    +      let v = try Hashtbl.find named_values name with
    +        | Not_found -> raise (Error "unknown variable name")
    +      in
    +      (* Load the value. *)
    +      build_load v name builder
    +
    +
    + +

    As you can see, this is pretty straightforward. Now we need to update the +things that define the variables to set up the alloca. We'll start with +codegen_expr Ast.For ... (see the full code listing +for the unabridged code):

    + +
    +
    +  | Ast.For (var_name, start, end_, step, body) ->
    +      let the_function = block_parent (insertion_block builder) in
    +
    +      (* Create an alloca for the variable in the entry block. *)
    +      let alloca = create_entry_block_alloca the_function var_name in
    +
    +      (* Emit the start code first, without 'variable' in scope. *)
    +      let start_val = codegen_expr start in
    +
    +      (* Store the value into the alloca. *)
    +      ignore(build_store start_val alloca builder);
    +
    +      ...
    +
    +      (* Within the loop, the variable is defined equal to the PHI node. If it
    +       * shadows an existing variable, we have to restore it, so save it
    +       * now. *)
    +      let old_val =
    +        try Some (Hashtbl.find named_values var_name) with Not_found -> None
    +      in
    +      Hashtbl.add named_values var_name alloca;
    +
    +      ...
    +
    +      (* Compute the end condition. *)
    +      let end_cond = codegen_expr end_ in
    +
    +      (* Reload, increment, and restore the alloca. This handles the case where
    +       * the body of the loop mutates the variable. *)
    +      let cur_var = build_load alloca var_name builder in
    +      let next_var = build_add cur_var step_val "nextvar" builder in
    +      ignore(build_store next_var alloca builder);
    +      ...
    +
    +
    + +

    This code is virtually identical to the code before we allowed mutable variables. +The big difference is that we no longer have to construct a PHI node, and we use +load/store to access the variable as needed.

    + +

    To support mutable argument variables, we need to also make allocas for them. +The code for this is also pretty simple:

    + +
    +
    +(* Create an alloca for each argument and register the argument in the symbol
    + * table so that references to it will succeed. *)
    +let create_argument_allocas the_function proto =
    +  let args = match proto with
    +    | Ast.Prototype (_, args) | Ast.BinOpPrototype (_, args, _) -> args
    +  in
    +  Array.iteri (fun i ai ->
    +    let var_name = args.(i) in
    +    (* Create an alloca for this variable. *)
    +    let alloca = create_entry_block_alloca the_function var_name in
    +
    +    (* Store the initial value into the alloca. *)
    +    ignore(build_store ai alloca builder);
    +
    +    (* Add arguments to variable symbol table. *)
    +    Hashtbl.add named_values var_name alloca;
    +  ) (params the_function)
    +
    +
    + +

    For each argument, we make an alloca, store the input value to the function +into the alloca, and register the alloca as the memory location for the +argument. This method gets invoked by Codegen.codegen_func right after +it sets up the entry block for the function.

    + +

    The final missing piece is adding the mem2reg pass, which allows us to get +good codegen once again:

    + +
    +
    +let main () =
    +  ...
    +  let the_fpm = PassManager.create_function the_module_provider in
    +
    +  (* Set up the optimizer pipeline.  Start with registering info about how the
    +   * target lays out data structures. *)
    +  TargetData.add (ExecutionEngine.target_data the_execution_engine) the_fpm;
    +
    +  (* Promote allocas to registers. *)
    +  add_memory_to_register_promotion the_fpm;
    +
    +  (* Do simple "peephole" optimizations and bit-twiddling optzn. *)
    +  add_instruction_combining the_fpm;
    +
    +  (* reassociate expressions. *)
    +  add_reassociation the_fpm;
    +
    +
    + +

    It is interesting to see what the code looks like before and after the +mem2reg optimization runs. For example, this is the before/after code for our +recursive fib function. Before the optimization:

    + +
    +
    +define double @fib(double %x) {
    +entry:
    +  %x1 = alloca double
    +  store double %x, double* %x1
    +  %x2 = load double* %x1
    +  %cmptmp = fcmp ult double %x2, 3.000000e+00
    +  %booltmp = uitofp i1 %cmptmp to double
    +  %ifcond = fcmp one double %booltmp, 0.000000e+00
    +  br i1 %ifcond, label %then, label %else
    +
    +then:    ; preds = %entry
    +  br label %ifcont
    +
    +else:    ; preds = %entry
    +  %x3 = load double* %x1
    +  %subtmp = sub double %x3, 1.000000e+00
    +  %calltmp = call double @fib( double %subtmp )
    +  %x4 = load double* %x1
    +  %subtmp5 = sub double %x4, 2.000000e+00
    +  %calltmp6 = call double @fib( double %subtmp5 )
    +  %addtmp = add double %calltmp, %calltmp6
    +  br label %ifcont
    +
    +ifcont:    ; preds = %else, %then
    +  %iftmp = phi double [ 1.000000e+00, %then ], [ %addtmp, %else ]
    +  ret double %iftmp
    +}
    +
    +
    + +

    Here there is only one variable (x, the input argument) but you can still +see the extremely simple-minded code generation strategy we are using. In the +entry block, an alloca is created, and the initial input value is stored into +it. Each reference to the variable does a reload from the stack. Also, note +that we didn't modify the if/then/else expression, so it still inserts a PHI +node. While we could make an alloca for it, it is actually easier to create a +PHI node for it, so we still just make the PHI.

    + +

    Here is the code after the mem2reg pass runs:

    + +
    +
    +define double @fib(double %x) {
    +entry:
    +  %cmptmp = fcmp ult double %x, 3.000000e+00
    +  %booltmp = uitofp i1 %cmptmp to double
    +  %ifcond = fcmp one double %booltmp, 0.000000e+00
    +  br i1 %ifcond, label %then, label %else
    +
    +then:
    +  br label %ifcont
    +
    +else:
    +  %subtmp = sub double %x, 1.000000e+00
    +  %calltmp = call double @fib( double %subtmp )
    +  %subtmp5 = sub double %x, 2.000000e+00
    +  %calltmp6 = call double @fib( double %subtmp5 )
    +  %addtmp = add double %calltmp, %calltmp6
    +  br label %ifcont
    +
    +ifcont:    ; preds = %else, %then
    +  %iftmp = phi double [ 1.000000e+00, %then ], [ %addtmp, %else ]
    +  ret double %iftmp
    +}
    +
    +
    + +

    This is a trivial case for mem2reg, since there are no redefinitions of the +variable. The point of showing this is to calm your tension about inserting +such blatent inefficiencies :).

    + +

    After the rest of the optimizers run, we get:

    + +
    +
    +define double @fib(double %x) {
    +entry:
    +  %cmptmp = fcmp ult double %x, 3.000000e+00
    +  %booltmp = uitofp i1 %cmptmp to double
    +  %ifcond = fcmp ueq double %booltmp, 0.000000e+00
    +  br i1 %ifcond, label %else, label %ifcont
    +
    +else:
    +  %subtmp = sub double %x, 1.000000e+00
    +  %calltmp = call double @fib( double %subtmp )
    +  %subtmp5 = sub double %x, 2.000000e+00
    +  %calltmp6 = call double @fib( double %subtmp5 )
    +  %addtmp = add double %calltmp, %calltmp6
    +  ret double %addtmp
    +
    +ifcont:
    +  ret double 1.000000e+00
    +}
    +
    +
    + +

    Here we see that the simplifycfg pass decided to clone the return instruction +into the end of the 'else' block. This allowed it to eliminate some branches +and the PHI node.

    + +

    Now that all symbol table references are updated to use stack variables, +we'll add the assignment operator.

    + +
    + + + + + +
    + +

    With our current framework, adding a new assignment operator is really +simple. We will parse it just like any other binary operator, but handle it +internally (instead of allowing the user to define it). The first step is to +set a precedence:

    + +
    +
    +let main () =
    +  (* Install standard binary operators.
    +   * 1 is the lowest precedence. *)
    +  Hashtbl.add Parser.binop_precedence '=' 2;
    +  Hashtbl.add Parser.binop_precedence '<' 10;
    +  Hashtbl.add Parser.binop_precedence '+' 20;
    +  Hashtbl.add Parser.binop_precedence '-' 20;
    +  ...
    +
    +
    + +

    Now that the parser knows the precedence of the binary operator, it takes +care of all the parsing and AST generation. We just need to implement codegen +for the assignment operator. This looks like:

    + +
    +
    +let rec codegen_expr = function
    +      begin match op with
    +      | '=' ->
    +          (* Special case '=' because we don't want to emit the LHS as an
    +           * expression. *)
    +          let name =
    +            match lhs with
    +            | Ast.Variable name -> name
    +            | _ -> raise (Error "destination of '=' must be a variable")
    +          in
    +
    +
    + +

    Unlike the rest of the binary operators, our assignment operator doesn't +follow the "emit LHS, emit RHS, do computation" model. As such, it is handled +as a special case before the other binary operators are handled. The other +strange thing is that it requires the LHS to be a variable. It is invalid to +have "(x+1) = expr" - only things like "x = expr" are allowed. +

    + + +
    +
    +          (* Codegen the rhs. *)
    +          let val_ = codegen_expr rhs in
    +
    +          (* Lookup the name. *)
    +          let variable = try Hashtbl.find named_values name with
    +          | Not_found -> raise (Error "unknown variable name")
    +          in
    +          ignore(build_store val_ variable builder);
    +          val_
    +      | _ ->
    +			...
    +
    +
    + +

    Once we have the variable, codegen'ing the assignment is straightforward: +we emit the RHS of the assignment, create a store, and return the computed +value. Returning a value allows for chained assignments like "X = (Y = Z)".

    + +

    Now that we have an assignment operator, we can mutate loop variables and +arguments. For example, we can now run code like this:

    + +
    +
    +# Function to print a double.
    +extern printd(x);
    +
    +# Define ':' for sequencing: as a low-precedence operator that ignores operands
    +# and just returns the RHS.
    +def binary : 1 (x y) y;
    +
    +def test(x)
    +  printd(x) :
    +  x = 4 :
    +  printd(x);
    +
    +test(123);
    +
    +
    + +

    When run, this example prints "123" and then "4", showing that we did +actually mutate the value! Okay, we have now officially implemented our goal: +getting this to work requires SSA construction in the general case. However, +to be really useful, we want the ability to define our own local variables, lets +add this next! +

    + +
    + + + + + +
    + +

    Adding var/in is just like any other other extensions we made to +Kaleidoscope: we extend the lexer, the parser, the AST and the code generator. +The first step for adding our new 'var/in' construct is to extend the lexer. +As before, this is pretty trivial, the code looks like this:

    + +
    +
    +type token =
    +  ...
    +  (* var definition *)
    +  | Var
    +
    +...
    +
    +and lex_ident buffer = parser
    +      ...
    +      | "in" -> [< 'Token.In; stream >]
    +      | "binary" -> [< 'Token.Binary; stream >]
    +      | "unary" -> [< 'Token.Unary; stream >]
    +      | "var" -> [< 'Token.Var; stream >]
    +      ...
    +
    +
    + +

    The next step is to define the AST node that we will construct. For var/in, +it looks like this:

    + +
    +
    +type expr =
    +  ...
    +  (* variant for var/in. *)
    +  | Var of (string * expr option) array * expr
    +  ...
    +
    +
    + +

    var/in allows a list of names to be defined all at once, and each name can +optionally have an initializer value. As such, we capture this information in +the VarNames vector. Also, var/in has a body, this body is allowed to access +the variables defined by the var/in.

    + +

    With this in place, we can define the parser pieces. The first thing we do +is add it as a primary expression:

    + +
    +
    +(* primary
    + *   ::= identifier
    + *   ::= numberexpr
    + *   ::= parenexpr
    + *   ::= ifexpr
    + *   ::= forexpr
    + *   ::= varexpr *)
    +let rec parse_primary = parser
    +  ...
    +  (* varexpr
    +   *   ::= 'var' identifier ('=' expression?
    +   *             (',' identifier ('=' expression)?)* 'in' expression *)
    +  | [< 'Token.Var;
    +       (* At least one variable name is required. *)
    +       'Token.Ident id ?? "expected identifier after var";
    +       init=parse_var_init;
    +       var_names=parse_var_names [(id, init)];
    +       (* At this point, we have to have 'in'. *)
    +       'Token.In ?? "expected 'in' keyword after 'var'";
    +       body=parse_expr >] ->
    +      Ast.Var (Array.of_list (List.rev var_names), body)
    +
    +...
    +
    +and parse_var_init = parser
    +  (* read in the optional initializer. *)
    +  | [< 'Token.Kwd '='; e=parse_expr >] -> Some e
    +  | [< >] -> None
    +
    +and parse_var_names accumulator = parser
    +  | [< 'Token.Kwd ',';
    +       'Token.Ident id ?? "expected identifier list after var";
    +       init=parse_var_init;
    +       e=parse_var_names ((id, init) :: accumulator) >] -> e
    +  | [< >] -> accumulator
    +
    +
    + +

    Now that we can parse and represent the code, we need to support emission of +LLVM IR for it. This code starts out with:

    + +
    +
    +let rec codegen_expr = function
    +  ...
    +  | Ast.Var (var_names, body)
    +      let old_bindings = ref [] in
    +
    +      let the_function = block_parent (insertion_block builder) in
    +
    +      (* Register all variables and emit their initializer. *)
    +      Array.iter (fun (var_name, init) ->
    +
    +
    + +

    Basically it loops over all the variables, installing them one at a time. +For each variable we put into the symbol table, we remember the previous value +that we replace in OldBindings.

    + +
    +
    +        (* Emit the initializer before adding the variable to scope, this
    +         * prevents the initializer from referencing the variable itself, and
    +         * permits stuff like this:
    +         *   var a = 1 in
    +         *     var a = a in ...   # refers to outer 'a'. *)
    +        let init_val =
    +          match init with
    +          | Some init -> codegen_expr init
    +          (* If not specified, use 0.0. *)
    +          | None -> const_float double_type 0.0
    +        in
    +
    +        let alloca = create_entry_block_alloca the_function var_name in
    +        ignore(build_store init_val alloca builder);
    +
    +        (* Remember the old variable binding so that we can restore the binding
    +         * when we unrecurse. *)
    +
    +        begin
    +          try
    +            let old_value = Hashtbl.find named_values var_name in
    +            old_bindings := (var_name, old_value) :: !old_bindings;
    +          with Not_found > ()
    +        end;
    +
    +        (* Remember this binding. *)
    +        Hashtbl.add named_values var_name alloca;
    +      ) var_names;
    +
    +
    + +

    There are more comments here than code. The basic idea is that we emit the +initializer, create the alloca, then update the symbol table to point to it. +Once all the variables are installed in the symbol table, we evaluate the body +of the var/in expression:

    + +
    +
    +      (* Codegen the body, now that all vars are in scope. *)
    +      let body_val = codegen_expr body in
    +
    +
    + +

    Finally, before returning, we restore the previous variable bindings:

    + +
    +
    +      (* Pop all our variables from scope. *)
    +      List.iter (fun (var_name, old_value) ->
    +        Hashtbl.add named_values var_name old_value
    +      ) !old_bindings;
    +
    +      (* Return the body computation. *)
    +      body_val
    +
    +
    + +

    The end result of all of this is that we get properly scoped variable +definitions, and we even (trivially) allow mutation of them :).

    + +

    With this, we completed what we set out to do. Our nice iterative fib +example from the intro compiles and runs just fine. The mem2reg pass optimizes +all of our stack variables into SSA registers, inserting PHI nodes where needed, +and our front-end remains simple: no "iterated dominance frontier" computation +anywhere in sight.

    + +
    + + + + + +
    + +

    +Here is the complete code listing for our running example, enhanced with mutable +variables and var/in support. To build this example, use: +

    + +
    +
    +# Compile
    +ocamlbuild toy.byte
    +# Run
    +./toy.byte
    +
    +
    + +

    Here is the code:

    + +
    +
    _tags:
    +
    +
    +<{lexer,parser}.ml>: use_camlp4, pp(camlp4of)
    +<*.{byte,native}>: g++, use_llvm, use_llvm_analysis
    +<*.{byte,native}>: use_llvm_executionengine, use_llvm_target
    +<*.{byte,native}>: use_llvm_scalar_opts, use_bindings
    +
    +
    + +
    myocamlbuild.ml:
    +
    +
    +open Ocamlbuild_plugin;;
    +
    +ocaml_lib ~extern:true "llvm";;
    +ocaml_lib ~extern:true "llvm_analysis";;
    +ocaml_lib ~extern:true "llvm_executionengine";;
    +ocaml_lib ~extern:true "llvm_target";;
    +ocaml_lib ~extern:true "llvm_scalar_opts";;
    +
    +flag ["link"; "ocaml"; "g++"] (S[A"-cc"; A"g++"]);;
    +dep ["link"; "ocaml"; "use_bindings"] ["bindings.o"];;
    +
    +
    + +
    token.ml:
    +
    +
    +(*===----------------------------------------------------------------------===
    + * Lexer Tokens
    + *===----------------------------------------------------------------------===*)
    +
    +(* The lexer returns these 'Kwd' if it is an unknown character, otherwise one of
    + * these others for known things. *)
    +type token =
    +  (* commands *)
    +  | Def | Extern
    +
    +  (* primary *)
    +  | Ident of string | Number of float
    +
    +  (* unknown *)
    +  | Kwd of char
    +
    +  (* control *)
    +  | If | Then | Else
    +  | For | In
    +
    +  (* operators *)
    +  | Binary | Unary
    +
    +  (* var definition *)
    +  | Var
    +
    +
    + +
    lexer.ml:
    +
    +
    +(*===----------------------------------------------------------------------===
    + * Lexer
    + *===----------------------------------------------------------------------===*)
    +
    +let rec lex = parser
    +  (* Skip any whitespace. *)
    +  | [< ' (' ' | '\n' | '\r' | '\t'); stream >] -> lex stream
    +
    +  (* identifier: [a-zA-Z][a-zA-Z0-9] *)
    +  | [< ' ('A' .. 'Z' | 'a' .. 'z' as c); stream >] ->
    +      let buffer = Buffer.create 1 in
    +      Buffer.add_char buffer c;
    +      lex_ident buffer stream
    +
    +  (* number: [0-9.]+ *)
    +  | [< ' ('0' .. '9' as c); stream >] ->
    +      let buffer = Buffer.create 1 in
    +      Buffer.add_char buffer c;
    +      lex_number buffer stream
    +
    +  (* Comment until end of line. *)
    +  | [< ' ('#'); stream >] ->
    +      lex_comment stream
    +
    +  (* Otherwise, just return the character as its ascii value. *)
    +  | [< 'c; stream >] ->
    +      [< 'Token.Kwd c; lex stream >]
    +
    +  (* end of stream. *)
    +  | [< >] -> [< >]
    +
    +and lex_number buffer = parser
    +  | [< ' ('0' .. '9' | '.' as c); stream >] ->
    +      Buffer.add_char buffer c;
    +      lex_number buffer stream
    +  | [< stream=lex >] ->
    +      [< 'Token.Number (float_of_string (Buffer.contents buffer)); stream >]
    +
    +and lex_ident buffer = parser
    +  | [< ' ('A' .. 'Z' | 'a' .. 'z' | '0' .. '9' as c); stream >] ->
    +      Buffer.add_char buffer c;
    +      lex_ident buffer stream
    +  | [< stream=lex >] ->
    +      match Buffer.contents buffer with
    +      | "def" -> [< 'Token.Def; stream >]
    +      | "extern" -> [< 'Token.Extern; stream >]
    +      | "if" -> [< 'Token.If; stream >]
    +      | "then" -> [< 'Token.Then; stream >]
    +      | "else" -> [< 'Token.Else; stream >]
    +      | "for" -> [< 'Token.For; stream >]
    +      | "in" -> [< 'Token.In; stream >]
    +      | "binary" -> [< 'Token.Binary; stream >]
    +      | "unary" -> [< 'Token.Unary; stream >]
    +      | "var" -> [< 'Token.Var; stream >]
    +      | id -> [< 'Token.Ident id; stream >]
    +
    +and lex_comment = parser
    +  | [< ' ('\n'); stream=lex >] -> stream
    +  | [< 'c; e=lex_comment >] -> e
    +  | [< >] -> [< >]
    +
    +
    + +
    ast.ml:
    +
    +
    +(*===----------------------------------------------------------------------===
    + * Abstract Syntax Tree (aka Parse Tree)
    + *===----------------------------------------------------------------------===*)
    +
    +(* expr - Base type for all expression nodes. *)
    +type expr =
    +  (* variant for numeric literals like "1.0". *)
    +  | Number of float
    +
    +  (* variant for referencing a variable, like "a". *)
    +  | Variable of string
    +
    +  (* variant for a unary operator. *)
    +  | Unary of char * expr
    +
    +  (* variant for a binary operator. *)
    +  | Binary of char * expr * expr
    +
    +  (* variant for function calls. *)
    +  | Call of string * expr array
    +
    +  (* variant for if/then/else. *)
    +  | If of expr * expr * expr
    +
    +  (* variant for for/in. *)
    +  | For of string * expr * expr * expr option * expr
    +
    +  (* variant for var/in. *)
    +  | Var of (string * expr option) array * expr
    +
    +(* proto - This type represents the "prototype" for a function, which captures
    + * its name, and its argument names (thus implicitly the number of arguments the
    + * function takes). *)
    +type proto =
    +  | Prototype of string * string array
    +  | BinOpPrototype of string * string array * int
    +
    +(* func - This type represents a function definition itself. *)
    +type func = Function of proto * expr
    +
    +
    + +
    parser.ml:
    +
    +
    +(*===---------------------------------------------------------------------===
    + * Parser
    + *===---------------------------------------------------------------------===*)
    +
    +(* binop_precedence - This holds the precedence for each binary operator that is
    + * defined *)
    +let binop_precedence:(char, int) Hashtbl.t = Hashtbl.create 10
    +
    +(* precedence - Get the precedence of the pending binary operator token. *)
    +let precedence c = try Hashtbl.find binop_precedence c with Not_found -> -1
    +
    +(* primary
    + *   ::= identifier
    + *   ::= numberexpr
    + *   ::= parenexpr
    + *   ::= ifexpr
    + *   ::= forexpr
    + *   ::= varexpr *)
    +let rec parse_primary = parser
    +  (* numberexpr ::= number *)
    +  | [< 'Token.Number n >] -> Ast.Number n
    +
    +  (* parenexpr ::= '(' expression ')' *)
    +  | [< 'Token.Kwd '('; e=parse_expr; 'Token.Kwd ')' ?? "expected ')'" >] -> e
    +
    +  (* identifierexpr
    +   *   ::= identifier
    +   *   ::= identifier '(' argumentexpr ')' *)
    +  | [< 'Token.Ident id; stream >] ->
    +      let rec parse_args accumulator = parser
    +        | [< e=parse_expr; stream >] ->
    +            begin parser
    +              | [< 'Token.Kwd ','; e=parse_args (e :: accumulator) >] -> e
    +              | [< >] -> e :: accumulator
    +            end stream
    +        | [< >] -> accumulator
    +      in
    +      let rec parse_ident id = parser
    +        (* Call. *)
    +        | [< 'Token.Kwd '(';
    +             args=parse_args [];
    +             'Token.Kwd ')' ?? "expected ')'">] ->
    +            Ast.Call (id, Array.of_list (List.rev args))
    +
    +        (* Simple variable ref. *)
    +        | [< >] -> Ast.Variable id
    +      in
    +      parse_ident id stream
    +
    +  (* ifexpr ::= 'if' expr 'then' expr 'else' expr *)
    +  | [< 'Token.If; c=parse_expr;
    +       'Token.Then ?? "expected 'then'"; t=parse_expr;
    +       'Token.Else ?? "expected 'else'"; e=parse_expr >] ->
    +      Ast.If (c, t, e)
    +
    +  (* forexpr
    +        ::= 'for' identifier '=' expr ',' expr (',' expr)? 'in' expression *)
    +  | [< 'Token.For;
    +       'Token.Ident id ?? "expected identifier after for";
    +       'Token.Kwd '=' ?? "expected '=' after for";
    +       stream >] ->
    +      begin parser
    +        | [<
    +             start=parse_expr;
    +             'Token.Kwd ',' ?? "expected ',' after for";
    +             end_=parse_expr;
    +             stream >] ->
    +            let step =
    +              begin parser
    +              | [< 'Token.Kwd ','; step=parse_expr >] -> Some step
    +              | [< >] -> None
    +              end stream
    +            in
    +            begin parser
    +            | [< 'Token.In; body=parse_expr >] ->
    +                Ast.For (id, start, end_, step, body)
    +            | [< >] ->
    +                raise (Stream.Error "expected 'in' after for")
    +            end stream
    +        | [< >] ->
    +            raise (Stream.Error "expected '=' after for")
    +      end stream
    +
    +  (* varexpr
    +   *   ::= 'var' identifier ('=' expression?
    +   *             (',' identifier ('=' expression)?)* 'in' expression *)
    +  | [< 'Token.Var;
    +       (* At least one variable name is required. *)
    +       'Token.Ident id ?? "expected identifier after var";
    +       init=parse_var_init;
    +       var_names=parse_var_names [(id, init)];
    +       (* At this point, we have to have 'in'. *)
    +       'Token.In ?? "expected 'in' keyword after 'var'";
    +       body=parse_expr >] ->
    +      Ast.Var (Array.of_list (List.rev var_names), body)
    +
    +  | [< >] -> raise (Stream.Error "unknown token when expecting an expression.")
    +
    +(* unary
    + *   ::= primary
    + *   ::= '!' unary *)
    +and parse_unary = parser
    +  (* If this is a unary operator, read it. *)
    +  | [< 'Token.Kwd op when op != '(' && op != ')'; operand=parse_expr >] ->
    +      Ast.Unary (op, operand)
    +
    +  (* If the current token is not an operator, it must be a primary expr. *)
    +  | [< stream >] -> parse_primary stream
    +
    +(* binoprhs
    + *   ::= ('+' primary)* *)
    +and parse_bin_rhs expr_prec lhs stream =
    +  match Stream.peek stream with
    +  (* If this is a binop, find its precedence. *)
    +  | Some (Token.Kwd c) when Hashtbl.mem binop_precedence c ->
    +      let token_prec = precedence c in
    +
    +      (* If this is a binop that binds at least as tightly as the current binop,
    +       * consume it, otherwise we are done. *)
    +      if token_prec < expr_prec then lhs else begin
    +        (* Eat the binop. *)
    +        Stream.junk stream;
    +
    +        (* Parse the primary expression after the binary operator. *)
    +        let rhs = parse_unary stream in
    +
    +        (* Okay, we know this is a binop. *)
    +        let rhs =
    +          match Stream.peek stream with
    +          | Some (Token.Kwd c2) ->
    +              (* If BinOp binds less tightly with rhs than the operator after
    +               * rhs, let the pending operator take rhs as its lhs. *)
    +              let next_prec = precedence c2 in
    +              if token_prec < next_prec
    +              then parse_bin_rhs (token_prec + 1) rhs stream
    +              else rhs
    +          | _ -> rhs
    +        in
    +
    +        (* Merge lhs/rhs. *)
    +        let lhs = Ast.Binary (c, lhs, rhs) in
    +        parse_bin_rhs expr_prec lhs stream
    +      end
    +  | _ -> lhs
    +
    +and parse_var_init = parser
    +  (* read in the optional initializer. *)
    +  | [< 'Token.Kwd '='; e=parse_expr >] -> Some e
    +  | [< >] -> None
    +
    +and parse_var_names accumulator = parser
    +  | [< 'Token.Kwd ',';
    +       'Token.Ident id ?? "expected identifier list after var";
    +       init=parse_var_init;
    +       e=parse_var_names ((id, init) :: accumulator) >] -> e
    +  | [< >] -> accumulator
    +
    +(* expression
    + *   ::= primary binoprhs *)
    +and parse_expr = parser
    +  | [< lhs=parse_unary; stream >] -> parse_bin_rhs 0 lhs stream
    +
    +(* prototype
    + *   ::= id '(' id* ')'
    + *   ::= binary LETTER number? (id, id)
    + *   ::= unary LETTER number? (id) *)
    +let parse_prototype =
    +  let rec parse_args accumulator = parser
    +    | [< 'Token.Ident id; e=parse_args (id::accumulator) >] -> e
    +    | [< >] -> accumulator
    +  in
    +  let parse_operator = parser
    +    | [< 'Token.Unary >] -> "unary", 1
    +    | [< 'Token.Binary >] -> "binary", 2
    +  in
    +  let parse_binary_precedence = parser
    +    | [< 'Token.Number n >] -> int_of_float n
    +    | [< >] -> 30
    +  in
    +  parser
    +  | [< 'Token.Ident id;
    +       'Token.Kwd '(' ?? "expected '(' in prototype";
    +       args=parse_args [];
    +       'Token.Kwd ')' ?? "expected ')' in prototype" >] ->
    +      (* success. *)
    +      Ast.Prototype (id, Array.of_list (List.rev args))
    +  | [< (prefix, kind)=parse_operator;
    +       'Token.Kwd op ?? "expected an operator";
    +       (* Read the precedence if present. *)
    +       binary_precedence=parse_binary_precedence;
    +       'Token.Kwd '(' ?? "expected '(' in prototype";
    +        args=parse_args [];
    +       'Token.Kwd ')' ?? "expected ')' in prototype" >] ->
    +      let name = prefix ^ (String.make 1 op) in
    +      let args = Array.of_list (List.rev args) in
    +
    +      (* Verify right number of arguments for operator. *)
    +      if Array.length args != kind
    +      then raise (Stream.Error "invalid number of operands for operator")
    +      else
    +        if kind == 1 then
    +          Ast.Prototype (name, args)
    +        else
    +          Ast.BinOpPrototype (name, args, binary_precedence)
    +  | [< >] ->
    +      raise (Stream.Error "expected function name in prototype")
    +
    +(* definition ::= 'def' prototype expression *)
    +let parse_definition = parser
    +  | [< 'Token.Def; p=parse_prototype; e=parse_expr >] ->
    +      Ast.Function (p, e)
    +
    +(* toplevelexpr ::= expression *)
    +let parse_toplevel = parser
    +  | [< e=parse_expr >] ->
    +      (* Make an anonymous proto. *)
    +      Ast.Function (Ast.Prototype ("", [||]), e)
    +
    +(*  external ::= 'extern' prototype *)
    +let parse_extern = parser
    +  | [< 'Token.Extern; e=parse_prototype >] -> e
    +
    +
    + +
    codegen.ml:
    +
    +
    +(*===----------------------------------------------------------------------===
    + * Code Generation
    + *===----------------------------------------------------------------------===*)
    +
    +open Llvm
    +
    +exception Error of string
    +
    +let context = global_context ()
    +let the_module = create_module context "my cool jit"
    +let builder = builder context
    +let named_values:(string, llvalue) Hashtbl.t = Hashtbl.create 10
    +
    +(* Create an alloca instruction in the entry block of the function. This
    + * is used for mutable variables etc. *)
    +let create_entry_block_alloca the_function var_name =
    +  let builder = builder_at context (instr_begin (entry_block the_function)) in
    +  build_alloca double_type var_name builder
    +
    +let rec codegen_expr = function
    +  | Ast.Number n -> const_float double_type n
    +  | Ast.Variable name ->
    +      let v = try Hashtbl.find named_values name with
    +        | Not_found -> raise (Error "unknown variable name")
    +      in
    +      (* Load the value. *)
    +      build_load v name builder
    +  | Ast.Unary (op, operand) ->
    +      let operand = codegen_expr operand in
    +      let callee = "unary" ^ (String.make 1 op) in
    +      let callee =
    +        match lookup_function callee the_module with
    +        | Some callee -> callee
    +        | None -> raise (Error "unknown unary operator")
    +      in
    +      build_call callee [|operand|] "unop" builder
    +  | Ast.Binary (op, lhs, rhs) ->
    +      begin match op with
    +      | '=' ->
    +          (* Special case '=' because we don't want to emit the LHS as an
    +           * expression. *)
    +          let name =
    +            match lhs with
    +            | Ast.Variable name -> name
    +            | _ -> raise (Error "destination of '=' must be a variable")
    +          in
    +
    +          (* Codegen the rhs. *)
    +          let val_ = codegen_expr rhs in
    +
    +          (* Lookup the name. *)
    +          let variable = try Hashtbl.find named_values name with
    +          | Not_found -> raise (Error "unknown variable name")
    +          in
    +          ignore(build_store val_ variable builder);
    +          val_
    +      | _ ->
    +          let lhs_val = codegen_expr lhs in
    +          let rhs_val = codegen_expr rhs in
    +          begin
    +            match op with
    +            | '+' -> build_add lhs_val rhs_val "addtmp" builder
    +            | '-' -> build_sub lhs_val rhs_val "subtmp" builder
    +            | '*' -> build_mul lhs_val rhs_val "multmp" builder
    +            | '<' ->
    +                (* Convert bool 0/1 to double 0.0 or 1.0 *)
    +                let i = build_fcmp Fcmp.Ult lhs_val rhs_val "cmptmp" builder in
    +                build_uitofp i double_type "booltmp" builder
    +            | _ ->
    +                (* If it wasn't a builtin binary operator, it must be a user defined
    +                 * one. Emit a call to it. *)
    +                let callee = "binary" ^ (String.make 1 op) in
    +                let callee =
    +                  match lookup_function callee the_module with
    +                  | Some callee -> callee
    +                  | None -> raise (Error "binary operator not found!")
    +                in
    +                build_call callee [|lhs_val; rhs_val|] "binop" builder
    +          end
    +      end
    +  | Ast.Call (callee, args) ->
    +      (* Look up the name in the module table. *)
    +      let callee =
    +        match lookup_function callee the_module with
    +        | Some callee -> callee
    +        | None -> raise (Error "unknown function referenced")
    +      in
    +      let params = params callee in
    +
    +      (* If argument mismatch error. *)
    +      if Array.length params == Array.length args then () else
    +        raise (Error "incorrect # arguments passed");
    +      let args = Array.map codegen_expr args in
    +      build_call callee args "calltmp" builder
    +  | Ast.If (cond, then_, else_) ->
    +      let cond = codegen_expr cond in
    +
    +      (* Convert condition to a bool by comparing equal to 0.0 *)
    +      let zero = const_float double_type 0.0 in
    +      let cond_val = build_fcmp Fcmp.One cond zero "ifcond" builder in
    +
    +      (* Grab the first block so that we might later add the conditional branch
    +       * to it at the end of the function. *)
    +      let start_bb = insertion_block builder in
    +      let the_function = block_parent start_bb in
    +
    +      let then_bb = append_block "then" the_function in
    +
    +      (* Emit 'then' value. *)
    +      position_at_end then_bb builder;
    +      let then_val = codegen_expr then_ in
    +
    +      (* Codegen of 'then' can change the current block, update then_bb for the
    +       * phi. We create a new name because one is used for the phi node, and the
    +       * other is used for the conditional branch. *)
    +      let new_then_bb = insertion_block builder in
    +
    +      (* Emit 'else' value. *)
    +      let else_bb = append_block "else" the_function in
    +      position_at_end else_bb builder;
    +      let else_val = codegen_expr else_ in
    +
    +      (* Codegen of 'else' can change the current block, update else_bb for the
    +       * phi. *)
    +      let new_else_bb = insertion_block builder in
    +
    +      (* Emit merge block. *)
    +      let merge_bb = append_block "ifcont" the_function in
    +      position_at_end merge_bb builder;
    +      let incoming = [(then_val, new_then_bb); (else_val, new_else_bb)] in
    +      let phi = build_phi incoming "iftmp" builder in
    +
    +      (* Return to the start block to add the conditional branch. *)
    +      position_at_end start_bb builder;
    +      ignore (build_cond_br cond_val then_bb else_bb builder);
    +
    +      (* Set a unconditional branch at the end of the 'then' block and the
    +       * 'else' block to the 'merge' block. *)
    +      position_at_end new_then_bb builder; ignore (build_br merge_bb builder);
    +      position_at_end new_else_bb builder; ignore (build_br merge_bb builder);
    +
    +      (* Finally, set the builder to the end of the merge block. *)
    +      position_at_end merge_bb builder;
    +
    +      phi
    +  | Ast.For (var_name, start, end_, step, body) ->
    +      (* Output this as:
    +       *   var = alloca double
    +       *   ...
    +       *   start = startexpr
    +       *   store start -> var
    +       *   goto loop
    +       * loop:
    +       *   ...
    +       *   bodyexpr
    +       *   ...
    +       * loopend:
    +       *   step = stepexpr
    +       *   endcond = endexpr
    +       *
    +       *   curvar = load var
    +       *   nextvar = curvar + step
    +       *   store nextvar -> var
    +       *   br endcond, loop, endloop
    +       * outloop: *)
    +
    +      let the_function = block_parent (insertion_block builder) in
    +
    +      (* Create an alloca for the variable in the entry block. *)
    +      let alloca = create_entry_block_alloca the_function var_name in
    +
    +      (* Emit the start code first, without 'variable' in scope. *)
    +      let start_val = codegen_expr start in
    +
    +      (* Store the value into the alloca. *)
    +      ignore(build_store start_val alloca builder);
    +
    +      (* Make the new basic block for the loop header, inserting after current
    +       * block. *)
    +      let loop_bb = append_block "loop" the_function in
    +
    +      (* Insert an explicit fall through from the current block to the
    +       * loop_bb. *)
    +      ignore (build_br loop_bb builder);
    +
    +      (* Start insertion in loop_bb. *)
    +      position_at_end loop_bb builder;
    +
    +      (* Within the loop, the variable is defined equal to the PHI node. If it
    +       * shadows an existing variable, we have to restore it, so save it
    +       * now. *)
    +      let old_val =
    +        try Some (Hashtbl.find named_values var_name) with Not_found -> None
    +      in
    +      Hashtbl.add named_values var_name alloca;
    +
    +      (* Emit the body of the loop.  This, like any other expr, can change the
    +       * current BB.  Note that we ignore the value computed by the body, but
    +       * don't allow an error *)
    +      ignore (codegen_expr body);
    +
    +      (* Emit the step value. *)
    +      let step_val =
    +        match step with
    +        | Some step -> codegen_expr step
    +        (* If not specified, use 1.0. *)
    +        | None -> const_float double_type 1.0
    +      in
    +
    +      (* Compute the end condition. *)
    +      let end_cond = codegen_expr end_ in
    +
    +      (* Reload, increment, and restore the alloca. This handles the case where
    +       * the body of the loop mutates the variable. *)
    +      let cur_var = build_load alloca var_name builder in
    +      let next_var = build_add cur_var step_val "nextvar" builder in
    +      ignore(build_store next_var alloca builder);
    +
    +      (* Convert condition to a bool by comparing equal to 0.0. *)
    +      let zero = const_float double_type 0.0 in
    +      let end_cond = build_fcmp Fcmp.One end_cond zero "loopcond" builder in
    +
    +      (* Create the "after loop" block and insert it. *)
    +      let after_bb = append_block "afterloop" the_function in
    +
    +      (* Insert the conditional branch into the end of loop_end_bb. *)
    +      ignore (build_cond_br end_cond loop_bb after_bb builder);
    +
    +      (* Any new code will be inserted in after_bb. *)
    +      position_at_end after_bb builder;
    +
    +      (* Restore the unshadowed variable. *)
    +      begin match old_val with
    +      | Some old_val -> Hashtbl.add named_values var_name old_val
    +      | None -> ()
    +      end;
    +
    +      (* for expr always returns 0.0. *)
    +      const_null double_type
    +  | Ast.Var (var_names, body) ->
    +      let old_bindings = ref [] in
    +
    +      let the_function = block_parent (insertion_block builder) in
    +
    +      (* Register all variables and emit their initializer. *)
    +      Array.iter (fun (var_name, init) ->
    +        (* Emit the initializer before adding the variable to scope, this
    +         * prevents the initializer from referencing the variable itself, and
    +         * permits stuff like this:
    +         *   var a = 1 in
    +         *     var a = a in ...   # refers to outer 'a'. *)
    +        let init_val =
    +          match init with
    +          | Some init -> codegen_expr init
    +          (* If not specified, use 0.0. *)
    +          | None -> const_float double_type 0.0
    +        in
    +
    +        let alloca = create_entry_block_alloca the_function var_name in
    +        ignore(build_store init_val alloca builder);
    +
    +        (* Remember the old variable binding so that we can restore the binding
    +         * when we unrecurse. *)
    +        begin
    +          try
    +            let old_value = Hashtbl.find named_values var_name in
    +            old_bindings := (var_name, old_value) :: !old_bindings;
    +          with Not_found -> ()
    +        end;
    +
    +        (* Remember this binding. *)
    +        Hashtbl.add named_values var_name alloca;
    +      ) var_names;
    +
    +      (* Codegen the body, now that all vars are in scope. *)
    +      let body_val = codegen_expr body in
    +
    +      (* Pop all our variables from scope. *)
    +      List.iter (fun (var_name, old_value) ->
    +        Hashtbl.add named_values var_name old_value
    +      ) !old_bindings;
    +
    +      (* Return the body computation. *)
    +      body_val
    +
    +let codegen_proto = function
    +  | Ast.Prototype (name, args) | Ast.BinOpPrototype (name, args, _) ->
    +      (* Make the function type: double(double,double) etc. *)
    +      let doubles = Array.make (Array.length args) double_type in
    +      let ft = function_type double_type doubles in
    +      let f =
    +        match lookup_function name the_module with
    +        | None -> declare_function name ft the_module
    +
    +        (* If 'f' conflicted, there was already something named 'name'. If it
    +         * has a body, don't allow redefinition or reextern. *)
    +        | Some f ->
    +            (* If 'f' already has a body, reject this. *)
    +            if block_begin f <> At_end f then
    +              raise (Error "redefinition of function");
    +
    +            (* If 'f' took a different number of arguments, reject. *)
    +            if element_type (type_of f) <> ft then
    +              raise (Error "redefinition of function with different # args");
    +            f
    +      in
    +
    +      (* Set names for all arguments. *)
    +      Array.iteri (fun i a ->
    +        let n = args.(i) in
    +        set_value_name n a;
    +        Hashtbl.add named_values n a;
    +      ) (params f);
    +      f
    +
    +(* Create an alloca for each argument and register the argument in the symbol
    + * table so that references to it will succeed. *)
    +let create_argument_allocas the_function proto =
    +  let args = match proto with
    +    | Ast.Prototype (_, args) | Ast.BinOpPrototype (_, args, _) -> args
    +  in
    +  Array.iteri (fun i ai ->
    +    let var_name = args.(i) in
    +    (* Create an alloca for this variable. *)
    +    let alloca = create_entry_block_alloca the_function var_name in
    +
    +    (* Store the initial value into the alloca. *)
    +    ignore(build_store ai alloca builder);
    +
    +    (* Add arguments to variable symbol table. *)
    +    Hashtbl.add named_values var_name alloca;
    +  ) (params the_function)
    +
    +let codegen_func the_fpm = function
    +  | Ast.Function (proto, body) ->
    +      Hashtbl.clear named_values;
    +      let the_function = codegen_proto proto in
    +
    +      (* If this is an operator, install it. *)
    +      begin match proto with
    +      | Ast.BinOpPrototype (name, args, prec) ->
    +          let op = name.[String.length name - 1] in
    +          Hashtbl.add Parser.binop_precedence op prec;
    +      | _ -> ()
    +      end;
    +
    +      (* Create a new basic block to start insertion into. *)
    +      let bb = append_block "entry" the_function in
    +      position_at_end bb builder;
    +
    +      try
    +        (* Add all arguments to the symbol table and create their allocas. *)
    +        create_argument_allocas the_function proto;
    +
    +        let ret_val = codegen_expr body in
    +
    +        (* Finish off the function. *)
    +        let _ = build_ret ret_val builder in
    +
    +        (* Validate the generated code, checking for consistency. *)
    +        Llvm_analysis.assert_valid_function the_function;
    +
    +        (* Optimize the function. *)
    +        let _ = PassManager.run_function the_function the_fpm in
    +
    +        the_function
    +      with e ->
    +        delete_function the_function;
    +        raise e
    +
    +
    + +
    toplevel.ml:
    +
    +
    +(*===----------------------------------------------------------------------===
    + * Top-Level parsing and JIT Driver
    + *===----------------------------------------------------------------------===*)
    +
    +open Llvm
    +open Llvm_executionengine
    +
    +(* top ::= definition | external | expression | ';' *)
    +let rec main_loop the_fpm the_execution_engine stream =
    +  match Stream.peek stream with
    +  | None -> ()
    +
    +  (* ignore top-level semicolons. *)
    +  | Some (Token.Kwd ';') ->
    +      Stream.junk stream;
    +      main_loop the_fpm the_execution_engine stream
    +
    +  | Some token ->
    +      begin
    +        try match token with
    +        | Token.Def ->
    +            let e = Parser.parse_definition stream in
    +            print_endline "parsed a function definition.";
    +            dump_value (Codegen.codegen_func the_fpm e);
    +        | Token.Extern ->
    +            let e = Parser.parse_extern stream in
    +            print_endline "parsed an extern.";
    +            dump_value (Codegen.codegen_proto e);
    +        | _ ->
    +            (* Evaluate a top-level expression into an anonymous function. *)
    +            let e = Parser.parse_toplevel stream in
    +            print_endline "parsed a top-level expr";
    +            let the_function = Codegen.codegen_func the_fpm e in
    +            dump_value the_function;
    +
    +            (* JIT the function, returning a function pointer. *)
    +            let result = ExecutionEngine.run_function the_function [||]
    +              the_execution_engine in
    +
    +            print_string "Evaluated to ";
    +            print_float (GenericValue.as_float double_type result);
    +            print_newline ();
    +        with Stream.Error s | Codegen.Error s ->
    +          (* Skip token for error recovery. *)
    +          Stream.junk stream;
    +          print_endline s;
    +      end;
    +      print_string "ready> "; flush stdout;
    +      main_loop the_fpm the_execution_engine stream
    +
    +
    + +
    toy.ml:
    +
    +
    +(*===----------------------------------------------------------------------===
    + * Main driver code.
    + *===----------------------------------------------------------------------===*)
    +
    +open Llvm
    +open Llvm_executionengine
    +open Llvm_target
    +open Llvm_scalar_opts
    +
    +let main () =
    +  ignore (initialize_native_target ());
    +
    +  (* Install standard binary operators.
    +   * 1 is the lowest precedence. *)
    +  Hashtbl.add Parser.binop_precedence '=' 2;
    +  Hashtbl.add Parser.binop_precedence '<' 10;
    +  Hashtbl.add Parser.binop_precedence '+' 20;
    +  Hashtbl.add Parser.binop_precedence '-' 20;
    +  Hashtbl.add Parser.binop_precedence '*' 40;    (* highest. *)
    +
    +  (* Prime the first token. *)
    +  print_string "ready> "; flush stdout;
    +  let stream = Lexer.lex (Stream.of_channel stdin) in
    +
    +  (* Create the JIT. *)
    +  let the_module_provider = ModuleProvider.create Codegen.the_module in
    +  let the_execution_engine = ExecutionEngine.create the_module_provider in
    +  let the_fpm = PassManager.create_function the_module_provider in
    +
    +  (* Set up the optimizer pipeline.  Start with registering info about how the
    +   * target lays out data structures. *)
    +  TargetData.add (ExecutionEngine.target_data the_execution_engine) the_fpm;
    +
    +  (* Promote allocas to registers. *)
    +  add_memory_to_register_promotion the_fpm;
    +
    +  (* Do simple "peephole" optimizations and bit-twiddling optzn. *)
    +  add_instruction_combining the_fpm;
    +
    +  (* reassociate expressions. *)
    +  add_reassociation the_fpm;
    +
    +  (* Eliminate Common SubExpressions. *)
    +  add_gvn the_fpm;
    +
    +  (* Simplify the control flow graph (deleting unreachable blocks, etc). *)
    +  add_cfg_simplification the_fpm;
    +
    +  ignore (PassManager.initialize the_fpm);
    +
    +  (* Run the main "interpreter loop" now. *)
    +  Toplevel.main_loop the_fpm the_execution_engine stream;
    +
    +  (* Print out all the generated code. *)
    +  dump_module Codegen.the_module
    +;;
    +
    +main ()
    +
    +
    + +
    bindings.c
    +
    +
    +#include <stdio.h>
    +
    +/* putchard - putchar that takes a double and returns 0. */
    +extern double putchard(double X) {
    +  putchar((char)X);
    +  return 0;
    +}
    +
    +/* printd - printf that takes a double prints it as "%f\n", returning 0. */
    +extern double printd(double X) {
    +  printf("%f\n", X);
    +  return 0;
    +}
    +
    +
    +
    + +Next: Conclusion and other useful LLVM tidbits +
    + + +
    +
    + Valid CSS! + Valid HTML 4.01! + + Chris Lattner
    + The LLVM Compiler Infrastructure
    + Erick Tryzelaar
    + Last modified: $Date: 2007-10-17 11:05:13 -0700 (Wed, 17 Oct 2007) $ +
    + + diff --git a/libclamav/c++/llvm/docs/tutorial/index.html b/libclamav/c++/llvm/docs/tutorial/index.html new file mode 100644 index 000000000..bfaafe726 --- /dev/null +++ b/libclamav/c++/llvm/docs/tutorial/index.html @@ -0,0 +1,58 @@ + + + + LLVM Tutorial: Table of Contents + + + + + + + + +
    LLVM Tutorial: Table of Contents
    + +
      +
    1. An Introduction to LLVM: Basic Concepts and Design
    2. +
    3. Simple JIT Tutorials +
        +
      1. A First Function
      2. +
      3. A More Complicated Function
      4. +
      5. Running Optimizations
      6. +
      7. Reading and Writing Bitcode
      8. +
      9. Invoking the JIT
      10. +
      +
    4. +
    5. Kaleidoscope: Implementing a Language with LLVM +
        +
      1. Tutorial Introduction and the Lexer
      2. +
      3. Implementing a Parser and AST
      4. +
      5. Implementing Code Generation to LLVM IR
      6. +
      7. Adding JIT and Optimizer Support
      8. +
      9. Extending the language: control flow
      10. +
      11. Extending the language: user-defined operators
      12. +
      13. Extending the language: mutable variables / SSA construction
      14. +
      15. Conclusion and other useful LLVM tidbits
      16. +
    6. +
    7. Kaleidoscope: Implementing a Language with LLVM in Objective Caml +
        +
      1. Tutorial Introduction and the Lexer
      2. +
      3. Implementing a Parser and AST
      4. +
      5. Implementing Code Generation to LLVM IR
      6. +
      7. Adding JIT and Optimizer Support
      8. +
      9. Extending the language: control flow
      10. +
      11. Extending the language: user-defined operators
      12. +
      13. Extending the language: mutable variables / SSA construction
      14. +
      15. Conclusion and other useful LLVM tidbits
      16. +
    8. +
    9. Advanced Topics +
        +
      1. Writing + an Optimization for LLVM
      2. +
    10. +
    + + + diff --git a/libclamav/c++/llvm/include/llvm-c/Analysis.h b/libclamav/c++/llvm/include/llvm-c/Analysis.h new file mode 100644 index 000000000..68d8e65db --- /dev/null +++ b/libclamav/c++/llvm/include/llvm-c/Analysis.h @@ -0,0 +1,55 @@ +/*===-- llvm-c/Analysis.h - Analysis Library 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 libLLVMAnalysis.a, which *| +|* implements various analyses of the LLVM IR. *| +|* *| +|* Many exotic languages can interoperate with C code but have a harder time *| +|* with C++ due to name mangling. So in addition to C, this interface enables *| +|* tools written in such languages. *| +|* *| +\*===----------------------------------------------------------------------===*/ + +#ifndef LLVM_C_ANALYSIS_H +#define LLVM_C_ANALYSIS_H + +#include "llvm-c/Core.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +typedef enum { + LLVMAbortProcessAction, /* verifier will print to stderr and abort() */ + LLVMPrintMessageAction, /* verifier will print to stderr and return 1 */ + LLVMReturnStatusAction /* verifier will just return 1 */ +} LLVMVerifierFailureAction; + + +/* Verifies that a module is valid, taking the specified action if not. + Optionally returns a human-readable description of any invalid constructs. + OutMessage must be disposed with LLVMDisposeMessage. */ +int LLVMVerifyModule(LLVMModuleRef M, LLVMVerifierFailureAction Action, + char **OutMessage); + +/* Verifies that a single function is valid, taking the specified action. Useful + for debugging. */ +int LLVMVerifyFunction(LLVMValueRef Fn, LLVMVerifierFailureAction Action); + +/* Open up a ghostview window that displays the CFG of the current function. + Useful for debugging. */ +void LLVMViewFunctionCFG(LLVMValueRef Fn); +void LLVMViewFunctionCFGOnly(LLVMValueRef Fn); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libclamav/c++/llvm/include/llvm-c/BitReader.h b/libclamav/c++/llvm/include/llvm-c/BitReader.h new file mode 100644 index 000000000..a184f609d --- /dev/null +++ b/libclamav/c++/llvm/include/llvm-c/BitReader.h @@ -0,0 +1,56 @@ +/*===-- llvm-c/BitReader.h - BitReader Library 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 libLLVMBitReader.a, which *| +|* implements input of the LLVM bitcode format. *| +|* *| +|* Many exotic languages can interoperate with C code but have a harder time *| +|* with C++ due to name mangling. So in addition to C, this interface enables *| +|* tools written in such languages. *| +|* *| +\*===----------------------------------------------------------------------===*/ + +#ifndef LLVM_C_BITCODEREADER_H +#define LLVM_C_BITCODEREADER_H + +#include "llvm-c/Core.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/* Builds a module from the bitcode in the specified memory buffer, returning a + reference to the module via the OutModule parameter. Returns 0 on success. + Optionally returns a human-readable error message via OutMessage. */ +int LLVMParseBitcode(LLVMMemoryBufferRef MemBuf, + LLVMModuleRef *OutModule, char **OutMessage); + +int LLVMParseBitcodeInContext(LLVMContextRef ContextRef, + LLVMMemoryBufferRef MemBuf, + LLVMModuleRef *OutModule, char **OutMessage); + +/* Reads a module from the specified path, returning via the OutMP parameter + a module provider which performs lazy deserialization. Returns 0 on success. + Optionally returns a human-readable error message via OutMessage. */ +int LLVMGetBitcodeModuleProvider(LLVMMemoryBufferRef MemBuf, + LLVMModuleProviderRef *OutMP, + char **OutMessage); + +int LLVMGetBitcodeModuleProviderInContext(LLVMContextRef ContextRef, + LLVMMemoryBufferRef MemBuf, + LLVMModuleProviderRef *OutMP, + char **OutMessage); + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libclamav/c++/llvm/include/llvm-c/BitWriter.h b/libclamav/c++/llvm/include/llvm-c/BitWriter.h new file mode 100644 index 000000000..008ff9f2c --- /dev/null +++ b/libclamav/c++/llvm/include/llvm-c/BitWriter.h @@ -0,0 +1,43 @@ +/*===-- llvm-c/BitWriter.h - BitWriter Library 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 libLLVMBitWriter.a, which *| +|* implements output of the LLVM bitcode format. *| +|* *| +|* Many exotic languages can interoperate with C code but have a harder time *| +|* with C++ due to name mangling. So in addition to C, this interface enables *| +|* tools written in such languages. *| +|* *| +\*===----------------------------------------------------------------------===*/ + +#ifndef LLVM_C_BITCODEWRITER_H +#define LLVM_C_BITCODEWRITER_H + +#include "llvm-c/Core.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/*===-- Operations on modules ---------------------------------------------===*/ + +/* Writes a module to an open file descriptor. Returns 0 on success. + Closes the Handle. Use dup first if this is not what you want. */ +int LLVMWriteBitcodeToFileHandle(LLVMModuleRef M, int Handle); + +/* Writes a module to the specified path. Returns 0 on success. */ +int LLVMWriteBitcodeToFile(LLVMModuleRef M, const char *Path); + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libclamav/c++/llvm/include/llvm-c/Core.h b/libclamav/c++/llvm/include/llvm-c/Core.h new file mode 100644 index 000000000..c741d1c19 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm-c/Core.h @@ -0,0 +1,1076 @@ +/*===-- llvm-c/Core.h - Core Library 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 libLLVMCore.a, which implements *| +|* the LLVM intermediate representation. *| +|* *| +|* LLVM uses a polymorphic type hierarchy which C cannot represent, therefore *| +|* parameters must be passed as base types. Despite the declared types, most *| +|* of the functions provided operate only on branches of the type hierarchy. *| +|* The declared parameter names are descriptive and specify which type is *| +|* required. Additionally, each type hierarchy is documented along with the *| +|* functions that operate upon it. For more detail, refer to LLVM's C++ code. *| +|* If in doubt, refer to Core.cpp, which performs paramter downcasts in the *| +|* form unwrap(Param). *| +|* *| +|* Many exotic languages can interoperate with C code but have a harder time *| +|* with C++ due to name mangling. So in addition to C, this interface enables *| +|* tools written in such languages. *| +|* *| +|* When included into a C++ source file, also declares 'wrap' and 'unwrap' *| +|* helpers to perform opaque reference<-->pointer conversions. These helpers *| +|* are shorter and more tightly typed than writing the casts by hand when *| +|* authoring bindings. In assert builds, they will do runtime type checking. *| +|* *| +\*===----------------------------------------------------------------------===*/ + +#ifndef LLVM_C_CORE_H +#define LLVM_C_CORE_H + +#include "llvm/System/DataTypes.h" + +#ifdef __cplusplus + +/* Need these includes to support the LLVM 'cast' template for the C++ 'wrap' + and 'unwrap' conversion functions. */ +#include "llvm/Module.h" +#include "llvm/Support/IRBuilder.h" + +extern "C" { +#endif + + +/* Opaque types. */ + +/** + * The top-level container for all LLVM global data. See the LLVMContext class. + */ +typedef struct LLVMOpaqueContext *LLVMContextRef; + +/** + * The top-level container for all other LLVM Intermediate Representation (IR) + * objects. See the llvm::Module class. + */ +typedef struct LLVMOpaqueModule *LLVMModuleRef; + +/** + * Each value in the LLVM IR has a type, an LLVMTypeRef. See the llvm::Type + * class. + */ +typedef struct LLVMOpaqueType *LLVMTypeRef; + +/** + * When building recursive types using LLVMRefineType, LLVMTypeRef values may + * become invalid; use LLVMTypeHandleRef to resolve this problem. See the + * llvm::AbstractTypeHolder class. + */ +typedef struct LLVMOpaqueTypeHandle *LLVMTypeHandleRef; + +typedef struct LLVMOpaqueValue *LLVMValueRef; +typedef struct LLVMOpaqueBasicBlock *LLVMBasicBlockRef; +typedef struct LLVMOpaqueBuilder *LLVMBuilderRef; + +/* Used to provide a module to JIT or interpreter. + * See the llvm::ModuleProvider class. + */ +typedef struct LLVMOpaqueModuleProvider *LLVMModuleProviderRef; + +/* Used to provide a module to JIT or interpreter. + * See the llvm::MemoryBuffer class. + */ +typedef struct LLVMOpaqueMemoryBuffer *LLVMMemoryBufferRef; + +/** See the llvm::PassManagerBase class. */ +typedef struct LLVMOpaquePassManager *LLVMPassManagerRef; + +/** + * Used to iterate through the uses of a Value, allowing access to all Values + * that use this Value. See the llvm::Use and llvm::value_use_iterator classes. + */ +typedef struct LLVMOpaqueUseIterator *LLVMUseIteratorRef; + +typedef enum { + LLVMZExtAttribute = 1<<0, + LLVMSExtAttribute = 1<<1, + LLVMNoReturnAttribute = 1<<2, + LLVMInRegAttribute = 1<<3, + LLVMStructRetAttribute = 1<<4, + LLVMNoUnwindAttribute = 1<<5, + LLVMNoAliasAttribute = 1<<6, + LLVMByValAttribute = 1<<7, + LLVMNestAttribute = 1<<8, + LLVMReadNoneAttribute = 1<<9, + LLVMReadOnlyAttribute = 1<<10, + LLVMNoInlineAttribute = 1<<11, + LLVMAlwaysInlineAttribute = 1<<12, + LLVMOptimizeForSizeAttribute = 1<<13, + LLVMStackProtectAttribute = 1<<14, + LLVMStackProtectReqAttribute = 1<<15, + LLVMNoCaptureAttribute = 1<<21, + LLVMNoRedZoneAttribute = 1<<22, + LLVMNoImplicitFloatAttribute = 1<<23, + LLVMNakedAttribute = 1<<24, + LLVMInlineHintAttribute = 1<<25 +} LLVMAttribute; + +typedef enum { + LLVMRet = 1, + LLVMBr = 2, + LLVMSwitch = 3, + LLVMInvoke = 4, + LLVMUnwind = 5, + LLVMUnreachable = 6, + LLVMAdd = 7, + LLVMFAdd = 8, + LLVMSub = 9, + LLVMFSub = 10, + LLVMMul = 11, + LLVMFMul = 12, + LLVMUDiv = 13, + LLVMSDiv = 14, + LLVMFDiv = 15, + LLVMURem = 16, + LLVMSRem = 17, + LLVMFRem = 18, + LLVMShl = 19, + LLVMLShr = 20, + LLVMAShr = 21, + LLVMAnd = 22, + LLVMOr = 23, + LLVMXor = 24, + LLVMMalloc = 25, + LLVMFree = 26, + LLVMAlloca = 27, + LLVMLoad = 28, + LLVMStore = 29, + LLVMGetElementPtr = 30, + LLVMTrunk = 31, + LLVMZExt = 32, + LLVMSExt = 33, + LLVMFPToUI = 34, + LLVMFPToSI = 35, + LLVMUIToFP = 36, + LLVMSIToFP = 37, + LLVMFPTrunc = 38, + LLVMFPExt = 39, + LLVMPtrToInt = 40, + LLVMIntToPtr = 41, + LLVMBitCast = 42, + LLVMICmp = 43, + LLVMFCmp = 44, + LLVMPHI = 45, + LLVMCall = 46, + LLVMSelect = 47, + LLVMVAArg = 50, + LLVMExtractElement = 51, + LLVMInsertElement = 52, + LLVMShuffleVector = 53, + LLVMExtractValue = 54, + LLVMInsertValue = 55 +} LLVMOpcode; + +typedef enum { + LLVMVoidTypeKind, /**< type with no size */ + LLVMFloatTypeKind, /**< 32 bit floating point type */ + LLVMDoubleTypeKind, /**< 64 bit floating point type */ + LLVMX86_FP80TypeKind, /**< 80 bit floating point type (X87) */ + LLVMFP128TypeKind, /**< 128 bit floating point type (112-bit mantissa)*/ + LLVMPPC_FP128TypeKind, /**< 128 bit floating point type (two 64-bits) */ + LLVMLabelTypeKind, /**< Labels */ + LLVMIntegerTypeKind, /**< Arbitrary bit width integers */ + LLVMFunctionTypeKind, /**< Functions */ + LLVMStructTypeKind, /**< Structures */ + LLVMArrayTypeKind, /**< Arrays */ + LLVMPointerTypeKind, /**< Pointers */ + LLVMOpaqueTypeKind, /**< Opaque: type with unknown structure */ + LLVMVectorTypeKind, /**< SIMD 'packed' format, or other vector type */ + LLVMMetadataTypeKind /**< Metadata */ +} LLVMTypeKind; + +typedef enum { + LLVMExternalLinkage, /**< Externally visible function */ + LLVMAvailableExternallyLinkage, + LLVMLinkOnceAnyLinkage, /**< Keep one copy of function when linking (inline)*/ + LLVMLinkOnceODRLinkage, /**< Same, but only replaced by something + equivalent. */ + LLVMWeakAnyLinkage, /**< Keep one copy of function when linking (weak) */ + LLVMWeakODRLinkage, /**< Same, but only replaced by something + equivalent. */ + LLVMAppendingLinkage, /**< Special purpose, only applies to global arrays */ + LLVMInternalLinkage, /**< Rename collisions when linking (static + functions) */ + LLVMPrivateLinkage, /**< Like Internal, but omit from symbol table */ + LLVMDLLImportLinkage, /**< Function to be imported from DLL */ + LLVMDLLExportLinkage, /**< Function to be accessible from DLL */ + LLVMExternalWeakLinkage,/**< ExternalWeak linkage description */ + LLVMGhostLinkage, /**< Stand-in functions for streaming fns from + bitcode */ + LLVMCommonLinkage, /**< Tentative definitions */ + LLVMLinkerPrivateLinkage /**< Like Private, but linker removes. */ +} LLVMLinkage; + +typedef enum { + LLVMDefaultVisibility, /**< The GV is visible */ + LLVMHiddenVisibility, /**< The GV is hidden */ + LLVMProtectedVisibility /**< The GV is protected */ +} LLVMVisibility; + +typedef enum { + LLVMCCallConv = 0, + LLVMFastCallConv = 8, + LLVMColdCallConv = 9, + LLVMX86StdcallCallConv = 64, + LLVMX86FastcallCallConv = 65 +} LLVMCallConv; + +typedef enum { + LLVMIntEQ = 32, /**< equal */ + LLVMIntNE, /**< not equal */ + LLVMIntUGT, /**< unsigned greater than */ + LLVMIntUGE, /**< unsigned greater or equal */ + LLVMIntULT, /**< unsigned less than */ + LLVMIntULE, /**< unsigned less or equal */ + LLVMIntSGT, /**< signed greater than */ + LLVMIntSGE, /**< signed greater or equal */ + LLVMIntSLT, /**< signed less than */ + LLVMIntSLE /**< signed less or equal */ +} LLVMIntPredicate; + +typedef enum { + LLVMRealPredicateFalse, /**< Always false (always folded) */ + LLVMRealOEQ, /**< True if ordered and equal */ + LLVMRealOGT, /**< True if ordered and greater than */ + LLVMRealOGE, /**< True if ordered and greater than or equal */ + LLVMRealOLT, /**< True if ordered and less than */ + LLVMRealOLE, /**< True if ordered and less than or equal */ + LLVMRealONE, /**< True if ordered and operands are unequal */ + LLVMRealORD, /**< True if ordered (no nans) */ + LLVMRealUNO, /**< True if unordered: isnan(X) | isnan(Y) */ + LLVMRealUEQ, /**< True if unordered or equal */ + LLVMRealUGT, /**< True if unordered or greater than */ + LLVMRealUGE, /**< True if unordered, greater than, or equal */ + LLVMRealULT, /**< True if unordered or less than */ + LLVMRealULE, /**< True if unordered, less than, or equal */ + LLVMRealUNE, /**< True if unordered or not equal */ + LLVMRealPredicateTrue /**< Always true (always folded) */ +} LLVMRealPredicate; + + +/*===-- Error handling ----------------------------------------------------===*/ + +void LLVMDisposeMessage(char *Message); + + +/*===-- Modules -----------------------------------------------------------===*/ + +/* Create and destroy contexts. */ +LLVMContextRef LLVMContextCreate(void); +LLVMContextRef LLVMGetGlobalContext(void); +void LLVMContextDispose(LLVMContextRef C); + +/* Create and destroy modules. */ +/** See llvm::Module::Module. */ +LLVMModuleRef LLVMModuleCreateWithName(const char *ModuleID); +LLVMModuleRef LLVMModuleCreateWithNameInContext(const char *ModuleID, + LLVMContextRef C); + +/** See llvm::Module::~Module. */ +void LLVMDisposeModule(LLVMModuleRef M); + +/** Data layout. See Module::getDataLayout. */ +const char *LLVMGetDataLayout(LLVMModuleRef M); +void LLVMSetDataLayout(LLVMModuleRef M, const char *Triple); + +/** Target triple. See Module::getTargetTriple. */ +const char *LLVMGetTarget(LLVMModuleRef M); +void LLVMSetTarget(LLVMModuleRef M, const char *Triple); + +/** See Module::addTypeName. */ +int LLVMAddTypeName(LLVMModuleRef M, const char *Name, LLVMTypeRef Ty); +void LLVMDeleteTypeName(LLVMModuleRef M, const char *Name); +LLVMTypeRef LLVMGetTypeByName(LLVMModuleRef M, const char *Name); + +/** See Module::dump. */ +void LLVMDumpModule(LLVMModuleRef M); + + +/*===-- Types -------------------------------------------------------------===*/ + +/* LLVM types conform to the following hierarchy: + * + * types: + * integer type + * real type + * function type + * sequence types: + * array type + * pointer type + * vector type + * void type + * label type + * opaque type + */ + +/** See llvm::LLVMTypeKind::getTypeID. */ +LLVMTypeKind LLVMGetTypeKind(LLVMTypeRef Ty); + +/** See llvm::LLVMType::getContext. */ +LLVMContextRef LLVMGetTypeContext(LLVMTypeRef Ty); + +/* Operations on integer types */ +LLVMTypeRef LLVMInt1TypeInContext(LLVMContextRef C); +LLVMTypeRef LLVMInt8TypeInContext(LLVMContextRef C); +LLVMTypeRef LLVMInt16TypeInContext(LLVMContextRef C); +LLVMTypeRef LLVMInt32TypeInContext(LLVMContextRef C); +LLVMTypeRef LLVMInt64TypeInContext(LLVMContextRef C); +LLVMTypeRef LLVMIntTypeInContext(LLVMContextRef C, unsigned NumBits); + +LLVMTypeRef LLVMInt1Type(void); +LLVMTypeRef LLVMInt8Type(void); +LLVMTypeRef LLVMInt16Type(void); +LLVMTypeRef LLVMInt32Type(void); +LLVMTypeRef LLVMInt64Type(void); +LLVMTypeRef LLVMIntType(unsigned NumBits); +unsigned LLVMGetIntTypeWidth(LLVMTypeRef IntegerTy); + +/* Operations on real types */ +LLVMTypeRef LLVMFloatTypeInContext(LLVMContextRef C); +LLVMTypeRef LLVMDoubleTypeInContext(LLVMContextRef C); +LLVMTypeRef LLVMX86FP80TypeInContext(LLVMContextRef C); +LLVMTypeRef LLVMFP128TypeInContext(LLVMContextRef C); +LLVMTypeRef LLVMPPCFP128TypeInContext(LLVMContextRef C); + +LLVMTypeRef LLVMFloatType(void); +LLVMTypeRef LLVMDoubleType(void); +LLVMTypeRef LLVMX86FP80Type(void); +LLVMTypeRef LLVMFP128Type(void); +LLVMTypeRef LLVMPPCFP128Type(void); + +/* Operations on function types */ +LLVMTypeRef LLVMFunctionType(LLVMTypeRef ReturnType, + LLVMTypeRef *ParamTypes, unsigned ParamCount, + int IsVarArg); +int LLVMIsFunctionVarArg(LLVMTypeRef FunctionTy); +LLVMTypeRef LLVMGetReturnType(LLVMTypeRef FunctionTy); +unsigned LLVMCountParamTypes(LLVMTypeRef FunctionTy); +void LLVMGetParamTypes(LLVMTypeRef FunctionTy, LLVMTypeRef *Dest); + +/* Operations on struct types */ +LLVMTypeRef LLVMStructTypeInContext(LLVMContextRef C, LLVMTypeRef *ElementTypes, + unsigned ElementCount, int Packed); +LLVMTypeRef LLVMStructType(LLVMTypeRef *ElementTypes, unsigned ElementCount, + int Packed); +unsigned LLVMCountStructElementTypes(LLVMTypeRef StructTy); +void LLVMGetStructElementTypes(LLVMTypeRef StructTy, LLVMTypeRef *Dest); +int LLVMIsPackedStruct(LLVMTypeRef StructTy); + +/* Operations on array, pointer, and vector types (sequence types) */ +LLVMTypeRef LLVMArrayType(LLVMTypeRef ElementType, unsigned ElementCount); +LLVMTypeRef LLVMPointerType(LLVMTypeRef ElementType, unsigned AddressSpace); +LLVMTypeRef LLVMVectorType(LLVMTypeRef ElementType, unsigned ElementCount); + +LLVMTypeRef LLVMGetElementType(LLVMTypeRef Ty); +unsigned LLVMGetArrayLength(LLVMTypeRef ArrayTy); +unsigned LLVMGetPointerAddressSpace(LLVMTypeRef PointerTy); +unsigned LLVMGetVectorSize(LLVMTypeRef VectorTy); + +/* Operations on other types */ +LLVMTypeRef LLVMVoidTypeInContext(LLVMContextRef C); +LLVMTypeRef LLVMLabelTypeInContext(LLVMContextRef C); +LLVMTypeRef LLVMOpaqueTypeInContext(LLVMContextRef C); + +LLVMTypeRef LLVMVoidType(void); +LLVMTypeRef LLVMLabelType(void); +LLVMTypeRef LLVMOpaqueType(void); + +/* Operations on type handles */ +LLVMTypeHandleRef LLVMCreateTypeHandle(LLVMTypeRef PotentiallyAbstractTy); +void LLVMRefineType(LLVMTypeRef AbstractTy, LLVMTypeRef ConcreteTy); +LLVMTypeRef LLVMResolveTypeHandle(LLVMTypeHandleRef TypeHandle); +void LLVMDisposeTypeHandle(LLVMTypeHandleRef TypeHandle); + + +/*===-- Values ------------------------------------------------------------===*/ + +/* The bulk of LLVM's object model consists of values, which comprise a very + * rich type hierarchy. + */ + +#define LLVM_FOR_EACH_VALUE_SUBCLASS(macro) \ + macro(Argument) \ + macro(BasicBlock) \ + macro(InlineAsm) \ + macro(User) \ + macro(Constant) \ + macro(ConstantAggregateZero) \ + macro(ConstantArray) \ + macro(ConstantExpr) \ + macro(ConstantFP) \ + macro(ConstantInt) \ + macro(ConstantPointerNull) \ + macro(ConstantStruct) \ + macro(ConstantVector) \ + macro(GlobalValue) \ + macro(Function) \ + macro(GlobalAlias) \ + macro(GlobalVariable) \ + macro(UndefValue) \ + macro(Instruction) \ + macro(BinaryOperator) \ + macro(CallInst) \ + macro(IntrinsicInst) \ + macro(DbgInfoIntrinsic) \ + macro(DbgDeclareInst) \ + macro(DbgFuncStartInst) \ + macro(DbgRegionEndInst) \ + macro(DbgRegionStartInst) \ + macro(DbgStopPointInst) \ + macro(EHSelectorInst) \ + macro(MemIntrinsic) \ + macro(MemCpyInst) \ + macro(MemMoveInst) \ + macro(MemSetInst) \ + macro(CmpInst) \ + macro(FCmpInst) \ + macro(ICmpInst) \ + macro(ExtractElementInst) \ + macro(GetElementPtrInst) \ + macro(InsertElementInst) \ + macro(InsertValueInst) \ + macro(PHINode) \ + macro(SelectInst) \ + macro(ShuffleVectorInst) \ + macro(StoreInst) \ + macro(TerminatorInst) \ + macro(BranchInst) \ + macro(InvokeInst) \ + macro(ReturnInst) \ + macro(SwitchInst) \ + macro(UnreachableInst) \ + macro(UnwindInst) \ + macro(UnaryInstruction) \ + macro(AllocaInst) \ + macro(CastInst) \ + macro(BitCastInst) \ + macro(FPExtInst) \ + macro(FPToSIInst) \ + macro(FPToUIInst) \ + macro(FPTruncInst) \ + macro(IntToPtrInst) \ + macro(PtrToIntInst) \ + macro(SExtInst) \ + macro(SIToFPInst) \ + macro(TruncInst) \ + macro(UIToFPInst) \ + macro(ZExtInst) \ + macro(ExtractValueInst) \ + macro(LoadInst) \ + macro(VAArgInst) + +/* Operations on all values */ +LLVMTypeRef LLVMTypeOf(LLVMValueRef Val); +const char *LLVMGetValueName(LLVMValueRef Val); +void LLVMSetValueName(LLVMValueRef Val, const char *Name); +void LLVMDumpValue(LLVMValueRef Val); +void LLVMReplaceAllUsesWith(LLVMValueRef OldVal, LLVMValueRef NewVal); + +/* Conversion functions. Return the input value if it is an instance of the + specified class, otherwise NULL. See llvm::dyn_cast_or_null<>. */ +#define LLVM_DECLARE_VALUE_CAST(name) \ + LLVMValueRef LLVMIsA##name(LLVMValueRef Val); +LLVM_FOR_EACH_VALUE_SUBCLASS(LLVM_DECLARE_VALUE_CAST) + +/* Operations on Uses */ +LLVMUseIteratorRef LLVMGetFirstUse(LLVMValueRef Val); +LLVMUseIteratorRef LLVMGetNextUse(LLVMUseIteratorRef U); +LLVMValueRef LLVMGetUser(LLVMUseIteratorRef U); +LLVMValueRef LLVMGetUsedValue(LLVMUseIteratorRef U); + +/* Operations on Users */ +LLVMValueRef LLVMGetOperand(LLVMValueRef Val, unsigned Index); + +/* Operations on constants of any type */ +LLVMValueRef LLVMConstNull(LLVMTypeRef Ty); /* all zeroes */ +LLVMValueRef LLVMConstAllOnes(LLVMTypeRef Ty); /* only for int/vector */ +LLVMValueRef LLVMGetUndef(LLVMTypeRef Ty); +int LLVMIsConstant(LLVMValueRef Val); +int LLVMIsNull(LLVMValueRef Val); +int LLVMIsUndef(LLVMValueRef Val); +LLVMValueRef LLVMConstPointerNull(LLVMTypeRef Ty); + +/* Operations on scalar constants */ +LLVMValueRef LLVMConstInt(LLVMTypeRef IntTy, unsigned long long N, + int SignExtend); +LLVMValueRef LLVMConstIntOfString(LLVMTypeRef IntTy, const char *Text, + uint8_t Radix); +LLVMValueRef LLVMConstIntOfStringAndSize(LLVMTypeRef IntTy, const char *Text, + unsigned SLen, uint8_t Radix); +LLVMValueRef LLVMConstReal(LLVMTypeRef RealTy, double N); +LLVMValueRef LLVMConstRealOfString(LLVMTypeRef RealTy, const char *Text); +LLVMValueRef LLVMConstRealOfStringAndSize(LLVMTypeRef RealTy, const char *Text, + unsigned SLen); +unsigned long long LLVMConstIntGetZExtValue(LLVMValueRef ConstantVal); +long long LLVMConstIntGetSExtValue(LLVMValueRef ConstantVal); + + +/* Operations on composite constants */ +LLVMValueRef LLVMConstStringInContext(LLVMContextRef C, const char *Str, + unsigned Length, int DontNullTerminate); +LLVMValueRef LLVMConstStructInContext(LLVMContextRef C, + LLVMValueRef *ConstantVals, + unsigned Count, int Packed); + +LLVMValueRef LLVMConstString(const char *Str, unsigned Length, + int DontNullTerminate); +LLVMValueRef LLVMConstArray(LLVMTypeRef ElementTy, + LLVMValueRef *ConstantVals, unsigned Length); +LLVMValueRef LLVMConstStruct(LLVMValueRef *ConstantVals, unsigned Count, + int Packed); +LLVMValueRef LLVMConstVector(LLVMValueRef *ScalarConstantVals, unsigned Size); + +/* Constant expressions */ +LLVMOpcode LLVMGetConstOpcode(LLVMValueRef ConstantVal); +LLVMValueRef LLVMAlignOf(LLVMTypeRef Ty); +LLVMValueRef LLVMSizeOf(LLVMTypeRef Ty); +LLVMValueRef LLVMConstNeg(LLVMValueRef ConstantVal); +LLVMValueRef LLVMConstFNeg(LLVMValueRef ConstantVal); +LLVMValueRef LLVMConstNot(LLVMValueRef ConstantVal); +LLVMValueRef LLVMConstAdd(LLVMValueRef LHSConstant, LLVMValueRef RHSConstant); +LLVMValueRef LLVMConstNSWAdd(LLVMValueRef LHSConstant, LLVMValueRef RHSConstant); +LLVMValueRef LLVMConstFAdd(LLVMValueRef LHSConstant, LLVMValueRef RHSConstant); +LLVMValueRef LLVMConstSub(LLVMValueRef LHSConstant, LLVMValueRef RHSConstant); +LLVMValueRef LLVMConstFSub(LLVMValueRef LHSConstant, LLVMValueRef RHSConstant); +LLVMValueRef LLVMConstMul(LLVMValueRef LHSConstant, LLVMValueRef RHSConstant); +LLVMValueRef LLVMConstFMul(LLVMValueRef LHSConstant, LLVMValueRef RHSConstant); +LLVMValueRef LLVMConstUDiv(LLVMValueRef LHSConstant, LLVMValueRef RHSConstant); +LLVMValueRef LLVMConstSDiv(LLVMValueRef LHSConstant, LLVMValueRef RHSConstant); +LLVMValueRef LLVMConstExactSDiv(LLVMValueRef LHSConstant, LLVMValueRef RHSConstant); +LLVMValueRef LLVMConstFDiv(LLVMValueRef LHSConstant, LLVMValueRef RHSConstant); +LLVMValueRef LLVMConstURem(LLVMValueRef LHSConstant, LLVMValueRef RHSConstant); +LLVMValueRef LLVMConstSRem(LLVMValueRef LHSConstant, LLVMValueRef RHSConstant); +LLVMValueRef LLVMConstFRem(LLVMValueRef LHSConstant, LLVMValueRef RHSConstant); +LLVMValueRef LLVMConstAnd(LLVMValueRef LHSConstant, LLVMValueRef RHSConstant); +LLVMValueRef LLVMConstOr(LLVMValueRef LHSConstant, LLVMValueRef RHSConstant); +LLVMValueRef LLVMConstXor(LLVMValueRef LHSConstant, LLVMValueRef RHSConstant); +LLVMValueRef LLVMConstICmp(LLVMIntPredicate Predicate, + LLVMValueRef LHSConstant, LLVMValueRef RHSConstant); +LLVMValueRef LLVMConstFCmp(LLVMRealPredicate Predicate, + LLVMValueRef LHSConstant, LLVMValueRef RHSConstant); +LLVMValueRef LLVMConstShl(LLVMValueRef LHSConstant, LLVMValueRef RHSConstant); +LLVMValueRef LLVMConstLShr(LLVMValueRef LHSConstant, LLVMValueRef RHSConstant); +LLVMValueRef LLVMConstAShr(LLVMValueRef LHSConstant, LLVMValueRef RHSConstant); +LLVMValueRef LLVMConstGEP(LLVMValueRef ConstantVal, + LLVMValueRef *ConstantIndices, unsigned NumIndices); +LLVMValueRef LLVMConstInBoundsGEP(LLVMValueRef ConstantVal, + LLVMValueRef *ConstantIndices, + unsigned NumIndices); +LLVMValueRef LLVMConstTrunc(LLVMValueRef ConstantVal, LLVMTypeRef ToType); +LLVMValueRef LLVMConstSExt(LLVMValueRef ConstantVal, LLVMTypeRef ToType); +LLVMValueRef LLVMConstZExt(LLVMValueRef ConstantVal, LLVMTypeRef ToType); +LLVMValueRef LLVMConstFPTrunc(LLVMValueRef ConstantVal, LLVMTypeRef ToType); +LLVMValueRef LLVMConstFPExt(LLVMValueRef ConstantVal, LLVMTypeRef ToType); +LLVMValueRef LLVMConstUIToFP(LLVMValueRef ConstantVal, LLVMTypeRef ToType); +LLVMValueRef LLVMConstSIToFP(LLVMValueRef ConstantVal, LLVMTypeRef ToType); +LLVMValueRef LLVMConstFPToUI(LLVMValueRef ConstantVal, LLVMTypeRef ToType); +LLVMValueRef LLVMConstFPToSI(LLVMValueRef ConstantVal, LLVMTypeRef ToType); +LLVMValueRef LLVMConstPtrToInt(LLVMValueRef ConstantVal, LLVMTypeRef ToType); +LLVMValueRef LLVMConstIntToPtr(LLVMValueRef ConstantVal, LLVMTypeRef ToType); +LLVMValueRef LLVMConstBitCast(LLVMValueRef ConstantVal, LLVMTypeRef ToType); +LLVMValueRef LLVMConstZExtOrBitCast(LLVMValueRef ConstantVal, + LLVMTypeRef ToType); +LLVMValueRef LLVMConstSExtOrBitCast(LLVMValueRef ConstantVal, + LLVMTypeRef ToType); +LLVMValueRef LLVMConstTruncOrBitCast(LLVMValueRef ConstantVal, + LLVMTypeRef ToType); +LLVMValueRef LLVMConstPointerCast(LLVMValueRef ConstantVal, + LLVMTypeRef ToType); +LLVMValueRef LLVMConstIntCast(LLVMValueRef ConstantVal, LLVMTypeRef ToType, + unsigned isSigned); +LLVMValueRef LLVMConstFPCast(LLVMValueRef ConstantVal, LLVMTypeRef ToType); +LLVMValueRef LLVMConstSelect(LLVMValueRef ConstantCondition, + LLVMValueRef ConstantIfTrue, + LLVMValueRef ConstantIfFalse); +LLVMValueRef LLVMConstExtractElement(LLVMValueRef VectorConstant, + LLVMValueRef IndexConstant); +LLVMValueRef LLVMConstInsertElement(LLVMValueRef VectorConstant, + LLVMValueRef ElementValueConstant, + LLVMValueRef IndexConstant); +LLVMValueRef LLVMConstShuffleVector(LLVMValueRef VectorAConstant, + LLVMValueRef VectorBConstant, + LLVMValueRef MaskConstant); +LLVMValueRef LLVMConstExtractValue(LLVMValueRef AggConstant, unsigned *IdxList, + unsigned NumIdx); +LLVMValueRef LLVMConstInsertValue(LLVMValueRef AggConstant, + LLVMValueRef ElementValueConstant, + unsigned *IdxList, unsigned NumIdx); +LLVMValueRef LLVMConstInlineAsm(LLVMTypeRef Ty, + const char *AsmString, const char *Constraints, + int HasSideEffects); + +/* Operations on global variables, functions, and aliases (globals) */ +LLVMModuleRef LLVMGetGlobalParent(LLVMValueRef Global); +int LLVMIsDeclaration(LLVMValueRef Global); +LLVMLinkage LLVMGetLinkage(LLVMValueRef Global); +void LLVMSetLinkage(LLVMValueRef Global, LLVMLinkage Linkage); +const char *LLVMGetSection(LLVMValueRef Global); +void LLVMSetSection(LLVMValueRef Global, const char *Section); +LLVMVisibility LLVMGetVisibility(LLVMValueRef Global); +void LLVMSetVisibility(LLVMValueRef Global, LLVMVisibility Viz); +unsigned LLVMGetAlignment(LLVMValueRef Global); +void LLVMSetAlignment(LLVMValueRef Global, unsigned Bytes); + +/* Operations on global variables */ +LLVMValueRef LLVMAddGlobal(LLVMModuleRef M, LLVMTypeRef Ty, const char *Name); +LLVMValueRef LLVMGetNamedGlobal(LLVMModuleRef M, const char *Name); +LLVMValueRef LLVMGetFirstGlobal(LLVMModuleRef M); +LLVMValueRef LLVMGetLastGlobal(LLVMModuleRef M); +LLVMValueRef LLVMGetNextGlobal(LLVMValueRef GlobalVar); +LLVMValueRef LLVMGetPreviousGlobal(LLVMValueRef GlobalVar); +void LLVMDeleteGlobal(LLVMValueRef GlobalVar); +LLVMValueRef LLVMGetInitializer(LLVMValueRef GlobalVar); +void LLVMSetInitializer(LLVMValueRef GlobalVar, LLVMValueRef ConstantVal); +int LLVMIsThreadLocal(LLVMValueRef GlobalVar); +void LLVMSetThreadLocal(LLVMValueRef GlobalVar, int IsThreadLocal); +int LLVMIsGlobalConstant(LLVMValueRef GlobalVar); +void LLVMSetGlobalConstant(LLVMValueRef GlobalVar, int IsConstant); + +/* Operations on aliases */ +LLVMValueRef LLVMAddAlias(LLVMModuleRef M, LLVMTypeRef Ty, LLVMValueRef Aliasee, + const char *Name); + +/* Operations on functions */ +LLVMValueRef LLVMAddFunction(LLVMModuleRef M, const char *Name, + LLVMTypeRef FunctionTy); +LLVMValueRef LLVMGetNamedFunction(LLVMModuleRef M, const char *Name); +LLVMValueRef LLVMGetFirstFunction(LLVMModuleRef M); +LLVMValueRef LLVMGetLastFunction(LLVMModuleRef M); +LLVMValueRef LLVMGetNextFunction(LLVMValueRef Fn); +LLVMValueRef LLVMGetPreviousFunction(LLVMValueRef Fn); +void LLVMDeleteFunction(LLVMValueRef Fn); +unsigned LLVMGetIntrinsicID(LLVMValueRef Fn); +unsigned LLVMGetFunctionCallConv(LLVMValueRef Fn); +void LLVMSetFunctionCallConv(LLVMValueRef Fn, unsigned CC); +const char *LLVMGetGC(LLVMValueRef Fn); +void LLVMSetGC(LLVMValueRef Fn, const char *Name); +void LLVMAddFunctionAttr(LLVMValueRef Fn, LLVMAttribute PA); +LLVMAttribute LLVMGetFunctionAttr(LLVMValueRef Fn); +void LLVMRemoveFunctionAttr(LLVMValueRef Fn, LLVMAttribute PA); + +/* Operations on parameters */ +unsigned LLVMCountParams(LLVMValueRef Fn); +void LLVMGetParams(LLVMValueRef Fn, LLVMValueRef *Params); +LLVMValueRef LLVMGetParam(LLVMValueRef Fn, unsigned Index); +LLVMValueRef LLVMGetParamParent(LLVMValueRef Inst); +LLVMValueRef LLVMGetFirstParam(LLVMValueRef Fn); +LLVMValueRef LLVMGetLastParam(LLVMValueRef Fn); +LLVMValueRef LLVMGetNextParam(LLVMValueRef Arg); +LLVMValueRef LLVMGetPreviousParam(LLVMValueRef Arg); +void LLVMAddAttribute(LLVMValueRef Arg, LLVMAttribute PA); +void LLVMRemoveAttribute(LLVMValueRef Arg, LLVMAttribute PA); +LLVMAttribute LLVMGetAttribute(LLVMValueRef Arg); +void LLVMSetParamAlignment(LLVMValueRef Arg, unsigned align); + +/* Operations on basic blocks */ +LLVMValueRef LLVMBasicBlockAsValue(LLVMBasicBlockRef BB); +int LLVMValueIsBasicBlock(LLVMValueRef Val); +LLVMBasicBlockRef LLVMValueAsBasicBlock(LLVMValueRef Val); +LLVMValueRef LLVMGetBasicBlockParent(LLVMBasicBlockRef BB); +unsigned LLVMCountBasicBlocks(LLVMValueRef Fn); +void LLVMGetBasicBlocks(LLVMValueRef Fn, LLVMBasicBlockRef *BasicBlocks); +LLVMBasicBlockRef LLVMGetFirstBasicBlock(LLVMValueRef Fn); +LLVMBasicBlockRef LLVMGetLastBasicBlock(LLVMValueRef Fn); +LLVMBasicBlockRef LLVMGetNextBasicBlock(LLVMBasicBlockRef BB); +LLVMBasicBlockRef LLVMGetPreviousBasicBlock(LLVMBasicBlockRef BB); +LLVMBasicBlockRef LLVMGetEntryBasicBlock(LLVMValueRef Fn); + +LLVMBasicBlockRef LLVMAppendBasicBlockInContext(LLVMContextRef C, + LLVMValueRef Fn, + const char *Name); +LLVMBasicBlockRef LLVMInsertBasicBlockInContext(LLVMContextRef C, + LLVMBasicBlockRef BB, + const char *Name); + +LLVMBasicBlockRef LLVMAppendBasicBlock(LLVMValueRef Fn, const char *Name); +LLVMBasicBlockRef LLVMInsertBasicBlock(LLVMBasicBlockRef InsertBeforeBB, + const char *Name); +void LLVMDeleteBasicBlock(LLVMBasicBlockRef BB); + +/* Operations on instructions */ +LLVMBasicBlockRef LLVMGetInstructionParent(LLVMValueRef Inst); +LLVMValueRef LLVMGetFirstInstruction(LLVMBasicBlockRef BB); +LLVMValueRef LLVMGetLastInstruction(LLVMBasicBlockRef BB); +LLVMValueRef LLVMGetNextInstruction(LLVMValueRef Inst); +LLVMValueRef LLVMGetPreviousInstruction(LLVMValueRef Inst); + +/* Operations on call sites */ +void LLVMSetInstructionCallConv(LLVMValueRef Instr, unsigned CC); +unsigned LLVMGetInstructionCallConv(LLVMValueRef Instr); +void LLVMAddInstrAttribute(LLVMValueRef Instr, unsigned index, LLVMAttribute); +void LLVMRemoveInstrAttribute(LLVMValueRef Instr, unsigned index, + LLVMAttribute); +void LLVMSetInstrParamAlignment(LLVMValueRef Instr, unsigned index, + unsigned align); + +/* Operations on call instructions (only) */ +int LLVMIsTailCall(LLVMValueRef CallInst); +void LLVMSetTailCall(LLVMValueRef CallInst, int IsTailCall); + +/* Operations on phi nodes */ +void LLVMAddIncoming(LLVMValueRef PhiNode, LLVMValueRef *IncomingValues, + LLVMBasicBlockRef *IncomingBlocks, unsigned Count); +unsigned LLVMCountIncoming(LLVMValueRef PhiNode); +LLVMValueRef LLVMGetIncomingValue(LLVMValueRef PhiNode, unsigned Index); +LLVMBasicBlockRef LLVMGetIncomingBlock(LLVMValueRef PhiNode, unsigned Index); + +/*===-- Instruction builders ----------------------------------------------===*/ + +/* An instruction builder represents a point within a basic block, and is the + * exclusive means of building instructions using the C interface. + */ + +LLVMBuilderRef LLVMCreateBuilderInContext(LLVMContextRef C); +LLVMBuilderRef LLVMCreateBuilder(void); +void LLVMPositionBuilder(LLVMBuilderRef Builder, LLVMBasicBlockRef Block, + LLVMValueRef Instr); +void LLVMPositionBuilderBefore(LLVMBuilderRef Builder, LLVMValueRef Instr); +void LLVMPositionBuilderAtEnd(LLVMBuilderRef Builder, LLVMBasicBlockRef Block); +LLVMBasicBlockRef LLVMGetInsertBlock(LLVMBuilderRef Builder); +void LLVMClearInsertionPosition(LLVMBuilderRef Builder); +void LLVMInsertIntoBuilder(LLVMBuilderRef Builder, LLVMValueRef Instr); +void LLVMInsertIntoBuilderWithName(LLVMBuilderRef Builder, LLVMValueRef Instr, + const char *Name); +void LLVMDisposeBuilder(LLVMBuilderRef Builder); + +/* Terminators */ +LLVMValueRef LLVMBuildRetVoid(LLVMBuilderRef); +LLVMValueRef LLVMBuildRet(LLVMBuilderRef, LLVMValueRef V); +LLVMValueRef LLVMBuildAggregateRet(LLVMBuilderRef, LLVMValueRef *RetVals, + unsigned N); +LLVMValueRef LLVMBuildBr(LLVMBuilderRef, LLVMBasicBlockRef Dest); +LLVMValueRef LLVMBuildCondBr(LLVMBuilderRef, LLVMValueRef If, + LLVMBasicBlockRef Then, LLVMBasicBlockRef Else); +LLVMValueRef LLVMBuildSwitch(LLVMBuilderRef, LLVMValueRef V, + LLVMBasicBlockRef Else, unsigned NumCases); +LLVMValueRef LLVMBuildInvoke(LLVMBuilderRef, LLVMValueRef Fn, + LLVMValueRef *Args, unsigned NumArgs, + LLVMBasicBlockRef Then, LLVMBasicBlockRef Catch, + const char *Name); +LLVMValueRef LLVMBuildUnwind(LLVMBuilderRef); +LLVMValueRef LLVMBuildUnreachable(LLVMBuilderRef); + +/* Add a case to the switch instruction */ +void LLVMAddCase(LLVMValueRef Switch, LLVMValueRef OnVal, + LLVMBasicBlockRef Dest); + +/* Arithmetic */ +LLVMValueRef LLVMBuildAdd(LLVMBuilderRef, LLVMValueRef LHS, LLVMValueRef RHS, + const char *Name); +LLVMValueRef LLVMBuildNSWAdd(LLVMBuilderRef, LLVMValueRef LHS, LLVMValueRef RHS, + const char *Name); +LLVMValueRef LLVMBuildFAdd(LLVMBuilderRef, LLVMValueRef LHS, LLVMValueRef RHS, + const char *Name); +LLVMValueRef LLVMBuildSub(LLVMBuilderRef, LLVMValueRef LHS, LLVMValueRef RHS, + const char *Name); +LLVMValueRef LLVMBuildFSub(LLVMBuilderRef, LLVMValueRef LHS, LLVMValueRef RHS, + const char *Name); +LLVMValueRef LLVMBuildMul(LLVMBuilderRef, LLVMValueRef LHS, LLVMValueRef RHS, + const char *Name); +LLVMValueRef LLVMBuildFMul(LLVMBuilderRef, LLVMValueRef LHS, LLVMValueRef RHS, + const char *Name); +LLVMValueRef LLVMBuildUDiv(LLVMBuilderRef, LLVMValueRef LHS, LLVMValueRef RHS, + const char *Name); +LLVMValueRef LLVMBuildSDiv(LLVMBuilderRef, LLVMValueRef LHS, LLVMValueRef RHS, + const char *Name); +LLVMValueRef LLVMBuildExactSDiv(LLVMBuilderRef, LLVMValueRef LHS, LLVMValueRef RHS, + const char *Name); +LLVMValueRef LLVMBuildFDiv(LLVMBuilderRef, LLVMValueRef LHS, LLVMValueRef RHS, + const char *Name); +LLVMValueRef LLVMBuildURem(LLVMBuilderRef, LLVMValueRef LHS, LLVMValueRef RHS, + const char *Name); +LLVMValueRef LLVMBuildSRem(LLVMBuilderRef, LLVMValueRef LHS, LLVMValueRef RHS, + const char *Name); +LLVMValueRef LLVMBuildFRem(LLVMBuilderRef, LLVMValueRef LHS, LLVMValueRef RHS, + const char *Name); +LLVMValueRef LLVMBuildShl(LLVMBuilderRef, LLVMValueRef LHS, LLVMValueRef RHS, + const char *Name); +LLVMValueRef LLVMBuildLShr(LLVMBuilderRef, LLVMValueRef LHS, LLVMValueRef RHS, + const char *Name); +LLVMValueRef LLVMBuildAShr(LLVMBuilderRef, LLVMValueRef LHS, LLVMValueRef RHS, + const char *Name); +LLVMValueRef LLVMBuildAnd(LLVMBuilderRef, LLVMValueRef LHS, LLVMValueRef RHS, + const char *Name); +LLVMValueRef LLVMBuildOr(LLVMBuilderRef, LLVMValueRef LHS, LLVMValueRef RHS, + const char *Name); +LLVMValueRef LLVMBuildXor(LLVMBuilderRef, LLVMValueRef LHS, LLVMValueRef RHS, + const char *Name); +LLVMValueRef LLVMBuildNeg(LLVMBuilderRef, LLVMValueRef V, const char *Name); +LLVMValueRef LLVMBuildFNeg(LLVMBuilderRef, LLVMValueRef V, const char *Name); +LLVMValueRef LLVMBuildNot(LLVMBuilderRef, LLVMValueRef V, const char *Name); + +/* Memory */ +LLVMValueRef LLVMBuildMalloc(LLVMBuilderRef, LLVMTypeRef Ty, const char *Name); +LLVMValueRef LLVMBuildArrayMalloc(LLVMBuilderRef, LLVMTypeRef Ty, + LLVMValueRef Val, const char *Name); +LLVMValueRef LLVMBuildAlloca(LLVMBuilderRef, LLVMTypeRef Ty, const char *Name); +LLVMValueRef LLVMBuildArrayAlloca(LLVMBuilderRef, LLVMTypeRef Ty, + LLVMValueRef Val, const char *Name); +LLVMValueRef LLVMBuildFree(LLVMBuilderRef, LLVMValueRef PointerVal); +LLVMValueRef LLVMBuildLoad(LLVMBuilderRef, LLVMValueRef PointerVal, + const char *Name); +LLVMValueRef LLVMBuildStore(LLVMBuilderRef, LLVMValueRef Val, LLVMValueRef Ptr); +LLVMValueRef LLVMBuildGEP(LLVMBuilderRef B, LLVMValueRef Pointer, + LLVMValueRef *Indices, unsigned NumIndices, + const char *Name); +LLVMValueRef LLVMBuildInBoundsGEP(LLVMBuilderRef B, LLVMValueRef Pointer, + LLVMValueRef *Indices, unsigned NumIndices, + const char *Name); +LLVMValueRef LLVMBuildStructGEP(LLVMBuilderRef B, LLVMValueRef Pointer, + unsigned Idx, const char *Name); +LLVMValueRef LLVMBuildGlobalString(LLVMBuilderRef B, const char *Str, + const char *Name); +LLVMValueRef LLVMBuildGlobalStringPtr(LLVMBuilderRef B, const char *Str, + const char *Name); + +/* Casts */ +LLVMValueRef LLVMBuildTrunc(LLVMBuilderRef, LLVMValueRef Val, + LLVMTypeRef DestTy, const char *Name); +LLVMValueRef LLVMBuildZExt(LLVMBuilderRef, LLVMValueRef Val, + LLVMTypeRef DestTy, const char *Name); +LLVMValueRef LLVMBuildSExt(LLVMBuilderRef, LLVMValueRef Val, + LLVMTypeRef DestTy, const char *Name); +LLVMValueRef LLVMBuildFPToUI(LLVMBuilderRef, LLVMValueRef Val, + LLVMTypeRef DestTy, const char *Name); +LLVMValueRef LLVMBuildFPToSI(LLVMBuilderRef, LLVMValueRef Val, + LLVMTypeRef DestTy, const char *Name); +LLVMValueRef LLVMBuildUIToFP(LLVMBuilderRef, LLVMValueRef Val, + LLVMTypeRef DestTy, const char *Name); +LLVMValueRef LLVMBuildSIToFP(LLVMBuilderRef, LLVMValueRef Val, + LLVMTypeRef DestTy, const char *Name); +LLVMValueRef LLVMBuildFPTrunc(LLVMBuilderRef, LLVMValueRef Val, + LLVMTypeRef DestTy, const char *Name); +LLVMValueRef LLVMBuildFPExt(LLVMBuilderRef, LLVMValueRef Val, + LLVMTypeRef DestTy, const char *Name); +LLVMValueRef LLVMBuildPtrToInt(LLVMBuilderRef, LLVMValueRef Val, + LLVMTypeRef DestTy, const char *Name); +LLVMValueRef LLVMBuildIntToPtr(LLVMBuilderRef, LLVMValueRef Val, + LLVMTypeRef DestTy, const char *Name); +LLVMValueRef LLVMBuildBitCast(LLVMBuilderRef, LLVMValueRef Val, + LLVMTypeRef DestTy, const char *Name); +LLVMValueRef LLVMBuildZExtOrBitCast(LLVMBuilderRef, LLVMValueRef Val, + LLVMTypeRef DestTy, const char *Name); +LLVMValueRef LLVMBuildSExtOrBitCast(LLVMBuilderRef, LLVMValueRef Val, + LLVMTypeRef DestTy, const char *Name); +LLVMValueRef LLVMBuildTruncOrBitCast(LLVMBuilderRef, LLVMValueRef Val, + LLVMTypeRef DestTy, const char *Name); +LLVMValueRef LLVMBuildPointerCast(LLVMBuilderRef, LLVMValueRef Val, + LLVMTypeRef DestTy, const char *Name); +LLVMValueRef LLVMBuildIntCast(LLVMBuilderRef, LLVMValueRef Val, /*Signed cast!*/ + LLVMTypeRef DestTy, const char *Name); +LLVMValueRef LLVMBuildFPCast(LLVMBuilderRef, LLVMValueRef Val, + LLVMTypeRef DestTy, const char *Name); + +/* Comparisons */ +LLVMValueRef LLVMBuildICmp(LLVMBuilderRef, LLVMIntPredicate Op, + LLVMValueRef LHS, LLVMValueRef RHS, + const char *Name); +LLVMValueRef LLVMBuildFCmp(LLVMBuilderRef, LLVMRealPredicate Op, + LLVMValueRef LHS, LLVMValueRef RHS, + const char *Name); + +/* Miscellaneous instructions */ +LLVMValueRef LLVMBuildPhi(LLVMBuilderRef, LLVMTypeRef Ty, const char *Name); +LLVMValueRef LLVMBuildCall(LLVMBuilderRef, LLVMValueRef Fn, + LLVMValueRef *Args, unsigned NumArgs, + const char *Name); +LLVMValueRef LLVMBuildSelect(LLVMBuilderRef, LLVMValueRef If, + LLVMValueRef Then, LLVMValueRef Else, + const char *Name); +LLVMValueRef LLVMBuildVAArg(LLVMBuilderRef, LLVMValueRef List, LLVMTypeRef Ty, + const char *Name); +LLVMValueRef LLVMBuildExtractElement(LLVMBuilderRef, LLVMValueRef VecVal, + LLVMValueRef Index, const char *Name); +LLVMValueRef LLVMBuildInsertElement(LLVMBuilderRef, LLVMValueRef VecVal, + LLVMValueRef EltVal, LLVMValueRef Index, + const char *Name); +LLVMValueRef LLVMBuildShuffleVector(LLVMBuilderRef, LLVMValueRef V1, + LLVMValueRef V2, LLVMValueRef Mask, + const char *Name); +LLVMValueRef LLVMBuildExtractValue(LLVMBuilderRef, LLVMValueRef AggVal, + unsigned Index, const char *Name); +LLVMValueRef LLVMBuildInsertValue(LLVMBuilderRef, LLVMValueRef AggVal, + LLVMValueRef EltVal, unsigned Index, + const char *Name); + +LLVMValueRef LLVMBuildIsNull(LLVMBuilderRef, LLVMValueRef Val, + const char *Name); +LLVMValueRef LLVMBuildIsNotNull(LLVMBuilderRef, LLVMValueRef Val, + const char *Name); +LLVMValueRef LLVMBuildPtrDiff(LLVMBuilderRef, LLVMValueRef LHS, + LLVMValueRef RHS, const char *Name); + + +/*===-- Module providers --------------------------------------------------===*/ + +/* Encapsulates the module M in a module provider, taking ownership of the + * module. + * See the constructor llvm::ExistingModuleProvider::ExistingModuleProvider. + */ +LLVMModuleProviderRef +LLVMCreateModuleProviderForExistingModule(LLVMModuleRef M); + +/* Destroys the module provider MP as well as the contained module. + * See the destructor llvm::ModuleProvider::~ModuleProvider. + */ +void LLVMDisposeModuleProvider(LLVMModuleProviderRef MP); + + +/*===-- Memory buffers ----------------------------------------------------===*/ + +int LLVMCreateMemoryBufferWithContentsOfFile(const char *Path, + LLVMMemoryBufferRef *OutMemBuf, + char **OutMessage); +int LLVMCreateMemoryBufferWithSTDIN(LLVMMemoryBufferRef *OutMemBuf, + char **OutMessage); +void LLVMDisposeMemoryBuffer(LLVMMemoryBufferRef MemBuf); + + +/*===-- Pass Managers -----------------------------------------------------===*/ + +/** Constructs a new whole-module pass pipeline. This type of pipeline is + suitable for link-time optimization and whole-module transformations. + See llvm::PassManager::PassManager. */ +LLVMPassManagerRef LLVMCreatePassManager(void); + +/** Constructs a new function-by-function pass pipeline over the module + provider. It does not take ownership of the module provider. This type of + pipeline is suitable for code generation and JIT compilation tasks. + See llvm::FunctionPassManager::FunctionPassManager. */ +LLVMPassManagerRef LLVMCreateFunctionPassManager(LLVMModuleProviderRef MP); + +/** Initializes, executes on the provided module, and finalizes all of the + passes scheduled in the pass manager. Returns 1 if any of the passes + modified the module, 0 otherwise. See llvm::PassManager::run(Module&). */ +int LLVMRunPassManager(LLVMPassManagerRef PM, LLVMModuleRef M); + +/** Initializes all of the function passes scheduled in the function pass + manager. Returns 1 if any of the passes modified the module, 0 otherwise. + See llvm::FunctionPassManager::doInitialization. */ +int LLVMInitializeFunctionPassManager(LLVMPassManagerRef FPM); + +/** Executes all of the function passes scheduled in the function pass manager + on the provided function. Returns 1 if any of the passes modified the + function, false otherwise. + See llvm::FunctionPassManager::run(Function&). */ +int LLVMRunFunctionPassManager(LLVMPassManagerRef FPM, LLVMValueRef F); + +/** Finalizes all of the function passes scheduled in in the function pass + manager. Returns 1 if any of the passes modified the module, 0 otherwise. + See llvm::FunctionPassManager::doFinalization. */ +int LLVMFinalizeFunctionPassManager(LLVMPassManagerRef FPM); + +/** Frees the memory of a pass pipeline. For function pipelines, does not free + the module provider. + See llvm::PassManagerBase::~PassManagerBase. */ +void LLVMDisposePassManager(LLVMPassManagerRef PM); + + +#ifdef __cplusplus +} + +namespace llvm { + class ModuleProvider; + class MemoryBuffer; + class PassManagerBase; + + #define DEFINE_SIMPLE_CONVERSION_FUNCTIONS(ty, ref) \ + inline ty *unwrap(ref P) { \ + return reinterpret_cast(P); \ + } \ + \ + inline ref wrap(const ty *P) { \ + return reinterpret_cast(const_cast(P)); \ + } + + #define DEFINE_ISA_CONVERSION_FUNCTIONS(ty, ref) \ + DEFINE_SIMPLE_CONVERSION_FUNCTIONS(ty, ref) \ + \ + template \ + inline T *unwrap(ref P) { \ + return cast(unwrap(P)); \ + } + + #define DEFINE_STDCXX_CONVERSION_FUNCTIONS(ty, ref) \ + DEFINE_SIMPLE_CONVERSION_FUNCTIONS(ty, ref) \ + \ + template \ + inline T *unwrap(ref P) { \ + T *Q = dynamic_cast(unwrap(P)); \ + assert(Q && "Invalid cast!"); \ + return Q; \ + } + + DEFINE_ISA_CONVERSION_FUNCTIONS (Type, LLVMTypeRef ) + DEFINE_ISA_CONVERSION_FUNCTIONS (Value, LLVMValueRef ) + DEFINE_SIMPLE_CONVERSION_FUNCTIONS(Module, LLVMModuleRef ) + DEFINE_SIMPLE_CONVERSION_FUNCTIONS(BasicBlock, LLVMBasicBlockRef ) + DEFINE_SIMPLE_CONVERSION_FUNCTIONS(IRBuilder<>, LLVMBuilderRef ) + DEFINE_SIMPLE_CONVERSION_FUNCTIONS(PATypeHolder, LLVMTypeHandleRef ) + DEFINE_SIMPLE_CONVERSION_FUNCTIONS(ModuleProvider, LLVMModuleProviderRef) + DEFINE_SIMPLE_CONVERSION_FUNCTIONS(MemoryBuffer, LLVMMemoryBufferRef ) + DEFINE_SIMPLE_CONVERSION_FUNCTIONS(LLVMContext, LLVMContextRef ) + DEFINE_SIMPLE_CONVERSION_FUNCTIONS(Use, LLVMUseIteratorRef ) + DEFINE_STDCXX_CONVERSION_FUNCTIONS(PassManagerBase, LLVMPassManagerRef ) + + #undef DEFINE_STDCXX_CONVERSION_FUNCTIONS + #undef DEFINE_ISA_CONVERSION_FUNCTIONS + #undef DEFINE_SIMPLE_CONVERSION_FUNCTIONS + + /* Specialized opaque context conversions. + */ + inline LLVMContext **unwrap(LLVMContextRef* Tys) { + return reinterpret_cast(Tys); + } + + inline LLVMContextRef *wrap(const LLVMContext **Tys) { + return reinterpret_cast(const_cast(Tys)); + } + + /* Specialized opaque type conversions. + */ + inline Type **unwrap(LLVMTypeRef* Tys) { + return reinterpret_cast(Tys); + } + + inline LLVMTypeRef *wrap(const Type **Tys) { + return reinterpret_cast(const_cast(Tys)); + } + + /* Specialized opaque value conversions. + */ + inline Value **unwrap(LLVMValueRef *Vals) { + return reinterpret_cast(Vals); + } + + template + inline T **unwrap(LLVMValueRef *Vals, unsigned Length) { + #if DEBUG + for (LLVMValueRef *I = Vals, *E = Vals + Length; I != E; ++I) + cast(*I); + #endif + return reinterpret_cast(Vals); + } + + inline LLVMValueRef *wrap(const Value **Vals) { + return reinterpret_cast(const_cast(Vals)); + } +} + +#endif /* !defined(__cplusplus) */ + +#endif /* !defined(LLVM_C_CORE_H) */ diff --git a/libclamav/c++/llvm/include/llvm-c/ExecutionEngine.h b/libclamav/c++/llvm/include/llvm-c/ExecutionEngine.h new file mode 100644 index 000000000..05f2a892e --- /dev/null +++ b/libclamav/c++/llvm/include/llvm-c/ExecutionEngine.h @@ -0,0 +1,127 @@ +/*===-- llvm-c/ExecutionEngine.h - ExecutionEngine Lib C Iface --*- 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 libLLVMExecutionEngine.o, which *| +|* implements various analyses of the LLVM IR. *| +|* *| +|* Many exotic languages can interoperate with C code but have a harder time *| +|* with C++ due to name mangling. So in addition to C, this interface enables *| +|* tools written in such languages. *| +|* *| +\*===----------------------------------------------------------------------===*/ + +#ifndef LLVM_C_EXECUTIONENGINE_H +#define LLVM_C_EXECUTIONENGINE_H + +#include "llvm-c/Core.h" +#include "llvm-c/Target.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void LLVMLinkInJIT(void); +void LLVMLinkInInterpreter(void); + +typedef struct LLVMOpaqueGenericValue *LLVMGenericValueRef; +typedef struct LLVMOpaqueExecutionEngine *LLVMExecutionEngineRef; + +/*===-- Operations on generic values --------------------------------------===*/ + +LLVMGenericValueRef LLVMCreateGenericValueOfInt(LLVMTypeRef Ty, + unsigned long long N, + int IsSigned); + +LLVMGenericValueRef LLVMCreateGenericValueOfPointer(void *P); + +LLVMGenericValueRef LLVMCreateGenericValueOfFloat(LLVMTypeRef Ty, double N); + +unsigned LLVMGenericValueIntWidth(LLVMGenericValueRef GenValRef); + +unsigned long long LLVMGenericValueToInt(LLVMGenericValueRef GenVal, + int IsSigned); + +void *LLVMGenericValueToPointer(LLVMGenericValueRef GenVal); + +double LLVMGenericValueToFloat(LLVMTypeRef TyRef, LLVMGenericValueRef GenVal); + +void LLVMDisposeGenericValue(LLVMGenericValueRef GenVal); + +/*===-- Operations on execution engines -----------------------------------===*/ + +int LLVMCreateExecutionEngine(LLVMExecutionEngineRef *OutEE, + LLVMModuleProviderRef MP, + char **OutError); + +int LLVMCreateInterpreter(LLVMExecutionEngineRef *OutInterp, + LLVMModuleProviderRef MP, + char **OutError); + +int LLVMCreateJITCompiler(LLVMExecutionEngineRef *OutJIT, + LLVMModuleProviderRef MP, + unsigned OptLevel, + char **OutError); + +void LLVMDisposeExecutionEngine(LLVMExecutionEngineRef EE); + +void LLVMRunStaticConstructors(LLVMExecutionEngineRef EE); + +void LLVMRunStaticDestructors(LLVMExecutionEngineRef EE); + +int LLVMRunFunctionAsMain(LLVMExecutionEngineRef EE, LLVMValueRef F, + unsigned ArgC, const char * const *ArgV, + const char * const *EnvP); + +LLVMGenericValueRef LLVMRunFunction(LLVMExecutionEngineRef EE, LLVMValueRef F, + unsigned NumArgs, + LLVMGenericValueRef *Args); + +void LLVMFreeMachineCodeForFunction(LLVMExecutionEngineRef EE, LLVMValueRef F); + +void LLVMAddModuleProvider(LLVMExecutionEngineRef EE, LLVMModuleProviderRef MP); + +int LLVMRemoveModuleProvider(LLVMExecutionEngineRef EE, + LLVMModuleProviderRef MP, + LLVMModuleRef *OutMod, char **OutError); + +int LLVMFindFunction(LLVMExecutionEngineRef EE, const char *Name, + LLVMValueRef *OutFn); + +LLVMTargetDataRef LLVMGetExecutionEngineTargetData(LLVMExecutionEngineRef EE); + +void LLVMAddGlobalMapping(LLVMExecutionEngineRef EE, LLVMValueRef Global, + void* Addr); + +void *LLVMGetPointerToGlobal(LLVMExecutionEngineRef EE, LLVMValueRef Global); + +#ifdef __cplusplus +} + +namespace llvm { + struct GenericValue; + class ExecutionEngine; + + #define DEFINE_SIMPLE_CONVERSION_FUNCTIONS(ty, ref) \ + inline ty *unwrap(ref P) { \ + return reinterpret_cast(P); \ + } \ + \ + inline ref wrap(const ty *P) { \ + return reinterpret_cast(const_cast(P)); \ + } + + DEFINE_SIMPLE_CONVERSION_FUNCTIONS(GenericValue, LLVMGenericValueRef ) + DEFINE_SIMPLE_CONVERSION_FUNCTIONS(ExecutionEngine, LLVMExecutionEngineRef) + + #undef DEFINE_SIMPLE_CONVERSION_FUNCTIONS +} + +#endif /* defined(__cplusplus) */ + +#endif diff --git a/libclamav/c++/llvm/include/llvm-c/LinkTimeOptimizer.h b/libclamav/c++/llvm/include/llvm-c/LinkTimeOptimizer.h new file mode 100644 index 000000000..ccfdceed0 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm-c/LinkTimeOptimizer.h @@ -0,0 +1,58 @@ +//===-- llvm/LinkTimeOptimizer.h - LTO Public 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 provides a C API to use the LLVM link time optimization +// library. This is inteded to be used by linkers which are C-only in +// their implementation for performing LTO. +// +//===----------------------------------------------------------------------===// + +#ifndef __LTO_CAPI_H__ +#define __LTO_CAPI_H__ + +#ifdef __cplusplus +extern "C" { +#endif + + /// This provides a dummy type for pointers to the LTO object. + typedef void* llvm_lto_t; + + /// This provides a C-visible enumerator to manage status codes. + /// This should map exactly onto the C++ enumerator LTOStatus. + typedef enum llvm_lto_status { + LLVM_LTO_UNKNOWN, + LLVM_LTO_OPT_SUCCESS, + LLVM_LTO_READ_SUCCESS, + LLVM_LTO_READ_FAILURE, + LLVM_LTO_WRITE_FAILURE, + LLVM_LTO_NO_TARGET, + LLVM_LTO_NO_WORK, + LLVM_LTO_MODULE_MERGE_FAILURE, + LLVM_LTO_ASM_FAILURE, + + // Added C-specific error codes + LLVM_LTO_NULL_OBJECT + } llvm_lto_status_t; + + /// This provides C interface to initialize link time optimizer. This allows + /// linker to use dlopen() interface to dynamically load LinkTimeOptimizer. + /// extern "C" helps, because dlopen() interface uses name to find the symbol. + extern llvm_lto_t llvm_create_optimizer(void); + extern void llvm_destroy_optimizer(llvm_lto_t lto); + + extern llvm_lto_status_t llvm_read_object_file + (llvm_lto_t lto, const char* input_filename); + extern llvm_lto_status_t llvm_optimize_modules + (llvm_lto_t lto, const char* output_filename); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libclamav/c++/llvm/include/llvm-c/Target.h b/libclamav/c++/llvm/include/llvm-c/Target.h new file mode 100644 index 000000000..43388512e --- /dev/null +++ b/libclamav/c++/llvm/include/llvm-c/Target.h @@ -0,0 +1,173 @@ +/*===-- llvm-c/Target.h - Target Lib C Iface --------------------*- 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 libLLVMTarget.a, which *| +|* implements target information. *| +|* *| +|* Many exotic languages can interoperate with C code but have a harder time *| +|* with C++ due to name mangling. So in addition to C, this interface enables *| +|* tools written in such languages. *| +|* *| +\*===----------------------------------------------------------------------===*/ + +#ifndef LLVM_C_TARGET_H +#define LLVM_C_TARGET_H + +#include "llvm-c/Core.h" +#include "llvm/Config/config.h" + +#ifdef __cplusplus +extern "C" { +#endif + +enum { LLVMBigEndian, LLVMLittleEndian }; +typedef int LLVMByteOrdering; + +typedef struct LLVMOpaqueTargetData *LLVMTargetDataRef; +typedef struct LLVMStructLayout *LLVMStructLayoutRef; + +/* Declare all of the target-initialization functions that are available. */ +#define LLVM_TARGET(TargetName) void LLVMInitialize##TargetName##TargetInfo(); +#include "llvm/Config/Targets.def" + +#define LLVM_TARGET(TargetName) void LLVMInitialize##TargetName##Target(); +#include "llvm/Config/Targets.def" + +/** LLVMInitializeAllTargetInfos - The main program should call this function if + it wants access to all available targets that LLVM is configured to + support. */ +static inline void LLVMInitializeAllTargetInfos() { +#define LLVM_TARGET(TargetName) LLVMInitialize##TargetName##TargetInfo(); +#include "llvm/Config/Targets.def" +} + +/** LLVMInitializeAllTargets - The main program should call this function if it + wants to link in all available targets that LLVM is configured to + support. */ +static inline void LLVMInitializeAllTargets() { +#define LLVM_TARGET(TargetName) LLVMInitialize##TargetName##Target(); +#include "llvm/Config/Targets.def" +} + +/** LLVMInitializeNativeTarget - The main program should call this function to + initialize the native target corresponding to the host. This is useful + for JIT applications to ensure that the target gets linked in correctly. */ +static inline int LLVMInitializeNativeTarget() { + /* If we have a native target, initialize it to ensure it is linked in. */ +#ifdef LLVM_NATIVE_ARCH +#define DoInit2(TARG) \ + LLVMInitialize ## TARG ## Info (); \ + LLVMInitialize ## TARG () +#define DoInit(T) DoInit2(T) + DoInit(LLVM_NATIVE_ARCH); + return 0; +#undef DoInit +#undef DoInit2 +#else + return 1; +#endif +} + +/*===-- Target Data -------------------------------------------------------===*/ + +/** Creates target data from a target layout string. + See the constructor llvm::TargetData::TargetData. */ +LLVMTargetDataRef LLVMCreateTargetData(const char *StringRep); + +/** Adds target data information to a pass manager. This does not take ownership + of the target data. + See the method llvm::PassManagerBase::add. */ +void LLVMAddTargetData(LLVMTargetDataRef, LLVMPassManagerRef); + +/** Converts target data to a target layout string. The string must be disposed + with LLVMDisposeMessage. + See the constructor llvm::TargetData::TargetData. */ +char *LLVMCopyStringRepOfTargetData(LLVMTargetDataRef); + +/** Returns the byte order of a target, either LLVMBigEndian or + LLVMLittleEndian. + See the method llvm::TargetData::isLittleEndian. */ +LLVMByteOrdering LLVMByteOrder(LLVMTargetDataRef); + +/** Returns the pointer size in bytes for a target. + See the method llvm::TargetData::getPointerSize. */ +unsigned LLVMPointerSize(LLVMTargetDataRef); + +/** Returns the integer type that is the same size as a pointer on a target. + See the method llvm::TargetData::getIntPtrType. */ +LLVMTypeRef LLVMIntPtrType(LLVMTargetDataRef); + +/** Computes the size of a type in bytes for a target. + See the method llvm::TargetData::getTypeSizeInBits. */ +unsigned long long LLVMSizeOfTypeInBits(LLVMTargetDataRef, LLVMTypeRef); + +/** Computes the storage size of a type in bytes for a target. + See the method llvm::TargetData::getTypeStoreSize. */ +unsigned long long LLVMStoreSizeOfType(LLVMTargetDataRef, LLVMTypeRef); + +/** Computes the ABI size of a type in bytes for a target. + See the method llvm::TargetData::getTypeAllocSize. */ +unsigned long long LLVMABISizeOfType(LLVMTargetDataRef, LLVMTypeRef); + +/** Computes the ABI alignment of a type in bytes for a target. + See the method llvm::TargetData::getTypeABISize. */ +unsigned LLVMABIAlignmentOfType(LLVMTargetDataRef, LLVMTypeRef); + +/** Computes the call frame alignment of a type in bytes for a target. + See the method llvm::TargetData::getTypeABISize. */ +unsigned LLVMCallFrameAlignmentOfType(LLVMTargetDataRef, LLVMTypeRef); + +/** Computes the preferred alignment of a type in bytes for a target. + See the method llvm::TargetData::getTypeABISize. */ +unsigned LLVMPreferredAlignmentOfType(LLVMTargetDataRef, LLVMTypeRef); + +/** Computes the preferred alignment of a global variable in bytes for a target. + See the method llvm::TargetData::getPreferredAlignment. */ +unsigned LLVMPreferredAlignmentOfGlobal(LLVMTargetDataRef, + LLVMValueRef GlobalVar); + +/** Computes the structure element that contains the byte offset for a target. + See the method llvm::StructLayout::getElementContainingOffset. */ +unsigned LLVMElementAtOffset(LLVMTargetDataRef, LLVMTypeRef StructTy, + unsigned long long Offset); + +/** Computes the byte offset of the indexed struct element for a target. + See the method llvm::StructLayout::getElementContainingOffset. */ +unsigned long long LLVMOffsetOfElement(LLVMTargetDataRef, LLVMTypeRef StructTy, + unsigned Element); + +/** Struct layouts are speculatively cached. If a TargetDataRef is alive when + types are being refined and removed, this method must be called whenever a + struct type is removed to avoid a dangling pointer in this cache. + See the method llvm::TargetData::InvalidateStructLayoutInfo. */ +void LLVMInvalidateStructLayout(LLVMTargetDataRef, LLVMTypeRef StructTy); + +/** Deallocates a TargetData. + See the destructor llvm::TargetData::~TargetData. */ +void LLVMDisposeTargetData(LLVMTargetDataRef); + + +#ifdef __cplusplus +} + +namespace llvm { + class TargetData; + + inline TargetData *unwrap(LLVMTargetDataRef P) { + return reinterpret_cast(P); + } + + inline LLVMTargetDataRef wrap(const TargetData *P) { + return reinterpret_cast(const_cast(P)); + } +} + +#endif /* defined(__cplusplus) */ + +#endif diff --git a/libclamav/c++/llvm/include/llvm-c/Transforms/IPO.h b/libclamav/c++/llvm/include/llvm-c/Transforms/IPO.h new file mode 100644 index 000000000..0a94315f6 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm-c/Transforms/IPO.h @@ -0,0 +1,70 @@ +/*===-- IPO.h - Interprocedural Transformations 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 libLLVMIPO.a, which implements *| +|* various interprocedural transformations of the LLVM IR. *| +|* *| +\*===----------------------------------------------------------------------===*/ + +#ifndef LLVM_C_TRANSFORMS_IPO_H +#define LLVM_C_TRANSFORMS_IPO_H + +#include "llvm-c/Core.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** See llvm::createArgumentPromotionPass function. */ +void LLVMAddArgumentPromotionPass(LLVMPassManagerRef PM); + +/** See llvm::createConstantMergePass function. */ +void LLVMAddConstantMergePass(LLVMPassManagerRef PM); + +/** See llvm::createDeadArgEliminationPass function. */ +void LLVMAddDeadArgEliminationPass(LLVMPassManagerRef PM); + +/** See llvm::createDeadTypeEliminationPass function. */ +void LLVMAddDeadTypeEliminationPass(LLVMPassManagerRef PM); + +/** See llvm::createFunctionAttrsPass function. */ +void LLVMAddFunctionAttrsPass(LLVMPassManagerRef PM); + +/** See llvm::createFunctionInliningPass function. */ +void LLVMAddFunctionInliningPass(LLVMPassManagerRef PM); + +/** See llvm::createGlobalDCEPass function. */ +void LLVMAddGlobalDCEPass(LLVMPassManagerRef PM); + +/** See llvm::createGlobalOptimizerPass function. */ +void LLVMAddGlobalOptimizerPass(LLVMPassManagerRef PM); + +/** See llvm::createIPConstantPropagationPass function. */ +void LLVMAddIPConstantPropagationPass(LLVMPassManagerRef PM); + +/** See llvm::createLowerSetJmpPass function. */ +void LLVMAddLowerSetJmpPass(LLVMPassManagerRef PM); + +/** See llvm::createPruneEHPass function. */ +void LLVMAddPruneEHPass(LLVMPassManagerRef PM); + +// FIXME: Remove in LLVM 3.0. +void LLVMAddRaiseAllocationsPass(LLVMPassManagerRef PM); + +/** See llvm::createStripDeadPrototypesPass function. */ +void LLVMAddStripDeadPrototypesPass(LLVMPassManagerRef PM); + +/** See llvm::createStripSymbolsPass function. */ +void LLVMAddStripSymbolsPass(LLVMPassManagerRef PM); + +#ifdef __cplusplus +} +#endif /* defined(__cplusplus) */ + +#endif diff --git a/libclamav/c++/llvm/include/llvm-c/Transforms/Scalar.h b/libclamav/c++/llvm/include/llvm-c/Transforms/Scalar.h new file mode 100644 index 000000000..2c5a3714d --- /dev/null +++ b/libclamav/c++/llvm/include/llvm-c/Transforms/Scalar.h @@ -0,0 +1,98 @@ +/*===-- Scalar.h - Scalar Transformation Library 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 libLLVMScalarOpts.a, which *| +|* implements various scalar transformations of the LLVM IR. *| +|* *| +|* Many exotic languages can interoperate with C code but have a harder time *| +|* with C++ due to name mangling. So in addition to C, this interface enables *| +|* tools written in such languages. *| +|* *| +\*===----------------------------------------------------------------------===*/ + +#ifndef LLVM_C_TRANSFORMS_SCALAR_H +#define LLVM_C_TRANSFORMS_SCALAR_H + +#include "llvm-c/Core.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** See llvm::createAggressiveDCEPass function. */ +void LLVMAddAggressiveDCEPass(LLVMPassManagerRef PM); + +/** See llvm::createCFGSimplificationPass function. */ +void LLVMAddCFGSimplificationPass(LLVMPassManagerRef PM); + +/** See llvm::createDeadStoreEliminationPass function. */ +void LLVMAddDeadStoreEliminationPass(LLVMPassManagerRef PM); + +/** See llvm::createGVNPass function. */ +void LLVMAddGVNPass(LLVMPassManagerRef PM); + +/** See llvm::createIndVarSimplifyPass function. */ +void LLVMAddIndVarSimplifyPass(LLVMPassManagerRef PM); + +/** See llvm::createInstructionCombiningPass function. */ +void LLVMAddInstructionCombiningPass(LLVMPassManagerRef PM); + +/** See llvm::createJumpThreadingPass function. */ +void LLVMAddJumpThreadingPass(LLVMPassManagerRef PM); + +/** See llvm::createLICMPass function. */ +void LLVMAddLICMPass(LLVMPassManagerRef PM); + +/** See llvm::createLoopDeletionPass function. */ +void LLVMAddLoopDeletionPass(LLVMPassManagerRef PM); + +/** See llvm::createLoopIndexSplitPass function. */ +void LLVMAddLoopIndexSplitPass(LLVMPassManagerRef PM); + +/** See llvm::createLoopRotatePass function. */ +void LLVMAddLoopRotatePass(LLVMPassManagerRef PM); + +/** See llvm::createLoopUnrollPass function. */ +void LLVMAddLoopUnrollPass(LLVMPassManagerRef PM); + +/** See llvm::createLoopUnswitchPass function. */ +void LLVMAddLoopUnswitchPass(LLVMPassManagerRef PM); + +/** See llvm::createMemCpyOptPass function. */ +void LLVMAddMemCpyOptPass(LLVMPassManagerRef PM); + +/** See llvm::createPromoteMemoryToRegisterPass function. */ +void LLVMAddPromoteMemoryToRegisterPass(LLVMPassManagerRef PM); + +/** See llvm::createReassociatePass function. */ +void LLVMAddReassociatePass(LLVMPassManagerRef PM); + +/** See llvm::createSCCPPass function. */ +void LLVMAddSCCPPass(LLVMPassManagerRef PM); + +/** See llvm::createScalarReplAggregatesPass function. */ +void LLVMAddScalarReplAggregatesPass(LLVMPassManagerRef PM); + +/** See llvm::createSimplifyLibCallsPass function. */ +void LLVMAddSimplifyLibCallsPass(LLVMPassManagerRef PM); + +/** See llvm::createTailCallEliminationPass function. */ +void LLVMAddTailCallEliminationPass(LLVMPassManagerRef PM); + +/** See llvm::createConstantPropagationPass function. */ +void LLVMAddConstantPropagationPass(LLVMPassManagerRef PM); + +/** See llvm::demotePromoteMemoryToRegisterPass function. */ +void LLVMAddDemoteMemoryToRegisterPass(LLVMPassManagerRef PM); + +#ifdef __cplusplus +} +#endif /* defined(__cplusplus) */ + +#endif diff --git a/libclamav/c++/llvm/include/llvm-c/lto.h b/libclamav/c++/llvm/include/llvm-c/lto.h new file mode 100644 index 000000000..7cafcb29f --- /dev/null +++ b/libclamav/c++/llvm/include/llvm-c/lto.h @@ -0,0 +1,258 @@ +/*===-- llvm-c/lto.h - LTO Public 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 provides public interface to an abstract link time optimization*| +|* library. LLVM provides an implementation of this interface for use with *| +|* llvm bitcode files. *| +|* *| +\*===----------------------------------------------------------------------===*/ + +#ifndef LTO_H +#define LTO_H 1 + +#include +#include + +#define LTO_API_VERSION 3 + +typedef enum { + LTO_SYMBOL_ALIGNMENT_MASK = 0x0000001F, /* log2 of alignment */ + LTO_SYMBOL_PERMISSIONS_MASK = 0x000000E0, + LTO_SYMBOL_PERMISSIONS_CODE = 0x000000A0, + LTO_SYMBOL_PERMISSIONS_DATA = 0x000000C0, + LTO_SYMBOL_PERMISSIONS_RODATA = 0x00000080, + LTO_SYMBOL_DEFINITION_MASK = 0x00000700, + LTO_SYMBOL_DEFINITION_REGULAR = 0x00000100, + LTO_SYMBOL_DEFINITION_TENTATIVE = 0x00000200, + LTO_SYMBOL_DEFINITION_WEAK = 0x00000300, + LTO_SYMBOL_DEFINITION_UNDEFINED = 0x00000400, + LTO_SYMBOL_DEFINITION_WEAKUNDEF = 0x00000500, + LTO_SYMBOL_SCOPE_MASK = 0x00003800, + LTO_SYMBOL_SCOPE_INTERNAL = 0x00000800, + LTO_SYMBOL_SCOPE_HIDDEN = 0x00001000, + LTO_SYMBOL_SCOPE_PROTECTED = 0x00002000, + LTO_SYMBOL_SCOPE_DEFAULT = 0x00001800 +} lto_symbol_attributes; + +typedef enum { + LTO_DEBUG_MODEL_NONE = 0, + LTO_DEBUG_MODEL_DWARF = 1 +} lto_debug_model; + +typedef enum { + LTO_CODEGEN_PIC_MODEL_STATIC = 0, + LTO_CODEGEN_PIC_MODEL_DYNAMIC = 1, + LTO_CODEGEN_PIC_MODEL_DYNAMIC_NO_PIC = 2 +} lto_codegen_model; + + +/** opaque reference to a loaded object module */ +typedef struct LTOModule* lto_module_t; + +/** opaque reference to a code generator */ +typedef struct LTOCodeGenerator* lto_code_gen_t; + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Returns a printable string. + */ +extern const char* +lto_get_version(void); + + +/** + * Returns the last error string or NULL if last operation was sucessful. + */ +extern const char* +lto_get_error_message(void); + +/** + * Checks if a file is a loadable object file. + */ +extern bool +lto_module_is_object_file(const char* path); + + +/** + * Checks if a file is a loadable object compiled for requested target. + */ +extern bool +lto_module_is_object_file_for_target(const char* path, + const char* target_triple_prefix); + + +/** + * Checks if a buffer is a loadable object file. + */ +extern bool +lto_module_is_object_file_in_memory(const void* mem, size_t length); + + +/** + * Checks if a buffer is a loadable object compiled for requested target. + */ +extern bool +lto_module_is_object_file_in_memory_for_target(const void* mem, size_t length, + const char* target_triple_prefix); + + +/** + * Loads an object file from disk. + * Returns NULL on error (check lto_get_error_message() for details). + */ +extern lto_module_t +lto_module_create(const char* path); + + +/** + * Loads an object file from memory. + * Returns NULL on error (check lto_get_error_message() for details). + */ +extern lto_module_t +lto_module_create_from_memory(const void* mem, size_t length); + + +/** + * Frees all memory internally allocated by the module. + * Upon return the lto_module_t is no longer valid. + */ +extern void +lto_module_dispose(lto_module_t mod); + + +/** + * Returns triple string which the object module was compiled under. + */ +extern const char* +lto_module_get_target_triple(lto_module_t mod); + + +/** + * Returns the number of symbols in the object module. + */ +extern unsigned int +lto_module_get_num_symbols(lto_module_t mod); + + +/** + * Returns the name of the ith symbol in the object module. + */ +extern const char* +lto_module_get_symbol_name(lto_module_t mod, unsigned int index); + + +/** + * Returns the attributes of the ith symbol in the object module. + */ +extern lto_symbol_attributes +lto_module_get_symbol_attribute(lto_module_t mod, unsigned int index); + + +/** + * Instantiates a code generator. + * Returns NULL on error (check lto_get_error_message() for details). + */ +extern lto_code_gen_t +lto_codegen_create(void); + + +/** + * Frees all code generator and all memory it internally allocated. + * Upon return the lto_code_gen_t is no longer valid. + */ +extern void +lto_codegen_dispose(lto_code_gen_t); + + + +/** + * Add an object module to the set of modules for which code will be generated. + * Returns true on error (check lto_get_error_message() for details). + */ +extern bool +lto_codegen_add_module(lto_code_gen_t cg, lto_module_t mod); + + + +/** + * Sets if debug info should be generated. + * Returns true on error (check lto_get_error_message() for details). + */ +extern bool +lto_codegen_set_debug_model(lto_code_gen_t cg, lto_debug_model); + + +/** + * Sets which PIC code model to generated. + * Returns true on error (check lto_get_error_message() for details). + */ +extern bool +lto_codegen_set_pic_model(lto_code_gen_t cg, lto_codegen_model); + + +/** + * Sets the location of the "gcc" to run. If not set, libLTO will search for + * "gcc" on the path. + */ +extern void +lto_codegen_set_gcc_path(lto_code_gen_t cg, const char* path); + + +/** + * Sets the location of the assembler tool to run. If not set, libLTO + * will use gcc to invoke the assembler. + */ +extern void +lto_codegen_set_assembler_path(lto_code_gen_t cg, const char* path); + + +/** + * Adds to a list of all global symbols that must exist in the final + * generated code. If a function is not listed, it might be + * inlined into every usage and optimized away. + */ +extern void +lto_codegen_add_must_preserve_symbol(lto_code_gen_t cg, const char* symbol); + + +/** + * Writes a new object file at the specified path that contains the + * merged contents of all modules added so far. + * Returns true on error (check lto_get_error_message() for details). + */ +extern bool +lto_codegen_write_merged_modules(lto_code_gen_t cg, const char* path); + + +/** + * Generates code for all added modules into one native object file. + * On sucess returns a pointer to a generated mach-o/ELF buffer and + * length set to the buffer size. The buffer is owned by the + * lto_code_gen_t and will be freed when lto_codegen_dispose() + * is called, or lto_codegen_compile() is called again. + * On failure, returns NULL (check lto_get_error_message() for details). + */ +extern const void* +lto_codegen_compile(lto_code_gen_t cg, size_t* length); + + +/** + * Sets options to help debug codegen bugs. + */ +extern void +lto_codegen_debug_options(lto_code_gen_t cg, const char *); +#ifdef __cplusplus +} +#endif + + +#endif diff --git a/libclamav/c++/llvm/include/llvm/ADT/APFloat.h b/libclamav/c++/llvm/include/llvm/ADT/APFloat.h new file mode 100644 index 000000000..30d998fc3 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/ADT/APFloat.h @@ -0,0 +1,374 @@ +//== llvm/Support/APFloat.h - Arbitrary Precision Floating Point -*- C++ -*-==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares a class to represent arbitrary precision floating +// point values and provide a variety of arithmetic operations on them. +// +//===----------------------------------------------------------------------===// + +/* A self-contained host- and target-independent arbitrary-precision + floating-point software implementation. It uses bignum integer + arithmetic as provided by static functions in the APInt class. + The library will work with bignum integers whose parts are any + unsigned type at least 16 bits wide, but 64 bits is recommended. + + Written for clarity rather than speed, in particular with a view + to use in the front-end of a cross compiler so that target + arithmetic can be correctly performed on the host. Performance + should nonetheless be reasonable, particularly for its intended + use. It may be useful as a base implementation for a run-time + library during development of a faster target-specific one. + + All 5 rounding modes in the IEEE-754R draft are handled correctly + for all implemented operations. Currently implemented operations + are add, subtract, multiply, divide, fused-multiply-add, + conversion-to-float, conversion-to-integer and + conversion-from-integer. New rounding modes (e.g. away from zero) + can be added with three or four lines of code. + + Four formats are built-in: IEEE single precision, double + precision, quadruple precision, and x87 80-bit extended double + (when operating with full extended precision). Adding a new + format that obeys IEEE semantics only requires adding two lines of + code: a declaration and definition of the format. + + All operations return the status of that operation as an exception + bit-mask, so multiple operations can be done consecutively with + their results or-ed together. The returned status can be useful + for compiler diagnostics; e.g., inexact, underflow and overflow + can be easily diagnosed on constant folding, and compiler + optimizers can determine what exceptions would be raised by + folding operations and optimize, or perhaps not optimize, + accordingly. + + At present, underflow tininess is detected after rounding; it + should be straight forward to add support for the before-rounding + case too. + + The library reads hexadecimal floating point numbers as per C99, + and correctly rounds if necessary according to the specified + rounding mode. Syntax is required to have been validated by the + caller. It also converts floating point numbers to hexadecimal + text as per the C99 %a and %A conversions. The output precision + (or alternatively the natural minimal precision) can be specified; + if the requested precision is less than the natural precision the + output is correctly rounded for the specified rounding mode. + + It also reads decimal floating point numbers and correctly rounds + according to the specified rounding mode. + + Conversion to decimal text is not currently implemented. + + Non-zero finite numbers are represented internally as a sign bit, + a 16-bit signed exponent, and the significand as an array of + integer parts. After normalization of a number of precision P the + exponent is within the range of the format, and if the number is + not denormal the P-th bit of the significand is set as an explicit + integer bit. For denormals the most significant bit is shifted + right so that the exponent is maintained at the format's minimum, + so that the smallest denormal has just the least significant bit + of the significand set. The sign of zeroes and infinities is + significant; the exponent and significand of such numbers is not + stored, but has a known implicit (deterministic) value: 0 for the + significands, 0 for zero exponent, all 1 bits for infinity + exponent. For NaNs the sign and significand are deterministic, + although not really meaningful, and preserved in non-conversion + operations. The exponent is implicitly all 1 bits. + + TODO + ==== + + Some features that may or may not be worth adding: + + Binary to decimal conversion (hard). + + Optional ability to detect underflow tininess before rounding. + + New formats: x87 in single and double precision mode (IEEE apart + from extended exponent range) (hard). + + New operations: sqrt, IEEE remainder, C90 fmod, nextafter, + nexttoward. +*/ + +#ifndef LLVM_FLOAT_H +#define LLVM_FLOAT_H + +// APInt contains static functions implementing bignum arithmetic. +#include "llvm/ADT/APInt.h" + +namespace llvm { + + /* Exponents are stored as signed numbers. */ + typedef signed short exponent_t; + + struct fltSemantics; + class StringRef; + + /* When bits of a floating point number are truncated, this enum is + used to indicate what fraction of the LSB those bits represented. + It essentially combines the roles of guard and sticky bits. */ + enum lostFraction { // Example of truncated bits: + lfExactlyZero, // 000000 + lfLessThanHalf, // 0xxxxx x's not all zero + lfExactlyHalf, // 100000 + lfMoreThanHalf // 1xxxxx x's not all zero + }; + + class APFloat { + public: + + /* We support the following floating point semantics. */ + static const fltSemantics IEEEhalf; + static const fltSemantics IEEEsingle; + static const fltSemantics IEEEdouble; + static const fltSemantics IEEEquad; + static const fltSemantics PPCDoubleDouble; + static const fltSemantics x87DoubleExtended; + /* And this pseudo, used to construct APFloats that cannot + conflict with anything real. */ + static const fltSemantics Bogus; + + static unsigned int semanticsPrecision(const fltSemantics &); + + /* Floating point numbers have a four-state comparison relation. */ + enum cmpResult { + cmpLessThan, + cmpEqual, + cmpGreaterThan, + cmpUnordered + }; + + /* IEEE-754R gives five rounding modes. */ + enum roundingMode { + rmNearestTiesToEven, + rmTowardPositive, + rmTowardNegative, + rmTowardZero, + rmNearestTiesToAway + }; + + // Operation status. opUnderflow or opOverflow are always returned + // or-ed with opInexact. + enum opStatus { + opOK = 0x00, + opInvalidOp = 0x01, + opDivByZero = 0x02, + opOverflow = 0x04, + opUnderflow = 0x08, + opInexact = 0x10 + }; + + // Category of internally-represented number. + enum fltCategory { + fcInfinity, + fcNaN, + fcNormal, + fcZero + }; + + // Constructors. + APFloat(const fltSemantics &); // Default construct to 0.0 + APFloat(const fltSemantics &, const StringRef &); + APFloat(const fltSemantics &, integerPart); + APFloat(const fltSemantics &, fltCategory, bool negative, unsigned type=0); + explicit APFloat(double d); + explicit APFloat(float f); + explicit APFloat(const APInt &, bool isIEEE = false); + APFloat(const APFloat &); + ~APFloat(); + + // Convenience "constructors" + static APFloat getZero(const fltSemantics &Sem, bool Negative = false) { + return APFloat(Sem, fcZero, Negative); + } + static APFloat getInf(const fltSemantics &Sem, bool Negative = false) { + return APFloat(Sem, fcInfinity, Negative); + } + /// getNaN - Factory for QNaN values. + /// + /// \param Negative - True iff the NaN generated should be negative. + /// \param type - The unspecified fill bits for creating the NaN, 0 by + /// default. The value is truncated as necessary. + static APFloat getNaN(const fltSemantics &Sem, bool Negative = false, + unsigned type = 0) { + return APFloat(Sem, fcNaN, Negative, type); + } + + /// Profile - Used to insert APFloat objects, or objects that contain + /// APFloat objects, into FoldingSets. + void Profile(FoldingSetNodeID& NID) const; + + /// @brief Used by the Bitcode serializer to emit APInts to Bitcode. + void Emit(Serializer& S) const; + + /// @brief Used by the Bitcode deserializer to deserialize APInts. + static APFloat ReadVal(Deserializer& D); + + /* Arithmetic. */ + opStatus add(const APFloat &, roundingMode); + opStatus subtract(const APFloat &, roundingMode); + opStatus multiply(const APFloat &, roundingMode); + opStatus divide(const APFloat &, roundingMode); + /* IEEE remainder. */ + opStatus remainder(const APFloat &); + /* C fmod, or llvm frem. */ + opStatus mod(const APFloat &, roundingMode); + opStatus fusedMultiplyAdd(const APFloat &, const APFloat &, roundingMode); + + /* Sign operations. */ + void changeSign(); + void clearSign(); + void copySign(const APFloat &); + + /* Conversions. */ + opStatus convert(const fltSemantics &, roundingMode, bool *); + opStatus convertToInteger(integerPart *, unsigned int, bool, + roundingMode, bool *) const; + opStatus convertFromAPInt(const APInt &, + bool, roundingMode); + opStatus convertFromSignExtendedInteger(const integerPart *, unsigned int, + bool, roundingMode); + opStatus convertFromZeroExtendedInteger(const integerPart *, unsigned int, + bool, roundingMode); + opStatus convertFromString(const StringRef&, roundingMode); + APInt bitcastToAPInt() const; + double convertToDouble() const; + float convertToFloat() const; + + /* The definition of equality is not straightforward for floating point, + so we won't use operator==. Use one of the following, or write + whatever it is you really mean. */ + // bool operator==(const APFloat &) const; // DO NOT IMPLEMENT + + /* IEEE comparison with another floating point number (NaNs + compare unordered, 0==-0). */ + cmpResult compare(const APFloat &) const; + + /* Bitwise comparison for equality (QNaNs compare equal, 0!=-0). */ + bool bitwiseIsEqual(const APFloat &) const; + + /* Write out a hexadecimal representation of the floating point + value to DST, which must be of sufficient size, in the C99 form + [-]0xh.hhhhp[+-]d. Return the number of characters written, + excluding the terminating NUL. */ + unsigned int convertToHexString(char *dst, unsigned int hexDigits, + bool upperCase, roundingMode) const; + + /* Simple queries. */ + fltCategory getCategory() const { return category; } + const fltSemantics &getSemantics() const { return *semantics; } + bool isZero() const { return category == fcZero; } + bool isNonZero() const { return category != fcZero; } + bool isNaN() const { return category == fcNaN; } + bool isInfinity() const { return category == fcInfinity; } + bool isNegative() const { return sign; } + bool isPosZero() const { return isZero() && !isNegative(); } + bool isNegZero() const { return isZero() && isNegative(); } + + APFloat& operator=(const APFloat &); + + /* Return an arbitrary integer value usable for hashing. */ + uint32_t getHashValue() const; + + private: + + /* Trivial queries. */ + integerPart *significandParts(); + const integerPart *significandParts() const; + unsigned int partCount() const; + + /* Significand operations. */ + integerPart addSignificand(const APFloat &); + integerPart subtractSignificand(const APFloat &, integerPart); + lostFraction addOrSubtractSignificand(const APFloat &, bool subtract); + lostFraction multiplySignificand(const APFloat &, const APFloat *); + lostFraction divideSignificand(const APFloat &); + void incrementSignificand(); + void initialize(const fltSemantics *); + void shiftSignificandLeft(unsigned int); + lostFraction shiftSignificandRight(unsigned int); + unsigned int significandLSB() const; + unsigned int significandMSB() const; + void zeroSignificand(); + + /* Arithmetic on special values. */ + opStatus addOrSubtractSpecials(const APFloat &, bool subtract); + opStatus divideSpecials(const APFloat &); + opStatus multiplySpecials(const APFloat &); + opStatus modSpecials(const APFloat &); + + /* Miscellany. */ + void makeNaN(unsigned = 0); + opStatus normalize(roundingMode, lostFraction); + opStatus addOrSubtract(const APFloat &, roundingMode, bool subtract); + cmpResult compareAbsoluteValue(const APFloat &) const; + opStatus handleOverflow(roundingMode); + bool roundAwayFromZero(roundingMode, lostFraction, unsigned int) const; + opStatus convertToSignExtendedInteger(integerPart *, unsigned int, bool, + roundingMode, bool *) const; + opStatus convertFromUnsignedParts(const integerPart *, unsigned int, + roundingMode); + opStatus convertFromHexadecimalString(const StringRef&, roundingMode); + opStatus convertFromDecimalString (const StringRef&, roundingMode); + char *convertNormalToHexString(char *, unsigned int, bool, + roundingMode) const; + opStatus roundSignificandWithExponent(const integerPart *, unsigned int, + int, roundingMode); + + APInt convertHalfAPFloatToAPInt() const; + APInt convertFloatAPFloatToAPInt() const; + APInt convertDoubleAPFloatToAPInt() const; + APInt convertQuadrupleAPFloatToAPInt() const; + APInt convertF80LongDoubleAPFloatToAPInt() const; + APInt convertPPCDoubleDoubleAPFloatToAPInt() const; + void initFromAPInt(const APInt& api, bool isIEEE = false); + void initFromHalfAPInt(const APInt& api); + void initFromFloatAPInt(const APInt& api); + void initFromDoubleAPInt(const APInt& api); + void initFromQuadrupleAPInt(const APInt &api); + void initFromF80LongDoubleAPInt(const APInt& api); + void initFromPPCDoubleDoubleAPInt(const APInt& api); + + void assign(const APFloat &); + void copySignificand(const APFloat &); + void freeSignificand(); + + /* What kind of semantics does this value obey? */ + const fltSemantics *semantics; + + /* Significand - the fraction with an explicit integer bit. Must be + at least one bit wider than the target precision. */ + union Significand + { + integerPart part; + integerPart *parts; + } significand; + + /* The exponent - a signed number. */ + exponent_t exponent; + + /* What kind of floating point number this is. */ + /* Only 2 bits are required, but VisualStudio incorrectly sign extends + it. Using the extra bit keeps it from failing under VisualStudio */ + fltCategory category: 3; + + /* The sign bit of this number. */ + unsigned int sign: 1; + + /* For PPCDoubleDouble, we have a second exponent and sign (the second + significand is appended to the first one, although it would be wrong to + regard these as a single number for arithmetic purposes). These fields + are not meaningful for any other type. */ + exponent_t exponent2 : 11; + unsigned int sign2: 1; + }; +} /* namespace llvm */ + +#endif /* LLVM_FLOAT_H */ diff --git a/libclamav/c++/llvm/include/llvm/ADT/APInt.h b/libclamav/c++/llvm/include/llvm/ADT/APInt.h new file mode 100644 index 000000000..88aa9956d --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/ADT/APInt.h @@ -0,0 +1,1616 @@ +//===-- llvm/ADT/APInt.h - For Arbitrary Precision Integer -----*- 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 a class to represent arbitrary precision integral +// constant values and operations on them. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_APINT_H +#define LLVM_APINT_H + +#include "llvm/Support/MathExtras.h" +#include +#include +#include +#include + +namespace llvm { + class Serializer; + class Deserializer; + class FoldingSetNodeID; + class raw_ostream; + class StringRef; + + template + class SmallVectorImpl; + + // An unsigned host type used as a single part of a multi-part + // bignum. + typedef uint64_t integerPart; + + const unsigned int host_char_bit = 8; + const unsigned int integerPartWidth = host_char_bit * + static_cast(sizeof(integerPart)); + +//===----------------------------------------------------------------------===// +// APInt Class +//===----------------------------------------------------------------------===// + +/// APInt - This class represents arbitrary precision constant integral values. +/// It is a functional replacement for common case unsigned integer type like +/// "unsigned", "unsigned long" or "uint64_t", but also allows non-byte-width +/// integer sizes and large integer value types such as 3-bits, 15-bits, or more +/// than 64-bits of precision. APInt provides a variety of arithmetic operators +/// and methods to manipulate integer values of any bit-width. It supports both +/// the typical integer arithmetic and comparison operations as well as bitwise +/// manipulation. +/// +/// The class has several invariants worth noting: +/// * All bit, byte, and word positions are zero-based. +/// * Once the bit width is set, it doesn't change except by the Truncate, +/// SignExtend, or ZeroExtend operations. +/// * All binary operators must be on APInt instances of the same bit width. +/// Attempting to use these operators on instances with different bit +/// widths will yield an assertion. +/// * The value is stored canonically as an unsigned value. For operations +/// where it makes a difference, there are both signed and unsigned variants +/// of the operation. For example, sdiv and udiv. However, because the bit +/// widths must be the same, operations such as Mul and Add produce the same +/// results regardless of whether the values are interpreted as signed or +/// not. +/// * In general, the class tries to follow the style of computation that LLVM +/// uses in its IR. This simplifies its use for LLVM. +/// +/// @brief Class for arbitrary precision integers. +class APInt { + unsigned BitWidth; ///< The number of bits in this APInt. + + /// This union is used to store the integer value. When the + /// integer bit-width <= 64, it uses VAL, otherwise it uses pVal. + union { + uint64_t VAL; ///< Used to store the <= 64 bits integer value. + uint64_t *pVal; ///< Used to store the >64 bits integer value. + }; + + /// This enum is used to hold the constants we needed for APInt. + enum { + /// Bits in a word + APINT_BITS_PER_WORD = static_cast(sizeof(uint64_t)) * + CHAR_BIT, + /// Byte size of a word + APINT_WORD_SIZE = static_cast(sizeof(uint64_t)) + }; + + /// This constructor is used only internally for speed of construction of + /// temporaries. It is unsafe for general use so it is not public. + /// @brief Fast internal constructor + APInt(uint64_t* val, unsigned bits) : BitWidth(bits), pVal(val) { } + + /// @returns true if the number of bits <= 64, false otherwise. + /// @brief Determine if this APInt just has one word to store value. + bool isSingleWord() const { + return BitWidth <= APINT_BITS_PER_WORD; + } + + /// @returns the word position for the specified bit position. + /// @brief Determine which word a bit is in. + static unsigned whichWord(unsigned bitPosition) { + return bitPosition / APINT_BITS_PER_WORD; + } + + /// @returns the bit position in a word for the specified bit position + /// in the APInt. + /// @brief Determine which bit in a word a bit is in. + static unsigned whichBit(unsigned bitPosition) { + return bitPosition % APINT_BITS_PER_WORD; + } + + /// This method generates and returns a uint64_t (word) mask for a single + /// bit at a specific bit position. This is used to mask the bit in the + /// corresponding word. + /// @returns a uint64_t with only bit at "whichBit(bitPosition)" set + /// @brief Get a single bit mask. + static uint64_t maskBit(unsigned bitPosition) { + return 1ULL << whichBit(bitPosition); + } + + /// This method is used internally to clear the to "N" bits in the high order + /// word that are not used by the APInt. This is needed after the most + /// significant word is assigned a value to ensure that those bits are + /// zero'd out. + /// @brief Clear unused high order bits + APInt& clearUnusedBits() { + // Compute how many bits are used in the final word + unsigned wordBits = BitWidth % APINT_BITS_PER_WORD; + if (wordBits == 0) + // If all bits are used, we want to leave the value alone. This also + // avoids the undefined behavior of >> when the shift is the same size as + // the word size (64). + return *this; + + // Mask out the high bits. + uint64_t mask = ~uint64_t(0ULL) >> (APINT_BITS_PER_WORD - wordBits); + if (isSingleWord()) + VAL &= mask; + else + pVal[getNumWords() - 1] &= mask; + return *this; + } + + /// @returns the corresponding word for the specified bit position. + /// @brief Get the word corresponding to a bit position + uint64_t getWord(unsigned bitPosition) const { + return isSingleWord() ? VAL : pVal[whichWord(bitPosition)]; + } + + /// This is used by the constructors that take string arguments. + /// @brief Convert a char array into an APInt + void fromString(unsigned numBits, const StringRef &str, uint8_t radix); + + /// This is used by the toString method to divide by the radix. It simply + /// provides a more convenient form of divide for internal use since KnuthDiv + /// has specific constraints on its inputs. If those constraints are not met + /// then it provides a simpler form of divide. + /// @brief An internal division function for dividing APInts. + static void divide(const APInt LHS, unsigned lhsWords, + const APInt &RHS, unsigned rhsWords, + APInt *Quotient, APInt *Remainder); + + /// out-of-line slow case for inline constructor + void initSlowCase(unsigned numBits, uint64_t val, bool isSigned); + + /// out-of-line slow case for inline copy constructor + void initSlowCase(const APInt& that); + + /// out-of-line slow case for shl + APInt shlSlowCase(unsigned shiftAmt) const; + + /// out-of-line slow case for operator& + APInt AndSlowCase(const APInt& RHS) const; + + /// out-of-line slow case for operator| + APInt OrSlowCase(const APInt& RHS) const; + + /// out-of-line slow case for operator^ + APInt XorSlowCase(const APInt& RHS) const; + + /// out-of-line slow case for operator= + APInt& AssignSlowCase(const APInt& RHS); + + /// out-of-line slow case for operator== + bool EqualSlowCase(const APInt& RHS) const; + + /// out-of-line slow case for operator== + bool EqualSlowCase(uint64_t Val) const; + + /// out-of-line slow case for countLeadingZeros + unsigned countLeadingZerosSlowCase() const; + + /// out-of-line slow case for countTrailingOnes + unsigned countTrailingOnesSlowCase() const; + + /// out-of-line slow case for countPopulation + unsigned countPopulationSlowCase() const; + +public: + /// @name Constructors + /// @{ + /// If isSigned is true then val is treated as if it were a signed value + /// (i.e. as an int64_t) and the appropriate sign extension to the bit width + /// will be done. Otherwise, no sign extension occurs (high order bits beyond + /// the range of val are zero filled). + /// @param numBits the bit width of the constructed APInt + /// @param val the initial value of the APInt + /// @param isSigned how to treat signedness of val + /// @brief Create a new APInt of numBits width, initialized as val. + APInt(unsigned numBits, uint64_t val, bool isSigned = false) + : BitWidth(numBits), VAL(0) { + assert(BitWidth && "bitwidth too small"); + if (isSingleWord()) + VAL = val; + else + initSlowCase(numBits, val, isSigned); + clearUnusedBits(); + } + + /// Note that numWords can be smaller or larger than the corresponding bit + /// width but any extraneous bits will be dropped. + /// @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 + /// @brief Construct an APInt of numBits width, initialized as bigVal[]. + APInt(unsigned numBits, unsigned numWords, const uint64_t bigVal[]); + + /// This constructor interprets the string \arg str in the given radix. 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 + /// are 2, 8, 10 and 16. It is an error for the value implied by the string to + /// require more bits than numBits. + /// + /// @param numBits the bit width of the constructed APInt + /// @param str the string to be interpreted + /// @param radix the radix to use for the conversion + /// @brief Construct an APInt from a string representation. + APInt(unsigned numBits, const StringRef &str, uint8_t radix); + + /// Simply makes *this a copy of that. + /// @brief Copy Constructor. + APInt(const APInt& that) + : BitWidth(that.BitWidth), VAL(0) { + assert(BitWidth && "bitwidth too small"); + if (isSingleWord()) + VAL = that.VAL; + else + initSlowCase(that); + } + + /// @brief Destructor. + ~APInt() { + if (!isSingleWord()) + delete [] pVal; + } + + /// Default constructor that creates an uninitialized APInt. This is useful + /// for object deserialization (pair this with the static method Read). + explicit APInt() : BitWidth(1) {} + + /// Profile - Used to insert APInt objects, or objects that contain APInt + /// objects, into FoldingSets. + void Profile(FoldingSetNodeID& id) const; + + /// @brief Used by the Bitcode serializer to emit APInts to Bitcode. + void Emit(Serializer& S) const; + + /// @brief Used by the Bitcode deserializer to deserialize APInts. + void Read(Deserializer& D); + + /// @} + /// @name Value Tests + /// @{ + /// This tests the high bit of this APInt to determine if it is set. + /// @returns true if this APInt is negative, false otherwise + /// @brief Determine sign of this APInt. + bool isNegative() const { + return (*this)[BitWidth - 1]; + } + + /// This tests the high bit of the APInt to determine if it is unset. + /// @brief Determine if this APInt Value is non-negative (>= 0) + bool isNonNegative() const { + return !isNegative(); + } + + /// This tests if the value of this APInt is positive (> 0). Note + /// that 0 is not a positive value. + /// @returns true if this APInt is positive. + /// @brief Determine if this APInt Value is positive. + bool isStrictlyPositive() const { + return isNonNegative() && (*this) != 0; + } + + /// This checks to see if the value has all bits of the APInt are set or not. + /// @brief Determine if all bits are set + bool isAllOnesValue() const { + return countPopulation() == BitWidth; + } + + /// This checks to see if the value of this APInt is the maximum unsigned + /// value for the APInt's bit width. + /// @brief Determine if this is the largest unsigned value. + bool isMaxValue() const { + return countPopulation() == BitWidth; + } + + /// This checks to see if the value of this APInt is the maximum signed + /// value for the APInt's bit width. + /// @brief Determine if this is the largest signed value. + bool isMaxSignedValue() const { + return BitWidth == 1 ? VAL == 0 : + !isNegative() && countPopulation() == BitWidth - 1; + } + + /// This checks to see if the value of this APInt is the minimum unsigned + /// value for the APInt's bit width. + /// @brief Determine if this is the smallest unsigned value. + bool isMinValue() const { + return countPopulation() == 0; + } + + /// This checks to see if the value of this APInt is the minimum signed + /// value for the APInt's bit width. + /// @brief Determine if this is the smallest signed value. + bool isMinSignedValue() const { + return BitWidth == 1 ? VAL == 1 : + isNegative() && countPopulation() == 1; + } + + /// @brief Check if this APInt has an N-bits unsigned integer value. + bool isIntN(unsigned N) const { + assert(N && "N == 0 ???"); + if (N >= getBitWidth()) + return true; + + if (isSingleWord()) + return VAL == (VAL & (~0ULL >> (64 - N))); + APInt Tmp(N, getNumWords(), pVal); + Tmp.zext(getBitWidth()); + return Tmp == (*this); + } + + /// @brief Check if this APInt has an N-bits signed integer value. + bool isSignedIntN(unsigned N) const { + assert(N && "N == 0 ???"); + return getMinSignedBits() <= N; + } + + /// @returns true if the argument APInt value is a power of two > 0. + bool isPowerOf2() const; + + /// isSignBit - Return true if this is the value returned by getSignBit. + bool isSignBit() const { return isMinSignedValue(); } + + /// This converts the APInt to a boolean value as a test against zero. + /// @brief Boolean conversion function. + bool getBoolValue() const { + return *this != 0; + } + + /// getLimitedValue - If this value is smaller than the specified limit, + /// return it, otherwise return the limit value. This causes the value + /// to saturate to the limit. + uint64_t getLimitedValue(uint64_t Limit = ~0ULL) const { + return (getActiveBits() > 64 || getZExtValue() > Limit) ? + Limit : getZExtValue(); + } + + /// @} + /// @name Value Generators + /// @{ + /// @brief Gets maximum unsigned value of APInt for specific bit width. + static APInt getMaxValue(unsigned numBits) { + return APInt(numBits, 0).set(); + } + + /// @brief Gets maximum signed value of APInt for a specific bit width. + static APInt getSignedMaxValue(unsigned numBits) { + return APInt(numBits, 0).set().clear(numBits - 1); + } + + /// @brief Gets minimum unsigned value of APInt for a specific bit width. + static APInt getMinValue(unsigned numBits) { + return APInt(numBits, 0); + } + + /// @brief Gets minimum signed value of APInt for a specific bit width. + static APInt getSignedMinValue(unsigned numBits) { + return APInt(numBits, 0).set(numBits - 1); + } + + /// getSignBit - This is just a wrapper function of getSignedMinValue(), and + /// it helps code readability when we want to get a SignBit. + /// @brief Get the SignBit for a specific bit width. + static APInt getSignBit(unsigned BitWidth) { + return getSignedMinValue(BitWidth); + } + + /// @returns the all-ones value for an APInt of the specified bit-width. + /// @brief Get the all-ones value. + static APInt getAllOnesValue(unsigned numBits) { + return APInt(numBits, 0).set(); + } + + /// @returns the '0' value for an APInt of the specified bit-width. + /// @brief Get the '0' value. + static APInt getNullValue(unsigned numBits) { + return APInt(numBits, 0); + } + + /// Get an APInt with the same BitWidth as this APInt, just zero mask + /// the low bits and right shift to the least significant bit. + /// @returns the high "numBits" bits of this APInt. + APInt getHiBits(unsigned numBits) const; + + /// Get an APInt with the same BitWidth as this APInt, just zero mask + /// the high bits. + /// @returns the low "numBits" bits of this APInt. + APInt getLoBits(unsigned numBits) const; + + /// Constructs an APInt value that has a contiguous range of bits set. The + /// bits from loBit (inclusive) to hiBit (exclusive) will be set. All other + /// bits will be zero. For example, with parameters(32, 0, 16) you would get + /// 0x0000FFFF. If hiBit is less than loBit then the set bits "wrap". For + /// example, with parameters (32, 28, 4), you would get 0xF000000F. + /// @param numBits the intended bit width of the result + /// @param loBit the index of the lowest bit set. + /// @param hiBit the index of the highest bit set. + /// @returns An APInt value with the requested bits set. + /// @brief Get a value with a block of bits set. + static APInt getBitsSet(unsigned numBits, unsigned loBit, unsigned hiBit) { + assert(hiBit <= numBits && "hiBit out of range"); + assert(loBit < numBits && "loBit out of range"); + if (hiBit < loBit) + return getLowBitsSet(numBits, hiBit) | + getHighBitsSet(numBits, numBits-loBit); + return getLowBitsSet(numBits, hiBit-loBit).shl(loBit); + } + + /// Constructs an APInt value that has the top hiBitsSet bits set. + /// @param numBits the bitwidth of the result + /// @param hiBitsSet the number of high-order bits set in the result. + /// @brief Get a value with high bits set + static APInt getHighBitsSet(unsigned numBits, unsigned hiBitsSet) { + assert(hiBitsSet <= numBits && "Too many bits to set!"); + // Handle a degenerate case, to avoid shifting by word size + if (hiBitsSet == 0) + return APInt(numBits, 0); + unsigned shiftAmt = numBits - hiBitsSet; + // For small values, return quickly + if (numBits <= APINT_BITS_PER_WORD) + return APInt(numBits, ~0ULL << shiftAmt); + return (~APInt(numBits, 0)).shl(shiftAmt); + } + + /// Constructs an APInt value that has the bottom loBitsSet bits set. + /// @param numBits the bitwidth of the result + /// @param loBitsSet the number of low-order bits set in the result. + /// @brief Get a value with low bits set + static APInt getLowBitsSet(unsigned numBits, unsigned loBitsSet) { + assert(loBitsSet <= numBits && "Too many bits to set!"); + // Handle a degenerate case, to avoid shifting by word size + if (loBitsSet == 0) + return APInt(numBits, 0); + if (loBitsSet == APINT_BITS_PER_WORD) + return APInt(numBits, -1ULL); + // For small values, return quickly. + if (numBits < APINT_BITS_PER_WORD) + return APInt(numBits, (1ULL << loBitsSet) - 1); + return (~APInt(numBits, 0)).lshr(numBits - loBitsSet); + } + + /// The hash value is computed as the sum of the words and the bit width. + /// @returns A hash value computed from the sum of the APInt words. + /// @brief Get a hash value based on this APInt + uint64_t getHashValue() const; + + /// This function returns a pointer to the internal storage of the APInt. + /// This is useful for writing out the APInt in binary form without any + /// conversions. + const uint64_t* getRawData() const { + if (isSingleWord()) + return &VAL; + return &pVal[0]; + } + + /// @} + /// @name Unary Operators + /// @{ + /// @returns a new APInt value representing *this incremented by one + /// @brief Postfix increment operator. + const APInt operator++(int) { + APInt API(*this); + ++(*this); + return API; + } + + /// @returns *this incremented by one + /// @brief Prefix increment operator. + APInt& operator++(); + + /// @returns a new APInt representing *this decremented by one. + /// @brief Postfix decrement operator. + const APInt operator--(int) { + APInt API(*this); + --(*this); + return API; + } + + /// @returns *this decremented by one. + /// @brief Prefix decrement operator. + APInt& operator--(); + + /// Performs a bitwise complement operation on this APInt. + /// @returns an APInt that is the bitwise complement of *this + /// @brief Unary bitwise complement operator. + APInt operator~() const { + APInt Result(*this); + Result.flip(); + return Result; + } + + /// Negates *this using two's complement logic. + /// @returns An APInt value representing the negation of *this. + /// @brief Unary negation operator + APInt operator-() const { + return APInt(BitWidth, 0) - (*this); + } + + /// Performs logical negation operation on this APInt. + /// @returns true if *this is zero, false otherwise. + /// @brief Logical negation operator. + bool operator!() const; + + /// @} + /// @name Assignment Operators + /// @{ + /// @returns *this after assignment of RHS. + /// @brief Copy assignment operator. + APInt& operator=(const APInt& RHS) { + // If the bitwidths are the same, we can avoid mucking with memory + if (isSingleWord() && RHS.isSingleWord()) { + VAL = RHS.VAL; + BitWidth = RHS.BitWidth; + return clearUnusedBits(); + } + + return AssignSlowCase(RHS); + } + + /// The RHS value is assigned to *this. If the significant bits in RHS exceed + /// the bit width, the excess bits are truncated. If the bit width is larger + /// than 64, the value is zero filled in the unspecified high order bits. + /// @returns *this after assignment of RHS value. + /// @brief Assignment operator. + APInt& operator=(uint64_t RHS); + + /// Performs a bitwise AND operation on this APInt and RHS. The result is + /// assigned to *this. + /// @returns *this after ANDing with RHS. + /// @brief Bitwise AND assignment operator. + APInt& operator&=(const APInt& RHS); + + /// Performs a bitwise OR operation on this APInt and RHS. The result is + /// assigned *this; + /// @returns *this after ORing with RHS. + /// @brief Bitwise OR assignment operator. + APInt& operator|=(const APInt& RHS); + + /// Performs a bitwise XOR operation on this APInt and RHS. The result is + /// assigned to *this. + /// @returns *this after XORing with RHS. + /// @brief Bitwise XOR assignment operator. + APInt& operator^=(const APInt& RHS); + + /// Multiplies this APInt by RHS and assigns the result to *this. + /// @returns *this + /// @brief Multiplication assignment operator. + APInt& operator*=(const APInt& RHS); + + /// Adds RHS to *this and assigns the result to *this. + /// @returns *this + /// @brief Addition assignment operator. + APInt& operator+=(const APInt& RHS); + + /// Subtracts RHS from *this and assigns the result to *this. + /// @returns *this + /// @brief Subtraction assignment operator. + APInt& operator-=(const APInt& RHS); + + /// Shifts *this left by shiftAmt and assigns the result to *this. + /// @returns *this after shifting left by shiftAmt + /// @brief Left-shift assignment function. + APInt& operator<<=(unsigned shiftAmt) { + *this = shl(shiftAmt); + return *this; + } + + /// @} + /// @name Binary Operators + /// @{ + /// Performs a bitwise AND operation on *this and RHS. + /// @returns An APInt value representing the bitwise AND of *this and RHS. + /// @brief Bitwise AND operator. + APInt operator&(const APInt& RHS) const { + assert(BitWidth == RHS.BitWidth && "Bit widths must be the same"); + if (isSingleWord()) + return APInt(getBitWidth(), VAL & RHS.VAL); + return AndSlowCase(RHS); + } + APInt And(const APInt& RHS) const { + return this->operator&(RHS); + } + + /// Performs a bitwise OR operation on *this and RHS. + /// @returns An APInt value representing the bitwise OR of *this and RHS. + /// @brief Bitwise OR operator. + APInt operator|(const APInt& RHS) const { + assert(BitWidth == RHS.BitWidth && "Bit widths must be the same"); + if (isSingleWord()) + return APInt(getBitWidth(), VAL | RHS.VAL); + return OrSlowCase(RHS); + } + APInt Or(const APInt& RHS) const { + return this->operator|(RHS); + } + + /// Performs a bitwise XOR operation on *this and RHS. + /// @returns An APInt value representing the bitwise XOR of *this and RHS. + /// @brief Bitwise XOR operator. + APInt operator^(const APInt& RHS) const { + assert(BitWidth == RHS.BitWidth && "Bit widths must be the same"); + if (isSingleWord()) + return APInt(BitWidth, VAL ^ RHS.VAL); + return XorSlowCase(RHS); + } + APInt Xor(const APInt& RHS) const { + return this->operator^(RHS); + } + + /// Multiplies this APInt by RHS and returns the result. + /// @brief Multiplication operator. + APInt operator*(const APInt& RHS) const; + + /// Adds RHS to this APInt and returns the result. + /// @brief Addition operator. + APInt operator+(const APInt& RHS) const; + APInt operator+(uint64_t RHS) const { + return (*this) + APInt(BitWidth, RHS); + } + + /// Subtracts RHS from this APInt and returns the result. + /// @brief Subtraction operator. + APInt operator-(const APInt& RHS) const; + APInt operator-(uint64_t RHS) const { + return (*this) - APInt(BitWidth, RHS); + } + + APInt operator<<(unsigned Bits) const { + return shl(Bits); + } + + APInt operator<<(const APInt &Bits) const { + return shl(Bits); + } + + /// Arithmetic right-shift this APInt by shiftAmt. + /// @brief Arithmetic right-shift function. + APInt ashr(unsigned shiftAmt) const; + + /// Logical right-shift this APInt by shiftAmt. + /// @brief Logical right-shift function. + APInt lshr(unsigned shiftAmt) const; + + /// Left-shift this APInt by shiftAmt. + /// @brief Left-shift function. + APInt shl(unsigned shiftAmt) const { + assert(shiftAmt <= BitWidth && "Invalid shift amount"); + if (isSingleWord()) { + if (shiftAmt == BitWidth) + return APInt(BitWidth, 0); // avoid undefined shift results + return APInt(BitWidth, VAL << shiftAmt); + } + return shlSlowCase(shiftAmt); + } + + /// @brief Rotate left by rotateAmt. + APInt rotl(unsigned rotateAmt) const; + + /// @brief Rotate right by rotateAmt. + APInt rotr(unsigned rotateAmt) const; + + /// Arithmetic right-shift this APInt by shiftAmt. + /// @brief Arithmetic right-shift function. + APInt ashr(const APInt &shiftAmt) const; + + /// Logical right-shift this APInt by shiftAmt. + /// @brief Logical right-shift function. + APInt lshr(const APInt &shiftAmt) const; + + /// Left-shift this APInt by shiftAmt. + /// @brief Left-shift function. + APInt shl(const APInt &shiftAmt) const; + + /// @brief Rotate left by rotateAmt. + APInt rotl(const APInt &rotateAmt) const; + + /// @brief Rotate right by rotateAmt. + APInt rotr(const APInt &rotateAmt) const; + + /// Perform an unsigned divide operation on this APInt by RHS. Both this and + /// RHS are treated as unsigned quantities for purposes of this division. + /// @returns a new APInt value containing the division result + /// @brief Unsigned division operation. + APInt udiv(const APInt& RHS) const; + + /// Signed divide this APInt by APInt RHS. + /// @brief Signed division function for APInt. + APInt sdiv(const APInt& RHS) const { + if (isNegative()) + if (RHS.isNegative()) + return (-(*this)).udiv(-RHS); + else + return -((-(*this)).udiv(RHS)); + else if (RHS.isNegative()) + return -(this->udiv(-RHS)); + return this->udiv(RHS); + } + + /// Perform an unsigned remainder operation on this APInt with RHS being the + /// divisor. Both this and RHS are treated as unsigned quantities for purposes + /// of this operation. Note that this is a true remainder operation and not + /// a modulo operation because the sign follows the sign of the dividend + /// which is *this. + /// @returns a new APInt value containing the remainder result + /// @brief Unsigned remainder operation. + APInt urem(const APInt& RHS) const; + + /// Signed remainder operation on APInt. + /// @brief Function for signed remainder operation. + APInt srem(const APInt& RHS) const { + if (isNegative()) + if (RHS.isNegative()) + return -((-(*this)).urem(-RHS)); + else + return -((-(*this)).urem(RHS)); + else if (RHS.isNegative()) + return this->urem(-RHS); + return this->urem(RHS); + } + + /// Sometimes it is convenient to divide two APInt values and obtain both the + /// quotient and remainder. This function does both operations in the same + /// computation making it a little more efficient. The pair of input arguments + /// may overlap with the pair of output arguments. It is safe to call + /// udivrem(X, Y, X, Y), for example. + /// @brief Dual division/remainder interface. + static void udivrem(const APInt &LHS, const APInt &RHS, + APInt &Quotient, APInt &Remainder); + + static void sdivrem(const APInt &LHS, const APInt &RHS, + APInt &Quotient, APInt &Remainder) + { + if (LHS.isNegative()) { + if (RHS.isNegative()) + APInt::udivrem(-LHS, -RHS, Quotient, Remainder); + else + APInt::udivrem(-LHS, RHS, Quotient, Remainder); + Quotient = -Quotient; + Remainder = -Remainder; + } else if (RHS.isNegative()) { + APInt::udivrem(LHS, -RHS, Quotient, Remainder); + Quotient = -Quotient; + } else { + APInt::udivrem(LHS, RHS, Quotient, Remainder); + } + } + + /// @returns the bit value at bitPosition + /// @brief Array-indexing support. + bool operator[](unsigned bitPosition) const; + + /// @} + /// @name Comparison Operators + /// @{ + /// Compares this APInt with RHS for the validity of the equality + /// relationship. + /// @brief Equality operator. + bool operator==(const APInt& RHS) const { + assert(BitWidth == RHS.BitWidth && "Comparison requires equal bit widths"); + if (isSingleWord()) + return VAL == RHS.VAL; + return EqualSlowCase(RHS); + } + + /// Compares this APInt with a uint64_t for the validity of the equality + /// relationship. + /// @returns true if *this == Val + /// @brief Equality operator. + bool operator==(uint64_t Val) const { + if (isSingleWord()) + return VAL == Val; + return EqualSlowCase(Val); + } + + /// Compares this APInt with RHS for the validity of the equality + /// relationship. + /// @returns true if *this == Val + /// @brief Equality comparison. + bool eq(const APInt &RHS) const { + return (*this) == RHS; + } + + /// Compares this APInt with RHS for the validity of the inequality + /// relationship. + /// @returns true if *this != Val + /// @brief Inequality operator. + bool operator!=(const APInt& RHS) const { + return !((*this) == RHS); + } + + /// Compares this APInt with a uint64_t for the validity of the inequality + /// relationship. + /// @returns true if *this != Val + /// @brief Inequality operator. + bool operator!=(uint64_t Val) const { + return !((*this) == Val); + } + + /// Compares this APInt with RHS for the validity of the inequality + /// relationship. + /// @returns true if *this != Val + /// @brief Inequality comparison + bool ne(const APInt &RHS) const { + return !((*this) == RHS); + } + + /// Regards both *this and RHS as unsigned quantities and compares them for + /// the validity of the less-than relationship. + /// @returns true if *this < RHS when both are considered unsigned. + /// @brief Unsigned less than comparison + bool ult(const APInt& RHS) const; + + /// Regards both *this and RHS as signed quantities and compares them for + /// validity of the less-than relationship. + /// @returns true if *this < RHS when both are considered signed. + /// @brief Signed less than comparison + bool slt(const APInt& RHS) const; + + /// Regards both *this and RHS as unsigned quantities and compares them for + /// validity of the less-or-equal relationship. + /// @returns true if *this <= RHS when both are considered unsigned. + /// @brief Unsigned less or equal comparison + bool ule(const APInt& RHS) const { + return ult(RHS) || eq(RHS); + } + + /// Regards both *this and RHS as signed quantities and compares them for + /// validity of the less-or-equal relationship. + /// @returns true if *this <= RHS when both are considered signed. + /// @brief Signed less or equal comparison + bool sle(const APInt& RHS) const { + return slt(RHS) || eq(RHS); + } + + /// Regards both *this and RHS as unsigned quantities and compares them for + /// the validity of the greater-than relationship. + /// @returns true if *this > RHS when both are considered unsigned. + /// @brief Unsigned greather than comparison + bool ugt(const APInt& RHS) const { + return !ult(RHS) && !eq(RHS); + } + + /// Regards both *this and RHS as signed quantities and compares them for + /// the validity of the greater-than relationship. + /// @returns true if *this > RHS when both are considered signed. + /// @brief Signed greather than comparison + bool sgt(const APInt& RHS) const { + return !slt(RHS) && !eq(RHS); + } + + /// Regards both *this and RHS as unsigned quantities and compares them for + /// validity of the greater-or-equal relationship. + /// @returns true if *this >= RHS when both are considered unsigned. + /// @brief Unsigned greater or equal comparison + bool uge(const APInt& RHS) const { + return !ult(RHS); + } + + /// Regards both *this and RHS as signed quantities and compares them for + /// validity of the greater-or-equal relationship. + /// @returns true if *this >= RHS when both are considered signed. + /// @brief Signed greather or equal comparison + bool sge(const APInt& RHS) const { + return !slt(RHS); + } + + /// This operation tests if there are any pairs of corresponding bits + /// between this APInt and RHS that are both set. + bool intersects(const APInt &RHS) const { + return (*this & RHS) != 0; + } + + /// @} + /// @name Resizing Operators + /// @{ + /// Truncate the APInt to a specified width. It is an error to specify a width + /// that is greater than or equal to the current width. + /// @brief Truncate to new width. + APInt &trunc(unsigned width); + + /// This operation sign extends the APInt to a new width. If the high order + /// bit is set, the fill on the left will be done with 1 bits, otherwise zero. + /// It is an error to specify a width that is less than or equal to the + /// current width. + /// @brief Sign extend to a new width. + APInt &sext(unsigned width); + + /// This operation zero extends the APInt to a new width. The high order bits + /// are filled with 0 bits. It is an error to specify a width that is less + /// than or equal to the current width. + /// @brief Zero extend to a new width. + APInt &zext(unsigned width); + + /// Make this APInt have the bit width given by \p width. The value is sign + /// extended, truncated, or left alone to make it that width. + /// @brief Sign extend or truncate to width + APInt &sextOrTrunc(unsigned width); + + /// Make this APInt have the bit width given by \p width. The value is zero + /// extended, truncated, or left alone to make it that width. + /// @brief Zero extend or truncate to width + APInt &zextOrTrunc(unsigned width); + + /// @} + /// @name Bit Manipulation Operators + /// @{ + /// @brief Set every bit to 1. + APInt& set() { + if (isSingleWord()) { + VAL = -1ULL; + return clearUnusedBits(); + } + + // Set all the bits in all the words. + for (unsigned i = 0; i < getNumWords(); ++i) + pVal[i] = -1ULL; + // Clear the unused ones + return clearUnusedBits(); + } + + /// Set the given bit to 1 whose position is given as "bitPosition". + /// @brief Set a given bit to 1. + APInt& set(unsigned bitPosition); + + /// @brief Set every bit to 0. + APInt& clear() { + if (isSingleWord()) + VAL = 0; + else + memset(pVal, 0, getNumWords() * APINT_WORD_SIZE); + return *this; + } + + /// Set the given bit to 0 whose position is given as "bitPosition". + /// @brief Set a given bit to 0. + APInt& clear(unsigned bitPosition); + + /// @brief Toggle every bit to its opposite value. + APInt& flip() { + if (isSingleWord()) { + VAL ^= -1ULL; + return clearUnusedBits(); + } + for (unsigned i = 0; i < getNumWords(); ++i) + pVal[i] ^= -1ULL; + return clearUnusedBits(); + } + + /// Toggle a given bit to its opposite value whose position is given + /// as "bitPosition". + /// @brief Toggles a given bit to its opposite value. + APInt& flip(unsigned bitPosition); + + /// @} + /// @name Value Characterization Functions + /// @{ + + /// @returns the total number of bits. + unsigned getBitWidth() const { + return BitWidth; + } + + /// Here one word's bitwidth equals to that of uint64_t. + /// @returns the number of words to hold the integer value of this APInt. + /// @brief Get the number of words. + unsigned getNumWords() const { + return getNumWords(BitWidth); + } + + /// Here one word's bitwidth equals to that of uint64_t. + /// @returns the number of words to hold the integer value with a + /// given bit width. + /// @brief Get the number of words. + static unsigned getNumWords(unsigned BitWidth) { + return (BitWidth + APINT_BITS_PER_WORD - 1) / APINT_BITS_PER_WORD; + } + + /// This function returns the number of active bits which is defined as the + /// bit width minus the number of leading zeros. This is used in several + /// computations to see how "wide" the value is. + /// @brief Compute the number of active bits in the value + unsigned getActiveBits() const { + return BitWidth - countLeadingZeros(); + } + + /// This function returns the number of active words in the value of this + /// APInt. This is used in conjunction with getActiveData to extract the raw + /// value of the APInt. + unsigned getActiveWords() const { + return whichWord(getActiveBits()-1) + 1; + } + + /// Computes the minimum bit width for this APInt while considering it to be + /// a signed (and probably negative) value. If the value is not negative, + /// this function returns the same value as getActiveBits()+1. Otherwise, it + /// returns the smallest bit width that will retain the negative value. For + /// example, -1 can be written as 0b1 or 0xFFFFFFFFFF. 0b1 is shorter and so + /// for -1, this function will always return 1. + /// @brief Get the minimum bit size for this signed APInt + unsigned getMinSignedBits() const { + if (isNegative()) + return BitWidth - countLeadingOnes() + 1; + return getActiveBits()+1; + } + + /// This method attempts to return the value of this APInt as a zero extended + /// uint64_t. The bitwidth must be <= 64 or the value must fit within a + /// uint64_t. Otherwise an assertion will result. + /// @brief Get zero extended value + uint64_t getZExtValue() const { + if (isSingleWord()) + return VAL; + assert(getActiveBits() <= 64 && "Too many bits for uint64_t"); + return pVal[0]; + } + + /// This method attempts to return the value of this APInt as a sign extended + /// int64_t. The bit width must be <= 64 or the value must fit within an + /// int64_t. Otherwise an assertion will result. + /// @brief Get sign extended value + int64_t getSExtValue() const { + if (isSingleWord()) + return int64_t(VAL << (APINT_BITS_PER_WORD - BitWidth)) >> + (APINT_BITS_PER_WORD - BitWidth); + assert(getMinSignedBits() <= 64 && "Too many bits for int64_t"); + return int64_t(pVal[0]); + } + + /// This method determines how many bits are required to hold the APInt + /// equivalent of the string given by \arg str. + /// @brief Get bits required for string value. + static unsigned getBitsNeeded(const StringRef& str, uint8_t radix); + + /// countLeadingZeros - This function is an APInt version of the + /// countLeadingZeros_{32,64} functions in MathExtras.h. It counts the number + /// of zeros from the most significant bit to the first one bit. + /// @returns BitWidth if the value is zero. + /// @returns the number of zeros from the most significant bit to the first + /// one bits. + unsigned countLeadingZeros() const { + if (isSingleWord()) { + unsigned unusedBits = APINT_BITS_PER_WORD - BitWidth; + return CountLeadingZeros_64(VAL) - unusedBits; + } + return countLeadingZerosSlowCase(); + } + + /// countLeadingOnes - This function is an APInt version of the + /// countLeadingOnes_{32,64} functions in MathExtras.h. It counts the number + /// of ones from the most significant bit to the first zero bit. + /// @returns 0 if the high order bit is not set + /// @returns the number of 1 bits from the most significant to the least + /// @brief Count the number of leading one bits. + unsigned countLeadingOnes() const; + + /// countTrailingZeros - This function is an APInt version of the + /// countTrailingZeros_{32,64} functions in MathExtras.h. It counts + /// the number of zeros from the least significant bit to the first set bit. + /// @returns BitWidth if the value is zero. + /// @returns the number of zeros from the least significant bit to the first + /// one bit. + /// @brief Count the number of trailing zero bits. + unsigned countTrailingZeros() const; + + /// countTrailingOnes - This function is an APInt version of the + /// countTrailingOnes_{32,64} functions in MathExtras.h. It counts + /// the number of ones from the least significant bit to the first zero bit. + /// @returns BitWidth if the value is all ones. + /// @returns the number of ones from the least significant bit to the first + /// zero bit. + /// @brief Count the number of trailing one bits. + unsigned countTrailingOnes() const { + if (isSingleWord()) + return CountTrailingOnes_64(VAL); + return countTrailingOnesSlowCase(); + } + + /// countPopulation - This function is an APInt version of the + /// countPopulation_{32,64} functions in MathExtras.h. It counts the number + /// of 1 bits in the APInt value. + /// @returns 0 if the value is zero. + /// @returns the number of set bits. + /// @brief Count the number of bits set. + unsigned countPopulation() const { + if (isSingleWord()) + return CountPopulation_64(VAL); + return countPopulationSlowCase(); + } + + /// @} + /// @name Conversion Functions + /// @{ + void print(raw_ostream &OS, bool isSigned) const; + + /// toString - Converts an APInt to a string and append it to Str. Str is + /// commonly a SmallString. + void toString(SmallVectorImpl &Str, unsigned Radix, bool Signed) const; + + /// 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. + void toStringUnsigned(SmallVectorImpl &Str, unsigned Radix = 10) const { + toString(Str, Radix, false); + } + + /// 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. + void toStringSigned(SmallVectorImpl &Str, unsigned Radix = 10) const { + toString(Str, Radix, true); + } + + /// toString - This returns the APInt as a std::string. Note that this is an + /// inefficient method. It is better to pass in a SmallVector/SmallString + /// to the methods above to avoid thrashing the heap for the string. + std::string toString(unsigned Radix, bool Signed) const; + + + /// @returns a byte-swapped representation of this APInt Value. + APInt byteSwap() const; + + /// @brief Converts this APInt to a double value. + double roundToDouble(bool isSigned) const; + + /// @brief Converts this unsigned APInt to a double value. + double roundToDouble() const { + return roundToDouble(false); + } + + /// @brief Converts this signed APInt to a double value. + double signedRoundToDouble() const { + return roundToDouble(true); + } + + /// The conversion does not do a translation from integer to double, it just + /// re-interprets the bits as a double. Note that it is valid to do this on + /// any bit width. Exactly 64 bits will be translated. + /// @brief Converts APInt bits to a double + double bitsToDouble() const { + union { + uint64_t I; + double D; + } T; + T.I = (isSingleWord() ? VAL : pVal[0]); + return T.D; + } + + /// The conversion does not do a translation from integer to float, it just + /// re-interprets the bits as a float. Note that it is valid to do this on + /// any bit width. Exactly 32 bits will be translated. + /// @brief Converts APInt bits to a double + float bitsToFloat() const { + union { + unsigned I; + float F; + } T; + T.I = unsigned((isSingleWord() ? VAL : pVal[0])); + return T.F; + } + + /// The conversion does not do a translation from double to integer, it just + /// re-interprets the bits of the double. Note that it is valid to do this on + /// any bit width but bits from V may get truncated. + /// @brief Converts a double to APInt bits. + APInt& doubleToBits(double V) { + union { + uint64_t I; + double D; + } T; + T.D = V; + if (isSingleWord()) + VAL = T.I; + else + pVal[0] = T.I; + return clearUnusedBits(); + } + + /// The conversion does not do a translation from float to integer, it just + /// re-interprets the bits of the float. Note that it is valid to do this on + /// any bit width but bits from V may get truncated. + /// @brief Converts a float to APInt bits. + APInt& floatToBits(float V) { + union { + unsigned I; + float F; + } T; + T.F = V; + if (isSingleWord()) + VAL = T.I; + else + pVal[0] = T.I; + return clearUnusedBits(); + } + + /// @} + /// @name Mathematics Operations + /// @{ + + /// @returns the floor log base 2 of this APInt. + unsigned logBase2() const { + return BitWidth - 1 - countLeadingZeros(); + } + + /// @returns the ceil log base 2 of this APInt. + unsigned ceilLogBase2() const { + return BitWidth - (*this - 1).countLeadingZeros(); + } + + /// @returns the log base 2 of this APInt if its an exact power of two, -1 + /// otherwise + int32_t exactLogBase2() const { + if (!isPowerOf2()) + return -1; + return logBase2(); + } + + /// @brief Compute the square root + APInt sqrt() const; + + /// If *this is < 0 then return -(*this), otherwise *this; + /// @brief Get the absolute value; + APInt abs() const { + if (isNegative()) + return -(*this); + return *this; + } + + /// @returns the multiplicative inverse for a given modulo. + APInt multiplicativeInverse(const APInt& modulo) const; + + /// @} + /// @name Support for division by constant + /// @{ + + /// Calculate the magic number for signed division by a constant. + struct ms; + ms magic() const; + + /// Calculate the magic number for unsigned division by a constant. + struct mu; + mu magicu() const; + + /// @} + /// @name Building-block Operations for APInt and APFloat + /// @{ + + // These building block operations operate on a representation of + // arbitrary precision, two's-complement, bignum integer values. + // They should be sufficient to implement APInt and APFloat bignum + // requirements. Inputs are generally a pointer to the base of an + // array of integer parts, representing an unsigned bignum, and a + // count of how many parts there are. + + /// Sets the least significant part of a bignum to the input value, + /// and zeroes out higher parts. */ + static void tcSet(integerPart *, integerPart, unsigned int); + + /// Assign one bignum to another. + static void tcAssign(integerPart *, const integerPart *, unsigned int); + + /// Returns true if a bignum is zero, false otherwise. + static bool tcIsZero(const integerPart *, unsigned int); + + /// Extract the given bit of a bignum; returns 0 or 1. Zero-based. + static int tcExtractBit(const integerPart *, unsigned int bit); + + /// Copy the bit vector of width srcBITS from SRC, starting at bit + /// srcLSB, to DST, of dstCOUNT parts, such that the bit srcLSB + /// becomes the least significant bit of DST. All high bits above + /// srcBITS in DST are zero-filled. + static void tcExtract(integerPart *, unsigned int dstCount, + const integerPart *, + unsigned int srcBits, unsigned int srcLSB); + + /// Set the given bit of a bignum. Zero-based. + static void tcSetBit(integerPart *, unsigned int bit); + + /// Returns the bit number of the least or most significant set bit + /// of a number. If the input number has no bits set -1U is + /// returned. + static unsigned int tcLSB(const integerPart *, unsigned int); + static unsigned int tcMSB(const integerPart *parts, unsigned int n); + + /// Negate a bignum in-place. + static void tcNegate(integerPart *, unsigned int); + + /// DST += RHS + CARRY where CARRY is zero or one. Returns the + /// carry flag. + static integerPart tcAdd(integerPart *, const integerPart *, + integerPart carry, unsigned); + + /// DST -= RHS + CARRY where CARRY is zero or one. Returns the + /// carry flag. + static integerPart tcSubtract(integerPart *, const integerPart *, + integerPart carry, unsigned); + + /// DST += SRC * MULTIPLIER + PART if add is true + /// DST = SRC * MULTIPLIER + PART if add is false + /// + /// Requires 0 <= DSTPARTS <= SRCPARTS + 1. If DST overlaps SRC + /// they must start at the same point, i.e. DST == SRC. + /// + /// If DSTPARTS == SRC_PARTS + 1 no overflow occurs and zero is + /// returned. Otherwise DST is filled with the least significant + /// DSTPARTS parts of the result, and if all of the omitted higher + /// parts were zero return zero, otherwise overflow occurred and + /// return one. + static int tcMultiplyPart(integerPart *dst, const integerPart *src, + integerPart multiplier, integerPart carry, + unsigned int srcParts, unsigned int dstParts, + bool add); + + /// DST = LHS * RHS, where DST has the same width as the operands + /// and is filled with the least significant parts of the result. + /// Returns one if overflow occurred, otherwise zero. DST must be + /// disjoint from both operands. + static int tcMultiply(integerPart *, const integerPart *, + const integerPart *, unsigned); + + /// DST = LHS * RHS, where DST has width the sum of the widths of + /// the operands. No overflow occurs. DST must be disjoint from + /// both operands. Returns the number of parts required to hold the + /// result. + static unsigned int tcFullMultiply(integerPart *, const integerPart *, + const integerPart *, unsigned, unsigned); + + /// If RHS is zero LHS and REMAINDER are left unchanged, return one. + /// Otherwise set LHS to LHS / RHS with the fractional part + /// discarded, set REMAINDER to the remainder, return zero. i.e. + /// + /// OLD_LHS = RHS * LHS + REMAINDER + /// + /// SCRATCH is a bignum of the same size as the operands and result + /// for use by the routine; its contents need not be initialized + /// and are destroyed. LHS, REMAINDER and SCRATCH must be + /// distinct. + static int tcDivide(integerPart *lhs, const integerPart *rhs, + integerPart *remainder, integerPart *scratch, + unsigned int parts); + + /// Shift a bignum left COUNT bits. Shifted in bits are zero. + /// There are no restrictions on COUNT. + static void tcShiftLeft(integerPart *, unsigned int parts, + unsigned int count); + + /// Shift a bignum right COUNT bits. Shifted in bits are zero. + /// There are no restrictions on COUNT. + static void tcShiftRight(integerPart *, unsigned int parts, + unsigned int count); + + /// The obvious AND, OR and XOR and complement operations. + static void tcAnd(integerPart *, const integerPart *, unsigned int); + static void tcOr(integerPart *, const integerPart *, unsigned int); + static void tcXor(integerPart *, const integerPart *, unsigned int); + static void tcComplement(integerPart *, unsigned int); + + /// Comparison (unsigned) of two bignums. + static int tcCompare(const integerPart *, const integerPart *, + unsigned int); + + /// Increment a bignum in-place. Return the carry flag. + static integerPart tcIncrement(integerPart *, unsigned int); + + /// Set the least significant BITS and clear the rest. + static void tcSetLeastSignificantBits(integerPart *, unsigned int, + unsigned int bits); + + /// @brief debug method + void dump() const; + + /// @} +}; + +/// Magic data for optimising signed division by a constant. +struct APInt::ms { + APInt m; ///< magic number + unsigned s; ///< shift amount +}; + +/// Magic data for optimising unsigned division by a constant. +struct APInt::mu { + APInt m; ///< magic number + bool a; ///< add indicator + unsigned s; ///< shift amount +}; + +inline bool operator==(uint64_t V1, const APInt& V2) { + return V2 == V1; +} + +inline bool operator!=(uint64_t V1, const APInt& V2) { + return V2 != V1; +} + +inline raw_ostream &operator<<(raw_ostream &OS, const APInt &I) { + I.print(OS, true); + return OS; +} + +namespace APIntOps { + +/// @brief Determine the smaller of two APInts considered to be signed. +inline APInt smin(const APInt &A, const APInt &B) { + return A.slt(B) ? A : B; +} + +/// @brief Determine the larger of two APInts considered to be signed. +inline APInt smax(const APInt &A, const APInt &B) { + return A.sgt(B) ? A : B; +} + +/// @brief Determine the smaller of two APInts considered to be signed. +inline APInt umin(const APInt &A, const APInt &B) { + return A.ult(B) ? A : B; +} + +/// @brief Determine the larger of two APInts considered to be unsigned. +inline APInt umax(const APInt &A, const APInt &B) { + return A.ugt(B) ? A : B; +} + +/// @brief Check if the specified APInt has a N-bits unsigned integer value. +inline bool isIntN(unsigned N, const APInt& APIVal) { + return APIVal.isIntN(N); +} + +/// @brief Check if the specified APInt has a N-bits signed integer value. +inline bool isSignedIntN(unsigned N, const APInt& APIVal) { + return APIVal.isSignedIntN(N); +} + +/// @returns true if the argument APInt value is a sequence of ones +/// starting at the least significant bit with the remainder zero. +inline bool isMask(unsigned numBits, const APInt& APIVal) { + return numBits <= APIVal.getBitWidth() && + APIVal == APInt::getLowBitsSet(APIVal.getBitWidth(), numBits); +} + +/// @returns true if the argument APInt value contains a sequence of ones +/// with the remainder zero. +inline bool isShiftedMask(unsigned numBits, const APInt& APIVal) { + return isMask(numBits, (APIVal - APInt(numBits,1)) | APIVal); +} + +/// @returns a byte-swapped representation of the specified APInt Value. +inline APInt byteSwap(const APInt& APIVal) { + return APIVal.byteSwap(); +} + +/// @returns the floor log base 2 of the specified APInt value. +inline unsigned logBase2(const APInt& APIVal) { + return APIVal.logBase2(); +} + +/// GreatestCommonDivisor - This function returns the greatest common +/// divisor of the two APInt values using Euclid's algorithm. +/// @returns the greatest common divisor of Val1 and Val2 +/// @brief Compute GCD of two APInt values. +APInt GreatestCommonDivisor(const APInt& Val1, const APInt& Val2); + +/// Treats the APInt as an unsigned value for conversion purposes. +/// @brief Converts the given APInt to a double value. +inline double RoundAPIntToDouble(const APInt& APIVal) { + return APIVal.roundToDouble(); +} + +/// Treats the APInt as a signed value for conversion purposes. +/// @brief Converts the given APInt to a double value. +inline double RoundSignedAPIntToDouble(const APInt& APIVal) { + return APIVal.signedRoundToDouble(); +} + +/// @brief Converts the given APInt to a float vlalue. +inline float RoundAPIntToFloat(const APInt& APIVal) { + return float(RoundAPIntToDouble(APIVal)); +} + +/// Treast the APInt as a signed value for conversion purposes. +/// @brief Converts the given APInt to a float value. +inline float RoundSignedAPIntToFloat(const APInt& APIVal) { + return float(APIVal.signedRoundToDouble()); +} + +/// RoundDoubleToAPInt - This function convert a double value to an APInt value. +/// @brief Converts the given double value into a APInt. +APInt RoundDoubleToAPInt(double Double, unsigned width); + +/// RoundFloatToAPInt - Converts a float value into an APInt value. +/// @brief Converts a float value into a APInt. +inline APInt RoundFloatToAPInt(float Float, unsigned width) { + return RoundDoubleToAPInt(double(Float), width); +} + +/// Arithmetic right-shift the APInt by shiftAmt. +/// @brief Arithmetic right-shift function. +inline APInt ashr(const APInt& LHS, unsigned shiftAmt) { + return LHS.ashr(shiftAmt); +} + +/// Logical right-shift the APInt by shiftAmt. +/// @brief Logical right-shift function. +inline APInt lshr(const APInt& LHS, unsigned shiftAmt) { + return LHS.lshr(shiftAmt); +} + +/// Left-shift the APInt by shiftAmt. +/// @brief Left-shift function. +inline APInt shl(const APInt& LHS, unsigned shiftAmt) { + return LHS.shl(shiftAmt); +} + +/// Signed divide APInt LHS by APInt RHS. +/// @brief Signed division function for APInt. +inline APInt sdiv(const APInt& LHS, const APInt& RHS) { + return LHS.sdiv(RHS); +} + +/// Unsigned divide APInt LHS by APInt RHS. +/// @brief Unsigned division function for APInt. +inline APInt udiv(const APInt& LHS, const APInt& RHS) { + return LHS.udiv(RHS); +} + +/// Signed remainder operation on APInt. +/// @brief Function for signed remainder operation. +inline APInt srem(const APInt& LHS, const APInt& RHS) { + return LHS.srem(RHS); +} + +/// Unsigned remainder operation on APInt. +/// @brief Function for unsigned remainder operation. +inline APInt urem(const APInt& LHS, const APInt& RHS) { + return LHS.urem(RHS); +} + +/// Performs multiplication on APInt values. +/// @brief Function for multiplication operation. +inline APInt mul(const APInt& LHS, const APInt& RHS) { + return LHS * RHS; +} + +/// Performs addition on APInt values. +/// @brief Function for addition operation. +inline APInt add(const APInt& LHS, const APInt& RHS) { + return LHS + RHS; +} + +/// Performs subtraction on APInt values. +/// @brief Function for subtraction operation. +inline APInt sub(const APInt& LHS, const APInt& RHS) { + return LHS - RHS; +} + +/// Performs bitwise AND operation on APInt LHS and +/// APInt RHS. +/// @brief Bitwise AND function for APInt. +inline APInt And(const APInt& LHS, const APInt& RHS) { + return LHS & RHS; +} + +/// Performs bitwise OR operation on APInt LHS and APInt RHS. +/// @brief Bitwise OR function for APInt. +inline APInt Or(const APInt& LHS, const APInt& RHS) { + return LHS | RHS; +} + +/// Performs bitwise XOR operation on APInt. +/// @brief Bitwise XOR function for APInt. +inline APInt Xor(const APInt& LHS, const APInt& RHS) { + return LHS ^ RHS; +} + +/// Performs a bitwise complement operation on APInt. +/// @brief Bitwise complement function. +inline APInt Not(const APInt& APIVal) { + return ~APIVal; +} + +} // End of APIntOps namespace + +} // End of llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/ADT/APSInt.h b/libclamav/c++/llvm/include/llvm/ADT/APSInt.h new file mode 100644 index 000000000..1c9931c30 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/ADT/APSInt.h @@ -0,0 +1,264 @@ +//===-- llvm/ADT/APSInt.h - Arbitrary Precision Signed Int -----*- 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 the APSInt class, which is a simple class that +// represents an arbitrary sized integer that knows its signedness. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_APSINT_H +#define LLVM_APSINT_H + +#include "llvm/ADT/APInt.h" + +namespace llvm { + +class APSInt : public APInt { + bool IsUnsigned; +public: + /// Default constructor that creates an uninitialized APInt. + explicit APSInt() {} + + /// APSInt ctor - Create an APSInt with the specified width, default to + /// unsigned. + explicit APSInt(uint32_t BitWidth, bool isUnsigned = true) + : APInt(BitWidth, 0), IsUnsigned(isUnsigned) {} + + explicit APSInt(const APInt &I, bool isUnsigned = true) + : APInt(I), IsUnsigned(isUnsigned) {} + + APSInt &operator=(const APSInt &RHS) { + APInt::operator=(RHS); + IsUnsigned = RHS.IsUnsigned; + return *this; + } + + APSInt &operator=(const APInt &RHS) { + // Retain our current sign. + APInt::operator=(RHS); + return *this; + } + + APSInt &operator=(uint64_t RHS) { + // Retain our current sign. + APInt::operator=(RHS); + return *this; + } + + // Query sign information. + bool isSigned() const { return !IsUnsigned; } + bool isUnsigned() const { return IsUnsigned; } + void setIsUnsigned(bool Val) { IsUnsigned = Val; } + void setIsSigned(bool Val) { IsUnsigned = !Val; } + + /// toString - Append this APSInt to the specified SmallString. + void toString(SmallVectorImpl &Str, unsigned Radix = 10) const { + APInt::toString(Str, Radix, isSigned()); + } + /// toString - Converts an APInt to a std::string. This is an inefficient + /// method, your should prefer passing in a SmallString instead. + std::string toString(unsigned Radix) const { + return APInt::toString(Radix, isSigned()); + } + using APInt::toString; + + APSInt& extend(uint32_t width) { + if (IsUnsigned) + zext(width); + else + sext(width); + return *this; + } + + APSInt& extOrTrunc(uint32_t width) { + if (IsUnsigned) + zextOrTrunc(width); + else + sextOrTrunc(width); + return *this; + } + + const APSInt &operator%=(const APSInt &RHS) { + assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); + if (IsUnsigned) + *this = urem(RHS); + else + *this = srem(RHS); + return *this; + } + const APSInt &operator/=(const APSInt &RHS) { + assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); + if (IsUnsigned) + *this = udiv(RHS); + else + *this = sdiv(RHS); + return *this; + } + APSInt operator%(const APSInt &RHS) const { + assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); + return IsUnsigned ? APSInt(urem(RHS), true) : APSInt(srem(RHS), false); + } + APSInt operator/(const APSInt &RHS) const { + assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); + return IsUnsigned ? APSInt(udiv(RHS), true) : APSInt(sdiv(RHS), false); + } + + APSInt operator>>(unsigned Amt) const { + return IsUnsigned ? APSInt(lshr(Amt), true) : APSInt(ashr(Amt), false); + } + APSInt& operator>>=(unsigned Amt) { + *this = *this >> Amt; + return *this; + } + + inline bool operator<(const APSInt& RHS) const { + assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); + return IsUnsigned ? ult(RHS) : slt(RHS); + } + inline bool operator>(const APSInt& RHS) const { + assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); + return IsUnsigned ? ugt(RHS) : sgt(RHS); + } + inline bool operator<=(const APSInt& RHS) const { + assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); + return IsUnsigned ? ule(RHS) : sle(RHS); + } + inline bool operator>=(const APSInt& RHS) const { + assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); + return IsUnsigned ? uge(RHS) : sge(RHS); + } + + // The remaining operators just wrap the logic of APInt, but retain the + // signedness information. + + APSInt operator<<(unsigned Bits) const { + return APSInt(static_cast(*this) << Bits, IsUnsigned); + } + APSInt& operator<<=(unsigned Amt) { + *this = *this << Amt; + return *this; + } + + APSInt& operator++() { + static_cast(*this)++; + return *this; + } + APSInt& operator--() { + static_cast(*this)--; + return *this; + } + APSInt operator++(int) { + return APSInt(++static_cast(*this), IsUnsigned); + } + APSInt operator--(int) { + return APSInt(--static_cast(*this), IsUnsigned); + } + APSInt operator-() const { + return APSInt(-static_cast(*this), IsUnsigned); + } + APSInt& operator+=(const APSInt& RHS) { + assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); + static_cast(*this) += RHS; + return *this; + } + APSInt& operator-=(const APSInt& RHS) { + assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); + static_cast(*this) -= RHS; + return *this; + } + APSInt& operator*=(const APSInt& RHS) { + assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); + static_cast(*this) *= RHS; + return *this; + } + APSInt& operator&=(const APSInt& RHS) { + assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); + static_cast(*this) &= RHS; + return *this; + } + APSInt& operator|=(const APSInt& RHS) { + assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); + static_cast(*this) |= RHS; + return *this; + } + APSInt& operator^=(const APSInt& RHS) { + assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); + static_cast(*this) ^= RHS; + return *this; + } + + APSInt operator&(const APSInt& RHS) const { + assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); + return APSInt(static_cast(*this) & RHS, IsUnsigned); + } + APSInt And(const APSInt& RHS) const { + return this->operator&(RHS); + } + + APSInt operator|(const APSInt& RHS) const { + assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); + return APSInt(static_cast(*this) | RHS, IsUnsigned); + } + APSInt Or(const APSInt& RHS) const { + return this->operator|(RHS); + } + + + APSInt operator^(const APSInt& RHS) const { + assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); + return APSInt(static_cast(*this) ^ RHS, IsUnsigned); + } + APSInt Xor(const APSInt& RHS) const { + return this->operator^(RHS); + } + + APSInt operator*(const APSInt& RHS) const { + assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); + return APSInt(static_cast(*this) * RHS, IsUnsigned); + } + APSInt operator+(const APSInt& RHS) const { + assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); + return APSInt(static_cast(*this) + RHS, IsUnsigned); + } + APSInt operator-(const APSInt& RHS) const { + assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); + return APSInt(static_cast(*this) - RHS, IsUnsigned); + } + APSInt operator~() const { + return APSInt(~static_cast(*this), IsUnsigned); + } + + /// getMaxValue - Return the APSInt representing the maximum integer value + /// with the given bit width and signedness. + static APSInt getMaxValue(uint32_t numBits, bool Unsigned) { + return APSInt(Unsigned ? APInt::getMaxValue(numBits) + : APInt::getSignedMaxValue(numBits), Unsigned); + } + + /// getMinValue - Return the APSInt representing the minimum integer value + /// with the given bit width and signedness. + static APSInt getMinValue(uint32_t numBits, bool Unsigned) { + return APSInt(Unsigned ? APInt::getMinValue(numBits) + : APInt::getSignedMinValue(numBits), Unsigned); + } + + /// Profile - Used to insert APSInt objects, or objects that contain APSInt + /// objects, into FoldingSets. + void Profile(FoldingSetNodeID& ID) const; +}; + +inline raw_ostream &operator<<(raw_ostream &OS, const APSInt &I) { + I.print(OS, I.isSigned()); + return OS; +} + + +} // end namespace llvm + +#endif diff --git a/libclamav/c++/llvm/include/llvm/ADT/BitVector.h b/libclamav/c++/llvm/include/llvm/ADT/BitVector.h new file mode 100644 index 000000000..9c046efaa --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/ADT/BitVector.h @@ -0,0 +1,409 @@ +//===- llvm/ADT/BitVector.h - Bit vectors -----------------------*- 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 the BitVector class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_BITVECTOR_H +#define LLVM_ADT_BITVECTOR_H + +#include "llvm/Support/MathExtras.h" +#include +#include +#include +#include + +namespace llvm { + +class BitVector { + typedef unsigned long BitWord; + + enum { BITWORD_SIZE = (unsigned)sizeof(BitWord) * CHAR_BIT }; + + BitWord *Bits; // Actual bits. + unsigned Size; // Size of bitvector in bits. + unsigned Capacity; // Size of allocated memory in BitWord. + +public: + // Encapsulation of a single bit. + class reference { + friend class BitVector; + + BitWord *WordRef; + unsigned BitPos; + + reference(); // Undefined + + public: + reference(BitVector &b, unsigned Idx) { + WordRef = &b.Bits[Idx / BITWORD_SIZE]; + BitPos = Idx % BITWORD_SIZE; + } + + ~reference() {} + + reference& operator=(bool t) { + if (t) + *WordRef |= 1L << BitPos; + else + *WordRef &= ~(1L << BitPos); + return *this; + } + + operator bool() const { + return ((*WordRef) & (1L << BitPos)) ? true : false; + } + }; + + + /// BitVector default ctor - Creates an empty bitvector. + BitVector() : Size(0), Capacity(0) { + Bits = 0; + } + + /// BitVector ctor - Creates a bitvector of specified number of bits. All + /// bits are initialized to the specified value. + explicit BitVector(unsigned s, bool t = false) : Size(s) { + Capacity = NumBitWords(s); + Bits = new BitWord[Capacity]; + init_words(Bits, Capacity, t); + if (t) + clear_unused_bits(); + } + + /// BitVector copy ctor. + BitVector(const BitVector &RHS) : Size(RHS.size()) { + if (Size == 0) { + Bits = 0; + Capacity = 0; + return; + } + + Capacity = NumBitWords(RHS.size()); + Bits = new BitWord[Capacity]; + std::copy(RHS.Bits, &RHS.Bits[Capacity], Bits); + } + + ~BitVector() { + delete[] Bits; + } + + /// size - Returns the number of bits in this bitvector. + unsigned size() const { return Size; } + + /// count - Returns the number of bits which are set. + unsigned count() const { + unsigned NumBits = 0; + for (unsigned i = 0; i < NumBitWords(size()); ++i) + if (sizeof(BitWord) == 4) + NumBits += CountPopulation_32((uint32_t)Bits[i]); + else if (sizeof(BitWord) == 8) + NumBits += CountPopulation_64(Bits[i]); + else + assert(0 && "Unsupported!"); + return NumBits; + } + + /// any - Returns true if any bit is set. + bool any() const { + for (unsigned i = 0; i < NumBitWords(size()); ++i) + if (Bits[i] != 0) + return true; + return false; + } + + /// none - Returns true if none of the bits are set. + bool none() const { + return !any(); + } + + /// find_first - Returns the index of the first set bit, -1 if none + /// of the bits are set. + int find_first() const { + for (unsigned i = 0; i < NumBitWords(size()); ++i) + if (Bits[i] != 0) { + if (sizeof(BitWord) == 4) + return i * BITWORD_SIZE + CountTrailingZeros_32((uint32_t)Bits[i]); + else if (sizeof(BitWord) == 8) + return i * BITWORD_SIZE + CountTrailingZeros_64(Bits[i]); + else + assert(0 && "Unsupported!"); + } + return -1; + } + + /// find_next - Returns the index of the next set bit following the + /// "Prev" bit. Returns -1 if the next set bit is not found. + int find_next(unsigned Prev) const { + ++Prev; + if (Prev >= Size) + return -1; + + unsigned WordPos = Prev / BITWORD_SIZE; + unsigned BitPos = Prev % BITWORD_SIZE; + BitWord Copy = Bits[WordPos]; + // Mask off previous bits. + Copy &= ~0L << BitPos; + + if (Copy != 0) { + if (sizeof(BitWord) == 4) + return WordPos * BITWORD_SIZE + CountTrailingZeros_32((uint32_t)Copy); + else if (sizeof(BitWord) == 8) + return WordPos * BITWORD_SIZE + CountTrailingZeros_64(Copy); + else + assert(0 && "Unsupported!"); + } + + // Check subsequent words. + for (unsigned i = WordPos+1; i < NumBitWords(size()); ++i) + if (Bits[i] != 0) { + if (sizeof(BitWord) == 4) + return i * BITWORD_SIZE + CountTrailingZeros_32((uint32_t)Bits[i]); + else if (sizeof(BitWord) == 8) + return i * BITWORD_SIZE + CountTrailingZeros_64(Bits[i]); + else + assert(0 && "Unsupported!"); + } + return -1; + } + + /// clear - Clear all bits. + void clear() { + Size = 0; + } + + /// resize - Grow or shrink the bitvector. + void resize(unsigned N, bool t = false) { + if (N > Capacity * BITWORD_SIZE) { + unsigned OldCapacity = Capacity; + grow(N); + init_words(&Bits[OldCapacity], (Capacity-OldCapacity), t); + } + + // Set any old unused bits that are now included in the BitVector. This + // may set bits that are not included in the new vector, but we will clear + // them back out below. + if (N > Size) + set_unused_bits(t); + + // Update the size, and clear out any bits that are now unused + unsigned OldSize = Size; + Size = N; + if (t || N < OldSize) + clear_unused_bits(); + } + + void reserve(unsigned N) { + if (N > Capacity * BITWORD_SIZE) + grow(N); + } + + // Set, reset, flip + BitVector &set() { + init_words(Bits, Capacity, true); + clear_unused_bits(); + return *this; + } + + BitVector &set(unsigned Idx) { + Bits[Idx / BITWORD_SIZE] |= 1L << (Idx % BITWORD_SIZE); + return *this; + } + + BitVector &reset() { + init_words(Bits, Capacity, false); + return *this; + } + + BitVector &reset(unsigned Idx) { + Bits[Idx / BITWORD_SIZE] &= ~(1L << (Idx % BITWORD_SIZE)); + return *this; + } + + BitVector &flip() { + for (unsigned i = 0; i < NumBitWords(size()); ++i) + Bits[i] = ~Bits[i]; + clear_unused_bits(); + return *this; + } + + BitVector &flip(unsigned Idx) { + Bits[Idx / BITWORD_SIZE] ^= 1L << (Idx % BITWORD_SIZE); + return *this; + } + + // No argument flip. + BitVector operator~() const { + return BitVector(*this).flip(); + } + + // Indexing. + reference operator[](unsigned Idx) { + assert (Idx < Size && "Out-of-bounds Bit access."); + return reference(*this, Idx); + } + + bool operator[](unsigned Idx) const { + assert (Idx < Size && "Out-of-bounds Bit access."); + BitWord Mask = 1L << (Idx % BITWORD_SIZE); + return (Bits[Idx / BITWORD_SIZE] & Mask) != 0; + } + + bool test(unsigned Idx) const { + return (*this)[Idx]; + } + + // Comparison operators. + bool operator==(const BitVector &RHS) const { + unsigned ThisWords = NumBitWords(size()); + unsigned RHSWords = NumBitWords(RHS.size()); + unsigned i; + for (i = 0; i != std::min(ThisWords, RHSWords); ++i) + if (Bits[i] != RHS.Bits[i]) + return false; + + // Verify that any extra words are all zeros. + if (i != ThisWords) { + for (; i != ThisWords; ++i) + if (Bits[i]) + return false; + } else if (i != RHSWords) { + for (; i != RHSWords; ++i) + if (RHS.Bits[i]) + return false; + } + return true; + } + + bool operator!=(const BitVector &RHS) const { + return !(*this == RHS); + } + + // Intersection, union, disjoint union. + BitVector &operator&=(const BitVector &RHS) { + unsigned ThisWords = NumBitWords(size()); + unsigned RHSWords = NumBitWords(RHS.size()); + unsigned i; + for (i = 0; i != std::min(ThisWords, RHSWords); ++i) + Bits[i] &= RHS.Bits[i]; + + // Any bits that are just in this bitvector become zero, because they aren't + // in the RHS bit vector. Any words only in RHS are ignored because they + // are already zero in the LHS. + for (; i != ThisWords; ++i) + Bits[i] = 0; + + return *this; + } + + BitVector &operator|=(const BitVector &RHS) { + assert(Size == RHS.Size && "Illegal operation!"); + for (unsigned i = 0; i < NumBitWords(size()); ++i) + Bits[i] |= RHS.Bits[i]; + return *this; + } + + BitVector &operator^=(const BitVector &RHS) { + assert(Size == RHS.Size && "Illegal operation!"); + for (unsigned i = 0; i < NumBitWords(size()); ++i) + Bits[i] ^= RHS.Bits[i]; + return *this; + } + + // Assignment operator. + const BitVector &operator=(const BitVector &RHS) { + if (this == &RHS) return *this; + + Size = RHS.size(); + unsigned RHSWords = NumBitWords(Size); + if (Size <= Capacity * BITWORD_SIZE) { + std::copy(RHS.Bits, &RHS.Bits[RHSWords], Bits); + clear_unused_bits(); + return *this; + } + + // Grow the bitvector to have enough elements. + Capacity = RHSWords; + BitWord *NewBits = new BitWord[Capacity]; + std::copy(RHS.Bits, &RHS.Bits[RHSWords], NewBits); + + // Destroy the old bits. + delete[] Bits; + Bits = NewBits; + + return *this; + } + +private: + unsigned NumBitWords(unsigned S) const { + return (S + BITWORD_SIZE-1) / BITWORD_SIZE; + } + + // Set the unused bits in the high words. + void set_unused_bits(bool t = true) { + // Set high words first. + unsigned UsedWords = NumBitWords(Size); + if (Capacity > UsedWords) + init_words(&Bits[UsedWords], (Capacity-UsedWords), t); + + // Then set any stray high bits of the last used word. + unsigned ExtraBits = Size % BITWORD_SIZE; + if (ExtraBits) { + Bits[UsedWords-1] &= ~(~0L << ExtraBits); + Bits[UsedWords-1] |= (0 - (BitWord)t) << ExtraBits; + } + } + + // Clear the unused bits in the high words. + void clear_unused_bits() { + set_unused_bits(false); + } + + void grow(unsigned NewSize) { + unsigned OldCapacity = Capacity; + Capacity = NumBitWords(NewSize); + BitWord *NewBits = new BitWord[Capacity]; + + // Copy the old bits over. + if (OldCapacity != 0) + std::copy(Bits, &Bits[OldCapacity], NewBits); + + // Destroy the old bits. + delete[] Bits; + Bits = NewBits; + + clear_unused_bits(); + } + + void init_words(BitWord *B, unsigned NumWords, bool t) { + memset(B, 0 - (int)t, NumWords*sizeof(BitWord)); + } +}; + +inline BitVector operator&(const BitVector &LHS, const BitVector &RHS) { + BitVector Result(LHS); + Result &= RHS; + return Result; +} + +inline BitVector operator|(const BitVector &LHS, const BitVector &RHS) { + BitVector Result(LHS); + Result |= RHS; + return Result; +} + +inline BitVector operator^(const BitVector &LHS, const BitVector &RHS) { + BitVector Result(LHS); + Result ^= RHS; + return Result; +} + +} // End llvm namespace +#endif diff --git a/libclamav/c++/llvm/include/llvm/ADT/DenseMap.h b/libclamav/c++/llvm/include/llvm/ADT/DenseMap.h new file mode 100644 index 000000000..83299478e --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/ADT/DenseMap.h @@ -0,0 +1,493 @@ +//===- llvm/ADT/DenseMap.h - Dense probed hash table ------------*- 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 the DenseMap class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_DENSEMAP_H +#define LLVM_ADT_DENSEMAP_H + +#include "llvm/Support/MathExtras.h" +#include "llvm/Support/PointerLikeTypeTraits.h" +#include "llvm/Support/type_traits.h" +#include "llvm/ADT/DenseMapInfo.h" +#include +#include +#include +#include +#include + +namespace llvm { + +template, + typename ValueInfoT = DenseMapInfo, bool IsConst = false> +class DenseMapIterator; + +template, + typename ValueInfoT = DenseMapInfo > +class DenseMap { + typedef std::pair BucketT; + unsigned NumBuckets; + BucketT *Buckets; + + unsigned NumEntries; + unsigned NumTombstones; +public: + typedef KeyT key_type; + typedef ValueT mapped_type; + typedef BucketT value_type; + + DenseMap(const DenseMap& other) { + NumBuckets = 0; + CopyFrom(other); + } + + explicit DenseMap(unsigned NumInitBuckets = 64) { + init(NumInitBuckets); + } + + ~DenseMap() { + const KeyT EmptyKey = getEmptyKey(), TombstoneKey = getTombstoneKey(); + for (BucketT *P = Buckets, *E = Buckets+NumBuckets; P != E; ++P) { + if (!KeyInfoT::isEqual(P->first, EmptyKey) && + !KeyInfoT::isEqual(P->first, TombstoneKey)) + P->second.~ValueT(); + P->first.~KeyT(); + } +#ifndef NDEBUG + memset(Buckets, 0x5a, sizeof(BucketT)*NumBuckets); +#endif + operator delete(Buckets); + } + + typedef DenseMapIterator iterator; + typedef DenseMapIterator const_iterator; + inline iterator begin() { + return iterator(Buckets, Buckets+NumBuckets); + } + inline iterator end() { + return iterator(Buckets+NumBuckets, Buckets+NumBuckets); + } + inline const_iterator begin() const { + return const_iterator(Buckets, Buckets+NumBuckets); + } + inline const_iterator end() const { + return const_iterator(Buckets+NumBuckets, Buckets+NumBuckets); + } + + bool empty() const { return NumEntries == 0; } + unsigned size() const { return NumEntries; } + + /// Grow the densemap so that it has at least Size buckets. Does not shrink + void resize(size_t Size) { grow(Size); } + + void clear() { + if (NumEntries == 0 && NumTombstones == 0) return; + + // If the capacity of the array is huge, and the # elements used is small, + // shrink the array. + if (NumEntries * 4 < NumBuckets && NumBuckets > 64) { + shrink_and_clear(); + return; + } + + const KeyT EmptyKey = getEmptyKey(), TombstoneKey = getTombstoneKey(); + for (BucketT *P = Buckets, *E = Buckets+NumBuckets; P != E; ++P) { + if (!KeyInfoT::isEqual(P->first, EmptyKey)) { + if (!KeyInfoT::isEqual(P->first, TombstoneKey)) { + P->second.~ValueT(); + --NumEntries; + } + P->first = EmptyKey; + } + } + assert(NumEntries == 0 && "Node count imbalance!"); + NumTombstones = 0; + } + + /// count - Return true if the specified key is in the map. + bool count(const KeyT &Val) const { + BucketT *TheBucket; + return LookupBucketFor(Val, TheBucket); + } + + iterator find(const KeyT &Val) { + BucketT *TheBucket; + if (LookupBucketFor(Val, TheBucket)) + return iterator(TheBucket, Buckets+NumBuckets); + return end(); + } + const_iterator find(const KeyT &Val) const { + BucketT *TheBucket; + if (LookupBucketFor(Val, TheBucket)) + return const_iterator(TheBucket, Buckets+NumBuckets); + return end(); + } + + /// lookup - Return the entry for the specified key, or a default + /// constructed value if no such entry exists. + ValueT lookup(const KeyT &Val) const { + BucketT *TheBucket; + if (LookupBucketFor(Val, TheBucket)) + return TheBucket->second; + return ValueT(); + } + + // Inserts key,value pair into the map if the key isn't already in the map. + // If the key is already in the map, it returns false and doesn't update the + // value. + std::pair insert(const std::pair &KV) { + BucketT *TheBucket; + if (LookupBucketFor(KV.first, TheBucket)) + return std::make_pair(iterator(TheBucket, Buckets+NumBuckets), + false); // Already in map. + + // Otherwise, insert the new element. + TheBucket = InsertIntoBucket(KV.first, KV.second, TheBucket); + return std::make_pair(iterator(TheBucket, Buckets+NumBuckets), + true); + } + + /// insert - Range insertion of pairs. + template + void insert(InputIt I, InputIt E) { + for (; I != E; ++I) + insert(*I); + } + + + bool erase(const KeyT &Val) { + BucketT *TheBucket; + if (!LookupBucketFor(Val, TheBucket)) + return false; // not in map. + + TheBucket->second.~ValueT(); + TheBucket->first = getTombstoneKey(); + --NumEntries; + ++NumTombstones; + return true; + } + bool erase(iterator I) { + BucketT *TheBucket = &*I; + TheBucket->second.~ValueT(); + TheBucket->first = getTombstoneKey(); + --NumEntries; + ++NumTombstones; + return true; + } + + value_type& FindAndConstruct(const KeyT &Key) { + BucketT *TheBucket; + if (LookupBucketFor(Key, TheBucket)) + return *TheBucket; + + return *InsertIntoBucket(Key, ValueT(), TheBucket); + } + + ValueT &operator[](const KeyT &Key) { + return FindAndConstruct(Key).second; + } + + DenseMap& operator=(const DenseMap& other) { + CopyFrom(other); + return *this; + } + + /// isPointerIntoBucketsArray - Return true if the specified pointer points + /// somewhere into the DenseMap's array of buckets (i.e. either to a key or + /// value in the DenseMap). + bool isPointerIntoBucketsArray(const void *Ptr) const { + return Ptr >= Buckets && Ptr < Buckets+NumBuckets; + } + + /// getPointerIntoBucketsArray() - Return an opaque pointer into the buckets + /// array. In conjunction with the previous method, this can be used to + /// determine whether an insertion caused the DenseMap to reallocate. + const void *getPointerIntoBucketsArray() const { return Buckets; } + +private: + void CopyFrom(const DenseMap& other) { + if (NumBuckets != 0 && (!KeyInfoT::isPod() || !ValueInfoT::isPod())) { + const KeyT EmptyKey = getEmptyKey(), TombstoneKey = getTombstoneKey(); + for (BucketT *P = Buckets, *E = Buckets+NumBuckets; P != E; ++P) { + if (!KeyInfoT::isEqual(P->first, EmptyKey) && + !KeyInfoT::isEqual(P->first, TombstoneKey)) + P->second.~ValueT(); + P->first.~KeyT(); + } + } + + NumEntries = other.NumEntries; + NumTombstones = other.NumTombstones; + + if (NumBuckets) { +#ifndef NDEBUG + memset(Buckets, 0x5a, sizeof(BucketT)*NumBuckets); +#endif + operator delete(Buckets); + } + Buckets = static_cast(operator new(sizeof(BucketT) * + other.NumBuckets)); + + if (KeyInfoT::isPod() && ValueInfoT::isPod()) + memcpy(Buckets, other.Buckets, other.NumBuckets * sizeof(BucketT)); + else + for (size_t i = 0; i < other.NumBuckets; ++i) { + new (&Buckets[i].first) KeyT(other.Buckets[i].first); + if (!KeyInfoT::isEqual(Buckets[i].first, getEmptyKey()) && + !KeyInfoT::isEqual(Buckets[i].first, getTombstoneKey())) + new (&Buckets[i].second) ValueT(other.Buckets[i].second); + } + NumBuckets = other.NumBuckets; + } + + BucketT *InsertIntoBucket(const KeyT &Key, const ValueT &Value, + BucketT *TheBucket) { + // If the load of the hash table is more than 3/4, or if fewer than 1/8 of + // the buckets are empty (meaning that many are filled with tombstones), + // grow the table. + // + // The later case is tricky. For example, if we had one empty bucket with + // tons of tombstones, failing lookups (e.g. for insertion) would have to + // probe almost the entire table until it found the empty bucket. If the + // table completely filled with tombstones, no lookup would ever succeed, + // causing infinite loops in lookup. + ++NumEntries; + if (NumEntries*4 >= NumBuckets*3 || + NumBuckets-(NumEntries+NumTombstones) < NumBuckets/8) { + this->grow(NumBuckets * 2); + LookupBucketFor(Key, TheBucket); + } + + // If we are writing over a tombstone, remember this. + if (!KeyInfoT::isEqual(TheBucket->first, getEmptyKey())) + --NumTombstones; + + TheBucket->first = Key; + new (&TheBucket->second) ValueT(Value); + return TheBucket; + } + + static unsigned getHashValue(const KeyT &Val) { + return KeyInfoT::getHashValue(Val); + } + static const KeyT getEmptyKey() { + return KeyInfoT::getEmptyKey(); + } + static const KeyT getTombstoneKey() { + return KeyInfoT::getTombstoneKey(); + } + + /// LookupBucketFor - Lookup the appropriate bucket for Val, returning it in + /// FoundBucket. If the bucket contains the key and a value, this returns + /// true, otherwise it returns a bucket with an empty marker or tombstone and + /// returns false. + bool LookupBucketFor(const KeyT &Val, BucketT *&FoundBucket) const { + unsigned BucketNo = getHashValue(Val); + unsigned ProbeAmt = 1; + BucketT *BucketsPtr = Buckets; + + // FoundTombstone - Keep track of whether we find a tombstone while probing. + BucketT *FoundTombstone = 0; + const KeyT EmptyKey = getEmptyKey(); + const KeyT TombstoneKey = getTombstoneKey(); + assert(!KeyInfoT::isEqual(Val, EmptyKey) && + !KeyInfoT::isEqual(Val, TombstoneKey) && + "Empty/Tombstone value shouldn't be inserted into map!"); + + while (1) { + BucketT *ThisBucket = BucketsPtr + (BucketNo & (NumBuckets-1)); + // Found Val's bucket? If so, return it. + if (KeyInfoT::isEqual(ThisBucket->first, Val)) { + FoundBucket = ThisBucket; + return true; + } + + // If we found an empty bucket, the key doesn't exist in the set. + // Insert it and return the default value. + if (KeyInfoT::isEqual(ThisBucket->first, EmptyKey)) { + // If we've already seen a tombstone while probing, fill it in instead + // of the empty bucket we eventually probed to. + if (FoundTombstone) ThisBucket = FoundTombstone; + FoundBucket = FoundTombstone ? FoundTombstone : ThisBucket; + return false; + } + + // If this is a tombstone, remember it. If Val ends up not in the map, we + // prefer to return it than something that would require more probing. + if (KeyInfoT::isEqual(ThisBucket->first, TombstoneKey) && !FoundTombstone) + FoundTombstone = ThisBucket; // Remember the first tombstone found. + + // Otherwise, it's a hash collision or a tombstone, continue quadratic + // probing. + BucketNo += ProbeAmt++; + } + } + + void init(unsigned InitBuckets) { + NumEntries = 0; + NumTombstones = 0; + NumBuckets = InitBuckets; + assert(InitBuckets && (InitBuckets & (InitBuckets-1)) == 0 && + "# initial buckets must be a power of two!"); + Buckets = static_cast(operator new(sizeof(BucketT)*InitBuckets)); + // Initialize all the keys to EmptyKey. + const KeyT EmptyKey = getEmptyKey(); + for (unsigned i = 0; i != InitBuckets; ++i) + new (&Buckets[i].first) KeyT(EmptyKey); + } + + void grow(unsigned AtLeast) { + unsigned OldNumBuckets = NumBuckets; + BucketT *OldBuckets = Buckets; + + // Double the number of buckets. + while (NumBuckets <= AtLeast) + NumBuckets <<= 1; + NumTombstones = 0; + Buckets = static_cast(operator new(sizeof(BucketT)*NumBuckets)); + + // Initialize all the keys to EmptyKey. + const KeyT EmptyKey = getEmptyKey(); + for (unsigned i = 0, e = NumBuckets; i != e; ++i) + new (&Buckets[i].first) KeyT(EmptyKey); + + // Insert all the old elements. + const KeyT TombstoneKey = getTombstoneKey(); + for (BucketT *B = OldBuckets, *E = OldBuckets+OldNumBuckets; B != E; ++B) { + if (!KeyInfoT::isEqual(B->first, EmptyKey) && + !KeyInfoT::isEqual(B->first, TombstoneKey)) { + // Insert the key/value into the new table. + BucketT *DestBucket; + bool FoundVal = LookupBucketFor(B->first, DestBucket); + FoundVal = FoundVal; // silence warning. + assert(!FoundVal && "Key already in new map?"); + DestBucket->first = B->first; + new (&DestBucket->second) ValueT(B->second); + + // Free the value. + B->second.~ValueT(); + } + B->first.~KeyT(); + } + +#ifndef NDEBUG + memset(OldBuckets, 0x5a, sizeof(BucketT)*OldNumBuckets); +#endif + // Free the old table. + operator delete(OldBuckets); + } + + void shrink_and_clear() { + unsigned OldNumBuckets = NumBuckets; + BucketT *OldBuckets = Buckets; + + // Reduce the number of buckets. + NumBuckets = NumEntries > 32 ? 1 << (Log2_32_Ceil(NumEntries) + 1) + : 64; + NumTombstones = 0; + Buckets = static_cast(operator new(sizeof(BucketT)*NumBuckets)); + + // Initialize all the keys to EmptyKey. + const KeyT EmptyKey = getEmptyKey(); + for (unsigned i = 0, e = NumBuckets; i != e; ++i) + new (&Buckets[i].first) KeyT(EmptyKey); + + // Free the old buckets. + const KeyT TombstoneKey = getTombstoneKey(); + for (BucketT *B = OldBuckets, *E = OldBuckets+OldNumBuckets; B != E; ++B) { + if (!KeyInfoT::isEqual(B->first, EmptyKey) && + !KeyInfoT::isEqual(B->first, TombstoneKey)) { + // Free the value. + B->second.~ValueT(); + } + B->first.~KeyT(); + } + +#ifndef NDEBUG + memset(OldBuckets, 0x5a, sizeof(BucketT)*OldNumBuckets); +#endif + // Free the old table. + operator delete(OldBuckets); + + NumEntries = 0; + } +}; + +template +class DenseMapIterator { + typedef std::pair Bucket; + typedef DenseMapIterator ConstIterator; + friend class DenseMapIterator; +public: + typedef ptrdiff_t difference_type; + typedef typename conditional::type value_type; + typedef value_type *pointer; + typedef value_type &reference; + typedef std::forward_iterator_tag iterator_category; +private: + pointer Ptr, End; +public: + DenseMapIterator() : Ptr(0), End(0) {} + + DenseMapIterator(pointer Pos, pointer E) : Ptr(Pos), End(E) { + AdvancePastEmptyBuckets(); + } + + // If IsConst is true this is a converting constructor from iterator to + // const_iterator and the default copy constructor is used. + // Otherwise this is a copy constructor for iterator. + DenseMapIterator(const DenseMapIterator& I) + : Ptr(I.Ptr), End(I.End) {} + + reference operator*() const { + return *Ptr; + } + pointer operator->() const { + return Ptr; + } + + bool operator==(const ConstIterator &RHS) const { + return Ptr == RHS.operator->(); + } + bool operator!=(const ConstIterator &RHS) const { + return Ptr != RHS.operator->(); + } + + inline DenseMapIterator& operator++() { // Preincrement + ++Ptr; + AdvancePastEmptyBuckets(); + return *this; + } + DenseMapIterator operator++(int) { // Postincrement + DenseMapIterator tmp = *this; ++*this; return tmp; + } + +private: + void AdvancePastEmptyBuckets() { + const KeyT Empty = KeyInfoT::getEmptyKey(); + const KeyT Tombstone = KeyInfoT::getTombstoneKey(); + + while (Ptr != End && + (KeyInfoT::isEqual(Ptr->first, Empty) || + KeyInfoT::isEqual(Ptr->first, Tombstone))) + ++Ptr; + } +}; + +} // end namespace llvm + +#endif diff --git a/libclamav/c++/llvm/include/llvm/ADT/DenseMapInfo.h b/libclamav/c++/llvm/include/llvm/ADT/DenseMapInfo.h new file mode 100644 index 000000000..2f241c514 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/ADT/DenseMapInfo.h @@ -0,0 +1,135 @@ +//===- llvm/ADT/DenseMapInfo.h - Type traits for DenseMap -------*- 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 DenseMapInfo traits for DenseMap. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_DENSEMAPINFO_H +#define LLVM_ADT_DENSEMAPINFO_H + +#include "llvm/Support/PointerLikeTypeTraits.h" +#include + +namespace llvm { + +template +struct DenseMapInfo { + //static inline T getEmptyKey(); + //static inline T getTombstoneKey(); + //static unsigned getHashValue(const T &Val); + //static bool isEqual(const T &LHS, const T &RHS); + //static bool isPod() +}; + +// Provide DenseMapInfo for all pointers. +template +struct DenseMapInfo { + static inline T* getEmptyKey() { + intptr_t Val = -1; + Val <<= PointerLikeTypeTraits::NumLowBitsAvailable; + return reinterpret_cast(Val); + } + static inline T* getTombstoneKey() { + intptr_t Val = -2; + Val <<= PointerLikeTypeTraits::NumLowBitsAvailable; + return reinterpret_cast(Val); + } + static unsigned getHashValue(const T *PtrVal) { + return (unsigned((uintptr_t)PtrVal) >> 4) ^ + (unsigned((uintptr_t)PtrVal) >> 9); + } + static bool isEqual(const T *LHS, const T *RHS) { return LHS == RHS; } + static bool isPod() { return true; } +}; + +// Provide DenseMapInfo for chars. +template<> struct DenseMapInfo { + static inline char getEmptyKey() { return ~0; } + static inline char getTombstoneKey() { return ~0 - 1; } + static unsigned getHashValue(const char& Val) { return Val * 37; } + static bool isPod() { return true; } + static bool isEqual(const char &LHS, const char &RHS) { + return LHS == RHS; + } +}; + +// Provide DenseMapInfo for unsigned ints. +template<> struct DenseMapInfo { + static inline unsigned getEmptyKey() { return ~0; } + static inline unsigned getTombstoneKey() { return ~0U - 1; } + static unsigned getHashValue(const unsigned& Val) { return Val * 37; } + static bool isPod() { return true; } + static bool isEqual(const unsigned& LHS, const unsigned& RHS) { + return LHS == RHS; + } +}; + +// Provide DenseMapInfo for unsigned longs. +template<> struct DenseMapInfo { + static inline unsigned long getEmptyKey() { return ~0UL; } + static inline unsigned long getTombstoneKey() { return ~0UL - 1L; } + static unsigned getHashValue(const unsigned long& Val) { + return (unsigned)(Val * 37UL); + } + static bool isPod() { return true; } + static bool isEqual(const unsigned long& LHS, const unsigned long& RHS) { + return LHS == RHS; + } +}; + +// Provide DenseMapInfo for unsigned long longs. +template<> struct DenseMapInfo { + static inline unsigned long long getEmptyKey() { return ~0ULL; } + static inline unsigned long long getTombstoneKey() { return ~0ULL - 1ULL; } + static unsigned getHashValue(const unsigned long long& Val) { + return (unsigned)(Val * 37ULL); + } + static bool isPod() { return true; } + static bool isEqual(const unsigned long long& LHS, + const unsigned long long& RHS) { + return LHS == RHS; + } +}; + +// Provide DenseMapInfo for all pairs whose members have info. +template +struct DenseMapInfo > { + typedef std::pair Pair; + typedef DenseMapInfo FirstInfo; + typedef DenseMapInfo SecondInfo; + + static inline Pair getEmptyKey() { + return std::make_pair(FirstInfo::getEmptyKey(), + SecondInfo::getEmptyKey()); + } + static inline Pair getTombstoneKey() { + return std::make_pair(FirstInfo::getTombstoneKey(), + SecondInfo::getEmptyKey()); + } + static unsigned getHashValue(const Pair& PairVal) { + uint64_t key = (uint64_t)FirstInfo::getHashValue(PairVal.first) << 32 + | (uint64_t)SecondInfo::getHashValue(PairVal.second); + key += ~(key << 32); + key ^= (key >> 22); + key += ~(key << 13); + key ^= (key >> 8); + key += (key << 3); + key ^= (key >> 15); + key += ~(key << 27); + key ^= (key >> 31); + return (unsigned)key; + } + static bool isEqual(const Pair& LHS, const Pair& RHS) { return LHS == RHS; } + static bool isPod() { return FirstInfo::isPod() && SecondInfo::isPod(); } +}; + +} // end namespace llvm + +#endif diff --git a/libclamav/c++/llvm/include/llvm/ADT/DenseSet.h b/libclamav/c++/llvm/include/llvm/ADT/DenseSet.h new file mode 100644 index 000000000..ce7344bc1 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/ADT/DenseSet.h @@ -0,0 +1,104 @@ +//===- llvm/ADT/DenseSet.h - Dense probed hash table ------------*- 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 the DenseSet class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_DENSESET_H +#define LLVM_ADT_DENSESET_H + +#include "llvm/ADT/DenseMap.h" + +namespace llvm { + +/// DenseSet - This implements a dense probed hash-table based set. +/// +/// FIXME: This is currently implemented directly in terms of DenseMap, this +/// should be optimized later if there is a need. +template > +class DenseSet { + typedef DenseMap MapTy; + MapTy TheMap; +public: + DenseSet(const DenseSet &Other) : TheMap(Other.TheMap) {} + explicit DenseSet(unsigned NumInitBuckets = 64) : TheMap(NumInitBuckets) {} + + bool empty() const { return TheMap.empty(); } + unsigned size() const { return TheMap.size(); } + + void clear() { + TheMap.clear(); + } + + bool count(const ValueT &V) const { + return TheMap.count(V); + } + + void erase(const ValueT &V) { + TheMap.erase(V); + } + + DenseSet &operator=(const DenseSet &RHS) { + TheMap = RHS.TheMap; + return *this; + } + + // Iterators. + + class Iterator { + typename MapTy::iterator I; + public: + Iterator(const typename MapTy::iterator &i) : I(i) {} + + ValueT& operator*() { return I->first; } + ValueT* operator->() { return &I->first; } + + Iterator& operator++() { ++I; return *this; }; + bool operator==(const Iterator& X) const { return I == X.I; } + bool operator!=(const Iterator& X) const { return I != X.I; } + }; + + class ConstIterator { + typename MapTy::const_iterator I; + public: + ConstIterator(const typename MapTy::const_iterator &i) : I(i) {} + + const ValueT& operator*() { return I->first; } + const ValueT* operator->() { return &I->first; } + + ConstIterator& operator++() { ++I; return *this; }; + bool operator==(const ConstIterator& X) const { return I == X.I; } + bool operator!=(const ConstIterator& X) const { return I != X.I; } + }; + + typedef Iterator iterator; + typedef ConstIterator const_iterator; + + iterator begin() { return Iterator(TheMap.begin()); } + iterator end() { return Iterator(TheMap.end()); } + + const_iterator begin() const { return ConstIterator(TheMap.begin()); } + const_iterator end() const { return ConstIterator(TheMap.end()); } + + std::pair insert(const ValueT &V) { + return TheMap.insert(std::make_pair(V, 0)); + } + + // Range insertion of values. + template + void insert(InputIt I, InputIt E) { + for (; I != E; ++I) + insert(*I); + } +}; + +} // end namespace llvm + +#endif diff --git a/libclamav/c++/llvm/include/llvm/ADT/DepthFirstIterator.h b/libclamav/c++/llvm/include/llvm/ADT/DepthFirstIterator.h new file mode 100644 index 000000000..5f2df2a17 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/ADT/DepthFirstIterator.h @@ -0,0 +1,259 @@ +//===- llvm/ADT/DepthFirstIterator.h - Depth First iterator -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file builds on the ADT/GraphTraits.h file to build generic depth +// first graph iterator. This file exposes the following functions/types: +// +// df_begin/df_end/df_iterator +// * Normal depth-first iteration - visit a node and then all of its children. +// +// idf_begin/idf_end/idf_iterator +// * Depth-first iteration on the 'inverse' graph. +// +// df_ext_begin/df_ext_end/df_ext_iterator +// * Normal depth-first iteration - visit a node and then all of its children. +// This iterator stores the 'visited' set in an external set, which allows +// it to be more efficient, and allows external clients to use the set for +// other purposes. +// +// idf_ext_begin/idf_ext_end/idf_ext_iterator +// * Depth-first iteration on the 'inverse' graph. +// This iterator stores the 'visited' set in an external set, which allows +// it to be more efficient, and allows external clients to use the set for +// other purposes. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_DEPTHFIRSTITERATOR_H +#define LLVM_ADT_DEPTHFIRSTITERATOR_H + +#include "llvm/ADT/GraphTraits.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/PointerIntPair.h" +#include +#include + +namespace llvm { + +// df_iterator_storage - A private class which is used to figure out where to +// store the visited set. +template // Non-external set +class df_iterator_storage { +public: + SetType Visited; +}; + +template +class df_iterator_storage { +public: + df_iterator_storage(SetType &VSet) : Visited(VSet) {} + df_iterator_storage(const df_iterator_storage &S) : Visited(S.Visited) {} + SetType &Visited; +}; + + +// Generic Depth First Iterator +template::NodeType*, 8>, + bool ExtStorage = false, class GT = GraphTraits > +class df_iterator : public std::iterator, + public df_iterator_storage { + typedef std::iterator super; + + typedef typename GT::NodeType NodeType; + typedef typename GT::ChildIteratorType ChildItTy; + typedef PointerIntPair PointerIntTy; + + // VisitStack - Used to maintain the ordering. Top = current block + // First element is node pointer, second is the 'next child' to visit + // if the int in PointerIntTy is 0, the 'next child' to visit is invalid + std::vector > VisitStack; +private: + inline df_iterator(NodeType *Node) { + this->Visited.insert(Node); + VisitStack.push_back(std::make_pair(PointerIntTy(Node, 0), + GT::child_begin(Node))); + } + inline df_iterator() { + // End is when stack is empty + } + inline df_iterator(NodeType *Node, SetType &S) + : df_iterator_storage(S) { + if (!S.count(Node)) { + VisitStack.push_back(std::make_pair(PointerIntTy(Node, 0), + GT::child_begin(Node))); + this->Visited.insert(Node); + } + } + inline df_iterator(SetType &S) + : df_iterator_storage(S) { + // End is when stack is empty + } + + inline void toNext() { + do { + std::pair &Top = VisitStack.back(); + NodeType *Node = Top.first.getPointer(); + ChildItTy &It = Top.second; + if (!Top.first.getInt()) { + // now retrieve the real begin of the children before we dive in + It = GT::child_begin(Node); + Top.first.setInt(1); + } + + while (It != GT::child_end(Node)) { + NodeType *Next = *It++; + // Has our next sibling been visited? + if (Next && !this->Visited.count(Next)) { + // No, do it now. + this->Visited.insert(Next); + VisitStack.push_back(std::make_pair(PointerIntTy(Next, 0), + GT::child_begin(Next))); + return; + } + } + + // Oops, ran out of successors... go up a level on the stack. + VisitStack.pop_back(); + } while (!VisitStack.empty()); + } + +public: + typedef typename super::pointer pointer; + typedef df_iterator _Self; + + // Provide static begin and end methods as our public "constructors" + static inline _Self begin(const GraphT& G) { + return _Self(GT::getEntryNode(G)); + } + static inline _Self end(const GraphT& G) { return _Self(); } + + // Static begin and end methods as our public ctors for external iterators + static inline _Self begin(const GraphT& G, SetType &S) { + return _Self(GT::getEntryNode(G), S); + } + static inline _Self end(const GraphT& G, SetType &S) { return _Self(S); } + + inline bool operator==(const _Self& x) const { + return VisitStack.size() == x.VisitStack.size() && + VisitStack == x.VisitStack; + } + inline bool operator!=(const _Self& x) const { return !operator==(x); } + + inline pointer operator*() const { + return VisitStack.back().first.getPointer(); + } + + // This is a nonstandard operator-> that dereferences the pointer an extra + // time... so that you can actually call methods ON the Node, because + // the contained type is a pointer. This allows BBIt->getTerminator() f.e. + // + inline NodeType *operator->() const { return operator*(); } + + inline _Self& operator++() { // Preincrement + toNext(); + return *this; + } + + // skips all children of the current node and traverses to next node + // + inline _Self& skipChildren() { + VisitStack.pop_back(); + if (!VisitStack.empty()) + toNext(); + return *this; + } + + inline _Self operator++(int) { // Postincrement + _Self tmp = *this; ++*this; return tmp; + } + + // nodeVisited - return true if this iterator has already visited the + // specified node. This is public, and will probably be used to iterate over + // nodes that a depth first iteration did not find: ie unreachable nodes. + // + inline bool nodeVisited(NodeType *Node) const { + return this->Visited.count(Node) != 0; + } +}; + + +// Provide global constructors that automatically figure out correct types... +// +template +df_iterator df_begin(const T& G) { + return df_iterator::begin(G); +} + +template +df_iterator df_end(const T& G) { + return df_iterator::end(G); +} + +// Provide global definitions of external depth first iterators... +template ::NodeType*> > +struct df_ext_iterator : public df_iterator { + df_ext_iterator(const df_iterator &V) + : df_iterator(V) {} +}; + +template +df_ext_iterator df_ext_begin(const T& G, SetTy &S) { + return df_ext_iterator::begin(G, S); +} + +template +df_ext_iterator df_ext_end(const T& G, SetTy &S) { + return df_ext_iterator::end(G, S); +} + + +// Provide global definitions of inverse depth first iterators... +template ::NodeType*, 8>, + bool External = false> +struct idf_iterator : public df_iterator, SetTy, External> { + idf_iterator(const df_iterator, SetTy, External> &V) + : df_iterator, SetTy, External>(V) {} +}; + +template +idf_iterator idf_begin(const T& G) { + return idf_iterator::begin(Inverse(G)); +} + +template +idf_iterator idf_end(const T& G){ + return idf_iterator::end(Inverse(G)); +} + +// Provide global definitions of external inverse depth first iterators... +template ::NodeType*> > +struct idf_ext_iterator : public idf_iterator { + idf_ext_iterator(const idf_iterator &V) + : idf_iterator(V) {} + idf_ext_iterator(const df_iterator, SetTy, true> &V) + : idf_iterator(V) {} +}; + +template +idf_ext_iterator idf_ext_begin(const T& G, SetTy &S) { + return idf_ext_iterator::begin(Inverse(G), S); +} + +template +idf_ext_iterator idf_ext_end(const T& G, SetTy &S) { + return idf_ext_iterator::end(Inverse(G), S); +} + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/ADT/EquivalenceClasses.h b/libclamav/c++/llvm/include/llvm/ADT/EquivalenceClasses.h new file mode 100644 index 000000000..f5f3d496f --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/ADT/EquivalenceClasses.h @@ -0,0 +1,280 @@ +//===-- llvm/ADT/EquivalenceClasses.h - Generic Equiv. Classes --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Generic implementation of equivalence classes through the use Tarjan's +// efficient union-find algorithm. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_EQUIVALENCECLASSES_H +#define LLVM_ADT_EQUIVALENCECLASSES_H + +#include "llvm/System/DataTypes.h" +#include + +namespace llvm { + +/// EquivalenceClasses - This represents a collection of equivalence classes and +/// supports three efficient operations: insert an element into a class of its +/// own, union two classes, and find the class for a given element. In +/// addition to these modification methods, it is possible to iterate over all +/// of the equivalence classes and all of the elements in a class. +/// +/// This implementation is an efficient implementation that only stores one copy +/// of the element being indexed per entry in the set, and allows any arbitrary +/// type to be indexed (as long as it can be ordered with operator<). +/// +/// Here is a simple example using integers: +/// +/// EquivalenceClasses EC; +/// EC.unionSets(1, 2); // insert 1, 2 into the same set +/// EC.insert(4); EC.insert(5); // insert 4, 5 into own sets +/// EC.unionSets(5, 1); // merge the set for 1 with 5's set. +/// +/// for (EquivalenceClasses::iterator I = EC.begin(), E = EC.end(); +/// I != E; ++I) { // Iterate over all of the equivalence sets. +/// if (!I->isLeader()) continue; // Ignore non-leader sets. +/// for (EquivalenceClasses::member_iterator MI = EC.member_begin(I); +/// MI != EC.member_end(); ++MI) // Loop over members in this set. +/// cerr << *MI << " "; // Print member. +/// cerr << "\n"; // Finish set. +/// } +/// +/// This example prints: +/// 4 +/// 5 1 2 +/// +template +class EquivalenceClasses { + /// ECValue - The EquivalenceClasses data structure is just a set of these. + /// Each of these represents a relation for a value. First it stores the + /// value itself, which provides the ordering that the set queries. Next, it + /// provides a "next pointer", which is used to enumerate all of the elements + /// in the unioned set. Finally, it defines either a "end of list pointer" or + /// "leader pointer" depending on whether the value itself is a leader. A + /// "leader pointer" points to the node that is the leader for this element, + /// if the node is not a leader. A "end of list pointer" points to the last + /// node in the list of members of this list. Whether or not a node is a + /// leader is determined by a bit stolen from one of the pointers. + class ECValue { + friend class EquivalenceClasses; + mutable const ECValue *Leader, *Next; + ElemTy Data; + // ECValue ctor - Start out with EndOfList pointing to this node, Next is + // Null, isLeader = true. + ECValue(const ElemTy &Elt) + : Leader(this), Next((ECValue*)(intptr_t)1), Data(Elt) {} + + const ECValue *getLeader() const { + if (isLeader()) return this; + if (Leader->isLeader()) return Leader; + // Path compression. + return Leader = Leader->getLeader(); + } + const ECValue *getEndOfList() const { + assert(isLeader() && "Cannot get the end of a list for a non-leader!"); + return Leader; + } + + void setNext(const ECValue *NewNext) const { + assert(getNext() == 0 && "Already has a next pointer!"); + Next = (const ECValue*)((intptr_t)NewNext | (intptr_t)isLeader()); + } + public: + ECValue(const ECValue &RHS) : Leader(this), Next((ECValue*)(intptr_t)1), + Data(RHS.Data) { + // Only support copying of singleton nodes. + assert(RHS.isLeader() && RHS.getNext() == 0 && "Not a singleton!"); + } + + bool operator<(const ECValue &UFN) const { return Data < UFN.Data; } + + bool isLeader() const { return (intptr_t)Next & 1; } + const ElemTy &getData() const { return Data; } + + const ECValue *getNext() const { + return (ECValue*)((intptr_t)Next & ~(intptr_t)1); + } + + template + bool operator<(const T &Val) const { return Data < Val; } + }; + + /// TheMapping - This implicitly provides a mapping from ElemTy values to the + /// ECValues, it just keeps the key as part of the value. + std::set TheMapping; + +public: + EquivalenceClasses() {} + EquivalenceClasses(const EquivalenceClasses &RHS) { + operator=(RHS); + } + + const EquivalenceClasses &operator=(const EquivalenceClasses &RHS) { + TheMapping.clear(); + for (iterator I = RHS.begin(), E = RHS.end(); I != E; ++I) + if (I->isLeader()) { + member_iterator MI = RHS.member_begin(I); + member_iterator LeaderIt = member_begin(insert(*MI)); + for (++MI; MI != member_end(); ++MI) + unionSets(LeaderIt, member_begin(insert(*MI))); + } + return *this; + } + + //===--------------------------------------------------------------------===// + // Inspection methods + // + + /// iterator* - Provides a way to iterate over all values in the set. + typedef typename std::set::const_iterator iterator; + iterator begin() const { return TheMapping.begin(); } + iterator end() const { return TheMapping.end(); } + + bool empty() const { return TheMapping.empty(); } + + /// member_* Iterate over the members of an equivalence class. + /// + class member_iterator; + member_iterator member_begin(iterator I) const { + // Only leaders provide anything to iterate over. + return member_iterator(I->isLeader() ? &*I : 0); + } + member_iterator member_end() const { + return member_iterator(0); + } + + /// findValue - Return an iterator to the specified value. If it does not + /// exist, end() is returned. + iterator findValue(const ElemTy &V) const { + return TheMapping.find(V); + } + + /// getLeaderValue - Return the leader for the specified value that is in the + /// set. It is an error to call this method for a value that is not yet in + /// the set. For that, call getOrInsertLeaderValue(V). + const ElemTy &getLeaderValue(const ElemTy &V) const { + member_iterator MI = findLeader(V); + assert(MI != member_end() && "Value is not in the set!"); + return *MI; + } + + /// getOrInsertLeaderValue - Return the leader for the specified value that is + /// in the set. If the member is not in the set, it is inserted, then + /// returned. + const ElemTy &getOrInsertLeaderValue(const ElemTy &V) const { + member_iterator MI = findLeader(insert(V)); + assert(MI != member_end() && "Value is not in the set!"); + return *MI; + } + + /// getNumClasses - Return the number of equivalence classes in this set. + /// Note that this is a linear time operation. + unsigned getNumClasses() const { + unsigned NC = 0; + for (iterator I = begin(), E = end(); I != E; ++I) + if (I->isLeader()) ++NC; + return NC; + } + + + //===--------------------------------------------------------------------===// + // Mutation methods + + /// insert - Insert a new value into the union/find set, ignoring the request + /// if the value already exists. + iterator insert(const ElemTy &Data) { + return TheMapping.insert(Data).first; + } + + /// findLeader - Given a value in the set, return a member iterator for the + /// equivalence class it is in. This does the path-compression part that + /// makes union-find "union findy". This returns an end iterator if the value + /// is not in the equivalence class. + /// + member_iterator findLeader(iterator I) const { + if (I == TheMapping.end()) return member_end(); + return member_iterator(I->getLeader()); + } + member_iterator findLeader(const ElemTy &V) const { + return findLeader(TheMapping.find(V)); + } + + + /// union - Merge the two equivalence sets for the specified values, inserting + /// them if they do not already exist in the equivalence set. + member_iterator unionSets(const ElemTy &V1, const ElemTy &V2) { + iterator V1I = insert(V1), V2I = insert(V2); + return unionSets(findLeader(V1I), findLeader(V2I)); + } + member_iterator unionSets(member_iterator L1, member_iterator L2) { + assert(L1 != member_end() && L2 != member_end() && "Illegal inputs!"); + if (L1 == L2) return L1; // Unifying the same two sets, noop. + + // Otherwise, this is a real union operation. Set the end of the L1 list to + // point to the L2 leader node. + const ECValue &L1LV = *L1.Node, &L2LV = *L2.Node; + L1LV.getEndOfList()->setNext(&L2LV); + + // Update L1LV's end of list pointer. + L1LV.Leader = L2LV.getEndOfList(); + + // Clear L2's leader flag: + L2LV.Next = L2LV.getNext(); + + // L2's leader is now L1. + L2LV.Leader = &L1LV; + return L1; + } + + class member_iterator : public std::iterator { + typedef std::iterator super; + const ECValue *Node; + friend class EquivalenceClasses; + public: + typedef size_t size_type; + typedef typename super::pointer pointer; + typedef typename super::reference reference; + + explicit member_iterator() {} + explicit member_iterator(const ECValue *N) : Node(N) {} + member_iterator(const member_iterator &I) : Node(I.Node) {} + + reference operator*() const { + assert(Node != 0 && "Dereferencing end()!"); + return Node->getData(); + } + reference operator->() const { return operator*(); } + + member_iterator &operator++() { + assert(Node != 0 && "++'d off the end of the list!"); + Node = Node->getNext(); + return *this; + } + + member_iterator operator++(int) { // postincrement operators. + member_iterator tmp = *this; + ++*this; + return tmp; + } + + bool operator==(const member_iterator &RHS) const { + return Node == RHS.Node; + } + bool operator!=(const member_iterator &RHS) const { + return Node != RHS.Node; + } + }; +}; + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/ADT/FoldingSet.h b/libclamav/c++/llvm/include/llvm/ADT/FoldingSet.h new file mode 100644 index 000000000..81dc46929 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/ADT/FoldingSet.h @@ -0,0 +1,472 @@ +//===-- llvm/ADT/FoldingSet.h - Uniquing Hash Set ---------------*- 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 a hash set that can be used to remove duplication of nodes +// in a graph. This code was originally created by Chris Lattner for use with +// SelectionDAGCSEMap, but was isolated to provide use across the llvm code set. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_FOLDINGSET_H +#define LLVM_ADT_FOLDINGSET_H + +#include "llvm/System/DataTypes.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" + +namespace llvm { + class APFloat; + class APInt; + +/// This folding set used for two purposes: +/// 1. Given information about a node we want to create, look up the unique +/// instance of the node in the set. If the node already exists, return +/// it, otherwise return the bucket it should be inserted into. +/// 2. Given a node that has already been created, remove it from the set. +/// +/// This class is implemented as a single-link chained hash table, where the +/// "buckets" are actually the nodes themselves (the next pointer is in the +/// node). The last node points back to the bucket to simplify node removal. +/// +/// Any node that is to be included in the folding set must be a subclass of +/// FoldingSetNode. The node class must also define a Profile method used to +/// establish the unique bits of data for the node. The Profile method is +/// passed a FoldingSetNodeID object which is used to gather the bits. Just +/// call one of the Add* functions defined in the FoldingSetImpl::NodeID class. +/// NOTE: That the folding set does not own the nodes and it is the +/// responsibility of the user to dispose of the nodes. +/// +/// Eg. +/// class MyNode : public FoldingSetNode { +/// private: +/// std::string Name; +/// unsigned Value; +/// public: +/// MyNode(const char *N, unsigned V) : Name(N), Value(V) {} +/// ... +/// void Profile(FoldingSetNodeID &ID) const { +/// ID.AddString(Name); +/// ID.AddInteger(Value); +/// } +/// ... +/// }; +/// +/// To define the folding set itself use the FoldingSet template; +/// +/// Eg. +/// FoldingSet MyFoldingSet; +/// +/// Four public methods are available to manipulate the folding set; +/// +/// 1) If you have an existing node that you want add to the set but unsure +/// that the node might already exist then call; +/// +/// MyNode *M = MyFoldingSet.GetOrInsertNode(N); +/// +/// If The result is equal to the input then the node has been inserted. +/// Otherwise, the result is the node existing in the folding set, and the +/// input can be discarded (use the result instead.) +/// +/// 2) If you are ready to construct a node but want to check if it already +/// exists, then call FindNodeOrInsertPos with a FoldingSetNodeID of the bits to +/// check; +/// +/// FoldingSetNodeID ID; +/// ID.AddString(Name); +/// ID.AddInteger(Value); +/// void *InsertPoint; +/// +/// MyNode *M = MyFoldingSet.FindNodeOrInsertPos(ID, InsertPoint); +/// +/// If found then M with be non-NULL, else InsertPoint will point to where it +/// should be inserted using InsertNode. +/// +/// 3) If you get a NULL result from FindNodeOrInsertPos then you can as a new +/// node with FindNodeOrInsertPos; +/// +/// InsertNode(N, InsertPoint); +/// +/// 4) Finally, if you want to remove a node from the folding set call; +/// +/// bool WasRemoved = RemoveNode(N); +/// +/// The result indicates whether the node existed in the folding set. + +class FoldingSetNodeID; + +//===----------------------------------------------------------------------===// +/// FoldingSetImpl - Implements the folding set functionality. The main +/// structure is an array of buckets. Each bucket is indexed by the hash of +/// the nodes it contains. The bucket itself points to the nodes contained +/// in the bucket via a singly linked list. The last node in the list points +/// back to the bucket to facilitate node removal. +/// +class FoldingSetImpl { +protected: + /// Buckets - Array of bucket chains. + /// + void **Buckets; + + /// NumBuckets - Length of the Buckets array. Always a power of 2. + /// + unsigned NumBuckets; + + /// NumNodes - Number of nodes in the folding set. Growth occurs when NumNodes + /// is greater than twice the number of buckets. + unsigned NumNodes; + +public: + explicit FoldingSetImpl(unsigned Log2InitSize = 6); + virtual ~FoldingSetImpl(); + + //===--------------------------------------------------------------------===// + /// Node - This class is used to maintain the singly linked bucket list in + /// a folding set. + /// + class Node { + private: + // NextInFoldingSetBucket - next link in the bucket list. + void *NextInFoldingSetBucket; + + public: + + Node() : NextInFoldingSetBucket(0) {} + + // Accessors + void *getNextInBucket() const { return NextInFoldingSetBucket; } + void SetNextInBucket(void *N) { NextInFoldingSetBucket = N; } + }; + + /// clear - Remove all nodes from the folding set. + void clear(); + + /// RemoveNode - Remove a node from the folding set, returning true if one + /// was removed or false if the node was not in the folding set. + bool RemoveNode(Node *N); + + /// GetOrInsertNode - If there is an existing simple Node exactly + /// equal to the specified node, return it. Otherwise, insert 'N' and return + /// it instead. + Node *GetOrInsertNode(Node *N); + + /// FindNodeOrInsertPos - Look up the node specified by ID. If it exists, + /// return it. If not, return the insertion token that will make insertion + /// faster. + Node *FindNodeOrInsertPos(const FoldingSetNodeID &ID, void *&InsertPos); + + /// InsertNode - Insert the specified node into the folding set, knowing that + /// it is not already in the folding set. InsertPos must be obtained from + /// FindNodeOrInsertPos. + void InsertNode(Node *N, void *InsertPos); + + /// size - Returns the number of nodes in the folding set. + unsigned size() const { return NumNodes; } + + /// empty - Returns true if there are no nodes in the folding set. + bool empty() const { return NumNodes == 0; } + +private: + + /// GrowHashTable - Double the size of the hash table and rehash everything. + /// + void GrowHashTable(); + +protected: + + /// GetNodeProfile - Instantiations of the FoldingSet template implement + /// this function to gather data bits for the given node. + virtual void GetNodeProfile(FoldingSetNodeID &ID, Node *N) const = 0; +}; + +//===----------------------------------------------------------------------===// +/// FoldingSetTrait - This trait class is used to define behavior of how +/// to "profile" (in the FoldingSet parlance) an object of a given type. +/// The default behavior is to invoke a 'Profile' method on an object, but +/// through template specialization the behavior can be tailored for specific +/// types. Combined with the FoldingSetNodeWrapper classs, one can add objects +/// to FoldingSets that were not originally designed to have that behavior. +/// +template struct FoldingSetTrait { + static inline void Profile(const T& X, FoldingSetNodeID& ID) { X.Profile(ID);} + static inline void Profile(T& X, FoldingSetNodeID& ID) { X.Profile(ID); } +}; + +//===--------------------------------------------------------------------===// +/// FoldingSetNodeID - This class is used to gather all the unique data bits of +/// a node. When all the bits are gathered this class is used to produce a +/// hash value for the node. +/// +class FoldingSetNodeID { + /// Bits - Vector of all the data bits that make the node unique. + /// Use a SmallVector to avoid a heap allocation in the common case. + SmallVector Bits; + +public: + FoldingSetNodeID() {} + + /// getRawData - Return the ith entry in the Bits data. + /// + unsigned getRawData(unsigned i) const { + return Bits[i]; + } + + /// Add* - Add various data types to Bit data. + /// + void AddPointer(const void *Ptr); + void AddInteger(signed I); + void AddInteger(unsigned I); + void AddInteger(long I); + void AddInteger(unsigned long I); + void AddInteger(long long I); + void AddInteger(unsigned long long I); + void AddBoolean(bool B) { AddInteger(B ? 1U : 0U); } + void AddString(StringRef String); + + template + inline void Add(const T& x) { FoldingSetTrait::Profile(x, *this); } + + /// clear - Clear the accumulated profile, allowing this FoldingSetNodeID + /// object to be used to compute a new profile. + inline void clear() { Bits.clear(); } + + /// ComputeHash - Compute a strong hash value for this FoldingSetNodeID, used + /// to lookup the node in the FoldingSetImpl. + unsigned ComputeHash() const; + + /// operator== - Used to compare two nodes to each other. + /// + bool operator==(const FoldingSetNodeID &RHS) const; +}; + +// Convenience type to hide the implementation of the folding set. +typedef FoldingSetImpl::Node FoldingSetNode; +template class FoldingSetIterator; +template class FoldingSetBucketIterator; + +//===----------------------------------------------------------------------===// +/// FoldingSet - This template class is used to instantiate a specialized +/// implementation of the folding set to the node class T. T must be a +/// subclass of FoldingSetNode and implement a Profile function. +/// +template class FoldingSet : public FoldingSetImpl { +private: + /// GetNodeProfile - Each instantiatation of the FoldingSet needs to provide a + /// way to convert nodes into a unique specifier. + virtual void GetNodeProfile(FoldingSetNodeID &ID, Node *N) const { + T *TN = static_cast(N); + FoldingSetTrait::Profile(*TN,ID); + } + +public: + explicit FoldingSet(unsigned Log2InitSize = 6) + : FoldingSetImpl(Log2InitSize) + {} + + typedef FoldingSetIterator iterator; + iterator begin() { return iterator(Buckets); } + iterator end() { return iterator(Buckets+NumBuckets); } + + typedef FoldingSetIterator const_iterator; + const_iterator begin() const { return const_iterator(Buckets); } + const_iterator end() const { return const_iterator(Buckets+NumBuckets); } + + typedef FoldingSetBucketIterator bucket_iterator; + + bucket_iterator bucket_begin(unsigned hash) { + return bucket_iterator(Buckets + (hash & (NumBuckets-1))); + } + + bucket_iterator bucket_end(unsigned hash) { + return bucket_iterator(Buckets + (hash & (NumBuckets-1)), true); + } + + /// GetOrInsertNode - If there is an existing simple Node exactly + /// equal to the specified node, return it. Otherwise, insert 'N' and + /// return it instead. + T *GetOrInsertNode(Node *N) { + return static_cast(FoldingSetImpl::GetOrInsertNode(N)); + } + + /// FindNodeOrInsertPos - Look up the node specified by ID. If it exists, + /// return it. If not, return the insertion token that will make insertion + /// faster. + T *FindNodeOrInsertPos(const FoldingSetNodeID &ID, void *&InsertPos) { + return static_cast(FoldingSetImpl::FindNodeOrInsertPos(ID, InsertPos)); + } +}; + +//===----------------------------------------------------------------------===// +/// FoldingSetIteratorImpl - This is the common iterator support shared by all +/// folding sets, which knows how to walk the folding set hash table. +class FoldingSetIteratorImpl { +protected: + FoldingSetNode *NodePtr; + FoldingSetIteratorImpl(void **Bucket); + void advance(); + +public: + bool operator==(const FoldingSetIteratorImpl &RHS) const { + return NodePtr == RHS.NodePtr; + } + bool operator!=(const FoldingSetIteratorImpl &RHS) const { + return NodePtr != RHS.NodePtr; + } +}; + + +template +class FoldingSetIterator : public FoldingSetIteratorImpl { +public: + explicit FoldingSetIterator(void **Bucket) : FoldingSetIteratorImpl(Bucket) {} + + T &operator*() const { + return *static_cast(NodePtr); + } + + T *operator->() const { + return static_cast(NodePtr); + } + + inline FoldingSetIterator& operator++() { // Preincrement + advance(); + return *this; + } + FoldingSetIterator operator++(int) { // Postincrement + FoldingSetIterator tmp = *this; ++*this; return tmp; + } +}; + +//===----------------------------------------------------------------------===// +/// FoldingSetBucketIteratorImpl - This is the common bucket iterator support +/// shared by all folding sets, which knows how to walk a particular bucket +/// of a folding set hash table. + +class FoldingSetBucketIteratorImpl { +protected: + void *Ptr; + + explicit FoldingSetBucketIteratorImpl(void **Bucket); + + FoldingSetBucketIteratorImpl(void **Bucket, bool) + : Ptr(Bucket) {} + + void advance() { + void *Probe = static_cast(Ptr)->getNextInBucket(); + uintptr_t x = reinterpret_cast(Probe) & ~0x1; + Ptr = reinterpret_cast(x); + } + +public: + bool operator==(const FoldingSetBucketIteratorImpl &RHS) const { + return Ptr == RHS.Ptr; + } + bool operator!=(const FoldingSetBucketIteratorImpl &RHS) const { + return Ptr != RHS.Ptr; + } +}; + + +template +class FoldingSetBucketIterator : public FoldingSetBucketIteratorImpl { +public: + explicit FoldingSetBucketIterator(void **Bucket) : + FoldingSetBucketIteratorImpl(Bucket) {} + + FoldingSetBucketIterator(void **Bucket, bool) : + FoldingSetBucketIteratorImpl(Bucket, true) {} + + T& operator*() const { return *static_cast(Ptr); } + T* operator->() const { return static_cast(Ptr); } + + inline FoldingSetBucketIterator& operator++() { // Preincrement + advance(); + return *this; + } + FoldingSetBucketIterator operator++(int) { // Postincrement + FoldingSetBucketIterator tmp = *this; ++*this; return tmp; + } +}; + +//===----------------------------------------------------------------------===// +/// FoldingSetNodeWrapper - This template class is used to "wrap" arbitrary +/// types in an enclosing object so that they can be inserted into FoldingSets. +template +class FoldingSetNodeWrapper : public FoldingSetNode { + T data; +public: + explicit FoldingSetNodeWrapper(const T& x) : data(x) {} + virtual ~FoldingSetNodeWrapper() {} + + template + explicit FoldingSetNodeWrapper(const A1& a1) + : data(a1) {} + + template + explicit FoldingSetNodeWrapper(const A1& a1, const A2& a2) + : data(a1,a2) {} + + template + explicit FoldingSetNodeWrapper(const A1& a1, const A2& a2, const A3& a3) + : data(a1,a2,a3) {} + + template + explicit FoldingSetNodeWrapper(const A1& a1, const A2& a2, const A3& a3, + const A4& a4) + : data(a1,a2,a3,a4) {} + + template + explicit FoldingSetNodeWrapper(const A1& a1, const A2& a2, const A3& a3, + const A4& a4, const A5& a5) + : data(a1,a2,a3,a4,a5) {} + + + void Profile(FoldingSetNodeID& ID) { FoldingSetTrait::Profile(data, ID); } + + T& getValue() { return data; } + const T& getValue() const { return data; } + + operator T&() { return data; } + operator const T&() const { return data; } +}; + +//===----------------------------------------------------------------------===// +/// FastFoldingSetNode - This is a subclass of FoldingSetNode which stores +/// a FoldingSetNodeID value rather than requiring the node to recompute it +/// each time it is needed. This trades space for speed (which can be +/// significant if the ID is long), and it also permits nodes to drop +/// information that would otherwise only be required for recomputing an ID. +class FastFoldingSetNode : public FoldingSetNode { + FoldingSetNodeID FastID; +protected: + explicit FastFoldingSetNode(const FoldingSetNodeID &ID) : FastID(ID) {} +public: + void Profile(FoldingSetNodeID& ID) { ID = FastID; } +}; + +//===----------------------------------------------------------------------===// +// Partial specializations of FoldingSetTrait. + +template struct FoldingSetTrait { + static inline void Profile(const T* X, FoldingSetNodeID& ID) { + ID.AddPointer(X); + } + static inline void Profile(T* X, FoldingSetNodeID& ID) { + ID.AddPointer(X); + } +}; + +template struct FoldingSetTrait { + static inline void Profile(const T* X, FoldingSetNodeID& ID) { + ID.AddPointer(X); + } +}; + +} // End of namespace llvm. + +#endif diff --git a/libclamav/c++/llvm/include/llvm/ADT/GraphTraits.h b/libclamav/c++/llvm/include/llvm/ADT/GraphTraits.h new file mode 100644 index 000000000..0fd1f5022 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/ADT/GraphTraits.h @@ -0,0 +1,103 @@ +//===-- llvm/ADT/GraphTraits.h - Graph traits template ----------*- 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 the little GraphTraits template class that should be +// specialized by classes that want to be iteratable by generic graph iterators. +// +// This file also defines the marker class Inverse that is used to iterate over +// graphs in a graph defined, inverse ordering... +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_GRAPHTRAITS_H +#define LLVM_ADT_GRAPHTRAITS_H + +namespace llvm { + +// GraphTraits - This class should be specialized by different graph types... +// which is why the default version is empty. +// +template +struct GraphTraits { + // Elements to provide: + + // typedef NodeType - Type of Node in the graph + // typedef ChildIteratorType - Type used to iterate over children in graph + + // static NodeType *getEntryNode(const GraphType &) + // Return the entry node of the graph + + // static ChildIteratorType child_begin(NodeType *) + // static ChildIteratorType child_end (NodeType *) + // Return iterators that point to the beginning and ending of the child + // node list for the specified node. + // + + + // typedef ...iterator nodes_iterator; + // static nodes_iterator nodes_begin(GraphType *G) + // static nodes_iterator nodes_end (GraphType *G) + // + // nodes_iterator/begin/end - Allow iteration over all nodes in the graph + + + // If anyone tries to use this class without having an appropriate + // specialization, make an error. If you get this error, it's because you + // need to include the appropriate specialization of GraphTraits<> for your + // graph, or you need to define it for a new graph type. Either that or + // your argument to XXX_begin(...) is unknown or needs to have the proper .h + // file #include'd. + // + typedef typename GraphType::UnknownGraphTypeError NodeType; +}; + + +// Inverse - This class is used as a little marker class to tell the graph +// iterator to iterate over the graph in a graph defined "Inverse" ordering. +// Not all graphs define an inverse ordering, and if they do, it depends on +// the graph exactly what that is. Here's an example of usage with the +// df_iterator: +// +// idf_iterator I = idf_begin(M), E = idf_end(M); +// for (; I != E; ++I) { ... } +// +// Which is equivalent to: +// df_iterator > I = idf_begin(M), E = idf_end(M); +// for (; I != E; ++I) { ... } +// +template +struct Inverse { + const GraphType &Graph; + + inline Inverse(const GraphType &G) : Graph(G) {} +}; + +// Provide a partial specialization of GraphTraits so that the inverse of an +// inverse falls back to the original graph. +template +struct GraphTraits > > { + typedef typename GraphTraits::NodeType NodeType; + typedef typename GraphTraits::ChildIteratorType ChildIteratorType; + + static NodeType *getEntryNode(Inverse > *G) { + return GraphTraits::getEntryNode(G->Graph.Graph); + } + + static ChildIteratorType child_begin(NodeType* N) { + return GraphTraits::child_begin(N); + } + + static ChildIteratorType child_end(NodeType* N) { + return GraphTraits::child_end(N); + } +}; + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/ADT/ImmutableList.h b/libclamav/c++/llvm/include/llvm/ADT/ImmutableList.h new file mode 100644 index 000000000..5f8cb57f1 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/ADT/ImmutableList.h @@ -0,0 +1,219 @@ +//==--- ImmutableList.h - Immutable (functional) list interface --*- 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 the ImmutableList class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_IMLIST_H +#define LLVM_ADT_IMLIST_H + +#include "llvm/Support/Allocator.h" +#include "llvm/ADT/FoldingSet.h" +#include "llvm/System/DataTypes.h" +#include + +namespace llvm { + +template class ImmutableListFactory; + +template +class ImmutableListImpl : public FoldingSetNode { + T Head; + const ImmutableListImpl* Tail; + + ImmutableListImpl(const T& head, const ImmutableListImpl* tail = 0) + : Head(head), Tail(tail) {} + + friend class ImmutableListFactory; + + // Do not implement. + void operator=(const ImmutableListImpl&); + ImmutableListImpl(const ImmutableListImpl&); + +public: + const T& getHead() const { return Head; } + const ImmutableListImpl* getTail() const { return Tail; } + + static inline void Profile(FoldingSetNodeID& ID, const T& H, + const ImmutableListImpl* L){ + ID.AddPointer(L); + ID.Add(H); + } + + void Profile(FoldingSetNodeID& ID) { + Profile(ID, Head, Tail); + } +}; + +/// ImmutableList - This class represents an immutable (functional) list. +/// It is implemented as a smart pointer (wraps ImmutableListImpl), so it +/// it is intended to always be copied by value as if it were a pointer. +/// This interface matches ImmutableSet and ImmutableMap. ImmutableList +/// objects should almost never be created directly, and instead should +/// be created by ImmutableListFactory objects that manage the lifetime +/// of a group of lists. When the factory object is reclaimed, all lists +/// created by that factory are released as well. +template +class ImmutableList { +public: + typedef T value_type; + typedef ImmutableListFactory Factory; + +private: + const ImmutableListImpl* X; + +public: + // This constructor should normally only be called by ImmutableListFactory. + // There may be cases, however, when one needs to extract the internal pointer + // and reconstruct a list object from that pointer. + ImmutableList(const ImmutableListImpl* x = 0) : X(x) {} + + const ImmutableListImpl* getInternalPointer() const { + return X; + } + + class iterator { + const ImmutableListImpl* L; + public: + iterator() : L(0) {} + iterator(ImmutableList l) : L(l.getInternalPointer()) {} + + iterator& operator++() { L = L->getTail(); return *this; } + bool operator==(const iterator& I) const { return L == I.L; } + bool operator!=(const iterator& I) const { return L != I.L; } + const value_type& operator*() const { return L->getHead(); } + ImmutableList getList() const { return L; } + }; + + /// begin - Returns an iterator referring to the head of the list, or + /// an iterator denoting the end of the list if the list is empty. + iterator begin() const { return iterator(X); } + + /// end - Returns an iterator denoting the end of the list. This iterator + /// does not refer to a valid list element. + iterator end() const { return iterator(); } + + /// isEmpty - Returns true if the list is empty. + bool isEmpty() const { return !X; } + + /// isEqual - Returns true if two lists are equal. Because all lists created + /// from the same ImmutableListFactory are uniqued, this has O(1) complexity + /// because it the contents of the list do not need to be compared. Note + /// that you should only compare two lists created from the same + /// ImmutableListFactory. + bool isEqual(const ImmutableList& L) const { return X == L.X; } + + bool operator==(const ImmutableList& L) const { return isEqual(L); } + + /// getHead - Returns the head of the list. + const T& getHead() { + assert (!isEmpty() && "Cannot get the head of an empty list."); + return X->getHead(); + } + + /// getTail - Returns the tail of the list, which is another (possibly empty) + /// ImmutableList. + ImmutableList getTail() { + return X ? X->getTail() : 0; + } + + void Profile(FoldingSetNodeID& ID) const { + ID.AddPointer(X); + } +}; + +template +class ImmutableListFactory { + typedef ImmutableListImpl ListTy; + typedef FoldingSet CacheTy; + + CacheTy Cache; + uintptr_t Allocator; + + bool ownsAllocator() const { + return Allocator & 0x1 ? false : true; + } + + BumpPtrAllocator& getAllocator() const { + return *reinterpret_cast(Allocator & ~0x1); + } + +public: + ImmutableListFactory() + : Allocator(reinterpret_cast(new BumpPtrAllocator())) {} + + ImmutableListFactory(BumpPtrAllocator& Alloc) + : Allocator(reinterpret_cast(&Alloc) | 0x1) {} + + ~ImmutableListFactory() { + if (ownsAllocator()) delete &getAllocator(); + } + + ImmutableList Concat(const T& Head, ImmutableList Tail) { + // Profile the new list to see if it already exists in our cache. + FoldingSetNodeID ID; + void* InsertPos; + + const ListTy* TailImpl = Tail.getInternalPointer(); + ListTy::Profile(ID, Head, TailImpl); + ListTy* L = Cache.FindNodeOrInsertPos(ID, InsertPos); + + if (!L) { + // The list does not exist in our cache. Create it. + BumpPtrAllocator& A = getAllocator(); + L = (ListTy*) A.Allocate(); + new (L) ListTy(Head, TailImpl); + + // Insert the new list into the cache. + Cache.InsertNode(L, InsertPos); + } + + return L; + } + + ImmutableList Add(const T& D, ImmutableList L) { + return Concat(D, L); + } + + ImmutableList GetEmptyList() const { + return ImmutableList(0); + } + + ImmutableList Create(const T& X) { + return Concat(X, GetEmptyList()); + } +}; + +//===----------------------------------------------------------------------===// +// Partially-specialized Traits. +//===----------------------------------------------------------------------===// + +template struct DenseMapInfo; +template struct DenseMapInfo > { + static inline ImmutableList getEmptyKey() { + return reinterpret_cast*>(-1); + } + static inline ImmutableList getTombstoneKey() { + return reinterpret_cast*>(-2); + } + static unsigned getHashValue(ImmutableList X) { + uintptr_t PtrVal = reinterpret_cast(X.getInternalPointer()); + return (unsigned((uintptr_t)PtrVal) >> 4) ^ + (unsigned((uintptr_t)PtrVal) >> 9); + } + static bool isEqual(ImmutableList X1, ImmutableList X2) { + return X1 == X2; + } + static bool isPod() { return true; } +}; + +} // end llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/ADT/ImmutableMap.h b/libclamav/c++/llvm/include/llvm/ADT/ImmutableMap.h new file mode 100644 index 000000000..fc9fe8b5a --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/ADT/ImmutableMap.h @@ -0,0 +1,233 @@ +//===--- ImmutableMap.h - Immutable (functional) map interface --*- 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 the ImmutableMap class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_IMMAP_H +#define LLVM_ADT_IMMAP_H + +#include "llvm/ADT/ImmutableSet.h" + +namespace llvm { + +/// ImutKeyValueInfo -Traits class used by ImmutableMap. While both the first +/// and second elements in a pair are used to generate profile information, +/// only the first element (the key) is used by isEqual and isLess. +template +struct ImutKeyValueInfo { + typedef const std::pair value_type; + typedef const value_type& value_type_ref; + typedef const T key_type; + typedef const T& key_type_ref; + typedef const S data_type; + typedef const S& data_type_ref; + + static inline key_type_ref KeyOfValue(value_type_ref V) { + return V.first; + } + + static inline data_type_ref DataOfValue(value_type_ref V) { + return V.second; + } + + static inline bool isEqual(key_type_ref L, key_type_ref R) { + return ImutContainerInfo::isEqual(L,R); + } + static inline bool isLess(key_type_ref L, key_type_ref R) { + return ImutContainerInfo::isLess(L,R); + } + + static inline bool isDataEqual(data_type_ref L, data_type_ref R) { + return ImutContainerInfo::isEqual(L,R); + } + + static inline void Profile(FoldingSetNodeID& ID, value_type_ref V) { + ImutContainerInfo::Profile(ID, V.first); + ImutContainerInfo::Profile(ID, V.second); + } +}; + + +template > +class ImmutableMap { +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 TreeTy; + +private: + TreeTy* Root; + +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 ImmutableMap(const TreeTy* R) : Root(const_cast(R)) {} + + class Factory { + typename TreeTy::Factory F; + const bool Canonicalize; + + public: + Factory(bool canonicalize = true) + : Canonicalize(canonicalize) {} + + Factory(BumpPtrAllocator& Alloc, bool canonicalize = true) + : F(Alloc), Canonicalize(canonicalize) {} + + ImmutableMap GetEmptyMap() { return ImmutableMap(F.GetEmptyTree()); } + + ImmutableMap Add(ImmutableMap Old, key_type_ref K, data_type_ref D) { + TreeTy *T = F.Add(Old.Root, std::make_pair(K,D)); + return ImmutableMap(Canonicalize ? F.GetCanonicalTree(T): T); + } + + ImmutableMap Remove(ImmutableMap Old, key_type_ref K) { + TreeTy *T = F.Remove(Old.Root,K); + return ImmutableMap(Canonicalize ? F.GetCanonicalTree(T): T); + } + + private: + Factory(const Factory& RHS); // DO NOT IMPLEMENT + void operator=(const Factory& RHS); // DO NOT IMPLEMENT + }; + + friend class Factory; + + bool contains(key_type_ref K) const { + return Root ? Root->contains(K) : false; + } + + + bool operator==(ImmutableMap RHS) const { + return Root && RHS.Root ? Root->isEqual(*RHS.Root) : Root == RHS.Root; + } + + bool operator!=(ImmutableMap RHS) const { + return Root && RHS.Root ? Root->isNotEqual(*RHS.Root) : Root != RHS.Root; + } + + TreeTy* getRoot() const { return Root; } + + bool isEmpty() const { return !Root; } + + //===--------------------------------------------------===// + // Foreach - A limited form of map iteration. + //===--------------------------------------------------===// + +private: + template + struct CBWrapper { + Callback C; + void operator()(value_type_ref V) { C(V.first,V.second); } + }; + + template + struct CBWrapperRef { + Callback &C; + CBWrapperRef(Callback& c) : C(c) {} + + void operator()(value_type_ref V) { C(V.first,V.second); } + }; + +public: + template + void foreach(Callback& C) { + if (Root) { + CBWrapperRef CB(C); + Root->foreach(CB); + } + } + + template + void foreach() { + if (Root) { + CBWrapper CB; + Root->foreach(CB); + } + } + + //===--------------------------------------------------===// + // For testing. + //===--------------------------------------------------===// + + void verify() const { if (Root) Root->verify(); } + + //===--------------------------------------------------===// + // Iterators. + //===--------------------------------------------------===// + + class iterator { + typename TreeTy::iterator itr; + + iterator() {} + iterator(TreeTy* t) : itr(t) {} + friend class ImmutableMap; + + 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 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. + //===--------------------------------------------------===// + + inline unsigned getHeight() const { return Root ? Root->getHeight() : 0; } + + static inline void Profile(FoldingSetNodeID& ID, const ImmutableMap& M) { + ID.AddPointer(M.Root); + } + + inline void Profile(FoldingSetNodeID& ID) const { + return Profile(ID,*this); + } +}; + +} // end namespace llvm + +#endif diff --git a/libclamav/c++/llvm/include/llvm/ADT/ImmutableSet.h b/libclamav/c++/llvm/include/llvm/ADT/ImmutableSet.h new file mode 100644 index 000000000..676a1989f --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/ADT/ImmutableSet.h @@ -0,0 +1,1073 @@ +//===--- ImmutableSet.h - Immutable (functional) set interface --*- 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 the ImutAVLTree and ImmutableSet classes. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_IMSET_H +#define LLVM_ADT_IMSET_H + +#include "llvm/Support/Allocator.h" +#include "llvm/ADT/FoldingSet.h" +#include "llvm/System/DataTypes.h" +#include +#include + +namespace llvm { + +//===----------------------------------------------------------------------===// +// Immutable AVL-Tree Definition. +//===----------------------------------------------------------------------===// + +template class ImutAVLFactory; +template class ImutAVLTreeInOrderIterator; +template class ImutAVLTreeGenericIterator; + +template +class ImutAVLTree : public FoldingSetNode { +public: + typedef typename ImutInfo::key_type_ref key_type_ref; + typedef typename ImutInfo::value_type value_type; + typedef typename ImutInfo::value_type_ref value_type_ref; + + typedef ImutAVLFactory Factory; + friend class ImutAVLFactory; + + friend class ImutAVLTreeGenericIterator; + friend class FoldingSet; + + typedef ImutAVLTreeInOrderIterator iterator; + + //===----------------------------------------------------===// + // Public Interface. + //===----------------------------------------------------===// + + /// getLeft - Returns a pointer to the left subtree. This value + /// is NULL if there is no left subtree. + ImutAVLTree *getLeft() const { + return reinterpret_cast(Left & ~LeftFlags); + } + + /// getRight - Returns a pointer to the right subtree. This value is + /// NULL if there is no right subtree. + ImutAVLTree* getRight() const { return Right; } + + /// getHeight - Returns the height of the tree. A tree with no subtrees + /// has a height of 1. + unsigned getHeight() const { return Height; } + + /// getValue - Returns the data value associated with the tree node. + const value_type& getValue() const { return Value; } + + /// find - Finds the subtree associated with the specified key value. + /// This method returns NULL if no matching subtree is found. + ImutAVLTree* find(key_type_ref K) { + ImutAVLTree *T = this; + + while (T) { + key_type_ref CurrentKey = ImutInfo::KeyOfValue(T->getValue()); + + if (ImutInfo::isEqual(K,CurrentKey)) + return T; + else if (ImutInfo::isLess(K,CurrentKey)) + T = T->getLeft(); + else + T = T->getRight(); + } + + return NULL; + } + + /// getMaxElement - Find the subtree associated with the highest ranged + /// key value. + ImutAVLTree* getMaxElement() { + ImutAVLTree *T = this; + ImutAVLTree *Right = T->getRight(); + while (Right) { T = Right; Right = T->getRight(); } + return T; + } + + /// size - Returns the number of nodes in the tree, which includes + /// both leaves and non-leaf nodes. + unsigned size() const { + unsigned n = 1; + + if (const ImutAVLTree* L = getLeft()) n += L->size(); + if (const ImutAVLTree* R = getRight()) n += R->size(); + + return n; + } + + /// begin - Returns an iterator that iterates over the nodes of the tree + /// in an inorder traversal. The returned iterator thus refers to the + /// the tree node with the minimum data element. + iterator begin() const { return iterator(this); } + + /// end - Returns an iterator for the tree that denotes the end of an + /// inorder traversal. + iterator end() const { return iterator(); } + + bool ElementEqual(value_type_ref V) const { + // Compare the keys. + if (!ImutInfo::isEqual(ImutInfo::KeyOfValue(getValue()), + ImutInfo::KeyOfValue(V))) + return false; + + // Also compare the data values. + if (!ImutInfo::isDataEqual(ImutInfo::DataOfValue(getValue()), + ImutInfo::DataOfValue(V))) + return false; + + return true; + } + + bool ElementEqual(const ImutAVLTree* RHS) const { + return ElementEqual(RHS->getValue()); + } + + /// isEqual - Compares two trees for structural equality and returns true + /// if they are equal. This worst case performance of this operation is + // linear in the sizes of the trees. + bool isEqual(const ImutAVLTree& RHS) const { + if (&RHS == this) + return true; + + iterator LItr = begin(), LEnd = end(); + iterator RItr = RHS.begin(), REnd = RHS.end(); + + while (LItr != LEnd && RItr != REnd) { + if (*LItr == *RItr) { + LItr.SkipSubTree(); + RItr.SkipSubTree(); + continue; + } + + if (!LItr->ElementEqual(*RItr)) + return false; + + ++LItr; + ++RItr; + } + + return LItr == LEnd && RItr == REnd; + } + + /// isNotEqual - Compares two trees for structural inequality. Performance + /// is the same is isEqual. + bool isNotEqual(const ImutAVLTree& RHS) const { return !isEqual(RHS); } + + /// contains - Returns true if this tree contains a subtree (node) that + /// has an data element that matches the specified key. Complexity + /// is logarithmic in the size of the tree. + bool contains(key_type_ref K) { return (bool) find(K); } + + /// foreach - A member template the accepts invokes operator() on a functor + /// object (specifed by Callback) for every node/subtree in the tree. + /// Nodes are visited using an inorder traversal. + template + void foreach(Callback& C) { + if (ImutAVLTree* L = getLeft()) L->foreach(C); + + C(Value); + + if (ImutAVLTree* R = getRight()) R->foreach(C); + } + + /// verify - A utility method that checks that the balancing and + /// ordering invariants of the tree are satisifed. It is a recursive + /// method that returns the height of the tree, which is then consumed + /// by the enclosing verify call. External callers should ignore the + /// return value. An invalid tree will cause an assertion to fire in + /// a debug build. + unsigned verify() const { + unsigned HL = getLeft() ? getLeft()->verify() : 0; + unsigned HR = getRight() ? getRight()->verify() : 0; + + assert (getHeight() == ( HL > HR ? HL : HR ) + 1 + && "Height calculation wrong."); + + assert ((HL > HR ? HL-HR : HR-HL) <= 2 + && "Balancing invariant violated."); + + + assert (!getLeft() + || ImutInfo::isLess(ImutInfo::KeyOfValue(getLeft()->getValue()), + ImutInfo::KeyOfValue(getValue())) + && "Value in left child is not less that current value."); + + + assert (!getRight() + || ImutInfo::isLess(ImutInfo::KeyOfValue(getValue()), + ImutInfo::KeyOfValue(getRight()->getValue())) + && "Current value is not less that value of right child."); + + return getHeight(); + } + + /// Profile - Profiling for ImutAVLTree. + void Profile(llvm::FoldingSetNodeID& ID) { + ID.AddInteger(ComputeDigest()); + } + + //===----------------------------------------------------===// + // Internal Values. + //===----------------------------------------------------===// + +private: + uintptr_t Left; + ImutAVLTree* Right; + unsigned Height; + value_type Value; + uint32_t Digest; + + //===----------------------------------------------------===// + // Internal methods (node manipulation; used by Factory). + //===----------------------------------------------------===// + +private: + + enum { Mutable = 0x1, NoCachedDigest = 0x2, LeftFlags = 0x3 }; + + /// ImutAVLTree - Internal constructor that is only called by + /// ImutAVLFactory. + ImutAVLTree(ImutAVLTree* l, ImutAVLTree* r, value_type_ref v, unsigned height) + : Left(reinterpret_cast(l) | (Mutable | NoCachedDigest)), + Right(r), Height(height), Value(v), Digest(0) {} + + + /// isMutable - Returns true if the left and right subtree references + /// (as well as height) can be changed. If this method returns false, + /// the tree is truly immutable. Trees returned from an ImutAVLFactory + /// object should always have this method return true. Further, if this + /// method returns false for an instance of ImutAVLTree, all subtrees + /// will also have this method return false. The converse is not true. + bool isMutable() const { return Left & Mutable; } + + /// hasCachedDigest - Returns true if the digest for this tree is cached. + /// This can only be true if the tree is immutable. + bool hasCachedDigest() const { return !(Left & NoCachedDigest); } + + //===----------------------------------------------------===// + // Mutating operations. A tree root can be manipulated as + // long as its reference has not "escaped" from internal + // methods of a factory object (see below). When a tree + // pointer is externally viewable by client code, the + // internal "mutable bit" is cleared to mark the tree + // immutable. Note that a tree that still has its mutable + // bit set may have children (subtrees) that are themselves + // immutable. + //===----------------------------------------------------===// + + /// MarkImmutable - Clears the mutable flag for a tree. After this happens, + /// it is an error to call setLeft(), setRight(), and setHeight(). + void MarkImmutable() { + assert(isMutable() && "Mutable flag already removed."); + Left &= ~Mutable; + } + + /// MarkedCachedDigest - Clears the NoCachedDigest flag for a tree. + void MarkedCachedDigest() { + assert(!hasCachedDigest() && "NoCachedDigest flag already removed."); + Left &= ~NoCachedDigest; + } + + /// setLeft - Changes the reference of the left subtree. Used internally + /// by ImutAVLFactory. + void setLeft(ImutAVLTree* NewLeft) { + assert(isMutable() && + "Only a mutable tree can have its left subtree changed."); + Left = reinterpret_cast(NewLeft) | LeftFlags; + } + + /// setRight - Changes the reference of the right subtree. Used internally + /// by ImutAVLFactory. + void setRight(ImutAVLTree* NewRight) { + assert(isMutable() && + "Only a mutable tree can have its right subtree changed."); + + Right = NewRight; + // Set the NoCachedDigest flag. + Left = Left | NoCachedDigest; + + } + + /// setHeight - Changes the height of the tree. Used internally by + /// ImutAVLFactory. + void setHeight(unsigned h) { + assert(isMutable() && "Only a mutable tree can have its height changed."); + Height = h; + } + + static inline + uint32_t ComputeDigest(ImutAVLTree* L, ImutAVLTree* R, value_type_ref V) { + uint32_t digest = 0; + + if (L) + digest += L->ComputeDigest(); + + // Compute digest of stored data. + FoldingSetNodeID ID; + ImutInfo::Profile(ID,V); + digest += ID.ComputeHash(); + + if (R) + digest += R->ComputeDigest(); + + return digest; + } + + inline uint32_t ComputeDigest() { + // Check the lowest bit to determine if digest has actually been + // pre-computed. + if (hasCachedDigest()) + return Digest; + + uint32_t X = ComputeDigest(getLeft(), getRight(), getValue()); + Digest = X; + MarkedCachedDigest(); + return X; + } +}; + +//===----------------------------------------------------------------------===// +// Immutable AVL-Tree Factory class. +//===----------------------------------------------------------------------===// + +template +class ImutAVLFactory { + typedef ImutAVLTree TreeTy; + typedef typename TreeTy::value_type_ref value_type_ref; + typedef typename TreeTy::key_type_ref key_type_ref; + + typedef FoldingSet CacheTy; + + CacheTy Cache; + uintptr_t Allocator; + + bool ownsAllocator() const { + return Allocator & 0x1 ? false : true; + } + + BumpPtrAllocator& getAllocator() const { + return *reinterpret_cast(Allocator & ~0x1); + } + + //===--------------------------------------------------===// + // Public interface. + //===--------------------------------------------------===// + +public: + ImutAVLFactory() + : Allocator(reinterpret_cast(new BumpPtrAllocator())) {} + + ImutAVLFactory(BumpPtrAllocator& Alloc) + : Allocator(reinterpret_cast(&Alloc) | 0x1) {} + + ~ImutAVLFactory() { + if (ownsAllocator()) delete &getAllocator(); + } + + TreeTy* Add(TreeTy* T, value_type_ref V) { + T = Add_internal(V,T); + MarkImmutable(T); + return T; + } + + TreeTy* Remove(TreeTy* T, key_type_ref V) { + T = Remove_internal(V,T); + MarkImmutable(T); + return T; + } + + TreeTy* GetEmptyTree() const { return NULL; } + + //===--------------------------------------------------===// + // A bunch of quick helper functions used for reasoning + // about the properties of trees and their children. + // These have succinct names so that the balancing code + // is as terse (and readable) as possible. + //===--------------------------------------------------===// +private: + + bool isEmpty(TreeTy* T) const { return !T; } + unsigned Height(TreeTy* T) const { return T ? T->getHeight() : 0; } + TreeTy* Left(TreeTy* T) const { return T->getLeft(); } + TreeTy* Right(TreeTy* T) const { return T->getRight(); } + value_type_ref Value(TreeTy* T) const { return T->Value; } + + unsigned IncrementHeight(TreeTy* L, TreeTy* R) const { + unsigned hl = Height(L); + unsigned hr = Height(R); + return ( hl > hr ? hl : hr ) + 1; + } + + static bool CompareTreeWithSection(TreeTy* T, + typename TreeTy::iterator& TI, + typename TreeTy::iterator& TE) { + + typename TreeTy::iterator I = T->begin(), E = T->end(); + + for ( ; I!=E ; ++I, ++TI) + if (TI == TE || !I->ElementEqual(*TI)) + return false; + + return true; + } + + //===--------------------------------------------------===// + // "CreateNode" is used to generate new tree roots that link + // to other trees. The functon may also simply move links + // in an existing root if that root is still marked mutable. + // This is necessary because otherwise our balancing code + // would leak memory as it would create nodes that are + // then discarded later before the finished tree is + // returned to the caller. + //===--------------------------------------------------===// + + TreeTy* CreateNode(TreeTy* L, value_type_ref V, TreeTy* R) { + BumpPtrAllocator& A = getAllocator(); + TreeTy* T = (TreeTy*) A.Allocate(); + new (T) TreeTy(L,R,V,IncrementHeight(L,R)); + return T; + } + + TreeTy* CreateNode(TreeTy* L, TreeTy* OldTree, TreeTy* R) { + assert (!isEmpty(OldTree)); + + if (OldTree->isMutable()) { + OldTree->setLeft(L); + OldTree->setRight(R); + OldTree->setHeight(IncrementHeight(L,R)); + return OldTree; + } + else + return CreateNode(L, Value(OldTree), R); + } + + /// Balance - Used by Add_internal and Remove_internal to + /// balance a newly created tree. + TreeTy* Balance(TreeTy* L, value_type_ref V, TreeTy* R) { + + unsigned hl = Height(L); + unsigned hr = Height(R); + + if (hl > hr + 2) { + assert (!isEmpty(L) && + "Left tree cannot be empty to have a height >= 2."); + + TreeTy* LL = Left(L); + TreeTy* LR = Right(L); + + if (Height(LL) >= Height(LR)) + return CreateNode(LL, L, CreateNode(LR,V,R)); + + assert (!isEmpty(LR) && + "LR cannot be empty because it has a height >= 1."); + + TreeTy* LRL = Left(LR); + TreeTy* LRR = Right(LR); + + return CreateNode(CreateNode(LL,L,LRL), LR, CreateNode(LRR,V,R)); + } + else if (hr > hl + 2) { + assert (!isEmpty(R) && + "Right tree cannot be empty to have a height >= 2."); + + TreeTy* RL = Left(R); + TreeTy* RR = Right(R); + + if (Height(RR) >= Height(RL)) + return CreateNode(CreateNode(L,V,RL), R, RR); + + assert (!isEmpty(RL) && + "RL cannot be empty because it has a height >= 1."); + + TreeTy* RLL = Left(RL); + TreeTy* RLR = Right(RL); + + return CreateNode(CreateNode(L,V,RLL), RL, CreateNode(RLR,R,RR)); + } + else + return CreateNode(L,V,R); + } + + /// Add_internal - Creates a new tree that includes the specified + /// data and the data from the original tree. If the original tree + /// already contained the data item, the original tree is returned. + TreeTy* Add_internal(value_type_ref V, TreeTy* T) { + if (isEmpty(T)) + return CreateNode(T, V, T); + + assert (!T->isMutable()); + + key_type_ref K = ImutInfo::KeyOfValue(V); + key_type_ref KCurrent = ImutInfo::KeyOfValue(Value(T)); + + if (ImutInfo::isEqual(K,KCurrent)) + return CreateNode(Left(T), V, Right(T)); + else if (ImutInfo::isLess(K,KCurrent)) + return Balance(Add_internal(V,Left(T)), Value(T), Right(T)); + else + return Balance(Left(T), Value(T), Add_internal(V,Right(T))); + } + + /// Remove_internal - Creates a new tree that includes all the data + /// from the original tree except the specified data. If the + /// specified data did not exist in the original tree, the original + /// tree is returned. + TreeTy* Remove_internal(key_type_ref K, TreeTy* T) { + if (isEmpty(T)) + return T; + + assert (!T->isMutable()); + + key_type_ref KCurrent = ImutInfo::KeyOfValue(Value(T)); + + if (ImutInfo::isEqual(K,KCurrent)) + return CombineLeftRightTrees(Left(T),Right(T)); + else if (ImutInfo::isLess(K,KCurrent)) + return Balance(Remove_internal(K,Left(T)), Value(T), Right(T)); + else + return Balance(Left(T), Value(T), Remove_internal(K,Right(T))); + } + + TreeTy* CombineLeftRightTrees(TreeTy* L, TreeTy* R) { + if (isEmpty(L)) return R; + if (isEmpty(R)) return L; + + TreeTy* OldNode; + TreeTy* NewRight = RemoveMinBinding(R,OldNode); + return Balance(L,Value(OldNode),NewRight); + } + + TreeTy* RemoveMinBinding(TreeTy* T, TreeTy*& NodeRemoved) { + assert (!isEmpty(T)); + + if (isEmpty(Left(T))) { + NodeRemoved = T; + return Right(T); + } + + return Balance(RemoveMinBinding(Left(T),NodeRemoved),Value(T),Right(T)); + } + + /// MarkImmutable - Clears the mutable bits of a root and all of its + /// descendants. + void MarkImmutable(TreeTy* T) { + if (!T || !T->isMutable()) + return; + + T->MarkImmutable(); + MarkImmutable(Left(T)); + MarkImmutable(Right(T)); + } + +public: + TreeTy *GetCanonicalTree(TreeTy *TNew) { + if (!TNew) + return NULL; + + // Search the FoldingSet bucket for a Tree with the same digest. + FoldingSetNodeID ID; + unsigned digest = TNew->ComputeDigest(); + ID.AddInteger(digest); + unsigned hash = ID.ComputeHash(); + + typename CacheTy::bucket_iterator I = Cache.bucket_begin(hash); + typename CacheTy::bucket_iterator E = Cache.bucket_end(hash); + + for (; I != E; ++I) { + TreeTy *T = &*I; + + if (T->ComputeDigest() != digest) + continue; + + // We found a collision. Perform a comparison of Contents('T') + // with Contents('L')+'V'+Contents('R'). + typename TreeTy::iterator TI = T->begin(), TE = T->end(); + + // First compare Contents('L') with the (initial) contents of T. + if (!CompareTreeWithSection(TNew->getLeft(), TI, TE)) + continue; + + // Now compare the new data element. + if (TI == TE || !TI->ElementEqual(TNew->getValue())) + continue; + + ++TI; + + // Now compare the remainder of 'T' with 'R'. + if (!CompareTreeWithSection(TNew->getRight(), TI, TE)) + continue; + + if (TI != TE) + continue; // Contents('R') did not match suffix of 'T'. + + // Trees did match! Return 'T'. + return T; + } + + // 'TNew' is the only tree of its kind. Return it. + Cache.InsertNode(TNew, (void*) &*Cache.bucket_end(hash)); + return TNew; + } +}; + + +//===----------------------------------------------------------------------===// +// Immutable AVL-Tree Iterators. +//===----------------------------------------------------------------------===// + +template +class ImutAVLTreeGenericIterator { + SmallVector stack; +public: + enum VisitFlag { VisitedNone=0x0, VisitedLeft=0x1, VisitedRight=0x3, + Flags=0x3 }; + + typedef ImutAVLTree TreeTy; + typedef ImutAVLTreeGenericIterator _Self; + + inline ImutAVLTreeGenericIterator() {} + inline ImutAVLTreeGenericIterator(const TreeTy* Root) { + if (Root) stack.push_back(reinterpret_cast(Root)); + } + + TreeTy* operator*() const { + assert (!stack.empty()); + return reinterpret_cast(stack.back() & ~Flags); + } + + uintptr_t getVisitState() { + assert (!stack.empty()); + return stack.back() & Flags; + } + + + bool AtEnd() const { return stack.empty(); } + + bool AtBeginning() const { + return stack.size() == 1 && getVisitState() == VisitedNone; + } + + void SkipToParent() { + assert (!stack.empty()); + stack.pop_back(); + + if (stack.empty()) + return; + + switch (getVisitState()) { + case VisitedNone: + stack.back() |= VisitedLeft; + break; + case VisitedLeft: + stack.back() |= VisitedRight; + break; + default: + assert (false && "Unreachable."); + } + } + + inline bool operator==(const _Self& x) const { + if (stack.size() != x.stack.size()) + return false; + + for (unsigned i = 0 ; i < stack.size(); i++) + if (stack[i] != x.stack[i]) + return false; + + return true; + } + + inline bool operator!=(const _Self& x) const { return !operator==(x); } + + _Self& operator++() { + assert (!stack.empty()); + + TreeTy* Current = reinterpret_cast(stack.back() & ~Flags); + assert (Current); + + switch (getVisitState()) { + case VisitedNone: + if (TreeTy* L = Current->getLeft()) + stack.push_back(reinterpret_cast(L)); + else + stack.back() |= VisitedLeft; + + break; + + case VisitedLeft: + if (TreeTy* R = Current->getRight()) + stack.push_back(reinterpret_cast(R)); + else + stack.back() |= VisitedRight; + + break; + + case VisitedRight: + SkipToParent(); + break; + + default: + assert (false && "Unreachable."); + } + + return *this; + } + + _Self& operator--() { + assert (!stack.empty()); + + TreeTy* Current = reinterpret_cast(stack.back() & ~Flags); + assert (Current); + + switch (getVisitState()) { + case VisitedNone: + stack.pop_back(); + break; + + case VisitedLeft: + stack.back() &= ~Flags; // Set state to "VisitedNone." + + if (TreeTy* L = Current->getLeft()) + stack.push_back(reinterpret_cast(L) | VisitedRight); + + break; + + case VisitedRight: + stack.back() &= ~Flags; + stack.back() |= VisitedLeft; + + if (TreeTy* R = Current->getRight()) + stack.push_back(reinterpret_cast(R) | VisitedRight); + + break; + + default: + assert (false && "Unreachable."); + } + + return *this; + } +}; + +template +class ImutAVLTreeInOrderIterator { + typedef ImutAVLTreeGenericIterator InternalIteratorTy; + InternalIteratorTy InternalItr; + +public: + typedef ImutAVLTree TreeTy; + typedef ImutAVLTreeInOrderIterator _Self; + + ImutAVLTreeInOrderIterator(const TreeTy* Root) : InternalItr(Root) { + if (Root) operator++(); // Advance to first element. + } + + ImutAVLTreeInOrderIterator() : InternalItr() {} + + inline bool operator==(const _Self& x) const { + return InternalItr == x.InternalItr; + } + + inline bool operator!=(const _Self& x) const { return !operator==(x); } + + inline TreeTy* operator*() const { return *InternalItr; } + inline TreeTy* operator->() const { return *InternalItr; } + + inline _Self& operator++() { + do ++InternalItr; + while (!InternalItr.AtEnd() && + InternalItr.getVisitState() != InternalIteratorTy::VisitedLeft); + + return *this; + } + + inline _Self& operator--() { + do --InternalItr; + while (!InternalItr.AtBeginning() && + InternalItr.getVisitState() != InternalIteratorTy::VisitedLeft); + + return *this; + } + + inline void SkipSubTree() { + InternalItr.SkipToParent(); + + while (!InternalItr.AtEnd() && + InternalItr.getVisitState() != InternalIteratorTy::VisitedLeft) + ++InternalItr; + } +}; + +//===----------------------------------------------------------------------===// +// Trait classes for Profile information. +//===----------------------------------------------------------------------===// + +/// Generic profile template. The default behavior is to invoke the +/// profile method of an object. Specializations for primitive integers +/// and generic handling of pointers is done below. +template +struct ImutProfileInfo { + typedef const T value_type; + typedef const T& value_type_ref; + + static inline void Profile(FoldingSetNodeID& ID, value_type_ref X) { + FoldingSetTrait::Profile(X,ID); + } +}; + +/// Profile traits for integers. +template +struct ImutProfileInteger { + typedef const T value_type; + typedef const T& value_type_ref; + + static inline void Profile(FoldingSetNodeID& ID, value_type_ref X) { + ID.AddInteger(X); + } +}; + +#define PROFILE_INTEGER_INFO(X)\ +template<> struct ImutProfileInfo : ImutProfileInteger {}; + +PROFILE_INTEGER_INFO(char) +PROFILE_INTEGER_INFO(unsigned char) +PROFILE_INTEGER_INFO(short) +PROFILE_INTEGER_INFO(unsigned short) +PROFILE_INTEGER_INFO(unsigned) +PROFILE_INTEGER_INFO(signed) +PROFILE_INTEGER_INFO(long) +PROFILE_INTEGER_INFO(unsigned long) +PROFILE_INTEGER_INFO(long long) +PROFILE_INTEGER_INFO(unsigned long long) + +#undef PROFILE_INTEGER_INFO + +/// Generic profile trait for pointer types. We treat pointers as +/// references to unique objects. +template +struct ImutProfileInfo { + typedef const T* value_type; + typedef value_type value_type_ref; + + static inline void Profile(FoldingSetNodeID &ID, value_type_ref X) { + ID.AddPointer(X); + } +}; + +//===----------------------------------------------------------------------===// +// Trait classes that contain element comparison operators and type +// definitions used by ImutAVLTree, ImmutableSet, and ImmutableMap. These +// inherit from the profile traits (ImutProfileInfo) to include operations +// for element profiling. +//===----------------------------------------------------------------------===// + + +/// ImutContainerInfo - Generic definition of comparison operations for +/// elements of immutable containers that defaults to using +/// std::equal_to<> and std::less<> to perform comparison of elements. +template +struct ImutContainerInfo : public ImutProfileInfo { + typedef typename ImutProfileInfo::value_type value_type; + typedef typename ImutProfileInfo::value_type_ref value_type_ref; + typedef value_type key_type; + typedef value_type_ref key_type_ref; + typedef bool data_type; + typedef bool data_type_ref; + + static inline key_type_ref KeyOfValue(value_type_ref D) { return D; } + static inline data_type_ref DataOfValue(value_type_ref) { return true; } + + static inline bool isEqual(key_type_ref LHS, key_type_ref RHS) { + return std::equal_to()(LHS,RHS); + } + + static inline bool isLess(key_type_ref LHS, key_type_ref RHS) { + return std::less()(LHS,RHS); + } + + static inline bool isDataEqual(data_type_ref,data_type_ref) { return true; } +}; + +/// ImutContainerInfo - Specialization for pointer values to treat pointers +/// as references to unique objects. Pointers are thus compared by +/// their addresses. +template +struct ImutContainerInfo : public ImutProfileInfo { + typedef typename ImutProfileInfo::value_type value_type; + typedef typename ImutProfileInfo::value_type_ref value_type_ref; + typedef value_type key_type; + typedef value_type_ref key_type_ref; + typedef bool data_type; + typedef bool data_type_ref; + + static inline key_type_ref KeyOfValue(value_type_ref D) { return D; } + static inline data_type_ref DataOfValue(value_type_ref) { return true; } + + static inline bool isEqual(key_type_ref LHS, key_type_ref RHS) { + return LHS == RHS; + } + + static inline bool isLess(key_type_ref LHS, key_type_ref RHS) { + return LHS < RHS; + } + + static inline bool isDataEqual(data_type_ref,data_type_ref) { return true; } +}; + +//===----------------------------------------------------------------------===// +// Immutable Set +//===----------------------------------------------------------------------===// + +template > +class ImmutableSet { +public: + typedef typename ValInfo::value_type value_type; + typedef typename ValInfo::value_type_ref value_type_ref; + typedef ImutAVLTree TreeTy; + +private: + TreeTy *Root; + +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 ImmutableSet(TreeTy* R) : Root(R) {} + + class Factory { + typename TreeTy::Factory F; + const bool Canonicalize; + + public: + Factory(bool canonicalize = true) + : Canonicalize(canonicalize) {} + + Factory(BumpPtrAllocator& Alloc, bool canonicalize = true) + : F(Alloc), Canonicalize(canonicalize) {} + + /// GetEmptySet - Returns an immutable set that contains no elements. + ImmutableSet GetEmptySet() { + return ImmutableSet(F.GetEmptyTree()); + } + + /// Add - Creates a new immutable set that contains all of the values + /// of the original set with the addition of the specified value. If + /// the original set already included the value, then the original set is + /// returned and no memory is allocated. The time and space complexity + /// of this operation is logarithmic in the size of the original set. + /// The memory allocated to represent the set is released when the + /// factory object that created the set is destroyed. + ImmutableSet Add(ImmutableSet Old, value_type_ref V) { + TreeTy *NewT = F.Add(Old.Root, V); + return ImmutableSet(Canonicalize ? F.GetCanonicalTree(NewT) : NewT); + } + + /// Remove - Creates a new immutable set that contains all of the values + /// of the original set with the exception of the specified value. If + /// the original set did not contain the value, the original set is + /// returned and no memory is allocated. The time and space complexity + /// of this operation is logarithmic in the size of the original set. + /// The memory allocated to represent the set is released when the + /// factory object that created the set is destroyed. + ImmutableSet Remove(ImmutableSet Old, value_type_ref V) { + TreeTy *NewT = F.Remove(Old.Root, V); + return ImmutableSet(Canonicalize ? F.GetCanonicalTree(NewT) : NewT); + } + + BumpPtrAllocator& getAllocator() { return F.getAllocator(); } + + private: + Factory(const Factory& RHS); // DO NOT IMPLEMENT + void operator=(const Factory& RHS); // DO NOT IMPLEMENT + }; + + friend class Factory; + + /// contains - Returns true if the set contains the specified value. + bool contains(value_type_ref V) const { + return Root ? Root->contains(V) : false; + } + + bool operator==(ImmutableSet RHS) const { + return Root && RHS.Root ? Root->isEqual(*RHS.Root) : Root == RHS.Root; + } + + bool operator!=(ImmutableSet RHS) const { + return Root && RHS.Root ? Root->isNotEqual(*RHS.Root) : Root != RHS.Root; + } + + TreeTy *getRoot() { + return 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; } + + template + void foreach(Callback& C) { if (Root) Root->foreach(C); } + + template + void foreach() { if (Root) { Callback C; Root->foreach(C); } } + + //===--------------------------------------------------===// + // Iterators. + //===--------------------------------------------------===// + + class iterator { + typename TreeTy::iterator itr; + iterator(TreeTy* t) : itr(t) {} + friend class ImmutableSet; + 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. + //===--------------------------------------------------===// + + inline unsigned getHeight() const { return Root ? Root->getHeight() : 0; } + + static inline void Profile(FoldingSetNodeID& ID, const ImmutableSet& S) { + ID.AddPointer(S.Root); + } + + inline void Profile(FoldingSetNodeID& ID) const { + return Profile(ID,*this); + } + + //===--------------------------------------------------===// + // For testing. + //===--------------------------------------------------===// + + void verify() const { if (Root) Root->verify(); } +}; + +} // end namespace llvm + +#endif diff --git a/libclamav/c++/llvm/include/llvm/ADT/IndexedMap.h b/libclamav/c++/llvm/include/llvm/ADT/IndexedMap.h new file mode 100644 index 000000000..89f0dfa64 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/ADT/IndexedMap.h @@ -0,0 +1,75 @@ +//===- llvm/ADT/IndexedMap.h - An index map implementation ------*- 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 an indexed map. The index map template takes two +// types. The first is the mapped type and the second is a functor +// that maps its argument to a size_t. On instantiation a "null" value +// can be provided to be used as a "does not exist" indicator in the +// map. A member function grow() is provided that given the value of +// the maximally indexed key (the argument of the functor) makes sure +// the map has enough space for it. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_INDEXEDMAP_H +#define LLVM_ADT_INDEXEDMAP_H + +#include +#include +#include + +namespace llvm { + + struct IdentityFunctor : public std::unary_function { + unsigned operator()(unsigned Index) const { + return Index; + } + }; + + template + class IndexedMap { + typedef typename ToIndexT::argument_type IndexT; + typedef std::vector StorageT; + StorageT storage_; + T nullVal_; + ToIndexT toIndex_; + + public: + IndexedMap() : nullVal_(T()) { } + + explicit IndexedMap(const T& val) : nullVal_(val) { } + + typename StorageT::reference operator[](IndexT n) { + assert(toIndex_(n) < storage_.size() && "index out of bounds!"); + return storage_[toIndex_(n)]; + } + + typename StorageT::const_reference operator[](IndexT n) const { + assert(toIndex_(n) < storage_.size() && "index out of bounds!"); + return storage_[toIndex_(n)]; + } + + void clear() { + storage_.clear(); + } + + void grow(IndexT n) { + unsigned NewSize = toIndex_(n) + 1; + if (NewSize > storage_.size()) + storage_.resize(NewSize, nullVal_); + } + + typename StorageT::size_type size() const { + return storage_.size(); + } + }; + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/ADT/IntrusiveRefCntPtr.h b/libclamav/c++/llvm/include/llvm/ADT/IntrusiveRefCntPtr.h new file mode 100644 index 000000000..37d4ac9d2 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/ADT/IntrusiveRefCntPtr.h @@ -0,0 +1,230 @@ +//== llvm/ADT/IntrusiveRefCntPtr.h - Smart Refcounting Pointer ---*- 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 IntrusiveRefCntPtr, a template class that +// implements a "smart" pointer for objects that maintain their own +// internal reference count, and RefCountedBase/RefCountedBaseVPTR, two +// generic base classes for objects that wish to have their lifetimes +// managed using reference counting. +// +// IntrusiveRefCntPtr is similar to Boost's intrusive_ptr with added +// LLVM-style casting. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_INTRUSIVE_REF_CNT_PTR +#define LLVM_ADT_INTRUSIVE_REF_CNT_PTR + +#include + +#include "llvm/Support/Casting.h" + +namespace llvm { + + template + class IntrusiveRefCntPtr; + +//===----------------------------------------------------------------------===// +/// RefCountedBase - A generic base class for objects that wish to +/// have their lifetimes managed using reference counts. Classes +/// subclass RefCountedBase to obtain such functionality, and are +/// typically handled with IntrusivePtr "smart pointers" (see below) +/// which automatically handle the management of reference counts. +/// Objects that subclass RefCountedBase should not be allocated on +/// the stack, as invoking "delete" (which is called when the +/// reference count hits 0) on such objects is an error. +//===----------------------------------------------------------------------===// + template + class RefCountedBase { + unsigned ref_cnt; + + protected: + RefCountedBase() : ref_cnt(0) {} + + void Retain() { ++ref_cnt; } + void Release() { + assert (ref_cnt > 0 && "Reference count is already zero."); + if (--ref_cnt == 0) delete static_cast(this); + } + + friend class IntrusiveRefCntPtr; + }; + +//===----------------------------------------------------------------------===// +/// RefCountedBaseVPTR - A class that has the same function as +/// RefCountedBase, but with a virtual destructor. Should be used +/// instead of RefCountedBase for classes that already have virtual +/// methods to enforce dynamic allocation via 'new'. Classes that +/// inherit from RefCountedBaseVPTR can't be allocated on stack - +/// attempting to do this will produce a compile error. +//===----------------------------------------------------------------------===// + template + class RefCountedBaseVPTR { + unsigned ref_cnt; + + protected: + RefCountedBaseVPTR() : ref_cnt(0) {} + virtual ~RefCountedBaseVPTR() {} + + void Retain() { ++ref_cnt; } + void Release() { + assert (ref_cnt > 0 && "Reference count is already zero."); + if (--ref_cnt == 0) delete this; + } + + friend class IntrusiveRefCntPtr; + }; + +//===----------------------------------------------------------------------===// +/// IntrusiveRefCntPtr - A template class that implements a "smart pointer" +/// that assumes the wrapped object has a reference count associated +/// with it that can be managed via calls to +/// IntrusivePtrAddRef/IntrusivePtrRelease. The smart pointers +/// manage reference counts via the RAII idiom: upon creation of +/// smart pointer the reference count of the wrapped object is +/// incremented and upon destruction of the smart pointer the +/// reference count is decremented. This class also safely handles +/// wrapping NULL pointers. +/// +/// Reference counting is implemented via calls to +/// Obj->Retain()/Obj->Release(). Release() is required to destroy +/// the object when the reference count reaches zero. Inheriting from +/// RefCountedBase/RefCountedBaseVPTR takes care of this +/// automatically. +//===----------------------------------------------------------------------===// + template + class IntrusiveRefCntPtr { + T* Obj; + typedef IntrusiveRefCntPtr this_type; + public: + typedef T element_type; + + explicit IntrusiveRefCntPtr() : Obj(0) {} + + explicit IntrusiveRefCntPtr(T* obj) : Obj(obj) { + retain(); + } + + IntrusiveRefCntPtr(const IntrusiveRefCntPtr& S) : Obj(S.Obj) { + retain(); + } + + template + IntrusiveRefCntPtr(const IntrusiveRefCntPtr& S) + : Obj(S.getPtr()) { + retain(); + } + + IntrusiveRefCntPtr& operator=(const IntrusiveRefCntPtr& S) { + replace(S.getPtr()); + return *this; + } + + template + IntrusiveRefCntPtr& operator=(const IntrusiveRefCntPtr& S) { + replace(S.getPtr()); + return *this; + } + + IntrusiveRefCntPtr& operator=(T * S) { + replace(S); + return *this; + } + + ~IntrusiveRefCntPtr() { release(); } + + T& operator*() const { return *Obj; } + + T* operator->() const { return Obj; } + + T* getPtr() const { return Obj; } + + typedef T* (IntrusiveRefCntPtr::*unspecified_bool_type) () const; + operator unspecified_bool_type() const { + return Obj == 0 ? 0 : &IntrusiveRefCntPtr::getPtr; + } + + void swap(IntrusiveRefCntPtr& other) { + T* tmp = other.Obj; + other.Obj = Obj; + Obj = tmp; + } + + private: + void retain() { if (Obj) Obj->Retain(); } + void release() { if (Obj) Obj->Release(); } + + void replace(T* S) { + this_type(S).swap(*this); + } + }; + + template + inline bool operator==(const IntrusiveRefCntPtr& A, + const IntrusiveRefCntPtr& B) + { + return A.getPtr() == B.getPtr(); + } + + template + inline bool operator!=(const IntrusiveRefCntPtr& A, + const IntrusiveRefCntPtr& B) + { + return A.getPtr() != B.getPtr(); + } + + template + inline bool operator==(const IntrusiveRefCntPtr& A, + U* B) + { + return A.getPtr() == B; + } + + template + inline bool operator!=(const IntrusiveRefCntPtr& A, + U* B) + { + return A.getPtr() != B; + } + + template + inline bool operator==(T* A, + const IntrusiveRefCntPtr& B) + { + return A == B.getPtr(); + } + + template + inline bool operator!=(T* A, + const IntrusiveRefCntPtr& B) + { + return A != B.getPtr(); + } + +//===----------------------------------------------------------------------===// +// LLVM-style downcasting support for IntrusiveRefCntPtr objects +//===----------------------------------------------------------------------===// + + template struct simplify_type > { + typedef T* SimpleType; + static SimpleType getSimplifiedValue(const IntrusiveRefCntPtr& Val) { + return Val.getPtr(); + } + }; + + template struct simplify_type > { + typedef T* SimpleType; + static SimpleType getSimplifiedValue(const IntrusiveRefCntPtr& Val) { + return Val.getPtr(); + } + }; + +} // end namespace llvm + +#endif // LLVM_ADT_INTRUSIVE_REF_CNT_PTR diff --git a/libclamav/c++/llvm/include/llvm/ADT/OwningPtr.h b/libclamav/c++/llvm/include/llvm/ADT/OwningPtr.h new file mode 100644 index 000000000..cc53c8c30 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/ADT/OwningPtr.h @@ -0,0 +1,134 @@ +//===- llvm/ADT/OwningPtr.h - Smart ptr that owns the pointee ---*- 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 and implements the OwningPtr class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_OWNING_PTR_H +#define LLVM_ADT_OWNING_PTR_H + +#include +#include + +namespace llvm { + +/// OwningPtr smart pointer - OwningPtr mimics a built-in pointer except that it +/// guarantees deletion of the object pointed to, either on destruction of the +/// OwningPtr or via an explicit reset(). Once created, ownership of the +/// pointee object can be taken away from OwningPtr by using the take method. +template +class OwningPtr { + OwningPtr(OwningPtr const &); // DO NOT IMPLEMENT + OwningPtr &operator=(OwningPtr const &); // DO NOT IMPLEMENT + T *Ptr; +public: + explicit OwningPtr(T *P = 0) : Ptr(P) {} + + ~OwningPtr() { + delete Ptr; + } + + /// reset - Change the current pointee to the specified pointer. Note that + /// calling this with any pointer (including a null pointer) deletes the + /// current pointer. + void reset(T *P = 0) { + if (P == Ptr) return; + T *Tmp = Ptr; + Ptr = P; + delete Tmp; + } + + /// take - Reset the owning pointer to null and return its pointer. This does + /// not delete the pointer before returning it. + T *take() { + T *Tmp = Ptr; + Ptr = 0; + return Tmp; + } + + T &operator*() const { + assert(Ptr && "Cannot dereference null pointer"); + return *Ptr; + } + + T *operator->() const { return Ptr; } + T *get() const { return Ptr; } + operator bool() const { return Ptr != 0; } + bool operator!() const { return Ptr == 0; } + + void swap(OwningPtr &RHS) { + T *Tmp = RHS.Ptr; + RHS.Ptr = Ptr; + Ptr = Tmp; + } +}; + +template +inline void swap(OwningPtr &a, OwningPtr &b) { + a.swap(b); +} + +/// OwningArrayPtr smart pointer - OwningArrayPtr provides the same +/// functionality as OwningPtr, except that it works for array types. +template +class OwningArrayPtr { + OwningArrayPtr(OwningArrayPtr const &); // DO NOT IMPLEMENT + OwningArrayPtr &operator=(OwningArrayPtr const &); // DO NOT IMPLEMENT + T *Ptr; +public: + explicit OwningArrayPtr(T *P = 0) : Ptr(P) {} + + ~OwningArrayPtr() { + delete [] Ptr; + } + + /// reset - Change the current pointee to the specified pointer. Note that + /// calling this with any pointer (including a null pointer) deletes the + /// current pointer. + void reset(T *P = 0) { + if (P == Ptr) return; + T *Tmp = Ptr; + Ptr = P; + delete [] Tmp; + } + + /// take - Reset the owning pointer to null and return its pointer. This does + /// not delete the pointer before returning it. + T *take() { + T *Tmp = Ptr; + Ptr = 0; + return Tmp; + } + + T &operator[](std::ptrdiff_t i) const { + assert(Ptr && "Cannot dereference null pointer"); + return Ptr[i]; + } + + T *get() const { return Ptr; } + operator bool() const { return Ptr != 0; } + bool operator!() const { return Ptr == 0; } + + void swap(OwningArrayPtr &RHS) { + T *Tmp = RHS.Ptr; + RHS.Ptr = Ptr; + Ptr = Tmp; + } +}; + +template +inline void swap(OwningArrayPtr &a, OwningArrayPtr &b) { + a.swap(b); +} + + +} // end namespace llvm + +#endif diff --git a/libclamav/c++/llvm/include/llvm/ADT/PointerIntPair.h b/libclamav/c++/llvm/include/llvm/ADT/PointerIntPair.h new file mode 100644 index 000000000..73ba3c729 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/ADT/PointerIntPair.h @@ -0,0 +1,151 @@ +//===- llvm/ADT/PointerIntPair.h - Pair for pointer and int -----*- 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 the PointerIntPair class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_POINTERINTPAIR_H +#define LLVM_ADT_POINTERINTPAIR_H + +#include "llvm/Support/PointerLikeTypeTraits.h" +#include + +namespace llvm { + +template +struct DenseMapInfo; + +/// PointerIntPair - This class implements a pair of a pointer and small +/// integer. It is designed to represent this in the space required by one +/// pointer by bitmangling the integer into the low part of the pointer. This +/// can only be done for small integers: typically up to 3 bits, but it depends +/// on the number of bits available according to PointerLikeTypeTraits for the +/// type. +/// +/// Note that PointerIntPair always puts the Int part in the highest bits +/// possible. For example, PointerIntPair will put the bit for +/// the bool into bit #2, not bit #0, which allows the low two bits to be used +/// for something else. For example, this allows: +/// PointerIntPair, 1, bool> +/// ... and the two bools will land in different bits. +/// +template > +class PointerIntPair { + intptr_t Value; + enum { + /// PointerBitMask - The bits that come from the pointer. + PointerBitMask = + ~(uintptr_t)(((intptr_t)1 << PtrTraits::NumLowBitsAvailable)-1), + + /// IntShift - The number of low bits that we reserve for other uses, and + /// keep zero. + IntShift = (uintptr_t)PtrTraits::NumLowBitsAvailable-IntBits, + + /// IntMask - This is the unshifted mask for valid bits of the int type. + IntMask = (uintptr_t)(((intptr_t)1 << IntBits)-1), + + // ShiftedIntMask - This is the bits for the integer shifted in place. + ShiftedIntMask = (uintptr_t)(IntMask << IntShift) + }; +public: + PointerIntPair() : Value(0) {} + PointerIntPair(PointerTy Ptr, IntType Int) : Value(0) { + assert(IntBits <= PtrTraits::NumLowBitsAvailable && + "PointerIntPair formed with integer size too large for pointer"); + setPointer(Ptr); + setInt(Int); + } + + PointerTy getPointer() const { + return PtrTraits::getFromVoidPointer( + reinterpret_cast(Value & PointerBitMask)); + } + + IntType getInt() const { + return (IntType)((Value >> IntShift) & IntMask); + } + + void setPointer(PointerTy Ptr) { + intptr_t PtrVal + = reinterpret_cast(PtrTraits::getAsVoidPointer(Ptr)); + assert((PtrVal & ((1 << PtrTraits::NumLowBitsAvailable)-1)) == 0 && + "Pointer is not sufficiently aligned"); + // Preserve all low bits, just update the pointer. + Value = PtrVal | (Value & ~PointerBitMask); + } + + void setInt(IntType Int) { + intptr_t IntVal = Int; + assert(IntVal < (1 << IntBits) && "Integer too large for field"); + + // Preserve all bits other than the ones we are updating. + Value &= ~ShiftedIntMask; // Remove integer field. + Value |= IntVal << IntShift; // Set new integer. + } + + void *getOpaqueValue() const { return reinterpret_cast(Value); } + void setFromOpaqueValue(void *Val) { Value = reinterpret_cast(Val);} + + static PointerIntPair getFromOpaqueValue(void *V) { + PointerIntPair P; P.setFromOpaqueValue(V); return P; + } + + bool operator==(const PointerIntPair &RHS) const {return Value == RHS.Value;} + bool operator!=(const PointerIntPair &RHS) const {return Value != RHS.Value;} + bool operator<(const PointerIntPair &RHS) const {return Value < RHS.Value;} + bool operator>(const PointerIntPair &RHS) const {return Value > RHS.Value;} + bool operator<=(const PointerIntPair &RHS) const {return Value <= RHS.Value;} + bool operator>=(const PointerIntPair &RHS) const {return Value >= RHS.Value;} +}; + +// Provide specialization of DenseMapInfo for PointerIntPair. +template +struct DenseMapInfo > { + typedef PointerIntPair Ty; + static Ty getEmptyKey() { + intptr_t Val = -1; + Val <<= PointerLikeTypeTraits::NumLowBitsAvailable; + return Ty(reinterpret_cast(Val), IntType((1 << IntBits)-1)); + } + static Ty getTombstoneKey() { + intptr_t Val = -2; + Val <<= PointerLikeTypeTraits::NumLowBitsAvailable; + return Ty(reinterpret_cast(Val), IntType(0)); + } + static unsigned getHashValue(Ty V) { + uintptr_t IV = reinterpret_cast(V.getOpaqueValue()); + return unsigned(IV) ^ unsigned(IV >> 9); + } + static bool isEqual(const Ty &LHS, const Ty &RHS) { return LHS == RHS; } + static bool isPod() { return true; } +}; + +// Teach SmallPtrSet that PointerIntPair is "basically a pointer". +template +class PointerLikeTypeTraits > { +public: + static inline void * + getAsVoidPointer(const PointerIntPair &P) { + return P.getOpaqueValue(); + } + static inline PointerIntPair + getFromVoidPointer(void *P) { + return PointerIntPair::getFromOpaqueValue(P); + } + enum { + NumLowBitsAvailable = PtrTraits::NumLowBitsAvailable - IntBits + }; +}; + +} // end namespace llvm +#endif diff --git a/libclamav/c++/llvm/include/llvm/ADT/PointerUnion.h b/libclamav/c++/llvm/include/llvm/ADT/PointerUnion.h new file mode 100644 index 000000000..49c894092 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/ADT/PointerUnion.h @@ -0,0 +1,371 @@ +//===- llvm/ADT/PointerUnion.h - Discriminated Union of 2 Ptrs --*- 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 the PointerUnion class, which is a discriminated union of +// pointer types. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_POINTERUNION_H +#define LLVM_ADT_POINTERUNION_H + +#include "llvm/ADT/PointerIntPair.h" + +namespace llvm { + + /// getPointerUnionTypeNum - If the argument has type PT1* or PT2* return + /// false or true respectively. + template + static inline int getPointerUnionTypeNum(PT1 *P) { return 0; } + template + static inline int getPointerUnionTypeNum(PT2 *P) { return 1; } + template + static inline int getPointerUnionTypeNum(...) { return -1; } + + + /// Provide PointerLikeTypeTraits for void* that is used by PointerUnion + /// for the two template arguments. + template + class PointerUnionUIntTraits { + public: + static inline void *getAsVoidPointer(void *P) { return P; } + static inline void *getFromVoidPointer(void *P) { return P; } + enum { + PT1BitsAv = PointerLikeTypeTraits::NumLowBitsAvailable, + PT2BitsAv = PointerLikeTypeTraits::NumLowBitsAvailable, + NumLowBitsAvailable = PT1BitsAv < PT2BitsAv ? PT1BitsAv : PT2BitsAv + }; + }; + + /// PointerUnion - This implements a discriminated union of two pointer types, + /// and keeps the discriminator bit-mangled into the low bits of the pointer. + /// This allows the implementation to be extremely efficient in space, but + /// permits a very natural and type-safe API. + /// + /// Common use patterns would be something like this: + /// PointerUnion P; + /// P = (int*)0; + /// printf("%d %d", P.is(), P.is()); // prints "1 0" + /// X = P.get(); // ok. + /// Y = P.get(); // runtime assertion failure. + /// Z = P.get(); // runtime assertion failure (regardless of tag) + /// P = (float*)0; + /// Y = P.get(); // ok. + /// X = P.get(); // runtime assertion failure. + template + class PointerUnion { + public: + typedef PointerIntPair > ValTy; + private: + ValTy Val; + public: + PointerUnion() {} + + PointerUnion(PT1 V) { + Val.setPointer( + const_cast(PointerLikeTypeTraits::getAsVoidPointer(V))); + Val.setInt(0); + } + PointerUnion(PT2 V) { + Val.setPointer( + const_cast(PointerLikeTypeTraits::getAsVoidPointer(V))); + Val.setInt(1); + } + + /// isNull - Return true if the pointer held in the union is null, + /// regardless of which type it is. + bool isNull() const { return Val.getPointer() == 0; } + operator bool() const { return !isNull(); } + + /// is() return true if the Union currently holds the type matching T. + template + int is() const { + int TyNo = ::llvm::getPointerUnionTypeNum((T*)0); + assert(TyNo != -1 && "Type query could never succeed on PointerUnion!"); + return static_cast(Val.getInt()) == TyNo; + } + + /// get() - Return the value of the specified pointer type. If the + /// specified pointer type is incorrect, assert. + template + T get() const { + assert(is() && "Invalid accessor called"); + return PointerLikeTypeTraits::getFromVoidPointer(Val.getPointer()); + } + + /// dyn_cast() - If the current value is of the specified pointer type, + /// return it, otherwise return null. + template + T dyn_cast() const { + if (is()) return get(); + return T(); + } + + /// Assignment operators - Allow assigning into this union from either + /// pointer type, setting the discriminator to remember what it came from. + const PointerUnion &operator=(const PT1 &RHS) { + Val.setPointer( + const_cast(PointerLikeTypeTraits::getAsVoidPointer(RHS))); + Val.setInt(0); + return *this; + } + const PointerUnion &operator=(const PT2 &RHS) { + Val.setPointer( + const_cast(PointerLikeTypeTraits::getAsVoidPointer(RHS))); + Val.setInt(1); + return *this; + } + + void *getOpaqueValue() const { return Val.getOpaqueValue(); } + static PointerUnion getFromOpaqueValue(void *VP) { + PointerUnion V; + V.Val = ValTy::getFromOpaqueValue(VP); + return V; + } + }; + + // Teach SmallPtrSet that PointerUnion is "basically a pointer", that has + // # low bits available = min(PT1bits,PT2bits)-1. + template + class PointerLikeTypeTraits > { + public: + static inline void * + getAsVoidPointer(const PointerUnion &P) { + return P.getOpaqueValue(); + } + static inline PointerUnion + getFromVoidPointer(void *P) { + return PointerUnion::getFromOpaqueValue(P); + } + + // The number of bits available are the min of the two pointer types. + enum { + NumLowBitsAvailable = + PointerLikeTypeTraits::ValTy> + ::NumLowBitsAvailable + }; + }; + + + /// PointerUnion3 - This is a pointer union of three pointer types. See + /// documentation for PointerUnion for usage. + template + class PointerUnion3 { + public: + typedef PointerUnion InnerUnion; + typedef PointerUnion ValTy; + private: + ValTy Val; + public: + PointerUnion3() {} + + PointerUnion3(PT1 V) { + Val = InnerUnion(V); + } + PointerUnion3(PT2 V) { + Val = InnerUnion(V); + } + PointerUnion3(PT3 V) { + Val = V; + } + + /// isNull - Return true if the pointer held in the union is null, + /// regardless of which type it is. + bool isNull() const { return Val.isNull(); } + operator bool() const { return !isNull(); } + + /// is() return true if the Union currently holds the type matching T. + template + int is() const { + // Is it PT1/PT2? + if (::llvm::getPointerUnionTypeNum((T*)0) != -1) + return Val.template is() && + Val.template get().template is(); + return Val.template is(); + } + + /// get() - Return the value of the specified pointer type. If the + /// specified pointer type is incorrect, assert. + template + T get() const { + assert(is() && "Invalid accessor called"); + // Is it PT1/PT2? + if (::llvm::getPointerUnionTypeNum((T*)0) != -1) + return Val.template get().template get(); + + return Val.template get(); + } + + /// dyn_cast() - If the current value is of the specified pointer type, + /// return it, otherwise return null. + template + T dyn_cast() const { + if (is()) return get(); + return T(); + } + + /// Assignment operators - Allow assigning into this union from either + /// pointer type, setting the discriminator to remember what it came from. + const PointerUnion3 &operator=(const PT1 &RHS) { + Val = InnerUnion(RHS); + return *this; + } + const PointerUnion3 &operator=(const PT2 &RHS) { + Val = InnerUnion(RHS); + return *this; + } + const PointerUnion3 &operator=(const PT3 &RHS) { + Val = RHS; + return *this; + } + + void *getOpaqueValue() const { return Val.getOpaqueValue(); } + static PointerUnion3 getFromOpaqueValue(void *VP) { + PointerUnion3 V; + V.Val = ValTy::getFromOpaqueValue(VP); + return V; + } + }; + + // Teach SmallPtrSet that PointerUnion3 is "basically a pointer", that has + // # low bits available = min(PT1bits,PT2bits,PT2bits)-2. + template + class PointerLikeTypeTraits > { + public: + static inline void * + getAsVoidPointer(const PointerUnion3 &P) { + return P.getOpaqueValue(); + } + static inline PointerUnion3 + getFromVoidPointer(void *P) { + return PointerUnion3::getFromOpaqueValue(P); + } + + // The number of bits available are the min of the two pointer types. + enum { + NumLowBitsAvailable = + PointerLikeTypeTraits::ValTy> + ::NumLowBitsAvailable + }; + }; + + /// PointerUnion4 - This is a pointer union of four pointer types. See + /// documentation for PointerUnion for usage. + template + class PointerUnion4 { + public: + typedef PointerUnion InnerUnion1; + typedef PointerUnion InnerUnion2; + typedef PointerUnion ValTy; + private: + ValTy Val; + public: + PointerUnion4() {} + + PointerUnion4(PT1 V) { + Val = InnerUnion1(V); + } + PointerUnion4(PT2 V) { + Val = InnerUnion1(V); + } + PointerUnion4(PT3 V) { + Val = InnerUnion2(V); + } + PointerUnion4(PT4 V) { + Val = InnerUnion2(V); + } + + /// isNull - Return true if the pointer held in the union is null, + /// regardless of which type it is. + bool isNull() const { return Val.isNull(); } + operator bool() const { return !isNull(); } + + /// is() return true if the Union currently holds the type matching T. + template + int is() const { + // Is it PT1/PT2? + if (::llvm::getPointerUnionTypeNum((T*)0) != -1) + return Val.template is() && + Val.template get().template is(); + return Val.template is() && + Val.template get().template is(); + } + + /// get() - Return the value of the specified pointer type. If the + /// specified pointer type is incorrect, assert. + template + T get() const { + assert(is() && "Invalid accessor called"); + // Is it PT1/PT2? + if (::llvm::getPointerUnionTypeNum((T*)0) != -1) + return Val.template get().template get(); + + return Val.template get().template get(); + } + + /// dyn_cast() - If the current value is of the specified pointer type, + /// return it, otherwise return null. + template + T dyn_cast() const { + if (is()) return get(); + return T(); + } + + /// Assignment operators - Allow assigning into this union from either + /// pointer type, setting the discriminator to remember what it came from. + const PointerUnion4 &operator=(const PT1 &RHS) { + Val = InnerUnion1(RHS); + return *this; + } + const PointerUnion4 &operator=(const PT2 &RHS) { + Val = InnerUnion1(RHS); + return *this; + } + const PointerUnion4 &operator=(const PT3 &RHS) { + Val = InnerUnion2(RHS); + return *this; + } + const PointerUnion4 &operator=(const PT4 &RHS) { + Val = InnerUnion2(RHS); + return *this; + } + + void *getOpaqueValue() const { return Val.getOpaqueValue(); } + static PointerUnion4 getFromOpaqueValue(void *VP) { + PointerUnion4 V; + V.Val = ValTy::getFromOpaqueValue(VP); + return V; + } + }; + + // Teach SmallPtrSet that PointerUnion4 is "basically a pointer", that has + // # low bits available = min(PT1bits,PT2bits,PT2bits)-2. + template + class PointerLikeTypeTraits > { + public: + static inline void * + getAsVoidPointer(const PointerUnion4 &P) { + return P.getOpaqueValue(); + } + static inline PointerUnion4 + getFromVoidPointer(void *P) { + return PointerUnion4::getFromOpaqueValue(P); + } + + // The number of bits available are the min of the two pointer types. + enum { + NumLowBitsAvailable = + PointerLikeTypeTraits::ValTy> + ::NumLowBitsAvailable + }; + }; +} + +#endif diff --git a/libclamav/c++/llvm/include/llvm/ADT/PostOrderIterator.h b/libclamav/c++/llvm/include/llvm/ADT/PostOrderIterator.h new file mode 100644 index 000000000..8315bc9f9 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/ADT/PostOrderIterator.h @@ -0,0 +1,233 @@ +//===- llvm/ADT/PostOrderIterator.h - PostOrder iterator --------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file builds on the ADT/GraphTraits.h file to build a generic graph +// post order iterator. This should work over any graph type that has a +// GraphTraits specialization. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_POSTORDERITERATOR_H +#define LLVM_ADT_POSTORDERITERATOR_H + +#include "llvm/ADT/GraphTraits.h" +#include "llvm/ADT/SmallPtrSet.h" +#include +#include +#include + +namespace llvm { + +template // Non-external set +class po_iterator_storage { +public: + SetType Visited; +}; + +template +class po_iterator_storage { +public: + po_iterator_storage(SetType &VSet) : Visited(VSet) {} + po_iterator_storage(const po_iterator_storage &S) : Visited(S.Visited) {} + SetType &Visited; +}; + +template::NodeType*, 8>, + bool ExtStorage = false, + class GT = GraphTraits > +class po_iterator : public std::iterator, + public po_iterator_storage { + typedef std::iterator super; + typedef typename GT::NodeType NodeType; + typedef typename GT::ChildIteratorType ChildItTy; + + // VisitStack - Used to maintain the ordering. Top = current block + // First element is basic block pointer, second is the 'next child' to visit + std::stack > VisitStack; + + void traverseChild() { + while (VisitStack.top().second != GT::child_end(VisitStack.top().first)) { + NodeType *BB = *VisitStack.top().second++; + if (!this->Visited.count(BB)) { // If the block is not visited... + this->Visited.insert(BB); + VisitStack.push(std::make_pair(BB, GT::child_begin(BB))); + } + } + } + + inline po_iterator(NodeType *BB) { + this->Visited.insert(BB); + VisitStack.push(std::make_pair(BB, GT::child_begin(BB))); + traverseChild(); + } + inline po_iterator() {} // End is when stack is empty. + + inline po_iterator(NodeType *BB, SetType &S) : + po_iterator_storage(S) { + if(!S.count(BB)) { + this->Visited.insert(BB); + VisitStack.push(std::make_pair(BB, GT::child_begin(BB))); + traverseChild(); + } + } + + inline po_iterator(SetType &S) : + po_iterator_storage(S) { + } // End is when stack is empty. +public: + typedef typename super::pointer pointer; + typedef po_iterator _Self; + + // Provide static "constructors"... + static inline _Self begin(GraphT G) { return _Self(GT::getEntryNode(G)); } + static inline _Self end (GraphT G) { return _Self(); } + + static inline _Self begin(GraphT G, SetType &S) { + return _Self(GT::getEntryNode(G), S); + } + static inline _Self end (GraphT G, SetType &S) { return _Self(S); } + + inline bool operator==(const _Self& x) const { + return VisitStack == x.VisitStack; + } + inline bool operator!=(const _Self& x) const { return !operator==(x); } + + inline pointer operator*() const { + return VisitStack.top().first; + } + + // This is a nonstandard operator-> that dereferences the pointer an extra + // time... so that you can actually call methods ON the BasicBlock, because + // the contained type is a pointer. This allows BBIt->getTerminator() f.e. + // + inline NodeType *operator->() const { return operator*(); } + + inline _Self& operator++() { // Preincrement + VisitStack.pop(); + if (!VisitStack.empty()) + traverseChild(); + return *this; + } + + inline _Self operator++(int) { // Postincrement + _Self tmp = *this; ++*this; return tmp; + } +}; + +// Provide global constructors that automatically figure out correct types... +// +template +po_iterator po_begin(T G) { return po_iterator::begin(G); } +template +po_iterator po_end (T G) { return po_iterator::end(G); } + +// Provide global definitions of external postorder iterators... +template::NodeType*> > +struct po_ext_iterator : public po_iterator { + po_ext_iterator(const po_iterator &V) : + po_iterator(V) {} +}; + +template +po_ext_iterator po_ext_begin(T G, SetType &S) { + return po_ext_iterator::begin(G, S); +} + +template +po_ext_iterator po_ext_end(T G, SetType &S) { + return po_ext_iterator::end(G, S); +} + +// Provide global definitions of inverse post order iterators... +template ::NodeType*>, + bool External = false> +struct ipo_iterator : public po_iterator, SetType, External > { + ipo_iterator(const po_iterator, SetType, External> &V) : + po_iterator, SetType, External> (V) {} +}; + +template +ipo_iterator ipo_begin(T G, bool Reverse = false) { + return ipo_iterator::begin(G, Reverse); +} + +template +ipo_iterator ipo_end(T G){ + return ipo_iterator::end(G); +} + +//Provide global definitions of external inverse postorder iterators... +template ::NodeType*> > +struct ipo_ext_iterator : public ipo_iterator { + ipo_ext_iterator(const ipo_iterator &V) : + ipo_iterator(&V) {} + ipo_ext_iterator(const po_iterator, SetType, true> &V) : + ipo_iterator(&V) {} +}; + +template +ipo_ext_iterator ipo_ext_begin(T G, SetType &S) { + return ipo_ext_iterator::begin(G, S); +} + +template +ipo_ext_iterator ipo_ext_end(T G, SetType &S) { + return ipo_ext_iterator::end(G, S); +} + +//===--------------------------------------------------------------------===// +// Reverse Post Order CFG iterator code +//===--------------------------------------------------------------------===// +// +// This is used to visit basic blocks in a method in reverse post order. This +// class is awkward to use because I don't know a good incremental algorithm to +// computer RPO from a graph. Because of this, the construction of the +// ReversePostOrderTraversal object is expensive (it must walk the entire graph +// with a postorder iterator to build the data structures). The moral of this +// story is: Don't create more ReversePostOrderTraversal classes than necessary. +// +// This class should be used like this: +// { +// ReversePostOrderTraversal RPOT(FuncPtr); // Expensive to create +// for (rpo_iterator I = RPOT.begin(); I != RPOT.end(); ++I) { +// ... +// } +// for (rpo_iterator I = RPOT.begin(); I != RPOT.end(); ++I) { +// ... +// } +// } +// + +template > +class ReversePostOrderTraversal { + typedef typename GT::NodeType NodeType; + std::vector Blocks; // Block list in normal PO order + inline void Initialize(NodeType *BB) { + copy(po_begin(BB), po_end(BB), back_inserter(Blocks)); + } +public: + typedef typename std::vector::reverse_iterator rpo_iterator; + + inline ReversePostOrderTraversal(GraphT G) { + Initialize(GT::getEntryNode(G)); + } + + // Because we want a reverse post order, use reverse iterators from the vector + inline rpo_iterator begin() { return Blocks.rbegin(); } + inline rpo_iterator end() { return Blocks.rend(); } +}; + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/ADT/PriorityQueue.h b/libclamav/c++/llvm/include/llvm/ADT/PriorityQueue.h new file mode 100644 index 000000000..bf8a68708 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/ADT/PriorityQueue.h @@ -0,0 +1,84 @@ +//===- llvm/ADT/PriorityQueue.h - Priority queues ---------------*- 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 the PriorityQueue class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_PRIORITY_QUEUE_H +#define LLVM_ADT_PRIORITY_QUEUE_H + +#include +#include + +namespace llvm { + +/// PriorityQueue - This class behaves like std::priority_queue and +/// provides a few additional convenience functions. +/// +template, + class Compare = std::less > +class PriorityQueue : public std::priority_queue { +public: + explicit PriorityQueue(const Compare &compare = Compare(), + const Sequence &sequence = Sequence()) + : std::priority_queue(compare, sequence) + {} + + template + PriorityQueue(Iterator begin, Iterator end, + const Compare &compare = Compare(), + const Sequence &sequence = Sequence()) + : std::priority_queue(begin, end, compare, sequence) + {} + + /// erase_one - Erase one element from the queue, regardless of its + /// position. This operation performs a linear search to find an element + /// equal to t, but then uses all logarithmic-time algorithms to do + /// the erase operation. + /// + void erase_one(const T &t) { + // Linear-search to find the element. + typename Sequence::size_type i = + std::find(this->c.begin(), this->c.end(), t) - this->c.begin(); + + // Logarithmic-time heap bubble-up. + while (i != 0) { + typename Sequence::size_type parent = (i - 1) / 2; + this->c[i] = this->c[parent]; + i = parent; + } + + // The element we want to remove is now at the root, so we can use + // priority_queue's plain pop to remove it. + this->pop(); + } + + /// reheapify - If an element in the queue has changed in a way that + /// affects its standing in the comparison function, the queue's + /// internal state becomes invalid. Calling reheapify() resets the + /// queue's state, making it valid again. This operation has time + /// complexity proportional to the number of elements in the queue, + /// so don't plan to use it a lot. + /// + void reheapify() { + std::make_heap(this->c.begin(), this->c.end(), this->comp); + } + + /// clear - Erase all elements from the queue. + /// + void clear() { + this->c.clear(); + } +}; + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/ADT/SCCIterator.h b/libclamav/c++/llvm/include/llvm/ADT/SCCIterator.h new file mode 100644 index 000000000..3afcabd83 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/ADT/SCCIterator.h @@ -0,0 +1,210 @@ +//===-- Support/SCCIterator.h - Strongly Connected Comp. Iter. --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This builds on the llvm/ADT/GraphTraits.h file to find the strongly connected +// components (SCCs) of a graph in O(N+E) time using Tarjan's DFS algorithm. +// +// The SCC iterator has the important property that if a node in SCC S1 has an +// edge to a node in SCC S2, then it visits S1 *after* S2. +// +// To visit S1 *before* S2, use the scc_iterator on the Inverse graph. +// (NOTE: This requires some simple wrappers and is not supported yet.) +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_SCCITERATOR_H +#define LLVM_ADT_SCCITERATOR_H + +#include "llvm/ADT/GraphTraits.h" +#include "llvm/ADT/DenseMap.h" +#include + +namespace llvm { + +//===----------------------------------------------------------------------===// +/// +/// scc_iterator - Enumerate the SCCs of a directed graph, in +/// reverse topological order of the SCC DAG. +/// +template > +class scc_iterator + : public std::iterator, ptrdiff_t> { + typedef typename GT::NodeType NodeType; + typedef typename GT::ChildIteratorType ChildItTy; + typedef std::vector SccTy; + typedef std::iterator, ptrdiff_t> super; + typedef typename super::reference reference; + typedef typename super::pointer pointer; + + // The visit counters used to detect when a complete SCC is on the stack. + // visitNum is the global counter. + // nodeVisitNumbers are per-node visit numbers, also used as DFS flags. + unsigned visitNum; + DenseMap nodeVisitNumbers; + + // SCCNodeStack - Stack holding nodes of the SCC. + std::vector SCCNodeStack; + + // CurrentSCC - The current SCC, retrieved using operator*(). + SccTy CurrentSCC; + + // VisitStack - Used to maintain the ordering. Top = current block + // First element is basic block pointer, second is the 'next child' to visit + std::vector > VisitStack; + + // MinVistNumStack - Stack holding the "min" values for each node in the DFS. + // This is used to track the minimum uplink values for all children of + // the corresponding node on the VisitStack. + std::vector MinVisitNumStack; + + // A single "visit" within the non-recursive DFS traversal. + void DFSVisitOne(NodeType* N) { + ++visitNum; // Global counter for the visit order + nodeVisitNumbers[N] = visitNum; + SCCNodeStack.push_back(N); + MinVisitNumStack.push_back(visitNum); + VisitStack.push_back(std::make_pair(N, GT::child_begin(N))); + //errs() << "TarjanSCC: Node " << N << + // " : visitNum = " << visitNum << "\n"; + } + + // The stack-based DFS traversal; defined below. + void DFSVisitChildren() { + assert(!VisitStack.empty()); + while (VisitStack.back().second != GT::child_end(VisitStack.back().first)) { + // TOS has at least one more child so continue DFS + NodeType *childN = *VisitStack.back().second++; + if (!nodeVisitNumbers.count(childN)) { + // this node has never been seen + DFSVisitOne(childN); + } else { + unsigned childNum = nodeVisitNumbers[childN]; + if (MinVisitNumStack.back() > childNum) + MinVisitNumStack.back() = childNum; + } + } + } + + // Compute the next SCC using the DFS traversal. + void GetNextSCC() { + assert(VisitStack.size() == MinVisitNumStack.size()); + CurrentSCC.clear(); // Prepare to compute the next SCC + while (!VisitStack.empty()) { + DFSVisitChildren(); + assert(VisitStack.back().second ==GT::child_end(VisitStack.back().first)); + NodeType* visitingN = VisitStack.back().first; + unsigned minVisitNum = MinVisitNumStack.back(); + VisitStack.pop_back(); + MinVisitNumStack.pop_back(); + if (!MinVisitNumStack.empty() && MinVisitNumStack.back() > minVisitNum) + MinVisitNumStack.back() = minVisitNum; + + //errs() << "TarjanSCC: Popped node " << visitingN << + // " : minVisitNum = " << minVisitNum << "; Node visit num = " << + // nodeVisitNumbers[visitingN] << "\n"; + + if (minVisitNum == nodeVisitNumbers[visitingN]) { + // A full SCC is on the SCCNodeStack! It includes all nodes below + // visitingN on the stack. Copy those nodes to CurrentSCC, + // reset their minVisit values, and return (this suspends + // the DFS traversal till the next ++). + do { + CurrentSCC.push_back(SCCNodeStack.back()); + SCCNodeStack.pop_back(); + nodeVisitNumbers[CurrentSCC.back()] = ~0U; + } while (CurrentSCC.back() != visitingN); + return; + } + } + } + + inline scc_iterator(NodeType *entryN) : visitNum(0) { + DFSVisitOne(entryN); + GetNextSCC(); + } + inline scc_iterator() { /* End is when DFS stack is empty */ } + +public: + typedef scc_iterator _Self; + + // Provide static "constructors"... + static inline _Self begin(const GraphT& G) { return _Self(GT::getEntryNode(G)); } + static inline _Self end (const GraphT& G) { return _Self(); } + + // Direct loop termination test (I.fini() is more efficient than I == end()) + inline bool fini() const { + assert(!CurrentSCC.empty() || VisitStack.empty()); + return CurrentSCC.empty(); + } + + inline bool operator==(const _Self& x) const { + return VisitStack == x.VisitStack && CurrentSCC == x.CurrentSCC; + } + inline bool operator!=(const _Self& x) const { return !operator==(x); } + + // Iterator traversal: forward iteration only + inline _Self& operator++() { // Preincrement + GetNextSCC(); + return *this; + } + inline _Self operator++(int) { // Postincrement + _Self tmp = *this; ++*this; return tmp; + } + + // Retrieve a reference to the current SCC + inline const SccTy &operator*() const { + assert(!CurrentSCC.empty() && "Dereferencing END SCC iterator!"); + return CurrentSCC; + } + inline SccTy &operator*() { + assert(!CurrentSCC.empty() && "Dereferencing END SCC iterator!"); + return CurrentSCC; + } + + // hasLoop() -- Test if the current SCC has a loop. If it has more than one + // node, this is trivially true. If not, it may still contain a loop if the + // node has an edge back to itself. + bool hasLoop() const { + assert(!CurrentSCC.empty() && "Dereferencing END SCC iterator!"); + if (CurrentSCC.size() > 1) return true; + NodeType *N = CurrentSCC.front(); + for (ChildItTy CI = GT::child_begin(N), CE=GT::child_end(N); CI != CE; ++CI) + if (*CI == N) + return true; + return false; + } +}; + + +// Global constructor for the SCC iterator. +template +scc_iterator scc_begin(const T& G) { + return scc_iterator::begin(G); +} + +template +scc_iterator scc_end(const T& G) { + return scc_iterator::end(G); +} + +template +scc_iterator > scc_begin(const Inverse& G) { + return scc_iterator >::begin(G); +} + +template +scc_iterator > scc_end(const Inverse& G) { + return scc_iterator >::end(G); +} + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/ADT/STLExtras.h b/libclamav/c++/llvm/include/llvm/ADT/STLExtras.h new file mode 100644 index 000000000..32cf4590e --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/ADT/STLExtras.h @@ -0,0 +1,284 @@ +//===- llvm/ADT/STLExtras.h - Useful STL related functions ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains some templates that are useful if you are working with the +// STL at all. +// +// No library is required when using these functions. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_STLEXTRAS_H +#define LLVM_ADT_STLEXTRAS_H + +#include // for std::size_t +#include // for qsort +#include +#include +#include // for std::pair + +namespace llvm { + +//===----------------------------------------------------------------------===// +// Extra additions to +//===----------------------------------------------------------------------===// + +template +struct less_ptr : public std::binary_function { + bool operator()(const Ty* left, const Ty* right) const { + return *left < *right; + } +}; + +template +struct greater_ptr : public std::binary_function { + bool operator()(const Ty* left, const Ty* right) const { + return *right < *left; + } +}; + +// deleter - Very very very simple method that is used to invoke operator +// delete on something. It is used like this: +// +// for_each(V.begin(), B.end(), deleter); +// +template +static inline void deleter(T *Ptr) { + delete Ptr; +} + + + +//===----------------------------------------------------------------------===// +// Extra additions to +//===----------------------------------------------------------------------===// + +// mapped_iterator - This is a simple iterator adapter that causes a function to +// be dereferenced whenever operator* is invoked on the iterator. +// +template +class mapped_iterator { + RootIt current; + UnaryFunc Fn; +public: + typedef typename std::iterator_traits::iterator_category + iterator_category; + typedef typename std::iterator_traits::difference_type + difference_type; + typedef typename UnaryFunc::result_type value_type; + + typedef void pointer; + //typedef typename UnaryFunc::result_type *pointer; + typedef void reference; // Can't modify value returned by fn + + typedef RootIt iterator_type; + typedef mapped_iterator _Self; + + inline const RootIt &getCurrent() const { return current; } + inline const UnaryFunc &getFunc() const { return Fn; } + + inline explicit mapped_iterator(const RootIt &I, UnaryFunc F) + : current(I), Fn(F) {} + inline mapped_iterator(const mapped_iterator &It) + : current(It.current), Fn(It.Fn) {} + + inline value_type operator*() const { // All this work to do this + return Fn(*current); // little change + } + + _Self& operator++() { ++current; return *this; } + _Self& operator--() { --current; return *this; } + _Self operator++(int) { _Self __tmp = *this; ++current; return __tmp; } + _Self operator--(int) { _Self __tmp = *this; --current; return __tmp; } + _Self operator+ (difference_type n) const { + return _Self(current + n, Fn); + } + _Self& operator+= (difference_type n) { current += n; return *this; } + _Self operator- (difference_type n) const { + return _Self(current - n, Fn); + } + _Self& operator-= (difference_type n) { current -= n; return *this; } + reference operator[](difference_type n) const { return *(*this + n); } + + inline bool operator!=(const _Self &X) const { return !operator==(X); } + inline bool operator==(const _Self &X) const { return current == X.current; } + inline bool operator< (const _Self &X) const { return current < X.current; } + + inline difference_type operator-(const _Self &X) const { + return current - X.current; + } +}; + +template +inline mapped_iterator<_Iterator, Func> +operator+(typename mapped_iterator<_Iterator, Func>::difference_type N, + const mapped_iterator<_Iterator, Func>& X) { + return mapped_iterator<_Iterator, Func>(X.getCurrent() - N, X.getFunc()); +} + + +// map_iterator - Provide a convenient way to create mapped_iterators, just like +// make_pair is useful for creating pairs... +// +template +inline mapped_iterator map_iterator(const ItTy &I, FuncTy F) { + return mapped_iterator(I, F); +} + + +// next/prior - These functions unlike std::advance do not modify the +// passed iterator but return a copy. +// +// next(myIt) returns copy of myIt incremented once +// next(myIt, n) returns copy of myIt incremented n times +// prior(myIt) returns copy of myIt decremented once +// prior(myIt, n) returns copy of myIt decremented n times + +template +inline ItTy next(ItTy it, Dist n) +{ + std::advance(it, n); + return it; +} + +template +inline ItTy next(ItTy it) +{ + return ++it; +} + +template +inline ItTy prior(ItTy it, Dist n) +{ + std::advance(it, -n); + return it; +} + +template +inline ItTy prior(ItTy it) +{ + return --it; +} + +//===----------------------------------------------------------------------===// +// Extra additions to +//===----------------------------------------------------------------------===// + +// tie - this function ties two objects and returns a temporary object +// that is assignable from a std::pair. This can be used to make code +// more readable when using values returned from functions bundled in +// a std::pair. Since an example is worth 1000 words: +// +// typedef std::map Int2IntMap; +// +// Int2IntMap myMap; +// Int2IntMap::iterator where; +// bool inserted; +// tie(where, inserted) = myMap.insert(std::make_pair(123,456)); +// +// if (inserted) +// // do stuff +// else +// // do other stuff + +namespace +{ + template + struct tier { + typedef T1 &first_type; + typedef T2 &second_type; + + first_type first; + second_type second; + + tier(first_type f, second_type s) : first(f), second(s) { } + tier& operator=(const std::pair& p) { + first = p.first; + second = p.second; + return *this; + } + }; +} + +template +inline tier tie(T1& f, T2& s) { + return tier(f, s); +} + +//===----------------------------------------------------------------------===// +// Extra additions for arrays +//===----------------------------------------------------------------------===// + +/// Find where an array ends (for ending iterators) +/// This returns a pointer to the byte immediately +/// after the end of an array. +template +inline T *array_endof(T (&x)[N]) { + return x+N; +} + +/// Find the length of an array. +template +inline size_t array_lengthof(T (&x)[N]) { + return N; +} + +/// array_pod_sort_comparator - This is helper function for array_pod_sort, +/// which just uses operator< on T. +template +static inline int array_pod_sort_comparator(const void *P1, const void *P2) { + if (*reinterpret_cast(P1) < *reinterpret_cast(P2)) + return -1; + if (*reinterpret_cast(P2) < *reinterpret_cast(P1)) + return 1; + return 0; +} + +/// get_array_pad_sort_comparator - This is an internal helper function used to +/// get type deduction of T right. +template +static int (*get_array_pad_sort_comparator(const T &X)) + (const void*, const void*) { + return array_pod_sort_comparator; +} + + +/// array_pod_sort - This sorts an array with the specified start and end +/// extent. This is just like std::sort, except that it calls qsort instead of +/// using an inlined template. qsort is slightly slower than std::sort, but +/// most sorts are not performance critical in LLVM and std::sort has to be +/// template instantiated for each type, leading to significant measured code +/// bloat. This function should generally be used instead of std::sort where +/// possible. +/// +/// This function assumes that you have simple POD-like types that can be +/// compared with operator< and can be moved with memcpy. If this isn't true, +/// you should use std::sort. +/// +/// NOTE: If qsort_r were portable, we could allow a custom comparator and +/// default to std::less. +template +static inline void array_pod_sort(IteratorTy Start, IteratorTy End) { + // Don't dereference start iterator of empty sequence. + if (Start == End) return; + qsort(&*Start, End-Start, sizeof(*Start), + get_array_pad_sort_comparator(*Start)); +} + +template +static inline void array_pod_sort(IteratorTy Start, IteratorTy End, + int (*Compare)(const void*, const void*)) { + // Don't dereference start iterator of empty sequence. + if (Start == End) return; + qsort(&*Start, End-Start, sizeof(*Start), Compare); +} + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/ADT/ScopedHashTable.h b/libclamav/c++/llvm/include/llvm/ADT/ScopedHashTable.h new file mode 100644 index 000000000..d5382954c --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/ADT/ScopedHashTable.h @@ -0,0 +1,193 @@ +//===- ScopedHashTable.h - A simple scoped hash table ---------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements an efficient scoped hash table, which is useful for +// things like dominator-based optimizations. This allows clients to do things +// like this: +// +// ScopedHashTable HT; +// { +// ScopedHashTableScope Scope1(HT); +// HT.insert(0, 0); +// HT.insert(1, 1); +// { +// ScopedHashTableScope Scope2(HT); +// HT.insert(0, 42); +// } +// } +// +// Looking up the value for "0" in the Scope2 block will return 42. Looking +// up the value for 0 before 42 is inserted or after Scope2 is popped will +// return 0. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_SCOPEDHASHTABLE_H +#define LLVM_ADT_SCOPEDHASHTABLE_H + +#include +#include "llvm/ADT/DenseMap.h" + +namespace llvm { + +template +class ScopedHashTable; + +template +class ScopedHashTableVal { + ScopedHashTableVal *NextInScope; + ScopedHashTableVal *NextForKey; + K Key; + V Val; +public: + ScopedHashTableVal(ScopedHashTableVal *nextInScope, + ScopedHashTableVal *nextForKey, const K &key, const V &val) + : NextInScope(nextInScope), NextForKey(nextForKey), Key(key), Val(val) { + } + + const K &getKey() const { return Key; } + const V &getValue() const { return Val; } + V &getValue() { return Val; } + + ScopedHashTableVal *getNextForKey() { return NextForKey; } + const ScopedHashTableVal *getNextForKey() const { return NextForKey; } +public: + ScopedHashTableVal *getNextInScope() { return NextInScope; } +}; + +template +class ScopedHashTableScope { + /// HT - The hashtable that we are active for. + ScopedHashTable &HT; + + /// PrevScope - This is the scope that we are shadowing in HT. + ScopedHashTableScope *PrevScope; + + /// LastValInScope - This is the last value that was inserted for this scope + /// or null if none have been inserted yet. + ScopedHashTableVal *LastValInScope; + void operator=(ScopedHashTableScope&); // DO NOT IMPLEMENT + ScopedHashTableScope(ScopedHashTableScope&); // DO NOT IMPLEMENT +public: + ScopedHashTableScope(ScopedHashTable &HT); + ~ScopedHashTableScope(); + +private: + friend class ScopedHashTable; + ScopedHashTableVal *getLastValInScope() { return LastValInScope; } + void setLastValInScope(ScopedHashTableVal *Val) { LastValInScope = Val; } +}; + + +template +class ScopedHashTableIterator { + ScopedHashTableVal *Node; +public: + ScopedHashTableIterator(ScopedHashTableVal *node) : Node(node){} + + V &operator*() const { + assert(Node && "Dereference end()"); + return Node->getValue(); + } + V *operator->() const { + return &Node->getValue(); + } + + bool operator==(const ScopedHashTableIterator &RHS) const { + return Node == RHS.Node; + } + bool operator!=(const ScopedHashTableIterator &RHS) const { + return Node != RHS.Node; + } + + inline ScopedHashTableIterator& operator++() { // Preincrement + assert(Node && "incrementing past end()"); + Node = Node->getNextForKey(); + return *this; + } + ScopedHashTableIterator operator++(int) { // Postincrement + ScopedHashTableIterator tmp = *this; ++*this; return tmp; + } +}; + + +template +class ScopedHashTable { + DenseMap*> TopLevelMap; + ScopedHashTableScope *CurScope; + ScopedHashTable(const ScopedHashTable&); // NOT YET IMPLEMENTED + void operator=(const ScopedHashTable&); // NOT YET IMPLEMENTED + friend class ScopedHashTableScope; +public: + ScopedHashTable() : CurScope(0) {} + ~ScopedHashTable() { + assert(CurScope == 0 && TopLevelMap.empty() && "Scope imbalance!"); + } + + void insert(const K &Key, const V &Val) { + assert(CurScope && "No scope active!"); + + ScopedHashTableVal *&KeyEntry = TopLevelMap[Key]; + + KeyEntry = new ScopedHashTableVal(CurScope->getLastValInScope(), + KeyEntry, Key, Val); + CurScope->setLastValInScope(KeyEntry); + } + + typedef ScopedHashTableIterator iterator; + + iterator end() { return iterator(0); } + + iterator begin(const K &Key) { + typename DenseMap*>::iterator I = + TopLevelMap.find(Key); + if (I == TopLevelMap.end()) return end(); + return iterator(I->second); + } +}; + +/// ScopedHashTableScope ctor - Install this as the current scope for the hash +/// table. +template +ScopedHashTableScope::ScopedHashTableScope(ScopedHashTable &ht) + : HT(ht) { + PrevScope = HT.CurScope; + HT.CurScope = this; + LastValInScope = 0; +} + +template +ScopedHashTableScope::~ScopedHashTableScope() { + assert(HT.CurScope == this && "Scope imbalance!"); + HT.CurScope = PrevScope; + + // Pop and delete all values corresponding to this scope. + while (ScopedHashTableVal *ThisEntry = LastValInScope) { + // Pop this value out of the TopLevelMap. + if (ThisEntry->getNextForKey() == 0) { + assert(HT.TopLevelMap[ThisEntry->getKey()] == ThisEntry && + "Scope imbalance!"); + HT.TopLevelMap.erase(ThisEntry->getKey()); + } else { + ScopedHashTableVal *&KeyEntry = HT.TopLevelMap[ThisEntry->getKey()]; + assert(KeyEntry == ThisEntry && "Scope imbalance!"); + KeyEntry = ThisEntry->getNextForKey(); + } + + // Pop this value out of the scope. + LastValInScope = ThisEntry->getNextInScope(); + + // Delete this entry. + delete ThisEntry; + } +} + +} // end namespace llvm + +#endif diff --git a/libclamav/c++/llvm/include/llvm/ADT/SetOperations.h b/libclamav/c++/llvm/include/llvm/ADT/SetOperations.h new file mode 100644 index 000000000..71f5db380 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/ADT/SetOperations.h @@ -0,0 +1,71 @@ +//===-- llvm/ADT/SetOperations.h - Generic Set Operations -------*- 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 generic set operations that may be used on set's of +// different types, and different element types. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_SETOPERATIONS_H +#define LLVM_ADT_SETOPERATIONS_H + +namespace llvm { + +/// set_union(A, B) - Compute A := A u B, return whether A changed. +/// +template +bool set_union(S1Ty &S1, const S2Ty &S2) { + bool Changed = false; + + for (typename S2Ty::const_iterator SI = S2.begin(), SE = S2.end(); + SI != SE; ++SI) + if (S1.insert(*SI).second) + Changed = true; + + return Changed; +} + +/// set_intersect(A, B) - Compute A := A ^ B +/// Identical to set_intersection, except that it works on set<>'s and +/// is nicer to use. Functionally, this iterates through S1, removing +/// elements that are not contained in S2. +/// +template +void set_intersect(S1Ty &S1, const S2Ty &S2) { + for (typename S1Ty::iterator I = S1.begin(); I != S1.end();) { + const typename S1Ty::key_type &E = *I; + ++I; + if (!S2.count(E)) S1.erase(E); // Erase element if not in S2 + } +} + +/// set_difference(A, B) - Return A - B +/// +template +S1Ty set_difference(const S1Ty &S1, const S2Ty &S2) { + S1Ty Result; + for (typename S1Ty::const_iterator SI = S1.begin(), SE = S1.end(); + SI != SE; ++SI) + if (!S2.count(*SI)) // if the element is not in set2 + Result.insert(*SI); + return Result; +} + +/// set_subtract(A, B) - Compute A := A - B +/// +template +void set_subtract(S1Ty &S1, const S2Ty &S2) { + for (typename S2Ty::const_iterator SI = S2.begin(), SE = S2.end(); + SI != SE; ++SI) + S1.erase(*SI); +} + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/ADT/SetVector.h b/libclamav/c++/llvm/include/llvm/ADT/SetVector.h new file mode 100644 index 000000000..fab133af4 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/ADT/SetVector.h @@ -0,0 +1,168 @@ +//===- llvm/ADT/SetVector.h - Set with insert order iteration ---*- 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 a set that has insertion order iteration +// characteristics. This is useful for keeping a set of things that need to be +// visited later but in a deterministic order (insertion order). The interface +// is purposefully minimal. +// +// This file defines SetVector and SmallSetVector, which performs no allocations +// if the SetVector has less than a certain number of elements. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_SETVECTOR_H +#define LLVM_ADT_SETVECTOR_H + +#include "llvm/ADT/SmallSet.h" +#include +#include +#include + +namespace llvm { + +/// This adapter class provides a way to keep a set of things that also has the +/// property of a deterministic iteration order. The order of iteration is the +/// order of insertion. +/// @brief A vector that has set insertion semantics. +template , + typename Set = SmallSet > +class SetVector { +public: + typedef T value_type; + typedef T key_type; + typedef T& reference; + typedef const T& const_reference; + typedef Set set_type; + typedef Vector vector_type; + typedef typename vector_type::const_iterator iterator; + typedef typename vector_type::const_iterator const_iterator; + typedef typename vector_type::size_type size_type; + + /// @brief Construct an empty SetVector + SetVector() {} + + /// @brief Initialize a SetVector with a range of elements + template + SetVector(It Start, It End) { + insert(Start, End); + } + + /// @brief Determine if the SetVector is empty or not. + bool empty() const { + return vector_.empty(); + } + + /// @brief Determine the number of elements in the SetVector. + size_type size() const { + return vector_.size(); + } + + /// @brief Get an iterator to the beginning of the SetVector. + iterator begin() { + return vector_.begin(); + } + + /// @brief Get a const_iterator to the beginning of the SetVector. + const_iterator begin() const { + return vector_.begin(); + } + + /// @brief Get an iterator to the end of the SetVector. + iterator end() { + return vector_.end(); + } + + /// @brief Get a const_iterator to the end of the SetVector. + const_iterator end() const { + return vector_.end(); + } + + /// @brief Return the last element of the SetVector. + const T &back() const { + assert(!empty() && "Cannot call back() on empty SetVector!"); + return vector_.back(); + } + + /// @brief Index into the SetVector. + const_reference operator[](size_type n) const { + assert(n < vector_.size() && "SetVector access out of range!"); + return vector_[n]; + } + + /// @returns true iff the element was inserted into the SetVector. + /// @brief Insert a new element into the SetVector. + bool insert(const value_type &X) { + bool result = set_.insert(X); + if (result) + vector_.push_back(X); + return result; + } + + /// @brief Insert a range of elements into the SetVector. + template + void insert(It Start, It End) { + for (; Start != End; ++Start) + if (set_.insert(*Start)) + vector_.push_back(*Start); + } + + /// @brief Remove an item from the set vector. + void remove(const value_type& X) { + if (set_.erase(X)) { + typename vector_type::iterator I = + std::find(vector_.begin(), vector_.end(), X); + assert(I != vector_.end() && "Corrupted SetVector instances!"); + vector_.erase(I); + } + } + + + /// @returns 0 if the element is not in the SetVector, 1 if it is. + /// @brief Count the number of elements of a given key in the SetVector. + size_type count(const key_type &key) const { + return set_.count(key); + } + + /// @brief Completely clear the SetVector + void clear() { + set_.clear(); + vector_.clear(); + } + + /// @brief Remove the last element of the SetVector. + void pop_back() { + assert(!empty() && "Cannot remove an element from an empty SetVector!"); + set_.erase(back()); + vector_.pop_back(); + } + +private: + set_type set_; ///< The set. + vector_type vector_; ///< The vector. +}; + +/// SmallSetVector - A SetVector that performs no allocations if smaller than +/// a certain size. +template +class SmallSetVector : public SetVector, SmallSet > { +public: + SmallSetVector() {} + + /// @brief Initialize a SmallSetVector with a range of elements + template + SmallSetVector(It Start, It End) { + this->insert(Start, End); + } +}; + +} // End llvm namespace + +// vim: sw=2 ai +#endif diff --git a/libclamav/c++/llvm/include/llvm/ADT/SmallPtrSet.h b/libclamav/c++/llvm/include/llvm/ADT/SmallPtrSet.h new file mode 100644 index 000000000..c29fc9f3d --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/ADT/SmallPtrSet.h @@ -0,0 +1,292 @@ +//===- llvm/ADT/SmallPtrSet.h - 'Normally small' pointer set ----*- 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 the SmallPtrSet class. See the doxygen comment for +// SmallPtrSetImpl for more details on the algorithm used. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_SMALLPTRSET_H +#define LLVM_ADT_SMALLPTRSET_H + +#include +#include +#include +#include "llvm/System/DataTypes.h" +#include "llvm/Support/PointerLikeTypeTraits.h" + +namespace llvm { + +class SmallPtrSetIteratorImpl; + +/// SmallPtrSetImpl - This is the common code shared among all the +/// SmallPtrSet<>'s, which is almost everything. SmallPtrSet has two modes, one +/// for small and one for large sets. +/// +/// Small sets use an array of pointers allocated in the SmallPtrSet object, +/// which is treated as a simple array of pointers. When a pointer is added to +/// the set, the array is scanned to see if the element already exists, if not +/// the element is 'pushed back' onto the array. If we run out of space in the +/// array, we grow into the 'large set' case. SmallSet should be used when the +/// sets are often small. In this case, no memory allocation is used, and only +/// light-weight and cache-efficient scanning is used. +/// +/// Large sets use a classic exponentially-probed hash table. Empty buckets are +/// represented with an illegal pointer value (-1) to allow null pointers to be +/// inserted. Tombstones are represented with another illegal pointer value +/// (-2), to allow deletion. The hash table is resized when the table is 3/4 or +/// more. When this happens, the table is doubled in size. +/// +class SmallPtrSetImpl { + friend class SmallPtrSetIteratorImpl; +protected: + /// CurArray - This is the current set of buckets. If it points to + /// SmallArray, then the set is in 'small mode'. + const void **CurArray; + /// CurArraySize - The allocated size of CurArray, always a power of two. + /// Note that CurArray points to an array that has CurArraySize+1 elements in + /// it, so that the end iterator actually points to valid memory. + unsigned CurArraySize; + + // If small, this is # elts allocated consequtively + unsigned NumElements; + unsigned NumTombstones; + const void *SmallArray[1]; // Must be last ivar. + + // Helper to copy construct a SmallPtrSet. + SmallPtrSetImpl(const SmallPtrSetImpl& that); + explicit SmallPtrSetImpl(unsigned SmallSize) { + assert(SmallSize && (SmallSize & (SmallSize-1)) == 0 && + "Initial size must be a power of two!"); + CurArray = &SmallArray[0]; + CurArraySize = SmallSize; + // The end pointer, always valid, is set to a valid element to help the + // iterator. + CurArray[SmallSize] = 0; + clear(); + } + ~SmallPtrSetImpl(); + +public: + bool empty() const { return size() == 0; } + unsigned size() const { return NumElements; } + + void clear() { + // If the capacity of the array is huge, and the # elements used is small, + // shrink the array. + if (!isSmall() && NumElements*4 < CurArraySize && CurArraySize > 32) + return shrink_and_clear(); + + // Fill the array with empty markers. + memset(CurArray, -1, CurArraySize*sizeof(void*)); + NumElements = 0; + NumTombstones = 0; + } + +protected: + static void *getTombstoneMarker() { return reinterpret_cast(-2); } + static void *getEmptyMarker() { + // Note that -1 is chosen to make clear() efficiently implementable with + // memset and because it's not a valid pointer value. + return reinterpret_cast(-1); + } + + /// insert_imp - This returns true if the pointer was new to the set, false if + /// it was already in the set. This is hidden from the client so that the + /// derived class can check that the right type of pointer is passed in. + bool insert_imp(const void * Ptr); + + /// erase_imp - If the set contains the specified pointer, remove it and + /// return true, otherwise return false. This is hidden from the client so + /// that the derived class can check that the right type of pointer is passed + /// in. + bool erase_imp(const void * Ptr); + + bool count_imp(const void * Ptr) const { + if (isSmall()) { + // Linear search for the item. + for (const void *const *APtr = SmallArray, + *const *E = SmallArray+NumElements; APtr != E; ++APtr) + if (*APtr == Ptr) + return true; + return false; + } + + // Big set case. + return *FindBucketFor(Ptr) == Ptr; + } + +private: + bool isSmall() const { return CurArray == &SmallArray[0]; } + + unsigned Hash(const void *Ptr) const { + return static_cast(((uintptr_t)Ptr >> 4) & (CurArraySize-1)); + } + const void * const *FindBucketFor(const void *Ptr) const; + void shrink_and_clear(); + + /// Grow - Allocate a larger backing store for the buckets and move it over. + void Grow(); + + void operator=(const SmallPtrSetImpl &RHS); // DO NOT IMPLEMENT. +protected: + void CopyFrom(const SmallPtrSetImpl &RHS); +}; + +/// SmallPtrSetIteratorImpl - This is the common base class shared between all +/// instances of SmallPtrSetIterator. +class SmallPtrSetIteratorImpl { +protected: + const void *const *Bucket; +public: + explicit SmallPtrSetIteratorImpl(const void *const *BP) : Bucket(BP) { + AdvanceIfNotValid(); + } + + bool operator==(const SmallPtrSetIteratorImpl &RHS) const { + return Bucket == RHS.Bucket; + } + bool operator!=(const SmallPtrSetIteratorImpl &RHS) const { + return Bucket != RHS.Bucket; + } + +protected: + /// AdvanceIfNotValid - If the current bucket isn't valid, advance to a bucket + /// that is. This is guaranteed to stop because the end() bucket is marked + /// valid. + void AdvanceIfNotValid() { + while (*Bucket == SmallPtrSetImpl::getEmptyMarker() || + *Bucket == SmallPtrSetImpl::getTombstoneMarker()) + ++Bucket; + } +}; + +/// SmallPtrSetIterator - This implements a const_iterator for SmallPtrSet. +template +class SmallPtrSetIterator : public SmallPtrSetIteratorImpl { + typedef PointerLikeTypeTraits PtrTraits; + +public: + typedef PtrTy value_type; + typedef PtrTy reference; + typedef PtrTy pointer; + typedef std::ptrdiff_t difference_type; + typedef std::forward_iterator_tag iterator_category; + + explicit SmallPtrSetIterator(const void *const *BP) + : SmallPtrSetIteratorImpl(BP) {} + + // Most methods provided by baseclass. + + const PtrTy operator*() const { + return PtrTraits::getFromVoidPointer(const_cast(*Bucket)); + } + + inline SmallPtrSetIterator& operator++() { // Preincrement + ++Bucket; + AdvanceIfNotValid(); + return *this; + } + + SmallPtrSetIterator operator++(int) { // Postincrement + SmallPtrSetIterator tmp = *this; ++*this; return tmp; + } +}; + +/// NextPowerOfTwo - This is a helper template that rounds N up to the next +/// power of two. +template +struct NextPowerOfTwo; + +/// NextPowerOfTwoH - If N is not a power of two, increase it. This is a helper +/// template used to implement NextPowerOfTwo. +template +struct NextPowerOfTwoH { + enum { Val = N }; +}; +template +struct NextPowerOfTwoH { + enum { + // We could just use NextVal = N+1, but this converges faster. N|(N-1) sets + // the right-most zero bits to one all at once, e.g. 0b0011000 -> 0b0011111. + Val = NextPowerOfTwo<(N|(N-1)) + 1>::Val + }; +}; + +template +struct NextPowerOfTwo { + enum { Val = NextPowerOfTwoH::Val }; +}; + + +/// SmallPtrSet - This class implements a set which is optimizer for holding +/// SmallSize or less elements. This internally rounds up SmallSize to the next +/// power of two if it is not already a power of two. See the comments above +/// SmallPtrSetImpl for details of the algorithm. +template +class SmallPtrSet : public SmallPtrSetImpl { + // Make sure that SmallSize is a power of two, round up if not. + enum { SmallSizePowTwo = NextPowerOfTwo::Val }; + void *SmallArray[SmallSizePowTwo]; + typedef PointerLikeTypeTraits PtrTraits; +public: + SmallPtrSet() : SmallPtrSetImpl(NextPowerOfTwo::Val) {} + SmallPtrSet(const SmallPtrSet &that) : SmallPtrSetImpl(that) {} + + template + SmallPtrSet(It I, It E) + : SmallPtrSetImpl(NextPowerOfTwo::Val) { + insert(I, E); + } + + /// insert - This returns true if the pointer was new to the set, false if it + /// was already in the set. + bool insert(PtrType Ptr) { + return insert_imp(PtrTraits::getAsVoidPointer(Ptr)); + } + + /// erase - If the set contains the specified pointer, remove it and return + /// true, otherwise return false. + bool erase(PtrType Ptr) { + return erase_imp(PtrTraits::getAsVoidPointer(Ptr)); + } + + /// count - Return true if the specified pointer is in the set. + bool count(PtrType Ptr) const { + return count_imp(PtrTraits::getAsVoidPointer(Ptr)); + } + + template + void insert(IterT I, IterT E) { + for (; I != E; ++I) + insert(*I); + } + + typedef SmallPtrSetIterator iterator; + typedef SmallPtrSetIterator const_iterator; + inline iterator begin() const { + return iterator(CurArray); + } + inline iterator end() const { + return iterator(CurArray+CurArraySize); + } + + // Allow assignment from any smallptrset with the same element type even if it + // doesn't have the same smallsize. + const SmallPtrSet& + operator=(const SmallPtrSet &RHS) { + CopyFrom(RHS); + return *this; + } + +}; + +} + +#endif diff --git a/libclamav/c++/llvm/include/llvm/ADT/SmallSet.h b/libclamav/c++/llvm/include/llvm/ADT/SmallSet.h new file mode 100644 index 000000000..d03f1bef1 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/ADT/SmallSet.h @@ -0,0 +1,118 @@ +//===- llvm/ADT/SmallSet.h - 'Normally small' sets --------------*- 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 the SmallSet class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_SMALLSET_H +#define LLVM_ADT_SMALLSET_H + +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/SmallPtrSet.h" +#include + +namespace llvm { + +/// SmallSet - This maintains a set of unique values, optimizing for the case +/// when the set is small (less than N). In this case, the set can be +/// maintained with no mallocs. If the set gets large, we expand to using an +/// std::set to maintain reasonable lookup times. +/// +/// Note that this set does not provide a way to iterate over members in the +/// set. +template +class SmallSet { + /// Use a SmallVector to hold the elements here (even though it will never + /// reach its 'large' stage) to avoid calling the default ctors of elements + /// we will never use. + SmallVector Vector; + std::set Set; + typedef typename SmallVector::const_iterator VIterator; + typedef typename SmallVector::iterator mutable_iterator; +public: + SmallSet() {} + + bool empty() const { return Vector.empty() && Set.empty(); } + unsigned size() const { + return isSmall() ? Vector.size() : Set.size(); + } + + /// count - Return true if the element is in the set. + bool count(const T &V) const { + if (isSmall()) { + // Since the collection is small, just do a linear search. + return vfind(V) != Vector.end(); + } else { + return Set.count(V); + } + } + + /// insert - Insert an element into the set if it isn't already there. + bool insert(const T &V) { + if (!isSmall()) + return Set.insert(V).second; + + VIterator I = vfind(V); + if (I != Vector.end()) // Don't reinsert if it already exists. + return false; + if (Vector.size() < N) { + Vector.push_back(V); + return true; + } + + // Otherwise, grow from vector to set. + while (!Vector.empty()) { + Set.insert(Vector.back()); + Vector.pop_back(); + } + Set.insert(V); + return true; + } + + template + void insert(IterT I, IterT E) { + for (; I != E; ++I) + insert(*I); + } + + bool erase(const T &V) { + if (!isSmall()) + return Set.erase(V); + for (mutable_iterator I = Vector.begin(), E = Vector.end(); I != E; ++I) + if (*I == V) { + Vector.erase(I); + return true; + } + return false; + } + + void clear() { + Vector.clear(); + Set.clear(); + } +private: + bool isSmall() const { return Set.empty(); } + + VIterator vfind(const T &V) const { + for (VIterator I = Vector.begin(), E = Vector.end(); I != E; ++I) + if (*I == V) + return I; + return Vector.end(); + } +}; + +/// If this set is of pointer values, transparently switch over to using +/// SmallPtrSet for performance. +template +class SmallSet : public SmallPtrSet {}; + +} // end namespace llvm + +#endif diff --git a/libclamav/c++/llvm/include/llvm/ADT/SmallString.h b/libclamav/c++/llvm/include/llvm/ADT/SmallString.h new file mode 100644 index 000000000..05bd8a42c --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/ADT/SmallString.h @@ -0,0 +1,68 @@ +//===- llvm/ADT/SmallString.h - 'Normally small' strings --------*- 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 the SmallString class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_SMALLSTRING_H +#define LLVM_ADT_SMALLSTRING_H + +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" + +namespace llvm { + +/// SmallString - A SmallString is just a SmallVector with methods and accessors +/// that make it work better as a string (e.g. operator+ etc). +template +class SmallString : public SmallVector { +public: + // Default ctor - Initialize to empty. + SmallString() {} + + // Initialize with a range. + template + SmallString(ItTy S, ItTy E) : SmallVector(S, E) {} + + // Copy ctor. + SmallString(const SmallString &RHS) : SmallVector(RHS) {} + + + // Extra methods. + StringRef str() const { return StringRef(this->begin(), this->size()); } + + // Implicit conversion to StringRef. + operator StringRef() const { return str(); } + + const char *c_str() { + this->push_back(0); + this->pop_back(); + return this->data(); + } + + // Extra operators. + const SmallString &operator=(StringRef RHS) { + this->clear(); + return *this += RHS; + } + + SmallString &operator+=(StringRef RHS) { + this->append(RHS.begin(), RHS.end()); + return *this; + } + SmallString &operator+=(char C) { + this->push_back(C); + return *this; + } +}; + +} + +#endif diff --git a/libclamav/c++/llvm/include/llvm/ADT/SmallVector.h b/libclamav/c++/llvm/include/llvm/ADT/SmallVector.h new file mode 100644 index 000000000..f3b4533b9 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/ADT/SmallVector.h @@ -0,0 +1,634 @@ +//===- llvm/ADT/SmallVector.h - 'Normally small' vectors --------*- 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 the SmallVector class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_SMALLVECTOR_H +#define LLVM_ADT_SMALLVECTOR_H + +#include "llvm/Support/type_traits.h" +#include +#include +#include +#include + +#ifdef _MSC_VER +namespace std { +#if _MSC_VER <= 1310 + // Work around flawed VC++ implementation of std::uninitialized_copy. Define + // additional overloads so that elements with pointer types are recognized as + // scalars and not objects, causing bizarre type conversion errors. + template + inline _Scalar_ptr_iterator_tag _Ptr_cat(T1 **, T2 **) { + _Scalar_ptr_iterator_tag _Cat; + return _Cat; + } + + template + inline _Scalar_ptr_iterator_tag _Ptr_cat(T1* const *, T2 **) { + _Scalar_ptr_iterator_tag _Cat; + return _Cat; + } +#else +// FIXME: It is not clear if the problem is fixed in VS 2005. What is clear +// is that the above hack won't work if it wasn't fixed. +#endif +} +#endif + +namespace llvm { + +/// SmallVectorImpl - This class consists of common code factored out of the +/// SmallVector class to reduce code duplication based on the SmallVector 'N' +/// template parameter. +template +class SmallVectorImpl { +protected: + T *Begin, *End, *Capacity; + + // Allocate raw space for N elements of type T. If T has a ctor or dtor, we + // don't want it to be automatically run, so we need to represent the space as + // something else. An array of char would work great, but might not be + // aligned sufficiently. Instead, we either use GCC extensions, or some + // number of union instances for the space, which guarantee maximal alignment. +protected: +#ifdef __GNUC__ + typedef char U; + U FirstEl __attribute__((aligned)); +#else + union U { + double D; + long double LD; + long long L; + void *P; + } FirstEl; +#endif + // Space after 'FirstEl' is clobbered, do not add any instance vars after it. +public: + // Default ctor - Initialize to empty. + explicit SmallVectorImpl(unsigned N) + : Begin(reinterpret_cast(&FirstEl)), + End(reinterpret_cast(&FirstEl)), + Capacity(reinterpret_cast(&FirstEl)+N) { + } + + ~SmallVectorImpl() { + // Destroy the constructed elements in the vector. + destroy_range(Begin, End); + + // If this wasn't grown from the inline copy, deallocate the old space. + if (!isSmall()) + operator delete(Begin); + } + + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef T value_type; + typedef T* iterator; + typedef const T* const_iterator; + + typedef std::reverse_iterator const_reverse_iterator; + typedef std::reverse_iterator reverse_iterator; + + typedef T& reference; + typedef const T& const_reference; + typedef T* pointer; + typedef const T* const_pointer; + + bool empty() const { return Begin == End; } + size_type size() const { return End-Begin; } + size_type max_size() const { return size_type(-1) / sizeof(T); } + + // forward iterator creation methods. + iterator begin() { return Begin; } + const_iterator begin() const { return Begin; } + iterator end() { return End; } + const_iterator end() const { return End; } + + // reverse iterator creation methods. + reverse_iterator rbegin() { return reverse_iterator(end()); } + const_reverse_iterator rbegin() const{ return const_reverse_iterator(end()); } + reverse_iterator rend() { return reverse_iterator(begin()); } + const_reverse_iterator rend() const { return const_reverse_iterator(begin());} + + + reference operator[](unsigned idx) { + assert(Begin + idx < End); + return Begin[idx]; + } + const_reference operator[](unsigned idx) const { + assert(Begin + idx < End); + return Begin[idx]; + } + + reference front() { + return begin()[0]; + } + const_reference front() const { + return begin()[0]; + } + + reference back() { + return end()[-1]; + } + const_reference back() const { + return end()[-1]; + } + + void push_back(const_reference Elt) { + if (End < Capacity) { + Retry: + new (End) T(Elt); + ++End; + return; + } + grow(); + goto Retry; + } + + void pop_back() { + --End; + End->~T(); + } + + T pop_back_val() { + T Result = back(); + pop_back(); + return Result; + } + + void clear() { + destroy_range(Begin, End); + End = Begin; + } + + void resize(unsigned N) { + if (N < size()) { + destroy_range(Begin+N, End); + End = Begin+N; + } else if (N > size()) { + if (unsigned(Capacity-Begin) < N) + grow(N); + construct_range(End, Begin+N, T()); + End = Begin+N; + } + } + + void resize(unsigned N, const T &NV) { + if (N < size()) { + destroy_range(Begin+N, End); + End = Begin+N; + } else if (N > size()) { + if (unsigned(Capacity-Begin) < N) + grow(N); + construct_range(End, Begin+N, NV); + End = Begin+N; + } + } + + void reserve(unsigned N) { + if (unsigned(Capacity-Begin) < N) + grow(N); + } + + void swap(SmallVectorImpl &RHS); + + /// append - Add the specified range to the end of the SmallVector. + /// + template + void append(in_iter in_start, in_iter in_end) { + size_type NumInputs = std::distance(in_start, in_end); + // Grow allocated space if needed. + if (NumInputs > size_type(Capacity-End)) + grow(size()+NumInputs); + + // Copy the new elements over. + std::uninitialized_copy(in_start, in_end, End); + End += NumInputs; + } + + /// append - Add the specified range to the end of the SmallVector. + /// + void append(size_type NumInputs, const T &Elt) { + // Grow allocated space if needed. + if (NumInputs > size_type(Capacity-End)) + grow(size()+NumInputs); + + // Copy the new elements over. + std::uninitialized_fill_n(End, NumInputs, Elt); + End += NumInputs; + } + + void assign(unsigned NumElts, const T &Elt) { + clear(); + if (unsigned(Capacity-Begin) < NumElts) + grow(NumElts); + End = Begin+NumElts; + construct_range(Begin, End, Elt); + } + + iterator erase(iterator I) { + iterator N = I; + // Shift all elts down one. + std::copy(I+1, End, I); + // Drop the last elt. + pop_back(); + return(N); + } + + iterator erase(iterator S, iterator E) { + iterator N = S; + // Shift all elts down. + iterator I = std::copy(E, End, S); + // Drop the last elts. + destroy_range(I, End); + End = I; + return(N); + } + + iterator insert(iterator I, const T &Elt) { + if (I == End) { // Important special case for empty vector. + push_back(Elt); + return end()-1; + } + + if (End < Capacity) { + Retry: + new (End) T(back()); + ++End; + // Push everything else over. + std::copy_backward(I, End-1, End); + *I = Elt; + return I; + } + size_t EltNo = I-Begin; + grow(); + I = Begin+EltNo; + goto Retry; + } + + iterator insert(iterator I, size_type NumToInsert, const T &Elt) { + if (I == End) { // Important special case for empty vector. + append(NumToInsert, Elt); + return end()-1; + } + + // Convert iterator to elt# to avoid invalidating iterator when we reserve() + size_t InsertElt = I-begin(); + + // Ensure there is enough space. + reserve(static_cast(size() + NumToInsert)); + + // Uninvalidate the iterator. + I = begin()+InsertElt; + + // If there are more elements between the insertion point and the end of the + // range than there are being inserted, we can use a simple approach to + // insertion. Since we already reserved space, we know that this won't + // reallocate the vector. + if (size_t(end()-I) >= NumToInsert) { + T *OldEnd = End; + append(End-NumToInsert, End); + + // Copy the existing elements that get replaced. + std::copy_backward(I, OldEnd-NumToInsert, OldEnd); + + std::fill_n(I, NumToInsert, Elt); + return I; + } + + // Otherwise, we're inserting more elements than exist already, and we're + // not inserting at the end. + + // Copy over the elements that we're about to overwrite. + T *OldEnd = End; + End += NumToInsert; + size_t NumOverwritten = OldEnd-I; + std::uninitialized_copy(I, OldEnd, End-NumOverwritten); + + // Replace the overwritten part. + std::fill_n(I, NumOverwritten, Elt); + + // Insert the non-overwritten middle part. + std::uninitialized_fill_n(OldEnd, NumToInsert-NumOverwritten, Elt); + return I; + } + + template + iterator insert(iterator I, ItTy From, ItTy To) { + if (I == End) { // Important special case for empty vector. + append(From, To); + return end()-1; + } + + size_t NumToInsert = std::distance(From, To); + // Convert iterator to elt# to avoid invalidating iterator when we reserve() + size_t InsertElt = I-begin(); + + // Ensure there is enough space. + reserve(static_cast(size() + NumToInsert)); + + // Uninvalidate the iterator. + I = begin()+InsertElt; + + // If there are more elements between the insertion point and the end of the + // range than there are being inserted, we can use a simple approach to + // insertion. Since we already reserved space, we know that this won't + // reallocate the vector. + if (size_t(end()-I) >= NumToInsert) { + T *OldEnd = End; + append(End-NumToInsert, End); + + // Copy the existing elements that get replaced. + std::copy_backward(I, OldEnd-NumToInsert, OldEnd); + + std::copy(From, To, I); + return I; + } + + // Otherwise, we're inserting more elements than exist already, and we're + // not inserting at the end. + + // Copy over the elements that we're about to overwrite. + T *OldEnd = End; + End += NumToInsert; + size_t NumOverwritten = OldEnd-I; + std::uninitialized_copy(I, OldEnd, End-NumOverwritten); + + // Replace the overwritten part. + std::copy(From, From+NumOverwritten, I); + + // Insert the non-overwritten middle part. + std::uninitialized_copy(From+NumOverwritten, To, OldEnd); + return I; + } + + /// data - Return a pointer to the vector's buffer, even if empty(). + pointer data() { + return pointer(Begin); + } + + /// data - Return a pointer to the vector's buffer, even if empty(). + const_pointer data() const { + return const_pointer(Begin); + } + + const SmallVectorImpl &operator=(const SmallVectorImpl &RHS); + + bool operator==(const SmallVectorImpl &RHS) const { + if (size() != RHS.size()) return false; + for (T *This = Begin, *That = RHS.Begin, *E = Begin+size(); + This != E; ++This, ++That) + if (*This != *That) + return false; + return true; + } + bool operator!=(const SmallVectorImpl &RHS) const { return !(*this == RHS); } + + bool operator<(const SmallVectorImpl &RHS) const { + return std::lexicographical_compare(begin(), end(), + RHS.begin(), RHS.end()); + } + + /// capacity - Return the total number of elements in the currently allocated + /// buffer. + size_t capacity() const { return Capacity - Begin; } + + /// set_size - Set the array size to \arg N, which the current array must have + /// enough capacity for. + /// + /// This does not construct or destroy any elements in the vector. + /// + /// Clients can use this in conjunction with capacity() to write past the end + /// of the buffer when they know that more elements are available, and only + /// update the size later. This avoids the cost of value initializing elements + /// which will only be overwritten. + void set_size(unsigned N) { + assert(N <= capacity()); + End = Begin + N; + } + +private: + /// isSmall - Return true if this is a smallvector which has not had dynamic + /// memory allocated for it. + bool isSmall() const { + return static_cast(Begin) == + static_cast(&FirstEl); + } + + /// grow - double the size of the allocated memory, guaranteeing space for at + /// least one more element or MinSize if specified. + void grow(size_type MinSize = 0); + + void construct_range(T *S, T *E, const T &Elt) { + for (; S != E; ++S) + new (S) T(Elt); + } + + void destroy_range(T *S, T *E) { + while (S != E) { + --E; + E->~T(); + } + } +}; + +// Define this out-of-line to dissuade the C++ compiler from inlining it. +template +void SmallVectorImpl::grow(size_t MinSize) { + size_t CurCapacity = Capacity-Begin; + size_t CurSize = size(); + size_t NewCapacity = 2*CurCapacity; + if (NewCapacity < MinSize) + NewCapacity = MinSize; + T *NewElts = static_cast(operator new(NewCapacity*sizeof(T))); + + // Copy the elements over. + if (is_class::value) + std::uninitialized_copy(Begin, End, NewElts); + else + // Use memcpy for PODs (std::uninitialized_copy optimizes to memmove). + memcpy(NewElts, Begin, CurSize * sizeof(T)); + + // Destroy the original elements. + destroy_range(Begin, End); + + // If this wasn't grown from the inline copy, deallocate the old space. + if (!isSmall()) + operator delete(Begin); + + Begin = NewElts; + End = NewElts+CurSize; + Capacity = Begin+NewCapacity; +} + +template +void SmallVectorImpl::swap(SmallVectorImpl &RHS) { + if (this == &RHS) return; + + // We can only avoid copying elements if neither vector is small. + if (!isSmall() && !RHS.isSmall()) { + std::swap(Begin, RHS.Begin); + std::swap(End, RHS.End); + std::swap(Capacity, RHS.Capacity); + return; + } + if (RHS.size() > size_type(Capacity-Begin)) + grow(RHS.size()); + if (size() > size_type(RHS.Capacity-RHS.begin())) + RHS.grow(size()); + + // Swap the shared elements. + size_t NumShared = size(); + if (NumShared > RHS.size()) NumShared = RHS.size(); + for (unsigned i = 0; i != static_cast(NumShared); ++i) + std::swap(Begin[i], RHS[i]); + + // Copy over the extra elts. + if (size() > RHS.size()) { + size_t EltDiff = size() - RHS.size(); + std::uninitialized_copy(Begin+NumShared, End, RHS.End); + RHS.End += EltDiff; + destroy_range(Begin+NumShared, End); + End = Begin+NumShared; + } else if (RHS.size() > size()) { + size_t EltDiff = RHS.size() - size(); + std::uninitialized_copy(RHS.Begin+NumShared, RHS.End, End); + End += EltDiff; + destroy_range(RHS.Begin+NumShared, RHS.End); + RHS.End = RHS.Begin+NumShared; + } +} + +template +const SmallVectorImpl & +SmallVectorImpl::operator=(const SmallVectorImpl &RHS) { + // Avoid self-assignment. + if (this == &RHS) return *this; + + // If we already have sufficient space, assign the common elements, then + // destroy any excess. + unsigned RHSSize = unsigned(RHS.size()); + unsigned CurSize = unsigned(size()); + if (CurSize >= RHSSize) { + // Assign common elements. + iterator NewEnd; + if (RHSSize) + NewEnd = std::copy(RHS.Begin, RHS.Begin+RHSSize, Begin); + else + NewEnd = Begin; + + // Destroy excess elements. + destroy_range(NewEnd, End); + + // Trim. + End = NewEnd; + return *this; + } + + // If we have to grow to have enough elements, destroy the current elements. + // This allows us to avoid copying them during the grow. + if (unsigned(Capacity-Begin) < RHSSize) { + // Destroy current elements. + destroy_range(Begin, End); + End = Begin; + CurSize = 0; + grow(RHSSize); + } else if (CurSize) { + // Otherwise, use assignment for the already-constructed elements. + std::copy(RHS.Begin, RHS.Begin+CurSize, Begin); + } + + // Copy construct the new elements in place. + std::uninitialized_copy(RHS.Begin+CurSize, RHS.End, Begin+CurSize); + + // Set end. + End = Begin+RHSSize; + return *this; +} + +/// SmallVector - This is a 'vector' (really, a variable-sized array), optimized +/// for the case when the array is small. It contains some number of elements +/// in-place, which allows it to avoid heap allocation when the actual number of +/// elements is below that threshold. This allows normal "small" cases to be +/// fast without losing generality for large inputs. +/// +/// Note that this does not attempt to be exception safe. +/// +template +class SmallVector : public SmallVectorImpl { + /// InlineElts - These are 'N-1' elements that are stored inline in the body + /// of the vector. The extra '1' element is stored in SmallVectorImpl. + typedef typename SmallVectorImpl::U U; + enum { + // MinUs - The number of U's require to cover N T's. + MinUs = (static_cast(sizeof(T))*N + + static_cast(sizeof(U)) - 1) / + static_cast(sizeof(U)), + + // NumInlineEltsElts - The number of elements actually in this array. There + // is already one in the parent class, and we have to round up to avoid + // having a zero-element array. + NumInlineEltsElts = MinUs > 1 ? (MinUs - 1) : 1, + + // NumTsAvailable - The number of T's we actually have space for, which may + // be more than N due to rounding. + NumTsAvailable = (NumInlineEltsElts+1)*static_cast(sizeof(U))/ + static_cast(sizeof(T)) + }; + U InlineElts[NumInlineEltsElts]; +public: + SmallVector() : SmallVectorImpl(NumTsAvailable) { + } + + explicit SmallVector(unsigned Size, const T &Value = T()) + : SmallVectorImpl(NumTsAvailable) { + this->reserve(Size); + while (Size--) + this->push_back(Value); + } + + template + SmallVector(ItTy S, ItTy E) : SmallVectorImpl(NumTsAvailable) { + this->append(S, E); + } + + SmallVector(const SmallVector &RHS) : SmallVectorImpl(NumTsAvailable) { + if (!RHS.empty()) + SmallVectorImpl::operator=(RHS); + } + + const SmallVector &operator=(const SmallVector &RHS) { + SmallVectorImpl::operator=(RHS); + return *this; + } + +}; + +} // End llvm namespace + +namespace std { + /// Implement std::swap in terms of SmallVector swap. + template + inline void + swap(llvm::SmallVectorImpl &LHS, llvm::SmallVectorImpl &RHS) { + LHS.swap(RHS); + } + + /// Implement std::swap in terms of SmallVector swap. + template + inline void + swap(llvm::SmallVector &LHS, llvm::SmallVector &RHS) { + LHS.swap(RHS); + } +} + +#endif diff --git a/libclamav/c++/llvm/include/llvm/ADT/SparseBitVector.h b/libclamav/c++/llvm/include/llvm/ADT/SparseBitVector.h new file mode 100644 index 000000000..6c813ecd3 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/ADT/SparseBitVector.h @@ -0,0 +1,902 @@ +//===- llvm/ADT/SparseBitVector.h - Efficient Sparse BitVector -*- 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 the SparseBitVector class. See the doxygen comment for +// SparseBitVector for more details on the algorithm used. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_SPARSEBITVECTOR_H +#define LLVM_ADT_SPARSEBITVECTOR_H + +#include "llvm/ADT/ilist.h" +#include "llvm/ADT/ilist_node.h" +#include "llvm/System/DataTypes.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/Support/raw_ostream.h" +#include +#include +#include + +namespace llvm { + +/// SparseBitVector is an implementation of a bitvector that is sparse by only +/// storing the elements that have non-zero bits set. In order to make this +/// fast for the most common cases, SparseBitVector is implemented as a linked +/// list of SparseBitVectorElements. We maintain a pointer to the last +/// SparseBitVectorElement accessed (in the form of a list iterator), in order +/// to make multiple in-order test/set constant time after the first one is +/// executed. Note that using vectors to store SparseBitVectorElement's does +/// not work out very well because it causes insertion in the middle to take +/// enormous amounts of time with a large amount of bits. Other structures that +/// have better worst cases for insertion in the middle (various balanced trees, +/// etc) do not perform as well in practice as a linked list with this iterator +/// kept up to date. They are also significantly more memory intensive. + + +template +struct SparseBitVectorElement + : public ilist_node > { +public: + typedef unsigned long BitWord; + enum { + BITWORD_SIZE = sizeof(BitWord) * CHAR_BIT, + BITWORDS_PER_ELEMENT = (ElementSize + BITWORD_SIZE - 1) / BITWORD_SIZE, + BITS_PER_ELEMENT = ElementSize + }; + +private: + // Index of Element in terms of where first bit starts. + unsigned ElementIndex; + BitWord Bits[BITWORDS_PER_ELEMENT]; + // Needed for sentinels + friend struct ilist_sentinel_traits; + SparseBitVectorElement() { + ElementIndex = ~0U; + memset(&Bits[0], 0, sizeof (BitWord) * BITWORDS_PER_ELEMENT); + } + +public: + explicit SparseBitVectorElement(unsigned Idx) { + ElementIndex = Idx; + memset(&Bits[0], 0, sizeof (BitWord) * BITWORDS_PER_ELEMENT); + } + + // Comparison. + bool operator==(const SparseBitVectorElement &RHS) const { + if (ElementIndex != RHS.ElementIndex) + return false; + for (unsigned i = 0; i < BITWORDS_PER_ELEMENT; ++i) + if (Bits[i] != RHS.Bits[i]) + return false; + return true; + } + + bool operator!=(const SparseBitVectorElement &RHS) const { + return !(*this == RHS); + } + + // Return the bits that make up word Idx in our element. + BitWord word(unsigned Idx) const { + assert (Idx < BITWORDS_PER_ELEMENT); + return Bits[Idx]; + } + + unsigned index() const { + return ElementIndex; + } + + bool empty() const { + for (unsigned i = 0; i < BITWORDS_PER_ELEMENT; ++i) + if (Bits[i]) + return false; + return true; + } + + void set(unsigned Idx) { + Bits[Idx / BITWORD_SIZE] |= 1L << (Idx % BITWORD_SIZE); + } + + bool test_and_set (unsigned Idx) { + bool old = test(Idx); + if (!old) { + set(Idx); + return true; + } + return false; + } + + void reset(unsigned Idx) { + Bits[Idx / BITWORD_SIZE] &= ~(1L << (Idx % BITWORD_SIZE)); + } + + bool test(unsigned Idx) const { + return Bits[Idx / BITWORD_SIZE] & (1L << (Idx % BITWORD_SIZE)); + } + + unsigned count() const { + unsigned NumBits = 0; + for (unsigned i = 0; i < BITWORDS_PER_ELEMENT; ++i) + if (sizeof(BitWord) == 4) + NumBits += CountPopulation_32(Bits[i]); + else if (sizeof(BitWord) == 8) + NumBits += CountPopulation_64(Bits[i]); + else + assert(0 && "Unsupported!"); + return NumBits; + } + + /// find_first - Returns the index of the first set bit. + int find_first() const { + for (unsigned i = 0; i < BITWORDS_PER_ELEMENT; ++i) + if (Bits[i] != 0) { + if (sizeof(BitWord) == 4) + return i * BITWORD_SIZE + CountTrailingZeros_32(Bits[i]); + else if (sizeof(BitWord) == 8) + return i * BITWORD_SIZE + CountTrailingZeros_64(Bits[i]); + else + assert(0 && "Unsupported!"); + } + assert(0 && "Illegal empty element"); + return 0; // Not reached + } + + /// find_next - Returns the index of the next set bit starting from the + /// "Curr" bit. Returns -1 if the next set bit is not found. + int find_next(unsigned Curr) const { + if (Curr >= BITS_PER_ELEMENT) + return -1; + + unsigned WordPos = Curr / BITWORD_SIZE; + unsigned BitPos = Curr % BITWORD_SIZE; + BitWord Copy = Bits[WordPos]; + assert (WordPos <= BITWORDS_PER_ELEMENT + && "Word Position outside of element"); + + // Mask off previous bits. + Copy &= ~0L << BitPos; + + if (Copy != 0) { + if (sizeof(BitWord) == 4) + return WordPos * BITWORD_SIZE + CountTrailingZeros_32(Copy); + else if (sizeof(BitWord) == 8) + return WordPos * BITWORD_SIZE + CountTrailingZeros_64(Copy); + else + assert(0 && "Unsupported!"); + } + + // Check subsequent words. + for (unsigned i = WordPos+1; i < BITWORDS_PER_ELEMENT; ++i) + if (Bits[i] != 0) { + if (sizeof(BitWord) == 4) + return i * BITWORD_SIZE + CountTrailingZeros_32(Bits[i]); + else if (sizeof(BitWord) == 8) + return i * BITWORD_SIZE + CountTrailingZeros_64(Bits[i]); + else + assert(0 && "Unsupported!"); + } + return -1; + } + + // Union this element with RHS and return true if this one changed. + bool unionWith(const SparseBitVectorElement &RHS) { + bool changed = false; + for (unsigned i = 0; i < BITWORDS_PER_ELEMENT; ++i) { + BitWord old = changed ? 0 : Bits[i]; + + Bits[i] |= RHS.Bits[i]; + if (!changed && old != Bits[i]) + changed = true; + } + return changed; + } + + // Return true if we have any bits in common with RHS + bool intersects(const SparseBitVectorElement &RHS) const { + for (unsigned i = 0; i < BITWORDS_PER_ELEMENT; ++i) { + if (RHS.Bits[i] & Bits[i]) + return true; + } + return false; + } + + // Intersect this Element with RHS and return true if this one changed. + // BecameZero is set to true if this element became all-zero bits. + bool intersectWith(const SparseBitVectorElement &RHS, + bool &BecameZero) { + bool changed = false; + bool allzero = true; + + BecameZero = false; + for (unsigned i = 0; i < BITWORDS_PER_ELEMENT; ++i) { + BitWord old = changed ? 0 : Bits[i]; + + Bits[i] &= RHS.Bits[i]; + if (Bits[i] != 0) + allzero = false; + + if (!changed && old != Bits[i]) + changed = true; + } + BecameZero = allzero; + return changed; + } + // Intersect this Element with the complement of RHS and return true if this + // one changed. BecameZero is set to true if this element became all-zero + // bits. + bool intersectWithComplement(const SparseBitVectorElement &RHS, + bool &BecameZero) { + bool changed = false; + bool allzero = true; + + BecameZero = false; + for (unsigned i = 0; i < BITWORDS_PER_ELEMENT; ++i) { + BitWord old = changed ? 0 : Bits[i]; + + Bits[i] &= ~RHS.Bits[i]; + if (Bits[i] != 0) + allzero = false; + + if (!changed && old != Bits[i]) + changed = true; + } + BecameZero = allzero; + return changed; + } + // Three argument version of intersectWithComplement that intersects + // RHS1 & ~RHS2 into this element + void intersectWithComplement(const SparseBitVectorElement &RHS1, + const SparseBitVectorElement &RHS2, + bool &BecameZero) { + bool allzero = true; + + BecameZero = false; + for (unsigned i = 0; i < BITWORDS_PER_ELEMENT; ++i) { + Bits[i] = RHS1.Bits[i] & ~RHS2.Bits[i]; + if (Bits[i] != 0) + allzero = false; + } + BecameZero = allzero; + } + + // Get a hash value for this element; + uint64_t getHashValue() const { + uint64_t HashVal = 0; + for (unsigned i = 0; i < BITWORDS_PER_ELEMENT; ++i) { + HashVal ^= Bits[i]; + } + return HashVal; + } +}; + +template +class SparseBitVector { + typedef ilist > ElementList; + typedef typename ElementList::iterator ElementListIter; + typedef typename ElementList::const_iterator ElementListConstIter; + enum { + BITWORD_SIZE = SparseBitVectorElement::BITWORD_SIZE + }; + + // Pointer to our current Element. + ElementListIter CurrElementIter; + ElementList Elements; + + // This is like std::lower_bound, except we do linear searching from the + // current position. + ElementListIter FindLowerBound(unsigned ElementIndex) { + + if (Elements.empty()) { + CurrElementIter = Elements.begin(); + return Elements.begin(); + } + + // Make sure our current iterator is valid. + if (CurrElementIter == Elements.end()) + --CurrElementIter; + + // Search from our current iterator, either backwards or forwards, + // depending on what element we are looking for. + ElementListIter ElementIter = CurrElementIter; + if (CurrElementIter->index() == ElementIndex) { + return ElementIter; + } else if (CurrElementIter->index() > ElementIndex) { + while (ElementIter != Elements.begin() + && ElementIter->index() > ElementIndex) + --ElementIter; + } else { + while (ElementIter != Elements.end() && + ElementIter->index() < ElementIndex) + ++ElementIter; + } + CurrElementIter = ElementIter; + return ElementIter; + } + + // Iterator to walk set bits in the bitmap. This iterator is a lot uglier + // than it would be, in order to be efficient. + class SparseBitVectorIterator { + private: + bool AtEnd; + + const SparseBitVector *BitVector; + + // Current element inside of bitmap. + ElementListConstIter Iter; + + // Current bit number inside of our bitmap. + unsigned BitNumber; + + // Current word number inside of our element. + unsigned WordNumber; + + // Current bits from the element. + typename SparseBitVectorElement::BitWord Bits; + + // Move our iterator to the first non-zero bit in the bitmap. + void AdvanceToFirstNonZero() { + if (AtEnd) + return; + if (BitVector->Elements.empty()) { + AtEnd = true; + return; + } + Iter = BitVector->Elements.begin(); + BitNumber = Iter->index() * ElementSize; + unsigned BitPos = Iter->find_first(); + BitNumber += BitPos; + WordNumber = (BitNumber % ElementSize) / BITWORD_SIZE; + Bits = Iter->word(WordNumber); + Bits >>= BitPos % BITWORD_SIZE; + } + + // Move our iterator to the next non-zero bit. + void AdvanceToNextNonZero() { + if (AtEnd) + return; + + while (Bits && !(Bits & 1)) { + Bits >>= 1; + BitNumber += 1; + } + + // See if we ran out of Bits in this word. + if (!Bits) { + int NextSetBitNumber = Iter->find_next(BitNumber % ElementSize) ; + // If we ran out of set bits in this element, move to next element. + if (NextSetBitNumber == -1 || (BitNumber % ElementSize == 0)) { + ++Iter; + WordNumber = 0; + + // We may run out of elements in the bitmap. + if (Iter == BitVector->Elements.end()) { + AtEnd = true; + return; + } + // Set up for next non zero word in bitmap. + BitNumber = Iter->index() * ElementSize; + NextSetBitNumber = Iter->find_first(); + BitNumber += NextSetBitNumber; + WordNumber = (BitNumber % ElementSize) / BITWORD_SIZE; + Bits = Iter->word(WordNumber); + Bits >>= NextSetBitNumber % BITWORD_SIZE; + } else { + WordNumber = (NextSetBitNumber % ElementSize) / BITWORD_SIZE; + Bits = Iter->word(WordNumber); + Bits >>= NextSetBitNumber % BITWORD_SIZE; + BitNumber = Iter->index() * ElementSize; + BitNumber += NextSetBitNumber; + } + } + } + public: + // Preincrement. + inline SparseBitVectorIterator& operator++() { + ++BitNumber; + Bits >>= 1; + AdvanceToNextNonZero(); + return *this; + } + + // Postincrement. + inline SparseBitVectorIterator operator++(int) { + SparseBitVectorIterator tmp = *this; + ++*this; + return tmp; + } + + // Return the current set bit number. + unsigned operator*() const { + return BitNumber; + } + + bool operator==(const SparseBitVectorIterator &RHS) const { + // If they are both at the end, ignore the rest of the fields. + if (AtEnd && RHS.AtEnd) + return true; + // Otherwise they are the same if they have the same bit number and + // bitmap. + return AtEnd == RHS.AtEnd && RHS.BitNumber == BitNumber; + } + bool operator!=(const SparseBitVectorIterator &RHS) const { + return !(*this == RHS); + } + SparseBitVectorIterator(): BitVector(NULL) { + } + + + SparseBitVectorIterator(const SparseBitVector *RHS, + bool end = false):BitVector(RHS) { + Iter = BitVector->Elements.begin(); + BitNumber = 0; + Bits = 0; + WordNumber = ~0; + AtEnd = end; + AdvanceToFirstNonZero(); + } + }; +public: + typedef SparseBitVectorIterator iterator; + + SparseBitVector () { + CurrElementIter = Elements.begin (); + } + + ~SparseBitVector() { + } + + // SparseBitVector copy ctor. + SparseBitVector(const SparseBitVector &RHS) { + ElementListConstIter ElementIter = RHS.Elements.begin(); + while (ElementIter != RHS.Elements.end()) { + Elements.push_back(SparseBitVectorElement(*ElementIter)); + ++ElementIter; + } + + CurrElementIter = Elements.begin (); + } + + // Clear. + void clear() { + Elements.clear(); + } + + // Assignment + SparseBitVector& operator=(const SparseBitVector& RHS) { + Elements.clear(); + + ElementListConstIter ElementIter = RHS.Elements.begin(); + while (ElementIter != RHS.Elements.end()) { + Elements.push_back(SparseBitVectorElement(*ElementIter)); + ++ElementIter; + } + + CurrElementIter = Elements.begin (); + + return *this; + } + + // Test, Reset, and Set a bit in the bitmap. + bool test(unsigned Idx) { + if (Elements.empty()) + return false; + + unsigned ElementIndex = Idx / ElementSize; + ElementListIter ElementIter = FindLowerBound(ElementIndex); + + // If we can't find an element that is supposed to contain this bit, there + // is nothing more to do. + if (ElementIter == Elements.end() || + ElementIter->index() != ElementIndex) + return false; + return ElementIter->test(Idx % ElementSize); + } + + void reset(unsigned Idx) { + if (Elements.empty()) + return; + + unsigned ElementIndex = Idx / ElementSize; + ElementListIter ElementIter = FindLowerBound(ElementIndex); + + // If we can't find an element that is supposed to contain this bit, there + // is nothing more to do. + if (ElementIter == Elements.end() || + ElementIter->index() != ElementIndex) + return; + ElementIter->reset(Idx % ElementSize); + + // When the element is zeroed out, delete it. + if (ElementIter->empty()) { + ++CurrElementIter; + Elements.erase(ElementIter); + } + } + + void set(unsigned Idx) { + unsigned ElementIndex = Idx / ElementSize; + SparseBitVectorElement *Element; + ElementListIter ElementIter; + if (Elements.empty()) { + Element = new SparseBitVectorElement(ElementIndex); + ElementIter = Elements.insert(Elements.end(), Element); + + } else { + ElementIter = FindLowerBound(ElementIndex); + + if (ElementIter == Elements.end() || + ElementIter->index() != ElementIndex) { + Element = new SparseBitVectorElement(ElementIndex); + // We may have hit the beginning of our SparseBitVector, in which case, + // we may need to insert right after this element, which requires moving + // the current iterator forward one, because insert does insert before. + if (ElementIter != Elements.end() && + ElementIter->index() < ElementIndex) + ElementIter = Elements.insert(++ElementIter, Element); + else + ElementIter = Elements.insert(ElementIter, Element); + } + } + CurrElementIter = ElementIter; + + ElementIter->set(Idx % ElementSize); + } + + bool test_and_set (unsigned Idx) { + bool old = test(Idx); + if (!old) { + set(Idx); + return true; + } + return false; + } + + bool operator!=(const SparseBitVector &RHS) const { + return !(*this == RHS); + } + + bool operator==(const SparseBitVector &RHS) const { + ElementListConstIter Iter1 = Elements.begin(); + ElementListConstIter Iter2 = RHS.Elements.begin(); + + for (; Iter1 != Elements.end() && Iter2 != RHS.Elements.end(); + ++Iter1, ++Iter2) { + if (*Iter1 != *Iter2) + return false; + } + return Iter1 == Elements.end() && Iter2 == RHS.Elements.end(); + } + + // Union our bitmap with the RHS and return true if we changed. + bool operator|=(const SparseBitVector &RHS) { + bool changed = false; + ElementListIter Iter1 = Elements.begin(); + ElementListConstIter Iter2 = RHS.Elements.begin(); + + // If RHS is empty, we are done + if (RHS.Elements.empty()) + return false; + + while (Iter2 != RHS.Elements.end()) { + if (Iter1 == Elements.end() || Iter1->index() > Iter2->index()) { + Elements.insert(Iter1, + new SparseBitVectorElement(*Iter2)); + ++Iter2; + changed = true; + } else if (Iter1->index() == Iter2->index()) { + changed |= Iter1->unionWith(*Iter2); + ++Iter1; + ++Iter2; + } else { + ++Iter1; + } + } + CurrElementIter = Elements.begin(); + return changed; + } + + // Intersect our bitmap with the RHS and return true if ours changed. + bool operator&=(const SparseBitVector &RHS) { + bool changed = false; + ElementListIter Iter1 = Elements.begin(); + ElementListConstIter Iter2 = RHS.Elements.begin(); + + // Check if both bitmaps are empty. + if (Elements.empty() && RHS.Elements.empty()) + return false; + + // Loop through, intersecting as we go, erasing elements when necessary. + while (Iter2 != RHS.Elements.end()) { + if (Iter1 == Elements.end()) { + CurrElementIter = Elements.begin(); + return changed; + } + + if (Iter1->index() > Iter2->index()) { + ++Iter2; + } else if (Iter1->index() == Iter2->index()) { + bool BecameZero; + changed |= Iter1->intersectWith(*Iter2, BecameZero); + if (BecameZero) { + ElementListIter IterTmp = Iter1; + ++Iter1; + Elements.erase(IterTmp); + } else { + ++Iter1; + } + ++Iter2; + } else { + ElementListIter IterTmp = Iter1; + ++Iter1; + Elements.erase(IterTmp); + } + } + Elements.erase(Iter1, Elements.end()); + CurrElementIter = Elements.begin(); + return changed; + } + + // Intersect our bitmap with the complement of the RHS and return true + // if ours changed. + bool intersectWithComplement(const SparseBitVector &RHS) { + bool changed = false; + ElementListIter Iter1 = Elements.begin(); + ElementListConstIter Iter2 = RHS.Elements.begin(); + + // If either our bitmap or RHS is empty, we are done + if (Elements.empty() || RHS.Elements.empty()) + return false; + + // Loop through, intersecting as we go, erasing elements when necessary. + while (Iter2 != RHS.Elements.end()) { + if (Iter1 == Elements.end()) { + CurrElementIter = Elements.begin(); + return changed; + } + + if (Iter1->index() > Iter2->index()) { + ++Iter2; + } else if (Iter1->index() == Iter2->index()) { + bool BecameZero; + changed |= Iter1->intersectWithComplement(*Iter2, BecameZero); + if (BecameZero) { + ElementListIter IterTmp = Iter1; + ++Iter1; + Elements.erase(IterTmp); + } else { + ++Iter1; + } + ++Iter2; + } else { + ++Iter1; + } + } + CurrElementIter = Elements.begin(); + return changed; + } + + bool intersectWithComplement(const SparseBitVector *RHS) const { + return intersectWithComplement(*RHS); + } + + + // Three argument version of intersectWithComplement. + // Result of RHS1 & ~RHS2 is stored into this bitmap. + void intersectWithComplement(const SparseBitVector &RHS1, + const SparseBitVector &RHS2) + { + Elements.clear(); + CurrElementIter = Elements.begin(); + ElementListConstIter Iter1 = RHS1.Elements.begin(); + ElementListConstIter Iter2 = RHS2.Elements.begin(); + + // If RHS1 is empty, we are done + // If RHS2 is empty, we still have to copy RHS1 + if (RHS1.Elements.empty()) + return; + + // Loop through, intersecting as we go, erasing elements when necessary. + while (Iter2 != RHS2.Elements.end()) { + if (Iter1 == RHS1.Elements.end()) + return; + + if (Iter1->index() > Iter2->index()) { + ++Iter2; + } else if (Iter1->index() == Iter2->index()) { + bool BecameZero = false; + SparseBitVectorElement *NewElement = + new SparseBitVectorElement(Iter1->index()); + NewElement->intersectWithComplement(*Iter1, *Iter2, BecameZero); + if (!BecameZero) { + Elements.push_back(NewElement); + } + else + delete NewElement; + ++Iter1; + ++Iter2; + } else { + SparseBitVectorElement *NewElement = + new SparseBitVectorElement(*Iter1); + Elements.push_back(NewElement); + ++Iter1; + } + } + + // copy the remaining elements + while (Iter1 != RHS1.Elements.end()) { + SparseBitVectorElement *NewElement = + new SparseBitVectorElement(*Iter1); + Elements.push_back(NewElement); + ++Iter1; + } + + return; + } + + void intersectWithComplement(const SparseBitVector *RHS1, + const SparseBitVector *RHS2) { + intersectWithComplement(*RHS1, *RHS2); + } + + bool intersects(const SparseBitVector *RHS) const { + return intersects(*RHS); + } + + // Return true if we share any bits in common with RHS + bool intersects(const SparseBitVector &RHS) const { + ElementListConstIter Iter1 = Elements.begin(); + ElementListConstIter Iter2 = RHS.Elements.begin(); + + // Check if both bitmaps are empty. + if (Elements.empty() && RHS.Elements.empty()) + return false; + + // Loop through, intersecting stopping when we hit bits in common. + while (Iter2 != RHS.Elements.end()) { + if (Iter1 == Elements.end()) + return false; + + if (Iter1->index() > Iter2->index()) { + ++Iter2; + } else if (Iter1->index() == Iter2->index()) { + if (Iter1->intersects(*Iter2)) + return true; + ++Iter1; + ++Iter2; + } else { + ++Iter1; + } + } + return false; + } + + // Return true iff all bits set in this SparseBitVector are + // also set in RHS. + bool contains(const SparseBitVector &RHS) const { + SparseBitVector Result(*this); + Result &= RHS; + return (Result == RHS); + } + + // Return the first set bit in the bitmap. Return -1 if no bits are set. + int find_first() const { + if (Elements.empty()) + return -1; + const SparseBitVectorElement &First = *(Elements.begin()); + return (First.index() * ElementSize) + First.find_first(); + } + + // Return true if the SparseBitVector is empty + bool empty() const { + return Elements.empty(); + } + + unsigned count() const { + unsigned BitCount = 0; + for (ElementListConstIter Iter = Elements.begin(); + Iter != Elements.end(); + ++Iter) + BitCount += Iter->count(); + + return BitCount; + } + iterator begin() const { + return iterator(this); + } + + iterator end() const { + return iterator(this, true); + } + + // Get a hash value for this bitmap. + uint64_t getHashValue() const { + uint64_t HashVal = 0; + for (ElementListConstIter Iter = Elements.begin(); + Iter != Elements.end(); + ++Iter) { + HashVal ^= Iter->index(); + HashVal ^= Iter->getHashValue(); + } + return HashVal; + } +}; + +// Convenience functions to allow Or and And without dereferencing in the user +// code. + +template +inline bool operator |=(SparseBitVector &LHS, + const SparseBitVector *RHS) { + return LHS |= *RHS; +} + +template +inline bool operator |=(SparseBitVector *LHS, + const SparseBitVector &RHS) { + return LHS->operator|=(RHS); +} + +template +inline bool operator &=(SparseBitVector *LHS, + const SparseBitVector &RHS) { + return LHS->operator&=(RHS); +} + +template +inline bool operator &=(SparseBitVector &LHS, + const SparseBitVector *RHS) { + return LHS &= *RHS; +} + +// Convenience functions for infix union, intersection, difference operators. + +template +inline SparseBitVector +operator|(const SparseBitVector &LHS, + const SparseBitVector &RHS) { + SparseBitVector Result(LHS); + Result |= RHS; + return Result; +} + +template +inline SparseBitVector +operator&(const SparseBitVector &LHS, + const SparseBitVector &RHS) { + SparseBitVector Result(LHS); + Result &= RHS; + return Result; +} + +template +inline SparseBitVector +operator-(const SparseBitVector &LHS, + const SparseBitVector &RHS) { + SparseBitVector Result; + Result.intersectWithComplement(LHS, RHS); + return Result; +} + + + + +// Dump a SparseBitVector to a stream +template +void dump(const SparseBitVector &LHS, raw_ostream &out) { + out << "[ "; + + typename SparseBitVector::iterator bi; + for (bi = LHS.begin(); bi != LHS.end(); ++bi) { + out << *bi << " "; + } + out << " ]\n"; +} +} // end namespace llvm + +#endif diff --git a/libclamav/c++/llvm/include/llvm/ADT/Statistic.h b/libclamav/c++/llvm/include/llvm/ADT/Statistic.h new file mode 100644 index 000000000..1a4833cc4 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/ADT/Statistic.h @@ -0,0 +1,118 @@ +//===-- llvm/ADT/Statistic.h - Easy way to expose stats ---------*- 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 the 'Statistic' class, which is designed to be an easy way +// to expose various metrics from passes. These statistics are printed at the +// end of a run (from llvm_shutdown), when the -stats command line option is +// passed on the command line. +// +// This is useful for reporting information like the number of instructions +// simplified, optimized or removed by various transformations, like this: +// +// static Statistic NumInstsKilled("gcse", "Number of instructions killed"); +// +// Later, in the code: ++NumInstsKilled; +// +// NOTE: Statistics *must* be declared as global variables. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_STATISTIC_H +#define LLVM_ADT_STATISTIC_H + +#include "llvm/System/Atomic.h" + +namespace llvm { + +class Statistic { +public: + const char *Name; + const char *Desc; + volatile llvm::sys::cas_flag Value; + bool Initialized; + + llvm::sys::cas_flag getValue() const { return Value; } + const char *getName() const { return Name; } + const char *getDesc() const { return Desc; } + + /// construct - This should only be called for non-global statistics. + void construct(const char *name, const char *desc) { + Name = name; Desc = desc; + Value = 0; Initialized = 0; + } + + // Allow use of this class as the value itself. + operator unsigned() const { return Value; } + const Statistic &operator=(unsigned Val) { + Value = Val; + return init(); + } + + const Statistic &operator++() { + sys::AtomicIncrement(&Value); + return init(); + } + + unsigned operator++(int) { + init(); + unsigned OldValue = Value; + sys::AtomicIncrement(&Value); + return OldValue; + } + + const Statistic &operator--() { + sys::AtomicDecrement(&Value); + return init(); + } + + unsigned operator--(int) { + init(); + unsigned OldValue = Value; + sys::AtomicDecrement(&Value); + return OldValue; + } + + const Statistic &operator+=(const unsigned &V) { + sys::AtomicAdd(&Value, V); + return init(); + } + + const Statistic &operator-=(const unsigned &V) { + sys::AtomicAdd(&Value, -V); + return init(); + } + + const Statistic &operator*=(const unsigned &V) { + sys::AtomicMul(&Value, V); + return init(); + } + + const Statistic &operator/=(const unsigned &V) { + sys::AtomicDiv(&Value, V); + return init(); + } + +protected: + Statistic &init() { + bool tmp = Initialized; + sys::MemoryFence(); + if (!tmp) RegisterStatistic(); + return *this; + } + void RegisterStatistic(); +}; + +// STATISTIC - A macro to make definition of statistics really simple. This +// automatically passes the DEBUG_TYPE of the file into the statistic. +#define STATISTIC(VARNAME, DESC) \ + static llvm::Statistic VARNAME = { DEBUG_TYPE, DESC, 0, 0 } + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/ADT/StringExtras.h b/libclamav/c++/llvm/include/llvm/ADT/StringExtras.h new file mode 100644 index 000000000..85936c019 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/ADT/StringExtras.h @@ -0,0 +1,235 @@ +//===-- llvm/ADT/StringExtras.h - Useful string functions -------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains some functions that are useful when dealing with strings. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_STRINGEXTRAS_H +#define LLVM_ADT_STRINGEXTRAS_H + +#include "llvm/System/DataTypes.h" +#include "llvm/ADT/APFloat.h" +#include "llvm/ADT/StringRef.h" +#include +#include +#include +#include + +namespace llvm { + +/// hexdigit - Return the (uppercase) hexadecimal character for the +/// given number \arg X (which should be less than 16). +static inline char hexdigit(unsigned X) { + return X < 10 ? '0' + X : 'A' + X - 10; +} + +/// utohex_buffer - Emit the specified number into the buffer specified by +/// BufferEnd, returning a pointer to the start of the string. This can be used +/// like this: (note that the buffer must be large enough to handle any number): +/// char Buffer[40]; +/// printf("0x%s", utohex_buffer(X, Buffer+40)); +/// +/// This should only be used with unsigned types. +/// +template +static inline char *utohex_buffer(IntTy X, char *BufferEnd) { + char *BufPtr = BufferEnd; + *--BufPtr = 0; // Null terminate buffer. + if (X == 0) { + *--BufPtr = '0'; // Handle special case. + return BufPtr; + } + + while (X) { + unsigned char Mod = static_cast(X) & 15; + *--BufPtr = hexdigit(Mod); + X >>= 4; + } + return BufPtr; +} + +static inline std::string utohexstr(uint64_t X) { + char Buffer[40]; + return utohex_buffer(X, Buffer+40); +} + +static inline std::string utostr_32(uint32_t X, bool isNeg = false) { + char Buffer[20]; + char *BufPtr = Buffer+19; + + *BufPtr = 0; // Null terminate buffer... + if (X == 0) *--BufPtr = '0'; // Handle special case... + + while (X) { + *--BufPtr = '0' + char(X % 10); + X /= 10; + } + + if (isNeg) *--BufPtr = '-'; // Add negative sign... + + return std::string(BufPtr); +} + +static inline std::string utostr(uint64_t X, bool isNeg = false) { + if (X == uint32_t(X)) + return utostr_32(uint32_t(X), isNeg); + + char Buffer[40]; + char *BufPtr = Buffer+39; + + *BufPtr = 0; // Null terminate buffer... + if (X == 0) *--BufPtr = '0'; // Handle special case... + + while (X) { + *--BufPtr = '0' + char(X % 10); + X /= 10; + } + + if (isNeg) *--BufPtr = '-'; // Add negative sign... + return std::string(BufPtr); +} + + +static inline std::string itostr(int64_t X) { + if (X < 0) + return utostr(static_cast(-X), true); + else + return utostr(static_cast(X)); +} + +static inline std::string ftostr(double V) { + char Buffer[200]; + sprintf(Buffer, "%20.6e", V); + char *B = Buffer; + while (*B == ' ') ++B; + return B; +} + +static inline std::string ftostr(const APFloat& V) { + if (&V.getSemantics() == &APFloat::IEEEdouble) + return ftostr(V.convertToDouble()); + else if (&V.getSemantics() == &APFloat::IEEEsingle) + return ftostr((double)V.convertToFloat()); + return ""; // error +} + +static inline std::string LowercaseString(const std::string &S) { + std::string result(S); + for (unsigned i = 0; i < S.length(); ++i) + if (isupper(result[i])) + result[i] = char(tolower(result[i])); + return result; +} + +static inline std::string UppercaseString(const std::string &S) { + std::string result(S); + for (unsigned i = 0; i < S.length(); ++i) + if (islower(result[i])) + result[i] = char(toupper(result[i])); + return result; +} + +/// StringsEqualNoCase - Return true if the two strings are equal, ignoring +/// case. +static inline bool StringsEqualNoCase(const std::string &LHS, + const std::string &RHS) { + if (LHS.size() != RHS.size()) return false; + for (unsigned i = 0, e = static_cast(LHS.size()); i != e; ++i) + if (tolower(LHS[i]) != tolower(RHS[i])) return false; + return true; +} + +/// StringsEqualNoCase - Return true if the two strings are equal, ignoring +/// case. +static inline bool StringsEqualNoCase(const std::string &LHS, + const char *RHS) { + for (unsigned i = 0, e = static_cast(LHS.size()); i != e; ++i) { + if (RHS[i] == 0) return false; // RHS too short. + if (tolower(LHS[i]) != tolower(RHS[i])) return false; + } + return RHS[LHS.size()] == 0; // Not too long? +} + +/// StringsEqualNoCase - Return true if the two null-terminated C strings are +/// equal, ignoring + +static inline bool StringsEqualNoCase(const char *LHS, const char *RHS, + unsigned len) { + + for (unsigned i = 0; i < len; ++i) { + if (tolower(LHS[i]) != tolower(RHS[i])) + return false; + + // If RHS[i] == 0 then LHS[i] == 0 or otherwise we would have returned + // at the previous branch as tolower('\0') == '\0'. + if (RHS[i] == 0) + return true; + } + + return true; +} + +/// CStrInCStrNoCase - Portable version of strcasestr. Locates the first +/// occurance of c-string 's2' in string 's1', ignoring case. Returns +/// NULL if 's2' cannot be found. +static inline const char* CStrInCStrNoCase(const char *s1, const char *s2) { + + // Are either strings NULL or empty? + if (!s1 || !s2 || s1[0] == '\0' || s2[0] == '\0') + return 0; + + if (s1 == s2) + return s1; + + const char *I1=s1, *I2=s2; + + while (*I1 != '\0' && *I2 != '\0' ) + if (tolower(*I1) != tolower(*I2)) { // No match. Start over. + ++s1; I1 = s1; I2 = s2; + } + else { // Character match. Advance to the next character. + ++I1; ++I2; + } + + // If we exhausted all of the characters in 's2', then 's2' appears in 's1'. + return *I2 == '\0' ? s1 : 0; +} + +/// getToken - This function extracts one token from source, ignoring any +/// leading characters that appear in the Delimiters string, and ending the +/// token at any of the characters that appear in the Delimiters string. If +/// there are no tokens in the source string, an empty string is returned. +/// The Source source string is updated in place to remove the returned string +/// and any delimiter prefix from it. +std::string getToken(std::string &Source, + const char *Delimiters = " \t\n\v\f\r"); + +/// SplitString - Split up the specified string according to the specified +/// delimiters, appending the result fragments to the output list. +void SplitString(const std::string &Source, + std::vector &OutFragments, + const char *Delimiters = " \t\n\v\f\r"); + +/// HashString - Hash funtion for strings. +/// +/// This is the Bernstein hash function. +// +// FIXME: Investigate whether a modified bernstein hash function performs +// better: http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx +// X*33+c -> X*33^c +static inline unsigned HashString(StringRef Str, unsigned Result = 0) { + for (unsigned i = 0, e = Str.size(); i != e; ++i) + Result = Result * 33 + Str[i]; + return Result; +} + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/ADT/StringMap.h b/libclamav/c++/llvm/include/llvm/ADT/StringMap.h new file mode 100644 index 000000000..86e8546ad --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/ADT/StringMap.h @@ -0,0 +1,478 @@ +//===--- StringMap.h - String Hash table map interface ----------*- 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 the StringMap class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_STRINGMAP_H +#define LLVM_ADT_STRINGMAP_H + +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/Allocator.h" +#include +#include + +namespace llvm { + template + class StringMapConstIterator; + template + class StringMapIterator; + template + class StringMapEntry; + +/// StringMapEntryInitializer - This datatype can be partially specialized for +/// various datatypes in a stringmap to allow them to be initialized when an +/// entry is default constructed for the map. +template +class StringMapEntryInitializer { +public: + template + static void Initialize(StringMapEntry &T, InitTy InitVal) { + T.second = InitVal; + } +}; + + +/// StringMapEntryBase - Shared base class of StringMapEntry instances. +class StringMapEntryBase { + unsigned StrLen; +public: + explicit StringMapEntryBase(unsigned Len) : StrLen(Len) {} + + unsigned getKeyLength() const { return StrLen; } +}; + +/// StringMapImpl - This is the base class of StringMap that is shared among +/// all of its instantiations. +class StringMapImpl { +public: + /// ItemBucket - The hash table consists of an array of these. If Item is + /// non-null, this is an extant entry, otherwise, it is a hole. + struct ItemBucket { + /// FullHashValue - This remembers the full hash value of the key for + /// easy scanning. + unsigned FullHashValue; + + /// Item - This is a pointer to the actual item object. + StringMapEntryBase *Item; + }; + +protected: + ItemBucket *TheTable; + unsigned NumBuckets; + unsigned NumItems; + unsigned NumTombstones; + unsigned ItemSize; +protected: + explicit StringMapImpl(unsigned itemSize) : ItemSize(itemSize) { + // Initialize the map with zero buckets to allocation. + TheTable = 0; + NumBuckets = 0; + NumItems = 0; + NumTombstones = 0; + } + StringMapImpl(unsigned InitSize, unsigned ItemSize); + void RehashTable(); + + /// ShouldRehash - Return true if the table should be rehashed after a new + /// element was recently inserted. + bool ShouldRehash() const { + // If the hash table is now more than 3/4 full, or if fewer than 1/8 of + // the buckets are empty (meaning that many are filled with tombstones), + // grow the table. + return NumItems*4 > NumBuckets*3 || + NumBuckets-(NumItems+NumTombstones) < NumBuckets/8; + } + + /// LookupBucketFor - Look up the bucket that the specified string should end + /// up in. If it already exists as a key in the map, the Item pointer for the + /// specified bucket will be non-null. Otherwise, it will be null. In either + /// case, the FullHashValue field of the bucket will be set to the hash value + /// of the string. + unsigned LookupBucketFor(StringRef Key); + + /// FindKey - Look up the bucket that contains the specified key. If it exists + /// in the map, return the bucket number of the key. Otherwise return -1. + /// This does not modify the map. + int FindKey(StringRef Key) const; + + /// RemoveKey - Remove the specified StringMapEntry from the table, but do not + /// delete it. This aborts if the value isn't in the table. + void RemoveKey(StringMapEntryBase *V); + + /// RemoveKey - Remove the StringMapEntry for the specified key from the + /// table, returning it. If the key is not in the table, this returns null. + StringMapEntryBase *RemoveKey(StringRef Key); +private: + void init(unsigned Size); +public: + static StringMapEntryBase *getTombstoneVal() { + return (StringMapEntryBase*)-1; + } + + unsigned getNumBuckets() const { return NumBuckets; } + unsigned getNumItems() const { return NumItems; } + + bool empty() const { return NumItems == 0; } + unsigned size() const { return NumItems; } +}; + +/// StringMapEntry - This is used to represent one value that is inserted into +/// a StringMap. It contains the Value itself and the key: the string length +/// and data. +template +class StringMapEntry : public StringMapEntryBase { +public: + ValueTy second; + + explicit StringMapEntry(unsigned strLen) + : StringMapEntryBase(strLen), second() {} + StringMapEntry(unsigned strLen, const ValueTy &V) + : StringMapEntryBase(strLen), second(V) {} + + StringRef getKey() const { + return StringRef(getKeyData(), getKeyLength()); + } + + const ValueTy &getValue() const { return second; } + ValueTy &getValue() { return second; } + + void setValue(const ValueTy &V) { second = V; } + + /// getKeyData - Return the start of the string data that is the key for this + /// value. The string data is always stored immediately after the + /// StringMapEntry object. + const char *getKeyData() const {return reinterpret_cast(this+1);} + + const char *first() const { return getKeyData(); } + + /// Create - Create a StringMapEntry for the specified key and default + /// construct the value. + template + static StringMapEntry *Create(const char *KeyStart, const char *KeyEnd, + AllocatorTy &Allocator, + InitType InitVal) { + unsigned KeyLength = static_cast(KeyEnd-KeyStart); + + // Okay, the item doesn't already exist, and 'Bucket' is the bucket to fill + // in. Allocate a new item with space for the string at the end and a null + // terminator. + + unsigned AllocSize = static_cast(sizeof(StringMapEntry))+ + KeyLength+1; + unsigned Alignment = alignof(); + + StringMapEntry *NewItem = + static_cast(Allocator.Allocate(AllocSize,Alignment)); + + // Default construct the value. + new (NewItem) StringMapEntry(KeyLength); + + // Copy the string information. + char *StrBuffer = const_cast(NewItem->getKeyData()); + memcpy(StrBuffer, KeyStart, KeyLength); + StrBuffer[KeyLength] = 0; // Null terminate for convenience of clients. + + // Initialize the value if the client wants to. + StringMapEntryInitializer::Initialize(*NewItem, InitVal); + return NewItem; + } + + template + static StringMapEntry *Create(const char *KeyStart, const char *KeyEnd, + AllocatorTy &Allocator) { + return Create(KeyStart, KeyEnd, Allocator, 0); + } + + + /// Create - Create a StringMapEntry with normal malloc/free. + template + static StringMapEntry *Create(const char *KeyStart, const char *KeyEnd, + InitType InitVal) { + MallocAllocator A; + return Create(KeyStart, KeyEnd, A, InitVal); + } + + static StringMapEntry *Create(const char *KeyStart, const char *KeyEnd) { + return Create(KeyStart, KeyEnd, ValueTy()); + } + + /// GetStringMapEntryFromValue - Given a value that is known to be embedded + /// into a StringMapEntry, return the StringMapEntry itself. + static StringMapEntry &GetStringMapEntryFromValue(ValueTy &V) { + StringMapEntry *EPtr = 0; + char *Ptr = reinterpret_cast(&V) - + (reinterpret_cast(&EPtr->second) - + reinterpret_cast(EPtr)); + return *reinterpret_cast(Ptr); + } + static const StringMapEntry &GetStringMapEntryFromValue(const ValueTy &V) { + return GetStringMapEntryFromValue(const_cast(V)); + } + + /// Destroy - Destroy this StringMapEntry, releasing memory back to the + /// specified allocator. + template + void Destroy(AllocatorTy &Allocator) { + // Free memory referenced by the item. + this->~StringMapEntry(); + Allocator.Deallocate(this); + } + + /// Destroy this object, releasing memory back to the malloc allocator. + void Destroy() { + MallocAllocator A; + Destroy(A); + } +}; + + +/// StringMap - This is an unconventional map that is specialized for handling +/// keys that are "strings", which are basically ranges of bytes. This does some +/// funky memory allocation and hashing things to make it extremely efficient, +/// storing the string data *after* the value in the map. +template +class StringMap : public StringMapImpl { + AllocatorTy Allocator; + typedef StringMapEntry MapEntryTy; +public: + StringMap() : StringMapImpl(static_cast(sizeof(MapEntryTy))) {} + explicit StringMap(unsigned InitialSize) + : StringMapImpl(InitialSize, static_cast(sizeof(MapEntryTy))) {} + explicit StringMap(const StringMap &RHS) + : StringMapImpl(static_cast(sizeof(MapEntryTy))) { + assert(RHS.empty() && + "Copy ctor from non-empty stringmap not implemented yet!"); + } + void operator=(const StringMap &RHS) { + assert(RHS.empty() && + "assignment from non-empty stringmap not implemented yet!"); + clear(); + } + + + AllocatorTy &getAllocator() { return Allocator; } + const AllocatorTy &getAllocator() const { return Allocator; } + + typedef const char* key_type; + typedef ValueTy mapped_type; + typedef StringMapEntry value_type; + typedef size_t size_type; + + typedef StringMapConstIterator const_iterator; + typedef StringMapIterator iterator; + + iterator begin() { + return iterator(TheTable, NumBuckets == 0); + } + iterator end() { + return iterator(TheTable+NumBuckets, true); + } + const_iterator begin() const { + return const_iterator(TheTable, NumBuckets == 0); + } + const_iterator end() const { + return const_iterator(TheTable+NumBuckets, true); + } + + iterator find(StringRef Key) { + int Bucket = FindKey(Key); + if (Bucket == -1) return end(); + return iterator(TheTable+Bucket); + } + + const_iterator find(StringRef Key) const { + int Bucket = FindKey(Key); + if (Bucket == -1) return end(); + return const_iterator(TheTable+Bucket); + } + + /// lookup - Return the entry for the specified key, or a default + /// constructed value if no such entry exists. + ValueTy lookup(StringRef Key) const { + const_iterator it = find(Key); + if (it != end()) + return it->second; + return ValueTy(); + } + + ValueTy& operator[](StringRef Key) { + return GetOrCreateValue(Key).getValue(); + } + + size_type count(StringRef Key) const { + return find(Key) == end() ? 0 : 1; + } + + /// insert - Insert the specified key/value pair into the map. If the key + /// already exists in the map, return false and ignore the request, otherwise + /// insert it and return true. + bool insert(MapEntryTy *KeyValue) { + unsigned BucketNo = LookupBucketFor(KeyValue->getKey()); + ItemBucket &Bucket = TheTable[BucketNo]; + if (Bucket.Item && Bucket.Item != getTombstoneVal()) + return false; // Already exists in map. + + if (Bucket.Item == getTombstoneVal()) + --NumTombstones; + Bucket.Item = KeyValue; + ++NumItems; + + if (ShouldRehash()) + RehashTable(); + return true; + } + + // clear - Empties out the StringMap + void clear() { + if (empty()) return; + + // Zap all values, resetting the keys back to non-present (not tombstone), + // which is safe because we're removing all elements. + for (ItemBucket *I = TheTable, *E = TheTable+NumBuckets; I != E; ++I) { + if (I->Item && I->Item != getTombstoneVal()) { + static_cast(I->Item)->Destroy(Allocator); + I->Item = 0; + } + } + + NumItems = 0; + } + + /// GetOrCreateValue - Look up the specified key in the table. If a value + /// exists, return it. Otherwise, default construct a value, insert it, and + /// return. + template + StringMapEntry &GetOrCreateValue(StringRef Key, + InitTy Val) { + unsigned BucketNo = LookupBucketFor(Key); + ItemBucket &Bucket = TheTable[BucketNo]; + if (Bucket.Item && Bucket.Item != getTombstoneVal()) + return *static_cast(Bucket.Item); + + MapEntryTy *NewItem = + MapEntryTy::Create(Key.begin(), Key.end(), Allocator, Val); + + if (Bucket.Item == getTombstoneVal()) + --NumTombstones; + ++NumItems; + + // Fill in the bucket for the hash table. The FullHashValue was already + // filled in by LookupBucketFor. + Bucket.Item = NewItem; + + if (ShouldRehash()) + RehashTable(); + return *NewItem; + } + + StringMapEntry &GetOrCreateValue(StringRef Key) { + return GetOrCreateValue(Key, ValueTy()); + } + + template + StringMapEntry &GetOrCreateValue(const char *KeyStart, + const char *KeyEnd, + InitTy Val) { + return GetOrCreateValue(StringRef(KeyStart, KeyEnd - KeyStart), Val); + } + + StringMapEntry &GetOrCreateValue(const char *KeyStart, + const char *KeyEnd) { + return GetOrCreateValue(StringRef(KeyStart, KeyEnd - KeyStart)); + } + + /// remove - Remove the specified key/value pair from the map, but do not + /// erase it. This aborts if the key is not in the map. + void remove(MapEntryTy *KeyValue) { + RemoveKey(KeyValue); + } + + void erase(iterator I) { + MapEntryTy &V = *I; + remove(&V); + V.Destroy(Allocator); + } + + bool erase(StringRef Key) { + iterator I = find(Key); + if (I == end()) return false; + erase(I); + return true; + } + + ~StringMap() { + clear(); + free(TheTable); + } +}; + + +template +class StringMapConstIterator { +protected: + StringMapImpl::ItemBucket *Ptr; +public: + typedef StringMapEntry value_type; + + explicit StringMapConstIterator(StringMapImpl::ItemBucket *Bucket, + bool NoAdvance = false) + : Ptr(Bucket) { + if (!NoAdvance) AdvancePastEmptyBuckets(); + } + + const value_type &operator*() const { + return *static_cast*>(Ptr->Item); + } + const value_type *operator->() const { + return static_cast*>(Ptr->Item); + } + + bool operator==(const StringMapConstIterator &RHS) const { + return Ptr == RHS.Ptr; + } + bool operator!=(const StringMapConstIterator &RHS) const { + return Ptr != RHS.Ptr; + } + + inline StringMapConstIterator& operator++() { // Preincrement + ++Ptr; + AdvancePastEmptyBuckets(); + return *this; + } + StringMapConstIterator operator++(int) { // Postincrement + StringMapConstIterator tmp = *this; ++*this; return tmp; + } + +private: + void AdvancePastEmptyBuckets() { + while (Ptr->Item == 0 || Ptr->Item == StringMapImpl::getTombstoneVal()) + ++Ptr; + } +}; + +template +class StringMapIterator : public StringMapConstIterator { +public: + explicit StringMapIterator(StringMapImpl::ItemBucket *Bucket, + bool NoAdvance = false) + : StringMapConstIterator(Bucket, NoAdvance) { + } + StringMapEntry &operator*() const { + return *static_cast*>(this->Ptr->Item); + } + StringMapEntry *operator->() const { + return static_cast*>(this->Ptr->Item); + } +}; + +} + +#endif diff --git a/libclamav/c++/llvm/include/llvm/ADT/StringRef.h b/libclamav/c++/llvm/include/llvm/ADT/StringRef.h new file mode 100644 index 000000000..f299f5fd6 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/ADT/StringRef.h @@ -0,0 +1,402 @@ +//===--- StringRef.h - Constant String Reference Wrapper --------*- 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_STRINGREF_H +#define LLVM_ADT_STRINGREF_H + +#include +#include +#include +#include + +namespace llvm { + template + class SmallVectorImpl; + + /// StringRef - Represent a constant reference to a string, i.e. a character + /// array and a length, which need not be null terminated. + /// + /// This class does not own the string data, it is expected to be used in + /// situations where the character data resides in some other buffer, whose + /// lifetime extends past that of the StringRef. For this reason, it is not in + /// general safe to store a StringRef. + class StringRef { + public: + typedef const char *iterator; + static const size_t npos = ~size_t(0); + typedef size_t size_type; + + private: + /// The start of the string, in an external buffer. + const char *Data; + + /// The length of the string. + size_t Length; + + // Workaround PR5482: nearly all gcc 4.x miscompile StringRef and std::min() + // Changing the arg of min to be an integer, instead of a reference to an + // integer works around this bug. + size_t min(size_t a, size_t b) const + { + return a < b ? a : b; + } + + size_t max(size_t a, size_t b) const + { + return a > b ? a : b; + } + + public: + /// @name Constructors + /// @{ + + /// Construct an empty string ref. + /*implicit*/ StringRef() : Data(0), Length(0) {} + + /// Construct a string ref from a cstring. + /*implicit*/ StringRef(const char *Str) + : Data(Str), Length(::strlen(Str)) {} + + /// Construct a string ref from a pointer and length. + /*implicit*/ StringRef(const char *data, size_t length) + : Data(data), Length(length) {} + + /// Construct a string ref from an std::string. + /*implicit*/ StringRef(const std::string &Str) + : Data(Str.data()), Length(Str.length()) {} + + /// @} + /// @name Iterators + /// @{ + + iterator begin() const { return Data; } + + iterator end() const { return Data + Length; } + + /// @} + /// @name String Operations + /// @{ + + /// data - Get a pointer to the start of the string (which may not be null + /// terminated). + const char *data() const { return Data; } + + /// empty - Check if the string is empty. + bool empty() const { return Length == 0; } + + /// size - Get the string size. + size_t size() const { return Length; } + + /// front - Get the first character in the string. + char front() const { + assert(!empty()); + return Data[0]; + } + + /// back - Get the last character in the string. + char back() const { + assert(!empty()); + return Data[Length-1]; + } + + /// equals - Check for string equality, this is more efficient than + /// compare() when the relative ordering of inequal strings isn't needed. + bool equals(StringRef RHS) const { + return (Length == RHS.Length && + memcmp(Data, RHS.Data, RHS.Length) == 0); + } + + /// equals_lower - Check for string equality, ignoring case. + bool equals_lower(StringRef RHS) const { + return Length == RHS.Length && compare_lower(RHS) == 0; + } + + /// compare - Compare two strings; the result is -1, 0, or 1 if this string + /// is lexicographically less than, equal to, or greater than the \arg RHS. + int compare(StringRef RHS) const { + // Check the prefix for a mismatch. + if (int Res = memcmp(Data, RHS.Data, min(Length, RHS.Length))) + return Res < 0 ? -1 : 1; + + // Otherwise the prefixes match, so we only need to check the lengths. + if (Length == RHS.Length) + return 0; + return Length < RHS.Length ? -1 : 1; + } + + /// compare_lower - Compare two strings, ignoring case. + int compare_lower(StringRef RHS) const; + + /// str - Get the contents as an std::string. + std::string str() const { return std::string(Data, Length); } + + /// @} + /// @name Operator Overloads + /// @{ + + char operator[](size_t Index) const { + assert(Index < Length && "Invalid index!"); + return Data[Index]; + } + + /// @} + /// @name Type Conversions + /// @{ + + operator std::string() const { + return str(); + } + + /// @} + /// @name String Predicates + /// @{ + + /// startswith - Check if this string starts with the given \arg Prefix. + bool startswith(StringRef Prefix) const { + return substr(0, Prefix.Length).equals(Prefix); + } + + /// endswith - Check if this string ends with the given \arg Suffix. + bool endswith(StringRef Suffix) const { + return slice(size() - Suffix.Length, size()).equals(Suffix); + } + + /// @} + /// @name String Searching + /// @{ + + /// find - Search for the first character \arg C in the string. + /// + /// \return - The index of the first occurence of \arg C, or npos if not + /// found. + size_t find(char C, size_t From = 0) const { + for (size_t i = min(From, Length), e = Length; i != e; ++i) + if (Data[i] == C) + return i; + return npos; + } + + /// find - Search for the first string \arg Str in the string. + /// + /// \return - The index of the first occurence of \arg Str, or npos if not + /// found. + size_t find(StringRef Str, size_t From = 0) const; + + /// rfind - Search for the last character \arg C in the string. + /// + /// \return - The index of the last occurence of \arg C, or npos if not + /// found. + size_t rfind(char C, size_t From = npos) const { + From = min(From, Length); + size_t i = From; + while (i != 0) { + --i; + if (Data[i] == C) + return i; + } + return npos; + } + + /// rfind - Search for the last string \arg Str in the string. + /// + /// \return - The index of the last occurence of \arg Str, or npos if not + /// found. + size_t rfind(StringRef Str) const; + + /// find_first_of - Find the first character in the string that is \arg C, + /// or npos if not found. Same as find. + size_type find_first_of(char C, size_t = 0) const { return find(C); } + + /// find_first_of - Find the first character in the string that is in \arg + /// Chars, or npos if not found. + /// + /// Note: O(size() * Chars.size()) + size_type find_first_of(StringRef Chars, size_t From = 0) const; + + /// find_first_not_of - Find the first character in the string that is not + /// \arg C or npos if not found. + size_type find_first_not_of(char C, size_t From = 0) const; + + /// find_first_not_of - Find the first character in the string that is not + /// in the string \arg Chars, or npos if not found. + /// + /// Note: O(size() * Chars.size()) + size_type find_first_not_of(StringRef Chars, size_t From = 0) const; + + /// @} + /// @name Helpful Algorithms + /// @{ + + /// count - Return the number of occurrences of \arg C in the string. + size_t count(char C) const { + size_t Count = 0; + for (size_t i = 0, e = Length; i != e; ++i) + if (Data[i] == C) + ++Count; + return Count; + } + + /// count - Return the number of non-overlapped occurrences of \arg Str in + /// the string. + size_t count(StringRef Str) const; + + /// getAsInteger - Parse the current string as an integer of the specified + /// radix. If Radix is specified as zero, this does radix autosensing using + /// extended C rules: 0 is octal, 0x is hex, 0b is binary. + /// + /// If the string is invalid or if only a subset of the string is valid, + /// this returns true to signify the error. The string is considered + /// erroneous if empty. + /// + bool getAsInteger(unsigned Radix, long long &Result) const; + bool getAsInteger(unsigned Radix, unsigned long long &Result) const; + bool getAsInteger(unsigned Radix, int &Result) const; + bool getAsInteger(unsigned Radix, unsigned &Result) const; + + // TODO: Provide overloads for int/unsigned that check for overflow. + + /// @} + /// @name Substring Operations + /// @{ + + /// substr - Return a reference to the substring from [Start, Start + N). + /// + /// \param Start - The index of the starting character in the substring; if + /// the index is npos or greater than the length of the string then the + /// empty substring will be returned. + /// + /// \param N - The number of characters to included in the substring. If N + /// exceeds the number of characters remaining in the string, the string + /// suffix (starting with \arg Start) will be returned. + StringRef substr(size_t Start, size_t N = npos) const { + Start = min(Start, Length); + return StringRef(Data + Start, min(N, Length - Start)); + } + + /// slice - Return a reference to the substring from [Start, End). + /// + /// \param Start - The index of the starting character in the substring; if + /// the index is npos or greater than the length of the string then the + /// empty substring will be returned. + /// + /// \param End - The index following the last character to include in the + /// substring. If this is npos, or less than \arg Start, or exceeds the + /// number of characters remaining in the string, the string suffix + /// (starting with \arg Start) will be returned. + StringRef slice(size_t Start, size_t End) const { + Start = min(Start, Length); + End = min(max(Start, End), Length); + return StringRef(Data + Start, End - Start); + } + + /// split - Split into two substrings around the first occurence of a + /// separator character. + /// + /// If \arg Separator is in the string, then the result is a pair (LHS, RHS) + /// such that (*this == LHS + Separator + RHS) is true and RHS is + /// maximal. If \arg Separator is not in the string, then the result is a + /// pair (LHS, RHS) where (*this == LHS) and (RHS == ""). + /// + /// \param Separator - The character to split on. + /// \return - The split substrings. + std::pair split(char Separator) const { + size_t Idx = find(Separator); + if (Idx == npos) + return std::make_pair(*this, StringRef()); + return std::make_pair(slice(0, Idx), slice(Idx+1, npos)); + } + + /// split - Split into two substrings around the first occurence of a + /// separator string. + /// + /// If \arg Separator is in the string, then the result is a pair (LHS, RHS) + /// such that (*this == LHS + Separator + RHS) is true and RHS is + /// maximal. If \arg Separator is not in the string, then the result is a + /// pair (LHS, RHS) where (*this == LHS) and (RHS == ""). + /// + /// \param Separator - The string to split on. + /// \return - The split substrings. + std::pair split(StringRef Separator) const { + size_t Idx = find(Separator); + if (Idx == npos) + return std::make_pair(*this, StringRef()); + return std::make_pair(slice(0, Idx), slice(Idx + Separator.size(), npos)); + } + + /// split - Split into substrings around the occurences of a separator + /// string. + /// + /// Each substring is stored in \arg A. If \arg MaxSplit is >= 0, at most + /// \arg MaxSplit splits are done and consequently <= \arg MaxSplit + /// elements are added to A. + /// If \arg KeepEmpty is false, empty strings are not added to \arg A. They + /// still count when considering \arg MaxSplit + /// An useful invariant is that + /// Separator.join(A) == *this if MaxSplit == -1 and KeepEmpty == true + /// + /// \param A - Where to put the substrings. + /// \param Separator - The string to split on. + /// \param MaxSplit - The maximum number of times the string is split. + /// \parm KeepEmpty - True if empty substring should be added. + void split(SmallVectorImpl &A, + StringRef Separator, int MaxSplit = -1, + bool KeepEmpty = true) const; + + /// rsplit - Split into two substrings around the last occurence of a + /// separator character. + /// + /// If \arg Separator is in the string, then the result is a pair (LHS, RHS) + /// such that (*this == LHS + Separator + RHS) is true and RHS is + /// minimal. If \arg Separator is not in the string, then the result is a + /// pair (LHS, RHS) where (*this == LHS) and (RHS == ""). + /// + /// \param Separator - The character to split on. + /// \return - The split substrings. + std::pair rsplit(char Separator) const { + size_t Idx = rfind(Separator); + if (Idx == npos) + return std::make_pair(*this, StringRef()); + return std::make_pair(slice(0, Idx), slice(Idx+1, npos)); + } + + /// @} + }; + + /// @name StringRef Comparison Operators + /// @{ + + inline bool operator==(StringRef LHS, StringRef RHS) { + return LHS.equals(RHS); + } + + inline bool operator!=(StringRef LHS, StringRef RHS) { + return !(LHS == RHS); + } + + inline bool operator<(StringRef LHS, StringRef RHS) { + return LHS.compare(RHS) == -1; + } + + inline bool operator<=(StringRef LHS, StringRef RHS) { + return LHS.compare(RHS) != 1; + } + + inline bool operator>(StringRef LHS, StringRef RHS) { + return LHS.compare(RHS) == 1; + } + + inline bool operator>=(StringRef LHS, StringRef RHS) { + return LHS.compare(RHS) != -1; + } + + /// @} + +} + +#endif diff --git a/libclamav/c++/llvm/include/llvm/ADT/StringSet.h b/libclamav/c++/llvm/include/llvm/ADT/StringSet.h new file mode 100644 index 000000000..00048361e --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/ADT/StringSet.h @@ -0,0 +1,39 @@ +//===--- StringSet.h - The LLVM Compiler Driver -----------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open +// Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// StringSet - A set-like wrapper for the StringMap. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_STRINGSET_H +#define LLVM_ADT_STRINGSET_H + +#include "llvm/ADT/StringMap.h" +#include + +namespace llvm { + + /// StringSet - A wrapper for StringMap that provides set-like + /// functionality. Only insert() and count() methods are used by my + /// code. + template + class StringSet : public llvm::StringMap { + typedef llvm::StringMap base; + public: + bool insert(const std::string& InLang) { + assert(!InLang.empty()); + const char* KeyStart = &InLang[0]; + const char* KeyEnd = KeyStart + InLang.size(); + return base::insert(llvm::StringMapEntry:: + Create(KeyStart, KeyEnd, base::getAllocator(), '+')); + } + }; +} + +#endif // LLVM_ADT_STRINGSET_H diff --git a/libclamav/c++/llvm/include/llvm/ADT/StringSwitch.h b/libclamav/c++/llvm/include/llvm/ADT/StringSwitch.h new file mode 100644 index 000000000..6562d57d3 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/ADT/StringSwitch.h @@ -0,0 +1,110 @@ +//===--- StringSwitch.h - Switch-on-literal-string Construct --------------===/ +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +//===----------------------------------------------------------------------===/ +// +// This file implements the StringSwitch template, which mimics a switch() +// statements whose cases are string literals. +// +//===----------------------------------------------------------------------===/ +#ifndef LLVM_ADT_STRINGSWITCH_H +#define LLVM_ADT_STRINGSWITCH_H + +#include "llvm/ADT/StringRef.h" +#include +#include + +namespace llvm { + +/// \brief A switch()-like statement whose cases are string literals. +/// +/// The StringSwitch class is a simple form of a switch() statement that +/// determines whether the given string matches one of the given string +/// literals. The template type parameter \p T is the type of the value that +/// will be returned from the string-switch expression. For example, +/// the following code switches on the name of a color in \c argv[i]: +/// +/// \code +/// Color color = StringSwitch(argv[i]) +/// .Case("red", Red) +/// .Case("orange", Orange) +/// .Case("yellow", Yellow) +/// .Case("green", Green) +/// .Case("blue", Blue) +/// .Case("indigo", Indigo) +/// .Case("violet", Violet) +/// .Default(UnknownColor); +/// \endcode +template +class StringSwitch { + /// \brief The string we are matching. + StringRef Str; + + /// \brief The result of this switch statement, once known. + T Result; + + /// \brief Set true when the result of this switch is already known; in this + /// case, Result is valid. + bool ResultKnown; + +public: + explicit StringSwitch(StringRef Str) + : Str(Str), ResultKnown(false) { } + + template + StringSwitch& Case(const char (&S)[N], const T& Value) { + if (!ResultKnown && N-1 == Str.size() && + (std::memcmp(S, Str.data(), N-1) == 0)) { + Result = Value; + ResultKnown = true; + } + + return *this; + } + + template + StringSwitch& Cases(const char (&S0)[N0], const char (&S1)[N1], + const T& Value) { + return Case(S0, Value).Case(S1, Value); + } + + template + StringSwitch& Cases(const char (&S0)[N0], const char (&S1)[N1], + const char (&S2)[N2], const T& Value) { + return Case(S0, Value).Case(S1, Value).Case(S2, Value); + } + + template + StringSwitch& Cases(const char (&S0)[N0], const char (&S1)[N1], + const char (&S2)[N2], const char (&S3)[N3], + const T& Value) { + return Case(S0, Value).Case(S1, Value).Case(S2, Value).Case(S3, Value); + } + + template + StringSwitch& Cases(const char (&S0)[N0], const char (&S1)[N1], + const char (&S2)[N2], const char (&S3)[N3], + const char (&S4)[N4], const T& Value) { + return Case(S0, Value).Case(S1, Value).Case(S2, Value).Case(S3, Value) + .Case(S4, Value); + } + + T Default(const T& Value) { + if (ResultKnown) + return Result; + + return Value; + } + + operator T() { + assert(ResultKnown && "Fell off the end of a string-switch"); + return Result; + } +}; + +} // end namespace llvm + +#endif // LLVM_ADT_STRINGSWITCH_H diff --git a/libclamav/c++/llvm/include/llvm/ADT/Trie.h b/libclamav/c++/llvm/include/llvm/ADT/Trie.h new file mode 100644 index 000000000..b415990b2 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/ADT/Trie.h @@ -0,0 +1,337 @@ +//===- llvm/ADT/Trie.h ---- Generic trie structure --------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This class defines a generic trie structure. The trie structure +// is immutable after creation, but the payload contained within it is not. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_TRIE_H +#define LLVM_ADT_TRIE_H + +#include "llvm/ADT/GraphTraits.h" +#include "llvm/Support/DOTGraphTraits.h" + +#include +#include + +namespace llvm { + +// FIXME: +// - Labels are usually small, maybe it's better to use SmallString +// - Should we use char* during construction? +// - Should we templatize Empty with traits-like interface? + +template +class Trie { + friend class GraphTraits >; + friend class DOTGraphTraits >; +public: + class Node { + friend class Trie; + + public: + typedef std::vector NodeVectorType; + typedef typename NodeVectorType::iterator iterator; + typedef typename NodeVectorType::const_iterator const_iterator; + + private: + enum QueryResult { + Same = -3, + StringIsPrefix = -2, + LabelIsPrefix = -1, + DontMatch = 0, + HaveCommonPart + }; + + struct NodeCmp { + bool operator() (Node* N1, Node* N2) { + return (N1->Label[0] < N2->Label[0]); + } + bool operator() (Node* N, char Id) { + return (N->Label[0] < Id); + } + }; + + std::string Label; + Payload Data; + NodeVectorType Children; + + // Do not implement + Node(const Node&); + Node& operator=(const Node&); + + inline void addEdge(Node* N) { + if (Children.empty()) + Children.push_back(N); + else { + iterator I = std::lower_bound(Children.begin(), Children.end(), + N, NodeCmp()); + // FIXME: no dups are allowed + Children.insert(I, N); + } + } + + inline void setEdge(Node* N) { + char Id = N->Label[0]; + iterator I = std::lower_bound(Children.begin(), Children.end(), + Id, NodeCmp()); + assert(I != Children.end() && "Node does not exists!"); + *I = N; + } + + QueryResult query(const std::string& s) const { + unsigned i, l; + unsigned l1 = s.length(); + unsigned l2 = Label.length(); + + // Find the length of common part + l = std::min(l1, l2); + i = 0; + while ((i < l) && (s[i] == Label[i])) + ++i; + + if (i == l) { // One is prefix of another, find who is who + if (l1 == l2) + return Same; + else if (i == l1) + return StringIsPrefix; + else + return LabelIsPrefix; + } else // s and Label have common (possible empty) part, return its length + return (QueryResult)i; + } + + public: + inline explicit Node(const Payload& data, const std::string& label = ""): + Label(label), Data(data) { } + + inline const Payload& data() const { return Data; } + inline void setData(const Payload& data) { Data = data; } + + inline const std::string& label() const { return Label; } + +#if 0 + inline void dump() { + llvm::cerr << "Node: " << this << "\n" + << "Label: " << Label << "\n" + << "Children:\n"; + + for (iterator I = Children.begin(), E = Children.end(); I != E; ++I) + llvm::cerr << (*I)->Label << "\n"; + } +#endif + + inline Node* getEdge(char Id) { + Node* fNode = NULL; + iterator I = std::lower_bound(Children.begin(), Children.end(), + Id, NodeCmp()); + if (I != Children.end() && (*I)->Label[0] == Id) + fNode = *I; + + return fNode; + } + + inline iterator begin() { return Children.begin(); } + inline const_iterator begin() const { return Children.begin(); } + inline iterator end () { return Children.end(); } + inline const_iterator end () const { return Children.end(); } + + inline size_t size () const { return Children.size(); } + inline bool empty() const { return Children.empty(); } + inline const Node* &front() const { return Children.front(); } + inline Node* &front() { return Children.front(); } + inline const Node* &back() const { return Children.back(); } + inline Node* &back() { return Children.back(); } + + }; + +private: + std::vector Nodes; + Payload Empty; + + inline Node* addNode(const Payload& data, const std::string label = "") { + Node* N = new Node(data, label); + Nodes.push_back(N); + return N; + } + + inline Node* splitEdge(Node* N, char Id, size_t index) { + Node* eNode = N->getEdge(Id); + assert(eNode && "Node doesn't exist"); + + const std::string &l = eNode->Label; + assert(index > 0 && index < l.length() && "Trying to split too far!"); + std::string l1 = l.substr(0, index); + std::string l2 = l.substr(index); + + Node* nNode = addNode(Empty, l1); + N->setEdge(nNode); + + eNode->Label = l2; + nNode->addEdge(eNode); + + return nNode; + } + + // Do not implement + Trie(const Trie&); + Trie& operator=(const Trie&); + +public: + inline explicit Trie(const Payload& empty):Empty(empty) { + addNode(Empty); + } + inline ~Trie() { + for (unsigned i = 0, e = Nodes.size(); i != e; ++i) + delete Nodes[i]; + } + + inline Node* getRoot() const { return Nodes[0]; } + + bool addString(const std::string& s, const Payload& data); + const Payload& lookup(const std::string& s) const; + +}; + +// Define this out-of-line to dissuade the C++ compiler from inlining it. +template +bool Trie::addString(const std::string& s, const Payload& data) { + Node* cNode = getRoot(); + Node* tNode = NULL; + std::string s1(s); + + while (tNode == NULL) { + char Id = s1[0]; + if (Node* nNode = cNode->getEdge(Id)) { + typename Node::QueryResult r = nNode->query(s1); + + switch (r) { + case Node::Same: + case Node::StringIsPrefix: + // Currently we don't allow to have two strings in the trie one + // being a prefix of another. This should be fixed. + assert(0 && "FIXME!"); + return false; + case Node::DontMatch: + assert(0 && "Impossible!"); + return false; + case Node::LabelIsPrefix: + s1 = s1.substr(nNode->label().length()); + cNode = nNode; + break; + default: + nNode = splitEdge(cNode, Id, r); + tNode = addNode(data, s1.substr(r)); + nNode->addEdge(tNode); + } + } else { + tNode = addNode(data, s1); + cNode->addEdge(tNode); + } + } + + return true; +} + +template +const Payload& Trie::lookup(const std::string& s) const { + Node* cNode = getRoot(); + Node* tNode = NULL; + std::string s1(s); + + while (tNode == NULL) { + char Id = s1[0]; + if (Node* nNode = cNode->getEdge(Id)) { + typename Node::QueryResult r = nNode->query(s1); + + switch (r) { + case Node::Same: + tNode = nNode; + break; + case Node::StringIsPrefix: + return Empty; + case Node::DontMatch: + assert(0 && "Impossible!"); + return Empty; + case Node::LabelIsPrefix: + s1 = s1.substr(nNode->label().length()); + cNode = nNode; + break; + default: + return Empty; + } + } else + return Empty; + } + + return tNode->data(); +} + +template +struct GraphTraits > { + typedef Trie TrieType; + typedef typename TrieType::Node NodeType; + typedef typename NodeType::iterator ChildIteratorType; + + static inline NodeType *getEntryNode(const TrieType& T) { + return T.getRoot(); + } + + static inline ChildIteratorType child_begin(NodeType *N) { + return N->begin(); + } + static inline ChildIteratorType child_end(NodeType *N) { return N->end(); } + + typedef typename std::vector::const_iterator nodes_iterator; + + static inline nodes_iterator nodes_begin(const TrieType& G) { + return G.Nodes.begin(); + } + static inline nodes_iterator nodes_end(const TrieType& G) { + return G.Nodes.end(); + } + +}; + +template +struct DOTGraphTraits > : public DefaultDOTGraphTraits { + typedef typename Trie::Node NodeType; + typedef typename GraphTraits >::ChildIteratorType EdgeIter; + + static std::string getGraphName(const Trie& T) { + return "Trie"; + } + + static std::string getNodeLabel(NodeType* Node, const Trie& T, + bool ShortNames) { + if (T.getRoot() == Node) + return ""; + else + return Node->label(); + } + + static std::string getEdgeSourceLabel(NodeType* Node, EdgeIter I) { + NodeType* N = *I; + return N->label().substr(0, 1); + } + + static std::string getNodeAttributes(const NodeType* Node, + const Trie& T) { + if (Node->data() != T.Empty) + return "color=blue"; + + return ""; + } + +}; + +} // end of llvm namespace + +#endif // LLVM_ADT_TRIE_H diff --git a/libclamav/c++/llvm/include/llvm/ADT/Triple.h b/libclamav/c++/llvm/include/llvm/ADT/Triple.h new file mode 100644 index 000000000..fe39324dd --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/ADT/Triple.h @@ -0,0 +1,289 @@ +//===-- llvm/ADT/Triple.h - Target triple helper class ----------*- 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_TRIPLE_H +#define LLVM_ADT_TRIPLE_H + +#include "llvm/ADT/StringRef.h" +#include + +// Some system headers or GCC predefined macros conflict with identifiers in +// this file. Undefine them here. +#undef mips +#undef sparc + +namespace llvm { +class StringRef; +class Twine; + +/// Triple - Helper class for working with target triples. +/// +/// Target triples are strings in the format of: +/// ARCHITECTURE-VENDOR-OPERATING_SYSTEM +/// or +/// ARCHITECTURE-VENDOR-OPERATING_SYSTEM-ENVIRONMENT +/// +/// This class is used for clients which want to support arbitrary +/// target triples, but also want to implement certain special +/// behavior for particular targets. This class isolates the mapping +/// from the components of the target triple to well known IDs. +/// +/// At its core the Triple class is designed to be a wrapper for a triple +/// string; it does not normally change or normalize the triple string, instead +/// it provides additional APIs to parse normalized parts out of the triple. +/// +/// One curiosity this implies is that for some odd triples the results of, +/// e.g., getOSName() can be very different from the result of getOS(). For +/// example, for 'i386-mingw32', getOS() will return MinGW32, but since +/// getOSName() is purely based on the string structure that will return the +/// empty string. +/// +/// Clients should generally avoid using getOSName() and related APIs unless +/// they are familiar with the triple format (this is particularly true when +/// rewriting a triple). +/// +/// See autoconf/config.guess for a glimpse into what they look like in +/// practice. +class Triple { +public: + enum ArchType { + UnknownArch, + + alpha, // Alpha: alpha + arm, // ARM; arm, armv.*, xscale + bfin, // Blackfin: bfin + cellspu, // CellSPU: spu, cellspu + mips, // MIPS: mips, mipsallegrex + mipsel, // MIPSEL: mipsel, mipsallegrexel, psp + msp430, // MSP430: msp430 + pic16, // PIC16: pic16 + ppc, // PPC: powerpc + ppc64, // PPC64: powerpc64, ppu + sparc, // Sparc: sparc + systemz, // SystemZ: s390x + tce, // TCE (http://tce.cs.tut.fi/): tce + thumb, // Thumb: thumb, thumbv.* + x86, // X86: i[3-9]86 + x86_64, // X86-64: amd64, x86_64 + xcore, // XCore: xcore + + InvalidArch + }; + enum VendorType { + UnknownVendor, + + Apple, + PC + }; + enum OSType { + UnknownOS, + + AuroraUX, + Cygwin, + Darwin, + DragonFly, + FreeBSD, + Linux, + Lv2, // PS3 + MinGW32, + MinGW64, + NetBSD, + OpenBSD, + Psp, + Solaris, + Win32, + Haiku + }; + +private: + std::string Data; + + /// The parsed arch type (or InvalidArch if uninitialized). + mutable ArchType Arch; + + /// The parsed vendor type. + mutable VendorType Vendor; + + /// The parsed OS type. + mutable OSType OS; + + bool isInitialized() const { return Arch != InvalidArch; } + void Parse() const; + +public: + /// @name Constructors + /// @{ + + Triple() : Data(), Arch(InvalidArch) {} + explicit Triple(StringRef Str) : Data(Str), Arch(InvalidArch) {} + explicit Triple(StringRef ArchStr, StringRef VendorStr, StringRef OSStr) + : Data(ArchStr), Arch(InvalidArch) { + Data += '-'; + Data += VendorStr; + Data += '-'; + Data += OSStr; + } + + /// @} + /// @name Typed Component Access + /// @{ + + /// getArch - Get the parsed architecture type of this triple. + ArchType getArch() const { + if (!isInitialized()) Parse(); + return Arch; + } + + /// getVendor - Get the parsed vendor type of this triple. + VendorType getVendor() const { + if (!isInitialized()) Parse(); + return Vendor; + } + + /// getOS - Get the parsed operating system type of this triple. + OSType getOS() const { + if (!isInitialized()) Parse(); + return OS; + } + + /// hasEnvironment - Does this triple have the optional environment + /// (fourth) component? + bool hasEnvironment() const { + return getEnvironmentName() != ""; + } + + /// @} + /// @name Direct Component Access + /// @{ + + const std::string &str() const { return Data; } + + const std::string &getTriple() const { return Data; } + + /// getArchName - Get the architecture (first) component of the + /// triple. + StringRef getArchName() const; + + /// getVendorName - Get the vendor (second) component of the triple. + StringRef getVendorName() const; + + /// getOSName - Get the operating system (third) component of the + /// triple. + StringRef getOSName() const; + + /// getEnvironmentName - Get the optional environment (fourth) + /// component of the triple, or "" if empty. + StringRef getEnvironmentName() const; + + /// getOSAndEnvironmentName - Get the operating system and optional + /// environment components as a single string (separated by a '-' + /// if the environment component is present). + StringRef getOSAndEnvironmentName() const; + + + /// getDarwinNumber - Parse the 'darwin number' out of the specific target + /// triple. For example, if we have darwin8.5 return 8,5,0. If any entry is + /// not defined, return 0's. This requires that the triple have an OSType of + /// darwin before it is called. + void getDarwinNumber(unsigned &Maj, unsigned &Min, unsigned &Revision) const; + + /// getDarwinMajorNumber - Return just the major version number, this is + /// specialized because it is a common query. + unsigned getDarwinMajorNumber() const { + unsigned Maj, Min, Rev; + getDarwinNumber(Maj, Min, Rev); + return Maj; + } + + /// @} + /// @name Mutators + /// @{ + + /// setArch - Set the architecture (first) component of the triple + /// to a known type. + void setArch(ArchType Kind); + + /// setVendor - Set the vendor (second) component of the triple to a + /// known type. + void setVendor(VendorType Kind); + + /// setOS - Set the operating system (third) component of the triple + /// to a known type. + void setOS(OSType Kind); + + /// setTriple - Set all components to the new triple \arg Str. + void setTriple(const Twine &Str); + + /// setArchName - Set the architecture (first) component of the + /// triple by name. + void setArchName(StringRef Str); + + /// setVendorName - Set the vendor (second) component of the triple + /// by name. + void setVendorName(StringRef Str); + + /// setOSName - Set the operating system (third) component of the + /// triple by name. + void setOSName(StringRef Str); + + /// setEnvironmentName - Set the optional environment (fourth) + /// component of the triple by name. + void setEnvironmentName(StringRef Str); + + /// setOSAndEnvironmentName - Set the operating system and optional + /// environment components with a single string. + void setOSAndEnvironmentName(StringRef Str); + + /// getArchNameForAssembler - Get an architecture name that is understood by the + /// target assembler. + const char *getArchNameForAssembler(); + + /// @} + /// @name Static helpers for IDs. + /// @{ + + /// getArchTypeName - Get the canonical name for the \arg Kind + /// architecture. + static const char *getArchTypeName(ArchType Kind); + + /// getArchTypePrefix - Get the "prefix" canonical name for the \arg Kind + /// architecture. This is the prefix used by the architecture specific + /// builtins, and is suitable for passing to \see + /// Intrinsic::getIntrinsicForGCCBuiltin(). + /// + /// \return - The architecture prefix, or 0 if none is defined. + static const char *getArchTypePrefix(ArchType Kind); + + /// getVendorTypeName - Get the canonical name for the \arg Kind + /// vendor. + static const char *getVendorTypeName(VendorType Kind); + + /// getOSTypeName - Get the canonical name for the \arg Kind vendor. + static const char *getOSTypeName(OSType Kind); + + /// @} + /// @name Static helpers for converting alternate architecture names. + /// @{ + + /// getArchTypeForLLVMName - The canonical type for the given LLVM + /// architecture name (e.g., "x86"). + static ArchType getArchTypeForLLVMName(StringRef Str); + + /// getArchTypeForDarwinArchName - Get the architecture type for a "Darwin" + /// architecture name, for example as accepted by "gcc -arch" (see also + /// arch(3)). + static ArchType getArchTypeForDarwinArchName(StringRef Str); + + /// @} +}; + +} // End llvm namespace + + +#endif diff --git a/libclamav/c++/llvm/include/llvm/ADT/Twine.h b/libclamav/c++/llvm/include/llvm/ADT/Twine.h new file mode 100644 index 000000000..ca0be53d4 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/ADT/Twine.h @@ -0,0 +1,422 @@ +//===-- Twine.h - Fast Temporary String Concatenation -----------*- 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_TWINE_H +#define LLVM_ADT_TWINE_H + +#include "llvm/ADT/StringRef.h" +#include "llvm/System/DataTypes.h" +#include +#include + +namespace llvm { + template + class SmallVectorImpl; + class StringRef; + class raw_ostream; + + /// Twine - A lightweight data structure for efficiently representing the + /// concatenation of temporary values as strings. + /// + /// A Twine is a kind of rope, it represents a concatenated string using a + /// binary-tree, where the string is the preorder of the nodes. Since the + /// Twine can be efficiently rendered into a buffer when its result is used, + /// it avoids the cost of generating temporary values for intermediate string + /// results -- particularly in cases when the Twine result is never + /// required. By explicitly tracking the type of leaf nodes, we can also avoid + /// the creation of temporary strings for conversions operations (such as + /// appending an integer to a string). + /// + /// A Twine is not intended for use directly and should not be stored, its + /// implementation relies on the ability to store pointers to temporary stack + /// objects which may be deallocated at the end of a statement. Twines should + /// only be used accepted as const references in arguments, when an API wishes + /// to accept possibly-concatenated strings. + /// + /// Twines support a special 'null' value, which always concatenates to form + /// itself, and renders as an empty string. This can be returned from APIs to + /// effectively nullify any concatenations performed on the result. + /// + /// \b Implementation \n + /// + /// Given the nature of a Twine, it is not possible for the Twine's + /// concatenation method to construct interior nodes; the result must be + /// represented inside the returned value. For this reason a Twine object + /// actually holds two values, the left- and right-hand sides of a + /// concatenation. We also have nullary Twine objects, which are effectively + /// sentinel values that represent empty strings. + /// + /// Thus, a Twine can effectively have zero, one, or two children. The \see + /// isNullary(), \see isUnary(), and \see isBinary() predicates exist for + /// testing the number of children. + /// + /// We maintain a number of invariants on Twine objects (FIXME: Why): + /// - Nullary twines are always represented with their Kind on the left-hand + /// side, and the Empty kind on the right-hand side. + /// - Unary twines are always represented with the value on the left-hand + /// side, and the Empty kind on the right-hand side. + /// - If a Twine has another Twine as a child, that child should always be + /// binary (otherwise it could have been folded into the parent). + /// + /// These invariants are check by \see isValid(). + /// + /// \b Efficiency Considerations \n + /// + /// The Twine is designed to yield efficient and small code for common + /// situations. For this reason, the concat() method is inlined so that + /// concatenations of leaf nodes can be optimized into stores directly into a + /// single stack allocated object. + /// + /// In practice, not all compilers can be trusted to optimize concat() fully, + /// so we provide two additional methods (and accompanying operator+ + /// overloads) to guarantee that particularly important cases (cstring plus + /// StringRef) codegen as desired. + class Twine { + /// NodeKind - Represent the type of an argument. + enum NodeKind { + /// An empty string; the result of concatenating anything with it is also + /// empty. + NullKind, + + /// The empty string. + EmptyKind, + + /// A pointer to a Twine instance. + TwineKind, + + /// A pointer to a C string instance. + CStringKind, + + /// A pointer to an std::string instance. + StdStringKind, + + /// A pointer to a StringRef instance. + StringRefKind, + + /// A pointer to an unsigned int value, to render as an unsigned decimal + /// integer. + DecUIKind, + + /// A pointer to an int value, to render as a signed decimal integer. + DecIKind, + + /// A pointer to an unsigned long value, to render as an unsigned decimal + /// integer. + DecULKind, + + /// A pointer to a long value, to render as a signed decimal integer. + DecLKind, + + /// A pointer to an unsigned long long value, to render as an unsigned + /// decimal integer. + DecULLKind, + + /// A pointer to a long long value, to render as a signed decimal integer. + DecLLKind, + + /// A pointer to a uint64_t value, to render as an unsigned hexadecimal + /// integer. + UHexKind + }; + + private: + /// LHS - The prefix in the concatenation, which may be uninitialized for + /// Null or Empty kinds. + const void *LHS; + /// RHS - The suffix in the concatenation, which may be uninitialized for + /// Null or Empty kinds. + const void *RHS; + /// LHSKind - The NodeKind of the left hand side, \see getLHSKind(). + unsigned char LHSKind; + /// RHSKind - The NodeKind of the left hand side, \see getLHSKind(). + unsigned char RHSKind; + + private: + /// Construct a nullary twine; the kind must be NullKind or EmptyKind. + explicit Twine(NodeKind Kind) + : LHSKind(Kind), RHSKind(EmptyKind) { + assert(isNullary() && "Invalid kind!"); + } + + /// Construct a binary twine. + explicit Twine(const Twine &_LHS, const Twine &_RHS) + : LHS(&_LHS), RHS(&_RHS), LHSKind(TwineKind), RHSKind(TwineKind) { + assert(isValid() && "Invalid twine!"); + } + + /// Construct a twine from explicit values. + explicit Twine(const void *_LHS, NodeKind _LHSKind, + const void *_RHS, NodeKind _RHSKind) + : LHS(_LHS), RHS(_RHS), LHSKind(_LHSKind), RHSKind(_RHSKind) { + assert(isValid() && "Invalid twine!"); + } + + /// isNull - Check for the null twine. + bool isNull() const { + return getLHSKind() == NullKind; + } + + /// isEmpty - Check for the empty twine. + bool isEmpty() const { + return getLHSKind() == EmptyKind; + } + + /// isNullary - Check if this is a nullary twine (null or empty). + bool isNullary() const { + return isNull() || isEmpty(); + } + + /// isUnary - Check if this is a unary twine. + bool isUnary() const { + return getRHSKind() == EmptyKind && !isNullary(); + } + + /// isBinary - Check if this is a binary twine. + bool isBinary() const { + return getLHSKind() != NullKind && getRHSKind() != EmptyKind; + } + + /// isValid - Check if this is a valid twine (satisfying the invariants on + /// order and number of arguments). + bool isValid() const { + // Nullary twines always have Empty on the RHS. + if (isNullary() && getRHSKind() != EmptyKind) + return false; + + // Null should never appear on the RHS. + if (getRHSKind() == NullKind) + return false; + + // The RHS cannot be non-empty if the LHS is empty. + if (getRHSKind() != EmptyKind && getLHSKind() == EmptyKind) + return false; + + // A twine child should always be binary. + if (getLHSKind() == TwineKind && + !static_cast(LHS)->isBinary()) + return false; + if (getRHSKind() == TwineKind && + !static_cast(RHS)->isBinary()) + return false; + + return true; + } + + /// getLHSKind - Get the NodeKind of the left-hand side. + NodeKind getLHSKind() const { return (NodeKind) LHSKind; } + + /// getRHSKind - Get the NodeKind of the left-hand side. + NodeKind getRHSKind() const { return (NodeKind) RHSKind; } + + /// printOneChild - Print one child from a twine. + void printOneChild(raw_ostream &OS, const void *Ptr, NodeKind Kind) const; + + /// printOneChildRepr - Print the representation of one child from a twine. + void printOneChildRepr(raw_ostream &OS, const void *Ptr, + NodeKind Kind) const; + + public: + /// @name Constructors + /// @{ + + /// Construct from an empty string. + /*implicit*/ Twine() : LHSKind(EmptyKind), RHSKind(EmptyKind) { + assert(isValid() && "Invalid twine!"); + } + + /// Construct from a C string. + /// + /// We take care here to optimize "" into the empty twine -- this will be + /// optimized out for string constants. This allows Twine arguments have + /// default "" values, without introducing unnecessary string constants. + /*implicit*/ Twine(const char *Str) + : RHSKind(EmptyKind) { + if (Str[0] != '\0') { + LHS = Str; + LHSKind = CStringKind; + } else + LHSKind = EmptyKind; + + assert(isValid() && "Invalid twine!"); + } + + /// Construct from an std::string. + /*implicit*/ Twine(const std::string &Str) + : LHS(&Str), LHSKind(StdStringKind), RHSKind(EmptyKind) { + assert(isValid() && "Invalid twine!"); + } + + /// Construct from a StringRef. + /*implicit*/ Twine(const StringRef &Str) + : LHS(&Str), LHSKind(StringRefKind), RHSKind(EmptyKind) { + assert(isValid() && "Invalid twine!"); + } + + /// Construct a twine to print \arg Val as an unsigned decimal integer. + explicit Twine(const unsigned int &Val) + : LHS(&Val), LHSKind(DecUIKind), RHSKind(EmptyKind) { + } + + /// Construct a twine to print \arg Val as a signed decimal integer. + explicit Twine(const int &Val) + : LHS(&Val), LHSKind(DecIKind), RHSKind(EmptyKind) { + } + + /// Construct a twine to print \arg Val as an unsigned decimal integer. + explicit Twine(const unsigned long &Val) + : LHS(&Val), LHSKind(DecULKind), RHSKind(EmptyKind) { + } + + /// Construct a twine to print \arg Val as a signed decimal integer. + explicit Twine(const long &Val) + : LHS(&Val), LHSKind(DecLKind), RHSKind(EmptyKind) { + } + + /// Construct a twine to print \arg Val as an unsigned decimal integer. + explicit Twine(const unsigned long long &Val) + : LHS(&Val), LHSKind(DecULLKind), RHSKind(EmptyKind) { + } + + /// Construct a twine to print \arg Val as a signed decimal integer. + explicit Twine(const long long &Val) + : LHS(&Val), LHSKind(DecLLKind), RHSKind(EmptyKind) { + } + + // FIXME: Unfortunately, to make sure this is as efficient as possible we + // need extra binary constructors from particular types. We can't rely on + // the compiler to be smart enough to fold operator+()/concat() down to the + // right thing. Yet. + + /// Construct as the concatenation of a C string and a StringRef. + /*implicit*/ Twine(const char *_LHS, const StringRef &_RHS) + : LHS(_LHS), RHS(&_RHS), LHSKind(CStringKind), RHSKind(StringRefKind) { + assert(isValid() && "Invalid twine!"); + } + + /// Construct as the concatenation of a StringRef and a C string. + /*implicit*/ Twine(const StringRef &_LHS, const char *_RHS) + : LHS(&_LHS), RHS(_RHS), LHSKind(StringRefKind), RHSKind(CStringKind) { + assert(isValid() && "Invalid twine!"); + } + + /// Create a 'null' string, which is an empty string that always + /// concatenates to form another empty string. + static Twine createNull() { + return Twine(NullKind); + } + + /// @} + /// @name Numeric Conversions + /// @{ + + // Construct a twine to print \arg Val as an unsigned hexadecimal integer. + static Twine utohexstr(const uint64_t &Val) { + return Twine(&Val, UHexKind, 0, EmptyKind); + } + + /// @} + /// @name Predicate Operations + /// @{ + + /// isTriviallyEmpty - Check if this twine is trivially empty; a false + /// return value does not necessarily mean the twine is empty. + bool isTriviallyEmpty() const { + return isNullary(); + } + + /// @} + /// @name String Operations + /// @{ + + Twine concat(const Twine &Suffix) const; + + /// @} + /// @name Output & Conversion. + /// @{ + + /// str - Return the twine contents as a std::string. + std::string str() const; + + /// toVector - Write the concatenated string into the given SmallString or + /// SmallVector. + void toVector(SmallVectorImpl &Out) const; + + /// print - Write the concatenated string represented by this twine to the + /// stream \arg OS. + void print(raw_ostream &OS) const; + + /// dump - Dump the concatenated string represented by this twine to stderr. + void dump() const; + + /// print - Write the representation of this twine to the stream \arg OS. + void printRepr(raw_ostream &OS) const; + + /// dumpRepr - Dump the representation of this twine to stderr. + void dumpRepr() const; + + /// @} + }; + + /// @name Twine Inline Implementations + /// @{ + + inline Twine Twine::concat(const Twine &Suffix) const { + // Concatenation with null is null. + if (isNull() || Suffix.isNull()) + return Twine(NullKind); + + // Concatenation with empty yields the other side. + if (isEmpty()) + return Suffix; + if (Suffix.isEmpty()) + return *this; + + // Otherwise we need to create a new node, taking care to fold in unary + // twines. + const void *NewLHS = this, *NewRHS = &Suffix; + NodeKind NewLHSKind = TwineKind, NewRHSKind = TwineKind; + if (isUnary()) { + NewLHS = LHS; + NewLHSKind = getLHSKind(); + } + if (Suffix.isUnary()) { + NewRHS = Suffix.LHS; + NewRHSKind = Suffix.getLHSKind(); + } + + return Twine(NewLHS, NewLHSKind, NewRHS, NewRHSKind); + } + + inline Twine operator+(const Twine &LHS, const Twine &RHS) { + return LHS.concat(RHS); + } + + /// Additional overload to guarantee simplified codegen; this is equivalent to + /// concat(). + + inline Twine operator+(const char *LHS, const StringRef &RHS) { + return Twine(LHS, RHS); + } + + /// Additional overload to guarantee simplified codegen; this is equivalent to + /// concat(). + + inline Twine operator+(const StringRef &LHS, const char *RHS) { + return Twine(LHS, RHS); + } + + inline raw_ostream &operator<<(raw_ostream &OS, const Twine &RHS) { + RHS.print(OS); + return OS; + } + + /// @} +} + +#endif diff --git a/libclamav/c++/llvm/include/llvm/ADT/UniqueVector.h b/libclamav/c++/llvm/include/llvm/ADT/UniqueVector.h new file mode 100644 index 000000000..2d02d1ce1 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/ADT/UniqueVector.h @@ -0,0 +1,89 @@ +//===-- llvm/ADT/UniqueVector.h ---------------------------------*- 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_UNIQUEVECTOR_H +#define LLVM_ADT_UNIQUEVECTOR_H + +#include +#include +#include + +namespace llvm { + +//===----------------------------------------------------------------------===// +/// UniqueVector - This class produces a sequential ID number (base 1) for each +/// unique entry that is added. T is the type of entries in the vector. This +/// class should have an implementation of operator== and of operator<. +/// Entries can be fetched using operator[] with the entry ID. +template class UniqueVector { +private: + // Map - Used to handle the correspondence of entry to ID. + std::map Map; + + // Vector - ID ordered vector of entries. Entries can be indexed by ID - 1. + // + std::vector Vector; + +public: + /// insert - Append entry to the vector if it doesn't already exist. Returns + /// the entry's index + 1 to be used as a unique ID. + unsigned insert(const T &Entry) { + // Check if the entry is already in the map. + unsigned &Val = Map[Entry]; + + // See if entry exists, if so return prior ID. + if (Val) return Val; + + // Compute ID for entry. + Val = static_cast(Vector.size()) + 1; + + // Insert in vector. + Vector.push_back(Entry); + return Val; + } + + /// idFor - return the ID for an existing entry. Returns 0 if the entry is + /// not found. + unsigned idFor(const T &Entry) const { + // Search for entry in the map. + typename std::map::const_iterator MI = Map.find(Entry); + + // See if entry exists, if so return ID. + if (MI != Map.end()) return MI->second; + + // No luck. + return 0; + } + + /// operator[] - Returns a reference to the entry with the specified ID. + /// + const T &operator[](unsigned ID) const { + assert(ID-1 < size() && "ID is 0 or out of range!"); + return Vector[ID - 1]; + } + + /// size - Returns the number of entries in the vector. + /// + size_t size() const { return Vector.size(); } + + /// empty - Returns true if the vector is empty. + /// + bool empty() const { return Vector.empty(); } + + /// reset - Clears all the entries. + /// + void reset() { + Map.clear(); + Vector.resize(0, 0); + } +}; + +} // End of namespace llvm + +#endif // LLVM_ADT_UNIQUEVECTOR_H diff --git a/libclamav/c++/llvm/include/llvm/ADT/ValueMap.h b/libclamav/c++/llvm/include/llvm/ADT/ValueMap.h new file mode 100644 index 000000000..b043c389f --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/ADT/ValueMap.h @@ -0,0 +1,375 @@ +//===- llvm/ADT/ValueMap.h - Safe map from Values to data -------*- 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 the ValueMap class. ValueMap maps Value* or any subclass +// to an arbitrary other type. It provides the DenseMap interface but updates +// itself to remain safe when keys are RAUWed or deleted. By default, when a +// key is RAUWed from V1 to V2, the old mapping V1->target is removed, and a new +// mapping V2->target is added. If V2 already existed, its old target is +// overwritten. When a key is deleted, its mapping is removed. +// +// You can override a ValueMap's Config parameter to control exactly what +// happens on RAUW and destruction and to get called back on each event. It's +// legal to call back into the ValueMap from a Config's callbacks. Config +// parameters should inherit from ValueMapConfig to get default +// implementations of all the methods ValueMap uses. See ValueMapConfig for +// documentation of the functions you can override. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_VALUEMAP_H +#define LLVM_ADT_VALUEMAP_H + +#include "llvm/ADT/DenseMap.h" +#include "llvm/Support/ValueHandle.h" +#include "llvm/Support/type_traits.h" +#include "llvm/System/Mutex.h" + +#include + +namespace llvm { + +template +class ValueMapCallbackVH; + +template +class ValueMapIterator; +template +class ValueMapConstIterator; + +/// This class defines the default behavior for configurable aspects of +/// ValueMap<>. User Configs should inherit from this class to be as compatible +/// as possible with future versions of ValueMap. +template +struct ValueMapConfig { + /// If FollowRAUW is true, the ValueMap will update mappings on RAUW. If it's + /// false, the ValueMap will leave the original mapping in place. + enum { FollowRAUW = true }; + + // All methods will be called with a first argument of type ExtraData. The + // default implementations in this class take a templated first argument so + // that users' subclasses can use any type they want without having to + // override all the defaults. + struct ExtraData {}; + + template + static void onRAUW(const ExtraDataT &Data, KeyT Old, KeyT New) {} + template + static void onDelete(const ExtraDataT &Data, KeyT Old) {} + + /// Returns a mutex that should be acquired around any changes to the map. + /// This is only acquired from the CallbackVH (and held around calls to onRAUW + /// and onDelete) and not inside other ValueMap methods. NULL means that no + /// mutex is necessary. + template + static sys::Mutex *getMutex(const ExtraDataT &Data) { return NULL; } +}; + +/// See the file comment. +template, + typename ValueInfoT = DenseMapInfo > +class ValueMap { + friend class ValueMapCallbackVH; + typedef ValueMapCallbackVH ValueMapCVH; + typedef DenseMap, + ValueInfoT> MapT; + typedef typename Config::ExtraData ExtraData; + MapT Map; + ExtraData Data; +public: + typedef KeyT key_type; + typedef ValueT mapped_type; + typedef std::pair value_type; + + ValueMap(const ValueMap& Other) : Map(Other.Map), Data(Other.Data) {} + + explicit ValueMap(unsigned NumInitBuckets = 64) + : Map(NumInitBuckets), Data() {} + explicit ValueMap(const ExtraData &Data, unsigned NumInitBuckets = 64) + : Map(NumInitBuckets), Data(Data) {} + + ~ValueMap() {} + + typedef ValueMapIterator iterator; + typedef ValueMapConstIterator const_iterator; + inline iterator begin() { return iterator(Map.begin()); } + inline iterator end() { return iterator(Map.end()); } + inline const_iterator begin() const { return const_iterator(Map.begin()); } + inline const_iterator end() const { return const_iterator(Map.end()); } + + bool empty() const { return Map.empty(); } + unsigned size() const { return Map.size(); } + + /// Grow the map so that it has at least Size buckets. Does not shrink + void resize(size_t Size) { Map.resize(Size); } + + void clear() { Map.clear(); } + + /// count - Return true if the specified key is in the map. + bool count(const KeyT &Val) const { + return Map.count(Wrap(Val)); + } + + iterator find(const KeyT &Val) { + return iterator(Map.find(Wrap(Val))); + } + const_iterator find(const KeyT &Val) const { + return const_iterator(Map.find(Wrap(Val))); + } + + /// lookup - Return the entry for the specified key, or a default + /// constructed value if no such entry exists. + ValueT lookup(const KeyT &Val) const { + return Map.lookup(Wrap(Val)); + } + + // Inserts key,value pair into the map if the key isn't already in the map. + // If the key is already in the map, it returns false and doesn't update the + // value. + std::pair insert(const std::pair &KV) { + std::pair map_result= + Map.insert(std::make_pair(Wrap(KV.first), KV.second)); + return std::make_pair(iterator(map_result.first), map_result.second); + } + + /// insert - Range insertion of pairs. + template + void insert(InputIt I, InputIt E) { + for (; I != E; ++I) + insert(*I); + } + + + bool erase(const KeyT &Val) { + return Map.erase(Wrap(Val)); + } + bool erase(iterator I) { + return Map.erase(I.base()); + } + + value_type& FindAndConstruct(const KeyT &Key) { + return Map.FindAndConstruct(Wrap(Key)); + } + + ValueT &operator[](const KeyT &Key) { + return Map[Wrap(Key)]; + } + + ValueMap& operator=(const ValueMap& Other) { + Map = Other.Map; + Data = Other.Data; + return *this; + } + + /// isPointerIntoBucketsArray - Return true if the specified pointer points + /// somewhere into the ValueMap's array of buckets (i.e. either to a key or + /// value in the ValueMap). + bool isPointerIntoBucketsArray(const void *Ptr) const { + return Map.isPointerIntoBucketsArray(Ptr); + } + + /// getPointerIntoBucketsArray() - Return an opaque pointer into the buckets + /// array. In conjunction with the previous method, this can be used to + /// determine whether an insertion caused the ValueMap to reallocate. + const void *getPointerIntoBucketsArray() const { + return Map.getPointerIntoBucketsArray(); + } + +private: + // Takes a key being looked up in the map and wraps it into a + // ValueMapCallbackVH, the actual key type of the map. We use a helper + // function because ValueMapCVH is constructed with a second parameter. + ValueMapCVH Wrap(KeyT key) const { + // The only way the resulting CallbackVH could try to modify *this (making + // the const_cast incorrect) is if it gets inserted into the map. But then + // this function must have been called from a non-const method, making the + // const_cast ok. + return ValueMapCVH(key, const_cast(this)); + } +}; + +// This CallbackVH updates its ValueMap when the contained Value changes, +// according to the user's preferences expressed through the Config object. +template +class ValueMapCallbackVH : public CallbackVH { + friend class ValueMap; + friend struct DenseMapInfo; + typedef ValueMap ValueMapT; + typedef typename llvm::remove_pointer::type KeySansPointerT; + + ValueMapT *Map; + + ValueMapCallbackVH(KeyT Key, ValueMapT *Map) + : CallbackVH(const_cast(static_cast(Key))), + Map(Map) {} + +public: + KeyT Unwrap() const { return cast_or_null(getValPtr()); } + + virtual void deleted() { + // Make a copy that won't get changed even when *this is destroyed. + ValueMapCallbackVH Copy(*this); + sys::Mutex *M = Config::getMutex(Copy.Map->Data); + if (M) + M->acquire(); + Config::onDelete(Copy.Map->Data, Copy.Unwrap()); // May destroy *this. + Copy.Map->Map.erase(Copy); // Definitely destroys *this. + if (M) + M->release(); + } + virtual void allUsesReplacedWith(Value *new_key) { + assert(isa(new_key) && + "Invalid RAUW on key of ValueMap<>"); + // Make a copy that won't get changed even when *this is destroyed. + ValueMapCallbackVH Copy(*this); + sys::Mutex *M = Config::getMutex(Copy.Map->Data); + if (M) + M->acquire(); + + KeyT typed_new_key = cast(new_key); + // Can destroy *this: + Config::onRAUW(Copy.Map->Data, Copy.Unwrap(), typed_new_key); + if (Config::FollowRAUW) { + typename ValueMapT::MapT::iterator I = Copy.Map->Map.find(Copy); + // I could == Copy.Map->Map.end() if the onRAUW callback already + // removed the old mapping. + if (I != Copy.Map->Map.end()) { + ValueT Target(I->second); + Copy.Map->Map.erase(I); // Definitely destroys *this. + Copy.Map->insert(std::make_pair(typed_new_key, Target)); + } + } + if (M) + M->release(); + } +}; + +template +struct DenseMapInfo > { + typedef ValueMapCallbackVH VH; + typedef DenseMapInfo PointerInfo; + + static inline VH getEmptyKey() { + return VH(PointerInfo::getEmptyKey(), NULL); + } + static inline VH getTombstoneKey() { + return VH(PointerInfo::getTombstoneKey(), NULL); + } + static unsigned getHashValue(const VH &Val) { + return PointerInfo::getHashValue(Val.Unwrap()); + } + static bool isEqual(const VH &LHS, const VH &RHS) { + return LHS == RHS; + } + static bool isPod() { return false; } +}; + + +template +class ValueMapIterator : + public std::iterator, + ptrdiff_t> { + typedef typename DenseMapT::iterator BaseT; + typedef typename DenseMapT::mapped_type ValueT; + BaseT I; +public: + ValueMapIterator() : I() {} + + ValueMapIterator(BaseT I) : I(I) {} + + BaseT base() const { return I; } + + struct ValueTypeProxy { + const KeyT first; + ValueT& second; + ValueTypeProxy *operator->() { return this; } + operator std::pair() const { + return std::make_pair(first, second); + } + }; + + ValueTypeProxy operator*() const { + ValueTypeProxy Result = {I->first.Unwrap(), I->second}; + return Result; + } + + ValueTypeProxy operator->() const { + return operator*(); + } + + bool operator==(const ValueMapIterator &RHS) const { + return I == RHS.I; + } + bool operator!=(const ValueMapIterator &RHS) const { + return I != RHS.I; + } + + inline ValueMapIterator& operator++() { // Preincrement + ++I; + return *this; + } + ValueMapIterator operator++(int) { // Postincrement + ValueMapIterator tmp = *this; ++*this; return tmp; + } +}; + +template +class ValueMapConstIterator : + public std::iterator, + ptrdiff_t> { + typedef typename DenseMapT::const_iterator BaseT; + typedef typename DenseMapT::mapped_type ValueT; + BaseT I; +public: + ValueMapConstIterator() : I() {} + ValueMapConstIterator(BaseT I) : I(I) {} + ValueMapConstIterator(ValueMapIterator Other) + : I(Other.base()) {} + + BaseT base() const { return I; } + + struct ValueTypeProxy { + const KeyT first; + const ValueT& second; + ValueTypeProxy *operator->() { return this; } + operator std::pair() const { + return std::make_pair(first, second); + } + }; + + ValueTypeProxy operator*() const { + ValueTypeProxy Result = {I->first.Unwrap(), I->second}; + return Result; + } + + ValueTypeProxy operator->() const { + return operator*(); + } + + bool operator==(const ValueMapConstIterator &RHS) const { + return I == RHS.I; + } + bool operator!=(const ValueMapConstIterator &RHS) const { + return I != RHS.I; + } + + inline ValueMapConstIterator& operator++() { // Preincrement + ++I; + return *this; + } + ValueMapConstIterator operator++(int) { // Postincrement + ValueMapConstIterator tmp = *this; ++*this; return tmp; + } +}; + +} // end namespace llvm + +#endif diff --git a/libclamav/c++/llvm/include/llvm/ADT/VectorExtras.h b/libclamav/c++/llvm/include/llvm/ADT/VectorExtras.h new file mode 100644 index 000000000..e05f58599 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/ADT/VectorExtras.h @@ -0,0 +1,41 @@ +//===-- llvm/ADT/VectorExtras.h - Helpers for std::vector -------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains helper functions which are useful for working with the +// std::vector class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_VECTOREXTRAS_H +#define LLVM_ADT_VECTOREXTRAS_H + +#include +#include + +namespace llvm { + +/// make_vector - Helper function which is useful for building temporary vectors +/// to pass into type construction of CallInst ctors. This turns a null +/// terminated list of pointers (or other value types) into a real live vector. +/// +template +inline std::vector make_vector(T A, ...) { + va_list Args; + va_start(Args, A); + std::vector Result; + Result.push_back(A); + while (T Val = va_arg(Args, T)) + Result.push_back(Val); + va_end(Args); + return Result; +} + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/ADT/ilist.h b/libclamav/c++/llvm/include/llvm/ADT/ilist.h new file mode 100644 index 000000000..b3824a217 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/ADT/ilist.h @@ -0,0 +1,707 @@ +//==-- llvm/ADT/ilist.h - Intrusive Linked List Template ---------*- 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 classes to implement an intrusive doubly linked list class +// (i.e. each node of the list must contain a next and previous field for the +// list. +// +// The ilist_traits trait class is used to gain access to the next and previous +// fields of the node type that the list is instantiated with. If it is not +// specialized, the list defaults to using the getPrev(), getNext() method calls +// to get the next and previous pointers. +// +// The ilist class itself, should be a plug in replacement for list, assuming +// that the nodes contain next/prev pointers. This list replacement does not +// provide a constant time size() method, so be careful to use empty() when you +// really want to know if it's empty. +// +// The ilist class is implemented by allocating a 'tail' node when the list is +// created (using ilist_traits<>::createSentinel()). This tail node is +// absolutely required because the user must be able to compute end()-1. Because +// of this, users of the direct next/prev links will see an extra link on the +// end of the list, which should be ignored. +// +// Requirements for a user of this list: +// +// 1. The user must provide {g|s}et{Next|Prev} methods, or specialize +// ilist_traits to provide an alternate way of getting and setting next and +// prev links. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_ILIST_H +#define LLVM_ADT_ILIST_H + +#include +#include + +namespace llvm { + +template class iplist; +template class ilist_iterator; + +/// ilist_nextprev_traits - A fragment for template traits for intrusive list +/// that provides default next/prev implementations for common operations. +/// +template +struct ilist_nextprev_traits { + static NodeTy *getPrev(NodeTy *N) { return N->getPrev(); } + static NodeTy *getNext(NodeTy *N) { return N->getNext(); } + static const NodeTy *getPrev(const NodeTy *N) { return N->getPrev(); } + static const NodeTy *getNext(const NodeTy *N) { return N->getNext(); } + + static void setPrev(NodeTy *N, NodeTy *Prev) { N->setPrev(Prev); } + static void setNext(NodeTy *N, NodeTy *Next) { N->setNext(Next); } +}; + +template +struct ilist_traits; + +/// ilist_sentinel_traits - A fragment for template traits for intrusive list +/// that provides default sentinel implementations for common operations. +/// +/// ilist_sentinel_traits implements a lazy dynamic sentinel allocation +/// strategy. The sentinel is stored in the prev field of ilist's Head. +/// +template +struct ilist_sentinel_traits { + /// createSentinel - create the dynamic sentinel + static NodeTy *createSentinel() { return new NodeTy(); } + + /// destroySentinel - deallocate the dynamic sentinel + static void destroySentinel(NodeTy *N) { delete N; } + + /// provideInitialHead - when constructing an ilist, provide a starting + /// value for its Head + /// @return null node to indicate that it needs to be allocated later + static NodeTy *provideInitialHead() { return 0; } + + /// ensureHead - make sure that Head is either already + /// initialized or assigned a fresh sentinel + /// @return the sentinel + static NodeTy *ensureHead(NodeTy *&Head) { + if (!Head) { + Head = ilist_traits::createSentinel(); + ilist_traits::noteHead(Head, Head); + ilist_traits::setNext(Head, 0); + return Head; + } + return ilist_traits::getPrev(Head); + } + + /// noteHead - stash the sentinel into its default location + static void noteHead(NodeTy *NewHead, NodeTy *Sentinel) { + ilist_traits::setPrev(NewHead, Sentinel); + } +}; + +/// ilist_node_traits - A fragment for template traits for intrusive list +/// that provides default node related operations. +/// +template +struct ilist_node_traits { + static NodeTy *createNode(const NodeTy &V) { return new NodeTy(V); } + static void deleteNode(NodeTy *V) { delete V; } + + void addNodeToList(NodeTy *) {} + void removeNodeFromList(NodeTy *) {} + void transferNodesFromList(ilist_node_traits & /*SrcTraits*/, + ilist_iterator /*first*/, + ilist_iterator /*last*/) {} +}; + +/// ilist_default_traits - Default template traits for intrusive list. +/// By inheriting from this, you can easily use default implementations +/// for all common operations. +/// +template +struct ilist_default_traits : public ilist_nextprev_traits, + public ilist_sentinel_traits, + public ilist_node_traits { +}; + +// Template traits for intrusive list. By specializing this template class, you +// can change what next/prev fields are used to store the links... +template +struct ilist_traits : public ilist_default_traits {}; + +// Const traits are the same as nonconst traits... +template +struct ilist_traits : public ilist_traits {}; + +//===----------------------------------------------------------------------===// +// ilist_iterator - Iterator for intrusive list. +// +template +class ilist_iterator + : public std::iterator { + +public: + typedef ilist_traits Traits; + typedef std::iterator super; + + typedef typename super::value_type value_type; + typedef typename super::difference_type difference_type; + typedef typename super::pointer pointer; + typedef typename super::reference reference; +private: + pointer NodePtr; + + // ilist_iterator is not a random-access iterator, but it has an + // implicit conversion to pointer-type, which is. Declare (but + // don't define) these functions as private to help catch + // accidental misuse. + void operator[](difference_type) const; + void operator+(difference_type) const; + void operator-(difference_type) const; + void operator+=(difference_type) const; + void operator-=(difference_type) const; + template void operator<(T) const; + template void operator<=(T) const; + template void operator>(T) const; + template void operator>=(T) const; + template void operator-(T) const; +public: + + ilist_iterator(pointer NP) : NodePtr(NP) {} + ilist_iterator(reference NR) : NodePtr(&NR) {} + ilist_iterator() : NodePtr(0) {} + + // This is templated so that we can allow constructing a const iterator from + // a nonconst iterator... + template + ilist_iterator(const ilist_iterator &RHS) + : NodePtr(RHS.getNodePtrUnchecked()) {} + + // This is templated so that we can allow assigning to a const iterator from + // a nonconst iterator... + template + const ilist_iterator &operator=(const ilist_iterator &RHS) { + NodePtr = RHS.getNodePtrUnchecked(); + return *this; + } + + // Accessors... + operator pointer() const { + return NodePtr; + } + + reference operator*() const { + return *NodePtr; + } + pointer operator->() const { return &operator*(); } + + // Comparison operators + bool operator==(const ilist_iterator &RHS) const { + return NodePtr == RHS.NodePtr; + } + bool operator!=(const ilist_iterator &RHS) const { + return NodePtr != RHS.NodePtr; + } + + // Increment and decrement operators... + ilist_iterator &operator--() { // predecrement - Back up + NodePtr = Traits::getPrev(NodePtr); + assert(NodePtr && "--'d off the beginning of an ilist!"); + return *this; + } + ilist_iterator &operator++() { // preincrement - Advance + NodePtr = Traits::getNext(NodePtr); + return *this; + } + ilist_iterator operator--(int) { // postdecrement operators... + ilist_iterator tmp = *this; + --*this; + return tmp; + } + ilist_iterator operator++(int) { // postincrement operators... + ilist_iterator tmp = *this; + ++*this; + return tmp; + } + + // Internal interface, do not use... + pointer getNodePtrUnchecked() const { return NodePtr; } +}; + +// do not implement. this is to catch errors when people try to use +// them as random access iterators +template +void operator-(int, ilist_iterator); +template +void operator-(ilist_iterator,int); + +template +void operator+(int, ilist_iterator); +template +void operator+(ilist_iterator,int); + +// operator!=/operator== - Allow mixed comparisons without dereferencing +// the iterator, which could very likely be pointing to end(). +template +bool operator!=(const T* LHS, const ilist_iterator &RHS) { + return LHS != RHS.getNodePtrUnchecked(); +} +template +bool operator==(const T* LHS, const ilist_iterator &RHS) { + return LHS == RHS.getNodePtrUnchecked(); +} +template +bool operator!=(T* LHS, const ilist_iterator &RHS) { + return LHS != RHS.getNodePtrUnchecked(); +} +template +bool operator==(T* LHS, const ilist_iterator &RHS) { + return LHS == RHS.getNodePtrUnchecked(); +} + + +// Allow ilist_iterators to convert into pointers to a node automatically when +// used by the dyn_cast, cast, isa mechanisms... + +template struct simplify_type; + +template struct simplify_type > { + typedef NodeTy* SimpleType; + + static SimpleType getSimplifiedValue(const ilist_iterator &Node) { + return &*Node; + } +}; +template struct simplify_type > { + typedef NodeTy* SimpleType; + + static SimpleType getSimplifiedValue(const ilist_iterator &Node) { + return &*Node; + } +}; + + +//===----------------------------------------------------------------------===// +// +/// iplist - The subset of list functionality that can safely be used on nodes +/// of polymorphic types, i.e. a heterogenous list with a common base class that +/// holds the next/prev pointers. The only state of the list itself is a single +/// pointer to the head of the list. +/// +/// This list can be in one of three interesting states: +/// 1. The list may be completely unconstructed. In this case, the head +/// pointer is null. When in this form, any query for an iterator (e.g. +/// begin() or end()) causes the list to transparently change to state #2. +/// 2. The list may be empty, but contain a sentinel for the end iterator. This +/// sentinel is created by the Traits::createSentinel method and is a link +/// in the list. When the list is empty, the pointer in the iplist points +/// to the sentinel. Once the sentinel is constructed, it +/// is not destroyed until the list is. +/// 3. The list may contain actual objects in it, which are stored as a doubly +/// linked list of nodes. One invariant of the list is that the predecessor +/// of the first node in the list always points to the last node in the list, +/// and the successor pointer for the sentinel (which always stays at the +/// end of the list) is always null. +/// +template > +class iplist : public Traits { + mutable NodeTy *Head; + + // Use the prev node pointer of 'head' as the tail pointer. This is really a + // circularly linked list where we snip the 'next' link from the sentinel node + // back to the first node in the list (to preserve assertions about going off + // the end of the list). + NodeTy *getTail() { return this->ensureHead(Head); } + const NodeTy *getTail() const { return this->ensureHead(Head); } + void setTail(NodeTy *N) const { this->noteHead(Head, N); } + + /// CreateLazySentinel - This method verifies whether the sentinel for the + /// list has been created and lazily makes it if not. + void CreateLazySentinel() const { + this->ensureHead(Head); + } + + static bool op_less(NodeTy &L, NodeTy &R) { return L < R; } + static bool op_equal(NodeTy &L, NodeTy &R) { return L == R; } + + // No fundamental reason why iplist can't be copyable, but the default + // copy/copy-assign won't do. + iplist(const iplist &); // do not implement + void operator=(const iplist &); // do not implement + +public: + typedef NodeTy *pointer; + typedef const NodeTy *const_pointer; + typedef NodeTy &reference; + typedef const NodeTy &const_reference; + typedef NodeTy value_type; + typedef ilist_iterator iterator; + typedef ilist_iterator const_iterator; + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef std::reverse_iterator const_reverse_iterator; + typedef std::reverse_iterator reverse_iterator; + + iplist() : Head(this->provideInitialHead()) {} + ~iplist() { + if (!Head) return; + clear(); + Traits::destroySentinel(getTail()); + } + + // Iterator creation methods. + iterator begin() { + CreateLazySentinel(); + return iterator(Head); + } + const_iterator begin() const { + CreateLazySentinel(); + return const_iterator(Head); + } + iterator end() { + CreateLazySentinel(); + return iterator(getTail()); + } + const_iterator end() const { + CreateLazySentinel(); + return const_iterator(getTail()); + } + + // reverse iterator creation methods. + reverse_iterator rbegin() { return reverse_iterator(end()); } + const_reverse_iterator rbegin() const{ return const_reverse_iterator(end()); } + reverse_iterator rend() { return reverse_iterator(begin()); } + const_reverse_iterator rend() const { return const_reverse_iterator(begin());} + + + // Miscellaneous inspection routines. + size_type max_size() const { return size_type(-1); } + bool empty() const { return Head == 0 || Head == getTail(); } + + // Front and back accessor functions... + reference front() { + assert(!empty() && "Called front() on empty list!"); + return *Head; + } + const_reference front() const { + assert(!empty() && "Called front() on empty list!"); + return *Head; + } + reference back() { + assert(!empty() && "Called back() on empty list!"); + return *this->getPrev(getTail()); + } + const_reference back() const { + assert(!empty() && "Called back() on empty list!"); + return *this->getPrev(getTail()); + } + + void swap(iplist &RHS) { + assert(0 && "Swap does not use list traits callback correctly yet!"); + std::swap(Head, RHS.Head); + } + + iterator insert(iterator where, NodeTy *New) { + NodeTy *CurNode = where.getNodePtrUnchecked(); + NodeTy *PrevNode = this->getPrev(CurNode); + this->setNext(New, CurNode); + this->setPrev(New, PrevNode); + + if (CurNode != Head) // Is PrevNode off the beginning of the list? + this->setNext(PrevNode, New); + else + Head = New; + this->setPrev(CurNode, New); + + this->addNodeToList(New); // Notify traits that we added a node... + return New; + } + + iterator insertAfter(iterator where, NodeTy *New) { + if (empty()) + return insert(begin(), New); + else + return insert(++where, New); + } + + NodeTy *remove(iterator &IT) { + assert(IT != end() && "Cannot remove end of list!"); + NodeTy *Node = &*IT; + NodeTy *NextNode = this->getNext(Node); + NodeTy *PrevNode = this->getPrev(Node); + + if (Node != Head) // Is PrevNode off the beginning of the list? + this->setNext(PrevNode, NextNode); + else + Head = NextNode; + this->setPrev(NextNode, PrevNode); + IT = NextNode; + this->removeNodeFromList(Node); // Notify traits that we removed a node... + + // Set the next/prev pointers of the current node to null. This isn't + // strictly required, but this catches errors where a node is removed from + // an ilist (and potentially deleted) with iterators still pointing at it. + // When those iterators are incremented or decremented, they will assert on + // the null next/prev pointer instead of "usually working". + this->setNext(Node, 0); + this->setPrev(Node, 0); + return Node; + } + + NodeTy *remove(const iterator &IT) { + iterator MutIt = IT; + return remove(MutIt); + } + + // erase - remove a node from the controlled sequence... and delete it. + iterator erase(iterator where) { + this->deleteNode(remove(where)); + return where; + } + + +private: + // transfer - The heart of the splice function. Move linked list nodes from + // [first, last) into position. + // + void transfer(iterator position, iplist &L2, iterator first, iterator last) { + assert(first != last && "Should be checked by callers"); + + if (position != last) { + // Note: we have to be careful about the case when we move the first node + // in the list. This node is the list sentinel node and we can't move it. + NodeTy *ThisSentinel = getTail(); + setTail(0); + NodeTy *L2Sentinel = L2.getTail(); + L2.setTail(0); + + // Remove [first, last) from its old position. + NodeTy *First = &*first, *Prev = this->getPrev(First); + NodeTy *Next = last.getNodePtrUnchecked(), *Last = this->getPrev(Next); + if (Prev) + this->setNext(Prev, Next); + else + L2.Head = Next; + this->setPrev(Next, Prev); + + // Splice [first, last) into its new position. + NodeTy *PosNext = position.getNodePtrUnchecked(); + NodeTy *PosPrev = this->getPrev(PosNext); + + // Fix head of list... + if (PosPrev) + this->setNext(PosPrev, First); + else + Head = First; + this->setPrev(First, PosPrev); + + // Fix end of list... + this->setNext(Last, PosNext); + this->setPrev(PosNext, Last); + + this->transferNodesFromList(L2, First, PosNext); + + // Now that everything is set, restore the pointers to the list sentinels. + L2.setTail(L2Sentinel); + setTail(ThisSentinel); + } + } + +public: + + //===----------------------------------------------------------------------=== + // Functionality derived from other functions defined above... + // + + size_type size() const { + if (Head == 0) return 0; // Don't require construction of sentinel if empty. + return std::distance(begin(), end()); + } + + iterator erase(iterator first, iterator last) { + while (first != last) + first = erase(first); + return last; + } + + void clear() { if (Head) erase(begin(), end()); } + + // Front and back inserters... + void push_front(NodeTy *val) { insert(begin(), val); } + void push_back(NodeTy *val) { insert(end(), val); } + void pop_front() { + assert(!empty() && "pop_front() on empty list!"); + erase(begin()); + } + void pop_back() { + assert(!empty() && "pop_back() on empty list!"); + iterator t = end(); erase(--t); + } + + // Special forms of insert... + template void insert(iterator where, InIt first, InIt last) { + for (; first != last; ++first) insert(where, *first); + } + + // Splice members - defined in terms of transfer... + void splice(iterator where, iplist &L2) { + if (!L2.empty()) + transfer(where, L2, L2.begin(), L2.end()); + } + void splice(iterator where, iplist &L2, iterator first) { + iterator last = first; ++last; + if (where == first || where == last) return; // No change + transfer(where, L2, first, last); + } + void splice(iterator where, iplist &L2, iterator first, iterator last) { + if (first != last) transfer(where, L2, first, last); + } + + + + //===----------------------------------------------------------------------=== + // High-Level Functionality that shouldn't really be here, but is part of list + // + + // These two functions are actually called remove/remove_if in list<>, but + // they actually do the job of erase, rename them accordingly. + // + void erase(const NodeTy &val) { + for (iterator I = begin(), E = end(); I != E; ) { + iterator next = I; ++next; + if (*I == val) erase(I); + I = next; + } + } + template void erase_if(Pr1 pred) { + for (iterator I = begin(), E = end(); I != E; ) { + iterator next = I; ++next; + if (pred(*I)) erase(I); + I = next; + } + } + + template void unique(Pr2 pred) { + if (empty()) return; + for (iterator I = begin(), E = end(), Next = begin(); ++Next != E;) { + if (pred(*I)) + erase(Next); + else + I = Next; + Next = I; + } + } + void unique() { unique(op_equal); } + + template void merge(iplist &right, Pr3 pred) { + iterator first1 = begin(), last1 = end(); + iterator first2 = right.begin(), last2 = right.end(); + while (first1 != last1 && first2 != last2) + if (pred(*first2, *first1)) { + iterator next = first2; + transfer(first1, right, first2, ++next); + first2 = next; + } else { + ++first1; + } + if (first2 != last2) transfer(last1, right, first2, last2); + } + void merge(iplist &right) { return merge(right, op_less); } + + template void sort(Pr3 pred); + void sort() { sort(op_less); } + void reverse(); +}; + + +template +struct ilist : public iplist { + typedef typename iplist::size_type size_type; + typedef typename iplist::iterator iterator; + + ilist() {} + ilist(const ilist &right) { + insert(this->begin(), right.begin(), right.end()); + } + explicit ilist(size_type count) { + insert(this->begin(), count, NodeTy()); + } + ilist(size_type count, const NodeTy &val) { + insert(this->begin(), count, val); + } + template ilist(InIt first, InIt last) { + insert(this->begin(), first, last); + } + + // bring hidden functions into scope + using iplist::insert; + using iplist::push_front; + using iplist::push_back; + + // Main implementation here - Insert for a node passed by value... + iterator insert(iterator where, const NodeTy &val) { + return insert(where, createNode(val)); + } + + + // Front and back inserters... + void push_front(const NodeTy &val) { insert(this->begin(), val); } + void push_back(const NodeTy &val) { insert(this->end(), val); } + + // Special forms of insert... + template void insert(iterator where, InIt first, InIt last) { + for (; first != last; ++first) insert(where, *first); + } + void insert(iterator where, size_type count, const NodeTy &val) { + for (; count != 0; --count) insert(where, val); + } + + // Assign special forms... + void assign(size_type count, const NodeTy &val) { + iterator I = this->begin(); + for (; I != this->end() && count != 0; ++I, --count) + *I = val; + if (count != 0) + insert(this->end(), val, val); + else + erase(I, this->end()); + } + template void assign(InIt first1, InIt last1) { + iterator first2 = this->begin(), last2 = this->end(); + for ( ; first1 != last1 && first2 != last2; ++first1, ++first2) + *first1 = *first2; + if (first2 == last2) + erase(first1, last1); + else + insert(last1, first2, last2); + } + + + // Resize members... + void resize(size_type newsize, NodeTy val) { + iterator i = this->begin(); + size_type len = 0; + for ( ; i != this->end() && len < newsize; ++i, ++len) /* empty*/ ; + + if (len == newsize) + erase(i, this->end()); + else // i == end() + insert(this->end(), newsize - len, val); + } + void resize(size_type newsize) { resize(newsize, NodeTy()); } +}; + +} // End llvm namespace + +namespace std { + // Ensure that swap uses the fast list swap... + template + void swap(llvm::iplist &Left, llvm::iplist &Right) { + Left.swap(Right); + } +} // End 'std' extensions... + +#endif // LLVM_ADT_ILIST_H diff --git a/libclamav/c++/llvm/include/llvm/ADT/ilist_node.h b/libclamav/c++/llvm/include/llvm/ADT/ilist_node.h new file mode 100644 index 000000000..da25f959e --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/ADT/ilist_node.h @@ -0,0 +1,56 @@ +//==-- llvm/ADT/ilist_node.h - Intrusive Linked List Helper ------*- 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 the ilist_node class template, which is a convenient +// base class for creating classes that can be used with ilists. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_ILIST_NODE_H +#define LLVM_ADT_ILIST_NODE_H + +namespace llvm { + +template +struct ilist_traits; + +/// ilist_half_node - Base class that provides prev services for sentinels. +/// +template +class ilist_half_node { + friend struct ilist_traits; + NodeTy *Prev; +protected: + NodeTy *getPrev() { return Prev; } + const NodeTy *getPrev() const { return Prev; } + void setPrev(NodeTy *P) { Prev = P; } + ilist_half_node() : Prev(0) {} +}; + +template +struct ilist_nextprev_traits; + +/// ilist_node - Base class that provides next/prev services for nodes +/// that use ilist_nextprev_traits or ilist_default_traits. +/// +template +class ilist_node : private ilist_half_node { + friend struct ilist_nextprev_traits; + friend struct ilist_traits; + NodeTy *Next; + NodeTy *getNext() { return Next; } + const NodeTy *getNext() const { return Next; } + void setNext(NodeTy *N) { Next = N; } +protected: + ilist_node() : Next(0) {} +}; + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/AbstractTypeUser.h b/libclamav/c++/llvm/include/llvm/AbstractTypeUser.h new file mode 100644 index 000000000..b6cceb401 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/AbstractTypeUser.h @@ -0,0 +1,204 @@ +//===-- llvm/AbstractTypeUser.h - AbstractTypeUser Interface ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the AbstractTypeUser class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ABSTRACT_TYPE_USER_H +#define LLVM_ABSTRACT_TYPE_USER_H + +#if !defined(LLVM_TYPE_H) && !defined(LLVM_VALUE_H) +#error Do not include this file directly. Include Type.h instead. +#error Some versions of GCC (e.g. 3.4 and 4.1) can not handle the inlined method +#error PATypeHolder::dropRef() correctly otherwise. +#endif + +// This is the "master" include for Whether this file needs it or not, +// it must always include for the files which include +// llvm/AbstractTypeUser.h +// +// In this way, most every LLVM source file will have access to the assert() +// macro without having to #include directly. +// +#include + +namespace llvm { + +class Value; +class Type; +class DerivedType; +template struct simplify_type; + +/// The AbstractTypeUser class is an interface to be implemented by classes who +/// could possibly use an abstract type. Abstract types are denoted by the +/// isAbstract flag set to true in the Type class. These are classes that +/// contain an Opaque type in their structure somewhere. +/// +/// Classes must implement this interface so that they may be notified when an +/// abstract type is resolved. Abstract types may be resolved into more +/// concrete types through: linking, parsing, and bitcode reading. When this +/// happens, all of the users of the type must be updated to reference the new, +/// more concrete type. They are notified through the AbstractTypeUser +/// interface. +/// +/// In addition to this, AbstractTypeUsers must keep the use list of the +/// potentially abstract type that they reference up-to-date. To do this in a +/// nice, transparent way, the PATypeHandle class is used to hold "Potentially +/// Abstract Types", and keep the use list of the abstract types up-to-date. +/// @brief LLVM Abstract Type User Representation +class AbstractTypeUser { +protected: + virtual ~AbstractTypeUser(); // Derive from me + + /// setType - It's normally not possible to change a Value's type in place, + /// but an AbstractTypeUser subclass that knows what its doing can be + /// permitted to do so with care. + void setType(Value *V, const Type *NewTy); + +public: + + /// refineAbstractType - The callback method invoked when an abstract type is + /// resolved to another type. An object must override this method to update + /// its internal state to reference NewType instead of OldType. + /// + virtual void refineAbstractType(const DerivedType *OldTy, + const Type *NewTy) = 0; + + /// The other case which AbstractTypeUsers must be aware of is when a type + /// makes the transition from being abstract (where it has clients on its + /// AbstractTypeUsers list) to concrete (where it does not). This method + /// notifies ATU's when this occurs for a type. + /// + virtual void typeBecameConcrete(const DerivedType *AbsTy) = 0; + + // for debugging... + virtual void dump() const = 0; +}; + + +/// PATypeHandle - Handle to a Type subclass. This class is used to keep the +/// use list of abstract types up-to-date. +/// +class PATypeHandle { + const Type *Ty; + AbstractTypeUser * const User; + + // These functions are defined at the bottom of Type.h. See the comment there + // for justification. + void addUser(); + void removeUser(); +public: + // ctor - Add use to type if abstract. Note that Ty must not be null + inline PATypeHandle(const Type *ty, AbstractTypeUser *user) + : Ty(ty), User(user) { + addUser(); + } + + // ctor - Add use to type if abstract. + inline PATypeHandle(const PATypeHandle &T) : Ty(T.Ty), User(T.User) { + addUser(); + } + + // dtor - Remove reference to type... + inline ~PATypeHandle() { removeUser(); } + + // Automatic casting operator so that the handle may be used naturally + inline operator Type *() const { return const_cast(Ty); } + inline Type *get() const { return const_cast(Ty); } + + // operator= - Allow assignment to handle + inline Type *operator=(const Type *ty) { + if (Ty != ty) { // Ensure we don't accidentally drop last ref to Ty + removeUser(); + Ty = ty; + addUser(); + } + return get(); + } + + // operator= - Allow assignment to handle + inline const Type *operator=(const PATypeHandle &T) { + return operator=(T.Ty); + } + + inline bool operator==(const Type *ty) { + return Ty == ty; + } + + // operator-> - Allow user to dereference handle naturally... + inline const Type *operator->() const { return Ty; } +}; + + +/// PATypeHolder - Holder class for a potentially abstract type. This uses +/// efficient union-find techniques to handle dynamic type resolution. Unless +/// you need to do custom processing when types are resolved, you should always +/// use PATypeHolders in preference to PATypeHandles. +/// +class PATypeHolder { + mutable const Type *Ty; + void destroy(); +public: + PATypeHolder(const Type *ty) : Ty(ty) { + addRef(); + } + PATypeHolder(const PATypeHolder &T) : Ty(T.Ty) { + addRef(); + } + + ~PATypeHolder() { if (Ty) dropRef(); } + + operator Type *() const { return get(); } + Type *get() const; + + // operator-> - Allow user to dereference handle naturally... + Type *operator->() const { return get(); } + + // operator= - Allow assignment to handle + Type *operator=(const Type *ty) { + if (Ty != ty) { // Don't accidentally drop last ref to Ty. + dropRef(); + Ty = ty; + addRef(); + } + return get(); + } + Type *operator=(const PATypeHolder &H) { + return operator=(H.Ty); + } + + /// getRawType - This should only be used to implement the vmcore library. + /// + const Type *getRawType() const { return Ty; } + +private: + void addRef(); + void dropRef(); + friend class TypeMapBase; +}; + +// simplify_type - Allow clients to treat uses just like values when using +// casting operators. +template<> struct simplify_type { + typedef const Type* SimpleType; + static SimpleType getSimplifiedValue(const PATypeHolder &Val) { + return static_cast(Val.get()); + } +}; +template<> struct simplify_type { + typedef const Type* SimpleType; + static SimpleType getSimplifiedValue(const PATypeHolder &Val) { + return static_cast(Val.get()); + } +}; + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Analysis/AliasAnalysis.h b/libclamav/c++/llvm/include/llvm/Analysis/AliasAnalysis.h new file mode 100644 index 000000000..2d43bddf7 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Analysis/AliasAnalysis.h @@ -0,0 +1,357 @@ +//===- llvm/Analysis/AliasAnalysis.h - Alias Analysis Interface -*- 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 the generic AliasAnalysis interface, which is used as the +// common interface used by all clients of alias analysis information, and +// implemented by all alias analysis implementations. Mod/Ref information is +// also captured by this interface. +// +// Implementations of this interface must implement the various virtual methods, +// which automatically provides functionality for the entire suite of client +// APIs. +// +// This API represents memory as a (Pointer, Size) pair. The Pointer component +// specifies the base memory address of the region, the Size specifies how large +// of an area is being queried. If Size is 0, two pointers only alias if they +// are exactly equal. If size is greater than zero, but small, the two pointers +// alias if the areas pointed to overlap. If the size is very large (ie, ~0U), +// then the two pointers alias if they may be pointing to components of the same +// memory object. Pointers that point to two completely different objects in +// memory never alias, regardless of the value of the Size component. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_ALIAS_ANALYSIS_H +#define LLVM_ANALYSIS_ALIAS_ANALYSIS_H + +#include "llvm/Support/CallSite.h" +#include "llvm/System/IncludeFile.h" +#include + +namespace llvm { + +class LoadInst; +class StoreInst; +class VAArgInst; +class TargetData; +class Pass; +class AnalysisUsage; + +class AliasAnalysis { +protected: + const TargetData *TD; + AliasAnalysis *AA; // Previous Alias Analysis to chain to. + + /// InitializeAliasAnalysis - Subclasses must call this method to initialize + /// the AliasAnalysis interface before any other methods are called. This is + /// typically called by the run* methods of these subclasses. This may be + /// called multiple times. + /// + void InitializeAliasAnalysis(Pass *P); + + /// getAnalysisUsage - All alias analysis implementations should invoke this + /// directly (using AliasAnalysis::getAnalysisUsage(AU)). + virtual void getAnalysisUsage(AnalysisUsage &AU) const; + +public: + static char ID; // Class identification, replacement for typeinfo + AliasAnalysis() : TD(0), AA(0) {} + virtual ~AliasAnalysis(); // We want to be subclassed + + /// getTargetData - Return a pointer to the current TargetData object, or + /// null if no TargetData object is available. + /// + const TargetData *getTargetData() const { return TD; } + + /// getTypeStoreSize - Return the TargetData store size for the given type, + /// if known, or a conservative value otherwise. + /// + unsigned getTypeStoreSize(const Type *Ty); + + //===--------------------------------------------------------------------===// + /// Alias Queries... + /// + + /// Alias analysis result - Either we know for sure that it does not alias, we + /// know for sure it must alias, or we don't know anything: The two pointers + /// _might_ alias. This enum is designed so you can do things like: + /// if (AA.alias(P1, P2)) { ... } + /// to check to see if two pointers might alias. + /// + enum AliasResult { NoAlias = 0, MayAlias = 1, MustAlias = 2 }; + + /// alias - The main low level interface to the alias analysis implementation. + /// Returns a Result indicating whether the two pointers are aliased to each + /// other. This is the interface that must be implemented by specific alias + /// analysis implementations. + /// + virtual AliasResult alias(const Value *V1, unsigned V1Size, + const Value *V2, unsigned V2Size); + + /// isNoAlias - A trivial helper function to check to see if the specified + /// pointers are no-alias. + bool isNoAlias(const Value *V1, unsigned V1Size, + const Value *V2, unsigned V2Size) { + return alias(V1, V1Size, V2, V2Size) == NoAlias; + } + + /// pointsToConstantMemory - If the specified pointer is known to point into + /// constant global memory, return true. This allows disambiguation of store + /// instructions from constant pointers. + /// + virtual bool pointsToConstantMemory(const Value *P); + + //===--------------------------------------------------------------------===// + /// Simple mod/ref information... + /// + + /// ModRefResult - Represent the result of a mod/ref query. Mod and Ref are + /// bits which may be or'd together. + /// + enum ModRefResult { NoModRef = 0, Ref = 1, Mod = 2, ModRef = 3 }; + + + /// ModRefBehavior - Summary of how a function affects memory in the program. + /// Loads from constant globals are not considered memory accesses for this + /// interface. Also, functions may freely modify stack space local to their + /// invocation without having to report it through these interfaces. + enum ModRefBehavior { + // DoesNotAccessMemory - This function does not perform any non-local loads + // or stores to memory. + // + // This property corresponds to the GCC 'const' attribute. + DoesNotAccessMemory, + + // AccessesArguments - This function accesses function arguments in well + // known (possibly volatile) ways, but does not access any other memory. + // + // Clients may use the Info parameter of getModRefBehavior to get specific + // information about how pointer arguments are used. + AccessesArguments, + + // AccessesArgumentsAndGlobals - This function has accesses function + // arguments and global variables well known (possibly volatile) ways, but + // does not access any other memory. + // + // Clients may use the Info parameter of getModRefBehavior to get specific + // information about how pointer arguments are used. + AccessesArgumentsAndGlobals, + + // OnlyReadsMemory - This function does not perform any non-local stores or + // volatile loads, but may read from any memory location. + // + // This property corresponds to the GCC 'pure' attribute. + OnlyReadsMemory, + + // UnknownModRefBehavior - This indicates that the function could not be + // classified into one of the behaviors above. + UnknownModRefBehavior + }; + + /// PointerAccessInfo - This struct is used to return results for pointers, + /// globals, and the return value of a function. + struct PointerAccessInfo { + /// V - The value this record corresponds to. This may be an Argument for + /// the function, a GlobalVariable, or null, corresponding to the return + /// value for the function. + Value *V; + + /// ModRefInfo - Whether the pointer is loaded or stored to/from. + /// + ModRefResult ModRefInfo; + + /// AccessType - Specific fine-grained access information for the argument. + /// If none of these classifications is general enough, the + /// getModRefBehavior method should not return AccessesArguments*. If a + /// record is not returned for a particular argument, the argument is never + /// dead and never dereferenced. + enum AccessType { + /// ScalarAccess - The pointer is dereferenced. + /// + ScalarAccess, + + /// ArrayAccess - The pointer is indexed through as an array of elements. + /// + ArrayAccess, + + /// ElementAccess ?? P->F only? + + /// CallsThrough - Indirect calls are made through the specified function + /// pointer. + CallsThrough + }; + }; + + /// getModRefBehavior - Return the behavior when calling the given call site. + virtual ModRefBehavior getModRefBehavior(CallSite CS, + std::vector *Info = 0); + + /// getModRefBehavior - Return the behavior when calling the given function. + /// For use when the call site is not known. + virtual ModRefBehavior getModRefBehavior(Function *F, + std::vector *Info = 0); + + /// doesNotAccessMemory - If the specified call is known to never read or + /// write memory, return true. If the call only reads from known-constant + /// memory, it is also legal to return true. Calls that unwind the stack + /// are legal for this predicate. + /// + /// Many optimizations (such as CSE and LICM) can be performed on such calls + /// without worrying about aliasing properties, and many calls have this + /// property (e.g. calls to 'sin' and 'cos'). + /// + /// This property corresponds to the GCC 'const' attribute. + /// + bool doesNotAccessMemory(CallSite CS) { + return getModRefBehavior(CS) == DoesNotAccessMemory; + } + + /// doesNotAccessMemory - If the specified function is known to never read or + /// write memory, return true. For use when the call site is not known. + /// + bool doesNotAccessMemory(Function *F) { + return getModRefBehavior(F) == DoesNotAccessMemory; + } + + /// onlyReadsMemory - If the specified call is known to only read from + /// non-volatile memory (or not access memory at all), return true. Calls + /// that unwind the stack are legal for this predicate. + /// + /// This property allows many common optimizations to be performed in the + /// absence of interfering store instructions, such as CSE of strlen calls. + /// + /// This property corresponds to the GCC 'pure' attribute. + /// + bool onlyReadsMemory(CallSite CS) { + ModRefBehavior MRB = getModRefBehavior(CS); + return MRB == DoesNotAccessMemory || MRB == OnlyReadsMemory; + } + + /// onlyReadsMemory - If the specified function is known to only read from + /// non-volatile memory (or not access memory at all), return true. For use + /// when the call site is not known. + /// + bool onlyReadsMemory(Function *F) { + ModRefBehavior MRB = getModRefBehavior(F); + return MRB == DoesNotAccessMemory || MRB == OnlyReadsMemory; + } + + + /// getModRefInfo - Return information about whether or not an instruction may + /// read or write memory specified by the pointer operand. An instruction + /// that doesn't read or write memory may be trivially LICM'd for example. + + /// getModRefInfo (for call sites) - Return whether information about whether + /// a particular call site modifies or reads the memory specified by the + /// pointer. + /// + virtual ModRefResult getModRefInfo(CallSite CS, Value *P, unsigned Size); + + /// getModRefInfo - Return information about whether two call sites may refer + /// to the same set of memory locations. This function returns NoModRef if + /// the two calls refer to disjoint memory locations, Ref if CS1 reads memory + /// written by CS2, Mod if CS1 writes to memory read or written by CS2, or + /// ModRef if CS1 might read or write memory accessed by CS2. + /// + virtual ModRefResult getModRefInfo(CallSite CS1, CallSite CS2); + +public: + /// Convenience functions... + ModRefResult getModRefInfo(LoadInst *L, Value *P, unsigned Size); + ModRefResult getModRefInfo(StoreInst *S, Value *P, unsigned Size); + ModRefResult getModRefInfo(CallInst *C, Value *P, unsigned Size) { + return getModRefInfo(CallSite(C), P, Size); + } + ModRefResult getModRefInfo(InvokeInst *I, Value *P, unsigned Size) { + return getModRefInfo(CallSite(I), P, Size); + } + ModRefResult getModRefInfo(VAArgInst* I, Value* P, unsigned Size) { + return AliasAnalysis::ModRef; + } + ModRefResult getModRefInfo(Instruction *I, Value *P, unsigned Size) { + switch (I->getOpcode()) { + case Instruction::VAArg: return getModRefInfo((VAArgInst*)I, P, Size); + case Instruction::Load: return getModRefInfo((LoadInst*)I, P, Size); + case Instruction::Store: return getModRefInfo((StoreInst*)I, P, Size); + case Instruction::Call: return getModRefInfo((CallInst*)I, P, Size); + case Instruction::Invoke: return getModRefInfo((InvokeInst*)I, P, Size); + default: return NoModRef; + } + } + + //===--------------------------------------------------------------------===// + /// Higher level methods for querying mod/ref information. + /// + + /// canBasicBlockModify - Return true if it is possible for execution of the + /// specified basic block to modify the value pointed to by Ptr. + /// + bool canBasicBlockModify(const BasicBlock &BB, const Value *P, unsigned Size); + + /// canInstructionRangeModify - Return true if it is possible for the + /// execution of the specified instructions to modify the value pointed to by + /// Ptr. The instructions to consider are all of the instructions in the + /// range of [I1,I2] INCLUSIVE. I1 and I2 must be in the same basic block. + /// + bool canInstructionRangeModify(const Instruction &I1, const Instruction &I2, + const Value *Ptr, unsigned Size); + + //===--------------------------------------------------------------------===// + /// Methods that clients should call when they transform the program to allow + /// alias analyses to update their internal data structures. Note that these + /// methods may be called on any instruction, regardless of whether or not + /// they have pointer-analysis implications. + /// + + /// deleteValue - This method should be called whenever an LLVM Value is + /// deleted from the program, for example when an instruction is found to be + /// redundant and is eliminated. + /// + virtual void deleteValue(Value *V); + + /// copyValue - This method should be used whenever a preexisting value in the + /// program is copied or cloned, introducing a new value. Note that analysis + /// implementations should tolerate clients that use this method to introduce + /// the same value multiple times: if the analysis already knows about a + /// value, it should ignore the request. + /// + virtual void copyValue(Value *From, Value *To); + + /// replaceWithNewValue - This method is the obvious combination of the two + /// above, and it provided as a helper to simplify client code. + /// + void replaceWithNewValue(Value *Old, Value *New) { + copyValue(Old, New); + deleteValue(Old); + } +}; + +/// isNoAliasCall - Return true if this pointer is returned by a noalias +/// function. +bool isNoAliasCall(const Value *V); + +/// isIdentifiedObject - Return true if this pointer refers to a distinct and +/// identifiable object. This returns true for: +/// Global Variables and Functions (but not Global Aliases) +/// Allocas and Mallocs +/// ByVal and NoAlias Arguments +/// NoAlias returns +/// +bool isIdentifiedObject(const Value *V); + +} // End llvm namespace + +// Because of the way .a files work, we must force the BasicAA implementation to +// be pulled in if the AliasAnalysis header is included. Otherwise we run +// the risk of AliasAnalysis being used, but the default implementation not +// being linked into the tool that uses it. +FORCE_DEFINING_FILE_TO_BE_LINKED(AliasAnalysis) +FORCE_DEFINING_FILE_TO_BE_LINKED(BasicAliasAnalysis) + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Analysis/AliasSetTracker.h b/libclamav/c++/llvm/include/llvm/Analysis/AliasSetTracker.h new file mode 100644 index 000000000..42a377e14 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Analysis/AliasSetTracker.h @@ -0,0 +1,408 @@ +//===- llvm/Analysis/AliasSetTracker.h - Build Alias Sets -------*- 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 two classes: AliasSetTracker and AliasSet. These interface +// are used to classify a collection of pointer references into a maximal number +// of disjoint sets. Each AliasSet object constructed by the AliasSetTracker +// object refers to memory disjoint from the other sets. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_ALIASSETTRACKER_H +#define LLVM_ANALYSIS_ALIASSETTRACKER_H + +#include "llvm/Support/CallSite.h" +#include "llvm/Support/ValueHandle.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/ilist.h" +#include "llvm/ADT/ilist_node.h" +#include + +namespace llvm { + +class AliasAnalysis; +class LoadInst; +class StoreInst; +class VAArgInst; +class AliasSetTracker; +class AliasSet; + +class AliasSet : public ilist_node { + friend class AliasSetTracker; + + class PointerRec { + Value *Val; // The pointer this record corresponds to. + PointerRec **PrevInList, *NextInList; + AliasSet *AS; + unsigned Size; + public: + PointerRec(Value *V) + : Val(V), PrevInList(0), NextInList(0), AS(0), Size(0) {} + + Value *getValue() const { return Val; } + + PointerRec *getNext() const { return NextInList; } + bool hasAliasSet() const { return AS != 0; } + + PointerRec** setPrevInList(PointerRec **PIL) { + PrevInList = PIL; + return &NextInList; + } + + void updateSize(unsigned NewSize) { + if (NewSize > Size) Size = NewSize; + } + + unsigned getSize() const { return Size; } + + AliasSet *getAliasSet(AliasSetTracker &AST) { + assert(AS && "No AliasSet yet!"); + if (AS->Forward) { + AliasSet *OldAS = AS; + AS = OldAS->getForwardedTarget(AST); + AS->addRef(); + OldAS->dropRef(AST); + } + return AS; + } + + void setAliasSet(AliasSet *as) { + assert(AS == 0 && "Already have an alias set!"); + AS = as; + } + + void eraseFromList() { + if (NextInList) NextInList->PrevInList = PrevInList; + *PrevInList = NextInList; + if (AS->PtrListEnd == &NextInList) { + AS->PtrListEnd = PrevInList; + assert(*AS->PtrListEnd == 0 && "List not terminated right!"); + } + delete this; + } + }; + + PointerRec *PtrList, **PtrListEnd; // Doubly linked list of nodes. + AliasSet *Forward; // Forwarding pointer. + AliasSet *Next, *Prev; // Doubly linked list of AliasSets. + + std::vector CallSites; // All calls & invokes in this alias set. + + // RefCount - Number of nodes pointing to this AliasSet plus the number of + // AliasSets forwarding to it. + unsigned RefCount : 28; + + /// AccessType - Keep track of whether this alias set merely refers to the + /// locations of memory, whether it modifies the memory, or whether it does + /// both. The lattice goes from "NoModRef" to either Refs or Mods, then to + /// ModRef as necessary. + /// + enum AccessType { + NoModRef = 0, Refs = 1, // Ref = bit 1 + Mods = 2, ModRef = 3 // Mod = bit 2 + }; + unsigned AccessTy : 2; + + /// AliasType - Keep track the relationships between the pointers in the set. + /// Lattice goes from MustAlias to MayAlias. + /// + enum AliasType { + MustAlias = 0, MayAlias = 1 + }; + unsigned AliasTy : 1; + + // Volatile - True if this alias set contains volatile loads or stores. + bool Volatile : 1; + + void addRef() { ++RefCount; } + void dropRef(AliasSetTracker &AST) { + assert(RefCount >= 1 && "Invalid reference count detected!"); + if (--RefCount == 0) + removeFromTracker(AST); + } + +public: + /// Accessors... + bool isRef() const { return AccessTy & Refs; } + bool isMod() const { return AccessTy & Mods; } + bool isMustAlias() const { return AliasTy == MustAlias; } + bool isMayAlias() const { return AliasTy == MayAlias; } + + // isVolatile - Return true if this alias set contains volatile loads or + // stores. + bool isVolatile() const { return Volatile; } + + /// isForwardingAliasSet - Return true if this alias set should be ignored as + /// part of the AliasSetTracker object. + bool isForwardingAliasSet() const { return Forward; } + + /// mergeSetIn - Merge the specified alias set into this alias set... + /// + void mergeSetIn(AliasSet &AS, AliasSetTracker &AST); + + // Alias Set iteration - Allow access to all of the pointer which are part of + // this alias set... + class iterator; + iterator begin() const { return iterator(PtrList); } + iterator end() const { return iterator(); } + bool empty() const { return PtrList == 0; } + + void print(raw_ostream &OS) const; + void dump() const; + + /// Define an iterator for alias sets... this is just a forward iterator. + class iterator : public std::iterator { + PointerRec *CurNode; + public: + explicit iterator(PointerRec *CN = 0) : CurNode(CN) {} + + bool operator==(const iterator& x) const { + return CurNode == x.CurNode; + } + bool operator!=(const iterator& x) const { return !operator==(x); } + + const iterator &operator=(const iterator &I) { + CurNode = I.CurNode; + return *this; + } + + value_type &operator*() const { + assert(CurNode && "Dereferencing AliasSet.end()!"); + return *CurNode; + } + value_type *operator->() const { return &operator*(); } + + Value *getPointer() const { return CurNode->getValue(); } + unsigned getSize() const { return CurNode->getSize(); } + + iterator& operator++() { // Preincrement + assert(CurNode && "Advancing past AliasSet.end()!"); + CurNode = CurNode->getNext(); + return *this; + } + iterator operator++(int) { // Postincrement + iterator tmp = *this; ++*this; return tmp; + } + }; + +private: + // Can only be created by AliasSetTracker. Also, ilist creates one + // to serve as a sentinel. + friend struct ilist_sentinel_traits; + AliasSet() : PtrList(0), PtrListEnd(&PtrList), Forward(0), RefCount(0), + AccessTy(NoModRef), AliasTy(MustAlias), Volatile(false) { + } + + AliasSet(const AliasSet &AS); // do not implement + void operator=(const AliasSet &AS); // do not implement + + PointerRec *getSomePointer() const { + return PtrList; + } + + /// getForwardedTarget - Return the real alias set this represents. If this + /// has been merged with another set and is forwarding, return the ultimate + /// destination set. This also implements the union-find collapsing as well. + AliasSet *getForwardedTarget(AliasSetTracker &AST) { + if (!Forward) return this; + + AliasSet *Dest = Forward->getForwardedTarget(AST); + if (Dest != Forward) { + Dest->addRef(); + Forward->dropRef(AST); + Forward = Dest; + } + return Dest; + } + + void removeFromTracker(AliasSetTracker &AST); + + void addPointer(AliasSetTracker &AST, PointerRec &Entry, unsigned Size, + bool KnownMustAlias = false); + void addCallSite(CallSite CS, AliasAnalysis &AA); + void removeCallSite(CallSite CS) { + for (size_t i = 0, e = CallSites.size(); i != e; ++i) + if (CallSites[i].getInstruction() == CS.getInstruction()) { + CallSites[i] = CallSites.back(); + CallSites.pop_back(); + } + } + void setVolatile() { Volatile = true; } + + /// aliasesPointer - Return true if the specified pointer "may" (or must) + /// alias one of the members in the set. + /// + bool aliasesPointer(const Value *Ptr, unsigned Size, AliasAnalysis &AA) const; + bool aliasesCallSite(CallSite CS, AliasAnalysis &AA) const; +}; + +inline raw_ostream& operator<<(raw_ostream &OS, const AliasSet &AS) { + AS.print(OS); + return OS; +} + + +class AliasSetTracker { + /// CallbackVH - A CallbackVH to arrange for AliasSetTracker to be + /// notified whenever a Value is deleted. + class ASTCallbackVH : public CallbackVH { + AliasSetTracker *AST; + virtual void deleted(); + public: + ASTCallbackVH(Value *V, AliasSetTracker *AST = 0); + ASTCallbackVH &operator=(Value *V); + }; + /// ASTCallbackVHDenseMapInfo - Traits to tell DenseMap that ASTCallbackVH + /// is not a POD (it needs its destructor called). + struct ASTCallbackVHDenseMapInfo : public DenseMapInfo { + static bool isPod() { return false; } + }; + + AliasAnalysis &AA; + ilist AliasSets; + + typedef DenseMap + PointerMapType; + + // Map from pointers to their node + PointerMapType PointerMap; + +public: + /// AliasSetTracker ctor - Create an empty collection of AliasSets, and use + /// the specified alias analysis object to disambiguate load and store + /// addresses. + explicit AliasSetTracker(AliasAnalysis &aa) : AA(aa) {} + ~AliasSetTracker() { clear(); } + + /// add methods - These methods are used to add different types of + /// instructions to the alias sets. Adding a new instruction can result in + /// one of three actions happening: + /// + /// 1. If the instruction doesn't alias any other sets, create a new set. + /// 2. If the instruction aliases exactly one set, add it to the set + /// 3. If the instruction aliases multiple sets, merge the sets, and add + /// the instruction to the result. + /// + /// These methods return true if inserting the instruction resulted in the + /// addition of a new alias set (i.e., the pointer did not alias anything). + /// + bool add(Value *Ptr, unsigned Size); // Add a location + bool add(LoadInst *LI); + bool add(StoreInst *SI); + 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... + void add(BasicBlock &BB); // Add all instructions in basic block + void add(const AliasSetTracker &AST); // Add alias relations from another AST + + /// remove methods - These methods are used to remove all entries that might + /// be aliased by the specified instruction. These methods return true if any + /// alias sets were eliminated. + bool remove(Value *Ptr, unsigned Size); // Remove a location + bool remove(LoadInst *LI); + bool remove(StoreInst *SI); + 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); + void remove(AliasSet &AS); + + void clear(); + + /// getAliasSets - Return the alias sets that are active. + /// + const ilist &getAliasSets() const { return AliasSets; } + + /// getAliasSetForPointer - Return the alias set that the specified pointer + /// lives in. If the New argument is non-null, this method sets the value to + /// true if a new alias set is created to contain the pointer (because the + /// pointer didn't alias anything). + AliasSet &getAliasSetForPointer(Value *P, unsigned Size, bool *New = 0); + + /// getAliasSetForPointerIfExists - Return the alias set containing the + /// location specified if one exists, otherwise return null. + AliasSet *getAliasSetForPointerIfExists(Value *P, unsigned Size) { + return findAliasSetForPointer(P, Size); + } + + /// containsPointer - Return true if the specified location is represented by + /// this alias set, false otherwise. This does not modify the AST object or + /// alias sets. + bool containsPointer(Value *P, unsigned Size) const; + + /// getAliasAnalysis - Return the underlying alias analysis object used by + /// this tracker. + AliasAnalysis &getAliasAnalysis() const { return AA; } + + /// deleteValue method - This method is used to remove a pointer value from + /// the AliasSetTracker entirely. It should be used when an instruction is + /// deleted from the program to update the AST. If you don't use this, you + /// would have dangling pointers to deleted instructions. + /// + void deleteValue(Value *PtrVal); + + /// copyValue - This method should be used whenever a preexisting value in the + /// program is copied or cloned, introducing a new value. Note that it is ok + /// for clients that use this method to introduce the same value multiple + /// times: if the tracker already knows about a value, it will ignore the + /// request. + /// + void copyValue(Value *From, Value *To); + + + typedef ilist::iterator iterator; + typedef ilist::const_iterator const_iterator; + + const_iterator begin() const { return AliasSets.begin(); } + const_iterator end() const { return AliasSets.end(); } + + iterator begin() { return AliasSets.begin(); } + iterator end() { return AliasSets.end(); } + + void print(raw_ostream &OS) const; + void dump() const; + +private: + friend class AliasSet; + void removeAliasSet(AliasSet *AS); + + // getEntryFor - Just like operator[] on the map, except that it creates an + // entry for the pointer if it doesn't already exist. + AliasSet::PointerRec &getEntryFor(Value *V) { + AliasSet::PointerRec *&Entry = PointerMap[ASTCallbackVH(V, this)]; + if (Entry == 0) + Entry = new AliasSet::PointerRec(V); + return *Entry; + } + + AliasSet &addPointer(Value *P, unsigned Size, AliasSet::AccessType E, + bool &NewSet) { + NewSet = false; + AliasSet &AS = getAliasSetForPointer(P, Size, &NewSet); + AS.AccessTy |= E; + return AS; + } + AliasSet *findAliasSetForPointer(const Value *Ptr, unsigned Size); + + AliasSet *findAliasSetForCallSite(CallSite CS); +}; + +inline raw_ostream& operator<<(raw_ostream &OS, const AliasSetTracker &AST) { + AST.print(OS); + return OS; +} + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Analysis/CFGPrinter.h b/libclamav/c++/llvm/include/llvm/Analysis/CFGPrinter.h new file mode 100644 index 000000000..440d18267 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Analysis/CFGPrinter.h @@ -0,0 +1,97 @@ +//===-- CFGPrinter.h - CFG printer external interface ------------*- 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 external functions that can be called to explicitly +// instantiate the CFG printer. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_CFGPRINTER_H +#define LLVM_ANALYSIS_CFGPRINTER_H + +#include "llvm/Function.h" +#include "llvm/Instructions.h" +#include "llvm/Assembly/Writer.h" +#include "llvm/Support/CFG.h" +#include "llvm/Support/GraphWriter.h" + +namespace llvm { +template<> +struct DOTGraphTraits : public DefaultDOTGraphTraits { + static std::string getGraphName(const Function *F) { + return "CFG for '" + F->getNameStr() + "' function"; + } + + static std::string getNodeLabel(const BasicBlock *Node, + const Function *Graph, + bool ShortNames) { + if (ShortNames && !Node->getName().empty()) + return Node->getNameStr() + ":"; + + std::string Str; + raw_string_ostream OS(Str); + + if (ShortNames) { + WriteAsOperand(OS, Node, false); + return OS.str(); + } + + if (Node->getName().empty()) { + WriteAsOperand(OS, Node, false); + OS << ":"; + } + + OS << *Node; + std::string OutStr = OS.str(); + if (OutStr[0] == '\n') OutStr.erase(OutStr.begin()); + + // Process string output to make it nicer... + for (unsigned i = 0; i != OutStr.length(); ++i) + if (OutStr[i] == '\n') { // Left justify + OutStr[i] = '\\'; + OutStr.insert(OutStr.begin()+i+1, 'l'); + } else if (OutStr[i] == ';') { // Delete comments! + unsigned Idx = OutStr.find('\n', i+1); // Find end of line + OutStr.erase(OutStr.begin()+i, OutStr.begin()+Idx); + --i; + } + + return OutStr; + } + + static std::string getEdgeSourceLabel(const BasicBlock *Node, + succ_const_iterator I) { + // Label source of conditional branches with "T" or "F" + if (const BranchInst *BI = dyn_cast(Node->getTerminator())) + if (BI->isConditional()) + return (I == succ_begin(Node)) ? "T" : "F"; + + // Label source of switch edges with the associated value. + if (const SwitchInst *SI = dyn_cast(Node->getTerminator())) { + unsigned SuccNo = I.getSuccessorIndex(); + + if (SuccNo == 0) return "def"; + + std::string Str; + raw_string_ostream OS(Str); + OS << SI->getCaseValue(SuccNo)->getValue(); + return OS.str(); + } + return ""; + } +}; +} // End llvm namespace + +namespace llvm { + class FunctionPass; + FunctionPass *createCFGPrinterPass (); + FunctionPass *createCFGOnlyPrinterPass (); +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Analysis/CallGraph.h b/libclamav/c++/llvm/include/llvm/Analysis/CallGraph.h new file mode 100644 index 000000000..287fe4faa --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Analysis/CallGraph.h @@ -0,0 +1,358 @@ +//===- CallGraph.h - Build a Module's call graph ----------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This interface is used to build and manipulate a call graph, which is a very +// useful tool for interprocedural optimization. +// +// Every function in a module is represented as a node in the call graph. The +// callgraph node keeps track of which functions the are called by the function +// corresponding to the node. +// +// A call graph may contain nodes where the function that they correspond to is +// null. These 'external' nodes are used to represent control flow that is not +// represented (or analyzable) in the module. In particular, this analysis +// builds one external node such that: +// 1. All functions in the module without internal linkage will have edges +// from this external node, indicating that they could be called by +// functions outside of the module. +// 2. All functions whose address is used for something more than a direct +// call, for example being stored into a memory location will also have an +// edge from this external node. Since they may be called by an unknown +// caller later, they must be tracked as such. +// +// There is a second external node added for calls that leave this module. +// Functions have a call edge to the external node iff: +// 1. The function is external, reflecting the fact that they could call +// anything without internal linkage or that has its address taken. +// 2. The function contains an indirect function call. +// +// As an extension in the future, there may be multiple nodes with a null +// function. These will be used when we can prove (through pointer analysis) +// that an indirect call site can call only a specific set of functions. +// +// Because of these properties, the CallGraph captures a conservative superset +// of all of the caller-callee relationships, which is useful for +// transformations. +// +// The CallGraph class also attempts to figure out what the root of the +// CallGraph is, which it currently does by looking for a function named 'main'. +// If no function named 'main' is found, the external node is used as the entry +// node, reflecting the fact that any function without internal linkage could +// be called into (which is common for libraries). +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_CALLGRAPH_H +#define LLVM_ANALYSIS_CALLGRAPH_H + +#include "llvm/Function.h" +#include "llvm/Pass.h" +#include "llvm/ADT/GraphTraits.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/Support/CallSite.h" +#include "llvm/Support/ValueHandle.h" +#include "llvm/System/IncludeFile.h" +#include + +namespace llvm { + +class Function; +class Module; +class CallGraphNode; + +//===----------------------------------------------------------------------===// +// CallGraph class definition +// +class CallGraph { +protected: + Module *Mod; // The module this call graph represents + + typedef std::map FunctionMapTy; + FunctionMapTy FunctionMap; // Map from a function to its node + +public: + static char ID; // Class identification, replacement for typeinfo + //===--------------------------------------------------------------------- + // Accessors. + // + typedef FunctionMapTy::iterator iterator; + typedef FunctionMapTy::const_iterator const_iterator; + + /// getModule - Return the module the call graph corresponds to. + /// + Module &getModule() const { return *Mod; } + + inline iterator begin() { return FunctionMap.begin(); } + inline iterator end() { return FunctionMap.end(); } + inline const_iterator begin() const { return FunctionMap.begin(); } + inline const_iterator end() const { return FunctionMap.end(); } + + // Subscripting operators, return the call graph node for the provided + // function + inline const CallGraphNode *operator[](const Function *F) const { + const_iterator I = FunctionMap.find(F); + assert(I != FunctionMap.end() && "Function not in callgraph!"); + return I->second; + } + inline CallGraphNode *operator[](const Function *F) { + const_iterator I = FunctionMap.find(F); + assert(I != FunctionMap.end() && "Function not in callgraph!"); + return I->second; + } + + /// Returns the CallGraphNode which is used to represent undetermined calls + /// into the callgraph. Override this if you want behavioral inheritance. + virtual CallGraphNode* getExternalCallingNode() const { return 0; } + virtual CallGraphNode* getCallsExternalNode() const { return 0; } + + /// Return the root/main method in the module, or some other root node, such + /// as the externalcallingnode. Overload these if you behavioral + /// inheritance. + virtual CallGraphNode* getRoot() { return 0; } + virtual const CallGraphNode* getRoot() const { return 0; } + + //===--------------------------------------------------------------------- + // Functions to keep a call graph up to date with a function that has been + // modified. + // + + /// removeFunctionFromModule - Unlink the function from this module, returning + /// it. Because this removes the function from the module, the call graph + /// node is destroyed. This is only valid if the function does not call any + /// other functions (ie, there are no edges in it's CGN). The easiest way to + /// do this is to dropAllReferences before calling this. + /// + Function *removeFunctionFromModule(CallGraphNode *CGN); + Function *removeFunctionFromModule(Function *F) { + return removeFunctionFromModule((*this)[F]); + } + + /// getOrInsertFunction - This method is identical to calling operator[], but + /// it will insert a new CallGraphNode for the specified function if one does + /// not already exist. + CallGraphNode *getOrInsertFunction(const Function *F); + + //===--------------------------------------------------------------------- + // Pass infrastructure interface glue code. + // +protected: + CallGraph() {} + +public: + virtual ~CallGraph() { destroy(); } + + /// initialize - Call this method before calling other methods, + /// re/initializes the state of the CallGraph. + /// + void initialize(Module &M); + + void print(raw_ostream &o, Module *) const; + void dump() const; +protected: + // destroy - Release memory for the call graph + virtual void destroy(); +}; + +//===----------------------------------------------------------------------===// +// CallGraphNode class definition. +// +class CallGraphNode { + AssertingVH F; + + // CallRecord - This is a pair of the calling instruction (a call or invoke) + // and the callgraph node being called. +public: + typedef std::pair CallRecord; +private: + std::vector CalledFunctions; + + /// NumReferences - This is the number of times that this CallGraphNode occurs + /// in the CalledFunctions array of this or other CallGraphNodes. + unsigned NumReferences; + + CallGraphNode(const CallGraphNode &); // DO NOT IMPLEMENT + void operator=(const CallGraphNode &); // DO NOT IMPLEMENT + + void DropRef() { --NumReferences; } + void AddRef() { ++NumReferences; } +public: + typedef std::vector CalledFunctionsVector; + + + // CallGraphNode ctor - Create a node for the specified function. + inline CallGraphNode(Function *f) : F(f), NumReferences(0) {} + + //===--------------------------------------------------------------------- + // Accessor methods. + // + + typedef std::vector::iterator iterator; + typedef std::vector::const_iterator const_iterator; + + // getFunction - Return the function that this call graph node represents. + Function *getFunction() const { return F; } + + inline iterator begin() { return CalledFunctions.begin(); } + inline iterator end() { return CalledFunctions.end(); } + inline const_iterator begin() const { return CalledFunctions.begin(); } + inline const_iterator end() const { return CalledFunctions.end(); } + inline bool empty() const { return CalledFunctions.empty(); } + inline unsigned size() const { return (unsigned)CalledFunctions.size(); } + + /// getNumReferences - Return the number of other CallGraphNodes in this + /// CallGraph that reference this node in their callee list. + unsigned getNumReferences() const { return NumReferences; } + + // Subscripting operator - Return the i'th called function. + // + CallGraphNode *operator[](unsigned i) const { + assert(i < CalledFunctions.size() && "Invalid index"); + return CalledFunctions[i].second; + } + + /// dump - Print out this call graph node. + /// + void dump() const; + void print(raw_ostream &OS) const; + + //===--------------------------------------------------------------------- + // Methods to keep a call graph up to date with a function that has been + // modified + // + + /// removeAllCalledFunctions - As the name implies, this removes all edges + /// from this CallGraphNode to any functions it calls. + void removeAllCalledFunctions() { + while (!CalledFunctions.empty()) { + CalledFunctions.back().second->DropRef(); + CalledFunctions.pop_back(); + } + } + + /// stealCalledFunctionsFrom - Move all the callee information from N to this + /// node. + void stealCalledFunctionsFrom(CallGraphNode *N) { + assert(CalledFunctions.empty() && + "Cannot steal callsite information if I already have some"); + std::swap(CalledFunctions, N->CalledFunctions); + } + + + /// addCalledFunction - Add a function to the list of functions called by this + /// one. + void addCalledFunction(CallSite CS, CallGraphNode *M) { + CalledFunctions.push_back(std::make_pair(CS.getInstruction(), M)); + M->AddRef(); + } + + void removeCallEdge(iterator I) { + I->second->DropRef(); + *I = CalledFunctions.back(); + CalledFunctions.pop_back(); + } + + + /// removeCallEdgeFor - This method removes the edge in the node for the + /// specified call site. Note that this method takes linear time, so it + /// should be used sparingly. + void removeCallEdgeFor(CallSite CS); + + /// removeAnyCallEdgeTo - This method removes all call edges from this node + /// to the specified callee function. This takes more time to execute than + /// removeCallEdgeTo, so it should not be used unless necessary. + void removeAnyCallEdgeTo(CallGraphNode *Callee); + + /// removeOneAbstractEdgeTo - Remove one edge associated with a null callsite + /// from this node to the specified callee function. + void removeOneAbstractEdgeTo(CallGraphNode *Callee); + + /// replaceCallEdge - This method replaces the edge in the node for the + /// specified call site with a new one. Note that this method takes linear + /// time, so it should be used sparingly. + void replaceCallEdge(CallSite CS, CallSite NewCS, CallGraphNode *NewNode); + +}; + +//===----------------------------------------------------------------------===// +// GraphTraits specializations for call graphs so that they can be treated as +// graphs by the generic graph algorithms. +// + +// Provide graph traits for tranversing call graphs using standard graph +// traversals. +template <> struct GraphTraits { + typedef CallGraphNode NodeType; + + typedef CallGraphNode::CallRecord CGNPairTy; + typedef std::pointer_to_unary_function CGNDerefFun; + + static NodeType *getEntryNode(CallGraphNode *CGN) { return CGN; } + + typedef mapped_iterator ChildIteratorType; + + static inline ChildIteratorType child_begin(NodeType *N) { + return map_iterator(N->begin(), CGNDerefFun(CGNDeref)); + } + static inline ChildIteratorType child_end (NodeType *N) { + return map_iterator(N->end(), CGNDerefFun(CGNDeref)); + } + + static CallGraphNode *CGNDeref(CGNPairTy P) { + return P.second; + } + +}; + +template <> struct GraphTraits { + typedef const CallGraphNode NodeType; + typedef NodeType::const_iterator ChildIteratorType; + + static NodeType *getEntryNode(const CallGraphNode *CGN) { return CGN; } + static inline ChildIteratorType child_begin(NodeType *N) { return N->begin();} + static inline ChildIteratorType child_end (NodeType *N) { return N->end(); } +}; + +template<> struct GraphTraits : public GraphTraits { + static NodeType *getEntryNode(CallGraph *CGN) { + return CGN->getExternalCallingNode(); // Start at the external node! + } + typedef std::pair PairTy; + typedef std::pointer_to_unary_function DerefFun; + + // nodes_iterator/begin/end - Allow iteration over all nodes in the graph + typedef mapped_iterator nodes_iterator; + static nodes_iterator nodes_begin(CallGraph *CG) { + return map_iterator(CG->begin(), DerefFun(CGdereference)); + } + static nodes_iterator nodes_end (CallGraph *CG) { + return map_iterator(CG->end(), DerefFun(CGdereference)); + } + + static CallGraphNode &CGdereference(PairTy P) { + return *P.second; + } +}; + +template<> struct GraphTraits : + public GraphTraits { + static NodeType *getEntryNode(const CallGraph *CGN) { + return CGN->getExternalCallingNode(); + } + // nodes_iterator/begin/end - Allow iteration over all nodes in the graph + typedef CallGraph::const_iterator nodes_iterator; + static nodes_iterator nodes_begin(const CallGraph *CG) { return CG->begin(); } + static nodes_iterator nodes_end (const CallGraph *CG) { return CG->end(); } +}; + +} // End llvm namespace + +// Make sure that any clients of this file link in CallGraph.cpp +FORCE_DEFINING_FILE_TO_BE_LINKED(CallGraph) + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Analysis/CaptureTracking.h b/libclamav/c++/llvm/include/llvm/Analysis/CaptureTracking.h new file mode 100644 index 000000000..493ecf517 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Analysis/CaptureTracking.h @@ -0,0 +1,33 @@ +//===----- llvm/Analysis/CaptureTracking.h - Pointer capture ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains routines that help determine which pointers are captured. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_CAPTURETRACKING_H +#define LLVM_ANALYSIS_CAPTURETRACKING_H + +namespace llvm { + class Value; + + /// PointerMayBeCaptured - Return true if this pointer value may be captured + /// by the enclosing function (which is required to exist). This routine can + /// be expensive, so consider caching the results. The boolean ReturnCaptures + /// specifies whether returning the value (or part of it) from the function + /// counts as capturing it or not. The boolean StoreCaptures specified whether + /// storing the value (or part of it) into memory anywhere automatically + /// counts as capturing it or not. + bool PointerMayBeCaptured(const Value *V, + bool ReturnCaptures, + bool StoreCaptures); + +} // end namespace llvm + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Analysis/ConstantFolding.h b/libclamav/c++/llvm/include/llvm/Analysis/ConstantFolding.h new file mode 100644 index 000000000..06951c7e4 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Analysis/ConstantFolding.h @@ -0,0 +1,81 @@ +//===-- ConstantFolding.h - Fold instructions into constants --------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares routines for folding instructions into constants. +// +// Also, to supplement the basic VMCore ConstantExpr simplifications, +// this file declares some additional folding routines that can make use of +// TargetData information. These functions cannot go in VMCore due to library +// dependency issues. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_CONSTANTFOLDING_H +#define LLVM_ANALYSIS_CONSTANTFOLDING_H + +namespace llvm { + class Constant; + class ConstantExpr; + class Instruction; + class TargetData; + class Function; + class Type; + +/// ConstantFoldInstruction - Attempt to constant fold the specified +/// instruction. If successful, the constant result is returned, if not, null +/// is returned. Note that this function can only fail when attempting to fold +/// instructions like loads and stores, which have no constant expression form. +/// +Constant *ConstantFoldInstruction(Instruction *I, const TargetData *TD = 0); + +/// ConstantFoldConstantExpression - Attempt to fold the constant expression +/// using the specified TargetData. If successful, the constant result is +/// result is returned, if not, null is returned. +Constant *ConstantFoldConstantExpression(ConstantExpr *CE, + const TargetData *TD = 0); + +/// ConstantFoldInstOperands - Attempt to constant fold an instruction with the +/// specified operands. If successful, the constant result is returned, if not, +/// null is returned. Note that this function can fail when attempting to +/// fold instructions like loads and stores, which have no constant expression +/// form. +/// +Constant *ConstantFoldInstOperands(unsigned Opcode, const Type *DestTy, + Constant *const *Ops, unsigned NumOps, + const TargetData *TD = 0); + +/// ConstantFoldCompareInstOperands - Attempt to constant fold a compare +/// instruction (icmp/fcmp) with the specified operands. If it fails, it +/// returns a constant expression of the specified operands. +/// +Constant *ConstantFoldCompareInstOperands(unsigned Predicate, + Constant *LHS, Constant *RHS, + const TargetData *TD = 0); + +/// ConstantFoldLoadFromConstPtr - Return the value that a load from C would +/// produce if it is constant and determinable. If this is not determinable, +/// return null. +Constant *ConstantFoldLoadFromConstPtr(Constant *C, const TargetData *TD = 0); + +/// ConstantFoldLoadThroughGEPConstantExpr - Given a constant and a +/// getelementptr constantexpr, return the constant value being addressed by the +/// constant expression, or null if something is funny and we can't decide. +Constant *ConstantFoldLoadThroughGEPConstantExpr(Constant *C, ConstantExpr *CE); + +/// canConstantFoldCallTo - Return true if its even possible to fold a call to +/// the specified function. +bool canConstantFoldCallTo(const Function *F); + +/// ConstantFoldCall - Attempt to constant fold a call to the specified function +/// with the specified arguments, returning null if unsuccessful. +Constant * +ConstantFoldCall(Function *F, Constant *const *Operands, unsigned NumOperands); +} + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Analysis/ConstantsScanner.h b/libclamav/c++/llvm/include/llvm/Analysis/ConstantsScanner.h new file mode 100644 index 000000000..cdaf68d75 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Analysis/ConstantsScanner.h @@ -0,0 +1,93 @@ +//==- llvm/Analysis/ConstantsScanner.h - Iterate over constants -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This class implements an iterator to walk through the constants referenced by +// a method. This is used by the Bitcode & Assembly writers to build constant +// pools. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_CONSTANTSSCANNER_H +#define LLVM_ANALYSIS_CONSTANTSSCANNER_H + +#include "llvm/Support/InstIterator.h" + +namespace llvm { + +class Constant; + +class constant_iterator : public std::iterator { + const_inst_iterator InstI; // Method instruction iterator + unsigned OpIdx; // Operand index + + typedef constant_iterator _Self; + + inline bool isAtConstant() const { + assert(!InstI.atEnd() && OpIdx < InstI->getNumOperands() && + "isAtConstant called with invalid arguments!"); + return isa(InstI->getOperand(OpIdx)); + } + +public: + inline constant_iterator(const Function *F) : InstI(inst_begin(F)), OpIdx(0) { + // Advance to first constant... if we are not already at constant or end + if (InstI != inst_end(F) && // InstI is valid? + (InstI->getNumOperands() == 0 || !isAtConstant())) // Not at constant? + operator++(); + } + + inline constant_iterator(const Function *F, bool) // end ctor + : InstI(inst_end(F)), OpIdx(0) { + } + + inline bool operator==(const _Self& x) const { return OpIdx == x.OpIdx && + InstI == x.InstI; } + inline bool operator!=(const _Self& x) const { return !operator==(x); } + + inline pointer operator*() const { + assert(isAtConstant() && "Dereferenced an iterator at the end!"); + return cast(InstI->getOperand(OpIdx)); + } + inline pointer operator->() const { return operator*(); } + + inline _Self& operator++() { // Preincrement implementation + ++OpIdx; + do { + unsigned NumOperands = InstI->getNumOperands(); + while (OpIdx < NumOperands && !isAtConstant()) { + ++OpIdx; + } + + if (OpIdx < NumOperands) return *this; // Found a constant! + ++InstI; + OpIdx = 0; + } while (!InstI.atEnd()); + + return *this; // At the end of the method + } + + inline _Self operator++(int) { // Postincrement + _Self tmp = *this; ++*this; return tmp; + } + + inline bool atEnd() const { return InstI.atEnd(); } +}; + +inline constant_iterator constant_begin(const Function *F) { + return constant_iterator(F); +} + +inline constant_iterator constant_end(const Function *F) { + return constant_iterator(F, true); +} + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Analysis/DebugInfo.h b/libclamav/c++/llvm/include/llvm/Analysis/DebugInfo.h new file mode 100644 index 000000000..866ed8a87 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Analysis/DebugInfo.h @@ -0,0 +1,742 @@ +//===--- llvm/Analysis/DebugInfo.h - Debug Information Helpers --*- 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 a bunch of datatypes that are useful for creating and +// walking debug info in LLVM IR form. They essentially provide wrappers around +// the information in the global variables that's needed when constructing the +// DWARF information. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_DEBUGINFO_H +#define LLVM_ANALYSIS_DEBUGINFO_H + +#include "llvm/Metadata.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/Support/Dwarf.h" +#include "llvm/Support/ValueHandle.h" + +namespace llvm { + class BasicBlock; + class Constant; + class Function; + class GlobalVariable; + class Module; + class Type; + class Value; + struct DbgStopPointInst; + struct DbgDeclareInst; + struct DbgFuncStartInst; + struct DbgRegionStartInst; + struct DbgRegionEndInst; + class DebugLoc; + struct DebugLocTracker; + class Instruction; + class LLVMContext; + + /// DIDescriptor - A thin wraper around MDNode to access encoded debug info. This should not + /// be stored in a container, because underly MDNode may change in certain situations. + class DIDescriptor { + protected: + MDNode *DbgNode; + + /// DIDescriptor constructor. If the specified node is non-null, check + /// to make sure that the tag in the descriptor matches 'RequiredTag'. If + /// not, the debug info is corrupt and we ignore it. + DIDescriptor(MDNode *N, unsigned RequiredTag); + + StringRef getStringField(unsigned Elt) const; + unsigned getUnsignedField(unsigned Elt) const { + return (unsigned)getUInt64Field(Elt); + } + uint64_t getUInt64Field(unsigned Elt) const; + DIDescriptor getDescriptorField(unsigned Elt) const; + + template + DescTy getFieldAs(unsigned Elt) const { + return DescTy(getDescriptorField(Elt).getNode()); + } + + GlobalVariable *getGlobalVariableField(unsigned Elt) const; + + public: + explicit DIDescriptor() : DbgNode(0) {} + explicit DIDescriptor(MDNode *N) : DbgNode(N) {} + + bool isNull() const { return DbgNode == 0; } + + MDNode *getNode() const { return DbgNode; } + + unsigned getVersion() const { + return getUnsignedField(0) & LLVMDebugVersionMask; + } + + unsigned getTag() const { + return getUnsignedField(0) & ~LLVMDebugVersionMask; + } + + /// ValidDebugInfo - Return true if N represents valid debug info value. + static bool ValidDebugInfo(MDNode *N, CodeGenOpt::Level OptLevel); + + /// dump - print descriptor. + void dump() const; + + bool isDerivedType() const; + bool isCompositeType() const; + bool isBasicType() const; + bool isVariable() const; + bool isSubprogram() const; + bool isGlobalVariable() const; + bool isScope() const; + bool isCompileUnit() const; + bool isLexicalBlock() const; + bool isSubrange() const; + bool isEnumerator() const; + bool isType() const; + bool isGlobal() const; + }; + + /// DISubrange - This is used to represent ranges, for array bounds. + class DISubrange : public DIDescriptor { + public: + explicit DISubrange(MDNode *N = 0) + : DIDescriptor(N, dwarf::DW_TAG_subrange_type) {} + + int64_t getLo() const { return (int64_t)getUInt64Field(1); } + int64_t getHi() const { return (int64_t)getUInt64Field(2); } + }; + + /// DIArray - This descriptor holds an array of descriptors. + class DIArray : public DIDescriptor { + public: + explicit DIArray(MDNode *N = 0) + : DIDescriptor(N) {} + + unsigned getNumElements() const; + DIDescriptor getElement(unsigned Idx) const { + return getDescriptorField(Idx); + } + }; + + /// DIScope - A base class for various scopes. + class DIScope : public DIDescriptor { + public: + explicit DIScope(MDNode *N = 0) : DIDescriptor (N) { + if (DbgNode && !isScope()) + DbgNode = 0; + } + virtual ~DIScope() {} + + StringRef getFilename() const; + StringRef getDirectory() const; + }; + + /// DICompileUnit - A wrapper for a compile unit. + class DICompileUnit : public DIScope { + public: + explicit DICompileUnit(MDNode *N = 0) : DIScope(N) { + if (DbgNode && !isCompileUnit()) + DbgNode = 0; + } + + unsigned getLanguage() const { return getUnsignedField(2); } + StringRef getFilename() const { return getStringField(3); } + StringRef getDirectory() const { return getStringField(4); } + StringRef getProducer() const { return getStringField(5); } + + /// isMain - Each input file is encoded as a separate compile unit in LLVM + /// debugging information output. However, many target specific tool chains + /// prefer to encode only one compile unit in an object file. In this + /// situation, the LLVM code generator will include debugging information + /// entities in the compile unit that is marked as main compile unit. The + /// code generator accepts maximum one main compile unit per module. If a + /// module does not contain any main compile unit then the code generator + /// will emit multiple compile units in the output object file. + + bool isMain() const { return getUnsignedField(6); } + bool isOptimized() const { return getUnsignedField(7); } + StringRef getFlags() const { return getStringField(8); } + unsigned getRunTimeVersion() const { return getUnsignedField(9); } + + /// Verify - Verify that a compile unit is well formed. + bool Verify() const; + + /// dump - print compile unit. + void dump() const; + }; + + /// DIEnumerator - A wrapper for an enumerator (e.g. X and Y in 'enum {X,Y}'). + /// FIXME: it seems strange that this doesn't have either a reference to the + /// type/precision or a file/line pair for location info. + class DIEnumerator : public DIDescriptor { + public: + explicit DIEnumerator(MDNode *N = 0) + : DIDescriptor(N, dwarf::DW_TAG_enumerator) {} + + StringRef getName() const { return getStringField(1); } + uint64_t getEnumValue() const { return getUInt64Field(2); } + }; + + /// DIType - This is a wrapper for a type. + /// FIXME: Types should be factored much better so that CV qualifiers and + /// others do not require a huge and empty descriptor full of zeros. + class DIType : public DIDescriptor { + public: + enum { + FlagPrivate = 1 << 0, + FlagProtected = 1 << 1, + FlagFwdDecl = 1 << 2, + FlagAppleBlock = 1 << 3, + FlagBlockByrefStruct = 1 << 4 + }; + + protected: + DIType(MDNode *N, unsigned Tag) + : DIDescriptor(N, Tag) {} + // This ctor is used when the Tag has already been validated by a derived + // ctor. + DIType(MDNode *N, bool, bool) : DIDescriptor(N) {} + + public: + + /// Verify - Verify that a type descriptor is well formed. + bool Verify() const; + public: + explicit DIType(MDNode *N); + explicit DIType() {} + virtual ~DIType() {} + + DIDescriptor getContext() const { return getDescriptorField(1); } + StringRef getName() const { return getStringField(2); } + DICompileUnit getCompileUnit() const{ return getFieldAs(3); } + unsigned getLineNumber() const { return getUnsignedField(4); } + uint64_t getSizeInBits() const { return getUInt64Field(5); } + uint64_t getAlignInBits() const { return getUInt64Field(6); } + // FIXME: Offset is only used for DW_TAG_member nodes. Making every type + // carry this is just plain insane. + uint64_t getOffsetInBits() const { return getUInt64Field(7); } + unsigned getFlags() const { return getUnsignedField(8); } + bool isPrivate() const { + return (getFlags() & FlagPrivate) != 0; + } + bool isProtected() const { + return (getFlags() & FlagProtected) != 0; + } + bool isForwardDecl() const { + return (getFlags() & FlagFwdDecl) != 0; + } + // isAppleBlock - Return true if this is the Apple Blocks extension. + bool isAppleBlockExtension() const { + return (getFlags() & FlagAppleBlock) != 0; + } + bool isBlockByrefStruct() const { + return (getFlags() & FlagBlockByrefStruct) != 0; + } + + /// dump - print type. + void dump() const; + }; + + /// DIBasicType - A basic type, like 'int' or 'float'. + class DIBasicType : public DIType { + public: + explicit DIBasicType(MDNode *N = 0) + : DIType(N, dwarf::DW_TAG_base_type) {} + + unsigned getEncoding() const { return getUnsignedField(9); } + + /// dump - print basic type. + void dump() const; + }; + + /// DIDerivedType - A simple derived type, like a const qualified type, + /// a typedef, a pointer or reference, etc. + class DIDerivedType : public DIType { + protected: + explicit DIDerivedType(MDNode *N, bool, bool) + : DIType(N, true, true) {} + public: + explicit DIDerivedType(MDNode *N = 0) + : DIType(N, true, true) { + if (DbgNode && !isDerivedType()) + DbgNode = 0; + } + + DIType getTypeDerivedFrom() const { return getFieldAs(9); } + + /// getOriginalTypeSize - If this type is derived from a base type then + /// return base type size. + uint64_t getOriginalTypeSize() const; + /// dump - print derived type. + void dump() const; + + /// replaceAllUsesWith - Replace all uses of debug info referenced by + /// this descriptor. After this completes, the current debug info value + /// is erased. + void replaceAllUsesWith(DIDescriptor &D); + }; + + /// DICompositeType - This descriptor holds a type that can refer to multiple + /// other types, like a function or struct. + /// FIXME: Why is this a DIDerivedType?? + class DICompositeType : public DIDerivedType { + public: + explicit DICompositeType(MDNode *N = 0) + : DIDerivedType(N, true, true) { + if (N && !isCompositeType()) + DbgNode = 0; + } + + DIArray getTypeArray() const { return getFieldAs(10); } + unsigned getRunTimeLang() const { return getUnsignedField(11); } + + /// Verify - Verify that a composite type descriptor is well formed. + bool Verify() const; + + /// dump - print composite type. + void dump() const; + }; + + /// DIGlobal - This is a common class for global variables and subprograms. + class DIGlobal : public DIDescriptor { + protected: + explicit DIGlobal(MDNode *N, unsigned RequiredTag) + : DIDescriptor(N, RequiredTag) {} + + public: + virtual ~DIGlobal() {} + + DIDescriptor getContext() const { return getDescriptorField(2); } + StringRef getName() const { return getStringField(3); } + StringRef getDisplayName() const { return getStringField(4); } + StringRef getLinkageName() const { return getStringField(5); } + DICompileUnit getCompileUnit() const{ return getFieldAs(6); } + unsigned getLineNumber() const { return getUnsignedField(7); } + DIType getType() const { return getFieldAs(8); } + + /// isLocalToUnit - Return true if this subprogram is local to the current + /// compile unit, like 'static' in C. + unsigned isLocalToUnit() const { return getUnsignedField(9); } + unsigned isDefinition() const { return getUnsignedField(10); } + + /// dump - print global. + void dump() const; + }; + + /// DISubprogram - This is a wrapper for a subprogram (e.g. a function). + class DISubprogram : public DIScope { + public: + explicit DISubprogram(MDNode *N = 0) : DIScope(N) { + if (DbgNode && !isSubprogram()) + DbgNode = 0; + } + + DIDescriptor getContext() const { return getDescriptorField(2); } + StringRef getName() const { return getStringField(3); } + StringRef getDisplayName() const { return getStringField(4); } + StringRef getLinkageName() const { return getStringField(5); } + DICompileUnit getCompileUnit() const{ return getFieldAs(6); } + unsigned getLineNumber() const { return getUnsignedField(7); } + DICompositeType getType() const { return getFieldAs(8); } + + /// getReturnTypeName - Subprogram return types are encoded either as + /// DIType or as DICompositeType. + StringRef getReturnTypeName() const { + DICompositeType DCT(getFieldAs(8)); + if (!DCT.isNull()) { + DIArray A = DCT.getTypeArray(); + DIType T(A.getElement(0).getNode()); + return T.getName(); + } + DIType T(getFieldAs(8)); + return T.getName(); + } + + /// isLocalToUnit - Return true if this subprogram is local to the current + /// compile unit, like 'static' in C. + unsigned isLocalToUnit() const { return getUnsignedField(9); } + unsigned isDefinition() const { return getUnsignedField(10); } + StringRef getFilename() const { return getCompileUnit().getFilename();} + StringRef getDirectory() const { return getCompileUnit().getDirectory();} + + /// Verify - Verify that a subprogram descriptor is well formed. + bool Verify() const; + + /// dump - print subprogram. + void dump() const; + + /// describes - Return true if this subprogram provides debugging + /// information for the function F. + bool describes(const Function *F); + }; + + /// DIGlobalVariable - This is a wrapper for a global variable. + class DIGlobalVariable : public DIGlobal { + public: + explicit DIGlobalVariable(MDNode *N = 0) + : DIGlobal(N, dwarf::DW_TAG_variable) {} + + GlobalVariable *getGlobal() const { return getGlobalVariableField(11); } + + /// Verify - Verify that a global variable descriptor is well formed. + bool Verify() const; + + /// dump - print global variable. + void dump() const; + }; + + /// DIVariable - This is a wrapper for a variable (e.g. parameter, local, + /// global etc). + class DIVariable : public DIDescriptor { + public: + explicit DIVariable(MDNode *N = 0) + : DIDescriptor(N) { + if (DbgNode && !isVariable()) + DbgNode = 0; + } + + DIDescriptor getContext() const { return getDescriptorField(1); } + StringRef getName() const { return getStringField(2); } + DICompileUnit getCompileUnit() const{ return getFieldAs(3); } + unsigned getLineNumber() const { return getUnsignedField(4); } + DIType getType() const { return getFieldAs(5); } + + + /// Verify - Verify that a variable descriptor is well formed. + bool Verify() const; + + /// HasComplexAddr - Return true if the variable has a complex address. + bool hasComplexAddress() const { + return getNumAddrElements() > 0; + } + + unsigned getNumAddrElements() const { return DbgNode->getNumElements()-6; } + + uint64_t getAddrElement(unsigned Idx) const { + return getUInt64Field(Idx+6); + } + + /// isBlockByrefVariable - Return true if the variable was declared as + /// a "__block" variable (Apple Blocks). + bool isBlockByrefVariable() const { + return getType().isBlockByrefStruct(); + } + + /// dump - print variable. + void dump() const; + }; + + /// DILexicalBlock - This is a wrapper for a lexical block. + class DILexicalBlock : public DIScope { + public: + explicit DILexicalBlock(MDNode *N = 0) : DIScope(N) { + if (DbgNode && !isLexicalBlock()) + DbgNode = 0; + } + DIScope getContext() const { return getFieldAs(1); } + StringRef getDirectory() const { return getContext().getDirectory(); } + StringRef getFilename() const { return getContext().getFilename(); } + }; + + /// DILocation - This object holds location information. This object + /// is not associated with any DWARF tag. + class DILocation : public DIDescriptor { + public: + explicit DILocation(MDNode *N) : DIDescriptor(N) { ; } + + unsigned getLineNumber() const { return getUnsignedField(0); } + unsigned getColumnNumber() const { return getUnsignedField(1); } + DIScope getScope() const { return getFieldAs(2); } + DILocation getOrigLocation() const { return getFieldAs(3); } + StringRef getFilename() const { return getScope().getFilename(); } + StringRef getDirectory() const { return getScope().getDirectory(); } + }; + + /// DIFactory - This object assists with the construction of the various + /// descriptors. + class DIFactory { + Module &M; + LLVMContext& VMContext; + + const Type *EmptyStructPtr; // "{}*". + Function *DeclareFn; // llvm.dbg.declare + + DIFactory(const DIFactory &); // DO NOT IMPLEMENT + void operator=(const DIFactory&); // DO NOT IMPLEMENT + public: + enum ComplexAddrKind { OpPlus=1, OpDeref }; + + explicit DIFactory(Module &m); + + /// GetOrCreateArray - Create an descriptor for an array of descriptors. + /// This implicitly uniques the arrays created. + DIArray GetOrCreateArray(DIDescriptor *Tys, unsigned NumTys); + + /// GetOrCreateSubrange - Create a descriptor for a value range. This + /// implicitly uniques the values returned. + DISubrange GetOrCreateSubrange(int64_t Lo, int64_t Hi); + + /// CreateCompileUnit - Create a new descriptor for the specified compile + /// unit. + DICompileUnit CreateCompileUnit(unsigned LangID, + StringRef Filename, + StringRef Directory, + StringRef Producer, + bool isMain = false, + bool isOptimized = false, + StringRef Flags = "", + unsigned RunTimeVer = 0); + + /// CreateEnumerator - Create a single enumerator value. + DIEnumerator CreateEnumerator(StringRef Name, uint64_t Val); + + /// CreateBasicType - Create a basic type like int, float, etc. + DIBasicType CreateBasicType(DIDescriptor Context, StringRef Name, + DICompileUnit CompileUnit, unsigned LineNumber, + uint64_t SizeInBits, uint64_t AlignInBits, + uint64_t OffsetInBits, unsigned Flags, + unsigned Encoding); + + /// CreateBasicType - Create a basic type like int, float, etc. + DIBasicType CreateBasicTypeEx(DIDescriptor Context, StringRef Name, + DICompileUnit CompileUnit, unsigned LineNumber, + Constant *SizeInBits, Constant *AlignInBits, + Constant *OffsetInBits, unsigned Flags, + unsigned Encoding); + + /// CreateDerivedType - Create a derived type like const qualified type, + /// pointer, typedef, etc. + DIDerivedType CreateDerivedType(unsigned Tag, DIDescriptor Context, + StringRef Name, + DICompileUnit CompileUnit, + unsigned LineNumber, + uint64_t SizeInBits, uint64_t AlignInBits, + uint64_t OffsetInBits, unsigned Flags, + DIType DerivedFrom); + + /// CreateDerivedType - Create a derived type like const qualified type, + /// pointer, typedef, etc. + DIDerivedType CreateDerivedTypeEx(unsigned Tag, DIDescriptor Context, + StringRef Name, + DICompileUnit CompileUnit, + unsigned LineNumber, + Constant *SizeInBits, Constant *AlignInBits, + Constant *OffsetInBits, unsigned Flags, + DIType DerivedFrom); + + /// CreateCompositeType - Create a composite type like array, struct, etc. + DICompositeType CreateCompositeType(unsigned Tag, DIDescriptor Context, + StringRef Name, + DICompileUnit CompileUnit, + unsigned LineNumber, + uint64_t SizeInBits, + uint64_t AlignInBits, + uint64_t OffsetInBits, unsigned Flags, + DIType DerivedFrom, + DIArray Elements, + unsigned RunTimeLang = 0); + + /// CreateCompositeType - Create a composite type like array, struct, etc. + DICompositeType CreateCompositeTypeEx(unsigned Tag, DIDescriptor Context, + StringRef Name, + DICompileUnit CompileUnit, + unsigned LineNumber, + Constant *SizeInBits, + Constant *AlignInBits, + Constant *OffsetInBits, unsigned Flags, + DIType DerivedFrom, + DIArray Elements, + unsigned RunTimeLang = 0); + + /// CreateSubprogram - Create a new descriptor for the specified subprogram. + /// See comments in DISubprogram for descriptions of these fields. + DISubprogram CreateSubprogram(DIDescriptor Context, StringRef Name, + StringRef DisplayName, + StringRef LinkageName, + DICompileUnit CompileUnit, unsigned LineNo, + DIType Type, bool isLocalToUnit, + bool isDefinition); + + /// CreateGlobalVariable - Create a new descriptor for the specified global. + DIGlobalVariable + CreateGlobalVariable(DIDescriptor Context, StringRef Name, + StringRef DisplayName, + StringRef LinkageName, + DICompileUnit CompileUnit, + unsigned LineNo, DIType Type, bool isLocalToUnit, + bool isDefinition, llvm::GlobalVariable *GV); + + /// CreateVariable - Create a new descriptor for the specified variable. + DIVariable CreateVariable(unsigned Tag, DIDescriptor Context, + StringRef Name, + DICompileUnit CompileUnit, unsigned LineNo, + DIType Type); + + /// CreateComplexVariable - Create a new descriptor for the specified + /// variable which has a complex address expression for its address. + DIVariable CreateComplexVariable(unsigned Tag, DIDescriptor Context, + const std::string &Name, + DICompileUnit CompileUnit, unsigned LineNo, + DIType Type, + SmallVector &addr); + + /// CreateLexicalBlock - This creates a descriptor for a lexical block + /// with the specified parent context. + DILexicalBlock CreateLexicalBlock(DIDescriptor Context); + + /// CreateLocation - Creates a debug info location. + DILocation CreateLocation(unsigned LineNo, unsigned ColumnNo, + DIScope S, DILocation OrigLoc); + + /// CreateLocation - Creates a debug info location. + DILocation CreateLocation(unsigned LineNo, unsigned ColumnNo, + DIScope S, MDNode *OrigLoc = 0); + + /// InsertDeclare - Insert a new llvm.dbg.declare intrinsic call. + Instruction *InsertDeclare(llvm::Value *Storage, DIVariable D, + BasicBlock *InsertAtEnd); + + /// InsertDeclare - Insert a new llvm.dbg.declare intrinsic call. + Instruction *InsertDeclare(llvm::Value *Storage, DIVariable D, + Instruction *InsertBefore); + + private: + Constant *GetTagConstant(unsigned TAG); + }; + + /// Finds the stoppoint coressponding to this instruction, that is the + /// stoppoint that dominates this instruction + const DbgStopPointInst *findStopPoint(const Instruction *Inst); + + /// Finds the stoppoint corresponding to first real (non-debug intrinsic) + /// instruction in this Basic Block, and returns the stoppoint for it. + const DbgStopPointInst *findBBStopPoint(const BasicBlock *BB); + + /// Finds the dbg.declare intrinsic corresponding to this value if any. + /// It looks through pointer casts too. + const DbgDeclareInst *findDbgDeclare(const Value *V, bool stripCasts = true); + + /// Find the debug info descriptor corresponding to this global variable. + Value *findDbgGlobalDeclare(GlobalVariable *V); + +bool getLocationInfo(const Value *V, std::string &DisplayName, + std::string &Type, unsigned &LineNo, std::string &File, + std::string &Dir); + + /// isValidDebugInfoIntrinsic - Return true if SPI is a valid debug + /// info intrinsic. + bool isValidDebugInfoIntrinsic(DbgStopPointInst &SPI, + CodeGenOpt::Level OptLev); + + /// isValidDebugInfoIntrinsic - Return true if FSI is a valid debug + /// info intrinsic. + bool isValidDebugInfoIntrinsic(DbgFuncStartInst &FSI, + CodeGenOpt::Level OptLev); + + /// isValidDebugInfoIntrinsic - Return true if RSI is a valid debug + /// info intrinsic. + bool isValidDebugInfoIntrinsic(DbgRegionStartInst &RSI, + CodeGenOpt::Level OptLev); + + /// isValidDebugInfoIntrinsic - Return true if REI is a valid debug + /// info intrinsic. + bool isValidDebugInfoIntrinsic(DbgRegionEndInst &REI, + CodeGenOpt::Level OptLev); + + /// isValidDebugInfoIntrinsic - Return true if DI is a valid debug + /// info intrinsic. + bool isValidDebugInfoIntrinsic(DbgDeclareInst &DI, + CodeGenOpt::Level OptLev); + + /// ExtractDebugLocation - Extract debug location information + /// from llvm.dbg.stoppoint intrinsic. + DebugLoc ExtractDebugLocation(DbgStopPointInst &SPI, + DebugLocTracker &DebugLocInfo); + + /// ExtractDebugLocation - Extract debug location information + /// from DILocation. + DebugLoc ExtractDebugLocation(DILocation &Loc, + DebugLocTracker &DebugLocInfo); + + /// ExtractDebugLocation - Extract debug location information + /// from llvm.dbg.func_start intrinsic. + DebugLoc ExtractDebugLocation(DbgFuncStartInst &FSI, + DebugLocTracker &DebugLocInfo); + + /// getDISubprogram - Find subprogram that is enclosing this scope. + DISubprogram getDISubprogram(MDNode *Scope); + + /// getDICompositeType - Find underlying composite type. + DICompositeType getDICompositeType(DIType T); + + class DebugInfoFinder { + + public: + /// processModule - Process entire module and collect debug info + /// anchors. + void processModule(Module &M); + + private: + /// processType - Process DIType. + void processType(DIType DT); + + /// processLexicalBlock - Process DILexicalBlock. + void processLexicalBlock(DILexicalBlock LB); + + /// processSubprogram - Process DISubprogram. + void processSubprogram(DISubprogram SP); + + /// processDeclare - Process DbgDeclareInst. + void processDeclare(DbgDeclareInst *DDI); + + /// processLocation - Process DILocation. + void processLocation(DILocation Loc); + + /// addCompileUnit - Add compile unit into CUs. + bool addCompileUnit(DICompileUnit CU); + + /// addGlobalVariable - Add global variable into GVs. + bool addGlobalVariable(DIGlobalVariable DIG); + + // addSubprogram - Add subprgoram into SPs. + bool addSubprogram(DISubprogram SP); + + /// addType - Add type into Tys. + bool addType(DIType DT); + + public: + typedef SmallVector::iterator iterator; + iterator compile_unit_begin() { return CUs.begin(); } + iterator compile_unit_end() { return CUs.end(); } + iterator subprogram_begin() { return SPs.begin(); } + iterator subprogram_end() { return SPs.end(); } + iterator global_variable_begin() { return GVs.begin(); } + iterator global_variable_end() { return GVs.end(); } + iterator type_begin() { return TYs.begin(); } + iterator type_end() { return TYs.end(); } + + unsigned compile_unit_count() { return CUs.size(); } + unsigned global_variable_count() { return GVs.size(); } + unsigned subprogram_count() { return SPs.size(); } + unsigned type_count() { return TYs.size(); } + + private: + SmallVector CUs; // Compile Units + SmallVector SPs; // Subprograms + SmallVector GVs; // Global Variables; + SmallVector TYs; // Types + SmallPtrSet NodesSeen; + }; +} // end namespace llvm + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Analysis/DomPrinter.h b/libclamav/c++/llvm/include/llvm/Analysis/DomPrinter.h new file mode 100644 index 000000000..0ed289949 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Analysis/DomPrinter.h @@ -0,0 +1,30 @@ +//===-- DomPrinter.h - Dom printer external interface ------------*- 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 external functions that can be called to explicitly +// instantiate the dominance tree printer. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_DOMPRINTER_H +#define LLVM_ANALYSIS_DOMPRINTER_H + +namespace llvm { + class FunctionPass; + FunctionPass *createDomPrinterPass(); + FunctionPass *createDomOnlyPrinterPass(); + FunctionPass *createDomViewerPass(); + FunctionPass *createDomOnlyViewerPass(); + FunctionPass *createPostDomPrinterPass(); + FunctionPass *createPostDomOnlyPrinterPass(); + FunctionPass *createPostDomViewerPass(); + FunctionPass *createPostDomOnlyViewerPass(); +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Analysis/DominatorInternals.h b/libclamav/c++/llvm/include/llvm/Analysis/DominatorInternals.h new file mode 100644 index 000000000..cca0d502b --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Analysis/DominatorInternals.h @@ -0,0 +1,363 @@ +//=== llvm/Analysis/DominatorInternals.h - Dominator Calculation -*- C++ -*-==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_DOMINATOR_INTERNALS_H +#define LLVM_ANALYSIS_DOMINATOR_INTERNALS_H + +#include "llvm/Analysis/Dominators.h" +#include "llvm/ADT/SmallPtrSet.h" + +//===----------------------------------------------------------------------===// +// +// DominatorTree construction - This pass constructs immediate dominator +// information for a flow-graph based on the algorithm described in this +// document: +// +// A Fast Algorithm for Finding Dominators in a Flowgraph +// T. Lengauer & R. Tarjan, ACM TOPLAS July 1979, pgs 121-141. +// +// This implements both the O(n*ack(n)) and the O(n*log(n)) versions of EVAL and +// LINK, but it turns out that the theoretically slower O(n*log(n)) +// implementation is actually faster than the "efficient" algorithm (even for +// large CFGs) because the constant overheads are substantially smaller. The +// lower-complexity version can be enabled with the following #define: +// +#define BALANCE_IDOM_TREE 0 +// +//===----------------------------------------------------------------------===// + +namespace llvm { + +template +unsigned DFSPass(DominatorTreeBase& DT, + typename GraphT::NodeType* V, unsigned N) { + // This is more understandable as a recursive algorithm, but we can't use the + // recursive algorithm due to stack depth issues. Keep it here for + // documentation purposes. +#if 0 + InfoRec &VInfo = DT.Info[DT.Roots[i]]; + VInfo.DFSNum = VInfo.Semi = ++N; + VInfo.Label = V; + + Vertex.push_back(V); // Vertex[n] = V; + //Info[V].Ancestor = 0; // Ancestor[n] = 0 + //Info[V].Child = 0; // Child[v] = 0 + VInfo.Size = 1; // Size[v] = 1 + + for (succ_iterator SI = succ_begin(V), E = succ_end(V); SI != E; ++SI) { + InfoRec &SuccVInfo = DT.Info[*SI]; + if (SuccVInfo.Semi == 0) { + SuccVInfo.Parent = V; + N = DTDFSPass(DT, *SI, N); + } + } +#else + bool IsChilOfArtificialExit = (N != 0); + + std::vector > Worklist; + Worklist.push_back(std::make_pair(V, GraphT::child_begin(V))); + while (!Worklist.empty()) { + typename GraphT::NodeType* BB = Worklist.back().first; + typename GraphT::ChildIteratorType NextSucc = Worklist.back().second; + + typename DominatorTreeBase::InfoRec &BBInfo = + DT.Info[BB]; + + // First time we visited this BB? + if (NextSucc == GraphT::child_begin(BB)) { + BBInfo.DFSNum = BBInfo.Semi = ++N; + BBInfo.Label = BB; + + DT.Vertex.push_back(BB); // Vertex[n] = V; + //BBInfo[V].Ancestor = 0; // Ancestor[n] = 0 + //BBInfo[V].Child = 0; // Child[v] = 0 + BBInfo.Size = 1; // Size[v] = 1 + + if (IsChilOfArtificialExit) + BBInfo.Parent = 1; + + IsChilOfArtificialExit = false; + } + + // store the DFS number of the current BB - the reference to BBInfo might + // get invalidated when processing the successors. + unsigned BBDFSNum = BBInfo.DFSNum; + + // If we are done with this block, remove it from the worklist. + if (NextSucc == GraphT::child_end(BB)) { + Worklist.pop_back(); + continue; + } + + // Increment the successor number for the next time we get to it. + ++Worklist.back().second; + + // Visit the successor next, if it isn't already visited. + typename GraphT::NodeType* Succ = *NextSucc; + + typename DominatorTreeBase::InfoRec &SuccVInfo = + DT.Info[Succ]; + if (SuccVInfo.Semi == 0) { + SuccVInfo.Parent = BBDFSNum; + Worklist.push_back(std::make_pair(Succ, GraphT::child_begin(Succ))); + } + } +#endif + return N; +} + +template +void Compress(DominatorTreeBase& DT, + typename GraphT::NodeType *VIn) { + std::vector Work; + SmallPtrSet Visited; + typename DominatorTreeBase::InfoRec &VInVAInfo = + DT.Info[DT.Vertex[DT.Info[VIn].Ancestor]]; + + if (VInVAInfo.Ancestor != 0) + Work.push_back(VIn); + + while (!Work.empty()) { + typename GraphT::NodeType* V = Work.back(); + typename DominatorTreeBase::InfoRec &VInfo = + DT.Info[V]; + typename GraphT::NodeType* VAncestor = DT.Vertex[VInfo.Ancestor]; + typename DominatorTreeBase::InfoRec &VAInfo = + DT.Info[VAncestor]; + + // Process Ancestor first + if (Visited.insert(VAncestor) && + VAInfo.Ancestor != 0) { + Work.push_back(VAncestor); + continue; + } + Work.pop_back(); + + // Update VInfo based on Ancestor info + if (VAInfo.Ancestor == 0) + continue; + typename GraphT::NodeType* VAncestorLabel = VAInfo.Label; + typename GraphT::NodeType* VLabel = VInfo.Label; + if (DT.Info[VAncestorLabel].Semi < DT.Info[VLabel].Semi) + VInfo.Label = VAncestorLabel; + VInfo.Ancestor = VAInfo.Ancestor; + } +} + +template +typename GraphT::NodeType* Eval(DominatorTreeBase& DT, + typename GraphT::NodeType *V) { + typename DominatorTreeBase::InfoRec &VInfo = + DT.Info[V]; +#if !BALANCE_IDOM_TREE + // Higher-complexity but faster implementation + if (VInfo.Ancestor == 0) + return V; + Compress(DT, V); + return VInfo.Label; +#else + // Lower-complexity but slower implementation + if (VInfo.Ancestor == 0) + return VInfo.Label; + Compress(DT, V); + GraphT::NodeType* VLabel = VInfo.Label; + + GraphT::NodeType* VAncestorLabel = DT.Info[VInfo.Ancestor].Label; + if (DT.Info[VAncestorLabel].Semi >= DT.Info[VLabel].Semi) + return VLabel; + else + return VAncestorLabel; +#endif +} + +template +void Link(DominatorTreeBase& DT, + unsigned DFSNumV, typename GraphT::NodeType* W, + typename DominatorTreeBase::InfoRec &WInfo) { +#if !BALANCE_IDOM_TREE + // Higher-complexity but faster implementation + WInfo.Ancestor = DFSNumV; +#else + // Lower-complexity but slower implementation + GraphT::NodeType* WLabel = WInfo.Label; + unsigned WLabelSemi = DT.Info[WLabel].Semi; + GraphT::NodeType* S = W; + InfoRec *SInfo = &DT.Info[S]; + + GraphT::NodeType* SChild = SInfo->Child; + InfoRec *SChildInfo = &DT.Info[SChild]; + + while (WLabelSemi < DT.Info[SChildInfo->Label].Semi) { + GraphT::NodeType* SChildChild = SChildInfo->Child; + if (SInfo->Size+DT.Info[SChildChild].Size >= 2*SChildInfo->Size) { + SChildInfo->Ancestor = S; + SInfo->Child = SChild = SChildChild; + SChildInfo = &DT.Info[SChild]; + } else { + SChildInfo->Size = SInfo->Size; + S = SInfo->Ancestor = SChild; + SInfo = SChildInfo; + SChild = SChildChild; + SChildInfo = &DT.Info[SChild]; + } + } + + DominatorTreeBase::InfoRec &VInfo = DT.Info[V]; + SInfo->Label = WLabel; + + assert(V != W && "The optimization here will not work in this case!"); + unsigned WSize = WInfo.Size; + unsigned VSize = (VInfo.Size += WSize); + + if (VSize < 2*WSize) + std::swap(S, VInfo.Child); + + while (S) { + SInfo = &DT.Info[S]; + SInfo->Ancestor = V; + S = SInfo->Child; + } +#endif +} + +template +void Calculate(DominatorTreeBase::NodeType>& DT, + FuncT& F) { + typedef GraphTraits GraphT; + + unsigned N = 0; + bool MultipleRoots = (DT.Roots.size() > 1); + if (MultipleRoots) { + typename DominatorTreeBase::InfoRec &BBInfo = + DT.Info[NULL]; + BBInfo.DFSNum = BBInfo.Semi = ++N; + BBInfo.Label = NULL; + + DT.Vertex.push_back(NULL); // Vertex[n] = V; + //BBInfo[V].Ancestor = 0; // Ancestor[n] = 0 + //BBInfo[V].Child = 0; // Child[v] = 0 + BBInfo.Size = 1; // Size[v] = 1 + } + + // Step #1: Number blocks in depth-first order and initialize variables used + // in later stages of the algorithm. + for (unsigned i = 0, e = static_cast(DT.Roots.size()); + i != e; ++i) + N = DFSPass(DT, DT.Roots[i], N); + + // it might be that some blocks did not get a DFS number (e.g., blocks of + // infinite loops). In these cases an artificial exit node is required. + MultipleRoots |= (DT.isPostDominator() && N != F.size()); + + for (unsigned i = N; i >= 2; --i) { + typename GraphT::NodeType* W = DT.Vertex[i]; + typename DominatorTreeBase::InfoRec &WInfo = + DT.Info[W]; + + // Step #2: Calculate the semidominators of all vertices + bool HasChildOutsideDFS = false; + + // initialize the semi dominator to point to the parent node + WInfo.Semi = WInfo.Parent; + for (typename GraphTraits >::ChildIteratorType CI = + GraphTraits >::child_begin(W), + E = GraphTraits >::child_end(W); CI != E; ++CI) { + if (DT.Info.count(*CI)) { // Only if this predecessor is reachable! + unsigned SemiU = DT.Info[Eval(DT, *CI)].Semi; + if (SemiU < WInfo.Semi) + WInfo.Semi = SemiU; + } + else { + // if the child has no DFS number it is not post-dominated by any exit, + // and so is the current block. + HasChildOutsideDFS = true; + } + } + + // if some child has no DFS number it is not post-dominated by any exit, + // and so is the current block. + if (DT.isPostDominator() && HasChildOutsideDFS) + WInfo.Semi = 0; + + DT.Info[DT.Vertex[WInfo.Semi]].Bucket.push_back(W); + + typename GraphT::NodeType* WParent = DT.Vertex[WInfo.Parent]; + Link(DT, WInfo.Parent, W, WInfo); + + // Step #3: Implicitly define the immediate dominator of vertices + std::vector &WParentBucket = + DT.Info[WParent].Bucket; + while (!WParentBucket.empty()) { + typename GraphT::NodeType* V = WParentBucket.back(); + WParentBucket.pop_back(); + typename GraphT::NodeType* U = Eval(DT, V); + DT.IDoms[V] = DT.Info[U].Semi < DT.Info[V].Semi ? U : WParent; + } + } + + // Step #4: Explicitly define the immediate dominator of each vertex + for (unsigned i = 2; i <= N; ++i) { + typename GraphT::NodeType* W = DT.Vertex[i]; + typename GraphT::NodeType*& WIDom = DT.IDoms[W]; + if (WIDom != DT.Vertex[DT.Info[W].Semi]) + WIDom = DT.IDoms[WIDom]; + } + + if (DT.Roots.empty()) return; + + // Add a node for the root. This node might be the actual root, if there is + // one exit block, or it may be the virtual exit (denoted by (BasicBlock *)0) + // which postdominates all real exits if there are multiple exit blocks, or + // an infinite loop. + typename GraphT::NodeType* Root = !MultipleRoots ? DT.Roots[0] : 0; + + DT.DomTreeNodes[Root] = DT.RootNode = + new DomTreeNodeBase(Root, 0); + + // Loop over all of the reachable blocks in the function... + for (unsigned i = 2; i <= N; ++i) { + typename GraphT::NodeType* W = DT.Vertex[i]; + + DomTreeNodeBase *BBNode = DT.DomTreeNodes[W]; + if (BBNode) continue; // Haven't calculated this node yet? + + typename GraphT::NodeType* ImmDom = DT.getIDom(W); + + assert(ImmDom || DT.DomTreeNodes[NULL]); + + // Get or calculate the node for the immediate dominator + DomTreeNodeBase *IDomNode = + DT.getNodeForBlock(ImmDom); + + // Add a new tree node for this BasicBlock, and link it as a child of + // IDomNode + DomTreeNodeBase *C = + new DomTreeNodeBase(W, IDomNode); + DT.DomTreeNodes[W] = IDomNode->addChild(C); + } + + // Free temporary memory used to construct idom's + DT.IDoms.clear(); + DT.Info.clear(); + std::vector().swap(DT.Vertex); + + // FIXME: This does not work on PostDomTrees. It seems likely that this is + // due to an error in the algorithm for post-dominators. This really should + // be investigated and fixed at some point. + // DT.updateDFSNumbers(); + + // Start out with the DFS numbers being invalid. Let them be computed if + // demanded. + DT.DFSInfoValid = false; +} + +} + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Analysis/Dominators.h b/libclamav/c++/llvm/include/llvm/Analysis/Dominators.h new file mode 100644 index 000000000..2e149d59e --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Analysis/Dominators.h @@ -0,0 +1,1055 @@ +//===- llvm/Analysis/Dominators.h - Dominator Info Calculation --*- 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 the following classes: +// 1. DominatorTree: Represent dominators as an explicit tree structure. +// 2. DominanceFrontier: Calculate and hold the dominance frontier for a +// function. +// +// These data structures are listed in increasing order of complexity. It +// takes longer to calculate the dominator frontier, for example, than the +// DominatorTree mapping. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_DOMINATORS_H +#define LLVM_ANALYSIS_DOMINATORS_H + +#include "llvm/Pass.h" +#include "llvm/Function.h" +#include "llvm/Instructions.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/DepthFirstIterator.h" +#include "llvm/ADT/GraphTraits.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/Assembly/Writer.h" +#include "llvm/Support/CFG.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/raw_ostream.h" +#include +#include +#include + +namespace llvm { + +//===----------------------------------------------------------------------===// +/// DominatorBase - Base class that other, more interesting dominator analyses +/// inherit from. +/// +template +class DominatorBase { +protected: + std::vector Roots; + const bool IsPostDominators; + inline explicit DominatorBase(bool isPostDom) : + Roots(), IsPostDominators(isPostDom) {} +public: + + /// getRoots - Return the root blocks of the current CFG. This may include + /// multiple blocks if we are computing post dominators. For forward + /// dominators, this will always be a single block (the entry node). + /// + inline const std::vector &getRoots() const { return Roots; } + + /// isPostDominator - Returns true if analysis based of postdoms + /// + bool isPostDominator() const { return IsPostDominators; } +}; + + +//===----------------------------------------------------------------------===// +// DomTreeNode - Dominator Tree Node +template class DominatorTreeBase; +struct PostDominatorTree; +class MachineBasicBlock; + +template +class DomTreeNodeBase { + NodeT *TheBB; + DomTreeNodeBase *IDom; + std::vector *> Children; + int DFSNumIn, DFSNumOut; + + template friend class DominatorTreeBase; + friend struct PostDominatorTree; +public: + typedef typename std::vector *>::iterator iterator; + typedef typename std::vector *>::const_iterator + const_iterator; + + iterator begin() { return Children.begin(); } + iterator end() { return Children.end(); } + const_iterator begin() const { return Children.begin(); } + const_iterator end() const { return Children.end(); } + + NodeT *getBlock() const { return TheBB; } + DomTreeNodeBase *getIDom() const { return IDom; } + const std::vector*> &getChildren() const { + return Children; + } + + DomTreeNodeBase(NodeT *BB, DomTreeNodeBase *iDom) + : TheBB(BB), IDom(iDom), DFSNumIn(-1), DFSNumOut(-1) { } + + DomTreeNodeBase *addChild(DomTreeNodeBase *C) { + Children.push_back(C); + return C; + } + + size_t getNumChildren() const { + return Children.size(); + } + + void clearAllChildren() { + Children.clear(); + } + + bool compare(DomTreeNodeBase *Other) { + if (getNumChildren() != Other->getNumChildren()) + return true; + + SmallPtrSet OtherChildren; + for(iterator I = Other->begin(), E = Other->end(); I != E; ++I) { + NodeT *Nd = (*I)->getBlock(); + OtherChildren.insert(Nd); + } + + for(iterator I = begin(), E = end(); I != E; ++I) { + NodeT *N = (*I)->getBlock(); + if (OtherChildren.count(N) == 0) + return true; + } + return false; + } + + void setIDom(DomTreeNodeBase *NewIDom) { + assert(IDom && "No immediate dominator?"); + if (IDom != NewIDom) { + typename std::vector*>::iterator I = + std::find(IDom->Children.begin(), IDom->Children.end(), this); + assert(I != IDom->Children.end() && + "Not in immediate dominator children set!"); + // I am no longer your child... + IDom->Children.erase(I); + + // Switch to new dominator + IDom = NewIDom; + IDom->Children.push_back(this); + } + } + + /// getDFSNumIn/getDFSNumOut - These are an internal implementation detail, do + /// not call them. + unsigned getDFSNumIn() const { return DFSNumIn; } + unsigned getDFSNumOut() const { return DFSNumOut; } +private: + // Return true if this node is dominated by other. Use this only if DFS info + // is valid. + bool DominatedBy(const DomTreeNodeBase *other) const { + return this->DFSNumIn >= other->DFSNumIn && + this->DFSNumOut <= other->DFSNumOut; + } +}; + +EXTERN_TEMPLATE_INSTANTIATION(class DomTreeNodeBase); +EXTERN_TEMPLATE_INSTANTIATION(class DomTreeNodeBase); + +template +static raw_ostream &operator<<(raw_ostream &o, + const DomTreeNodeBase *Node) { + if (Node->getBlock()) + WriteAsOperand(o, Node->getBlock(), false); + else + o << " <>"; + + o << " {" << Node->getDFSNumIn() << "," << Node->getDFSNumOut() << "}"; + + return o << "\n"; +} + +template +static void PrintDomTree(const DomTreeNodeBase *N, raw_ostream &o, + unsigned Lev) { + o.indent(2*Lev) << "[" << Lev << "] " << N; + for (typename DomTreeNodeBase::const_iterator I = N->begin(), + E = N->end(); I != E; ++I) + PrintDomTree(*I, o, Lev+1); +} + +typedef DomTreeNodeBase DomTreeNode; + +//===----------------------------------------------------------------------===// +/// DominatorTree - Calculate the immediate dominator tree for a function. +/// + +template +void Calculate(DominatorTreeBase::NodeType>& DT, + FuncT& F); + +template +class DominatorTreeBase : public DominatorBase { +protected: + typedef DenseMap*> DomTreeNodeMapType; + DomTreeNodeMapType DomTreeNodes; + DomTreeNodeBase *RootNode; + + bool DFSInfoValid; + unsigned int SlowQueries; + // Information record used during immediate dominators computation. + struct InfoRec { + unsigned DFSNum; + unsigned Semi; + unsigned Size; + NodeT *Label, *Child; + unsigned Parent, Ancestor; + + std::vector Bucket; + + InfoRec() : DFSNum(0), Semi(0), Size(0), Label(0), Child(0), Parent(0), + Ancestor(0) {} + }; + + DenseMap IDoms; + + // Vertex - Map the DFS number to the BasicBlock* + std::vector Vertex; + + // Info - Collection of information used during the computation of idoms. + DenseMap Info; + + void reset() { + for (typename DomTreeNodeMapType::iterator I = this->DomTreeNodes.begin(), + E = DomTreeNodes.end(); I != E; ++I) + delete I->second; + DomTreeNodes.clear(); + IDoms.clear(); + this->Roots.clear(); + Vertex.clear(); + RootNode = 0; + } + + // NewBB is split and now it has one successor. Update dominator tree to + // reflect this change. + template + void Split(DominatorTreeBase& DT, + typename GraphT::NodeType* NewBB) { + assert(std::distance(GraphT::child_begin(NewBB), GraphT::child_end(NewBB)) == 1 + && "NewBB should have a single successor!"); + typename GraphT::NodeType* NewBBSucc = *GraphT::child_begin(NewBB); + + std::vector PredBlocks; + for (typename GraphTraits >::ChildIteratorType PI = + GraphTraits >::child_begin(NewBB), + PE = GraphTraits >::child_end(NewBB); PI != PE; ++PI) + PredBlocks.push_back(*PI); + + assert(!PredBlocks.empty() && "No predblocks??"); + + bool NewBBDominatesNewBBSucc = true; + for (typename GraphTraits >::ChildIteratorType PI = + GraphTraits >::child_begin(NewBBSucc), + E = GraphTraits >::child_end(NewBBSucc); PI != E; ++PI) + if (*PI != NewBB && !DT.dominates(NewBBSucc, *PI) && + DT.isReachableFromEntry(*PI)) { + NewBBDominatesNewBBSucc = false; + break; + } + + // Find NewBB's immediate dominator and create new dominator tree node for + // NewBB. + NodeT *NewBBIDom = 0; + unsigned i = 0; + for (i = 0; i < PredBlocks.size(); ++i) + if (DT.isReachableFromEntry(PredBlocks[i])) { + NewBBIDom = PredBlocks[i]; + break; + } + + // It's possible that none of the predecessors of NewBB are reachable; + // in that case, NewBB itself is unreachable, so nothing needs to be + // changed. + if (!NewBBIDom) + return; + + for (i = i + 1; i < PredBlocks.size(); ++i) { + if (DT.isReachableFromEntry(PredBlocks[i])) + NewBBIDom = DT.findNearestCommonDominator(NewBBIDom, PredBlocks[i]); + } + + // Create the new dominator tree node... and set the idom of NewBB. + DomTreeNodeBase *NewBBNode = DT.addNewBlock(NewBB, NewBBIDom); + + // If NewBB strictly dominates other blocks, then it is now the immediate + // dominator of NewBBSucc. Update the dominator tree as appropriate. + if (NewBBDominatesNewBBSucc) { + DomTreeNodeBase *NewBBSuccNode = DT.getNode(NewBBSucc); + DT.changeImmediateDominator(NewBBSuccNode, NewBBNode); + } + } + +public: + explicit DominatorTreeBase(bool isPostDom) + : DominatorBase(isPostDom), DFSInfoValid(false), SlowQueries(0) {} + virtual ~DominatorTreeBase() { reset(); } + + // FIXME: Should remove this + virtual bool runOnFunction(Function &F) { return false; } + + /// compare - Return false if the other dominator tree base matches this + /// dominator tree base. Otherwise return true. + bool compare(DominatorTreeBase &Other) const { + + const DomTreeNodeMapType &OtherDomTreeNodes = Other.DomTreeNodes; + if (DomTreeNodes.size() != OtherDomTreeNodes.size()) + return true; + + for (typename DomTreeNodeMapType::const_iterator + I = this->DomTreeNodes.begin(), + E = this->DomTreeNodes.end(); I != E; ++I) { + NodeT *BB = I->first; + typename DomTreeNodeMapType::const_iterator OI = OtherDomTreeNodes.find(BB); + if (OI == OtherDomTreeNodes.end()) + return true; + + DomTreeNodeBase* MyNd = I->second; + DomTreeNodeBase* OtherNd = OI->second; + + if (MyNd->compare(OtherNd)) + return true; + } + + return false; + } + + virtual void releaseMemory() { reset(); } + + /// getNode - return the (Post)DominatorTree node for the specified basic + /// block. This is the same as using operator[] on this class. + /// + inline DomTreeNodeBase *getNode(NodeT *BB) const { + typename DomTreeNodeMapType::const_iterator I = DomTreeNodes.find(BB); + return I != DomTreeNodes.end() ? I->second : 0; + } + + /// getRootNode - This returns the entry node for the CFG of the function. If + /// this tree represents the post-dominance relations for a function, however, + /// this root may be a node with the block == NULL. This is the case when + /// there are multiple exit nodes from a particular function. Consumers of + /// post-dominance information must be capable of dealing with this + /// possibility. + /// + DomTreeNodeBase *getRootNode() { return RootNode; } + const DomTreeNodeBase *getRootNode() const { return RootNode; } + + /// properlyDominates - Returns true iff this dominates N and this != N. + /// Note that this is not a constant time operation! + /// + bool properlyDominates(const DomTreeNodeBase *A, + const DomTreeNodeBase *B) const { + if (A == 0 || B == 0) return false; + return dominatedBySlowTreeWalk(A, B); + } + + inline bool properlyDominates(NodeT *A, NodeT *B) { + return properlyDominates(getNode(A), getNode(B)); + } + + bool dominatedBySlowTreeWalk(const DomTreeNodeBase *A, + const DomTreeNodeBase *B) const { + const DomTreeNodeBase *IDom; + if (A == 0 || B == 0) return false; + while ((IDom = B->getIDom()) != 0 && IDom != A && IDom != B) + B = IDom; // Walk up the tree + return IDom != 0; + } + + + /// isReachableFromEntry - Return true if A is dominated by the entry + /// block of the function containing it. + bool isReachableFromEntry(NodeT* A) { + assert (!this->isPostDominator() + && "This is not implemented for post dominators"); + return dominates(&A->getParent()->front(), A); + } + + /// dominates - Returns true iff A dominates B. Note that this is not a + /// constant time operation! + /// + inline bool dominates(const DomTreeNodeBase *A, + const DomTreeNodeBase *B) { + if (B == A) + return true; // A node trivially dominates itself. + + if (A == 0 || B == 0) + return false; + + if (DFSInfoValid) + return B->DominatedBy(A); + + // If we end up with too many slow queries, just update the + // DFS numbers on the theory that we are going to keep querying. + SlowQueries++; + if (SlowQueries > 32) { + updateDFSNumbers(); + return B->DominatedBy(A); + } + + return dominatedBySlowTreeWalk(A, B); + } + + inline bool dominates(const NodeT *A, const NodeT *B) { + if (A == B) + return true; + + // Cast away the const qualifiers here. This is ok since + // this function doesn't actually return the values returned + // from getNode. + return dominates(getNode(const_cast(A)), + getNode(const_cast(B))); + } + + NodeT *getRoot() const { + assert(this->Roots.size() == 1 && "Should always have entry node!"); + return this->Roots[0]; + } + + /// findNearestCommonDominator - Find nearest common dominator basic block + /// for basic block A and B. If there is no such block then return NULL. + NodeT *findNearestCommonDominator(NodeT *A, NodeT *B) { + + assert (!this->isPostDominator() + && "This is not implemented for post dominators"); + assert (A->getParent() == B->getParent() + && "Two blocks are not in same function"); + + // If either A or B is a entry block then it is nearest common dominator. + NodeT &Entry = A->getParent()->front(); + if (A == &Entry || B == &Entry) + return &Entry; + + // If B dominates A then B is nearest common dominator. + if (dominates(B, A)) + return B; + + // If A dominates B then A is nearest common dominator. + if (dominates(A, B)) + return A; + + DomTreeNodeBase *NodeA = getNode(A); + DomTreeNodeBase *NodeB = getNode(B); + + // Collect NodeA dominators set. + SmallPtrSet*, 16> NodeADoms; + NodeADoms.insert(NodeA); + DomTreeNodeBase *IDomA = NodeA->getIDom(); + while (IDomA) { + NodeADoms.insert(IDomA); + IDomA = IDomA->getIDom(); + } + + // Walk NodeB immediate dominators chain and find common dominator node. + DomTreeNodeBase *IDomB = NodeB->getIDom(); + while(IDomB) { + if (NodeADoms.count(IDomB) != 0) + return IDomB->getBlock(); + + IDomB = IDomB->getIDom(); + } + + return NULL; + } + + //===--------------------------------------------------------------------===// + // API to update (Post)DominatorTree information based on modifications to + // the CFG... + + /// addNewBlock - Add a new node to the dominator tree information. This + /// creates a new node as a child of DomBB dominator node,linking it into + /// the children list of the immediate dominator. + DomTreeNodeBase *addNewBlock(NodeT *BB, NodeT *DomBB) { + assert(getNode(BB) == 0 && "Block already in dominator tree!"); + DomTreeNodeBase *IDomNode = getNode(DomBB); + assert(IDomNode && "Not immediate dominator specified for block!"); + DFSInfoValid = false; + return DomTreeNodes[BB] = + IDomNode->addChild(new DomTreeNodeBase(BB, IDomNode)); + } + + /// changeImmediateDominator - This method is used to update the dominator + /// tree information when a node's immediate dominator changes. + /// + void changeImmediateDominator(DomTreeNodeBase *N, + DomTreeNodeBase *NewIDom) { + assert(N && NewIDom && "Cannot change null node pointers!"); + DFSInfoValid = false; + N->setIDom(NewIDom); + } + + void changeImmediateDominator(NodeT *BB, NodeT *NewBB) { + changeImmediateDominator(getNode(BB), getNode(NewBB)); + } + + /// eraseNode - Removes a node from the dominator tree. Block must not + /// domiante any other blocks. Removes node from its immediate dominator's + /// children list. Deletes dominator node associated with basic block BB. + void eraseNode(NodeT *BB) { + DomTreeNodeBase *Node = getNode(BB); + assert (Node && "Removing node that isn't in dominator tree."); + assert (Node->getChildren().empty() && "Node is not a leaf node."); + + // Remove node from immediate dominator's children list. + DomTreeNodeBase *IDom = Node->getIDom(); + if (IDom) { + typename std::vector*>::iterator I = + std::find(IDom->Children.begin(), IDom->Children.end(), Node); + assert(I != IDom->Children.end() && + "Not in immediate dominator children set!"); + // I am no longer your child... + IDom->Children.erase(I); + } + + DomTreeNodes.erase(BB); + delete Node; + } + + /// removeNode - Removes a node from the dominator tree. Block must not + /// dominate any other blocks. Invalidates any node pointing to removed + /// block. + void removeNode(NodeT *BB) { + assert(getNode(BB) && "Removing node that isn't in dominator tree."); + DomTreeNodes.erase(BB); + } + + /// splitBlock - BB is split and now it has one successor. Update dominator + /// tree to reflect this change. + void splitBlock(NodeT* NewBB) { + if (this->IsPostDominators) + this->Split, GraphTraits > >(*this, NewBB); + else + this->Split >(*this, NewBB); + } + + /// print - Convert to human readable form + /// + void print(raw_ostream &o) const { + o << "=============================--------------------------------\n"; + if (this->isPostDominator()) + o << "Inorder PostDominator Tree: "; + else + o << "Inorder Dominator Tree: "; + if (this->DFSInfoValid) + o << "DFSNumbers invalid: " << SlowQueries << " slow queries."; + o << "\n"; + + // The postdom tree can have a null root if there are no returns. + if (getRootNode()) + PrintDomTree(getRootNode(), o, 1); + } + +protected: + template + friend void Compress(DominatorTreeBase& DT, + typename GraphT::NodeType* VIn); + + template + friend typename GraphT::NodeType* Eval( + DominatorTreeBase& DT, + typename GraphT::NodeType* V); + + template + friend void Link(DominatorTreeBase& DT, + unsigned DFSNumV, typename GraphT::NodeType* W, + typename DominatorTreeBase::InfoRec &WInfo); + + template + friend unsigned DFSPass(DominatorTreeBase& DT, + typename GraphT::NodeType* V, + unsigned N); + + template + friend void Calculate(DominatorTreeBase::NodeType>& DT, + FuncT& F); + + /// updateDFSNumbers - Assign In and Out numbers to the nodes while walking + /// dominator tree in dfs order. + void updateDFSNumbers() { + unsigned DFSNum = 0; + + SmallVector*, + typename DomTreeNodeBase::iterator>, 32> WorkStack; + + for (unsigned i = 0, e = (unsigned)this->Roots.size(); i != e; ++i) { + DomTreeNodeBase *ThisRoot = getNode(this->Roots[i]); + WorkStack.push_back(std::make_pair(ThisRoot, ThisRoot->begin())); + ThisRoot->DFSNumIn = DFSNum++; + + while (!WorkStack.empty()) { + DomTreeNodeBase *Node = WorkStack.back().first; + typename DomTreeNodeBase::iterator ChildIt = + WorkStack.back().second; + + // If we visited all of the children of this node, "recurse" back up the + // stack setting the DFOutNum. + if (ChildIt == Node->end()) { + Node->DFSNumOut = DFSNum++; + WorkStack.pop_back(); + } else { + // Otherwise, recursively visit this child. + DomTreeNodeBase *Child = *ChildIt; + ++WorkStack.back().second; + + WorkStack.push_back(std::make_pair(Child, Child->begin())); + Child->DFSNumIn = DFSNum++; + } + } + } + + SlowQueries = 0; + DFSInfoValid = true; + } + + DomTreeNodeBase *getNodeForBlock(NodeT *BB) { + typename DomTreeNodeMapType::iterator I = this->DomTreeNodes.find(BB); + if (I != this->DomTreeNodes.end() && I->second) + return I->second; + + // Haven't calculated this node yet? Get or calculate the node for the + // immediate dominator. + NodeT *IDom = getIDom(BB); + + assert(IDom || this->DomTreeNodes[NULL]); + DomTreeNodeBase *IDomNode = getNodeForBlock(IDom); + + // Add a new tree node for this BasicBlock, and link it as a child of + // IDomNode + DomTreeNodeBase *C = new DomTreeNodeBase(BB, IDomNode); + return this->DomTreeNodes[BB] = IDomNode->addChild(C); + } + + inline NodeT *getIDom(NodeT *BB) const { + typename DenseMap::const_iterator I = IDoms.find(BB); + return I != IDoms.end() ? I->second : 0; + } + + inline void addRoot(NodeT* BB) { + this->Roots.push_back(BB); + } + +public: + /// recalculate - compute a dominator tree for the given function + template + void recalculate(FT& F) { + if (!this->IsPostDominators) { + reset(); + + // Initialize roots + this->Roots.push_back(&F.front()); + this->IDoms[&F.front()] = 0; + this->DomTreeNodes[&F.front()] = 0; + this->Vertex.push_back(0); + + Calculate(*this, F); + + updateDFSNumbers(); + } else { + reset(); // Reset from the last time we were run... + + // Initialize the roots list + for (typename FT::iterator I = F.begin(), E = F.end(); I != E; ++I) { + if (std::distance(GraphTraits::child_begin(I), + GraphTraits::child_end(I)) == 0) + addRoot(I); + + // Prepopulate maps so that we don't get iterator invalidation issues later. + this->IDoms[I] = 0; + this->DomTreeNodes[I] = 0; + } + + this->Vertex.push_back(0); + + Calculate >(*this, F); + } + } +}; + +EXTERN_TEMPLATE_INSTANTIATION(class DominatorTreeBase); + +//===------------------------------------- +/// DominatorTree Class - Concrete subclass of DominatorTreeBase that is used to +/// compute a normal dominator tree. +/// +class DominatorTree : public FunctionPass { +public: + static char ID; // Pass ID, replacement for typeid + DominatorTreeBase* DT; + + DominatorTree() : FunctionPass(&ID) { + DT = new DominatorTreeBase(false); + } + + ~DominatorTree() { + DT->releaseMemory(); + delete DT; + } + + DominatorTreeBase& getBase() { return *DT; } + + /// getRoots - Return the root blocks of the current CFG. This may include + /// multiple blocks if we are computing post dominators. For forward + /// dominators, this will always be a single block (the entry node). + /// + inline const std::vector &getRoots() const { + return DT->getRoots(); + } + + inline BasicBlock *getRoot() const { + return DT->getRoot(); + } + + inline DomTreeNode *getRootNode() const { + return DT->getRootNode(); + } + + /// compare - Return false if the other dominator tree matches this + /// dominator tree. Otherwise return true. + inline bool compare(DominatorTree &Other) const { + DomTreeNode *R = getRootNode(); + DomTreeNode *OtherR = Other.getRootNode(); + + if (!R || !OtherR || R->getBlock() != OtherR->getBlock()) + return true; + + if (DT->compare(Other.getBase())) + return true; + + return false; + } + + virtual bool runOnFunction(Function &F); + + virtual void verifyAnalysis() const; + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + } + + inline bool dominates(DomTreeNode* A, DomTreeNode* B) const { + return DT->dominates(A, B); + } + + inline bool dominates(const BasicBlock* A, const BasicBlock* B) const { + return DT->dominates(A, B); + } + + // dominates - Return true if A dominates B. This performs the + // special checks necessary if A and B are in the same basic block. + bool dominates(const Instruction *A, const Instruction *B) const; + + bool properlyDominates(const DomTreeNode *A, const DomTreeNode *B) const { + return DT->properlyDominates(A, B); + } + + bool properlyDominates(BasicBlock *A, BasicBlock *B) const { + return DT->properlyDominates(A, B); + } + + /// findNearestCommonDominator - Find nearest common dominator basic block + /// for basic block A and B. If there is no such block then return NULL. + inline BasicBlock *findNearestCommonDominator(BasicBlock *A, BasicBlock *B) { + return DT->findNearestCommonDominator(A, B); + } + + inline DomTreeNode *operator[](BasicBlock *BB) const { + return DT->getNode(BB); + } + + /// getNode - return the (Post)DominatorTree node for the specified basic + /// block. This is the same as using operator[] on this class. + /// + inline DomTreeNode *getNode(BasicBlock *BB) const { + return DT->getNode(BB); + } + + /// addNewBlock - Add a new node to the dominator tree information. This + /// creates a new node as a child of DomBB dominator node,linking it into + /// the children list of the immediate dominator. + inline DomTreeNode *addNewBlock(BasicBlock *BB, BasicBlock *DomBB) { + return DT->addNewBlock(BB, DomBB); + } + + /// changeImmediateDominator - This method is used to update the dominator + /// tree information when a node's immediate dominator changes. + /// + inline void changeImmediateDominator(BasicBlock *N, BasicBlock* NewIDom) { + DT->changeImmediateDominator(N, NewIDom); + } + + inline void changeImmediateDominator(DomTreeNode *N, DomTreeNode* NewIDom) { + DT->changeImmediateDominator(N, NewIDom); + } + + /// eraseNode - Removes a node from the dominator tree. Block must not + /// domiante any other blocks. Removes node from its immediate dominator's + /// children list. Deletes dominator node associated with basic block BB. + inline void eraseNode(BasicBlock *BB) { + DT->eraseNode(BB); + } + + /// splitBlock - BB is split and now it has one successor. Update dominator + /// tree to reflect this change. + inline void splitBlock(BasicBlock* NewBB) { + DT->splitBlock(NewBB); + } + + bool isReachableFromEntry(BasicBlock* A) { + return DT->isReachableFromEntry(A); + } + + + virtual void releaseMemory() { + DT->releaseMemory(); + } + + virtual void print(raw_ostream &OS, const Module* M= 0) const; +}; + +//===------------------------------------- +/// DominatorTree GraphTraits specialization so the DominatorTree can be +/// iterable by generic graph iterators. +/// +template <> struct GraphTraits { + typedef DomTreeNode NodeType; + typedef NodeType::iterator ChildIteratorType; + + static NodeType *getEntryNode(NodeType *N) { + return N; + } + static inline ChildIteratorType child_begin(NodeType *N) { + return N->begin(); + } + static inline ChildIteratorType child_end(NodeType *N) { + return N->end(); + } + + typedef df_iterator nodes_iterator; + + static nodes_iterator nodes_begin(DomTreeNode *N) { + return df_begin(getEntryNode(N)); + } + + static nodes_iterator nodes_end(DomTreeNode *N) { + return df_end(getEntryNode(N)); + } +}; + +template <> struct GraphTraits + : public GraphTraits { + static NodeType *getEntryNode(DominatorTree *DT) { + return DT->getRootNode(); + } + + static nodes_iterator nodes_begin(DominatorTree *N) { + return df_begin(getEntryNode(N)); + } + + static nodes_iterator nodes_end(DominatorTree *N) { + return df_end(getEntryNode(N)); + } +}; + + +//===----------------------------------------------------------------------===// +/// DominanceFrontierBase - Common base class for computing forward and inverse +/// dominance frontiers for a function. +/// +class DominanceFrontierBase : public FunctionPass { +public: + typedef std::set DomSetType; // Dom set for a bb + typedef std::map DomSetMapType; // Dom set map +protected: + DomSetMapType Frontiers; + std::vector Roots; + const bool IsPostDominators; + +public: + DominanceFrontierBase(void *ID, bool isPostDom) + : FunctionPass(ID), IsPostDominators(isPostDom) {} + + /// getRoots - Return the root blocks of the current CFG. This may include + /// multiple blocks if we are computing post dominators. For forward + /// dominators, this will always be a single block (the entry node). + /// + inline const std::vector &getRoots() const { return Roots; } + + /// isPostDominator - Returns true if analysis based of postdoms + /// + bool isPostDominator() const { return IsPostDominators; } + + virtual void releaseMemory() { Frontiers.clear(); } + + // Accessor interface: + typedef DomSetMapType::iterator iterator; + typedef DomSetMapType::const_iterator const_iterator; + iterator begin() { return Frontiers.begin(); } + const_iterator begin() const { return Frontiers.begin(); } + iterator end() { return Frontiers.end(); } + const_iterator end() const { return Frontiers.end(); } + iterator find(BasicBlock *B) { return Frontiers.find(B); } + const_iterator find(BasicBlock *B) const { return Frontiers.find(B); } + + iterator addBasicBlock(BasicBlock *BB, const DomSetType &frontier) { + assert(find(BB) == end() && "Block already in DominanceFrontier!"); + return Frontiers.insert(std::make_pair(BB, frontier)).first; + } + + /// removeBlock - Remove basic block BB's frontier. + void removeBlock(BasicBlock *BB) { + assert(find(BB) != end() && "Block is not in DominanceFrontier!"); + for (iterator I = begin(), E = end(); I != E; ++I) + I->second.erase(BB); + Frontiers.erase(BB); + } + + void addToFrontier(iterator I, BasicBlock *Node) { + assert(I != end() && "BB is not in DominanceFrontier!"); + I->second.insert(Node); + } + + void removeFromFrontier(iterator I, BasicBlock *Node) { + assert(I != end() && "BB is not in DominanceFrontier!"); + assert(I->second.count(Node) && "Node is not in DominanceFrontier of BB"); + I->second.erase(Node); + } + + /// compareDomSet - Return false if two domsets match. Otherwise + /// return true; + bool compareDomSet(DomSetType &DS1, const DomSetType &DS2) const { + std::set tmpSet; + for (DomSetType::const_iterator I = DS2.begin(), + E = DS2.end(); I != E; ++I) + tmpSet.insert(*I); + + for (DomSetType::const_iterator I = DS1.begin(), + E = DS1.end(); I != E; ) { + BasicBlock *Node = *I++; + + if (tmpSet.erase(Node) == 0) + // Node is in DS1 but not in DS2. + return true; + } + + if(!tmpSet.empty()) + // There are nodes that are in DS2 but not in DS1. + return true; + + // DS1 and DS2 matches. + return false; + } + + /// compare - Return true if the other dominance frontier base matches + /// this dominance frontier base. Otherwise return false. + bool compare(DominanceFrontierBase &Other) const { + DomSetMapType tmpFrontiers; + for (DomSetMapType::const_iterator I = Other.begin(), + E = Other.end(); I != E; ++I) + tmpFrontiers.insert(std::make_pair(I->first, I->second)); + + for (DomSetMapType::iterator I = tmpFrontiers.begin(), + E = tmpFrontiers.end(); I != E; ) { + BasicBlock *Node = I->first; + const_iterator DFI = find(Node); + if (DFI == end()) + return true; + + if (compareDomSet(I->second, DFI->second)) + return true; + + ++I; + tmpFrontiers.erase(Node); + } + + if (!tmpFrontiers.empty()) + return true; + + return false; + } + + /// print - Convert to human readable form + /// + virtual void print(raw_ostream &OS, const Module* = 0) const; +}; + + +//===------------------------------------- +/// DominanceFrontier Class - Concrete subclass of DominanceFrontierBase that is +/// used to compute a forward dominator frontiers. +/// +class DominanceFrontier : public DominanceFrontierBase { +public: + static char ID; // Pass ID, replacement for typeid + DominanceFrontier() : + DominanceFrontierBase(&ID, false) {} + + BasicBlock *getRoot() const { + assert(Roots.size() == 1 && "Should always have entry node!"); + return Roots[0]; + } + + virtual bool runOnFunction(Function &) { + Frontiers.clear(); + DominatorTree &DT = getAnalysis(); + Roots = DT.getRoots(); + assert(Roots.size() == 1 && "Only one entry block for forward domfronts!"); + calculate(DT, DT[Roots[0]]); + return false; + } + + virtual void verifyAnalysis() const; + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + AU.addRequired(); + } + + /// splitBlock - BB is split and now it has one successor. Update dominance + /// frontier to reflect this change. + void splitBlock(BasicBlock *BB); + + /// BasicBlock BB's new dominator is NewBB. Update BB's dominance frontier + /// to reflect this change. + void changeImmediateDominator(BasicBlock *BB, BasicBlock *NewBB, + DominatorTree *DT) { + // NewBB is now dominating BB. Which means BB's dominance + // frontier is now part of NewBB's dominance frontier. However, BB + // itself is not member of NewBB's dominance frontier. + DominanceFrontier::iterator NewDFI = find(NewBB); + DominanceFrontier::iterator DFI = find(BB); + // If BB was an entry block then its frontier is empty. + if (DFI == end()) + return; + DominanceFrontier::DomSetType BBSet = DFI->second; + for (DominanceFrontier::DomSetType::iterator BBSetI = BBSet.begin(), + BBSetE = BBSet.end(); BBSetI != BBSetE; ++BBSetI) { + BasicBlock *DFMember = *BBSetI; + // Insert only if NewBB dominates DFMember. + if (!DT->dominates(NewBB, DFMember)) + NewDFI->second.insert(DFMember); + } + NewDFI->second.erase(BB); + } + + const DomSetType &calculate(const DominatorTree &DT, + const DomTreeNode *Node); +}; + + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Analysis/FindUsedTypes.h b/libclamav/c++/llvm/include/llvm/Analysis/FindUsedTypes.h new file mode 100644 index 000000000..133738584 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Analysis/FindUsedTypes.h @@ -0,0 +1,64 @@ +//===- llvm/Analysis/FindUsedTypes.h - Find all Types in use ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This pass is used to seek out all of the types in use by the program. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_FINDUSEDTYPES_H +#define LLVM_ANALYSIS_FINDUSEDTYPES_H + +#include "llvm/Pass.h" +#include + +namespace llvm { + +class Type; +class Value; + +class FindUsedTypes : public ModulePass { + std::set UsedTypes; +public: + static char ID; // Pass identification, replacement for typeid + FindUsedTypes() : ModulePass(&ID) {} + + /// getTypes - After the pass has been run, return the set containing all of + /// the types used in the module. + /// + const std::set &getTypes() const { return UsedTypes; } + + /// 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 + /// symbol table from the module. + /// + void print(raw_ostream &o, const Module *M) const; + +private: + /// IncorporateType - Incorporate one type and all of its subtypes into the + /// collection of used types. + /// + void IncorporateType(const Type *Ty); + + /// IncorporateValue - Incorporate all of the types used by this value. + /// + void IncorporateValue(const Value *V); + +public: + /// run - This incorporates all types used by the specified module + bool runOnModule(Module &M); + + /// getAnalysisUsage - We do not modify anything. + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + } +}; + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Analysis/IVUsers.h b/libclamav/c++/llvm/include/llvm/Analysis/IVUsers.h new file mode 100644 index 000000000..22fbb35cd --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Analysis/IVUsers.h @@ -0,0 +1,225 @@ +//===- llvm/Analysis/IVUsers.h - Induction Variable Users -------*- 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 bookkeeping for "interesting" users of expressions +// computed from induction variables. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_IVUSERS_H +#define LLVM_ANALYSIS_IVUSERS_H + +#include "llvm/Analysis/LoopPass.h" +#include "llvm/Analysis/ScalarEvolution.h" +#include "llvm/ADT/SmallVector.h" +#include + +namespace llvm { + +class DominatorTree; +class Instruction; +class Value; +struct IVUsersOfOneStride; + +/// IVStrideUse - Keep track of one use of a strided induction variable, where +/// the stride is stored externally. The Offset member keeps track of the +/// offset from the IV, User is the actual user of the operand, and +/// 'OperandValToReplace' is the operand of the User that is the use. +class IVStrideUse : public CallbackVH, public ilist_node { +public: + IVStrideUse(IVUsersOfOneStride *parent, + const SCEV *offset, + Instruction* U, Value *O) + : CallbackVH(U), Parent(parent), Offset(offset), + OperandValToReplace(O), + IsUseOfPostIncrementedValue(false) { + } + + /// getUser - Return the user instruction for this use. + Instruction *getUser() const { + return cast(getValPtr()); + } + + /// setUser - Assign a new user instruction for this use. + void setUser(Instruction *NewUser) { + setValPtr(NewUser); + } + + /// getParent - Return a pointer to the IVUsersOfOneStride that owns + /// this IVStrideUse. + IVUsersOfOneStride *getParent() const { return Parent; } + + /// getOffset - Return the offset to add to a theoeretical induction + /// variable that starts at zero and counts up by the stride to compute + /// the value for the use. This always has the same type as the stride. + const SCEV *getOffset() const { return Offset; } + + /// setOffset - Assign a new offset to this use. + void setOffset(const SCEV *Val) { + Offset = Val; + } + + /// getOperandValToReplace - Return the Value of the operand in the user + /// instruction that this IVStrideUse is representing. + Value *getOperandValToReplace() const { + return OperandValToReplace; + } + + /// setOperandValToReplace - Assign a new Value as the operand value + /// to replace. + void setOperandValToReplace(Value *Op) { + OperandValToReplace = Op; + } + + /// isUseOfPostIncrementedValue - True if this should use the + /// post-incremented version of this IV, not the preincremented version. + /// This can only be set in special cases, such as the terminating setcc + /// instruction for a loop or uses dominated by the loop. + bool isUseOfPostIncrementedValue() const { + return IsUseOfPostIncrementedValue; + } + + /// setIsUseOfPostIncrmentedValue - set the flag that indicates whether + /// this is a post-increment use. + void setIsUseOfPostIncrementedValue(bool Val) { + IsUseOfPostIncrementedValue = Val; + } + +private: + /// Parent - a pointer to the IVUsersOfOneStride that owns this IVStrideUse. + IVUsersOfOneStride *Parent; + + /// Offset - The offset to add to the base induction expression. + const SCEV *Offset; + + /// OperandValToReplace - The Value of the operand in the user instruction + /// that this IVStrideUse is representing. + WeakVH OperandValToReplace; + + /// IsUseOfPostIncrementedValue - True if this should use the + /// post-incremented version of this IV, not the preincremented version. + bool IsUseOfPostIncrementedValue; + + /// Deleted - Implementation of CallbackVH virtual function to + /// recieve notification when the User is deleted. + virtual void deleted(); +}; + +template<> struct ilist_traits + : public ilist_default_traits { + // createSentinel is used to get hold of a node that marks the end of + // the list... + // The sentinel is relative to this instance, so we use a non-static + // method. + IVStrideUse *createSentinel() const { + // since i(p)lists always publicly derive from the corresponding + // traits, placing a data member in this class will augment i(p)list. + // But since the NodeTy is expected to publicly derive from + // ilist_node, there is a legal viable downcast from it + // to NodeTy. We use this trick to superpose i(p)list with a "ghostly" + // NodeTy, which becomes the sentinel. Dereferencing the sentinel is + // forbidden (save the ilist_node) so no one will ever notice + // the superposition. + return static_cast(&Sentinel); + } + static void destroySentinel(IVStrideUse*) {} + + IVStrideUse *provideInitialHead() const { return createSentinel(); } + IVStrideUse *ensureHead(IVStrideUse*) const { return createSentinel(); } + static void noteHead(IVStrideUse*, IVStrideUse*) {} + +private: + mutable ilist_node Sentinel; +}; + +/// IVUsersOfOneStride - This structure keeps track of all instructions that +/// have an operand that is based on the trip count multiplied by some stride. +struct IVUsersOfOneStride : public ilist_node { +private: + IVUsersOfOneStride(const IVUsersOfOneStride &I); // do not implement + void operator=(const IVUsersOfOneStride &I); // do not implement + +public: + IVUsersOfOneStride() : Stride(0) {} + + explicit IVUsersOfOneStride(const SCEV *stride) : Stride(stride) {} + + /// Stride - The stride for all the contained IVStrideUses. This is + /// a constant for affine strides. + const SCEV *Stride; + + /// Users - Keep track of all of the users of this stride as well as the + /// initial value and the operand that uses the IV. + ilist Users; + + void addUser(const SCEV *Offset, Instruction *User, Value *Operand) { + Users.push_back(new IVStrideUse(this, Offset, User, Operand)); + } + + void removeUser(IVStrideUse *User) { + Users.erase(User); + } +}; + +class IVUsers : public LoopPass { + friend class IVStrideUserVH; + Loop *L; + LoopInfo *LI; + DominatorTree *DT; + ScalarEvolution *SE; + SmallPtrSet Processed; + +public: + /// IVUses - A list of all tracked IV uses of induction variable expressions + /// we are interested in. + ilist IVUses; + + /// IVUsesByStride - A mapping from the strides in StrideOrder to the + /// uses in IVUses. + std::map IVUsesByStride; + + /// StrideOrder - An ordering of the keys in IVUsesByStride that is stable: + /// We use this to iterate over the IVUsesByStride collection without being + /// dependent on random ordering of pointers in the process. + SmallVector StrideOrder; + +private: + virtual void getAnalysisUsage(AnalysisUsage &AU) const; + + virtual bool runOnLoop(Loop *L, LPPassManager &LPM); + + virtual void releaseMemory(); + +public: + static char ID; // Pass ID, replacement for typeid + IVUsers(); + + /// AddUsersIfInteresting - Inspect the specified Instruction. If it is a + /// reducible SCEV, recursively add its users to the IVUsesByStride set and + /// return true. Otherwise, return false. + bool AddUsersIfInteresting(Instruction *I); + + void AddUser(const SCEV *Stride, const SCEV *Offset, + Instruction *User, Value *Operand); + + /// getReplacementExpr - Return a SCEV expression which computes the + /// value of the OperandValToReplace of the given IVStrideUse. + const SCEV *getReplacementExpr(const IVStrideUse &U) const; + + void print(raw_ostream &OS, const Module* = 0) const; + + /// dump - This method is used for debugging. + void dump() const; +}; + +Pass *createIVUsersPass(); + +} + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Analysis/InlineCost.h b/libclamav/c++/llvm/include/llvm/Analysis/InlineCost.h new file mode 100644 index 000000000..7ce49d7de --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Analysis/InlineCost.h @@ -0,0 +1,180 @@ +//===- InlineCost.cpp - Cost analysis for inliner ---------------*- 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 heuristics for inlining decisions. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_INLINECOST_H +#define LLVM_ANALYSIS_INLINECOST_H + +#include +#include +#include +#include + +namespace llvm { + + class Value; + class Function; + class BasicBlock; + class CallSite; + template + class SmallPtrSet; + + // CodeMetrics - Calculate size and a few similar metrics for a set of + // basic blocks. + struct CodeMetrics { + /// NeverInline - True if this callee should never be inlined into a + /// caller. + bool NeverInline; + + /// usesDynamicAlloca - True if this function calls alloca (in the C sense). + bool usesDynamicAlloca; + + /// NumInsts, NumBlocks - Keep track of how large each function is, which + /// is used to estimate the code size cost of inlining it. + unsigned NumInsts, NumBlocks; + + /// NumVectorInsts - Keep track of how many instructions produce vector + /// values. The inliner is being more aggressive with inlining vector + /// kernels. + unsigned NumVectorInsts; + + /// NumRets - Keep track of how many Ret instructions the block contains. + unsigned NumRets; + + CodeMetrics() : NeverInline(false), usesDynamicAlloca(false), NumInsts(0), + NumBlocks(0), NumVectorInsts(0), NumRets(0) {} + + /// analyzeBasicBlock - Add information about the specified basic block + /// to the current structure. + void analyzeBasicBlock(const BasicBlock *BB); + + /// analyzeFunction - Add information about the specified function + /// to the current structure. + void analyzeFunction(Function *F); + }; + + namespace InlineConstants { + // Various magic constants used to adjust heuristics. + const int CallPenalty = 5; + const int LastCallToStaticBonus = -15000; + const int ColdccPenalty = 2000; + const int NoreturnPenalty = 10000; + } + + /// InlineCost - Represent the cost of inlining a function. This + /// supports special values for functions which should "always" or + /// "never" be inlined. Otherwise, the cost represents a unitless + /// amount; smaller values increase the likelyhood of the function + /// being inlined. + class InlineCost { + enum Kind { + Value, + Always, + Never + }; + + // This is a do-it-yourself implementation of + // int Cost : 30; + // unsigned Type : 2; + // We used to use bitfields, but they were sometimes miscompiled (PR3822). + enum { TYPE_BITS = 2 }; + enum { COST_BITS = unsigned(sizeof(unsigned)) * CHAR_BIT - TYPE_BITS }; + unsigned TypedCost; // int Cost : COST_BITS; unsigned Type : TYPE_BITS; + + Kind getType() const { + return Kind(TypedCost >> COST_BITS); + } + + int getCost() const { + // Sign-extend the bottom COST_BITS bits. + return (int(TypedCost << TYPE_BITS)) >> TYPE_BITS; + } + + InlineCost(int C, int T) { + TypedCost = (unsigned(C << TYPE_BITS) >> TYPE_BITS) | (T << COST_BITS); + assert(getCost() == C && "Cost exceeds InlineCost precision"); + } + public: + static InlineCost get(int Cost) { return InlineCost(Cost, Value); } + static InlineCost getAlways() { return InlineCost(0, Always); } + static InlineCost getNever() { return InlineCost(0, Never); } + + bool isVariable() const { return getType() == Value; } + bool isAlways() const { return getType() == Always; } + bool isNever() const { return getType() == Never; } + + /// getValue() - Return a "variable" inline cost's amount. It is + /// an error to call this on an "always" or "never" InlineCost. + int getValue() const { + assert(getType() == Value && "Invalid access of InlineCost"); + return getCost(); + } + }; + + /// InlineCostAnalyzer - Cost analyzer used by inliner. + class InlineCostAnalyzer { + struct ArgInfo { + public: + unsigned ConstantWeight; + unsigned AllocaWeight; + + ArgInfo(unsigned CWeight, unsigned AWeight) + : ConstantWeight(CWeight), AllocaWeight(AWeight) {} + }; + + struct FunctionInfo { + CodeMetrics Metrics; + + /// ArgumentWeights - Each formal argument of the function is inspected to + /// see if it is used in any contexts where making it a constant or alloca + /// would reduce the code size. If so, we add some value to the argument + /// entry here. + std::vector ArgumentWeights; + + /// CountCodeReductionForConstant - Figure out an approximation for how + /// many instructions will be constant folded if the specified value is + /// constant. + unsigned CountCodeReductionForConstant(Value *V); + + /// CountCodeReductionForAlloca - Figure out an approximation of how much + /// smaller the function will be if it is inlined into a context where an + /// argument becomes an alloca. + /// + unsigned CountCodeReductionForAlloca(Value *V); + + /// analyzeFunction - Add information about the specified function + /// to the current structure. + void analyzeFunction(Function *F); + }; + + std::map CachedFunctionInfo; + + public: + + /// getInlineCost - The heuristic used to determine if we should inline the + /// function call or not. + /// + InlineCost getInlineCost(CallSite CS, + SmallPtrSet &NeverInline); + + /// getInlineFudgeFactor - Return a > 1.0 factor if the inliner should use a + /// higher threshold to determine if the function call should be inlined. + float getInlineFudgeFactor(CallSite CS); + + /// resetCachedFunctionInfo - erase any cached cost info for this function. + void resetCachedCostInfo(Function* Caller) { + CachedFunctionInfo[Caller] = FunctionInfo(); + } + }; +} + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Analysis/InstructionSimplify.h b/libclamav/c++/llvm/include/llvm/Analysis/InstructionSimplify.h new file mode 100644 index 000000000..1cd7e5655 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Analysis/InstructionSimplify.h @@ -0,0 +1,79 @@ +//===-- InstructionSimplify.h - Fold instructions into simpler forms ------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares routines for folding instructions into simpler forms that +// do not require creating new instructions. For example, this does constant +// folding, and can handle identities like (X&0)->0. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_INSTRUCTIONSIMPLIFY_H +#define LLVM_ANALYSIS_INSTRUCTIONSIMPLIFY_H + +namespace llvm { + class Instruction; + class Value; + class TargetData; + + /// SimplifyAndInst - Given operands for an And, see if we can + /// fold the result. If not, this returns null. + Value *SimplifyAndInst(Value *LHS, Value *RHS, + const TargetData *TD = 0); + + /// SimplifyOrInst - Given operands for an Or, see if we can + /// fold the result. If not, this returns null. + Value *SimplifyOrInst(Value *LHS, Value *RHS, + const TargetData *TD = 0); + + /// SimplifyICmpInst - Given operands for an ICmpInst, see if we can + /// fold the result. If not, this returns null. + Value *SimplifyICmpInst(unsigned Predicate, Value *LHS, Value *RHS, + const TargetData *TD = 0); + + /// SimplifyFCmpInst - Given operands for an FCmpInst, see if we can + /// fold the result. If not, this returns null. + Value *SimplifyFCmpInst(unsigned Predicate, Value *LHS, Value *RHS, + const TargetData *TD = 0); + + + /// SimplifyGEPInst - Given operands for an GetElementPtrInst, see if we can + /// fold the result. If not, this returns null. + Value *SimplifyGEPInst(Value * const *Ops, unsigned NumOps, + const TargetData *TD = 0); + + //=== Helper functions for higher up the class hierarchy. + + + /// SimplifyCmpInst - Given operands for a CmpInst, see if we can + /// fold the result. If not, this returns null. + Value *SimplifyCmpInst(unsigned Predicate, Value *LHS, Value *RHS, + const TargetData *TD = 0); + + /// SimplifyBinOp - Given operands for a BinaryOperator, see if we can + /// fold the result. If not, this returns null. + Value *SimplifyBinOp(unsigned Opcode, Value *LHS, Value *RHS, + const TargetData *TD = 0); + + /// SimplifyInstruction - See if we can compute a simplified version of this + /// instruction. If not, this returns null. + Value *SimplifyInstruction(Instruction *I, const TargetData *TD = 0); + + + /// ReplaceAndSimplifyAllUses - Perform From->replaceAllUsesWith(To) and then + /// delete the From instruction. In addition to a basic RAUW, this does a + /// recursive simplification of the updated instructions. This catches + /// things where one simplification exposes other opportunities. This only + /// simplifies and deletes scalar operations, it does not change the CFG. + /// + void ReplaceAndSimplifyAllUses(Instruction *From, Value *To, + const TargetData *TD = 0); +} // end namespace llvm + +#endif + diff --git a/libclamav/c++/llvm/include/llvm/Analysis/Interval.h b/libclamav/c++/llvm/include/llvm/Analysis/Interval.h new file mode 100644 index 000000000..ca8ad7313 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Analysis/Interval.h @@ -0,0 +1,153 @@ +//===- llvm/Analysis/Interval.h - Interval Class Declaration ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the declaration of the Interval class, which +// represents a set of CFG nodes and is a portion of an interval partition. +// +// Intervals have some interesting and useful properties, including the +// following: +// 1. The header node of an interval dominates all of the elements of the +// interval +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_INTERVAL_H +#define LLVM_INTERVAL_H + +#include "llvm/ADT/GraphTraits.h" +#include + +namespace llvm { + +class BasicBlock; +class raw_ostream; + +//===----------------------------------------------------------------------===// +// +/// Interval Class - An Interval is a set of nodes defined such that every node +/// in the interval has all of its predecessors in the interval (except for the +/// header) +/// +class Interval { + /// HeaderNode - The header BasicBlock, which dominates all BasicBlocks in this + /// interval. Also, any loops in this interval must go through the HeaderNode. + /// + BasicBlock *HeaderNode; +public: + typedef std::vector::iterator succ_iterator; + typedef std::vector::iterator pred_iterator; + typedef std::vector::iterator node_iterator; + + inline Interval(BasicBlock *Header) : HeaderNode(Header) { + Nodes.push_back(Header); + } + + inline Interval(const Interval &I) // copy ctor + : HeaderNode(I.HeaderNode), Nodes(I.Nodes), Successors(I.Successors) {} + + inline BasicBlock *getHeaderNode() const { return HeaderNode; } + + /// Nodes - The basic blocks in this interval. + /// + std::vector Nodes; + + /// Successors - List of BasicBlocks that are reachable directly from nodes in + /// this interval, but are not in the interval themselves. + /// These nodes necessarily must be header nodes for other intervals. + /// + std::vector Successors; + + /// Predecessors - List of BasicBlocks that have this Interval's header block + /// as one of their successors. + /// + std::vector Predecessors; + + /// contains - Find out if a basic block is in this interval + inline bool contains(BasicBlock *BB) const { + for (unsigned i = 0; i < Nodes.size(); ++i) + if (Nodes[i] == BB) return true; + return false; + // I don't want the dependency on + //return find(Nodes.begin(), Nodes.end(), BB) != Nodes.end(); + } + + /// isSuccessor - find out if a basic block is a successor of this Interval + inline bool isSuccessor(BasicBlock *BB) const { + for (unsigned i = 0; i < Successors.size(); ++i) + if (Successors[i] == BB) return true; + return false; + // I don't want the dependency on + //return find(Successors.begin(), Successors.end(), BB) != Successors.end(); + } + + /// Equality operator. It is only valid to compare two intervals from the + /// same partition, because of this, all we have to check is the header node + /// for equality. + /// + inline bool operator==(const Interval &I) const { + return HeaderNode == I.HeaderNode; + } + + /// isLoop - Find out if there is a back edge in this interval... + bool isLoop() const; + + /// print - Show contents in human readable format... + void print(raw_ostream &O) const; +}; + +/// succ_begin/succ_end - define methods so that Intervals may be used +/// just like BasicBlocks can with the succ_* functions, and *::succ_iterator. +/// +inline Interval::succ_iterator succ_begin(Interval *I) { + return I->Successors.begin(); +} +inline Interval::succ_iterator succ_end(Interval *I) { + return I->Successors.end(); +} + +/// pred_begin/pred_end - define methods so that Intervals may be used +/// just like BasicBlocks can with the pred_* functions, and *::pred_iterator. +/// +inline Interval::pred_iterator pred_begin(Interval *I) { + return I->Predecessors.begin(); +} +inline Interval::pred_iterator pred_end(Interval *I) { + return I->Predecessors.end(); +} + +template <> struct GraphTraits { + typedef Interval NodeType; + typedef Interval::succ_iterator ChildIteratorType; + + static NodeType *getEntryNode(Interval *I) { return I; } + + /// nodes_iterator/begin/end - Allow iteration over all nodes in the graph + static inline ChildIteratorType child_begin(NodeType *N) { + return succ_begin(N); + } + static inline ChildIteratorType child_end(NodeType *N) { + return succ_end(N); + } +}; + +template <> struct GraphTraits > { + typedef Interval NodeType; + typedef Interval::pred_iterator ChildIteratorType; + static NodeType *getEntryNode(Inverse G) { return G.Graph; } + static inline ChildIteratorType child_begin(NodeType *N) { + return pred_begin(N); + } + static inline ChildIteratorType child_end(NodeType *N) { + return pred_end(N); + } +}; + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Analysis/IntervalIterator.h b/libclamav/c++/llvm/include/llvm/Analysis/IntervalIterator.h new file mode 100644 index 000000000..d842840b6 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Analysis/IntervalIterator.h @@ -0,0 +1,259 @@ +//===- IntervalIterator.h - Interval Iterator Declaration -------*- 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 an iterator that enumerates the intervals in a control flow +// graph of some sort. This iterator is parametric, allowing iterator over the +// following types of graphs: +// +// 1. A Function* object, composed of BasicBlock nodes. +// 2. An IntervalPartition& object, composed of Interval nodes. +// +// This iterator is defined to walk the control flow graph, returning intervals +// in depth first order. These intervals are completely filled in except for +// the predecessor fields (the successor information is filled in however). +// +// By default, the intervals created by this iterator are deleted after they +// are no longer any use to the iterator. This behavior can be changed by +// passing a false value into the intervals_begin() function. This causes the +// IOwnMem member to be set, and the intervals to not be deleted. +// +// It is only safe to use this if all of the intervals are deleted by the caller +// and all of the intervals are processed. However, the user of the iterator is +// not allowed to modify or delete the intervals until after the iterator has +// been used completely. The IntervalPartition class uses this functionality. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_INTERVAL_ITERATOR_H +#define LLVM_INTERVAL_ITERATOR_H + +#include "llvm/Analysis/IntervalPartition.h" +#include "llvm/Function.h" +#include "llvm/Support/CFG.h" +#include +#include +#include + +namespace llvm { + +// getNodeHeader - Given a source graph node and the source graph, return the +// BasicBlock that is the header node. This is the opposite of +// getSourceGraphNode. +// +inline BasicBlock *getNodeHeader(BasicBlock *BB) { return BB; } +inline BasicBlock *getNodeHeader(Interval *I) { return I->getHeaderNode(); } + +// getSourceGraphNode - Given a BasicBlock and the source graph, return the +// source graph node that corresponds to the BasicBlock. This is the opposite +// of getNodeHeader. +// +inline BasicBlock *getSourceGraphNode(Function *, BasicBlock *BB) { + return BB; +} +inline Interval *getSourceGraphNode(IntervalPartition *IP, BasicBlock *BB) { + return IP->getBlockInterval(BB); +} + +// addNodeToInterval - This method exists to assist the generic ProcessNode +// with the task of adding a node to the new interval, depending on the +// type of the source node. In the case of a CFG source graph (BasicBlock +// case), the BasicBlock itself is added to the interval. +// +inline void addNodeToInterval(Interval *Int, BasicBlock *BB) { + Int->Nodes.push_back(BB); +} + +// addNodeToInterval - This method exists to assist the generic ProcessNode +// with the task of adding a node to the new interval, depending on the +// type of the source node. In the case of a CFG source graph (BasicBlock +// case), the BasicBlock itself is added to the interval. In the case of +// an IntervalPartition source graph (Interval case), all of the member +// BasicBlocks are added to the interval. +// +inline void addNodeToInterval(Interval *Int, Interval *I) { + // Add all of the nodes in I as new nodes in Int. + copy(I->Nodes.begin(), I->Nodes.end(), back_inserter(Int->Nodes)); +} + + + + + +template, + class IGT = GraphTraits > > +class IntervalIterator { + std::stack > IntStack; + std::set Visited; + OrigContainer_t *OrigContainer; + bool IOwnMem; // If True, delete intervals when done with them + // See file header for conditions of use +public: + typedef IntervalIterator _Self; + typedef std::forward_iterator_tag iterator_category; + + IntervalIterator() {} // End iterator, empty stack + IntervalIterator(Function *M, bool OwnMemory) : IOwnMem(OwnMemory) { + OrigContainer = M; + if (!ProcessInterval(&M->front())) { + assert(0 && "ProcessInterval should never fail for first interval!"); + } + } + + IntervalIterator(IntervalPartition &IP, bool OwnMemory) : IOwnMem(OwnMemory) { + OrigContainer = &IP; + if (!ProcessInterval(IP.getRootInterval())) { + assert(0 && "ProcessInterval should never fail for first interval!"); + } + } + + inline ~IntervalIterator() { + if (IOwnMem) + while (!IntStack.empty()) { + delete operator*(); + IntStack.pop(); + } + } + + inline bool operator==(const _Self& x) const { return IntStack == x.IntStack;} + inline bool operator!=(const _Self& x) const { return !operator==(x); } + + inline const Interval *operator*() const { return IntStack.top().first; } + inline Interval *operator*() { return IntStack.top().first; } + inline const Interval *operator->() const { return operator*(); } + inline Interval *operator->() { return operator*(); } + + _Self& operator++() { // Preincrement + assert(!IntStack.empty() && "Attempting to use interval iterator at end!"); + do { + // All of the intervals on the stack have been visited. Try visiting + // their successors now. + Interval::succ_iterator &SuccIt = IntStack.top().second, + EndIt = succ_end(IntStack.top().first); + while (SuccIt != EndIt) { // Loop over all interval succs + bool Done = ProcessInterval(getSourceGraphNode(OrigContainer, *SuccIt)); + ++SuccIt; // Increment iterator + if (Done) return *this; // Found a new interval! Use it! + } + + // Free interval memory... if necessary + if (IOwnMem) delete IntStack.top().first; + + // We ran out of successors for this interval... pop off the stack + IntStack.pop(); + } while (!IntStack.empty()); + + return *this; + } + inline _Self operator++(int) { // Postincrement + _Self tmp = *this; ++*this; return tmp; + } + +private: + // ProcessInterval - This method is used during the construction of the + // interval graph. It walks through the source graph, recursively creating + // an interval per invokation until the entire graph is covered. This uses + // the ProcessNode method to add all of the nodes to the interval. + // + // This method is templated because it may operate on two different source + // graphs: a basic block graph, or a preexisting interval graph. + // + bool ProcessInterval(NodeTy *Node) { + BasicBlock *Header = getNodeHeader(Node); + if (Visited.count(Header)) return false; + + Interval *Int = new Interval(Header); + Visited.insert(Header); // The header has now been visited! + + // Check all of our successors to see if they are in the interval... + for (typename GT::ChildIteratorType I = GT::child_begin(Node), + E = GT::child_end(Node); I != E; ++I) + ProcessNode(Int, getSourceGraphNode(OrigContainer, *I)); + + IntStack.push(std::make_pair(Int, succ_begin(Int))); + return true; + } + + // ProcessNode - This method is called by ProcessInterval to add nodes to the + // interval being constructed, and it is also called recursively as it walks + // the source graph. A node is added to the current interval only if all of + // its predecessors are already in the graph. This also takes care of keeping + // the successor set of an interval up to date. + // + // This method is templated because it may operate on two different source + // graphs: a basic block graph, or a preexisting interval graph. + // + void ProcessNode(Interval *Int, NodeTy *Node) { + assert(Int && "Null interval == bad!"); + assert(Node && "Null Node == bad!"); + + BasicBlock *NodeHeader = getNodeHeader(Node); + + if (Visited.count(NodeHeader)) { // Node already been visited? + if (Int->contains(NodeHeader)) { // Already in this interval... + return; + } else { // In other interval, add as successor + if (!Int->isSuccessor(NodeHeader)) // Add only if not already in set + Int->Successors.push_back(NodeHeader); + } + } else { // Otherwise, not in interval yet + for (typename IGT::ChildIteratorType I = IGT::child_begin(Node), + E = IGT::child_end(Node); I != E; ++I) { + if (!Int->contains(*I)) { // If pred not in interval, we can't be + if (!Int->isSuccessor(NodeHeader)) // Add only if not already in set + Int->Successors.push_back(NodeHeader); + return; // See you later + } + } + + // If we get here, then all of the predecessors of BB are in the interval + // already. In this case, we must add BB to the interval! + addNodeToInterval(Int, Node); + Visited.insert(NodeHeader); // The node has now been visited! + + if (Int->isSuccessor(NodeHeader)) { + // If we were in the successor list from before... remove from succ list + Int->Successors.erase(std::remove(Int->Successors.begin(), + Int->Successors.end(), NodeHeader), + Int->Successors.end()); + } + + // Now that we have discovered that Node is in the interval, perhaps some + // of its successors are as well? + for (typename GT::ChildIteratorType It = GT::child_begin(Node), + End = GT::child_end(Node); It != End; ++It) + ProcessNode(Int, getSourceGraphNode(OrigContainer, *It)); + } + } +}; + +typedef IntervalIterator function_interval_iterator; +typedef IntervalIterator + interval_part_interval_iterator; + + +inline function_interval_iterator intervals_begin(Function *F, + bool DeleteInts = true) { + return function_interval_iterator(F, DeleteInts); +} +inline function_interval_iterator intervals_end(Function *) { + return function_interval_iterator(); +} + +inline interval_part_interval_iterator + intervals_begin(IntervalPartition &IP, bool DeleteIntervals = true) { + return interval_part_interval_iterator(IP, DeleteIntervals); +} + +inline interval_part_interval_iterator intervals_end(IntervalPartition &IP) { + return interval_part_interval_iterator(); +} + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Analysis/IntervalPartition.h b/libclamav/c++/llvm/include/llvm/Analysis/IntervalPartition.h new file mode 100644 index 000000000..c1214e742 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Analysis/IntervalPartition.h @@ -0,0 +1,109 @@ +//===- IntervalPartition.h - Interval partition Calculation -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the declaration of the IntervalPartition class, which +// calculates and represents the interval partition of a function, or a +// preexisting interval partition. +// +// In this way, the interval partition may be used to reduce a flow graph down +// to its degenerate single node interval partition (unless it is irreducible). +// +// TODO: The IntervalPartition class should take a bool parameter that tells +// whether it should add the "tails" of an interval to an interval itself or if +// they should be represented as distinct intervals. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_INTERVAL_PARTITION_H +#define LLVM_INTERVAL_PARTITION_H + +#include "llvm/Analysis/Interval.h" +#include "llvm/Pass.h" +#include + +namespace llvm { + +//===----------------------------------------------------------------------===// +// +// IntervalPartition - This class builds and holds an "interval partition" for +// a function. This partition divides the control flow graph into a set of +// maximal intervals, as defined with the properties above. Intuitively, a +// BasicBlock is a (possibly nonexistent) loop with a "tail" of non looping +// nodes following it. +// +class IntervalPartition : public FunctionPass { + typedef std::map IntervalMapTy; + IntervalMapTy IntervalMap; + + typedef std::vector IntervalListTy; + Interval *RootInterval; + std::vector Intervals; + +public: + static char ID; // Pass identification, replacement for typeid + + IntervalPartition() : FunctionPass(&ID), RootInterval(0) {} + + // run - Calculate the interval partition for this function + virtual bool runOnFunction(Function &F); + + // IntervalPartition ctor - Build a reduced interval partition from an + // existing interval graph. This takes an additional boolean parameter to + // distinguish it from a copy constructor. Always pass in false for now. + // + IntervalPartition(IntervalPartition &I, bool); + + // print - Show contents in human readable format... + virtual void print(raw_ostream &O, const Module* = 0) const; + + // getRootInterval() - Return the root interval that contains the starting + // block of the function. + inline Interval *getRootInterval() { return RootInterval; } + + // isDegeneratePartition() - Returns true if the interval partition contains + // a single interval, and thus cannot be simplified anymore. + bool isDegeneratePartition() { return Intervals.size() == 1; } + + // TODO: isIrreducible - look for triangle graph. + + // getBlockInterval - Return the interval that a basic block exists in. + inline Interval *getBlockInterval(BasicBlock *BB) { + IntervalMapTy::iterator I = IntervalMap.find(BB); + return I != IntervalMap.end() ? I->second : 0; + } + + // getAnalysisUsage - Implement the Pass API + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + } + + // Interface to Intervals vector... + const std::vector &getIntervals() const { return Intervals; } + + // releaseMemory - Reset state back to before function was analyzed + void releaseMemory(); + +private: + // addIntervalToPartition - Add an interval to the internal list of intervals, + // and then add mappings from all of the basic blocks in the interval to the + // interval itself (in the IntervalMap). + // + void addIntervalToPartition(Interval *I); + + // updatePredecessors - Interval generation only sets the successor fields of + // the interval data structures. After interval generation is complete, + // run through all of the intervals and propagate successor info as + // predecessor info. + // + void updatePredecessors(Interval *Int); +}; + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Analysis/LazyValueInfo.h b/libclamav/c++/llvm/include/llvm/Analysis/LazyValueInfo.h new file mode 100644 index 000000000..566788daa --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Analysis/LazyValueInfo.h @@ -0,0 +1,73 @@ +//===- LazyValueInfo.h - Value constraint analysis --------------*- 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 the interface for lazy computation of value constraint +// information. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_LIVEVALUES_H +#define LLVM_ANALYSIS_LIVEVALUES_H + +#include "llvm/Pass.h" + +namespace llvm { + class Constant; + class TargetData; + class Value; + +/// LazyValueInfo - This pass computes, caches, and vends lazy value constraint +/// information. +class LazyValueInfo : public FunctionPass { + class TargetData *TD; + void *PImpl; + LazyValueInfo(const LazyValueInfo&); // DO NOT IMPLEMENT. + void operator=(const LazyValueInfo&); // DO NOT IMPLEMENT. +public: + static char ID; + LazyValueInfo() : FunctionPass(&ID), PImpl(0) {} + ~LazyValueInfo() { assert(PImpl == 0 && "releaseMemory not called"); } + + /// Tristate - This is used to return true/false/dunno results. + enum Tristate { + Unknown = -1, False = 0, True = 1 + }; + + + // Public query interface. + + /// getPredicateOnEdge - Determine whether the specified value comparison + /// with a constant is known to be true or false on the specified CFG edge. + /// Pred is a CmpInst predicate. + Tristate getPredicateOnEdge(unsigned Pred, Value *V, Constant *C, + BasicBlock *FromBB, BasicBlock *ToBB); + + + /// getConstant - Determine whether the specified value is known to be a + /// constant at the end of the specified block. Return null if not. + Constant *getConstant(Value *V, BasicBlock *BB); + + /// getConstantOnEdge - Determine whether the specified value is known to be a + /// constant on the specified edge. Return null if not. + Constant *getConstantOnEdge(Value *V, BasicBlock *FromBB, BasicBlock *ToBB); + + + // Implementation boilerplate. + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + } + virtual void releaseMemory(); + virtual bool runOnFunction(Function &F); +}; + +} // end namespace llvm + +#endif + diff --git a/libclamav/c++/llvm/include/llvm/Analysis/LibCallAliasAnalysis.h b/libclamav/c++/llvm/include/llvm/Analysis/LibCallAliasAnalysis.h new file mode 100644 index 000000000..01f108d29 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Analysis/LibCallAliasAnalysis.h @@ -0,0 +1,58 @@ +//===- LibCallAliasAnalysis.h - Implement AliasAnalysis for libcalls ------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the LibCallAliasAnalysis class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_LIBCALL_AA_H +#define LLVM_ANALYSIS_LIBCALL_AA_H + +#include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/Pass.h" + +namespace llvm { + class LibCallInfo; + struct LibCallFunctionInfo; + + /// LibCallAliasAnalysis - Alias analysis driven from LibCallInfo. + struct LibCallAliasAnalysis : public FunctionPass, public AliasAnalysis { + static char ID; // Class identification + + LibCallInfo *LCI; + + explicit LibCallAliasAnalysis(LibCallInfo *LC = 0) + : FunctionPass(&ID), LCI(LC) { + } + explicit LibCallAliasAnalysis(const void *ID, LibCallInfo *LC) + : FunctionPass(ID), LCI(LC) { + } + ~LibCallAliasAnalysis(); + + ModRefResult getModRefInfo(CallSite CS, Value *P, unsigned Size); + + ModRefResult getModRefInfo(CallSite CS1, CallSite CS2) { + // TODO: Could compare two direct calls against each other if we cared to. + return AliasAnalysis::getModRefInfo(CS1,CS2); + } + + virtual void getAnalysisUsage(AnalysisUsage &AU) const; + + virtual bool runOnFunction(Function &F) { + InitializeAliasAnalysis(this); // set up super class + return false; + } + + private: + ModRefResult AnalyzeLibCallDetails(const LibCallFunctionInfo *FI, + CallSite CS, Value *P, unsigned Size); + }; +} // End of llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Analysis/LibCallSemantics.h b/libclamav/c++/llvm/include/llvm/Analysis/LibCallSemantics.h new file mode 100644 index 000000000..74e8401a1 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Analysis/LibCallSemantics.h @@ -0,0 +1,166 @@ +//===- LibCallSemantics.h - Describe library semantics --------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines interfaces that can be used to describe language specific +// runtime library interfaces (e.g. libc, libm, etc) to LLVM optimizers. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_LIBCALLSEMANTICS_H +#define LLVM_ANALYSIS_LIBCALLSEMANTICS_H + +#include "llvm/Analysis/AliasAnalysis.h" + +namespace llvm { + + /// LibCallLocationInfo - This struct describes a set of memory locations that + /// are accessed by libcalls. Identification of a location is doing with a + /// simple callback function. + /// + /// For example, the LibCallInfo may be set up to model the behavior of + /// standard libm functions. The location that they may be interested in is + /// an abstract location that represents errno for the current target. In + /// this case, a location for errno is anything such that the predicate + /// returns true. On Mac OS/X, this predicate would return true if the + /// pointer is the result of a call to "__error()". + /// + /// Locations can also be defined in a constant-sensitive way. For example, + /// it is possible to define a location that returns true iff it is passed + /// into the call as a specific argument. This is useful for modeling things + /// like "printf", which can store to memory, but only through pointers passed + /// with a '%n' constraint. + /// + struct LibCallLocationInfo { + // TODO: Flags: isContextSensitive etc. + + /// isLocation - Return a LocResult if the specified pointer refers to this + /// location for the specified call site. This returns "Yes" if we can tell + /// that the pointer *does definitely* refer to the location, "No" if we can + /// tell that the location *definitely does not* refer to the location, and + /// returns "Unknown" if we cannot tell for certain. + enum LocResult { + Yes, No, Unknown + }; + LocResult (*isLocation)(CallSite CS, const Value *Ptr, unsigned Size); + }; + + /// LibCallFunctionInfo - Each record in the array of FunctionInfo structs + /// records the behavior of one libcall that is known by the optimizer. This + /// captures things like the side effects of the call. Side effects are + /// modeled both universally (in the readnone/readonly) sense, but also + /// potentially against a set of abstract locations defined by the optimizer. + /// This allows an optimizer to define that some libcall (e.g. sqrt) is + /// side-effect free except that it might modify errno (thus, the call is + /// *not* universally readonly). Or it might say that the side effects + /// are unknown other than to say that errno is not modified. + /// + struct LibCallFunctionInfo { + /// Name - This is the name of the libcall this describes. + const char *Name; + + /// TODO: Constant folding function: Constant* vector -> Constant*. + + /// UniversalBehavior - This captures the absolute mod/ref behavior without + /// any specific context knowledge. For example, if the function is known + /// to be readonly, this would be set to 'ref'. If known to be readnone, + /// this is set to NoModRef. + AliasAnalysis::ModRefResult UniversalBehavior; + + /// LocationMRInfo - This pair captures info about whether a specific + /// location is modified or referenced by a libcall. + struct LocationMRInfo { + /// LocationID - ID # of the accessed location or ~0U for array end. + unsigned LocationID; + /// MRInfo - Mod/Ref info for this location. + AliasAnalysis::ModRefResult MRInfo; + }; + + /// DetailsType - Indicate the sense of the LocationDetails array. This + /// controls how the LocationDetails array is interpreted. + enum { + /// DoesOnly - If DetailsType is set to DoesOnly, then we know that the + /// *only* mod/ref behavior of this function is captured by the + /// LocationDetails array. If we are trying to say that 'sqrt' can only + /// modify errno, we'd have the {errnoloc,mod} in the LocationDetails + /// array and have DetailsType set to DoesOnly. + DoesOnly, + + /// DoesNot - If DetailsType is set to DoesNot, then the sense of the + /// LocationDetails array is completely inverted. This means that we *do + /// not* know everything about the side effects of this libcall, but we do + /// know things that the libcall cannot do. This is useful for complex + /// functions like 'ctime' which have crazy mod/ref behavior, but are + /// known to never read or write errno. In this case, we'd have + /// {errnoloc,modref} in the LocationDetails array and DetailsType would + /// be set to DoesNot, indicating that ctime does not read or write the + /// errno location. + DoesNot + } DetailsType; + + /// LocationDetails - This is a pointer to an array of LocationMRInfo + /// structs which indicates the behavior of the libcall w.r.t. specific + /// locations. For example, if this libcall is known to only modify + /// 'errno', it would have a LocationDetails array with the errno ID and + /// 'mod' in it. See the DetailsType field for how this is interpreted. + /// + /// In the "DoesOnly" case, this information is 'may' information for: there + /// is no guarantee that the specified side effect actually does happen, + /// just that it could. In the "DoesNot" case, this is 'must not' info. + /// + /// If this pointer is null, no details are known. + /// + const LocationMRInfo *LocationDetails; + }; + + + /// LibCallInfo - Abstract interface to query about library call information. + /// Instances of this class return known information about some set of + /// libcalls. + /// + class LibCallInfo { + // Implementation details of this object, private. + mutable void *Impl; + mutable const LibCallLocationInfo *Locations; + mutable unsigned NumLocations; + public: + LibCallInfo() : Impl(0), Locations(0), NumLocations(0) {} + virtual ~LibCallInfo(); + + //===------------------------------------------------------------------===// + // Accessor Methods: Efficient access to contained data. + //===------------------------------------------------------------------===// + + /// getLocationInfo - Return information about the specified LocationID. + const LibCallLocationInfo &getLocationInfo(unsigned LocID) const; + + + /// getFunctionInfo - Return the LibCallFunctionInfo object corresponding to + /// the specified function if we have it. If not, return null. + const LibCallFunctionInfo *getFunctionInfo(Function *F) const; + + + //===------------------------------------------------------------------===// + // Implementation Methods: Subclasses should implement these. + //===------------------------------------------------------------------===// + + /// getLocationInfo - Return descriptors for the locations referenced by + /// this set of libcalls. + virtual unsigned getLocationInfo(const LibCallLocationInfo *&Array) const { + return 0; + } + + /// getFunctionInfoArray - Return an array of descriptors that describe the + /// set of libcalls represented by this LibCallInfo object. This array is + /// terminated by an entry with a NULL name. + virtual const LibCallFunctionInfo *getFunctionInfoArray() const = 0; + }; + +} // end namespace llvm + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Analysis/LiveValues.h b/libclamav/c++/llvm/include/llvm/Analysis/LiveValues.h new file mode 100644 index 000000000..b92cb7833 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Analysis/LiveValues.h @@ -0,0 +1,99 @@ +//===- LiveValues.h - Liveness information for LLVM IR Values. ------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the interface for the LLVM IR Value liveness +// analysis pass. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_LIVEVALUES_H +#define LLVM_ANALYSIS_LIVEVALUES_H + +#include "llvm/Pass.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallPtrSet.h" + +namespace llvm { + +class DominatorTree; +class LoopInfo; +class Value; + +/// LiveValues - Analysis that provides liveness information for +/// LLVM IR Values. +/// +class LiveValues : public FunctionPass { + DominatorTree *DT; + LoopInfo *LI; + + /// Memo - A bunch of state to be associated with a value. + /// + struct Memo { + /// Used - The set of blocks which contain a use of the value. + /// + SmallPtrSet Used; + + /// LiveThrough - A conservative approximation of the set of blocks in + /// which the value is live-through, meaning blocks properly dominated + /// by the definition, and from which blocks containing uses of the + /// value are reachable. + /// + SmallPtrSet LiveThrough; + + /// Killed - A conservative approximation of the set of blocks in which + /// the value is used and not live-out. + /// + SmallPtrSet Killed; + }; + + /// Memos - Remembers the Memo for each Value. This is populated on + /// demand. + /// + DenseMap Memos; + + /// getMemo - Retrieve an existing Memo for the given value if one + /// is available, otherwise compute a new one. + /// + Memo &getMemo(const Value *V); + + /// compute - Compute a new Memo for the given value. + /// + Memo &compute(const Value *V); + +public: + static char ID; + LiveValues(); + + virtual void getAnalysisUsage(AnalysisUsage &AU) const; + virtual bool runOnFunction(Function &F); + virtual void releaseMemory(); + + /// isUsedInBlock - Test if the given value is used in the given block. + /// + bool isUsedInBlock(const Value *V, const BasicBlock *BB); + + /// isLiveThroughBlock - Test if the given value is known to be + /// live-through the given block, meaning that the block is properly + /// dominated by the value's definition, and there exists a block + /// reachable from it that contains a use. This uses a conservative + /// approximation that errs on the side of returning false. + /// + bool isLiveThroughBlock(const Value *V, const BasicBlock *BB); + + /// isKilledInBlock - Test if the given value is known to be killed in + /// the given block, meaning that the block contains a use of the value, + /// and no blocks reachable from the block contain a use. This uses a + /// conservative approximation that errs on the side of returning false. + /// + bool isKilledInBlock(const Value *V, const BasicBlock *BB); +}; + +} // end namespace llvm + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Analysis/LoopDependenceAnalysis.h b/libclamav/c++/llvm/include/llvm/Analysis/LoopDependenceAnalysis.h new file mode 100644 index 000000000..1d386ba88 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Analysis/LoopDependenceAnalysis.h @@ -0,0 +1,122 @@ +//===- llvm/Analysis/LoopDependenceAnalysis.h --------------- -*- C++ -*---===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// LoopDependenceAnalysis is an LLVM pass that analyses dependences in memory +// accesses in loops. +// +// Please note that this is work in progress and the interface is subject to +// change. +// +// TODO: adapt as interface progresses +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_LOOP_DEPENDENCE_ANALYSIS_H +#define LLVM_ANALYSIS_LOOP_DEPENDENCE_ANALYSIS_H + +#include "llvm/ADT/DenseSet.h" +#include "llvm/ADT/FoldingSet.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/Analysis/LoopPass.h" +#include "llvm/Support/Allocator.h" + +namespace llvm { + +class AliasAnalysis; +class AnalysisUsage; +class ScalarEvolution; +class SCEV; +class Value; +class raw_ostream; + +class LoopDependenceAnalysis : public LoopPass { + AliasAnalysis *AA; + ScalarEvolution *SE; + + /// L - The loop we are currently analysing. + Loop *L; + + /// TODO: doc + enum DependenceResult { Independent = 0, Dependent = 1, Unknown = 2 }; + + /// TODO: doc + struct Subscript { + /// TODO: Add distance, direction, breaking conditions, ... + }; + + /// DependencePair - Represents a data dependence relation between to memory + /// reference instructions. + struct DependencePair : public FastFoldingSetNode { + Value *A; + Value *B; + DependenceResult Result; + SmallVector Subscripts; + + DependencePair(const FoldingSetNodeID &ID, Value *a, Value *b) : + FastFoldingSetNode(ID), A(a), B(b), Result(Unknown), Subscripts() {} + }; + + /// findOrInsertDependencePair - Return true if a DependencePair for the + /// given Values already exists, false if a new DependencePair had to be + /// created. The third argument is set to the pair found or created. + bool findOrInsertDependencePair(Value*, Value*, DependencePair*&); + + /// getLoops - Collect all loops of the loop-nest L a given SCEV is variant + /// in. + void getLoops(const SCEV*, DenseSet*) const; + + /// isLoopInvariant - True if a given SCEV is invariant in all loops of the + /// loop-nest starting at the innermost loop L. + bool isLoopInvariant(const SCEV*) const; + + /// isAffine - An SCEV is affine with respect to the loop-nest starting at + /// the innermost loop L if it is of the form A+B*X where A, B are invariant + /// in the loop-nest and X is a induction variable in the loop-nest. + bool isAffine(const SCEV*) const; + + /// TODO: doc + bool isZIVPair(const SCEV*, const SCEV*) const; + bool isSIVPair(const SCEV*, const SCEV*) const; + DependenceResult analyseZIV(const SCEV*, const SCEV*, Subscript*) const; + DependenceResult analyseSIV(const SCEV*, const SCEV*, Subscript*) const; + DependenceResult analyseMIV(const SCEV*, const SCEV*, Subscript*) const; + DependenceResult analyseSubscript(const SCEV*, const SCEV*, Subscript*) const; + DependenceResult analysePair(DependencePair*) const; + +public: + static char ID; // Class identification, replacement for typeinfo + LoopDependenceAnalysis() : LoopPass(&ID) {} + + /// isDependencePair - Check wether two values can possibly give rise to a + /// data dependence: that is the case if both are instructions accessing + /// memory and at least one of those accesses is a write. + bool isDependencePair(const Value*, const Value*) const; + + /// depends - Return a boolean indicating if there is a data dependence + /// between two instructions. + bool depends(Value*, Value*); + + bool runOnLoop(Loop*, LPPassManager&); + virtual void releaseMemory(); + virtual void getAnalysisUsage(AnalysisUsage&) const; + void print(raw_ostream&, const Module* = 0) const; + +private: + FoldingSet Pairs; + BumpPtrAllocator PairAllocator; +}; // class LoopDependenceAnalysis + +// createLoopDependenceAnalysisPass - This creates an instance of the +// LoopDependenceAnalysis pass. +// +LoopPass *createLoopDependenceAnalysisPass(); + +} // namespace llvm + +#endif /* LLVM_ANALYSIS_LOOP_DEPENDENCE_ANALYSIS_H */ diff --git a/libclamav/c++/llvm/include/llvm/Analysis/LoopInfo.h b/libclamav/c++/llvm/include/llvm/Analysis/LoopInfo.h new file mode 100644 index 000000000..9969d999e --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Analysis/LoopInfo.h @@ -0,0 +1,1039 @@ +//===- llvm/Analysis/LoopInfo.h - Natural Loop Calculator -------*- 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 the LoopInfo class that is used to identify natural loops +// and determine the loop depth of various nodes of the CFG. A natural loop +// has exactly one entry-point, which is called the header. Note that natural +// loops may actually be several loops that share the same header node. +// +// This analysis calculates the nesting structure of loops in a function. For +// each natural loop identified, this analysis identifies natural loops +// contained entirely within the loop and the basic blocks the make up the loop. +// +// It can calculate on the fly various bits of information, for example: +// +// * whether there is a preheader for the loop +// * the number of back edges to the header +// * whether or not a particular block branches out of the loop +// * the successor blocks of the loop +// * the loop depth +// * the trip count +// * etc... +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_LOOP_INFO_H +#define LLVM_ANALYSIS_LOOP_INFO_H + +#include "llvm/Pass.h" +#include "llvm/ADT/DepthFirstIterator.h" +#include "llvm/ADT/GraphTraits.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/Analysis/Dominators.h" +#include "llvm/Support/CFG.h" +#include "llvm/Support/raw_ostream.h" +#include + +namespace llvm { + +template +static void RemoveFromVector(std::vector &V, T *N) { + typename std::vector::iterator I = std::find(V.begin(), V.end(), N); + assert(I != V.end() && "N is not in this list!"); + V.erase(I); +} + +class DominatorTree; +class LoopInfo; +class Loop; +template class LoopInfoBase; +template class LoopBase; + +//===----------------------------------------------------------------------===// +/// LoopBase class - Instances of this class are used to represent loops that +/// are detected in the flow graph +/// +template +class LoopBase { + LoopT *ParentLoop; + // SubLoops - Loops contained entirely within this one. + std::vector SubLoops; + + // Blocks - The list of blocks in this loop. First entry is the header node. + std::vector Blocks; + + // DO NOT IMPLEMENT + LoopBase(const LoopBase &); + // DO NOT IMPLEMENT + const LoopBase&operator=(const LoopBase &); +public: + /// Loop ctor - This creates an empty loop. + LoopBase() : ParentLoop(0) {} + ~LoopBase() { + for (size_t i = 0, e = SubLoops.size(); i != e; ++i) + delete SubLoops[i]; + } + + /// getLoopDepth - Return the nesting level of this loop. An outer-most + /// loop has depth 1, for consistency with loop depth values used for basic + /// blocks, where depth 0 is used for blocks not inside any loops. + unsigned getLoopDepth() const { + unsigned D = 1; + for (const LoopT *CurLoop = ParentLoop; CurLoop; + CurLoop = CurLoop->ParentLoop) + ++D; + return D; + } + BlockT *getHeader() const { return Blocks.front(); } + LoopT *getParentLoop() const { return ParentLoop; } + + /// contains - Return true if the specified basic block is in this loop + /// + bool contains(const BlockT *BB) const { + return std::find(block_begin(), block_end(), BB) != block_end(); + } + + /// iterator/begin/end - Return the loops contained entirely within this loop. + /// + const std::vector &getSubLoops() const { return SubLoops; } + typedef typename std::vector::const_iterator iterator; + iterator begin() const { return SubLoops.begin(); } + iterator end() const { return SubLoops.end(); } + bool empty() const { return SubLoops.empty(); } + + /// getBlocks - Get a list of the basic blocks which make up this loop. + /// + const std::vector &getBlocks() const { return Blocks; } + typedef typename std::vector::const_iterator block_iterator; + block_iterator block_begin() const { return Blocks.begin(); } + block_iterator block_end() const { return Blocks.end(); } + + /// isLoopExiting - True if terminator in the block can branch to another + /// block that is outside of the current loop. + /// + bool isLoopExiting(const BlockT *BB) const { + typedef GraphTraits BlockTraits; + for (typename BlockTraits::ChildIteratorType SI = + BlockTraits::child_begin(const_cast(BB)), + SE = BlockTraits::child_end(const_cast(BB)); SI != SE; ++SI) { + if (!contains(*SI)) + return true; + } + return false; + } + + /// getNumBackEdges - Calculate the number of back edges to the loop header + /// + unsigned getNumBackEdges() const { + unsigned NumBackEdges = 0; + BlockT *H = getHeader(); + + typedef GraphTraits > InvBlockTraits; + for (typename InvBlockTraits::ChildIteratorType I = + InvBlockTraits::child_begin(const_cast(H)), + E = InvBlockTraits::child_end(const_cast(H)); I != E; ++I) + if (contains(*I)) + ++NumBackEdges; + + return NumBackEdges; + } + + //===--------------------------------------------------------------------===// + // APIs for simple analysis of the loop. + // + // Note that all of these methods can fail on general loops (ie, there may not + // be a preheader, etc). For best success, the loop simplification and + // induction variable canonicalization pass should be used to normalize loops + // for easy analysis. These methods assume canonical loops. + + /// getExitingBlocks - Return all blocks inside the loop that have successors + /// outside of the loop. These are the blocks _inside of the current loop_ + /// which branch out. The returned list is always unique. + /// + void getExitingBlocks(SmallVectorImpl &ExitingBlocks) const { + // Sort the blocks vector so that we can use binary search to do quick + // lookups. + SmallVector LoopBBs(block_begin(), block_end()); + std::sort(LoopBBs.begin(), LoopBBs.end()); + + typedef GraphTraits BlockTraits; + for (block_iterator BI = block_begin(), BE = block_end(); BI != BE; ++BI) + for (typename BlockTraits::ChildIteratorType I = + BlockTraits::child_begin(*BI), E = BlockTraits::child_end(*BI); + I != E; ++I) + if (!std::binary_search(LoopBBs.begin(), LoopBBs.end(), *I)) { + // Not in current loop? It must be an exit block. + ExitingBlocks.push_back(*BI); + break; + } + } + + /// getExitingBlock - If getExitingBlocks would return exactly one block, + /// return that block. Otherwise return null. + BlockT *getExitingBlock() const { + SmallVector ExitingBlocks; + getExitingBlocks(ExitingBlocks); + if (ExitingBlocks.size() == 1) + return ExitingBlocks[0]; + return 0; + } + + /// getExitBlocks - Return all of the successor blocks of this loop. These + /// are the blocks _outside of the current loop_ which are branched to. + /// + void getExitBlocks(SmallVectorImpl &ExitBlocks) const { + // Sort the blocks vector so that we can use binary search to do quick + // lookups. + SmallVector LoopBBs(block_begin(), block_end()); + std::sort(LoopBBs.begin(), LoopBBs.end()); + + typedef GraphTraits BlockTraits; + for (block_iterator BI = block_begin(), BE = block_end(); BI != BE; ++BI) + for (typename BlockTraits::ChildIteratorType I = + BlockTraits::child_begin(*BI), E = BlockTraits::child_end(*BI); + I != E; ++I) + if (!std::binary_search(LoopBBs.begin(), LoopBBs.end(), *I)) + // Not in current loop? It must be an exit block. + ExitBlocks.push_back(*I); + } + + /// getExitBlock - If getExitBlocks would return exactly one block, + /// return that block. Otherwise return null. + BlockT *getExitBlock() const { + SmallVector ExitBlocks; + getExitBlocks(ExitBlocks); + if (ExitBlocks.size() == 1) + return ExitBlocks[0]; + return 0; + } + + /// getExitEdges - Return all pairs of (_inside_block_,_outside_block_). + typedef std::pair Edge; + void getExitEdges(SmallVectorImpl &ExitEdges) const { + // Sort the blocks vector so that we can use binary search to do quick + // lookups. + SmallVector LoopBBs(block_begin(), block_end()); + std::sort(LoopBBs.begin(), LoopBBs.end()); + + typedef GraphTraits BlockTraits; + for (block_iterator BI = block_begin(), BE = block_end(); BI != BE; ++BI) + for (typename BlockTraits::ChildIteratorType I = + BlockTraits::child_begin(*BI), E = BlockTraits::child_end(*BI); + I != E; ++I) + if (!std::binary_search(LoopBBs.begin(), LoopBBs.end(), *I)) + // Not in current loop? It must be an exit block. + ExitEdges.push_back(std::make_pair(*BI, *I)); + } + + /// getLoopPreheader - If there is a preheader for this loop, return it. A + /// loop has a preheader if there is only one edge to the header of the loop + /// from outside of the loop. If this is the case, the block branching to the + /// header of the loop is the preheader node. + /// + /// This method returns null if there is no preheader for the loop. + /// + BlockT *getLoopPreheader() const { + // Keep track of nodes outside the loop branching to the header... + BlockT *Out = 0; + + // Loop over the predecessors of the header node... + BlockT *Header = getHeader(); + typedef GraphTraits BlockTraits; + typedef GraphTraits > InvBlockTraits; + for (typename InvBlockTraits::ChildIteratorType PI = + InvBlockTraits::child_begin(Header), + PE = InvBlockTraits::child_end(Header); PI != PE; ++PI) + if (!contains(*PI)) { // If the block is not in the loop... + if (Out && Out != *PI) + return 0; // Multiple predecessors outside the loop + Out = *PI; + } + + // Make sure there is only one exit out of the preheader. + assert(Out && "Header of loop has no predecessors from outside loop?"); + typename BlockTraits::ChildIteratorType SI = BlockTraits::child_begin(Out); + ++SI; + if (SI != BlockTraits::child_end(Out)) + return 0; // Multiple exits from the block, must not be a preheader. + + // If there is exactly one preheader, return it. If there was zero, then + // Out is still null. + return Out; + } + + /// getLoopLatch - If there is a single latch block for this loop, return it. + /// A latch block is a block that contains a branch back to the header. + BlockT *getLoopLatch() const { + BlockT *Header = getHeader(); + typedef GraphTraits > InvBlockTraits; + typename InvBlockTraits::ChildIteratorType PI = + InvBlockTraits::child_begin(Header); + typename InvBlockTraits::ChildIteratorType PE = + InvBlockTraits::child_end(Header); + BlockT *Latch = 0; + for (; PI != PE; ++PI) + if (contains(*PI)) { + if (Latch) return 0; + Latch = *PI; + } + + return Latch; + } + + //===--------------------------------------------------------------------===// + // APIs for updating loop information after changing the CFG + // + + /// addBasicBlockToLoop - This method is used by other analyses to update loop + /// information. NewBB is set to be a new member of the current loop. + /// Because of this, it is added as a member of all parent loops, and is added + /// to the specified LoopInfo object as being in the current basic block. It + /// is not valid to replace the loop header with this method. + /// + void addBasicBlockToLoop(BlockT *NewBB, LoopInfoBase &LI); + + /// replaceChildLoopWith - This is used when splitting loops up. It replaces + /// the OldChild entry in our children list with NewChild, and updates the + /// parent pointer of OldChild to be null and the NewChild to be this loop. + /// This updates the loop depth of the new child. + void replaceChildLoopWith(LoopT *OldChild, + LoopT *NewChild) { + assert(OldChild->ParentLoop == this && "This loop is already broken!"); + assert(NewChild->ParentLoop == 0 && "NewChild already has a parent!"); + typename std::vector::iterator I = + std::find(SubLoops.begin(), SubLoops.end(), OldChild); + assert(I != SubLoops.end() && "OldChild not in loop!"); + *I = NewChild; + OldChild->ParentLoop = 0; + NewChild->ParentLoop = static_cast(this); + } + + /// addChildLoop - Add the specified loop to be a child of this loop. This + /// updates the loop depth of the new child. + /// + void addChildLoop(LoopT *NewChild) { + assert(NewChild->ParentLoop == 0 && "NewChild already has a parent!"); + NewChild->ParentLoop = static_cast(this); + SubLoops.push_back(NewChild); + } + + /// removeChildLoop - This removes the specified child from being a subloop of + /// this loop. The loop is not deleted, as it will presumably be inserted + /// into another loop. + LoopT *removeChildLoop(iterator I) { + assert(I != SubLoops.end() && "Cannot remove end iterator!"); + LoopT *Child = *I; + assert(Child->ParentLoop == this && "Child is not a child of this loop!"); + SubLoops.erase(SubLoops.begin()+(I-begin())); + Child->ParentLoop = 0; + return Child; + } + + /// addBlockEntry - This adds a basic block directly to the basic block list. + /// This should only be used by transformations that create new loops. Other + /// transformations should use addBasicBlockToLoop. + void addBlockEntry(BlockT *BB) { + Blocks.push_back(BB); + } + + /// moveToHeader - This method is used to move BB (which must be part of this + /// loop) to be the loop header of the loop (the block that dominates all + /// others). + void moveToHeader(BlockT *BB) { + if (Blocks[0] == BB) return; + for (unsigned i = 0; ; ++i) { + assert(i != Blocks.size() && "Loop does not contain BB!"); + if (Blocks[i] == BB) { + Blocks[i] = Blocks[0]; + Blocks[0] = BB; + return; + } + } + } + + /// removeBlockFromLoop - This removes the specified basic block from the + /// current loop, updating the Blocks as appropriate. This does not update + /// the mapping in the LoopInfo class. + void removeBlockFromLoop(BlockT *BB) { + RemoveFromVector(Blocks, BB); + } + + /// verifyLoop - Verify loop structure + void verifyLoop() const { +#ifndef NDEBUG + assert(!Blocks.empty() && "Loop header is missing"); + + // Sort the blocks vector so that we can use binary search to do quick + // lookups. + SmallVector LoopBBs(block_begin(), block_end()); + std::sort(LoopBBs.begin(), LoopBBs.end()); + + // Check the individual blocks. + for (block_iterator I = block_begin(), E = block_end(); I != E; ++I) { + BlockT *BB = *I; + bool HasInsideLoopSuccs = false; + bool HasInsideLoopPreds = false; + SmallVector OutsideLoopPreds; + + typedef GraphTraits BlockTraits; + for (typename BlockTraits::ChildIteratorType SI = + BlockTraits::child_begin(BB), SE = BlockTraits::child_end(BB); + SI != SE; ++SI) + if (std::binary_search(LoopBBs.begin(), LoopBBs.end(), *SI)) { + HasInsideLoopSuccs = true; + break; + } + typedef GraphTraits > InvBlockTraits; + for (typename InvBlockTraits::ChildIteratorType PI = + InvBlockTraits::child_begin(BB), PE = InvBlockTraits::child_end(BB); + PI != PE; ++PI) { + if (std::binary_search(LoopBBs.begin(), LoopBBs.end(), *PI)) + HasInsideLoopPreds = true; + else + OutsideLoopPreds.push_back(*PI); + } + + if (BB == getHeader()) { + assert(!OutsideLoopPreds.empty() && "Loop is unreachable!"); + } else if (!OutsideLoopPreds.empty()) { + // A non-header loop shouldn't be reachable from outside the loop, + // though it is permitted if the predecessor is not itself actually + // reachable. + BlockT *EntryBB = BB->getParent()->begin(); + for (df_iterator NI = df_begin(EntryBB), + NE = df_end(EntryBB); NI != NE; ++NI) + for (unsigned i = 0, e = OutsideLoopPreds.size(); i != e; ++i) + assert(*NI != OutsideLoopPreds[i] && + "Loop has multiple entry points!"); + } + assert(HasInsideLoopPreds && "Loop block has no in-loop predecessors!"); + assert(HasInsideLoopSuccs && "Loop block has no in-loop successors!"); + assert(BB != getHeader()->getParent()->begin() && + "Loop contains function entry block!"); + } + + // Check the subloops. + for (iterator I = begin(), E = end(); I != E; ++I) + // Each block in each subloop should be contained within this loop. + for (block_iterator BI = (*I)->block_begin(), BE = (*I)->block_end(); + BI != BE; ++BI) { + assert(std::binary_search(LoopBBs.begin(), LoopBBs.end(), *BI) && + "Loop does not contain all the blocks of a subloop!"); + } + + // Check the parent loop pointer. + if (ParentLoop) { + assert(std::find(ParentLoop->begin(), ParentLoop->end(), this) != + ParentLoop->end() && + "Loop is not a subloop of its parent!"); + } +#endif + } + + /// verifyLoop - Verify loop structure of this loop and all nested loops. + void verifyLoopNest() const { + // Verify this loop. + verifyLoop(); + // Verify the subloops. + for (iterator I = begin(), E = end(); I != E; ++I) + (*I)->verifyLoopNest(); + } + + void print(raw_ostream &OS, unsigned Depth = 0) const { + OS.indent(Depth*2) << "Loop at depth " << getLoopDepth() + << " containing: "; + + for (unsigned i = 0; i < getBlocks().size(); ++i) { + if (i) OS << ","; + BlockT *BB = getBlocks()[i]; + WriteAsOperand(OS, BB, false); + if (BB == getHeader()) OS << "
    "; + if (BB == getLoopLatch()) OS << ""; + if (isLoopExiting(BB)) OS << ""; + } + OS << "\n"; + + for (iterator I = begin(), E = end(); I != E; ++I) + (*I)->print(OS, Depth+2); + } + + void dump() const { + print(errs()); + } + +protected: + friend class LoopInfoBase; + explicit LoopBase(BlockT *BB) : ParentLoop(0) { + Blocks.push_back(BB); + } +}; + +class Loop : public LoopBase { +public: + Loop() {} + + /// isLoopInvariant - Return true if the specified value is loop invariant + /// + bool isLoopInvariant(Value *V) const; + + /// isLoopInvariant - Return true if the specified instruction is + /// loop-invariant. + /// + bool isLoopInvariant(Instruction *I) const; + + /// makeLoopInvariant - If the given value is an instruction inside of the + /// loop and it can be hoisted, do so to make it trivially loop-invariant. + /// Return true if the value after any hoisting is loop invariant. This + /// function can be used as a slightly more aggressive replacement for + /// isLoopInvariant. + /// + /// If InsertPt is specified, it is the point to hoist instructions to. + /// If null, the terminator of the loop preheader is used. + /// + bool makeLoopInvariant(Value *V, bool &Changed, + Instruction *InsertPt = 0) const; + + /// makeLoopInvariant - If the given instruction is inside of the + /// loop and it can be hoisted, do so to make it trivially loop-invariant. + /// Return true if the instruction after any hoisting is loop invariant. This + /// function can be used as a slightly more aggressive replacement for + /// isLoopInvariant. + /// + /// If InsertPt is specified, it is the point to hoist instructions to. + /// If null, the terminator of the loop preheader is used. + /// + bool makeLoopInvariant(Instruction *I, bool &Changed, + Instruction *InsertPt = 0) const; + + /// getCanonicalInductionVariable - Check to see if the loop has a canonical + /// induction variable: an integer recurrence that starts at 0 and increments + /// by one each time through the loop. If so, return the phi node that + /// corresponds to it. + /// + /// The IndVarSimplify pass transforms loops to have a canonical induction + /// variable. + /// + PHINode *getCanonicalInductionVariable() const; + + /// getCanonicalInductionVariableIncrement - Return the LLVM value that holds + /// the canonical induction variable value for the "next" iteration of the + /// loop. This always succeeds if getCanonicalInductionVariable succeeds. + /// + Instruction *getCanonicalInductionVariableIncrement() const; + + /// getTripCount - Return a loop-invariant LLVM value indicating the number of + /// times the loop will be executed. Note that this means that the backedge + /// of the loop executes N-1 times. If the trip-count cannot be determined, + /// this returns null. + /// + /// The IndVarSimplify pass transforms loops to have a form that this + /// function easily understands. + /// + Value *getTripCount() const; + + /// getSmallConstantTripCount - Returns the trip count of this loop as a + /// normal unsigned value, if possible. Returns 0 if the trip count is unknown + /// of not constant. Will also return 0 if the trip count is very large + /// (>= 2^32) + unsigned getSmallConstantTripCount() const; + + /// 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!). + /// + /// Returns 1 if the trip count is unknown or not guaranteed to be the + /// multiple of a constant (which is also the case if the trip count is simply + /// constant, use getSmallConstantTripCount for that case), Will also return 1 + /// if the trip count is very large (>= 2^32). + unsigned getSmallConstantTripMultiple() const; + + /// isLCSSAForm - Return true if the Loop is in LCSSA form + bool isLCSSAForm() const; + + /// isLoopSimplifyForm - Return true if the Loop is in the form that + /// the LoopSimplify form transforms loops to, which is sometimes called + /// normal form. + bool isLoopSimplifyForm() const; + + /// hasDedicatedExits - Return true if no exit block for the loop + /// has a predecessor that is outside the loop. + bool hasDedicatedExits() const; + + /// getUniqueExitBlocks - Return all unique successor blocks of this loop. + /// These are the blocks _outside of the current loop_ which are branched to. + /// This assumes that loop is in canonical form. + /// + void getUniqueExitBlocks(SmallVectorImpl &ExitBlocks) const; + + /// getUniqueExitBlock - If getUniqueExitBlocks would return exactly one + /// block, return that block. Otherwise return null. + BasicBlock *getUniqueExitBlock() const; + +private: + friend class LoopInfoBase; + explicit Loop(BasicBlock *BB) : LoopBase(BB) {} +}; + +//===----------------------------------------------------------------------===// +/// LoopInfo - This class builds and contains all of the top level loop +/// structures in the specified function. +/// + +template +class LoopInfoBase { + // BBMap - Mapping of basic blocks to the inner most loop they occur in + std::map BBMap; + std::vector TopLevelLoops; + friend class LoopBase; + + void operator=(const LoopInfoBase &); // do not implement + LoopInfoBase(const LoopInfo &); // do not implement +public: + LoopInfoBase() { } + ~LoopInfoBase() { releaseMemory(); } + + void releaseMemory() { + for (typename std::vector::iterator I = + TopLevelLoops.begin(), E = TopLevelLoops.end(); I != E; ++I) + delete *I; // Delete all of the loops... + + BBMap.clear(); // Reset internal state of analysis + TopLevelLoops.clear(); + } + + /// iterator/begin/end - The interface to the top-level loops in the current + /// function. + /// + typedef typename std::vector::const_iterator iterator; + iterator begin() const { return TopLevelLoops.begin(); } + iterator end() const { return TopLevelLoops.end(); } + bool empty() const { return TopLevelLoops.empty(); } + + /// 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. + /// + LoopT *getLoopFor(const BlockT *BB) const { + typename std::map::const_iterator I= + BBMap.find(const_cast(BB)); + return I != BBMap.end() ? I->second : 0; + } + + /// operator[] - same as getLoopFor... + /// + const LoopT *operator[](const BlockT *BB) const { + return getLoopFor(BB); + } + + /// getLoopDepth - Return the loop nesting level of the specified block. A + /// depth of 0 means the block is not inside any loop. + /// + unsigned getLoopDepth(const BlockT *BB) const { + const LoopT *L = getLoopFor(BB); + return L ? L->getLoopDepth() : 0; + } + + // isLoopHeader - True if the block is a loop header node + bool isLoopHeader(BlockT *BB) const { + const LoopT *L = getLoopFor(BB); + return L && L->getHeader() == BB; + } + + /// 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 + /// another loop. + LoopT *removeLoop(iterator I) { + assert(I != end() && "Cannot remove end iterator!"); + LoopT *L = *I; + assert(L->getParentLoop() == 0 && "Not a top-level loop!"); + TopLevelLoops.erase(TopLevelLoops.begin() + (I-begin())); + return L; + } + + /// changeLoopFor - Change the top-level loop that contains BB to the + /// specified loop. This should be used by transformations that restructure + /// the loop hierarchy tree. + void changeLoopFor(BlockT *BB, LoopT *L) { + LoopT *&OldLoop = BBMap[BB]; + assert(OldLoop && "Block not in a loop yet!"); + OldLoop = L; + } + + /// changeTopLevelLoop - Replace the specified loop in the top-level loops + /// list with the indicated loop. + void changeTopLevelLoop(LoopT *OldLoop, + LoopT *NewLoop) { + typename std::vector::iterator I = + std::find(TopLevelLoops.begin(), TopLevelLoops.end(), OldLoop); + assert(I != TopLevelLoops.end() && "Old loop not at top level!"); + *I = NewLoop; + assert(NewLoop->ParentLoop == 0 && OldLoop->ParentLoop == 0 && + "Loops already embedded into a subloop!"); + } + + /// addTopLevelLoop - This adds the specified loop to the collection of + /// top-level loops. + void addTopLevelLoop(LoopT *New) { + assert(New->getParentLoop() == 0 && "Loop already in subloop!"); + TopLevelLoops.push_back(New); + } + + /// removeBlock - This method completely removes BB from all data structures, + /// including all of the Loop objects it is nested in and our mapping from + /// BasicBlocks to loops. + void removeBlock(BlockT *BB) { + typename std::map::iterator I = BBMap.find(BB); + if (I != BBMap.end()) { + for (LoopT *L = I->second; L; L = L->getParentLoop()) + L->removeBlockFromLoop(BB); + + BBMap.erase(I); + } + } + + // Internals + + static bool isNotAlreadyContainedIn(const LoopT *SubLoop, + const LoopT *ParentLoop) { + if (SubLoop == 0) return true; + if (SubLoop == ParentLoop) return false; + return isNotAlreadyContainedIn(SubLoop->getParentLoop(), ParentLoop); + } + + void Calculate(DominatorTreeBase &DT) { + BlockT *RootNode = DT.getRootNode()->getBlock(); + + for (df_iterator NI = df_begin(RootNode), + NE = df_end(RootNode); NI != NE; ++NI) + if (LoopT *L = ConsiderForLoop(*NI, DT)) + TopLevelLoops.push_back(L); + } + + LoopT *ConsiderForLoop(BlockT *BB, DominatorTreeBase &DT) { + if (BBMap.find(BB) != BBMap.end()) return 0;// Haven't processed this node? + + std::vector TodoStack; + + // Scan the predecessors of BB, checking to see if BB dominates any of + // them. This identifies backedges which target this node... + typedef GraphTraits > InvBlockTraits; + for (typename InvBlockTraits::ChildIteratorType I = + InvBlockTraits::child_begin(BB), E = InvBlockTraits::child_end(BB); + I != E; ++I) + if (DT.dominates(BB, *I)) // If BB dominates its predecessor... + TodoStack.push_back(*I); + + if (TodoStack.empty()) return 0; // No backedges to this block... + + // Create a new loop to represent this basic block... + LoopT *L = new LoopT(BB); + BBMap[BB] = L; + + BlockT *EntryBlock = BB->getParent()->begin(); + + while (!TodoStack.empty()) { // Process all the nodes in the loop + BlockT *X = TodoStack.back(); + TodoStack.pop_back(); + + if (!L->contains(X) && // As of yet unprocessed?? + DT.dominates(EntryBlock, X)) { // X is reachable from entry block? + // Check to see if this block already belongs to a loop. If this occurs + // then we have a case where a loop that is supposed to be a child of + // the current loop was processed before the current loop. When this + // occurs, this child loop gets added to a part of the current loop, + // making it a sibling to the current loop. We have to reparent this + // loop. + if (LoopT *SubLoop = + const_cast(getLoopFor(X))) + if (SubLoop->getHeader() == X && isNotAlreadyContainedIn(SubLoop, L)){ + // Remove the subloop from its current parent... + assert(SubLoop->ParentLoop && SubLoop->ParentLoop != L); + LoopT *SLP = SubLoop->ParentLoop; // SubLoopParent + typename std::vector::iterator I = + std::find(SLP->SubLoops.begin(), SLP->SubLoops.end(), SubLoop); + assert(I != SLP->SubLoops.end() &&"SubLoop not a child of parent?"); + SLP->SubLoops.erase(I); // Remove from parent... + + // Add the subloop to THIS loop... + SubLoop->ParentLoop = L; + L->SubLoops.push_back(SubLoop); + } + + // Normal case, add the block to our loop... + L->Blocks.push_back(X); + + typedef GraphTraits > InvBlockTraits; + + // Add all of the predecessors of X to the end of the work stack... + TodoStack.insert(TodoStack.end(), InvBlockTraits::child_begin(X), + InvBlockTraits::child_end(X)); + } + } + + // If there are any loops nested within this loop, create them now! + for (typename std::vector::iterator I = L->Blocks.begin(), + E = L->Blocks.end(); I != E; ++I) + if (LoopT *NewLoop = ConsiderForLoop(*I, DT)) { + L->SubLoops.push_back(NewLoop); + NewLoop->ParentLoop = L; + } + + // Add the basic blocks that comprise this loop to the BBMap so that this + // loop can be found for them. + // + for (typename std::vector::iterator I = L->Blocks.begin(), + E = L->Blocks.end(); I != E; ++I) + BBMap.insert(std::make_pair(*I, L)); + + // Now that we have a list of all of the child loops of this loop, check to + // see if any of them should actually be nested inside of each other. We + // can accidentally pull loops our of their parents, so we must make sure to + // organize the loop nests correctly now. + { + std::map ContainingLoops; + for (unsigned i = 0; i != L->SubLoops.size(); ++i) { + LoopT *Child = L->SubLoops[i]; + assert(Child->getParentLoop() == L && "Not proper child loop?"); + + if (LoopT *ContainingLoop = ContainingLoops[Child->getHeader()]) { + // If there is already a loop which contains this loop, move this loop + // into the containing loop. + MoveSiblingLoopInto(Child, ContainingLoop); + --i; // The loop got removed from the SubLoops list. + } else { + // This is currently considered to be a top-level loop. Check to see + // if any of the contained blocks are loop headers for subloops we + // have already processed. + for (unsigned b = 0, e = Child->Blocks.size(); b != e; ++b) { + LoopT *&BlockLoop = ContainingLoops[Child->Blocks[b]]; + if (BlockLoop == 0) { // Child block not processed yet... + BlockLoop = Child; + } else if (BlockLoop != Child) { + LoopT *SubLoop = BlockLoop; + // Reparent all of the blocks which used to belong to BlockLoops + for (unsigned j = 0, e = SubLoop->Blocks.size(); j != e; ++j) + ContainingLoops[SubLoop->Blocks[j]] = Child; + + // There is already a loop which contains this block, that means + // that we should reparent the loop which the block is currently + // considered to belong to to be a child of this loop. + MoveSiblingLoopInto(SubLoop, Child); + --i; // We just shrunk the SubLoops list. + } + } + } + } + } + + return L; + } + + /// MoveSiblingLoopInto - This method moves the NewChild loop to live inside + /// of the NewParent Loop, instead of being a sibling of it. + void MoveSiblingLoopInto(LoopT *NewChild, + LoopT *NewParent) { + LoopT *OldParent = NewChild->getParentLoop(); + assert(OldParent && OldParent == NewParent->getParentLoop() && + NewChild != NewParent && "Not sibling loops!"); + + // Remove NewChild from being a child of OldParent + typename std::vector::iterator I = + std::find(OldParent->SubLoops.begin(), OldParent->SubLoops.end(), + NewChild); + assert(I != OldParent->SubLoops.end() && "Parent fields incorrect??"); + OldParent->SubLoops.erase(I); // Remove from parent's subloops list + NewChild->ParentLoop = 0; + + InsertLoopInto(NewChild, NewParent); + } + + /// InsertLoopInto - This inserts loop L into the specified parent loop. If + /// the parent loop contains a loop which should contain L, the loop gets + /// inserted into L instead. + void InsertLoopInto(LoopT *L, LoopT *Parent) { + BlockT *LHeader = L->getHeader(); + assert(Parent->contains(LHeader) && + "This loop should not be inserted here!"); + + // Check to see if it belongs in a child loop... + for (unsigned i = 0, e = static_cast(Parent->SubLoops.size()); + i != e; ++i) + if (Parent->SubLoops[i]->contains(LHeader)) { + InsertLoopInto(L, Parent->SubLoops[i]); + return; + } + + // If not, insert it here! + Parent->SubLoops.push_back(L); + L->ParentLoop = Parent; + } + + // Debugging + + void print(raw_ostream &OS) const { + for (unsigned i = 0; i < TopLevelLoops.size(); ++i) + TopLevelLoops[i]->print(OS); + #if 0 + for (std::map::const_iterator I = BBMap.begin(), + E = BBMap.end(); I != E; ++I) + OS << "BB '" << I->first->getName() << "' level = " + << I->second->getLoopDepth() << "\n"; + #endif + } +}; + +class LoopInfo : public FunctionPass { + LoopInfoBase LI; + friend class LoopBase; + + void operator=(const LoopInfo &); // do not implement + LoopInfo(const LoopInfo &); // do not implement +public: + static char ID; // Pass identification, replacement for typeid + + LoopInfo() : FunctionPass(&ID) {} + + LoopInfoBase& getBase() { return LI; } + + /// iterator/begin/end - The interface to the top-level loops in the current + /// function. + /// + typedef LoopInfoBase::iterator iterator; + inline iterator begin() const { return LI.begin(); } + inline iterator end() const { return LI.end(); } + bool empty() const { return LI.empty(); } + + /// 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. + /// + inline Loop *getLoopFor(const BasicBlock *BB) const { + return LI.getLoopFor(BB); + } + + /// operator[] - same as getLoopFor... + /// + inline const Loop *operator[](const BasicBlock *BB) const { + return LI.getLoopFor(BB); + } + + /// getLoopDepth - Return the loop nesting level of the specified block. A + /// depth of 0 means the block is not inside any loop. + /// + inline unsigned getLoopDepth(const BasicBlock *BB) const { + return LI.getLoopDepth(BB); + } + + // isLoopHeader - True if the block is a loop header node + inline bool isLoopHeader(BasicBlock *BB) const { + return LI.isLoopHeader(BB); + } + + /// runOnFunction - Calculate the natural loop information. + /// + virtual bool runOnFunction(Function &F); + + virtual void verifyAnalysis() const; + + virtual void releaseMemory() { LI.releaseMemory(); } + + virtual void print(raw_ostream &O, const Module* M = 0) const; + + virtual void getAnalysisUsage(AnalysisUsage &AU) const; + + /// 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 + /// another loop. + inline Loop *removeLoop(iterator I) { return LI.removeLoop(I); } + + /// changeLoopFor - Change the top-level loop that contains BB to the + /// specified loop. This should be used by transformations that restructure + /// the loop hierarchy tree. + inline void changeLoopFor(BasicBlock *BB, Loop *L) { + LI.changeLoopFor(BB, L); + } + + /// changeTopLevelLoop - Replace the specified loop in the top-level loops + /// list with the indicated loop. + inline void changeTopLevelLoop(Loop *OldLoop, Loop *NewLoop) { + LI.changeTopLevelLoop(OldLoop, NewLoop); + } + + /// addTopLevelLoop - This adds the specified loop to the collection of + /// top-level loops. + inline void addTopLevelLoop(Loop *New) { + LI.addTopLevelLoop(New); + } + + /// removeBlock - This method completely removes BB from all data structures, + /// including all of the Loop objects it is nested in and our mapping from + /// BasicBlocks to loops. + void removeBlock(BasicBlock *BB) { + LI.removeBlock(BB); + } + + static bool isNotAlreadyContainedIn(const Loop *SubLoop, + const Loop *ParentLoop) { + return + LoopInfoBase::isNotAlreadyContainedIn(SubLoop, + ParentLoop); + } +}; + + +// Allow clients to walk the list of nested loops... +template <> struct GraphTraits { + typedef const Loop NodeType; + typedef LoopInfo::iterator ChildIteratorType; + + static NodeType *getEntryNode(const Loop *L) { return L; } + static inline ChildIteratorType child_begin(NodeType *N) { + return N->begin(); + } + static inline ChildIteratorType child_end(NodeType *N) { + return N->end(); + } +}; + +template <> struct GraphTraits { + typedef Loop NodeType; + typedef LoopInfo::iterator ChildIteratorType; + + static NodeType *getEntryNode(Loop *L) { return L; } + static inline ChildIteratorType child_begin(NodeType *N) { + return N->begin(); + } + static inline ChildIteratorType child_end(NodeType *N) { + return N->end(); + } +}; + +template +void +LoopBase::addBasicBlockToLoop(BlockT *NewBB, + LoopInfoBase &LIB) { + assert((Blocks.empty() || LIB[getHeader()] == this) && + "Incorrect LI specified for this loop!"); + assert(NewBB && "Cannot add a null basic block to the loop!"); + assert(LIB[NewBB] == 0 && "BasicBlock already in the loop!"); + + LoopT *L = static_cast(this); + + // Add the loop mapping to the LoopInfo object... + LIB.BBMap[NewBB] = L; + + // Add the basic block to this loop and all parent loops... + while (L) { + L->Blocks.push_back(NewBB); + L = L->getParentLoop(); + } +} + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Analysis/LoopPass.h b/libclamav/c++/llvm/include/llvm/Analysis/LoopPass.h new file mode 100644 index 000000000..2eb329f7f --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Analysis/LoopPass.h @@ -0,0 +1,151 @@ +//===- LoopPass.h - LoopPass class ----------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines LoopPass class. All loop optimization +// and transformation passes are derived from LoopPass. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LOOP_PASS_H +#define LLVM_LOOP_PASS_H + +#include "llvm/Analysis/LoopInfo.h" +#include "llvm/Pass.h" +#include "llvm/PassManagers.h" +#include "llvm/Function.h" + +namespace llvm { + +class LPPassManager; +class Function; +class PMStack; + +class LoopPass : public Pass { +public: + explicit LoopPass(intptr_t pid) : Pass(pid) {} + explicit LoopPass(void *pid) : Pass(pid) {} + + // runOnLoop - This method should be implemented by the subclass to perform + // whatever action is necessary for the specified Loop. + virtual bool runOnLoop(Loop *L, LPPassManager &LPM) = 0; + + // Initialization and finalization hooks. + virtual bool doInitialization(Loop *L, LPPassManager &LPM) { + return false; + } + + // Finalization hook does not supply Loop because at this time + // loop nest is completely different. + virtual bool doFinalization() { return false; } + + // Check if this pass is suitable for the current LPPassManager, if + // available. This pass P is not suitable for a LPPassManager if P + // is not preserving higher level analysis info used by other + // LPPassManager passes. In such case, pop LPPassManager from the + // stack. This will force assignPassManager() to create new + // LPPassManger as expected. + void preparePassManager(PMStack &PMS); + + /// Assign pass manager to manager this pass + virtual void assignPassManager(PMStack &PMS, + PassManagerType PMT = PMT_LoopPassManager); + + /// Return what kind of Pass Manager can manage this pass. + virtual PassManagerType getPotentialPassManagerType() const { + return PMT_LoopPassManager; + } + + //===--------------------------------------------------------------------===// + /// SimpleAnalysis - Provides simple interface to update analysis info + /// maintained by various passes. Note, if required this interface can + /// be extracted into a separate abstract class but it would require + /// additional use of multiple inheritance in Pass class hierarchy, something + /// we are trying to avoid. + + /// Each loop pass can override these simple analysis hooks to update + /// desired analysis information. + /// cloneBasicBlockAnalysis - Clone analysis info associated with basic block. + virtual void cloneBasicBlockAnalysis(BasicBlock *F, BasicBlock *T, Loop *L) {} + + /// deletekAnalysisValue - Delete analysis info associated with value V. + virtual void deleteAnalysisValue(Value *V, Loop *L) {} +}; + +class LPPassManager : public FunctionPass, public PMDataManager { +public: + static char ID; + explicit LPPassManager(int Depth); + + /// 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. + bool runOnFunction(Function &F); + + /// Pass Manager itself does not invalidate any analysis info. + // LPPassManager needs LoopInfo. + void getAnalysisUsage(AnalysisUsage &Info) const; + + virtual const char *getPassName() const { + return "Loop Pass Manager"; + } + + /// Print passes managed by this manager + void dumpPassStructure(unsigned Offset); + + Pass *getContainedPass(unsigned N) { + assert(N < PassVector.size() && "Pass number out of range!"); + Pass *FP = static_cast(PassVector[N]); + return FP; + } + + virtual PassManagerType getPassManagerType() const { + return PMT_LoopPassManager; + } + +public: + // Delete loop from the loop queue and loop nest (LoopInfo). + void deleteLoopFromQueue(Loop *L); + + // Insert loop into the loop queue and add it as a child of the + // given parent. + void insertLoop(Loop *L, Loop *ParentLoop); + + // Insert a loop into the loop queue. + void insertLoopIntoQueue(Loop *L); + + // Reoptimize this loop. LPPassManager will re-insert this loop into the + // queue. This allows LoopPass to change loop nest for the loop. This + // utility may send LPPassManager into infinite loops so use caution. + void redoLoop(Loop *L); + + //===--------------------------------------------------------------------===// + /// SimpleAnalysis - Provides simple interface to update analysis info + /// maintained by various passes. Note, if required this interface can + /// be extracted into a separate abstract class but it would require + /// additional use of multiple inheritance in Pass class hierarchy, something + /// we are trying to avoid. + + /// cloneBasicBlockSimpleAnalysis - Invoke cloneBasicBlockAnalysis hook for + /// all passes that implement simple analysis interface. + void cloneBasicBlockSimpleAnalysis(BasicBlock *From, BasicBlock *To, Loop *L); + + /// deleteSimpleAnalysisValue - Invoke deleteAnalysisValue hook for all passes + /// that implement simple analysis interface. + void deleteSimpleAnalysisValue(Value *V, Loop *L); + +private: + std::deque LQ; + bool skipThisLoop; + bool redoThisLoop; + LoopInfo *LI; + Loop *CurrentLoop; +}; + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Analysis/MemoryBuiltins.h b/libclamav/c++/llvm/include/llvm/Analysis/MemoryBuiltins.h new file mode 100644 index 000000000..f6fa0c8d1 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Analysis/MemoryBuiltins.h @@ -0,0 +1,80 @@ +//===- llvm/Analysis/MemoryBuiltins.h- Calls to memory builtins -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This family of functions identifies calls to builtin functions that allocate +// or free memory. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_MEMORYBUILTINS_H +#define LLVM_ANALYSIS_MEMORYBUILTINS_H + +namespace llvm { +class CallInst; +class PointerType; +class TargetData; +class Type; +class Value; + +//===----------------------------------------------------------------------===// +// malloc Call Utility Functions. +// + +/// isMalloc - Returns true if the value is either a malloc call or a bitcast of +/// the result of a malloc call +bool isMalloc(const Value *I); + +/// extractMallocCall - Returns the corresponding CallInst if the instruction +/// is a malloc call. Since CallInst::CreateMalloc() only creates calls, we +/// ignore InvokeInst here. +const CallInst *extractMallocCall(const Value *I); +CallInst *extractMallocCall(Value *I); + +/// extractMallocCallFromBitCast - Returns the corresponding CallInst if the +/// instruction is a bitcast of the result of a malloc call. +const CallInst *extractMallocCallFromBitCast(const Value *I); +CallInst *extractMallocCallFromBitCast(Value *I); + +/// isArrayMalloc - Returns the corresponding CallInst if the instruction +/// is a call to malloc whose array size can be determined and the array size +/// is not constant 1. Otherwise, return NULL. +const CallInst *isArrayMalloc(const Value *I, const TargetData *TD); + +/// getMallocType - Returns the PointerType resulting from the malloc call. +/// The PointerType depends on the number of bitcast uses of the malloc call: +/// 0: PointerType is the malloc calls' return type. +/// 1: PointerType is the bitcast's result type. +/// >1: Unique PointerType cannot be determined, return NULL. +const PointerType *getMallocType(const CallInst *CI); + +/// getMallocAllocatedType - Returns the Type allocated by malloc call. +/// The Type depends on the number of bitcast uses of the malloc call: +/// 0: PointerType is the malloc calls' return type. +/// 1: PointerType is the bitcast's result type. +/// >1: Unique PointerType cannot be determined, return NULL. +const Type *getMallocAllocatedType(const CallInst *CI); + +/// 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, +/// then return that multiple. For non-array mallocs, the multiple is +/// constant 1. Otherwise, return NULL for mallocs whose array size cannot be +/// determined. +Value *getMallocArraySize(CallInst *CI, const TargetData *TD, + bool LookThroughSExt = false); + +//===----------------------------------------------------------------------===// +// free Call Utility Functions. +// + +/// isFreeCall - Returns true if the the value is a call to the builtin free() +bool isFreeCall(const Value *I); + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Analysis/MemoryDependenceAnalysis.h b/libclamav/c++/llvm/include/llvm/Analysis/MemoryDependenceAnalysis.h new file mode 100644 index 000000000..042c7fc73 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Analysis/MemoryDependenceAnalysis.h @@ -0,0 +1,301 @@ +//===- llvm/Analysis/MemoryDependenceAnalysis.h - Memory Deps --*- 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 the MemoryDependenceAnalysis analysis pass. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_MEMORY_DEPENDENCE_H +#define LLVM_ANALYSIS_MEMORY_DEPENDENCE_H + +#include "llvm/BasicBlock.h" +#include "llvm/Pass.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/PointerIntPair.h" + +namespace llvm { + class Function; + class FunctionPass; + class Instruction; + class CallSite; + class AliasAnalysis; + class TargetData; + class MemoryDependenceAnalysis; + class PredIteratorCache; + + /// MemDepResult - A memory dependence query can return one of three different + /// answers, described below. + class MemDepResult { + enum DepType { + /// Invalid - Clients of MemDep never see this. + Invalid = 0, + + /// Clobber - This is a dependence on the specified instruction which + /// clobbers the desired value. The pointer member of the MemDepResult + /// pair holds the instruction that clobbers the memory. For example, + /// this occurs when we see a may-aliased store to the memory location we + /// care about. + Clobber, + + /// Def - This is a dependence on the specified instruction which + /// defines/produces the desired memory location. The pointer member of + /// the MemDepResult pair holds the instruction that defines the memory. + /// Cases of interest: + /// 1. This could be a load or store for dependence queries on + /// load/store. The value loaded or stored is the produced value. + /// Note that the pointer operand may be different than that of the + /// queried pointer due to must aliases and phi translation. Note + /// that the def may not be the same type as the query, the pointers + /// may just be must aliases. + /// 2. For loads and stores, this could be an allocation instruction. In + /// this case, the load is loading an undef value or a store is the + /// first store to (that part of) the allocation. + /// 3. Dependence queries on calls return Def only when they are + /// readonly calls with identical callees and no intervening + /// clobbers. No validation is done that the operands to the calls + /// are the same. + Def, + + /// NonLocal - This marker indicates that the query has no dependency in + /// the specified block. To find out more, the client should query other + /// predecessor blocks. + NonLocal + }; + typedef PointerIntPair PairTy; + PairTy Value; + explicit MemDepResult(PairTy V) : Value(V) {} + public: + MemDepResult() : Value(0, Invalid) {} + + /// get methods: These are static ctor methods for creating various + /// MemDepResult kinds. + static MemDepResult getDef(Instruction *Inst) { + return MemDepResult(PairTy(Inst, Def)); + } + static MemDepResult getClobber(Instruction *Inst) { + return MemDepResult(PairTy(Inst, Clobber)); + } + static MemDepResult getNonLocal() { + return MemDepResult(PairTy(0, NonLocal)); + } + + /// isClobber - Return true if this MemDepResult represents a query that is + /// a instruction clobber dependency. + bool isClobber() const { return Value.getInt() == Clobber; } + + /// isDef - Return true if this MemDepResult represents a query that is + /// a instruction definition dependency. + bool isDef() const { return Value.getInt() == Def; } + + /// 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 + /// been done. + bool isNonLocal() const { return Value.getInt() == NonLocal; } + + /// getInst() - If this is a normal dependency, return the instruction that + /// is depended on. Otherwise, return null. + Instruction *getInst() const { 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; } + private: + friend class MemoryDependenceAnalysis; + /// Dirty - Entries with this marker occur in a LocalDeps map or + /// NonLocalDeps map when the instruction they previously referenced was + /// removed from MemDep. In either case, the entry may include an + /// instruction pointer. If so, the pointer is an instruction in the + /// block where scanning can start from, saving some work. + /// + /// In a default-constructed MemDepResult object, the type will be Dirty + /// and the instruction pointer will be null. + /// + + /// isDirty - Return true if this is a MemDepResult in its dirty/invalid. + /// state. + bool isDirty() const { return Value.getInt() == Invalid; } + + static MemDepResult getDirty(Instruction *Inst) { + return MemDepResult(PairTy(Inst, Invalid)); + } + }; + + /// MemoryDependenceAnalysis - This is an analysis that determines, for a + /// given memory operation, what preceding memory operations it depends on. + /// It builds on alias analysis information, and tries to provide a lazy, + /// caching interface to a common kind of alias information query. + /// + /// The dependency information returned is somewhat unusual, but is pragmatic. + /// If queried about a store or call that might modify memory, the analysis + /// will return the instruction[s] that may either load from that memory or + /// store to it. If queried with a load or call that can never modify memory, + /// the analysis will return calls and stores that might modify the pointer, + /// but generally does not return loads unless a) they are volatile, or + /// b) they load from *must-aliased* pointers. Returning a dependence on + /// must-alias'd pointers instead of all pointers interacts well with the + /// internal caching mechanism. + /// + class MemoryDependenceAnalysis : public FunctionPass { + // A map from instructions to their dependency. + typedef DenseMap LocalDepMapType; + LocalDepMapType LocalDeps; + + public: + typedef std::pair NonLocalDepEntry; + typedef std::vector NonLocalDepInfo; + private: + /// ValueIsLoadPair - This is a pair where the bool is true if + /// the dependence is a read only dependence, false if read/write. + typedef PointerIntPair ValueIsLoadPair; + + /// BBSkipFirstBlockPair - This pair is used when caching information for a + /// block. If the pointer is null, the cache value is not a full query that + /// starts at the specified block. If non-null, the bool indicates whether + /// or not the contents of the block was skipped. + typedef PointerIntPair BBSkipFirstBlockPair; + + /// CachedNonLocalPointerInfo - This map stores the cached results of doing + /// a pointer lookup at the bottom of a block. The key of this map is the + /// pointer+isload bit, the value is a list of result> mappings. + typedef DenseMap > CachedNonLocalPointerInfo; + CachedNonLocalPointerInfo NonLocalPointerDeps; + + // A map from instructions to their non-local pointer dependencies. + typedef DenseMap > ReverseNonLocalPtrDepTy; + ReverseNonLocalPtrDepTy ReverseNonLocalPtrDeps; + + + /// PerInstNLInfo - This is the instruction we keep for each cached access + /// that we have for an instruction. The pointer is an owning pointer and + /// the bool indicates whether we have any dirty bits in the set. + typedef std::pair PerInstNLInfo; + + // A map from instructions to their non-local dependencies. + typedef DenseMap NonLocalDepMapType; + + NonLocalDepMapType NonLocalDeps; + + // A reverse mapping from dependencies to the dependees. This is + // used when removing instructions to keep the cache coherent. + typedef DenseMap > ReverseDepMapType; + ReverseDepMapType ReverseLocalDeps; + + // A reverse mapping form dependencies to the non-local dependees. + ReverseDepMapType ReverseNonLocalDeps; + + /// Current AA implementation, just a cache. + AliasAnalysis *AA; + TargetData *TD; + OwningPtr PredCache; + public: + MemoryDependenceAnalysis(); + ~MemoryDependenceAnalysis(); + static char ID; + + /// Pass Implementation stuff. This doesn't do any analysis eagerly. + bool runOnFunction(Function &); + + /// Clean up memory in between runs + void releaseMemory(); + + /// getAnalysisUsage - Does not modify anything. It uses Value Numbering + /// and Alias Analysis. + /// + virtual void getAnalysisUsage(AnalysisUsage &AU) const; + + /// getDependency - Return the instruction on which a memory operation + /// depends. See the class comment for more details. It is illegal to call + /// this on non-memory instructions. + MemDepResult getDependency(Instruction *QueryInst); + + /// getNonLocalCallDependency - Perform a full dependency query for the + /// specified call, returning the set of blocks that the value is + /// potentially live across. The returned set of results will include a + /// "NonLocal" result for all blocks where the value is live across. + /// + /// This method assumes the instruction returns a "NonLocal" dependency + /// within its own block. + /// + /// This returns a reference to an internal data structure that may be + /// invalidated on the next non-local query or when an instruction is + /// removed. Clients must copy this data if they want it around longer than + /// that. + const NonLocalDepInfo &getNonLocalCallDependency(CallSite QueryCS); + + + /// getNonLocalPointerDependency - Perform a full dependency query for an + /// access to the specified (non-volatile) memory location, returning the + /// set of instructions that either define or clobber the value. + /// + /// This method assumes the pointer has a "NonLocal" dependency within BB. + void getNonLocalPointerDependency(Value *Pointer, bool isLoad, + BasicBlock *BB, + SmallVectorImpl &Result); + + /// PHITranslatePointer - Find an available version of the specified value + /// PHI translated across the specified edge. If MemDep isn't able to + /// satisfy this request, it returns null. + Value *PHITranslatePointer(Value *V, + BasicBlock *CurBB, BasicBlock *PredBB, + const TargetData *TD) const; + + /// InsertPHITranslatedPointer - Insert a computation of the PHI translated + /// version of 'V' for the edge PredBB->CurBB into the end of the PredBB + /// block. + Value *InsertPHITranslatedPointer(Value *V, + BasicBlock *CurBB, BasicBlock *PredBB, + const TargetData *TD) const; + + /// removeInstruction - Remove an instruction from the dependence analysis, + /// updating the dependence of instructions that previously depended on it. + void removeInstruction(Instruction *InstToRemove); + + /// invalidateCachedPointerInfo - This method is used to invalidate cached + /// information about the specified pointer, because it may be too + /// conservative in memdep. This is an optional call that can be used when + /// the client detects an equivalence between the pointer and some other + /// value and replaces the other value with ptr. This can make Ptr available + /// in more places that cached info does not necessarily keep. + void invalidateCachedPointerInfo(Value *Ptr); + + private: + MemDepResult getPointerDependencyFrom(Value *Pointer, uint64_t MemSize, + bool isLoad, + BasicBlock::iterator ScanIt, + BasicBlock *BB); + MemDepResult getCallSiteDependencyFrom(CallSite C, bool isReadOnlyCall, + BasicBlock::iterator ScanIt, + BasicBlock *BB); + bool getNonLocalPointerDepFromBB(Value *Pointer, uint64_t Size, + bool isLoad, BasicBlock *BB, + SmallVectorImpl &Result, + DenseMap &Visited, + bool SkipFirstBlock = false); + MemDepResult GetNonLocalInfoForBlock(Value *Pointer, uint64_t PointeeSize, + bool isLoad, BasicBlock *BB, + NonLocalDepInfo *Cache, + unsigned NumSortedEntries); + + void RemoveCachedNonLocalPointerDependencies(ValueIsLoadPair P); + + /// verifyRemoved - Verify that the specified instruction does not occur + /// in our internal data structures. + void verifyRemoved(Instruction *Inst) const; + + }; + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Analysis/Passes.h b/libclamav/c++/llvm/include/llvm/Analysis/Passes.h new file mode 100644 index 000000000..b22232122 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Analysis/Passes.h @@ -0,0 +1,164 @@ +//===-- llvm/Analysis/Passes.h - Constructors for analyses ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This header file defines prototypes for accessor functions that expose passes +// in the analysis libraries. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_PASSES_H +#define LLVM_ANALYSIS_PASSES_H + +namespace llvm { + class FunctionPass; + class ImmutablePass; + class LoopPass; + class ModulePass; + class Pass; + class PassInfo; + class LibCallInfo; + + //===--------------------------------------------------------------------===// + // + // createGlobalsModRefPass - This pass provides alias and mod/ref info for + // global values that do not have their addresses taken. + // + Pass *createGlobalsModRefPass(); + + //===--------------------------------------------------------------------===// + // + // createAliasDebugger - This pass helps debug clients of AA + // + Pass *createAliasDebugger(); + + //===--------------------------------------------------------------------===// + // + // createAliasAnalysisCounterPass - This pass counts alias queries and how the + // alias analysis implementation responds. + // + ModulePass *createAliasAnalysisCounterPass(); + + //===--------------------------------------------------------------------===// + // + // createAAEvalPass - This pass implements a simple N^2 alias analysis + // accuracy evaluator. + // + FunctionPass *createAAEvalPass(); + + //===--------------------------------------------------------------------===// + // + // createNoAAPass - This pass implements a "I don't know" alias analysis. + // + ImmutablePass *createNoAAPass(); + + //===--------------------------------------------------------------------===// + // + // createBasicAliasAnalysisPass - This pass implements the default alias + // analysis. + // + ImmutablePass *createBasicAliasAnalysisPass(); + + //===--------------------------------------------------------------------===// + // + /// createLibCallAliasAnalysisPass - Create an alias analysis pass that knows + /// about the semantics of a set of libcalls specified by LCI. The newly + /// constructed pass takes ownership of the pointer that is provided. + /// + FunctionPass *createLibCallAliasAnalysisPass(LibCallInfo *LCI); + + //===--------------------------------------------------------------------===// + // + // createScalarEvolutionAliasAnalysisPass - This pass implements a simple + // alias analysis using ScalarEvolution queries. + // + FunctionPass *createScalarEvolutionAliasAnalysisPass(); + + //===--------------------------------------------------------------------===// + // + // createAndersensPass - This pass implements Andersen's interprocedural alias + // analysis. + // + ModulePass *createAndersensPass(); + + //===--------------------------------------------------------------------===// + // + // createProfileLoaderPass - This pass loads information from a profile dump + // file. + // + ModulePass *createProfileLoaderPass(); + + //===--------------------------------------------------------------------===// + // + // createNoProfileInfoPass - This pass implements the default "no profile". + // + ImmutablePass *createNoProfileInfoPass(); + + //===--------------------------------------------------------------------===// + // + // createProfileEstimatorPass - This pass estimates profiling information + // instead of loading it from a previous run. + // + FunctionPass *createProfileEstimatorPass(); + extern const PassInfo *ProfileEstimatorPassID; + + //===--------------------------------------------------------------------===// + // + // createProfileVerifierPass - This pass verifies profiling information. + // + FunctionPass *createProfileVerifierPass(); + + //===--------------------------------------------------------------------===// + // + // createDSAAPass - This pass implements simple context sensitive alias + // analysis. + // + ModulePass *createDSAAPass(); + + //===--------------------------------------------------------------------===// + // + // createDSOptPass - This pass uses DSA to do a series of simple + // optimizations. + // + ModulePass *createDSOptPass(); + + //===--------------------------------------------------------------------===// + // + // createSteensgaardPass - This pass uses the data structure graphs to do a + // simple context insensitive alias analysis. + // + ModulePass *createSteensgaardPass(); + + //===--------------------------------------------------------------------===// + // + // createLiveValuesPass - This creates an instance of the LiveValues pass. + // + FunctionPass *createLiveValuesPass(); + + //===--------------------------------------------------------------------===// + // + /// createLazyValueInfoPass - This creates an instance of the LazyValueInfo + /// pass. + FunctionPass *createLazyValueInfoPass(); + + //===--------------------------------------------------------------------===// + // + // createLoopDependenceAnalysisPass - This creates an instance of the + // LoopDependenceAnalysis pass. + // + LoopPass *createLoopDependenceAnalysisPass(); + + // Minor pass prototypes, allowing us to expose them through bugpoint and + // analyze. + FunctionPass *createInstCountPass(); + + // print debug info intrinsics in human readable form + FunctionPass *createDbgInfoPrinterPass(); +} + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Analysis/PointerTracking.h b/libclamav/c++/llvm/include/llvm/Analysis/PointerTracking.h new file mode 100644 index 000000000..a14bbf029 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Analysis/PointerTracking.h @@ -0,0 +1,131 @@ +//===- PointerTracking.h - Pointer Bounds Tracking --------------*- 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 tracking of pointer bounds. +// It knows that the libc functions "calloc" and "realloc" allocate memory, thus +// you should avoid using this pass if they mean something else for your +// language. +// +// All methods assume that the pointer is not NULL, if it is then the returned +// allocation size is wrong, and the result from checkLimits is wrong too. +// It also assumes that pointers are valid, and that it is not analyzing a +// use-after-free scenario. +// Due to these limitations the "size" returned by these methods should be +// considered as either 0 or the returned size. +// +// Another analysis pass should be used to find use-after-free/NULL dereference +// bugs. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_POINTERTRACKING_H +#define LLVM_ANALYSIS_POINTERTRACKING_H + +#include "llvm/ADT/SmallSet.h" +#include "llvm/Analysis/Dominators.h" +#include "llvm/Instructions.h" +#include "llvm/Pass.h" +#include "llvm/Support/PredIteratorCache.h" + +namespace llvm { + class DominatorTree; + class ScalarEvolution; + class SCEV; + class Loop; + class LoopInfo; + class TargetData; + + // Result from solver, assuming pointer is not NULL, + // and it is not a use-after-free situation. + enum SolverResult { + AlwaysFalse,// always false with above constraints + AlwaysTrue,// always true with above constraints + Unknown // it can sometimes be true, sometimes false, or it is undecided + }; + + class PointerTracking : public FunctionPass { + public: + typedef ICmpInst::Predicate Predicate; + static char ID; + PointerTracking(); + + virtual bool doInitialization(Module &M); + + // If this pointer directly points to an allocation, return + // the number of elements of type Ty allocated. + // Otherwise return CouldNotCompute. + // Since allocations can fail by returning NULL, the real element count + // for every allocation is either 0 or the value returned by this function. + const SCEV *getAllocationElementCount(Value *P) const; + + // Same as getAllocationSize() but returns size in bytes. + // We consider one byte as 8 bits. + const SCEV *getAllocationSizeInBytes(Value *V) const; + + // Given a Pointer, determine a base pointer of known size, and an offset + // therefrom. + // When unable to determine, sets Base to NULL, and Limit/Offset to + // CouldNotCompute. + // BaseSize, and Offset are in bytes: Pointer == Base + Offset + void getPointerOffset(Value *Pointer, Value *&Base, const SCEV *& BaseSize, + const SCEV *&Offset) const; + + // Compares the 2 scalar evolution expressions according to predicate, + // and if it can prove that the result is always true or always false + // return AlwaysTrue/AlwaysFalse. Otherwise it returns Unknown. + enum SolverResult compareSCEV(const SCEV *A, Predicate Pred, const SCEV *B, + const Loop *L); + + // Determines whether the condition LHS RHS is sufficient + // for the condition A B to hold. + // Currently only ULT/ULE is supported. + // This errs on the side of returning false. + bool conditionSufficient(const SCEV *LHS, Predicate Pred1, const SCEV *RHS, + const SCEV *A, Predicate Pred2, const SCEV *B, + const Loop *L); + + // Determines whether Offset is known to be always in [0, Limit) bounds. + // This errs on the side of returning Unknown. + enum SolverResult checkLimits(const SCEV *Offset, const SCEV *Limit, + BasicBlock *BB); + + virtual bool runOnFunction(Function &F); + virtual void getAnalysisUsage(AnalysisUsage &AU) const; + void print(raw_ostream &OS, const Module* = 0) const; + private: + Function *FF; + TargetData *TD; + ScalarEvolution *SE; + LoopInfo *LI; + DominatorTree *DT; + + Function *callocFunc; + Function *reallocFunc; + PredIteratorCache predCache; + + SmallPtrSet analyzing; + + enum SolverResult isLoopGuardedBy(const Loop *L, Predicate Pred, + const SCEV *A, const SCEV *B) const; + static bool isMonotonic(const SCEV *S); + bool scevPositive(const SCEV *A, const Loop *L, bool strict=true) const; + bool conditionSufficient(Value *Cond, bool negated, + const SCEV *A, Predicate Pred, const SCEV *B); + Value *getConditionToReach(BasicBlock *A, + DomTreeNodeBase *B, + bool &negated); + Value *getConditionToReach(BasicBlock *A, + BasicBlock *B, + bool &negated); + const SCEV *computeAllocationCount(Value *P, const Type *&Ty) const; + const SCEV *computeAllocationCountForType(Value *P, const Type *Ty) const; + }; +} +#endif + diff --git a/libclamav/c++/llvm/include/llvm/Analysis/PostDominators.h b/libclamav/c++/llvm/include/llvm/Analysis/PostDominators.h new file mode 100644 index 000000000..42a16e74a --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Analysis/PostDominators.h @@ -0,0 +1,123 @@ +//=- llvm/Analysis/PostDominators.h - Post Dominator Calculation-*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file exposes interfaces to post dominance information. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_POST_DOMINATORS_H +#define LLVM_ANALYSIS_POST_DOMINATORS_H + +#include "llvm/Analysis/Dominators.h" + +namespace llvm { + +/// PostDominatorTree Class - Concrete subclass of DominatorTree that is used to +/// compute the a post-dominator tree. +/// +struct PostDominatorTree : public FunctionPass { + static char ID; // Pass identification, replacement for typeid + DominatorTreeBase* DT; + + PostDominatorTree() : FunctionPass(&ID) { + DT = new DominatorTreeBase(true); + } + + ~PostDominatorTree(); + + virtual bool runOnFunction(Function &F); + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + } + + inline const std::vector &getRoots() const { + return DT->getRoots(); + } + + inline DomTreeNode *getRootNode() const { + return DT->getRootNode(); + } + + inline DomTreeNode *operator[](BasicBlock *BB) const { + return DT->getNode(BB); + } + + inline bool dominates(DomTreeNode* A, DomTreeNode* B) const { + return DT->dominates(A, B); + } + + inline bool dominates(const BasicBlock* A, const BasicBlock* B) const { + return DT->dominates(A, B); + } + + inline bool properlyDominates(const DomTreeNode* A, DomTreeNode* B) const { + return DT->properlyDominates(A, B); + } + + inline bool properlyDominates(BasicBlock* A, BasicBlock* B) const { + return DT->properlyDominates(A, B); + } + + virtual void releaseMemory() { + DT->releaseMemory(); + } + + virtual void print(raw_ostream &OS, const Module*) const; +}; + +FunctionPass* createPostDomTree(); + +template <> struct GraphTraits + : public GraphTraits { + static NodeType *getEntryNode(PostDominatorTree *DT) { + return DT->getRootNode(); + } + + static nodes_iterator nodes_begin(PostDominatorTree *N) { + return df_begin(getEntryNode(N)); + } + + static nodes_iterator nodes_end(PostDominatorTree *N) { + return df_end(getEntryNode(N)); + } +}; + +/// PostDominanceFrontier Class - Concrete subclass of DominanceFrontier that is +/// used to compute the a post-dominance frontier. +/// +struct PostDominanceFrontier : public DominanceFrontierBase { + static char ID; + PostDominanceFrontier() + : DominanceFrontierBase(&ID, true) {} + + virtual bool runOnFunction(Function &) { + Frontiers.clear(); + PostDominatorTree &DT = getAnalysis(); + Roots = DT.getRoots(); + if (const DomTreeNode *Root = DT.getRootNode()) + calculate(DT, Root); + return false; + } + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + AU.addRequired(); + } + +private: + const DomSetType &calculate(const PostDominatorTree &DT, + const DomTreeNode *Node); +}; + +FunctionPass* createPostDomFrontier(); + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Analysis/ProfileInfo.h b/libclamav/c++/llvm/include/llvm/Analysis/ProfileInfo.h new file mode 100644 index 000000000..2a80f3d4c --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Analysis/ProfileInfo.h @@ -0,0 +1,136 @@ +//===- llvm/Analysis/ProfileInfo.h - Profile Info Interface -----*- 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 the generic ProfileInfo interface, which is used as the +// common interface used by all clients of profiling information, and +// implemented either by making static guestimations, or by actually reading in +// profiling information gathered by running the program. +// +// Note that to be useful, all profile-based optimizations should preserve +// ProfileInfo, which requires that they notify it when changes to the CFG are +// made. (This is not implemented yet.) +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_PROFILEINFO_H +#define LLVM_ANALYSIS_PROFILEINFO_H + +#include "llvm/BasicBlock.h" +#include +#include +#include + +namespace llvm { + class Function; + class Pass; + class raw_ostream; + + /// ProfileInfo Class - This class holds and maintains profiling + /// information for some unit of code. + class ProfileInfo { + public: + // Types for handling profiling information. + typedef std::pair Edge; + typedef std::pair EdgeWeight; + typedef std::map EdgeWeights; + typedef std::map BlockCounts; + + protected: + // EdgeInformation - Count the number of times a transition between two + // blocks is executed. As a special case, we also hold an edge from the + // null BasicBlock to the entry block to indicate how many times the + // function was entered. + std::map EdgeInformation; + + // BlockInformation - Count the number of times a block is executed. + std::map BlockInformation; + + // FunctionInformation - Count the number of times a function is executed. + std::map FunctionInformation; + public: + static char ID; // Class identification, replacement for typeinfo + virtual ~ProfileInfo(); // We want to be subclassed + + // MissingValue - The value that is returned for execution counts in case + // no value is available. + static const double MissingValue; + + // getFunction() - Returns the Function for an Edge, checking for validity. + static const Function* getFunction(Edge e) { + if (e.first) { + return e.first->getParent(); + } else if (e.second) { + return e.second->getParent(); + } + assert(0 && "Invalid ProfileInfo::Edge"); + return (const Function*)0; + } + + // getEdge() - Creates an Edge from two BasicBlocks. + static Edge getEdge(const BasicBlock *Src, const BasicBlock *Dest) { + return std::make_pair(Src, Dest); + } + + //===------------------------------------------------------------------===// + /// Profile Information Queries + /// + double getExecutionCount(const Function *F); + + double getExecutionCount(const BasicBlock *BB); + + double getEdgeWeight(Edge e) const { + std::map::const_iterator J = + EdgeInformation.find(getFunction(e)); + if (J == EdgeInformation.end()) return MissingValue; + + EdgeWeights::const_iterator I = J->second.find(e); + if (I == J->second.end()) return MissingValue; + + return I->second; + } + + EdgeWeights &getEdgeWeights (const Function *F) { + return EdgeInformation[F]; + } + + //===------------------------------------------------------------------===// + /// Analysis Update Methods + /// + void removeBlock(const BasicBlock *BB) { + std::map::iterator J = + BlockInformation.find(BB->getParent()); + if (J == BlockInformation.end()) return; + + J->second.erase(BB); + } + + void removeEdge(Edge e) { + std::map::iterator J = + EdgeInformation.find(getFunction(e)); + if (J == EdgeInformation.end()) return; + + J->second.erase(e); + } + + void splitEdge(const BasicBlock *FirstBB, const BasicBlock *SecondBB, + const BasicBlock *NewBB, bool MergeIdenticalEdges = false); + + void replaceAllUses(const BasicBlock *RmBB, const BasicBlock *DestBB); + }; + + /// createProfileLoaderPass - This function returns a Pass that loads the + /// profiling information for the module from the specified filename, making + /// it available to the optimizers. + Pass *createProfileLoaderPass(const std::string &Filename); + + raw_ostream& operator<<(raw_ostream &O, ProfileInfo::Edge E); + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Analysis/ProfileInfoLoader.h b/libclamav/c++/llvm/include/llvm/Analysis/ProfileInfoLoader.h new file mode 100644 index 000000000..9e0c393c4 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Analysis/ProfileInfoLoader.h @@ -0,0 +1,84 @@ +//===- ProfileInfoLoader.h - Load & convert profile information -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// The ProfileInfoLoader class is used to load and represent profiling +// information read in from the dump file. If conversions between formats are +// needed, it can also do this. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_PROFILEINFOLOADER_H +#define LLVM_ANALYSIS_PROFILEINFOLOADER_H + +#include +#include +#include + +namespace llvm { + +class Module; +class Function; +class BasicBlock; + +class ProfileInfoLoader { + const std::string &Filename; + Module &M; + std::vector CommandLines; + std::vector FunctionCounts; + std::vector BlockCounts; + std::vector EdgeCounts; + std::vector OptimalEdgeCounts; + std::vector BBTrace; + bool Warned; +public: + // ProfileInfoLoader ctor - Read the specified profiling data file, exiting + // the program if the file is invalid or broken. + ProfileInfoLoader(const char *ToolName, const std::string &Filename, + Module &M); + + static const unsigned Uncounted; + + unsigned getNumExecutions() const { return CommandLines.size(); } + const std::string &getExecution(unsigned i) const { return CommandLines[i]; } + + const std::string &getFileName() const { return Filename; } + + // getRawFunctionCounts - This method is used by consumers of function + // counting information. + // + const std::vector &getRawFunctionCounts() const { + return FunctionCounts; + } + + // getRawBlockCounts - This method is used by consumers of block counting + // information. + // + const std::vector &getRawBlockCounts() const { + return BlockCounts; + } + + // getEdgeCounts - This method is used by consumers of edge counting + // information. + // + const std::vector &getRawEdgeCounts() const { + return EdgeCounts; + } + + // getEdgeOptimalCounts - This method is used by consumers of optimal edge + // counting information. + // + const std::vector &getRawOptimalEdgeCounts() const { + return OptimalEdgeCounts; + } + +}; + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Analysis/ProfileInfoTypes.h b/libclamav/c++/llvm/include/llvm/Analysis/ProfileInfoTypes.h new file mode 100644 index 000000000..0d531d5c5 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Analysis/ProfileInfoTypes.h @@ -0,0 +1,29 @@ +/*===-- ProfileInfoTypes.h - Profiling info shared constants ------*- 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 constants shared by the various different profiling +|* runtime libraries and the LLVM C++ profile info loader. It must be a +|* C header because, at present, the profiling runtimes are written in C. +|* +\*===----------------------------------------------------------------------===*/ + +#ifndef LLVM_ANALYSIS_PROFILEINFOTYPES_H +#define LLVM_ANALYSIS_PROFILEINFOTYPES_H + +enum ProfilingType { + ArgumentInfo = 1, /* The command line argument block */ + FunctionInfo = 2, /* Function profiling information */ + BlockInfo = 3, /* Block profiling information */ + EdgeInfo = 4, /* Edge profiling information */ + PathInfo = 5, /* Path profiling information */ + BBTraceInfo = 6, /* Basic block trace information */ + OptEdgeInfo = 7 /* Edge profiling information, optimal version */ +}; + +#endif /* LLVM_ANALYSIS_PROFILEINFOTYPES_H */ diff --git a/libclamav/c++/llvm/include/llvm/Analysis/ScalarEvolution.h b/libclamav/c++/llvm/include/llvm/Analysis/ScalarEvolution.h new file mode 100644 index 000000000..4aa3dfa55 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Analysis/ScalarEvolution.h @@ -0,0 +1,626 @@ +//===- llvm/Analysis/ScalarEvolution.h - Scalar Evolution -------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// The ScalarEvolution class is an LLVM pass which can be used to analyze and +// catagorize scalar expressions in loops. It specializes in recognizing +// general induction variables, representing them with the abstract and opaque +// SCEV class. Given this analysis, trip counts of loops and other important +// properties can be obtained. +// +// This analysis is primarily useful for induction variable substitution and +// strength reduction. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_SCALAREVOLUTION_H +#define LLVM_ANALYSIS_SCALAREVOLUTION_H + +#include "llvm/Pass.h" +#include "llvm/Instructions.h" +#include "llvm/Function.h" +#include "llvm/System/DataTypes.h" +#include "llvm/Support/ValueHandle.h" +#include "llvm/Support/Allocator.h" +#include "llvm/Support/ConstantRange.h" +#include "llvm/ADT/FoldingSet.h" +#include "llvm/ADT/DenseMap.h" +#include + +namespace llvm { + class APInt; + class Constant; + class ConstantInt; + class DominatorTree; + class Type; + class ScalarEvolution; + class TargetData; + class LLVMContext; + class Loop; + class LoopInfo; + class Operator; + + /// SCEV - This class represents an analyzed expression in the program. These + /// are opaque objects that the client is not allowed to do much with + /// directly. + /// + class SCEV : public FastFoldingSetNode { + // The SCEV baseclass this node corresponds to + const unsigned short SCEVType; + + protected: + /// SubclassData - This field is initialized to zero and may be used in + /// subclasses to store miscelaneous information. + unsigned short SubclassData; + + private: + SCEV(const SCEV &); // DO NOT IMPLEMENT + void operator=(const SCEV &); // DO NOT IMPLEMENT + protected: + virtual ~SCEV(); + public: + explicit SCEV(const FoldingSetNodeID &ID, unsigned SCEVTy) : + FastFoldingSetNode(ID), SCEVType(SCEVTy), SubclassData(0) {} + + unsigned getSCEVType() const { return SCEVType; } + + /// isLoopInvariant - Return true if the value of this SCEV is unchanging in + /// the specified loop. + virtual bool isLoopInvariant(const Loop *L) const = 0; + + /// hasComputableLoopEvolution - Return true if this SCEV changes value in a + /// known way in the specified loop. This property being true implies that + /// the value is variant in the loop AND that we can emit an expression to + /// compute the value of the expression at any particular loop iteration. + virtual bool hasComputableLoopEvolution(const Loop *L) const = 0; + + /// getType - Return the LLVM type of this SCEV expression. + /// + virtual const Type *getType() const = 0; + + /// isZero - Return true if the expression is a constant zero. + /// + bool isZero() const; + + /// isOne - Return true if the expression is a constant one. + /// + bool isOne() const; + + /// isAllOnesValue - Return true if the expression is a constant + /// all-ones value. + /// + bool isAllOnesValue() const; + + /// hasOperand - Test whether this SCEV has Op as a direct or + /// indirect operand. + virtual bool hasOperand(const SCEV *Op) const = 0; + + /// dominates - Return true if elements that makes up this SCEV dominates + /// the specified basic block. + virtual bool dominates(BasicBlock *BB, DominatorTree *DT) const = 0; + + /// properlyDominates - Return true if elements that makes up this SCEV + /// properly dominate the specified basic block. + virtual bool properlyDominates(BasicBlock *BB, DominatorTree *DT) const = 0; + + /// print - Print out the internal representation of this scalar to the + /// specified stream. This should really only be used for debugging + /// purposes. + virtual void print(raw_ostream &OS) const = 0; + + /// dump - This method is used for debugging. + /// + void dump() const; + }; + + inline raw_ostream &operator<<(raw_ostream &OS, const SCEV &S) { + S.print(OS); + return OS; + } + + /// SCEVCouldNotCompute - An object of this class is returned by queries that + /// could not be answered. For example, if you ask for the number of + /// iterations of a linked-list traversal loop, you will get one of these. + /// None of the standard SCEV operations are valid on this class, it is just a + /// marker. + struct SCEVCouldNotCompute : public SCEV { + SCEVCouldNotCompute(); + + // None of these methods are valid for this object. + virtual bool isLoopInvariant(const Loop *L) const; + virtual const Type *getType() const; + virtual bool hasComputableLoopEvolution(const Loop *L) const; + virtual void print(raw_ostream &OS) const; + virtual bool hasOperand(const SCEV *Op) const; + + virtual bool dominates(BasicBlock *BB, DominatorTree *DT) const { + return true; + } + + virtual bool properlyDominates(BasicBlock *BB, DominatorTree *DT) const { + return true; + } + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const SCEVCouldNotCompute *S) { return true; } + static bool classof(const SCEV *S); + }; + + /// ScalarEvolution - This class is the main scalar evolution driver. Because + /// client code (intentionally) can't do much with the SCEV objects directly, + /// they must ask this class for services. + /// + class ScalarEvolution : public FunctionPass { + /// SCEVCallbackVH - A CallbackVH to arrange for ScalarEvolution to be + /// notified whenever a Value is deleted. + class SCEVCallbackVH : public CallbackVH { + ScalarEvolution *SE; + virtual void deleted(); + virtual void allUsesReplacedWith(Value *New); + public: + SCEVCallbackVH(Value *V, ScalarEvolution *SE = 0); + }; + + friend class SCEVCallbackVH; + friend struct SCEVExpander; + + /// F - The function we are analyzing. + /// + Function *F; + + /// LI - The loop information for the function we are currently analyzing. + /// + LoopInfo *LI; + + /// TD - The target data information for the target we are targetting. + /// + TargetData *TD; + + /// CouldNotCompute - This SCEV is used to represent unknown trip + /// counts and things. + SCEVCouldNotCompute CouldNotCompute; + + /// Scalars - This is a cache of the scalars we have analyzed so far. + /// + std::map Scalars; + + /// BackedgeTakenInfo - Information about the backedge-taken count + /// of a loop. This currently inclues an exact count and a maximum count. + /// + struct BackedgeTakenInfo { + /// Exact - An expression indicating the exact backedge-taken count of + /// the loop if it is known, or a SCEVCouldNotCompute otherwise. + const SCEV *Exact; + + /// Max - An expression indicating the least maximum backedge-taken + /// count of the loop that is known, or a SCEVCouldNotCompute. + const SCEV *Max; + + /*implicit*/ BackedgeTakenInfo(const SCEV *exact) : + Exact(exact), Max(exact) {} + + BackedgeTakenInfo(const SCEV *exact, const SCEV *max) : + Exact(exact), Max(max) {} + + /// hasAnyInfo - Test whether this BackedgeTakenInfo contains any + /// computed information, or whether it's all SCEVCouldNotCompute + /// values. + bool hasAnyInfo() const { + return !isa(Exact) || + !isa(Max); + } + }; + + /// BackedgeTakenCounts - Cache the backedge-taken count of the loops for + /// this function as they are computed. + std::map BackedgeTakenCounts; + + /// ConstantEvolutionLoopExitValue - This map contains entries for all of + /// the PHI instructions that we attempt to compute constant evolutions for. + /// This allows us to avoid potentially expensive recomputation of these + /// properties. An instruction maps to null if we are unable to compute its + /// exit value. + std::map ConstantEvolutionLoopExitValue; + + /// ValuesAtScopes - This map contains entries for all the expressions + /// that we attempt to compute getSCEVAtScope information for, which can + /// be expensive in extreme cases. + std::map > ValuesAtScopes; + + /// createSCEV - We know that there is no SCEV for the specified value. + /// Analyze the expression. + const SCEV *createSCEV(Value *V); + + /// createNodeForPHI - Provide the special handling we need to analyze PHI + /// SCEVs. + const SCEV *createNodeForPHI(PHINode *PN); + + /// createNodeForGEP - Provide the special handling we need to analyze GEP + /// SCEVs. + const SCEV *createNodeForGEP(Operator *GEP); + + /// computeSCEVAtScope - Implementation code for getSCEVAtScope; called + /// at most once for each SCEV+Loop pair. + /// + const SCEV *computeSCEVAtScope(const SCEV *S, const Loop *L); + + /// ForgetSymbolicValue - This looks up computed SCEV values for all + /// instructions that depend on the given instruction and removes them from + /// the Scalars map if they reference SymName. This is used during PHI + /// resolution. + void ForgetSymbolicName(Instruction *I, const SCEV *SymName); + + /// getBECount - Subtract the end and start values and divide by the step, + /// rounding up, to get the number of times the backedge is executed. Return + /// CouldNotCompute if an intermediate computation overflows. + const SCEV *getBECount(const SCEV *Start, + const SCEV *End, + const SCEV *Step, + bool NoWrap); + + /// getBackedgeTakenInfo - Return the BackedgeTakenInfo for the given + /// loop, lazily computing new values if the loop hasn't been analyzed + /// yet. + const BackedgeTakenInfo &getBackedgeTakenInfo(const Loop *L); + + /// ComputeBackedgeTakenCount - Compute the number of times the specified + /// loop will iterate. + BackedgeTakenInfo ComputeBackedgeTakenCount(const Loop *L); + + /// ComputeBackedgeTakenCountFromExit - Compute the number of times the + /// backedge of the specified loop will execute if it exits via the + /// specified block. + BackedgeTakenInfo ComputeBackedgeTakenCountFromExit(const Loop *L, + BasicBlock *ExitingBlock); + + /// ComputeBackedgeTakenCountFromExitCond - Compute the number of times the + /// backedge of the specified loop will execute if its exit condition + /// were a conditional branch of ExitCond, TBB, and FBB. + BackedgeTakenInfo + ComputeBackedgeTakenCountFromExitCond(const Loop *L, + Value *ExitCond, + BasicBlock *TBB, + BasicBlock *FBB); + + /// ComputeBackedgeTakenCountFromExitCondICmp - Compute the number of + /// times the backedge of the specified loop will execute if its exit + /// condition were a conditional branch of the ICmpInst ExitCond, TBB, + /// and FBB. + BackedgeTakenInfo + ComputeBackedgeTakenCountFromExitCondICmp(const Loop *L, + ICmpInst *ExitCond, + BasicBlock *TBB, + BasicBlock *FBB); + + /// ComputeLoadConstantCompareBackedgeTakenCount - Given an exit condition + /// of 'icmp op load X, cst', try to see if we can compute the + /// backedge-taken count. + const SCEV * + ComputeLoadConstantCompareBackedgeTakenCount(LoadInst *LI, + Constant *RHS, + const Loop *L, + ICmpInst::Predicate p); + + /// ComputeBackedgeTakenCountExhaustively - If the loop is known to execute + /// a constant number of times (the condition evolves only from constants), + /// 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 + /// evaluate the backedge-taken count of the loop, return CouldNotCompute. + const SCEV *ComputeBackedgeTakenCountExhaustively(const Loop *L, + Value *Cond, + bool ExitWhen); + + /// HowFarToZero - Return the number of times a backedge comparing the + /// specified value to zero will execute. If not computable, return + /// CouldNotCompute. + const SCEV *HowFarToZero(const SCEV *V, const Loop *L); + + /// HowFarToNonZero - Return the number of times a backedge checking the + /// specified value for nonzero will execute. If not computable, return + /// CouldNotCompute. + const SCEV *HowFarToNonZero(const SCEV *V, const Loop *L); + + /// HowManyLessThans - Return the number of times a backedge containing the + /// specified less-than comparison will execute. If not computable, return + /// CouldNotCompute. isSigned specifies whether the less-than is signed. + BackedgeTakenInfo HowManyLessThans(const SCEV *LHS, const SCEV *RHS, + const Loop *L, bool isSigned); + + /// getLoopPredecessor - If the given loop's header has exactly one unique + /// predecessor outside the loop, return it. Otherwise return null. + BasicBlock *getLoopPredecessor(const Loop *L); + + /// getPredecessorWithUniqueSuccessorForBB - Return a predecessor of BB + /// (which may not be an immediate predecessor) which has exactly one + /// successor from which BB is reachable, or null if no such block is + /// found. + BasicBlock* getPredecessorWithUniqueSuccessorForBB(BasicBlock *BB); + + /// isImpliedCond - Test whether the condition described by Pred, LHS, + /// and RHS is true whenever the given Cond value evaluates to true. + bool isImpliedCond(Value *Cond, ICmpInst::Predicate Pred, + const SCEV *LHS, const SCEV *RHS, + bool Inverse); + + /// isImpliedCondOperands - Test whether the condition described by Pred, + /// LHS, and RHS is true whenever the condition desribed by Pred, FoundLHS, + /// and FoundRHS is true. + bool isImpliedCondOperands(ICmpInst::Predicate Pred, + const SCEV *LHS, const SCEV *RHS, + const SCEV *FoundLHS, const SCEV *FoundRHS); + + /// isImpliedCondOperandsHelper - Test whether the condition described by + /// Pred, LHS, and RHS is true whenever the condition desribed by Pred, + /// FoundLHS, and FoundRHS is true. + bool isImpliedCondOperandsHelper(ICmpInst::Predicate Pred, + const SCEV *LHS, const SCEV *RHS, + const SCEV *FoundLHS, const SCEV *FoundRHS); + + /// getConstantEvolutionLoopExitValue - If we know that the specified Phi is + /// in the header of its containing loop, we know the loop executes a + /// constant number of times, and the PHI node is just a recurrence + /// involving constants, fold it. + Constant *getConstantEvolutionLoopExitValue(PHINode *PN, const APInt& BEs, + const Loop *L); + + public: + static char ID; // Pass identification, replacement for typeid + ScalarEvolution(); + + LLVMContext &getContext() const { return F->getContext(); } + + /// isSCEVable - Test if values of the given type are analyzable within + /// the SCEV framework. This primarily includes integer types, and it + /// can optionally include pointer types if the ScalarEvolution class + /// has access to target-specific information. + bool isSCEVable(const Type *Ty) const; + + /// getTypeSizeInBits - Return the size in bits of the specified type, + /// for which isSCEVable must return true. + uint64_t getTypeSizeInBits(const Type *Ty) const; + + /// getEffectiveSCEVType - Return a type with the same bitwidth as + /// the given type and which represents how SCEV will treat the given + /// type, for which isSCEVable must return true. For pointer types, + /// this is the pointer-sized integer type. + const Type *getEffectiveSCEVType(const Type *Ty) const; + + /// getSCEV - Return a SCEV expression for the full generality of the + /// specified expression. + const SCEV *getSCEV(Value *V); + + const SCEV *getConstant(ConstantInt *V); + const SCEV *getConstant(const APInt& Val); + const SCEV *getConstant(const Type *Ty, uint64_t V, bool isSigned = false); + const SCEV *getTruncateExpr(const SCEV *Op, const Type *Ty); + const SCEV *getZeroExtendExpr(const SCEV *Op, const Type *Ty); + const SCEV *getSignExtendExpr(const SCEV *Op, const Type *Ty); + const SCEV *getAnyExtendExpr(const SCEV *Op, const Type *Ty); + const SCEV *getAddExpr(SmallVectorImpl &Ops, + bool HasNUW = false, bool HasNSW = false); + const SCEV *getAddExpr(const SCEV *LHS, const SCEV *RHS, + bool HasNUW = false, bool HasNSW = false) { + SmallVector Ops; + Ops.push_back(LHS); + Ops.push_back(RHS); + return getAddExpr(Ops, HasNUW, HasNSW); + } + const SCEV *getAddExpr(const SCEV *Op0, const SCEV *Op1, + const SCEV *Op2, + bool HasNUW = false, bool HasNSW = false) { + SmallVector Ops; + Ops.push_back(Op0); + Ops.push_back(Op1); + Ops.push_back(Op2); + return getAddExpr(Ops, HasNUW, HasNSW); + } + const SCEV *getMulExpr(SmallVectorImpl &Ops, + bool HasNUW = false, bool HasNSW = false); + const SCEV *getMulExpr(const SCEV *LHS, const SCEV *RHS, + bool HasNUW = false, bool HasNSW = false) { + SmallVector Ops; + Ops.push_back(LHS); + Ops.push_back(RHS); + return getMulExpr(Ops, HasNUW, HasNSW); + } + const SCEV *getUDivExpr(const SCEV *LHS, const SCEV *RHS); + const SCEV *getAddRecExpr(const SCEV *Start, const SCEV *Step, + const Loop *L, + bool HasNUW = false, bool HasNSW = false); + const SCEV *getAddRecExpr(SmallVectorImpl &Operands, + const Loop *L, + bool HasNUW = false, bool HasNSW = false); + const SCEV *getAddRecExpr(const SmallVectorImpl &Operands, + const Loop *L, + bool HasNUW = false, bool HasNSW = false) { + SmallVector NewOp(Operands.begin(), Operands.end()); + return getAddRecExpr(NewOp, L, HasNUW, HasNSW); + } + const SCEV *getSMaxExpr(const SCEV *LHS, const SCEV *RHS); + const SCEV *getSMaxExpr(SmallVectorImpl &Operands); + const SCEV *getUMaxExpr(const SCEV *LHS, const SCEV *RHS); + const SCEV *getUMaxExpr(SmallVectorImpl &Operands); + const SCEV *getSMinExpr(const SCEV *LHS, const SCEV *RHS); + const SCEV *getUMinExpr(const SCEV *LHS, const SCEV *RHS); + const SCEV *getFieldOffsetExpr(const StructType *STy, unsigned FieldNo); + const SCEV *getAllocSizeExpr(const Type *AllocTy); + const SCEV *getUnknown(Value *V); + const SCEV *getCouldNotCompute(); + + /// getNegativeSCEV - Return the SCEV object corresponding to -V. + /// + const SCEV *getNegativeSCEV(const SCEV *V); + + /// getNotSCEV - Return the SCEV object corresponding to ~V. + /// + const SCEV *getNotSCEV(const SCEV *V); + + /// getMinusSCEV - Return LHS-RHS. + /// + const SCEV *getMinusSCEV(const SCEV *LHS, + const SCEV *RHS); + + /// getTruncateOrZeroExtend - Return a SCEV corresponding to a conversion + /// of the input value to the specified type. If the type must be + /// extended, it is zero extended. + const SCEV *getTruncateOrZeroExtend(const SCEV *V, const Type *Ty); + + /// getTruncateOrSignExtend - Return a SCEV corresponding to a conversion + /// of the input value to the specified type. If the type must be + /// extended, it is sign extended. + const SCEV *getTruncateOrSignExtend(const SCEV *V, const Type *Ty); + + /// getNoopOrZeroExtend - Return a SCEV corresponding to a conversion of + /// the input value to the specified type. If the type must be extended, + /// it is zero extended. The conversion must not be narrowing. + const SCEV *getNoopOrZeroExtend(const SCEV *V, const Type *Ty); + + /// getNoopOrSignExtend - Return a SCEV corresponding to a conversion of + /// the input value to the specified type. If the type must be extended, + /// it is sign extended. The conversion must not be narrowing. + const SCEV *getNoopOrSignExtend(const SCEV *V, const Type *Ty); + + /// getNoopOrAnyExtend - Return a SCEV corresponding to a conversion of + /// the input value to the specified type. If the type must be extended, + /// it is extended with unspecified bits. The conversion must not be + /// narrowing. + const SCEV *getNoopOrAnyExtend(const SCEV *V, const Type *Ty); + + /// getTruncateOrNoop - Return a SCEV corresponding to a conversion of the + /// input value to the specified type. The conversion must not be + /// widening. + const SCEV *getTruncateOrNoop(const SCEV *V, const Type *Ty); + + /// getIntegerSCEV - Given a SCEVable type, create a constant for the + /// specified signed integer value and return a SCEV for the constant. + const SCEV *getIntegerSCEV(int Val, const Type *Ty); + + /// getUMaxFromMismatchedTypes - Promote the operands to the wider of + /// the types using zero-extension, and then perform a umax operation + /// with them. + const SCEV *getUMaxFromMismatchedTypes(const SCEV *LHS, + const SCEV *RHS); + + /// getUMinFromMismatchedTypes - Promote the operands to the wider of + /// the types using zero-extension, and then perform a umin operation + /// with them. + const SCEV *getUMinFromMismatchedTypes(const SCEV *LHS, + const SCEV *RHS); + + /// getSCEVAtScope - Return a SCEV expression for the specified value + /// at the specified scope in the program. The L value specifies a loop + /// nest to evaluate the expression at, where null is the top-level or a + /// specified loop is immediately inside of the loop. + /// + /// This method can be used to compute the exit value for a variable defined + /// in a loop by querying what the value will hold in the parent loop. + /// + /// In the case that a relevant loop exit value cannot be computed, the + /// original value V is returned. + const SCEV *getSCEVAtScope(const SCEV *S, const Loop *L); + + /// getSCEVAtScope - This is a convenience function which does + /// getSCEVAtScope(getSCEV(V), L). + const SCEV *getSCEVAtScope(Value *V, const Loop *L); + + /// isLoopGuardedByCond - Test whether entry to the loop is protected by + /// a conditional between LHS and RHS. This is used to help avoid max + /// expressions in loop trip counts, and to eliminate casts. + bool isLoopGuardedByCond(const Loop *L, ICmpInst::Predicate Pred, + const SCEV *LHS, const SCEV *RHS); + + /// isLoopBackedgeGuardedByCond - Test whether the backedge of the loop is + /// protected by a conditional between LHS and RHS. This is used to + /// to eliminate casts. + bool isLoopBackedgeGuardedByCond(const Loop *L, ICmpInst::Predicate Pred, + const SCEV *LHS, const SCEV *RHS); + + /// getBackedgeTakenCount - If the specified loop has a predictable + /// backedge-taken count, return it, otherwise return a SCEVCouldNotCompute + /// object. The backedge-taken count is the number of times the loop header + /// will be branched to from within the loop. This is one less than the + /// trip count of the loop, since it doesn't count the first iteration, + /// when the header is branched to from outside the loop. + /// + /// Note that it is not valid to call this method on a loop without a + /// loop-invariant backedge-taken count (see + /// hasLoopInvariantBackedgeTakenCount). + /// + const SCEV *getBackedgeTakenCount(const Loop *L); + + /// getMaxBackedgeTakenCount - Similar to getBackedgeTakenCount, except + /// return the least SCEV value that is known never to be less than the + /// actual backedge taken count. + const SCEV *getMaxBackedgeTakenCount(const Loop *L); + + /// hasLoopInvariantBackedgeTakenCount - Return true if the specified loop + /// has an analyzable loop-invariant backedge-taken count. + bool hasLoopInvariantBackedgeTakenCount(const Loop *L); + + /// forgetLoop - This method should be called by the client when it has + /// changed a loop in a way that may effect ScalarEvolution's ability to + /// compute a trip count, or if the loop is deleted. + void forgetLoop(const Loop *L); + + /// GetMinTrailingZeros - Determine the minimum number of zero bits that S + /// is guaranteed to end in (at every loop iteration). It is, at the same + /// time, the minimum number of times S is divisible by 2. For example, + /// given {4,+,8} it returns 2. If S is guaranteed to be 0, it returns the + /// bitwidth of S. + uint32_t GetMinTrailingZeros(const SCEV *S); + + /// getUnsignedRange - Determine the unsigned range for a particular SCEV. + /// + ConstantRange getUnsignedRange(const SCEV *S); + + /// getSignedRange - Determine the signed range for a particular SCEV. + /// + ConstantRange getSignedRange(const SCEV *S); + + /// isKnownNegative - Test if the given expression is known to be negative. + /// + bool isKnownNegative(const SCEV *S); + + /// isKnownPositive - Test if the given expression is known to be positive. + /// + bool isKnownPositive(const SCEV *S); + + /// isKnownNonNegative - Test if the given expression is known to be + /// non-negative. + /// + bool isKnownNonNegative(const SCEV *S); + + /// isKnownNonPositive - Test if the given expression is known to be + /// non-positive. + /// + bool isKnownNonPositive(const SCEV *S); + + /// isKnownNonZero - Test if the given expression is known to be + /// non-zero. + /// + bool isKnownNonZero(const SCEV *S); + + /// isKnownNonZero - Test if the given expression is known to satisfy + /// the condition described by Pred, LHS, and RHS. + /// + bool isKnownPredicate(ICmpInst::Predicate Pred, + const SCEV *LHS, const SCEV *RHS); + + virtual bool runOnFunction(Function &F); + virtual void releaseMemory(); + virtual void getAnalysisUsage(AnalysisUsage &AU) const; + virtual void print(raw_ostream &OS, const Module* = 0) const; + + private: + FoldingSet UniqueSCEVs; + BumpPtrAllocator SCEVAllocator; + }; +} + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Analysis/ScalarEvolutionExpander.h b/libclamav/c++/llvm/include/llvm/Analysis/ScalarEvolutionExpander.h new file mode 100644 index 000000000..bbdd0437a --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Analysis/ScalarEvolutionExpander.h @@ -0,0 +1,127 @@ +//===---- llvm/Analysis/ScalarEvolutionExpander.h - SCEV Exprs --*- 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 the classes used to generate code from scalar expressions. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_SCALAREVOLUTION_EXPANDER_H +#define LLVM_ANALYSIS_SCALAREVOLUTION_EXPANDER_H + +#include "llvm/Analysis/ScalarEvolutionExpressions.h" +#include "llvm/Support/IRBuilder.h" +#include "llvm/Support/TargetFolder.h" +#include + +namespace llvm { + /// SCEVExpander - This class uses information about analyze scalars to + /// rewrite expressions in canonical form. + /// + /// Clients should create an instance of this class when rewriting is needed, + /// and destroy it when finished to allow the release of the associated + /// memory. + struct SCEVExpander : public SCEVVisitor { + ScalarEvolution &SE; + std::map, AssertingVH > + InsertedExpressions; + std::set InsertedValues; + + typedef IRBuilder BuilderType; + BuilderType Builder; + + friend struct SCEVVisitor; + public: + explicit SCEVExpander(ScalarEvolution &se) + : SE(se), Builder(se.getContext(), TargetFolder(se.TD)) {} + + /// clear - Erase the contents of the InsertedExpressions map so that users + /// trying to expand the same expression into multiple BasicBlocks or + /// different places within the same BasicBlock can do so. + void clear() { InsertedExpressions.clear(); } + + /// getOrInsertCanonicalInductionVariable - This method returns the + /// canonical induction variable of the specified type for the specified + /// loop (inserting one if there is none). A canonical induction variable + /// starts at zero and steps by one on each iteration. + Value *getOrInsertCanonicalInductionVariable(const Loop *L, const Type *Ty); + + /// expandCodeFor - Insert code to directly compute the specified SCEV + /// expression into the program. The inserted code is inserted into the + /// specified block. + Value *expandCodeFor(const SCEV *SH, const Type *Ty, Instruction *IP) { + Builder.SetInsertPoint(IP->getParent(), IP); + return expandCodeFor(SH, Ty); + } + + private: + LLVMContext &getContext() const { return SE.getContext(); } + + /// InsertBinop - Insert the specified binary operator, doing a small amount + /// of work to avoid inserting an obviously redundant operation. + Value *InsertBinop(Instruction::BinaryOps Opcode, Value *LHS, Value *RHS); + + /// InsertNoopCastOfTo - Insert a cast of V to the specified type, + /// which must be possible with a noop cast, doing what we can to + /// share the casts. + Value *InsertNoopCastOfTo(Value *V, const Type *Ty); + + /// expandAddToGEP - Expand a SCEVAddExpr with a pointer type into a GEP + /// instead of using ptrtoint+arithmetic+inttoptr. + Value *expandAddToGEP(const SCEV *const *op_begin, + const SCEV *const *op_end, + const PointerType *PTy, const Type *Ty, Value *V); + + Value *expand(const SCEV *S); + + /// expandCodeFor - Insert code to directly compute the specified SCEV + /// expression into the program. The inserted code is inserted into 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. + Value *expandCodeFor(const SCEV *SH, const Type *Ty = 0); + + /// isInsertedInstruction - Return true if the specified instruction was + /// inserted by the code rewriter. If so, the client should not modify the + /// instruction. + bool isInsertedInstruction(Instruction *I) const { + return InsertedValues.count(I); + } + + Value *visitConstant(const SCEVConstant *S) { + return S->getValue(); + } + + Value *visitTruncateExpr(const SCEVTruncateExpr *S); + + Value *visitZeroExtendExpr(const SCEVZeroExtendExpr *S); + + Value *visitSignExtendExpr(const SCEVSignExtendExpr *S); + + Value *visitAddExpr(const SCEVAddExpr *S); + + Value *visitMulExpr(const SCEVMulExpr *S); + + Value *visitUDivExpr(const SCEVUDivExpr *S); + + Value *visitAddRecExpr(const SCEVAddRecExpr *S); + + Value *visitSMaxExpr(const SCEVSMaxExpr *S); + + Value *visitUMaxExpr(const SCEVUMaxExpr *S); + + Value *visitFieldOffsetExpr(const SCEVFieldOffsetExpr *S); + + Value *visitAllocSizeExpr(const SCEVAllocSizeExpr *S); + + Value *visitUnknown(const SCEVUnknown *S) { + return S->getValue(); + } + }; +} + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Analysis/ScalarEvolutionExpressions.h b/libclamav/c++/llvm/include/llvm/Analysis/ScalarEvolutionExpressions.h new file mode 100644 index 000000000..2c5035060 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Analysis/ScalarEvolutionExpressions.h @@ -0,0 +1,681 @@ +//===- llvm/Analysis/ScalarEvolutionExpressions.h - SCEV Exprs --*- 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 the classes used to represent and build scalar expressions. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_SCALAREVOLUTION_EXPRESSIONS_H +#define LLVM_ANALYSIS_SCALAREVOLUTION_EXPRESSIONS_H + +#include "llvm/Analysis/ScalarEvolution.h" +#include "llvm/Support/ErrorHandling.h" + +namespace llvm { + class ConstantInt; + class ConstantRange; + class DominatorTree; + + enum SCEVTypes { + // These should be ordered in terms of increasing complexity to make the + // folders simpler. + scConstant, scTruncate, scZeroExtend, scSignExtend, scAddExpr, scMulExpr, + scUDivExpr, scAddRecExpr, scUMaxExpr, scSMaxExpr, + scFieldOffset, scAllocSize, scUnknown, scCouldNotCompute + }; + + //===--------------------------------------------------------------------===// + /// SCEVConstant - This class represents a constant integer value. + /// + class SCEVConstant : public SCEV { + friend class ScalarEvolution; + + ConstantInt *V; + SCEVConstant(const FoldingSetNodeID &ID, ConstantInt *v) : + SCEV(ID, scConstant), V(v) {} + public: + ConstantInt *getValue() const { return V; } + + virtual bool isLoopInvariant(const Loop *L) const { + return true; + } + + virtual bool hasComputableLoopEvolution(const Loop *L) const { + return false; // Not loop variant + } + + virtual const Type *getType() const; + + virtual bool hasOperand(const SCEV *) const { + return false; + } + + bool dominates(BasicBlock *BB, DominatorTree *DT) const { + return true; + } + + bool properlyDominates(BasicBlock *BB, DominatorTree *DT) const { + return true; + } + + virtual void print(raw_ostream &OS) const; + + /// 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 SCEV *S) { + return S->getSCEVType() == scConstant; + } + }; + + //===--------------------------------------------------------------------===// + /// SCEVCastExpr - This is the base class for unary cast operator classes. + /// + class SCEVCastExpr : public SCEV { + protected: + const SCEV *Op; + const Type *Ty; + + SCEVCastExpr(const FoldingSetNodeID &ID, + unsigned SCEVTy, const SCEV *op, const Type *ty); + + public: + const SCEV *getOperand() const { return Op; } + virtual const Type *getType() const { return Ty; } + + virtual bool isLoopInvariant(const Loop *L) const { + return Op->isLoopInvariant(L); + } + + virtual bool hasComputableLoopEvolution(const Loop *L) const { + return Op->hasComputableLoopEvolution(L); + } + + virtual bool hasOperand(const SCEV *O) const { + return Op == O || Op->hasOperand(O); + } + + virtual bool dominates(BasicBlock *BB, DominatorTree *DT) const; + + virtual bool properlyDominates(BasicBlock *BB, DominatorTree *DT) const; + + /// 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 SCEV *S) { + return S->getSCEVType() == scTruncate || + S->getSCEVType() == scZeroExtend || + S->getSCEVType() == scSignExtend; + } + }; + + //===--------------------------------------------------------------------===// + /// SCEVTruncateExpr - This class represents a truncation of an integer value + /// to a smaller integer value. + /// + class SCEVTruncateExpr : public SCEVCastExpr { + friend class ScalarEvolution; + + SCEVTruncateExpr(const FoldingSetNodeID &ID, + const SCEV *op, const Type *ty); + + public: + virtual void print(raw_ostream &OS) const; + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const SCEVTruncateExpr *S) { return true; } + static inline bool classof(const SCEV *S) { + return S->getSCEVType() == scTruncate; + } + }; + + //===--------------------------------------------------------------------===// + /// SCEVZeroExtendExpr - This class represents a zero extension of a small + /// integer value to a larger integer value. + /// + class SCEVZeroExtendExpr : public SCEVCastExpr { + friend class ScalarEvolution; + + SCEVZeroExtendExpr(const FoldingSetNodeID &ID, + const SCEV *op, const Type *ty); + + public: + virtual void print(raw_ostream &OS) const; + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const SCEVZeroExtendExpr *S) { return true; } + static inline bool classof(const SCEV *S) { + return S->getSCEVType() == scZeroExtend; + } + }; + + //===--------------------------------------------------------------------===// + /// SCEVSignExtendExpr - This class represents a sign extension of a small + /// integer value to a larger integer value. + /// + class SCEVSignExtendExpr : public SCEVCastExpr { + friend class ScalarEvolution; + + SCEVSignExtendExpr(const FoldingSetNodeID &ID, + const SCEV *op, const Type *ty); + + public: + virtual void print(raw_ostream &OS) const; + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const SCEVSignExtendExpr *S) { return true; } + static inline bool classof(const SCEV *S) { + return S->getSCEVType() == scSignExtend; + } + }; + + + //===--------------------------------------------------------------------===// + /// SCEVNAryExpr - This node is a base class providing common + /// functionality for n'ary operators. + /// + class SCEVNAryExpr : public SCEV { + protected: + SmallVector Operands; + + SCEVNAryExpr(const FoldingSetNodeID &ID, + enum SCEVTypes T, const SmallVectorImpl &ops) + : SCEV(ID, T), Operands(ops.begin(), ops.end()) {} + + public: + unsigned getNumOperands() const { return (unsigned)Operands.size(); } + const SCEV *getOperand(unsigned i) const { + assert(i < Operands.size() && "Operand index out of range!"); + return Operands[i]; + } + + const SmallVectorImpl &getOperands() const { + return Operands; + } + typedef SmallVectorImpl::const_iterator op_iterator; + op_iterator op_begin() const { return Operands.begin(); } + op_iterator op_end() const { return Operands.end(); } + + virtual bool isLoopInvariant(const Loop *L) const { + for (unsigned i = 0, e = getNumOperands(); i != e; ++i) + if (!getOperand(i)->isLoopInvariant(L)) return false; + return true; + } + + // hasComputableLoopEvolution - N-ary expressions have computable loop + // evolutions iff they have at least one operand that varies with the loop, + // but that all varying operands are computable. + virtual bool hasComputableLoopEvolution(const Loop *L) const { + bool HasVarying = false; + for (unsigned i = 0, e = getNumOperands(); i != e; ++i) + if (!getOperand(i)->isLoopInvariant(L)) { + if (getOperand(i)->hasComputableLoopEvolution(L)) + HasVarying = true; + else + return false; + } + return HasVarying; + } + + virtual bool hasOperand(const SCEV *O) const { + for (unsigned i = 0, e = getNumOperands(); i != e; ++i) + if (O == getOperand(i) || getOperand(i)->hasOperand(O)) + return true; + return false; + } + + bool dominates(BasicBlock *BB, DominatorTree *DT) const; + + bool properlyDominates(BasicBlock *BB, DominatorTree *DT) const; + + virtual const Type *getType() const { return getOperand(0)->getType(); } + + bool hasNoUnsignedWrap() const { return SubclassData & (1 << 0); } + void setHasNoUnsignedWrap(bool B) { + SubclassData = (SubclassData & ~(1 << 0)) | (B << 0); + } + bool hasNoSignedWrap() const { return SubclassData & (1 << 1); } + void setHasNoSignedWrap(bool B) { + SubclassData = (SubclassData & ~(1 << 1)) | (B << 1); + } + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const SCEVNAryExpr *S) { return true; } + static inline bool classof(const SCEV *S) { + return S->getSCEVType() == scAddExpr || + S->getSCEVType() == scMulExpr || + S->getSCEVType() == scSMaxExpr || + S->getSCEVType() == scUMaxExpr || + S->getSCEVType() == scAddRecExpr; + } + }; + + //===--------------------------------------------------------------------===// + /// SCEVCommutativeExpr - This node is the base class for n'ary commutative + /// operators. + /// + class SCEVCommutativeExpr : public SCEVNAryExpr { + protected: + SCEVCommutativeExpr(const FoldingSetNodeID &ID, + enum SCEVTypes T, + const SmallVectorImpl &ops) + : SCEVNAryExpr(ID, T, ops) {} + + public: + virtual const char *getOperationStr() const = 0; + + virtual void print(raw_ostream &OS) const; + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const SCEVCommutativeExpr *S) { return true; } + static inline bool classof(const SCEV *S) { + return S->getSCEVType() == scAddExpr || + S->getSCEVType() == scMulExpr || + S->getSCEVType() == scSMaxExpr || + S->getSCEVType() == scUMaxExpr; + } + }; + + + //===--------------------------------------------------------------------===// + /// SCEVAddExpr - This node represents an addition of some number of SCEVs. + /// + class SCEVAddExpr : public SCEVCommutativeExpr { + friend class ScalarEvolution; + + SCEVAddExpr(const FoldingSetNodeID &ID, + const SmallVectorImpl &ops) + : SCEVCommutativeExpr(ID, scAddExpr, ops) { + } + + public: + virtual const char *getOperationStr() const { return " + "; } + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const SCEVAddExpr *S) { return true; } + static inline bool classof(const SCEV *S) { + return S->getSCEVType() == scAddExpr; + } + }; + + //===--------------------------------------------------------------------===// + /// SCEVMulExpr - This node represents multiplication of some number of SCEVs. + /// + class SCEVMulExpr : public SCEVCommutativeExpr { + friend class ScalarEvolution; + + SCEVMulExpr(const FoldingSetNodeID &ID, + const SmallVectorImpl &ops) + : SCEVCommutativeExpr(ID, scMulExpr, ops) { + } + + public: + virtual const char *getOperationStr() const { return " * "; } + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const SCEVMulExpr *S) { return true; } + static inline bool classof(const SCEV *S) { + return S->getSCEVType() == scMulExpr; + } + }; + + + //===--------------------------------------------------------------------===// + /// SCEVUDivExpr - This class represents a binary unsigned division operation. + /// + class SCEVUDivExpr : public SCEV { + friend class ScalarEvolution; + + const SCEV *LHS; + const SCEV *RHS; + SCEVUDivExpr(const FoldingSetNodeID &ID, const SCEV *lhs, const SCEV *rhs) + : SCEV(ID, scUDivExpr), LHS(lhs), RHS(rhs) {} + + public: + const SCEV *getLHS() const { return LHS; } + const SCEV *getRHS() const { return RHS; } + + virtual bool isLoopInvariant(const Loop *L) const { + return LHS->isLoopInvariant(L) && RHS->isLoopInvariant(L); + } + + virtual bool hasComputableLoopEvolution(const Loop *L) const { + return LHS->hasComputableLoopEvolution(L) && + RHS->hasComputableLoopEvolution(L); + } + + virtual bool hasOperand(const SCEV *O) const { + return O == LHS || O == RHS || LHS->hasOperand(O) || RHS->hasOperand(O); + } + + bool dominates(BasicBlock *BB, DominatorTree *DT) const; + + bool properlyDominates(BasicBlock *BB, DominatorTree *DT) const; + + virtual const Type *getType() const; + + void print(raw_ostream &OS) const; + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const SCEVUDivExpr *S) { return true; } + static inline bool classof(const SCEV *S) { + return S->getSCEVType() == scUDivExpr; + } + }; + + + //===--------------------------------------------------------------------===// + /// SCEVAddRecExpr - This node represents a polynomial recurrence on the trip + /// count of the specified loop. This is the primary focus of the + /// ScalarEvolution framework; all the other SCEV subclasses are mostly just + /// supporting infrastructure to allow SCEVAddRecExpr expressions to be + /// created and analyzed. + /// + /// All operands of an AddRec are required to be loop invariant. + /// + class SCEVAddRecExpr : public SCEVNAryExpr { + friend class ScalarEvolution; + + const Loop *L; + + SCEVAddRecExpr(const FoldingSetNodeID &ID, + const SmallVectorImpl &ops, const Loop *l) + : SCEVNAryExpr(ID, scAddRecExpr, ops), L(l) { + for (size_t i = 0, e = Operands.size(); i != e; ++i) + assert(Operands[i]->isLoopInvariant(l) && + "Operands of AddRec must be loop-invariant!"); + } + + public: + const SCEV *getStart() const { return Operands[0]; } + const Loop *getLoop() const { return L; } + + /// getStepRecurrence - This method constructs and returns the recurrence + /// indicating how much this expression steps by. If this is a polynomial + /// of degree N, it returns a chrec of degree N-1. + const SCEV *getStepRecurrence(ScalarEvolution &SE) const { + if (isAffine()) return getOperand(1); + return SE.getAddRecExpr(SmallVector(op_begin()+1, + op_end()), + getLoop()); + } + + virtual bool hasComputableLoopEvolution(const Loop *QL) const { + if (L == QL) return true; + return false; + } + + virtual bool isLoopInvariant(const Loop *QueryLoop) const; + + /// isAffine - Return true if this is an affine AddRec (i.e., it represents + /// an expressions A+B*x where A and B are loop invariant values. + bool isAffine() const { + // We know that the start value is invariant. This expression is thus + // affine iff the step is also invariant. + return getNumOperands() == 2; + } + + /// isQuadratic - Return true if this is an quadratic AddRec (i.e., it + /// represents an expressions A+B*x+C*x^2 where A, B and C are loop + /// invariant values. This corresponds to an addrec of the form {L,+,M,+,N} + bool isQuadratic() const { + return getNumOperands() == 3; + } + + /// evaluateAtIteration - Return the value of this chain of recurrences at + /// the specified iteration number. + const SCEV *evaluateAtIteration(const SCEV *It, ScalarEvolution &SE) const; + + /// getNumIterationsInRange - Return the number of iterations of this loop + /// that produce values in the specified constant range. Another way of + /// looking at this is that it returns the first iteration number where the + /// value is not in the condition, thus computing the exit count. If the + /// iteration count can't be computed, an instance of SCEVCouldNotCompute is + /// returned. + const SCEV *getNumIterationsInRange(ConstantRange Range, + ScalarEvolution &SE) const; + + /// getPostIncExpr - Return an expression representing the value of + /// this expression one iteration of the loop ahead. + const SCEVAddRecExpr *getPostIncExpr(ScalarEvolution &SE) const { + return cast(SE.getAddExpr(this, getStepRecurrence(SE))); + } + + virtual void print(raw_ostream &OS) const; + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const SCEVAddRecExpr *S) { return true; } + static inline bool classof(const SCEV *S) { + return S->getSCEVType() == scAddRecExpr; + } + }; + + + //===--------------------------------------------------------------------===// + /// SCEVSMaxExpr - This class represents a signed maximum selection. + /// + class SCEVSMaxExpr : public SCEVCommutativeExpr { + friend class ScalarEvolution; + + SCEVSMaxExpr(const FoldingSetNodeID &ID, + const SmallVectorImpl &ops) + : SCEVCommutativeExpr(ID, scSMaxExpr, ops) { + // Max never overflows. + setHasNoUnsignedWrap(true); + setHasNoSignedWrap(true); + } + + public: + virtual const char *getOperationStr() const { return " smax "; } + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const SCEVSMaxExpr *S) { return true; } + static inline bool classof(const SCEV *S) { + return S->getSCEVType() == scSMaxExpr; + } + }; + + + //===--------------------------------------------------------------------===// + /// SCEVUMaxExpr - This class represents an unsigned maximum selection. + /// + class SCEVUMaxExpr : public SCEVCommutativeExpr { + friend class ScalarEvolution; + + SCEVUMaxExpr(const FoldingSetNodeID &ID, + const SmallVectorImpl &ops) + : SCEVCommutativeExpr(ID, scUMaxExpr, ops) { + // Max never overflows. + setHasNoUnsignedWrap(true); + setHasNoSignedWrap(true); + } + + public: + virtual const char *getOperationStr() const { return " umax "; } + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const SCEVUMaxExpr *S) { return true; } + static inline bool classof(const SCEV *S) { + return S->getSCEVType() == scUMaxExpr; + } + }; + + //===--------------------------------------------------------------------===// + /// SCEVTargetDataConstant - This node is the base class for representing + /// target-dependent values in a target-independent way. + /// + class SCEVTargetDataConstant : public SCEV { + protected: + const Type *Ty; + SCEVTargetDataConstant(const FoldingSetNodeID &ID, enum SCEVTypes T, + const Type *ty) : + SCEV(ID, T), Ty(ty) {} + + public: + virtual bool isLoopInvariant(const Loop *) const { return true; } + virtual bool hasComputableLoopEvolution(const Loop *) const { + return false; // not computable + } + + virtual bool hasOperand(const SCEV *) const { + return false; + } + + bool dominates(BasicBlock *, DominatorTree *) const { + return true; + } + + bool properlyDominates(BasicBlock *, DominatorTree *) const { + return true; + } + + virtual const Type *getType() const { return Ty; } + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const SCEVTargetDataConstant *S) { return true; } + static inline bool classof(const SCEV *S) { + return S->getSCEVType() == scFieldOffset || + S->getSCEVType() == scAllocSize; + } + }; + + //===--------------------------------------------------------------------===// + /// SCEVFieldOffsetExpr - This node represents an offsetof expression. + /// + class SCEVFieldOffsetExpr : public SCEVTargetDataConstant { + friend class ScalarEvolution; + + const StructType *STy; + unsigned FieldNo; + SCEVFieldOffsetExpr(const FoldingSetNodeID &ID, const Type *ty, + const StructType *sty, unsigned fieldno) : + SCEVTargetDataConstant(ID, scFieldOffset, ty), + STy(sty), FieldNo(fieldno) {} + + public: + const StructType *getStructType() const { return STy; } + unsigned getFieldNo() const { return FieldNo; } + + virtual void print(raw_ostream &OS) const; + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const SCEVFieldOffsetExpr *S) { return true; } + static inline bool classof(const SCEV *S) { + return S->getSCEVType() == scFieldOffset; + } + }; + + //===--------------------------------------------------------------------===// + /// SCEVAllocSize - This node represents a sizeof expression. + /// + class SCEVAllocSizeExpr : public SCEVTargetDataConstant { + friend class ScalarEvolution; + + const Type *AllocTy; + SCEVAllocSizeExpr(const FoldingSetNodeID &ID, + const Type *ty, const Type *allocty) : + SCEVTargetDataConstant(ID, scAllocSize, ty), + AllocTy(allocty) {} + + public: + const Type *getAllocType() const { return AllocTy; } + + virtual void print(raw_ostream &OS) const; + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const SCEVAllocSizeExpr *S) { return true; } + static inline bool classof(const SCEV *S) { + return S->getSCEVType() == scAllocSize; + } + }; + + //===--------------------------------------------------------------------===// + /// SCEVUnknown - This means that we are dealing with an entirely unknown SCEV + /// value, and only represent it as its LLVM Value. This is the "bottom" + /// value for the analysis. + /// + class SCEVUnknown : public SCEV { + friend class ScalarEvolution; + + Value *V; + SCEVUnknown(const FoldingSetNodeID &ID, Value *v) : + SCEV(ID, scUnknown), V(v) {} + + public: + Value *getValue() const { return V; } + + virtual bool isLoopInvariant(const Loop *L) const; + virtual bool hasComputableLoopEvolution(const Loop *QL) const { + return false; // not computable + } + + virtual bool hasOperand(const SCEV *) const { + return false; + } + + bool dominates(BasicBlock *BB, DominatorTree *DT) const; + + bool properlyDominates(BasicBlock *BB, DominatorTree *DT) const; + + virtual const Type *getType() const; + + virtual void print(raw_ostream &OS) const; + + /// 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 SCEV *S) { + return S->getSCEVType() == scUnknown; + } + }; + + /// SCEVVisitor - This class defines a simple visitor class that may be used + /// for various SCEV analysis purposes. + template + struct SCEVVisitor { + RetVal visit(const SCEV *S) { + switch (S->getSCEVType()) { + case scConstant: + return ((SC*)this)->visitConstant((const SCEVConstant*)S); + case scTruncate: + return ((SC*)this)->visitTruncateExpr((const SCEVTruncateExpr*)S); + case scZeroExtend: + return ((SC*)this)->visitZeroExtendExpr((const SCEVZeroExtendExpr*)S); + case scSignExtend: + return ((SC*)this)->visitSignExtendExpr((const SCEVSignExtendExpr*)S); + case scAddExpr: + return ((SC*)this)->visitAddExpr((const SCEVAddExpr*)S); + case scMulExpr: + return ((SC*)this)->visitMulExpr((const SCEVMulExpr*)S); + case scUDivExpr: + return ((SC*)this)->visitUDivExpr((const SCEVUDivExpr*)S); + case scAddRecExpr: + return ((SC*)this)->visitAddRecExpr((const SCEVAddRecExpr*)S); + case scSMaxExpr: + return ((SC*)this)->visitSMaxExpr((const SCEVSMaxExpr*)S); + case scUMaxExpr: + return ((SC*)this)->visitUMaxExpr((const SCEVUMaxExpr*)S); + case scFieldOffset: + return ((SC*)this)->visitFieldOffsetExpr((const SCEVFieldOffsetExpr*)S); + case scAllocSize: + return ((SC*)this)->visitAllocSizeExpr((const SCEVAllocSizeExpr*)S); + case scUnknown: + return ((SC*)this)->visitUnknown((const SCEVUnknown*)S); + case scCouldNotCompute: + return ((SC*)this)->visitCouldNotCompute((const SCEVCouldNotCompute*)S); + default: + llvm_unreachable("Unknown SCEV type!"); + } + } + + RetVal visitCouldNotCompute(const SCEVCouldNotCompute *S) { + llvm_unreachable("Invalid use of SCEVCouldNotCompute!"); + return RetVal(); + } + }; +} + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Analysis/SparsePropagation.h b/libclamav/c++/llvm/include/llvm/Analysis/SparsePropagation.h new file mode 100644 index 000000000..677d41d80 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Analysis/SparsePropagation.h @@ -0,0 +1,209 @@ +//===- SparsePropagation.h - Sparse Conditional Property Propagation ------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements an abstract sparse conditional propagation algorithm, +// modeled after SCCP, but with a customizable lattice function. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_SPARSE_PROPAGATION_H +#define LLVM_ANALYSIS_SPARSE_PROPAGATION_H + +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallPtrSet.h" +#include +#include + +namespace llvm { + class Value; + class Constant; + class Argument; + class Instruction; + class PHINode; + class TerminatorInst; + class BasicBlock; + class Function; + class SparseSolver; + class LLVMContext; + class raw_ostream; + + template class SmallVectorImpl; + +/// AbstractLatticeFunction - This class is implemented by the dataflow instance +/// to specify what the lattice values are and how they handle merges etc. +/// This gives the client the power to compute lattice values from instructions, +/// constants, etc. The requirement is that lattice values must all fit into +/// a void*. If a void* is not sufficient, the implementation should use this +/// pointer to be a pointer into a uniquing set or something. +/// +class AbstractLatticeFunction { +public: + typedef void *LatticeVal; +private: + LatticeVal UndefVal, OverdefinedVal, UntrackedVal; +public: + AbstractLatticeFunction(LatticeVal undefVal, LatticeVal overdefinedVal, + LatticeVal untrackedVal) { + UndefVal = undefVal; + OverdefinedVal = overdefinedVal; + UntrackedVal = untrackedVal; + } + virtual ~AbstractLatticeFunction(); + + LatticeVal getUndefVal() const { return UndefVal; } + LatticeVal getOverdefinedVal() const { return OverdefinedVal; } + LatticeVal getUntrackedVal() const { return UntrackedVal; } + + /// IsUntrackedValue - If the specified Value is something that is obviously + /// uninteresting to the analysis (and would always return UntrackedVal), + /// this function can return true to avoid pointless work. + virtual bool IsUntrackedValue(Value *V) { + return false; + } + + /// ComputeConstant - Given a constant value, compute and return a lattice + /// value corresponding to the specified constant. + virtual LatticeVal ComputeConstant(Constant *C) { + return getOverdefinedVal(); // always safe + } + + /// IsSpecialCasedPHI - Given a PHI node, determine whether this PHI node is + /// one that the we want to handle through ComputeInstructionState. + virtual bool IsSpecialCasedPHI(PHINode *PN) { + return false; + } + + /// GetConstant - If the specified lattice value is representable as an LLVM + /// constant value, return it. Otherwise return null. The returned value + /// must be in the same LLVM type as Val. + virtual Constant *GetConstant(LatticeVal LV, Value *Val, SparseSolver &SS) { + return 0; + } + + /// ComputeArgument - Given a formal argument value, compute and return a + /// lattice value corresponding to the specified argument. + virtual LatticeVal ComputeArgument(Argument *I) { + return getOverdefinedVal(); // always safe + } + + /// MergeValues - Compute and return the merge of the two specified lattice + /// values. Merging should only move one direction down the lattice to + /// guarantee convergence (toward overdefined). + virtual LatticeVal MergeValues(LatticeVal X, LatticeVal Y) { + return getOverdefinedVal(); // always safe, never useful. + } + + /// ComputeInstructionState - Given an instruction and a vector of its operand + /// values, compute the result value of the instruction. + virtual LatticeVal ComputeInstructionState(Instruction &I, SparseSolver &SS) { + return getOverdefinedVal(); // always safe, never useful. + } + + /// PrintValue - Render the specified lattice value to the specified stream. + virtual void PrintValue(LatticeVal V, raw_ostream &OS); +}; + + +/// SparseSolver - This class is a general purpose solver for Sparse Conditional +/// Propagation with a programmable lattice function. +/// +class SparseSolver { + typedef AbstractLatticeFunction::LatticeVal LatticeVal; + + /// LatticeFunc - This is the object that knows the lattice and how to do + /// compute transfer functions. + AbstractLatticeFunction *LatticeFunc; + + LLVMContext *Context; + + DenseMap ValueState; // The state each value is in. + SmallPtrSet BBExecutable; // The bbs that are executable. + + std::vector InstWorkList; // Worklist of insts to process. + + std::vector BBWorkList; // The BasicBlock work list + + /// KnownFeasibleEdges - Entries in this set are edges which have already had + /// PHI nodes retriggered. + typedef std::pair Edge; + std::set KnownFeasibleEdges; + + SparseSolver(const SparseSolver&); // DO NOT IMPLEMENT + void operator=(const SparseSolver&); // DO NOT IMPLEMENT +public: + explicit SparseSolver(AbstractLatticeFunction *Lattice, LLVMContext *C) + : LatticeFunc(Lattice), Context(C) {} + ~SparseSolver() { + delete LatticeFunc; + } + + /// Solve - Solve for constants and executable blocks. + /// + void Solve(Function &F); + + void Print(Function &F, raw_ostream &OS) const; + + /// getLatticeState - Return the LatticeVal object that corresponds to the + /// value. If an value is not in the map, it is returned as untracked, + /// unlike the getOrInitValueState method. + LatticeVal getLatticeState(Value *V) const { + DenseMap::const_iterator I = ValueState.find(V); + return I != ValueState.end() ? I->second : LatticeFunc->getUntrackedVal(); + } + + /// getOrInitValueState - Return the LatticeVal object that corresponds to the + /// value, initializing the value's state if it hasn't been entered into the + /// map yet. This function is necessary because not all values should start + /// out in the underdefined state... Arguments should be overdefined, and + /// constants should be marked as constants. + /// + LatticeVal getOrInitValueState(Value *V); + + /// isEdgeFeasible - Return true if the control flow edge from the 'From' + /// basic block to the 'To' basic block is currently feasible. If + /// AggressiveUndef is true, then this treats values with unknown lattice + /// values as undefined. This is generally only useful when solving the + /// lattice, not when querying it. + bool isEdgeFeasible(BasicBlock *From, BasicBlock *To, + bool AggressiveUndef = false); + + /// isBlockExecutable - Return true if there are any known feasible + /// edges into the basic block. This is generally only useful when + /// querying the lattice. + bool isBlockExecutable(BasicBlock *BB) const { + return BBExecutable.count(BB); + } + +private: + /// UpdateState - When the state for some instruction is potentially updated, + /// this function notices and adds I to the worklist if needed. + void UpdateState(Instruction &Inst, LatticeVal V); + + /// MarkBlockExecutable - This method can be used by clients to mark all of + /// the blocks that are known to be intrinsically live in the processed unit. + void MarkBlockExecutable(BasicBlock *BB); + + /// markEdgeExecutable - Mark a basic block as executable, adding it to the BB + /// work list if it is not already executable. + void markEdgeExecutable(BasicBlock *Source, BasicBlock *Dest); + + /// getFeasibleSuccessors - Return a vector of booleans to indicate which + /// successors are reachable from a given terminator instruction. + void getFeasibleSuccessors(TerminatorInst &TI, SmallVectorImpl &Succs, + bool AggressiveUndef); + + void visitInst(Instruction &I); + void visitPHINode(PHINode &I); + void visitTerminatorInst(TerminatorInst &TI); + +}; + +} // end namespace llvm + +#endif // LLVM_ANALYSIS_SPARSE_PROPAGATION_H diff --git a/libclamav/c++/llvm/include/llvm/Analysis/Trace.h b/libclamav/c++/llvm/include/llvm/Analysis/Trace.h new file mode 100644 index 000000000..99651e192 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Analysis/Trace.h @@ -0,0 +1,119 @@ +//===- llvm/Analysis/Trace.h - Represent one trace of LLVM code -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This class represents a single trace of LLVM basic blocks. A trace is a +// single entry, multiple exit, region of code that is often hot. Trace-based +// optimizations treat traces almost like they are a large, strange, basic +// block: because the trace path is assumed to be hot, optimizations for the +// fall-through path are made at the expense of the non-fall-through paths. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_TRACE_H +#define LLVM_ANALYSIS_TRACE_H + +#include +#include + +namespace llvm { + class BasicBlock; + class Function; + class Module; + class raw_ostream; + +class Trace { + typedef std::vector BasicBlockListType; + BasicBlockListType BasicBlocks; + +public: + /// Trace ctor - Make a new trace from a vector of basic blocks, + /// residing in the function which is the parent of the first + /// basic block in the vector. + /// + Trace(const std::vector &vBB) : BasicBlocks (vBB) {} + + /// getEntryBasicBlock - Return the entry basic block (first block) + /// of the trace. + /// + BasicBlock *getEntryBasicBlock () const { return BasicBlocks[0]; } + + /// operator[]/getBlock - Return basic block N in the trace. + /// + BasicBlock *operator[](unsigned i) const { return BasicBlocks[i]; } + BasicBlock *getBlock(unsigned i) const { return BasicBlocks[i]; } + + /// getFunction - Return this trace's parent function. + /// + Function *getFunction () const; + + /// getModule - Return this Module that contains this trace's parent + /// function. + /// + Module *getModule () const; + + /// getBlockIndex - Return the index of the specified basic block in the + /// trace, or -1 if it is not in the trace. + int getBlockIndex(const BasicBlock *X) const { + for (unsigned i = 0, e = BasicBlocks.size(); i != e; ++i) + if (BasicBlocks[i] == X) + return i; + return -1; + } + + /// contains - Returns true if this trace contains the given basic + /// block. + /// + bool contains(const BasicBlock *X) const { + return getBlockIndex(X) != -1; + } + + /// Returns true if B1 occurs before B2 in the trace, or if it is the same + /// block as B2.. Both blocks must be in the trace. + /// + bool dominates(const BasicBlock *B1, const BasicBlock *B2) const { + int B1Idx = getBlockIndex(B1), B2Idx = getBlockIndex(B2); + assert(B1Idx != -1 && B2Idx != -1 && "Block is not in the trace!"); + return B1Idx <= B2Idx; + } + + // BasicBlock iterators... + typedef BasicBlockListType::iterator iterator; + typedef BasicBlockListType::const_iterator const_iterator; + typedef std::reverse_iterator const_reverse_iterator; + typedef std::reverse_iterator reverse_iterator; + + iterator begin() { return BasicBlocks.begin(); } + const_iterator begin() const { return BasicBlocks.begin(); } + iterator end () { return BasicBlocks.end(); } + const_iterator end () const { return BasicBlocks.end(); } + + reverse_iterator rbegin() { return BasicBlocks.rbegin(); } + const_reverse_iterator rbegin() const { return BasicBlocks.rbegin(); } + reverse_iterator rend () { return BasicBlocks.rend(); } + const_reverse_iterator rend () const { return BasicBlocks.rend(); } + + unsigned size() const { return BasicBlocks.size(); } + bool empty() const { return BasicBlocks.empty(); } + + iterator erase(iterator q) { return BasicBlocks.erase (q); } + iterator erase(iterator q1, iterator q2) { return BasicBlocks.erase (q1, q2); } + + /// print - Write trace to output stream. + /// + void print(raw_ostream &O) const; + + /// dump - Debugger convenience method; writes trace to standard error + /// output stream. + /// + void dump() const; +}; + +} // end namespace llvm + +#endif // TRACE_H diff --git a/libclamav/c++/llvm/include/llvm/Analysis/ValueTracking.h b/libclamav/c++/llvm/include/llvm/Analysis/ValueTracking.h new file mode 100644 index 000000000..5f3c671d0 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Analysis/ValueTracking.h @@ -0,0 +1,130 @@ +//===- llvm/Analysis/ValueTracking.h - Walk computations --------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains routines that help analyze properties that chains of +// computations have. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_VALUETRACKING_H +#define LLVM_ANALYSIS_VALUETRACKING_H + +#include "llvm/System/DataTypes.h" +#include + +namespace llvm { + template class SmallVectorImpl; + class Value; + class Instruction; + class APInt; + class TargetData; + class LLVMContext; + + /// ComputeMaskedBits - Determine which of the bits specified in Mask are + /// known to be either zero or one and return them in the KnownZero/KnownOne + /// bit sets. This code only analyzes bits in Mask, in order to short-circuit + /// processing. + /// + /// This function is defined on values with integer type, values with pointer + /// type (but only if TD is non-null), and vectors of integers. In the case + /// where V is a vector, the mask, known zero, and known one values are the + /// same width as the vector element, and the bit is set only if it is true + /// for all of the elements in the vector. + void ComputeMaskedBits(Value *V, const APInt &Mask, APInt &KnownZero, + APInt &KnownOne, const TargetData *TD = 0, + unsigned Depth = 0); + + /// MaskedValueIsZero - Return true if 'V & Mask' is known to be zero. We use + /// this predicate to simplify operations downstream. Mask is known to be + /// zero for bits that V cannot have. + /// + /// This function is defined on values with integer type, values with pointer + /// type (but only if TD is non-null), and vectors of integers. In the case + /// where V is a vector, the mask, known zero, and known one values are the + /// same width as the vector element, and the bit is set only if it is true + /// for all of the elements in the vector. + bool MaskedValueIsZero(Value *V, const APInt &Mask, + const TargetData *TD = 0, unsigned Depth = 0); + + + /// ComputeNumSignBits - Return the number of times the sign bit of the + /// register is replicated into the other bits. We know that at least 1 bit + /// is always equal to the sign bit (itself), but other cases can give us + /// information. For example, immediately after an "ashr X, 2", we know that + /// the top 3 bits are all equal to each other, so we return 3. + /// + /// 'Op' must have a scalar integer type. + /// + unsigned ComputeNumSignBits(Value *Op, const TargetData *TD = 0, + unsigned Depth = 0); + + /// ComputeMultiple - This function computes the integer multiple of Base that + /// equals V. If successful, it returns true and returns the multiple in + /// Multiple. If unsuccessful, it returns false. Also, if V can be + /// simplified to an integer, then the simplified V is returned in Val. Look + /// through sext only if LookThroughSExt=true. + bool ComputeMultiple(Value *V, unsigned Base, Value *&Multiple, + bool LookThroughSExt = false, + unsigned Depth = 0); + + /// CannotBeNegativeZero - Return true if we can prove that the specified FP + /// value is never equal to -0.0. + /// + bool CannotBeNegativeZero(const Value *V, unsigned Depth = 0); + + /// DecomposeGEPExpression - If V is a symbolic pointer expression, decompose + /// it into a base pointer with a constant offset and a number of scaled + /// symbolic offsets. + /// + /// The scaled symbolic offsets (represented by pairs of a Value* and a scale + /// in the VarIndices vector) are Value*'s that are known to be scaled by the + /// specified amount, but which may have other unrepresented high bits. As + /// such, the gep cannot necessarily be reconstructed from its decomposed + /// form. + /// + /// When TargetData is around, this function is capable of analyzing + /// everything that Value::getUnderlyingObject() can look through. When not, + /// it just looks through pointer casts. + /// + const Value *DecomposeGEPExpression(const Value *V, int64_t &BaseOffs, + SmallVectorImpl > &VarIndices, + const TargetData *TD); + + + + /// FindScalarValue - Given an aggregrate and an sequence of indices, see if + /// the scalar value indexed is already around as a register, for example if + /// it were inserted directly into the aggregrate. + /// + /// If InsertBefore is not null, this function will duplicate (modified) + /// insertvalues when a part of a nested struct is extracted. + Value *FindInsertedValue(Value *V, + const unsigned *idx_begin, + const unsigned *idx_end, + Instruction *InsertBefore = 0); + + /// This is a convenience wrapper for finding values indexed by a single index + /// only. + inline Value *FindInsertedValue(Value *V, const unsigned Idx, + Instruction *InsertBefore = 0) { + const unsigned Idxs[1] = { Idx }; + return FindInsertedValue(V, &Idxs[0], &Idxs[1], InsertBefore); + } + + /// GetConstantStringInfo - This function computes the length of a + /// null-terminated C string pointed to by V. If successful, it returns true + /// and returns the string in Str. If unsuccessful, it returns false. If + /// StopAtNul is set to true (the default), the returned string is truncated + /// by a nul character in the global. If StopAtNul is false, the nul + /// character is included in the result string. + bool GetConstantStringInfo(Value *V, std::string &Str, uint64_t Offset = 0, + bool StopAtNul = true); +} // end namespace llvm + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Analysis/Verifier.h b/libclamav/c++/llvm/include/llvm/Analysis/Verifier.h new file mode 100644 index 000000000..a6b2a6df2 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Analysis/Verifier.h @@ -0,0 +1,75 @@ +//===-- llvm/Analysis/Verifier.h - Module Verifier --------------*- 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 the function verifier interface, that can be used for some +// sanity checking of input to the system, and for checking that transformations +// haven't done something bad. +// +// Note that this does not provide full 'java style' security and verifications, +// instead it just tries to ensure that code is well formed. +// +// To see what specifically is checked, look at the top of Verifier.cpp +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_VERIFIER_H +#define LLVM_ANALYSIS_VERIFIER_H + +#include + +namespace llvm { + +class FunctionPass; +class Module; +class Function; + +/// @brief An enumeration to specify the action to be taken if errors found. +/// +/// This enumeration is used in the functions below to indicate what should +/// happen if the verifier finds errors. Each of the functions that uses +/// this enumeration as an argument provides a default value for it. The +/// actions are listed below. +enum VerifierFailureAction { + AbortProcessAction, ///< verifyModule will print to stderr and abort() + PrintMessageAction, ///< verifyModule will print to stderr and return true + ReturnStatusAction ///< verifyModule will just return true +}; + +/// @brief Create a verifier pass. +/// +/// Check a module or function for validity. When the pass is used, the +/// action indicated by the \p action argument will be used if errors are +/// found. +FunctionPass *createVerifierPass( + VerifierFailureAction action = AbortProcessAction ///< Action to take +); + +/// @brief Check a module for errors. +/// +/// If there are no errors, the function returns false. If an error is found, +/// the action taken depends on the \p action parameter. +/// This should only be used for debugging, because it plays games with +/// PassManagers and stuff. + +bool verifyModule( + const Module &M, ///< The module to be verified + VerifierFailureAction action = AbortProcessAction, ///< Action to take + std::string *ErrorInfo = 0 ///< Information about failures. +); + +// verifyFunction - Check a function for errors, useful for use when debugging a +// pass. +bool verifyFunction( + const Function &F, ///< The function to be verified + VerifierFailureAction action = AbortProcessAction ///< Action to take +); + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Argument.h b/libclamav/c++/llvm/include/llvm/Argument.h new file mode 100644 index 000000000..3a846c289 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Argument.h @@ -0,0 +1,83 @@ +//===-- llvm/Argument.h - Definition of the Argument class ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the Argument class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ARGUMENT_H +#define LLVM_ARGUMENT_H + +#include "llvm/Value.h" +#include "llvm/Attributes.h" +#include "llvm/ADT/ilist_node.h" + +namespace llvm { + +template + class SymbolTableListTraits; + +/// A class to represent an incoming formal argument to a Function. An argument +/// is a very simple Value. It is essentially a named (optional) type. When used +/// in the body of a function, it represents the value of the actual argument +/// the function was called with. +/// @brief LLVM Argument representation +class Argument : public Value, public ilist_node { + Function *Parent; + + friend class SymbolTableListTraits; + void setParent(Function *parent); + +public: + /// Argument ctor - If Function argument is specified, this argument is + /// inserted at the end of the argument list for the function. + /// + explicit Argument(const Type *Ty, const Twine &Name = "", Function *F = 0); + + inline const Function *getParent() const { return Parent; } + inline Function *getParent() { return Parent; } + + /// getArgNo - Return the index of this formal argument in its containing + /// function. For example in "void foo(int a, float b)" a is 0 and b is 1. + unsigned getArgNo() const; + + /// hasByValAttr - Return true if this argument has the byval attribute on it + /// in its containing function. + bool hasByValAttr() const; + + /// hasNoAliasAttr - Return true if this argument has the noalias attribute on + /// it in its containing function. + bool hasNoAliasAttr() const; + + /// hasNoCaptureAttr - Return true if this argument has the nocapture + /// attribute on it in its containing function. + bool hasNoCaptureAttr() const; + + /// hasSRetAttr - Return true if this argument has the sret attribute on it in + /// its containing function. + bool hasStructRetAttr() const; + + /// addAttr - Add a Attribute to an argument + void addAttr(Attributes); + + /// removeAttr - Remove a Attribute from an argument + void removeAttr(Attributes); + + /// classof - Methods for support type inquiry through isa, cast, and + /// dyn_cast: + /// + static inline bool classof(const Argument *) { return true; } + static inline bool classof(const Value *V) { + return V->getValueID() == ArgumentVal; + } +}; + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Assembly/AsmAnnotationWriter.h b/libclamav/c++/llvm/include/llvm/Assembly/AsmAnnotationWriter.h new file mode 100644 index 000000000..6c3ddaf7d --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Assembly/AsmAnnotationWriter.h @@ -0,0 +1,53 @@ +//===-- AsmAnnotationWriter.h - Itf for annotation .ll files - --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Clients of the assembly writer can use this interface to add their own +// special-purpose annotations to LLVM assembly language printouts. Note that +// the assembly parser won't be able to parse these, in general, so +// implementations are advised to print stuff as LLVM comments. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ASSEMBLY_ASMANNOTATIONWRITER_H +#define LLVM_ASSEMBLY_ASMANNOTATIONWRITER_H + +namespace llvm { + +class Function; +class BasicBlock; +class Instruction; +class raw_ostream; + +class AssemblyAnnotationWriter { +public: + + virtual ~AssemblyAnnotationWriter(); + + // emitFunctionAnnot - This may be implemented to emit a string right before + // the start of a function. + virtual void emitFunctionAnnot(const Function *F, raw_ostream &OS) {} + + // emitBasicBlockStartAnnot - This may be implemented to emit a string right + // after the basic block label, but before the first instruction in the block. + virtual void emitBasicBlockStartAnnot(const BasicBlock *BB, raw_ostream &OS){ + } + + // emitBasicBlockEndAnnot - This may be implemented to emit a string right + // after the basic block. + virtual void emitBasicBlockEndAnnot(const BasicBlock *BB, raw_ostream &OS){ + } + + // emitInstructionAnnot - This may be implemented to emit a string right + // before an instruction is emitted. + virtual void emitInstructionAnnot(const Instruction *I, raw_ostream &OS) {} +}; + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Assembly/Parser.h b/libclamav/c++/llvm/include/llvm/Assembly/Parser.h new file mode 100644 index 000000000..82ec6d813 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Assembly/Parser.h @@ -0,0 +1,65 @@ +//===-- llvm/Assembly/Parser.h - Parser for VM assembly files ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// These classes are implemented by the lib/AsmParser library. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ASSEMBLY_PARSER_H +#define LLVM_ASSEMBLY_PARSER_H + +#include + +namespace llvm { + +class Module; +class MemoryBuffer; +class SMDiagnostic; +class raw_ostream; +class LLVMContext; + +/// This function is the main interface to the LLVM Assembly Parser. It parses +/// an ASCII file that (presumably) contains LLVM Assembly code. It returns a +/// Module (intermediate representation) with the corresponding features. Note +/// that this does not verify that the generated Module is valid, so you should +/// run the verifier after parsing the file to check that it is okay. +/// @brief Parse LLVM Assembly from a file +Module *ParseAssemblyFile( + const std::string &Filename, ///< The name of the file to parse + SMDiagnostic &Error, ///< Error result info. + LLVMContext &Context ///< Context in which to allocate globals info. +); + +/// The function is a secondary interface to the LLVM Assembly Parser. It parses +/// an ASCII string that (presumably) contains LLVM Assembly code. It returns a +/// Module (intermediate representation) with the corresponding features. Note +/// that this does not verify that the generated Module is valid, so you should +/// run the verifier after parsing the file to check that it is okay. +/// @brief Parse LLVM Assembly from a string +Module *ParseAssemblyString( + const char *AsmString, ///< The string containing assembly + Module *M, ///< A module to add the assembly too. + SMDiagnostic &Error, ///< Error result info. + LLVMContext &Context +); + +/// This function is the low-level interface to the LLVM Assembly Parser. +/// ParseAssemblyFile and ParseAssemblyString are wrappers around this function. +/// @brief Parse LLVM Assembly from a MemoryBuffer. This function *always* +/// takes ownership of the MemoryBuffer. +Module *ParseAssembly( + MemoryBuffer *F, ///< The MemoryBuffer containing assembly + Module *M, ///< A module to add the assembly too. + SMDiagnostic &Err, ///< Error result info. + LLVMContext &Context +); + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Assembly/PrintModulePass.h b/libclamav/c++/llvm/include/llvm/Assembly/PrintModulePass.h new file mode 100644 index 000000000..fb4f6a7e1 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Assembly/PrintModulePass.h @@ -0,0 +1,40 @@ +//===- llvm/Assembly/PrintModulePass.h - Printing Pass ----------*- 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 two passes to print out a module. The PrintModulePass pass +// simply prints out the entire module when it is executed. The +// PrintFunctionPass class is designed to be pipelined with other +// FunctionPass's, and prints out the functions of the module as they are +// processed. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ASSEMBLY_PRINTMODULEPASS_H +#define LLVM_ASSEMBLY_PRINTMODULEPASS_H + +#include + +namespace llvm { + class FunctionPass; + class ModulePass; + class raw_ostream; + + /// createPrintModulePass - Create and return a pass that writes the + /// module to the specified raw_ostream. + ModulePass *createPrintModulePass(raw_ostream *OS, bool DeleteStream=false); + + /// createPrintFunctionPass - Create and return a pass that prints + /// functions to the specified raw_ostream as they are processed. + FunctionPass *createPrintFunctionPass(const std::string &Banner, + raw_ostream *OS, + bool DeleteStream=false); + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Assembly/Writer.h b/libclamav/c++/llvm/include/llvm/Assembly/Writer.h new file mode 100644 index 000000000..c5b239079 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Assembly/Writer.h @@ -0,0 +1,78 @@ +//===-- llvm/Assembly/Writer.h - Printer for LLVM assembly files --*- C++ -*-=// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This functionality is implemented by lib/VMCore/AsmWriter.cpp. +// This library is used to print LLVM assembly language files to an iostream. It +// can print LLVM code at a variety of granularities, including Modules, +// BasicBlocks, and Instructions. This makes it useful for debugging. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ASSEMBLY_WRITER_H +#define LLVM_ASSEMBLY_WRITER_H + +#include + +namespace llvm { + +class Type; +class Module; +class Value; +class raw_ostream; +template class SmallVectorImpl; + +/// TypePrinting - Type printing machinery. +class TypePrinting { + void *TypeNames; // A map to remember type names. + TypePrinting(const TypePrinting &); // DO NOT IMPLEMENT + void operator=(const TypePrinting&); // DO NOT IMPLEMENT +public: + TypePrinting(); + ~TypePrinting(); + + void clear(); + + void print(const Type *Ty, raw_ostream &OS, bool IgnoreTopLevelName = false); + + void printAtLeastOneLevel(const Type *Ty, raw_ostream &OS) { + print(Ty, OS, true); + } + + /// hasTypeName - Return true if the type has a name in TypeNames, false + /// otherwise. + bool hasTypeName(const Type *Ty) const; + + /// addTypeName - Add a name for the specified type if it doesn't already have + /// one. This name will be printed instead of the structural version of the + /// type in order to make the output more concise. + void addTypeName(const Type *Ty, const std::string &N); + +private: + void CalcTypeName(const Type *Ty, SmallVectorImpl &TypeStack, + raw_ostream &OS, bool IgnoreTopLevelName = false); +}; + +// WriteTypeSymbolic - This attempts to write the specified type as a symbolic +// type, if there is an entry in the Module's symbol table for the specified +// type or one of its component types. +// +void WriteTypeSymbolic(raw_ostream &, const Type *, const Module *M); + +// WriteAsOperand - Write the name of the specified value out to the specified +// ostream. This can be useful when you just want to print int %reg126, not the +// whole instruction that generated it. If you specify a Module for context, +// then even constants get pretty-printed; for example, the type of a null +// pointer is printed symbolically. +// +void WriteAsOperand(raw_ostream &, const Value *, bool PrintTy = true, + const Module *Context = 0); + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Attributes.h b/libclamav/c++/llvm/include/llvm/Attributes.h new file mode 100644 index 000000000..0bbdc349b --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Attributes.h @@ -0,0 +1,257 @@ +//===-- llvm/Attributes.h - Container for Attributes ---*---------- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the simple types necessary to represent the +// attributes associated with functions and their calls. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ATTRIBUTES_H +#define LLVM_ATTRIBUTES_H + +#include "llvm/Support/MathExtras.h" +#include +#include + +namespace llvm { +class Type; + +/// Attributes - A bitset of attributes. +typedef unsigned Attributes; + +namespace Attribute { + +/// Function parameters and results can have attributes to indicate how they +/// should be treated by optimizations and code generation. This enumeration +/// lists the attributes that can be associated with parameters, function +/// results or the function itself. +/// @brief Function attributes. + +const Attributes None = 0; ///< No attributes have been set +const Attributes ZExt = 1<<0; ///< Zero extended before/after call +const Attributes SExt = 1<<1; ///< Sign extended before/after call +const Attributes NoReturn = 1<<2; ///< Mark the function as not returning +const Attributes InReg = 1<<3; ///< Force argument to be passed in register +const Attributes StructRet = 1<<4; ///< Hidden pointer to structure to return +const Attributes NoUnwind = 1<<5; ///< Function doesn't unwind stack +const Attributes NoAlias = 1<<6; ///< Considered to not alias after call +const Attributes ByVal = 1<<7; ///< Pass structure by value +const Attributes Nest = 1<<8; ///< Nested function static chain +const Attributes ReadNone = 1<<9; ///< Function does not access memory +const Attributes ReadOnly = 1<<10; ///< Function only reads from memory +const Attributes NoInline = 1<<11; ///< inline=never +const Attributes AlwaysInline = 1<<12; ///< inline=always +const Attributes OptimizeForSize = 1<<13; ///< opt_size +const Attributes StackProtect = 1<<14; ///< Stack protection. +const Attributes StackProtectReq = 1<<15; ///< Stack protection required. +const Attributes Alignment = 31<<16; ///< Alignment of parameter (5 bits) + // stored as log2 of alignment with +1 bias + // 0 means unaligned different from align 1 +const Attributes NoCapture = 1<<21; ///< Function creates no aliases of pointer +const Attributes NoRedZone = 1<<22; /// disable redzone +const Attributes NoImplicitFloat = 1<<23; /// disable implicit floating point + /// instructions. +const Attributes Naked = 1<<24; ///< Naked function +const Attributes InlineHint = 1<<25; ///< source said inlining was desirable + +/// @brief Attributes that only apply to function parameters. +const Attributes ParameterOnly = ByVal | Nest | StructRet | NoCapture; + +/// @brief Attributes that may be applied to the function itself. These cannot +/// be used on return values or function parameters. +const Attributes FunctionOnly = NoReturn | NoUnwind | ReadNone | ReadOnly | + NoInline | AlwaysInline | OptimizeForSize | StackProtect | StackProtectReq | + NoRedZone | NoImplicitFloat | Naked | InlineHint; + +/// @brief Parameter attributes that do not apply to vararg call arguments. +const Attributes VarArgsIncompatible = StructRet; + +/// @brief Attributes that are mutually incompatible. +const Attributes MutuallyIncompatible[4] = { + ByVal | InReg | Nest | StructRet, + ZExt | SExt, + ReadNone | ReadOnly, + NoInline | AlwaysInline +}; + +/// @brief Which attributes cannot be applied to a type. +Attributes typeIncompatible(const Type *Ty); + +/// This turns an int alignment (a power of 2, normally) into the +/// form used internally in Attributes. +inline Attributes constructAlignmentFromInt(unsigned i) { + // Default alignment, allow the target to define how to align it. + if (i == 0) + return 0; + + assert(isPowerOf2_32(i) && "Alignment must be a power of two."); + assert(i <= 0x40000000 && "Alignment too large."); + return (Log2_32(i)+1) << 16; +} + +/// This returns the alignment field of an attribute as a byte alignment value. +inline unsigned getAlignmentFromAttrs(Attributes A) { + Attributes Align = A & Attribute::Alignment; + if (Align == 0) + return 0; + + return 1U << ((Align >> 16) - 1); +} + + +/// The set of Attributes set in Attributes is converted to a +/// string of equivalent mnemonics. This is, presumably, for writing out +/// the mnemonics for the assembly writer. +/// @brief Convert attribute bits to text +std::string getAsString(Attributes Attrs); +} // end namespace Attribute + +/// This is just a pair of values to associate a set of attributes +/// with an index. +struct AttributeWithIndex { + Attributes Attrs; ///< The attributes that are set, or'd together. + unsigned Index; ///< Index of the parameter for which the attributes apply. + ///< Index 0 is used for return value attributes. + ///< Index ~0U is used for function attributes. + + static AttributeWithIndex get(unsigned Idx, Attributes Attrs) { + AttributeWithIndex P; + P.Index = Idx; + P.Attrs = Attrs; + return P; + } +}; + +//===----------------------------------------------------------------------===// +// AttrListPtr Smart Pointer +//===----------------------------------------------------------------------===// + +class AttributeListImpl; + +/// AttrListPtr - This class manages the ref count for the opaque +/// AttributeListImpl object and provides accessors for it. +class AttrListPtr { + /// AttrList - The attributes that we are managing. This can be null + /// to represent the empty attributes list. + AttributeListImpl *AttrList; +public: + AttrListPtr() : AttrList(0) {} + AttrListPtr(const AttrListPtr &P); + const AttrListPtr &operator=(const AttrListPtr &RHS); + ~AttrListPtr(); + + //===--------------------------------------------------------------------===// + // Attribute List Construction and Mutation + //===--------------------------------------------------------------------===// + + /// get - Return a Attributes list with the specified parameter in it. + static AttrListPtr get(const AttributeWithIndex *Attr, unsigned NumAttrs); + + /// get - Return a Attribute list with the parameters specified by the + /// consecutive random access iterator range. + template + static AttrListPtr get(const Iter &I, const Iter &E) { + if (I == E) return AttrListPtr(); // Empty list. + return get(&*I, static_cast(E-I)); + } + + /// addAttr - Add the specified attribute at the specified index to this + /// attribute list. Since attribute lists are immutable, this + /// returns the new list. + AttrListPtr addAttr(unsigned Idx, Attributes Attrs) const; + + /// removeAttr - Remove the specified attribute at the specified index from + /// this attribute list. Since attribute lists are immutable, this + /// returns the new list. + AttrListPtr removeAttr(unsigned Idx, Attributes Attrs) const; + + //===--------------------------------------------------------------------===// + // Attribute List Accessors + //===--------------------------------------------------------------------===// + /// getParamAttributes - The attributes for the specified index are + /// returned. + Attributes getParamAttributes(unsigned Idx) const { + assert (Idx && Idx != ~0U && "Invalid parameter index!"); + return getAttributes(Idx); + } + + /// getRetAttributes - The attributes for the ret value are + /// returned. + Attributes getRetAttributes() const { + return getAttributes(0); + } + + /// getFnAttributes - The function attributes are returned. + Attributes getFnAttributes() const { + return getAttributes(~0U); + } + + /// paramHasAttr - Return true if the specified parameter index has the + /// specified attribute set. + bool paramHasAttr(unsigned Idx, Attributes Attr) const { + return getAttributes(Idx) & Attr; + } + + /// getParamAlignment - Return the alignment for the specified function + /// parameter. + unsigned getParamAlignment(unsigned Idx) const { + return Attribute::getAlignmentFromAttrs(getAttributes(Idx)); + } + + /// hasAttrSomewhere - Return true if the specified attribute is set for at + /// least one parameter or for the return value. + bool hasAttrSomewhere(Attributes Attr) const; + + /// operator==/!= - Provide equality predicates. + bool operator==(const AttrListPtr &RHS) const { return AttrList == RHS.AttrList; } + bool operator!=(const AttrListPtr &RHS) const { return AttrList != RHS.AttrList; } + + void dump() const; + + //===--------------------------------------------------------------------===// + // Attribute List Introspection + //===--------------------------------------------------------------------===// + + /// getRawPointer - Return a raw pointer that uniquely identifies this + /// attribute list. + void *getRawPointer() const { + return AttrList; + } + + // Attributes are stored as a dense set of slots, where there is one + // slot for each argument that has an attribute. This allows walking over the + // dense set instead of walking the sparse list of attributes. + + /// isEmpty - Return true if there are no attributes. + /// + bool isEmpty() const { + return AttrList == 0; + } + + /// getNumSlots - Return the number of slots used in this attribute list. + /// This is the number of arguments that have an attribute set on them + /// (including the function itself). + unsigned getNumSlots() const; + + /// getSlot - Return the AttributeWithIndex at the specified slot. This + /// holds a index number plus a set of attributes. + const AttributeWithIndex &getSlot(unsigned Slot) const; + +private: + explicit AttrListPtr(AttributeListImpl *L); + + /// getAttributes - The attributes for the specified index are + /// returned. Attributes for the result are denoted with Idx = 0. + Attributes getAttributes(unsigned Idx) const; + +}; + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/AutoUpgrade.h b/libclamav/c++/llvm/include/llvm/AutoUpgrade.h new file mode 100644 index 000000000..0a81c8079 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/AutoUpgrade.h @@ -0,0 +1,43 @@ +//===-- llvm/AutoUpgrade.h - AutoUpgrade Helpers ----------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// These functions are implemented by lib/VMCore/AutoUpgrade.cpp. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_AUTOUPGRADE_H +#define LLVM_AUTOUPGRADE_H + +namespace llvm { + class Module; + class Function; + class CallInst; + + /// This is a more granular function that simply checks an intrinsic function + /// for upgrading, and returns true if it requires upgrading. It may return + /// null in NewFn if the all calls to the original intrinsic function + /// should be transformed to non-function-call instructions. + bool UpgradeIntrinsicFunction(Function *F, Function *&NewFn); + + /// This is the complement to the above, replacing a specific call to an + /// intrinsic function with a call to the specified new function. + void UpgradeIntrinsicCall(CallInst *CI, Function *NewFn); + + /// This is an auto-upgrade hook for any old intrinsic function syntaxes + /// which need to have both the function updated as well as all calls updated + /// to the new function. This should only be run in a post-processing fashion + /// so that it can update all calls to the old function. + void UpgradeCallsToIntrinsic(Function* F); + + /// This function checks debug info intrinsics. If an intrinsic is invalid + /// then this function simply removes the intrinsic. + void CheckDebugInfoIntrinsics(Module *M); +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/BasicBlock.h b/libclamav/c++/llvm/include/llvm/BasicBlock.h new file mode 100644 index 000000000..80d870272 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/BasicBlock.h @@ -0,0 +1,256 @@ +//===-- llvm/BasicBlock.h - Represent a basic block in the VM ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the declaration of the BasicBlock class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_BASICBLOCK_H +#define LLVM_BASICBLOCK_H + +#include "llvm/Instruction.h" +#include "llvm/SymbolTableListTraits.h" +#include "llvm/ADT/ilist.h" +#include "llvm/System/DataTypes.h" + +namespace llvm { + +class TerminatorInst; +class LLVMContext; +class BlockAddress; + +template<> struct ilist_traits + : public SymbolTableListTraits { + // createSentinel is used to get hold of a node that marks the end of + // the list... + // The sentinel is relative to this instance, so we use a non-static + // method. + Instruction *createSentinel() const { + // since i(p)lists always publicly derive from the corresponding + // traits, placing a data member in this class will augment i(p)list. + // But since the NodeTy is expected to publicly derive from + // ilist_node, there is a legal viable downcast from it + // to NodeTy. We use this trick to superpose i(p)list with a "ghostly" + // NodeTy, which becomes the sentinel. Dereferencing the sentinel is + // forbidden (save the ilist_node) so no one will ever notice + // the superposition. + return static_cast(&Sentinel); + } + static void destroySentinel(Instruction*) {} + + Instruction *provideInitialHead() const { return createSentinel(); } + Instruction *ensureHead(Instruction*) const { return createSentinel(); } + static void noteHead(Instruction*, Instruction*) {} +private: + mutable ilist_half_node Sentinel; +}; + +/// This represents a single basic block in LLVM. A basic block is simply a +/// container of instructions that execute sequentially. Basic blocks are Values +/// because they are referenced by instructions such as branches and switch +/// tables. The type of a BasicBlock is "Type::LabelTy" because the basic block +/// represents a label to which a branch can jump. +/// +/// A well formed basic block is formed of a list of non-terminating +/// instructions followed by a single TerminatorInst instruction. +/// TerminatorInst's may not occur in the middle of basic blocks, and must +/// terminate the blocks. The BasicBlock class allows malformed basic blocks to +/// occur because it may be useful in the intermediate stage of constructing or +/// modifying a program. However, the verifier will ensure that basic blocks +/// are "well formed". +/// @brief LLVM Basic Block Representation +class BasicBlock : public Value, // Basic blocks are data objects also + public ilist_node { + friend class BlockAddress; +public: + typedef iplist InstListType; +private: + InstListType InstList; + Function *Parent; + + void setParent(Function *parent); + friend class SymbolTableListTraits; + + BasicBlock(const BasicBlock &); // Do not implement + void operator=(const BasicBlock &); // Do not implement + + /// BasicBlock ctor - If the function parameter is specified, the basic block + /// is automatically inserted at either the end of the function (if + /// InsertBefore is null), or before the specified basic block. + /// + explicit BasicBlock(LLVMContext &C, const Twine &Name = "", + Function *Parent = 0, BasicBlock *InsertBefore = 0); +public: + /// getContext - Get the context in which this basic block lives. + LLVMContext &getContext() const; + + /// Instruction iterators... + typedef InstListType::iterator iterator; + typedef InstListType::const_iterator const_iterator; + + /// Create - Creates a new BasicBlock. If the Parent parameter is specified, + /// the basic block is automatically inserted at either the end of the + /// function (if InsertBefore is 0), or before the specified basic block. + static BasicBlock *Create(LLVMContext &Context, const Twine &Name = "", + Function *Parent = 0,BasicBlock *InsertBefore = 0) { + return new BasicBlock(Context, Name, Parent, InsertBefore); + } + ~BasicBlock(); + + /// getParent - Return the enclosing method, or null if none + /// + const Function *getParent() const { return Parent; } + Function *getParent() { return Parent; } + + /// use_back - Specialize the methods defined in Value, as we know that an + /// BasicBlock can only be used by Users (specifically PHI nodes, terminators, + /// and BlockAddress's). + User *use_back() { return cast(*use_begin());} + const User *use_back() const { return cast(*use_begin());} + + /// getTerminator() - If this is a well formed basic block, then this returns + /// a pointer to the terminator instruction. If it is not, then you get a + /// null pointer back. + /// + TerminatorInst *getTerminator(); + const TerminatorInst *getTerminator() const; + + /// Returns a pointer to the first instructon in this block that is not a + /// PHINode instruction. When adding instruction to the beginning of the + /// basic block, they should be added before the returned value, not before + /// the first instruction, which might be PHI. + /// Returns 0 is there's no non-PHI instruction. + Instruction* getFirstNonPHI(); + const Instruction* getFirstNonPHI() const { + return const_cast(this)->getFirstNonPHI(); + } + + /// removeFromParent - This method unlinks 'this' from the containing + /// function, but does not delete it. + /// + void removeFromParent(); + + /// eraseFromParent - This method unlinks 'this' from the containing function + /// and deletes it. + /// + void eraseFromParent(); + + /// moveBefore - Unlink this basic block from its current function and + /// insert it into the function that MovePos lives in, right before MovePos. + void moveBefore(BasicBlock *MovePos); + + /// moveAfter - Unlink this basic block from its current function and + /// insert it into the function that MovePos lives in, right after MovePos. + void moveAfter(BasicBlock *MovePos); + + + /// getSinglePredecessor - If this basic block has a single predecessor block, + /// return the block, otherwise return a null pointer. + BasicBlock *getSinglePredecessor(); + const BasicBlock *getSinglePredecessor() const { + return const_cast(this)->getSinglePredecessor(); + } + + /// getUniquePredecessor - If this basic block has a unique predecessor block, + /// return the block, otherwise return a null pointer. + /// Note that unique predecessor doesn't mean single edge, there can be + /// multiple edges from the unique predecessor to this block (for example + /// a switch statement with multiple cases having the same destination). + BasicBlock *getUniquePredecessor(); + const BasicBlock *getUniquePredecessor() const { + return const_cast(this)->getUniquePredecessor(); + } + + //===--------------------------------------------------------------------===// + /// Instruction iterator methods + /// + inline iterator begin() { return InstList.begin(); } + inline const_iterator begin() const { return InstList.begin(); } + inline iterator end () { return InstList.end(); } + inline const_iterator end () const { return InstList.end(); } + + inline size_t size() const { return InstList.size(); } + inline bool empty() const { return InstList.empty(); } + inline const Instruction &front() const { return InstList.front(); } + inline Instruction &front() { return InstList.front(); } + inline const Instruction &back() const { return InstList.back(); } + inline Instruction &back() { return InstList.back(); } + + /// getInstList() - Return the underlying instruction list container. You + /// need to access it directly if you want to modify it currently. + /// + const InstListType &getInstList() const { return InstList; } + InstListType &getInstList() { return InstList; } + + /// getSublistAccess() - returns pointer to member of instruction list + static iplist BasicBlock::*getSublistAccess(Instruction*) { + return &BasicBlock::InstList; + } + + /// getValueSymbolTable() - returns pointer to symbol table (if any) + ValueSymbolTable *getValueSymbolTable(); + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const BasicBlock *) { return true; } + static inline bool classof(const Value *V) { + return V->getValueID() == Value::BasicBlockVal; + } + + /// dropAllReferences() - This function causes all the subinstructions to "let + /// go" of all references that they are maintaining. This allows one to + /// 'delete' a whole class at a time, even though there may be circular + /// references... first all references are dropped, and all use counts go to + /// zero. Then everything is delete'd for real. Note that no operations are + /// valid on an object that has "dropped all references", except operator + /// delete. + /// + void dropAllReferences(); + + /// removePredecessor - This method is used to notify a BasicBlock that the + /// specified Predecessor of the block is no longer able to reach it. This is + /// actually not used to update the Predecessor list, but is actually used to + /// update the PHI nodes that reside in the block. Note that this should be + /// called while the predecessor still refers to this block. + /// + void removePredecessor(BasicBlock *Pred, bool DontDeleteUselessPHIs = false); + + /// splitBasicBlock - This splits a basic block into two at the specified + /// instruction. Note that all instructions BEFORE the specified iterator + /// stay as part of the original basic block, an unconditional branch is added + /// to the original BB, and the rest of the instructions in the BB are moved + /// to the new BB, including the old terminator. The newly formed BasicBlock + /// is returned. This function invalidates the specified iterator. + /// + /// Note that this only works on well formed basic blocks (must have a + /// terminator), and 'I' must not be the end of instruction list (which would + /// cause a degenerate basic block to be formed, having a terminator inside of + /// the basic block). + /// + /// Also note that this doesn't preserve any passes. To split blocks while + /// keeping loop information consistent, use the SplitBlock utility function. + /// + BasicBlock *splitBasicBlock(iterator I, const Twine &BBName = ""); + + /// hasAddressTaken - returns true if there are any uses of this basic block + /// other than direct branches, switches, etc. to it. + bool hasAddressTaken() const { return SubclassData != 0; } + +private: + /// AdjustBlockAddressRefCount - BasicBlock stores the number of BlockAddress + /// objects using it. This is almost always 0, sometimes one, possibly but + /// almost never 2, and inconceivably 3 or more. + void AdjustBlockAddressRefCount(int Amt) { + SubclassData += Amt; + assert((int)(signed char)SubclassData >= 0 && "Refcount wrap-around"); + } +}; + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Bitcode/Archive.h b/libclamav/c++/llvm/include/llvm/Bitcode/Archive.h new file mode 100644 index 000000000..e19e4c09c --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Bitcode/Archive.h @@ -0,0 +1,549 @@ +//===-- llvm/Bitcode/Archive.h - LLVM Bitcode Archive -----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This header file declares the Archive and ArchiveMember classes that provide +// manipulation of LLVM Archive files. The implementation is provided by the +// lib/Bitcode/Archive library. This library is used to read and write +// archive (*.a) files that contain LLVM bitcode files (or others). +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_BITCODE_ARCHIVE_H +#define LLVM_BITCODE_ARCHIVE_H + +#include "llvm/ADT/ilist.h" +#include "llvm/ADT/ilist_node.h" +#include "llvm/System/Path.h" +#include +#include + +namespace llvm { + class MemoryBuffer; + +// Forward declare classes +class ModuleProvider; // From VMCore +class Module; // From VMCore +class Archive; // Declared below +class ArchiveMemberHeader; // Internal implementation class +class LLVMContext; // Global data + +/// This class is the main class manipulated by users of the Archive class. It +/// holds information about one member of the Archive. It is also the element +/// stored by the Archive's ilist, the Archive's main abstraction. Because of +/// the special requirements of archive files, users are not permitted to +/// construct ArchiveMember instances. You should obtain them from the methods +/// of the Archive class instead. +/// @brief This class represents a single archive member. +class ArchiveMember : public ilist_node { + /// @name Types + /// @{ + public: + /// These flags are used internally by the archive member to specify various + /// characteristics of the member. The various "is" methods below provide + /// access to the flags. The flags are not user settable. + enum Flags { + CompressedFlag = 1, ///< Member is a normal compressed file + SVR4SymbolTableFlag = 2, ///< Member is a SVR4 symbol table + BSD4SymbolTableFlag = 4, ///< Member is a BSD4 symbol table + LLVMSymbolTableFlag = 8, ///< Member is an LLVM symbol table + BitcodeFlag = 16, ///< Member is bitcode + HasPathFlag = 64, ///< Member has a full or partial path + HasLongFilenameFlag = 128, ///< Member uses the long filename syntax + StringTableFlag = 256 ///< Member is an ar(1) format string table + }; + + /// @} + /// @name Accessors + /// @{ + public: + /// @returns the parent Archive instance + /// @brief Get the archive associated with this member + Archive* getArchive() const { return parent; } + + /// @returns the path to the Archive's file + /// @brief Get the path to the archive member + const sys::Path& getPath() const { return path; } + + /// The "user" is the owner of the file per Unix security. This may not + /// have any applicability on non-Unix systems but is a required component + /// of the "ar" file format. + /// @brief Get the user associated with this archive member. + unsigned getUser() const { return info.getUser(); } + + /// The "group" is the owning group of the file per Unix security. This + /// may not have any applicability on non-Unix systems but is a required + /// component of the "ar" file format. + /// @brief Get the group associated with this archive member. + unsigned getGroup() const { return info.getGroup(); } + + /// The "mode" specifies the access permissions for the file per Unix + /// security. This may not have any applicabiity on non-Unix systems but is + /// a required component of the "ar" file format. + /// @brief Get the permission mode associated with this archive member. + unsigned getMode() const { return info.getMode(); } + + /// This method returns the time at which the archive member was last + /// modified when it was not in the archive. + /// @brief Get the time of last modification of the archive member. + sys::TimeValue getModTime() const { return info.getTimestamp(); } + + /// @returns the size of the archive member in bytes. + /// @brief Get the size of the archive member. + uint64_t getSize() const { return info.getSize(); } + + /// This method returns the total size of the archive member as it + /// appears on disk. This includes the file content, the header, the + /// long file name if any, and the padding. + /// @brief Get total on-disk member size. + unsigned getMemberSize() const; + + /// This method will return a pointer to the in-memory content of the + /// archive member, if it is available. If the data has not been loaded + /// into memory, the return value will be null. + /// @returns a pointer to the member's data. + /// @brief Get the data content of the archive member + const void* getData() const { return data; } + + /// This method determines if the member is a regular compressed file. + /// @returns true iff the archive member is a compressed regular file. + /// @brief Determine if the member is a compressed regular file. + bool isCompressed() const { return flags&CompressedFlag; } + + /// @returns true iff the member is a SVR4 (non-LLVM) symbol table + /// @brief Determine if this member is a SVR4 symbol table. + bool isSVR4SymbolTable() const { return flags&SVR4SymbolTableFlag; } + + /// @returns true iff the member is a BSD4.4 (non-LLVM) symbol table + /// @brief Determine if this member is a BSD4.4 symbol table. + bool isBSD4SymbolTable() const { return flags&BSD4SymbolTableFlag; } + + /// @returns true iff the archive member is the LLVM symbol table + /// @brief Determine if this member is the LLVM symbol table. + bool isLLVMSymbolTable() const { return flags&LLVMSymbolTableFlag; } + + /// @returns true iff the archive member is the ar(1) string table + /// @brief Determine if this member is the ar(1) string table. + bool isStringTable() const { return flags&StringTableFlag; } + + /// @returns true iff the archive member is a bitcode file. + /// @brief Determine if this member is a bitcode file. + bool isBitcode() const { return flags&BitcodeFlag; } + + /// @returns true iff the file name contains a path (directory) component. + /// @brief Determine if the member has a path + bool hasPath() const { return flags&HasPathFlag; } + + /// Long filenames are an artifact of the ar(1) file format which allows + /// up to sixteen characters in its header and doesn't allow a path + /// separator character (/). To avoid this, a "long format" member name is + /// allowed that doesn't have this restriction. This method determines if + /// that "long format" is used for this member. + /// @returns true iff the file name uses the long form + /// @brief Determin if the member has a long file name + bool hasLongFilename() const { return flags&HasLongFilenameFlag; } + + /// This method returns the status info (like Unix stat(2)) for the archive + /// member. The status info provides the file's size, permissions, and + /// modification time. The contents of the Path::StatusInfo structure, other + /// than the size and modification time, may not have utility on non-Unix + /// systems. + /// @returns the status info for the archive member + /// @brief Obtain the status info for the archive member + const sys::FileStatus &getFileStatus() const { return info; } + + /// This method causes the archive member to be replaced with the contents + /// of the file specified by \p File. The contents of \p this will be + /// updated to reflect the new data from \p File. The \p File must exist and + /// be readable on entry to this method. + /// @returns true if an error occurred, false otherwise + /// @brief Replace contents of archive member with a new file. + bool replaceWith(const sys::Path &aFile, std::string* ErrMsg); + + /// @} + /// @name Data + /// @{ + private: + Archive* parent; ///< Pointer to parent archive + sys::PathWithStatus path; ///< Path of file containing the member + sys::FileStatus info; ///< Status info (size,mode,date) + unsigned flags; ///< Flags about the archive member + const void* data; ///< Data for the member + + /// @} + /// @name Constructors + /// @{ + public: + /// The default constructor is only used by the Archive's iplist when it + /// constructs the list's sentry node. + ArchiveMember(); + + private: + /// Used internally by the Archive class to construct an ArchiveMember. + /// The contents of the ArchiveMember are filled out by the Archive class. + explicit ArchiveMember(Archive *PAR); + + // So Archive can construct an ArchiveMember + friend class llvm::Archive; + /// @} +}; + +/// This class defines the interface to LLVM Archive files. The Archive class +/// presents the archive file as an ilist of ArchiveMember objects. The members +/// can be rearranged in any fashion either by directly editing the ilist or by +/// using editing methods on the Archive class (recommended). The Archive +/// class also provides several ways of accessing the archive file for various +/// purposes such as editing and linking. Full symbol table support is provided +/// for loading only those files that resolve symbols. Note that read +/// performance of this library is _crucial_ for performance of JIT type +/// applications and the linkers. Consequently, the implementation of the class +/// is optimized for reading. +class Archive { + + /// @name Types + /// @{ + public: + /// This is the ilist type over which users may iterate to examine + /// the contents of the archive + /// @brief The ilist type of ArchiveMembers that Archive contains. + typedef iplist MembersList; + + /// @brief Forward mutable iterator over ArchiveMember + typedef MembersList::iterator iterator; + + /// @brief Forward immutable iterator over ArchiveMember + typedef MembersList::const_iterator const_iterator; + + /// @brief Reverse mutable iterator over ArchiveMember + typedef std::reverse_iterator reverse_iterator; + + /// @brief Reverse immutable iterator over ArchiveMember + typedef std::reverse_iterator const_reverse_iterator; + + /// @brief The in-memory version of the symbol table + typedef std::map SymTabType; + + /// @} + /// @name ilist accessor methods + /// @{ + public: + inline iterator begin() { return members.begin(); } + inline const_iterator begin() const { return members.begin(); } + inline iterator end () { return members.end(); } + inline const_iterator end () const { return members.end(); } + + inline reverse_iterator rbegin() { return members.rbegin(); } + inline const_reverse_iterator rbegin() const { return members.rbegin(); } + inline reverse_iterator rend () { return members.rend(); } + inline const_reverse_iterator rend () const { return members.rend(); } + + inline size_t size() const { return members.size(); } + inline bool empty() const { return members.empty(); } + inline const ArchiveMember& front() const { return members.front(); } + inline ArchiveMember& front() { return members.front(); } + inline const ArchiveMember& back() const { return members.back(); } + inline ArchiveMember& back() { return members.back(); } + + /// @} + /// @name ilist mutator methods + /// @{ + public: + /// This method splices a \p src member from an archive (possibly \p this), + /// to a position just before the member given by \p dest in \p this. When + /// the archive is written, \p src will be written in its new location. + /// @brief Move a member to a new location + inline void splice(iterator dest, Archive& arch, iterator src) + { return members.splice(dest,arch.members,src); } + + /// This method erases a \p target member from the archive. When the + /// archive is written, it will no longer contain \p target. The associated + /// ArchiveMember is deleted. + /// @brief Erase a member. + inline iterator erase(iterator target) { return members.erase(target); } + + /// @} + /// @name Constructors + /// @{ + public: + /// Create an empty archive file and associate it with the \p Filename. This + /// method does not actually create the archive disk file. It creates an + /// empty Archive object. If the writeToDisk method is called, the archive + /// file \p Filename will be created at that point, with whatever content + /// the returned Archive object has at that time. + /// @returns An Archive* that represents the new archive file. + /// @brief Create an empty Archive. + static Archive* CreateEmpty( + const sys::Path& Filename,///< Name of the archive to (eventually) create. + LLVMContext& C ///< Context to use for global information + ); + + /// Open an existing archive and load its contents in preparation for + /// editing. After this call, the member ilist is completely populated based + /// on the contents of the archive file. You should use this form of open if + /// you intend to modify the archive or traverse its contents (e.g. for + /// printing). + /// @brief Open and load an archive file + static Archive* OpenAndLoad( + const sys::Path& filePath, ///< The file path to open and load + LLVMContext& C, ///< The context to use for global information + std::string* ErrorMessage ///< An optional error string + ); + + /// This method opens an existing archive file from \p Filename and reads in + /// its symbol table without reading in any of the archive's members. This + /// reduces both I/O and cpu time in opening the archive if it is to be used + /// solely for symbol lookup (e.g. during linking). The \p Filename must + /// exist and be an archive file or an exception will be thrown. This form + /// of opening the archive is intended for read-only operations that need to + /// locate members via the symbol table for link editing. Since the archve + /// members are not read by this method, the archive will appear empty upon + /// return. If editing operations are performed on the archive, they will + /// completely replace the contents of the archive! It is recommended that + /// if this form of opening the archive is used that only the symbol table + /// lookup methods (getSymbolTable, findModuleDefiningSymbol, and + /// findModulesDefiningSymbols) be used. + /// @throws std::string if an error occurs opening the file + /// @returns an Archive* that represents the archive file. + /// @brief Open an existing archive and load its symbols. + static Archive* OpenAndLoadSymbols( + const sys::Path& Filename, ///< Name of the archive file to open + LLVMContext& C, ///< The context to use for global info + std::string* ErrorMessage=0 ///< An optional error string + ); + + /// This destructor cleans up the Archive object, releases all memory, and + /// closes files. It does nothing with the archive file on disk. If you + /// haven't used the writeToDisk method by the time the destructor is + /// called, all changes to the archive will be lost. + /// @throws std::string if an error occurs + /// @brief Destruct in-memory archive + ~Archive(); + + /// @} + /// @name Accessors + /// @{ + public: + /// @returns the path to the archive file. + /// @brief Get the archive path. + const sys::Path& getPath() { return archPath; } + + /// This method is provided so that editing methods can be invoked directly + /// on the Archive's iplist of ArchiveMember. However, it is recommended + /// that the usual STL style iterator interface be used instead. + /// @returns the iplist of ArchiveMember + /// @brief Get the iplist of the members + MembersList& getMembers() { return members; } + + /// This method allows direct query of the Archive's symbol table. The + /// symbol table is a std::map of std::string (the symbol) to unsigned (the + /// file offset). Note that for efficiency reasons, the offset stored in + /// the symbol table is not the actual offset. It is the offset from the + /// beginning of the first "real" file member (after the symbol table). Use + /// the getFirstFileOffset() to obtain that offset and add this value to the + /// offset in the symbol table to obtain the real file offset. Note that + /// there is purposefully no interface provided by Archive to look up + /// members by their offset. Use the findModulesDefiningSymbols and + /// findModuleDefiningSymbol methods instead. + /// @returns the Archive's symbol table. + /// @brief Get the archive's symbol table + const SymTabType& getSymbolTable() { return symTab; } + + /// This method returns the offset in the archive file to the first "real" + /// file member. Archive files, on disk, have a signature and might have a + /// symbol table that precedes the first actual file member. This method + /// allows you to determine what the size of those fields are. + /// @returns the offset to the first "real" file member in the archive. + /// @brief Get the offset to the first "real" file member in the archive. + unsigned getFirstFileOffset() { return firstFileOffset; } + + /// This method will scan the archive for bitcode modules, interpret them + /// and return a vector of the instantiated modules in \p Modules. If an + /// error occurs, this method will return true. If \p ErrMessage is not null + /// and an error occurs, \p *ErrMessage will be set to a string explaining + /// the error that occurred. + /// @returns true if an error occurred + /// @brief Instantiate all the bitcode modules located in the archive + bool getAllModules(std::vector& Modules, std::string* ErrMessage); + + /// This accessor looks up the \p symbol in the archive's symbol table and + /// returns the associated module that defines that symbol. This method can + /// be called as many times as necessary. This is handy for linking the + /// archive into another module based on unresolved symbols. Note that the + /// ModuleProvider returned by this accessor should not be deleted by the + /// caller. It is managed internally by the Archive class. It is possible + /// that multiple calls to this accessor will return the same ModuleProvider + /// instance because the associated module defines multiple symbols. + /// @returns The ModuleProvider* found or null if the archive does not + /// contain a module that defines the \p symbol. + /// @brief Look up a module by symbol name. + ModuleProvider* findModuleDefiningSymbol( + const std::string& symbol, ///< Symbol to be sought + std::string* ErrMessage ///< Error message storage, if non-zero + ); + + /// This method is similar to findModuleDefiningSymbol but allows lookup of + /// more than one symbol at a time. If \p symbols contains a list of + /// undefined symbols in some module, then calling this method is like + /// making one complete pass through the archive to resolve symbols but is + /// more efficient than looking at the individual members. Note that on + /// exit, the symbols resolved by this method will be removed from \p + /// symbols to ensure they are not re-searched on a subsequent call. If + /// you need to retain the list of symbols, make a copy. + /// @brief Look up multiple symbols in the archive. + bool findModulesDefiningSymbols( + std::set& symbols, ///< Symbols to be sought + std::set& modules, ///< The modules matching \p symbols + std::string* ErrMessage ///< Error msg storage, if non-zero + ); + + /// This method determines whether the archive is a properly formed llvm + /// bitcode archive. It first makes sure the symbol table has been loaded + /// and has a non-zero size. If it does, then it is an archive. If not, + /// then it tries to load all the bitcode modules of the archive. Finally, + /// it returns whether it was successfull. + /// @returns true if the archive is a proper llvm bitcode archive + /// @brief Determine whether the archive is a proper llvm bitcode archive. + bool isBitcodeArchive(); + + /// @} + /// @name Mutators + /// @{ + public: + /// This method is the only way to get the archive written to disk. It + /// creates or overwrites the file specified when \p this was created + /// or opened. The arguments provide options for writing the archive. If + /// \p CreateSymbolTable is true, the archive is scanned for bitcode files + /// and a symbol table of the externally visible function and global + /// variable names is created. If \p TruncateNames is true, the names of the + /// archive members will have their path component stripped and the file + /// name will be truncated at 15 characters. If \p Compress is specified, + /// all archive members will be compressed before being written. If + /// \p PrintSymTab is true, the symbol table will be printed to std::cout. + /// @returns true if an error occurred, \p error set to error message + /// @returns false if the writing succeeded. + /// @brief Write (possibly modified) archive contents to disk + bool writeToDisk( + bool CreateSymbolTable=false, ///< Create Symbol table + bool TruncateNames=false, ///< Truncate the filename to 15 chars + bool Compress=false, ///< Compress files + std::string* ErrMessage=0 ///< If non-null, where error msg is set + ); + + /// This method adds a new file to the archive. The \p filename is examined + /// to determine just enough information to create an ArchiveMember object + /// which is then inserted into the Archive object's ilist at the location + /// given by \p where. + /// @returns true if an error occured, false otherwise + /// @brief Add a file to the archive. + bool addFileBefore( + const sys::Path& filename, ///< The file to be added + iterator where, ///< Insertion point + std::string* ErrMsg ///< Optional error message location + ); + + /// @} + /// @name Implementation + /// @{ + protected: + /// @brief Construct an Archive for \p filename and optionally map it + /// into memory. + explicit Archive(const sys::Path& filename, LLVMContext& C); + + /// @param data The symbol table data to be parsed + /// @param len The length of the symbol table data + /// @param error Set to address of a std::string to get error messages + /// @returns false on error + /// @brief Parse the symbol table at \p data. + bool parseSymbolTable(const void* data,unsigned len,std::string* error); + + /// @returns A fully populated ArchiveMember or 0 if an error occurred. + /// @brief Parse the header of a member starting at \p At + ArchiveMember* parseMemberHeader( + const char*&At, ///< The pointer to the location we're parsing + const char*End, ///< The pointer to the end of the archive + std::string* error ///< Optional error message catcher + ); + + /// @param ErrMessage Set to address of a std::string to get error messages + /// @returns false on error + /// @brief Check that the archive signature is correct + bool checkSignature(std::string* ErrMessage); + + /// @param ErrMessage Set to address of a std::string to get error messages + /// @returns false on error + /// @brief Load the entire archive. + bool loadArchive(std::string* ErrMessage); + + /// @param ErrMessage Set to address of a std::string to get error messages + /// @returns false on error + /// @brief Load just the symbol table. + bool loadSymbolTable(std::string* ErrMessage); + + /// @brief Write the symbol table to an ofstream. + void writeSymbolTable(std::ofstream& ARFile); + + /// Writes one ArchiveMember to an ofstream. If an error occurs, returns + /// false, otherwise true. If an error occurs and error is non-null then + /// it will be set to an error message. + /// @returns false Writing member succeeded + /// @returns true Writing member failed, \p error set to error message + bool writeMember( + const ArchiveMember& member, ///< The member to be written + std::ofstream& ARFile, ///< The file to write member onto + bool CreateSymbolTable, ///< Should symbol table be created? + bool TruncateNames, ///< Should names be truncated to 11 chars? + bool ShouldCompress, ///< Should the member be compressed? + std::string* ErrMessage ///< If non-null, place were error msg is set + ); + + /// @brief Fill in an ArchiveMemberHeader from ArchiveMember. + bool fillHeader(const ArchiveMember&mbr, + ArchiveMemberHeader& hdr,int sz, bool TruncateNames) const; + + /// @brief Maps archive into memory + bool mapToMemory(std::string* ErrMsg); + + /// @brief Frees all the members and unmaps the archive file. + void cleanUpMemory(); + + /// This type is used to keep track of bitcode modules loaded from the + /// symbol table. It maps the file offset to a pair that consists of the + /// associated ArchiveMember and the ModuleProvider. + /// @brief Module mapping type + typedef std::map > + ModuleMap; + + + /// @} + /// @name Data + /// @{ + protected: + sys::Path archPath; ///< Path to the archive file we read/write + MembersList members; ///< The ilist of ArchiveMember + MemoryBuffer *mapfile; ///< Raw Archive contents mapped into memory + const char* base; ///< Base of the memory mapped file data + SymTabType symTab; ///< The symbol table + std::string strtab; ///< The string table for long file names + unsigned symTabSize; ///< Size in bytes of symbol table + unsigned firstFileOffset; ///< Offset to first normal file. + ModuleMap modules; ///< The modules loaded via symbol lookup. + ArchiveMember* foreignST; ///< This holds the foreign symbol table. + LLVMContext& Context; ///< This holds global data. + /// @} + /// @name Hidden + /// @{ + private: + Archive(); ///< Do not implement + Archive(const Archive&); ///< Do not implement + Archive& operator=(const Archive&); ///< Do not implement + /// @} +}; + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Bitcode/BitCodes.h b/libclamav/c++/llvm/include/llvm/Bitcode/BitCodes.h new file mode 100644 index 000000000..ada2e65ee --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Bitcode/BitCodes.h @@ -0,0 +1,185 @@ +//===- BitCodes.h - Enum values for the bitcode format ----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This header Bitcode enum values. +// +// The enum values defined in this file should be considered permanent. If +// new features are added, they should have values added at the end of the +// respective lists. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_BITCODE_BITCODES_H +#define LLVM_BITCODE_BITCODES_H + +#include "llvm/ADT/SmallVector.h" +#include "llvm/System/DataTypes.h" +#include + +namespace llvm { +namespace bitc { + enum StandardWidths { + BlockIDWidth = 8, // We use VBR-8 for block IDs. + CodeLenWidth = 4, // Codelen are VBR-4. + BlockSizeWidth = 32 // BlockSize up to 2^32 32-bit words = 16GB per block. + }; + + // The standard abbrev namespace always has a way to exit a block, enter a + // nested block, define abbrevs, and define an unabbreviated record. + enum FixedAbbrevIDs { + END_BLOCK = 0, // Must be zero to guarantee termination for broken bitcode. + ENTER_SUBBLOCK = 1, + + /// DEFINE_ABBREV - Defines an abbrev for the current block. It consists + /// of a vbr5 for # operand infos. Each operand info is emitted with a + /// single bit to indicate if it is a literal encoding. If so, the value is + /// emitted with a vbr8. If not, the encoding is emitted as 3 bits followed + /// by the info value as a vbr5 if needed. + DEFINE_ABBREV = 2, + + // UNABBREV_RECORDs are emitted with a vbr6 for the record code, followed by + // a vbr6 for the # operands, followed by vbr6's for each operand. + UNABBREV_RECORD = 3, + + // This is not a code, this is a marker for the first abbrev assignment. + FIRST_APPLICATION_ABBREV = 4 + }; + + /// StandardBlockIDs - All bitcode files can optionally include a BLOCKINFO + /// block, which contains metadata about other blocks in the file. + enum StandardBlockIDs { + /// BLOCKINFO_BLOCK is used to define metadata about blocks, for example, + /// standard abbrevs that should be available to all blocks of a specified + /// ID. + BLOCKINFO_BLOCK_ID = 0, + + // Block IDs 1-7 are reserved for future expansion. + FIRST_APPLICATION_BLOCKID = 8 + }; + + /// BlockInfoCodes - The blockinfo block contains metadata about user-defined + /// blocks. + enum BlockInfoCodes { + // DEFINE_ABBREV has magic semantics here, applying to the current SETBID'd + // block, instead of the BlockInfo block. + + BLOCKINFO_CODE_SETBID = 1, // SETBID: [blockid#] + BLOCKINFO_CODE_BLOCKNAME = 2, // BLOCKNAME: [name] + BLOCKINFO_CODE_SETRECORDNAME = 3 // BLOCKINFO_CODE_SETRECORDNAME: [id, name] + }; + +} // End bitc namespace + +/// BitCodeAbbrevOp - This describes one or more operands in an abbreviation. +/// This is actually a union of two different things: +/// 1. It could be a literal integer value ("the operand is always 17"). +/// 2. It could be an encoding specification ("this operand encoded like so"). +/// +class BitCodeAbbrevOp { + uint64_t Val; // A literal value or data for an encoding. + bool IsLiteral : 1; // Indicate whether this is a literal value or not. + unsigned Enc : 3; // The encoding to use. +public: + enum Encoding { + Fixed = 1, // A fixed width field, Val specifies number of bits. + VBR = 2, // A VBR field where Val specifies the width of each chunk. + Array = 3, // A sequence of fields, next field species elt encoding. + Char6 = 4, // A 6-bit fixed field which maps to [a-zA-Z0-9._]. + Blob = 5 // 32-bit aligned array of 8-bit characters. + }; + + explicit BitCodeAbbrevOp(uint64_t V) : Val(V), IsLiteral(true) {} + explicit BitCodeAbbrevOp(Encoding E, uint64_t Data = 0) + : Val(Data), IsLiteral(false), Enc(E) {} + + bool isLiteral() const { return IsLiteral; } + bool isEncoding() const { return !IsLiteral; } + + // Accessors for literals. + uint64_t getLiteralValue() const { assert(isLiteral()); return Val; } + + // Accessors for encoding info. + Encoding getEncoding() const { assert(isEncoding()); return (Encoding)Enc; } + uint64_t getEncodingData() const { + assert(isEncoding() && hasEncodingData()); + return Val; + } + + bool hasEncodingData() const { return hasEncodingData(getEncoding()); } + static bool hasEncodingData(Encoding E) { + switch (E) { + default: assert(0 && "Unknown encoding"); + case Fixed: + case VBR: + return true; + case Array: + case Char6: + case Blob: + return false; + } + } + + /// isChar6 - Return true if this character is legal in the Char6 encoding. + static bool isChar6(char C) { + if (C >= 'a' && C <= 'z') return true; + if (C >= 'A' && C <= 'Z') return true; + if (C >= '0' && C <= '9') return true; + if (C == '.' || C == '_') return true; + return false; + } + static unsigned EncodeChar6(char C) { + if (C >= 'a' && C <= 'z') return C-'a'; + if (C >= 'A' && C <= 'Z') return C-'A'+26; + if (C >= '0' && C <= '9') return C-'0'+26+26; + if (C == '.') return 62; + if (C == '_') return 63; + assert(0 && "Not a value Char6 character!"); + return 0; + } + + static char DecodeChar6(unsigned V) { + assert((V & ~63) == 0 && "Not a Char6 encoded character!"); + if (V < 26) return V+'a'; + if (V < 26+26) return V-26+'A'; + if (V < 26+26+10) return V-26-26+'0'; + if (V == 62) return '.'; + if (V == 63) return '_'; + assert(0 && "Not a value Char6 character!"); + return ' '; + } + +}; + +/// BitCodeAbbrev - This class represents an abbreviation record. An +/// abbreviation allows a complex record that has redundancy to be stored in a +/// specialized format instead of the fully-general, fully-vbr, format. +class BitCodeAbbrev { + SmallVector OperandList; + unsigned char RefCount; // Number of things using this. + ~BitCodeAbbrev() {} +public: + BitCodeAbbrev() : RefCount(1) {} + + void addRef() { ++RefCount; } + void dropRef() { if (--RefCount == 0) delete this; } + + unsigned getNumOperandInfos() const { + return static_cast(OperandList.size()); + } + const BitCodeAbbrevOp &getOperandInfo(unsigned N) const { + return OperandList[N]; + } + + void Add(const BitCodeAbbrevOp &OpInfo) { + OperandList.push_back(OpInfo); + } +}; +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Bitcode/BitstreamReader.h b/libclamav/c++/llvm/include/llvm/Bitcode/BitstreamReader.h new file mode 100644 index 000000000..779ef5fa2 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Bitcode/BitstreamReader.h @@ -0,0 +1,642 @@ +//===- BitstreamReader.h - Low-level bitstream reader 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 defines the BitstreamReader class. This class can be used to +// read an arbitrary bitstream, regardless of its contents. +// +//===----------------------------------------------------------------------===// + +#ifndef BITSTREAM_READER_H +#define BITSTREAM_READER_H + +#include "llvm/Bitcode/BitCodes.h" +#include +#include +#include + +namespace llvm { + + class Deserializer; + +class BitstreamReader { +public: + /// BlockInfo - This contains information emitted to BLOCKINFO_BLOCK blocks. + /// These describe abbreviations that all blocks of the specified ID inherit. + struct BlockInfo { + unsigned BlockID; + std::vector Abbrevs; + std::string Name; + + std::vector > RecordNames; + }; +private: + /// FirstChar/LastChar - This remembers the first and last bytes of the + /// stream. + const unsigned char *FirstChar, *LastChar; + + std::vector BlockInfoRecords; + + /// IgnoreBlockInfoNames - This is set to true if we don't care about the + /// block/record name information in the BlockInfo block. Only llvm-bcanalyzer + /// uses this. + bool IgnoreBlockInfoNames; + + BitstreamReader(const BitstreamReader&); // NOT IMPLEMENTED + void operator=(const BitstreamReader&); // NOT IMPLEMENTED +public: + BitstreamReader() : FirstChar(0), LastChar(0), IgnoreBlockInfoNames(true) { + } + + BitstreamReader(const unsigned char *Start, const unsigned char *End) { + IgnoreBlockInfoNames = true; + init(Start, End); + } + + void init(const unsigned char *Start, const unsigned char *End) { + FirstChar = Start; + LastChar = End; + assert(((End-Start) & 3) == 0 &&"Bitcode stream not a multiple of 4 bytes"); + } + + ~BitstreamReader() { + // Free the BlockInfoRecords. + while (!BlockInfoRecords.empty()) { + BlockInfo &Info = BlockInfoRecords.back(); + // Free blockinfo abbrev info. + for (unsigned i = 0, e = static_cast(Info.Abbrevs.size()); + i != e; ++i) + Info.Abbrevs[i]->dropRef(); + BlockInfoRecords.pop_back(); + } + } + + const unsigned char *getFirstChar() const { return FirstChar; } + const unsigned char *getLastChar() const { return LastChar; } + + /// CollectBlockInfoNames - This is called by clients that want block/record + /// name information. + void CollectBlockInfoNames() { IgnoreBlockInfoNames = false; } + bool isIgnoringBlockInfoNames() { return IgnoreBlockInfoNames; } + + //===--------------------------------------------------------------------===// + // Block Manipulation + //===--------------------------------------------------------------------===// + + /// hasBlockInfoRecords - Return true if we've already read and processed the + /// block info block for this Bitstream. We only process it for the first + /// cursor that walks over it. + bool hasBlockInfoRecords() const { return !BlockInfoRecords.empty(); } + + /// getBlockInfo - If there is block info for the specified ID, return it, + /// otherwise return null. + const BlockInfo *getBlockInfo(unsigned BlockID) const { + // Common case, the most recent entry matches BlockID. + if (!BlockInfoRecords.empty() && BlockInfoRecords.back().BlockID == BlockID) + return &BlockInfoRecords.back(); + + for (unsigned i = 0, e = static_cast(BlockInfoRecords.size()); + i != e; ++i) + if (BlockInfoRecords[i].BlockID == BlockID) + return &BlockInfoRecords[i]; + return 0; + } + + BlockInfo &getOrCreateBlockInfo(unsigned BlockID) { + if (const BlockInfo *BI = getBlockInfo(BlockID)) + return *const_cast(BI); + + // Otherwise, add a new record. + BlockInfoRecords.push_back(BlockInfo()); + BlockInfoRecords.back().BlockID = BlockID; + return BlockInfoRecords.back(); + } + +}; + +class BitstreamCursor { + friend class Deserializer; + BitstreamReader *BitStream; + const unsigned char *NextChar; + + /// CurWord - This is the current data we have pulled from the stream but have + /// not returned to the client. + uint32_t CurWord; + + /// BitsInCurWord - This is the number of bits in CurWord that are valid. This + /// is always from [0...31] inclusive. + unsigned BitsInCurWord; + + // CurCodeSize - This is the declared size of code values used for the current + // block, in bits. + unsigned CurCodeSize; + + /// CurAbbrevs - Abbrevs installed at in this block. + std::vector CurAbbrevs; + + struct Block { + unsigned PrevCodeSize; + std::vector PrevAbbrevs; + explicit Block(unsigned PCS) : PrevCodeSize(PCS) {} + }; + + /// BlockScope - This tracks the codesize of parent blocks. + SmallVector BlockScope; + +public: + BitstreamCursor() : BitStream(0), NextChar(0) { + } + BitstreamCursor(const BitstreamCursor &RHS) : BitStream(0), NextChar(0) { + operator=(RHS); + } + + explicit BitstreamCursor(BitstreamReader &R) : BitStream(&R) { + NextChar = R.getFirstChar(); + assert(NextChar && "Bitstream not initialized yet"); + CurWord = 0; + BitsInCurWord = 0; + CurCodeSize = 2; + } + + void init(BitstreamReader &R) { + freeState(); + + BitStream = &R; + NextChar = R.getFirstChar(); + assert(NextChar && "Bitstream not initialized yet"); + CurWord = 0; + BitsInCurWord = 0; + CurCodeSize = 2; + } + + ~BitstreamCursor() { + freeState(); + } + + void operator=(const BitstreamCursor &RHS) { + freeState(); + + BitStream = RHS.BitStream; + NextChar = RHS.NextChar; + CurWord = RHS.CurWord; + BitsInCurWord = RHS.BitsInCurWord; + CurCodeSize = RHS.CurCodeSize; + + // Copy abbreviations, and bump ref counts. + CurAbbrevs = RHS.CurAbbrevs; + for (unsigned i = 0, e = static_cast(CurAbbrevs.size()); + i != e; ++i) + CurAbbrevs[i]->addRef(); + + // Copy block scope and bump ref counts. + for (unsigned S = 0, e = static_cast(BlockScope.size()); + S != e; ++S) { + std::vector &Abbrevs = BlockScope[S].PrevAbbrevs; + for (unsigned i = 0, e = static_cast(Abbrevs.size()); + i != e; ++i) + Abbrevs[i]->addRef(); + } + } + + void freeState() { + // Free all the Abbrevs. + for (unsigned i = 0, e = static_cast(CurAbbrevs.size()); + i != e; ++i) + CurAbbrevs[i]->dropRef(); + CurAbbrevs.clear(); + + // Free all the Abbrevs in the block scope. + for (unsigned S = 0, e = static_cast(BlockScope.size()); + S != e; ++S) { + std::vector &Abbrevs = BlockScope[S].PrevAbbrevs; + for (unsigned i = 0, e = static_cast(Abbrevs.size()); + i != e; ++i) + Abbrevs[i]->dropRef(); + } + BlockScope.clear(); + } + + /// GetAbbrevIDWidth - Return the number of bits used to encode an abbrev #. + unsigned GetAbbrevIDWidth() const { return CurCodeSize; } + + bool AtEndOfStream() const { + return NextChar == BitStream->getLastChar() && BitsInCurWord == 0; + } + + /// GetCurrentBitNo - Return the bit # of the bit we are reading. + uint64_t GetCurrentBitNo() const { + return (NextChar-BitStream->getFirstChar())*CHAR_BIT - BitsInCurWord; + } + + BitstreamReader *getBitStreamReader() { + return BitStream; + } + const BitstreamReader *getBitStreamReader() const { + return BitStream; + } + + + /// JumpToBit - Reset the stream to the specified bit number. + void JumpToBit(uint64_t BitNo) { + uintptr_t ByteNo = uintptr_t(BitNo/8) & ~3; + uintptr_t WordBitNo = uintptr_t(BitNo) & 31; + assert(ByteNo <= (uintptr_t)(BitStream->getLastChar()- + BitStream->getFirstChar()) && + "Invalid location"); + + // Move the cursor to the right word. + NextChar = BitStream->getFirstChar()+ByteNo; + BitsInCurWord = 0; + CurWord = 0; + + // Skip over any bits that are already consumed. + if (WordBitNo) + Read(static_cast(WordBitNo)); + } + + + uint32_t Read(unsigned NumBits) { + assert(NumBits <= 32 && "Cannot return more than 32 bits!"); + // If the field is fully contained by CurWord, return it quickly. + if (BitsInCurWord >= NumBits) { + uint32_t R = CurWord & ((1U << NumBits)-1); + CurWord >>= NumBits; + BitsInCurWord -= NumBits; + return R; + } + + // If we run out of data, stop at the end of the stream. + if (NextChar == BitStream->getLastChar()) { + CurWord = 0; + BitsInCurWord = 0; + return 0; + } + + unsigned R = CurWord; + + // Read the next word from the stream. + CurWord = (NextChar[0] << 0) | (NextChar[1] << 8) | + (NextChar[2] << 16) | (NextChar[3] << 24); + NextChar += 4; + + // Extract NumBits-BitsInCurWord from what we just read. + unsigned BitsLeft = NumBits-BitsInCurWord; + + // Be careful here, BitsLeft is in the range [1..32] inclusive. + R |= (CurWord & (~0U >> (32-BitsLeft))) << BitsInCurWord; + + // BitsLeft bits have just been used up from CurWord. + if (BitsLeft != 32) + CurWord >>= BitsLeft; + else + CurWord = 0; + BitsInCurWord = 32-BitsLeft; + return R; + } + + uint64_t Read64(unsigned NumBits) { + if (NumBits <= 32) return Read(NumBits); + + uint64_t V = Read(32); + return V | (uint64_t)Read(NumBits-32) << 32; + } + + uint32_t ReadVBR(unsigned NumBits) { + uint32_t Piece = Read(NumBits); + if ((Piece & (1U << (NumBits-1))) == 0) + return Piece; + + uint32_t Result = 0; + unsigned NextBit = 0; + while (1) { + Result |= (Piece & ((1U << (NumBits-1))-1)) << NextBit; + + if ((Piece & (1U << (NumBits-1))) == 0) + return Result; + + NextBit += NumBits-1; + Piece = Read(NumBits); + } + } + + // ReadVBR64 - Read a VBR that may have a value up to 64-bits in size. The + // chunk size of the VBR must still be <= 32 bits though. + uint64_t ReadVBR64(unsigned NumBits) { + uint32_t Piece = Read(NumBits); + if ((Piece & (1U << (NumBits-1))) == 0) + return uint64_t(Piece); + + uint64_t Result = 0; + unsigned NextBit = 0; + while (1) { + Result |= uint64_t(Piece & ((1U << (NumBits-1))-1)) << NextBit; + + if ((Piece & (1U << (NumBits-1))) == 0) + return Result; + + NextBit += NumBits-1; + Piece = Read(NumBits); + } + } + + void SkipToWord() { + BitsInCurWord = 0; + CurWord = 0; + } + + unsigned ReadCode() { + return Read(CurCodeSize); + } + + + // Block header: + // [ENTER_SUBBLOCK, blockid, newcodelen, , blocklen] + + /// ReadSubBlockID - Having read the ENTER_SUBBLOCK code, read the BlockID for + /// the block. + unsigned ReadSubBlockID() { + return ReadVBR(bitc::BlockIDWidth); + } + + /// SkipBlock - Having read the ENTER_SUBBLOCK abbrevid and a BlockID, skip + /// over the body of this block. If the block record is malformed, return + /// true. + bool SkipBlock() { + // Read and ignore the codelen value. Since we are skipping this block, we + // don't care what code widths are used inside of it. + ReadVBR(bitc::CodeLenWidth); + SkipToWord(); + unsigned NumWords = Read(bitc::BlockSizeWidth); + + // Check that the block wasn't partially defined, and that the offset isn't + // bogus. + if (AtEndOfStream() || NextChar+NumWords*4 > BitStream->getLastChar()) + return true; + + NextChar += NumWords*4; + return false; + } + + /// EnterSubBlock - Having read the ENTER_SUBBLOCK abbrevid, enter + /// the block, and return true if the block is valid. + bool EnterSubBlock(unsigned BlockID, unsigned *NumWordsP = 0) { + // Save the current block's state on BlockScope. + BlockScope.push_back(Block(CurCodeSize)); + BlockScope.back().PrevAbbrevs.swap(CurAbbrevs); + + // Add the abbrevs specific to this block to the CurAbbrevs list. + if (const BitstreamReader::BlockInfo *Info = + BitStream->getBlockInfo(BlockID)) { + for (unsigned i = 0, e = static_cast(Info->Abbrevs.size()); + i != e; ++i) { + CurAbbrevs.push_back(Info->Abbrevs[i]); + CurAbbrevs.back()->addRef(); + } + } + + // Get the codesize of this block. + CurCodeSize = ReadVBR(bitc::CodeLenWidth); + SkipToWord(); + unsigned NumWords = Read(bitc::BlockSizeWidth); + if (NumWordsP) *NumWordsP = NumWords; + + // Validate that this block is sane. + if (CurCodeSize == 0 || AtEndOfStream() || + NextChar+NumWords*4 > BitStream->getLastChar()) + return true; + + return false; + } + + bool ReadBlockEnd() { + if (BlockScope.empty()) return true; + + // Block tail: + // [END_BLOCK, ] + SkipToWord(); + + PopBlockScope(); + return false; + } + +private: + void PopBlockScope() { + CurCodeSize = BlockScope.back().PrevCodeSize; + + // Delete abbrevs from popped scope. + for (unsigned i = 0, e = static_cast(CurAbbrevs.size()); + i != e; ++i) + CurAbbrevs[i]->dropRef(); + + BlockScope.back().PrevAbbrevs.swap(CurAbbrevs); + BlockScope.pop_back(); + } + + //===--------------------------------------------------------------------===// + // Record Processing + //===--------------------------------------------------------------------===// + +private: + void ReadAbbreviatedLiteral(const BitCodeAbbrevOp &Op, + SmallVectorImpl &Vals) { + assert(Op.isLiteral() && "Not a literal"); + // If the abbrev specifies the literal value to use, use it. + Vals.push_back(Op.getLiteralValue()); + } + + void ReadAbbreviatedField(const BitCodeAbbrevOp &Op, + SmallVectorImpl &Vals) { + assert(!Op.isLiteral() && "Use ReadAbbreviatedLiteral for literals!"); + + // Decode the value as we are commanded. + switch (Op.getEncoding()) { + default: assert(0 && "Unknown encoding!"); + case BitCodeAbbrevOp::Fixed: + Vals.push_back(Read((unsigned)Op.getEncodingData())); + break; + case BitCodeAbbrevOp::VBR: + Vals.push_back(ReadVBR64((unsigned)Op.getEncodingData())); + break; + case BitCodeAbbrevOp::Char6: + Vals.push_back(BitCodeAbbrevOp::DecodeChar6(Read(6))); + break; + } + } +public: + + /// getAbbrev - Return the abbreviation for the specified AbbrevId. + const BitCodeAbbrev *getAbbrev(unsigned AbbrevID) { + unsigned AbbrevNo = AbbrevID-bitc::FIRST_APPLICATION_ABBREV; + assert(AbbrevNo < CurAbbrevs.size() && "Invalid abbrev #!"); + return CurAbbrevs[AbbrevNo]; + } + + unsigned ReadRecord(unsigned AbbrevID, SmallVectorImpl &Vals, + const char **BlobStart = 0, unsigned *BlobLen = 0) { + if (AbbrevID == bitc::UNABBREV_RECORD) { + unsigned Code = ReadVBR(6); + unsigned NumElts = ReadVBR(6); + for (unsigned i = 0; i != NumElts; ++i) + Vals.push_back(ReadVBR64(6)); + return Code; + } + + const BitCodeAbbrev *Abbv = getAbbrev(AbbrevID); + + for (unsigned i = 0, e = Abbv->getNumOperandInfos(); i != e; ++i) { + const BitCodeAbbrevOp &Op = Abbv->getOperandInfo(i); + if (Op.isLiteral()) { + ReadAbbreviatedLiteral(Op, Vals); + } else if (Op.getEncoding() == BitCodeAbbrevOp::Array) { + // Array case. Read the number of elements as a vbr6. + unsigned NumElts = ReadVBR(6); + + // Get the element encoding. + assert(i+2 == e && "array op not second to last?"); + const BitCodeAbbrevOp &EltEnc = Abbv->getOperandInfo(++i); + + // Read all the elements. + for (; NumElts; --NumElts) + ReadAbbreviatedField(EltEnc, Vals); + } else if (Op.getEncoding() == BitCodeAbbrevOp::Blob) { + // Blob case. Read the number of bytes as a vbr6. + unsigned NumElts = ReadVBR(6); + SkipToWord(); // 32-bit alignment + + // Figure out where the end of this blob will be including tail padding. + const unsigned char *NewEnd = NextChar+((NumElts+3)&~3); + + // If this would read off the end of the bitcode file, just set the + // record to empty and return. + if (NewEnd > BitStream->getLastChar()) { + Vals.append(NumElts, 0); + NextChar = BitStream->getLastChar(); + break; + } + + // Otherwise, read the number of bytes. If we can return a reference to + // the data, do so to avoid copying it. + if (BlobStart) { + *BlobStart = (const char*)NextChar; + *BlobLen = NumElts; + } else { + for (; NumElts; ++NextChar, --NumElts) + Vals.push_back(*NextChar); + } + // Skip over tail padding. + NextChar = NewEnd; + } else { + ReadAbbreviatedField(Op, Vals); + } + } + + unsigned Code = (unsigned)Vals[0]; + Vals.erase(Vals.begin()); + return Code; + } + + unsigned ReadRecord(unsigned AbbrevID, SmallVectorImpl &Vals, + const char *&BlobStart, unsigned &BlobLen) { + return ReadRecord(AbbrevID, Vals, &BlobStart, &BlobLen); + } + + + //===--------------------------------------------------------------------===// + // Abbrev Processing + //===--------------------------------------------------------------------===// + + void ReadAbbrevRecord() { + BitCodeAbbrev *Abbv = new BitCodeAbbrev(); + unsigned NumOpInfo = ReadVBR(5); + for (unsigned i = 0; i != NumOpInfo; ++i) { + bool IsLiteral = Read(1) ? true : false; + if (IsLiteral) { + Abbv->Add(BitCodeAbbrevOp(ReadVBR64(8))); + continue; + } + + BitCodeAbbrevOp::Encoding E = (BitCodeAbbrevOp::Encoding)Read(3); + if (BitCodeAbbrevOp::hasEncodingData(E)) + Abbv->Add(BitCodeAbbrevOp(E, ReadVBR64(5))); + else + Abbv->Add(BitCodeAbbrevOp(E)); + } + CurAbbrevs.push_back(Abbv); + } + +public: + + bool ReadBlockInfoBlock() { + // If this is the second stream to get to the block info block, skip it. + if (BitStream->hasBlockInfoRecords()) + return SkipBlock(); + + if (EnterSubBlock(bitc::BLOCKINFO_BLOCK_ID)) return true; + + SmallVector Record; + BitstreamReader::BlockInfo *CurBlockInfo = 0; + + // Read all the records for this module. + while (1) { + unsigned Code = ReadCode(); + if (Code == bitc::END_BLOCK) + return ReadBlockEnd(); + if (Code == bitc::ENTER_SUBBLOCK) { + ReadSubBlockID(); + if (SkipBlock()) return true; + continue; + } + + // Read abbrev records, associate them with CurBID. + if (Code == bitc::DEFINE_ABBREV) { + if (!CurBlockInfo) return true; + ReadAbbrevRecord(); + + // ReadAbbrevRecord installs the abbrev in CurAbbrevs. Move it to the + // appropriate BlockInfo. + BitCodeAbbrev *Abbv = CurAbbrevs.back(); + CurAbbrevs.pop_back(); + CurBlockInfo->Abbrevs.push_back(Abbv); + continue; + } + + // Read a record. + Record.clear(); + switch (ReadRecord(Code, Record)) { + default: break; // Default behavior, ignore unknown content. + case bitc::BLOCKINFO_CODE_SETBID: + if (Record.size() < 1) return true; + CurBlockInfo = &BitStream->getOrCreateBlockInfo((unsigned)Record[0]); + break; + case bitc::BLOCKINFO_CODE_BLOCKNAME: { + if (!CurBlockInfo) return true; + if (BitStream->isIgnoringBlockInfoNames()) break; // Ignore name. + std::string Name; + for (unsigned i = 0, e = Record.size(); i != e; ++i) + Name += (char)Record[i]; + CurBlockInfo->Name = Name; + break; + } + case bitc::BLOCKINFO_CODE_SETRECORDNAME: { + if (!CurBlockInfo) return true; + if (BitStream->isIgnoringBlockInfoNames()) break; // Ignore name. + std::string Name; + for (unsigned i = 1, e = Record.size(); i != e; ++i) + Name += (char)Record[i]; + CurBlockInfo->RecordNames.push_back(std::make_pair((unsigned)Record[0], + Name)); + break; + } + } + } + } +}; + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Bitcode/BitstreamWriter.h b/libclamav/c++/llvm/include/llvm/Bitcode/BitstreamWriter.h new file mode 100644 index 000000000..2b1b85ea4 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Bitcode/BitstreamWriter.h @@ -0,0 +1,531 @@ +//===- BitstreamWriter.h - Low-level bitstream writer 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 defines the BitstreamWriter class. This class can be used to +// write an arbitrary bitstream, regardless of its contents. +// +//===----------------------------------------------------------------------===// + +#ifndef BITSTREAM_WRITER_H +#define BITSTREAM_WRITER_H + +#include "llvm/ADT/StringRef.h" +#include "llvm/Bitcode/BitCodes.h" +#include + +namespace llvm { + +class BitstreamWriter { + std::vector &Out; + + /// CurBit - Always between 0 and 31 inclusive, specifies the next bit to use. + unsigned CurBit; + + /// CurValue - The current value. Only bits < CurBit are valid. + uint32_t CurValue; + + /// CurCodeSize - This is the declared size of code values used for the + /// current block, in bits. + unsigned CurCodeSize; + + /// BlockInfoCurBID - When emitting a BLOCKINFO_BLOCK, this is the currently + /// selected BLOCK ID. + unsigned BlockInfoCurBID; + + /// CurAbbrevs - Abbrevs installed at in this block. + std::vector CurAbbrevs; + + struct Block { + unsigned PrevCodeSize; + unsigned StartSizeWord; + std::vector PrevAbbrevs; + Block(unsigned PCS, unsigned SSW) : PrevCodeSize(PCS), StartSizeWord(SSW) {} + }; + + /// BlockScope - This tracks the current blocks that we have entered. + std::vector BlockScope; + + /// BlockInfo - This contains information emitted to BLOCKINFO_BLOCK blocks. + /// These describe abbreviations that all blocks of the specified ID inherit. + struct BlockInfo { + unsigned BlockID; + std::vector Abbrevs; + }; + std::vector BlockInfoRecords; + +public: + explicit BitstreamWriter(std::vector &O) + : Out(O), CurBit(0), CurValue(0), CurCodeSize(2) {} + + ~BitstreamWriter() { + assert(CurBit == 0 && "Unflused data remaining"); + assert(BlockScope.empty() && CurAbbrevs.empty() && "Block imbalance"); + + // Free the BlockInfoRecords. + while (!BlockInfoRecords.empty()) { + BlockInfo &Info = BlockInfoRecords.back(); + // Free blockinfo abbrev info. + for (unsigned i = 0, e = static_cast(Info.Abbrevs.size()); + i != e; ++i) + Info.Abbrevs[i]->dropRef(); + BlockInfoRecords.pop_back(); + } + } + + std::vector &getBuffer() { return Out; } + + /// \brief Retrieve the current position in the stream, in bits. + uint64_t GetCurrentBitNo() const { return Out.size() * 8 + CurBit; } + + //===--------------------------------------------------------------------===// + // Basic Primitives for emitting bits to the stream. + //===--------------------------------------------------------------------===// + + void Emit(uint32_t Val, unsigned NumBits) { + assert(NumBits <= 32 && "Invalid value size!"); + assert((Val & ~(~0U >> (32-NumBits))) == 0 && "High bits set!"); + CurValue |= Val << CurBit; + if (CurBit + NumBits < 32) { + CurBit += NumBits; + return; + } + + // Add the current word. + unsigned V = CurValue; + Out.push_back((unsigned char)(V >> 0)); + Out.push_back((unsigned char)(V >> 8)); + Out.push_back((unsigned char)(V >> 16)); + Out.push_back((unsigned char)(V >> 24)); + + if (CurBit) + CurValue = Val >> (32-CurBit); + else + CurValue = 0; + CurBit = (CurBit+NumBits) & 31; + } + + void Emit64(uint64_t Val, unsigned NumBits) { + if (NumBits <= 32) + Emit((uint32_t)Val, NumBits); + else { + Emit((uint32_t)Val, 32); + Emit((uint32_t)(Val >> 32), NumBits-32); + } + } + + void FlushToWord() { + if (CurBit) { + unsigned V = CurValue; + Out.push_back((unsigned char)(V >> 0)); + Out.push_back((unsigned char)(V >> 8)); + Out.push_back((unsigned char)(V >> 16)); + Out.push_back((unsigned char)(V >> 24)); + CurBit = 0; + CurValue = 0; + } + } + + void EmitVBR(uint32_t Val, unsigned NumBits) { + uint32_t Threshold = 1U << (NumBits-1); + + // Emit the bits with VBR encoding, NumBits-1 bits at a time. + while (Val >= Threshold) { + Emit((Val & ((1 << (NumBits-1))-1)) | (1 << (NumBits-1)), NumBits); + Val >>= NumBits-1; + } + + Emit(Val, NumBits); + } + + void EmitVBR64(uint64_t Val, unsigned NumBits) { + if ((uint32_t)Val == Val) + return EmitVBR((uint32_t)Val, NumBits); + + uint64_t Threshold = 1U << (NumBits-1); + + // Emit the bits with VBR encoding, NumBits-1 bits at a time. + while (Val >= Threshold) { + Emit(((uint32_t)Val & ((1 << (NumBits-1))-1)) | + (1 << (NumBits-1)), NumBits); + Val >>= NumBits-1; + } + + Emit((uint32_t)Val, NumBits); + } + + /// EmitCode - Emit the specified code. + void EmitCode(unsigned Val) { + Emit(Val, CurCodeSize); + } + + // BackpatchWord - Backpatch a 32-bit word in the output with the specified + // value. + void BackpatchWord(unsigned ByteNo, unsigned NewWord) { + Out[ByteNo++] = (unsigned char)(NewWord >> 0); + Out[ByteNo++] = (unsigned char)(NewWord >> 8); + Out[ByteNo++] = (unsigned char)(NewWord >> 16); + Out[ByteNo ] = (unsigned char)(NewWord >> 24); + } + + //===--------------------------------------------------------------------===// + // Block Manipulation + //===--------------------------------------------------------------------===// + + /// getBlockInfo - If there is block info for the specified ID, return it, + /// otherwise return null. + BlockInfo *getBlockInfo(unsigned BlockID) { + // Common case, the most recent entry matches BlockID. + if (!BlockInfoRecords.empty() && BlockInfoRecords.back().BlockID == BlockID) + return &BlockInfoRecords.back(); + + for (unsigned i = 0, e = static_cast(BlockInfoRecords.size()); + i != e; ++i) + if (BlockInfoRecords[i].BlockID == BlockID) + return &BlockInfoRecords[i]; + return 0; + } + + void EnterSubblock(unsigned BlockID, unsigned CodeLen) { + // Block header: + // [ENTER_SUBBLOCK, blockid, newcodelen, , blocklen] + EmitCode(bitc::ENTER_SUBBLOCK); + EmitVBR(BlockID, bitc::BlockIDWidth); + EmitVBR(CodeLen, bitc::CodeLenWidth); + FlushToWord(); + + unsigned BlockSizeWordLoc = static_cast(Out.size()); + unsigned OldCodeSize = CurCodeSize; + + // Emit a placeholder, which will be replaced when the block is popped. + Emit(0, bitc::BlockSizeWidth); + + CurCodeSize = CodeLen; + + // Push the outer block's abbrev set onto the stack, start out with an + // empty abbrev set. + BlockScope.push_back(Block(OldCodeSize, BlockSizeWordLoc/4)); + BlockScope.back().PrevAbbrevs.swap(CurAbbrevs); + + // If there is a blockinfo for this BlockID, add all the predefined abbrevs + // to the abbrev list. + if (BlockInfo *Info = getBlockInfo(BlockID)) { + for (unsigned i = 0, e = static_cast(Info->Abbrevs.size()); + i != e; ++i) { + CurAbbrevs.push_back(Info->Abbrevs[i]); + Info->Abbrevs[i]->addRef(); + } + } + } + + void ExitBlock() { + assert(!BlockScope.empty() && "Block scope imbalance!"); + + // Delete all abbrevs. + for (unsigned i = 0, e = static_cast(CurAbbrevs.size()); + i != e; ++i) + CurAbbrevs[i]->dropRef(); + + const Block &B = BlockScope.back(); + + // Block tail: + // [END_BLOCK, ] + EmitCode(bitc::END_BLOCK); + FlushToWord(); + + // Compute the size of the block, in words, not counting the size field. + unsigned SizeInWords= static_cast(Out.size())/4-B.StartSizeWord-1; + unsigned ByteNo = B.StartSizeWord*4; + + // Update the block size field in the header of this sub-block. + BackpatchWord(ByteNo, SizeInWords); + + // Restore the inner block's code size and abbrev table. + CurCodeSize = B.PrevCodeSize; + BlockScope.back().PrevAbbrevs.swap(CurAbbrevs); + BlockScope.pop_back(); + } + + //===--------------------------------------------------------------------===// + // Record Emission + //===--------------------------------------------------------------------===// + +private: + /// EmitAbbreviatedLiteral - Emit a literal value according to its abbrev + /// record. This is a no-op, since the abbrev specifies the literal to use. + template + void EmitAbbreviatedLiteral(const BitCodeAbbrevOp &Op, uintty V) { + assert(Op.isLiteral() && "Not a literal"); + // If the abbrev specifies the literal value to use, don't emit + // anything. + assert(V == Op.getLiteralValue() && + "Invalid abbrev for record!"); + } + + /// EmitAbbreviatedField - Emit a single scalar field value with the specified + /// encoding. + template + void EmitAbbreviatedField(const BitCodeAbbrevOp &Op, uintty V) { + assert(!Op.isLiteral() && "Literals should use EmitAbbreviatedLiteral!"); + + // Encode the value as we are commanded. + switch (Op.getEncoding()) { + default: assert(0 && "Unknown encoding!"); + case BitCodeAbbrevOp::Fixed: + Emit((unsigned)V, (unsigned)Op.getEncodingData()); + break; + case BitCodeAbbrevOp::VBR: + EmitVBR64(V, (unsigned)Op.getEncodingData()); + break; + case BitCodeAbbrevOp::Char6: + Emit(BitCodeAbbrevOp::EncodeChar6((char)V), 6); + break; + } + } + + /// EmitRecordWithAbbrevImpl - This is the core implementation of the record + /// emission code. If BlobData is non-null, then it specifies an array of + /// data that should be emitted as part of the Blob or Array operand that is + /// known to exist at the end of the the record. + template + void EmitRecordWithAbbrevImpl(unsigned Abbrev, SmallVectorImpl &Vals, + StringRef Blob) { + const char *BlobData = Blob.data(); + unsigned BlobLen = (unsigned) Blob.size(); + unsigned AbbrevNo = Abbrev-bitc::FIRST_APPLICATION_ABBREV; + assert(AbbrevNo < CurAbbrevs.size() && "Invalid abbrev #!"); + BitCodeAbbrev *Abbv = CurAbbrevs[AbbrevNo]; + + EmitCode(Abbrev); + + unsigned RecordIdx = 0; + for (unsigned i = 0, e = static_cast(Abbv->getNumOperandInfos()); + i != e; ++i) { + const BitCodeAbbrevOp &Op = Abbv->getOperandInfo(i); + if (Op.isLiteral()) { + assert(RecordIdx < Vals.size() && "Invalid abbrev/record"); + EmitAbbreviatedLiteral(Op, Vals[RecordIdx]); + ++RecordIdx; + } else if (Op.getEncoding() == BitCodeAbbrevOp::Array) { + // Array case. + assert(i+2 == e && "array op not second to last?"); + const BitCodeAbbrevOp &EltEnc = Abbv->getOperandInfo(++i); + + // If this record has blob data, emit it, otherwise we must have record + // entries to encode this way. + if (BlobData) { + assert(RecordIdx == Vals.size() && + "Blob data and record entries specified for array!"); + // Emit a vbr6 to indicate the number of elements present. + EmitVBR(static_cast(BlobLen), 6); + + // Emit each field. + for (unsigned i = 0; i != BlobLen; ++i) + EmitAbbreviatedField(EltEnc, (unsigned char)BlobData[i]); + + // Know that blob data is consumed for assertion below. + BlobData = 0; + } else { + // Emit a vbr6 to indicate the number of elements present. + EmitVBR(static_cast(Vals.size()-RecordIdx), 6); + + // Emit each field. + for (unsigned e = Vals.size(); RecordIdx != e; ++RecordIdx) + EmitAbbreviatedField(EltEnc, Vals[RecordIdx]); + } + } else if (Op.getEncoding() == BitCodeAbbrevOp::Blob) { + // If this record has blob data, emit it, otherwise we must have record + // entries to encode this way. + + // Emit a vbr6 to indicate the number of elements present. + if (BlobData) { + EmitVBR(static_cast(BlobLen), 6); + assert(RecordIdx == Vals.size() && + "Blob data and record entries specified for blob operand!"); + } else { + EmitVBR(static_cast(Vals.size()-RecordIdx), 6); + } + + // Flush to a 32-bit alignment boundary. + FlushToWord(); + assert((Out.size() & 3) == 0 && "Not 32-bit aligned"); + + // Emit each field as a literal byte. + if (BlobData) { + for (unsigned i = 0; i != BlobLen; ++i) + Out.push_back((unsigned char)BlobData[i]); + + // Know that blob data is consumed for assertion below. + BlobData = 0; + } else { + for (unsigned e = Vals.size(); RecordIdx != e; ++RecordIdx) { + assert(Vals[RecordIdx] < 256 && "Value too large to emit as blob"); + Out.push_back((unsigned char)Vals[RecordIdx]); + } + } + // Align end to 32-bits. + while (Out.size() & 3) + Out.push_back(0); + + } else { // Single scalar field. + assert(RecordIdx < Vals.size() && "Invalid abbrev/record"); + EmitAbbreviatedField(Op, Vals[RecordIdx]); + ++RecordIdx; + } + } + assert(RecordIdx == Vals.size() && "Not all record operands emitted!"); + assert(BlobData == 0 && + "Blob data specified for record that doesn't use it!"); + } + +public: + + /// EmitRecord - Emit the specified record to the stream, using an abbrev if + /// we have one to compress the output. + template + void EmitRecord(unsigned Code, SmallVectorImpl &Vals, + unsigned Abbrev = 0) { + if (!Abbrev) { + // If we don't have an abbrev to use, emit this in its fully unabbreviated + // form. + EmitCode(bitc::UNABBREV_RECORD); + EmitVBR(Code, 6); + EmitVBR(static_cast(Vals.size()), 6); + for (unsigned i = 0, e = static_cast(Vals.size()); i != e; ++i) + EmitVBR64(Vals[i], 6); + return; + } + + // Insert the code into Vals to treat it uniformly. + Vals.insert(Vals.begin(), Code); + + EmitRecordWithAbbrev(Abbrev, Vals); + } + + /// EmitRecordWithAbbrev - Emit a record with the specified abbreviation. + /// Unlike EmitRecord, the code for the record should be included in Vals as + /// the first entry. + template + void EmitRecordWithAbbrev(unsigned Abbrev, SmallVectorImpl &Vals) { + EmitRecordWithAbbrevImpl(Abbrev, Vals, StringRef()); + } + + /// EmitRecordWithBlob - Emit the specified record to the stream, using an + /// abbrev that includes a blob at the end. The blob data to emit is + /// specified by the pointer and length specified at the end. In contrast to + /// EmitRecord, this routine expects that the first entry in Vals is the code + /// of the record. + template + void EmitRecordWithBlob(unsigned Abbrev, SmallVectorImpl &Vals, + StringRef Blob) { + EmitRecordWithAbbrevImpl(Abbrev, Vals, Blob); + } + template + void EmitRecordWithBlob(unsigned Abbrev, SmallVectorImpl &Vals, + const char *BlobData, unsigned BlobLen) { + return EmitRecordWithAbbrevImpl(Abbrev, Vals, StringRef(BlobData, BlobLen)); + } + + /// EmitRecordWithArray - Just like EmitRecordWithBlob, works with records + /// that end with an array. + template + void EmitRecordWithArray(unsigned Abbrev, SmallVectorImpl &Vals, + StringRef Array) { + EmitRecordWithAbbrevImpl(Abbrev, Vals, Array); + } + template + void EmitRecordWithArray(unsigned Abbrev, SmallVectorImpl &Vals, + const char *ArrayData, unsigned ArrayLen) { + return EmitRecordWithAbbrevImpl(Abbrev, Vals, StringRef(ArrayData, + ArrayLen)); + } + + //===--------------------------------------------------------------------===// + // Abbrev Emission + //===--------------------------------------------------------------------===// + +private: + // Emit the abbreviation as a DEFINE_ABBREV record. + void EncodeAbbrev(BitCodeAbbrev *Abbv) { + EmitCode(bitc::DEFINE_ABBREV); + EmitVBR(Abbv->getNumOperandInfos(), 5); + for (unsigned i = 0, e = static_cast(Abbv->getNumOperandInfos()); + i != e; ++i) { + const BitCodeAbbrevOp &Op = Abbv->getOperandInfo(i); + Emit(Op.isLiteral(), 1); + if (Op.isLiteral()) { + EmitVBR64(Op.getLiteralValue(), 8); + } else { + Emit(Op.getEncoding(), 3); + if (Op.hasEncodingData()) + EmitVBR64(Op.getEncodingData(), 5); + } + } + } +public: + + /// EmitAbbrev - This emits an abbreviation to the stream. Note that this + /// method takes ownership of the specified abbrev. + unsigned EmitAbbrev(BitCodeAbbrev *Abbv) { + // Emit the abbreviation as a record. + EncodeAbbrev(Abbv); + CurAbbrevs.push_back(Abbv); + return static_cast(CurAbbrevs.size())-1 + + bitc::FIRST_APPLICATION_ABBREV; + } + + //===--------------------------------------------------------------------===// + // BlockInfo Block Emission + //===--------------------------------------------------------------------===// + + /// EnterBlockInfoBlock - Start emitting the BLOCKINFO_BLOCK. + void EnterBlockInfoBlock(unsigned CodeWidth) { + EnterSubblock(bitc::BLOCKINFO_BLOCK_ID, CodeWidth); + BlockInfoCurBID = -1U; + } +private: + /// SwitchToBlockID - If we aren't already talking about the specified block + /// ID, emit a BLOCKINFO_CODE_SETBID record. + void SwitchToBlockID(unsigned BlockID) { + if (BlockInfoCurBID == BlockID) return; + SmallVector V; + V.push_back(BlockID); + EmitRecord(bitc::BLOCKINFO_CODE_SETBID, V); + BlockInfoCurBID = BlockID; + } + + BlockInfo &getOrCreateBlockInfo(unsigned BlockID) { + if (BlockInfo *BI = getBlockInfo(BlockID)) + return *BI; + + // Otherwise, add a new record. + BlockInfoRecords.push_back(BlockInfo()); + BlockInfoRecords.back().BlockID = BlockID; + return BlockInfoRecords.back(); + } + +public: + + /// EmitBlockInfoAbbrev - Emit a DEFINE_ABBREV record for the specified + /// BlockID. + unsigned EmitBlockInfoAbbrev(unsigned BlockID, BitCodeAbbrev *Abbv) { + SwitchToBlockID(BlockID); + EncodeAbbrev(Abbv); + + // Add the abbrev to the specified block record. + BlockInfo &Info = getOrCreateBlockInfo(BlockID); + Info.Abbrevs.push_back(Abbv); + + return Info.Abbrevs.size()-1+bitc::FIRST_APPLICATION_ABBREV; + } +}; + + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Bitcode/Deserialize.h b/libclamav/c++/llvm/include/llvm/Bitcode/Deserialize.h new file mode 100644 index 000000000..90a51417d --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Bitcode/Deserialize.h @@ -0,0 +1,517 @@ +//=- Deserialize.h - Generic Object Deserialization from Bitcode --*- 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 the interface for generic object deserialization from +// LLVM bitcode. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_BITCODE_SERIALIZE_INPUT +#define LLVM_BITCODE_SERIALIZE_INPUT + +#include "llvm/Bitcode/BitstreamReader.h" +#include "llvm/Bitcode/Serialization.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/Allocator.h" +#include "llvm/System/DataTypes.h" +#include + +namespace llvm { + +class Deserializer { + + //===----------------------------------------------------------===// + // Internal type definitions. + //===----------------------------------------------------------===// + + struct BPNode { + BPNode* Next; + uintptr_t& PtrRef; + + BPNode(BPNode* n, uintptr_t& pref) + : Next(n), PtrRef(pref) { + PtrRef = 0; + } + }; + + struct BPEntry { + union { BPNode* Head; void* Ptr; }; + + BPEntry() : Head(NULL) {} + + static inline bool isPod() { return true; } + + void SetPtr(BPNode*& FreeList, void* P); + }; + + class BPKey { + unsigned Raw; + + public: + BPKey(SerializedPtrID PtrId) : Raw(PtrId << 1) { assert (PtrId > 0); } + BPKey(unsigned code, unsigned) : Raw(code) {} + + void MarkFinal() { Raw |= 0x1; } + bool hasFinalPtr() const { return Raw & 0x1 ? true : false; } + SerializedPtrID getID() const { return Raw >> 1; } + + static inline BPKey getEmptyKey() { return BPKey(0,0); } + static inline BPKey getTombstoneKey() { return BPKey(1,0); } + static inline unsigned getHashValue(const BPKey& K) { return K.Raw & ~0x1; } + + static bool isEqual(const BPKey& K1, const BPKey& K2) { + return (K1.Raw ^ K2.Raw) & ~0x1 ? false : true; + } + + static bool isPod() { return true; } + }; + + typedef llvm::DenseMap MapTy; + + //===----------------------------------------------------------===// + // Publicly visible types. + //===----------------------------------------------------------===// + +public: + struct Location { + uint64_t BitNo; + unsigned BlockID; + unsigned NumWords; + + Location(uint64_t bit, unsigned bid, unsigned words) + : BitNo(bit), BlockID(bid), NumWords(words) {} + + Location() : BitNo(0), BlockID(0), NumWords(0) {} + + Location& operator=(Location& RHS) { + BitNo = RHS.BitNo; + BlockID = RHS.BlockID; + NumWords = RHS.NumWords; + return *this; + } + + bool operator==(const Location& RHS) const { return BitNo == RHS.BitNo; } + bool operator!=(const Location& RHS) const { return BitNo != RHS.BitNo; } + + bool contains(const Location& RHS) const { + if (RHS.BitNo < BitNo) + return false; + + if ((RHS.BitNo - BitNo) >> 5 < NumWords) + return true; + + return false; + } + }; + + //===----------------------------------------------------------===// + // Internal data members. + //===----------------------------------------------------------===// + +private: + BitstreamCursor Stream; + SmallVector Record; + unsigned RecIdx; + BumpPtrAllocator Allocator; + BPNode* FreeList; + MapTy BPatchMap; + llvm::SmallVector BlockStack; + unsigned AbbrevNo; + unsigned RecordCode; + uint64_t StreamStart; + + //===----------------------------------------------------------===// + // Public Interface. + //===----------------------------------------------------------===// + +public: + Deserializer(BitstreamReader& stream); + ~Deserializer(); + + uint64_t ReadInt(); + int64_t ReadSInt(); + SerializedPtrID ReadPtrID() { return (SerializedPtrID) ReadInt(); } + + + bool ReadBool() { + return ReadInt() ? true : false; + } + + template + inline T& Read(T& X) { + SerializeTrait::Read(*this,X); + return X; + } + + template + inline T* Create() { + return SerializeTrait::Create(*this); + } + + char* ReadCStr(char* cstr = NULL, unsigned MaxLen=0, bool isNullTerm=true); + void ReadCStr(std::vector& buff, bool isNullTerm=false, unsigned Idx=0); + + template + inline T* ReadOwnedPtr(bool AutoRegister = true) { + SerializedPtrID PtrID = ReadPtrID(); + + if (!PtrID) + return NULL; + + T* x = SerializeTrait::Create(*this); + + if (AutoRegister) + RegisterPtr(PtrID,x); + + return x; + } + + template + inline T* ReadOwnedPtr(Arg1& arg1, bool AutoRegister = true) { + SerializedPtrID PtrID = ReadPtrID(); + + if (!PtrID) + return NULL; + + T* x = SerializeTrait::Create(*this, arg1); + + if (AutoRegister) + RegisterPtr(PtrID,x); + + return x; + } + + template + inline void ReadOwnedPtr(T*& Ptr, bool AutoRegister = true) { + Ptr = ReadOwnedPtr(AutoRegister); + } + + template + void BatchReadOwnedPtrs(T1*& P1, T2*& P2, + bool A1=true, bool A2=true) { + + SerializedPtrID ID1 = ReadPtrID(); + SerializedPtrID ID2 = ReadPtrID(); + + P1 = (ID1) ? SerializeTrait::Create(*this) : NULL; + if (ID1 && A1) RegisterPtr(ID1,P1); + + P2 = (ID2) ? SerializeTrait::Create(*this) : NULL; + if (ID2 && A2) RegisterPtr(ID2,P2); + } + + template + void BatchReadOwnedPtrs(T1*& P1, T2*& P2, Arg1& arg1, + bool A1=true, bool A2=true) { + + SerializedPtrID ID1 = ReadPtrID(); + SerializedPtrID ID2 = ReadPtrID(); + + P1 = (ID1) ? SerializeTrait::Create(*this, arg1) : NULL; + if (ID1 && A1) RegisterPtr(ID1,P1); + + P2 = (ID2) ? SerializeTrait::Create(*this, arg1) : NULL; + if (ID2 && A2) RegisterPtr(ID2,P2); + } + + template + void BatchReadOwnedPtrs(T1*& P1, T2*& P2, T3*& P3, + bool A1=true, bool A2=true, bool A3=true) { + + SerializedPtrID ID1 = ReadPtrID(); + SerializedPtrID ID2 = ReadPtrID(); + SerializedPtrID ID3 = ReadPtrID(); + + P1 = (ID1) ? SerializeTrait::Create(*this) : NULL; + if (ID1 && A1) RegisterPtr(ID1,P1); + + P2 = (ID2) ? SerializeTrait::Create(*this) : NULL; + if (ID2 && A2) RegisterPtr(ID2,P2); + + P3 = (ID3) ? SerializeTrait::Create(*this) : NULL; + if (ID3 && A3) RegisterPtr(ID3,P3); + } + + template + void BatchReadOwnedPtrs(T1*& P1, T2*& P2, T3*& P3, Arg1& arg1, + bool A1=true, bool A2=true, bool A3=true) { + + SerializedPtrID ID1 = ReadPtrID(); + SerializedPtrID ID2 = ReadPtrID(); + SerializedPtrID ID3 = ReadPtrID(); + + P1 = (ID1) ? SerializeTrait::Create(*this, arg1) : NULL; + if (ID1 && A1) RegisterPtr(ID1,P1); + + P2 = (ID2) ? SerializeTrait::Create(*this, arg1) : NULL; + if (ID2 && A2) RegisterPtr(ID2,P2); + + P3 = (ID3) ? SerializeTrait::Create(*this, arg1) : NULL; + if (ID3 && A3) RegisterPtr(ID3,P3); + } + + template + void BatchReadOwnedPtrs(unsigned NumPtrs, T** Ptrs, bool AutoRegister=true) { + llvm::SmallVector BatchIDVec; + + for (unsigned i = 0; i < NumPtrs; ++i) + BatchIDVec.push_back(ReadPtrID()); + + for (unsigned i = 0; i < NumPtrs; ++i) { + SerializedPtrID& PtrID = BatchIDVec[i]; + + T* p = PtrID ? SerializeTrait::Create(*this) : NULL; + + if (PtrID && AutoRegister) + RegisterPtr(PtrID,p); + + Ptrs[i] = p; + } + } + + template + void BatchReadOwnedPtrs(unsigned NumPtrs, T** Ptrs, Arg1& arg1, + bool AutoRegister=true) { + + llvm::SmallVector BatchIDVec; + + for (unsigned i = 0; i < NumPtrs; ++i) + BatchIDVec.push_back(ReadPtrID()); + + for (unsigned i = 0; i < NumPtrs; ++i) { + SerializedPtrID& PtrID = BatchIDVec[i]; + + T* p = PtrID ? SerializeTrait::Create(*this, arg1) : NULL; + + if (PtrID && AutoRegister) + RegisterPtr(PtrID,p); + + Ptrs[i] = p; + } + } + + template + void BatchReadOwnedPtrs(unsigned NumT1Ptrs, T1** Ptrs, T2*& P2, + bool A1=true, bool A2=true) { + + llvm::SmallVector BatchIDVec; + + for (unsigned i = 0; i < NumT1Ptrs; ++i) + BatchIDVec.push_back(ReadPtrID()); + + SerializedPtrID ID2 = ReadPtrID(); + + for (unsigned i = 0; i < NumT1Ptrs; ++i) { + SerializedPtrID& PtrID = BatchIDVec[i]; + + T1* p = PtrID ? SerializeTrait::Create(*this) : NULL; + + if (PtrID && A1) + RegisterPtr(PtrID,p); + + Ptrs[i] = p; + } + + P2 = (ID2) ? SerializeTrait::Create(*this) : NULL; + if (ID2 && A2) RegisterPtr(ID2,P2); + } + + template + void BatchReadOwnedPtrs(unsigned NumT1Ptrs, T1** Ptrs, T2*& P2, Arg1& arg1, + bool A1=true, bool A2=true) { + + llvm::SmallVector BatchIDVec; + + for (unsigned i = 0; i < NumT1Ptrs; ++i) + BatchIDVec.push_back(ReadPtrID()); + + SerializedPtrID ID2 = ReadPtrID(); + + for (unsigned i = 0; i < NumT1Ptrs; ++i) { + SerializedPtrID& PtrID = BatchIDVec[i]; + + T1* p = PtrID ? SerializeTrait::Create(*this, arg1) : NULL; + + if (PtrID && A1) + RegisterPtr(PtrID,p); + + Ptrs[i] = p; + } + + P2 = (ID2) ? SerializeTrait::Create(*this, arg1) : NULL; + if (ID2 && A2) RegisterPtr(ID2,P2); + } + + template + void BatchReadOwnedPtrs(unsigned NumT1Ptrs, T1** Ptrs, + T2*& P2, T3*& P3, + bool A1=true, bool A2=true, bool A3=true) { + + llvm::SmallVector BatchIDVec; + + for (unsigned i = 0; i < NumT1Ptrs; ++i) + BatchIDVec.push_back(ReadPtrID()); + + SerializedPtrID ID2 = ReadPtrID(); + SerializedPtrID ID3 = ReadPtrID(); + + for (unsigned i = 0; i < NumT1Ptrs; ++i) { + SerializedPtrID& PtrID = BatchIDVec[i]; + + T1* p = PtrID ? SerializeTrait::Create(*this) : NULL; + + if (PtrID && A1) + RegisterPtr(PtrID,p); + + Ptrs[i] = p; + } + + P2 = (ID2) ? SerializeTrait::Create(*this) : NULL; + if (ID2 && A2) RegisterPtr(ID2,P2); + + P3 = (ID3) ? SerializeTrait::Create(*this) : NULL; + if (ID3 && A3) RegisterPtr(ID3,P3); + } + + template + void BatchReadOwnedPtrs(unsigned NumT1Ptrs, T1** Ptrs, + T2*& P2, T3*& P3, Arg1& arg1, + bool A1=true, bool A2=true, bool A3=true) { + + llvm::SmallVector BatchIDVec; + + for (unsigned i = 0; i < NumT1Ptrs; ++i) + BatchIDVec.push_back(ReadPtrID()); + + SerializedPtrID ID2 = ReadPtrID(); + SerializedPtrID ID3 = ReadPtrID(); + + for (unsigned i = 0; i < NumT1Ptrs; ++i) { + SerializedPtrID& PtrID = BatchIDVec[i]; + + T1* p = PtrID ? SerializeTrait::Create(*this, arg1) : NULL; + + if (PtrID && A1) + RegisterPtr(PtrID,p); + + Ptrs[i] = p; + } + + P2 = (ID2) ? SerializeTrait::Create(*this, arg1) : NULL; + if (ID2 && A2) RegisterPtr(ID2,P2); + + P3 = (ID3) ? SerializeTrait::Create(*this, arg1) : NULL; + if (ID3 && A3) RegisterPtr(ID3,P3); + } + + template + void ReadPtr(T*& PtrRef, bool AllowBackpatch = true) { + ReadUIntPtr(reinterpret_cast(PtrRef), AllowBackpatch); + } + + template + void ReadPtr(const T*& PtrRef, bool AllowBackpatch = true) { + ReadPtr(const_cast(PtrRef), AllowBackpatch); + } + + + template + void ReadPtr(T*& PtrRef, const SerializedPtrID& PtrID, + bool AllowBackpatch = true) { + ReadUIntPtr(reinterpret_cast(PtrRef), PtrID, AllowBackpatch); + } + + template + void ReadPtr(const T*& PtrRef, const SerializedPtrID& PtrID, + bool AllowBackpatch = true) { + + ReadPtr(const_cast(PtrRef), PtrID, AllowBackpatch); + } + + template + T* ReadPtr() { T* x = 0; ReadPtr(x,false); return x; } + + void ReadUIntPtr(uintptr_t& PtrRef, const SerializedPtrID& PtrID, + bool AllowBackpatch = true); + + void ReadUIntPtr(uintptr_t& PtrRef, bool AllowBackpatch = true) { + ReadUIntPtr(PtrRef,ReadPtrID(),AllowBackpatch); + } + + template + T& ReadRef() { + T* p = reinterpret_cast(ReadInternalRefPtr()); + return *p; + } + + void RegisterPtr(const SerializedPtrID& PtrID, const void* Ptr); + + void RegisterPtr(const void* Ptr) { + RegisterPtr(ReadPtrID(),Ptr); + } + + template + void RegisterRef(const T& x) { + RegisterPtr(&x); + } + + template + void RegisterRef(const SerializedPtrID& PtrID, const T& x) { + RegisterPtr(PtrID,&x); + } + + Location getCurrentBlockLocation(); + unsigned getCurrentBlockID(); + unsigned getAbbrevNo(); + + bool FinishedBlock(Location BlockLoc); + bool JumpTo(const Location& BlockLoc); + void Rewind(); + + bool AtEnd(); + bool inRecord(); + void SkipBlock(); + bool SkipToBlock(unsigned BlockID); + + unsigned getRecordCode(); + + BitstreamCursor &getStream() { return Stream; } + +private: + bool AdvanceStream(); + void ReadRecord(); + + uintptr_t ReadInternalRefPtr(); + + static inline bool HasFinalPtr(MapTy::value_type& V) { + return V.first.hasFinalPtr(); + } + + static inline uintptr_t GetFinalPtr(MapTy::value_type& V) { + return reinterpret_cast(V.second.Ptr); + } + + static inline BPNode* GetBPNode(MapTy::value_type& V) { + return V.second.Head; + } + + static inline void SetBPNode(MapTy::value_type& V, BPNode* N) { + V.second.Head = N; + } + + void SetPtr(MapTy::value_type& V, const void* P) { + V.first.MarkFinal(); + V.second.SetPtr(FreeList,const_cast(P)); + } +}; + +} // end namespace llvm + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Bitcode/LLVMBitCodes.h b/libclamav/c++/llvm/include/llvm/Bitcode/LLVMBitCodes.h new file mode 100644 index 000000000..c037399b9 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Bitcode/LLVMBitCodes.h @@ -0,0 +1,246 @@ +//===- LLVMBitCodes.h - Enum values for the LLVM bitcode format -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This header defines Bitcode enum values for LLVM IR bitcode files. +// +// The enum values defined in this file should be considered permanent. If +// new features are added, they should have values added at the end of the +// respective lists. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_BITCODE_LLVMBITCODES_H +#define LLVM_BITCODE_LLVMBITCODES_H + +#include "llvm/Bitcode/BitCodes.h" + +namespace llvm { +namespace bitc { + // The only top-level block type defined is for a module. + enum BlockIDs { + // Blocks + MODULE_BLOCK_ID = FIRST_APPLICATION_BLOCKID, + + // Module sub-block id's. + PARAMATTR_BLOCK_ID, + TYPE_BLOCK_ID, + CONSTANTS_BLOCK_ID, + FUNCTION_BLOCK_ID, + TYPE_SYMTAB_BLOCK_ID, + VALUE_SYMTAB_BLOCK_ID, + METADATA_BLOCK_ID, + METADATA_ATTACHMENT_ID + }; + + + /// MODULE blocks have a number of optional fields and subblocks. + enum ModuleCodes { + MODULE_CODE_VERSION = 1, // VERSION: [version#] + MODULE_CODE_TRIPLE = 2, // TRIPLE: [strchr x N] + MODULE_CODE_DATALAYOUT = 3, // DATALAYOUT: [strchr x N] + MODULE_CODE_ASM = 4, // ASM: [strchr x N] + MODULE_CODE_SECTIONNAME = 5, // SECTIONNAME: [strchr x N] + MODULE_CODE_DEPLIB = 6, // DEPLIB: [strchr x N] + + // GLOBALVAR: [pointer type, isconst, initid, + // linkage, alignment, section, visibility, threadlocal] + MODULE_CODE_GLOBALVAR = 7, + + // FUNCTION: [type, callingconv, isproto, linkage, paramattrs, alignment, + // section, visibility] + MODULE_CODE_FUNCTION = 8, + + // ALIAS: [alias type, aliasee val#, linkage] + MODULE_CODE_ALIAS = 9, + + /// MODULE_CODE_PURGEVALS: [numvals] + MODULE_CODE_PURGEVALS = 10, + + MODULE_CODE_GCNAME = 11 // GCNAME: [strchr x N] + }; + + /// PARAMATTR blocks have code for defining a parameter attribute set. + enum AttributeCodes { + PARAMATTR_CODE_ENTRY = 1 // ENTRY: [paramidx0, attr0, paramidx1, attr1...] + }; + + /// TYPE blocks have codes for each type primitive they use. + enum TypeCodes { + TYPE_CODE_NUMENTRY = 1, // NUMENTRY: [numentries] + + // Type Codes + TYPE_CODE_VOID = 2, // VOID + TYPE_CODE_FLOAT = 3, // FLOAT + TYPE_CODE_DOUBLE = 4, // DOUBLE + TYPE_CODE_LABEL = 5, // LABEL + TYPE_CODE_OPAQUE = 6, // OPAQUE + TYPE_CODE_INTEGER = 7, // INTEGER: [width] + TYPE_CODE_POINTER = 8, // POINTER: [pointee type] + TYPE_CODE_FUNCTION = 9, // FUNCTION: [vararg, retty, paramty x N] + TYPE_CODE_STRUCT = 10, // STRUCT: [ispacked, eltty x N] + TYPE_CODE_ARRAY = 11, // ARRAY: [numelts, eltty] + TYPE_CODE_VECTOR = 12, // VECTOR: [numelts, eltty] + + // These are not with the other floating point types because they're + // a late addition, and putting them in the right place breaks + // binary compatibility. + TYPE_CODE_X86_FP80 = 13, // X86 LONG DOUBLE + TYPE_CODE_FP128 = 14, // LONG DOUBLE (112 bit mantissa) + TYPE_CODE_PPC_FP128= 15, // PPC LONG DOUBLE (2 doubles) + + TYPE_CODE_METADATA = 16 // METADATA + }; + + // The type symbol table only has one code (TST_ENTRY_CODE). + enum TypeSymtabCodes { + TST_CODE_ENTRY = 1 // TST_ENTRY: [typeid, namechar x N] + }; + + // The value symbol table only has one code (VST_ENTRY_CODE). + enum ValueSymtabCodes { + VST_CODE_ENTRY = 1, // VST_ENTRY: [valid, namechar x N] + VST_CODE_BBENTRY = 2 // VST_BBENTRY: [bbid, namechar x N] + }; + + enum MetadataCodes { + METADATA_STRING = 1, // MDSTRING: [values] + METADATA_NODE = 2, // MDNODE: [n x (type num, value num)] + METADATA_NAME = 3, // STRING: [values] + METADATA_NAMED_NODE = 4, // NAMEDMDNODE: [n x mdnodes] + METADATA_KIND = 5, // [n x [id, name]] + METADATA_ATTACHMENT = 6 // [m x [value, [n x [id, mdnode]]] + }; + // The constants block (CONSTANTS_BLOCK_ID) describes emission for each + // constant and maintains an implicit current type value. + enum ConstantsCodes { + CST_CODE_SETTYPE = 1, // SETTYPE: [typeid] + CST_CODE_NULL = 2, // NULL + CST_CODE_UNDEF = 3, // UNDEF + CST_CODE_INTEGER = 4, // INTEGER: [intval] + CST_CODE_WIDE_INTEGER = 5, // WIDE_INTEGER: [n x intval] + CST_CODE_FLOAT = 6, // FLOAT: [fpval] + CST_CODE_AGGREGATE = 7, // AGGREGATE: [n x value number] + CST_CODE_STRING = 8, // STRING: [values] + CST_CODE_CSTRING = 9, // CSTRING: [values] + CST_CODE_CE_BINOP = 10, // CE_BINOP: [opcode, opval, opval] + CST_CODE_CE_CAST = 11, // CE_CAST: [opcode, opty, opval] + CST_CODE_CE_GEP = 12, // CE_GEP: [n x operands] + CST_CODE_CE_SELECT = 13, // CE_SELECT: [opval, opval, opval] + CST_CODE_CE_EXTRACTELT = 14, // CE_EXTRACTELT: [opty, opval, opval] + CST_CODE_CE_INSERTELT = 15, // CE_INSERTELT: [opval, opval, opval] + CST_CODE_CE_SHUFFLEVEC = 16, // CE_SHUFFLEVEC: [opval, opval, opval] + CST_CODE_CE_CMP = 17, // CE_CMP: [opty, opval, opval, pred] + CST_CODE_INLINEASM = 18, // INLINEASM: [sideeffect,asmstr,conststr] + CST_CODE_CE_SHUFVEC_EX = 19, // SHUFVEC_EX: [opty, opval, opval, opval] + CST_CODE_CE_INBOUNDS_GEP = 20,// INBOUNDS_GEP: [n x operands] + CST_CODE_BLOCKADDRESS = 21 // CST_CODE_BLOCKADDRESS [fnty, fnval, bb#] + }; + + /// CastOpcodes - These are values used in the bitcode files to encode which + /// cast a CST_CODE_CE_CAST or a XXX refers to. The values of these enums + /// have no fixed relation to the LLVM IR enum values. Changing these will + /// break compatibility with old files. + enum CastOpcodes { + CAST_TRUNC = 0, + CAST_ZEXT = 1, + CAST_SEXT = 2, + CAST_FPTOUI = 3, + CAST_FPTOSI = 4, + CAST_UITOFP = 5, + CAST_SITOFP = 6, + CAST_FPTRUNC = 7, + CAST_FPEXT = 8, + CAST_PTRTOINT = 9, + CAST_INTTOPTR = 10, + CAST_BITCAST = 11 + }; + + /// BinaryOpcodes - These are values used in the bitcode files to encode which + /// binop a CST_CODE_CE_BINOP or a XXX refers to. The values of these enums + /// have no fixed relation to the LLVM IR enum values. Changing these will + /// break compatibility with old files. + enum BinaryOpcodes { + BINOP_ADD = 0, + BINOP_SUB = 1, + BINOP_MUL = 2, + BINOP_UDIV = 3, + BINOP_SDIV = 4, // overloaded for FP + BINOP_UREM = 5, + BINOP_SREM = 6, // overloaded for FP + BINOP_SHL = 7, + BINOP_LSHR = 8, + BINOP_ASHR = 9, + BINOP_AND = 10, + BINOP_OR = 11, + BINOP_XOR = 12 + }; + + /// OverflowingBinaryOperatorOptionalFlags - Flags for serializing + /// OverflowingBinaryOperator's SubclassOptionalData contents. + enum OverflowingBinaryOperatorOptionalFlags { + OBO_NO_UNSIGNED_WRAP = 0, + OBO_NO_SIGNED_WRAP = 1 + }; + + /// SDivOperatorOptionalFlags - Flags for serializing SDivOperator's + /// SubclassOptionalData contents. + enum SDivOperatorOptionalFlags { + SDIV_EXACT = 0 + }; + + // The function body block (FUNCTION_BLOCK_ID) describes function bodies. It + // can contain a constant block (CONSTANTS_BLOCK_ID). + enum FunctionCodes { + FUNC_CODE_DECLAREBLOCKS = 1, // DECLAREBLOCKS: [n] + + FUNC_CODE_INST_BINOP = 2, // BINOP: [opcode, ty, opval, opval] + FUNC_CODE_INST_CAST = 3, // CAST: [opcode, ty, opty, opval] + FUNC_CODE_INST_GEP = 4, // GEP: [n x operands] + FUNC_CODE_INST_SELECT = 5, // SELECT: [ty, opval, opval, opval] + FUNC_CODE_INST_EXTRACTELT = 6, // EXTRACTELT: [opty, opval, opval] + FUNC_CODE_INST_INSERTELT = 7, // INSERTELT: [ty, opval, opval, opval] + FUNC_CODE_INST_SHUFFLEVEC = 8, // SHUFFLEVEC: [ty, opval, opval, opval] + FUNC_CODE_INST_CMP = 9, // CMP: [opty, opval, opval, pred] + + FUNC_CODE_INST_RET = 10, // RET: [opty,opval] + FUNC_CODE_INST_BR = 11, // BR: [bb#, bb#, cond] or [bb#] + FUNC_CODE_INST_SWITCH = 12, // SWITCH: [opty, op0, op1, ...] + FUNC_CODE_INST_INVOKE = 13, // INVOKE: [attr, fnty, op0,op1, ...] + FUNC_CODE_INST_UNWIND = 14, // UNWIND + FUNC_CODE_INST_UNREACHABLE = 15, // UNREACHABLE + + FUNC_CODE_INST_PHI = 16, // PHI: [ty, val0,bb0, ...] + FUNC_CODE_INST_MALLOC = 17, // MALLOC: [instty, op, align] + FUNC_CODE_INST_FREE = 18, // FREE: [opty, op] + FUNC_CODE_INST_ALLOCA = 19, // ALLOCA: [instty, op, align] + FUNC_CODE_INST_LOAD = 20, // LOAD: [opty, op, align, vol] + // FIXME: Remove STORE in favor of STORE2 in LLVM 3.0 + FUNC_CODE_INST_STORE = 21, // STORE: [valty,val,ptr, align, vol] + FUNC_CODE_INST_CALL = 22, // CALL: [attr, fnty, fnid, args...] + FUNC_CODE_INST_VAARG = 23, // VAARG: [valistty, valist, instty] + // This store code encodes the pointer type, rather than the value type + // this is so information only available in the pointer type (e.g. address + // spaces) is retained. + FUNC_CODE_INST_STORE2 = 24, // STORE: [ptrty,ptr,val, align, vol] + // FIXME: Remove GETRESULT in favor of EXTRACTVAL in LLVM 3.0 + FUNC_CODE_INST_GETRESULT = 25, // GETRESULT: [ty, opval, n] + FUNC_CODE_INST_EXTRACTVAL = 26, // EXTRACTVAL: [n x operands] + FUNC_CODE_INST_INSERTVAL = 27, // INSERTVAL: [n x operands] + // fcmp/icmp returning Int1TY or vector of Int1Ty. Same as CMP, exists to + // support legacy vicmp/vfcmp instructions. + FUNC_CODE_INST_CMP2 = 28, // CMP2: [opty, opval, opval, pred] + // new select on i1 or [N x i1] + FUNC_CODE_INST_VSELECT = 29, // VSELECT: [ty,opval,opval,predty,pred] + FUNC_CODE_INST_INBOUNDS_GEP= 30, // INBOUNDS_GEP: [n x operands] + FUNC_CODE_INST_INDIRECTBR = 31 // INDIRECTBR: [opty, op0, op1, ...] + }; +} // End bitc namespace +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Bitcode/ReaderWriter.h b/libclamav/c++/llvm/include/llvm/Bitcode/ReaderWriter.h new file mode 100644 index 000000000..7b74bdf76 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Bitcode/ReaderWriter.h @@ -0,0 +1,136 @@ +//===-- llvm/Bitcode/ReaderWriter.h - Bitcode reader/writers ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This header defines interfaces to read and write LLVM bitcode files/streams. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_BITCODE_H +#define LLVM_BITCODE_H + +#include + +namespace llvm { + class Module; + class ModuleProvider; + class MemoryBuffer; + class ModulePass; + class BitstreamWriter; + class LLVMContext; + class raw_ostream; + + /// getBitcodeModuleProvider - Read the header of the specified bitcode buffer + /// and prepare for lazy deserialization of function bodies. If successful, + /// this takes ownership of 'buffer' and returns a non-null pointer. On + /// error, this returns null, *does not* take ownership of Buffer, and fills + /// in *ErrMsg with an error description if ErrMsg is non-null. + ModuleProvider *getBitcodeModuleProvider(MemoryBuffer *Buffer, + LLVMContext& Context, + std::string *ErrMsg = 0); + + /// ParseBitcodeFile - Read the specified bitcode file, returning the module. + /// If an error occurs, this returns null and fills in *ErrMsg if it is + /// non-null. This method *never* takes ownership of Buffer. + Module *ParseBitcodeFile(MemoryBuffer *Buffer, LLVMContext& Context, + std::string *ErrMsg = 0); + + /// WriteBitcodeToFile - Write the specified module to the specified + /// raw output stream. + void WriteBitcodeToFile(const Module *M, raw_ostream &Out); + + /// WriteBitcodeToStream - Write the specified module to the specified + /// raw output stream. + void WriteBitcodeToStream(const Module *M, BitstreamWriter &Stream); + + /// createBitcodeWriterPass - Create and return a pass that writes the module + /// to the specified ostream. + ModulePass *createBitcodeWriterPass(raw_ostream &Str); + + + /// isBitcodeWrapper - Return true if the given bytes are the magic bytes + /// for an LLVM IR bitcode wrapper. + /// + static inline bool isBitcodeWrapper(const unsigned char *BufPtr, + const unsigned char *BufEnd) { + // See if you can find the hidden message in the magic bytes :-). + // (Hint: it's a little-endian encoding.) + return BufPtr != BufEnd && + BufPtr[0] == 0xDE && + BufPtr[1] == 0xC0 && + BufPtr[2] == 0x17 && + BufPtr[3] == 0x0B; + } + + /// isRawBitcode - Return true if the given bytes are the magic bytes for + /// raw LLVM IR bitcode (without a wrapper). + /// + static inline bool isRawBitcode(const unsigned char *BufPtr, + const unsigned char *BufEnd) { + // These bytes sort of have a hidden message, but it's not in + // little-endian this time, and it's a little redundant. + return BufPtr != BufEnd && + BufPtr[0] == 'B' && + BufPtr[1] == 'C' && + BufPtr[2] == 0xc0 && + BufPtr[3] == 0xde; + } + + /// isBitcode - Return true if the given bytes are the magic bytes for + /// LLVM IR bitcode, either with or without a wrapper. + /// + static bool inline isBitcode(const unsigned char *BufPtr, + const unsigned char *BufEnd) { + return isBitcodeWrapper(BufPtr, BufEnd) || + isRawBitcode(BufPtr, BufEnd); + } + + /// SkipBitcodeWrapperHeader - Some systems wrap bc files with a special + /// header for padding or other reasons. The format of this header is: + /// + /// struct bc_header { + /// uint32_t Magic; // 0x0B17C0DE + /// uint32_t Version; // Version, currently always 0. + /// uint32_t BitcodeOffset; // Offset to traditional bitcode file. + /// uint32_t BitcodeSize; // Size of traditional bitcode file. + /// ... potentially other gunk ... + /// }; + /// + /// This function is called when we find a file with a matching magic number. + /// In this case, skip down to the subsection of the file that is actually a + /// BC file. + static inline bool SkipBitcodeWrapperHeader(unsigned char *&BufPtr, + unsigned char *&BufEnd) { + enum { + KnownHeaderSize = 4*4, // Size of header we read. + OffsetField = 2*4, // Offset in bytes to Offset field. + SizeField = 3*4 // Offset in bytes to Size field. + }; + + // Must contain the header! + if (BufEnd-BufPtr < KnownHeaderSize) return true; + + unsigned Offset = ( BufPtr[OffsetField ] | + (BufPtr[OffsetField+1] << 8) | + (BufPtr[OffsetField+2] << 16) | + (BufPtr[OffsetField+3] << 24)); + unsigned Size = ( BufPtr[SizeField ] | + (BufPtr[SizeField +1] << 8) | + (BufPtr[SizeField +2] << 16) | + (BufPtr[SizeField +3] << 24)); + + // Verify that Offset+Size fits in the file. + if (Offset+Size > unsigned(BufEnd-BufPtr)) + return true; + BufPtr += Offset; + BufEnd = BufPtr+Size; + return false; + } +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Bitcode/Serialization.h b/libclamav/c++/llvm/include/llvm/Bitcode/Serialization.h new file mode 100644 index 000000000..2f0d35034 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Bitcode/Serialization.h @@ -0,0 +1,68 @@ +//==- Serialization.h - Generic Object Serialization to Bitcode ---*- 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 traits for primitive types used for both object +// serialization and deserialization. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_BITCODE_SERIALIZE +#define LLVM_BITCODE_SERIALIZE + +#include "llvm/Bitcode/SerializationFwd.h" + +namespace llvm { + +/// SerializeTrait - SerializeTrait bridges between the Serializer/Deserializer +/// and the functions that serialize objects of specific types. The default +/// behavior is to call static methods of the class for the object being +/// serialized, but this behavior can be changed by specializing this +/// template. Classes only need to implement the methods corresponding +/// to the serialization scheme they want to support. For example, "Read" +/// and "ReadVal" correspond to different deserialization schemes which make +/// sense for different types; a class need only implement one of them. +/// Serialization and deserialization of pointers are specially handled +/// by the Serializer and Deserializer using the EmitOwnedPtr, etc. methods. +/// To serialize the actual object referred to by a pointer, the class +/// of the object either must implement the methods called by the default +/// behavior of SerializeTrait, or specialize SerializeTrait. This latter +/// is useful when one cannot add methods to an existing class (for example). +template +struct SerializeTrait { + static inline void Emit(Serializer& S, const T& X) { X.Emit(S); } + static inline void Read(Deserializer& D, T& X) { X.Read(D); } + static inline T* Create(Deserializer& D) { return T::Create(D); } + + template + static inline T* Create(Deserializer& D, Arg1& arg1) { + return T::Create(D, arg1); + } +}; + +#define SERIALIZE_INT_TRAIT(TYPE)\ +template <> struct SerializeTrait {\ + static void Emit(Serializer& S, TYPE X);\ + static void Read(Deserializer& S, TYPE& X); }; + +SERIALIZE_INT_TRAIT(bool) +SERIALIZE_INT_TRAIT(unsigned char) +SERIALIZE_INT_TRAIT(unsigned short) +SERIALIZE_INT_TRAIT(unsigned int) +SERIALIZE_INT_TRAIT(unsigned long) + +SERIALIZE_INT_TRAIT(signed char) +SERIALIZE_INT_TRAIT(signed short) +SERIALIZE_INT_TRAIT(signed int) +SERIALIZE_INT_TRAIT(signed long) + +#undef SERIALIZE_INT_TRAIT + +} // end namespace llvm + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Bitcode/SerializationFwd.h b/libclamav/c++/llvm/include/llvm/Bitcode/SerializationFwd.h new file mode 100644 index 000000000..722419035 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Bitcode/SerializationFwd.h @@ -0,0 +1,27 @@ +//==- SerializationFwd.h - Forward references for Serialization ---*- C++ -*-=// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides forward references for bitcode object serialization. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_BITCODE_SERIALIZE_FWD +#define LLVM_BITCODE_SERIALIZE_FWD + +namespace llvm { + +class Serializer; +class Deserializer; +template struct SerializeTrait; + +typedef unsigned SerializedPtrID; + +} // end namespace llvm + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Bitcode/Serialize.h b/libclamav/c++/llvm/include/llvm/Bitcode/Serialize.h new file mode 100644 index 000000000..6fe4f0228 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Bitcode/Serialize.h @@ -0,0 +1,211 @@ +//==- Serialize.h - Generic Object Serialization to Bitcode -------*- 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 the interface for generic object serialization to +// LLVM bitcode. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_BITCODE_SERIALIZE_OUTPUT +#define LLVM_BITCODE_SERIALIZE_OUTPUT + +#include "llvm/Bitcode/Serialization.h" +#include "llvm/Bitcode/BitstreamWriter.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/DenseMap.h" + +namespace llvm { + +class Serializer { + BitstreamWriter& Stream; + SmallVector Record; + unsigned BlockLevel; + + typedef DenseMap MapTy; + MapTy PtrMap; + +public: + explicit Serializer(BitstreamWriter& stream); + ~Serializer(); + + //==------------------------------------------------==// + // Template-based dispatch to emit arbitrary types. + //==------------------------------------------------==// + + template + inline void Emit(const T& X) { SerializeTrait::Emit(*this,X); } + + //==------------------------------------------------==// + // Methods to emit primitive types. + //==------------------------------------------------==// + + void EmitInt(uint64_t X); + void EmitSInt(int64_t X); + + inline void EmitBool(bool X) { EmitInt(X); } + void EmitCStr(const char* beg, const char* end); + void EmitCStr(const char* cstr); + + void EmitPtr(const void* ptr) { EmitInt(getPtrId(ptr)); } + + template + inline void EmitRef(const T& ref) { EmitPtr(&ref); } + + // Emit a pointer and the object pointed to. (This has no relation to the + // OwningPtr<> class.) + template + inline void EmitOwnedPtr(T* ptr) { + EmitPtr(ptr); + if (ptr) SerializeTrait::Emit(*this,*ptr); + } + + + //==------------------------------------------------==// + // Batch emission of pointers. + //==------------------------------------------------==// + + template + void BatchEmitOwnedPtrs(T1* p1, T2* p2) { + EmitPtr(p1); + EmitPtr(p2); + if (p1) SerializeTrait::Emit(*this,*p1); + if (p2) SerializeTrait::Emit(*this,*p2); + } + + template + void BatchEmitOwnedPtrs(T1* p1, T2* p2, T3* p3) { + EmitPtr(p1); + EmitPtr(p2); + EmitPtr(p3); + if (p1) SerializeTrait::Emit(*this,*p1); + if (p2) SerializeTrait::Emit(*this,*p2); + if (p3) SerializeTrait::Emit(*this,*p3); + } + + template + void BatchEmitOwnedPtrs(T1* p1, T2* p2, T3* p3, T4& p4) { + EmitPtr(p1); + EmitPtr(p2); + EmitPtr(p3); + EmitPtr(p4); + if (p1) SerializeTrait::Emit(*this,*p1); + if (p2) SerializeTrait::Emit(*this,*p2); + if (p3) SerializeTrait::Emit(*this,*p3); + if (p4) SerializeTrait::Emit(*this,*p4); + } + + template + void BatchEmitOwnedPtrs(unsigned NumPtrs, T* const * Ptrs) { + for (unsigned i = 0; i < NumPtrs; ++i) + EmitPtr(Ptrs[i]); + + for (unsigned i = 0; i < NumPtrs; ++i) + if (Ptrs[i]) SerializeTrait::Emit(*this,*Ptrs[i]); + } + + template + void BatchEmitOwnedPtrs(unsigned NumT1Ptrs, T1* const * Ptrs, T2* p2) { + + for (unsigned i = 0; i < NumT1Ptrs; ++i) + EmitPtr(Ptrs[i]); + + EmitPtr(p2); + + for (unsigned i = 0; i < NumT1Ptrs; ++i) + if (Ptrs[i]) SerializeTrait::Emit(*this,*Ptrs[i]); + + if (p2) SerializeTrait::Emit(*this,*p2); + } + + template + void BatchEmitOwnedPtrs(unsigned NumT1Ptrs, T1* const * Ptrs, + T2* p2, T3* p3) { + + for (unsigned i = 0; i < NumT1Ptrs; ++i) + EmitPtr(Ptrs[i]); + + EmitPtr(p2); + EmitPtr(p3); + + for (unsigned i = 0; i < NumT1Ptrs; ++i) + if (Ptrs[i]) SerializeTrait::Emit(*this,*Ptrs[i]); + + if (p2) SerializeTrait::Emit(*this,*p2); + if (p3) SerializeTrait::Emit(*this,*p3); + } + + //==------------------------------------------------==// + // Emitter Functors + //==------------------------------------------------==// + + template + struct Emitter0 { + Serializer& S; + Emitter0(Serializer& s) : S(s) {} + void operator()(const T& x) const { + SerializeTrait::Emit(S,x); + } + }; + + template + struct Emitter1 { + Serializer& S; + Arg1 A1; + + Emitter1(Serializer& s, Arg1 a1) : S(s), A1(a1) {} + void operator()(const T& x) const { + SerializeTrait::Emit(S,x,A1); + } + }; + + template + struct Emitter2 { + Serializer& S; + Arg1 A1; + Arg2 A2; + + Emitter2(Serializer& s, Arg1 a1, Arg2 a2) : S(s), A1(a1), A2(a2) {} + void operator()(const T& x) const { + SerializeTrait::Emit(S,x,A1,A2); + } + }; + + template + Emitter0 MakeEmitter() { + return Emitter0(*this); + } + + template + Emitter1 MakeEmitter(Arg1 a1) { + return Emitter1(*this,a1); + } + + template + Emitter2 MakeEmitter(Arg1 a1, Arg2 a2) { + return Emitter2(*this,a1,a2); + } + + //==------------------------------------------------==// + // Misc. query and block/record manipulation methods. + //==------------------------------------------------==// + + bool isRegistered(const void* p) const; + + void FlushRecord() { if (inRecord()) EmitRecord(); } + void EnterBlock(unsigned BlockID = 8, unsigned CodeLen = 3); + void ExitBlock(); + +private: + void EmitRecord(); + inline bool inRecord() { return Record.size() > 0; } + SerializedPtrID getPtrId(const void* ptr); +}; + +} // end namespace llvm +#endif diff --git a/libclamav/c++/llvm/include/llvm/CMakeLists.txt b/libclamav/c++/llvm/include/llvm/CMakeLists.txt new file mode 100644 index 000000000..5e4f40881 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/CMakeLists.txt @@ -0,0 +1,19 @@ +set(LLVM_TARGET_DEFINITIONS Intrinsics.td) + +tablegen(Intrinsics.gen -gen-intrinsic) + +add_custom_target(intrinsics_gen ALL + DEPENDS ${llvm_builded_incs_dir}/Intrinsics.gen) + +set(LLVM_COMMON_DEPENDS ${LLVM_COMMON_DEPENDS} intrinsics_gen PARENT_SCOPE) + +if( MSVC_IDE OR XCODE ) + # Creates a dummy target containing all headers for the benefit of + # Visual Studio users. + file(GLOB_RECURSE headers *.h) + add_td_sources(headers) + add_library(llvm_headers_do_not_build EXCLUDE_FROM_ALL + # We need at least one source file: + ${LLVM_MAIN_SRC_DIR}/lib/Transforms/Hello/Hello.cpp + ${headers}) +endif() diff --git a/libclamav/c++/llvm/include/llvm/CallGraphSCCPass.h b/libclamav/c++/llvm/include/llvm/CallGraphSCCPass.h new file mode 100644 index 000000000..fc9feda5b --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/CallGraphSCCPass.h @@ -0,0 +1,77 @@ +//===- CallGraphSCCPass.h - Pass that operates BU on call graph -*- 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 the CallGraphSCCPass class, which is used for passes which +// are implemented as bottom-up traversals on the call graph. Because there may +// be cycles in the call graph, passes of this type operate on the call-graph in +// SCC order: that is, they process function bottom-up, except for recursive +// functions, which they process all at once. +// +// These passes are inherently interprocedural, and are required to keep the +// call graph up-to-date if they do anything which could modify it. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CALL_GRAPH_SCC_PASS_H +#define LLVM_CALL_GRAPH_SCC_PASS_H + +#include "llvm/Pass.h" +#include "llvm/Analysis/CallGraph.h" + +namespace llvm { + +class CallGraphNode; +class CallGraph; +class PMStack; + +struct CallGraphSCCPass : public Pass { + + explicit CallGraphSCCPass(intptr_t pid) : Pass(pid) {} + explicit CallGraphSCCPass(void *pid) : Pass(pid) {} + + /// doInitialization - This method is called before the SCC's of the program + /// has been processed, allowing the pass to do initialization as necessary. + virtual bool doInitialization(CallGraph &CG) { + return false; + } + + /// runOnSCC - This method should be implemented by the subclass to perform + /// whatever action is necessary for the specified SCC. Note that + /// non-recursive (or only self-recursive) functions will have an SCC size of + /// 1, where recursive portions of the call graph will have SCC size > 1. + /// + /// SCC passes that add or delete functions to the SCC are required to update + /// the SCC list, otherwise stale pointers may be dereferenced. + /// + virtual bool runOnSCC(std::vector &SCC) = 0; + + /// doFinalization - This method is called after the SCC's of the program has + /// been processed, allowing the pass to do final cleanup as necessary. + virtual bool doFinalization(CallGraph &CG) { + return false; + } + + /// Assign pass manager to manager this pass + virtual void assignPassManager(PMStack &PMS, + PassManagerType PMT = PMT_CallGraphPassManager); + + /// Return what kind of Pass Manager can manage this pass. + virtual PassManagerType getPotentialPassManagerType() const { + return PMT_CallGraphPassManager; + } + + /// getAnalysisUsage - For this class, we declare that we require and preserve + /// the call graph. If the derived class implements this method, it should + /// always explicitly call the implementation here. + virtual void getAnalysisUsage(AnalysisUsage &Info) const; +}; + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/CallingConv.h b/libclamav/c++/llvm/include/llvm/CallingConv.h new file mode 100644 index 000000000..318ea2875 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/CallingConv.h @@ -0,0 +1,77 @@ +//===-- llvm/CallingConv.h - LLVM Calling Conventions -----------*- 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 LLVM's set of calling conventions. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CALLINGCONV_H +#define LLVM_CALLINGCONV_H + +namespace llvm { + +/// CallingConv Namespace - This namespace contains an enum with a value for +/// the well-known calling conventions. +/// +namespace CallingConv { + /// A set of enums which specify the assigned numeric values for known llvm + /// calling conventions. + /// @brief LLVM Calling Convention Representation + enum ID { + /// C - The default llvm calling convention, compatible with C. This + /// convention is the only calling convention that supports varargs calls. + /// As with typical C calling conventions, the callee/caller have to + /// tolerate certain amounts of prototype mismatch. + C = 0, + + // Generic LLVM calling conventions. None of these calling conventions + // support varargs calls, and all assume that the caller and callee + // prototype exactly match. + + /// Fast - This calling convention attempts to make calls as fast as + /// possible (e.g. by passing things in registers). + Fast = 8, + + // Cold - This calling convention attempts to make code in the caller as + // efficient as possible under the assumption that the call is not commonly + // executed. As such, these calls often preserve all registers so that the + // call does not break any live ranges in the caller side. + Cold = 9, + + // Target - This is the start of the target-specific calling conventions, + // e.g. fastcall and thiscall on X86. + FirstTargetCC = 64, + + /// X86_StdCall - stdcall is the calling conventions mostly used by the + /// Win32 API. It is basically the same as the C convention with the + /// difference in that the callee is responsible for popping the arguments + /// from the stack. + X86_StdCall = 64, + + /// X86_FastCall - 'fast' analog of X86_StdCall. Passes first two arguments + /// in ECX:EDX registers, others - via stack. Callee is responsible for + /// stack cleaning. + X86_FastCall = 65, + + /// ARM_APCS - ARM Procedure Calling Standard calling convention (obsolete, + /// but still used on some targets). + ARM_APCS = 66, + + /// ARM_AAPCS - ARM Architecture Procedure Calling Standard calling + /// convention (aka EABI). Soft float variant. + ARM_AAPCS = 67, + + /// ARM_AAPCS_VFP - Same as ARM_AAPCS, but uses hard floating point ABI. + ARM_AAPCS_VFP = 68 + }; +} // End CallingConv namespace + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/CodeGen/AsmPrinter.h b/libclamav/c++/llvm/include/llvm/CodeGen/AsmPrinter.h new file mode 100644 index 000000000..9a07e31ac --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/CodeGen/AsmPrinter.h @@ -0,0 +1,425 @@ +//===-- llvm/CodeGen/AsmPrinter.h - AsmPrinter Framework --------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains a class to be used as the base class for target specific +// asm writers. This class primarily handles common functionality used by +// all asm writers. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_ASMPRINTER_H +#define LLVM_CODEGEN_ASMPRINTER_H + +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/Support/DebugLoc.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/ADT/DenseMap.h" + +namespace llvm { + class BlockAddress; + class GCStrategy; + class Constant; + class ConstantArray; + class ConstantFP; + class ConstantInt; + class ConstantStruct; + class ConstantVector; + class GCMetadataPrinter; + class GlobalValue; + class GlobalVariable; + class MachineBasicBlock; + class MachineFunction; + class MachineInstr; + class MachineLoopInfo; + class MachineLoop; + class MachineConstantPool; + class MachineConstantPoolEntry; + class MachineConstantPoolValue; + class MachineJumpTableInfo; + class MachineModuleInfo; + class MCInst; + class MCContext; + class MCSection; + class MCStreamer; + class MCSymbol; + class DwarfWriter; + class Mangler; + class MCAsmInfo; + class TargetLoweringObjectFile; + class Type; + class formatted_raw_ostream; + + /// AsmPrinter - This class is intended to be used as a driving class for all + /// asm writers. + class AsmPrinter : public MachineFunctionPass { + static char ID; + + /// FunctionNumber - This provides a unique ID for each function emitted in + /// this translation unit. It is autoincremented by SetupMachineFunction, + /// and can be accessed with getFunctionNumber() and + /// IncrementFunctionNumber(). + /// + unsigned FunctionNumber; + + // GCMetadataPrinters - The garbage collection metadata printer table. + typedef DenseMap gcp_map_type; + typedef gcp_map_type::iterator gcp_iterator; + gcp_map_type GCMetadataPrinters; + + /// If VerboseAsm is set, a pointer to the loop info for this + /// function. + /// + MachineLoopInfo *LI; + + public: + /// MMI - If available, this is a pointer to the current MachineModuleInfo. + MachineModuleInfo *MMI; + + protected: + /// DW - If available, this is a pointer to the current dwarf writer. + DwarfWriter *DW; + + public: + /// Flags to specify different kinds of comments to output in + /// assembly code. These flags carry semantic information not + /// otherwise easily derivable from the IR text. + /// + enum CommentFlag { + ReloadReuse = 0x1 + }; + + /// Output stream on which we're printing assembly code. + /// + formatted_raw_ostream &O; + + /// Target machine description. + /// + TargetMachine &TM; + + /// getObjFileLowering - Return information about object file lowering. + TargetLoweringObjectFile &getObjFileLowering() const; + + /// Target Asm Printer information. + /// + const MCAsmInfo *MAI; + + /// Target Register Information. + /// + const TargetRegisterInfo *TRI; + + /// OutContext - This is the context for the output file that we are + /// streaming. This owns all of the global MC-related objects for the + /// generated translation unit. + MCContext &OutContext; + + /// OutStreamer - This is the MCStreamer object for the file we are + /// generating. This contains the transient state for the current + /// translation unit that we are generating (such as the current section + /// etc). + MCStreamer &OutStreamer; + + /// The current machine function. + const MachineFunction *MF; + + /// Name-mangler for global names. + /// + Mangler *Mang; + + /// Cache of mangled name for current function. This is recalculated at the + /// beginning of each call to runOnMachineFunction(). + /// + std::string CurrentFnName; + + /// getCurrentSection() - Return the current section we are emitting to. + const MCSection *getCurrentSection() const; + + + /// VerboseAsm - Emit comments in assembly output if this is true. + /// + bool VerboseAsm; + + /// Private state for PrintSpecial() + // Assign a unique ID to this machine instruction. + mutable const MachineInstr *LastMI; + mutable const Function *LastFn; + mutable unsigned Counter; + + // Private state for processDebugLoc() + mutable DebugLocTuple PrevDLT; + + protected: + explicit AsmPrinter(formatted_raw_ostream &o, TargetMachine &TM, + const MCAsmInfo *T, bool V); + + public: + virtual ~AsmPrinter(); + + /// isVerbose - Return true if assembly output should contain comments. + /// + bool isVerbose() const { return VerboseAsm; } + + /// getFunctionNumber - Return a unique ID for the current function. + /// + unsigned getFunctionNumber() const { return FunctionNumber; } + + protected: + /// getAnalysisUsage - Record analysis usage. + /// + void getAnalysisUsage(AnalysisUsage &AU) const; + + /// doInitialization - Set up the AsmPrinter when we are working on a new + /// module. If your pass overrides this, it must make sure to explicitly + /// call this implementation. + bool doInitialization(Module &M); + + /// EmitStartOfAsmFile - This virtual method can be overridden by targets + /// that want to emit something at the start of their file. + virtual void EmitStartOfAsmFile(Module &) {} + + /// EmitEndOfAsmFile - This virtual method can be overridden by targets that + /// want to emit something at the end of their file. + virtual void EmitEndOfAsmFile(Module &) {} + + /// doFinalization - Shut down the asmprinter. If you override this in your + /// pass, you must make sure to call it explicitly. + bool doFinalization(Module &M); + + /// PrintSpecial - Print information related to the specified machine instr + /// that is independent of the operand, and may be independent of the instr + /// itself. This can be useful for portably encoding the comment character + /// or other bits of target-specific knowledge into the asmstrings. The + /// syntax used is ${:comment}. Targets can override this to add support + /// for their own strange codes. + virtual void PrintSpecial(const MachineInstr *MI, const char *Code) const; + + /// PrintAsmOperand - Print the specified operand of MI, an INLINEASM + /// instruction, using the specified assembler variant. Targets should + /// override this to format as appropriate. This method can return true if + /// the operand is erroneous. + virtual bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, + unsigned AsmVariant, const char *ExtraCode); + + /// PrintAsmMemoryOperand - Print the specified operand of MI, an INLINEASM + /// instruction, using the specified assembler variant as an address. + /// Targets should override this to format as appropriate. This method can + /// return true if the operand is erroneous. + virtual bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo, + unsigned AsmVariant, + const char *ExtraCode); + + /// PrintGlobalVariable - Emit the specified global variable and its + /// initializer to the output stream. + virtual void PrintGlobalVariable(const GlobalVariable *GV) = 0; + + /// SetupMachineFunction - This should be called when a new MachineFunction + /// is being processed from runOnMachineFunction. + void SetupMachineFunction(MachineFunction &MF); + + /// IncrementFunctionNumber - Increase Function Number. AsmPrinters should + /// not normally call this, as the counter is automatically bumped by + /// SetupMachineFunction. + void IncrementFunctionNumber() { FunctionNumber++; } + + /// EmitConstantPool - Print to the current output stream assembly + /// representations of the constants in the constant pool MCP. This is + /// used to print out constants which have been "spilled to memory" by + /// the code generator. + /// + void EmitConstantPool(MachineConstantPool *MCP); + + /// EmitJumpTableInfo - Print assembly representations of the jump tables + /// used by the current function to the current output stream. + /// + void EmitJumpTableInfo(MachineJumpTableInfo *MJTI, MachineFunction &MF); + + /// EmitSpecialLLVMGlobal - Check to see if the specified global is a + /// special global used by LLVM. If so, emit it and return true, otherwise + /// do nothing and return false. + bool EmitSpecialLLVMGlobal(const GlobalVariable *GV); + + public: + //===------------------------------------------------------------------===// + /// LEB 128 number encoding. + + /// PrintULEB128 - Print a series of hexidecimal values(separated by commas) + /// representing an unsigned leb128 value. + void PrintULEB128(unsigned Value) const; + + /// PrintSLEB128 - Print a series of hexidecimal values(separated by commas) + /// representing a signed leb128 value. + void PrintSLEB128(int Value) const; + + //===------------------------------------------------------------------===// + // Emission and print routines + // + + /// PrintHex - Print a value as a hexidecimal value. + /// + void PrintHex(int Value) const; + + /// EOL - Print a newline character to asm stream. If a comment is present + /// then it will be printed first. Comments should not contain '\n'. + void EOL() const; + void EOL(const std::string &Comment) const; + void EOL(const char* Comment) const; + void EOL(const char *Comment, unsigned Encoding) const; + + /// EmitULEB128Bytes - Emit an assembler byte data directive to compose an + /// unsigned leb128 value. + void EmitULEB128Bytes(unsigned Value) const; + + /// EmitSLEB128Bytes - print an assembler byte data directive to compose a + /// signed leb128 value. + void EmitSLEB128Bytes(int Value) const; + + /// EmitInt8 - Emit a byte directive and value. + /// + void EmitInt8(int Value) const; + + /// EmitInt16 - Emit a short directive and value. + /// + void EmitInt16(int Value) const; + + /// EmitInt32 - Emit a long directive and value. + /// + void EmitInt32(int Value) const; + + /// EmitInt64 - Emit a long long directive and value. + /// + void EmitInt64(uint64_t Value) const; + + /// EmitString - Emit a string with quotes and a null terminator. + /// Special characters are emitted properly. + /// @verbatim (Eg. '\t') @endverbatim + void EmitString(const StringRef String) const; + void EmitString(const char *String, unsigned Size) const; + + /// EmitFile - Emit a .file directive. + void EmitFile(unsigned Number, const std::string &Name) const; + + //===------------------------------------------------------------------===// + + /// EmitAlignment - Emit an alignment directive to the specified power of + /// two boundary. For example, if you pass in 3 here, you will get an 8 + /// byte alignment. If a global value is specified, and if that global has + /// an explicit alignment requested, it will unconditionally override the + /// alignment request. However, if ForcedAlignBits is specified, this value + /// has final say: the ultimate alignment will be the max of ForcedAlignBits + /// and the alignment computed with NumBits and the global. If UseFillExpr + /// is true, it also emits an optional second value FillValue which the + /// assembler uses to fill gaps to match alignment for text sections if the + /// has specified a non-zero fill value. + /// + /// The algorithm is: + /// Align = NumBits; + /// if (GV && GV->hasalignment) Align = GV->getalignment(); + /// Align = std::max(Align, ForcedAlignBits); + /// + void EmitAlignment(unsigned NumBits, const GlobalValue *GV = 0, + unsigned ForcedAlignBits = 0, + bool UseFillExpr = true) const; + + /// printLabel - This method prints a local label used by debug and + /// exception handling tables. + void printLabel(const MachineInstr *MI) const; + void printLabel(unsigned Id) const; + + /// printDeclare - This method prints a local variable declaration used by + /// debug tables. + void printDeclare(const MachineInstr *MI) const; + + /// EmitComments - Pretty-print comments for instructions + void EmitComments(const MachineInstr &MI) const; + /// EmitComments - Pretty-print comments for basic blocks + void EmitComments(const MachineBasicBlock &MBB) const; + + /// GetMBBSymbol - Return the MCSymbol corresponding to the specified basic + /// block label. + MCSymbol *GetMBBSymbol(unsigned MBBID) const; + + /// GetBlockAddressSymbol - Return the MCSymbol used to satisfy BlockAddress + /// uses of the specified basic block. + MCSymbol *GetBlockAddressSymbol(const BlockAddress *BA, + const char *Suffix = "") const; + MCSymbol *GetBlockAddressSymbol(const Function *F, + const BasicBlock *BB, + const char *Suffix = "") const; + + /// EmitBasicBlockStart - This method prints the label for the specified + /// MachineBasicBlock, an alignment (if present) and a comment describing + /// it if appropriate. + void EmitBasicBlockStart(const MachineBasicBlock *MBB) const; + protected: + /// EmitZeros - Emit a block of zeros. + /// + void EmitZeros(uint64_t NumZeros, unsigned AddrSpace = 0) const; + + /// EmitString - Emit a zero-byte-terminated string constant. + /// + virtual void EmitString(const ConstantArray *CVA) const; + + /// EmitConstantValueOnly - Print out the specified constant, without a + /// storage class. Only constants of first-class type are allowed here. + void EmitConstantValueOnly(const Constant *CV); + + /// EmitGlobalConstant - Print a general LLVM constant to the .s file. + void EmitGlobalConstant(const Constant* CV, unsigned AddrSpace = 0); + + virtual void EmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV); + + /// processDebugLoc - Processes the debug information of each machine + /// instruction's DebugLoc. + void processDebugLoc(const MachineInstr *MI, bool BeforePrintingInsn); + + /// printInlineAsm - This method formats and prints the specified machine + /// instruction that is an inline asm. + void printInlineAsm(const MachineInstr *MI) const; + + /// printImplicitDef - This method prints the specified machine instruction + /// that is an implicit def. + void printImplicitDef(const MachineInstr *MI) const; + + /// printKill - This method prints the specified kill machine instruction. + void printKill(const MachineInstr *MI) const; + + /// printPICJumpTableSetLabel - This method prints a set label for the + /// specified MachineBasicBlock for a jumptable entry. + virtual void printPICJumpTableSetLabel(unsigned uid, + const MachineBasicBlock *MBB) const; + virtual void printPICJumpTableSetLabel(unsigned uid, unsigned uid2, + const MachineBasicBlock *MBB) const; + virtual void printPICJumpTableEntry(const MachineJumpTableInfo *MJTI, + const MachineBasicBlock *MBB, + unsigned uid) const; + + /// printDataDirective - This method prints the asm directive for the + /// specified type. + void printDataDirective(const Type *type, unsigned AddrSpace = 0); + + /// printVisibility - This prints visibility information about symbol, if + /// this is suported by the target. + void printVisibility(const std::string& Name, unsigned Visibility) const; + + /// printOffset - This is just convenient handler for printing offsets. + void printOffset(int64_t Offset) const; + + private: + void EmitLLVMUsedList(Constant *List); + void EmitXXStructorList(Constant *List); + void EmitGlobalConstantStruct(const ConstantStruct* CVS, + unsigned AddrSpace); + void EmitGlobalConstantArray(const ConstantArray* CVA, unsigned AddrSpace); + void EmitGlobalConstantVector(const ConstantVector* CP); + void EmitGlobalConstantFP(const ConstantFP* CFP, unsigned AddrSpace); + void EmitGlobalConstantLargeInt(const ConstantInt* CI, unsigned AddrSpace); + GCMetadataPrinter *GetOrCreateGCPrinter(GCStrategy *C); + }; +} + +#endif diff --git a/libclamav/c++/llvm/include/llvm/CodeGen/BinaryObject.h b/libclamav/c++/llvm/include/llvm/CodeGen/BinaryObject.h new file mode 100644 index 000000000..3ade7c9e4 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/CodeGen/BinaryObject.h @@ -0,0 +1,353 @@ +//===-- llvm/CodeGen/BinaryObject.h - Binary Object. -----------*- 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 a Binary Object Aka. "blob" for holding data from code +// generators, ready for data to the object module code writters. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_BINARYOBJECT_H +#define LLVM_CODEGEN_BINARYOBJECT_H + +#include "llvm/CodeGen/MachineRelocation.h" +#include "llvm/System/DataTypes.h" + +#include +#include + +namespace llvm { + +typedef std::vector BinaryData; + +class BinaryObject { +protected: + std::string Name; + bool IsLittleEndian; + bool Is64Bit; + BinaryData Data; + std::vector Relocations; + +public: + /// Constructors and destructor + BinaryObject() {} + + BinaryObject(bool isLittleEndian, bool is64Bit) + : IsLittleEndian(isLittleEndian), Is64Bit(is64Bit) {} + + BinaryObject(const std::string &name, bool isLittleEndian, bool is64Bit) + : Name(name), IsLittleEndian(isLittleEndian), Is64Bit(is64Bit) {} + + ~BinaryObject() {} + + /// getName - get name of BinaryObject + inline std::string getName() const { return Name; } + + /// get size of binary data + size_t size() const { + return Data.size(); + } + + /// get binary data + BinaryData& getData() { + return Data; + } + + /// get machine relocations + const std::vector& getRelocations() const { + return Relocations; + } + + /// hasRelocations - Return true if 'Relocations' is not empty + bool hasRelocations() const { + return !Relocations.empty(); + } + + /// emitZeros - This callback is invoked to emit a arbitrary number + /// of zero bytes to the data stream. + inline void emitZeros(unsigned Size) { + for (unsigned i=0; i < Size; ++i) + emitByte(0); + } + + /// emitByte - This callback is invoked when a byte needs to be + /// written to the data stream. + inline void emitByte(uint8_t B) { + Data.push_back(B); + } + + /// emitWord16 - This callback is invoked when a 16-bit word needs to be + /// written to the data stream in correct endian format and correct size. + inline void emitWord16(uint16_t W) { + if (IsLittleEndian) + emitWord16LE(W); + else + emitWord16BE(W); + } + + /// emitWord16LE - This callback is invoked when a 16-bit word needs to be + /// written to the data stream in correct endian format and correct size. + inline void emitWord16LE(uint16_t W) { + Data.push_back((uint8_t)(W >> 0)); + Data.push_back((uint8_t)(W >> 8)); + } + + /// emitWord16BE - This callback is invoked when a 16-bit word needs to be + /// written to the data stream in correct endian format and correct size. + inline void emitWord16BE(uint16_t W) { + Data.push_back((uint8_t)(W >> 8)); + Data.push_back((uint8_t)(W >> 0)); + } + + /// emitWord - This callback is invoked when a word needs to be + /// written to the data stream in correct endian format and correct size. + inline void emitWord(uint64_t W) { + if (!Is64Bit) + emitWord32(W); + else + emitWord64(W); + } + + /// emitWord32 - This callback is invoked when a 32-bit word needs to be + /// written to the data stream in correct endian format. + inline void emitWord32(uint32_t W) { + if (IsLittleEndian) + emitWordLE(W); + else + emitWordBE(W); + } + + /// emitWord64 - This callback is invoked when a 32-bit word needs to be + /// written to the data stream in correct endian format. + inline void emitWord64(uint64_t W) { + if (IsLittleEndian) + emitDWordLE(W); + else + emitDWordBE(W); + } + + /// emitWord64 - This callback is invoked when a x86_fp80 needs to be + /// written to the data stream in correct endian format. + inline void emitWordFP80(const uint64_t *W, unsigned PadSize) { + if (IsLittleEndian) { + emitWord64(W[0]); + emitWord16(W[1]); + } else { + emitWord16(W[1]); + emitWord64(W[0]); + } + emitZeros(PadSize); + } + + /// emitWordLE - This callback is invoked when a 32-bit word needs to be + /// written to the data stream in little-endian format. + inline void emitWordLE(uint32_t W) { + Data.push_back((uint8_t)(W >> 0)); + Data.push_back((uint8_t)(W >> 8)); + Data.push_back((uint8_t)(W >> 16)); + Data.push_back((uint8_t)(W >> 24)); + } + + /// emitWordBE - This callback is invoked when a 32-bit word needs to be + /// written to the data stream in big-endian format. + /// + inline void emitWordBE(uint32_t W) { + Data.push_back((uint8_t)(W >> 24)); + Data.push_back((uint8_t)(W >> 16)); + Data.push_back((uint8_t)(W >> 8)); + Data.push_back((uint8_t)(W >> 0)); + } + + /// emitDWordLE - This callback is invoked when a 64-bit word needs to be + /// written to the data stream in little-endian format. + inline void emitDWordLE(uint64_t W) { + Data.push_back((uint8_t)(W >> 0)); + Data.push_back((uint8_t)(W >> 8)); + Data.push_back((uint8_t)(W >> 16)); + Data.push_back((uint8_t)(W >> 24)); + Data.push_back((uint8_t)(W >> 32)); + Data.push_back((uint8_t)(W >> 40)); + Data.push_back((uint8_t)(W >> 48)); + Data.push_back((uint8_t)(W >> 56)); + } + + /// emitDWordBE - This callback is invoked when a 64-bit word needs to be + /// written to the data stream in big-endian format. + inline void emitDWordBE(uint64_t W) { + Data.push_back((uint8_t)(W >> 56)); + Data.push_back((uint8_t)(W >> 48)); + Data.push_back((uint8_t)(W >> 40)); + Data.push_back((uint8_t)(W >> 32)); + Data.push_back((uint8_t)(W >> 24)); + Data.push_back((uint8_t)(W >> 16)); + Data.push_back((uint8_t)(W >> 8)); + Data.push_back((uint8_t)(W >> 0)); + } + + /// fixByte - This callback is invoked when a byte needs to be + /// fixup the buffer. + inline void fixByte(uint8_t B, uint32_t offset) { + Data[offset] = B; + } + + /// fixWord16 - This callback is invoked when a 16-bit word needs to + /// fixup the data stream in correct endian format. + inline void fixWord16(uint16_t W, uint32_t offset) { + if (IsLittleEndian) + fixWord16LE(W, offset); + else + fixWord16BE(W, offset); + } + + /// emitWord16LE - This callback is invoked when a 16-bit word needs to + /// fixup the data stream in little endian format. + inline void fixWord16LE(uint16_t W, uint32_t offset) { + Data[offset] = (uint8_t)(W >> 0); + Data[++offset] = (uint8_t)(W >> 8); + } + + /// fixWord16BE - This callback is invoked when a 16-bit word needs to + /// fixup data stream in big endian format. + inline void fixWord16BE(uint16_t W, uint32_t offset) { + Data[offset] = (uint8_t)(W >> 8); + Data[++offset] = (uint8_t)(W >> 0); + } + + /// emitWord - This callback is invoked when a word needs to + /// fixup the data in correct endian format and correct size. + inline void fixWord(uint64_t W, uint32_t offset) { + if (!Is64Bit) + fixWord32(W, offset); + else + fixWord64(W, offset); + } + + /// fixWord32 - This callback is invoked when a 32-bit word needs to + /// fixup the data in correct endian format. + inline void fixWord32(uint32_t W, uint32_t offset) { + if (IsLittleEndian) + fixWord32LE(W, offset); + else + fixWord32BE(W, offset); + } + + /// fixWord32LE - This callback is invoked when a 32-bit word needs to + /// fixup the data in little endian format. + inline void fixWord32LE(uint32_t W, uint32_t offset) { + Data[offset] = (uint8_t)(W >> 0); + Data[++offset] = (uint8_t)(W >> 8); + Data[++offset] = (uint8_t)(W >> 16); + Data[++offset] = (uint8_t)(W >> 24); + } + + /// fixWord32BE - This callback is invoked when a 32-bit word needs to + /// fixup the data in big endian format. + inline void fixWord32BE(uint32_t W, uint32_t offset) { + Data[offset] = (uint8_t)(W >> 24); + Data[++offset] = (uint8_t)(W >> 16); + Data[++offset] = (uint8_t)(W >> 8); + Data[++offset] = (uint8_t)(W >> 0); + } + + /// fixWord64 - This callback is invoked when a 64-bit word needs to + /// fixup the data in correct endian format. + inline void fixWord64(uint64_t W, uint32_t offset) { + if (IsLittleEndian) + fixWord64LE(W, offset); + else + fixWord64BE(W, offset); + } + + /// fixWord64BE - This callback is invoked when a 64-bit word needs to + /// fixup the data in little endian format. + inline void fixWord64LE(uint64_t W, uint32_t offset) { + Data[offset] = (uint8_t)(W >> 0); + Data[++offset] = (uint8_t)(W >> 8); + Data[++offset] = (uint8_t)(W >> 16); + Data[++offset] = (uint8_t)(W >> 24); + Data[++offset] = (uint8_t)(W >> 32); + Data[++offset] = (uint8_t)(W >> 40); + Data[++offset] = (uint8_t)(W >> 48); + Data[++offset] = (uint8_t)(W >> 56); + } + + /// fixWord64BE - This callback is invoked when a 64-bit word needs to + /// fixup the data in big endian format. + inline void fixWord64BE(uint64_t W, uint32_t offset) { + Data[offset] = (uint8_t)(W >> 56); + Data[++offset] = (uint8_t)(W >> 48); + Data[++offset] = (uint8_t)(W >> 40); + Data[++offset] = (uint8_t)(W >> 32); + Data[++offset] = (uint8_t)(W >> 24); + Data[++offset] = (uint8_t)(W >> 16); + Data[++offset] = (uint8_t)(W >> 8); + Data[++offset] = (uint8_t)(W >> 0); + } + + /// emitAlignment - Pad the data to the specified alignment. + void emitAlignment(unsigned Alignment, uint8_t fill = 0) { + if (Alignment <= 1) return; + unsigned PadSize = -Data.size() & (Alignment-1); + for (unsigned i = 0; i>= 7; + if (Value) Byte |= 0x80; + emitByte(Byte); + } while (Value); + } + + /// emitSLEB128Bytes - This callback is invoked when a SLEB128 needs to be + /// written to the data stream. + void emitSLEB128Bytes(int64_t Value) { + int Sign = Value >> (8 * sizeof(Value) - 1); + bool IsMore; + + do { + uint8_t Byte = (uint8_t)(Value & 0x7f); + Value >>= 7; + IsMore = Value != Sign || ((Byte ^ Sign) & 0x40) != 0; + if (IsMore) Byte |= 0x80; + emitByte(Byte); + } while (IsMore); + } + + /// emitString - This callback is invoked when a String needs to be + /// written to the data stream. + void emitString(const std::string &String) { + for (unsigned i = 0, N = static_cast(String.size()); igetParent(); + const BasicBlock* srcBB = src->getBasicBlock(); + + MachineBasicBlock* crit_mbb = MF.CreateMachineBasicBlock(srcBB); + + // modify the llvm control flow graph + src->removeSuccessor(dst); + src->addSuccessor(crit_mbb); + crit_mbb->addSuccessor(dst); + + // insert the new block into the machine function. + MF.push_back(crit_mbb); + + // insert a unconditional branch linking the new block to dst + const TargetMachine& TM = MF.getTarget(); + const TargetInstrInfo* TII = TM.getInstrInfo(); + std::vector emptyConditions; + TII->InsertBranch(*crit_mbb, dst, (MachineBasicBlock*)0, + emptyConditions); + + // modify every branch in src that points to dst to point to the new + // machine basic block instead: + MachineBasicBlock::iterator mii = src->end(); + bool found_branch = false; + while (mii != src->begin()) { + mii--; + // if there are no more branches, finish the loop + if (!mii->getDesc().isTerminator()) { + break; + } + + // Scan the operands of this branch, replacing any uses of dst with + // crit_mbb. + for (unsigned i = 0, e = mii->getNumOperands(); i != e; ++i) { + MachineOperand & mo = mii->getOperand(i); + if (mo.isMBB() && mo.getMBB() == dst) { + found_branch = true; + mo.setMBB(crit_mbb); + } + } + } + + // TODO: This is tentative. It may be necessary to fix this code. Maybe + // I am inserting too many gotos, but I am trusting that the asm printer + // will optimize the unnecessary gotos. + if(!found_branch) { + TII->InsertBranch(*src, crit_mbb, (MachineBasicBlock*)0, + emptyConditions); + } + + /// Change all the phi functions in dst, so that the incoming block be + /// crit_mbb, instead of src + for(mii = dst->begin(); mii != dst->end(); mii++) { + /// the first instructions are always phi functions. + if(mii->getOpcode() != TargetInstrInfo::PHI) + break; + + // Find the operands corresponding to the source block + std::vector toRemove; + unsigned reg = 0; + for (unsigned u = 0; u != mii->getNumOperands(); ++u) + if (mii->getOperand(u).isMBB() && + mii->getOperand(u).getMBB() == src) { + reg = mii->getOperand(u-1).getReg(); + toRemove.push_back(u-1); + } + // Remove all uses of this MBB + for (std::vector::reverse_iterator I = toRemove.rbegin(), + E = toRemove.rend(); I != E; ++I) { + mii->RemoveOperand(*I+1); + mii->RemoveOperand(*I); + } + + // Add a single use corresponding to the new MBB + mii->addOperand(MachineOperand::CreateReg(reg, false)); + mii->addOperand(MachineOperand::CreateMBB(crit_mbb)); + } + + return crit_mbb; +} + +} + +#endif diff --git a/libclamav/c++/llvm/include/llvm/CodeGen/CallingConvLower.h b/libclamav/c++/llvm/include/llvm/CodeGen/CallingConvLower.h new file mode 100644 index 000000000..45a2757d3 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/CodeGen/CallingConvLower.h @@ -0,0 +1,293 @@ +//===-- llvm/CallingConvLower.h - Calling Conventions -----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the CCState and CCValAssign classes, used for lowering +// and implementing calling conventions. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_CALLINGCONVLOWER_H +#define LLVM_CODEGEN_CALLINGCONVLOWER_H + +#include "llvm/ADT/SmallVector.h" +#include "llvm/CodeGen/ValueTypes.h" +#include "llvm/CodeGen/SelectionDAGNodes.h" +#include "llvm/CallingConv.h" + +namespace llvm { + class TargetRegisterInfo; + class TargetMachine; + class CCState; + class SDNode; + +/// CCValAssign - Represent assignment of one arg/retval to a location. +class CCValAssign { +public: + enum LocInfo { + Full, // The value fills the full location. + SExt, // The value is sign extended in the location. + ZExt, // The value is zero extended in the location. + AExt, // The value is extended with undefined upper bits. + BCvt, // The value is bit-converted in the location. + Indirect // The location contains pointer to the value. + // TODO: a subset of the value is in the location. + }; +private: + /// ValNo - This is the value number begin assigned (e.g. an argument number). + unsigned ValNo; + + /// Loc is either a stack offset or a register number. + unsigned Loc; + + /// isMem - True if this is a memory loc, false if it is a register loc. + bool isMem : 1; + + /// isCustom - True if this arg/retval requires special handling. + bool isCustom : 1; + + /// Information about how the value is assigned. + LocInfo HTP : 6; + + /// ValVT - The type of the value being assigned. + EVT ValVT; + + /// LocVT - The type of the location being assigned to. + EVT LocVT; +public: + + static CCValAssign getReg(unsigned ValNo, EVT ValVT, + unsigned RegNo, EVT LocVT, + LocInfo HTP) { + CCValAssign Ret; + Ret.ValNo = ValNo; + Ret.Loc = RegNo; + Ret.isMem = false; + Ret.isCustom = false; + Ret.HTP = HTP; + Ret.ValVT = ValVT; + Ret.LocVT = LocVT; + return Ret; + } + + static CCValAssign getCustomReg(unsigned ValNo, EVT ValVT, + unsigned RegNo, EVT LocVT, + LocInfo HTP) { + CCValAssign Ret; + Ret = getReg(ValNo, ValVT, RegNo, LocVT, HTP); + Ret.isCustom = true; + return Ret; + } + + static CCValAssign getMem(unsigned ValNo, EVT ValVT, + unsigned Offset, EVT LocVT, + LocInfo HTP) { + CCValAssign Ret; + Ret.ValNo = ValNo; + Ret.Loc = Offset; + Ret.isMem = true; + Ret.isCustom = false; + Ret.HTP = HTP; + Ret.ValVT = ValVT; + Ret.LocVT = LocVT; + return Ret; + } + + static CCValAssign getCustomMem(unsigned ValNo, EVT ValVT, + unsigned Offset, EVT LocVT, + LocInfo HTP) { + CCValAssign Ret; + Ret = getMem(ValNo, ValVT, Offset, LocVT, HTP); + Ret.isCustom = true; + return Ret; + } + + unsigned getValNo() const { return ValNo; } + EVT getValVT() const { return ValVT; } + + bool isRegLoc() const { return !isMem; } + bool isMemLoc() const { return isMem; } + + bool needsCustom() const { return isCustom; } + + unsigned getLocReg() const { assert(isRegLoc()); return Loc; } + unsigned getLocMemOffset() const { assert(isMemLoc()); return Loc; } + EVT getLocVT() const { return LocVT; } + + LocInfo getLocInfo() const { return HTP; } + bool isExtInLoc() const { + return (HTP == AExt || HTP == SExt || HTP == ZExt); + } + +}; + +/// CCAssignFn - This function assigns a location for Val, updating State to +/// reflect the change. +typedef bool CCAssignFn(unsigned ValNo, EVT ValVT, + EVT LocVT, CCValAssign::LocInfo LocInfo, + ISD::ArgFlagsTy ArgFlags, CCState &State); + +/// CCCustomFn - This function assigns a location for Val, possibly updating +/// all args to reflect changes and indicates if it handled it. It must set +/// isCustom if it handles the arg and returns true. +typedef bool CCCustomFn(unsigned &ValNo, EVT &ValVT, + EVT &LocVT, CCValAssign::LocInfo &LocInfo, + ISD::ArgFlagsTy &ArgFlags, CCState &State); + +/// CCState - This class holds information needed while lowering arguments and +/// return values. It captures which registers are already assigned and which +/// stack slots are used. It provides accessors to allocate these values. +class CCState { + CallingConv::ID CallingConv; + bool IsVarArg; + const TargetMachine &TM; + const TargetRegisterInfo &TRI; + SmallVector &Locs; + LLVMContext &Context; + + unsigned StackOffset; + SmallVector UsedRegs; +public: + CCState(CallingConv::ID CC, bool isVarArg, const TargetMachine &TM, + SmallVector &locs, LLVMContext &C); + + void addLoc(const CCValAssign &V) { + Locs.push_back(V); + } + + LLVMContext &getContext() const { return Context; } + const TargetMachine &getTarget() const { return TM; } + CallingConv::ID getCallingConv() const { return CallingConv; } + bool isVarArg() const { return IsVarArg; } + + unsigned getNextStackOffset() const { return StackOffset; } + + /// isAllocated - Return true if the specified register (or an alias) is + /// allocated. + bool isAllocated(unsigned Reg) const { + return UsedRegs[Reg/32] & (1 << (Reg&31)); + } + + /// AnalyzeFormalArguments - Analyze an array of argument values, + /// incorporating info about the formals into this state. + void AnalyzeFormalArguments(const SmallVectorImpl &Ins, + CCAssignFn Fn); + + /// AnalyzeReturn - Analyze the returned values of a return, + /// incorporating info about the result values into this state. + void AnalyzeReturn(const SmallVectorImpl &Outs, + CCAssignFn Fn); + + /// CheckReturn - Analyze the return values of a function, returning + /// true if the return can be performed without sret-demotion, and + /// false otherwise. + bool CheckReturn(const SmallVectorImpl &OutTys, + const SmallVectorImpl &ArgsFlags, + CCAssignFn Fn); + + /// AnalyzeCallOperands - Analyze the outgoing arguments to a call, + /// incorporating info about the passed values into this state. + void AnalyzeCallOperands(const SmallVectorImpl &Outs, + CCAssignFn Fn); + + /// AnalyzeCallOperands - Same as above except it takes vectors of types + /// and argument flags. + void AnalyzeCallOperands(SmallVectorImpl &ArgVTs, + SmallVectorImpl &Flags, + CCAssignFn Fn); + + /// AnalyzeCallResult - Analyze the return values of a call, + /// incorporating info about the passed values into this state. + void AnalyzeCallResult(const SmallVectorImpl &Ins, + CCAssignFn Fn); + + /// AnalyzeCallResult - Same as above except it's specialized for calls which + /// produce a single value. + void AnalyzeCallResult(EVT VT, CCAssignFn Fn); + + /// getFirstUnallocated - Return the first unallocated register in the set, or + /// NumRegs if they are all allocated. + unsigned getFirstUnallocated(const unsigned *Regs, unsigned NumRegs) const { + for (unsigned i = 0; i != NumRegs; ++i) + if (!isAllocated(Regs[i])) + return i; + return NumRegs; + } + + /// AllocateReg - Attempt to allocate one register. If it is not available, + /// return zero. Otherwise, return the register, marking it and any aliases + /// as allocated. + unsigned AllocateReg(unsigned Reg) { + if (isAllocated(Reg)) return 0; + MarkAllocated(Reg); + return Reg; + } + + /// Version of AllocateReg with extra register to be shadowed. + unsigned AllocateReg(unsigned Reg, unsigned ShadowReg) { + if (isAllocated(Reg)) return 0; + MarkAllocated(Reg); + MarkAllocated(ShadowReg); + return Reg; + } + + /// AllocateReg - Attempt to allocate one of the specified registers. If none + /// are available, return zero. Otherwise, return the first one available, + /// marking it and any aliases as allocated. + unsigned AllocateReg(const unsigned *Regs, unsigned NumRegs) { + unsigned FirstUnalloc = getFirstUnallocated(Regs, NumRegs); + if (FirstUnalloc == NumRegs) + return 0; // Didn't find the reg. + + // Mark the register and any aliases as allocated. + unsigned Reg = Regs[FirstUnalloc]; + MarkAllocated(Reg); + return Reg; + } + + /// Version of AllocateReg with list of registers to be shadowed. + unsigned AllocateReg(const unsigned *Regs, const unsigned *ShadowRegs, + unsigned NumRegs) { + unsigned FirstUnalloc = getFirstUnallocated(Regs, NumRegs); + if (FirstUnalloc == NumRegs) + return 0; // Didn't find the reg. + + // Mark the register and any aliases as allocated. + unsigned Reg = Regs[FirstUnalloc], ShadowReg = ShadowRegs[FirstUnalloc]; + MarkAllocated(Reg); + MarkAllocated(ShadowReg); + return Reg; + } + + /// AllocateStack - Allocate a chunk of stack space with the specified size + /// and alignment. + unsigned AllocateStack(unsigned Size, unsigned Align) { + assert(Align && ((Align-1) & Align) == 0); // Align is power of 2. + StackOffset = ((StackOffset + Align-1) & ~(Align-1)); + unsigned Result = StackOffset; + StackOffset += Size; + return Result; + } + + // HandleByVal - Allocate a stack slot large enough to pass an argument by + // value. The size and alignment information of the argument is encoded in its + // parameter attribute. + void HandleByVal(unsigned ValNo, EVT ValVT, + EVT LocVT, CCValAssign::LocInfo LocInfo, + int MinSize, int MinAlign, ISD::ArgFlagsTy ArgFlags); + +private: + /// MarkAllocated - Mark a register and all of its aliases as allocated. + void MarkAllocated(unsigned Reg); +}; + + + +} // end namespace llvm + +#endif diff --git a/libclamav/c++/llvm/include/llvm/CodeGen/DAGISelHeader.h b/libclamav/c++/llvm/include/llvm/CodeGen/DAGISelHeader.h new file mode 100644 index 000000000..624f18aba --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/CodeGen/DAGISelHeader.h @@ -0,0 +1,136 @@ +//==-llvm/CodeGen/DAGISelHeader.h - Common DAG ISel definitions -*- C++ -*-==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides definitions of the common, target-independent methods and +// data, which is used by SelectionDAG-based instruction selectors. +// +// *** NOTE: This file is #included into the middle of the target +// instruction selector class. These functions are really methods. +// This is a little awkward, but it allows this code to be shared +// by all the targets while still being able to call into +// target-specific code without using a virtual function call. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_DAGISEL_HEADER_H +#define LLVM_CODEGEN_DAGISEL_HEADER_H + +/// ISelPosition - Node iterator marking the current position of +/// instruction selection as it procedes through the topologically-sorted +/// node list. +SelectionDAG::allnodes_iterator ISelPosition; + +/// IsChainCompatible - Returns true if Chain is Op or Chain does +/// not reach Op. +static bool IsChainCompatible(SDNode *Chain, SDNode *Op) { + if (Chain->getOpcode() == ISD::EntryToken) + return true; + if (Chain->getOpcode() == ISD::TokenFactor) + return false; + if (Chain->getNumOperands() > 0) { + SDValue C0 = Chain->getOperand(0); + if (C0.getValueType() == MVT::Other) + return C0.getNode() != Op && IsChainCompatible(C0.getNode(), Op); + } + return true; +} + +/// ISelUpdater - helper class to handle updates of the +/// instruciton selection graph. +class VISIBILITY_HIDDEN ISelUpdater : public SelectionDAG::DAGUpdateListener { + SelectionDAG::allnodes_iterator &ISelPosition; +public: + explicit ISelUpdater(SelectionDAG::allnodes_iterator &isp) + : ISelPosition(isp) {} + + /// NodeDeleted - Handle nodes deleted from the graph. If the + /// node being deleted is the current ISelPosition node, update + /// ISelPosition. + /// + virtual void NodeDeleted(SDNode *N, SDNode *E) { + if (ISelPosition == SelectionDAG::allnodes_iterator(N)) + ++ISelPosition; + } + + /// NodeUpdated - Ignore updates for now. + virtual void NodeUpdated(SDNode *N) {} +}; + +/// ReplaceUses - replace all uses of the old node F with the use +/// of the new node T. +DISABLE_INLINE void ReplaceUses(SDValue F, SDValue T) { + ISelUpdater ISU(ISelPosition); + CurDAG->ReplaceAllUsesOfValueWith(F, T, &ISU); +} + +/// ReplaceUses - replace all uses of the old nodes F with the use +/// of the new nodes T. +DISABLE_INLINE void ReplaceUses(const SDValue *F, const SDValue *T, + unsigned Num) { + ISelUpdater ISU(ISelPosition); + CurDAG->ReplaceAllUsesOfValuesWith(F, T, Num, &ISU); +} + +/// ReplaceUses - replace all uses of the old node F with the use +/// of the new node T. +DISABLE_INLINE void ReplaceUses(SDNode *F, SDNode *T) { + ISelUpdater ISU(ISelPosition); + CurDAG->ReplaceAllUsesWith(F, T, &ISU); +} + +/// SelectRoot - Top level entry to DAG instruction selector. +/// Selects instructions starting at the root of the current DAG. +void SelectRoot(SelectionDAG &DAG) { + SelectRootInit(); + + // Create a dummy node (which is not added to allnodes), that adds + // a reference to the root node, preventing it from being deleted, + // and tracking any changes of the root. + HandleSDNode Dummy(CurDAG->getRoot()); + ISelPosition = next(SelectionDAG::allnodes_iterator(CurDAG->getRoot().getNode())); + + // The AllNodes list is now topological-sorted. Visit the + // nodes by starting at the end of the list (the root of the + // graph) and preceding back toward the beginning (the entry + // node). + while (ISelPosition != CurDAG->allnodes_begin()) { + SDNode *Node = --ISelPosition; + // Skip dead nodes. DAGCombiner is expected to eliminate all dead nodes, + // but there are currently some corner cases that it misses. Also, this + // makes it theoretically possible to disable the DAGCombiner. + if (Node->use_empty()) + continue; +#if 0 + DAG.setSubgraphColor(Node, "red"); +#endif + SDNode *ResNode = Select(SDValue(Node, 0)); + // If node should not be replaced, + // continue with the next one. + if (ResNode == Node) + continue; + // Replace node. + if (ResNode) { +#if 0 + DAG.setSubgraphColor(ResNode, "yellow"); + DAG.setSubgraphColor(ResNode, "black"); +#endif + ReplaceUses(Node, ResNode); + } + // If after the replacement this node is not used any more, + // remove this dead node. + if (Node->use_empty()) { // Don't delete EntryToken, etc. + ISelUpdater ISU(ISelPosition); + CurDAG->RemoveDeadNode(Node, &ISU); + } + } + + CurDAG->setRoot(Dummy.getValue()); +} + +#endif /* LLVM_CODEGEN_DAGISEL_HEADER_H */ diff --git a/libclamav/c++/llvm/include/llvm/CodeGen/DwarfWriter.h b/libclamav/c++/llvm/include/llvm/CodeGen/DwarfWriter.h new file mode 100644 index 000000000..460c3c7f6 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/CodeGen/DwarfWriter.h @@ -0,0 +1,103 @@ +//===-- llvm/CodeGen/DwarfWriter.h - Dwarf Framework ------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains support for writing Dwarf debug and exception info into +// asm files. For Details on the Dwarf 3 specfication see DWARF Debugging +// Information Format V.3 reference manual http://dwarf.freestandards.org , +// +// The role of the Dwarf Writer class is to extract information from the +// MachineModuleInfo object, organize it in Dwarf form and then emit it into asm +// the current asm file using data and high level Dwarf directives. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_DWARFWRITER_H +#define LLVM_CODEGEN_DWARFWRITER_H + +#include "llvm/Pass.h" +#include "llvm/Target/TargetMachine.h" + +namespace llvm { + +class AsmPrinter; +class DwarfDebug; +class DwarfException; +class MachineModuleInfo; +class MachineFunction; +class MachineInstr; +class Value; +class Module; +class MDNode; +class MCAsmInfo; +class raw_ostream; +class Instruction; +class DICompileUnit; +class DISubprogram; +class DIVariable; + +//===----------------------------------------------------------------------===// +// DwarfWriter - Emits Dwarf debug and exception handling directives. +// + +class DwarfWriter : public ImmutablePass { +private: + /// DD - Provides the DwarfWriter debug implementation. + /// + DwarfDebug *DD; + + /// DE - Provides the DwarfWriter exception implementation. + /// + DwarfException *DE; + +public: + static char ID; // Pass identification, replacement for typeid + + DwarfWriter(); + virtual ~DwarfWriter(); + + //===--------------------------------------------------------------------===// + // Main entry points. + // + + /// BeginModule - Emit all Dwarf sections that should come prior to the + /// content. + void BeginModule(Module *M, MachineModuleInfo *MMI, raw_ostream &OS, + AsmPrinter *A, const MCAsmInfo *T); + + /// EndModule - Emit all Dwarf sections that should come after the content. + /// + void EndModule(); + + /// BeginFunction - Gather pre-function debug information. Assumes being + /// emitted immediately after the function entry point. + void BeginFunction(MachineFunction *MF); + + /// EndFunction - Gather and emit post-function debug information. + /// + void EndFunction(MachineFunction *MF); + + /// RecordSourceLine - Register a source line with debug info. Returns a + /// unique label ID used to generate a label and provide correspondence to + /// the source line list. + unsigned RecordSourceLine(unsigned Line, unsigned Col, MDNode *Scope); + + /// getRecordSourceLineCount - Count source lines. + unsigned getRecordSourceLineCount(); + + /// ShouldEmitDwarfDebug - Returns true if Dwarf debugging declarations should + /// be emitted. + bool ShouldEmitDwarfDebug() const; + + void BeginScope(const MachineInstr *MI, unsigned Label); + void EndScope(const MachineInstr *MI); +}; + +} // end llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/CodeGen/ELFRelocation.h b/libclamav/c++/llvm/include/llvm/CodeGen/ELFRelocation.h new file mode 100644 index 000000000..e58b8df55 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/CodeGen/ELFRelocation.h @@ -0,0 +1,51 @@ +//=== ELFRelocation.h - ELF Relocation 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 defines the ELFRelocation class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_ELF_RELOCATION_H +#define LLVM_CODEGEN_ELF_RELOCATION_H + +#include "llvm/System/DataTypes.h" + +namespace llvm { + + /// ELFRelocation - This class contains all the information necessary to + /// to generate any 32-bit or 64-bit ELF relocation entry. + class ELFRelocation { + uint64_t r_offset; // offset in the section of the object this applies to + uint32_t r_symidx; // symbol table index of the symbol to use + uint32_t r_type; // machine specific relocation type + int64_t r_add; // explicit relocation addend + bool r_rela; // if true then the addend is part of the entry + // otherwise the addend is at the location specified + // by r_offset + public: + + uint64_t getInfo(bool is64Bit = false) const { + if (is64Bit) + return ((uint64_t)r_symidx << 32) + ((uint64_t)r_type & 0xFFFFFFFFL); + else + return (r_symidx << 8) + (r_type & 0xFFL); + } + + uint64_t getOffset() const { return r_offset; } + uint64_t getAddress() const { return r_add; } + + ELFRelocation(uint64_t off, uint32_t sym, uint32_t type, + bool rela = true, int64_t addend = 0) : + r_offset(off), r_symidx(sym), r_type(type), + r_add(addend), r_rela(rela) {} + }; + +} // end llvm namespace + +#endif // LLVM_CODEGEN_ELF_RELOCATION_H diff --git a/libclamav/c++/llvm/include/llvm/CodeGen/FastISel.h b/libclamav/c++/llvm/include/llvm/CodeGen/FastISel.h new file mode 100644 index 000000000..1efd1e08a --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/CodeGen/FastISel.h @@ -0,0 +1,316 @@ +//===-- FastISel.h - Definition of the FastISel class ---------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the FastISel class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_FASTISEL_H +#define LLVM_CODEGEN_FASTISEL_H + +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallSet.h" +#include "llvm/CodeGen/SelectionDAGNodes.h" + +namespace llvm { + +class AllocaInst; +class ConstantFP; +class Instruction; +class MachineBasicBlock; +class MachineConstantPool; +class MachineFunction; +class MachineFrameInfo; +class MachineModuleInfo; +class DwarfWriter; +class MachineRegisterInfo; +class TargetData; +class TargetInstrInfo; +class TargetLowering; +class TargetMachine; +class TargetRegisterClass; + +/// FastISel - This is a fast-path instruction selection class that +/// generates poor code and doesn't support illegal types or non-trivial +/// lowering, but runs quickly. +class FastISel { +protected: + MachineBasicBlock *MBB; + DenseMap LocalValueMap; + DenseMap &ValueMap; + DenseMap &MBBMap; + DenseMap &StaticAllocaMap; +#ifndef NDEBUG + SmallSet &CatchInfoLost; +#endif + MachineFunction &MF; + MachineModuleInfo *MMI; + DwarfWriter *DW; + MachineRegisterInfo &MRI; + MachineFrameInfo &MFI; + MachineConstantPool &MCP; + DebugLoc DL; + const TargetMachine &TM; + const TargetData &TD; + const TargetInstrInfo &TII; + const TargetLowering &TLI; + +public: + /// startNewBlock - Set the current block to which generated machine + /// instructions will be appended, and clear the local CSE map. + /// + void startNewBlock(MachineBasicBlock *mbb) { + setCurrentBlock(mbb); + LocalValueMap.clear(); + } + + /// setCurrentBlock - Set the current block to which generated machine + /// instructions will be appended. + /// + void setCurrentBlock(MachineBasicBlock *mbb) { + MBB = mbb; + } + + /// setCurDebugLoc - Set the current debug location information, which is used + /// when creating a machine instruction. + /// + void setCurDebugLoc(DebugLoc dl) { DL = dl; } + + /// getCurDebugLoc() - Return current debug location information. + DebugLoc getCurDebugLoc() const { return DL; } + + /// SelectInstruction - Do "fast" instruction selection for the given + /// LLVM IR instruction, and append generated machine instructions to + /// the current block. Return true if selection was successful. + /// + bool SelectInstruction(Instruction *I); + + /// SelectOperator - Do "fast" instruction selection for the given + /// LLVM IR operator (Instruction or ConstantExpr), and append + /// generated machine instructions to the current block. Return true + /// if selection was successful. + /// + bool SelectOperator(User *I, unsigned Opcode); + + /// TargetSelectInstruction - This method is called by target-independent + /// code when the normal FastISel process fails to select an instruction. + /// This gives targets a chance to emit code for anything that doesn't + /// fit into FastISel's framework. It returns true if it was successful. + /// + virtual bool + TargetSelectInstruction(Instruction *I) = 0; + + /// getRegForValue - Create a virtual register and arrange for it to + /// be assigned the value for the given LLVM value. + unsigned getRegForValue(Value *V); + + /// lookUpRegForValue - Look up the value to see if its value is already + /// cached in a register. It may be defined by instructions across blocks or + /// defined locally. + unsigned lookUpRegForValue(Value *V); + + /// getRegForGEPIndex - This is a wrapper around getRegForValue that also + /// takes care of truncating or sign-extending the given getelementptr + /// index value. + unsigned getRegForGEPIndex(Value *V); + + virtual ~FastISel(); + +protected: + FastISel(MachineFunction &mf, + MachineModuleInfo *mmi, + DwarfWriter *dw, + DenseMap &vm, + DenseMap &bm, + DenseMap &am +#ifndef NDEBUG + , SmallSet &cil +#endif + ); + + /// FastEmit_r - This method is called by target-independent code + /// to request that an instruction with the given type and opcode + /// be emitted. + virtual unsigned FastEmit_(MVT VT, + MVT RetVT, + ISD::NodeType Opcode); + + /// FastEmit_r - This method is called by target-independent code + /// to request that an instruction with the given type, opcode, and + /// register operand be emitted. + /// + virtual unsigned FastEmit_r(MVT VT, + MVT RetVT, + ISD::NodeType Opcode, unsigned Op0); + + /// FastEmit_rr - This method is called by target-independent code + /// to request that an instruction with the given type, opcode, and + /// register operands be emitted. + /// + virtual unsigned FastEmit_rr(MVT VT, + MVT RetVT, + ISD::NodeType Opcode, + unsigned Op0, unsigned Op1); + + /// FastEmit_ri - This method is called by target-independent code + /// to request that an instruction with the given type, opcode, and + /// register and immediate operands be emitted. + /// + virtual unsigned FastEmit_ri(MVT VT, + MVT RetVT, + ISD::NodeType Opcode, + unsigned Op0, uint64_t Imm); + + /// FastEmit_rf - This method is called by target-independent code + /// to request that an instruction with the given type, opcode, and + /// register and floating-point immediate operands be emitted. + /// + virtual unsigned FastEmit_rf(MVT VT, + MVT RetVT, + ISD::NodeType Opcode, + unsigned Op0, ConstantFP *FPImm); + + /// FastEmit_rri - This method is called by target-independent code + /// to request that an instruction with the given type, opcode, and + /// register and immediate operands be emitted. + /// + virtual unsigned FastEmit_rri(MVT VT, + MVT RetVT, + ISD::NodeType Opcode, + unsigned Op0, unsigned Op1, uint64_t Imm); + + /// FastEmit_ri_ - This method is a wrapper of FastEmit_ri. It first tries + /// to emit an instruction with an immediate operand using FastEmit_ri. + /// If that fails, it materializes the immediate into a register and try + /// FastEmit_rr instead. + unsigned FastEmit_ri_(MVT VT, + ISD::NodeType Opcode, + unsigned Op0, uint64_t Imm, + MVT ImmType); + + /// FastEmit_rf_ - This method is a wrapper of FastEmit_rf. It first tries + /// to emit an instruction with an immediate operand using FastEmit_rf. + /// If that fails, it materializes the immediate into a register and try + /// FastEmit_rr instead. + unsigned FastEmit_rf_(MVT VT, + ISD::NodeType Opcode, + unsigned Op0, ConstantFP *FPImm, + MVT ImmType); + + /// FastEmit_i - This method is called by target-independent code + /// to request that an instruction with the given type, opcode, and + /// immediate operand be emitted. + virtual unsigned FastEmit_i(MVT VT, + MVT RetVT, + ISD::NodeType Opcode, + uint64_t Imm); + + /// FastEmit_f - This method is called by target-independent code + /// to request that an instruction with the given type, opcode, and + /// floating-point immediate operand be emitted. + virtual unsigned FastEmit_f(MVT VT, + MVT RetVT, + ISD::NodeType Opcode, + ConstantFP *FPImm); + + /// FastEmitInst_ - Emit a MachineInstr with no operands and a + /// result register in the given register class. + /// + unsigned FastEmitInst_(unsigned MachineInstOpcode, + const TargetRegisterClass *RC); + + /// FastEmitInst_r - Emit a MachineInstr with one register operand + /// and a result register in the given register class. + /// + unsigned FastEmitInst_r(unsigned MachineInstOpcode, + const TargetRegisterClass *RC, + unsigned Op0); + + /// FastEmitInst_rr - Emit a MachineInstr with two register operands + /// and a result register in the given register class. + /// + unsigned FastEmitInst_rr(unsigned MachineInstOpcode, + const TargetRegisterClass *RC, + unsigned Op0, unsigned Op1); + + /// FastEmitInst_ri - Emit a MachineInstr with two register operands + /// and a result register in the given register class. + /// + unsigned FastEmitInst_ri(unsigned MachineInstOpcode, + const TargetRegisterClass *RC, + unsigned Op0, uint64_t Imm); + + /// FastEmitInst_rf - Emit a MachineInstr with two register operands + /// and a result register in the given register class. + /// + unsigned FastEmitInst_rf(unsigned MachineInstOpcode, + const TargetRegisterClass *RC, + unsigned Op0, ConstantFP *FPImm); + + /// FastEmitInst_rri - Emit a MachineInstr with two register operands, + /// an immediate, and a result register in the given register class. + /// + unsigned FastEmitInst_rri(unsigned MachineInstOpcode, + const TargetRegisterClass *RC, + unsigned Op0, unsigned Op1, uint64_t Imm); + + /// FastEmitInst_i - Emit a MachineInstr with a single immediate + /// operand, and a result register in the given register class. + unsigned FastEmitInst_i(unsigned MachineInstrOpcode, + const TargetRegisterClass *RC, + uint64_t Imm); + + /// FastEmitInst_extractsubreg - Emit a MachineInstr for an extract_subreg + /// from a specified index of a superregister to a specified type. + unsigned FastEmitInst_extractsubreg(MVT RetVT, + unsigned Op0, uint32_t Idx); + + /// FastEmitZExtFromI1 - Emit MachineInstrs to compute the value of Op + /// with all but the least significant bit set to zero. + unsigned FastEmitZExtFromI1(MVT VT, + unsigned Op); + + /// FastEmitBranch - Emit an unconditional branch to the given block, + /// unless it is the immediate (fall-through) successor, and update + /// the CFG. + void FastEmitBranch(MachineBasicBlock *MBB); + + unsigned UpdateValueMap(Value* I, unsigned Reg); + + unsigned createResultReg(const TargetRegisterClass *RC); + + /// TargetMaterializeConstant - Emit a constant in a register using + /// target-specific logic, such as constant pool loads. + virtual unsigned TargetMaterializeConstant(Constant* C) { + return 0; + } + + /// TargetMaterializeAlloca - Emit an alloca address in a register using + /// target-specific logic. + virtual unsigned TargetMaterializeAlloca(AllocaInst* C) { + return 0; + } + +private: + bool SelectBinaryOp(User *I, ISD::NodeType ISDOpcode); + + bool SelectFNeg(User *I); + + bool SelectGetElementPtr(User *I); + + bool SelectCall(User *I); + + bool SelectBitCast(User *I); + + bool SelectCast(User *I, ISD::NodeType Opcode); +}; + +} + +#endif diff --git a/libclamav/c++/llvm/include/llvm/CodeGen/FileWriters.h b/libclamav/c++/llvm/include/llvm/CodeGen/FileWriters.h new file mode 100644 index 000000000..a913d21eb --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/CodeGen/FileWriters.h @@ -0,0 +1,31 @@ +//===-- FileWriters.h - File Writers Creation Functions ---------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Functions to add the various file writer passes. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_FILEWRITERS_H +#define LLVM_CODEGEN_FILEWRITERS_H + +namespace llvm { + + class PassManagerBase; + class ObjectCodeEmitter; + class TargetMachine; + class raw_ostream; + + ObjectCodeEmitter *AddELFWriter(PassManagerBase &FPM, raw_ostream &O, + TargetMachine &TM); + ObjectCodeEmitter *AddMachOWriter(PassManagerBase &FPM, raw_ostream &O, + TargetMachine &TM); + +} // end llvm namespace + +#endif // LLVM_CODEGEN_FILEWRITERS_H diff --git a/libclamav/c++/llvm/include/llvm/CodeGen/GCMetadata.h b/libclamav/c++/llvm/include/llvm/CodeGen/GCMetadata.h new file mode 100644 index 000000000..04fd8bed9 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/CodeGen/GCMetadata.h @@ -0,0 +1,192 @@ +//===-- GCMetadata.h - Garbage collector metadata -------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the GCFunctionInfo and GCModuleInfo classes, which are +// used as a communication channel from the target code generator to the target +// garbage collectors. This interface allows code generators and garbage +// collectors to be developed independently. +// +// The GCFunctionInfo class logs the data necessary to build a type accurate +// stack map. The code generator outputs: +// +// - Safe points as specified by the GCStrategy's NeededSafePoints. +// - Stack offsets for GC roots, as specified by calls to llvm.gcroot +// +// As a refinement, liveness analysis calculates the set of live roots at each +// safe point. Liveness analysis is not presently performed by the code +// generator, so all roots are assumed live. +// +// GCModuleInfo simply collects GCFunctionInfo instances for each Function as +// they are compiled. This accretion is necessary for collectors which must emit +// a stack map for the compilation unit as a whole. Therefore, GCFunctionInfo +// outlives the MachineFunction from which it is derived and must not refer to +// any code generator data structures. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_GCMETADATA_H +#define LLVM_CODEGEN_GCMETADATA_H + +#include "llvm/Pass.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/StringMap.h" + +namespace llvm { + + class AsmPrinter; + class GCStrategy; + class Constant; + class MCAsmInfo; + + + namespace GC { + /// PointKind - The type of a collector-safe point. + /// + enum PointKind { + Loop, //< Instr is a loop (backwards branch). + Return, //< Instr is a return instruction. + PreCall, //< Instr is a call instruction. + PostCall //< Instr is the return address of a call. + }; + } + + /// GCPoint - Metadata for a collector-safe point in machine code. + /// + struct GCPoint { + GC::PointKind Kind; //< The kind of the safe point. + unsigned Num; //< Usually a label. + + GCPoint(GC::PointKind K, unsigned N) : Kind(K), Num(N) {} + }; + + /// GCRoot - Metadata for a pointer to an object managed by the garbage + /// collector. + struct GCRoot { + int Num; //< Usually a frame index. + int StackOffset; //< Offset from the stack pointer. + Constant *Metadata; //< Metadata straight from the call to llvm.gcroot. + + GCRoot(int N, Constant *MD) : Num(N), StackOffset(-1), Metadata(MD) {} + }; + + + /// GCFunctionInfo - Garbage collection metadata for a single function. + /// + class GCFunctionInfo { + public: + typedef std::vector::iterator iterator; + typedef std::vector::iterator roots_iterator; + typedef std::vector::const_iterator live_iterator; + + private: + const Function &F; + GCStrategy &S; + uint64_t FrameSize; + std::vector Roots; + std::vector SafePoints; + + // FIXME: Liveness. A 2D BitVector, perhaps? + // + // BitVector Liveness; + // + // bool islive(int point, int root) = + // Liveness[point * SafePoints.size() + root] + // + // The bit vector is the more compact representation where >3.2% of roots + // are live per safe point (1.5% on 64-bit hosts). + + public: + GCFunctionInfo(const Function &F, GCStrategy &S); + ~GCFunctionInfo(); + + /// getFunction - Return the function to which this metadata applies. + /// + const Function &getFunction() const { return F; } + + /// getStrategy - Return the GC strategy for the function. + /// + GCStrategy &getStrategy() { return S; } + + /// addStackRoot - Registers a root that lives on the stack. Num is the + /// stack object ID for the alloca (if the code generator is + // using MachineFrameInfo). + void addStackRoot(int Num, Constant *Metadata) { + Roots.push_back(GCRoot(Num, Metadata)); + } + + /// addSafePoint - Notes the existence of a safe point. Num is the ID of the + /// label just prior to the safe point (if the code generator is using + /// MachineModuleInfo). + void addSafePoint(GC::PointKind Kind, unsigned Num) { + SafePoints.push_back(GCPoint(Kind, Num)); + } + + /// getFrameSize/setFrameSize - Records the function's frame size. + /// + uint64_t getFrameSize() const { return FrameSize; } + void setFrameSize(uint64_t S) { FrameSize = S; } + + /// begin/end - Iterators for safe points. + /// + iterator begin() { return SafePoints.begin(); } + iterator end() { return SafePoints.end(); } + size_t size() const { return SafePoints.size(); } + + /// roots_begin/roots_end - Iterators for all roots in the function. + /// + roots_iterator roots_begin() { return Roots.begin(); } + roots_iterator roots_end () { return Roots.end(); } + size_t roots_size() const { return Roots.size(); } + + /// live_begin/live_end - Iterators for live roots at a given safe point. + /// + live_iterator live_begin(const iterator &p) { return roots_begin(); } + live_iterator live_end (const iterator &p) { return roots_end(); } + size_t live_size(const iterator &p) const { return roots_size(); } + }; + + + /// GCModuleInfo - Garbage collection metadata for a whole module. + /// + class GCModuleInfo : public ImmutablePass { + typedef StringMap strategy_map_type; + typedef std::vector list_type; + typedef DenseMap finfo_map_type; + + strategy_map_type StrategyMap; + list_type StrategyList; + finfo_map_type FInfoMap; + + GCStrategy *getOrCreateStrategy(const Module *M, const std::string &Name); + + public: + typedef list_type::const_iterator iterator; + + static char ID; + + GCModuleInfo(); + ~GCModuleInfo(); + + /// clear - Resets the pass. The metadata deleter pass calls this. + /// + void clear(); + + /// begin/end - Iterators for used strategies. + /// + iterator begin() const { return StrategyList.begin(); } + iterator end() const { return StrategyList.end(); } + + /// get - Look up function metadata. + /// + GCFunctionInfo &getFunctionInfo(const Function &F); + }; + +} + +#endif diff --git a/libclamav/c++/llvm/include/llvm/CodeGen/GCMetadataPrinter.h b/libclamav/c++/llvm/include/llvm/CodeGen/GCMetadataPrinter.h new file mode 100644 index 000000000..ff1a205ad --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/CodeGen/GCMetadataPrinter.h @@ -0,0 +1,76 @@ +//===-- llvm/CodeGen/GCMetadataPrinter.h - Prints asm GC tables -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// The abstract base class GCMetadataPrinter supports writing GC metadata tables +// as assembly code. This is a separate class from GCStrategy in order to allow +// users of the LLVM JIT to avoid linking with the AsmWriter. +// +// Subclasses of GCMetadataPrinter must be registered using the +// GCMetadataPrinterRegistry. This is separate from the GCStrategy itself +// because these subclasses are logically plugins for the AsmWriter. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_GCMETADATAPRINTER_H +#define LLVM_CODEGEN_GCMETADATAPRINTER_H + +#include "llvm/CodeGen/GCMetadata.h" +#include "llvm/CodeGen/GCStrategy.h" +#include "llvm/Support/Registry.h" + +namespace llvm { + + class GCMetadataPrinter; + class raw_ostream; + + /// GCMetadataPrinterRegistry - The GC assembly printer registry uses all the + /// defaults from Registry. + typedef Registry GCMetadataPrinterRegistry; + + /// GCMetadataPrinter - Emits GC metadata as assembly code. + /// + class GCMetadataPrinter { + public: + typedef GCStrategy::list_type list_type; + typedef GCStrategy::iterator iterator; + + private: + GCStrategy *S; + + friend class AsmPrinter; + + protected: + // May only be subclassed. + GCMetadataPrinter(); + + // Do not implement. + GCMetadataPrinter(const GCMetadataPrinter &); + GCMetadataPrinter &operator=(const GCMetadataPrinter &); + + public: + GCStrategy &getStrategy() { return *S; } + const Module &getModule() const { return S->getModule(); } + + /// begin/end - Iterate over the collected function metadata. + iterator begin() { return S->begin(); } + iterator end() { return S->end(); } + + /// beginAssembly/finishAssembly - Emit module metadata as assembly code. + virtual void beginAssembly(raw_ostream &OS, AsmPrinter &AP, + const MCAsmInfo &MAI); + + virtual void finishAssembly(raw_ostream &OS, AsmPrinter &AP, + const MCAsmInfo &MAI); + + virtual ~GCMetadataPrinter(); + }; + +} + +#endif diff --git a/libclamav/c++/llvm/include/llvm/CodeGen/GCStrategy.h b/libclamav/c++/llvm/include/llvm/CodeGen/GCStrategy.h new file mode 100644 index 000000000..cd760dba9 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/CodeGen/GCStrategy.h @@ -0,0 +1,142 @@ +//===-- llvm/CodeGen/GCStrategy.h - Garbage collection ----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// GCStrategy coordinates code generation algorithms and implements some itself +// in order to generate code compatible with a target code generator as +// specified in a function's 'gc' attribute. Algorithms are enabled by setting +// flags in a subclass's constructor, and some virtual methods can be +// overridden. +// +// When requested, the GCStrategy will be populated with data about each +// function which uses it. Specifically: +// +// - Safe points +// Garbage collection is generally only possible at certain points in code. +// GCStrategy can request that the collector insert such points: +// +// - At and after any call to a subroutine +// - Before returning from the current function +// - Before backwards branches (loops) +// +// - Roots +// When a reference to a GC-allocated object exists on the stack, it must be +// stored in an alloca registered with llvm.gcoot. +// +// This information can used to emit the metadata tables which are required by +// the target garbage collector runtime. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_GCSTRATEGY_H +#define LLVM_CODEGEN_GCSTRATEGY_H + +#include "llvm/CodeGen/GCMetadata.h" +#include "llvm/Support/Registry.h" +#include + +namespace llvm { + + class GCStrategy; + + /// The GC strategy registry uses all the defaults from Registry. + /// + typedef Registry GCRegistry; + + /// GCStrategy describes a garbage collector algorithm's code generation + /// requirements, and provides overridable hooks for those needs which cannot + /// be abstractly described. + class GCStrategy { + public: + typedef std::vector list_type; + typedef list_type::iterator iterator; + + private: + friend class GCModuleInfo; + const Module *M; + std::string Name; + + list_type Functions; + + protected: + unsigned NeededSafePoints; //< Bitmask of required safe points. + bool CustomReadBarriers; //< Default is to insert loads. + bool CustomWriteBarriers; //< Default is to insert stores. + bool CustomRoots; //< Default is to pass through to backend. + bool InitRoots; //< If set, roots are nulled during lowering. + bool UsesMetadata; //< If set, backend must emit metadata tables. + + public: + GCStrategy(); + + virtual ~GCStrategy(); + + + /// getName - The name of the GC strategy, for debugging. + /// + const std::string &getName() const { return Name; } + + /// getModule - The module within which the GC strategy is operating. + /// + const Module &getModule() const { return *M; } + + /// needsSafePoitns - True if safe points of any kind are required. By + // default, none are recorded. + bool needsSafePoints() const { return NeededSafePoints != 0; } + + /// needsSafePoint(Kind) - True if the given kind of safe point is + // required. By default, none are recorded. + bool needsSafePoint(GC::PointKind Kind) const { + return (NeededSafePoints & 1 << Kind) != 0; + } + + /// customWriteBarrier - By default, write barriers are replaced with simple + /// store instructions. If true, then + /// performCustomLowering must instead lower them. + bool customWriteBarrier() const { return CustomWriteBarriers; } + + /// customReadBarrier - By default, read barriers are replaced with simple + /// load instructions. If true, then + /// performCustomLowering must instead lower them. + bool customReadBarrier() const { return CustomReadBarriers; } + + /// customRoots - By default, roots are left for the code generator so it + /// can generate a stack map. If true, then + // performCustomLowering must delete them. + bool customRoots() const { return CustomRoots; } + + /// initializeRoots - If set, gcroot intrinsics should initialize their + // allocas to null before the first use. This is + // necessary for most GCs and is enabled by default. + bool initializeRoots() const { return InitRoots; } + + /// usesMetadata - If set, appropriate metadata tables must be emitted by + /// the back-end (assembler, JIT, or otherwise). + bool usesMetadata() const { return UsesMetadata; } + + /// begin/end - Iterators for function metadata. + /// + iterator begin() { return Functions.begin(); } + iterator end() { return Functions.end(); } + + /// insertFunctionMetadata - Creates metadata for a function. + /// + GCFunctionInfo *insertFunctionInfo(const Function &F); + + /// initializeCustomLowering/performCustomLowering - If any of the actions + /// are set to custom, performCustomLowering must be overriden to transform + /// the corresponding actions to LLVM IR. initializeCustomLowering is + /// optional to override. These are the only GCStrategy methods through + /// which the LLVM IR can be modified. + virtual bool initializeCustomLowering(Module &F); + virtual bool performCustomLowering(Function &F); + }; + +} + +#endif diff --git a/libclamav/c++/llvm/include/llvm/CodeGen/GCs.h b/libclamav/c++/llvm/include/llvm/CodeGen/GCs.h new file mode 100644 index 000000000..c407b6167 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/CodeGen/GCs.h @@ -0,0 +1,35 @@ +//===-- GCs.h - Garbage collector linkage hacks ---------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains hack functions to force linking in the GC components. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_GCS_H +#define LLVM_CODEGEN_GCS_H + +namespace llvm { + class GCStrategy; + class GCMetadataPrinter; + + /// FIXME: Collector instances are not useful on their own. These no longer + /// serve any purpose except to link in the plugins. + + /// Creates an ocaml-compatible garbage collector. + void linkOcamlGC(); + + /// Creates an ocaml-compatible metadata printer. + void linkOcamlGCPrinter(); + + /// Creates a shadow stack garbage collector. This collector requires no code + /// generator support. + void linkShadowStackGC(); +} + +#endif diff --git a/libclamav/c++/llvm/include/llvm/CodeGen/IntrinsicLowering.h b/libclamav/c++/llvm/include/llvm/CodeGen/IntrinsicLowering.h new file mode 100644 index 000000000..eefbc45cb --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/CodeGen/IntrinsicLowering.h @@ -0,0 +1,54 @@ +//===-- IntrinsicLowering.h - Intrinsic Function Lowering -------*- 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 the IntrinsicLowering interface. This interface allows +// addition of domain-specific or front-end specific intrinsics to LLVM without +// having to modify all of the C backend or interpreter. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_INTRINSICLOWERING_H +#define LLVM_CODEGEN_INTRINSICLOWERING_H + +#include "llvm/Intrinsics.h" + +namespace llvm { + class CallInst; + class Module; + class TargetData; + + class IntrinsicLowering { + const TargetData& TD; + + + bool Warned; + public: + explicit IntrinsicLowering(const TargetData &td) : + TD(td), Warned(false) {} + + /// AddPrototypes - This method, if called, causes all of the prototypes + /// that might be needed by an intrinsic lowering implementation to be + /// inserted into the module specified. + void AddPrototypes(Module &M); + + /// LowerIntrinsicCall - This method replaces a call with the LLVM function + /// which should be used to implement the specified intrinsic function call. + /// If an intrinsic function must be implemented by the code generator + /// (such as va_start), this function should print a message and abort. + /// + /// Otherwise, if an intrinsic function call can be lowered, the code to + /// implement it (often a call to a non-intrinsic function) is inserted + /// _after_ the call instruction and the call is deleted. The caller must + /// be capable of handling this kind of change. + /// + void LowerIntrinsicCall(CallInst *CI); + }; +} + +#endif diff --git a/libclamav/c++/llvm/include/llvm/CodeGen/JITCodeEmitter.h b/libclamav/c++/llvm/include/llvm/CodeGen/JITCodeEmitter.h new file mode 100644 index 000000000..ea3e59bea --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/CodeGen/JITCodeEmitter.h @@ -0,0 +1,349 @@ +//===-- llvm/CodeGen/JITCodeEmitter.h - Code emission ----------*- 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 an abstract interface that is used by the machine code +// emission framework to output the code. This allows machine code emission to +// be separated from concerns such as resolution of call targets, and where the +// machine code will be written (memory or disk, f.e.). +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_JITCODEEMITTER_H +#define LLVM_CODEGEN_JITCODEEMITTER_H + +#include +#include "llvm/System/DataTypes.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/CodeGen/MachineCodeEmitter.h" + +using namespace std; + +namespace llvm { + +class MachineBasicBlock; +class MachineConstantPool; +class MachineJumpTableInfo; +class MachineFunction; +class MachineModuleInfo; +class MachineRelocation; +class Value; +class GlobalValue; +class Function; + +/// JITCodeEmitter - This class defines two sorts of methods: those for +/// emitting the actual bytes of machine code, and those for emitting auxillary +/// structures, such as jump tables, relocations, etc. +/// +/// Emission of machine code is complicated by the fact that we don't (in +/// general) know the size of the machine code that we're about to emit before +/// we emit it. As such, we preallocate a certain amount of memory, and set the +/// BufferBegin/BufferEnd pointers to the start and end of the buffer. As we +/// emit machine instructions, we advance the CurBufferPtr to indicate the +/// location of the next byte to emit. In the case of a buffer overflow (we +/// need to emit more machine code than we have allocated space for), the +/// CurBufferPtr will saturate to BufferEnd and ignore stores. Once the entire +/// function has been emitted, the overflow condition is checked, and if it has +/// occurred, more memory is allocated, and we reemit the code into it. +/// +class JITCodeEmitter : public MachineCodeEmitter { +public: + virtual ~JITCodeEmitter() {} + + /// startFunction - This callback is invoked when the specified function is + /// about to be code generated. This initializes the BufferBegin/End/Ptr + /// fields. + /// + virtual void startFunction(MachineFunction &F) = 0; + + /// finishFunction - This callback is invoked when the specified function has + /// finished code generation. If a buffer overflow has occurred, this method + /// returns true (the callee is required to try again), otherwise it returns + /// false. + /// + virtual bool finishFunction(MachineFunction &F) = 0; + + /// startGVStub - This callback is invoked when the JIT needs the address of a + /// GV (e.g. function) that has not been code generated yet. The StubSize + /// specifies the total size required by the stub. The BufferState must be + /// passed to finishGVStub, and start/finish pairs with the same BufferState + /// must be properly nested. + /// + virtual void startGVStub(BufferState &BS, const GlobalValue* GV, + unsigned StubSize, unsigned Alignment = 1) = 0; + + /// startGVStub - This callback is invoked when the JIT needs the address of a + /// GV (e.g. function) that has not been code generated yet. Buffer points to + /// memory already allocated for this stub. The BufferState must be passed to + /// finishGVStub, and start/finish pairs with the same BufferState must be + /// properly nested. + /// + virtual void startGVStub(BufferState &BS, void *Buffer, + unsigned StubSize) = 0; + + /// finishGVStub - This callback is invoked to terminate a GV stub and returns + /// the start address of the stub. The BufferState must first have been + /// passed to startGVStub. + /// + virtual void *finishGVStub(BufferState &BS) = 0; + + /// emitByte - This callback is invoked when a byte needs to be written to the + /// output stream. + /// + void emitByte(uint8_t B) { + if (CurBufferPtr != BufferEnd) + *CurBufferPtr++ = B; + } + + /// emitWordLE - This callback is invoked when a 32-bit word needs to be + /// written to the output stream in little-endian format. + /// + void emitWordLE(uint32_t W) { + if (4 <= BufferEnd-CurBufferPtr) { + *CurBufferPtr++ = (uint8_t)(W >> 0); + *CurBufferPtr++ = (uint8_t)(W >> 8); + *CurBufferPtr++ = (uint8_t)(W >> 16); + *CurBufferPtr++ = (uint8_t)(W >> 24); + } else { + CurBufferPtr = BufferEnd; + } + } + + /// emitWordBE - This callback is invoked when a 32-bit word needs to be + /// written to the output stream in big-endian format. + /// + void emitWordBE(uint32_t W) { + if (4 <= BufferEnd-CurBufferPtr) { + *CurBufferPtr++ = (uint8_t)(W >> 24); + *CurBufferPtr++ = (uint8_t)(W >> 16); + *CurBufferPtr++ = (uint8_t)(W >> 8); + *CurBufferPtr++ = (uint8_t)(W >> 0); + } else { + CurBufferPtr = BufferEnd; + } + } + + /// emitDWordLE - This callback is invoked when a 64-bit word needs to be + /// written to the output stream in little-endian format. + /// + void emitDWordLE(uint64_t W) { + if (8 <= BufferEnd-CurBufferPtr) { + *CurBufferPtr++ = (uint8_t)(W >> 0); + *CurBufferPtr++ = (uint8_t)(W >> 8); + *CurBufferPtr++ = (uint8_t)(W >> 16); + *CurBufferPtr++ = (uint8_t)(W >> 24); + *CurBufferPtr++ = (uint8_t)(W >> 32); + *CurBufferPtr++ = (uint8_t)(W >> 40); + *CurBufferPtr++ = (uint8_t)(W >> 48); + *CurBufferPtr++ = (uint8_t)(W >> 56); + } else { + CurBufferPtr = BufferEnd; + } + } + + /// emitDWordBE - This callback is invoked when a 64-bit word needs to be + /// written to the output stream in big-endian format. + /// + void emitDWordBE(uint64_t W) { + if (8 <= BufferEnd-CurBufferPtr) { + *CurBufferPtr++ = (uint8_t)(W >> 56); + *CurBufferPtr++ = (uint8_t)(W >> 48); + *CurBufferPtr++ = (uint8_t)(W >> 40); + *CurBufferPtr++ = (uint8_t)(W >> 32); + *CurBufferPtr++ = (uint8_t)(W >> 24); + *CurBufferPtr++ = (uint8_t)(W >> 16); + *CurBufferPtr++ = (uint8_t)(W >> 8); + *CurBufferPtr++ = (uint8_t)(W >> 0); + } else { + CurBufferPtr = BufferEnd; + } + } + + /// emitAlignment - Move the CurBufferPtr pointer up the the specified + /// alignment (saturated to BufferEnd of course). + void emitAlignment(unsigned Alignment) { + if (Alignment == 0) Alignment = 1; + uint8_t *NewPtr = (uint8_t*)RoundUpToAlignment((uintptr_t)CurBufferPtr, + Alignment); + CurBufferPtr = std::min(NewPtr, BufferEnd); + } + + /// emitAlignmentWithFill - Similar to emitAlignment, except that the + /// extra bytes are filled with the provided byte. + void emitAlignmentWithFill(unsigned Alignment, uint8_t Fill) { + if (Alignment == 0) Alignment = 1; + uint8_t *NewPtr = (uint8_t*)RoundUpToAlignment((uintptr_t)CurBufferPtr, + Alignment); + // Fail if we don't have room. + if (NewPtr > BufferEnd) { + CurBufferPtr = BufferEnd; + return; + } + while (CurBufferPtr < NewPtr) { + *CurBufferPtr++ = Fill; + } + } + + /// emitULEB128Bytes - This callback is invoked when a ULEB128 needs to be + /// written to the output stream. + void emitULEB128Bytes(uint64_t Value) { + do { + uint8_t Byte = Value & 0x7f; + Value >>= 7; + if (Value) Byte |= 0x80; + emitByte(Byte); + } while (Value); + } + + /// emitSLEB128Bytes - This callback is invoked when a SLEB128 needs to be + /// written to the output stream. + void emitSLEB128Bytes(int64_t Value) { + int32_t Sign = Value >> (8 * sizeof(Value) - 1); + bool IsMore; + + do { + uint8_t Byte = Value & 0x7f; + Value >>= 7; + IsMore = Value != Sign || ((Byte ^ Sign) & 0x40) != 0; + if (IsMore) Byte |= 0x80; + emitByte(Byte); + } while (IsMore); + } + + /// emitString - This callback is invoked when a String needs to be + /// written to the output stream. + void emitString(const std::string &String) { + for (unsigned i = 0, N = static_cast(String.size()); + i < N; ++i) { + uint8_t C = String[i]; + emitByte(C); + } + emitByte(0); + } + + /// emitInt32 - Emit a int32 directive. + void emitInt32(uint32_t Value) { + if (4 <= BufferEnd-CurBufferPtr) { + *((uint32_t*)CurBufferPtr) = Value; + CurBufferPtr += 4; + } else { + CurBufferPtr = BufferEnd; + } + } + + /// emitInt64 - Emit a int64 directive. + void emitInt64(uint64_t Value) { + if (8 <= BufferEnd-CurBufferPtr) { + *((uint64_t*)CurBufferPtr) = Value; + CurBufferPtr += 8; + } else { + CurBufferPtr = BufferEnd; + } + } + + /// emitInt32At - Emit the Int32 Value in Addr. + void emitInt32At(uintptr_t *Addr, uintptr_t Value) { + if (Addr >= (uintptr_t*)BufferBegin && Addr < (uintptr_t*)BufferEnd) + (*(uint32_t*)Addr) = (uint32_t)Value; + } + + /// emitInt64At - Emit the Int64 Value in Addr. + void emitInt64At(uintptr_t *Addr, uintptr_t Value) { + if (Addr >= (uintptr_t*)BufferBegin && Addr < (uintptr_t*)BufferEnd) + (*(uint64_t*)Addr) = (uint64_t)Value; + } + + + /// emitLabel - Emits a label + virtual void emitLabel(uint64_t LabelID) = 0; + + /// allocateSpace - Allocate a block of space in the current output buffer, + /// returning null (and setting conditions to indicate buffer overflow) on + /// failure. Alignment is the alignment in bytes of the buffer desired. + virtual void *allocateSpace(uintptr_t Size, unsigned Alignment) { + emitAlignment(Alignment); + void *Result; + + // Check for buffer overflow. + if (Size >= (uintptr_t)(BufferEnd-CurBufferPtr)) { + CurBufferPtr = BufferEnd; + Result = 0; + } else { + // Allocate the space. + Result = CurBufferPtr; + CurBufferPtr += Size; + } + + return Result; + } + + /// allocateGlobal - Allocate memory for a global. Unlike allocateSpace, + /// this method does not allocate memory in the current output buffer, + /// because a global may live longer than the current function. + virtual void *allocateGlobal(uintptr_t Size, unsigned Alignment) = 0; + + /// StartMachineBasicBlock - This should be called by the target when a new + /// basic block is about to be emitted. This way the MCE knows where the + /// start of the block is, and can implement getMachineBasicBlockAddress. + virtual void StartMachineBasicBlock(MachineBasicBlock *MBB) = 0; + + /// getCurrentPCValue - This returns the address that the next emitted byte + /// will be output to. + /// + virtual uintptr_t getCurrentPCValue() const { + return (uintptr_t)CurBufferPtr; + } + + /// getCurrentPCOffset - Return the offset from the start of the emitted + /// buffer that we are currently writing to. + uintptr_t getCurrentPCOffset() const { + return CurBufferPtr-BufferBegin; + } + + /// earlyResolveAddresses - True if the code emitter can use symbol addresses + /// during code emission time. The JIT is capable of doing this because it + /// creates jump tables or constant pools in memory on the fly while the + /// object code emitters rely on a linker to have real addresses and should + /// use relocations instead. + bool earlyResolveAddresses() const { return true; } + + /// addRelocation - Whenever a relocatable address is needed, it should be + /// noted with this interface. + virtual void addRelocation(const MachineRelocation &MR) = 0; + + /// FIXME: These should all be handled with relocations! + + /// getConstantPoolEntryAddress - Return the address of the 'Index' entry in + /// the constant pool that was last emitted with the emitConstantPool method. + /// + virtual uintptr_t getConstantPoolEntryAddress(unsigned Index) const = 0; + + /// getJumpTableEntryAddress - Return the address of the jump table with index + /// 'Index' in the function that last called initJumpTableInfo. + /// + virtual uintptr_t getJumpTableEntryAddress(unsigned Index) const = 0; + + /// getMachineBasicBlockAddress - Return the address of the specified + /// MachineBasicBlock, only usable after the label for the MBB has been + /// emitted. + /// + virtual uintptr_t getMachineBasicBlockAddress(MachineBasicBlock *MBB) const= 0; + + /// getLabelAddress - Return the address of the specified LabelID, only usable + /// after the LabelID has been emitted. + /// + virtual uintptr_t getLabelAddress(uint64_t LabelID) const = 0; + + /// Specifies the MachineModuleInfo object. This is used for exception handling + /// purposes. + virtual void setModuleInfo(MachineModuleInfo* Info) = 0; +}; + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/CodeGen/LatencyPriorityQueue.h b/libclamav/c++/llvm/include/llvm/CodeGen/LatencyPriorityQueue.h new file mode 100644 index 000000000..7ac0418c9 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/CodeGen/LatencyPriorityQueue.h @@ -0,0 +1,114 @@ +//===---- LatencyPriorityQueue.h - A latency-oriented priority queue ------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the LatencyPriorityQueue class, which is a +// SchedulingPriorityQueue that schedules using latency information to +// reduce the length of the critical path through the basic block. +// +//===----------------------------------------------------------------------===// + +#ifndef LATENCY_PRIORITY_QUEUE_H +#define LATENCY_PRIORITY_QUEUE_H + +#include "llvm/CodeGen/ScheduleDAG.h" +#include "llvm/ADT/PriorityQueue.h" + +namespace llvm { + class LatencyPriorityQueue; + + /// Sorting functions for the Available queue. + struct latency_sort : public std::binary_function { + LatencyPriorityQueue *PQ; + explicit latency_sort(LatencyPriorityQueue *pq) : PQ(pq) {} + + bool operator()(const SUnit* left, const SUnit* right) const; + }; + + class LatencyPriorityQueue : public SchedulingPriorityQueue { + // SUnits - The SUnits for the current graph. + std::vector *SUnits; + + /// NumNodesSolelyBlocking - This vector contains, for every node in the + /// Queue, the number of nodes that the node is the sole unscheduled + /// predecessor for. This is used as a tie-breaker heuristic for better + /// mobility. + std::vector NumNodesSolelyBlocking; + + /// Queue - The queue. + PriorityQueue, latency_sort> Queue; + +public: + LatencyPriorityQueue() : Queue(latency_sort(this)) { + } + + void initNodes(std::vector &sunits) { + SUnits = &sunits; + NumNodesSolelyBlocking.resize(SUnits->size(), 0); + } + + void addNode(const SUnit *SU) { + NumNodesSolelyBlocking.resize(SUnits->size(), 0); + } + + void updateNode(const SUnit *SU) { + } + + void releaseState() { + SUnits = 0; + } + + unsigned getLatency(unsigned NodeNum) const { + assert(NodeNum < (*SUnits).size()); + return (*SUnits)[NodeNum].getHeight(); + } + + unsigned getNumSolelyBlockNodes(unsigned NodeNum) const { + assert(NodeNum < NumNodesSolelyBlocking.size()); + return NumNodesSolelyBlocking[NodeNum]; + } + + unsigned size() const { return Queue.size(); } + + bool empty() const { return Queue.empty(); } + + virtual void push(SUnit *U) { + push_impl(U); + } + void push_impl(SUnit *U); + + void push_all(const std::vector &Nodes) { + for (unsigned i = 0, e = Nodes.size(); i != e; ++i) + push_impl(Nodes[i]); + } + + SUnit *pop() { + if (empty()) return NULL; + SUnit *V = Queue.top(); + Queue.pop(); + return V; + } + + void remove(SUnit *SU) { + assert(!Queue.empty() && "Not in queue!"); + Queue.erase_one(SU); + } + + // ScheduledNode - As nodes are scheduled, we look to see if there are any + // successor nodes that have a single unscheduled predecessor. If so, that + // single predecessor has a higher priority, since scheduling it will make + // the node available. + void ScheduledNode(SUnit *Node); + +private: + void AdjustPriorityOfUnscheduledPreds(SUnit *SU); + SUnit *getSingleUnscheduledPred(SUnit *SU); + }; +} + +#endif diff --git a/libclamav/c++/llvm/include/llvm/CodeGen/LinkAllAsmWriterComponents.h b/libclamav/c++/llvm/include/llvm/CodeGen/LinkAllAsmWriterComponents.h new file mode 100644 index 000000000..7d1b1fe47 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/CodeGen/LinkAllAsmWriterComponents.h @@ -0,0 +1,37 @@ +//===- llvm/Codegen/LinkAllAsmWriterComponents.h ----------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This header file pulls in all assembler writer related passes for tools like +// llc that need this functionality. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_LINKALLASMWRITERCOMPONENTS_H +#define LLVM_CODEGEN_LINKALLASMWRITERCOMPONENTS_H + +#include "llvm/CodeGen/GCs.h" +#include + +namespace { + struct ForceAsmWriterLinking { + ForceAsmWriterLinking() { + // We must reference the plug-ins in such a way that compilers will not + // delete it all as dead code, even with whole program optimization, + // yet is effectively a NO-OP. As the compiler isn't smart enough + // to know that getenv() never returns -1, this will do the job. + if (std::getenv("bar") != (char*) -1) + return; + + llvm::linkOcamlGCPrinter(); + + } + } ForceAsmWriterLinking; // Force link by creating a global definition. +} + +#endif // LLVM_CODEGEN_LINKALLASMWRITERCOMPONENTS_H diff --git a/libclamav/c++/llvm/include/llvm/CodeGen/LinkAllCodegenComponents.h b/libclamav/c++/llvm/include/llvm/CodeGen/LinkAllCodegenComponents.h new file mode 100644 index 000000000..4d2d0eec5 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/CodeGen/LinkAllCodegenComponents.h @@ -0,0 +1,54 @@ +//===- llvm/Codegen/LinkAllCodegenComponents.h ------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This header file pulls in all codegen related passes for tools like lli and +// llc that need this functionality. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_LINKALLCODEGENCOMPONENTS_H +#define LLVM_CODEGEN_LINKALLCODEGENCOMPONENTS_H + +#include "llvm/CodeGen/Passes.h" +#include "llvm/CodeGen/SchedulerRegistry.h" +#include "llvm/CodeGen/GCs.h" +#include "llvm/Target/TargetMachine.h" + +namespace { + struct ForceCodegenLinking { + ForceCodegenLinking() { + // We must reference the passes in such a way that compilers will not + // delete it all as dead code, even with whole program optimization, + // yet is effectively a NO-OP. As the compiler isn't smart enough + // to know that getenv() never returns -1, this will do the job. + if (std::getenv("bar") != (char*) -1) + return; + + (void) llvm::createDeadMachineInstructionElimPass(); + + (void) llvm::createLocalRegisterAllocator(); + (void) llvm::createLinearScanRegisterAllocator(); + (void) llvm::createPBQPRegisterAllocator(); + + (void) llvm::createSimpleRegisterCoalescer(); + + llvm::linkOcamlGC(); + llvm::linkShadowStackGC(); + + (void) llvm::createBURRListDAGScheduler(NULL, llvm::CodeGenOpt::Default); + (void) llvm::createTDRRListDAGScheduler(NULL, llvm::CodeGenOpt::Default); + (void) llvm::createTDListDAGScheduler(NULL, llvm::CodeGenOpt::Default); + (void) llvm::createFastDAGScheduler(NULL, llvm::CodeGenOpt::Default); + (void) llvm::createDefaultScheduler(NULL, llvm::CodeGenOpt::Default); + + } + } ForceCodegenLinking; // Force link by creating a global definition. +} + +#endif diff --git a/libclamav/c++/llvm/include/llvm/CodeGen/LiveInterval.h b/libclamav/c++/llvm/include/llvm/CodeGen/LiveInterval.h new file mode 100644 index 000000000..e31a7f0a2 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/CodeGen/LiveInterval.h @@ -0,0 +1,602 @@ +//===-- llvm/CodeGen/LiveInterval.h - Interval representation ---*- 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 the LiveRange and LiveInterval classes. Given some +// numbering of each the machine instructions an interval [i, j) is said to be a +// live interval for register v if there is no instruction with number j' >= j +// such that v is live at j' and there is no instruction with number i' < i such +// that v is live at i'. In this implementation intervals can have holes, +// i.e. an interval might look like [1,20), [50,65), [1000,1001). Each +// individual range is represented as an instance of LiveRange, and the whole +// interval is represented as an instance of LiveInterval. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_LIVEINTERVAL_H +#define LLVM_CODEGEN_LIVEINTERVAL_H + +#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/Allocator.h" +#include "llvm/Support/AlignOf.h" +#include "llvm/CodeGen/SlotIndexes.h" +#include +#include + +namespace llvm { + class LiveIntervals; + class MachineInstr; + class MachineRegisterInfo; + class TargetRegisterInfo; + class raw_ostream; + + /// VNInfo - Value Number Information. + /// This class holds information about a machine level values, including + /// definition and use points. + /// + /// Care must be taken in interpreting the def index of the value. The + /// following rules apply: + /// + /// If the isDefAccurate() method returns false then def does not contain the + /// index of the defining MachineInstr, or even (necessarily) to a + /// MachineInstr at all. In general such a def index is not meaningful + /// and should not be used. The exception is that, for values originally + /// defined by PHI instructions, after PHI elimination def will contain the + /// index of the MBB in which the PHI originally existed. This can be used + /// to insert code (spills or copies) which deals with the value, which will + /// be live in to the block. + class VNInfo { + private: + enum { + HAS_PHI_KILL = 1, + REDEF_BY_EC = 1 << 1, + IS_PHI_DEF = 1 << 2, + IS_UNUSED = 1 << 3, + IS_DEF_ACCURATE = 1 << 4 + }; + + unsigned char flags; + union { + MachineInstr *copy; + unsigned reg; + } cr; + + public: + + typedef SmallVector KillSet; + + /// The ID number of this value. + unsigned id; + + /// The index of the defining instruction (if isDefAccurate() returns true). + SlotIndex def; + + KillSet kills; + + /* + VNInfo(LiveIntervals &li_) + : defflags(IS_UNUSED), id(~1U) { cr.copy = 0; } + */ + + /// VNInfo constructor. + /// d is presumed to point to the actual defining instr. If it doesn't + /// setIsDefAccurate(false) should be called after construction. + VNInfo(unsigned i, SlotIndex d, MachineInstr *c) + : flags(IS_DEF_ACCURATE), id(i), def(d) { cr.copy = c; } + + /// VNInfo construtor, copies values from orig, except for the value number. + VNInfo(unsigned i, const VNInfo &orig) + : flags(orig.flags), cr(orig.cr), id(i), def(orig.def), kills(orig.kills) + { } + + /// Copy from the parameter into this VNInfo. + void copyFrom(VNInfo &src) { + flags = src.flags; + cr = src.cr; + def = src.def; + kills = src.kills; + } + + /// Used for copying value number info. + unsigned getFlags() const { return flags; } + void setFlags(unsigned flags) { this->flags = flags; } + + /// For a register interval, if this VN was definied by a copy instr + /// getCopy() returns a pointer to it, otherwise returns 0. + /// For a stack interval the behaviour of this method is undefined. + MachineInstr* getCopy() const { return cr.copy; } + /// For a register interval, set the copy member. + /// This method should not be called on stack intervals as it may lead to + /// undefined behavior. + void setCopy(MachineInstr *c) { cr.copy = c; } + + /// For a stack interval, returns the reg which this stack interval was + /// defined from. + /// For a register interval the behaviour of this method is undefined. + unsigned getReg() const { return cr.reg; } + /// For a stack interval, set the defining register. + /// This method should not be called on register intervals as it may lead + /// to undefined behaviour. + void setReg(unsigned reg) { cr.reg = reg; } + + /// Returns true if one or more kills are PHI nodes. + bool hasPHIKill() const { return flags & HAS_PHI_KILL; } + /// Set the PHI kill flag on this value. + void setHasPHIKill(bool hasKill) { + if (hasKill) + flags |= HAS_PHI_KILL; + else + flags &= ~HAS_PHI_KILL; + } + + /// Returns true if this value is re-defined by an early clobber somewhere + /// during the live range. + bool hasRedefByEC() const { return flags & REDEF_BY_EC; } + /// Set the "redef by early clobber" flag on this value. + void setHasRedefByEC(bool hasRedef) { + if (hasRedef) + flags |= REDEF_BY_EC; + else + flags &= ~REDEF_BY_EC; + } + + /// Returns true if this value is defined by a PHI instruction (or was, + /// PHI instrucions may have been eliminated). + bool isPHIDef() const { return flags & IS_PHI_DEF; } + /// Set the "phi def" flag on this value. + void setIsPHIDef(bool phiDef) { + if (phiDef) + flags |= IS_PHI_DEF; + else + flags &= ~IS_PHI_DEF; + } + + /// Returns true if this value is unused. + bool isUnused() const { return flags & IS_UNUSED; } + /// Set the "is unused" flag on this value. + void setIsUnused(bool unused) { + if (unused) + flags |= IS_UNUSED; + else + flags &= ~IS_UNUSED; + } + + /// Returns true if the def is accurate. + bool isDefAccurate() const { return flags & IS_DEF_ACCURATE; } + /// Set the "is def accurate" flag on this value. + void setIsDefAccurate(bool defAccurate) { + if (defAccurate) + flags |= IS_DEF_ACCURATE; + else + flags &= ~IS_DEF_ACCURATE; + } + + /// Returns true if the given index is a kill of this value. + bool isKill(SlotIndex k) const { + KillSet::const_iterator + i = std::lower_bound(kills.begin(), kills.end(), k); + return (i != kills.end() && *i == k); + } + + /// addKill - Add a kill instruction index to the specified value + /// number. + void addKill(SlotIndex k) { + if (kills.empty()) { + kills.push_back(k); + } else { + KillSet::iterator + i = std::lower_bound(kills.begin(), kills.end(), k); + kills.insert(i, k); + } + } + + /// Remove the specified kill index from this value's kills list. + /// Returns true if the value was present, otherwise returns false. + bool removeKill(SlotIndex k) { + KillSet::iterator i = std::lower_bound(kills.begin(), kills.end(), k); + if (i != kills.end() && *i == k) { + kills.erase(i); + return true; + } + return false; + } + + /// Remove all kills in the range [s, e). + void removeKills(SlotIndex s, SlotIndex e) { + KillSet::iterator + si = std::lower_bound(kills.begin(), kills.end(), s), + se = std::upper_bound(kills.begin(), kills.end(), e); + + kills.erase(si, se); + } + + }; + + /// LiveRange structure - This represents a simple register range in the + /// program, with an inclusive start point and an exclusive end point. + /// These ranges are rendered as [start,end). + struct LiveRange { + SlotIndex start; // Start point of the interval (inclusive) + SlotIndex end; // End point of the interval (exclusive) + VNInfo *valno; // identifier for the value contained in this interval. + + LiveRange(SlotIndex S, SlotIndex E, VNInfo *V) + : start(S), end(E), valno(V) { + + assert(S < E && "Cannot create empty or backwards range"); + } + + /// contains - Return true if the index is covered by this range. + /// + bool contains(SlotIndex I) const { + return start <= I && I < end; + } + + /// containsRange - Return true if the given range, [S, E), is covered by + /// this range. + bool containsRange(SlotIndex S, SlotIndex E) const { + assert((S < E) && "Backwards interval?"); + return (start <= S && S < end) && (start < E && E <= end); + } + + bool operator<(const LiveRange &LR) const { + return start < LR.start || (start == LR.start && end < LR.end); + } + bool operator==(const LiveRange &LR) const { + return start == LR.start && end == LR.end; + } + + void dump() const; + void print(raw_ostream &os) const; + + private: + LiveRange(); // DO NOT IMPLEMENT + }; + + raw_ostream& operator<<(raw_ostream& os, const LiveRange &LR); + + + inline bool operator<(SlotIndex V, const LiveRange &LR) { + return V < LR.start; + } + + inline bool operator<(const LiveRange &LR, SlotIndex V) { + return LR.start < V; + } + + /// LiveInterval - This class represents some number of live ranges for a + /// register or value. This class also contains a bit of register allocator + /// state. + class LiveInterval { + public: + + typedef SmallVector Ranges; + typedef SmallVector VNInfoList; + + unsigned reg; // the register or stack slot of this interval + // if the top bits is set, it represents a stack slot. + float weight; // weight of this interval + Ranges ranges; // the ranges in which this register is live + VNInfoList valnos; // value#'s + + struct InstrSlots { + enum { + LOAD = 0, + USE = 1, + DEF = 2, + STORE = 3, + NUM = 4 + }; + + }; + + LiveInterval(unsigned Reg, float Weight, bool IsSS = false) + : reg(Reg), weight(Weight) { + if (IsSS) + reg = reg | (1U << (sizeof(unsigned)*CHAR_BIT-1)); + } + + typedef Ranges::iterator iterator; + iterator begin() { return ranges.begin(); } + iterator end() { return ranges.end(); } + + typedef Ranges::const_iterator const_iterator; + const_iterator begin() const { return ranges.begin(); } + const_iterator end() const { return ranges.end(); } + + typedef VNInfoList::iterator vni_iterator; + vni_iterator vni_begin() { return valnos.begin(); } + vni_iterator vni_end() { return valnos.end(); } + + typedef VNInfoList::const_iterator const_vni_iterator; + const_vni_iterator vni_begin() const { return valnos.begin(); } + const_vni_iterator vni_end() const { return valnos.end(); } + + /// advanceTo - Advance the specified iterator to point to the LiveRange + /// containing the specified position, or end() if the position is past the + /// end of the interval. If no LiveRange contains this position, but the + /// position is in a hole, this method returns an iterator pointing the the + /// LiveRange immediately after the hole. + iterator advanceTo(iterator I, SlotIndex Pos) { + if (Pos >= endIndex()) + return end(); + while (I->end <= Pos) ++I; + return I; + } + + void clear() { + while (!valnos.empty()) { + VNInfo *VNI = valnos.back(); + valnos.pop_back(); + VNI->~VNInfo(); + } + + ranges.clear(); + } + + /// isStackSlot - Return true if this is a stack slot interval. + /// + bool isStackSlot() const { + return reg & (1U << (sizeof(unsigned)*CHAR_BIT-1)); + } + + /// getStackSlotIndex - Return stack slot index if this is a stack slot + /// interval. + int getStackSlotIndex() const { + assert(isStackSlot() && "Interval is not a stack slot interval!"); + return reg & ~(1U << (sizeof(unsigned)*CHAR_BIT-1)); + } + + bool hasAtLeastOneValue() const { return !valnos.empty(); } + + bool containsOneValue() const { return valnos.size() == 1; } + + unsigned getNumValNums() const { return (unsigned)valnos.size(); } + + /// getValNumInfo - Returns pointer to the specified val#. + /// + inline VNInfo *getValNumInfo(unsigned ValNo) { + return valnos[ValNo]; + } + inline const VNInfo *getValNumInfo(unsigned ValNo) const { + return valnos[ValNo]; + } + + /// getNextValue - Create a new value number and return it. MIIdx specifies + /// the instruction that defines the value number. + VNInfo *getNextValue(SlotIndex def, MachineInstr *CopyMI, + bool isDefAccurate, BumpPtrAllocator &VNInfoAllocator){ + VNInfo *VNI = + static_cast(VNInfoAllocator.Allocate((unsigned)sizeof(VNInfo), + alignof())); + new (VNI) VNInfo((unsigned)valnos.size(), def, CopyMI); + VNI->setIsDefAccurate(isDefAccurate); + valnos.push_back(VNI); + return VNI; + } + + /// Create a copy of the given value. The new value will be identical except + /// for the Value number. + VNInfo *createValueCopy(const VNInfo *orig, + BumpPtrAllocator &VNInfoAllocator) { + VNInfo *VNI = + static_cast(VNInfoAllocator.Allocate((unsigned)sizeof(VNInfo), + alignof())); + + new (VNI) VNInfo((unsigned)valnos.size(), *orig); + valnos.push_back(VNI); + return VNI; + } + + /// addKills - Add a number of kills into the VNInfo kill vector. If this + /// interval is live at a kill point, then the kill is not added. + void addKills(VNInfo *VNI, const VNInfo::KillSet &kills) { + for (unsigned i = 0, e = static_cast(kills.size()); + i != e; ++i) { + if (!liveBeforeAndAt(kills[i])) { + VNI->addKill(kills[i]); + } + } + } + + /// isOnlyLROfValNo - Return true if the specified live range is the only + /// one defined by the its val#. + bool isOnlyLROfValNo(const LiveRange *LR) { + for (const_iterator I = begin(), E = end(); I != E; ++I) { + const LiveRange *Tmp = I; + if (Tmp != LR && Tmp->valno == LR->valno) + return false; + } + return true; + } + + /// MergeValueNumberInto - This method is called when two value nubmers + /// are found to be equivalent. This eliminates V1, replacing all + /// LiveRanges with the V1 value number with the V2 value number. This can + /// cause merging of V1/V2 values numbers and compaction of the value space. + VNInfo* MergeValueNumberInto(VNInfo *V1, VNInfo *V2); + + /// MergeInClobberRanges - For any live ranges that are not defined in the + /// current interval, but are defined in the Clobbers interval, mark them + /// used with an unknown definition value. Caller must pass in reference to + /// VNInfoAllocator since it will create a new val#. + void MergeInClobberRanges(LiveIntervals &li_, + const LiveInterval &Clobbers, + BumpPtrAllocator &VNInfoAllocator); + + /// MergeInClobberRange - Same as MergeInClobberRanges except it merge in a + /// single LiveRange only. + void MergeInClobberRange(LiveIntervals &li_, + SlotIndex Start, + SlotIndex End, + BumpPtrAllocator &VNInfoAllocator); + + /// MergeValueInAsValue - Merge all of the live ranges of a specific val# + /// in RHS into this live interval as the specified value number. + /// The LiveRanges in RHS are allowed to overlap with LiveRanges in the + /// current interval, it will replace the value numbers of the overlaped + /// live ranges with the specified value number. + void MergeRangesInAsValue(const LiveInterval &RHS, VNInfo *LHSValNo); + + /// MergeValueInAsValue - Merge all of the live ranges of a specific val# + /// in RHS into this live interval as the specified value number. + /// The LiveRanges in RHS are allowed to overlap with LiveRanges in the + /// current interval, but only if the overlapping LiveRanges have the + /// specified value number. + void MergeValueInAsValue(const LiveInterval &RHS, + const VNInfo *RHSValNo, VNInfo *LHSValNo); + + /// Copy - Copy the specified live interval. This copies all the fields + /// except for the register of the interval. + void Copy(const LiveInterval &RHS, MachineRegisterInfo *MRI, + BumpPtrAllocator &VNInfoAllocator); + + bool empty() const { return ranges.empty(); } + + /// beginIndex - Return the lowest numbered slot covered by interval. + SlotIndex beginIndex() const { + assert(!empty() && "Call to beginIndex() on empty interval."); + return ranges.front().start; + } + + /// endNumber - return the maximum point of the interval of the whole, + /// exclusive. + SlotIndex endIndex() const { + assert(!empty() && "Call to endIndex() on empty interval."); + return ranges.back().end; + } + + bool expiredAt(SlotIndex index) const { + return index >= endIndex(); + } + + bool liveAt(SlotIndex index) const; + + // liveBeforeAndAt - Check if the interval is live at the index and the + // index just before it. If index is liveAt, check if it starts a new live + // range.If it does, then check if the previous live range ends at index-1. + bool liveBeforeAndAt(SlotIndex index) const; + + /// getLiveRangeContaining - Return the live range that contains the + /// specified index, or null if there is none. + const LiveRange *getLiveRangeContaining(SlotIndex Idx) const { + const_iterator I = FindLiveRangeContaining(Idx); + return I == end() ? 0 : &*I; + } + + /// getLiveRangeContaining - Return the live range that contains the + /// specified index, or null if there is none. + LiveRange *getLiveRangeContaining(SlotIndex Idx) { + iterator I = FindLiveRangeContaining(Idx); + return I == end() ? 0 : &*I; + } + + /// FindLiveRangeContaining - Return an iterator to the live range that + /// contains the specified index, or end() if there is none. + const_iterator FindLiveRangeContaining(SlotIndex Idx) const; + + /// FindLiveRangeContaining - Return an iterator to the live range that + /// contains the specified index, or end() if there is none. + iterator FindLiveRangeContaining(SlotIndex Idx); + + /// findDefinedVNInfo - Find the by the specified + /// index (register interval) or defined + VNInfo *findDefinedVNInfoForRegInt(SlotIndex Idx) const; + + /// findDefinedVNInfo - Find the VNInfo that's defined by the specified + /// register (stack inteval only). + VNInfo *findDefinedVNInfoForStackInt(unsigned Reg) const; + + + /// overlaps - Return true if the intersection of the two live intervals is + /// not empty. + bool overlaps(const LiveInterval& other) const { + return overlapsFrom(other, other.begin()); + } + + /// overlaps - Return true if the live interval overlaps a range specified + /// by [Start, End). + bool overlaps(SlotIndex Start, SlotIndex End) const; + + /// overlapsFrom - Return true if the intersection of the two live intervals + /// is not empty. The specified iterator is a hint that we can begin + /// scanning the Other interval starting at I. + bool overlapsFrom(const LiveInterval& other, const_iterator I) const; + + /// addRange - Add the specified LiveRange to this interval, merging + /// intervals as appropriate. This returns an iterator to the inserted live + /// range (which may have grown since it was inserted. + void addRange(LiveRange LR) { + addRangeFrom(LR, ranges.begin()); + } + + /// join - Join two live intervals (this, and other) together. This applies + /// mappings to the value numbers in the LHS/RHS intervals as specified. If + /// the intervals are not joinable, this aborts. + void join(LiveInterval &Other, + const int *ValNoAssignments, + const int *RHSValNoAssignments, + SmallVector &NewVNInfo, + MachineRegisterInfo *MRI); + + /// isInOneLiveRange - Return true if the range specified is entirely in the + /// a single LiveRange of the live interval. + bool isInOneLiveRange(SlotIndex Start, SlotIndex End); + + /// removeRange - Remove the specified range from this interval. Note that + /// the range must be a single LiveRange in its entirety. + void removeRange(SlotIndex Start, SlotIndex End, + bool RemoveDeadValNo = false); + + void removeRange(LiveRange LR, bool RemoveDeadValNo = false) { + removeRange(LR.start, LR.end, RemoveDeadValNo); + } + + /// removeValNo - Remove all the ranges defined by the specified value#. + /// Also remove the value# from value# list. + void removeValNo(VNInfo *ValNo); + + /// scaleNumbering - Renumber VNI and ranges to provide gaps for new + /// instructions. + void scaleNumbering(unsigned factor); + + /// getSize - Returns the sum of sizes of all the LiveRange's. + /// + unsigned getSize() const; + + /// ComputeJoinedWeight - Set the weight of a live interval after + /// Other has been merged into it. + void ComputeJoinedWeight(const LiveInterval &Other); + + bool operator<(const LiveInterval& other) const { + const SlotIndex &thisIndex = beginIndex(); + const SlotIndex &otherIndex = other.beginIndex(); + return (thisIndex < otherIndex || + (thisIndex == otherIndex && reg < other.reg)); + } + + void print(raw_ostream &OS, const TargetRegisterInfo *TRI = 0) const; + void dump() const; + + private: + + Ranges::iterator addRangeFrom(LiveRange LR, Ranges::iterator From); + void extendIntervalEndTo(Ranges::iterator I, SlotIndex NewEnd); + Ranges::iterator extendIntervalStartTo(Ranges::iterator I, SlotIndex NewStr); + + LiveInterval& operator=(const LiveInterval& rhs); // DO NOT IMPLEMENT + + }; + + inline raw_ostream &operator<<(raw_ostream &OS, const LiveInterval &LI) { + LI.print(OS); + return OS; + } +} + +#endif diff --git a/libclamav/c++/llvm/include/llvm/CodeGen/LiveIntervalAnalysis.h b/libclamav/c++/llvm/include/llvm/CodeGen/LiveIntervalAnalysis.h new file mode 100644 index 000000000..7a02d0fe9 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/CodeGen/LiveIntervalAnalysis.h @@ -0,0 +1,412 @@ +//===-- LiveIntervalAnalysis.h - Live Interval Analysis ---------*- 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 the LiveInterval analysis pass. Given some numbering of +// each the machine instructions (in this implemention depth-first order) an +// interval [i, j) is said to be a live interval for register v if there is no +// instruction with number j' > j such that v is live at j' and there is no +// instruction with number i' < i such that v is live at i'. In this +// implementation intervals can have holes, i.e. an interval might look like +// [1,20), [50,65), [1000,1001). +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_LIVEINTERVAL_ANALYSIS_H +#define LLVM_CODEGEN_LIVEINTERVAL_ANALYSIS_H + +#include "llvm/CodeGen/MachineBasicBlock.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/LiveInterval.h" +#include "llvm/CodeGen/SlotIndexes.h" +#include "llvm/ADT/BitVector.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/Allocator.h" +#include +#include + +namespace llvm { + + class AliasAnalysis; + class LiveVariables; + class MachineLoopInfo; + class TargetRegisterInfo; + class MachineRegisterInfo; + class TargetInstrInfo; + class TargetRegisterClass; + class VirtRegMap; + + class LiveIntervals : public MachineFunctionPass { + MachineFunction* mf_; + MachineRegisterInfo* mri_; + const TargetMachine* tm_; + const TargetRegisterInfo* tri_; + const TargetInstrInfo* tii_; + AliasAnalysis *aa_; + LiveVariables* lv_; + SlotIndexes* indexes_; + + /// Special pool allocator for VNInfo's (LiveInterval val#). + /// + BumpPtrAllocator VNInfoAllocator; + + typedef DenseMap Reg2IntervalMap; + Reg2IntervalMap r2iMap_; + + /// allocatableRegs_ - A bit vector of allocatable registers. + BitVector allocatableRegs_; + + /// CloneMIs - A list of clones as result of re-materialization. + std::vector CloneMIs; + + public: + static char ID; // Pass identification, replacement for typeid + LiveIntervals() : MachineFunctionPass(&ID) {} + + static float getSpillWeight(bool isDef, bool isUse, unsigned loopDepth) { + return (isDef + isUse) * powf(10.0F, (float)loopDepth); + } + + typedef Reg2IntervalMap::iterator iterator; + typedef Reg2IntervalMap::const_iterator const_iterator; + const_iterator begin() const { return r2iMap_.begin(); } + const_iterator end() const { return r2iMap_.end(); } + iterator begin() { return r2iMap_.begin(); } + iterator end() { return r2iMap_.end(); } + unsigned getNumIntervals() const { return (unsigned)r2iMap_.size(); } + + LiveInterval &getInterval(unsigned reg) { + Reg2IntervalMap::iterator I = r2iMap_.find(reg); + assert(I != r2iMap_.end() && "Interval does not exist for register"); + return *I->second; + } + + const LiveInterval &getInterval(unsigned reg) const { + Reg2IntervalMap::const_iterator I = r2iMap_.find(reg); + assert(I != r2iMap_.end() && "Interval does not exist for register"); + return *I->second; + } + + bool hasInterval(unsigned reg) const { + return r2iMap_.count(reg); + } + + /// getScaledIntervalSize - get the size of an interval in "units," + /// where every function is composed of one thousand units. This + /// measure scales properly with empty index slots in the function. + double getScaledIntervalSize(LiveInterval& I) { + return (1000.0 * I.getSize()) / indexes_->getIndexesLength(); + } + + /// getApproximateInstructionCount - computes an estimate of the number + /// of instructions in a given LiveInterval. + unsigned getApproximateInstructionCount(LiveInterval& I) { + double IntervalPercentage = getScaledIntervalSize(I) / 1000.0; + return (unsigned)(IntervalPercentage * indexes_->getFunctionSize()); + } + + /// conflictsWithPhysRegDef - Returns true if the specified register + /// is defined during the duration of the specified interval. + bool conflictsWithPhysRegDef(const LiveInterval &li, VirtRegMap &vrm, + unsigned reg); + + /// conflictsWithPhysRegRef - Similar to conflictsWithPhysRegRef except + /// it can check use as well. + bool conflictsWithPhysRegRef(LiveInterval &li, unsigned Reg, + bool CheckUse, + SmallPtrSet &JoinedCopies); + + // Interval creation + LiveInterval &getOrCreateInterval(unsigned reg) { + Reg2IntervalMap::iterator I = r2iMap_.find(reg); + if (I == r2iMap_.end()) + I = r2iMap_.insert(std::make_pair(reg, createInterval(reg))).first; + return *I->second; + } + + /// dupInterval - Duplicate a live interval. The caller is responsible for + /// managing the allocated memory. + LiveInterval *dupInterval(LiveInterval *li); + + /// addLiveRangeToEndOfBlock - Given a register and an instruction, + /// adds a live range from that instruction to the end of its MBB. + LiveRange addLiveRangeToEndOfBlock(unsigned reg, + MachineInstr* startInst); + + // Interval removal + + void removeInterval(unsigned Reg) { + DenseMap::iterator I = r2iMap_.find(Reg); + delete I->second; + r2iMap_.erase(I); + } + + SlotIndex getZeroIndex() const { + return indexes_->getZeroIndex(); + } + + SlotIndex getInvalidIndex() const { + return indexes_->getInvalidIndex(); + } + + /// isNotInMIMap - returns true if the specified machine instr has been + /// removed or was never entered in the map. + bool isNotInMIMap(const MachineInstr* Instr) const { + return !indexes_->hasIndex(Instr); + } + + /// Returns the base index of the given instruction. + SlotIndex getInstructionIndex(const MachineInstr *instr) const { + return indexes_->getInstructionIndex(instr); + } + + /// Returns the instruction associated with the given index. + MachineInstr* getInstructionFromIndex(SlotIndex index) const { + return indexes_->getInstructionFromIndex(index); + } + + /// Return the first index in the given basic block. + SlotIndex getMBBStartIdx(const MachineBasicBlock *mbb) const { + return indexes_->getMBBStartIdx(mbb); + } + + /// Return the last index in the given basic block. + SlotIndex getMBBEndIdx(const MachineBasicBlock *mbb) const { + return indexes_->getMBBEndIdx(mbb); + } + + MachineBasicBlock* getMBBFromIndex(SlotIndex index) const { + return indexes_->getMBBFromIndex(index); + } + + SlotIndex InsertMachineInstrInMaps(MachineInstr *MI) { + return indexes_->insertMachineInstrInMaps(MI); + } + + void RemoveMachineInstrFromMaps(MachineInstr *MI) { + indexes_->removeMachineInstrFromMaps(MI); + } + + void ReplaceMachineInstrInMaps(MachineInstr *MI, MachineInstr *NewMI) { + indexes_->replaceMachineInstrInMaps(MI, NewMI); + } + + bool findLiveInMBBs(SlotIndex Start, SlotIndex End, + SmallVectorImpl &MBBs) const { + return indexes_->findLiveInMBBs(Start, End, MBBs); + } + + void renumber() { + indexes_->renumberIndexes(); + } + + BumpPtrAllocator& getVNInfoAllocator() { return VNInfoAllocator; } + + /// getVNInfoSourceReg - Helper function that parses the specified VNInfo + /// copy field and returns the source register that defines it. + unsigned getVNInfoSourceReg(const VNInfo *VNI) const; + + virtual void getAnalysisUsage(AnalysisUsage &AU) const; + virtual void releaseMemory(); + + /// runOnMachineFunction - pass entry point + virtual bool runOnMachineFunction(MachineFunction&); + + /// print - Implement the dump method. + virtual void print(raw_ostream &O, const Module* = 0) const; + + /// addIntervalsForSpills - Create new intervals for spilled defs / uses of + /// the given interval. FIXME: It also returns the weight of the spill slot + /// (if any is created) by reference. This is temporary. + std::vector + addIntervalsForSpills(const LiveInterval& i, + SmallVectorImpl &SpillIs, + const MachineLoopInfo *loopInfo, VirtRegMap& vrm); + + /// addIntervalsForSpillsFast - Quickly create new intervals for spilled + /// defs / uses without remat or splitting. + std::vector + addIntervalsForSpillsFast(const LiveInterval &li, + const MachineLoopInfo *loopInfo, VirtRegMap &vrm); + + /// spillPhysRegAroundRegDefsUses - Spill the specified physical register + /// around all defs and uses of the specified interval. Return true if it + /// was able to cut its interval. + bool spillPhysRegAroundRegDefsUses(const LiveInterval &li, + unsigned PhysReg, VirtRegMap &vrm); + + /// isReMaterializable - Returns true if every definition of MI of every + /// val# of the specified interval is re-materializable. Also returns true + /// by reference if all of the defs are load instructions. + bool isReMaterializable(const LiveInterval &li, + SmallVectorImpl &SpillIs, + bool &isLoad); + + /// isReMaterializable - Returns true if the definition MI of the specified + /// val# of the specified interval is re-materializable. + bool isReMaterializable(const LiveInterval &li, const VNInfo *ValNo, + MachineInstr *MI); + + /// getRepresentativeReg - Find the largest super register of the specified + /// physical register. + unsigned getRepresentativeReg(unsigned Reg) const; + + /// getNumConflictsWithPhysReg - Return the number of uses and defs of the + /// specified interval that conflicts with the specified physical register. + unsigned getNumConflictsWithPhysReg(const LiveInterval &li, + unsigned PhysReg) const; + + /// processImplicitDefs - Process IMPLICIT_DEF instructions. Add isUndef + /// marker to implicit_def defs and their uses. + void processImplicitDefs(); + + /// intervalIsInOneMBB - Returns true if the specified interval is entirely + /// within a single basic block. + bool intervalIsInOneMBB(const LiveInterval &li) const; + + private: + /// computeIntervals - Compute live intervals. + void computeIntervals(); + + /// handleRegisterDef - update intervals for a register def + /// (calls handlePhysicalRegisterDef and + /// handleVirtualRegisterDef) + void handleRegisterDef(MachineBasicBlock *MBB, + MachineBasicBlock::iterator MI, + SlotIndex MIIdx, + MachineOperand& MO, unsigned MOIdx); + + /// handleVirtualRegisterDef - update intervals for a virtual + /// register def + void handleVirtualRegisterDef(MachineBasicBlock *MBB, + MachineBasicBlock::iterator MI, + SlotIndex MIIdx, MachineOperand& MO, + unsigned MOIdx, + LiveInterval& interval); + + /// handlePhysicalRegisterDef - update intervals for a physical register + /// def. + void handlePhysicalRegisterDef(MachineBasicBlock* mbb, + MachineBasicBlock::iterator mi, + SlotIndex MIIdx, MachineOperand& MO, + LiveInterval &interval, + MachineInstr *CopyMI); + + /// handleLiveInRegister - Create interval for a livein register. + void handleLiveInRegister(MachineBasicBlock* mbb, + SlotIndex MIIdx, + LiveInterval &interval, bool isAlias = false); + + /// getReMatImplicitUse - If the remat definition MI has one (for now, we + /// only allow one) virtual register operand, then its uses are implicitly + /// using the register. Returns the virtual register. + unsigned getReMatImplicitUse(const LiveInterval &li, + MachineInstr *MI) const; + + /// isValNoAvailableAt - Return true if the val# of the specified interval + /// which reaches the given instruction also reaches the specified use + /// index. + bool isValNoAvailableAt(const LiveInterval &li, MachineInstr *MI, + SlotIndex UseIdx) const; + + /// isReMaterializable - Returns true if the definition MI of the specified + /// val# of the specified interval is re-materializable. Also returns true + /// by reference if the def is a load. + bool isReMaterializable(const LiveInterval &li, const VNInfo *ValNo, + MachineInstr *MI, + SmallVectorImpl &SpillIs, + bool &isLoad); + + /// tryFoldMemoryOperand - Attempts to fold either a spill / restore from + /// slot / to reg or any rematerialized load into ith operand of specified + /// MI. If it is successul, MI is updated with the newly created MI and + /// returns true. + bool tryFoldMemoryOperand(MachineInstr* &MI, VirtRegMap &vrm, + MachineInstr *DefMI, SlotIndex InstrIdx, + SmallVector &Ops, + bool isSS, int FrameIndex, unsigned Reg); + + /// canFoldMemoryOperand - Return true if the specified load / store + /// folding is possible. + bool canFoldMemoryOperand(MachineInstr *MI, + SmallVector &Ops, + bool ReMatLoadSS) const; + + /// anyKillInMBBAfterIdx - Returns true if there is a kill of the specified + /// VNInfo that's after the specified index but is within the basic block. + bool anyKillInMBBAfterIdx(const LiveInterval &li, const VNInfo *VNI, + MachineBasicBlock *MBB, + SlotIndex Idx) const; + + /// hasAllocatableSuperReg - Return true if the specified physical register + /// has any super register that's allocatable. + bool hasAllocatableSuperReg(unsigned Reg) const; + + /// SRInfo - Spill / restore info. + struct SRInfo { + SlotIndex index; + unsigned vreg; + bool canFold; + SRInfo(SlotIndex i, unsigned vr, bool f) + : index(i), vreg(vr), canFold(f) {} + }; + + bool alsoFoldARestore(int Id, SlotIndex index, unsigned vr, + BitVector &RestoreMBBs, + DenseMap >&RestoreIdxes); + void eraseRestoreInfo(int Id, SlotIndex index, unsigned vr, + BitVector &RestoreMBBs, + DenseMap >&RestoreIdxes); + + /// handleSpilledImpDefs - Remove IMPLICIT_DEF instructions which are being + /// spilled and create empty intervals for their uses. + void handleSpilledImpDefs(const LiveInterval &li, VirtRegMap &vrm, + const TargetRegisterClass* rc, + std::vector &NewLIs); + + /// rewriteImplicitOps - Rewrite implicit use operands of MI (i.e. uses of + /// interval on to-be re-materialized operands of MI) with new register. + void rewriteImplicitOps(const LiveInterval &li, + MachineInstr *MI, unsigned NewVReg, VirtRegMap &vrm); + + /// rewriteInstructionForSpills, rewriteInstructionsForSpills - Helper + /// functions for addIntervalsForSpills to rewrite uses / defs for the given + /// live range. + bool rewriteInstructionForSpills(const LiveInterval &li, const VNInfo *VNI, + bool TrySplit, SlotIndex index, SlotIndex end, + MachineInstr *MI, MachineInstr *OrigDefMI, MachineInstr *DefMI, + unsigned Slot, int LdSlot, + bool isLoad, bool isLoadSS, bool DefIsReMat, bool CanDelete, + VirtRegMap &vrm, const TargetRegisterClass* rc, + SmallVector &ReMatIds, const MachineLoopInfo *loopInfo, + unsigned &NewVReg, unsigned ImpUse, bool &HasDef, bool &HasUse, + DenseMap &MBBVRegsMap, + std::vector &NewLIs); + void rewriteInstructionsForSpills(const LiveInterval &li, bool TrySplit, + LiveInterval::Ranges::const_iterator &I, + MachineInstr *OrigDefMI, MachineInstr *DefMI, unsigned Slot, int LdSlot, + bool isLoad, bool isLoadSS, bool DefIsReMat, bool CanDelete, + VirtRegMap &vrm, const TargetRegisterClass* rc, + SmallVector &ReMatIds, const MachineLoopInfo *loopInfo, + BitVector &SpillMBBs, + DenseMap > &SpillIdxes, + BitVector &RestoreMBBs, + DenseMap > &RestoreIdxes, + DenseMap &MBBVRegsMap, + std::vector &NewLIs); + + static LiveInterval* createInterval(unsigned Reg); + + void printInstrs(raw_ostream &O) const; + void dumpInstrs() const; + }; +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/CodeGen/LiveStackAnalysis.h b/libclamav/c++/llvm/include/llvm/CodeGen/LiveStackAnalysis.h new file mode 100644 index 000000000..e01d1aea7 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/CodeGen/LiveStackAnalysis.h @@ -0,0 +1,107 @@ +//===-- LiveStackAnalysis.h - Live Stack Slot Analysis ----------*- 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 the live stack slot analysis pass. It is analogous to +// live interval analysis except it's analyzing liveness of stack slots rather +// than registers. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_LIVESTACK_ANALYSIS_H +#define LLVM_CODEGEN_LIVESTACK_ANALYSIS_H + +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/LiveInterval.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Support/Allocator.h" +#include + +namespace llvm { + + class LiveStacks : public MachineFunctionPass { + /// Special pool allocator for VNInfo's (LiveInterval val#). + /// + BumpPtrAllocator VNInfoAllocator; + + /// S2IMap - Stack slot indices to live interval mapping. + /// + typedef std::map SS2IntervalMap; + SS2IntervalMap S2IMap; + + /// S2RCMap - Stack slot indices to register class mapping. + std::map S2RCMap; + + public: + static char ID; // Pass identification, replacement for typeid + LiveStacks() : MachineFunctionPass(&ID) {} + + typedef SS2IntervalMap::iterator iterator; + typedef SS2IntervalMap::const_iterator const_iterator; + const_iterator begin() const { return S2IMap.begin(); } + const_iterator end() const { return S2IMap.end(); } + iterator begin() { return S2IMap.begin(); } + iterator end() { return S2IMap.end(); } + + unsigned getNumIntervals() const { return (unsigned)S2IMap.size(); } + + LiveInterval &getOrCreateInterval(int Slot, const TargetRegisterClass *RC) { + assert(Slot >= 0 && "Spill slot indice must be >= 0"); + SS2IntervalMap::iterator I = S2IMap.find(Slot); + if (I == S2IMap.end()) { + I = S2IMap.insert(I,std::make_pair(Slot, LiveInterval(Slot,0.0F,true))); + S2RCMap.insert(std::make_pair(Slot, RC)); + } else { + // Use the largest common subclass register class. + const TargetRegisterClass *OldRC = S2RCMap[Slot]; + S2RCMap[Slot] = getCommonSubClass(OldRC, RC); + } + return I->second; + } + + LiveInterval &getInterval(int Slot) { + assert(Slot >= 0 && "Spill slot indice must be >= 0"); + SS2IntervalMap::iterator I = S2IMap.find(Slot); + assert(I != S2IMap.end() && "Interval does not exist for stack slot"); + return I->second; + } + + const LiveInterval &getInterval(int Slot) const { + assert(Slot >= 0 && "Spill slot indice must be >= 0"); + SS2IntervalMap::const_iterator I = S2IMap.find(Slot); + assert(I != S2IMap.end() && "Interval does not exist for stack slot"); + return I->second; + } + + bool hasInterval(int Slot) const { + return S2IMap.count(Slot); + } + + const TargetRegisterClass *getIntervalRegClass(int Slot) const { + assert(Slot >= 0 && "Spill slot indice must be >= 0"); + std::map::const_iterator + I = S2RCMap.find(Slot); + assert(I != S2RCMap.end() && + "Register class info does not exist for stack slot"); + return I->second; + } + + BumpPtrAllocator& getVNInfoAllocator() { return VNInfoAllocator; } + + virtual void getAnalysisUsage(AnalysisUsage &AU) const; + virtual void releaseMemory(); + + /// runOnMachineFunction - pass entry point + virtual bool runOnMachineFunction(MachineFunction&); + + /// print - Implement the dump method. + virtual void print(raw_ostream &O, const Module* = 0) const; + }; +} + +#endif /* LLVM_CODEGEN_LIVESTACK_ANALYSIS_H */ diff --git a/libclamav/c++/llvm/include/llvm/CodeGen/LiveVariables.h b/libclamav/c++/llvm/include/llvm/CodeGen/LiveVariables.h new file mode 100644 index 000000000..a37abd464 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/CodeGen/LiveVariables.h @@ -0,0 +1,292 @@ +//===-- llvm/CodeGen/LiveVariables.h - Live Variable Analysis ---*- 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 the LiveVariables analysis pass. For each machine +// instruction in the function, this pass calculates the set of registers that +// are immediately dead after the instruction (i.e., the instruction calculates +// the value, but it is never used) and the set of registers that are used by +// the instruction, but are never used after the instruction (i.e., they are +// killed). +// +// This class computes live variables using a sparse implementation based on +// the machine code SSA form. This class computes live variable information for +// each virtual and _register allocatable_ physical register in a function. It +// uses the dominance properties of SSA form to efficiently compute live +// variables for virtual registers, and assumes that physical registers are only +// live within a single basic block (allowing it to do a single local analysis +// to resolve physical register lifetimes in each basic block). If a physical +// register is not register allocatable, it is not tracked. This is useful for +// things like the stack pointer and condition codes. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_LIVEVARIABLES_H +#define LLVM_CODEGEN_LIVEVARIABLES_H + +#include "llvm/CodeGen/MachineBasicBlock.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/ADT/BitVector.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallSet.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/SparseBitVector.h" + +namespace llvm { + +class MachineRegisterInfo; +class TargetRegisterInfo; + +class LiveVariables : public MachineFunctionPass { +public: + static char ID; // Pass identification, replacement for typeid + LiveVariables() : MachineFunctionPass(&ID) {} + + /// VarInfo - This represents the regions where a virtual register is live in + /// the program. We represent this with three different pieces of + /// information: the set of blocks in which the instruction is live + /// throughout, the set of blocks in which the instruction is actually used, + /// and the set of non-phi instructions that are the last users of the value. + /// + /// In the common case where a value is defined and killed in the same block, + /// There is one killing instruction, and AliveBlocks is empty. + /// + /// Otherwise, the value is live out of the block. If the value is live + /// throughout any blocks, these blocks are listed in AliveBlocks. Blocks + /// where the liveness range ends are not included in AliveBlocks, instead + /// being captured by the Kills set. In these blocks, the value is live into + /// the block (unless the value is defined and killed in the same block) and + /// lives until the specified instruction. Note that there cannot ever be a + /// value whose Kills set contains two instructions from the same basic block. + /// + /// PHI nodes complicate things a bit. If a PHI node is the last user of a + /// value in one of its predecessor blocks, it is not listed in the kills set, + /// but does include the predecessor block in the AliveBlocks set (unless that + /// block also defines the value). This leads to the (perfectly sensical) + /// situation where a value is defined in a block, and the last use is a phi + /// node in the successor. In this case, AliveBlocks is empty (the value is + /// not live across any blocks) and Kills is empty (phi nodes are not + /// included). This is sensical because the value must be live to the end of + /// the block, but is not live in any successor blocks. + struct VarInfo { + /// AliveBlocks - Set of blocks in which this value is alive completely + /// through. This is a bit set which uses the basic block number as an + /// index. + /// + SparseBitVector<> AliveBlocks; + + /// NumUses - Number of uses of this register across the entire function. + /// + unsigned NumUses; + + /// Kills - List of MachineInstruction's which are the last use of this + /// virtual register (kill it) in their basic block. + /// + std::vector Kills; + + VarInfo() : NumUses(0) {} + + /// removeKill - Delete a kill corresponding to the specified + /// machine instruction. Returns true if there was a kill + /// corresponding to this instruction, false otherwise. + bool removeKill(MachineInstr *MI) { + std::vector::iterator + I = std::find(Kills.begin(), Kills.end(), MI); + if (I == Kills.end()) + return false; + Kills.erase(I); + return true; + } + + /// findKill - Find a kill instruction in MBB. Return NULL if none is found. + MachineInstr *findKill(const MachineBasicBlock *MBB) const; + + /// isLiveIn - Is Reg live in to MBB? This means that Reg is live through + /// MBB, or it is killed in MBB. If Reg is only used by PHI instructions in + /// MBB, it is not considered live in. + bool isLiveIn(const MachineBasicBlock &MBB, + unsigned Reg, + MachineRegisterInfo &MRI); + + void dump() const; + }; + +private: + /// VirtRegInfo - This list is a mapping from virtual register number to + /// variable information. FirstVirtualRegister is subtracted from the virtual + /// register number before indexing into this list. + /// + std::vector VirtRegInfo; + + /// ReservedRegisters - This vector keeps track of which registers + /// are reserved register which are not allocatable by the target machine. + /// We can not track liveness for values that are in this set. + /// + BitVector ReservedRegisters; + +private: // Intermediate data structures + MachineFunction *MF; + + MachineRegisterInfo* MRI; + + const TargetRegisterInfo *TRI; + + // PhysRegInfo - Keep track of which instruction was the last def of a + // physical register. This is a purely local property, because all physical + // register references are presumed dead across basic blocks. + MachineInstr **PhysRegDef; + + // PhysRegInfo - Keep track of which instruction was the last use of a + // physical register. This is a purely local property, because all physical + // register references are presumed dead across basic blocks. + MachineInstr **PhysRegUse; + + SmallVector *PHIVarInfo; + + // DistanceMap - Keep track the distance of a MI from the start of the + // current basic block. + DenseMap DistanceMap; + + /// HandlePhysRegKill - Add kills of Reg and its sub-registers to the + /// uses. Pay special attention to the sub-register uses which may come below + /// the last use of the whole register. + bool HandlePhysRegKill(unsigned Reg, MachineInstr *MI); + + void HandlePhysRegUse(unsigned Reg, MachineInstr *MI); + void HandlePhysRegDef(unsigned Reg, MachineInstr *MI, + SmallVector &Defs); + void UpdatePhysRegDefs(MachineInstr *MI, SmallVector &Defs); + + /// FindLastPartialDef - Return the last partial def of the specified register. + /// Also returns the sub-registers that're defined by the instruction. + MachineInstr *FindLastPartialDef(unsigned Reg, + SmallSet &PartDefRegs); + + /// analyzePHINodes - Gather information about the PHI nodes in here. In + /// particular, we want to map the variable information of a virtual + /// register which is used in a PHI node. We map that to the BB the vreg + /// is coming from. + void analyzePHINodes(const MachineFunction& Fn); +public: + + virtual bool runOnMachineFunction(MachineFunction &MF); + + /// RegisterDefIsDead - Return true if the specified instruction defines the + /// specified register, but that definition is dead. + bool RegisterDefIsDead(MachineInstr *MI, unsigned Reg) const; + + //===--------------------------------------------------------------------===// + // API to update live variable information + + /// replaceKillInstruction - Update register kill info by replacing a kill + /// instruction with a new one. + void replaceKillInstruction(unsigned Reg, MachineInstr *OldMI, + MachineInstr *NewMI); + + /// addVirtualRegisterKilled - Add information about the fact that the + /// specified register is killed after being used by the specified + /// instruction. If AddIfNotFound is true, add a implicit operand if it's + /// not found. + void addVirtualRegisterKilled(unsigned IncomingReg, MachineInstr *MI, + bool AddIfNotFound = false) { + if (MI->addRegisterKilled(IncomingReg, TRI, AddIfNotFound)) + getVarInfo(IncomingReg).Kills.push_back(MI); + } + + /// removeVirtualRegisterKilled - Remove the specified kill of the virtual + /// register from the live variable information. Returns true if the + /// variable was marked as killed by the specified instruction, + /// false otherwise. + bool removeVirtualRegisterKilled(unsigned reg, MachineInstr *MI) { + if (!getVarInfo(reg).removeKill(MI)) + return false; + + bool Removed = false; + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + MachineOperand &MO = MI->getOperand(i); + if (MO.isReg() && MO.isKill() && MO.getReg() == reg) { + MO.setIsKill(false); + Removed = true; + break; + } + } + + assert(Removed && "Register is not used by this instruction!"); + return true; + } + + /// removeVirtualRegistersKilled - Remove all killed info for the specified + /// instruction. + void removeVirtualRegistersKilled(MachineInstr *MI); + + /// addVirtualRegisterDead - Add information about the fact that the specified + /// register is dead after being used by the specified instruction. If + /// AddIfNotFound is true, add a implicit operand if it's not found. + void addVirtualRegisterDead(unsigned IncomingReg, MachineInstr *MI, + bool AddIfNotFound = false) { + if (MI->addRegisterDead(IncomingReg, TRI, AddIfNotFound)) + getVarInfo(IncomingReg).Kills.push_back(MI); + } + + /// removeVirtualRegisterDead - Remove the specified kill of the virtual + /// register from the live variable information. Returns true if the + /// variable was marked dead at the specified instruction, false + /// otherwise. + bool removeVirtualRegisterDead(unsigned reg, MachineInstr *MI) { + if (!getVarInfo(reg).removeKill(MI)) + return false; + + bool Removed = false; + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + MachineOperand &MO = MI->getOperand(i); + if (MO.isReg() && MO.isDef() && MO.getReg() == reg) { + MO.setIsDead(false); + Removed = true; + break; + } + } + assert(Removed && "Register is not defined by this instruction!"); + return true; + } + + void getAnalysisUsage(AnalysisUsage &AU) const; + + virtual void releaseMemory() { + VirtRegInfo.clear(); + } + + /// getVarInfo - Return the VarInfo structure for the specified VIRTUAL + /// register. + VarInfo &getVarInfo(unsigned RegIdx); + + void MarkVirtRegAliveInBlock(VarInfo& VRInfo, MachineBasicBlock* DefBlock, + MachineBasicBlock *BB); + void MarkVirtRegAliveInBlock(VarInfo& VRInfo, MachineBasicBlock* DefBlock, + MachineBasicBlock *BB, + std::vector &WorkList); + void HandleVirtRegDef(unsigned reg, MachineInstr *MI); + void HandleVirtRegUse(unsigned reg, MachineBasicBlock *MBB, + MachineInstr *MI); + + bool isLiveIn(unsigned Reg, const MachineBasicBlock &MBB) { + return getVarInfo(Reg).isLiveIn(MBB, Reg, *MRI); + } + + /// addNewBlock - Add a new basic block BB between DomBB and SuccBB. All + /// variables that are live out of DomBB and live into SuccBB will be marked + /// as passing live through BB. This method assumes that the machine code is + /// still in SSA form. + void addNewBlock(MachineBasicBlock *BB, + MachineBasicBlock *DomBB, + MachineBasicBlock *SuccBB); +}; + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/CodeGen/MachORelocation.h b/libclamav/c++/llvm/include/llvm/CodeGen/MachORelocation.h new file mode 100644 index 000000000..27306c62d --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/CodeGen/MachORelocation.h @@ -0,0 +1,56 @@ +//=== MachORelocation.h - Mach-O Relocation 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 defines the MachORelocation class. +// +//===----------------------------------------------------------------------===// + + +#ifndef LLVM_CODEGEN_MACHO_RELOCATION_H +#define LLVM_CODEGEN_MACHO_RELOCATION_H + +#include "llvm/System/DataTypes.h" + +namespace llvm { + + /// MachORelocation - This struct contains information about each relocation + /// that needs to be emitted to the file. + /// see + class MachORelocation { + uint32_t r_address; // offset in the section to what is being relocated + uint32_t r_symbolnum; // symbol index if r_extern == 1 else section index + bool r_pcrel; // was relocated pc-relative already + uint8_t r_length; // length = 2 ^ r_length + bool r_extern; // + uint8_t r_type; // if not 0, machine-specific relocation type. + bool r_scattered; // 1 = scattered, 0 = non-scattered + int32_t r_value; // the value the item to be relocated is referring + // to. + public: + uint32_t getPackedFields() const { + if (r_scattered) + return (1 << 31) | (r_pcrel << 30) | ((r_length & 3) << 28) | + ((r_type & 15) << 24) | (r_address & 0x00FFFFFF); + else + return (r_symbolnum << 8) | (r_pcrel << 7) | ((r_length & 3) << 5) | + (r_extern << 4) | (r_type & 15); + } + uint32_t getAddress() const { return r_scattered ? r_value : r_address; } + uint32_t getRawAddress() const { return r_address; } + + MachORelocation(uint32_t addr, uint32_t index, bool pcrel, uint8_t len, + bool ext, uint8_t type, bool scattered = false, + int32_t value = 0) : + r_address(addr), r_symbolnum(index), r_pcrel(pcrel), r_length(len), + r_extern(ext), r_type(type), r_scattered(scattered), r_value(value) {} + }; + +} // end llvm namespace + +#endif // LLVM_CODEGEN_MACHO_RELOCATION_H diff --git a/libclamav/c++/llvm/include/llvm/CodeGen/MachineBasicBlock.h b/libclamav/c++/llvm/include/llvm/CodeGen/MachineBasicBlock.h new file mode 100644 index 000000000..6b4c64055 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/CodeGen/MachineBasicBlock.h @@ -0,0 +1,444 @@ +//===-- llvm/CodeGen/MachineBasicBlock.h ------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Collect the sequence of machine instructions for a basic block. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_MACHINEBASICBLOCK_H +#define LLVM_CODEGEN_MACHINEBASICBLOCK_H + +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/ADT/GraphTraits.h" + +namespace llvm { + +class BasicBlock; +class MachineFunction; +class raw_ostream; + +template <> +struct ilist_traits : public ilist_default_traits { +private: + mutable ilist_half_node Sentinel; + + // this is only set by the MachineBasicBlock owning the LiveList + friend class MachineBasicBlock; + MachineBasicBlock* Parent; + +public: + MachineInstr *createSentinel() const { + return static_cast(&Sentinel); + } + void destroySentinel(MachineInstr *) const {} + + MachineInstr *provideInitialHead() const { return createSentinel(); } + MachineInstr *ensureHead(MachineInstr*) const { return createSentinel(); } + static void noteHead(MachineInstr*, MachineInstr*) {} + + void addNodeToList(MachineInstr* N); + void removeNodeFromList(MachineInstr* N); + void transferNodesFromList(ilist_traits &SrcTraits, + ilist_iterator first, + ilist_iterator last); + void deleteNode(MachineInstr *N); +private: + void createNode(const MachineInstr &); +}; + +class MachineBasicBlock : public ilist_node { + typedef ilist Instructions; + Instructions Insts; + const BasicBlock *BB; + int Number; + MachineFunction *xParent; + + /// Predecessors/Successors - Keep track of the predecessor / successor + /// basicblocks. + std::vector Predecessors; + std::vector Successors; + + /// LiveIns - Keep track of the physical registers that are livein of + /// the basicblock. + std::vector LiveIns; + + /// Alignment - Alignment of the basic block. Zero if the basic block does + /// not need to be aligned. + unsigned Alignment; + + /// IsLandingPad - Indicate that this basic block is entered via an + /// exception handler. + bool IsLandingPad; + + /// AddressTaken - Indicate that this basic block is potentially the + /// target of an indirect branch. + bool AddressTaken; + + // Intrusive list support + MachineBasicBlock() {} + + explicit MachineBasicBlock(MachineFunction &mf, const BasicBlock *bb); + + ~MachineBasicBlock(); + + // MachineBasicBlocks are allocated and owned by MachineFunction. + friend class MachineFunction; + +public: + /// getBasicBlock - Return the LLVM basic block that this instance + /// corresponded to originally. Note that this may be NULL if this instance + /// does not correspond directly to an LLVM basic block. + /// + const BasicBlock *getBasicBlock() const { return BB; } + + /// getName - Return the name of the corresponding LLVM basic block, or + /// "(null)". + StringRef getName() const; + + /// hasAddressTaken - Test whether this block is potentially the target + /// of an indirect branch. + bool hasAddressTaken() const { return AddressTaken; } + + /// setHasAddressTaken - Set this block to reflect that it potentially + /// is the target of an indirect branch. + void setHasAddressTaken() { AddressTaken = true; } + + /// getParent - Return the MachineFunction containing this basic block. + /// + const MachineFunction *getParent() const { return xParent; } + MachineFunction *getParent() { return xParent; } + + typedef Instructions::iterator iterator; + typedef Instructions::const_iterator const_iterator; + typedef std::reverse_iterator const_reverse_iterator; + typedef std::reverse_iterator reverse_iterator; + + unsigned size() const { return (unsigned)Insts.size(); } + bool empty() const { return Insts.empty(); } + + MachineInstr& front() { return Insts.front(); } + MachineInstr& back() { return Insts.back(); } + const MachineInstr& front() const { return Insts.front(); } + const MachineInstr& back() const { return Insts.back(); } + + iterator begin() { return Insts.begin(); } + const_iterator begin() const { return Insts.begin(); } + iterator end() { return Insts.end(); } + const_iterator end() const { return Insts.end(); } + reverse_iterator rbegin() { return Insts.rbegin(); } + const_reverse_iterator rbegin() const { return Insts.rbegin(); } + reverse_iterator rend () { return Insts.rend(); } + const_reverse_iterator rend () const { return Insts.rend(); } + + // Machine-CFG iterators + typedef std::vector::iterator pred_iterator; + typedef std::vector::const_iterator const_pred_iterator; + typedef std::vector::iterator succ_iterator; + typedef std::vector::const_iterator const_succ_iterator; + typedef std::vector::reverse_iterator + pred_reverse_iterator; + typedef std::vector::const_reverse_iterator + const_pred_reverse_iterator; + typedef std::vector::reverse_iterator + succ_reverse_iterator; + typedef std::vector::const_reverse_iterator + const_succ_reverse_iterator; + + pred_iterator pred_begin() { return Predecessors.begin(); } + const_pred_iterator pred_begin() const { return Predecessors.begin(); } + pred_iterator pred_end() { return Predecessors.end(); } + const_pred_iterator pred_end() const { return Predecessors.end(); } + pred_reverse_iterator pred_rbegin() + { return Predecessors.rbegin();} + const_pred_reverse_iterator pred_rbegin() const + { return Predecessors.rbegin();} + pred_reverse_iterator pred_rend() + { return Predecessors.rend(); } + const_pred_reverse_iterator pred_rend() const + { return Predecessors.rend(); } + unsigned pred_size() const { + return (unsigned)Predecessors.size(); + } + bool pred_empty() const { return Predecessors.empty(); } + succ_iterator succ_begin() { return Successors.begin(); } + const_succ_iterator succ_begin() const { return Successors.begin(); } + succ_iterator succ_end() { return Successors.end(); } + const_succ_iterator succ_end() const { return Successors.end(); } + succ_reverse_iterator succ_rbegin() + { return Successors.rbegin(); } + const_succ_reverse_iterator succ_rbegin() const + { return Successors.rbegin(); } + succ_reverse_iterator succ_rend() + { return Successors.rend(); } + const_succ_reverse_iterator succ_rend() const + { return Successors.rend(); } + unsigned succ_size() const { + return (unsigned)Successors.size(); + } + bool succ_empty() const { return Successors.empty(); } + + // LiveIn management methods. + + /// addLiveIn - Add the specified register as a live in. Note that it + /// is an error to add the same register to the same set more than once. + void addLiveIn(unsigned Reg) { LiveIns.push_back(Reg); } + + /// removeLiveIn - Remove the specified register from the live in set. + /// + void removeLiveIn(unsigned Reg); + + /// isLiveIn - Return true if the specified register is in the live in set. + /// + bool isLiveIn(unsigned Reg) const; + + // Iteration support for live in sets. These sets are kept in sorted + // order by their register number. + typedef std::vector::iterator livein_iterator; + typedef std::vector::const_iterator const_livein_iterator; + livein_iterator livein_begin() { return LiveIns.begin(); } + const_livein_iterator livein_begin() const { return LiveIns.begin(); } + livein_iterator livein_end() { return LiveIns.end(); } + const_livein_iterator livein_end() const { return LiveIns.end(); } + bool livein_empty() const { return LiveIns.empty(); } + + /// getAlignment - Return alignment of the basic block. + /// + unsigned getAlignment() const { return Alignment; } + + /// setAlignment - Set alignment of the basic block. + /// + void setAlignment(unsigned Align) { Alignment = Align; } + + /// isLandingPad - Returns true if the block is a landing pad. That is + /// this basic block is entered via an exception handler. + bool isLandingPad() const { return IsLandingPad; } + + /// setIsLandingPad - Indicates the block is a landing pad. That is + /// this basic block is entered via an exception handler. + void setIsLandingPad() { IsLandingPad = true; } + + // Code Layout methods. + + /// moveBefore/moveAfter - move 'this' block before or after the specified + /// block. This only moves the block, it does not modify the CFG or adjust + /// potential fall-throughs at the end of the block. + void moveBefore(MachineBasicBlock *NewAfter); + void moveAfter(MachineBasicBlock *NewBefore); + + /// updateTerminator - Update the terminator instructions in block to account + /// for changes to the layout. If the block previously used a fallthrough, + /// it may now need a branch, and if it previously used branching it may now + /// be able to use a fallthrough. + void updateTerminator(); + + // Machine-CFG mutators + + /// addSuccessor - Add succ as a successor of this MachineBasicBlock. + /// The Predecessors list of succ is automatically updated. + /// + void addSuccessor(MachineBasicBlock *succ); + + /// removeSuccessor - Remove successor from the successors list of this + /// MachineBasicBlock. The Predecessors list of succ is automatically updated. + /// + void removeSuccessor(MachineBasicBlock *succ); + + /// removeSuccessor - Remove specified successor from the successors list of + /// this MachineBasicBlock. The Predecessors list of succ is automatically + /// updated. Return the iterator to the element after the one removed. + /// + succ_iterator removeSuccessor(succ_iterator I); + + /// transferSuccessors - Transfers all the successors from MBB to this + /// machine basic block (i.e., copies all the successors fromMBB and + /// remove all the successors from fromMBB). + void transferSuccessors(MachineBasicBlock *fromMBB); + + /// isSuccessor - Return true if the specified MBB is a successor of this + /// block. + bool isSuccessor(const MachineBasicBlock *MBB) const; + + /// isLayoutSuccessor - Return true if the specified MBB will be emitted + /// immediately after this block, such that if this block exits by + /// falling through, control will transfer to the specified MBB. Note + /// that MBB need not be a successor at all, for example if this block + /// ends with an unconditional branch to some other block. + bool isLayoutSuccessor(const MachineBasicBlock *MBB) const; + + /// canFallThrough - Return true if the block can implicitly transfer + /// control to the block after it by falling off the end of it. This should + /// return false if it can reach the block after it, but it uses an explicit + /// branch to do so (e.g., a table jump). True is a conservative answer. + bool canFallThrough(); + + /// getFirstTerminator - returns an iterator to the first terminator + /// instruction of this basic block. If a terminator does not exist, + /// it returns end() + iterator getFirstTerminator(); + + /// isOnlyReachableViaFallthough - Return true if this basic block has + /// exactly one predecessor and the control transfer mechanism between + /// the predecessor and this block is a fall-through. + bool isOnlyReachableByFallthrough() const; + + void pop_front() { Insts.pop_front(); } + void pop_back() { Insts.pop_back(); } + void push_back(MachineInstr *MI) { Insts.push_back(MI); } + template + void insert(iterator I, IT S, IT E) { Insts.insert(I, S, E); } + iterator insert(iterator I, MachineInstr *M) { return Insts.insert(I, M); } + + // erase - Remove the specified element or range from the instruction list. + // These functions delete any instructions removed. + // + iterator erase(iterator I) { return Insts.erase(I); } + iterator erase(iterator I, iterator E) { return Insts.erase(I, E); } + MachineInstr *remove(MachineInstr *I) { return Insts.remove(I); } + void clear() { Insts.clear(); } + + /// splice - Take an instruction from MBB 'Other' at the position From, + /// and insert it into this MBB right before 'where'. + void splice(iterator where, MachineBasicBlock *Other, iterator From) { + Insts.splice(where, Other->Insts, From); + } + + /// splice - Take a block of instructions from MBB 'Other' in the range [From, + /// To), and insert them into this MBB right before 'where'. + void splice(iterator where, MachineBasicBlock *Other, iterator From, + iterator To) { + Insts.splice(where, Other->Insts, From, To); + } + + /// removeFromParent - This method unlinks 'this' from the containing + /// function, and returns it, but does not delete it. + MachineBasicBlock *removeFromParent(); + + /// eraseFromParent - This method unlinks 'this' from the containing + /// function and deletes it. + void eraseFromParent(); + + /// ReplaceUsesOfBlockWith - Given a machine basic block that branched to + /// 'Old', change the code and CFG so that it branches to 'New' instead. + void ReplaceUsesOfBlockWith(MachineBasicBlock *Old, MachineBasicBlock *New); + + /// CorrectExtraCFGEdges - Various pieces of code can cause excess edges in + /// the CFG to be inserted. If we have proven that MBB can only branch to + /// DestA and DestB, remove any other MBB successors from the CFG. DestA and + /// DestB can be null. Besides DestA and DestB, retain other edges leading + /// to LandingPads (currently there can be only one; we don't check or require + /// that here). Note it is possible that DestA and/or DestB are LandingPads. + bool CorrectExtraCFGEdges(MachineBasicBlock *DestA, + MachineBasicBlock *DestB, + bool isCond); + + // Debugging methods. + void dump() const; + void print(raw_ostream &OS) const; + + /// getNumber - MachineBasicBlocks are uniquely numbered at the function + /// level, unless they're not in a MachineFunction yet, in which case this + /// will return -1. + /// + int getNumber() const { return Number; } + void setNumber(int N) { Number = N; } + +private: // Methods used to maintain doubly linked list of blocks... + friend struct ilist_traits; + + // Machine-CFG mutators + + /// addPredecessor - Remove pred as a predecessor of this MachineBasicBlock. + /// Don't do this unless you know what you're doing, because it doesn't + /// update pred's successors list. Use pred->addSuccessor instead. + /// + void addPredecessor(MachineBasicBlock *pred); + + /// removePredecessor - Remove pred as a predecessor of this + /// MachineBasicBlock. Don't do this unless you know what you're + /// doing, because it doesn't update pred's successors list. Use + /// pred->removeSuccessor instead. + /// + void removePredecessor(MachineBasicBlock *pred); +}; + +raw_ostream& operator<<(raw_ostream &OS, const MachineBasicBlock &MBB); + +void WriteAsOperand(raw_ostream &, const MachineBasicBlock*, bool t); + +//===--------------------------------------------------------------------===// +// GraphTraits specializations for machine basic block graphs (machine-CFGs) +//===--------------------------------------------------------------------===// + +// Provide specializations of GraphTraits to be able to treat a +// MachineFunction as a graph of MachineBasicBlocks... +// + +template <> struct GraphTraits { + typedef MachineBasicBlock NodeType; + typedef MachineBasicBlock::succ_iterator ChildIteratorType; + + static NodeType *getEntryNode(MachineBasicBlock *BB) { return BB; } + static inline ChildIteratorType child_begin(NodeType *N) { + return N->succ_begin(); + } + static inline ChildIteratorType child_end(NodeType *N) { + return N->succ_end(); + } +}; + +template <> struct GraphTraits { + typedef const MachineBasicBlock NodeType; + typedef MachineBasicBlock::const_succ_iterator ChildIteratorType; + + static NodeType *getEntryNode(const MachineBasicBlock *BB) { return BB; } + static inline ChildIteratorType child_begin(NodeType *N) { + return N->succ_begin(); + } + static inline ChildIteratorType child_end(NodeType *N) { + return N->succ_end(); + } +}; + +// Provide specializations of GraphTraits to be able to treat a +// MachineFunction as a graph of MachineBasicBlocks... and to walk it +// in inverse order. Inverse order for a function is considered +// to be when traversing the predecessor edges of a MBB +// instead of the successor edges. +// +template <> struct GraphTraits > { + typedef MachineBasicBlock NodeType; + typedef MachineBasicBlock::pred_iterator ChildIteratorType; + static NodeType *getEntryNode(Inverse G) { + return G.Graph; + } + static inline ChildIteratorType child_begin(NodeType *N) { + return N->pred_begin(); + } + static inline ChildIteratorType child_end(NodeType *N) { + return N->pred_end(); + } +}; + +template <> struct GraphTraits > { + typedef const MachineBasicBlock NodeType; + typedef MachineBasicBlock::const_pred_iterator ChildIteratorType; + static NodeType *getEntryNode(Inverse G) { + return G.Graph; + } + static inline ChildIteratorType child_begin(NodeType *N) { + return N->pred_begin(); + } + static inline ChildIteratorType child_end(NodeType *N) { + return N->pred_end(); + } +}; + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/CodeGen/MachineCodeEmitter.h b/libclamav/c++/llvm/include/llvm/CodeGen/MachineCodeEmitter.h new file mode 100644 index 000000000..791db003e --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/CodeGen/MachineCodeEmitter.h @@ -0,0 +1,348 @@ +//===-- llvm/CodeGen/MachineCodeEmitter.h - Code emission -------*- 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 an abstract interface that is used by the machine code +// emission framework to output the code. This allows machine code emission to +// be separated from concerns such as resolution of call targets, and where the +// machine code will be written (memory or disk, f.e.). +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_MACHINECODEEMITTER_H +#define LLVM_CODEGEN_MACHINECODEEMITTER_H + +#include "llvm/System/DataTypes.h" +#include "llvm/Support/DebugLoc.h" + +namespace llvm { + +class MachineBasicBlock; +class MachineConstantPool; +class MachineJumpTableInfo; +class MachineFunction; +class MachineModuleInfo; +class MachineRelocation; +class Value; +class GlobalValue; +class Function; + +/// MachineCodeEmitter - This class defines two sorts of methods: those for +/// emitting the actual bytes of machine code, and those for emitting auxillary +/// structures, such as jump tables, relocations, etc. +/// +/// Emission of machine code is complicated by the fact that we don't (in +/// general) know the size of the machine code that we're about to emit before +/// we emit it. As such, we preallocate a certain amount of memory, and set the +/// BufferBegin/BufferEnd pointers to the start and end of the buffer. As we +/// emit machine instructions, we advance the CurBufferPtr to indicate the +/// location of the next byte to emit. In the case of a buffer overflow (we +/// need to emit more machine code than we have allocated space for), the +/// CurBufferPtr will saturate to BufferEnd and ignore stores. Once the entire +/// function has been emitted, the overflow condition is checked, and if it has +/// occurred, more memory is allocated, and we reemit the code into it. +/// +class MachineCodeEmitter { +public: + class BufferState { + friend class MachineCodeEmitter; + /// BufferBegin/BufferEnd - Pointers to the start and end of the memory + /// allocated for this code buffer. + uint8_t *BufferBegin, *BufferEnd; + + /// CurBufferPtr - Pointer to the next byte of memory to fill when emitting + /// code. This is guranteed to be in the range [BufferBegin,BufferEnd]. If + /// this pointer is at BufferEnd, it will never move due to code emission, + /// and all code emission requests will be ignored (this is the buffer + /// overflow condition). + uint8_t *CurBufferPtr; + public: + BufferState() : BufferBegin(NULL), BufferEnd(NULL), CurBufferPtr(NULL) {} + }; + +protected: + /// These have the same meanings as the fields in BufferState + uint8_t *BufferBegin, *BufferEnd, *CurBufferPtr; + + /// Save or restore the current buffer state. The BufferState objects must be + /// used as a stack. + void SaveStateTo(BufferState &BS) { + assert(BS.BufferBegin == NULL && + "Can't save state into the same BufferState twice."); + BS.BufferBegin = BufferBegin; + BS.BufferEnd = BufferEnd; + BS.CurBufferPtr = CurBufferPtr; + } + void RestoreStateFrom(BufferState &BS) { + BufferBegin = BS.BufferBegin; + BufferEnd = BS.BufferEnd; + CurBufferPtr = BS.CurBufferPtr; + } + +public: + virtual ~MachineCodeEmitter() {} + + /// startFunction - This callback is invoked when the specified function is + /// about to be code generated. This initializes the BufferBegin/End/Ptr + /// fields. + /// + virtual void startFunction(MachineFunction &F) = 0; + + /// finishFunction - This callback is invoked when the specified function has + /// finished code generation. If a buffer overflow has occurred, this method + /// returns true (the callee is required to try again), otherwise it returns + /// false. + /// + virtual bool finishFunction(MachineFunction &F) = 0; + + /// emitByte - This callback is invoked when a byte needs to be written to the + /// output stream. + /// + void emitByte(uint8_t B) { + if (CurBufferPtr != BufferEnd) + *CurBufferPtr++ = B; + } + + /// emitWordLE - This callback is invoked when a 32-bit word needs to be + /// written to the output stream in little-endian format. + /// + void emitWordLE(uint32_t W) { + if (4 <= BufferEnd-CurBufferPtr) { + *CurBufferPtr++ = (uint8_t)(W >> 0); + *CurBufferPtr++ = (uint8_t)(W >> 8); + *CurBufferPtr++ = (uint8_t)(W >> 16); + *CurBufferPtr++ = (uint8_t)(W >> 24); + } else { + CurBufferPtr = BufferEnd; + } + } + + /// emitWordBE - This callback is invoked when a 32-bit word needs to be + /// written to the output stream in big-endian format. + /// + void emitWordBE(uint32_t W) { + if (4 <= BufferEnd-CurBufferPtr) { + *CurBufferPtr++ = (uint8_t)(W >> 24); + *CurBufferPtr++ = (uint8_t)(W >> 16); + *CurBufferPtr++ = (uint8_t)(W >> 8); + *CurBufferPtr++ = (uint8_t)(W >> 0); + } else { + CurBufferPtr = BufferEnd; + } + } + + /// emitDWordLE - This callback is invoked when a 64-bit word needs to be + /// written to the output stream in little-endian format. + /// + void emitDWordLE(uint64_t W) { + if (8 <= BufferEnd-CurBufferPtr) { + *CurBufferPtr++ = (uint8_t)(W >> 0); + *CurBufferPtr++ = (uint8_t)(W >> 8); + *CurBufferPtr++ = (uint8_t)(W >> 16); + *CurBufferPtr++ = (uint8_t)(W >> 24); + *CurBufferPtr++ = (uint8_t)(W >> 32); + *CurBufferPtr++ = (uint8_t)(W >> 40); + *CurBufferPtr++ = (uint8_t)(W >> 48); + *CurBufferPtr++ = (uint8_t)(W >> 56); + } else { + CurBufferPtr = BufferEnd; + } + } + + /// emitDWordBE - This callback is invoked when a 64-bit word needs to be + /// written to the output stream in big-endian format. + /// + void emitDWordBE(uint64_t W) { + if (8 <= BufferEnd-CurBufferPtr) { + *CurBufferPtr++ = (uint8_t)(W >> 56); + *CurBufferPtr++ = (uint8_t)(W >> 48); + *CurBufferPtr++ = (uint8_t)(W >> 40); + *CurBufferPtr++ = (uint8_t)(W >> 32); + *CurBufferPtr++ = (uint8_t)(W >> 24); + *CurBufferPtr++ = (uint8_t)(W >> 16); + *CurBufferPtr++ = (uint8_t)(W >> 8); + *CurBufferPtr++ = (uint8_t)(W >> 0); + } else { + CurBufferPtr = BufferEnd; + } + } + + /// emitAlignment - Move the CurBufferPtr pointer up the the specified + /// alignment (saturated to BufferEnd of course). + void emitAlignment(unsigned Alignment) { + if (Alignment == 0) Alignment = 1; + + if(Alignment <= (uintptr_t)(BufferEnd-CurBufferPtr)) { + // Move the current buffer ptr up to the specified alignment. + CurBufferPtr = + (uint8_t*)(((uintptr_t)CurBufferPtr+Alignment-1) & + ~(uintptr_t)(Alignment-1)); + } else { + CurBufferPtr = BufferEnd; + } + } + + + /// emitULEB128Bytes - This callback is invoked when a ULEB128 needs to be + /// written to the output stream. + void emitULEB128Bytes(uint64_t Value) { + do { + uint8_t Byte = Value & 0x7f; + Value >>= 7; + if (Value) Byte |= 0x80; + emitByte(Byte); + } while (Value); + } + + /// emitSLEB128Bytes - This callback is invoked when a SLEB128 needs to be + /// written to the output stream. + void emitSLEB128Bytes(uint64_t Value) { + uint64_t Sign = Value >> (8 * sizeof(Value) - 1); + bool IsMore; + + do { + uint8_t Byte = Value & 0x7f; + Value >>= 7; + IsMore = Value != Sign || ((Byte ^ Sign) & 0x40) != 0; + if (IsMore) Byte |= 0x80; + emitByte(Byte); + } while (IsMore); + } + + /// emitString - This callback is invoked when a String needs to be + /// written to the output stream. + void emitString(const std::string &String) { + for (unsigned i = 0, N = static_cast(String.size()); + i < N; ++i) { + uint8_t C = String[i]; + emitByte(C); + } + emitByte(0); + } + + /// emitInt32 - Emit a int32 directive. + void emitInt32(int32_t Value) { + if (4 <= BufferEnd-CurBufferPtr) { + *((uint32_t*)CurBufferPtr) = Value; + CurBufferPtr += 4; + } else { + CurBufferPtr = BufferEnd; + } + } + + /// emitInt64 - Emit a int64 directive. + void emitInt64(uint64_t Value) { + if (8 <= BufferEnd-CurBufferPtr) { + *((uint64_t*)CurBufferPtr) = Value; + CurBufferPtr += 8; + } else { + CurBufferPtr = BufferEnd; + } + } + + /// emitInt32At - Emit the Int32 Value in Addr. + void emitInt32At(uintptr_t *Addr, uintptr_t Value) { + if (Addr >= (uintptr_t*)BufferBegin && Addr < (uintptr_t*)BufferEnd) + (*(uint32_t*)Addr) = (uint32_t)Value; + } + + /// emitInt64At - Emit the Int64 Value in Addr. + void emitInt64At(uintptr_t *Addr, uintptr_t Value) { + if (Addr >= (uintptr_t*)BufferBegin && Addr < (uintptr_t*)BufferEnd) + (*(uint64_t*)Addr) = (uint64_t)Value; + } + + /// processDebugLoc - Records debug location information about a + /// MachineInstruction. This is called before emitting any bytes associated + /// with the instruction. Even if successive instructions have the same debug + /// location, this method will be called for each one. + virtual void processDebugLoc(DebugLoc DL, bool BeforePrintintInsn) {} + + /// emitLabel - Emits a label + virtual void emitLabel(uint64_t LabelID) = 0; + + /// allocateSpace - Allocate a block of space in the current output buffer, + /// returning null (and setting conditions to indicate buffer overflow) on + /// failure. Alignment is the alignment in bytes of the buffer desired. + virtual void *allocateSpace(uintptr_t Size, unsigned Alignment) { + emitAlignment(Alignment); + void *Result; + + // Check for buffer overflow. + if (Size >= (uintptr_t)(BufferEnd-CurBufferPtr)) { + CurBufferPtr = BufferEnd; + Result = 0; + } else { + // Allocate the space. + Result = CurBufferPtr; + CurBufferPtr += Size; + } + + return Result; + } + + /// StartMachineBasicBlock - This should be called by the target when a new + /// basic block is about to be emitted. This way the MCE knows where the + /// start of the block is, and can implement getMachineBasicBlockAddress. + virtual void StartMachineBasicBlock(MachineBasicBlock *MBB) = 0; + + /// getCurrentPCValue - This returns the address that the next emitted byte + /// will be output to. + /// + virtual uintptr_t getCurrentPCValue() const { + return (uintptr_t)CurBufferPtr; + } + + /// getCurrentPCOffset - Return the offset from the start of the emitted + /// buffer that we are currently writing to. + virtual uintptr_t getCurrentPCOffset() const { + return CurBufferPtr-BufferBegin; + } + + /// earlyResolveAddresses - True if the code emitter can use symbol addresses + /// during code emission time. The JIT is capable of doing this because it + /// creates jump tables or constant pools in memory on the fly while the + /// object code emitters rely on a linker to have real addresses and should + /// use relocations instead. + virtual bool earlyResolveAddresses() const = 0; + + /// addRelocation - Whenever a relocatable address is needed, it should be + /// noted with this interface. + virtual void addRelocation(const MachineRelocation &MR) = 0; + + /// FIXME: These should all be handled with relocations! + + /// getConstantPoolEntryAddress - Return the address of the 'Index' entry in + /// the constant pool that was last emitted with the emitConstantPool method. + /// + virtual uintptr_t getConstantPoolEntryAddress(unsigned Index) const = 0; + + /// getJumpTableEntryAddress - Return the address of the jump table with index + /// 'Index' in the function that last called initJumpTableInfo. + /// + virtual uintptr_t getJumpTableEntryAddress(unsigned Index) const = 0; + + /// getMachineBasicBlockAddress - Return the address of the specified + /// MachineBasicBlock, only usable after the label for the MBB has been + /// emitted. + /// + virtual uintptr_t getMachineBasicBlockAddress(MachineBasicBlock *MBB) const= 0; + + /// getLabelAddress - Return the address of the specified LabelID, only usable + /// after the LabelID has been emitted. + /// + virtual uintptr_t getLabelAddress(uint64_t LabelID) const = 0; + + /// Specifies the MachineModuleInfo object. This is used for exception handling + /// purposes. + virtual void setModuleInfo(MachineModuleInfo* Info) = 0; +}; + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/CodeGen/MachineCodeInfo.h b/libclamav/c++/llvm/include/llvm/CodeGen/MachineCodeInfo.h new file mode 100644 index 000000000..a75c02a05 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/CodeGen/MachineCodeInfo.h @@ -0,0 +1,53 @@ +//===-- MachineCodeInfo.h - Class used to report JIT 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 defines MachineCodeInfo, a class used by the JIT ExecutionEngine +// to report information about the generated machine code. +// +// See JIT::runJITOnFunction for usage. +// +//===----------------------------------------------------------------------===// + +#ifndef EE_MACHINE_CODE_INFO_H +#define EE_MACHINE_CODE_INFO_H + +#include "llvm/System/DataTypes.h" + +namespace llvm { + +class MachineCodeInfo { +private: + size_t Size; // Number of bytes in memory used + void *Address; // The address of the function in memory + +public: + MachineCodeInfo() : Size(0), Address(0) {} + + void setSize(size_t s) { + Size = s; + } + + void setAddress(void *a) { + Address = a; + } + + size_t size() const { + return Size; + } + + void *address() const { + return Address; + } + +}; + +} + +#endif + diff --git a/libclamav/c++/llvm/include/llvm/CodeGen/MachineConstantPool.h b/libclamav/c++/llvm/include/llvm/CodeGen/MachineConstantPool.h new file mode 100644 index 000000000..8d6c1d1e4 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/CodeGen/MachineConstantPool.h @@ -0,0 +1,167 @@ +//===-- CodeGen/MachineConstantPool.h - Abstract Constant Pool --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +/// @file +/// This file declares the MachineConstantPool class which is an abstract +/// constant pool to keep track of constants referenced by a function. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_MACHINECONSTANTPOOL_H +#define LLVM_CODEGEN_MACHINECONSTANTPOOL_H + +#include +#include +#include + +namespace llvm { + +class Constant; +class FoldingSetNodeID; +class TargetData; +class TargetMachine; +class Type; +class MachineConstantPool; +class raw_ostream; + +/// Abstract base class for all machine specific constantpool value subclasses. +/// +class MachineConstantPoolValue { + const Type *Ty; + +public: + explicit MachineConstantPoolValue(const Type *ty) : Ty(ty) {} + virtual ~MachineConstantPoolValue() {} + + /// getType - get type of this MachineConstantPoolValue. + /// + const Type *getType() const { return Ty; } + + + /// getRelocationInfo - This method classifies the entry according to + /// whether or not it may generate a relocation entry. This must be + /// conservative, so if it might codegen to a relocatable entry, it should say + /// so. The return values are the same as Constant::getRelocationInfo(). + virtual unsigned getRelocationInfo() const = 0; + + virtual int getExistingMachineCPValue(MachineConstantPool *CP, + unsigned Alignment) = 0; + + virtual void AddSelectionDAGCSEId(FoldingSetNodeID &ID) = 0; + + /// print - Implement operator<< + virtual void print(raw_ostream &O) const = 0; +}; + +inline raw_ostream &operator<<(raw_ostream &OS, + const MachineConstantPoolValue &V) { + V.print(OS); + return OS; +} + + +/// This class is a data container for one entry in a MachineConstantPool. +/// It contains a pointer to the value and an offset from the start of +/// the constant pool. +/// @brief An entry in a MachineConstantPool +class MachineConstantPoolEntry { +public: + /// The constant itself. + union { + Constant *ConstVal; + MachineConstantPoolValue *MachineCPVal; + } Val; + + /// The required alignment for this entry. The top bit is set when Val is + /// a MachineConstantPoolValue. + unsigned Alignment; + + MachineConstantPoolEntry(Constant *V, unsigned A) + : Alignment(A) { + Val.ConstVal = V; + } + MachineConstantPoolEntry(MachineConstantPoolValue *V, unsigned A) + : Alignment(A) { + Val.MachineCPVal = V; + Alignment |= 1U << (sizeof(unsigned)*CHAR_BIT-1); + } + + bool isMachineConstantPoolEntry() const { + return (int)Alignment < 0; + } + + int getAlignment() const { + return Alignment & ~(1 << (sizeof(unsigned)*CHAR_BIT-1)); + } + + const Type *getType() const; + + /// getRelocationInfo - This method classifies the entry according to + /// whether or not it may generate a relocation entry. This must be + /// conservative, so if it might codegen to a relocatable entry, it should say + /// so. The return values are: + /// + /// 0: This constant pool entry is guaranteed to never have a relocation + /// applied to it (because it holds a simple constant like '4'). + /// 1: This entry has relocations, but the entries are guaranteed to be + /// resolvable by the static linker, so the dynamic linker will never see + /// them. + /// 2: This entry may have arbitrary relocations. + unsigned getRelocationInfo() const; +}; + +/// The MachineConstantPool class keeps track of constants referenced by a +/// function which must be spilled to memory. This is used for constants which +/// are unable to be used directly as operands to instructions, which typically +/// include floating point and large integer constants. +/// +/// Instructions reference the address of these constant pool constants through +/// the use of MO_ConstantPoolIndex values. When emitting assembly or machine +/// code, these virtual address references are converted to refer to the +/// address of the function constant pool values. +/// @brief The machine constant pool. +class MachineConstantPool { + const TargetData *TD; ///< The machine's TargetData. + unsigned PoolAlignment; ///< The alignment for the pool. + std::vector Constants; ///< The pool of constants. +public: + /// @brief The only constructor. + explicit MachineConstantPool(const TargetData *td) + : TD(td), PoolAlignment(1) {} + ~MachineConstantPool(); + + /// getConstantPoolAlignment - Return the the alignment required by + /// the whole constant pool, of which the first element must be aligned. + unsigned getConstantPoolAlignment() const { return PoolAlignment; } + + /// getConstantPoolIndex - Create a new entry in the constant pool or return + /// an existing one. User must specify the minimum required alignment for + /// the object. + unsigned getConstantPoolIndex(Constant *C, unsigned Alignment); + unsigned getConstantPoolIndex(MachineConstantPoolValue *V,unsigned Alignment); + + /// isEmpty - Return true if this constant pool contains no constants. + bool isEmpty() const { return Constants.empty(); } + + const std::vector &getConstants() const { + return Constants; + } + + /// print - Used by the MachineFunction printer to print information about + /// constant pool objects. Implemented in MachineFunction.cpp + /// + void print(raw_ostream &OS) const; + + /// dump - Call print(cerr) to be called from the debugger. + void dump() const; +}; + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/CodeGen/MachineDominators.h b/libclamav/c++/llvm/include/llvm/CodeGen/MachineDominators.h new file mode 100644 index 000000000..086528aaf --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/CodeGen/MachineDominators.h @@ -0,0 +1,197 @@ +//=- llvm/CodeGen/MachineDominators.h - Machine Dom Calculation --*- 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 classes mirroring those in llvm/Analysis/Dominators.h, +// but for target-specific code rather than target-independent IR. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_MACHINEDOMINATORS_H +#define LLVM_CODEGEN_MACHINEDOMINATORS_H + +#include "llvm/CodeGen/MachineBasicBlock.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/Analysis/Dominators.h" +#include "llvm/Analysis/DominatorInternals.h" + +namespace llvm { + +template<> +inline void DominatorTreeBase::addRoot(MachineBasicBlock* MBB) { + this->Roots.push_back(MBB); +} + +EXTERN_TEMPLATE_INSTANTIATION(class DomTreeNodeBase); +EXTERN_TEMPLATE_INSTANTIATION(class DominatorTreeBase); + +typedef DomTreeNodeBase MachineDomTreeNode; + +//===------------------------------------- +/// DominatorTree Class - Concrete subclass of DominatorTreeBase that is used to +/// compute a normal dominator tree. +/// +class MachineDominatorTree : public MachineFunctionPass { +public: + static char ID; // Pass ID, replacement for typeid + DominatorTreeBase* DT; + + MachineDominatorTree(); + + ~MachineDominatorTree(); + + DominatorTreeBase& getBase() { return *DT; } + + virtual void getAnalysisUsage(AnalysisUsage &AU) const; + + /// getRoots - Return the root blocks of the current CFG. This may include + /// multiple blocks if we are computing post dominators. For forward + /// dominators, this will always be a single block (the entry node). + /// + inline const std::vector &getRoots() const { + return DT->getRoots(); + } + + inline MachineBasicBlock *getRoot() const { + return DT->getRoot(); + } + + inline MachineDomTreeNode *getRootNode() const { + return DT->getRootNode(); + } + + virtual bool runOnMachineFunction(MachineFunction &F); + + inline bool dominates(MachineDomTreeNode* A, MachineDomTreeNode* B) const { + return DT->dominates(A, B); + } + + inline bool dominates(MachineBasicBlock* A, MachineBasicBlock* B) const { + return DT->dominates(A, B); + } + + // dominates - Return true if A dominates B. This performs the + // special checks necessary if A and B are in the same basic block. + bool dominates(MachineInstr *A, MachineInstr *B) const { + MachineBasicBlock *BBA = A->getParent(), *BBB = B->getParent(); + if (BBA != BBB) return DT->dominates(BBA, BBB); + + // Loop through the basic block until we find A or B. + MachineBasicBlock::iterator I = BBA->begin(); + for (; &*I != A && &*I != B; ++I) /*empty*/; + + //if(!DT.IsPostDominators) { + // A dominates B if it is found first in the basic block. + return &*I == A; + //} else { + // // A post-dominates B if B is found first in the basic block. + // return &*I == B; + //} + } + + inline bool properlyDominates(const MachineDomTreeNode* A, + MachineDomTreeNode* B) const { + return DT->properlyDominates(A, B); + } + + inline bool properlyDominates(MachineBasicBlock* A, + MachineBasicBlock* B) const { + return DT->properlyDominates(A, B); + } + + /// findNearestCommonDominator - Find nearest common dominator basic block + /// for basic block A and B. If there is no such block then return NULL. + inline MachineBasicBlock *findNearestCommonDominator(MachineBasicBlock *A, + MachineBasicBlock *B) { + return DT->findNearestCommonDominator(A, B); + } + + inline MachineDomTreeNode *operator[](MachineBasicBlock *BB) const { + return DT->getNode(BB); + } + + /// getNode - return the (Post)DominatorTree node for the specified basic + /// block. This is the same as using operator[] on this class. + /// + inline MachineDomTreeNode *getNode(MachineBasicBlock *BB) const { + return DT->getNode(BB); + } + + /// addNewBlock - Add a new node to the dominator tree information. This + /// creates a new node as a child of DomBB dominator node,linking it into + /// the children list of the immediate dominator. + inline MachineDomTreeNode *addNewBlock(MachineBasicBlock *BB, + MachineBasicBlock *DomBB) { + return DT->addNewBlock(BB, DomBB); + } + + /// changeImmediateDominator - This method is used to update the dominator + /// tree information when a node's immediate dominator changes. + /// + inline void changeImmediateDominator(MachineBasicBlock *N, + MachineBasicBlock* NewIDom) { + DT->changeImmediateDominator(N, NewIDom); + } + + inline void changeImmediateDominator(MachineDomTreeNode *N, + MachineDomTreeNode* NewIDom) { + DT->changeImmediateDominator(N, NewIDom); + } + + /// eraseNode - Removes a node from the dominator tree. Block must not + /// domiante any other blocks. Removes node from its immediate dominator's + /// children list. Deletes dominator node associated with basic block BB. + inline void eraseNode(MachineBasicBlock *BB) { + DT->eraseNode(BB); + } + + /// splitBlock - BB is split and now it has one successor. Update dominator + /// tree to reflect this change. + inline void splitBlock(MachineBasicBlock* NewBB) { + DT->splitBlock(NewBB); + } + + + virtual void releaseMemory(); + + virtual void print(raw_ostream &OS, const Module*) const; +}; + +//===------------------------------------- +/// DominatorTree GraphTraits specialization so the DominatorTree can be +/// iterable by generic graph iterators. +/// + +template struct GraphTraits; + +template <> struct GraphTraits { + typedef MachineDomTreeNode NodeType; + typedef NodeType::iterator ChildIteratorType; + + static NodeType *getEntryNode(NodeType *N) { + return N; + } + static inline ChildIteratorType child_begin(NodeType* N) { + return N->begin(); + } + static inline ChildIteratorType child_end(NodeType* N) { + return N->end(); + } +}; + +template <> struct GraphTraits + : public GraphTraits { + static NodeType *getEntryNode(MachineDominatorTree *DT) { + return DT->getRootNode(); + } +}; + +} + +#endif diff --git a/libclamav/c++/llvm/include/llvm/CodeGen/MachineFrameInfo.h b/libclamav/c++/llvm/include/llvm/CodeGen/MachineFrameInfo.h new file mode 100644 index 000000000..bed82af81 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/CodeGen/MachineFrameInfo.h @@ -0,0 +1,470 @@ +//===-- CodeGen/MachineFrameInfo.h - Abstract Stack Frame Rep. --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// The file defines the MachineFrameInfo class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_MACHINEFRAMEINFO_H +#define LLVM_CODEGEN_MACHINEFRAMEINFO_H + +#include "llvm/ADT/BitVector.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/System/DataTypes.h" +#include +#include +#include + +namespace llvm { +class raw_ostream; +class TargetData; +class TargetRegisterClass; +class Type; +class MachineModuleInfo; +class MachineFunction; +class MachineBasicBlock; +class TargetFrameInfo; + +/// The CalleeSavedInfo class tracks the information need to locate where a +/// callee saved register in the current frame. +class CalleeSavedInfo { + +private: + unsigned Reg; + const TargetRegisterClass *RegClass; + int FrameIdx; + +public: + CalleeSavedInfo(unsigned R, const TargetRegisterClass *RC, int FI = 0) + : Reg(R) + , RegClass(RC) + , FrameIdx(FI) + {} + + // Accessors. + unsigned getReg() const { return Reg; } + const TargetRegisterClass *getRegClass() const { return RegClass; } + int getFrameIdx() const { return FrameIdx; } + void setFrameIdx(int FI) { FrameIdx = FI; } +}; + +/// The MachineFrameInfo class represents an abstract stack frame until +/// prolog/epilog code is inserted. This class is key to allowing stack frame +/// representation optimizations, such as frame pointer elimination. It also +/// allows more mundane (but still important) optimizations, such as reordering +/// of abstract objects on the stack frame. +/// +/// To support this, the class assigns unique integer identifiers to stack +/// objects requested clients. These identifiers are negative integers for +/// fixed stack objects (such as arguments passed on the stack) or nonnegative +/// for objects that may be reordered. Instructions which refer to stack +/// objects use a special MO_FrameIndex operand to represent these frame +/// indexes. +/// +/// Because this class keeps track of all references to the stack frame, it +/// knows when a variable sized object is allocated on the stack. This is the +/// sole condition which prevents frame pointer elimination, which is an +/// important optimization on register-poor architectures. Because original +/// variable sized alloca's in the source program are the only source of +/// variable sized stack objects, it is safe to decide whether there will be +/// any variable sized objects before all stack objects are known (for +/// example, register allocator spill code never needs variable sized +/// objects). +/// +/// When prolog/epilog code emission is performed, the final stack frame is +/// built and the machine instructions are modified to refer to the actual +/// stack offsets of the object, eliminating all MO_FrameIndex operands from +/// the program. +/// +/// @brief Abstract Stack Frame Information +class MachineFrameInfo { + + // StackObject - Represent a single object allocated on the stack. + struct StackObject { + // SPOffset - The offset of this object from the stack pointer on entry to + // the function. This field has no meaning for a variable sized element. + int64_t SPOffset; + + // The size of this object on the stack. 0 means a variable sized object, + // ~0ULL means a dead object. + uint64_t Size; + + // Alignment - The required alignment of this stack slot. + unsigned Alignment; + + // isImmutable - If true, the value of the stack object is set before + // entering the function and is not modified inside the function. By + // default, fixed objects are immutable unless marked otherwise. + bool isImmutable; + + // isSpillSlot - If true, the stack object is used as spill slot. It + // cannot alias any other memory objects. + bool isSpillSlot; + + StackObject(uint64_t Sz, unsigned Al, int64_t SP, bool IM, + bool isSS) + : SPOffset(SP), Size(Sz), Alignment(Al), isImmutable(IM), + isSpillSlot(isSS) {} + }; + + /// Objects - The list of stack objects allocated... + /// + std::vector Objects; + + /// NumFixedObjects - This contains the number of fixed objects contained on + /// the stack. Because fixed objects are stored at a negative index in the + /// Objects list, this is also the index to the 0th object in the list. + /// + unsigned NumFixedObjects; + + /// HasVarSizedObjects - This boolean keeps track of whether any variable + /// sized objects have been allocated yet. + /// + bool HasVarSizedObjects; + + /// FrameAddressTaken - This boolean keeps track of whether there is a call + /// to builtin \@llvm.frameaddress. + bool FrameAddressTaken; + + /// StackSize - The prolog/epilog code inserter calculates the final stack + /// offsets for all of the fixed size objects, updating the Objects list + /// above. It then updates StackSize to contain the number of bytes that need + /// to be allocated on entry to the function. + /// + uint64_t StackSize; + + /// OffsetAdjustment - The amount that a frame offset needs to be adjusted to + /// have the actual offset from the stack/frame pointer. The exact usage of + /// this is target-dependent, but it is typically used to adjust between + /// SP-relative and FP-relative offsets. E.G., if objects are accessed via + /// SP then OffsetAdjustment is zero; if FP is used, OffsetAdjustment is set + /// to the distance between the initial SP and the value in FP. For many + /// targets, this value is only used when generating debug info (via + /// TargetRegisterInfo::getFrameIndexOffset); when generating code, the + /// corresponding adjustments are performed directly. + int OffsetAdjustment; + + /// MaxAlignment - The prolog/epilog code inserter may process objects + /// that require greater alignment than the default alignment the target + /// provides. To handle this, MaxAlignment is set to the maximum alignment + /// needed by the objects on the current frame. If this is greater than the + /// native alignment maintained by the compiler, dynamic alignment code will + /// be needed. + /// + unsigned MaxAlignment; + + /// HasCalls - Set to true if this function has any function calls. This is + /// only valid during and after prolog/epilog code insertion. + bool HasCalls; + + /// StackProtectorIdx - The frame index for the stack protector. + int StackProtectorIdx; + + /// MaxCallFrameSize - This contains the size of the largest call frame if the + /// target uses frame setup/destroy pseudo instructions (as defined in the + /// TargetFrameInfo class). This information is important for frame pointer + /// elimination. If is only valid during and after prolog/epilog code + /// insertion. + /// + unsigned MaxCallFrameSize; + + /// CSInfo - The prolog/epilog code inserter fills in this vector with each + /// callee saved register saved in the frame. Beyond its use by the prolog/ + /// epilog code inserter, this data used for debug info and exception + /// handling. + std::vector CSInfo; + + /// CSIValid - Has CSInfo been set yet? + bool CSIValid; + + /// SpillObjects - A vector indicating which frame indices refer to + /// spill slots. + SmallVector SpillObjects; + + /// MMI - This field is set (via setMachineModuleInfo) by a module info + /// consumer (ex. DwarfWriter) to indicate that frame layout information + /// should be acquired. Typically, it's the responsibility of the target's + /// TargetRegisterInfo prologue/epilogue emitting code to inform + /// MachineModuleInfo of frame layouts. + MachineModuleInfo *MMI; + + /// TargetFrameInfo - Target information about frame layout. + /// + const TargetFrameInfo &TFI; + +public: + explicit MachineFrameInfo(const TargetFrameInfo &tfi) : TFI(tfi) { + StackSize = NumFixedObjects = OffsetAdjustment = MaxAlignment = 0; + HasVarSizedObjects = false; + FrameAddressTaken = false; + HasCalls = false; + StackProtectorIdx = -1; + MaxCallFrameSize = 0; + CSIValid = false; + MMI = 0; + } + + /// hasStackObjects - Return true if there are any stack objects in this + /// function. + /// + bool hasStackObjects() const { return !Objects.empty(); } + + /// hasVarSizedObjects - This method may be called any time after instruction + /// selection is complete to determine if the stack frame for this function + /// contains any variable sized objects. + /// + bool hasVarSizedObjects() const { return HasVarSizedObjects; } + + /// getStackProtectorIndex/setStackProtectorIndex - Return the index for the + /// stack protector object. + /// + int getStackProtectorIndex() const { return StackProtectorIdx; } + void setStackProtectorIndex(int I) { StackProtectorIdx = I; } + + /// isFrameAddressTaken - This method may be called any time after instruction + /// selection is complete to determine if there is a call to + /// \@llvm.frameaddress in this function. + bool isFrameAddressTaken() const { return FrameAddressTaken; } + void setFrameAddressIsTaken(bool T) { FrameAddressTaken = T; } + + /// getObjectIndexBegin - Return the minimum frame object index. + /// + int getObjectIndexBegin() const { return -NumFixedObjects; } + + /// getObjectIndexEnd - Return one past the maximum frame object index. + /// + int getObjectIndexEnd() const { return (int)Objects.size()-NumFixedObjects; } + + /// getNumFixedObjects() - Return the number of fixed objects. + unsigned getNumFixedObjects() const { return NumFixedObjects; } + + /// getNumObjects() - Return the number of objects. + /// + unsigned getNumObjects() const { return Objects.size(); } + + /// getObjectSize - Return the size of the specified object. + /// + int64_t getObjectSize(int ObjectIdx) const { + assert(unsigned(ObjectIdx+NumFixedObjects) < Objects.size() && + "Invalid Object Idx!"); + return Objects[ObjectIdx+NumFixedObjects].Size; + } + + /// setObjectSize - Change the size of the specified stack object. + void setObjectSize(int ObjectIdx, int64_t Size) { + assert(unsigned(ObjectIdx+NumFixedObjects) < Objects.size() && + "Invalid Object Idx!"); + Objects[ObjectIdx+NumFixedObjects].Size = Size; + } + + /// getObjectAlignment - Return the alignment of the specified stack object. + unsigned getObjectAlignment(int ObjectIdx) const { + assert(unsigned(ObjectIdx+NumFixedObjects) < Objects.size() && + "Invalid Object Idx!"); + return Objects[ObjectIdx+NumFixedObjects].Alignment; + } + + /// setObjectAlignment - Change the alignment of the specified stack object. + void setObjectAlignment(int ObjectIdx, unsigned Align) { + assert(unsigned(ObjectIdx+NumFixedObjects) < Objects.size() && + "Invalid Object Idx!"); + Objects[ObjectIdx+NumFixedObjects].Alignment = Align; + } + + /// getObjectOffset - Return the assigned stack offset of the specified object + /// from the incoming stack pointer. + /// + int64_t getObjectOffset(int ObjectIdx) const { + assert(unsigned(ObjectIdx+NumFixedObjects) < Objects.size() && + "Invalid Object Idx!"); + assert(!isDeadObjectIndex(ObjectIdx) && + "Getting frame offset for a dead object?"); + return Objects[ObjectIdx+NumFixedObjects].SPOffset; + } + + /// setObjectOffset - Set the stack frame offset of the specified object. The + /// offset is relative to the stack pointer on entry to the function. + /// + void setObjectOffset(int ObjectIdx, int64_t SPOffset) { + assert(unsigned(ObjectIdx+NumFixedObjects) < Objects.size() && + "Invalid Object Idx!"); + assert(!isDeadObjectIndex(ObjectIdx) && + "Setting frame offset for a dead object?"); + Objects[ObjectIdx+NumFixedObjects].SPOffset = SPOffset; + } + + /// getStackSize - Return the number of bytes that must be allocated to hold + /// all of the fixed size frame objects. This is only valid after + /// Prolog/Epilog code insertion has finalized the stack frame layout. + /// + uint64_t getStackSize() const { return StackSize; } + + /// setStackSize - Set the size of the stack... + /// + void setStackSize(uint64_t Size) { StackSize = Size; } + + /// getOffsetAdjustment - Return the correction for frame offsets. + /// + int getOffsetAdjustment() const { return OffsetAdjustment; } + + /// setOffsetAdjustment - Set the correction for frame offsets. + /// + void setOffsetAdjustment(int Adj) { OffsetAdjustment = Adj; } + + /// getMaxAlignment - Return the alignment in bytes that this function must be + /// aligned to, which is greater than the default stack alignment provided by + /// the target. + /// + unsigned getMaxAlignment() const { return MaxAlignment; } + + /// setMaxAlignment - Set the preferred alignment. + /// + void setMaxAlignment(unsigned Align) { MaxAlignment = Align; } + + /// hasCalls - Return true if the current function has no function calls. + /// This is only valid during or after prolog/epilog code emission. + /// + bool hasCalls() const { return HasCalls; } + void setHasCalls(bool V) { HasCalls = V; } + + /// getMaxCallFrameSize - Return the maximum size of a call frame that must be + /// allocated for an outgoing function call. This is only available if + /// CallFrameSetup/Destroy pseudo instructions are used by the target, and + /// then only during or after prolog/epilog code insertion. + /// + unsigned getMaxCallFrameSize() const { return MaxCallFrameSize; } + void setMaxCallFrameSize(unsigned S) { MaxCallFrameSize = S; } + + /// CreateFixedObject - Create a new object at a fixed location on the stack. + /// All fixed objects should be created before other objects are created for + /// efficiency. By default, fixed objects are immutable. This returns an + /// index with a negative value. + /// + int CreateFixedObject(uint64_t Size, int64_t SPOffset, + bool Immutable, bool isSS); + + + /// isFixedObjectIndex - Returns true if the specified index corresponds to a + /// fixed stack object. + bool isFixedObjectIndex(int ObjectIdx) const { + return ObjectIdx < 0 && (ObjectIdx >= -(int)NumFixedObjects); + } + + /// isImmutableObjectIndex - Returns true if the specified index corresponds + /// to an immutable object. + bool isImmutableObjectIndex(int ObjectIdx) const { + assert(unsigned(ObjectIdx+NumFixedObjects) < Objects.size() && + "Invalid Object Idx!"); + return Objects[ObjectIdx+NumFixedObjects].isImmutable; + } + + /// isSpillSlotObjectIndex - Returns true if the specified index corresponds + /// to a spill slot.. + bool isSpillSlotObjectIndex(int ObjectIdx) const { + assert(unsigned(ObjectIdx+NumFixedObjects) < Objects.size() && + "Invalid Object Idx!"); + return Objects[ObjectIdx+NumFixedObjects].isSpillSlot;; + } + + /// isDeadObjectIndex - Returns true if the specified index corresponds to + /// a dead object. + bool isDeadObjectIndex(int ObjectIdx) const { + assert(unsigned(ObjectIdx+NumFixedObjects) < Objects.size() && + "Invalid Object Idx!"); + return Objects[ObjectIdx+NumFixedObjects].Size == ~0ULL; + } + + /// CreateStackObject - Create a new statically sized stack object, + /// returning a nonnegative identifier to represent it. + /// + int CreateStackObject(uint64_t Size, unsigned Alignment, bool isSS) { + assert(Size != 0 && "Cannot allocate zero size stack objects!"); + Objects.push_back(StackObject(Size, Alignment, 0, false, isSS)); + int Index = (int)Objects.size()-NumFixedObjects-1; + assert(Index >= 0 && "Bad frame index!"); + return Index; + } + + /// CreateSpillStackObject - Create a new statically sized stack + /// object that represents a spill slot, returning a nonnegative + /// identifier to represent it. + /// + int CreateSpillStackObject(uint64_t Size, unsigned Alignment) { + CreateStackObject(Size, Alignment, true); + int Index = (int)Objects.size()-NumFixedObjects-1; + return Index; + } + + /// RemoveStackObject - Remove or mark dead a statically sized stack object. + /// + void RemoveStackObject(int ObjectIdx) { + // Mark it dead. + Objects[ObjectIdx+NumFixedObjects].Size = ~0ULL; + } + + /// CreateVariableSizedObject - Notify the MachineFrameInfo object that a + /// variable sized object has been created. This must be created whenever a + /// variable sized object is created, whether or not the index returned is + /// actually used. + /// + int CreateVariableSizedObject() { + HasVarSizedObjects = true; + Objects.push_back(StackObject(0, 1, 0, false, false)); + return (int)Objects.size()-NumFixedObjects-1; + } + + /// getCalleeSavedInfo - Returns a reference to call saved info vector for the + /// current function. + const std::vector &getCalleeSavedInfo() const { + return CSInfo; + } + + /// setCalleeSavedInfo - Used by prolog/epilog inserter to set the function's + /// callee saved information. + void setCalleeSavedInfo(const std::vector &CSI) { + CSInfo = CSI; + } + + /// isCalleeSavedInfoValid - Has the callee saved info been calculated yet? + bool isCalleeSavedInfoValid() const { return CSIValid; } + + void setCalleeSavedInfoValid(bool v) { CSIValid = v; } + + /// getPristineRegs - Return a set of physical registers that are pristine on + /// entry to the MBB. + /// + /// Pristine registers hold a value that is useless to the current function, + /// but that must be preserved - they are callee saved registers that have not + /// been saved yet. + /// + /// Before the PrologueEpilogueInserter has placed the CSR spill code, this + /// method always returns an empty set. + BitVector getPristineRegs(const MachineBasicBlock *MBB) const; + + /// getMachineModuleInfo - Used by a prologue/epilogue + /// emitter (TargetRegisterInfo) to provide frame layout information. + MachineModuleInfo *getMachineModuleInfo() const { return MMI; } + + /// setMachineModuleInfo - Used by a meta info consumer (DwarfWriter) to + /// indicate that frame layout information should be gathered. + void setMachineModuleInfo(MachineModuleInfo *mmi) { MMI = mmi; } + + /// print - Used by the MachineFunction printer to print information about + /// stack objects. Implemented in MachineFunction.cpp + /// + void print(const MachineFunction &MF, raw_ostream &OS) const; + + /// dump - Print the function to stderr. + void dump(const MachineFunction &MF) const; +}; + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/CodeGen/MachineFunction.h b/libclamav/c++/llvm/include/llvm/CodeGen/MachineFunction.h new file mode 100644 index 000000000..f1bfa0145 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/CodeGen/MachineFunction.h @@ -0,0 +1,441 @@ +//===-- llvm/CodeGen/MachineFunction.h --------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Collect native machine code for a function. This class contains a list of +// MachineBasicBlock instances that make up the current compiled function. +// +// This class also contains pointers to various classes which hold +// target-specific information about the generated code. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_MACHINEFUNCTION_H +#define LLVM_CODEGEN_MACHINEFUNCTION_H + +#include "llvm/CodeGen/MachineBasicBlock.h" +#include "llvm/ADT/ilist.h" +#include "llvm/Support/DebugLoc.h" +#include "llvm/Support/Allocator.h" +#include "llvm/Support/Recycler.h" + +namespace llvm { + +class Value; +class Function; +class MachineRegisterInfo; +class MachineFrameInfo; +class MachineConstantPool; +class MachineJumpTableInfo; +class TargetMachine; +class TargetRegisterClass; + +template <> +struct ilist_traits + : public ilist_default_traits { + mutable ilist_half_node Sentinel; +public: + MachineBasicBlock *createSentinel() const { + return static_cast(&Sentinel); + } + void destroySentinel(MachineBasicBlock *) const {} + + MachineBasicBlock *provideInitialHead() const { return createSentinel(); } + MachineBasicBlock *ensureHead(MachineBasicBlock*) const { + return createSentinel(); + } + static void noteHead(MachineBasicBlock*, MachineBasicBlock*) {} + + void addNodeToList(MachineBasicBlock* MBB); + void removeNodeFromList(MachineBasicBlock* MBB); + void deleteNode(MachineBasicBlock *MBB); +private: + void createNode(const MachineBasicBlock &); +}; + +/// MachineFunctionInfo - This class can be derived from and used by targets to +/// hold private target-specific information for each MachineFunction. Objects +/// of type are accessed/created with MF::getInfo and destroyed when the +/// MachineFunction is destroyed. +struct MachineFunctionInfo { + virtual ~MachineFunctionInfo(); +}; + +class MachineFunction { + Function *Fn; + const TargetMachine &Target; + + // RegInfo - Information about each register in use in the function. + MachineRegisterInfo *RegInfo; + + // Used to keep track of target-specific per-machine function information for + // the target implementation. + MachineFunctionInfo *MFInfo; + + // Keep track of objects allocated on the stack. + MachineFrameInfo *FrameInfo; + + // Keep track of constants which are spilled to memory + MachineConstantPool *ConstantPool; + + // Keep track of jump tables for switch instructions + MachineJumpTableInfo *JumpTableInfo; + + // Function-level unique numbering for MachineBasicBlocks. When a + // MachineBasicBlock is inserted into a MachineFunction is it automatically + // numbered and this vector keeps track of the mapping from ID's to MBB's. + std::vector MBBNumbering; + + // Pool-allocate MachineFunction-lifetime and IR objects. + BumpPtrAllocator Allocator; + + // Allocation management for instructions in function. + Recycler InstructionRecycler; + + // Allocation management for basic blocks in function. + Recycler BasicBlockRecycler; + + // List of machine basic blocks in function + typedef ilist BasicBlockListType; + BasicBlockListType BasicBlocks; + + // Default debug location. Used to print out the debug label at the beginning + // of a function. + DebugLoc DefaultDebugLoc; + + // Tracks debug locations. + DebugLocTracker DebugLocInfo; + + // The alignment of the function. + unsigned Alignment; + + MachineFunction(const MachineFunction &); // intentionally unimplemented + void operator=(const MachineFunction&); // intentionally unimplemented + +public: + MachineFunction(Function *Fn, const TargetMachine &TM); + ~MachineFunction(); + + /// getFunction - Return the LLVM function that this machine code represents + /// + Function *getFunction() const { return Fn; } + + /// getTarget - Return the target machine this machine code is compiled with + /// + const TargetMachine &getTarget() const { return Target; } + + /// getRegInfo - Return information about the registers currently in use. + /// + MachineRegisterInfo &getRegInfo() { return *RegInfo; } + const MachineRegisterInfo &getRegInfo() const { return *RegInfo; } + + /// getFrameInfo - Return the frame info object for the current function. + /// This object contains information about objects allocated on the stack + /// frame of the current function in an abstract way. + /// + MachineFrameInfo *getFrameInfo() { return FrameInfo; } + const MachineFrameInfo *getFrameInfo() const { return FrameInfo; } + + /// getJumpTableInfo - Return the jump table info object for the current + /// function. This object contains information about jump tables for switch + /// instructions in the current function. + /// + MachineJumpTableInfo *getJumpTableInfo() { return JumpTableInfo; } + const MachineJumpTableInfo *getJumpTableInfo() const { return JumpTableInfo; } + + /// getConstantPool - Return the constant pool object for the current + /// function. + /// + MachineConstantPool *getConstantPool() { return ConstantPool; } + const MachineConstantPool *getConstantPool() const { return ConstantPool; } + + /// getAlignment - Return the alignment (log2, not bytes) of the function. + /// + unsigned getAlignment() const { return Alignment; } + + /// setAlignment - Set the alignment (log2, not bytes) of the function. + /// + void setAlignment(unsigned A) { Alignment = A; } + + /// getInfo - Keep track of various per-function pieces of information for + /// backends that would like to do so. + /// + template + Ty *getInfo() { + if (!MFInfo) { + // This should be just `new (Allocator.Allocate()) Ty(*this)', but + // that apparently breaks GCC 3.3. + Ty *Loc = static_cast(Allocator.Allocate(sizeof(Ty), + AlignOf::Alignment)); + MFInfo = new (Loc) Ty(*this); + } + + assert((void*)dynamic_cast(MFInfo) == (void*)MFInfo && + "Invalid concrete type or multiple inheritence for getInfo"); + return static_cast(MFInfo); + } + + template + const Ty *getInfo() const { + return const_cast(this)->getInfo(); + } + + /// getBlockNumbered - MachineBasicBlocks are automatically numbered when they + /// are inserted into the machine function. The block number for a machine + /// basic block can be found by using the MBB::getBlockNumber method, this + /// method provides the inverse mapping. + /// + MachineBasicBlock *getBlockNumbered(unsigned N) const { + assert(N < MBBNumbering.size() && "Illegal block number"); + assert(MBBNumbering[N] && "Block was removed from the machine function!"); + return MBBNumbering[N]; + } + + /// getNumBlockIDs - Return the number of MBB ID's allocated. + /// + unsigned getNumBlockIDs() const { return (unsigned)MBBNumbering.size(); } + + /// RenumberBlocks - This discards all of the MachineBasicBlock numbers and + /// recomputes them. This guarantees that the MBB numbers are sequential, + /// dense, and match the ordering of the blocks within the function. If a + /// specific MachineBasicBlock is specified, only that block and those after + /// it are renumbered. + void RenumberBlocks(MachineBasicBlock *MBBFrom = 0); + + /// print - Print out the MachineFunction in a format suitable for debugging + /// to the specified stream. + /// + void print(raw_ostream &OS) const; + + /// viewCFG - This function is meant for use from the debugger. You can just + /// say 'call F->viewCFG()' and a ghostview window should pop up from the + /// program, displaying the CFG of the current function with the code for each + /// basic block inside. This depends on there being a 'dot' and 'gv' program + /// in your path. + /// + void viewCFG() const; + + /// viewCFGOnly - This function is meant for use from the debugger. It works + /// just like viewCFG, but it does not include the contents of basic blocks + /// into the nodes, just the label. If you are only interested in the CFG + /// this can make the graph smaller. + /// + void viewCFGOnly() const; + + /// dump - Print the current MachineFunction to cerr, useful for debugger use. + /// + void dump() const; + + /// verify - Run the current MachineFunction through the machine code + /// verifier, useful for debugger use. + void verify(Pass *p=NULL, bool allowDoubleDefs=false) const; + + // Provide accessors for the MachineBasicBlock list... + typedef BasicBlockListType::iterator iterator; + typedef BasicBlockListType::const_iterator const_iterator; + typedef std::reverse_iterator const_reverse_iterator; + typedef std::reverse_iterator reverse_iterator; + + /// addLiveIn - Add the specified physical register as a live-in value and + /// create a corresponding virtual register for it. + unsigned addLiveIn(unsigned PReg, const TargetRegisterClass *RC); + + //===--------------------------------------------------------------------===// + // BasicBlock accessor functions. + // + iterator begin() { return BasicBlocks.begin(); } + const_iterator begin() const { return BasicBlocks.begin(); } + iterator end () { return BasicBlocks.end(); } + const_iterator end () const { return BasicBlocks.end(); } + + reverse_iterator rbegin() { return BasicBlocks.rbegin(); } + const_reverse_iterator rbegin() const { return BasicBlocks.rbegin(); } + reverse_iterator rend () { return BasicBlocks.rend(); } + const_reverse_iterator rend () const { return BasicBlocks.rend(); } + + unsigned size() const { return (unsigned)BasicBlocks.size();} + bool empty() const { return BasicBlocks.empty(); } + const MachineBasicBlock &front() const { return BasicBlocks.front(); } + MachineBasicBlock &front() { return BasicBlocks.front(); } + const MachineBasicBlock & back() const { return BasicBlocks.back(); } + MachineBasicBlock & back() { return BasicBlocks.back(); } + + void push_back (MachineBasicBlock *MBB) { BasicBlocks.push_back (MBB); } + void push_front(MachineBasicBlock *MBB) { BasicBlocks.push_front(MBB); } + void insert(iterator MBBI, MachineBasicBlock *MBB) { + BasicBlocks.insert(MBBI, MBB); + } + void splice(iterator InsertPt, iterator MBBI) { + BasicBlocks.splice(InsertPt, BasicBlocks, MBBI); + } + void splice(iterator InsertPt, iterator MBBI, iterator MBBE) { + BasicBlocks.splice(InsertPt, BasicBlocks, MBBI, MBBE); + } + + void remove(iterator MBBI) { + BasicBlocks.remove(MBBI); + } + void erase(iterator MBBI) { + BasicBlocks.erase(MBBI); + } + + //===--------------------------------------------------------------------===// + // Internal functions used to automatically number MachineBasicBlocks + // + + /// getNextMBBNumber - Returns the next unique number to be assigned + /// to a MachineBasicBlock in this MachineFunction. + /// + unsigned addToMBBNumbering(MachineBasicBlock *MBB) { + MBBNumbering.push_back(MBB); + return (unsigned)MBBNumbering.size()-1; + } + + /// removeFromMBBNumbering - Remove the specific machine basic block from our + /// tracker, this is only really to be used by the MachineBasicBlock + /// implementation. + void removeFromMBBNumbering(unsigned N) { + assert(N < MBBNumbering.size() && "Illegal basic block #"); + MBBNumbering[N] = 0; + } + + /// CreateMachineInstr - Allocate a new MachineInstr. Use this instead + /// of `new MachineInstr'. + /// + MachineInstr *CreateMachineInstr(const TargetInstrDesc &TID, + DebugLoc DL, + bool NoImp = false); + + /// CloneMachineInstr - Create a new MachineInstr which is a copy of the + /// 'Orig' instruction, identical in all ways except the the instruction + /// has no parent, prev, or next. + /// + MachineInstr *CloneMachineInstr(const MachineInstr *Orig); + + /// DeleteMachineInstr - Delete the given MachineInstr. + /// + void DeleteMachineInstr(MachineInstr *MI); + + /// CreateMachineBasicBlock - Allocate a new MachineBasicBlock. Use this + /// instead of `new MachineBasicBlock'. + /// + MachineBasicBlock *CreateMachineBasicBlock(const BasicBlock *bb = 0); + + /// DeleteMachineBasicBlock - Delete the given MachineBasicBlock. + /// + void DeleteMachineBasicBlock(MachineBasicBlock *MBB); + + /// getMachineMemOperand - Allocate a new MachineMemOperand. + /// MachineMemOperands are owned by the MachineFunction and need not be + /// explicitly deallocated. + MachineMemOperand *getMachineMemOperand(const Value *v, unsigned f, + int64_t o, uint64_t s, + unsigned base_alignment); + + /// getMachineMemOperand - Allocate a new MachineMemOperand by copying + /// an existing one, adjusting by an offset and using the given size. + /// MachineMemOperands are owned by the MachineFunction and need not be + /// explicitly deallocated. + MachineMemOperand *getMachineMemOperand(const MachineMemOperand *MMO, + int64_t Offset, uint64_t Size); + + /// allocateMemRefsArray - Allocate an array to hold MachineMemOperand + /// pointers. This array is owned by the MachineFunction. + MachineInstr::mmo_iterator allocateMemRefsArray(unsigned long Num); + + /// extractLoadMemRefs - Allocate an array and populate it with just the + /// load information from the given MachineMemOperand sequence. + std::pair + extractLoadMemRefs(MachineInstr::mmo_iterator Begin, + MachineInstr::mmo_iterator End); + + /// extractStoreMemRefs - Allocate an array and populate it with just the + /// store information from the given MachineMemOperand sequence. + std::pair + extractStoreMemRefs(MachineInstr::mmo_iterator Begin, + MachineInstr::mmo_iterator End); + + //===--------------------------------------------------------------------===// + // Debug location. + // + + /// getDebugLocTuple - Get the DebugLocTuple for a given DebugLoc object. + DebugLocTuple getDebugLocTuple(DebugLoc DL) const; + + /// getDefaultDebugLoc - Get the default debug location for the machine + /// function. + DebugLoc getDefaultDebugLoc() const { return DefaultDebugLoc; } + + /// setDefaultDebugLoc - Get the default debug location for the machine + /// function. + void setDefaultDebugLoc(DebugLoc DL) { DefaultDebugLoc = DL; } + + /// getDebugLocInfo - Get the debug info location tracker. + DebugLocTracker &getDebugLocInfo() { return DebugLocInfo; } +}; + +//===--------------------------------------------------------------------===// +// GraphTraits specializations for function basic block graphs (CFGs) +//===--------------------------------------------------------------------===// + +// Provide specializations of GraphTraits to be able to treat a +// machine function as a graph of machine basic blocks... these are +// the same as the machine basic block iterators, except that the root +// node is implicitly the first node of the function. +// +template <> struct GraphTraits : + public GraphTraits { + static NodeType *getEntryNode(MachineFunction *F) { + return &F->front(); + } + + // nodes_iterator/begin/end - Allow iteration over all nodes in the graph + typedef MachineFunction::iterator nodes_iterator; + static nodes_iterator nodes_begin(MachineFunction *F) { return F->begin(); } + static nodes_iterator nodes_end (MachineFunction *F) { return F->end(); } +}; +template <> struct GraphTraits : + public GraphTraits { + static NodeType *getEntryNode(const MachineFunction *F) { + return &F->front(); + } + + // nodes_iterator/begin/end - Allow iteration over all nodes in the graph + typedef MachineFunction::const_iterator nodes_iterator; + static nodes_iterator nodes_begin(const MachineFunction *F) { + return F->begin(); + } + static nodes_iterator nodes_end (const MachineFunction *F) { + return F->end(); + } +}; + + +// Provide specializations of GraphTraits to be able to treat a function as a +// graph of basic blocks... and to walk it in inverse order. Inverse order for +// a function is considered to be when traversing the predecessor edges of a BB +// instead of the successor edges. +// +template <> struct GraphTraits > : + public GraphTraits > { + static NodeType *getEntryNode(Inverse G) { + return &G.Graph->front(); + } +}; +template <> struct GraphTraits > : + public GraphTraits > { + static NodeType *getEntryNode(Inverse G) { + return &G.Graph->front(); + } +}; + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/CodeGen/MachineFunctionAnalysis.h b/libclamav/c++/llvm/include/llvm/CodeGen/MachineFunctionAnalysis.h new file mode 100644 index 000000000..aa4cc9176 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/CodeGen/MachineFunctionAnalysis.h @@ -0,0 +1,49 @@ +//===-- MachineFunctionAnalysis.h - Owner of MachineFunctions ----*-C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the MachineFunctionAnalysis class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_MACHINE_FUNCTION_ANALYSIS_H +#define LLVM_CODEGEN_MACHINE_FUNCTION_ANALYSIS_H + +#include "llvm/Pass.h" +#include "llvm/Target/TargetMachine.h" + +namespace llvm { + +class MachineFunction; + +/// MachineFunctionAnalysis - This class is a Pass that manages a +/// MachineFunction object. +struct MachineFunctionAnalysis : public FunctionPass { +private: + const TargetMachine &TM; + CodeGenOpt::Level OptLevel; + MachineFunction *MF; + +public: + static char ID; + explicit MachineFunctionAnalysis(const TargetMachine &tm, + CodeGenOpt::Level OL = CodeGenOpt::Default); + ~MachineFunctionAnalysis(); + + MachineFunction &getMF() const { return *MF; } + CodeGenOpt::Level getOptLevel() const { return OptLevel; } + +private: + virtual bool runOnFunction(Function &F); + virtual void releaseMemory(); + virtual void getAnalysisUsage(AnalysisUsage &AU) const; +}; + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/CodeGen/MachineFunctionPass.h b/libclamav/c++/llvm/include/llvm/CodeGen/MachineFunctionPass.h new file mode 100644 index 000000000..bac110316 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/CodeGen/MachineFunctionPass.h @@ -0,0 +1,56 @@ +//===-- MachineFunctionPass.h - Pass for MachineFunctions --------*-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 the MachineFunctionPass class. MachineFunctionPass's are +// just FunctionPass's, except they operate on machine code as part of a code +// generator. Because they operate on machine code, not the LLVM +// representation, MachineFunctionPass's are not allowed to modify the LLVM +// representation. Due to this limitation, the MachineFunctionPass class takes +// care of declaring that no LLVM passes are invalidated. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_MACHINE_FUNCTION_PASS_H +#define LLVM_CODEGEN_MACHINE_FUNCTION_PASS_H + +#include "llvm/Pass.h" + +namespace llvm { + +class MachineFunction; + +/// MachineFunctionPass - This class adapts the FunctionPass interface to +/// allow convenient creation of passes that operate on the MachineFunction +/// representation. Instead of overriding runOnFunction, subclasses +/// override runOnMachineFunction. +class MachineFunctionPass : public FunctionPass { +protected: + explicit MachineFunctionPass(intptr_t ID) : FunctionPass(ID) {} + explicit MachineFunctionPass(void *ID) : FunctionPass(ID) {} + + /// runOnMachineFunction - This method must be overloaded to perform the + /// desired machine code transformation or analysis. + /// + virtual bool runOnMachineFunction(MachineFunction &MF) = 0; + + /// getAnalysisUsage - Subclasses that override getAnalysisUsage + /// must call this. + /// + /// For MachineFunctionPasses, calling AU.preservesCFG() indicates that + /// the pass does not modify the MachineBasicBlock CFG. + /// + virtual void getAnalysisUsage(AnalysisUsage &AU) const; + +private: + bool runOnFunction(Function &F); +}; + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/CodeGen/MachineInstr.h b/libclamav/c++/llvm/include/llvm/CodeGen/MachineInstr.h new file mode 100644 index 000000000..c62044940 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/CodeGen/MachineInstr.h @@ -0,0 +1,396 @@ +//===-- llvm/CodeGen/MachineInstr.h - MachineInstr class --------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the declaration of the MachineInstr class, which is the +// basic representation for all target dependent machine instructions used by +// the back end. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_MACHINEINSTR_H +#define LLVM_CODEGEN_MACHINEINSTR_H + +#include "llvm/ADT/ilist.h" +#include "llvm/ADT/ilist_node.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/CodeGen/AsmPrinter.h" +#include "llvm/CodeGen/MachineOperand.h" +#include "llvm/Target/TargetInstrDesc.h" +#include "llvm/Support/DebugLoc.h" +#include + +namespace llvm { + +class AliasAnalysis; +class TargetInstrDesc; +class TargetInstrInfo; +class TargetRegisterInfo; +class MachineFunction; +class MachineMemOperand; + +//===----------------------------------------------------------------------===// +/// MachineInstr - Representation of each machine instruction. +/// +class MachineInstr : public ilist_node { +public: + typedef MachineMemOperand **mmo_iterator; + +private: + const TargetInstrDesc *TID; // Instruction descriptor. + unsigned short NumImplicitOps; // Number of implicit operands (which + // are determined at construction time). + + unsigned short AsmPrinterFlags; // Various bits of information used by + // the AsmPrinter to emit helpful + // comments. This is *not* semantic + // information. Do not use this for + // anything other than to convey comment + // information to AsmPrinter. + + std::vector Operands; // the operands + mmo_iterator MemRefs; // information on memory references + mmo_iterator MemRefsEnd; + MachineBasicBlock *Parent; // Pointer to the owning basic block. + 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 + void operator=(const MachineInstr&); // DO NOT IMPLEMENT + + // Intrusive list support + friend struct ilist_traits; + friend struct ilist_traits; + void setParent(MachineBasicBlock *P) { Parent = P; } + + /// MachineInstr ctor - This constructor creates a copy of the given + /// MachineInstr in the given MachineFunction. + MachineInstr(MachineFunction &, const MachineInstr &); + + /// MachineInstr ctor - This constructor creates a dummy MachineInstr with + /// TID NULL and no operands. + MachineInstr(); + + // The next two constructors have DebugLoc and non-DebugLoc versions; + // over time, the non-DebugLoc versions should be phased out and eventually + // removed. + + /// MachineInstr ctor - This constructor create a MachineInstr and add the + /// implicit operands. It reserves space for number of operands specified by + /// TargetInstrDesc. The version with a DebugLoc should be preferred. + explicit MachineInstr(const TargetInstrDesc &TID, bool NoImp = false); + + /// MachineInstr ctor - Work exactly the same as the ctor above, except that + /// the MachineInstr is created and added to the end of the specified basic + /// block. The version with a DebugLoc should be preferred. + /// + MachineInstr(MachineBasicBlock *MBB, const TargetInstrDesc &TID); + + /// MachineInstr ctor - This constructor create a MachineInstr and add the + /// implicit operands. It reserves space for number of operands specified by + /// TargetInstrDesc. An explicit DebugLoc is supplied. + explicit MachineInstr(const TargetInstrDesc &TID, const DebugLoc dl, + bool NoImp = false); + + /// MachineInstr ctor - Work exactly the same as the ctor above, except that + /// the MachineInstr is created and added to the end of the specified basic + /// block. + /// + MachineInstr(MachineBasicBlock *MBB, const DebugLoc dl, + const TargetInstrDesc &TID); + + ~MachineInstr(); + + // MachineInstrs are pool-allocated and owned by MachineFunction. + friend class MachineFunction; + +public: + const MachineBasicBlock* getParent() const { return Parent; } + MachineBasicBlock* getParent() { return Parent; } + + /// getAsmPrinterFlags - Return the asm printer flags bitvector. + /// + unsigned short getAsmPrinterFlags() const { return AsmPrinterFlags; } + + /// getAsmPrinterFlag - Return whether an AsmPrinter flag is set. + /// + bool getAsmPrinterFlag(AsmPrinter::CommentFlag Flag) const { + return AsmPrinterFlags & Flag; + } + + /// setAsmPrinterFlag - Set a flag for the AsmPrinter. + /// + void setAsmPrinterFlag(unsigned short Flag) { + AsmPrinterFlags |= Flag; + } + + /// getDebugLoc - Returns the debug location id of this MachineInstr. + /// + DebugLoc getDebugLoc() const { return debugLoc; } + + /// getDesc - Returns the target instruction descriptor of this + /// MachineInstr. + const TargetInstrDesc &getDesc() const { return *TID; } + + /// getOpcode - Returns the opcode of this MachineInstr. + /// + int getOpcode() const { return TID->Opcode; } + + /// Access to explicit operands of the instruction. + /// + unsigned getNumOperands() const { return (unsigned)Operands.size(); } + + const MachineOperand& getOperand(unsigned i) const { + assert(i < getNumOperands() && "getOperand() out of range!"); + return Operands[i]; + } + MachineOperand& getOperand(unsigned i) { + assert(i < getNumOperands() && "getOperand() out of range!"); + return Operands[i]; + } + + /// getNumExplicitOperands - Returns the number of non-implicit operands. + /// + unsigned getNumExplicitOperands() const; + + /// Access to memory operands of the instruction + mmo_iterator memoperands_begin() const { return MemRefs; } + mmo_iterator memoperands_end() const { return MemRefsEnd; } + bool memoperands_empty() const { return MemRefsEnd == MemRefs; } + + /// hasOneMemOperand - Return true if this instruction has exactly one + /// MachineMemOperand. + bool hasOneMemOperand() const { + return MemRefsEnd - MemRefs == 1; + } + + /// isIdenticalTo - Return true if this instruction is identical to (same + /// opcode and same operands as) the specified instruction. + bool isIdenticalTo(const MachineInstr *Other) const { + if (Other->getOpcode() != getOpcode() || + Other->getNumOperands() != getNumOperands()) + return false; + for (unsigned i = 0, e = getNumOperands(); i != e; ++i) + if (!getOperand(i).isIdenticalTo(Other->getOperand(i))) + return false; + return true; + } + + /// removeFromParent - This method unlinks 'this' from the containing basic + /// block, and returns it, but does not delete it. + MachineInstr *removeFromParent(); + + /// eraseFromParent - This method unlinks 'this' from the containing basic + /// block and deletes it. + void eraseFromParent(); + + /// isLabel - Returns true if the MachineInstr represents a label. + /// + bool isLabel() const; + + /// isDebugLabel - Returns true if the MachineInstr represents a debug label. + /// + bool isDebugLabel() const; + + /// readsRegister - Return true if the MachineInstr reads the specified + /// register. If TargetRegisterInfo is passed, then it also checks if there + /// is a read of a super-register. + bool readsRegister(unsigned Reg, const TargetRegisterInfo *TRI = NULL) const { + return findRegisterUseOperandIdx(Reg, false, TRI) != -1; + } + + /// killsRegister - Return true if the MachineInstr kills the specified + /// register. If TargetRegisterInfo is passed, then it also checks if there is + /// a kill of a super-register. + bool killsRegister(unsigned Reg, const TargetRegisterInfo *TRI = NULL) const { + return findRegisterUseOperandIdx(Reg, true, TRI) != -1; + } + + /// modifiesRegister - Return true if the MachineInstr modifies the + /// specified register. If TargetRegisterInfo is passed, then it also checks + /// if there is a def of a super-register. + bool modifiesRegister(unsigned Reg, + const TargetRegisterInfo *TRI = NULL) const { + return findRegisterDefOperandIdx(Reg, false, TRI) != -1; + } + + /// registerDefIsDead - Returns true if the register is dead in this machine + /// instruction. If TargetRegisterInfo is passed, then it also checks + /// if there is a dead def of a super-register. + bool registerDefIsDead(unsigned Reg, + const TargetRegisterInfo *TRI = NULL) const { + return findRegisterDefOperandIdx(Reg, true, TRI) != -1; + } + + /// findRegisterUseOperandIdx() - Returns the operand index that is a use of + /// the specific register or -1 if it is not found. It further tightens + /// the search criteria to a use that kills the register if isKill is true. + int findRegisterUseOperandIdx(unsigned Reg, bool isKill = false, + const TargetRegisterInfo *TRI = NULL) const; + + /// findRegisterUseOperand - Wrapper for findRegisterUseOperandIdx, it returns + /// a pointer to the MachineOperand rather than an index. + MachineOperand *findRegisterUseOperand(unsigned Reg, bool isKill = false, + const TargetRegisterInfo *TRI = NULL) { + int Idx = findRegisterUseOperandIdx(Reg, isKill, TRI); + return (Idx == -1) ? NULL : &getOperand(Idx); + } + + /// findRegisterDefOperandIdx() - Returns the operand index that is a def of + /// the specified register or -1 if it is not found. If isDead is true, defs + /// that are not dead are skipped. If TargetRegisterInfo is non-null, then it + /// also checks if there is a def of a super-register. + int findRegisterDefOperandIdx(unsigned Reg, bool isDead = false, + const TargetRegisterInfo *TRI = NULL) const; + + /// findRegisterDefOperand - Wrapper for findRegisterDefOperandIdx, it returns + /// a pointer to the MachineOperand rather than an index. + MachineOperand *findRegisterDefOperand(unsigned Reg, bool isDead = false, + const TargetRegisterInfo *TRI = NULL) { + int Idx = findRegisterDefOperandIdx(Reg, isDead, TRI); + return (Idx == -1) ? NULL : &getOperand(Idx); + } + + /// findFirstPredOperandIdx() - Find the index of the first operand in the + /// operand list that is used to represent the predicate. It returns -1 if + /// none is found. + int findFirstPredOperandIdx() const; + + /// isRegTiedToUseOperand - Given the index of a register def operand, + /// check if the register def is tied to a source operand, due to either + /// two-address elimination or inline assembly constraints. Returns the + /// first tied use operand index by reference is UseOpIdx is not null. + bool isRegTiedToUseOperand(unsigned DefOpIdx, unsigned *UseOpIdx = 0) const; + + /// isRegTiedToDefOperand - Return true if the use operand of the specified + /// index is tied to an def operand. It also returns the def operand index by + /// reference if DefOpIdx is not null. + bool isRegTiedToDefOperand(unsigned UseOpIdx, unsigned *DefOpIdx = 0) const; + + /// copyKillDeadInfo - Copies kill / dead operand properties from MI. + /// + void copyKillDeadInfo(const MachineInstr *MI); + + /// copyPredicates - Copies predicate operand(s) from MI. + void copyPredicates(const MachineInstr *MI); + + /// addRegisterKilled - We have determined MI kills a register. Look for the + /// operand that uses it and mark it as IsKill. If AddIfNotFound is true, + /// add a implicit operand if it's not found. Returns true if the operand + /// exists / is added. + bool addRegisterKilled(unsigned IncomingReg, + const TargetRegisterInfo *RegInfo, + bool AddIfNotFound = false); + + /// addRegisterDead - We have determined MI defined a register without a use. + /// Look for the operand that defines it and mark it as IsDead. If + /// AddIfNotFound is true, add a implicit operand if it's not found. Returns + /// true if the operand exists / is added. + bool addRegisterDead(unsigned IncomingReg, const TargetRegisterInfo *RegInfo, + bool AddIfNotFound = false); + + /// isSafeToMove - Return true if it is safe to move this instruction. If + /// SawStore is set to true, it means that there is a store (or call) between + /// the instruction's location and its intended destination. + bool isSafeToMove(const TargetInstrInfo *TII, bool &SawStore, + AliasAnalysis *AA) const; + + /// isSafeToReMat - Return true if it's safe to rematerialize the specified + /// instruction which defined the specified register instead of copying it. + bool isSafeToReMat(const TargetInstrInfo *TII, unsigned DstReg, + AliasAnalysis *AA) const; + + /// hasVolatileMemoryRef - Return true if this instruction may have a + /// volatile memory reference, or if the information describing the + /// memory reference is not available. Return false if it is known to + /// have no volatile memory references. + bool hasVolatileMemoryRef() const; + + /// isInvariantLoad - Return true if this instruction is loading from a + /// location whose value is invariant across the function. For example, + /// loading a value from the constant pool or from from the argument area of + /// a function if it does not change. This should only return true of *all* + /// loads the instruction does are invariant (if it does multiple loads). + bool isInvariantLoad(AliasAnalysis *AA) const; + + // + // Debugging support + // + void print(raw_ostream &OS, const TargetMachine *TM = 0) const; + void dump() const; + + //===--------------------------------------------------------------------===// + // Accessors used to build up machine instructions. + + /// addOperand - Add the specified operand to the instruction. If it is an + /// implicit operand, it is added to the end of the operand list. If it is + /// an explicit operand it is added at the end of the explicit operand list + /// (before the first implicit operand). + void addOperand(const MachineOperand &Op); + + /// setDesc - Replace the instruction descriptor (thus opcode) of + /// the current instruction with a new one. + /// + void setDesc(const TargetInstrDesc &tid) { TID = &tid; } + + /// setDebugLoc - Replace current source information with new such. + /// Avoid using this, the constructor argument is preferable. + /// + void setDebugLoc(const DebugLoc dl) { debugLoc = dl; } + + /// RemoveOperand - Erase an operand from an instruction, leaving it with one + /// fewer operand than it started with. + /// + void RemoveOperand(unsigned i); + + /// addMemOperand - Add a MachineMemOperand to the machine instruction. + /// This function should be used only occasionally. The setMemRefs function + /// is the primary method for setting up a MachineInstr's MemRefs list. + void addMemOperand(MachineFunction &MF, MachineMemOperand *MO); + + /// setMemRefs - Assign this MachineInstr's memory reference descriptor + /// list. This does not transfer ownership. + void setMemRefs(mmo_iterator NewMemRefs, mmo_iterator NewMemRefsEnd) { + MemRefs = NewMemRefs; + MemRefsEnd = NewMemRefsEnd; + } + +private: + /// getRegInfo - If this instruction is embedded into a MachineFunction, + /// return the MachineRegisterInfo object for the current function, otherwise + /// return null. + MachineRegisterInfo *getRegInfo(); + + /// addImplicitDefUseOperands - Add all implicit def and use operands to + /// this instruction. + void addImplicitDefUseOperands(); + + /// RemoveRegOperandsFromUseLists - Unlink all of the register operands in + /// this instruction from their respective use lists. This requires that the + /// operands already be on their use lists. + void RemoveRegOperandsFromUseLists(); + + /// AddRegOperandsToUseLists - Add all of the register operands in + /// this instruction from their respective use lists. This requires that the + /// operands not be on their use lists yet. + void AddRegOperandsToUseLists(MachineRegisterInfo &RegInfo); +}; + +//===----------------------------------------------------------------------===// +// Debugging Support + +inline raw_ostream& operator<<(raw_ostream &OS, const MachineInstr &MI) { + MI.print(OS); + return OS; +} + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/CodeGen/MachineInstrBuilder.h b/libclamav/c++/llvm/include/llvm/CodeGen/MachineInstrBuilder.h new file mode 100644 index 000000000..6ca63f011 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/CodeGen/MachineInstrBuilder.h @@ -0,0 +1,214 @@ +//===-- CodeGen/MachineInstBuilder.h - Simplify creation of MIs -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file exposes a function named BuildMI, which is useful for dramatically +// simplifying how MachineInstr's are created. It allows use of code like this: +// +// M = BuildMI(X86::ADDrr8, 2).addReg(argVal1).addReg(argVal2); +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_MACHINEINSTRBUILDER_H +#define LLVM_CODEGEN_MACHINEINSTRBUILDER_H + +#include "llvm/CodeGen/MachineFunction.h" + +namespace llvm { + +class TargetInstrDesc; + +namespace RegState { + enum { + Define = 0x2, + Implicit = 0x4, + Kill = 0x8, + Dead = 0x10, + Undef = 0x20, + EarlyClobber = 0x40, + ImplicitDefine = Implicit | Define, + ImplicitKill = Implicit | Kill + }; +} + +class MachineInstrBuilder { + MachineInstr *MI; +public: + MachineInstrBuilder() : MI(0) {} + explicit MachineInstrBuilder(MachineInstr *mi) : MI(mi) {} + + /// Allow automatic conversion to the machine instruction we are working on. + /// + operator MachineInstr*() const { return MI; } + operator MachineBasicBlock::iterator() const { return MI; } + + /// addReg - Add a new virtual register operand... + /// + const + MachineInstrBuilder &addReg(unsigned RegNo, unsigned flags = 0, + unsigned SubReg = 0) const { + assert((flags & 0x1) == 0 && + "Passing in 'true' to addReg is forbidden! Use enums instead."); + MI->addOperand(MachineOperand::CreateReg(RegNo, + flags & RegState::Define, + flags & RegState::Implicit, + flags & RegState::Kill, + flags & RegState::Dead, + flags & RegState::Undef, + flags & RegState::EarlyClobber, + SubReg)); + return *this; + } + + /// addImm - Add a new immediate operand. + /// + const MachineInstrBuilder &addImm(int64_t Val) const { + MI->addOperand(MachineOperand::CreateImm(Val)); + return *this; + } + + const MachineInstrBuilder &addFPImm(const ConstantFP *Val) const { + MI->addOperand(MachineOperand::CreateFPImm(Val)); + return *this; + } + + const MachineInstrBuilder &addMBB(MachineBasicBlock *MBB, + unsigned char TargetFlags = 0) const { + MI->addOperand(MachineOperand::CreateMBB(MBB, TargetFlags)); + return *this; + } + + const MachineInstrBuilder &addFrameIndex(unsigned Idx) const { + MI->addOperand(MachineOperand::CreateFI(Idx)); + return *this; + } + + const MachineInstrBuilder &addConstantPoolIndex(unsigned Idx, + int Offset = 0, + unsigned char TargetFlags = 0) const { + MI->addOperand(MachineOperand::CreateCPI(Idx, Offset, TargetFlags)); + return *this; + } + + const MachineInstrBuilder &addJumpTableIndex(unsigned Idx, + unsigned char TargetFlags = 0) const { + MI->addOperand(MachineOperand::CreateJTI(Idx, TargetFlags)); + return *this; + } + + const MachineInstrBuilder &addGlobalAddress(GlobalValue *GV, + int64_t Offset = 0, + unsigned char TargetFlags = 0) const { + MI->addOperand(MachineOperand::CreateGA(GV, Offset, TargetFlags)); + return *this; + } + + const MachineInstrBuilder &addExternalSymbol(const char *FnName, + unsigned char TargetFlags = 0) const { + MI->addOperand(MachineOperand::CreateES(FnName, TargetFlags)); + return *this; + } + + const MachineInstrBuilder &addMemOperand(MachineMemOperand *MMO) const { + MI->addMemOperand(*MI->getParent()->getParent(), MMO); + return *this; + } + + const MachineInstrBuilder &addOperand(const MachineOperand &MO) const { + MI->addOperand(MO); + return *this; + } +}; + +/// BuildMI - Builder interface. Specify how to create the initial instruction +/// itself. +/// +inline MachineInstrBuilder BuildMI(MachineFunction &MF, + DebugLoc DL, + const TargetInstrDesc &TID) { + return MachineInstrBuilder(MF.CreateMachineInstr(TID, DL)); +} + +/// BuildMI - This version of the builder sets up the first operand as a +/// destination virtual register. +/// +inline MachineInstrBuilder BuildMI(MachineFunction &MF, + DebugLoc DL, + const TargetInstrDesc &TID, + unsigned DestReg) { + return MachineInstrBuilder(MF.CreateMachineInstr(TID, DL)) + .addReg(DestReg, RegState::Define); +} + +/// BuildMI - This version of the builder inserts the newly-built +/// instruction before the given position in the given MachineBasicBlock, and +/// sets up the first operand as a destination virtual register. +/// +inline MachineInstrBuilder BuildMI(MachineBasicBlock &BB, + MachineBasicBlock::iterator I, + DebugLoc DL, + const TargetInstrDesc &TID, + unsigned DestReg) { + MachineInstr *MI = BB.getParent()->CreateMachineInstr(TID, DL); + BB.insert(I, MI); + return MachineInstrBuilder(MI).addReg(DestReg, RegState::Define); +} + +/// BuildMI - This version of the builder inserts the newly-built +/// instruction before the given position in the given MachineBasicBlock, and +/// does NOT take a destination register. +/// +inline MachineInstrBuilder BuildMI(MachineBasicBlock &BB, + MachineBasicBlock::iterator I, + DebugLoc DL, + const TargetInstrDesc &TID) { + MachineInstr *MI = BB.getParent()->CreateMachineInstr(TID, DL); + BB.insert(I, MI); + return MachineInstrBuilder(MI); +} + +/// BuildMI - This version of the builder inserts the newly-built +/// instruction at the end of the given MachineBasicBlock, and does NOT take a +/// destination register. +/// +inline MachineInstrBuilder BuildMI(MachineBasicBlock *BB, + DebugLoc DL, + const TargetInstrDesc &TID) { + return BuildMI(*BB, BB->end(), DL, TID); +} + +/// BuildMI - This version of the builder inserts the newly-built +/// instruction at the end of the given MachineBasicBlock, and sets up the first +/// operand as a destination virtual register. +/// +inline MachineInstrBuilder BuildMI(MachineBasicBlock *BB, + DebugLoc DL, + const TargetInstrDesc &TID, + unsigned DestReg) { + return BuildMI(*BB, BB->end(), DL, TID, DestReg); +} + +inline unsigned getDefRegState(bool B) { + return B ? RegState::Define : 0; +} +inline unsigned getImplRegState(bool B) { + return B ? RegState::Implicit : 0; +} +inline unsigned getKillRegState(bool B) { + return B ? RegState::Kill : 0; +} +inline unsigned getDeadRegState(bool B) { + return B ? RegState::Dead : 0; +} +inline unsigned getUndefRegState(bool B) { + return B ? RegState::Undef : 0; +} + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/CodeGen/MachineJumpTableInfo.h b/libclamav/c++/llvm/include/llvm/CodeGen/MachineJumpTableInfo.h new file mode 100644 index 000000000..57c65c80a --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/CodeGen/MachineJumpTableInfo.h @@ -0,0 +1,96 @@ +//===-- CodeGen/MachineJumpTableInfo.h - Abstract Jump Tables --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// The MachineJumpTableInfo class keeps track of jump tables referenced by +// lowered switch instructions in the MachineFunction. +// +// Instructions reference the address of these jump tables through the use of +// MO_JumpTableIndex values. When emitting assembly or machine code, these +// virtual address references are converted to refer to the address of the +// function jump tables. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_MACHINEJUMPTABLEINFO_H +#define LLVM_CODEGEN_MACHINEJUMPTABLEINFO_H + +#include +#include + +namespace llvm { + +class MachineBasicBlock; +class TargetData; +class raw_ostream; + +/// MachineJumpTableEntry - One jump table in the jump table info. +/// +struct MachineJumpTableEntry { + /// MBBs - The vector of basic blocks from which to create the jump table. + std::vector MBBs; + + explicit MachineJumpTableEntry(const std::vector &M) + : MBBs(M) {} +}; + +class MachineJumpTableInfo { + unsigned EntrySize; + unsigned Alignment; + std::vector JumpTables; +public: + MachineJumpTableInfo(unsigned Size, unsigned Align) + : EntrySize(Size), Alignment(Align) {} + + /// getJumpTableIndex - Create a new jump table or return an existing one. + /// + unsigned getJumpTableIndex(const std::vector &DestBBs); + + /// isEmpty - Return true if there are no jump tables. + /// + bool isEmpty() const { return JumpTables.empty(); } + + const std::vector &getJumpTables() const { + return JumpTables; + } + + /// RemoveJumpTable - Mark the specific index as being dead. This will cause + /// it to not be emitted. + void RemoveJumpTable(unsigned Idx) { + JumpTables[Idx].MBBs.clear(); + } + + /// ReplaceMBBInJumpTables - If Old is the target of any jump tables, update + /// the jump tables to branch to New instead. + bool ReplaceMBBInJumpTables(MachineBasicBlock *Old, MachineBasicBlock *New); + + /// ReplaceMBBInJumpTable - If Old is a target of the jump tables, update + /// the jump table to branch to New instead. + bool ReplaceMBBInJumpTable(unsigned Idx, MachineBasicBlock *Old, + MachineBasicBlock *New); + + /// getEntrySize - Returns the size of an individual field in a jump table. + /// + unsigned getEntrySize() const { return EntrySize; } + + /// getAlignment - returns the target's preferred alignment for jump tables + unsigned getAlignment() const { return Alignment; } + + /// print - Used by the MachineFunction printer to print information about + /// jump tables. Implemented in MachineFunction.cpp + /// + void print(raw_ostream &OS) const; + + /// dump - Call to stderr. + /// + void dump() const; +}; + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/CodeGen/MachineLocation.h b/libclamav/c++/llvm/include/llvm/CodeGen/MachineLocation.h new file mode 100644 index 000000000..2db4e5571 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/CodeGen/MachineLocation.h @@ -0,0 +1,106 @@ +//===-- llvm/CodeGen/MachineLocation.h --------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// The MachineLocation class is used to represent a simple location in a machine +// frame. Locations will be one of two forms; a register or an address formed +// from a base address plus an offset. Register indirection can be specified by +// using an offset of zero. +// +// The MachineMove class is used to represent abstract move operations in the +// prolog/epilog of a compiled function. A collection of these objects can be +// used by a debug consumer to track the location of values when unwinding stack +// frames. +//===----------------------------------------------------------------------===// + + +#ifndef LLVM_CODEGEN_MACHINELOCATION_H +#define LLVM_CODEGEN_MACHINELOCATION_H + +namespace llvm { + +class MachineLocation { +private: + bool IsRegister; // True if location is a register. + unsigned Register; // gcc/gdb register number. + int Offset; // Displacement if not register. + +public: + enum { + // The target register number for an abstract frame pointer. The value is + // an arbitrary value greater than TargetRegisterInfo::FirstVirtualRegister. + VirtualFP = ~0U + }; + MachineLocation() + : IsRegister(false) + , Register(0) + , Offset(0) + {} + explicit MachineLocation(unsigned R) + : IsRegister(true) + , Register(R) + , Offset(0) + {} + MachineLocation(unsigned R, int O) + : IsRegister(false) + , Register(R) + , Offset(O) + {} + + // Accessors + bool isReg() const { return IsRegister; } + unsigned getReg() const { return Register; } + int getOffset() const { return Offset; } + void setIsRegister(bool Is) { IsRegister = Is; } + void setRegister(unsigned R) { Register = R; } + void setOffset(int O) { Offset = O; } + void set(unsigned R) { + IsRegister = true; + Register = R; + Offset = 0; + } + void set(unsigned R, int O) { + IsRegister = false; + Register = R; + Offset = O; + } + +#ifndef NDEBUG + void dump(); +#endif +}; + +class MachineMove { +private: + unsigned LabelID; // Label ID number for post-instruction + // address when result of move takes + // effect. + MachineLocation Destination; // Move to location. + MachineLocation Source; // Move from location. + +public: + MachineMove() + : LabelID(0) + , Destination() + , Source() + {} + + MachineMove(unsigned ID, MachineLocation &D, MachineLocation &S) + : LabelID(ID) + , Destination(D) + , Source(S) + {} + + // Accessors + unsigned getLabelID() const { return LabelID; } + const MachineLocation &getDestination() const { return Destination; } + const MachineLocation &getSource() const { return Source; } +}; + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/CodeGen/MachineLoopInfo.h b/libclamav/c++/llvm/include/llvm/CodeGen/MachineLoopInfo.h new file mode 100644 index 000000000..d3df805f6 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/CodeGen/MachineLoopInfo.h @@ -0,0 +1,174 @@ +//===- llvm/CodeGen/MachineLoopInfo.h - Natural Loop Calculator -*- 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 the MachineLoopInfo class that is used to identify natural +// loops and determine the loop depth of various nodes of the CFG. Note that +// natural loops may actually be several loops that share the same header node. +// +// This analysis calculates the nesting structure of loops in a function. For +// each natural loop identified, this analysis identifies natural loops +// contained entirely within the loop and the basic blocks the make up the loop. +// +// It can calculate on the fly various bits of information, for example: +// +// * whether there is a preheader for the loop +// * the number of back edges to the header +// * whether or not a particular block branches out of the loop +// * the successor blocks of the loop +// * the loop depth +// * the trip count +// * etc... +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_MACHINE_LOOP_INFO_H +#define LLVM_CODEGEN_MACHINE_LOOP_INFO_H + +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/Analysis/LoopInfo.h" + +namespace llvm { + +class MachineLoop : public LoopBase { +public: + MachineLoop(); + + /// getTopBlock - Return the "top" block in the loop, which is the first + /// block in the linear layout, ignoring any parts of the loop not + /// contiguous with the part the contains the header. + MachineBasicBlock *getTopBlock(); + + /// getBottomBlock - Return the "bottom" block in the loop, which is the last + /// block in the linear layout, ignoring any parts of the loop not + /// contiguous with the part the contains the header. + MachineBasicBlock *getBottomBlock(); + +private: + friend class LoopInfoBase; + explicit MachineLoop(MachineBasicBlock *MBB) + : LoopBase(MBB) {} +}; + +class MachineLoopInfo : public MachineFunctionPass { + LoopInfoBase LI; + friend class LoopBase; + + void operator=(const MachineLoopInfo &); // do not implement + MachineLoopInfo(const MachineLoopInfo &); // do not implement + + LoopInfoBase& getBase() { return LI; } + +public: + static char ID; // Pass identification, replacement for typeid + + MachineLoopInfo() : MachineFunctionPass(&ID) {} + + /// iterator/begin/end - The interface to the top-level loops in the current + /// function. + /// + typedef LoopInfoBase::iterator iterator; + inline iterator begin() const { return LI.begin(); } + inline iterator end() const { return LI.end(); } + bool empty() const { return LI.empty(); } + + /// 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. + /// + inline MachineLoop *getLoopFor(const MachineBasicBlock *BB) const { + return LI.getLoopFor(BB); + } + + /// operator[] - same as getLoopFor... + /// + inline const MachineLoop *operator[](const MachineBasicBlock *BB) const { + return LI.getLoopFor(BB); + } + + /// getLoopDepth - Return the loop nesting level of the specified block... + /// + inline unsigned getLoopDepth(const MachineBasicBlock *BB) const { + return LI.getLoopDepth(BB); + } + + // isLoopHeader - True if the block is a loop header node + inline bool isLoopHeader(MachineBasicBlock *BB) const { + return LI.isLoopHeader(BB); + } + + /// runOnFunction - Calculate the natural loop information. + /// + virtual bool runOnMachineFunction(MachineFunction &F); + + virtual void releaseMemory() { LI.releaseMemory(); } + + virtual void getAnalysisUsage(AnalysisUsage &AU) const; + + /// 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 + /// another loop. + inline MachineLoop *removeLoop(iterator I) { return LI.removeLoop(I); } + + /// changeLoopFor - Change the top-level loop that contains BB to the + /// specified loop. This should be used by transformations that restructure + /// the loop hierarchy tree. + inline void changeLoopFor(MachineBasicBlock *BB, MachineLoop *L) { + LI.changeLoopFor(BB, L); + } + + /// changeTopLevelLoop - Replace the specified loop in the top-level loops + /// list with the indicated loop. + inline void changeTopLevelLoop(MachineLoop *OldLoop, MachineLoop *NewLoop) { + LI.changeTopLevelLoop(OldLoop, NewLoop); + } + + /// addTopLevelLoop - This adds the specified loop to the collection of + /// top-level loops. + inline void addTopLevelLoop(MachineLoop *New) { + LI.addTopLevelLoop(New); + } + + /// removeBlock - This method completely removes BB from all data structures, + /// including all of the Loop objects it is nested in and our mapping from + /// MachineBasicBlocks to loops. + void removeBlock(MachineBasicBlock *BB) { + LI.removeBlock(BB); + } +}; + + +// Allow clients to walk the list of nested loops... +template <> struct GraphTraits { + typedef const MachineLoop NodeType; + typedef MachineLoopInfo::iterator ChildIteratorType; + + static NodeType *getEntryNode(const MachineLoop *L) { return L; } + static inline ChildIteratorType child_begin(NodeType *N) { + return N->begin(); + } + static inline ChildIteratorType child_end(NodeType *N) { + return N->end(); + } +}; + +template <> struct GraphTraits { + typedef MachineLoop NodeType; + typedef MachineLoopInfo::iterator ChildIteratorType; + + static NodeType *getEntryNode(MachineLoop *L) { return L; } + static inline ChildIteratorType child_begin(NodeType *N) { + return N->begin(); + } + static inline ChildIteratorType child_end(NodeType *N) { + return N->end(); + } +}; + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/CodeGen/MachineMemOperand.h b/libclamav/c++/llvm/include/llvm/CodeGen/MachineMemOperand.h new file mode 100644 index 000000000..5dee199c7 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/CodeGen/MachineMemOperand.h @@ -0,0 +1,108 @@ +//==- llvm/CodeGen/MachineMemOperand.h - MachineMemOperand class -*- C++ -*-==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the declaration of the MachineMemOperand class, which is a +// description of a memory reference. It is used to help track dependencies +// in the backend. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_MACHINEMEMOPERAND_H +#define LLVM_CODEGEN_MACHINEMEMOPERAND_H + +#include "llvm/System/DataTypes.h" + +namespace llvm { + +class Value; +class FoldingSetNodeID; +class raw_ostream; + +//===----------------------------------------------------------------------===// +/// MachineMemOperand - A description of a memory reference used in the backend. +/// Instead of holding a StoreInst or LoadInst, this class holds the address +/// Value of the reference along with a byte size and offset. This allows it +/// to describe lowered loads and stores. Also, the special PseudoSourceValue +/// objects can be used to represent loads and stores to memory locations +/// that aren't explicit in the regular LLVM IR. +/// +class MachineMemOperand { + int64_t Offset; + uint64_t Size; + const Value *V; + unsigned int Flags; + +public: + /// Flags values. These may be or'd together. + enum MemOperandFlags { + /// The memory access reads data. + MOLoad = 1, + /// The memory access writes data. + MOStore = 2, + /// The memory access is volatile. + MOVolatile = 4 + }; + + /// MachineMemOperand - Construct an MachineMemOperand object with the + /// specified address Value, flags, offset, size, and base alignment. + MachineMemOperand(const Value *v, unsigned int f, int64_t o, uint64_t s, + unsigned int base_alignment); + + /// getValue - Return the base address of the memory access. This may either + /// be a normal LLVM IR Value, or one of the special values used in CodeGen. + /// Special values are those obtained via + /// PseudoSourceValue::getFixedStack(int), PseudoSourceValue::getStack, and + /// other PseudoSourceValue member functions which return objects which stand + /// for frame/stack pointer relative references and other special references + /// which are not representable in the high-level IR. + const Value *getValue() const { return V; } + + /// getFlags - Return the raw flags of the source value, \see MemOperandFlags. + unsigned int getFlags() const { return Flags & 7; } + + /// getOffset - For normal values, this is a byte offset added to the base + /// address. For PseudoSourceValue::FPRel values, this is the FrameIndex + /// number. + int64_t getOffset() const { return Offset; } + + /// getSize - Return the size in bytes of the memory reference. + uint64_t getSize() const { return Size; } + + /// getAlignment - Return the minimum known alignment in bytes of the + /// actual memory reference. + uint64_t getAlignment() const; + + /// getBaseAlignment - Return the minimum known alignment in bytes of the + /// base address, without the offset. + uint64_t getBaseAlignment() const { return (1u << (Flags >> 3)) >> 1; } + + bool isLoad() const { return Flags & MOLoad; } + bool isStore() const { return Flags & MOStore; } + bool isVolatile() const { return Flags & MOVolatile; } + + /// refineAlignment - Update this MachineMemOperand to reflect the alignment + /// of MMO, if it has a greater alignment. This must only be used when the + /// new alignment applies to all users of this MachineMemOperand. + void refineAlignment(const MachineMemOperand *MMO); + + /// setValue - Change the SourceValue for this MachineMemOperand. This + /// should only be used when an object is being relocated and all references + /// to it are being updated. + void setValue(const Value *NewSV) { V = NewSV; } + + /// Profile - Gather unique data for the object. + /// + void Profile(FoldingSetNodeID &ID) const; +}; + +raw_ostream &operator<<(raw_ostream &OS, const MachineMemOperand &MRO); + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/CodeGen/MachineModuleInfo.h b/libclamav/c++/llvm/include/llvm/CodeGen/MachineModuleInfo.h new file mode 100644 index 000000000..bac9fce46 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/CodeGen/MachineModuleInfo.h @@ -0,0 +1,332 @@ +//===-- llvm/CodeGen/MachineModuleInfo.h ------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Collect meta information for a module. This information should be in a +// neutral form that can be used by different debugging and exception handling +// schemes. +// +// The organization of information is primarily clustered around the source +// compile units. The main exception is source line correspondence where +// inlining may interleave code from various compile units. +// +// The following information can be retrieved from the MachineModuleInfo. +// +// -- Source directories - Directories are uniqued based on their canonical +// string and assigned a sequential numeric ID (base 1.) +// -- Source files - Files are also uniqued based on their name and directory +// ID. A file ID is sequential number (base 1.) +// -- Source line correspondence - A vector of file ID, line#, column# triples. +// A DEBUG_LOCATION instruction is generated by the DAG Legalizer +// corresponding to each entry in the source line list. This allows a debug +// emitter to generate labels referenced by debug information tables. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_MACHINEMODULEINFO_H +#define LLVM_CODEGEN_MACHINEMODULEINFO_H + +#include "llvm/Support/Dwarf.h" +#include "llvm/System/DataTypes.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/UniqueVector.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallSet.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/CodeGen/MachineLocation.h" +#include "llvm/GlobalValue.h" +#include "llvm/Pass.h" +#include "llvm/Metadata.h" + +namespace llvm { + +//===----------------------------------------------------------------------===// +// Forward declarations. +class Constant; +class MDNode; +class GlobalVariable; +class MachineBasicBlock; +class MachineFunction; +class Module; +class PointerType; +class StructType; + + +/// MachineModuleInfoImpl - This class can be derived from and used by targets +/// to hold private target-specific information for each Module. Objects of +/// type are accessed/created with MMI::getInfo and destroyed when the +/// MachineModuleInfo is destroyed. +class MachineModuleInfoImpl { +public: + virtual ~MachineModuleInfoImpl(); +}; + + + +//===----------------------------------------------------------------------===// +/// LandingPadInfo - This structure is used to retain landing pad info for +/// the current function. +/// +struct LandingPadInfo { + MachineBasicBlock *LandingPadBlock; // Landing pad block. + SmallVector BeginLabels; // Labels prior to invoke. + SmallVector EndLabels; // Labels after invoke. + unsigned LandingPadLabel; // Label at beginning of landing pad. + Function *Personality; // Personality function. + std::vector TypeIds; // List of type ids (filters negative) + + explicit LandingPadInfo(MachineBasicBlock *MBB) + : LandingPadBlock(MBB) + , LandingPadLabel(0) + , Personality(NULL) + {} +}; + +//===----------------------------------------------------------------------===// +/// MachineModuleInfo - This class contains meta information specific to a +/// module. Queries can be made by different debugging and exception handling +/// schemes and reformated for specific use. +/// +class MachineModuleInfo : public ImmutablePass { + /// ObjFileMMI - This is the object-file-format-specific implementation of + /// MachineModuleInfoImpl, which lets targets accumulate whatever info they + /// want. + MachineModuleInfoImpl *ObjFileMMI; + + // LabelIDList - One entry per assigned label. Normally the entry is equal to + // the list index(+1). If the entry is zero then the label has been deleted. + // Any other value indicates the label has been deleted by is mapped to + // another label. + std::vector LabelIDList; + + // FrameMoves - List of moves done by a function's prolog. Used to construct + // frame maps by debug and exception handling consumers. + std::vector FrameMoves; + + // LandingPads - List of LandingPadInfo describing the landing pad information + // in the current function. + std::vector LandingPads; + + // TypeInfos - List of C++ TypeInfo used in the current function. + // + std::vector TypeInfos; + + // FilterIds - List of typeids encoding filters used in the current function. + // + std::vector FilterIds; + + // FilterEnds - List of the indices in FilterIds corresponding to filter + // terminators. + // + std::vector FilterEnds; + + // Personalities - Vector of all personality functions ever seen. Used to emit + // common EH frames. + std::vector Personalities; + + /// UsedFunctions - The functions in the @llvm.used list in a more easily + /// searchable format. This does not include the functions in + /// llvm.compiler.used. + SmallPtrSet UsedFunctions; + + bool CallsEHReturn; + bool CallsUnwindInit; + + /// DbgInfoAvailable - True if debugging information is available + /// in this module. + bool DbgInfoAvailable; + +public: + static char ID; // Pass identification, replacement for typeid + + typedef std::pair > UnsignedAndMDNodePair; + typedef SmallVector< std::pair, UnsignedAndMDNodePair>, 4> + VariableDbgInfoMapTy; + VariableDbgInfoMapTy VariableDbgInfo; + + MachineModuleInfo(); + ~MachineModuleInfo(); + + bool doInitialization(); + bool doFinalization(); + + /// BeginFunction - Begin gathering function meta information. + /// + void BeginFunction(MachineFunction *) {} + + /// EndFunction - Discard function meta information. + /// + void EndFunction(); + + /// getInfo - Keep track of various per-function pieces of information for + /// backends that would like to do so. + /// + template + Ty &getObjFileInfo() { + if (ObjFileMMI == 0) + ObjFileMMI = new Ty(*this); + + assert((void*)dynamic_cast(ObjFileMMI) == (void*)ObjFileMMI && + "Invalid concrete type or multiple inheritence for getInfo"); + return *static_cast(ObjFileMMI); + } + + template + const Ty &getObjFileInfo() const { + return const_cast(this)->getObjFileInfo(); + } + + /// AnalyzeModule - Scan the module for global debug information. + /// + void AnalyzeModule(Module &M); + + /// hasDebugInfo - Returns true if valid debug info is present. + /// + bool hasDebugInfo() const { return DbgInfoAvailable; } + void setDebugInfoAvailability(bool avail) { DbgInfoAvailable = true; } + + bool callsEHReturn() const { return CallsEHReturn; } + void setCallsEHReturn(bool b) { CallsEHReturn = b; } + + bool callsUnwindInit() const { return CallsUnwindInit; } + void setCallsUnwindInit(bool b) { CallsUnwindInit = b; } + + /// NextLabelID - Return the next unique label id. + /// + unsigned NextLabelID() { + unsigned ID = (unsigned)LabelIDList.size() + 1; + LabelIDList.push_back(ID); + return ID; + } + + /// InvalidateLabel - Inhibit use of the specified label # from + /// MachineModuleInfo, for example because the code was deleted. + void InvalidateLabel(unsigned LabelID) { + // Remap to zero to indicate deletion. + RemapLabel(LabelID, 0); + } + + /// RemapLabel - Indicate that a label has been merged into another. + /// + void RemapLabel(unsigned OldLabelID, unsigned NewLabelID) { + assert(0 < OldLabelID && OldLabelID <= LabelIDList.size() && + "Old label ID out of range."); + assert(NewLabelID <= LabelIDList.size() && + "New label ID out of range."); + LabelIDList[OldLabelID - 1] = NewLabelID; + } + + /// MappedLabel - Find out the label's final ID. Zero indicates deletion. + /// ID != Mapped ID indicates that the label was folded into another label. + unsigned MappedLabel(unsigned LabelID) const { + assert(LabelID <= LabelIDList.size() && "Debug label ID out of range."); + return LabelID ? LabelIDList[LabelID - 1] : 0; + } + + /// getFrameMoves - Returns a reference to a list of moves done in the current + /// function's prologue. Used to construct frame maps for debug and exception + /// handling comsumers. + std::vector &getFrameMoves() { return FrameMoves; } + + //===-EH-----------------------------------------------------------------===// + + /// getOrCreateLandingPadInfo - Find or create an LandingPadInfo for the + /// specified MachineBasicBlock. + LandingPadInfo &getOrCreateLandingPadInfo(MachineBasicBlock *LandingPad); + + /// addInvoke - Provide the begin and end labels of an invoke style call and + /// associate it with a try landing pad block. + void addInvoke(MachineBasicBlock *LandingPad, unsigned BeginLabel, + unsigned EndLabel); + + /// addLandingPad - Add a new panding pad. Returns the label ID for the + /// landing pad entry. + unsigned addLandingPad(MachineBasicBlock *LandingPad); + + /// addPersonality - Provide the personality function for the exception + /// information. + void addPersonality(MachineBasicBlock *LandingPad, Function *Personality); + + /// getPersonalityIndex - Get index of the current personality function inside + /// Personalitites array + unsigned getPersonalityIndex() const; + + /// getPersonalities - Return array of personality functions ever seen. + const std::vector& getPersonalities() const { + return Personalities; + } + + /// isUsedFunction - Return true if the functions in the llvm.used list. This + /// does not return true for things in llvm.compiler.used unless they are also + /// in llvm.used. + bool isUsedFunction(const Function *F) { + return UsedFunctions.count(F); + } + + /// addCatchTypeInfo - Provide the catch typeinfo for a landing pad. + /// + void addCatchTypeInfo(MachineBasicBlock *LandingPad, + std::vector &TyInfo); + + /// addFilterTypeInfo - Provide the filter typeinfo for a landing pad. + /// + void addFilterTypeInfo(MachineBasicBlock *LandingPad, + std::vector &TyInfo); + + /// addCleanup - Add a cleanup action for a landing pad. + /// + void addCleanup(MachineBasicBlock *LandingPad); + + /// getTypeIDFor - Return the type id for the specified typeinfo. This is + /// function wide. + unsigned getTypeIDFor(GlobalVariable *TI); + + /// getFilterIDFor - Return the id of the filter encoded by TyIds. This is + /// function wide. + int getFilterIDFor(std::vector &TyIds); + + /// TidyLandingPads - Remap landing pad labels and remove any deleted landing + /// pads. + void TidyLandingPads(); + + /// getLandingPads - Return a reference to the landing pad info for the + /// current function. + const std::vector &getLandingPads() const { + return LandingPads; + } + + /// getTypeInfos - Return a reference to the C++ typeinfo for the current + /// function. + const std::vector &getTypeInfos() const { + return TypeInfos; + } + + /// getFilterIds - Return a reference to the typeids encoding filters used in + /// the current function. + const std::vector &getFilterIds() const { + return FilterIds; + } + + /// getPersonality - Return a personality function if available. The presence + /// of one is required to emit exception handling info. + Function *getPersonality() const; + + /// setVariableDbgInfo - Collect information used to emit debugging information + /// of a variable. + void setVariableDbgInfo(MDNode *N, unsigned Slot, MDNode *Scope) { + VariableDbgInfo.push_back(std::make_pair(N, std::make_pair(Slot, Scope))); + } + + VariableDbgInfoMapTy &getVariableDbgInfo() { return VariableDbgInfo; } + +}; // End class MachineModuleInfo + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/CodeGen/MachineModuleInfoImpls.h b/libclamav/c++/llvm/include/llvm/CodeGen/MachineModuleInfoImpls.h new file mode 100644 index 000000000..44813cbdc --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/CodeGen/MachineModuleInfoImpls.h @@ -0,0 +1,79 @@ +//===-- llvm/CodeGen/MachineModuleInfoImpls.h -------------------*- 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 object-file format specific implementations of +// MachineModuleInfoImpl. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_MACHINEMODULEINFOIMPLS_H +#define LLVM_CODEGEN_MACHINEMODULEINFOIMPLS_H + +#include "llvm/CodeGen/MachineModuleInfo.h" + +namespace llvm { + class MCSymbol; + + /// MachineModuleInfoMachO - This is a MachineModuleInfoImpl implementation + /// for MachO targets. + class MachineModuleInfoMachO : public MachineModuleInfoImpl { + /// FnStubs - Darwin '$stub' stubs. The key is something like "Lfoo$stub", + /// the value is something like "_foo". + DenseMap FnStubs; + + /// GVStubs - Darwin '$non_lazy_ptr' stubs. The key is something like + /// "Lfoo$non_lazy_ptr", the value is something like "_foo". + DenseMap GVStubs; + + /// HiddenGVStubs - Darwin '$non_lazy_ptr' stubs. The key is something like + /// "Lfoo$non_lazy_ptr", the value is something like "_foo". Unlike GVStubs + /// these are for things with hidden visibility. + DenseMap HiddenGVStubs; + + virtual void Anchor(); // Out of line virtual method. + public: + MachineModuleInfoMachO(const MachineModuleInfo &) {} + + const MCSymbol *&getFnStubEntry(const MCSymbol *Sym) { + assert(Sym && "Key cannot be null"); + return FnStubs[Sym]; + } + + const MCSymbol *&getGVStubEntry(const MCSymbol *Sym) { + assert(Sym && "Key cannot be null"); + return GVStubs[Sym]; + } + + const MCSymbol *&getHiddenGVStubEntry(const MCSymbol *Sym) { + assert(Sym && "Key cannot be null"); + return HiddenGVStubs[Sym]; + } + + /// Accessor methods to return the set of stubs in sorted order. + typedef std::vector > + SymbolListTy; + + SymbolListTy GetFnStubList() const { + return GetSortedStubs(FnStubs); + } + SymbolListTy GetGVStubList() const { + return GetSortedStubs(GVStubs); + } + SymbolListTy GetHiddenGVStubList() const { + return GetSortedStubs(HiddenGVStubs); + } + + private: + static SymbolListTy + GetSortedStubs(const DenseMap &Map); + }; + +} // end namespace llvm + +#endif diff --git a/libclamav/c++/llvm/include/llvm/CodeGen/MachineOperand.h b/libclamav/c++/llvm/include/llvm/CodeGen/MachineOperand.h new file mode 100644 index 000000000..8748afcba --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/CodeGen/MachineOperand.h @@ -0,0 +1,479 @@ +//===-- llvm/CodeGen/MachineOperand.h - MachineOperand class ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the declaration of the MachineOperand class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_MACHINEOPERAND_H +#define LLVM_CODEGEN_MACHINEOPERAND_H + +#include "llvm/System/DataTypes.h" +#include + +namespace llvm { + +class ConstantFP; +class BlockAddress; +class MachineBasicBlock; +class GlobalValue; +class MachineInstr; +class TargetMachine; +class MachineRegisterInfo; +class raw_ostream; + +/// MachineOperand class - Representation of each machine instruction operand. +/// +class MachineOperand { +public: + enum MachineOperandType { + MO_Register, ///< Register operand. + MO_Immediate, ///< Immediate operand + MO_FPImmediate, ///< Floating-point immediate operand + MO_MachineBasicBlock, ///< MachineBasicBlock reference + MO_FrameIndex, ///< Abstract Stack Frame Index + MO_ConstantPoolIndex, ///< Address of indexed Constant in Constant Pool + MO_JumpTableIndex, ///< Address of indexed Jump Table for switch + MO_ExternalSymbol, ///< Name of external global symbol + MO_GlobalAddress, ///< Address of a global value + MO_BlockAddress ///< Address of a basic block + }; + +private: + /// OpKind - Specify what kind of operand this is. This discriminates the + /// union. + unsigned char OpKind; // MachineOperandType + + /// SubReg - Subregister number, only valid for MO_Register. A value of 0 + /// indicates the MO_Register has no subReg. + unsigned char SubReg; + + /// TargetFlags - This is a set of target-specific operand flags. + unsigned char TargetFlags; + + /// IsDef/IsImp/IsKill/IsDead flags - These are only valid for MO_Register + /// operands. + + /// IsDef - True if this is a def, false if this is a use of the register. + /// + bool IsDef : 1; + + /// IsImp - True if this is an implicit def or use, false if it is explicit. + /// + bool IsImp : 1; + + /// IsKill - True if this instruction is the last use of the register on this + /// path through the function. This is only valid on uses of registers. + bool IsKill : 1; + + /// IsDead - True if this register is never used by a subsequent instruction. + /// This is only valid on definitions of registers. + bool IsDead : 1; + + /// IsUndef - True if this is a register def / use of "undef", i.e. register + /// defined by an IMPLICIT_DEF. This is only valid on registers. + bool IsUndef : 1; + + /// IsEarlyClobber - True if this MO_Register 'def' operand is written to + /// by the MachineInstr before all input registers are read. This is used to + /// model the GCC inline asm '&' constraint modifier. + bool IsEarlyClobber : 1; + + /// ParentMI - This is the instruction that this operand is embedded into. + /// This is valid for all operand types, when the operand is in an instr. + MachineInstr *ParentMI; + + /// Contents union - This contains the payload for the various operand types. + union { + MachineBasicBlock *MBB; // For MO_MachineBasicBlock. + const ConstantFP *CFP; // For MO_FPImmediate. + int64_t ImmVal; // For MO_Immediate. + + struct { // For MO_Register. + unsigned RegNo; + MachineOperand **Prev; // Access list for register. + MachineOperand *Next; + } Reg; + + /// OffsetedInfo - This struct contains the offset and an object identifier. + /// this represent the object as with an optional offset from it. + struct { + union { + int Index; // For MO_*Index - The index itself. + const char *SymbolName; // For MO_ExternalSymbol. + GlobalValue *GV; // For MO_GlobalAddress. + BlockAddress *BA; // For MO_BlockAddress. + } Val; + int64_t Offset; // An offset from the object. + } OffsetedInfo; + } Contents; + + explicit MachineOperand(MachineOperandType K) : OpKind(K), ParentMI(0) { + TargetFlags = 0; + } +public: + /// getType - Returns the MachineOperandType for this operand. + /// + MachineOperandType getType() const { return (MachineOperandType)OpKind; } + + unsigned char getTargetFlags() const { return TargetFlags; } + void setTargetFlags(unsigned char F) { TargetFlags = F; } + void addTargetFlag(unsigned char F) { TargetFlags |= F; } + + + /// getParent - Return the instruction that this operand belongs to. + /// + MachineInstr *getParent() { return ParentMI; } + const MachineInstr *getParent() const { return ParentMI; } + + void print(raw_ostream &os, const TargetMachine *TM = 0) const; + + //===--------------------------------------------------------------------===// + // Accessors that tell you what kind of MachineOperand you're looking at. + //===--------------------------------------------------------------------===// + + /// isReg - Tests if this is a MO_Register operand. + bool isReg() const { return OpKind == MO_Register; } + /// isImm - Tests if this is a MO_Immediate operand. + bool isImm() const { return OpKind == MO_Immediate; } + /// isFPImm - Tests if this is a MO_FPImmediate operand. + bool isFPImm() const { return OpKind == MO_FPImmediate; } + /// isMBB - Tests if this is a MO_MachineBasicBlock operand. + bool isMBB() const { return OpKind == MO_MachineBasicBlock; } + /// isFI - Tests if this is a MO_FrameIndex operand. + bool isFI() const { return OpKind == MO_FrameIndex; } + /// isCPI - Tests if this is a MO_ConstantPoolIndex operand. + bool isCPI() const { return OpKind == MO_ConstantPoolIndex; } + /// isJTI - Tests if this is a MO_JumpTableIndex operand. + bool isJTI() const { return OpKind == MO_JumpTableIndex; } + /// isGlobal - Tests if this is a MO_GlobalAddress operand. + bool isGlobal() const { return OpKind == MO_GlobalAddress; } + /// isSymbol - Tests if this is a MO_ExternalSymbol operand. + bool isSymbol() const { return OpKind == MO_ExternalSymbol; } + /// isBlockAddress - Tests if this is a MO_BlockAddress operand. + bool isBlockAddress() const { return OpKind == MO_BlockAddress; } + + //===--------------------------------------------------------------------===// + // Accessors for Register Operands + //===--------------------------------------------------------------------===// + + /// getReg - Returns the register number. + unsigned getReg() const { + assert(isReg() && "This is not a register operand!"); + return Contents.Reg.RegNo; + } + + unsigned getSubReg() const { + assert(isReg() && "Wrong MachineOperand accessor"); + return (unsigned)SubReg; + } + + bool isUse() const { + assert(isReg() && "Wrong MachineOperand accessor"); + return !IsDef; + } + + bool isDef() const { + assert(isReg() && "Wrong MachineOperand accessor"); + return IsDef; + } + + bool isImplicit() const { + assert(isReg() && "Wrong MachineOperand accessor"); + return IsImp; + } + + bool isDead() const { + assert(isReg() && "Wrong MachineOperand accessor"); + return IsDead; + } + + bool isKill() const { + assert(isReg() && "Wrong MachineOperand accessor"); + return IsKill; + } + + bool isUndef() const { + assert(isReg() && "Wrong MachineOperand accessor"); + return IsUndef; + } + + bool isEarlyClobber() const { + assert(isReg() && "Wrong MachineOperand accessor"); + return IsEarlyClobber; + } + + /// getNextOperandForReg - Return the next MachineOperand in the function that + /// uses or defines this register. + MachineOperand *getNextOperandForReg() const { + assert(isReg() && "This is not a register operand!"); + return Contents.Reg.Next; + } + + //===--------------------------------------------------------------------===// + // Mutators for Register Operands + //===--------------------------------------------------------------------===// + + /// Change the register this operand corresponds to. + /// + void setReg(unsigned Reg); + + void setSubReg(unsigned subReg) { + assert(isReg() && "Wrong MachineOperand accessor"); + SubReg = (unsigned char)subReg; + } + + void setIsUse(bool Val = true) { + assert(isReg() && "Wrong MachineOperand accessor"); + IsDef = !Val; + } + + void setIsDef(bool Val = true) { + assert(isReg() && "Wrong MachineOperand accessor"); + IsDef = Val; + } + + void setImplicit(bool Val = true) { + assert(isReg() && "Wrong MachineOperand accessor"); + IsImp = Val; + } + + void setIsKill(bool Val = true) { + assert(isReg() && !IsDef && "Wrong MachineOperand accessor"); + IsKill = Val; + } + + void setIsDead(bool Val = true) { + assert(isReg() && IsDef && "Wrong MachineOperand accessor"); + IsDead = Val; + } + + void setIsUndef(bool Val = true) { + assert(isReg() && "Wrong MachineOperand accessor"); + IsUndef = Val; + } + + void setIsEarlyClobber(bool Val = true) { + assert(isReg() && IsDef && "Wrong MachineOperand accessor"); + IsEarlyClobber = Val; + } + + //===--------------------------------------------------------------------===// + // Accessors for various operand types. + //===--------------------------------------------------------------------===// + + int64_t getImm() const { + assert(isImm() && "Wrong MachineOperand accessor"); + return Contents.ImmVal; + } + + const ConstantFP *getFPImm() const { + assert(isFPImm() && "Wrong MachineOperand accessor"); + return Contents.CFP; + } + + MachineBasicBlock *getMBB() const { + assert(isMBB() && "Wrong MachineOperand accessor"); + return Contents.MBB; + } + + int getIndex() const { + assert((isFI() || isCPI() || isJTI()) && + "Wrong MachineOperand accessor"); + return Contents.OffsetedInfo.Val.Index; + } + + GlobalValue *getGlobal() const { + assert(isGlobal() && "Wrong MachineOperand accessor"); + return Contents.OffsetedInfo.Val.GV; + } + + BlockAddress *getBlockAddress() const { + assert(isBlockAddress() && "Wrong MachineOperand accessor"); + return Contents.OffsetedInfo.Val.BA; + } + + /// getOffset - Return the offset from the symbol in this operand. This always + /// returns 0 for ExternalSymbol operands. + int64_t getOffset() const { + assert((isGlobal() || isSymbol() || isCPI() || isBlockAddress()) && + "Wrong MachineOperand accessor"); + return Contents.OffsetedInfo.Offset; + } + + const char *getSymbolName() const { + assert(isSymbol() && "Wrong MachineOperand accessor"); + return Contents.OffsetedInfo.Val.SymbolName; + } + + //===--------------------------------------------------------------------===// + // Mutators for various operand types. + //===--------------------------------------------------------------------===// + + void setImm(int64_t immVal) { + assert(isImm() && "Wrong MachineOperand mutator"); + Contents.ImmVal = immVal; + } + + void setOffset(int64_t Offset) { + assert((isGlobal() || isSymbol() || isCPI() || isBlockAddress()) && + "Wrong MachineOperand accessor"); + Contents.OffsetedInfo.Offset = Offset; + } + + void setIndex(int Idx) { + assert((isFI() || isCPI() || isJTI()) && + "Wrong MachineOperand accessor"); + Contents.OffsetedInfo.Val.Index = Idx; + } + + void setMBB(MachineBasicBlock *MBB) { + assert(isMBB() && "Wrong MachineOperand accessor"); + Contents.MBB = MBB; + } + + //===--------------------------------------------------------------------===// + // Other methods. + //===--------------------------------------------------------------------===// + + /// isIdenticalTo - Return true if this operand is identical to the specified + /// operand. Note: This method ignores isKill and isDead properties. + bool isIdenticalTo(const MachineOperand &Other) const; + + /// ChangeToImmediate - Replace this operand with a new immediate operand of + /// the specified value. If an operand is known to be an immediate already, + /// the setImm method should be used. + void ChangeToImmediate(int64_t ImmVal); + + /// ChangeToRegister - Replace this operand with a new register operand of + /// the specified value. If an operand is known to be an register already, + /// the setReg method should be used. + void ChangeToRegister(unsigned Reg, bool isDef, bool isImp = false, + bool isKill = false, bool isDead = false, + bool isUndef = false); + + //===--------------------------------------------------------------------===// + // Construction methods. + //===--------------------------------------------------------------------===// + + static MachineOperand CreateImm(int64_t Val) { + MachineOperand Op(MachineOperand::MO_Immediate); + Op.setImm(Val); + return Op; + } + + static MachineOperand CreateFPImm(const ConstantFP *CFP) { + MachineOperand Op(MachineOperand::MO_FPImmediate); + Op.Contents.CFP = CFP; + return Op; + } + + static MachineOperand CreateReg(unsigned Reg, bool isDef, bool isImp = false, + bool isKill = false, bool isDead = false, + bool isUndef = false, + bool isEarlyClobber = false, + unsigned SubReg = 0) { + MachineOperand Op(MachineOperand::MO_Register); + Op.IsDef = isDef; + Op.IsImp = isImp; + Op.IsKill = isKill; + Op.IsDead = isDead; + Op.IsUndef = isUndef; + Op.IsEarlyClobber = isEarlyClobber; + Op.Contents.Reg.RegNo = Reg; + Op.Contents.Reg.Prev = 0; + Op.Contents.Reg.Next = 0; + Op.SubReg = SubReg; + return Op; + } + static MachineOperand CreateMBB(MachineBasicBlock *MBB, + unsigned char TargetFlags = 0) { + MachineOperand Op(MachineOperand::MO_MachineBasicBlock); + Op.setMBB(MBB); + Op.setTargetFlags(TargetFlags); + return Op; + } + static MachineOperand CreateFI(unsigned Idx) { + MachineOperand Op(MachineOperand::MO_FrameIndex); + Op.setIndex(Idx); + return Op; + } + static MachineOperand CreateCPI(unsigned Idx, int Offset, + unsigned char TargetFlags = 0) { + MachineOperand Op(MachineOperand::MO_ConstantPoolIndex); + Op.setIndex(Idx); + Op.setOffset(Offset); + Op.setTargetFlags(TargetFlags); + return Op; + } + static MachineOperand CreateJTI(unsigned Idx, + unsigned char TargetFlags = 0) { + MachineOperand Op(MachineOperand::MO_JumpTableIndex); + Op.setIndex(Idx); + Op.setTargetFlags(TargetFlags); + return Op; + } + static MachineOperand CreateGA(GlobalValue *GV, int64_t Offset, + unsigned char TargetFlags = 0) { + MachineOperand Op(MachineOperand::MO_GlobalAddress); + Op.Contents.OffsetedInfo.Val.GV = GV; + Op.setOffset(Offset); + Op.setTargetFlags(TargetFlags); + return Op; + } + static MachineOperand CreateES(const char *SymName, + unsigned char TargetFlags = 0) { + MachineOperand Op(MachineOperand::MO_ExternalSymbol); + Op.Contents.OffsetedInfo.Val.SymbolName = SymName; + Op.setOffset(0); // Offset is always 0. + Op.setTargetFlags(TargetFlags); + return Op; + } + static MachineOperand CreateBA(BlockAddress *BA, + unsigned char TargetFlags = 0) { + MachineOperand Op(MachineOperand::MO_BlockAddress); + Op.Contents.OffsetedInfo.Val.BA = BA; + Op.setOffset(0); // Offset is always 0. + Op.setTargetFlags(TargetFlags); + return Op; + } + + friend class MachineInstr; + friend class MachineRegisterInfo; +private: + //===--------------------------------------------------------------------===// + // Methods for handling register use/def lists. + //===--------------------------------------------------------------------===// + + /// isOnRegUseList - Return true if this operand is on a register use/def list + /// or false if not. This can only be called for register operands that are + /// part of a machine instruction. + bool isOnRegUseList() const { + assert(isReg() && "Can only add reg operand to use lists"); + return Contents.Reg.Prev != 0; + } + + /// AddRegOperandToRegInfo - Add this register operand to the specified + /// MachineRegisterInfo. If it is null, then the next/prev fields should be + /// explicitly nulled out. + void AddRegOperandToRegInfo(MachineRegisterInfo *RegInfo); + + /// RemoveRegOperandFromRegInfo - Remove this register operand from the + /// MachineRegisterInfo it is linked with. + void RemoveRegOperandFromRegInfo(); +}; + +inline raw_ostream &operator<<(raw_ostream &OS, const MachineOperand& MO) { + MO.print(OS, 0); + return OS; +} + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/CodeGen/MachinePassRegistry.h b/libclamav/c++/llvm/include/llvm/CodeGen/MachinePassRegistry.h new file mode 100644 index 000000000..680d2b80d --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/CodeGen/MachinePassRegistry.h @@ -0,0 +1,156 @@ +//===-- llvm/CodeGen/MachinePassRegistry.h ----------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the mechanics for machine function pass registries. A +// function pass registry (MachinePassRegistry) is auto filled by the static +// constructors of MachinePassRegistryNode. Further there is a command line +// parser (RegisterPassParser) which listens to each registry for additions +// and deletions, so that the appropriate command option is updated. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_MACHINEPASSREGISTRY_H +#define LLVM_CODEGEN_MACHINEPASSREGISTRY_H + +#include "llvm/CodeGen/Passes.h" +#include "llvm/Support/CommandLine.h" + +namespace llvm { + +typedef void *(*MachinePassCtor)(); + + +//===----------------------------------------------------------------------===// +/// +/// MachinePassRegistryListener - Listener to adds and removals of nodes in +/// registration list. +/// +//===----------------------------------------------------------------------===// +class MachinePassRegistryListener { +public: + MachinePassRegistryListener() {} + virtual ~MachinePassRegistryListener() {} + virtual void NotifyAdd(const char *N, MachinePassCtor C, const char *D) = 0; + virtual void NotifyRemove(const char *N) = 0; +}; + + +//===----------------------------------------------------------------------===// +/// +/// MachinePassRegistryNode - Machine pass node stored in registration list. +/// +//===----------------------------------------------------------------------===// +class MachinePassRegistryNode { + +private: + + MachinePassRegistryNode *Next; // Next function pass in list. + const char *Name; // Name of function pass. + const char *Description; // Description string. + MachinePassCtor Ctor; // Function pass creator. + +public: + + MachinePassRegistryNode(const char *N, const char *D, MachinePassCtor C) + : Next(NULL) + , Name(N) + , Description(D) + , Ctor(C) + {} + + // Accessors + MachinePassRegistryNode *getNext() const { return Next; } + MachinePassRegistryNode **getNextAddress() { return &Next; } + const char *getName() const { return Name; } + const char *getDescription() const { return Description; } + MachinePassCtor getCtor() const { return Ctor; } + void setNext(MachinePassRegistryNode *N) { Next = N; } + +}; + + +//===----------------------------------------------------------------------===// +/// +/// MachinePassRegistry - Track the registration of machine passes. +/// +//===----------------------------------------------------------------------===// +class MachinePassRegistry { + +private: + + MachinePassRegistryNode *List; // List of registry nodes. + MachinePassCtor Default; // Default function pass creator. + MachinePassRegistryListener* Listener;// Listener for list adds are removes. + +public: + + // NO CONSTRUCTOR - we don't want static constructor ordering to mess + // with the registry. + + // Accessors. + // + MachinePassRegistryNode *getList() { return List; } + MachinePassCtor getDefault() { return Default; } + void setDefault(MachinePassCtor C) { Default = C; } + void setListener(MachinePassRegistryListener *L) { Listener = L; } + + /// Add - Adds a function pass to the registration list. + /// + void Add(MachinePassRegistryNode *Node); + + /// Remove - Removes a function pass from the registration list. + /// + void Remove(MachinePassRegistryNode *Node); + +}; + + +//===----------------------------------------------------------------------===// +/// +/// RegisterPassParser class - Handle the addition of new machine passes. +/// +//===----------------------------------------------------------------------===// +template +class RegisterPassParser : public MachinePassRegistryListener, + public cl::parser { +public: + RegisterPassParser() {} + ~RegisterPassParser() { RegistryClass::setListener(NULL); } + + void initialize(cl::Option &O) { + cl::parser::initialize(O); + + // Add existing passes to option. + for (RegistryClass *Node = RegistryClass::getList(); + Node; Node = Node->getNext()) { + addLiteralOption(Node->getName(), + (typename RegistryClass::FunctionPassCtor)Node->getCtor(), + Node->getDescription()); + } + + // Make sure we listen for list changes. + RegistryClass::setListener(this); + } + + // Implement the MachinePassRegistryListener callbacks. + // + virtual void NotifyAdd(const char *N, + MachinePassCtor C, + const char *D) { + this->addLiteralOption(N, (typename RegistryClass::FunctionPassCtor)C, D); + } + virtual void NotifyRemove(const char *N) { + this->removeLiteralOption(N); + } +}; + + +} // end namespace llvm + +#endif diff --git a/libclamav/c++/llvm/include/llvm/CodeGen/MachineRegisterInfo.h b/libclamav/c++/llvm/include/llvm/CodeGen/MachineRegisterInfo.h new file mode 100644 index 000000000..c55cb3227 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/CodeGen/MachineRegisterInfo.h @@ -0,0 +1,339 @@ +//===-- llvm/CodeGen/MachineRegisterInfo.h ----------------------*- 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 the MachineRegisterInfo class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_MACHINEREGISTERINFO_H +#define LLVM_CODEGEN_MACHINEREGISTERINFO_H + +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/ADT/BitVector.h" +#include + +namespace llvm { + +/// MachineRegisterInfo - Keep track of information for virtual and physical +/// registers, including vreg register classes, use/def chains for registers, +/// etc. +class MachineRegisterInfo { + /// VRegInfo - Information we keep for each virtual register. The entries in + /// this vector are actually converted to vreg numbers by adding the + /// TargetRegisterInfo::FirstVirtualRegister delta to their index. + /// + /// Each element in this list contains the register class of the vreg and the + /// start of the use/def list for the register. + std::vector > VRegInfo; + + /// RegClassVRegMap - This vector acts as a map from TargetRegisterClass to + /// virtual registers. For each target register class, it keeps a list of + /// virtual registers belonging to the class. + std::vector > RegClass2VRegMap; + + /// RegAllocHints - This vector records register allocation hints for virtual + /// registers. For each virtual register, it keeps a register and hint type + /// pair making up the allocation hint. Hint type is target specific except + /// for the value 0 which means the second value of the pair is the preferred + /// register for allocation. For example, if the hint is <0, 1024>, it means + /// the allocator should prefer the physical register allocated to the virtual + /// register of the hint. + std::vector > RegAllocHints; + + /// PhysRegUseDefLists - This is an array of the head of the use/def list for + /// physical registers. + MachineOperand **PhysRegUseDefLists; + + /// UsedPhysRegs - This is a bit vector that is computed and set by the + /// register allocator, and must be kept up to date by passes that run after + /// register allocation (though most don't modify this). This is used + /// so that the code generator knows which callee save registers to save and + /// for other target specific uses. + BitVector UsedPhysRegs; + + /// LiveIns/LiveOuts - Keep track of the physical registers that are + /// livein/liveout of the function. Live in values are typically arguments in + /// registers, live out values are typically return values in registers. + /// LiveIn values are allowed to have virtual registers associated with them, + /// stored in the second element. + std::vector > LiveIns; + std::vector LiveOuts; + + MachineRegisterInfo(const MachineRegisterInfo&); // DO NOT IMPLEMENT + void operator=(const MachineRegisterInfo&); // DO NOT IMPLEMENT +public: + explicit MachineRegisterInfo(const TargetRegisterInfo &TRI); + ~MachineRegisterInfo(); + + //===--------------------------------------------------------------------===// + // Register Info + //===--------------------------------------------------------------------===// + + /// reg_begin/reg_end - Provide iteration support to walk over all definitions + /// and uses of a register within the MachineFunction that corresponds to this + /// MachineRegisterInfo object. + template + class defusechain_iterator; + + /// reg_iterator/reg_begin/reg_end - Walk all defs and uses of the specified + /// register. + typedef defusechain_iterator reg_iterator; + reg_iterator reg_begin(unsigned RegNo) const { + return reg_iterator(getRegUseDefListHead(RegNo)); + } + static reg_iterator reg_end() { return reg_iterator(0); } + + /// reg_empty - Return true if there are no instructions using or defining the + /// specified register (it may be live-in). + bool reg_empty(unsigned RegNo) const { return reg_begin(RegNo) == reg_end(); } + + /// def_iterator/def_begin/def_end - Walk all defs of the specified register. + typedef defusechain_iterator def_iterator; + def_iterator def_begin(unsigned RegNo) const { + return def_iterator(getRegUseDefListHead(RegNo)); + } + static def_iterator def_end() { return def_iterator(0); } + + /// def_empty - Return true if there are no instructions defining the + /// specified register (it may be live-in). + bool def_empty(unsigned RegNo) const { return def_begin(RegNo) == def_end(); } + + /// use_iterator/use_begin/use_end - Walk all uses of the specified register. + typedef defusechain_iterator use_iterator; + use_iterator use_begin(unsigned RegNo) const { + return use_iterator(getRegUseDefListHead(RegNo)); + } + static use_iterator use_end() { return use_iterator(0); } + + /// use_empty - Return true if there are no instructions using the specified + /// register. + bool use_empty(unsigned RegNo) const { return use_begin(RegNo) == use_end(); } + + + /// replaceRegWith - Replace all instances of FromReg with ToReg in the + /// machine function. This is like llvm-level X->replaceAllUsesWith(Y), + /// except that it also changes any definitions of the register as well. + void replaceRegWith(unsigned FromReg, unsigned ToReg); + + /// getRegUseDefListHead - Return the head pointer for the register use/def + /// list for the specified virtual or physical register. + MachineOperand *&getRegUseDefListHead(unsigned RegNo) { + if (RegNo < TargetRegisterInfo::FirstVirtualRegister) + return PhysRegUseDefLists[RegNo]; + RegNo -= TargetRegisterInfo::FirstVirtualRegister; + return VRegInfo[RegNo].second; + } + + MachineOperand *getRegUseDefListHead(unsigned RegNo) const { + if (RegNo < TargetRegisterInfo::FirstVirtualRegister) + return PhysRegUseDefLists[RegNo]; + RegNo -= TargetRegisterInfo::FirstVirtualRegister; + return VRegInfo[RegNo].second; + } + + /// getVRegDef - Return the machine instr that defines the specified virtual + /// register or null if none is found. This assumes that the code is in SSA + /// form, so there should only be one definition. + MachineInstr *getVRegDef(unsigned Reg) const; + +#ifndef NDEBUG + void dumpUses(unsigned RegNo) const; +#endif + + //===--------------------------------------------------------------------===// + // Virtual Register Info + //===--------------------------------------------------------------------===// + + /// getRegClass - Return the register class of the specified virtual register. + /// + const TargetRegisterClass *getRegClass(unsigned Reg) const { + Reg -= TargetRegisterInfo::FirstVirtualRegister; + assert(Reg < VRegInfo.size() && "Invalid vreg!"); + return VRegInfo[Reg].first; + } + + /// setRegClass - Set the register class of the specified virtual register. + /// + void setRegClass(unsigned Reg, const TargetRegisterClass *RC); + + /// createVirtualRegister - Create and return a new virtual register in the + /// function with the specified register class. + /// + unsigned createVirtualRegister(const TargetRegisterClass *RegClass); + + /// getLastVirtReg - Return the highest currently assigned virtual register. + /// + unsigned getLastVirtReg() const { + return (unsigned)VRegInfo.size()+TargetRegisterInfo::FirstVirtualRegister-1; + } + + /// getRegClassVirtRegs - Return the list of virtual registers of the given + /// target register class. + std::vector &getRegClassVirtRegs(const TargetRegisterClass *RC) { + return RegClass2VRegMap[RC->getID()]; + } + + /// setRegAllocationHint - Specify a register allocation hint for the + /// specified virtual register. + void setRegAllocationHint(unsigned Reg, unsigned Type, unsigned PrefReg) { + Reg -= TargetRegisterInfo::FirstVirtualRegister; + assert(Reg < VRegInfo.size() && "Invalid vreg!"); + RegAllocHints[Reg].first = Type; + RegAllocHints[Reg].second = PrefReg; + } + + /// getRegAllocationHint - Return the register allocation hint for the + /// specified virtual register. + std::pair + getRegAllocationHint(unsigned Reg) const { + Reg -= TargetRegisterInfo::FirstVirtualRegister; + assert(Reg < VRegInfo.size() && "Invalid vreg!"); + return RegAllocHints[Reg]; + } + + //===--------------------------------------------------------------------===// + // Physical Register Use Info + //===--------------------------------------------------------------------===// + + /// isPhysRegUsed - Return true if the specified register is used in this + /// function. This only works after register allocation. + bool isPhysRegUsed(unsigned Reg) const { return UsedPhysRegs[Reg]; } + + /// setPhysRegUsed - Mark the specified register used in this function. + /// This should only be called during and after register allocation. + void setPhysRegUsed(unsigned Reg) { UsedPhysRegs[Reg] = true; } + + /// setPhysRegUnused - Mark the specified register unused in this function. + /// This should only be called during and after register allocation. + void setPhysRegUnused(unsigned Reg) { UsedPhysRegs[Reg] = false; } + + + //===--------------------------------------------------------------------===// + // LiveIn/LiveOut Management + //===--------------------------------------------------------------------===// + + /// addLiveIn/Out - Add the specified register as a live in/out. Note that it + /// is an error to add the same register to the same set more than once. + void addLiveIn(unsigned Reg, unsigned vreg = 0) { + LiveIns.push_back(std::make_pair(Reg, vreg)); + } + void addLiveOut(unsigned Reg) { LiveOuts.push_back(Reg); } + + // Iteration support for live in/out sets. These sets are kept in sorted + // order by their register number. + typedef std::vector >::const_iterator + livein_iterator; + typedef std::vector::const_iterator liveout_iterator; + livein_iterator livein_begin() const { return LiveIns.begin(); } + livein_iterator livein_end() const { return LiveIns.end(); } + bool livein_empty() const { return LiveIns.empty(); } + liveout_iterator liveout_begin() const { return LiveOuts.begin(); } + liveout_iterator liveout_end() const { return LiveOuts.end(); } + bool liveout_empty() const { return LiveOuts.empty(); } + + bool isLiveIn(unsigned Reg) const { + for (livein_iterator I = livein_begin(), E = livein_end(); I != E; ++I) + if (I->first == Reg || I->second == Reg) + return true; + return false; + } + bool isLiveOut(unsigned Reg) const { + for (liveout_iterator I = liveout_begin(), E = liveout_end(); I != E; ++I) + if (*I == Reg) + return true; + return false; + } + +private: + void HandleVRegListReallocation(); + +public: + /// defusechain_iterator - This class provides iterator support for machine + /// operands in the function that use or define a specific register. If + /// ReturnUses is true it returns uses of registers, if ReturnDefs is true it + /// returns defs. If neither are true then you are silly and it always + /// returns end(). + template + class defusechain_iterator + : public std::iterator { + MachineOperand *Op; + explicit defusechain_iterator(MachineOperand *op) : Op(op) { + // If the first node isn't one we're interested in, advance to one that + // we are interested in. + if (op) { + if ((!ReturnUses && op->isUse()) || + (!ReturnDefs && op->isDef())) + ++*this; + } + } + friend class MachineRegisterInfo; + public: + typedef std::iterator::reference reference; + typedef std::iterator::pointer pointer; + + defusechain_iterator(const defusechain_iterator &I) : Op(I.Op) {} + defusechain_iterator() : Op(0) {} + + bool operator==(const defusechain_iterator &x) const { + return Op == x.Op; + } + bool operator!=(const defusechain_iterator &x) const { + return !operator==(x); + } + + /// atEnd - return true if this iterator is equal to reg_end() on the value. + bool atEnd() const { return Op == 0; } + + // Iterator traversal: forward iteration only + defusechain_iterator &operator++() { // Preincrement + assert(Op && "Cannot increment end iterator!"); + Op = Op->getNextOperandForReg(); + + // If this is an operand we don't care about, skip it. + while (Op && ((!ReturnUses && Op->isUse()) || + (!ReturnDefs && Op->isDef()))) + Op = Op->getNextOperandForReg(); + + return *this; + } + defusechain_iterator operator++(int) { // Postincrement + defusechain_iterator tmp = *this; ++*this; return tmp; + } + + MachineOperand &getOperand() const { + assert(Op && "Cannot dereference end iterator!"); + return *Op; + } + + /// getOperandNo - Return the operand # of this MachineOperand in its + /// MachineInstr. + unsigned getOperandNo() const { + assert(Op && "Cannot dereference end iterator!"); + return Op - &Op->getParent()->getOperand(0); + } + + // Retrieve a reference to the current operand. + MachineInstr &operator*() const { + assert(Op && "Cannot dereference end iterator!"); + return *Op->getParent(); + } + + MachineInstr *operator->() const { + assert(Op && "Cannot dereference end iterator!"); + return Op->getParent(); + } + }; + +}; + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/CodeGen/MachineRelocation.h b/libclamav/c++/llvm/include/llvm/CodeGen/MachineRelocation.h new file mode 100644 index 000000000..1c15fab53 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/CodeGen/MachineRelocation.h @@ -0,0 +1,341 @@ +//===-- llvm/CodeGen/MachineRelocation.h - Target Relocation ----*- 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 the MachineRelocation class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_MACHINERELOCATION_H +#define LLVM_CODEGEN_MACHINERELOCATION_H + +#include "llvm/System/DataTypes.h" +#include + +namespace llvm { +class GlobalValue; +class MachineBasicBlock; + +/// MachineRelocation - This represents a target-specific relocation value, +/// produced by the code emitter. This relocation is resolved after the has +/// been emitted, either to an object file or to memory, when the target of the +/// relocation can be resolved. +/// +/// A relocation is made up of the following logical portions: +/// 1. An offset in the machine code buffer, the location to modify. +/// 2. A target specific relocation type (a number from 0 to 63). +/// 3. A symbol being referenced, either as a GlobalValue* or as a string. +/// 4. An optional constant value to be added to the reference. +/// 5. A bit, CanRewrite, which indicates to the JIT that a function stub is +/// not needed for the relocation. +/// 6. An index into the GOT, if the target uses a GOT +/// +class MachineRelocation { + enum AddressType { + isResult, // Relocation has be transformed into its result pointer. + isGV, // The Target.GV field is valid. + isIndirectSym, // Relocation of an indirect symbol. + isBB, // Relocation of BB address. + isExtSym, // The Target.ExtSym field is valid. + isConstPool, // Relocation of constant pool address. + isJumpTable, // Relocation of jump table address. + isGOTIndex // The Target.GOTIndex field is valid. + }; + + /// Offset - This is the offset from the start of the code buffer of the + /// relocation to perform. + uintptr_t Offset; + + /// ConstantVal - A field that may be used by the target relocation type. + intptr_t ConstantVal; + + union { + void *Result; // If this has been resolved to a resolved pointer + GlobalValue *GV; // If this is a pointer to a GV or an indirect ref. + MachineBasicBlock *MBB; // If this is a pointer to a LLVM BB + const char *ExtSym; // If this is a pointer to a named symbol + unsigned Index; // Constant pool / jump table index + unsigned GOTIndex; // Index in the GOT of this symbol/global + } Target; + + unsigned TargetReloType : 6; // The target relocation ID + AddressType AddrType : 4; // The field of Target to use + bool MayNeedFarStub : 1; // True if this relocation may require a far-stub + bool GOTRelative : 1; // Should this relocation be relative to the GOT? + bool TargetResolve : 1; // True if target should resolve the address + +public: + // Relocation types used in a generic implementation. Currently, relocation + // entries for all things use the generic VANILLA type until they are refined + // into target relocation types. + enum RelocationType { + VANILLA + }; + + /// MachineRelocation::getGV - Return a relocation entry for a GlobalValue. + /// + static MachineRelocation getGV(uintptr_t offset, unsigned RelocationType, + GlobalValue *GV, intptr_t cst = 0, + bool MayNeedFarStub = 0, + bool GOTrelative = 0) { + assert((RelocationType & ~63) == 0 && "Relocation type too large!"); + MachineRelocation Result; + Result.Offset = offset; + Result.ConstantVal = cst; + Result.TargetReloType = RelocationType; + Result.AddrType = isGV; + Result.MayNeedFarStub = MayNeedFarStub; + Result.GOTRelative = GOTrelative; + Result.TargetResolve = false; + Result.Target.GV = GV; + return Result; + } + + /// MachineRelocation::getIndirectSymbol - Return a relocation entry for an + /// indirect symbol. + static MachineRelocation getIndirectSymbol(uintptr_t offset, + unsigned RelocationType, + GlobalValue *GV, intptr_t cst = 0, + bool MayNeedFarStub = 0, + bool GOTrelative = 0) { + assert((RelocationType & ~63) == 0 && "Relocation type too large!"); + MachineRelocation Result; + Result.Offset = offset; + Result.ConstantVal = cst; + Result.TargetReloType = RelocationType; + Result.AddrType = isIndirectSym; + Result.MayNeedFarStub = MayNeedFarStub; + Result.GOTRelative = GOTrelative; + Result.TargetResolve = false; + Result.Target.GV = GV; + return Result; + } + + /// MachineRelocation::getBB - Return a relocation entry for a BB. + /// + static MachineRelocation getBB(uintptr_t offset,unsigned RelocationType, + MachineBasicBlock *MBB, intptr_t cst = 0) { + assert((RelocationType & ~63) == 0 && "Relocation type too large!"); + MachineRelocation Result; + Result.Offset = offset; + Result.ConstantVal = cst; + Result.TargetReloType = RelocationType; + Result.AddrType = isBB; + Result.MayNeedFarStub = false; + Result.GOTRelative = false; + Result.TargetResolve = false; + Result.Target.MBB = MBB; + return Result; + } + + /// MachineRelocation::getExtSym - Return a relocation entry for an external + /// symbol, like "free". + /// + static MachineRelocation getExtSym(uintptr_t offset, unsigned RelocationType, + const char *ES, intptr_t cst = 0, + bool GOTrelative = 0) { + assert((RelocationType & ~63) == 0 && "Relocation type too large!"); + MachineRelocation Result; + Result.Offset = offset; + Result.ConstantVal = cst; + Result.TargetReloType = RelocationType; + Result.AddrType = isExtSym; + Result.MayNeedFarStub = true; + Result.GOTRelative = GOTrelative; + Result.TargetResolve = false; + Result.Target.ExtSym = ES; + return Result; + } + + /// MachineRelocation::getConstPool - Return a relocation entry for a constant + /// pool entry. + /// + static MachineRelocation getConstPool(uintptr_t offset,unsigned RelocationType, + unsigned CPI, intptr_t cst = 0, + bool letTargetResolve = false) { + assert((RelocationType & ~63) == 0 && "Relocation type too large!"); + MachineRelocation Result; + Result.Offset = offset; + Result.ConstantVal = cst; + Result.TargetReloType = RelocationType; + Result.AddrType = isConstPool; + Result.MayNeedFarStub = false; + Result.GOTRelative = false; + Result.TargetResolve = letTargetResolve; + Result.Target.Index = CPI; + return Result; + } + + /// MachineRelocation::getJumpTable - Return a relocation entry for a jump + /// table entry. + /// + static MachineRelocation getJumpTable(uintptr_t offset,unsigned RelocationType, + unsigned JTI, intptr_t cst = 0, + bool letTargetResolve = false) { + assert((RelocationType & ~63) == 0 && "Relocation type too large!"); + MachineRelocation Result; + Result.Offset = offset; + Result.ConstantVal = cst; + Result.TargetReloType = RelocationType; + Result.AddrType = isJumpTable; + Result.MayNeedFarStub = false; + Result.GOTRelative = false; + Result.TargetResolve = letTargetResolve; + Result.Target.Index = JTI; + return Result; + } + + /// getMachineCodeOffset - Return the offset into the code buffer that the + /// relocation should be performed. + intptr_t getMachineCodeOffset() const { + return Offset; + } + + /// getRelocationType - Return the target-specific relocation ID for this + /// relocation. + unsigned getRelocationType() const { + return TargetReloType; + } + + /// getConstantVal - Get the constant value associated with this relocation. + /// This is often an offset from the symbol. + /// + intptr_t getConstantVal() const { + return ConstantVal; + } + + /// setConstantVal - Set the constant value associated with this relocation. + /// This is often an offset from the symbol. + /// + void setConstantVal(intptr_t val) { + ConstantVal = val; + } + + /// isGlobalValue - Return true if this relocation is a GlobalValue, as + /// opposed to a constant string. + bool isGlobalValue() const { + return AddrType == isGV; + } + + /// isIndirectSymbol - Return true if this relocation is the address an + /// indirect symbol + bool isIndirectSymbol() const { + return AddrType == isIndirectSym; + } + + /// isBasicBlock - Return true if this relocation is a basic block reference. + /// + bool isBasicBlock() const { + return AddrType == isBB; + } + + /// isExternalSymbol - Return true if this is a constant string. + /// + bool isExternalSymbol() const { + return AddrType == isExtSym; + } + + /// isConstantPoolIndex - Return true if this is a constant pool reference. + /// + bool isConstantPoolIndex() const { + return AddrType == isConstPool; + } + + /// isJumpTableIndex - Return true if this is a jump table reference. + /// + bool isJumpTableIndex() const { + return AddrType == isJumpTable; + } + + /// isGOTRelative - Return true the target wants the index into the GOT of + /// the symbol rather than the address of the symbol. + bool isGOTRelative() const { + return GOTRelative; + } + + /// mayNeedFarStub - This function returns true if the JIT for this target may + /// need either a stub function or an indirect global-variable load to handle + /// the relocated GlobalValue reference. For example, the x86-64 call + /// instruction can only call functions within +/-2GB of the call site. + /// Anything farther away needs a longer mov+call sequence, which can't just + /// be written on top of the existing call. + bool mayNeedFarStub() const { + return MayNeedFarStub; + } + + /// letTargetResolve - Return true if the target JITInfo is usually + /// responsible for resolving the address of this relocation. + bool letTargetResolve() const { + return TargetResolve; + } + + /// getGlobalValue - If this is a global value reference, return the + /// referenced global. + GlobalValue *getGlobalValue() const { + assert((isGlobalValue() || isIndirectSymbol()) && + "This is not a global value reference!"); + return Target.GV; + } + + MachineBasicBlock *getBasicBlock() const { + assert(isBasicBlock() && "This is not a basic block reference!"); + return Target.MBB; + } + + /// getString - If this is a string value, return the string reference. + /// + const char *getExternalSymbol() const { + assert(isExternalSymbol() && "This is not an external symbol reference!"); + return Target.ExtSym; + } + + /// getConstantPoolIndex - If this is a const pool reference, return + /// the index into the constant pool. + unsigned getConstantPoolIndex() const { + assert(isConstantPoolIndex() && "This is not a constant pool reference!"); + return Target.Index; + } + + /// getJumpTableIndex - If this is a jump table reference, return + /// the index into the jump table. + unsigned getJumpTableIndex() const { + assert(isJumpTableIndex() && "This is not a jump table reference!"); + return Target.Index; + } + + /// getResultPointer - Once this has been resolved to point to an actual + /// address, this returns the pointer. + void *getResultPointer() const { + assert(AddrType == isResult && "Result pointer isn't set yet!"); + return Target.Result; + } + + /// setResultPointer - Set the result to the specified pointer value. + /// + void setResultPointer(void *Ptr) { + Target.Result = Ptr; + AddrType = isResult; + } + + /// setGOTIndex - Set the GOT index to a specific value. + void setGOTIndex(unsigned idx) { + AddrType = isGOTIndex; + Target.GOTIndex = idx; + } + + /// getGOTIndex - Once this has been resolved to an entry in the GOT, + /// this returns that index. The index is from the lowest address entry + /// in the GOT. + unsigned getGOTIndex() const { + assert(AddrType == isGOTIndex); + return Target.GOTIndex; + } +}; +} + +#endif diff --git a/libclamav/c++/llvm/include/llvm/CodeGen/ObjectCodeEmitter.h b/libclamav/c++/llvm/include/llvm/CodeGen/ObjectCodeEmitter.h new file mode 100644 index 000000000..8252e07d8 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/CodeGen/ObjectCodeEmitter.h @@ -0,0 +1,178 @@ +//===-- llvm/CodeGen/ObjectCodeEmitter.h - Object Code Emitter -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Generalized Object Code Emitter, works with ObjectModule and BinaryObject. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_OBJECTCODEEMITTER_H +#define LLVM_CODEGEN_OBJECTCODEEMITTER_H + +#include "llvm/CodeGen/MachineCodeEmitter.h" + +namespace llvm { + +class BinaryObject; +class MachineBasicBlock; +class MachineCodeEmitter; +class MachineFunction; +class MachineConstantPool; +class MachineJumpTableInfo; +class MachineModuleInfo; + +class ObjectCodeEmitter : public MachineCodeEmitter { +protected: + + /// Binary Object (Section or Segment) we are emitting to. + BinaryObject *BO; + + /// MBBLocations - This vector is a mapping from MBB ID's to their address. + /// It is filled in by the StartMachineBasicBlock callback and queried by + /// the getMachineBasicBlockAddress callback. + std::vector MBBLocations; + + /// LabelLocations - This vector is a mapping from Label ID's to their + /// address. + std::vector LabelLocations; + + /// CPLocations - This is a map of constant pool indices to offsets from the + /// start of the section for that constant pool index. + std::vector CPLocations; + + /// CPSections - This is a map of constant pool indices to the Section + /// containing the constant pool entry for that index. + std::vector CPSections; + + /// JTLocations - This is a map of jump table indices to offsets from the + /// start of the section for that jump table index. + std::vector JTLocations; + +public: + ObjectCodeEmitter(); + ObjectCodeEmitter(BinaryObject *bo); + virtual ~ObjectCodeEmitter(); + + /// setBinaryObject - set the BinaryObject we are writting to + void setBinaryObject(BinaryObject *bo); + + /// emitByte - This callback is invoked when a byte needs to be + /// written to the data stream, without buffer overflow testing. + void emitByte(uint8_t B); + + /// emitWordLE - This callback is invoked when a 32-bit word needs to be + /// written to the data stream in little-endian format. + void emitWordLE(uint32_t W); + + /// emitWordBE - This callback is invoked when a 32-bit word needs to be + /// written to the data stream in big-endian format. + void emitWordBE(uint32_t W); + + /// emitDWordLE - This callback is invoked when a 64-bit word needs to be + /// written to the data stream in little-endian format. + void emitDWordLE(uint64_t W); + + /// emitDWordBE - This callback is invoked when a 64-bit word needs to be + /// written to the data stream in big-endian format. + void emitDWordBE(uint64_t W); + + /// emitAlignment - Move the CurBufferPtr pointer up the the specified + /// alignment (saturated to BufferEnd of course). + void emitAlignment(unsigned Alignment = 0, uint8_t fill = 0); + + /// emitULEB128Bytes - This callback is invoked when a ULEB128 needs to be + /// written to the data stream. + void emitULEB128Bytes(uint64_t Value); + + /// emitSLEB128Bytes - This callback is invoked when a SLEB128 needs to be + /// written to the data stream. + void emitSLEB128Bytes(uint64_t Value); + + /// emitString - This callback is invoked when a String needs to be + /// written to the data stream. + void emitString(const std::string &String); + + /// getCurrentPCValue - This returns the address that the next emitted byte + /// will be output to. + uintptr_t getCurrentPCValue() const; + + /// getCurrentPCOffset - Return the offset from the start of the emitted + /// buffer that we are currently writing to. + uintptr_t getCurrentPCOffset() const; + + /// addRelocation - Whenever a relocatable address is needed, it should be + /// noted with this interface. + void addRelocation(const MachineRelocation& relocation); + + /// earlyResolveAddresses - True if the code emitter can use symbol addresses + /// during code emission time. The JIT is capable of doing this because it + /// creates jump tables or constant pools in memory on the fly while the + /// object code emitters rely on a linker to have real addresses and should + /// use relocations instead. + bool earlyResolveAddresses() const { return false; } + + /// startFunction - This callback is invoked when the specified function is + /// about to be code generated. This initializes the BufferBegin/End/Ptr + /// fields. + virtual void startFunction(MachineFunction &F) = 0; + + /// finishFunction - This callback is invoked when the specified function has + /// finished code generation. If a buffer overflow has occurred, this method + /// returns true (the callee is required to try again), otherwise it returns + /// false. + virtual bool finishFunction(MachineFunction &F) = 0; + + /// StartMachineBasicBlock - This should be called by the target when a new + /// basic block is about to be emitted. This way the MCE knows where the + /// start of the block is, and can implement getMachineBasicBlockAddress. + virtual void StartMachineBasicBlock(MachineBasicBlock *MBB); + + /// getMachineBasicBlockAddress - Return the address of the specified + /// MachineBasicBlock, only usable after the label for the MBB has been + /// emitted. + virtual uintptr_t getMachineBasicBlockAddress(MachineBasicBlock *MBB) const; + + /// emitLabel - Emits a label + virtual void emitLabel(uint64_t LabelID) = 0; + + /// getLabelAddress - Return the address of the specified LabelID, only usable + /// after the LabelID has been emitted. + virtual uintptr_t getLabelAddress(uint64_t LabelID) const = 0; + + /// emitJumpTables - Emit all the jump tables for a given jump table info + /// record to the appropriate section. + virtual void emitJumpTables(MachineJumpTableInfo *MJTI) = 0; + + /// getJumpTableEntryAddress - Return the address of the jump table with index + /// 'Index' in the function that last called initJumpTableInfo. + virtual uintptr_t getJumpTableEntryAddress(unsigned Index) const; + + /// emitConstantPool - For each constant pool entry, figure out which section + /// the constant should live in, allocate space for it, and emit it to the + /// Section data buffer. + virtual void emitConstantPool(MachineConstantPool *MCP) = 0; + + /// getConstantPoolEntryAddress - Return the address of the 'Index' entry in + /// the constant pool that was last emitted with the emitConstantPool method. + virtual uintptr_t getConstantPoolEntryAddress(unsigned Index) const; + + /// getConstantPoolEntrySection - Return the section of the 'Index' entry in + /// the constant pool that was last emitted with the emitConstantPool method. + virtual uintptr_t getConstantPoolEntrySection(unsigned Index) const; + + /// Specifies the MachineModuleInfo object. This is used for exception handling + /// purposes. + virtual void setModuleInfo(MachineModuleInfo* Info) = 0; + // to be implemented or depreciated with MachineModuleInfo + +}; // end class ObjectCodeEmitter + +} // end namespace llvm + +#endif + diff --git a/libclamav/c++/llvm/include/llvm/CodeGen/Passes.h b/libclamav/c++/llvm/include/llvm/CodeGen/Passes.h new file mode 100644 index 000000000..8e8970269 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/CodeGen/Passes.h @@ -0,0 +1,196 @@ +//===-- Passes.h - Target independent code generation passes ----*- 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 interfaces to access the target independent code generation +// passes provided by the LLVM backend. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_PASSES_H +#define LLVM_CODEGEN_PASSES_H + +#include "llvm/Target/TargetMachine.h" +#include + +namespace llvm { + + class FunctionPass; + class PassInfo; + class TargetLowering; + class RegisterCoalescer; + class raw_ostream; + + /// createUnreachableBlockEliminationPass - The LLVM code generator does not + /// work well with unreachable basic blocks (what live ranges make sense for a + /// block that cannot be reached?). As such, a code generator should either + /// not instruction select unreachable blocks, or it can run this pass as it's + /// last LLVM modifying pass to clean up blocks that are not reachable from + /// the entry block. + FunctionPass *createUnreachableBlockEliminationPass(); + + /// MachineFunctionPrinter pass - This pass prints out the machine function to + /// the given stream, as a debugging tool. + FunctionPass *createMachineFunctionPrinterPass(raw_ostream &OS, + const std::string &Banner =""); + + /// MachineLoopInfo pass - This pass is a loop analysis pass. + /// + extern const PassInfo *const MachineLoopInfoID; + + /// MachineDominators pass - This pass is a machine dominators analysis pass. + /// + extern const PassInfo *const MachineDominatorsID; + + /// PHIElimination pass - This pass eliminates machine instruction PHI nodes + /// by inserting copy instructions. This destroys SSA information, but is the + /// desired input for some register allocators. This pass is "required" by + /// these register allocator like this: AU.addRequiredID(PHIEliminationID); + /// + extern const PassInfo *const PHIEliminationID; + + /// StrongPHIElimination pass - This pass eliminates machine instruction PHI + /// nodes by inserting copy instructions. This destroys SSA information, but + /// is the desired input for some register allocators. This pass is + /// "required" by these register allocator like this: + /// AU.addRequiredID(PHIEliminationID); + /// This pass is still in development + extern const PassInfo *const StrongPHIEliminationID; + + extern const PassInfo *const PreAllocSplittingID; + + /// SimpleRegisterCoalescing pass. Aggressively coalesces every register + /// copy it can. + /// + extern const PassInfo *const SimpleRegisterCoalescingID; + + /// TwoAddressInstruction pass - This pass reduces two-address instructions to + /// use two operands. This destroys SSA information but it is desired by + /// register allocators. + extern const PassInfo *const TwoAddressInstructionPassID; + + /// UnreachableMachineBlockElimination pass - This pass removes unreachable + /// machine basic blocks. + extern const PassInfo *const UnreachableMachineBlockElimID; + + /// DeadMachineInstructionElim pass - This pass removes dead machine + /// instructions. + /// + FunctionPass *createDeadMachineInstructionElimPass(); + + /// Creates a register allocator as the user specified on the command line. + /// + FunctionPass *createRegisterAllocator(); + + /// LocalRegisterAllocation Pass - This pass register allocates the input code + /// a basic block at a time, yielding code better than the simple register + /// allocator, but not as good as a global allocator. + /// + FunctionPass *createLocalRegisterAllocator(); + + /// LinearScanRegisterAllocation Pass - This pass implements the linear scan + /// register allocation algorithm, a global register allocator. + /// + FunctionPass *createLinearScanRegisterAllocator(); + + /// PBQPRegisterAllocation Pass - This pass implements the Partitioned Boolean + /// Quadratic Prograaming (PBQP) based register allocator. + /// + FunctionPass *createPBQPRegisterAllocator(); + + /// SimpleRegisterCoalescing Pass - Coalesce all copies possible. Can run + /// independently of the register allocator. + /// + RegisterCoalescer *createSimpleRegisterCoalescer(); + + /// PrologEpilogCodeInserter Pass - This pass inserts prolog and epilog code, + /// and eliminates abstract frame references. + /// + FunctionPass *createPrologEpilogCodeInserter(); + + /// LowerSubregs Pass - This pass lowers subregs to register-register copies + /// which yields suboptimal, but correct code if the register allocator + /// cannot coalesce all subreg operations during allocation. + /// + FunctionPass *createLowerSubregsPass(); + + /// createPostRAScheduler - This pass performs post register allocation + /// scheduling. + FunctionPass *createPostRAScheduler(CodeGenOpt::Level OptLevel); + + /// BranchFolding Pass - This pass performs machine code CFG based + /// optimizations to delete branches to branches, eliminate branches to + /// successor blocks (creating fall throughs), and eliminating branches over + /// branches. + FunctionPass *createBranchFoldingPass(bool DefaultEnableTailMerge); + + /// TailDuplicate Pass - Duplicate blocks with unconditional branches + /// into tails of their predecessors. + FunctionPass *createTailDuplicatePass(); + + /// IfConverter Pass - This pass performs machine code if conversion. + FunctionPass *createIfConverterPass(); + + /// Code Placement Pass - This pass optimize code placement and aligns loop + /// headers to target specific alignment boundary. + FunctionPass *createCodePlacementOptPass(); + + /// getRegisterAllocator - This creates an instance of the register allocator + /// for the Sparc. + FunctionPass *getRegisterAllocator(TargetMachine &T); + + /// IntrinsicLowering Pass - Performs target-independent LLVM IR + /// transformations for highly portable strategies. + FunctionPass *createGCLoweringPass(); + + /// MachineCodeAnalysis Pass - Target-independent pass to mark safe points in + /// machine code. Must be added very late during code generation, just prior + /// to output, and importantly after all CFG transformations (such as branch + /// folding). + FunctionPass *createGCMachineCodeAnalysisPass(); + + /// Deleter Pass - Releases GC metadata. + /// + FunctionPass *createGCInfoDeleter(); + + /// Creates a pass to print GC metadata. + /// + FunctionPass *createGCInfoPrinter(raw_ostream &OS); + + /// createMachineLICMPass - This pass performs LICM on machine instructions. + /// + FunctionPass *createMachineLICMPass(); + + /// createMachineSinkingPass - This pass performs sinking on machine + /// instructions. + FunctionPass *createMachineSinkingPass(); + + /// createStackSlotColoringPass - This pass performs stack slot coloring. + FunctionPass *createStackSlotColoringPass(bool); + + /// createStackProtectorPass - This pass adds stack protectors to functions. + FunctionPass *createStackProtectorPass(const TargetLowering *tli); + + /// createMachineVerifierPass - This pass verifies cenerated machine code + /// instructions for correctness. + /// + /// @param allowPhysDoubleDefs ignore double definitions of + /// registers. Useful before LiveVariables has run. + FunctionPass *createMachineVerifierPass(bool allowDoubleDefs); + + /// createDwarfEHPass - This pass mulches exception handling code into a form + /// adapted to code generation. Required if using dwarf exception handling. + FunctionPass *createDwarfEHPass(const TargetLowering *tli, bool fast); + + /// createSjLjEHPass - This pass adapts exception handling code to use + /// the GCC-style builtin setjmp/longjmp (sjlj) to handling EH control flow. + FunctionPass *createSjLjEHPass(const TargetLowering *tli); + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/CodeGen/ProcessImplicitDefs.h b/libclamav/c++/llvm/include/llvm/CodeGen/ProcessImplicitDefs.h new file mode 100644 index 000000000..cec867f9e --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/CodeGen/ProcessImplicitDefs.h @@ -0,0 +1,41 @@ +//===-------------- llvm/CodeGen/ProcessImplicitDefs.h ----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + + +#ifndef LLVM_CODEGEN_PROCESSIMPLICITDEFS_H +#define LLVM_CODEGEN_PROCESSIMPLICITDEFS_H + +#include "llvm/CodeGen/MachineFunctionPass.h" + +namespace llvm { + + class MachineInstr; + class TargetInstrInfo; + + /// Process IMPLICIT_DEF instructions and make sure there is one implicit_def + /// for each use. Add isUndef marker to implicit_def defs and their uses. + class ProcessImplicitDefs : public MachineFunctionPass { + private: + + bool CanTurnIntoImplicitDef(MachineInstr *MI, unsigned Reg, + unsigned OpIdx, const TargetInstrInfo *tii_); + + public: + static char ID; + + ProcessImplicitDefs() : MachineFunctionPass(&ID) {} + + virtual void getAnalysisUsage(AnalysisUsage &au) const; + + virtual bool runOnMachineFunction(MachineFunction &fn); + }; + +} + +#endif // LLVM_CODEGEN_PROCESSIMPLICITDEFS_H diff --git a/libclamav/c++/llvm/include/llvm/CodeGen/PseudoSourceValue.h b/libclamav/c++/llvm/include/llvm/CodeGen/PseudoSourceValue.h new file mode 100644 index 000000000..bace631ab --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/CodeGen/PseudoSourceValue.h @@ -0,0 +1,112 @@ +//===-- llvm/CodeGen/PseudoSourceValue.h ------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the declaration of the PseudoSourceValue class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_PSEUDOSOURCEVALUE_H +#define LLVM_CODEGEN_PSEUDOSOURCEVALUE_H + +#include "llvm/Value.h" + +namespace llvm { + class MachineFrameInfo; + class raw_ostream; + + /// PseudoSourceValue - Special value supplied for machine level alias + /// analysis. It indicates that the a memory access references the functions + /// stack frame (e.g., a spill slot), below the stack frame (e.g., argument + /// space), or constant pool. + class PseudoSourceValue : public Value { + private: + /// printCustom - Implement printing for PseudoSourceValue. This is called + /// from Value::print or Value's operator<<. + /// + virtual void printCustom(raw_ostream &O) const; + + public: + explicit PseudoSourceValue(enum ValueTy Subclass = PseudoSourceValueVal); + + /// isConstant - Test whether the memory pointed to by this + /// PseudoSourceValue has a constant value. + /// + virtual bool isConstant(const MachineFrameInfo *) const; + + /// isAliased - Test whether the memory pointed to by this + /// PseudoSourceValue may also be pointed to by an LLVM IR Value. + virtual bool isAliased(const MachineFrameInfo *) const; + + /// mayAlias - Return true if the memory pointed to by this + /// PseudoSourceValue can ever alias a LLVM IR Value. + virtual bool mayAlias(const MachineFrameInfo *) const; + + /// classof - Methods for support type inquiry through isa, cast, and + /// dyn_cast: + /// + static inline bool classof(const PseudoSourceValue *) { return true; } + static inline bool classof(const Value *V) { + return V->getValueID() == PseudoSourceValueVal || + V->getValueID() == FixedStackPseudoSourceValueVal; + } + + /// A pseudo source value referencing a fixed stack frame entry, + /// e.g., a spill slot. + static const PseudoSourceValue *getFixedStack(int FI); + + /// A pseudo source value referencing the area below the stack frame of + /// a function, e.g., the argument space. + static const PseudoSourceValue *getStack(); + + /// A pseudo source value referencing the global offset table + /// (or something the like). + static const PseudoSourceValue *getGOT(); + + /// A pseudo source value referencing the constant pool. Since constant + /// pools are constant, this doesn't need to identify a specific constant + /// pool entry. + static const PseudoSourceValue *getConstantPool(); + + /// A pseudo source value referencing a jump table. Since jump tables are + /// constant, this doesn't need to identify a specific jump table. + static const PseudoSourceValue *getJumpTable(); + }; + + /// FixedStackPseudoSourceValue - A specialized PseudoSourceValue + /// for holding FixedStack values, which must include a frame + /// index. + class FixedStackPseudoSourceValue : public PseudoSourceValue { + const int FI; + public: + explicit FixedStackPseudoSourceValue(int fi) : + PseudoSourceValue(FixedStackPseudoSourceValueVal), FI(fi) {} + + /// classof - Methods for support type inquiry through isa, cast, and + /// dyn_cast: + /// + static inline bool classof(const FixedStackPseudoSourceValue *) { + return true; + } + static inline bool classof(const Value *V) { + return V->getValueID() == FixedStackPseudoSourceValueVal; + } + + virtual bool isConstant(const MachineFrameInfo *MFI) const; + + virtual bool isAliased(const MachineFrameInfo *MFI) const; + + virtual bool mayAlias(const MachineFrameInfo *) const; + + virtual void printCustom(raw_ostream &OS) const; + + int getFrameIndex() const { return FI; } + }; +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/CodeGen/RegAllocRegistry.h b/libclamav/c++/llvm/include/llvm/CodeGen/RegAllocRegistry.h new file mode 100644 index 000000000..100e35765 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/CodeGen/RegAllocRegistry.h @@ -0,0 +1,66 @@ +//===-- llvm/CodeGen/RegAllocRegistry.h -------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the implementation for register allocator function +// pass registry (RegisterRegAlloc). +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGENREGALLOCREGISTRY_H +#define LLVM_CODEGENREGALLOCREGISTRY_H + +#include "llvm/CodeGen/MachinePassRegistry.h" + +namespace llvm { + +//===----------------------------------------------------------------------===// +/// +/// RegisterRegAlloc class - Track the registration of register allocators. +/// +//===----------------------------------------------------------------------===// +class RegisterRegAlloc : public MachinePassRegistryNode { + +public: + + typedef FunctionPass *(*FunctionPassCtor)(); + + static MachinePassRegistry Registry; + + RegisterRegAlloc(const char *N, const char *D, FunctionPassCtor C) + : MachinePassRegistryNode(N, D, (MachinePassCtor)C) + { + Registry.Add(this); + } + ~RegisterRegAlloc() { Registry.Remove(this); } + + + // Accessors. + // + RegisterRegAlloc *getNext() const { + return (RegisterRegAlloc *)MachinePassRegistryNode::getNext(); + } + static RegisterRegAlloc *getList() { + return (RegisterRegAlloc *)Registry.getList(); + } + static FunctionPassCtor getDefault() { + return (FunctionPassCtor)Registry.getDefault(); + } + static void setDefault(FunctionPassCtor C) { + Registry.setDefault((MachinePassCtor)C); + } + static void setListener(MachinePassRegistryListener *L) { + Registry.setListener(L); + } + +}; + +} // end namespace llvm + + +#endif diff --git a/libclamav/c++/llvm/include/llvm/CodeGen/RegisterCoalescer.h b/libclamav/c++/llvm/include/llvm/CodeGen/RegisterCoalescer.h new file mode 100644 index 000000000..1490aa017 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/CodeGen/RegisterCoalescer.h @@ -0,0 +1,154 @@ +//===-- RegisterCoalescer.h - Register Coalescing Interface ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the abstract interface for register coalescers, +// allowing them to interact with and query register allocators. +// +//===----------------------------------------------------------------------===// + +#include "llvm/System/IncludeFile.h" +#include "llvm/CodeGen/LiveInterval.h" +#include "llvm/ADT/SmallPtrSet.h" + +#ifndef LLVM_CODEGEN_REGISTER_COALESCER_H +#define LLVM_CODEGEN_REGISTER_COALESCER_H + +namespace llvm { + + class MachineFunction; + class RegallocQuery; + class AnalysisUsage; + class MachineInstr; + + /// An abstract interface for register coalescers. Coalescers must + /// implement this interface to be part of the coalescer analysis + /// group. + class RegisterCoalescer { + public: + static char ID; // Class identification, replacement for typeinfo + RegisterCoalescer() {} + virtual ~RegisterCoalescer(); // We want to be subclassed + + /// Run the coalescer on this function, providing interference + /// data to query. Return whether we removed any copies. + virtual bool coalesceFunction(MachineFunction &mf, + RegallocQuery &ifd) = 0; + + /// Reset state. Can be used to allow a coalescer run by + /// PassManager to be run again by the register allocator. + virtual void reset(MachineFunction &mf) {} + + /// Register allocators must call this from their own + /// getAnalysisUsage to cover the case where the coalescer is not + /// a Pass in the proper sense and isn't managed by PassManager. + /// PassManager needs to know which analyses to make available and + /// which to invalidate when running the register allocator or any + /// pass that might call coalescing. The long-term solution is to + /// allow hierarchies of PassManagers. + virtual void getAnalysisUsage(AnalysisUsage &AU) const {} + }; + + /// An abstract interface for register allocators to interact with + /// coalescers + /// + /// Example: + /// + /// This is simply an example of how to use the RegallocQuery + /// interface. It is not meant to be used in production. + /// + /// class LinearScanRegallocQuery : public RegallocQuery { + /// private: + /// const LiveIntervals \&li; + /// + /// public: + /// LinearScanRegallocQuery(LiveIntervals &intervals) + /// : li(intervals) {} + /// + /// /// This is pretty slow and conservative, but since linear scan + /// /// allocation doesn't pre-compute interference information it's + /// /// the best we can do. Coalescers are always free to ignore this + /// /// and implement their own discovery strategy. See + /// /// SimpleRegisterCoalescing for an example. + /// void getInterferences(IntervalSet &interferences, + /// const LiveInterval &a) const { + /// for(LiveIntervals::const_iterator iv = li.begin(), + /// ivend = li.end(); + /// iv != ivend; + /// ++iv) { + /// if (interfere(a, iv->second)) { + /// interferences.insert(&iv->second); + /// } + /// } + /// } + /// + /// /// This is *really* slow and stupid. See above. + /// int getNumberOfInterferences(const LiveInterval &a) const { + /// IntervalSet intervals; + /// getInterferences(intervals, a); + /// return intervals.size(); + /// } + /// }; + /// + /// In the allocator: + /// + /// RegisterCoalescer &coalescer = getAnalysis(); + /// + /// // We don't reset the coalescer so if it's already been run this + /// // takes almost no time. + /// LinearScanRegallocQuery ifd(*li_); + /// coalescer.coalesceFunction(fn, ifd); + /// + class RegallocQuery { + public: + typedef SmallPtrSet IntervalSet; + + virtual ~RegallocQuery() {} + + /// Return whether two live ranges interfere. + virtual bool interfere(const LiveInterval &a, + const LiveInterval &b) const { + // A naive test + return a.overlaps(b); + } + + /// Return the set of intervals that interfere with this one. + virtual void getInterferences(IntervalSet &interferences, + const LiveInterval &a) const = 0; + + /// This can often be cheaper than actually returning the + /// interferences. + virtual int getNumberOfInterferences(const LiveInterval &a) const = 0; + + /// Make any data structure updates necessary to reflect + /// coalescing or other modifications. + virtual void updateDataForMerge(const LiveInterval &a, + const LiveInterval &b, + const MachineInstr ©) {} + + /// Allow the register allocator to communicate when it doesn't + /// want a copy coalesced. This may be due to assumptions made by + /// the allocator about various invariants and so this question is + /// a matter of legality, not performance. Performance decisions + /// about which copies to coalesce should be made by the + /// coalescer. + virtual bool isLegalToCoalesce(const MachineInstr &inst) const { + return true; + } + }; +} + +// Because of the way .a files work, we must force the SimpleRC +// implementation to be pulled in if the RegisterCoalescing header is +// included. Otherwise we run the risk of RegisterCoalescing being +// used, but the default implementation not being linked into the tool +// that uses it. +FORCE_DEFINING_FILE_TO_BE_LINKED(RegisterCoalescer) +FORCE_DEFINING_FILE_TO_BE_LINKED(SimpleRegisterCoalescing) + +#endif diff --git a/libclamav/c++/llvm/include/llvm/CodeGen/RegisterScavenging.h b/libclamav/c++/llvm/include/llvm/CodeGen/RegisterScavenging.h new file mode 100644 index 000000000..84b726d73 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/CodeGen/RegisterScavenging.h @@ -0,0 +1,159 @@ +//===-- RegisterScavenging.h - Machine register scavenging ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the machine register scavenger class. It can provide +// information such as unused register at any point in a machine basic block. +// It also provides a mechanism to make registers availbale by evicting them +// to spill slots. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_REGISTER_SCAVENGING_H +#define LLVM_CODEGEN_REGISTER_SCAVENGING_H + +#include "llvm/CodeGen/MachineBasicBlock.h" +#include "llvm/ADT/BitVector.h" + +namespace llvm { + +class MachineRegisterInfo; +class TargetRegisterInfo; +class TargetInstrInfo; +class TargetRegisterClass; + +class RegScavenger { + const TargetRegisterInfo *TRI; + const TargetInstrInfo *TII; + MachineRegisterInfo* MRI; + MachineBasicBlock *MBB; + MachineBasicBlock::iterator MBBI; + unsigned NumPhysRegs; + + /// Tracking - True if RegScavenger is currently tracking the liveness of + /// registers. + bool Tracking; + + /// ScavengingFrameIndex - Special spill slot used for scavenging a register + /// post register allocation. + int ScavengingFrameIndex; + + /// ScavengedReg - If none zero, the specific register is currently being + /// scavenged. That is, it is spilled to the special scavenging stack slot. + unsigned ScavengedReg; + + /// ScavengedRC - Register class of the scavenged register. + /// + const TargetRegisterClass *ScavengedRC; + + /// ScavengeRestore - Instruction that restores the scavenged register from + /// stack. + const MachineInstr *ScavengeRestore; + + /// CalleeSavedrRegs - A bitvector of callee saved registers for the target. + /// + BitVector CalleeSavedRegs; + + /// ReservedRegs - A bitvector of reserved registers. + /// + BitVector ReservedRegs; + + /// RegsAvailable - The current state of all the physical registers immediately + /// before MBBI. One bit per physical register. If bit is set that means it's + /// available, unset means the register is currently being used. + BitVector RegsAvailable; + +public: + RegScavenger() + : MBB(NULL), NumPhysRegs(0), Tracking(false), + ScavengingFrameIndex(-1), ScavengedReg(0), ScavengedRC(NULL) {} + + /// enterBasicBlock - Start tracking liveness from the begin of the specific + /// basic block. + void enterBasicBlock(MachineBasicBlock *mbb); + + /// initRegState - allow resetting register state info for multiple + /// passes over/within the same function. + void initRegState(); + + /// forward - Move the internal MBB iterator and update register states. + void forward(); + + /// forward - Move the internal MBB iterator and update register states until + /// it has processed the specific iterator. + void forward(MachineBasicBlock::iterator I) { + if (!Tracking && MBB->begin() != I) forward(); + while (MBBI != I) forward(); + } + + /// skipTo - Move the internal MBB iterator but do not update register states. + /// + void skipTo(MachineBasicBlock::iterator I) { MBBI = I; } + + /// getRegsUsed - return all registers currently in use in used. + void getRegsUsed(BitVector &used, bool includeReserved); + + /// FindUnusedReg - Find a unused register of the specified register class. + /// Return 0 if none is found. + unsigned FindUnusedReg(const TargetRegisterClass *RegClass) const; + + /// setScavengingFrameIndex / getScavengingFrameIndex - accessor and setter of + /// ScavengingFrameIndex. + void setScavengingFrameIndex(int FI) { ScavengingFrameIndex = FI; } + int getScavengingFrameIndex() const { return ScavengingFrameIndex; } + + /// scavengeRegister - Make a register of the specific register class + /// available and do the appropriate bookkeeping. SPAdj is the stack + /// adjustment due to call frame, it's passed along to eliminateFrameIndex(). + /// Returns the scavenged register. + unsigned scavengeRegister(const TargetRegisterClass *RegClass, + MachineBasicBlock::iterator I, int SPAdj); + unsigned scavengeRegister(const TargetRegisterClass *RegClass, int SPAdj) { + return scavengeRegister(RegClass, MBBI, SPAdj); + } + + /// setUsed - Tell the scavenger a register is used. + /// + void setUsed(unsigned Reg); +private: + /// isReserved - Returns true if a register is reserved. It is never "unused". + bool isReserved(unsigned Reg) const { return ReservedRegs.test(Reg); } + + /// isUsed / isUnused - Test if a register is currently being used. + /// + bool isUsed(unsigned Reg) const { return !RegsAvailable.test(Reg); } + bool isUnused(unsigned Reg) const { return RegsAvailable.test(Reg); } + + /// isAliasUsed - Is Reg or an alias currently in use? + bool isAliasUsed(unsigned Reg) const; + + /// setUsed / setUnused - Mark the state of one or a number of registers. + /// + void setUsed(BitVector &Regs) { + RegsAvailable &= ~Regs; + } + void setUnused(BitVector &Regs) { + RegsAvailable |= Regs; + } + + /// Add Reg and all its sub-registers to BV. + void addRegWithSubRegs(BitVector &BV, unsigned Reg); + + /// Add Reg and its aliases to BV. + void addRegWithAliases(BitVector &BV, unsigned Reg); + + unsigned findSurvivorReg(MachineBasicBlock::iterator MI, + BitVector &Candidates, + unsigned InstrLimit, + MachineBasicBlock::iterator &UseMI); + +}; + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/CodeGen/RuntimeLibcalls.h b/libclamav/c++/llvm/include/llvm/CodeGen/RuntimeLibcalls.h new file mode 100644 index 000000000..c404ab6ea --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/CodeGen/RuntimeLibcalls.h @@ -0,0 +1,269 @@ +//===-- CodeGen/RuntimeLibcall.h - Runtime Library Calls --------*- 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 the enum representing the list of runtime library calls +// the backend may emit during code generation, and also some helper functions. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_RUNTIMELIBCALLS_H +#define LLVM_CODEGEN_RUNTIMELIBCALLS_H + +#include "llvm/CodeGen/ValueTypes.h" + +namespace llvm { +namespace RTLIB { + /// RTLIB::Libcall enum - This enum defines all of the runtime library calls + /// the backend can emit. The various long double types cannot be merged, + /// because 80-bit library functions use "xf" and 128-bit use "tf". + /// + /// When adding PPCF128 functions here, note that their names generally need + /// to be overridden for Darwin with the xxx$LDBL128 form. See + /// PPCISelLowering.cpp. + /// + enum Libcall { + // Integer + SHL_I16, + SHL_I32, + SHL_I64, + SHL_I128, + SRL_I16, + SRL_I32, + SRL_I64, + SRL_I128, + SRA_I16, + SRA_I32, + SRA_I64, + SRA_I128, + MUL_I8, + MUL_I16, + MUL_I32, + MUL_I64, + MUL_I128, + SDIV_I8, + SDIV_I16, + SDIV_I32, + SDIV_I64, + SDIV_I128, + UDIV_I8, + UDIV_I16, + UDIV_I32, + UDIV_I64, + UDIV_I128, + SREM_I8, + SREM_I16, + SREM_I32, + SREM_I64, + SREM_I128, + UREM_I8, + UREM_I16, + UREM_I32, + UREM_I64, + UREM_I128, + NEG_I32, + NEG_I64, + + // FLOATING POINT + ADD_F32, + ADD_F64, + ADD_F80, + ADD_PPCF128, + SUB_F32, + SUB_F64, + SUB_F80, + SUB_PPCF128, + MUL_F32, + MUL_F64, + MUL_F80, + MUL_PPCF128, + DIV_F32, + DIV_F64, + DIV_F80, + DIV_PPCF128, + REM_F32, + REM_F64, + REM_F80, + REM_PPCF128, + POWI_F32, + POWI_F64, + POWI_F80, + POWI_PPCF128, + SQRT_F32, + SQRT_F64, + SQRT_F80, + SQRT_PPCF128, + LOG_F32, + LOG_F64, + LOG_F80, + LOG_PPCF128, + LOG2_F32, + LOG2_F64, + LOG2_F80, + LOG2_PPCF128, + LOG10_F32, + LOG10_F64, + LOG10_F80, + LOG10_PPCF128, + EXP_F32, + EXP_F64, + EXP_F80, + EXP_PPCF128, + EXP2_F32, + EXP2_F64, + EXP2_F80, + EXP2_PPCF128, + SIN_F32, + SIN_F64, + SIN_F80, + SIN_PPCF128, + COS_F32, + COS_F64, + COS_F80, + COS_PPCF128, + POW_F32, + POW_F64, + POW_F80, + POW_PPCF128, + CEIL_F32, + CEIL_F64, + CEIL_F80, + CEIL_PPCF128, + TRUNC_F32, + TRUNC_F64, + TRUNC_F80, + TRUNC_PPCF128, + RINT_F32, + RINT_F64, + RINT_F80, + RINT_PPCF128, + NEARBYINT_F32, + NEARBYINT_F64, + NEARBYINT_F80, + NEARBYINT_PPCF128, + FLOOR_F32, + FLOOR_F64, + FLOOR_F80, + FLOOR_PPCF128, + + // CONVERSION + FPEXT_F32_F64, + FPROUND_F64_F32, + FPROUND_F80_F32, + FPROUND_PPCF128_F32, + FPROUND_F80_F64, + FPROUND_PPCF128_F64, + FPTOSINT_F32_I8, + FPTOSINT_F32_I16, + FPTOSINT_F32_I32, + FPTOSINT_F32_I64, + FPTOSINT_F32_I128, + FPTOSINT_F64_I32, + FPTOSINT_F64_I64, + FPTOSINT_F64_I128, + FPTOSINT_F80_I32, + FPTOSINT_F80_I64, + FPTOSINT_F80_I128, + FPTOSINT_PPCF128_I32, + FPTOSINT_PPCF128_I64, + FPTOSINT_PPCF128_I128, + FPTOUINT_F32_I8, + FPTOUINT_F32_I16, + FPTOUINT_F32_I32, + FPTOUINT_F32_I64, + FPTOUINT_F32_I128, + FPTOUINT_F64_I32, + FPTOUINT_F64_I64, + FPTOUINT_F64_I128, + FPTOUINT_F80_I32, + FPTOUINT_F80_I64, + FPTOUINT_F80_I128, + FPTOUINT_PPCF128_I32, + FPTOUINT_PPCF128_I64, + FPTOUINT_PPCF128_I128, + SINTTOFP_I32_F32, + SINTTOFP_I32_F64, + SINTTOFP_I32_F80, + SINTTOFP_I32_PPCF128, + SINTTOFP_I64_F32, + SINTTOFP_I64_F64, + SINTTOFP_I64_F80, + SINTTOFP_I64_PPCF128, + SINTTOFP_I128_F32, + SINTTOFP_I128_F64, + SINTTOFP_I128_F80, + SINTTOFP_I128_PPCF128, + UINTTOFP_I32_F32, + UINTTOFP_I32_F64, + UINTTOFP_I32_F80, + UINTTOFP_I32_PPCF128, + UINTTOFP_I64_F32, + UINTTOFP_I64_F64, + UINTTOFP_I64_F80, + UINTTOFP_I64_PPCF128, + UINTTOFP_I128_F32, + UINTTOFP_I128_F64, + UINTTOFP_I128_F80, + UINTTOFP_I128_PPCF128, + + // COMPARISON + OEQ_F32, + OEQ_F64, + UNE_F32, + UNE_F64, + OGE_F32, + OGE_F64, + OLT_F32, + OLT_F64, + OLE_F32, + OLE_F64, + OGT_F32, + OGT_F64, + UO_F32, + UO_F64, + O_F32, + O_F64, + + // MEMORY + MEMCPY, + MEMSET, + MEMMOVE, + + // EXCEPTION HANDLING + UNWIND_RESUME, + + UNKNOWN_LIBCALL + }; + + /// getFPEXT - Return the FPEXT_*_* value for the given types, or + /// UNKNOWN_LIBCALL if there is none. + Libcall getFPEXT(EVT OpVT, EVT RetVT); + + /// getFPROUND - Return the FPROUND_*_* value for the given types, or + /// UNKNOWN_LIBCALL if there is none. + Libcall getFPROUND(EVT OpVT, EVT RetVT); + + /// getFPTOSINT - Return the FPTOSINT_*_* value for the given types, or + /// UNKNOWN_LIBCALL if there is none. + Libcall getFPTOSINT(EVT OpVT, EVT RetVT); + + /// getFPTOUINT - Return the FPTOUINT_*_* value for the given types, or + /// UNKNOWN_LIBCALL if there is none. + Libcall getFPTOUINT(EVT OpVT, EVT RetVT); + + /// getSINTTOFP - Return the SINTTOFP_*_* value for the given types, or + /// UNKNOWN_LIBCALL if there is none. + Libcall getSINTTOFP(EVT OpVT, EVT RetVT); + + /// getUINTTOFP - Return the UINTTOFP_*_* value for the given types, or + /// UNKNOWN_LIBCALL if there is none. + Libcall getUINTTOFP(EVT OpVT, EVT RetVT); +} +} + +#endif diff --git a/libclamav/c++/llvm/include/llvm/CodeGen/ScheduleDAG.h b/libclamav/c++/llvm/include/llvm/CodeGen/ScheduleDAG.h new file mode 100644 index 000000000..955965bcc --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/CodeGen/ScheduleDAG.h @@ -0,0 +1,665 @@ +//===------- llvm/CodeGen/ScheduleDAG.h - Common Base Class------*- 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 the ScheduleDAG class, which is used as the common +// base class for instruction schedulers. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_SCHEDULEDAG_H +#define LLVM_CODEGEN_SCHEDULEDAG_H + +#include "llvm/CodeGen/MachineBasicBlock.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/BitVector.h" +#include "llvm/ADT/GraphTraits.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/PointerIntPair.h" + +namespace llvm { + class AliasAnalysis; + class SUnit; + class MachineConstantPool; + class MachineFunction; + class MachineModuleInfo; + class MachineRegisterInfo; + class MachineInstr; + class TargetRegisterInfo; + class ScheduleDAG; + class SDNode; + class TargetInstrInfo; + class TargetInstrDesc; + class TargetLowering; + class TargetMachine; + class TargetRegisterClass; + template class GraphWriter; + + /// SDep - Scheduling dependency. This represents one direction of an + /// edge in the scheduling DAG. + class SDep { + public: + /// Kind - These are the different kinds of scheduling dependencies. + enum Kind { + Data, ///< Regular data dependence (aka true-dependence). + Anti, ///< A register anti-dependedence (aka WAR). + Output, ///< A register output-dependence (aka WAW). + Order ///< Any other ordering dependency. + }; + + private: + /// Dep - A pointer to the depending/depended-on SUnit, and an enum + /// indicating the kind of the dependency. + PointerIntPair Dep; + + /// Contents - A union discriminated by the dependence kind. + union { + /// Reg - For Data, Anti, and Output dependencies, the associated + /// register. For Data dependencies that don't currently have a register + /// assigned, this is set to zero. + unsigned Reg; + + /// Order - Additional information about Order dependencies. + struct { + /// isNormalMemory - True if both sides of the dependence + /// access memory in non-volatile and fully modeled ways. + bool isNormalMemory : 1; + + /// isMustAlias - True if both sides of the dependence are known to + /// access the same memory. + bool isMustAlias : 1; + + /// isArtificial - True if this is an artificial dependency, meaning + /// it is not necessary for program correctness, and may be safely + /// deleted if necessary. + bool isArtificial : 1; + } Order; + } Contents; + + /// Latency - The time associated with this edge. Often this is just + /// the value of the Latency field of the predecessor, however advanced + /// models may provide additional information about specific edges. + unsigned Latency; + + public: + /// SDep - Construct a null SDep. This is only for use by container + /// classes which require default constructors. SUnits may not + /// have null SDep edges. + SDep() : Dep(0, Data) {} + + /// SDep - Construct an SDep with the specified values. + SDep(SUnit *S, Kind kind, unsigned latency = 1, unsigned Reg = 0, + bool isNormalMemory = false, bool isMustAlias = false, + bool isArtificial = false) + : Dep(S, kind), Contents(), Latency(latency) { + switch (kind) { + case Anti: + case Output: + assert(Reg != 0 && + "SDep::Anti and SDep::Output must use a non-zero Reg!"); + // fall through + case Data: + assert(!isMustAlias && "isMustAlias only applies with SDep::Order!"); + assert(!isArtificial && "isArtificial only applies with SDep::Order!"); + Contents.Reg = Reg; + break; + case Order: + assert(Reg == 0 && "Reg given for non-register dependence!"); + Contents.Order.isNormalMemory = isNormalMemory; + Contents.Order.isMustAlias = isMustAlias; + Contents.Order.isArtificial = isArtificial; + break; + } + } + + bool operator==(const SDep &Other) const { + if (Dep != Other.Dep || Latency != Other.Latency) return false; + switch (Dep.getInt()) { + case Data: + case Anti: + case Output: + return Contents.Reg == Other.Contents.Reg; + case Order: + return Contents.Order.isNormalMemory == + Other.Contents.Order.isNormalMemory && + Contents.Order.isMustAlias == Other.Contents.Order.isMustAlias && + Contents.Order.isArtificial == Other.Contents.Order.isArtificial; + } + assert(0 && "Invalid dependency kind!"); + return false; + } + + bool operator!=(const SDep &Other) const { + return !operator==(Other); + } + + /// getLatency - Return the latency value for this edge, which roughly + /// means the minimum number of cycles that must elapse between the + /// predecessor and the successor, given that they have this edge + /// between them. + unsigned getLatency() const { + return Latency; + } + + /// setLatency - Set the latency for this edge. + void setLatency(unsigned Lat) { + Latency = Lat; + } + + //// getSUnit - Return the SUnit to which this edge points. + SUnit *getSUnit() const { + return Dep.getPointer(); + } + + //// setSUnit - Assign the SUnit to which this edge points. + void setSUnit(SUnit *SU) { + Dep.setPointer(SU); + } + + /// getKind - Return an enum value representing the kind of the dependence. + Kind getKind() const { + return Dep.getInt(); + } + + /// isCtrl - Shorthand for getKind() != SDep::Data. + bool isCtrl() const { + return getKind() != Data; + } + + /// isNormalMemory - Test if this is an Order dependence between two + /// memory accesses where both sides of the dependence access memory + /// in non-volatile and fully modeled ways. + bool isNormalMemory() const { + return getKind() == Order && Contents.Order.isNormalMemory; + } + + /// isMustAlias - Test if this is an Order dependence that is marked + /// as "must alias", meaning that the SUnits at either end of the edge + /// have a memory dependence on a known memory location. + bool isMustAlias() const { + return getKind() == Order && Contents.Order.isMustAlias; + } + + /// isArtificial - Test if this is an Order dependence that is marked + /// as "artificial", meaning it isn't necessary for correctness. + bool isArtificial() const { + return getKind() == Order && Contents.Order.isArtificial; + } + + /// isAssignedRegDep - Test if this is a Data dependence that is + /// associated with a register. + bool isAssignedRegDep() const { + return getKind() == Data && Contents.Reg != 0; + } + + /// getReg - Return the register associated with this edge. This is + /// only valid on Data, Anti, and Output edges. On Data edges, this + /// value may be zero, meaning there is no associated register. + unsigned getReg() const { + assert((getKind() == Data || getKind() == Anti || getKind() == Output) && + "getReg called on non-register dependence edge!"); + return Contents.Reg; + } + + /// setReg - Assign the associated register for this edge. This is + /// only valid on Data, Anti, and Output edges. On Anti and Output + /// edges, this value must not be zero. On Data edges, the value may + /// be zero, which would mean that no specific register is associated + /// with this edge. + void setReg(unsigned Reg) { + assert((getKind() == Data || getKind() == Anti || getKind() == Output) && + "setReg called on non-register dependence edge!"); + assert((getKind() != Anti || Reg != 0) && + "SDep::Anti edge cannot use the zero register!"); + assert((getKind() != Output || Reg != 0) && + "SDep::Output edge cannot use the zero register!"); + Contents.Reg = Reg; + } + }; + + /// SUnit - Scheduling unit. This is a node in the scheduling DAG. + class SUnit { + private: + SDNode *Node; // Representative node. + MachineInstr *Instr; // Alternatively, a MachineInstr. + public: + SUnit *OrigNode; // If not this, the node from which + // this node was cloned. + + // Preds/Succs - The SUnits before/after us in the graph. The boolean value + // is true if the edge is a token chain edge, false if it is a value edge. + SmallVector Preds; // All sunit predecessors. + SmallVector Succs; // All sunit successors. + + typedef SmallVector::iterator pred_iterator; + typedef SmallVector::iterator succ_iterator; + typedef SmallVector::const_iterator const_pred_iterator; + typedef SmallVector::const_iterator const_succ_iterator; + + unsigned NodeNum; // Entry # of node in the node vector. + unsigned NodeQueueId; // Queue id of node. + unsigned short Latency; // Node latency. + unsigned NumPreds; // # of SDep::Data preds. + unsigned NumSuccs; // # of SDep::Data sucss. + unsigned NumPredsLeft; // # of preds not scheduled. + unsigned NumSuccsLeft; // # of succs not scheduled. + bool isTwoAddress : 1; // Is a two-address instruction. + bool isCommutable : 1; // Is a commutable instruction. + bool hasPhysRegDefs : 1; // Has physreg defs that are being used. + bool hasPhysRegClobbers : 1; // Has any physreg defs, used or not. + bool isPending : 1; // True once pending. + bool isAvailable : 1; // True once available. + bool isScheduled : 1; // True once scheduled. + bool isScheduleHigh : 1; // True if preferable to schedule high. + bool isCloned : 1; // True if this node has been cloned. + private: + bool isDepthCurrent : 1; // True if Depth is current. + bool isHeightCurrent : 1; // True if Height is current. + unsigned Depth; // Node depth. + unsigned Height; // Node height. + public: + const TargetRegisterClass *CopyDstRC; // Is a special copy node if not null. + const TargetRegisterClass *CopySrcRC; + + /// SUnit - Construct an SUnit for pre-regalloc scheduling to represent + /// an SDNode and any nodes flagged to it. + SUnit(SDNode *node, unsigned nodenum) + : Node(node), Instr(0), OrigNode(0), NodeNum(nodenum), NodeQueueId(0), + Latency(0), NumPreds(0), NumSuccs(0), NumPredsLeft(0), NumSuccsLeft(0), + isTwoAddress(false), isCommutable(false), hasPhysRegDefs(false), + hasPhysRegClobbers(false), + isPending(false), isAvailable(false), isScheduled(false), + isScheduleHigh(false), isCloned(false), + isDepthCurrent(false), isHeightCurrent(false), Depth(0), Height(0), + CopyDstRC(NULL), CopySrcRC(NULL) {} + + /// SUnit - Construct an SUnit for post-regalloc scheduling to represent + /// a MachineInstr. + SUnit(MachineInstr *instr, unsigned nodenum) + : Node(0), Instr(instr), OrigNode(0), NodeNum(nodenum), NodeQueueId(0), + Latency(0), NumPreds(0), NumSuccs(0), NumPredsLeft(0), NumSuccsLeft(0), + isTwoAddress(false), isCommutable(false), hasPhysRegDefs(false), + hasPhysRegClobbers(false), + isPending(false), isAvailable(false), isScheduled(false), + isScheduleHigh(false), isCloned(false), + isDepthCurrent(false), isHeightCurrent(false), Depth(0), Height(0), + CopyDstRC(NULL), CopySrcRC(NULL) {} + + /// SUnit - Construct a placeholder SUnit. + SUnit() + : Node(0), Instr(0), OrigNode(0), NodeNum(~0u), NodeQueueId(0), + Latency(0), NumPreds(0), NumSuccs(0), NumPredsLeft(0), NumSuccsLeft(0), + isTwoAddress(false), isCommutable(false), hasPhysRegDefs(false), + hasPhysRegClobbers(false), + isPending(false), isAvailable(false), isScheduled(false), + isScheduleHigh(false), isCloned(false), + isDepthCurrent(false), isHeightCurrent(false), Depth(0), Height(0), + CopyDstRC(NULL), CopySrcRC(NULL) {} + + /// setNode - Assign the representative SDNode for this SUnit. + /// This may be used during pre-regalloc scheduling. + void setNode(SDNode *N) { + assert(!Instr && "Setting SDNode of SUnit with MachineInstr!"); + Node = N; + } + + /// getNode - Return the representative SDNode for this SUnit. + /// This may be used during pre-regalloc scheduling. + SDNode *getNode() const { + assert(!Instr && "Reading SDNode of SUnit with MachineInstr!"); + return Node; + } + + /// setInstr - Assign the instruction for the SUnit. + /// This may be used during post-regalloc scheduling. + void setInstr(MachineInstr *MI) { + assert(!Node && "Setting MachineInstr of SUnit with SDNode!"); + Instr = MI; + } + + /// getInstr - Return the representative MachineInstr for this SUnit. + /// This may be used during post-regalloc scheduling. + MachineInstr *getInstr() const { + assert(!Node && "Reading MachineInstr of SUnit with SDNode!"); + return Instr; + } + + /// addPred - This adds the specified edge as a pred of the current node if + /// not already. It also adds the current node as a successor of the + /// specified node. + void addPred(const SDep &D); + + /// removePred - This removes the specified edge as a pred of the current + /// node if it exists. It also removes the current node as a successor of + /// the specified node. + void removePred(const SDep &D); + + /// getDepth - Return the depth of this node, which is the length of the + /// maximum path up to any node with has no predecessors. + unsigned getDepth() const { + if (!isDepthCurrent) + const_cast(this)->ComputeDepth(); + return Depth; + } + + /// getHeight - Return the height of this node, which is the length of the + /// maximum path down to any node with has no successors. + unsigned getHeight() const { + if (!isHeightCurrent) + const_cast(this)->ComputeHeight(); + return Height; + } + + /// setDepthToAtLeast - If NewDepth is greater than this node's + /// depth value, set it to be the new depth value. This also + /// recursively marks successor nodes dirty. + void setDepthToAtLeast(unsigned NewDepth); + + /// setDepthToAtLeast - If NewDepth is greater than this node's + /// depth value, set it to be the new height value. This also + /// recursively marks predecessor nodes dirty. + void setHeightToAtLeast(unsigned NewHeight); + + /// setDepthDirty - Set a flag in this node to indicate that its + /// stored Depth value will require recomputation the next time + /// getDepth() is called. + void setDepthDirty(); + + /// setHeightDirty - Set a flag in this node to indicate that its + /// stored Height value will require recomputation the next time + /// getHeight() is called. + void setHeightDirty(); + + /// isPred - Test if node N is a predecessor of this node. + bool isPred(SUnit *N) { + for (unsigned i = 0, e = (unsigned)Preds.size(); i != e; ++i) + if (Preds[i].getSUnit() == N) + return true; + return false; + } + + /// isSucc - Test if node N is a successor of this node. + bool isSucc(SUnit *N) { + for (unsigned i = 0, e = (unsigned)Succs.size(); i != e; ++i) + if (Succs[i].getSUnit() == N) + return true; + return false; + } + + void dump(const ScheduleDAG *G) const; + void dumpAll(const ScheduleDAG *G) const; + void print(raw_ostream &O, const ScheduleDAG *G) const; + + private: + void ComputeDepth(); + void ComputeHeight(); + }; + + //===--------------------------------------------------------------------===// + /// SchedulingPriorityQueue - This interface is used to plug different + /// priorities computation algorithms into the list scheduler. It implements + /// the interface of a standard priority queue, where nodes are inserted in + /// arbitrary order and returned in priority order. The computation of the + /// priority and the representation of the queue are totally up to the + /// implementation to decide. + /// + class SchedulingPriorityQueue { + public: + virtual ~SchedulingPriorityQueue() {} + + virtual void initNodes(std::vector &SUnits) = 0; + virtual void addNode(const SUnit *SU) = 0; + virtual void updateNode(const SUnit *SU) = 0; + virtual void releaseState() = 0; + + virtual unsigned size() const = 0; + virtual bool empty() const = 0; + virtual void push(SUnit *U) = 0; + + virtual void push_all(const std::vector &Nodes) = 0; + virtual SUnit *pop() = 0; + + virtual void remove(SUnit *SU) = 0; + + /// ScheduledNode - As each node is scheduled, this method is invoked. This + /// allows the priority function to adjust the priority of related + /// unscheduled nodes, for example. + /// + virtual void ScheduledNode(SUnit *) {} + + virtual void UnscheduledNode(SUnit *) {} + }; + + class ScheduleDAG { + public: + MachineBasicBlock *BB; // The block in which to insert instructions + MachineBasicBlock::iterator InsertPos;// The position to insert instructions + const TargetMachine &TM; // Target processor + const TargetInstrInfo *TII; // Target instruction information + const TargetRegisterInfo *TRI; // Target processor register info + const TargetLowering *TLI; // Target lowering info + MachineFunction &MF; // Machine function + MachineRegisterInfo &MRI; // Virtual/real register map + MachineConstantPool *ConstPool; // Target constant pool + std::vector Sequence; // The schedule. Null SUnit*'s + // represent noop instructions. + std::vector SUnits; // The scheduling units. + SUnit EntrySU; // Special node for the region entry. + SUnit ExitSU; // Special node for the region exit. + + explicit ScheduleDAG(MachineFunction &mf); + + virtual ~ScheduleDAG(); + + /// viewGraph - Pop up a GraphViz/gv window with the ScheduleDAG rendered + /// using 'dot'. + /// + void viewGraph(); + + /// EmitSchedule - Insert MachineInstrs into the MachineBasicBlock + /// according to the order specified in Sequence. + /// + virtual MachineBasicBlock* + EmitSchedule(DenseMap*) = 0; + + void dumpSchedule() const; + + virtual void dumpNode(const SUnit *SU) const = 0; + + /// getGraphNodeLabel - Return a label for an SUnit node in a visualization + /// of the ScheduleDAG. + virtual std::string getGraphNodeLabel(const SUnit *SU) const = 0; + + /// addCustomGraphFeatures - Add custom features for a visualization of + /// the ScheduleDAG. + virtual void addCustomGraphFeatures(GraphWriter &) const {} + +#ifndef NDEBUG + /// VerifySchedule - Verify that all SUnits were scheduled and that + /// their state is consistent. + void VerifySchedule(bool isBottomUp); +#endif + + protected: + /// Run - perform scheduling. + /// + void Run(MachineBasicBlock *bb, MachineBasicBlock::iterator insertPos); + + /// BuildSchedGraph - Build SUnits and set up their Preds and Succs + /// to form the scheduling dependency graph. + /// + virtual void BuildSchedGraph(AliasAnalysis *AA) = 0; + + /// ComputeLatency - Compute node latency. + /// + virtual void ComputeLatency(SUnit *SU) = 0; + + /// ComputeOperandLatency - Override dependence edge latency using + /// operand use/def information + /// + virtual void ComputeOperandLatency(SUnit *, SUnit *, + SDep&) const { } + + /// Schedule - Order nodes according to selected style, filling + /// in the Sequence member. + /// + virtual void Schedule() = 0; + + /// ForceUnitLatencies - Return true if all scheduling edges should be given + /// a latency value of one. The default is to return false; schedulers may + /// override this as needed. + virtual bool ForceUnitLatencies() const { return false; } + + /// EmitNoop - Emit a noop instruction. + /// + void EmitNoop(); + + void EmitPhysRegCopy(SUnit *SU, DenseMap &VRBaseMap); + }; + + class SUnitIterator : public std::iterator { + SUnit *Node; + unsigned Operand; + + SUnitIterator(SUnit *N, unsigned Op) : Node(N), Operand(Op) {} + public: + bool operator==(const SUnitIterator& x) const { + return Operand == x.Operand; + } + bool operator!=(const SUnitIterator& x) const { return !operator==(x); } + + const SUnitIterator &operator=(const SUnitIterator &I) { + assert(I.Node==Node && "Cannot assign iterators to two different nodes!"); + Operand = I.Operand; + return *this; + } + + pointer operator*() const { + return Node->Preds[Operand].getSUnit(); + } + pointer operator->() const { return operator*(); } + + SUnitIterator& operator++() { // Preincrement + ++Operand; + return *this; + } + SUnitIterator operator++(int) { // Postincrement + SUnitIterator tmp = *this; ++*this; return tmp; + } + + static SUnitIterator begin(SUnit *N) { return SUnitIterator(N, 0); } + static SUnitIterator end (SUnit *N) { + return SUnitIterator(N, (unsigned)N->Preds.size()); + } + + unsigned getOperand() const { return Operand; } + const SUnit *getNode() const { return Node; } + /// isCtrlDep - Test if this is not an SDep::Data dependence. + bool isCtrlDep() const { + return getSDep().isCtrl(); + } + bool isArtificialDep() const { + return getSDep().isArtificial(); + } + const SDep &getSDep() const { + return Node->Preds[Operand]; + } + }; + + template <> struct GraphTraits { + typedef SUnit NodeType; + typedef SUnitIterator ChildIteratorType; + static inline NodeType *getEntryNode(SUnit *N) { return N; } + static inline ChildIteratorType child_begin(NodeType *N) { + return SUnitIterator::begin(N); + } + static inline ChildIteratorType child_end(NodeType *N) { + return SUnitIterator::end(N); + } + }; + + template <> struct GraphTraits : public GraphTraits { + typedef std::vector::iterator nodes_iterator; + static nodes_iterator nodes_begin(ScheduleDAG *G) { + return G->SUnits.begin(); + } + static nodes_iterator nodes_end(ScheduleDAG *G) { + return G->SUnits.end(); + } + }; + + /// ScheduleDAGTopologicalSort is a class that computes a topological + /// ordering for SUnits and provides methods for dynamically updating + /// the ordering as new edges are added. + /// + /// This allows a very fast implementation of IsReachable, for example. + /// + class ScheduleDAGTopologicalSort { + /// SUnits - A reference to the ScheduleDAG's SUnits. + std::vector &SUnits; + + /// Index2Node - Maps topological index to the node number. + std::vector Index2Node; + /// Node2Index - Maps the node number to its topological index. + std::vector Node2Index; + /// Visited - a set of nodes visited during a DFS traversal. + BitVector Visited; + + /// DFS - make a DFS traversal and mark all nodes affected by the + /// edge insertion. These nodes will later get new topological indexes + /// by means of the Shift method. + void DFS(const SUnit *SU, int UpperBound, bool& HasLoop); + + /// Shift - reassign topological indexes for the nodes in the DAG + /// to preserve the topological ordering. + void Shift(BitVector& Visited, int LowerBound, int UpperBound); + + /// Allocate - assign the topological index to the node n. + void Allocate(int n, int index); + + public: + explicit ScheduleDAGTopologicalSort(std::vector &SUnits); + + /// InitDAGTopologicalSorting - create the initial topological + /// ordering from the DAG to be scheduled. + void InitDAGTopologicalSorting(); + + /// IsReachable - Checks if SU is reachable from TargetSU. + bool IsReachable(const SUnit *SU, const SUnit *TargetSU); + + /// WillCreateCycle - Returns true if adding an edge from SU to TargetSU + /// will create a cycle. + bool WillCreateCycle(SUnit *SU, SUnit *TargetSU); + + /// AddPred - Updates the topological ordering to accomodate an edge + /// to be added from SUnit X to SUnit Y. + void AddPred(SUnit *Y, SUnit *X); + + /// RemovePred - Updates the topological ordering to accomodate an + /// an edge to be removed from the specified node N from the predecessors + /// of the current node M. + void RemovePred(SUnit *M, SUnit *N); + + typedef std::vector::iterator iterator; + typedef std::vector::const_iterator const_iterator; + iterator begin() { return Index2Node.begin(); } + const_iterator begin() const { return Index2Node.begin(); } + iterator end() { return Index2Node.end(); } + const_iterator end() const { return Index2Node.end(); } + + typedef std::vector::reverse_iterator reverse_iterator; + typedef std::vector::const_reverse_iterator const_reverse_iterator; + reverse_iterator rbegin() { return Index2Node.rbegin(); } + const_reverse_iterator rbegin() const { return Index2Node.rbegin(); } + reverse_iterator rend() { return Index2Node.rend(); } + const_reverse_iterator rend() const { return Index2Node.rend(); } + }; +} + +#endif diff --git a/libclamav/c++/llvm/include/llvm/CodeGen/ScheduleHazardRecognizer.h b/libclamav/c++/llvm/include/llvm/CodeGen/ScheduleHazardRecognizer.h new file mode 100644 index 000000000..09e3e8861 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/CodeGen/ScheduleHazardRecognizer.h @@ -0,0 +1,71 @@ +//=- llvm/CodeGen/ScheduleHazardRecognizer.h - Scheduling Support -*- 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 the ScheduleHazardRecognizer class, which implements +// hazard-avoidance heuristics for scheduling. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_SCHEDULEHAZARDRECOGNIZER_H +#define LLVM_CODEGEN_SCHEDULEHAZARDRECOGNIZER_H + +namespace llvm { + +class SUnit; + +/// HazardRecognizer - This determines whether or not an instruction can be +/// issued this cycle, and whether or not a noop needs to be inserted to handle +/// the hazard. +class ScheduleHazardRecognizer { +public: + virtual ~ScheduleHazardRecognizer(); + + enum HazardType { + NoHazard, // This instruction can be emitted at this cycle. + Hazard, // This instruction can't be emitted at this cycle. + NoopHazard // This instruction can't be emitted, and needs noops. + }; + + /// getHazardType - Return the hazard type of emitting this node. There are + /// three possible results. Either: + /// * NoHazard: it is legal to issue this instruction on this cycle. + /// * Hazard: issuing this instruction would stall the machine. If some + /// other instruction is available, issue it first. + /// * NoopHazard: issuing this instruction would break the program. If + /// some other instruction can be issued, do so, otherwise issue a noop. + virtual HazardType getHazardType(SUnit *) { + return NoHazard; + } + + /// Reset - This callback is invoked when a new block of + /// instructions is about to be schedule. The hazard state should be + /// set to an initialized state. + virtual void Reset() {} + + /// EmitInstruction - This callback is invoked when an instruction is + /// emitted, to advance the hazard state. + virtual void EmitInstruction(SUnit *) {} + + /// AdvanceCycle - This callback is invoked when no instructions can be + /// issued on this cycle without a hazard. This should increment the + /// internal state of the hazard recognizer so that previously "Hazard" + /// instructions will now not be hazards. + virtual void AdvanceCycle() {} + + /// EmitNoop - This callback is invoked when a noop was added to the + /// instruction stream. + virtual void EmitNoop() { + // Default implementation: count it as a cycle. + AdvanceCycle(); + } +}; + +} + +#endif diff --git a/libclamav/c++/llvm/include/llvm/CodeGen/SchedulerRegistry.h b/libclamav/c++/llvm/include/llvm/CodeGen/SchedulerRegistry.h new file mode 100644 index 000000000..1cf64a09a --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/CodeGen/SchedulerRegistry.h @@ -0,0 +1,93 @@ +//===-- llvm/CodeGen/SchedulerRegistry.h ------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the implementation for instruction scheduler function +// pass registry (RegisterScheduler). +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGENSCHEDULERREGISTRY_H +#define LLVM_CODEGENSCHEDULERREGISTRY_H + +#include "llvm/CodeGen/MachinePassRegistry.h" +#include "llvm/Target/TargetMachine.h" + +namespace llvm { + +//===----------------------------------------------------------------------===// +/// +/// RegisterScheduler class - Track the registration of instruction schedulers. +/// +//===----------------------------------------------------------------------===// + +class SelectionDAGISel; +class ScheduleDAGSDNodes; +class SelectionDAG; +class MachineBasicBlock; + +class RegisterScheduler : public MachinePassRegistryNode { +public: + typedef ScheduleDAGSDNodes *(*FunctionPassCtor)(SelectionDAGISel*, + CodeGenOpt::Level); + + static MachinePassRegistry Registry; + + RegisterScheduler(const char *N, const char *D, FunctionPassCtor C) + : MachinePassRegistryNode(N, D, (MachinePassCtor)C) + { Registry.Add(this); } + ~RegisterScheduler() { Registry.Remove(this); } + + + // Accessors. + // + RegisterScheduler *getNext() const { + return (RegisterScheduler *)MachinePassRegistryNode::getNext(); + } + static RegisterScheduler *getList() { + return (RegisterScheduler *)Registry.getList(); + } + static FunctionPassCtor getDefault() { + return (FunctionPassCtor)Registry.getDefault(); + } + static void setDefault(FunctionPassCtor C) { + Registry.setDefault((MachinePassCtor)C); + } + static void setListener(MachinePassRegistryListener *L) { + Registry.setListener(L); + } +}; + +/// createBURRListDAGScheduler - This creates a bottom up register usage +/// reduction list scheduler. +ScheduleDAGSDNodes *createBURRListDAGScheduler(SelectionDAGISel *IS, + CodeGenOpt::Level OptLevel); + +/// createTDRRListDAGScheduler - This creates a top down register usage +/// reduction list scheduler. +ScheduleDAGSDNodes *createTDRRListDAGScheduler(SelectionDAGISel *IS, + CodeGenOpt::Level OptLevel); + +/// createTDListDAGScheduler - This creates a top-down list scheduler with +/// a hazard recognizer. +ScheduleDAGSDNodes *createTDListDAGScheduler(SelectionDAGISel *IS, + CodeGenOpt::Level OptLevel); + +/// createFastDAGScheduler - This creates a "fast" scheduler. +/// +ScheduleDAGSDNodes *createFastDAGScheduler(SelectionDAGISel *IS, + CodeGenOpt::Level OptLevel); + +/// createDefaultScheduler - This creates an instruction scheduler appropriate +/// for the target. +ScheduleDAGSDNodes *createDefaultScheduler(SelectionDAGISel *IS, + CodeGenOpt::Level OptLevel); + +} // end namespace llvm + +#endif diff --git a/libclamav/c++/llvm/include/llvm/CodeGen/SelectionDAG.h b/libclamav/c++/llvm/include/llvm/CodeGen/SelectionDAG.h new file mode 100644 index 000000000..f194e4e3f --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/CodeGen/SelectionDAG.h @@ -0,0 +1,926 @@ +//===-- llvm/CodeGen/SelectionDAG.h - InstSelection DAG ---------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the SelectionDAG class, and transitively defines the +// SDNode class and subclasses. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_SELECTIONDAG_H +#define LLVM_CODEGEN_SELECTIONDAG_H + +#include "llvm/ADT/ilist.h" +#include "llvm/ADT/DenseSet.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/CodeGen/SelectionDAGNodes.h" +#include "llvm/Support/RecyclingAllocator.h" +#include "llvm/Target/TargetMachine.h" +#include +#include +#include +#include + +namespace llvm { + +class AliasAnalysis; +class TargetLowering; +class MachineModuleInfo; +class DwarfWriter; +class MachineFunction; +class MachineConstantPoolValue; +class FunctionLoweringInfo; + +template<> struct ilist_traits : public ilist_default_traits { +private: + mutable ilist_half_node Sentinel; +public: + SDNode *createSentinel() const { + return static_cast(&Sentinel); + } + static void destroySentinel(SDNode *) {} + + SDNode *provideInitialHead() const { return createSentinel(); } + SDNode *ensureHead(SDNode*) const { return createSentinel(); } + static void noteHead(SDNode*, SDNode*) {} + + static void deleteNode(SDNode *) { + assert(0 && "ilist_traits shouldn't see a deleteNode call!"); + } +private: + static void createNode(const SDNode &); +}; + +enum CombineLevel { + Unrestricted, // Combine may create illegal operations and illegal types. + NoIllegalTypes, // Combine may create illegal operations but no illegal types. + NoIllegalOperations // Combine may only create legal operations and types. +}; + +/// SelectionDAG class - This is used to represent a portion of an LLVM function +/// in a low-level Data Dependence DAG representation suitable for instruction +/// selection. This DAG is constructed as the first step of instruction +/// selection in order to allow implementation of machine specific optimizations +/// and code simplifications. +/// +/// The representation used by the SelectionDAG is a target-independent +/// representation, which has some similarities to the GCC RTL representation, +/// but is significantly more simple, powerful, and is a graph form instead of a +/// linear form. +/// +class SelectionDAG { + TargetLowering &TLI; + MachineFunction *MF; + FunctionLoweringInfo &FLI; + MachineModuleInfo *MMI; + DwarfWriter *DW; + LLVMContext* Context; + + /// EntryNode - The starting token. + SDNode EntryNode; + + /// Root - The root of the entire DAG. + SDValue Root; + + /// AllNodes - A linked list of nodes in the current DAG. + ilist AllNodes; + + /// NodeAllocatorType - The AllocatorType for allocating SDNodes. We use + /// pool allocation with recycling. + typedef RecyclingAllocator::Alignment> + NodeAllocatorType; + + /// NodeAllocator - Pool allocation for nodes. + NodeAllocatorType NodeAllocator; + + /// CSEMap - This structure is used to memoize nodes, automatically performing + /// CSE with existing nodes when a duplicate is requested. + FoldingSet CSEMap; + + /// OperandAllocator - Pool allocation for machine-opcode SDNode operands. + BumpPtrAllocator OperandAllocator; + + /// Allocator - Pool allocation for misc. objects that are created once per + /// SelectionDAG. + BumpPtrAllocator Allocator; + + /// VerifyNode - Sanity check the given node. Aborts if it is invalid. + void VerifyNode(SDNode *N); + + /// setGraphColorHelper - Implementation of setSubgraphColor. + /// Return whether we had to truncate the search. + /// + bool setSubgraphColorHelper(SDNode *N, const char *Color, + DenseSet &visited, + int level, bool &printed); + +public: + SelectionDAG(TargetLowering &tli, FunctionLoweringInfo &fli); + ~SelectionDAG(); + + /// init - Prepare this SelectionDAG to process code in the given + /// MachineFunction. + /// + void init(MachineFunction &mf, MachineModuleInfo *mmi, DwarfWriter *dw); + + /// clear - Clear state and free memory necessary to make this + /// SelectionDAG ready to process a new block. + /// + void clear(); + + MachineFunction &getMachineFunction() const { return *MF; } + const TargetMachine &getTarget() const; + TargetLowering &getTargetLoweringInfo() const { return TLI; } + FunctionLoweringInfo &getFunctionLoweringInfo() const { return FLI; } + MachineModuleInfo *getMachineModuleInfo() const { return MMI; } + DwarfWriter *getDwarfWriter() const { return DW; } + LLVMContext *getContext() const {return Context; } + + /// viewGraph - Pop up a GraphViz/gv window with the DAG rendered using 'dot'. + /// + void viewGraph(const std::string &Title); + void viewGraph(); + +#ifndef NDEBUG + std::map NodeGraphAttrs; +#endif + + /// clearGraphAttrs - Clear all previously defined node graph attributes. + /// Intended to be used from a debugging tool (eg. gdb). + void clearGraphAttrs(); + + /// setGraphAttrs - Set graph attributes for a node. (eg. "color=red".) + /// + void setGraphAttrs(const SDNode *N, const char *Attrs); + + /// getGraphAttrs - Get graph attributes for a node. (eg. "color=red".) + /// Used from getNodeAttributes. + const std::string getGraphAttrs(const SDNode *N) const; + + /// setGraphColor - Convenience for setting node color attribute. + /// + void setGraphColor(const SDNode *N, const char *Color); + + /// setGraphColor - Convenience for setting subgraph color attribute. + /// + void setSubgraphColor(SDNode *N, const char *Color); + + typedef ilist::const_iterator allnodes_const_iterator; + allnodes_const_iterator allnodes_begin() const { return AllNodes.begin(); } + allnodes_const_iterator allnodes_end() const { return AllNodes.end(); } + typedef ilist::iterator allnodes_iterator; + allnodes_iterator allnodes_begin() { return AllNodes.begin(); } + allnodes_iterator allnodes_end() { return AllNodes.end(); } + ilist::size_type allnodes_size() const { + return AllNodes.size(); + } + + /// getRoot - Return the root tag of the SelectionDAG. + /// + const SDValue &getRoot() const { return Root; } + + /// getEntryNode - Return the token chain corresponding to the entry of the + /// function. + SDValue getEntryNode() const { + return SDValue(const_cast(&EntryNode), 0); + } + + /// setRoot - Set the current root tag of the SelectionDAG. + /// + const SDValue &setRoot(SDValue N) { + assert((!N.getNode() || N.getValueType() == MVT::Other) && + "DAG root value is not a chain!"); + return Root = N; + } + + /// Combine - This iterates over the nodes in the SelectionDAG, folding + /// certain types of nodes together, or eliminating superfluous nodes. The + /// Level argument controls whether Combine is allowed to produce nodes and + /// types that are illegal on the target. + void Combine(CombineLevel Level, AliasAnalysis &AA, + CodeGenOpt::Level OptLevel); + + /// LegalizeTypes - This transforms the SelectionDAG into a SelectionDAG that + /// only uses types natively supported by the target. Returns "true" if it + /// made any changes. + /// + /// Note that this is an involved process that may invalidate pointers into + /// the graph. + bool LegalizeTypes(); + + /// Legalize - This transforms the SelectionDAG into a SelectionDAG that is + /// compatible with the target instruction selector, as indicated by the + /// TargetLowering object. + /// + /// Note that this is an involved process that may invalidate pointers into + /// the graph. + void Legalize(bool TypesNeedLegalizing, CodeGenOpt::Level OptLevel); + + /// LegalizeVectors - This transforms the SelectionDAG into a SelectionDAG + /// that only uses vector math operations supported by the target. This is + /// necessary as a separate step from Legalize because unrolling a vector + /// operation can introduce illegal types, which requires running + /// LegalizeTypes again. + /// + /// This returns true if it made any changes; in that case, LegalizeTypes + /// is called again before Legalize. + /// + /// Note that this is an involved process that may invalidate pointers into + /// the graph. + bool LegalizeVectors(); + + /// RemoveDeadNodes - This method deletes all unreachable nodes in the + /// SelectionDAG. + void RemoveDeadNodes(); + + /// DeleteNode - Remove the specified node from the system. This node must + /// have no referrers. + void DeleteNode(SDNode *N); + + /// getVTList - Return an SDVTList that represents the list of values + /// specified. + SDVTList getVTList(EVT VT); + SDVTList getVTList(EVT VT1, EVT VT2); + SDVTList getVTList(EVT VT1, EVT VT2, EVT VT3); + SDVTList getVTList(EVT VT1, EVT VT2, EVT VT3, EVT VT4); + SDVTList getVTList(const EVT *VTs, unsigned NumVTs); + + //===--------------------------------------------------------------------===// + // Node creation methods. + // + SDValue getConstant(uint64_t Val, EVT VT, bool isTarget = false); + SDValue getConstant(const APInt &Val, EVT VT, bool isTarget = false); + SDValue getConstant(const ConstantInt &Val, EVT VT, bool isTarget = false); + SDValue getIntPtrConstant(uint64_t Val, bool isTarget = false); + SDValue getTargetConstant(uint64_t Val, EVT VT) { + return getConstant(Val, VT, true); + } + SDValue getTargetConstant(const APInt &Val, EVT VT) { + return getConstant(Val, VT, true); + } + SDValue getTargetConstant(const ConstantInt &Val, EVT VT) { + return getConstant(Val, VT, true); + } + SDValue getConstantFP(double Val, EVT VT, bool isTarget = false); + SDValue getConstantFP(const APFloat& Val, EVT VT, bool isTarget = false); + SDValue getConstantFP(const ConstantFP &CF, EVT VT, bool isTarget = false); + SDValue getTargetConstantFP(double Val, EVT VT) { + return getConstantFP(Val, VT, true); + } + SDValue getTargetConstantFP(const APFloat& Val, EVT VT) { + return getConstantFP(Val, VT, true); + } + SDValue getTargetConstantFP(const ConstantFP &Val, EVT VT) { + return getConstantFP(Val, VT, true); + } + SDValue getGlobalAddress(const GlobalValue *GV, EVT VT, + int64_t offset = 0, bool isTargetGA = false, + unsigned char TargetFlags = 0); + SDValue getTargetGlobalAddress(const GlobalValue *GV, EVT VT, + int64_t offset = 0, + unsigned char TargetFlags = 0) { + return getGlobalAddress(GV, VT, offset, true, TargetFlags); + } + SDValue getFrameIndex(int FI, EVT VT, bool isTarget = false); + SDValue getTargetFrameIndex(int FI, EVT VT) { + return getFrameIndex(FI, VT, true); + } + SDValue getJumpTable(int JTI, EVT VT, bool isTarget = false, + unsigned char TargetFlags = 0); + SDValue getTargetJumpTable(int JTI, EVT VT, unsigned char TargetFlags = 0) { + return getJumpTable(JTI, VT, true, TargetFlags); + } + SDValue getConstantPool(Constant *C, EVT VT, + unsigned Align = 0, int Offs = 0, bool isT=false, + unsigned char TargetFlags = 0); + SDValue getTargetConstantPool(Constant *C, EVT VT, + unsigned Align = 0, int Offset = 0, + unsigned char TargetFlags = 0) { + return getConstantPool(C, VT, Align, Offset, true, TargetFlags); + } + SDValue getConstantPool(MachineConstantPoolValue *C, EVT VT, + unsigned Align = 0, int Offs = 0, bool isT=false, + unsigned char TargetFlags = 0); + SDValue getTargetConstantPool(MachineConstantPoolValue *C, + EVT VT, unsigned Align = 0, + int Offset = 0, unsigned char TargetFlags=0) { + return getConstantPool(C, VT, Align, Offset, true, TargetFlags); + } + // When generating a branch to a BB, we don't in general know enough + // to provide debug info for the BB at that time, so keep this one around. + SDValue getBasicBlock(MachineBasicBlock *MBB); + SDValue getBasicBlock(MachineBasicBlock *MBB, DebugLoc dl); + SDValue getExternalSymbol(const char *Sym, EVT VT); + SDValue getExternalSymbol(const char *Sym, DebugLoc dl, EVT VT); + SDValue getTargetExternalSymbol(const char *Sym, EVT VT, + unsigned char TargetFlags = 0); + SDValue getValueType(EVT); + SDValue getRegister(unsigned Reg, EVT VT); + SDValue getLabel(unsigned Opcode, DebugLoc dl, SDValue Root, + unsigned LabelID); + SDValue getBlockAddress(BlockAddress *BA, EVT VT, + bool isTarget = false, unsigned char TargetFlags = 0); + + SDValue getCopyToReg(SDValue Chain, DebugLoc dl, unsigned Reg, SDValue N) { + return getNode(ISD::CopyToReg, dl, MVT::Other, Chain, + getRegister(Reg, N.getValueType()), N); + } + + // This version of the getCopyToReg method takes an extra operand, which + // indicates that there is potentially an incoming flag value (if Flag is not + // null) and that there should be a flag result. + SDValue getCopyToReg(SDValue Chain, DebugLoc dl, unsigned Reg, SDValue N, + SDValue Flag) { + SDVTList VTs = getVTList(MVT::Other, MVT::Flag); + SDValue Ops[] = { Chain, getRegister(Reg, N.getValueType()), N, Flag }; + return getNode(ISD::CopyToReg, dl, VTs, Ops, Flag.getNode() ? 4 : 3); + } + + // Similar to last getCopyToReg() except parameter Reg is a SDValue + SDValue getCopyToReg(SDValue Chain, DebugLoc dl, SDValue Reg, SDValue N, + SDValue Flag) { + SDVTList VTs = getVTList(MVT::Other, MVT::Flag); + SDValue Ops[] = { Chain, Reg, N, Flag }; + return getNode(ISD::CopyToReg, dl, VTs, Ops, Flag.getNode() ? 4 : 3); + } + + SDValue getCopyFromReg(SDValue Chain, DebugLoc dl, unsigned Reg, EVT VT) { + SDVTList VTs = getVTList(VT, MVT::Other); + SDValue Ops[] = { Chain, getRegister(Reg, VT) }; + return getNode(ISD::CopyFromReg, dl, VTs, Ops, 2); + } + + // This version of the getCopyFromReg method takes an extra operand, which + // indicates that there is potentially an incoming flag value (if Flag is not + // null) and that there should be a flag result. + SDValue getCopyFromReg(SDValue Chain, DebugLoc dl, unsigned Reg, EVT VT, + SDValue Flag) { + SDVTList VTs = getVTList(VT, MVT::Other, MVT::Flag); + SDValue Ops[] = { Chain, getRegister(Reg, VT), Flag }; + return getNode(ISD::CopyFromReg, dl, VTs, Ops, Flag.getNode() ? 3 : 2); + } + + SDValue getCondCode(ISD::CondCode Cond); + + /// Returns the ConvertRndSat Note: Avoid using this node because it may + /// disappear in the future and most targets don't support it. + SDValue getConvertRndSat(EVT VT, DebugLoc dl, SDValue Val, SDValue DTy, + SDValue STy, + SDValue Rnd, SDValue Sat, ISD::CvtCode Code); + + /// getVectorShuffle - Return an ISD::VECTOR_SHUFFLE node. The number of + /// elements in VT, which must be a vector type, must match the number of + /// mask elements NumElts. A integer mask element equal to -1 is treated as + /// undefined. + SDValue getVectorShuffle(EVT VT, DebugLoc dl, SDValue N1, SDValue N2, + const int *MaskElts); + + /// getSExtOrTrunc - Convert Op, which must be of integer type, to the + /// integer type VT, by either sign-extending or truncating it. + SDValue getSExtOrTrunc(SDValue Op, DebugLoc DL, EVT VT); + + /// getZExtOrTrunc - Convert Op, which must be of integer type, to the + /// integer type VT, by either zero-extending or truncating it. + SDValue getZExtOrTrunc(SDValue Op, DebugLoc DL, EVT VT); + + /// getZeroExtendInReg - Return the expression required to zero extend the Op + /// value assuming it was the smaller SrcTy value. + SDValue getZeroExtendInReg(SDValue Op, DebugLoc DL, EVT SrcTy); + + /// getNOT - Create a bitwise NOT operation as (XOR Val, -1). + SDValue getNOT(DebugLoc DL, SDValue Val, EVT VT); + + /// getCALLSEQ_START - Return a new CALLSEQ_START node, which always must have + /// a flag result (to ensure it's not CSE'd). CALLSEQ_START does not have a + /// useful DebugLoc. + SDValue getCALLSEQ_START(SDValue Chain, SDValue Op) { + SDVTList VTs = getVTList(MVT::Other, MVT::Flag); + SDValue Ops[] = { Chain, Op }; + return getNode(ISD::CALLSEQ_START, DebugLoc::getUnknownLoc(), + VTs, Ops, 2); + } + + /// getCALLSEQ_END - Return a new CALLSEQ_END node, which always must have a + /// flag result (to ensure it's not CSE'd). CALLSEQ_END does not have + /// a useful DebugLoc. + SDValue getCALLSEQ_END(SDValue Chain, SDValue Op1, SDValue Op2, + SDValue InFlag) { + SDVTList NodeTys = getVTList(MVT::Other, MVT::Flag); + SmallVector Ops; + Ops.push_back(Chain); + Ops.push_back(Op1); + Ops.push_back(Op2); + Ops.push_back(InFlag); + return getNode(ISD::CALLSEQ_END, DebugLoc::getUnknownLoc(), NodeTys, + &Ops[0], + (unsigned)Ops.size() - (InFlag.getNode() == 0 ? 1 : 0)); + } + + /// getUNDEF - Return an UNDEF node. UNDEF does not have a useful DebugLoc. + SDValue getUNDEF(EVT VT) { + return getNode(ISD::UNDEF, DebugLoc::getUnknownLoc(), VT); + } + + /// getGLOBAL_OFFSET_TABLE - Return a GLOBAL_OFFSET_TABLE node. This does + /// not have a useful DebugLoc. + SDValue getGLOBAL_OFFSET_TABLE(EVT VT) { + return getNode(ISD::GLOBAL_OFFSET_TABLE, DebugLoc::getUnknownLoc(), VT); + } + + /// getNode - Gets or creates the specified node. + /// + SDValue getNode(unsigned Opcode, DebugLoc DL, EVT VT); + SDValue getNode(unsigned Opcode, DebugLoc DL, EVT VT, SDValue N); + SDValue getNode(unsigned Opcode, DebugLoc DL, EVT VT, SDValue N1, SDValue N2); + SDValue getNode(unsigned Opcode, DebugLoc DL, EVT VT, + SDValue N1, SDValue N2, SDValue N3); + SDValue getNode(unsigned Opcode, DebugLoc DL, EVT VT, + SDValue N1, SDValue N2, SDValue N3, SDValue N4); + SDValue getNode(unsigned Opcode, DebugLoc DL, EVT VT, + SDValue N1, SDValue N2, SDValue N3, SDValue N4, + SDValue N5); + SDValue getNode(unsigned Opcode, DebugLoc DL, EVT VT, + const SDUse *Ops, unsigned NumOps); + SDValue getNode(unsigned Opcode, DebugLoc DL, EVT VT, + const SDValue *Ops, unsigned NumOps); + SDValue getNode(unsigned Opcode, DebugLoc DL, + const std::vector &ResultTys, + const SDValue *Ops, unsigned NumOps); + SDValue getNode(unsigned Opcode, DebugLoc DL, const EVT *VTs, unsigned NumVTs, + const SDValue *Ops, unsigned NumOps); + SDValue getNode(unsigned Opcode, DebugLoc DL, SDVTList VTs, + const SDValue *Ops, unsigned NumOps); + SDValue getNode(unsigned Opcode, DebugLoc DL, SDVTList VTs); + SDValue getNode(unsigned Opcode, DebugLoc DL, SDVTList VTs, SDValue N); + SDValue getNode(unsigned Opcode, DebugLoc DL, SDVTList VTs, + SDValue N1, SDValue N2); + SDValue getNode(unsigned Opcode, DebugLoc DL, SDVTList VTs, + SDValue N1, SDValue N2, SDValue N3); + SDValue getNode(unsigned Opcode, DebugLoc DL, SDVTList VTs, + SDValue N1, SDValue N2, SDValue N3, SDValue N4); + SDValue getNode(unsigned Opcode, DebugLoc DL, SDVTList VTs, + SDValue N1, SDValue N2, SDValue N3, SDValue N4, + SDValue N5); + + /// getStackArgumentTokenFactor - Compute a TokenFactor to force all + /// the incoming stack arguments to be loaded from the stack. This is + /// used in tail call lowering to protect stack arguments from being + /// clobbered. + SDValue getStackArgumentTokenFactor(SDValue Chain); + + SDValue getMemcpy(SDValue Chain, DebugLoc dl, SDValue Dst, SDValue Src, + SDValue Size, unsigned Align, bool AlwaysInline, + const Value *DstSV, uint64_t DstSVOff, + const Value *SrcSV, uint64_t SrcSVOff); + + SDValue getMemmove(SDValue Chain, DebugLoc dl, SDValue Dst, SDValue Src, + SDValue Size, unsigned Align, + const Value *DstSV, uint64_t DstOSVff, + const Value *SrcSV, uint64_t SrcSVOff); + + SDValue getMemset(SDValue Chain, DebugLoc dl, SDValue Dst, SDValue Src, + SDValue Size, unsigned Align, + const Value *DstSV, uint64_t DstSVOff); + + /// getSetCC - Helper function to make it easier to build SetCC's if you just + /// have an ISD::CondCode instead of an SDValue. + /// + SDValue getSetCC(DebugLoc DL, EVT VT, SDValue LHS, SDValue RHS, + ISD::CondCode Cond) { + return getNode(ISD::SETCC, DL, VT, LHS, RHS, getCondCode(Cond)); + } + + /// getVSetCC - Helper function to make it easier to build VSetCC's nodes + /// if you just have an ISD::CondCode instead of an SDValue. + /// + SDValue getVSetCC(DebugLoc DL, EVT VT, SDValue LHS, SDValue RHS, + ISD::CondCode Cond) { + return getNode(ISD::VSETCC, DL, VT, LHS, RHS, getCondCode(Cond)); + } + + /// getSelectCC - Helper function to make it easier to build SelectCC's if you + /// just have an ISD::CondCode instead of an SDValue. + /// + SDValue getSelectCC(DebugLoc DL, SDValue LHS, SDValue RHS, + SDValue True, SDValue False, ISD::CondCode Cond) { + return getNode(ISD::SELECT_CC, DL, True.getValueType(), + LHS, RHS, True, False, getCondCode(Cond)); + } + + /// getVAArg - VAArg produces a result and token chain, and takes a pointer + /// and a source value as input. + SDValue getVAArg(EVT VT, DebugLoc dl, SDValue Chain, SDValue Ptr, + SDValue SV); + + /// getAtomic - Gets a node for an atomic op, produces result and chain and + /// takes 3 operands + SDValue getAtomic(unsigned Opcode, DebugLoc dl, EVT MemVT, SDValue Chain, + SDValue Ptr, SDValue Cmp, SDValue Swp, const Value* PtrVal, + unsigned Alignment=0); + SDValue getAtomic(unsigned Opcode, DebugLoc dl, EVT MemVT, SDValue Chain, + SDValue Ptr, SDValue Cmp, SDValue Swp, + MachineMemOperand *MMO); + + /// getAtomic - Gets a node for an atomic op, produces result and chain and + /// takes 2 operands. + SDValue getAtomic(unsigned Opcode, DebugLoc dl, EVT MemVT, SDValue Chain, + SDValue Ptr, SDValue Val, const Value* PtrVal, + unsigned Alignment = 0); + SDValue getAtomic(unsigned Opcode, DebugLoc dl, EVT MemVT, SDValue Chain, + SDValue Ptr, SDValue Val, + MachineMemOperand *MMO); + + /// getMemIntrinsicNode - Creates a MemIntrinsicNode that may produce a + /// result and takes a list of operands. Opcode may be INTRINSIC_VOID, + /// INTRINSIC_W_CHAIN, or a target-specific opcode with a value not + /// less than FIRST_TARGET_MEMORY_OPCODE. + SDValue getMemIntrinsicNode(unsigned Opcode, DebugLoc dl, + const EVT *VTs, unsigned NumVTs, + const SDValue *Ops, unsigned NumOps, + EVT MemVT, const Value *srcValue, int SVOff, + unsigned Align = 0, bool Vol = false, + bool ReadMem = true, bool WriteMem = true); + + SDValue getMemIntrinsicNode(unsigned Opcode, DebugLoc dl, SDVTList VTList, + const SDValue *Ops, unsigned NumOps, + EVT MemVT, const Value *srcValue, int SVOff, + unsigned Align = 0, bool Vol = false, + bool ReadMem = true, bool WriteMem = true); + + SDValue getMemIntrinsicNode(unsigned Opcode, DebugLoc dl, SDVTList VTList, + const SDValue *Ops, unsigned NumOps, + EVT MemVT, MachineMemOperand *MMO); + + /// getMergeValues - Create a MERGE_VALUES node from the given operands. + SDValue getMergeValues(const SDValue *Ops, unsigned NumOps, DebugLoc dl); + + /// getLoad - Loads are not normal binary operators: their result type is not + /// determined by their operands, and they produce a value AND a token chain. + /// + SDValue getLoad(EVT VT, DebugLoc dl, SDValue Chain, SDValue Ptr, + const Value *SV, int SVOffset, bool isVolatile=false, + unsigned Alignment=0); + SDValue getExtLoad(ISD::LoadExtType ExtType, DebugLoc dl, EVT VT, + SDValue Chain, SDValue Ptr, const Value *SV, + int SVOffset, EVT MemVT, bool isVolatile=false, + unsigned Alignment=0); + SDValue getIndexedLoad(SDValue OrigLoad, DebugLoc dl, SDValue Base, + SDValue Offset, ISD::MemIndexedMode AM); + SDValue getLoad(ISD::MemIndexedMode AM, DebugLoc dl, ISD::LoadExtType ExtType, + EVT VT, SDValue Chain, SDValue Ptr, SDValue Offset, + const Value *SV, int SVOffset, EVT MemVT, + bool isVolatile=false, unsigned Alignment=0); + SDValue getLoad(ISD::MemIndexedMode AM, DebugLoc dl, ISD::LoadExtType ExtType, + EVT VT, SDValue Chain, SDValue Ptr, SDValue Offset, + EVT MemVT, MachineMemOperand *MMO); + + /// getStore - Helper function to build ISD::STORE nodes. + /// + SDValue getStore(SDValue Chain, DebugLoc dl, SDValue Val, SDValue Ptr, + const Value *SV, int SVOffset, bool isVolatile=false, + unsigned Alignment=0); + SDValue getStore(SDValue Chain, DebugLoc dl, SDValue Val, SDValue Ptr, + MachineMemOperand *MMO); + SDValue getTruncStore(SDValue Chain, DebugLoc dl, SDValue Val, SDValue Ptr, + const Value *SV, int SVOffset, EVT TVT, + bool isVolatile=false, unsigned Alignment=0); + SDValue getTruncStore(SDValue Chain, DebugLoc dl, SDValue Val, SDValue Ptr, + EVT TVT, MachineMemOperand *MMO); + SDValue getIndexedStore(SDValue OrigStoe, DebugLoc dl, SDValue Base, + SDValue Offset, ISD::MemIndexedMode AM); + + /// getSrcValue - Construct a node to track a Value* through the backend. + SDValue getSrcValue(const Value *v); + + /// getShiftAmountOperand - Return the specified value casted to + /// the target's desired shift amount type. + SDValue getShiftAmountOperand(SDValue Op); + + /// UpdateNodeOperands - *Mutate* the specified node in-place to have the + /// specified operands. If the resultant node already exists in the DAG, + /// this does not modify the specified node, instead it returns the node that + /// already exists. If the resultant node does not exist in the DAG, the + /// input node is returned. As a degenerate case, if you specify the same + /// input operands as the node already has, the input node is returned. + SDValue UpdateNodeOperands(SDValue N, SDValue Op); + SDValue UpdateNodeOperands(SDValue N, SDValue Op1, SDValue Op2); + SDValue UpdateNodeOperands(SDValue N, SDValue Op1, SDValue Op2, + SDValue Op3); + SDValue UpdateNodeOperands(SDValue N, SDValue Op1, SDValue Op2, + SDValue Op3, SDValue Op4); + SDValue UpdateNodeOperands(SDValue N, SDValue Op1, SDValue Op2, + SDValue Op3, SDValue Op4, SDValue Op5); + SDValue UpdateNodeOperands(SDValue N, + const SDValue *Ops, unsigned NumOps); + + /// SelectNodeTo - These are used for target selectors to *mutate* the + /// specified node to have the specified return type, Target opcode, and + /// operands. Note that target opcodes are stored as + /// ~TargetOpcode in the node opcode field. The resultant node is returned. + SDNode *SelectNodeTo(SDNode *N, unsigned TargetOpc, EVT VT); + SDNode *SelectNodeTo(SDNode *N, unsigned TargetOpc, EVT VT, SDValue Op1); + SDNode *SelectNodeTo(SDNode *N, unsigned TargetOpc, EVT VT, + SDValue Op1, SDValue Op2); + SDNode *SelectNodeTo(SDNode *N, unsigned TargetOpc, EVT VT, + SDValue Op1, SDValue Op2, SDValue Op3); + SDNode *SelectNodeTo(SDNode *N, unsigned TargetOpc, EVT VT, + const SDValue *Ops, unsigned NumOps); + SDNode *SelectNodeTo(SDNode *N, unsigned TargetOpc, EVT VT1, EVT VT2); + SDNode *SelectNodeTo(SDNode *N, unsigned TargetOpc, EVT VT1, + EVT VT2, const SDValue *Ops, unsigned NumOps); + SDNode *SelectNodeTo(SDNode *N, unsigned TargetOpc, EVT VT1, + EVT VT2, EVT VT3, const SDValue *Ops, unsigned NumOps); + SDNode *SelectNodeTo(SDNode *N, unsigned MachineOpc, EVT VT1, + EVT VT2, EVT VT3, EVT VT4, const SDValue *Ops, + unsigned NumOps); + SDNode *SelectNodeTo(SDNode *N, unsigned TargetOpc, EVT VT1, + EVT VT2, SDValue Op1); + SDNode *SelectNodeTo(SDNode *N, unsigned TargetOpc, EVT VT1, + EVT VT2, SDValue Op1, SDValue Op2); + SDNode *SelectNodeTo(SDNode *N, unsigned TargetOpc, EVT VT1, + EVT VT2, SDValue Op1, SDValue Op2, SDValue Op3); + SDNode *SelectNodeTo(SDNode *N, unsigned TargetOpc, EVT VT1, + EVT VT2, EVT VT3, SDValue Op1, SDValue Op2, SDValue Op3); + SDNode *SelectNodeTo(SDNode *N, unsigned TargetOpc, SDVTList VTs, + const SDValue *Ops, unsigned NumOps); + + /// MorphNodeTo - These *mutate* the specified node to have the specified + /// return type, opcode, and operands. + SDNode *MorphNodeTo(SDNode *N, unsigned Opc, EVT VT); + SDNode *MorphNodeTo(SDNode *N, unsigned Opc, EVT VT, SDValue Op1); + SDNode *MorphNodeTo(SDNode *N, unsigned Opc, EVT VT, + SDValue Op1, SDValue Op2); + SDNode *MorphNodeTo(SDNode *N, unsigned Opc, EVT VT, + SDValue Op1, SDValue Op2, SDValue Op3); + SDNode *MorphNodeTo(SDNode *N, unsigned Opc, EVT VT, + const SDValue *Ops, unsigned NumOps); + SDNode *MorphNodeTo(SDNode *N, unsigned Opc, EVT VT1, EVT VT2); + SDNode *MorphNodeTo(SDNode *N, unsigned Opc, EVT VT1, + EVT VT2, const SDValue *Ops, unsigned NumOps); + SDNode *MorphNodeTo(SDNode *N, unsigned Opc, EVT VT1, + EVT VT2, EVT VT3, const SDValue *Ops, unsigned NumOps); + SDNode *MorphNodeTo(SDNode *N, unsigned Opc, EVT VT1, + EVT VT2, SDValue Op1); + SDNode *MorphNodeTo(SDNode *N, unsigned Opc, EVT VT1, + EVT VT2, SDValue Op1, SDValue Op2); + SDNode *MorphNodeTo(SDNode *N, unsigned Opc, EVT VT1, + EVT VT2, SDValue Op1, SDValue Op2, SDValue Op3); + SDNode *MorphNodeTo(SDNode *N, unsigned Opc, SDVTList VTs, + const SDValue *Ops, unsigned NumOps); + + /// getMachineNode - These are used for target selectors to create a new node + /// with specified return type(s), MachineInstr opcode, and operands. + /// + /// Note that getMachineNode returns the resultant node. If there is already + /// a node of the specified opcode and operands, it returns that node instead + /// of the current one. + MachineSDNode *getMachineNode(unsigned Opcode, DebugLoc dl, EVT VT); + MachineSDNode *getMachineNode(unsigned Opcode, DebugLoc dl, EVT VT, + SDValue Op1); + MachineSDNode *getMachineNode(unsigned Opcode, DebugLoc dl, EVT VT, + SDValue Op1, SDValue Op2); + MachineSDNode *getMachineNode(unsigned Opcode, DebugLoc dl, EVT VT, + SDValue Op1, SDValue Op2, SDValue Op3); + MachineSDNode *getMachineNode(unsigned Opcode, DebugLoc dl, EVT VT, + const SDValue *Ops, unsigned NumOps); + MachineSDNode *getMachineNode(unsigned Opcode, DebugLoc dl, EVT VT1, EVT VT2); + MachineSDNode *getMachineNode(unsigned Opcode, DebugLoc dl, EVT VT1, EVT VT2, + SDValue Op1); + MachineSDNode *getMachineNode(unsigned Opcode, DebugLoc dl, EVT VT1, + EVT VT2, SDValue Op1, SDValue Op2); + MachineSDNode *getMachineNode(unsigned Opcode, DebugLoc dl, EVT VT1, + EVT VT2, SDValue Op1, SDValue Op2, SDValue Op3); + MachineSDNode *getMachineNode(unsigned Opcode, DebugLoc dl, EVT VT1, EVT VT2, + const SDValue *Ops, unsigned NumOps); + MachineSDNode *getMachineNode(unsigned Opcode, DebugLoc dl, EVT VT1, EVT VT2, + EVT VT3, SDValue Op1, SDValue Op2); + MachineSDNode *getMachineNode(unsigned Opcode, DebugLoc dl, EVT VT1, EVT VT2, + EVT VT3, SDValue Op1, SDValue Op2, SDValue Op3); + MachineSDNode *getMachineNode(unsigned Opcode, DebugLoc dl, EVT VT1, EVT VT2, + EVT VT3, const SDValue *Ops, unsigned NumOps); + MachineSDNode *getMachineNode(unsigned Opcode, DebugLoc dl, EVT VT1, EVT VT2, + EVT VT3, EVT VT4, const SDValue *Ops, unsigned NumOps); + MachineSDNode *getMachineNode(unsigned Opcode, DebugLoc dl, + const std::vector &ResultTys, const SDValue *Ops, + unsigned NumOps); + MachineSDNode *getMachineNode(unsigned Opcode, DebugLoc dl, SDVTList VTs, + const SDValue *Ops, unsigned NumOps); + + /// getTargetExtractSubreg - A convenience function for creating + /// TargetInstrInfo::EXTRACT_SUBREG nodes. + SDValue getTargetExtractSubreg(int SRIdx, DebugLoc DL, EVT VT, + SDValue Operand); + + /// getTargetInsertSubreg - A convenience function for creating + /// TargetInstrInfo::INSERT_SUBREG nodes. + SDValue getTargetInsertSubreg(int SRIdx, DebugLoc DL, EVT VT, + SDValue Operand, SDValue Subreg); + + /// getNodeIfExists - Get the specified node if it's already available, or + /// else return NULL. + SDNode *getNodeIfExists(unsigned Opcode, SDVTList VTs, + const SDValue *Ops, unsigned NumOps); + + /// DAGUpdateListener - Clients of various APIs that cause global effects on + /// the DAG can optionally implement this interface. This allows the clients + /// to handle the various sorts of updates that happen. + class DAGUpdateListener { + public: + virtual ~DAGUpdateListener(); + + /// NodeDeleted - The node N that was deleted and, if E is not null, an + /// equivalent node E that replaced it. + virtual void NodeDeleted(SDNode *N, SDNode *E) = 0; + + /// NodeUpdated - The node N that was updated. + virtual void NodeUpdated(SDNode *N) = 0; + }; + + /// RemoveDeadNode - Remove the specified node from the system. If any of its + /// operands then becomes dead, remove them as well. Inform UpdateListener + /// for each node deleted. + void RemoveDeadNode(SDNode *N, DAGUpdateListener *UpdateListener = 0); + + /// RemoveDeadNodes - This method deletes the unreachable nodes in the + /// given list, and any nodes that become unreachable as a result. + void RemoveDeadNodes(SmallVectorImpl &DeadNodes, + DAGUpdateListener *UpdateListener = 0); + + /// ReplaceAllUsesWith - Modify anything using 'From' to use 'To' instead. + /// This can cause recursive merging of nodes in the DAG. Use the first + /// version if 'From' is known to have a single result, use the second + /// if you have two nodes with identical results (or if 'To' has a superset + /// of the results of 'From'), use the third otherwise. + /// + /// These methods all take an optional UpdateListener, which (if not null) is + /// informed about nodes that are deleted and modified due to recursive + /// changes in the dag. + /// + /// These functions only replace all existing uses. It's possible that as + /// these replacements are being performed, CSE may cause the From node + /// to be given new uses. These new uses of From are left in place, and + /// not automatically transfered to To. + /// + void ReplaceAllUsesWith(SDValue From, SDValue Op, + DAGUpdateListener *UpdateListener = 0); + void ReplaceAllUsesWith(SDNode *From, SDNode *To, + DAGUpdateListener *UpdateListener = 0); + void ReplaceAllUsesWith(SDNode *From, const SDValue *To, + DAGUpdateListener *UpdateListener = 0); + + /// ReplaceAllUsesOfValueWith - Replace any uses of From with To, leaving + /// uses of other values produced by From.Val alone. + void ReplaceAllUsesOfValueWith(SDValue From, SDValue To, + DAGUpdateListener *UpdateListener = 0); + + /// ReplaceAllUsesOfValuesWith - Like ReplaceAllUsesOfValueWith, but + /// for multiple values at once. This correctly handles the case where + /// there is an overlap between the From values and the To values. + void ReplaceAllUsesOfValuesWith(const SDValue *From, const SDValue *To, + unsigned Num, + DAGUpdateListener *UpdateListener = 0); + + /// AssignTopologicalOrder - Topological-sort the AllNodes list and a + /// assign a unique node id for each node in the DAG based on their + /// topological order. Returns the number of nodes. + unsigned AssignTopologicalOrder(); + + /// RepositionNode - Move node N in the AllNodes list to be immediately + /// before the given iterator Position. This may be used to update the + /// topological ordering when the list of nodes is modified. + void RepositionNode(allnodes_iterator Position, SDNode *N) { + AllNodes.insert(Position, AllNodes.remove(N)); + } + + /// isCommutativeBinOp - Returns true if the opcode is a commutative binary + /// operation. + static bool isCommutativeBinOp(unsigned Opcode) { + // FIXME: This should get its info from the td file, so that we can include + // target info. + switch (Opcode) { + case ISD::ADD: + case ISD::MUL: + case ISD::MULHU: + case ISD::MULHS: + case ISD::SMUL_LOHI: + case ISD::UMUL_LOHI: + case ISD::FADD: + case ISD::FMUL: + case ISD::AND: + case ISD::OR: + case ISD::XOR: + case ISD::SADDO: + case ISD::UADDO: + case ISD::ADDC: + case ISD::ADDE: return true; + default: return false; + } + } + + void dump() const; + + /// CreateStackTemporary - Create a stack temporary, suitable for holding the + /// specified value type. If minAlign is specified, the slot size will have + /// at least that alignment. + SDValue CreateStackTemporary(EVT VT, unsigned minAlign = 1); + + /// CreateStackTemporary - Create a stack temporary suitable for holding + /// either of the specified value types. + SDValue CreateStackTemporary(EVT VT1, EVT VT2); + + /// FoldConstantArithmetic - + SDValue FoldConstantArithmetic(unsigned Opcode, + EVT VT, + ConstantSDNode *Cst1, + ConstantSDNode *Cst2); + + /// FoldSetCC - Constant fold a setcc to true or false. + SDValue FoldSetCC(EVT VT, SDValue N1, + SDValue N2, ISD::CondCode Cond, DebugLoc dl); + + /// SignBitIsZero - Return true if the sign bit of Op is known to be zero. We + /// use this predicate to simplify operations downstream. + bool SignBitIsZero(SDValue Op, unsigned Depth = 0) const; + + /// MaskedValueIsZero - Return true if 'Op & Mask' is known to be zero. We + /// use this predicate to simplify operations downstream. Op and Mask are + /// known to be the same type. + bool MaskedValueIsZero(SDValue Op, const APInt &Mask, unsigned Depth = 0) + const; + + /// ComputeMaskedBits - Determine which of the bits specified in Mask are + /// known to be either zero or one and return them in the KnownZero/KnownOne + /// bitsets. This code only analyzes bits in Mask, in order to short-circuit + /// processing. Targets can implement the computeMaskedBitsForTargetNode + /// method in the TargetLowering class to allow target nodes to be understood. + void ComputeMaskedBits(SDValue Op, const APInt &Mask, APInt &KnownZero, + APInt &KnownOne, unsigned Depth = 0) const; + + /// ComputeNumSignBits - Return the number of times the sign bit of the + /// register is replicated into the other bits. We know that at least 1 bit + /// is always equal to the sign bit (itself), but other cases can give us + /// information. For example, immediately after an "SRA X, 2", we know that + /// the top 3 bits are all equal to each other, so we return 3. Targets can + /// implement the ComputeNumSignBitsForTarget method in the TargetLowering + /// class to allow target nodes to be understood. + unsigned ComputeNumSignBits(SDValue Op, unsigned Depth = 0) const; + + /// isKnownNeverNan - Test whether the given SDValue is known to never be NaN. + bool isKnownNeverNaN(SDValue Op) const; + + /// isVerifiedDebugInfoDesc - Returns true if the specified SDValue has + /// been verified as a debug information descriptor. + bool isVerifiedDebugInfoDesc(SDValue Op) const; + + /// getShuffleScalarElt - Returns the scalar element that will make up the ith + /// element of the result of the vector shuffle. + SDValue getShuffleScalarElt(const ShuffleVectorSDNode *N, unsigned Idx); + +private: + bool RemoveNodeFromCSEMaps(SDNode *N); + void AddModifiedNodeToCSEMaps(SDNode *N, DAGUpdateListener *UpdateListener); + SDNode *FindModifiedNodeSlot(SDNode *N, SDValue Op, void *&InsertPos); + SDNode *FindModifiedNodeSlot(SDNode *N, SDValue Op1, SDValue Op2, + void *&InsertPos); + SDNode *FindModifiedNodeSlot(SDNode *N, const SDValue *Ops, unsigned NumOps, + void *&InsertPos); + + void DeleteNodeNotInCSEMaps(SDNode *N); + void DeallocateNode(SDNode *N); + + unsigned getEVTAlignment(EVT MemoryVT) const; + + void allnodes_clear(); + + /// VTList - List of non-single value types. + std::vector VTList; + + /// CondCodeNodes - Maps to auto-CSE operations. + std::vector CondCodeNodes; + + std::vector ValueTypeNodes; + std::map ExtendedValueTypeNodes; + StringMap ExternalSymbols; + + std::map,SDNode*> TargetExternalSymbols; +}; + +template <> struct GraphTraits : public GraphTraits { + typedef SelectionDAG::allnodes_iterator nodes_iterator; + static nodes_iterator nodes_begin(SelectionDAG *G) { + return G->allnodes_begin(); + } + static nodes_iterator nodes_end(SelectionDAG *G) { + return G->allnodes_end(); + } +}; + +} // end namespace llvm + +#endif diff --git a/libclamav/c++/llvm/include/llvm/CodeGen/SelectionDAGISel.h b/libclamav/c++/llvm/include/llvm/CodeGen/SelectionDAGISel.h new file mode 100644 index 000000000..4130d2c0a --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/CodeGen/SelectionDAGISel.h @@ -0,0 +1,150 @@ +//===-- llvm/CodeGen/SelectionDAGISel.h - Common Base Class------*- 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 the SelectionDAGISel class, which is used as the common +// base class for SelectionDAG-based instruction selectors. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_SELECTIONDAG_ISEL_H +#define LLVM_CODEGEN_SELECTIONDAG_ISEL_H + +#include "llvm/BasicBlock.h" +#include "llvm/Pass.h" +#include "llvm/Constant.h" +#include "llvm/CodeGen/SelectionDAG.h" +#include "llvm/CodeGen/MachineFunctionPass.h" + +namespace llvm { + class FastISel; + class SelectionDAGBuilder; + class SDValue; + class MachineRegisterInfo; + class MachineBasicBlock; + class MachineFunction; + class MachineInstr; + class MachineModuleInfo; + class DwarfWriter; + class TargetLowering; + class TargetInstrInfo; + class FunctionLoweringInfo; + class ScheduleHazardRecognizer; + class GCFunctionInfo; + class ScheduleDAGSDNodes; + +/// SelectionDAGISel - This is the common base class used for SelectionDAG-based +/// pattern-matching instruction selectors. +class SelectionDAGISel : public MachineFunctionPass { +public: + const TargetMachine &TM; + TargetLowering &TLI; + FunctionLoweringInfo *FuncInfo; + MachineFunction *MF; + MachineRegisterInfo *RegInfo; + SelectionDAG *CurDAG; + SelectionDAGBuilder *SDB; + MachineBasicBlock *BB; + AliasAnalysis *AA; + GCFunctionInfo *GFI; + CodeGenOpt::Level OptLevel; + static char ID; + + explicit SelectionDAGISel(TargetMachine &tm, + CodeGenOpt::Level OL = CodeGenOpt::Default); + virtual ~SelectionDAGISel(); + + TargetLowering &getTargetLowering() { return TLI; } + + virtual void getAnalysisUsage(AnalysisUsage &AU) const; + + virtual bool runOnMachineFunction(MachineFunction &MF); + + unsigned MakeReg(EVT VT); + + virtual void EmitFunctionEntryCode(Function &Fn, MachineFunction &MF) {} + virtual void InstructionSelect() = 0; + + void SelectRootInit() { + DAGSize = CurDAG->AssignTopologicalOrder(); + } + + /// SelectInlineAsmMemoryOperand - Select the specified address as a target + /// addressing mode, according to the specified constraint code. If this does + /// not match or is not implemented, return true. The resultant operands + /// (which will appear in the machine instruction) should be added to the + /// OutOps vector. + virtual bool SelectInlineAsmMemoryOperand(const SDValue &Op, + char ConstraintCode, + std::vector &OutOps) { + return true; + } + + /// IsLegalAndProfitableToFold - Returns true if the specific operand node N of + /// U can be folded during instruction selection that starts at Root and + /// folding N is profitable. + virtual + bool IsLegalAndProfitableToFold(SDNode *N, SDNode *U, SDNode *Root) const; + + /// CreateTargetHazardRecognizer - Return a newly allocated hazard recognizer + /// to use for this target when scheduling the DAG. + virtual ScheduleHazardRecognizer *CreateTargetHazardRecognizer(); + +protected: + /// DAGSize - Size of DAG being instruction selected. + /// + unsigned DAGSize; + + /// SelectInlineAsmMemoryOperands - Calls to this are automatically generated + /// by tblgen. Others should not call it. + void SelectInlineAsmMemoryOperands(std::vector &Ops); + + // Calls to these predicates are generated by tblgen. + bool CheckAndMask(SDValue LHS, ConstantSDNode *RHS, + int64_t DesiredMaskS) const; + bool CheckOrMask(SDValue LHS, ConstantSDNode *RHS, + int64_t DesiredMaskS) const; + + // Calls to these functions are generated by tblgen. + SDNode *Select_INLINEASM(SDValue N); + SDNode *Select_UNDEF(const SDValue &N); + SDNode *Select_DBG_LABEL(const SDValue &N); + SDNode *Select_EH_LABEL(const SDValue &N); + void CannotYetSelect(SDValue N); + void CannotYetSelectIntrinsic(SDValue N); + +private: + void SelectAllBasicBlocks(Function &Fn, MachineFunction &MF, + MachineModuleInfo *MMI, + DwarfWriter *DW, + const TargetInstrInfo &TII); + void FinishBasicBlock(); + + void SelectBasicBlock(BasicBlock *LLVMBB, + BasicBlock::iterator Begin, + BasicBlock::iterator End, + bool &HadTailCall); + void CodeGenAndEmitDAG(); + void LowerArguments(BasicBlock *BB); + + void ComputeLiveOutVRegInfo(); + + void HandlePHINodesInSuccessorBlocks(BasicBlock *LLVMBB); + + bool HandlePHINodesInSuccessorBlocksFast(BasicBlock *LLVMBB, FastISel *F); + + /// Create the scheduler. If a specific scheduler was specified + /// via the SchedulerRegistry, use it, otherwise select the + /// one preferred by the target. + /// + ScheduleDAGSDNodes *CreateScheduler(); +}; + +} + +#endif /* LLVM_CODEGEN_SELECTIONDAG_ISEL_H */ diff --git a/libclamav/c++/llvm/include/llvm/CodeGen/SelectionDAGNodes.h b/libclamav/c++/llvm/include/llvm/CodeGen/SelectionDAGNodes.h new file mode 100644 index 000000000..950fd322d --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/CodeGen/SelectionDAGNodes.h @@ -0,0 +1,2506 @@ +//===-- llvm/CodeGen/SelectionDAGNodes.h - SelectionDAG Nodes ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the SDNode class and derived classes, which are used to +// represent the nodes and operations present in a SelectionDAG. These nodes +// and operations are machine code level operations, with some similarities to +// the GCC RTL representation. +// +// Clients should include the SelectionDAG.h file instead of this file directly. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_SELECTIONDAGNODES_H +#define LLVM_CODEGEN_SELECTIONDAGNODES_H + +#include "llvm/Constants.h" +#include "llvm/ADT/FoldingSet.h" +#include "llvm/ADT/GraphTraits.h" +#include "llvm/ADT/ilist_node.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/CodeGen/ValueTypes.h" +#include "llvm/CodeGen/MachineMemOperand.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/System/DataTypes.h" +#include "llvm/Support/DebugLoc.h" +#include + +namespace llvm { + +class SelectionDAG; +class GlobalValue; +class MachineBasicBlock; +class MachineConstantPoolValue; +class SDNode; +class Value; +template struct DenseMapInfo; +template struct simplify_type; +template struct ilist_traits; + +/// SDVTList - This represents a list of ValueType's that has been intern'd by +/// a SelectionDAG. Instances of this simple value class are returned by +/// SelectionDAG::getVTList(...). +/// +struct SDVTList { + const EVT *VTs; + unsigned int NumVTs; +}; + +/// ISD namespace - This namespace contains an enum which represents all of the +/// SelectionDAG node types and value types. +/// +namespace ISD { + + //===--------------------------------------------------------------------===// + /// ISD::NodeType enum - This enum defines the target-independent operators + /// for a SelectionDAG. + /// + /// Targets may also define target-dependent operator codes for SDNodes. For + /// example, on x86, these are the enum values in the X86ISD namespace. + /// Targets should aim to use target-independent operators to model their + /// instruction sets as much as possible, and only use target-dependent + /// operators when they have special requirements. + /// + /// Finally, during and after selection proper, SNodes may use special + /// operator codes that correspond directly with MachineInstr opcodes. These + /// are used to represent selected instructions. See the isMachineOpcode() + /// and getMachineOpcode() member functions of SDNode. + /// + enum NodeType { + // DELETED_NODE - This is an illegal value that is used to catch + // errors. This opcode is not a legal opcode for any node. + DELETED_NODE, + + // EntryToken - This is the marker used to indicate the start of the region. + EntryToken, + + // TokenFactor - This node takes multiple tokens as input and produces a + // single token result. This is used to represent the fact that the operand + // operators are independent of each other. + TokenFactor, + + // AssertSext, AssertZext - These nodes record if a register contains a + // value that has already been zero or sign extended from a narrower type. + // These nodes take two operands. The first is the node that has already + // been extended, and the second is a value type node indicating the width + // of the extension + AssertSext, AssertZext, + + // Various leaf nodes. + BasicBlock, VALUETYPE, CONDCODE, Register, + Constant, ConstantFP, + GlobalAddress, GlobalTLSAddress, FrameIndex, + JumpTable, ConstantPool, ExternalSymbol, BlockAddress, + + // The address of the GOT + GLOBAL_OFFSET_TABLE, + + // FRAMEADDR, RETURNADDR - These nodes represent llvm.frameaddress and + // llvm.returnaddress on the DAG. These nodes take one operand, the index + // of the frame or return address to return. An index of zero corresponds + // to the current function's frame or return address, an index of one to the + // parent's frame or return address, and so on. + FRAMEADDR, RETURNADDR, + + // FRAME_TO_ARGS_OFFSET - This node represents offset from frame pointer to + // first (possible) on-stack argument. This is needed for correct stack + // adjustment during unwind. + FRAME_TO_ARGS_OFFSET, + + // RESULT, OUTCHAIN = EXCEPTIONADDR(INCHAIN) - This node represents the + // address of the exception block on entry to an landing pad block. + EXCEPTIONADDR, + + // RESULT, OUTCHAIN = LSDAADDR(INCHAIN) - This node represents the + // address of the Language Specific Data Area for the enclosing function. + LSDAADDR, + + // RESULT, OUTCHAIN = EHSELECTION(INCHAIN, EXCEPTION) - This node represents + // the selection index of the exception thrown. + EHSELECTION, + + // OUTCHAIN = EH_RETURN(INCHAIN, OFFSET, HANDLER) - This node represents + // 'eh_return' gcc dwarf builtin, which is used to return from + // exception. The general meaning is: adjust stack by OFFSET and pass + // execution to HANDLER. Many platform-related details also :) + EH_RETURN, + + // TargetConstant* - Like Constant*, but the DAG does not do any folding or + // simplification of the constant. + TargetConstant, + TargetConstantFP, + + // TargetGlobalAddress - Like GlobalAddress, but the DAG does no folding or + // anything else with this node, and this is valid in the target-specific + // dag, turning into a GlobalAddress operand. + TargetGlobalAddress, + TargetGlobalTLSAddress, + TargetFrameIndex, + TargetJumpTable, + TargetConstantPool, + TargetExternalSymbol, + TargetBlockAddress, + + /// RESULT = INTRINSIC_WO_CHAIN(INTRINSICID, arg1, arg2, ...) + /// This node represents a target intrinsic function with no side effects. + /// The first operand is the ID number of the intrinsic from the + /// llvm::Intrinsic namespace. The operands to the intrinsic follow. The + /// node has returns the result of the intrinsic. + INTRINSIC_WO_CHAIN, + + /// RESULT,OUTCHAIN = INTRINSIC_W_CHAIN(INCHAIN, INTRINSICID, arg1, ...) + /// This node represents a target intrinsic function with side effects that + /// returns a result. The first operand is a chain pointer. The second is + /// the ID number of the intrinsic from the llvm::Intrinsic namespace. The + /// operands to the intrinsic follow. The node has two results, the result + /// of the intrinsic and an output chain. + INTRINSIC_W_CHAIN, + + /// OUTCHAIN = INTRINSIC_VOID(INCHAIN, INTRINSICID, arg1, arg2, ...) + /// This node represents a target intrinsic function with side effects that + /// does not return a result. The first operand is a chain pointer. The + /// second is the ID number of the intrinsic from the llvm::Intrinsic + /// namespace. The operands to the intrinsic follow. + INTRINSIC_VOID, + + // CopyToReg - This node has three operands: a chain, a register number to + // set to this value, and a value. + CopyToReg, + + // CopyFromReg - This node indicates that the input value is a virtual or + // physical register that is defined outside of the scope of this + // SelectionDAG. The register is available from the RegisterSDNode object. + CopyFromReg, + + // UNDEF - An undefined node + UNDEF, + + // EXTRACT_ELEMENT - This is used to get the lower or upper (determined by + // a Constant, which is required to be operand #1) half of the integer or + // float value specified as operand #0. This is only for use before + // legalization, for values that will be broken into multiple registers. + EXTRACT_ELEMENT, + + // BUILD_PAIR - This is the opposite of EXTRACT_ELEMENT in some ways. Given + // two values of the same integer value type, this produces a value twice as + // big. Like EXTRACT_ELEMENT, this can only be used before legalization. + BUILD_PAIR, + + // MERGE_VALUES - This node takes multiple discrete operands and returns + // them all as its individual results. This nodes has exactly the same + // number of inputs and outputs. This node is useful for some pieces of the + // code generator that want to think about a single node with multiple + // results, not multiple nodes. + MERGE_VALUES, + + // Simple integer binary arithmetic operators. + ADD, SUB, MUL, SDIV, UDIV, SREM, UREM, + + // SMUL_LOHI/UMUL_LOHI - Multiply two integers of type iN, producing + // a signed/unsigned value of type i[2*N], and return the full value as + // two results, each of type iN. + SMUL_LOHI, UMUL_LOHI, + + // SDIVREM/UDIVREM - Divide two integers and produce both a quotient and + // remainder result. + SDIVREM, UDIVREM, + + // CARRY_FALSE - This node is used when folding other nodes, + // like ADDC/SUBC, which indicate the carry result is always false. + CARRY_FALSE, + + // Carry-setting nodes for multiple precision addition and subtraction. + // These nodes take two operands of the same value type, and produce two + // results. The first result is the normal add or sub result, the second + // result is the carry flag result. + ADDC, SUBC, + + // Carry-using nodes for multiple precision addition and subtraction. These + // nodes take three operands: The first two are the normal lhs and rhs to + // the add or sub, and the third is the input carry flag. These nodes + // produce two results; the normal result of the add or sub, and the output + // carry flag. These nodes both read and write a carry flag to allow them + // to them to be chained together for add and sub of arbitrarily large + // values. + ADDE, SUBE, + + // RESULT, BOOL = [SU]ADDO(LHS, RHS) - Overflow-aware nodes for addition. + // These nodes take two operands: the normal LHS and RHS to the add. They + // produce two results: the normal result of the add, and a boolean that + // indicates if an overflow occured (*not* a flag, because it may be stored + // to memory, etc.). If the type of the boolean is not i1 then the high + // bits conform to getBooleanContents. + // These nodes are generated from the llvm.[su]add.with.overflow intrinsics. + SADDO, UADDO, + + // Same for subtraction + SSUBO, USUBO, + + // Same for multiplication + SMULO, UMULO, + + // Simple binary floating point operators. + FADD, FSUB, FMUL, FDIV, FREM, + + // FCOPYSIGN(X, Y) - Return the value of X with the sign of Y. NOTE: This + // DAG node does not require that X and Y have the same type, just that they + // are both floating point. X and the result must have the same type. + // FCOPYSIGN(f32, f64) is allowed. + FCOPYSIGN, + + // INT = FGETSIGN(FP) - Return the sign bit of the specified floating point + // value as an integer 0/1 value. + FGETSIGN, + + /// BUILD_VECTOR(ELT0, ELT1, ELT2, ELT3,...) - Return a vector with the + /// specified, possibly variable, elements. The number of elements is + /// required to be a power of two. The types of the operands must all be + /// the same and must match the vector element type, except that integer + /// types are allowed to be larger than the element type, in which case + /// the operands are implicitly truncated. + BUILD_VECTOR, + + /// INSERT_VECTOR_ELT(VECTOR, VAL, IDX) - Returns VECTOR with the element + /// at IDX replaced with VAL. If the type of VAL is larger than the vector + /// element type then VAL is truncated before replacement. + INSERT_VECTOR_ELT, + + /// EXTRACT_VECTOR_ELT(VECTOR, IDX) - Returns a single element from VECTOR + /// identified by the (potentially variable) element number IDX. If the + /// return type is an integer type larger than the element type of the + /// vector, the result is extended to the width of the return type. + EXTRACT_VECTOR_ELT, + + /// CONCAT_VECTORS(VECTOR0, VECTOR1, ...) - Given a number of values of + /// vector type with the same length and element type, this produces a + /// concatenated vector result value, with length equal to the sum of the + /// lengths of the input vectors. + CONCAT_VECTORS, + + /// EXTRACT_SUBVECTOR(VECTOR, IDX) - Returns a subvector from VECTOR (an + /// vector value) starting with the (potentially variable) element number + /// IDX, which must be a multiple of the result vector length. + EXTRACT_SUBVECTOR, + + /// VECTOR_SHUFFLE(VEC1, VEC2) - Returns a vector, of the same type as + /// VEC1/VEC2. A VECTOR_SHUFFLE node also contains an array of constant int + /// values that indicate which value (or undef) each result element will + /// get. These constant ints are accessible through the + /// ShuffleVectorSDNode class. This is quite similar to the Altivec + /// 'vperm' instruction, except that the indices must be constants and are + /// in terms of the element size of VEC1/VEC2, not in terms of bytes. + VECTOR_SHUFFLE, + + /// SCALAR_TO_VECTOR(VAL) - This represents the operation of loading a + /// scalar value into element 0 of the resultant vector type. The top + /// elements 1 to N-1 of the N-element vector are undefined. The type + /// of the operand must match the vector element type, except when they + /// are integer types. In this case the operand is allowed to be wider + /// than the vector element type, and is implicitly truncated to it. + SCALAR_TO_VECTOR, + + // MULHU/MULHS - Multiply high - Multiply two integers of type iN, producing + // an unsigned/signed value of type i[2*N], then return the top part. + MULHU, MULHS, + + // Bitwise operators - logical and, logical or, logical xor, shift left, + // shift right algebraic (shift in sign bits), shift right logical (shift in + // zeroes), rotate left, rotate right, and byteswap. + AND, OR, XOR, SHL, SRA, SRL, ROTL, ROTR, BSWAP, + + // Counting operators + CTTZ, CTLZ, CTPOP, + + // Select(COND, TRUEVAL, FALSEVAL). If the type of the boolean COND is not + // i1 then the high bits must conform to getBooleanContents. + SELECT, + + // 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 + // the lhs and rhs (ops #0 and #1) of a conditional expression with the + // condition code in op #4, a CondCodeSDNode. + SELECT_CC, + + // SetCC operator - This evaluates to a true value iff the condition is + // 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 + // operands to compare (ops #0, and #1) and the condition code to compare + // them with (op #2) as a CondCodeSDNode. + 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 + // integer shift operations, just like ADD/SUB_PARTS. The operation + // ordering is: + // [Lo,Hi] = op [LoLHS,HiLHS], Amt + SHL_PARTS, SRA_PARTS, SRL_PARTS, + + // Conversion operators. These are all single input single output + // operations. For all of these, the result type must be strictly + // wider or narrower (depending on the operation) than the source + // type. + + // SIGN_EXTEND - Used for integer types, replicating the sign bit + // into new bits. + SIGN_EXTEND, + + // ZERO_EXTEND - Used for integer types, zeroing the new bits. + ZERO_EXTEND, + + // ANY_EXTEND - Used for integer types. The high bits are undefined. + ANY_EXTEND, + + // TRUNCATE - Completely drop the high bits. + TRUNCATE, + + // [SU]INT_TO_FP - These operators convert integers (whose interpreted sign + // depends on the first letter) to floating point. + SINT_TO_FP, + UINT_TO_FP, + + // SIGN_EXTEND_INREG - This operator atomically performs a SHL/SRA pair to + // sign extend a small value in a large integer register (e.g. sign + // extending the low 8 bits of a 32-bit register to fill the top 24 bits + // with the 7th bit). The size of the smaller type is indicated by the 1th + // operand, a ValueType node. + SIGN_EXTEND_INREG, + + /// FP_TO_[US]INT - Convert a floating point value to a signed or unsigned + /// integer. + FP_TO_SINT, + FP_TO_UINT, + + /// X = FP_ROUND(Y, TRUNC) - Rounding 'Y' from a larger floating point type + /// down to the precision of the destination VT. TRUNC is a flag, which is + /// always an integer that is zero or one. If TRUNC is 0, this is a + /// normal rounding, if it is 1, this FP_ROUND is known to not change the + /// value of Y. + /// + /// The TRUNC = 1 case is used in cases where we know that the value will + /// not be modified by the node, because Y is not using any of the extra + /// precision of source type. This allows certain transformations like + /// FP_EXTEND(FP_ROUND(X,1)) -> X which are not safe for + /// FP_EXTEND(FP_ROUND(X,0)) because the extra bits aren't removed. + FP_ROUND, + + // FLT_ROUNDS_ - Returns current rounding mode: + // -1 Undefined + // 0 Round to 0 + // 1 Round to nearest + // 2 Round to +inf + // 3 Round to -inf + FLT_ROUNDS_, + + /// X = FP_ROUND_INREG(Y, VT) - This operator takes an FP register, and + /// rounds it to a floating point value. It then promotes it and returns it + /// in a register of the same size. This operation effectively just + /// discards excess precision. The type to round down to is specified by + /// the VT operand, a VTSDNode. + FP_ROUND_INREG, + + /// X = FP_EXTEND(Y) - Extend a smaller FP type into a larger FP type. + FP_EXTEND, + + // BIT_CONVERT - Theis operator converts between integer and FP values, as + // if one was stored to memory as integer and the other was loaded from the + // same address (or equivalently for vector format conversions, etc). The + // source and result are required to have the same bit size (e.g. + // f32 <-> i32). This can also be used for int-to-int or fp-to-fp + // conversions, but that is a noop, deleted by getNode(). + BIT_CONVERT, + + // CONVERT_RNDSAT - This operator is used to support various conversions + // between various types (float, signed, unsigned and vectors of those + // types) with rounding and saturation. NOTE: Avoid using this operator as + // most target don't support it and the operator might be removed in the + // future. It takes the following arguments: + // 0) value + // 1) dest type (type to convert to) + // 2) src type (type to convert from) + // 3) rounding imm + // 4) saturation imm + // 5) ISD::CvtCode indicating the type of conversion to do + CONVERT_RNDSAT, + + // FNEG, FABS, FSQRT, FSIN, FCOS, FPOWI, FPOW, + // FLOG, FLOG2, FLOG10, FEXP, FEXP2, + // FCEIL, FTRUNC, FRINT, FNEARBYINT, FFLOOR - Perform various unary floating + // point operations. These are inspired by libm. + FNEG, FABS, FSQRT, FSIN, FCOS, FPOWI, FPOW, + FLOG, FLOG2, FLOG10, FEXP, FEXP2, + FCEIL, FTRUNC, FRINT, FNEARBYINT, FFLOOR, + + // LOAD and STORE have token chains as their first operand, then the same + // operands as an LLVM load/store instruction, then an offset node that + // is added / subtracted from the base pointer to form the address (for + // indexed memory ops). + LOAD, STORE, + + // DYNAMIC_STACKALLOC - Allocate some number of bytes on the stack aligned + // to a specified boundary. This node always has two return values: a new + // stack pointer value and a chain. The first operand is the token chain, + // the second is the number of bytes to allocate, and the third is the + // alignment boundary. The size is guaranteed to be a multiple of the stack + // alignment, and the alignment is guaranteed to be bigger than the stack + // alignment (if required) or 0 to get standard stack alignment. + DYNAMIC_STACKALLOC, + + // Control flow instructions. These all have token chains. + + // BR - Unconditional branch. The first operand is the chain + // operand, the second is the MBB to branch to. + BR, + + // BRIND - Indirect branch. The first operand is the chain, the second + // is the value to branch to, which must be of the same type as the target's + // pointer type. + BRIND, + + // BR_JT - Jumptable branch. The first operand is the chain, the second + // is the jumptable index, the last one is the jumptable entry index. + BR_JT, + + // BRCOND - Conditional branch. The first operand is the chain, the + // second is the condition, the third is the block to branch to if the + // condition is true. If the type of the condition is not i1, then the + // high bits must conform to getBooleanContents. + BRCOND, + + // BR_CC - Conditional branch. The behavior is like that of SELECT_CC, in + // that the condition is represented as condition code, and two nodes to + // compare, rather than as a combined SetCC node. The operands in order are + // chain, cc, lhs, rhs, block to branch to if condition is true. + BR_CC, + + // INLINEASM - Represents an inline asm block. This node always has two + // return values: a chain and a flag result. The inputs are as follows: + // Operand #0 : Input chain. + // Operand #1 : a ExternalSymbolSDNode with a pointer to the asm string. + // Operand #2n+2: A RegisterNode. + // Operand #2n+3: A TargetConstant, indicating if the reg is a use/def + // Operand #last: Optional, an incoming flag. + INLINEASM, + + // EH_LABEL - Represents a label in mid basic block used to track + // locations needed for debug and exception handling tables. These nodes + // take a chain as input and return a chain. + EH_LABEL, + + // STACKSAVE - STACKSAVE has one operand, an input chain. It produces a + // value, the same type as the pointer type for the system, and an output + // chain. + STACKSAVE, + + // STACKRESTORE has two operands, an input chain and a pointer to restore to + // it returns an output chain. + STACKRESTORE, + + // CALLSEQ_START/CALLSEQ_END - These operators mark the beginning and end of + // a call sequence, and carry arbitrary information that target might want + // to know. The first operand is a chain, the rest are specified by the + // target and not touched by the DAG optimizers. + // CALLSEQ_START..CALLSEQ_END pairs may not be nested. + CALLSEQ_START, // Beginning of a call sequence + CALLSEQ_END, // End of a call sequence + + // VAARG - VAARG has three operands: an input chain, a pointer, and a + // SRCVALUE. It returns a pair of values: the vaarg value and a new chain. + VAARG, + + // VACOPY - VACOPY has five operands: an input chain, a destination pointer, + // a source pointer, a SRCVALUE for the destination, and a SRCVALUE for the + // source. + VACOPY, + + // VAEND, VASTART - VAEND and VASTART have three operands: an input chain, a + // pointer, and a SRCVALUE. + VAEND, VASTART, + + // SRCVALUE - This is a node type that holds a Value* that is used to + // make reference to a value in the LLVM IR. + SRCVALUE, + + // PCMARKER - This corresponds to the pcmarker intrinsic. + PCMARKER, + + // READCYCLECOUNTER - This corresponds to the readcyclecounter intrinsic. + // The only operand is a chain and a value and a chain are produced. The + // value is the contents of the architecture specific cycle counter like + // register (or other high accuracy low latency clock source) + READCYCLECOUNTER, + + // HANDLENODE node - Used as a handle for various purposes. + HANDLENODE, + + // TRAMPOLINE - This corresponds to the init_trampoline intrinsic. + // It takes as input a token chain, the pointer to the trampoline, + // the pointer to the nested function, the pointer to pass for the + // 'nest' parameter, a SRCVALUE for the trampoline and another for + // the nested function (allowing targets to access the original + // Function*). It produces the result of the intrinsic and a token + // chain as output. + TRAMPOLINE, + + // TRAP - Trapping instruction + TRAP, + + // PREFETCH - This corresponds to a prefetch intrinsic. It takes chains are + // their first operand. The other operands are the address to prefetch, + // read / write specifier, and locality specifier. + PREFETCH, + + // OUTCHAIN = MEMBARRIER(INCHAIN, load-load, load-store, store-load, + // store-store, device) + // This corresponds to the memory.barrier intrinsic. + // it takes an input chain, 4 operands to specify the type of barrier, an + // operand specifying if the barrier applies to device and uncached memory + // and produces an output chain. + MEMBARRIER, + + // Val, OUTCHAIN = ATOMIC_CMP_SWAP(INCHAIN, ptr, cmp, swap) + // this corresponds to the atomic.lcs intrinsic. + // 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, + + // 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) + // this corresponds to the atomic.load.[OpName] intrinsic. + // op(*ptr, amt) is stored to *ptr atomically. + // the return is always the original value in *ptr + ATOMIC_LOAD_ADD, + ATOMIC_LOAD_SUB, + ATOMIC_LOAD_AND, + ATOMIC_LOAD_OR, + ATOMIC_LOAD_XOR, + ATOMIC_LOAD_NAND, + ATOMIC_LOAD_MIN, + ATOMIC_LOAD_MAX, + ATOMIC_LOAD_UMIN, + ATOMIC_LOAD_UMAX, + + /// BUILTIN_OP_END - This must be the last enum value in this list. + /// The target-specific pre-isel opcode values start here. + BUILTIN_OP_END + }; + + /// FIRST_TARGET_MEMORY_OPCODE - Target-specific pre-isel operations + /// which do not reference a specific memory location should be less than + /// this value. Those that do must not be less than this value, and can + /// be used with SelectionDAG::getMemIntrinsicNode. + static const int FIRST_TARGET_MEMORY_OPCODE = 1 << 14; + + /// Node predicates + + /// isBuildVectorAllOnes - Return true if the specified node is a + /// BUILD_VECTOR where all of the elements are ~0 or undef. + bool isBuildVectorAllOnes(const SDNode *N); + + /// isBuildVectorAllZeros - Return true if the specified node is a + /// BUILD_VECTOR where all of the elements are 0 or undef. + bool isBuildVectorAllZeros(const SDNode *N); + + /// isScalarToVector - Return true if the specified node is a + /// ISD::SCALAR_TO_VECTOR node or a BUILD_VECTOR node where only the low + /// element is not an undef. + bool isScalarToVector(const SDNode *N); + + //===--------------------------------------------------------------------===// + /// MemIndexedMode enum - This enum defines the load / store indexed + /// addressing modes. + /// + /// UNINDEXED "Normal" load / store. The effective address is already + /// computed and is available in the base pointer. The offset + /// operand is always undefined. In addition to producing a + /// chain, an unindexed load produces one value (result of the + /// load); an unindexed store does not produce a value. + /// + /// PRE_INC Similar to the unindexed mode where the effective address is + /// PRE_DEC the value of the base pointer add / subtract the offset. + /// It considers the computation as being folded into the load / + /// store operation (i.e. the load / store does the address + /// computation as well as performing the memory transaction). + /// The base operand is always undefined. In addition to + /// producing a chain, pre-indexed load produces two values + /// (result of the load and the result of the address + /// computation); a pre-indexed store produces one value (result + /// of the address computation). + /// + /// POST_INC The effective address is the value of the base pointer. The + /// POST_DEC value of the offset operand is then added to / subtracted + /// from the base after memory transaction. In addition to + /// producing a chain, post-indexed load produces two values + /// (the result of the load and the result of the base +/- offset + /// computation); a post-indexed store produces one value (the + /// the result of the base +/- offset computation). + /// + enum MemIndexedMode { + UNINDEXED = 0, + PRE_INC, + PRE_DEC, + POST_INC, + POST_DEC, + LAST_INDEXED_MODE + }; + + //===--------------------------------------------------------------------===// + /// LoadExtType enum - This enum defines the three variants of LOADEXT + /// (load with extension). + /// + /// SEXTLOAD loads the integer operand and sign extends it to a larger + /// integer result type. + /// ZEXTLOAD loads the integer operand and zero extends it to a larger + /// integer result type. + /// EXTLOAD is used for three things: floating point extending loads, + /// integer extending loads [the top bits are undefined], and vector + /// extending loads [load into low elt]. + /// + enum LoadExtType { + NON_EXTLOAD = 0, + EXTLOAD, + SEXTLOAD, + ZEXTLOAD, + LAST_LOADEXT_TYPE + }; + + //===--------------------------------------------------------------------===// + /// ISD::CondCode enum - These are ordered carefully to make the bitfields + /// below work out, when considering SETFALSE (something that never exists + /// dynamically) as 0. "U" -> Unsigned (for integer operands) or Unordered + /// (for floating point), "L" -> Less than, "G" -> Greater than, "E" -> Equal + /// to. If the "N" column is 1, the result of the comparison is undefined if + /// the input is a NAN. + /// + /// All of these (except for the 'always folded ops') should be handled for + /// floating point. For integer, only the SETEQ,SETNE,SETLT,SETLE,SETGT, + /// SETGE,SETULT,SETULE,SETUGT, and SETUGE opcodes are used. + /// + /// Note that these are laid out in a specific order to allow bit-twiddling + /// to transform conditions. + enum CondCode { + // Opcode N U L G E Intuitive operation + SETFALSE, // 0 0 0 0 Always false (always folded) + SETOEQ, // 0 0 0 1 True if ordered and equal + SETOGT, // 0 0 1 0 True if ordered and greater than + SETOGE, // 0 0 1 1 True if ordered and greater than or equal + SETOLT, // 0 1 0 0 True if ordered and less than + SETOLE, // 0 1 0 1 True if ordered and less than or equal + SETONE, // 0 1 1 0 True if ordered and operands are unequal + SETO, // 0 1 1 1 True if ordered (no nans) + SETUO, // 1 0 0 0 True if unordered: isnan(X) | isnan(Y) + SETUEQ, // 1 0 0 1 True if unordered or equal + SETUGT, // 1 0 1 0 True if unordered or greater than + SETUGE, // 1 0 1 1 True if unordered, greater than, or equal + SETULT, // 1 1 0 0 True if unordered or less than + SETULE, // 1 1 0 1 True if unordered, less than, or equal + SETUNE, // 1 1 1 0 True if unordered or not equal + SETTRUE, // 1 1 1 1 Always true (always folded) + // Don't care operations: undefined if the input is a nan. + SETFALSE2, // 1 X 0 0 0 Always false (always folded) + SETEQ, // 1 X 0 0 1 True if equal + SETGT, // 1 X 0 1 0 True if greater than + SETGE, // 1 X 0 1 1 True if greater than or equal + SETLT, // 1 X 1 0 0 True if less than + SETLE, // 1 X 1 0 1 True if less than or equal + SETNE, // 1 X 1 1 0 True if not equal + SETTRUE2, // 1 X 1 1 1 Always true (always folded) + + SETCC_INVALID // Marker value. + }; + + /// isSignedIntSetCC - Return true if this is a setcc instruction that + /// performs a signed comparison when used with integer operands. + inline bool isSignedIntSetCC(CondCode Code) { + return Code == SETGT || Code == SETGE || Code == SETLT || Code == SETLE; + } + + /// isUnsignedIntSetCC - Return true if this is a setcc instruction that + /// performs an unsigned comparison when used with integer operands. + inline bool isUnsignedIntSetCC(CondCode Code) { + return Code == SETUGT || Code == SETUGE || Code == SETULT || Code == SETULE; + } + + /// isTrueWhenEqual - Return true if the specified condition returns true if + /// the two operands to the condition are equal. Note that if one of the two + /// operands is a NaN, this value is meaningless. + inline bool isTrueWhenEqual(CondCode Cond) { + return ((int)Cond & 1) != 0; + } + + /// getUnorderedFlavor - This function returns 0 if the condition is always + /// false if an operand is a NaN, 1 if the condition is always true if the + /// operand is a NaN, and 2 if the condition is undefined if the operand is a + /// NaN. + inline unsigned getUnorderedFlavor(CondCode Cond) { + return ((int)Cond >> 3) & 3; + } + + /// getSetCCInverse - Return the operation corresponding to !(X op Y), where + /// 'op' is a valid SetCC operation. + CondCode getSetCCInverse(CondCode Operation, bool isInteger); + + /// getSetCCSwappedOperands - Return the operation corresponding to (Y op X) + /// when given the operation for (X op Y). + CondCode getSetCCSwappedOperands(CondCode Operation); + + /// getSetCCOrOperation - Return the result of a logical OR between different + /// comparisons of identical values: ((X op1 Y) | (X op2 Y)). This + /// function returns SETCC_INVALID if it is not possible to represent the + /// resultant comparison. + CondCode getSetCCOrOperation(CondCode Op1, CondCode Op2, bool isInteger); + + /// getSetCCAndOperation - Return the result of a logical AND between + /// different comparisons of identical values: ((X op1 Y) & (X op2 Y)). This + /// function returns SETCC_INVALID if it is not possible to represent the + /// resultant comparison. + CondCode getSetCCAndOperation(CondCode Op1, CondCode Op2, bool isInteger); + + //===--------------------------------------------------------------------===// + /// CvtCode enum - This enum defines the various converts CONVERT_RNDSAT + /// supports. + enum CvtCode { + CVT_FF, // Float from Float + CVT_FS, // Float from Signed + CVT_FU, // Float from Unsigned + CVT_SF, // Signed from Float + CVT_UF, // Unsigned from Float + CVT_SS, // Signed from Signed + CVT_SU, // Signed from Unsigned + CVT_US, // Unsigned from Signed + CVT_UU, // Unsigned from Unsigned + CVT_INVALID // Marker - Invalid opcode + }; +} // end llvm::ISD namespace + + +//===----------------------------------------------------------------------===// +/// SDValue - Unlike LLVM values, Selection DAG nodes may return multiple +/// values as the result of a computation. Many nodes return multiple values, +/// from loads (which define a token and a return value) to ADDC (which returns +/// a result and a carry value), to calls (which may return an arbitrary number +/// of values). +/// +/// As such, each use of a SelectionDAG computation must indicate the node that +/// computes it as well as which return value to use from that node. This pair +/// of information is represented with the SDValue value type. +/// +class SDValue { + SDNode *Node; // The node defining the value we are using. + unsigned ResNo; // Which return value of the node we are using. +public: + SDValue() : Node(0), ResNo(0) {} + SDValue(SDNode *node, unsigned resno) : Node(node), ResNo(resno) {} + + /// get the index which selects a specific result in the SDNode + unsigned getResNo() const { return ResNo; } + + /// get the SDNode which holds the desired result + SDNode *getNode() const { return Node; } + + /// set the SDNode + void setNode(SDNode *N) { Node = N; } + + bool operator==(const SDValue &O) const { + return Node == O.Node && ResNo == O.ResNo; + } + bool operator!=(const SDValue &O) const { + return !operator==(O); + } + bool operator<(const SDValue &O) const { + return Node < O.Node || (Node == O.Node && ResNo < O.ResNo); + } + + SDValue getValue(unsigned R) const { + return SDValue(Node, R); + } + + // isOperandOf - Return true if this node is an operand of N. + bool isOperandOf(SDNode *N) const; + + /// getValueType - Return the ValueType of the referenced return value. + /// + inline EVT getValueType() const; + + /// getValueSizeInBits - Returns the size of the value in bits. + /// + unsigned getValueSizeInBits() const { + return getValueType().getSizeInBits(); + } + + // Forwarding methods - These forward to the corresponding methods in SDNode. + inline unsigned getOpcode() const; + inline unsigned getNumOperands() const; + inline const SDValue &getOperand(unsigned i) const; + inline uint64_t getConstantOperandVal(unsigned i) const; + inline bool isTargetMemoryOpcode() const; + inline bool isTargetOpcode() const; + inline bool isMachineOpcode() const; + inline unsigned getMachineOpcode() const; + inline const DebugLoc getDebugLoc() const; + + + /// reachesChainWithoutSideEffects - Return true if this operand (which must + /// be a chain) reaches the specified operand without crossing any + /// side-effecting instructions. In practice, this looks through token + /// factors and non-volatile loads. In order to remain efficient, this only + /// looks a couple of nodes in, it does not do an exhaustive search. + bool reachesChainWithoutSideEffects(SDValue Dest, + unsigned Depth = 2) const; + + /// use_empty - Return true if there are no nodes using value ResNo + /// of Node. + /// + inline bool use_empty() const; + + /// hasOneUse - Return true if there is exactly one node using value + /// ResNo of Node. + /// + inline bool hasOneUse() const; +}; + + +template<> struct DenseMapInfo { + static inline SDValue getEmptyKey() { + return SDValue((SDNode*)-1, -1U); + } + static inline SDValue getTombstoneKey() { + return SDValue((SDNode*)-1, 0); + } + static unsigned getHashValue(const SDValue &Val) { + return ((unsigned)((uintptr_t)Val.getNode() >> 4) ^ + (unsigned)((uintptr_t)Val.getNode() >> 9)) + Val.getResNo(); + } + static bool isEqual(const SDValue &LHS, const SDValue &RHS) { + return LHS == RHS; + } + static bool isPod() { return true; } +}; + +/// simplify_type specializations - Allow casting operators to work directly on +/// SDValues as if they were SDNode*'s. +template<> struct simplify_type { + typedef SDNode* SimpleType; + static SimpleType getSimplifiedValue(const SDValue &Val) { + return static_cast(Val.getNode()); + } +}; +template<> struct simplify_type { + typedef SDNode* SimpleType; + static SimpleType getSimplifiedValue(const SDValue &Val) { + return static_cast(Val.getNode()); + } +}; + +/// SDUse - Represents a use of a SDNode. This class holds an SDValue, +/// which records the SDNode being used and the result number, a +/// pointer to the SDNode using the value, and Next and Prev pointers, +/// which link together all the uses of an SDNode. +/// +class SDUse { + /// Val - The value being used. + SDValue Val; + /// User - The user of this value. + SDNode *User; + /// Prev, Next - Pointers to the uses list of the SDNode referred by + /// this operand. + SDUse **Prev, *Next; + + SDUse(const SDUse &U); // Do not implement + void operator=(const SDUse &U); // Do not implement + +public: + SDUse() : Val(), User(NULL), Prev(NULL), Next(NULL) {} + + /// Normally SDUse will just implicitly convert to an SDValue that it holds. + operator const SDValue&() const { return Val; } + + /// If implicit conversion to SDValue doesn't work, the get() method returns + /// the SDValue. + const SDValue &get() const { return Val; } + + /// getUser - This returns the SDNode that contains this Use. + SDNode *getUser() { return User; } + + /// getNext - Get the next SDUse in the use list. + SDUse *getNext() const { return Next; } + + /// getNode - Convenience function for get().getNode(). + SDNode *getNode() const { return Val.getNode(); } + /// getResNo - Convenience function for get().getResNo(). + unsigned getResNo() const { return Val.getResNo(); } + /// getValueType - Convenience function for get().getValueType(). + EVT getValueType() const { return Val.getValueType(); } + + /// operator== - Convenience function for get().operator== + bool operator==(const SDValue &V) const { + return Val == V; + } + + /// operator!= - Convenience function for get().operator!= + bool operator!=(const SDValue &V) const { + return Val != V; + } + + /// operator< - Convenience function for get().operator< + bool operator<(const SDValue &V) const { + return Val < V; + } + +private: + friend class SelectionDAG; + friend class SDNode; + + void setUser(SDNode *p) { User = p; } + + /// set - Remove this use from its existing use list, assign it the + /// given value, and add it to the new value's node's use list. + inline void set(const SDValue &V); + /// setInitial - like set, but only supports initializing a newly-allocated + /// SDUse with a non-null value. + inline void setInitial(const SDValue &V); + /// setNode - like set, but only sets the Node portion of the value, + /// leaving the ResNo portion unmodified. + inline void setNode(SDNode *N); + + void addToList(SDUse **List) { + Next = *List; + if (Next) Next->Prev = &Next; + Prev = List; + *List = this; + } + + void removeFromList() { + *Prev = Next; + if (Next) Next->Prev = Prev; + } +}; + +/// simplify_type specializations - Allow casting operators to work directly on +/// SDValues as if they were SDNode*'s. +template<> struct simplify_type { + typedef SDNode* SimpleType; + static SimpleType getSimplifiedValue(const SDUse &Val) { + return static_cast(Val.getNode()); + } +}; +template<> struct simplify_type { + typedef SDNode* SimpleType; + static SimpleType getSimplifiedValue(const SDUse &Val) { + return static_cast(Val.getNode()); + } +}; + + +/// SDNode - Represents one node in the SelectionDAG. +/// +class SDNode : public FoldingSetNode, public ilist_node { +private: + /// NodeType - The operation that this node performs. + /// + int16_t NodeType; + + /// OperandsNeedDelete - This is true if OperandList was new[]'d. If true, + /// then they will be delete[]'d when the node is destroyed. + uint16_t OperandsNeedDelete : 1; + +protected: + /// SubclassData - This member is defined by this class, but is not used for + /// anything. Subclasses can use it to hold whatever state they find useful. + /// This field is initialized to zero by the ctor. + uint16_t SubclassData : 15; + +private: + /// NodeId - Unique id per SDNode in the DAG. + int NodeId; + + /// OperandList - The values that are used by this operation. + /// + SDUse *OperandList; + + /// ValueList - The types of the values this node defines. SDNode's may + /// define multiple values simultaneously. + const EVT *ValueList; + + /// UseList - List of uses for this SDNode. + SDUse *UseList; + + /// NumOperands/NumValues - The number of entries in the Operand/Value list. + unsigned short NumOperands, NumValues; + + /// debugLoc - source line information. + DebugLoc debugLoc; + + /// getValueTypeList - Return a pointer to the specified value type. + static const EVT *getValueTypeList(EVT VT); + + friend class SelectionDAG; + friend struct ilist_traits; + +public: + //===--------------------------------------------------------------------===// + // Accessors + // + + /// getOpcode - Return the SelectionDAG opcode value for this node. For + /// pre-isel nodes (those for which isMachineOpcode returns false), these + /// are the opcode values in the ISD and ISD namespaces. For + /// post-isel opcodes, see getMachineOpcode. + unsigned getOpcode() const { return (unsigned short)NodeType; } + + /// isTargetOpcode - Test if this node has a target-specific opcode (in the + /// \ISD namespace). + bool isTargetOpcode() const { return NodeType >= ISD::BUILTIN_OP_END; } + + /// isTargetMemoryOpcode - Test if this node has a target-specific + /// memory-referencing opcode (in the \ISD namespace and + /// greater than FIRST_TARGET_MEMORY_OPCODE). + bool isTargetMemoryOpcode() const { + return NodeType >= ISD::FIRST_TARGET_MEMORY_OPCODE; + } + + /// isMachineOpcode - Test if this node has a post-isel opcode, directly + /// corresponding to a MachineInstr opcode. + bool isMachineOpcode() const { return NodeType < 0; } + + /// getMachineOpcode - This may only be called if isMachineOpcode returns + /// true. It returns the MachineInstr opcode value that the node's opcode + /// corresponds to. + unsigned getMachineOpcode() const { + assert(isMachineOpcode() && "Not a MachineInstr opcode!"); + return ~NodeType; + } + + /// use_empty - Return true if there are no uses of this node. + /// + bool use_empty() const { return UseList == NULL; } + + /// hasOneUse - Return true if there is exactly one use of this node. + /// + bool hasOneUse() const { + return !use_empty() && next(use_begin()) == use_end(); + } + + /// use_size - Return the number of uses of this node. This method takes + /// time proportional to the number of uses. + /// + size_t use_size() const { return std::distance(use_begin(), use_end()); } + + /// getNodeId - Return the unique node id. + /// + int getNodeId() const { return NodeId; } + + /// setNodeId - Set unique node id. + void setNodeId(int Id) { NodeId = Id; } + + /// getDebugLoc - Return the source location info. + const DebugLoc getDebugLoc() const { return debugLoc; } + + /// setDebugLoc - Set source location info. Try to avoid this, putting + /// it in the constructor is preferable. + void setDebugLoc(const DebugLoc dl) { debugLoc = dl; } + + /// use_iterator - This class provides iterator support for SDUse + /// operands that use a specific SDNode. + class use_iterator + : public std::iterator { + SDUse *Op; + explicit use_iterator(SDUse *op) : Op(op) { + } + friend class SDNode; + public: + typedef std::iterator::reference reference; + typedef std::iterator::pointer pointer; + + use_iterator(const use_iterator &I) : Op(I.Op) {} + use_iterator() : Op(0) {} + + bool operator==(const use_iterator &x) const { + return Op == x.Op; + } + bool operator!=(const use_iterator &x) const { + return !operator==(x); + } + + /// atEnd - return true if this iterator is at the end of uses list. + bool atEnd() const { return Op == 0; } + + // Iterator traversal: forward iteration only. + use_iterator &operator++() { // Preincrement + assert(Op && "Cannot increment end iterator!"); + Op = Op->getNext(); + return *this; + } + + use_iterator operator++(int) { // Postincrement + use_iterator tmp = *this; ++*this; return tmp; + } + + /// Retrieve a pointer to the current user node. + SDNode *operator*() const { + assert(Op && "Cannot dereference end iterator!"); + return Op->getUser(); + } + + SDNode *operator->() const { return operator*(); } + + SDUse &getUse() const { return *Op; } + + /// getOperandNo - Retrieve the operand # of this use in its user. + /// + unsigned getOperandNo() const { + assert(Op && "Cannot dereference end iterator!"); + return (unsigned)(Op - Op->getUser()->OperandList); + } + }; + + /// use_begin/use_end - Provide iteration support to walk over all uses + /// of an SDNode. + + use_iterator use_begin() const { + return use_iterator(UseList); + } + + static use_iterator use_end() { return use_iterator(0); } + + + /// hasNUsesOfValue - Return true if there are exactly NUSES uses of the + /// indicated value. This method ignores uses of other values defined by this + /// operation. + bool hasNUsesOfValue(unsigned NUses, unsigned Value) const; + + /// hasAnyUseOfValue - Return true if there are any use of the indicated + /// value. This method ignores uses of other values defined by this operation. + bool hasAnyUseOfValue(unsigned Value) const; + + /// isOnlyUserOf - Return true if this node is the only use of N. + /// + bool isOnlyUserOf(SDNode *N) const; + + /// isOperandOf - Return true if this node is an operand of N. + /// + bool isOperandOf(SDNode *N) const; + + /// isPredecessorOf - Return true if this node is a predecessor of N. This + /// node is either an operand of N or it can be reached by recursively + /// traversing up the operands. + /// NOTE: this is an expensive method. Use it carefully. + bool isPredecessorOf(SDNode *N) const; + + /// getNumOperands - Return the number of values used by this operation. + /// + unsigned getNumOperands() const { return NumOperands; } + + /// getConstantOperandVal - Helper method returns the integer value of a + /// ConstantSDNode operand. + uint64_t getConstantOperandVal(unsigned Num) const; + + const SDValue &getOperand(unsigned Num) const { + assert(Num < NumOperands && "Invalid child # of SDNode!"); + return OperandList[Num]; + } + + typedef SDUse* op_iterator; + op_iterator op_begin() const { return OperandList; } + op_iterator op_end() const { return OperandList+NumOperands; } + + SDVTList getVTList() const { + SDVTList X = { ValueList, NumValues }; + return X; + }; + + /// getFlaggedNode - If this node has a flag operand, return the node + /// to which the flag operand points. Otherwise return NULL. + SDNode *getFlaggedNode() const { + if (getNumOperands() != 0 && + getOperand(getNumOperands()-1).getValueType().getSimpleVT() == MVT::Flag) + return getOperand(getNumOperands()-1).getNode(); + return 0; + } + + // If this is a pseudo op, like copyfromreg, look to see if there is a + // real target node flagged to it. If so, return the target node. + const SDNode *getFlaggedMachineNode() const { + const SDNode *FoundNode = this; + + // Climb up flag edges until a machine-opcode node is found, or the + // end of the chain is reached. + while (!FoundNode->isMachineOpcode()) { + const SDNode *N = FoundNode->getFlaggedNode(); + if (!N) break; + FoundNode = N; + } + + return FoundNode; + } + + /// getNumValues - Return the number of values defined/returned by this + /// operator. + /// + unsigned getNumValues() const { return NumValues; } + + /// getValueType - Return the type of a specified result. + /// + EVT getValueType(unsigned ResNo) const { + assert(ResNo < NumValues && "Illegal result number!"); + return ValueList[ResNo]; + } + + /// getValueSizeInBits - Returns MVT::getSizeInBits(getValueType(ResNo)). + /// + unsigned getValueSizeInBits(unsigned ResNo) const { + return getValueType(ResNo).getSizeInBits(); + } + + typedef const EVT* value_iterator; + value_iterator value_begin() const { return ValueList; } + value_iterator value_end() const { return ValueList+NumValues; } + + /// getOperationName - Return the opcode of this operation for printing. + /// + std::string getOperationName(const SelectionDAG *G = 0) const; + static const char* getIndexedModeName(ISD::MemIndexedMode AM); + void print_types(raw_ostream &OS, const SelectionDAG *G) const; + void print_details(raw_ostream &OS, const SelectionDAG *G) const; + void print(raw_ostream &OS, const SelectionDAG *G = 0) const; + void printr(raw_ostream &OS, const SelectionDAG *G = 0) const; + void dump() const; + void dumpr() const; + void dump(const SelectionDAG *G) const; + void dumpr(const SelectionDAG *G) const; + + static bool classof(const SDNode *) { return true; } + + /// Profile - Gather unique data for the node. + /// + void Profile(FoldingSetNodeID &ID) const; + + /// addUse - This method should only be used by the SDUse class. + /// + void addUse(SDUse &U) { U.addToList(&UseList); } + +protected: + static SDVTList getSDVTList(EVT VT) { + SDVTList Ret = { getValueTypeList(VT), 1 }; + return Ret; + } + + SDNode(unsigned Opc, const DebugLoc dl, SDVTList VTs, const SDValue *Ops, + unsigned NumOps) + : NodeType(Opc), OperandsNeedDelete(true), SubclassData(0), + NodeId(-1), + OperandList(NumOps ? new SDUse[NumOps] : 0), + ValueList(VTs.VTs), UseList(NULL), + NumOperands(NumOps), NumValues(VTs.NumVTs), + debugLoc(dl) { + for (unsigned i = 0; i != NumOps; ++i) { + OperandList[i].setUser(this); + OperandList[i].setInitial(Ops[i]); + } + } + + /// This constructor adds no operands itself; operands can be + /// set later with InitOperands. + SDNode(unsigned Opc, const DebugLoc dl, SDVTList VTs) + : NodeType(Opc), OperandsNeedDelete(false), SubclassData(0), + NodeId(-1), OperandList(0), ValueList(VTs.VTs), UseList(NULL), + NumOperands(0), NumValues(VTs.NumVTs), + debugLoc(dl) {} + + /// InitOperands - Initialize the operands list of this with 1 operand. + void InitOperands(SDUse *Ops, const SDValue &Op0) { + Ops[0].setUser(this); + Ops[0].setInitial(Op0); + NumOperands = 1; + OperandList = Ops; + } + + /// InitOperands - Initialize the operands list of this with 2 operands. + void InitOperands(SDUse *Ops, const SDValue &Op0, const SDValue &Op1) { + Ops[0].setUser(this); + Ops[0].setInitial(Op0); + Ops[1].setUser(this); + Ops[1].setInitial(Op1); + NumOperands = 2; + OperandList = Ops; + } + + /// InitOperands - Initialize the operands list of this with 3 operands. + void InitOperands(SDUse *Ops, const SDValue &Op0, const SDValue &Op1, + const SDValue &Op2) { + Ops[0].setUser(this); + Ops[0].setInitial(Op0); + Ops[1].setUser(this); + Ops[1].setInitial(Op1); + Ops[2].setUser(this); + Ops[2].setInitial(Op2); + NumOperands = 3; + OperandList = Ops; + } + + /// InitOperands - Initialize the operands list of this with 4 operands. + void InitOperands(SDUse *Ops, const SDValue &Op0, const SDValue &Op1, + const SDValue &Op2, const SDValue &Op3) { + Ops[0].setUser(this); + Ops[0].setInitial(Op0); + Ops[1].setUser(this); + Ops[1].setInitial(Op1); + Ops[2].setUser(this); + Ops[2].setInitial(Op2); + Ops[3].setUser(this); + Ops[3].setInitial(Op3); + NumOperands = 4; + OperandList = Ops; + } + + /// InitOperands - Initialize the operands list of this with N operands. + void InitOperands(SDUse *Ops, const SDValue *Vals, unsigned N) { + for (unsigned i = 0; i != N; ++i) { + Ops[i].setUser(this); + Ops[i].setInitial(Vals[i]); + } + NumOperands = N; + OperandList = Ops; + } + + /// DropOperands - Release the operands and set this node to have + /// zero operands. + void DropOperands(); +}; + + +// Define inline functions from the SDValue class. + +inline unsigned SDValue::getOpcode() const { + return Node->getOpcode(); +} +inline EVT SDValue::getValueType() const { + return Node->getValueType(ResNo); +} +inline unsigned SDValue::getNumOperands() const { + return Node->getNumOperands(); +} +inline const SDValue &SDValue::getOperand(unsigned i) const { + return Node->getOperand(i); +} +inline uint64_t SDValue::getConstantOperandVal(unsigned i) const { + return Node->getConstantOperandVal(i); +} +inline bool SDValue::isTargetOpcode() const { + return Node->isTargetOpcode(); +} +inline bool SDValue::isTargetMemoryOpcode() const { + return Node->isTargetMemoryOpcode(); +} +inline bool SDValue::isMachineOpcode() const { + return Node->isMachineOpcode(); +} +inline unsigned SDValue::getMachineOpcode() const { + return Node->getMachineOpcode(); +} +inline bool SDValue::use_empty() const { + return !Node->hasAnyUseOfValue(ResNo); +} +inline bool SDValue::hasOneUse() const { + return Node->hasNUsesOfValue(1, ResNo); +} +inline const DebugLoc SDValue::getDebugLoc() const { + return Node->getDebugLoc(); +} + +// Define inline functions from the SDUse class. + +inline void SDUse::set(const SDValue &V) { + if (Val.getNode()) removeFromList(); + Val = V; + if (V.getNode()) V.getNode()->addUse(*this); +} + +inline void SDUse::setInitial(const SDValue &V) { + Val = V; + V.getNode()->addUse(*this); +} + +inline void SDUse::setNode(SDNode *N) { + if (Val.getNode()) removeFromList(); + Val.setNode(N); + if (N) N->addUse(*this); +} + +/// UnarySDNode - This class is used for single-operand SDNodes. This is solely +/// to allow co-allocation of node operands with the node itself. +class UnarySDNode : public SDNode { + SDUse Op; +public: + UnarySDNode(unsigned Opc, DebugLoc dl, SDVTList VTs, SDValue X) + : SDNode(Opc, dl, VTs) { + InitOperands(&Op, X); + } +}; + +/// BinarySDNode - This class is used for two-operand SDNodes. This is solely +/// to allow co-allocation of node operands with the node itself. +class BinarySDNode : public SDNode { + SDUse Ops[2]; +public: + BinarySDNode(unsigned Opc, DebugLoc dl, SDVTList VTs, SDValue X, SDValue Y) + : SDNode(Opc, dl, VTs) { + InitOperands(Ops, X, Y); + } +}; + +/// TernarySDNode - This class is used for three-operand SDNodes. This is solely +/// to allow co-allocation of node operands with the node itself. +class TernarySDNode : public SDNode { + SDUse Ops[3]; +public: + TernarySDNode(unsigned Opc, DebugLoc dl, SDVTList VTs, SDValue X, SDValue Y, + SDValue Z) + : SDNode(Opc, dl, VTs) { + InitOperands(Ops, X, Y, Z); + } +}; + + +/// HandleSDNode - This class is used to form a handle around another node that +/// is persistant and is updated across invocations of replaceAllUsesWith on its +/// operand. This node should be directly created by end-users and not added to +/// the AllNodes list. +class HandleSDNode : public SDNode { + SDUse Op; +public: + // FIXME: Remove the "noinline" attribute once is + // fixed. +#ifdef __GNUC__ + explicit __attribute__((__noinline__)) HandleSDNode(SDValue X) +#else + explicit HandleSDNode(SDValue X) +#endif + : SDNode(ISD::HANDLENODE, DebugLoc::getUnknownLoc(), + getSDVTList(MVT::Other)) { + InitOperands(&Op, X); + } + ~HandleSDNode(); + const SDValue &getValue() const { return Op; } +}; + +/// Abstact virtual class for operations for memory operations +class MemSDNode : public SDNode { +private: + // MemoryVT - VT of in-memory value. + EVT MemoryVT; + +protected: + /// MMO - Memory reference information. + MachineMemOperand *MMO; + +public: + MemSDNode(unsigned Opc, DebugLoc dl, SDVTList VTs, EVT MemoryVT, + MachineMemOperand *MMO); + + MemSDNode(unsigned Opc, DebugLoc dl, SDVTList VTs, const SDValue *Ops, + unsigned NumOps, EVT MemoryVT, MachineMemOperand *MMO); + + bool readMem() const { return MMO->isLoad(); } + bool writeMem() const { return MMO->isStore(); } + + /// Returns alignment and volatility of the memory access + unsigned getOriginalAlignment() const { + return MMO->getBaseAlignment(); + } + unsigned getAlignment() const { + return MMO->getAlignment(); + } + + /// getRawSubclassData - Return the SubclassData value, which contains an + /// encoding of the volatile flag, as well as bits used by subclasses. This + /// function should only be used to compute a FoldingSetNodeID value. + unsigned getRawSubclassData() const { + return SubclassData; + } + + bool isVolatile() const { return (SubclassData >> 5) & 1; } + + /// Returns the SrcValue and offset that describes the location of the access + const Value *getSrcValue() const { return MMO->getValue(); } + int64_t getSrcValueOffset() const { return MMO->getOffset(); } + + /// getMemoryVT - Return the type of the in-memory value. + EVT getMemoryVT() const { return MemoryVT; } + + /// getMemOperand - Return a MachineMemOperand object describing the memory + /// reference performed by operation. + MachineMemOperand *getMemOperand() const { return MMO; } + + /// refineAlignment - Update this MemSDNode's MachineMemOperand information + /// to reflect the alignment of NewMMO, if it has a greater alignment. + /// This must only be used when the new alignment applies to all users of + /// this MachineMemOperand. + void refineAlignment(const MachineMemOperand *NewMMO) { + MMO->refineAlignment(NewMMO); + } + + const SDValue &getChain() const { return getOperand(0); } + const SDValue &getBasePtr() const { + return getOperand(getOpcode() == ISD::STORE ? 2 : 1); + } + + // Methods to support isa and dyn_cast + static bool classof(const MemSDNode *) { return true; } + static bool classof(const SDNode *N) { + // For some targets, we lower some target intrinsics to a MemIntrinsicNode + // with either an intrinsic or a target opcode. + return N->getOpcode() == ISD::LOAD || + N->getOpcode() == ISD::STORE || + N->getOpcode() == ISD::ATOMIC_CMP_SWAP || + N->getOpcode() == ISD::ATOMIC_SWAP || + N->getOpcode() == ISD::ATOMIC_LOAD_ADD || + N->getOpcode() == ISD::ATOMIC_LOAD_SUB || + N->getOpcode() == ISD::ATOMIC_LOAD_AND || + N->getOpcode() == ISD::ATOMIC_LOAD_OR || + N->getOpcode() == ISD::ATOMIC_LOAD_XOR || + N->getOpcode() == ISD::ATOMIC_LOAD_NAND || + N->getOpcode() == ISD::ATOMIC_LOAD_MIN || + N->getOpcode() == ISD::ATOMIC_LOAD_MAX || + N->getOpcode() == ISD::ATOMIC_LOAD_UMIN || + N->getOpcode() == ISD::ATOMIC_LOAD_UMAX || + N->isTargetMemoryOpcode(); + } +}; + +/// AtomicSDNode - A SDNode reprenting atomic operations. +/// +class AtomicSDNode : public MemSDNode { + SDUse Ops[4]; + +public: + // Opc: opcode for atomic + // VTL: value type list + // Chain: memory chain for operaand + // Ptr: address to update as a SDValue + // Cmp: compare value + // Swp: swap value + // SrcVal: address to update as a Value (used for MemOperand) + // Align: alignment of memory + AtomicSDNode(unsigned Opc, DebugLoc dl, SDVTList VTL, EVT MemVT, + SDValue Chain, SDValue Ptr, + SDValue Cmp, SDValue Swp, MachineMemOperand *MMO) + : MemSDNode(Opc, dl, VTL, MemVT, MMO) { + assert(readMem() && "Atomic MachineMemOperand is not a load!"); + assert(writeMem() && "Atomic MachineMemOperand is not a store!"); + InitOperands(Ops, Chain, Ptr, Cmp, Swp); + } + AtomicSDNode(unsigned Opc, DebugLoc dl, SDVTList VTL, EVT MemVT, + SDValue Chain, SDValue Ptr, + SDValue Val, MachineMemOperand *MMO) + : MemSDNode(Opc, dl, VTL, MemVT, MMO) { + assert(readMem() && "Atomic MachineMemOperand is not a load!"); + assert(writeMem() && "Atomic MachineMemOperand is not a store!"); + InitOperands(Ops, Chain, Ptr, Val); + } + + const SDValue &getBasePtr() const { return getOperand(1); } + const SDValue &getVal() const { return getOperand(2); } + + bool isCompareAndSwap() const { + unsigned Op = getOpcode(); + return Op == ISD::ATOMIC_CMP_SWAP; + } + + // Methods to support isa and dyn_cast + static bool classof(const AtomicSDNode *) { return true; } + static bool classof(const SDNode *N) { + return N->getOpcode() == ISD::ATOMIC_CMP_SWAP || + N->getOpcode() == ISD::ATOMIC_SWAP || + N->getOpcode() == ISD::ATOMIC_LOAD_ADD || + N->getOpcode() == ISD::ATOMIC_LOAD_SUB || + N->getOpcode() == ISD::ATOMIC_LOAD_AND || + N->getOpcode() == ISD::ATOMIC_LOAD_OR || + N->getOpcode() == ISD::ATOMIC_LOAD_XOR || + N->getOpcode() == ISD::ATOMIC_LOAD_NAND || + N->getOpcode() == ISD::ATOMIC_LOAD_MIN || + N->getOpcode() == ISD::ATOMIC_LOAD_MAX || + N->getOpcode() == ISD::ATOMIC_LOAD_UMIN || + N->getOpcode() == ISD::ATOMIC_LOAD_UMAX; + } +}; + +/// MemIntrinsicSDNode - This SDNode is used for target intrinsics that touch +/// memory and need an associated MachineMemOperand. Its opcode may be +/// INTRINSIC_VOID, INTRINSIC_W_CHAIN, or a target-specific opcode with a +/// value not less than FIRST_TARGET_MEMORY_OPCODE. +class MemIntrinsicSDNode : public MemSDNode { +public: + MemIntrinsicSDNode(unsigned Opc, DebugLoc dl, SDVTList VTs, + const SDValue *Ops, unsigned NumOps, + EVT MemoryVT, MachineMemOperand *MMO) + : MemSDNode(Opc, dl, VTs, Ops, NumOps, MemoryVT, MMO) { + } + + // Methods to support isa and dyn_cast + static bool classof(const MemIntrinsicSDNode *) { return true; } + static bool classof(const SDNode *N) { + // We lower some target intrinsics to their target opcode + // early a node with a target opcode can be of this class + return N->getOpcode() == ISD::INTRINSIC_W_CHAIN || + N->getOpcode() == ISD::INTRINSIC_VOID || + N->isTargetMemoryOpcode(); + } +}; + +/// ShuffleVectorSDNode - This SDNode is used to implement the code generator +/// support for the llvm IR shufflevector instruction. It combines elements +/// from two input vectors into a new input vector, with the selection and +/// ordering of elements determined by an array of integers, referred to as +/// the shuffle mask. For input vectors of width N, mask indices of 0..N-1 +/// refer to elements from the LHS input, and indices from N to 2N-1 the RHS. +/// An index of -1 is treated as undef, such that the code generator may put +/// any value in the corresponding element of the result. +class ShuffleVectorSDNode : public SDNode { + SDUse Ops[2]; + + // The memory for Mask is owned by the SelectionDAG's OperandAllocator, and + // is freed when the SelectionDAG object is destroyed. + const int *Mask; +protected: + friend class SelectionDAG; + ShuffleVectorSDNode(EVT VT, DebugLoc dl, SDValue N1, SDValue N2, + const int *M) + : SDNode(ISD::VECTOR_SHUFFLE, dl, getSDVTList(VT)), Mask(M) { + InitOperands(Ops, N1, N2); + } +public: + + void getMask(SmallVectorImpl &M) const { + EVT VT = getValueType(0); + M.clear(); + for (unsigned i = 0, e = VT.getVectorNumElements(); i != e; ++i) + M.push_back(Mask[i]); + } + int getMaskElt(unsigned Idx) const { + assert(Idx < getValueType(0).getVectorNumElements() && "Idx out of range!"); + return Mask[Idx]; + } + + bool isSplat() const { return isSplatMask(Mask, getValueType(0)); } + int getSplatIndex() const { + assert(isSplat() && "Cannot get splat index for non-splat!"); + return Mask[0]; + } + static bool isSplatMask(const int *Mask, EVT VT); + + static bool classof(const ShuffleVectorSDNode *) { return true; } + static bool classof(const SDNode *N) { + return N->getOpcode() == ISD::VECTOR_SHUFFLE; + } +}; + +class ConstantSDNode : public SDNode { + const ConstantInt *Value; + friend class SelectionDAG; + ConstantSDNode(bool isTarget, const ConstantInt *val, EVT VT) + : SDNode(isTarget ? ISD::TargetConstant : ISD::Constant, + DebugLoc::getUnknownLoc(), getSDVTList(VT)), Value(val) { + } +public: + + const ConstantInt *getConstantIntValue() const { return Value; } + const APInt &getAPIntValue() const { return Value->getValue(); } + uint64_t getZExtValue() const { return Value->getZExtValue(); } + int64_t getSExtValue() const { return Value->getSExtValue(); } + + bool isNullValue() const { return Value->isNullValue(); } + bool isAllOnesValue() const { return Value->isAllOnesValue(); } + + static bool classof(const ConstantSDNode *) { return true; } + static bool classof(const SDNode *N) { + return N->getOpcode() == ISD::Constant || + N->getOpcode() == ISD::TargetConstant; + } +}; + +class ConstantFPSDNode : public SDNode { + const ConstantFP *Value; + friend class SelectionDAG; + ConstantFPSDNode(bool isTarget, const ConstantFP *val, EVT VT) + : SDNode(isTarget ? ISD::TargetConstantFP : ISD::ConstantFP, + DebugLoc::getUnknownLoc(), getSDVTList(VT)), Value(val) { + } +public: + + const APFloat& getValueAPF() const { return Value->getValueAPF(); } + const ConstantFP *getConstantFPValue() const { return Value; } + + /// isExactlyValue - We don't rely on operator== working on double values, as + /// it returns true for things that are clearly not equal, like -0.0 and 0.0. + /// As such, this method can be used to do an exact bit-for-bit comparison of + /// two floating point values. + + /// We leave the version with the double argument here because it's just so + /// convenient to write "2.0" and the like. Without this function we'd + /// have to duplicate its logic everywhere it's called. + bool isExactlyValue(double V) const { + bool ignored; + // convert is not supported on this type + if (&Value->getValueAPF().getSemantics() == &APFloat::PPCDoubleDouble) + return false; + APFloat Tmp(V); + Tmp.convert(Value->getValueAPF().getSemantics(), + APFloat::rmNearestTiesToEven, &ignored); + return isExactlyValue(Tmp); + } + bool isExactlyValue(const APFloat& V) const; + + bool isValueValidForType(EVT VT, const APFloat& Val); + + static bool classof(const ConstantFPSDNode *) { return true; } + static bool classof(const SDNode *N) { + return N->getOpcode() == ISD::ConstantFP || + N->getOpcode() == ISD::TargetConstantFP; + } +}; + +class GlobalAddressSDNode : public SDNode { + GlobalValue *TheGlobal; + int64_t Offset; + unsigned char TargetFlags; + friend class SelectionDAG; + GlobalAddressSDNode(unsigned Opc, const GlobalValue *GA, EVT VT, + int64_t o, unsigned char TargetFlags); +public: + + GlobalValue *getGlobal() const { return TheGlobal; } + int64_t getOffset() const { return Offset; } + unsigned char getTargetFlags() const { return TargetFlags; } + // Return the address space this GlobalAddress belongs to. + unsigned getAddressSpace() const; + + static bool classof(const GlobalAddressSDNode *) { return true; } + static bool classof(const SDNode *N) { + return N->getOpcode() == ISD::GlobalAddress || + N->getOpcode() == ISD::TargetGlobalAddress || + N->getOpcode() == ISD::GlobalTLSAddress || + N->getOpcode() == ISD::TargetGlobalTLSAddress; + } +}; + +class FrameIndexSDNode : public SDNode { + int FI; + friend class SelectionDAG; + FrameIndexSDNode(int fi, EVT VT, bool isTarg) + : SDNode(isTarg ? ISD::TargetFrameIndex : ISD::FrameIndex, + DebugLoc::getUnknownLoc(), getSDVTList(VT)), FI(fi) { + } +public: + + int getIndex() const { return FI; } + + static bool classof(const FrameIndexSDNode *) { return true; } + static bool classof(const SDNode *N) { + return N->getOpcode() == ISD::FrameIndex || + N->getOpcode() == ISD::TargetFrameIndex; + } +}; + +class JumpTableSDNode : public SDNode { + int JTI; + unsigned char TargetFlags; + friend class SelectionDAG; + JumpTableSDNode(int jti, EVT VT, bool isTarg, unsigned char TF) + : SDNode(isTarg ? ISD::TargetJumpTable : ISD::JumpTable, + DebugLoc::getUnknownLoc(), getSDVTList(VT)), JTI(jti), TargetFlags(TF) { + } +public: + + int getIndex() const { return JTI; } + unsigned char getTargetFlags() const { return TargetFlags; } + + static bool classof(const JumpTableSDNode *) { return true; } + static bool classof(const SDNode *N) { + return N->getOpcode() == ISD::JumpTable || + N->getOpcode() == ISD::TargetJumpTable; + } +}; + +class ConstantPoolSDNode : public SDNode { + union { + Constant *ConstVal; + MachineConstantPoolValue *MachineCPVal; + } Val; + int Offset; // It's a MachineConstantPoolValue if top bit is set. + unsigned Alignment; // Minimum alignment requirement of CP (not log2 value). + unsigned char TargetFlags; + friend class SelectionDAG; + ConstantPoolSDNode(bool isTarget, Constant *c, EVT VT, int o, unsigned Align, + unsigned char TF) + : SDNode(isTarget ? ISD::TargetConstantPool : ISD::ConstantPool, + DebugLoc::getUnknownLoc(), + getSDVTList(VT)), Offset(o), Alignment(Align), TargetFlags(TF) { + assert((int)Offset >= 0 && "Offset is too large"); + Val.ConstVal = c; + } + ConstantPoolSDNode(bool isTarget, MachineConstantPoolValue *v, + EVT VT, int o, unsigned Align, unsigned char TF) + : SDNode(isTarget ? ISD::TargetConstantPool : ISD::ConstantPool, + DebugLoc::getUnknownLoc(), + getSDVTList(VT)), Offset(o), Alignment(Align), TargetFlags(TF) { + assert((int)Offset >= 0 && "Offset is too large"); + Val.MachineCPVal = v; + Offset |= 1 << (sizeof(unsigned)*CHAR_BIT-1); + } +public: + + + bool isMachineConstantPoolEntry() const { + return (int)Offset < 0; + } + + Constant *getConstVal() const { + assert(!isMachineConstantPoolEntry() && "Wrong constantpool type"); + return Val.ConstVal; + } + + MachineConstantPoolValue *getMachineCPVal() const { + assert(isMachineConstantPoolEntry() && "Wrong constantpool type"); + return Val.MachineCPVal; + } + + int getOffset() const { + return Offset & ~(1 << (sizeof(unsigned)*CHAR_BIT-1)); + } + + // Return the alignment of this constant pool object, which is either 0 (for + // default alignment) or the desired value. + unsigned getAlignment() const { return Alignment; } + unsigned char getTargetFlags() const { return TargetFlags; } + + const Type *getType() const; + + static bool classof(const ConstantPoolSDNode *) { return true; } + static bool classof(const SDNode *N) { + return N->getOpcode() == ISD::ConstantPool || + N->getOpcode() == ISD::TargetConstantPool; + } +}; + +class BasicBlockSDNode : public SDNode { + MachineBasicBlock *MBB; + friend class SelectionDAG; + /// Debug info is meaningful and potentially useful here, but we create + /// blocks out of order when they're jumped to, which makes it a bit + /// harder. Let's see if we need it first. + explicit BasicBlockSDNode(MachineBasicBlock *mbb) + : SDNode(ISD::BasicBlock, DebugLoc::getUnknownLoc(), + getSDVTList(MVT::Other)), MBB(mbb) { + } +public: + + MachineBasicBlock *getBasicBlock() const { return MBB; } + + static bool classof(const BasicBlockSDNode *) { return true; } + static bool classof(const SDNode *N) { + return N->getOpcode() == ISD::BasicBlock; + } +}; + +/// BuildVectorSDNode - A "pseudo-class" with methods for operating on +/// BUILD_VECTORs. +class BuildVectorSDNode : public SDNode { + // These are constructed as SDNodes and then cast to BuildVectorSDNodes. + explicit BuildVectorSDNode(); // Do not implement +public: + /// isConstantSplat - Check if this is a constant splat, and if so, find the + /// smallest element size that splats the vector. If MinSplatBits is + /// nonzero, the element size must be at least that large. Note that the + /// splat element may be the entire vector (i.e., a one element vector). + /// Returns the splat element value in SplatValue. Any undefined bits in + /// that value are zero, and the corresponding bits in the SplatUndef mask + /// are set. The SplatBitSize value is set to the splat element size in + /// bits. HasAnyUndefs is set to true if any bits in the vector are + /// undefined. isBigEndian describes the endianness of the target. + bool isConstantSplat(APInt &SplatValue, APInt &SplatUndef, + unsigned &SplatBitSize, bool &HasAnyUndefs, + unsigned MinSplatBits = 0, bool isBigEndian = false); + + static inline bool classof(const BuildVectorSDNode *) { return true; } + static inline bool classof(const SDNode *N) { + return N->getOpcode() == ISD::BUILD_VECTOR; + } +}; + +/// SrcValueSDNode - An SDNode that holds an arbitrary LLVM IR Value. This is +/// used when the SelectionDAG needs to make a simple reference to something +/// in the LLVM IR representation. +/// +class SrcValueSDNode : public SDNode { + const Value *V; + friend class SelectionDAG; + /// Create a SrcValue for a general value. + explicit SrcValueSDNode(const Value *v) + : SDNode(ISD::SRCVALUE, DebugLoc::getUnknownLoc(), + getSDVTList(MVT::Other)), V(v) {} + +public: + /// getValue - return the contained Value. + const Value *getValue() const { return V; } + + static bool classof(const SrcValueSDNode *) { return true; } + static bool classof(const SDNode *N) { + return N->getOpcode() == ISD::SRCVALUE; + } +}; + + +class RegisterSDNode : public SDNode { + unsigned Reg; + friend class SelectionDAG; + RegisterSDNode(unsigned reg, EVT VT) + : SDNode(ISD::Register, DebugLoc::getUnknownLoc(), + getSDVTList(VT)), Reg(reg) { + } +public: + + unsigned getReg() const { return Reg; } + + static bool classof(const RegisterSDNode *) { return true; } + static bool classof(const SDNode *N) { + return N->getOpcode() == ISD::Register; + } +}; + +class BlockAddressSDNode : public SDNode { + BlockAddress *BA; + unsigned char TargetFlags; + friend class SelectionDAG; + BlockAddressSDNode(unsigned NodeTy, EVT VT, BlockAddress *ba, + unsigned char Flags) + : SDNode(NodeTy, DebugLoc::getUnknownLoc(), getSDVTList(VT)), + BA(ba), TargetFlags(Flags) { + } +public: + BlockAddress *getBlockAddress() const { return BA; } + unsigned char getTargetFlags() const { return TargetFlags; } + + static bool classof(const BlockAddressSDNode *) { return true; } + static bool classof(const SDNode *N) { + return N->getOpcode() == ISD::BlockAddress || + N->getOpcode() == ISD::TargetBlockAddress; + } +}; + +class LabelSDNode : public SDNode { + SDUse Chain; + unsigned LabelID; + friend class SelectionDAG; + LabelSDNode(unsigned NodeTy, DebugLoc dl, SDValue ch, unsigned id) + : SDNode(NodeTy, dl, getSDVTList(MVT::Other)), LabelID(id) { + InitOperands(&Chain, ch); + } +public: + unsigned getLabelID() const { return LabelID; } + + static bool classof(const LabelSDNode *) { return true; } + static bool classof(const SDNode *N) { + return N->getOpcode() == ISD::EH_LABEL; + } +}; + +class ExternalSymbolSDNode : public SDNode { + const char *Symbol; + unsigned char TargetFlags; + + friend class SelectionDAG; + ExternalSymbolSDNode(bool isTarget, const char *Sym, unsigned char TF, EVT VT) + : SDNode(isTarget ? ISD::TargetExternalSymbol : ISD::ExternalSymbol, + DebugLoc::getUnknownLoc(), + getSDVTList(VT)), Symbol(Sym), TargetFlags(TF) { + } +public: + + const char *getSymbol() const { return Symbol; } + unsigned char getTargetFlags() const { return TargetFlags; } + + static bool classof(const ExternalSymbolSDNode *) { return true; } + static bool classof(const SDNode *N) { + return N->getOpcode() == ISD::ExternalSymbol || + N->getOpcode() == ISD::TargetExternalSymbol; + } +}; + +class CondCodeSDNode : public SDNode { + ISD::CondCode Condition; + friend class SelectionDAG; + explicit CondCodeSDNode(ISD::CondCode Cond) + : SDNode(ISD::CONDCODE, DebugLoc::getUnknownLoc(), + getSDVTList(MVT::Other)), Condition(Cond) { + } +public: + + ISD::CondCode get() const { return Condition; } + + static bool classof(const CondCodeSDNode *) { return true; } + static bool classof(const SDNode *N) { + return N->getOpcode() == ISD::CONDCODE; + } +}; + +/// CvtRndSatSDNode - NOTE: avoid using this node as this may disappear in the +/// future and most targets don't support it. +class CvtRndSatSDNode : public SDNode { + ISD::CvtCode CvtCode; + friend class SelectionDAG; + explicit CvtRndSatSDNode(EVT VT, DebugLoc dl, const SDValue *Ops, + unsigned NumOps, ISD::CvtCode Code) + : SDNode(ISD::CONVERT_RNDSAT, dl, getSDVTList(VT), Ops, NumOps), + CvtCode(Code) { + assert(NumOps == 5 && "wrong number of operations"); + } +public: + ISD::CvtCode getCvtCode() const { return CvtCode; } + + static bool classof(const CvtRndSatSDNode *) { return true; } + static bool classof(const SDNode *N) { + return N->getOpcode() == ISD::CONVERT_RNDSAT; + } +}; + +namespace ISD { + struct ArgFlagsTy { + private: + static const uint64_t NoFlagSet = 0ULL; + static const uint64_t ZExt = 1ULL<<0; ///< Zero extended + static const uint64_t ZExtOffs = 0; + static const uint64_t SExt = 1ULL<<1; ///< Sign extended + static const uint64_t SExtOffs = 1; + static const uint64_t InReg = 1ULL<<2; ///< Passed in register + static const uint64_t InRegOffs = 2; + static const uint64_t SRet = 1ULL<<3; ///< Hidden struct-ret ptr + static const uint64_t SRetOffs = 3; + static const uint64_t ByVal = 1ULL<<4; ///< Struct passed by value + static const uint64_t ByValOffs = 4; + static const uint64_t Nest = 1ULL<<5; ///< Nested fn static chain + static const uint64_t NestOffs = 5; + static const uint64_t ByValAlign = 0xFULL << 6; //< Struct alignment + static const uint64_t ByValAlignOffs = 6; + static const uint64_t Split = 1ULL << 10; + static const uint64_t SplitOffs = 10; + static const uint64_t OrigAlign = 0x1FULL<<27; + static const uint64_t OrigAlignOffs = 27; + static const uint64_t ByValSize = 0xffffffffULL << 32; //< Struct size + static const uint64_t ByValSizeOffs = 32; + + static const uint64_t One = 1ULL; //< 1 of this type, for shifts + + uint64_t Flags; + public: + ArgFlagsTy() : Flags(0) { } + + bool isZExt() const { return Flags & ZExt; } + void setZExt() { Flags |= One << ZExtOffs; } + + bool isSExt() const { return Flags & SExt; } + void setSExt() { Flags |= One << SExtOffs; } + + bool isInReg() const { return Flags & InReg; } + void setInReg() { Flags |= One << InRegOffs; } + + bool isSRet() const { return Flags & SRet; } + void setSRet() { Flags |= One << SRetOffs; } + + bool isByVal() const { return Flags & ByVal; } + void setByVal() { Flags |= One << ByValOffs; } + + bool isNest() const { return Flags & Nest; } + void setNest() { Flags |= One << NestOffs; } + + unsigned getByValAlign() const { + return (unsigned) + ((One << ((Flags & ByValAlign) >> ByValAlignOffs)) / 2); + } + void setByValAlign(unsigned A) { + Flags = (Flags & ~ByValAlign) | + (uint64_t(Log2_32(A) + 1) << ByValAlignOffs); + } + + bool isSplit() const { return Flags & Split; } + void setSplit() { Flags |= One << SplitOffs; } + + unsigned getOrigAlign() const { + return (unsigned) + ((One << ((Flags & OrigAlign) >> OrigAlignOffs)) / 2); + } + void setOrigAlign(unsigned A) { + Flags = (Flags & ~OrigAlign) | + (uint64_t(Log2_32(A) + 1) << OrigAlignOffs); + } + + unsigned getByValSize() const { + return (unsigned)((Flags & ByValSize) >> ByValSizeOffs); + } + void setByValSize(unsigned S) { + Flags = (Flags & ~ByValSize) | (uint64_t(S) << ByValSizeOffs); + } + + /// getArgFlagsString - Returns the flags as a string, eg: "zext align:4". + std::string getArgFlagsString(); + + /// getRawBits - Represent the flags as a bunch of bits. + uint64_t getRawBits() const { return Flags; } + }; + + /// InputArg - This struct carries flags and type information about a + /// single incoming (formal) argument or incoming (from the perspective + /// of the caller) return value virtual register. + /// + struct InputArg { + ArgFlagsTy Flags; + EVT VT; + bool Used; + + InputArg() : VT(MVT::Other), Used(false) {} + InputArg(ISD::ArgFlagsTy flags, EVT vt, bool used) + : Flags(flags), VT(vt), Used(used) { + assert(VT.isSimple() && + "InputArg value type must be Simple!"); + } + }; + + /// OutputArg - This struct carries flags and a value for a + /// single outgoing (actual) argument or outgoing (from the perspective + /// of the caller) return value virtual register. + /// + struct OutputArg { + ArgFlagsTy Flags; + SDValue Val; + bool IsFixed; + + OutputArg() : IsFixed(false) {} + OutputArg(ISD::ArgFlagsTy flags, SDValue val, bool isfixed) + : Flags(flags), Val(val), IsFixed(isfixed) { + assert(Val.getValueType().isSimple() && + "OutputArg value type must be Simple!"); + } + }; +} + +/// VTSDNode - This class is used to represent EVT's, which are used +/// to parameterize some operations. +class VTSDNode : public SDNode { + EVT ValueType; + friend class SelectionDAG; + explicit VTSDNode(EVT VT) + : SDNode(ISD::VALUETYPE, DebugLoc::getUnknownLoc(), + getSDVTList(MVT::Other)), ValueType(VT) { + } +public: + + EVT getVT() const { return ValueType; } + + static bool classof(const VTSDNode *) { return true; } + static bool classof(const SDNode *N) { + return N->getOpcode() == ISD::VALUETYPE; + } +}; + +/// LSBaseSDNode - Base class for LoadSDNode and StoreSDNode +/// +class LSBaseSDNode : public MemSDNode { + //! Operand array for load and store + /*! + \note Moving this array to the base class captures more + common functionality shared between LoadSDNode and + StoreSDNode + */ + SDUse Ops[4]; +public: + LSBaseSDNode(ISD::NodeType NodeTy, DebugLoc dl, SDValue *Operands, + unsigned numOperands, SDVTList VTs, ISD::MemIndexedMode AM, + EVT MemVT, MachineMemOperand *MMO) + : MemSDNode(NodeTy, dl, VTs, MemVT, MMO) { + SubclassData |= AM << 2; + assert(getAddressingMode() == AM && "MemIndexedMode encoding error!"); + InitOperands(Ops, Operands, numOperands); + assert((getOffset().getOpcode() == ISD::UNDEF || isIndexed()) && + "Only indexed loads and stores have a non-undef offset operand"); + } + + const SDValue &getOffset() const { + return getOperand(getOpcode() == ISD::LOAD ? 2 : 3); + } + + /// getAddressingMode - Return the addressing mode for this load or store: + /// unindexed, pre-inc, pre-dec, post-inc, or post-dec. + ISD::MemIndexedMode getAddressingMode() const { + return ISD::MemIndexedMode((SubclassData >> 2) & 7); + } + + /// isIndexed - Return true if this is a pre/post inc/dec load/store. + bool isIndexed() const { return getAddressingMode() != ISD::UNINDEXED; } + + /// isUnindexed - Return true if this is NOT a pre/post inc/dec load/store. + bool isUnindexed() const { return getAddressingMode() == ISD::UNINDEXED; } + + static bool classof(const LSBaseSDNode *) { return true; } + static bool classof(const SDNode *N) { + return N->getOpcode() == ISD::LOAD || + N->getOpcode() == ISD::STORE; + } +}; + +/// LoadSDNode - This class is used to represent ISD::LOAD nodes. +/// +class LoadSDNode : public LSBaseSDNode { + friend class SelectionDAG; + LoadSDNode(SDValue *ChainPtrOff, DebugLoc dl, SDVTList VTs, + ISD::MemIndexedMode AM, ISD::LoadExtType ETy, EVT MemVT, + MachineMemOperand *MMO) + : LSBaseSDNode(ISD::LOAD, dl, ChainPtrOff, 3, + VTs, AM, MemVT, MMO) { + SubclassData |= (unsigned short)ETy; + assert(getExtensionType() == ETy && "LoadExtType encoding error!"); + assert(readMem() && "Load MachineMemOperand is not a load!"); + assert(!writeMem() && "Load MachineMemOperand is a store!"); + } +public: + + /// getExtensionType - Return whether this is a plain node, + /// or one of the varieties of value-extending loads. + ISD::LoadExtType getExtensionType() const { + return ISD::LoadExtType(SubclassData & 3); + } + + const SDValue &getBasePtr() const { return getOperand(1); } + const SDValue &getOffset() const { return getOperand(2); } + + static bool classof(const LoadSDNode *) { return true; } + static bool classof(const SDNode *N) { + return N->getOpcode() == ISD::LOAD; + } +}; + +/// StoreSDNode - This class is used to represent ISD::STORE nodes. +/// +class StoreSDNode : public LSBaseSDNode { + friend class SelectionDAG; + StoreSDNode(SDValue *ChainValuePtrOff, DebugLoc dl, SDVTList VTs, + ISD::MemIndexedMode AM, bool isTrunc, EVT MemVT, + MachineMemOperand *MMO) + : LSBaseSDNode(ISD::STORE, dl, ChainValuePtrOff, 4, + VTs, AM, MemVT, MMO) { + SubclassData |= (unsigned short)isTrunc; + assert(isTruncatingStore() == isTrunc && "isTrunc encoding error!"); + assert(!readMem() && "Store MachineMemOperand is a load!"); + assert(writeMem() && "Store MachineMemOperand is not a store!"); + } +public: + + /// isTruncatingStore - Return true if the op does a truncation before store. + /// For integers this is the same as doing a TRUNCATE and storing the result. + /// For floats, it is the same as doing an FP_ROUND and storing the result. + bool isTruncatingStore() const { return SubclassData & 1; } + + const SDValue &getValue() const { return getOperand(1); } + const SDValue &getBasePtr() const { return getOperand(2); } + const SDValue &getOffset() const { return getOperand(3); } + + static bool classof(const StoreSDNode *) { return true; } + static bool classof(const SDNode *N) { + return N->getOpcode() == ISD::STORE; + } +}; + +/// MachineSDNode - An SDNode that represents everything that will be needed +/// to construct a MachineInstr. These nodes are created during the +/// instruction selection proper phase. +/// +class MachineSDNode : public SDNode { +public: + typedef MachineMemOperand **mmo_iterator; + +private: + friend class SelectionDAG; + MachineSDNode(unsigned Opc, const DebugLoc DL, SDVTList VTs) + : SDNode(Opc, DL, VTs), MemRefs(0), MemRefsEnd(0) {} + + /// LocalOperands - Operands for this instruction, if they fit here. If + /// they don't, this field is unused. + SDUse LocalOperands[4]; + + /// MemRefs - Memory reference descriptions for this instruction. + mmo_iterator MemRefs; + mmo_iterator MemRefsEnd; + +public: + mmo_iterator memoperands_begin() const { return MemRefs; } + mmo_iterator memoperands_end() const { return MemRefsEnd; } + bool memoperands_empty() const { return MemRefsEnd == MemRefs; } + + /// setMemRefs - Assign this MachineSDNodes's memory reference descriptor + /// list. This does not transfer ownership. + void setMemRefs(mmo_iterator NewMemRefs, mmo_iterator NewMemRefsEnd) { + MemRefs = NewMemRefs; + MemRefsEnd = NewMemRefsEnd; + } + + static bool classof(const MachineSDNode *) { return true; } + static bool classof(const SDNode *N) { + return N->isMachineOpcode(); + } +}; + +class SDNodeIterator : public std::iterator { + SDNode *Node; + unsigned Operand; + + SDNodeIterator(SDNode *N, unsigned Op) : Node(N), Operand(Op) {} +public: + bool operator==(const SDNodeIterator& x) const { + return Operand == x.Operand; + } + bool operator!=(const SDNodeIterator& x) const { return !operator==(x); } + + const SDNodeIterator &operator=(const SDNodeIterator &I) { + assert(I.Node == Node && "Cannot assign iterators to two different nodes!"); + Operand = I.Operand; + return *this; + } + + pointer operator*() const { + return Node->getOperand(Operand).getNode(); + } + pointer operator->() const { return operator*(); } + + SDNodeIterator& operator++() { // Preincrement + ++Operand; + return *this; + } + SDNodeIterator operator++(int) { // Postincrement + SDNodeIterator tmp = *this; ++*this; return tmp; + } + + static SDNodeIterator begin(SDNode *N) { return SDNodeIterator(N, 0); } + static SDNodeIterator end (SDNode *N) { + return SDNodeIterator(N, N->getNumOperands()); + } + + unsigned getOperand() const { return Operand; } + const SDNode *getNode() const { return Node; } +}; + +template <> struct GraphTraits { + typedef SDNode NodeType; + typedef SDNodeIterator ChildIteratorType; + static inline NodeType *getEntryNode(SDNode *N) { return N; } + static inline ChildIteratorType child_begin(NodeType *N) { + return SDNodeIterator::begin(N); + } + static inline ChildIteratorType child_end(NodeType *N) { + return SDNodeIterator::end(N); + } +}; + +/// LargestSDNode - The largest SDNode class. +/// +typedef LoadSDNode LargestSDNode; + +/// MostAlignedSDNode - The SDNode class with the greatest alignment +/// requirement. +/// +typedef GlobalAddressSDNode MostAlignedSDNode; + +namespace ISD { + /// isNormalLoad - Returns true if the specified node is a non-extending + /// and unindexed load. + inline bool isNormalLoad(const SDNode *N) { + const LoadSDNode *Ld = dyn_cast(N); + return Ld && Ld->getExtensionType() == ISD::NON_EXTLOAD && + Ld->getAddressingMode() == ISD::UNINDEXED; + } + + /// isNON_EXTLoad - Returns true if the specified node is a non-extending + /// load. + inline bool isNON_EXTLoad(const SDNode *N) { + return isa(N) && + cast(N)->getExtensionType() == ISD::NON_EXTLOAD; + } + + /// isEXTLoad - Returns true if the specified node is a EXTLOAD. + /// + inline bool isEXTLoad(const SDNode *N) { + return isa(N) && + cast(N)->getExtensionType() == ISD::EXTLOAD; + } + + /// isSEXTLoad - Returns true if the specified node is a SEXTLOAD. + /// + inline bool isSEXTLoad(const SDNode *N) { + return isa(N) && + cast(N)->getExtensionType() == ISD::SEXTLOAD; + } + + /// isZEXTLoad - Returns true if the specified node is a ZEXTLOAD. + /// + inline bool isZEXTLoad(const SDNode *N) { + return isa(N) && + cast(N)->getExtensionType() == ISD::ZEXTLOAD; + } + + /// isUNINDEXEDLoad - Returns true if the specified node is an unindexed load. + /// + inline bool isUNINDEXEDLoad(const SDNode *N) { + return isa(N) && + cast(N)->getAddressingMode() == ISD::UNINDEXED; + } + + /// isNormalStore - Returns true if the specified node is a non-truncating + /// and unindexed store. + inline bool isNormalStore(const SDNode *N) { + const StoreSDNode *St = dyn_cast(N); + return St && !St->isTruncatingStore() && + St->getAddressingMode() == ISD::UNINDEXED; + } + + /// isNON_TRUNCStore - Returns true if the specified node is a non-truncating + /// store. + inline bool isNON_TRUNCStore(const SDNode *N) { + return isa(N) && !cast(N)->isTruncatingStore(); + } + + /// isTRUNCStore - Returns true if the specified node is a truncating + /// store. + inline bool isTRUNCStore(const SDNode *N) { + return isa(N) && cast(N)->isTruncatingStore(); + } + + /// isUNINDEXEDStore - Returns true if the specified node is an + /// unindexed store. + inline bool isUNINDEXEDStore(const SDNode *N) { + return isa(N) && + cast(N)->getAddressingMode() == ISD::UNINDEXED; + } +} + + +} // end llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/CodeGen/SlotIndexes.h b/libclamav/c++/llvm/include/llvm/CodeGen/SlotIndexes.h new file mode 100644 index 000000000..65d85fcb3 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/CodeGen/SlotIndexes.h @@ -0,0 +1,767 @@ +//===- llvm/CodeGen/SlotIndexes.h - Slot indexes representation -*- 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 SlotIndex and related classes. The purpuse of SlotIndex +// is to describe a position at which a register can become live, or cease to +// be live. +// +// SlotIndex is mostly a proxy for entries of the SlotIndexList, a class which +// is held is LiveIntervals and provides the real numbering. This allows +// LiveIntervals to perform largely transparent renumbering. The SlotIndex +// class does hold a PHI bit, which determines whether the index relates to a +// PHI use or def point, or an actual instruction. See the SlotIndex class +// description for futher information. +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_SLOTINDEXES_H +#define LLVM_CODEGEN_SLOTINDEXES_H + +#include "llvm/ADT/PointerIntPair.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/CodeGen/MachineBasicBlock.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/Support/Allocator.h" +#include "llvm/Support/ErrorHandling.h" + +namespace llvm { + + /// This class represents an entry in the slot index list held in the + /// SlotIndexes pass. It should not be used directly. See the + /// SlotIndex & SlotIndexes classes for the public interface to this + /// information. + class IndexListEntry { + private: + + static const unsigned EMPTY_KEY_INDEX = ~0U & ~3U, + TOMBSTONE_KEY_INDEX = ~0U & ~7U; + + IndexListEntry *next, *prev; + MachineInstr *mi; + unsigned index; + + protected: + + typedef enum { EMPTY_KEY, TOMBSTONE_KEY } ReservedEntryType; + + // This constructor is only to be used by getEmptyKeyEntry + // & getTombstoneKeyEntry. It sets index to the given + // value and mi to zero. + IndexListEntry(ReservedEntryType r) : mi(0) { + switch(r) { + case EMPTY_KEY: index = EMPTY_KEY_INDEX; break; + case TOMBSTONE_KEY: index = TOMBSTONE_KEY_INDEX; break; + default: assert(false && "Invalid value for constructor."); + } + next = this; + prev = this; + } + + public: + + IndexListEntry(MachineInstr *mi, unsigned index) : mi(mi), index(index) { + if (index == EMPTY_KEY_INDEX || index == TOMBSTONE_KEY_INDEX) { + llvm_report_error("Attempt to create invalid index. " + "Available indexes may have been exhausted?."); + } + } + + MachineInstr* getInstr() const { return mi; } + void setInstr(MachineInstr *mi) { + assert(index != EMPTY_KEY_INDEX && index != TOMBSTONE_KEY_INDEX && + "Attempt to modify reserved index."); + this->mi = mi; + } + + unsigned getIndex() const { return index; } + void setIndex(unsigned index) { + assert(index != EMPTY_KEY_INDEX && index != TOMBSTONE_KEY_INDEX && + "Attempt to set index to invalid value."); + assert(this->index != EMPTY_KEY_INDEX && + this->index != TOMBSTONE_KEY_INDEX && + "Attempt to reset reserved index value."); + this->index = index; + } + + IndexListEntry* getNext() { return next; } + const IndexListEntry* getNext() const { return next; } + void setNext(IndexListEntry *next) { + assert(index != EMPTY_KEY_INDEX && index != TOMBSTONE_KEY_INDEX && + "Attempt to modify reserved index."); + this->next = next; + } + + IndexListEntry* getPrev() { return prev; } + const IndexListEntry* getPrev() const { return prev; } + void setPrev(IndexListEntry *prev) { + assert(index != EMPTY_KEY_INDEX && index != TOMBSTONE_KEY_INDEX && + "Attempt to modify reserved index."); + this->prev = prev; + } + + // This function returns the index list entry that is to be used for empty + // SlotIndex keys. + static IndexListEntry* getEmptyKeyEntry(); + + // This function returns the index list entry that is to be used for + // tombstone SlotIndex keys. + static IndexListEntry* getTombstoneKeyEntry(); + }; + + // Specialize PointerLikeTypeTraits for IndexListEntry. + template <> + class PointerLikeTypeTraits { + public: + static inline void* getAsVoidPointer(IndexListEntry *p) { + return p; + } + static inline IndexListEntry* getFromVoidPointer(void *p) { + return static_cast(p); + } + enum { NumLowBitsAvailable = 3 }; + }; + + /// SlotIndex - An opaque wrapper around machine indexes. + class SlotIndex { + friend class SlotIndexes; + friend struct DenseMapInfo; + + private: + static const unsigned PHI_BIT = 1 << 2; + + PointerIntPair lie; + + SlotIndex(IndexListEntry *entry, unsigned phiAndSlot) + : lie(entry, phiAndSlot) { + assert(entry != 0 && "Attempt to construct index with 0 pointer."); + } + + IndexListEntry& entry() const { + return *lie.getPointer(); + } + + int getIndex() const { + return entry().getIndex() | getSlot(); + } + + static inline unsigned getHashValue(const SlotIndex &v) { + IndexListEntry *ptrVal = &v.entry(); + return (unsigned((intptr_t)ptrVal) >> 4) ^ + (unsigned((intptr_t)ptrVal) >> 9); + } + + public: + + // FIXME: Ugh. This is public because LiveIntervalAnalysis is still using it + // for some spill weight stuff. Fix that, then make this private. + enum Slot { LOAD, USE, DEF, STORE, NUM }; + + static inline SlotIndex getEmptyKey() { + return SlotIndex(IndexListEntry::getEmptyKeyEntry(), 0); + } + + static inline SlotIndex getTombstoneKey() { + return SlotIndex(IndexListEntry::getTombstoneKeyEntry(), 0); + } + + /// Construct an invalid index. + SlotIndex() : lie(IndexListEntry::getEmptyKeyEntry(), 0) {} + + // Construct a new slot index from the given one, set the phi flag on the + // new index to the value of the phi parameter. + SlotIndex(const SlotIndex &li, bool phi) + : lie(&li.entry(), phi ? PHI_BIT & li.getSlot() : (unsigned)li.getSlot()){ + assert(lie.getPointer() != 0 && + "Attempt to construct index with 0 pointer."); + } + + // Construct a new slot index from the given one, set the phi flag on the + // new index to the value of the phi parameter, and the slot to the new slot. + SlotIndex(const SlotIndex &li, bool phi, Slot s) + : lie(&li.entry(), phi ? PHI_BIT & s : (unsigned)s) { + assert(lie.getPointer() != 0 && + "Attempt to construct index with 0 pointer."); + } + + /// Returns true if this is a valid index. Invalid indicies do + /// not point into an index table, and cannot be compared. + bool isValid() const { + return (lie.getPointer() != 0) && (lie.getPointer()->getIndex() != 0); + } + + /// Print this index to the given raw_ostream. + void print(raw_ostream &os) const; + + /// Dump this index to stderr. + void dump() const; + + /// Compare two SlotIndex objects for equality. + bool operator==(SlotIndex other) const { + return getIndex() == other.getIndex(); + } + /// Compare two SlotIndex objects for inequality. + bool operator!=(SlotIndex other) const { + return getIndex() != other.getIndex(); + } + + /// Compare two SlotIndex objects. Return true if the first index + /// is strictly lower than the second. + bool operator<(SlotIndex other) const { + return getIndex() < other.getIndex(); + } + /// Compare two SlotIndex objects. Return true if the first index + /// is lower than, or equal to, the second. + bool operator<=(SlotIndex other) const { + return getIndex() <= other.getIndex(); + } + + /// Compare two SlotIndex objects. Return true if the first index + /// is greater than the second. + bool operator>(SlotIndex other) const { + return getIndex() > other.getIndex(); + } + + /// Compare two SlotIndex objects. Return true if the first index + /// is greater than, or equal to, the second. + bool operator>=(SlotIndex other) const { + return getIndex() >= other.getIndex(); + } + + /// Return the distance from this index to the given one. + int distance(SlotIndex other) const { + return other.getIndex() - getIndex(); + } + + /// Returns the slot for this SlotIndex. + Slot getSlot() const { + return static_cast(lie.getInt() & ~PHI_BIT); + } + + /// Returns the state of the PHI bit. + bool isPHI() const { + return lie.getInt() & PHI_BIT; + } + + /// Returns the base index for associated with this index. The base index + /// is the one associated with the LOAD slot for the instruction pointed to + /// by this index. + SlotIndex getBaseIndex() const { + return getLoadIndex(); + } + + /// Returns the boundary index for associated with this index. The boundary + /// index is the one associated with the LOAD slot for the instruction + /// pointed to by this index. + SlotIndex getBoundaryIndex() const { + return getStoreIndex(); + } + + /// Returns the index of the LOAD slot for the instruction pointed to by + /// this index. + SlotIndex getLoadIndex() const { + return SlotIndex(&entry(), SlotIndex::LOAD); + } + + /// Returns the index of the USE slot for the instruction pointed to by + /// this index. + SlotIndex getUseIndex() const { + return SlotIndex(&entry(), SlotIndex::USE); + } + + /// Returns the index of the DEF slot for the instruction pointed to by + /// this index. + SlotIndex getDefIndex() const { + return SlotIndex(&entry(), SlotIndex::DEF); + } + + /// Returns the index of the STORE slot for the instruction pointed to by + /// this index. + SlotIndex getStoreIndex() const { + return SlotIndex(&entry(), SlotIndex::STORE); + } + + /// Returns the next slot in the index list. This could be either the + /// next slot for the instruction pointed to by this index or, if this + /// index is a STORE, the first slot for the next instruction. + /// WARNING: This method is considerably more expensive than the methods + /// that return specific slots (getUseIndex(), etc). If you can - please + /// use one of those methods. + SlotIndex getNextSlot() const { + Slot s = getSlot(); + if (s == SlotIndex::STORE) { + return SlotIndex(entry().getNext(), SlotIndex::LOAD); + } + return SlotIndex(&entry(), s + 1); + } + + /// Returns the next index. This is the index corresponding to the this + /// index's slot, but for the next instruction. + SlotIndex getNextIndex() const { + return SlotIndex(entry().getNext(), getSlot()); + } + + /// Returns the previous slot in the index list. This could be either the + /// previous slot for the instruction pointed to by this index or, if this + /// index is a LOAD, the last slot for the previous instruction. + /// WARNING: This method is considerably more expensive than the methods + /// that return specific slots (getUseIndex(), etc). If you can - please + /// use one of those methods. + SlotIndex getPrevSlot() const { + Slot s = getSlot(); + if (s == SlotIndex::LOAD) { + return SlotIndex(entry().getPrev(), SlotIndex::STORE); + } + return SlotIndex(&entry(), s - 1); + } + + /// Returns the previous index. This is the index corresponding to this + /// index's slot, but for the previous instruction. + SlotIndex getPrevIndex() const { + return SlotIndex(entry().getPrev(), getSlot()); + } + + }; + + /// DenseMapInfo specialization for SlotIndex. + template <> + struct DenseMapInfo { + static inline SlotIndex getEmptyKey() { + return SlotIndex::getEmptyKey(); + } + static inline SlotIndex getTombstoneKey() { + return SlotIndex::getTombstoneKey(); + } + static inline unsigned getHashValue(const SlotIndex &v) { + return SlotIndex::getHashValue(v); + } + static inline bool isEqual(const SlotIndex &LHS, const SlotIndex &RHS) { + return (LHS == RHS); + } + static inline bool isPod() { return false; } + }; + + inline raw_ostream& operator<<(raw_ostream &os, SlotIndex li) { + li.print(os); + return os; + } + + typedef std::pair IdxMBBPair; + + inline bool operator<(SlotIndex V, const IdxMBBPair &IM) { + return V < IM.first; + } + + inline bool operator<(const IdxMBBPair &IM, SlotIndex V) { + return IM.first < V; + } + + struct Idx2MBBCompare { + bool operator()(const IdxMBBPair &LHS, const IdxMBBPair &RHS) const { + return LHS.first < RHS.first; + } + }; + + /// SlotIndexes pass. + /// + /// This pass assigns indexes to each instruction. + class SlotIndexes : public MachineFunctionPass { + private: + + MachineFunction *mf; + IndexListEntry *indexListHead; + unsigned functionSize; + + typedef DenseMap Mi2IndexMap; + Mi2IndexMap mi2iMap; + + /// MBB2IdxMap - The indexes of the first and last instructions in the + /// specified basic block. + typedef DenseMap > MBB2IdxMap; + MBB2IdxMap mbb2IdxMap; + + /// Idx2MBBMap - Sorted list of pairs of index of first instruction + /// and MBB id. + std::vector idx2MBBMap; + + typedef DenseMap TerminatorGapsMap; + TerminatorGapsMap terminatorGaps; + + // IndexListEntry allocator. + BumpPtrAllocator ileAllocator; + + IndexListEntry* createEntry(MachineInstr *mi, unsigned index) { + IndexListEntry *entry = + static_cast( + ileAllocator.Allocate(sizeof(IndexListEntry), + alignof())); + + new (entry) IndexListEntry(mi, index); + + return entry; + } + + void initList() { + assert(indexListHead == 0 && "Zero entry non-null at initialisation."); + indexListHead = createEntry(0, ~0U); + indexListHead->setNext(0); + indexListHead->setPrev(indexListHead); + } + + void clearList() { + indexListHead = 0; + ileAllocator.Reset(); + } + + IndexListEntry* getTail() { + assert(indexListHead != 0 && "Call to getTail on uninitialized list."); + return indexListHead->getPrev(); + } + + const IndexListEntry* getTail() const { + assert(indexListHead != 0 && "Call to getTail on uninitialized list."); + return indexListHead->getPrev(); + } + + // Returns true if the index list is empty. + bool empty() const { return (indexListHead == getTail()); } + + IndexListEntry* front() { + assert(!empty() && "front() called on empty index list."); + return indexListHead; + } + + const IndexListEntry* front() const { + assert(!empty() && "front() called on empty index list."); + return indexListHead; + } + + IndexListEntry* back() { + assert(!empty() && "back() called on empty index list."); + return getTail()->getPrev(); + } + + const IndexListEntry* back() const { + assert(!empty() && "back() called on empty index list."); + return getTail()->getPrev(); + } + + /// Insert a new entry before itr. + void insert(IndexListEntry *itr, IndexListEntry *val) { + assert(itr != 0 && "itr should not be null."); + IndexListEntry *prev = itr->getPrev(); + val->setNext(itr); + val->setPrev(prev); + + if (itr != indexListHead) { + prev->setNext(val); + } + else { + indexListHead = val; + } + itr->setPrev(val); + } + + /// Push a new entry on to the end of the list. + void push_back(IndexListEntry *val) { + insert(getTail(), val); + } + + public: + static char ID; + + SlotIndexes() : MachineFunctionPass(&ID), indexListHead(0) {} + + virtual void getAnalysisUsage(AnalysisUsage &au) const; + virtual void releaseMemory(); + + virtual bool runOnMachineFunction(MachineFunction &fn); + + /// Dump the indexes. + void dump() const; + + /// Renumber the index list, providing space for new instructions. + void renumberIndexes(); + + /// Returns the zero index for this analysis. + SlotIndex getZeroIndex() { + assert(front()->getIndex() == 0 && "First index is not 0?"); + return SlotIndex(front(), 0); + } + + /// Returns the invalid index marker for this analysis. + SlotIndex getInvalidIndex() { + return getZeroIndex(); + } + + /// Returns the distance between the highest and lowest indexes allocated + /// so far. + unsigned getIndexesLength() const { + assert(front()->getIndex() == 0 && + "Initial index isn't zero?"); + + return back()->getIndex(); + } + + /// Returns the number of instructions in the function. + unsigned getFunctionSize() const { + return functionSize; + } + + /// Returns true if the given machine instr is mapped to an index, + /// otherwise returns false. + bool hasIndex(const MachineInstr *instr) const { + return (mi2iMap.find(instr) != mi2iMap.end()); + } + + /// Returns the base index for the given instruction. + SlotIndex getInstructionIndex(const MachineInstr *instr) const { + Mi2IndexMap::const_iterator itr = mi2iMap.find(instr); + assert(itr != mi2iMap.end() && "Instruction not found in maps."); + return itr->second; + } + + /// Returns the instruction for the given index, or null if the given + /// index has no instruction associated with it. + MachineInstr* getInstructionFromIndex(SlotIndex index) const { + return index.entry().getInstr(); + } + + /// Returns the next non-null index. + SlotIndex getNextNonNullIndex(SlotIndex index) { + SlotIndex nextNonNull = index.getNextIndex(); + + while (&nextNonNull.entry() != getTail() && + getInstructionFromIndex(nextNonNull) == 0) { + nextNonNull = nextNonNull.getNextIndex(); + } + + return nextNonNull; + } + + /// Returns the first index in the given basic block. + SlotIndex getMBBStartIdx(const MachineBasicBlock *mbb) const { + MBB2IdxMap::const_iterator itr = mbb2IdxMap.find(mbb); + assert(itr != mbb2IdxMap.end() && "MBB not found in maps."); + return itr->second.first; + } + + /// Returns the last index in the given basic block. + SlotIndex getMBBEndIdx(const MachineBasicBlock *mbb) const { + MBB2IdxMap::const_iterator itr = mbb2IdxMap.find(mbb); + assert(itr != mbb2IdxMap.end() && "MBB not found in maps."); + return itr->second.second; + } + + /// Returns the terminator gap for the given index. + SlotIndex getTerminatorGap(const MachineBasicBlock *mbb) { + TerminatorGapsMap::iterator itr = terminatorGaps.find(mbb); + assert(itr != terminatorGaps.end() && + "All MBBs should have terminator gaps in their indexes."); + return itr->second; + } + + /// Returns the basic block which the given index falls in. + MachineBasicBlock* getMBBFromIndex(SlotIndex index) const { + std::vector::const_iterator I = + std::lower_bound(idx2MBBMap.begin(), idx2MBBMap.end(), index); + // Take the pair containing the index + std::vector::const_iterator J = + ((I != idx2MBBMap.end() && I->first > index) || + (I == idx2MBBMap.end() && idx2MBBMap.size()>0)) ? (I-1): I; + + assert(J != idx2MBBMap.end() && J->first <= index && + index <= getMBBEndIdx(J->second) && + "index does not correspond to an MBB"); + return J->second; + } + + bool findLiveInMBBs(SlotIndex start, SlotIndex end, + SmallVectorImpl &mbbs) const { + std::vector::const_iterator itr = + std::lower_bound(idx2MBBMap.begin(), idx2MBBMap.end(), start); + bool resVal = false; + + while (itr != idx2MBBMap.end()) { + if (itr->first >= end) + break; + mbbs.push_back(itr->second); + resVal = true; + ++itr; + } + return resVal; + } + + /// Return a list of MBBs that can be reach via any branches or + /// fall-throughs. + bool findReachableMBBs(SlotIndex start, SlotIndex end, + SmallVectorImpl &mbbs) const { + std::vector::const_iterator itr = + std::lower_bound(idx2MBBMap.begin(), idx2MBBMap.end(), start); + + bool resVal = false; + while (itr != idx2MBBMap.end()) { + if (itr->first > end) + break; + MachineBasicBlock *mbb = itr->second; + if (getMBBEndIdx(mbb) > end) + break; + for (MachineBasicBlock::succ_iterator si = mbb->succ_begin(), + se = mbb->succ_end(); si != se; ++si) + mbbs.push_back(*si); + resVal = true; + ++itr; + } + return resVal; + } + + /// Returns the MBB covering the given range, or null if the range covers + /// more than one basic block. + MachineBasicBlock* getMBBCoveringRange(SlotIndex start, SlotIndex end) const { + + assert(start < end && "Backwards ranges not allowed."); + + std::vector::const_iterator itr = + std::lower_bound(idx2MBBMap.begin(), idx2MBBMap.end(), start); + + if (itr == idx2MBBMap.end()) { + itr = prior(itr); + return itr->second; + } + + // Check that we don't cross the boundary into this block. + if (itr->first < end) + return 0; + + itr = prior(itr); + + if (itr->first <= start) + return itr->second; + + return 0; + } + + /// Insert the given machine instruction into the mapping. Returns the + /// assigned index. + SlotIndex insertMachineInstrInMaps(MachineInstr *mi, + bool *deferredRenumber = 0) { + assert(mi2iMap.find(mi) == mi2iMap.end() && "Instr already indexed."); + + MachineBasicBlock *mbb = mi->getParent(); + + assert(mbb != 0 && "Instr must be added to function."); + + MBB2IdxMap::iterator mbbRangeItr = mbb2IdxMap.find(mbb); + + assert(mbbRangeItr != mbb2IdxMap.end() && + "Instruction's parent MBB has not been added to SlotIndexes."); + + MachineBasicBlock::iterator miItr(mi); + bool needRenumber = false; + IndexListEntry *newEntry; + + IndexListEntry *prevEntry; + if (miItr == mbb->begin()) { + // If mi is at the mbb beginning, get the prev index from the mbb. + prevEntry = &mbbRangeItr->second.first.entry(); + } else { + // Otherwise get it from the previous instr. + MachineBasicBlock::iterator pItr(prior(miItr)); + prevEntry = &getInstructionIndex(pItr).entry(); + } + + // Get next entry from previous entry. + IndexListEntry *nextEntry = prevEntry->getNext(); + + // Get a number for the new instr, or 0 if there's no room currently. + // In the latter case we'll force a renumber later. + unsigned dist = nextEntry->getIndex() - prevEntry->getIndex(); + unsigned newNumber = dist > SlotIndex::NUM ? + prevEntry->getIndex() + ((dist >> 1) & ~3U) : 0; + + if (newNumber == 0) { + needRenumber = true; + } + + // Insert a new list entry for mi. + newEntry = createEntry(mi, newNumber); + insert(nextEntry, newEntry); + + SlotIndex newIndex(newEntry, SlotIndex::LOAD); + mi2iMap.insert(std::make_pair(mi, newIndex)); + + if (miItr == mbb->end()) { + // If this is the last instr in the MBB then we need to fix up the bb + // range: + mbbRangeItr->second.second = SlotIndex(newEntry, SlotIndex::STORE); + } + + // Renumber if we need to. + if (needRenumber) { + if (deferredRenumber == 0) + renumberIndexes(); + else + *deferredRenumber = true; + } + + return newIndex; + } + + /// Add all instructions in the vector to the index list. This method will + /// defer renumbering until all instrs have been added, and should be + /// preferred when adding multiple instrs. + void insertMachineInstrsInMaps(SmallVectorImpl &mis) { + bool renumber = false; + + for (SmallVectorImpl::iterator + miItr = mis.begin(), miEnd = mis.end(); + miItr != miEnd; ++miItr) { + insertMachineInstrInMaps(*miItr, &renumber); + } + + if (renumber) + renumberIndexes(); + } + + + /// Remove the given machine instruction from the mapping. + void removeMachineInstrFromMaps(MachineInstr *mi) { + // remove index -> MachineInstr and + // MachineInstr -> index mappings + Mi2IndexMap::iterator mi2iItr = mi2iMap.find(mi); + if (mi2iItr != mi2iMap.end()) { + IndexListEntry *miEntry(&mi2iItr->second.entry()); + assert(miEntry->getInstr() == mi && "Instruction indexes broken."); + // FIXME: Eventually we want to actually delete these indexes. + miEntry->setInstr(0); + mi2iMap.erase(mi2iItr); + } + } + + /// ReplaceMachineInstrInMaps - Replacing a machine instr with a new one in + /// maps used by register allocator. + void replaceMachineInstrInMaps(MachineInstr *mi, MachineInstr *newMI) { + Mi2IndexMap::iterator mi2iItr = mi2iMap.find(mi); + if (mi2iItr == mi2iMap.end()) + return; + SlotIndex replaceBaseIndex = mi2iItr->second; + IndexListEntry *miEntry(&replaceBaseIndex.entry()); + assert(miEntry->getInstr() == mi && + "Mismatched instruction in index tables."); + miEntry->setInstr(newMI); + mi2iMap.erase(mi2iItr); + mi2iMap.insert(std::make_pair(newMI, replaceBaseIndex)); + } + + }; + + +} + +#endif // LLVM_CODEGEN_LIVEINDEX_H diff --git a/libclamav/c++/llvm/include/llvm/CodeGen/ValueTypes.h b/libclamav/c++/llvm/include/llvm/CodeGen/ValueTypes.h new file mode 100644 index 000000000..45ef9b930 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/CodeGen/ValueTypes.h @@ -0,0 +1,650 @@ +//===- CodeGen/ValueTypes.h - Low-Level Target independ. types --*- 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 the set of low-level target independent types which various +// values in the code generator are. This allows the target specific behavior +// of instructions to be described to target independent passes. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_VALUETYPES_H +#define LLVM_CODEGEN_VALUETYPES_H + +#include +#include +#include "llvm/System/DataTypes.h" +#include "llvm/Support/MathExtras.h" + +namespace llvm { + class Type; + class LLVMContext; + struct EVT; + + class MVT { // MVT = Machine Value Type + public: + enum SimpleValueType { + // If you change this numbering, you must change the values in + // ValueTypes.td as well! + Other = 0, // This is a non-standard value + i1 = 1, // This is a 1 bit integer value + i8 = 2, // This is an 8 bit integer value + i16 = 3, // This is a 16 bit integer value + i32 = 4, // This is a 32 bit integer value + i64 = 5, // This is a 64 bit integer value + i128 = 6, // This is a 128 bit integer value + + FIRST_INTEGER_VALUETYPE = i1, + LAST_INTEGER_VALUETYPE = i128, + + f32 = 7, // This is a 32 bit floating point value + f64 = 8, // This is a 64 bit floating point value + f80 = 9, // This is a 80 bit floating point value + f128 = 10, // This is a 128 bit floating point value + ppcf128 = 11, // This is a PPC 128-bit floating point value + Flag = 12, // This is a condition code or machine flag. + + isVoid = 13, // This has no value + + v2i8 = 14, // 2 x i8 + v4i8 = 15, // 4 x i8 + v8i8 = 16, // 8 x i8 + v16i8 = 17, // 16 x i8 + v32i8 = 18, // 32 x i8 + v2i16 = 19, // 2 x i16 + v4i16 = 20, // 4 x i16 + v8i16 = 21, // 8 x i16 + v16i16 = 22, // 16 x i16 + v2i32 = 23, // 2 x i32 + v4i32 = 24, // 4 x i32 + v8i32 = 25, // 8 x i32 + v1i64 = 26, // 1 x i64 + v2i64 = 27, // 2 x i64 + v4i64 = 28, // 4 x i64 + + v2f32 = 29, // 2 x f32 + v4f32 = 30, // 4 x f32 + v8f32 = 31, // 8 x f32 + v2f64 = 32, // 2 x f64 + v4f64 = 33, // 4 x f64 + + FIRST_VECTOR_VALUETYPE = v2i8, + LAST_VECTOR_VALUETYPE = v4f64, + + LAST_VALUETYPE = 34, // This always remains at the end of the list. + + // This is the current maximum for LAST_VALUETYPE. + // EVT::MAX_ALLOWED_VALUETYPE is used for asserts and to size bit vectors + // This value must be a multiple of 32. + MAX_ALLOWED_VALUETYPE = 64, + + // Metadata - This is MDNode or MDString. + Metadata = 250, + + // iPTRAny - An int value the size of the pointer of the current + // target to any address space. This must only be used internal to + // tblgen. Other than for overloading, we treat iPTRAny the same as iPTR. + iPTRAny = 251, + + // vAny - A vector with any length and element size. This is used + // for intrinsics that have overloadings based on vector types. + // This is only for tblgen's consumption! + vAny = 252, + + // fAny - Any floating-point or vector floating-point value. This is used + // for intrinsics that have overloadings based on floating-point types. + // This is only for tblgen's consumption! + fAny = 253, + + // iAny - An integer or vector integer value of any bit width. This is + // used for intrinsics that have overloadings based on integer bit widths. + // This is only for tblgen's consumption! + iAny = 254, + + // iPTR - An int value the size of the pointer of the current + // target. This should only be used internal to tblgen! + iPTR = 255, + + // LastSimpleValueType - The greatest valid SimpleValueType value. + LastSimpleValueType = 255, + + // INVALID_SIMPLE_VALUE_TYPE - Simple value types greater than or equal + // to this are considered extended value types. + INVALID_SIMPLE_VALUE_TYPE = LastSimpleValueType + 1 + }; + + SimpleValueType SimpleTy; + + MVT() : SimpleTy((SimpleValueType)(INVALID_SIMPLE_VALUE_TYPE)) {} + MVT(SimpleValueType SVT) : SimpleTy(SVT) { } + + bool operator>(const MVT& S) const { return SimpleTy > S.SimpleTy; } + bool operator<(const MVT& S) const { return SimpleTy < S.SimpleTy; } + bool operator==(const MVT& S) const { return SimpleTy == S.SimpleTy; } + bool operator>=(const MVT& S) const { return SimpleTy >= S.SimpleTy; } + bool operator<=(const MVT& S) const { return SimpleTy <= S.SimpleTy; } + + /// isFloatingPoint - Return true if this is a FP, or a vector FP type. + bool isFloatingPoint() const { + return ((SimpleTy >= MVT::f32 && SimpleTy <= MVT::ppcf128) || + (SimpleTy >= MVT::v2f32 && SimpleTy <= MVT::v4f64)); + } + + /// isInteger - Return true if this is an integer, or a vector integer type. + bool isInteger() const { + return ((SimpleTy >= MVT::FIRST_INTEGER_VALUETYPE && + SimpleTy <= MVT::LAST_INTEGER_VALUETYPE) || + (SimpleTy >= MVT::v2i8 && SimpleTy <= MVT::v4i64)); + } + + /// isVector - Return true if this is a vector value type. + bool isVector() const { + return (SimpleTy >= MVT::FIRST_VECTOR_VALUETYPE && + SimpleTy <= MVT::LAST_VECTOR_VALUETYPE); + } + + /// isPow2VectorType - Retuns true if the given vector is a power of 2. + bool isPow2VectorType() const { + unsigned NElts = getVectorNumElements(); + return !(NElts & (NElts - 1)); + } + + /// getPow2VectorType - Widens the length of the given vector EVT up to + /// the nearest power of 2 and returns that type. + MVT getPow2VectorType() const { + if (!isPow2VectorType()) { + unsigned NElts = getVectorNumElements(); + unsigned Pow2NElts = 1 << Log2_32_Ceil(NElts); + return MVT::getVectorVT(getVectorElementType(), Pow2NElts); + } + else { + return *this; + } + } + + MVT getVectorElementType() const { + switch (SimpleTy) { + default: + return (MVT::SimpleValueType)(MVT::INVALID_SIMPLE_VALUE_TYPE); + case v2i8 : + case v4i8 : + case v8i8 : + case v16i8: + case v32i8: return i8; + case v2i16: + case v4i16: + case v8i16: + case v16i16: return i16; + case v2i32: + case v4i32: + case v8i32: return i32; + case v1i64: + case v2i64: + case v4i64: return i64; + case v2f32: + case v4f32: + case v8f32: return f32; + case v2f64: + case v4f64: return f64; + } + } + + unsigned getVectorNumElements() const { + switch (SimpleTy) { + default: + return ~0U; + case v32i8: return 32; + case v16i8: + case v16i16: return 16; + case v8i8 : + case v8i16: + case v8i32: + case v8f32: return 8; + case v4i8: + case v4i16: + case v4i32: + case v4i64: + case v4f32: + case v4f64: return 4; + case v2i8: + case v2i16: + case v2i32: + case v2i64: + case v2f32: + case v2f64: return 2; + case v1i64: return 1; + } + } + + unsigned getSizeInBits() const { + switch (SimpleTy) { + case iPTR: + assert(0 && "Value type size is target-dependent. Ask TLI."); + case iPTRAny: + case iAny: + case fAny: + assert(0 && "Value type is overloaded."); + default: + assert(0 && "getSizeInBits called on extended MVT."); + case i1 : return 1; + case i8 : return 8; + case i16 : + case v2i8: return 16; + case f32 : + case i32 : + case v4i8: + case v2i16: return 32; + case f64 : + case i64 : + case v8i8: + case v4i16: + case v2i32: + case v1i64: + case v2f32: return 64; + case f80 : return 80; + case f128: + case ppcf128: + case i128: + case v16i8: + case v8i16: + case v4i32: + case v2i64: + case v4f32: + case v2f64: return 128; + case v32i8: + case v16i16: + case v8i32: + case v4i64: + case v8f32: + case v4f64: return 256; + } + } + + static MVT getFloatingPointVT(unsigned BitWidth) { + switch (BitWidth) { + default: + assert(false && "Bad bit width!"); + case 32: + return MVT::f32; + case 64: + return MVT::f64; + case 80: + return MVT::f80; + case 128: + return MVT::f128; + } + } + + static MVT getIntegerVT(unsigned BitWidth) { + switch (BitWidth) { + default: + return (MVT::SimpleValueType)(MVT::INVALID_SIMPLE_VALUE_TYPE); + case 1: + return MVT::i1; + case 8: + return MVT::i8; + case 16: + return MVT::i16; + case 32: + return MVT::i32; + case 64: + return MVT::i64; + case 128: + return MVT::i128; + } + } + + static MVT getVectorVT(MVT VT, unsigned NumElements) { + switch (VT.SimpleTy) { + default: + break; + case MVT::i8: + if (NumElements == 2) return MVT::v2i8; + if (NumElements == 4) return MVT::v4i8; + if (NumElements == 8) return MVT::v8i8; + if (NumElements == 16) return MVT::v16i8; + if (NumElements == 32) return MVT::v32i8; + break; + case MVT::i16: + if (NumElements == 2) return MVT::v2i16; + if (NumElements == 4) return MVT::v4i16; + if (NumElements == 8) return MVT::v8i16; + if (NumElements == 16) return MVT::v16i16; + break; + case MVT::i32: + if (NumElements == 2) return MVT::v2i32; + if (NumElements == 4) return MVT::v4i32; + if (NumElements == 8) return MVT::v8i32; + break; + case MVT::i64: + if (NumElements == 1) return MVT::v1i64; + if (NumElements == 2) return MVT::v2i64; + if (NumElements == 4) return MVT::v4i64; + break; + case MVT::f32: + if (NumElements == 2) return MVT::v2f32; + if (NumElements == 4) return MVT::v4f32; + if (NumElements == 8) return MVT::v8f32; + break; + case MVT::f64: + if (NumElements == 2) return MVT::v2f64; + if (NumElements == 4) return MVT::v4f64; + break; + } + return (MVT::SimpleValueType)(MVT::INVALID_SIMPLE_VALUE_TYPE); + } + + static MVT getIntVectorWithNumElements(unsigned NumElts) { + switch (NumElts) { + default: return (MVT::SimpleValueType)(MVT::INVALID_SIMPLE_VALUE_TYPE); + case 1: return MVT::v1i64; + case 2: return MVT::v2i32; + case 4: return MVT::v4i16; + case 8: return MVT::v8i8; + case 16: return MVT::v16i8; + } + } + }; + + struct EVT { // EVT = Extended Value Type + private: + MVT V; + const Type *LLVMTy; + + public: + EVT() : V((MVT::SimpleValueType)(MVT::INVALID_SIMPLE_VALUE_TYPE)), + LLVMTy(0) {} + EVT(MVT::SimpleValueType SVT) : V(SVT), LLVMTy(0) { } + EVT(MVT S) : V(S), LLVMTy(0) {} + + bool operator==(const EVT VT) const { + if (V.SimpleTy == VT.V.SimpleTy) { + if (V.SimpleTy == MVT::INVALID_SIMPLE_VALUE_TYPE) + return LLVMTy == VT.LLVMTy; + return true; + } + return false; + } + bool operator!=(const EVT VT) const { + if (V.SimpleTy == VT.V.SimpleTy) { + if (V.SimpleTy == MVT::INVALID_SIMPLE_VALUE_TYPE) + return LLVMTy != VT.LLVMTy; + return false; + } + return true; + } + + /// getFloatingPointVT - Returns the EVT that represents a floating point + /// type with the given number of bits. There are two floating point types + /// with 128 bits - this returns f128 rather than ppcf128. + static EVT getFloatingPointVT(unsigned BitWidth) { + return MVT::getFloatingPointVT(BitWidth); + } + + /// getIntegerVT - Returns the EVT that represents an integer with the given + /// number of bits. + static EVT getIntegerVT(LLVMContext &Context, unsigned BitWidth) { + MVT M = MVT::getIntegerVT(BitWidth); + if (M.SimpleTy == MVT::INVALID_SIMPLE_VALUE_TYPE) + return getExtendedIntegerVT(Context, BitWidth); + else + return M; + } + + /// getVectorVT - Returns the EVT that represents a vector NumElements in + /// length, where each element is of type VT. + static EVT getVectorVT(LLVMContext &Context, EVT VT, unsigned NumElements) { + MVT M = MVT::getVectorVT(VT.V, NumElements); + if (M.SimpleTy == MVT::INVALID_SIMPLE_VALUE_TYPE) + return getExtendedVectorVT(Context, VT, NumElements); + else + return M; + } + + /// getIntVectorWithNumElements - Return any integer vector type that has + /// the specified number of elements. + static EVT getIntVectorWithNumElements(LLVMContext &C, unsigned NumElts) { + MVT M = MVT::getIntVectorWithNumElements(NumElts); + if (M.SimpleTy == MVT::INVALID_SIMPLE_VALUE_TYPE) + return getVectorVT(C, MVT::i8, NumElts); + else + return M; + } + + /// isSimple - Test if the given EVT is simple (as opposed to being + /// extended). + bool isSimple() const { + return V.SimpleTy <= MVT::LastSimpleValueType; + } + + /// isExtended - Test if the given EVT is extended (as opposed to + /// being simple). + bool isExtended() const { + return !isSimple(); + } + + /// isFloatingPoint - Return true if this is a FP, or a vector FP type. + bool isFloatingPoint() const { + return isSimple() ? + ((V >= MVT::f32 && V <= MVT::ppcf128) || + (V >= MVT::v2f32 && V <= MVT::v4f64)) : isExtendedFloatingPoint(); + } + + /// isInteger - Return true if this is an integer, or a vector integer type. + bool isInteger() const { + return isSimple() ? + ((V >= MVT::FIRST_INTEGER_VALUETYPE && + V <= MVT::LAST_INTEGER_VALUETYPE) || + (V >= MVT::v2i8 && V <= MVT::v4i64)) : isExtendedInteger(); + } + + /// isVector - Return true if this is a vector value type. + bool isVector() const { + return isSimple() ? + (V >= MVT::FIRST_VECTOR_VALUETYPE && V <= + MVT::LAST_VECTOR_VALUETYPE) : + isExtendedVector(); + } + + /// is64BitVector - Return true if this is a 64-bit vector type. + bool is64BitVector() const { + return isSimple() ? + (V==MVT::v8i8 || V==MVT::v4i16 || V==MVT::v2i32 || + V==MVT::v1i64 || V==MVT::v2f32) : + isExtended64BitVector(); + } + + /// is128BitVector - Return true if this is a 128-bit vector type. + bool is128BitVector() const { + return isSimple() ? + (V==MVT::v16i8 || V==MVT::v8i16 || V==MVT::v4i32 || + V==MVT::v2i64 || V==MVT::v4f32 || V==MVT::v2f64) : + isExtended128BitVector(); + } + + /// is256BitVector - Return true if this is a 256-bit vector type. + inline bool is256BitVector() const { + return isSimple() ? + (V==MVT::v8f32 || V==MVT::v4f64 || V==MVT::v32i8 || + V==MVT::v16i16 || V==MVT::v8i32 || V==MVT::v4i64) : + isExtended256BitVector(); + } + + /// isOverloaded - Return true if this is an overloaded type for TableGen. + bool isOverloaded() const { + return (V==MVT::iAny || V==MVT::fAny || V==MVT::vAny || V==MVT::iPTRAny); + } + + /// isByteSized - Return true if the bit size is a multiple of 8. + bool isByteSized() const { + return (getSizeInBits() & 7) == 0; + } + + /// isRound - Return true if the size is a power-of-two number of bytes. + bool isRound() const { + unsigned BitSize = getSizeInBits(); + return BitSize >= 8 && !(BitSize & (BitSize - 1)); + } + + /// bitsEq - Return true if this has the same number of bits as VT. + bool bitsEq(EVT VT) const { + return getSizeInBits() == VT.getSizeInBits(); + } + + /// bitsGT - Return true if this has more bits than VT. + bool bitsGT(EVT VT) const { + return getSizeInBits() > VT.getSizeInBits(); + } + + /// bitsGE - Return true if this has no less bits than VT. + bool bitsGE(EVT VT) const { + return getSizeInBits() >= VT.getSizeInBits(); + } + + /// bitsLT - Return true if this has less bits than VT. + bool bitsLT(EVT VT) const { + return getSizeInBits() < VT.getSizeInBits(); + } + + /// bitsLE - Return true if this has no more bits than VT. + bool bitsLE(EVT VT) const { + return getSizeInBits() <= VT.getSizeInBits(); + } + + + /// getSimpleVT - Return the SimpleValueType held in the specified + /// simple EVT. + MVT getSimpleVT() const { + assert(isSimple() && "Expected a SimpleValueType!"); + return V; + } + + /// getVectorElementType - Given a vector type, return the type of + /// each element. + EVT getVectorElementType() const { + assert(isVector() && "Invalid vector type!"); + if (isSimple()) + return V.getVectorElementType(); + else + return getExtendedVectorElementType(); + } + + /// getVectorNumElements - Given a vector type, return the number of + /// elements it contains. + unsigned getVectorNumElements() const { + assert(isVector() && "Invalid vector type!"); + if (isSimple()) + return V.getVectorNumElements(); + else + return getExtendedVectorNumElements(); + } + + /// getSizeInBits - Return the size of the specified value type in bits. + unsigned getSizeInBits() const { + if (isSimple()) + return V.getSizeInBits(); + else + return getExtendedSizeInBits(); + } + + /// getStoreSize - Return the number of bytes overwritten by a store + /// of the specified value type. + unsigned getStoreSize() const { + return (getSizeInBits() + 7) / 8; + } + + /// getStoreSizeInBits - Return the number of bits overwritten by a store + /// of the specified value type. + unsigned getStoreSizeInBits() const { + return getStoreSize() * 8; + } + + /// getRoundIntegerType - Rounds the bit-width of the given integer EVT up + /// to the nearest power of two (and at least to eight), and returns the + /// integer EVT with that number of bits. + EVT getRoundIntegerType(LLVMContext &Context) const { + assert(isInteger() && !isVector() && "Invalid integer type!"); + unsigned BitWidth = getSizeInBits(); + if (BitWidth <= 8) + return EVT(MVT::i8); + else + return getIntegerVT(Context, 1 << Log2_32_Ceil(BitWidth)); + } + + /// isPow2VectorType - Retuns true if the given vector is a power of 2. + bool isPow2VectorType() const { + unsigned NElts = getVectorNumElements(); + return !(NElts & (NElts - 1)); + } + + /// getPow2VectorType - Widens the length of the given vector EVT up to + /// the nearest power of 2 and returns that type. + EVT getPow2VectorType(LLVMContext &Context) const { + if (!isPow2VectorType()) { + unsigned NElts = getVectorNumElements(); + unsigned Pow2NElts = 1 << Log2_32_Ceil(NElts); + return EVT::getVectorVT(Context, getVectorElementType(), Pow2NElts); + } + else { + return *this; + } + } + + /// getEVTString - This function returns value type as a string, + /// e.g. "i32". + std::string getEVTString() const; + + /// getTypeForEVT - This method returns an LLVM type corresponding to the + /// specified EVT. For integer types, this returns an unsigned type. Note + /// that this will abort for types that cannot be represented. + const Type *getTypeForEVT(LLVMContext &Context) const; + + /// getEVT - Return the value type corresponding to the specified type. + /// This returns all pointers as iPTR. If HandleUnknown is true, unknown + /// types are returned as Other, otherwise they are invalid. + static EVT getEVT(const Type *Ty, bool HandleUnknown = false); + + intptr_t getRawBits() { + if (V.SimpleTy <= MVT::LastSimpleValueType) + return V.SimpleTy; + else + return (intptr_t)(LLVMTy); + } + + /// compareRawBits - A meaningless but well-behaved order, useful for + /// constructing containers. + struct compareRawBits { + bool operator()(EVT L, EVT R) const { + if (L.V.SimpleTy == R.V.SimpleTy) + return L.LLVMTy < R.LLVMTy; + else + return L.V.SimpleTy < R.V.SimpleTy; + } + }; + + private: + // Methods for handling the Extended-type case in functions above. + // These are all out-of-line to prevent users of this header file + // from having a dependency on Type.h. + static EVT getExtendedIntegerVT(LLVMContext &C, unsigned BitWidth); + static EVT getExtendedVectorVT(LLVMContext &C, EVT VT, + unsigned NumElements); + bool isExtendedFloatingPoint() const; + bool isExtendedInteger() const; + bool isExtendedVector() const; + bool isExtended64BitVector() const; + bool isExtended128BitVector() const; + bool isExtended256BitVector() const; + EVT getExtendedVectorElementType() const; + unsigned getExtendedVectorNumElements() const; + unsigned getExtendedSizeInBits() const; + }; + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/CodeGen/ValueTypes.td b/libclamav/c++/llvm/include/llvm/CodeGen/ValueTypes.td new file mode 100644 index 000000000..986555b97 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/CodeGen/ValueTypes.td @@ -0,0 +1,75 @@ +//===- ValueTypes.td - ValueType definitions ---------------*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Value types - These values correspond to the register types defined in the +// ValueTypes.h file. If you update anything here, you must update it there as +// well! +// +//===----------------------------------------------------------------------===// + +class ValueType { + string Namespace = "MVT"; + int Size = size; + int Value = value; +} + +def OtherVT: ValueType<0 , 0>; // "Other" value +def i1 : ValueType<1 , 1>; // One bit boolean value +def i8 : ValueType<8 , 2>; // 8-bit integer value +def i16 : ValueType<16 , 3>; // 16-bit integer value +def i32 : ValueType<32 , 4>; // 32-bit integer value +def i64 : ValueType<64 , 5>; // 64-bit integer value +def i128 : ValueType<128, 6>; // 128-bit integer value +def f32 : ValueType<32 , 7>; // 32-bit floating point value +def f64 : ValueType<64 , 8>; // 64-bit floating point value +def f80 : ValueType<80 , 9>; // 80-bit floating point value +def f128 : ValueType<128, 10>; // 128-bit floating point value +def ppcf128: ValueType<128, 11>; // PPC 128-bit floating point value +def FlagVT : ValueType<0 , 12>; // Condition code or machine flag +def isVoid : ValueType<0 , 13>; // Produces no value + +def v2i8 : ValueType<16 , 14>; // 2 x i8 vector value +def v4i8 : ValueType<32 , 15>; // 4 x i8 vector value +def v8i8 : ValueType<64 , 16>; // 8 x i8 vector value +def v16i8 : ValueType<128, 17>; // 16 x i8 vector value +def v32i8 : ValueType<256, 18>; // 32 x i8 vector value +def v2i16 : ValueType<32 , 19>; // 2 x i16 vector value +def v4i16 : ValueType<64 , 20>; // 4 x i16 vector value +def v8i16 : ValueType<128, 21>; // 8 x i16 vector value +def v16i16 : ValueType<256, 22>; // 16 x i16 vector value +def v2i32 : ValueType<64 , 23>; // 2 x i32 vector value +def v4i32 : ValueType<128, 24>; // 4 x i32 vector value +def v8i32 : ValueType<256, 25>; // 8 x i32 vector value +def v1i64 : ValueType<64 , 26>; // 1 x i64 vector value +def v2i64 : ValueType<128, 27>; // 2 x i64 vector value +def v4i64 : ValueType<256, 28>; // 4 x f64 vector value + +def v2f32 : ValueType<64, 29>; // 2 x f32 vector value +def v4f32 : ValueType<128, 30>; // 4 x f32 vector value +def v8f32 : ValueType<256, 31>; // 8 x f32 vector value +def v2f64 : ValueType<128, 32>; // 2 x f64 vector value +def v4f64 : ValueType<256, 33>; // 4 x f64 vector value + +def MetadataVT: ValueType<0, 250>; // Metadata + +// Pseudo valuetype mapped to the current pointer size to any address space. +// Should only be used in TableGen. +def iPTRAny : ValueType<0, 251>; + +// Pseudo valuetype to represent "vector of any size" +def vAny : ValueType<0 , 252>; + +// Pseudo valuetype to represent "float of any format" +def fAny : ValueType<0 , 253>; + +// Pseudo valuetype to represent "integer of any bit width" +def iAny : ValueType<0 , 254>; + +// Pseudo valuetype mapped to the current pointer size. +def iPTR : ValueType<0 , 255>; diff --git a/libclamav/c++/llvm/include/llvm/CompilerDriver/Action.h b/libclamav/c++/llvm/include/llvm/CompilerDriver/Action.h new file mode 100644 index 000000000..70141393c --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/CompilerDriver/Action.h @@ -0,0 +1,50 @@ +//===--- Action.h - The LLVM Compiler Driver --------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open +// Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Action - encapsulates a single shell command. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_INCLUDE_COMPILER_DRIVER_ACTION_H +#define LLVM_INCLUDE_COMPILER_DRIVER_ACTION_H + +#include +#include + +namespace llvmc { + + typedef std::vector StrVector; + + /// Action - A class that encapsulates a single shell command. + class Action { + /// Command_ - The actual command (for example, 'ls'). + std::string Command_; + /// Args_ - Command arguments. Stdout redirection ("> file") is allowed. + std::vector Args_; + /// StopCompilation_ - Should we stop compilation after executing + /// this action? + bool StopCompilation_; + /// OutFile_ - The output file name. + std::string OutFile_; + + public: + Action (const std::string& C, const StrVector& A, + bool S, const std::string& O) + : Command_(C), Args_(A), StopCompilation_(S), OutFile_(O) + {} + + /// Execute - Executes the represented action. + int Execute () const; + bool StopCompilation () const { return StopCompilation_; } + const std::string& OutFile() { return OutFile_; } + }; + +} + +#endif // LLVM_INCLUDE_COMPILER_DRIVER_ACTION_H diff --git a/libclamav/c++/llvm/include/llvm/CompilerDriver/BuiltinOptions.h b/libclamav/c++/llvm/include/llvm/CompilerDriver/BuiltinOptions.h new file mode 100644 index 000000000..0c1bbe258 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/CompilerDriver/BuiltinOptions.h @@ -0,0 +1,35 @@ +//===--- BuiltinOptions.h - The LLVM Compiler Driver ------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open +// Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Declarations of all global command-line option variables. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_INCLUDE_COMPILER_DRIVER_BUILTIN_OPTIONS_H +#define LLVM_INCLUDE_COMPILER_DRIVER_BUILTIN_OPTIONS_H + +#include "llvm/Support/CommandLine.h" + +#include + +namespace SaveTempsEnum { enum Values { Cwd, Obj, Unset }; } + +extern llvm::cl::list InputFilenames; +extern llvm::cl::opt OutputFilename; +extern llvm::cl::opt TempDirname; +extern llvm::cl::list Languages; +extern llvm::cl::opt DryRun; +extern llvm::cl::opt Time; +extern llvm::cl::opt VerboseMode; +extern llvm::cl::opt CheckGraph; +extern llvm::cl::opt ViewGraph; +extern llvm::cl::opt WriteGraph; +extern llvm::cl::opt SaveTemps; + +#endif // LLVM_INCLUDE_COMPILER_DRIVER_BUILTIN_OPTIONS_H diff --git a/libclamav/c++/llvm/include/llvm/CompilerDriver/Common.td b/libclamav/c++/llvm/include/llvm/CompilerDriver/Common.td new file mode 100644 index 000000000..79edb0260 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/CompilerDriver/Common.td @@ -0,0 +1,137 @@ +//===- Common.td - Common definitions for LLVMC2 ----------*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains common definitions used in llvmc tool description files. +// +//===----------------------------------------------------------------------===// + +class Tool l> { + list properties = l; +} + +// Possible Tool properties. + +def in_language; +def out_language; +def output_suffix; +def cmd_line; +def join; +def sink; +def actions; + +// Possible option types. + +def alias_option; +def switch_option; +def parameter_option; +def parameter_list_option; +def prefix_option; +def prefix_list_option; + +// Possible option properties. + +def extern; +def help; +def hidden; +def init; +def multi_val; +def one_or_more; +def really_hidden; +def required; +def zero_or_one; + +// The 'case' construct. +def case; + +// Boolean constants. +def true; +def false; + +// Boolean operators. +def and; +def or; +def not; + +// Primitive tests. +def switch_on; +def parameter_equals; +def element_in_list; +def input_languages_contain; +def empty; +def not_empty; +def default; +def single_input_file; +def multiple_input_files; +def any_switch_on; +def any_not_empty; +def any_empty; + +// Possible actions. + +def append_cmd; +def forward; +def forward_as; +def stop_compilation; +def unpack_values; +def warning; +def error; +def unset_option; + +// Increase/decrease the edge weight. +def inc_weight; +def dec_weight; + +// Empty DAG marker. +def empty_dag_marker; + +// Used to specify plugin priority. +class PluginPriority { + int priority = p; +} + +// Option list - a single place to specify options. +class OptionList l> { + list options = l; +} + +// Option preprocessor - actions taken during plugin loading. +class OptionPreprocessor { + dag preprocessor = d; +} + +// Map from suffixes to language names + +class LangToSuffixes lst> { + string lang = str; + list suffixes = lst; +} + +class LanguageMap lst> { + list map = lst; +} + +// Compilation graph + +class EdgeBase { + string a = t1; + string b = t2; + dag weight = d; +} + +class Edge : EdgeBase; + +// Edge and SimpleEdge are synonyms. +class SimpleEdge : EdgeBase; + +// Optionally enabled edge. +class OptionalEdge : EdgeBase; + +class CompilationGraph lst> { + list edges = lst; +} diff --git a/libclamav/c++/llvm/include/llvm/CompilerDriver/CompilationGraph.h b/libclamav/c++/llvm/include/llvm/CompilerDriver/CompilationGraph.h new file mode 100644 index 000000000..ba6ff4714 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/CompilerDriver/CompilationGraph.h @@ -0,0 +1,325 @@ +//===--- CompilationGraph.h - The LLVM Compiler Driver ----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open +// Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Compilation graph - definition. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_INCLUDE_COMPILER_DRIVER_COMPILATION_GRAPH_H +#define LLVM_INCLUDE_COMPILER_DRIVER_COMPILATION_GRAPH_H + +#include "llvm/CompilerDriver/Tool.h" + +#include "llvm/ADT/GraphTraits.h" +#include "llvm/ADT/IntrusiveRefCntPtr.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringSet.h" +#include "llvm/System/Path.h" + +#include +#include + +namespace llvmc { + + class CompilationGraph; + typedef llvm::StringSet<> InputLanguagesSet; + + /// LanguageMap - Maps from extensions to language names. + class LanguageMap : public llvm::StringMap { + public: + + /// GetLanguage - Find the language name corresponding to a given file. + const std::string& GetLanguage(const llvm::sys::Path&) const; + }; + + /// Edge - Represents an edge of the compilation graph. + class Edge : public llvm::RefCountedBaseVPTR { + public: + Edge(const std::string& T) : ToolName_(T) {} + virtual ~Edge() {} + + const std::string& ToolName() const { return ToolName_; } + virtual unsigned Weight(const InputLanguagesSet& InLangs) const = 0; + private: + std::string ToolName_; + }; + + /// SimpleEdge - An edge that has no properties. + class SimpleEdge : public Edge { + public: + SimpleEdge(const std::string& T) : Edge(T) {} + unsigned Weight(const InputLanguagesSet&) const { return 1; } + }; + + /// Node - A node (vertex) of the compilation graph. + struct Node { + // A Node holds a list of the outward edges. + typedef llvm::SmallVector, 3> container_type; + typedef container_type::iterator iterator; + typedef container_type::const_iterator const_iterator; + + Node() : OwningGraph(0), InEdges(0) {} + Node(CompilationGraph* G) : OwningGraph(G), InEdges(0) {} + Node(CompilationGraph* G, Tool* T) : + OwningGraph(G), ToolPtr(T), InEdges(0) {} + + bool HasChildren() const { return !OutEdges.empty(); } + const std::string Name() const + { return ToolPtr ? ToolPtr->Name() : "root"; } + + // Iteration. + iterator EdgesBegin() { return OutEdges.begin(); } + const_iterator EdgesBegin() const { return OutEdges.begin(); } + iterator EdgesEnd() { return OutEdges.end(); } + const_iterator EdgesEnd() const { return OutEdges.end(); } + + /// AddEdge - Add an outward edge. Takes ownership of the provided + /// Edge object. + void AddEdge(Edge* E); + + // Inward edge counter. Used to implement topological sort. + void IncrInEdges() { ++InEdges; } + void DecrInEdges() { --InEdges; } + bool HasNoInEdges() const { return InEdges == 0; } + + // Needed to implement NodeChildIterator/GraphTraits + CompilationGraph* OwningGraph; + // The corresponding Tool. + // WARNING: ToolPtr can be NULL (for the root node). + llvm::IntrusiveRefCntPtr ToolPtr; + // Links to children. + container_type OutEdges; + // Inward edge counter. Updated in + // CompilationGraph::insertEdge(). Used for topological sorting. + unsigned InEdges; + }; + + class NodesIterator; + + /// CompilationGraph - The compilation graph itself. + class CompilationGraph { + /// nodes_map_type - The main data structure. + typedef llvm::StringMap nodes_map_type; + /// tools_vector_type, tools_map_type - Data structures used to + /// map from language names to tools. (We can have several tools + /// associated with each language name, hence the need for a + /// vector.) + typedef + llvm::SmallVector, 3> tools_vector_type; + typedef llvm::StringMap tools_map_type; + + /// ToolsMap - Map from language names to lists of tool names. + tools_map_type ToolsMap; + /// NodesMap - Map from tool names to Tool objects. + nodes_map_type NodesMap; + + public: + + typedef nodes_map_type::iterator nodes_iterator; + typedef nodes_map_type::const_iterator const_nodes_iterator; + + CompilationGraph(); + + /// insertNode - Insert a new node into the graph. Takes + /// ownership of the object. + void insertNode(Tool* T); + + /// insertEdge - Insert a new edge into the graph. Takes ownership + /// of the Edge object. + void insertEdge(const std::string& A, Edge* E); + + /// Build - Build target(s) from the input file set. Command-line + /// options are passed implicitly as global variables. + int Build(llvm::sys::Path const& TempDir, const LanguageMap& LangMap); + + /// Check - Check the compilation graph for common errors like + /// cycles, input/output language mismatch and multiple default + /// edges. Prints error messages and in case it finds any errors. + int Check(); + + /// getNode - Return a reference to the node correponding to the + /// given tool name. Throws std::runtime_error. + Node& getNode(const std::string& ToolName); + const Node& getNode(const std::string& ToolName) const; + + /// viewGraph - This function is meant for use from the debugger. + /// You can just say 'call G->viewGraph()' and a ghostview window + /// should pop up from the program, displaying the compilation + /// graph. This depends on there being a 'dot' and 'gv' program + /// in your path. + void viewGraph(); + + /// writeGraph - Write Graphviz .dot source file to the current direcotry. + void writeGraph(const std::string& OutputFilename); + + // GraphTraits support. + friend NodesIterator GraphBegin(CompilationGraph*); + friend NodesIterator GraphEnd(CompilationGraph*); + + private: + // Helper functions. + + /// getToolsVector - Return a reference to the list of tool names + /// corresponding to the given language name. Throws + /// std::runtime_error. + const tools_vector_type& getToolsVector(const std::string& LangName) const; + + /// PassThroughGraph - Pass the input file through the toolchain + /// starting at StartNode. + void PassThroughGraph (const llvm::sys::Path& In, const Node* StartNode, + const InputLanguagesSet& InLangs, + const llvm::sys::Path& TempDir, + const LanguageMap& LangMap) const; + + /// FindToolChain - Find head of the toolchain corresponding to + /// the given file. + const Node* FindToolChain(const llvm::sys::Path& In, + const std::string* ForceLanguage, + InputLanguagesSet& InLangs, + const LanguageMap& LangMap) const; + + /// BuildInitial - Traverse the initial parts of the toolchains. + void BuildInitial(InputLanguagesSet& InLangs, + const llvm::sys::Path& TempDir, + const LanguageMap& LangMap); + + /// TopologicalSort - Sort the nodes in topological order. + void TopologicalSort(std::vector& Out); + /// TopologicalSortFilterJoinNodes - Call TopologicalSort and + /// filter the resulting list to include only Join nodes. + void TopologicalSortFilterJoinNodes(std::vector& Out); + + // Functions used to implement Check(). + + /// CheckLanguageNames - Check that output/input language names + /// match for all nodes. + int CheckLanguageNames() const; + /// CheckMultipleDefaultEdges - check that there are no multiple + /// default default edges. + int CheckMultipleDefaultEdges() const; + /// CheckCycles - Check that there are no cycles in the graph. + int CheckCycles(); + + }; + + // GraphTraits support code. + + /// NodesIterator - Auxiliary class needed to implement GraphTraits + /// support. Can be generalised to something like value_iterator + /// for map-like containers. + class NodesIterator : public CompilationGraph::nodes_iterator { + typedef CompilationGraph::nodes_iterator super; + typedef NodesIterator ThisType; + typedef Node* pointer; + typedef Node& reference; + + public: + NodesIterator(super I) : super(I) {} + + inline reference operator*() const { + return super::operator->()->second; + } + inline pointer operator->() const { + return &super::operator->()->second; + } + }; + + inline NodesIterator GraphBegin(CompilationGraph* G) { + return NodesIterator(G->NodesMap.begin()); + } + + inline NodesIterator GraphEnd(CompilationGraph* G) { + return NodesIterator(G->NodesMap.end()); + } + + + /// NodeChildIterator - Another auxiliary class needed by GraphTraits. + class NodeChildIterator : public + std::iterator { + typedef NodeChildIterator ThisType; + typedef Node::container_type::iterator iterator; + + CompilationGraph* OwningGraph; + iterator EdgeIter; + public: + typedef Node* pointer; + typedef Node& reference; + + NodeChildIterator(Node* N, iterator I) : + OwningGraph(N->OwningGraph), EdgeIter(I) {} + + const ThisType& operator=(const ThisType& I) { + assert(OwningGraph == I.OwningGraph); + EdgeIter = I.EdgeIter; + return *this; + } + + inline bool operator==(const ThisType& I) const { + assert(OwningGraph == I.OwningGraph); + return EdgeIter == I.EdgeIter; + } + inline bool operator!=(const ThisType& I) const { + return !this->operator==(I); + } + + inline pointer operator*() const { + return &OwningGraph->getNode((*EdgeIter)->ToolName()); + } + inline pointer operator->() const { + return this->operator*(); + } + + ThisType& operator++() { ++EdgeIter; return *this; } // Preincrement + ThisType operator++(int) { // Postincrement + ThisType tmp = *this; + ++*this; + return tmp; + } + + inline ThisType& operator--() { --EdgeIter; return *this; } // Predecrement + inline ThisType operator--(int) { // Postdecrement + ThisType tmp = *this; + --*this; + return tmp; + } + + }; +} + +namespace llvm { + template <> + struct GraphTraits { + typedef llvmc::CompilationGraph GraphType; + typedef llvmc::Node NodeType; + typedef llvmc::NodeChildIterator ChildIteratorType; + + static NodeType* getEntryNode(GraphType* G) { + return &G->getNode("root"); + } + + static ChildIteratorType child_begin(NodeType* N) { + return ChildIteratorType(N, N->OutEdges.begin()); + } + static ChildIteratorType child_end(NodeType* N) { + return ChildIteratorType(N, N->OutEdges.end()); + } + + typedef llvmc::NodesIterator nodes_iterator; + static nodes_iterator nodes_begin(GraphType *G) { + return GraphBegin(G); + } + static nodes_iterator nodes_end(GraphType *G) { + return GraphEnd(G); + } + }; + +} + +#endif // LLVM_INCLUDE_COMPILER_DRIVER_COMPILATION_GRAPH_H diff --git a/libclamav/c++/llvm/include/llvm/CompilerDriver/Error.h b/libclamav/c++/llvm/include/llvm/CompilerDriver/Error.h new file mode 100644 index 000000000..fa678cfbf --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/CompilerDriver/Error.h @@ -0,0 +1,35 @@ +//===--- Error.h - The LLVM Compiler Driver ---------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open +// Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Exception classes for llvmc. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_INCLUDE_COMPILER_DRIVER_ERROR_H +#define LLVM_INCLUDE_COMPILER_DRIVER_ERROR_H + +#include + +namespace llvmc { + + /// error_code - This gets thrown during the compilation process if a tool + /// invocation returns a non-zero exit code. + class error_code: public std::runtime_error { + int Code_; + public: + error_code (int c) + : std::runtime_error("Tool returned error code"), Code_(c) + {} + + int code() const { return Code_; } + }; + +} + +#endif // LLVM_INCLUDE_COMPILER_DRIVER_ERROR_H diff --git a/libclamav/c++/llvm/include/llvm/CompilerDriver/ForceLinkage.h b/libclamav/c++/llvm/include/llvm/CompilerDriver/ForceLinkage.h new file mode 100644 index 000000000..830c04e2d --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/CompilerDriver/ForceLinkage.h @@ -0,0 +1,122 @@ +//===--- ForceLinkage.h - The LLVM Compiler Driver --------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open +// Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// A bit of preprocessor magic to force references to static libraries. Needed +// because plugin initialization is done via static variables. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_INCLUDE_COMPILER_DRIVER_FORCE_LINKAGE_H +#define LLVM_INCLUDE_COMPILER_DRIVER_FORCE_LINKAGE_H + +#include "llvm/CompilerDriver/ForceLinkageMacros.h" + +namespace llvmc { + +// Declare all ForceLinkage$(PluginName) functions. + +#ifdef LLVMC_BUILTIN_PLUGIN_1 + LLVMC_FORCE_LINKAGE_DECL(LLVMC_BUILTIN_PLUGIN_1); +#endif + +#ifdef LLVMC_BUILTIN_PLUGIN_2 + LLVMC_FORCE_LINKAGE_DECL(LLVMC_BUILTIN_PLUGIN_2); +#endif + +#ifdef LLVMC_BUILTIN_PLUGIN_3 + LLVMC_FORCE_LINKAGE_DECL(LLVMC_BUILTIN_PLUGIN_3); +#endif + +#ifdef LLVMC_BUILTIN_PLUGIN_4 + LLVMC_FORCE_LINKAGE_DECL(LLVMC_BUILTIN_PLUGIN_4); +#endif + +#ifdef LLVMC_BUILTIN_PLUGIN_5 + LLVMC_FORCE_LINKAGE_DECL(LLVMC_BUILTIN_PLUGIN_5); +#endif + +#ifdef LLVMC_BUILTIN_PLUGIN_6 + LLVMC_FORCE_LINKAGE_DECL(LLVMC_BUILTIN_PLUGIN_6); +#endif + +#ifdef LLVMC_BUILTIN_PLUGIN_7 + LLVMC_FORCE_LINKAGE_DECL(LLVMC_BUILTIN_PLUGIN_7); +#endif + +#ifdef LLVMC_BUILTIN_PLUGIN_8 + LLVMC_FORCE_LINKAGE_DECL(LLVMC_BUILTIN_PLUGIN_8); +#endif + +#ifdef LLVMC_BUILTIN_PLUGIN_9 + LLVMC_FORCE_LINKAGE_DECL(LLVMC_BUILTIN_PLUGIN_9); +#endif + +#ifdef LLVMC_BUILTIN_PLUGIN_10 + LLVMC_FORCE_LINKAGE_DECL(LLVMC_BUILTIN_PLUGIN_10); +#endif + +namespace force_linkage { + + struct LinkageForcer { + + LinkageForcer() { + +// Call all ForceLinkage$(PluginName) functions. +#ifdef LLVMC_BUILTIN_PLUGIN_1 + LLVMC_FORCE_LINKAGE_CALL(LLVMC_BUILTIN_PLUGIN_1); +#endif + +#ifdef LLVMC_BUILTIN_PLUGIN_2 + LLVMC_FORCE_LINKAGE_CALL(LLVMC_BUILTIN_PLUGIN_2); +#endif + +#ifdef LLVMC_BUILTIN_PLUGIN_3 + LLVMC_FORCE_LINKAGE_CALL(LLVMC_BUILTIN_PLUGIN_3); +#endif + +#ifdef LLVMC_BUILTIN_PLUGIN_4 + LLVMC_FORCE_LINKAGE_CALL(LLVMC_BUILTIN_PLUGIN_4); +#endif + +#ifdef LLVMC_BUILTIN_PLUGIN_5 + LLVMC_FORCE_LINKAGE_CALL(LLVMC_BUILTIN_PLUGIN_5); +#endif + +#ifdef LLVMC_BUILTIN_PLUGIN_6 + LLVMC_FORCE_LINKAGE_CALL(LLVMC_BUILTIN_PLUGIN_6); +#endif + +#ifdef LLVMC_BUILTIN_PLUGIN_7 + LLVMC_FORCE_LINKAGE_CALL(LLVMC_BUILTIN_PLUGIN_7); +#endif + +#ifdef LLVMC_BUILTIN_PLUGIN_8 + LLVMC_FORCE_LINKAGE_CALL(LLVMC_BUILTIN_PLUGIN_8); +#endif + +#ifdef LLVMC_BUILTIN_PLUGIN_9 + LLVMC_FORCE_LINKAGE_CALL(LLVMC_BUILTIN_PLUGIN_9); +#endif + +#ifdef LLVMC_BUILTIN_PLUGIN_10 + LLVMC_FORCE_LINKAGE_CALL(LLVMC_BUILTIN_PLUGIN_10); +#endif + + } + }; +} // End namespace force_linkage. + +// The only externally used bit. +void ForceLinkage() { + force_linkage::LinkageForcer dummy; +} + +} // End namespace llvmc. + +#endif // LLVM_INCLUDE_COMPILER_DRIVER_FORCE_LINKAGE_H diff --git a/libclamav/c++/llvm/include/llvm/CompilerDriver/ForceLinkageMacros.h b/libclamav/c++/llvm/include/llvm/CompilerDriver/ForceLinkageMacros.h new file mode 100644 index 000000000..8862b0082 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/CompilerDriver/ForceLinkageMacros.h @@ -0,0 +1,29 @@ +//===--- ForceLinkageMacros.h - The LLVM Compiler Driver --------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open +// Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Preprocessor magic that forces references to static libraries - common +// macros used by both driver and plugins. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_INCLUDE_COMPILER_DRIVER_FORCE_LINKAGE_MACROS_H +#define LLVM_INCLUDE_COMPILER_DRIVER_FORCE_LINKAGE_MACROS_H + +#define LLVMC_FORCE_LINKAGE_PREFIX(PluginName) ForceLinkage ## PluginName + +#define LLVMC_FORCE_LINKAGE_FUN(PluginName) \ + LLVMC_FORCE_LINKAGE_PREFIX(PluginName) + +#define LLVMC_FORCE_LINKAGE_DECL(PluginName) \ + void LLVMC_FORCE_LINKAGE_FUN(PluginName) () + +#define LLVMC_FORCE_LINKAGE_CALL(PluginName) \ + LLVMC_FORCE_LINKAGE_FUN(PluginName) () + +#endif // LLVM_INCLUDE_COMPILER_DRIVER_FORCE_LINKAGE_MACROS_H diff --git a/libclamav/c++/llvm/include/llvm/CompilerDriver/Main.inc b/libclamav/c++/llvm/include/llvm/CompilerDriver/Main.inc new file mode 100644 index 000000000..fc8b5035e --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/CompilerDriver/Main.inc @@ -0,0 +1,33 @@ +//===--- Main.inc - The LLVM Compiler Driver --------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open +// Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This tool provides a single point of access to the LLVM +// compilation tools. It has many options. To discover the options +// supported please refer to the tools' manual page or run the tool +// with the --help option. +// +// This file provides the default entry point for the driver executable. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_INCLUDE_COMPILER_DRIVER_MAIN_INC +#define LLVM_INCLUDE_COMPILER_DRIVER_MAIN_INC + +#include "llvm/CompilerDriver/ForceLinkage.h" + +namespace llvmc { + int Main(int argc, char** argv); +} + +int main(int argc, char** argv) { + llvmc::ForceLinkage(); + return llvmc::Main(argc, argv); +} + +#endif // LLVM_INCLUDE_COMPILER_DRIVER_MAIN_INC diff --git a/libclamav/c++/llvm/include/llvm/CompilerDriver/Plugin.h b/libclamav/c++/llvm/include/llvm/CompilerDriver/Plugin.h new file mode 100644 index 000000000..e9a20488a --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/CompilerDriver/Plugin.h @@ -0,0 +1,81 @@ +//===--- Plugin.h - The LLVM Compiler Driver --------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open +// Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Plugin support for llvmc. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_INCLUDE_COMPILER_DRIVER_PLUGIN_H +#define LLVM_INCLUDE_COMPILER_DRIVER_PLUGIN_H + +#include "llvm/Support/Registry.h" + +namespace llvmc { + + class LanguageMap; + class CompilationGraph; + + /// BasePlugin - An abstract base class for all LLVMC plugins. + struct BasePlugin { + + /// Priority - Plugin priority, useful for handling dependencies + /// between plugins. Plugins with lower priorities are loaded + /// first. + virtual int Priority() const { return 0; } + + /// PreprocessOptions - The auto-generated function that performs various + /// consistency checks on options (like ensuring that -O2 and -O3 are not + /// used together). + virtual void PreprocessOptions() const = 0; + + /// PopulateLanguageMap - The auto-generated function that fills in + /// the language map (map from file extensions to language names). + virtual void PopulateLanguageMap(LanguageMap&) const = 0; + + /// PopulateCompilationGraph - The auto-generated function that + /// populates the compilation graph with nodes and edges. + virtual void PopulateCompilationGraph(CompilationGraph&) const = 0; + + /// Needed to avoid a compiler warning. + virtual ~BasePlugin() {} + }; + + typedef llvm::Registry PluginRegistry; + + template + struct RegisterPlugin + : public PluginRegistry::Add

    { + typedef PluginRegistry::Add

    Base; + + RegisterPlugin(const char* Name = "Nameless", + const char* Desc = "Auto-generated plugin") + : Base(Name, Desc) {} + }; + + + /// PluginLoader - Helper class used by the main program for + /// lifetime management. + struct PluginLoader { + PluginLoader(); + ~PluginLoader(); + + /// RunInitialization - Calls PreprocessOptions, PopulateLanguageMap and + /// PopulateCompilationGraph methods of all plugins. This populates the + /// global language map and the compilation graph. + void RunInitialization(LanguageMap& langMap, CompilationGraph& graph) const; + + private: + // noncopyable + PluginLoader(const PluginLoader& other); + const PluginLoader& operator=(const PluginLoader& other); + }; + +} + +#endif // LLVM_INCLUDE_COMPILER_DRIVER_PLUGIN_H diff --git a/libclamav/c++/llvm/include/llvm/CompilerDriver/Tool.h b/libclamav/c++/llvm/include/llvm/CompilerDriver/Tool.h new file mode 100644 index 000000000..a982e2d39 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/CompilerDriver/Tool.h @@ -0,0 +1,85 @@ +//===--- Tool.h - The LLVM Compiler Driver ----------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open +// Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Tool abstract base class - an interface to tool descriptions. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_INCLUDE_COMPILER_DRIVER_TOOL_H +#define LLVM_INCLUDE_COMPILER_DRIVER_TOOL_H + +#include "llvm/CompilerDriver/Action.h" + +#include "llvm/ADT/IntrusiveRefCntPtr.h" +#include "llvm/ADT/StringSet.h" +#include "llvm/System/Path.h" + +#include + +namespace llvmc { + + class LanguageMap; + typedef std::vector PathVector; + typedef llvm::StringSet<> InputLanguagesSet; + + /// Tool - A class + class Tool : public llvm::RefCountedBaseVPTR { + public: + + virtual ~Tool() {} + + virtual Action GenerateAction (const PathVector& inFiles, + bool HasChildren, + const llvm::sys::Path& TempDir, + const InputLanguagesSet& InLangs, + const LanguageMap& LangMap) const = 0; + + virtual Action GenerateAction (const llvm::sys::Path& inFile, + bool HasChildren, + const llvm::sys::Path& TempDir, + const InputLanguagesSet& InLangs, + const LanguageMap& LangMap) const = 0; + + virtual const char* Name() const = 0; + virtual const char** InputLanguages() const = 0; + virtual const char* OutputLanguage() const = 0; + + virtual bool IsJoin() const = 0; + + protected: + /// OutFileName - Generate the output file name. + llvm::sys::Path OutFilename(const llvm::sys::Path& In, + const llvm::sys::Path& TempDir, + bool StopCompilation, + const char* OutputSuffix) const; + }; + + /// JoinTool - A Tool that has an associated input file list. + class JoinTool : public Tool { + public: + void AddToJoinList(const llvm::sys::Path& P) { JoinList_.push_back(P); } + void ClearJoinList() { JoinList_.clear(); } + bool JoinListEmpty() const { return JoinList_.empty(); } + + Action GenerateAction(bool HasChildren, + const llvm::sys::Path& TempDir, + const InputLanguagesSet& InLangs, + const LanguageMap& LangMap) const { + return GenerateAction(JoinList_, HasChildren, TempDir, InLangs, LangMap); + } + // We shouldn't shadow base class's version of GenerateAction. + using Tool::GenerateAction; + + private: + PathVector JoinList_; + }; + +} + +#endif // LLVM_INCLUDE_COMPILER_DRIVER_TOOL_H diff --git a/libclamav/c++/llvm/include/llvm/Config/AsmParsers.def.in b/libclamav/c++/llvm/include/llvm/Config/AsmParsers.def.in new file mode 100644 index 000000000..041af8375 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Config/AsmParsers.def.in @@ -0,0 +1,29 @@ +//===- llvm/Config/AsmParsers.def - LLVM Assembly Parsers -------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file enumerates all of the assembly-language parsers +// supported by this build of LLVM. Clients of this file should define +// the LLVM_ASM_PARSER macro to be a function-like macro with a +// single parameter (the name of the target whose assembly can be +// generated); including this file will then enumerate all of the +// targets with assembly parsers. +// +// The set of targets supported by LLVM is generated at configuration +// time, at which point this header is generated. Do not modify this +// header directly. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ASM_PARSER +# error Please define the macro LLVM_ASM_PARSER(TargetName) +#endif + +@LLVM_ENUM_ASM_PARSERS@ + +#undef LLVM_ASM_PARSER diff --git a/libclamav/c++/llvm/include/llvm/Config/AsmPrinters.def.in b/libclamav/c++/llvm/include/llvm/Config/AsmPrinters.def.in new file mode 100644 index 000000000..9729bd75e --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Config/AsmPrinters.def.in @@ -0,0 +1,29 @@ +//===- llvm/Config/AsmPrinters.def - LLVM Assembly Printers -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file enumerates all of the assembly-language printers +// supported by this build of LLVM. Clients of this file should define +// the LLVM_ASM_PRINTER macro to be a function-like macro with a +// single parameter (the name of the target whose assembly can be +// generated); including this file will then enumerate all of the +// targets with assembly printers. +// +// The set of targets supported by LLVM is generated at configuration +// time, at which point this header is generated. Do not modify this +// header directly. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ASM_PRINTER +# error Please define the macro LLVM_ASM_PRINTER(TargetName) +#endif + +@LLVM_ENUM_ASM_PRINTERS@ + +#undef LLVM_ASM_PRINTER diff --git a/libclamav/c++/llvm/include/llvm/Config/Disassemblers.def.in b/libclamav/c++/llvm/include/llvm/Config/Disassemblers.def.in new file mode 100644 index 000000000..1b1365709 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Config/Disassemblers.def.in @@ -0,0 +1,29 @@ +//===- llvm/Config/Disassemblers.def - LLVM Assembly Parsers ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file enumerates all of the assembly-language parsers +// supported by this build of LLVM. Clients of this file should define +// the LLVM_ASM_PARSER macro to be a function-like macro with a +// single parameter (the name of the target whose assembly can be +// generated); including this file will then enumerate all of the +// targets with assembly parsers. +// +// The set of targets supported by LLVM is generated at configuration +// time, at which point this header is generated. Do not modify this +// header directly. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DISASSEMBLER +# error Please define the macro LLVM_DISASSEMBLER(TargetName) +#endif + +@LLVM_ENUM_DISASSEMBLERS@ + +#undef LLVM_DISASSEMBLER diff --git a/libclamav/c++/llvm/include/llvm/Config/Targets.def.in b/libclamav/c++/llvm/include/llvm/Config/Targets.def.in new file mode 100644 index 000000000..d589ecee1 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Config/Targets.def.in @@ -0,0 +1,28 @@ +/*===- llvm/Config/Targets.def - LLVM Target Architectures ------*- C++ -*-===*\ +|* *| +|* The LLVM Compiler Infrastructure *| +|* *| +|* This file is distributed under the University of Illinois Open Source *| +|* License. See LICENSE.TXT for details. *| +|* *| +|*===----------------------------------------------------------------------===*| +|* *| +|* This file enumerates all of the target architectures supported by *| +|* this build of LLVM. Clients of this file should define the *| +|* LLVM_TARGET macro to be a function-like macro with a single *| +|* parameter (the name of the target); including this file will then *| +|* enumerate all of the targets. *| +|* *| +|* The set of targets supported by LLVM is generated at configuration *| +|* time, at which point this header is generated. Do not modify this *| +|* header directly. *| +|* *| +\*===----------------------------------------------------------------------===*/ + +#ifndef LLVM_TARGET +# error Please define the macro LLVM_TARGET(TargetName) +#endif + +@LLVM_ENUM_TARGETS@ + +#undef LLVM_TARGET diff --git a/libclamav/c++/llvm/include/llvm/Config/config.h.cmake b/libclamav/c++/llvm/include/llvm/Config/config.h.cmake new file mode 100644 index 000000000..1f48ae968 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Config/config.h.cmake @@ -0,0 +1,621 @@ + +/************************************** +** Created by Kevin from config.h.in ** +***************************************/ + +/* Define if dlopen(0) will open the symbols of the program */ +#undef CAN_DLOPEN_SELF + +/* Define if CBE is enabled for printf %a output */ +#undef ENABLE_CBE_PRINTF_A + +/* Directories clang will search for headers */ +#define C_INCLUDE_DIRS "${C_INCLUDE_DIRS}" + +/* Directory clang will search for libstdc++ headers */ +#define CXX_INCLUDE_ROOT "${CXX_INCLUDE_ROOT}" + +/* Architecture of libstdc++ headers */ +#define CXX_INCLUDE_ARCH "${CXX_INCLUDE_ARCH}" + +/* 32 bit multilib directory */ +#define CXX_INCLUDE_32BIT_DIR "${CXX_INCLUDE_32BIT_DIR}" + +/* 64 bit multilib directory */ +#define CXX_INCLUDE_64BIT_DIR "${CXX_INCLUDE_64BIT_DIR}" + +/* Define if position independent code is enabled */ +#cmakedefine ENABLE_PIC ${ENABLE_PIC} + +/* Define if threads enabled */ +#cmakedefine ENABLE_THREADS ${ENABLE_THREADS} + +/* Define to 1 if you have the `argz_append' function. */ +#undef HAVE_ARGZ_APPEND + +/* Define to 1 if you have the `argz_create_sep' function. */ +#undef HAVE_ARGZ_CREATE_SEP + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_ARGZ_H ${HAVE_ARGZ_H} + +/* Define to 1 if you have the `argz_insert' function. */ +#undef HAVE_ARGZ_INSERT + +/* Define to 1 if you have the `argz_next' function. */ +#undef HAVE_ARGZ_NEXT + +/* Define to 1 if you have the `argz_stringify' function. */ +#undef HAVE_ARGZ_STRINGIFY + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_ASSERT_H ${HAVE_ASSERT_H} + +/* Define to 1 if you have the `backtrace' function. */ +#undef HAVE_BACKTRACE + +/* Define to 1 if you have the `bcopy' function. */ +#undef HAVE_BCOPY + +/* Does not have bi-directional iterator */ +#undef HAVE_BI_ITERATOR + +/* Define to 1 if you have the `ceilf' function. */ +#cmakedefine HAVE_CEILF ${HAVE_CEILF} + +/* Define if the neat program is available */ +#cmakedefine HAVE_CIRCO ${HAVE_CIRCO} + +/* Define to 1 if you have the `closedir' function. */ +#undef HAVE_CLOSEDIR + +/* Define to 1 if you have the header file. */ +#undef HAVE_CTYPE_H + +/* Define to 1 if you have the header file, and it defines `DIR'. + */ +#cmakedefine HAVE_DIRENT_H ${HAVE_DIRENT_H} + +/* Define if you have the GNU dld library. */ +#undef HAVE_DLD + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_DLD_H ${HAVE_DLD_H} + +/* Define to 1 if you have the `dlerror' function. */ +#undef HAVE_DLERROR + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_DLFCN_H ${HAVE_DLFCN_H} + +/* Define if dlopen() is available on this platform. */ +#undef HAVE_DLOPEN + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_DL_H ${HAVE_DL_H} + +/* Define if the dot program is available */ +#cmakedefine HAVE_DOT ${HAVE_DOT} + +/* Define if the dotty program is available */ +#cmakedefine HAVE_DOTTY ${HAVE_DOTTY} + +/* Define if you have the _dyld_func_lookup function. */ +#undef HAVE_DYLD + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_ERRNO_H ${HAVE_ERRNO_H} + +/* Define to 1 if the system has the type `error_t'. */ +#undef HAVE_ERROR_T + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_EXECINFO_H ${HAVE_EXECINFO_H} + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_FCNTL_H ${HAVE_FCNTL_H} + +/* Define if the neat program is available */ +#cmakedefine HAVE_FDP ${HAVE_FDP} + +/* Set to 1 if the finite function is found in */ +#cmakedefine HAVE_FINITE_IN_IEEEFP_H ${HAVE_FINITE_IN_IEEEFP_H} + +/* Define to 1 if you have the `floorf' function. */ +#cmakedefine HAVE_FLOORF ${HAVE_FLOORF} + +/* Does not have forward iterator */ +#undef HAVE_FWD_ITERATOR + +/* Define to 1 if you have the `getcwd' function. */ +#undef HAVE_GETCWD + +/* Define to 1 if you have the `getpagesize' function. */ +#cmakedefine HAVE_GETPAGESIZE ${HAVE_GETPAGESIZE} + +/* Define to 1 if you have the `getrlimit' function. */ +#undef HAVE_GETRLIMIT + +/* Define to 1 if you have the `getrusage' function. */ +#cmakedefine HAVE_GETRUSAGE ${HAVE_GETRUSAGE} + +/* Define to 1 if you have the `gettimeofday' function. */ +#undef HAVE_GETTIMEOFDAY + +/* Does not have */ +#undef HAVE_GLOBAL_HASH_MAP + +/* Does not have hash_set in global namespace */ +#undef HAVE_GLOBAL_HASH_SET + +/* Does not have ext/hash_map */ +#undef HAVE_GNU_EXT_HASH_MAP + +/* Does not have hash_set in gnu namespace */ +#undef HAVE_GNU_EXT_HASH_SET + +/* Define if the Graphviz program is available */ +#undef HAVE_GRAPHVIZ + +/* Define if the gv program is available */ +#cmakedefine HAVE_GV ${HAVE_GV} + +/* Define to 1 if you have the `index' function. */ +#undef HAVE_INDEX + +/* Define to 1 if the system has the type `int64_t'. */ +#undef HAVE_INT64_T + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_INTTYPES_H ${HAVE_INTTYPES_H} + +/* Define to 1 if you have the `isatty' function. */ +#cmakedefine HAVE_ISATTY 1 + +/* Set to 1 if the isinf function is found in */ +#cmakedefine HAVE_ISINF_IN_CMATH ${HAVE_ISINF_IN_CMATH} + +/* Set to 1 if the isinf function is found in */ +#cmakedefine HAVE_ISINF_IN_MATH_H ${HAVE_ISINF_IN_MATH_H} + +/* Set to 1 if the isnan function is found in */ +#cmakedefine HAVE_ISNAN_IN_CMATH ${HAVE_ISNAN_IN_CMATH} + +/* Set to 1 if the isnan function is found in */ +#cmakedefine HAVE_ISNAN_IN_MATH_H ${HAVE_ISNAN_IN_MATH_H} + +/* Define if you have the libdl library or equivalent. */ +#undef HAVE_LIBDL + +/* Define to 1 if you have the `imagehlp' library (-limagehlp). */ +#cmakedefine HAVE_LIBIMAGEHLP ${HAVE_LIBIMAGEHLP} + +/* Define to 1 if you have the `m' library (-lm). */ +#undef HAVE_LIBM + +/* Define to 1 if you have the `psapi' library (-lpsapi). */ +#cmakedefine HAVE_LIBPSAPI ${HAVE_LIBPSAPI} + +/* Define to 1 if you have the `pthread' library (-lpthread). */ +#cmakedefine HAVE_LIBPTHREAD ${HAVE_LIBPTHREAD} + +/* Define to 1 if you have the `udis86' library (-ludis86). */ +#undef HAVE_LIBUDIS86 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_LIMITS_H ${HAVE_LIMITS_H} + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_LINK_H ${HAVE_LINK_H} + +/* Define if you can use -Wl,-R. to pass -R. to the linker, in order to add + the current directory to the dynamic linker search path. */ +#undef HAVE_LINK_R + +/* Define to 1 if you have the `longjmp' function. */ +#undef HAVE_LONGJMP + +/* Define to 1 if you have the header file. */ +#undef HAVE_MACH_MACH_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_MACH_O_DYLD_H + +/* Define if mallinfo() is available on this platform. */ +#cmakedefine HAVE_MALLINFO ${HAVE_MALLINFO} + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_MALLOC_H ${HAVE_MALLOC_H} + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_MALLOC_MALLOC_H ${HAVE_MALLOC_MALLOC_H} + +/* Define to 1 if you have the `malloc_zone_statistics' function. */ +#cmakedefine HAVE_MALLOC_ZONE_STATISTICS ${HAVE_MALLOC_ZONE_STATISTICS} + +/* Define to 1 if you have the `memcpy' function. */ +#undef HAVE_MEMCPY + +/* Define to 1 if you have the `memmove' function. */ +#undef HAVE_MEMMOVE + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_MEMORY_H ${HAVE_MEMORY_H} + +/* Define to 1 if you have the `mkdtemp' function. */ +#cmakedefine HAVE_MKDTEMP ${HAVE_MKDTEMP} + +/* Define to 1 if you have the `mkstemp' function. */ +#cmakedefine HAVE_MKSTEMP ${HAVE_MKSTEMP} + +/* Define to 1 if you have the `mktemp' function. */ +#cmakedefine HAVE_MKTEMP ${HAVE_MKTEMP} + +/* Define to 1 if you have a working `mmap' system call. */ +#undef HAVE_MMAP + +/* Define if mmap() uses MAP_ANONYMOUS to map anonymous pages, or undefine if + it uses MAP_ANON */ +#undef HAVE_MMAP_ANONYMOUS + +/* Define if mmap() can map files into memory */ +#undef HAVE_MMAP_FILE + +/* define if the compiler implements namespaces */ +#undef HAVE_NAMESPACES + +/* Define to 1 if you have the header file, and it defines `DIR'. */ +#cmakedefine HAVE_NDIR_H ${HAVE_NDIR_H} + +/* Define to 1 if you have the `nearbyintf' function. */ +#cmakedefine HAVE_NEARBYINTF ${HAVE_NEARBYINTF} + +/* Define if the neat program is available */ +#cmakedefine HAVE_NEATO ${HAVE_NEATO} + +/* Define to 1 if you have the `opendir' function. */ +#undef HAVE_OPENDIR + +/* Define if libtool can extract symbol lists from object files. */ +#undef HAVE_PRELOADED_SYMBOLS + +/* Define to have the %a format string */ +#undef HAVE_PRINTF_A + +/* Have pthread.h */ +#cmakedefine HAVE_PTHREAD_H ${HAVE_PTHREAD_H} + +/* Have pthread_mutex_lock */ +#cmakedefine HAVE_PTHREAD_MUTEX_LOCK ${HAVE_PTHREAD_MUTEX_LOCK} + +/* Have pthread_rwlock_init */ +#cmakedefine HAVE_PTHREAD_RWLOCK_INIT ${HAVE_PTHREAD_RWLOCK_INIT} + +/* Have pthread_getspecific */ +#cmakedefine HAVE_PTHREAD_GETSPECIFIC ${HAVE_PTHREAD_GETSPECIFIC} + +/* Define to 1 if srand48/lrand48/drand48 exist in */ +#undef HAVE_RAND48 + +/* Define to 1 if you have the `readdir' function. */ +#undef HAVE_READDIR + +/* Define to 1 if you have the `realpath' function. */ +#undef HAVE_REALPATH + +/* Define to 1 if you have the `rindex' function. */ +#undef HAVE_RINDEX + +/* Define to 1 if you have the `rintf' function. */ +#undef HAVE_RINTF + +/* Define to 1 if you have the `roundf' function. */ +#undef HAVE_ROUNDF + +/* Define to 1 if you have the `sbrk' function. */ +#cmakedefine HAVE_SBRK ${HAVE_SBRK} + +/* Define to 1 if you have the `setenv' function. */ +#cmakedefine HAVE_SETENV ${HAVE_SETENV} + +/* Define to 1 if you have the `setjmp' function. */ +#undef HAVE_SETJMP + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SETJMP_H ${HAVE_SETJMP_H} + +/* Define to 1 if you have the `setrlimit' function. */ +#cmakedefine HAVE_SETRLIMIT ${HAVE_SETRLIMIT} + +/* Define if you have the shl_load function. */ +#undef HAVE_SHL_LOAD + +/* Define to 1 if you have the `siglongjmp' function. */ +#undef HAVE_SIGLONGJMP + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SIGNAL_H ${HAVE_SIGNAL_H} + +/* Define to 1 if you have the `sigsetjmp' function. */ +#undef HAVE_SIGSETJMP + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_STDINT_H ${HAVE_STDINT_H} + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_STDIO_H ${HAVE_STDIO_H} + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_STDLIB_H ${HAVE_STDLIB_H} + +/* Does not have ext/hash_map> */ +#undef HAVE_STD_EXT_HASH_MAP + +/* Does not have hash_set in std namespace */ +#undef HAVE_STD_EXT_HASH_SET + +/* Set to 1 if the std::isinf function is found in */ +#undef HAVE_STD_ISINF_IN_CMATH + +/* Set to 1 if the std::isnan function is found in */ +#undef HAVE_STD_ISNAN_IN_CMATH + +/* Does not have std namespace iterator */ +#undef HAVE_STD_ITERATOR + +/* Define to 1 if you have the `strchr' function. */ +#undef HAVE_STRCHR + +/* Define to 1 if you have the `strcmp' function. */ +#undef HAVE_STRCMP + +/* Define to 1 if you have the `strdup' function. */ +#undef HAVE_STRDUP + +/* Define to 1 if you have the `strerror' function. */ +#cmakedefine HAVE_STRERROR ${HAVE_STRERROR} + +/* Define to 1 if you have the `strerror_r' function. */ +#cmakedefine HAVE_STRERROR_R ${HAVE_STRERROR_R} + +/* Define to 1 if you have the `strerror_s' function. */ +#cmakedefine HAVE_STRERROR_S ${HAVE_STRERROR_S} + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRINGS_H + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_STRING_H ${HAVE_STRING_H} + +/* Define to 1 if you have the `strrchr' function. */ +#undef HAVE_STRRCHR + +/* Define to 1 if you have the `strtoll' function. */ +#cmakedefine HAVE_STRTOLL ${HAVE_STRTOLL} + +/* Define to 1 if you have the `strtoq' function. */ +#undef HAVE_STRTOQ + +/* Define to 1 if you have the `sysconf' function. */ +#undef HAVE_SYSCONF + +/* Define to 1 if you have the header file, and it defines `DIR'. + */ +#cmakedefine HAVE_SYS_DIR_H ${HAVE_SYS_DIR_H} + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_DL_H ${HAVE_SYS_DL_H} + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_IOCTL_H ${HAVE_SYS_IOCTL_H} + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_MMAN_H ${} + +/* Define to 1 if you have the header file, and it defines `DIR'. + */ +#cmakedefine HAVE_SYS_NDIR_H ${HAVE_SYS_NDIR_H} + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_PARAM_H ${HAVE_SYS_PARAM_H} + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_RESOURCE_H ${HAVE_SYS_RESOURCE_H} + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_STAT_H ${HAVE_SYS_STAT_H} + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_TIME_H ${HAVE_SYS_TIME_H} + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_TYPES_H ${HAVE_SYS_TYPES_H} + +/* Define to 1 if you have that is POSIX.1 compatible. */ +#cmakedefine HAVE_SYS_WAIT_H ${HAVE_SYS_WAIT_H} + +/* Define if the neat program is available */ +#cmakedefine HAVE_TWOPI ${HAVE_TWOPI} + +/* Define to 1 if the system has the type `uint64_t'. */ +#undef HAVE_UINT64_T + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_TERMIOS_H ${HAVE_TERMIOS_H} + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_UNISTD_H ${HAVE_UNISTD_H} + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_UTIME_H ${HAVE_UTIME_H} + +/* Define to 1 if the system has the type `u_int64_t'. */ +#undef HAVE_U_INT64_T + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_WINDOWS_H ${HAVE_WINDOWS_H} + +/* Installation directory for binary executables */ +#undef LLVM_BINDIR + +/* Time at which LLVM was configured */ +#undef LLVM_CONFIGTIME + +/* Installation directory for documentation */ +#undef LLVM_DATADIR + +/* Installation directory for config files */ +#undef LLVM_ETCDIR + +/* Host triple we were built on */ +#cmakedefine LLVM_HOSTTRIPLE "${LLVM_HOSTTRIPLE}" + +/* Installation directory for include files */ +#undef LLVM_INCLUDEDIR + +/* Installation directory for .info files */ +#undef LLVM_INFODIR + +/* Installation directory for libraries */ +#undef LLVM_LIBDIR + +/* Installation directory for man pages */ +#undef LLVM_MANDIR + +/* Build multithreading support into LLVM */ +#cmakedefine LLVM_MULTITHREADED ${LLVM_MULTITHREADED} + +/* Define if this is Unixish platform */ +#cmakedefine LLVM_ON_UNIX ${LLVM_ON_UNIX} + +/* Define if this is Win32ish platform */ +#cmakedefine LLVM_ON_WIN32 ${LLVM_ON_WIN32} + +/* Added by Kevin -- Maximum path length */ +#cmakedefine MAXPATHLEN ${MAXPATHLEN} + +/* Define to path to circo program if found or 'echo circo' otherwise */ +#cmakedefine LLVM_PATH_CIRCO "${LLVM_PATH_CIRCO}" + +/* Define to path to dot program if found or 'echo dot' otherwise */ +#cmakedefine LLVM_PATH_DOT "${LLVM_PATH_DOT}" + +/* Define to path to dotty program if found or 'echo dotty' otherwise */ +#cmakedefine LLVM_PATH_DOTTY "${LLVM_PATH_DOTTY}" + +/* Define to path to fdp program if found or 'echo fdp' otherwise */ +#cmakedefine LLVM_PATH_FDP "${LLVM_PATH_FDP}" + +/* Define to path to Graphviz program if found or 'echo Graphviz' otherwise */ +#undef LLVM_PATH_GRAPHVIZ + +/* Define to path to gv program if found or 'echo gv' otherwise */ +#cmakedefine LLVM_PATH_GV "${LLVM_PATH_GV}" + +/* Define to path to neato program if found or 'echo neato' otherwise */ +#cmakedefine LLVM_PATH_NEATO "${LLVM_PATH_NEATO}" + +/* Define to path to twopi program if found or 'echo twopi' otherwise */ +#cmakedefine LLVM_PATH_TWOPI "${LLVM_PATH_TWOPI}" + +/* Installation prefix directory */ +#undef LLVM_PREFIX + +/* Define if the OS needs help to load dependent libraries for dlopen(). */ +#cmakedefine LTDL_DLOPEN_DEPLIBS ${LTDL_DLOPEN_DEPLIBS} + +/* Define to the sub-directory in which libtool stores uninstalled libraries. + */ +#undef LTDL_OBJDIR + +/* Define to the name of the environment variable that determines the dynamic + library search path. */ +#cmakedefine LTDL_SHLIBPATH_VAR "${LTDL_SHLIBPATH_VAR}" + +/* Define to the extension used for shared libraries, say, ".so". */ +#cmakedefine LTDL_SHLIB_EXT "${LTDL_SHLIB_EXT}" + +/* Define to the system default library search path. */ +#cmakedefine LTDL_SYSSEARCHPATH "${LTDL_SYSSEARCHPATH}" + +/* Define if /dev/zero should be used when mapping RWX memory, or undefine if + its not necessary */ +#undef NEED_DEV_ZERO_FOR_MMAP + +/* Define if dlsym() requires a leading underscore in symbol names. */ +#undef NEED_USCORE + +/* Define to the address where bug reports for this package should be sent. */ +#cmakedefine PACKAGE_BUGREPORT "${PACKAGE_BUGREPORT}" + +/* Define to the full name of this package. */ +#cmakedefine PACKAGE_NAME "${PACKAGE_NAME}" + +/* Define to the full name and version of this package. */ +#cmakedefine PACKAGE_STRING "${PACKAGE_STRING}" + +/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME + +/* Define to the version of this package. */ +#cmakedefine PACKAGE_VERSION "${PACKAGE_VERSION}" + +/* Define as the return type of signal handlers (`int' or `void'). */ +#cmakedefine RETSIGTYPE ${RETSIGTYPE} + +/* If using the C implementation of alloca, define if you know the + direction of stack growth for your system; otherwise it will be + automatically deduced at runtime. + STACK_DIRECTION > 0 => grows toward higher addresses + STACK_DIRECTION < 0 => grows toward lower addresses + STACK_DIRECTION = 0 => direction of growth unknown */ +#undef STACK_DIRECTION + +/* Define to 1 if the `S_IS*' macros in do not work properly. */ +#undef STAT_MACROS_BROKEN + +/* Define to 1 if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* Define to 1 if you can safely include both and . */ +#undef TIME_WITH_SYS_TIME + +/* Define to 1 if your declares `struct tm'. */ +#undef TM_IN_SYS_TIME + +/* Define if use udis86 library */ +#undef USE_UDIS86 + +/* Define to 1 if `lex' declares `yytext' as a `char *' by default, not a + `char[]'. */ +#undef YYTEXT_POINTER + +/* Define to empty if `const' does not conform to ANSI C. */ +#undef const + +/* Define to a type to use for `error_t' if it is not otherwise available. */ +#cmakedefine error_t ${error_t} + +/* Define to a type to use for `mode_t' if it is not otherwise available. */ +#cmakedefine mode_t ${mode_t} + +/* Define to `int' if does not define. */ +#undef pid_t + +/* Define to `unsigned int' if does not define. */ +#undef size_t + +/* Define to a function replacing strtoll */ +#cmakedefine strtoll ${strtoll} + +/* Define to a function implementing strtoull */ +#cmakedefine strtoull ${strtoull} + +/* Define to a function implementing stricmp */ +#cmakedefine stricmp ${stricmp} + +/* Define to a function implementing strdup */ +#cmakedefine strdup ${strdup} + +/* Native LLVM architecture */ +#cmakedefine LLVM_NATIVE_ARCH ${LLVM_NATIVE_ARCH}Target diff --git a/libclamav/c++/llvm/include/llvm/Config/config.h.in b/libclamav/c++/llvm/include/llvm/Config/config.h.in new file mode 100644 index 000000000..8051f55dd --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Config/config.h.in @@ -0,0 +1,626 @@ +/* include/llvm/Config/config.h.in. Generated from autoconf/configure.ac by autoheader. */ + +/* Define if dlopen(0) will open the symbols of the program */ +#undef CAN_DLOPEN_SELF + +/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP + systems. This function is required for `alloca.c' support on those systems. + */ +#undef CRAY_STACKSEG_END + +/* 32 bit multilib directory. */ +#undef CXX_INCLUDE_32BIT_DIR + +/* 64 bit multilib directory. */ +#undef CXX_INCLUDE_64BIT_DIR + +/* Arch the libstdc++ headers. */ +#undef CXX_INCLUDE_ARCH + +/* Directory with the libstdc++ headers. */ +#undef CXX_INCLUDE_ROOT + +/* Define to 1 if using `alloca.c'. */ +#undef C_ALLOCA + +/* Directories clang will search for headers */ +#undef C_INCLUDE_DIRS + +/* Define if CBE is enabled for printf %a output */ +#undef ENABLE_CBE_PRINTF_A + +/* Define if position independent code is enabled */ +#undef ENABLE_PIC + +/* Define if threads enabled */ +#undef ENABLE_THREADS + +/* Define to 1 if you have `alloca', as a function or macro. */ +#undef HAVE_ALLOCA + +/* Define to 1 if you have and it should be used (not on Ultrix). + */ +#undef HAVE_ALLOCA_H + +/* Define to 1 if you have the `argz_append' function. */ +#undef HAVE_ARGZ_APPEND + +/* Define to 1 if you have the `argz_create_sep' function. */ +#undef HAVE_ARGZ_CREATE_SEP + +/* Define to 1 if you have the header file. */ +#undef HAVE_ARGZ_H + +/* Define to 1 if you have the `argz_insert' function. */ +#undef HAVE_ARGZ_INSERT + +/* Define to 1 if you have the `argz_next' function. */ +#undef HAVE_ARGZ_NEXT + +/* Define to 1 if you have the `argz_stringify' function. */ +#undef HAVE_ARGZ_STRINGIFY + +/* Define to 1 if you have the header file. */ +#undef HAVE_ASSERT_H + +/* Define to 1 if you have the `backtrace' function. */ +#undef HAVE_BACKTRACE + +/* Define to 1 if you have the `bcopy' function. */ +#undef HAVE_BCOPY + +/* Does not have bi-directional iterator */ +#undef HAVE_BI_ITERATOR + +/* Define to 1 if you have the `ceilf' function. */ +#undef HAVE_CEILF + +/* Define if the neat program is available */ +#undef HAVE_CIRCO + +/* Define to 1 if you have the `closedir' function. */ +#undef HAVE_CLOSEDIR + +/* Define to 1 if you have the header file. */ +#undef HAVE_CTYPE_H + +/* Define to 1 if you have the header file, and it defines `DIR'. + */ +#undef HAVE_DIRENT_H + +/* Define if you have the GNU dld library. */ +#undef HAVE_DLD + +/* Define to 1 if you have the header file. */ +#undef HAVE_DLD_H + +/* Define to 1 if you have the `dlerror' function. */ +#undef HAVE_DLERROR + +/* Define to 1 if you have the header file. */ +#undef HAVE_DLFCN_H + +/* Define if dlopen() is available on this platform. */ +#undef HAVE_DLOPEN + +/* Define to 1 if you have the header file. */ +#undef HAVE_DL_H + +/* Define if the dot program is available */ +#undef HAVE_DOT + +/* Define if the dotty program is available */ +#undef HAVE_DOTTY + +/* Define if you have the _dyld_func_lookup function. */ +#undef HAVE_DYLD + +/* Define to 1 if you have the header file. */ +#undef HAVE_ERRNO_H + +/* Define to 1 if the system has the type `error_t'. */ +#undef HAVE_ERROR_T + +/* Define to 1 if you have the header file. */ +#undef HAVE_EXECINFO_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_FCNTL_H + +/* Define if the neat program is available */ +#undef HAVE_FDP + +/* Define if libffi is available on this platform. */ +#undef HAVE_FFI_CALL + +/* Define to 1 if you have the header file. */ +#undef HAVE_FFI_FFI_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_FFI_H + +/* Set to 1 if the finite function is found in */ +#undef HAVE_FINITE_IN_IEEEFP_H + +/* Define to 1 if you have the `floorf' function. */ +#undef HAVE_FLOORF + +/* Define to 1 if you have the `fmodf' function. */ +#undef HAVE_FMODF + +/* Does not have forward iterator */ +#undef HAVE_FWD_ITERATOR + +/* Define to 1 if you have the `getcwd' function. */ +#undef HAVE_GETCWD + +/* Define to 1 if you have the `getpagesize' function. */ +#undef HAVE_GETPAGESIZE + +/* Define to 1 if you have the `getrlimit' function. */ +#undef HAVE_GETRLIMIT + +/* Define to 1 if you have the `getrusage' function. */ +#undef HAVE_GETRUSAGE + +/* Define to 1 if you have the `gettimeofday' function. */ +#undef HAVE_GETTIMEOFDAY + +/* Define if the Graphviz program is available */ +#undef HAVE_GRAPHVIZ + +/* Define if the gv program is available */ +#undef HAVE_GV + +/* Define to 1 if you have the `index' function. */ +#undef HAVE_INDEX + +/* Define to 1 if the system has the type `int64_t'. */ +#undef HAVE_INT64_T + +/* Define to 1 if you have the header file. */ +#undef HAVE_INTTYPES_H + +/* Define to 1 if you have the `isatty' function. */ +#undef HAVE_ISATTY + +/* Set to 1 if the isinf function is found in */ +#undef HAVE_ISINF_IN_CMATH + +/* Set to 1 if the isinf function is found in */ +#undef HAVE_ISINF_IN_MATH_H + +/* Set to 1 if the isnan function is found in */ +#undef HAVE_ISNAN_IN_CMATH + +/* Set to 1 if the isnan function is found in */ +#undef HAVE_ISNAN_IN_MATH_H + +/* Define if you have the libdl library or equivalent. */ +#undef HAVE_LIBDL + +/* Define to 1 if you have the `imagehlp' library (-limagehlp). */ +#undef HAVE_LIBIMAGEHLP + +/* Define to 1 if you have the `m' library (-lm). */ +#undef HAVE_LIBM + +/* Define to 1 if you have the `psapi' library (-lpsapi). */ +#undef HAVE_LIBPSAPI + +/* Define to 1 if you have the `pthread' library (-lpthread). */ +#undef HAVE_LIBPTHREAD + +/* Define to 1 if you have the `udis86' library (-ludis86). */ +#undef HAVE_LIBUDIS86 + +/* Define to 1 if you have the header file. */ +#undef HAVE_LIMITS_H + +/* Define if you can use -Wl,-export-dynamic. */ +#undef HAVE_LINK_EXPORT_DYNAMIC + +/* Define to 1 if you have the header file. */ +#undef HAVE_LINK_H + +/* Define if you can use -Wl,-R. to pass -R. to the linker, in order to add + the current directory to the dynamic linker search path. */ +#undef HAVE_LINK_R + +/* Define to 1 if you have the `longjmp' function. */ +#undef HAVE_LONGJMP + +/* Define to 1 if you have the header file. */ +#undef HAVE_MACH_MACH_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_MACH_O_DYLD_H + +/* Define if mallinfo() is available on this platform. */ +#undef HAVE_MALLINFO + +/* Define to 1 if you have the header file. */ +#undef HAVE_MALLOC_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_MALLOC_MALLOC_H + +/* Define to 1 if you have the `malloc_zone_statistics' function. */ +#undef HAVE_MALLOC_ZONE_STATISTICS + +/* Define to 1 if you have the `memcpy' function. */ +#undef HAVE_MEMCPY + +/* Define to 1 if you have the `memmove' function. */ +#undef HAVE_MEMMOVE + +/* Define to 1 if you have the header file. */ +#undef HAVE_MEMORY_H + +/* Define to 1 if you have the `mkdtemp' function. */ +#undef HAVE_MKDTEMP + +/* Define to 1 if you have the `mkstemp' function. */ +#undef HAVE_MKSTEMP + +/* Define to 1 if you have the `mktemp' function. */ +#undef HAVE_MKTEMP + +/* Define to 1 if you have a working `mmap' system call. */ +#undef HAVE_MMAP + +/* Define if mmap() uses MAP_ANONYMOUS to map anonymous pages, or undefine if + it uses MAP_ANON */ +#undef HAVE_MMAP_ANONYMOUS + +/* Define if mmap() can map files into memory */ +#undef HAVE_MMAP_FILE + +/* define if the compiler implements namespaces */ +#undef HAVE_NAMESPACES + +/* Define to 1 if you have the header file, and it defines `DIR'. */ +#undef HAVE_NDIR_H + +/* Define to 1 if you have the `nearbyintf' function. */ +#undef HAVE_NEARBYINTF + +/* Define if the neat program is available */ +#undef HAVE_NEATO + +/* Define to 1 if you have the `opendir' function. */ +#undef HAVE_OPENDIR + +/* Define to 1 if you have the `powf' function. */ +#undef HAVE_POWF + +/* Define if libtool can extract symbol lists from object files. */ +#undef HAVE_PRELOADED_SYMBOLS + +/* Define to have the %a format string */ +#undef HAVE_PRINTF_A + +/* Have pthread_getspecific */ +#undef HAVE_PTHREAD_GETSPECIFIC + +/* Define to 1 if you have the header file. */ +#undef HAVE_PTHREAD_H + +/* Have pthread_mutex_lock */ +#undef HAVE_PTHREAD_MUTEX_LOCK + +/* Have pthread_rwlock_init */ +#undef HAVE_PTHREAD_RWLOCK_INIT + +/* Define to 1 if srand48/lrand48/drand48 exist in */ +#undef HAVE_RAND48 + +/* Define to 1 if you have the `readdir' function. */ +#undef HAVE_READDIR + +/* Define to 1 if you have the `realpath' function. */ +#undef HAVE_REALPATH + +/* Define to 1 if you have the `rindex' function. */ +#undef HAVE_RINDEX + +/* Define to 1 if you have the `rintf' function. */ +#undef HAVE_RINTF + +/* Define to 1 if you have the `round' function. */ +#undef HAVE_ROUND + +/* Define to 1 if you have the `roundf' function. */ +#undef HAVE_ROUNDF + +/* Define to 1 if you have the `sbrk' function. */ +#undef HAVE_SBRK + +/* Define to 1 if you have the `setenv' function. */ +#undef HAVE_SETENV + +/* Define to 1 if you have the `setjmp' function. */ +#undef HAVE_SETJMP + +/* Define to 1 if you have the header file. */ +#undef HAVE_SETJMP_H + +/* Define to 1 if you have the `setrlimit' function. */ +#undef HAVE_SETRLIMIT + +/* Define if you have the shl_load function. */ +#undef HAVE_SHL_LOAD + +/* Define to 1 if you have the `siglongjmp' function. */ +#undef HAVE_SIGLONGJMP + +/* Define to 1 if you have the header file. */ +#undef HAVE_SIGNAL_H + +/* Define to 1 if you have the `sigsetjmp' function. */ +#undef HAVE_SIGSETJMP + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDINT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDIO_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDLIB_H + +/* Set to 1 if the std::isinf function is found in */ +#undef HAVE_STD_ISINF_IN_CMATH + +/* Set to 1 if the std::isnan function is found in */ +#undef HAVE_STD_ISNAN_IN_CMATH + +/* Does not have std namespace iterator */ +#undef HAVE_STD_ITERATOR + +/* Define to 1 if you have the `strchr' function. */ +#undef HAVE_STRCHR + +/* Define to 1 if you have the `strcmp' function. */ +#undef HAVE_STRCMP + +/* Define to 1 if you have the `strdup' function. */ +#undef HAVE_STRDUP + +/* Define to 1 if you have the `strerror' function. */ +#undef HAVE_STRERROR + +/* Define to 1 if you have the `strerror_r' function. */ +#undef HAVE_STRERROR_R + +/* Define to 1 if you have the `strerror_s' function. */ +#undef HAVE_STRERROR_S + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRINGS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRING_H + +/* Define to 1 if you have the `strrchr' function. */ +#undef HAVE_STRRCHR + +/* Define to 1 if you have the `strtof' function. */ +#undef HAVE_STRTOF + +/* Define to 1 if you have the `strtoll' function. */ +#undef HAVE_STRTOLL + +/* Define to 1 if you have the `strtoq' function. */ +#undef HAVE_STRTOQ + +/* Define to 1 if you have the `sysconf' function. */ +#undef HAVE_SYSCONF + +/* Define to 1 if you have the header file, and it defines `DIR'. + */ +#undef HAVE_SYS_DIR_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_DL_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_IOCTL_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_MMAN_H + +/* Define to 1 if you have the header file, and it defines `DIR'. + */ +#undef HAVE_SYS_NDIR_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_PARAM_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_RESOURCE_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_STAT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TIME_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TYPES_H + +/* Define to 1 if you have that is POSIX.1 compatible. */ +#undef HAVE_SYS_WAIT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_TERMIOS_H + +/* Define if the neat program is available */ +#undef HAVE_TWOPI + +/* Define to 1 if the system has the type `uint64_t'. */ +#undef HAVE_UINT64_T + +/* Define to 1 if you have the header file. */ +#undef HAVE_UNISTD_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_UTIME_H + +/* Define to 1 if the system has the type `u_int64_t'. */ +#undef HAVE_U_INT64_T + +/* Define to 1 if you have the header file. */ +#undef HAVE_WINDOWS_H + +/* Define to 1 if you have the `__dso_handle' function. */ +#undef HAVE___DSO_HANDLE + +/* Installation directory for binary executables */ +#undef LLVM_BINDIR + +/* Time at which LLVM was configured */ +#undef LLVM_CONFIGTIME + +/* Installation directory for data files */ +#undef LLVM_DATADIR + +/* Installation directory for documentation */ +#undef LLVM_DOCSDIR + +/* Installation directory for config files */ +#undef LLVM_ETCDIR + +/* Host triple we were built on */ +#undef LLVM_HOSTTRIPLE + +/* Installation directory for include files */ +#undef LLVM_INCLUDEDIR + +/* Installation directory for .info files */ +#undef LLVM_INFODIR + +/* Installation directory for libraries */ +#undef LLVM_LIBDIR + +/* Installation directory for man pages */ +#undef LLVM_MANDIR + +/* Build multithreading support into LLVM */ +#undef LLVM_MULTITHREADED + +/* LLVM architecture name for the native architecture, if available */ +#undef LLVM_NATIVE_ARCH + +/* Define if this is Unixish platform */ +#undef LLVM_ON_UNIX + +/* Define if this is Win32ish platform */ +#undef LLVM_ON_WIN32 + +/* Define to path to circo program if found or 'echo circo' otherwise */ +#undef LLVM_PATH_CIRCO + +/* Define to path to dot program if found or 'echo dot' otherwise */ +#undef LLVM_PATH_DOT + +/* Define to path to dotty program if found or 'echo dotty' otherwise */ +#undef LLVM_PATH_DOTTY + +/* Define to path to fdp program if found or 'echo fdp' otherwise */ +#undef LLVM_PATH_FDP + +/* Define to path to Graphviz program if found or 'echo Graphviz' otherwise */ +#undef LLVM_PATH_GRAPHVIZ + +/* Define to path to gv program if found or 'echo gv' otherwise */ +#undef LLVM_PATH_GV + +/* Define to path to neato program if found or 'echo neato' otherwise */ +#undef LLVM_PATH_NEATO + +/* Define to path to twopi program if found or 'echo twopi' otherwise */ +#undef LLVM_PATH_TWOPI + +/* Installation prefix directory */ +#undef LLVM_PREFIX + +/* Define if the OS needs help to load dependent libraries for dlopen(). */ +#undef LTDL_DLOPEN_DEPLIBS + +/* Define to the sub-directory in which libtool stores uninstalled libraries. + */ +#undef LTDL_OBJDIR + +/* Define to the name of the environment variable that determines the dynamic + library search path. */ +#undef LTDL_SHLIBPATH_VAR + +/* Define to the extension used for shared libraries, say, ".so". */ +#undef LTDL_SHLIB_EXT + +/* Define to the system default library search path. */ +#undef LTDL_SYSSEARCHPATH + +/* Define if /dev/zero should be used when mapping RWX memory, or undefine if + its not necessary */ +#undef NEED_DEV_ZERO_FOR_MMAP + +/* Define if dlsym() requires a leading underscore in symbol names. */ +#undef NEED_USCORE + +/* Define to the address where bug reports for this package should be sent. */ +#undef PACKAGE_BUGREPORT + +/* Define to the full name of this package. */ +#undef PACKAGE_NAME + +/* Define to the full name and version of this package. */ +#undef PACKAGE_STRING + +/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME + +/* Define to the version of this package. */ +#undef PACKAGE_VERSION + +/* Define as the return type of signal handlers (`int' or `void'). */ +#undef RETSIGTYPE + +/* If using the C implementation of alloca, define if you know the + direction of stack growth for your system; otherwise it will be + automatically deduced at runtime. + STACK_DIRECTION > 0 => grows toward higher addresses + STACK_DIRECTION < 0 => grows toward lower addresses + STACK_DIRECTION = 0 => direction of growth unknown */ +#undef STACK_DIRECTION + +/* Define to 1 if the `S_IS*' macros in do not work properly. */ +#undef STAT_MACROS_BROKEN + +/* Define to 1 if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* Define to 1 if you can safely include both and . */ +#undef TIME_WITH_SYS_TIME + +/* Define to 1 if your declares `struct tm'. */ +#undef TM_IN_SYS_TIME + +/* Define if we have the oprofile JIT-support library */ +#undef USE_OPROFILE + +/* Define if use udis86 library */ +#undef USE_UDIS86 + +/* Define to empty if `const' does not conform to ANSI C. */ +#undef const + +/* Define to a type to use for `error_t' if it is not otherwise available. */ +#undef error_t + +/* Define to `int' if does not define. */ +#undef pid_t + +/* Define to `unsigned int' if does not define. */ +#undef size_t diff --git a/libclamav/c++/llvm/include/llvm/Constant.h b/libclamav/c++/llvm/include/llvm/Constant.h new file mode 100644 index 000000000..8072fd9f4 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Constant.h @@ -0,0 +1,160 @@ +//===-- llvm/Constant.h - Constant class definition -------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the declaration of the Constant class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CONSTANT_H +#define LLVM_CONSTANT_H + +#include "llvm/User.h" + +namespace llvm { + class APInt; + + template class SmallVectorImpl; + class LLVMContext; + +/// This is an important base class in LLVM. It provides the common facilities +/// of all constant values in an LLVM program. A constant is a value that is +/// immutable at runtime. Functions are constants because their address is +/// immutable. Same with global variables. +/// +/// All constants share the capabilities provided in this class. All constants +/// can have a null value. They can have an operand list. Constants can be +/// simple (integer and floating point values), complex (arrays and structures), +/// or expression based (computations yielding a constant value composed of +/// only certain operators and other constant values). +/// +/// Note that Constants are immutable (once created they never change) +/// and are fully shared by structural equivalence. This means that two +/// structurally equivalent constants will always have the same address. +/// Constants are created on demand as needed and never deleted: thus clients +/// don't have to worry about the lifetime of the objects. +/// @brief LLVM Constant Representation +class Constant : public User { + void operator=(const Constant &); // Do not implement + Constant(const Constant &); // Do not implement + +protected: + Constant(const Type *ty, ValueTy vty, Use *Ops, unsigned NumOps) + : User(ty, vty, Ops, NumOps) {} + + void destroyConstantImpl(); + + void setOperand(unsigned i, Value *V) { + User::setOperand(i, V); + } +public: + /// isNullValue - Return true if this is the value that would be returned by + /// getNullValue. + virtual bool isNullValue() const = 0; + + /// isNegativeZeroValue - Return true if the value is what would be returned + /// by getZeroValueForNegation. + virtual bool isNegativeZeroValue() const { return isNullValue(); } + + /// canTrap - Return true if evaluation of this constant could trap. This is + /// true for things like constant expressions that could divide by zero. + bool canTrap() const; + + /// isConstantUsed - Return true if the constant has users other than constant + /// exprs and other dangling things. + bool isConstantUsed() const; + + enum PossibleRelocationsTy { + NoRelocation = 0, + LocalRelocation = 1, + GlobalRelocations = 2 + }; + + /// getRelocationInfo - This method classifies the entry according to + /// whether or not it may generate a relocation entry. This must be + /// conservative, so if it might codegen to a relocatable entry, it should say + /// so. The return values are: + /// + /// NoRelocation: This constant pool entry is guaranteed to never have a + /// relocation applied to it (because it holds a simple constant like + /// '4'). + /// LocalRelocation: This entry has relocations, but the entries are + /// guaranteed to be resolvable by the static linker, so the dynamic + /// linker will never see them. + /// GlobalRelocations: This entry may have arbitrary relocations. + /// + /// FIXME: This really should not be in VMCore. + PossibleRelocationsTy getRelocationInfo() const; + + // Specialize get/setOperand for Users as their operands are always + // constants or BasicBlocks as well. + User *getOperand(unsigned i) { + return static_cast(User::getOperand(i)); + } + const User *getOperand(unsigned i) const { + return static_cast(User::getOperand(i)); + } + + /// getVectorElements - This method, which is only valid on constant of vector + /// type, returns the elements of the vector in the specified smallvector. + /// This handles breaking down a vector undef into undef elements, etc. For + /// constant exprs and other cases we can't handle, we return an empty vector. + void getVectorElements(LLVMContext &Context, + SmallVectorImpl &Elts) const; + + /// destroyConstant - Called if some element of this constant is no longer + /// valid. At this point only other constants may be on the use_list for this + /// constant. Any constants on our Use list must also be destroy'd. The + /// implementation must be sure to remove the constant from the list of + /// available cached constants. Implementations should call + /// destroyConstantImpl as the last thing they do, to destroy all users and + /// delete this. + virtual void destroyConstant() { assert(0 && "Not reached!"); } + + //// Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const Constant *) { return true; } + static inline bool classof(const GlobalValue *) { return true; } + static inline bool classof(const Value *V) { + return V->getValueID() >= ConstantFirstVal && + V->getValueID() <= ConstantLastVal; + } + + /// replaceUsesOfWithOnConstant - This method is a special form of + /// User::replaceUsesOfWith (which does not work on constants) that does work + /// on constants. Basically this method goes through the trouble of building + /// a new constant that is equivalent to the current one, with all uses of + /// From replaced with uses of To. After this construction is completed, all + /// of the users of 'this' are replaced to use the new constant, and then + /// 'this' is deleted. In general, you should not call this method, instead, + /// use Value::replaceAllUsesWith, which automatically dispatches to this + /// method as needed. + /// + virtual void replaceUsesOfWithOnConstant(Value *, Value *, Use *) { + // Provide a default implementation for constants (like integers) that + // cannot use any other values. This cannot be called at runtime, but needs + // to be here to avoid link errors. + assert(getNumOperands() == 0 && "replaceUsesOfWithOnConstant must be " + "implemented for all constants that have operands!"); + assert(0 && "Constants that do not have operands cannot be using 'From'!"); + } + + static Constant* getNullValue(const Type* Ty); + + /// @returns the value for an integer constant of the given type that has all + /// its bits set to true. + /// @brief Get the all ones value + static Constant* getAllOnesValue(const Type* Ty); + + /// getIntegerValue - Return the value for an integer or pointer constant, + /// or a vector thereof, with the given scalar value. + static Constant* getIntegerValue(const Type* Ty, const APInt &V); +}; + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Constants.h b/libclamav/c++/llvm/include/llvm/Constants.h new file mode 100644 index 000000000..caa13f6ac --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Constants.h @@ -0,0 +1,893 @@ +//===-- llvm/Constants.h - Constant class subclass definitions --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +/// @file +/// This file contains the declarations for the subclasses of Constant, +/// which represent the different flavors of constant values that live in LLVM. +/// Note that Constants are immutable (once created they never change) and are +/// fully shared by structural equivalence. This means that two structurally +/// equivalent constants will always have the same address. Constant's are +/// created on demand as needed and never deleted: thus clients don't have to +/// worry about the lifetime of the objects. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CONSTANTS_H +#define LLVM_CONSTANTS_H + +#include "llvm/Constant.h" +#include "llvm/OperandTraits.h" +#include "llvm/ADT/APInt.h" +#include "llvm/ADT/APFloat.h" +#include "llvm/ADT/SmallVector.h" +#include + +namespace llvm { + +class ArrayType; +class IntegerType; +class StructType; +class PointerType; +class VectorType; + +template +struct ConstantCreator; +template +struct ConvertConstantType; + +//===----------------------------------------------------------------------===// +/// This is the shared class of boolean and integer constants. This class +/// represents both boolean and integral constants. +/// @brief Class for constant integers. +class ConstantInt : public Constant { + void *operator new(size_t, unsigned); // DO NOT IMPLEMENT + ConstantInt(const ConstantInt &); // DO NOT IMPLEMENT + ConstantInt(const IntegerType *Ty, const APInt& V); + APInt Val; +protected: + // allocate space for exactly zero operands + void *operator new(size_t s) { + return User::operator new(s, 0); + } +public: + static ConstantInt *getTrue(LLVMContext &Context); + static ConstantInt *getFalse(LLVMContext &Context); + + /// If Ty is a vector type, return a Constant with a splat of the given + /// value. Otherwise return a ConstantInt for the given value. + static Constant *get(const Type *Ty, uint64_t V, bool isSigned = false); + + /// Return a ConstantInt with the specified integer value for the specified + /// type. If the type is wider than 64 bits, the value will be zero-extended + /// to fit the type, unless isSigned is true, in which case the value will + /// be interpreted as a 64-bit signed integer and sign-extended to fit + /// the type. + /// @brief Get a ConstantInt for a specific value. + static ConstantInt *get(const IntegerType *Ty, uint64_t V, + bool isSigned = false); + + /// Return a ConstantInt with the specified value for the specified type. The + /// value V will be canonicalized to a an unsigned APInt. Accessing it with + /// either getSExtValue() or getZExtValue() will yield a correctly sized and + /// signed value for the type Ty. + /// @brief Get a ConstantInt for a specific signed value. + static ConstantInt *getSigned(const IntegerType *Ty, int64_t V); + static Constant *getSigned(const Type *Ty, int64_t V); + + /// Return a ConstantInt with the specified value and an implied Type. The + /// type is the integer type that corresponds to the bit width of the value. + static ConstantInt *get(LLVMContext &Context, const APInt &V); + + /// Return a ConstantInt constructed from the string strStart with the given + /// radix. + static ConstantInt *get(const IntegerType *Ty, StringRef Str, + uint8_t radix); + + /// If Ty is a vector type, return a Constant with a splat of the given + /// value. Otherwise return a ConstantInt for the given value. + static Constant *get(const Type* Ty, const APInt& V); + + /// Return the constant as an APInt value reference. This allows clients to + /// obtain a copy of the value, with all its precision in tact. + /// @brief Return the constant's value. + inline const APInt &getValue() const { + return Val; + } + + /// getBitWidth - Return the bitwidth of this constant. + unsigned getBitWidth() const { return Val.getBitWidth(); } + + /// Return the constant as a 64-bit unsigned integer value after it + /// has been zero extended as appropriate for the type of this constant. Note + /// that this method can assert if the value does not fit in 64 bits. + /// @deprecated + /// @brief Return the zero extended value. + inline uint64_t getZExtValue() const { + return Val.getZExtValue(); + } + + /// Return the constant as a 64-bit integer value after it has been sign + /// extended as appropriate for the type of this constant. Note that + /// this method can assert if the value does not fit in 64 bits. + /// @deprecated + /// @brief Return the sign extended value. + inline int64_t getSExtValue() const { + return Val.getSExtValue(); + } + + /// A helper method that can be used to determine if the constant contained + /// within is equal to a constant. This only works for very small values, + /// because this is all that can be represented with all types. + /// @brief Determine if this constant's value is same as an unsigned char. + bool equalsInt(uint64_t V) const { + return Val == V; + } + + /// getType - Specialize the getType() method to always return an IntegerType, + /// which reduces the amount of casting needed in parts of the compiler. + /// + inline const IntegerType *getType() const { + return reinterpret_cast(Value::getType()); + } + + /// This static method returns true if the type Ty is big enough to + /// represent the value V. This can be used to avoid having the get method + /// assert when V is larger than Ty can represent. Note that there are two + /// versions of this method, one for unsigned and one for signed integers. + /// Although ConstantInt canonicalizes everything to an unsigned integer, + /// the signed version avoids callers having to convert a signed quantity + /// to the appropriate unsigned type before calling the method. + /// @returns true if V is a valid value for type Ty + /// @brief Determine if the value is in range for the given type. + static bool isValueValidForType(const Type *Ty, uint64_t V); + static bool isValueValidForType(const Type *Ty, int64_t V); + + /// This function will return true iff this constant represents the "null" + /// value that would be returned by the getNullValue method. + /// @returns true if this is the null integer value. + /// @brief Determine if the value is null. + virtual bool isNullValue() const { + return Val == 0; + } + + /// This is just a convenience method to make client code smaller for a + /// common code. It also correctly performs the comparison without the + /// potential for an assertion from getZExtValue(). + bool isZero() const { + return Val == 0; + } + + /// This is just a convenience method to make client code smaller for a + /// common case. It also correctly performs the comparison without the + /// potential for an assertion from getZExtValue(). + /// @brief Determine if the value is one. + bool isOne() const { + return Val == 1; + } + + /// This function will return true iff every bit in this constant is set + /// to true. + /// @returns true iff this constant's bits are all set to true. + /// @brief Determine if the value is all ones. + bool isAllOnesValue() const { + return Val.isAllOnesValue(); + } + + /// This function will return true iff this constant represents the largest + /// value that may be represented by the constant's type. + /// @returns true iff this is the largest value that may be represented + /// by this type. + /// @brief Determine if the value is maximal. + bool isMaxValue(bool isSigned) const { + if (isSigned) + return Val.isMaxSignedValue(); + else + return Val.isMaxValue(); + } + + /// This function will return true iff this constant represents the smallest + /// value that may be represented by this constant's type. + /// @returns true if this is the smallest value that may be represented by + /// this type. + /// @brief Determine if the value is minimal. + bool isMinValue(bool isSigned) const { + if (isSigned) + return Val.isMinSignedValue(); + else + return Val.isMinValue(); + } + + /// This function will return true iff this constant represents a value with + /// active bits bigger than 64 bits or a value greater than the given uint64_t + /// value. + /// @returns true iff this constant is greater or equal to the given number. + /// @brief Determine if the value is greater or equal to the given number. + bool uge(uint64_t Num) { + return Val.getActiveBits() > 64 || Val.getZExtValue() >= Num; + } + + /// getLimitedValue - If the value is smaller than the specified limit, + /// return it, otherwise return the limit value. This causes the value + /// to saturate to the limit. + /// @returns the min of the value of the constant and the specified value + /// @brief Get the constant's value with a saturation limit + uint64_t getLimitedValue(uint64_t Limit = ~0ULL) const { + return Val.getLimitedValue(Limit); + } + + /// @brief Methods to support type inquiry through isa, cast, and dyn_cast. + static inline bool classof(const ConstantInt *) { return true; } + static bool classof(const Value *V) { + return V->getValueID() == ConstantIntVal; + } +}; + + +//===----------------------------------------------------------------------===// +/// ConstantFP - Floating Point Values [float, double] +/// +class ConstantFP : public Constant { + APFloat Val; + void *operator new(size_t, unsigned);// DO NOT IMPLEMENT + ConstantFP(const ConstantFP &); // DO NOT IMPLEMENT + friend class LLVMContextImpl; +protected: + ConstantFP(const Type *Ty, const APFloat& V); +protected: + // allocate space for exactly zero operands + void *operator new(size_t s) { + return User::operator new(s, 0); + } +public: + /// Floating point negation must be implemented with f(x) = -0.0 - x. This + /// method returns the negative zero constant for floating point or vector + /// floating point types; for all other types, it returns the null value. + static Constant *getZeroValueForNegation(const Type *Ty); + + /// get() - This returns a ConstantFP, or a vector containing a splat of a + /// ConstantFP, for the specified value in the specified type. This should + /// only be used for simple constant values like 2.0/1.0 etc, that are + /// known-valid both as host double and as the target format. + static Constant *get(const Type* Ty, double V); + static Constant *get(const Type* Ty, StringRef Str); + static ConstantFP *get(LLVMContext &Context, const APFloat &V); + static ConstantFP *getNegativeZero(const Type* Ty); + static ConstantFP *getInfinity(const Type *Ty, bool Negative = false); + + /// isValueValidForType - return true if Ty is big enough to represent V. + static bool isValueValidForType(const Type *Ty, const APFloat &V); + inline const APFloat& getValueAPF() const { return Val; } + + /// isNullValue - Return true if this is the value that would be returned by + /// getNullValue. Don't depend on == for doubles to tell us it's zero, it + /// considers -0.0 to be null as well as 0.0. :( + virtual bool isNullValue() const; + + /// isNegativeZeroValue - Return true if the value is what would be returned + /// by getZeroValueForNegation. + virtual bool isNegativeZeroValue() const { + return Val.isZero() && Val.isNegative(); + } + + /// isExactlyValue - We don't rely on operator== working on double values, as + /// it returns true for things that are clearly not equal, like -0.0 and 0.0. + /// As such, this method can be used to do an exact bit-for-bit comparison of + /// two floating point values. The version with a double operand is retained + /// because it's so convenient to write isExactlyValue(2.0), but please use + /// it only for simple constants. + bool isExactlyValue(const APFloat &V) const; + + bool isExactlyValue(double V) const { + bool ignored; + // convert is not supported on this type + if (&Val.getSemantics() == &APFloat::PPCDoubleDouble) + return false; + APFloat FV(V); + FV.convert(Val.getSemantics(), APFloat::rmNearestTiesToEven, &ignored); + return isExactlyValue(FV); + } + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const ConstantFP *) { return true; } + static bool classof(const Value *V) { + return V->getValueID() == ConstantFPVal; + } +}; + +//===----------------------------------------------------------------------===// +/// ConstantAggregateZero - All zero aggregate value +/// +class ConstantAggregateZero : public Constant { + friend struct ConstantCreator; + void *operator new(size_t, unsigned); // DO NOT IMPLEMENT + ConstantAggregateZero(const ConstantAggregateZero &); // DO NOT IMPLEMENT +protected: + explicit ConstantAggregateZero(const Type *ty) + : Constant(ty, ConstantAggregateZeroVal, 0, 0) {} +protected: + // allocate space for exactly zero operands + void *operator new(size_t s) { + return User::operator new(s, 0); + } +public: + static ConstantAggregateZero* get(const Type *Ty); + + /// isNullValue - Return true if this is the value that would be returned by + /// getNullValue. + virtual bool isNullValue() const { return true; } + + virtual void destroyConstant(); + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + /// + static bool classof(const ConstantAggregateZero *) { return true; } + static bool classof(const Value *V) { + return V->getValueID() == ConstantAggregateZeroVal; + } +}; + + +//===----------------------------------------------------------------------===// +/// ConstantArray - Constant Array Declarations +/// +class ConstantArray : public Constant { + friend struct ConstantCreator >; + ConstantArray(const ConstantArray &); // DO NOT IMPLEMENT +protected: + ConstantArray(const ArrayType *T, const std::vector &Val); +public: + // ConstantArray accessors + static Constant *get(const ArrayType *T, const std::vector &V); + static Constant *get(const ArrayType *T, Constant *const *Vals, + unsigned NumVals); + + /// This method constructs a ConstantArray and initializes it with a text + /// string. The default behavior (AddNull==true) causes a null terminator to + /// be placed at the end of the array. This effectively increases the length + /// of the array by one (you've been warned). However, in some situations + /// this is not desired so if AddNull==false then the string is copied without + /// null termination. + static Constant *get(LLVMContext &Context, StringRef Initializer, + bool AddNull = true); + + /// Transparently provide more efficient getOperand methods. + DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Constant); + + /// getType - Specialize the getType() method to always return an ArrayType, + /// which reduces the amount of casting needed in parts of the compiler. + /// + inline const ArrayType *getType() const { + return reinterpret_cast(Value::getType()); + } + + /// isString - This method returns true if the array is an array of i8 and + /// the elements of the array are all ConstantInt's. + bool isString() const; + + /// isCString - This method returns true if the array is a string (see + /// @verbatim + /// isString) and it ends in a null byte \0 and does not contains any other + /// @endverbatim + /// null bytes except its terminator. + bool isCString() const; + + /// getAsString - If this array is isString(), then this method converts the + /// array to an std::string and returns it. Otherwise, it asserts out. + /// + std::string getAsString() const; + + /// isNullValue - Return true if this is the value that would be returned by + /// getNullValue. This always returns false because zero arrays are always + /// created as ConstantAggregateZero objects. + virtual bool isNullValue() const { return false; } + + virtual void destroyConstant(); + virtual void replaceUsesOfWithOnConstant(Value *From, Value *To, Use *U); + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const ConstantArray *) { return true; } + static bool classof(const Value *V) { + return V->getValueID() == ConstantArrayVal; + } +}; + +template <> +struct OperandTraits : public VariadicOperandTraits<> { +}; + +DEFINE_TRANSPARENT_CASTED_OPERAND_ACCESSORS(ConstantArray, Constant) + +//===----------------------------------------------------------------------===// +// ConstantStruct - Constant Struct Declarations +// +class ConstantStruct : public Constant { + friend struct ConstantCreator >; + ConstantStruct(const ConstantStruct &); // DO NOT IMPLEMENT +protected: + ConstantStruct(const StructType *T, const std::vector &Val); +public: + // ConstantStruct accessors + static Constant *get(const StructType *T, const std::vector &V); + static Constant *get(LLVMContext &Context, + const std::vector &V, bool Packed); + static Constant *get(LLVMContext &Context, + Constant *const *Vals, unsigned NumVals, bool Packed); + + /// Transparently provide more efficient getOperand methods. + DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Constant); + + /// getType() specialization - Reduce amount of casting... + /// + inline const StructType *getType() const { + return reinterpret_cast(Value::getType()); + } + + /// isNullValue - Return true if this is the value that would be returned by + /// getNullValue. This always returns false because zero structs are always + /// created as ConstantAggregateZero objects. + virtual bool isNullValue() const { + return false; + } + + virtual void destroyConstant(); + virtual void replaceUsesOfWithOnConstant(Value *From, Value *To, Use *U); + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const ConstantStruct *) { return true; } + static bool classof(const Value *V) { + return V->getValueID() == ConstantStructVal; + } +}; + +template <> +struct OperandTraits : public VariadicOperandTraits<> { +}; + +DEFINE_TRANSPARENT_CASTED_OPERAND_ACCESSORS(ConstantStruct, Constant) + +//===----------------------------------------------------------------------===// +/// ConstantVector - Constant Vector Declarations +/// +class ConstantVector : public Constant { + friend struct ConstantCreator >; + ConstantVector(const ConstantVector &); // DO NOT IMPLEMENT +protected: + ConstantVector(const VectorType *T, const std::vector &Val); +public: + // ConstantVector accessors + static Constant *get(const VectorType *T, const std::vector &V); + static Constant *get(const std::vector &V); + static Constant *get(Constant *const *Vals, unsigned NumVals); + + /// Transparently provide more efficient getOperand methods. + DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Constant); + + /// getType - Specialize the getType() method to always return a VectorType, + /// which reduces the amount of casting needed in parts of the compiler. + /// + inline const VectorType *getType() const { + return reinterpret_cast(Value::getType()); + } + + /// isNullValue - Return true if this is the value that would be returned by + /// getNullValue. This always returns false because zero vectors are always + /// created as ConstantAggregateZero objects. + virtual bool isNullValue() const { return false; } + + /// This function will return true iff every element in this vector constant + /// is set to all ones. + /// @returns true iff this constant's emements are all set to all ones. + /// @brief Determine if the value is all ones. + bool isAllOnesValue() const; + + /// getSplatValue - If this is a splat constant, meaning that all of the + /// elements have the same value, return that value. Otherwise return NULL. + Constant *getSplatValue(); + + virtual void destroyConstant(); + virtual void replaceUsesOfWithOnConstant(Value *From, Value *To, Use *U); + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const ConstantVector *) { return true; } + static bool classof(const Value *V) { + return V->getValueID() == ConstantVectorVal; + } +}; + +template <> +struct OperandTraits : public VariadicOperandTraits<> { +}; + +DEFINE_TRANSPARENT_CASTED_OPERAND_ACCESSORS(ConstantVector, Constant) + +//===----------------------------------------------------------------------===// +/// ConstantPointerNull - a constant pointer value that points to null +/// +class ConstantPointerNull : public Constant { + friend struct ConstantCreator; + void *operator new(size_t, unsigned); // DO NOT IMPLEMENT + ConstantPointerNull(const ConstantPointerNull &); // DO NOT IMPLEMENT +protected: + explicit ConstantPointerNull(const PointerType *T) + : Constant(reinterpret_cast(T), + Value::ConstantPointerNullVal, 0, 0) {} + +protected: + // allocate space for exactly zero operands + void *operator new(size_t s) { + return User::operator new(s, 0); + } +public: + /// get() - Static factory methods - Return objects of the specified value + static ConstantPointerNull *get(const PointerType *T); + + /// isNullValue - Return true if this is the value that would be returned by + /// getNullValue. + virtual bool isNullValue() const { return true; } + + virtual void destroyConstant(); + + /// getType - Specialize the getType() method to always return an PointerType, + /// which reduces the amount of casting needed in parts of the compiler. + /// + inline const PointerType *getType() const { + return reinterpret_cast(Value::getType()); + } + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const ConstantPointerNull *) { return true; } + static bool classof(const Value *V) { + return V->getValueID() == ConstantPointerNullVal; + } +}; + +/// BlockAddress - The address of a basic block. +/// +class BlockAddress : public Constant { + void *operator new(size_t, unsigned); // DO NOT IMPLEMENT + void *operator new(size_t s) { return User::operator new(s, 2); } + BlockAddress(Function *F, BasicBlock *BB); +public: + /// get - Return a BlockAddress for the specified function and basic block. + static BlockAddress *get(Function *F, BasicBlock *BB); + + /// get - Return a BlockAddress for the specified basic block. The basic + /// block must be embedded into a function. + static BlockAddress *get(BasicBlock *BB); + + /// Transparently provide more efficient getOperand methods. + DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); + + Function *getFunction() const { return (Function*)Op<0>().get(); } + BasicBlock *getBasicBlock() const { return (BasicBlock*)Op<1>().get(); } + + /// isNullValue - Return true if this is the value that would be returned by + /// getNullValue. + virtual bool isNullValue() const { return false; } + + virtual void destroyConstant(); + virtual void replaceUsesOfWithOnConstant(Value *From, Value *To, Use *U); + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const BlockAddress *) { return true; } + static inline bool classof(const Value *V) { + return V->getValueID() == BlockAddressVal; + } +}; + +template <> +struct OperandTraits : public FixedNumOperandTraits<2> { +}; + +DEFINE_TRANSPARENT_CASTED_OPERAND_ACCESSORS(BlockAddress, Value) + +//===----------------------------------------------------------------------===// +/// ConstantExpr - a constant value that is initialized with an expression using +/// other constant values. +/// +/// This class uses the standard Instruction opcodes to define the various +/// constant expressions. The Opcode field for the ConstantExpr class is +/// maintained in the Value::SubclassData field. +class ConstantExpr : public Constant { + friend struct ConstantCreator > >; + friend struct ConvertConstantType; + +protected: + ConstantExpr(const Type *ty, unsigned Opcode, Use *Ops, unsigned NumOps) + : Constant(ty, ConstantExprVal, Ops, NumOps) { + // Operation type (an Instruction opcode) is stored as the SubclassData. + SubclassData = Opcode; + } + + // These private methods are used by the type resolution code to create + // ConstantExprs in intermediate forms. + static Constant *getTy(const Type *Ty, unsigned Opcode, + Constant *C1, Constant *C2, + unsigned Flags = 0); + static Constant *getCompareTy(unsigned short pred, Constant *C1, + Constant *C2); + static Constant *getSelectTy(const Type *Ty, + Constant *C1, Constant *C2, Constant *C3); + static Constant *getGetElementPtrTy(const Type *Ty, Constant *C, + Value* const *Idxs, unsigned NumIdxs); + static Constant *getInBoundsGetElementPtrTy(const Type *Ty, Constant *C, + Value* const *Idxs, + unsigned NumIdxs); + static Constant *getExtractElementTy(const Type *Ty, Constant *Val, + Constant *Idx); + static Constant *getInsertElementTy(const Type *Ty, Constant *Val, + Constant *Elt, Constant *Idx); + static Constant *getShuffleVectorTy(const Type *Ty, Constant *V1, + Constant *V2, Constant *Mask); + static Constant *getExtractValueTy(const Type *Ty, Constant *Agg, + const unsigned *Idxs, unsigned NumIdxs); + static Constant *getInsertValueTy(const Type *Ty, Constant *Agg, + Constant *Val, + const unsigned *Idxs, unsigned NumIdxs); + +public: + // Static methods to construct a ConstantExpr of different kinds. Note that + // these methods may return a object that is not an instance of the + // ConstantExpr class, because they will attempt to fold the constant + // expression into something simpler if possible. + + /// Cast constant expr + /// + + /// getAlignOf constant expr - computes the alignment of a type in a target + /// independent way (Note: the return type is an i32; Note: assumes that i8 + /// is byte aligned). + static Constant *getAlignOf(const Type* Ty); + + /// getSizeOf constant expr - computes the size of a type in a target + /// independent way (Note: the return type is an i64). + /// + static Constant *getSizeOf(const Type* Ty); + + /// getOffsetOf constant expr - computes the offset of a field in a target + /// independent way (Note: the return type is an i64). + /// + static Constant *getOffsetOf(const StructType* Ty, unsigned FieldNo); + + static Constant *getNeg(Constant *C); + static Constant *getFNeg(Constant *C); + static Constant *getNot(Constant *C); + static Constant *getAdd(Constant *C1, Constant *C2); + static Constant *getFAdd(Constant *C1, Constant *C2); + static Constant *getSub(Constant *C1, Constant *C2); + static Constant *getFSub(Constant *C1, Constant *C2); + static Constant *getMul(Constant *C1, Constant *C2); + static Constant *getFMul(Constant *C1, Constant *C2); + static Constant *getUDiv(Constant *C1, Constant *C2); + static Constant *getSDiv(Constant *C1, Constant *C2); + static Constant *getFDiv(Constant *C1, Constant *C2); + static Constant *getURem(Constant *C1, Constant *C2); + static Constant *getSRem(Constant *C1, Constant *C2); + static Constant *getFRem(Constant *C1, Constant *C2); + static Constant *getAnd(Constant *C1, Constant *C2); + static Constant *getOr(Constant *C1, Constant *C2); + static Constant *getXor(Constant *C1, Constant *C2); + static Constant *getShl(Constant *C1, Constant *C2); + static Constant *getLShr(Constant *C1, Constant *C2); + static Constant *getAShr(Constant *C1, Constant *C2); + static Constant *getTrunc (Constant *C, const Type *Ty); + static Constant *getSExt (Constant *C, const Type *Ty); + static Constant *getZExt (Constant *C, const Type *Ty); + static Constant *getFPTrunc (Constant *C, const Type *Ty); + static Constant *getFPExtend(Constant *C, const Type *Ty); + static Constant *getUIToFP (Constant *C, const Type *Ty); + static Constant *getSIToFP (Constant *C, const Type *Ty); + static Constant *getFPToUI (Constant *C, const Type *Ty); + static Constant *getFPToSI (Constant *C, const Type *Ty); + static Constant *getPtrToInt(Constant *C, const Type *Ty); + static Constant *getIntToPtr(Constant *C, const Type *Ty); + static Constant *getBitCast (Constant *C, const Type *Ty); + + static Constant *getNSWAdd(Constant *C1, Constant *C2); + static Constant *getNSWSub(Constant *C1, Constant *C2); + static Constant *getExactSDiv(Constant *C1, Constant *C2); + + /// Transparently provide more efficient getOperand methods. + DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Constant); + + // @brief Convenience function for getting one of the casting operations + // using a CastOps opcode. + static Constant *getCast( + unsigned ops, ///< The opcode for the conversion + Constant *C, ///< The constant to be converted + const Type *Ty ///< The type to which the constant is converted + ); + + // @brief Create a ZExt or BitCast cast constant expression + static Constant *getZExtOrBitCast( + Constant *C, ///< The constant to zext or bitcast + const Type *Ty ///< The type to zext or bitcast C to + ); + + // @brief Create a SExt or BitCast cast constant expression + static Constant *getSExtOrBitCast( + Constant *C, ///< The constant to sext or bitcast + const Type *Ty ///< The type to sext or bitcast C to + ); + + // @brief Create a Trunc or BitCast cast constant expression + static Constant *getTruncOrBitCast( + Constant *C, ///< The constant to trunc or bitcast + const Type *Ty ///< The type to trunc or bitcast C to + ); + + /// @brief Create a BitCast or a PtrToInt cast constant expression + static Constant *getPointerCast( + Constant *C, ///< The pointer value to be casted (operand 0) + const Type *Ty ///< The type to which cast should be made + ); + + /// @brief Create a ZExt, Bitcast or Trunc for integer -> integer casts + static Constant *getIntegerCast( + Constant *C, ///< The integer constant to be casted + const Type *Ty, ///< The integer type to cast to + bool isSigned ///< Whether C should be treated as signed or not + ); + + /// @brief Create a FPExt, Bitcast or FPTrunc for fp -> fp casts + static Constant *getFPCast( + Constant *C, ///< The integer constant to be casted + const Type *Ty ///< The integer type to cast to + ); + + /// @brief Return true if this is a convert constant expression + bool isCast() const; + + /// @brief Return true if this is a compare constant expression + bool isCompare() const; + + /// @brief Return true if this is an insertvalue or extractvalue expression, + /// and the getIndices() method may be used. + bool hasIndices() const; + + /// @brief Return true if this is a getelementptr expression and all + /// the index operands are compile-time known integers within the + /// corresponding notional static array extents. Note that this is + /// not equivalant to, a subset of, or a superset of the "inbounds" + /// property. + bool isGEPWithNoNotionalOverIndexing() const; + + /// Select constant expr + /// + static Constant *getSelect(Constant *C, Constant *V1, Constant *V2) { + return getSelectTy(V1->getType(), C, V1, V2); + } + + /// get - Return a binary or shift operator constant expression, + /// folding if possible. + /// + static Constant *get(unsigned Opcode, Constant *C1, Constant *C2, + unsigned Flags = 0); + + /// @brief Return an ICmp or FCmp comparison operator constant expression. + static Constant *getCompare(unsigned short pred, Constant *C1, Constant *C2); + + /// get* - Return some common constants without having to + /// specify the full Instruction::OPCODE identifier. + /// + static Constant *getICmp(unsigned short pred, Constant *LHS, Constant *RHS); + static Constant *getFCmp(unsigned short pred, Constant *LHS, Constant *RHS); + + /// Getelementptr form. std::vector is only accepted for convenience: + /// all elements must be Constant's. + /// + static Constant *getGetElementPtr(Constant *C, + Constant *const *IdxList, unsigned NumIdx); + static Constant *getGetElementPtr(Constant *C, + Value* const *IdxList, unsigned NumIdx); + + /// Create an "inbounds" getelementptr. See the documentation for the + /// "inbounds" flag in LangRef.html for details. + static Constant *getInBoundsGetElementPtr(Constant *C, + Constant *const *IdxList, + unsigned NumIdx); + static Constant *getInBoundsGetElementPtr(Constant *C, + Value* const *IdxList, + unsigned NumIdx); + + static Constant *getExtractElement(Constant *Vec, Constant *Idx); + static Constant *getInsertElement(Constant *Vec, Constant *Elt,Constant *Idx); + static Constant *getShuffleVector(Constant *V1, Constant *V2, Constant *Mask); + static Constant *getExtractValue(Constant *Agg, + const unsigned *IdxList, unsigned NumIdx); + static Constant *getInsertValue(Constant *Agg, Constant *Val, + const unsigned *IdxList, unsigned NumIdx); + + /// isNullValue - Return true if this is the value that would be returned by + /// getNullValue. + virtual bool isNullValue() const { return false; } + + /// getOpcode - Return the opcode at the root of this constant expression + unsigned getOpcode() const { return SubclassData; } + + /// getPredicate - Return the ICMP or FCMP predicate value. Assert if this is + /// not an ICMP or FCMP constant expression. + unsigned getPredicate() const; + + /// getIndices - Assert that this is an insertvalue or exactvalue + /// expression and return the list of indices. + const SmallVector &getIndices() const; + + /// getOpcodeName - Return a string representation for an opcode. + const char *getOpcodeName() const; + + /// getWithOperandReplaced - Return a constant expression identical to this + /// one, but with the specified operand set to the specified value. + Constant *getWithOperandReplaced(unsigned OpNo, Constant *Op) const; + + /// getWithOperands - This returns the current constant expression with the + /// operands replaced with the specified values. The specified operands must + /// match count and type with the existing ones. + Constant *getWithOperands(const std::vector &Ops) const { + return getWithOperands(&Ops[0], (unsigned)Ops.size()); + } + Constant *getWithOperands(Constant *const *Ops, unsigned NumOps) const; + + virtual void destroyConstant(); + virtual void replaceUsesOfWithOnConstant(Value *From, Value *To, Use *U); + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const ConstantExpr *) { return true; } + static inline bool classof(const Value *V) { + return V->getValueID() == ConstantExprVal; + } +}; + +template <> +struct OperandTraits : public VariadicOperandTraits<1> { +}; + +DEFINE_TRANSPARENT_CASTED_OPERAND_ACCESSORS(ConstantExpr, Constant) + +//===----------------------------------------------------------------------===// +/// UndefValue - 'undef' values are things that do not have specified contents. +/// These are used for a variety of purposes, including global variable +/// initializers and operands to instructions. 'undef' values can occur with +/// any type. +/// +class UndefValue : public Constant { + friend struct ConstantCreator; + void *operator new(size_t, unsigned); // DO NOT IMPLEMENT + UndefValue(const UndefValue &); // DO NOT IMPLEMENT +protected: + explicit UndefValue(const Type *T) : Constant(T, UndefValueVal, 0, 0) {} +protected: + // allocate space for exactly zero operands + void *operator new(size_t s) { + return User::operator new(s, 0); + } +public: + /// get() - Static factory methods - Return an 'undef' object of the specified + /// type. + /// + static UndefValue *get(const Type *T); + + /// isNullValue - Return true if this is the value that would be returned by + /// getNullValue. + virtual bool isNullValue() const { return false; } + + virtual void destroyConstant(); + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const UndefValue *) { return true; } + static bool classof(const Value *V) { + return V->getValueID() == UndefValueVal; + } +}; +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/DerivedTypes.h b/libclamav/c++/llvm/include/llvm/DerivedTypes.h new file mode 100644 index 000000000..fb51430b4 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/DerivedTypes.h @@ -0,0 +1,518 @@ +//===-- llvm/DerivedTypes.h - Classes for handling data types ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the declarations of classes that represent "derived +// types". These are things like "arrays of x" or "structure of x, y, z" or +// "method returning x taking (y,z) as parameters", etc... +// +// The implementations of these classes live in the Type.cpp file. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DERIVED_TYPES_H +#define LLVM_DERIVED_TYPES_H + +#include "llvm/Type.h" + +namespace llvm { + +class Value; +template class TypeMap; +class FunctionValType; +class ArrayValType; +class StructValType; +class PointerValType; +class VectorValType; +class IntegerValType; +class APInt; +class LLVMContext; + +class DerivedType : public Type { + friend class Type; + +protected: + explicit DerivedType(LLVMContext &C, TypeID id) : Type(C, id) {} + + /// notifyUsesThatTypeBecameConcrete - Notify AbstractTypeUsers of this type + /// that the current type has transitioned from being abstract to being + /// concrete. + /// + void notifyUsesThatTypeBecameConcrete(); + + /// dropAllTypeUses - When this (abstract) type is resolved to be equal to + /// another (more concrete) type, we must eliminate all references to other + /// types, to avoid some circular reference problems. + /// + void dropAllTypeUses(); + + /// unlockedRefineAbstractTypeTo - Internal version of refineAbstractTypeTo + /// that performs no locking. Only used for internal recursion. + void unlockedRefineAbstractTypeTo(const Type *NewType); + +public: + + //===--------------------------------------------------------------------===// + // Abstract Type handling methods - These types have special lifetimes, which + // are managed by (add|remove)AbstractTypeUser. See comments in + // AbstractTypeUser.h for more information. + + /// refineAbstractTypeTo - This function is used to when it is discovered that + /// the 'this' abstract type is actually equivalent to the NewType specified. + /// This causes all users of 'this' to switch to reference the more concrete + /// type NewType and for 'this' to be deleted. + /// + void refineAbstractTypeTo(const Type *NewType); + + void dump() const { Type::dump(); } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const DerivedType *) { return true; } + static inline bool classof(const Type *T) { + return T->isDerivedType(); + } +}; + +/// Class to represent integer types. Note that this class is also used to +/// represent the built-in integer types: Int1Ty, Int8Ty, Int16Ty, Int32Ty and +/// Int64Ty. +/// @brief Integer representation type +class IntegerType : public DerivedType { + friend class LLVMContextImpl; + +protected: + explicit IntegerType(LLVMContext &C, unsigned NumBits) : + DerivedType(C, IntegerTyID) { + setSubclassData(NumBits); + } + friend class TypeMap; +public: + /// This enum is just used to hold constants we need for IntegerType. + enum { + MIN_INT_BITS = 1, ///< Minimum number of bits that can be specified + MAX_INT_BITS = (1<<23)-1 ///< Maximum number of bits that can be specified + ///< Note that bit width is stored in the Type classes SubclassData field + ///< which has 23 bits. This yields a maximum bit width of 8,388,607 bits. + }; + + /// This static method is the primary way of constructing an IntegerType. + /// If an IntegerType with the same NumBits value was previously instantiated, + /// that instance will be returned. Otherwise a new one will be created. Only + /// one instance with a given NumBits value is ever created. + /// @brief Get or create an IntegerType instance. + static const IntegerType* get(LLVMContext &C, unsigned NumBits); + + /// @brief Get the number of bits in this IntegerType + unsigned getBitWidth() const { return getSubclassData(); } + + /// getBitMask - Return a bitmask with ones set for all of the bits + /// that can be set by an unsigned version of this type. This is 0xFF for + /// i8, 0xFFFF for i16, etc. + uint64_t getBitMask() const { + return ~uint64_t(0UL) >> (64-getBitWidth()); + } + + /// getSignBit - Return a uint64_t with just the most significant bit set (the + /// sign bit, if the value is treated as a signed number). + uint64_t getSignBit() const { + return 1ULL << (getBitWidth()-1); + } + + /// For example, this is 0xFF for an 8 bit integer, 0xFFFF for i16, etc. + /// @returns a bit mask with ones set for all the bits of this type. + /// @brief Get a bit mask for this type. + APInt getMask() const; + + /// This method determines if the width of this IntegerType is a power-of-2 + /// in terms of 8 bit bytes. + /// @returns true if this is a power-of-2 byte width. + /// @brief Is this a power-of-2 byte-width IntegerType ? + bool isPowerOf2ByteWidth() const; + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const IntegerType *) { return true; } + static inline bool classof(const Type *T) { + return T->getTypeID() == IntegerTyID; + } +}; + + +/// FunctionType - Class to represent function types +/// +class FunctionType : public DerivedType { + friend class TypeMap; + bool isVarArgs; + + FunctionType(const FunctionType &); // Do not implement + const FunctionType &operator=(const FunctionType &); // Do not implement + FunctionType(const Type *Result, const std::vector &Params, + bool IsVarArgs); + +public: + /// FunctionType::get - This static method is the primary way of constructing + /// a FunctionType. + /// + static FunctionType *get( + const Type *Result, ///< The result type + const std::vector &Params, ///< The types of the parameters + bool isVarArg ///< Whether this is a variable argument length function + ); + + /// FunctionType::get - Create a FunctionType taking no parameters. + /// + static FunctionType *get( + const Type *Result, ///< The result type + bool isVarArg ///< Whether this is a variable argument length function + ) { + return get(Result, std::vector(), isVarArg); + } + + /// isValidReturnType - Return true if the specified type is valid as a return + /// type. + static bool isValidReturnType(const Type *RetTy); + + /// isValidArgumentType - Return true if the specified type is valid as an + /// argument type. + static bool isValidArgumentType(const Type *ArgTy); + + inline bool isVarArg() const { return isVarArgs; } + inline const Type *getReturnType() const { return ContainedTys[0]; } + + typedef Type::subtype_iterator param_iterator; + param_iterator param_begin() const { return ContainedTys + 1; } + param_iterator param_end() const { return &ContainedTys[NumContainedTys]; } + + // Parameter type accessors... + const Type *getParamType(unsigned i) const { return ContainedTys[i+1]; } + + /// getNumParams - Return the number of fixed parameters this function type + /// requires. This does not consider varargs. + /// + unsigned getNumParams() const { return NumContainedTys - 1; } + + // Implement the AbstractTypeUser interface. + virtual void refineAbstractType(const DerivedType *OldTy, const Type *NewTy); + virtual void typeBecameConcrete(const DerivedType *AbsTy); + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const FunctionType *) { return true; } + static inline bool classof(const Type *T) { + return T->getTypeID() == FunctionTyID; + } +}; + + +/// CompositeType - Common super class of ArrayType, StructType, PointerType +/// and VectorType +class CompositeType : public DerivedType { +protected: + inline explicit CompositeType(LLVMContext &C, TypeID id) : + DerivedType(C, id) { } +public: + + /// getTypeAtIndex - Given an index value into the type, return the type of + /// the element. + /// + virtual const Type *getTypeAtIndex(const Value *V) const = 0; + virtual const Type *getTypeAtIndex(unsigned Idx) const = 0; + virtual bool indexValid(const Value *V) const = 0; + virtual bool indexValid(unsigned Idx) const = 0; + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const CompositeType *) { return true; } + static inline bool classof(const Type *T) { + return T->getTypeID() == ArrayTyID || + T->getTypeID() == StructTyID || + T->getTypeID() == PointerTyID || + T->getTypeID() == VectorTyID; + } +}; + + +/// StructType - Class to represent struct types +/// +class StructType : public CompositeType { + friend class TypeMap; + StructType(const StructType &); // Do not implement + const StructType &operator=(const StructType &); // Do not implement + StructType(LLVMContext &C, + const std::vector &Types, bool isPacked); +public: + /// StructType::get - This static method is the primary way to create a + /// StructType. + /// + static StructType *get(LLVMContext &Context, + const std::vector &Params, + bool isPacked=false); + + /// StructType::get - Create an empty structure type. + /// + static StructType *get(LLVMContext &Context, bool isPacked=false) { + return get(Context, std::vector(), isPacked); + } + + /// StructType::get - This static method is a convenience method for + /// creating structure types by specifying the elements as arguments. + /// Note that this method always returns a non-packed struct. To get + /// an empty struct, pass NULL, NULL. + static StructType *get(LLVMContext &Context, + const Type *type, ...) END_WITH_NULL; + + /// isValidElementType - Return true if the specified type is valid as a + /// element type. + static bool isValidElementType(const Type *ElemTy); + + // Iterator access to the elements + typedef Type::subtype_iterator element_iterator; + element_iterator element_begin() const { return ContainedTys; } + element_iterator element_end() const { return &ContainedTys[NumContainedTys];} + + // Random access to the elements + unsigned getNumElements() const { return NumContainedTys; } + const Type *getElementType(unsigned N) const { + assert(N < NumContainedTys && "Element number out of range!"); + return ContainedTys[N]; + } + + /// getTypeAtIndex - Given an index value into the type, return the type of + /// the element. For a structure type, this must be a constant value... + /// + virtual const Type *getTypeAtIndex(const Value *V) const; + virtual const Type *getTypeAtIndex(unsigned Idx) const; + virtual bool indexValid(const Value *V) const; + virtual bool indexValid(unsigned Idx) const; + + // Implement the AbstractTypeUser interface. + virtual void refineAbstractType(const DerivedType *OldTy, const Type *NewTy); + virtual void typeBecameConcrete(const DerivedType *AbsTy); + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const StructType *) { return true; } + static inline bool classof(const Type *T) { + return T->getTypeID() == StructTyID; + } + + bool isPacked() const { return (0 != getSubclassData()) ? true : false; } +}; + + +/// SequentialType - This is the superclass of the array, pointer and vector +/// type classes. All of these represent "arrays" in memory. The array type +/// represents a specifically sized array, pointer types are unsized/unknown +/// size arrays, vector types represent specifically sized arrays that +/// allow for use of SIMD instructions. SequentialType holds the common +/// features of all, which stem from the fact that all three lay their +/// components out in memory identically. +/// +class SequentialType : public CompositeType { + PATypeHandle ContainedType; ///< Storage for the single contained type + SequentialType(const SequentialType &); // Do not implement! + const SequentialType &operator=(const SequentialType &); // Do not implement! + + // avoiding warning: 'this' : used in base member initializer list + SequentialType* this_() { return this; } +protected: + SequentialType(TypeID TID, const Type *ElType) + : CompositeType(ElType->getContext(), TID), ContainedType(ElType, this_()) { + ContainedTys = &ContainedType; + NumContainedTys = 1; + } + +public: + inline const Type *getElementType() const { return ContainedTys[0]; } + + virtual bool indexValid(const Value *V) const; + virtual bool indexValid(unsigned) const { + return true; + } + + /// getTypeAtIndex - Given an index value into the type, return the type of + /// the element. For sequential types, there is only one subtype... + /// + virtual const Type *getTypeAtIndex(const Value *) const { + return ContainedTys[0]; + } + virtual const Type *getTypeAtIndex(unsigned) const { + return ContainedTys[0]; + } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const SequentialType *) { return true; } + static inline bool classof(const Type *T) { + return T->getTypeID() == ArrayTyID || + T->getTypeID() == PointerTyID || + T->getTypeID() == VectorTyID; + } +}; + + +/// ArrayType - Class to represent array types +/// +class ArrayType : public SequentialType { + friend class TypeMap; + uint64_t NumElements; + + ArrayType(const ArrayType &); // Do not implement + const ArrayType &operator=(const ArrayType &); // Do not implement + ArrayType(const Type *ElType, uint64_t NumEl); +public: + /// ArrayType::get - This static method is the primary way to construct an + /// ArrayType + /// + static ArrayType *get(const Type *ElementType, uint64_t NumElements); + + /// isValidElementType - Return true if the specified type is valid as a + /// element type. + static bool isValidElementType(const Type *ElemTy); + + inline uint64_t getNumElements() const { return NumElements; } + + // Implement the AbstractTypeUser interface. + virtual void refineAbstractType(const DerivedType *OldTy, const Type *NewTy); + virtual void typeBecameConcrete(const DerivedType *AbsTy); + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const ArrayType *) { return true; } + static inline bool classof(const Type *T) { + return T->getTypeID() == ArrayTyID; + } +}; + +/// VectorType - Class to represent vector types +/// +class VectorType : public SequentialType { + friend class TypeMap; + unsigned NumElements; + + VectorType(const VectorType &); // Do not implement + const VectorType &operator=(const VectorType &); // Do not implement + VectorType(const Type *ElType, unsigned NumEl); +public: + /// VectorType::get - This static method is the primary way to construct an + /// VectorType + /// + static VectorType *get(const Type *ElementType, unsigned NumElements); + + /// VectorType::getInteger - This static method gets a VectorType with the + /// same number of elements as the input type, and the element type is an + /// integer type of the same width as the input element type. + /// + static VectorType *getInteger(const VectorType *VTy) { + unsigned EltBits = VTy->getElementType()->getPrimitiveSizeInBits(); + const Type *EltTy = IntegerType::get(VTy->getContext(), EltBits); + return VectorType::get(EltTy, VTy->getNumElements()); + } + + /// VectorType::getExtendedElementVectorType - This static method is like + /// getInteger except that the element types are twice as wide as the + /// elements in the input type. + /// + static VectorType *getExtendedElementVectorType(const VectorType *VTy) { + unsigned EltBits = VTy->getElementType()->getPrimitiveSizeInBits(); + const Type *EltTy = IntegerType::get(VTy->getContext(), EltBits * 2); + return VectorType::get(EltTy, VTy->getNumElements()); + } + + /// VectorType::getTruncatedElementVectorType - This static method is like + /// getInteger except that the element types are half as wide as the + /// elements in the input type. + /// + static VectorType *getTruncatedElementVectorType(const VectorType *VTy) { + unsigned EltBits = VTy->getElementType()->getPrimitiveSizeInBits(); + assert((EltBits & 1) == 0 && + "Cannot truncate vector element with odd bit-width"); + const Type *EltTy = IntegerType::get(VTy->getContext(), EltBits / 2); + return VectorType::get(EltTy, VTy->getNumElements()); + } + + /// isValidElementType - Return true if the specified type is valid as a + /// element type. + static bool isValidElementType(const Type *ElemTy); + + /// @brief Return the number of elements in the Vector type. + inline unsigned getNumElements() const { return NumElements; } + + /// @brief Return the number of bits in the Vector type. + inline unsigned getBitWidth() const { + return NumElements * getElementType()->getPrimitiveSizeInBits(); + } + + // Implement the AbstractTypeUser interface. + virtual void refineAbstractType(const DerivedType *OldTy, const Type *NewTy); + virtual void typeBecameConcrete(const DerivedType *AbsTy); + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const VectorType *) { return true; } + static inline bool classof(const Type *T) { + return T->getTypeID() == VectorTyID; + } +}; + + +/// PointerType - Class to represent pointers +/// +class PointerType : public SequentialType { + friend class TypeMap; + unsigned AddressSpace; + + PointerType(const PointerType &); // Do not implement + const PointerType &operator=(const PointerType &); // Do not implement + explicit PointerType(const Type *ElType, unsigned AddrSpace); +public: + /// PointerType::get - This constructs a pointer to an object of the specified + /// type in a numbered address space. + static PointerType *get(const Type *ElementType, unsigned AddressSpace); + + /// PointerType::getUnqual - This constructs a pointer to an object of the + /// specified type in the generic address space (address space zero). + static PointerType *getUnqual(const Type *ElementType) { + return PointerType::get(ElementType, 0); + } + + /// isValidElementType - Return true if the specified type is valid as a + /// element type. + static bool isValidElementType(const Type *ElemTy); + + /// @brief Return the address space of the Pointer type. + inline unsigned getAddressSpace() const { return AddressSpace; } + + // Implement the AbstractTypeUser interface. + virtual void refineAbstractType(const DerivedType *OldTy, const Type *NewTy); + virtual void typeBecameConcrete(const DerivedType *AbsTy); + + // Implement support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const PointerType *) { return true; } + static inline bool classof(const Type *T) { + return T->getTypeID() == PointerTyID; + } +}; + + +/// OpaqueType - Class to represent abstract types +/// +class OpaqueType : public DerivedType { + OpaqueType(const OpaqueType &); // DO NOT IMPLEMENT + const OpaqueType &operator=(const OpaqueType &); // DO NOT IMPLEMENT + OpaqueType(LLVMContext &C); +public: + /// OpaqueType::get - Static factory method for the OpaqueType class... + /// + static OpaqueType *get(LLVMContext &C) { + return new OpaqueType(C); // All opaque types are distinct + } + + // Implement support for type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const OpaqueType *) { return true; } + static inline bool classof(const Type *T) { + return T->getTypeID() == OpaqueTyID; + } +}; + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/ExecutionEngine/ExecutionEngine.h b/libclamav/c++/llvm/include/llvm/ExecutionEngine/ExecutionEngine.h new file mode 100644 index 000000000..d2c547dcf --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/ExecutionEngine/ExecutionEngine.h @@ -0,0 +1,510 @@ +//===- ExecutionEngine.h - Abstract Execution Engine Interface --*- 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 the abstract interface that implements execution support +// for LLVM. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_EXECUTION_ENGINE_H +#define LLVM_EXECUTION_ENGINE_H + +#include +#include +#include +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/ValueMap.h" +#include "llvm/Support/ValueHandle.h" +#include "llvm/System/Mutex.h" +#include "llvm/Target/TargetMachine.h" + +namespace llvm { + +struct GenericValue; +class Constant; +class ExecutionEngine; +class Function; +class GlobalVariable; +class GlobalValue; +class JITEventListener; +class JITMemoryManager; +class MachineCodeInfo; +class Module; +class ModuleProvider; +class MutexGuard; +class TargetData; +class Type; + +class ExecutionEngineState { +public: + struct AddressMapConfig : public ValueMapConfig { + typedef ExecutionEngineState *ExtraData; + static sys::Mutex *getMutex(ExecutionEngineState *EES); + static void onDelete(ExecutionEngineState *EES, const GlobalValue *Old); + static void onRAUW(ExecutionEngineState *, const GlobalValue *, + const GlobalValue *); + }; + + typedef ValueMap + GlobalAddressMapTy; + +private: + ExecutionEngine &EE; + + /// GlobalAddressMap - A mapping between LLVM global values and their + /// actualized version... + GlobalAddressMapTy GlobalAddressMap; + + /// GlobalAddressReverseMap - This is the reverse mapping of GlobalAddressMap, + /// used to convert raw addresses into the LLVM global value that is emitted + /// at the address. This map is not computed unless getGlobalValueAtAddress + /// is called at some point. + std::map > GlobalAddressReverseMap; + +public: + ExecutionEngineState(ExecutionEngine &EE); + + GlobalAddressMapTy & + getGlobalAddressMap(const MutexGuard &) { + return GlobalAddressMap; + } + + std::map > & + getGlobalAddressReverseMap(const MutexGuard &) { + return GlobalAddressReverseMap; + } + + // Returns the address ToUnmap was mapped to. + void *RemoveMapping(const MutexGuard &, const GlobalValue *ToUnmap); +}; + + +class ExecutionEngine { + const TargetData *TD; + ExecutionEngineState EEState; + bool CompilingLazily; + bool GVCompilationDisabled; + bool SymbolSearchingDisabled; + + friend class EngineBuilder; // To allow access to JITCtor and InterpCtor. + +protected: + /// Modules - This is a list of ModuleProvider's that we are JIT'ing from. We + /// use a smallvector to optimize for the case where there is only one module. + SmallVector Modules; + + void setTargetData(const TargetData *td) { + TD = td; + } + + /// getMemoryforGV - Allocate memory for a global variable. + virtual char* getMemoryForGV(const GlobalVariable* GV); + + // To avoid having libexecutionengine depend on the JIT and interpreter + // libraries, the JIT and Interpreter set these functions to ctor pointers + // at startup time if they are linked in. + static ExecutionEngine *(*JITCtor)(ModuleProvider *MP, + std::string *ErrorStr, + JITMemoryManager *JMM, + CodeGenOpt::Level OptLevel, + bool GVsWithCode, + CodeModel::Model CMM); + static ExecutionEngine *(*InterpCtor)(ModuleProvider *MP, + std::string *ErrorStr); + + /// LazyFunctionCreator - If an unknown function is needed, this function + /// pointer is invoked to create it. If this returns null, the JIT will abort. + void* (*LazyFunctionCreator)(const std::string &); + + /// ExceptionTableRegister - If Exception Handling is set, the JIT will + /// register dwarf tables with this function + typedef void (*EERegisterFn)(void*); + static EERegisterFn ExceptionTableRegister; + +public: + /// lock - This lock is protects the ExecutionEngine, JIT, JITResolver and + /// JITEmitter classes. It must be held while changing the internal state of + /// any of those classes. + sys::Mutex lock; // Used to make this class and subclasses thread-safe + + //===--------------------------------------------------------------------===// + // ExecutionEngine Startup + //===--------------------------------------------------------------------===// + + virtual ~ExecutionEngine(); + + /// create - This is the factory method for creating an execution engine which + /// is appropriate for the current machine. This takes ownership of the + /// module provider. + static ExecutionEngine *create(ModuleProvider *MP, + bool ForceInterpreter = false, + std::string *ErrorStr = 0, + CodeGenOpt::Level OptLevel = + CodeGenOpt::Default, + // Allocating globals with code breaks + // freeMachineCodeForFunction and is probably + // unsafe and bad for performance. However, + // we have clients who depend on this + // behavior, so we must support it. + // Eventually, when we're willing to break + // some backwards compatability, this flag + // should be flipped to false, so that by + // default freeMachineCodeForFunction works. + bool GVsWithCode = true); + + /// create - This is the factory method for creating an execution engine which + /// is appropriate for the current machine. This takes ownership of the + /// module. + static ExecutionEngine *create(Module *M); + + /// createJIT - This is the factory method for creating a JIT for the current + /// machine, it does not fall back to the interpreter. This takes ownership + /// of the ModuleProvider and JITMemoryManager if successful. + /// + /// Clients should make sure to initialize targets prior to calling this + /// function. + static ExecutionEngine *createJIT(ModuleProvider *MP, + std::string *ErrorStr = 0, + JITMemoryManager *JMM = 0, + CodeGenOpt::Level OptLevel = + CodeGenOpt::Default, + bool GVsWithCode = true, + CodeModel::Model CMM = + CodeModel::Default); + + /// addModuleProvider - Add a ModuleProvider to the list of modules that we + /// can JIT from. Note that this takes ownership of the ModuleProvider: when + /// the ExecutionEngine is destroyed, it destroys the MP as well. + virtual void addModuleProvider(ModuleProvider *P) { + Modules.push_back(P); + } + + //===----------------------------------------------------------------------===// + + const TargetData *getTargetData() const { return TD; } + + + /// removeModuleProvider - Remove a ModuleProvider from the list of modules. + /// Relases the Module from the ModuleProvider, materializing it in the + /// process, and returns the materialized Module. + virtual Module* removeModuleProvider(ModuleProvider *P, + std::string *ErrInfo = 0); + + /// deleteModuleProvider - Remove a ModuleProvider from the list of modules, + /// and deletes the ModuleProvider and owned Module. Avoids materializing + /// the underlying module. + virtual void deleteModuleProvider(ModuleProvider *P,std::string *ErrInfo = 0); + + /// FindFunctionNamed - Search all of the active modules to find the one that + /// defines FnName. This is very slow operation and shouldn't be used for + /// general code. + Function *FindFunctionNamed(const char *FnName); + + /// runFunction - Execute the specified function with the specified arguments, + /// and return the result. + /// + virtual GenericValue runFunction(Function *F, + const std::vector &ArgValues) = 0; + + /// runStaticConstructorsDestructors - This method is used to execute all of + /// the static constructors or destructors for a program, depending on the + /// value of isDtors. + void runStaticConstructorsDestructors(bool isDtors); + /// runStaticConstructorsDestructors - This method is used to execute all of + /// the static constructors or destructors for a module, depending on the + /// value of isDtors. + void runStaticConstructorsDestructors(Module *module, bool isDtors); + + + /// runFunctionAsMain - This is a helper function which wraps runFunction to + /// handle the common task of starting up main with the specified argc, argv, + /// and envp parameters. + int runFunctionAsMain(Function *Fn, const std::vector &argv, + const char * const * envp); + + + /// addGlobalMapping - Tell the execution engine that the specified global is + /// at the specified location. This is used internally as functions are JIT'd + /// and as global variables are laid out in memory. It can and should also be + /// used by clients of the EE that want to have an LLVM global overlay + /// existing data in memory. Mappings are automatically removed when their + /// GlobalValue is destroyed. + void addGlobalMapping(const GlobalValue *GV, void *Addr); + + /// clearAllGlobalMappings - Clear all global mappings and start over again + /// use in dynamic compilation scenarios when you want to move globals + void clearAllGlobalMappings(); + + /// clearGlobalMappingsFromModule - Clear all global mappings that came from a + /// particular module, because it has been removed from the JIT. + void clearGlobalMappingsFromModule(Module *M); + + /// updateGlobalMapping - Replace an existing mapping for GV with a new + /// address. This updates both maps as required. If "Addr" is null, the + /// entry for the global is removed from the mappings. This returns the old + /// value of the pointer, or null if it was not in the map. + void *updateGlobalMapping(const GlobalValue *GV, void *Addr); + + /// getPointerToGlobalIfAvailable - This returns the address of the specified + /// global value if it is has already been codegen'd, otherwise it returns + /// null. + /// + void *getPointerToGlobalIfAvailable(const GlobalValue *GV); + + /// getPointerToGlobal - This returns the address of the specified global + /// value. This may involve code generation if it's a function. + /// + void *getPointerToGlobal(const GlobalValue *GV); + + /// getPointerToFunction - The different EE's represent function bodies in + /// different ways. They should each implement this to say what a function + /// pointer should look like. When F is destroyed, the ExecutionEngine will + /// remove its global mapping and free any machine code. Be sure no threads + /// are running inside F when that happens. + /// + virtual void *getPointerToFunction(Function *F) = 0; + + /// getPointerToBasicBlock - The different EE's represent basic blocks in + /// different ways. Return the representation for a blockaddress of the + /// specified block. + /// + virtual void *getPointerToBasicBlock(BasicBlock *BB) = 0; + + /// getPointerToFunctionOrStub - If the specified function has been + /// code-gen'd, return a pointer to the function. If not, compile it, or use + /// a stub to implement lazy compilation if available. See + /// getPointerToFunction for the requirements on destroying F. + /// + virtual void *getPointerToFunctionOrStub(Function *F) { + // Default implementation, just codegen the function. + return getPointerToFunction(F); + } + + // The JIT overrides a version that actually does this. + virtual void runJITOnFunction(Function *, MachineCodeInfo * = 0) { } + + /// getGlobalValueAtAddress - Return the LLVM global value object that starts + /// at the specified address. + /// + const GlobalValue *getGlobalValueAtAddress(void *Addr); + + + void StoreValueToMemory(const GenericValue &Val, GenericValue *Ptr, + const Type *Ty); + void InitializeMemory(const Constant *Init, void *Addr); + + /// recompileAndRelinkFunction - This method is used to force a function + /// which has already been compiled to be compiled again, possibly + /// after it has been modified. Then the entry to the old copy is overwritten + /// with a branch to the new copy. If there was no old copy, this acts + /// just like VM::getPointerToFunction(). + /// + virtual void *recompileAndRelinkFunction(Function *F) = 0; + + /// freeMachineCodeForFunction - Release memory in the ExecutionEngine + /// corresponding to the machine code emitted to execute this function, useful + /// for garbage-collecting generated code. + /// + virtual void freeMachineCodeForFunction(Function *F) = 0; + + /// getOrEmitGlobalVariable - Return the address of the specified global + /// variable, possibly emitting it to memory if needed. This is used by the + /// Emitter. + virtual void *getOrEmitGlobalVariable(const GlobalVariable *GV) { + return getPointerToGlobal((GlobalValue*)GV); + } + + /// Registers a listener to be called back on various events within + /// the JIT. See JITEventListener.h for more details. Does not + /// take ownership of the argument. The argument may be NULL, in + /// which case these functions do nothing. + virtual void RegisterJITEventListener(JITEventListener *) {} + virtual void UnregisterJITEventListener(JITEventListener *) {} + + /// DisableLazyCompilation - When lazy compilation is off (the default), the + /// JIT will eagerly compile every function reachable from the argument to + /// getPointerToFunction. If lazy compilation is turned on, the JIT will only + /// compile the one function and emit stubs to compile the rest when they're + /// first called. If lazy compilation is turned off again while some lazy + /// stubs are still around, and one of those stubs is called, the program will + /// abort. + /// + /// In order to safely compile lazily in a threaded program, the user must + /// ensure that 1) only one thread at a time can call any particular lazy + /// stub, and 2) any thread modifying LLVM IR must hold the JIT's lock + /// (ExecutionEngine::lock) or otherwise ensure that no other thread calls a + /// lazy stub. See http://llvm.org/PR5184 for details. + void DisableLazyCompilation(bool Disabled = true) { + CompilingLazily = !Disabled; + } + bool isCompilingLazily() const { + return CompilingLazily; + } + // Deprecated in favor of isCompilingLazily (to reduce double-negatives). + // Remove this in LLVM 2.8. + bool isLazyCompilationDisabled() const { + return !CompilingLazily; + } + + /// DisableGVCompilation - If called, the JIT will abort if it's asked to + /// allocate space and populate a GlobalVariable that is not internal to + /// the module. + void DisableGVCompilation(bool Disabled = true) { + GVCompilationDisabled = Disabled; + } + bool isGVCompilationDisabled() const { + return GVCompilationDisabled; + } + + /// DisableSymbolSearching - If called, the JIT will not try to lookup unknown + /// symbols with dlsym. A client can still use InstallLazyFunctionCreator to + /// resolve symbols in a custom way. + void DisableSymbolSearching(bool Disabled = true) { + SymbolSearchingDisabled = Disabled; + } + bool isSymbolSearchingDisabled() const { + return SymbolSearchingDisabled; + } + + /// InstallLazyFunctionCreator - If an unknown function is needed, the + /// specified function pointer is invoked to create it. If it returns null, + /// the JIT will abort. + void InstallLazyFunctionCreator(void* (*P)(const std::string &)) { + LazyFunctionCreator = P; + } + + /// InstallExceptionTableRegister - The JIT will use the given function + /// to register the exception tables it generates. + static void InstallExceptionTableRegister(void (*F)(void*)) { + ExceptionTableRegister = F; + } + + /// RegisterTable - Registers the given pointer as an exception table. It uses + /// the ExceptionTableRegister function. + static void RegisterTable(void* res) { + if (ExceptionTableRegister) + ExceptionTableRegister(res); + } + +protected: + explicit ExecutionEngine(ModuleProvider *P); + + void emitGlobals(); + + // EmitGlobalVariable - This method emits the specified global variable to the + // address specified in GlobalAddresses, or allocates new memory if it's not + // already in the map. + void EmitGlobalVariable(const GlobalVariable *GV); + + GenericValue getConstantValue(const Constant *C); + void LoadValueFromMemory(GenericValue &Result, GenericValue *Ptr, + const Type *Ty); +}; + +namespace EngineKind { + // These are actually bitmasks that get or-ed together. + enum Kind { + JIT = 0x1, + Interpreter = 0x2 + }; + const static Kind Either = (Kind)(JIT | Interpreter); +} + +/// EngineBuilder - Builder class for ExecutionEngines. Use this by +/// stack-allocating a builder, chaining the various set* methods, and +/// terminating it with a .create() call. +class EngineBuilder { + + private: + ModuleProvider *MP; + EngineKind::Kind WhichEngine; + std::string *ErrorStr; + CodeGenOpt::Level OptLevel; + JITMemoryManager *JMM; + bool AllocateGVsWithCode; + CodeModel::Model CMModel; + + /// InitEngine - Does the common initialization of default options. + /// + void InitEngine() { + WhichEngine = EngineKind::Either; + ErrorStr = NULL; + OptLevel = CodeGenOpt::Default; + JMM = NULL; + AllocateGVsWithCode = false; + CMModel = CodeModel::Default; + } + + public: + /// EngineBuilder - Constructor for EngineBuilder. If create() is called and + /// is successful, the created engine takes ownership of the module + /// provider. + EngineBuilder(ModuleProvider *mp) : MP(mp) { + InitEngine(); + } + + /// EngineBuilder - Overloaded constructor that automatically creates an + /// ExistingModuleProvider for an existing module. + EngineBuilder(Module *m); + + /// setEngineKind - Controls whether the user wants the interpreter, the JIT, + /// or whichever engine works. This option defaults to EngineKind::Either. + EngineBuilder &setEngineKind(EngineKind::Kind w) { + WhichEngine = w; + return *this; + } + + /// setJITMemoryManager - Sets the memory manager to use. This allows + /// clients to customize their memory allocation policies. If create() is + /// called and is successful, the created engine takes ownership of the + /// memory manager. This option defaults to NULL. + EngineBuilder &setJITMemoryManager(JITMemoryManager *jmm) { + JMM = jmm; + return *this; + } + + /// setErrorStr - Set the error string to write to on error. This option + /// defaults to NULL. + EngineBuilder &setErrorStr(std::string *e) { + ErrorStr = e; + return *this; + } + + /// setOptLevel - Set the optimization level for the JIT. This option + /// defaults to CodeGenOpt::Default. + EngineBuilder &setOptLevel(CodeGenOpt::Level l) { + OptLevel = l; + return *this; + } + + /// setCodeModel - Set the CodeModel that the ExecutionEngine target + /// data is using. Defaults to target specific default "CodeModel::Default". + EngineBuilder &setCodeModel(CodeModel::Model M) { + CMModel = M; + return *this; + } + + /// setAllocateGVsWithCode - Sets whether global values should be allocated + /// into the same buffer as code. For most applications this should be set + /// to false. Allocating globals with code breaks freeMachineCodeForFunction + /// and is probably unsafe and bad for performance. However, we have clients + /// who depend on this behavior, so we must support it. This option defaults + /// to false so that users of the new API can safely use the new memory + /// manager and free machine code. + EngineBuilder &setAllocateGVsWithCode(bool a) { + AllocateGVsWithCode = a; + return *this; + } + + ExecutionEngine *create(); +}; + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/ExecutionEngine/GenericValue.h b/libclamav/c++/llvm/include/llvm/ExecutionEngine/GenericValue.h new file mode 100644 index 000000000..1301320c1 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/ExecutionEngine/GenericValue.h @@ -0,0 +1,44 @@ +//===-- GenericValue.h - Represent any type of LLVM value -------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// The GenericValue class is used to represent an LLVM value of arbitrary type. +// +//===----------------------------------------------------------------------===// + + +#ifndef GENERIC_VALUE_H +#define GENERIC_VALUE_H + +#include "llvm/ADT/APInt.h" +#include "llvm/System/DataTypes.h" + +namespace llvm { + +typedef void* PointerTy; +class APInt; + +struct GenericValue { + union { + double DoubleVal; + float FloatVal; + PointerTy PointerVal; + struct { unsigned int first; unsigned int second; } UIntPairVal; + unsigned char Untyped[8]; + }; + APInt IntVal; // also used for long doubles + + GenericValue() : DoubleVal(0.0), IntVal(1,0) {} + explicit GenericValue(void *V) : PointerVal(V), IntVal(1,0) { } +}; + +inline GenericValue PTOGV(void *P) { return GenericValue(P); } +inline void* GVTOP(const GenericValue &GV) { return GV.PointerVal; } + +} // End llvm namespace +#endif diff --git a/libclamav/c++/llvm/include/llvm/ExecutionEngine/Interpreter.h b/libclamav/c++/llvm/include/llvm/ExecutionEngine/Interpreter.h new file mode 100644 index 000000000..7425cdbcf --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/ExecutionEngine/Interpreter.h @@ -0,0 +1,38 @@ +//===-- Interpreter.h - Abstract Execution Engine Interface -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file forces the interpreter to link in on certain operating systems. +// (Windows). +// +//===----------------------------------------------------------------------===// + +#ifndef EXECUTION_ENGINE_INTERPRETER_H +#define EXECUTION_ENGINE_INTERPRETER_H + +#include "llvm/ExecutionEngine/ExecutionEngine.h" +#include + +extern "C" void LLVMLinkInInterpreter(); + +namespace { + struct ForceInterpreterLinking { + ForceInterpreterLinking() { + // We must reference the passes in such a way that compilers will not + // delete it all as dead code, even with whole program optimization, + // yet is effectively a NO-OP. As the compiler isn't smart enough + // to know that getenv() never returns -1, this will do the job. + if (std::getenv("bar") != (char*) -1) + return; + + LLVMLinkInInterpreter(); + } + } ForceInterpreterLinking; +} + +#endif diff --git a/libclamav/c++/llvm/include/llvm/ExecutionEngine/JIT.h b/libclamav/c++/llvm/include/llvm/ExecutionEngine/JIT.h new file mode 100644 index 000000000..6013db48c --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/ExecutionEngine/JIT.h @@ -0,0 +1,38 @@ +//===-- JIT.h - Abstract Execution Engine Interface -------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file forces the JIT to link in on certain operating systems. +// (Windows). +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_EXECUTION_ENGINE_JIT_H +#define LLVM_EXECUTION_ENGINE_JIT_H + +#include "llvm/ExecutionEngine/ExecutionEngine.h" +#include + +extern "C" void LLVMLinkInJIT(); + +namespace { + struct ForceJITLinking { + ForceJITLinking() { + // We must reference the passes in such a way that compilers will not + // delete it all as dead code, even with whole program optimization, + // yet is effectively a NO-OP. As the compiler isn't smart enough + // to know that getenv() never returns -1, this will do the job. + if (std::getenv("bar") != (char*) -1) + return; + + LLVMLinkInJIT(); + } + } ForceJITLinking; +} + +#endif diff --git a/libclamav/c++/llvm/include/llvm/ExecutionEngine/JITEventListener.h b/libclamav/c++/llvm/include/llvm/ExecutionEngine/JITEventListener.h new file mode 100644 index 000000000..dcc66b2a0 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/ExecutionEngine/JITEventListener.h @@ -0,0 +1,78 @@ +//===- JITEventListener.h - Exposes events from JIT compilation -*- 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 the JITEventListener interface, which lets users get +// callbacks when significant events happen during the JIT compilation process. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_EXECUTION_ENGINE_JIT_EVENTLISTENER_H +#define LLVM_EXECUTION_ENGINE_JIT_EVENTLISTENER_H + +#include "llvm/System/DataTypes.h" +#include "llvm/Support/DebugLoc.h" + +#include + +namespace llvm { +class Function; +class MachineFunction; + +/// Empty for now, but this object will contain all details about the +/// generated machine code that a Listener might care about. +struct JITEvent_EmittedFunctionDetails { + const MachineFunction *MF; + + struct LineStart { + // The address at which the current line changes. + uintptr_t Address; + // The new location information. These can be translated to + // DebugLocTuples using MF->getDebugLocTuple(). + DebugLoc Loc; + }; + // This holds line boundary information sorted by address. + std::vector LineStarts; +}; + +/// JITEventListener - This interface is used by the JIT to notify clients about +/// significant events during compilation. For example, we could have +/// implementations for profilers and debuggers that need to know where +/// functions have been emitted. +/// +/// Each method defaults to doing nothing, so you only need to override the ones +/// you care about. +class JITEventListener { +public: + JITEventListener() {} + virtual ~JITEventListener(); // Defined in JIT.cpp. + + typedef JITEvent_EmittedFunctionDetails EmittedFunctionDetails; + /// NotifyFunctionEmitted - Called after a function has been successfully + /// emitted to memory. The function still has its MachineFunction attached, + /// if you should happen to need that. + virtual void NotifyFunctionEmitted(const Function &F, + void *Code, size_t Size, + const EmittedFunctionDetails &Details) {} + + /// NotifyFreeingMachineCode - This is called inside of + /// freeMachineCodeForFunction(), after the global mapping is removed, but + /// before the machine code is returned to the allocator. OldPtr is the + /// address of the machine code and will be the same as the Code parameter to + /// a previous NotifyFunctionEmitted call. The Function passed to + /// NotifyFunctionEmitted may have been destroyed by the time of the matching + /// NotifyFreeingMachineCode call. + virtual void NotifyFreeingMachineCode(void *OldPtr) {} +}; + +// This returns NULL if support isn't available. +JITEventListener *createOProfileJITEventListener(); + +} // end namespace llvm. + +#endif diff --git a/libclamav/c++/llvm/include/llvm/ExecutionEngine/JITMemoryManager.h b/libclamav/c++/llvm/include/llvm/ExecutionEngine/JITMemoryManager.h new file mode 100644 index 000000000..fd519203e --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/ExecutionEngine/JITMemoryManager.h @@ -0,0 +1,192 @@ +//===-- JITMemoryManager.h - Interface JIT uses to Allocate Mem -*- 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 the JITMemoryManagerInterface +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_EXECUTION_ENGINE_JIT_MEMMANAGER_H +#define LLVM_EXECUTION_ENGINE_JIT_MEMMANAGER_H + +#include "llvm/System/DataTypes.h" +#include + +namespace llvm { + + class Function; + class GlobalValue; + +/// JITMemoryManager - This interface is used by the JIT to allocate and manage +/// memory for the code generated by the JIT. This can be reimplemented by +/// clients that have a strong desire to control how the layout of JIT'd memory +/// works. +class JITMemoryManager { +protected: + bool HasGOT; + bool SizeRequired; +public: + + JITMemoryManager() : HasGOT(false), SizeRequired(false) {} + virtual ~JITMemoryManager(); + + /// CreateDefaultMemManager - This is used to create the default + /// JIT Memory Manager if the client does not provide one to the JIT. + static JITMemoryManager *CreateDefaultMemManager(); + + /// setMemoryWritable - When code generation is in progress, + /// the code pages may need permissions changed. + virtual void setMemoryWritable() = 0; + + /// setMemoryExecutable - When code generation is done and we're ready to + /// start execution, the code pages may need permissions changed. + virtual void setMemoryExecutable() = 0; + + /// setPoisonMemory - Setting this flag to true makes the memory manager + /// garbage values over freed memory. This is useful for testing and + /// debugging, and is be turned on by default in debug mode. + virtual void setPoisonMemory(bool poison) = 0; + + //===--------------------------------------------------------------------===// + // Global Offset Table Management + //===--------------------------------------------------------------------===// + + /// AllocateGOT - If the current table requires a Global Offset Table, this + /// method is invoked to allocate it. This method is required to set HasGOT + /// to true. + virtual void AllocateGOT() = 0; + + /// isManagingGOT - Return true if the AllocateGOT method is called. + /// + bool isManagingGOT() const { + return HasGOT; + } + + /// getGOTBase - If this is managing a Global Offset Table, this method should + /// return a pointer to its base. + virtual uint8_t *getGOTBase() const = 0; + + /// NeedsExactSize - If the memory manager requires to know the size of the + /// objects to be emitted + bool NeedsExactSize() const { + return SizeRequired; + } + + //===--------------------------------------------------------------------===// + // Main Allocation Functions + //===--------------------------------------------------------------------===// + + /// startFunctionBody - When we start JITing a function, the JIT calls this + /// method to allocate a block of free RWX memory, which returns a pointer to + /// it. If the JIT wants to request a block of memory of at least a certain + /// size, it passes that value as ActualSize, and this method returns a block + /// with at least that much space. If the JIT doesn't know ahead of time how + /// much space it will need to emit the function, it passes 0 for the + /// ActualSize. In either case, this method is required to pass back the size + /// of the allocated block through ActualSize. The JIT will be careful to + /// not write more than the returned ActualSize bytes of memory. + virtual uint8_t *startFunctionBody(const Function *F, + uintptr_t &ActualSize) = 0; + + /// allocateStub - This method is called by the JIT to allocate space for a + /// function stub (used to handle limited branch displacements) while it is + /// JIT compiling a function. For example, if foo calls bar, and if bar + /// either needs to be lazily compiled or is a native function that exists too + /// far away from the call site to work, this method will be used to make a + /// thunk for it. The stub should be "close" to the current function body, + /// but should not be included in the 'actualsize' returned by + /// startFunctionBody. + virtual uint8_t *allocateStub(const GlobalValue* F, unsigned StubSize, + unsigned Alignment) = 0; + + /// endFunctionBody - This method is called when the JIT is done codegen'ing + /// the specified function. At this point we know the size of the JIT + /// compiled function. This passes in FunctionStart (which was returned by + /// the startFunctionBody method) and FunctionEnd which is a pointer to the + /// actual end of the function. This method should mark the space allocated + /// and remember where it is in case the client wants to deallocate it. + virtual void endFunctionBody(const Function *F, uint8_t *FunctionStart, + uint8_t *FunctionEnd) = 0; + + /// allocateSpace - Allocate a memory block of the given size. This method + /// cannot be called between calls to startFunctionBody and endFunctionBody. + virtual uint8_t *allocateSpace(intptr_t Size, unsigned Alignment) = 0; + + /// allocateGlobal - Allocate memory for a global. + /// + virtual uint8_t *allocateGlobal(uintptr_t Size, unsigned Alignment) = 0; + + /// deallocateFunctionBody - Free the specified function body. The argument + /// must be the return value from a call to startFunctionBody() that hasn't + /// been deallocated yet. This is never called when the JIT is currently + /// emitting a function. + virtual void deallocateFunctionBody(void *Body) = 0; + + /// startExceptionTable - When we finished JITing the function, if exception + /// handling is set, we emit the exception table. + virtual uint8_t* startExceptionTable(const Function* F, + uintptr_t &ActualSize) = 0; + + /// endExceptionTable - This method is called when the JIT is done emitting + /// the exception table. + virtual void endExceptionTable(const Function *F, uint8_t *TableStart, + uint8_t *TableEnd, uint8_t* FrameRegister) = 0; + + /// deallocateExceptionTable - Free the specified exception table's memory. + /// The argument must be the return value from a call to startExceptionTable() + /// that hasn't been deallocated yet. This is never called when the JIT is + /// currently emitting an exception table. + virtual void deallocateExceptionTable(void *ET) = 0; + + /// CheckInvariants - For testing only. Return true if all internal + /// invariants are preserved, or return false and set ErrorStr to a helpful + /// error message. + virtual bool CheckInvariants(std::string &) { + return true; + } + + /// GetDefaultCodeSlabSize - For testing only. Returns DefaultCodeSlabSize + /// from DefaultJITMemoryManager. + virtual size_t GetDefaultCodeSlabSize() { + return 0; + } + + /// GetDefaultDataSlabSize - For testing only. Returns DefaultCodeSlabSize + /// from DefaultJITMemoryManager. + virtual size_t GetDefaultDataSlabSize() { + return 0; + } + + /// GetDefaultStubSlabSize - For testing only. Returns DefaultCodeSlabSize + /// from DefaultJITMemoryManager. + virtual size_t GetDefaultStubSlabSize() { + return 0; + } + + /// GetNumCodeSlabs - For testing only. Returns the number of MemoryBlocks + /// allocated for code. + virtual unsigned GetNumCodeSlabs() { + return 0; + } + + /// GetNumDataSlabs - For testing only. Returns the number of MemoryBlocks + /// allocated for data. + virtual unsigned GetNumDataSlabs() { + return 0; + } + + /// GetNumStubSlabs - For testing only. Returns the number of MemoryBlocks + /// allocated for function stubs. + virtual unsigned GetNumStubSlabs() { + return 0; + } +}; + +} // end namespace llvm. + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Function.h b/libclamav/c++/llvm/include/llvm/Function.h new file mode 100644 index 000000000..64be545ba --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Function.h @@ -0,0 +1,424 @@ +//===-- llvm/Function.h - Class to represent a single function --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the declaration of the Function class, which represents a +// single function/procedure in LLVM. +// +// A function basically consists of a list of basic blocks, a list of arguments, +// and a symbol table. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_FUNCTION_H +#define LLVM_FUNCTION_H + +#include "llvm/GlobalValue.h" +#include "llvm/CallingConv.h" +#include "llvm/BasicBlock.h" +#include "llvm/Argument.h" +#include "llvm/Attributes.h" +#include "llvm/Support/Compiler.h" + +namespace llvm { + +class FunctionType; +class LLVMContext; + +// Traits for intrusive list of basic blocks... +template<> struct ilist_traits + : public SymbolTableListTraits { + + // createSentinel is used to get hold of the node that marks the end of the + // list... (same trick used here as in ilist_traits) + BasicBlock *createSentinel() const { + return static_cast(&Sentinel); + } + static void destroySentinel(BasicBlock*) {} + + BasicBlock *provideInitialHead() const { return createSentinel(); } + BasicBlock *ensureHead(BasicBlock*) const { return createSentinel(); } + static void noteHead(BasicBlock*, BasicBlock*) {} + + static ValueSymbolTable *getSymTab(Function *ItemParent); +private: + mutable ilist_half_node Sentinel; +}; + +template<> struct ilist_traits + : public SymbolTableListTraits { + + Argument *createSentinel() const { + return static_cast(&Sentinel); + } + static void destroySentinel(Argument*) {} + + Argument *provideInitialHead() const { return createSentinel(); } + Argument *ensureHead(Argument*) const { return createSentinel(); } + static void noteHead(Argument*, Argument*) {} + + static ValueSymbolTable *getSymTab(Function *ItemParent); +private: + mutable ilist_half_node Sentinel; +}; + +class Function : public GlobalValue, + public ilist_node { +public: + typedef iplist ArgumentListType; + typedef iplist BasicBlockListType; + + // BasicBlock iterators... + typedef BasicBlockListType::iterator iterator; + typedef BasicBlockListType::const_iterator const_iterator; + + typedef ArgumentListType::iterator arg_iterator; + typedef ArgumentListType::const_iterator const_arg_iterator; + +private: + // Important things that make up a function! + BasicBlockListType BasicBlocks; ///< The basic blocks + mutable ArgumentListType ArgumentList; ///< The formal arguments + ValueSymbolTable *SymTab; ///< Symbol table of args/instructions + AttrListPtr AttributeList; ///< Parameter attributes + + // The Calling Convention is stored in Value::SubclassData. + /*CallingConv::ID CallingConvention;*/ + + friend class SymbolTableListTraits; + + void setParent(Module *parent); + + /// hasLazyArguments/CheckLazyArguments - The argument list of a function is + /// built on demand, so that the list isn't allocated until the first client + /// needs it. The hasLazyArguments predicate returns true if the arg list + /// hasn't been set up yet. + bool hasLazyArguments() const { + return SubclassData & 1; + } + void CheckLazyArguments() const { + if (hasLazyArguments()) + BuildLazyArguments(); + } + void BuildLazyArguments() const; + + Function(const Function&); // DO NOT IMPLEMENT + void operator=(const Function&); // DO NOT IMPLEMENT + + /// Function ctor - If the (optional) Module argument is specified, the + /// function is automatically inserted into the end of the function list for + /// the module. + /// + Function(const FunctionType *Ty, LinkageTypes Linkage, + const Twine &N = "", Module *M = 0); + +public: + static Function *Create(const FunctionType *Ty, LinkageTypes Linkage, + const Twine &N = "", Module *M = 0) { + return new(0) Function(Ty, Linkage, N, M); + } + + ~Function(); + + const Type *getReturnType() const; // Return the type of the ret val + const FunctionType *getFunctionType() const; // Return the FunctionType for me + + /// getContext - Return a pointer to the LLVMContext associated with this + /// function, or NULL if this function is not bound to a context yet. + LLVMContext &getContext() const; + + /// isVarArg - Return true if this function takes a variable number of + /// arguments. + bool isVarArg() const; + + /// isDeclaration - Is the body of this function unknown? (The basic block + /// list is empty if so.) This is true for function declarations, but not + /// true for function definitions. + /// + virtual bool isDeclaration() const { return BasicBlocks.empty(); } + + /// getIntrinsicID - This method returns the ID number of the specified + /// function, or Intrinsic::not_intrinsic if the function is not an + /// instrinsic, or if the pointer is null. This value is always defined to be + /// zero to allow easy checking for whether a function is intrinsic or not. + /// The particular intrinsic functions which correspond to this value are + /// defined in llvm/Intrinsics.h. + /// + unsigned getIntrinsicID() const ATTRIBUTE_READONLY; + bool isIntrinsic() const { return getIntrinsicID() != 0; } + + /// getCallingConv()/setCallingConv(CC) - These method get and set the + /// calling convention of this function. The enum values for the known + /// calling conventions are defined in CallingConv.h. + CallingConv::ID getCallingConv() const { + return static_cast(SubclassData >> 1); + } + void setCallingConv(CallingConv::ID CC) { + SubclassData = (SubclassData & 1) | (static_cast(CC) << 1); + } + + /// getAttributes - Return the attribute list for this Function. + /// + const AttrListPtr &getAttributes() const { return AttributeList; } + + /// setAttributes - Set the attribute list for this Function. + /// + void setAttributes(const AttrListPtr &attrs) { AttributeList = attrs; } + + /// hasFnAttr - Return true if this function has the given attribute. + bool hasFnAttr(Attributes N) const { + // Function Attributes are stored at ~0 index + return AttributeList.paramHasAttr(~0U, N); + } + + /// addFnAttr - Add function attributes to this function. + /// + void addFnAttr(Attributes N) { + // Function Attributes are stored at ~0 index + addAttribute(~0U, N); + } + + /// removeFnAttr - Remove function attributes from this function. + /// + void removeFnAttr(Attributes N) { + // Function Attributes are stored at ~0 index + removeAttribute(~0U, N); + } + + /// hasGC/getGC/setGC/clearGC - The name of the garbage collection algorithm + /// to use during code generation. + bool hasGC() const; + const char *getGC() const; + void setGC(const char *Str); + void clearGC(); + + /// @brief Determine whether the function has the given attribute. + bool paramHasAttr(unsigned i, Attributes attr) const { + return AttributeList.paramHasAttr(i, attr); + } + + /// addAttribute - adds the attribute to the list of attributes. + void addAttribute(unsigned i, Attributes attr); + + /// removeAttribute - removes the attribute from the list of attributes. + void removeAttribute(unsigned i, Attributes attr); + + /// @brief Extract the alignment for a call or parameter (0=unknown). + unsigned getParamAlignment(unsigned i) const { + return AttributeList.getParamAlignment(i); + } + + /// @brief Determine if the function does not access memory. + bool doesNotAccessMemory() const { + return hasFnAttr(Attribute::ReadNone); + } + void setDoesNotAccessMemory(bool DoesNotAccessMemory = true) { + if (DoesNotAccessMemory) addFnAttr(Attribute::ReadNone); + else removeFnAttr(Attribute::ReadNone); + } + + /// @brief Determine if the function does not access or only reads memory. + bool onlyReadsMemory() const { + return doesNotAccessMemory() || hasFnAttr(Attribute::ReadOnly); + } + void setOnlyReadsMemory(bool OnlyReadsMemory = true) { + if (OnlyReadsMemory) addFnAttr(Attribute::ReadOnly); + else removeFnAttr(Attribute::ReadOnly | Attribute::ReadNone); + } + + /// @brief Determine if the function cannot return. + bool doesNotReturn() const { + return hasFnAttr(Attribute::NoReturn); + } + void setDoesNotReturn(bool DoesNotReturn = true) { + if (DoesNotReturn) addFnAttr(Attribute::NoReturn); + else removeFnAttr(Attribute::NoReturn); + } + + /// @brief Determine if the function cannot unwind. + bool doesNotThrow() const { + return hasFnAttr(Attribute::NoUnwind); + } + void setDoesNotThrow(bool DoesNotThrow = true) { + if (DoesNotThrow) addFnAttr(Attribute::NoUnwind); + else removeFnAttr(Attribute::NoUnwind); + } + + /// @brief Determine if the function returns a structure through first + /// pointer argument. + bool hasStructRetAttr() const { + return paramHasAttr(1, Attribute::StructRet); + } + + /// @brief Determine if the parameter does not alias other parameters. + /// @param n The parameter to check. 1 is the first parameter, 0 is the return + bool doesNotAlias(unsigned n) const { + return paramHasAttr(n, Attribute::NoAlias); + } + void setDoesNotAlias(unsigned n, bool DoesNotAlias = true) { + if (DoesNotAlias) addAttribute(n, Attribute::NoAlias); + else removeAttribute(n, Attribute::NoAlias); + } + + /// @brief Determine if the parameter can be captured. + /// @param n The parameter to check. 1 is the first parameter, 0 is the return + bool doesNotCapture(unsigned n) const { + return paramHasAttr(n, Attribute::NoCapture); + } + void setDoesNotCapture(unsigned n, bool DoesNotCapture = true) { + if (DoesNotCapture) addAttribute(n, Attribute::NoCapture); + else removeAttribute(n, Attribute::NoCapture); + } + + /// copyAttributesFrom - copy all additional attributes (those not needed to + /// create a Function) from the Function Src to this one. + void copyAttributesFrom(const GlobalValue *Src); + + /// deleteBody - This method deletes the body of the function, and converts + /// the linkage to external. + /// + void deleteBody() { + dropAllReferences(); + setLinkage(ExternalLinkage); + } + + /// removeFromParent - This method unlinks 'this' from the containing module, + /// but does not delete it. + /// + virtual void removeFromParent(); + + /// eraseFromParent - This method unlinks 'this' from the containing module + /// and deletes it. + /// + virtual void eraseFromParent(); + + + /// Get the underlying elements of the Function... the basic block list is + /// empty for external functions. + /// + const ArgumentListType &getArgumentList() const { + CheckLazyArguments(); + return ArgumentList; + } + ArgumentListType &getArgumentList() { + CheckLazyArguments(); + return ArgumentList; + } + static iplist Function::*getSublistAccess(Argument*) { + return &Function::ArgumentList; + } + + const BasicBlockListType &getBasicBlockList() const { return BasicBlocks; } + BasicBlockListType &getBasicBlockList() { return BasicBlocks; } + static iplist Function::*getSublistAccess(BasicBlock*) { + return &Function::BasicBlocks; + } + + const BasicBlock &getEntryBlock() const { return front(); } + BasicBlock &getEntryBlock() { return front(); } + + //===--------------------------------------------------------------------===// + // Symbol Table Accessing functions... + + /// getSymbolTable() - Return the symbol table... + /// + inline ValueSymbolTable &getValueSymbolTable() { return *SymTab; } + inline const ValueSymbolTable &getValueSymbolTable() const { return *SymTab; } + + + //===--------------------------------------------------------------------===// + // BasicBlock iterator forwarding functions + // + iterator begin() { return BasicBlocks.begin(); } + const_iterator begin() const { return BasicBlocks.begin(); } + iterator end () { return BasicBlocks.end(); } + const_iterator end () const { return BasicBlocks.end(); } + + size_t size() const { return BasicBlocks.size(); } + bool empty() const { return BasicBlocks.empty(); } + const BasicBlock &front() const { return BasicBlocks.front(); } + BasicBlock &front() { return BasicBlocks.front(); } + const BasicBlock &back() const { return BasicBlocks.back(); } + BasicBlock &back() { return BasicBlocks.back(); } + + //===--------------------------------------------------------------------===// + // Argument iterator forwarding functions + // + arg_iterator arg_begin() { + CheckLazyArguments(); + return ArgumentList.begin(); + } + const_arg_iterator arg_begin() const { + CheckLazyArguments(); + return ArgumentList.begin(); + } + arg_iterator arg_end() { + CheckLazyArguments(); + return ArgumentList.end(); + } + const_arg_iterator arg_end() const { + CheckLazyArguments(); + return ArgumentList.end(); + } + + size_t arg_size() const; + bool arg_empty() const; + + /// viewCFG - This function is meant for use from the debugger. You can just + /// say 'call F->viewCFG()' and a ghostview window should pop up from the + /// program, displaying the CFG of the current function with the code for each + /// basic block inside. This depends on there being a 'dot' and 'gv' program + /// in your path. + /// + void viewCFG() const; + + /// viewCFGOnly - This function is meant for use from the debugger. It works + /// just like viewCFG, but it does not include the contents of basic blocks + /// into the nodes, just the label. If you are only interested in the CFG + /// this can make the graph smaller. + /// + void viewCFGOnly() const; + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const Function *) { return true; } + static inline bool classof(const Value *V) { + return V->getValueID() == Value::FunctionVal; + } + + /// dropAllReferences() - This method causes all the subinstructions to "let + /// go" of all references that they are maintaining. This allows one to + /// 'delete' a whole module at a time, even though there may be circular + /// references... first all references are dropped, and all use counts go to + /// zero. Then everything is deleted for real. Note that no operations are + /// valid on an object that has "dropped all references", except operator + /// delete. + /// + /// Since no other object in the module can have references into the body of a + /// function, dropping all references deletes the entire body of the function, + /// including any contained basic blocks. + /// + void dropAllReferences(); + + /// hasAddressTaken - returns true if there are any uses of this function + /// other than direct calls or invokes to it. + bool hasAddressTaken() const; +}; + +inline ValueSymbolTable * +ilist_traits::getSymTab(Function *F) { + return F ? &F->getValueSymbolTable() : 0; +} + +inline ValueSymbolTable * +ilist_traits::getSymTab(Function *F) { + return F ? &F->getValueSymbolTable() : 0; +} + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/GlobalAlias.h b/libclamav/c++/llvm/include/llvm/GlobalAlias.h new file mode 100644 index 000000000..9b3f45056 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/GlobalAlias.h @@ -0,0 +1,98 @@ +//===-------- llvm/GlobalAlias.h - GlobalAlias class ------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the declaration of the GlobalAlias class, which +// represents a single function or variable alias in the IR. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_GLOBAL_ALIAS_H +#define LLVM_GLOBAL_ALIAS_H + +#include "llvm/GlobalValue.h" +#include "llvm/OperandTraits.h" +#include "llvm/ADT/ilist_node.h" + +namespace llvm { + +class Module; +class Constant; +template + class SymbolTableListTraits; + +class GlobalAlias : public GlobalValue, public ilist_node { + friend class SymbolTableListTraits; + void operator=(const GlobalAlias &); // Do not implement + GlobalAlias(const GlobalAlias &); // Do not implement + + void setParent(Module *parent); + +public: + // allocate space for exactly one operand + void *operator new(size_t s) { + return User::operator new(s, 1); + } + /// GlobalAlias ctor - If a parent module is specified, the alias is + /// automatically inserted into the end of the specified module's alias list. + GlobalAlias(const Type *Ty, LinkageTypes Linkage, const Twine &Name = "", + Constant* Aliasee = 0, Module *Parent = 0); + + /// Provide fast operand accessors + DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); + + /// isDeclaration - Is this global variable lacking an initializer? If so, + /// the global variable is defined in some other translation unit, and is thus + /// only a declaration here. + virtual bool isDeclaration() const; + + /// removeFromParent - This method unlinks 'this' from the containing module, + /// but does not delete it. + /// + virtual void removeFromParent(); + + /// eraseFromParent - This method unlinks 'this' from the containing module + /// and deletes it. + /// + virtual void eraseFromParent(); + + /// set/getAliasee - These methods retrive and set alias target. + void setAliasee(Constant* GV); + const Constant* getAliasee() const { + return cast_or_null(getOperand(0)); + } + Constant* getAliasee() { + return cast_or_null(getOperand(0)); + } + /// getAliasedGlobal() - Aliasee can be either global or bitcast of + /// global. This method retrives the global for both aliasee flavours. + const GlobalValue* getAliasedGlobal() const; + + /// resolveAliasedGlobal() - This method tries to ultimately resolve the alias + /// by going through the aliasing chain and trying to find the very last + /// global. Returns NULL if a cycle was found. If stopOnWeak is false, then + /// the whole chain aliasing chain is traversed, otherwise - only strong + /// aliases. + const GlobalValue* resolveAliasedGlobal(bool stopOnWeak = true) const; + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const GlobalAlias *) { return true; } + static inline bool classof(const Value *V) { + return V->getValueID() == Value::GlobalAliasVal; + } +}; + +template <> +struct OperandTraits : public FixedNumOperandTraits<1> { +}; + +DEFINE_TRANSPARENT_OPERAND_ACCESSORS(GlobalAlias, Value) + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/GlobalValue.h b/libclamav/c++/llvm/include/llvm/GlobalValue.h new file mode 100644 index 000000000..b8d219c72 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/GlobalValue.h @@ -0,0 +1,215 @@ +//===-- llvm/GlobalValue.h - Class to represent a global value --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file is a common base class of all globally definable objects. As such, +// it is subclassed by GlobalVariable, GlobalAlias and by Function. This is +// used because you can do certain things with these global objects that you +// can't do to anything else. For example, use the address of one as a +// constant. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_GLOBALVALUE_H +#define LLVM_GLOBALVALUE_H + +#include "llvm/Constant.h" + +namespace llvm { + +class PointerType; +class Module; + +class GlobalValue : public Constant { + GlobalValue(const GlobalValue &); // do not implement +public: + /// @brief An enumeration for the kinds of linkage for global values. + enum LinkageTypes { + ExternalLinkage = 0,///< Externally visible function + AvailableExternallyLinkage, ///< Available for inspection, not emission. + LinkOnceAnyLinkage, ///< Keep one copy of function when linking (inline) + LinkOnceODRLinkage, ///< Same, but only replaced by something equivalent. + WeakAnyLinkage, ///< Keep one copy of named function when linking (weak) + WeakODRLinkage, ///< Same, but only replaced by something equivalent. + AppendingLinkage, ///< Special purpose, only applies to global arrays + InternalLinkage, ///< Rename collisions when linking (static functions). + PrivateLinkage, ///< Like Internal, but omit from symbol table. + LinkerPrivateLinkage, ///< Like Private, but linker removes. + DLLImportLinkage, ///< Function to be imported from DLL + DLLExportLinkage, ///< Function to be accessible from DLL. + ExternalWeakLinkage,///< ExternalWeak linkage description. + GhostLinkage, ///< Stand-in functions for streaming fns from BC files. + CommonLinkage ///< Tentative definitions. + }; + + /// @brief An enumeration for the kinds of visibility of global values. + enum VisibilityTypes { + DefaultVisibility = 0, ///< The GV is visible + HiddenVisibility, ///< The GV is hidden + ProtectedVisibility ///< The GV is protected + }; + +protected: + GlobalValue(const Type *ty, ValueTy vty, Use *Ops, unsigned NumOps, + LinkageTypes linkage, const Twine &Name = "") + : Constant(ty, vty, Ops, NumOps), Parent(0), + Linkage(linkage), Visibility(DefaultVisibility), Alignment(0) { + setName(Name); + } + + Module *Parent; + // Note: VC++ treats enums as signed, so an extra bit is required to prevent + // Linkage and Visibility from turning into negative values. + LinkageTypes Linkage : 5; // The linkage of this global + unsigned Visibility : 2; // The visibility style of this global + unsigned Alignment : 16; // Alignment of this symbol, must be power of two + std::string Section; // Section to emit this into, empty mean default +public: + ~GlobalValue() { + removeDeadConstantUsers(); // remove any dead constants using this. + } + + unsigned getAlignment() const { return Alignment; } + void setAlignment(unsigned Align) { + assert((Align & (Align-1)) == 0 && "Alignment is not a power of 2!"); + Alignment = Align; + } + + VisibilityTypes getVisibility() const { return VisibilityTypes(Visibility); } + bool hasDefaultVisibility() const { return Visibility == DefaultVisibility; } + bool hasHiddenVisibility() const { return Visibility == HiddenVisibility; } + bool hasProtectedVisibility() const { + return Visibility == ProtectedVisibility; + } + void setVisibility(VisibilityTypes V) { Visibility = V; } + + bool hasSection() const { return !Section.empty(); } + const std::string &getSection() const { return Section; } + void setSection(StringRef S) { Section = S; } + + /// If the usage is empty (except transitively dead constants), then this + /// global value can can be safely deleted since the destructor will + /// delete the dead constants as well. + /// @brief Determine if the usage of this global value is empty except + /// for transitively dead constants. + bool use_empty_except_constants(); + + /// getType - Global values are always pointers. + inline const PointerType *getType() const { + return reinterpret_cast(User::getType()); + } + + static LinkageTypes getLinkOnceLinkage(bool ODR) { + return ODR ? LinkOnceODRLinkage : LinkOnceAnyLinkage; + } + static LinkageTypes getWeakLinkage(bool ODR) { + return ODR ? WeakODRLinkage : WeakAnyLinkage; + } + + bool hasExternalLinkage() const { return Linkage == ExternalLinkage; } + bool hasAvailableExternallyLinkage() const { + return Linkage == AvailableExternallyLinkage; + } + bool hasLinkOnceLinkage() const { + return Linkage == LinkOnceAnyLinkage || Linkage == LinkOnceODRLinkage; + } + bool hasWeakLinkage() const { + return Linkage == WeakAnyLinkage || Linkage == WeakODRLinkage; + } + bool hasAppendingLinkage() const { return Linkage == AppendingLinkage; } + bool hasInternalLinkage() const { return Linkage == InternalLinkage; } + bool hasPrivateLinkage() const { return Linkage == PrivateLinkage; } + bool hasLinkerPrivateLinkage() const { return Linkage==LinkerPrivateLinkage; } + bool hasLocalLinkage() const { + return hasInternalLinkage() || hasPrivateLinkage() || + hasLinkerPrivateLinkage(); + } + bool hasDLLImportLinkage() const { return Linkage == DLLImportLinkage; } + bool hasDLLExportLinkage() const { return Linkage == DLLExportLinkage; } + bool hasExternalWeakLinkage() const { return Linkage == ExternalWeakLinkage; } + bool hasGhostLinkage() const { return Linkage == GhostLinkage; } + bool hasCommonLinkage() const { return Linkage == CommonLinkage; } + + void setLinkage(LinkageTypes LT) { Linkage = LT; } + LinkageTypes getLinkage() const { return Linkage; } + + /// mayBeOverridden - Whether the definition of this global may be replaced + /// by something non-equivalent at link time. For example, if a function has + /// weak linkage then the code defining it may be replaced by different code. + bool mayBeOverridden() const { + return (Linkage == WeakAnyLinkage || + Linkage == LinkOnceAnyLinkage || + Linkage == CommonLinkage || + Linkage == ExternalWeakLinkage); + } + + /// isWeakForLinker - Whether the definition of this global may be replaced at + /// link time. + bool isWeakForLinker() const { + return (Linkage == AvailableExternallyLinkage || + Linkage == WeakAnyLinkage || + Linkage == WeakODRLinkage || + Linkage == LinkOnceAnyLinkage || + Linkage == LinkOnceODRLinkage || + Linkage == CommonLinkage || + Linkage == ExternalWeakLinkage); + } + + /// copyAttributesFrom - copy all additional attributes (those not needed to + /// create a GlobalValue) from the GlobalValue Src to this one. + virtual void copyAttributesFrom(const GlobalValue *Src); + + /// hasNotBeenReadFromBitcode - If a module provider is being used to lazily + /// stream in functions from disk, this method can be used to check to see if + /// the function has been read in yet or not. Unless you are working on the + /// JIT or something else that streams stuff in lazily, you don't need to + /// worry about this. + bool hasNotBeenReadFromBitcode() const { return Linkage == GhostLinkage; } + + /// Override from Constant class. No GlobalValue's are null values so this + /// always returns false. + virtual bool isNullValue() const { return false; } + + /// Override from Constant class. + virtual void destroyConstant(); + + /// isDeclaration - Return true if the primary definition of this global + /// value is outside of the current translation unit... + virtual bool isDeclaration() const = 0; + + /// removeFromParent - This method unlinks 'this' from the containing module, + /// but does not delete it. + virtual void removeFromParent() = 0; + + /// eraseFromParent - This method unlinks 'this' from the containing module + /// and deletes it. + virtual void eraseFromParent() = 0; + + /// getParent - Get the module that this global value is contained inside + /// of... + inline Module *getParent() { return Parent; } + inline const Module *getParent() const { return Parent; } + + /// removeDeadConstantUsers - If there are any dead constant users dangling + /// off of this global value, remove them. This method is useful for clients + /// that want to check to see if a global is unused, but don't want to deal + /// with potentially dead constants hanging off of the globals. + void removeDeadConstantUsers() const; + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const GlobalValue *) { return true; } + static inline bool classof(const Value *V) { + return V->getValueID() == Value::FunctionVal || + V->getValueID() == Value::GlobalVariableVal || + V->getValueID() == Value::GlobalAliasVal; + } +}; + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/GlobalVariable.h b/libclamav/c++/llvm/include/llvm/GlobalVariable.h new file mode 100644 index 000000000..68bd1b3ea --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/GlobalVariable.h @@ -0,0 +1,151 @@ +//===-- llvm/GlobalVariable.h - GlobalVariable class ------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the declaration of the GlobalVariable class, which +// represents a single global variable (or constant) in the VM. +// +// Global variables are constant pointers that refer to hunks of space that are +// allocated by either the VM, or by the linker in a static compiler. A global +// variable may have an intial value, which is copied into the executables .data +// area. Global Constants are required to have initializers. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_GLOBAL_VARIABLE_H +#define LLVM_GLOBAL_VARIABLE_H + +#include "llvm/GlobalValue.h" +#include "llvm/OperandTraits.h" +#include "llvm/ADT/ilist_node.h" + +namespace llvm { + +class Module; +class Constant; +template + class SymbolTableListTraits; + +class GlobalVariable : public GlobalValue, public ilist_node { + friend class SymbolTableListTraits; + void *operator new(size_t, unsigned); // Do not implement + void operator=(const GlobalVariable &); // Do not implement + GlobalVariable(const GlobalVariable &); // Do not implement + + void setParent(Module *parent); + + bool isConstantGlobal : 1; // Is this a global constant? + bool isThreadLocalSymbol : 1; // Is this symbol "Thread Local"? + +public: + // allocate space for exactly one operand + void *operator new(size_t s) { + return User::operator new(s, 1); + } + /// GlobalVariable ctor - If a parent module is specified, the global is + /// automatically inserted into the end of the specified modules global list. + GlobalVariable(const Type *Ty, bool isConstant, LinkageTypes Linkage, + Constant *Initializer = 0, const Twine &Name = "", + bool ThreadLocal = false, unsigned AddressSpace = 0); + /// GlobalVariable ctor - This creates a global and inserts it before the + /// specified other global. + GlobalVariable(Module &M, const Type *Ty, bool isConstant, + LinkageTypes Linkage, Constant *Initializer, + const Twine &Name, + GlobalVariable *InsertBefore = 0, bool ThreadLocal = false, + unsigned AddressSpace = 0); + + ~GlobalVariable() { + NumOperands = 1; // FIXME: needed by operator delete + } + + /// Provide fast operand accessors + DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); + + /// isDeclaration - Is this global variable lacking an initializer? If so, + /// the global variable is defined in some other translation unit, and is thus + /// only a declaration here. + virtual bool isDeclaration() const { return getNumOperands() == 0; } + + /// hasInitializer - Unless a global variable isExternal(), it has an + /// initializer. The initializer for the global variable/constant is held by + /// Initializer if an initializer is specified. + /// + inline bool hasInitializer() const { return !isDeclaration(); } + + /// hasDefinitiveInitializer - Whether the global variable has an initializer, + /// and this is the initializer that will be used in the final executable. + inline bool hasDefinitiveInitializer() const { + return hasInitializer() && + // The initializer of a global variable with weak linkage may change at + // link time. + !mayBeOverridden(); + } + + /// getInitializer - Return the initializer for this global variable. It is + /// illegal to call this method if the global is external, because we cannot + /// tell what the value is initialized to! + /// + inline /*const FIXME*/ Constant *getInitializer() const { + assert(hasInitializer() && "GV doesn't have initializer!"); + return static_cast(Op<0>().get()); + } + inline Constant *getInitializer() { + assert(hasInitializer() && "GV doesn't have initializer!"); + return static_cast(Op<0>().get()); + } + /// setInitializer - Sets the initializer for this global variable, removing + /// any existing initializer if InitVal==NULL. If this GV has type T*, the + /// initializer must have type T. + void setInitializer(Constant *InitVal); + + /// If the value is a global constant, its value is immutable throughout the + /// runtime execution of the program. Assigning a value into the constant + /// leads to undefined behavior. + /// + bool isConstant() const { return isConstantGlobal; } + void setConstant(bool Val) { isConstantGlobal = Val; } + + /// If the value is "Thread Local", its value isn't shared by the threads. + bool isThreadLocal() const { return isThreadLocalSymbol; } + void setThreadLocal(bool Val) { isThreadLocalSymbol = Val; } + + /// copyAttributesFrom - copy all additional attributes (those not needed to + /// create a GlobalVariable) from the GlobalVariable Src to this one. + void copyAttributesFrom(const GlobalValue *Src); + + /// removeFromParent - This method unlinks 'this' from the containing module, + /// but does not delete it. + /// + virtual void removeFromParent(); + + /// eraseFromParent - This method unlinks 'this' from the containing module + /// and deletes it. + /// + virtual void eraseFromParent(); + + /// Override Constant's implementation of this method so we can + /// replace constant initializers. + virtual void replaceUsesOfWithOnConstant(Value *From, Value *To, Use *U); + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const GlobalVariable *) { return true; } + static inline bool classof(const Value *V) { + return V->getValueID() == Value::GlobalVariableVal; + } +}; + +template <> +struct OperandTraits : public OptionalOperandTraits<> { +}; + +DEFINE_TRANSPARENT_OPERAND_ACCESSORS(GlobalVariable, Value) + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/InlineAsm.h b/libclamav/c++/llvm/include/llvm/InlineAsm.h new file mode 100644 index 000000000..482e53e3f --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/InlineAsm.h @@ -0,0 +1,156 @@ +//===-- llvm/InlineAsm.h - Class to represent inline asm strings-*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This class represents the inline asm strings, which are Value*'s that are +// used as the callee operand of call instructions. InlineAsm's are uniqued +// like constants, and created via InlineAsm::get(...). +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_INLINEASM_H +#define LLVM_INLINEASM_H + +#include "llvm/Value.h" +#include + +namespace llvm { + +class PointerType; +class FunctionType; +class Module; + +class InlineAsm : public Value { + InlineAsm(const InlineAsm &); // do not implement + void operator=(const InlineAsm&); // do not implement + + std::string AsmString, Constraints; + bool HasSideEffects; + bool IsAlignStack; + + InlineAsm(const FunctionType *Ty, StringRef AsmString, + StringRef Constraints, bool hasSideEffects, + bool isAlignStack = false); + virtual ~InlineAsm(); +public: + + /// InlineAsm::get - Return the the specified uniqued inline asm string. + /// + static InlineAsm *get(const FunctionType *Ty, StringRef AsmString, + StringRef Constraints, bool hasSideEffects, + bool isAlignStack = false); + + bool hasSideEffects() const { return HasSideEffects; } + bool isAlignStack() const { return IsAlignStack; } + + /// getType - InlineAsm's are always pointers. + /// + const PointerType *getType() const { + return reinterpret_cast(Value::getType()); + } + + /// getFunctionType - InlineAsm's are always pointers to functions. + /// + const FunctionType *getFunctionType() const; + + const std::string &getAsmString() const { return AsmString; } + const std::string &getConstraintString() const { return Constraints; } + + /// Verify - This static method can be used by the parser to check to see if + /// the specified constraint string is legal for the type. This returns true + /// if legal, false if not. + /// + static bool Verify(const FunctionType *Ty, StringRef Constraints); + + // Constraint String Parsing + enum ConstraintPrefix { + isInput, // 'x' + isOutput, // '=x' + isClobber // '~x' + }; + + struct ConstraintInfo { + /// Type - The basic type of the constraint: input/output/clobber + /// + ConstraintPrefix Type; + + /// isEarlyClobber - "&": output operand writes result before inputs are all + /// read. This is only ever set for an output operand. + bool isEarlyClobber; + + /// MatchingInput - If this is not -1, this is an output constraint where an + /// input constraint is required to match it (e.g. "0"). The value is the + /// constraint number that matches this one (for example, if this is + /// constraint #0 and constraint #4 has the value "0", this will be 4). + signed char MatchingInput; + + /// hasMatchingInput - Return true if this is an output constraint that has + /// a matching input constraint. + bool hasMatchingInput() const { return MatchingInput != -1; } + + /// isCommutative - This is set to true for a constraint that is commutative + /// with the next operand. + bool isCommutative; + + /// isIndirect - True if this operand is an indirect operand. This means + /// that the address of the source or destination is present in the call + /// instruction, instead of it being returned or passed in explicitly. This + /// is represented with a '*' in the asm string. + bool isIndirect; + + /// Code - The constraint code, either the register name (in braces) or the + /// constraint letter/number. + std::vector Codes; + + /// Parse - Analyze the specified string (e.g. "=*&{eax}") and fill in the + /// fields in this structure. If the constraint string is not understood, + /// return true, otherwise return false. + bool Parse(StringRef Str, + std::vector &ConstraintsSoFar); + }; + + /// ParseConstraints - Split up the constraint string into the specific + /// constraints and their prefixes. If this returns an empty vector, and if + /// the constraint string itself isn't empty, there was an error parsing. + static std::vector + ParseConstraints(StringRef ConstraintString); + + /// ParseConstraints - Parse the constraints of this inlineasm object, + /// returning them the same way that ParseConstraints(str) does. + std::vector + ParseConstraints() const { + return ParseConstraints(Constraints); + } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const InlineAsm *) { return true; } + static inline bool classof(const Value *V) { + return V->getValueID() == Value::InlineAsmVal; + } + + /// getNumOperandRegisters - Extract the number of registers field from the + /// inline asm operand flag. + static unsigned getNumOperandRegisters(unsigned Flag) { + return (Flag & 0xffff) >> 3; + } + + /// isUseOperandTiedToDef - Return true if the flag of the inline asm + /// operand indicates it is an use operand that's matched to a def operand. + static bool isUseOperandTiedToDef(unsigned Flag, unsigned &Idx) { + if ((Flag & 0x80000000) == 0) + return false; + Idx = (Flag & ~0x80000000) >> 16; + return true; + } + + +}; + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/InstrTypes.h b/libclamav/c++/llvm/include/llvm/InstrTypes.h new file mode 100644 index 000000000..bc899699d --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/InstrTypes.h @@ -0,0 +1,846 @@ +//===-- llvm/InstrTypes.h - Important Instruction subclasses ----*- 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 various meta classes of instructions that exist in the VM +// representation. Specific concrete subclasses of these may be found in the +// i*.h files... +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_INSTRUCTION_TYPES_H +#define LLVM_INSTRUCTION_TYPES_H + +#include "llvm/Instruction.h" +#include "llvm/OperandTraits.h" +#include "llvm/Operator.h" +#include "llvm/DerivedTypes.h" + +namespace llvm { + +class LLVMContext; + +//===----------------------------------------------------------------------===// +// TerminatorInst Class +//===----------------------------------------------------------------------===// + +/// TerminatorInst - Subclasses of this class are all able to terminate a basic +/// block. Thus, these are all the flow control type of operations. +/// +class TerminatorInst : public Instruction { +protected: + TerminatorInst(const Type *Ty, Instruction::TermOps iType, + Use *Ops, unsigned NumOps, + Instruction *InsertBefore = 0) + : Instruction(Ty, iType, Ops, NumOps, InsertBefore) {} + + TerminatorInst(const Type *Ty, Instruction::TermOps iType, + Use *Ops, unsigned NumOps, BasicBlock *InsertAtEnd) + : Instruction(Ty, iType, Ops, NumOps, InsertAtEnd) {} + + // Out of line virtual method, so the vtable, etc has a home. + ~TerminatorInst(); + + /// Virtual methods - Terminators should overload these and provide inline + /// overrides of non-V methods. + virtual BasicBlock *getSuccessorV(unsigned idx) const = 0; + virtual unsigned getNumSuccessorsV() const = 0; + virtual void setSuccessorV(unsigned idx, BasicBlock *B) = 0; + virtual TerminatorInst *clone_impl() const = 0; +public: + + /// getNumSuccessors - Return the number of successors that this terminator + /// has. + unsigned getNumSuccessors() const { + return getNumSuccessorsV(); + } + + /// getSuccessor - Return the specified successor. + /// + BasicBlock *getSuccessor(unsigned idx) const { + return getSuccessorV(idx); + } + + /// setSuccessor - Update the specified successor to point at the provided + /// block. + void setSuccessor(unsigned idx, BasicBlock *B) { + setSuccessorV(idx, B); + } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const TerminatorInst *) { return true; } + static inline bool classof(const Instruction *I) { + return I->isTerminator(); + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } +}; + + +//===----------------------------------------------------------------------===// +// UnaryInstruction Class +//===----------------------------------------------------------------------===// + +class UnaryInstruction : public Instruction { + void *operator new(size_t, unsigned); // Do not implement + +protected: + UnaryInstruction(const Type *Ty, unsigned iType, Value *V, + Instruction *IB = 0) + : Instruction(Ty, iType, &Op<0>(), 1, IB) { + Op<0>() = V; + } + UnaryInstruction(const Type *Ty, unsigned iType, Value *V, BasicBlock *IAE) + : Instruction(Ty, iType, &Op<0>(), 1, IAE) { + Op<0>() = V; + } +public: + // allocate space for exactly one operand + void *operator new(size_t s) { + return User::operator new(s, 1); + } + + // Out of line virtual method, so the vtable, etc has a home. + ~UnaryInstruction(); + + /// Transparently provide more efficient getOperand methods. + DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const UnaryInstruction *) { return true; } + static inline bool classof(const Instruction *I) { + return I->getOpcode() == Instruction::Alloca || + I->getOpcode() == Instruction::Load || + I->getOpcode() == Instruction::VAArg || + I->getOpcode() == Instruction::ExtractValue || + (I->getOpcode() >= CastOpsBegin && I->getOpcode() < CastOpsEnd); + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } +}; + +template <> +struct OperandTraits : public FixedNumOperandTraits<1> { +}; + +DEFINE_TRANSPARENT_OPERAND_ACCESSORS(UnaryInstruction, Value) + +//===----------------------------------------------------------------------===// +// BinaryOperator Class +//===----------------------------------------------------------------------===// + +class BinaryOperator : public Instruction { + void *operator new(size_t, unsigned); // Do not implement +protected: + void init(BinaryOps iType); + BinaryOperator(BinaryOps iType, Value *S1, Value *S2, const Type *Ty, + const Twine &Name, Instruction *InsertBefore); + BinaryOperator(BinaryOps iType, Value *S1, Value *S2, const Type *Ty, + const Twine &Name, BasicBlock *InsertAtEnd); + virtual BinaryOperator *clone_impl() const; +public: + // allocate space for exactly two operands + void *operator new(size_t s) { + return User::operator new(s, 2); + } + + /// Transparently provide more efficient getOperand methods. + DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); + + /// Create() - Construct a binary instruction, given the opcode and the two + /// operands. Optionally (if InstBefore is specified) insert the instruction + /// into a BasicBlock right before the specified instruction. The specified + /// Instruction is allowed to be a dereferenced end iterator. + /// + static BinaryOperator *Create(BinaryOps Op, Value *S1, Value *S2, + const Twine &Name = "", + Instruction *InsertBefore = 0); + + /// Create() - Construct a binary instruction, given the opcode and the two + /// operands. Also automatically insert this instruction to the end of the + /// BasicBlock specified. + /// + static BinaryOperator *Create(BinaryOps Op, Value *S1, Value *S2, + const Twine &Name, BasicBlock *InsertAtEnd); + + /// Create* - These methods just forward to Create, and are useful when you + /// statically know what type of instruction you're going to create. These + /// helpers just save some typing. +#define HANDLE_BINARY_INST(N, OPC, CLASS) \ + static BinaryOperator *Create##OPC(Value *V1, Value *V2, \ + const Twine &Name = "") {\ + return Create(Instruction::OPC, V1, V2, Name);\ + } +#include "llvm/Instruction.def" +#define HANDLE_BINARY_INST(N, OPC, CLASS) \ + static BinaryOperator *Create##OPC(Value *V1, Value *V2, \ + const Twine &Name, BasicBlock *BB) {\ + return Create(Instruction::OPC, V1, V2, Name, BB);\ + } +#include "llvm/Instruction.def" +#define HANDLE_BINARY_INST(N, OPC, CLASS) \ + static BinaryOperator *Create##OPC(Value *V1, Value *V2, \ + const Twine &Name, Instruction *I) {\ + return Create(Instruction::OPC, V1, V2, Name, I);\ + } +#include "llvm/Instruction.def" + + + /// CreateNSWAdd - Create an Add operator with the NSW flag set. + /// + static BinaryOperator *CreateNSWAdd(Value *V1, Value *V2, + const Twine &Name = "") { + BinaryOperator *BO = CreateAdd(V1, V2, Name); + BO->setHasNoSignedWrap(true); + return BO; + } + static BinaryOperator *CreateNSWAdd(Value *V1, Value *V2, + const Twine &Name, BasicBlock *BB) { + BinaryOperator *BO = CreateAdd(V1, V2, Name, BB); + BO->setHasNoSignedWrap(true); + return BO; + } + static BinaryOperator *CreateNSWAdd(Value *V1, Value *V2, + const Twine &Name, Instruction *I) { + BinaryOperator *BO = CreateAdd(V1, V2, Name, I); + BO->setHasNoSignedWrap(true); + return BO; + } + + /// CreateNUWAdd - Create an Add operator with the NUW flag set. + /// + static BinaryOperator *CreateNUWAdd(Value *V1, Value *V2, + const Twine &Name = "") { + BinaryOperator *BO = CreateAdd(V1, V2, Name); + BO->setHasNoUnsignedWrap(true); + return BO; + } + static BinaryOperator *CreateNUWAdd(Value *V1, Value *V2, + const Twine &Name, BasicBlock *BB) { + BinaryOperator *BO = CreateAdd(V1, V2, Name, BB); + BO->setHasNoUnsignedWrap(true); + return BO; + } + static BinaryOperator *CreateNUWAdd(Value *V1, Value *V2, + const Twine &Name, Instruction *I) { + BinaryOperator *BO = CreateAdd(V1, V2, Name, I); + BO->setHasNoUnsignedWrap(true); + return BO; + } + + /// CreateNSWSub - Create an Sub operator with the NSW flag set. + /// + static BinaryOperator *CreateNSWSub(Value *V1, Value *V2, + const Twine &Name = "") { + BinaryOperator *BO = CreateSub(V1, V2, Name); + BO->setHasNoSignedWrap(true); + return BO; + } + static BinaryOperator *CreateNSWSub(Value *V1, Value *V2, + const Twine &Name, BasicBlock *BB) { + BinaryOperator *BO = CreateSub(V1, V2, Name, BB); + BO->setHasNoSignedWrap(true); + return BO; + } + static BinaryOperator *CreateNSWSub(Value *V1, Value *V2, + const Twine &Name, Instruction *I) { + BinaryOperator *BO = CreateSub(V1, V2, Name, I); + BO->setHasNoSignedWrap(true); + return BO; + } + + /// CreateNUWSub - Create an Sub operator with the NUW flag set. + /// + static BinaryOperator *CreateNUWSub(Value *V1, Value *V2, + const Twine &Name = "") { + BinaryOperator *BO = CreateSub(V1, V2, Name); + BO->setHasNoUnsignedWrap(true); + return BO; + } + static BinaryOperator *CreateNUWSub(Value *V1, Value *V2, + const Twine &Name, BasicBlock *BB) { + BinaryOperator *BO = CreateSub(V1, V2, Name, BB); + BO->setHasNoUnsignedWrap(true); + return BO; + } + static BinaryOperator *CreateNUWSub(Value *V1, Value *V2, + const Twine &Name, Instruction *I) { + BinaryOperator *BO = CreateSub(V1, V2, Name, I); + BO->setHasNoUnsignedWrap(true); + return BO; + } + + /// CreateExactSDiv - Create an SDiv operator with the exact flag set. + /// + static BinaryOperator *CreateExactSDiv(Value *V1, Value *V2, + const Twine &Name = "") { + BinaryOperator *BO = CreateSDiv(V1, V2, Name); + BO->setIsExact(true); + return BO; + } + static BinaryOperator *CreateExactSDiv(Value *V1, Value *V2, + const Twine &Name, BasicBlock *BB) { + BinaryOperator *BO = CreateSDiv(V1, V2, Name, BB); + BO->setIsExact(true); + return BO; + } + static BinaryOperator *CreateExactSDiv(Value *V1, Value *V2, + const Twine &Name, Instruction *I) { + BinaryOperator *BO = CreateSDiv(V1, V2, Name, I); + BO->setIsExact(true); + return BO; + } + + /// Helper functions to construct and inspect unary operations (NEG and NOT) + /// via binary operators SUB and XOR: + /// + /// CreateNeg, CreateNot - Create the NEG and NOT + /// instructions out of SUB and XOR instructions. + /// + static BinaryOperator *CreateNeg(Value *Op, const Twine &Name = "", + Instruction *InsertBefore = 0); + static BinaryOperator *CreateNeg(Value *Op, const Twine &Name, + BasicBlock *InsertAtEnd); + static BinaryOperator *CreateFNeg(Value *Op, const Twine &Name = "", + Instruction *InsertBefore = 0); + static BinaryOperator *CreateFNeg(Value *Op, const Twine &Name, + BasicBlock *InsertAtEnd); + static BinaryOperator *CreateNot(Value *Op, const Twine &Name = "", + Instruction *InsertBefore = 0); + static BinaryOperator *CreateNot(Value *Op, const Twine &Name, + BasicBlock *InsertAtEnd); + + /// isNeg, isFNeg, isNot - Check if the given Value is a + /// NEG, FNeg, or NOT instruction. + /// + static bool isNeg(const Value *V); + static bool isFNeg(const Value *V); + static bool isNot(const Value *V); + + /// getNegArgument, getNotArgument - Helper functions to extract the + /// unary argument of a NEG, FNEG or NOT operation implemented via + /// Sub, FSub, or Xor. + /// + static const Value *getNegArgument(const Value *BinOp); + static Value *getNegArgument( Value *BinOp); + static const Value *getFNegArgument(const Value *BinOp); + static Value *getFNegArgument( Value *BinOp); + static const Value *getNotArgument(const Value *BinOp); + static Value *getNotArgument( Value *BinOp); + + BinaryOps getOpcode() const { + return static_cast(Instruction::getOpcode()); + } + + /// swapOperands - Exchange the two operands to this instruction. + /// This instruction is safe to use on any binary instruction and + /// does not modify the semantics of the instruction. If the instruction + /// cannot be reversed (ie, it's a Div), then return true. + /// + bool swapOperands(); + + /// setHasNoUnsignedWrap - Set or clear the nsw flag on this instruction, + /// which must be an operator which supports this flag. See LangRef.html + /// for the meaning of this flag. + void setHasNoUnsignedWrap(bool b = true); + + /// setHasNoSignedWrap - Set or clear the nsw flag on this instruction, + /// which must be an operator which supports this flag. See LangRef.html + /// for the meaning of this flag. + void setHasNoSignedWrap(bool b = true); + + /// setIsExact - Set or clear the exact flag on this instruction, + /// which must be an operator which supports this flag. See LangRef.html + /// for the meaning of this flag. + void setIsExact(bool b = true); + + /// hasNoUnsignedWrap - Determine whether the no unsigned wrap flag is set. + bool hasNoUnsignedWrap() const; + + /// hasNoSignedWrap - Determine whether the no signed wrap flag is set. + bool hasNoSignedWrap() const; + + /// isExact - Determine whether the exact flag is set. + bool isExact() const; + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const BinaryOperator *) { return true; } + static inline bool classof(const Instruction *I) { + return I->isBinaryOp(); + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } +}; + +template <> +struct OperandTraits : public FixedNumOperandTraits<2> { +}; + +DEFINE_TRANSPARENT_OPERAND_ACCESSORS(BinaryOperator, Value) + +//===----------------------------------------------------------------------===// +// CastInst Class +//===----------------------------------------------------------------------===// + +/// CastInst - This is the base class for all instructions that perform data +/// casts. It is simply provided so that instruction category testing +/// can be performed with code like: +/// +/// if (isa(Instr)) { ... } +/// @brief Base class of casting instructions. +class CastInst : public UnaryInstruction { +protected: + /// @brief Constructor with insert-before-instruction semantics for subclasses + CastInst(const Type *Ty, unsigned iType, Value *S, + const Twine &NameStr = "", Instruction *InsertBefore = 0) + : UnaryInstruction(Ty, iType, S, InsertBefore) { + setName(NameStr); + } + /// @brief Constructor with insert-at-end-of-block semantics for subclasses + CastInst(const Type *Ty, unsigned iType, Value *S, + const Twine &NameStr, BasicBlock *InsertAtEnd) + : UnaryInstruction(Ty, iType, S, InsertAtEnd) { + setName(NameStr); + } +public: + /// Provides a way to construct any of the CastInst subclasses using an + /// opcode instead of the subclass's constructor. The opcode must be in the + /// CastOps category (Instruction::isCast(opcode) returns true). This + /// constructor has insert-before-instruction semantics to automatically + /// insert the new CastInst before InsertBefore (if it is non-null). + /// @brief Construct any of the CastInst subclasses + static CastInst *Create( + Instruction::CastOps, ///< The opcode of the cast instruction + Value *S, ///< The value to be casted (operand 0) + const Type *Ty, ///< The type to which cast should be made + const Twine &Name = "", ///< Name for the instruction + Instruction *InsertBefore = 0 ///< Place to insert the instruction + ); + /// Provides a way to construct any of the CastInst subclasses using an + /// opcode instead of the subclass's constructor. The opcode must be in the + /// CastOps category. This constructor has insert-at-end-of-block semantics + /// to automatically insert the new CastInst at the end of InsertAtEnd (if + /// its non-null). + /// @brief Construct any of the CastInst subclasses + static CastInst *Create( + Instruction::CastOps, ///< The opcode for the cast instruction + Value *S, ///< The value to be casted (operand 0) + const Type *Ty, ///< The type to which operand is casted + const Twine &Name, ///< The name for the instruction + BasicBlock *InsertAtEnd ///< The block to insert the instruction into + ); + + /// @brief Create a ZExt or BitCast cast instruction + static CastInst *CreateZExtOrBitCast( + Value *S, ///< The value to be casted (operand 0) + const Type *Ty, ///< The type to which cast should be made + const Twine &Name = "", ///< Name for the instruction + Instruction *InsertBefore = 0 ///< Place to insert the instruction + ); + + /// @brief Create a ZExt or BitCast cast instruction + static CastInst *CreateZExtOrBitCast( + Value *S, ///< The value to be casted (operand 0) + const Type *Ty, ///< The type to which operand is casted + const Twine &Name, ///< The name for the instruction + BasicBlock *InsertAtEnd ///< The block to insert the instruction into + ); + + /// @brief Create a SExt or BitCast cast instruction + static CastInst *CreateSExtOrBitCast( + Value *S, ///< The value to be casted (operand 0) + const Type *Ty, ///< The type to which cast should be made + const Twine &Name = "", ///< Name for the instruction + Instruction *InsertBefore = 0 ///< Place to insert the instruction + ); + + /// @brief Create a SExt or BitCast cast instruction + static CastInst *CreateSExtOrBitCast( + Value *S, ///< The value to be casted (operand 0) + const Type *Ty, ///< The type to which operand is casted + const Twine &Name, ///< The name for the instruction + BasicBlock *InsertAtEnd ///< The block to insert the instruction into + ); + + /// @brief Create a BitCast or a PtrToInt cast instruction + static CastInst *CreatePointerCast( + Value *S, ///< The pointer value to be casted (operand 0) + const Type *Ty, ///< The type to which operand is casted + const Twine &Name, ///< The name for the instruction + BasicBlock *InsertAtEnd ///< The block to insert the instruction into + ); + + /// @brief Create a BitCast or a PtrToInt cast instruction + static CastInst *CreatePointerCast( + Value *S, ///< The pointer value to be casted (operand 0) + const Type *Ty, ///< The type to which cast should be made + const Twine &Name = "", ///< Name for the instruction + Instruction *InsertBefore = 0 ///< Place to insert the instruction + ); + + /// @brief Create a ZExt, BitCast, or Trunc for int -> int casts. + static CastInst *CreateIntegerCast( + Value *S, ///< The pointer value to be casted (operand 0) + const Type *Ty, ///< The type to which cast should be made + bool isSigned, ///< Whether to regard S as signed or not + const Twine &Name = "", ///< Name for the instruction + Instruction *InsertBefore = 0 ///< Place to insert the instruction + ); + + /// @brief Create a ZExt, BitCast, or Trunc for int -> int casts. + static CastInst *CreateIntegerCast( + Value *S, ///< The integer value to be casted (operand 0) + const Type *Ty, ///< The integer type to which operand is casted + bool isSigned, ///< Whether to regard S as signed or not + const Twine &Name, ///< The name for the instruction + BasicBlock *InsertAtEnd ///< The block to insert the instruction into + ); + + /// @brief Create an FPExt, BitCast, or FPTrunc for fp -> fp casts + static CastInst *CreateFPCast( + Value *S, ///< The floating point value to be casted + const Type *Ty, ///< The floating point type to cast to + const Twine &Name = "", ///< Name for the instruction + Instruction *InsertBefore = 0 ///< Place to insert the instruction + ); + + /// @brief Create an FPExt, BitCast, or FPTrunc for fp -> fp casts + static CastInst *CreateFPCast( + Value *S, ///< The floating point value to be casted + const Type *Ty, ///< The floating point type to cast to + const Twine &Name, ///< The name for the instruction + BasicBlock *InsertAtEnd ///< The block to insert the instruction into + ); + + /// @brief Create a Trunc or BitCast cast instruction + static CastInst *CreateTruncOrBitCast( + Value *S, ///< The value to be casted (operand 0) + const Type *Ty, ///< The type to which cast should be made + const Twine &Name = "", ///< Name for the instruction + Instruction *InsertBefore = 0 ///< Place to insert the instruction + ); + + /// @brief Create a Trunc or BitCast cast instruction + static CastInst *CreateTruncOrBitCast( + Value *S, ///< The value to be casted (operand 0) + const Type *Ty, ///< The type to which operand is casted + const Twine &Name, ///< The name for the instruction + BasicBlock *InsertAtEnd ///< The block to insert the instruction into + ); + + /// @brief Check whether it is valid to call getCastOpcode for these types. + static bool isCastable( + const Type *SrcTy, ///< The Type from which the value should be cast. + const Type *DestTy ///< The Type to which the value should be cast. + ); + + /// Returns the opcode necessary to cast Val into Ty using usual casting + /// rules. + /// @brief Infer the opcode for cast operand and type + static Instruction::CastOps getCastOpcode( + const Value *Val, ///< The value to cast + bool SrcIsSigned, ///< Whether to treat the source as signed + const Type *Ty, ///< The Type to which the value should be casted + bool DstIsSigned ///< Whether to treate the dest. as signed + ); + + /// There are several places where we need to know if a cast instruction + /// only deals with integer source and destination types. To simplify that + /// logic, this method is provided. + /// @returns true iff the cast has only integral typed operand and dest type. + /// @brief Determine if this is an integer-only cast. + bool isIntegerCast() const; + + /// A lossless cast is one that does not alter the basic value. It implies + /// a no-op cast but is more stringent, preventing things like int->float, + /// long->double, int->ptr, or vector->anything. + /// @returns true iff the cast is lossless. + /// @brief Determine if this is a lossless cast. + bool isLosslessCast() const; + + /// A no-op cast is one that can be effected without changing any bits. + /// It implies that the source and destination types are the same size. The + /// IntPtrTy argument is used to make accurate determinations for casts + /// involving Integer and Pointer types. They are no-op casts if the integer + /// is the same size as the pointer. However, pointer size varies with + /// platform. Generally, the result of TargetData::getIntPtrType() should be + /// passed in. If that's not available, use Type::Int64Ty, which will make + /// the isNoopCast call conservative. + /// @brief Determine if this cast is a no-op cast. + bool isNoopCast( + const Type *IntPtrTy ///< Integer type corresponding to pointer + ) const; + + /// Determine how a pair of casts can be eliminated, if they can be at all. + /// This is a helper function for both CastInst and ConstantExpr. + /// @returns 0 if the CastInst pair can't be eliminated + /// @returns Instruction::CastOps value for a cast that can replace + /// the pair, casting SrcTy to DstTy. + /// @brief Determine if a cast pair is eliminable + static unsigned isEliminableCastPair( + Instruction::CastOps firstOpcode, ///< Opcode of first cast + Instruction::CastOps secondOpcode, ///< Opcode of second cast + const Type *SrcTy, ///< SrcTy of 1st cast + const Type *MidTy, ///< DstTy of 1st cast & SrcTy of 2nd cast + const Type *DstTy, ///< DstTy of 2nd cast + const Type *IntPtrTy ///< Integer type corresponding to Ptr types, or null + ); + + /// @brief Return the opcode of this CastInst + Instruction::CastOps getOpcode() const { + return Instruction::CastOps(Instruction::getOpcode()); + } + + /// @brief Return the source type, as a convenience + const Type* getSrcTy() const { return getOperand(0)->getType(); } + /// @brief Return the destination type, as a convenience + const Type* getDestTy() const { return getType(); } + + /// This method can be used to determine if a cast from S to DstTy using + /// Opcode op is valid or not. + /// @returns true iff the proposed cast is valid. + /// @brief Determine if a cast is valid without creating one. + static bool castIsValid(Instruction::CastOps op, Value *S, const Type *DstTy); + + /// @brief Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const CastInst *) { return true; } + static inline bool classof(const Instruction *I) { + return I->isCast(); + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } +}; + +//===----------------------------------------------------------------------===// +// CmpInst Class +//===----------------------------------------------------------------------===// + +/// This class is the base class for the comparison instructions. +/// @brief Abstract base class of comparison instructions. +// FIXME: why not derive from BinaryOperator? +class CmpInst: public Instruction { + void *operator new(size_t, unsigned); // DO NOT IMPLEMENT + CmpInst(); // do not implement +protected: + CmpInst(const Type *ty, Instruction::OtherOps op, unsigned short pred, + Value *LHS, Value *RHS, const Twine &Name = "", + Instruction *InsertBefore = 0); + + CmpInst(const Type *ty, Instruction::OtherOps op, unsigned short pred, + Value *LHS, Value *RHS, const Twine &Name, + BasicBlock *InsertAtEnd); + +public: + /// This enumeration lists the possible predicates for CmpInst subclasses. + /// Values in the range 0-31 are reserved for FCmpInst, while values in the + /// range 32-64 are reserved for ICmpInst. This is necessary to ensure the + /// predicate values are not overlapping between the classes. + enum Predicate { + // Opcode U L G E Intuitive operation + FCMP_FALSE = 0, /// 0 0 0 0 Always false (always folded) + FCMP_OEQ = 1, /// 0 0 0 1 True if ordered and equal + FCMP_OGT = 2, /// 0 0 1 0 True if ordered and greater than + FCMP_OGE = 3, /// 0 0 1 1 True if ordered and greater than or equal + FCMP_OLT = 4, /// 0 1 0 0 True if ordered and less than + FCMP_OLE = 5, /// 0 1 0 1 True if ordered and less than or equal + FCMP_ONE = 6, /// 0 1 1 0 True if ordered and operands are unequal + FCMP_ORD = 7, /// 0 1 1 1 True if ordered (no nans) + FCMP_UNO = 8, /// 1 0 0 0 True if unordered: isnan(X) | isnan(Y) + FCMP_UEQ = 9, /// 1 0 0 1 True if unordered or equal + FCMP_UGT = 10, /// 1 0 1 0 True if unordered or greater than + FCMP_UGE = 11, /// 1 0 1 1 True if unordered, greater than, or equal + FCMP_ULT = 12, /// 1 1 0 0 True if unordered or less than + FCMP_ULE = 13, /// 1 1 0 1 True if unordered, less than, or equal + FCMP_UNE = 14, /// 1 1 1 0 True if unordered or not equal + FCMP_TRUE = 15, /// 1 1 1 1 Always true (always folded) + FIRST_FCMP_PREDICATE = FCMP_FALSE, + LAST_FCMP_PREDICATE = FCMP_TRUE, + BAD_FCMP_PREDICATE = FCMP_TRUE + 1, + ICMP_EQ = 32, /// equal + ICMP_NE = 33, /// not equal + ICMP_UGT = 34, /// unsigned greater than + ICMP_UGE = 35, /// unsigned greater or equal + ICMP_ULT = 36, /// unsigned less than + ICMP_ULE = 37, /// unsigned less or equal + ICMP_SGT = 38, /// signed greater than + ICMP_SGE = 39, /// signed greater or equal + ICMP_SLT = 40, /// signed less than + ICMP_SLE = 41, /// signed less or equal + FIRST_ICMP_PREDICATE = ICMP_EQ, + LAST_ICMP_PREDICATE = ICMP_SLE, + BAD_ICMP_PREDICATE = ICMP_SLE + 1 + }; + + // allocate space for exactly two operands + void *operator new(size_t s) { + return User::operator new(s, 2); + } + /// Construct a compare instruction, given the opcode, the predicate and + /// the two operands. Optionally (if InstBefore is specified) insert the + /// instruction into a BasicBlock right before the specified instruction. + /// The specified Instruction is allowed to be a dereferenced end iterator. + /// @brief Create a CmpInst + static CmpInst *Create(OtherOps Op, + unsigned short predicate, Value *S1, + Value *S2, const Twine &Name = "", + Instruction *InsertBefore = 0); + + /// Construct a compare instruction, given the opcode, the predicate and the + /// two operands. Also automatically insert this instruction to the end of + /// the BasicBlock specified. + /// @brief Create a CmpInst + static CmpInst *Create(OtherOps Op, unsigned short predicate, Value *S1, + Value *S2, const Twine &Name, BasicBlock *InsertAtEnd); + + /// @brief Get the opcode casted to the right type + OtherOps getOpcode() const { + return static_cast(Instruction::getOpcode()); + } + + /// @brief Return the predicate for this instruction. + Predicate getPredicate() const { return Predicate(SubclassData); } + + /// @brief Set the predicate for this instruction to the specified value. + void setPredicate(Predicate P) { SubclassData = P; } + + static bool isFPPredicate(Predicate P) { + return P >= FIRST_FCMP_PREDICATE && P <= LAST_FCMP_PREDICATE; + } + + static bool isIntPredicate(Predicate P) { + return P >= FIRST_ICMP_PREDICATE && P <= LAST_ICMP_PREDICATE; + } + + bool isFPPredicate() const { return isFPPredicate(getPredicate()); } + bool isIntPredicate() const { return isIntPredicate(getPredicate()); } + + + /// For example, EQ -> NE, UGT -> ULE, SLT -> SGE, + /// OEQ -> UNE, UGT -> OLE, OLT -> UGE, etc. + /// @returns the inverse predicate for the instruction's current predicate. + /// @brief Return the inverse of the instruction's predicate. + Predicate getInversePredicate() const { + return getInversePredicate(getPredicate()); + } + + /// For example, EQ -> NE, UGT -> ULE, SLT -> SGE, + /// OEQ -> UNE, UGT -> OLE, OLT -> UGE, etc. + /// @returns the inverse predicate for predicate provided in \p pred. + /// @brief Return the inverse of a given predicate + static Predicate getInversePredicate(Predicate pred); + + /// For example, EQ->EQ, SLE->SGE, ULT->UGT, + /// OEQ->OEQ, ULE->UGE, OLT->OGT, etc. + /// @returns the predicate that would be the result of exchanging the two + /// operands of the CmpInst instruction without changing the result + /// produced. + /// @brief Return the predicate as if the operands were swapped + Predicate getSwappedPredicate() const { + return getSwappedPredicate(getPredicate()); + } + + /// This is a static version that you can use without an instruction + /// available. + /// @brief Return the predicate as if the operands were swapped. + static Predicate getSwappedPredicate(Predicate pred); + + /// @brief Provide more efficient getOperand methods. + DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); + + /// This is just a convenience that dispatches to the subclasses. + /// @brief Swap the operands and adjust predicate accordingly to retain + /// the same comparison. + void swapOperands(); + + /// This is just a convenience that dispatches to the subclasses. + /// @brief Determine if this CmpInst is commutative. + bool isCommutative(); + + /// This is just a convenience that dispatches to the subclasses. + /// @brief Determine if this is an equals/not equals predicate. + bool isEquality(); + + /// @returns true if the comparison is signed, false otherwise. + /// @brief Determine if this instruction is using a signed comparison. + bool isSigned() const { + return isSigned(getPredicate()); + } + + /// @returns true if the comparison is unsigned, false otherwise. + /// @brief Determine if this instruction is using an unsigned comparison. + bool isUnsigned() const { + return isUnsigned(getPredicate()); + } + + /// This is just a convenience. + /// @brief Determine if this is true when both operands are the same. + bool isTrueWhenEqual() const { + return isTrueWhenEqual(getPredicate()); + } + + /// This is just a convenience. + /// @brief Determine if this is false when both operands are the same. + bool isFalseWhenEqual() const { + return isFalseWhenEqual(getPredicate()); + } + + /// @returns true if the predicate is unsigned, false otherwise. + /// @brief Determine if the predicate is an unsigned operation. + static bool isUnsigned(unsigned short predicate); + + /// @returns true if the predicate is signed, false otherwise. + /// @brief Determine if the predicate is an signed operation. + static bool isSigned(unsigned short predicate); + + /// @brief Determine if the predicate is an ordered operation. + static bool isOrdered(unsigned short predicate); + + /// @brief Determine if the predicate is an unordered operation. + static bool isUnordered(unsigned short predicate); + + /// Determine if the predicate is true when comparing a value with itself. + static bool isTrueWhenEqual(unsigned short predicate); + + /// Determine if the predicate is false when comparing a value with itself. + static bool isFalseWhenEqual(unsigned short predicate); + + /// @brief Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const CmpInst *) { return true; } + static inline bool classof(const Instruction *I) { + return I->getOpcode() == Instruction::ICmp || + I->getOpcode() == Instruction::FCmp; + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } + + /// @brief Create a result type for fcmp/icmp + static const Type* makeCmpResultType(const Type* opnd_type) { + if (const VectorType* vt = dyn_cast(opnd_type)) { + return VectorType::get(Type::getInt1Ty(opnd_type->getContext()), + vt->getNumElements()); + } + return Type::getInt1Ty(opnd_type->getContext()); + } +}; + + +// FIXME: these are redundant if CmpInst < BinaryOperator +template <> +struct OperandTraits : public FixedNumOperandTraits<2> { +}; + +DEFINE_TRANSPARENT_OPERAND_ACCESSORS(CmpInst, Value) + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Instruction.def b/libclamav/c++/llvm/include/llvm/Instruction.def new file mode 100644 index 000000000..205f30313 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Instruction.def @@ -0,0 +1,196 @@ +//===-- llvm/Instruction.def - File that describes Instructions -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains descriptions of the various LLVM instructions. This is +// used as a central place for enumerating the different instructions and +// should eventually be the place to put comments about the instructions. +// +//===----------------------------------------------------------------------===// + +// NOTE: NO INCLUDE GUARD DESIRED! + +// Provide definitions of macros so that users of this file do not have to +// define everything to use it... +// +#ifndef FIRST_TERM_INST +#define FIRST_TERM_INST(num) +#endif +#ifndef HANDLE_TERM_INST +#ifndef HANDLE_INST +#define HANDLE_TERM_INST(num, opcode, Class) +#else +#define HANDLE_TERM_INST(num, opcode, Class) HANDLE_INST(num, opcode, Class) +#endif +#endif +#ifndef LAST_TERM_INST +#define LAST_TERM_INST(num) +#endif + +#ifndef FIRST_BINARY_INST +#define FIRST_BINARY_INST(num) +#endif +#ifndef HANDLE_BINARY_INST +#ifndef HANDLE_INST +#define HANDLE_BINARY_INST(num, opcode, instclass) +#else +#define HANDLE_BINARY_INST(num, opcode, Class) HANDLE_INST(num, opcode, Class) +#endif +#endif +#ifndef LAST_BINARY_INST +#define LAST_BINARY_INST(num) +#endif + +#ifndef FIRST_MEMORY_INST +#define FIRST_MEMORY_INST(num) +#endif +#ifndef HANDLE_MEMORY_INST +#ifndef HANDLE_INST +#define HANDLE_MEMORY_INST(num, opcode, Class) +#else +#define HANDLE_MEMORY_INST(num, opcode, Class) HANDLE_INST(num, opcode, Class) +#endif +#endif +#ifndef LAST_MEMORY_INST +#define LAST_MEMORY_INST(num) +#endif + +#ifndef FIRST_CAST_INST +#define FIRST_CAST_INST(num) +#endif +#ifndef HANDLE_CAST_INST +#ifndef HANDLE_INST +#define HANDLE_CAST_INST(num, opcode, Class) +#else +#define HANDLE_CAST_INST(num, opcode, Class) HANDLE_INST(num, opcode, Class) +#endif +#endif +#ifndef LAST_CAST_INST +#define LAST_CAST_INST(num) +#endif + +#ifndef FIRST_OTHER_INST +#define FIRST_OTHER_INST(num) +#endif +#ifndef HANDLE_OTHER_INST +#ifndef HANDLE_INST +#define HANDLE_OTHER_INST(num, opcode, Class) +#else +#define HANDLE_OTHER_INST(num, opcode, Class) HANDLE_INST(num, opcode, Class) +#endif +#endif +#ifndef LAST_OTHER_INST +#define LAST_OTHER_INST(num) +#endif + + +// Terminator Instructions - These instructions are used to terminate a basic +// block of the program. Every basic block must end with one of these +// instructions for it to be a well formed basic block. +// + FIRST_TERM_INST ( 1) +HANDLE_TERM_INST ( 1, Ret , ReturnInst) +HANDLE_TERM_INST ( 2, Br , BranchInst) +HANDLE_TERM_INST ( 3, Switch , SwitchInst) +HANDLE_TERM_INST ( 4, IndirectBr , IndirectBrInst) +HANDLE_TERM_INST ( 5, Invoke , InvokeInst) +HANDLE_TERM_INST ( 6, Unwind , UnwindInst) +HANDLE_TERM_INST ( 7, Unreachable, UnreachableInst) + LAST_TERM_INST ( 7) + +// Standard binary operators... + FIRST_BINARY_INST( 8) +HANDLE_BINARY_INST( 8, Add , BinaryOperator) +HANDLE_BINARY_INST( 9, FAdd , BinaryOperator) +HANDLE_BINARY_INST(10, Sub , BinaryOperator) +HANDLE_BINARY_INST(11, FSub , BinaryOperator) +HANDLE_BINARY_INST(12, Mul , BinaryOperator) +HANDLE_BINARY_INST(13, FMul , BinaryOperator) +HANDLE_BINARY_INST(14, UDiv , BinaryOperator) +HANDLE_BINARY_INST(15, SDiv , BinaryOperator) +HANDLE_BINARY_INST(16, FDiv , BinaryOperator) +HANDLE_BINARY_INST(17, URem , BinaryOperator) +HANDLE_BINARY_INST(18, SRem , BinaryOperator) +HANDLE_BINARY_INST(19, FRem , BinaryOperator) + +// Logical operators (integer operands) +HANDLE_BINARY_INST(20, Shl , BinaryOperator) // Shift left (logical) +HANDLE_BINARY_INST(21, LShr , BinaryOperator) // Shift right (logical) +HANDLE_BINARY_INST(22, AShr , BinaryOperator) // Shift right (arithmetic) +HANDLE_BINARY_INST(23, And , BinaryOperator) +HANDLE_BINARY_INST(24, Or , BinaryOperator) +HANDLE_BINARY_INST(25, Xor , BinaryOperator) + LAST_BINARY_INST(25) + +// Memory operators... + FIRST_MEMORY_INST(26) +HANDLE_MEMORY_INST(26, Alloca, AllocaInst) // Stack management +HANDLE_MEMORY_INST(27, Load , LoadInst ) // Memory manipulation instrs +HANDLE_MEMORY_INST(28, Store , StoreInst ) +HANDLE_MEMORY_INST(29, GetElementPtr, GetElementPtrInst) + LAST_MEMORY_INST(29) + +// Cast operators ... +// NOTE: The order matters here because CastInst::isEliminableCastPair +// NOTE: (see Instructions.cpp) encodes a table based on this ordering. + FIRST_CAST_INST(30) +HANDLE_CAST_INST(30, Trunc , TruncInst ) // Truncate integers +HANDLE_CAST_INST(31, ZExt , ZExtInst ) // Zero extend integers +HANDLE_CAST_INST(32, SExt , SExtInst ) // Sign extend integers +HANDLE_CAST_INST(33, FPToUI , FPToUIInst ) // floating point -> UInt +HANDLE_CAST_INST(34, FPToSI , FPToSIInst ) // floating point -> SInt +HANDLE_CAST_INST(35, UIToFP , UIToFPInst ) // UInt -> floating point +HANDLE_CAST_INST(36, SIToFP , SIToFPInst ) // SInt -> floating point +HANDLE_CAST_INST(37, FPTrunc , FPTruncInst ) // Truncate floating point +HANDLE_CAST_INST(38, FPExt , FPExtInst ) // Extend floating point +HANDLE_CAST_INST(39, PtrToInt, PtrToIntInst) // Pointer -> Integer +HANDLE_CAST_INST(40, IntToPtr, IntToPtrInst) // Integer -> Pointer +HANDLE_CAST_INST(41, BitCast , BitCastInst ) // Type cast + LAST_CAST_INST(41) + +// Other operators... + FIRST_OTHER_INST(42) +HANDLE_OTHER_INST(42, ICmp , ICmpInst ) // Integer comparison instruction +HANDLE_OTHER_INST(43, FCmp , FCmpInst ) // Floating point comparison instr. +HANDLE_OTHER_INST(44, PHI , PHINode ) // PHI node instruction +HANDLE_OTHER_INST(45, Call , CallInst ) // Call a function +HANDLE_OTHER_INST(46, Select , SelectInst ) // select instruction +HANDLE_OTHER_INST(47, UserOp1, Instruction) // May be used internally in a pass +HANDLE_OTHER_INST(48, UserOp2, Instruction) // Internal to passes only +HANDLE_OTHER_INST(49, VAArg , VAArgInst ) // vaarg instruction +HANDLE_OTHER_INST(50, ExtractElement, ExtractElementInst)// extract from vector +HANDLE_OTHER_INST(51, InsertElement, InsertElementInst) // insert into vector +HANDLE_OTHER_INST(52, ShuffleVector, ShuffleVectorInst) // shuffle two vectors. +HANDLE_OTHER_INST(53, ExtractValue, ExtractValueInst)// extract from aggregate +HANDLE_OTHER_INST(54, InsertValue, InsertValueInst) // insert into aggregate + + LAST_OTHER_INST(54) + +#undef FIRST_TERM_INST +#undef HANDLE_TERM_INST +#undef LAST_TERM_INST + +#undef FIRST_BINARY_INST +#undef HANDLE_BINARY_INST +#undef LAST_BINARY_INST + +#undef FIRST_MEMORY_INST +#undef HANDLE_MEMORY_INST +#undef LAST_MEMORY_INST + +#undef FIRST_CAST_INST +#undef HANDLE_CAST_INST +#undef LAST_CAST_INST + +#undef FIRST_OTHER_INST +#undef HANDLE_OTHER_INST +#undef LAST_OTHER_INST + +#ifdef HANDLE_INST +#undef HANDLE_INST +#endif diff --git a/libclamav/c++/llvm/include/llvm/Instruction.h b/libclamav/c++/llvm/include/llvm/Instruction.h new file mode 100644 index 000000000..07b3231aa --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Instruction.h @@ -0,0 +1,278 @@ +//===-- llvm/Instruction.h - Instruction class definition -------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the declaration of the Instruction class, which is the +// base class for all of the LLVM instructions. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_INSTRUCTION_H +#define LLVM_INSTRUCTION_H + +#include "llvm/User.h" +#include "llvm/ADT/ilist_node.h" + +namespace llvm { + +class LLVMContext; + +template + class SymbolTableListTraits; + +class Instruction : public User, public ilist_node { + void operator=(const Instruction &); // Do not implement + Instruction(const Instruction &); // Do not implement + + BasicBlock *Parent; + + friend class SymbolTableListTraits; + void setParent(BasicBlock *P); +protected: + Instruction(const Type *Ty, unsigned iType, Use *Ops, unsigned NumOps, + Instruction *InsertBefore = 0); + Instruction(const Type *Ty, unsigned iType, Use *Ops, unsigned NumOps, + BasicBlock *InsertAtEnd); + virtual Instruction *clone_impl() const = 0; +public: + // Out of line virtual method, so the vtable, etc has a home. + ~Instruction(); + + /// clone() - Create a copy of 'this' instruction that is identical in all + /// ways except the following: + /// * The instruction has no parent + /// * The instruction has no name + /// + Instruction *clone() const; + + /// isIdenticalTo - Return true if the specified instruction is exactly + /// identical to the current one. This means that all operands match and any + /// extra information (e.g. load is volatile) agree. + bool isIdenticalTo(const Instruction *I) const; + + /// isIdenticalToWhenDefined - This is like isIdenticalTo, except that it + /// ignores the SubclassOptionalData flags, which specify conditions + /// under which the instruction's result is undefined. + bool isIdenticalToWhenDefined(const Instruction *I) const; + + /// This function determines if the specified instruction executes the same + /// operation as the current one. This means that the opcodes, type, operand + /// types and any other factors affecting the operation must be the same. This + /// is similar to isIdenticalTo except the operands themselves don't have to + /// be identical. + /// @returns true if the specified instruction is the same operation as + /// the current one. + /// @brief Determine if one instruction is the same operation as another. + bool isSameOperationAs(const Instruction *I) const; + + /// isUsedOutsideOfBlock - Return true if there are any uses of this + /// instruction in blocks other than the specified block. Note that PHI nodes + /// are considered to evaluate their operands in the corresponding predecessor + /// block. + bool isUsedOutsideOfBlock(const BasicBlock *BB) const; + + + /// use_back - Specialize the methods defined in Value, as we know that an + /// instruction can only be used by other instructions. + Instruction *use_back() { return cast(*use_begin());} + const Instruction *use_back() const { return cast(*use_begin());} + + // Accessor methods... + // + inline const BasicBlock *getParent() const { return Parent; } + inline BasicBlock *getParent() { return Parent; } + + /// removeFromParent - This method unlinks 'this' from the containing basic + /// block, but does not delete it. + /// + void removeFromParent(); + + /// eraseFromParent - This method unlinks 'this' from the containing basic + /// block and deletes it. + /// + void eraseFromParent(); + + /// insertBefore - Insert an unlinked instructions into a basic block + /// immediately before the specified instruction. + void insertBefore(Instruction *InsertPos); + + /// insertAfter - Insert an unlinked instructions into a basic block + /// immediately after the specified instruction. + void insertAfter(Instruction *InsertPos); + + /// moveBefore - Unlink this instruction from its current basic block and + /// insert it into the basic block that MovePos lives in, right before + /// MovePos. + void moveBefore(Instruction *MovePos); + + // --------------------------------------------------------------------------- + /// Subclass classification... getOpcode() returns a member of + /// one of the enums that is coming soon (down below)... + /// + unsigned getOpcode() const { return getValueID() - InstructionVal; } + const char *getOpcodeName() const { return getOpcodeName(getOpcode()); } + bool isTerminator() const { return isTerminator(getOpcode()); } + bool isBinaryOp() const { return isBinaryOp(getOpcode()); } + bool isShift() { return isShift(getOpcode()); } + bool isCast() const { return isCast(getOpcode()); } + + + + static const char* getOpcodeName(unsigned OpCode); + + static inline bool isTerminator(unsigned OpCode) { + return OpCode >= TermOpsBegin && OpCode < TermOpsEnd; + } + + static inline bool isBinaryOp(unsigned Opcode) { + return Opcode >= BinaryOpsBegin && Opcode < BinaryOpsEnd; + } + + /// @brief Determine if the Opcode is one of the shift instructions. + static inline bool isShift(unsigned Opcode) { + return Opcode >= Shl && Opcode <= AShr; + } + + /// isLogicalShift - Return true if this is a logical shift left or a logical + /// shift right. + inline bool isLogicalShift() const { + return getOpcode() == Shl || getOpcode() == LShr; + } + + /// isArithmeticShift - Return true if this is an arithmetic shift right. + inline bool isArithmeticShift() const { + return getOpcode() == AShr; + } + + /// @brief Determine if the OpCode is one of the CastInst instructions. + static inline bool isCast(unsigned OpCode) { + return OpCode >= CastOpsBegin && OpCode < CastOpsEnd; + } + + /// isAssociative - Return true if the instruction is associative: + /// + /// Associative operators satisfy: x op (y op z) === (x op y) op z + /// + /// In LLVM, the Add, Mul, And, Or, and Xor operators are associative, when + /// not applied to floating point types. + /// + bool isAssociative() const { return isAssociative(getOpcode(), getType()); } + static bool isAssociative(unsigned op, const Type *Ty); + + /// isCommutative - Return true if the instruction is commutative: + /// + /// Commutative operators satisfy: (x op y) === (y op x) + /// + /// In LLVM, these are the associative operators, plus SetEQ and SetNE, when + /// applied to any type. + /// + bool isCommutative() const { return isCommutative(getOpcode()); } + static bool isCommutative(unsigned op); + + /// mayWriteToMemory - Return true if this instruction may modify memory. + /// + bool mayWriteToMemory() const; + + /// mayReadFromMemory - Return true if this instruction may read memory. + /// + bool mayReadFromMemory() const; + + /// mayThrow - Return true if this instruction may throw an exception. + /// + bool mayThrow() const; + + /// mayHaveSideEffects - Return true if the instruction may have side effects. + /// + /// Note that this does not consider malloc and alloca to have side + /// effects because the newly allocated memory is completely invisible to + /// instructions which don't used the returned value. For cases where this + /// matters, isSafeToSpeculativelyExecute may be more appropriate. + bool mayHaveSideEffects() const { + return mayWriteToMemory() || mayThrow(); + } + + /// isSafeToSpeculativelyExecute - Return true if the instruction does not + /// have any effects besides calculating the result and does not have + /// undefined behavior. + /// + /// This method never returns true for an instruction that returns true for + /// mayHaveSideEffects; however, this method also does some other checks in + /// addition. It checks for undefined behavior, like dividing by zero or + /// loading from an invalid pointer (but not for undefined results, like a + /// shift with a shift amount larger than the width of the result). It checks + /// for malloc and alloca because speculatively executing them might cause a + /// memory leak. It also returns false for instructions related to control + /// flow, specifically terminators and PHI nodes. + /// + /// This method only looks at the instruction itself and its operands, so if + /// this method returns true, it is safe to move the instruction as long as + /// the correct dominance relationships for the operands and users hold. + /// However, this method can return true for instructions that read memory; + /// for such instructions, moving them may change the resulting value. + bool isSafeToSpeculativelyExecute() const; + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const Instruction *) { return true; } + static inline bool classof(const Value *V) { + return V->getValueID() >= Value::InstructionVal; + } + + //---------------------------------------------------------------------- + // Exported enumerations... + // + enum TermOps { // These terminate basic blocks +#define FIRST_TERM_INST(N) TermOpsBegin = N, +#define HANDLE_TERM_INST(N, OPC, CLASS) OPC = N, +#define LAST_TERM_INST(N) TermOpsEnd = N+1 +#include "llvm/Instruction.def" + }; + + enum BinaryOps { +#define FIRST_BINARY_INST(N) BinaryOpsBegin = N, +#define HANDLE_BINARY_INST(N, OPC, CLASS) OPC = N, +#define LAST_BINARY_INST(N) BinaryOpsEnd = N+1 +#include "llvm/Instruction.def" + }; + + enum MemoryOps { +#define FIRST_MEMORY_INST(N) MemoryOpsBegin = N, +#define HANDLE_MEMORY_INST(N, OPC, CLASS) OPC = N, +#define LAST_MEMORY_INST(N) MemoryOpsEnd = N+1 +#include "llvm/Instruction.def" + }; + + enum CastOps { +#define FIRST_CAST_INST(N) CastOpsBegin = N, +#define HANDLE_CAST_INST(N, OPC, CLASS) OPC = N, +#define LAST_CAST_INST(N) CastOpsEnd = N+1 +#include "llvm/Instruction.def" + }; + + enum OtherOps { +#define FIRST_OTHER_INST(N) OtherOpsBegin = N, +#define HANDLE_OTHER_INST(N, OPC, CLASS) OPC = N, +#define LAST_OTHER_INST(N) OtherOpsEnd = N+1 +#include "llvm/Instruction.def" + }; +}; + +// Instruction* is only 4-byte aligned. +template<> +class PointerLikeTypeTraits { + typedef Instruction* PT; +public: + static inline void *getAsVoidPointer(PT P) { return P; } + static inline PT getFromVoidPointer(void *P) { + return static_cast(P); + } + enum { NumLowBitsAvailable = 2 }; +}; + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Instructions.h b/libclamav/c++/llvm/include/llvm/Instructions.h new file mode 100644 index 000000000..5b48e1a5d --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Instructions.h @@ -0,0 +1,3087 @@ +//===-- llvm/Instructions.h - Instruction subclass definitions --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file exposes the class definitions of all of the subclasses of the +// Instruction class. This is meant to be an easy way to get access to all +// instruction subclasses. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_INSTRUCTIONS_H +#define LLVM_INSTRUCTIONS_H + +#include "llvm/InstrTypes.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Attributes.h" +#include "llvm/CallingConv.h" +#include "llvm/ADT/SmallVector.h" +#include + +namespace llvm { + +class ConstantInt; +class ConstantRange; +class APInt; +class LLVMContext; +class DominatorTree; + +//===----------------------------------------------------------------------===// +// AllocaInst Class +//===----------------------------------------------------------------------===// + +/// AllocaInst - an instruction to allocate memory on the stack +/// +class AllocaInst : public UnaryInstruction { +protected: + virtual AllocaInst *clone_impl() const; +public: + explicit AllocaInst(const Type *Ty, Value *ArraySize = 0, + const Twine &Name = "", Instruction *InsertBefore = 0); + AllocaInst(const Type *Ty, Value *ArraySize, + const Twine &Name, BasicBlock *InsertAtEnd); + + AllocaInst(const Type *Ty, const Twine &Name, Instruction *InsertBefore = 0); + AllocaInst(const Type *Ty, const Twine &Name, BasicBlock *InsertAtEnd); + + AllocaInst(const Type *Ty, Value *ArraySize, unsigned Align, + const Twine &Name = "", Instruction *InsertBefore = 0); + AllocaInst(const Type *Ty, Value *ArraySize, unsigned Align, + const Twine &Name, BasicBlock *InsertAtEnd); + + // Out of line virtual method, so the vtable, etc. has a home. + virtual ~AllocaInst(); + + /// isArrayAllocation - Return true if there is an allocation size parameter + /// to the allocation instruction that is not 1. + /// + bool isArrayAllocation() const; + + /// getArraySize - Get the number of elements allocated. For a simple + /// allocation of a single element, this will return a constant 1 value. + /// + const Value *getArraySize() const { return getOperand(0); } + Value *getArraySize() { return getOperand(0); } + + /// getType - Overload to return most specific pointer type + /// + const PointerType *getType() const { + return reinterpret_cast(Instruction::getType()); + } + + /// getAllocatedType - Return the type that is being allocated by the + /// instruction. + /// + const Type *getAllocatedType() const; + + /// getAlignment - Return the alignment of the memory that is being allocated + /// by the instruction. + /// + unsigned getAlignment() const { return (1u << SubclassData) >> 1; } + void setAlignment(unsigned Align); + + /// isStaticAlloca - Return true if this alloca is in the entry block of the + /// function and is a constant size. If so, the code generator will fold it + /// into the prolog/epilog code, so it is basically free. + bool isStaticAlloca() const; + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const AllocaInst *) { return true; } + static inline bool classof(const Instruction *I) { + return (I->getOpcode() == Instruction::Alloca); + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } +}; + + +//===----------------------------------------------------------------------===// +// LoadInst Class +//===----------------------------------------------------------------------===// + +/// LoadInst - an instruction for reading from memory. This uses the +/// SubclassData field in Value to store whether or not the load is volatile. +/// +class LoadInst : public UnaryInstruction { + void AssertOK(); +protected: + virtual LoadInst *clone_impl() const; +public: + LoadInst(Value *Ptr, const Twine &NameStr, Instruction *InsertBefore); + LoadInst(Value *Ptr, const Twine &NameStr, BasicBlock *InsertAtEnd); + LoadInst(Value *Ptr, const Twine &NameStr, bool isVolatile = false, + Instruction *InsertBefore = 0); + LoadInst(Value *Ptr, const Twine &NameStr, bool isVolatile, + unsigned Align, Instruction *InsertBefore = 0); + LoadInst(Value *Ptr, const Twine &NameStr, bool isVolatile, + BasicBlock *InsertAtEnd); + LoadInst(Value *Ptr, const Twine &NameStr, bool isVolatile, + unsigned Align, BasicBlock *InsertAtEnd); + + LoadInst(Value *Ptr, const char *NameStr, Instruction *InsertBefore); + LoadInst(Value *Ptr, const char *NameStr, BasicBlock *InsertAtEnd); + explicit LoadInst(Value *Ptr, const char *NameStr = 0, + bool isVolatile = false, Instruction *InsertBefore = 0); + LoadInst(Value *Ptr, const char *NameStr, bool isVolatile, + BasicBlock *InsertAtEnd); + + /// isVolatile - Return true if this is a load from a volatile memory + /// location. + /// + bool isVolatile() const { return SubclassData & 1; } + + /// setVolatile - Specify whether this is a volatile load or not. + /// + void setVolatile(bool V) { + SubclassData = (SubclassData & ~1) | (V ? 1 : 0); + } + + /// getAlignment - Return the alignment of the access that is being performed + /// + unsigned getAlignment() const { + return (1 << (SubclassData>>1)) >> 1; + } + + void setAlignment(unsigned Align); + + Value *getPointerOperand() { return getOperand(0); } + const Value *getPointerOperand() const { return getOperand(0); } + static unsigned getPointerOperandIndex() { return 0U; } + + unsigned getPointerAddressSpace() const { + return cast(getPointerOperand()->getType())->getAddressSpace(); + } + + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const LoadInst *) { return true; } + static inline bool classof(const Instruction *I) { + return I->getOpcode() == Instruction::Load; + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } +}; + + +//===----------------------------------------------------------------------===// +// StoreInst Class +//===----------------------------------------------------------------------===// + +/// StoreInst - an instruction for storing to memory +/// +class StoreInst : public Instruction { + void *operator new(size_t, unsigned); // DO NOT IMPLEMENT + void AssertOK(); +protected: + virtual StoreInst *clone_impl() const; +public: + // allocate space for exactly two operands + void *operator new(size_t s) { + return User::operator new(s, 2); + } + StoreInst(Value *Val, Value *Ptr, Instruction *InsertBefore); + StoreInst(Value *Val, Value *Ptr, BasicBlock *InsertAtEnd); + StoreInst(Value *Val, Value *Ptr, bool isVolatile = false, + Instruction *InsertBefore = 0); + StoreInst(Value *Val, Value *Ptr, bool isVolatile, + unsigned Align, Instruction *InsertBefore = 0); + StoreInst(Value *Val, Value *Ptr, bool isVolatile, BasicBlock *InsertAtEnd); + StoreInst(Value *Val, Value *Ptr, bool isVolatile, + unsigned Align, BasicBlock *InsertAtEnd); + + + /// isVolatile - Return true if this is a load from a volatile memory + /// location. + /// + bool isVolatile() const { return SubclassData & 1; } + + /// setVolatile - Specify whether this is a volatile load or not. + /// + void setVolatile(bool V) { + SubclassData = (SubclassData & ~1) | (V ? 1 : 0); + } + + /// Transparently provide more efficient getOperand methods. + DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); + + /// getAlignment - Return the alignment of the access that is being performed + /// + unsigned getAlignment() const { + return (1 << (SubclassData>>1)) >> 1; + } + + void setAlignment(unsigned Align); + + Value *getPointerOperand() { return getOperand(1); } + const Value *getPointerOperand() const { return getOperand(1); } + static unsigned getPointerOperandIndex() { return 1U; } + + unsigned getPointerAddressSpace() const { + return cast(getPointerOperand()->getType())->getAddressSpace(); + } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const StoreInst *) { return true; } + static inline bool classof(const Instruction *I) { + return I->getOpcode() == Instruction::Store; + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } +}; + +template <> +struct OperandTraits : public FixedNumOperandTraits<2> { +}; + +DEFINE_TRANSPARENT_OPERAND_ACCESSORS(StoreInst, Value) + +//===----------------------------------------------------------------------===// +// GetElementPtrInst Class +//===----------------------------------------------------------------------===// + +// checkType - Simple wrapper function to give a better assertion failure +// message on bad indexes for a gep instruction. +// +static inline const Type *checkType(const Type *Ty) { + assert(Ty && "Invalid GetElementPtrInst indices for type!"); + return Ty; +} + +/// GetElementPtrInst - an instruction for type-safe pointer arithmetic to +/// access elements of arrays and structs +/// +class GetElementPtrInst : public Instruction { + GetElementPtrInst(const GetElementPtrInst &GEPI); + void init(Value *Ptr, Value* const *Idx, unsigned NumIdx, + const Twine &NameStr); + void init(Value *Ptr, Value *Idx, const Twine &NameStr); + + template + void init(Value *Ptr, InputIterator IdxBegin, InputIterator IdxEnd, + const Twine &NameStr, + // This argument ensures that we have an iterator we can + // do arithmetic on in constant time + std::random_access_iterator_tag) { + unsigned NumIdx = static_cast(std::distance(IdxBegin, IdxEnd)); + + if (NumIdx > 0) { + // This requires that the iterator points to contiguous memory. + init(Ptr, &*IdxBegin, NumIdx, NameStr); // FIXME: for the general case + // we have to build an array here + } + else { + init(Ptr, 0, NumIdx, NameStr); + } + } + + /// getIndexedType - Returns the type of the element that would be loaded with + /// a load instruction with the specified parameters. + /// + /// Null is returned if the indices are invalid for the specified + /// pointer type. + /// + template + static const Type *getIndexedType(const Type *Ptr, + InputIterator IdxBegin, + InputIterator IdxEnd, + // This argument ensures that we + // have an iterator we can do + // arithmetic on in constant time + std::random_access_iterator_tag) { + unsigned NumIdx = static_cast(std::distance(IdxBegin, IdxEnd)); + + if (NumIdx > 0) + // This requires that the iterator points to contiguous memory. + return getIndexedType(Ptr, &*IdxBegin, NumIdx); + else + return getIndexedType(Ptr, (Value *const*)0, NumIdx); + } + + /// Constructors - Create a getelementptr instruction with a base pointer an + /// list of indices. The first ctor can optionally insert before an existing + /// instruction, the second appends the new instruction to the specified + /// BasicBlock. + template + inline GetElementPtrInst(Value *Ptr, InputIterator IdxBegin, + InputIterator IdxEnd, + unsigned Values, + const Twine &NameStr, + Instruction *InsertBefore); + template + inline GetElementPtrInst(Value *Ptr, + InputIterator IdxBegin, InputIterator IdxEnd, + unsigned Values, + const Twine &NameStr, BasicBlock *InsertAtEnd); + + /// Constructors - These two constructors are convenience methods because one + /// and two index getelementptr instructions are so common. + GetElementPtrInst(Value *Ptr, Value *Idx, const Twine &NameStr = "", + Instruction *InsertBefore = 0); + GetElementPtrInst(Value *Ptr, Value *Idx, + const Twine &NameStr, BasicBlock *InsertAtEnd); +protected: + virtual GetElementPtrInst *clone_impl() const; +public: + template + static GetElementPtrInst *Create(Value *Ptr, InputIterator IdxBegin, + InputIterator IdxEnd, + const Twine &NameStr = "", + Instruction *InsertBefore = 0) { + typename std::iterator_traits::difference_type Values = + 1 + std::distance(IdxBegin, IdxEnd); + return new(Values) + GetElementPtrInst(Ptr, IdxBegin, IdxEnd, Values, NameStr, InsertBefore); + } + template + static GetElementPtrInst *Create(Value *Ptr, + InputIterator IdxBegin, InputIterator IdxEnd, + const Twine &NameStr, + BasicBlock *InsertAtEnd) { + typename std::iterator_traits::difference_type Values = + 1 + std::distance(IdxBegin, IdxEnd); + return new(Values) + GetElementPtrInst(Ptr, IdxBegin, IdxEnd, Values, NameStr, InsertAtEnd); + } + + /// Constructors - These two creators are convenience methods because one + /// index getelementptr instructions are so common. + static GetElementPtrInst *Create(Value *Ptr, Value *Idx, + const Twine &NameStr = "", + Instruction *InsertBefore = 0) { + return new(2) GetElementPtrInst(Ptr, Idx, NameStr, InsertBefore); + } + static GetElementPtrInst *Create(Value *Ptr, Value *Idx, + const Twine &NameStr, + BasicBlock *InsertAtEnd) { + return new(2) GetElementPtrInst(Ptr, Idx, NameStr, InsertAtEnd); + } + + /// Create an "inbounds" getelementptr. See the documentation for the + /// "inbounds" flag in LangRef.html for details. + template + static GetElementPtrInst *CreateInBounds(Value *Ptr, InputIterator IdxBegin, + InputIterator IdxEnd, + const Twine &NameStr = "", + Instruction *InsertBefore = 0) { + GetElementPtrInst *GEP = Create(Ptr, IdxBegin, IdxEnd, + NameStr, InsertBefore); + GEP->setIsInBounds(true); + return GEP; + } + template + static GetElementPtrInst *CreateInBounds(Value *Ptr, + InputIterator IdxBegin, + InputIterator IdxEnd, + const Twine &NameStr, + BasicBlock *InsertAtEnd) { + GetElementPtrInst *GEP = Create(Ptr, IdxBegin, IdxEnd, + NameStr, InsertAtEnd); + GEP->setIsInBounds(true); + return GEP; + } + static GetElementPtrInst *CreateInBounds(Value *Ptr, Value *Idx, + const Twine &NameStr = "", + Instruction *InsertBefore = 0) { + GetElementPtrInst *GEP = Create(Ptr, Idx, NameStr, InsertBefore); + GEP->setIsInBounds(true); + return GEP; + } + static GetElementPtrInst *CreateInBounds(Value *Ptr, Value *Idx, + const Twine &NameStr, + BasicBlock *InsertAtEnd) { + GetElementPtrInst *GEP = Create(Ptr, Idx, NameStr, InsertAtEnd); + GEP->setIsInBounds(true); + return GEP; + } + + /// Transparently provide more efficient getOperand methods. + DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); + + // getType - Overload to return most specific pointer type... + const PointerType *getType() const { + return reinterpret_cast(Instruction::getType()); + } + + /// getIndexedType - Returns the type of the element that would be loaded with + /// a load instruction with the specified parameters. + /// + /// Null is returned if the indices are invalid for the specified + /// pointer type. + /// + template + static const Type *getIndexedType(const Type *Ptr, + InputIterator IdxBegin, + InputIterator IdxEnd) { + return getIndexedType(Ptr, IdxBegin, IdxEnd, + typename std::iterator_traits:: + iterator_category()); + } + + static const Type *getIndexedType(const Type *Ptr, + Value* const *Idx, unsigned NumIdx); + + static const Type *getIndexedType(const Type *Ptr, + uint64_t const *Idx, unsigned NumIdx); + + static const Type *getIndexedType(const Type *Ptr, Value *Idx); + + inline op_iterator idx_begin() { return op_begin()+1; } + inline const_op_iterator idx_begin() const { return op_begin()+1; } + inline op_iterator idx_end() { return op_end(); } + inline const_op_iterator idx_end() const { return op_end(); } + + Value *getPointerOperand() { + return getOperand(0); + } + const Value *getPointerOperand() const { + return getOperand(0); + } + static unsigned getPointerOperandIndex() { + return 0U; // get index for modifying correct operand + } + + unsigned getPointerAddressSpace() const { + return cast(getType())->getAddressSpace(); + } + + /// getPointerOperandType - Method to return the pointer operand as a + /// PointerType. + const PointerType *getPointerOperandType() const { + return reinterpret_cast(getPointerOperand()->getType()); + } + + + unsigned getNumIndices() const { // Note: always non-negative + return getNumOperands() - 1; + } + + bool hasIndices() const { + return getNumOperands() > 1; + } + + /// hasAllZeroIndices - Return true if all of the indices of this GEP are + /// zeros. If so, the result pointer and the first operand have the same + /// value, just potentially different types. + bool hasAllZeroIndices() const; + + /// hasAllConstantIndices - Return true if all of the indices of this GEP are + /// constant integers. If so, the result pointer and the first operand have + /// a constant offset between them. + bool hasAllConstantIndices() const; + + /// setIsInBounds - Set or clear the inbounds flag on this GEP instruction. + /// See LangRef.html for the meaning of inbounds on a getelementptr. + void setIsInBounds(bool b = true); + + /// isInBounds - Determine whether the GEP has the inbounds flag. + bool isInBounds() const; + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const GetElementPtrInst *) { return true; } + static inline bool classof(const Instruction *I) { + return (I->getOpcode() == Instruction::GetElementPtr); + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } +}; + +template <> +struct OperandTraits : public VariadicOperandTraits<1> { +}; + +template +GetElementPtrInst::GetElementPtrInst(Value *Ptr, + InputIterator IdxBegin, + InputIterator IdxEnd, + unsigned Values, + const Twine &NameStr, + Instruction *InsertBefore) + : Instruction(PointerType::get(checkType( + getIndexedType(Ptr->getType(), + IdxBegin, IdxEnd)), + cast(Ptr->getType()) + ->getAddressSpace()), + GetElementPtr, + OperandTraits::op_end(this) - Values, + Values, InsertBefore) { + init(Ptr, IdxBegin, IdxEnd, NameStr, + typename std::iterator_traits::iterator_category()); +} +template +GetElementPtrInst::GetElementPtrInst(Value *Ptr, + InputIterator IdxBegin, + InputIterator IdxEnd, + unsigned Values, + const Twine &NameStr, + BasicBlock *InsertAtEnd) + : Instruction(PointerType::get(checkType( + getIndexedType(Ptr->getType(), + IdxBegin, IdxEnd)), + cast(Ptr->getType()) + ->getAddressSpace()), + GetElementPtr, + OperandTraits::op_end(this) - Values, + Values, InsertAtEnd) { + init(Ptr, IdxBegin, IdxEnd, NameStr, + typename std::iterator_traits::iterator_category()); +} + + +DEFINE_TRANSPARENT_OPERAND_ACCESSORS(GetElementPtrInst, Value) + + +//===----------------------------------------------------------------------===// +// ICmpInst Class +//===----------------------------------------------------------------------===// + +/// This instruction compares its operands according to the predicate given +/// to the constructor. It only operates on integers or pointers. The operands +/// must be identical types. +/// @brief Represent an integer comparison operator. +class ICmpInst: public CmpInst { +protected: + /// @brief Clone an indentical ICmpInst + virtual ICmpInst *clone_impl() const; +public: + /// @brief Constructor with insert-before-instruction semantics. + ICmpInst( + Instruction *InsertBefore, ///< Where to insert + Predicate pred, ///< The predicate to use for the comparison + Value *LHS, ///< The left-hand-side of the expression + Value *RHS, ///< The right-hand-side of the expression + const Twine &NameStr = "" ///< Name of the instruction + ) : CmpInst(makeCmpResultType(LHS->getType()), + Instruction::ICmp, pred, LHS, RHS, NameStr, + InsertBefore) { + assert(pred >= CmpInst::FIRST_ICMP_PREDICATE && + pred <= CmpInst::LAST_ICMP_PREDICATE && + "Invalid ICmp predicate value"); + assert(getOperand(0)->getType() == getOperand(1)->getType() && + "Both operands to ICmp instruction are not of the same type!"); + // Check that the operands are the right type + assert((getOperand(0)->getType()->isIntOrIntVector() || + isa(getOperand(0)->getType())) && + "Invalid operand types for ICmp instruction"); + } + + /// @brief Constructor with insert-at-end semantics. + ICmpInst( + BasicBlock &InsertAtEnd, ///< Block to insert into. + Predicate pred, ///< The predicate to use for the comparison + Value *LHS, ///< The left-hand-side of the expression + Value *RHS, ///< The right-hand-side of the expression + const Twine &NameStr = "" ///< Name of the instruction + ) : CmpInst(makeCmpResultType(LHS->getType()), + Instruction::ICmp, pred, LHS, RHS, NameStr, + &InsertAtEnd) { + assert(pred >= CmpInst::FIRST_ICMP_PREDICATE && + pred <= CmpInst::LAST_ICMP_PREDICATE && + "Invalid ICmp predicate value"); + assert(getOperand(0)->getType() == getOperand(1)->getType() && + "Both operands to ICmp instruction are not of the same type!"); + // Check that the operands are the right type + assert((getOperand(0)->getType()->isIntOrIntVector() || + isa(getOperand(0)->getType())) && + "Invalid operand types for ICmp instruction"); + } + + /// @brief Constructor with no-insertion semantics + ICmpInst( + Predicate pred, ///< The predicate to use for the comparison + Value *LHS, ///< The left-hand-side of the expression + Value *RHS, ///< The right-hand-side of the expression + const Twine &NameStr = "" ///< Name of the instruction + ) : CmpInst(makeCmpResultType(LHS->getType()), + Instruction::ICmp, pred, LHS, RHS, NameStr) { + assert(pred >= CmpInst::FIRST_ICMP_PREDICATE && + pred <= CmpInst::LAST_ICMP_PREDICATE && + "Invalid ICmp predicate value"); + assert(getOperand(0)->getType() == getOperand(1)->getType() && + "Both operands to ICmp instruction are not of the same type!"); + // Check that the operands are the right type + assert((getOperand(0)->getType()->isIntOrIntVector() || + isa(getOperand(0)->getType())) && + "Invalid operand types for ICmp instruction"); + } + + /// For example, EQ->EQ, SLE->SLE, UGT->SGT, etc. + /// @returns the predicate that would be the result if the operand were + /// regarded as signed. + /// @brief Return the signed version of the predicate + Predicate getSignedPredicate() const { + return getSignedPredicate(getPredicate()); + } + + /// This is a static version that you can use without an instruction. + /// @brief Return the signed version of the predicate. + static Predicate getSignedPredicate(Predicate pred); + + /// For example, EQ->EQ, SLE->ULE, UGT->UGT, etc. + /// @returns the predicate that would be the result if the operand were + /// regarded as unsigned. + /// @brief Return the unsigned version of the predicate + Predicate getUnsignedPredicate() const { + return getUnsignedPredicate(getPredicate()); + } + + /// This is a static version that you can use without an instruction. + /// @brief Return the unsigned version of the predicate. + static Predicate getUnsignedPredicate(Predicate pred); + + /// isEquality - Return true if this predicate is either EQ or NE. This also + /// tests for commutativity. + static bool isEquality(Predicate P) { + return P == ICMP_EQ || P == ICMP_NE; + } + + /// isEquality - Return true if this predicate is either EQ or NE. This also + /// tests for commutativity. + bool isEquality() const { + return isEquality(getPredicate()); + } + + /// @returns true if the predicate of this ICmpInst is commutative + /// @brief Determine if this relation is commutative. + bool isCommutative() const { return isEquality(); } + + /// isRelational - Return true if the predicate is relational (not EQ or NE). + /// + bool isRelational() const { + return !isEquality(); + } + + /// isRelational - Return true if the predicate is relational (not EQ or NE). + /// + static bool isRelational(Predicate P) { + return !isEquality(P); + } + + /// Initialize a set of values that all satisfy the predicate with C. + /// @brief Make a ConstantRange for a relation with a constant value. + static ConstantRange makeConstantRange(Predicate pred, const APInt &C); + + /// Exchange the two operands to this instruction in such a way that it does + /// not modify the semantics of the instruction. The predicate value may be + /// changed to retain the same result if the predicate is order dependent + /// (e.g. ult). + /// @brief Swap operands and adjust predicate. + void swapOperands() { + SubclassData = getSwappedPredicate(); + Op<0>().swap(Op<1>()); + } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const ICmpInst *) { return true; } + static inline bool classof(const Instruction *I) { + return I->getOpcode() == Instruction::ICmp; + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } + +}; + +//===----------------------------------------------------------------------===// +// FCmpInst Class +//===----------------------------------------------------------------------===// + +/// This instruction compares its operands according to the predicate given +/// to the constructor. It only operates on floating point values or packed +/// vectors of floating point values. The operands must be identical types. +/// @brief Represents a floating point comparison operator. +class FCmpInst: public CmpInst { +protected: + /// @brief Clone an indentical FCmpInst + virtual FCmpInst *clone_impl() const; +public: + /// @brief Constructor with insert-before-instruction semantics. + FCmpInst( + Instruction *InsertBefore, ///< Where to insert + Predicate pred, ///< The predicate to use for the comparison + Value *LHS, ///< The left-hand-side of the expression + Value *RHS, ///< The right-hand-side of the expression + const Twine &NameStr = "" ///< Name of the instruction + ) : CmpInst(makeCmpResultType(LHS->getType()), + Instruction::FCmp, pred, LHS, RHS, NameStr, + InsertBefore) { + assert(pred <= FCmpInst::LAST_FCMP_PREDICATE && + "Invalid FCmp predicate value"); + assert(getOperand(0)->getType() == getOperand(1)->getType() && + "Both operands to FCmp instruction are not of the same type!"); + // Check that the operands are the right type + assert(getOperand(0)->getType()->isFPOrFPVector() && + "Invalid operand types for FCmp instruction"); + } + + /// @brief Constructor with insert-at-end semantics. + FCmpInst( + BasicBlock &InsertAtEnd, ///< Block to insert into. + Predicate pred, ///< The predicate to use for the comparison + Value *LHS, ///< The left-hand-side of the expression + Value *RHS, ///< The right-hand-side of the expression + const Twine &NameStr = "" ///< Name of the instruction + ) : CmpInst(makeCmpResultType(LHS->getType()), + Instruction::FCmp, pred, LHS, RHS, NameStr, + &InsertAtEnd) { + assert(pred <= FCmpInst::LAST_FCMP_PREDICATE && + "Invalid FCmp predicate value"); + assert(getOperand(0)->getType() == getOperand(1)->getType() && + "Both operands to FCmp instruction are not of the same type!"); + // Check that the operands are the right type + assert(getOperand(0)->getType()->isFPOrFPVector() && + "Invalid operand types for FCmp instruction"); + } + + /// @brief Constructor with no-insertion semantics + FCmpInst( + Predicate pred, ///< The predicate to use for the comparison + Value *LHS, ///< The left-hand-side of the expression + Value *RHS, ///< The right-hand-side of the expression + const Twine &NameStr = "" ///< Name of the instruction + ) : CmpInst(makeCmpResultType(LHS->getType()), + Instruction::FCmp, pred, LHS, RHS, NameStr) { + assert(pred <= FCmpInst::LAST_FCMP_PREDICATE && + "Invalid FCmp predicate value"); + assert(getOperand(0)->getType() == getOperand(1)->getType() && + "Both operands to FCmp instruction are not of the same type!"); + // Check that the operands are the right type + assert(getOperand(0)->getType()->isFPOrFPVector() && + "Invalid operand types for FCmp instruction"); + } + + /// @returns true if the predicate of this instruction is EQ or NE. + /// @brief Determine if this is an equality predicate. + bool isEquality() const { + return SubclassData == FCMP_OEQ || SubclassData == FCMP_ONE || + SubclassData == FCMP_UEQ || SubclassData == FCMP_UNE; + } + + /// @returns true if the predicate of this instruction is commutative. + /// @brief Determine if this is a commutative predicate. + bool isCommutative() const { + return isEquality() || + SubclassData == FCMP_FALSE || + SubclassData == FCMP_TRUE || + SubclassData == FCMP_ORD || + SubclassData == FCMP_UNO; + } + + /// @returns true if the predicate is relational (not EQ or NE). + /// @brief Determine if this a relational predicate. + bool isRelational() const { return !isEquality(); } + + /// Exchange the two operands to this instruction in such a way that it does + /// not modify the semantics of the instruction. The predicate value may be + /// changed to retain the same result if the predicate is order dependent + /// (e.g. ult). + /// @brief Swap operands and adjust predicate. + void swapOperands() { + SubclassData = getSwappedPredicate(); + Op<0>().swap(Op<1>()); + } + + /// @brief Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const FCmpInst *) { return true; } + static inline bool classof(const Instruction *I) { + return I->getOpcode() == Instruction::FCmp; + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } +}; + +//===----------------------------------------------------------------------===// +// CallInst Class +//===----------------------------------------------------------------------===// +/// CallInst - This class represents a function call, abstracting a target +/// machine's calling convention. This class uses low bit of the SubClassData +/// field to indicate whether or not this is a tail call. The rest of the bits +/// hold the calling convention of the call. +/// + +class CallInst : public Instruction { + AttrListPtr AttributeList; ///< parameter attributes for call + CallInst(const CallInst &CI); + void init(Value *Func, Value* const *Params, unsigned NumParams); + void init(Value *Func, Value *Actual1, Value *Actual2); + void init(Value *Func, Value *Actual); + void init(Value *Func); + + template + void init(Value *Func, InputIterator ArgBegin, InputIterator ArgEnd, + const Twine &NameStr, + // This argument ensures that we have an iterator we can + // do arithmetic on in constant time + std::random_access_iterator_tag) { + unsigned NumArgs = (unsigned)std::distance(ArgBegin, ArgEnd); + + // This requires that the iterator points to contiguous memory. + init(Func, NumArgs ? &*ArgBegin : 0, NumArgs); + setName(NameStr); + } + + /// Construct a CallInst given a range of arguments. InputIterator + /// must be a random-access iterator pointing to contiguous storage + /// (e.g. a std::vector<>::iterator). Checks are made for + /// random-accessness but not for contiguous storage as that would + /// incur runtime overhead. + /// @brief Construct a CallInst from a range of arguments + template + CallInst(Value *Func, InputIterator ArgBegin, InputIterator ArgEnd, + const Twine &NameStr, Instruction *InsertBefore); + + /// Construct a CallInst given a range of arguments. InputIterator + /// must be a random-access iterator pointing to contiguous storage + /// (e.g. a std::vector<>::iterator). Checks are made for + /// random-accessness but not for contiguous storage as that would + /// incur runtime overhead. + /// @brief Construct a CallInst from a range of arguments + template + inline CallInst(Value *Func, InputIterator ArgBegin, InputIterator ArgEnd, + const Twine &NameStr, BasicBlock *InsertAtEnd); + + CallInst(Value *F, Value *Actual, const Twine &NameStr, + Instruction *InsertBefore); + CallInst(Value *F, Value *Actual, const Twine &NameStr, + BasicBlock *InsertAtEnd); + explicit CallInst(Value *F, const Twine &NameStr, + Instruction *InsertBefore); + CallInst(Value *F, const Twine &NameStr, BasicBlock *InsertAtEnd); +protected: + virtual CallInst *clone_impl() const; +public: + template + static CallInst *Create(Value *Func, + InputIterator ArgBegin, InputIterator ArgEnd, + const Twine &NameStr = "", + Instruction *InsertBefore = 0) { + return new((unsigned)(ArgEnd - ArgBegin + 1)) + CallInst(Func, ArgBegin, ArgEnd, NameStr, InsertBefore); + } + template + static CallInst *Create(Value *Func, + InputIterator ArgBegin, InputIterator ArgEnd, + const Twine &NameStr, BasicBlock *InsertAtEnd) { + return new((unsigned)(ArgEnd - ArgBegin + 1)) + CallInst(Func, ArgBegin, ArgEnd, NameStr, InsertAtEnd); + } + static CallInst *Create(Value *F, Value *Actual, + const Twine &NameStr = "", + Instruction *InsertBefore = 0) { + return new(2) CallInst(F, Actual, NameStr, InsertBefore); + } + static CallInst *Create(Value *F, Value *Actual, const Twine &NameStr, + BasicBlock *InsertAtEnd) { + return new(2) CallInst(F, Actual, NameStr, InsertAtEnd); + } + static CallInst *Create(Value *F, const Twine &NameStr = "", + Instruction *InsertBefore = 0) { + return new(1) CallInst(F, NameStr, InsertBefore); + } + static CallInst *Create(Value *F, const Twine &NameStr, + BasicBlock *InsertAtEnd) { + return new(1) CallInst(F, NameStr, InsertAtEnd); + } + /// CreateMalloc - Generate the IR for a call to malloc: + /// 1. Compute the malloc call's argument as the specified type's size, + /// possibly multiplied by the array size if the array size is not + /// constant 1. + /// 2. Call malloc with that argument. + /// 3. Bitcast the result of the malloc call to the specified type. + static Instruction *CreateMalloc(Instruction *InsertBefore, + const Type *IntPtrTy, const Type *AllocTy, + Value *AllocSize, Value *ArraySize = 0, + const Twine &Name = ""); + static Instruction *CreateMalloc(BasicBlock *InsertAtEnd, + const Type *IntPtrTy, const Type *AllocTy, + Value *AllocSize, Value *ArraySize = 0, + Function* MallocF = 0, + const Twine &Name = ""); + /// CreateFree - Generate the IR for a call to the builtin free function. + static void CreateFree(Value* Source, Instruction *InsertBefore); + static Instruction* CreateFree(Value* Source, BasicBlock *InsertAtEnd); + + ~CallInst(); + + bool isTailCall() const { return SubclassData & 1; } + void setTailCall(bool isTC = true) { + SubclassData = (SubclassData & ~1) | unsigned(isTC); + } + + /// Provide fast operand accessors + DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); + + /// getCallingConv/setCallingConv - Get or set the calling convention of this + /// function call. + CallingConv::ID getCallingConv() const { + return static_cast(SubclassData >> 1); + } + void setCallingConv(CallingConv::ID CC) { + SubclassData = (SubclassData & 1) | (static_cast(CC) << 1); + } + + /// getAttributes - Return the parameter attributes for this call. + /// + const AttrListPtr &getAttributes() const { return AttributeList; } + + /// setAttributes - Set the parameter attributes for this call. + /// + void setAttributes(const AttrListPtr &Attrs) { AttributeList = Attrs; } + + /// addAttribute - adds the attribute to the list of attributes. + void addAttribute(unsigned i, Attributes attr); + + /// removeAttribute - removes the attribute from the list of attributes. + void removeAttribute(unsigned i, Attributes attr); + + /// @brief Determine whether the call or the callee has the given attribute. + bool paramHasAttr(unsigned i, Attributes attr) const; + + /// @brief Extract the alignment for a call or parameter (0=unknown). + unsigned getParamAlignment(unsigned i) const { + return AttributeList.getParamAlignment(i); + } + + /// @brief Determine if the call does not access memory. + bool doesNotAccessMemory() const { + return paramHasAttr(~0, Attribute::ReadNone); + } + void setDoesNotAccessMemory(bool NotAccessMemory = true) { + if (NotAccessMemory) addAttribute(~0, Attribute::ReadNone); + else removeAttribute(~0, Attribute::ReadNone); + } + + /// @brief Determine if the call does not access or only reads memory. + bool onlyReadsMemory() const { + return doesNotAccessMemory() || paramHasAttr(~0, Attribute::ReadOnly); + } + void setOnlyReadsMemory(bool OnlyReadsMemory = true) { + if (OnlyReadsMemory) addAttribute(~0, Attribute::ReadOnly); + else removeAttribute(~0, Attribute::ReadOnly | Attribute::ReadNone); + } + + /// @brief Determine if the call cannot return. + bool doesNotReturn() const { + return paramHasAttr(~0, Attribute::NoReturn); + } + void setDoesNotReturn(bool DoesNotReturn = true) { + if (DoesNotReturn) addAttribute(~0, Attribute::NoReturn); + else removeAttribute(~0, Attribute::NoReturn); + } + + /// @brief Determine if the call cannot unwind. + bool doesNotThrow() const { + return paramHasAttr(~0, Attribute::NoUnwind); + } + void setDoesNotThrow(bool DoesNotThrow = true) { + if (DoesNotThrow) addAttribute(~0, Attribute::NoUnwind); + else removeAttribute(~0, Attribute::NoUnwind); + } + + /// @brief Determine if the call returns a structure through first + /// pointer argument. + bool hasStructRetAttr() const { + // Be friendly and also check the callee. + return paramHasAttr(1, Attribute::StructRet); + } + + /// @brief Determine if any call argument is an aggregate passed by value. + bool hasByValArgument() const { + return AttributeList.hasAttrSomewhere(Attribute::ByVal); + } + + /// getCalledFunction - Return the function called, or null if this is an + /// indirect function invocation. + /// + Function *getCalledFunction() const { + return dyn_cast(Op<0>()); + } + + /// getCalledValue - Get a pointer to the function that is invoked by this + /// instruction. + const Value *getCalledValue() const { return Op<0>(); } + Value *getCalledValue() { return Op<0>(); } + + /// setCalledFunction - Set the function called. + void setCalledFunction(Value* Fn) { + Op<0>() = Fn; + } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const CallInst *) { return true; } + static inline bool classof(const Instruction *I) { + return I->getOpcode() == Instruction::Call; + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } +}; + +template <> +struct OperandTraits : public VariadicOperandTraits<1> { +}; + +template +CallInst::CallInst(Value *Func, InputIterator ArgBegin, InputIterator ArgEnd, + const Twine &NameStr, BasicBlock *InsertAtEnd) + : Instruction(cast(cast(Func->getType()) + ->getElementType())->getReturnType(), + Instruction::Call, + OperandTraits::op_end(this) - (ArgEnd - ArgBegin + 1), + (unsigned)(ArgEnd - ArgBegin + 1), InsertAtEnd) { + init(Func, ArgBegin, ArgEnd, NameStr, + typename std::iterator_traits::iterator_category()); +} + +template +CallInst::CallInst(Value *Func, InputIterator ArgBegin, InputIterator ArgEnd, + const Twine &NameStr, Instruction *InsertBefore) + : Instruction(cast(cast(Func->getType()) + ->getElementType())->getReturnType(), + Instruction::Call, + OperandTraits::op_end(this) - (ArgEnd - ArgBegin + 1), + (unsigned)(ArgEnd - ArgBegin + 1), InsertBefore) { + init(Func, ArgBegin, ArgEnd, NameStr, + typename std::iterator_traits::iterator_category()); +} + +DEFINE_TRANSPARENT_OPERAND_ACCESSORS(CallInst, Value) + +//===----------------------------------------------------------------------===// +// SelectInst Class +//===----------------------------------------------------------------------===// + +/// SelectInst - This class represents the LLVM 'select' instruction. +/// +class SelectInst : public Instruction { + void init(Value *C, Value *S1, Value *S2) { + assert(!areInvalidOperands(C, S1, S2) && "Invalid operands for select"); + Op<0>() = C; + Op<1>() = S1; + Op<2>() = S2; + } + + SelectInst(Value *C, Value *S1, Value *S2, const Twine &NameStr, + Instruction *InsertBefore) + : Instruction(S1->getType(), Instruction::Select, + &Op<0>(), 3, InsertBefore) { + init(C, S1, S2); + setName(NameStr); + } + SelectInst(Value *C, Value *S1, Value *S2, const Twine &NameStr, + BasicBlock *InsertAtEnd) + : Instruction(S1->getType(), Instruction::Select, + &Op<0>(), 3, InsertAtEnd) { + init(C, S1, S2); + setName(NameStr); + } +protected: + virtual SelectInst *clone_impl() const; +public: + static SelectInst *Create(Value *C, Value *S1, Value *S2, + const Twine &NameStr = "", + Instruction *InsertBefore = 0) { + return new(3) SelectInst(C, S1, S2, NameStr, InsertBefore); + } + static SelectInst *Create(Value *C, Value *S1, Value *S2, + const Twine &NameStr, + BasicBlock *InsertAtEnd) { + return new(3) SelectInst(C, S1, S2, NameStr, InsertAtEnd); + } + + const Value *getCondition() const { return Op<0>(); } + const Value *getTrueValue() const { return Op<1>(); } + const Value *getFalseValue() const { return Op<2>(); } + Value *getCondition() { return Op<0>(); } + Value *getTrueValue() { return Op<1>(); } + Value *getFalseValue() { return Op<2>(); } + + /// areInvalidOperands - Return a string if the specified operands are invalid + /// for a select operation, otherwise return null. + static const char *areInvalidOperands(Value *Cond, Value *True, Value *False); + + /// Transparently provide more efficient getOperand methods. + DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); + + OtherOps getOpcode() const { + return static_cast(Instruction::getOpcode()); + } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const SelectInst *) { return true; } + static inline bool classof(const Instruction *I) { + return I->getOpcode() == Instruction::Select; + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } +}; + +template <> +struct OperandTraits : public FixedNumOperandTraits<3> { +}; + +DEFINE_TRANSPARENT_OPERAND_ACCESSORS(SelectInst, Value) + +//===----------------------------------------------------------------------===// +// VAArgInst Class +//===----------------------------------------------------------------------===// + +/// VAArgInst - This class represents the va_arg llvm instruction, which returns +/// an argument of the specified type given a va_list and increments that list +/// +class VAArgInst : public UnaryInstruction { +protected: + virtual VAArgInst *clone_impl() const; + +public: + VAArgInst(Value *List, const Type *Ty, const Twine &NameStr = "", + Instruction *InsertBefore = 0) + : UnaryInstruction(Ty, VAArg, List, InsertBefore) { + setName(NameStr); + } + VAArgInst(Value *List, const Type *Ty, const Twine &NameStr, + BasicBlock *InsertAtEnd) + : UnaryInstruction(Ty, VAArg, List, InsertAtEnd) { + setName(NameStr); + } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const VAArgInst *) { return true; } + static inline bool classof(const Instruction *I) { + return I->getOpcode() == VAArg; + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } +}; + +//===----------------------------------------------------------------------===// +// ExtractElementInst Class +//===----------------------------------------------------------------------===// + +/// ExtractElementInst - This instruction extracts a single (scalar) +/// element from a VectorType value +/// +class ExtractElementInst : public Instruction { + ExtractElementInst(Value *Vec, Value *Idx, const Twine &NameStr = "", + Instruction *InsertBefore = 0); + ExtractElementInst(Value *Vec, Value *Idx, const Twine &NameStr, + BasicBlock *InsertAtEnd); +protected: + virtual ExtractElementInst *clone_impl() const; + +public: + static ExtractElementInst *Create(Value *Vec, Value *Idx, + const Twine &NameStr = "", + Instruction *InsertBefore = 0) { + return new(2) ExtractElementInst(Vec, Idx, NameStr, InsertBefore); + } + static ExtractElementInst *Create(Value *Vec, Value *Idx, + const Twine &NameStr, + BasicBlock *InsertAtEnd) { + return new(2) ExtractElementInst(Vec, Idx, NameStr, InsertAtEnd); + } + + /// isValidOperands - Return true if an extractelement instruction can be + /// formed with the specified operands. + static bool isValidOperands(const Value *Vec, const Value *Idx); + + Value *getVectorOperand() { return Op<0>(); } + Value *getIndexOperand() { return Op<1>(); } + const Value *getVectorOperand() const { return Op<0>(); } + const Value *getIndexOperand() const { return Op<1>(); } + + const VectorType *getVectorOperandType() const { + return reinterpret_cast(getVectorOperand()->getType()); + } + + + /// Transparently provide more efficient getOperand methods. + DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const ExtractElementInst *) { return true; } + static inline bool classof(const Instruction *I) { + return I->getOpcode() == Instruction::ExtractElement; + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } +}; + +template <> +struct OperandTraits : public FixedNumOperandTraits<2> { +}; + +DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ExtractElementInst, Value) + +//===----------------------------------------------------------------------===// +// InsertElementInst Class +//===----------------------------------------------------------------------===// + +/// InsertElementInst - This instruction inserts a single (scalar) +/// element into a VectorType value +/// +class InsertElementInst : public Instruction { + InsertElementInst(Value *Vec, Value *NewElt, Value *Idx, + const Twine &NameStr = "", + Instruction *InsertBefore = 0); + InsertElementInst(Value *Vec, Value *NewElt, Value *Idx, + const Twine &NameStr, BasicBlock *InsertAtEnd); +protected: + virtual InsertElementInst *clone_impl() const; + +public: + static InsertElementInst *Create(Value *Vec, Value *NewElt, Value *Idx, + const Twine &NameStr = "", + Instruction *InsertBefore = 0) { + return new(3) InsertElementInst(Vec, NewElt, Idx, NameStr, InsertBefore); + } + static InsertElementInst *Create(Value *Vec, Value *NewElt, Value *Idx, + const Twine &NameStr, + BasicBlock *InsertAtEnd) { + return new(3) InsertElementInst(Vec, NewElt, Idx, NameStr, InsertAtEnd); + } + + /// isValidOperands - Return true if an insertelement instruction can be + /// formed with the specified operands. + static bool isValidOperands(const Value *Vec, const Value *NewElt, + const Value *Idx); + + /// getType - Overload to return most specific vector type. + /// + const VectorType *getType() const { + return reinterpret_cast(Instruction::getType()); + } + + /// Transparently provide more efficient getOperand methods. + DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const InsertElementInst *) { return true; } + static inline bool classof(const Instruction *I) { + return I->getOpcode() == Instruction::InsertElement; + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } +}; + +template <> +struct OperandTraits : public FixedNumOperandTraits<3> { +}; + +DEFINE_TRANSPARENT_OPERAND_ACCESSORS(InsertElementInst, Value) + +//===----------------------------------------------------------------------===// +// ShuffleVectorInst Class +//===----------------------------------------------------------------------===// + +/// ShuffleVectorInst - This instruction constructs a fixed permutation of two +/// input vectors. +/// +class ShuffleVectorInst : public Instruction { +protected: + virtual ShuffleVectorInst *clone_impl() const; + +public: + // allocate space for exactly three operands + void *operator new(size_t s) { + return User::operator new(s, 3); + } + ShuffleVectorInst(Value *V1, Value *V2, Value *Mask, + const Twine &NameStr = "", + Instruction *InsertBefor = 0); + ShuffleVectorInst(Value *V1, Value *V2, Value *Mask, + const Twine &NameStr, BasicBlock *InsertAtEnd); + + /// isValidOperands - Return true if a shufflevector instruction can be + /// formed with the specified operands. + static bool isValidOperands(const Value *V1, const Value *V2, + const Value *Mask); + + /// getType - Overload to return most specific vector type. + /// + const VectorType *getType() const { + return reinterpret_cast(Instruction::getType()); + } + + /// Transparently provide more efficient getOperand methods. + DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); + + /// getMaskValue - Return the index from the shuffle mask for the specified + /// output result. This is either -1 if the element is undef or a number less + /// than 2*numelements. + int getMaskValue(unsigned i) const; + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const ShuffleVectorInst *) { return true; } + static inline bool classof(const Instruction *I) { + return I->getOpcode() == Instruction::ShuffleVector; + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } +}; + +template <> +struct OperandTraits : public FixedNumOperandTraits<3> { +}; + +DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ShuffleVectorInst, Value) + +//===----------------------------------------------------------------------===// +// ExtractValueInst Class +//===----------------------------------------------------------------------===// + +/// ExtractValueInst - This instruction extracts a struct member or array +/// element value from an aggregate value. +/// +class ExtractValueInst : public UnaryInstruction { + SmallVector Indices; + + ExtractValueInst(const ExtractValueInst &EVI); + void init(const unsigned *Idx, unsigned NumIdx, + const Twine &NameStr); + void init(unsigned Idx, const Twine &NameStr); + + template + void init(InputIterator IdxBegin, InputIterator IdxEnd, + const Twine &NameStr, + // This argument ensures that we have an iterator we can + // do arithmetic on in constant time + std::random_access_iterator_tag) { + unsigned NumIdx = static_cast(std::distance(IdxBegin, IdxEnd)); + + // There's no fundamental reason why we require at least one index + // (other than weirdness with &*IdxBegin being invalid; see + // getelementptr's init routine for example). But there's no + // present need to support it. + assert(NumIdx > 0 && "ExtractValueInst must have at least one index"); + + // This requires that the iterator points to contiguous memory. + init(&*IdxBegin, NumIdx, NameStr); // FIXME: for the general case + // we have to build an array here + } + + /// getIndexedType - Returns the type of the element that would be extracted + /// with an extractvalue instruction with the specified parameters. + /// + /// Null is returned if the indices are invalid for the specified + /// pointer type. + /// + static const Type *getIndexedType(const Type *Agg, + const unsigned *Idx, unsigned NumIdx); + + template + static const Type *getIndexedType(const Type *Ptr, + InputIterator IdxBegin, + InputIterator IdxEnd, + // This argument ensures that we + // have an iterator we can do + // arithmetic on in constant time + std::random_access_iterator_tag) { + unsigned NumIdx = static_cast(std::distance(IdxBegin, IdxEnd)); + + if (NumIdx > 0) + // This requires that the iterator points to contiguous memory. + return getIndexedType(Ptr, &*IdxBegin, NumIdx); + else + return getIndexedType(Ptr, (const unsigned *)0, NumIdx); + } + + /// Constructors - Create a extractvalue instruction with a base aggregate + /// value and a list of indices. The first ctor can optionally insert before + /// an existing instruction, the second appends the new instruction to the + /// specified BasicBlock. + template + inline ExtractValueInst(Value *Agg, InputIterator IdxBegin, + InputIterator IdxEnd, + const Twine &NameStr, + Instruction *InsertBefore); + template + inline ExtractValueInst(Value *Agg, + InputIterator IdxBegin, InputIterator IdxEnd, + const Twine &NameStr, BasicBlock *InsertAtEnd); + + // allocate space for exactly one operand + void *operator new(size_t s) { + return User::operator new(s, 1); + } +protected: + virtual ExtractValueInst *clone_impl() const; + +public: + template + static ExtractValueInst *Create(Value *Agg, InputIterator IdxBegin, + InputIterator IdxEnd, + const Twine &NameStr = "", + Instruction *InsertBefore = 0) { + return new + ExtractValueInst(Agg, IdxBegin, IdxEnd, NameStr, InsertBefore); + } + template + static ExtractValueInst *Create(Value *Agg, + InputIterator IdxBegin, InputIterator IdxEnd, + const Twine &NameStr, + BasicBlock *InsertAtEnd) { + return new ExtractValueInst(Agg, IdxBegin, IdxEnd, NameStr, InsertAtEnd); + } + + /// Constructors - These two creators are convenience methods because one + /// index extractvalue instructions are much more common than those with + /// more than one. + static ExtractValueInst *Create(Value *Agg, unsigned Idx, + const Twine &NameStr = "", + Instruction *InsertBefore = 0) { + unsigned Idxs[1] = { Idx }; + return new ExtractValueInst(Agg, Idxs, Idxs + 1, NameStr, InsertBefore); + } + static ExtractValueInst *Create(Value *Agg, unsigned Idx, + const Twine &NameStr, + BasicBlock *InsertAtEnd) { + unsigned Idxs[1] = { Idx }; + return new ExtractValueInst(Agg, Idxs, Idxs + 1, NameStr, InsertAtEnd); + } + + /// getIndexedType - Returns the type of the element that would be extracted + /// with an extractvalue instruction with the specified parameters. + /// + /// Null is returned if the indices are invalid for the specified + /// pointer type. + /// + template + static const Type *getIndexedType(const Type *Ptr, + InputIterator IdxBegin, + InputIterator IdxEnd) { + return getIndexedType(Ptr, IdxBegin, IdxEnd, + typename std::iterator_traits:: + iterator_category()); + } + static const Type *getIndexedType(const Type *Ptr, unsigned Idx); + + typedef const unsigned* idx_iterator; + inline idx_iterator idx_begin() const { return Indices.begin(); } + inline idx_iterator idx_end() const { return Indices.end(); } + + Value *getAggregateOperand() { + return getOperand(0); + } + const Value *getAggregateOperand() const { + return getOperand(0); + } + static unsigned getAggregateOperandIndex() { + return 0U; // get index for modifying correct operand + } + + unsigned getNumIndices() const { // Note: always non-negative + return (unsigned)Indices.size(); + } + + bool hasIndices() const { + return true; + } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const ExtractValueInst *) { return true; } + static inline bool classof(const Instruction *I) { + return I->getOpcode() == Instruction::ExtractValue; + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } +}; + +template +ExtractValueInst::ExtractValueInst(Value *Agg, + InputIterator IdxBegin, + InputIterator IdxEnd, + const Twine &NameStr, + Instruction *InsertBefore) + : UnaryInstruction(checkType(getIndexedType(Agg->getType(), + IdxBegin, IdxEnd)), + ExtractValue, Agg, InsertBefore) { + init(IdxBegin, IdxEnd, NameStr, + typename std::iterator_traits::iterator_category()); +} +template +ExtractValueInst::ExtractValueInst(Value *Agg, + InputIterator IdxBegin, + InputIterator IdxEnd, + const Twine &NameStr, + BasicBlock *InsertAtEnd) + : UnaryInstruction(checkType(getIndexedType(Agg->getType(), + IdxBegin, IdxEnd)), + ExtractValue, Agg, InsertAtEnd) { + init(IdxBegin, IdxEnd, NameStr, + typename std::iterator_traits::iterator_category()); +} + + +//===----------------------------------------------------------------------===// +// InsertValueInst Class +//===----------------------------------------------------------------------===// + +/// InsertValueInst - This instruction inserts a struct field of array element +/// value into an aggregate value. +/// +class InsertValueInst : public Instruction { + SmallVector Indices; + + void *operator new(size_t, unsigned); // Do not implement + InsertValueInst(const InsertValueInst &IVI); + void init(Value *Agg, Value *Val, const unsigned *Idx, unsigned NumIdx, + const Twine &NameStr); + void init(Value *Agg, Value *Val, unsigned Idx, const Twine &NameStr); + + template + void init(Value *Agg, Value *Val, + InputIterator IdxBegin, InputIterator IdxEnd, + const Twine &NameStr, + // This argument ensures that we have an iterator we can + // do arithmetic on in constant time + std::random_access_iterator_tag) { + unsigned NumIdx = static_cast(std::distance(IdxBegin, IdxEnd)); + + // There's no fundamental reason why we require at least one index + // (other than weirdness with &*IdxBegin being invalid; see + // getelementptr's init routine for example). But there's no + // present need to support it. + assert(NumIdx > 0 && "InsertValueInst must have at least one index"); + + // This requires that the iterator points to contiguous memory. + init(Agg, Val, &*IdxBegin, NumIdx, NameStr); // FIXME: for the general case + // we have to build an array here + } + + /// Constructors - Create a insertvalue instruction with a base aggregate + /// value, a value to insert, and a list of indices. The first ctor can + /// optionally insert before an existing instruction, the second appends + /// the new instruction to the specified BasicBlock. + template + inline InsertValueInst(Value *Agg, Value *Val, InputIterator IdxBegin, + InputIterator IdxEnd, + const Twine &NameStr, + Instruction *InsertBefore); + template + inline InsertValueInst(Value *Agg, Value *Val, + InputIterator IdxBegin, InputIterator IdxEnd, + const Twine &NameStr, BasicBlock *InsertAtEnd); + + /// Constructors - These two constructors are convenience methods because one + /// and two index insertvalue instructions are so common. + InsertValueInst(Value *Agg, Value *Val, + unsigned Idx, const Twine &NameStr = "", + Instruction *InsertBefore = 0); + InsertValueInst(Value *Agg, Value *Val, unsigned Idx, + const Twine &NameStr, BasicBlock *InsertAtEnd); +protected: + virtual InsertValueInst *clone_impl() const; +public: + // allocate space for exactly two operands + void *operator new(size_t s) { + return User::operator new(s, 2); + } + + template + static InsertValueInst *Create(Value *Agg, Value *Val, InputIterator IdxBegin, + InputIterator IdxEnd, + const Twine &NameStr = "", + Instruction *InsertBefore = 0) { + return new InsertValueInst(Agg, Val, IdxBegin, IdxEnd, + NameStr, InsertBefore); + } + template + static InsertValueInst *Create(Value *Agg, Value *Val, + InputIterator IdxBegin, InputIterator IdxEnd, + const Twine &NameStr, + BasicBlock *InsertAtEnd) { + return new InsertValueInst(Agg, Val, IdxBegin, IdxEnd, + NameStr, InsertAtEnd); + } + + /// Constructors - These two creators are convenience methods because one + /// index insertvalue instructions are much more common than those with + /// more than one. + static InsertValueInst *Create(Value *Agg, Value *Val, unsigned Idx, + const Twine &NameStr = "", + Instruction *InsertBefore = 0) { + return new InsertValueInst(Agg, Val, Idx, NameStr, InsertBefore); + } + static InsertValueInst *Create(Value *Agg, Value *Val, unsigned Idx, + const Twine &NameStr, + BasicBlock *InsertAtEnd) { + return new InsertValueInst(Agg, Val, Idx, NameStr, InsertAtEnd); + } + + /// Transparently provide more efficient getOperand methods. + DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); + + typedef const unsigned* idx_iterator; + inline idx_iterator idx_begin() const { return Indices.begin(); } + inline idx_iterator idx_end() const { return Indices.end(); } + + Value *getAggregateOperand() { + return getOperand(0); + } + const Value *getAggregateOperand() const { + return getOperand(0); + } + static unsigned getAggregateOperandIndex() { + return 0U; // get index for modifying correct operand + } + + Value *getInsertedValueOperand() { + return getOperand(1); + } + const Value *getInsertedValueOperand() const { + return getOperand(1); + } + static unsigned getInsertedValueOperandIndex() { + return 1U; // get index for modifying correct operand + } + + unsigned getNumIndices() const { // Note: always non-negative + return (unsigned)Indices.size(); + } + + bool hasIndices() const { + return true; + } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const InsertValueInst *) { return true; } + static inline bool classof(const Instruction *I) { + return I->getOpcode() == Instruction::InsertValue; + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } +}; + +template <> +struct OperandTraits : public FixedNumOperandTraits<2> { +}; + +template +InsertValueInst::InsertValueInst(Value *Agg, + Value *Val, + InputIterator IdxBegin, + InputIterator IdxEnd, + const Twine &NameStr, + Instruction *InsertBefore) + : Instruction(Agg->getType(), InsertValue, + OperandTraits::op_begin(this), + 2, InsertBefore) { + init(Agg, Val, IdxBegin, IdxEnd, NameStr, + typename std::iterator_traits::iterator_category()); +} +template +InsertValueInst::InsertValueInst(Value *Agg, + Value *Val, + InputIterator IdxBegin, + InputIterator IdxEnd, + const Twine &NameStr, + BasicBlock *InsertAtEnd) + : Instruction(Agg->getType(), InsertValue, + OperandTraits::op_begin(this), + 2, InsertAtEnd) { + init(Agg, Val, IdxBegin, IdxEnd, NameStr, + typename std::iterator_traits::iterator_category()); +} + +DEFINE_TRANSPARENT_OPERAND_ACCESSORS(InsertValueInst, Value) + +//===----------------------------------------------------------------------===// +// PHINode Class +//===----------------------------------------------------------------------===// + +// PHINode - The PHINode class is used to represent the magical mystical PHI +// node, that can not exist in nature, but can be synthesized in a computer +// scientist's overactive imagination. +// +class PHINode : public Instruction { + void *operator new(size_t, unsigned); // DO NOT IMPLEMENT + /// ReservedSpace - The number of operands actually allocated. NumOperands is + /// the number actually in use. + unsigned ReservedSpace; + PHINode(const PHINode &PN); + // allocate space for exactly zero operands + void *operator new(size_t s) { + return User::operator new(s, 0); + } + explicit PHINode(const Type *Ty, const Twine &NameStr = "", + Instruction *InsertBefore = 0) + : Instruction(Ty, Instruction::PHI, 0, 0, InsertBefore), + ReservedSpace(0) { + setName(NameStr); + } + + PHINode(const Type *Ty, const Twine &NameStr, BasicBlock *InsertAtEnd) + : Instruction(Ty, Instruction::PHI, 0, 0, InsertAtEnd), + ReservedSpace(0) { + setName(NameStr); + } +protected: + virtual PHINode *clone_impl() const; +public: + static PHINode *Create(const Type *Ty, const Twine &NameStr = "", + Instruction *InsertBefore = 0) { + return new PHINode(Ty, NameStr, InsertBefore); + } + static PHINode *Create(const Type *Ty, const Twine &NameStr, + BasicBlock *InsertAtEnd) { + return new PHINode(Ty, NameStr, InsertAtEnd); + } + ~PHINode(); + + /// reserveOperandSpace - This method can be used to avoid repeated + /// reallocation of PHI operand lists by reserving space for the correct + /// number of operands before adding them. Unlike normal vector reserves, + /// this method can also be used to trim the operand space. + void reserveOperandSpace(unsigned NumValues) { + resizeOperands(NumValues*2); + } + + /// Provide fast operand accessors + DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); + + /// getNumIncomingValues - Return the number of incoming edges + /// + unsigned getNumIncomingValues() const { return getNumOperands()/2; } + + /// getIncomingValue - Return incoming value number x + /// + Value *getIncomingValue(unsigned i) const { + assert(i*2 < getNumOperands() && "Invalid value number!"); + return getOperand(i*2); + } + void setIncomingValue(unsigned i, Value *V) { + assert(i*2 < getNumOperands() && "Invalid value number!"); + setOperand(i*2, V); + } + static unsigned getOperandNumForIncomingValue(unsigned i) { + return i*2; + } + static unsigned getIncomingValueNumForOperand(unsigned i) { + assert(i % 2 == 0 && "Invalid incoming-value operand index!"); + return i/2; + } + + /// getIncomingBlock - Return incoming basic block #i. + /// + BasicBlock *getIncomingBlock(unsigned i) const { + return cast(getOperand(i*2+1)); + } + + /// getIncomingBlock - Return incoming basic block corresponding + /// to an operand of the PHI. + /// + BasicBlock *getIncomingBlock(const Use &U) const { + assert(this == U.getUser() && "Iterator doesn't point to PHI's Uses?"); + return cast((&U + 1)->get()); + } + + /// getIncomingBlock - Return incoming basic block corresponding + /// to value use iterator. + /// + template + BasicBlock *getIncomingBlock(value_use_iterator I) const { + return getIncomingBlock(I.getUse()); + } + + + void setIncomingBlock(unsigned i, BasicBlock *BB) { + setOperand(i*2+1, (Value*)BB); + } + static unsigned getOperandNumForIncomingBlock(unsigned i) { + return i*2+1; + } + static unsigned getIncomingBlockNumForOperand(unsigned i) { + assert(i % 2 == 1 && "Invalid incoming-block operand index!"); + return i/2; + } + + /// addIncoming - Add an incoming value to the end of the PHI list + /// + void addIncoming(Value *V, BasicBlock *BB) { + assert(V && "PHI node got a null value!"); + assert(BB && "PHI node got a null basic block!"); + assert(getType() == V->getType() && + "All operands to PHI node must be the same type as the PHI node!"); + unsigned OpNo = NumOperands; + if (OpNo+2 > ReservedSpace) + resizeOperands(0); // Get more space! + // Initialize some new operands. + NumOperands = OpNo+2; + OperandList[OpNo] = V; + OperandList[OpNo+1] = (Value*)BB; + } + + /// removeIncomingValue - Remove an incoming value. This is useful if a + /// predecessor basic block is deleted. The value removed is returned. + /// + /// If the last incoming value for a PHI node is removed (and DeletePHIIfEmpty + /// is true), the PHI node is destroyed and any uses of it are replaced with + /// dummy values. The only time there should be zero incoming values to a PHI + /// node is when the block is dead, so this strategy is sound. + /// + Value *removeIncomingValue(unsigned Idx, bool DeletePHIIfEmpty = true); + + Value *removeIncomingValue(const BasicBlock *BB, bool DeletePHIIfEmpty=true) { + int Idx = getBasicBlockIndex(BB); + assert(Idx >= 0 && "Invalid basic block argument to remove!"); + return removeIncomingValue(Idx, DeletePHIIfEmpty); + } + + /// getBasicBlockIndex - Return the first index of the specified basic + /// block in the value list for this PHI. Returns -1 if no instance. + /// + int getBasicBlockIndex(const BasicBlock *BB) const { + Use *OL = OperandList; + for (unsigned i = 0, e = getNumOperands(); i != e; i += 2) + if (OL[i+1].get() == (const Value*)BB) return i/2; + return -1; + } + + Value *getIncomingValueForBlock(const BasicBlock *BB) const { + return getIncomingValue(getBasicBlockIndex(BB)); + } + + /// hasConstantValue - If the specified PHI node always merges together the + /// same value, return the value, otherwise return null. + /// + /// If the PHI has undef operands, but all the rest of the operands are + /// some unique value, return that value if it can be proved that the + /// value dominates the PHI. If DT is null, use a conservative check, + /// otherwise use DT to test for dominance. + /// + Value *hasConstantValue(DominatorTree *DT = 0) const; + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const PHINode *) { return true; } + static inline bool classof(const Instruction *I) { + return I->getOpcode() == Instruction::PHI; + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } + private: + void resizeOperands(unsigned NumOperands); +}; + +template <> +struct OperandTraits : public HungoffOperandTraits<2> { +}; + +DEFINE_TRANSPARENT_OPERAND_ACCESSORS(PHINode, Value) + + +//===----------------------------------------------------------------------===// +// ReturnInst Class +//===----------------------------------------------------------------------===// + +//===--------------------------------------------------------------------------- +/// ReturnInst - Return a value (possibly void), from a function. Execution +/// does not continue in this function any longer. +/// +class ReturnInst : public TerminatorInst { + ReturnInst(const ReturnInst &RI); + +private: + // ReturnInst constructors: + // ReturnInst() - 'ret void' instruction + // ReturnInst( null) - 'ret void' instruction + // ReturnInst(Value* X) - 'ret X' instruction + // ReturnInst( null, Inst *I) - 'ret void' instruction, insert before I + // ReturnInst(Value* X, Inst *I) - 'ret X' instruction, insert before I + // ReturnInst( null, BB *B) - 'ret void' instruction, insert @ end of B + // ReturnInst(Value* X, BB *B) - 'ret X' instruction, insert @ end of B + // + // NOTE: If the Value* passed is of type void then the constructor behaves as + // if it was passed NULL. + explicit ReturnInst(LLVMContext &C, Value *retVal = 0, + Instruction *InsertBefore = 0); + ReturnInst(LLVMContext &C, Value *retVal, BasicBlock *InsertAtEnd); + explicit ReturnInst(LLVMContext &C, BasicBlock *InsertAtEnd); +protected: + virtual ReturnInst *clone_impl() const; +public: + static ReturnInst* Create(LLVMContext &C, Value *retVal = 0, + Instruction *InsertBefore = 0) { + return new(!!retVal) ReturnInst(C, retVal, InsertBefore); + } + static ReturnInst* Create(LLVMContext &C, Value *retVal, + BasicBlock *InsertAtEnd) { + return new(!!retVal) ReturnInst(C, retVal, InsertAtEnd); + } + static ReturnInst* Create(LLVMContext &C, BasicBlock *InsertAtEnd) { + return new(0) ReturnInst(C, InsertAtEnd); + } + virtual ~ReturnInst(); + + /// Provide fast operand accessors + DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); + + /// Convenience accessor + Value *getReturnValue(unsigned n = 0) const { + return n < getNumOperands() + ? getOperand(n) + : 0; + } + + unsigned getNumSuccessors() const { return 0; } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const ReturnInst *) { return true; } + static inline bool classof(const Instruction *I) { + return (I->getOpcode() == Instruction::Ret); + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } + private: + virtual BasicBlock *getSuccessorV(unsigned idx) const; + virtual unsigned getNumSuccessorsV() const; + virtual void setSuccessorV(unsigned idx, BasicBlock *B); +}; + +template <> +struct OperandTraits : public OptionalOperandTraits<> { +}; + +DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ReturnInst, Value) + +//===----------------------------------------------------------------------===// +// BranchInst Class +//===----------------------------------------------------------------------===// + +//===--------------------------------------------------------------------------- +/// BranchInst - Conditional or Unconditional Branch instruction. +/// +class BranchInst : public TerminatorInst { + /// Ops list - Branches are strange. The operands are ordered: + /// [Cond, FalseDest,] TrueDest. This makes some accessors faster because + /// they don't have to check for cond/uncond branchness. These are mostly + /// accessed relative from op_end(). + BranchInst(const BranchInst &BI); + void AssertOK(); + // BranchInst constructors (where {B, T, F} are blocks, and C is a condition): + // BranchInst(BB *B) - 'br B' + // BranchInst(BB* T, BB *F, Value *C) - 'br C, T, F' + // BranchInst(BB* B, Inst *I) - 'br B' insert before I + // BranchInst(BB* T, BB *F, Value *C, Inst *I) - 'br C, T, F', insert before I + // BranchInst(BB* B, BB *I) - 'br B' insert at end + // BranchInst(BB* T, BB *F, Value *C, BB *I) - 'br C, T, F', insert at end + explicit BranchInst(BasicBlock *IfTrue, Instruction *InsertBefore = 0); + BranchInst(BasicBlock *IfTrue, BasicBlock *IfFalse, Value *Cond, + Instruction *InsertBefore = 0); + BranchInst(BasicBlock *IfTrue, BasicBlock *InsertAtEnd); + BranchInst(BasicBlock *IfTrue, BasicBlock *IfFalse, Value *Cond, + BasicBlock *InsertAtEnd); +protected: + virtual BranchInst *clone_impl() const; +public: + static BranchInst *Create(BasicBlock *IfTrue, Instruction *InsertBefore = 0) { + return new(1, true) BranchInst(IfTrue, InsertBefore); + } + static BranchInst *Create(BasicBlock *IfTrue, BasicBlock *IfFalse, + Value *Cond, Instruction *InsertBefore = 0) { + return new(3) BranchInst(IfTrue, IfFalse, Cond, InsertBefore); + } + static BranchInst *Create(BasicBlock *IfTrue, BasicBlock *InsertAtEnd) { + return new(1, true) BranchInst(IfTrue, InsertAtEnd); + } + static BranchInst *Create(BasicBlock *IfTrue, BasicBlock *IfFalse, + Value *Cond, BasicBlock *InsertAtEnd) { + return new(3) BranchInst(IfTrue, IfFalse, Cond, InsertAtEnd); + } + + ~BranchInst(); + + /// Transparently provide more efficient getOperand methods. + DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); + + bool isUnconditional() const { return getNumOperands() == 1; } + bool isConditional() const { return getNumOperands() == 3; } + + Value *getCondition() const { + assert(isConditional() && "Cannot get condition of an uncond branch!"); + return Op<-3>(); + } + + void setCondition(Value *V) { + assert(isConditional() && "Cannot set condition of unconditional branch!"); + Op<-3>() = V; + } + + // setUnconditionalDest - Change the current branch to an unconditional branch + // targeting the specified block. + // FIXME: Eliminate this ugly method. + void setUnconditionalDest(BasicBlock *Dest) { + Op<-1>() = (Value*)Dest; + if (isConditional()) { // Convert this to an uncond branch. + Op<-2>() = 0; + Op<-3>() = 0; + NumOperands = 1; + OperandList = op_begin(); + } + } + + unsigned getNumSuccessors() const { return 1+isConditional(); } + + BasicBlock *getSuccessor(unsigned i) const { + assert(i < getNumSuccessors() && "Successor # out of range for Branch!"); + return cast_or_null((&Op<-1>() - i)->get()); + } + + void setSuccessor(unsigned idx, BasicBlock *NewSucc) { + assert(idx < getNumSuccessors() && "Successor # out of range for Branch!"); + *(&Op<-1>() - idx) = (Value*)NewSucc; + } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const BranchInst *) { return true; } + static inline bool classof(const Instruction *I) { + return (I->getOpcode() == Instruction::Br); + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } +private: + virtual BasicBlock *getSuccessorV(unsigned idx) const; + virtual unsigned getNumSuccessorsV() const; + virtual void setSuccessorV(unsigned idx, BasicBlock *B); +}; + +template <> +struct OperandTraits : public VariadicOperandTraits<1> {}; + +DEFINE_TRANSPARENT_OPERAND_ACCESSORS(BranchInst, Value) + +//===----------------------------------------------------------------------===// +// SwitchInst Class +//===----------------------------------------------------------------------===// + +//===--------------------------------------------------------------------------- +/// SwitchInst - Multiway switch +/// +class SwitchInst : public TerminatorInst { + void *operator new(size_t, unsigned); // DO NOT IMPLEMENT + unsigned ReservedSpace; + // Operand[0] = Value to switch on + // Operand[1] = Default basic block destination + // Operand[2n ] = Value to match + // Operand[2n+1] = BasicBlock to go to on match + SwitchInst(const SwitchInst &SI); + void init(Value *Value, BasicBlock *Default, unsigned NumCases); + void resizeOperands(unsigned No); + // allocate space for exactly zero operands + void *operator new(size_t s) { + return User::operator new(s, 0); + } + /// SwitchInst ctor - Create a new switch instruction, specifying a value to + /// switch on and a default destination. The number of additional cases can + /// be specified here to make memory allocation more efficient. This + /// constructor can also autoinsert before another instruction. + SwitchInst(Value *Value, BasicBlock *Default, unsigned NumCases, + Instruction *InsertBefore); + + /// SwitchInst ctor - Create a new switch instruction, specifying a value to + /// switch on and a default destination. The number of additional cases can + /// be specified here to make memory allocation more efficient. This + /// constructor also autoinserts at the end of the specified BasicBlock. + SwitchInst(Value *Value, BasicBlock *Default, unsigned NumCases, + BasicBlock *InsertAtEnd); +protected: + virtual SwitchInst *clone_impl() const; +public: + static SwitchInst *Create(Value *Value, BasicBlock *Default, + unsigned NumCases, Instruction *InsertBefore = 0) { + return new SwitchInst(Value, Default, NumCases, InsertBefore); + } + static SwitchInst *Create(Value *Value, BasicBlock *Default, + unsigned NumCases, BasicBlock *InsertAtEnd) { + return new SwitchInst(Value, Default, NumCases, InsertAtEnd); + } + ~SwitchInst(); + + /// Provide fast operand accessors + DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); + + // Accessor Methods for Switch stmt + Value *getCondition() const { return getOperand(0); } + void setCondition(Value *V) { setOperand(0, V); } + + BasicBlock *getDefaultDest() const { + return cast(getOperand(1)); + } + + /// getNumCases - return the number of 'cases' in this switch instruction. + /// Note that case #0 is always the default case. + unsigned getNumCases() const { + return getNumOperands()/2; + } + + /// getCaseValue - Return the specified case value. Note that case #0, the + /// default destination, does not have a case value. + ConstantInt *getCaseValue(unsigned i) { + assert(i && i < getNumCases() && "Illegal case value to get!"); + return getSuccessorValue(i); + } + + /// getCaseValue - Return the specified case value. Note that case #0, the + /// default destination, does not have a case value. + const ConstantInt *getCaseValue(unsigned i) const { + assert(i && i < getNumCases() && "Illegal case value to get!"); + return getSuccessorValue(i); + } + + /// findCaseValue - Search all of the case values for the specified constant. + /// If it is explicitly handled, return the case number of it, otherwise + /// return 0 to indicate that it is handled by the default handler. + unsigned findCaseValue(const ConstantInt *C) const { + for (unsigned i = 1, e = getNumCases(); i != e; ++i) + if (getCaseValue(i) == C) + return i; + return 0; + } + + /// findCaseDest - Finds the unique case value for a given successor. Returns + /// null if the successor is not found, not unique, or is the default case. + ConstantInt *findCaseDest(BasicBlock *BB) { + if (BB == getDefaultDest()) return NULL; + + ConstantInt *CI = NULL; + for (unsigned i = 1, e = getNumCases(); i != e; ++i) { + if (getSuccessor(i) == BB) { + if (CI) return NULL; // Multiple cases lead to BB. + else CI = getCaseValue(i); + } + } + return CI; + } + + /// addCase - Add an entry to the switch instruction... + /// + void addCase(ConstantInt *OnVal, BasicBlock *Dest); + + /// removeCase - This method removes the specified successor from the switch + /// instruction. Note that this cannot be used to remove the default + /// destination (successor #0). + /// + void removeCase(unsigned idx); + + unsigned getNumSuccessors() const { return getNumOperands()/2; } + BasicBlock *getSuccessor(unsigned idx) const { + assert(idx < getNumSuccessors() &&"Successor idx out of range for switch!"); + return cast(getOperand(idx*2+1)); + } + void setSuccessor(unsigned idx, BasicBlock *NewSucc) { + assert(idx < getNumSuccessors() && "Successor # out of range for switch!"); + setOperand(idx*2+1, (Value*)NewSucc); + } + + // getSuccessorValue - Return the value associated with the specified + // successor. + ConstantInt *getSuccessorValue(unsigned idx) const { + assert(idx < getNumSuccessors() && "Successor # out of range!"); + return reinterpret_cast(getOperand(idx*2)); + } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const SwitchInst *) { return true; } + static inline bool classof(const Instruction *I) { + return I->getOpcode() == Instruction::Switch; + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } +private: + virtual BasicBlock *getSuccessorV(unsigned idx) const; + virtual unsigned getNumSuccessorsV() const; + virtual void setSuccessorV(unsigned idx, BasicBlock *B); +}; + +template <> +struct OperandTraits : public HungoffOperandTraits<2> { +}; + +DEFINE_TRANSPARENT_OPERAND_ACCESSORS(SwitchInst, Value) + + +//===----------------------------------------------------------------------===// +// IndirectBrInst Class +//===----------------------------------------------------------------------===// + +//===--------------------------------------------------------------------------- +/// IndirectBrInst - Indirect Branch Instruction. +/// +class IndirectBrInst : public TerminatorInst { + void *operator new(size_t, unsigned); // DO NOT IMPLEMENT + unsigned ReservedSpace; + // Operand[0] = Value to switch on + // Operand[1] = Default basic block destination + // Operand[2n ] = Value to match + // Operand[2n+1] = BasicBlock to go to on match + IndirectBrInst(const IndirectBrInst &IBI); + void init(Value *Address, unsigned NumDests); + void resizeOperands(unsigned No); + // allocate space for exactly zero operands + void *operator new(size_t s) { + return User::operator new(s, 0); + } + /// IndirectBrInst ctor - Create a new indirectbr instruction, specifying an + /// Address to jump to. The number of expected destinations can be specified + /// here to make memory allocation more efficient. This constructor can also + /// autoinsert before another instruction. + IndirectBrInst(Value *Address, unsigned NumDests, Instruction *InsertBefore); + + /// IndirectBrInst ctor - Create a new indirectbr instruction, specifying an + /// Address to jump to. The number of expected destinations can be specified + /// here to make memory allocation more efficient. This constructor also + /// autoinserts at the end of the specified BasicBlock. + IndirectBrInst(Value *Address, unsigned NumDests, BasicBlock *InsertAtEnd); +protected: + virtual IndirectBrInst *clone_impl() const; +public: + static IndirectBrInst *Create(Value *Address, unsigned NumDests, + Instruction *InsertBefore = 0) { + return new IndirectBrInst(Address, NumDests, InsertBefore); + } + static IndirectBrInst *Create(Value *Address, unsigned NumDests, + BasicBlock *InsertAtEnd) { + return new IndirectBrInst(Address, NumDests, InsertAtEnd); + } + ~IndirectBrInst(); + + /// Provide fast operand accessors. + DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); + + // Accessor Methods for IndirectBrInst instruction. + Value *getAddress() { return getOperand(0); } + const Value *getAddress() const { return getOperand(0); } + void setAddress(Value *V) { setOperand(0, V); } + + + /// getNumDestinations - return the number of possible destinations in this + /// indirectbr instruction. + unsigned getNumDestinations() const { return getNumOperands()-1; } + + /// getDestination - Return the specified destination. + BasicBlock *getDestination(unsigned i) { return getSuccessor(i); } + const BasicBlock *getDestination(unsigned i) const { return getSuccessor(i); } + + /// addDestination - Add a destination. + /// + void addDestination(BasicBlock *Dest); + + /// removeDestination - This method removes the specified successor from the + /// indirectbr instruction. + void removeDestination(unsigned i); + + unsigned getNumSuccessors() const { return getNumOperands()-1; } + BasicBlock *getSuccessor(unsigned i) const { + return cast(getOperand(i+1)); + } + void setSuccessor(unsigned i, BasicBlock *NewSucc) { + setOperand(i+1, (Value*)NewSucc); + } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const IndirectBrInst *) { return true; } + static inline bool classof(const Instruction *I) { + return I->getOpcode() == Instruction::IndirectBr; + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } +private: + virtual BasicBlock *getSuccessorV(unsigned idx) const; + virtual unsigned getNumSuccessorsV() const; + virtual void setSuccessorV(unsigned idx, BasicBlock *B); +}; + +template <> +struct OperandTraits : public HungoffOperandTraits<1> { +}; + +DEFINE_TRANSPARENT_OPERAND_ACCESSORS(IndirectBrInst, Value) + + +//===----------------------------------------------------------------------===// +// InvokeInst Class +//===----------------------------------------------------------------------===// + +/// InvokeInst - Invoke instruction. The SubclassData field is used to hold the +/// calling convention of the call. +/// +class InvokeInst : public TerminatorInst { + AttrListPtr AttributeList; + InvokeInst(const InvokeInst &BI); + void init(Value *Fn, BasicBlock *IfNormal, BasicBlock *IfException, + Value* const *Args, unsigned NumArgs); + + template + void init(Value *Func, BasicBlock *IfNormal, BasicBlock *IfException, + InputIterator ArgBegin, InputIterator ArgEnd, + const Twine &NameStr, + // This argument ensures that we have an iterator we can + // do arithmetic on in constant time + std::random_access_iterator_tag) { + unsigned NumArgs = (unsigned)std::distance(ArgBegin, ArgEnd); + + // This requires that the iterator points to contiguous memory. + init(Func, IfNormal, IfException, NumArgs ? &*ArgBegin : 0, NumArgs); + setName(NameStr); + } + + /// Construct an InvokeInst given a range of arguments. + /// InputIterator must be a random-access iterator pointing to + /// contiguous storage (e.g. a std::vector<>::iterator). Checks are + /// made for random-accessness but not for contiguous storage as + /// that would incur runtime overhead. + /// + /// @brief Construct an InvokeInst from a range of arguments + template + inline InvokeInst(Value *Func, BasicBlock *IfNormal, BasicBlock *IfException, + InputIterator ArgBegin, InputIterator ArgEnd, + unsigned Values, + const Twine &NameStr, Instruction *InsertBefore); + + /// Construct an InvokeInst given a range of arguments. + /// InputIterator must be a random-access iterator pointing to + /// contiguous storage (e.g. a std::vector<>::iterator). Checks are + /// made for random-accessness but not for contiguous storage as + /// that would incur runtime overhead. + /// + /// @brief Construct an InvokeInst from a range of arguments + template + inline InvokeInst(Value *Func, BasicBlock *IfNormal, BasicBlock *IfException, + InputIterator ArgBegin, InputIterator ArgEnd, + unsigned Values, + const Twine &NameStr, BasicBlock *InsertAtEnd); +protected: + virtual InvokeInst *clone_impl() const; +public: + template + static InvokeInst *Create(Value *Func, + BasicBlock *IfNormal, BasicBlock *IfException, + InputIterator ArgBegin, InputIterator ArgEnd, + const Twine &NameStr = "", + Instruction *InsertBefore = 0) { + unsigned Values(ArgEnd - ArgBegin + 3); + return new(Values) InvokeInst(Func, IfNormal, IfException, ArgBegin, ArgEnd, + Values, NameStr, InsertBefore); + } + template + static InvokeInst *Create(Value *Func, + BasicBlock *IfNormal, BasicBlock *IfException, + InputIterator ArgBegin, InputIterator ArgEnd, + const Twine &NameStr, + BasicBlock *InsertAtEnd) { + unsigned Values(ArgEnd - ArgBegin + 3); + return new(Values) InvokeInst(Func, IfNormal, IfException, ArgBegin, ArgEnd, + Values, NameStr, InsertAtEnd); + } + + /// Provide fast operand accessors + DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); + + /// getCallingConv/setCallingConv - Get or set the calling convention of this + /// function call. + CallingConv::ID getCallingConv() const { + return static_cast(SubclassData); + } + void setCallingConv(CallingConv::ID CC) { + SubclassData = static_cast(CC); + } + + /// getAttributes - Return the parameter attributes for this invoke. + /// + const AttrListPtr &getAttributes() const { return AttributeList; } + + /// setAttributes - Set the parameter attributes for this invoke. + /// + void setAttributes(const AttrListPtr &Attrs) { AttributeList = Attrs; } + + /// addAttribute - adds the attribute to the list of attributes. + void addAttribute(unsigned i, Attributes attr); + + /// removeAttribute - removes the attribute from the list of attributes. + void removeAttribute(unsigned i, Attributes attr); + + /// @brief Determine whether the call or the callee has the given attribute. + bool paramHasAttr(unsigned i, Attributes attr) const; + + /// @brief Extract the alignment for a call or parameter (0=unknown). + unsigned getParamAlignment(unsigned i) const { + return AttributeList.getParamAlignment(i); + } + + /// @brief Determine if the call does not access memory. + bool doesNotAccessMemory() const { + return paramHasAttr(~0, Attribute::ReadNone); + } + void setDoesNotAccessMemory(bool NotAccessMemory = true) { + if (NotAccessMemory) addAttribute(~0, Attribute::ReadNone); + else removeAttribute(~0, Attribute::ReadNone); + } + + /// @brief Determine if the call does not access or only reads memory. + bool onlyReadsMemory() const { + return doesNotAccessMemory() || paramHasAttr(~0, Attribute::ReadOnly); + } + void setOnlyReadsMemory(bool OnlyReadsMemory = true) { + if (OnlyReadsMemory) addAttribute(~0, Attribute::ReadOnly); + else removeAttribute(~0, Attribute::ReadOnly | Attribute::ReadNone); + } + + /// @brief Determine if the call cannot return. + bool doesNotReturn() const { + return paramHasAttr(~0, Attribute::NoReturn); + } + void setDoesNotReturn(bool DoesNotReturn = true) { + if (DoesNotReturn) addAttribute(~0, Attribute::NoReturn); + else removeAttribute(~0, Attribute::NoReturn); + } + + /// @brief Determine if the call cannot unwind. + bool doesNotThrow() const { + return paramHasAttr(~0, Attribute::NoUnwind); + } + void setDoesNotThrow(bool DoesNotThrow = true) { + if (DoesNotThrow) addAttribute(~0, Attribute::NoUnwind); + else removeAttribute(~0, Attribute::NoUnwind); + } + + /// @brief Determine if the call returns a structure through first + /// pointer argument. + bool hasStructRetAttr() const { + // Be friendly and also check the callee. + return paramHasAttr(1, Attribute::StructRet); + } + + /// @brief Determine if any call argument is an aggregate passed by value. + bool hasByValArgument() const { + return AttributeList.hasAttrSomewhere(Attribute::ByVal); + } + + /// getCalledFunction - Return the function called, or null if this is an + /// indirect function invocation. + /// + Function *getCalledFunction() const { + return dyn_cast(getOperand(0)); + } + + /// getCalledValue - Get a pointer to the function that is invoked by this + /// instruction + const Value *getCalledValue() const { return getOperand(0); } + Value *getCalledValue() { return getOperand(0); } + + // get*Dest - Return the destination basic blocks... + BasicBlock *getNormalDest() const { + return cast(getOperand(1)); + } + BasicBlock *getUnwindDest() const { + return cast(getOperand(2)); + } + void setNormalDest(BasicBlock *B) { + setOperand(1, (Value*)B); + } + + void setUnwindDest(BasicBlock *B) { + setOperand(2, (Value*)B); + } + + BasicBlock *getSuccessor(unsigned i) const { + assert(i < 2 && "Successor # out of range for invoke!"); + return i == 0 ? getNormalDest() : getUnwindDest(); + } + + void setSuccessor(unsigned idx, BasicBlock *NewSucc) { + assert(idx < 2 && "Successor # out of range for invoke!"); + setOperand(idx+1, (Value*)NewSucc); + } + + unsigned getNumSuccessors() const { return 2; } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const InvokeInst *) { return true; } + static inline bool classof(const Instruction *I) { + return (I->getOpcode() == Instruction::Invoke); + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } +private: + virtual BasicBlock *getSuccessorV(unsigned idx) const; + virtual unsigned getNumSuccessorsV() const; + virtual void setSuccessorV(unsigned idx, BasicBlock *B); +}; + +template <> +struct OperandTraits : public VariadicOperandTraits<3> { +}; + +template +InvokeInst::InvokeInst(Value *Func, + BasicBlock *IfNormal, BasicBlock *IfException, + InputIterator ArgBegin, InputIterator ArgEnd, + unsigned Values, + const Twine &NameStr, Instruction *InsertBefore) + : TerminatorInst(cast(cast(Func->getType()) + ->getElementType())->getReturnType(), + Instruction::Invoke, + OperandTraits::op_end(this) - Values, + Values, InsertBefore) { + init(Func, IfNormal, IfException, ArgBegin, ArgEnd, NameStr, + typename std::iterator_traits::iterator_category()); +} +template +InvokeInst::InvokeInst(Value *Func, + BasicBlock *IfNormal, BasicBlock *IfException, + InputIterator ArgBegin, InputIterator ArgEnd, + unsigned Values, + const Twine &NameStr, BasicBlock *InsertAtEnd) + : TerminatorInst(cast(cast(Func->getType()) + ->getElementType())->getReturnType(), + Instruction::Invoke, + OperandTraits::op_end(this) - Values, + Values, InsertAtEnd) { + init(Func, IfNormal, IfException, ArgBegin, ArgEnd, NameStr, + typename std::iterator_traits::iterator_category()); +} + +DEFINE_TRANSPARENT_OPERAND_ACCESSORS(InvokeInst, Value) + +//===----------------------------------------------------------------------===// +// UnwindInst Class +//===----------------------------------------------------------------------===// + +//===--------------------------------------------------------------------------- +/// UnwindInst - Immediately exit the current function, unwinding the stack +/// until an invoke instruction is found. +/// +class UnwindInst : public TerminatorInst { + void *operator new(size_t, unsigned); // DO NOT IMPLEMENT +protected: + virtual UnwindInst *clone_impl() const; +public: + // allocate space for exactly zero operands + void *operator new(size_t s) { + return User::operator new(s, 0); + } + explicit UnwindInst(LLVMContext &C, Instruction *InsertBefore = 0); + explicit UnwindInst(LLVMContext &C, BasicBlock *InsertAtEnd); + + unsigned getNumSuccessors() const { return 0; } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const UnwindInst *) { return true; } + static inline bool classof(const Instruction *I) { + return I->getOpcode() == Instruction::Unwind; + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } +private: + virtual BasicBlock *getSuccessorV(unsigned idx) const; + virtual unsigned getNumSuccessorsV() const; + virtual void setSuccessorV(unsigned idx, BasicBlock *B); +}; + +//===----------------------------------------------------------------------===// +// UnreachableInst Class +//===----------------------------------------------------------------------===// + +//===--------------------------------------------------------------------------- +/// UnreachableInst - This function has undefined behavior. In particular, the +/// presence of this instruction indicates some higher level knowledge that the +/// end of the block cannot be reached. +/// +class UnreachableInst : public TerminatorInst { + void *operator new(size_t, unsigned); // DO NOT IMPLEMENT +protected: + virtual UnreachableInst *clone_impl() const; + +public: + // allocate space for exactly zero operands + void *operator new(size_t s) { + return User::operator new(s, 0); + } + explicit UnreachableInst(LLVMContext &C, Instruction *InsertBefore = 0); + explicit UnreachableInst(LLVMContext &C, BasicBlock *InsertAtEnd); + + unsigned getNumSuccessors() const { return 0; } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const UnreachableInst *) { return true; } + static inline bool classof(const Instruction *I) { + return I->getOpcode() == Instruction::Unreachable; + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } +private: + virtual BasicBlock *getSuccessorV(unsigned idx) const; + virtual unsigned getNumSuccessorsV() const; + virtual void setSuccessorV(unsigned idx, BasicBlock *B); +}; + +//===----------------------------------------------------------------------===// +// TruncInst Class +//===----------------------------------------------------------------------===// + +/// @brief This class represents a truncation of integer types. +class TruncInst : public CastInst { +protected: + /// @brief Clone an identical TruncInst + virtual TruncInst *clone_impl() const; + +public: + /// @brief Constructor with insert-before-instruction semantics + TruncInst( + Value *S, ///< The value to be truncated + const Type *Ty, ///< The (smaller) type to truncate to + const Twine &NameStr = "", ///< A name for the new instruction + Instruction *InsertBefore = 0 ///< Where to insert the new instruction + ); + + /// @brief Constructor with insert-at-end-of-block semantics + TruncInst( + Value *S, ///< The value to be truncated + const Type *Ty, ///< The (smaller) type to truncate to + const Twine &NameStr, ///< A name for the new instruction + BasicBlock *InsertAtEnd ///< The block to insert the instruction into + ); + + /// @brief Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const TruncInst *) { return true; } + static inline bool classof(const Instruction *I) { + return I->getOpcode() == Trunc; + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } +}; + +//===----------------------------------------------------------------------===// +// ZExtInst Class +//===----------------------------------------------------------------------===// + +/// @brief This class represents zero extension of integer types. +class ZExtInst : public CastInst { +protected: + /// @brief Clone an identical ZExtInst + virtual ZExtInst *clone_impl() const; + +public: + /// @brief Constructor with insert-before-instruction semantics + ZExtInst( + Value *S, ///< The value to be zero extended + const Type *Ty, ///< The type to zero extend to + const Twine &NameStr = "", ///< A name for the new instruction + Instruction *InsertBefore = 0 ///< Where to insert the new instruction + ); + + /// @brief Constructor with insert-at-end semantics. + ZExtInst( + Value *S, ///< The value to be zero extended + const Type *Ty, ///< The type to zero extend to + const Twine &NameStr, ///< A name for the new instruction + BasicBlock *InsertAtEnd ///< The block to insert the instruction into + ); + + /// @brief Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const ZExtInst *) { return true; } + static inline bool classof(const Instruction *I) { + return I->getOpcode() == ZExt; + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } +}; + +//===----------------------------------------------------------------------===// +// SExtInst Class +//===----------------------------------------------------------------------===// + +/// @brief This class represents a sign extension of integer types. +class SExtInst : public CastInst { +protected: + /// @brief Clone an identical SExtInst + virtual SExtInst *clone_impl() const; + +public: + /// @brief Constructor with insert-before-instruction semantics + SExtInst( + Value *S, ///< The value to be sign extended + const Type *Ty, ///< The type to sign extend to + const Twine &NameStr = "", ///< A name for the new instruction + Instruction *InsertBefore = 0 ///< Where to insert the new instruction + ); + + /// @brief Constructor with insert-at-end-of-block semantics + SExtInst( + Value *S, ///< The value to be sign extended + const Type *Ty, ///< The type to sign extend to + const Twine &NameStr, ///< A name for the new instruction + BasicBlock *InsertAtEnd ///< The block to insert the instruction into + ); + + /// @brief Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const SExtInst *) { return true; } + static inline bool classof(const Instruction *I) { + return I->getOpcode() == SExt; + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } +}; + +//===----------------------------------------------------------------------===// +// FPTruncInst Class +//===----------------------------------------------------------------------===// + +/// @brief This class represents a truncation of floating point types. +class FPTruncInst : public CastInst { +protected: + /// @brief Clone an identical FPTruncInst + virtual FPTruncInst *clone_impl() const; + +public: + /// @brief Constructor with insert-before-instruction semantics + FPTruncInst( + Value *S, ///< The value to be truncated + const Type *Ty, ///< The type to truncate to + const Twine &NameStr = "", ///< A name for the new instruction + Instruction *InsertBefore = 0 ///< Where to insert the new instruction + ); + + /// @brief Constructor with insert-before-instruction semantics + FPTruncInst( + Value *S, ///< The value to be truncated + const Type *Ty, ///< The type to truncate to + const Twine &NameStr, ///< A name for the new instruction + BasicBlock *InsertAtEnd ///< The block to insert the instruction into + ); + + /// @brief Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const FPTruncInst *) { return true; } + static inline bool classof(const Instruction *I) { + return I->getOpcode() == FPTrunc; + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } +}; + +//===----------------------------------------------------------------------===// +// FPExtInst Class +//===----------------------------------------------------------------------===// + +/// @brief This class represents an extension of floating point types. +class FPExtInst : public CastInst { +protected: + /// @brief Clone an identical FPExtInst + virtual FPExtInst *clone_impl() const; + +public: + /// @brief Constructor with insert-before-instruction semantics + FPExtInst( + Value *S, ///< The value to be extended + const Type *Ty, ///< The type to extend to + const Twine &NameStr = "", ///< A name for the new instruction + Instruction *InsertBefore = 0 ///< Where to insert the new instruction + ); + + /// @brief Constructor with insert-at-end-of-block semantics + FPExtInst( + Value *S, ///< The value to be extended + const Type *Ty, ///< The type to extend to + const Twine &NameStr, ///< A name for the new instruction + BasicBlock *InsertAtEnd ///< The block to insert the instruction into + ); + + /// @brief Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const FPExtInst *) { return true; } + static inline bool classof(const Instruction *I) { + return I->getOpcode() == FPExt; + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } +}; + +//===----------------------------------------------------------------------===// +// UIToFPInst Class +//===----------------------------------------------------------------------===// + +/// @brief This class represents a cast unsigned integer to floating point. +class UIToFPInst : public CastInst { +protected: + /// @brief Clone an identical UIToFPInst + virtual UIToFPInst *clone_impl() const; + +public: + /// @brief Constructor with insert-before-instruction semantics + UIToFPInst( + Value *S, ///< The value to be converted + const Type *Ty, ///< The type to convert to + const Twine &NameStr = "", ///< A name for the new instruction + Instruction *InsertBefore = 0 ///< Where to insert the new instruction + ); + + /// @brief Constructor with insert-at-end-of-block semantics + UIToFPInst( + Value *S, ///< The value to be converted + const Type *Ty, ///< The type to convert to + const Twine &NameStr, ///< A name for the new instruction + BasicBlock *InsertAtEnd ///< The block to insert the instruction into + ); + + /// @brief Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const UIToFPInst *) { return true; } + static inline bool classof(const Instruction *I) { + return I->getOpcode() == UIToFP; + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } +}; + +//===----------------------------------------------------------------------===// +// SIToFPInst Class +//===----------------------------------------------------------------------===// + +/// @brief This class represents a cast from signed integer to floating point. +class SIToFPInst : public CastInst { +protected: + /// @brief Clone an identical SIToFPInst + virtual SIToFPInst *clone_impl() const; + +public: + /// @brief Constructor with insert-before-instruction semantics + SIToFPInst( + Value *S, ///< The value to be converted + const Type *Ty, ///< The type to convert to + const Twine &NameStr = "", ///< A name for the new instruction + Instruction *InsertBefore = 0 ///< Where to insert the new instruction + ); + + /// @brief Constructor with insert-at-end-of-block semantics + SIToFPInst( + Value *S, ///< The value to be converted + const Type *Ty, ///< The type to convert to + const Twine &NameStr, ///< A name for the new instruction + BasicBlock *InsertAtEnd ///< The block to insert the instruction into + ); + + /// @brief Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const SIToFPInst *) { return true; } + static inline bool classof(const Instruction *I) { + return I->getOpcode() == SIToFP; + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } +}; + +//===----------------------------------------------------------------------===// +// FPToUIInst Class +//===----------------------------------------------------------------------===// + +/// @brief This class represents a cast from floating point to unsigned integer +class FPToUIInst : public CastInst { +protected: + /// @brief Clone an identical FPToUIInst + virtual FPToUIInst *clone_impl() const; + +public: + /// @brief Constructor with insert-before-instruction semantics + FPToUIInst( + Value *S, ///< The value to be converted + const Type *Ty, ///< The type to convert to + const Twine &NameStr = "", ///< A name for the new instruction + Instruction *InsertBefore = 0 ///< Where to insert the new instruction + ); + + /// @brief Constructor with insert-at-end-of-block semantics + FPToUIInst( + Value *S, ///< The value to be converted + const Type *Ty, ///< The type to convert to + const Twine &NameStr, ///< A name for the new instruction + BasicBlock *InsertAtEnd ///< Where to insert the new instruction + ); + + /// @brief Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const FPToUIInst *) { return true; } + static inline bool classof(const Instruction *I) { + return I->getOpcode() == FPToUI; + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } +}; + +//===----------------------------------------------------------------------===// +// FPToSIInst Class +//===----------------------------------------------------------------------===// + +/// @brief This class represents a cast from floating point to signed integer. +class FPToSIInst : public CastInst { +protected: + /// @brief Clone an identical FPToSIInst + virtual FPToSIInst *clone_impl() const; + +public: + /// @brief Constructor with insert-before-instruction semantics + FPToSIInst( + Value *S, ///< The value to be converted + const Type *Ty, ///< The type to convert to + const Twine &NameStr = "", ///< A name for the new instruction + Instruction *InsertBefore = 0 ///< Where to insert the new instruction + ); + + /// @brief Constructor with insert-at-end-of-block semantics + FPToSIInst( + Value *S, ///< The value to be converted + const Type *Ty, ///< The type to convert to + const Twine &NameStr, ///< A name for the new instruction + BasicBlock *InsertAtEnd ///< The block to insert the instruction into + ); + + /// @brief Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const FPToSIInst *) { return true; } + static inline bool classof(const Instruction *I) { + return I->getOpcode() == FPToSI; + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } +}; + +//===----------------------------------------------------------------------===// +// IntToPtrInst Class +//===----------------------------------------------------------------------===// + +/// @brief This class represents a cast from an integer to a pointer. +class IntToPtrInst : public CastInst { +public: + /// @brief Constructor with insert-before-instruction semantics + IntToPtrInst( + Value *S, ///< The value to be converted + const Type *Ty, ///< The type to convert to + const Twine &NameStr = "", ///< A name for the new instruction + Instruction *InsertBefore = 0 ///< Where to insert the new instruction + ); + + /// @brief Constructor with insert-at-end-of-block semantics + IntToPtrInst( + Value *S, ///< The value to be converted + const Type *Ty, ///< The type to convert to + const Twine &NameStr, ///< A name for the new instruction + BasicBlock *InsertAtEnd ///< The block to insert the instruction into + ); + + /// @brief Clone an identical IntToPtrInst + virtual IntToPtrInst *clone_impl() const; + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const IntToPtrInst *) { return true; } + static inline bool classof(const Instruction *I) { + return I->getOpcode() == IntToPtr; + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } +}; + +//===----------------------------------------------------------------------===// +// PtrToIntInst Class +//===----------------------------------------------------------------------===// + +/// @brief This class represents a cast from a pointer to an integer +class PtrToIntInst : public CastInst { +protected: + /// @brief Clone an identical PtrToIntInst + virtual PtrToIntInst *clone_impl() const; + +public: + /// @brief Constructor with insert-before-instruction semantics + PtrToIntInst( + Value *S, ///< The value to be converted + const Type *Ty, ///< The type to convert to + const Twine &NameStr = "", ///< A name for the new instruction + Instruction *InsertBefore = 0 ///< Where to insert the new instruction + ); + + /// @brief Constructor with insert-at-end-of-block semantics + PtrToIntInst( + Value *S, ///< The value to be converted + const Type *Ty, ///< The type to convert to + const Twine &NameStr, ///< A name for the new instruction + BasicBlock *InsertAtEnd ///< The block to insert the instruction into + ); + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const PtrToIntInst *) { return true; } + static inline bool classof(const Instruction *I) { + return I->getOpcode() == PtrToInt; + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } +}; + +//===----------------------------------------------------------------------===// +// BitCastInst Class +//===----------------------------------------------------------------------===// + +/// @brief This class represents a no-op cast from one type to another. +class BitCastInst : public CastInst { +protected: + /// @brief Clone an identical BitCastInst + virtual BitCastInst *clone_impl() const; + +public: + /// @brief Constructor with insert-before-instruction semantics + BitCastInst( + Value *S, ///< The value to be casted + const Type *Ty, ///< The type to casted to + const Twine &NameStr = "", ///< A name for the new instruction + Instruction *InsertBefore = 0 ///< Where to insert the new instruction + ); + + /// @brief Constructor with insert-at-end-of-block semantics + BitCastInst( + Value *S, ///< The value to be casted + const Type *Ty, ///< The type to casted to + const Twine &NameStr, ///< A name for the new instruction + BasicBlock *InsertAtEnd ///< The block to insert the instruction into + ); + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const BitCastInst *) { return true; } + static inline bool classof(const Instruction *I) { + return I->getOpcode() == BitCast; + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } +}; + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/IntrinsicInst.h b/libclamav/c++/llvm/include/llvm/IntrinsicInst.h new file mode 100644 index 000000000..1e1dca2eb --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/IntrinsicInst.h @@ -0,0 +1,347 @@ +//===-- llvm/IntrinsicInst.h - Intrinsic Instruction Wrappers ---*- 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 classes that make it really easy to deal with intrinsic +// functions with the isa/dyncast family of functions. In particular, this +// allows you to do things like: +// +// if (MemCpyInst *MCI = dyn_cast(Inst)) +// ... MCI->getDest() ... MCI->getSource() ... +// +// All intrinsic function calls are instances of the call instruction, so these +// are all subclasses of the CallInst class. Note that none of these classes +// has state or virtual methods, which is an important part of this gross/neat +// hack working. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_INTRINSICINST_H +#define LLVM_INTRINSICINST_H + +#include "llvm/Constants.h" +#include "llvm/Metadata.h" +#include "llvm/Function.h" +#include "llvm/Instructions.h" +#include "llvm/Intrinsics.h" + +namespace llvm { + /// IntrinsicInst - A useful wrapper class for inspecting calls to intrinsic + /// functions. This allows the standard isa/dyncast/cast functionality to + /// work with calls to intrinsic functions. + class IntrinsicInst : public CallInst { + IntrinsicInst(); // DO NOT IMPLEMENT + IntrinsicInst(const IntrinsicInst&); // DO NOT IMPLEMENT + void operator=(const IntrinsicInst&); // DO NOT IMPLEMENT + public: + /// getIntrinsicID - Return the intrinsic ID of this intrinsic. + /// + Intrinsic::ID getIntrinsicID() const { + return (Intrinsic::ID)getCalledFunction()->getIntrinsicID(); + } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const IntrinsicInst *) { return true; } + static inline bool classof(const CallInst *I) { + if (const Function *CF = I->getCalledFunction()) + return CF->getIntrinsicID() != 0; + return false; + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } + }; + + /// DbgInfoIntrinsic - This is the common base class for debug info intrinsics + /// + struct DbgInfoIntrinsic : public IntrinsicInst { + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const DbgInfoIntrinsic *) { return true; } + static inline bool classof(const IntrinsicInst *I) { + switch (I->getIntrinsicID()) { + case Intrinsic::dbg_stoppoint: + case Intrinsic::dbg_func_start: + case Intrinsic::dbg_region_start: + case Intrinsic::dbg_region_end: + case Intrinsic::dbg_declare: + return true; + default: return false; + } + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } + + static Value *StripCast(Value *C); + }; + + /// DbgStopPointInst - This represents the llvm.dbg.stoppoint instruction. + /// + struct DbgStopPointInst : public DbgInfoIntrinsic { + Value *getLineValue() const { return const_cast(getOperand(1)); } + Value *getColumnValue() const { return const_cast(getOperand(2)); } + MDNode *getContext() const { + return cast(getOperand(3)); + } + + unsigned getLine() const { + return unsigned(cast(getOperand(1))->getZExtValue()); + } + unsigned getColumn() const { + return unsigned(cast(getOperand(2))->getZExtValue()); + } + + Value* getFileName() const; + Value* getDirectory() const; + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const DbgStopPointInst *) { return true; } + static inline bool classof(const IntrinsicInst *I) { + return I->getIntrinsicID() == Intrinsic::dbg_stoppoint; + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } + }; + + /// DbgFuncStartInst - This represents the llvm.dbg.func.start instruction. + /// + struct DbgFuncStartInst : public DbgInfoIntrinsic { + MDNode *getSubprogram() const { return cast(getOperand(1)); } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const DbgFuncStartInst *) { return true; } + static inline bool classof(const IntrinsicInst *I) { + return I->getIntrinsicID() == Intrinsic::dbg_func_start; + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } + }; + + /// DbgRegionStartInst - This represents the llvm.dbg.region.start + /// instruction. + struct DbgRegionStartInst : public DbgInfoIntrinsic { + MDNode *getContext() const { return cast(getOperand(1)); } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const DbgRegionStartInst *) { return true; } + static inline bool classof(const IntrinsicInst *I) { + return I->getIntrinsicID() == Intrinsic::dbg_region_start; + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } + }; + + /// DbgRegionEndInst - This represents the llvm.dbg.region.end instruction. + /// + struct DbgRegionEndInst : public DbgInfoIntrinsic { + MDNode *getContext() const { return cast(getOperand(1)); } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const DbgRegionEndInst *) { return true; } + static inline bool classof(const IntrinsicInst *I) { + return I->getIntrinsicID() == Intrinsic::dbg_region_end; + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } + }; + + /// DbgDeclareInst - This represents the llvm.dbg.declare instruction. + /// + struct DbgDeclareInst : public DbgInfoIntrinsic { + Value *getAddress() const { return getOperand(1); } + MDNode *getVariable() const { return cast(getOperand(2)); } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const DbgDeclareInst *) { return true; } + static inline bool classof(const IntrinsicInst *I) { + return I->getIntrinsicID() == Intrinsic::dbg_declare; + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } + }; + + /// MemIntrinsic - This is the common base class for memset/memcpy/memmove. + /// + struct MemIntrinsic : public IntrinsicInst { + Value *getRawDest() const { return const_cast(getOperand(1)); } + + Value *getLength() const { return const_cast(getOperand(3)); } + ConstantInt *getAlignmentCst() const { + return cast(const_cast(getOperand(4))); + } + + unsigned getAlignment() const { + return getAlignmentCst()->getZExtValue(); + } + + /// getDest - This is just like getRawDest, but it strips off any cast + /// instructions that feed it, giving the original input. The returned + /// value is guaranteed to be a pointer. + Value *getDest() const { return getRawDest()->stripPointerCasts(); } + + /// set* - Set the specified arguments of the instruction. + /// + void setDest(Value *Ptr) { + assert(getRawDest()->getType() == Ptr->getType() && + "setDest called with pointer of wrong type!"); + setOperand(1, Ptr); + } + + void setLength(Value *L) { + assert(getLength()->getType() == L->getType() && + "setLength called with value of wrong type!"); + setOperand(3, L); + } + + void setAlignment(Constant* A) { + setOperand(4, A); + } + + const Type *getAlignmentType() const { + return getOperand(4)->getType(); + } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const MemIntrinsic *) { return true; } + static inline bool classof(const IntrinsicInst *I) { + switch (I->getIntrinsicID()) { + case Intrinsic::memcpy: + case Intrinsic::memmove: + case Intrinsic::memset: + return true; + default: return false; + } + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } + }; + + /// MemSetInst - This class wraps the llvm.memset intrinsic. + /// + struct MemSetInst : public MemIntrinsic { + /// get* - Return the arguments to the instruction. + /// + Value *getValue() const { return const_cast(getOperand(2)); } + + void setValue(Value *Val) { + assert(getValue()->getType() == Val->getType() && + "setSource called with pointer of wrong type!"); + setOperand(2, Val); + } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const MemSetInst *) { return true; } + static inline bool classof(const IntrinsicInst *I) { + return I->getIntrinsicID() == Intrinsic::memset; + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } + }; + + /// MemTransferInst - This class wraps the llvm.memcpy/memmove intrinsics. + /// + struct MemTransferInst : public MemIntrinsic { + /// get* - Return the arguments to the instruction. + /// + Value *getRawSource() const { return const_cast(getOperand(2)); } + + /// getSource - This is just like getRawSource, but it strips off any cast + /// instructions that feed it, giving the original input. The returned + /// value is guaranteed to be a pointer. + Value *getSource() const { return getRawSource()->stripPointerCasts(); } + + void setSource(Value *Ptr) { + assert(getRawSource()->getType() == Ptr->getType() && + "setSource called with pointer of wrong type!"); + setOperand(2, Ptr); + } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const MemTransferInst *) { return true; } + static inline bool classof(const IntrinsicInst *I) { + return I->getIntrinsicID() == Intrinsic::memcpy || + I->getIntrinsicID() == Intrinsic::memmove; + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } + }; + + + /// MemCpyInst - This class wraps the llvm.memcpy intrinsic. + /// + struct MemCpyInst : public MemTransferInst { + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const MemCpyInst *) { return true; } + static inline bool classof(const IntrinsicInst *I) { + return I->getIntrinsicID() == Intrinsic::memcpy; + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } + }; + + /// MemMoveInst - This class wraps the llvm.memmove intrinsic. + /// + struct MemMoveInst : public MemTransferInst { + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const MemMoveInst *) { return true; } + static inline bool classof(const IntrinsicInst *I) { + return I->getIntrinsicID() == Intrinsic::memmove; + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } + }; + + /// EHSelectorInst - This represents the llvm.eh.selector instruction. + /// + struct EHSelectorInst : public IntrinsicInst { + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const EHSelectorInst *) { return true; } + static inline bool classof(const IntrinsicInst *I) { + return I->getIntrinsicID() == Intrinsic::eh_selector; + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } + }; + + /// MemoryUseIntrinsic - This is the common base class for the memory use + /// marker intrinsics. + /// + struct MemoryUseIntrinsic : public IntrinsicInst { + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const MemoryUseIntrinsic *) { return true; } + static inline bool classof(const IntrinsicInst *I) { + switch (I->getIntrinsicID()) { + case Intrinsic::lifetime_start: + case Intrinsic::lifetime_end: + case Intrinsic::invariant_start: + case Intrinsic::invariant_end: + return true; + default: return false; + } + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } + }; + +} + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Intrinsics.h b/libclamav/c++/llvm/include/llvm/Intrinsics.h new file mode 100644 index 000000000..8f1b1aee1 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Intrinsics.h @@ -0,0 +1,80 @@ +//===-- llvm/Instrinsics.h - LLVM Intrinsic Function Handling ---*- 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 a set of enums which allow processing of intrinsic +// functions. Values of these enum types are returned by +// Function::getIntrinsicID. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_INTRINSICS_H +#define LLVM_INTRINSICS_H + +#include + +namespace llvm { + +class Type; +class FunctionType; +class Function; +class LLVMContext; +class Module; +class AttrListPtr; + +/// Intrinsic Namespace - This namespace contains an enum with a value for +/// every intrinsic/builtin function known by LLVM. These enum values are +/// returned by Function::getIntrinsicID(). +/// +namespace Intrinsic { + enum ID { + not_intrinsic = 0, // Must be zero + + // Get the intrinsic enums generated from Intrinsics.td +#define GET_INTRINSIC_ENUM_VALUES +#include "llvm/Intrinsics.gen" +#undef GET_INTRINSIC_ENUM_VALUES + , num_intrinsics + }; + + /// Intrinsic::getName(ID) - Return the LLVM name for an intrinsic, such as + /// "llvm.ppc.altivec.lvx". + std::string getName(ID id, const Type **Tys = 0, unsigned numTys = 0); + + /// Intrinsic::getType(ID) - Return the function type for an intrinsic. + /// + const FunctionType *getType(LLVMContext &Context, ID id, + const Type **Tys = 0, unsigned numTys = 0); + + /// Intrinsic::isOverloaded(ID) - Returns true if the intrinsic can be + /// overloaded. + bool isOverloaded(ID id); + + /// Intrinsic::getAttributes(ID) - Return the attributes for an intrinsic. + /// + AttrListPtr getAttributes(ID id); + + /// Intrinsic::getDeclaration(M, ID) - Create or insert an LLVM Function + /// declaration for an intrinsic, and return it. + /// + /// The Tys and numTys parameters are for intrinsics with overloaded types + /// (e.g., those using iAny or fAny). For a declaration for an overloaded + /// intrinsic, Tys should point to an array of numTys pointers to Type, + /// and must provide exactly one type for each overloaded type in the + /// intrinsic. + Function *getDeclaration(Module *M, ID id, const Type **Tys = 0, + unsigned numTys = 0); + + /// Map a GCC builtin name to an intrinsic ID. + ID getIntrinsicForGCCBuiltin(const char *Prefix, const char *BuiltinName); + +} // End Intrinsic namespace + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Intrinsics.td b/libclamav/c++/llvm/include/llvm/Intrinsics.td new file mode 100644 index 000000000..c0cf00e8e --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Intrinsics.td @@ -0,0 +1,481 @@ +//===- Intrinsics.td - Defines all LLVM intrinsics ---------*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines properties of all LLVM intrinsics. +// +//===----------------------------------------------------------------------===// + +include "llvm/CodeGen/ValueTypes.td" + +//===----------------------------------------------------------------------===// +// Properties we keep track of for intrinsics. +//===----------------------------------------------------------------------===// + +class IntrinsicProperty; + +// Intr*Mem - Memory properties. An intrinsic is allowed to have exactly one of +// these properties set. They are listed from the most aggressive (best to use +// if correct) to the least aggressive. If no property is set, the worst case +// is assumed (IntrWriteMem). + +// IntrNoMem - The intrinsic does not access memory or have any other side +// effects. It may be CSE'd deleted if dead, etc. +def IntrNoMem : IntrinsicProperty; + +// IntrReadArgMem - This intrinsic reads only from memory that one of its +// arguments points to, but may read an unspecified amount. +def IntrReadArgMem : IntrinsicProperty; + +// IntrReadMem - This intrinsic reads from unspecified memory, so it cannot be +// moved across stores. However, it can be reordered otherwise and can be +// deleted if dead. +def IntrReadMem : IntrinsicProperty; + +// IntrWriteArgMem - This intrinsic reads and writes only from memory that one +// of its arguments points to, but may access an unspecified amount. The reads +// and writes may be volatile, but except for this it has no other side effects. +def IntrWriteArgMem : IntrinsicProperty; + +// IntrWriteMem - This intrinsic may read or modify unspecified memory or has +// other side effects. It cannot be modified by the optimizer. This is the +// default if the intrinsic has no other Intr*Mem property. +def IntrWriteMem : IntrinsicProperty; + +// Commutative - This intrinsic is commutative: X op Y == Y op X. +def Commutative : IntrinsicProperty; + +// NoCapture - The specified argument pointer is not captured by the intrinsic. +class NoCapture : IntrinsicProperty { + int ArgNo = argNo; +} + +//===----------------------------------------------------------------------===// +// Types used by intrinsics. +//===----------------------------------------------------------------------===// + +class LLVMType { + ValueType VT = vt; +} + +class LLVMPointerType + : LLVMType{ + LLVMType ElTy = elty; +} + +class LLVMAnyPointerType + : LLVMType{ + LLVMType ElTy = elty; +} + +// Match the type of another intrinsic parameter. Number is an index into the +// list of overloaded types for the intrinsic, excluding all the fixed types. +// The Number value must refer to a previously listed type. For example: +// Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_anyfloat_ty, LLVMMatchType<0>]> +// has two overloaded types, the 2nd and 3rd arguments. LLVMMatchType<0> +// refers to the first overloaded type, which is the 2nd argument. +class LLVMMatchType + : LLVMType{ + int Number = num; +} + +// Match the type of another intrinsic parameter that is expected to be +// an integral vector type, but change the element size to be twice as wide +// or half as wide as the other type. This is only useful when the intrinsic +// is overloaded, so the matched type should be declared as iAny. +class LLVMExtendedElementVectorType : LLVMMatchType; +class LLVMTruncatedElementVectorType : LLVMMatchType; + +def llvm_void_ty : LLVMType; +def llvm_anyint_ty : LLVMType; +def llvm_anyfloat_ty : LLVMType; +def llvm_anyvector_ty : LLVMType; +def llvm_i1_ty : LLVMType; +def llvm_i8_ty : LLVMType; +def llvm_i16_ty : LLVMType; +def llvm_i32_ty : LLVMType; +def llvm_i64_ty : LLVMType; +def llvm_float_ty : LLVMType; +def llvm_double_ty : LLVMType; +def llvm_f80_ty : LLVMType; +def llvm_f128_ty : LLVMType; +def llvm_ppcf128_ty : LLVMType; +def llvm_ptr_ty : LLVMPointerType; // i8* +def llvm_ptrptr_ty : LLVMPointerType; // i8** +def llvm_anyptr_ty : LLVMAnyPointerType; // (space)i8* +def llvm_empty_ty : LLVMType; // { } +def llvm_descriptor_ty : LLVMPointerType; // { }* +def llvm_metadata_ty : LLVMType; // !{...} + +def llvm_v2i8_ty : LLVMType; // 2 x i8 +def llvm_v4i8_ty : LLVMType; // 4 x i8 +def llvm_v8i8_ty : LLVMType; // 8 x i8 +def llvm_v16i8_ty : LLVMType; // 16 x i8 +def llvm_v32i8_ty : LLVMType; // 32 x i8 +def llvm_v2i16_ty : LLVMType; // 4 x i16 +def llvm_v4i16_ty : LLVMType; // 4 x i16 +def llvm_v8i16_ty : LLVMType; // 8 x i16 +def llvm_v16i16_ty : LLVMType; // 16 x i16 +def llvm_v2i32_ty : LLVMType; // 2 x i32 +def llvm_v4i32_ty : LLVMType; // 4 x i32 +def llvm_v8i32_ty : LLVMType; // 8 x i32 +def llvm_v1i64_ty : LLVMType; // 1 x i64 +def llvm_v2i64_ty : LLVMType; // 2 x i64 +def llvm_v4i64_ty : LLVMType; // 4 x i64 + +def llvm_v2f32_ty : LLVMType; // 2 x float +def llvm_v4f32_ty : LLVMType; // 4 x float +def llvm_v8f32_ty : LLVMType; // 8 x float +def llvm_v2f64_ty : LLVMType; // 2 x double +def llvm_v4f64_ty : LLVMType; // 4 x double + +def llvm_vararg_ty : LLVMType; // this means vararg here + + +//===----------------------------------------------------------------------===// +// Intrinsic Definitions. +//===----------------------------------------------------------------------===// + +// Intrinsic class - This is used to define one LLVM intrinsic. The name of the +// intrinsic definition should start with "int_", then match the LLVM intrinsic +// name with the "llvm." prefix removed, and all "."s turned into "_"s. For +// example, llvm.bswap.i16 -> int_bswap_i16. +// +// * RetTypes is a list containing the return types expected for the +// intrinsic. +// * ParamTypes is a list containing the parameter types expected for the +// intrinsic. +// * Properties can be set to describe the behavior of the intrinsic. +// +class Intrinsic ret_types, + list param_types = [], + list properties = [], + string name = ""> { + string LLVMName = name; + string TargetPrefix = ""; // Set to a prefix for target-specific intrinsics. + list RetTypes = ret_types; + list ParamTypes = param_types; + list Properties = properties; + + bit isTarget = 0; +} + +/// GCCBuiltin - If this intrinsic exactly corresponds to a GCC builtin, this +/// specifies the name of the builtin. This provides automatic CBE and CFE +/// support. +class GCCBuiltin { + string GCCBuiltinName = name; +} + + +//===--------------- Variable Argument Handling Intrinsics ----------------===// +// + +def int_vastart : Intrinsic<[llvm_void_ty], [llvm_ptr_ty], [], "llvm.va_start">; +def int_vacopy : Intrinsic<[llvm_void_ty], [llvm_ptr_ty, llvm_ptr_ty], [], + "llvm.va_copy">; +def int_vaend : Intrinsic<[llvm_void_ty], [llvm_ptr_ty], [], "llvm.va_end">; + +//===------------------- Garbage Collection Intrinsics --------------------===// +// +def int_gcroot : Intrinsic<[llvm_void_ty], + [llvm_ptrptr_ty, llvm_ptr_ty]>; +def int_gcread : Intrinsic<[llvm_ptr_ty], + [llvm_ptr_ty, llvm_ptrptr_ty], + [IntrReadArgMem]>; +def int_gcwrite : Intrinsic<[llvm_void_ty], + [llvm_ptr_ty, llvm_ptr_ty, llvm_ptrptr_ty], + [IntrWriteArgMem, NoCapture<1>, NoCapture<2>]>; + +//===--------------------- Code Generator Intrinsics ----------------------===// +// +def int_returnaddress : Intrinsic<[llvm_ptr_ty], [llvm_i32_ty], [IntrNoMem]>; +def int_frameaddress : Intrinsic<[llvm_ptr_ty], [llvm_i32_ty], [IntrNoMem]>; + +// Note: we treat stacksave/stackrestore as writemem because we don't otherwise +// model their dependencies on allocas. +def int_stacksave : Intrinsic<[llvm_ptr_ty]>, + GCCBuiltin<"__builtin_stack_save">; +def int_stackrestore : Intrinsic<[llvm_void_ty], [llvm_ptr_ty]>, + GCCBuiltin<"__builtin_stack_restore">; + +// IntrWriteArgMem is more pessimistic than strictly necessary for prefetch, +// however it does conveniently prevent the prefetch from being reordered +// with respect to nearby accesses to the same memory. +def int_prefetch : Intrinsic<[llvm_void_ty], + [llvm_ptr_ty, llvm_i32_ty, llvm_i32_ty], + [IntrWriteArgMem, NoCapture<0>]>; +def int_pcmarker : Intrinsic<[llvm_void_ty], [llvm_i32_ty]>; + +def int_readcyclecounter : Intrinsic<[llvm_i64_ty]>; + +// Stack Protector Intrinsic - The stackprotector intrinsic writes the stack +// guard to the correct place on the stack frame. +def int_stackprotector : Intrinsic<[llvm_void_ty], + [llvm_ptr_ty, llvm_ptrptr_ty], + [IntrWriteMem]>; + +//===------------------- Standard C Library Intrinsics --------------------===// +// + +def int_memcpy : Intrinsic<[llvm_void_ty], + [llvm_ptr_ty, llvm_ptr_ty, llvm_anyint_ty, + llvm_i32_ty], + [IntrWriteArgMem, NoCapture<0>, NoCapture<1>]>; +def int_memmove : Intrinsic<[llvm_void_ty], + [llvm_ptr_ty, llvm_ptr_ty, llvm_anyint_ty, + llvm_i32_ty], + [IntrWriteArgMem, NoCapture<0>, NoCapture<1>]>; +def int_memset : Intrinsic<[llvm_void_ty], + [llvm_ptr_ty, llvm_i8_ty, llvm_anyint_ty, + llvm_i32_ty], + [IntrWriteArgMem, NoCapture<0>]>; + +// These functions do not actually read memory, but they are sensitive to the +// rounding mode. This needs to be modelled separately; in the meantime +// declaring them as reading memory is conservatively correct. +let Properties = [IntrReadMem] in { + def int_sqrt : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; + def int_powi : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>, llvm_i32_ty]>; + def int_sin : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; + def int_cos : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; + def int_pow : Intrinsic<[llvm_anyfloat_ty], + [LLVMMatchType<0>, LLVMMatchType<0>]>; + def int_log : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; + def int_log10: Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; + def int_log2 : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; + def int_exp : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; + def int_exp2 : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; +} + +// NOTE: these are internal interfaces. +def int_setjmp : Intrinsic<[llvm_i32_ty], [llvm_ptr_ty]>; +def int_longjmp : Intrinsic<[llvm_void_ty], [llvm_ptr_ty, llvm_i32_ty]>; +def int_sigsetjmp : Intrinsic<[llvm_i32_ty] , [llvm_ptr_ty, llvm_i32_ty]>; +def int_siglongjmp : Intrinsic<[llvm_void_ty], [llvm_ptr_ty, llvm_i32_ty]>; + +// Internal interface for object size checking +def int_objectsize : Intrinsic<[llvm_anyint_ty], [llvm_ptr_ty, llvm_i32_ty], + [IntrReadArgMem]>, + GCCBuiltin<"__builtin_object_size">; + +//===-------------------- Bit Manipulation Intrinsics ---------------------===// +// + +// None of these intrinsics accesses memory at all. +let Properties = [IntrNoMem] in { + def int_bswap: Intrinsic<[llvm_anyint_ty], [LLVMMatchType<0>]>; + def int_ctpop: Intrinsic<[llvm_anyint_ty], [LLVMMatchType<0>]>; + def int_ctlz : Intrinsic<[llvm_anyint_ty], [LLVMMatchType<0>]>; + def int_cttz : Intrinsic<[llvm_anyint_ty], [LLVMMatchType<0>]>; +} + +//===------------------------ Debugger Intrinsics -------------------------===// +// + +// None of these intrinsics accesses memory at all...but that doesn't mean the +// optimizers can change them aggressively. Special handling needed in a few +// places. +let Properties = [IntrNoMem] in { + def int_dbg_stoppoint : Intrinsic<[llvm_void_ty], + [llvm_i32_ty, llvm_i32_ty, + llvm_metadata_ty]>; + def int_dbg_region_start : Intrinsic<[llvm_void_ty], [llvm_metadata_ty]>; + def int_dbg_region_end : Intrinsic<[llvm_void_ty], [llvm_metadata_ty]>; + def int_dbg_func_start : Intrinsic<[llvm_void_ty], [llvm_metadata_ty]>; + def int_dbg_declare : Intrinsic<[llvm_void_ty], + [llvm_descriptor_ty, llvm_metadata_ty]>; +} + +//===------------------ Exception Handling Intrinsics----------------------===// +// +def int_eh_exception : Intrinsic<[llvm_ptr_ty], [], [IntrReadMem]>; +def int_eh_selector : Intrinsic<[llvm_i32_ty], + [llvm_ptr_ty, llvm_ptr_ty, llvm_vararg_ty]>; + +def int_eh_typeid_for : Intrinsic<[llvm_i32_ty], [llvm_ptr_ty]>; + +def int_eh_return_i32 : Intrinsic<[llvm_void_ty], [llvm_i32_ty, llvm_ptr_ty]>; +def int_eh_return_i64 : Intrinsic<[llvm_void_ty], [llvm_i64_ty, llvm_ptr_ty]>; + +def int_eh_unwind_init: Intrinsic<[llvm_void_ty]>, + GCCBuiltin<"__builtin_unwind_init">; + +def int_eh_dwarf_cfa : Intrinsic<[llvm_ptr_ty], [llvm_i32_ty]>; + +let Properties = [IntrNoMem] in { + def int_eh_sjlj_setjmp : Intrinsic<[llvm_i32_ty], [llvm_ptr_ty]>; + def int_eh_sjlj_longjmp : Intrinsic<[llvm_void_ty], [llvm_ptr_ty]>; + def int_eh_sjlj_lsda : Intrinsic<[llvm_ptr_ty]>; +} + +//===---------------- Generic Variable Attribute Intrinsics----------------===// +// +def int_var_annotation : Intrinsic<[llvm_void_ty], + [llvm_ptr_ty, llvm_ptr_ty, + llvm_ptr_ty, llvm_i32_ty], + [], "llvm.var.annotation">; +def int_ptr_annotation : Intrinsic<[LLVMAnyPointerType], + [LLVMMatchType<0>, llvm_ptr_ty, llvm_ptr_ty, + llvm_i32_ty], + [], "llvm.ptr.annotation">; +def int_annotation : Intrinsic<[llvm_anyint_ty], + [LLVMMatchType<0>, llvm_ptr_ty, + llvm_ptr_ty, llvm_i32_ty], + [], "llvm.annotation">; + +//===------------------------ Trampoline Intrinsics -----------------------===// +// +def int_init_trampoline : Intrinsic<[llvm_ptr_ty], + [llvm_ptr_ty, llvm_ptr_ty, llvm_ptr_ty], + [IntrWriteArgMem]>, + GCCBuiltin<"__builtin_init_trampoline">; + +//===------------------------ Overflow Intrinsics -------------------------===// +// + +// Expose the carry flag from add operations on two integrals. +def int_sadd_with_overflow : Intrinsic<[llvm_anyint_ty, llvm_i1_ty], + [LLVMMatchType<0>, LLVMMatchType<0>]>; +def int_uadd_with_overflow : Intrinsic<[llvm_anyint_ty, llvm_i1_ty], + [LLVMMatchType<0>, LLVMMatchType<0>]>; + +def int_ssub_with_overflow : Intrinsic<[llvm_anyint_ty, llvm_i1_ty], + [LLVMMatchType<0>, LLVMMatchType<0>]>; +def int_usub_with_overflow : Intrinsic<[llvm_anyint_ty, llvm_i1_ty], + [LLVMMatchType<0>, LLVMMatchType<0>]>; + +def int_smul_with_overflow : Intrinsic<[llvm_anyint_ty, llvm_i1_ty], + [LLVMMatchType<0>, LLVMMatchType<0>]>; +def int_umul_with_overflow : Intrinsic<[llvm_anyint_ty, llvm_i1_ty], + [LLVMMatchType<0>, LLVMMatchType<0>]>; + +//===------------------------- Atomic Intrinsics --------------------------===// +// +def int_memory_barrier : Intrinsic<[llvm_void_ty], + [llvm_i1_ty, llvm_i1_ty, + llvm_i1_ty, llvm_i1_ty, llvm_i1_ty], []>, + GCCBuiltin<"__builtin_llvm_memory_barrier">; + +def int_atomic_cmp_swap : Intrinsic<[llvm_anyint_ty], + [LLVMAnyPointerType>, + LLVMMatchType<0>, LLVMMatchType<0>], + [IntrWriteArgMem, NoCapture<0>]>, + GCCBuiltin<"__sync_val_compare_and_swap">; +def int_atomic_load_add : Intrinsic<[llvm_anyint_ty], + [LLVMAnyPointerType>, + LLVMMatchType<0>], + [IntrWriteArgMem, NoCapture<0>]>, + GCCBuiltin<"__sync_fetch_and_add">; +def int_atomic_swap : Intrinsic<[llvm_anyint_ty], + [LLVMAnyPointerType>, + LLVMMatchType<0>], + [IntrWriteArgMem, NoCapture<0>]>, + GCCBuiltin<"__sync_lock_test_and_set">; +def int_atomic_load_sub : Intrinsic<[llvm_anyint_ty], + [LLVMAnyPointerType>, + LLVMMatchType<0>], + [IntrWriteArgMem, NoCapture<0>]>, + GCCBuiltin<"__sync_fetch_and_sub">; +def int_atomic_load_and : Intrinsic<[llvm_anyint_ty], + [LLVMAnyPointerType>, + LLVMMatchType<0>], + [IntrWriteArgMem, NoCapture<0>]>, + GCCBuiltin<"__sync_fetch_and_and">; +def int_atomic_load_or : Intrinsic<[llvm_anyint_ty], + [LLVMAnyPointerType>, + LLVMMatchType<0>], + [IntrWriteArgMem, NoCapture<0>]>, + GCCBuiltin<"__sync_fetch_and_or">; +def int_atomic_load_xor : Intrinsic<[llvm_anyint_ty], + [LLVMAnyPointerType>, + LLVMMatchType<0>], + [IntrWriteArgMem, NoCapture<0>]>, + GCCBuiltin<"__sync_fetch_and_xor">; +def int_atomic_load_nand : Intrinsic<[llvm_anyint_ty], + [LLVMAnyPointerType>, + LLVMMatchType<0>], + [IntrWriteArgMem, NoCapture<0>]>, + GCCBuiltin<"__sync_fetch_and_nand">; +def int_atomic_load_min : Intrinsic<[llvm_anyint_ty], + [LLVMAnyPointerType>, + LLVMMatchType<0>], + [IntrWriteArgMem, NoCapture<0>]>, + GCCBuiltin<"__sync_fetch_and_min">; +def int_atomic_load_max : Intrinsic<[llvm_anyint_ty], + [LLVMAnyPointerType>, + LLVMMatchType<0>], + [IntrWriteArgMem, NoCapture<0>]>, + GCCBuiltin<"__sync_fetch_and_max">; +def int_atomic_load_umin : Intrinsic<[llvm_anyint_ty], + [LLVMAnyPointerType>, + LLVMMatchType<0>], + [IntrWriteArgMem, NoCapture<0>]>, + GCCBuiltin<"__sync_fetch_and_umin">; +def int_atomic_load_umax : Intrinsic<[llvm_anyint_ty], + [LLVMAnyPointerType>, + LLVMMatchType<0>], + [IntrWriteArgMem, NoCapture<0>]>, + GCCBuiltin<"__sync_fetch_and_umax">; + +//===------------------------- Memory Use Markers -------------------------===// +// +def int_lifetime_start : Intrinsic<[llvm_void_ty], + [llvm_i64_ty, llvm_ptr_ty], + [IntrWriteArgMem, NoCapture<1>]>; +def int_lifetime_end : Intrinsic<[llvm_void_ty], + [llvm_i64_ty, llvm_ptr_ty], + [IntrWriteArgMem, NoCapture<1>]>; +def int_invariant_start : Intrinsic<[llvm_descriptor_ty], + [llvm_i64_ty, llvm_ptr_ty], + [IntrReadArgMem, NoCapture<1>]>; +def int_invariant_end : Intrinsic<[llvm_void_ty], + [llvm_descriptor_ty, llvm_i64_ty, + llvm_ptr_ty], + [IntrWriteArgMem, NoCapture<2>]>; + +//===-------------------------- Other Intrinsics --------------------------===// +// +def int_flt_rounds : Intrinsic<[llvm_i32_ty]>, + GCCBuiltin<"__builtin_flt_rounds">; +def int_trap : Intrinsic<[llvm_void_ty]>, + GCCBuiltin<"__builtin_trap">; + +// These convert intrinsics are to support various conversions between +// various types with rounding and saturation. NOTE: avoid using these +// intrinsics as they might be removed sometime in the future and +// most targets don't support them. +def int_convertff : Intrinsic<[llvm_anyfloat_ty], + [llvm_anyfloat_ty, llvm_i32_ty, llvm_i32_ty]>; +def int_convertfsi : Intrinsic<[llvm_anyfloat_ty], + [llvm_anyint_ty, llvm_i32_ty, llvm_i32_ty]>; +def int_convertfui : Intrinsic<[llvm_anyfloat_ty], + [llvm_anyint_ty, llvm_i32_ty, llvm_i32_ty]>; +def int_convertsif : Intrinsic<[llvm_anyint_ty], + [llvm_anyfloat_ty, llvm_i32_ty, llvm_i32_ty]>; +def int_convertuif : Intrinsic<[llvm_anyint_ty], + [llvm_anyfloat_ty, llvm_i32_ty, llvm_i32_ty]>; +def int_convertss : Intrinsic<[llvm_anyint_ty], + [llvm_anyint_ty, llvm_i32_ty, llvm_i32_ty]>; +def int_convertsu : Intrinsic<[llvm_anyint_ty], + [llvm_anyint_ty, llvm_i32_ty, llvm_i32_ty]>; +def int_convertus : Intrinsic<[llvm_anyint_ty], + [llvm_anyint_ty, llvm_i32_ty, llvm_i32_ty]>; +def int_convertuu : Intrinsic<[llvm_anyint_ty], + [llvm_anyint_ty, llvm_i32_ty, llvm_i32_ty]>; + +//===----------------------------------------------------------------------===// +// Target-specific intrinsics +//===----------------------------------------------------------------------===// + +include "llvm/IntrinsicsPowerPC.td" +include "llvm/IntrinsicsX86.td" +include "llvm/IntrinsicsARM.td" +include "llvm/IntrinsicsCellSPU.td" +include "llvm/IntrinsicsAlpha.td" +include "llvm/IntrinsicsXCore.td" diff --git a/libclamav/c++/llvm/include/llvm/IntrinsicsARM.td b/libclamav/c++/llvm/include/llvm/IntrinsicsARM.td new file mode 100644 index 000000000..c408a2f37 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/IntrinsicsARM.td @@ -0,0 +1,376 @@ +//===- IntrinsicsARM.td - Defines ARM intrinsics -----------*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines all of the ARM-specific intrinsics. +// +//===----------------------------------------------------------------------===// + + +//===----------------------------------------------------------------------===// +// TLS + +let TargetPrefix = "arm" in { // All intrinsics start with "llvm.arm.". + def int_arm_thread_pointer : GCCBuiltin<"__builtin_thread_pointer">, + Intrinsic<[llvm_ptr_ty], [], [IntrNoMem]>; +} + +//===----------------------------------------------------------------------===// +// Advanced SIMD (NEON) + +let TargetPrefix = "arm" in { // All intrinsics start with "llvm.arm.". + + // The following classes do not correspond directly to GCC builtins. + class Neon_1Arg_Intrinsic + : Intrinsic<[llvm_anyvector_ty], [LLVMMatchType<0>], [IntrNoMem]>; + class Neon_1Arg_Narrow_Intrinsic + : Intrinsic<[llvm_anyvector_ty], + [LLVMExtendedElementVectorType<0>], [IntrNoMem]>; + class Neon_1Arg_Long_Intrinsic + : Intrinsic<[llvm_anyvector_ty], + [LLVMTruncatedElementVectorType<0>], [IntrNoMem]>; + class Neon_2Arg_Intrinsic + : Intrinsic<[llvm_anyvector_ty], [LLVMMatchType<0>, LLVMMatchType<0>], + [IntrNoMem]>; + class Neon_2Arg_Narrow_Intrinsic + : Intrinsic<[llvm_anyvector_ty], + [LLVMExtendedElementVectorType<0>, + LLVMExtendedElementVectorType<0>], + [IntrNoMem]>; + class Neon_2Arg_Long_Intrinsic + : Intrinsic<[llvm_anyvector_ty], + [LLVMTruncatedElementVectorType<0>, + LLVMTruncatedElementVectorType<0>], + [IntrNoMem]>; + class Neon_2Arg_Wide_Intrinsic + : Intrinsic<[llvm_anyvector_ty], + [LLVMMatchType<0>, LLVMTruncatedElementVectorType<0>], + [IntrNoMem]>; + class Neon_3Arg_Intrinsic + : Intrinsic<[llvm_anyvector_ty], + [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>], + [IntrNoMem]>; + class Neon_3Arg_Long_Intrinsic + : Intrinsic<[llvm_anyvector_ty], + [LLVMMatchType<0>, + LLVMTruncatedElementVectorType<0>, + LLVMTruncatedElementVectorType<0>], + [IntrNoMem]>; + class Neon_CvtFxToFP_Intrinsic + : Intrinsic<[llvm_anyfloat_ty], [llvm_anyint_ty, llvm_i32_ty], [IntrNoMem]>; + class Neon_CvtFPToFx_Intrinsic + : Intrinsic<[llvm_anyint_ty], [llvm_anyfloat_ty, llvm_i32_ty], [IntrNoMem]>; + + // The table operands for VTBL and VTBX consist of 1 to 4 v8i8 vectors. + // Besides the table, VTBL has one other v8i8 argument and VTBX has two. + // Overall, the classes range from 2 to 6 v8i8 arguments. + class Neon_Tbl2Arg_Intrinsic + : Intrinsic<[llvm_v8i8_ty], + [llvm_v8i8_ty, llvm_v8i8_ty], [IntrNoMem]>; + class Neon_Tbl3Arg_Intrinsic + : Intrinsic<[llvm_v8i8_ty], + [llvm_v8i8_ty, llvm_v8i8_ty, llvm_v8i8_ty], [IntrNoMem]>; + class Neon_Tbl4Arg_Intrinsic + : Intrinsic<[llvm_v8i8_ty], + [llvm_v8i8_ty, llvm_v8i8_ty, llvm_v8i8_ty, llvm_v8i8_ty], + [IntrNoMem]>; + class Neon_Tbl5Arg_Intrinsic + : Intrinsic<[llvm_v8i8_ty], + [llvm_v8i8_ty, llvm_v8i8_ty, llvm_v8i8_ty, llvm_v8i8_ty, + llvm_v8i8_ty], [IntrNoMem]>; + class Neon_Tbl6Arg_Intrinsic + : Intrinsic<[llvm_v8i8_ty], + [llvm_v8i8_ty, llvm_v8i8_ty, llvm_v8i8_ty, llvm_v8i8_ty, + llvm_v8i8_ty, llvm_v8i8_ty], [IntrNoMem]>; +} + +// Arithmetic ops + +let Properties = [IntrNoMem, Commutative] in { + + // Vector Add. + def int_arm_neon_vhadds : Neon_2Arg_Intrinsic; + def int_arm_neon_vhaddu : Neon_2Arg_Intrinsic; + def int_arm_neon_vrhadds : Neon_2Arg_Intrinsic; + def int_arm_neon_vrhaddu : Neon_2Arg_Intrinsic; + def int_arm_neon_vqadds : Neon_2Arg_Intrinsic; + def int_arm_neon_vqaddu : Neon_2Arg_Intrinsic; + def int_arm_neon_vaddhn : Neon_2Arg_Narrow_Intrinsic; + def int_arm_neon_vraddhn : Neon_2Arg_Narrow_Intrinsic; + def int_arm_neon_vaddls : Neon_2Arg_Long_Intrinsic; + def int_arm_neon_vaddlu : Neon_2Arg_Long_Intrinsic; + def int_arm_neon_vaddws : Neon_2Arg_Wide_Intrinsic; + def int_arm_neon_vaddwu : Neon_2Arg_Wide_Intrinsic; + + // Vector Multiply. + def int_arm_neon_vmulp : Neon_2Arg_Intrinsic; + def int_arm_neon_vqdmulh : Neon_2Arg_Intrinsic; + def int_arm_neon_vqrdmulh : Neon_2Arg_Intrinsic; + def int_arm_neon_vmulls : Neon_2Arg_Long_Intrinsic; + def int_arm_neon_vmullu : Neon_2Arg_Long_Intrinsic; + def int_arm_neon_vmullp : Neon_2Arg_Long_Intrinsic; + def int_arm_neon_vqdmull : Neon_2Arg_Long_Intrinsic; + + // Vector Multiply and Accumulate/Subtract. + def int_arm_neon_vmlals : Neon_3Arg_Long_Intrinsic; + def int_arm_neon_vmlalu : Neon_3Arg_Long_Intrinsic; + def int_arm_neon_vmlsls : Neon_3Arg_Long_Intrinsic; + def int_arm_neon_vmlslu : Neon_3Arg_Long_Intrinsic; + def int_arm_neon_vqdmlal : Neon_3Arg_Long_Intrinsic; + def int_arm_neon_vqdmlsl : Neon_3Arg_Long_Intrinsic; + + // Vector Maximum. + def int_arm_neon_vmaxs : Neon_2Arg_Intrinsic; + def int_arm_neon_vmaxu : Neon_2Arg_Intrinsic; + + // Vector Minimum. + def int_arm_neon_vmins : Neon_2Arg_Intrinsic; + def int_arm_neon_vminu : Neon_2Arg_Intrinsic; + + // Vector Reciprocal Step. + def int_arm_neon_vrecps : Neon_2Arg_Intrinsic; + + // Vector Reciprocal Square Root Step. + def int_arm_neon_vrsqrts : Neon_2Arg_Intrinsic; +} + +// Vector Subtract. +def int_arm_neon_vhsubs : Neon_2Arg_Intrinsic; +def int_arm_neon_vhsubu : Neon_2Arg_Intrinsic; +def int_arm_neon_vqsubs : Neon_2Arg_Intrinsic; +def int_arm_neon_vqsubu : Neon_2Arg_Intrinsic; +def int_arm_neon_vsubhn : Neon_2Arg_Narrow_Intrinsic; +def int_arm_neon_vrsubhn : Neon_2Arg_Narrow_Intrinsic; +def int_arm_neon_vsubls : Neon_2Arg_Long_Intrinsic; +def int_arm_neon_vsublu : Neon_2Arg_Long_Intrinsic; +def int_arm_neon_vsubws : Neon_2Arg_Wide_Intrinsic; +def int_arm_neon_vsubwu : Neon_2Arg_Wide_Intrinsic; + +// Vector Absolute Compare. +let TargetPrefix = "arm" in { + def int_arm_neon_vacged : Intrinsic<[llvm_v2i32_ty], + [llvm_v2f32_ty, llvm_v2f32_ty], + [IntrNoMem]>; + def int_arm_neon_vacgeq : Intrinsic<[llvm_v4i32_ty], + [llvm_v4f32_ty, llvm_v4f32_ty], + [IntrNoMem]>; + def int_arm_neon_vacgtd : Intrinsic<[llvm_v2i32_ty], + [llvm_v2f32_ty, llvm_v2f32_ty], + [IntrNoMem]>; + def int_arm_neon_vacgtq : Intrinsic<[llvm_v4i32_ty], + [llvm_v4f32_ty, llvm_v4f32_ty], + [IntrNoMem]>; +} + +// Vector Absolute Differences. +def int_arm_neon_vabds : Neon_2Arg_Intrinsic; +def int_arm_neon_vabdu : Neon_2Arg_Intrinsic; +def int_arm_neon_vabdls : Neon_2Arg_Long_Intrinsic; +def int_arm_neon_vabdlu : Neon_2Arg_Long_Intrinsic; + +// Vector Absolute Difference and Accumulate. +def int_arm_neon_vabas : Neon_3Arg_Intrinsic; +def int_arm_neon_vabau : Neon_3Arg_Intrinsic; +def int_arm_neon_vabals : Neon_3Arg_Long_Intrinsic; +def int_arm_neon_vabalu : Neon_3Arg_Long_Intrinsic; + +// Vector Pairwise Add. +def int_arm_neon_vpadd : Neon_2Arg_Intrinsic; + +// Vector Pairwise Add Long. +// Note: This is different than the other "long" NEON intrinsics because +// the result vector has half as many elements as the source vector. +// The source and destination vector types must be specified separately. +let TargetPrefix = "arm" in { + def int_arm_neon_vpaddls : Intrinsic<[llvm_anyvector_ty], [llvm_anyvector_ty], + [IntrNoMem]>; + def int_arm_neon_vpaddlu : Intrinsic<[llvm_anyvector_ty], [llvm_anyvector_ty], + [IntrNoMem]>; +} + +// Vector Pairwise Add and Accumulate Long. +// Note: This is similar to vpaddl but the destination vector also appears +// as the first argument. +let TargetPrefix = "arm" in { + def int_arm_neon_vpadals : Intrinsic<[llvm_anyvector_ty], + [LLVMMatchType<0>, llvm_anyvector_ty], + [IntrNoMem]>; + def int_arm_neon_vpadalu : Intrinsic<[llvm_anyvector_ty], + [LLVMMatchType<0>, llvm_anyvector_ty], + [IntrNoMem]>; +} + +// Vector Pairwise Maximum and Minimum. +def int_arm_neon_vpmaxs : Neon_2Arg_Intrinsic; +def int_arm_neon_vpmaxu : Neon_2Arg_Intrinsic; +def int_arm_neon_vpmins : Neon_2Arg_Intrinsic; +def int_arm_neon_vpminu : Neon_2Arg_Intrinsic; + +// Vector Shifts: +// +// The various saturating and rounding vector shift operations need to be +// represented by intrinsics in LLVM, and even the basic VSHL variable shift +// operation cannot be safely translated to LLVM's shift operators. VSHL can +// be used for both left and right shifts, or even combinations of the two, +// depending on the signs of the shift amounts. It also has well-defined +// behavior for shift amounts that LLVM leaves undefined. Only basic shifts +// by constants can be represented with LLVM's shift operators. +// +// The shift counts for these intrinsics are always vectors, even for constant +// shifts, where the constant is replicated. For consistency with VSHL (and +// other variable shift instructions), left shifts have positive shift counts +// and right shifts have negative shift counts. This convention is also used +// for constant right shift intrinsics, and to help preserve sanity, the +// intrinsic names use "shift" instead of either "shl" or "shr". Where +// applicable, signed and unsigned versions of the intrinsics are +// distinguished with "s" and "u" suffixes. A few NEON shift instructions, +// such as VQSHLU, take signed operands but produce unsigned results; these +// use a "su" suffix. + +// Vector Shift. +def int_arm_neon_vshifts : Neon_2Arg_Intrinsic; +def int_arm_neon_vshiftu : Neon_2Arg_Intrinsic; +def int_arm_neon_vshiftls : Neon_2Arg_Long_Intrinsic; +def int_arm_neon_vshiftlu : Neon_2Arg_Long_Intrinsic; +def int_arm_neon_vshiftn : Neon_2Arg_Narrow_Intrinsic; + +// Vector Rounding Shift. +def int_arm_neon_vrshifts : Neon_2Arg_Intrinsic; +def int_arm_neon_vrshiftu : Neon_2Arg_Intrinsic; +def int_arm_neon_vrshiftn : Neon_2Arg_Narrow_Intrinsic; + +// Vector Saturating Shift. +def int_arm_neon_vqshifts : Neon_2Arg_Intrinsic; +def int_arm_neon_vqshiftu : Neon_2Arg_Intrinsic; +def int_arm_neon_vqshiftsu : Neon_2Arg_Intrinsic; +def int_arm_neon_vqshiftns : Neon_2Arg_Narrow_Intrinsic; +def int_arm_neon_vqshiftnu : Neon_2Arg_Narrow_Intrinsic; +def int_arm_neon_vqshiftnsu : Neon_2Arg_Narrow_Intrinsic; + +// Vector Saturating Rounding Shift. +def int_arm_neon_vqrshifts : Neon_2Arg_Intrinsic; +def int_arm_neon_vqrshiftu : Neon_2Arg_Intrinsic; +def int_arm_neon_vqrshiftns : Neon_2Arg_Narrow_Intrinsic; +def int_arm_neon_vqrshiftnu : Neon_2Arg_Narrow_Intrinsic; +def int_arm_neon_vqrshiftnsu : Neon_2Arg_Narrow_Intrinsic; + +// Vector Shift and Insert. +def int_arm_neon_vshiftins : Neon_3Arg_Intrinsic; + +// Vector Absolute Value and Saturating Absolute Value. +def int_arm_neon_vabs : Neon_1Arg_Intrinsic; +def int_arm_neon_vqabs : Neon_1Arg_Intrinsic; + +// Vector Saturating Negate. +def int_arm_neon_vqneg : Neon_1Arg_Intrinsic; + +// Vector Count Leading Sign/Zero Bits. +def int_arm_neon_vcls : Neon_1Arg_Intrinsic; +def int_arm_neon_vclz : Neon_1Arg_Intrinsic; + +// Vector Count One Bits. +def int_arm_neon_vcnt : Neon_1Arg_Intrinsic; + +// Vector Reciprocal Estimate. +def int_arm_neon_vrecpe : Neon_1Arg_Intrinsic; + +// Vector Reciprocal Square Root Estimate. +def int_arm_neon_vrsqrte : Neon_1Arg_Intrinsic; + +// Vector Conversions Between Floating-point and Fixed-point. +def int_arm_neon_vcvtfp2fxs : Neon_CvtFPToFx_Intrinsic; +def int_arm_neon_vcvtfp2fxu : Neon_CvtFPToFx_Intrinsic; +def int_arm_neon_vcvtfxs2fp : Neon_CvtFxToFP_Intrinsic; +def int_arm_neon_vcvtfxu2fp : Neon_CvtFxToFP_Intrinsic; + +// Narrowing and Lengthening Vector Moves. +def int_arm_neon_vmovn : Neon_1Arg_Narrow_Intrinsic; +def int_arm_neon_vqmovns : Neon_1Arg_Narrow_Intrinsic; +def int_arm_neon_vqmovnu : Neon_1Arg_Narrow_Intrinsic; +def int_arm_neon_vqmovnsu : Neon_1Arg_Narrow_Intrinsic; +def int_arm_neon_vmovls : Neon_1Arg_Long_Intrinsic; +def int_arm_neon_vmovlu : Neon_1Arg_Long_Intrinsic; + +// Vector Table Lookup. +// The first 1-4 arguments are the table. +def int_arm_neon_vtbl1 : Neon_Tbl2Arg_Intrinsic; +def int_arm_neon_vtbl2 : Neon_Tbl3Arg_Intrinsic; +def int_arm_neon_vtbl3 : Neon_Tbl4Arg_Intrinsic; +def int_arm_neon_vtbl4 : Neon_Tbl5Arg_Intrinsic; + +// Vector Table Extension. +// Some elements of the destination vector may not be updated, so the original +// value of that vector is passed as the first argument. The next 1-4 +// arguments after that are the table. +def int_arm_neon_vtbx1 : Neon_Tbl3Arg_Intrinsic; +def int_arm_neon_vtbx2 : Neon_Tbl4Arg_Intrinsic; +def int_arm_neon_vtbx3 : Neon_Tbl5Arg_Intrinsic; +def int_arm_neon_vtbx4 : Neon_Tbl6Arg_Intrinsic; + +let TargetPrefix = "arm" in { + + // De-interleaving vector loads from N-element structures. + def int_arm_neon_vld1 : Intrinsic<[llvm_anyvector_ty], + [llvm_ptr_ty], [IntrReadArgMem]>; + def int_arm_neon_vld2 : Intrinsic<[llvm_anyvector_ty, LLVMMatchType<0>], + [llvm_ptr_ty], [IntrReadArgMem]>; + def int_arm_neon_vld3 : Intrinsic<[llvm_anyvector_ty, LLVMMatchType<0>, + LLVMMatchType<0>], + [llvm_ptr_ty], [IntrReadArgMem]>; + def int_arm_neon_vld4 : Intrinsic<[llvm_anyvector_ty, LLVMMatchType<0>, + LLVMMatchType<0>, LLVMMatchType<0>], + [llvm_ptr_ty], [IntrReadArgMem]>; + + // Vector load N-element structure to one lane. + def int_arm_neon_vld2lane : Intrinsic<[llvm_anyvector_ty, LLVMMatchType<0>], + [llvm_ptr_ty, LLVMMatchType<0>, + LLVMMatchType<0>, llvm_i32_ty], + [IntrReadArgMem]>; + def int_arm_neon_vld3lane : Intrinsic<[llvm_anyvector_ty, LLVMMatchType<0>, + LLVMMatchType<0>], + [llvm_ptr_ty, LLVMMatchType<0>, + LLVMMatchType<0>, LLVMMatchType<0>, + llvm_i32_ty], [IntrReadArgMem]>; + def int_arm_neon_vld4lane : Intrinsic<[llvm_anyvector_ty, LLVMMatchType<0>, + LLVMMatchType<0>, LLVMMatchType<0>], + [llvm_ptr_ty, LLVMMatchType<0>, + LLVMMatchType<0>, LLVMMatchType<0>, + LLVMMatchType<0>, llvm_i32_ty], + [IntrReadArgMem]>; + + // Interleaving vector stores from N-element structures. + def int_arm_neon_vst1 : Intrinsic<[llvm_void_ty], + [llvm_ptr_ty, llvm_anyvector_ty], + [IntrWriteArgMem]>; + def int_arm_neon_vst2 : Intrinsic<[llvm_void_ty], + [llvm_ptr_ty, llvm_anyvector_ty, + LLVMMatchType<0>], [IntrWriteArgMem]>; + def int_arm_neon_vst3 : Intrinsic<[llvm_void_ty], + [llvm_ptr_ty, llvm_anyvector_ty, + LLVMMatchType<0>, LLVMMatchType<0>], + [IntrWriteArgMem]>; + def int_arm_neon_vst4 : Intrinsic<[llvm_void_ty], + [llvm_ptr_ty, llvm_anyvector_ty, + LLVMMatchType<0>, LLVMMatchType<0>, + LLVMMatchType<0>], [IntrWriteArgMem]>; + + // Vector store N-element structure from one lane. + def int_arm_neon_vst2lane : Intrinsic<[llvm_void_ty], + [llvm_ptr_ty, llvm_anyvector_ty, + LLVMMatchType<0>, llvm_i32_ty], + [IntrWriteArgMem]>; + def int_arm_neon_vst3lane : Intrinsic<[llvm_void_ty], + [llvm_ptr_ty, llvm_anyvector_ty, + LLVMMatchType<0>, LLVMMatchType<0>, + llvm_i32_ty], [IntrWriteArgMem]>; + def int_arm_neon_vst4lane : Intrinsic<[llvm_void_ty], + [llvm_ptr_ty, llvm_anyvector_ty, + LLVMMatchType<0>, LLVMMatchType<0>, + LLVMMatchType<0>, llvm_i32_ty], + [IntrWriteArgMem]>; +} diff --git a/libclamav/c++/llvm/include/llvm/IntrinsicsAlpha.td b/libclamav/c++/llvm/include/llvm/IntrinsicsAlpha.td new file mode 100644 index 000000000..59865cf8a --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/IntrinsicsAlpha.td @@ -0,0 +1,18 @@ +//===- IntrinsicsAlpha.td - Defines Alpha intrinsics -------*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines all of the Alpha-specific intrinsics. +// +//===----------------------------------------------------------------------===// + + +let TargetPrefix = "alpha" in { // All intrinsics start with "llvm.alpha.". + def int_alpha_umulh : GCCBuiltin<"__builtin_alpha_umulh">, + Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i64_ty], [IntrNoMem]>; +} diff --git a/libclamav/c++/llvm/include/llvm/IntrinsicsCellSPU.td b/libclamav/c++/llvm/include/llvm/IntrinsicsCellSPU.td new file mode 100644 index 000000000..1e311bbec --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/IntrinsicsCellSPU.td @@ -0,0 +1,242 @@ +//==- IntrinsicsCellSPU.td - Cell SDK intrinsics -*- tablegen -*-==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// Department at The Aerospace Corporation and is distributed under the +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Cell SPU Instructions: +//===----------------------------------------------------------------------===// +// TODO Items (not urgent today, but would be nice, low priority) +// +// ANDBI, ORBI: SPU constructs a 4-byte constant for these instructions by +// concatenating the byte argument b as "bbbb". Could recognize this bit pattern +// in 16-bit and 32-bit constants and reduce instruction count. +//===----------------------------------------------------------------------===// + +// 7-bit integer type, used as an immediate: +def cell_i7_ty: LLVMType; +def cell_i8_ty: LLVMType; + +// Keep this here until it's actually supported: +def llvm_i128_ty : LLVMType; + +class v16i8_u7imm : + GCCBuiltin, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, cell_i7_ty], + [IntrNoMem]>; + +class v16i8_u8imm : + GCCBuiltin, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i8_ty], + [IntrNoMem]>; + +class v16i8_s10imm : + GCCBuiltin, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i16_ty], + [IntrNoMem]>; + +class v16i8_u16imm : + GCCBuiltin, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i16_ty], + [IntrNoMem]>; + +class v16i8_rr : + GCCBuiltin, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], + [IntrNoMem]>; + +class v8i16_s10imm : + GCCBuiltin, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i16_ty], + [IntrNoMem]>; + +class v8i16_u16imm : + GCCBuiltin, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i16_ty], + [IntrNoMem]>; + +class v8i16_rr : + GCCBuiltin, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], + [IntrNoMem]>; + +class v4i32_rr : + GCCBuiltin, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem]>; + +class v4i32_u7imm : + GCCBuiltin, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, cell_i7_ty], + [IntrNoMem]>; + +class v4i32_s10imm : + GCCBuiltin, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i16_ty], + [IntrNoMem]>; + +class v4i32_u16imm : + GCCBuiltin, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i16_ty], + [IntrNoMem]>; + +class v4f32_rr : + GCCBuiltin, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], + [IntrNoMem]>; + +class v4f32_rrr : + GCCBuiltin, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty], + [IntrNoMem]>; + +class v2f64_rr : + GCCBuiltin, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], + [IntrNoMem]>; + +// All Cell SPU intrinsics start with "llvm.spu.". +let TargetPrefix = "spu" in { + def int_spu_si_fsmbi : v8i16_u16imm<"fsmbi">; + def int_spu_si_ah : v8i16_rr<"ah">; + def int_spu_si_ahi : v8i16_s10imm<"ahi">; + def int_spu_si_a : v4i32_rr<"a">; + def int_spu_si_ai : v4i32_s10imm<"ai">; + def int_spu_si_sfh : v8i16_rr<"sfh">; + def int_spu_si_sfhi : v8i16_s10imm<"sfhi">; + def int_spu_si_sf : v4i32_rr<"sf">; + def int_spu_si_sfi : v4i32_s10imm<"sfi">; + def int_spu_si_addx : v4i32_rr<"addx">; + def int_spu_si_cg : v4i32_rr<"cg">; + def int_spu_si_cgx : v4i32_rr<"cgx">; + def int_spu_si_sfx : v4i32_rr<"sfx">; + def int_spu_si_bg : v4i32_rr<"bg">; + def int_spu_si_bgx : v4i32_rr<"bgx">; + def int_spu_si_mpy : // This is special: + GCCBuiltin<"__builtin_si_mpy">, + Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty], + [IntrNoMem]>; + def int_spu_si_mpyu : // This is special: + GCCBuiltin<"__builtin_si_mpyu">, + Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty], + [IntrNoMem]>; + def int_spu_si_mpyi : // This is special: + GCCBuiltin<"__builtin_si_mpyi">, + Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_i16_ty], + [IntrNoMem]>; + def int_spu_si_mpyui : // This is special: + GCCBuiltin<"__builtin_si_mpyui">, + Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_i16_ty], + [IntrNoMem]>; + def int_spu_si_mpya : // This is special: + GCCBuiltin<"__builtin_si_mpya">, + Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_v8i16_ty], + [IntrNoMem]>; + def int_spu_si_mpyh : // This is special: + GCCBuiltin<"__builtin_si_mpyh">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v8i16_ty], + [IntrNoMem]>; + def int_spu_si_mpys : // This is special: + GCCBuiltin<"__builtin_si_mpys">, + Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty], + [IntrNoMem]>; + def int_spu_si_mpyhh : // This is special: + GCCBuiltin<"__builtin_si_mpyhh">, + Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty], + [IntrNoMem]>; + def int_spu_si_mpyhha : // This is special: + GCCBuiltin<"__builtin_si_mpyhha">, + Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty], + [IntrNoMem]>; + def int_spu_si_mpyhhu : // This is special: + GCCBuiltin<"__builtin_si_mpyhhu">, + Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty], + [IntrNoMem]>; + def int_spu_si_mpyhhau : // This is special: + GCCBuiltin<"__builtin_si_mpyhhau">, + Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty], + [IntrNoMem]>; + + def int_spu_si_shli: v4i32_u7imm<"shli">; + + def int_spu_si_shlqbi: + GCCBuiltin, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], + [IntrNoMem]>; + + def int_spu_si_shlqbii: v16i8_u7imm<"shlqbii">; + def int_spu_si_shlqby: + GCCBuiltin, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], + [IntrNoMem]>; + def int_spu_si_shlqbyi: v16i8_u7imm<"shlqbyi">; + + def int_spu_si_ceq: v4i32_rr<"ceq">; + def int_spu_si_ceqi: v4i32_s10imm<"ceqi">; + def int_spu_si_ceqb: v16i8_rr<"ceqb">; + def int_spu_si_ceqbi: v16i8_u8imm<"ceqbi">; + def int_spu_si_ceqh: v8i16_rr<"ceqh">; + def int_spu_si_ceqhi: v8i16_s10imm<"ceqhi">; + def int_spu_si_cgt: v4i32_rr<"cgt">; + def int_spu_si_cgti: v4i32_s10imm<"cgti">; + def int_spu_si_cgtb: v16i8_rr<"cgtb">; + def int_spu_si_cgtbi: v16i8_u8imm<"cgtbi">; + def int_spu_si_cgth: v8i16_rr<"cgth">; + def int_spu_si_cgthi: v8i16_s10imm<"cgthi">; + def int_spu_si_clgtb: v16i8_rr<"clgtb">; + def int_spu_si_clgtbi: v16i8_u8imm<"clgtbi">; + def int_spu_si_clgth: v8i16_rr<"clgth">; + def int_spu_si_clgthi: v8i16_s10imm<"clgthi">; + def int_spu_si_clgt: v4i32_rr<"clgt">; + def int_spu_si_clgti: v4i32_s10imm<"clgti">; + + def int_spu_si_and: v4i32_rr<"and">; + def int_spu_si_andbi: v16i8_u8imm<"andbi">; + def int_spu_si_andc: v4i32_rr<"andc">; + def int_spu_si_andhi: v8i16_s10imm<"andhi">; + def int_spu_si_andi: v4i32_s10imm<"andi">; + + def int_spu_si_or: v4i32_rr<"or">; + def int_spu_si_orbi: v16i8_u8imm<"orbi">; + def int_spu_si_orc: v4i32_rr<"orc">; + def int_spu_si_orhi: v8i16_s10imm<"orhi">; + def int_spu_si_ori: v4i32_s10imm<"ori">; + + def int_spu_si_xor: v4i32_rr<"xor">; + def int_spu_si_xorbi: v16i8_u8imm<"xorbi">; + def int_spu_si_xorhi: v8i16_s10imm<"xorhi">; + def int_spu_si_xori: v4i32_s10imm<"xori">; + + def int_spu_si_nor: v4i32_rr<"nor">; + def int_spu_si_nand: v4i32_rr<"nand">; + + def int_spu_si_fa: v4f32_rr<"fa">; + def int_spu_si_fs: v4f32_rr<"fs">; + def int_spu_si_fm: v4f32_rr<"fm">; + + def int_spu_si_fceq: v4f32_rr<"fceq">; + def int_spu_si_fcmeq: v4f32_rr<"fcmeq">; + def int_spu_si_fcgt: v4f32_rr<"fcgt">; + def int_spu_si_fcmgt: v4f32_rr<"fcmgt">; + + def int_spu_si_fma: v4f32_rrr<"fma">; + def int_spu_si_fnms: v4f32_rrr<"fnms">; + def int_spu_si_fms: v4f32_rrr<"fms">; + + def int_spu_si_dfa: v2f64_rr<"dfa">; + def int_spu_si_dfs: v2f64_rr<"dfs">; + def int_spu_si_dfm: v2f64_rr<"dfm">; + +//def int_spu_si_dfceq: v2f64_rr<"dfceq">; +//def int_spu_si_dfcmeq: v2f64_rr<"dfcmeq">; +//def int_spu_si_dfcgt: v2f64_rr<"dfcgt">; +//def int_spu_si_dfcmgt: v2f64_rr<"dfcmgt">; + + def int_spu_si_dfnma: v2f64_rr<"dfnma">; + def int_spu_si_dfma: v2f64_rr<"dfma">; + def int_spu_si_dfnms: v2f64_rr<"dfnms">; + def int_spu_si_dfms: v2f64_rr<"dfms">; +} diff --git a/libclamav/c++/llvm/include/llvm/IntrinsicsPowerPC.td b/libclamav/c++/llvm/include/llvm/IntrinsicsPowerPC.td new file mode 100644 index 000000000..ffb870da1 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/IntrinsicsPowerPC.td @@ -0,0 +1,470 @@ +//===- IntrinsicsPowerPC.td - Defines PowerPC intrinsics ---*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines all of the PowerPC-specific intrinsics. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// Definitions for all PowerPC intrinsics. +// + +// Non-altivec intrinsics. +let TargetPrefix = "ppc" in { // All intrinsics start with "llvm.ppc.". + // dcba/dcbf/dcbi/dcbst/dcbt/dcbz/dcbzl(PPC970) instructions. + def int_ppc_dcba : Intrinsic<[llvm_void_ty], [llvm_ptr_ty], [IntrWriteMem]>; + def int_ppc_dcbf : Intrinsic<[llvm_void_ty], [llvm_ptr_ty], [IntrWriteMem]>; + def int_ppc_dcbi : Intrinsic<[llvm_void_ty], [llvm_ptr_ty], [IntrWriteMem]>; + def int_ppc_dcbst : Intrinsic<[llvm_void_ty], [llvm_ptr_ty], [IntrWriteMem]>; + def int_ppc_dcbt : Intrinsic<[llvm_void_ty], [llvm_ptr_ty], [IntrWriteMem]>; + def int_ppc_dcbtst: Intrinsic<[llvm_void_ty], [llvm_ptr_ty], [IntrWriteMem]>; + def int_ppc_dcbz : Intrinsic<[llvm_void_ty], [llvm_ptr_ty], [IntrWriteMem]>; + def int_ppc_dcbzl : Intrinsic<[llvm_void_ty], [llvm_ptr_ty], [IntrWriteMem]>; + + // sync instruction + def int_ppc_sync : Intrinsic<[llvm_void_ty], [], [IntrWriteMem]>; +} + + +let TargetPrefix = "ppc" in { // All PPC intrinsics start with "llvm.ppc.". + /// PowerPC_Vec_Intrinsic - Base class for all altivec intrinsics. + class PowerPC_Vec_Intrinsic ret_types, + list param_types, + list properties> + : GCCBuiltin, + Intrinsic; +} + +//===----------------------------------------------------------------------===// +// PowerPC Altivec Intrinsic Class Definitions. +// + +/// PowerPC_Vec_FF_Intrinsic - A PowerPC intrinsic that takes one v4f32 +/// vector and returns one. These intrinsics have no side effects. +class PowerPC_Vec_FF_Intrinsic + : PowerPC_Vec_Intrinsic; + +/// PowerPC_Vec_FFF_Intrinsic - A PowerPC intrinsic that takes two v4f32 +/// vectors and returns one. These intrinsics have no side effects. +class PowerPC_Vec_FFF_Intrinsic + : PowerPC_Vec_Intrinsic; + +/// PowerPC_Vec_BBB_Intrinsic - A PowerPC intrinsic that takes two v16f8 +/// vectors and returns one. These intrinsics have no side effects. +class PowerPC_Vec_BBB_Intrinsic + : PowerPC_Vec_Intrinsic; + +/// PowerPC_Vec_HHH_Intrinsic - A PowerPC intrinsic that takes two v8i16 +/// vectors and returns one. These intrinsics have no side effects. +class PowerPC_Vec_HHH_Intrinsic + : PowerPC_Vec_Intrinsic; + +/// PowerPC_Vec_WWW_Intrinsic - A PowerPC intrinsic that takes two v4i32 +/// vectors and returns one. These intrinsics have no side effects. +class PowerPC_Vec_WWW_Intrinsic + : PowerPC_Vec_Intrinsic; + + +//===----------------------------------------------------------------------===// +// PowerPC Altivec Intrinsic Definitions. + +let TargetPrefix = "ppc" in { // All intrinsics start with "llvm.ppc.". + // Data Stream Control. + def int_ppc_altivec_dss : GCCBuiltin<"__builtin_altivec_dss">, + Intrinsic<[llvm_void_ty], [llvm_i32_ty], [IntrWriteMem]>; + def int_ppc_altivec_dssall : GCCBuiltin<"__builtin_altivec_dssall">, + Intrinsic<[llvm_void_ty], [], [IntrWriteMem]>; + def int_ppc_altivec_dst : GCCBuiltin<"__builtin_altivec_dst">, + Intrinsic<[llvm_void_ty], + [llvm_ptr_ty, llvm_i32_ty, llvm_i32_ty], + [IntrWriteMem]>; + def int_ppc_altivec_dstt : GCCBuiltin<"__builtin_altivec_dstt">, + Intrinsic<[llvm_void_ty], + [llvm_ptr_ty, llvm_i32_ty, llvm_i32_ty], + [IntrWriteMem]>; + def int_ppc_altivec_dstst : GCCBuiltin<"__builtin_altivec_dstst">, + Intrinsic<[llvm_void_ty], + [llvm_ptr_ty, llvm_i32_ty, llvm_i32_ty], + [IntrWriteMem]>; + def int_ppc_altivec_dststt : GCCBuiltin<"__builtin_altivec_dststt">, + Intrinsic<[llvm_void_ty], + [llvm_ptr_ty, llvm_i32_ty, llvm_i32_ty], + [IntrWriteMem]>; + + // VSCR access. + def int_ppc_altivec_mfvscr : GCCBuiltin<"__builtin_altivec_mfvscr">, + Intrinsic<[llvm_v8i16_ty], [], [IntrReadMem]>; + def int_ppc_altivec_mtvscr : GCCBuiltin<"__builtin_altivec_mtvscr">, + Intrinsic<[llvm_void_ty], [llvm_v4i32_ty], [IntrWriteMem]>; + + + // Loads. These don't map directly to GCC builtins because they represent the + // source address with a single pointer. + def int_ppc_altivec_lvx : + Intrinsic<[llvm_v4i32_ty], [llvm_ptr_ty], [IntrReadMem]>; + def int_ppc_altivec_lvxl : + Intrinsic<[llvm_v4i32_ty], [llvm_ptr_ty], [IntrReadMem]>; + def int_ppc_altivec_lvebx : + Intrinsic<[llvm_v16i8_ty], [llvm_ptr_ty], [IntrReadMem]>; + def int_ppc_altivec_lvehx : + Intrinsic<[llvm_v8i16_ty], [llvm_ptr_ty], [IntrReadMem]>; + def int_ppc_altivec_lvewx : + Intrinsic<[llvm_v4i32_ty], [llvm_ptr_ty], [IntrReadMem]>; + + // Stores. These don't map directly to GCC builtins because they represent the + // source address with a single pointer. + def int_ppc_altivec_stvx : + Intrinsic<[llvm_void_ty], [llvm_v4i32_ty, llvm_ptr_ty], + [IntrWriteMem]>; + def int_ppc_altivec_stvxl : + Intrinsic<[llvm_void_ty], [llvm_v4i32_ty, llvm_ptr_ty], + [IntrWriteMem]>; + def int_ppc_altivec_stvebx : + Intrinsic<[llvm_void_ty], [llvm_v16i8_ty, llvm_ptr_ty], + [IntrWriteMem]>; + def int_ppc_altivec_stvehx : + Intrinsic<[llvm_void_ty], [llvm_v8i16_ty, llvm_ptr_ty], + [IntrWriteMem]>; + def int_ppc_altivec_stvewx : + Intrinsic<[llvm_void_ty], [llvm_v4i32_ty, llvm_ptr_ty], + [IntrWriteMem]>; + + // Comparisons setting a vector. + def int_ppc_altivec_vcmpbfp : GCCBuiltin<"__builtin_altivec_vcmpbfp">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], + [IntrNoMem]>; + def int_ppc_altivec_vcmpeqfp : GCCBuiltin<"__builtin_altivec_vcmpeqfp">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], + [IntrNoMem]>; + def int_ppc_altivec_vcmpgefp : GCCBuiltin<"__builtin_altivec_vcmpgefp">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], + [IntrNoMem]>; + def int_ppc_altivec_vcmpgtfp : GCCBuiltin<"__builtin_altivec_vcmpgtfp">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], + [IntrNoMem]>; + + def int_ppc_altivec_vcmpequw : GCCBuiltin<"__builtin_altivec_vcmpequw">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem]>; + def int_ppc_altivec_vcmpgtsw : GCCBuiltin<"__builtin_altivec_vcmpgtsw">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem]>; + def int_ppc_altivec_vcmpgtuw : GCCBuiltin<"__builtin_altivec_vcmpgtuw">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem]>; + + def int_ppc_altivec_vcmpequh : GCCBuiltin<"__builtin_altivec_vcmpequh">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], + [IntrNoMem]>; + def int_ppc_altivec_vcmpgtsh : GCCBuiltin<"__builtin_altivec_vcmpgtsh">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], + [IntrNoMem]>; + def int_ppc_altivec_vcmpgtuh : GCCBuiltin<"__builtin_altivec_vcmpgtuh">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], + [IntrNoMem]>; + + def int_ppc_altivec_vcmpequb : GCCBuiltin<"__builtin_altivec_vcmpequb">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], + [IntrNoMem]>; + def int_ppc_altivec_vcmpgtsb : GCCBuiltin<"__builtin_altivec_vcmpgtsb">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], + [IntrNoMem]>; + def int_ppc_altivec_vcmpgtub : GCCBuiltin<"__builtin_altivec_vcmpgtub">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], + [IntrNoMem]>; + + // Predicate Comparisons. The first operand specifies interpretation of CR6. + def int_ppc_altivec_vcmpbfp_p : GCCBuiltin<"__builtin_altivec_vcmpbfp_p">, + Intrinsic<[llvm_i32_ty],[llvm_i32_ty,llvm_v4f32_ty,llvm_v4f32_ty], + [IntrNoMem]>; + def int_ppc_altivec_vcmpeqfp_p : GCCBuiltin<"__builtin_altivec_vcmpeqfp_p">, + Intrinsic<[llvm_i32_ty],[llvm_i32_ty,llvm_v4f32_ty,llvm_v4f32_ty], + [IntrNoMem]>; + def int_ppc_altivec_vcmpgefp_p : GCCBuiltin<"__builtin_altivec_vcmpgefp_p">, + Intrinsic<[llvm_i32_ty],[llvm_i32_ty,llvm_v4f32_ty,llvm_v4f32_ty], + [IntrNoMem]>; + def int_ppc_altivec_vcmpgtfp_p : GCCBuiltin<"__builtin_altivec_vcmpgtfp_p">, + Intrinsic<[llvm_i32_ty],[llvm_i32_ty,llvm_v4f32_ty,llvm_v4f32_ty], + [IntrNoMem]>; + + def int_ppc_altivec_vcmpequw_p : GCCBuiltin<"__builtin_altivec_vcmpequw_p">, + Intrinsic<[llvm_i32_ty],[llvm_i32_ty,llvm_v4i32_ty,llvm_v4i32_ty], + [IntrNoMem]>; + def int_ppc_altivec_vcmpgtsw_p : GCCBuiltin<"__builtin_altivec_vcmpgtsw_p">, + Intrinsic<[llvm_i32_ty],[llvm_i32_ty,llvm_v4i32_ty,llvm_v4i32_ty], + [IntrNoMem]>; + def int_ppc_altivec_vcmpgtuw_p : GCCBuiltin<"__builtin_altivec_vcmpgtuw_p">, + Intrinsic<[llvm_i32_ty],[llvm_i32_ty,llvm_v4i32_ty,llvm_v4i32_ty], + [IntrNoMem]>; + + def int_ppc_altivec_vcmpequh_p : GCCBuiltin<"__builtin_altivec_vcmpequh_p">, + Intrinsic<[llvm_i32_ty],[llvm_i32_ty,llvm_v8i16_ty,llvm_v8i16_ty], + [IntrNoMem]>; + def int_ppc_altivec_vcmpgtsh_p : GCCBuiltin<"__builtin_altivec_vcmpgtsh_p">, + Intrinsic<[llvm_i32_ty],[llvm_i32_ty,llvm_v8i16_ty,llvm_v8i16_ty], + [IntrNoMem]>; + def int_ppc_altivec_vcmpgtuh_p : GCCBuiltin<"__builtin_altivec_vcmpgtuh_p">, + Intrinsic<[llvm_i32_ty],[llvm_i32_ty,llvm_v8i16_ty,llvm_v8i16_ty], + [IntrNoMem]>; + + def int_ppc_altivec_vcmpequb_p : GCCBuiltin<"__builtin_altivec_vcmpequb_p">, + Intrinsic<[llvm_i32_ty],[llvm_i32_ty,llvm_v16i8_ty,llvm_v16i8_ty], + [IntrNoMem]>; + def int_ppc_altivec_vcmpgtsb_p : GCCBuiltin<"__builtin_altivec_vcmpgtsb_p">, + Intrinsic<[llvm_i32_ty],[llvm_i32_ty,llvm_v16i8_ty,llvm_v16i8_ty], + [IntrNoMem]>; + def int_ppc_altivec_vcmpgtub_p : GCCBuiltin<"__builtin_altivec_vcmpgtub_p">, + Intrinsic<[llvm_i32_ty],[llvm_i32_ty,llvm_v16i8_ty,llvm_v16i8_ty], + [IntrNoMem]>; +} + +// Vector average. +def int_ppc_altivec_vavgsb : PowerPC_Vec_BBB_Intrinsic<"vavgsb">; +def int_ppc_altivec_vavgsh : PowerPC_Vec_HHH_Intrinsic<"vavgsh">; +def int_ppc_altivec_vavgsw : PowerPC_Vec_WWW_Intrinsic<"vavgsw">; +def int_ppc_altivec_vavgub : PowerPC_Vec_BBB_Intrinsic<"vavgub">; +def int_ppc_altivec_vavguh : PowerPC_Vec_HHH_Intrinsic<"vavguh">; +def int_ppc_altivec_vavguw : PowerPC_Vec_WWW_Intrinsic<"vavguw">; + +// Vector maximum. +def int_ppc_altivec_vmaxfp : PowerPC_Vec_FFF_Intrinsic<"vmaxfp">; +def int_ppc_altivec_vmaxsb : PowerPC_Vec_BBB_Intrinsic<"vmaxsb">; +def int_ppc_altivec_vmaxsh : PowerPC_Vec_HHH_Intrinsic<"vmaxsh">; +def int_ppc_altivec_vmaxsw : PowerPC_Vec_WWW_Intrinsic<"vmaxsw">; +def int_ppc_altivec_vmaxub : PowerPC_Vec_BBB_Intrinsic<"vmaxub">; +def int_ppc_altivec_vmaxuh : PowerPC_Vec_HHH_Intrinsic<"vmaxuh">; +def int_ppc_altivec_vmaxuw : PowerPC_Vec_WWW_Intrinsic<"vmaxuw">; + +// Vector minimum. +def int_ppc_altivec_vminfp : PowerPC_Vec_FFF_Intrinsic<"vminfp">; +def int_ppc_altivec_vminsb : PowerPC_Vec_BBB_Intrinsic<"vminsb">; +def int_ppc_altivec_vminsh : PowerPC_Vec_HHH_Intrinsic<"vminsh">; +def int_ppc_altivec_vminsw : PowerPC_Vec_WWW_Intrinsic<"vminsw">; +def int_ppc_altivec_vminub : PowerPC_Vec_BBB_Intrinsic<"vminub">; +def int_ppc_altivec_vminuh : PowerPC_Vec_HHH_Intrinsic<"vminuh">; +def int_ppc_altivec_vminuw : PowerPC_Vec_WWW_Intrinsic<"vminuw">; + +// Saturating adds. +def int_ppc_altivec_vaddubs : PowerPC_Vec_BBB_Intrinsic<"vaddubs">; +def int_ppc_altivec_vaddsbs : PowerPC_Vec_BBB_Intrinsic<"vaddsbs">; +def int_ppc_altivec_vadduhs : PowerPC_Vec_HHH_Intrinsic<"vadduhs">; +def int_ppc_altivec_vaddshs : PowerPC_Vec_HHH_Intrinsic<"vaddshs">; +def int_ppc_altivec_vadduws : PowerPC_Vec_WWW_Intrinsic<"vadduws">; +def int_ppc_altivec_vaddsws : PowerPC_Vec_WWW_Intrinsic<"vaddsws">; +def int_ppc_altivec_vaddcuw : PowerPC_Vec_WWW_Intrinsic<"vaddcuw">; + +// Saturating subs. +def int_ppc_altivec_vsububs : PowerPC_Vec_BBB_Intrinsic<"vsububs">; +def int_ppc_altivec_vsubsbs : PowerPC_Vec_BBB_Intrinsic<"vsubsbs">; +def int_ppc_altivec_vsubuhs : PowerPC_Vec_HHH_Intrinsic<"vsubuhs">; +def int_ppc_altivec_vsubshs : PowerPC_Vec_HHH_Intrinsic<"vsubshs">; +def int_ppc_altivec_vsubuws : PowerPC_Vec_WWW_Intrinsic<"vsubuws">; +def int_ppc_altivec_vsubsws : PowerPC_Vec_WWW_Intrinsic<"vsubsws">; +def int_ppc_altivec_vsubcuw : PowerPC_Vec_WWW_Intrinsic<"vsubcuw">; + +let TargetPrefix = "ppc" in { // All PPC intrinsics start with "llvm.ppc.". + // Saturating multiply-adds. + def int_ppc_altivec_vmhaddshs : GCCBuiltin<"__builtin_altivec_vmhaddshs">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, + llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; + def int_ppc_altivec_vmhraddshs : GCCBuiltin<"__builtin_altivec_vmhraddshs">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, + llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; + + def int_ppc_altivec_vmaddfp : GCCBuiltin<"__builtin_altivec_vmaddfp">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, + llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; + def int_ppc_altivec_vnmsubfp : GCCBuiltin<"__builtin_altivec_vnmsubfp">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, + llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; + + // Vector Multiply Sum Intructions. + def int_ppc_altivec_vmsummbm : GCCBuiltin<"__builtin_altivec_vmsummbm">, + Intrinsic<[llvm_v4i32_ty], [llvm_v16i8_ty, llvm_v16i8_ty, + llvm_v4i32_ty], [IntrNoMem]>; + def int_ppc_altivec_vmsumshm : GCCBuiltin<"__builtin_altivec_vmsumshm">, + Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty, + llvm_v4i32_ty], [IntrNoMem]>; + def int_ppc_altivec_vmsumshs : GCCBuiltin<"__builtin_altivec_vmsumshs">, + Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty, + llvm_v4i32_ty], [IntrNoMem]>; + def int_ppc_altivec_vmsumubm : GCCBuiltin<"__builtin_altivec_vmsumubm">, + Intrinsic<[llvm_v4i32_ty], [llvm_v16i8_ty, llvm_v16i8_ty, + llvm_v4i32_ty], [IntrNoMem]>; + def int_ppc_altivec_vmsumuhm : GCCBuiltin<"__builtin_altivec_vmsumuhm">, + Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty, + llvm_v4i32_ty], [IntrNoMem]>; + def int_ppc_altivec_vmsumuhs : GCCBuiltin<"__builtin_altivec_vmsumuhs">, + Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty, + llvm_v4i32_ty], [IntrNoMem]>; + + // Vector Multiply Intructions. + def int_ppc_altivec_vmulesb : GCCBuiltin<"__builtin_altivec_vmulesb">, + Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty], + [IntrNoMem]>; + def int_ppc_altivec_vmulesh : GCCBuiltin<"__builtin_altivec_vmulesh">, + Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty], + [IntrNoMem]>; + def int_ppc_altivec_vmuleub : GCCBuiltin<"__builtin_altivec_vmuleub">, + Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty], + [IntrNoMem]>; + def int_ppc_altivec_vmuleuh : GCCBuiltin<"__builtin_altivec_vmuleuh">, + Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty], + [IntrNoMem]>; + + def int_ppc_altivec_vmulosb : GCCBuiltin<"__builtin_altivec_vmulosb">, + Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty], + [IntrNoMem]>; + def int_ppc_altivec_vmulosh : GCCBuiltin<"__builtin_altivec_vmulosh">, + Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty], + [IntrNoMem]>; + def int_ppc_altivec_vmuloub : GCCBuiltin<"__builtin_altivec_vmuloub">, + Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty], + [IntrNoMem]>; + def int_ppc_altivec_vmulouh : GCCBuiltin<"__builtin_altivec_vmulouh">, + Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty], + [IntrNoMem]>; + + // Vector Sum Intructions. + def int_ppc_altivec_vsumsws : GCCBuiltin<"__builtin_altivec_vsumsws">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem]>; + def int_ppc_altivec_vsum2sws : GCCBuiltin<"__builtin_altivec_vsum2sws">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem]>; + def int_ppc_altivec_vsum4sbs : GCCBuiltin<"__builtin_altivec_vsum4sbs">, + Intrinsic<[llvm_v4i32_ty], [llvm_v16i8_ty, llvm_v4i32_ty], + [IntrNoMem]>; + def int_ppc_altivec_vsum4shs : GCCBuiltin<"__builtin_altivec_vsum4shs">, + Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v4i32_ty], + [IntrNoMem]>; + def int_ppc_altivec_vsum4ubs : GCCBuiltin<"__builtin_altivec_vsum4ubs">, + Intrinsic<[llvm_v4i32_ty], [llvm_v16i8_ty, llvm_v4i32_ty], + [IntrNoMem]>; + + // Other multiplies. + def int_ppc_altivec_vmladduhm : GCCBuiltin<"__builtin_altivec_vmladduhm">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, + llvm_v8i16_ty], [IntrNoMem]>; + + // Packs. + def int_ppc_altivec_vpkpx : GCCBuiltin<"__builtin_altivec_vpkpx">, + Intrinsic<[llvm_v8i16_ty], [llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem]>; + def int_ppc_altivec_vpkshss : GCCBuiltin<"__builtin_altivec_vpkshss">, + Intrinsic<[llvm_v16i8_ty], [llvm_v8i16_ty, llvm_v8i16_ty], + [IntrNoMem]>; + def int_ppc_altivec_vpkshus : GCCBuiltin<"__builtin_altivec_vpkshus">, + Intrinsic<[llvm_v16i8_ty], [llvm_v8i16_ty, llvm_v8i16_ty], + [IntrNoMem]>; + def int_ppc_altivec_vpkswss : GCCBuiltin<"__builtin_altivec_vpkswss">, + Intrinsic<[llvm_v16i8_ty], [llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem]>; + def int_ppc_altivec_vpkswus : GCCBuiltin<"__builtin_altivec_vpkswus">, + Intrinsic<[llvm_v8i16_ty], [llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem]>; + // vpkuhum is lowered to a shuffle. + def int_ppc_altivec_vpkuhus : GCCBuiltin<"__builtin_altivec_vpkuhus">, + Intrinsic<[llvm_v16i8_ty], [llvm_v8i16_ty, llvm_v8i16_ty], + [IntrNoMem]>; + // vpkuwum is lowered to a shuffle. + def int_ppc_altivec_vpkuwus : GCCBuiltin<"__builtin_altivec_vpkuwus">, + Intrinsic<[llvm_v8i16_ty], [llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem]>; + + // Unpacks. + def int_ppc_altivec_vupkhpx : GCCBuiltin<"__builtin_altivec_vupkhpx">, + Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty], [IntrNoMem]>; + def int_ppc_altivec_vupkhsb : GCCBuiltin<"__builtin_altivec_vupkhsb">, + Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty], [IntrNoMem]>; + def int_ppc_altivec_vupkhsh : GCCBuiltin<"__builtin_altivec_vupkhsh">, + Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty], [IntrNoMem]>; + def int_ppc_altivec_vupklpx : GCCBuiltin<"__builtin_altivec_vupklpx">, + Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty], [IntrNoMem]>; + def int_ppc_altivec_vupklsb : GCCBuiltin<"__builtin_altivec_vupklsb">, + Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty], [IntrNoMem]>; + def int_ppc_altivec_vupklsh : GCCBuiltin<"__builtin_altivec_vupklsh">, + Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty], [IntrNoMem]>; + + + // FP <-> integer conversion. + def int_ppc_altivec_vcfsx : GCCBuiltin<"__builtin_altivec_vcfsx">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4i32_ty, llvm_i32_ty], + [IntrNoMem]>; + def int_ppc_altivec_vcfux : GCCBuiltin<"__builtin_altivec_vcfux">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4i32_ty, llvm_i32_ty], + [IntrNoMem]>; + def int_ppc_altivec_vctsxs : GCCBuiltin<"__builtin_altivec_vctsxs">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_i32_ty], + [IntrNoMem]>; + def int_ppc_altivec_vctuxs : GCCBuiltin<"__builtin_altivec_vctuxs">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_i32_ty], + [IntrNoMem]>; + + def int_ppc_altivec_vrfim : GCCBuiltin<"__builtin_altivec_vrfim">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty], [IntrNoMem]>; + def int_ppc_altivec_vrfin : GCCBuiltin<"__builtin_altivec_vrfin">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty], [IntrNoMem]>; + def int_ppc_altivec_vrfip : GCCBuiltin<"__builtin_altivec_vrfip">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty], [IntrNoMem]>; + def int_ppc_altivec_vrfiz : GCCBuiltin<"__builtin_altivec_vrfiz">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty], [IntrNoMem]>; +} + +def int_ppc_altivec_vsl : PowerPC_Vec_WWW_Intrinsic<"vsl">; +def int_ppc_altivec_vslo : PowerPC_Vec_WWW_Intrinsic<"vslo">; + +def int_ppc_altivec_vslb : PowerPC_Vec_BBB_Intrinsic<"vslb">; +def int_ppc_altivec_vslh : PowerPC_Vec_HHH_Intrinsic<"vslh">; +def int_ppc_altivec_vslw : PowerPC_Vec_WWW_Intrinsic<"vslw">; + +// Right Shifts. +def int_ppc_altivec_vsr : PowerPC_Vec_WWW_Intrinsic<"vsr">; +def int_ppc_altivec_vsro : PowerPC_Vec_WWW_Intrinsic<"vsro">; + +def int_ppc_altivec_vsrb : PowerPC_Vec_BBB_Intrinsic<"vsrb">; +def int_ppc_altivec_vsrh : PowerPC_Vec_HHH_Intrinsic<"vsrh">; +def int_ppc_altivec_vsrw : PowerPC_Vec_WWW_Intrinsic<"vsrw">; +def int_ppc_altivec_vsrab : PowerPC_Vec_BBB_Intrinsic<"vsrab">; +def int_ppc_altivec_vsrah : PowerPC_Vec_HHH_Intrinsic<"vsrah">; +def int_ppc_altivec_vsraw : PowerPC_Vec_WWW_Intrinsic<"vsraw">; + +// Rotates. +def int_ppc_altivec_vrlb : PowerPC_Vec_BBB_Intrinsic<"vrlb">; +def int_ppc_altivec_vrlh : PowerPC_Vec_HHH_Intrinsic<"vrlh">; +def int_ppc_altivec_vrlw : PowerPC_Vec_WWW_Intrinsic<"vrlw">; + +let TargetPrefix = "ppc" in { // All PPC intrinsics start with "llvm.ppc.". + // Miscellaneous. + def int_ppc_altivec_lvsl : + Intrinsic<[llvm_v16i8_ty], [llvm_ptr_ty], [IntrNoMem]>; + def int_ppc_altivec_lvsr : + Intrinsic<[llvm_v16i8_ty], [llvm_ptr_ty], [IntrNoMem]>; + + def int_ppc_altivec_vperm : GCCBuiltin<"__builtin_altivec_vperm_4si">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, + llvm_v4i32_ty, llvm_v16i8_ty], [IntrNoMem]>; + def int_ppc_altivec_vsel : GCCBuiltin<"__builtin_altivec_vsel_4si">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, + llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; +} + +def int_ppc_altivec_vexptefp : PowerPC_Vec_FF_Intrinsic<"vexptefp">; +def int_ppc_altivec_vlogefp : PowerPC_Vec_FF_Intrinsic<"vlogefp">; +def int_ppc_altivec_vrefp : PowerPC_Vec_FF_Intrinsic<"vrefp">; +def int_ppc_altivec_vrsqrtefp : PowerPC_Vec_FF_Intrinsic<"vrsqrtefp">; diff --git a/libclamav/c++/llvm/include/llvm/IntrinsicsX86.td b/libclamav/c++/llvm/include/llvm/IntrinsicsX86.td new file mode 100644 index 000000000..2f75ed520 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/IntrinsicsX86.td @@ -0,0 +1,1161 @@ +//===- IntrinsicsX86.td - Defines X86 intrinsics -----------*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines all of the X86-specific intrinsics. +// +//===----------------------------------------------------------------------===// + + +//===----------------------------------------------------------------------===// +// SSE1 + +// Arithmetic ops +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse_add_ss : GCCBuiltin<"__builtin_ia32_addss">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, + llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_sse_sub_ss : GCCBuiltin<"__builtin_ia32_subss">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, + llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_sse_mul_ss : GCCBuiltin<"__builtin_ia32_mulss">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, + llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_sse_div_ss : GCCBuiltin<"__builtin_ia32_divss">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, + llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_sse_sqrt_ss : GCCBuiltin<"__builtin_ia32_sqrtss">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty], + [IntrNoMem]>; + def int_x86_sse_sqrt_ps : GCCBuiltin<"__builtin_ia32_sqrtps">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty], + [IntrNoMem]>; + def int_x86_sse_rcp_ss : GCCBuiltin<"__builtin_ia32_rcpss">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty], + [IntrNoMem]>; + def int_x86_sse_rcp_ps : GCCBuiltin<"__builtin_ia32_rcpps">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty], + [IntrNoMem]>; + def int_x86_sse_rsqrt_ss : GCCBuiltin<"__builtin_ia32_rsqrtss">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty], + [IntrNoMem]>; + def int_x86_sse_rsqrt_ps : GCCBuiltin<"__builtin_ia32_rsqrtps">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty], + [IntrNoMem]>; + def int_x86_sse_min_ss : GCCBuiltin<"__builtin_ia32_minss">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, + llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_sse_min_ps : GCCBuiltin<"__builtin_ia32_minps">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, + llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_sse_max_ss : GCCBuiltin<"__builtin_ia32_maxss">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, + llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_sse_max_ps : GCCBuiltin<"__builtin_ia32_maxps">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, + llvm_v4f32_ty], [IntrNoMem]>; +} + +// Comparison ops +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse_cmp_ss : + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, + llvm_v4f32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_sse_cmp_ps : + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, + llvm_v4f32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_sse_comieq_ss : GCCBuiltin<"__builtin_ia32_comieq">, + Intrinsic<[llvm_i32_ty], [llvm_v4f32_ty, + llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_sse_comilt_ss : GCCBuiltin<"__builtin_ia32_comilt">, + Intrinsic<[llvm_i32_ty], [llvm_v4f32_ty, + llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_sse_comile_ss : GCCBuiltin<"__builtin_ia32_comile">, + Intrinsic<[llvm_i32_ty], [llvm_v4f32_ty, + llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_sse_comigt_ss : GCCBuiltin<"__builtin_ia32_comigt">, + Intrinsic<[llvm_i32_ty], [llvm_v4f32_ty, + llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_sse_comige_ss : GCCBuiltin<"__builtin_ia32_comige">, + Intrinsic<[llvm_i32_ty], [llvm_v4f32_ty, + llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_sse_comineq_ss : GCCBuiltin<"__builtin_ia32_comineq">, + Intrinsic<[llvm_i32_ty], [llvm_v4f32_ty, + llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_sse_ucomieq_ss : GCCBuiltin<"__builtin_ia32_ucomieq">, + Intrinsic<[llvm_i32_ty], [llvm_v4f32_ty, + llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_sse_ucomilt_ss : GCCBuiltin<"__builtin_ia32_ucomilt">, + Intrinsic<[llvm_i32_ty], [llvm_v4f32_ty, + llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_sse_ucomile_ss : GCCBuiltin<"__builtin_ia32_ucomile">, + Intrinsic<[llvm_i32_ty], [llvm_v4f32_ty, + llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_sse_ucomigt_ss : GCCBuiltin<"__builtin_ia32_ucomigt">, + Intrinsic<[llvm_i32_ty], [llvm_v4f32_ty, + llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_sse_ucomige_ss : GCCBuiltin<"__builtin_ia32_ucomige">, + Intrinsic<[llvm_i32_ty], [llvm_v4f32_ty, + llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_sse_ucomineq_ss : GCCBuiltin<"__builtin_ia32_ucomineq">, + Intrinsic<[llvm_i32_ty], [llvm_v4f32_ty, + llvm_v4f32_ty], [IntrNoMem]>; +} + + +// Conversion ops +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse_cvtss2si : GCCBuiltin<"__builtin_ia32_cvtss2si">, + Intrinsic<[llvm_i32_ty], [llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_sse_cvtss2si64 : GCCBuiltin<"__builtin_ia32_cvtss2si64">, + Intrinsic<[llvm_i64_ty], [llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_sse_cvttss2si : GCCBuiltin<"__builtin_ia32_cvttss2si">, + Intrinsic<[llvm_i32_ty], [llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_sse_cvttss2si64 : GCCBuiltin<"__builtin_ia32_cvttss2si64">, + Intrinsic<[llvm_i64_ty], [llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_sse_cvtsi2ss : GCCBuiltin<"__builtin_ia32_cvtsi2ss">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_sse_cvtsi642ss : GCCBuiltin<"__builtin_ia32_cvtsi642ss">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, + llvm_i64_ty], [IntrNoMem]>; + def int_x86_sse_cvtps2pi : GCCBuiltin<"__builtin_ia32_cvtps2pi">, + Intrinsic<[llvm_v2i32_ty], [llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_sse_cvttps2pi: GCCBuiltin<"__builtin_ia32_cvttps2pi">, + Intrinsic<[llvm_v2i32_ty], [llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_sse_cvtpi2ps : GCCBuiltin<"__builtin_ia32_cvtpi2ps">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, + llvm_v2i32_ty], [IntrNoMem]>; +} + +// SIMD load ops +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse_loadu_ps : GCCBuiltin<"__builtin_ia32_loadups">, + Intrinsic<[llvm_v4f32_ty], [llvm_ptr_ty], [IntrReadMem]>; +} + +// SIMD store ops +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse_storeu_ps : GCCBuiltin<"__builtin_ia32_storeups">, + Intrinsic<[llvm_void_ty], [llvm_ptr_ty, + llvm_v4f32_ty], [IntrWriteMem]>; +} + +// Cacheability support ops +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse_movnt_ps : GCCBuiltin<"__builtin_ia32_movntps">, + Intrinsic<[llvm_void_ty], [llvm_ptr_ty, + llvm_v4f32_ty], [IntrWriteMem]>; + def int_x86_sse_sfence : GCCBuiltin<"__builtin_ia32_sfence">, + Intrinsic<[llvm_void_ty], [], [IntrWriteMem]>; +} + +// Control register. +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse_stmxcsr : + Intrinsic<[llvm_void_ty], [llvm_ptr_ty], [IntrWriteMem]>; + def int_x86_sse_ldmxcsr : + Intrinsic<[llvm_void_ty], [llvm_ptr_ty], [IntrWriteMem]>; +} + +// Misc. +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse_movmsk_ps : GCCBuiltin<"__builtin_ia32_movmskps">, + Intrinsic<[llvm_i32_ty], [llvm_v4f32_ty], [IntrNoMem]>; +} + +//===----------------------------------------------------------------------===// +// SSE2 + +// FP arithmetic ops +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse2_add_sd : GCCBuiltin<"__builtin_ia32_addsd">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, + llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_sse2_sub_sd : GCCBuiltin<"__builtin_ia32_subsd">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, + llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_sse2_mul_sd : GCCBuiltin<"__builtin_ia32_mulsd">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, + llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_sse2_div_sd : GCCBuiltin<"__builtin_ia32_divsd">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, + llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_sse2_sqrt_sd : GCCBuiltin<"__builtin_ia32_sqrtsd">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty], + [IntrNoMem]>; + def int_x86_sse2_sqrt_pd : GCCBuiltin<"__builtin_ia32_sqrtpd">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty], + [IntrNoMem]>; + def int_x86_sse2_min_sd : GCCBuiltin<"__builtin_ia32_minsd">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, + llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_sse2_min_pd : GCCBuiltin<"__builtin_ia32_minpd">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, + llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_sse2_max_sd : GCCBuiltin<"__builtin_ia32_maxsd">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, + llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_sse2_max_pd : GCCBuiltin<"__builtin_ia32_maxpd">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, + llvm_v2f64_ty], [IntrNoMem]>; +} + +// FP comparison ops +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse2_cmp_sd : + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, + llvm_v2f64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_sse2_cmp_pd : + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, + llvm_v2f64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_sse2_comieq_sd : GCCBuiltin<"__builtin_ia32_comisdeq">, + Intrinsic<[llvm_i32_ty], [llvm_v2f64_ty, + llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_sse2_comilt_sd : GCCBuiltin<"__builtin_ia32_comisdlt">, + Intrinsic<[llvm_i32_ty], [llvm_v2f64_ty, + llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_sse2_comile_sd : GCCBuiltin<"__builtin_ia32_comisdle">, + Intrinsic<[llvm_i32_ty], [llvm_v2f64_ty, + llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_sse2_comigt_sd : GCCBuiltin<"__builtin_ia32_comisdgt">, + Intrinsic<[llvm_i32_ty], [llvm_v2f64_ty, + llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_sse2_comige_sd : GCCBuiltin<"__builtin_ia32_comisdge">, + Intrinsic<[llvm_i32_ty], [llvm_v2f64_ty, + llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_sse2_comineq_sd : GCCBuiltin<"__builtin_ia32_comisdneq">, + Intrinsic<[llvm_i32_ty], [llvm_v2f64_ty, + llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_sse2_ucomieq_sd : GCCBuiltin<"__builtin_ia32_ucomisdeq">, + Intrinsic<[llvm_i32_ty], [llvm_v2f64_ty, + llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_sse2_ucomilt_sd : GCCBuiltin<"__builtin_ia32_ucomisdlt">, + Intrinsic<[llvm_i32_ty], [llvm_v2f64_ty, + llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_sse2_ucomile_sd : GCCBuiltin<"__builtin_ia32_ucomisdle">, + Intrinsic<[llvm_i32_ty], [llvm_v2f64_ty, + llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_sse2_ucomigt_sd : GCCBuiltin<"__builtin_ia32_ucomisdgt">, + Intrinsic<[llvm_i32_ty], [llvm_v2f64_ty, + llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_sse2_ucomige_sd : GCCBuiltin<"__builtin_ia32_ucomisdge">, + Intrinsic<[llvm_i32_ty], [llvm_v2f64_ty, + llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_sse2_ucomineq_sd : GCCBuiltin<"__builtin_ia32_ucomisdneq">, + Intrinsic<[llvm_i32_ty], [llvm_v2f64_ty, + llvm_v2f64_ty], [IntrNoMem]>; +} + +// Integer arithmetic ops. +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse2_padds_b : GCCBuiltin<"__builtin_ia32_paddsb128">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, + llvm_v16i8_ty], [IntrNoMem, Commutative]>; + def int_x86_sse2_padds_w : GCCBuiltin<"__builtin_ia32_paddsw128">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, + llvm_v8i16_ty], [IntrNoMem, Commutative]>; + def int_x86_sse2_paddus_b : GCCBuiltin<"__builtin_ia32_paddusb128">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, + llvm_v16i8_ty], [IntrNoMem, Commutative]>; + def int_x86_sse2_paddus_w : GCCBuiltin<"__builtin_ia32_paddusw128">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, + llvm_v8i16_ty], [IntrNoMem, Commutative]>; + def int_x86_sse2_psubs_b : GCCBuiltin<"__builtin_ia32_psubsb128">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, + llvm_v16i8_ty], [IntrNoMem]>; + def int_x86_sse2_psubs_w : GCCBuiltin<"__builtin_ia32_psubsw128">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, + llvm_v8i16_ty], [IntrNoMem]>; + def int_x86_sse2_psubus_b : GCCBuiltin<"__builtin_ia32_psubusb128">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, + llvm_v16i8_ty], [IntrNoMem]>; + def int_x86_sse2_psubus_w : GCCBuiltin<"__builtin_ia32_psubusw128">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, + llvm_v8i16_ty], [IntrNoMem]>; + def int_x86_sse2_pmulhu_w : GCCBuiltin<"__builtin_ia32_pmulhuw128">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, + llvm_v8i16_ty], [IntrNoMem, Commutative]>; + def int_x86_sse2_pmulh_w : GCCBuiltin<"__builtin_ia32_pmulhw128">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, + llvm_v8i16_ty], [IntrNoMem, Commutative]>; + def int_x86_sse2_pmulu_dq : GCCBuiltin<"__builtin_ia32_pmuludq128">, + Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty, + llvm_v4i32_ty], [IntrNoMem, Commutative]>; + def int_x86_sse2_pmadd_wd : GCCBuiltin<"__builtin_ia32_pmaddwd128">, + Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, + llvm_v8i16_ty], [IntrNoMem, Commutative]>; + def int_x86_sse2_pavg_b : GCCBuiltin<"__builtin_ia32_pavgb128">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, + llvm_v16i8_ty], [IntrNoMem, Commutative]>; + def int_x86_sse2_pavg_w : GCCBuiltin<"__builtin_ia32_pavgw128">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, + llvm_v8i16_ty], [IntrNoMem, Commutative]>; + def int_x86_sse2_pmaxu_b : GCCBuiltin<"__builtin_ia32_pmaxub128">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, + llvm_v16i8_ty], [IntrNoMem, Commutative]>; + def int_x86_sse2_pmaxs_w : GCCBuiltin<"__builtin_ia32_pmaxsw128">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, + llvm_v8i16_ty], [IntrNoMem, Commutative]>; + def int_x86_sse2_pminu_b : GCCBuiltin<"__builtin_ia32_pminub128">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, + llvm_v16i8_ty], [IntrNoMem, Commutative]>; + def int_x86_sse2_pmins_w : GCCBuiltin<"__builtin_ia32_pminsw128">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, + llvm_v8i16_ty], [IntrNoMem, Commutative]>; + def int_x86_sse2_psad_bw : GCCBuiltin<"__builtin_ia32_psadbw128">, + Intrinsic<[llvm_v2i64_ty], [llvm_v16i8_ty, + llvm_v16i8_ty], [IntrNoMem, Commutative]>; +} + +// Integer shift ops. +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse2_psll_w : GCCBuiltin<"__builtin_ia32_psllw128">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, + llvm_v8i16_ty], [IntrNoMem]>; + def int_x86_sse2_psll_d : GCCBuiltin<"__builtin_ia32_pslld128">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, + llvm_v4i32_ty], [IntrNoMem]>; + def int_x86_sse2_psll_q : GCCBuiltin<"__builtin_ia32_psllq128">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, + llvm_v2i64_ty], [IntrNoMem]>; + def int_x86_sse2_psrl_w : GCCBuiltin<"__builtin_ia32_psrlw128">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, + llvm_v8i16_ty], [IntrNoMem]>; + def int_x86_sse2_psrl_d : GCCBuiltin<"__builtin_ia32_psrld128">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, + llvm_v4i32_ty], [IntrNoMem]>; + def int_x86_sse2_psrl_q : GCCBuiltin<"__builtin_ia32_psrlq128">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, + llvm_v2i64_ty], [IntrNoMem]>; + def int_x86_sse2_psra_w : GCCBuiltin<"__builtin_ia32_psraw128">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, + llvm_v8i16_ty], [IntrNoMem]>; + def int_x86_sse2_psra_d : GCCBuiltin<"__builtin_ia32_psrad128">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, + llvm_v4i32_ty], [IntrNoMem]>; + + def int_x86_sse2_pslli_w : GCCBuiltin<"__builtin_ia32_psllwi128">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_sse2_pslli_d : GCCBuiltin<"__builtin_ia32_pslldi128">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_sse2_pslli_q : GCCBuiltin<"__builtin_ia32_psllqi128">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_sse2_psrli_w : GCCBuiltin<"__builtin_ia32_psrlwi128">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_sse2_psrli_d : GCCBuiltin<"__builtin_ia32_psrldi128">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_sse2_psrli_q : GCCBuiltin<"__builtin_ia32_psrlqi128">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_sse2_psrai_w : GCCBuiltin<"__builtin_ia32_psrawi128">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_sse2_psrai_d : GCCBuiltin<"__builtin_ia32_psradi128">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, + llvm_i32_ty], [IntrNoMem]>; + + def int_x86_sse2_psll_dq : GCCBuiltin<"__builtin_ia32_pslldqi128">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_sse2_psrl_dq : GCCBuiltin<"__builtin_ia32_psrldqi128">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_sse2_psll_dq_bs : GCCBuiltin<"__builtin_ia32_pslldqi128_byteshift">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_sse2_psrl_dq_bs : GCCBuiltin<"__builtin_ia32_psrldqi128_byteshift">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, + llvm_i32_ty], [IntrNoMem]>; +} + +// Integer comparison ops +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse2_pcmpeq_b : GCCBuiltin<"__builtin_ia32_pcmpeqb128">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, + llvm_v16i8_ty], [IntrNoMem]>; + def int_x86_sse2_pcmpeq_w : GCCBuiltin<"__builtin_ia32_pcmpeqw128">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, + llvm_v8i16_ty], [IntrNoMem]>; + def int_x86_sse2_pcmpeq_d : GCCBuiltin<"__builtin_ia32_pcmpeqd128">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, + llvm_v4i32_ty], [IntrNoMem]>; + def int_x86_sse2_pcmpgt_b : GCCBuiltin<"__builtin_ia32_pcmpgtb128">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, + llvm_v16i8_ty], [IntrNoMem]>; + def int_x86_sse2_pcmpgt_w : GCCBuiltin<"__builtin_ia32_pcmpgtw128">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, + llvm_v8i16_ty], [IntrNoMem]>; + def int_x86_sse2_pcmpgt_d : GCCBuiltin<"__builtin_ia32_pcmpgtd128">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, + llvm_v4i32_ty], [IntrNoMem]>; +} + +// Conversion ops +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse2_cvtdq2pd : GCCBuiltin<"__builtin_ia32_cvtdq2pd">, + Intrinsic<[llvm_v2f64_ty], [llvm_v4i32_ty], [IntrNoMem]>; + def int_x86_sse2_cvtdq2ps : GCCBuiltin<"__builtin_ia32_cvtdq2ps">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4i32_ty], [IntrNoMem]>; + def int_x86_sse2_cvtpd2dq : GCCBuiltin<"__builtin_ia32_cvtpd2dq">, + Intrinsic<[llvm_v4i32_ty], [llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_sse2_cvttpd2dq : GCCBuiltin<"__builtin_ia32_cvttpd2dq">, + Intrinsic<[llvm_v4i32_ty], [llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_sse2_cvtpd2ps : GCCBuiltin<"__builtin_ia32_cvtpd2ps">, + Intrinsic<[llvm_v4f32_ty], [llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_sse2_cvtps2dq : GCCBuiltin<"__builtin_ia32_cvtps2dq">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_sse2_cvttps2dq : GCCBuiltin<"__builtin_ia32_cvttps2dq">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_sse2_cvtps2pd : GCCBuiltin<"__builtin_ia32_cvtps2pd">, + Intrinsic<[llvm_v2f64_ty], [llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_sse2_cvtsd2si : GCCBuiltin<"__builtin_ia32_cvtsd2si">, + Intrinsic<[llvm_i32_ty], [llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_sse2_cvtsd2si64 : GCCBuiltin<"__builtin_ia32_cvtsd2si64">, + Intrinsic<[llvm_i64_ty], [llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_sse2_cvttsd2si : GCCBuiltin<"__builtin_ia32_cvttsd2si">, + Intrinsic<[llvm_i32_ty], [llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_sse2_cvttsd2si64 : GCCBuiltin<"__builtin_ia32_cvttsd2si64">, + Intrinsic<[llvm_i64_ty], [llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_sse2_cvtsi2sd : GCCBuiltin<"__builtin_ia32_cvtsi2sd">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_sse2_cvtsi642sd : GCCBuiltin<"__builtin_ia32_cvtsi642sd">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, + llvm_i64_ty], [IntrNoMem]>; + def int_x86_sse2_cvtsd2ss : GCCBuiltin<"__builtin_ia32_cvtsd2ss">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, + llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_sse2_cvtss2sd : GCCBuiltin<"__builtin_ia32_cvtss2sd">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, + llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_sse_cvtpd2pi : GCCBuiltin<"__builtin_ia32_cvtpd2pi">, + Intrinsic<[llvm_v2i32_ty], [llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_sse_cvttpd2pi: GCCBuiltin<"__builtin_ia32_cvttpd2pi">, + Intrinsic<[llvm_v2i32_ty], [llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_sse_cvtpi2pd : GCCBuiltin<"__builtin_ia32_cvtpi2pd">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2i32_ty], [IntrNoMem]>; +} + +// SIMD load ops +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse2_loadu_pd : GCCBuiltin<"__builtin_ia32_loadupd">, + Intrinsic<[llvm_v2f64_ty], [llvm_ptr_ty], [IntrReadMem]>; + def int_x86_sse2_loadu_dq : GCCBuiltin<"__builtin_ia32_loaddqu">, + Intrinsic<[llvm_v16i8_ty], [llvm_ptr_ty], [IntrReadMem]>; +} + +// SIMD store ops +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse2_storeu_pd : GCCBuiltin<"__builtin_ia32_storeupd">, + Intrinsic<[llvm_void_ty], [llvm_ptr_ty, + llvm_v2f64_ty], [IntrWriteMem]>; + def int_x86_sse2_storeu_dq : GCCBuiltin<"__builtin_ia32_storedqu">, + Intrinsic<[llvm_void_ty], [llvm_ptr_ty, + llvm_v16i8_ty], [IntrWriteMem]>; + def int_x86_sse2_storel_dq : GCCBuiltin<"__builtin_ia32_storelv4si">, + Intrinsic<[llvm_void_ty], [llvm_ptr_ty, + llvm_v4i32_ty], [IntrWriteMem]>; +} + +// Cacheability support ops +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse2_movnt_dq : GCCBuiltin<"__builtin_ia32_movntdq">, + Intrinsic<[llvm_void_ty], [llvm_ptr_ty, + llvm_v2i64_ty], [IntrWriteMem]>; + def int_x86_sse2_movnt_pd : GCCBuiltin<"__builtin_ia32_movntpd">, + Intrinsic<[llvm_void_ty], [llvm_ptr_ty, + llvm_v2f64_ty], [IntrWriteMem]>; + def int_x86_sse2_movnt_i : GCCBuiltin<"__builtin_ia32_movnti">, + Intrinsic<[llvm_void_ty], [llvm_ptr_ty, + llvm_i32_ty], [IntrWriteMem]>; +} + +// Misc. +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse2_packsswb_128 : GCCBuiltin<"__builtin_ia32_packsswb128">, + Intrinsic<[llvm_v16i8_ty], [llvm_v8i16_ty, + llvm_v8i16_ty], [IntrNoMem]>; + def int_x86_sse2_packssdw_128 : GCCBuiltin<"__builtin_ia32_packssdw128">, + Intrinsic<[llvm_v8i16_ty], [llvm_v4i32_ty, + llvm_v4i32_ty], [IntrNoMem]>; + def int_x86_sse2_packuswb_128 : GCCBuiltin<"__builtin_ia32_packuswb128">, + Intrinsic<[llvm_v16i8_ty], [llvm_v8i16_ty, + llvm_v8i16_ty], [IntrNoMem]>; + def int_x86_sse2_movmsk_pd : GCCBuiltin<"__builtin_ia32_movmskpd">, + Intrinsic<[llvm_i32_ty], [llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_sse2_pmovmskb_128 : GCCBuiltin<"__builtin_ia32_pmovmskb128">, + Intrinsic<[llvm_i32_ty], [llvm_v16i8_ty], [IntrNoMem]>; + def int_x86_sse2_maskmov_dqu : GCCBuiltin<"__builtin_ia32_maskmovdqu">, + Intrinsic<[llvm_void_ty], [llvm_v16i8_ty, + llvm_v16i8_ty, llvm_ptr_ty], [IntrWriteMem]>; + def int_x86_sse2_clflush : GCCBuiltin<"__builtin_ia32_clflush">, + Intrinsic<[llvm_void_ty], [llvm_ptr_ty], [IntrWriteMem]>; + def int_x86_sse2_lfence : GCCBuiltin<"__builtin_ia32_lfence">, + Intrinsic<[llvm_void_ty], [], [IntrWriteMem]>; + def int_x86_sse2_mfence : GCCBuiltin<"__builtin_ia32_mfence">, + Intrinsic<[llvm_void_ty], [], [IntrWriteMem]>; +} + +//===----------------------------------------------------------------------===// +// SSE3 + +// Addition / subtraction ops. +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse3_addsub_ps : GCCBuiltin<"__builtin_ia32_addsubps">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, + llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_sse3_addsub_pd : GCCBuiltin<"__builtin_ia32_addsubpd">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, + llvm_v2f64_ty], [IntrNoMem]>; +} + +// Horizontal ops. +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse3_hadd_ps : GCCBuiltin<"__builtin_ia32_haddps">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, + llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_sse3_hadd_pd : GCCBuiltin<"__builtin_ia32_haddpd">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, + llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_sse3_hsub_ps : GCCBuiltin<"__builtin_ia32_hsubps">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, + llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_sse3_hsub_pd : GCCBuiltin<"__builtin_ia32_hsubpd">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, + llvm_v2f64_ty], [IntrNoMem]>; +} + +// Specialized unaligned load. +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse3_ldu_dq : GCCBuiltin<"__builtin_ia32_lddqu">, + Intrinsic<[llvm_v16i8_ty], [llvm_ptr_ty], [IntrReadMem]>; +} + +// Thread synchronization ops. +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse3_monitor : GCCBuiltin<"__builtin_ia32_monitor">, + Intrinsic<[llvm_void_ty], [llvm_ptr_ty, + llvm_i32_ty, llvm_i32_ty], [IntrWriteMem]>; + def int_x86_sse3_mwait : GCCBuiltin<"__builtin_ia32_mwait">, + Intrinsic<[llvm_void_ty], [llvm_i32_ty, + llvm_i32_ty], [IntrWriteMem]>; +} + +//===----------------------------------------------------------------------===// +// SSSE3 + +// Horizontal arithmetic ops +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_ssse3_phadd_w : GCCBuiltin<"__builtin_ia32_phaddw">, + Intrinsic<[llvm_v4i16_ty], [llvm_v4i16_ty, + llvm_v4i16_ty], [IntrNoMem]>; + def int_x86_ssse3_phadd_w_128 : GCCBuiltin<"__builtin_ia32_phaddw128">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, + llvm_v8i16_ty], [IntrNoMem]>; + + def int_x86_ssse3_phadd_d : GCCBuiltin<"__builtin_ia32_phaddd">, + Intrinsic<[llvm_v2i32_ty], [llvm_v2i32_ty, + llvm_v2i32_ty], [IntrNoMem]>; + def int_x86_ssse3_phadd_d_128 : GCCBuiltin<"__builtin_ia32_phaddd128">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, + llvm_v4i32_ty], [IntrNoMem]>; + + def int_x86_ssse3_phadd_sw : GCCBuiltin<"__builtin_ia32_phaddsw">, + Intrinsic<[llvm_v4i16_ty], [llvm_v4i16_ty, + llvm_v4i16_ty], [IntrNoMem]>; + def int_x86_ssse3_phadd_sw_128 : GCCBuiltin<"__builtin_ia32_phaddsw128">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, + llvm_v4i32_ty], [IntrNoMem]>; + + def int_x86_ssse3_phsub_w : GCCBuiltin<"__builtin_ia32_phsubw">, + Intrinsic<[llvm_v4i16_ty], [llvm_v4i16_ty, + llvm_v4i16_ty], [IntrNoMem]>; + def int_x86_ssse3_phsub_w_128 : GCCBuiltin<"__builtin_ia32_phsubw128">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, + llvm_v8i16_ty], [IntrNoMem]>; + + def int_x86_ssse3_phsub_d : GCCBuiltin<"__builtin_ia32_phsubd">, + Intrinsic<[llvm_v2i32_ty], [llvm_v2i32_ty, + llvm_v2i32_ty], [IntrNoMem]>; + def int_x86_ssse3_phsub_d_128 : GCCBuiltin<"__builtin_ia32_phsubd128">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, + llvm_v4i32_ty], [IntrNoMem]>; + + def int_x86_ssse3_phsub_sw : GCCBuiltin<"__builtin_ia32_phsubsw">, + Intrinsic<[llvm_v4i16_ty], [llvm_v4i16_ty, + llvm_v4i16_ty], [IntrNoMem]>; + def int_x86_ssse3_phsub_sw_128 : GCCBuiltin<"__builtin_ia32_phsubsw128">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, + llvm_v8i16_ty], [IntrNoMem]>; + + def int_x86_ssse3_pmadd_ub_sw : GCCBuiltin<"__builtin_ia32_pmaddubsw">, + Intrinsic<[llvm_v4i16_ty], [llvm_v4i16_ty, + llvm_v4i16_ty], [IntrNoMem]>; + def int_x86_ssse3_pmadd_ub_sw_128 : GCCBuiltin<"__builtin_ia32_pmaddubsw128">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, + llvm_v8i16_ty], [IntrNoMem]>; +} + +// Packed multiply high with round and scale +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_ssse3_pmul_hr_sw : GCCBuiltin<"__builtin_ia32_pmulhrsw">, + Intrinsic<[llvm_v4i16_ty], [llvm_v4i16_ty, + llvm_v4i16_ty], [IntrNoMem, Commutative]>; + def int_x86_ssse3_pmul_hr_sw_128 : GCCBuiltin<"__builtin_ia32_pmulhrsw128">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, + llvm_v8i16_ty], [IntrNoMem, Commutative]>; +} + +// Shuffle ops +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_ssse3_pshuf_b : GCCBuiltin<"__builtin_ia32_pshufb">, + Intrinsic<[llvm_v8i8_ty], [llvm_v8i8_ty, + llvm_v8i8_ty], [IntrNoMem]>; + def int_x86_ssse3_pshuf_b_128 : GCCBuiltin<"__builtin_ia32_pshufb128">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, + llvm_v16i8_ty], [IntrNoMem]>; +} + +// Sign ops +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_ssse3_psign_b : GCCBuiltin<"__builtin_ia32_psignb">, + Intrinsic<[llvm_v8i8_ty], [llvm_v8i8_ty, + llvm_v8i8_ty], [IntrNoMem]>; + def int_x86_ssse3_psign_b_128 : GCCBuiltin<"__builtin_ia32_psignb128">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, + llvm_v16i8_ty], [IntrNoMem]>; + + def int_x86_ssse3_psign_w : GCCBuiltin<"__builtin_ia32_psignw">, + Intrinsic<[llvm_v4i16_ty], [llvm_v4i16_ty, + llvm_v4i16_ty], [IntrNoMem]>; + def int_x86_ssse3_psign_w_128 : GCCBuiltin<"__builtin_ia32_psignw128">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, + llvm_v8i16_ty], [IntrNoMem]>; + + def int_x86_ssse3_psign_d : GCCBuiltin<"__builtin_ia32_psignd">, + Intrinsic<[llvm_v2i32_ty], [llvm_v2i32_ty, + llvm_v2i32_ty], [IntrNoMem]>; + def int_x86_ssse3_psign_d_128 : GCCBuiltin<"__builtin_ia32_psignd128">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, + llvm_v4i32_ty], [IntrNoMem]>; +} + +// Absolute value ops +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_ssse3_pabs_b : GCCBuiltin<"__builtin_ia32_pabsb">, + Intrinsic<[llvm_v8i8_ty], [llvm_v8i8_ty], [IntrNoMem]>; + def int_x86_ssse3_pabs_b_128 : GCCBuiltin<"__builtin_ia32_pabsb128">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty], [IntrNoMem]>; + + def int_x86_ssse3_pabs_w : GCCBuiltin<"__builtin_ia32_pabsw">, + Intrinsic<[llvm_v4i16_ty], [llvm_v4i16_ty], [IntrNoMem]>; + def int_x86_ssse3_pabs_w_128 : GCCBuiltin<"__builtin_ia32_pabsw128">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty], [IntrNoMem]>; + + def int_x86_ssse3_pabs_d : GCCBuiltin<"__builtin_ia32_pabsd">, + Intrinsic<[llvm_v2i32_ty], [llvm_v2i32_ty], [IntrNoMem]>; + def int_x86_ssse3_pabs_d_128 : GCCBuiltin<"__builtin_ia32_pabsd128">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty], [IntrNoMem]>; +} + +// Align ops +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_ssse3_palign_r : GCCBuiltin<"__builtin_ia32_palignr">, + Intrinsic<[llvm_v1i64_ty], [llvm_v1i64_ty, + llvm_v1i64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_ssse3_palign_r_128 : GCCBuiltin<"__builtin_ia32_palignr128">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, + llvm_v2i64_ty, llvm_i8_ty], [IntrNoMem]>; +} + +//===----------------------------------------------------------------------===// +// SSE4.1 + +// FP rounding ops +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse41_round_ss : GCCBuiltin<"__builtin_ia32_roundss">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_sse41_round_ps : GCCBuiltin<"__builtin_ia32_roundps">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_sse41_round_sd : GCCBuiltin<"__builtin_ia32_roundsd">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_sse41_round_pd : GCCBuiltin<"__builtin_ia32_roundpd">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, + llvm_i32_ty], [IntrNoMem]>; +} + +// Vector sign and zero extend +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse41_pmovsxbd : GCCBuiltin<"__builtin_ia32_pmovsxbd128">, + Intrinsic<[llvm_v4i32_ty], [llvm_v16i8_ty], + [IntrNoMem]>; + def int_x86_sse41_pmovsxbq : GCCBuiltin<"__builtin_ia32_pmovsxbq128">, + Intrinsic<[llvm_v2i64_ty], [llvm_v16i8_ty], + [IntrNoMem]>; + def int_x86_sse41_pmovsxbw : GCCBuiltin<"__builtin_ia32_pmovsxbw128">, + Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty], + [IntrNoMem]>; + def int_x86_sse41_pmovsxdq : GCCBuiltin<"__builtin_ia32_pmovsxdq128">, + Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty], + [IntrNoMem]>; + def int_x86_sse41_pmovsxwd : GCCBuiltin<"__builtin_ia32_pmovsxwd128">, + Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty], + [IntrNoMem]>; + def int_x86_sse41_pmovsxwq : GCCBuiltin<"__builtin_ia32_pmovsxwq128">, + Intrinsic<[llvm_v2i64_ty], [llvm_v8i16_ty], + [IntrNoMem]>; + def int_x86_sse41_pmovzxbd : GCCBuiltin<"__builtin_ia32_pmovzxbd128">, + Intrinsic<[llvm_v4i32_ty], [llvm_v16i8_ty], + [IntrNoMem]>; + def int_x86_sse41_pmovzxbq : GCCBuiltin<"__builtin_ia32_pmovzxbq128">, + Intrinsic<[llvm_v2i64_ty], [llvm_v16i8_ty], + [IntrNoMem]>; + def int_x86_sse41_pmovzxbw : GCCBuiltin<"__builtin_ia32_pmovzxbw128">, + Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty], + [IntrNoMem]>; + def int_x86_sse41_pmovzxdq : GCCBuiltin<"__builtin_ia32_pmovzxdq128">, + Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty], + [IntrNoMem]>; + def int_x86_sse41_pmovzxwd : GCCBuiltin<"__builtin_ia32_pmovzxwd128">, + Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty], + [IntrNoMem]>; + def int_x86_sse41_pmovzxwq : GCCBuiltin<"__builtin_ia32_pmovzxwq128">, + Intrinsic<[llvm_v2i64_ty], [llvm_v8i16_ty], + [IntrNoMem]>; +} + +// Vector min element +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse41_phminposuw : GCCBuiltin<"__builtin_ia32_phminposuw128">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty], + [IntrNoMem]>; +} + +// Vector compare, min, max +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse41_pcmpeqq : GCCBuiltin<"__builtin_ia32_pcmpeqq">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], + [IntrNoMem, Commutative]>; + def int_x86_sse42_pcmpgtq : GCCBuiltin<"__builtin_ia32_pcmpgtq">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], + [IntrNoMem]>; + def int_x86_sse41_pmaxsb : GCCBuiltin<"__builtin_ia32_pmaxsb128">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], + [IntrNoMem, Commutative]>; + def int_x86_sse41_pmaxsd : GCCBuiltin<"__builtin_ia32_pmaxsd128">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem, Commutative]>; + def int_x86_sse41_pmaxud : GCCBuiltin<"__builtin_ia32_pmaxud128">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem, Commutative]>; + def int_x86_sse41_pmaxuw : GCCBuiltin<"__builtin_ia32_pmaxuw128">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], + [IntrNoMem, Commutative]>; + def int_x86_sse41_pminsb : GCCBuiltin<"__builtin_ia32_pminsb128">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], + [IntrNoMem, Commutative]>; + def int_x86_sse41_pminsd : GCCBuiltin<"__builtin_ia32_pminsd128">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem, Commutative]>; + def int_x86_sse41_pminud : GCCBuiltin<"__builtin_ia32_pminud128">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem, Commutative]>; + def int_x86_sse41_pminuw : GCCBuiltin<"__builtin_ia32_pminuw128">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], + [IntrNoMem, Commutative]>; +} + +// Vector pack +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse41_packusdw : GCCBuiltin<"__builtin_ia32_packusdw128">, + Intrinsic<[llvm_v8i16_ty], [llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem]>; +} + +// Vector multiply +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse41_pmuldq : GCCBuiltin<"__builtin_ia32_pmuldq128">, + Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem, Commutative]>; + def int_x86_sse41_pmulld : GCCBuiltin<"__builtin_ia32_pmulld128">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem, Commutative]>; +} + +// Vector extract +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse41_pextrb : + Intrinsic<[llvm_i32_ty], [llvm_v16i8_ty, llvm_i32_ty], + [IntrNoMem]>; + def int_x86_sse41_pextrd : + Intrinsic<[llvm_i32_ty], [llvm_v4i32_ty, llvm_i32_ty], + [IntrNoMem]>; + def int_x86_sse41_pextrq : + Intrinsic<[llvm_i64_ty], [llvm_v2i64_ty, llvm_i32_ty], + [IntrNoMem]>; + def int_x86_sse41_extractps : GCCBuiltin<"__builtin_ia32_extractps128">, + Intrinsic<[llvm_i32_ty], [llvm_v4f32_ty, llvm_i32_ty], + [IntrNoMem]>; +} + +// Vector insert +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse41_insertps : GCCBuiltin<"__builtin_ia32_insertps128">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty,llvm_i32_ty], + [IntrNoMem]>; +} + +// Vector blend +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse41_pblendvb : GCCBuiltin<"__builtin_ia32_pblendvb128">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty,llvm_v16i8_ty], + [IntrNoMem]>; + def int_x86_sse41_pblendw : GCCBuiltin<"__builtin_ia32_pblendw128">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_i32_ty], + [IntrNoMem]>; + def int_x86_sse41_blendpd : GCCBuiltin<"__builtin_ia32_blendpd">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, llvm_i32_ty], + [IntrNoMem]>; + def int_x86_sse41_blendps : GCCBuiltin<"__builtin_ia32_blendps">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_i32_ty], + [IntrNoMem]>; + def int_x86_sse41_blendvpd : GCCBuiltin<"__builtin_ia32_blendvpd">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty,llvm_v2f64_ty], + [IntrNoMem]>; + def int_x86_sse41_blendvps : GCCBuiltin<"__builtin_ia32_blendvps">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty,llvm_v4f32_ty], + [IntrNoMem]>; +} + +// Vector dot product +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse41_dppd : GCCBuiltin<"__builtin_ia32_dppd">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty,llvm_i32_ty], + [IntrNoMem, Commutative]>; + def int_x86_sse41_dpps : GCCBuiltin<"__builtin_ia32_dpps">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty,llvm_i32_ty], + [IntrNoMem, Commutative]>; +} + +// Vector sum of absolute differences +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse41_mpsadbw : GCCBuiltin<"__builtin_ia32_mpsadbw128">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty,llvm_i32_ty], + [IntrNoMem, Commutative]>; +} + +// Cacheability support ops +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse41_movntdqa : GCCBuiltin<"__builtin_ia32_movntdqa">, + Intrinsic<[llvm_v2i64_ty], [llvm_ptr_ty], [IntrReadMem]>; +} + +// Test instruction with bitwise comparison. +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse41_ptestz : GCCBuiltin<"__builtin_ia32_ptestz128">, + Intrinsic<[llvm_i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], + [IntrNoMem]>; + def int_x86_sse41_ptestc : GCCBuiltin<"__builtin_ia32_ptestc128">, + Intrinsic<[llvm_i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], + [IntrNoMem]>; + def int_x86_sse41_ptestnzc : GCCBuiltin<"__builtin_ia32_ptestnzc128">, + Intrinsic<[llvm_i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], + [IntrNoMem]>; +} + +//===----------------------------------------------------------------------===// +// SSE4.2 + +// Miscellaneous +// CRC Instruction +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse42_crc32_8 : GCCBuiltin<"__builtin_ia32_crc32qi">, + Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_sse42_crc32_16 : GCCBuiltin<"__builtin_ia32_crc32hi">, + Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i16_ty], + [IntrNoMem]>; + def int_x86_sse42_crc32_32 : GCCBuiltin<"__builtin_ia32_crc32si">, + Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], + [IntrNoMem]>; + def int_x86_sse42_crc32_64 : GCCBuiltin<"__builtin_ia32_crc32di">, + Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i64_ty], + [IntrNoMem]>; +} + +// String/text processing ops. +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse42_pcmpistrm128 : GCCBuiltin<"__builtin_ia32_pcmpistrm128">, + Intrinsic<[llvm_v16i8_ty], + [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_sse42_pcmpistri128 : GCCBuiltin<"__builtin_ia32_pcmpistri128">, + Intrinsic<[llvm_i32_ty], + [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_sse42_pcmpistria128 : GCCBuiltin<"__builtin_ia32_pcmpistria128">, + Intrinsic<[llvm_i32_ty], + [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_sse42_pcmpistric128 : GCCBuiltin<"__builtin_ia32_pcmpistric128">, + Intrinsic<[llvm_i32_ty], + [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_sse42_pcmpistrio128 : GCCBuiltin<"__builtin_ia32_pcmpistrio128">, + Intrinsic<[llvm_i32_ty], + [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_sse42_pcmpistris128 : GCCBuiltin<"__builtin_ia32_pcmpistris128">, + Intrinsic<[llvm_i32_ty], + [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_sse42_pcmpistriz128 : GCCBuiltin<"__builtin_ia32_pcmpistriz128">, + Intrinsic<[llvm_i32_ty], + [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_sse42_pcmpestrm128 : GCCBuiltin<"__builtin_ia32_pcmpestrm128">, + Intrinsic<[llvm_v16i8_ty], + [llvm_v16i8_ty, llvm_i32_ty, llvm_v16i8_ty, llvm_i32_ty, + llvm_i8_ty], + [IntrNoMem]>; + def int_x86_sse42_pcmpestri128 : GCCBuiltin<"__builtin_ia32_pcmpestri128">, + Intrinsic<[llvm_i32_ty], + [llvm_v16i8_ty, llvm_i32_ty, llvm_v16i8_ty, llvm_i32_ty, + llvm_i8_ty], + [IntrNoMem]>; + def int_x86_sse42_pcmpestria128 : GCCBuiltin<"__builtin_ia32_pcmpestria128">, + Intrinsic<[llvm_i32_ty], + [llvm_v16i8_ty, llvm_i32_ty, llvm_v16i8_ty, llvm_i32_ty, + llvm_i8_ty], + [IntrNoMem]>; + def int_x86_sse42_pcmpestric128 : GCCBuiltin<"__builtin_ia32_pcmpestric128">, + Intrinsic<[llvm_i32_ty], + [llvm_v16i8_ty, llvm_i32_ty, llvm_v16i8_ty, llvm_i32_ty, + llvm_i8_ty], + [IntrNoMem]>; + def int_x86_sse42_pcmpestrio128 : GCCBuiltin<"__builtin_ia32_pcmpestrio128">, + Intrinsic<[llvm_i32_ty], + [llvm_v16i8_ty, llvm_i32_ty, llvm_v16i8_ty, llvm_i32_ty, + llvm_i8_ty], + [IntrNoMem]>; + def int_x86_sse42_pcmpestris128 : GCCBuiltin<"__builtin_ia32_pcmpestris128">, + Intrinsic<[llvm_i32_ty], + [llvm_v16i8_ty, llvm_i32_ty, llvm_v16i8_ty, llvm_i32_ty, + llvm_i8_ty], + [IntrNoMem]>; + def int_x86_sse42_pcmpestriz128 : GCCBuiltin<"__builtin_ia32_pcmpestriz128">, + Intrinsic<[llvm_i32_ty], + [llvm_v16i8_ty, llvm_i32_ty, llvm_v16i8_ty, llvm_i32_ty, + llvm_i8_ty], + [IntrNoMem]>; +} + +//===----------------------------------------------------------------------===// +// MMX + +// Empty MMX state op. +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_mmx_emms : GCCBuiltin<"__builtin_ia32_emms">, + Intrinsic<[llvm_void_ty], [], [IntrWriteMem]>; + def int_x86_mmx_femms : GCCBuiltin<"__builtin_ia32_femms">, + Intrinsic<[llvm_void_ty], [], [IntrWriteMem]>; +} + +// Integer arithmetic ops. +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + // Addition + def int_x86_mmx_padds_b : GCCBuiltin<"__builtin_ia32_paddsb">, + Intrinsic<[llvm_v8i8_ty], [llvm_v8i8_ty, + llvm_v8i8_ty], [IntrNoMem, Commutative]>; + def int_x86_mmx_padds_w : GCCBuiltin<"__builtin_ia32_paddsw">, + Intrinsic<[llvm_v4i16_ty], [llvm_v4i16_ty, + llvm_v4i16_ty], [IntrNoMem, Commutative]>; + + def int_x86_mmx_paddus_b : GCCBuiltin<"__builtin_ia32_paddusb">, + Intrinsic<[llvm_v8i8_ty], [llvm_v8i8_ty, + llvm_v8i8_ty], [IntrNoMem, Commutative]>; + def int_x86_mmx_paddus_w : GCCBuiltin<"__builtin_ia32_paddusw">, + Intrinsic<[llvm_v4i16_ty], [llvm_v4i16_ty, + llvm_v4i16_ty], [IntrNoMem, Commutative]>; + + // Subtraction + def int_x86_mmx_psubs_b : GCCBuiltin<"__builtin_ia32_psubsb">, + Intrinsic<[llvm_v8i8_ty], [llvm_v8i8_ty, + llvm_v8i8_ty], [IntrNoMem]>; + def int_x86_mmx_psubs_w : GCCBuiltin<"__builtin_ia32_psubsw">, + Intrinsic<[llvm_v4i16_ty], [llvm_v4i16_ty, + llvm_v4i16_ty], [IntrNoMem]>; + + def int_x86_mmx_psubus_b : GCCBuiltin<"__builtin_ia32_psubusb">, + Intrinsic<[llvm_v8i8_ty], [llvm_v8i8_ty, + llvm_v8i8_ty], [IntrNoMem]>; + def int_x86_mmx_psubus_w : GCCBuiltin<"__builtin_ia32_psubusw">, + Intrinsic<[llvm_v4i16_ty], [llvm_v4i16_ty, + llvm_v4i16_ty], [IntrNoMem]>; + + // Multiplication + def int_x86_mmx_pmulh_w : GCCBuiltin<"__builtin_ia32_pmulhw">, + Intrinsic<[llvm_v4i16_ty], [llvm_v4i16_ty, + llvm_v4i16_ty], [IntrNoMem, Commutative]>; + def int_x86_mmx_pmulhu_w : GCCBuiltin<"__builtin_ia32_pmulhuw">, + Intrinsic<[llvm_v4i16_ty], [llvm_v4i16_ty, + llvm_v4i16_ty], [IntrNoMem, Commutative]>; + def int_x86_mmx_pmulu_dq : GCCBuiltin<"__builtin_ia32_pmuludq">, + Intrinsic<[llvm_v2i32_ty], [llvm_v2i32_ty, + llvm_v2i32_ty], [IntrNoMem, Commutative]>; + def int_x86_mmx_pmadd_wd : GCCBuiltin<"__builtin_ia32_pmaddwd">, + Intrinsic<[llvm_v2i32_ty], [llvm_v4i16_ty, + llvm_v4i16_ty], [IntrNoMem, Commutative]>; + + // Averages + def int_x86_mmx_pavg_b : GCCBuiltin<"__builtin_ia32_pavgb">, + Intrinsic<[llvm_v8i8_ty], [llvm_v8i8_ty, + llvm_v8i8_ty], [IntrNoMem, Commutative]>; + def int_x86_mmx_pavg_w : GCCBuiltin<"__builtin_ia32_pavgw">, + Intrinsic<[llvm_v4i16_ty], [llvm_v4i16_ty, + llvm_v4i16_ty], [IntrNoMem, Commutative]>; + + // Maximum + def int_x86_mmx_pmaxu_b : GCCBuiltin<"__builtin_ia32_pmaxub">, + Intrinsic<[llvm_v8i8_ty], [llvm_v8i8_ty, + llvm_v8i8_ty], [IntrNoMem, Commutative]>; + def int_x86_mmx_pmaxs_w : GCCBuiltin<"__builtin_ia32_pmaxsw">, + Intrinsic<[llvm_v4i16_ty], [llvm_v4i16_ty, + llvm_v4i16_ty], [IntrNoMem, Commutative]>; + + // Minimum + def int_x86_mmx_pminu_b : GCCBuiltin<"__builtin_ia32_pminub">, + Intrinsic<[llvm_v8i8_ty], [llvm_v8i8_ty, + llvm_v8i8_ty], [IntrNoMem, Commutative]>; + def int_x86_mmx_pmins_w : GCCBuiltin<"__builtin_ia32_pminsw">, + Intrinsic<[llvm_v4i16_ty], [llvm_v4i16_ty, + llvm_v4i16_ty], [IntrNoMem, Commutative]>; + + // Packed sum of absolute differences + def int_x86_mmx_psad_bw : GCCBuiltin<"__builtin_ia32_psadbw">, + Intrinsic<[llvm_v4i16_ty], [llvm_v8i8_ty, + llvm_v8i8_ty], [IntrNoMem, Commutative]>; +} + +// Integer shift ops. +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + // Shift left logical + def int_x86_mmx_psll_w : GCCBuiltin<"__builtin_ia32_psllw">, + Intrinsic<[llvm_v4i16_ty], [llvm_v4i16_ty, + llvm_v1i64_ty], [IntrNoMem]>; + def int_x86_mmx_psll_d : GCCBuiltin<"__builtin_ia32_pslld">, + Intrinsic<[llvm_v2i32_ty], [llvm_v2i32_ty, + llvm_v1i64_ty], [IntrNoMem]>; + def int_x86_mmx_psll_q : GCCBuiltin<"__builtin_ia32_psllq">, + Intrinsic<[llvm_v1i64_ty], [llvm_v1i64_ty, + llvm_v1i64_ty], [IntrNoMem]>; + + def int_x86_mmx_psrl_w : GCCBuiltin<"__builtin_ia32_psrlw">, + Intrinsic<[llvm_v4i16_ty], [llvm_v4i16_ty, + llvm_v1i64_ty], [IntrNoMem]>; + def int_x86_mmx_psrl_d : GCCBuiltin<"__builtin_ia32_psrld">, + Intrinsic<[llvm_v2i32_ty], [llvm_v2i32_ty, + llvm_v1i64_ty], [IntrNoMem]>; + def int_x86_mmx_psrl_q : GCCBuiltin<"__builtin_ia32_psrlq">, + Intrinsic<[llvm_v1i64_ty], [llvm_v1i64_ty, + llvm_v1i64_ty], [IntrNoMem]>; + + def int_x86_mmx_psra_w : GCCBuiltin<"__builtin_ia32_psraw">, + Intrinsic<[llvm_v4i16_ty], [llvm_v4i16_ty, + llvm_v1i64_ty], [IntrNoMem]>; + def int_x86_mmx_psra_d : GCCBuiltin<"__builtin_ia32_psrad">, + Intrinsic<[llvm_v2i32_ty], [llvm_v2i32_ty, + llvm_v1i64_ty], [IntrNoMem]>; + + def int_x86_mmx_pslli_w : GCCBuiltin<"__builtin_ia32_psllwi">, + Intrinsic<[llvm_v4i16_ty], [llvm_v4i16_ty, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_mmx_pslli_d : GCCBuiltin<"__builtin_ia32_pslldi">, + Intrinsic<[llvm_v2i32_ty], [llvm_v2i32_ty, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_mmx_pslli_q : GCCBuiltin<"__builtin_ia32_psllqi">, + Intrinsic<[llvm_v1i64_ty], [llvm_v1i64_ty, + llvm_i32_ty], [IntrNoMem]>; + + def int_x86_mmx_psrli_w : GCCBuiltin<"__builtin_ia32_psrlwi">, + Intrinsic<[llvm_v4i16_ty], [llvm_v4i16_ty, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_mmx_psrli_d : GCCBuiltin<"__builtin_ia32_psrldi">, + Intrinsic<[llvm_v2i32_ty], [llvm_v2i32_ty, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_mmx_psrli_q : GCCBuiltin<"__builtin_ia32_psrlqi">, + Intrinsic<[llvm_v1i64_ty], [llvm_v1i64_ty, + llvm_i32_ty], [IntrNoMem]>; + + def int_x86_mmx_psrai_w : GCCBuiltin<"__builtin_ia32_psrawi">, + Intrinsic<[llvm_v4i16_ty], [llvm_v4i16_ty, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_mmx_psrai_d : GCCBuiltin<"__builtin_ia32_psradi">, + Intrinsic<[llvm_v2i32_ty], [llvm_v2i32_ty, + llvm_i32_ty], [IntrNoMem]>; +} + +// Pack ops. +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_mmx_packsswb : GCCBuiltin<"__builtin_ia32_packsswb">, + Intrinsic<[llvm_v8i8_ty], [llvm_v4i16_ty, + llvm_v4i16_ty], [IntrNoMem]>; + def int_x86_mmx_packssdw : GCCBuiltin<"__builtin_ia32_packssdw">, + Intrinsic<[llvm_v4i16_ty], [llvm_v2i32_ty, + llvm_v2i32_ty], [IntrNoMem]>; + def int_x86_mmx_packuswb : GCCBuiltin<"__builtin_ia32_packuswb">, + Intrinsic<[llvm_v8i8_ty], [llvm_v4i16_ty, + llvm_v4i16_ty], [IntrNoMem]>; +} + +// Integer comparison ops +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_mmx_pcmpeq_b : GCCBuiltin<"__builtin_ia32_pcmpeqb">, + Intrinsic<[llvm_v8i8_ty], [llvm_v8i8_ty, + llvm_v8i8_ty], [IntrNoMem]>; + def int_x86_mmx_pcmpeq_w : GCCBuiltin<"__builtin_ia32_pcmpeqw">, + Intrinsic<[llvm_v4i16_ty], [llvm_v4i16_ty, + llvm_v4i16_ty], [IntrNoMem]>; + def int_x86_mmx_pcmpeq_d : GCCBuiltin<"__builtin_ia32_pcmpeqd">, + Intrinsic<[llvm_v2i32_ty], [llvm_v2i32_ty, + llvm_v2i32_ty], [IntrNoMem]>; + + def int_x86_mmx_pcmpgt_b : GCCBuiltin<"__builtin_ia32_pcmpgtb">, + Intrinsic<[llvm_v8i8_ty], [llvm_v8i8_ty, + llvm_v8i8_ty], [IntrNoMem]>; + def int_x86_mmx_pcmpgt_w : GCCBuiltin<"__builtin_ia32_pcmpgtw">, + Intrinsic<[llvm_v4i16_ty], [llvm_v4i16_ty, + llvm_v4i16_ty], [IntrNoMem]>; + def int_x86_mmx_pcmpgt_d : GCCBuiltin<"__builtin_ia32_pcmpgtd">, + Intrinsic<[llvm_v2i32_ty], [llvm_v2i32_ty, + llvm_v2i32_ty], [IntrNoMem]>; +} + +// Misc. +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_mmx_maskmovq : GCCBuiltin<"__builtin_ia32_maskmovq">, + Intrinsic<[llvm_void_ty], + [llvm_v8i8_ty, llvm_v8i8_ty, llvm_ptr_ty], + [IntrWriteMem]>; + + def int_x86_mmx_pmovmskb : GCCBuiltin<"__builtin_ia32_pmovmskb">, + Intrinsic<[llvm_i32_ty], [llvm_v8i8_ty], [IntrNoMem]>; + + def int_x86_mmx_movnt_dq : GCCBuiltin<"__builtin_ia32_movntq">, + Intrinsic<[llvm_void_ty], [llvm_ptr_ty, + llvm_v1i64_ty], [IntrWriteMem]>; +} diff --git a/libclamav/c++/llvm/include/llvm/IntrinsicsXCore.td b/libclamav/c++/llvm/include/llvm/IntrinsicsXCore.td new file mode 100644 index 000000000..a86cda28a --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/IntrinsicsXCore.td @@ -0,0 +1,14 @@ +//==- IntrinsicsXCore.td - XCore intrinsics -*- tablegen -*-==// +// +// Copyright (C) 2008 XMOS +// +//===----------------------------------------------------------------------===// +// +// This file defines all of the XCore-specific intrinsics. +// +//===----------------------------------------------------------------------===// + +let TargetPrefix = "xcore" in { // All intrinsics start with "llvm.xcore.". + def int_xcore_bitrev : Intrinsic<[llvm_i32_ty],[llvm_i32_ty],[IntrNoMem]>; + def int_xcore_getid : Intrinsic<[llvm_i32_ty],[],[IntrNoMem]>; +} diff --git a/libclamav/c++/llvm/include/llvm/LLVMContext.h b/libclamav/c++/llvm/include/llvm/LLVMContext.h new file mode 100644 index 000000000..b9ffeb002 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/LLVMContext.h @@ -0,0 +1,45 @@ +//===-- llvm/LLVMContext.h - Class for managing "global" state --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares LLVMContext, a container of "global" state in LLVM, such +// as the global type and constant uniquing tables. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LLVMCONTEXT_H +#define LLVM_LLVMCONTEXT_H + +namespace llvm { + +class LLVMContextImpl; +class MetadataContext; + +/// This is an important class for using LLVM in a threaded context. It +/// (opaquely) owns and manages the core "global" data of LLVM's core +/// infrastructure, including the type and constant uniquing tables. +/// LLVMContext itself provides no locking guarantees, so you should be careful +/// to have one context per thread. +class LLVMContext { + // DO NOT IMPLEMENT + LLVMContext(LLVMContext&); + void operator=(LLVMContext&); + +public: + LLVMContextImpl* const pImpl; + MetadataContext &getMetadata(); + LLVMContext(); + ~LLVMContext(); +}; + +/// FOR BACKWARDS COMPATIBILITY - Returns a global context. +extern LLVMContext& getGlobalContext(); + +} + +#endif diff --git a/libclamav/c++/llvm/include/llvm/LinkAllPasses.h b/libclamav/c++/llvm/include/llvm/LinkAllPasses.h new file mode 100644 index 000000000..4aba21042 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/LinkAllPasses.h @@ -0,0 +1,157 @@ +//===- llvm/LinkAllPasses.h ------------ Reference All Passes ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This header file pulls in all transformation and analysis passes for tools +// like opt and bugpoint that need this functionality. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LINKALLPASSES_H +#define LLVM_LINKALLPASSES_H + +#include "llvm/Analysis/AliasSetTracker.h" +#include "llvm/Analysis/DomPrinter.h" +#include "llvm/Analysis/FindUsedTypes.h" +#include "llvm/Analysis/IntervalPartition.h" +#include "llvm/Analysis/Passes.h" +#include "llvm/Analysis/PointerTracking.h" +#include "llvm/Analysis/PostDominators.h" +#include "llvm/Analysis/ScalarEvolution.h" +#include "llvm/Assembly/PrintModulePass.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/Function.h" +#include "llvm/Transforms/Instrumentation.h" +#include "llvm/Transforms/IPO.h" +#include "llvm/Transforms/Scalar.h" +#include "llvm/Transforms/Utils/UnifyFunctionExitNodes.h" +#include + +namespace { + struct ForcePassLinking { + ForcePassLinking() { + // We must reference the passes in such a way that compilers will not + // delete it all as dead code, even with whole program optimization, + // yet is effectively a NO-OP. As the compiler isn't smart enough + // to know that getenv() never returns -1, this will do the job. + if (std::getenv("bar") != (char*) -1) + return; + + (void) llvm::createAAEvalPass(); + (void) llvm::createAggressiveDCEPass(); + (void) llvm::createAliasAnalysisCounterPass(); + (void) llvm::createAliasDebugger(); + (void) llvm::createAndersensPass(); + (void) llvm::createArgumentPromotionPass(); + (void) llvm::createStructRetPromotionPass(); + (void) llvm::createBasicAliasAnalysisPass(); + (void) llvm::createLibCallAliasAnalysisPass(0); + (void) llvm::createScalarEvolutionAliasAnalysisPass(); + (void) llvm::createBlockPlacementPass(); + (void) llvm::createBlockProfilerPass(); + (void) llvm::createBreakCriticalEdgesPass(); + (void) llvm::createCFGSimplificationPass(); + (void) llvm::createConstantMergePass(); + (void) llvm::createConstantPropagationPass(); + (void) llvm::createDeadArgEliminationPass(); + (void) llvm::createDeadCodeEliminationPass(); + (void) llvm::createDeadInstEliminationPass(); + (void) llvm::createDeadStoreEliminationPass(); + (void) llvm::createDeadTypeEliminationPass(); + (void) llvm::createDomOnlyPrinterPass(); + (void) llvm::createDomPrinterPass(); + (void) llvm::createDomOnlyViewerPass(); + (void) llvm::createDomViewerPass(); + (void) llvm::createEdgeProfilerPass(); + (void) llvm::createOptimalEdgeProfilerPass(); + (void) llvm::createFunctionInliningPass(); + (void) llvm::createAlwaysInlinerPass(); + (void) llvm::createFunctionProfilerPass(); + (void) llvm::createGlobalDCEPass(); + (void) llvm::createGlobalOptimizerPass(); + (void) llvm::createGlobalsModRefPass(); + (void) llvm::createIPConstantPropagationPass(); + (void) llvm::createIPSCCPPass(); + (void) llvm::createIndVarSimplifyPass(); + (void) llvm::createInstructionCombiningPass(); + (void) llvm::createInternalizePass(false); + (void) llvm::createLCSSAPass(); + (void) llvm::createLICMPass(); + (void) llvm::createLazyValueInfoPass(); + (void) llvm::createLiveValuesPass(); + (void) llvm::createLoopDependenceAnalysisPass(); + (void) llvm::createLoopExtractorPass(); + (void) llvm::createLoopSimplifyPass(); + (void) llvm::createLoopStrengthReducePass(); + (void) llvm::createLoopUnrollPass(); + (void) llvm::createLoopUnswitchPass(); + (void) llvm::createLoopRotatePass(); + (void) llvm::createLoopIndexSplitPass(); + (void) llvm::createLowerInvokePass(); + (void) llvm::createLowerSetJmpPass(); + (void) llvm::createLowerSwitchPass(); + (void) llvm::createNoAAPass(); + (void) llvm::createNoProfileInfoPass(); + (void) llvm::createProfileEstimatorPass(); + (void) llvm::createProfileVerifierPass(); + (void) llvm::createProfileLoaderPass(); + (void) llvm::createPromoteMemoryToRegisterPass(); + (void) llvm::createDemoteRegisterToMemoryPass(); + (void) llvm::createPruneEHPass(); + (void) llvm::createPostDomOnlyPrinterPass(); + (void) llvm::createPostDomPrinterPass(); + (void) llvm::createPostDomOnlyViewerPass(); + (void) llvm::createPostDomViewerPass(); + (void) llvm::createReassociatePass(); + (void) llvm::createSCCPPass(); + (void) llvm::createScalarReplAggregatesPass(); + (void) llvm::createSimplifyLibCallsPass(); + (void) llvm::createSimplifyHalfPowrLibCallsPass(); + (void) llvm::createSingleLoopExtractorPass(); + (void) llvm::createStripSymbolsPass(); + (void) llvm::createStripNonDebugSymbolsPass(); + (void) llvm::createStripDeadPrototypesPass(); + (void) llvm::createTailCallEliminationPass(); + (void) llvm::createTailDuplicationPass(); + (void) llvm::createJumpThreadingPass(); + (void) llvm::createUnifyFunctionExitNodesPass(); + (void) llvm::createNullProfilerRSPass(); + (void) llvm::createRSProfilingPass(); + (void) llvm::createInstCountPass(); + (void) llvm::createCodeGenPreparePass(); + (void) llvm::createGVNPass(); + (void) llvm::createMemCpyOptPass(); + (void) llvm::createLoopDeletionPass(); + (void) llvm::createPostDomTree(); + (void) llvm::createPostDomFrontier(); + (void) llvm::createInstructionNamerPass(); + (void) llvm::createPartialSpecializationPass(); + (void) llvm::createFunctionAttrsPass(); + (void) llvm::createMergeFunctionsPass(); + (void) llvm::createPrintModulePass(0); + (void) llvm::createPrintFunctionPass("", 0); + (void) llvm::createDbgInfoPrinterPass(); + (void) llvm::createPartialInliningPass(); + (void) llvm::createSSIPass(); + (void) llvm::createSSIEverythingPass(); + (void) llvm::createGEPSplitterPass(); + (void) llvm::createSCCVNPass(); + (void) llvm::createABCDPass(); + + (void)new llvm::IntervalPartition(); + (void)new llvm::FindUsedTypes(); + (void)new llvm::ScalarEvolution(); + (void)new llvm::PointerTracking(); + ((llvm::Function*)0)->viewCFGOnly(); + llvm::AliasSetTracker X(*(llvm::AliasAnalysis*)0); + X.add((llvm::Value*)0, 0); // for -print-alias-sets + } + } ForcePassLinking; // Force link by creating a global definition. +} + +#endif diff --git a/libclamav/c++/llvm/include/llvm/LinkAllVMCore.h b/libclamav/c++/llvm/include/llvm/LinkAllVMCore.h new file mode 100644 index 000000000..0ee18d57a --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/LinkAllVMCore.h @@ -0,0 +1,56 @@ +//===- LinkAllVMCore.h - Reference All VMCore Code --------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This header file pulls in all the object modules of the VMCore library so +// that tools like llc, opt, and lli can ensure they are linked with all symbols +// from libVMCore.a It should only be used from a tool's main program. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LINKALLVMCORE_H +#define LLVM_LINKALLVMCORE_H + +#include "llvm/LLVMContext.h" +#include "llvm/Module.h" +#include "llvm/Instructions.h" +#include "llvm/IntrinsicInst.h" +#include "llvm/InlineAsm.h" +#include "llvm/Analysis/Verifier.h" +#include "llvm/System/Alarm.h" +#include "llvm/System/DynamicLibrary.h" +#include "llvm/System/Memory.h" +#include "llvm/System/Mutex.h" +#include "llvm/System/Path.h" +#include "llvm/System/Process.h" +#include "llvm/System/Program.h" +#include "llvm/System/Signals.h" +#include "llvm/System/TimeValue.h" +#include "llvm/Support/Dwarf.h" +#include "llvm/Support/Mangler.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/Support/SlowOperationInformer.h" + +namespace { + struct ForceVMCoreLinking { + ForceVMCoreLinking() { + // We must reference VMCore in such a way that compilers will not + // delete it all as dead code, even with whole program optimization, + // yet is effectively a NO-OP. As the compiler isn't smart enough + // to know that getenv() never returns -1, this will do the job. + if (std::getenv("bar") != (char*) -1) + return; + llvm::Module* M = new llvm::Module("", llvm::getGlobalContext()); + (void)new llvm::UnreachableInst(llvm::getGlobalContext()); + (void) llvm::createVerifierPass(); + (void) new llvm::Mangler(*M,""); + } + } ForceVMCoreLinking; +} + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Linker.h b/libclamav/c++/llvm/include/llvm/Linker.h new file mode 100644 index 000000000..a68a2e0fd --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Linker.h @@ -0,0 +1,300 @@ +//===- llvm/Linker.h - Module Linker Interface ------------------*- 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 the interface to the module/file/archive linker. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LINKER_H +#define LLVM_LINKER_H + +#include +#include +#include "llvm/ADT/StringRef.h" + +namespace llvm { + namespace sys { class Path; } + +class Module; +class LLVMContext; + +/// This class provides the core functionality of linking in LLVM. It retains a +/// Module object which is the composite of the modules and libraries linked +/// into it. The composite Module can be retrieved via the getModule() method. +/// In this case the Linker still retains ownership of the Module. If the +/// releaseModule() method is used, the ownership of the Module is transferred +/// to the caller and the Linker object is only suitable for destruction. +/// The Linker can link Modules from memory, bitcode files, or bitcode +/// archives. It retains a set of search paths in which to find any libraries +/// presented to it. By default, the linker will generate error and warning +/// messages to stderr but this capability can be turned off with the +/// QuietWarnings and QuietErrors flags. It can also be instructed to verbosely +/// print out the linking actions it is taking with the Verbose flag. +/// @brief The LLVM Linker. +class Linker { + + /// @name Types + /// @{ + public: + /// This type is used to pass the linkage items (libraries and files) to + /// the LinkItems function. It is composed of string/bool pairs. The string + /// provides the name of the file or library (as with the -l option). The + /// bool should be true for libraries and false for files, signifying + /// "isLibrary". + /// @brief A list of linkage items + typedef std::vector > ItemList; + + /// This enumeration is used to control various optional features of the + /// linker. + enum ControlFlags { + Verbose = 1, ///< Print to stderr what steps the linker is taking + QuietWarnings = 2, ///< Don't print warnings to stderr. + QuietErrors = 4 ///< Don't print errors to stderr. + }; + + /// @} + /// @name Constructors + /// @{ + public: + /// Construct the Linker with an empty module which will be given the + /// name \p progname. \p progname will also be used for error messages. + /// @brief Construct with empty module + Linker(StringRef progname, ///< name of tool running linker + StringRef modulename, ///< name of linker's end-result module + LLVMContext &C, ///< Context for global info + unsigned Flags = 0 ///< ControlFlags (one or more |'d together) + ); + + /// Construct the Linker with a previously defined module, \p aModule. Use + /// \p progname for the name of the program in error messages. + /// @brief Construct with existing module + Linker(StringRef progname, Module* aModule, unsigned Flags = 0); + + /// Destruct the Linker. + /// @brief Destructor + ~Linker(); + + /// @} + /// @name Accessors + /// @{ + public: + /// This method gets the composite module into which linking is being + /// done. The Composite module starts out empty and accumulates modules + /// linked into it via the various LinkIn* methods. This method does not + /// release the Module to the caller. The Linker retains ownership and will + /// destruct the Module when the Linker is destructed. + /// @see releaseModule + /// @brief Get the linked/composite module. + Module* getModule() const { return Composite; } + + /// This method releases the composite Module into which linking is being + /// done. Ownership of the composite Module is transferred to the caller who + /// must arrange for its destruct. After this method is called, the Linker + /// terminates the linking session for the returned Module. It will no + /// longer utilize the returned Module but instead resets itself for + /// subsequent linking as if the constructor had been called. The Linker's + /// LibPaths and flags to be reset, and memory will be released. + /// @brief Release the linked/composite module. + Module* releaseModule(); + + /// This method gets the list of libraries that form the path that the + /// Linker will search when it is presented with a library name. + /// @brief Get the Linkers library path + const std::vector& getLibPaths() const { return LibPaths; } + + /// This method returns an error string suitable for printing to the user. + /// The return value will be empty unless an error occurred in one of the + /// LinkIn* methods. In those cases, the LinkIn* methods will have returned + /// true, indicating an error occurred. At most one error is retained so + /// this function always returns the last error that occurred. Note that if + /// the Quiet control flag is not set, the error string will have already + /// been printed to stderr. + /// @brief Get the text of the last error that occurred. + const std::string &getLastError() const { return Error; } + + /// @} + /// @name Mutators + /// @{ + public: + /// Add a path to the list of paths that the Linker will search. The Linker + /// accumulates the set of libraries added + /// library paths for the target platform. The standard libraries will + /// always be searched last. The added libraries will be searched in the + /// order added. + /// @brief Add a path. + void addPath(const sys::Path& path); + + /// Add a set of paths to the list of paths that the linker will search. The + /// Linker accumulates the set of libraries added. The \p paths will be + /// added to the end of the Linker's list. Order will be retained. + /// @brief Add a set of paths. + void addPaths(const std::vector& paths); + + /// This method augments the Linker's list of library paths with the system + /// paths of the host operating system, include LLVM_LIB_SEARCH_PATH. + /// @brief Add the system paths. + void addSystemPaths(); + + /// Control optional linker behavior by setting a group of flags. The flags + /// are defined in the ControlFlags enumeration. + /// @see ControlFlags + /// @brief Set control flags. + void setFlags(unsigned flags) { Flags = flags; } + + /// This method is the main interface to the linker. It can be used to + /// link a set of linkage items into a module. A linkage item is either a + /// file name with fully qualified path, or a library for which the Linker's + /// LibraryPath will be utilized to locate the library. The bool value in + /// the LinkItemKind should be set to true for libraries. This function + /// allows linking to preserve the order of specification associated with + /// the command line, or for other purposes. Each item will be linked in + /// turn as it occurs in \p Items. + /// @returns true if an error occurred, false otherwise + /// @see LinkItemKind + /// @see getLastError + /// @throws nothing + bool LinkInItems ( + const ItemList& Items, ///< Set of libraries/files to link in + ItemList& NativeItems ///< Output list of native files/libs + ); + + /// This function links the bitcode \p Files into the composite module. + /// Note that this does not do any linking of unresolved symbols. The \p + /// Files are all completely linked into \p HeadModule regardless of + /// unresolved symbols. This function just loads each bitcode file and + /// calls LinkInModule on them. + /// @returns true if an error occurs, false otherwise + /// @see getLastError + /// @brief Link in multiple files. + bool LinkInFiles ( + const std::vector & Files ///< Files to link in + ); + + /// This function links a single bitcode file, \p File, into the composite + /// module. Note that this does not attempt to resolve symbols. This method + /// just loads the bitcode file and calls LinkInModule on it. If an error + /// occurs, the Linker's error string is set. + /// @returns true if an error occurs, false otherwise + /// @see getLastError + /// @brief Link in a single file. + bool LinkInFile( + const sys::Path& File, ///< File to link in. + bool &is_native ///< Indicates if the file is native object file + ); + + /// This function provides a way to selectively link in a set of modules, + /// found in libraries, based on the unresolved symbols in the composite + /// module. Each item in \p Libraries should be the base name of a library, + /// as if given with the -l option of a linker tool. The Linker's LibPaths + /// are searched for the \p Libraries and any found will be linked in with + /// LinkInArchive. If an error occurs, the Linker's error string is set. + /// @see LinkInArchive + /// @see getLastError + /// @returns true if an error occurs, false otherwise + /// @brief Link libraries into the module + bool LinkInLibraries ( + const std::vector & Libraries ///< Libraries to link in + ); + + /// This function provides a way to selectively link in a set of modules, + /// found in one library, based on the unresolved symbols in the composite + /// module.The \p Library should be the base name of a library, as if given + /// with the -l option of a linker tool. The Linker's LibPaths are searched + /// for the \p Library and if found, it will be linked in with via the + /// LinkInArchive method. If an error occurs, the Linker's error string is + /// set. + /// @see LinkInArchive + /// @see getLastError + /// @returns true if an error occurs, false otherwise + /// @brief Link one library into the module + bool LinkInLibrary ( + StringRef Library, ///< The library to link in + bool& is_native ///< Indicates if lib a native library + ); + + /// This function links one bitcode archive, \p Filename, into the module. + /// The archive is searched to resolve outstanding symbols. Any modules in + /// the archive that resolve outstanding symbols will be linked in. The + /// library is searched repeatedly until no more modules that resolve + /// symbols can be found. If an error occurs, the error string is set. + /// To speed up this function, ensure the the archive has been processed + /// llvm-ranlib or the S option was given to llvm-ar when the archive was + /// created. These tools add a symbol table to the archive which makes the + /// search for undefined symbols much faster. + /// @see getLastError + /// @returns true if an error occurs, otherwise false. + /// @brief Link in one archive. + bool LinkInArchive( + const sys::Path& Filename, ///< Filename of the archive to link + bool& is_native ///< Indicates if archive is a native archive + ); + + /// This method links the \p Src module into the Linker's Composite module + /// by calling LinkModules. All the other LinkIn* methods eventually + /// result in calling this method to link a Module into the Linker's + /// composite. + /// @see LinkModules + /// @returns True if an error occurs, false otherwise. + /// @brief Link in a module. + bool LinkInModule( + Module* Src, ///< Module linked into \p Dest + std::string* ErrorMsg = 0 /// Error/diagnostic string + ) { + return LinkModules(Composite, Src, ErrorMsg ); + } + + /// This is the heart of the linker. This method will take unconditional + /// control of the \p Src module and link it into the \p Dest module. The + /// \p Src module will be destructed or subsumed by this method. In either + /// case it is not usable by the caller after this method is invoked. Only + /// the \p Dest module will remain. The \p Src module is linked into the + /// Linker's composite module such that types, global variables, functions, + /// and etc. are matched and resolved. If an error occurs, this function + /// returns true and ErrorMsg is set to a descriptive message about the + /// error. + /// @returns True if an error occurs, false otherwise. + /// @brief Generically link two modules together. + static bool LinkModules(Module* Dest, Module* Src, std::string* ErrorMsg); + + /// This function looks through the Linker's LibPaths to find a library with + /// the name \p Filename. If the library cannot be found, the returned path + /// will be empty (i.e. sys::Path::isEmpty() will return true). + /// @returns A sys::Path to the found library + /// @brief Find a library from its short name. + sys::Path FindLib(StringRef Filename); + + /// @} + /// @name Implementation + /// @{ + private: + /// Read in and parse the bitcode file named by FN and return the + /// Module it contains (wrapped in an auto_ptr), or 0 if an error occurs. + std::auto_ptr LoadObject(const sys::Path& FN); + + bool warning(StringRef message); + bool error(StringRef message); + void verbose(StringRef message); + + /// @} + /// @name Data + /// @{ + private: + LLVMContext& Context; ///< The context for global information + Module* Composite; ///< The composite module linked together + std::vector LibPaths; ///< The library search paths + unsigned Flags; ///< Flags to control optional behavior. + std::string Error; ///< Text of error that occurred. + std::string ProgramName; ///< Name of the program being linked + /// @} + +}; + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/MC/MCAsmInfo.h b/libclamav/c++/llvm/include/llvm/MC/MCAsmInfo.h new file mode 100644 index 000000000..fb69630ff --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/MC/MCAsmInfo.h @@ -0,0 +1,472 @@ +//===-- llvm/MC/MCAsmInfo.h - Asm 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 contains a class to be used as the basis for target specific +// asm writers. This class primarily takes care of global printing constants, +// which are used in very similar ways across all targets. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TARGET_ASM_INFO_H +#define LLVM_TARGET_ASM_INFO_H + +#include + +namespace llvm { + /// MCAsmInfo - This class is intended to be used as a base class for asm + /// properties and features specific to the target. + namespace ExceptionHandling { enum ExceptionsType { None, Dwarf, SjLj }; } + + class MCAsmInfo { + protected: + //===------------------------------------------------------------------===// + // Properties to be set by the target writer, used to configure asm printer. + // + + /// ZeroFillDirective - Directive for emitting a global to the ZeroFill + /// section on this target. Null if this target doesn't support zerofill. + const char *ZeroFillDirective; // Default is null. + + /// NonexecutableStackDirective - Directive for declaring to the + /// linker and beyond that the emitted code does not require stack + /// memory to be executable. + const char *NonexecutableStackDirective; // Default is null. + + /// NeedsSet - True if target asm treats expressions in data directives + /// as linktime-relocatable. For assembly-time computation, we need to + /// use a .set. Thus: + /// .set w, x-y + /// .long w + /// is computed at assembly time, while + /// .long x-y + /// is relocated if the relative locations of x and y change at linktime. + /// We want both these things in different places. + bool NeedsSet; // Defaults to false. + + /// MaxInstLength - This is the maximum possible length of an instruction, + /// which is needed to compute the size of an inline asm. + unsigned MaxInstLength; // Defaults to 4. + + /// PCSymbol - The symbol used to represent the current PC. Used in PC + /// relative expressions. + const char *PCSymbol; // Defaults to "$". + + /// SeparatorChar - This character, if specified, is used to separate + /// instructions from each other when on the same line. This is used to + /// measure inline asm instructions. + char SeparatorChar; // Defaults to ';' + + /// CommentColumn - This indicates the comment num (zero-based) at + /// which asm comments should be printed. + unsigned CommentColumn; // Defaults to 60 + + /// CommentString - This indicates the comment character used by the + /// assembler. + const char *CommentString; // Defaults to "#" + + /// GlobalPrefix - If this is set to a non-empty string, it is prepended + /// onto all global symbols. This is often used for "_" or ".". + const char *GlobalPrefix; // Defaults to "" + + /// PrivateGlobalPrefix - This prefix is used for globals like constant + /// pool entries that are completely private to the .s file and should not + /// have names in the .o file. This is often "." or "L". + const char *PrivateGlobalPrefix; // Defaults to "." + + /// LinkerPrivateGlobalPrefix - This prefix is used for symbols that should + /// be passed through the assembler but be removed by the linker. This + /// is "l" on Darwin, currently used for some ObjC metadata. + const char *LinkerPrivateGlobalPrefix; // Defaults to "" + + /// InlineAsmStart/End - If these are nonempty, they contain a directive to + /// emit before and after an inline assembly statement. + const char *InlineAsmStart; // Defaults to "#APP\n" + const char *InlineAsmEnd; // Defaults to "#NO_APP\n" + + /// AssemblerDialect - Which dialect of an assembler variant to use. + unsigned AssemblerDialect; // Defaults to 0 + + /// AllowQuotesInName - This is true if the assembler allows for complex + /// symbol names to be surrounded in quotes. This defaults to false. + bool AllowQuotesInName; + + /// AllowNameToStartWithDigit - This is true if the assembler allows symbol + /// names to start with a digit (e.g., "0x0021"). This defaults to false. + bool AllowNameToStartWithDigit; + + //===--- Data Emission Directives -------------------------------------===// + + /// ZeroDirective - this should be set to the directive used to get some + /// number of zero bytes emitted to the current section. Common cases are + /// "\t.zero\t" and "\t.space\t". If this is set to null, the + /// Data*bitsDirective's will be used to emit zero bytes. + const char *ZeroDirective; // Defaults to "\t.zero\t" + const char *ZeroDirectiveSuffix; // Defaults to "" + + /// AsciiDirective - This directive allows emission of an ascii string with + /// the standard C escape characters embedded into it. + const char *AsciiDirective; // Defaults to "\t.ascii\t" + + /// AscizDirective - If not null, this allows for special handling of + /// zero terminated strings on this target. This is commonly supported as + /// ".asciz". If a target doesn't support this, it can be set to null. + const char *AscizDirective; // Defaults to "\t.asciz\t" + + /// DataDirectives - These directives are used to output some unit of + /// integer data to the current section. If a data directive is set to + /// null, smaller data directives will be used to emit the large sizes. + const char *Data8bitsDirective; // Defaults to "\t.byte\t" + const char *Data16bitsDirective; // Defaults to "\t.short\t" + const char *Data32bitsDirective; // Defaults to "\t.long\t" + const char *Data64bitsDirective; // Defaults to "\t.quad\t" + + /// getDataASDirective - Return the directive that should be used to emit + /// data of the specified size to the specified numeric address space. + virtual const char *getDataASDirective(unsigned Size, unsigned AS) const { + assert(AS != 0 && "Don't know the directives for default addr space"); + return 0; + } + + /// SunStyleELFSectionSwitchSyntax - This is true if this target uses "Sun + /// Style" syntax for section switching ("#alloc,#write" etc) instead of the + /// normal ELF syntax (,"a,w") in .section directives. + bool SunStyleELFSectionSwitchSyntax; // Defaults to false. + + /// UsesELFSectionDirectiveForBSS - This is true if this target uses ELF + /// '.section' directive before the '.bss' one. It's used for PPC/Linux + /// which doesn't support the '.bss' directive only. + bool UsesELFSectionDirectiveForBSS; // Defaults to false. + + //===--- Alignment Information ----------------------------------------===// + + /// AlignDirective - The directive used to emit round up to an alignment + /// boundary. + /// + const char *AlignDirective; // Defaults to "\t.align\t" + + /// AlignmentIsInBytes - If this is true (the default) then the asmprinter + /// emits ".align N" directives, where N is the number of bytes to align to. + /// Otherwise, it emits ".align log2(N)", e.g. 3 to align to an 8 byte + /// boundary. + bool AlignmentIsInBytes; // Defaults to true + + /// TextAlignFillValue - If non-zero, this is used to fill the executable + /// space created as the result of a alignment directive. + unsigned TextAlignFillValue; // Defaults to 0 + + //===--- Section Switching Directives ---------------------------------===// + + /// JumpTableDirective - if non-null, the directive to emit before jump + /// table entries. FIXME: REMOVE THIS. + const char *JumpTableDirective; // Defaults to NULL. + const char *PICJumpTableDirective; // Defaults to NULL. + + + //===--- Global Variable Emission Directives --------------------------===// + + /// GlobalDirective - This is the directive used to declare a global entity. + /// + const char *GlobalDirective; // Defaults to NULL. + + /// ExternDirective - This is the directive used to declare external + /// globals. + /// + const char *ExternDirective; // Defaults to NULL. + + /// SetDirective - This is the name of a directive that can be used to tell + /// the assembler to set the value of a variable to some expression. + const char *SetDirective; // Defaults to null. + + /// LCOMMDirective - This is the name of a directive (if supported) that can + /// be used to efficiently declare a local (internal) block of zero + /// initialized data in the .bss/.data section. The syntax expected is: + /// @verbatim SYMBOLNAME LENGTHINBYTES, ALIGNMENT + /// @endverbatim + const char *LCOMMDirective; // Defaults to null. + + const char *COMMDirective; // Defaults to "\t.comm\t". + + /// COMMDirectiveTakesAlignment - True if COMMDirective take a third + /// argument that specifies the alignment of the declaration. + bool COMMDirectiveTakesAlignment; // Defaults to true. + + /// HasDotTypeDotSizeDirective - True if the target has .type and .size + /// directives, this is true for most ELF targets. + bool HasDotTypeDotSizeDirective; // Defaults to true. + + /// HasSingleParameterDotFile - True if the target has a single parameter + /// .file directive, this is true for ELF targets. + bool HasSingleParameterDotFile; // Defaults to true. + + /// UsedDirective - This directive, if non-null, is used to declare a global + /// as being used somehow that the assembler can't see. This prevents dead + /// code elimination on some targets. + const char *UsedDirective; // Defaults to NULL. + + /// WeakRefDirective - This directive, if non-null, is used to declare a + /// global as being a weak undefined symbol. + const char *WeakRefDirective; // Defaults to NULL. + + /// WeakDefDirective - This directive, if non-null, is used to declare a + /// global as being a weak defined symbol. + const char *WeakDefDirective; // Defaults to NULL. + + /// HiddenDirective - This directive, if non-null, is used to declare a + /// global or function as having hidden visibility. + const char *HiddenDirective; // Defaults to "\t.hidden\t". + + /// ProtectedDirective - This directive, if non-null, is used to declare a + /// global or function as having protected visibility. + const char *ProtectedDirective; // Defaults to "\t.protected\t". + + //===--- Dwarf Emission Directives -----------------------------------===// + + /// AbsoluteDebugSectionOffsets - True if we should emit abolute section + /// offsets for debug information. + bool AbsoluteDebugSectionOffsets; // Defaults to false. + + /// AbsoluteEHSectionOffsets - True if we should emit abolute section + /// offsets for EH information. Defaults to false. + bool AbsoluteEHSectionOffsets; + + /// HasLEB128 - True if target asm supports leb128 directives. + bool HasLEB128; // Defaults to false. + + /// hasDotLocAndDotFile - True if target asm supports .loc and .file + /// directives for emitting debugging information. + bool HasDotLocAndDotFile; // Defaults to false. + + /// SupportsDebugInformation - True if target supports emission of debugging + /// information. + bool SupportsDebugInformation; // Defaults to false. + + /// SupportsExceptionHandling - True if target supports exception handling. + ExceptionHandling::ExceptionsType ExceptionsType; // Defaults to None + + /// RequiresFrameSection - true if the Dwarf2 output needs a frame section + bool DwarfRequiresFrameSection; // Defaults to true. + + /// DwarfUsesInlineInfoSection - True if DwarfDebugInlineSection is used to + /// encode inline subroutine information. + bool DwarfUsesInlineInfoSection; // Defaults to false. + + /// Is_EHSymbolPrivate - If set, the "_foo.eh" is made private so that it + /// doesn't show up in the symbol table of the object file. + bool Is_EHSymbolPrivate; // Defaults to true. + + /// GlobalEHDirective - This is the directive used to make exception frame + /// tables globally visible. + const char *GlobalEHDirective; // Defaults to NULL. + + /// SupportsWeakEmptyEHFrame - True if target assembler and linker will + /// handle a weak_definition of constant 0 for an omitted EH frame. + bool SupportsWeakOmittedEHFrame; // Defaults to true. + + /// DwarfSectionOffsetDirective - Special section offset directive. + const char* DwarfSectionOffsetDirective; // Defaults to NULL + + //===--- CBE Asm Translation Table -----------------------------------===// + + const char *const *AsmTransCBE; // Defaults to empty + + public: + explicit MCAsmInfo(); + virtual ~MCAsmInfo(); + + /// getSLEB128Size - Compute the number of bytes required for a signed + /// leb128 value. + static unsigned getSLEB128Size(int Value); + + /// getULEB128Size - Compute the number of bytes required for an unsigned + /// leb128 value. + static unsigned getULEB128Size(unsigned Value); + + // Data directive accessors. + // + const char *getData8bitsDirective(unsigned AS = 0) const { + return AS == 0 ? Data8bitsDirective : getDataASDirective(8, AS); + } + const char *getData16bitsDirective(unsigned AS = 0) const { + return AS == 0 ? Data16bitsDirective : getDataASDirective(16, AS); + } + const char *getData32bitsDirective(unsigned AS = 0) const { + return AS == 0 ? Data32bitsDirective : getDataASDirective(32, AS); + } + const char *getData64bitsDirective(unsigned AS = 0) const { + return AS == 0 ? Data64bitsDirective : getDataASDirective(64, AS); + } + + + bool usesSunStyleELFSectionSwitchSyntax() const { + return SunStyleELFSectionSwitchSyntax; + } + + bool usesELFSectionDirectiveForBSS() const { + return UsesELFSectionDirectiveForBSS; + } + + // Accessors. + // + const char *getZeroFillDirective() const { + return ZeroFillDirective; + } + const char *getNonexecutableStackDirective() const { + return NonexecutableStackDirective; + } + bool needsSet() const { + return NeedsSet; + } + unsigned getMaxInstLength() const { + return MaxInstLength; + } + const char *getPCSymbol() const { + return PCSymbol; + } + char getSeparatorChar() const { + return SeparatorChar; + } + unsigned getCommentColumn() const { + return CommentColumn; + } + const char *getCommentString() const { + return CommentString; + } + const char *getGlobalPrefix() const { + return GlobalPrefix; + } + const char *getPrivateGlobalPrefix() const { + return PrivateGlobalPrefix; + } + const char *getLinkerPrivateGlobalPrefix() const { + return LinkerPrivateGlobalPrefix; + } + const char *getInlineAsmStart() const { + return InlineAsmStart; + } + const char *getInlineAsmEnd() const { + return InlineAsmEnd; + } + unsigned getAssemblerDialect() const { + return AssemblerDialect; + } + bool doesAllowQuotesInName() const { + return AllowQuotesInName; + } + bool doesAllowNameToStartWithDigit() const { + return AllowNameToStartWithDigit; + } + const char *getZeroDirective() const { + return ZeroDirective; + } + const char *getZeroDirectiveSuffix() const { + return ZeroDirectiveSuffix; + } + const char *getAsciiDirective() const { + return AsciiDirective; + } + const char *getAscizDirective() const { + return AscizDirective; + } + const char *getJumpTableDirective(bool isPIC) const { + return isPIC ? PICJumpTableDirective : JumpTableDirective; + } + const char *getAlignDirective() const { + return AlignDirective; + } + bool getAlignmentIsInBytes() const { + return AlignmentIsInBytes; + } + unsigned getTextAlignFillValue() const { + return TextAlignFillValue; + } + const char *getGlobalDirective() const { + return GlobalDirective; + } + const char *getExternDirective() const { + return ExternDirective; + } + const char *getSetDirective() const { + return SetDirective; + } + const char *getLCOMMDirective() const { + return LCOMMDirective; + } + const char *getCOMMDirective() const { + return COMMDirective; + } + bool getCOMMDirectiveTakesAlignment() const { + return COMMDirectiveTakesAlignment; + } + bool hasDotTypeDotSizeDirective() const { + return HasDotTypeDotSizeDirective; + } + bool hasSingleParameterDotFile() const { + return HasSingleParameterDotFile; + } + const char *getUsedDirective() const { + return UsedDirective; + } + const char *getWeakRefDirective() const { + return WeakRefDirective; + } + const char *getWeakDefDirective() const { + return WeakDefDirective; + } + const char *getHiddenDirective() const { + return HiddenDirective; + } + const char *getProtectedDirective() const { + return ProtectedDirective; + } + bool isAbsoluteDebugSectionOffsets() const { + return AbsoluteDebugSectionOffsets; + } + bool isAbsoluteEHSectionOffsets() const { + return AbsoluteEHSectionOffsets; + } + bool hasLEB128() const { + return HasLEB128; + } + bool hasDotLocAndDotFile() const { + return HasDotLocAndDotFile; + } + bool doesSupportDebugInformation() const { + return SupportsDebugInformation; + } + bool doesSupportExceptionHandling() const { + return ExceptionsType != ExceptionHandling::None; + } + ExceptionHandling::ExceptionsType getExceptionHandlingType() const { + return ExceptionsType; + } + bool doesDwarfRequireFrameSection() const { + return DwarfRequiresFrameSection; + } + bool doesDwarfUsesInlineInfoSection() const { + return DwarfUsesInlineInfoSection; + } + bool is_EHSymbolPrivate() const { + return Is_EHSymbolPrivate; + } + const char *getGlobalEHDirective() const { + return GlobalEHDirective; + } + bool getSupportsWeakOmittedEHFrame() const { + return SupportsWeakOmittedEHFrame; + } + const char *getDwarfSectionOffsetDirective() const { + return DwarfSectionOffsetDirective; + } + const char *const *getAsmCBE() const { + return AsmTransCBE; + } + }; +} + +#endif diff --git a/libclamav/c++/llvm/include/llvm/MC/MCAsmInfoCOFF.h b/libclamav/c++/llvm/include/llvm/MC/MCAsmInfoCOFF.h new file mode 100644 index 000000000..a3ee1593c --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/MC/MCAsmInfoCOFF.h @@ -0,0 +1,24 @@ +//===-- MCAsmInfoCOFF.h - COFF asm properties -------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_COFF_TARGET_ASM_INFO_H +#define LLVM_COFF_TARGET_ASM_INFO_H + +#include "llvm/MC/MCAsmInfo.h" + +namespace llvm { + class MCAsmInfoCOFF : public MCAsmInfo { + protected: + explicit MCAsmInfoCOFF(); + + }; +} + + +#endif // LLVM_COFF_TARGET_ASM_INFO_H diff --git a/libclamav/c++/llvm/include/llvm/MC/MCAsmInfoDarwin.h b/libclamav/c++/llvm/include/llvm/MC/MCAsmInfoDarwin.h new file mode 100644 index 000000000..c85aa3da9 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/MC/MCAsmInfoDarwin.h @@ -0,0 +1,32 @@ +//===---- MCAsmInfoDarwin.h - Darwin asm properties -------------*- 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 target asm properties related what form asm statements +// should take in general on Darwin-based targets +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DARWIN_TARGET_ASM_INFO_H +#define LLVM_DARWIN_TARGET_ASM_INFO_H + +#include "llvm/MC/MCAsmInfo.h" + +namespace llvm { + class GlobalValue; + class GlobalVariable; + class Type; + class Mangler; + + struct MCAsmInfoDarwin : public MCAsmInfo { + explicit MCAsmInfoDarwin(); + }; +} + + +#endif // LLVM_DARWIN_TARGET_ASM_INFO_H diff --git a/libclamav/c++/llvm/include/llvm/MC/MCAsmLexer.h b/libclamav/c++/llvm/include/llvm/MC/MCAsmLexer.h new file mode 100644 index 000000000..da471d284 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/MC/MCAsmLexer.h @@ -0,0 +1,141 @@ +//===-- llvm/MC/MCAsmLexer.h - Abstract Asm Lexer Interface -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCASMLEXER_H +#define LLVM_MC_MCASMLEXER_H + +#include "llvm/ADT/StringRef.h" +#include "llvm/System/DataTypes.h" + +namespace llvm { +class MCAsmLexer; +class MCInst; +class SMLoc; +class Target; + +/// AsmToken - Target independent representation for an assembler token. +struct AsmToken { + enum TokenKind { + // Markers + Eof, Error, + + // String values. + Identifier, + String, + + // Integer values. + Integer, + + // No-value. + EndOfStatement, + Colon, + Plus, Minus, Tilde, + Slash, // '/' + LParen, RParen, LBrac, RBrac, LCurly, RCurly, + Star, Comma, Dollar, Equal, EqualEqual, + + Pipe, PipePipe, Caret, + Amp, AmpAmp, Exclaim, ExclaimEqual, Percent, Hash, + Less, LessEqual, LessLess, LessGreater, + Greater, GreaterEqual, GreaterGreater + }; + + TokenKind Kind; + + /// A reference to the entire token contents; this is always a pointer into + /// a memory buffer owned by the source manager. + StringRef Str; + + int64_t IntVal; + +public: + AsmToken() {} + AsmToken(TokenKind _Kind, StringRef _Str, int64_t _IntVal = 0) + : Kind(_Kind), Str(_Str), IntVal(_IntVal) {} + + TokenKind getKind() const { return Kind; } + bool is(TokenKind K) const { return Kind == K; } + bool isNot(TokenKind K) const { return Kind != K; } + + SMLoc getLoc() const; + + /// getStringContents - Get the contents of a string token (without quotes). + StringRef getStringContents() const { + assert(Kind == String && "This token isn't a string!"); + return Str.slice(1, Str.size() - 1); + } + + /// getIdentifier - Get the identifier string for the current token, which + /// should be an identifier or a string. This gets the portion of the string + /// which should be used as the identifier, e.g., it does not include the + /// quotes on strings. + StringRef getIdentifier() const { + if (Kind == Identifier) + return getString(); + return getStringContents(); + } + + /// getString - Get the string for the current token, this includes all + /// characters (for example, the quotes on strings) in the token. + /// + /// The returned StringRef points into the source manager's memory buffer, and + /// is safe to store across calls to Lex(). + StringRef getString() const { return Str; } + + // FIXME: Don't compute this in advance, it makes every token larger, and is + // also not generally what we want (it is nicer for recovery etc. to lex 123br + // as a single token, then diagnose as an invalid number). + int64_t getIntVal() const { + assert(Kind == Integer && "This token isn't an integer!"); + return IntVal; + } +}; + +/// MCAsmLexer - Generic assembler lexer interface, for use by target specific +/// assembly lexers. +class MCAsmLexer { + /// The current token, stored in the base class for faster access. + AsmToken CurTok; + + MCAsmLexer(const MCAsmLexer &); // DO NOT IMPLEMENT + void operator=(const MCAsmLexer &); // DO NOT IMPLEMENT +protected: // Can only create subclasses. + MCAsmLexer(); + + virtual AsmToken LexToken() = 0; + +public: + virtual ~MCAsmLexer(); + + /// Lex - Consume the next token from the input stream and return it. + /// + /// The lexer will continuosly return the end-of-file token once the end of + /// the main input file has been reached. + const AsmToken &Lex() { + return CurTok = LexToken(); + } + + /// getTok - Get the current (last) lexed token. + const AsmToken &getTok() { + return CurTok; + } + + /// getKind - Get the kind of current token. + AsmToken::TokenKind getKind() const { return CurTok.getKind(); } + + /// is - Check if the current token has kind \arg K. + bool is(AsmToken::TokenKind K) const { return CurTok.is(K); } + + /// isNot - Check if the current token has kind \arg K. + bool isNot(AsmToken::TokenKind K) const { return CurTok.isNot(K); } +}; + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/MC/MCAsmParser.h b/libclamav/c++/llvm/include/llvm/MC/MCAsmParser.h new file mode 100644 index 000000000..d53009338 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/MC/MCAsmParser.h @@ -0,0 +1,79 @@ +//===-- llvm/MC/MCAsmParser.h - Abstract Asm Parser Interface ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCASMPARSER_H +#define LLVM_MC_MCASMPARSER_H + +#include "llvm/System/DataTypes.h" + +namespace llvm { +class MCAsmLexer; +class MCContext; +class MCExpr; +class MCStreamer; +class MCValue; +class SMLoc; +class Twine; + +/// MCAsmParser - Generic assembler parser interface, for use by target specific +/// assembly parsers. +class MCAsmParser { + MCAsmParser(const MCAsmParser &); // DO NOT IMPLEMENT + void operator=(const MCAsmParser &); // DO NOT IMPLEMENT +protected: // Can only create subclasses. + MCAsmParser(); + +public: + virtual ~MCAsmParser(); + + virtual MCAsmLexer &getLexer() = 0; + + virtual MCContext &getContext() = 0; + + /// getSteamer - Return the output streamer for the assembler. + virtual MCStreamer &getStreamer() = 0; + + /// Warning - Emit a warning at the location \arg L, with the message \arg + /// Msg. + virtual void Warning(SMLoc L, const Twine &Msg) = 0; + + /// Warning - Emit an error at the location \arg L, with the message \arg + /// Msg. + /// + /// \return The return value is always true, as an idiomatic convenience to + /// clients. + virtual bool Error(SMLoc L, const Twine &Msg) = 0; + + /// ParseExpression - Parse an arbitrary expression. + /// + /// @param Res - The value of the expression. The result is undefined + /// on error. + /// @result - False on success. + virtual bool ParseExpression(const MCExpr *&Res) = 0; + + /// ParseParenExpression - Parse an arbitrary expression, assuming that an + /// initial '(' has already been consumed. + /// + /// @param Res - The value of the expression. The result is undefined + /// on error. + /// @result - False on success. + virtual bool ParseParenExpression(const MCExpr *&Res) = 0; + + /// ParseAbsoluteExpression - Parse an expression which must evaluate to an + /// absolute value. + /// + /// @param Res - The value of the absolute expression. The result is undefined + /// on error. + /// @result - False on success. + virtual bool ParseAbsoluteExpression(int64_t &Res) = 0; +}; + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/MC/MCAssembler.h b/libclamav/c++/llvm/include/llvm/MC/MCAssembler.h new file mode 100644 index 000000000..86569271e --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/MC/MCAssembler.h @@ -0,0 +1,659 @@ +//===- MCAssembler.h - Object File Generation -------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCASSEMBLER_H +#define LLVM_MC_MCASSEMBLER_H + +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/ilist.h" +#include "llvm/ADT/ilist_node.h" +#include "llvm/Support/Casting.h" +#include "llvm/System/DataTypes.h" +#include // FIXME: Shouldn't be needed. + +namespace llvm { +class raw_ostream; +class MCAssembler; +class MCContext; +class MCExpr; +class MCSection; +class MCSectionData; +class MCSymbol; + +class MCFragment : public ilist_node { + MCFragment(const MCFragment&); // DO NOT IMPLEMENT + void operator=(const MCFragment&); // DO NOT IMPLEMENT + +public: + enum FragmentType { + FT_Data, + FT_Align, + FT_Fill, + FT_Org, + FT_ZeroFill + }; + +private: + FragmentType Kind; + + /// Parent - The data for the section this fragment is in. + MCSectionData *Parent; + + /// @name Assembler Backend Data + /// @{ + // + // FIXME: This could all be kept private to the assembler implementation. + + /// Offset - The offset of this fragment in its section. This is ~0 until + /// initialized. + uint64_t Offset; + + /// FileSize - The file size of this section. This is ~0 until initialized. + uint64_t FileSize; + + /// @} + +protected: + MCFragment(FragmentType _Kind, MCSectionData *_Parent = 0); + +public: + // Only for sentinel. + MCFragment(); + virtual ~MCFragment(); + + FragmentType getKind() const { return Kind; } + + MCSectionData *getParent() const { return Parent; } + void setParent(MCSectionData *Value) { Parent = Value; } + + // FIXME: This should be abstract, fix sentinel. + virtual uint64_t getMaxFileSize() const { + assert(0 && "Invalid getMaxFileSize call!"); + return 0; + }; + + /// @name Assembler Backend Support + /// @{ + // + // FIXME: This could all be kept private to the assembler implementation. + + uint64_t getAddress() const; + + uint64_t getFileSize() const { + assert(FileSize != ~UINT64_C(0) && "File size not set!"); + return FileSize; + } + void setFileSize(uint64_t Value) { + assert(Value <= getMaxFileSize() && "Invalid file size!"); + FileSize = Value; + } + + uint64_t getOffset() const { + assert(Offset != ~UINT64_C(0) && "File offset not set!"); + return Offset; + } + void setOffset(uint64_t Value) { Offset = Value; } + + /// @} + + static bool classof(const MCFragment *O) { return true; } +}; + +class MCDataFragment : public MCFragment { + SmallString<32> Contents; + +public: + MCDataFragment(MCSectionData *SD = 0) : MCFragment(FT_Data, SD) {} + + /// @name Accessors + /// @{ + + uint64_t getMaxFileSize() const { + return Contents.size(); + } + + SmallString<32> &getContents() { return Contents; } + const SmallString<32> &getContents() const { return Contents; } + + /// @} + + static bool classof(const MCFragment *F) { + return F->getKind() == MCFragment::FT_Data; + } + static bool classof(const MCDataFragment *) { return true; } +}; + +class MCAlignFragment : public MCFragment { + /// Alignment - The alignment to ensure, in bytes. + unsigned Alignment; + + /// Value - Value to use for filling padding bytes. + int64_t Value; + + /// ValueSize - The size of the integer (in bytes) of \arg Value. + unsigned ValueSize; + + /// MaxBytesToEmit - The maximum number of bytes to emit; if the alignment + /// cannot be satisfied in this width then this fragment is ignored. + unsigned MaxBytesToEmit; + +public: + MCAlignFragment(unsigned _Alignment, int64_t _Value, unsigned _ValueSize, + unsigned _MaxBytesToEmit, MCSectionData *SD = 0) + : MCFragment(FT_Align, SD), Alignment(_Alignment), + Value(_Value),ValueSize(_ValueSize), + MaxBytesToEmit(_MaxBytesToEmit) {} + + /// @name Accessors + /// @{ + + uint64_t getMaxFileSize() const { + return std::max(Alignment - 1, MaxBytesToEmit); + } + + unsigned getAlignment() const { return Alignment; } + + int64_t getValue() const { return Value; } + + unsigned getValueSize() const { return ValueSize; } + + unsigned getMaxBytesToEmit() const { return MaxBytesToEmit; } + + /// @} + + static bool classof(const MCFragment *F) { + return F->getKind() == MCFragment::FT_Align; + } + static bool classof(const MCAlignFragment *) { return true; } +}; + +class MCFillFragment : public MCFragment { + /// Value - Value to use for filling bytes. + const MCExpr *Value; + + /// ValueSize - The size (in bytes) of \arg Value to use when filling. + unsigned ValueSize; + + /// Count - The number of copies of \arg Value to insert. + uint64_t Count; + +public: + MCFillFragment(const MCExpr &_Value, unsigned _ValueSize, uint64_t _Count, + MCSectionData *SD = 0) + : MCFragment(FT_Fill, SD), + Value(&_Value), ValueSize(_ValueSize), Count(_Count) {} + + /// @name Accessors + /// @{ + + uint64_t getMaxFileSize() const { + return ValueSize * Count; + } + + const MCExpr &getValue() const { return *Value; } + + unsigned getValueSize() const { return ValueSize; } + + uint64_t getCount() const { return Count; } + + /// @} + + static bool classof(const MCFragment *F) { + return F->getKind() == MCFragment::FT_Fill; + } + static bool classof(const MCFillFragment *) { return true; } +}; + +class MCOrgFragment : public MCFragment { + /// Offset - The offset this fragment should start at. + const MCExpr *Offset; + + /// Value - Value to use for filling bytes. + int8_t Value; + +public: + MCOrgFragment(const MCExpr &_Offset, int8_t _Value, MCSectionData *SD = 0) + : MCFragment(FT_Org, SD), + Offset(&_Offset), Value(_Value) {} + + /// @name Accessors + /// @{ + + uint64_t getMaxFileSize() const { + // FIXME: This doesn't make much sense. + return ~UINT64_C(0); + } + + const MCExpr &getOffset() const { return *Offset; } + + uint8_t getValue() const { return Value; } + + /// @} + + static bool classof(const MCFragment *F) { + return F->getKind() == MCFragment::FT_Org; + } + static bool classof(const MCOrgFragment *) { return true; } +}; + +/// MCZeroFillFragment - Represent data which has a fixed size and alignment, +/// but requires no physical space in the object file. +class MCZeroFillFragment : public MCFragment { + /// Size - The size of this fragment. + uint64_t Size; + + /// Alignment - The alignment for this fragment. + unsigned Alignment; + +public: + MCZeroFillFragment(uint64_t _Size, unsigned _Alignment, MCSectionData *SD = 0) + : MCFragment(FT_ZeroFill, SD), + Size(_Size), Alignment(_Alignment) {} + + /// @name Accessors + /// @{ + + uint64_t getMaxFileSize() const { + // FIXME: This also doesn't make much sense, this method is misnamed. + return ~UINT64_C(0); + } + + uint64_t getSize() const { return Size; } + + unsigned getAlignment() const { return Alignment; } + + /// @} + + static bool classof(const MCFragment *F) { + return F->getKind() == MCFragment::FT_ZeroFill; + } + static bool classof(const MCZeroFillFragment *) { return true; } +}; + +// FIXME: Should this be a separate class, or just merged into MCSection? Since +// we anticipate the fast path being through an MCAssembler, the only reason to +// keep it out is for API abstraction. +class MCSectionData : public ilist_node { + MCSectionData(const MCSectionData&); // DO NOT IMPLEMENT + void operator=(const MCSectionData&); // DO NOT IMPLEMENT + +public: + /// Fixup - Represent a fixed size region of bytes inside some fragment which + /// needs to be rewritten. This region will either be rewritten by the + /// assembler or cause a relocation entry to be generated. + struct Fixup { + /// Fragment - The fragment containing the fixup. + MCFragment *Fragment; + + /// Offset - The offset inside the fragment which needs to be rewritten. + uint64_t Offset; + + /// Value - The expression to eventually write into the fragment. + const MCExpr *Value; + + /// Size - The fixup size. + unsigned Size; + + /// FixedValue - The value to replace the fix up by. + // + // FIXME: This should not be here. + uint64_t FixedValue; + + public: + Fixup(MCFragment &_Fragment, uint64_t _Offset, const MCExpr &_Value, + unsigned _Size) + : Fragment(&_Fragment), Offset(_Offset), Value(&_Value), Size(_Size), + FixedValue(0) {} + }; + + typedef iplist FragmentListType; + + typedef FragmentListType::const_iterator const_iterator; + typedef FragmentListType::iterator iterator; + + typedef std::vector::const_iterator const_fixup_iterator; + typedef std::vector::iterator fixup_iterator; + +private: + iplist Fragments; + const MCSection *Section; + + /// Alignment - The maximum alignment seen in this section. + unsigned Alignment; + + /// @name Assembler Backend Data + /// @{ + // + // FIXME: This could all be kept private to the assembler implementation. + + /// Address - The computed address of this section. This is ~0 until + /// initialized. + uint64_t Address; + + /// Size - The content size of this section. This is ~0 until initialized. + uint64_t Size; + + /// FileSize - The size of this section in the object file. This is ~0 until + /// initialized. + uint64_t FileSize; + + /// LastFixupLookup - Cache for the last looked up fixup. + mutable unsigned LastFixupLookup; + + /// Fixups - The list of fixups in this section. + std::vector Fixups; + + /// @} + +public: + // Only for use as sentinel. + MCSectionData(); + MCSectionData(const MCSection &Section, MCAssembler *A = 0); + + const MCSection &getSection() const { return *Section; } + + unsigned getAlignment() const { return Alignment; } + void setAlignment(unsigned Value) { Alignment = Value; } + + /// @name Fragment Access + /// @{ + + const FragmentListType &getFragmentList() const { return Fragments; } + FragmentListType &getFragmentList() { return Fragments; } + + iterator begin() { return Fragments.begin(); } + const_iterator begin() const { return Fragments.begin(); } + + iterator end() { return Fragments.end(); } + const_iterator end() const { return Fragments.end(); } + + size_t size() const { return Fragments.size(); } + + bool empty() const { return Fragments.empty(); } + + /// @} + /// @name Fixup Access + /// @{ + + std::vector &getFixups() { + return Fixups; + } + + fixup_iterator fixup_begin() { + return Fixups.begin(); + } + + fixup_iterator fixup_end() { + return Fixups.end(); + } + + size_t fixup_size() const { return Fixups.size(); } + + /// @} + /// @name Assembler Backend Support + /// @{ + // + // FIXME: This could all be kept private to the assembler implementation. + + /// LookupFixup - Look up the fixup for the given \arg Fragment and \arg + /// Offset. + /// + /// If multiple fixups exist for the same fragment and offset it is undefined + /// which one is returned. + // + // FIXME: This isn't horribly slow in practice, but there are much nicer + // solutions to applying the fixups. + const Fixup *LookupFixup(const MCFragment *Fragment, uint64_t Offset) const; + + uint64_t getAddress() const { + assert(Address != ~UINT64_C(0) && "Address not set!"); + return Address; + } + void setAddress(uint64_t Value) { Address = Value; } + + uint64_t getSize() const { + assert(Size != ~UINT64_C(0) && "File size not set!"); + return Size; + } + void setSize(uint64_t Value) { Size = Value; } + + uint64_t getFileSize() const { + assert(FileSize != ~UINT64_C(0) && "File size not set!"); + return FileSize; + } + void setFileSize(uint64_t Value) { FileSize = Value; } + + /// @} +}; + +// FIXME: Same concerns as with SectionData. +class MCSymbolData : public ilist_node { +public: + const MCSymbol *Symbol; + + /// Fragment - The fragment this symbol's value is relative to, if any. + MCFragment *Fragment; + + /// Offset - The offset to apply to the fragment address to form this symbol's + /// value. + uint64_t Offset; + + /// IsExternal - True if this symbol is visible outside this translation + /// unit. + unsigned IsExternal : 1; + + /// IsPrivateExtern - True if this symbol is private extern. + unsigned IsPrivateExtern : 1; + + /// CommonSize - The size of the symbol, if it is 'common', or 0. + // + // FIXME: Pack this in with other fields? We could put it in offset, since a + // common symbol can never get a definition. + uint64_t CommonSize; + + /// CommonAlign - The alignment of the symbol, if it is 'common'. + // + // FIXME: Pack this in with other fields? + unsigned CommonAlign; + + /// Flags - The Flags field is used by object file implementations to store + /// additional per symbol information which is not easily classified. + uint32_t Flags; + + /// Index - Index field, for use by the object file implementation. + uint64_t Index; + +public: + // Only for use as sentinel. + MCSymbolData(); + MCSymbolData(const MCSymbol &_Symbol, MCFragment *_Fragment, uint64_t _Offset, + MCAssembler *A = 0); + + /// @name Accessors + /// @{ + + const MCSymbol &getSymbol() const { return *Symbol; } + + MCFragment *getFragment() const { return Fragment; } + void setFragment(MCFragment *Value) { Fragment = Value; } + + uint64_t getOffset() const { return Offset; } + void setOffset(uint64_t Value) { Offset = Value; } + + /// @} + /// @name Symbol Attributes + /// @{ + + bool isExternal() const { return IsExternal; } + void setExternal(bool Value) { IsExternal = Value; } + + bool isPrivateExtern() const { return IsPrivateExtern; } + void setPrivateExtern(bool Value) { IsPrivateExtern = Value; } + + /// isCommon - Is this a 'common' symbol. + bool isCommon() const { return CommonSize != 0; } + + /// setCommon - Mark this symbol as being 'common'. + /// + /// \param Size - The size of the symbol. + /// \param Align - The alignment of the symbol. + void setCommon(uint64_t Size, unsigned Align) { + CommonSize = Size; + CommonAlign = Align; + } + + /// getCommonSize - Return the size of a 'common' symbol. + uint64_t getCommonSize() const { + assert(isCommon() && "Not a 'common' symbol!"); + return CommonSize; + } + + /// getCommonAlignment - Return the alignment of a 'common' symbol. + unsigned getCommonAlignment() const { + assert(isCommon() && "Not a 'common' symbol!"); + return CommonAlign; + } + + /// getFlags - Get the (implementation defined) symbol flags. + uint32_t getFlags() const { return Flags; } + + /// setFlags - Set the (implementation defined) symbol flags. + void setFlags(uint32_t Value) { Flags = Value; } + + /// getIndex - Get the (implementation defined) index. + uint64_t getIndex() const { return Index; } + + /// setIndex - Set the (implementation defined) index. + void setIndex(uint64_t Value) { Index = Value; } + + /// @} +}; + +// FIXME: This really doesn't belong here. See comments below. +struct IndirectSymbolData { + MCSymbol *Symbol; + MCSectionData *SectionData; +}; + +class MCAssembler { +public: + typedef iplist SectionDataListType; + typedef iplist SymbolDataListType; + + typedef SectionDataListType::const_iterator const_iterator; + typedef SectionDataListType::iterator iterator; + + typedef SymbolDataListType::const_iterator const_symbol_iterator; + typedef SymbolDataListType::iterator symbol_iterator; + + typedef std::vector::iterator indirect_symbol_iterator; + +private: + MCAssembler(const MCAssembler&); // DO NOT IMPLEMENT + void operator=(const MCAssembler&); // DO NOT IMPLEMENT + + MCContext &Context; + + raw_ostream &OS; + + iplist Sections; + + iplist Symbols; + + std::vector IndirectSymbols; + + unsigned SubsectionsViaSymbols : 1; + +private: + /// LayoutSection - Assign offsets and sizes to the fragments in the section + /// \arg SD, and update the section size. The section file offset should + /// already have been computed. + void LayoutSection(MCSectionData &SD); + +public: + /// Construct a new assembler instance. + /// + /// \arg OS - The stream to output to. + // + // FIXME: How are we going to parameterize this? Two obvious options are stay + // concrete and require clients to pass in a target like object. The other + // option is to make this abstract, and have targets provide concrete + // implementations as we do with AsmParser. + MCAssembler(MCContext &_Context, raw_ostream &OS); + ~MCAssembler(); + + MCContext &getContext() const { return Context; } + + /// Finish - Do final processing and write the object to the output stream. + void Finish(); + + // FIXME: This does not belong here. + bool getSubsectionsViaSymbols() const { + return SubsectionsViaSymbols; + } + void setSubsectionsViaSymbols(bool Value) { + SubsectionsViaSymbols = Value; + } + + /// @name Section List Access + /// @{ + + const SectionDataListType &getSectionList() const { return Sections; } + SectionDataListType &getSectionList() { return Sections; } + + iterator begin() { return Sections.begin(); } + const_iterator begin() const { return Sections.begin(); } + + iterator end() { return Sections.end(); } + const_iterator end() const { return Sections.end(); } + + size_t size() const { return Sections.size(); } + + /// @} + /// @name Symbol List Access + /// @{ + + const SymbolDataListType &getSymbolList() const { return Symbols; } + SymbolDataListType &getSymbolList() { return Symbols; } + + symbol_iterator symbol_begin() { return Symbols.begin(); } + const_symbol_iterator symbol_begin() const { return Symbols.begin(); } + + symbol_iterator symbol_end() { return Symbols.end(); } + const_symbol_iterator symbol_end() const { return Symbols.end(); } + + size_t symbol_size() const { return Symbols.size(); } + + /// @} + /// @name Indirect Symbol List Access + /// @{ + + // FIXME: This is a total hack, this should not be here. Once things are + // factored so that the streamer has direct access to the .o writer, it can + // disappear. + std::vector &getIndirectSymbols() { + return IndirectSymbols; + } + + indirect_symbol_iterator indirect_symbol_begin() { + return IndirectSymbols.begin(); + } + + indirect_symbol_iterator indirect_symbol_end() { + return IndirectSymbols.end(); + } + + size_t indirect_symbol_size() const { return IndirectSymbols.size(); } + + /// @} +}; + +} // end namespace llvm + +#endif diff --git a/libclamav/c++/llvm/include/llvm/MC/MCCodeEmitter.h b/libclamav/c++/llvm/include/llvm/MC/MCCodeEmitter.h new file mode 100644 index 000000000..ad42dc2e5 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/MC/MCCodeEmitter.h @@ -0,0 +1,34 @@ +//===-- llvm/MC/MCCodeEmitter.h - Instruction Encoding ----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCCODEEMITTER_H +#define LLVM_MC_MCCODEEMITTER_H + +namespace llvm { +class MCInst; +class raw_ostream; + +/// MCCodeEmitter - Generic instruction encoding interface. +class MCCodeEmitter { + MCCodeEmitter(const MCCodeEmitter &); // DO NOT IMPLEMENT + void operator=(const MCCodeEmitter &); // DO NOT IMPLEMENT +protected: // Can only create subclasses. + MCCodeEmitter(); + +public: + virtual ~MCCodeEmitter(); + + /// EncodeInstruction - Encode the given \arg Inst to bytes on the output + /// stream \arg OS. + virtual void EncodeInstruction(const MCInst &Inst, raw_ostream &OS) const = 0; +}; + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/MC/MCContext.h b/libclamav/c++/llvm/include/llvm/MC/MCContext.h new file mode 100644 index 000000000..95c6bd4bb --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/MC/MCContext.h @@ -0,0 +1,159 @@ +//===- MCContext.h - Machine Code Context -----------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCCONTEXT_H +#define LLVM_MC_MCCONTEXT_H + +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/Support/Allocator.h" + +namespace llvm { + class MCExpr; + class MCSection; + class MCSymbol; + class StringRef; + class Twine; + + /// MCContext - Context object for machine code objects. This class owns all + /// of the sections that it creates. + /// + class MCContext { + MCContext(const MCContext&); // DO NOT IMPLEMENT + MCContext &operator=(const MCContext&); // DO NOT IMPLEMENT + + /// Sections - Bindings of names to allocated sections. + StringMap Sections; + + /// Symbols - Bindings of names to symbols. + StringMap Symbols; + + /// Allocator - Allocator object used for creating machine code objects. + /// + /// We use a bump pointer allocator to avoid the need to track all allocated + /// objects. + BumpPtrAllocator Allocator; + public: + MCContext(); + ~MCContext(); + + /// @name Symbol Managment + /// @{ + + /// CreateSymbol - Create a new symbol with the specified @param Name. + /// + /// @param Name - The symbol name, which must be unique across all symbols. + MCSymbol *CreateSymbol(StringRef Name); + + /// GetOrCreateSymbol - Lookup the symbol inside with the specified + /// @param Name. If it exists, return it. If not, create a forward + /// reference and return it. + /// + /// @param Name - The symbol name, which must be unique across all symbols. + /// @param IsTemporary - Whether this symbol is an assembler temporary, + /// which should not survive into the symbol table for the translation unit. + MCSymbol *GetOrCreateSymbol(StringRef Name); + MCSymbol *GetOrCreateSymbol(const Twine &Name); + + /// CreateTemporarySymbol - Create a new temporary symbol with the specified + /// @param Name. + /// + /// @param Name - The symbol name, for debugging purposes only, temporary + /// symbols do not surive assembly. If non-empty the name must be unique + /// across all symbols. + MCSymbol *CreateTemporarySymbol(StringRef Name = ""); + + /// LookupSymbol - Get the symbol for @param Name, or null. + MCSymbol *LookupSymbol(StringRef Name) const; + + /// @} + + void *Allocate(unsigned Size, unsigned Align = 8) { + return Allocator.Allocate(Size, Align); + } + void Deallocate(void *Ptr) { + } + }; + +} // end namespace llvm + +// operator new and delete aren't allowed inside namespaces. +// The throw specifications are mandated by the standard. +/// @brief Placement new for using the MCContext's allocator. +/// +/// This placement form of operator new uses the MCContext's allocator for +/// obtaining memory. It is a non-throwing new, which means that it returns +/// null on error. (If that is what the allocator does. The current does, so if +/// this ever changes, this operator will have to be changed, too.) +/// Usage looks like this (assuming there's an MCContext 'Context' in scope): +/// @code +/// // Default alignment (16) +/// IntegerLiteral *Ex = new (Context) IntegerLiteral(arguments); +/// // Specific alignment +/// IntegerLiteral *Ex2 = new (Context, 8) IntegerLiteral(arguments); +/// @endcode +/// Please note that you cannot use delete on the pointer; it must be +/// deallocated using an explicit destructor call followed by +/// @c Context.Deallocate(Ptr). +/// +/// @param Bytes The number of bytes to allocate. Calculated by the compiler. +/// @param C The MCContext that provides the allocator. +/// @param Alignment The alignment of the allocated memory (if the underlying +/// allocator supports it). +/// @return The allocated memory. Could be NULL. +inline void *operator new(size_t Bytes, llvm::MCContext &C, + size_t Alignment = 16) throw () { + return C.Allocate(Bytes, Alignment); +} +/// @brief Placement delete companion to the new above. +/// +/// This operator is just a companion to the new above. There is no way of +/// invoking it directly; see the new operator for more details. This operator +/// is called implicitly by the compiler if a placement new expression using +/// the MCContext throws in the object constructor. +inline void operator delete(void *Ptr, llvm::MCContext &C, size_t) + throw () { + C.Deallocate(Ptr); +} + +/// This placement form of operator new[] uses the MCContext's allocator for +/// obtaining memory. It is a non-throwing new[], which means that it returns +/// null on error. +/// Usage looks like this (assuming there's an MCContext 'Context' in scope): +/// @code +/// // Default alignment (16) +/// char *data = new (Context) char[10]; +/// // Specific alignment +/// char *data = new (Context, 8) char[10]; +/// @endcode +/// Please note that you cannot use delete on the pointer; it must be +/// deallocated using an explicit destructor call followed by +/// @c Context.Deallocate(Ptr). +/// +/// @param Bytes The number of bytes to allocate. Calculated by the compiler. +/// @param C The MCContext that provides the allocator. +/// @param Alignment The alignment of the allocated memory (if the underlying +/// allocator supports it). +/// @return The allocated memory. Could be NULL. +inline void *operator new[](size_t Bytes, llvm::MCContext& C, + size_t Alignment = 16) throw () { + return C.Allocate(Bytes, Alignment); +} + +/// @brief Placement delete[] companion to the new[] above. +/// +/// This operator is just a companion to the new[] above. There is no way of +/// invoking it directly; see the new[] operator for more details. This operator +/// is called implicitly by the compiler if a placement new[] expression using +/// the MCContext throws in the object constructor. +inline void operator delete[](void *Ptr, llvm::MCContext &C) throw () { + C.Deallocate(Ptr); +} + +#endif diff --git a/libclamav/c++/llvm/include/llvm/MC/MCDisassembler.h b/libclamav/c++/llvm/include/llvm/MC/MCDisassembler.h new file mode 100644 index 000000000..ffa0e419c --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/MC/MCDisassembler.h @@ -0,0 +1,50 @@ +//===-- llvm/MC/MCDisassembler.h - Disassembler interface -------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +#ifndef MCDISASSEMBLER_H +#define MCDISASSEMBLER_H + +#include "llvm/System/DataTypes.h" + +namespace llvm { + +class MCInst; +class MemoryObject; +class raw_ostream; + +/// MCDisassembler - Superclass for all disassemblers. Consumes a memory region +/// and provides an array of assembly instructions. +class MCDisassembler { +public: + /// Constructor - Performs initial setup for the disassembler. + MCDisassembler() {} + + virtual ~MCDisassembler(); + + /// getInstruction - Returns the disassembly of a single instruction. + /// + /// @param instr - An MCInst to populate with the contents of the + /// instruction. + /// @param size - A value to populate with the size of the instruction, or + /// the number of bytes consumed while attempting to decode + /// an invalid instruction. + /// @param region - The memory object to use as a source for machine code. + /// @param address - The address, in the memory space of region, of the first + /// byte of the instruction. + /// @param vStream - The stream to print warnings and diagnostic messages on. + /// @return - True if the instruction is valid; false otherwise. + virtual bool getInstruction(MCInst& instr, + uint64_t& size, + const MemoryObject ®ion, + uint64_t address, + raw_ostream &vStream) const = 0; +}; + +} // namespace llvm + +#endif diff --git a/libclamav/c++/llvm/include/llvm/MC/MCExpr.h b/libclamav/c++/llvm/include/llvm/MC/MCExpr.h new file mode 100644 index 000000000..13d40eca7 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/MC/MCExpr.h @@ -0,0 +1,326 @@ +//===- MCExpr.h - Assembly Level Expressions --------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCEXPR_H +#define LLVM_MC_MCEXPR_H + +#include "llvm/Support/Casting.h" +#include "llvm/System/DataTypes.h" + +namespace llvm { +class MCAsmInfo; +class MCContext; +class MCSymbol; +class MCValue; +class raw_ostream; +class StringRef; + +/// MCExpr - Base class for the full range of assembler expressions which are +/// needed for parsing. +class MCExpr { +public: + enum ExprKind { + Binary, ///< Binary expressions. + Constant, ///< Constant expressions. + SymbolRef, ///< References to labels and assigned expressions. + Unary ///< Unary expressions. + }; + +private: + ExprKind Kind; + + MCExpr(const MCExpr&); // DO NOT IMPLEMENT + void operator=(const MCExpr&); // DO NOT IMPLEMENT + +protected: + MCExpr(ExprKind _Kind) : Kind(_Kind) {} + +public: + /// @name Accessors + /// @{ + + ExprKind getKind() const { return Kind; } + + /// @} + /// @name Utility Methods + /// @{ + + void print(raw_ostream &OS, const MCAsmInfo *MAI) const; + void dump() const; + + /// @} + /// @name Expression Evaluation + /// @{ + + /// EvaluateAsAbsolute - Try to evaluate the expression to an absolute value. + /// + /// @param Res - The absolute value, if evaluation succeeds. + /// @result - True on success. + bool EvaluateAsAbsolute(int64_t &Res) const; + + /// EvaluateAsRelocatable - Try to evaluate the expression to a relocatable + /// value, i.e. an expression of the fixed form (a - b + constant). + /// + /// @param Res - The relocatable value, if evaluation succeeds. + /// @result - True on success. + bool EvaluateAsRelocatable(MCValue &Res) const; + + /// @} + + static bool classof(const MCExpr *) { return true; } +}; + +//// MCConstantExpr - Represent a constant integer expression. +class MCConstantExpr : public MCExpr { + int64_t Value; + + MCConstantExpr(int64_t _Value) + : MCExpr(MCExpr::Constant), Value(_Value) {} + +public: + /// @name Construction + /// @{ + + static const MCConstantExpr *Create(int64_t Value, MCContext &Ctx); + + /// @} + /// @name Accessors + /// @{ + + int64_t getValue() const { return Value; } + + /// @} + + static bool classof(const MCExpr *E) { + return E->getKind() == MCExpr::Constant; + } + static bool classof(const MCConstantExpr *) { return true; } +}; + +/// MCSymbolRefExpr - Represent a reference to a symbol from inside an +/// expression. +/// +/// A symbol reference in an expression may be a use of a label, a use of an +/// assembler variable (defined constant), or constitute an implicit definition +/// of the symbol as external. +class MCSymbolRefExpr : public MCExpr { + const MCSymbol *Symbol; + + MCSymbolRefExpr(const MCSymbol *_Symbol) + : MCExpr(MCExpr::SymbolRef), Symbol(_Symbol) {} + +public: + /// @name Construction + /// @{ + + static const MCSymbolRefExpr *Create(const MCSymbol *Symbol, MCContext &Ctx); + static const MCSymbolRefExpr *Create(StringRef Name, MCContext &Ctx); + + /// @} + /// @name Accessors + /// @{ + + const MCSymbol &getSymbol() const { return *Symbol; } + + /// @} + + static bool classof(const MCExpr *E) { + return E->getKind() == MCExpr::SymbolRef; + } + static bool classof(const MCSymbolRefExpr *) { return true; } +}; + +/// MCUnaryExpr - Unary assembler expressions. +class MCUnaryExpr : public MCExpr { +public: + enum Opcode { + LNot, ///< Logical negation. + Minus, ///< Unary minus. + Not, ///< Bitwise negation. + Plus ///< Unary plus. + }; + +private: + Opcode Op; + const MCExpr *Expr; + + MCUnaryExpr(Opcode _Op, const MCExpr *_Expr) + : MCExpr(MCExpr::Unary), Op(_Op), Expr(_Expr) {} + +public: + /// @name Construction + /// @{ + + static const MCUnaryExpr *Create(Opcode Op, const MCExpr *Expr, + MCContext &Ctx); + static const MCUnaryExpr *CreateLNot(const MCExpr *Expr, MCContext &Ctx) { + return Create(LNot, Expr, Ctx); + } + static const MCUnaryExpr *CreateMinus(const MCExpr *Expr, MCContext &Ctx) { + return Create(Minus, Expr, Ctx); + } + static const MCUnaryExpr *CreateNot(const MCExpr *Expr, MCContext &Ctx) { + return Create(Not, Expr, Ctx); + } + static const MCUnaryExpr *CreatePlus(const MCExpr *Expr, MCContext &Ctx) { + return Create(Plus, Expr, Ctx); + } + + /// @} + /// @name Accessors + /// @{ + + /// getOpcode - Get the kind of this unary expression. + Opcode getOpcode() const { return Op; } + + /// getSubExpr - Get the child of this unary expression. + const MCExpr *getSubExpr() const { return Expr; } + + /// @} + + static bool classof(const MCExpr *E) { + return E->getKind() == MCExpr::Unary; + } + static bool classof(const MCUnaryExpr *) { return true; } +}; + +/// MCBinaryExpr - Binary assembler expressions. +class MCBinaryExpr : public MCExpr { +public: + enum Opcode { + Add, ///< Addition. + And, ///< Bitwise and. + Div, ///< Division. + EQ, ///< Equality comparison. + GT, ///< Greater than comparison. + GTE, ///< Greater than or equal comparison. + LAnd, ///< Logical and. + LOr, ///< Logical or. + LT, ///< Less than comparison. + LTE, ///< Less than or equal comparison. + Mod, ///< Modulus. + Mul, ///< Multiplication. + NE, ///< Inequality comparison. + Or, ///< Bitwise or. + Shl, ///< Bitwise shift left. + Shr, ///< Bitwise shift right. + Sub, ///< Subtraction. + Xor ///< Bitwise exclusive or. + }; + +private: + Opcode Op; + const MCExpr *LHS, *RHS; + + MCBinaryExpr(Opcode _Op, const MCExpr *_LHS, const MCExpr *_RHS) + : MCExpr(MCExpr::Binary), Op(_Op), LHS(_LHS), RHS(_RHS) {} + +public: + /// @name Construction + /// @{ + + static const MCBinaryExpr *Create(Opcode Op, const MCExpr *LHS, + const MCExpr *RHS, MCContext &Ctx); + static const MCBinaryExpr *CreateAdd(const MCExpr *LHS, const MCExpr *RHS, + MCContext &Ctx) { + return Create(Add, LHS, RHS, Ctx); + } + static const MCBinaryExpr *CreateAnd(const MCExpr *LHS, const MCExpr *RHS, + MCContext &Ctx) { + return Create(And, LHS, RHS, Ctx); + } + static const MCBinaryExpr *CreateDiv(const MCExpr *LHS, const MCExpr *RHS, + MCContext &Ctx) { + return Create(Div, LHS, RHS, Ctx); + } + static const MCBinaryExpr *CreateEQ(const MCExpr *LHS, const MCExpr *RHS, + MCContext &Ctx) { + return Create(EQ, LHS, RHS, Ctx); + } + static const MCBinaryExpr *CreateGT(const MCExpr *LHS, const MCExpr *RHS, + MCContext &Ctx) { + return Create(GT, LHS, RHS, Ctx); + } + static const MCBinaryExpr *CreateGTE(const MCExpr *LHS, const MCExpr *RHS, + MCContext &Ctx) { + return Create(GTE, LHS, RHS, Ctx); + } + static const MCBinaryExpr *CreateLAnd(const MCExpr *LHS, const MCExpr *RHS, + MCContext &Ctx) { + return Create(LAnd, LHS, RHS, Ctx); + } + static const MCBinaryExpr *CreateLOr(const MCExpr *LHS, const MCExpr *RHS, + MCContext &Ctx) { + return Create(LOr, LHS, RHS, Ctx); + } + static const MCBinaryExpr *CreateLT(const MCExpr *LHS, const MCExpr *RHS, + MCContext &Ctx) { + return Create(LT, LHS, RHS, Ctx); + } + static const MCBinaryExpr *CreateLTE(const MCExpr *LHS, const MCExpr *RHS, + MCContext &Ctx) { + return Create(LTE, LHS, RHS, Ctx); + } + static const MCBinaryExpr *CreateMod(const MCExpr *LHS, const MCExpr *RHS, + MCContext &Ctx) { + return Create(Mod, LHS, RHS, Ctx); + } + static const MCBinaryExpr *CreateMul(const MCExpr *LHS, const MCExpr *RHS, + MCContext &Ctx) { + return Create(Mul, LHS, RHS, Ctx); + } + static const MCBinaryExpr *CreateNE(const MCExpr *LHS, const MCExpr *RHS, + MCContext &Ctx) { + return Create(NE, LHS, RHS, Ctx); + } + static const MCBinaryExpr *CreateOr(const MCExpr *LHS, const MCExpr *RHS, + MCContext &Ctx) { + return Create(Or, LHS, RHS, Ctx); + } + static const MCBinaryExpr *CreateShl(const MCExpr *LHS, const MCExpr *RHS, + MCContext &Ctx) { + return Create(Shl, LHS, RHS, Ctx); + } + static const MCBinaryExpr *CreateShr(const MCExpr *LHS, const MCExpr *RHS, + MCContext &Ctx) { + return Create(Shr, LHS, RHS, Ctx); + } + static const MCBinaryExpr *CreateSub(const MCExpr *LHS, const MCExpr *RHS, + MCContext &Ctx) { + return Create(Sub, LHS, RHS, Ctx); + } + static const MCBinaryExpr *CreateXor(const MCExpr *LHS, const MCExpr *RHS, + MCContext &Ctx) { + return Create(Xor, LHS, RHS, Ctx); + } + + /// @} + /// @name Accessors + /// @{ + + /// getOpcode - Get the kind of this binary expression. + Opcode getOpcode() const { return Op; } + + /// getLHS - Get the left-hand side expression of the binary operator. + const MCExpr *getLHS() const { return LHS; } + + /// getRHS - Get the right-hand side expression of the binary operator. + const MCExpr *getRHS() const { return RHS; } + + /// @} + + static bool classof(const MCExpr *E) { + return E->getKind() == MCExpr::Binary; + } + static bool classof(const MCBinaryExpr *) { return true; } +}; + +} // end namespace llvm + +#endif diff --git a/libclamav/c++/llvm/include/llvm/MC/MCInst.h b/libclamav/c++/llvm/include/llvm/MC/MCInst.h new file mode 100644 index 000000000..29b38dd15 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/MC/MCInst.h @@ -0,0 +1,133 @@ +//===-- llvm/MC/MCInst.h - MCInst class -------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the declaration of the MCInst and MCOperand classes, which +// is the basic representation used to represent low-level machine code +// instructions. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCINST_H +#define LLVM_MC_MCINST_H + +#include "llvm/ADT/SmallVector.h" +#include "llvm/System/DataTypes.h" + +namespace llvm { +class raw_ostream; +class MCAsmInfo; +class MCExpr; + +/// MCOperand - Instances of this class represent operands of the MCInst class. +/// This is a simple discriminated union. +class MCOperand { + enum MachineOperandType { + kInvalid, ///< Uninitialized. + kRegister, ///< Register operand. + kImmediate, ///< Immediate operand. + kExpr ///< Relocatable immediate operand. + }; + unsigned char Kind; + + union { + unsigned RegVal; + int64_t ImmVal; + const MCExpr *ExprVal; + }; +public: + + MCOperand() : Kind(kInvalid) {} + + bool isValid() const { return Kind != kInvalid; } + bool isReg() const { return Kind == kRegister; } + bool isImm() const { return Kind == kImmediate; } + bool isExpr() const { return Kind == kExpr; } + + /// getReg - Returns the register number. + unsigned getReg() const { + assert(isReg() && "This is not a register operand!"); + return RegVal; + } + + /// setReg - Set the register number. + void setReg(unsigned Reg) { + assert(isReg() && "This is not a register operand!"); + RegVal = Reg; + } + + int64_t getImm() const { + assert(isImm() && "This is not an immediate"); + return ImmVal; + } + void setImm(int64_t Val) { + assert(isImm() && "This is not an immediate"); + ImmVal = Val; + } + + const MCExpr *getExpr() const { + assert(isExpr() && "This is not an expression"); + return ExprVal; + } + void setExpr(const MCExpr *Val) { + assert(isExpr() && "This is not an expression"); + ExprVal = Val; + } + + static MCOperand CreateReg(unsigned Reg) { + MCOperand Op; + Op.Kind = kRegister; + Op.RegVal = Reg; + return Op; + } + static MCOperand CreateImm(int64_t Val) { + MCOperand Op; + Op.Kind = kImmediate; + Op.ImmVal = Val; + return Op; + } + static MCOperand CreateExpr(const MCExpr *Val) { + MCOperand Op; + Op.Kind = kExpr; + Op.ExprVal = Val; + return Op; + } + + void print(raw_ostream &OS, const MCAsmInfo *MAI) const; + void dump() const; +}; + + +/// MCInst - Instances of this class represent a single low-level machine +/// instruction. +class MCInst { + unsigned Opcode; + SmallVector Operands; +public: + MCInst() : Opcode(0) {} + + void setOpcode(unsigned Op) { Opcode = Op; } + + unsigned getOpcode() const { return Opcode; } + + const MCOperand &getOperand(unsigned i) const { return Operands[i]; } + MCOperand &getOperand(unsigned i) { return Operands[i]; } + unsigned getNumOperands() const { return Operands.size(); } + + void addOperand(const MCOperand &Op) { + Operands.push_back(Op); + } + + void print(raw_ostream &OS, const MCAsmInfo *MAI) const; + void dump() const; +}; + + +} // end namespace llvm + +#endif diff --git a/libclamav/c++/llvm/include/llvm/MC/MCInstPrinter.h b/libclamav/c++/llvm/include/llvm/MC/MCInstPrinter.h new file mode 100644 index 000000000..d62a9dae7 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/MC/MCInstPrinter.h @@ -0,0 +1,37 @@ +//===-- MCInstPrinter.h - Convert an MCInst to target assembly syntax -----===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCINSTPRINTER_H +#define LLVM_MC_MCINSTPRINTER_H + +namespace llvm { +class MCInst; +class raw_ostream; +class MCAsmInfo; + + +/// MCInstPrinter - This is an instance of a target assembly language printer +/// that converts an MCInst to valid target assembly syntax. +class MCInstPrinter { +protected: + raw_ostream &O; + const MCAsmInfo &MAI; +public: + MCInstPrinter(raw_ostream &o, const MCAsmInfo &mai) : O(o), MAI(mai) {} + + virtual ~MCInstPrinter(); + + /// printInst - Print the specified MCInst to the current raw_ostream. + /// + virtual void printInst(const MCInst *MI) = 0; +}; + +} // namespace llvm + +#endif diff --git a/libclamav/c++/llvm/include/llvm/MC/MCSection.h b/libclamav/c++/llvm/include/llvm/MC/MCSection.h new file mode 100644 index 000000000..ceb6d278c --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/MC/MCSection.h @@ -0,0 +1,71 @@ +//===- MCSection.h - Machine Code Sections ----------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the MCSection class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCSECTION_H +#define LLVM_MC_MCSECTION_H + +#include +#include "llvm/ADT/StringRef.h" +#include "llvm/MC/SectionKind.h" + +namespace llvm { + class MCContext; + class MCAsmInfo; + class raw_ostream; + + /// MCSection - Instances of this class represent a uniqued identifier for a + /// section in the current translation unit. The MCContext class uniques and + /// creates these. + class MCSection { + MCSection(const MCSection&); // DO NOT IMPLEMENT + void operator=(const MCSection&); // DO NOT IMPLEMENT + protected: + MCSection(SectionKind K) : Kind(K) {} + SectionKind Kind; + public: + virtual ~MCSection(); + + SectionKind getKind() const { return Kind; } + + virtual void PrintSwitchToSection(const MCAsmInfo &MAI, + raw_ostream &OS) const = 0; + }; + + class MCSectionCOFF : public MCSection { + std::string Name; + + /// IsDirective - This is true if the section name is a directive, not + /// something that should be printed with ".section". + /// + /// FIXME: This is a hack. Switch to a semantic view of the section instead + /// of a syntactic one. + bool IsDirective; + + MCSectionCOFF(StringRef name, bool isDirective, SectionKind K) + : MCSection(K), Name(name), IsDirective(isDirective) { + } + public: + + static MCSectionCOFF *Create(StringRef Name, bool IsDirective, + SectionKind K, MCContext &Ctx); + + const std::string &getName() const { return Name; } + bool isDirective() const { return IsDirective; } + + virtual void PrintSwitchToSection(const MCAsmInfo &MAI, + raw_ostream &OS) const; + }; + +} // end namespace llvm + +#endif diff --git a/libclamav/c++/llvm/include/llvm/MC/MCSectionELF.h b/libclamav/c++/llvm/include/llvm/MC/MCSectionELF.h new file mode 100644 index 000000000..4ec745fff --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/MC/MCSectionELF.h @@ -0,0 +1,191 @@ +//===- MCSectionELF.h - ELF Machine Code Sections ---------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the MCSectionELF class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCSECTIONELF_H +#define LLVM_MC_MCSECTIONELF_H + +#include "llvm/MC/MCSection.h" + +namespace llvm { + +/// MCSectionELF - This represents a section on linux, lots of unix variants +/// and some bare metal systems. +class MCSectionELF : public MCSection { + std::string SectionName; + + /// Type - This is the sh_type field of a section, drawn from the enums below. + unsigned Type; + + /// Flags - This is the sh_flags field of a section, drawn from the enums. + /// below. + unsigned Flags; + + /// IsExplicit - Indicates that this section comes from globals with an + /// explicit section specfied. + bool IsExplicit; + +protected: + MCSectionELF(StringRef Section, unsigned type, unsigned flags, + SectionKind K, bool isExplicit) + : MCSection(K), SectionName(Section.str()), Type(type), Flags(flags), + IsExplicit(isExplicit) {} +public: + + static MCSectionELF *Create(StringRef Section, unsigned Type, + unsigned Flags, SectionKind K, bool isExplicit, + MCContext &Ctx); + + /// ShouldOmitSectionDirective - Decides whether a '.section' directive + /// should be printed before the section name + bool ShouldOmitSectionDirective(const char *Name, + const MCAsmInfo &MAI) const; + + /// ShouldPrintSectionType - Only prints the section type if supported + bool ShouldPrintSectionType(unsigned Ty) const; + + /// HasCommonSymbols - True if this section holds common symbols, this is + /// indicated on the ELF object file by a symbol with SHN_COMMON section + /// header index. + bool HasCommonSymbols() const; + + /// These are the section type and flags fields. An ELF section can have + /// only one Type, but can have more than one of the flags specified. + /// + /// Valid section types. + enum { + // This value marks the section header as inactive. + SHT_NULL = 0x00U, + + // Holds information defined by the program, with custom format and meaning. + SHT_PROGBITS = 0x01U, + + // This section holds a symbol table. + SHT_SYMTAB = 0x02U, + + // The section holds a string table. + SHT_STRTAB = 0x03U, + + // The section holds relocation entries with explicit addends. + SHT_RELA = 0x04U, + + // The section holds a symbol hash table. + SHT_HASH = 0x05U, + + // Information for dynamic linking. + SHT_DYNAMIC = 0x06U, + + // The section holds information that marks the file in some way. + SHT_NOTE = 0x07U, + + // A section of this type occupies no space in the file. + SHT_NOBITS = 0x08U, + + // The section holds relocation entries without explicit addends. + SHT_REL = 0x09U, + + // This section type is reserved but has unspecified semantics. + SHT_SHLIB = 0x0AU, + + // This section holds a symbol table. + SHT_DYNSYM = 0x0BU, + + // This section contains an array of pointers to initialization functions. + SHT_INIT_ARRAY = 0x0EU, + + // This section contains an array of pointers to termination functions. + SHT_FINI_ARRAY = 0x0FU, + + // This section contains an array of pointers to functions that are invoked + // before all other initialization functions. + SHT_PREINIT_ARRAY = 0x10U, + + // A section group is a set of sections that are related and that must be + // treated specially by the linker. + SHT_GROUP = 0x11U, + + // This section is associated with a section of type SHT_SYMTAB, when the + // referenced symbol table contain the escape value SHN_XINDEX + SHT_SYMTAB_SHNDX = 0x12U, + + LAST_KNOWN_SECTION_TYPE = SHT_SYMTAB_SHNDX + }; + + /// Valid section flags. + enum { + // The section contains data that should be writable. + SHF_WRITE = 0x1U, + + // The section occupies memory during execution. + SHF_ALLOC = 0x2U, + + // The section contains executable machine instructions. + SHF_EXECINSTR = 0x4U, + + // The data in the section may be merged to eliminate duplication. + SHF_MERGE = 0x10U, + + // Elements in the section consist of null-terminated character strings. + SHF_STRINGS = 0x20U, + + // A field in this section holds a section header table index. + SHF_INFO_LINK = 0x40U, + + // Adds special ordering requirements for link editors. + SHF_LINK_ORDER = 0x80U, + + // This section requires special OS-specific processing to avoid incorrect + // behavior. + SHF_OS_NONCONFORMING = 0x100U, + + // This section is a member of a section group. + SHF_GROUP = 0x200U, + + // This section holds Thread-Local Storage. + SHF_TLS = 0x400U, + + /// FIRST_TARGET_DEP_FLAG - This is the first flag that subclasses are + /// allowed to specify. + FIRST_TARGET_DEP_FLAG = 0x800U, + + /// TARGET_INDEP_SHF - This is the bitmask for all the target independent + /// section flags. Targets can define their own target flags above these. + /// If they do that, they should implement their own MCSectionELF subclasses + /// and implement the virtual method hooks below to handle printing needs. + TARGET_INDEP_SHF = FIRST_TARGET_DEP_FLAG-1U + }; + + StringRef getSectionName() const { + return StringRef(SectionName); + } + + unsigned getType() const { return Type; } + unsigned getFlags() const { return Flags; } + + virtual void PrintSwitchToSection(const MCAsmInfo &MAI, + raw_ostream &OS) const; + + + /// PrintTargetSpecificSectionFlags - Targets that define their own + /// MCSectionELF subclasses with target specific section flags should + /// implement this method if they end up adding letters to the attributes + /// list. + virtual void PrintTargetSpecificSectionFlags(const MCAsmInfo &MAI, + raw_ostream &OS) const { + } + + +}; + +} // end namespace llvm + +#endif diff --git a/libclamav/c++/llvm/include/llvm/MC/MCSectionMachO.h b/libclamav/c++/llvm/include/llvm/MC/MCSectionMachO.h new file mode 100644 index 000000000..61568194d --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/MC/MCSectionMachO.h @@ -0,0 +1,175 @@ +//===- MCSectionMachO.h - MachO Machine Code Sections -----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the MCSectionMachO class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCSECTIONMACHO_H +#define LLVM_MC_MCSECTIONMACHO_H + +#include "llvm/MC/MCSection.h" + +namespace llvm { + +/// MCSectionMachO - This represents a section on a Mach-O system (used by +/// Mac OS X). On a Mac system, these are also described in +/// /usr/include/mach-o/loader.h. +class MCSectionMachO : public MCSection { + char SegmentName[16]; // Not necessarily null terminated! + char SectionName[16]; // Not necessarily null terminated! + + /// TypeAndAttributes - This is the SECTION_TYPE and SECTION_ATTRIBUTES + /// field of a section, drawn from the enums below. + unsigned TypeAndAttributes; + + /// Reserved2 - The 'reserved2' field of a section, used to represent the + /// size of stubs, for example. + unsigned Reserved2; + + MCSectionMachO(StringRef Segment, StringRef Section, + unsigned TAA, unsigned reserved2, SectionKind K) + : MCSection(K), TypeAndAttributes(TAA), Reserved2(reserved2) { + assert(Segment.size() <= 16 && Section.size() <= 16 && + "Segment or section string too long"); + for (unsigned i = 0; i != 16; ++i) { + if (i < Segment.size()) + SegmentName[i] = Segment[i]; + else + SegmentName[i] = 0; + + if (i < Section.size()) + SectionName[i] = Section[i]; + else + SectionName[i] = 0; + } + } +public: + + static MCSectionMachO *Create(StringRef Segment, + StringRef Section, + unsigned TypeAndAttributes, + unsigned Reserved2, + SectionKind K, MCContext &Ctx); + + /// These are the section type and attributes fields. A MachO section can + /// have only one Type, but can have any of the attributes specified. + enum { + // TypeAndAttributes bitmasks. + SECTION_TYPE = 0x000000FFU, + SECTION_ATTRIBUTES = 0xFFFFFF00U, + + // Valid section types. + + /// S_REGULAR - Regular section. + S_REGULAR = 0x00U, + /// S_ZEROFILL - Zero fill on demand section. + S_ZEROFILL = 0x01U, + /// S_CSTRING_LITERALS - Section with literal C strings. + S_CSTRING_LITERALS = 0x02U, + /// S_4BYTE_LITERALS - Section with 4 byte literals. + S_4BYTE_LITERALS = 0x03U, + /// S_8BYTE_LITERALS - Section with 8 byte literals. + S_8BYTE_LITERALS = 0x04U, + /// S_LITERAL_POINTERS - Section with pointers to literals. + S_LITERAL_POINTERS = 0x05U, + /// S_NON_LAZY_SYMBOL_POINTERS - Section with non-lazy symbol pointers. + S_NON_LAZY_SYMBOL_POINTERS = 0x06U, + /// S_LAZY_SYMBOL_POINTERS - Section with lazy symbol pointers. + S_LAZY_SYMBOL_POINTERS = 0x07U, + /// S_SYMBOL_STUBS - Section with symbol stubs, byte size of stub in + /// the Reserved2 field. + S_SYMBOL_STUBS = 0x08U, + /// S_SYMBOL_STUBS - Section with only function pointers for + /// initialization. + S_MOD_INIT_FUNC_POINTERS = 0x09U, + /// S_MOD_INIT_FUNC_POINTERS - Section with only function pointers for + /// termination. + S_MOD_TERM_FUNC_POINTERS = 0x0AU, + /// S_COALESCED - Section contains symbols that are to be coalesced. + S_COALESCED = 0x0BU, + /// S_GB_ZEROFILL - Zero fill on demand section (that can be larger than 4 + /// gigabytes). + S_GB_ZEROFILL = 0x0CU, + /// S_INTERPOSING - Section with only pairs of function pointers for + /// interposing. + S_INTERPOSING = 0x0DU, + /// S_16BYTE_LITERALS - Section with only 16 byte literals. + S_16BYTE_LITERALS = 0x0EU, + /// S_DTRACE_DOF - Section contains DTrace Object Format. + S_DTRACE_DOF = 0x0FU, + /// S_LAZY_DYLIB_SYMBOL_POINTERS - Section with lazy symbol pointers to + /// lazy loaded dylibs. + S_LAZY_DYLIB_SYMBOL_POINTERS = 0x10U, + + LAST_KNOWN_SECTION_TYPE = S_LAZY_DYLIB_SYMBOL_POINTERS, + + + // Valid section attributes. + + /// S_ATTR_PURE_INSTRUCTIONS - Section contains only true machine + /// instructions. + S_ATTR_PURE_INSTRUCTIONS = 1U << 31, + /// S_ATTR_NO_TOC - Section contains coalesced symbols that are not to be + /// in a ranlib table of contents. + S_ATTR_NO_TOC = 1U << 30, + /// S_ATTR_STRIP_STATIC_SYMS - Ok to strip static symbols in this section + /// in files with the MY_DYLDLINK flag. + S_ATTR_STRIP_STATIC_SYMS = 1U << 29, + /// S_ATTR_NO_DEAD_STRIP - No dead stripping. + S_ATTR_NO_DEAD_STRIP = 1U << 28, + /// S_ATTR_LIVE_SUPPORT - Blocks are live if they reference live blocks. + S_ATTR_LIVE_SUPPORT = 1U << 27, + /// S_ATTR_SELF_MODIFYING_CODE - Used with i386 code stubs written on by + /// dyld. + S_ATTR_SELF_MODIFYING_CODE = 1U << 26, + /// S_ATTR_DEBUG - A debug section. + S_ATTR_DEBUG = 1U << 25, + /// S_ATTR_SOME_INSTRUCTIONS - Section contains some machine instructions. + S_ATTR_SOME_INSTRUCTIONS = 1U << 10, + /// S_ATTR_EXT_RELOC - Section has external relocation entries. + S_ATTR_EXT_RELOC = 1U << 9, + /// S_ATTR_LOC_RELOC - Section has local relocation entries. + S_ATTR_LOC_RELOC = 1U << 8 + }; + + StringRef getSegmentName() const { + // SegmentName is not necessarily null terminated! + if (SegmentName[15]) + return StringRef(SegmentName, 16); + return StringRef(SegmentName); + } + StringRef getSectionName() const { + // SectionName is not necessarily null terminated! + if (SectionName[15]) + return StringRef(SectionName, 16); + return StringRef(SectionName); + } + + unsigned getTypeAndAttributes() const { return TypeAndAttributes; } + unsigned getStubSize() const { return Reserved2; } + + /// ParseSectionSpecifier - Parse the section specifier indicated by "Spec". + /// This is a string that can appear after a .section directive in a mach-o + /// flavored .s file. If successful, this fills in the specified Out + /// parameters and returns an empty string. When an invalid section + /// specifier is present, this returns a string indicating the problem. + static std::string ParseSectionSpecifier(StringRef Spec, // In. + StringRef &Segment, // Out. + StringRef &Section, // Out. + unsigned &TAA, // Out. + unsigned &StubSize); // Out. + + virtual void PrintSwitchToSection(const MCAsmInfo &MAI, + raw_ostream &OS) const; +}; + +} // end namespace llvm + +#endif diff --git a/libclamav/c++/llvm/include/llvm/MC/MCStreamer.h b/libclamav/c++/llvm/include/llvm/MC/MCStreamer.h new file mode 100644 index 000000000..5febed71b --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/MC/MCStreamer.h @@ -0,0 +1,240 @@ +//===- MCStreamer.h - High-level Streaming Machine Code Output --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the MCStreamer class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCSTREAMER_H +#define LLVM_MC_MCSTREAMER_H + +#include "llvm/System/DataTypes.h" + +namespace llvm { + class MCAsmInfo; + class MCCodeEmitter; + class MCContext; + class MCExpr; + class MCInst; + class MCInstPrinter; + class MCSection; + class MCSymbol; + class StringRef; + class raw_ostream; + + /// MCStreamer - Streaming machine code generation interface. This interface + /// is intended to provide a programatic interface that is very similar to the + /// level that an assembler .s file provides. It has callbacks to emit bytes, + /// handle directives, etc. The implementation of this interface retains + /// state to know what the current section is etc. + /// + /// There are multiple implementations of this interface: one for writing out + /// a .s file, and implementations that write out .o files of various formats. + /// + class MCStreamer { + public: + enum SymbolAttr { + Global, /// .globl + Hidden, /// .hidden (ELF) + IndirectSymbol, /// .indirect_symbol (Apple) + Internal, /// .internal (ELF) + LazyReference, /// .lazy_reference (Apple) + NoDeadStrip, /// .no_dead_strip (Apple) + PrivateExtern, /// .private_extern (Apple) + Protected, /// .protected (ELF) + Reference, /// .reference (Apple) + Weak, /// .weak + WeakDefinition, /// .weak_definition (Apple) + WeakReference, /// .weak_reference (Apple) + + SymbolAttrFirst = Global, + SymbolAttrLast = WeakReference + }; + + enum AssemblerFlag { + SubsectionsViaSymbols /// .subsections_via_symbols (Apple) + }; + + private: + MCContext &Context; + + MCStreamer(const MCStreamer&); // DO NOT IMPLEMENT + MCStreamer &operator=(const MCStreamer&); // DO NOT IMPLEMENT + + protected: + MCStreamer(MCContext &Ctx); + + /// CurSection - This is the current section code is being emitted to, it is + /// kept up to date by SwitchSection. + const MCSection *CurSection; + + public: + virtual ~MCStreamer(); + + MCContext &getContext() const { return Context; } + + /// @name Symbol & Section Management + /// @{ + + /// getCurrentSection - Return the current seciton that the streamer is + /// emitting code to. + const MCSection *getCurrentSection() const { return CurSection; } + + /// SwitchSection - Set the current section where code is being emitted to + /// @param Section. This is required to update CurSection. + /// + /// This corresponds to assembler directives like .section, .text, etc. + virtual void SwitchSection(const MCSection *Section) = 0; + + /// EmitLabel - Emit a label for @param Symbol into the current section. + /// + /// This corresponds to an assembler statement such as: + /// foo: + /// + /// @param Symbol - The symbol to emit. A given symbol should only be + /// emitted as a label once, and symbols emitted as a label should never be + /// used in an assignment. + virtual void EmitLabel(MCSymbol *Symbol) = 0; + + /// EmitAssemblerFlag - Note in the output the specified @param Flag + virtual void EmitAssemblerFlag(AssemblerFlag Flag) = 0; + + /// EmitAssignment - Emit an assignment of @param Value to @param Symbol. + /// + /// This corresponds to an assembler statement such as: + /// symbol = value + /// + /// The assignment generates no code, but has the side effect of binding the + /// value in the current context. For the assembly streamer, this prints the + /// binding into the .s file. + /// + /// @param Symbol - The symbol being assigned to. + /// @param Value - The value for the symbol. + virtual void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) = 0; + + /// EmitSymbolAttribute - Add the given @param Attribute to @param Symbol. + virtual void EmitSymbolAttribute(MCSymbol *Symbol, + SymbolAttr Attribute) = 0; + + /// EmitSymbolDesc - Set the @param DescValue for the @param Symbol. + /// + /// @param Symbol - The symbol to have its n_desc field set. + /// @param DescValue - The value to set into the n_desc field. + virtual void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) = 0; + + /// EmitCommonSymbol - Emit a common or local common symbol. + /// + /// @param Symbol - The common symbol to emit. + /// @param Size - The size of the common symbol. + /// @param ByteAlignment - The alignment of the symbol if + /// non-zero. This must be a power of 2 on some targets. + virtual void EmitCommonSymbol(MCSymbol *Symbol, unsigned Size, + unsigned ByteAlignment) = 0; + + /// EmitZerofill - Emit a the zerofill section and an option symbol. + /// + /// @param Section - The zerofill section to create and or to put the symbol + /// @param Symbol - The zerofill symbol to emit, if non-NULL. + /// @param Size - The size of the zerofill symbol. + /// @param ByteAlignment - The alignment of the zerofill symbol if + /// non-zero. This must be a power of 2 on some targets. + virtual void EmitZerofill(const MCSection *Section, MCSymbol *Symbol = 0, + unsigned Size = 0,unsigned ByteAlignment = 0) = 0; + + /// @} + /// @name Generating Data + /// @{ + + /// EmitBytes - Emit the bytes in \arg Data into the output. + /// + /// This is used to implement assembler directives such as .byte, .ascii, + /// etc. + virtual void EmitBytes(StringRef Data) = 0; + + /// EmitValue - Emit the expression @param Value into the output as a native + /// integer of the given @param Size bytes. + /// + /// This is used to implement assembler directives such as .word, .quad, + /// etc. + /// + /// @param Value - The value to emit. + /// @param Size - The size of the integer (in bytes) to emit. This must + /// match a native machine width. + virtual void EmitValue(const MCExpr *Value, unsigned Size) = 0; + + /// EmitValueToAlignment - Emit some number of copies of @param Value until + /// the byte alignment @param ByteAlignment is reached. + /// + /// If the number of bytes need to emit for the alignment is not a multiple + /// of @param ValueSize, then the contents of the emitted fill bytes is + /// undefined. + /// + /// This used to implement the .align assembler directive. + /// + /// @param ByteAlignment - The alignment to reach. This must be a power of + /// two on some targets. + /// @param Value - The value to use when filling bytes. + /// @param Size - The size of the integer (in bytes) to emit for @param + /// Value. This must match a native machine width. + /// @param MaxBytesToEmit - The maximum numbers of bytes to emit, or 0. If + /// the alignment cannot be reached in this many bytes, no bytes are + /// emitted. + virtual void EmitValueToAlignment(unsigned ByteAlignment, int64_t Value = 0, + unsigned ValueSize = 1, + unsigned MaxBytesToEmit = 0) = 0; + + /// EmitValueToOffset - Emit some number of copies of @param Value until the + /// byte offset @param Offset is reached. + /// + /// This is used to implement assembler directives such as .org. + /// + /// @param Offset - The offset to reach. This may be an expression, but the + /// expression must be associated with the current section. + /// @param Value - The value to use when filling bytes. + virtual void EmitValueToOffset(const MCExpr *Offset, + unsigned char Value = 0) = 0; + + /// @} + + /// EmitInstruction - Emit the given @param Instruction into the current + /// section. + virtual void EmitInstruction(const MCInst &Inst) = 0; + + /// Finish - Finish emission of machine code and flush any output. + virtual void Finish() = 0; + }; + + /// createNullStreamer - Create a dummy machine code streamer, which does + /// nothing. This is useful for timing the assembler front end. + MCStreamer *createNullStreamer(MCContext &Ctx); + + /// createAsmStreamer - Create a machine code streamer which will print out + /// assembly for the native target, suitable for compiling with a native + /// assembler. + MCStreamer *createAsmStreamer(MCContext &Ctx, raw_ostream &OS, + const MCAsmInfo &MAI, + MCInstPrinter *InstPrint = 0, + MCCodeEmitter *CE = 0); + + // FIXME: These two may end up getting rolled into a single + // createObjectStreamer interface, which implements the assembler backend, and + // is parameterized on an output object file writer. + + /// createMachOStream - Create a machine code streamer which will generative + /// Mach-O format object files. + MCStreamer *createMachOStreamer(MCContext &Ctx, raw_ostream &OS, + MCCodeEmitter *CE = 0); + + /// createELFStreamer - Create a machine code streamer which will generative + /// ELF format object files. + MCStreamer *createELFStreamer(MCContext &Ctx, raw_ostream &OS); + +} // end namespace llvm + +#endif diff --git a/libclamav/c++/llvm/include/llvm/MC/MCSymbol.h b/libclamav/c++/llvm/include/llvm/MC/MCSymbol.h new file mode 100644 index 000000000..cfe04d885 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/MC/MCSymbol.h @@ -0,0 +1,143 @@ +//===- MCSymbol.h - Machine Code Symbols ------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the declaration of the MCSymbol class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCSYMBOL_H +#define LLVM_MC_MCSYMBOL_H + +#include +#include "llvm/ADT/StringRef.h" +#include "llvm/System/DataTypes.h" + +namespace llvm { + class MCAsmInfo; + class MCExpr; + class MCSection; + class MCContext; + class raw_ostream; + + /// MCSymbol - Instances of this class represent a symbol name in the MC file, + /// and MCSymbols are created and unique'd by the MCContext class. + /// + /// If the symbol is defined/emitted into the current translation unit, the + /// Section member is set to indicate what section it lives in. Otherwise, if + /// it is a reference to an external entity, it has a null section. + /// + class MCSymbol { + // Special sentinal value for the absolute pseudo section. + // + // FIXME: Use a PointerInt wrapper for this? + static const MCSection *AbsolutePseudoSection; + + /// Name - The name of the symbol. + std::string Name; + + /// Section - The section the symbol is defined in. This is null for + /// undefined symbols, and the special AbsolutePseudoSection value for + /// absolute symbols. + const MCSection *Section; + + /// Value - If non-null, the value for a variable symbol. + const MCExpr *Value; + + /// IsTemporary - True if this is an assembler temporary label, which + /// typically does not survive in the .o file's symbol table. Usually + /// "Lfoo" or ".foo". + unsigned IsTemporary : 1; + + private: // MCContext creates and uniques these. + friend class MCContext; + MCSymbol(StringRef _Name, bool _IsTemporary) + : Name(_Name), Section(0), Value(0), IsTemporary(_IsTemporary) {} + + MCSymbol(const MCSymbol&); // DO NOT IMPLEMENT + void operator=(const MCSymbol&); // DO NOT IMPLEMENT + public: + /// getName - Get the symbol name. + const std::string &getName() const { return Name; } + + /// @name Symbol Type + /// @{ + + /// isTemporary - Check if this is an assembler temporary symbol. + bool isTemporary() const { + return IsTemporary; + } + + /// @} + /// @name Associated Sections + /// @{ + + /// isDefined - Check if this symbol is defined (i.e., it has an address). + /// + /// Defined symbols are either absolute or in some section. + bool isDefined() const { + return Section != 0; + } + + /// isUndefined - Check if this symbol undefined (i.e., implicitly defined). + bool isUndefined() const { + return !isDefined(); + } + + /// isAbsolute - Check if this this is an absolute symbol. + bool isAbsolute() const { + return Section == AbsolutePseudoSection; + } + + /// getSection - Get the section associated with a defined, non-absolute + /// symbol. + const MCSection &getSection() const { + assert(!isUndefined() && !isAbsolute() && "Invalid accessor!"); + return *Section; + } + + /// setSection - Mark the symbol as defined in the section \arg S. + void setSection(const MCSection &S) { Section = &S; } + + /// setUndefined - Mark the symbol as undefined. + void setUndefined() { + Section = 0; + } + + /// setAbsolute - Mark the symbol as absolute. + void setAbsolute() { Section = AbsolutePseudoSection; } + + /// @} + /// @name Variable Symbols + /// @{ + + /// isVariable - Check if this is a variable symbol. + bool isVariable() const { + return Value != 0; + } + + /// getValue() - Get the value for variable symbols, or null if the symbol + /// is not a variable. + const MCExpr *getValue() const { return Value; } + + void setValue(const MCExpr *Value) { + this->Value = Value; + } + + /// @} + + /// print - Print the value to the stream \arg OS. + void print(raw_ostream &OS, const MCAsmInfo *MAI) const; + + /// dump - Print the value to stderr. + void dump() const; + }; + +} // end namespace llvm + +#endif diff --git a/libclamav/c++/llvm/include/llvm/MC/MCValue.h b/libclamav/c++/llvm/include/llvm/MC/MCValue.h new file mode 100644 index 000000000..4f5ab314a --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/MC/MCValue.h @@ -0,0 +1,85 @@ +//===-- llvm/MC/MCValue.h - MCValue class -----------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the declaration of the MCValue class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCVALUE_H +#define LLVM_MC_MCVALUE_H + +#include "llvm/System/DataTypes.h" +#include "llvm/MC/MCSymbol.h" +#include + +namespace llvm { +class MCSymbol; +class raw_ostream; + +/// MCValue - This represents an "assembler immediate". In its most general +/// form, this can hold "SymbolA - SymbolB + imm64". Not all targets supports +/// relocations of this general form, but we need to represent this anyway. +/// +/// In the general form, SymbolB can only be defined if SymbolA is, and both +/// must be in the same (non-external) section. The latter constraint is not +/// enforced, since a symbol's section may not be known at construction. +/// +/// Note that this class must remain a simple POD value class, because we need +/// it to live in unions etc. +class MCValue { + const MCSymbol *SymA, *SymB; + int64_t Cst; +public: + + int64_t getConstant() const { return Cst; } + const MCSymbol *getSymA() const { return SymA; } + const MCSymbol *getSymB() const { return SymB; } + + /// isAbsolute - Is this an absolute (as opposed to relocatable) value. + bool isAbsolute() const { return !SymA && !SymB; } + + /// getAssociatedSection - For relocatable values, return the section the + /// value is associated with. + /// + /// @result - The value's associated section, or null for external or constant + /// values. + // + // FIXME: Switch to a tagged section, so this can return the tagged section + // value. + const MCSection *getAssociatedSection() const; + + /// print - Print the value to the stream \arg OS. + void print(raw_ostream &OS, const MCAsmInfo *MAI) const; + + /// dump - Print the value to stderr. + void dump() const; + + static MCValue get(const MCSymbol *SymA, const MCSymbol *SymB = 0, + int64_t Val = 0) { + MCValue R; + assert((!SymB || SymA) && "Invalid relocatable MCValue!"); + R.Cst = Val; + R.SymA = SymA; + R.SymB = SymB; + return R; + } + + static MCValue get(int64_t Val) { + MCValue R; + R.Cst = Val; + R.SymA = 0; + R.SymB = 0; + return R; + } + +}; + +} // end namespace llvm + +#endif diff --git a/libclamav/c++/llvm/include/llvm/MC/SectionKind.h b/libclamav/c++/llvm/include/llvm/MC/SectionKind.h new file mode 100644 index 000000000..945cff790 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/MC/SectionKind.h @@ -0,0 +1,221 @@ +//===-- llvm/Target/TargetLoweringObjectFile.h - Object 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 classes used to handle lowerings specific to common +// object file formats. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_SECTIONKIND_H +#define LLVM_MC_SECTIONKIND_H + +namespace llvm { + +/// SectionKind - This is a simple POD value that classifies the properties of +/// a section. A section is classified into the deepest possible +/// classification, and then the target maps them onto their sections based on +/// what capabilities they have. +/// +/// The comments below describe these as if they were an inheritance hierarchy +/// in order to explain the predicates below. +/// +class SectionKind { + enum Kind { + /// Metadata - Debug info sections or other metadata. + Metadata, + + /// Text - Text section, used for functions and other executable code. + Text, + + /// ReadOnly - Data that is never written to at program runtime by the + /// program or the dynamic linker. Things in the top-level readonly + /// SectionKind are not mergeable. + ReadOnly, + + /// MergableCString - Any null-terminated string which allows merging. + /// These values are known to end in a nul value of the specified size, + /// not otherwise contain a nul value, and be mergable. This allows the + /// linker to unique the strings if it so desires. + + /// Mergeable1ByteCString - 1 byte mergable, null terminated, string. + Mergeable1ByteCString, + + /// Mergeable2ByteCString - 2 byte mergable, null terminated, string. + Mergeable2ByteCString, + + /// Mergeable4ByteCString - 4 byte mergable, null terminated, string. + Mergeable4ByteCString, + + /// MergeableConst - These are sections for merging fixed-length + /// constants together. For example, this can be used to unique + /// constant pool entries etc. + MergeableConst, + + /// MergeableConst4 - This is a section used by 4-byte constants, + /// for example, floats. + MergeableConst4, + + /// MergeableConst8 - This is a section used by 8-byte constants, + /// for example, doubles. + MergeableConst8, + + /// MergeableConst16 - This is a section used by 16-byte constants, + /// for example, vectors. + MergeableConst16, + + /// Writeable - This is the base of all segments that need to be written + /// to during program runtime. + + /// ThreadLocal - This is the base of all TLS segments. All TLS + /// objects must be writeable, otherwise there is no reason for them to + /// be thread local! + + /// ThreadBSS - Zero-initialized TLS data objects. + ThreadBSS, + + /// ThreadData - Initialized TLS data objects. + ThreadData, + + /// GlobalWriteableData - Writeable data that is global (not thread + /// local). + + /// BSS - Zero initialized writeable data. + BSS, + + /// DataRel - This is the most general form of data that is written + /// to by the program, it can have random relocations to arbitrary + /// globals. + DataRel, + + /// DataRelLocal - This is writeable data that has a non-zero + /// initializer and has relocations in it, but all of the + /// relocations are known to be within the final linked image + /// the global is linked into. + DataRelLocal, + + /// DataNoRel - This is writeable data that has a non-zero + /// initializer, but whose initializer is known to have no + /// relocations. + DataNoRel, + + /// ReadOnlyWithRel - These are global variables that are never + /// written to by the program, but that have relocations, so they + /// must be stuck in a writeable section so that the dynamic linker + /// can write to them. If it chooses to, the dynamic linker can + /// mark the pages these globals end up on as read-only after it is + /// done with its relocation phase. + ReadOnlyWithRel, + + /// ReadOnlyWithRelLocal - This is data that is readonly by the + /// program, but must be writeable so that the dynamic linker + /// can perform relocations in it. This is used when we know + /// that all the relocations are to globals in this final + /// linked image. + ReadOnlyWithRelLocal + + } K : 8; +public: + + bool isMetadata() const { return K == Metadata; } + bool isText() const { return K == Text; } + + bool isReadOnly() const { + return K == ReadOnly || isMergeableCString() || + isMergeableConst(); + } + + bool isMergeableCString() const { + return K == Mergeable1ByteCString || K == Mergeable2ByteCString || + K == Mergeable4ByteCString; + } + bool isMergeable1ByteCString() const { return K == Mergeable1ByteCString; } + bool isMergeable2ByteCString() const { return K == Mergeable2ByteCString; } + bool isMergeable4ByteCString() const { return K == Mergeable4ByteCString; } + + bool isMergeableConst() const { + return K == MergeableConst || K == MergeableConst4 || + K == MergeableConst8 || K == MergeableConst16; + } + bool isMergeableConst4() const { return K == MergeableConst4; } + bool isMergeableConst8() const { return K == MergeableConst8; } + bool isMergeableConst16() const { return K == MergeableConst16; } + + bool isWriteable() const { + return isThreadLocal() || isGlobalWriteableData(); + } + + bool isThreadLocal() const { + return K == ThreadData || K == ThreadBSS; + } + + bool isThreadBSS() const { return K == ThreadBSS; } + bool isThreadData() const { return K == ThreadData; } + + bool isGlobalWriteableData() const { + return isBSS() || isDataRel() || isReadOnlyWithRel(); + } + + bool isBSS() const { return K == BSS; } + + bool isDataRel() const { + return K == DataRel || K == DataRelLocal || K == DataNoRel; + } + + bool isDataRelLocal() const { + return K == DataRelLocal || K == DataNoRel; + } + + bool isDataNoRel() const { return K == DataNoRel; } + + bool isReadOnlyWithRel() const { + return K == ReadOnlyWithRel || K == ReadOnlyWithRelLocal; + } + + bool isReadOnlyWithRelLocal() const { + return K == ReadOnlyWithRelLocal; + } +private: + static SectionKind get(Kind K) { + SectionKind Res; + Res.K = K; + return Res; + } +public: + + static SectionKind getMetadata() { return get(Metadata); } + static SectionKind getText() { return get(Text); } + static SectionKind getReadOnly() { return get(ReadOnly); } + static SectionKind getMergeable1ByteCString() { + return get(Mergeable1ByteCString); + } + static SectionKind getMergeable2ByteCString() { + return get(Mergeable2ByteCString); + } + static SectionKind getMergeable4ByteCString() { + return get(Mergeable4ByteCString); + } + static SectionKind getMergeableConst() { return get(MergeableConst); } + static SectionKind getMergeableConst4() { return get(MergeableConst4); } + static SectionKind getMergeableConst8() { return get(MergeableConst8); } + static SectionKind getMergeableConst16() { return get(MergeableConst16); } + static SectionKind getThreadBSS() { return get(ThreadBSS); } + static SectionKind getThreadData() { return get(ThreadData); } + static SectionKind getBSS() { return get(BSS); } + static SectionKind getDataRel() { return get(DataRel); } + static SectionKind getDataRelLocal() { return get(DataRelLocal); } + static SectionKind getDataNoRel() { return get(DataNoRel); } + static SectionKind getReadOnlyWithRel() { return get(ReadOnlyWithRel); } + static SectionKind getReadOnlyWithRelLocal(){ + return get(ReadOnlyWithRelLocal); + } +}; + +} // end namespace llvm + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Metadata.h b/libclamav/c++/llvm/include/llvm/Metadata.h new file mode 100644 index 000000000..1d18eba32 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Metadata.h @@ -0,0 +1,284 @@ +//===-- llvm/Metadata.h - Metadata definitions ------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +/// @file +/// This file contains the declarations for metadata subclasses. +/// They represent the different flavors of metadata that live in LLVM. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_METADATA_H +#define LLVM_METADATA_H + +#include "llvm/Value.h" +#include "llvm/Type.h" +#include "llvm/ADT/FoldingSet.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/ilist_node.h" +#include "llvm/Support/ValueHandle.h" + +namespace llvm { +class Constant; +class Instruction; +class LLVMContext; +class MetadataContextImpl; + +//===----------------------------------------------------------------------===// +// MetadataBase - A base class for MDNode, MDString and NamedMDNode. +class MetadataBase : public Value { +protected: + MetadataBase(const Type *Ty, unsigned scid) + : Value(Ty, scid) {} + +public: + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const MetadataBase *) { return true; } + static bool classof(const Value *V) { + return V->getValueID() == MDStringVal || V->getValueID() == MDNodeVal + || V->getValueID() == NamedMDNodeVal; + } +}; + +//===----------------------------------------------------------------------===// +/// MDString - a single uniqued string. +/// These are used to efficiently contain a byte sequence for metadata. +/// MDString is always unnamd. +class MDString : public MetadataBase { + MDString(const MDString &); // DO NOT IMPLEMENT + + StringRef Str; +protected: + explicit MDString(LLVMContext &C, StringRef S) + : MetadataBase(Type::getMetadataTy(C), Value::MDStringVal), Str(S) {} + +public: + static MDString *get(LLVMContext &Context, StringRef Str); + static MDString *get(LLVMContext &Context, const char *Str); + + StringRef getString() const { return Str; } + + unsigned getLength() const { return (unsigned)Str.size(); } + + typedef StringRef::iterator iterator; + + /// begin() - Pointer to the first byte of the string. + /// + iterator begin() const { return Str.begin(); } + + /// end() - Pointer to one byte past the end of the string. + /// + iterator end() const { return Str.end(); } + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const MDString *) { return true; } + static bool classof(const Value *V) { + return V->getValueID() == MDStringVal; + } +}; + +//===----------------------------------------------------------------------===// +/// MDNode - a tuple of other values. +/// These contain a list of the values that represent the metadata. +/// MDNode is always unnamed. +class MDNode : public MetadataBase, public FoldingSetNode { + MDNode(const MDNode &); // DO NOT IMPLEMENT + + friend class ElementVH; + // Use CallbackVH to hold MDNOde elements. + struct ElementVH : public CallbackVH { + MDNode *Parent; + ElementVH() {} + ElementVH(Value *V, MDNode *P) : CallbackVH(V), Parent(P) {} + ~ElementVH() {} + + virtual void deleted() { + Parent->replaceElement(this->operator Value*(), 0); + } + + virtual void allUsesReplacedWith(Value *NV) { + Parent->replaceElement(this->operator Value*(), NV); + } + }; + // Replace each instance of F from the element list of this node with T. + void replaceElement(Value *F, Value *T); + + ElementVH *Node; + unsigned NodeSize; + +protected: + explicit MDNode(LLVMContext &C, Value *const *Vals, unsigned NumVals); +public: + // Constructors and destructors. + static MDNode *get(LLVMContext &Context, + Value *const *Vals, unsigned NumVals); + + /// ~MDNode - Destroy MDNode. + ~MDNode(); + + /// getElement - Return specified element. + Value *getElement(unsigned i) const { + assert(i < getNumElements() && "Invalid element number!"); + return Node[i]; + } + + /// getNumElements - Return number of MDNode elements. + unsigned getNumElements() const { return NodeSize; } + + /// Profile - calculate a unique identifier for this MDNode to collapse + /// duplicates + void Profile(FoldingSetNodeID &ID) const; + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const MDNode *) { return true; } + static bool classof(const Value *V) { + return V->getValueID() == MDNodeVal; + } +}; + +//===----------------------------------------------------------------------===// +/// NamedMDNode - a tuple of other metadata. +/// NamedMDNode is always named. All NamedMDNode element has a type of metadata. +template + class SymbolTableListTraits; + +class NamedMDNode : public MetadataBase, public ilist_node { + friend class SymbolTableListTraits; + friend class LLVMContextImpl; + + NamedMDNode(const NamedMDNode &); // DO NOT IMPLEMENT + + Module *Parent; + SmallVector, 4> Node; + + void setParent(Module *M) { Parent = M; } +protected: + explicit NamedMDNode(LLVMContext &C, const Twine &N, MetadataBase*const *Vals, + unsigned NumVals, Module *M = 0); +public: + static NamedMDNode *Create(LLVMContext &C, const Twine &N, + MetadataBase *const *MDs, + unsigned NumMDs, Module *M = 0) { + return new NamedMDNode(C, N, MDs, NumMDs, M); + } + + static NamedMDNode *Create(const NamedMDNode *NMD, Module *M = 0); + + /// eraseFromParent - Drop all references and remove the node from parent + /// module. + void eraseFromParent(); + + /// dropAllReferences - Remove all uses and clear node vector. + void dropAllReferences(); + + /// ~NamedMDNode - Destroy NamedMDNode. + ~NamedMDNode(); + + /// getParent - Get the module that holds this named metadata collection. + inline Module *getParent() { return Parent; } + inline const Module *getParent() const { return Parent; } + + /// getElement - Return specified element. + MetadataBase *getElement(unsigned i) const { + assert(i < getNumElements() && "Invalid element number!"); + return Node[i]; + } + + /// getNumElements - Return number of NamedMDNode elements. + unsigned getNumElements() const { + return (unsigned)Node.size(); + } + + /// addElement - Add metadata element. + void addElement(MetadataBase *M) { + Node.push_back(TrackingVH(M)); + } + + typedef SmallVectorImpl >::iterator elem_iterator; + typedef SmallVectorImpl >::const_iterator + const_elem_iterator; + bool elem_empty() const { return Node.empty(); } + const_elem_iterator elem_begin() const { return Node.begin(); } + const_elem_iterator elem_end() const { return Node.end(); } + elem_iterator elem_begin() { return Node.begin(); } + elem_iterator elem_end() { return Node.end(); } + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const NamedMDNode *) { return true; } + static bool classof(const Value *V) { + return V->getValueID() == NamedMDNodeVal; + } +}; + +//===----------------------------------------------------------------------===// +/// MetadataContext - +/// MetadataContext handles uniquing and assignment of IDs for custom metadata +/// types. Custom metadata handler names do not contain spaces. And the name +/// must start with an alphabet. The regular expression used to check name +/// is [a-zA-Z$._][a-zA-Z$._0-9]* +class MetadataContext { + // DO NOT IMPLEMENT + MetadataContext(MetadataContext&); + void operator=(MetadataContext&); + + MetadataContextImpl *const pImpl; +public: + MetadataContext(); + ~MetadataContext(); + + /// registerMDKind - Register a new metadata kind and return its ID. + /// A metadata kind can be registered only once. + unsigned registerMDKind(StringRef Name); + + /// getMDKind - Return metadata kind. If the requested metadata kind + /// is not registered then return 0. + unsigned getMDKind(StringRef Name) const; + + /// isValidName - Return true if Name is a valid custom metadata handler name. + static bool isValidName(StringRef Name); + + /// getMD - Get the metadata of given kind attached to an Instruction. + /// If the metadata is not found then return 0. + MDNode *getMD(unsigned Kind, const Instruction *Inst); + + /// getMDs - Get the metadata attached to an Instruction. + void getMDs(const Instruction *Inst, + SmallVectorImpl > > &MDs) const; + + /// addMD - Attach the metadata of given kind to an Instruction. + void addMD(unsigned Kind, MDNode *Node, Instruction *Inst); + + /// removeMD - Remove metadata of given kind attached with an instuction. + void removeMD(unsigned Kind, Instruction *Inst); + + /// removeAllMetadata - Remove all metadata attached with an instruction. + void removeAllMetadata(Instruction *Inst); + + /// copyMD - If metadata is attached with Instruction In1 then attach + /// the same metadata to In2. + void copyMD(Instruction *In1, Instruction *In2); + + /// getHandlerNames - Populate client supplied smallvector using custome + /// metadata name and ID. + void getHandlerNames(SmallVectorImpl >&) const; + + /// ValueIsDeleted - This handler is used to update metadata store + /// when a value is deleted. + void ValueIsDeleted(const Value *) {} + void ValueIsDeleted(Instruction *Inst); + void ValueIsRAUWd(Value *V1, Value *V2); + + /// ValueIsCloned - This handler is used to update metadata store + /// when In1 is cloned to create In2. + void ValueIsCloned(const Instruction *In1, Instruction *In2); +}; + +} // end llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Module.h b/libclamav/c++/llvm/include/llvm/Module.h new file mode 100644 index 000000000..04dfb35ca --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Module.h @@ -0,0 +1,493 @@ +//===-- llvm/Module.h - C++ class to represent a VM module ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +/// @file +/// Module.h This file contains the declarations for the Module class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MODULE_H +#define LLVM_MODULE_H + +#include "llvm/Function.h" +#include "llvm/GlobalVariable.h" +#include "llvm/GlobalAlias.h" +#include "llvm/Metadata.h" +#include "llvm/System/DataTypes.h" +#include + +namespace llvm { + +class GlobalValueRefMap; // Used by ConstantVals.cpp +class FunctionType; +class LLVMContext; + +template<> struct ilist_traits + : public SymbolTableListTraits { + + // createSentinel is used to get hold of the node that marks the end of the + // list... (same trick used here as in ilist_traits) + Function *createSentinel() const { + return static_cast(&Sentinel); + } + static void destroySentinel(Function*) {} + + Function *provideInitialHead() const { return createSentinel(); } + Function *ensureHead(Function*) const { return createSentinel(); } + static void noteHead(Function*, Function*) {} + +private: + mutable ilist_node Sentinel; +}; +template<> struct ilist_traits + : public SymbolTableListTraits { + // createSentinel is used to create a node that marks the end of the list. + static GlobalVariable *createSentinel(); + static void destroySentinel(GlobalVariable *GV) { delete GV; } +}; +template<> struct ilist_traits + : public SymbolTableListTraits { + // createSentinel is used to create a node that marks the end of the list. + static GlobalAlias *createSentinel(); + static void destroySentinel(GlobalAlias *GA) { delete GA; } +}; +template<> struct ilist_traits + : public SymbolTableListTraits { + // createSentinel is used to get hold of a node that marks the end of + // the list... + NamedMDNode *createSentinel() const { + return static_cast(&Sentinel); + } + static void destroySentinel(NamedMDNode*) {} + + NamedMDNode *provideInitialHead() const { return createSentinel(); } + NamedMDNode *ensureHead(NamedMDNode*) const { return createSentinel(); } + static void noteHead(NamedMDNode*, NamedMDNode*) {} +private: + mutable ilist_node Sentinel; +}; + +/// A Module instance is used to store all the information related to an +/// LLVM module. Modules are the top level container of all other LLVM +/// Intermediate Representation (IR) objects. Each module directly contains a +/// list of globals variables, a list of functions, a list of libraries (or +/// other modules) this module depends on, a symbol table, and various data +/// about the target's characteristics. +/// +/// A module maintains a GlobalValRefMap object that is used to hold all +/// constant references to global variables in the module. When a global +/// variable is destroyed, it should have no entries in the GlobalValueRefMap. +/// @brief The main container class for the LLVM Intermediate Representation. +class Module { +/// @name Types And Enumerations +/// @{ +public: + /// The type for the list of global variables. + typedef iplist GlobalListType; + /// The type for the list of functions. + typedef iplist FunctionListType; + /// The type for the list of aliases. + typedef iplist AliasListType; + /// The type for the list of named metadata. + typedef iplist NamedMDListType; + + /// The type for the list of dependent libraries. + typedef std::vector LibraryListType; + + /// The Global Variable iterator. + typedef GlobalListType::iterator global_iterator; + /// The Global Variable constant iterator. + typedef GlobalListType::const_iterator const_global_iterator; + + /// The Function iterators. + typedef FunctionListType::iterator iterator; + /// The Function constant iterator + typedef FunctionListType::const_iterator const_iterator; + + /// The Global Alias iterators. + typedef AliasListType::iterator alias_iterator; + /// The Global Alias constant iterator + typedef AliasListType::const_iterator const_alias_iterator; + + /// The named metadata iterators. + typedef NamedMDListType::iterator named_metadata_iterator; + /// The named metadata constant interators. + typedef NamedMDListType::const_iterator const_named_metadata_iterator; + /// The Library list iterator. + typedef LibraryListType::const_iterator lib_iterator; + + /// An enumeration for describing the endianess of the target machine. + enum Endianness { AnyEndianness, LittleEndian, BigEndian }; + + /// An enumeration for describing the size of a pointer on the target machine. + enum PointerSize { AnyPointerSize, Pointer32, Pointer64 }; + +/// @} +/// @name Member Variables +/// @{ +private: + LLVMContext& Context; ///< The LLVMContext from which types and + ///< constants are allocated. + GlobalListType GlobalList; ///< The Global Variables in the module + FunctionListType FunctionList; ///< The Functions in the module + AliasListType AliasList; ///< The Aliases in the module + LibraryListType LibraryList; ///< The Libraries needed by the module + NamedMDListType NamedMDList; ///< The named metadata in the module + std::string GlobalScopeAsm; ///< Inline Asm at global scope. + ValueSymbolTable *ValSymTab; ///< Symbol table for values + TypeSymbolTable *TypeSymTab; ///< Symbol table for types + std::string ModuleID; ///< Human readable identifier for the module + std::string TargetTriple; ///< Platform target triple Module compiled on + std::string DataLayout; ///< Target data description + + friend class Constant; + +/// @} +/// @name Constructors +/// @{ +public: + /// The Module constructor. Note that there is no default constructor. You + /// must provide a name for the module upon construction. + explicit Module(StringRef ModuleID, LLVMContext& C); + /// The module destructor. This will dropAllReferences. + ~Module(); + +/// @} +/// @name Module Level Accessors +/// @{ +public: + /// Get the module identifier which is, essentially, the name of the module. + /// @returns the module identifier as a string + const std::string &getModuleIdentifier() const { return ModuleID; } + + /// Get the data layout string for the module's target platform. This encodes + /// the type sizes and alignments expected by this module. + /// @returns the data layout as a string + const std::string &getDataLayout() const { return DataLayout; } + + /// Get the target triple which is a string describing the target host. + /// @returns a string containing the target triple. + const std::string &getTargetTriple() const { return TargetTriple; } + + /// Get the target endian information. + /// @returns Endianess - an enumeration for the endianess of the target + Endianness getEndianness() const; + + /// Get the target pointer size. + /// @returns PointerSize - an enumeration for the size of the target's pointer + PointerSize getPointerSize() const; + + /// Get the global data context. + /// @returns LLVMContext - a container for LLVM's global information + LLVMContext& getContext() const { return Context; } + + /// Get any module-scope inline assembly blocks. + /// @returns a string containing the module-scope inline assembly blocks. + const std::string &getModuleInlineAsm() const { return GlobalScopeAsm; } +/// @} +/// @name Module Level Mutators +/// @{ +public: + + /// Set the module identifier. + void setModuleIdentifier(StringRef ID) { ModuleID = ID; } + + /// Set the data layout + void setDataLayout(StringRef DL) { DataLayout = DL; } + + /// Set the target triple. + void setTargetTriple(StringRef T) { TargetTriple = T; } + + /// Set the module-scope inline assembly blocks. + void setModuleInlineAsm(StringRef Asm) { GlobalScopeAsm = Asm; } + + /// Append to the module-scope inline assembly blocks, automatically + /// appending a newline to the end. + void appendModuleInlineAsm(StringRef Asm) { + GlobalScopeAsm += Asm; + GlobalScopeAsm += '\n'; + } + +/// @} +/// @name Generic Value Accessors +/// @{ + + /// getNamedValue - Return the first global value in the module with + /// the specified name, of arbitrary type. This method returns null + /// if a global with the specified name is not found. + GlobalValue *getNamedValue(StringRef Name) const; + +/// @} +/// @name Function Accessors +/// @{ +public: + /// getOrInsertFunction - Look up the specified function in the module symbol + /// table. Four possibilities: + /// 1. If it does not exist, add a prototype for the function and return it. + /// 2. If it exists, and has a local linkage, the existing function is + /// renamed and a new one is inserted. + /// 3. Otherwise, if the existing function has the correct prototype, return + /// the existing function. + /// 4. Finally, the function exists but has the wrong prototype: return the + /// function with a constantexpr cast to the right prototype. + Constant *getOrInsertFunction(StringRef Name, const FunctionType *T, + AttrListPtr AttributeList); + + Constant *getOrInsertFunction(StringRef Name, const FunctionType *T); + + /// getOrInsertFunction - Look up the specified function in the module symbol + /// table. If it does not exist, add a prototype for the function and return + /// it. This function guarantees to return a constant of pointer to the + /// specified function type or a ConstantExpr BitCast of that type if the + /// named function has a different type. This version of the method takes a + /// null terminated list of function arguments, which makes it easier for + /// clients to use. + Constant *getOrInsertFunction(StringRef Name, + AttrListPtr AttributeList, + const Type *RetTy, ...) END_WITH_NULL; + + /// getOrInsertFunction - Same as above, but without the attributes. + Constant *getOrInsertFunction(StringRef Name, const Type *RetTy, ...) + END_WITH_NULL; + + Constant *getOrInsertTargetIntrinsic(StringRef Name, + const FunctionType *Ty, + AttrListPtr AttributeList); + + /// getFunction - Look up the specified function in the module symbol table. + /// If it does not exist, return null. + Function *getFunction(StringRef Name) const; + +/// @} +/// @name Global Variable Accessors +/// @{ +public: + /// getGlobalVariable - Look up the specified global variable in the module + /// symbol table. If it does not exist, return null. If AllowInternal is set + /// to true, this function will return types that have InternalLinkage. By + /// default, these types are not returned. + GlobalVariable *getGlobalVariable(StringRef Name, + bool AllowInternal = false) const; + + /// getNamedGlobal - Return the first global variable in the module with the + /// specified name, of arbitrary type. This method returns null if a global + /// with the specified name is not found. + GlobalVariable *getNamedGlobal(StringRef Name) const { + return getGlobalVariable(Name, true); + } + + /// getOrInsertGlobal - Look up the specified global in the module symbol + /// table. + /// 1. If it does not exist, add a declaration of the global and return it. + /// 2. Else, the global exists but has the wrong type: return the function + /// with a constantexpr cast to the right type. + /// 3. Finally, if the existing global is the correct delclaration, return + /// the existing global. + Constant *getOrInsertGlobal(StringRef Name, const Type *Ty); + +/// @} +/// @name Global Alias Accessors +/// @{ +public: + /// getNamedAlias - Return the first global alias in the module with the + /// specified name, of arbitrary type. This method returns null if a global + /// with the specified name is not found. + GlobalAlias *getNamedAlias(StringRef Name) const; + +/// @} +/// @name Named Metadata Accessors +/// @{ +public: + /// getNamedMetadata - Return the first NamedMDNode in the module with the + /// specified name. This method returns null if a NamedMDNode with the + /// specified name is not found. + NamedMDNode *getNamedMetadata(StringRef Name) const; + + /// getOrInsertNamedMetadata - Return the first named MDNode in the module + /// with the specified name. This method returns a new NamedMDNode if a + /// NamedMDNode with the specified name is not found. + NamedMDNode *getOrInsertNamedMetadata(StringRef Name); + +/// @} +/// @name Type Accessors +/// @{ +public: + /// addTypeName - Insert an entry in the symbol table mapping Str to Type. If + /// there is already an entry for this name, true is returned and the symbol + /// table is not modified. + bool addTypeName(StringRef Name, const Type *Ty); + + /// getTypeName - If there is at least one entry in the symbol table for the + /// specified type, return it. + std::string getTypeName(const Type *Ty) const; + + /// getTypeByName - Return the type with the specified name in this module, or + /// null if there is none by that name. + const Type *getTypeByName(StringRef Name) const; + +/// @} +/// @name Direct access to the globals list, functions list, and symbol table +/// @{ +public: + /// Get the Module's list of global variables (constant). + const GlobalListType &getGlobalList() const { return GlobalList; } + /// Get the Module's list of global variables. + GlobalListType &getGlobalList() { return GlobalList; } + static iplist Module::*getSublistAccess(GlobalVariable*) { + return &Module::GlobalList; + } + /// Get the Module's list of functions (constant). + const FunctionListType &getFunctionList() const { return FunctionList; } + /// Get the Module's list of functions. + FunctionListType &getFunctionList() { return FunctionList; } + static iplist Module::*getSublistAccess(Function*) { + return &Module::FunctionList; + } + /// Get the Module's list of aliases (constant). + const AliasListType &getAliasList() const { return AliasList; } + /// Get the Module's list of aliases. + AliasListType &getAliasList() { return AliasList; } + static iplist Module::*getSublistAccess(GlobalAlias*) { + return &Module::AliasList; + } + /// Get the Module's list of named metadata (constant). + const NamedMDListType &getNamedMDList() const { return NamedMDList; } + /// Get the Module's list of named metadata. + NamedMDListType &getNamedMDList() { return NamedMDList; } + static iplist Module::*getSublistAccess(NamedMDNode *) { + return &Module::NamedMDList; + } + /// Get the symbol table of global variable and function identifiers + const ValueSymbolTable &getValueSymbolTable() const { return *ValSymTab; } + /// Get the Module's symbol table of global variable and function identifiers. + ValueSymbolTable &getValueSymbolTable() { return *ValSymTab; } + /// Get the symbol table of types + const TypeSymbolTable &getTypeSymbolTable() const { return *TypeSymTab; } + /// Get the Module's symbol table of types + TypeSymbolTable &getTypeSymbolTable() { return *TypeSymTab; } + +/// @} +/// @name Global Variable Iteration +/// @{ +public: + /// Get an iterator to the first global variable + global_iterator global_begin() { return GlobalList.begin(); } + /// Get a constant iterator to the first global variable + const_global_iterator global_begin() const { return GlobalList.begin(); } + /// Get an iterator to the last global variable + global_iterator global_end () { return GlobalList.end(); } + /// Get a constant iterator to the last global variable + const_global_iterator global_end () const { return GlobalList.end(); } + /// Determine if the list of globals is empty. + bool global_empty() const { return GlobalList.empty(); } + +/// @} +/// @name Function Iteration +/// @{ +public: + /// Get an iterator to the first function. + iterator begin() { return FunctionList.begin(); } + /// Get a constant iterator to the first function. + const_iterator begin() const { return FunctionList.begin(); } + /// Get an iterator to the last function. + iterator end () { return FunctionList.end(); } + /// Get a constant iterator to the last function. + const_iterator end () const { return FunctionList.end(); } + /// Determine how many functions are in the Module's list of functions. + size_t size() const { return FunctionList.size(); } + /// Determine if the list of functions is empty. + bool empty() const { return FunctionList.empty(); } + +/// @} +/// @name Dependent Library Iteration +/// @{ +public: + /// @brief Get a constant iterator to beginning of dependent library list. + inline lib_iterator lib_begin() const { return LibraryList.begin(); } + /// @brief Get a constant iterator to end of dependent library list. + inline lib_iterator lib_end() const { return LibraryList.end(); } + /// @brief Returns the number of items in the list of libraries. + inline size_t lib_size() const { return LibraryList.size(); } + /// @brief Add a library to the list of dependent libraries + void addLibrary(StringRef Lib); + /// @brief Remove a library from the list of dependent libraries + void removeLibrary(StringRef Lib); + /// @brief Get all the libraries + inline const LibraryListType& getLibraries() const { return LibraryList; } + +/// @} +/// @name Alias Iteration +/// @{ +public: + /// Get an iterator to the first alias. + alias_iterator alias_begin() { return AliasList.begin(); } + /// Get a constant iterator to the first alias. + const_alias_iterator alias_begin() const { return AliasList.begin(); } + /// Get an iterator to the last alias. + alias_iterator alias_end () { return AliasList.end(); } + /// Get a constant iterator to the last alias. + const_alias_iterator alias_end () const { return AliasList.end(); } + /// Determine how many aliases are in the Module's list of aliases. + size_t alias_size () const { return AliasList.size(); } + /// Determine if the list of aliases is empty. + bool alias_empty() const { return AliasList.empty(); } + + +/// @} +/// @name Named Metadata Iteration +/// @{ +public: + /// Get an iterator to the first named metadata. + named_metadata_iterator named_metadata_begin() + { return NamedMDList.begin(); } + /// Get a constant iterator to the first named metadata. + const_named_metadata_iterator named_metadata_begin() const + { return NamedMDList.begin(); } + /// Get an iterator to the last named metadata. + named_metadata_iterator named_metadata_end () + { return NamedMDList.end(); } + /// Get a constant iterator to the last named metadata. + const_named_metadata_iterator named_metadata_end () const + { return NamedMDList.end(); } + /// Determine how many NamedMDNodes are in the Module's list of named metadata. + size_t named_metadata_size () const + { return NamedMDList.size(); } + /// Determine if the list of named metadata is empty. + bool named_metadata_empty() const + { return NamedMDList.empty(); } + + +/// @} +/// @name Utility functions for printing and dumping Module objects +/// @{ +public: + /// Print the module to an output stream with AssemblyAnnotationWriter. + void print(raw_ostream &OS, AssemblyAnnotationWriter *AAW) const; + + /// Dump the module to stderr (for debugging). + void dump() const; + /// This function causes all the subinstructions to "let go" of all references + /// that they are maintaining. This allows one to 'delete' a whole class at + /// a time, even though there may be circular references... first all + /// references are dropped, and all use counts go to zero. Then everything + /// is delete'd for real. Note that no operations are valid on an object + /// that has "dropped all references", except operator delete. + void dropAllReferences(); +/// @} +}; + +/// An raw_ostream inserter for modules. +inline raw_ostream &operator<<(raw_ostream &O, const Module &M) { + M.print(O, 0); + return O; +} + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/ModuleProvider.h b/libclamav/c++/llvm/include/llvm/ModuleProvider.h new file mode 100644 index 000000000..8a0a20c0e --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/ModuleProvider.h @@ -0,0 +1,88 @@ +//===-- llvm/ModuleProvider.h - Interface for module providers --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides an abstract interface for loading a module from some +// place. This interface allows incremental or random access loading of +// functions from the file. This is useful for applications like JIT compilers +// or interprocedural optimizers that do not need the entire program in memory +// at the same time. +// +//===----------------------------------------------------------------------===// + +#ifndef MODULEPROVIDER_H +#define MODULEPROVIDER_H + +#include + +namespace llvm { + +class Function; +class Module; + +class ModuleProvider { +protected: + Module *TheModule; + ModuleProvider(); + +public: + virtual ~ModuleProvider(); + + /// getModule - returns the module this provider is encapsulating. + /// + Module* getModule() { return TheModule; } + + /// materializeFunction - make sure the given function is fully read. If the + /// module is corrupt, this returns true and fills in the optional string + /// with information about the problem. If successful, this returns false. + /// + virtual bool materializeFunction(Function *F, std::string *ErrInfo = 0) = 0; + + /// dematerializeFunction - If the given function is read in, and if the + /// module provider supports it, release the memory for the function, and set + /// it up to be materialized lazily. If the provider doesn't support this + /// capability, this method is a noop. + /// + virtual void dematerializeFunction(Function *) {} + + /// materializeModule - make sure the entire Module has been completely read. + /// On error, return null and fill in the error string if specified. + /// + virtual Module* materializeModule(std::string *ErrInfo = 0) = 0; + + /// releaseModule - no longer delete the Module* when provider is destroyed. + /// On error, return null and fill in the error string if specified. + /// + virtual Module* releaseModule(std::string *ErrInfo = 0) { + // Since we're losing control of this Module, we must hand it back complete + if (!materializeModule(ErrInfo)) + return 0; + Module *tempM = TheModule; + TheModule = 0; + return tempM; + } +}; + + +/// ExistingModuleProvider - Allow conversion from a fully materialized Module +/// into a ModuleProvider, allowing code that expects a ModuleProvider to work +/// if we just have a Module. Note that the ModuleProvider takes ownership of +/// the Module specified. +struct ExistingModuleProvider : public ModuleProvider { + explicit ExistingModuleProvider(Module *M) { + TheModule = M; + } + bool materializeFunction(Function *, std::string * = 0) { + return false; + } + Module* materializeModule(std::string * = 0) { return TheModule; } +}; + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/OperandTraits.h b/libclamav/c++/llvm/include/llvm/OperandTraits.h new file mode 100644 index 000000000..7c879c88f --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/OperandTraits.h @@ -0,0 +1,204 @@ +//===-- llvm/OperandTraits.h - OperandTraits class definition ---*- 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 the traits classes that are handy for enforcing the correct +// layout of various User subclasses. It also provides the means for accessing +// the operands in the most efficient manner. +// + +#ifndef LLVM_OPERAND_TRAITS_H +#define LLVM_OPERAND_TRAITS_H + +#include "llvm/User.h" + +namespace llvm { + +//===----------------------------------------------------------------------===// +// FixedNumOperands Trait Class +//===----------------------------------------------------------------------===// + +/// FixedNumOperandTraits - determine the allocation regime of the Use array +/// when it is a prefix to the User object, and the number of Use objects is +/// known at compile time. + +template +struct FixedNumOperandTraits { + static Use *op_begin(User* U) { + return reinterpret_cast(U) - ARITY; + } + static Use *op_end(User* U) { + return reinterpret_cast(U); + } + static unsigned operands(const User*) { + return ARITY; + } + struct prefix { + Use Ops[ARITY]; + prefix(); // DO NOT IMPLEMENT + }; + template + struct Layout { + struct overlay : public prefix, public U { + overlay(); // DO NOT IMPLEMENT + }; + }; +}; + +//===----------------------------------------------------------------------===// +// OptionalOperands Trait Class +//===----------------------------------------------------------------------===// + +template +struct OptionalOperandTraits : public FixedNumOperandTraits { + static unsigned operands(const User *U) { + return U->getNumOperands(); + } +}; + +//===----------------------------------------------------------------------===// +// VariadicOperand Trait Class +//===----------------------------------------------------------------------===// + +/// VariadicOperandTraits - determine the allocation regime of the Use array +/// when it is a prefix to the User object, and the number of Use objects is +/// only known at allocation time. + +template +struct VariadicOperandTraits { + static Use *op_begin(User* U) { + return reinterpret_cast(U) - U->getNumOperands(); + } + static Use *op_end(User* U) { + return reinterpret_cast(U); + } + static unsigned operands(const User *U) { + return U->getNumOperands(); + } +}; + +//===----------------------------------------------------------------------===// +// HungoffOperand Trait Class +//===----------------------------------------------------------------------===// + +/// HungoffOperandTraits - determine the allocation regime of the Use array +/// when it is not a prefix to the User object, but allocated at an unrelated +/// heap address. +/// Assumes that the User subclass that is determined by this traits class +/// has an OperandList member of type User::op_iterator. [Note: this is now +/// trivially satisfied, because User has that member for historic reasons.] +/// +/// This is the traits class that is needed when the Use array must be +/// resizable. + +template +struct HungoffOperandTraits { + static Use *op_begin(User* U) { + return U->OperandList; + } + static Use *op_end(User* U) { + return U->OperandList + U->getNumOperands(); + } + static unsigned operands(const User *U) { + return U->getNumOperands(); + } +}; + +/// Macro for generating in-class operand accessor declarations. +/// It should only be called in the public section of the interface. +/// +#define DECLARE_TRANSPARENT_OPERAND_ACCESSORS(VALUECLASS) \ + public: \ + inline VALUECLASS *getOperand(unsigned) const; \ + inline void setOperand(unsigned, VALUECLASS*); \ + inline op_iterator op_begin(); \ + inline const_op_iterator op_begin() const; \ + inline op_iterator op_end(); \ + inline const_op_iterator op_end() const; \ + protected: \ + template inline Use &Op(); \ + template inline const Use &Op() const; \ + public: \ + inline unsigned getNumOperands() const + +/// Macro for generating out-of-class operand accessor definitions +#define DEFINE_TRANSPARENT_OPERAND_ACCESSORS(CLASS, VALUECLASS) \ +CLASS::op_iterator CLASS::op_begin() { \ + return OperandTraits::op_begin(this); \ +} \ +CLASS::const_op_iterator CLASS::op_begin() const { \ + return OperandTraits::op_begin(const_cast(this)); \ +} \ +CLASS::op_iterator CLASS::op_end() { \ + return OperandTraits::op_end(this); \ +} \ +CLASS::const_op_iterator CLASS::op_end() const { \ + return OperandTraits::op_end(const_cast(this)); \ +} \ +VALUECLASS *CLASS::getOperand(unsigned i_nocapture) const { \ + assert(i_nocapture < OperandTraits::operands(this) \ + && "getOperand() out of range!"); \ + return static_cast( \ + OperandTraits::op_begin(const_cast(this))[i_nocapture]); \ +} \ +void CLASS::setOperand(unsigned i_nocapture, VALUECLASS *Val_nocapture) { \ + assert(i_nocapture < OperandTraits::operands(this) \ + && "setOperand() out of range!"); \ + OperandTraits::op_begin(this)[i_nocapture] = Val_nocapture; \ +} \ +unsigned CLASS::getNumOperands() const { \ + return OperandTraits::operands(this); \ +} \ +template Use &CLASS::Op() { \ + return this->OpFrom(this); \ +} \ +template const Use &CLASS::Op() const { \ + return this->OpFrom(this); \ +} + + +/// Macro for generating out-of-class operand accessor +/// definitions with casted result +#define DEFINE_TRANSPARENT_CASTED_OPERAND_ACCESSORS(CLASS, VALUECLASS) \ +CLASS::op_iterator CLASS::op_begin() { \ + return OperandTraits::op_begin(this); \ +} \ +CLASS::const_op_iterator CLASS::op_begin() const { \ + return OperandTraits::op_begin(const_cast(this)); \ +} \ +CLASS::op_iterator CLASS::op_end() { \ + return OperandTraits::op_end(this); \ +} \ +CLASS::const_op_iterator CLASS::op_end() const { \ + return OperandTraits::op_end(const_cast(this)); \ +} \ +VALUECLASS *CLASS::getOperand(unsigned i_nocapture) const { \ + assert(i_nocapture < OperandTraits::operands(this) \ + && "getOperand() out of range!"); \ + return cast( \ + OperandTraits::op_begin(const_cast(this))[i_nocapture]); \ +} \ +void CLASS::setOperand(unsigned i_nocapture, VALUECLASS *Val_nocapture) { \ + assert(i_nocapture < OperandTraits::operands(this) \ + && "setOperand() out of range!"); \ + OperandTraits::op_begin(this)[i_nocapture] = Val_nocapture; \ +} \ +unsigned CLASS::getNumOperands() const { \ + return OperandTraits::operands(this); \ +} \ +template Use &CLASS::Op() { \ + return this->OpFrom(this); \ +} \ +template const Use &CLASS::Op() const { \ + return this->OpFrom(this); \ +} + + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Operator.h b/libclamav/c++/llvm/include/llvm/Operator.h new file mode 100644 index 000000000..60865aa8a --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Operator.h @@ -0,0 +1,306 @@ +//===-- llvm/Operator.h - Operator utility subclass -------------*- 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 various classes for working with Instructions and +// ConstantExprs. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_OPERATOR_H +#define LLVM_OPERATOR_H + +#include "llvm/Instruction.h" +#include "llvm/Constants.h" + +namespace llvm { + +class GetElementPtrInst; +class BinaryOperator; +class ConstantExpr; + +/// Operator - This is a utility class that provides an abstraction for the +/// common functionality between Instructions and ConstantExprs. +/// +class Operator : public User { +private: + // Do not implement any of these. The Operator class is intended to be used + // as a utility, and is never itself instantiated. + void *operator new(size_t, unsigned); + void *operator new(size_t s); + Operator(); + ~Operator(); + +public: + /// getOpcode - Return the opcode for this Instruction or ConstantExpr. + /// + unsigned getOpcode() const { + if (const Instruction *I = dyn_cast(this)) + return I->getOpcode(); + return cast(this)->getOpcode(); + } + + /// getOpcode - If V is an Instruction or ConstantExpr, return its + /// opcode. Otherwise return UserOp1. + /// + static unsigned getOpcode(const Value *V) { + if (const Instruction *I = dyn_cast(V)) + return I->getOpcode(); + if (const ConstantExpr *CE = dyn_cast(V)) + return CE->getOpcode(); + return Instruction::UserOp1; + } + + static inline bool classof(const Operator *) { return true; } + static inline bool classof(const Instruction *) { return true; } + static inline bool classof(const ConstantExpr *) { return true; } + static inline bool classof(const Value *V) { + return isa(V) || isa(V); + } +}; + +/// OverflowingBinaryOperator - Utility class for integer arithmetic operators +/// which may exhibit overflow - Add, Sub, and Mul. It does not include SDiv, +/// despite that operator having the potential for overflow. +/// +class OverflowingBinaryOperator : public Operator { +public: + enum { + NoUnsignedWrap = (1 << 0), + NoSignedWrap = (1 << 1) + }; + +private: + ~OverflowingBinaryOperator(); // do not implement + + friend class BinaryOperator; + friend class ConstantExpr; + void setHasNoUnsignedWrap(bool B) { + SubclassOptionalData = + (SubclassOptionalData & ~NoUnsignedWrap) | (B * NoUnsignedWrap); + } + void setHasNoSignedWrap(bool B) { + SubclassOptionalData = + (SubclassOptionalData & ~NoSignedWrap) | (B * NoSignedWrap); + } + +public: + /// hasNoUnsignedWrap - Test whether this operation is known to never + /// undergo unsigned overflow, aka the nuw property. + bool hasNoUnsignedWrap() const { + return SubclassOptionalData & NoUnsignedWrap; + } + + /// hasNoSignedWrap - Test whether this operation is known to never + /// undergo signed overflow, aka the nsw property. + bool hasNoSignedWrap() const { + return SubclassOptionalData & NoSignedWrap; + } + + static inline bool classof(const OverflowingBinaryOperator *) { return true; } + static inline bool classof(const Instruction *I) { + return I->getOpcode() == Instruction::Add || + I->getOpcode() == Instruction::Sub || + I->getOpcode() == Instruction::Mul; + } + static inline bool classof(const ConstantExpr *CE) { + return CE->getOpcode() == Instruction::Add || + CE->getOpcode() == Instruction::Sub || + CE->getOpcode() == Instruction::Mul; + } + static inline bool classof(const Value *V) { + return (isa(V) && classof(cast(V))) || + (isa(V) && classof(cast(V))); + } +}; + +/// AddOperator - Utility class for integer addition operators. +/// +class AddOperator : public OverflowingBinaryOperator { + ~AddOperator(); // do not implement +public: + static inline bool classof(const AddOperator *) { return true; } + static inline bool classof(const Instruction *I) { + return I->getOpcode() == Instruction::Add; + } + static inline bool classof(const ConstantExpr *CE) { + return CE->getOpcode() == Instruction::Add; + } + static inline bool classof(const Value *V) { + return (isa(V) && classof(cast(V))) || + (isa(V) && classof(cast(V))); + } +}; + +/// SubOperator - Utility class for integer subtraction operators. +/// +class SubOperator : public OverflowingBinaryOperator { + ~SubOperator(); // do not implement +public: + static inline bool classof(const SubOperator *) { return true; } + static inline bool classof(const Instruction *I) { + return I->getOpcode() == Instruction::Sub; + } + static inline bool classof(const ConstantExpr *CE) { + return CE->getOpcode() == Instruction::Sub; + } + static inline bool classof(const Value *V) { + return (isa(V) && classof(cast(V))) || + (isa(V) && classof(cast(V))); + } +}; + +/// MulOperator - Utility class for integer multiplication operators. +/// +class MulOperator : public OverflowingBinaryOperator { + ~MulOperator(); // do not implement +public: + static inline bool classof(const MulOperator *) { return true; } + static inline bool classof(const Instruction *I) { + return I->getOpcode() == Instruction::Mul; + } + static inline bool classof(const ConstantExpr *CE) { + return CE->getOpcode() == Instruction::Mul; + } + static inline bool classof(const Value *V) { + return (isa(V) && classof(cast(V))) || + (isa(V) && classof(cast(V))); + } +}; + +/// SDivOperator - An Operator with opcode Instruction::SDiv. +/// +class SDivOperator : public Operator { +public: + enum { + IsExact = (1 << 0) + }; + +private: + ~SDivOperator(); // do not implement + + friend class BinaryOperator; + friend class ConstantExpr; + void setIsExact(bool B) { + SubclassOptionalData = (SubclassOptionalData & ~IsExact) | (B * IsExact); + } + +public: + /// isExact - Test whether this division is known to be exact, with + /// zero remainder. + bool isExact() const { + return SubclassOptionalData & IsExact; + } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const SDivOperator *) { return true; } + static inline bool classof(const ConstantExpr *CE) { + return CE->getOpcode() == Instruction::SDiv; + } + static inline bool classof(const Instruction *I) { + return I->getOpcode() == Instruction::SDiv; + } + static inline bool classof(const Value *V) { + return (isa(V) && classof(cast(V))) || + (isa(V) && classof(cast(V))); + } +}; + +class GEPOperator : public Operator { + enum { + IsInBounds = (1 << 0) + }; + + ~GEPOperator(); // do not implement + + friend class GetElementPtrInst; + friend class ConstantExpr; + void setIsInBounds(bool B) { + SubclassOptionalData = + (SubclassOptionalData & ~IsInBounds) | (B * IsInBounds); + } + +public: + /// isInBounds - Test whether this is an inbounds GEP, as defined + /// by LangRef.html. + bool isInBounds() const { + return SubclassOptionalData & IsInBounds; + } + + inline op_iterator idx_begin() { return op_begin()+1; } + inline const_op_iterator idx_begin() const { return op_begin()+1; } + inline op_iterator idx_end() { return op_end(); } + inline const_op_iterator idx_end() const { return op_end(); } + + Value *getPointerOperand() { + return getOperand(0); + } + const Value *getPointerOperand() const { + return getOperand(0); + } + static unsigned getPointerOperandIndex() { + return 0U; // get index for modifying correct operand + } + + /// getPointerOperandType - Method to return the pointer operand as a + /// PointerType. + const PointerType *getPointerOperandType() const { + return reinterpret_cast(getPointerOperand()->getType()); + } + + unsigned getNumIndices() const { // Note: always non-negative + return getNumOperands() - 1; + } + + bool hasIndices() const { + return getNumOperands() > 1; + } + + /// hasAllZeroIndices - Return true if all of the indices of this GEP are + /// zeros. If so, the result pointer and the first operand have the same + /// value, just potentially different types. + bool hasAllZeroIndices() const { + for (const_op_iterator I = idx_begin(), E = idx_end(); I != E; ++I) { + if (Constant *C = dyn_cast(I)) + if (C->isNullValue()) + continue; + return false; + } + return true; + } + + /// hasAllConstantIndices - Return true if all of the indices of this GEP are + /// constant integers. If so, the result pointer and the first operand have + /// a constant offset between them. + bool hasAllConstantIndices() const { + for (const_op_iterator I = idx_begin(), E = idx_end(); I != E; ++I) { + if (!isa(I)) + return false; + } + return true; + } + + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const GEPOperator *) { return true; } + static inline bool classof(const GetElementPtrInst *) { return true; } + static inline bool classof(const ConstantExpr *CE) { + return CE->getOpcode() == Instruction::GetElementPtr; + } + static inline bool classof(const Instruction *I) { + return I->getOpcode() == Instruction::GetElementPtr; + } + static inline bool classof(const Value *V) { + return (isa(V) && classof(cast(V))) || + (isa(V) && classof(cast(V))); + } +}; + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Pass.h b/libclamav/c++/llvm/include/llvm/Pass.h new file mode 100644 index 000000000..909ccde86 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Pass.h @@ -0,0 +1,381 @@ +//===- llvm/Pass.h - Base class for Passes ----------------------*- 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 a base class that indicates that a specified class is a +// transformation pass implementation. +// +// Passes are designed this way so that it is possible to run passes in a cache +// and organizationally optimal order without having to specify it at the front +// end. This allows arbitrary passes to be strung together and have them +// executed as effeciently as possible. +// +// Passes should extend one of the classes below, depending on the guarantees +// that it can make about what will be modified as it is run. For example, most +// global optimizations should derive from FunctionPass, because they do not add +// or delete functions, they operate on the internals of the function. +// +// Note that this file #includes PassSupport.h and PassAnalysisSupport.h (at the +// bottom), so the APIs exposed by these files are also automatically available +// to all users of this file. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_PASS_H +#define LLVM_PASS_H + +#include "llvm/System/DataTypes.h" +#include +#include +#include + +namespace llvm { + +class BasicBlock; +class Function; +class Module; +class AnalysisUsage; +class PassInfo; +class ImmutablePass; +class PMStack; +class AnalysisResolver; +class PMDataManager; +class raw_ostream; +class StringRef; + +// AnalysisID - Use the PassInfo to identify a pass... +typedef const PassInfo* AnalysisID; + +/// Different types of internal pass managers. External pass managers +/// (PassManager and FunctionPassManager) are not represented here. +/// Ordering of pass manager types is important here. +enum PassManagerType { + PMT_Unknown = 0, + PMT_ModulePassManager = 1, /// MPPassManager + PMT_CallGraphPassManager, /// CGPassManager + PMT_FunctionPassManager, /// FPPassManager + PMT_LoopPassManager, /// LPPassManager + PMT_BasicBlockPassManager, /// BBPassManager + PMT_Last +}; + +//===----------------------------------------------------------------------===// +/// Pass interface - Implemented by all 'passes'. Subclass this if you are an +/// interprocedural optimization or you do not fit into any of the more +/// constrained passes described below. +/// +class Pass { + AnalysisResolver *Resolver; // Used to resolve analysis + intptr_t PassID; + + void operator=(const Pass&); // DO NOT IMPLEMENT + Pass(const Pass &); // DO NOT IMPLEMENT + +public: + explicit Pass(intptr_t pid) : Resolver(0), PassID(pid) { + assert(pid && "pid cannot be 0"); + } + explicit Pass(const void *pid) : Resolver(0), PassID((intptr_t)pid) { + assert(pid && "pid cannot be 0"); + } + virtual ~Pass(); + + /// getPassName - Return a nice clean name for a pass. This usually + /// implemented in terms of the name that is registered by one of the + /// Registration templates, but can be overloaded directly. + /// + virtual const char *getPassName() const; + + /// getPassInfo - Return the PassInfo data structure that corresponds to this + /// pass... If the pass has not been registered, this will return null. + /// + const PassInfo *getPassInfo() const; + + /// print - Print out the internal state of the pass. This is called by + /// Analyze to print out the contents of an analysis. Otherwise it is not + /// necessary to implement this method. Beware that the module pointer MAY be + /// null. This automatically forwards to a virtual function that does not + /// provide the Module* in case the analysis doesn't need it it can just be + /// ignored. + /// + virtual void print(raw_ostream &O, const Module *M) const; + void dump() const; // dump - Print to stderr. + + /// Each pass is responsible for assigning a pass manager to itself. + /// PMS is the stack of available pass manager. + virtual void assignPassManager(PMStack &, + PassManagerType = PMT_Unknown) {} + /// Check if available pass managers are suitable for this pass or not. + virtual void preparePassManager(PMStack &) {} + + /// Return what kind of Pass Manager can manage this pass. + virtual PassManagerType getPotentialPassManagerType() const { + return PMT_Unknown; + } + + // Access AnalysisResolver + inline void setResolver(AnalysisResolver *AR) { + assert (!Resolver && "Resolver is already set"); + Resolver = AR; + } + inline AnalysisResolver *getResolver() { + return Resolver; + } + + /// getAnalysisUsage - This function should be overriden by passes that need + /// analysis information to do their job. If a pass specifies that it uses a + /// particular analysis result to this function, it can then use the + /// getAnalysis() function, below. + /// + virtual void getAnalysisUsage(AnalysisUsage &) const { + // By default, no analysis results are used, all are invalidated. + } + + /// releaseMemory() - This member can be implemented by a pass if it wants to + /// be able to release its memory when it is no longer needed. The default + /// behavior of passes is to hold onto memory for the entire duration of their + /// lifetime (which is the entire compile time). For pipelined passes, this + /// is not a big deal because that memory gets recycled every time the pass is + /// invoked on another program unit. For IP passes, it is more important to + /// free memory when it is unused. + /// + /// Optionally implement this function to release pass memory when it is no + /// longer used. + /// + virtual void releaseMemory() {} + + /// verifyAnalysis() - This member can be implemented by a analysis pass to + /// check state of analysis information. + virtual void verifyAnalysis() const {} + + // dumpPassStructure - Implement the -debug-passes=PassStructure option + virtual void dumpPassStructure(unsigned Offset = 0); + + template + static const PassInfo *getClassPassInfo() { + return lookupPassInfo(intptr_t(&AnalysisClass::ID)); + } + + // lookupPassInfo - Return the pass info object for the specified pass class, + // or null if it is not known. + static const PassInfo *lookupPassInfo(intptr_t TI); + + // lookupPassInfo - Return the pass info object for the pass with the given + // argument string, or null if it is not known. + static const PassInfo *lookupPassInfo(StringRef Arg); + + /// getAnalysisIfAvailable() - Subclasses use this function to + /// get analysis information that might be around, for example to update it. + /// This is different than getAnalysis in that it can fail (if the analysis + /// results haven't been computed), so should only be used if you can handle + /// the case when the analysis is not available. This method is often used by + /// transformation APIs to update analysis results for a pass automatically as + /// the transform is performed. + /// + template AnalysisType * + getAnalysisIfAvailable() const; // Defined in PassAnalysisSupport.h + + /// mustPreserveAnalysisID - This method serves the same function as + /// getAnalysisIfAvailable, but works if you just have an AnalysisID. This + /// obviously cannot give you a properly typed instance of the class if you + /// don't have the class name available (use getAnalysisIfAvailable if you + /// do), but it can tell you if you need to preserve the pass at least. + /// + bool mustPreserveAnalysisID(const PassInfo *AnalysisID) const; + + /// getAnalysis() - This function is used by subclasses to get + /// to the analysis information that they claim to use by overriding the + /// getAnalysisUsage function. + /// + template + AnalysisType &getAnalysis() const; // Defined in PassAnalysisSupport.h + + template + AnalysisType &getAnalysis(Function &F); // Defined in PassAnalysisSupport.h + + template + AnalysisType &getAnalysisID(const PassInfo *PI) const; + + template + AnalysisType &getAnalysisID(const PassInfo *PI, Function &F); +}; + + +//===----------------------------------------------------------------------===// +/// ModulePass class - This class is used to implement unstructured +/// interprocedural optimizations and analyses. ModulePasses may do anything +/// they want to the program. +/// +class ModulePass : public Pass { +public: + /// runOnModule - Virtual method overriden by subclasses to process the module + /// being operated on. + virtual bool runOnModule(Module &M) = 0; + + virtual void assignPassManager(PMStack &PMS, + PassManagerType T = PMT_ModulePassManager); + + /// Return what kind of Pass Manager can manage this pass. + virtual PassManagerType getPotentialPassManagerType() const { + return PMT_ModulePassManager; + } + + explicit ModulePass(intptr_t pid) : Pass(pid) {} + explicit ModulePass(const void *pid) : Pass(pid) {} + // Force out-of-line virtual method. + virtual ~ModulePass(); +}; + + +//===----------------------------------------------------------------------===// +/// ImmutablePass class - This class is used to provide information that does +/// not need to be run. This is useful for things like target information and +/// "basic" versions of AnalysisGroups. +/// +class ImmutablePass : public ModulePass { +public: + /// initializePass - This method may be overriden by immutable passes to allow + /// them to perform various initialization actions they require. This is + /// primarily because an ImmutablePass can "require" another ImmutablePass, + /// and if it does, the overloaded version of initializePass may get access to + /// these passes with getAnalysis<>. + /// + virtual void initializePass() {} + + /// ImmutablePasses are never run. + /// + bool runOnModule(Module &) { return false; } + + explicit ImmutablePass(intptr_t pid) : ModulePass(pid) {} + explicit ImmutablePass(const void *pid) + : ModulePass(pid) {} + + // Force out-of-line virtual method. + virtual ~ImmutablePass(); +}; + +//===----------------------------------------------------------------------===// +/// FunctionPass class - This class is used to implement most global +/// optimizations. Optimizations should subclass this class if they meet the +/// following constraints: +/// +/// 1. Optimizations are organized globally, i.e., a function at a time +/// 2. Optimizing a function does not cause the addition or removal of any +/// functions in the module +/// +class FunctionPass : public Pass { +public: + explicit FunctionPass(intptr_t pid) : Pass(pid) {} + explicit FunctionPass(const void *pid) : Pass(pid) {} + + /// doInitialization - Virtual method overridden by subclasses to do + /// any necessary per-module initialization. + /// + virtual bool doInitialization(Module &) { return false; } + + /// runOnFunction - Virtual method overriden by subclasses to do the + /// per-function processing of the pass. + /// + virtual bool runOnFunction(Function &F) = 0; + + /// doFinalization - Virtual method overriden by subclasses to do any post + /// processing needed after all passes have run. + /// + virtual bool doFinalization(Module &) { return false; } + + /// runOnModule - On a module, we run this pass by initializing, + /// ronOnFunction'ing once for every function in the module, then by + /// finalizing. + /// + virtual bool runOnModule(Module &M); + + /// run - On a function, we simply initialize, run the function, then + /// finalize. + /// + bool run(Function &F); + + virtual void assignPassManager(PMStack &PMS, + PassManagerType T = PMT_FunctionPassManager); + + /// Return what kind of Pass Manager can manage this pass. + virtual PassManagerType getPotentialPassManagerType() const { + return PMT_FunctionPassManager; + } +}; + + + +//===----------------------------------------------------------------------===// +/// BasicBlockPass class - This class is used to implement most local +/// optimizations. Optimizations should subclass this class if they +/// meet the following constraints: +/// 1. Optimizations are local, operating on either a basic block or +/// instruction at a time. +/// 2. Optimizations do not modify the CFG of the contained function, or any +/// other basic block in the function. +/// 3. Optimizations conform to all of the constraints of FunctionPasses. +/// +class BasicBlockPass : public Pass { +public: + explicit BasicBlockPass(intptr_t pid) : Pass(pid) {} + explicit BasicBlockPass(const void *pid) : Pass(pid) {} + + /// doInitialization - Virtual method overridden by subclasses to do + /// any necessary per-module initialization. + /// + virtual bool doInitialization(Module &) { return false; } + + /// doInitialization - Virtual method overridden by BasicBlockPass subclasses + /// to do any necessary per-function initialization. + /// + virtual bool doInitialization(Function &) { return false; } + + /// runOnBasicBlock - Virtual method overriden by subclasses to do the + /// per-basicblock processing of the pass. + /// + virtual bool runOnBasicBlock(BasicBlock &BB) = 0; + + /// doFinalization - Virtual method overriden by BasicBlockPass subclasses to + /// do any post processing needed after all passes have run. + /// + virtual bool doFinalization(Function &) { return false; } + + /// doFinalization - Virtual method overriden by subclasses to do any post + /// processing needed after all passes have run. + /// + virtual bool doFinalization(Module &) { return false; } + + + // To run this pass on a function, we simply call runOnBasicBlock once for + // each function. + // + bool runOnFunction(Function &F); + + virtual void assignPassManager(PMStack &PMS, + PassManagerType T = PMT_BasicBlockPassManager); + + /// Return what kind of Pass Manager can manage this pass. + virtual PassManagerType getPotentialPassManagerType() const { + return PMT_BasicBlockPassManager; + } +}; + +/// If the user specifies the -time-passes argument on an LLVM tool command line +/// then the value of this boolean will be true, otherwise false. +/// @brief This is the storage for the -time-passes option. +extern bool TimePassesIsEnabled; + +} // End llvm namespace + +// Include support files that contain important APIs commonly used by Passes, +// but that we want to separate out to make it easier to read the header files. +// +#include "llvm/PassSupport.h" +#include "llvm/PassAnalysisSupport.h" + +#endif diff --git a/libclamav/c++/llvm/include/llvm/PassAnalysisSupport.h b/libclamav/c++/llvm/include/llvm/PassAnalysisSupport.h new file mode 100644 index 000000000..5864fad0d --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/PassAnalysisSupport.h @@ -0,0 +1,265 @@ +//===- llvm/PassAnalysisSupport.h - Analysis Pass Support code --*- 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 stuff that is used to define and "use" Analysis Passes. +// This file is automatically #included by Pass.h, so: +// +// NO .CPP FILES SHOULD INCLUDE THIS FILE DIRECTLY +// +// Instead, #include Pass.h +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_PASS_ANALYSIS_SUPPORT_H +#define LLVM_PASS_ANALYSIS_SUPPORT_H + +#include +#include "llvm/Pass.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" + +namespace llvm { + +class StringRef; + +//===----------------------------------------------------------------------===// +// AnalysisUsage - Represent the analysis usage information of a pass. This +// tracks analyses that the pass REQUIRES (must be available when the pass +// runs), REQUIRES TRANSITIVE (must be available throughout the lifetime of the +// pass), and analyses that the pass PRESERVES (the pass does not invalidate the +// results of these analyses). This information is provided by a pass to the +// Pass infrastructure through the getAnalysisUsage virtual function. +// +class AnalysisUsage { +public: + typedef SmallVector VectorType; + +private: + // Sets of analyses required and preserved by a pass + VectorType Required, RequiredTransitive, Preserved; + bool PreservesAll; + +public: + AnalysisUsage() : PreservesAll(false) {} + + // addRequired - Add the specified ID to the required set of the usage info + // for a pass. + // + AnalysisUsage &addRequiredID(AnalysisID ID) { + assert(ID && "Pass class not registered!"); + Required.push_back(ID); + return *this; + } + template + AnalysisUsage &addRequired() { + return addRequiredID(Pass::getClassPassInfo()); + } + + AnalysisUsage &addRequiredTransitiveID(AnalysisID ID) { + assert(ID && "Pass class not registered!"); + Required.push_back(ID); + RequiredTransitive.push_back(ID); + return *this; + } + template + AnalysisUsage &addRequiredTransitive() { + AnalysisID ID = Pass::getClassPassInfo(); + return addRequiredTransitiveID(ID); + } + + // addPreserved - Add the specified ID to the set of analyses preserved by + // this pass + // + AnalysisUsage &addPreservedID(AnalysisID ID) { + Preserved.push_back(ID); + return *this; + } + + // addPreserved - Add the specified Pass class to the set of analyses + // preserved by this pass. + // + template + AnalysisUsage &addPreserved() { + assert(Pass::getClassPassInfo() && "Pass class not registered!"); + Preserved.push_back(Pass::getClassPassInfo()); + return *this; + } + + // addPreserved - Add the Pass with the specified argument string to the set + // of analyses preserved by this pass. If no such Pass exists, do nothing. + // This can be useful when a pass is trivially preserved, but may not be + // linked in. Be careful about spelling! + // + AnalysisUsage &addPreserved(StringRef Arg) { + const PassInfo *PI = Pass::lookupPassInfo(Arg); + // If the pass exists, preserve it. Otherwise silently do nothing. + if (PI) Preserved.push_back(PI); + return *this; + } + + // setPreservesAll - Set by analyses that do not transform their input at all + void setPreservesAll() { PreservesAll = true; } + bool getPreservesAll() const { return PreservesAll; } + + /// setPreservesCFG - This function should be called by the pass, iff they do + /// not: + /// + /// 1. Add or remove basic blocks from the function + /// 2. Modify terminator instructions in any way. + /// + /// This function annotates the AnalysisUsage info object to say that analyses + /// that only depend on the CFG are preserved by this pass. + /// + void setPreservesCFG(); + + const VectorType &getRequiredSet() const { return Required; } + const VectorType &getRequiredTransitiveSet() const { + return RequiredTransitive; + } + const VectorType &getPreservedSet() const { return Preserved; } +}; + +//===----------------------------------------------------------------------===// +// AnalysisResolver - Simple interface used by Pass objects to pull all +// analysis information out of pass manager that is responsible to manage +// the pass. +// +class PMDataManager; +class AnalysisResolver { +private: + AnalysisResolver(); // DO NOT IMPLEMENT + +public: + explicit AnalysisResolver(PMDataManager &P) : PM(P) { } + + inline PMDataManager &getPMDataManager() { return PM; } + + // Find pass that is implementing PI. + Pass *findImplPass(const PassInfo *PI) { + Pass *ResultPass = 0; + for (unsigned i = 0; i < AnalysisImpls.size() ; ++i) { + if (AnalysisImpls[i].first == PI) { + ResultPass = AnalysisImpls[i].second; + break; + } + } + return ResultPass; + } + + // Find pass that is implementing PI. Initialize pass for Function F. + Pass *findImplPass(Pass *P, const PassInfo *PI, Function &F); + + void addAnalysisImplsPair(const PassInfo *PI, Pass *P) { + std::pair pir = std::make_pair(PI,P); + AnalysisImpls.push_back(pir); + } + + /// clearAnalysisImpls - Clear cache that is used to connect a pass to the + /// the analysis (PassInfo). + void clearAnalysisImpls() { + AnalysisImpls.clear(); + } + + // getAnalysisIfAvailable - Return analysis result or null if it doesn't exist + Pass *getAnalysisIfAvailable(AnalysisID ID, bool Direction) const; + + // AnalysisImpls - This keeps track of which passes implements the interfaces + // that are required by the current pass (to implement getAnalysis()). + std::vector > AnalysisImpls; + +private: + // PassManager that is used to resolve analysis info + PMDataManager &PM; +}; + +/// getAnalysisIfAvailable() - Subclasses use this function to +/// get analysis information that might be around, for example to update it. +/// This is different than getAnalysis in that it can fail (if the analysis +/// results haven't been computed), so should only be used if you can handle +/// the case when the analysis is not available. This method is often used by +/// transformation APIs to update analysis results for a pass automatically as +/// the transform is performed. +/// +template +AnalysisType *Pass::getAnalysisIfAvailable() const { + assert(Resolver && "Pass not resident in a PassManager object!"); + + const PassInfo *PI = getClassPassInfo(); + if (PI == 0) return 0; + return dynamic_cast + (Resolver->getAnalysisIfAvailable(PI, true)); +} + +/// getAnalysis() - This function is used by subclasses to get +/// to the analysis information that they claim to use by overriding the +/// getAnalysisUsage function. +/// +template +AnalysisType &Pass::getAnalysis() const { + assert(Resolver &&"Pass has not been inserted into a PassManager object!"); + + return getAnalysisID(getClassPassInfo()); +} + +template +AnalysisType &Pass::getAnalysisID(const PassInfo *PI) const { + assert(PI && "getAnalysis for unregistered pass!"); + assert(Resolver&&"Pass has not been inserted into a PassManager object!"); + // PI *must* appear in AnalysisImpls. Because the number of passes used + // should be a small number, we just do a linear search over a (dense) + // vector. + Pass *ResultPass = Resolver->findImplPass(PI); + assert (ResultPass && + "getAnalysis*() called on an analysis that was not " + "'required' by pass!"); + + // Because the AnalysisType may not be a subclass of pass (for + // AnalysisGroups), we must use dynamic_cast here to potentially adjust the + // return pointer (because the class may multiply inherit, once from pass, + // once from AnalysisType). + // + AnalysisType *Result = dynamic_cast(ResultPass); + assert(Result && "Pass does not implement interface required!"); + return *Result; +} + +/// getAnalysis() - This function is used by subclasses to get +/// to the analysis information that they claim to use by overriding the +/// getAnalysisUsage function. +/// +template +AnalysisType &Pass::getAnalysis(Function &F) { + assert(Resolver &&"Pass has not been inserted into a PassManager object!"); + + return getAnalysisID(getClassPassInfo(), F); +} + +template +AnalysisType &Pass::getAnalysisID(const PassInfo *PI, Function &F) { + assert(PI && "getAnalysis for unregistered pass!"); + assert(Resolver && "Pass has not been inserted into a PassManager object!"); + // PI *must* appear in AnalysisImpls. Because the number of passes used + // should be a small number, we just do a linear search over a (dense) + // vector. + Pass *ResultPass = Resolver->findImplPass(this, PI, F); + assert (ResultPass && "Unable to find requested analysis info"); + + // Because the AnalysisType may not be a subclass of pass (for + // AnalysisGroups), we must use dynamic_cast here to potentially adjust the + // return pointer (because the class may multiply inherit, once from pass, + // once from AnalysisType). + // + AnalysisType *Result = dynamic_cast(ResultPass); + assert(Result && "Pass does not implement interface required!"); + return *Result; +} + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/PassManager.h b/libclamav/c++/llvm/include/llvm/PassManager.h new file mode 100644 index 000000000..a6703fd58 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/PassManager.h @@ -0,0 +1,112 @@ +//===- llvm/PassManager.h - Container for Passes ----------------*- 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 the PassManager class. This class is used to hold, +// maintain, and optimize execution of Passes. The PassManager class ensures +// that analysis results are available before a pass runs, and that Pass's are +// destroyed when the PassManager is destroyed. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_PASSMANAGER_H +#define LLVM_PASSMANAGER_H + +#include "llvm/Pass.h" + +namespace llvm { + +class Pass; +class ModulePass; +class Module; +class ModuleProvider; + +class PassManagerImpl; +class FunctionPassManagerImpl; + +/// PassManagerBase - An abstract interface to allow code to add passes to +/// a pass manager without having to hard-code what kind of pass manager +/// it is. +class PassManagerBase { +public: + virtual ~PassManagerBase(); + + /// add - Add a pass to the queue of passes to run. This passes ownership of + /// the Pass to the PassManager. When the PassManager is destroyed, the pass + /// will be destroyed as well, so there is no need to delete the pass. This + /// implies that all passes MUST be allocated with 'new'. + virtual void add(Pass *P) = 0; +}; + +/// PassManager manages ModulePassManagers +class PassManager : public PassManagerBase { +public: + + PassManager(); + ~PassManager(); + + /// add - Add a pass to the queue of passes to run. This passes ownership of + /// the Pass to the PassManager. When the PassManager is destroyed, the pass + /// will be destroyed as well, so there is no need to delete the pass. This + /// implies that all passes MUST be allocated with 'new'. + void add(Pass *P); + + /// 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. + bool run(Module &M); + +private: + + /// PassManagerImpl_New is the actual class. PassManager is just the + /// wraper to publish simple pass manager interface + PassManagerImpl *PM; +}; + +/// FunctionPassManager manages FunctionPasses and BasicBlockPassManagers. +class FunctionPassManager : public PassManagerBase { +public: + /// FunctionPassManager ctor - This initializes the pass manager. It needs, + /// but does not take ownership of, the specified module provider. + explicit FunctionPassManager(ModuleProvider *P); + ~FunctionPassManager(); + + /// add - Add a pass to the queue of passes to run. This passes + /// ownership of the Pass to the PassManager. When the + /// PassManager_X is destroyed, the pass will be destroyed as well, so + /// there is no need to delete the pass. (TODO delete passes.) + /// This implies that all passes MUST be allocated with 'new'. + void add(Pass *P); + + /// run - Execute all of the passes scheduled for execution. Keep + /// track of whether any of the passes modifies the function, and if + /// so, return true. + /// + bool run(Function &F); + + /// doInitialization - Run all of the initializers for the function passes. + /// + bool doInitialization(); + + /// doFinalization - Run all of the finalizers for the function passes. + /// + bool doFinalization(); + + /// getModuleProvider - Return the module provider that this passmanager is + /// currently using. This is the module provider that it uses when a function + /// is optimized that is non-resident in the module. + ModuleProvider *getModuleProvider() const { return MP; } + void setModuleProvider(ModuleProvider *NewMP) { MP = NewMP; } + +private: + FunctionPassManagerImpl *FPM; + ModuleProvider *MP; +}; + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/PassManagers.h b/libclamav/c++/llvm/include/llvm/PassManagers.h new file mode 100644 index 000000000..dffc24a41 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/PassManagers.h @@ -0,0 +1,466 @@ +//===- llvm/PassManagers.h - Pass Infrastructure classes -------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the LLVM Pass Manager infrastructure. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_PASSMANAGERS_H +#define LLVM_PASSMANAGERS_H + +#include "llvm/PassManager.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/DenseMap.h" +#include +#include + +//===----------------------------------------------------------------------===// +// Overview: +// The Pass Manager Infrastructure manages passes. It's responsibilities are: +// +// o Manage optimization pass execution order +// o Make required Analysis information available before pass P is run +// o Release memory occupied by dead passes +// o If Analysis information is dirtied by a pass then regenerate Analysis +// information before it is consumed by another pass. +// +// Pass Manager Infrastructure uses multiple pass managers. They are +// PassManager, FunctionPassManager, MPPassManager, FPPassManager, BBPassManager. +// This class hierarchy uses multiple inheritance but pass managers do not +// derive from another pass manager. +// +// PassManager and FunctionPassManager are two top-level pass manager that +// represents the external interface of this entire pass manager infrastucture. +// +// Important classes : +// +// [o] class PMTopLevelManager; +// +// Two top level managers, PassManager and FunctionPassManager, derive from +// PMTopLevelManager. PMTopLevelManager manages information used by top level +// managers such as last user info. +// +// [o] class PMDataManager; +// +// PMDataManager manages information, e.g. list of available analysis info, +// used by a pass manager to manage execution order of passes. It also provides +// a place to implement common pass manager APIs. All pass managers derive from +// PMDataManager. +// +// [o] class BBPassManager : public FunctionPass, public PMDataManager; +// +// BBPassManager manages BasicBlockPasses. +// +// [o] class FunctionPassManager; +// +// This is a external interface used by JIT to manage FunctionPasses. This +// interface relies on FunctionPassManagerImpl to do all the tasks. +// +// [o] class FunctionPassManagerImpl : public ModulePass, PMDataManager, +// public PMTopLevelManager; +// +// FunctionPassManagerImpl is a top level manager. It manages FPPassManagers +// +// [o] class FPPassManager : public ModulePass, public PMDataManager; +// +// FPPassManager manages FunctionPasses and BBPassManagers +// +// [o] class MPPassManager : public Pass, public PMDataManager; +// +// MPPassManager manages ModulePasses and FPPassManagers +// +// [o] class PassManager; +// +// This is a external interface used by various tools to manages passes. It +// relies on PassManagerImpl to do all the tasks. +// +// [o] class PassManagerImpl : public Pass, public PMDataManager, +// public PMDTopLevelManager +// +// PassManagerImpl is a top level pass manager responsible for managing +// MPPassManagers. +//===----------------------------------------------------------------------===// + +#include "llvm/Support/PrettyStackTrace.h" + +namespace llvm { + class Module; + class Pass; + class StringRef; + class Value; + class Timer; + +/// FunctionPassManager and PassManager, two top level managers, serve +/// as the public interface of pass manager infrastructure. +enum TopLevelManagerType { + TLM_Function, // FunctionPassManager + TLM_Pass // PassManager +}; + +// enums for debugging strings +enum PassDebuggingString { + EXECUTION_MSG, // "Executing Pass '" + MODIFICATION_MSG, // "' Made Modification '" + FREEING_MSG, // " Freeing Pass '" + ON_BASICBLOCK_MSG, // "' on BasicBlock '" + PassName + "'...\n" + ON_FUNCTION_MSG, // "' on Function '" + FunctionName + "'...\n" + ON_MODULE_MSG, // "' on Module '" + ModuleName + "'...\n" + ON_LOOP_MSG, // " 'on Loop ...\n'" + ON_CG_MSG // "' on Call Graph ...\n'" +}; + +/// PassManagerPrettyStackEntry - This is used to print informative information +/// about what pass is running when/if a stack trace is generated. +class PassManagerPrettyStackEntry : public PrettyStackTraceEntry { + Pass *P; + Value *V; + Module *M; +public: + explicit PassManagerPrettyStackEntry(Pass *p) + : P(p), V(0), M(0) {} // When P is releaseMemory'd. + PassManagerPrettyStackEntry(Pass *p, Value &v) + : P(p), V(&v), M(0) {} // When P is run on V + PassManagerPrettyStackEntry(Pass *p, Module &m) + : P(p), V(0), M(&m) {} // When P is run on M + + /// print - Emit information about this stack frame to OS. + virtual void print(raw_ostream &OS) const; +}; + + +//===----------------------------------------------------------------------===// +// PMStack +// +/// PMStack +/// Top level pass managers (see PassManager.cpp) maintain active Pass Managers +/// using PMStack. Each Pass implements assignPassManager() to connect itself +/// with appropriate manager. assignPassManager() walks PMStack to find +/// suitable manager. +/// +/// PMStack is just a wrapper around standard deque that overrides pop() and +/// push() methods. +class PMStack { +public: + typedef std::deque::reverse_iterator iterator; + iterator begin() { return S.rbegin(); } + iterator end() { return S.rend(); } + + void handleLastUserOverflow(); + + void pop(); + inline PMDataManager *top() { return S.back(); } + void push(PMDataManager *PM); + inline bool empty() { return S.empty(); } + + void dump(); +private: + std::deque S; +}; + + +//===----------------------------------------------------------------------===// +// PMTopLevelManager +// +/// PMTopLevelManager manages LastUser info and collects common APIs used by +/// top level pass managers. +class PMTopLevelManager { +public: + + virtual unsigned getNumContainedManagers() const { + return (unsigned)PassManagers.size(); + } + + /// Schedule pass P for execution. Make sure that passes required by + /// P are run before P is run. Update analysis info maintained by + /// the manager. Remove dead passes. This is a recursive function. + void schedulePass(Pass *P); + + /// This is implemented by top level pass manager and used by + /// schedulePass() to add analysis info passes that are not available. + virtual void addTopLevelPass(Pass *P) = 0; + + /// Set pass P as the last user of the given analysis passes. + void setLastUser(SmallVector &AnalysisPasses, Pass *P); + + /// Collect passes whose last user is P + void collectLastUses(SmallVector &LastUses, Pass *P); + + /// Find the pass that implements Analysis AID. Search immutable + /// passes and all pass managers. If desired pass is not found + /// then return NULL. + Pass *findAnalysisPass(AnalysisID AID); + + /// Find analysis usage information for the pass P. + AnalysisUsage *findAnalysisUsage(Pass *P); + + explicit PMTopLevelManager(enum TopLevelManagerType t); + virtual ~PMTopLevelManager(); + + /// Add immutable pass and initialize it. + inline void addImmutablePass(ImmutablePass *P) { + P->initializePass(); + ImmutablePasses.push_back(P); + } + + inline SmallVector& getImmutablePasses() { + return ImmutablePasses; + } + + void addPassManager(PMDataManager *Manager) { + PassManagers.push_back(Manager); + } + + // Add Manager into the list of managers that are not directly + // maintained by this top level pass manager + inline void addIndirectPassManager(PMDataManager *Manager) { + IndirectPassManagers.push_back(Manager); + } + + // Print passes managed by this top level manager. + void dumpPasses() const; + void dumpArguments() const; + + void initializeAllAnalysisInfo(); + + // Active Pass Managers + PMStack activeStack; + +protected: + + /// Collection of pass managers + SmallVector PassManagers; + +private: + + /// Collection of pass managers that are not directly maintained + /// by this pass manager + SmallVector IndirectPassManagers; + + // Map to keep track of last user of the analysis pass. + // LastUser->second is the last user of Lastuser->first. + DenseMap LastUser; + + // Map to keep track of passes that are last used by a pass. + // This inverse map is initialized at PM->run() based on + // LastUser map. + DenseMap > InversedLastUser; + + /// Immutable passes are managed by top level manager. + SmallVector ImmutablePasses; + + DenseMap AnUsageMap; +}; + + + +//===----------------------------------------------------------------------===// +// PMDataManager + +/// PMDataManager provides the common place to manage the analysis data +/// used by pass managers. +class PMDataManager { +public: + + explicit PMDataManager(int Depth) : TPM(NULL), Depth(Depth) { + initializeAnalysisInfo(); + } + + virtual ~PMDataManager(); + + /// Augment AvailableAnalysis by adding analysis made available by pass P. + void recordAvailableAnalysis(Pass *P); + + /// verifyPreservedAnalysis -- Verify analysis presreved by pass P. + void verifyPreservedAnalysis(Pass *P); + + /// Remove Analysis that is not preserved by the pass + void removeNotPreservedAnalysis(Pass *P); + + /// Remove dead passes used by P. + void removeDeadPasses(Pass *P, StringRef Msg, + enum PassDebuggingString); + + /// Remove P. + void freePass(Pass *P, StringRef Msg, + enum PassDebuggingString); + + /// Add pass P into the PassVector. Update + /// AvailableAnalysis appropriately if ProcessAnalysis is true. + void add(Pass *P, bool ProcessAnalysis = true); + + /// Add RequiredPass into list of lower level passes required by pass P. + /// RequiredPass is run on the fly by Pass Manager when P requests it + /// through getAnalysis interface. + virtual void addLowerLevelRequiredPass(Pass *P, Pass *RequiredPass); + + virtual Pass * getOnTheFlyPass(Pass *P, const PassInfo *PI, Function &F) { + assert (0 && "Unable to find on the fly pass"); + return NULL; + } + + /// Initialize available analysis information. + void initializeAnalysisInfo() { + AvailableAnalysis.clear(); + for (unsigned i = 0; i < PMT_Last; ++i) + InheritedAnalysis[i] = NULL; + } + + // Return true if P preserves high level analysis used by other + // passes that are managed by this manager. + bool preserveHigherLevelAnalysis(Pass *P); + + + /// Populate RequiredPasses with analysis pass that are required by + /// pass P and are available. Populate ReqPassNotAvailable with analysis + /// pass that are required by pass P but are not available. + void collectRequiredAnalysis(SmallVector &RequiredPasses, + SmallVector &ReqPassNotAvailable, + Pass *P); + + /// All Required analyses should be available to the pass as it runs! Here + /// we fill in the AnalysisImpls member of the pass so that it can + /// successfully use the getAnalysis() method to retrieve the + /// implementations it needs. + void initializeAnalysisImpl(Pass *P); + + /// Find the pass that implements Analysis AID. If desired pass is not found + /// then return NULL. + Pass *findAnalysisPass(AnalysisID AID, bool Direction); + + // Access toplevel manager + PMTopLevelManager *getTopLevelManager() { return TPM; } + void setTopLevelManager(PMTopLevelManager *T) { TPM = T; } + + unsigned getDepth() const { return Depth; } + + // Print routines used by debug-pass + void dumpLastUses(Pass *P, unsigned Offset) const; + void dumpPassArguments() const; + void dumpPassInfo(Pass *P, enum PassDebuggingString S1, + enum PassDebuggingString S2, StringRef Msg); + void dumpRequiredSet(const Pass *P) const; + void dumpPreservedSet(const Pass *P) const; + + virtual unsigned getNumContainedPasses() const { + return (unsigned)PassVector.size(); + } + + virtual PassManagerType getPassManagerType() const { + assert ( 0 && "Invalid use of getPassManagerType"); + return PMT_Unknown; + } + + std::map *getAvailableAnalysis() { + return &AvailableAnalysis; + } + + // Collect AvailableAnalysis from all the active Pass Managers. + void populateInheritedAnalysis(PMStack &PMS) { + unsigned Index = 0; + for (PMStack::iterator I = PMS.begin(), E = PMS.end(); + I != E; ++I) + InheritedAnalysis[Index++] = (*I)->getAvailableAnalysis(); + } + +protected: + + // Top level manager. + PMTopLevelManager *TPM; + + // Collection of pass that are managed by this manager + SmallVector PassVector; + + // Collection of Analysis provided by Parent pass manager and + // used by current pass manager. At at time there can not be more + // then PMT_Last active pass mangers. + std::map *InheritedAnalysis[PMT_Last]; + + + /// isPassDebuggingExecutionsOrMore - Return true if -debug-pass=Executions + /// or higher is specified. + bool isPassDebuggingExecutionsOrMore() const; + +private: + void dumpAnalysisUsage(StringRef Msg, const Pass *P, + const AnalysisUsage::VectorType &Set) const; + + // Set of available Analysis. This information is used while scheduling + // pass. If a pass requires an analysis which is not not available then + // equired analysis pass is scheduled to run before the pass itself is + // scheduled to run. + std::map AvailableAnalysis; + + // Collection of higher level analysis used by the pass managed by + // this manager. + SmallVector HigherLevelAnalysis; + + unsigned Depth; +}; + +//===----------------------------------------------------------------------===// +// FPPassManager +// +/// FPPassManager manages BBPassManagers and FunctionPasses. +/// It batches all function passes and basic block pass managers together and +/// sequence them to process one function at a time before processing next +/// function. + +class FPPassManager : public ModulePass, public PMDataManager { + +public: + static char ID; + explicit FPPassManager(int Depth) + : ModulePass(&ID), PMDataManager(Depth) { } + + /// 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. + bool runOnFunction(Function &F); + bool runOnModule(Module &M); + + /// cleanup - After running all passes, clean up pass manager cache. + void cleanup(); + + /// doInitialization - Run all of the initializers for the function passes. + /// + bool doInitialization(Module &M); + + /// doFinalization - Run all of the finalizers for the function passes. + /// + bool doFinalization(Module &M); + + /// Pass Manager itself does not invalidate any analysis info. + void getAnalysisUsage(AnalysisUsage &Info) const { + Info.setPreservesAll(); + } + + // Print passes managed by this manager + void dumpPassStructure(unsigned Offset); + + virtual const char *getPassName() const { + return "Function Pass Manager"; + } + + FunctionPass *getContainedPass(unsigned N) { + assert ( N < PassVector.size() && "Pass number out of range!"); + FunctionPass *FP = static_cast(PassVector[N]); + return FP; + } + + virtual PassManagerType getPassManagerType() const { + return PMT_FunctionPassManager; + } +}; + +extern Timer *StartPassTimer(Pass *); +extern void StopPassTimer(Pass *, Timer *); + +} + +#endif diff --git a/libclamav/c++/llvm/include/llvm/PassSupport.h b/libclamav/c++/llvm/include/llvm/PassSupport.h new file mode 100644 index 000000000..d7f3097bd --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/PassSupport.h @@ -0,0 +1,253 @@ +//===- llvm/PassSupport.h - Pass Support code -------------------*- 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 stuff that is used to define and "use" Passes. This file +// is automatically #included by Pass.h, so: +// +// NO .CPP FILES SHOULD INCLUDE THIS FILE DIRECTLY +// +// Instead, #include Pass.h. +// +// This file defines Pass registration code and classes used for it. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_PASS_SUPPORT_H +#define LLVM_PASS_SUPPORT_H + +#include "Pass.h" + +namespace llvm { + +class TargetMachine; + +//===--------------------------------------------------------------------------- +/// PassInfo class - An instance of this class exists for every pass known by +/// the system, and can be obtained from a live Pass by calling its +/// getPassInfo() method. These objects are set up by the RegisterPass<> +/// template, defined below. +/// +class PassInfo { +public: + typedef Pass* (*NormalCtor_t)(); + +private: + const char *const PassName; // Nice name for Pass + const char *const PassArgument; // Command Line argument to run this pass + const intptr_t PassID; + const bool IsCFGOnlyPass; // Pass only looks at the CFG. + const bool IsAnalysis; // True if an analysis pass. + const bool IsAnalysisGroup; // True if an analysis group. + std::vector ItfImpl;// Interfaces implemented by this pass + + NormalCtor_t NormalCtor; + +public: + /// PassInfo ctor - Do not call this directly, this should only be invoked + /// through RegisterPass. + PassInfo(const char *name, const char *arg, intptr_t pi, + NormalCtor_t normal = 0, + bool isCFGOnly = false, bool is_analysis = false) + : PassName(name), PassArgument(arg), PassID(pi), + IsCFGOnlyPass(isCFGOnly), + IsAnalysis(is_analysis), IsAnalysisGroup(false), NormalCtor(normal) { + registerPass(); + } + /// PassInfo ctor - Do not call this directly, this should only be invoked + /// through RegisterPass. This version is for use by analysis groups; it + /// does not auto-register the pass. + PassInfo(const char *name, intptr_t pi) + : PassName(name), PassArgument(""), PassID(pi), + IsCFGOnlyPass(false), + IsAnalysis(false), IsAnalysisGroup(true), NormalCtor(0) { + } + + /// getPassName - Return the friendly name for the pass, never returns null + /// + const char *getPassName() const { return PassName; } + + /// getPassArgument - Return the command line option that may be passed to + /// 'opt' that will cause this pass to be run. This will return null if there + /// is no argument. + /// + const char *getPassArgument() const { return PassArgument; } + + /// getTypeInfo - Return the id object for the pass... + /// TODO : Rename + intptr_t getTypeInfo() const { return PassID; } + + /// isAnalysisGroup - Return true if this is an analysis group, not a normal + /// pass. + /// + bool isAnalysisGroup() const { return IsAnalysisGroup; } + bool isAnalysis() const { return IsAnalysis; } + + /// isCFGOnlyPass - return true if this pass only looks at the CFG for the + /// function. + bool isCFGOnlyPass() const { return IsCFGOnlyPass; } + + /// getNormalCtor - Return a pointer to a function, that when called, creates + /// an instance of the pass and returns it. This pointer may be null if there + /// is no default constructor for the pass. + /// + NormalCtor_t getNormalCtor() const { + return NormalCtor; + } + void setNormalCtor(NormalCtor_t Ctor) { + NormalCtor = Ctor; + } + + /// createPass() - Use this method to create an instance of this pass. + Pass *createPass() const { + assert((!isAnalysisGroup() || NormalCtor) && + "No default implementation found for analysis group!"); + assert(NormalCtor && + "Cannot call createPass on PassInfo without default ctor!"); + return NormalCtor(); + } + + /// addInterfaceImplemented - This method is called when this pass is + /// registered as a member of an analysis group with the RegisterAnalysisGroup + /// template. + /// + void addInterfaceImplemented(const PassInfo *ItfPI) { + ItfImpl.push_back(ItfPI); + } + + /// getInterfacesImplemented - Return a list of all of the analysis group + /// interfaces implemented by this pass. + /// + const std::vector &getInterfacesImplemented() const { + return ItfImpl; + } + +protected: + void registerPass(); + void unregisterPass(); + +private: + void operator=(const PassInfo &); // do not implement + PassInfo(const PassInfo &); // do not implement +}; + + +template +Pass *callDefaultCtor() { return new PassName(); } + +//===--------------------------------------------------------------------------- +/// RegisterPass template - This template class is used to notify the system +/// that a Pass is available for use, and registers it into the internal +/// database maintained by the PassManager. Unless this template is used, opt, +/// for example will not be able to see the pass and attempts to create the pass +/// will fail. This template is used in the follow manner (at global scope, in +/// your .cpp file): +/// +/// static RegisterPass tmp("passopt", "My Pass Name"); +/// +/// This statement will cause your pass to be created by calling the default +/// constructor exposed by the pass. If you have a different constructor that +/// must be called, create a global constructor function (which takes the +/// arguments you need and returns a Pass*) and register your pass like this: +/// +/// static RegisterPass tmp("passopt", "My Name"); +/// +template +struct RegisterPass : public PassInfo { + + // Register Pass using default constructor... + RegisterPass(const char *PassArg, const char *Name, bool CFGOnly = false, + bool is_analysis = false) + : PassInfo(Name, PassArg, intptr_t(&passName::ID), + PassInfo::NormalCtor_t(callDefaultCtor), + CFGOnly, is_analysis) { + } +}; + + +/// RegisterAnalysisGroup - Register a Pass as a member of an analysis _group_. +/// Analysis groups are used to define an interface (which need not derive from +/// Pass) that is required by passes to do their job. Analysis Groups differ +/// from normal analyses because any available implementation of the group will +/// be used if it is available. +/// +/// If no analysis implementing the interface is available, a default +/// implementation is created and added. A pass registers itself as the default +/// implementation by specifying 'true' as the second template argument of this +/// class. +/// +/// In addition to registering itself as an analysis group member, a pass must +/// register itself normally as well. Passes may be members of multiple groups +/// and may still be "required" specifically by name. +/// +/// The actual interface may also be registered as well (by not specifying the +/// second template argument). The interface should be registered to associate +/// a nice name with the interface. +/// +class RegisterAGBase : public PassInfo { +protected: + RegisterAGBase(const char *Name, + intptr_t InterfaceID, + intptr_t PassID = 0, + bool isDefault = false); +}; + +template +struct RegisterAnalysisGroup : public RegisterAGBase { + explicit RegisterAnalysisGroup(PassInfo &RPB) + : RegisterAGBase(RPB.getPassName(), + intptr_t(&Interface::ID), RPB.getTypeInfo(), + Default) { + } + + explicit RegisterAnalysisGroup(const char *Name) + : RegisterAGBase(Name, intptr_t(&Interface::ID)) { + } +}; + + + +//===--------------------------------------------------------------------------- +/// PassRegistrationListener class - This class is meant to be derived from by +/// clients that are interested in which passes get registered and unregistered +/// at runtime (which can be because of the RegisterPass constructors being run +/// as the program starts up, or may be because a shared object just got +/// loaded). Deriving from the PassRegistationListener class automatically +/// registers your object to receive callbacks indicating when passes are loaded +/// and removed. +/// +struct PassRegistrationListener { + + /// PassRegistrationListener ctor - Add the current object to the list of + /// PassRegistrationListeners... + PassRegistrationListener(); + + /// dtor - Remove object from list of listeners... + /// + virtual ~PassRegistrationListener(); + + /// Callback functions - These functions are invoked whenever a pass is loaded + /// or removed from the current executable. + /// + virtual void passRegistered(const PassInfo *) {} + + /// enumeratePasses - Iterate over the registered passes, calling the + /// passEnumerate callback on each PassInfo object. + /// + void enumeratePasses(); + + /// passEnumerate - Callback function invoked when someone calls + /// enumeratePasses on this PassRegistrationListener object. + /// + virtual void passEnumerate(const PassInfo *) {} +}; + + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Support/AlignOf.h b/libclamav/c++/llvm/include/llvm/Support/AlignOf.h new file mode 100644 index 000000000..6a7a1a6bd --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Support/AlignOf.h @@ -0,0 +1,60 @@ +//===--- AlignOf.h - Portable calculation of type alignment -----*- 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 the AlignOf function that computes alignments for +// arbitrary types. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_ALIGNOF_H +#define LLVM_SUPPORT_ALIGNOF_H + +namespace llvm { + +template +struct AlignmentCalcImpl { + char x; + T t; +private: + AlignmentCalcImpl() {} // Never instantiate. +}; + +/// AlignOf - A templated class that contains an enum value representing +/// the alignment of the template argument. For example, +/// AlignOf::Alignment represents the alignment of type "int". The +/// alignment calculated is the minimum alignment, and not necessarily +/// the "desired" alignment returned by GCC's __alignof__ (for example). Note +/// that because the alignment is an enum value, it can be used as a +/// compile-time constant (e.g., for template instantiation). +template +struct AlignOf { + enum { Alignment = + static_cast(sizeof(AlignmentCalcImpl) - sizeof(T)) }; + + enum { Alignment_GreaterEqual_2Bytes = Alignment >= 2 ? 1 : 0 }; + enum { Alignment_GreaterEqual_4Bytes = Alignment >= 4 ? 1 : 0 }; + enum { Alignment_GreaterEqual_8Bytes = Alignment >= 8 ? 1 : 0 }; + enum { Alignment_GreaterEqual_16Bytes = Alignment >= 16 ? 1 : 0 }; + + enum { Alignment_LessEqual_2Bytes = Alignment <= 2 ? 1 : 0 }; + enum { Alignment_LessEqual_4Bytes = Alignment <= 4 ? 1 : 0 }; + enum { Alignment_LessEqual_8Bytes = Alignment <= 8 ? 1 : 0 }; + enum { Alignment_LessEqual_16Bytes = Alignment <= 16 ? 1 : 0 }; + +}; + +/// alignof - A templated function that returns the mininum alignment of +/// of a type. This provides no extra functionality beyond the AlignOf +/// class besides some cosmetic cleanliness. Example usage: +/// alignof() returns the alignment of an int. +template +static inline unsigned alignof() { return AlignOf::Alignment; } + +} // end namespace llvm +#endif diff --git a/libclamav/c++/llvm/include/llvm/Support/Allocator.h b/libclamav/c++/llvm/include/llvm/Support/Allocator.h new file mode 100644 index 000000000..b0ed33d6e --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Support/Allocator.h @@ -0,0 +1,178 @@ +//===--- Allocator.h - Simple memory allocation abstraction -----*- 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 the MallocAllocator and BumpPtrAllocator interfaces. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_ALLOCATOR_H +#define LLVM_SUPPORT_ALLOCATOR_H + +#include "llvm/Support/AlignOf.h" +#include "llvm/System/DataTypes.h" +#include +#include + +namespace llvm { + +class MallocAllocator { +public: + MallocAllocator() {} + ~MallocAllocator() {} + + void Reset() {} + + void *Allocate(size_t Size, size_t /*Alignment*/) { return malloc(Size); } + + template + T *Allocate() { return static_cast(malloc(sizeof(T))); } + + template + T *Allocate(size_t Num) { + return static_cast(malloc(sizeof(T)*Num)); + } + + void Deallocate(const void *Ptr) { free(const_cast(Ptr)); } + + void PrintStats() const {} +}; + +/// MemSlab - This structure lives at the beginning of every slab allocated by +/// the bump allocator. +class MemSlab { +public: + size_t Size; + MemSlab *NextPtr; +}; + +/// SlabAllocator - This class can be used to parameterize the underlying +/// allocation strategy for the bump allocator. In particular, this is used +/// by the JIT to allocate contiguous swathes of executable memory. The +/// interface uses MemSlab's instead of void *'s so that the allocator +/// doesn't have to remember the size of the pointer it allocated. +class SlabAllocator { +public: + virtual ~SlabAllocator(); + virtual MemSlab *Allocate(size_t Size) = 0; + virtual void Deallocate(MemSlab *Slab) = 0; +}; + +/// MallocSlabAllocator - The default slab allocator for the bump allocator +/// is an adapter class for MallocAllocator that just forwards the method +/// calls and translates the arguments. +class MallocSlabAllocator : public SlabAllocator { + /// Allocator - The underlying allocator that we forward to. + /// + MallocAllocator Allocator; + +public: + MallocSlabAllocator() : Allocator() { } + virtual ~MallocSlabAllocator(); + virtual MemSlab *Allocate(size_t Size); + virtual void Deallocate(MemSlab *Slab); +}; + +/// BumpPtrAllocator - This allocator is useful for containers that need +/// very simple memory allocation strategies. In particular, this just keeps +/// allocating memory, and never deletes it until the entire block is dead. This +/// makes allocation speedy, but must only be used when the trade-off is ok. +class BumpPtrAllocator { + BumpPtrAllocator(const BumpPtrAllocator &); // do not implement + void operator=(const BumpPtrAllocator &); // do not implement + + /// SlabSize - Allocate data into slabs of this size unless we get an + /// allocation above SizeThreshold. + size_t SlabSize; + + /// SizeThreshold - For any allocation larger than this threshold, we should + /// allocate a separate slab. + size_t SizeThreshold; + + /// Allocator - The underlying allocator we use to get slabs of memory. This + /// defaults to MallocSlabAllocator, which wraps malloc, but it could be + /// changed to use a custom allocator. + SlabAllocator &Allocator; + + /// CurSlab - The slab that we are currently allocating into. + /// + MemSlab *CurSlab; + + /// CurPtr - The current pointer into the current slab. This points to the + /// next free byte in the slab. + char *CurPtr; + + /// End - The end of the current slab. + /// + char *End; + + /// BytesAllocated - This field tracks how many bytes we've allocated, so + /// that we can compute how much space was wasted. + size_t BytesAllocated; + + /// AlignPtr - Align Ptr to Alignment bytes, rounding up. Alignment should + /// be a power of two. This method rounds up, so AlignPtr(7, 4) == 8 and + /// AlignPtr(8, 4) == 8. + static char *AlignPtr(char *Ptr, size_t Alignment); + + /// StartNewSlab - Allocate a new slab and move the bump pointers over into + /// the new slab. Modifies CurPtr and End. + void StartNewSlab(); + + /// DeallocateSlabs - Deallocate all memory slabs after and including this + /// one. + void DeallocateSlabs(MemSlab *Slab); + + static MallocSlabAllocator DefaultSlabAllocator; + +public: + BumpPtrAllocator(size_t size = 4096, size_t threshold = 4096, + SlabAllocator &allocator = DefaultSlabAllocator); + ~BumpPtrAllocator(); + + /// Reset - Deallocate all but the current slab and reset the current pointer + /// to the beginning of it, freeing all memory allocated so far. + void Reset(); + + /// Allocate - Allocate space at the specified alignment. + /// + void *Allocate(size_t Size, size_t Alignment); + + /// Allocate space, but do not construct, one object. + /// + template + T *Allocate() { + return static_cast(Allocate(sizeof(T),AlignOf::Alignment)); + } + + /// Allocate space for an array of objects. This does not construct the + /// objects though. + template + T *Allocate(size_t Num) { + return static_cast(Allocate(Num * sizeof(T), AlignOf::Alignment)); + } + + /// Allocate space for a specific count of elements and with a specified + /// alignment. + template + T *Allocate(size_t Num, size_t Alignment) { + // Round EltSize up to the specified alignment. + size_t EltSize = (sizeof(T)+Alignment-1)&(-Alignment); + return static_cast(Allocate(Num * EltSize, Alignment)); + } + + void Deallocate(const void * /*Ptr*/) {} + + unsigned GetNumSlabs() const; + + void PrintStats() const; +}; + +} // end namespace llvm + +#endif // LLVM_SUPPORT_ALLOCATOR_H diff --git a/libclamav/c++/llvm/include/llvm/Support/CFG.h b/libclamav/c++/llvm/include/llvm/Support/CFG.h new file mode 100644 index 000000000..3a20696f0 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Support/CFG.h @@ -0,0 +1,266 @@ +//===-- llvm/Support/CFG.h - Process LLVM structures as graphs --*- 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 specializations of GraphTraits that allow Function and +// BasicBlock graphs to be treated as proper graphs for generic algorithms. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_CFG_H +#define LLVM_SUPPORT_CFG_H + +#include "llvm/ADT/GraphTraits.h" +#include "llvm/Function.h" +#include "llvm/InstrTypes.h" + +namespace llvm { + +//===----------------------------------------------------------------------===// +// BasicBlock pred_iterator definition +//===----------------------------------------------------------------------===// + +template // Predecessor Iterator +class PredIterator : public std::iterator { + typedef std::iterator super; + _USE_iterator It; +public: + typedef PredIterator<_Ptr,_USE_iterator> _Self; + typedef typename super::pointer pointer; + + inline void advancePastNonTerminators() { + // Loop to ignore non terminator uses (for example PHI nodes)... + while (!It.atEnd() && !isa(*It)) + ++It; + } + + inline PredIterator(_Ptr *bb) : It(bb->use_begin()) { + advancePastNonTerminators(); + } + inline PredIterator(_Ptr *bb, bool) : It(bb->use_end()) {} + + inline bool operator==(const _Self& x) const { return It == x.It; } + inline bool operator!=(const _Self& x) const { return !operator==(x); } + + inline pointer operator*() const { + assert(!It.atEnd() && "pred_iterator out of range!"); + return cast(*It)->getParent(); + } + inline pointer *operator->() const { return &(operator*()); } + + inline _Self& operator++() { // Preincrement + assert(!It.atEnd() && "pred_iterator out of range!"); + ++It; advancePastNonTerminators(); + return *this; + } + + inline _Self operator++(int) { // Postincrement + _Self tmp = *this; ++*this; return tmp; + } +}; + +typedef PredIterator pred_iterator; +typedef PredIterator pred_const_iterator; + +inline pred_iterator pred_begin(BasicBlock *BB) { return pred_iterator(BB); } +inline pred_const_iterator pred_begin(const BasicBlock *BB) { + return pred_const_iterator(BB); +} +inline pred_iterator pred_end(BasicBlock *BB) { return pred_iterator(BB, true);} +inline pred_const_iterator pred_end(const BasicBlock *BB) { + return pred_const_iterator(BB, true); +} + + + +//===----------------------------------------------------------------------===// +// BasicBlock succ_iterator definition +//===----------------------------------------------------------------------===// + +template // Successor Iterator +class SuccIterator : public std::iterator { + const Term_ Term; + unsigned idx; + typedef std::iterator super; +public: + typedef SuccIterator _Self; + typedef typename super::pointer pointer; + // TODO: This can be random access iterator, need operator+ and stuff tho + + inline SuccIterator(Term_ T) : Term(T), idx(0) { // begin iterator + assert(T && "getTerminator returned null!"); + } + inline SuccIterator(Term_ T, bool) // end iterator + : Term(T), idx(Term->getNumSuccessors()) { + assert(T && "getTerminator returned null!"); + } + + inline const _Self &operator=(const _Self &I) { + assert(Term == I.Term &&"Cannot assign iterators to two different blocks!"); + idx = I.idx; + return *this; + } + + /// getSuccessorIndex - This is used to interface between code that wants to + /// operate on terminator instructions directly. + unsigned getSuccessorIndex() const { return idx; } + + inline bool operator==(const _Self& x) const { return idx == x.idx; } + inline bool operator!=(const _Self& x) const { return !operator==(x); } + + inline pointer operator*() const { return Term->getSuccessor(idx); } + inline pointer operator->() const { return operator*(); } + + inline _Self& operator++() { ++idx; return *this; } // Preincrement + inline _Self operator++(int) { // Postincrement + _Self tmp = *this; ++*this; return tmp; + } + + inline _Self& operator--() { --idx; return *this; } // Predecrement + inline _Self operator--(int) { // Postdecrement + _Self tmp = *this; --*this; return tmp; + } +}; + +typedef SuccIterator succ_iterator; +typedef SuccIterator succ_const_iterator; + +inline succ_iterator succ_begin(BasicBlock *BB) { + return succ_iterator(BB->getTerminator()); +} +inline succ_const_iterator succ_begin(const BasicBlock *BB) { + return succ_const_iterator(BB->getTerminator()); +} +inline succ_iterator succ_end(BasicBlock *BB) { + return succ_iterator(BB->getTerminator(), true); +} +inline succ_const_iterator succ_end(const BasicBlock *BB) { + return succ_const_iterator(BB->getTerminator(), true); +} + + + +//===--------------------------------------------------------------------===// +// GraphTraits specializations for basic block graphs (CFGs) +//===--------------------------------------------------------------------===// + +// Provide specializations of GraphTraits to be able to treat a function as a +// graph of basic blocks... + +template <> struct GraphTraits { + typedef BasicBlock NodeType; + typedef succ_iterator ChildIteratorType; + + static NodeType *getEntryNode(BasicBlock *BB) { return BB; } + static inline ChildIteratorType child_begin(NodeType *N) { + return succ_begin(N); + } + static inline ChildIteratorType child_end(NodeType *N) { + return succ_end(N); + } +}; + +template <> struct GraphTraits { + typedef const BasicBlock NodeType; + typedef succ_const_iterator ChildIteratorType; + + static NodeType *getEntryNode(const BasicBlock *BB) { return BB; } + + static inline ChildIteratorType child_begin(NodeType *N) { + return succ_begin(N); + } + static inline ChildIteratorType child_end(NodeType *N) { + return succ_end(N); + } +}; + +// Provide specializations of GraphTraits to be able to treat a function as a +// graph of basic blocks... and to walk it in inverse order. Inverse order for +// a function is considered to be when traversing the predecessor edges of a BB +// instead of the successor edges. +// +template <> struct GraphTraits > { + typedef BasicBlock NodeType; + typedef pred_iterator ChildIteratorType; + static NodeType *getEntryNode(Inverse G) { return G.Graph; } + static inline ChildIteratorType child_begin(NodeType *N) { + return pred_begin(N); + } + static inline ChildIteratorType child_end(NodeType *N) { + return pred_end(N); + } +}; + +template <> struct GraphTraits > { + typedef const BasicBlock NodeType; + typedef pred_const_iterator ChildIteratorType; + static NodeType *getEntryNode(Inverse G) { + return G.Graph; + } + static inline ChildIteratorType child_begin(NodeType *N) { + return pred_begin(N); + } + static inline ChildIteratorType child_end(NodeType *N) { + return pred_end(N); + } +}; + + + +//===--------------------------------------------------------------------===// +// GraphTraits specializations for function basic block graphs (CFGs) +//===--------------------------------------------------------------------===// + +// Provide specializations of GraphTraits to be able to treat a function as a +// graph of basic blocks... these are the same as the basic block iterators, +// except that the root node is implicitly the first node of the function. +// +template <> struct GraphTraits : public GraphTraits { + static NodeType *getEntryNode(Function *F) { return &F->getEntryBlock(); } + + // nodes_iterator/begin/end - Allow iteration over all nodes in the graph + typedef Function::iterator nodes_iterator; + static nodes_iterator nodes_begin(Function *F) { return F->begin(); } + static nodes_iterator nodes_end (Function *F) { return F->end(); } +}; +template <> struct GraphTraits : + public GraphTraits { + static NodeType *getEntryNode(const Function *F) {return &F->getEntryBlock();} + + // nodes_iterator/begin/end - Allow iteration over all nodes in the graph + typedef Function::const_iterator nodes_iterator; + static nodes_iterator nodes_begin(const Function *F) { return F->begin(); } + static nodes_iterator nodes_end (const Function *F) { return F->end(); } +}; + + +// Provide specializations of GraphTraits to be able to treat a function as a +// graph of basic blocks... and to walk it in inverse order. Inverse order for +// a function is considered to be when traversing the predecessor edges of a BB +// instead of the successor edges. +// +template <> struct GraphTraits > : + public GraphTraits > { + static NodeType *getEntryNode(Inverse G) { + return &G.Graph->getEntryBlock(); + } +}; +template <> struct GraphTraits > : + public GraphTraits > { + static NodeType *getEntryNode(Inverse G) { + return &G.Graph->getEntryBlock(); + } +}; + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Support/CallSite.h b/libclamav/c++/llvm/include/llvm/Support/CallSite.h new file mode 100644 index 000000000..285b558af --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Support/CallSite.h @@ -0,0 +1,198 @@ +//===-- llvm/Support/CallSite.h - Abstract Call & Invoke instrs -*- 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 the CallSite class, which is a handy wrapper for code that +// wants to treat Call and Invoke instructions in a generic way. +// +// NOTE: This class is supposed to have "value semantics". So it should be +// passed by value, not by reference; it should not be "new"ed or "delete"d. It +// is efficiently copyable, assignable and constructable, with cost equivalent +// to copying a pointer (notice that it has only a single data member). +// The internal representation carries a flag which indicates which of the two +// variants is enclosed. This allows for cheaper checks when various accessors +// of CallSite are employed. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_CALLSITE_H +#define LLVM_SUPPORT_CALLSITE_H + +#include "llvm/Attributes.h" +#include "llvm/ADT/PointerIntPair.h" +#include "llvm/BasicBlock.h" +#include "llvm/CallingConv.h" +#include "llvm/Instruction.h" + +namespace llvm { + +class CallInst; +class InvokeInst; + +class CallSite { + PointerIntPair I; +public: + CallSite() : I(0, false) {} + CallSite(CallInst *CI) : I(reinterpret_cast(CI), true) {} + CallSite(InvokeInst *II) : I(reinterpret_cast(II), false) {} + CallSite(Instruction *C); + + bool operator==(const CallSite &CS) const { return I == CS.I; } + bool operator!=(const CallSite &CS) const { return I != CS.I; } + + /// CallSite::get - This static method is sort of like a constructor. It will + /// create an appropriate call site for a Call or Invoke instruction, but it + /// can also create a null initialized CallSite object for something which is + /// NOT a call site. + /// + static CallSite get(Value *V) { + if (Instruction *I = dyn_cast(V)) { + if (I->getOpcode() == Instruction::Call) + return CallSite(reinterpret_cast(I)); + else if (I->getOpcode() == Instruction::Invoke) + return CallSite(reinterpret_cast(I)); + } + return CallSite(); + } + + /// getCallingConv/setCallingConv - get or set the calling convention of the + /// call. + CallingConv::ID getCallingConv() const; + void setCallingConv(CallingConv::ID CC); + + /// getAttributes/setAttributes - get or set the parameter attributes of + /// the call. + const AttrListPtr &getAttributes() const; + void setAttributes(const AttrListPtr &PAL); + + /// paramHasAttr - whether the call or the callee has the given attribute. + bool paramHasAttr(uint16_t i, Attributes attr) const; + + /// @brief Extract the alignment for a call or parameter (0=unknown). + uint16_t getParamAlignment(uint16_t i) const; + + /// @brief Determine if the call does not access memory. + bool doesNotAccessMemory() const; + void setDoesNotAccessMemory(bool doesNotAccessMemory = true); + + /// @brief Determine if the call does not access or only reads memory. + bool onlyReadsMemory() const; + void setOnlyReadsMemory(bool onlyReadsMemory = true); + + /// @brief Determine if the call cannot return. + bool doesNotReturn() const; + void setDoesNotReturn(bool doesNotReturn = true); + + /// @brief Determine if the call cannot unwind. + bool doesNotThrow() const; + void setDoesNotThrow(bool doesNotThrow = true); + + /// getType - Return the type of the instruction that generated this call site + /// + const Type *getType() const { return getInstruction()->getType(); } + + /// isCall - true if a CallInst is enclosed. + /// Note that !isCall() does not mean it is an InvokeInst enclosed, + /// it also could signify a NULL Instruction pointer. + bool isCall() const { return I.getInt(); } + + /// isInvoke - true if a InvokeInst is enclosed. + /// + bool isInvoke() const { return getInstruction() && !I.getInt(); } + + /// getInstruction - Return the instruction this call site corresponds to + /// + Instruction *getInstruction() const { return I.getPointer(); } + + /// getCaller - Return the caller function for this call site + /// + Function *getCaller() const { return getInstruction() + ->getParent()->getParent(); } + + /// getCalledValue - Return the pointer to function that is being called... + /// + Value *getCalledValue() const { + assert(getInstruction() && "Not a call or invoke instruction!"); + return getInstruction()->getOperand(0); + } + + /// getCalledFunction - Return the function being called if this is a direct + /// call, otherwise return null (if it's an indirect call). + /// + Function *getCalledFunction() const { + return dyn_cast(getCalledValue()); + } + + /// setCalledFunction - Set the callee to the specified value... + /// + void setCalledFunction(Value *V) { + assert(getInstruction() && "Not a call or invoke instruction!"); + getInstruction()->setOperand(0, V); + } + + Value *getArgument(unsigned ArgNo) const { + assert(arg_begin() + ArgNo < arg_end() && "Argument # out of range!"); + return *(arg_begin()+ArgNo); + } + + void setArgument(unsigned ArgNo, Value* newVal) { + assert(getInstruction() && "Not a call or invoke instruction!"); + assert(arg_begin() + ArgNo < arg_end() && "Argument # out of range!"); + getInstruction()->setOperand(getArgumentOffset() + ArgNo, newVal); + } + + /// Given an operand number, returns the argument that corresponds to it. + /// OperandNo must be a valid operand number that actually corresponds to an + /// argument. + unsigned getArgumentNo(unsigned OperandNo) const { + assert(OperandNo >= getArgumentOffset() && "Operand number passed was not " + "a valid argument"); + return OperandNo - getArgumentOffset(); + } + + /// hasArgument - Returns true if this CallSite passes the given Value* as an + /// argument to the called function. + bool hasArgument(const Value *Arg) const; + + /// arg_iterator - The type of iterator to use when looping over actual + /// arguments at this call site... + typedef User::op_iterator arg_iterator; + + /// arg_begin/arg_end - Return iterators corresponding to the actual argument + /// list for a call site. + arg_iterator arg_begin() const { + assert(getInstruction() && "Not a call or invoke instruction!"); + // Skip non-arguments + return getInstruction()->op_begin() + getArgumentOffset(); + } + + arg_iterator arg_end() const { return getInstruction()->op_end(); } + bool arg_empty() const { return arg_end() == arg_begin(); } + unsigned arg_size() const { return unsigned(arg_end() - arg_begin()); } + + bool operator<(const CallSite &CS) const { + return getInstruction() < CS.getInstruction(); + } + + bool isCallee(Value::use_iterator UI) const { + return getInstruction()->op_begin() == &UI.getUse(); + } + +private: + /// Returns the operand number of the first argument + unsigned getArgumentOffset() const { + if (isCall()) + return 1; // Skip Function + else + return 3; // Skip Function, BB, BB + } +}; + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Support/Casting.h b/libclamav/c++/llvm/include/llvm/Support/Casting.h new file mode 100644 index 000000000..35fb29ec6 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Support/Casting.h @@ -0,0 +1,303 @@ +//===-- llvm/Support/Casting.h - Allow flexible, checked, casts -*- 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 the isa(), cast(), dyn_cast(), cast_or_null(), +// and dyn_cast_or_null() templates. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_CASTING_H +#define LLVM_SUPPORT_CASTING_H + +#include + +namespace llvm { + +//===----------------------------------------------------------------------===// +// isa Support Templates +//===----------------------------------------------------------------------===// + +template struct isa_impl_cl; + +// Define a template that can be specialized by smart pointers to reflect the +// fact that they are automatically dereferenced, and are not involved with the +// template selection process... the default implementation is a noop. +// +template struct simplify_type { + typedef From SimpleType; // The real type this represents... + + // An accessor to get the real value... + static SimpleType &getSimplifiedValue(From &Val) { return Val; } +}; + +template struct simplify_type { + typedef const From SimpleType; + static SimpleType &getSimplifiedValue(const From &Val) { + return simplify_type::getSimplifiedValue(static_cast(Val)); + } +}; + + +// isa - Return true if the parameter to the template is an instance of the +// template type argument. Used like this: +// +// if (isa(myVal)) { ... } +// +template +inline bool isa_impl(const From &Val) { + return To::classof(&Val); +} + +template +struct isa_impl_wrap { + // When From != SimplifiedType, we can simplify the type some more by using + // the simplify_type template. + static bool doit(const From &Val) { + return isa_impl_cl::template + isa(simplify_type::getSimplifiedValue(Val)); + } +}; + +template +struct isa_impl_wrap { + // When From == SimpleType, we are as simple as we are going to get. + static bool doit(const FromTy &Val) { + return isa_impl(Val); + } +}; + +// isa_impl_cl - Use class partial specialization to transform types to a single +// canonical form for isa_impl. +// +template +struct isa_impl_cl { + template + static bool isa(const FromCl &Val) { + return isa_impl_wrap::SimpleType>::doit(Val); + } +}; + +// Specialization used to strip const qualifiers off of the FromCl type... +template +struct isa_impl_cl { + template + static bool isa(const FromCl &Val) { + return isa_impl_cl::template isa(Val); + } +}; + +// Define pointer traits in terms of base traits... +template +struct isa_impl_cl { + template + static bool isa(FromCl *Val) { + return isa_impl_cl::template isa(*Val); + } +}; + +// Define reference traits in terms of base traits... +template +struct isa_impl_cl { + template + static bool isa(FromCl &Val) { + return isa_impl_cl::template isa(&Val); + } +}; + +template +inline bool isa(const Y &Val) { + return isa_impl_cl::template isa(Val); +} + +//===----------------------------------------------------------------------===// +// cast Support Templates +//===----------------------------------------------------------------------===// + +template struct cast_retty; + + +// Calculate what type the 'cast' function should return, based on a requested +// type of To and a source type of From. +template struct cast_retty_impl { + typedef To& ret_type; // Normal case, return Ty& +}; +template struct cast_retty_impl { + typedef const To &ret_type; // Normal case, return Ty& +}; + +template struct cast_retty_impl { + typedef To* ret_type; // Pointer arg case, return Ty* +}; + +template struct cast_retty_impl { + typedef const To* ret_type; // Constant pointer arg case, return const Ty* +}; + +template struct cast_retty_impl { + typedef const To* ret_type; // Constant pointer arg case, return const Ty* +}; + + +template +struct cast_retty_wrap { + // When the simplified type and the from type are not the same, use the type + // simplifier to reduce the type, then reuse cast_retty_impl to get the + // resultant type. + typedef typename cast_retty::ret_type ret_type; +}; + +template +struct cast_retty_wrap { + // When the simplified type is equal to the from type, use it directly. + typedef typename cast_retty_impl::ret_type ret_type; +}; + +template +struct cast_retty { + typedef typename cast_retty_wrap::SimpleType>::ret_type ret_type; +}; + +// Ensure the non-simple values are converted using the simplify_type template +// that may be specialized by smart pointers... +// +template struct cast_convert_val { + // This is not a simple type, use the template to simplify it... + static typename cast_retty::ret_type doit(const From &Val) { + return cast_convert_val::SimpleType>::doit( + simplify_type::getSimplifiedValue(Val)); + } +}; + +template struct cast_convert_val { + // This _is_ a simple type, just cast it. + static typename cast_retty::ret_type doit(const FromTy &Val) { + return reinterpret_cast::ret_type>( + const_cast(Val)); + } +}; + + + +// cast - Return the argument parameter cast to the specified type. This +// casting operator asserts that the type is correct, so it does not return null +// on failure. But it will correctly return NULL when the input is NULL. +// Used Like this: +// +// cast(myVal)->getParent() +// +template +inline typename cast_retty::ret_type cast(const Y &Val) { + assert(isa(Val) && "cast() argument of incompatible type!"); + return cast_convert_val::SimpleType>::doit(Val); +} + +// cast_or_null - Functionally identical to cast, except that a null value is +// accepted. +// +template +inline typename cast_retty::ret_type cast_or_null(Y *Val) { + if (Val == 0) return 0; + assert(isa(Val) && "cast_or_null() argument of incompatible type!"); + return cast(Val); +} + + +// dyn_cast - Return the argument parameter cast to the specified type. This +// casting operator returns null if the argument is of the wrong type, so it can +// be used to test for a type as well as cast if successful. This should be +// used in the context of an if statement like this: +// +// if (const Instruction *I = dyn_cast(myVal)) { ... } +// + +template +inline typename cast_retty::ret_type dyn_cast(const Y &Val) { + return isa(Val) ? cast(Val) : 0; +} + +// dyn_cast_or_null - Functionally identical to dyn_cast, except that a null +// value is accepted. +// +template +inline typename cast_retty::ret_type dyn_cast_or_null(const Y &Val) { + return (Val && isa(Val)) ? cast(Val) : 0; +} + + +#ifdef DEBUG_CAST_OPERATORS +#include "llvm/Support/raw_ostream.h" + +struct bar { + bar() {} +private: + bar(const bar &); +}; +struct foo { + void ext() const; + /* static bool classof(const bar *X) { + cerr << "Classof: " << X << "\n"; + return true; + }*/ +}; + +template <> inline bool isa_impl(const bar &Val) { + errs() << "Classof: " << &Val << "\n"; + return true; +} + + +bar *fub(); +void test(bar &B1, const bar *B2) { + // test various configurations of const + const bar &B3 = B1; + const bar *const B4 = B2; + + // test isa + if (!isa(B1)) return; + if (!isa(B2)) return; + if (!isa(B3)) return; + if (!isa(B4)) return; + + // test cast + foo &F1 = cast(B1); + const foo *F3 = cast(B2); + const foo *F4 = cast(B2); + const foo &F8 = cast(B3); + const foo *F9 = cast(B4); + foo *F10 = cast(fub()); + + // test cast_or_null + const foo *F11 = cast_or_null(B2); + const foo *F12 = cast_or_null(B2); + const foo *F13 = cast_or_null(B4); + const foo *F14 = cast_or_null(fub()); // Shouldn't print. + + // These lines are errors... + //foo *F20 = cast(B2); // Yields const foo* + //foo &F21 = cast(B3); // Yields const foo& + //foo *F22 = cast(B4); // Yields const foo* + //foo &F23 = cast_or_null(B1); + //const foo &F24 = cast_or_null(B3); +} + +bar *fub() { return 0; } +void main() { + bar B; + test(B, &B); +} + +#endif + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Support/CommandLine.h b/libclamav/c++/llvm/include/llvm/Support/CommandLine.h new file mode 100644 index 000000000..2e65fdd79 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Support/CommandLine.h @@ -0,0 +1,1384 @@ +//===- llvm/Support/CommandLine.h - Command line handler --------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This class implements a command line argument processor that is useful when +// creating a tool. It provides a simple, minimalistic interface that is easily +// extensible and supports nonlocal (library) command line options. +// +// Note that rather than trying to figure out what this code does, you should +// read the library documentation located in docs/CommandLine.html or looks at +// the many example usages in tools/*/*.cpp +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_COMMANDLINE_H +#define LLVM_SUPPORT_COMMANDLINE_H + +#include "llvm/Support/type_traits.h" +#include "llvm/Support/Compiler.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/Twine.h" +#include +#include +#include +#include +#include + +namespace llvm { + +/// cl Namespace - This namespace contains all of the command line option +/// processing machinery. It is intentionally a short name to make qualified +/// usage concise. +namespace cl { + +//===----------------------------------------------------------------------===// +// ParseCommandLineOptions - Command line option processing entry point. +// +void ParseCommandLineOptions(int argc, char **argv, + const char *Overview = 0, + bool ReadResponseFiles = false); + +//===----------------------------------------------------------------------===// +// ParseEnvironmentOptions - Environment variable option processing alternate +// entry point. +// +void ParseEnvironmentOptions(const char *progName, const char *envvar, + const char *Overview = 0, + bool ReadResponseFiles = false); + +///===---------------------------------------------------------------------===// +/// SetVersionPrinter - Override the default (LLVM specific) version printer +/// used to print out the version when --version is given +/// on the command line. This allows other systems using the +/// CommandLine utilities to print their own version string. +void SetVersionPrinter(void (*func)()); + + +// MarkOptionsChanged - Internal helper function. +void MarkOptionsChanged(); + +//===----------------------------------------------------------------------===// +// Flags permitted to be passed to command line arguments +// + +enum NumOccurrencesFlag { // Flags for the number of occurrences allowed + Optional = 0x01, // Zero or One occurrence + ZeroOrMore = 0x02, // Zero or more occurrences allowed + Required = 0x03, // One occurrence required + OneOrMore = 0x04, // One or more occurrences required + + // ConsumeAfter - Indicates that this option is fed anything that follows the + // last positional argument required by the application (it is an error if + // there are zero positional arguments, and a ConsumeAfter option is used). + // Thus, for example, all arguments to LLI are processed until a filename is + // found. Once a filename is found, all of the succeeding arguments are + // passed, unprocessed, to the ConsumeAfter option. + // + ConsumeAfter = 0x05, + + OccurrencesMask = 0x07 +}; + +enum ValueExpected { // Is a value required for the option? + ValueOptional = 0x08, // The value can appear... or not + ValueRequired = 0x10, // The value is required to appear! + ValueDisallowed = 0x18, // A value may not be specified (for flags) + ValueMask = 0x18 +}; + +enum OptionHidden { // Control whether -help shows this option + NotHidden = 0x20, // Option included in --help & --help-hidden + Hidden = 0x40, // -help doesn't, but --help-hidden does + ReallyHidden = 0x60, // Neither --help nor --help-hidden show this arg + HiddenMask = 0x60 +}; + +// Formatting flags - This controls special features that the option might have +// that cause it to be parsed differently... +// +// Prefix - This option allows arguments that are otherwise unrecognized to be +// matched by options that are a prefix of the actual value. This is useful for +// cases like a linker, where options are typically of the form '-lfoo' or +// '-L../../include' where -l or -L are the actual flags. When prefix is +// enabled, and used, the value for the flag comes from the suffix of the +// argument. +// +// Grouping - With this option enabled, multiple letter options are allowed to +// bunch together with only a single hyphen for the whole group. This allows +// emulation of the behavior that ls uses for example: ls -la === ls -l -a +// + +enum FormattingFlags { + NormalFormatting = 0x000, // Nothing special + Positional = 0x080, // Is a positional argument, no '-' required + Prefix = 0x100, // Can this option directly prefix its value? + Grouping = 0x180, // Can this option group with other options? + FormattingMask = 0x180 // Union of the above flags. +}; + +enum MiscFlags { // Miscellaneous flags to adjust argument + CommaSeparated = 0x200, // Should this cl::list split between commas? + PositionalEatsArgs = 0x400, // Should this positional cl::list eat -args? + Sink = 0x800, // Should this cl::list eat all unknown options? + MiscMask = 0xE00 // Union of the above flags. +}; + + + +//===----------------------------------------------------------------------===// +// Option Base class +// +class alias; +class Option { + friend class alias; + + // handleOccurrences - Overriden by subclasses to handle the value passed into + // an argument. Should return true if there was an error processing the + // argument and the program should exit. + // + virtual bool handleOccurrence(unsigned pos, StringRef ArgName, + StringRef Arg) = 0; + + virtual enum ValueExpected getValueExpectedFlagDefault() const { + return ValueOptional; + } + + // Out of line virtual function to provide home for the class. + virtual void anchor(); + + int NumOccurrences; // The number of times specified + int Flags; // Flags for the argument + unsigned Position; // Position of last occurrence of the option + unsigned AdditionalVals;// Greater than 0 for multi-valued option. + Option *NextRegistered; // Singly linked list of registered options. +public: + const char *ArgStr; // The argument string itself (ex: "help", "o") + const char *HelpStr; // The descriptive text message for --help + const char *ValueStr; // String describing what the value of this option is + + inline enum NumOccurrencesFlag getNumOccurrencesFlag() const { + return static_cast(Flags & OccurrencesMask); + } + inline enum ValueExpected getValueExpectedFlag() const { + int VE = Flags & ValueMask; + return VE ? static_cast(VE) + : getValueExpectedFlagDefault(); + } + inline enum OptionHidden getOptionHiddenFlag() const { + return static_cast(Flags & HiddenMask); + } + inline enum FormattingFlags getFormattingFlag() const { + return static_cast(Flags & FormattingMask); + } + inline unsigned getMiscFlags() const { + return Flags & MiscMask; + } + inline unsigned getPosition() const { return Position; } + inline unsigned getNumAdditionalVals() const { return AdditionalVals; } + + // hasArgStr - Return true if the argstr != "" + bool hasArgStr() const { return ArgStr[0] != 0; } + + //-------------------------------------------------------------------------=== + // Accessor functions set by OptionModifiers + // + void setArgStr(const char *S) { ArgStr = S; } + void setDescription(const char *S) { HelpStr = S; } + void setValueStr(const char *S) { ValueStr = S; } + + void setFlag(unsigned Flag, unsigned FlagMask) { + Flags &= ~FlagMask; + Flags |= Flag; + } + + void setNumOccurrencesFlag(enum NumOccurrencesFlag Val) { + setFlag(Val, OccurrencesMask); + } + void setValueExpectedFlag(enum ValueExpected Val) { setFlag(Val, ValueMask); } + void setHiddenFlag(enum OptionHidden Val) { setFlag(Val, HiddenMask); } + void setFormattingFlag(enum FormattingFlags V) { setFlag(V, FormattingMask); } + void setMiscFlag(enum MiscFlags M) { setFlag(M, M); } + void setPosition(unsigned pos) { Position = pos; } +protected: + explicit Option(unsigned DefaultFlags) + : NumOccurrences(0), Flags(DefaultFlags | NormalFormatting), Position(0), + AdditionalVals(0), NextRegistered(0), + ArgStr(""), HelpStr(""), ValueStr("") { + assert(getNumOccurrencesFlag() != 0 && + getOptionHiddenFlag() != 0 && "Not all default flags specified!"); + } + + inline void setNumAdditionalVals(unsigned n) { AdditionalVals = n; } +public: + // addArgument - Register this argument with the commandline system. + // + void addArgument(); + + Option *getNextRegisteredOption() const { return NextRegistered; } + + // Return the width of the option tag for printing... + virtual size_t getOptionWidth() const = 0; + + // printOptionInfo - Print out information about this option. The + // to-be-maintained width is specified. + // + virtual void printOptionInfo(size_t GlobalWidth) const = 0; + + virtual void getExtraOptionNames(SmallVectorImpl &) {} + + // addOccurrence - Wrapper around handleOccurrence that enforces Flags. + // + bool addOccurrence(unsigned pos, StringRef ArgName, + StringRef Value, bool MultiArg = false); + + // Prints option name followed by message. Always returns true. + bool error(const Twine &Message, StringRef ArgName = StringRef()); + +public: + inline int getNumOccurrences() const { return NumOccurrences; } + virtual ~Option() {} +}; + + +//===----------------------------------------------------------------------===// +// Command line option modifiers that can be used to modify the behavior of +// command line option parsers... +// + +// desc - Modifier to set the description shown in the --help output... +struct desc { + const char *Desc; + desc(const char *Str) : Desc(Str) {} + void apply(Option &O) const { O.setDescription(Desc); } +}; + +// value_desc - Modifier to set the value description shown in the --help +// output... +struct value_desc { + const char *Desc; + value_desc(const char *Str) : Desc(Str) {} + void apply(Option &O) const { O.setValueStr(Desc); } +}; + +// init - Specify a default (initial) value for the command line argument, if +// the default constructor for the argument type does not give you what you +// want. This is only valid on "opt" arguments, not on "list" arguments. +// +template +struct initializer { + const Ty &Init; + initializer(const Ty &Val) : Init(Val) {} + + template + void apply(Opt &O) const { O.setInitialValue(Init); } +}; + +template +initializer init(const Ty &Val) { + return initializer(Val); +} + + +// location - Allow the user to specify which external variable they want to +// store the results of the command line argument processing into, if they don't +// want to store it in the option itself. +// +template +struct LocationClass { + Ty &Loc; + LocationClass(Ty &L) : Loc(L) {} + + template + void apply(Opt &O) const { O.setLocation(O, Loc); } +}; + +template +LocationClass location(Ty &L) { return LocationClass(L); } + + +//===----------------------------------------------------------------------===// +// Enum valued command line option +// +#define clEnumVal(ENUMVAL, DESC) #ENUMVAL, int(ENUMVAL), DESC +#define clEnumValN(ENUMVAL, FLAGNAME, DESC) FLAGNAME, int(ENUMVAL), DESC +#define clEnumValEnd (reinterpret_cast(0)) + +// values - For custom data types, allow specifying a group of values together +// as the values that go into the mapping that the option handler uses. Note +// that the values list must always have a 0 at the end of the list to indicate +// that the list has ended. +// +template +class ValuesClass { + // Use a vector instead of a map, because the lists should be short, + // the overhead is less, and most importantly, it keeps them in the order + // inserted so we can print our option out nicely. + SmallVector >,4> Values; + void processValues(va_list Vals); +public: + ValuesClass(const char *EnumName, DataType Val, const char *Desc, + va_list ValueArgs) { + // Insert the first value, which is required. + Values.push_back(std::make_pair(EnumName, std::make_pair(Val, Desc))); + + // Process the varargs portion of the values... + while (const char *enumName = va_arg(ValueArgs, const char *)) { + DataType EnumVal = static_cast(va_arg(ValueArgs, int)); + const char *EnumDesc = va_arg(ValueArgs, const char *); + Values.push_back(std::make_pair(enumName, // Add value to value map + std::make_pair(EnumVal, EnumDesc))); + } + } + + template + void apply(Opt &O) const { + for (unsigned i = 0, e = static_cast(Values.size()); + i != e; ++i) + O.getParser().addLiteralOption(Values[i].first, Values[i].second.first, + Values[i].second.second); + } +}; + +template +ValuesClass END_WITH_NULL values(const char *Arg, DataType Val, + const char *Desc, ...) { + va_list ValueArgs; + va_start(ValueArgs, Desc); + ValuesClass Vals(Arg, Val, Desc, ValueArgs); + va_end(ValueArgs); + return Vals; +} + + +//===----------------------------------------------------------------------===// +// parser class - Parameterizable parser for different data types. By default, +// known data types (string, int, bool) have specialized parsers, that do what +// you would expect. The default parser, used for data types that are not +// built-in, uses a mapping table to map specific options to values, which is +// used, among other things, to handle enum types. + +//-------------------------------------------------- +// generic_parser_base - This class holds all the non-generic code that we do +// not need replicated for every instance of the generic parser. This also +// allows us to put stuff into CommandLine.cpp +// +struct generic_parser_base { + virtual ~generic_parser_base() {} // Base class should have virtual-dtor + + // getNumOptions - Virtual function implemented by generic subclass to + // indicate how many entries are in Values. + // + virtual unsigned getNumOptions() const = 0; + + // getOption - Return option name N. + virtual const char *getOption(unsigned N) const = 0; + + // getDescription - Return description N + virtual const char *getDescription(unsigned N) const = 0; + + // Return the width of the option tag for printing... + virtual size_t getOptionWidth(const Option &O) const; + + // printOptionInfo - Print out information about this option. The + // to-be-maintained width is specified. + // + virtual void printOptionInfo(const Option &O, size_t GlobalWidth) const; + + void initialize(Option &O) { + // All of the modifiers for the option have been processed by now, so the + // argstr field should be stable, copy it down now. + // + hasArgStr = O.hasArgStr(); + } + + void getExtraOptionNames(SmallVectorImpl &OptionNames) { + // If there has been no argstr specified, that means that we need to add an + // argument for every possible option. This ensures that our options are + // vectored to us. + if (!hasArgStr) + for (unsigned i = 0, e = getNumOptions(); i != e; ++i) + OptionNames.push_back(getOption(i)); + } + + + enum ValueExpected getValueExpectedFlagDefault() const { + // If there is an ArgStr specified, then we are of the form: + // + // -opt=O2 or -opt O2 or -optO2 + // + // In which case, the value is required. Otherwise if an arg str has not + // been specified, we are of the form: + // + // -O2 or O2 or -la (where -l and -a are separate options) + // + // If this is the case, we cannot allow a value. + // + if (hasArgStr) + return ValueRequired; + else + return ValueDisallowed; + } + + // findOption - Return the option number corresponding to the specified + // argument string. If the option is not found, getNumOptions() is returned. + // + unsigned findOption(const char *Name); + +protected: + bool hasArgStr; +}; + +// Default parser implementation - This implementation depends on having a +// mapping of recognized options to values of some sort. In addition to this, +// each entry in the mapping also tracks a help message that is printed with the +// command line option for --help. Because this is a simple mapping parser, the +// data type can be any unsupported type. +// +template +class parser : public generic_parser_base { +protected: + SmallVector >, 8> Values; +public: + typedef DataType parser_data_type; + + // Implement virtual functions needed by generic_parser_base + unsigned getNumOptions() const { return unsigned(Values.size()); } + const char *getOption(unsigned N) const { return Values[N].first; } + const char *getDescription(unsigned N) const { + return Values[N].second.second; + } + + // parse - Return true on error. + bool parse(Option &O, StringRef ArgName, StringRef Arg, DataType &V) { + StringRef ArgVal; + if (hasArgStr) + ArgVal = Arg; + else + ArgVal = ArgName; + + for (unsigned i = 0, e = static_cast(Values.size()); + i != e; ++i) + if (Values[i].first == ArgVal) { + V = Values[i].second.first; + return false; + } + + return O.error("Cannot find option named '" + ArgVal + "'!"); + } + + /// addLiteralOption - Add an entry to the mapping table. + /// + template + void addLiteralOption(const char *Name, const DT &V, const char *HelpStr) { + assert(findOption(Name) == Values.size() && "Option already exists!"); + Values.push_back(std::make_pair(Name, + std::make_pair(static_cast(V),HelpStr))); + MarkOptionsChanged(); + } + + /// removeLiteralOption - Remove the specified option. + /// + void removeLiteralOption(const char *Name) { + unsigned N = findOption(Name); + assert(N != Values.size() && "Option not found!"); + Values.erase(Values.begin()+N); + } +}; + +//-------------------------------------------------- +// basic_parser - Super class of parsers to provide boilerplate code +// +class basic_parser_impl { // non-template implementation of basic_parser +public: + virtual ~basic_parser_impl() {} + + enum ValueExpected getValueExpectedFlagDefault() const { + return ValueRequired; + } + + void getExtraOptionNames(SmallVectorImpl &) {} + + void initialize(Option &) {} + + // Return the width of the option tag for printing... + size_t getOptionWidth(const Option &O) const; + + // printOptionInfo - Print out information about this option. The + // to-be-maintained width is specified. + // + void printOptionInfo(const Option &O, size_t GlobalWidth) const; + + // getValueName - Overload in subclass to provide a better default value. + virtual const char *getValueName() const { return "value"; } + + // An out-of-line virtual method to provide a 'home' for this class. + virtual void anchor(); +}; + +// basic_parser - The real basic parser is just a template wrapper that provides +// a typedef for the provided data type. +// +template +class basic_parser : public basic_parser_impl { +public: + typedef DataType parser_data_type; +}; + +//-------------------------------------------------- +// parser +// +template<> +class parser : public basic_parser { + const char *ArgStr; +public: + + // parse - Return true on error. + bool parse(Option &O, StringRef ArgName, StringRef Arg, bool &Val); + + template + void initialize(Opt &O) { + ArgStr = O.ArgStr; + } + + enum ValueExpected getValueExpectedFlagDefault() const { + return ValueOptional; + } + + // getValueName - Do not print = at all. + virtual const char *getValueName() const { return 0; } + + // An out-of-line virtual method to provide a 'home' for this class. + virtual void anchor(); +}; + +EXTERN_TEMPLATE_INSTANTIATION(class basic_parser); + +//-------------------------------------------------- +// parser +enum boolOrDefault { BOU_UNSET, BOU_TRUE, BOU_FALSE }; +template<> +class parser : public basic_parser { +public: + // parse - Return true on error. + bool parse(Option &O, StringRef ArgName, StringRef Arg, boolOrDefault &Val); + + enum ValueExpected getValueExpectedFlagDefault() const { + return ValueOptional; + } + + // getValueName - Do not print = at all. + virtual const char *getValueName() const { return 0; } + + // An out-of-line virtual method to provide a 'home' for this class. + virtual void anchor(); +}; + +EXTERN_TEMPLATE_INSTANTIATION(class basic_parser); + +//-------------------------------------------------- +// parser +// +template<> +class parser : public basic_parser { +public: + // parse - Return true on error. + bool parse(Option &O, StringRef ArgName, StringRef Arg, int &Val); + + // getValueName - Overload in subclass to provide a better default value. + virtual const char *getValueName() const { return "int"; } + + // An out-of-line virtual method to provide a 'home' for this class. + virtual void anchor(); +}; + +EXTERN_TEMPLATE_INSTANTIATION(class basic_parser); + + +//-------------------------------------------------- +// parser +// +template<> +class parser : public basic_parser { +public: + // parse - Return true on error. + bool parse(Option &O, StringRef ArgName, StringRef Arg, unsigned &Val); + + // getValueName - Overload in subclass to provide a better default value. + virtual const char *getValueName() const { return "uint"; } + + // An out-of-line virtual method to provide a 'home' for this class. + virtual void anchor(); +}; + +EXTERN_TEMPLATE_INSTANTIATION(class basic_parser); + +//-------------------------------------------------- +// parser +// +template<> +class parser : public basic_parser { +public: + // parse - Return true on error. + bool parse(Option &O, StringRef ArgName, StringRef Arg, double &Val); + + // getValueName - Overload in subclass to provide a better default value. + virtual const char *getValueName() const { return "number"; } + + // An out-of-line virtual method to provide a 'home' for this class. + virtual void anchor(); +}; + +EXTERN_TEMPLATE_INSTANTIATION(class basic_parser); + +//-------------------------------------------------- +// parser +// +template<> +class parser : public basic_parser { +public: + // parse - Return true on error. + bool parse(Option &O, StringRef ArgName, StringRef Arg, float &Val); + + // getValueName - Overload in subclass to provide a better default value. + virtual const char *getValueName() const { return "number"; } + + // An out-of-line virtual method to provide a 'home' for this class. + virtual void anchor(); +}; + +EXTERN_TEMPLATE_INSTANTIATION(class basic_parser); + +//-------------------------------------------------- +// parser +// +template<> +class parser : public basic_parser { +public: + // parse - Return true on error. + bool parse(Option &, StringRef, StringRef Arg, std::string &Value) { + Value = Arg.str(); + return false; + } + + // getValueName - Overload in subclass to provide a better default value. + virtual const char *getValueName() const { return "string"; } + + // An out-of-line virtual method to provide a 'home' for this class. + virtual void anchor(); +}; + +EXTERN_TEMPLATE_INSTANTIATION(class basic_parser); + +//-------------------------------------------------- +// parser +// +template<> +class parser : public basic_parser { +public: + // parse - Return true on error. + bool parse(Option &, StringRef, StringRef Arg, char &Value) { + Value = Arg[0]; + return false; + } + + // getValueName - Overload in subclass to provide a better default value. + virtual const char *getValueName() const { return "char"; } + + // An out-of-line virtual method to provide a 'home' for this class. + virtual void anchor(); +}; + +EXTERN_TEMPLATE_INSTANTIATION(class basic_parser); + +//===----------------------------------------------------------------------===// +// applicator class - This class is used because we must use partial +// specialization to handle literal string arguments specially (const char* does +// not correctly respond to the apply method). Because the syntax to use this +// is a pain, we have the 'apply' method below to handle the nastiness... +// +template struct applicator { + template + static void opt(const Mod &M, Opt &O) { M.apply(O); } +}; + +// Handle const char* as a special case... +template struct applicator { + template + static void opt(const char *Str, Opt &O) { O.setArgStr(Str); } +}; +template struct applicator { + template + static void opt(const char *Str, Opt &O) { O.setArgStr(Str); } +}; +template<> struct applicator { + template + static void opt(const char *Str, Opt &O) { O.setArgStr(Str); } +}; + +template<> struct applicator { + static void opt(NumOccurrencesFlag NO, Option &O) { + O.setNumOccurrencesFlag(NO); + } +}; +template<> struct applicator { + static void opt(ValueExpected VE, Option &O) { O.setValueExpectedFlag(VE); } +}; +template<> struct applicator { + static void opt(OptionHidden OH, Option &O) { O.setHiddenFlag(OH); } +}; +template<> struct applicator { + static void opt(FormattingFlags FF, Option &O) { O.setFormattingFlag(FF); } +}; +template<> struct applicator { + static void opt(MiscFlags MF, Option &O) { O.setMiscFlag(MF); } +}; + +// apply method - Apply a modifier to an option in a type safe way. +template +void apply(const Mod &M, Opt *O) { + applicator::opt(M, *O); +} + + +//===----------------------------------------------------------------------===// +// opt_storage class + +// Default storage class definition: external storage. This implementation +// assumes the user will specify a variable to store the data into with the +// cl::location(x) modifier. +// +template +class opt_storage { + DataType *Location; // Where to store the object... + + void check() const { + assert(Location != 0 && "cl::location(...) not specified for a command " + "line option with external storage, " + "or cl::init specified before cl::location()!!"); + } +public: + opt_storage() : Location(0) {} + + bool setLocation(Option &O, DataType &L) { + if (Location) + return O.error("cl::location(x) specified more than once!"); + Location = &L; + return false; + } + + template + void setValue(const T &V) { + check(); + *Location = V; + } + + DataType &getValue() { check(); return *Location; } + const DataType &getValue() const { check(); return *Location; } + + operator DataType() const { return this->getValue(); } +}; + + +// Define how to hold a class type object, such as a string. Since we can +// inherit from a class, we do so. This makes us exactly compatible with the +// object in all cases that it is used. +// +template +class opt_storage : public DataType { +public: + template + void setValue(const T &V) { DataType::operator=(V); } + + DataType &getValue() { return *this; } + const DataType &getValue() const { return *this; } +}; + +// Define a partial specialization to handle things we cannot inherit from. In +// this case, we store an instance through containment, and overload operators +// to get at the value. +// +template +class opt_storage { +public: + DataType Value; + + // Make sure we initialize the value with the default constructor for the + // type. + opt_storage() : Value(DataType()) {} + + template + void setValue(const T &V) { Value = V; } + DataType &getValue() { return Value; } + DataType getValue() const { return Value; } + + operator DataType() const { return getValue(); } + + // If the datatype is a pointer, support -> on it. + DataType operator->() const { return Value; } +}; + + +//===----------------------------------------------------------------------===// +// opt - A scalar command line option. +// +template > +class opt : public Option, + public opt_storage::value> { + ParserClass Parser; + + virtual bool handleOccurrence(unsigned pos, StringRef ArgName, + StringRef Arg) { + typename ParserClass::parser_data_type Val = + typename ParserClass::parser_data_type(); + if (Parser.parse(*this, ArgName, Arg, Val)) + return true; // Parse error! + this->setValue(Val); + this->setPosition(pos); + return false; + } + + virtual enum ValueExpected getValueExpectedFlagDefault() const { + return Parser.getValueExpectedFlagDefault(); + } + virtual void getExtraOptionNames(SmallVectorImpl &OptionNames) { + return Parser.getExtraOptionNames(OptionNames); + } + + // Forward printing stuff to the parser... + virtual size_t getOptionWidth() const {return Parser.getOptionWidth(*this);} + virtual void printOptionInfo(size_t GlobalWidth) const { + Parser.printOptionInfo(*this, GlobalWidth); + } + + void done() { + addArgument(); + Parser.initialize(*this); + } +public: + // setInitialValue - Used by the cl::init modifier... + void setInitialValue(const DataType &V) { this->setValue(V); } + + ParserClass &getParser() { return Parser; } + + template + DataType &operator=(const T &Val) { + this->setValue(Val); + return this->getValue(); + } + + // One option... + template + explicit opt(const M0t &M0) : Option(Optional | NotHidden) { + apply(M0, this); + done(); + } + + // Two options... + template + opt(const M0t &M0, const M1t &M1) : Option(Optional | NotHidden) { + apply(M0, this); apply(M1, this); + done(); + } + + // Three options... + template + opt(const M0t &M0, const M1t &M1, + const M2t &M2) : Option(Optional | NotHidden) { + apply(M0, this); apply(M1, this); apply(M2, this); + done(); + } + // Four options... + template + opt(const M0t &M0, const M1t &M1, const M2t &M2, + const M3t &M3) : Option(Optional | NotHidden) { + apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); + done(); + } + // Five options... + template + opt(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, + const M4t &M4) : Option(Optional | NotHidden) { + apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); + apply(M4, this); + done(); + } + // Six options... + template + opt(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, + const M4t &M4, const M5t &M5) : Option(Optional | NotHidden) { + apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); + apply(M4, this); apply(M5, this); + done(); + } + // Seven options... + template + opt(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, + const M4t &M4, const M5t &M5, + const M6t &M6) : Option(Optional | NotHidden) { + apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); + apply(M4, this); apply(M5, this); apply(M6, this); + done(); + } + // Eight options... + template + opt(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, + const M4t &M4, const M5t &M5, const M6t &M6, + const M7t &M7) : Option(Optional | NotHidden) { + apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); + apply(M4, this); apply(M5, this); apply(M6, this); apply(M7, this); + done(); + } +}; + +EXTERN_TEMPLATE_INSTANTIATION(class opt); +EXTERN_TEMPLATE_INSTANTIATION(class opt); +EXTERN_TEMPLATE_INSTANTIATION(class opt); +EXTERN_TEMPLATE_INSTANTIATION(class opt); +EXTERN_TEMPLATE_INSTANTIATION(class opt); + +//===----------------------------------------------------------------------===// +// list_storage class + +// Default storage class definition: external storage. This implementation +// assumes the user will specify a variable to store the data into with the +// cl::location(x) modifier. +// +template +class list_storage { + StorageClass *Location; // Where to store the object... + +public: + list_storage() : Location(0) {} + + bool setLocation(Option &O, StorageClass &L) { + if (Location) + return O.error("cl::location(x) specified more than once!"); + Location = &L; + return false; + } + + template + void addValue(const T &V) { + assert(Location != 0 && "cl::location(...) not specified for a command " + "line option with external storage!"); + Location->push_back(V); + } +}; + + +// Define how to hold a class type object, such as a string. Since we can +// inherit from a class, we do so. This makes us exactly compatible with the +// object in all cases that it is used. +// +template +class list_storage : public std::vector { +public: + template + void addValue(const T &V) { push_back(V); } +}; + + +//===----------------------------------------------------------------------===// +// list - A list of command line options. +// +template > +class list : public Option, public list_storage { + std::vector Positions; + ParserClass Parser; + + virtual enum ValueExpected getValueExpectedFlagDefault() const { + return Parser.getValueExpectedFlagDefault(); + } + virtual void getExtraOptionNames(SmallVectorImpl &OptionNames) { + return Parser.getExtraOptionNames(OptionNames); + } + + virtual bool handleOccurrence(unsigned pos, StringRef ArgName, StringRef Arg){ + typename ParserClass::parser_data_type Val = + typename ParserClass::parser_data_type(); + if (Parser.parse(*this, ArgName, Arg, Val)) + return true; // Parse Error! + addValue(Val); + setPosition(pos); + Positions.push_back(pos); + return false; + } + + // Forward printing stuff to the parser... + virtual size_t getOptionWidth() const {return Parser.getOptionWidth(*this);} + virtual void printOptionInfo(size_t GlobalWidth) const { + Parser.printOptionInfo(*this, GlobalWidth); + } + + void done() { + addArgument(); + Parser.initialize(*this); + } +public: + ParserClass &getParser() { return Parser; } + + unsigned getPosition(unsigned optnum) const { + assert(optnum < this->size() && "Invalid option index"); + return Positions[optnum]; + } + + void setNumAdditionalVals(unsigned n) { + Option::setNumAdditionalVals(n); + } + + // One option... + template + explicit list(const M0t &M0) : Option(ZeroOrMore | NotHidden) { + apply(M0, this); + done(); + } + // Two options... + template + list(const M0t &M0, const M1t &M1) : Option(ZeroOrMore | NotHidden) { + apply(M0, this); apply(M1, this); + done(); + } + // Three options... + template + list(const M0t &M0, const M1t &M1, const M2t &M2) + : Option(ZeroOrMore | NotHidden) { + apply(M0, this); apply(M1, this); apply(M2, this); + done(); + } + // Four options... + template + list(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3) + : Option(ZeroOrMore | NotHidden) { + apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); + done(); + } + // Five options... + template + list(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, + const M4t &M4) : Option(ZeroOrMore | NotHidden) { + apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); + apply(M4, this); + done(); + } + // Six options... + template + list(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, + const M4t &M4, const M5t &M5) : Option(ZeroOrMore | NotHidden) { + apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); + apply(M4, this); apply(M5, this); + done(); + } + // Seven options... + template + list(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, + const M4t &M4, const M5t &M5, const M6t &M6) + : Option(ZeroOrMore | NotHidden) { + apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); + apply(M4, this); apply(M5, this); apply(M6, this); + done(); + } + // Eight options... + template + list(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, + const M4t &M4, const M5t &M5, const M6t &M6, + const M7t &M7) : Option(ZeroOrMore | NotHidden) { + apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); + apply(M4, this); apply(M5, this); apply(M6, this); apply(M7, this); + done(); + } +}; + +// multi_val - Modifier to set the number of additional values. +struct multi_val { + unsigned AdditionalVals; + explicit multi_val(unsigned N) : AdditionalVals(N) {} + + template + void apply(list &L) const { L.setNumAdditionalVals(AdditionalVals); } +}; + + +//===----------------------------------------------------------------------===// +// bits_storage class + +// Default storage class definition: external storage. This implementation +// assumes the user will specify a variable to store the data into with the +// cl::location(x) modifier. +// +template +class bits_storage { + unsigned *Location; // Where to store the bits... + + template + static unsigned Bit(const T &V) { + unsigned BitPos = reinterpret_cast(V); + assert(BitPos < sizeof(unsigned) * CHAR_BIT && + "enum exceeds width of bit vector!"); + return 1 << BitPos; + } + +public: + bits_storage() : Location(0) {} + + bool setLocation(Option &O, unsigned &L) { + if (Location) + return O.error("cl::location(x) specified more than once!"); + Location = &L; + return false; + } + + template + void addValue(const T &V) { + assert(Location != 0 && "cl::location(...) not specified for a command " + "line option with external storage!"); + *Location |= Bit(V); + } + + unsigned getBits() { return *Location; } + + template + bool isSet(const T &V) { + return (*Location & Bit(V)) != 0; + } +}; + + +// Define how to hold bits. Since we can inherit from a class, we do so. +// This makes us exactly compatible with the bits in all cases that it is used. +// +template +class bits_storage { + unsigned Bits; // Where to store the bits... + + template + static unsigned Bit(const T &V) { + unsigned BitPos = reinterpret_cast(V); + assert(BitPos < sizeof(unsigned) * CHAR_BIT && + "enum exceeds width of bit vector!"); + return 1 << BitPos; + } + +public: + template + void addValue(const T &V) { + Bits |= Bit(V); + } + + unsigned getBits() { return Bits; } + + template + bool isSet(const T &V) { + return (Bits & Bit(V)) != 0; + } +}; + + +//===----------------------------------------------------------------------===// +// bits - A bit vector of command options. +// +template > +class bits : public Option, public bits_storage { + std::vector Positions; + ParserClass Parser; + + virtual enum ValueExpected getValueExpectedFlagDefault() const { + return Parser.getValueExpectedFlagDefault(); + } + virtual void getExtraOptionNames(SmallVectorImpl &OptionNames) { + return Parser.getExtraOptionNames(OptionNames); + } + + virtual bool handleOccurrence(unsigned pos, StringRef ArgName, StringRef Arg){ + typename ParserClass::parser_data_type Val = + typename ParserClass::parser_data_type(); + if (Parser.parse(*this, ArgName, Arg, Val)) + return true; // Parse Error! + addValue(Val); + setPosition(pos); + Positions.push_back(pos); + return false; + } + + // Forward printing stuff to the parser... + virtual size_t getOptionWidth() const {return Parser.getOptionWidth(*this);} + virtual void printOptionInfo(size_t GlobalWidth) const { + Parser.printOptionInfo(*this, GlobalWidth); + } + + void done() { + addArgument(); + Parser.initialize(*this); + } +public: + ParserClass &getParser() { return Parser; } + + unsigned getPosition(unsigned optnum) const { + assert(optnum < this->size() && "Invalid option index"); + return Positions[optnum]; + } + + // One option... + template + explicit bits(const M0t &M0) : Option(ZeroOrMore | NotHidden) { + apply(M0, this); + done(); + } + // Two options... + template + bits(const M0t &M0, const M1t &M1) : Option(ZeroOrMore | NotHidden) { + apply(M0, this); apply(M1, this); + done(); + } + // Three options... + template + bits(const M0t &M0, const M1t &M1, const M2t &M2) + : Option(ZeroOrMore | NotHidden) { + apply(M0, this); apply(M1, this); apply(M2, this); + done(); + } + // Four options... + template + bits(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3) + : Option(ZeroOrMore | NotHidden) { + apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); + done(); + } + // Five options... + template + bits(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, + const M4t &M4) : Option(ZeroOrMore | NotHidden) { + apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); + apply(M4, this); + done(); + } + // Six options... + template + bits(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, + const M4t &M4, const M5t &M5) : Option(ZeroOrMore | NotHidden) { + apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); + apply(M4, this); apply(M5, this); + done(); + } + // Seven options... + template + bits(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, + const M4t &M4, const M5t &M5, const M6t &M6) + : Option(ZeroOrMore | NotHidden) { + apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); + apply(M4, this); apply(M5, this); apply(M6, this); + done(); + } + // Eight options... + template + bits(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, + const M4t &M4, const M5t &M5, const M6t &M6, + const M7t &M7) : Option(ZeroOrMore | NotHidden) { + apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); + apply(M4, this); apply(M5, this); apply(M6, this); apply(M7, this); + done(); + } +}; + +//===----------------------------------------------------------------------===// +// Aliased command line option (alias this name to a preexisting name) +// + +class alias : public Option { + Option *AliasFor; + virtual bool handleOccurrence(unsigned pos, StringRef /*ArgName*/, + StringRef Arg) { + return AliasFor->handleOccurrence(pos, AliasFor->ArgStr, Arg); + } + // Handle printing stuff... + virtual size_t getOptionWidth() const; + virtual void printOptionInfo(size_t GlobalWidth) const; + + void done() { + if (!hasArgStr()) + error("cl::alias must have argument name specified!"); + if (AliasFor == 0) + error("cl::alias must have an cl::aliasopt(option) specified!"); + addArgument(); + } +public: + void setAliasFor(Option &O) { + if (AliasFor) + error("cl::alias must only have one cl::aliasopt(...) specified!"); + AliasFor = &O; + } + + // One option... + template + explicit alias(const M0t &M0) : Option(Optional | Hidden), AliasFor(0) { + apply(M0, this); + done(); + } + // Two options... + template + alias(const M0t &M0, const M1t &M1) : Option(Optional | Hidden), AliasFor(0) { + apply(M0, this); apply(M1, this); + done(); + } + // Three options... + template + alias(const M0t &M0, const M1t &M1, const M2t &M2) + : Option(Optional | Hidden), AliasFor(0) { + apply(M0, this); apply(M1, this); apply(M2, this); + done(); + } + // Four options... + template + alias(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3) + : Option(Optional | Hidden), AliasFor(0) { + apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); + done(); + } +}; + +// aliasfor - Modifier to set the option an alias aliases. +struct aliasopt { + Option &Opt; + explicit aliasopt(Option &O) : Opt(O) {} + void apply(alias &A) const { A.setAliasFor(Opt); } +}; + +// extrahelp - provide additional help at the end of the normal help +// output. All occurrences of cl::extrahelp will be accumulated and +// printed to stderr at the end of the regular help, just before +// exit is called. +struct extrahelp { + const char * morehelp; + explicit extrahelp(const char* help); +}; + +void PrintVersionMessage(); +// This function just prints the help message, exactly the same way as if the +// --help option had been given on the command line. +// NOTE: THIS FUNCTION TERMINATES THE PROGRAM! +void PrintHelpMessage(); + +} // End namespace cl + +} // End namespace llvm + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Support/Compiler.h b/libclamav/c++/llvm/include/llvm/Support/Compiler.h new file mode 100644 index 000000000..da31f9862 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Support/Compiler.h @@ -0,0 +1,81 @@ +//===-- llvm/Support/Compiler.h - Compiler abstraction support --*- 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 several macros, based on the current compiler. This allows +// use of compiler-specific features in a way that remains portable. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_COMPILER_H +#define LLVM_SUPPORT_COMPILER_H + +// The VISIBILITY_HIDDEN macro, used for marking classes with the GCC-specific +// visibility("hidden") attribute. +#if (__GNUC__ >= 4) && !defined(__MINGW32__) && !defined(__CYGWIN__) +#define VISIBILITY_HIDDEN __attribute__ ((visibility("hidden"))) +#else +#define VISIBILITY_HIDDEN +#endif + +#if (__GNUC__ >= 4 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)) +#define ATTRIBUTE_USED __attribute__((__used__)) +#else +#define ATTRIBUTE_USED +#endif + +#ifdef __GNUC__ // aka 'ATTRIBUTE_CONST' but following LLVM Conventions. +#define ATTRIBUTE_READNONE __attribute__((__const__)) +#else +#define ATTRIBUTE_READNONE +#endif + +#ifdef __GNUC__ // aka 'ATTRIBUTE_PURE' but following LLVM Conventions. +#define ATTRIBUTE_READONLY __attribute__((__pure__)) +#else +#define ATTRIBUTE_READONLY +#endif + +#if (__GNUC__ >= 4) +#define BUILTIN_EXPECT(EXPR, VALUE) __builtin_expect((EXPR), (VALUE)) +#else +#define BUILTIN_EXPECT(EXPR, VALUE) (EXPR) +#endif + +// C++ doesn't support 'extern template' of template specializations. GCC does, +// but requires __extension__ before it. In the header, use this: +// EXTERN_TEMPLATE_INSTANTIATION(class foo); +// in the .cpp file, use this: +// TEMPLATE_INSTANTIATION(class foo); +#ifdef __GNUC__ +#define EXTERN_TEMPLATE_INSTANTIATION(X) __extension__ extern template X +#define TEMPLATE_INSTANTIATION(X) template X +#else +#define EXTERN_TEMPLATE_INSTANTIATION(X) +#define TEMPLATE_INSTANTIATION(X) +#endif + +// DISABLE_INLINE - On compilers where we have a directive to do so, mark a +// method "not for inlining". +#if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)) +#define DISABLE_INLINE __attribute__((noinline)) +#elif defined(_MSC_VER) +#define DISABLE_INLINE __declspec(noinline) +#else +#define DISABLE_INLINE +#endif + +#ifdef __GNUC__ +#define NORETURN __attribute__((noreturn)) +#elif defined(_MSC_VER) +#define NORETURN __declspec(noreturn) +#else +#define NORETURN +#endif + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Support/ConstantFolder.h b/libclamav/c++/llvm/include/llvm/Support/ConstantFolder.h new file mode 100644 index 000000000..b73cea04a --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Support/ConstantFolder.h @@ -0,0 +1,228 @@ +//===-- llvm/Support/ConstantFolder.h - Constant folding helper -*- 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 the ConstantFolder class, a helper for IRBuilder. +// It provides IRBuilder with a set of methods for creating constants +// with minimal folding. For general constant creation and folding, +// use ConstantExpr and the routines in llvm/Analysis/ConstantFolding.h. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_CONSTANTFOLDER_H +#define LLVM_SUPPORT_CONSTANTFOLDER_H + +#include "llvm/Constants.h" +#include "llvm/InstrTypes.h" + +namespace llvm { + +class LLVMContext; + +/// ConstantFolder - Create constants with minimum, target independent, folding. +class ConstantFolder { +public: + explicit ConstantFolder(LLVMContext &) {} + + //===--------------------------------------------------------------------===// + // Binary Operators + //===--------------------------------------------------------------------===// + + Constant *CreateAdd(Constant *LHS, Constant *RHS) const { + return ConstantExpr::getAdd(LHS, RHS); + } + Constant *CreateNSWAdd(Constant *LHS, Constant *RHS) const { + return ConstantExpr::getNSWAdd(LHS, RHS); + } + Constant *CreateFAdd(Constant *LHS, Constant *RHS) const { + return ConstantExpr::getFAdd(LHS, RHS); + } + Constant *CreateSub(Constant *LHS, Constant *RHS) const { + return ConstantExpr::getSub(LHS, RHS); + } + Constant *CreateNSWSub(Constant *LHS, Constant *RHS) const { + return ConstantExpr::getNSWSub(LHS, RHS); + } + Constant *CreateFSub(Constant *LHS, Constant *RHS) const { + return ConstantExpr::getFSub(LHS, RHS); + } + Constant *CreateMul(Constant *LHS, Constant *RHS) const { + return ConstantExpr::getMul(LHS, RHS); + } + Constant *CreateFMul(Constant *LHS, Constant *RHS) const { + return ConstantExpr::getFMul(LHS, RHS); + } + Constant *CreateUDiv(Constant *LHS, Constant *RHS) const { + return ConstantExpr::getUDiv(LHS, RHS); + } + Constant *CreateSDiv(Constant *LHS, Constant *RHS) const { + return ConstantExpr::getSDiv(LHS, RHS); + } + Constant *CreateExactSDiv(Constant *LHS, Constant *RHS) const { + return ConstantExpr::getExactSDiv(LHS, RHS); + } + Constant *CreateFDiv(Constant *LHS, Constant *RHS) const { + return ConstantExpr::getFDiv(LHS, RHS); + } + Constant *CreateURem(Constant *LHS, Constant *RHS) const { + return ConstantExpr::getURem(LHS, RHS); + } + Constant *CreateSRem(Constant *LHS, Constant *RHS) const { + return ConstantExpr::getSRem(LHS, RHS); + } + Constant *CreateFRem(Constant *LHS, Constant *RHS) const { + return ConstantExpr::getFRem(LHS, RHS); + } + Constant *CreateShl(Constant *LHS, Constant *RHS) const { + return ConstantExpr::getShl(LHS, RHS); + } + Constant *CreateLShr(Constant *LHS, Constant *RHS) const { + return ConstantExpr::getLShr(LHS, RHS); + } + Constant *CreateAShr(Constant *LHS, Constant *RHS) const { + return ConstantExpr::getAShr(LHS, RHS); + } + Constant *CreateAnd(Constant *LHS, Constant *RHS) const { + return ConstantExpr::getAnd(LHS, RHS); + } + Constant *CreateOr(Constant *LHS, Constant *RHS) const { + return ConstantExpr::getOr(LHS, RHS); + } + Constant *CreateXor(Constant *LHS, Constant *RHS) const { + return ConstantExpr::getXor(LHS, RHS); + } + + Constant *CreateBinOp(Instruction::BinaryOps Opc, + Constant *LHS, Constant *RHS) const { + return ConstantExpr::get(Opc, LHS, RHS); + } + + //===--------------------------------------------------------------------===// + // Unary Operators + //===--------------------------------------------------------------------===// + + Constant *CreateNeg(Constant *C) const { + return ConstantExpr::getNeg(C); + } + Constant *CreateFNeg(Constant *C) const { + return ConstantExpr::getFNeg(C); + } + Constant *CreateNot(Constant *C) const { + return ConstantExpr::getNot(C); + } + + //===--------------------------------------------------------------------===// + // Memory Instructions + //===--------------------------------------------------------------------===// + + Constant *CreateGetElementPtr(Constant *C, Constant* const *IdxList, + unsigned NumIdx) const { + return ConstantExpr::getGetElementPtr(C, IdxList, NumIdx); + } + Constant *CreateGetElementPtr(Constant *C, Value* const *IdxList, + unsigned NumIdx) const { + return ConstantExpr::getGetElementPtr(C, IdxList, NumIdx); + } + + Constant *CreateInBoundsGetElementPtr(Constant *C, Constant* const *IdxList, + unsigned NumIdx) const { + return ConstantExpr::getInBoundsGetElementPtr(C, IdxList, NumIdx); + } + Constant *CreateInBoundsGetElementPtr(Constant *C, Value* const *IdxList, + unsigned NumIdx) const { + return ConstantExpr::getInBoundsGetElementPtr(C, IdxList, NumIdx); + } + + //===--------------------------------------------------------------------===// + // Cast/Conversion Operators + //===--------------------------------------------------------------------===// + + Constant *CreateCast(Instruction::CastOps Op, Constant *C, + const Type *DestTy) const { + return ConstantExpr::getCast(Op, C, DestTy); + } + Constant *CreatePointerCast(Constant *C, const Type *DestTy) const { + return ConstantExpr::getPointerCast(C, DestTy); + } + Constant *CreateIntCast(Constant *C, const Type *DestTy, + bool isSigned) const { + return ConstantExpr::getIntegerCast(C, DestTy, isSigned); + } + Constant *CreateFPCast(Constant *C, const Type *DestTy) const { + return ConstantExpr::getFPCast(C, DestTy); + } + + Constant *CreateBitCast(Constant *C, const Type *DestTy) const { + return CreateCast(Instruction::BitCast, C, DestTy); + } + Constant *CreateIntToPtr(Constant *C, const Type *DestTy) const { + return CreateCast(Instruction::IntToPtr, C, DestTy); + } + Constant *CreatePtrToInt(Constant *C, const Type *DestTy) const { + return CreateCast(Instruction::PtrToInt, C, DestTy); + } + Constant *CreateZExtOrBitCast(Constant *C, const Type *DestTy) const { + return ConstantExpr::getZExtOrBitCast(C, DestTy); + } + Constant *CreateSExtOrBitCast(Constant *C, const Type *DestTy) const { + return ConstantExpr::getSExtOrBitCast(C, DestTy); + } + + Constant *CreateTruncOrBitCast(Constant *C, const Type *DestTy) const { + return ConstantExpr::getTruncOrBitCast(C, DestTy); + } + + //===--------------------------------------------------------------------===// + // Compare Instructions + //===--------------------------------------------------------------------===// + + Constant *CreateICmp(CmpInst::Predicate P, Constant *LHS, + Constant *RHS) const { + return ConstantExpr::getCompare(P, LHS, RHS); + } + Constant *CreateFCmp(CmpInst::Predicate P, Constant *LHS, + Constant *RHS) const { + return ConstantExpr::getCompare(P, LHS, RHS); + } + + //===--------------------------------------------------------------------===// + // Other Instructions + //===--------------------------------------------------------------------===// + + Constant *CreateSelect(Constant *C, Constant *True, Constant *False) const { + return ConstantExpr::getSelect(C, True, False); + } + + Constant *CreateExtractElement(Constant *Vec, Constant *Idx) const { + return ConstantExpr::getExtractElement(Vec, Idx); + } + + Constant *CreateInsertElement(Constant *Vec, Constant *NewElt, + Constant *Idx) const { + return ConstantExpr::getInsertElement(Vec, NewElt, Idx); + } + + Constant *CreateShuffleVector(Constant *V1, Constant *V2, + Constant *Mask) const { + return ConstantExpr::getShuffleVector(V1, V2, Mask); + } + + Constant *CreateExtractValue(Constant *Agg, const unsigned *IdxList, + unsigned NumIdx) const { + return ConstantExpr::getExtractValue(Agg, IdxList, NumIdx); + } + + Constant *CreateInsertValue(Constant *Agg, Constant *Val, + const unsigned *IdxList, unsigned NumIdx) const { + return ConstantExpr::getInsertValue(Agg, Val, IdxList, NumIdx); + } +}; + +} + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Support/ConstantRange.h b/libclamav/c++/llvm/include/llvm/Support/ConstantRange.h new file mode 100644 index 000000000..6342c6f1b --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Support/ConstantRange.h @@ -0,0 +1,248 @@ +//===-- llvm/Support/ConstantRange.h - Represent a range --------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Represent a range of possible values that may occur when the program is run +// for an integral value. This keeps track of a lower and upper bound for the +// constant, which MAY wrap around the end of the numeric range. To do this, it +// keeps track of a [lower, upper) bound, which specifies an interval just like +// STL iterators. When used with boolean values, the following are important +// ranges: : +// +// [F, F) = {} = Empty set +// [T, F) = {T} +// [F, T) = {F} +// [T, T) = {F, T} = Full set +// +// The other integral ranges use min/max values for special range values. For +// example, for 8-bit types, it uses: +// [0, 0) = {} = Empty set +// [255, 255) = {0..255} = Full Set +// +// Note that ConstantRange can be used to represent either signed or +// unsigned ranges. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_CONSTANT_RANGE_H +#define LLVM_SUPPORT_CONSTANT_RANGE_H + +#include "llvm/ADT/APInt.h" +#include "llvm/System/DataTypes.h" + +namespace llvm { + +/// ConstantRange - This class represents an range of values. +/// +class ConstantRange { + APInt Lower, Upper; + static ConstantRange intersect1Wrapped(const ConstantRange &LHS, + const ConstantRange &RHS); + +public: + /// Initialize a full (the default) or empty set for the specified bit width. + /// + explicit ConstantRange(uint32_t BitWidth, bool isFullSet = true); + + /// Initialize a range to hold the single specified value. + /// + ConstantRange(const APInt &Value); + + /// @brief Initialize a range of values explicitly. This will assert out if + /// Lower==Upper and Lower != Min or Max value for its type. It will also + /// assert out if the two APInt's are not the same bit width. + ConstantRange(const APInt& Lower, const APInt& Upper); + + /// makeICmpRegion - Produce the smallest range that contains all values that + /// might satisfy the comparison specified by Pred when compared to any value + /// contained within Other. + /// + /// Solves for range X in 'for all x in X, there exists a y in Y such that + /// icmp op x, y is true'. Every value that might make the comparison true + /// is included in the resulting range. + static ConstantRange makeICmpRegion(unsigned Pred, + const ConstantRange &Other); + + /// getLower - Return the lower value for this range... + /// + const APInt &getLower() const { return Lower; } + + /// getUpper - Return the upper value for this range... + /// + const APInt &getUpper() const { return Upper; } + + /// getBitWidth - get the bit width of this ConstantRange + /// + uint32_t getBitWidth() const { return Lower.getBitWidth(); } + + /// isFullSet - Return true if this set contains all of the elements possible + /// for this data-type + /// + bool isFullSet() const; + + /// isEmptySet - Return true if this set contains no members. + /// + bool isEmptySet() const; + + /// isWrappedSet - Return true if this set wraps around the top of the range, + /// for example: [100, 8) + /// + bool isWrappedSet() const; + + /// contains - Return true if the specified value is in the set. + /// + bool contains(const APInt &Val) const; + + /// contains - Return true if the other range is a subset of this one. + /// + bool contains(const ConstantRange &CR) const; + + /// getSingleElement - If this set contains a single element, return it, + /// otherwise return null. + /// + const APInt *getSingleElement() const { + if (Upper == Lower + 1) + return &Lower; + return 0; + } + + /// isSingleElement - Return true if this set contains exactly one member. + /// + bool isSingleElement() const { return getSingleElement() != 0; } + + /// getSetSize - Return the number of elements in this set. + /// + APInt getSetSize() const; + + /// getUnsignedMax - Return the largest unsigned value contained in the + /// ConstantRange. + /// + APInt getUnsignedMax() const; + + /// getUnsignedMin - Return the smallest unsigned value contained in the + /// ConstantRange. + /// + APInt getUnsignedMin() const; + + /// getSignedMax - Return the largest signed value contained in the + /// ConstantRange. + /// + APInt getSignedMax() const; + + /// getSignedMin - Return the smallest signed value contained in the + /// ConstantRange. + /// + APInt getSignedMin() const; + + /// operator== - Return true if this range is equal to another range. + /// + bool operator==(const ConstantRange &CR) const { + return Lower == CR.Lower && Upper == CR.Upper; + } + bool operator!=(const ConstantRange &CR) const { + return !operator==(CR); + } + + /// subtract - Subtract the specified constant from the endpoints of this + /// constant range. + ConstantRange subtract(const APInt &CI) const; + + /// intersectWith - Return the range that results from the intersection of + /// this range with another range. The resultant range is guaranteed to + /// include all elements contained in both input ranges, and to have the + /// smallest possible set size that does so. Because there may be two + /// intersections with the same set size, A.intersectWith(B) might not + /// be equal to B.intersectWith(A). + /// + ConstantRange intersectWith(const ConstantRange &CR) const; + + /// unionWith - Return the range that results from the union of this range + /// with another range. The resultant range is guaranteed to include the + /// elements of both sets, but may contain more. For example, [3, 9) union + /// [12,15) is [3, 15), which includes 9, 10, and 11, which were not included + /// in either set before. + /// + ConstantRange unionWith(const ConstantRange &CR) const; + + /// zeroExtend - Return a new range in the specified integer type, which must + /// be strictly larger than the current type. The returned range will + /// correspond to the possible range of values if the source range had been + /// zero extended to BitWidth. + ConstantRange zeroExtend(uint32_t BitWidth) const; + + /// signExtend - Return a new range in the specified integer type, which must + /// be strictly larger than the current type. The returned range will + /// correspond to the possible range of values if the source range had been + /// sign extended to BitWidth. + ConstantRange signExtend(uint32_t BitWidth) const; + + /// truncate - Return a new range in the specified integer type, which must be + /// strictly smaller than the current type. The returned range will + /// correspond to the possible range of values if the source range had been + /// truncated to the specified type. + ConstantRange truncate(uint32_t BitWidth) const; + + /// zextOrTrunc - make this range have the bit width given by \p BitWidth. The + /// value is zero extended, truncated, or left alone to make it that width. + ConstantRange zextOrTrunc(uint32_t BitWidth) const; + + /// sextOrTrunc - make this range have the bit width given by \p BitWidth. The + /// value is sign extended, truncated, or left alone to make it that width. + ConstantRange sextOrTrunc(uint32_t BitWidth) const; + + /// add - Return a new range representing the possible values resulting + /// from an addition of a value in this range and a value in Other. + ConstantRange add(const ConstantRange &Other) const; + + /// multiply - Return a new range representing the possible values resulting + /// from a multiplication of a value in this range and a value in Other. + /// TODO: This isn't fully implemented yet. + ConstantRange multiply(const ConstantRange &Other) const; + + /// smax - Return a new range representing the possible values resulting + /// from a signed maximum of a value in this range and a value in Other. + ConstantRange smax(const ConstantRange &Other) const; + + /// umax - Return a new range representing the possible values resulting + /// from an unsigned maximum of a value in this range and a value in Other. + ConstantRange umax(const ConstantRange &Other) const; + + /// udiv - Return a new range representing the possible values resulting + /// from an unsigned division of a value in this range and a value in Other. + /// TODO: This isn't fully implemented yet. + ConstantRange udiv(const ConstantRange &Other) const; + + /// shl - Return a new range representing the possible values resulting + /// from a left shift of a value in this range by the Amount value. + ConstantRange shl(const ConstantRange &Amount) const; + + /// ashr - Return a new range representing the possible values resulting from + /// an arithmetic right shift of a value in this range by the Amount value. + ConstantRange ashr(const ConstantRange &Amount) const; + + /// shr - Return a new range representing the possible values resulting + /// from a logical right shift of a value in this range by the Amount value. + ConstantRange lshr(const ConstantRange &Amount) const; + + /// print - Print out the bounds to a stream... + /// + void print(raw_ostream &OS) const; + + /// dump - Allow printing from a debugger easily... + /// + void dump() const; +}; + +inline raw_ostream &operator<<(raw_ostream &OS, const ConstantRange &CR) { + CR.print(OS); + return OS; +} + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Support/DOTGraphTraits.h b/libclamav/c++/llvm/include/llvm/Support/DOTGraphTraits.h new file mode 100644 index 000000000..080297f82 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Support/DOTGraphTraits.h @@ -0,0 +1,142 @@ +//===-- llvm/Support/DotGraphTraits.h - Customize .dot output ---*- 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 a template class that can be used to customize dot output +// graphs generated by the GraphWriter.h file. The default implementation of +// this file will produce a simple, but not very polished graph. By +// specializing this template, lots of customization opportunities are possible. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_DOTGRAPHTRAITS_H +#define LLVM_SUPPORT_DOTGRAPHTRAITS_H + +#include + +namespace llvm { + +/// DefaultDOTGraphTraits - This class provides the default implementations of +/// all of the DOTGraphTraits methods. If a specialization does not need to +/// override all methods here it should inherit so that it can get the default +/// implementations. +/// +struct DefaultDOTGraphTraits { + /// getGraphName - Return the label for the graph as a whole. Printed at the + /// top of the graph. + /// + template + static std::string getGraphName(const GraphType& Graph) { return ""; } + + /// getGraphProperties - Return any custom properties that should be included + /// in the top level graph structure for dot. + /// + template + static std::string getGraphProperties(const GraphType& Graph) { + return ""; + } + + /// renderGraphFromBottomUp - If this function returns true, the graph is + /// emitted bottom-up instead of top-down. This requires graphviz 2.0 to work + /// though. + static bool renderGraphFromBottomUp() { + return false; + } + + /// getNodeLabel - Given a node and a pointer to the top level graph, return + /// the label to print in the node. + template + static std::string getNodeLabel(const void *Node, + const GraphType& Graph, bool ShortNames) { + return ""; + } + + /// hasNodeAddressLabel - If this method returns true, the address of the node + /// is added to the label of the node. + template + static bool hasNodeAddressLabel(const void *Node, const GraphType& Graph) { + return false; + } + + /// If you want to specify custom node attributes, this is the place to do so + /// + template + static std::string getNodeAttributes(const void *Node, + const GraphType& Graph) { + return ""; + } + + /// If you want to override the dot attributes printed for a particular edge, + /// override this method. + template + static std::string getEdgeAttributes(const void *Node, EdgeIter EI) { + return ""; + } + + /// getEdgeSourceLabel - If you want to label the edge source itself, + /// implement this method. + template + static std::string getEdgeSourceLabel(const void *Node, EdgeIter I) { + return ""; + } + + /// edgeTargetsEdgeSource - This method returns true if this outgoing edge + /// should actually target another edge source, not a node. If this method is + /// implemented, getEdgeTarget should be implemented. + template + static bool edgeTargetsEdgeSource(const void *Node, EdgeIter I) { + return false; + } + + /// getEdgeTarget - If edgeTargetsEdgeSource returns true, this method is + /// called to determine which outgoing edge of Node is the target of this + /// edge. + template + static EdgeIter getEdgeTarget(const void *Node, EdgeIter I) { + return I; + } + + /// hasEdgeDestLabels - If this function returns true, the graph is able + /// to provide labels for edge destinations. + static bool hasEdgeDestLabels() { + return false; + } + + /// numEdgeDestLabels - If hasEdgeDestLabels, this function returns the + /// number of incoming edge labels the given node has. + static unsigned numEdgeDestLabels(const void *Node) { + return 0; + } + + /// getEdgeDestLabel - If hasEdgeDestLabels, this function returns the + /// incoming edge label with the given index in the given node. + static std::string getEdgeDestLabel(const void *Node, unsigned i) { + return ""; + } + + /// addCustomGraphFeatures - If a graph is made up of more than just + /// straight-forward nodes and edges, this is the place to put all of the + /// custom stuff necessary. The GraphWriter object, instantiated with your + /// GraphType is passed in as an argument. You may call arbitrary methods on + /// it to add things to the output graph. + /// + template + static void addCustomGraphFeatures(const GraphType& Graph, GraphWriter &GW) {} +}; + + +/// DOTGraphTraits - Template class that can be specialized to customize how +/// graphs are converted to 'dot' graphs. When specializing, you may inherit +/// from DefaultDOTGraphTraits if you don't need to override everything. +/// +template +struct DOTGraphTraits : public DefaultDOTGraphTraits {}; + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Support/DataFlow.h b/libclamav/c++/llvm/include/llvm/Support/DataFlow.h new file mode 100644 index 000000000..8f79ead1c --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Support/DataFlow.h @@ -0,0 +1,103 @@ +//===-- llvm/Support/DataFlow.h - dataflow as graphs ------------*- 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 specializations of GraphTraits that allows Use-Def and +// Def-Use relations to be treated as proper graphs for generic algorithms. +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_DATAFLOW_H +#define LLVM_SUPPORT_DATAFLOW_H + +#include "llvm/User.h" +#include "llvm/ADT/GraphTraits.h" + +namespace llvm { + +//===----------------------------------------------------------------------===// +// Provide specializations of GraphTraits to be able to treat def-use/use-def +// chains as graphs + +template <> struct GraphTraits { + typedef const Value NodeType; + typedef Value::use_const_iterator ChildIteratorType; + + static NodeType *getEntryNode(const Value *G) { + return G; + } + + static inline ChildIteratorType child_begin(NodeType *N) { + return N->use_begin(); + } + + static inline ChildIteratorType child_end(NodeType *N) { + return N->use_end(); + } +}; + +template <> struct GraphTraits { + typedef Value NodeType; + typedef Value::use_iterator ChildIteratorType; + + static NodeType *getEntryNode(Value *G) { + return G; + } + + static inline ChildIteratorType child_begin(NodeType *N) { + return N->use_begin(); + } + + static inline ChildIteratorType child_end(NodeType *N) { + return N->use_end(); + } +}; + +template <> struct GraphTraits > { + typedef const Value NodeType; + typedef User::const_op_iterator ChildIteratorType; + + static NodeType *getEntryNode(Inverse G) { + return G.Graph; + } + + static inline ChildIteratorType child_begin(NodeType *N) { + if (const User *U = dyn_cast(N)) + return U->op_begin(); + return NULL; + } + + static inline ChildIteratorType child_end(NodeType *N) { + if(const User *U = dyn_cast(N)) + return U->op_end(); + return NULL; + } +}; + +template <> struct GraphTraits > { + typedef Value NodeType; + typedef User::op_iterator ChildIteratorType; + + static NodeType *getEntryNode(Inverse G) { + return G.Graph; + } + + static inline ChildIteratorType child_begin(NodeType *N) { + if (User *U = dyn_cast(N)) + return U->op_begin(); + return NULL; + } + + static inline ChildIteratorType child_end(NodeType *N) { + if (User *U = dyn_cast(N)) + return U->op_end(); + return NULL; + } +}; + +} +#endif diff --git a/libclamav/c++/llvm/include/llvm/Support/Debug.h b/libclamav/c++/llvm/include/llvm/Support/Debug.h new file mode 100644 index 000000000..afa828c36 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Support/Debug.h @@ -0,0 +1,85 @@ +//===- llvm/Support/Debug.h - Easy way to add debug output ------*- 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 a handy way of adding debugging information to your +// code, without it being enabled all of the time, and without having to add +// command line options to enable it. +// +// In particular, just wrap your code with the DEBUG() macro, and it will be +// enabled automatically if you specify '-debug' on the command-line. +// Alternatively, you can also use the SET_DEBUG_TYPE("foo") macro to specify +// that your debug code belongs to class "foo". Then, on the command line, you +// can specify '-debug-only=foo' to enable JUST the debug information for the +// foo class. +// +// When compiling without assertions, the -debug-* options and all code in +// DEBUG() statements disappears, so it does not effect the runtime of the code. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_DEBUG_H +#define LLVM_SUPPORT_DEBUG_H + +namespace llvm { + +/// DEBUG_TYPE macro - Files can specify a DEBUG_TYPE as a string, which causes +/// all of their DEBUG statements to be activatable with -debug-only=thatstring. +#ifndef DEBUG_TYPE +#define DEBUG_TYPE "" +#endif + +#ifndef NDEBUG +/// DebugFlag - This boolean is set to true if the '-debug' command line option +/// is specified. This should probably not be referenced directly, instead, use +/// the DEBUG macro below. +/// +extern bool DebugFlag; + +/// isCurrentDebugType - Return true if the specified string is the debug type +/// specified on the command line, or if none was specified on the command line +/// with the -debug-only=X option. +/// +bool isCurrentDebugType(const char *Type); + +/// SetCurrentDebugType - Set the current debug type, as if the -debug-only=X +/// option were specified. Note that DebugFlag also needs to be set to true for +/// debug output to be produced. +/// +void SetCurrentDebugType(const char *Type); + +/// DEBUG_WITH_TYPE macro - This macro should be used by passes to emit debug +/// information. In the '-debug' option is specified on the commandline, and if +/// this is a debug build, then the code specified as the option to the macro +/// will be executed. Otherwise it will not be. Example: +/// +/// DEBUG_WITH_TYPE("bitset", errs() << "Bitset contains: " << Bitset << "\n"); +/// +/// This will emit the debug information if -debug is present, and -debug-only +/// is not specified, or is specified as "bitset". +#define DEBUG_WITH_TYPE(TYPE, X) \ + do { if (DebugFlag && isCurrentDebugType(TYPE)) { X; } } while (0) + +#else +#define isCurrentDebugType(X) (false) +#define SetCurrentDebugType(X) +#define DEBUG_WITH_TYPE(TYPE, X) do { } while (0) +#endif + +// DEBUG macro - This macro should be used by passes to emit debug information. +// In the '-debug' option is specified on the commandline, and if this is a +// debug build, then the code specified as the option to the macro will be +// executed. Otherwise it will not be. Example: +// +// DEBUG(errs() << "Bitset contains: " << Bitset << "\n"); +// +#define DEBUG(X) DEBUG_WITH_TYPE(DEBUG_TYPE, X) + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Support/DebugLoc.h b/libclamav/c++/llvm/include/llvm/Support/DebugLoc.h new file mode 100644 index 000000000..362390f62 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Support/DebugLoc.h @@ -0,0 +1,108 @@ +//===---- llvm/DebugLoc.h - Debug Location Information ----------*- 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 a number of light weight data structures used +// to describe and track debug location information. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGLOC_H +#define LLVM_DEBUGLOC_H + +#include "llvm/ADT/DenseMap.h" +#include + +namespace llvm { + class MDNode; + + /// DebugLocTuple - Debug location tuple of filename id, line and column. + /// + struct DebugLocTuple { + MDNode *Scope; + MDNode *InlinedAtLoc; + unsigned Line, Col; + + DebugLocTuple() + : Scope(0), InlinedAtLoc(0), Line(~0U), Col(~0U) {} + + DebugLocTuple(MDNode *n, MDNode *i, unsigned l, unsigned c) + : Scope(n), InlinedAtLoc(i), Line(l), Col(c) {} + + bool operator==(const DebugLocTuple &DLT) const { + return Scope == DLT.Scope && + InlinedAtLoc == DLT.InlinedAtLoc && + Line == DLT.Line && Col == DLT.Col; + } + bool operator!=(const DebugLocTuple &DLT) const { + return !(*this == DLT); + } + }; + + /// DebugLoc - Debug location id. This is carried by SDNode and MachineInstr + /// to index into a vector of unique debug location tuples. + class DebugLoc { + unsigned Idx; + + public: + DebugLoc() : Idx(~0U) {} // Defaults to invalid. + + static DebugLoc getUnknownLoc() { DebugLoc L; L.Idx = ~0U; return L; } + static DebugLoc get(unsigned idx) { DebugLoc L; L.Idx = idx; return L; } + + unsigned getIndex() const { return Idx; } + + /// isUnknown - Return true if there is no debug info for the SDNode / + /// MachineInstr. + bool isUnknown() const { return Idx == ~0U; } + + bool operator==(const DebugLoc &DL) const { return Idx == DL.Idx; } + bool operator!=(const DebugLoc &DL) const { return !(*this == DL); } + }; + + // Specialize DenseMapInfo for DebugLocTuple. + template<> struct DenseMapInfo { + static inline DebugLocTuple getEmptyKey() { + return DebugLocTuple(0, 0, ~0U, ~0U); + } + static inline DebugLocTuple getTombstoneKey() { + return DebugLocTuple((MDNode*)~1U, (MDNode*)~1U, ~1U, ~1U); + } + static unsigned getHashValue(const DebugLocTuple &Val) { + return DenseMapInfo::getHashValue(Val.Scope) ^ + DenseMapInfo::getHashValue(Val.InlinedAtLoc) ^ + DenseMapInfo::getHashValue(Val.Line) ^ + DenseMapInfo::getHashValue(Val.Col); + } + static bool isEqual(const DebugLocTuple &LHS, const DebugLocTuple &RHS) { + return LHS.Scope == RHS.Scope && + LHS.InlinedAtLoc == RHS.InlinedAtLoc && + LHS.Line == RHS.Line && + LHS.Col == RHS.Col; + } + + static bool isPod() { return true; } + }; + + /// DebugLocTracker - This class tracks debug location information. + /// + struct DebugLocTracker { + /// DebugLocations - A vector of unique DebugLocTuple's. + /// + std::vector DebugLocations; + + /// DebugIdMap - This maps DebugLocTuple's to indices into the + /// DebugLocations vector. + DenseMap DebugIdMap; + + DebugLocTracker() {} + }; + +} // end namespace llvm + +#endif /* LLVM_DEBUGLOC_H */ diff --git a/libclamav/c++/llvm/include/llvm/Support/Dwarf.h b/libclamav/c++/llvm/include/llvm/Support/Dwarf.h new file mode 100644 index 000000000..bfccc522b --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Support/Dwarf.h @@ -0,0 +1,588 @@ +//===-- llvm/Support/Dwarf.h ---Dwarf Constants------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains constants used for implementing Dwarf debug support. For +// Details on the Dwarf 3 specfication see DWARF Debugging Information Format +// V.3 reference manual http://dwarf.freestandards.org , +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_DWARF_H +#define LLVM_SUPPORT_DWARF_H + +namespace llvm { + +//===----------------------------------------------------------------------===// +// Debug info constants. + +enum { + LLVMDebugVersion = (7 << 16), // Current version of debug information. + LLVMDebugVersion6 = (6 << 16), // Constant for version 6. + LLVMDebugVersion5 = (5 << 16), // Constant for version 5. + LLVMDebugVersion4 = (4 << 16), // Constant for version 4. + LLVMDebugVersionMask = 0xffff0000 // Mask for version number. +}; + +namespace dwarf { + +//===----------------------------------------------------------------------===// +// Dwarf constants as gleaned from the DWARF Debugging Information Format V.3 +// reference manual http://dwarf.freestandards.org . +// + +// Do not mix the following two enumerations sets. DW_TAG_invalid changes the +// enumeration base type. + +enum llvm_dwarf_constants { + // llvm mock tags + DW_TAG_invalid = ~0U, // Tag for invalid results. + + DW_TAG_anchor = 0, // Tag for descriptor anchors. + DW_TAG_auto_variable = 0x100, // Tag for local (auto) variables. + DW_TAG_arg_variable = 0x101, // Tag for argument variables. + DW_TAG_return_variable = 0x102, // Tag for return variables. + + DW_TAG_vector_type = 0x103, // Tag for vector types. + + DW_TAG_user_base = 0x1000, // Recommended base for user tags. + + DW_CIE_VERSION = 1, // Common frame information version. + DW_CIE_ID = 0xffffffff // Common frame information mark. +}; + +enum dwarf_constants { + DWARF_VERSION = 2, + + // Tags + DW_TAG_array_type = 0x01, + DW_TAG_class_type = 0x02, + DW_TAG_entry_point = 0x03, + DW_TAG_enumeration_type = 0x04, + DW_TAG_formal_parameter = 0x05, + DW_TAG_imported_declaration = 0x08, + DW_TAG_label = 0x0a, + DW_TAG_lexical_block = 0x0b, + DW_TAG_member = 0x0d, + DW_TAG_pointer_type = 0x0f, + DW_TAG_reference_type = 0x10, + DW_TAG_compile_unit = 0x11, + DW_TAG_string_type = 0x12, + DW_TAG_structure_type = 0x13, + DW_TAG_subroutine_type = 0x15, + DW_TAG_typedef = 0x16, + DW_TAG_union_type = 0x17, + DW_TAG_unspecified_parameters = 0x18, + DW_TAG_variant = 0x19, + DW_TAG_common_block = 0x1a, + DW_TAG_common_inclusion = 0x1b, + DW_TAG_inheritance = 0x1c, + DW_TAG_inlined_subroutine = 0x1d, + DW_TAG_module = 0x1e, + DW_TAG_ptr_to_member_type = 0x1f, + DW_TAG_set_type = 0x20, + DW_TAG_subrange_type = 0x21, + DW_TAG_with_stmt = 0x22, + DW_TAG_access_declaration = 0x23, + DW_TAG_base_type = 0x24, + DW_TAG_catch_block = 0x25, + DW_TAG_const_type = 0x26, + DW_TAG_constant = 0x27, + DW_TAG_enumerator = 0x28, + DW_TAG_file_type = 0x29, + DW_TAG_friend = 0x2a, + DW_TAG_namelist = 0x2b, + DW_TAG_namelist_item = 0x2c, + DW_TAG_packed_type = 0x2d, + DW_TAG_subprogram = 0x2e, + DW_TAG_template_type_parameter = 0x2f, + DW_TAG_template_value_parameter = 0x30, + DW_TAG_thrown_type = 0x31, + DW_TAG_try_block = 0x32, + DW_TAG_variant_part = 0x33, + DW_TAG_variable = 0x34, + DW_TAG_volatile_type = 0x35, + DW_TAG_dwarf_procedure = 0x36, + DW_TAG_restrict_type = 0x37, + DW_TAG_interface_type = 0x38, + DW_TAG_namespace = 0x39, + DW_TAG_imported_module = 0x3a, + DW_TAG_unspecified_type = 0x3b, + DW_TAG_partial_unit = 0x3c, + DW_TAG_imported_unit = 0x3d, + DW_TAG_condition = 0x3f, + DW_TAG_shared_type = 0x40, + DW_TAG_lo_user = 0x4080, + DW_TAG_hi_user = 0xffff, + + // Children flag + DW_CHILDREN_no = 0x00, + DW_CHILDREN_yes = 0x01, + + // Attributes + DW_AT_sibling = 0x01, + DW_AT_location = 0x02, + DW_AT_name = 0x03, + DW_AT_ordering = 0x09, + DW_AT_byte_size = 0x0b, + DW_AT_bit_offset = 0x0c, + DW_AT_bit_size = 0x0d, + DW_AT_stmt_list = 0x10, + DW_AT_low_pc = 0x11, + DW_AT_high_pc = 0x12, + DW_AT_language = 0x13, + DW_AT_discr = 0x15, + DW_AT_discr_value = 0x16, + DW_AT_visibility = 0x17, + DW_AT_import = 0x18, + DW_AT_string_length = 0x19, + DW_AT_common_reference = 0x1a, + DW_AT_comp_dir = 0x1b, + DW_AT_const_value = 0x1c, + DW_AT_containing_type = 0x1d, + DW_AT_default_value = 0x1e, + DW_AT_inline = 0x20, + DW_AT_is_optional = 0x21, + DW_AT_lower_bound = 0x22, + DW_AT_producer = 0x25, + DW_AT_prototyped = 0x27, + DW_AT_return_addr = 0x2a, + DW_AT_start_scope = 0x2c, + DW_AT_bit_stride = 0x2e, + DW_AT_upper_bound = 0x2f, + DW_AT_abstract_origin = 0x31, + DW_AT_accessibility = 0x32, + DW_AT_address_class = 0x33, + DW_AT_artificial = 0x34, + DW_AT_base_types = 0x35, + DW_AT_calling_convention = 0x36, + DW_AT_count = 0x37, + DW_AT_data_member_location = 0x38, + DW_AT_decl_column = 0x39, + DW_AT_decl_file = 0x3a, + DW_AT_decl_line = 0x3b, + DW_AT_declaration = 0x3c, + DW_AT_discr_list = 0x3d, + DW_AT_encoding = 0x3e, + DW_AT_external = 0x3f, + DW_AT_frame_base = 0x40, + DW_AT_friend = 0x41, + DW_AT_identifier_case = 0x42, + DW_AT_macro_info = 0x43, + DW_AT_namelist_item = 0x44, + DW_AT_priority = 0x45, + DW_AT_segment = 0x46, + DW_AT_specification = 0x47, + DW_AT_static_link = 0x48, + DW_AT_type = 0x49, + DW_AT_use_location = 0x4a, + DW_AT_variable_parameter = 0x4b, + DW_AT_virtuality = 0x4c, + DW_AT_vtable_elem_location = 0x4d, + DW_AT_allocated = 0x4e, + DW_AT_associated = 0x4f, + DW_AT_data_location = 0x50, + DW_AT_byte_stride = 0x51, + DW_AT_entry_pc = 0x52, + DW_AT_use_UTF8 = 0x53, + DW_AT_extension = 0x54, + DW_AT_ranges = 0x55, + DW_AT_trampoline = 0x56, + DW_AT_call_column = 0x57, + DW_AT_call_file = 0x58, + DW_AT_call_line = 0x59, + DW_AT_description = 0x5a, + DW_AT_binary_scale = 0x5b, + DW_AT_decimal_scale = 0x5c, + DW_AT_small = 0x5d, + DW_AT_decimal_sign = 0x5e, + DW_AT_digit_count = 0x5f, + DW_AT_picture_string = 0x60, + DW_AT_mutable = 0x61, + DW_AT_threads_scaled = 0x62, + DW_AT_explicit = 0x63, + DW_AT_object_pointer = 0x64, + DW_AT_endianity = 0x65, + DW_AT_elemental = 0x66, + DW_AT_pure = 0x67, + DW_AT_recursive = 0x68, + DW_AT_MIPS_linkage_name = 0x2007, + DW_AT_sf_names = 0x2101, + DW_AT_src_info = 0x2102, + DW_AT_mac_info = 0x2103, + DW_AT_src_coords = 0x2104, + DW_AT_body_begin = 0x2105, + DW_AT_body_end = 0x2106, + DW_AT_GNU_vector = 0x2107, + DW_AT_lo_user = 0x2000, + DW_AT_hi_user = 0x3fff, + + // Apple extensions. + DW_AT_APPLE_optimized = 0x3fe1, + DW_AT_APPLE_flags = 0x3fe2, + DW_AT_APPLE_isa = 0x3fe3, + DW_AT_APPLE_block = 0x3fe4, + DW_AT_APPLE_major_runtime_vers = 0x3fe5, + DW_AT_APPLE_runtime_class = 0x3fe6, + + // Attribute form encodings + DW_FORM_addr = 0x01, + DW_FORM_block2 = 0x03, + DW_FORM_block4 = 0x04, + DW_FORM_data2 = 0x05, + DW_FORM_data4 = 0x06, + DW_FORM_data8 = 0x07, + DW_FORM_string = 0x08, + DW_FORM_block = 0x09, + DW_FORM_block1 = 0x0a, + DW_FORM_data1 = 0x0b, + DW_FORM_flag = 0x0c, + DW_FORM_sdata = 0x0d, + DW_FORM_strp = 0x0e, + DW_FORM_udata = 0x0f, + DW_FORM_ref_addr = 0x10, + DW_FORM_ref1 = 0x11, + DW_FORM_ref2 = 0x12, + DW_FORM_ref4 = 0x13, + DW_FORM_ref8 = 0x14, + DW_FORM_ref_udata = 0x15, + DW_FORM_indirect = 0x16, + + // Operation encodings + DW_OP_addr = 0x03, + DW_OP_deref = 0x06, + DW_OP_const1u = 0x08, + DW_OP_const1s = 0x09, + DW_OP_const2u = 0x0a, + DW_OP_const2s = 0x0b, + DW_OP_const4u = 0x0c, + DW_OP_const4s = 0x0d, + DW_OP_const8u = 0x0e, + DW_OP_const8s = 0x0f, + DW_OP_constu = 0x10, + DW_OP_consts = 0x11, + DW_OP_dup = 0x12, + DW_OP_drop = 0x13, + DW_OP_over = 0x14, + DW_OP_pick = 0x15, + DW_OP_swap = 0x16, + DW_OP_rot = 0x17, + DW_OP_xderef = 0x18, + DW_OP_abs = 0x19, + DW_OP_and = 0x1a, + DW_OP_div = 0x1b, + DW_OP_minus = 0x1c, + DW_OP_mod = 0x1d, + DW_OP_mul = 0x1e, + DW_OP_neg = 0x1f, + DW_OP_not = 0x20, + DW_OP_or = 0x21, + DW_OP_plus = 0x22, + DW_OP_plus_uconst = 0x23, + DW_OP_shl = 0x24, + DW_OP_shr = 0x25, + DW_OP_shra = 0x26, + DW_OP_xor = 0x27, + DW_OP_skip = 0x2f, + DW_OP_bra = 0x28, + DW_OP_eq = 0x29, + DW_OP_ge = 0x2a, + DW_OP_gt = 0x2b, + DW_OP_le = 0x2c, + DW_OP_lt = 0x2d, + DW_OP_ne = 0x2e, + DW_OP_lit0 = 0x30, + DW_OP_lit1 = 0x31, + DW_OP_lit31 = 0x4f, + DW_OP_reg0 = 0x50, + DW_OP_reg1 = 0x51, + DW_OP_reg31 = 0x6f, + DW_OP_breg0 = 0x70, + DW_OP_breg1 = 0x71, + DW_OP_breg31 = 0x8f, + DW_OP_regx = 0x90, + DW_OP_fbreg = 0x91, + DW_OP_bregx = 0x92, + DW_OP_piece = 0x93, + DW_OP_deref_size = 0x94, + DW_OP_xderef_size = 0x95, + DW_OP_nop = 0x96, + DW_OP_push_object_address = 0x97, + DW_OP_call2 = 0x98, + DW_OP_call4 = 0x99, + DW_OP_call_ref = 0x9a, + DW_OP_form_tls_address = 0x9b, + DW_OP_call_frame_cfa = 0x9c, + DW_OP_lo_user = 0xe0, + DW_OP_hi_user = 0xff, + + // Encoding attribute values + DW_ATE_address = 0x01, + DW_ATE_boolean = 0x02, + DW_ATE_complex_float = 0x03, + DW_ATE_float = 0x04, + DW_ATE_signed = 0x05, + DW_ATE_signed_char = 0x06, + DW_ATE_unsigned = 0x07, + DW_ATE_unsigned_char = 0x08, + DW_ATE_imaginary_float = 0x09, + DW_ATE_packed_decimal = 0x0a, + DW_ATE_numeric_string = 0x0b, + DW_ATE_edited = 0x0c, + DW_ATE_signed_fixed = 0x0d, + DW_ATE_unsigned_fixed = 0x0e, + DW_ATE_decimal_float = 0x0f, + DW_ATE_lo_user = 0x80, + DW_ATE_hi_user = 0xff, + + // Decimal sign attribute values + DW_DS_unsigned = 0x01, + DW_DS_leading_overpunch = 0x02, + DW_DS_trailing_overpunch = 0x03, + DW_DS_leading_separate = 0x04, + DW_DS_trailing_separate = 0x05, + + // Endianity attribute values + DW_END_default = 0x00, + DW_END_big = 0x01, + DW_END_little = 0x02, + DW_END_lo_user = 0x40, + DW_END_hi_user = 0xff, + + // Accessibility codes + DW_ACCESS_public = 0x01, + DW_ACCESS_protected = 0x02, + DW_ACCESS_private = 0x03, + + // Visibility codes + DW_VIS_local = 0x01, + DW_VIS_exported = 0x02, + DW_VIS_qualified = 0x03, + + // Virtuality codes + DW_VIRTUALITY_none = 0x00, + DW_VIRTUALITY_virtual = 0x01, + DW_VIRTUALITY_pure_virtual = 0x02, + + // Language names + DW_LANG_C89 = 0x0001, + DW_LANG_C = 0x0002, + DW_LANG_Ada83 = 0x0003, + DW_LANG_C_plus_plus = 0x0004, + DW_LANG_Cobol74 = 0x0005, + DW_LANG_Cobol85 = 0x0006, + DW_LANG_Fortran77 = 0x0007, + DW_LANG_Fortran90 = 0x0008, + DW_LANG_Pascal83 = 0x0009, + DW_LANG_Modula2 = 0x000a, + DW_LANG_Java = 0x000b, + DW_LANG_C99 = 0x000c, + DW_LANG_Ada95 = 0x000d, + DW_LANG_Fortran95 = 0x000e, + DW_LANG_PLI = 0x000f, + DW_LANG_ObjC = 0x0010, + DW_LANG_ObjC_plus_plus = 0x0011, + DW_LANG_UPC = 0x0012, + DW_LANG_D = 0x0013, + DW_LANG_lo_user = 0x8000, + DW_LANG_hi_user = 0xffff, + + // Identifier case codes + DW_ID_case_sensitive = 0x00, + DW_ID_up_case = 0x01, + DW_ID_down_case = 0x02, + DW_ID_case_insensitive = 0x03, + + // Calling convention codes + DW_CC_normal = 0x01, + DW_CC_program = 0x02, + DW_CC_nocall = 0x03, + DW_CC_lo_user = 0x40, + DW_CC_hi_user = 0xff, + + // Inline codes + DW_INL_not_inlined = 0x00, + DW_INL_inlined = 0x01, + DW_INL_declared_not_inlined = 0x02, + DW_INL_declared_inlined = 0x03, + + // Array ordering + DW_ORD_row_major = 0x00, + DW_ORD_col_major = 0x01, + + // Discriminant descriptor values + DW_DSC_label = 0x00, + DW_DSC_range = 0x01, + + // Line Number Standard Opcode Encodings + DW_LNS_copy = 0x01, + DW_LNS_advance_pc = 0x02, + DW_LNS_advance_line = 0x03, + DW_LNS_set_file = 0x04, + DW_LNS_set_column = 0x05, + DW_LNS_negate_stmt = 0x06, + DW_LNS_set_basic_block = 0x07, + DW_LNS_const_add_pc = 0x08, + DW_LNS_fixed_advance_pc = 0x09, + DW_LNS_set_prologue_end = 0x0a, + DW_LNS_set_epilogue_begin = 0x0b, + DW_LNS_set_isa = 0x0c, + + // Line Number Extended Opcode Encodings + DW_LNE_end_sequence = 0x01, + DW_LNE_set_address = 0x02, + DW_LNE_define_file = 0x03, + DW_LNE_lo_user = 0x80, + DW_LNE_hi_user = 0xff, + + // Macinfo Type Encodings + DW_MACINFO_define = 0x01, + DW_MACINFO_undef = 0x02, + DW_MACINFO_start_file = 0x03, + DW_MACINFO_end_file = 0x04, + DW_MACINFO_vendor_ext = 0xff, + + // Call frame instruction encodings + DW_CFA_extended = 0x00, + DW_CFA_nop = 0x00, + DW_CFA_advance_loc = 0x40, + DW_CFA_offset = 0x80, + DW_CFA_restore = 0xc0, + DW_CFA_set_loc = 0x01, + DW_CFA_advance_loc1 = 0x02, + DW_CFA_advance_loc2 = 0x03, + DW_CFA_advance_loc4 = 0x04, + DW_CFA_offset_extended = 0x05, + DW_CFA_restore_extended = 0x06, + DW_CFA_undefined = 0x07, + DW_CFA_same_value = 0x08, + DW_CFA_register = 0x09, + DW_CFA_remember_state = 0x0a, + DW_CFA_restore_state = 0x0b, + DW_CFA_def_cfa = 0x0c, + DW_CFA_def_cfa_register = 0x0d, + DW_CFA_def_cfa_offset = 0x0e, + DW_CFA_def_cfa_expression = 0x0f, + DW_CFA_expression = 0x10, + DW_CFA_offset_extended_sf = 0x11, + DW_CFA_def_cfa_sf = 0x12, + DW_CFA_def_cfa_offset_sf = 0x13, + DW_CFA_val_offset = 0x14, + DW_CFA_val_offset_sf = 0x15, + DW_CFA_val_expression = 0x16, + DW_CFA_lo_user = 0x1c, + DW_CFA_hi_user = 0x3f, + + DW_EH_PE_absptr = 0x00, + DW_EH_PE_omit = 0xff, + DW_EH_PE_uleb128 = 0x01, + DW_EH_PE_udata2 = 0x02, + DW_EH_PE_udata4 = 0x03, + DW_EH_PE_udata8 = 0x04, + DW_EH_PE_sleb128 = 0x09, + DW_EH_PE_sdata2 = 0x0A, + DW_EH_PE_sdata4 = 0x0B, + DW_EH_PE_sdata8 = 0x0C, + DW_EH_PE_signed = 0x08, + DW_EH_PE_pcrel = 0x10, + DW_EH_PE_textrel = 0x20, + DW_EH_PE_datarel = 0x30, + DW_EH_PE_funcrel = 0x40, + DW_EH_PE_aligned = 0x50, + DW_EH_PE_indirect = 0x80 +}; + +/// TagString - Return the string for the specified tag. +/// +const char *TagString(unsigned Tag); + +/// ChildrenString - Return the string for the specified children flag. +/// +const char *ChildrenString(unsigned Children); + +/// AttributeString - Return the string for the specified attribute. +/// +const char *AttributeString(unsigned Attribute); + +/// FormEncodingString - Return the string for the specified form encoding. +/// +const char *FormEncodingString(unsigned Encoding); + +/// OperationEncodingString - Return the string for the specified operation +/// encoding. +const char *OperationEncodingString(unsigned Encoding); + +/// AttributeEncodingString - Return the string for the specified attribute +/// encoding. +const char *AttributeEncodingString(unsigned Encoding); + +/// DecimalSignString - Return the string for the specified decimal sign +/// attribute. +const char *DecimalSignString(unsigned Sign); + +/// EndianityString - Return the string for the specified endianity. +/// +const char *EndianityString(unsigned Endian); + +/// AccessibilityString - Return the string for the specified accessibility. +/// +const char *AccessibilityString(unsigned Access); + +/// VisibilityString - Return the string for the specified visibility. +/// +const char *VisibilityString(unsigned Visibility); + +/// VirtualityString - Return the string for the specified virtuality. +/// +const char *VirtualityString(unsigned Virtuality); + +/// LanguageString - Return the string for the specified language. +/// +const char *LanguageString(unsigned Language); + +/// CaseString - Return the string for the specified identifier case. +/// +const char *CaseString(unsigned Case); + +/// ConventionString - Return the string for the specified calling convention. +/// +const char *ConventionString(unsigned Convention); + +/// InlineCodeString - Return the string for the specified inline code. +/// +const char *InlineCodeString(unsigned Code); + +/// ArrayOrderString - Return the string for the specified array order. +/// +const char *ArrayOrderString(unsigned Order); + +/// DiscriminantString - Return the string for the specified discriminant +/// descriptor. +const char *DiscriminantString(unsigned Discriminant); + +/// LNStandardString - Return the string for the specified line number standard. +/// +const char *LNStandardString(unsigned Standard); + +/// LNExtendedString - Return the string for the specified line number extended +/// opcode encodings. +const char *LNExtendedString(unsigned Encoding); + +/// MacinfoString - Return the string for the specified macinfo type encodings. +/// +const char *MacinfoString(unsigned Encoding); + +/// CallFrameString - Return the string for the specified call frame instruction +/// encodings. +const char *CallFrameString(unsigned Encoding); + +} // End of namespace dwarf + +} // End of namespace llvm + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Support/DynamicLinker.h b/libclamav/c++/llvm/include/llvm/Support/DynamicLinker.h new file mode 100644 index 000000000..b60ffa875 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Support/DynamicLinker.h @@ -0,0 +1,40 @@ +//===-- llvm/Support/DynamicLinker.h - Portable Dynamic Linker --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Lightweight interface to dynamic library linking and loading, and dynamic +// symbol lookup functionality, in whatever form the operating system +// provides it. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_DYNAMICLINKER_H +#define LLVM_SUPPORT_DYNAMICLINKER_H + +#include + +namespace llvm { + +/// LinkDynamicObject - Load the named file as a dynamic library +/// and link it with the currently running process. Returns false +/// on success, true if there is an error (and sets ErrorMessage +/// if it is not NULL). Analogous to dlopen(). +/// +bool LinkDynamicObject (const char *filename, std::string *ErrorMessage); + +/// GetAddressOfSymbol - Returns the address of the named symbol in +/// the currently running process, as reported by the dynamic linker, +/// or NULL if the symbol does not exist or some other error has +/// occurred. +/// +void *GetAddressOfSymbol (const char *symbolName); +void *GetAddressOfSymbol (const std::string &symbolName); + +} // End llvm namespace + +#endif // SUPPORT_DYNAMICLINKER_H diff --git a/libclamav/c++/llvm/include/llvm/Support/ELF.h b/libclamav/c++/llvm/include/llvm/Support/ELF.h new file mode 100644 index 000000000..e747c7a74 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Support/ELF.h @@ -0,0 +1,309 @@ +//===-- llvm/Support/ELF.h - ELF constants and data structures --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This header contains common, non-processor-specific data structures and +// constants for the ELF file format. +// +// The details of the ELF32 bits in this file are largely based on +// the Tool Interface Standard (TIS) Executable and Linking Format +// (ELF) Specification Version 1.2, May 1995. The ELF64 stuff is not +// standardized, as far as I can tell. It was largely based on information +// I found in OpenBSD header files. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_ELF_H +#define LLVM_SUPPORT_ELF_H + +#include "llvm/System/DataTypes.h" +#include + +namespace llvm { + +namespace ELF { + +typedef uint32_t Elf32_Addr; // Program address +typedef uint16_t Elf32_Half; +typedef uint32_t Elf32_Off; // File offset +typedef int32_t Elf32_Sword; +typedef uint32_t Elf32_Word; + +typedef uint64_t Elf64_Addr; +typedef uint64_t Elf64_Off; +typedef int32_t Elf64_Shalf; +typedef int32_t Elf64_Sword; +typedef uint32_t Elf64_Word; +typedef int64_t Elf64_Sxword; +typedef uint64_t Elf64_Xword; +typedef uint32_t Elf64_Half; +typedef uint16_t Elf64_Quarter; + +// Object file magic string. +static const char ElfMagic[] = { 0x7f, 'E', 'L', 'F', '\0' }; + +struct Elf32_Ehdr { + unsigned char e_ident[16]; // ELF Identification bytes + Elf32_Half e_type; // Type of file (see ET_* below) + Elf32_Half e_machine; // Required architecture for this file (see EM_*) + Elf32_Word e_version; // Must be equal to 1 + Elf32_Addr e_entry; // Address to jump to in order to start program + Elf32_Off e_phoff; // Program header table's file offset, in bytes + Elf32_Off e_shoff; // Section header table's file offset, in bytes + Elf32_Word e_flags; // Processor-specific flags + Elf32_Half e_ehsize; // Size of ELF header, in bytes + Elf32_Half e_phentsize; // Size of an entry in the program header table + Elf32_Half e_phnum; // Number of entries in the program header table + Elf32_Half e_shentsize; // Size of an entry in the section header table + Elf32_Half e_shnum; // Number of entries in the section header table + Elf32_Half e_shstrndx; // Sect hdr table index of sect name string table + bool checkMagic () const { + return (memcmp (e_ident, ElfMagic, strlen (ElfMagic))) == 0; + } + unsigned char getFileClass () const { return e_ident[4]; } + unsigned char getDataEncoding () { return e_ident[5]; } +}; + +// 64-bit ELF header. Fields are the same as for ELF32, but with different +// types (see above). +struct Elf64_Ehdr { + unsigned char e_ident[16]; + Elf64_Quarter e_type; + Elf64_Quarter e_machine; + Elf64_Half e_version; + Elf64_Addr e_entry; + Elf64_Off e_phoff; + Elf64_Off e_shoff; + Elf64_Half e_flags; + Elf64_Quarter e_ehsize; + Elf64_Quarter e_phentsize; + Elf64_Quarter e_phnum; + Elf64_Quarter e_shentsize; + Elf64_Quarter e_shnum; + Elf64_Quarter e_shstrndx; +}; + +// File types +enum { + ET_NONE = 0, // No file type + ET_REL = 1, // Relocatable file + ET_EXEC = 2, // Executable file + ET_DYN = 3, // Shared object file + ET_CORE = 4, // Core file + ET_LOPROC = 0xff00, // Beginning of processor-specific codes + ET_HIPROC = 0xffff // Processor-specific +}; + +// Machine architectures +enum { + EM_NONE = 0, // No machine + EM_M32 = 1, // AT&T WE 32100 + EM_SPARC = 2, // SPARC + EM_386 = 3, // Intel 386 + EM_68K = 4, // Motorola 68000 + EM_88K = 5, // Motorola 88000 + EM_486 = 6, // Intel 486 (deprecated) + EM_860 = 7, // Intel 80860 + EM_MIPS = 8, // MIPS R3000 + EM_PPC = 20, // PowerPC + EM_ARM = 40, // ARM + EM_ALPHA = 41, // DEC Alpha + EM_SPARCV9 = 43, // SPARC V9 + EM_X86_64 = 62 // AMD64 +}; + +// Object file classes. +enum { + ELFCLASS32 = 1, // 32-bit object file + ELFCLASS64 = 2 // 64-bit object file +}; + +// Object file byte orderings. +enum { + ELFDATA2LSB = 1, // Little-endian object file + ELFDATA2MSB = 2 // Big-endian object file +}; + +// Section header. +struct Elf32_Shdr { + Elf32_Word sh_name; // Section name (index into string table) + Elf32_Word sh_type; // Section type (SHT_*) + Elf32_Word sh_flags; // Section flags (SHF_*) + Elf32_Addr sh_addr; // Address where section is to be loaded + Elf32_Off sh_offset; // File offset of section data, in bytes + Elf32_Word sh_size; // Size of section, in bytes + Elf32_Word sh_link; // Section type-specific header table index link + Elf32_Word sh_info; // Section type-specific extra information + Elf32_Word sh_addralign; // Section address alignment + Elf32_Word sh_entsize; // Size of records contained within the section +}; + +// Section header for ELF64 - same fields as ELF32, different types. +struct Elf64_Shdr { + Elf64_Half sh_name; + Elf64_Half sh_type; + Elf64_Xword sh_flags; + Elf64_Addr sh_addr; + Elf64_Off sh_offset; + Elf64_Xword sh_size; + Elf64_Half sh_link; + Elf64_Half sh_info; + Elf64_Xword sh_addralign; + Elf64_Xword sh_entsize; +}; + +// Special section indices. +enum { + SHN_UNDEF = 0, // Undefined, missing, irrelevant, or meaningless + SHN_LORESERVE = 0xff00, // Lowest reserved index + SHN_LOPROC = 0xff00, // Lowest processor-specific index + SHN_HIPROC = 0xff1f, // Highest processor-specific index + SHN_ABS = 0xfff1, // Symbol has absolute value; does not need relocation + SHN_COMMON = 0xfff2, // FORTRAN COMMON or C external global variables + SHN_HIRESERVE = 0xffff // Highest reserved index +}; + +// Section types. +enum { + SHT_NULL = 0, // No associated section (inactive entry). + SHT_PROGBITS = 1, // Program-defined contents. + SHT_SYMTAB = 2, // Symbol table. + SHT_STRTAB = 3, // String table. + SHT_RELA = 4, // Relocation entries; explicit addends. + SHT_HASH = 5, // Symbol hash table. + SHT_DYNAMIC = 6, // Information for dynamic linking. + SHT_NOTE = 7, // Information about the file. + SHT_NOBITS = 8, // Data occupies no space in the file. + SHT_REL = 9, // Relocation entries; no explicit addends. + SHT_SHLIB = 10, // Reserved. + SHT_DYNSYM = 11, // Symbol table. + SHT_LOPROC = 0x70000000, // Lowest processor architecture-specific type. + SHT_HIPROC = 0x7fffffff, // Highest processor architecture-specific type. + SHT_LOUSER = 0x80000000, // Lowest type reserved for applications. + SHT_HIUSER = 0xffffffff // Highest type reserved for applications. +}; + +// Section flags. +enum { + SHF_WRITE = 0x1, // Section data should be writable during execution. + SHF_ALLOC = 0x2, // Section occupies memory during program execution. + SHF_EXECINSTR = 0x4, // Section contains executable machine instructions. + SHF_MASKPROC = 0xf0000000 // Bits indicating processor-specific flags. +}; + +// Symbol table entries. +struct Elf32_Sym { + Elf32_Word st_name; // Symbol name (index into string table) + Elf32_Addr st_value; // Value or address associated with the symbol + Elf32_Word st_size; // Size of the symbol + unsigned char st_info; // Symbol's type and binding attributes + unsigned char st_other; // Must be zero; reserved + Elf32_Half st_shndx; // Which section (header table index) it's defined in + + // These accessors and mutators correspond to the ELF32_ST_BIND, + // ELF32_ST_TYPE, and ELF32_ST_INFO macros defined in the ELF specification: + unsigned char getBinding () const { return st_info >> 4; } + unsigned char getType () const { return st_info & 0x0f; } + void setBinding (unsigned char b) { setBindingAndType (b, getType ()); } + void setType (unsigned char t) { setBindingAndType (getBinding (), t); } + void setBindingAndType (unsigned char b, unsigned char t) { + st_info = (b << 4) + (t & 0x0f); + } +}; + +// Symbol bindings. +enum { + STB_LOCAL = 0, // Local symbol, not visible outside obj file containing def + STB_GLOBAL = 1, // Global symbol, visible to all object files being combined + STB_WEAK = 2, // Weak symbol, like global but lower-precedence + STB_LOPROC = 13, // Lowest processor-specific binding type + STB_HIPROC = 15 // Highest processor-specific binding type +}; + +// Symbol types. +enum { + STT_NOTYPE = 0, // Symbol's type is not specified + STT_OBJECT = 1, // Symbol is a data object (variable, array, etc.) + STT_FUNC = 2, // Symbol is executable code (function, etc.) + STT_SECTION = 3, // Symbol refers to a section + STT_FILE = 4, // Local, absolute symbol that refers to a file + STT_LOPROC = 13, // Lowest processor-specific symbol type + STT_HIPROC = 15 // Highest processor-specific symbol type +}; + +// Relocation entry, without explicit addend. +struct Elf32_Rel { + Elf32_Addr r_offset; // Location (file byte offset, or program virtual addr) + Elf32_Word r_info; // Symbol table index and type of relocation to apply + + // These accessors and mutators correspond to the ELF32_R_SYM, ELF32_R_TYPE, + // and ELF32_R_INFO macros defined in the ELF specification: + Elf32_Word getSymbol () const { return (r_info >> 8); } + unsigned char getType () const { return (unsigned char) (r_info & 0x0ff); } + void setSymbol (Elf32_Word s) { setSymbolAndType (s, getType ()); } + void setType (unsigned char t) { setSymbolAndType (getSymbol(), t); } + void setSymbolAndType (Elf32_Word s, unsigned char t) { + r_info = (s << 8) + t; + }; +}; + +// Relocation entry with explicit addend. +struct Elf32_Rela { + Elf32_Addr r_offset; // Location (file byte offset, or program virtual addr) + Elf32_Word r_info; // Symbol table index and type of relocation to apply + Elf32_Sword r_addend; // Compute value for relocatable field by adding this + + // These accessors and mutators correspond to the ELF32_R_SYM, ELF32_R_TYPE, + // and ELF32_R_INFO macros defined in the ELF specification: + Elf32_Word getSymbol () const { return (r_info >> 8); } + unsigned char getType () const { return (unsigned char) (r_info & 0x0ff); } + void setSymbol (Elf32_Word s) { setSymbolAndType (s, getType ()); } + void setType (unsigned char t) { setSymbolAndType (getSymbol(), t); } + void setSymbolAndType (Elf32_Word s, unsigned char t) { + r_info = (s << 8) + t; + }; +}; + +// Program header. +struct Elf32_Phdr { + Elf32_Word p_type; // Type of segment + Elf32_Off p_offset; // File offset where segment is located, in bytes + Elf32_Addr p_vaddr; // Virtual address of beginning of segment + Elf32_Addr p_paddr; // Physical address of beginning of segment (OS-specific) + Elf32_Word p_filesz; // Num. of bytes in file image of segment (may be zero) + Elf32_Word p_memsz; // Num. of bytes in mem image of segment (may be zero) + Elf32_Word p_flags; // Segment flags + Elf32_Word p_align; // Segment alignment constraint +}; + +// Segment types. +enum { + PT_NULL = 0, // Unused segment. + PT_LOAD = 1, // Loadable segment. + PT_DYNAMIC = 2, // Dynamic linking information. + PT_INTERP = 3, // Interpreter pathname. + PT_NOTE = 4, // Auxiliary information. + PT_SHLIB = 5, // Reserved. + PT_PHDR = 6, // The program header table itself. + PT_LOPROC = 0x70000000, // Lowest processor-specific program hdr entry type. + PT_HIPROC = 0x7fffffff // Highest processor-specific program hdr entry type. +}; + +// Segment flag bits. +enum { + PF_X = 1, // Execute + PF_W = 2, // Write + PF_R = 4, // Read + PF_MASKPROC = 0xf0000000 // Unspecified +}; + +} // end namespace ELF + +} // end namespace llvm + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Support/ErrorHandling.h b/libclamav/c++/llvm/include/llvm/Support/ErrorHandling.h new file mode 100644 index 000000000..60677951a --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Support/ErrorHandling.h @@ -0,0 +1,87 @@ +//===- llvm/Support/ErrorHandling.h - Callbacks for errors ------*- 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 an API used to indicate error conditions. +// Callbacks can be registered for these errors through this API. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_ERRORHANDLING_H +#define LLVM_SUPPORT_ERRORHANDLING_H + +#include "llvm/Support/Compiler.h" +#include + +namespace llvm { + class Twine; + + /// An error handler callback. + typedef void (*llvm_error_handler_t)(void *user_data, + const std::string& reason); + + /// llvm_instal_error_handler - Installs a new error handler to be used + /// whenever a serious (non-recoverable) error is encountered by LLVM. + /// + /// If you are using llvm_start_multithreaded, you should register the handler + /// before doing that. + /// + /// If no error handler is installed the default is to print the error message + /// to stderr, and call exit(1). If an error handler is installed then it is + /// the handler's responsibility to log the message, it will no longer be + /// printed to stderr. If the error handler returns, then exit(1) will be + /// called. + /// + /// It is dangerous to naively use an error handler which throws an exception. + /// Even though some applications desire to gracefully recover from arbitrary + /// faults, blindly throwing exceptions through unfamiliar code isn't a way to + /// achieve this. + /// + /// \param user_data - An argument which will be passed to the install error + /// handler. + void llvm_install_error_handler(llvm_error_handler_t handler, + void *user_data = 0); + + /// Restores default error handling behaviour. + /// This must not be called between llvm_start_multithreaded() and + /// llvm_stop_multithreaded(). + void llvm_remove_error_handler(); + + /// Reports a serious error, calling any installed error handler. These + /// functions are intended to be used for error conditions which are outside + /// the control of the compiler (I/O errors, invalid user input, etc.) + /// + /// If no error handler is installed the default is to print the message to + /// standard error, followed by a newline. + /// After the error handler is called this function will call exit(1), it + /// does not return. + NORETURN void llvm_report_error(const char *reason); + NORETURN void llvm_report_error(const std::string &reason); + NORETURN void llvm_report_error(const Twine &reason); + + /// This function calls abort(), and prints the optional message to stderr. + /// Use the llvm_unreachable macro (that adds location info), instead of + /// calling this function directly. + NORETURN void llvm_unreachable_internal(const char *msg=0, + const char *file=0, unsigned line=0); +} + +/// Prints the message and location info to stderr in !NDEBUG builds. +/// This is intended to be used for "impossible" situations that imply +/// a bug in the compiler. +/// +/// In NDEBUG mode it only prints "UNREACHABLE executed". +/// Use this instead of assert(0), so that the compiler knows this path +/// is not reachable even for NDEBUG builds. +#ifndef NDEBUG +#define llvm_unreachable(msg) llvm_unreachable_internal(msg, __FILE__, __LINE__) +#else +#define llvm_unreachable(msg) llvm_unreachable_internal() +#endif + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Support/FileUtilities.h b/libclamav/c++/llvm/include/llvm/Support/FileUtilities.h new file mode 100644 index 000000000..cc8f95372 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Support/FileUtilities.h @@ -0,0 +1,59 @@ +//===- llvm/Support/FileUtilities.h - File System Utilities -----*- 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 a family of utility functions which are useful for doing +// various things with files. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_FILEUTILITIES_H +#define LLVM_SUPPORT_FILEUTILITIES_H + +#include "llvm/System/Path.h" + +namespace llvm { + + /// DiffFilesWithTolerance - Compare the two files specified, returning 0 if + /// the files match, 1 if they are different, and 2 if there is a file error. + /// This function allows you to specify an absolete and relative FP error that + /// is allowed to exist. If you specify a string to fill in for the error + /// option, it will set the string to an error message if an error occurs, or + /// if the files are different. + /// + int DiffFilesWithTolerance(const sys::PathWithStatus &FileA, + const sys::PathWithStatus &FileB, + double AbsTol, double RelTol, + std::string *Error = 0); + + + /// FileRemover - This class is a simple object meant to be stack allocated. + /// If an exception is thrown from a region, the object removes the filename + /// specified (if deleteIt is true). + /// + class FileRemover { + sys::Path Filename; + bool DeleteIt; + public: + explicit FileRemover(const sys::Path &filename, bool deleteIt = true) + : Filename(filename), DeleteIt(deleteIt) {} + + ~FileRemover() { + if (DeleteIt) { + // Ignore problems deleting the file. + Filename.eraseFromDisk(); + } + } + + /// releaseFile - Take ownership of the file away from the FileRemover so it + /// will not be removed when the object is destroyed. + void releaseFile() { DeleteIt = false; } + }; +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Support/Format.h b/libclamav/c++/llvm/include/llvm/Support/Format.h new file mode 100644 index 000000000..340f51735 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Support/Format.h @@ -0,0 +1,149 @@ +//===- Format.h - Efficient printf-style formatting for streams -*- 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 the format() function, which can be used with other +// LLVM subsystems to provide printf-style formatting. This gives all the power +// and risk of printf. This can be used like this (with raw_ostreams as an +// example): +// +// OS << "mynumber: " << format("%4.5f", 1234.412) << '\n'; +// +// Or if you prefer: +// +// OS << format("mynumber: %4.5f\n", 1234.412); +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_FORMAT_H +#define LLVM_SUPPORT_FORMAT_H + +#include +#include +#ifdef WIN32 +#define snprintf _snprintf +#endif + +namespace llvm { + +/// format_object_base - This is a helper class used for handling formatted +/// output. It is the abstract base class of a templated derived class. +class format_object_base { +protected: + const char *Fmt; + virtual void home(); // Out of line virtual method. + + /// snprint - Call snprintf() for this object, on the given buffer and size. + virtual int snprint(char *Buffer, unsigned BufferSize) const = 0; + +public: + format_object_base(const char *fmt) : Fmt(fmt) {} + virtual ~format_object_base() {} + + /// print - Format the object into the specified buffer. On success, this + /// returns the length of the formatted string. If the buffer is too small, + /// this returns a length to retry with, which will be larger than BufferSize. + unsigned print(char *Buffer, unsigned BufferSize) const { + assert(BufferSize && "Invalid buffer size!"); + + // Print the string, leaving room for the terminating null. + int N = snprint(Buffer, BufferSize); + + // VC++ and old GlibC return negative on overflow, just double the size. + if (N < 0) + return BufferSize*2; + + // Other impls yield number of bytes needed, not including the final '\0'. + if (unsigned(N) >= BufferSize) + return N+1; + + // Otherwise N is the length of output (not including the final '\0'). + return N; + } +}; + +/// format_object1 - This is a templated helper class used by the format +/// function that captures the object to be formated and the format string. When +/// actually printed, this synthesizes the string into a temporary buffer +/// provided and returns whether or not it is big enough. +template +class format_object1 : public format_object_base { + T Val; +public: + format_object1(const char *fmt, const T &val) + : format_object_base(fmt), Val(val) { + } + + virtual int snprint(char *Buffer, unsigned BufferSize) const { + return snprintf(Buffer, BufferSize, Fmt, Val); + } +}; + +/// format_object2 - This is a templated helper class used by the format +/// function that captures the object to be formated and the format string. When +/// actually printed, this synthesizes the string into a temporary buffer +/// provided and returns whether or not it is big enough. +template +class format_object2 : public format_object_base { + T1 Val1; + T2 Val2; +public: + format_object2(const char *fmt, const T1 &val1, const T2 &val2) + : format_object_base(fmt), Val1(val1), Val2(val2) { + } + + virtual int snprint(char *Buffer, unsigned BufferSize) const { + return snprintf(Buffer, BufferSize, Fmt, Val1, Val2); + } +}; + +/// format_object3 - This is a templated helper class used by the format +/// function that captures the object to be formated and the format string. When +/// actually printed, this synthesizes the string into a temporary buffer +/// provided and returns whether or not it is big enough. +template +class format_object3 : public format_object_base { + T1 Val1; + T2 Val2; + T3 Val3; +public: + format_object3(const char *fmt, const T1 &val1, const T2 &val2,const T3 &val3) + : format_object_base(fmt), Val1(val1), Val2(val2), Val3(val3) { + } + + virtual int snprint(char *Buffer, unsigned BufferSize) const { + return snprintf(Buffer, BufferSize, Fmt, Val1, Val2, Val3); + } +}; + +/// format - This is a helper function that is used to produce formatted output. +/// This is typically used like: OS << format("%0.4f", myfloat) << '\n'; +template +inline format_object1 format(const char *Fmt, const T &Val) { + return format_object1(Fmt, Val); +} + +/// format - This is a helper function that is used to produce formatted output. +/// This is typically used like: OS << format("%0.4f", myfloat) << '\n'; +template +inline format_object2 format(const char *Fmt, const T1 &Val1, + const T2 &Val2) { + return format_object2(Fmt, Val1, Val2); +} + +/// format - This is a helper function that is used to produce formatted output. +/// This is typically used like: OS << format("%0.4f", myfloat) << '\n'; +template + inline format_object3 format(const char *Fmt, const T1 &Val1, + const T2 &Val2, const T3 &Val3) { + return format_object3(Fmt, Val1, Val2, Val3); +} + +} // end namespace llvm + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Support/FormattedStream.h b/libclamav/c++/llvm/include/llvm/Support/FormattedStream.h new file mode 100644 index 000000000..24a354620 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Support/FormattedStream.h @@ -0,0 +1,150 @@ +//===-- llvm/CodeGen/FormattedStream.h - Formatted streams ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains raw_ostream implementations for streams to do +// things like pretty-print comments. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_FORMATTEDSTREAM_H +#define LLVM_SUPPORT_FORMATTEDSTREAM_H + +#include "llvm/Support/raw_ostream.h" + +namespace llvm +{ + /// formatted_raw_ostream - Formatted raw_fd_ostream to handle + /// asm-specific constructs. + /// + class formatted_raw_ostream : public raw_ostream { + public: + /// DELETE_STREAM - Tell the destructor to delete the held stream. + /// + static const bool DELETE_STREAM = true; + + /// PRESERVE_STREAM - Tell the destructor to not delete the held + /// stream. + /// + static const bool PRESERVE_STREAM = false; + + private: + /// TheStream - The real stream we output to. We set it to be + /// unbuffered, since we're already doing our own buffering. + /// + raw_ostream *TheStream; + + /// DeleteStream - Do we need to delete TheStream in the + /// destructor? + /// + bool DeleteStream; + + /// ColumnScanned - The current output column of the data that's + /// been flushed and the portion of the buffer that's been + /// scanned. The column scheme is zero-based. + /// + unsigned ColumnScanned; + + /// Scanned - This points to one past the last character in the + /// buffer we've scanned. + /// + const char *Scanned; + + virtual void write_impl(const char *Ptr, size_t Size); + + /// current_pos - Return the current position within the stream, + /// not counting the bytes currently in the buffer. + virtual uint64_t current_pos() { + // This has the same effect as calling TheStream.current_pos(), + // but that interface is private. + return TheStream->tell() - TheStream->GetNumBytesInBuffer(); + } + + /// ComputeColumn - Examine the given output buffer and figure out which + /// column we end up in after output. + /// + void ComputeColumn(const char *Ptr, size_t size); + + public: + /// formatted_raw_ostream - Open the specified file for + /// writing. If an error occurs, information about the error is + /// put into ErrorInfo, and the stream should be immediately + /// destroyed; the string will be empty if no error occurred. + /// + /// As a side effect, the given Stream is set to be Unbuffered. + /// This is because formatted_raw_ostream does its own buffering, + /// so it doesn't want another layer of buffering to be happening + /// underneath it. + /// + formatted_raw_ostream(raw_ostream &Stream, bool Delete = false) + : raw_ostream(), TheStream(0), DeleteStream(false), ColumnScanned(0) { + setStream(Stream, Delete); + } + explicit formatted_raw_ostream() + : raw_ostream(), TheStream(0), DeleteStream(false), ColumnScanned(0) { + Scanned = 0; + } + + ~formatted_raw_ostream() { + flush(); + releaseStream(); + } + + void setStream(raw_ostream &Stream, bool Delete = false) { + releaseStream(); + + TheStream = &Stream; + DeleteStream = Delete; + + // This formatted_raw_ostream inherits from raw_ostream, so it'll do its + // own buffering, and it doesn't need or want TheStream to do another + // layer of buffering underneath. Resize the buffer to what TheStream + // had been using, and tell TheStream not to do its own buffering. + if (size_t BufferSize = TheStream->GetBufferSize()) + SetBufferSize(BufferSize); + else + SetUnbuffered(); + TheStream->SetUnbuffered(); + + Scanned = 0; + } + + /// PadToColumn - Align the output to some column number. If the current + /// column is already equal to or more than NewCol, PadToColumn inserts one + /// space. + /// + /// \param NewCol - The column to move to. + void PadToColumn(unsigned NewCol); + + private: + void releaseStream() { + // Delete the stream if needed. Otherwise, transfer the buffer + // settings from this raw_ostream back to the underlying stream. + if (!TheStream) + return; + if (DeleteStream) + delete TheStream; + else if (size_t BufferSize = GetBufferSize()) + TheStream->SetBufferSize(BufferSize); + else + TheStream->SetUnbuffered(); + } + }; + +/// fouts() - This returns a reference to a formatted_raw_ostream for +/// standard output. Use it like: fouts() << "foo" << "bar"; +formatted_raw_ostream &fouts(); + +/// ferrs() - This returns a reference to a formatted_raw_ostream for +/// standard error. Use it like: ferrs() << "foo" << "bar"; +formatted_raw_ostream &ferrs(); + +} // end llvm namespace + + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Support/GetElementPtrTypeIterator.h b/libclamav/c++/llvm/include/llvm/Support/GetElementPtrTypeIterator.h new file mode 100644 index 000000000..f5915c992 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Support/GetElementPtrTypeIterator.h @@ -0,0 +1,113 @@ +//===- llvm/Support/GetElementPtrTypeIterator.h -----------------*- 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 an iterator for walking through the types indexed by +// getelementptr instructions. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_GETELEMENTPTRTYPE_H +#define LLVM_SUPPORT_GETELEMENTPTRTYPE_H + +#include "llvm/User.h" +#include "llvm/DerivedTypes.h" + +namespace llvm { + template + class generic_gep_type_iterator + : public std::iterator { + typedef std::iterator super; + + ItTy OpIt; + const Type *CurTy; + generic_gep_type_iterator() {} + public: + + static generic_gep_type_iterator begin(const Type *Ty, ItTy It) { + generic_gep_type_iterator I; + I.CurTy = Ty; + I.OpIt = It; + return I; + } + static generic_gep_type_iterator end(ItTy It) { + generic_gep_type_iterator I; + I.CurTy = 0; + I.OpIt = It; + return I; + } + + bool operator==(const generic_gep_type_iterator& x) const { + return OpIt == x.OpIt; + } + bool operator!=(const generic_gep_type_iterator& x) const { + return !operator==(x); + } + + const Type *operator*() const { + return CurTy; + } + + const Type *getIndexedType() const { + const CompositeType *CT = cast(CurTy); + return CT->getTypeAtIndex(getOperand()); + } + + // This is a non-standard operator->. It allows you to call methods on the + // current type directly. + const Type *operator->() const { return operator*(); } + + Value *getOperand() const { return *OpIt; } + + generic_gep_type_iterator& operator++() { // Preincrement + if (const CompositeType *CT = dyn_cast(CurTy)) { + CurTy = CT->getTypeAtIndex(getOperand()); + } else { + CurTy = 0; + } + ++OpIt; + return *this; + } + + generic_gep_type_iterator operator++(int) { // Postincrement + generic_gep_type_iterator tmp = *this; ++*this; return tmp; + } + }; + + typedef generic_gep_type_iterator<> gep_type_iterator; + + inline gep_type_iterator gep_type_begin(const User *GEP) { + return gep_type_iterator::begin(GEP->getOperand(0)->getType(), + GEP->op_begin()+1); + } + inline gep_type_iterator gep_type_end(const User *GEP) { + return gep_type_iterator::end(GEP->op_end()); + } + inline gep_type_iterator gep_type_begin(const User &GEP) { + return gep_type_iterator::begin(GEP.getOperand(0)->getType(), + GEP.op_begin()+1); + } + inline gep_type_iterator gep_type_end(const User &GEP) { + return gep_type_iterator::end(GEP.op_end()); + } + + template + inline generic_gep_type_iterator + gep_type_begin(const Type *Op0, ItTy I, ItTy E) { + return generic_gep_type_iterator::begin(Op0, I); + } + + template + inline generic_gep_type_iterator + gep_type_end(const Type *Op0, ItTy I, ItTy E) { + return generic_gep_type_iterator::end(E); + } +} // end namespace llvm + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Support/GraphWriter.h b/libclamav/c++/llvm/include/llvm/Support/GraphWriter.h new file mode 100644 index 000000000..bd3fcea11 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Support/GraphWriter.h @@ -0,0 +1,307 @@ +//===-- llvm/Support/GraphWriter.h - Write graph to a .dot file -*- 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 a simple interface that can be used to print out generic +// LLVM graphs to ".dot" files. "dot" is a tool that is part of the AT&T +// graphviz package (http://www.research.att.com/sw/tools/graphviz/) which can +// be used to turn the files output by this interface into a variety of +// different graphics formats. +// +// Graphs do not need to implement any interface past what is already required +// by the GraphTraits template, but they can choose to implement specializations +// of the DOTGraphTraits template if they want to customize the graphs output in +// any way. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_GRAPHWRITER_H +#define LLVM_SUPPORT_GRAPHWRITER_H + +#include "llvm/Support/DOTGraphTraits.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/ADT/GraphTraits.h" +#include "llvm/System/Path.h" +#include +#include + +namespace llvm { + +namespace DOT { // Private functions... + std::string EscapeString(const std::string &Label); +} + +namespace GraphProgram { + enum Name { + DOT, + FDP, + NEATO, + TWOPI, + CIRCO + }; +} + +void DisplayGraph(const sys::Path& Filename, bool wait=true, GraphProgram::Name program = GraphProgram::DOT); + +template +class GraphWriter { + raw_ostream &O; + const GraphType &G; + bool ShortNames; + + typedef DOTGraphTraits DOTTraits; + typedef GraphTraits GTraits; + typedef typename GTraits::NodeType NodeType; + typedef typename GTraits::nodes_iterator node_iterator; + typedef typename GTraits::ChildIteratorType child_iterator; +public: + GraphWriter(raw_ostream &o, const GraphType &g, bool SN) : + O(o), G(g), ShortNames(SN) {} + + void writeHeader(const std::string &Name) { + std::string GraphName = DOTTraits::getGraphName(G); + + if (!Name.empty()) + O << "digraph \"" << DOT::EscapeString(Name) << "\" {\n"; + else if (!GraphName.empty()) + O << "digraph \"" << DOT::EscapeString(GraphName) << "\" {\n"; + else + O << "digraph unnamed {\n"; + + if (DOTTraits::renderGraphFromBottomUp()) + O << "\trankdir=\"BT\";\n"; + + if (!Name.empty()) + O << "\tlabel=\"" << DOT::EscapeString(Name) << "\";\n"; + else if (!GraphName.empty()) + O << "\tlabel=\"" << DOT::EscapeString(GraphName) << "\";\n"; + O << DOTTraits::getGraphProperties(G); + O << "\n"; + } + + void writeFooter() { + // Finish off the graph + O << "}\n"; + } + + void writeNodes() { + // Loop over the graph, printing it out... + for (node_iterator I = GTraits::nodes_begin(G), E = GTraits::nodes_end(G); + I != E; ++I) + writeNode(*I); + } + + void writeNode(NodeType& Node) { + writeNode(&Node); + } + + void writeNode(NodeType *const *Node) { + writeNode(*Node); + } + + void writeNode(NodeType *Node) { + std::string NodeAttributes = DOTTraits::getNodeAttributes(Node, G); + + O << "\tNode" << static_cast(Node) << " [shape=record,"; + if (!NodeAttributes.empty()) O << NodeAttributes << ","; + O << "label=\"{"; + + if (!DOTTraits::renderGraphFromBottomUp()) { + O << DOT::EscapeString(DOTTraits::getNodeLabel(Node, G, ShortNames)); + + // If we should include the address of the node in the label, do so now. + if (DOTTraits::hasNodeAddressLabel(Node, G)) + O << "|" << (void*)Node; + } + + // Print out the fields of the current node... + child_iterator EI = GTraits::child_begin(Node); + child_iterator EE = GTraits::child_end(Node); + if (EI != EE) { + if (!DOTTraits::renderGraphFromBottomUp()) O << "|"; + O << "{"; + + for (unsigned i = 0; EI != EE && i != 64; ++EI, ++i) { + if (i) O << "|"; + O << "" << DOTTraits::getEdgeSourceLabel(Node, EI); + } + + if (EI != EE) + O << "|truncated..."; + O << "}"; + if (DOTTraits::renderGraphFromBottomUp()) O << "|"; + } + + if (DOTTraits::renderGraphFromBottomUp()) { + O << DOT::EscapeString(DOTTraits::getNodeLabel(Node, G, ShortNames)); + + // If we should include the address of the node in the label, do so now. + if (DOTTraits::hasNodeAddressLabel(Node, G)) + O << "|" << (void*)Node; + } + + if (DOTTraits::hasEdgeDestLabels()) { + O << "|{"; + + unsigned i = 0, e = DOTTraits::numEdgeDestLabels(Node); + for (; i != e && i != 64; ++i) { + if (i) O << "|"; + O << "" << DOTTraits::getEdgeDestLabel(Node, i); + } + + if (i != e) + O << "|truncated..."; + O << "}"; + } + + O << "}\"];\n"; // Finish printing the "node" line + + // Output all of the edges now + EI = GTraits::child_begin(Node); + for (unsigned i = 0; EI != EE && i != 64; ++EI, ++i) + writeEdge(Node, i, EI); + for (; EI != EE; ++EI) + writeEdge(Node, 64, EI); + } + + void writeEdge(NodeType *Node, unsigned edgeidx, child_iterator EI) { + if (NodeType *TargetNode = *EI) { + int DestPort = -1; + if (DOTTraits::edgeTargetsEdgeSource(Node, EI)) { + child_iterator TargetIt = DOTTraits::getEdgeTarget(Node, EI); + + // Figure out which edge this targets... + unsigned Offset = + (unsigned)std::distance(GTraits::child_begin(TargetNode), TargetIt); + DestPort = static_cast(Offset); + } + + emitEdge(static_cast(Node), edgeidx, + static_cast(TargetNode), DestPort, + DOTTraits::getEdgeAttributes(Node, EI)); + } + } + + /// emitSimpleNode - Outputs a simple (non-record) node + void emitSimpleNode(const void *ID, const std::string &Attr, + const std::string &Label, unsigned NumEdgeSources = 0, + const std::vector *EdgeSourceLabels = 0) { + O << "\tNode" << ID << "[ "; + if (!Attr.empty()) + O << Attr << ","; + O << " label =\""; + if (NumEdgeSources) O << "{"; + O << DOT::EscapeString(Label); + if (NumEdgeSources) { + O << "|{"; + + for (unsigned i = 0; i != NumEdgeSources; ++i) { + if (i) O << "|"; + O << ""; + if (EdgeSourceLabels) O << (*EdgeSourceLabels)[i]; + } + O << "}}"; + } + O << "\"];\n"; + } + + /// emitEdge - Output an edge from a simple node into the graph... + void emitEdge(const void *SrcNodeID, int SrcNodePort, + const void *DestNodeID, int DestNodePort, + const std::string &Attrs) { + if (SrcNodePort > 64) return; // Eminating from truncated part? + if (DestNodePort > 64) DestNodePort = 64; // Targetting the truncated part? + + O << "\tNode" << SrcNodeID; + if (SrcNodePort >= 0) + O << ":s" << SrcNodePort; + O << " -> Node" << DestNodeID; + if (DestNodePort >= 0) { + if (DOTTraits::hasEdgeDestLabels()) + O << ":d" << DestNodePort; + else + O << ":s" << DestNodePort; + } + + if (!Attrs.empty()) + O << "[" << Attrs << "]"; + O << ";\n"; + } +}; + +template +raw_ostream &WriteGraph(raw_ostream &O, const GraphType &G, + bool ShortNames = false, + const std::string &Name = "", + const std::string &Title = "") { + // Start the graph emission process... + GraphWriter W(O, G, ShortNames); + + // Output the header for the graph... + W.writeHeader(Title); + + // Emit all of the nodes in the graph... + W.writeNodes(); + + // Output any customizations on the graph + DOTGraphTraits::addCustomGraphFeatures(G, W); + + // Output the end of the graph + W.writeFooter(); + return O; +} + +template +sys::Path WriteGraph(const GraphType &G, const std::string &Name, + bool ShortNames = false, const std::string &Title = "") { + std::string ErrMsg; + sys::Path Filename = sys::Path::GetTemporaryDirectory(&ErrMsg); + if (Filename.isEmpty()) { + errs() << "Error: " << ErrMsg << "\n"; + return Filename; + } + Filename.appendComponent(Name + ".dot"); + if (Filename.makeUnique(true,&ErrMsg)) { + errs() << "Error: " << ErrMsg << "\n"; + return sys::Path(); + } + + errs() << "Writing '" << Filename.str() << "'... "; + + std::string ErrorInfo; + raw_fd_ostream O(Filename.c_str(), ErrorInfo); + + if (ErrorInfo.empty()) { + WriteGraph(O, G, ShortNames, Name, Title); + errs() << " done. \n"; + } else { + errs() << "error opening file '" << Filename.str() << "' for writing!\n"; + Filename.clear(); + } + + return Filename; +} + +/// ViewGraph - Emit a dot graph, run 'dot', run gv on the postscript file, +/// then cleanup. For use from the debugger. +/// +template +void ViewGraph(const GraphType &G, const std::string &Name, + bool ShortNames = false, const std::string &Title = "", + GraphProgram::Name Program = GraphProgram::DOT) { + sys::Path Filename = WriteGraph(G, Name, ShortNames, Title); + + if (Filename.isEmpty()) + return; + + DisplayGraph(Filename, true, Program); +} + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Support/IRBuilder.h b/libclamav/c++/llvm/include/llvm/Support/IRBuilder.h new file mode 100644 index 000000000..2db2477a9 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Support/IRBuilder.h @@ -0,0 +1,965 @@ +//===---- llvm/Support/IRBuilder.h - Builder for LLVM Instrs ----*- 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 the IRBuilder class, which is used as a convenient way +// to create LLVM instructions with a consistent and simplified interface. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_IRBUILDER_H +#define LLVM_SUPPORT_IRBUILDER_H + +#include "llvm/Constants.h" +#include "llvm/Instructions.h" +#include "llvm/GlobalAlias.h" +#include "llvm/GlobalVariable.h" +#include "llvm/Function.h" +#include "llvm/Metadata.h" +#include "llvm/LLVMContext.h" +#include "llvm/ADT/Twine.h" +#include "llvm/Support/ConstantFolder.h" + +namespace llvm { + +/// IRBuilderDefaultInserter - This provides the default implementation of the +/// IRBuilder 'InsertHelper' method that is called whenever an instruction is +/// created by IRBuilder and needs to be inserted. By default, this inserts the +/// instruction at the insertion point. +template +class IRBuilderDefaultInserter { +protected: + void InsertHelper(Instruction *I, const Twine &Name, + BasicBlock *BB, BasicBlock::iterator InsertPt) const { + if (BB) BB->getInstList().insert(InsertPt, I); + if (preserveNames) + I->setName(Name); + } +}; + + +/// IRBuilder - This provides a uniform API for creating instructions and +/// inserting them into a basic block: either at the end of a BasicBlock, or +/// at a specific iterator location in a block. +/// +/// Note that the builder does not expose the full generality of LLVM +/// instructions. For access to extra instruction properties, use the mutators +/// (e.g. setVolatile) on the instructions after they have been created. +/// The first template argument handles whether or not to preserve names in the +/// final instruction output. This defaults to on. The second template argument +/// specifies a class to use for creating constants. This defaults to creating +/// minimally folded constants. The fourth template argument allows clients to +/// specify custom insertion hooks that are called on every newly created +/// insertion. +template > +class IRBuilder : public Inserter { + BasicBlock *BB; + BasicBlock::iterator InsertPt; + unsigned MDKind; + MDNode *CurDbgLocation; + LLVMContext &Context; + T Folder; +public: + IRBuilder(LLVMContext &C, const T &F, const Inserter &I = Inserter()) + : Inserter(I), MDKind(0), CurDbgLocation(0), Context(C), Folder(F) { + ClearInsertionPoint(); + } + + explicit IRBuilder(LLVMContext &C) + : MDKind(0), CurDbgLocation(0), Context(C), Folder(C) { + ClearInsertionPoint(); + } + + explicit IRBuilder(BasicBlock *TheBB, const T &F) + : MDKind(0), CurDbgLocation(0), Context(TheBB->getContext()), Folder(F) { + SetInsertPoint(TheBB); + } + + explicit IRBuilder(BasicBlock *TheBB) + : MDKind(0), CurDbgLocation(0), Context(TheBB->getContext()), + Folder(Context) { + SetInsertPoint(TheBB); + } + + IRBuilder(BasicBlock *TheBB, BasicBlock::iterator IP, const T& F) + : MDKind(0), CurDbgLocation(0), Context(TheBB->getContext()), Folder(F) { + SetInsertPoint(TheBB, IP); + } + + IRBuilder(BasicBlock *TheBB, BasicBlock::iterator IP) + : MDKind(0), CurDbgLocation(0), Context(TheBB->getContext()), + Folder(Context) { + SetInsertPoint(TheBB, IP); + } + + /// getFolder - Get the constant folder being used. + const T &getFolder() { return Folder; } + + /// isNamePreserving - Return true if this builder is configured to actually + /// add the requested names to IR created through it. + bool isNamePreserving() const { return preserveNames; } + + //===--------------------------------------------------------------------===// + // Builder configuration methods + //===--------------------------------------------------------------------===// + + /// ClearInsertionPoint - Clear the insertion point: created instructions will + /// not be inserted into a block. + void ClearInsertionPoint() { + BB = 0; + } + + BasicBlock *GetInsertBlock() const { return BB; } + + BasicBlock::iterator GetInsertPoint() const { return InsertPt; } + + /// SetInsertPoint - This specifies that created instructions should be + /// appended to the end of the specified block. + void SetInsertPoint(BasicBlock *TheBB) { + BB = TheBB; + InsertPt = BB->end(); + } + + /// SetInsertPoint - This specifies that created instructions should be + /// inserted at the specified point. + void SetInsertPoint(BasicBlock *TheBB, BasicBlock::iterator IP) { + BB = TheBB; + InsertPt = IP; + } + + /// SetCurrentDebugLocation - Set location information used by debugging + /// information. + void SetCurrentDebugLocation(MDNode *L) { + if (MDKind == 0) + MDKind = Context.getMetadata().getMDKind("dbg"); + if (MDKind == 0) + MDKind = Context.getMetadata().registerMDKind("dbg"); + CurDbgLocation = L; + } + + MDNode *getCurrentDebugLocation() const { return CurDbgLocation; } + + /// SetDebugLocation - Set location information for the given instruction. + void SetDebugLocation(Instruction *I) { + if (CurDbgLocation) + Context.getMetadata().addMD(MDKind, CurDbgLocation, I); + } + + /// SetDebugLocation - Set location information for the given instruction. + void SetDebugLocation(Instruction *I, MDNode *Loc) { + if (MDKind == 0) + MDKind = Context.getMetadata().getMDKind("dbg"); + if (MDKind == 0) + MDKind = Context.getMetadata().registerMDKind("dbg"); + Context.getMetadata().addMD(MDKind, Loc, I); + } + + /// Insert - Insert and return the specified instruction. + template + InstTy *Insert(InstTy *I, const Twine &Name = "") const { + this->InsertHelper(I, Name, BB, InsertPt); + if (CurDbgLocation) + Context.getMetadata().addMD(MDKind, CurDbgLocation, I); + return I; + } + + //===--------------------------------------------------------------------===// + // Type creation methods + //===--------------------------------------------------------------------===// + + /// getInt1Ty - Fetch the type representing a single bit + const Type *getInt1Ty() { + return Type::getInt1Ty(Context); + } + + /// getInt8Ty - Fetch the type representing an 8-bit integer. + const Type *getInt8Ty() { + return Type::getInt8Ty(Context); + } + + /// getInt16Ty - Fetch the type representing a 16-bit integer. + const Type *getInt16Ty() { + return Type::getInt16Ty(Context); + } + + /// getInt32Ty - Fetch the type resepresenting a 32-bit integer. + const Type *getInt32Ty() { + return Type::getInt32Ty(Context); + } + + /// getInt64Ty - Fetch the type representing a 64-bit integer. + const Type *getInt64Ty() { + return Type::getInt64Ty(Context); + } + + /// getFloatTy - Fetch the type representing a 32-bit floating point value. + const Type *getFloatTy() { + return Type::getFloatTy(Context); + } + + /// getDoubleTy - Fetch the type representing a 64-bit floating point value. + const Type *getDoubleTy() { + return Type::getDoubleTy(Context); + } + + /// getVoidTy - Fetch the type representing void. + const Type *getVoidTy() { + return Type::getVoidTy(Context); + } + + //===--------------------------------------------------------------------===// + // Instruction creation methods: Terminators + //===--------------------------------------------------------------------===// + + /// CreateRetVoid - Create a 'ret void' instruction. + ReturnInst *CreateRetVoid() { + return Insert(ReturnInst::Create(Context)); + } + + /// @verbatim + /// CreateRet - Create a 'ret ' instruction. + /// @endverbatim + ReturnInst *CreateRet(Value *V) { + return Insert(ReturnInst::Create(Context, V)); + } + + /// CreateAggregateRet - Create a sequence of N insertvalue instructions, + /// with one Value from the retVals array each, that build a aggregate + /// return value one value at a time, and a ret instruction to return + /// the resulting aggregate value. This is a convenience function for + /// code that uses aggregate return values as a vehicle for having + /// multiple return values. + /// + ReturnInst *CreateAggregateRet(Value * const* retVals, unsigned N) { + const Type *RetType = BB->getParent()->getReturnType(); + Value *V = UndefValue::get(RetType); + for (unsigned i = 0; i != N; ++i) + V = CreateInsertValue(V, retVals[i], i, "mrv"); + return Insert(ReturnInst::Create(Context, V)); + } + + /// CreateBr - Create an unconditional 'br label X' instruction. + BranchInst *CreateBr(BasicBlock *Dest) { + return Insert(BranchInst::Create(Dest)); + } + + /// CreateCondBr - Create a conditional 'br Cond, TrueDest, FalseDest' + /// instruction. + BranchInst *CreateCondBr(Value *Cond, BasicBlock *True, BasicBlock *False) { + return Insert(BranchInst::Create(True, False, Cond)); + } + + /// CreateSwitch - Create a switch instruction with the specified value, + /// default dest, and with a hint for the number of cases that will be added + /// (for efficient allocation). + SwitchInst *CreateSwitch(Value *V, BasicBlock *Dest, unsigned NumCases = 10) { + return Insert(SwitchInst::Create(V, Dest, NumCases)); + } + + /// CreateIndirectBr - Create an indirect branch instruction with the + /// specified address operand, with an optional hint for the number of + /// destinations that will be added (for efficient allocation). + IndirectBrInst *CreateIndirectBr(Value *Addr, unsigned NumDests = 10) { + return Insert(IndirectBrInst::Create(Addr, NumDests)); + } + + /// CreateInvoke - Create an invoke instruction. + template + InvokeInst *CreateInvoke(Value *Callee, BasicBlock *NormalDest, + BasicBlock *UnwindDest, InputIterator ArgBegin, + InputIterator ArgEnd, const Twine &Name = "") { + return Insert(InvokeInst::Create(Callee, NormalDest, UnwindDest, + ArgBegin, ArgEnd), Name); + } + + UnwindInst *CreateUnwind() { + return Insert(new UnwindInst(Context)); + } + + UnreachableInst *CreateUnreachable() { + return Insert(new UnreachableInst(Context)); + } + + //===--------------------------------------------------------------------===// + // Instruction creation methods: Binary Operators + //===--------------------------------------------------------------------===// + + Value *CreateAdd(Value *LHS, Value *RHS, const Twine &Name = "") { + if (Constant *LC = dyn_cast(LHS)) + if (Constant *RC = dyn_cast(RHS)) + return Folder.CreateAdd(LC, RC); + return Insert(BinaryOperator::CreateAdd(LHS, RHS), Name); + } + Value *CreateNSWAdd(Value *LHS, Value *RHS, const Twine &Name = "") { + if (Constant *LC = dyn_cast(LHS)) + if (Constant *RC = dyn_cast(RHS)) + return Folder.CreateNSWAdd(LC, RC); + return Insert(BinaryOperator::CreateNSWAdd(LHS, RHS), Name); + } + Value *CreateFAdd(Value *LHS, Value *RHS, const Twine &Name = "") { + if (Constant *LC = dyn_cast(LHS)) + if (Constant *RC = dyn_cast(RHS)) + return Folder.CreateFAdd(LC, RC); + return Insert(BinaryOperator::CreateFAdd(LHS, RHS), Name); + } + Value *CreateSub(Value *LHS, Value *RHS, const Twine &Name = "") { + if (Constant *LC = dyn_cast(LHS)) + if (Constant *RC = dyn_cast(RHS)) + return Folder.CreateSub(LC, RC); + return Insert(BinaryOperator::CreateSub(LHS, RHS), Name); + } + Value *CreateNSWSub(Value *LHS, Value *RHS, const Twine &Name = "") { + if (Constant *LC = dyn_cast(LHS)) + if (Constant *RC = dyn_cast(RHS)) + return Folder.CreateNSWSub(LC, RC); + return Insert(BinaryOperator::CreateNSWSub(LHS, RHS), Name); + } + Value *CreateFSub(Value *LHS, Value *RHS, const Twine &Name = "") { + if (Constant *LC = dyn_cast(LHS)) + if (Constant *RC = dyn_cast(RHS)) + return Folder.CreateFSub(LC, RC); + return Insert(BinaryOperator::CreateFSub(LHS, RHS), Name); + } + Value *CreateMul(Value *LHS, Value *RHS, const Twine &Name = "") { + if (Constant *LC = dyn_cast(LHS)) + if (Constant *RC = dyn_cast(RHS)) + return Folder.CreateMul(LC, RC); + return Insert(BinaryOperator::CreateMul(LHS, RHS), Name); + } + Value *CreateFMul(Value *LHS, Value *RHS, const Twine &Name = "") { + if (Constant *LC = dyn_cast(LHS)) + if (Constant *RC = dyn_cast(RHS)) + return Folder.CreateFMul(LC, RC); + return Insert(BinaryOperator::CreateFMul(LHS, RHS), Name); + } + Value *CreateUDiv(Value *LHS, Value *RHS, const Twine &Name = "") { + if (Constant *LC = dyn_cast(LHS)) + if (Constant *RC = dyn_cast(RHS)) + return Folder.CreateUDiv(LC, RC); + return Insert(BinaryOperator::CreateUDiv(LHS, RHS), Name); + } + Value *CreateSDiv(Value *LHS, Value *RHS, const Twine &Name = "") { + if (Constant *LC = dyn_cast(LHS)) + if (Constant *RC = dyn_cast(RHS)) + return Folder.CreateSDiv(LC, RC); + return Insert(BinaryOperator::CreateSDiv(LHS, RHS), Name); + } + Value *CreateExactSDiv(Value *LHS, Value *RHS, const Twine &Name = "") { + if (Constant *LC = dyn_cast(LHS)) + if (Constant *RC = dyn_cast(RHS)) + return Folder.CreateExactSDiv(LC, RC); + return Insert(BinaryOperator::CreateExactSDiv(LHS, RHS), Name); + } + Value *CreateFDiv(Value *LHS, Value *RHS, const Twine &Name = "") { + if (Constant *LC = dyn_cast(LHS)) + if (Constant *RC = dyn_cast(RHS)) + return Folder.CreateFDiv(LC, RC); + return Insert(BinaryOperator::CreateFDiv(LHS, RHS), Name); + } + Value *CreateURem(Value *LHS, Value *RHS, const Twine &Name = "") { + if (Constant *LC = dyn_cast(LHS)) + if (Constant *RC = dyn_cast(RHS)) + return Folder.CreateURem(LC, RC); + return Insert(BinaryOperator::CreateURem(LHS, RHS), Name); + } + Value *CreateSRem(Value *LHS, Value *RHS, const Twine &Name = "") { + if (Constant *LC = dyn_cast(LHS)) + if (Constant *RC = dyn_cast(RHS)) + return Folder.CreateSRem(LC, RC); + return Insert(BinaryOperator::CreateSRem(LHS, RHS), Name); + } + Value *CreateFRem(Value *LHS, Value *RHS, const Twine &Name = "") { + if (Constant *LC = dyn_cast(LHS)) + if (Constant *RC = dyn_cast(RHS)) + return Folder.CreateFRem(LC, RC); + return Insert(BinaryOperator::CreateFRem(LHS, RHS), Name); + } + Value *CreateShl(Value *LHS, Value *RHS, const Twine &Name = "") { + if (Constant *LC = dyn_cast(LHS)) + if (Constant *RC = dyn_cast(RHS)) + return Folder.CreateShl(LC, RC); + return Insert(BinaryOperator::CreateShl(LHS, RHS), Name); + } + Value *CreateLShr(Value *LHS, Value *RHS, const Twine &Name = "") { + if (Constant *LC = dyn_cast(LHS)) + if (Constant *RC = dyn_cast(RHS)) + return Folder.CreateLShr(LC, RC); + return Insert(BinaryOperator::CreateLShr(LHS, RHS), Name); + } + Value *CreateAShr(Value *LHS, Value *RHS, const Twine &Name = "") { + if (Constant *LC = dyn_cast(LHS)) + if (Constant *RC = dyn_cast(RHS)) + return Folder.CreateAShr(LC, RC); + return Insert(BinaryOperator::CreateAShr(LHS, RHS), Name); + } + Value *CreateAnd(Value *LHS, Value *RHS, const Twine &Name = "") { + if (Constant *RC = dyn_cast(RHS)) { + if (isa(RC) && cast(RC)->isAllOnesValue()) + return LHS; // LHS & -1 -> LHS + if (Constant *LC = dyn_cast(LHS)) + return Folder.CreateAnd(LC, RC); + } + return Insert(BinaryOperator::CreateAnd(LHS, RHS), Name); + } + Value *CreateOr(Value *LHS, Value *RHS, const Twine &Name = "") { + if (Constant *RC = dyn_cast(RHS)) { + if (RC->isNullValue()) + return LHS; // LHS | 0 -> LHS + if (Constant *LC = dyn_cast(LHS)) + return Folder.CreateOr(LC, RC); + } + return Insert(BinaryOperator::CreateOr(LHS, RHS), Name); + } + Value *CreateXor(Value *LHS, Value *RHS, const Twine &Name = "") { + if (Constant *LC = dyn_cast(LHS)) + if (Constant *RC = dyn_cast(RHS)) + return Folder.CreateXor(LC, RC); + return Insert(BinaryOperator::CreateXor(LHS, RHS), Name); + } + + Value *CreateBinOp(Instruction::BinaryOps Opc, + Value *LHS, Value *RHS, const Twine &Name = "") { + if (Constant *LC = dyn_cast(LHS)) + if (Constant *RC = dyn_cast(RHS)) + return Folder.CreateBinOp(Opc, LC, RC); + return Insert(BinaryOperator::Create(Opc, LHS, RHS), Name); + } + + Value *CreateNeg(Value *V, const Twine &Name = "") { + if (Constant *VC = dyn_cast(V)) + return Folder.CreateNeg(VC); + return Insert(BinaryOperator::CreateNeg(V), Name); + } + Value *CreateFNeg(Value *V, const Twine &Name = "") { + if (Constant *VC = dyn_cast(V)) + return Folder.CreateFNeg(VC); + return Insert(BinaryOperator::CreateFNeg(V), Name); + } + Value *CreateNot(Value *V, const Twine &Name = "") { + if (Constant *VC = dyn_cast(V)) + return Folder.CreateNot(VC); + return Insert(BinaryOperator::CreateNot(V), Name); + } + + //===--------------------------------------------------------------------===// + // Instruction creation methods: Memory Instructions + //===--------------------------------------------------------------------===// + + AllocaInst *CreateAlloca(const Type *Ty, Value *ArraySize = 0, + const Twine &Name = "") { + return Insert(new AllocaInst(Ty, ArraySize), Name); + } + // Provided to resolve 'CreateLoad(Ptr, "...")' correctly, instead of + // converting the string to 'bool' for the isVolatile parameter. + LoadInst *CreateLoad(Value *Ptr, const char *Name) { + return Insert(new LoadInst(Ptr), Name); + } + LoadInst *CreateLoad(Value *Ptr, const Twine &Name = "") { + return Insert(new LoadInst(Ptr), Name); + } + LoadInst *CreateLoad(Value *Ptr, bool isVolatile, const Twine &Name = "") { + return Insert(new LoadInst(Ptr, 0, isVolatile), Name); + } + StoreInst *CreateStore(Value *Val, Value *Ptr, bool isVolatile = false) { + return Insert(new StoreInst(Val, Ptr, isVolatile)); + } + template + Value *CreateGEP(Value *Ptr, InputIterator IdxBegin, InputIterator IdxEnd, + const Twine &Name = "") { + if (Constant *PC = dyn_cast(Ptr)) { + // Every index must be constant. + InputIterator i; + for (i = IdxBegin; i < IdxEnd; ++i) + if (!isa(*i)) + break; + if (i == IdxEnd) + return Folder.CreateGetElementPtr(PC, &IdxBegin[0], IdxEnd - IdxBegin); + } + return Insert(GetElementPtrInst::Create(Ptr, IdxBegin, IdxEnd), Name); + } + template + Value *CreateInBoundsGEP(Value *Ptr, InputIterator IdxBegin, InputIterator IdxEnd, + const Twine &Name = "") { + if (Constant *PC = dyn_cast(Ptr)) { + // Every index must be constant. + InputIterator i; + for (i = IdxBegin; i < IdxEnd; ++i) + if (!isa(*i)) + break; + if (i == IdxEnd) + return Folder.CreateInBoundsGetElementPtr(PC, + &IdxBegin[0], + IdxEnd - IdxBegin); + } + return Insert(GetElementPtrInst::CreateInBounds(Ptr, IdxBegin, IdxEnd), + Name); + } + Value *CreateGEP(Value *Ptr, Value *Idx, const Twine &Name = "") { + if (Constant *PC = dyn_cast(Ptr)) + if (Constant *IC = dyn_cast(Idx)) + return Folder.CreateGetElementPtr(PC, &IC, 1); + return Insert(GetElementPtrInst::Create(Ptr, Idx), Name); + } + Value *CreateInBoundsGEP(Value *Ptr, Value *Idx, const Twine &Name = "") { + if (Constant *PC = dyn_cast(Ptr)) + if (Constant *IC = dyn_cast(Idx)) + return Folder.CreateInBoundsGetElementPtr(PC, &IC, 1); + return Insert(GetElementPtrInst::CreateInBounds(Ptr, Idx), Name); + } + Value *CreateConstGEP1_32(Value *Ptr, unsigned Idx0, const Twine &Name = "") { + Value *Idx = ConstantInt::get(Type::getInt32Ty(Context), Idx0); + + if (Constant *PC = dyn_cast(Ptr)) + return Folder.CreateGetElementPtr(PC, &Idx, 1); + + return Insert(GetElementPtrInst::Create(Ptr, &Idx, &Idx+1), Name); + } + Value *CreateConstInBoundsGEP1_32(Value *Ptr, unsigned Idx0, + const Twine &Name = "") { + Value *Idx = ConstantInt::get(Type::getInt32Ty(Context), Idx0); + + if (Constant *PC = dyn_cast(Ptr)) + return Folder.CreateInBoundsGetElementPtr(PC, &Idx, 1); + + return Insert(GetElementPtrInst::CreateInBounds(Ptr, &Idx, &Idx+1), Name); + } + Value *CreateConstGEP2_32(Value *Ptr, unsigned Idx0, unsigned Idx1, + const Twine &Name = "") { + Value *Idxs[] = { + ConstantInt::get(Type::getInt32Ty(Context), Idx0), + ConstantInt::get(Type::getInt32Ty(Context), Idx1) + }; + + if (Constant *PC = dyn_cast(Ptr)) + return Folder.CreateGetElementPtr(PC, Idxs, 2); + + return Insert(GetElementPtrInst::Create(Ptr, Idxs, Idxs+2), Name); + } + Value *CreateConstInBoundsGEP2_32(Value *Ptr, unsigned Idx0, unsigned Idx1, + const Twine &Name = "") { + Value *Idxs[] = { + ConstantInt::get(Type::getInt32Ty(Context), Idx0), + ConstantInt::get(Type::getInt32Ty(Context), Idx1) + }; + + if (Constant *PC = dyn_cast(Ptr)) + return Folder.CreateInBoundsGetElementPtr(PC, Idxs, 2); + + return Insert(GetElementPtrInst::CreateInBounds(Ptr, Idxs, Idxs+2), Name); + } + Value *CreateConstGEP1_64(Value *Ptr, uint64_t Idx0, const Twine &Name = "") { + Value *Idx = ConstantInt::get(Type::getInt64Ty(Context), Idx0); + + if (Constant *PC = dyn_cast(Ptr)) + return Folder.CreateGetElementPtr(PC, &Idx, 1); + + return Insert(GetElementPtrInst::Create(Ptr, &Idx, &Idx+1), Name); + } + Value *CreateConstInBoundsGEP1_64(Value *Ptr, uint64_t Idx0, + const Twine &Name = "") { + Value *Idx = ConstantInt::get(Type::getInt64Ty(Context), Idx0); + + if (Constant *PC = dyn_cast(Ptr)) + return Folder.CreateInBoundsGetElementPtr(PC, &Idx, 1); + + return Insert(GetElementPtrInst::CreateInBounds(Ptr, &Idx, &Idx+1), Name); + } + Value *CreateConstGEP2_64(Value *Ptr, uint64_t Idx0, uint64_t Idx1, + const Twine &Name = "") { + Value *Idxs[] = { + ConstantInt::get(Type::getInt64Ty(Context), Idx0), + ConstantInt::get(Type::getInt64Ty(Context), Idx1) + }; + + if (Constant *PC = dyn_cast(Ptr)) + return Folder.CreateGetElementPtr(PC, Idxs, 2); + + return Insert(GetElementPtrInst::Create(Ptr, Idxs, Idxs+2), Name); + } + Value *CreateConstInBoundsGEP2_64(Value *Ptr, uint64_t Idx0, uint64_t Idx1, + const Twine &Name = "") { + Value *Idxs[] = { + ConstantInt::get(Type::getInt64Ty(Context), Idx0), + ConstantInt::get(Type::getInt64Ty(Context), Idx1) + }; + + if (Constant *PC = dyn_cast(Ptr)) + return Folder.CreateInBoundsGetElementPtr(PC, Idxs, 2); + + return Insert(GetElementPtrInst::CreateInBounds(Ptr, Idxs, Idxs+2), Name); + } + Value *CreateStructGEP(Value *Ptr, unsigned Idx, const Twine &Name = "") { + return CreateConstInBoundsGEP2_32(Ptr, 0, Idx, Name); + } + Value *CreateGlobalString(const char *Str = "", const Twine &Name = "") { + Constant *StrConstant = ConstantArray::get(Context, Str, true); + Module &M = *BB->getParent()->getParent(); + GlobalVariable *gv = new GlobalVariable(M, + StrConstant->getType(), + true, + GlobalValue::InternalLinkage, + StrConstant, + "", + 0, + false); + gv->setName(Name); + return gv; + } + Value *CreateGlobalStringPtr(const char *Str = "", const Twine &Name = "") { + Value *gv = CreateGlobalString(Str, Name); + Value *zero = ConstantInt::get(Type::getInt32Ty(Context), 0); + Value *Args[] = { zero, zero }; + return CreateInBoundsGEP(gv, Args, Args+2, Name); + } + //===--------------------------------------------------------------------===// + // Instruction creation methods: Cast/Conversion Operators + //===--------------------------------------------------------------------===// + + Value *CreateTrunc(Value *V, const Type *DestTy, const Twine &Name = "") { + return CreateCast(Instruction::Trunc, V, DestTy, Name); + } + Value *CreateZExt(Value *V, const Type *DestTy, const Twine &Name = "") { + return CreateCast(Instruction::ZExt, V, DestTy, Name); + } + Value *CreateSExt(Value *V, const Type *DestTy, const Twine &Name = "") { + return CreateCast(Instruction::SExt, V, DestTy, Name); + } + Value *CreateFPToUI(Value *V, const Type *DestTy, const Twine &Name = ""){ + return CreateCast(Instruction::FPToUI, V, DestTy, Name); + } + Value *CreateFPToSI(Value *V, const Type *DestTy, const Twine &Name = ""){ + return CreateCast(Instruction::FPToSI, V, DestTy, Name); + } + Value *CreateUIToFP(Value *V, const Type *DestTy, const Twine &Name = ""){ + return CreateCast(Instruction::UIToFP, V, DestTy, Name); + } + Value *CreateSIToFP(Value *V, const Type *DestTy, const Twine &Name = ""){ + return CreateCast(Instruction::SIToFP, V, DestTy, Name); + } + Value *CreateFPTrunc(Value *V, const Type *DestTy, + const Twine &Name = "") { + return CreateCast(Instruction::FPTrunc, V, DestTy, Name); + } + Value *CreateFPExt(Value *V, const Type *DestTy, const Twine &Name = "") { + return CreateCast(Instruction::FPExt, V, DestTy, Name); + } + Value *CreatePtrToInt(Value *V, const Type *DestTy, + const Twine &Name = "") { + return CreateCast(Instruction::PtrToInt, V, DestTy, Name); + } + Value *CreateIntToPtr(Value *V, const Type *DestTy, + const Twine &Name = "") { + return CreateCast(Instruction::IntToPtr, V, DestTy, Name); + } + Value *CreateBitCast(Value *V, const Type *DestTy, + const Twine &Name = "") { + return CreateCast(Instruction::BitCast, V, DestTy, Name); + } + Value *CreateZExtOrBitCast(Value *V, const Type *DestTy, + const Twine &Name = "") { + if (V->getType() == DestTy) + return V; + if (Constant *VC = dyn_cast(V)) + return Folder.CreateZExtOrBitCast(VC, DestTy); + return Insert(CastInst::CreateZExtOrBitCast(V, DestTy), Name); + } + Value *CreateSExtOrBitCast(Value *V, const Type *DestTy, + const Twine &Name = "") { + if (V->getType() == DestTy) + return V; + if (Constant *VC = dyn_cast(V)) + return Folder.CreateSExtOrBitCast(VC, DestTy); + return Insert(CastInst::CreateSExtOrBitCast(V, DestTy), Name); + } + Value *CreateTruncOrBitCast(Value *V, const Type *DestTy, + const Twine &Name = "") { + if (V->getType() == DestTy) + return V; + if (Constant *VC = dyn_cast(V)) + return Folder.CreateTruncOrBitCast(VC, DestTy); + return Insert(CastInst::CreateTruncOrBitCast(V, DestTy), Name); + } + Value *CreateCast(Instruction::CastOps Op, Value *V, const Type *DestTy, + const Twine &Name = "") { + if (V->getType() == DestTy) + return V; + if (Constant *VC = dyn_cast(V)) + return Folder.CreateCast(Op, VC, DestTy); + return Insert(CastInst::Create(Op, V, DestTy), Name); + } + Value *CreatePointerCast(Value *V, const Type *DestTy, + const Twine &Name = "") { + if (V->getType() == DestTy) + return V; + if (Constant *VC = dyn_cast(V)) + return Folder.CreatePointerCast(VC, DestTy); + return Insert(CastInst::CreatePointerCast(V, DestTy), Name); + } + Value *CreateIntCast(Value *V, const Type *DestTy, bool isSigned, + const Twine &Name = "") { + if (V->getType() == DestTy) + return V; + if (Constant *VC = dyn_cast(V)) + return Folder.CreateIntCast(VC, DestTy, isSigned); + return Insert(CastInst::CreateIntegerCast(V, DestTy, isSigned), Name); + } +private: + // Provided to resolve 'CreateIntCast(Ptr, Ptr, "...")', giving a compile time + // error, instead of converting the string to bool for the isSigned parameter. + Value *CreateIntCast(Value *, const Type *, const char *); // DO NOT IMPLEMENT +public: + Value *CreateFPCast(Value *V, const Type *DestTy, const Twine &Name = "") { + if (V->getType() == DestTy) + return V; + if (Constant *VC = dyn_cast(V)) + return Folder.CreateFPCast(VC, DestTy); + return Insert(CastInst::CreateFPCast(V, DestTy), Name); + } + + //===--------------------------------------------------------------------===// + // Instruction creation methods: Compare Instructions + //===--------------------------------------------------------------------===// + + Value *CreateICmpEQ(Value *LHS, Value *RHS, const Twine &Name = "") { + return CreateICmp(ICmpInst::ICMP_EQ, LHS, RHS, Name); + } + Value *CreateICmpNE(Value *LHS, Value *RHS, const Twine &Name = "") { + return CreateICmp(ICmpInst::ICMP_NE, LHS, RHS, Name); + } + Value *CreateICmpUGT(Value *LHS, Value *RHS, const Twine &Name = "") { + return CreateICmp(ICmpInst::ICMP_UGT, LHS, RHS, Name); + } + Value *CreateICmpUGE(Value *LHS, Value *RHS, const Twine &Name = "") { + return CreateICmp(ICmpInst::ICMP_UGE, LHS, RHS, Name); + } + Value *CreateICmpULT(Value *LHS, Value *RHS, const Twine &Name = "") { + return CreateICmp(ICmpInst::ICMP_ULT, LHS, RHS, Name); + } + Value *CreateICmpULE(Value *LHS, Value *RHS, const Twine &Name = "") { + return CreateICmp(ICmpInst::ICMP_ULE, LHS, RHS, Name); + } + Value *CreateICmpSGT(Value *LHS, Value *RHS, const Twine &Name = "") { + return CreateICmp(ICmpInst::ICMP_SGT, LHS, RHS, Name); + } + Value *CreateICmpSGE(Value *LHS, Value *RHS, const Twine &Name = "") { + return CreateICmp(ICmpInst::ICMP_SGE, LHS, RHS, Name); + } + Value *CreateICmpSLT(Value *LHS, Value *RHS, const Twine &Name = "") { + return CreateICmp(ICmpInst::ICMP_SLT, LHS, RHS, Name); + } + Value *CreateICmpSLE(Value *LHS, Value *RHS, const Twine &Name = "") { + return CreateICmp(ICmpInst::ICMP_SLE, LHS, RHS, Name); + } + + Value *CreateFCmpOEQ(Value *LHS, Value *RHS, const Twine &Name = "") { + return CreateFCmp(FCmpInst::FCMP_OEQ, LHS, RHS, Name); + } + Value *CreateFCmpOGT(Value *LHS, Value *RHS, const Twine &Name = "") { + return CreateFCmp(FCmpInst::FCMP_OGT, LHS, RHS, Name); + } + Value *CreateFCmpOGE(Value *LHS, Value *RHS, const Twine &Name = "") { + return CreateFCmp(FCmpInst::FCMP_OGE, LHS, RHS, Name); + } + Value *CreateFCmpOLT(Value *LHS, Value *RHS, const Twine &Name = "") { + return CreateFCmp(FCmpInst::FCMP_OLT, LHS, RHS, Name); + } + Value *CreateFCmpOLE(Value *LHS, Value *RHS, const Twine &Name = "") { + return CreateFCmp(FCmpInst::FCMP_OLE, LHS, RHS, Name); + } + Value *CreateFCmpONE(Value *LHS, Value *RHS, const Twine &Name = "") { + return CreateFCmp(FCmpInst::FCMP_ONE, LHS, RHS, Name); + } + Value *CreateFCmpORD(Value *LHS, Value *RHS, const Twine &Name = "") { + return CreateFCmp(FCmpInst::FCMP_ORD, LHS, RHS, Name); + } + Value *CreateFCmpUNO(Value *LHS, Value *RHS, const Twine &Name = "") { + return CreateFCmp(FCmpInst::FCMP_UNO, LHS, RHS, Name); + } + Value *CreateFCmpUEQ(Value *LHS, Value *RHS, const Twine &Name = "") { + return CreateFCmp(FCmpInst::FCMP_UEQ, LHS, RHS, Name); + } + Value *CreateFCmpUGT(Value *LHS, Value *RHS, const Twine &Name = "") { + return CreateFCmp(FCmpInst::FCMP_UGT, LHS, RHS, Name); + } + Value *CreateFCmpUGE(Value *LHS, Value *RHS, const Twine &Name = "") { + return CreateFCmp(FCmpInst::FCMP_UGE, LHS, RHS, Name); + } + Value *CreateFCmpULT(Value *LHS, Value *RHS, const Twine &Name = "") { + return CreateFCmp(FCmpInst::FCMP_ULT, LHS, RHS, Name); + } + Value *CreateFCmpULE(Value *LHS, Value *RHS, const Twine &Name = "") { + return CreateFCmp(FCmpInst::FCMP_ULE, LHS, RHS, Name); + } + Value *CreateFCmpUNE(Value *LHS, Value *RHS, const Twine &Name = "") { + return CreateFCmp(FCmpInst::FCMP_UNE, LHS, RHS, Name); + } + + Value *CreateICmp(CmpInst::Predicate P, Value *LHS, Value *RHS, + const Twine &Name = "") { + if (Constant *LC = dyn_cast(LHS)) + if (Constant *RC = dyn_cast(RHS)) + return Folder.CreateICmp(P, LC, RC); + return Insert(new ICmpInst(P, LHS, RHS), Name); + } + Value *CreateFCmp(CmpInst::Predicate P, Value *LHS, Value *RHS, + const Twine &Name = "") { + if (Constant *LC = dyn_cast(LHS)) + if (Constant *RC = dyn_cast(RHS)) + return Folder.CreateFCmp(P, LC, RC); + return Insert(new FCmpInst(P, LHS, RHS), Name); + } + + //===--------------------------------------------------------------------===// + // Instruction creation methods: Other Instructions + //===--------------------------------------------------------------------===// + + PHINode *CreatePHI(const Type *Ty, const Twine &Name = "") { + return Insert(PHINode::Create(Ty), Name); + } + + CallInst *CreateCall(Value *Callee, const Twine &Name = "") { + return Insert(CallInst::Create(Callee), Name); + } + CallInst *CreateCall(Value *Callee, Value *Arg, const Twine &Name = "") { + return Insert(CallInst::Create(Callee, Arg), Name); + } + CallInst *CreateCall2(Value *Callee, Value *Arg1, Value *Arg2, + const Twine &Name = "") { + Value *Args[] = { Arg1, Arg2 }; + return Insert(CallInst::Create(Callee, Args, Args+2), Name); + } + CallInst *CreateCall3(Value *Callee, Value *Arg1, Value *Arg2, Value *Arg3, + const Twine &Name = "") { + Value *Args[] = { Arg1, Arg2, Arg3 }; + return Insert(CallInst::Create(Callee, Args, Args+3), Name); + } + CallInst *CreateCall4(Value *Callee, Value *Arg1, Value *Arg2, Value *Arg3, + Value *Arg4, const Twine &Name = "") { + Value *Args[] = { Arg1, Arg2, Arg3, Arg4 }; + return Insert(CallInst::Create(Callee, Args, Args+4), Name); + } + + template + CallInst *CreateCall(Value *Callee, InputIterator ArgBegin, + InputIterator ArgEnd, const Twine &Name = "") { + return Insert(CallInst::Create(Callee, ArgBegin, ArgEnd), Name); + } + + Value *CreateSelect(Value *C, Value *True, Value *False, + const Twine &Name = "") { + if (Constant *CC = dyn_cast(C)) + if (Constant *TC = dyn_cast(True)) + if (Constant *FC = dyn_cast(False)) + return Folder.CreateSelect(CC, TC, FC); + return Insert(SelectInst::Create(C, True, False), Name); + } + + VAArgInst *CreateVAArg(Value *List, const Type *Ty, const Twine &Name = "") { + return Insert(new VAArgInst(List, Ty), Name); + } + + Value *CreateExtractElement(Value *Vec, Value *Idx, + const Twine &Name = "") { + if (Constant *VC = dyn_cast(Vec)) + if (Constant *IC = dyn_cast(Idx)) + return Folder.CreateExtractElement(VC, IC); + return Insert(ExtractElementInst::Create(Vec, Idx), Name); + } + + Value *CreateInsertElement(Value *Vec, Value *NewElt, Value *Idx, + const Twine &Name = "") { + if (Constant *VC = dyn_cast(Vec)) + if (Constant *NC = dyn_cast(NewElt)) + if (Constant *IC = dyn_cast(Idx)) + return Folder.CreateInsertElement(VC, NC, IC); + return Insert(InsertElementInst::Create(Vec, NewElt, Idx), Name); + } + + Value *CreateShuffleVector(Value *V1, Value *V2, Value *Mask, + const Twine &Name = "") { + if (Constant *V1C = dyn_cast(V1)) + if (Constant *V2C = dyn_cast(V2)) + if (Constant *MC = dyn_cast(Mask)) + return Folder.CreateShuffleVector(V1C, V2C, MC); + return Insert(new ShuffleVectorInst(V1, V2, Mask), Name); + } + + Value *CreateExtractValue(Value *Agg, unsigned Idx, + const Twine &Name = "") { + if (Constant *AggC = dyn_cast(Agg)) + return Folder.CreateExtractValue(AggC, &Idx, 1); + return Insert(ExtractValueInst::Create(Agg, Idx), Name); + } + + template + Value *CreateExtractValue(Value *Agg, + InputIterator IdxBegin, + InputIterator IdxEnd, + const Twine &Name = "") { + if (Constant *AggC = dyn_cast(Agg)) + return Folder.CreateExtractValue(AggC, IdxBegin, IdxEnd - IdxBegin); + return Insert(ExtractValueInst::Create(Agg, IdxBegin, IdxEnd), Name); + } + + Value *CreateInsertValue(Value *Agg, Value *Val, unsigned Idx, + const Twine &Name = "") { + if (Constant *AggC = dyn_cast(Agg)) + if (Constant *ValC = dyn_cast(Val)) + return Folder.CreateInsertValue(AggC, ValC, &Idx, 1); + return Insert(InsertValueInst::Create(Agg, Val, Idx), Name); + } + + template + Value *CreateInsertValue(Value *Agg, Value *Val, + InputIterator IdxBegin, + InputIterator IdxEnd, + const Twine &Name = "") { + if (Constant *AggC = dyn_cast(Agg)) + if (Constant *ValC = dyn_cast(Val)) + return Folder.CreateInsertValue(AggC, ValC, IdxBegin, IdxEnd-IdxBegin); + return Insert(InsertValueInst::Create(Agg, Val, IdxBegin, IdxEnd), Name); + } + + //===--------------------------------------------------------------------===// + // Utility creation methods + //===--------------------------------------------------------------------===// + + /// CreateIsNull - Return an i1 value testing if \arg Arg is null. + Value *CreateIsNull(Value *Arg, const Twine &Name = "") { + return CreateICmpEQ(Arg, Constant::getNullValue(Arg->getType()), + Name); + } + + /// CreateIsNotNull - Return an i1 value testing if \arg Arg is not null. + Value *CreateIsNotNull(Value *Arg, const Twine &Name = "") { + return CreateICmpNE(Arg, Constant::getNullValue(Arg->getType()), + Name); + } + + /// CreatePtrDiff - Return the i64 difference between two pointer values, + /// dividing out the size of the pointed-to objects. This is intended to + /// implement C-style pointer subtraction. As such, the pointers must be + /// appropriately aligned for their element types and pointing into the + /// same object. + Value *CreatePtrDiff(Value *LHS, Value *RHS, const Twine &Name = "") { + assert(LHS->getType() == RHS->getType() && + "Pointer subtraction operand types must match!"); + const PointerType *ArgType = cast(LHS->getType()); + Value *LHS_int = CreatePtrToInt(LHS, Type::getInt64Ty(Context)); + Value *RHS_int = CreatePtrToInt(RHS, Type::getInt64Ty(Context)); + Value *Difference = CreateSub(LHS_int, RHS_int); + return CreateExactSDiv(Difference, + ConstantExpr::getSizeOf(ArgType->getElementType()), + Name); + } +}; + +} + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Support/IRReader.h b/libclamav/c++/llvm/include/llvm/Support/IRReader.h new file mode 100644 index 000000000..e7780b05d --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Support/IRReader.h @@ -0,0 +1,115 @@ +//===---- llvm/Support/IRReader.h - Reader for LLVM IR files ----*- 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 functions for reading LLVM IR. They support both +// Bitcode and Assembly, automatically detecting the input format. +// +// These functions must be defined in a header file in order to avoid +// library dependencies, since they reference both Bitcode and Assembly +// functions. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_IRREADER_H +#define LLVM_SUPPORT_IRREADER_H + +#include "llvm/Assembly/Parser.h" +#include "llvm/Bitcode/ReaderWriter.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/SourceMgr.h" +#include "llvm/ModuleProvider.h" + +namespace llvm { + + /// If the given MemoryBuffer holds a bitcode image, return a ModuleProvider + /// for it which does lazy deserialization of function bodies. Otherwise, + /// attempt to parse it as LLVM Assembly and return a fully populated + /// ModuleProvider. This function *always* takes ownership of the given + /// MemoryBuffer. + inline ModuleProvider *getIRModuleProvider(MemoryBuffer *Buffer, + SMDiagnostic &Err, + LLVMContext &Context) { + if (isBitcode((const unsigned char *)Buffer->getBufferStart(), + (const unsigned char *)Buffer->getBufferEnd())) { + std::string ErrMsg; + ModuleProvider *MP = getBitcodeModuleProvider(Buffer, Context, &ErrMsg); + if (MP == 0) { + Err = SMDiagnostic(Buffer->getBufferIdentifier(), -1, -1, ErrMsg, ""); + // ParseBitcodeFile does not take ownership of the Buffer in the + // case of an error. + delete Buffer; + } + return MP; + } + + Module *M = ParseAssembly(Buffer, 0, Err, Context); + if (M == 0) + return 0; + return new ExistingModuleProvider(M); + } + + /// If the given file holds a bitcode image, return a ModuleProvider + /// for it which does lazy deserialization of function bodies. Otherwise, + /// attempt to parse it as LLVM Assembly and return a fully populated + /// ModuleProvider. + inline ModuleProvider *getIRFileModuleProvider(const std::string &Filename, + SMDiagnostic &Err, + LLVMContext &Context) { + std::string ErrMsg; + MemoryBuffer *F = MemoryBuffer::getFileOrSTDIN(Filename.c_str(), &ErrMsg); + if (F == 0) { + Err = SMDiagnostic(Filename, -1, -1, + "Could not open input file '" + Filename + "'", ""); + return 0; + } + + return getIRModuleProvider(F, Err, Context); + } + + /// If the given MemoryBuffer holds a bitcode image, return a Module + /// for it. Otherwise, attempt to parse it as LLVM Assembly and return + /// a Module for it. This function *always* takes ownership of the given + /// MemoryBuffer. + inline Module *ParseIR(MemoryBuffer *Buffer, + SMDiagnostic &Err, + LLVMContext &Context) { + if (isBitcode((const unsigned char *)Buffer->getBufferStart(), + (const unsigned char *)Buffer->getBufferEnd())) { + std::string ErrMsg; + Module *M = ParseBitcodeFile(Buffer, Context, &ErrMsg); + // ParseBitcodeFile does not take ownership of the Buffer. + delete Buffer; + if (M == 0) + Err = SMDiagnostic(Buffer->getBufferIdentifier(), -1, -1, ErrMsg, ""); + return M; + } + + return ParseAssembly(Buffer, 0, Err, Context); + } + + /// If the given file holds a bitcode image, return a Module for it. + /// Otherwise, attempt to parse it as LLVM Assembly and return a Module + /// for it. + inline Module *ParseIRFile(const std::string &Filename, + SMDiagnostic &Err, + LLVMContext &Context) { + std::string ErrMsg; + MemoryBuffer *F = MemoryBuffer::getFileOrSTDIN(Filename.c_str(), &ErrMsg); + if (F == 0) { + Err = SMDiagnostic(Filename, -1, -1, + "Could not open input file '" + Filename + "'", ""); + return 0; + } + + return ParseIR(F, Err, Context); + } + +} + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Support/InstIterator.h b/libclamav/c++/llvm/include/llvm/Support/InstIterator.h new file mode 100644 index 000000000..7d3f88350 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Support/InstIterator.h @@ -0,0 +1,147 @@ +//===- llvm/Support/InstIterator.h - Classes for inst iteration -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains definitions of two iterators for iterating over the +// instructions in a function. This is effectively a wrapper around a two level +// iterator that can probably be genericized later. +// +// Note that this iterator gets invalidated any time that basic blocks or +// instructions are moved around. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_INSTITERATOR_H +#define LLVM_SUPPORT_INSTITERATOR_H + +#include "llvm/BasicBlock.h" +#include "llvm/Function.h" + +namespace llvm { + +// This class implements inst_begin() & inst_end() for +// inst_iterator and const_inst_iterator's. +// +template +class InstIterator { + typedef _BB_t BBty; + typedef _BB_i_t BBIty; + typedef _BI_t BIty; + typedef _II_t IIty; + _BB_t *BBs; // BasicBlocksType + _BB_i_t BB; // BasicBlocksType::iterator + _BI_t BI; // BasicBlock::iterator +public: + typedef std::bidirectional_iterator_tag iterator_category; + typedef IIty value_type; + typedef signed difference_type; + typedef IIty* pointer; + typedef IIty& reference; + + // Default constructor + InstIterator() {} + + // Copy constructor... + template + InstIterator(const InstIterator &II) + : BBs(II.BBs), BB(II.BB), BI(II.BI) {} + + template + InstIterator(InstIterator &II) + : BBs(II.BBs), BB(II.BB), BI(II.BI) {} + + template InstIterator(M &m) + : BBs(&m.getBasicBlockList()), BB(BBs->begin()) { // begin ctor + if (BB != BBs->end()) { + BI = BB->begin(); + advanceToNextBB(); + } + } + + template InstIterator(M &m, bool) + : BBs(&m.getBasicBlockList()), BB(BBs->end()) { // end ctor + } + + // Accessors to get at the underlying iterators... + inline BBIty &getBasicBlockIterator() { return BB; } + inline BIty &getInstructionIterator() { return BI; } + + inline reference operator*() const { return *BI; } + inline pointer operator->() const { return &operator*(); } + + inline bool operator==(const InstIterator &y) const { + return BB == y.BB && (BB == BBs->end() || BI == y.BI); + } + inline bool operator!=(const InstIterator& y) const { + return !operator==(y); + } + + InstIterator& operator++() { + ++BI; + advanceToNextBB(); + return *this; + } + inline InstIterator operator++(int) { + InstIterator tmp = *this; ++*this; return tmp; + } + + InstIterator& operator--() { + while (BB == BBs->end() || BI == BB->begin()) { + --BB; + BI = BB->end(); + } + --BI; + return *this; + } + inline InstIterator operator--(int) { + InstIterator tmp = *this; --*this; return tmp; + } + + inline bool atEnd() const { return BB == BBs->end(); } + +private: + inline void advanceToNextBB() { + // The only way that the II could be broken is if it is now pointing to + // the end() of the current BasicBlock and there are successor BBs. + while (BI == BB->end()) { + ++BB; + if (BB == BBs->end()) break; + BI = BB->begin(); + } + } +}; + + +typedef InstIterator, + Function::iterator, BasicBlock::iterator, + Instruction> inst_iterator; +typedef InstIterator, + Function::const_iterator, + BasicBlock::const_iterator, + const Instruction> const_inst_iterator; + +inline inst_iterator inst_begin(Function *F) { return inst_iterator(*F); } +inline inst_iterator inst_end(Function *F) { return inst_iterator(*F, true); } +inline const_inst_iterator inst_begin(const Function *F) { + return const_inst_iterator(*F); +} +inline const_inst_iterator inst_end(const Function *F) { + return const_inst_iterator(*F, true); +} +inline inst_iterator inst_begin(Function &F) { return inst_iterator(F); } +inline inst_iterator inst_end(Function &F) { return inst_iterator(F, true); } +inline const_inst_iterator inst_begin(const Function &F) { + return const_inst_iterator(F); +} +inline const_inst_iterator inst_end(const Function &F) { + return const_inst_iterator(F, true); +} + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Support/InstVisitor.h b/libclamav/c++/llvm/include/llvm/Support/InstVisitor.h new file mode 100644 index 000000000..b2e5d58b7 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Support/InstVisitor.h @@ -0,0 +1,217 @@ +//===- llvm/Support/InstVisitor.h - Define instruction visitors -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + + +#ifndef LLVM_SUPPORT_INSTVISITOR_H +#define LLVM_SUPPORT_INSTVISITOR_H + +#include "llvm/Function.h" +#include "llvm/Instructions.h" +#include "llvm/Module.h" +#include "llvm/Support/ErrorHandling.h" + +namespace llvm { + +// We operate on opaque instruction classes, so forward declare all instruction +// types now... +// +#define HANDLE_INST(NUM, OPCODE, CLASS) class CLASS; +#include "llvm/Instruction.def" + +#define DELEGATE(CLASS_TO_VISIT) \ + return static_cast(this)-> \ + visit##CLASS_TO_VISIT(static_cast(I)) + + +/// @brief Base class for instruction visitors +/// +/// Instruction visitors are used when you want to perform different actions +/// for different kinds of instructions without having to use lots of casts +/// and a big switch statement (in your code, that is). +/// +/// To define your own visitor, inherit from this class, specifying your +/// new type for the 'SubClass' template parameter, and "override" visitXXX +/// functions in your class. I say "override" because this class is defined +/// in terms of statically resolved overloading, not virtual functions. +/// +/// For example, here is a visitor that counts the number of malloc +/// instructions processed: +/// +/// /// Declare the class. Note that we derive from InstVisitor instantiated +/// /// with _our new subclasses_ type. +/// /// +/// struct CountAllocaVisitor : public InstVisitor { +/// unsigned Count; +/// CountAllocaVisitor() : Count(0) {} +/// +/// void visitAllocaInst(AllocaInst &AI) { ++Count; } +/// }; +/// +/// And this class would be used like this: +/// CountAllocaVisitor CAV; +/// CAV.visit(function); +/// NumAllocas = CAV.Count; +/// +/// The defined has 'visit' methods for Instruction, and also for BasicBlock, +/// Function, and Module, which recursively process all contained instructions. +/// +/// Note that if you don't implement visitXXX for some instruction type, +/// the visitXXX method for instruction superclass will be invoked. So +/// if instructions are added in the future, they will be automatically +/// supported, if you handle one of their superclasses. +/// +/// The optional second template argument specifies the type that instruction +/// visitation functions should return. If you specify this, you *MUST* provide +/// an implementation of visitInstruction though!. +/// +/// Note that this class is specifically designed as a template to avoid +/// virtual function call overhead. Defining and using an InstVisitor is just +/// as efficient as having your own switch statement over the instruction +/// opcode. +template +class InstVisitor { + //===--------------------------------------------------------------------===// + // Interface code - This is the public interface of the InstVisitor that you + // use to visit instructions... + // + +public: + // Generic visit method - Allow visitation to all instructions in a range + template + void visit(Iterator Start, Iterator End) { + while (Start != End) + static_cast(this)->visit(*Start++); + } + + // Define visitors for functions and basic blocks... + // + void visit(Module &M) { + static_cast(this)->visitModule(M); + visit(M.begin(), M.end()); + } + void visit(Function &F) { + static_cast(this)->visitFunction(F); + visit(F.begin(), F.end()); + } + void visit(BasicBlock &BB) { + static_cast(this)->visitBasicBlock(BB); + visit(BB.begin(), BB.end()); + } + + // Forwarding functions so that the user can visit with pointers AND refs. + void visit(Module *M) { visit(*M); } + void visit(Function *F) { visit(*F); } + void visit(BasicBlock *BB) { visit(*BB); } + RetTy visit(Instruction *I) { return visit(*I); } + + // visit - Finally, code to visit an instruction... + // + RetTy visit(Instruction &I) { + switch (I.getOpcode()) { + default: llvm_unreachable("Unknown instruction type encountered!"); + // Build the switch statement using the Instruction.def file... +#define HANDLE_INST(NUM, OPCODE, CLASS) \ + case Instruction::OPCODE: return \ + static_cast(this)-> \ + visit##OPCODE(static_cast(I)); +#include "llvm/Instruction.def" + } + } + + //===--------------------------------------------------------------------===// + // Visitation functions... these functions provide default fallbacks in case + // the user does not specify what to do for a particular instruction type. + // The default behavior is to generalize the instruction type to its subtype + // and try visiting the subtype. All of this should be inlined perfectly, + // because there are no virtual functions to get in the way. + // + + // When visiting a module, function or basic block directly, these methods get + // called to indicate when transitioning into a new unit. + // + void visitModule (Module &M) {} + void visitFunction (Function &F) {} + void visitBasicBlock(BasicBlock &BB) {} + + // Define instruction specific visitor functions that can be overridden to + // handle SPECIFIC instructions. These functions automatically define + // visitMul to proxy to visitBinaryOperator for instance in case the user does + // not need this generality. + // + // The one problem case we have to handle here though is that the PHINode + // class and opcode name are the exact same. Because of this, we cannot + // define visitPHINode (the inst version) to forward to visitPHINode (the + // generic version) without multiply defined symbols and recursion. To handle + // this, we do not autoexpand "Other" instructions, we do it manually. + // +#define HANDLE_INST(NUM, OPCODE, CLASS) \ + RetTy visit##OPCODE(CLASS &I) { DELEGATE(CLASS); } +#include "llvm/Instruction.def" + + // Specific Instruction type classes... note that all of the casts are + // necessary because we use the instruction classes as opaque types... + // + RetTy visitReturnInst(ReturnInst &I) { DELEGATE(TerminatorInst);} + RetTy visitBranchInst(BranchInst &I) { DELEGATE(TerminatorInst);} + RetTy visitSwitchInst(SwitchInst &I) { DELEGATE(TerminatorInst);} + RetTy visitIndirectBrInst(IndirectBrInst &I) { DELEGATE(TerminatorInst);} + RetTy visitInvokeInst(InvokeInst &I) { DELEGATE(TerminatorInst);} + RetTy visitUnwindInst(UnwindInst &I) { DELEGATE(TerminatorInst);} + RetTy visitUnreachableInst(UnreachableInst &I) { DELEGATE(TerminatorInst);} + RetTy visitICmpInst(ICmpInst &I) { DELEGATE(CmpInst);} + RetTy visitFCmpInst(FCmpInst &I) { DELEGATE(CmpInst);} + RetTy visitAllocaInst(AllocaInst &I) { DELEGATE(Instruction); } + RetTy visitLoadInst(LoadInst &I) { DELEGATE(Instruction); } + RetTy visitStoreInst(StoreInst &I) { DELEGATE(Instruction); } + RetTy visitGetElementPtrInst(GetElementPtrInst &I){ DELEGATE(Instruction); } + RetTy visitPHINode(PHINode &I) { DELEGATE(Instruction); } + RetTy visitTruncInst(TruncInst &I) { DELEGATE(CastInst); } + RetTy visitZExtInst(ZExtInst &I) { DELEGATE(CastInst); } + RetTy visitSExtInst(SExtInst &I) { DELEGATE(CastInst); } + RetTy visitFPTruncInst(FPTruncInst &I) { DELEGATE(CastInst); } + RetTy visitFPExtInst(FPExtInst &I) { DELEGATE(CastInst); } + RetTy visitFPToUIInst(FPToUIInst &I) { DELEGATE(CastInst); } + RetTy visitFPToSIInst(FPToSIInst &I) { DELEGATE(CastInst); } + RetTy visitUIToFPInst(UIToFPInst &I) { DELEGATE(CastInst); } + RetTy visitSIToFPInst(SIToFPInst &I) { DELEGATE(CastInst); } + RetTy visitPtrToIntInst(PtrToIntInst &I) { DELEGATE(CastInst); } + RetTy visitIntToPtrInst(IntToPtrInst &I) { DELEGATE(CastInst); } + RetTy visitBitCastInst(BitCastInst &I) { DELEGATE(CastInst); } + RetTy visitSelectInst(SelectInst &I) { DELEGATE(Instruction); } + RetTy visitCallInst(CallInst &I) { DELEGATE(Instruction); } + RetTy visitVAArgInst(VAArgInst &I) { DELEGATE(Instruction); } + RetTy visitExtractElementInst(ExtractElementInst &I) { DELEGATE(Instruction);} + RetTy visitInsertElementInst(InsertElementInst &I) { DELEGATE(Instruction); } + RetTy visitShuffleVectorInst(ShuffleVectorInst &I) { DELEGATE(Instruction); } + RetTy visitExtractValueInst(ExtractValueInst &I) { DELEGATE(Instruction);} + RetTy visitInsertValueInst(InsertValueInst &I) { DELEGATE(Instruction); } + + // Next level propagators: If the user does not overload a specific + // instruction type, they can overload one of these to get the whole class + // of instructions... + // + RetTy visitTerminatorInst(TerminatorInst &I) { DELEGATE(Instruction); } + RetTy visitBinaryOperator(BinaryOperator &I) { DELEGATE(Instruction); } + RetTy visitCmpInst(CmpInst &I) { DELEGATE(Instruction); } + RetTy visitCastInst(CastInst &I) { DELEGATE(Instruction); } + + // If the user wants a 'default' case, they can choose to override this + // function. If this function is not overloaded in the user's subclass, then + // this instruction just gets ignored. + // + // Note that you MUST override this function if your return type is not void. + // + void visitInstruction(Instruction &I) {} // Ignore unhandled instructions +}; + +#undef DELEGATE + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Support/LeakDetector.h b/libclamav/c++/llvm/include/llvm/Support/LeakDetector.h new file mode 100644 index 000000000..501a9db72 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Support/LeakDetector.h @@ -0,0 +1,92 @@ +//===-- llvm/Support/LeakDetector.h - Provide leak detection ----*- 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 a class that can be used to provide very simple memory leak +// checks for an API. Basically LLVM uses this to make sure that Instructions, +// for example, are deleted when they are supposed to be, and not leaked away. +// +// When compiling with NDEBUG (Release build), this class does nothing, thus +// adding no checking overhead to release builds. Note that this class is +// implemented in a very simple way, requiring completely manual manipulation +// and checking for garbage, but this is intentional: users should not be using +// this API, only other APIs should. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_LEAKDETECTOR_H +#define LLVM_SUPPORT_LEAKDETECTOR_H + +#include + +namespace llvm { + +class LLVMContext; +class Value; + +struct LeakDetector { + /// addGarbageObject - Add a pointer to the internal set of "garbage" object + /// pointers. This should be called when objects are created, or if they are + /// taken out of an owning collection. + /// + static void addGarbageObject(void *Object) { +#ifndef NDEBUG + addGarbageObjectImpl(Object); +#endif + } + + /// removeGarbageObject - Remove a pointer from our internal representation of + /// our "garbage" objects. This should be called when an object is added to + /// an "owning" collection. + /// + static void removeGarbageObject(void *Object) { +#ifndef NDEBUG + removeGarbageObjectImpl(Object); +#endif + } + + /// checkForGarbage - Traverse the internal representation of garbage + /// pointers. If there are any pointers that have been add'ed, but not + /// remove'd, big obnoxious warnings about memory leaks are issued. + /// + /// The specified message will be printed indicating when the check was + /// performed. + /// + static void checkForGarbage(LLVMContext &C, const std::string &Message) { +#ifndef NDEBUG + checkForGarbageImpl(C, Message); +#endif + } + + /// Overload the normal methods to work better with Value*'s because they are + /// by far the most common in LLVM. This does not affect the actual + /// functioning of this class, it just makes the warning messages nicer. + /// + static void addGarbageObject(const Value *Object) { +#ifndef NDEBUG + addGarbageObjectImpl(Object); +#endif + } + static void removeGarbageObject(const Value *Object) { +#ifndef NDEBUG + removeGarbageObjectImpl(Object); +#endif + } + +private: + // If we are debugging, the actual implementations will be called... + static void addGarbageObjectImpl(const Value *Object); + static void removeGarbageObjectImpl(const Value *Object); + static void addGarbageObjectImpl(void *Object); + static void removeGarbageObjectImpl(void *Object); + static void checkForGarbageImpl(LLVMContext &C, const std::string &Message); +}; + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Support/ManagedStatic.h b/libclamav/c++/llvm/include/llvm/Support/ManagedStatic.h new file mode 100644 index 000000000..b8e223587 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Support/ManagedStatic.h @@ -0,0 +1,116 @@ +//===-- llvm/Support/ManagedStatic.h - Static Global wrapper ----*- 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 the ManagedStatic class and the llvm_shutdown() function. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_MANAGED_STATIC_H +#define LLVM_SUPPORT_MANAGED_STATIC_H + +#include "llvm/System/Atomic.h" +#include "llvm/System/Threading.h" + +namespace llvm { + +/// object_creator - Helper method for ManagedStatic. +template +void* object_creator() { + return new C(); +} + +/// object_deleter - Helper method for ManagedStatic. +/// +template struct object_deleter { + static void call(void * Ptr) { delete (T*)Ptr; } +}; +template struct object_deleter { + static void call(void * Ptr) { delete[] (T*)Ptr; } +}; + +/// ManagedStaticBase - Common base class for ManagedStatic instances. +class ManagedStaticBase { +protected: + // This should only be used as a static variable, which guarantees that this + // will be zero initialized. + mutable void *Ptr; + mutable void (*DeleterFn)(void*); + mutable const ManagedStaticBase *Next; + + void RegisterManagedStatic(void *(*creator)(), void (*deleter)(void*)) const; +public: + /// isConstructed - Return true if this object has not been created yet. + bool isConstructed() const { return Ptr != 0; } + + void destroy() const; +}; + +/// ManagedStatic - This transparently changes the behavior of global statics to +/// be lazily constructed on demand (good for reducing startup times of dynamic +/// libraries that link in LLVM components) and for making destruction be +/// explicit through the llvm_shutdown() function call. +/// +template +class ManagedStatic : public ManagedStaticBase { +public: + + // Accessors. + C &operator*() { + void* tmp = Ptr; + if (llvm_is_multithreaded()) sys::MemoryFence(); + if (!tmp) RegisterManagedStatic(object_creator, object_deleter::call); + + return *static_cast(Ptr); + } + C *operator->() { + void* tmp = Ptr; + if (llvm_is_multithreaded()) sys::MemoryFence(); + if (!tmp) RegisterManagedStatic(object_creator, object_deleter::call); + + return static_cast(Ptr); + } + const C &operator*() const { + void* tmp = Ptr; + if (llvm_is_multithreaded()) sys::MemoryFence(); + if (!tmp) RegisterManagedStatic(object_creator, object_deleter::call); + + return *static_cast(Ptr); + } + const C *operator->() const { + void* tmp = Ptr; + if (llvm_is_multithreaded()) sys::MemoryFence(); + if (!tmp) RegisterManagedStatic(object_creator, object_deleter::call); + + return static_cast(Ptr); + } +}; + +template +class ManagedCleanup : public ManagedStaticBase { +public: + void Register() { RegisterManagedStatic(0, CleanupFn); } +}; + +/// llvm_shutdown - Deallocate and destroy all ManagedStatic variables. +void llvm_shutdown(); + + +/// llvm_shutdown_obj - This is a simple helper class that calls +/// llvm_shutdown() when it is destroyed. +struct llvm_shutdown_obj { + llvm_shutdown_obj() { } + explicit llvm_shutdown_obj(bool multithreaded) { + if (multithreaded) llvm_start_multithreaded(); + } + ~llvm_shutdown_obj() { llvm_shutdown(); } +}; + +} + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Support/Mangler.h b/libclamav/c++/llvm/include/llvm/Support/Mangler.h new file mode 100644 index 000000000..03c564897 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Support/Mangler.h @@ -0,0 +1,126 @@ +//===-- llvm/Support/Mangler.h - Self-contained name mangler ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Unified name mangler for various backends. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_MANGLER_H +#define LLVM_SUPPORT_MANGLER_H + +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallPtrSet.h" +#include + +namespace llvm { +class Type; +class Module; +class Value; +class GlobalValue; +template class SmallVectorImpl; + +class Mangler { +public: + enum ManglerPrefixTy { + Default, ///< Emit default string before each symbol. + Private, ///< Emit "private" prefix before each symbol. + LinkerPrivate ///< Emit "linker private" prefix before each symbol. + }; + +private: + /// Prefix - This string is added to each symbol that is emitted, unless the + /// symbol is marked as not needing this prefix. + const char *Prefix; + + /// PrivatePrefix - This string is emitted before each symbol with private + /// linkage. + const char *PrivatePrefix; + + /// LinkerPrivatePrefix - This string is emitted before each symbol with + /// "linker_private" linkage. + const char *LinkerPrivatePrefix; + + /// UseQuotes - If this is set, the target accepts global names in quotes, + /// e.g. "foo bar" is a legal name. This syntax is used instead of escaping + /// the space character. By default, this is false. + bool UseQuotes; + + /// SymbolsCanStartWithDigit - If this is set, the target allows symbols to + /// start with digits (e.g., "0x0021"). By default, this is false. + bool SymbolsCanStartWithDigit; + + /// AnonGlobalIDs - We need to give global values the same name every time + /// they are mangled. This keeps track of the number we give to anonymous + /// ones. + /// + DenseMap AnonGlobalIDs; + + /// NextAnonGlobalID - This simple counter is used to unique value names. + /// + unsigned NextAnonGlobalID; + + /// AcceptableChars - This bitfield contains a one for each character that is + /// allowed to be part of an unmangled name. + unsigned AcceptableChars[256 / 32]; + +public: + // Mangler ctor - if a prefix is specified, it will be prepended onto all + // symbols. + Mangler(Module &M, const char *Prefix = "", const char *privatePrefix = "", + const char *linkerPrivatePrefix = ""); + + /// setUseQuotes - If UseQuotes is set to true, this target accepts quoted + /// strings for assembler labels. + void setUseQuotes(bool Val) { UseQuotes = Val; } + + /// setSymbolsCanStartWithDigit - If SymbolsCanStartWithDigit is set to true, + /// this target allows symbols to start with digits. + void setSymbolsCanStartWithDigit(bool Val) { SymbolsCanStartWithDigit = Val; } + + /// Acceptable Characters - This allows the target to specify which characters + /// are acceptable to the assembler without being mangled. By default we + /// allow letters, numbers, '_', '$', '.', which is what GAS accepts, and '@'. + void markCharAcceptable(unsigned char X) { + AcceptableChars[X/32] |= 1 << (X&31); + } + void markCharUnacceptable(unsigned char X) { + AcceptableChars[X/32] &= ~(1 << (X&31)); + } + bool isCharAcceptable(unsigned char X) const { + return (AcceptableChars[X/32] & (1 << (X&31))) != 0; + } + + /// getMangledName - Returns the mangled name of V, an LLVM Value, + /// in the current module. If 'Suffix' is specified, the name ends with the + /// specified suffix. If 'ForcePrivate' is specified, the label is specified + /// to have a private label prefix. + /// + std::string getMangledName(const GlobalValue *V, const char *Suffix = "", + bool ForcePrivate = false); + + /// makeNameProper - We don't want identifier names with ., space, or + /// - in them, so we mangle these characters into the strings "d_", + /// "s_", and "D_", respectively. This is a very simple mangling that + /// doesn't guarantee unique names for values. getValueName already + /// does this for you, so there's no point calling it on the result + /// from getValueName. + /// + std::string makeNameProper(const std::string &x, + ManglerPrefixTy PrefixTy = Mangler::Default); + + /// getNameWithPrefix - Fill OutName with the name of the appropriate prefix + /// and the specified global variable's name. If the global variable doesn't + /// have a name, this fills in a unique name for the global. + void getNameWithPrefix(SmallVectorImpl &OutName, const GlobalValue *GV, + bool isImplicitlyPrivate); +}; + +} // End llvm namespace + +#endif // LLVM_SUPPORT_MANGLER_H diff --git a/libclamav/c++/llvm/include/llvm/Support/MathExtras.h b/libclamav/c++/llvm/include/llvm/Support/MathExtras.h new file mode 100644 index 000000000..438b021e4 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Support/MathExtras.h @@ -0,0 +1,454 @@ +//===-- llvm/Support/MathExtras.h - Useful math functions -------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains some functions that are useful for math stuff. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_MATHEXTRAS_H +#define LLVM_SUPPORT_MATHEXTRAS_H + +#include "llvm/System/DataTypes.h" + +namespace llvm { + +// NOTE: The following support functions use the _32/_64 extensions instead of +// type overloading so that signed and unsigned integers can be used without +// ambiguity. + +/// Hi_32 - This function returns the high 32 bits of a 64 bit value. +inline uint32_t Hi_32(uint64_t Value) { + return static_cast(Value >> 32); +} + +/// Lo_32 - This function returns the low 32 bits of a 64 bit value. +inline uint32_t Lo_32(uint64_t Value) { + return static_cast(Value); +} + +/// is?Type - these functions produce optimal testing for integer data types. +inline bool isInt8 (int64_t Value) { + return static_cast(Value) == Value; +} +inline bool isUInt8 (int64_t Value) { + return static_cast(Value) == Value; +} +inline bool isInt16 (int64_t Value) { + return static_cast(Value) == Value; +} +inline bool isUInt16(int64_t Value) { + return static_cast(Value) == Value; +} +inline bool isInt32 (int64_t Value) { + return static_cast(Value) == Value; +} +inline bool isUInt32(int64_t Value) { + return static_cast(Value) == Value; +} + +template +inline bool isInt(int64_t x) { + return N >= 64 || (-(INT64_C(1)<<(N-1)) <= x && x < (INT64_C(1)<<(N-1))); +} + +template +inline bool isUint(uint64_t x) { + return N >= 64 || x < (UINT64_C(1)< 0. Ex. isPowerOf2_32(0x00100000U) == true (32 bit edition.) +inline bool isPowerOf2_32(uint32_t Value) { + return Value && !(Value & (Value - 1)); +} + +/// isPowerOf2_64 - This function returns true if the argument is a power of two +/// > 0 (64 bit edition.) +inline bool isPowerOf2_64(uint64_t Value) { + return Value && !(Value & (Value - int64_t(1L))); +} + +/// ByteSwap_16 - This function returns a byte-swapped representation of the +/// 16-bit argument, Value. +inline uint16_t ByteSwap_16(uint16_t Value) { +#if defined(_MSC_VER) && !defined(_DEBUG) + // The DLL version of the runtime lacks these functions (bug!?), but in a + // release build they're replaced with BSWAP instructions anyway. + return _byteswap_ushort(Value); +#else + uint16_t Hi = Value << 8; + uint16_t Lo = Value >> 8; + return Hi | Lo; +#endif +} + +/// ByteSwap_32 - This function returns a byte-swapped representation of the +/// 32-bit argument, Value. +inline uint32_t ByteSwap_32(uint32_t Value) { +#if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)) && !defined(__ICC) + return __builtin_bswap32(Value); +#elif defined(_MSC_VER) && !defined(_DEBUG) + return _byteswap_ulong(Value); +#else + uint32_t Byte0 = Value & 0x000000FF; + uint32_t Byte1 = Value & 0x0000FF00; + uint32_t Byte2 = Value & 0x00FF0000; + uint32_t Byte3 = Value & 0xFF000000; + return (Byte0 << 24) | (Byte1 << 8) | (Byte2 >> 8) | (Byte3 >> 24); +#endif +} + +/// ByteSwap_64 - This function returns a byte-swapped representation of the +/// 64-bit argument, Value. +inline uint64_t ByteSwap_64(uint64_t Value) { +#if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)) && !defined(__ICC) + return __builtin_bswap64(Value); +#elif defined(_MSC_VER) && !defined(_DEBUG) + return _byteswap_uint64(Value); +#else + uint64_t Hi = ByteSwap_32(uint32_t(Value)); + uint32_t Lo = ByteSwap_32(uint32_t(Value >> 32)); + return (Hi << 32) | Lo; +#endif +} + +/// CountLeadingZeros_32 - this function performs the platform optimal form of +/// counting the number of zeros from the most significant bit to the first one +/// bit. Ex. CountLeadingZeros_32(0x00F000FF) == 8. +/// Returns 32 if the word is zero. +inline unsigned CountLeadingZeros_32(uint32_t Value) { + unsigned Count; // result +#if __GNUC__ >= 4 + // PowerPC is defined for __builtin_clz(0) +#if !defined(__ppc__) && !defined(__ppc64__) + if (!Value) return 32; +#endif + Count = __builtin_clz(Value); +#else + if (!Value) return 32; + Count = 0; + // bisecton method for count leading zeros + for (unsigned Shift = 32 >> 1; Shift; Shift >>= 1) { + uint32_t Tmp = Value >> Shift; + if (Tmp) { + Value = Tmp; + } else { + Count |= Shift; + } + } +#endif + return Count; +} + +/// CountLeadingOnes_32 - this function performs the operation of +/// counting the number of ones from the most significant bit to the first zero +/// bit. Ex. CountLeadingOnes_32(0xFF0FFF00) == 8. +/// Returns 32 if the word is all ones. +inline unsigned CountLeadingOnes_32(uint32_t Value) { + return CountLeadingZeros_32(~Value); +} + +/// CountLeadingZeros_64 - This function performs the platform optimal form +/// of counting the number of zeros from the most significant bit to the first +/// one bit (64 bit edition.) +/// Returns 64 if the word is zero. +inline unsigned CountLeadingZeros_64(uint64_t Value) { + unsigned Count; // result +#if __GNUC__ >= 4 + // PowerPC is defined for __builtin_clzll(0) +#if !defined(__ppc__) && !defined(__ppc64__) + if (!Value) return 64; +#endif + Count = __builtin_clzll(Value); +#else + if (sizeof(long) == sizeof(int64_t)) { + if (!Value) return 64; + Count = 0; + // bisecton method for count leading zeros + for (unsigned Shift = 64 >> 1; Shift; Shift >>= 1) { + uint64_t Tmp = Value >> Shift; + if (Tmp) { + Value = Tmp; + } else { + Count |= Shift; + } + } + } else { + // get hi portion + uint32_t Hi = Hi_32(Value); + + // if some bits in hi portion + if (Hi) { + // leading zeros in hi portion plus all bits in lo portion + Count = CountLeadingZeros_32(Hi); + } else { + // get lo portion + uint32_t Lo = Lo_32(Value); + // same as 32 bit value + Count = CountLeadingZeros_32(Lo)+32; + } + } +#endif + return Count; +} + +/// CountLeadingOnes_64 - This function performs the operation +/// of counting the number of ones from the most significant bit to the first +/// zero bit (64 bit edition.) +/// Returns 64 if the word is all ones. +inline unsigned CountLeadingOnes_64(uint64_t Value) { + return CountLeadingZeros_64(~Value); +} + +/// CountTrailingZeros_32 - this function performs the platform optimal form of +/// counting the number of zeros from the least significant bit to the first one +/// bit. Ex. CountTrailingZeros_32(0xFF00FF00) == 8. +/// Returns 32 if the word is zero. +inline unsigned CountTrailingZeros_32(uint32_t Value) { +#if __GNUC__ >= 4 + return Value ? __builtin_ctz(Value) : 32; +#else + static const unsigned Mod37BitPosition[] = { + 32, 0, 1, 26, 2, 23, 27, 0, 3, 16, 24, 30, 28, 11, 0, 13, + 4, 7, 17, 0, 25, 22, 31, 15, 29, 10, 12, 6, 0, 21, 14, 9, + 5, 20, 8, 19, 18 + }; + return Mod37BitPosition[(-Value & Value) % 37]; +#endif +} + +/// CountTrailingOnes_32 - this function performs the operation of +/// counting the number of ones from the least significant bit to the first zero +/// bit. Ex. CountTrailingOnes_32(0x00FF00FF) == 8. +/// Returns 32 if the word is all ones. +inline unsigned CountTrailingOnes_32(uint32_t Value) { + return CountTrailingZeros_32(~Value); +} + +/// CountTrailingZeros_64 - This function performs the platform optimal form +/// of counting the number of zeros from the least significant bit to the first +/// one bit (64 bit edition.) +/// Returns 64 if the word is zero. +inline unsigned CountTrailingZeros_64(uint64_t Value) { +#if __GNUC__ >= 4 + return Value ? __builtin_ctzll(Value) : 64; +#else + static const unsigned Mod67Position[] = { + 64, 0, 1, 39, 2, 15, 40, 23, 3, 12, 16, 59, 41, 19, 24, 54, + 4, 64, 13, 10, 17, 62, 60, 28, 42, 30, 20, 51, 25, 44, 55, + 47, 5, 32, 65, 38, 14, 22, 11, 58, 18, 53, 63, 9, 61, 27, + 29, 50, 43, 46, 31, 37, 21, 57, 52, 8, 26, 49, 45, 36, 56, + 7, 48, 35, 6, 34, 33, 0 + }; + return Mod67Position[(-Value & Value) % 67]; +#endif +} + +/// CountTrailingOnes_64 - This function performs the operation +/// of counting the number of ones from the least significant bit to the first +/// zero bit (64 bit edition.) +/// Returns 64 if the word is all ones. +inline unsigned CountTrailingOnes_64(uint64_t Value) { + return CountTrailingZeros_64(~Value); +} + +/// CountPopulation_32 - this function counts the number of set bits in a value. +/// Ex. CountPopulation(0xF000F000) = 8 +/// Returns 0 if the word is zero. +inline unsigned CountPopulation_32(uint32_t Value) { +#if __GNUC__ >= 4 + return __builtin_popcount(Value); +#else + uint32_t v = Value - ((Value >> 1) & 0x55555555); + v = (v & 0x33333333) + ((v >> 2) & 0x33333333); + return ((v + (v >> 4) & 0xF0F0F0F) * 0x1010101) >> 24; +#endif +} + +/// CountPopulation_64 - this function counts the number of set bits in a value, +/// (64 bit edition.) +inline unsigned CountPopulation_64(uint64_t Value) { +#if __GNUC__ >= 4 + return __builtin_popcountll(Value); +#else + uint64_t v = Value - ((Value >> 1) & 0x5555555555555555ULL); + v = (v & 0x3333333333333333ULL) + ((v >> 2) & 0x3333333333333333ULL); + v = (v + (v >> 4)) & 0x0F0F0F0F0F0F0F0FULL; + return unsigned((uint64_t)(v * 0x0101010101010101ULL) >> 56); +#endif +} + +/// Log2_32 - This function returns the floor log base 2 of the specified value, +/// -1 if the value is zero. (32 bit edition.) +/// Ex. Log2_32(32) == 5, Log2_32(1) == 0, Log2_32(0) == -1, Log2_32(6) == 2 +inline unsigned Log2_32(uint32_t Value) { + return 31 - CountLeadingZeros_32(Value); +} + +/// Log2_64 - This function returns the floor log base 2 of the specified value, +/// -1 if the value is zero. (64 bit edition.) +inline unsigned Log2_64(uint64_t Value) { + return 63 - CountLeadingZeros_64(Value); +} + +/// Log2_32_Ceil - This function returns the ceil log base 2 of the specified +/// value, 32 if the value is zero. (32 bit edition). +/// Ex. Log2_32_Ceil(32) == 5, Log2_32_Ceil(1) == 0, Log2_32_Ceil(6) == 3 +inline unsigned Log2_32_Ceil(uint32_t Value) { + return 32-CountLeadingZeros_32(Value-1); +} + +/// Log2_64_Ceil - This function returns the ceil log base 2 of the specified +/// value, 64 if the value is zero. (64 bit edition.) +inline unsigned Log2_64_Ceil(uint64_t Value) { + return 64-CountLeadingZeros_64(Value-1); +} + +/// GreatestCommonDivisor64 - Return the greatest common divisor of the two +/// values using Euclid's algorithm. +inline uint64_t GreatestCommonDivisor64(uint64_t A, uint64_t B) { + while (B) { + uint64_t T = B; + B = A % B; + A = T; + } + return A; +} + +/// BitsToDouble - This function takes a 64-bit integer and returns the bit +/// equivalent double. +inline double BitsToDouble(uint64_t Bits) { + union { + uint64_t L; + double D; + } T; + T.L = Bits; + return T.D; +} + +/// BitsToFloat - This function takes a 32-bit integer and returns the bit +/// equivalent float. +inline float BitsToFloat(uint32_t Bits) { + union { + uint32_t I; + float F; + } T; + T.I = Bits; + return T.F; +} + +/// DoubleToBits - This function takes a double and returns the bit +/// equivalent 64-bit integer. Note that copying doubles around +/// changes the bits of NaNs on some hosts, notably x86, so this +/// routine cannot be used if these bits are needed. +inline uint64_t DoubleToBits(double Double) { + union { + uint64_t L; + double D; + } T; + T.D = Double; + return T.L; +} + +/// FloatToBits - This function takes a float and returns the bit +/// equivalent 32-bit integer. Note that copying floats around +/// changes the bits of NaNs on some hosts, notably x86, so this +/// routine cannot be used if these bits are needed. +inline uint32_t FloatToBits(float Float) { + union { + uint32_t I; + float F; + } T; + T.F = Float; + return T.I; +} + +/// Platform-independent wrappers for the C99 isnan() function. +int IsNAN(float f); +int IsNAN(double d); + +/// Platform-independent wrappers for the C99 isinf() function. +int IsInf(float f); +int IsInf(double d); + +/// MinAlign - A and B are either alignments or offsets. Return the minimum +/// alignment that may be assumed after adding the two together. +static inline uint64_t MinAlign(uint64_t A, uint64_t B) { + // The largest power of 2 that divides both A and B. + return (A | B) & -(A | B); +} + +/// NextPowerOf2 - Returns the next power of two (in 64-bits) +/// that is strictly greater than A. Returns zero on overflow. +static inline uint64_t NextPowerOf2(uint64_t A) { + A |= (A >> 1); + A |= (A >> 2); + A |= (A >> 4); + A |= (A >> 8); + A |= (A >> 16); + A |= (A >> 32); + return A + 1; +} + +/// RoundUpToAlignment - Returns the next integer (mod 2**64) that is +/// greater than or equal to \arg Value and is a multiple of \arg +/// Align. Align must be non-zero. +/// +/// Examples: +/// RoundUpToAlignment(5, 8) = 8 +/// RoundUpToAlignment(17, 8) = 24 +/// RoundUpToAlignment(~0LL, 8) = 0 +inline uint64_t RoundUpToAlignment(uint64_t Value, uint64_t Align) { + return ((Value + Align - 1) / Align) * Align; +} + +/// OffsetToAlignment - Return the offset to the next integer (mod 2**64) that +/// is greater than or equal to \arg Value and is a multiple of \arg +/// Align. Align must be non-zero. +inline uint64_t OffsetToAlignment(uint64_t Value, uint64_t Align) { + return RoundUpToAlignment(Value, Align) - Value; +} + +/// abs64 - absolute value of a 64-bit int. Not all environments support +/// "abs" on whatever their name for the 64-bit int type is. The absolute +/// value of the largest negative number is undefined, as with "abs". +inline int64_t abs64(int64_t x) { + return (x < 0) ? -x : x; +} + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Support/MemoryBuffer.h b/libclamav/c++/llvm/include/llvm/Support/MemoryBuffer.h new file mode 100644 index 000000000..65c716731 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Support/MemoryBuffer.h @@ -0,0 +1,103 @@ +//===--- MemoryBuffer.h - Memory Buffer Interface ---------------*- 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 the MemoryBuffer interface. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_MEMORYBUFFER_H +#define LLVM_SUPPORT_MEMORYBUFFER_H + +#include "llvm/ADT/StringRef.h" +#include "llvm/System/DataTypes.h" +#include + +namespace llvm { + +/// MemoryBuffer - This interface provides simple read-only access to a block +/// of memory, and provides simple methods for reading files and standard input +/// into a memory buffer. In addition to basic access to the characters in the +/// file, this interface guarantees you can read one character past the end of +/// the file, and that this character will read as '\0'. +class MemoryBuffer { + const char *BufferStart; // Start of the buffer. + const char *BufferEnd; // End of the buffer. + + /// MustDeleteBuffer - True if we allocated this buffer. If so, the + /// destructor must know the delete[] it. + bool MustDeleteBuffer; +protected: + MemoryBuffer() : MustDeleteBuffer(false) {} + void init(const char *BufStart, const char *BufEnd); + void initCopyOf(const char *BufStart, const char *BufEnd); +public: + virtual ~MemoryBuffer(); + + const char *getBufferStart() const { return BufferStart; } + const char *getBufferEnd() const { return BufferEnd; } + size_t getBufferSize() const { return BufferEnd-BufferStart; } + + StringRef getBuffer() const { + return StringRef(BufferStart, getBufferSize()); + } + + /// getBufferIdentifier - Return an identifier for this buffer, typically the + /// filename it was read from. + virtual const char *getBufferIdentifier() const { + return "Unknown buffer"; + } + + /// getFile - Open the specified file as a MemoryBuffer, returning a new + /// MemoryBuffer if successful, otherwise returning null. If FileSize is + /// specified, this means that the client knows that the file exists and that + /// it has the specified size. + static MemoryBuffer *getFile(StringRef Filename, + std::string *ErrStr = 0, + int64_t FileSize = -1); + + /// getMemBuffer - Open the specified memory range as a MemoryBuffer. Note + /// that EndPtr[0] must be a null byte and be accessible! + static MemoryBuffer *getMemBuffer(const char *StartPtr, const char *EndPtr, + const char *BufferName = ""); + + /// getMemBufferCopy - Open the specified memory range as a MemoryBuffer, + /// copying the contents and taking ownership of it. This has no requirements + /// on EndPtr[0]. + static MemoryBuffer *getMemBufferCopy(const char *StartPtr,const char *EndPtr, + const char *BufferName = ""); + + /// getNewMemBuffer - Allocate a new MemoryBuffer of the specified size that + /// is completely initialized to zeros. Note that the caller should + /// initialize the memory allocated by this method. The memory is owned by + /// the MemoryBuffer object. + static MemoryBuffer *getNewMemBuffer(size_t Size, + const char *BufferName = ""); + + /// getNewUninitMemBuffer - Allocate a new MemoryBuffer of the specified size + /// that is not initialized. Note that the caller should initialize the + /// memory allocated by this method. The memory is owned by the MemoryBuffer + /// object. + static MemoryBuffer *getNewUninitMemBuffer(size_t Size, + StringRef BufferName = ""); + + /// getSTDIN - Read all of stdin into a file buffer, and return it. + static MemoryBuffer *getSTDIN(); + + + /// getFileOrSTDIN - Open the specified file as a MemoryBuffer, or open stdin + /// if the Filename is "-". If an error occurs, this returns null and fills + /// in *ErrStr with a reason. + static MemoryBuffer *getFileOrSTDIN(StringRef Filename, + std::string *ErrStr = 0, + int64_t FileSize = -1); +}; + +} // end namespace llvm + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Support/MemoryObject.h b/libclamav/c++/llvm/include/llvm/Support/MemoryObject.h new file mode 100644 index 000000000..e193ca2f2 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Support/MemoryObject.h @@ -0,0 +1,70 @@ +//===- MemoryObject.h - Abstract memory interface ---------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef MEMORYOBJECT_H +#define MEMORYOBJECT_H + +#include "llvm/System/DataTypes.h" + +namespace llvm { + +/// MemoryObject - Abstract base class for contiguous addressable memory. +/// Necessary for cases in which the memory is in another process, in a +/// file, or on a remote machine. +/// All size and offset parameters are uint64_ts, to allow 32-bit processes +/// access to 64-bit address spaces. +class MemoryObject { +public: + /// Destructor - Override as necessary. + virtual ~MemoryObject(); + + /// getBase - Returns the lowest valid address in the region. + /// + /// @result - The lowest valid address. + virtual uint64_t getBase() const = 0; + + /// getExtent - Returns the size of the region in bytes. (The region is + /// contiguous, so the highest valid address of the region + /// is getBase() + getExtent() - 1). + /// + /// @result - The size of the region. + virtual uint64_t getExtent() const = 0; + + /// readByte - Tries to read a single byte from the region. + /// + /// @param address - The address of the byte, in the same space as getBase(). + /// @param ptr - A pointer to a byte to be filled in. Must be non-NULL. + /// @result - 0 if successful; -1 if not. Failure may be due to a + /// bounds violation or an implementation-specific error. + virtual int readByte(uint64_t address, uint8_t* ptr) const = 0; + + /// readBytes - Tries to read a contiguous range of bytes from the + /// region, up to the end of the region. + /// You should override this function if there is a quicker + /// way than going back and forth with individual bytes. + /// + /// @param address - The address of the first byte, in the same space as + /// getBase(). + /// @param size - The maximum number of bytes to copy. + /// @param buf - A pointer to a buffer to be filled in. Must be non-NULL + /// and large enough to hold size bytes. + /// @param copied - A pointer to a nunber that is filled in with the number + /// of bytes actually read. May be NULL. + /// @result - 0 if successful; -1 if not. Failure may be due to a + /// bounds violation or an implementation-specific error. + virtual int readBytes(uint64_t address, + uint64_t size, + uint8_t* buf, + uint64_t* copied) const; +}; + +} + +#endif + diff --git a/libclamav/c++/llvm/include/llvm/Support/MutexGuard.h b/libclamav/c++/llvm/include/llvm/Support/MutexGuard.h new file mode 100644 index 000000000..9958b97a3 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Support/MutexGuard.h @@ -0,0 +1,41 @@ +//===-- Support/MutexGuard.h - Acquire/Release Mutex In Scope ---*- 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 a guard for a block of code that ensures a Mutex is locked +// upon construction and released upon destruction. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_MUTEXGUARD_H +#define LLVM_SUPPORT_MUTEXGUARD_H + +#include "llvm/System/Mutex.h" + +namespace llvm { + /// Instances of this class acquire a given Mutex Lock when constructed and + /// hold that lock until destruction. The intention is to instantiate one of + /// these on the stack at the top of some scope to be assured that C++ + /// destruction of the object will always release the Mutex and thus avoid + /// a host of nasty multi-threading problems in the face of exceptions, etc. + /// @brief Guard a section of code with a Mutex. + class MutexGuard { + sys::Mutex &M; + MutexGuard(const MutexGuard &); // DO NOT IMPLEMENT + void operator=(const MutexGuard &); // DO NOT IMPLEMENT + public: + MutexGuard(sys::Mutex &m) : M(m) { M.acquire(); } + ~MutexGuard() { M.release(); } + /// holds - Returns true if this locker instance holds the specified lock. + /// This is mostly used in assertions to validate that the correct mutex + /// is held. + bool holds(const sys::Mutex& lock) const { return &M == &lock; } + }; +} + +#endif // LLVM_SUPPORT_MUTEXGUARD_H diff --git a/libclamav/c++/llvm/include/llvm/Support/NoFolder.h b/libclamav/c++/llvm/include/llvm/Support/NoFolder.h new file mode 100644 index 000000000..7f2f1497f --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Support/NoFolder.h @@ -0,0 +1,202 @@ +//======-- llvm/Support/NoFolder.h - Constant folding helper -*- 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 the NoFolder class, a helper for IRBuilder. It provides +// IRBuilder with a set of methods for creating unfolded constants. This is +// useful for learners trying to understand how LLVM IR works, and who don't +// want details to be hidden by the constant folder. For general constant +// creation and folding, use ConstantExpr and the routines in +// llvm/Analysis/ConstantFolding.h. +// +// Note: since it is not actually possible to create unfolded constants, this +// class returns values rather than constants. The values do not have names, +// even if names were provided to IRBuilder, which may be confusing. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_NOFOLDER_H +#define LLVM_SUPPORT_NOFOLDER_H + +#include "llvm/Constants.h" +#include "llvm/Instructions.h" + +namespace llvm { + +class LLVMContext; + +/// NoFolder - Create "constants" (actually, values) with no folding. +class NoFolder { +public: + explicit NoFolder(LLVMContext &) {} + + //===--------------------------------------------------------------------===// + // Binary Operators + //===--------------------------------------------------------------------===// + + Value *CreateAdd(Constant *LHS, Constant *RHS) const { + return BinaryOperator::CreateAdd(LHS, RHS); + } + Value *CreateNSWAdd(Constant *LHS, Constant *RHS) const { + return BinaryOperator::CreateNSWAdd(LHS, RHS); + } + Value *CreateFAdd(Constant *LHS, Constant *RHS) const { + return BinaryOperator::CreateFAdd(LHS, RHS); + } + Value *CreateSub(Constant *LHS, Constant *RHS) const { + return BinaryOperator::CreateSub(LHS, RHS); + } + Value *CreateNSWSub(Constant *LHS, Constant *RHS) const { + return BinaryOperator::CreateNSWSub(LHS, RHS); + } + Value *CreateFSub(Constant *LHS, Constant *RHS) const { + return BinaryOperator::CreateFSub(LHS, RHS); + } + Value *CreateMul(Constant *LHS, Constant *RHS) const { + return BinaryOperator::CreateMul(LHS, RHS); + } + Value *CreateFMul(Constant *LHS, Constant *RHS) const { + return BinaryOperator::CreateFMul(LHS, RHS); + } + Value *CreateUDiv(Constant *LHS, Constant *RHS) const { + return BinaryOperator::CreateUDiv(LHS, RHS); + } + Value *CreateSDiv(Constant *LHS, Constant *RHS) const { + return BinaryOperator::CreateSDiv(LHS, RHS); + } + Value *CreateExactSDiv(Constant *LHS, Constant *RHS) const { + return BinaryOperator::CreateExactSDiv(LHS, RHS); + } + Value *CreateFDiv(Constant *LHS, Constant *RHS) const { + return BinaryOperator::CreateFDiv(LHS, RHS); + } + Value *CreateURem(Constant *LHS, Constant *RHS) const { + return BinaryOperator::CreateURem(LHS, RHS); + } + Value *CreateSRem(Constant *LHS, Constant *RHS) const { + return BinaryOperator::CreateSRem(LHS, RHS); + } + Value *CreateFRem(Constant *LHS, Constant *RHS) const { + return BinaryOperator::CreateFRem(LHS, RHS); + } + Value *CreateShl(Constant *LHS, Constant *RHS) const { + return BinaryOperator::CreateShl(LHS, RHS); + } + Value *CreateLShr(Constant *LHS, Constant *RHS) const { + return BinaryOperator::CreateLShr(LHS, RHS); + } + Value *CreateAShr(Constant *LHS, Constant *RHS) const { + return BinaryOperator::CreateAShr(LHS, RHS); + } + Value *CreateAnd(Constant *LHS, Constant *RHS) const { + return BinaryOperator::CreateAnd(LHS, RHS); + } + Value *CreateOr(Constant *LHS, Constant *RHS) const { + return BinaryOperator::CreateOr(LHS, RHS); + } + Value *CreateXor(Constant *LHS, Constant *RHS) const { + return BinaryOperator::CreateXor(LHS, RHS); + } + + Value *CreateBinOp(Instruction::BinaryOps Opc, + Constant *LHS, Constant *RHS) const { + return BinaryOperator::Create(Opc, LHS, RHS); + } + + //===--------------------------------------------------------------------===// + // Unary Operators + //===--------------------------------------------------------------------===// + + Value *CreateNeg(Constant *C) const { + return BinaryOperator::CreateNeg(C); + } + Value *CreateNot(Constant *C) const { + return BinaryOperator::CreateNot(C); + } + + //===--------------------------------------------------------------------===// + // Memory Instructions + //===--------------------------------------------------------------------===// + + Constant *CreateGetElementPtr(Constant *C, Constant* const *IdxList, + unsigned NumIdx) const { + return ConstantExpr::getGetElementPtr(C, IdxList, NumIdx); + } + Value *CreateGetElementPtr(Constant *C, Value* const *IdxList, + unsigned NumIdx) const { + return GetElementPtrInst::Create(C, IdxList, IdxList+NumIdx); + } + + Constant *CreateInBoundsGetElementPtr(Constant *C, Constant* const *IdxList, + unsigned NumIdx) const { + return ConstantExpr::getInBoundsGetElementPtr(C, IdxList, NumIdx); + } + Value *CreateInBoundsGetElementPtr(Constant *C, Value* const *IdxList, + unsigned NumIdx) const { + return GetElementPtrInst::CreateInBounds(C, IdxList, IdxList+NumIdx); + } + + //===--------------------------------------------------------------------===// + // Cast/Conversion Operators + //===--------------------------------------------------------------------===// + + Value *CreateCast(Instruction::CastOps Op, Constant *C, + const Type *DestTy) const { + return CastInst::Create(Op, C, DestTy); + } + Value *CreateIntCast(Constant *C, const Type *DestTy, + bool isSigned) const { + return CastInst::CreateIntegerCast(C, DestTy, isSigned); + } + + //===--------------------------------------------------------------------===// + // Compare Instructions + //===--------------------------------------------------------------------===// + + Value *CreateICmp(CmpInst::Predicate P, Constant *LHS, Constant *RHS) const { + return new ICmpInst(P, LHS, RHS); + } + Value *CreateFCmp(CmpInst::Predicate P, Constant *LHS, Constant *RHS) const { + return new FCmpInst(P, LHS, RHS); + } + + //===--------------------------------------------------------------------===// + // Other Instructions + //===--------------------------------------------------------------------===// + + Value *CreateSelect(Constant *C, Constant *True, Constant *False) const { + return SelectInst::Create(C, True, False); + } + + Value *CreateExtractElement(Constant *Vec, Constant *Idx) const { + return ExtractElementInst::Create(Vec, Idx); + } + + Value *CreateInsertElement(Constant *Vec, Constant *NewElt, + Constant *Idx) const { + return InsertElementInst::Create(Vec, NewElt, Idx); + } + + Value *CreateShuffleVector(Constant *V1, Constant *V2, Constant *Mask) const { + return new ShuffleVectorInst(V1, V2, Mask); + } + + Value *CreateExtractValue(Constant *Agg, const unsigned *IdxList, + unsigned NumIdx) const { + return ExtractValueInst::Create(Agg, IdxList, IdxList+NumIdx); + } + + Value *CreateInsertValue(Constant *Agg, Constant *Val, + const unsigned *IdxList, unsigned NumIdx) const { + return InsertValueInst::Create(Agg, Val, IdxList, IdxList+NumIdx); + } +}; + +} + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Support/OutputBuffer.h b/libclamav/c++/llvm/include/llvm/Support/OutputBuffer.h new file mode 100644 index 000000000..6b98e99e2 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Support/OutputBuffer.h @@ -0,0 +1,166 @@ +//=== OutputBuffer.h - Output Buffer ----------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Methods to output values to a data buffer. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_OUTPUTBUFFER_H +#define LLVM_SUPPORT_OUTPUTBUFFER_H + +#include +#include +#include + +namespace llvm { + + class OutputBuffer { + /// Output buffer. + std::vector &Output; + + /// is64Bit/isLittleEndian - This information is inferred from the target + /// machine directly, indicating what header values and flags to set. + bool is64Bit, isLittleEndian; + public: + OutputBuffer(std::vector &Out, + bool is64bit, bool le) + : Output(Out), is64Bit(is64bit), isLittleEndian(le) {} + + // align - Emit padding into the file until the current output position is + // aligned to the specified power of two boundary. + void align(unsigned Boundary) { + assert(Boundary && (Boundary & (Boundary - 1)) == 0 && + "Must align to 2^k boundary"); + size_t Size = Output.size(); + + if (Size & (Boundary - 1)) { + // Add padding to get alignment to the correct place. + size_t Pad = Boundary - (Size & (Boundary - 1)); + Output.resize(Size + Pad); + } + } + + //===------------------------------------------------------------------===// + // Out Functions - Output the specified value to the data buffer. + + void outbyte(unsigned char X) { + Output.push_back(X); + } + void outhalf(unsigned short X) { + if (isLittleEndian) { + Output.push_back(X & 255); + Output.push_back(X >> 8); + } else { + Output.push_back(X >> 8); + Output.push_back(X & 255); + } + } + void outword(unsigned X) { + if (isLittleEndian) { + Output.push_back((X >> 0) & 255); + Output.push_back((X >> 8) & 255); + Output.push_back((X >> 16) & 255); + Output.push_back((X >> 24) & 255); + } else { + Output.push_back((X >> 24) & 255); + Output.push_back((X >> 16) & 255); + Output.push_back((X >> 8) & 255); + Output.push_back((X >> 0) & 255); + } + } + void outxword(uint64_t X) { + if (isLittleEndian) { + Output.push_back(unsigned(X >> 0) & 255); + Output.push_back(unsigned(X >> 8) & 255); + Output.push_back(unsigned(X >> 16) & 255); + Output.push_back(unsigned(X >> 24) & 255); + Output.push_back(unsigned(X >> 32) & 255); + Output.push_back(unsigned(X >> 40) & 255); + Output.push_back(unsigned(X >> 48) & 255); + Output.push_back(unsigned(X >> 56) & 255); + } else { + Output.push_back(unsigned(X >> 56) & 255); + Output.push_back(unsigned(X >> 48) & 255); + Output.push_back(unsigned(X >> 40) & 255); + Output.push_back(unsigned(X >> 32) & 255); + Output.push_back(unsigned(X >> 24) & 255); + Output.push_back(unsigned(X >> 16) & 255); + Output.push_back(unsigned(X >> 8) & 255); + Output.push_back(unsigned(X >> 0) & 255); + } + } + void outaddr32(unsigned X) { + outword(X); + } + void outaddr64(uint64_t X) { + outxword(X); + } + void outaddr(uint64_t X) { + if (!is64Bit) + outword((unsigned)X); + else + outxword(X); + } + void outstring(const std::string &S, unsigned Length) { + unsigned len_to_copy = static_cast(S.length()) < Length + ? static_cast(S.length()) : Length; + unsigned len_to_fill = static_cast(S.length()) < Length + ? Length - static_cast(S.length()) : 0; + + for (unsigned i = 0; i < len_to_copy; ++i) + outbyte(S[i]); + + for (unsigned i = 0; i < len_to_fill; ++i) + outbyte(0); + } + + //===------------------------------------------------------------------===// + // Fix Functions - Replace an existing entry at an offset. + + void fixhalf(unsigned short X, unsigned Offset) { + unsigned char *P = &Output[Offset]; + P[0] = (X >> (isLittleEndian ? 0 : 8)) & 255; + P[1] = (X >> (isLittleEndian ? 8 : 0)) & 255; + } + void fixword(unsigned X, unsigned Offset) { + unsigned char *P = &Output[Offset]; + P[0] = (X >> (isLittleEndian ? 0 : 24)) & 255; + P[1] = (X >> (isLittleEndian ? 8 : 16)) & 255; + P[2] = (X >> (isLittleEndian ? 16 : 8)) & 255; + P[3] = (X >> (isLittleEndian ? 24 : 0)) & 255; + } + void fixxword(uint64_t X, unsigned Offset) { + unsigned char *P = &Output[Offset]; + P[0] = (X >> (isLittleEndian ? 0 : 56)) & 255; + P[1] = (X >> (isLittleEndian ? 8 : 48)) & 255; + P[2] = (X >> (isLittleEndian ? 16 : 40)) & 255; + P[3] = (X >> (isLittleEndian ? 24 : 32)) & 255; + P[4] = (X >> (isLittleEndian ? 32 : 24)) & 255; + P[5] = (X >> (isLittleEndian ? 40 : 16)) & 255; + P[6] = (X >> (isLittleEndian ? 48 : 8)) & 255; + P[7] = (X >> (isLittleEndian ? 56 : 0)) & 255; + } + void fixaddr(uint64_t X, unsigned Offset) { + if (!is64Bit) + fixword((unsigned)X, Offset); + else + fixxword(X, Offset); + } + + unsigned char &operator[](unsigned Index) { + return Output[Index]; + } + const unsigned char &operator[](unsigned Index) const { + return Output[Index]; + } + }; + +} // end llvm namespace + +#endif // LLVM_SUPPORT_OUTPUTBUFFER_H diff --git a/libclamav/c++/llvm/include/llvm/Support/PassNameParser.h b/libclamav/c++/llvm/include/llvm/Support/PassNameParser.h new file mode 100644 index 000000000..ea4fe01f7 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Support/PassNameParser.h @@ -0,0 +1,135 @@ +//===- llvm/Support/PassNameParser.h ----------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file the PassNameParser and FilteredPassNameParser<> classes, which are +// used to add command line arguments to a utility for all of the passes that +// have been registered into the system. +// +// The PassNameParser class adds ALL passes linked into the system (that are +// creatable) as command line arguments to the tool (when instantiated with the +// appropriate command line option template). The FilteredPassNameParser<> +// template is used for the same purposes as PassNameParser, except that it only +// includes passes that have a PassType that are compatible with the filter +// (which is the template argument). +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_PASS_NAME_PARSER_H +#define LLVM_SUPPORT_PASS_NAME_PARSER_H + +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Pass.h" +#include +#include + +namespace llvm { + +//===----------------------------------------------------------------------===// +// PassNameParser class - Make use of the pass registration mechanism to +// automatically add a command line argument to opt for each pass. +// +class PassNameParser : public PassRegistrationListener, + public cl::parser { + cl::Option *Opt; +public: + PassNameParser() : Opt(0) {} + + void initialize(cl::Option &O) { + Opt = &O; + cl::parser::initialize(O); + + // Add all of the passes to the map that got initialized before 'this' did. + enumeratePasses(); + } + + // ignorablePassImpl - Can be overriden in subclasses to refine the list of + // which passes we want to include. + // + virtual bool ignorablePassImpl(const PassInfo *P) const { return false; } + + inline bool ignorablePass(const PassInfo *P) const { + // Ignore non-selectable and non-constructible passes! Ignore + // non-optimizations. + return P->getPassArgument() == 0 || *P->getPassArgument() == 0 || + P->getNormalCtor() == 0 || ignorablePassImpl(P); + } + + // Implement the PassRegistrationListener callbacks used to populate our map + // + virtual void passRegistered(const PassInfo *P) { + if (ignorablePass(P) || !Opt) return; + if (findOption(P->getPassArgument()) != getNumOptions()) { + errs() << "Two passes with the same argument (-" + << P->getPassArgument() << ") attempted to be registered!\n"; + llvm_unreachable(0); + } + addLiteralOption(P->getPassArgument(), P, P->getPassName()); + } + virtual void passEnumerate(const PassInfo *P) { passRegistered(P); } + + // ValLessThan - Provide a sorting comparator for Values elements... + typedef std::pair > ValType; + static bool ValLessThan(const ValType &VT1, const ValType &VT2) { + return std::string(VT1.first) < std::string(VT2.first); + } + + // printOptionInfo - Print out information about this option. Override the + // default implementation to sort the table before we print... + virtual void printOptionInfo(const cl::Option &O, size_t GlobalWidth) const { + PassNameParser *PNP = const_cast(this); + std::sort(PNP->Values.begin(), PNP->Values.end(), ValLessThan); + cl::parser::printOptionInfo(O, GlobalWidth); + } +}; + +///===----------------------------------------------------------------------===// +/// FilteredPassNameParser class - Make use of the pass registration +/// mechanism to automatically add a command line argument to opt for +/// each pass that satisfies a filter criteria. Filter should return +/// true for passes to be registered as command-line options. +/// +template +class FilteredPassNameParser : public PassNameParser { +private: + Filter filter; + +public: + bool ignorablePassImpl(const PassInfo *P) const { return !filter(*P); } +}; + +///===----------------------------------------------------------------------===// +/// PassArgFilter - A filter for use with PassNameFilterParser that only +/// accepts a Pass whose Arg matches certain strings. +/// +/// Use like this: +/// +/// extern const char AllowedPassArgs[] = "-anders_aa -dse"; +/// +/// static cl::list< +/// const PassInfo*, +/// bool, +/// FilteredPassNameParser > > +/// PassList(cl::desc("Passes available:")); +/// +/// Only the -anders_aa and -dse options will be available to the user. +/// +template +class PassArgFilter { +public: + bool operator()(const PassInfo &P) const { + return(std::strstr(Args, P.getPassArgument())); + } +}; + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Support/PatternMatch.h b/libclamav/c++/llvm/include/llvm/Support/PatternMatch.h new file mode 100644 index 000000000..c0b6a6b98 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Support/PatternMatch.h @@ -0,0 +1,592 @@ +//===-- llvm/Support/PatternMatch.h - Match on the LLVM IR ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides a simple and efficient mechanism for performing general +// tree-based pattern matches on the LLVM IR. The power of these routines is +// that it allows you to write concise patterns that are expressive and easy to +// understand. The other major advantage of this is that it allows you to +// trivially capture/bind elements in the pattern to variables. For example, +// you can do something like this: +// +// Value *Exp = ... +// Value *X, *Y; ConstantInt *C1, *C2; // (X & C1) | (Y & C2) +// if (match(Exp, m_Or(m_And(m_Value(X), m_ConstantInt(C1)), +// m_And(m_Value(Y), m_ConstantInt(C2))))) { +// ... Pattern is matched and variables are bound ... +// } +// +// This is primarily useful to things like the instruction combiner, but can +// also be useful for static analysis tools or code generators. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_PATTERNMATCH_H +#define LLVM_SUPPORT_PATTERNMATCH_H + +#include "llvm/Constants.h" +#include "llvm/Instructions.h" + +namespace llvm { +namespace PatternMatch { + +template +bool match(Val *V, const Pattern &P) { + return const_cast(P).match(V); +} + +template +struct leaf_ty { + template + bool match(ITy *V) { return isa(V); } +}; + +/// m_Value() - Match an arbitrary value and ignore it. +inline leaf_ty m_Value() { return leaf_ty(); } +/// m_ConstantInt() - Match an arbitrary ConstantInt and ignore it. +inline leaf_ty m_ConstantInt() { return leaf_ty(); } + +template +struct constantint_ty { + template + bool match(ITy *V) { + if (const ConstantInt *CI = dyn_cast(V)) { + const APInt &CIV = CI->getValue(); + if (Val >= 0) + return CIV == static_cast(Val); + // If Val is negative, and CI is shorter than it, truncate to the right + // number of bits. If it is larger, then we have to sign extend. Just + // compare their negated values. + return -CIV == -Val; + } + return false; + } +}; + +/// m_ConstantInt(int64_t) - Match a ConstantInt with a specific value +/// and ignore it. +template +inline constantint_ty m_ConstantInt() { + return constantint_ty(); +} + +struct zero_ty { + template + bool match(ITy *V) { + if (const Constant *C = dyn_cast(V)) + return C->isNullValue(); + return false; + } +}; + +/// m_Zero() - Match an arbitrary zero/null constant. +inline zero_ty m_Zero() { return zero_ty(); } + +struct one_ty { + template + bool match(ITy *V) { + if (const ConstantInt *C = dyn_cast(V)) + return C->isOne(); + return false; + } +}; + +/// m_One() - Match a an integer 1. +inline one_ty m_One() { return one_ty(); } + + +template +struct bind_ty { + Class *&VR; + bind_ty(Class *&V) : VR(V) {} + + template + bool match(ITy *V) { + if (Class *CV = dyn_cast(V)) { + VR = CV; + return true; + } + return false; + } +}; + +/// m_Value - Match a value, capturing it if we match. +inline bind_ty m_Value(Value *&V) { return V; } + +/// m_ConstantInt - Match a ConstantInt, capturing the value if we match. +inline bind_ty m_ConstantInt(ConstantInt *&CI) { return CI; } + +/// specificval_ty - Match a specified Value*. +struct specificval_ty { + const Value *Val; + specificval_ty(const Value *V) : Val(V) {} + + template + bool match(ITy *V) { + return V == Val; + } +}; + +/// m_Specific - Match if we have a specific specified value. +inline specificval_ty m_Specific(const Value *V) { return V; } + + +//===----------------------------------------------------------------------===// +// Matchers for specific binary operators. +// + +template +struct BinaryOp_match { + LHS_t L; + RHS_t R; + + BinaryOp_match(const LHS_t &LHS, const RHS_t &RHS) : L(LHS), R(RHS) {} + + template + bool match(OpTy *V) { + if (V->getValueID() == Value::InstructionVal + Opcode) { + ConcreteTy *I = cast(V); + return I->getOpcode() == Opcode && L.match(I->getOperand(0)) && + R.match(I->getOperand(1)); + } + if (ConstantExpr *CE = dyn_cast(V)) + return CE->getOpcode() == Opcode && L.match(CE->getOperand(0)) && + R.match(CE->getOperand(1)); + return false; + } +}; + +template +inline BinaryOp_match m_Add(const LHS &L, + const RHS &R) { + return BinaryOp_match(L, R); +} + +template +inline BinaryOp_match m_FAdd(const LHS &L, + const RHS &R) { + return BinaryOp_match(L, R); +} + +template +inline BinaryOp_match m_Sub(const LHS &L, + const RHS &R) { + return BinaryOp_match(L, R); +} + +template +inline BinaryOp_match m_FSub(const LHS &L, + const RHS &R) { + return BinaryOp_match(L, R); +} + +template +inline BinaryOp_match m_Mul(const LHS &L, + const RHS &R) { + return BinaryOp_match(L, R); +} + +template +inline BinaryOp_match m_FMul(const LHS &L, + const RHS &R) { + return BinaryOp_match(L, R); +} + +template +inline BinaryOp_match m_UDiv(const LHS &L, + const RHS &R) { + return BinaryOp_match(L, R); +} + +template +inline BinaryOp_match m_SDiv(const LHS &L, + const RHS &R) { + return BinaryOp_match(L, R); +} + +template +inline BinaryOp_match m_FDiv(const LHS &L, + const RHS &R) { + return BinaryOp_match(L, R); +} + +template +inline BinaryOp_match m_URem(const LHS &L, + const RHS &R) { + return BinaryOp_match(L, R); +} + +template +inline BinaryOp_match m_SRem(const LHS &L, + const RHS &R) { + return BinaryOp_match(L, R); +} + +template +inline BinaryOp_match m_FRem(const LHS &L, + const RHS &R) { + return BinaryOp_match(L, R); +} + +template +inline BinaryOp_match m_And(const LHS &L, + const RHS &R) { + return BinaryOp_match(L, R); +} + +template +inline BinaryOp_match m_Or(const LHS &L, + const RHS &R) { + return BinaryOp_match(L, R); +} + +template +inline BinaryOp_match m_Xor(const LHS &L, + const RHS &R) { + return BinaryOp_match(L, R); +} + +template +inline BinaryOp_match m_Shl(const LHS &L, + const RHS &R) { + return BinaryOp_match(L, R); +} + +template +inline BinaryOp_match m_LShr(const LHS &L, + const RHS &R) { + return BinaryOp_match(L, R); +} + +template +inline BinaryOp_match m_AShr(const LHS &L, + const RHS &R) { + return BinaryOp_match(L, R); +} + +//===----------------------------------------------------------------------===// +// Matchers for either AShr or LShr .. for convenience +// +template +struct Shr_match { + LHS_t L; + RHS_t R; + + Shr_match(const LHS_t &LHS, const RHS_t &RHS) : L(LHS), R(RHS) {} + + template + bool match(OpTy *V) { + if (V->getValueID() == Value::InstructionVal + Instruction::LShr || + V->getValueID() == Value::InstructionVal + Instruction::AShr) { + ConcreteTy *I = cast(V); + return (I->getOpcode() == Instruction::AShr || + I->getOpcode() == Instruction::LShr) && + L.match(I->getOperand(0)) && + R.match(I->getOperand(1)); + } + if (ConstantExpr *CE = dyn_cast(V)) + return (CE->getOpcode() == Instruction::LShr || + CE->getOpcode() == Instruction::AShr) && + L.match(CE->getOperand(0)) && + R.match(CE->getOperand(1)); + return false; + } +}; + +template +inline Shr_match m_Shr(const LHS &L, const RHS &R) { + return Shr_match(L, R); +} + +//===----------------------------------------------------------------------===// +// Matchers for binary classes +// + +template +struct BinaryOpClass_match { + OpcType *Opcode; + LHS_t L; + RHS_t R; + + BinaryOpClass_match(OpcType &Op, const LHS_t &LHS, + const RHS_t &RHS) + : Opcode(&Op), L(LHS), R(RHS) {} + BinaryOpClass_match(const LHS_t &LHS, const RHS_t &RHS) + : Opcode(0), L(LHS), R(RHS) {} + + template + bool match(OpTy *V) { + if (Class *I = dyn_cast(V)) + if (L.match(I->getOperand(0)) && + R.match(I->getOperand(1))) { + if (Opcode) + *Opcode = I->getOpcode(); + return true; + } +#if 0 // Doesn't handle constantexprs yet! + if (ConstantExpr *CE = dyn_cast(V)) + return CE->getOpcode() == Opcode && L.match(CE->getOperand(0)) && + R.match(CE->getOperand(1)); +#endif + return false; + } +}; + +template +inline BinaryOpClass_match +m_Shift(Instruction::BinaryOps &Op, const LHS &L, const RHS &R) { + return BinaryOpClass_match(Op, L, R); +} + +template +inline BinaryOpClass_match +m_Shift(const LHS &L, const RHS &R) { + return BinaryOpClass_match(L, R); +} + +//===----------------------------------------------------------------------===// +// Matchers for CmpInst classes +// + +template +struct CmpClass_match { + PredicateTy &Predicate; + LHS_t L; + RHS_t R; + + CmpClass_match(PredicateTy &Pred, const LHS_t &LHS, + const RHS_t &RHS) + : Predicate(Pred), L(LHS), R(RHS) {} + + template + bool match(OpTy *V) { + if (Class *I = dyn_cast(V)) + if (L.match(I->getOperand(0)) && + R.match(I->getOperand(1))) { + Predicate = I->getPredicate(); + return true; + } + return false; + } +}; + +template +inline CmpClass_match +m_ICmp(ICmpInst::Predicate &Pred, const LHS &L, const RHS &R) { + return CmpClass_match(Pred, L, R); +} + +template +inline CmpClass_match +m_FCmp(FCmpInst::Predicate &Pred, const LHS &L, const RHS &R) { + return CmpClass_match(Pred, L, R); +} + +//===----------------------------------------------------------------------===// +// Matchers for SelectInst classes +// + +template +struct SelectClass_match { + Cond_t C; + LHS_t L; + RHS_t R; + + SelectClass_match(const Cond_t &Cond, const LHS_t &LHS, + const RHS_t &RHS) + : C(Cond), L(LHS), R(RHS) {} + + template + bool match(OpTy *V) { + if (SelectInst *I = dyn_cast(V)) + return C.match(I->getOperand(0)) && + L.match(I->getOperand(1)) && + R.match(I->getOperand(2)); + return false; + } +}; + +template +inline SelectClass_match +m_Select(const Cond &C, const LHS &L, const RHS &R) { + return SelectClass_match(C, L, R); +} + +/// m_SelectCst - This matches a select of two constants, e.g.: +/// m_SelectCst(m_Value(V), -1, 0) +template +inline SelectClass_match, constantint_ty > +m_SelectCst(const Cond &C) { + return SelectClass_match, + constantint_ty >(C, m_ConstantInt(), + m_ConstantInt()); +} + + +//===----------------------------------------------------------------------===// +// Matchers for CastInst classes +// + +template +struct CastClass_match { + Op_t Op; + + CastClass_match(const Op_t &OpMatch) : Op(OpMatch) {} + + template + bool match(OpTy *V) { + if (Class *I = dyn_cast(V)) + return Op.match(I->getOperand(0)); + return false; + } +}; + +template +inline CastClass_match m_Cast(const OpTy &Op) { + return CastClass_match(Op); +} + + +//===----------------------------------------------------------------------===// +// Matchers for unary operators +// + +template +struct not_match { + LHS_t L; + + not_match(const LHS_t &LHS) : L(LHS) {} + + template + bool match(OpTy *V) { + if (Instruction *I = dyn_cast(V)) + if (I->getOpcode() == Instruction::Xor) + return matchIfNot(I->getOperand(0), I->getOperand(1)); + if (ConstantExpr *CE = dyn_cast(V)) + if (CE->getOpcode() == Instruction::Xor) + return matchIfNot(CE->getOperand(0), CE->getOperand(1)); + if (ConstantInt *CI = dyn_cast(V)) + return L.match(ConstantExpr::getNot(CI)); + return false; + } +private: + bool matchIfNot(Value *LHS, Value *RHS) { + if (ConstantInt *CI = dyn_cast(RHS)) + return CI->isAllOnesValue() && L.match(LHS); + if (ConstantInt *CI = dyn_cast(LHS)) + return CI->isAllOnesValue() && L.match(RHS); + if (ConstantVector *CV = dyn_cast(RHS)) + return CV->isAllOnesValue() && L.match(LHS); + if (ConstantVector *CV = dyn_cast(LHS)) + return CV->isAllOnesValue() && L.match(RHS); + return false; + } +}; + +template +inline not_match m_Not(const LHS &L) { return L; } + + +template +struct neg_match { + LHS_t L; + + neg_match(const LHS_t &LHS) : L(LHS) {} + + template + bool match(OpTy *V) { + if (Instruction *I = dyn_cast(V)) + if (I->getOpcode() == Instruction::Sub) + return matchIfNeg(I->getOperand(0), I->getOperand(1)); + if (ConstantExpr *CE = dyn_cast(V)) + if (CE->getOpcode() == Instruction::Sub) + return matchIfNeg(CE->getOperand(0), CE->getOperand(1)); + if (ConstantInt *CI = dyn_cast(V)) + return L.match(ConstantExpr::getNeg(CI)); + return false; + } +private: + bool matchIfNeg(Value *LHS, Value *RHS) { + return LHS == ConstantFP::getZeroValueForNegation(LHS->getType()) && + L.match(RHS); + } +}; + +template +inline neg_match m_Neg(const LHS &L) { return L; } + + +template +struct fneg_match { + LHS_t L; + + fneg_match(const LHS_t &LHS) : L(LHS) {} + + template + bool match(OpTy *V) { + if (Instruction *I = dyn_cast(V)) + if (I->getOpcode() == Instruction::FSub) + return matchIfFNeg(I->getOperand(0), I->getOperand(1)); + if (ConstantExpr *CE = dyn_cast(V)) + if (CE->getOpcode() == Instruction::FSub) + return matchIfFNeg(CE->getOperand(0), CE->getOperand(1)); + if (ConstantFP *CF = dyn_cast(V)) + return L.match(ConstantExpr::getFNeg(CF)); + return false; + } +private: + bool matchIfFNeg(Value *LHS, Value *RHS) { + return LHS == ConstantFP::getZeroValueForNegation(LHS->getType()) && + L.match(RHS); + } +}; + +template +inline fneg_match m_FNeg(const LHS &L) { return L; } + + +//===----------------------------------------------------------------------===// +// Matchers for control flow +// + +template +struct brc_match { + Cond_t Cond; + BasicBlock *&T, *&F; + brc_match(const Cond_t &C, BasicBlock *&t, BasicBlock *&f) + : Cond(C), T(t), F(f) { + } + + template + bool match(OpTy *V) { + if (BranchInst *BI = dyn_cast(V)) + if (BI->isConditional()) { + if (Cond.match(BI->getCondition())) { + T = BI->getSuccessor(0); + F = BI->getSuccessor(1); + return true; + } + } + return false; + } +}; + +template +inline brc_match m_Br(const Cond_t &C, BasicBlock *&T, BasicBlock *&F) { + return brc_match(C, T, F); +} + +} // end namespace PatternMatch +} // end namespace llvm + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Support/PluginLoader.h b/libclamav/c++/llvm/include/llvm/Support/PluginLoader.h new file mode 100644 index 000000000..bdbb134b2 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Support/PluginLoader.h @@ -0,0 +1,37 @@ +//===-- llvm/Support/PluginLoader.h - Plugin Loader for Tools ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// A tool can #include this file to get a -load option that allows the user to +// load arbitrary shared objects into the tool's address space. Note that this +// header can only be included by a program ONCE, so it should never to used by +// library authors. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_PLUGINLOADER_H +#define LLVM_SUPPORT_PLUGINLOADER_H + +#include "llvm/Support/CommandLine.h" + +namespace llvm { + struct PluginLoader { + void operator=(const std::string &Filename); + static unsigned getNumPlugins(); + static std::string& getPlugin(unsigned num); + }; + +#ifndef DONT_GET_PLUGIN_LOADER_OPTION + // This causes operator= above to be invoked for every -load option. + static cl::opt > + LoadOpt("load", cl::ZeroOrMore, cl::value_desc("pluginfilename"), + cl::desc("Load the specified plugin")); +#endif +} + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Support/PointerLikeTypeTraits.h b/libclamav/c++/llvm/include/llvm/Support/PointerLikeTypeTraits.h new file mode 100644 index 000000000..b85140480 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Support/PointerLikeTypeTraits.h @@ -0,0 +1,81 @@ +//===- llvm/Support/PointerLikeTypeTraits.h - Pointer Traits ----*- 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 the PointerLikeTypeTraits class. This allows data +// structures to reason about pointers and other things that are pointer sized. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_POINTERLIKETYPETRAITS_H +#define LLVM_SUPPORT_POINTERLIKETYPETRAITS_H + +#include "llvm/System/DataTypes.h" + +namespace llvm { + +/// PointerLikeTypeTraits - This is a traits object that is used to handle +/// pointer types and things that are just wrappers for pointers as a uniform +/// entity. +template +class PointerLikeTypeTraits { + // getAsVoidPointer + // getFromVoidPointer + // getNumLowBitsAvailable +}; + +// Provide PointerLikeTypeTraits for non-cvr pointers. +template +class PointerLikeTypeTraits { +public: + static inline void *getAsVoidPointer(T* P) { return P; } + static inline T *getFromVoidPointer(void *P) { + return static_cast(P); + } + + /// Note, we assume here that malloc returns objects at least 4-byte aligned. + /// However, this may be wrong, or pointers may be from something other than + /// malloc. In this case, you should specialize this template to reduce this. + /// + /// All clients should use assertions to do a run-time check to ensure that + /// this is actually true. + enum { NumLowBitsAvailable = 2 }; +}; + +// Provide PointerLikeTypeTraits for const pointers. +template +class PointerLikeTypeTraits { + typedef PointerLikeTypeTraits NonConst; + +public: + static inline const void *getAsVoidPointer(const T* P) { + return NonConst::getAsVoidPointer(const_cast(P)); + } + static inline const T *getFromVoidPointer(const void *P) { + return NonConst::getFromVoidPointer(const_cast(P)); + } + enum { NumLowBitsAvailable = NonConst::NumLowBitsAvailable }; +}; + +// Provide PointerLikeTypeTraits for uintptr_t. +template<> +class PointerLikeTypeTraits { +public: + static inline void *getAsVoidPointer(uintptr_t P) { + return reinterpret_cast(P); + } + static inline uintptr_t getFromVoidPointer(void *P) { + return reinterpret_cast(P); + } + // No bits are available! + enum { NumLowBitsAvailable = 0 }; +}; + +} // end namespace llvm + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Support/PredIteratorCache.h b/libclamav/c++/llvm/include/llvm/Support/PredIteratorCache.h new file mode 100644 index 000000000..bb66a8ed5 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Support/PredIteratorCache.h @@ -0,0 +1,70 @@ +//===- llvm/Support/PredIteratorCache.h - pred_iterator Cache ---*- 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 the PredIteratorCache class. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/Allocator.h" +#include "llvm/Support/CFG.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallVector.h" + +#ifndef LLVM_SUPPORT_PREDITERATORCACHE_H +#define LLVM_SUPPORT_PREDITERATORCACHE_H + +namespace llvm { + + /// PredIteratorCache - This class is an extremely trivial cache for + /// predecessor iterator queries. This is useful for code that repeatedly + /// wants the predecessor list for the same blocks. + class PredIteratorCache { + /// BlockToPredsMap - Pointer to null-terminated list. + DenseMap BlockToPredsMap; + DenseMap BlockToPredCountMap; + + /// Memory - This is the space that holds cached preds. + BumpPtrAllocator Memory; + public: + + /// GetPreds - Get a cached list for the null-terminated predecessor list of + /// the specified block. This can be used in a loop like this: + /// for (BasicBlock **PI = PredCache->GetPreds(BB); *PI; ++PI) + /// use(*PI); + /// instead of: + /// for (pred_iterator PI = pred_begin(BB), E = pred_end(BB); PI != E; ++PI) + BasicBlock **GetPreds(BasicBlock *BB) { + BasicBlock **&Entry = BlockToPredsMap[BB]; + if (Entry) return Entry; + + SmallVector PredCache(pred_begin(BB), pred_end(BB)); + PredCache.push_back(0); // null terminator. + + BlockToPredCountMap[BB] = PredCache.size()-1; + + Entry = Memory.Allocate(PredCache.size()); + std::copy(PredCache.begin(), PredCache.end(), Entry); + return Entry; + } + + unsigned GetNumPreds(BasicBlock *BB) { + GetPreds(BB); + return BlockToPredCountMap[BB]; + } + + /// clear - Remove all information. + void clear() { + BlockToPredsMap.clear(); + BlockToPredCountMap.clear(); + Memory.Reset(); + } + }; +} // end namespace llvm + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Support/PrettyStackTrace.h b/libclamav/c++/llvm/include/llvm/Support/PrettyStackTrace.h new file mode 100644 index 000000000..0db84e1a1 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Support/PrettyStackTrace.h @@ -0,0 +1,71 @@ +//===- llvm/Support/PrettyStackTrace.h - Pretty Crash Handling --*- 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 the PrettyStackTraceEntry class, which is used to make +// crashes give more contextual information about what the program was doing +// when it crashed. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_PRETTYSTACKTRACE_H +#define LLVM_SUPPORT_PRETTYSTACKTRACE_H + +namespace llvm { + class raw_ostream; + + /// DisablePrettyStackTrace - Set this to true to disable this module. This + /// might be neccessary if the host application installs its own signal + /// handlers which conflict with the ones installed by this module. + /// Defaults to false. + extern bool DisablePrettyStackTrace; + + /// PrettyStackTraceEntry - This class is used to represent a frame of the + /// "pretty" stack trace that is dumped when a program crashes. You can define + /// subclasses of this and declare them on the program stack: when they are + /// constructed and destructed, they will add their symbolic frames to a + /// virtual stack trace. This gets dumped out if the program crashes. + class PrettyStackTraceEntry { + const PrettyStackTraceEntry *NextEntry; + PrettyStackTraceEntry(const PrettyStackTraceEntry &); // DO NOT IMPLEMENT + void operator=(const PrettyStackTraceEntry&); // DO NOT IMPLEMENT + public: + PrettyStackTraceEntry(); + virtual ~PrettyStackTraceEntry(); + + /// print - Emit information about this stack frame to OS. + virtual void print(raw_ostream &OS) const = 0; + + /// getNextEntry - Return the next entry in the list of frames. + const PrettyStackTraceEntry *getNextEntry() const { return NextEntry; } + }; + + /// PrettyStackTraceString - This object prints a specified string (which + /// should not contain newlines) to the stream as the stack trace when a crash + /// occurs. + class PrettyStackTraceString : public PrettyStackTraceEntry { + const char *Str; + public: + PrettyStackTraceString(const char *str) : Str(str) {} + virtual void print(raw_ostream &OS) const; + }; + + /// PrettyStackTraceProgram - This object prints a specified program arguments + /// to the stream as the stack trace when a crash occurs. + class PrettyStackTraceProgram : public PrettyStackTraceEntry { + int ArgC; + const char *const *ArgV; + public: + PrettyStackTraceProgram(int argc, const char * const*argv) + : ArgC(argc), ArgV(argv) {} + virtual void print(raw_ostream &OS) const; + }; + +} // end namespace llvm + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Support/Recycler.h b/libclamav/c++/llvm/include/llvm/Support/Recycler.h new file mode 100644 index 000000000..d8f8c7894 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Support/Recycler.h @@ -0,0 +1,117 @@ +//==- llvm/Support/Recycler.h - Recycling Allocator --------------*- 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 the Recycler class template. See the doxygen comment for +// Recycler for more details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_RECYCLER_H +#define LLVM_SUPPORT_RECYCLER_H + +#include "llvm/ADT/ilist.h" +#include "llvm/Support/AlignOf.h" +#include + +namespace llvm { + +/// PrintRecyclingAllocatorStats - Helper for RecyclingAllocator for +/// printing statistics. +/// +void PrintRecyclerStats(size_t Size, size_t Align, size_t FreeListSize); + +/// RecyclerStruct - Implementation detail for Recycler. This is a +/// class that the recycler imposes on free'd memory to carve out +/// next/prev pointers. +struct RecyclerStruct { + RecyclerStruct *Prev, *Next; +}; + +template<> +struct ilist_traits : + public ilist_default_traits { + static RecyclerStruct *getPrev(const RecyclerStruct *t) { return t->Prev; } + static RecyclerStruct *getNext(const RecyclerStruct *t) { return t->Next; } + static void setPrev(RecyclerStruct *t, RecyclerStruct *p) { t->Prev = p; } + static void setNext(RecyclerStruct *t, RecyclerStruct *n) { t->Next = n; } + + mutable RecyclerStruct Sentinel; + RecyclerStruct *createSentinel() const { + return &Sentinel; + } + static void destroySentinel(RecyclerStruct *) {} + + RecyclerStruct *provideInitialHead() const { return createSentinel(); } + RecyclerStruct *ensureHead(RecyclerStruct*) const { return createSentinel(); } + static void noteHead(RecyclerStruct*, RecyclerStruct*) {} + + static void deleteNode(RecyclerStruct *) { + assert(0 && "Recycler's ilist_traits shouldn't see a deleteNode call!"); + } +}; + +/// Recycler - This class manages a linked-list of deallocated nodes +/// and facilitates reusing deallocated memory in place of allocating +/// new memory. +/// +template::Alignment> +class Recycler { + /// FreeList - Doubly-linked list of nodes that have deleted contents and + /// are not in active use. + /// + iplist FreeList; + +public: + ~Recycler() { + // If this fails, either the callee has lost track of some allocation, + // or the callee isn't tracking allocations and should just call + // clear() before deleting the Recycler. + assert(FreeList.empty() && "Non-empty recycler deleted!"); + } + + /// clear - Release all the tracked allocations to the allocator. The + /// recycler must be free of any tracked allocations before being + /// deleted; calling clear is one way to ensure this. + template + void clear(AllocatorType &Allocator) { + while (!FreeList.empty()) { + T *t = reinterpret_cast(FreeList.remove(FreeList.begin())); + Allocator.Deallocate(t); + } + } + + template + SubClass *Allocate(AllocatorType &Allocator) { + assert(sizeof(SubClass) <= Size && + "Recycler allocation size is less than object size!"); + assert(AlignOf::Alignment <= Align && + "Recycler allocation alignment is less than object alignment!"); + return !FreeList.empty() ? + reinterpret_cast(FreeList.remove(FreeList.begin())) : + static_cast(Allocator.Allocate(Size, Align)); + } + + template + T *Allocate(AllocatorType &Allocator) { + return Allocate(Allocator); + } + + template + void Deallocate(AllocatorType & /*Allocator*/, SubClass* Element) { + FreeList.push_front(reinterpret_cast(Element)); + } + + void PrintStats() { + PrintRecyclerStats(Size, Align, FreeList.size()); + } +}; + +} + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Support/RecyclingAllocator.h b/libclamav/c++/llvm/include/llvm/Support/RecyclingAllocator.h new file mode 100644 index 000000000..609193ffd --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Support/RecyclingAllocator.h @@ -0,0 +1,59 @@ +//==- llvm/Support/RecyclingAllocator.h - Recycling Allocator ----*- 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 the RecyclingAllocator class. See the doxygen comment for +// RecyclingAllocator for more details on the implementation. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_RECYCLINGALLOCATOR_H +#define LLVM_SUPPORT_RECYCLINGALLOCATOR_H + +#include "llvm/Support/Recycler.h" + +namespace llvm { + +/// RecyclingAllocator - This class wraps an Allocator, adding the +/// functionality of recycling deleted objects. +/// +template::Alignment> +class RecyclingAllocator { +private: + /// Base - Implementation details. + /// + Recycler Base; + + /// Allocator - The wrapped allocator. + /// + AllocatorType Allocator; + +public: + ~RecyclingAllocator() { Base.clear(Allocator); } + + /// Allocate - Return a pointer to storage for an object of type + /// SubClass. The storage may be either newly allocated or recycled. + /// + template + SubClass *Allocate() { return Base.template Allocate(Allocator); } + + T *Allocate() { return Base.Allocate(Allocator); } + + /// Deallocate - Release storage for the pointed-to object. The + /// storage will be kept track of and may be recycled. + /// + template + void Deallocate(SubClass* E) { return Base.Deallocate(Allocator, E); } + + void PrintStats() { Base.PrintStats(); } +}; + +} + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Support/Regex.h b/libclamav/c++/llvm/include/llvm/Support/Regex.h new file mode 100644 index 000000000..c954c0d31 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Support/Regex.h @@ -0,0 +1,63 @@ +//===-- Regex.h - Regular Expression matcher implementation -*- 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 a POSIX regular expression matcher. +// +//===----------------------------------------------------------------------===// + +#include + +struct llvm_regex; + +namespace llvm { + class StringRef; + template class SmallVectorImpl; + + class Regex { + public: + enum { + NoFlags=0, + /// Compile for matching that ignores upper/lower case distinctions. + IgnoreCase=1, + /// Compile for newline-sensitive matching. With this flag '[^' bracket + /// expressions and '.' never match newline. A ^ anchor matches the + /// null string after any newline in the string in addition to its normal + /// function, and the $ anchor matches the null string before any + /// newline in the string in addition to its normal function. + Newline=2 + }; + + /// Compiles the given POSIX Extended Regular Expression \arg Regex. + /// This implementation supports regexes and matching strings with embedded + /// NUL characters. + Regex(const StringRef &Regex, unsigned Flags = NoFlags); + ~Regex(); + + /// isValid - returns the error encountered during regex compilation, or + /// matching, if any. + bool isValid(std::string &Error); + + /// getNumMatches - In a valid regex, return the number of parenthesized + /// matches it contains. The number filled in by match will include this + /// many entries plus one for the whole regex (as element 0). + unsigned getNumMatches() const; + + /// matches - Match the regex against a given \arg String. + /// + /// \param Matches - If given, on a succesful match this will be filled in + /// with references to the matched group expressions (inside \arg String), + /// the first group is always the entire pattern. + /// + /// This returns true on a successful match. + bool match(const StringRef &String, SmallVectorImpl *Matches=0); + private: + struct llvm_regex *preg; + int error; + }; +} diff --git a/libclamav/c++/llvm/include/llvm/Support/Registry.h b/libclamav/c++/llvm/include/llvm/Support/Registry.h new file mode 100644 index 000000000..4db88825a --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Support/Registry.h @@ -0,0 +1,221 @@ +//=== Registry.h - Linker-supported plugin registries -----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Defines a registry template for discovering pluggable modules. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_REGISTRY_H +#define LLVM_SUPPORT_REGISTRY_H + +namespace llvm { + /// A simple registry entry which provides only a name, description, and + /// no-argument constructor. + template + class SimpleRegistryEntry { + const char *Name, *Desc; + T *(*Ctor)(); + + public: + SimpleRegistryEntry(const char *N, const char *D, T *(*C)()) + : Name(N), Desc(D), Ctor(C) + {} + + const char *getName() const { return Name; } + const char *getDesc() const { return Desc; } + T *instantiate() const { return Ctor(); } + }; + + + /// Traits for registry entries. If using other than SimpleRegistryEntry, it + /// is necessary to define an alternate traits class. + template + class RegistryTraits { + RegistryTraits(); // Do not implement. + + public: + typedef SimpleRegistryEntry entry; + + /// nameof/descof - Accessors for name and description of entries. These are + // used to generate help for command-line options. + static const char *nameof(const entry &Entry) { return Entry.getName(); } + static const char *descof(const entry &Entry) { return Entry.getDesc(); } + }; + + + /// A global registry used in conjunction with static constructors to make + /// pluggable components (like targets or garbage collectors) "just work" when + /// linked with an executable. + template > + class Registry { + public: + typedef U traits; + typedef typename U::entry entry; + + class node; + class listener; + class iterator; + + private: + Registry(); // Do not implement. + + static void Announce(const entry &E) { + for (listener *Cur = ListenerHead; Cur; Cur = Cur->Next) + Cur->registered(E); + } + + friend class node; + static node *Head, *Tail; + + friend class listener; + static listener *ListenerHead, *ListenerTail; + + public: + /// Node in linked list of entries. + /// + class node { + friend class iterator; + + node *Next; + const entry& Val; + + public: + node(const entry& V) : Next(0), Val(V) { + if (Tail) + Tail->Next = this; + else + Head = this; + Tail = this; + + Announce(V); + } + }; + + + /// Iterators for registry entries. + /// + class iterator { + const node *Cur; + + public: + explicit iterator(const node *N) : Cur(N) {} + + bool operator==(const iterator &That) const { return Cur == That.Cur; } + bool operator!=(const iterator &That) const { return Cur != That.Cur; } + iterator &operator++() { Cur = Cur->Next; return *this; } + const entry &operator*() const { return Cur->Val; } + const entry *operator->() const { return &Cur->Val; } + }; + + static iterator begin() { return iterator(Head); } + static iterator end() { return iterator(0); } + + + /// Abstract base class for registry listeners, which are informed when new + /// entries are added to the registry. Simply subclass and instantiate: + /// + /// class CollectorPrinter : public Registry::listener { + /// protected: + /// void registered(const Registry::entry &e) { + /// cerr << "collector now available: " << e->getName() << "\n"; + /// } + /// + /// public: + /// CollectorPrinter() { init(); } // Print those already registered. + /// }; + /// + /// CollectorPrinter Printer; + /// + class listener { + listener *Prev, *Next; + + friend void Registry::Announce(const entry &E); + + protected: + /// Called when an entry is added to the registry. + /// + virtual void registered(const entry &) = 0; + + /// Calls 'registered' for each pre-existing entry. + /// + void init() { + for (iterator I = begin(), E = end(); I != E; ++I) + registered(*I); + } + + public: + listener() : Prev(ListenerTail), Next(0) { + if (Prev) + Prev->Next = this; + else + ListenerHead = this; + ListenerTail = this; + } + + virtual ~listener() { + if (Next) + Next->Prev = Prev; + else + ListenerTail = Prev; + if (Prev) + Prev->Next = Next; + else + ListenerHead = Next; + } + }; + + + /// A static registration template. Use like such: + /// + /// Registry::Add + /// X("fancy-gc", "Newfangled garbage collector."); + /// + /// Use of this template requires that: + /// + /// 1. The registered subclass has a default constructor. + // + /// 2. The registry entry type has a constructor compatible with this + /// signature: + /// + /// entry(const char *Name, const char *ShortDesc, T *(*Ctor)()); + /// + /// If you have more elaborate requirements, then copy and modify. + /// + template + class Add { + entry Entry; + node Node; + + static T *CtorFn() { return new V(); } + + public: + Add(const char *Name, const char *Desc) + : Entry(Name, Desc, CtorFn), Node(Entry) {} + }; + + /// Registry::Parser now lives in llvm/Support/RegistryParser.h. + + }; + + + template + typename Registry::node *Registry::Head; + + template + typename Registry::node *Registry::Tail; + + template + typename Registry::listener *Registry::ListenerHead; + + template + typename Registry::listener *Registry::ListenerTail; + +} + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Support/RegistryParser.h b/libclamav/c++/llvm/include/llvm/Support/RegistryParser.h new file mode 100644 index 000000000..2cc578370 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Support/RegistryParser.h @@ -0,0 +1,55 @@ +//=== RegistryParser.h - Linker-supported plugin registries -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Defines a command-line parser for a registry. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_REGISTRY_PARSER_H +#define LLVM_SUPPORT_REGISTRY_PARSER_H + +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Registry.h" + +namespace llvm { + + /// A command-line parser for a registry. Use like such: + /// + /// static cl::opt::entry, false, + /// RegistryParser > + /// GCOpt("gc", cl::desc("Garbage collector to use."), + /// cl::value_desc()); + /// + /// To make use of the value: + /// + /// Collector *TheCollector = GCOpt->instantiate(); + /// + template > + class RegistryParser : + public cl::parser, + public Registry::listener { + typedef U traits; + typedef typename U::entry entry; + typedef typename Registry::listener listener; + + protected: + void registered(const entry &E) { + addLiteralOption(traits::nameof(E), &E, traits::descof(E)); + } + + public: + void initialize(cl::Option &O) { + listener::init(); + cl::parser::initialize(O); + } + }; + +} + +#endif // LLVM_SUPPORT_REGISTRY_PARSER_H diff --git a/libclamav/c++/llvm/include/llvm/Support/SlowOperationInformer.h b/libclamav/c++/llvm/include/llvm/Support/SlowOperationInformer.h new file mode 100644 index 000000000..524049cbf --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Support/SlowOperationInformer.h @@ -0,0 +1,65 @@ +//===- llvm/Support/SlowOperationInformer.h - Keep user informed *- 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 a simple object which can be used to let the user know what +// is going on when a slow operation is happening, and gives them the ability to +// cancel it. Potentially slow operations can stack allocate one of these +// objects, and periodically call the "progress" method to update the progress +// bar. If the operation takes more than 1 second to complete, the progress bar +// is automatically shown and updated. As such, the slow operation should not +// print stuff to the screen, and should not be confused if an extra line +// appears on the screen (ie, the cursor should be at the start of the line). +// +// If the user presses CTRL-C during the operation, the next invocation of the +// progress method return true indicating that the operation was cancelled. +// +// Because SlowOperationInformers fiddle around with signals, they cannot be +// nested, and interact poorly with threads. The SIGALRM handler is set back to +// SIGDFL, but the SIGINT signal handler is restored when the +// SlowOperationInformer is destroyed. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_SLOW_OPERATION_INFORMER_H +#define LLVM_SUPPORT_SLOW_OPERATION_INFORMER_H + +#include +#include +#include "llvm/System/DataTypes.h" + +namespace llvm { + class SlowOperationInformer { + std::string OperationName; + unsigned LastPrintAmount; + + SlowOperationInformer(const SlowOperationInformer&); // DO NOT IMPLEMENT + void operator=(const SlowOperationInformer&); // DO NOT IMPLEMENT + public: + SlowOperationInformer(const std::string &Name); + ~SlowOperationInformer(); + + /// progress - Clients should periodically call this method when they can + /// handle cancellation. The Amount variable should indicate how far + /// along the operation is, given in 1/10ths of a percent (in other words, + /// Amount should range from 0 to 1000). If the user cancels the operation, + /// this returns true, false otherwise. + bool progress(unsigned Amount); + + /// progress - Same as the method above, but this performs the division for + /// you, and helps you avoid overflow if you are dealing with largish + /// numbers. + bool progress(unsigned Current, unsigned Maximum) { + assert(Maximum != 0 && + "Shouldn't be doing work if there is nothing to do!"); + return progress(Current*uint64_t(1000UL)/Maximum); + } + }; +} // end namespace llvm + +#endif /* SLOW_OPERATION_INFORMER_H */ diff --git a/libclamav/c++/llvm/include/llvm/Support/SourceMgr.h b/libclamav/c++/llvm/include/llvm/Support/SourceMgr.h new file mode 100644 index 000000000..b695ff10f --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Support/SourceMgr.h @@ -0,0 +1,165 @@ +//===- SourceMgr.h - Manager for Source Buffers & Diagnostics ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the SMLoc, SMDiagnostic and SourceMgr classes. This +// provides a simple substrate for diagnostics, #include handling, and other low +// level things for simple parsers. +// +//===----------------------------------------------------------------------===// + +#ifndef SUPPORT_SOURCEMGR_H +#define SUPPORT_SOURCEMGR_H + +#include +#include +#include + +namespace llvm { + class MemoryBuffer; + class SourceMgr; + class SMDiagnostic; + class raw_ostream; + +class SMLoc { + const char *Ptr; +public: + SMLoc() : Ptr(0) {} + SMLoc(const SMLoc &RHS) : Ptr(RHS.Ptr) {} + + bool isValid() const { return Ptr != 0; } + + bool operator==(const SMLoc &RHS) const { return RHS.Ptr == Ptr; } + bool operator!=(const SMLoc &RHS) const { return RHS.Ptr != Ptr; } + + const char *getPointer() const { return Ptr; } + + static SMLoc getFromPointer(const char *Ptr) { + SMLoc L; + L.Ptr = Ptr; + return L; + } +}; + +/// SourceMgr - This owns the files read by a parser, handles include stacks, +/// and handles diagnostic wrangling. +class SourceMgr { + struct SrcBuffer { + /// Buffer - The memory buffer for the file. + MemoryBuffer *Buffer; + + /// IncludeLoc - This is the location of the parent include, or null if at + /// the top level. + SMLoc IncludeLoc; + }; + + /// Buffers - This is all of the buffers that we are reading from. + std::vector Buffers; + + // IncludeDirectories - This is the list of directories we should search for + // include files in. + std::vector IncludeDirectories; + + /// LineNoCache - This is a cache for line number queries, its implementation + /// is really private to SourceMgr.cpp. + mutable void *LineNoCache; + + SourceMgr(const SourceMgr&); // DO NOT IMPLEMENT + void operator=(const SourceMgr&); // DO NOT IMPLEMENT +public: + SourceMgr() : LineNoCache(0) {} + ~SourceMgr(); + + void setIncludeDirs(const std::vector &Dirs) { + IncludeDirectories = Dirs; + } + + const SrcBuffer &getBufferInfo(unsigned i) const { + assert(i < Buffers.size() && "Invalid Buffer ID!"); + return Buffers[i]; + } + + const MemoryBuffer *getMemoryBuffer(unsigned i) const { + assert(i < Buffers.size() && "Invalid Buffer ID!"); + return Buffers[i].Buffer; + } + + SMLoc getParentIncludeLoc(unsigned i) const { + assert(i < Buffers.size() && "Invalid Buffer ID!"); + return Buffers[i].IncludeLoc; + } + + unsigned AddNewSourceBuffer(MemoryBuffer *F, SMLoc IncludeLoc) { + SrcBuffer NB; + NB.Buffer = F; + NB.IncludeLoc = IncludeLoc; + Buffers.push_back(NB); + return Buffers.size()-1; + } + + /// AddIncludeFile - Search for a file with the specified name in the current + /// directory or in one of the IncludeDirs. If no file is found, this returns + /// ~0, otherwise it returns the buffer ID of the stacked file. + unsigned AddIncludeFile(const std::string &Filename, SMLoc IncludeLoc); + + /// FindBufferContainingLoc - Return the ID of the buffer containing the + /// specified location, returning -1 if not found. + int FindBufferContainingLoc(SMLoc Loc) const; + + /// FindLineNumber - Find the line number for the specified location in the + /// specified file. This is not a fast method. + unsigned FindLineNumber(SMLoc Loc, int BufferID = -1) const; + + /// PrintMessage - Emit a message about the specified location with the + /// specified string. + /// + /// @param Type - If non-null, the kind of message (e.g., "error") which is + /// prefixed to the message. + /// @param ShowLine - Should the diagnostic show the source line. + void PrintMessage(SMLoc Loc, const std::string &Msg, const char *Type, + bool ShowLine = true) const; + + + /// GetMessage - Return an SMDiagnostic at the specified location with the + /// specified string. + /// + /// @param Type - If non-null, the kind of message (e.g., "error") which is + /// prefixed to the message. + /// @param ShowLine - Should the diagnostic show the source line. + SMDiagnostic GetMessage(SMLoc Loc, + const std::string &Msg, const char *Type, + bool ShowLine = true) const; + + +private: + void PrintIncludeStack(SMLoc IncludeLoc, raw_ostream &OS) const; +}; + + +/// SMDiagnostic - Instances of this class encapsulate one diagnostic report, +/// allowing printing to a raw_ostream as a caret diagnostic. +class SMDiagnostic { + std::string Filename; + int LineNo, ColumnNo; + std::string Message, LineContents; + unsigned ShowLine : 1; + +public: + SMDiagnostic() : LineNo(0), ColumnNo(0) {} + SMDiagnostic(const std::string &FN, int Line, int Col, + const std::string &Msg, const std::string &LineStr, + bool showline = true) + : Filename(FN), LineNo(Line), ColumnNo(Col), Message(Msg), + LineContents(LineStr), ShowLine(showline) {} + + void Print(const char *ProgName, raw_ostream &S); +}; + +} // end llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Support/StableBasicBlockNumbering.h b/libclamav/c++/llvm/include/llvm/Support/StableBasicBlockNumbering.h new file mode 100644 index 000000000..5e0f87e48 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Support/StableBasicBlockNumbering.h @@ -0,0 +1,59 @@ +//===- StableBasicBlockNumbering.h - Provide BB identifiers -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This class provides a *stable* numbering of basic blocks that does not depend +// on their address in memory (which is nondeterministic). When requested, this +// class simply provides a unique ID for each basic block in the function +// specified and the inverse mapping. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_STABLEBASICBLOCKNUMBERING_H +#define LLVM_SUPPORT_STABLEBASICBLOCKNUMBERING_H + +#include "llvm/Function.h" +#include "llvm/ADT/UniqueVector.h" + +namespace llvm { + class StableBasicBlockNumbering { + // BBNumbering - Holds the numbering. + UniqueVector BBNumbering; + public: + StableBasicBlockNumbering(Function *F = 0) { + if (F) compute(*F); + } + + /// compute - If we have not computed a numbering for the function yet, do + /// so. + void compute(Function &F) { + if (BBNumbering.empty()) { + for (Function::iterator I = F.begin(), E = F.end(); I != E; ++I) + BBNumbering.insert(I); + } + } + + /// getNumber - Return the ID number for the specified BasicBlock. + /// + unsigned getNumber(BasicBlock *BB) const { + unsigned Idx = BBNumbering.idFor(BB); + assert(Idx && "Invalid basic block or numbering not computed!"); + return Idx-1; + } + + /// getBlock - Return the BasicBlock corresponding to a particular ID. + /// + BasicBlock *getBlock(unsigned N) const { + assert(N < BBNumbering.size() && + "Block ID out of range or numbering not computed!"); + return BBNumbering[N+1]; + } + }; +} + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Support/StandardPasses.h b/libclamav/c++/llvm/include/llvm/Support/StandardPasses.h new file mode 100644 index 000000000..18be1addb --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Support/StandardPasses.h @@ -0,0 +1,247 @@ +//===-- llvm/Support/StandardPasses.h - Standard pass lists -----*- 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 utility functions for creating a "standard" set of +// optimization passes, so that compilers and tools which use optimization +// passes use the same set of standard passes. +// +// These are implemented as inline functions so that we do not have to worry +// about link issues. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_STANDARDPASSES_H +#define LLVM_SUPPORT_STANDARDPASSES_H + +#include "llvm/PassManager.h" +#include "llvm/Analysis/Passes.h" +#include "llvm/Analysis/Verifier.h" +#include "llvm/Transforms/Scalar.h" +#include "llvm/Transforms/IPO.h" + +namespace llvm { + /// createStandardFunctionPasses - Add the standard list of function passes to + /// the provided pass manager. + /// + /// \arg OptimizationLevel - The optimization level, corresponding to -O0, + /// -O1, etc. + static inline void createStandardFunctionPasses(FunctionPassManager *PM, + unsigned OptimizationLevel); + + /// createStandardModulePasses - Add the standard list of module passes to the + /// provided pass manager. + /// + /// \arg OptimizationLevel - The optimization level, corresponding to -O0, + /// -O1, etc. + /// \arg OptimizeSize - Whether the transformations should optimize for size. + /// \arg UnitAtATime - Allow passes which may make global module changes. + /// \arg UnrollLoops - Allow loop unrolling. + /// \arg SimplifyLibCalls - Allow library calls to be simplified. + /// \arg HaveExceptions - Whether the module may have code using exceptions. + /// \arg InliningPass - The inlining pass to use, if any, or null. This will + /// always be added, even at -O0.a + static inline void createStandardModulePasses(PassManager *PM, + unsigned OptimizationLevel, + bool OptimizeSize, + bool UnitAtATime, + bool UnrollLoops, + bool SimplifyLibCalls, + bool HaveExceptions, + Pass *InliningPass); + + /// createStandardLTOPasses - Add the standard list of module passes suitable + /// for link time optimization. + /// + /// Internalize - Run the internalize pass. + /// RunInliner - Use a function inlining pass. + /// VerifyEach - Run the verifier after each pass. + static inline void createStandardLTOPasses(PassManager *PM, + bool Internalize, + bool RunInliner, + bool VerifyEach); + + // Implementations + + static inline void createStandardFunctionPasses(FunctionPassManager *PM, + unsigned OptimizationLevel) { + if (OptimizationLevel > 0) { + PM->add(createCFGSimplificationPass()); + if (OptimizationLevel == 1) + PM->add(createPromoteMemoryToRegisterPass()); + else + PM->add(createScalarReplAggregatesPass()); + PM->add(createInstructionCombiningPass()); + } + } + + /// createStandardModulePasses - Add the standard module passes. This is + /// expected to be run after the standard function passes. + static inline void createStandardModulePasses(PassManager *PM, + unsigned OptimizationLevel, + bool OptimizeSize, + bool UnitAtATime, + bool UnrollLoops, + bool SimplifyLibCalls, + bool HaveExceptions, + Pass *InliningPass) { + if (OptimizationLevel == 0) { + if (InliningPass) + PM->add(InliningPass); + return; + } + + if (UnitAtATime) { + PM->add(createGlobalOptimizerPass()); // Optimize out global vars + + PM->add(createIPSCCPPass()); // IP SCCP + PM->add(createDeadArgEliminationPass()); // Dead argument elimination + } + PM->add(createInstructionCombiningPass()); // Clean up after IPCP & DAE + PM->add(createCFGSimplificationPass()); // Clean up after IPCP & DAE + + // Start of CallGraph SCC passes. + if (UnitAtATime && HaveExceptions) + PM->add(createPruneEHPass()); // Remove dead EH info + if (InliningPass) + PM->add(InliningPass); + if (UnitAtATime) + PM->add(createFunctionAttrsPass()); // Set readonly/readnone attrs + if (OptimizationLevel > 2) + PM->add(createArgumentPromotionPass()); // Scalarize uninlined fn args + + // Start of function pass. + + PM->add(createScalarReplAggregatesPass()); // Break up aggregate allocas + if (SimplifyLibCalls) + PM->add(createSimplifyLibCallsPass()); // Library Call Optimizations + PM->add(createInstructionCombiningPass()); // Cleanup for scalarrepl. + PM->add(createJumpThreadingPass()); // Thread jumps. + PM->add(createCFGSimplificationPass()); // Merge & remove BBs + PM->add(createInstructionCombiningPass()); // Combine silly seq's + + PM->add(createTailCallEliminationPass()); // Eliminate tail calls + PM->add(createCFGSimplificationPass()); // Merge & remove BBs + PM->add(createReassociatePass()); // Reassociate expressions + PM->add(createLoopRotatePass()); // Rotate Loop + PM->add(createLICMPass()); // Hoist loop invariants + PM->add(createLoopUnswitchPass(OptimizeSize || OptimizationLevel < 3)); + PM->add(createInstructionCombiningPass()); + PM->add(createIndVarSimplifyPass()); // Canonicalize indvars + PM->add(createLoopDeletionPass()); // Delete dead loops + if (UnrollLoops) + PM->add(createLoopUnrollPass()); // Unroll small loops + PM->add(createInstructionCombiningPass()); // Clean up after the unroller + PM->add(createGVNPass()); // Remove redundancies + PM->add(createMemCpyOptPass()); // Remove memcpy / form memset + PM->add(createSCCPPass()); // Constant prop with SCCP + + // Run instcombine after redundancy elimination to exploit opportunities + // opened up by them. + PM->add(createInstructionCombiningPass()); + PM->add(createJumpThreadingPass()); // Thread jumps + PM->add(createDeadStoreEliminationPass()); // Delete dead stores + PM->add(createAggressiveDCEPass()); // Delete dead instructions + PM->add(createCFGSimplificationPass()); // Merge & remove BBs + + if (UnitAtATime) { + PM->add(createStripDeadPrototypesPass()); // Get rid of dead prototypes + PM->add(createDeadTypeEliminationPass()); // Eliminate dead types + + // GlobalOpt already deletes dead functions and globals, at -O3 try a + // late pass of GlobalDCE. It is capable of deleting dead cycles. + if (OptimizationLevel > 2) + PM->add(createGlobalDCEPass()); // Remove dead fns and globals. + + if (OptimizationLevel > 1) + PM->add(createConstantMergePass()); // Merge dup global constants + } + } + + static inline void addOnePass(PassManager *PM, Pass *P, bool AndVerify) { + PM->add(P); + + if (AndVerify) + PM->add(createVerifierPass()); + } + + static inline void createStandardLTOPasses(PassManager *PM, + bool Internalize, + bool RunInliner, + bool VerifyEach) { + // Now that composite has been compiled, scan through the module, looking + // for a main function. If main is defined, mark all other functions + // internal. + if (Internalize) + addOnePass(PM, createInternalizePass(true), VerifyEach); + + // Propagate constants at call sites into the functions they call. This + // opens opportunities for globalopt (and inlining) by substituting function + // pointers passed as arguments to direct uses of functions. + addOnePass(PM, createIPSCCPPass(), VerifyEach); + + // Now that we internalized some globals, see if we can hack on them! + addOnePass(PM, createGlobalOptimizerPass(), VerifyEach); + + // Linking modules together can lead to duplicated global constants, only + // keep one copy of each constant... + addOnePass(PM, createConstantMergePass(), VerifyEach); + + // Remove unused arguments from functions... + addOnePass(PM, createDeadArgEliminationPass(), VerifyEach); + + // Reduce the code after globalopt and ipsccp. Both can open up significant + // simplification opportunities, and both can propagate functions through + // function pointers. When this happens, we often have to resolve varargs + // calls, etc, so let instcombine do this. + addOnePass(PM, createInstructionCombiningPass(), VerifyEach); + + // Inline small functions + if (RunInliner) + addOnePass(PM, createFunctionInliningPass(), VerifyEach); + + addOnePass(PM, createPruneEHPass(), VerifyEach); // Remove dead EH info. + // Optimize globals again if we ran the inliner. + if (RunInliner) + addOnePass(PM, createGlobalOptimizerPass(), VerifyEach); + addOnePass(PM, createGlobalDCEPass(), VerifyEach); // Remove dead functions. + + // If we didn't decide to inline a function, check to see if we can + // transform it to pass arguments by value instead of by reference. + addOnePass(PM, createArgumentPromotionPass(), VerifyEach); + + // The IPO passes may leave cruft around. Clean up after them. + addOnePass(PM, createInstructionCombiningPass(), VerifyEach); + addOnePass(PM, createJumpThreadingPass(), VerifyEach); + // Break up allocas + addOnePass(PM, createScalarReplAggregatesPass(), VerifyEach); + + // Run a few AA driven optimizations here and now, to cleanup the code. + addOnePass(PM, createFunctionAttrsPass(), VerifyEach); // Add nocapture. + addOnePass(PM, createGlobalsModRefPass(), VerifyEach); // IP alias analysis. + + addOnePass(PM, createLICMPass(), VerifyEach); // Hoist loop invariants. + addOnePass(PM, createGVNPass(), VerifyEach); // Remove redundancies. + addOnePass(PM, createMemCpyOptPass(), VerifyEach); // Remove dead memcpys. + // Nuke dead stores. + addOnePass(PM, createDeadStoreEliminationPass(), VerifyEach); + + // Cleanup and simplify the code after the scalar optimizations. + addOnePass(PM, createInstructionCombiningPass(), VerifyEach); + + addOnePass(PM, createJumpThreadingPass(), VerifyEach); + + // Delete basic blocks, which optimization passes may have killed. + addOnePass(PM, createCFGSimplificationPass(), VerifyEach); + + // Now that we have optimized the program, discard unreachable functions. + addOnePass(PM, createGlobalDCEPass(), VerifyEach); + } +} + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Support/StringPool.h b/libclamav/c++/llvm/include/llvm/Support/StringPool.h new file mode 100644 index 000000000..82e46d42c --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Support/StringPool.h @@ -0,0 +1,139 @@ +//===-- StringPool.h - Interned string pool ---------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares an interned string pool, which helps reduce the cost of +// strings by using the same storage for identical strings. +// +// To intern a string: +// +// StringPool Pool; +// PooledStringPtr Str = Pool.intern("wakka wakka"); +// +// To use the value of an interned string, use operator bool and operator*: +// +// if (Str) +// cerr << "the string is" << *Str << "\n"; +// +// Pooled strings are immutable, but you can change a PooledStringPtr to point +// to another instance. So that interned strings can eventually be freed, +// strings in the string pool are reference-counted (automatically). +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_STRINGPOOL_H +#define LLVM_SUPPORT_STRINGPOOL_H + +#include "llvm/ADT/StringMap.h" +#include +#include + +namespace llvm { + + class PooledStringPtr; + + /// StringPool - An interned string pool. Use the intern method to add a + /// string. Strings are removed automatically as PooledStringPtrs are + /// destroyed. + class StringPool { + /// PooledString - This is the value of an entry in the pool's interning + /// table. + struct PooledString { + StringPool *Pool; ///< So the string can remove itself. + unsigned Refcount; ///< Number of referencing PooledStringPtrs. + + public: + PooledString() : Pool(0), Refcount(0) { } + }; + + friend class PooledStringPtr; + + typedef StringMap table_t; + typedef StringMapEntry entry_t; + table_t InternTable; + + public: + StringPool(); + ~StringPool(); + + /// intern - Adds a string to the pool and returns a reference-counted + /// pointer to it. No additional memory is allocated if the string already + /// exists in the pool. + PooledStringPtr intern(const StringRef &Str); + + /// empty - Checks whether the pool is empty. Returns true if so. + /// + inline bool empty() const { return InternTable.empty(); } + }; + + /// PooledStringPtr - A pointer to an interned string. Use operator bool to + /// test whether the pointer is valid, and operator * to get the string if so. + /// This is a lightweight value class with storage requirements equivalent to + /// a single pointer, but it does have reference-counting overhead when + /// copied. + class PooledStringPtr { + typedef StringPool::entry_t entry_t; + entry_t *S; + + public: + PooledStringPtr() : S(0) {} + + explicit PooledStringPtr(entry_t *E) : S(E) { + if (S) ++S->getValue().Refcount; + } + + PooledStringPtr(const PooledStringPtr &That) : S(That.S) { + if (S) ++S->getValue().Refcount; + } + + PooledStringPtr &operator=(const PooledStringPtr &That) { + if (S != That.S) { + clear(); + S = That.S; + if (S) ++S->getValue().Refcount; + } + return *this; + } + + void clear() { + if (!S) + return; + if (--S->getValue().Refcount == 0) { + S->getValue().Pool->InternTable.remove(S); + S->Destroy(); + } + S = 0; + } + + ~PooledStringPtr() { clear(); } + + inline const char *begin() const { + assert(*this && "Attempt to dereference empty PooledStringPtr!"); + return S->getKeyData(); + } + + inline const char *end() const { + assert(*this && "Attempt to dereference empty PooledStringPtr!"); + return S->getKeyData() + S->getKeyLength(); + } + + inline unsigned size() const { + assert(*this && "Attempt to dereference empty PooledStringPtr!"); + return S->getKeyLength(); + } + + inline const char *operator*() const { return begin(); } + inline operator bool() const { return S != 0; } + + inline bool operator==(const PooledStringPtr &That) { return S == That.S; } + inline bool operator!=(const PooledStringPtr &That) { return S != That.S; } + }; + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Support/SystemUtils.h b/libclamav/c++/llvm/include/llvm/Support/SystemUtils.h new file mode 100644 index 000000000..b3d83fc24 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Support/SystemUtils.h @@ -0,0 +1,44 @@ +//===- SystemUtils.h - Utilities to do low-level system stuff ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains functions used to do a variety of low-level, often +// system-specific, tasks. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_SYSTEMUTILS_H +#define LLVM_SUPPORT_SYSTEMUTILS_H + +#include + +namespace llvm { + class raw_ostream; + namespace sys { class Path; } + +/// Determine if the raw_ostream provided is connected to the outs() and +/// displayed or not (to a console window). If so, generate a warning message +/// advising against display of bitcode and return true. Otherwise just return +/// false +/// @brief Check for output written to a console +bool CheckBitcodeOutputToConsole( + raw_ostream &stream_to_check, ///< The stream to be checked + bool print_warning = true ///< Control whether warnings are printed +); + +/// FindExecutable - Find a named executable, giving the argv[0] of program +/// being executed. This allows us to find another LLVM tool if it is built in +/// the same directory. If the executable cannot be found, return an +/// empty string. +/// @brief Find a named executable. +sys::Path FindExecutable(const std::string &ExeName, + const char *Argv0, void *MainAddr); + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Support/TargetFolder.h b/libclamav/c++/llvm/include/llvm/Support/TargetFolder.h new file mode 100644 index 000000000..afed853e8 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Support/TargetFolder.h @@ -0,0 +1,244 @@ +//====-- llvm/Support/TargetFolder.h - Constant folding helper -*- 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 the TargetFolder class, a helper for IRBuilder. +// It provides IRBuilder with a set of methods for creating constants with +// target dependent folding, in addition to the same target-independent +// folding that the ConstantFolder class provides. For general constant +// creation and folding, use ConstantExpr and the routines in +// llvm/Analysis/ConstantFolding.h. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_TARGETFOLDER_H +#define LLVM_SUPPORT_TARGETFOLDER_H + +#include "llvm/Constants.h" +#include "llvm/InstrTypes.h" +#include "llvm/Analysis/ConstantFolding.h" + +namespace llvm { + +class TargetData; + +/// TargetFolder - Create constants with target dependent folding. +class TargetFolder { + const TargetData *TD; + + /// Fold - Fold the constant using target specific information. + Constant *Fold(Constant *C) const { + if (ConstantExpr *CE = dyn_cast(C)) + if (Constant *CF = ConstantFoldConstantExpression(CE, TD)) + return CF; + return C; + } + +public: + explicit TargetFolder(const TargetData *TheTD) : TD(TheTD) {} + + //===--------------------------------------------------------------------===// + // Binary Operators + //===--------------------------------------------------------------------===// + + Constant *CreateAdd(Constant *LHS, Constant *RHS) const { + return Fold(ConstantExpr::getAdd(LHS, RHS)); + } + Constant *CreateNSWAdd(Constant *LHS, Constant *RHS) const { + return Fold(ConstantExpr::getNSWAdd(LHS, RHS)); + } + Constant *CreateFAdd(Constant *LHS, Constant *RHS) const { + return Fold(ConstantExpr::getFAdd(LHS, RHS)); + } + Constant *CreateSub(Constant *LHS, Constant *RHS) const { + return Fold(ConstantExpr::getSub(LHS, RHS)); + } + Constant *CreateNSWSub(Constant *LHS, Constant *RHS) const { + return Fold(ConstantExpr::getNSWSub(LHS, RHS)); + } + Constant *CreateFSub(Constant *LHS, Constant *RHS) const { + return Fold(ConstantExpr::getFSub(LHS, RHS)); + } + Constant *CreateMul(Constant *LHS, Constant *RHS) const { + return Fold(ConstantExpr::getMul(LHS, RHS)); + } + Constant *CreateFMul(Constant *LHS, Constant *RHS) const { + return Fold(ConstantExpr::getFMul(LHS, RHS)); + } + Constant *CreateUDiv(Constant *LHS, Constant *RHS) const { + return Fold(ConstantExpr::getUDiv(LHS, RHS)); + } + Constant *CreateSDiv(Constant *LHS, Constant *RHS) const { + return Fold(ConstantExpr::getSDiv(LHS, RHS)); + } + Constant *CreateExactSDiv(Constant *LHS, Constant *RHS) const { + return Fold(ConstantExpr::getExactSDiv(LHS, RHS)); + } + Constant *CreateFDiv(Constant *LHS, Constant *RHS) const { + return Fold(ConstantExpr::getFDiv(LHS, RHS)); + } + Constant *CreateURem(Constant *LHS, Constant *RHS) const { + return Fold(ConstantExpr::getURem(LHS, RHS)); + } + Constant *CreateSRem(Constant *LHS, Constant *RHS) const { + return Fold(ConstantExpr::getSRem(LHS, RHS)); + } + Constant *CreateFRem(Constant *LHS, Constant *RHS) const { + return Fold(ConstantExpr::getFRem(LHS, RHS)); + } + Constant *CreateShl(Constant *LHS, Constant *RHS) const { + return Fold(ConstantExpr::getShl(LHS, RHS)); + } + Constant *CreateLShr(Constant *LHS, Constant *RHS) const { + return Fold(ConstantExpr::getLShr(LHS, RHS)); + } + Constant *CreateAShr(Constant *LHS, Constant *RHS) const { + return Fold(ConstantExpr::getAShr(LHS, RHS)); + } + Constant *CreateAnd(Constant *LHS, Constant *RHS) const { + return Fold(ConstantExpr::getAnd(LHS, RHS)); + } + Constant *CreateOr(Constant *LHS, Constant *RHS) const { + return Fold(ConstantExpr::getOr(LHS, RHS)); + } + Constant *CreateXor(Constant *LHS, Constant *RHS) const { + return Fold(ConstantExpr::getXor(LHS, RHS)); + } + + Constant *CreateBinOp(Instruction::BinaryOps Opc, + Constant *LHS, Constant *RHS) const { + return Fold(ConstantExpr::get(Opc, LHS, RHS)); + } + + //===--------------------------------------------------------------------===// + // Unary Operators + //===--------------------------------------------------------------------===// + + Constant *CreateNeg(Constant *C) const { + return Fold(ConstantExpr::getNeg(C)); + } + Constant *CreateFNeg(Constant *C) const { + return Fold(ConstantExpr::getFNeg(C)); + } + Constant *CreateNot(Constant *C) const { + return Fold(ConstantExpr::getNot(C)); + } + + //===--------------------------------------------------------------------===// + // Memory Instructions + //===--------------------------------------------------------------------===// + + Constant *CreateGetElementPtr(Constant *C, Constant* const *IdxList, + unsigned NumIdx) const { + return Fold(ConstantExpr::getGetElementPtr(C, IdxList, NumIdx)); + } + Constant *CreateGetElementPtr(Constant *C, Value* const *IdxList, + unsigned NumIdx) const { + return Fold(ConstantExpr::getGetElementPtr(C, IdxList, NumIdx)); + } + + Constant *CreateInBoundsGetElementPtr(Constant *C, Constant* const *IdxList, + unsigned NumIdx) const { + return Fold(ConstantExpr::getInBoundsGetElementPtr(C, IdxList, NumIdx)); + } + Constant *CreateInBoundsGetElementPtr(Constant *C, Value* const *IdxList, + unsigned NumIdx) const { + return Fold(ConstantExpr::getInBoundsGetElementPtr(C, IdxList, NumIdx)); + } + + //===--------------------------------------------------------------------===// + // Cast/Conversion Operators + //===--------------------------------------------------------------------===// + + Constant *CreateCast(Instruction::CastOps Op, Constant *C, + const Type *DestTy) const { + if (C->getType() == DestTy) + return C; // avoid calling Fold + return Fold(ConstantExpr::getCast(Op, C, DestTy)); + } + Constant *CreateIntCast(Constant *C, const Type *DestTy, + bool isSigned) const { + if (C->getType() == DestTy) + return C; // avoid calling Fold + return Fold(ConstantExpr::getIntegerCast(C, DestTy, isSigned)); + } + + Constant *CreateBitCast(Constant *C, const Type *DestTy) const { + return CreateCast(Instruction::BitCast, C, DestTy); + } + Constant *CreateIntToPtr(Constant *C, const Type *DestTy) const { + return CreateCast(Instruction::IntToPtr, C, DestTy); + } + Constant *CreatePtrToInt(Constant *C, const Type *DestTy) const { + return CreateCast(Instruction::PtrToInt, C, DestTy); + } + Constant *CreateZExtOrBitCast(Constant *C, const Type *DestTy) const { + if (C->getType() == DestTy) + return C; // avoid calling Fold + return Fold(ConstantExpr::getZExtOrBitCast(C, DestTy)); + } + Constant *CreateSExtOrBitCast(Constant *C, const Type *DestTy) const { + if (C->getType() == DestTy) + return C; // avoid calling Fold + return Fold(ConstantExpr::getSExtOrBitCast(C, DestTy)); + } + Constant *CreateTruncOrBitCast(Constant *C, const Type *DestTy) const { + if (C->getType() == DestTy) + return C; // avoid calling Fold + return Fold(ConstantExpr::getTruncOrBitCast(C, DestTy)); + } + + //===--------------------------------------------------------------------===// + // Compare Instructions + //===--------------------------------------------------------------------===// + + Constant *CreateICmp(CmpInst::Predicate P, Constant *LHS, + Constant *RHS) const { + return Fold(ConstantExpr::getCompare(P, LHS, RHS)); + } + Constant *CreateFCmp(CmpInst::Predicate P, Constant *LHS, + Constant *RHS) const { + return Fold(ConstantExpr::getCompare(P, LHS, RHS)); + } + + //===--------------------------------------------------------------------===// + // Other Instructions + //===--------------------------------------------------------------------===// + + Constant *CreateSelect(Constant *C, Constant *True, Constant *False) const { + return Fold(ConstantExpr::getSelect(C, True, False)); + } + + Constant *CreateExtractElement(Constant *Vec, Constant *Idx) const { + return Fold(ConstantExpr::getExtractElement(Vec, Idx)); + } + + Constant *CreateInsertElement(Constant *Vec, Constant *NewElt, + Constant *Idx) const { + return Fold(ConstantExpr::getInsertElement(Vec, NewElt, Idx)); + } + + Constant *CreateShuffleVector(Constant *V1, Constant *V2, + Constant *Mask) const { + return Fold(ConstantExpr::getShuffleVector(V1, V2, Mask)); + } + + Constant *CreateExtractValue(Constant *Agg, const unsigned *IdxList, + unsigned NumIdx) const { + return Fold(ConstantExpr::getExtractValue(Agg, IdxList, NumIdx)); + } + + Constant *CreateInsertValue(Constant *Agg, Constant *Val, + const unsigned *IdxList, unsigned NumIdx) const { + return Fold(ConstantExpr::getInsertValue(Agg, Val, IdxList, NumIdx)); + } +}; + +} + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Support/Timer.h b/libclamav/c++/llvm/include/llvm/Support/Timer.h new file mode 100644 index 000000000..8a0f55d9b --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Support/Timer.h @@ -0,0 +1,189 @@ +//===-- llvm/Support/Timer.h - Interval Timing Support ----------*- 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 three classes: Timer, TimeRegion, and TimerGroup, +// documented below. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_TIMER_H +#define LLVM_SUPPORT_TIMER_H + +#include "llvm/System/DataTypes.h" +#include "llvm/System/Mutex.h" +#include +#include +#include + +namespace llvm { + +class TimerGroup; +class raw_ostream; + +/// Timer - This class is used to track the amount of time spent between +/// invocations of its startTimer()/stopTimer() methods. Given appropriate OS +/// support it can also keep track of the RSS of the program at various points. +/// By default, the Timer will print the amount of time it has captured to +/// standard error when the laster timer is destroyed, otherwise it is printed +/// when its TimerGroup is destroyed. Timers do not print their information +/// if they are never started. +/// +class Timer { + double Elapsed; // Wall clock time elapsed in seconds + double UserTime; // User time elapsed + double SystemTime; // System time elapsed + ssize_t MemUsed; // Memory allocated (in bytes) + size_t PeakMem; // Peak memory used + size_t PeakMemBase; // Temporary for peak calculation... + std::string Name; // The name of this time variable + bool Started; // Has this time variable ever been started? + TimerGroup *TG; // The TimerGroup this Timer is in. + mutable sys::SmartMutex Lock; // Mutex for the contents of this Timer. +public: + explicit Timer(const std::string &N); + Timer(const std::string &N, TimerGroup &tg); + Timer(const Timer &T); + ~Timer(); + + double getProcessTime() const { return UserTime+SystemTime; } + double getWallTime() const { return Elapsed; } + ssize_t getMemUsed() const { return MemUsed; } + size_t getPeakMem() const { return PeakMem; } + std::string getName() const { return Name; } + + const Timer &operator=(const Timer &T) { + if (&T < this) { + T.Lock.acquire(); + Lock.acquire(); + } else { + Lock.acquire(); + T.Lock.acquire(); + } + + Elapsed = T.Elapsed; + UserTime = T.UserTime; + SystemTime = T.SystemTime; + MemUsed = T.MemUsed; + PeakMem = T.PeakMem; + PeakMemBase = T.PeakMemBase; + Name = T.Name; + Started = T.Started; + assert(TG == T.TG && "Can only assign timers in the same TimerGroup!"); + + if (&T < this) { + T.Lock.release(); + Lock.release(); + } else { + Lock.release(); + T.Lock.release(); + } + + return *this; + } + + // operator< - Allow sorting... + bool operator<(const Timer &T) const { + // Sort by Wall Time elapsed, as it is the only thing really accurate + return Elapsed < T.Elapsed; + } + bool operator>(const Timer &T) const { return T.operator<(*this); } + + /// startTimer - Start the timer running. Time between calls to + /// startTimer/stopTimer is counted by the Timer class. Note that these calls + /// must be correctly paired. + /// + void startTimer(); + + /// stopTimer - Stop the timer. + /// + void stopTimer(); + + /// addPeakMemoryMeasurement - This method should be called whenever memory + /// usage needs to be checked. It adds a peak memory measurement to the + /// currently active timers, which will be printed when the timer group prints + /// + static void addPeakMemoryMeasurement(); + + /// print - Print the current timer to standard error, and reset the "Started" + /// flag. + void print(const Timer &Total, raw_ostream &OS); + +private: + friend class TimerGroup; + + // Copy ctor, initialize with no TG member. + Timer(bool, const Timer &T); + + /// sum - Add the time accumulated in the specified timer into this timer. + /// + void sum(const Timer &T); +}; + + +/// The TimeRegion class is used as a helper class to call the startTimer() and +/// stopTimer() methods of the Timer class. When the object is constructed, it +/// starts the timer specified as it's argument. When it is destroyed, it stops +/// the relevant timer. This makes it easy to time a region of code. +/// +class TimeRegion { + Timer *T; + TimeRegion(const TimeRegion &); // DO NOT IMPLEMENT +public: + explicit TimeRegion(Timer &t) : T(&t) { + T->startTimer(); + } + explicit TimeRegion(Timer *t) : T(t) { + if (T) + T->startTimer(); + } + ~TimeRegion() { + if (T) + T->stopTimer(); + } +}; + + +/// NamedRegionTimer - This class is basically a combination of TimeRegion and +/// Timer. It allows you to declare a new timer, AND specify the region to +/// time, all in one statement. All timers with the same name are merged. This +/// is primarily used for debugging and for hunting performance problems. +/// +struct NamedRegionTimer : public TimeRegion { + explicit NamedRegionTimer(const std::string &Name); + explicit NamedRegionTimer(const std::string &Name, + const std::string &GroupName); +}; + + +/// The TimerGroup class is used to group together related timers into a single +/// report that is printed when the TimerGroup is destroyed. It is illegal to +/// destroy a TimerGroup object before all of the Timers in it are gone. A +/// TimerGroup can be specified for a newly created timer in its constructor. +/// +class TimerGroup { + std::string Name; + unsigned NumTimers; + std::vector TimersToPrint; +public: + explicit TimerGroup(const std::string &name) : Name(name), NumTimers(0) {} + ~TimerGroup() { + assert(NumTimers == 0 && + "TimerGroup destroyed before all contained timers!"); + } + +private: + friend class Timer; + void addTimer(); + void removeTimer(); + void addTimerToPrint(const Timer &T); +}; + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Support/TypeBuilder.h b/libclamav/c++/llvm/include/llvm/Support/TypeBuilder.h new file mode 100644 index 000000000..fb22e3f52 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Support/TypeBuilder.h @@ -0,0 +1,387 @@ +//===---- llvm/Support/TypeBuilder.h - Builder for LLVM types ---*- 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 the TypeBuilder class, which is used as a convenient way to +// create LLVM types with a consistent and simplified interface. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_TYPEBUILDER_H +#define LLVM_SUPPORT_TYPEBUILDER_H + +#include "llvm/DerivedTypes.h" +#include "llvm/LLVMContext.h" +#include + +namespace llvm { + +/// TypeBuilder - This provides a uniform API for looking up types +/// known at compile time. To support cross-compilation, we define a +/// series of tag types in the llvm::types namespace, like i, +/// ieee_float, ppc_fp128, etc. TypeBuilder allows T to be +/// any of these, a native C type (whose size may depend on the host +/// compiler), or a pointer, function, or struct type built out of +/// these. TypeBuilder removes native C types from this set +/// to guarantee that its result is suitable for cross-compilation. +/// We define the primitive types, pointer types, and functions up to +/// 5 arguments here, but to use this class with your own types, +/// you'll need to specialize it. For example, say you want to call a +/// function defined externally as: +/// +/// struct MyType { +/// int32 a; +/// int32 *b; +/// void *array[1]; // Intended as a flexible array. +/// }; +/// int8 AFunction(struct MyType *value); +/// +/// You'll want to use +/// Function::Create(TypeBuilder(MyType*), true>::get(), ...) +/// to declare the function, but when you first try this, your compiler will +/// complain that TypeBuilder::get() doesn't exist. To fix this, +/// write: +/// +/// namespace llvm { +/// template class TypeBuilder { +/// public: +/// static const StructType *get(LLVMContext &Context) { +/// // If you cache this result, be sure to cache it separately +/// // for each LLVMContext. +/// return StructType::get( +/// TypeBuilder, xcompile>::get(Context), +/// TypeBuilder*, xcompile>::get(Context), +/// TypeBuilder*[], xcompile>::get(Context), +/// NULL); +/// } +/// +/// // You may find this a convenient place to put some constants +/// // to help with getelementptr. They don't have any effect on +/// // the operation of TypeBuilder. +/// enum Fields { +/// FIELD_A, +/// FIELD_B, +/// FIELD_ARRAY +/// }; +/// } +/// } // namespace llvm +/// +/// TypeBuilder cannot handle recursive types or types you only know at runtime. +/// If you try to give it a recursive type, it will deadlock, infinitely +/// recurse, or throw a recursive_init exception. +template class TypeBuilder {}; + +// Types for use with cross-compilable TypeBuilders. These correspond +// exactly with an LLVM-native type. +namespace types { +/// i corresponds to the LLVM IntegerType with N bits. +template class i {}; + +// The following classes represent the LLVM floating types. +class ieee_float {}; +class ieee_double {}; +class x86_fp80 {}; +class fp128 {}; +class ppc_fp128 {}; +} // namespace types + +// LLVM doesn't have const or volatile types. +template class TypeBuilder + : public TypeBuilder {}; +template class TypeBuilder + : public TypeBuilder {}; +template class TypeBuilder + : public TypeBuilder {}; + +// Pointers +template class TypeBuilder { +public: + static const PointerType *get(LLVMContext &Context) { + return PointerType::getUnqual(TypeBuilder::get(Context)); + } +}; + +/// There is no support for references +template class TypeBuilder {}; + +// Arrays +template class TypeBuilder { +public: + static const ArrayType *get(LLVMContext &Context) { + return ArrayType::get(TypeBuilder::get(Context), N); + } +}; +/// LLVM uses an array of length 0 to represent an unknown-length array. +template class TypeBuilder { +public: + static const ArrayType *get(LLVMContext &Context) { + return ArrayType::get(TypeBuilder::get(Context), 0); + } +}; + +// Define the C integral types only for TypeBuilder. +// +// C integral types do not have a defined size. It would be nice to use the +// stdint.h-defined typedefs that do have defined sizes, but we'd run into the +// following problem: +// +// On an ILP32 machine, stdint.h might define: +// +// typedef int int32_t; +// typedef long long int64_t; +// typedef long size_t; +// +// If we defined TypeBuilder and TypeBuilder, then any use of +// TypeBuilder would fail. We couldn't define TypeBuilder in +// addition to the defined-size types because we'd get duplicate definitions on +// platforms where stdint.h instead defines: +// +// typedef int int32_t; +// typedef long long int64_t; +// typedef int size_t; +// +// So we define all the primitive C types and nothing else. +#define DEFINE_INTEGRAL_TYPEBUILDER(T) \ +template<> class TypeBuilder { \ +public: \ + static const IntegerType *get(LLVMContext &Context) { \ + return IntegerType::get(Context, sizeof(T) * CHAR_BIT); \ + } \ +}; \ +template<> class TypeBuilder { \ + /* We provide a definition here so users don't accidentally */ \ + /* define these types to work. */ \ +} +DEFINE_INTEGRAL_TYPEBUILDER(char); +DEFINE_INTEGRAL_TYPEBUILDER(signed char); +DEFINE_INTEGRAL_TYPEBUILDER(unsigned char); +DEFINE_INTEGRAL_TYPEBUILDER(short); +DEFINE_INTEGRAL_TYPEBUILDER(unsigned short); +DEFINE_INTEGRAL_TYPEBUILDER(int); +DEFINE_INTEGRAL_TYPEBUILDER(unsigned int); +DEFINE_INTEGRAL_TYPEBUILDER(long); +DEFINE_INTEGRAL_TYPEBUILDER(unsigned long); +#ifdef _MSC_VER +DEFINE_INTEGRAL_TYPEBUILDER(__int64); +DEFINE_INTEGRAL_TYPEBUILDER(unsigned __int64); +#else /* _MSC_VER */ +DEFINE_INTEGRAL_TYPEBUILDER(long long); +DEFINE_INTEGRAL_TYPEBUILDER(unsigned long long); +#endif /* _MSC_VER */ +#undef DEFINE_INTEGRAL_TYPEBUILDER + +template +class TypeBuilder, cross> { +public: + static const IntegerType *get(LLVMContext &C) { + return IntegerType::get(C, num_bits); + } +}; + +template<> class TypeBuilder { +public: + static const Type *get(LLVMContext& C) { + return Type::getFloatTy(C); + } +}; +template<> class TypeBuilder {}; + +template<> class TypeBuilder { +public: + static const Type *get(LLVMContext& C) { + return Type::getDoubleTy(C); + } +}; +template<> class TypeBuilder {}; + +template class TypeBuilder { +public: + static const Type *get(LLVMContext& C) { return Type::getFloatTy(C); } +}; +template class TypeBuilder { +public: + static const Type *get(LLVMContext& C) { return Type::getDoubleTy(C); } +}; +template class TypeBuilder { +public: + static const Type *get(LLVMContext& C) { return Type::getX86_FP80Ty(C); } +}; +template class TypeBuilder { +public: + static const Type *get(LLVMContext& C) { return Type::getFP128Ty(C); } +}; +template class TypeBuilder { +public: + static const Type *get(LLVMContext& C) { return Type::getPPC_FP128Ty(C); } +}; + +template class TypeBuilder { +public: + static const Type *get(LLVMContext &C) { + return Type::getVoidTy(C); + } +}; + +/// void* is disallowed in LLVM types, but it occurs often enough in C code that +/// we special case it. +template<> class TypeBuilder + : public TypeBuilder*, false> {}; + +template class TypeBuilder { +public: + static const FunctionType *get(LLVMContext &Context) { + return FunctionType::get(TypeBuilder::get(Context), false); + } +}; +template class TypeBuilder { +public: + static const FunctionType *get(LLVMContext &Context) { + std::vector params; + params.reserve(1); + params.push_back(TypeBuilder::get(Context)); + return FunctionType::get(TypeBuilder::get(Context), + params, false); + } +}; +template +class TypeBuilder { +public: + static const FunctionType *get(LLVMContext &Context) { + std::vector params; + params.reserve(2); + params.push_back(TypeBuilder::get(Context)); + params.push_back(TypeBuilder::get(Context)); + return FunctionType::get(TypeBuilder::get(Context), + params, false); + } +}; +template +class TypeBuilder { +public: + static const FunctionType *get(LLVMContext &Context) { + std::vector params; + params.reserve(3); + params.push_back(TypeBuilder::get(Context)); + params.push_back(TypeBuilder::get(Context)); + params.push_back(TypeBuilder::get(Context)); + return FunctionType::get(TypeBuilder::get(Context), + params, false); + } +}; + +template +class TypeBuilder { +public: + static const FunctionType *get(LLVMContext &Context) { + std::vector params; + params.reserve(4); + params.push_back(TypeBuilder::get(Context)); + params.push_back(TypeBuilder::get(Context)); + params.push_back(TypeBuilder::get(Context)); + params.push_back(TypeBuilder::get(Context)); + return FunctionType::get(TypeBuilder::get(Context), + params, false); + } +}; + +template +class TypeBuilder { +public: + static const FunctionType *get(LLVMContext &Context) { + std::vector params; + params.reserve(5); + params.push_back(TypeBuilder::get(Context)); + params.push_back(TypeBuilder::get(Context)); + params.push_back(TypeBuilder::get(Context)); + params.push_back(TypeBuilder::get(Context)); + params.push_back(TypeBuilder::get(Context)); + return FunctionType::get(TypeBuilder::get(Context), + params, false); + } +}; + +template class TypeBuilder { +public: + static const FunctionType *get(LLVMContext &Context) { + return FunctionType::get(TypeBuilder::get(Context), true); + } +}; +template +class TypeBuilder { +public: + static const FunctionType *get(LLVMContext &Context) { + std::vector params; + params.reserve(1); + params.push_back(TypeBuilder::get(Context)); + return FunctionType::get(TypeBuilder::get(Context), params, true); + } +}; +template +class TypeBuilder { +public: + static const FunctionType *get(LLVMContext &Context) { + std::vector params; + params.reserve(2); + params.push_back(TypeBuilder::get(Context)); + params.push_back(TypeBuilder::get(Context)); + return FunctionType::get(TypeBuilder::get(Context), + params, true); + } +}; +template +class TypeBuilder { +public: + static const FunctionType *get(LLVMContext &Context) { + std::vector params; + params.reserve(3); + params.push_back(TypeBuilder::get(Context)); + params.push_back(TypeBuilder::get(Context)); + params.push_back(TypeBuilder::get(Context)); + return FunctionType::get(TypeBuilder::get(Context), + params, true); + } +}; + +template +class TypeBuilder { +public: + static const FunctionType *get(LLVMContext &Context) { + std::vector params; + params.reserve(4); + params.push_back(TypeBuilder::get(Context)); + params.push_back(TypeBuilder::get(Context)); + params.push_back(TypeBuilder::get(Context)); + params.push_back(TypeBuilder::get(Context)); + return FunctionType::get(TypeBuilder::get(Context), + params, true); + } +}; + +template +class TypeBuilder { +public: + static const FunctionType *get(LLVMContext &Context) { + std::vector params; + params.reserve(5); + params.push_back(TypeBuilder::get(Context)); + params.push_back(TypeBuilder::get(Context)); + params.push_back(TypeBuilder::get(Context)); + params.push_back(TypeBuilder::get(Context)); + params.push_back(TypeBuilder::get(Context)); + return FunctionType::get(TypeBuilder::get(Context), + params, true); + } +}; + +} // namespace llvm + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Support/ValueHandle.h b/libclamav/c++/llvm/include/llvm/Support/ValueHandle.h new file mode 100644 index 000000000..a9872a7be --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Support/ValueHandle.h @@ -0,0 +1,406 @@ +//===- llvm/Support/ValueHandle.h - Value Smart Pointer classes -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the ValueHandle class and its sub-classes. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_VALUEHANDLE_H +#define LLVM_SUPPORT_VALUEHANDLE_H + +#include "llvm/ADT/DenseMapInfo.h" +#include "llvm/ADT/PointerIntPair.h" +#include "llvm/Value.h" + +namespace llvm { +class ValueHandleBase; + +// ValueHandleBase** is only 4-byte aligned. +template<> +class PointerLikeTypeTraits { +public: + static inline void *getAsVoidPointer(ValueHandleBase** P) { return P; } + static inline ValueHandleBase **getFromVoidPointer(void *P) { + return static_cast(P); + } + enum { NumLowBitsAvailable = 2 }; +}; + +/// ValueHandleBase - This is the common base class of value handles. +/// ValueHandle's are smart pointers to Value's that have special behavior when +/// the value is deleted or ReplaceAllUsesWith'd. See the specific handles +/// below for details. +/// +class ValueHandleBase { + friend class Value; +protected: + /// HandleBaseKind - This indicates what sub class the handle actually is. + /// This is to avoid having a vtable for the light-weight handle pointers. The + /// fully general Callback version does have a vtable. + enum HandleBaseKind { + Assert, + Callback, + Tracking, + Weak + }; +private: + + PointerIntPair PrevPair; + ValueHandleBase *Next; + Value *VP; + + explicit ValueHandleBase(const ValueHandleBase&); // DO NOT IMPLEMENT. +public: + explicit ValueHandleBase(HandleBaseKind Kind) + : PrevPair(0, Kind), Next(0), VP(0) {} + ValueHandleBase(HandleBaseKind Kind, Value *V) + : PrevPair(0, Kind), Next(0), VP(V) { + if (isValid(VP)) + AddToUseList(); + } + ValueHandleBase(HandleBaseKind Kind, const ValueHandleBase &RHS) + : PrevPair(0, Kind), Next(0), VP(RHS.VP) { + if (isValid(VP)) + AddToExistingUseList(RHS.getPrevPtr()); + } + ~ValueHandleBase() { + if (isValid(VP)) + RemoveFromUseList(); + } + + Value *operator=(Value *RHS) { + if (VP == RHS) return RHS; + if (isValid(VP)) RemoveFromUseList(); + VP = RHS; + if (isValid(VP)) AddToUseList(); + return RHS; + } + + Value *operator=(const ValueHandleBase &RHS) { + if (VP == RHS.VP) return RHS.VP; + if (isValid(VP)) RemoveFromUseList(); + VP = RHS.VP; + if (isValid(VP)) AddToExistingUseList(RHS.getPrevPtr()); + return VP; + } + + Value *operator->() const { return getValPtr(); } + Value &operator*() const { return *getValPtr(); } + +protected: + Value *getValPtr() const { return VP; } + static bool isValid(Value *V) { + return V && + V != DenseMapInfo::getEmptyKey() && + V != DenseMapInfo::getTombstoneKey(); + } + +private: + // Callbacks made from Value. + static void ValueIsDeleted(Value *V); + static void ValueIsRAUWd(Value *Old, Value *New); + + // Internal implementation details. + ValueHandleBase **getPrevPtr() const { return PrevPair.getPointer(); } + HandleBaseKind getKind() const { return PrevPair.getInt(); } + void setPrevPtr(ValueHandleBase **Ptr) { PrevPair.setPointer(Ptr); } + + /// AddToExistingUseList - Add this ValueHandle to the use list for VP, where + /// List is the address of either the head of the list or a Next node within + /// the existing use list. + void AddToExistingUseList(ValueHandleBase **List); + + /// AddToExistingUseListAfter - Add this ValueHandle to the use list after + /// Node. + void AddToExistingUseListAfter(ValueHandleBase *Node); + + /// AddToUseList - Add this ValueHandle to the use list for VP. + void AddToUseList(); + /// RemoveFromUseList - Remove this ValueHandle from its current use list. + void RemoveFromUseList(); +}; + +/// WeakVH - This is a value handle that tries hard to point to a Value, even +/// across RAUW operations, but will null itself out if the value is destroyed. +/// this is useful for advisory sorts of information, but should not be used as +/// the key of a map (since the map would have to rearrange itself when the +/// pointer changes). +class WeakVH : public ValueHandleBase { +public: + WeakVH() : ValueHandleBase(Weak) {} + WeakVH(Value *P) : ValueHandleBase(Weak, P) {} + WeakVH(const WeakVH &RHS) + : ValueHandleBase(Weak, RHS) {} + + Value *operator=(Value *RHS) { + return ValueHandleBase::operator=(RHS); + } + Value *operator=(const ValueHandleBase &RHS) { + return ValueHandleBase::operator=(RHS); + } + + operator Value*() const { + return getValPtr(); + } +}; + +// Specialize simplify_type to allow WeakVH to participate in +// dyn_cast, isa, etc. +template struct simplify_type; +template<> struct simplify_type { + typedef Value* SimpleType; + static SimpleType getSimplifiedValue(const WeakVH &WVH) { + return static_cast(WVH); + } +}; +template<> struct simplify_type : public simplify_type {}; + +/// AssertingVH - This is a Value Handle that points to a value and asserts out +/// if the value is destroyed while the handle is still live. This is very +/// useful for catching dangling pointer bugs and other things which can be +/// non-obvious. One particularly useful place to use this is as the Key of a +/// map. Dangling pointer bugs often lead to really subtle bugs that only occur +/// if another object happens to get allocated to the same address as the old +/// one. Using an AssertingVH ensures that an assert is triggered as soon as +/// the bad delete occurs. +/// +/// Note that an AssertingVH handle does *not* follow values across RAUW +/// operations. This means that RAUW's need to explicitly update the +/// AssertingVH's as it moves. This is required because in non-assert mode this +/// class turns into a trivial wrapper around a pointer. +template +class AssertingVH +#ifndef NDEBUG + : public ValueHandleBase +#endif + { + +#ifndef NDEBUG + ValueTy *getValPtr() const { + return static_cast(ValueHandleBase::getValPtr()); + } + void setValPtr(ValueTy *P) { + ValueHandleBase::operator=(GetAsValue(P)); + } +#else + ValueTy *ThePtr; + ValueTy *getValPtr() const { return ThePtr; } + void setValPtr(ValueTy *P) { ThePtr = P; } +#endif + + // Convert a ValueTy*, which may be const, to the type the base + // class expects. + static Value *GetAsValue(Value *V) { return V; } + static Value *GetAsValue(const Value *V) { return const_cast(V); } + +public: +#ifndef NDEBUG + AssertingVH() : ValueHandleBase(Assert) {} + AssertingVH(ValueTy *P) : ValueHandleBase(Assert, GetAsValue(P)) {} + AssertingVH(const AssertingVH &RHS) : ValueHandleBase(Assert, RHS) {} +#else + AssertingVH() : ThePtr(0) {} + AssertingVH(ValueTy *P) : ThePtr(P) {} +#endif + + operator ValueTy*() const { + return getValPtr(); + } + + ValueTy *operator=(ValueTy *RHS) { + setValPtr(RHS); + return getValPtr(); + } + ValueTy *operator=(const AssertingVH &RHS) { + setValPtr(RHS.getValPtr()); + return getValPtr(); + } + + ValueTy *operator->() const { return getValPtr(); } + ValueTy &operator*() const { return *getValPtr(); } +}; + +// Specialize simplify_type to allow AssertingVH to participate in +// dyn_cast, isa, etc. +template struct simplify_type; +template<> struct simplify_type > { + typedef Value* SimpleType; + static SimpleType getSimplifiedValue(const AssertingVH &AVH) { + return static_cast(AVH); + } +}; +template<> struct simplify_type > + : public simplify_type > {}; + +// Specialize DenseMapInfo to allow AssertingVH to participate in DenseMap. +template +struct DenseMapInfo > { + typedef DenseMapInfo PointerInfo; + static inline AssertingVH getEmptyKey() { + return AssertingVH(PointerInfo::getEmptyKey()); + } + static inline T* getTombstoneKey() { + return AssertingVH(PointerInfo::getTombstoneKey()); + } + static unsigned getHashValue(const AssertingVH &Val) { + return PointerInfo::getHashValue(Val); + } + static bool isEqual(const AssertingVH &LHS, const AssertingVH &RHS) { + return LHS == RHS; + } + static bool isPod() { +#ifdef NDEBUG + return true; +#else + return false; +#endif + } +}; + +/// TrackingVH - This is a value handle that tracks a Value (or Value subclass), +/// even across RAUW operations. +/// +/// TrackingVH is designed for situations where a client needs to hold a handle +/// to a Value (or subclass) across some operations which may move that value, +/// but should never destroy it or replace it with some unacceptable type. +/// +/// It is an error to do anything with a TrackingVH whose value has been +/// destroyed, except to destruct it. +/// +/// It is an error to attempt to replace a value with one of a type which is +/// incompatible with any of its outstanding TrackingVHs. +template +class TrackingVH : public ValueHandleBase { + void CheckValidity() const { + Value *VP = ValueHandleBase::getValPtr(); + + // Null is always ok. + if (!VP) + return; + + // Check that this value is valid (i.e., it hasn't been deleted). We + // explicitly delay this check until access to avoid requiring clients to be + // unnecessarily careful w.r.t. destruction. + assert(ValueHandleBase::isValid(VP) && "Tracked Value was deleted!"); + + // Check that the value is a member of the correct subclass. We would like + // to check this property on assignment for better debugging, but we don't + // want to require a virtual interface on this VH. Instead we allow RAUW to + // replace this value with a value of an invalid type, and check it here. + assert(isa(VP) && + "Tracked Value was replaced by one with an invalid type!"); + } + + ValueTy *getValPtr() const { + CheckValidity(); + return static_cast(ValueHandleBase::getValPtr()); + } + void setValPtr(ValueTy *P) { + CheckValidity(); + ValueHandleBase::operator=(GetAsValue(P)); + } + + // Convert a ValueTy*, which may be const, to the type the base + // class expects. + static Value *GetAsValue(Value *V) { return V; } + static Value *GetAsValue(const Value *V) { return const_cast(V); } + +public: + TrackingVH() : ValueHandleBase(Tracking) {} + TrackingVH(ValueTy *P) : ValueHandleBase(Tracking, P) {} + TrackingVH(const TrackingVH &RHS) : ValueHandleBase(Tracking, RHS) {} + + operator ValueTy*() const { + return getValPtr(); + } + + ValueTy *operator=(ValueTy *RHS) { + setValPtr(RHS); + return getValPtr(); + } + ValueTy *operator=(const TrackingVH &RHS) { + setValPtr(RHS.getValPtr()); + return getValPtr(); + } + + ValueTy *operator->() const { return getValPtr(); } + ValueTy &operator*() const { return *getValPtr(); } +}; + +// Specialize simplify_type to allow TrackingVH to participate in +// dyn_cast, isa, etc. +template struct simplify_type; +template<> struct simplify_type > { + typedef Value* SimpleType; + static SimpleType getSimplifiedValue(const TrackingVH &AVH) { + return static_cast(AVH); + } +}; +template<> struct simplify_type > + : public simplify_type > {}; + +/// CallbackVH - This is a value handle that allows subclasses to define +/// callbacks that run when the underlying Value has RAUW called on it or is +/// destroyed. This class can be used as the key of a map, as long as the user +/// takes it out of the map before calling setValPtr() (since the map has to +/// rearrange itself when the pointer changes). Unlike ValueHandleBase, this +/// class has a vtable and a virtual destructor. +class CallbackVH : public ValueHandleBase { +protected: + CallbackVH(const CallbackVH &RHS) + : ValueHandleBase(Callback, RHS) {} + + virtual ~CallbackVH(); + + void setValPtr(Value *P) { + ValueHandleBase::operator=(P); + } + +public: + CallbackVH() : ValueHandleBase(Callback) {} + CallbackVH(Value *P) : ValueHandleBase(Callback, P) {} + + operator Value*() const { + return getValPtr(); + } + + /// Called when this->getValPtr() is destroyed, inside ~Value(), so you may + /// call any non-virtual Value method on getValPtr(), but no subclass methods. + /// If WeakVH were implemented as a CallbackVH, it would use this method to + /// call setValPtr(NULL). AssertingVH would use this method to cause an + /// assertion failure. + /// + /// All implementations must remove the reference from this object to the + /// Value that's being destroyed. + virtual void deleted() { + setValPtr(NULL); + } + + /// Called when this->getValPtr()->replaceAllUsesWith(new_value) is called, + /// _before_ any of the uses have actually been replaced. If WeakVH were + /// implemented as a CallbackVH, it would use this method to call + /// setValPtr(new_value). AssertingVH would do nothing in this method. + virtual void allUsesReplacedWith(Value *) {} +}; + +// Specialize simplify_type to allow CallbackVH to participate in +// dyn_cast, isa, etc. +template struct simplify_type; +template<> struct simplify_type { + typedef Value* SimpleType; + static SimpleType getSimplifiedValue(const CallbackVH &CVH) { + return static_cast(CVH); + } +}; +template<> struct simplify_type + : public simplify_type {}; + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Support/raw_os_ostream.h b/libclamav/c++/llvm/include/llvm/Support/raw_os_ostream.h new file mode 100644 index 000000000..e0978b238 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Support/raw_os_ostream.h @@ -0,0 +1,42 @@ +//===- raw_os_ostream.h - std::ostream adaptor for raw_ostream --*- 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 the raw_os_ostream class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_RAW_OS_OSTREAM_H +#define LLVM_SUPPORT_RAW_OS_OSTREAM_H + +#include "llvm/Support/raw_ostream.h" +#include + +namespace llvm { + +/// raw_os_ostream - A raw_ostream that writes to an std::ostream. This is a +/// simple adaptor class. It does not check for output errors; clients should +/// use the underlying stream to detect errors. +class raw_os_ostream : public raw_ostream { + std::ostream &OS; + + /// write_impl - See raw_ostream::write_impl. + virtual void write_impl(const char *Ptr, size_t Size); + + /// current_pos - Return the current position within the stream, not + /// counting the bytes currently in the buffer. + virtual uint64_t current_pos(); + +public: + raw_os_ostream(std::ostream &O) : OS(O) {} + ~raw_os_ostream(); +}; + +} // end llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Support/raw_ostream.h b/libclamav/c++/llvm/include/llvm/Support/raw_ostream.h new file mode 100644 index 000000000..a78e81fe9 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Support/raw_ostream.h @@ -0,0 +1,484 @@ +//===--- raw_ostream.h - Raw output stream ----------------------*- 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 the raw_ostream class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_RAW_OSTREAM_H +#define LLVM_SUPPORT_RAW_OSTREAM_H + +#include "llvm/ADT/StringRef.h" +#include "llvm/System/DataTypes.h" + +namespace llvm { + class format_object_base; + template + class SmallVectorImpl; + +/// raw_ostream - This class implements an extremely fast bulk output stream +/// that can *only* output to a stream. It does not support seeking, reopening, +/// rewinding, line buffered disciplines etc. It is a simple buffer that outputs +/// a chunk at a time. +class raw_ostream { +private: + // Do not implement. raw_ostream is noncopyable. + void operator=(const raw_ostream &); + raw_ostream(const raw_ostream &); + + /// The buffer is handled in such a way that the buffer is + /// uninitialized, unbuffered, or out of space when OutBufCur >= + /// OutBufEnd. Thus a single comparison suffices to determine if we + /// need to take the slow path to write a single character. + /// + /// The buffer is in one of three states: + /// 1. Unbuffered (BufferMode == Unbuffered) + /// 1. Uninitialized (BufferMode != Unbuffered && OutBufStart == 0). + /// 2. Buffered (BufferMode != Unbuffered && OutBufStart != 0 && + /// OutBufEnd - OutBufStart >= 1). + /// + /// If buffered, then the raw_ostream owns the buffer if (BufferMode == + /// InternalBuffer); otherwise the buffer has been set via SetBuffer and is + /// managed by the subclass. + /// + /// If a subclass installs an external buffer using SetBuffer then it can wait + /// for a \see write_impl() call to handle the data which has been put into + /// this buffer. + char *OutBufStart, *OutBufEnd, *OutBufCur; + + enum BufferKind { + Unbuffered = 0, + InternalBuffer, + ExternalBuffer + } BufferMode; + + /// Error This flag is true if an error of any kind has been detected. + /// + bool Error; + +public: + // color order matches ANSI escape sequence, don't change + enum Colors { + BLACK=0, + RED, + GREEN, + YELLOW, + BLUE, + MAGENTA, + CYAN, + WHITE, + SAVEDCOLOR + }; + + explicit raw_ostream(bool unbuffered=false) + : BufferMode(unbuffered ? Unbuffered : InternalBuffer), Error(false) { + // Start out ready to flush. + OutBufStart = OutBufEnd = OutBufCur = 0; + } + + virtual ~raw_ostream(); + + /// tell - Return the current offset with the file. + uint64_t tell() { return current_pos() + GetNumBytesInBuffer(); } + + /// has_error - Return the value of the flag in this raw_ostream indicating + /// whether an output error has been encountered. + bool has_error() const { + return Error; + } + + /// clear_error - Set the flag read by has_error() to false. If the error + /// flag is set at the time when this raw_ostream's destructor is called, + /// llvm_report_error is called to report the error. Use clear_error() + /// after handling the error to avoid this behavior. + void clear_error() { + Error = false; + } + + //===--------------------------------------------------------------------===// + // Configuration Interface + //===--------------------------------------------------------------------===// + + /// SetBuffered - Set the stream to be buffered, with an automatically + /// determined buffer size. + void SetBuffered(); + + /// SetBufferSize - Set the stream to be buffered, using the + /// specified buffer size. + void SetBufferSize(size_t Size) { + flush(); + SetBufferAndMode(new char[Size], Size, InternalBuffer); + } + + size_t GetBufferSize() { + // If we're supposed to be buffered but haven't actually gotten around + // to allocating the buffer yet, return the value that would be used. + if (BufferMode != Unbuffered && OutBufStart == 0) + return preferred_buffer_size(); + + // Otherwise just return the size of the allocated buffer. + return OutBufEnd - OutBufStart; + } + + /// SetUnbuffered - Set the stream to be unbuffered. When + /// unbuffered, the stream will flush after every write. This routine + /// will also flush the buffer immediately when the stream is being + /// set to unbuffered. + void SetUnbuffered() { + flush(); + SetBufferAndMode(0, 0, Unbuffered); + } + + size_t GetNumBytesInBuffer() const { + return OutBufCur - OutBufStart; + } + + //===--------------------------------------------------------------------===// + // Data Output Interface + //===--------------------------------------------------------------------===// + + void flush() { + if (OutBufCur != OutBufStart) + flush_nonempty(); + } + + raw_ostream &operator<<(char C) { + if (OutBufCur >= OutBufEnd) + return write(C); + *OutBufCur++ = C; + return *this; + } + + raw_ostream &operator<<(unsigned char C) { + if (OutBufCur >= OutBufEnd) + return write(C); + *OutBufCur++ = C; + return *this; + } + + raw_ostream &operator<<(signed char C) { + if (OutBufCur >= OutBufEnd) + return write(C); + *OutBufCur++ = C; + return *this; + } + + raw_ostream &operator<<(StringRef Str) { + // Inline fast path, particularly for strings with a known length. + size_t Size = Str.size(); + + // Make sure we can use the fast path. + if (OutBufCur+Size > OutBufEnd) + return write(Str.data(), Size); + + memcpy(OutBufCur, Str.data(), Size); + OutBufCur += Size; + return *this; + } + + raw_ostream &operator<<(const char *Str) { + // Inline fast path, particulary for constant strings where a sufficiently + // smart compiler will simplify strlen. + + this->operator<<(StringRef(Str)); + return *this; + } + + raw_ostream &operator<<(const std::string &Str) { + // Avoid the fast path, it would only increase code size for a marginal win. + write(Str.data(), Str.length()); + return *this; + } + + raw_ostream &operator<<(unsigned long N); + raw_ostream &operator<<(long N); + raw_ostream &operator<<(unsigned long long N); + raw_ostream &operator<<(long long N); + raw_ostream &operator<<(const void *P); + raw_ostream &operator<<(unsigned int N) { + this->operator<<(static_cast(N)); + return *this; + } + + raw_ostream &operator<<(int N) { + this->operator<<(static_cast(N)); + return *this; + } + + raw_ostream &operator<<(double N); + + /// write_hex - Output \arg N in hexadecimal, without any prefix or padding. + raw_ostream &write_hex(unsigned long long N); + + /// write_escaped - Output \arg Str, turning '\\', '\t', '\n', '"', and + /// anything that doesn't satisfy std::isprint into an escape sequence. + raw_ostream &write_escaped(StringRef Str); + + raw_ostream &write(unsigned char C); + raw_ostream &write(const char *Ptr, size_t Size); + + // Formatted output, see the format() function in Support/Format.h. + raw_ostream &operator<<(const format_object_base &Fmt); + + /// indent - Insert 'NumSpaces' spaces. + raw_ostream &indent(unsigned NumSpaces); + + + /// Changes the foreground color of text that will be output from this point + /// forward. + /// @param colors ANSI color to use, the special SAVEDCOLOR can be used to + /// change only the bold attribute, and keep colors untouched + /// @param bold bold/brighter text, default false + /// @param bg if true change the background, default: change foreground + /// @returns itself so it can be used within << invocations + virtual raw_ostream &changeColor(enum Colors, bool = false, + bool = false) { return *this; } + + /// Resets the colors to terminal defaults. Call this when you are done + /// outputting colored text, or before program exit. + virtual raw_ostream &resetColor() { return *this; } + + /// This function determines if this stream is connected to a "tty" or + /// "console" window. That is, the output would be displayed to the user + /// rather than being put on a pipe or stored in a file. + virtual bool is_displayed() const { return false; } + + //===--------------------------------------------------------------------===// + // Subclass Interface + //===--------------------------------------------------------------------===// + +private: + /// write_impl - The is the piece of the class that is implemented + /// by subclasses. This writes the \args Size bytes starting at + /// \arg Ptr to the underlying stream. + /// + /// This function is guaranteed to only be called at a point at which it is + /// safe for the subclass to install a new buffer via SetBuffer. + /// + /// \arg Ptr - The start of the data to be written. For buffered streams this + /// is guaranteed to be the start of the buffer. + /// \arg Size - The number of bytes to be written. + /// + /// \invariant { Size > 0 } + virtual void write_impl(const char *Ptr, size_t Size) = 0; + + // An out of line virtual method to provide a home for the class vtable. + virtual void handle(); + + /// current_pos - Return the current position within the stream, not + /// counting the bytes currently in the buffer. + virtual uint64_t current_pos() = 0; + +protected: + /// SetBuffer - Use the provided buffer as the raw_ostream buffer. This is + /// intended for use only by subclasses which can arrange for the output to go + /// directly into the desired output buffer, instead of being copied on each + /// flush. + void SetBuffer(char *BufferStart, size_t Size) { + SetBufferAndMode(BufferStart, Size, ExternalBuffer); + } + + /// preferred_buffer_size - Return an efficient buffer size for the + /// underlying output mechanism. + virtual size_t preferred_buffer_size(); + + /// error_detected - Set the flag indicating that an output error has + /// been encountered. + void error_detected() { Error = true; } + + /// getBufferStart - Return the beginning of the current stream buffer, or 0 + /// if the stream is unbuffered. + const char *getBufferStart() const { return OutBufStart; } + + //===--------------------------------------------------------------------===// + // Private Interface + //===--------------------------------------------------------------------===// +private: + /// SetBufferAndMode - Install the given buffer and mode. + void SetBufferAndMode(char *BufferStart, size_t Size, BufferKind Mode); + + /// flush_nonempty - Flush the current buffer, which is known to be + /// non-empty. This outputs the currently buffered data and resets + /// the buffer to empty. + void flush_nonempty(); + + /// copy_to_buffer - Copy data into the buffer. Size must not be + /// greater than the number of unused bytes in the buffer. + void copy_to_buffer(const char *Ptr, size_t Size); +}; + +//===----------------------------------------------------------------------===// +// File Output Streams +//===----------------------------------------------------------------------===// + +/// raw_fd_ostream - A raw_ostream that writes to a file descriptor. +/// +class raw_fd_ostream : public raw_ostream { + int FD; + bool ShouldClose; + uint64_t pos; + + /// write_impl - See raw_ostream::write_impl. + virtual void write_impl(const char *Ptr, size_t Size); + + /// current_pos - Return the current position within the stream, not + /// counting the bytes currently in the buffer. + virtual uint64_t current_pos() { return pos; } + + /// preferred_buffer_size - Determine an efficient buffer size. + virtual size_t preferred_buffer_size(); + +public: + + enum { + /// F_Excl - When opening a file, this flag makes raw_fd_ostream + /// report an error if the file already exists. + F_Excl = 1, + + /// F_Append - When opening a file, if it already exists append to the + /// existing file instead of returning an error. This may not be specified + /// with F_Excl. + F_Append = 2, + + /// F_Binary - The file should be opened in binary mode on platforms that + /// make this distinction. + F_Binary = 4 + }; + + /// raw_fd_ostream - Open the specified file for writing. If an error occurs, + /// information about the error is put into ErrorInfo, and the stream should + /// be immediately destroyed; the string will be empty if no error occurred. + /// This allows optional flags to control how the file will be opened. + /// + /// \param Filename - The file to open. If this is "-" then the + /// stream will use stdout instead. + raw_fd_ostream(const char *Filename, std::string &ErrorInfo, + unsigned Flags = 0); + + /// raw_fd_ostream ctor - FD is the file descriptor that this writes to. If + /// ShouldClose is true, this closes the file when the stream is destroyed. + raw_fd_ostream(int fd, bool shouldClose, + bool unbuffered=false) : raw_ostream(unbuffered), FD(fd), + ShouldClose(shouldClose) {} + + ~raw_fd_ostream(); + + /// close - Manually flush the stream and close the file. + void close(); + + /// seek - Flushes the stream and repositions the underlying file descriptor + /// positition to the offset specified from the beginning of the file. + uint64_t seek(uint64_t off); + + virtual raw_ostream &changeColor(enum Colors colors, bool bold=false, + bool bg=false); + virtual raw_ostream &resetColor(); + + virtual bool is_displayed() const; +}; + +/// raw_stdout_ostream - This is a stream that always prints to stdout. +/// +class raw_stdout_ostream : public raw_fd_ostream { + // An out of line virtual method to provide a home for the class vtable. + virtual void handle(); +public: + raw_stdout_ostream(); +}; + +/// raw_stderr_ostream - This is a stream that always prints to stderr. +/// +class raw_stderr_ostream : public raw_fd_ostream { + // An out of line virtual method to provide a home for the class vtable. + virtual void handle(); +public: + raw_stderr_ostream(); +}; + +/// outs() - This returns a reference to a raw_ostream for standard output. +/// Use it like: outs() << "foo" << "bar"; +raw_ostream &outs(); + +/// errs() - This returns a reference to a raw_ostream for standard error. +/// Use it like: errs() << "foo" << "bar"; +raw_ostream &errs(); + +/// nulls() - This returns a reference to a raw_ostream which simply discards +/// output. +raw_ostream &nulls(); + +//===----------------------------------------------------------------------===// +// Output Stream Adaptors +//===----------------------------------------------------------------------===// + +/// raw_string_ostream - A raw_ostream that writes to an std::string. This is a +/// simple adaptor class. This class does not encounter output errors. +class raw_string_ostream : public raw_ostream { + std::string &OS; + + /// write_impl - See raw_ostream::write_impl. + virtual void write_impl(const char *Ptr, size_t Size); + + /// current_pos - Return the current position within the stream, not + /// counting the bytes currently in the buffer. + virtual uint64_t current_pos() { return OS.size(); } +public: + explicit raw_string_ostream(std::string &O) : OS(O) {} + ~raw_string_ostream(); + + /// str - Flushes the stream contents to the target string and returns + /// the string's reference. + std::string& str() { + flush(); + return OS; + } +}; + +/// raw_svector_ostream - A raw_ostream that writes to an SmallVector or +/// SmallString. This is a simple adaptor class. This class does not +/// encounter output errors. +class raw_svector_ostream : public raw_ostream { + SmallVectorImpl &OS; + + /// write_impl - See raw_ostream::write_impl. + virtual void write_impl(const char *Ptr, size_t Size); + + /// current_pos - Return the current position within the stream, not + /// counting the bytes currently in the buffer. + virtual uint64_t current_pos(); +public: + /// Construct a new raw_svector_ostream. + /// + /// \arg O - The vector to write to; this should generally have at least 128 + /// bytes free to avoid any extraneous memory overhead. + explicit raw_svector_ostream(SmallVectorImpl &O); + ~raw_svector_ostream(); + + /// str - Flushes the stream contents to the target vector and return a + /// StringRef for the vector contents. + StringRef str(); +}; + +/// raw_null_ostream - A raw_ostream that discards all output. +class raw_null_ostream : public raw_ostream { + /// write_impl - See raw_ostream::write_impl. + virtual void write_impl(const char *Ptr, size_t size); + + /// current_pos - Return the current position within the stream, not + /// counting the bytes currently in the buffer. + virtual uint64_t current_pos(); + +public: + explicit raw_null_ostream() {} + ~raw_null_ostream(); +}; + +} // end llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Support/type_traits.h b/libclamav/c++/llvm/include/llvm/Support/type_traits.h new file mode 100644 index 000000000..ce916b5fc --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Support/type_traits.h @@ -0,0 +1,107 @@ +//===- llvm/Support/type_traits.h - Simplfied type traits -------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides a template class that determines if a type is a class or +// not. The basic mechanism, based on using the pointer to member function of +// a zero argument to a function was "boosted" from the boost type_traits +// library. See http://www.boost.org/ for all the gory details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_TYPE_TRAITS_H +#define LLVM_SUPPORT_TYPE_TRAITS_H + +// This is actually the conforming implementation which works with abstract +// classes. However, enough compilers have trouble with it that most will use +// the one in boost/type_traits/object_traits.hpp. This implementation actually +// works with VC7.0, but other interactions seem to fail when we use it. + +namespace llvm { + +namespace dont_use +{ + // These two functions should never be used. They are helpers to + // the is_class template below. They cannot be located inside + // is_class because doing so causes at least GCC to think that + // the value of the "value" enumerator is not constant. Placing + // them out here (for some strange reason) allows the sizeof + // operator against them to magically be constant. This is + // important to make the is_class::value idiom zero cost. it + // evaluates to a constant 1 or 0 depending on whether the + // parameter T is a class or not (respectively). + template char is_class_helper(void(T::*)()); + template double is_class_helper(...); +} + +template +struct is_class +{ + // is_class<> metafunction due to Paul Mensonides (leavings@attbi.com). For + // more details: + // http://groups.google.com/groups?hl=en&selm=000001c1cc83%24e154d5e0%247772e50c%40c161550a&rnum=1 + public: + enum { value = sizeof(char) == sizeof(dont_use::is_class_helper(0)) }; +}; + +/// \brief Metafunction that determines whether the two given types are +/// equivalent. +template +struct is_same { + static const bool value = false; +}; + +template +struct is_same { + static const bool value = true; +}; + +// enable_if_c - Enable/disable a template based on a metafunction +template +struct enable_if_c { + typedef T type; +}; + +template struct enable_if_c { }; + +// enable_if - Enable/disable a template based on a metafunction +template +struct enable_if : public enable_if_c { }; + +namespace dont_use { + template char base_of_helper(const volatile Base*); + template double base_of_helper(...); +} + +/// is_base_of - Metafunction to determine whether one type is a base class of +/// (or identical to) another type. +template +struct is_base_of { + static const bool value + = is_class::value && is_class::value && + sizeof(char) == sizeof(dont_use::base_of_helper((Derived*)0)); +}; + +// remove_pointer - Metafunction to turn Foo* into Foo. Defined in +// C++0x [meta.trans.ptr]. +template struct remove_pointer { typedef T type; }; +template struct remove_pointer { typedef T type; }; +template struct remove_pointer { typedef T type; }; +template struct remove_pointer { typedef T type; }; +template struct remove_pointer { + typedef T type; }; + +template +struct conditional { typedef T type; }; + +template +struct conditional { typedef F type; }; + +} + +#endif diff --git a/libclamav/c++/llvm/include/llvm/SymbolTableListTraits.h b/libclamav/c++/llvm/include/llvm/SymbolTableListTraits.h new file mode 100644 index 000000000..39953e1a5 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/SymbolTableListTraits.h @@ -0,0 +1,80 @@ +//===-- llvm/SymbolTableListTraits.h - Traits for iplist --------*- 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 a generic class that is used to implement the automatic +// symbol table manipulation that occurs when you put (for example) a named +// instruction into a basic block. +// +// The way that this is implemented is by using a special traits class with the +// intrusive list that makes up the list of instructions in a basic block. When +// a new element is added to the list of instructions, the traits class is +// notified, allowing the symbol table to be updated. +// +// This generic class implements the traits class. It must be generic so that +// it can work for all uses it, which include lists of instructions, basic +// blocks, arguments, functions, global variables, etc... +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SYMBOLTABLELISTTRAITS_H +#define LLVM_SYMBOLTABLELISTTRAITS_H + +#include "llvm/ADT/ilist.h" + +namespace llvm { +class ValueSymbolTable; + +template class ilist_iterator; +template class iplist; +template struct ilist_traits; + +// ValueSubClass - The type of objects that I hold, e.g. Instruction. +// ItemParentClass - The type of object that owns the list, e.g. BasicBlock. +// +template +class SymbolTableListTraits : public ilist_default_traits { + typedef ilist_traits TraitsClass; +public: + SymbolTableListTraits() {} + + /// getListOwner - Return the object that owns this list. If this is a list + /// of instructions, it returns the BasicBlock that owns them. + ItemParentClass *getListOwner() { + typedef iplist ItemParentClass::*Sublist; + Sublist Sub(ItemParentClass:: + getSublistAccess(static_cast(0))); + size_t Offset(size_t(&((ItemParentClass*)0->*Sub))); + iplist* Anchor(static_cast*>(this)); + return reinterpret_cast(reinterpret_cast(Anchor)- + Offset); + } + + static iplist &getList(ItemParentClass *Par) { + return Par->*(Par->getSublistAccess((ValueSubClass*)0)); + } + + static ValueSymbolTable *getSymTab(ItemParentClass *Par) { + return Par ? toPtr(Par->getValueSymbolTable()) : 0; + } + + void addNodeToList(ValueSubClass *V); + void removeNodeFromList(ValueSubClass *V); + void transferNodesFromList(ilist_traits &L2, + ilist_iterator first, + ilist_iterator last); +//private: + template + void setSymTabObject(TPtr *, TPtr); + static ValueSymbolTable *toPtr(ValueSymbolTable *P) { return P; } + static ValueSymbolTable *toPtr(ValueSymbolTable &R) { return &R; } +}; + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/System/AIXDataTypesFix.h b/libclamav/c++/llvm/include/llvm/System/AIXDataTypesFix.h new file mode 100644 index 000000000..8dbf02f28 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/System/AIXDataTypesFix.h @@ -0,0 +1,25 @@ +//===-- llvm/System/AIXDataTypesFix.h - Fix datatype defs ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file overrides default system-defined types and limits which cannot be +// done in DataTypes.h.in because it is processed by autoheader first, which +// comments out any #undef statement +// +//===----------------------------------------------------------------------===// + +// No include guards desired! + +#ifndef SUPPORT_DATATYPES_H +#error "AIXDataTypesFix.h must only be included via DataTypes.h!" +#endif + +// GCC is strict about defining large constants: they must have LL modifier. +// These will be defined properly at the end of DataTypes.h +#undef INT64_MAX +#undef INT64_MIN diff --git a/libclamav/c++/llvm/include/llvm/System/Alarm.h b/libclamav/c++/llvm/include/llvm/System/Alarm.h new file mode 100644 index 000000000..7c284167c --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/System/Alarm.h @@ -0,0 +1,51 @@ +//===- llvm/System/Alarm.h - Alarm Generation support ----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides an operating system independent interface to alarm(2) +// type functionality. The Alarm class allows a one-shot alarm to be set up +// at some number of seconds in the future. When the alarm triggers, a method +// is called to process the event +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SYSTEM_ALARM_H +#define LLVM_SYSTEM_ALARM_H + +namespace llvm { +namespace sys { + + /// This function registers an alarm to trigger some number of \p seconds in + /// the future. When that time arrives, the AlarmStatus function will begin + /// to return 1 instead of 0. The user must poll the status of the alarm by + /// making occasional calls to AlarmStatus. If the user sends an interrupt + /// signal, AlarmStatus will begin returning -1, even if the alarm event + /// occurred. + /// @returns nothing + void SetupAlarm( + unsigned seconds ///< Number of seconds in future when alarm arrives + ); + + /// This function terminates the alarm previously set up + /// @returns nothing + void TerminateAlarm(); + + /// This function acquires the status of the alarm. + /// @returns -1=cancelled, 0=untriggered, 1=triggered + int AlarmStatus(); + + /// Sleep for n seconds. Warning: mixing calls to Sleep() and other *Alarm + /// calls may be a bad idea on some platforms (source: Linux man page). + /// @returns nothing. + void Sleep(unsigned n); + + +} // End sys namespace +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/System/Atomic.h b/libclamav/c++/llvm/include/llvm/System/Atomic.h new file mode 100644 index 000000000..0c05d696e --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/System/Atomic.h @@ -0,0 +1,35 @@ +//===- llvm/System/Atomic.h - Atomic Operations -----------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the llvm::sys atomic operations. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SYSTEM_ATOMIC_H +#define LLVM_SYSTEM_ATOMIC_H + +#include "llvm/System/DataTypes.h" + +namespace llvm { + namespace sys { + void MemoryFence(); + + typedef uint32_t cas_flag; + cas_flag CompareAndSwap(volatile cas_flag* ptr, + cas_flag new_value, + cas_flag old_value); + cas_flag AtomicIncrement(volatile cas_flag* ptr); + cas_flag AtomicDecrement(volatile cas_flag* ptr); + cas_flag AtomicAdd(volatile cas_flag* ptr, cas_flag val); + cas_flag AtomicMul(volatile cas_flag* ptr, cas_flag val); + cas_flag AtomicDiv(volatile cas_flag* ptr, cas_flag val); + } +} + +#endif diff --git a/libclamav/c++/llvm/include/llvm/System/DataTypes.h.cmake b/libclamav/c++/llvm/include/llvm/System/DataTypes.h.cmake new file mode 100644 index 000000000..180c86c14 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/System/DataTypes.h.cmake @@ -0,0 +1,152 @@ +/*===-- include/System/DataTypes.h - Define fixed size types -----*- C -*-===*\ +|* *| +|* The LLVM Compiler Infrastructure *| +|* *| +|* This file is distributed under the University of Illinois Open Source *| +|* License. See LICENSE.TXT for details. *| +|* *| +|*===----------------------------------------------------------------------===*| +|* *| +|* This file contains definitions to figure out the size of _HOST_ data types.*| +|* This file is important because different host OS's define different macros,*| +|* which makes portability tough. This file exports the following *| +|* definitions: *| +|* *| +|* [u]int(32|64)_t : typedefs for signed and unsigned 32/64 bit system types*| +|* [U]INT(8|16|32|64)_(MIN|MAX) : Constants for the min and max values. *| +|* *| +|* No library is required when using these functinons. *| +|* *| +|*===----------------------------------------------------------------------===*/ + +/* Please leave this file C-compatible. */ + +#ifndef SUPPORT_DATATYPES_H +#define SUPPORT_DATATYPES_H + +#cmakedefine HAVE_SYS_TYPES_H ${HAVE_SYS_TYPES_H} +#cmakedefine HAVE_INTTYPES_H ${HAVE_INTTYPES_H} +#cmakedefine HAVE_STDINT_H ${HAVE_STDINT_H} +#cmakedefine HAVE_UINT64_T ${HAVE_UINT64_T} +#cmakedefine HAVE_U_INT64_T ${HAVE_U_INT64_T} + +#ifdef __cplusplus +#include +#else +#include +#endif + +#ifndef _MSC_VER + +/* Note that this header's correct operation depends on __STDC_LIMIT_MACROS + being defined. We would define it here, but in order to prevent Bad Things + happening when system headers or C++ STL headers include stdint.h before we + define it here, we define it on the g++ command line (in Makefile.rules). */ +#if !defined(__STDC_LIMIT_MACROS) +# error "Must #define __STDC_LIMIT_MACROS before #including System/DataTypes.h" +#endif + +#if !defined(__STDC_CONSTANT_MACROS) +# error "Must #define __STDC_CONSTANT_MACROS before " \ + "#including System/DataTypes.h" +#endif + +/* Note that includes , if this is a C99 system. */ +#ifdef HAVE_SYS_TYPES_H +#include +#endif + +#ifdef HAVE_INTTYPES_H +#include +#endif + +#ifdef HAVE_STDINT_H +#include +#endif + +#ifdef _AIX +#include "llvm/System/AIXDataTypesFix.h" +#endif + +/* Handle incorrect definition of uint64_t as u_int64_t */ +#ifndef HAVE_UINT64_T +#ifdef HAVE_U_INT64_T +typedef u_int64_t uint64_t; +#else +# error "Don't have a definition for uint64_t on this platform" +#endif +#endif + +#ifdef _OpenBSD_ +#define INT8_MAX 127 +#define INT8_MIN -128 +#define UINT8_MAX 255 +#define INT16_MAX 32767 +#define INT16_MIN -32768 +#define UINT16_MAX 65535 +#define INT32_MAX 2147483647 +#define INT32_MIN -2147483648 +#define UINT32_MAX 4294967295U +#endif + +#else /* _MSC_VER */ +/* Visual C++ doesn't provide standard integer headers, but it does provide + built-in data types. */ +#include +#include +#include +#ifdef __cplusplus +#include +#else +#include +#endif +typedef __int64 int64_t; +typedef unsigned __int64 uint64_t; +typedef signed int int32_t; +typedef unsigned int uint32_t; +typedef short int16_t; +typedef unsigned short uint16_t; +typedef signed char int8_t; +typedef unsigned char uint8_t; +typedef signed int ssize_t; +#define INT8_MAX 127 +#define INT8_MIN -128 +#define UINT8_MAX 255 +#define INT16_MAX 32767 +#define INT16_MIN -32768 +#define UINT16_MAX 65535 +#define INT32_MAX 2147483647 +#define INT32_MIN -2147483648 +#define UINT32_MAX 4294967295U +#define INT8_C(C) C +#define UINT8_C(C) C +#define INT16_C(C) C +#define UINT16_C(C) C +#define INT32_C(C) C +#define UINT32_C(C) C ## U +#define INT64_C(C) ((int64_t) C ## LL) +#define UINT64_C(C) ((uint64_t) C ## ULL) +#endif /* _MSC_VER */ + +/* Set defaults for constants which we cannot find. */ +#if !defined(INT64_MAX) +# define INT64_MAX 9223372036854775807LL +#endif +#if !defined(INT64_MIN) +# define INT64_MIN ((-INT64_MAX)-1) +#endif +#if !defined(UINT64_MAX) +# define UINT64_MAX 0xffffffffffffffffULL +#endif + +#if __GNUC__ > 3 +#define END_WITH_NULL __attribute__((sentinel)) +#else +#define END_WITH_NULL +#endif + +#ifndef HUGE_VALF +#define HUGE_VALF (float)HUGE_VAL +#endif + +#endif /* SUPPORT_DATATYPES_H */ diff --git a/libclamav/c++/llvm/include/llvm/System/DataTypes.h.in b/libclamav/c++/llvm/include/llvm/System/DataTypes.h.in new file mode 100644 index 000000000..d5749104c --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/System/DataTypes.h.in @@ -0,0 +1,147 @@ +/*===-- include/System/DataTypes.h - Define fixed size types -----*- C -*-===*\ +|* *| +|* The LLVM Compiler Infrastructure *| +|* *| +|* This file is distributed under the University of Illinois Open Source *| +|* License. See LICENSE.TXT for details. *| +|* *| +|*===----------------------------------------------------------------------===*| +|* *| +|* This file contains definitions to figure out the size of _HOST_ data types.*| +|* This file is important because different host OS's define different macros,*| +|* which makes portability tough. This file exports the following *| +|* definitions: *| +|* *| +|* [u]int(32|64)_t : typedefs for signed and unsigned 32/64 bit system types*| +|* [U]INT(8|16|32|64)_(MIN|MAX) : Constants for the min and max values. *| +|* *| +|* No library is required when using these functinons. *| +|* *| +|*===----------------------------------------------------------------------===*/ + +/* Please leave this file C-compatible. */ + +#ifndef SUPPORT_DATATYPES_H +#define SUPPORT_DATATYPES_H + +#undef HAVE_SYS_TYPES_H +#undef HAVE_INTTYPES_H +#undef HAVE_STDINT_H +#undef HAVE_UINT64_T +#undef HAVE_U_INT64_T + +#ifdef __cplusplus +#include +#else +#include +#endif + +#ifndef _MSC_VER + +/* Note that this header's correct operation depends on __STDC_LIMIT_MACROS + being defined. We would define it here, but in order to prevent Bad Things + happening when system headers or C++ STL headers include stdint.h before we + define it here, we define it on the g++ command line (in Makefile.rules). */ +#if !defined(__STDC_LIMIT_MACROS) +# error "Must #define __STDC_LIMIT_MACROS before #including System/DataTypes.h" +#endif + +#if !defined(__STDC_CONSTANT_MACROS) +# error "Must #define __STDC_CONSTANT_MACROS before " \ + "#including System/DataTypes.h" +#endif + +/* Note that includes , if this is a C99 system. */ +#ifdef HAVE_SYS_TYPES_H +#include +#endif + +#ifdef HAVE_INTTYPES_H +#include +#endif + +#ifdef HAVE_STDINT_H +#include +#endif + +#ifdef _AIX +#include "llvm/System/AIXDataTypesFix.h" +#endif + +/* Handle incorrect definition of uint64_t as u_int64_t */ +#ifndef HAVE_UINT64_T +#ifdef HAVE_U_INT64_T +typedef u_int64_t uint64_t; +#else +# error "Don't have a definition for uint64_t on this platform" +#endif +#endif + +#ifdef _OpenBSD_ +#define INT8_MAX 127 +#define INT8_MIN -128 +#define UINT8_MAX 255 +#define INT16_MAX 32767 +#define INT16_MIN -32768 +#define UINT16_MAX 65535 +#define INT32_MAX 2147483647 +#define INT32_MIN -2147483648 +#define UINT32_MAX 4294967295U +#endif + +#else /* _MSC_VER */ +/* Visual C++ doesn't provide standard integer headers, but it does provide + built-in data types. */ +#include +#include +#include +typedef __int64 int64_t; +typedef unsigned __int64 uint64_t; +typedef signed int int32_t; +typedef unsigned int uint32_t; +typedef short int16_t; +typedef unsigned short uint16_t; +typedef signed char int8_t; +typedef unsigned char uint8_t; +typedef signed int ssize_t; +#define INT8_MAX 127 +#define INT8_MIN -128 +#define UINT8_MAX 255 +#define INT16_MAX 32767 +#define INT16_MIN -32768 +#define UINT16_MAX 65535 +#define INT32_MAX 2147483647 +#define INT32_MIN -2147483648 +#define UINT32_MAX 4294967295U +#define INT8_C(C) C +#define UINT8_C(C) C +#define INT16_C(C) C +#define UINT16_C(C) C +#define INT32_C(C) C +#define UINT32_C(C) C ## U +#define INT64_C(C) ((int64_t) C ## LL) +#define UINT64_C(C) ((uint64_t) C ## ULL) +#endif /* _MSC_VER */ + +/* Set defaults for constants which we cannot find. */ +#if !defined(INT64_MAX) +# define INT64_MAX 9223372036854775807LL +#endif +#if !defined(INT64_MIN) +# define INT64_MIN ((-INT64_MAX)-1) +#endif +#if !defined(UINT64_MAX) +# define UINT64_MAX 0xffffffffffffffffULL +#endif + +#if __GNUC__ > 3 +#define END_WITH_NULL __attribute__((sentinel)) +#else +#define END_WITH_NULL +#endif + +#ifndef HUGE_VALF +#define HUGE_VALF (float)HUGE_VAL +#endif + +#endif /* SUPPORT_DATATYPES_H */ diff --git a/libclamav/c++/llvm/include/llvm/System/Disassembler.h b/libclamav/c++/llvm/include/llvm/System/Disassembler.h new file mode 100644 index 000000000..e11e792de --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/System/Disassembler.h @@ -0,0 +1,35 @@ +//===- llvm/Support/Disassembler.h ------------------------------*- 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 the necessary glue to call external disassembler +// libraries. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SYSTEM_DISASSEMBLER_H +#define LLVM_SYSTEM_DISASSEMBLER_H + +#include "llvm/System/DataTypes.h" +#include + +namespace llvm { +namespace sys { + +/// This function returns true, if there is possible to use some external +/// disassembler library. False otherwise. +bool hasDisassembler(); + +/// This function provides some "glue" code to call external disassembler +/// libraries. +std::string disassembleBuffer(uint8_t* start, size_t length, uint64_t pc = 0); + +} +} + +#endif // LLVM_SYSTEM_DISASSEMBLER_H diff --git a/libclamav/c++/llvm/include/llvm/System/DynamicLibrary.h b/libclamav/c++/llvm/include/llvm/System/DynamicLibrary.h new file mode 100644 index 000000000..ac58407a1 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/System/DynamicLibrary.h @@ -0,0 +1,86 @@ +//===-- llvm/System/DynamicLibrary.h - Portable Dynamic Library -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the sys::DynamicLibrary class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SYSTEM_DYNAMIC_LIBRARY_H +#define LLVM_SYSTEM_DYNAMIC_LIBRARY_H + +#include + +namespace llvm { +namespace sys { + + /// This class provides a portable interface to dynamic libraries which also + /// might be known as shared libraries, shared objects, dynamic shared + /// objects, or dynamic link libraries. Regardless of the terminology or the + /// operating system interface, this class provides a portable interface that + /// allows dynamic libraries to be loaded and and searched for externally + /// defined symbols. This is typically used to provide "plug-in" support. + /// It also allows for symbols to be defined which don't live in any library, + /// but rather the main program itself, useful on Windows where the main + /// executable cannot be searched. + class DynamicLibrary { + DynamicLibrary(); // DO NOT IMPLEMENT + public: + /// This function allows a library to be loaded without instantiating a + /// DynamicLibrary object. Consequently, it is marked as being permanent + /// and will only be unloaded when the program terminates. This returns + /// false on success or returns true and fills in *ErrMsg on failure. + /// @brief Open a dynamic library permanently. + /// + /// NOTE: This function is not thread safe. + /// + static bool LoadLibraryPermanently(const char *filename, + std::string *ErrMsg = 0); + + /// This function will search through all previously loaded dynamic + /// libraries for the symbol \p symbolName. If it is found, the addressof + /// that symbol is returned. If not, null is returned. Note that this will + /// search permanently loaded libraries (LoadLibraryPermanently) as well + /// as ephemerally loaded libraries (constructors). + /// @throws std::string on error. + /// @brief Search through libraries for address of a symbol + /// + /// NOTE: This function is not thread safe. + /// + static void *SearchForAddressOfSymbol(const char *symbolName); + + /// @brief Convenience function for C++ophiles. + /// + /// NOTE: This function is not thread safe. + /// + static void *SearchForAddressOfSymbol(const std::string &symbolName) { + return SearchForAddressOfSymbol(symbolName.c_str()); + } + + /// This functions permanently adds the symbol \p symbolName with the + /// value \p symbolValue. These symbols are searched before any + /// libraries. + /// @brief Add searchable symbol/value pair. + /// + /// NOTE: This function is not thread safe. + /// + static void AddSymbol(const char *symbolName, void *symbolValue); + + /// @brief Convenience function for C++ophiles. + /// + /// NOTE: This function is not thread safe. + /// + static void AddSymbol(const std::string &symbolName, void *symbolValue) { + AddSymbol(symbolName.c_str(), symbolValue); + } + }; + +} // End sys namespace +} // End llvm namespace + +#endif // LLVM_SYSTEM_DYNAMIC_LIBRARY_H diff --git a/libclamav/c++/llvm/include/llvm/System/Errno.h b/libclamav/c++/llvm/include/llvm/System/Errno.h new file mode 100644 index 000000000..6e292ba62 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/System/Errno.h @@ -0,0 +1,34 @@ +//===- llvm/System/Errno.h - Portable+convenient errno handling -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares some portable and convenient functions to deal with errno. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SYSTEM_ERRNO_H +#define LLVM_SYSTEM_ERRNO_H + +#include + +namespace llvm { +namespace sys { + +/// Returns a string representation of the errno value, using whatever +/// thread-safe variant of strerror() is available. Be sure to call this +/// immediately after the function that set errno, or errno may have been +/// overwritten by an intervening call. +std::string StrError(); + +/// Like the no-argument version above, but uses \p errnum instead of errno. +std::string StrError(int errnum); + +} // namespace sys +} // namespace llvm + +#endif // LLVM_SYSTEM_ERRNO_H diff --git a/libclamav/c++/llvm/include/llvm/System/Host.h b/libclamav/c++/llvm/include/llvm/System/Host.h new file mode 100644 index 000000000..6de1a4a9b --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/System/Host.h @@ -0,0 +1,53 @@ +//===- llvm/System/Host.h - Host machine characteristics --------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Methods for querying the nature of the host machine. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SYSTEM_HOST_H +#define LLVM_SYSTEM_HOST_H + +#include + +namespace llvm { +namespace sys { + + inline bool isLittleEndianHost() { + union { + int i; + char c; + }; + i = 1; + return c; + } + + inline bool isBigEndianHost() { + return !isLittleEndianHost(); + } + + /// getHostTriple() - Return the target triple of the running + /// system. + /// + /// The target triple is a string in the format of: + /// CPU_TYPE-VENDOR-OPERATING_SYSTEM + /// or + /// CPU_TYPE-VENDOR-KERNEL-OPERATING_SYSTEM + std::string getHostTriple(); + + /// getHostCPUName - Get the LLVM name for the host CPU. The particular format + /// of the name is target dependent, and suitable for passing as -mcpu to the + /// target which matches the host. + /// + /// \return - The host CPU name, or empty if the CPU could not be determined. + std::string getHostCPUName(); +} +} + +#endif diff --git a/libclamav/c++/llvm/include/llvm/System/IncludeFile.h b/libclamav/c++/llvm/include/llvm/System/IncludeFile.h new file mode 100644 index 000000000..3268ea225 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/System/IncludeFile.h @@ -0,0 +1,79 @@ +//===- llvm/System/IncludeFile.h - Ensure Linking Of Library ---*- 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 the FORCE_DEFINING_FILE_TO_BE_LINKED and DEFINE_FILE_FOR +// macros. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SYSTEM_INCLUDEFILE_H +#define LLVM_SYSTEM_INCLUDEFILE_H + +/// This macro is the public interface that IncludeFile.h exports. This gives +/// us the option to implement the "link the definition" capability in any +/// manner that we choose. All header files that depend on a specific .cpp +/// file being linked at run time should use this macro instead of the +/// IncludeFile class directly. +/// +/// For example, foo.h would use:
    +/// FORCE_DEFINING_FILE_TO_BE_LINKED(foo)
    +/// +/// And, foo.cp would use:
    +/// DEFINING_FILE_FOR(foo)
    +#ifdef __GNUC__ +// If the `used' attribute is available, use it to create a variable +// with an initializer that will force the linking of the defining file. +#define FORCE_DEFINING_FILE_TO_BE_LINKED(name) \ + namespace llvm { \ + extern const char name ## LinkVar; \ + __attribute__((used)) static const char *const name ## LinkObj = \ + &name ## LinkVar; \ + } +#else +// Otherwise use a constructor call. +#define FORCE_DEFINING_FILE_TO_BE_LINKED(name) \ + namespace llvm { \ + extern const char name ## LinkVar; \ + static const IncludeFile name ## LinkObj ( &name ## LinkVar ); \ + } +#endif + +/// This macro is the counterpart to FORCE_DEFINING_FILE_TO_BE_LINKED. It should +/// be used in a .cpp file to define the name referenced in a header file that +/// will cause linkage of the .cpp file. It should only be used at extern level. +#define DEFINING_FILE_FOR(name) \ + namespace llvm { const char name ## LinkVar = 0; } + +namespace llvm { + +/// This class is used in the implementation of FORCE_DEFINING_FILE_TO_BE_LINKED +/// macro to make sure that the implementation of a header file is included +/// into a tool that uses the header. This is solely +/// to overcome problems linking .a files and not getting the implementation +/// of compilation units we need. This is commonly an issue with the various +/// Passes but also occurs elsewhere in LLVM. We like to use .a files because +/// they link faster and provide the smallest executables. However, sometimes +/// those executables are too small, if the program doesn't reference something +/// that might be needed, especially by a loaded share object. This little class +/// helps to resolve that problem. The basic strategy is to use this class in +/// a header file and pass the address of a variable to the constructor. If the +/// variable is defined in the header file's corresponding .cpp file then all +/// tools/libraries that \#include the header file will require the .cpp as +/// well. +/// For example:
    +/// extern int LinkMyCodeStub;
    +/// static IncludeFile LinkMyModule(&LinkMyCodeStub);
    +/// @brief Class to ensure linking of corresponding object file. +struct IncludeFile { + explicit IncludeFile(const void *); +}; + +} + +#endif diff --git a/libclamav/c++/llvm/include/llvm/System/LICENSE.TXT b/libclamav/c++/llvm/include/llvm/System/LICENSE.TXT new file mode 100644 index 000000000..f569da205 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/System/LICENSE.TXT @@ -0,0 +1,6 @@ +LLVM System Interface Library +------------------------------------------------------------------------------- +The LLVM System Interface Library is licensed under the Illinois Open Source +License and has the following additional copyright: + +Copyright (C) 2004 eXtensible Systems, Inc. diff --git a/libclamav/c++/llvm/include/llvm/System/Memory.h b/libclamav/c++/llvm/include/llvm/System/Memory.h new file mode 100644 index 000000000..69251dd2b --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/System/Memory.h @@ -0,0 +1,97 @@ +//===- llvm/System/Memory.h - Memory Support --------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the llvm::sys::Memory class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SYSTEM_MEMORY_H +#define LLVM_SYSTEM_MEMORY_H + +#include "llvm/System/DataTypes.h" +#include + +namespace llvm { +namespace sys { + + /// This class encapsulates the notion of a memory block which has an address + /// and a size. It is used by the Memory class (a friend) as the result of + /// various memory allocation operations. + /// @see Memory + /// @brief Memory block abstraction. + class MemoryBlock { + public: + MemoryBlock() { } + MemoryBlock(void *addr, size_t size) : Address(addr), Size(size) { } + void *base() const { return Address; } + size_t size() const { return Size; } + private: + void *Address; ///< Address of first byte of memory area + size_t Size; ///< Size, in bytes of the memory area + friend class Memory; + }; + + /// This class provides various memory handling functions that manipulate + /// MemoryBlock instances. + /// @since 1.4 + /// @brief An abstraction for memory operations. + class Memory { + public: + /// This method allocates a block of Read/Write/Execute memory that is + /// suitable for executing dynamically generated code (e.g. JIT). An + /// attempt to allocate \p NumBytes bytes of virtual memory is made. + /// \p NearBlock may point to an existing allocation in which case + /// an attempt is made to allocate more memory near the existing block. + /// + /// On success, this returns a non-null memory block, otherwise it returns + /// a null memory block and fills in *ErrMsg. + /// + /// @brief Allocate Read/Write/Execute memory. + static MemoryBlock AllocateRWX(size_t NumBytes, + const MemoryBlock *NearBlock, + std::string *ErrMsg = 0); + + /// This method releases a block of Read/Write/Execute memory that was + /// allocated with the AllocateRWX method. It should not be used to + /// release any memory block allocated any other way. + /// + /// On success, this returns false, otherwise it returns true and fills + /// in *ErrMsg. + /// @throws std::string if an error occurred. + /// @brief Release Read/Write/Execute memory. + static bool ReleaseRWX(MemoryBlock &block, std::string *ErrMsg = 0); + + + /// InvalidateInstructionCache - Before the JIT can run a block of code + /// that has been emitted it must invalidate the instruction cache on some + /// platforms. + static void InvalidateInstructionCache(const void *Addr, size_t Len); + + /// setExecutable - Before the JIT can run a block of code, it has to be + /// given read and executable privilege. Return true if it is already r-x + /// or the system is able to change its previlege. + static bool setExecutable (MemoryBlock &M, std::string *ErrMsg = 0); + + /// setWritable - When adding to a block of code, the JIT may need + /// to mark a block of code as RW since the protections are on page + /// boundaries, and the JIT internal allocations are not page aligned. + static bool setWritable (MemoryBlock &M, std::string *ErrMsg = 0); + + /// setRangeExecutable - Mark the page containing a range of addresses + /// as executable. + static bool setRangeExecutable(const void *Addr, size_t Size); + + /// setRangeWritable - Mark the page containing a range of addresses + /// as writable. + static bool setRangeWritable(const void *Addr, size_t Size); + }; +} +} + +#endif diff --git a/libclamav/c++/llvm/include/llvm/System/Mutex.h b/libclamav/c++/llvm/include/llvm/System/Mutex.h new file mode 100644 index 000000000..71d10067c --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/System/Mutex.h @@ -0,0 +1,154 @@ +//===- llvm/System/Mutex.h - Mutex Operating System Concept -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the llvm::sys::Mutex class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SYSTEM_MUTEX_H +#define LLVM_SYSTEM_MUTEX_H + +#include "llvm/System/Threading.h" +#include + +namespace llvm +{ + namespace sys + { + /// @brief Platform agnostic Mutex class. + class MutexImpl + { + /// @name Constructors + /// @{ + public: + + /// Initializes the lock but doesn't acquire it. if \p recursive is set + /// to false, the lock will not be recursive which makes it cheaper but + /// also more likely to deadlock (same thread can't acquire more than + /// once). + /// @brief Default Constructor. + explicit MutexImpl(bool recursive = true); + + /// Releases and removes the lock + /// @brief Destructor + ~MutexImpl(); + + /// @} + /// @name Methods + /// @{ + public: + + /// Attempts to unconditionally acquire the lock. If the lock is held by + /// another thread, this method will wait until it can acquire the lock. + /// @returns false if any kind of error occurs, true otherwise. + /// @brief Unconditionally acquire the lock. + bool acquire(); + + /// Attempts to release the lock. If the lock is held by the current + /// thread, the lock is released allowing other threads to acquire the + /// lock. + /// @returns false if any kind of error occurs, true otherwise. + /// @brief Unconditionally release the lock. + bool release(); + + /// Attempts to acquire the lock without blocking. If the lock is not + /// available, this function returns false quickly (without blocking). If + /// the lock is available, it is acquired. + /// @returns false if any kind of error occurs or the lock is not + /// available, true otherwise. + /// @brief Try to acquire the lock. + bool tryacquire(); + + //@} + /// @name Platform Dependent Data + /// @{ + private: + void* data_; ///< We don't know what the data will be + + /// @} + /// @name Do Not Implement + /// @{ + private: + MutexImpl(const MutexImpl & original); + void operator=(const MutexImpl &); + /// @} + }; + + + /// SmartMutex - A mutex with a compile time constant parameter that + /// indicates whether this mutex should become a no-op when we're not + /// running in multithreaded mode. + template + class SmartMutex : public MutexImpl { + unsigned acquired; + bool recursive; + public: + explicit SmartMutex(bool rec = true) : + MutexImpl(rec), acquired(0), recursive(rec) { } + + bool acquire() { + if (!mt_only || llvm_is_multithreaded()) { + return MutexImpl::acquire(); + } else { + // Single-threaded debugging code. This would be racy in + // multithreaded mode, but provides not sanity checks in single + // threaded mode. + assert((recursive || acquired == 0) && "Lock already acquired!!"); + ++acquired; + return true; + } + } + + bool release() { + if (!mt_only || llvm_is_multithreaded()) { + return MutexImpl::release(); + } else { + // Single-threaded debugging code. This would be racy in + // multithreaded mode, but provides not sanity checks in single + // threaded mode. + assert(((recursive && acquired) || (acquired == 1)) && + "Lock not acquired before release!"); + --acquired; + return true; + } + } + + bool tryacquire() { + if (!mt_only || llvm_is_multithreaded()) + return MutexImpl::tryacquire(); + else return true; + } + + private: + SmartMutex(const SmartMutex & original); + void operator=(const SmartMutex &); + }; + + /// Mutex - A standard, always enforced mutex. + typedef SmartMutex Mutex; + + template + class SmartScopedLock { + SmartMutex& mtx; + + public: + SmartScopedLock(SmartMutex& m) : mtx(m) { + mtx.acquire(); + } + + ~SmartScopedLock() { + mtx.release(); + } + }; + + typedef SmartScopedLock ScopedLock; + } +} + +#endif diff --git a/libclamav/c++/llvm/include/llvm/System/Path.h b/libclamav/c++/llvm/include/llvm/System/Path.h new file mode 100644 index 000000000..b8554c829 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/System/Path.h @@ -0,0 +1,722 @@ +//===- llvm/System/Path.h - Path Operating System Concept -------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the llvm::sys::Path class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SYSTEM_PATH_H +#define LLVM_SYSTEM_PATH_H + +#include "llvm/System/TimeValue.h" +#include +#include +#include + +namespace llvm { +namespace sys { + + /// This structure provides basic file system information about a file. It + /// is patterned after the stat(2) Unix operating system call but made + /// platform independent and eliminates many of the unix-specific fields. + /// However, to support llvm-ar, the mode, user, and group fields are + /// retained. These pertain to unix security and may not have a meaningful + /// value on non-Unix platforms. However, the other fields fields should + /// always be applicable on all platforms. The structure is filled in by + /// the PathWithStatus class. + /// @brief File status structure + class FileStatus { + public: + uint64_t fileSize; ///< Size of the file in bytes + TimeValue modTime; ///< Time of file's modification + uint32_t mode; ///< Mode of the file, if applicable + uint32_t user; ///< User ID of owner, if applicable + uint32_t group; ///< Group ID of owner, if applicable + uint64_t uniqueID; ///< A number to uniquely ID this file + bool isDir : 1; ///< True if this is a directory. + bool isFile : 1; ///< True if this is a file. + + FileStatus() : fileSize(0), modTime(0,0), mode(0777), user(999), + group(999), uniqueID(0), isDir(false), isFile(false) { } + + TimeValue getTimestamp() const { return modTime; } + uint64_t getSize() const { return fileSize; } + uint32_t getMode() const { return mode; } + uint32_t getUser() const { return user; } + uint32_t getGroup() const { return group; } + uint64_t getUniqueID() const { return uniqueID; } + }; + + /// This class provides an abstraction for the path to a file or directory + /// in the operating system's filesystem and provides various basic operations + /// on it. Note that this class only represents the name of a path to a file + /// or directory which may or may not be valid for a given machine's file + /// system. The class is patterned after the java.io.File class with various + /// extensions and several omissions (not relevant to LLVM). A Path object + /// ensures that the path it encapsulates is syntactically valid for the + /// operating system it is running on but does not ensure correctness for + /// any particular file system. That is, a syntactically valid path might + /// specify path components that do not exist in the file system and using + /// such a Path to act on the file system could produce errors. There is one + /// invalid Path value which is permitted: the empty path. The class should + /// never allow a syntactically invalid non-empty path name to be assigned. + /// Empty paths are required in order to indicate an error result in some + /// situations. If the path is empty, the isValid operation will return + /// false. All operations will fail if isValid is false. Operations that + /// change the path will either return false if it would cause a syntactically + /// invalid path name (in which case the Path object is left unchanged) or + /// throw an std::string exception indicating the error. The methods are + /// grouped into four basic categories: Path Accessors (provide information + /// about the path without accessing disk), Disk Accessors (provide + /// information about the underlying file or directory), Path Mutators + /// (change the path information, not the disk), and Disk Mutators (change + /// the disk file/directory referenced by the path). The Disk Mutator methods + /// all have the word "disk" embedded in their method name to reinforce the + /// notion that the operation modifies the file system. + /// @since 1.4 + /// @brief An abstraction for operating system paths. + class Path { + /// @name Constructors + /// @{ + public: + /// Construct a path to the root directory of the file system. The root + /// directory is a top level directory above which there are no more + /// directories. For example, on UNIX, the root directory is /. On Windows + /// it is C:\. Other operating systems may have different notions of + /// what the root directory is or none at all. In that case, a consistent + /// default root directory will be used. + static Path GetRootDirectory(); + + /// Construct a path to a unique temporary directory that is created in + /// a "standard" place for the operating system. The directory is + /// guaranteed to be created on exit from this function. If the directory + /// cannot be created, the function will throw an exception. + /// @returns an invalid path (empty) on error + /// @param ErrMsg Optional place for an error message if an error occurs + /// @brief Constrct a path to an new, unique, existing temporary + /// directory. + static Path GetTemporaryDirectory(std::string* ErrMsg = 0); + + /// Construct a vector of sys::Path that contains the "standard" system + /// library paths suitable for linking into programs. This function *must* + /// return the value of LLVM_LIB_SEARCH_PATH as the first item in \p Paths + /// if that environment variable is set and it references a directory. + /// @brief Construct a path to the system library directory + static void GetSystemLibraryPaths(std::vector& Paths); + + /// Construct a vector of sys::Path that contains the "standard" bitcode + /// library paths suitable for linking into an llvm program. This function + /// *must* return the value of LLVM_LIB_SEARCH_PATH as well as the value + /// of LLVM_LIBDIR. It also must provide the System library paths as + /// returned by GetSystemLibraryPaths. + /// @see GetSystemLibraryPaths + /// @brief Construct a list of directories in which bitcode could be + /// found. + static void GetBitcodeLibraryPaths(std::vector& Paths); + + /// Find the path to a library using its short name. Use the system + /// dependent library paths to locate the library. + /// @brief Find a library. + static Path FindLibrary(std::string& short_name); + + /// Construct a path to the default LLVM configuration directory. The + /// implementation must ensure that this is a well-known (same on many + /// systems) directory in which llvm configuration files exist. For + /// example, on Unix, the /etc/llvm directory has been selected. + /// @brief Construct a path to the default LLVM configuration directory + static Path GetLLVMDefaultConfigDir(); + + /// Construct a path to the LLVM installed configuration directory. The + /// implementation must ensure that this refers to the "etc" directory of + /// the LLVM installation. This is the location where configuration files + /// will be located for a particular installation of LLVM on a machine. + /// @brief Construct a path to the LLVM installed configuration directory + static Path GetLLVMConfigDir(); + + /// Construct a path to the current user's home directory. The + /// implementation must use an operating system specific mechanism for + /// determining the user's home directory. For example, the environment + /// variable "HOME" could be used on Unix. If a given operating system + /// does not have the concept of a user's home directory, this static + /// constructor must provide the same result as GetRootDirectory. + /// @brief Construct a path to the current user's "home" directory + static Path GetUserHomeDirectory(); + + /// Construct a path to the current directory for the current process. + /// @returns The current working directory. + /// @brief Returns the current working directory. + static Path GetCurrentDirectory(); + + /// Return the suffix commonly used on file names that contain a shared + /// object, shared archive, or dynamic link library. Such files are + /// linked at runtime into a process and their code images are shared + /// between processes. + /// @returns The dynamic link library suffix for the current platform. + /// @brief Return the dynamic link library suffix. + static std::string GetDLLSuffix(); + + /// GetMainExecutable - Return the path to the main executable, given the + /// value of argv[0] from program startup and the address of main itself. + static Path GetMainExecutable(const char *argv0, void *MainAddr); + + /// This is one of the very few ways in which a path can be constructed + /// with a syntactically invalid name. The only *legal* invalid name is an + /// empty one. Other invalid names are not permitted. Empty paths are + /// provided so that they can be used to indicate null or error results in + /// other lib/System functionality. + /// @brief Construct an empty (and invalid) path. + Path() : path() {} + Path(const Path &that) : path(that.path) {} + + /// This constructor will accept a std::string as a path. No checking is + /// done on this path to determine if it is valid. To determine validity + /// of the path, use the isValid method. + /// @param p The path to assign. + /// @brief Construct a Path from a string. + explicit Path(const std::string& p); + + /// This constructor will accept a character range as a path. No checking + /// is done on this path to determine if it is valid. To determine + /// validity of the path, use the isValid method. + /// @param StrStart A pointer to the first character of the path name + /// @param StrLen The length of the path name at StrStart + /// @brief Construct a Path from a string. + Path(const char *StrStart, unsigned StrLen); + + /// @} + /// @name Operators + /// @{ + public: + /// Makes a copy of \p that to \p this. + /// @returns \p this + /// @brief Assignment Operator + Path &operator=(const Path &that) { + path = that.path; + return *this; + } + + /// Makes a copy of \p that to \p this. + /// @param \p that A std::string denoting the path + /// @returns \p this + /// @brief Assignment Operator + Path &operator=(const std::string &that); + + /// Compares \p this Path with \p that Path for equality. + /// @returns true if \p this and \p that refer to the same thing. + /// @brief Equality Operator + bool operator==(const Path &that) const; + + /// Compares \p this Path with \p that Path for inequality. + /// @returns true if \p this and \p that refer to different things. + /// @brief Inequality Operator + bool operator!=(const Path &that) const { return !(*this == that); } + + /// Determines if \p this Path is less than \p that Path. This is required + /// so that Path objects can be placed into ordered collections (e.g. + /// std::map). The comparison is done lexicographically as defined by + /// the std::string::compare method. + /// @returns true if \p this path is lexicographically less than \p that. + /// @brief Less Than Operator + bool operator<(const Path& that) const; + + /// @} + /// @name Path Accessors + /// @{ + public: + /// This function will use an operating system specific algorithm to + /// determine if the current value of \p this is a syntactically valid + /// path name for the operating system. The path name does not need to + /// exist, validity is simply syntactical. Empty paths are always invalid. + /// @returns true iff the path name is syntactically legal for the + /// host operating system. + /// @brief Determine if a path is syntactically valid or not. + bool isValid() const; + + /// This function determines if the contents of the path name are empty. + /// That is, the path name has a zero length. This does NOT determine if + /// if the file is empty. To get the length of the file itself, Use the + /// PathWithStatus::getFileStatus() method and then the getSize() method + /// on the returned FileStatus object. + /// @returns true iff the path is empty. + /// @brief Determines if the path name is empty (invalid). + bool isEmpty() const { return path.empty(); } + + /// This function returns the last component of the path name. The last + /// component is the file or directory name occuring after the last + /// directory separator. If no directory separator is present, the entire + /// path name is returned (i.e. same as toString). + /// @returns std::string containing the last component of the path name. + /// @brief Returns the last component of the path name. + std::string getLast() const; + + /// This function strips off the path and suffix of the file or directory + /// name and returns just the basename. For example /a/foo.bar would cause + /// this function to return "foo". + /// @returns std::string containing the basename of the path + /// @brief Get the base name of the path + std::string getBasename() const; + + /// This function strips off the suffix of the path beginning with the + /// path separator ('/' on Unix, '\' on Windows) and returns the result. + std::string getDirname() const; + + /// This function strips off the path and basename(up to and + /// including the last dot) of the file or directory name and + /// returns just the suffix. For example /a/foo.bar would cause + /// this function to return "bar". + /// @returns std::string containing the suffix of the path + /// @brief Get the suffix of the path + std::string getSuffix() const; + + /// Obtain a 'C' string for the path name. + /// @returns a 'C' string containing the path name. + /// @brief Returns the path as a C string. + const char *c_str() const { return path.c_str(); } + const std::string &str() const { return path; } + + + /// size - Return the length in bytes of this path name. + size_t size() const { return path.size(); } + + /// empty - Returns true if the path is empty. + unsigned empty() const { return path.empty(); } + + /// @} + /// @name Disk Accessors + /// @{ + public: + /// This function determines if the path name in this object references + /// the root (top level directory) of the file system. The details of what + /// is considered the "root" may vary from system to system so this method + /// will do the necessary checking. + /// @returns true iff the path name references the root directory. + /// @brief Determines if the path references the root directory. + bool isRootDirectory() const; + + /// This function determines if the path name is absolute, as opposed to + /// relative. + /// @brief Determine if the path is absolute. + bool isAbsolute() const; + + /// This function determines if the path name is absolute, as opposed to + /// relative. + /// @brief Determine if the path is absolute. + static bool isAbsolute(const char *NameStart, unsigned NameLen); + + /// This function opens the file associated with the path name provided by + /// the Path object and reads its magic number. If the magic number at the + /// start of the file matches \p magic, true is returned. In all other + /// cases (file not found, file not accessible, etc.) it returns false. + /// @returns true if the magic number of the file matches \p magic. + /// @brief Determine if file has a specific magic number + bool hasMagicNumber(const std::string& magic) const; + + /// This function retrieves the first \p len bytes of the file associated + /// with \p this. These bytes are returned as the "magic number" in the + /// \p Magic parameter. + /// @returns true if the Path is a file and the magic number is retrieved, + /// false otherwise. + /// @brief Get the file's magic number. + bool getMagicNumber(std::string& Magic, unsigned len) const; + + /// This function determines if the path name in the object references an + /// archive file by looking at its magic number. + /// @returns true if the file starts with the magic number for an archive + /// file. + /// @brief Determine if the path references an archive file. + bool isArchive() const; + + /// This function determines if the path name in the object references an + /// LLVM Bitcode file by looking at its magic number. + /// @returns true if the file starts with the magic number for LLVM + /// bitcode files. + /// @brief Determine if the path references a bitcode file. + bool isBitcodeFile() const; + + /// This function determines if the path name in the object references a + /// native Dynamic Library (shared library, shared object) by looking at + /// the file's magic number. The Path object must reference a file, not a + /// directory. + /// @return strue if the file starts with the magid number for a native + /// shared library. + /// @brief Determine if the path reference a dynamic library. + bool isDynamicLibrary() const; + + /// This function determines if the path name references an existing file + /// or directory in the file system. + /// @returns true if the pathname references an existing file or + /// directory. + /// @brief Determines if the path is a file or directory in + /// the file system. + bool exists() const; + + /// This function determines if the path name refences an + /// existing directory. + /// @returns true if the pathname references an existing directory. + /// @brief Determins if the path is a directory in the file system. + bool isDirectory() const; + + /// This function determines if the path name references a readable file + /// or directory in the file system. This function checks for + /// the existence and readability (by the current program) of the file + /// or directory. + /// @returns true if the pathname references a readable file. + /// @brief Determines if the path is a readable file or directory + /// in the file system. + bool canRead() const; + + /// This function determines if the path name references a writable file + /// or directory in the file system. This function checks for the + /// existence and writability (by the current program) of the file or + /// directory. + /// @returns true if the pathname references a writable file. + /// @brief Determines if the path is a writable file or directory + /// in the file system. + bool canWrite() const; + + /// This function checks that what we're trying to work only on a regular file. + /// Check for things like /dev/null, any block special file, + /// or other things that aren't "regular" regular files. + /// @returns true if the file is S_ISREG. + /// @brief Determines if the file is a regular file + bool isRegularFile() const; + + /// This function determines if the path name references an executable + /// file in the file system. This function checks for the existence and + /// executability (by the current program) of the file. + /// @returns true if the pathname references an executable file. + /// @brief Determines if the path is an executable file in the file + /// system. + bool canExecute() const; + + /// This function builds a list of paths that are the names of the + /// files and directories in a directory. + /// @returns true if an error occurs, true otherwise + /// @brief Build a list of directory's contents. + bool getDirectoryContents( + std::set &paths, ///< The resulting list of file & directory names + std::string* ErrMsg ///< Optional place to return an error message. + ) const; + + /// @} + /// @name Path Mutators + /// @{ + public: + /// The path name is cleared and becomes empty. This is an invalid + /// path name but is the *only* invalid path name. This is provided + /// so that path objects can be used to indicate the lack of a + /// valid path being found. + /// @brief Make the path empty. + void clear() { path.clear(); } + + /// This method sets the Path object to \p unverified_path. This can fail + /// if the \p unverified_path does not pass the syntactic checks of the + /// isValid() method. If verification fails, the Path object remains + /// unchanged and false is returned. Otherwise true is returned and the + /// Path object takes on the path value of \p unverified_path + /// @returns true if the path was set, false otherwise. + /// @param unverified_path The path to be set in Path object. + /// @brief Set a full path from a std::string + bool set(const std::string& unverified_path); + + /// One path component is removed from the Path. If only one component is + /// present in the path, the Path object becomes empty. If the Path object + /// is empty, no change is made. + /// @returns false if the path component could not be removed. + /// @brief Removes the last directory component of the Path. + bool eraseComponent(); + + /// The \p component is added to the end of the Path if it is a legal + /// name for the operating system. A directory separator will be added if + /// needed. + /// @returns false if the path component could not be added. + /// @brief Appends one path component to the Path. + bool appendComponent( const std::string& component ); + + /// A period and the \p suffix are appended to the end of the pathname. + /// The precondition for this function is that the Path reference a file + /// name (i.e. isFile() returns true). If the Path is not a file, no + /// action is taken and the function returns false. If the path would + /// become invalid for the host operating system, false is returned. + /// @returns false if the suffix could not be added, true if it was. + /// @brief Adds a period and the \p suffix to the end of the pathname. + bool appendSuffix(const std::string& suffix); + + /// The suffix of the filename is erased. The suffix begins with and + /// includes the last . character in the filename after the last directory + /// separator and extends until the end of the name. If no . character is + /// after the last directory separator, then the file name is left + /// unchanged (i.e. it was already without a suffix) but the function + /// returns false. + /// @returns false if there was no suffix to remove, true otherwise. + /// @brief Remove the suffix from a path name. + bool eraseSuffix(); + + /// The current Path name is made unique in the file system. Upon return, + /// the Path will have been changed to make a unique file in the file + /// system or it will not have been changed if the current path name is + /// already unique. + /// @throws std::string if an unrecoverable error occurs. + /// @brief Make the current path name unique in the file system. + bool makeUnique( bool reuse_current /*= true*/, std::string* ErrMsg ); + + /// The current Path name is made absolute by prepending the + /// current working directory if necessary. + void makeAbsolute(); + + /// @} + /// @name Disk Mutators + /// @{ + public: + /// This method attempts to make the file referenced by the Path object + /// available for reading so that the canRead() method will return true. + /// @brief Make the file readable; + bool makeReadableOnDisk(std::string* ErrMsg = 0); + + /// This method attempts to make the file referenced by the Path object + /// available for writing so that the canWrite() method will return true. + /// @brief Make the file writable; + bool makeWriteableOnDisk(std::string* ErrMsg = 0); + + /// This method attempts to make the file referenced by the Path object + /// available for execution so that the canExecute() method will return + /// true. + /// @brief Make the file readable; + bool makeExecutableOnDisk(std::string* ErrMsg = 0); + + /// This method allows the last modified time stamp and permission bits + /// to be set on the disk object referenced by the Path. + /// @throws std::string if an error occurs. + /// @returns true on error. + /// @brief Set the status information. + bool setStatusInfoOnDisk(const FileStatus &SI, + std::string *ErrStr = 0) const; + + /// This method attempts to create a directory in the file system with the + /// same name as the Path object. The \p create_parents parameter controls + /// whether intermediate directories are created or not. if \p + /// create_parents is true, then an attempt will be made to create all + /// intermediate directories, as needed. If \p create_parents is false, + /// then only the final directory component of the Path name will be + /// created. The created directory will have no entries. + /// @returns true if the directory could not be created, false otherwise + /// @brief Create the directory this Path refers to. + bool createDirectoryOnDisk( + bool create_parents = false, ///< Determines whether non-existent + ///< directory components other than the last one (the "parents") + ///< are created or not. + std::string* ErrMsg = 0 ///< Optional place to put error messages. + ); + + /// This method attempts to create a file in the file system with the same + /// name as the Path object. The intermediate directories must all exist + /// at the time this method is called. Use createDirectoriesOnDisk to + /// accomplish that. The created file will be empty upon return from this + /// function. + /// @returns true if the file could not be created, false otherwise. + /// @brief Create the file this Path refers to. + bool createFileOnDisk( + std::string* ErrMsg = 0 ///< Optional place to put error messages. + ); + + /// This is like createFile except that it creates a temporary file. A + /// unique temporary file name is generated based on the contents of + /// \p this before the call. The new name is assigned to \p this and the + /// file is created. Note that this will both change the Path object + /// *and* create the corresponding file. This function will ensure that + /// the newly generated temporary file name is unique in the file system. + /// @returns true if the file couldn't be created, false otherwise. + /// @brief Create a unique temporary file + bool createTemporaryFileOnDisk( + bool reuse_current = false, ///< When set to true, this parameter + ///< indicates that if the current file name does not exist then + ///< it will be used without modification. + std::string* ErrMsg = 0 ///< Optional place to put error messages + ); + + /// This method renames the file referenced by \p this as \p newName. The + /// file referenced by \p this must exist. The file referenced by + /// \p newName does not need to exist. + /// @returns true on error, false otherwise + /// @brief Rename one file as another. + bool renamePathOnDisk(const Path& newName, std::string* ErrMsg); + + /// This method attempts to destroy the file or directory named by the + /// last component of the Path. If the Path refers to a directory and the + /// \p destroy_contents is false, an attempt will be made to remove just + /// the directory (the final Path component). If \p destroy_contents is + /// true, an attempt will be made to remove the entire contents of the + /// directory, recursively. If the Path refers to a file, the + /// \p destroy_contents parameter is ignored. + /// @param destroy_contents Indicates whether the contents of a destroyed + /// @param Err An optional string to receive an error message. + /// directory should also be destroyed (recursively). + /// @returns false if the file/directory was destroyed, true on error. + /// @brief Removes the file or directory from the filesystem. + bool eraseFromDisk(bool destroy_contents = false, + std::string *Err = 0) const; + + + /// MapInFilePages - This is a low level system API to map in the file + /// that is currently opened as FD into the current processes' address + /// space for read only access. This function may return null on failure + /// or if the system cannot provide the following constraints: + /// 1) The pages must be valid after the FD is closed, until + /// UnMapFilePages is called. + /// 2) Any padding after the end of the file must be zero filled, if + /// present. + /// 3) The pages must be contiguous. + /// + /// This API is not intended for general use, clients should use + /// MemoryBuffer::getFile instead. + static const char *MapInFilePages(int FD, uint64_t FileSize); + + /// UnMapFilePages - Free pages mapped into the current process by + /// MapInFilePages. + /// + /// This API is not intended for general use, clients should use + /// MemoryBuffer::getFile instead. + static void UnMapFilePages(const char *Base, uint64_t FileSize); + + /// @} + /// @name Data + /// @{ + protected: + // Our win32 implementation relies on this string being mutable. + mutable std::string path; ///< Storage for the path name. + + + /// @} + }; + + /// This class is identical to Path class except it allows you to obtain the + /// file status of the Path as well. The reason for the distinction is one of + /// efficiency. First, the file status requires additional space and the space + /// is incorporated directly into PathWithStatus without an additional malloc. + /// Second, obtaining status information is an expensive operation on most + /// operating systems so we want to be careful and explicity about where we + /// allow this operation in LLVM. + /// @brief Path with file status class. + class PathWithStatus : public Path { + /// @name Constructors + /// @{ + public: + /// @brief Default constructor + PathWithStatus() : Path(), status(), fsIsValid(false) {} + + /// @brief Copy constructor + PathWithStatus(const PathWithStatus &that) + : Path(static_cast(that)), status(that.status), + fsIsValid(that.fsIsValid) {} + + /// This constructor allows construction from a Path object + /// @brief Path constructor + PathWithStatus(const Path &other) + : Path(other), status(), fsIsValid(false) {} + + /// This constructor will accept a std::string as a path. No checking is + /// done on this path to determine if it is valid. To determine validity + /// of the path, use the isValid method. + /// @brief Construct a Path from a string. + explicit PathWithStatus( + const std::string& p ///< The path to assign. + ) : Path(p), status(), fsIsValid(false) {} + + /// This constructor will accept a character range as a path. No checking + /// is done on this path to determine if it is valid. To determine + /// validity of the path, use the isValid method. + /// @brief Construct a Path from a string. + explicit PathWithStatus( + const char *StrStart, ///< Pointer to the first character of the path + unsigned StrLen ///< Length of the path. + ) : Path(StrStart, StrLen), status(), fsIsValid(false) {} + + /// Makes a copy of \p that to \p this. + /// @returns \p this + /// @brief Assignment Operator + PathWithStatus &operator=(const PathWithStatus &that) { + static_cast(*this) = static_cast(that); + status = that.status; + fsIsValid = that.fsIsValid; + return *this; + } + + /// Makes a copy of \p that to \p this. + /// @returns \p this + /// @brief Assignment Operator + PathWithStatus &operator=(const Path &that) { + static_cast(*this) = static_cast(that); + fsIsValid = false; + return *this; + } + + /// @} + /// @name Methods + /// @{ + public: + /// This function returns status information about the file. The type of + /// path (file or directory) is updated to reflect the actual contents + /// of the file system. + /// @returns 0 on failure, with Error explaining why (if non-zero) + /// @returns a pointer to a FileStatus structure on success. + /// @brief Get file status. + const FileStatus *getFileStatus( + bool forceUpdate = false, ///< Force an update from the file system + std::string *Error = 0 ///< Optional place to return an error msg. + ) const; + + /// @} + /// @name Data + /// @{ + private: + mutable FileStatus status; ///< Status information. + mutable bool fsIsValid; ///< Whether we've obtained it or not + + /// @} + }; + + /// This enumeration delineates the kinds of files that LLVM knows about. + enum LLVMFileType { + Unknown_FileType = 0, ///< Unrecognized file + Bitcode_FileType, ///< Bitcode file + Archive_FileType, ///< ar style archive file + ELF_Relocatable_FileType, ///< ELF Relocatable object file + ELF_Executable_FileType, ///< ELF Executable image + ELF_SharedObject_FileType, ///< ELF dynamically linked shared lib + ELF_Core_FileType, ///< ELF core image + Mach_O_Object_FileType, ///< Mach-O Object file + Mach_O_Executable_FileType, ///< Mach-O Executable + Mach_O_FixedVirtualMemorySharedLib_FileType, ///< Mach-O Shared Lib, FVM + Mach_O_Core_FileType, ///< Mach-O Core File + Mach_O_PreloadExectuable_FileType, ///< Mach-O Preloaded Executable + Mach_O_DynamicallyLinkedSharedLib_FileType, ///< Mach-O dynlinked shared lib + Mach_O_DynamicLinker_FileType, ///< The Mach-O dynamic linker + Mach_O_Bundle_FileType, ///< Mach-O Bundle file + Mach_O_DynamicallyLinkedSharedLibStub_FileType, ///< Mach-O Shared lib stub + COFF_FileType ///< COFF object file or lib + }; + + /// This utility function allows any memory block to be examined in order + /// to determine its file type. + LLVMFileType IdentifyFileType(const char*magic, unsigned length); + + /// This function can be used to copy the file specified by Src to the + /// file specified by Dest. If an error occurs, Dest is removed. + /// @returns true if an error occurs, false otherwise + /// @brief Copy one file to another. + bool CopyFile(const Path& Dest, const Path& Src, std::string* ErrMsg); + + /// This is the OS-specific path separator: a colon on Unix or a semicolon + /// on Windows. + extern const char PathSeparator; +} + +} + +#endif diff --git a/libclamav/c++/llvm/include/llvm/System/Process.h b/libclamav/c++/llvm/include/llvm/System/Process.h new file mode 100644 index 000000000..010499acd --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/System/Process.h @@ -0,0 +1,148 @@ +//===- llvm/System/Process.h ------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the llvm::sys::Process class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SYSTEM_PROCESS_H +#define LLVM_SYSTEM_PROCESS_H + +#include "llvm/System/TimeValue.h" + +namespace llvm { +namespace sys { + + /// This class provides an abstraction for getting information about the + /// currently executing process. + /// @since 1.4 + /// @brief An abstraction for operating system processes. + class Process { + /// @name Accessors + /// @{ + public: + /// This static function will return the operating system's virtual memory + /// page size. + /// @returns The number of bytes in a virtual memory page. + /// @throws nothing + /// @brief Get the virtual memory page size + static unsigned GetPageSize(); + + /// This static function will return the total amount of memory allocated + /// by the process. This only counts the memory allocated via the malloc, + /// calloc and realloc functions and includes any "free" holes in the + /// allocated space. + /// @throws nothing + /// @brief Return process memory usage. + static size_t GetMallocUsage(); + + /// This static function will return the total memory usage of the + /// process. This includes code, data, stack and mapped pages usage. Notei + /// that the value returned here is not necessarily the Running Set Size, + /// it is the total virtual memory usage, regardless of mapped state of + /// that memory. + static size_t GetTotalMemoryUsage(); + + /// This static function will set \p user_time to the amount of CPU time + /// spent in user (non-kernel) mode and \p sys_time to the amount of CPU + /// time spent in system (kernel) mode. If the operating system does not + /// support collection of these metrics, a zero TimeValue will be for both + /// values. + static void GetTimeUsage( + TimeValue& elapsed, + ///< Returns the TimeValue::now() giving current time + TimeValue& user_time, + ///< Returns the current amount of user time for the process + TimeValue& sys_time + ///< Returns the current amount of system time for the process + ); + + /// This static function will return the process' current user id number. + /// Not all operating systems support this feature. Where it is not + /// supported, the function should return 65536 as the value. + static int GetCurrentUserId(); + + /// This static function will return the process' current group id number. + /// Not all operating systems support this feature. Where it is not + /// supported, the function should return 65536 as the value. + static int GetCurrentGroupId(); + + /// This function makes the necessary calls to the operating system to + /// prevent core files or any other kind of large memory dumps that can + /// occur when a program fails. + /// @brief Prevent core file generation. + static void PreventCoreFiles(); + + /// This function determines if the standard input is connected directly + /// to a user's input (keyboard probably), rather than coming from a file + /// or pipe. + static bool StandardInIsUserInput(); + + /// This function determines if the standard output is connected to a + /// "tty" or "console" window. That is, the output would be displayed to + /// the user rather than being put on a pipe or stored in a file. + static bool StandardOutIsDisplayed(); + + /// This function determines if the standard error is connected to a + /// "tty" or "console" window. That is, the output would be displayed to + /// the user rather than being put on a pipe or stored in a file. + static bool StandardErrIsDisplayed(); + + /// This function determines if the given file descriptor is connected to + /// a "tty" or "console" window. That is, the output would be displayed to + /// the user rather than being put on a pipe or stored in a file. + static bool FileDescriptorIsDisplayed(int fd); + + /// This function determines the number of columns in the window + /// if standard output is connected to a "tty" or "console" + /// window. If standard output is not connected to a tty or + /// console, or if the number of columns cannot be determined, + /// this routine returns zero. + static unsigned StandardOutColumns(); + + /// This function determines the number of columns in the window + /// if standard error is connected to a "tty" or "console" + /// window. If standard error is not connected to a tty or + /// console, or if the number of columns cannot be determined, + /// this routine returns zero. + static unsigned StandardErrColumns(); + + /// This function determines whether the terminal connected to standard + /// output supports colors. If standard output is not connected to a + /// terminal, this function returns false. + static bool StandardOutHasColors(); + + /// This function determines whether the terminal connected to standard + /// error supports colors. If standard error is not connected to a + /// terminal, this function returns false. + static bool StandardErrHasColors(); + + /// Whether changing colors requires the output to be flushed. + /// This is needed on systems that don't support escape sequences for + /// changing colors. + static bool ColorNeedsFlush(); + + /// This function returns the colorcode escape sequences. + /// If ColorNeedsFlush() is true then this function will change the colors + /// and return an empty escape sequence. In that case it is the + /// responsibility of the client to flush the output stream prior to + /// calling this function. + static const char *OutputColor(char c, bool bold, bool bg); + + /// Same as OutputColor, but only enables the bold attribute. + static const char *OutputBold(bool bg); + + /// Resets the terminals colors, or returns an escape sequence to do so. + static const char *ResetColor(); + /// @} + }; +} +} + +#endif diff --git a/libclamav/c++/llvm/include/llvm/System/Program.h b/libclamav/c++/llvm/include/llvm/System/Program.h new file mode 100644 index 000000000..679956272 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/System/Program.h @@ -0,0 +1,156 @@ +//===- llvm/System/Program.h ------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the llvm::sys::Program class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SYSTEM_PROGRAM_H +#define LLVM_SYSTEM_PROGRAM_H + +#include "llvm/System/Path.h" + +namespace llvm { +namespace sys { + + // TODO: Add operations to communicate with the process, redirect its I/O, + // etc. + + /// This class provides an abstraction for programs that are executable by the + /// operating system. It provides a platform generic way to find executable + /// programs from the path and to execute them in various ways. The sys::Path + /// class is used to specify the location of the Program. + /// @since 1.4 + /// @brief An abstraction for finding and executing programs. + class Program { + /// Opaque handle for target specific data. + void *Data_; + + // Noncopyable. + Program(const Program& other); + Program& operator=(const Program& other); + + /// @name Methods + /// @{ + public: + + Program(); + ~Program(); + + /// Return process ID of this program. + unsigned GetPid() const; + + /// This function executes the program using the \p arguments provided. The + /// invoked program will inherit the stdin, stdout, and stderr file + /// descriptors, the environment and other configuration settings of the + /// invoking program. If Path::executable() does not return true when this + /// function is called then a std::string is thrown. + /// @returns false in case of error, true otherwise. + /// @see FindProgramByName + /// @brief Executes the program with the given set of \p args. + bool Execute + ( const Path& path, ///< sys::Path object providing the path of the + ///< program to be executed. It is presumed this is the result of + ///< the FindProgramByName method. + const char** args, ///< A vector of strings that are passed to the + ///< program. The first element should be the name of the program. + ///< The list *must* be terminated by a null char* entry. + const char ** env = 0, ///< An optional vector of strings to use for + ///< the program's environment. If not provided, the current program's + ///< environment will be used. + const sys::Path** redirects = 0, ///< An optional array of pointers to + ///< Paths. If the array is null, no redirection is done. The array + ///< should have a size of at least three. If the pointer in the array + ///< are not null, then the inferior process's stdin(0), stdout(1), + ///< and stderr(2) will be redirected to the corresponding Paths. + ///< When an empty Path is passed in, the corresponding file + ///< descriptor will be disconnected (ie, /dev/null'd) in a portable + ///< way. + unsigned memoryLimit = 0, ///< If non-zero, this specifies max. amount + ///< of memory can be allocated by process. If memory usage will be + ///< higher limit, the child is killed and this call returns. If zero + ///< - no memory limit. + std::string* ErrMsg = 0 ///< If non-zero, provides a pointer to a string + ///< instance in which error messages will be returned. If the string + ///< is non-empty upon return an error occurred while invoking the + ///< program. + ); + + /// This function waits for the program to exit. This function will block + /// the current program until the invoked program exits. + /// @returns an integer result code indicating the status of the program. + /// A zero or positive value indicates the result code of the program. A + /// negative value is the signal number on which it terminated. + /// @see Execute + /// @brief Waits for the program to exit. + int Wait + ( unsigned secondsToWait = 0, ///< If non-zero, this specifies the amount + ///< of time to wait for the child process to exit. If the time + ///< expires, the child is killed and this call returns. If zero, + ///< this function will wait until the child finishes or forever if + ///< it doesn't. + std::string* ErrMsg = 0 ///< If non-zero, provides a pointer to a string + ///< instance in which error messages will be returned. If the string + ///< is non-empty upon return an error occurred while waiting. + ); + + /// This function terminates the program. + /// @returns true if an error occured. + /// @see Execute + /// @brief Terminates the program. + bool Kill + ( std::string* ErrMsg = 0 ///< If non-zero, provides a pointer to a string + ///< instance in which error messages will be returned. If the string + ///< is non-empty upon return an error occurred while killing the + ///< program. + ); + + /// This static constructor (factory) will attempt to locate a program in + /// the operating system's file system using some pre-determined set of + /// locations to search (e.g. the PATH on Unix). + /// @returns A Path object initialized to the path of the program or a + /// Path object that is empty (invalid) if the program could not be found. + /// @throws nothing + /// @brief Construct a Program by finding it by name. + static Path FindProgramByName(const std::string& name); + + // These methods change the specified standard stream (stdin or stdout) to + // binary mode. They return true if an error occurred + static bool ChangeStdinToBinary(); + static bool ChangeStdoutToBinary(); + + /// A convenience function equivalent to Program prg; prg.Execute(..); + /// prg.Wait(..); + /// @throws nothing + /// @see Execute, Wait + static int ExecuteAndWait(const Path& path, + const char** args, + const char ** env = 0, + const sys::Path** redirects = 0, + unsigned secondsToWait = 0, + unsigned memoryLimit = 0, + std::string* ErrMsg = 0); + + /// A convenience function equivalent to Program prg; prg.Execute(..); + /// @throws nothing + /// @see Execute + static void ExecuteNoWait(const Path& path, + const char** args, + const char ** env = 0, + const sys::Path** redirects = 0, + unsigned memoryLimit = 0, + std::string* ErrMsg = 0); + + /// @} + + }; +} +} + +#endif diff --git a/libclamav/c++/llvm/include/llvm/System/RWMutex.h b/libclamav/c++/llvm/include/llvm/System/RWMutex.h new file mode 100644 index 000000000..3a288180b --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/System/RWMutex.h @@ -0,0 +1,173 @@ +//===- RWMutex.h - Reader/Writer Mutual Exclusion Lock ----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the llvm::sys::RWMutex class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SYSTEM_RWMUTEX_H +#define LLVM_SYSTEM_RWMUTEX_H + +#include "llvm/System/Threading.h" +#include + +namespace llvm +{ + namespace sys + { + /// @brief Platform agnostic RWMutex class. + class RWMutexImpl + { + /// @name Constructors + /// @{ + public: + + /// Initializes the lock but doesn't acquire it. + /// @brief Default Constructor. + explicit RWMutexImpl(); + + /// Releases and removes the lock + /// @brief Destructor + ~RWMutexImpl(); + + /// @} + /// @name Methods + /// @{ + public: + + /// Attempts to unconditionally acquire the lock in reader mode. If the + /// lock is held by a writer, this method will wait until it can acquire + /// the lock. + /// @returns false if any kind of error occurs, true otherwise. + /// @brief Unconditionally acquire the lock in reader mode. + bool reader_acquire(); + + /// Attempts to release the lock in reader mode. + /// @returns false if any kind of error occurs, true otherwise. + /// @brief Unconditionally release the lock in reader mode. + bool reader_release(); + + /// Attempts to unconditionally acquire the lock in reader mode. If the + /// lock is held by any readers, this method will wait until it can + /// acquire the lock. + /// @returns false if any kind of error occurs, true otherwise. + /// @brief Unconditionally acquire the lock in writer mode. + bool writer_acquire(); + + /// Attempts to release the lock in writer mode. + /// @returns false if any kind of error occurs, true otherwise. + /// @brief Unconditionally release the lock in write mode. + bool writer_release(); + + //@} + /// @name Platform Dependent Data + /// @{ + private: + void* data_; ///< We don't know what the data will be + + /// @} + /// @name Do Not Implement + /// @{ + private: + RWMutexImpl(const RWMutexImpl & original); + void operator=(const RWMutexImpl &); + /// @} + }; + + /// SmartMutex - An R/W mutex with a compile time constant parameter that + /// indicates whether this mutex should become a no-op when we're not + /// running in multithreaded mode. + template + class SmartRWMutex : public RWMutexImpl { + unsigned readers, writers; + public: + explicit SmartRWMutex() : RWMutexImpl(), readers(0), writers(0) { } + + bool reader_acquire() { + if (!mt_only || llvm_is_multithreaded()) + return RWMutexImpl::reader_acquire(); + + // Single-threaded debugging code. This would be racy in multithreaded + // mode, but provides not sanity checks in single threaded mode. + ++readers; + return true; + } + + bool reader_release() { + if (!mt_only || llvm_is_multithreaded()) + return RWMutexImpl::reader_release(); + + // Single-threaded debugging code. This would be racy in multithreaded + // mode, but provides not sanity checks in single threaded mode. + assert(readers > 0 && "Reader lock not acquired before release!"); + --readers; + return true; + } + + bool writer_acquire() { + if (!mt_only || llvm_is_multithreaded()) + return RWMutexImpl::writer_acquire(); + + // Single-threaded debugging code. This would be racy in multithreaded + // mode, but provides not sanity checks in single threaded mode. + assert(writers == 0 && "Writer lock already acquired!"); + ++writers; + return true; + } + + bool writer_release() { + if (!mt_only || llvm_is_multithreaded()) + return RWMutexImpl::writer_release(); + + // Single-threaded debugging code. This would be racy in multithreaded + // mode, but provides not sanity checks in single threaded mode. + assert(writers == 1 && "Writer lock not acquired before release!"); + --writers; + return true; + } + + private: + SmartRWMutex(const SmartRWMutex & original); + void operator=(const SmartRWMutex &); + }; + typedef SmartRWMutex RWMutex; + + /// ScopedReader - RAII acquisition of a reader lock + template + struct SmartScopedReader { + SmartRWMutex& mutex; + + explicit SmartScopedReader(SmartRWMutex& m) : mutex(m) { + mutex.reader_acquire(); + } + + ~SmartScopedReader() { + mutex.reader_release(); + } + }; + typedef SmartScopedReader ScopedReader; + + /// ScopedWriter - RAII acquisition of a writer lock + template + struct SmartScopedWriter { + SmartRWMutex& mutex; + + explicit SmartScopedWriter(SmartRWMutex& m) : mutex(m) { + mutex.writer_acquire(); + } + + ~SmartScopedWriter() { + mutex.writer_release(); + } + }; + typedef SmartScopedWriter ScopedWriter; + } +} + +#endif diff --git a/libclamav/c++/llvm/include/llvm/System/Signals.h b/libclamav/c++/llvm/include/llvm/System/Signals.h new file mode 100644 index 000000000..2b9d8ca6b --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/System/Signals.h @@ -0,0 +1,51 @@ +//===- llvm/System/Signals.h - Signal Handling support ----------*- 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 some helpful functions for dealing with the possibility of +// unix signals occuring while your program is running. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SYSTEM_SIGNALS_H +#define LLVM_SYSTEM_SIGNALS_H + +#include "llvm/System/Path.h" + +namespace llvm { +namespace sys { + + /// This function registers signal handlers to ensure that if a signal gets + /// delivered that the named file is removed. + /// @brief Remove a file if a fatal signal occurs. + bool RemoveFileOnSignal(const Path &Filename, std::string* ErrMsg = 0); + + /// When an error signal (such as SIBABRT or SIGSEGV) is delivered to the + /// process, print a stack trace and then exit. + /// @brief Print a stack trace if a fatal signal occurs. + void PrintStackTraceOnErrorSignal(); + + /// AddSignalHandler - Add a function to be called when an abort/kill signal + /// is delivered to the process. The handler can have a cookie passed to it + /// to identify what instance of the handler it is. + void AddSignalHandler(void (*FnPtr)(void *), void *Cookie); + + /// This function registers a function to be called when the user "interrupts" + /// the program (typically by pressing ctrl-c). When the user interrupts the + /// program, the specified interrupt function is called instead of the program + /// being killed, and the interrupt function automatically disabled. Note + /// that interrupt functions are not allowed to call any non-reentrant + /// functions. An null interrupt function pointer disables the current + /// installed function. Note also that the handler may be executed on a + /// different thread on some platforms. + /// @brief Register a function to be called when ctrl-c is pressed. + void SetInterruptFunction(void (*IF)()); +} // End sys namespace +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/System/Solaris.h b/libclamav/c++/llvm/include/llvm/System/Solaris.h new file mode 100644 index 000000000..15adb7472 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/System/Solaris.h @@ -0,0 +1,40 @@ +/*===- llvm/System/Solaris.h ------------------------------------*- C++ -*-===* + * + * The LLVM Compiler Infrastructure + * + * This file is distributed under the University of Illinois Open Source + * License. See LICENSE.TXT for details. + * + *===----------------------------------------------------------------------===* + * + * This file contains portability fixes for Solaris hosts. + * + *===----------------------------------------------------------------------===*/ + +#ifndef LLVM_SYSTEM_SOLARIS_H +#define LLVM_SYSTEM_SOLARIS_H + +#include +#include + +#undef CS +#undef DS +#undef ES +#undef FS +#undef GS +#undef SS +#undef EAX +#undef ECX +#undef EDX +#undef EBX +#undef ESP +#undef EBP +#undef ESI +#undef EDI +#undef EIP +#undef UESP +#undef EFL +#undef ERR +#undef TRAPNO + +#endif diff --git a/libclamav/c++/llvm/include/llvm/System/ThreadLocal.h b/libclamav/c++/llvm/include/llvm/System/ThreadLocal.h new file mode 100644 index 000000000..39b1e64be --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/System/ThreadLocal.h @@ -0,0 +1,41 @@ +//===- llvm/System/ThreadLocal.h - Thread Local Data ------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the llvm::sys::ThreadLocal class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SYSTEM_THREAD_LOCAL_H +#define LLVM_SYSTEM_THREAD_LOCAL_H + +#include "llvm/System/Threading.h" +#include + +namespace llvm { + namespace sys { + class ThreadLocalImpl { + void* data; + public: + ThreadLocalImpl(); + virtual ~ThreadLocalImpl(); + void setInstance(const void* d); + const void* getInstance(); + }; + + template + class ThreadLocal : public ThreadLocalImpl { + public: + ThreadLocal() : ThreadLocalImpl() { } + T* get() { return static_cast(getInstance()); } + void set(T* d) { setInstance(d); } + }; + } +} + +#endif diff --git a/libclamav/c++/llvm/include/llvm/System/Threading.h b/libclamav/c++/llvm/include/llvm/System/Threading.h new file mode 100644 index 000000000..42d2f89bc --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/System/Threading.h @@ -0,0 +1,45 @@ +//===-- llvm/System/Threading.h - Control multithreading mode --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// TThis file defines llvm_start_multithreaded() and friends. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SYSTEM_THREADING_H +#define LLVM_SYSTEM_THREADING_H + +namespace llvm { + /// llvm_start_multithreaded - Allocate and initialize structures needed to + /// make LLVM safe for multithreading. The return value indicates whether + /// multithreaded initialization succeeded. LLVM will still be operational + /// on "failed" return, and will still be safe for hosting threading + /// applications in the JIT, but will not be safe for concurrent calls to the + /// LLVM APIs. + /// THIS MUST EXECUTE IN ISOLATION FROM ALL OTHER LLVM API CALLS. + bool llvm_start_multithreaded(); + + /// llvm_stop_multithreaded - Deallocate structures necessary to make LLVM + /// safe for multithreading. + /// THIS MUST EXECUTE IN ISOLATION FROM ALL OTHER LLVM API CALLS. + void llvm_stop_multithreaded(); + + /// llvm_is_multithreaded - Check whether LLVM is executing in thread-safe + /// mode or not. + bool llvm_is_multithreaded(); + + /// acquire_global_lock - Acquire the global lock. This is a no-op if called + /// before llvm_start_multithreaded(). + void llvm_acquire_global_lock(); + + /// release_global_lock - Release the global lock. This is a no-op if called + /// before llvm_start_multithreaded(). + void llvm_release_global_lock(); +} + +#endif diff --git a/libclamav/c++/llvm/include/llvm/System/TimeValue.h b/libclamav/c++/llvm/include/llvm/System/TimeValue.h new file mode 100644 index 000000000..b82647f74 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/System/TimeValue.h @@ -0,0 +1,382 @@ +//===-- TimeValue.h - Declare OS TimeValue Concept --------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This header file declares the operating system TimeValue concept. +// +//===----------------------------------------------------------------------===// + +#include "llvm/System/DataTypes.h" +#include + +#ifndef LLVM_SYSTEM_TIMEVALUE_H +#define LLVM_SYSTEM_TIMEVALUE_H + +namespace llvm { +namespace sys { + /// This class is used where a precise fixed point in time is required. The + /// range of TimeValue spans many hundreds of billions of years both past and + /// present. The precision of TimeValue is to the nanosecond. However, the + /// actual precision of its values will be determined by the resolution of + /// the system clock. The TimeValue class is used in conjunction with several + /// other lib/System interfaces to specify the time at which a call should + /// timeout, etc. + /// @since 1.4 + /// @brief Provides an abstraction for a fixed point in time. + class TimeValue { + + /// @name Constants + /// @{ + public: + + /// A constant TimeValue representing the smallest time + /// value permissable by the class. MinTime is some point + /// in the distant past, about 300 billion years BCE. + /// @brief The smallest possible time value. + static const TimeValue MinTime; + + /// A constant TimeValue representing the largest time + /// value permissable by the class. MaxTime is some point + /// in the distant future, about 300 billion years AD. + /// @brief The largest possible time value. + static const TimeValue MaxTime; + + /// A constant TimeValue representing the base time, + /// or zero time of 00:00:00 (midnight) January 1st, 2000. + /// @brief 00:00:00 Jan 1, 2000 UTC. + static const TimeValue ZeroTime; + + /// A constant TimeValue for the Posix base time which is + /// 00:00:00 (midnight) January 1st, 1970. + /// @brief 00:00:00 Jan 1, 1970 UTC. + static const TimeValue PosixZeroTime; + + /// A constant TimeValue for the Win32 base time which is + /// 00:00:00 (midnight) January 1st, 1601. + /// @brief 00:00:00 Jan 1, 1601 UTC. + static const TimeValue Win32ZeroTime; + + /// @} + /// @name Types + /// @{ + public: + typedef int64_t SecondsType; ///< Type used for representing seconds. + typedef int32_t NanoSecondsType;///< Type used for representing nanoseconds. + + enum TimeConversions { + NANOSECONDS_PER_SECOND = 1000000000, ///< One Billion + MICROSECONDS_PER_SECOND = 1000000, ///< One Million + MILLISECONDS_PER_SECOND = 1000, ///< One Thousand + NANOSECONDS_PER_MICROSECOND = 1000, ///< One Thousand + NANOSECONDS_PER_MILLISECOND = 1000000,///< One Million + NANOSECONDS_PER_POSIX_TICK = 100, ///< Posix tick is 100 Hz (10ms) + NANOSECONDS_PER_WIN32_TICK = 100 ///< Win32 tick is 100 Hz (10ms) + }; + + /// @} + /// @name Constructors + /// @{ + public: + /// Caller provides the exact value in seconds and nanoseconds. The + /// \p nanos argument defaults to zero for convenience. + /// @brief Explicit constructor + explicit TimeValue (SecondsType seconds, NanoSecondsType nanos = 0) + : seconds_( seconds ), nanos_( nanos ) { this->normalize(); } + + /// Caller provides the exact value as a double in seconds with the + /// fractional part representing nanoseconds. + /// @brief Double Constructor. + explicit TimeValue( double new_time ) + : seconds_( 0 ) , nanos_ ( 0 ) { + SecondsType integer_part = static_cast( new_time ); + seconds_ = integer_part; + nanos_ = static_cast( (new_time - + static_cast(integer_part)) * NANOSECONDS_PER_SECOND ); + this->normalize(); + } + + /// This is a static constructor that returns a TimeValue that represents + /// the current time. + /// @brief Creates a TimeValue with the current time (UTC). + static TimeValue now(); + + /// @} + /// @name Operators + /// @{ + public: + /// Add \p that to \p this. + /// @returns this + /// @brief Incrementing assignment operator. + TimeValue& operator += (const TimeValue& that ) { + this->seconds_ += that.seconds_ ; + this->nanos_ += that.nanos_ ; + this->normalize(); + return *this; + } + + /// Subtract \p that from \p this. + /// @returns this + /// @brief Decrementing assignment operator. + TimeValue& operator -= (const TimeValue &that ) { + this->seconds_ -= that.seconds_ ; + this->nanos_ -= that.nanos_ ; + this->normalize(); + return *this; + } + + /// Determine if \p this is less than \p that. + /// @returns True iff *this < that. + /// @brief True if this < that. + int operator < (const TimeValue &that) const { return that > *this; } + + /// Determine if \p this is greather than \p that. + /// @returns True iff *this > that. + /// @brief True if this > that. + int operator > (const TimeValue &that) const { + if ( this->seconds_ > that.seconds_ ) { + return 1; + } else if ( this->seconds_ == that.seconds_ ) { + if ( this->nanos_ > that.nanos_ ) return 1; + } + return 0; + } + + /// Determine if \p this is less than or equal to \p that. + /// @returns True iff *this <= that. + /// @brief True if this <= that. + int operator <= (const TimeValue &that) const { return that >= *this; } + + /// Determine if \p this is greater than or equal to \p that. + /// @returns True iff *this >= that. + /// @brief True if this >= that. + int operator >= (const TimeValue &that) const { + if ( this->seconds_ > that.seconds_ ) { + return 1; + } else if ( this->seconds_ == that.seconds_ ) { + if ( this->nanos_ >= that.nanos_ ) return 1; + } + return 0; + } + + /// Determines if two TimeValue objects represent the same moment in time. + /// @brief True iff *this == that. + /// @brief True if this == that. + int operator == (const TimeValue &that) const { + return (this->seconds_ == that.seconds_) && + (this->nanos_ == that.nanos_); + } + + /// Determines if two TimeValue objects represent times that are not the + /// same. + /// @return True iff *this != that. + /// @brief True if this != that. + int operator != (const TimeValue &that) const { return !(*this == that); } + + /// Adds two TimeValue objects together. + /// @returns The sum of the two operands as a new TimeValue + /// @brief Addition operator. + friend TimeValue operator + (const TimeValue &tv1, const TimeValue &tv2); + + /// Subtracts two TimeValue objects. + /// @returns The difference of the two operands as a new TimeValue + /// @brief Subtraction operator. + friend TimeValue operator - (const TimeValue &tv1, const TimeValue &tv2); + + /// @} + /// @name Accessors + /// @{ + public: + + /// Returns only the seconds component of the TimeValue. The nanoseconds + /// portion is ignored. No rounding is performed. + /// @brief Retrieve the seconds component + SecondsType seconds() const { return seconds_; } + + /// Returns only the nanoseconds component of the TimeValue. The seconds + /// portion is ignored. + /// @brief Retrieve the nanoseconds component. + NanoSecondsType nanoseconds() const { return nanos_; } + + /// Returns only the fractional portion of the TimeValue rounded down to the + /// nearest microsecond (divide by one thousand). + /// @brief Retrieve the fractional part as microseconds; + uint32_t microseconds() const { + return nanos_ / NANOSECONDS_PER_MICROSECOND; + } + + /// Returns only the fractional portion of the TimeValue rounded down to the + /// nearest millisecond (divide by one million). + /// @brief Retrieve the fractional part as milliseconds; + uint32_t milliseconds() const { + return nanos_ / NANOSECONDS_PER_MILLISECOND; + } + + /// Returns the TimeValue as a number of microseconds. Note that the value + /// returned can overflow because the range of a uint64_t is smaller than + /// the range of a TimeValue. Nevertheless, this is useful on some operating + /// systems and is therefore provided. + /// @brief Convert to a number of microseconds (can overflow) + uint64_t usec() const { + return seconds_ * MICROSECONDS_PER_SECOND + + ( nanos_ / NANOSECONDS_PER_MICROSECOND ); + } + + /// Returns the TimeValue as a number of milliseconds. Note that the value + /// returned can overflow because the range of a uint64_t is smaller than + /// the range of a TimeValue. Nevertheless, this is useful on some operating + /// systems and is therefore provided. + /// @brief Convert to a number of milliseconds (can overflow) + uint64_t msec() const { + return seconds_ * MILLISECONDS_PER_SECOND + + ( nanos_ / NANOSECONDS_PER_MILLISECOND ); + } + + /// Converts the TimeValue into the corresponding number of "ticks" for + /// Posix, correcting for the difference in Posix zero time. + /// @brief Convert to unix time (100 nanoseconds since 12:00:00a Jan 1,1970) + uint64_t toPosixTime() const { + uint64_t result = seconds_ - PosixZeroTime.seconds_; + result += nanos_ / NANOSECONDS_PER_POSIX_TICK; + return result; + } + + /// Converts the TimeValue into the corresponding number of seconds + /// since the epoch (00:00:00 Jan 1,1970). + uint64_t toEpochTime() const { + return seconds_ - PosixZeroTime.seconds_; + } + + /// Converts the TimeValue into the corresponding number of "ticks" for + /// Win32 platforms, correcting for the difference in Win32 zero time. + /// @brief Convert to windows time (seconds since 12:00:00a Jan 1, 1601) + uint64_t toWin32Time() const { + uint64_t result = seconds_ - Win32ZeroTime.seconds_; + result += nanos_ / NANOSECONDS_PER_WIN32_TICK; + return result; + } + + /// Provides the seconds and nanoseconds as results in its arguments after + /// correction for the Posix zero time. + /// @brief Convert to timespec time (ala POSIX.1b) + void getTimespecTime( uint64_t& seconds, uint32_t& nanos ) const { + seconds = seconds_ - PosixZeroTime.seconds_; + nanos = nanos_; + } + + /// Provides conversion of the TimeValue into a readable time & date. + /// @returns std::string containing the readable time value + /// @brief Convert time to a string. + std::string str() const; + + /// @} + /// @name Mutators + /// @{ + public: + /// The seconds component of the TimeValue is set to \p sec without + /// modifying the nanoseconds part. This is useful for whole second + /// arithmetic. + /// @brief Set the seconds component. + void seconds (SecondsType sec ) { + this->seconds_ = sec; + this->normalize(); + } + + /// The nanoseconds component of the TimeValue is set to \p nanos without + /// modifying the seconds part. This is useful for basic computations + /// involving just the nanoseconds portion. Note that the TimeValue will be + /// normalized after this call so that the fractional (nanoseconds) portion + /// will have the smallest equivalent value. + /// @brief Set the nanoseconds component using a number of nanoseconds. + void nanoseconds ( NanoSecondsType nanos ) { + this->nanos_ = nanos; + this->normalize(); + } + + /// The seconds component remains unchanged. + /// @brief Set the nanoseconds component using a number of microseconds. + void microseconds ( int32_t micros ) { + this->nanos_ = micros * NANOSECONDS_PER_MICROSECOND; + this->normalize(); + } + + /// The seconds component remains unchanged. + /// @brief Set the nanoseconds component using a number of milliseconds. + void milliseconds ( int32_t millis ) { + this->nanos_ = millis * NANOSECONDS_PER_MILLISECOND; + this->normalize(); + } + + /// @brief Converts from microsecond format to TimeValue format + void usec( int64_t microseconds ) { + this->seconds_ = microseconds / MICROSECONDS_PER_SECOND; + this->nanos_ = NanoSecondsType(microseconds % MICROSECONDS_PER_SECOND) * + NANOSECONDS_PER_MICROSECOND; + this->normalize(); + } + + /// @brief Converts from millisecond format to TimeValue format + void msec( int64_t milliseconds ) { + this->seconds_ = milliseconds / MILLISECONDS_PER_SECOND; + this->nanos_ = NanoSecondsType(milliseconds % MILLISECONDS_PER_SECOND) * + NANOSECONDS_PER_MILLISECOND; + this->normalize(); + } + + /// Converts the \p seconds argument from PosixTime to the corresponding + /// TimeValue and assigns that value to \p this. + /// @brief Convert seconds form PosixTime to TimeValue + void fromEpochTime( SecondsType seconds ) { + seconds_ = seconds + PosixZeroTime.seconds_; + nanos_ = 0; + this->normalize(); + } + + /// Converts the \p win32Time argument from Windows FILETIME to the + /// corresponding TimeValue and assigns that value to \p this. + /// @brief Convert seconds form Windows FILETIME to TimeValue + void fromWin32Time( uint64_t win32Time ) { + this->seconds_ = win32Time / 10000000 + Win32ZeroTime.seconds_; + this->nanos_ = NanoSecondsType(win32Time % 10000000) * 100; + } + + /// @} + /// @name Implementation + /// @{ + private: + /// This causes the values to be represented so that the fractional + /// part is minimized, possibly incrementing the seconds part. + /// @brief Normalize to canonical form. + void normalize(); + + /// @} + /// @name Data + /// @{ + private: + /// Store the values as a . + SecondsType seconds_;///< Stores the seconds part of the TimeVal + NanoSecondsType nanos_; ///< Stores the nanoseconds part of the TimeVal + /// @} + + }; + +inline TimeValue operator + (const TimeValue &tv1, const TimeValue &tv2) { + TimeValue sum (tv1.seconds_ + tv2.seconds_, tv1.nanos_ + tv2.nanos_); + sum.normalize (); + return sum; +} + +inline TimeValue operator - (const TimeValue &tv1, const TimeValue &tv2) { + TimeValue difference (tv1.seconds_ - tv2.seconds_, tv1.nanos_ - tv2.nanos_ ); + difference.normalize (); + return difference; +} + +} +} + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Target/SubtargetFeature.h b/libclamav/c++/llvm/include/llvm/Target/SubtargetFeature.h new file mode 100644 index 000000000..38a3cc2fe --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Target/SubtargetFeature.h @@ -0,0 +1,118 @@ +//===-- llvm/Target/SubtargetFeature.h - CPU characteristics ----*- 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 and manages user or tool specified CPU characteristics. +// The intent is to be able to package specific features that should or should +// not be used on a specific target processor. A tool, such as llc, could, as +// as example, gather chip info from the command line, a long with features +// that should be used on that chip. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TARGET_SUBTARGETFEATURE_H +#define LLVM_TARGET_SUBTARGETFEATURE_H + +#include +#include +#include +#include "llvm/ADT/Triple.h" +#include "llvm/System/DataTypes.h" + +namespace llvm { + class raw_ostream; + +//===----------------------------------------------------------------------===// +/// +/// SubtargetFeatureKV - Used to provide key value pairs for feature and +/// CPU bit flags. +// +struct SubtargetFeatureKV { + const char *Key; // K-V key string + const char *Desc; // Help descriptor + uint32_t Value; // K-V integer value + uint32_t Implies; // K-V bit mask + + // Compare routine for std binary search + bool operator<(const SubtargetFeatureKV &S) const { + return strcmp(Key, S.Key) < 0; + } +}; + +//===----------------------------------------------------------------------===// +/// +/// SubtargetInfoKV - Used to provide key value pairs for CPU and arbitrary +/// pointers. +// +struct SubtargetInfoKV { + const char *Key; // K-V key string + void *Value; // K-V pointer value + + // Compare routine for std binary search + bool operator<(const SubtargetInfoKV &S) const { + return strcmp(Key, S.Key) < 0; + } +}; + +//===----------------------------------------------------------------------===// +/// +/// SubtargetFeatures - Manages the enabling and disabling of subtarget +/// specific features. Features are encoded as a string of the form +/// "cpu,+attr1,+attr2,-attr3,...,+attrN" +/// A comma separates each feature from the next (all lowercase.) +/// The first feature is always the CPU subtype (eg. pentiumm). If the CPU +/// value is "generic" then the CPU subtype should be generic for the target. +/// Each of the remaining features is prefixed with + or - indicating whether +/// that feature should be enabled or disabled contrary to the cpu +/// specification. +/// + +class SubtargetFeatures { + std::vector Features; // Subtarget features as a vector +public: + explicit SubtargetFeatures(const std::string &Initial = std::string()); + + /// Features string accessors. + std::string getString() const; + void setString(const std::string &Initial); + + /// Set the CPU string. Replaces previous setting. Setting to "" clears CPU. + void setCPU(const std::string &String); + + /// Setting CPU string only if no string is set. + void setCPUIfNone(const std::string &String); + + /// Returns current CPU string. + const std::string & getCPU() const; + + /// Adding Features. + void AddFeature(const std::string &String, bool IsEnabled = true); + + /// Get feature bits. + uint32_t getBits(const SubtargetFeatureKV *CPUTable, + size_t CPUTableSize, + const SubtargetFeatureKV *FeatureTable, + size_t FeatureTableSize); + + /// Get info pointer + void *getInfo(const SubtargetInfoKV *Table, size_t TableSize); + + /// Print feature string. + void print(raw_ostream &OS) const; + + // Dump feature info. + void dump() const; + + /// Retrieve a formatted string of the default features for + /// the specified target triple. + static std::string getDefaultSubtargetFeatures(const Triple &Triple); +}; + +} // End namespace llvm + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Target/Target.td b/libclamav/c++/llvm/include/llvm/Target/Target.td new file mode 100644 index 000000000..6f1e06655 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Target/Target.td @@ -0,0 +1,623 @@ +//===- Target.td - Target Independent TableGen interface ---*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the target-independent interfaces which should be +// implemented by each target which is using a TableGen based code generator. +// +//===----------------------------------------------------------------------===// + +// Include all information about LLVM intrinsics. +include "llvm/Intrinsics.td" + +//===----------------------------------------------------------------------===// +// Register file description - These classes are used to fill in the target +// description classes. + +class RegisterClass; // Forward def + +// Register - You should define one instance of this class for each register +// in the target machine. String n will become the "name" of the register. +class Register { + string Namespace = ""; + string AsmName = n; + + // SpillSize - If this value is set to a non-zero value, it is the size in + // bits of the spill slot required to hold this register. If this value is + // set to zero, the information is inferred from any register classes the + // register belongs to. + int SpillSize = 0; + + // SpillAlignment - This value is used to specify the alignment required for + // spilling the register. Like SpillSize, this should only be explicitly + // specified if the register is not in a register class. + int SpillAlignment = 0; + + // Aliases - A list of registers that this register overlaps with. A read or + // modification of this register can potentially read or modify the aliased + // registers. + list Aliases = []; + + // SubRegs - A list of registers that are parts of this register. Note these + // are "immediate" sub-registers and the registers within the list do not + // themselves overlap. e.g. For X86, EAX's SubRegs list contains only [AX], + // not [AX, AH, AL]. + list SubRegs = []; + + // DwarfNumbers - Numbers used internally by gcc/gdb to identify the register. + // These values can be determined by locating the .h file in the + // directory llvmgcc/gcc/config// and looking for REGISTER_NAMES. The + // order of these names correspond to the enumeration used by gcc. A value of + // -1 indicates that the gcc number is undefined and -2 that register number + // is invalid for this mode/flavour. + list DwarfNumbers = []; +} + +// RegisterWithSubRegs - This can be used to define instances of Register which +// need to specify sub-registers. +// List "subregs" specifies which registers are sub-registers to this one. This +// is used to populate the SubRegs and AliasSet fields of TargetRegisterDesc. +// This allows the code generator to be careful not to put two values with +// overlapping live ranges into registers which alias. +class RegisterWithSubRegs subregs> : Register { + let SubRegs = subregs; +} + +// SubRegSet - This can be used to define a specific mapping of registers to +// indices, for use as named subregs of a particular physical register. Each +// register in 'subregs' becomes an addressable subregister at index 'n' of the +// corresponding register in 'regs'. +class SubRegSet regs, list subregs> { + int index = n; + + list From = regs; + list To = subregs; +} + +// RegisterClass - Now that all of the registers are defined, and aliases +// between registers are defined, specify which registers belong to which +// register classes. This also defines the default allocation order of +// registers by register allocators. +// +class RegisterClass regTypes, int alignment, + list regList> { + string Namespace = namespace; + + // RegType - Specify the list ValueType of the registers in this register + // class. Note that all registers in a register class must have the same + // ValueTypes. This is a list because some targets permit storing different + // types in same register, for example vector values with 128-bit total size, + // but different count/size of items, like SSE on x86. + // + list RegTypes = regTypes; + + // Size - Specify the spill size in bits of the registers. A default value of + // zero lets tablgen pick an appropriate size. + int Size = 0; + + // Alignment - Specify the alignment required of the registers when they are + // stored or loaded to memory. + // + int Alignment = alignment; + + // CopyCost - This value is used to specify the cost of copying a value + // between two registers in this register class. The default value is one + // meaning it takes a single instruction to perform the copying. A negative + // value means copying is extremely expensive or impossible. + int CopyCost = 1; + + // MemberList - Specify which registers are in this class. If the + // allocation_order_* method are not specified, this also defines the order of + // allocation used by the register allocator. + // + list MemberList = regList; + + // SubClassList - Specify which register classes correspond to subregisters + // of this class. The order should be by subregister set index. + list SubRegClassList = []; + + // MethodProtos/MethodBodies - These members can be used to insert arbitrary + // code into a generated register class. The normal usage of this is to + // overload virtual methods. + code MethodProtos = [{}]; + code MethodBodies = [{}]; +} + + +//===----------------------------------------------------------------------===// +// DwarfRegNum - This class provides a mapping of the llvm register enumeration +// to the register numbering used by gcc and gdb. These values are used by a +// debug information writer (ex. DwarfWriter) to describe where values may be +// located during execution. +class DwarfRegNum Numbers> { + // DwarfNumbers - Numbers used internally by gcc/gdb to identify the register. + // These values can be determined by locating the .h file in the + // directory llvmgcc/gcc/config// and looking for REGISTER_NAMES. The + // order of these names correspond to the enumeration used by gcc. A value of + // -1 indicates that the gcc number is undefined and -2 that register number is + // invalid for this mode/flavour. + list DwarfNumbers = Numbers; +} + +//===----------------------------------------------------------------------===// +// Pull in the common support for scheduling +// +include "llvm/Target/TargetSchedule.td" + +class Predicate; // Forward def + +//===----------------------------------------------------------------------===// +// Instruction set description - These classes correspond to the C++ classes in +// the Target/TargetInstrInfo.h file. +// +class Instruction { + string Namespace = ""; + + dag OutOperandList; // An dag containing the MI def operand list. + dag InOperandList; // An dag containing the MI use operand list. + string AsmString = ""; // The .s format to print the instruction with. + + // Pattern - Set to the DAG pattern for this instruction, if we know of one, + // otherwise, uninitialized. + list Pattern; + + // The follow state will eventually be inferred automatically from the + // instruction pattern. + + list Uses = []; // Default to using no non-operand registers + list Defs = []; // Default to modifying no non-operand registers + + // Predicates - List of predicates which will be turned into isel matching + // code. + list Predicates = []; + + // Code size. + int CodeSize = 0; + + // Added complexity passed onto matching pattern. + int AddedComplexity = 0; + + // These bits capture information about the high-level semantics of the + // instruction. + bit isReturn = 0; // Is this instruction a return instruction? + bit isBranch = 0; // Is this instruction a branch instruction? + bit isIndirectBranch = 0; // Is this instruction an indirect branch? + bit isBarrier = 0; // Can control flow fall through this instruction? + bit isCall = 0; // Is this instruction a call instruction? + bit canFoldAsLoad = 0; // Can this be folded as a simple memory operand? + bit mayLoad = 0; // Is it possible for this inst to read memory? + bit mayStore = 0; // Is it possible for this inst to write memory? + bit isTwoAddress = 0; // Is this a two address instruction? + bit isConvertibleToThreeAddress = 0; // Can this 2-addr instruction promote? + bit isCommutable = 0; // Is this 3 operand instruction commutable? + bit isTerminator = 0; // Is this part of the terminator for a basic block? + bit isReMaterializable = 0; // Is this instruction re-materializable? + bit isPredicable = 0; // Is this instruction predicable? + bit hasDelaySlot = 0; // Does this instruction have an delay slot? + bit usesCustomInserter = 0; // Pseudo instr needing special help. + bit hasCtrlDep = 0; // Does this instruction r/w ctrl-flow chains? + bit isNotDuplicable = 0; // Is it unsafe to duplicate this instruction? + bit isAsCheapAsAMove = 0; // As cheap (or cheaper) than a move instruction. + bit hasExtraSrcRegAllocReq = 0; // Sources have special regalloc requirement? + bit hasExtraDefRegAllocReq = 0; // Defs have special regalloc requirement? + + // Side effect flags - When set, the flags have these meanings: + // + // hasSideEffects - The instruction has side effects that are not + // captured by any operands of the instruction or other flags. + // + // mayHaveSideEffects - Some instances of the instruction can have side + // effects. The virtual method "isReallySideEffectFree" is called to + // determine this. Load instructions are an example of where this is + // useful. In general, loads always have side effects. However, loads from + // constant pools don't. Individual back ends make this determination. + // + // neverHasSideEffects - Set on an instruction with no pattern if it has no + // side effects. + bit hasSideEffects = 0; + bit mayHaveSideEffects = 0; + bit neverHasSideEffects = 0; + + // Is this instruction a "real" instruction (with a distinct machine + // encoding), or is it a pseudo instruction used for codegen modeling + // purposes. + bit isCodeGenOnly = 0; + + InstrItinClass Itinerary = NoItinerary;// Execution steps used for scheduling. + + string Constraints = ""; // OperandConstraint, e.g. $src = $dst. + + /// DisableEncoding - List of operand names (e.g. "$op1,$op2") that should not + /// be encoded into the output machineinstr. + string DisableEncoding = ""; +} + +/// Predicates - These are extra conditionals which are turned into instruction +/// selector matching code. Currently each predicate is just a string. +class Predicate { + string CondString = cond; +} + +/// NoHonorSignDependentRounding - This predicate is true if support for +/// sign-dependent-rounding is not enabled. +def NoHonorSignDependentRounding + : Predicate<"!HonorSignDependentRoundingFPMath()">; + +class Requires preds> { + list Predicates = preds; +} + +/// ops definition - This is just a simple marker used to identify the operands +/// list for an instruction. outs and ins are identical both syntatically and +/// semantically, they are used to define def operands and use operands to +/// improve readibility. This should be used like this: +/// (outs R32:$dst), (ins R32:$src1, R32:$src2) or something similar. +def ops; +def outs; +def ins; + +/// variable_ops definition - Mark this instruction as taking a variable number +/// of operands. +def variable_ops; + + +/// PointerLikeRegClass - Values that are designed to have pointer width are +/// derived from this. TableGen treats the register class as having a symbolic +/// type that it doesn't know, and resolves the actual regclass to use by using +/// the TargetRegisterInfo::getPointerRegClass() hook at codegen time. +class PointerLikeRegClass { + int RegClassKind = Kind; +} + + +/// ptr_rc definition - Mark this operand as being a pointer value whose +/// register class is resolved dynamically via a callback to TargetInstrInfo. +/// FIXME: We should probably change this to a class which contain a list of +/// flags. But currently we have but one flag. +def ptr_rc : PointerLikeRegClass<0>; + +/// unknown definition - Mark this operand as being of unknown type, causing +/// it to be resolved by inference in the context it is used. +def unknown; + +/// AsmOperandClass - Representation for the kinds of operands which the target +/// specific parser can create and the assembly matcher may need to distinguish. +/// +/// Operand classes are used to define the order in which instructions are +/// matched, to ensure that the instruction which gets matched for any +/// particular list of operands is deterministic. +/// +/// The target specific parser must be able to classify a parsed operand into a +/// unique class which does not partially overlap with any other classes. It can +/// match a subset of some other class, in which case the super class field +/// should be defined. +class AsmOperandClass { + /// The name to use for this class, which should be usable as an enum value. + string Name = ?; + + /// The super class of this operand. + AsmOperandClass SuperClass = ?; + + /// The name of the method on the target specific operand to call to test + /// whether the operand is an instance of this class. If not set, this will + /// default to "isFoo", where Foo is the AsmOperandClass name. The method + /// signature should be: + /// bool isFoo() const; + string PredicateMethod = ?; + + /// The name of the method on the target specific operand to call to add the + /// target specific operand to an MCInst. If not set, this will default to + /// "addFooOperands", where Foo is the AsmOperandClass name. The method + /// signature should be: + /// void addFooOperands(MCInst &Inst, unsigned N) const; + string RenderMethod = ?; +} + +def ImmAsmOperand : AsmOperandClass { + let Name = "Imm"; +} + +/// Operand Types - These provide the built-in operand types that may be used +/// by a target. Targets can optionally provide their own operand types as +/// needed, though this should not be needed for RISC targets. +class Operand { + ValueType Type = ty; + string PrintMethod = "printOperand"; + string AsmOperandLowerMethod = ?; + dag MIOperandInfo = (ops); + + // ParserMatchClass - The "match class" that operands of this type fit + // in. Match classes are used to define the order in which instructions are + // match, to ensure that which instructions gets matched is deterministic. + // + // The target specific parser must be able to classify an parsed operand + // into a unique class, which does not partially overlap with any other + // classes. It can match a subset of some other class, in which case + // ParserMatchSuperClass should be set to the name of that class. + AsmOperandClass ParserMatchClass = ImmAsmOperand; +} + +def i1imm : Operand; +def i8imm : Operand; +def i16imm : Operand; +def i32imm : Operand; +def i64imm : Operand; + +def f32imm : Operand; +def f64imm : Operand; + +/// zero_reg definition - Special node to stand for the zero register. +/// +def zero_reg; + +/// PredicateOperand - This can be used to define a predicate operand for an +/// instruction. OpTypes specifies the MIOperandInfo for the operand, and +/// AlwaysVal specifies the value of this predicate when set to "always +/// execute". +class PredicateOperand + : Operand { + let MIOperandInfo = OpTypes; + dag DefaultOps = AlwaysVal; +} + +/// OptionalDefOperand - This is used to define a optional definition operand +/// for an instruction. DefaultOps is the register the operand represents if +/// none is supplied, e.g. zero_reg. +class OptionalDefOperand + : Operand { + let MIOperandInfo = OpTypes; + dag DefaultOps = defaultops; +} + + +// InstrInfo - This class should only be instantiated once to provide parameters +// which are global to the the target machine. +// +class InstrInfo { + // If the target wants to associate some target-specific information with each + // instruction, it should provide these two lists to indicate how to assemble + // the target specific information into the 32 bits available. + // + list TSFlagsFields = []; + list TSFlagsShifts = []; + + // Target can specify its instructions in either big or little-endian formats. + // For instance, while both Sparc and PowerPC are big-endian platforms, the + // Sparc manual specifies its instructions in the format [31..0] (big), while + // PowerPC specifies them using the format [0..31] (little). + bit isLittleEndianEncoding = 0; +} + +// Standard Pseudo Instructions. +let isCodeGenOnly = 1 in { +def PHI : Instruction { + let OutOperandList = (ops); + let InOperandList = (ops variable_ops); + let AsmString = "PHINODE"; + let Namespace = "TargetInstrInfo"; +} +def INLINEASM : Instruction { + let OutOperandList = (ops); + let InOperandList = (ops variable_ops); + let AsmString = ""; + let Namespace = "TargetInstrInfo"; +} +def DBG_LABEL : Instruction { + let OutOperandList = (ops); + let InOperandList = (ops i32imm:$id); + let AsmString = ""; + let Namespace = "TargetInstrInfo"; + let hasCtrlDep = 1; + let isNotDuplicable = 1; +} +def EH_LABEL : Instruction { + let OutOperandList = (ops); + let InOperandList = (ops i32imm:$id); + let AsmString = ""; + let Namespace = "TargetInstrInfo"; + let hasCtrlDep = 1; + let isNotDuplicable = 1; +} +def GC_LABEL : Instruction { + let OutOperandList = (ops); + let InOperandList = (ops i32imm:$id); + let AsmString = ""; + let Namespace = "TargetInstrInfo"; + let hasCtrlDep = 1; + let isNotDuplicable = 1; +} +def KILL : Instruction { + let OutOperandList = (ops); + let InOperandList = (ops variable_ops); + let AsmString = ""; + let Namespace = "TargetInstrInfo"; + let neverHasSideEffects = 1; +} +def EXTRACT_SUBREG : Instruction { + let OutOperandList = (ops unknown:$dst); + let InOperandList = (ops unknown:$supersrc, i32imm:$subidx); + let AsmString = ""; + let Namespace = "TargetInstrInfo"; + let neverHasSideEffects = 1; +} +def INSERT_SUBREG : Instruction { + let OutOperandList = (ops unknown:$dst); + let InOperandList = (ops unknown:$supersrc, unknown:$subsrc, i32imm:$subidx); + let AsmString = ""; + let Namespace = "TargetInstrInfo"; + let neverHasSideEffects = 1; + let Constraints = "$supersrc = $dst"; +} +def IMPLICIT_DEF : Instruction { + let OutOperandList = (ops unknown:$dst); + let InOperandList = (ops); + let AsmString = ""; + let Namespace = "TargetInstrInfo"; + let neverHasSideEffects = 1; + let isReMaterializable = 1; + let isAsCheapAsAMove = 1; +} +def SUBREG_TO_REG : Instruction { + let OutOperandList = (ops unknown:$dst); + let InOperandList = (ops unknown:$implsrc, unknown:$subsrc, i32imm:$subidx); + let AsmString = ""; + let Namespace = "TargetInstrInfo"; + let neverHasSideEffects = 1; +} +def COPY_TO_REGCLASS : Instruction { + let OutOperandList = (ops unknown:$dst); + let InOperandList = (ops unknown:$src, i32imm:$regclass); + let AsmString = ""; + let Namespace = "TargetInstrInfo"; + let neverHasSideEffects = 1; + let isAsCheapAsAMove = 1; +} +} + +//===----------------------------------------------------------------------===// +// AsmParser - This class can be implemented by targets that wish to implement +// .s file parsing. +// +// Subtargets can have multiple different assembly parsers (e.g. AT&T vs Intel +// syntax on X86 for example). +// +class AsmParser { + // AsmParserClassName - This specifies the suffix to use for the asmparser + // class. Generated AsmParser classes are always prefixed with the target + // name. + string AsmParserClassName = "AsmParser"; + + // Variant - AsmParsers can be of multiple different variants. Variants are + // used to support targets that need to parser multiple formats for the + // assembly language. + int Variant = 0; + + // CommentDelimiter - If given, the delimiter string used to recognize + // comments which are hard coded in the .td assembler strings for individual + // instructions. + string CommentDelimiter = ""; + + // RegisterPrefix - If given, the token prefix which indicates a register + // token. This is used by the matcher to automatically recognize hard coded + // register tokens as constrained registers, instead of tokens, for the + // purposes of matching. + string RegisterPrefix = ""; +} +def DefaultAsmParser : AsmParser; + + +//===----------------------------------------------------------------------===// +// AsmWriter - This class can be implemented by targets that need to customize +// the format of the .s file writer. +// +// Subtargets can have multiple different asmwriters (e.g. AT&T vs Intel syntax +// on X86 for example). +// +class AsmWriter { + // AsmWriterClassName - This specifies the suffix to use for the asmwriter + // class. Generated AsmWriter classes are always prefixed with the target + // name. + string AsmWriterClassName = "AsmPrinter"; + + // InstFormatName - AsmWriters can specify the name of the format string to + // print instructions with. + string InstFormatName = "AsmString"; + + // Variant - AsmWriters can be of multiple different variants. Variants are + // used to support targets that need to emit assembly code in ways that are + // mostly the same for different targets, but have minor differences in + // syntax. If the asmstring contains {|} characters in them, this integer + // will specify which alternative to use. For example "{x|y|z}" with Variant + // == 1, will expand to "y". + int Variant = 0; + + + // FirstOperandColumn/OperandSpacing - If the assembler syntax uses a columnar + // layout, the asmwriter can actually generate output in this columns (in + // verbose-asm mode). These two values indicate the width of the first column + // (the "opcode" area) and the width to reserve for subsequent operands. When + // verbose asm mode is enabled, operands will be indented to respect this. + int FirstOperandColumn = -1; + + // OperandSpacing - Space between operand columns. + int OperandSpacing = -1; +} +def DefaultAsmWriter : AsmWriter; + + +//===----------------------------------------------------------------------===// +// Target - This class contains the "global" target information +// +class Target { + // InstructionSet - Instruction set description for this target. + InstrInfo InstructionSet; + + // AssemblyParsers - The AsmParser instances available for this target. + list AssemblyParsers = [DefaultAsmParser]; + + // AssemblyWriters - The AsmWriter instances available for this target. + list AssemblyWriters = [DefaultAsmWriter]; +} + +//===----------------------------------------------------------------------===// +// SubtargetFeature - A characteristic of the chip set. +// +class SubtargetFeature i = []> { + // Name - Feature name. Used by command line (-mattr=) to determine the + // appropriate target chip. + // + string Name = n; + + // Attribute - Attribute to be set by feature. + // + string Attribute = a; + + // Value - Value the attribute to be set to by feature. + // + string Value = v; + + // Desc - Feature description. Used by command line (-mattr=) to display help + // information. + // + string Desc = d; + + // Implies - Features that this feature implies are present. If one of those + // features isn't set, then this one shouldn't be set either. + // + list Implies = i; +} + +//===----------------------------------------------------------------------===// +// Processor chip sets - These values represent each of the chip sets supported +// by the scheduler. Each Processor definition requires corresponding +// instruction itineraries. +// +class Processor f> { + // Name - Chip set name. Used by command line (-mcpu=) to determine the + // appropriate target chip. + // + string Name = n; + + // ProcItin - The scheduling information for the target processor. + // + ProcessorItineraries ProcItin = pi; + + // Features - list of + list Features = f; +} + +//===----------------------------------------------------------------------===// +// Pull in the common support for calling conventions. +// +include "llvm/Target/TargetCallingConv.td" + +//===----------------------------------------------------------------------===// +// Pull in the common support for DAG isel generation. +// +include "llvm/Target/TargetSelectionDAG.td" diff --git a/libclamav/c++/llvm/include/llvm/Target/TargetAsmParser.h b/libclamav/c++/llvm/include/llvm/Target/TargetAsmParser.h new file mode 100644 index 000000000..ef1fc49ce --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Target/TargetAsmParser.h @@ -0,0 +1,65 @@ +//===-- llvm/Target/TargetAsmParser.h - Target Assembly Parser --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TARGET_TARGETPARSER_H +#define LLVM_TARGET_TARGETPARSER_H + +#include "llvm/MC/MCAsmLexer.h" + +namespace llvm { +class MCAsmParser; +class MCInst; +class StringRef; +class Target; + +/// TargetAsmParser - Generic interface to target specific assembly parsers. +class TargetAsmParser { + TargetAsmParser(const TargetAsmParser &); // DO NOT IMPLEMENT + void operator=(const TargetAsmParser &); // DO NOT IMPLEMENT +protected: // Can only create subclasses. + TargetAsmParser(const Target &); + + /// TheTarget - The Target that this machine was created for. + const Target &TheTarget; + +public: + virtual ~TargetAsmParser(); + + const Target &getTarget() const { return TheTarget; } + + /// ParseInstruction - Parse one assembly instruction. + /// + /// The parser is positioned following the instruction name. The target + /// specific instruction parser should parse the entire instruction and + /// construct the appropriate MCInst, or emit an error. On success, the entire + /// line should be parsed up to and including the end-of-statement token. On + /// failure, the parser is not required to read to the end of the line. + // + /// \param AP - The current parser object. + /// \param Name - The instruction name. + /// \param Inst [out] - On success, the parsed instruction. + /// \return True on failure. + virtual bool ParseInstruction(const StringRef &Name, MCInst &Inst) = 0; + + /// ParseDirective - Parse a target specific assembler directive + /// + /// The parser is positioned following the directive name. The target + /// specific directive parser should parse the entire directive doing or + /// recording any target specific work, or return true and do nothing if the + /// directive is not target specific. If the directive is specific for + /// the target, the entire line is parsed up to and including the + /// end-of-statement token and false is returned. + /// + /// \param ID - the identifier token of the directive. + virtual bool ParseDirective(AsmToken DirectiveID) = 0; +}; + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Target/TargetCallingConv.td b/libclamav/c++/llvm/include/llvm/Target/TargetCallingConv.td new file mode 100644 index 000000000..ceaeb0b50 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Target/TargetCallingConv.td @@ -0,0 +1,128 @@ +//===- TargetCallingConv.td - Target Calling Conventions ---*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the target-independent interfaces with which targets +// describe their calling conventions. +// +//===----------------------------------------------------------------------===// + +class CCAction; +class CallingConv; + +/// CCCustom - Calls a custom arg handling function. +class CCCustom : CCAction { + string FuncName = fn; +} + +/// CCPredicateAction - Instances of this class check some predicate, then +/// delegate to another action if the predicate is true. +class CCPredicateAction : CCAction { + CCAction SubAction = A; +} + +/// CCIfType - If the current argument is one of the specified types, apply +/// Action A. +class CCIfType vts, CCAction A> : CCPredicateAction { + list VTs = vts; +} + +/// CCIf - If the predicate matches, apply A. +class CCIf : CCPredicateAction { + string Predicate = predicate; +} + +/// CCIfByVal - If the current argument has ByVal parameter attribute, apply +/// Action A. +class CCIfByVal : CCIf<"ArgFlags.isByVal()", A> { +} + +/// CCIfCC - Match of the current calling convention is 'CC'. +class CCIfCC + : CCIf {} + +/// CCIfInReg - If this argument is marked with the 'inreg' attribute, apply +/// the specified action. +class CCIfInReg : CCIf<"ArgFlags.isInReg()", A> {} + +/// CCIfNest - If this argument is marked with the 'nest' attribute, apply +/// the specified action. +class CCIfNest : CCIf<"ArgFlags.isNest()", A> {} + +/// CCIfSplit - If this argument is marked with the 'split' attribute, apply +/// the specified action. +class CCIfSplit : CCIf<"ArgFlags.isSplit()", A> {} + +/// CCIfSRet - If this argument is marked with the 'sret' attribute, apply +/// the specified action. +class CCIfSRet : CCIf<"ArgFlags.isSRet()", A> {} + +/// CCIfNotVarArg - If the current function is not vararg - apply the action +class CCIfNotVarArg : CCIf<"!State.isVarArg()", A> {} + +/// CCAssignToReg - This action matches if there is a register in the specified +/// list that is still available. If so, it assigns the value to the first +/// available register and succeeds. +class CCAssignToReg regList> : CCAction { + list RegList = regList; +} + +/// CCAssignToRegWithShadow - Same as CCAssignToReg, but with list of registers +/// which became shadowed, when some register is used. +class CCAssignToRegWithShadow regList, + list shadowList> : CCAction { + list RegList = regList; + list ShadowRegList = shadowList; +} + +/// CCAssignToStack - This action always matches: it assigns the value to a +/// stack slot of the specified size and alignment on the stack. If size is +/// zero then the ABI size is used; if align is zero then the ABI alignment +/// is used - these may depend on the target or subtarget. +class CCAssignToStack : CCAction { + int Size = size; + int Align = align; +} + +/// CCPassByVal - This action always matches: it assigns the value to a stack +/// slot to implement ByVal aggregate parameter passing. Size and alignment +/// specify the minimum size and alignment for the stack slot. +class CCPassByVal : CCAction { + int Size = size; + int Align = align; +} + +/// CCPromoteToType - If applied, this promotes the specified current value to +/// the specified type. +class CCPromoteToType : CCAction { + ValueType DestTy = destTy; +} + +/// CCBitConvertToType - If applied, this bitconverts the specified current +/// value to the specified type. +class CCBitConvertToType : CCAction { + ValueType DestTy = destTy; +} + +/// CCPassIndirect - If applied, this stores the value to stack and passes the pointer +/// as normal argument. +class CCPassIndirect : CCAction { + ValueType DestTy = destTy; +} + +/// CCDelegateTo - This action invokes the specified sub-calling-convention. It +/// is successful if the specified CC matches. +class CCDelegateTo : CCAction { + CallingConv CC = cc; +} + +/// CallingConv - An instance of this is used to define each calling convention +/// that the target supports. +class CallingConv actions> { + list Actions = actions; +} diff --git a/libclamav/c++/llvm/include/llvm/Target/TargetData.h b/libclamav/c++/llvm/include/llvm/Target/TargetData.h new file mode 100644 index 000000000..e1d052edb --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Target/TargetData.h @@ -0,0 +1,333 @@ +//===-- llvm/Target/TargetData.h - Data size & alignment 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 defines target properties related to datatype size/offset/alignment +// information. It uses lazy annotations to cache information about how +// structure types are laid out and used. +// +// This structure should be created once, filled in if the defaults are not +// correct and then passed around by const&. None of the members functions +// require modification to the object. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TARGET_TARGETDATA_H +#define LLVM_TARGET_TARGETDATA_H + +#include "llvm/Pass.h" +#include "llvm/ADT/SmallVector.h" + +namespace llvm { + +class Value; +class Type; +class IntegerType; +class StructType; +class StructLayout; +class StructLayoutMap; +class GlobalVariable; +class LLVMContext; + +/// Enum used to categorize the alignment types stored by TargetAlignElem +enum AlignTypeEnum { + INTEGER_ALIGN = 'i', ///< Integer type alignment + VECTOR_ALIGN = 'v', ///< Vector type alignment + FLOAT_ALIGN = 'f', ///< Floating point type alignment + AGGREGATE_ALIGN = 'a', ///< Aggregate alignment + STACK_ALIGN = 's' ///< Stack objects alignment +}; +/// Target alignment element. +/// +/// Stores the alignment data associated with a given alignment type (pointer, +/// integer, vector, float) and type bit width. +/// +/// @note The unusual order of elements in the structure attempts to reduce +/// padding and make the structure slightly more cache friendly. +struct TargetAlignElem { + AlignTypeEnum AlignType : 8; //< Alignment type (AlignTypeEnum) + unsigned char ABIAlign; //< ABI alignment for this type/bitw + unsigned char PrefAlign; //< Pref. alignment for this type/bitw + uint32_t TypeBitWidth; //< Type bit width + + /// Initializer + static TargetAlignElem get(AlignTypeEnum align_type, unsigned char abi_align, + unsigned char pref_align, uint32_t bit_width); + /// Equality predicate + bool operator==(const TargetAlignElem &rhs) const; + /// output stream operator + std::ostream &dump(std::ostream &os) const; +}; + +class TargetData : public ImmutablePass { +private: + bool LittleEndian; ///< Defaults to false + unsigned char PointerMemSize; ///< Pointer size in bytes + unsigned char PointerABIAlign; ///< Pointer ABI alignment + unsigned char PointerPrefAlign; ///< Pointer preferred alignment + + SmallVector LegalIntWidths; ///< Legal Integers. + + /// Alignments- Where the primitive type alignment data is stored. + /// + /// @sa init(). + /// @note Could support multiple size pointer alignments, e.g., 32-bit + /// pointers vs. 64-bit pointers by extending TargetAlignment, but for now, + /// we don't. + SmallVector Alignments; + + /// InvalidAlignmentElem - This member is a signal that a requested alignment + /// type and bit width were not found in the SmallVector. + static const TargetAlignElem InvalidAlignmentElem; + + // The StructType -> StructLayout map. + mutable StructLayoutMap *LayoutMap; + + //! Set/initialize target alignments + void setAlignment(AlignTypeEnum align_type, unsigned char abi_align, + unsigned char pref_align, uint32_t bit_width); + unsigned getAlignmentInfo(AlignTypeEnum align_type, uint32_t bit_width, + bool ABIAlign, const Type *Ty) const; + //! Internal helper method that returns requested alignment for type. + unsigned char getAlignment(const Type *Ty, bool abi_or_pref) const; + + /// Valid alignment predicate. + /// + /// Predicate that tests a TargetAlignElem reference returned by get() against + /// InvalidAlignmentElem. + bool validAlignment(const TargetAlignElem &align) const { + return &align != &InvalidAlignmentElem; + } + +public: + /// Default ctor. + /// + /// @note This has to exist, because this is a pass, but it should never be + /// used. + TargetData(); + + /// Constructs a TargetData from a specification string. See init(). + explicit TargetData(StringRef TargetDescription) + : ImmutablePass(&ID) { + init(TargetDescription); + } + + /// Initialize target data from properties stored in the module. + explicit TargetData(const Module *M); + + TargetData(const TargetData &TD) : + ImmutablePass(&ID), + LittleEndian(TD.isLittleEndian()), + PointerMemSize(TD.PointerMemSize), + PointerABIAlign(TD.PointerABIAlign), + PointerPrefAlign(TD.PointerPrefAlign), + LegalIntWidths(TD.LegalIntWidths), + Alignments(TD.Alignments), + LayoutMap(0) + { } + + ~TargetData(); // Not virtual, do not subclass this class + + //! Parse a target data layout string and initialize TargetData alignments. + void init(StringRef TargetDescription); + + /// Target endianness... + bool isLittleEndian() const { return LittleEndian; } + bool isBigEndian() const { return !LittleEndian; } + + /// getStringRepresentation - Return the string representation of the + /// TargetData. This representation is in the same format accepted by the + /// string constructor above. + std::string getStringRepresentation() const; + + /// isLegalInteger - This function returns true if the specified type is + /// known tobe a native integer type supported by the CPU. For example, + /// i64 is not native on most 32-bit CPUs and i37 is not native on any known + /// one. This returns false if the integer width is not legal. + /// + /// The width is specified in bits. + /// + bool isLegalInteger(unsigned Width) const { + for (unsigned i = 0, e = LegalIntWidths.size(); i != e; ++i) + if (LegalIntWidths[i] == Width) + return true; + return false; + } + + bool isIllegalInteger(unsigned Width) const { + return !isLegalInteger(Width); + } + + /// Target pointer alignment + unsigned char getPointerABIAlignment() const { return PointerABIAlign; } + /// Return target's alignment for stack-based pointers + unsigned char getPointerPrefAlignment() const { return PointerPrefAlign; } + /// Target pointer size + unsigned char getPointerSize() const { return PointerMemSize; } + /// Target pointer size, in bits + unsigned char getPointerSizeInBits() const { return 8*PointerMemSize; } + + /// Size examples: + /// + /// Type SizeInBits StoreSizeInBits AllocSizeInBits[*] + /// ---- ---------- --------------- --------------- + /// i1 1 8 8 + /// i8 8 8 8 + /// i19 19 24 32 + /// i32 32 32 32 + /// i100 100 104 128 + /// i128 128 128 128 + /// Float 32 32 32 + /// Double 64 64 64 + /// X86_FP80 80 80 96 + /// + /// [*] The alloc size depends on the alignment, and thus on the target. + /// These values are for x86-32 linux. + + /// getTypeSizeInBits - Return the number of bits necessary to hold the + /// specified type. For example, returns 36 for i36 and 80 for x86_fp80. + uint64_t getTypeSizeInBits(const Type* Ty) const; + + /// getTypeStoreSize - Return the maximum number of bytes that may be + /// overwritten by storing the specified type. For example, returns 5 + /// for i36 and 10 for x86_fp80. + uint64_t getTypeStoreSize(const Type *Ty) const { + return (getTypeSizeInBits(Ty)+7)/8; + } + + /// getTypeStoreSizeInBits - Return the maximum number of bits that may be + /// overwritten by storing the specified type; always a multiple of 8. For + /// example, returns 40 for i36 and 80 for x86_fp80. + uint64_t getTypeStoreSizeInBits(const Type *Ty) const { + return 8*getTypeStoreSize(Ty); + } + + /// getTypeAllocSize - Return the offset in bytes between successive objects + /// of the specified type, including alignment padding. This is the amount + /// that alloca reserves for this type. For example, returns 12 or 16 for + /// x86_fp80, depending on alignment. + uint64_t getTypeAllocSize(const Type* Ty) const { + // Round up to the next alignment boundary. + return RoundUpAlignment(getTypeStoreSize(Ty), getABITypeAlignment(Ty)); + } + + /// getTypeAllocSizeInBits - Return the offset in bits between successive + /// objects of the specified type, including alignment padding; always a + /// multiple of 8. This is the amount that alloca reserves for this type. + /// For example, returns 96 or 128 for x86_fp80, depending on alignment. + uint64_t getTypeAllocSizeInBits(const Type* Ty) const { + return 8*getTypeAllocSize(Ty); + } + + /// getABITypeAlignment - Return the minimum ABI-required alignment for the + /// specified type. + unsigned char getABITypeAlignment(const Type *Ty) const; + + /// getCallFrameTypeAlignment - Return the minimum ABI-required alignment + /// for the specified type when it is part of a call frame. + unsigned char getCallFrameTypeAlignment(const Type *Ty) const; + + + /// getPrefTypeAlignment - Return the preferred stack/global alignment for + /// the specified type. This is always at least as good as the ABI alignment. + unsigned char getPrefTypeAlignment(const Type *Ty) const; + + /// getPreferredTypeAlignmentShift - Return the preferred alignment for the + /// specified type, returned as log2 of the value (a shift amount). + /// + unsigned char getPreferredTypeAlignmentShift(const Type *Ty) const; + + /// getIntPtrType - Return an unsigned integer type that is the same size or + /// greater to the host pointer size. + /// + const IntegerType *getIntPtrType(LLVMContext &C) const; + + /// getIndexedOffset - return the offset from the beginning of the type for + /// the specified indices. This is used to implement getelementptr. + /// + uint64_t getIndexedOffset(const Type *Ty, + Value* const* Indices, unsigned NumIndices) const; + + /// getStructLayout - Return a StructLayout object, indicating the alignment + /// of the struct, its size, and the offsets of its fields. Note that this + /// information is lazily cached. + const StructLayout *getStructLayout(const StructType *Ty) const; + + /// InvalidateStructLayoutInfo - TargetData speculatively caches StructLayout + /// objects. If a TargetData object is alive when types are being refined and + /// removed, this method must be called whenever a StructType is removed to + /// avoid a dangling pointer in this cache. + void InvalidateStructLayoutInfo(const StructType *Ty) const; + + /// getPreferredAlignment - Return the preferred alignment of the specified + /// global. This includes an explicitly requested alignment (if the global + /// has one). + unsigned getPreferredAlignment(const GlobalVariable *GV) const; + + /// getPreferredAlignmentLog - Return the preferred alignment of the + /// specified global, returned in log form. This includes an explicitly + /// requested alignment (if the global has one). + unsigned getPreferredAlignmentLog(const GlobalVariable *GV) const; + + /// RoundUpAlignment - Round the specified value up to the next alignment + /// boundary specified by Alignment. For example, 7 rounded up to an + /// alignment boundary of 4 is 8. 8 rounded up to the alignment boundary of 4 + /// is 8 because it is already aligned. + template + static UIntTy RoundUpAlignment(UIntTy Val, unsigned Alignment) { + assert((Alignment & (Alignment-1)) == 0 && "Alignment must be power of 2!"); + return (Val + (Alignment-1)) & ~UIntTy(Alignment-1); + } + + static char ID; // Pass identification, replacement for typeid +}; + +/// StructLayout - used to lazily calculate structure layout information for a +/// target machine, based on the TargetData structure. +/// +class StructLayout { + uint64_t StructSize; + unsigned StructAlignment; + unsigned NumElements; + uint64_t MemberOffsets[1]; // variable sized array! +public: + + uint64_t getSizeInBytes() const { + return StructSize; + } + + uint64_t getSizeInBits() const { + return 8*StructSize; + } + + unsigned getAlignment() const { + return StructAlignment; + } + + /// getElementContainingOffset - Given a valid byte offset into the structure, + /// return the structure index that contains it. + /// + unsigned getElementContainingOffset(uint64_t Offset) const; + + uint64_t getElementOffset(unsigned Idx) const { + assert(Idx < NumElements && "Invalid element idx!"); + return MemberOffsets[Idx]; + } + + uint64_t getElementOffsetInBits(unsigned Idx) const { + return getElementOffset(Idx)*8; + } + +private: + friend class TargetData; // Only TargetData can create this class + StructLayout(const StructType *ST, const TargetData &TD); +}; + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Target/TargetELFWriterInfo.h b/libclamav/c++/llvm/include/llvm/Target/TargetELFWriterInfo.h new file mode 100644 index 000000000..7cb693155 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Target/TargetELFWriterInfo.h @@ -0,0 +1,124 @@ +//===-- llvm/Target/TargetELFWriterInfo.h - ELF Writer 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 defines the TargetELFWriterInfo class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TARGET_TARGETELFWRITERINFO_H +#define LLVM_TARGET_TARGETELFWRITERINFO_H + +namespace llvm { + class Function; + class TargetData; + class TargetMachine; + + //===--------------------------------------------------------------------===// + // TargetELFWriterInfo + //===--------------------------------------------------------------------===// + + class TargetELFWriterInfo { + protected: + // EMachine - This field is the target specific value to emit as the + // e_machine member of the ELF header. + unsigned short EMachine; + TargetMachine &TM; + bool is64Bit, isLittleEndian; + public: + + // Machine architectures + enum MachineType { + EM_NONE = 0, // No machine + EM_M32 = 1, // AT&T WE 32100 + EM_SPARC = 2, // SPARC + EM_386 = 3, // Intel 386 + EM_68K = 4, // Motorola 68000 + EM_88K = 5, // Motorola 88000 + EM_486 = 6, // Intel 486 (deprecated) + EM_860 = 7, // Intel 80860 + EM_MIPS = 8, // MIPS R3000 + EM_PPC = 20, // PowerPC + EM_ARM = 40, // ARM + EM_ALPHA = 41, // DEC Alpha + EM_SPARCV9 = 43, // SPARC V9 + EM_X86_64 = 62 // AMD64 + }; + + // ELF File classes + enum { + ELFCLASS32 = 1, // 32-bit object file + ELFCLASS64 = 2 // 64-bit object file + }; + + // ELF Endianess + enum { + ELFDATA2LSB = 1, // Little-endian object file + ELFDATA2MSB = 2 // Big-endian object file + }; + + explicit TargetELFWriterInfo(TargetMachine &tm); + virtual ~TargetELFWriterInfo(); + + unsigned short getEMachine() const { return EMachine; } + unsigned getEFlags() const { return 0; } + unsigned getEIClass() const { return is64Bit ? ELFCLASS64 : ELFCLASS32; } + unsigned getEIData() const { + return isLittleEndian ? ELFDATA2LSB : ELFDATA2MSB; + } + + /// ELF Header and ELF Section Header Info + unsigned getHdrSize() const { return is64Bit ? 64 : 52; } + unsigned getSHdrSize() const { return is64Bit ? 64 : 40; } + + /// Symbol Table Info + unsigned getSymTabEntrySize() const { return is64Bit ? 24 : 16; } + + /// getPrefELFAlignment - Returns the preferred alignment for ELF. This + /// is used to align some sections. + unsigned getPrefELFAlignment() const { return is64Bit ? 8 : 4; } + + /// getRelocationEntrySize - Entry size used in the relocation section + unsigned getRelocationEntrySize() const { + return is64Bit ? (hasRelocationAddend() ? 24 : 16) + : (hasRelocationAddend() ? 12 : 8); + } + + /// getRelocationType - Returns the target specific ELF Relocation type. + /// 'MachineRelTy' contains the object code independent relocation type + virtual unsigned getRelocationType(unsigned MachineRelTy) const = 0; + + /// hasRelocationAddend - True if the target uses an addend in the + /// ELF relocation entry. + virtual bool hasRelocationAddend() const = 0; + + /// getDefaultAddendForRelTy - Gets the default addend value for a + /// relocation entry based on the target ELF relocation type. + virtual long int getDefaultAddendForRelTy(unsigned RelTy, + long int Modifier = 0) const = 0; + + /// getRelTySize - Returns the size of relocatable field in bits + virtual unsigned getRelocationTySize(unsigned RelTy) const = 0; + + /// isPCRelativeRel - True if the relocation type is pc relative + virtual bool isPCRelativeRel(unsigned RelTy) const = 0; + + /// getJumpTableRelocationTy - Returns the machine relocation type used + /// to reference a jumptable. + virtual unsigned getAbsoluteLabelMachineRelTy() const = 0; + + /// computeRelocation - Some relocatable fields could be relocated + /// directly, avoiding the relocation symbol emission, compute the + /// final relocation value for this symbol. + virtual long int computeRelocation(unsigned SymOffset, unsigned RelOffset, + unsigned RelTy) const = 0; + }; + +} // end llvm namespace + +#endif // LLVM_TARGET_TARGETELFWRITERINFO_H diff --git a/libclamav/c++/llvm/include/llvm/Target/TargetFrameInfo.h b/libclamav/c++/llvm/include/llvm/Target/TargetFrameInfo.h new file mode 100644 index 000000000..975d15659 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Target/TargetFrameInfo.h @@ -0,0 +1,97 @@ +//===-- llvm/Target/TargetFrameInfo.h ---------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Interface to describe the layout of a stack frame on the target machine. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TARGET_TARGETFRAMEINFO_H +#define LLVM_TARGET_TARGETFRAMEINFO_H + +#include + +namespace llvm { + +/// Information about stack frame layout on the target. It holds the direction +/// of stack growth, the known stack alignment on entry to each function, and +/// the offset to the locals area. +/// +/// The offset to the local area is the offset from the stack pointer on +/// function entry to the first location where function data (local variables, +/// spill locations) can be stored. +class TargetFrameInfo { +public: + enum StackDirection { + StackGrowsUp, // Adding to the stack increases the stack address + StackGrowsDown // Adding to the stack decreases the stack address + }; + + // Maps a callee saved register to a stack slot with a fixed offset. + struct SpillSlot { + unsigned Reg; + int Offset; // Offset relative to stack pointer on function entry. + }; +private: + StackDirection StackDir; + unsigned StackAlignment; + unsigned TransientStackAlignment; + int LocalAreaOffset; +public: + TargetFrameInfo(StackDirection D, unsigned StackAl, int LAO, + unsigned TransAl = 1) + : StackDir(D), StackAlignment(StackAl), TransientStackAlignment(TransAl), + LocalAreaOffset(LAO) {} + + virtual ~TargetFrameInfo(); + + // These methods return information that describes the abstract stack layout + // of the target machine. + + /// getStackGrowthDirection - Return the direction the stack grows + /// + StackDirection getStackGrowthDirection() const { return StackDir; } + + /// getStackAlignment - This method returns the number of bytes to which the + /// stack pointer must be aligned on entry to a function. Typically, this + /// is the largest alignment for any data object in the target. + /// + unsigned getStackAlignment() const { return StackAlignment; } + + /// getTransientStackAlignment - This method returns the number of bytes to + /// which the stack pointer must be aligned at all times, even between + /// calls. + /// + unsigned getTransientStackAlignment() const { + return TransientStackAlignment; + } + + /// getOffsetOfLocalArea - This method returns the offset of the local area + /// from the stack pointer on entrance to a function. + /// + int getOffsetOfLocalArea() const { return LocalAreaOffset; } + + /// getCalleeSavedSpillSlots - This method returns a pointer to an array of + /// pairs, that contains an entry for each callee saved register that must be + /// spilled to a particular stack location if it is spilled. + /// + /// Each entry in this array contains a pair, indicating the + /// fixed offset from the incoming stack pointer that each register should be + /// spilled at. If a register is not listed here, the code generator is + /// allowed to spill it anywhere it chooses. + /// + virtual const SpillSlot * + getCalleeSavedSpillSlots(unsigned &NumEntries) const { + NumEntries = 0; + return 0; + } +}; + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Target/TargetInstrDesc.h b/libclamav/c++/llvm/include/llvm/Target/TargetInstrDesc.h new file mode 100644 index 000000000..b0ed0bf0c --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Target/TargetInstrDesc.h @@ -0,0 +1,472 @@ +//===-- llvm/Target/TargetInstrDesc.h - Instruction Descriptors -*- 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 the TargetOperandInfo and TargetInstrDesc classes, which +// are used to describe target instructions and their operands. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TARGET_TARGETINSTRDESC_H +#define LLVM_TARGET_TARGETINSTRDESC_H + +namespace llvm { + +class TargetRegisterClass; +class TargetRegisterInfo; + +//===----------------------------------------------------------------------===// +// Machine Operand Flags and Description +//===----------------------------------------------------------------------===// + +namespace TOI { + // Operand constraints: only "tied_to" for now. + enum OperandConstraint { + TIED_TO = 0 // Must be allocated the same register as. + }; + + /// OperandFlags - These are flags set on operands, but should be considered + /// private, all access should go through the TargetOperandInfo accessors. + /// See the accessors for a description of what these are. + enum OperandFlags { + LookupPtrRegClass = 0, + Predicate, + OptionalDef + }; +} + +/// TargetOperandInfo - This holds information about one operand of a machine +/// instruction, indicating the register class for register operands, etc. +/// +class TargetOperandInfo { +public: + /// RegClass - This specifies the register class enumeration of the operand + /// if the operand is a register. If isLookupPtrRegClass is set, then this is + /// an index that is passed to TargetRegisterInfo::getPointerRegClass(x) to + /// get a dynamic register class. + /// + /// NOTE: This member should be considered to be private, all access should go + /// through "getRegClass(TRI)" below. + unsigned short RegClass; + + /// Flags - These are flags from the TOI::OperandFlags enum. + unsigned short Flags; + + /// Lower 16 bits are used to specify which constraints are set. The higher 16 + /// bits are used to specify the value of constraints (4 bits each). + unsigned Constraints; + /// Currently no other information. + + /// getRegClass - Get the register class for the operand, handling resolution + /// of "symbolic" pointer register classes etc. If this is not a register + /// operand, this returns null. + const TargetRegisterClass *getRegClass(const TargetRegisterInfo *TRI) const; + + + /// isLookupPtrRegClass - Set if this operand is a pointer value and it + /// requires a callback to look up its register class. + bool isLookupPtrRegClass() const { return Flags&(1 <> Pos) & 0xf; + } + return -1; + } + + /// getOpcode - Return the opcode number for this descriptor. + unsigned getOpcode() const { + return Opcode; + } + + /// getName - Return the name of the record in the .td file for this + /// instruction, for example "ADD8ri". + const char *getName() const { + return Name; + } + + /// getNumOperands - Return the number of declared MachineOperands for this + /// MachineInstruction. Note that variadic (isVariadic() returns true) + /// instructions may have additional operands at the end of the list, and note + /// that the machine instruction may include implicit register def/uses as + /// well. + unsigned getNumOperands() const { + return NumOperands; + } + + /// getNumDefs - Return the number of MachineOperands that are register + /// definitions. Register definitions always occur at the start of the + /// machine operand list. This is the number of "outs" in the .td file, + /// and does not include implicit defs. + unsigned getNumDefs() const { + return NumDefs; + } + + /// isVariadic - Return true if this instruction can have a variable number of + /// operands. In this case, the variable operands will be after the normal + /// operands but before the implicit definitions and uses (if any are + /// present). + bool isVariadic() const { + return Flags & (1 << TID::Variadic); + } + + /// hasOptionalDef - Set if this instruction has an optional definition, e.g. + /// ARM instructions which can set condition code if 's' bit is set. + bool hasOptionalDef() const { + return Flags & (1 << TID::HasOptionalDef); + } + + /// getImplicitUses - Return a list of registers that are potentially + /// read by any instance of this machine instruction. For example, on X86, + /// the "adc" instruction adds two register operands and adds the carry bit in + /// from the flags register. In this case, the instruction is marked as + /// implicitly reading the flags. Likewise, the variable shift instruction on + /// X86 is marked as implicitly reading the 'CL' register, which it always + /// does. + /// + /// This method returns null if the instruction has no implicit uses. + const unsigned *getImplicitUses() const { + return ImplicitUses; + } + + /// getImplicitDefs - Return a list of registers that are potentially + /// written by any instance of this machine instruction. For example, on X86, + /// many instructions implicitly set the flags register. In this case, they + /// are marked as setting the FLAGS. Likewise, many instructions always + /// deposit their result in a physical register. For example, the X86 divide + /// instruction always deposits the quotient and remainder in the EAX/EDX + /// registers. For that instruction, this will return a list containing the + /// EAX/EDX/EFLAGS registers. + /// + /// This method returns null if the instruction has no implicit defs. + const unsigned *getImplicitDefs() const { + return ImplicitDefs; + } + + /// hasImplicitUseOfPhysReg - Return true if this instruction implicitly + /// uses the specified physical register. + bool hasImplicitUseOfPhysReg(unsigned Reg) const { + if (const unsigned *ImpUses = ImplicitUses) + for (; *ImpUses; ++ImpUses) + if (*ImpUses == Reg) return true; + return false; + } + + /// hasImplicitDefOfPhysReg - Return true if this instruction implicitly + /// defines the specified physical register. + bool hasImplicitDefOfPhysReg(unsigned Reg) const { + if (const unsigned *ImpDefs = ImplicitDefs) + for (; *ImpDefs; ++ImpDefs) + if (*ImpDefs == Reg) return true; + return false; + } + + /// getRegClassBarriers - Return a list of register classes that are + /// completely clobbered by this machine instruction. For example, on X86 + /// the call instructions will completely clobber all the registers in the + /// fp stack and XMM classes. + /// + /// This method returns null if the instruction doesn't completely clobber + /// any register class. + const TargetRegisterClass **getRegClassBarriers() const { + return RCBarriers; + } + + /// getSchedClass - Return the scheduling class for this instruction. The + /// scheduling class is an index into the InstrItineraryData table. This + /// returns zero if there is no known scheduling information for the + /// instruction. + /// + unsigned getSchedClass() const { + return SchedClass; + } + + bool isReturn() const { + return Flags & (1 << TID::Return); + } + + bool isCall() const { + return Flags & (1 << TID::Call); + } + + /// isBarrier - Returns true if the specified instruction stops control flow + /// from executing the instruction immediately following it. Examples include + /// unconditional branches and return instructions. + bool isBarrier() const { + return Flags & (1 << TID::Barrier); + } + + /// isTerminator - Returns true if this instruction part of the terminator for + /// a basic block. Typically this is things like return and branch + /// instructions. + /// + /// Various passes use this to insert code into the bottom of a basic block, + /// but before control flow occurs. + bool isTerminator() const { + return Flags & (1 << TID::Terminator); + } + + /// isBranch - Returns true if this is a conditional, unconditional, or + /// indirect branch. Predicates below can be used to discriminate between + /// these cases, and the TargetInstrInfo::AnalyzeBranch method can be used to + /// get more information. + bool isBranch() const { + return Flags & (1 << TID::Branch); + } + + /// isIndirectBranch - Return true if this is an indirect branch, such as a + /// branch through a register. + bool isIndirectBranch() const { + return Flags & (1 << TID::IndirectBranch); + } + + /// isConditionalBranch - Return true if this is a branch which may fall + /// through to the next instruction or may transfer control flow to some other + /// block. The TargetInstrInfo::AnalyzeBranch method can be used to get more + /// information about this branch. + bool isConditionalBranch() const { + return isBranch() & !isBarrier() & !isIndirectBranch(); + } + + /// isUnconditionalBranch - Return true if this is a branch which always + /// transfers control flow to some other block. The + /// TargetInstrInfo::AnalyzeBranch method can be used to get more information + /// about this branch. + bool isUnconditionalBranch() const { + return isBranch() & isBarrier() & !isIndirectBranch(); + } + + // isPredicable - Return true if this instruction has a predicate operand that + // controls execution. It may be set to 'always', or may be set to other + /// values. There are various methods in TargetInstrInfo that can be used to + /// control and modify the predicate in this instruction. + bool isPredicable() const { + return Flags & (1 << TID::Predicable); + } + + /// isNotDuplicable - Return true if this instruction cannot be safely + /// duplicated. For example, if the instruction has a unique labels attached + /// to it, duplicating it would cause multiple definition errors. + bool isNotDuplicable() const { + return Flags & (1 << TID::NotDuplicable); + } + + /// hasDelaySlot - Returns true if the specified instruction has a delay slot + /// which must be filled by the code generator. + bool hasDelaySlot() const { + return Flags & (1 << TID::DelaySlot); + } + + /// canFoldAsLoad - Return true for instructions that can be folded as + /// memory operands in other instructions. The most common use for this + /// is instructions that are simple loads from memory that don't modify + /// the loaded value in any way, but it can also be used for instructions + /// that can be expressed as constant-pool loads, such as V_SETALLONES + /// on x86, to allow them to be folded when it is beneficial. + /// This should only be set on instructions that return a value in their + /// only virtual register definition. + bool canFoldAsLoad() const { + return Flags & (1 << TID::FoldableAsLoad); + } + + //===--------------------------------------------------------------------===// + // Side Effect Analysis + //===--------------------------------------------------------------------===// + + /// mayLoad - Return true if this instruction could possibly read memory. + /// Instructions with this flag set are not necessarily simple load + /// instructions, they may load a value and modify it, for example. + bool mayLoad() const { + return Flags & (1 << TID::MayLoad); + } + + + /// mayStore - Return true if this instruction could possibly modify memory. + /// Instructions with this flag set are not necessarily simple store + /// instructions, they may store a modified value based on their operands, or + /// may not actually modify anything, for example. + bool mayStore() const { + return Flags & (1 << TID::MayStore); + } + + /// hasUnmodeledSideEffects - Return true if this instruction has side + /// effects that are not modeled by other flags. This does not return true + /// for instructions whose effects are captured by: + /// + /// 1. Their operand list and implicit definition/use list. Register use/def + /// info is explicit for instructions. + /// 2. Memory accesses. Use mayLoad/mayStore. + /// 3. Calling, branching, returning: use isCall/isReturn/isBranch. + /// + /// Examples of side effects would be modifying 'invisible' machine state like + /// a control register, flushing a cache, modifying a register invisible to + /// LLVM, etc. + /// + bool hasUnmodeledSideEffects() const { + return Flags & (1 << TID::UnmodeledSideEffects); + } + + //===--------------------------------------------------------------------===// + // Flags that indicate whether an instruction can be modified by a method. + //===--------------------------------------------------------------------===// + + /// isCommutable - Return true if this may be a 2- or 3-address + /// instruction (of the form "X = op Y, Z, ..."), which produces the same + /// result if Y and Z are exchanged. If this flag is set, then the + /// TargetInstrInfo::commuteInstruction method may be used to hack on the + /// instruction. + /// + /// Note that this flag may be set on instructions that are only commutable + /// sometimes. In these cases, the call to commuteInstruction will fail. + /// Also note that some instructions require non-trivial modification to + /// commute them. + bool isCommutable() const { + return Flags & (1 << TID::Commutable); + } + + /// isConvertibleTo3Addr - Return true if this is a 2-address instruction + /// which can be changed into a 3-address instruction if needed. Doing this + /// transformation can be profitable in the register allocator, because it + /// means that the instruction can use a 2-address form if possible, but + /// degrade into a less efficient form if the source and dest register cannot + /// be assigned to the same register. For example, this allows the x86 + /// backend to turn a "shl reg, 3" instruction into an LEA instruction, which + /// is the same speed as the shift but has bigger code size. + /// + /// If this returns true, then the target must implement the + /// TargetInstrInfo::convertToThreeAddress method for this instruction, which + /// is allowed to fail if the transformation isn't valid for this specific + /// instruction (e.g. shl reg, 4 on x86). + /// + bool isConvertibleTo3Addr() const { + return Flags & (1 << TID::ConvertibleTo3Addr); + } + + /// usesCustomInsertionHook - Return true if this instruction requires + /// custom insertion support when the DAG scheduler is inserting it into a + /// machine basic block. If this is true for the instruction, it basically + /// means that it is a pseudo instruction used at SelectionDAG time that is + /// expanded out into magic code by the target when MachineInstrs are formed. + /// + /// If this is true, the TargetLoweringInfo::InsertAtEndOfBasicBlock method + /// is used to insert this into the MachineBasicBlock. + bool usesCustomInsertionHook() const { + return Flags & (1 << TID::UsesCustomInserter); + } + + /// isRematerializable - Returns true if this instruction is a candidate for + /// remat. This flag is deprecated, please don't use it anymore. If this + /// flag is set, the isReallyTriviallyReMaterializable() method is called to + /// verify the instruction is really rematable. + bool isRematerializable() const { + return Flags & (1 << TID::Rematerializable); + } + + /// isAsCheapAsAMove - Returns true if this instruction has the same cost (or + /// less) than a move instruction. This is useful during certain types of + /// optimizations (e.g., remat during two-address conversion or machine licm) + /// where we would like to remat or hoist the instruction, but not if it costs + /// more than moving the instruction into the appropriate register. Note, we + /// are not marking copies from and to the same register class with this flag. + bool isAsCheapAsAMove() const { + return Flags & (1 << TID::CheapAsAMove); + } + + /// hasExtraSrcRegAllocReq - Returns true if this instruction source operands + /// have special register allocation requirements that are not captured by the + /// operand register classes. e.g. ARM::STRD's two source registers must be an + /// even / odd pair, ARM::STM registers have to be in ascending order. + /// Post-register allocation passes should not attempt to change allocations + /// for sources of instructions with this flag. + bool hasExtraSrcRegAllocReq() const { + return Flags & (1 << TID::ExtraSrcRegAllocReq); + } + + /// hasExtraDefRegAllocReq - Returns true if this instruction def operands + /// have special register allocation requirements that are not captured by the + /// operand register classes. e.g. ARM::LDRD's two def registers must be an + /// even / odd pair, ARM::LDM registers have to be in ascending order. + /// Post-register allocation passes should not attempt to change allocations + /// for definitions of instructions with this flag. + bool hasExtraDefRegAllocReq() const { + return Flags & (1 << TID::ExtraDefRegAllocReq); + } +}; + +} // end namespace llvm + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Target/TargetInstrInfo.h b/libclamav/c++/llvm/include/llvm/Target/TargetInstrInfo.h new file mode 100644 index 000000000..8070d4585 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Target/TargetInstrInfo.h @@ -0,0 +1,581 @@ +//===-- llvm/Target/TargetInstrInfo.h - Instruction 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 describes the target machine instruction set to the code generator. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TARGET_TARGETINSTRINFO_H +#define LLVM_TARGET_TARGETINSTRINFO_H + +#include "llvm/Target/TargetInstrDesc.h" +#include "llvm/CodeGen/MachineFunction.h" + +namespace llvm { + +class MCAsmInfo; +class TargetRegisterClass; +class TargetRegisterInfo; +class LiveVariables; +class CalleeSavedInfo; +class SDNode; +class SelectionDAG; + +template class SmallVectorImpl; + + +//--------------------------------------------------------------------------- +/// +/// TargetInstrInfo - Interface to description of machine instruction set +/// +class TargetInstrInfo { + const TargetInstrDesc *Descriptors; // Raw array to allow static init'n + unsigned NumOpcodes; // Number of entries in the desc array + + TargetInstrInfo(const TargetInstrInfo &); // DO NOT IMPLEMENT + void operator=(const TargetInstrInfo &); // DO NOT IMPLEMENT +public: + TargetInstrInfo(const TargetInstrDesc *desc, unsigned NumOpcodes); + virtual ~TargetInstrInfo(); + + // Invariant opcodes: All instruction sets have these as their low opcodes. + enum { + PHI = 0, + INLINEASM = 1, + DBG_LABEL = 2, + EH_LABEL = 3, + GC_LABEL = 4, + + /// KILL - This instruction is a noop that is used only to adjust the liveness + /// of registers. This can be useful when dealing with sub-registers. + KILL = 5, + + /// EXTRACT_SUBREG - This instruction takes two operands: a register + /// that has subregisters, and a subregister index. It returns the + /// extracted subregister value. This is commonly used to implement + /// truncation operations on target architectures which support it. + EXTRACT_SUBREG = 6, + + /// INSERT_SUBREG - This instruction takes three operands: a register + /// that has subregisters, a register providing an insert value, and a + /// subregister index. It returns the value of the first register with + /// the value of the second register inserted. The first register is + /// often defined by an IMPLICIT_DEF, as is commonly used to implement + /// anyext operations on target architectures which support it. + INSERT_SUBREG = 7, + + /// IMPLICIT_DEF - This is the MachineInstr-level equivalent of undef. + IMPLICIT_DEF = 8, + + /// SUBREG_TO_REG - This instruction is similar to INSERT_SUBREG except + /// that the first operand is an immediate integer constant. This constant + /// is often zero, as is commonly used to implement zext operations on + /// target architectures which support it, such as with x86-64 (with + /// zext from i32 to i64 via implicit zero-extension). + SUBREG_TO_REG = 9, + + /// COPY_TO_REGCLASS - This instruction is a placeholder for a plain + /// register-to-register copy into a specific register class. This is only + /// used between instruction selection and MachineInstr creation, before + /// virtual registers have been created for all the instructions, and it's + /// only needed in cases where the register classes implied by the + /// instructions are insufficient. The actual MachineInstrs to perform + /// the copy are emitted with the TargetInstrInfo::copyRegToReg hook. + COPY_TO_REGCLASS = 10 + }; + + unsigned getNumOpcodes() const { return NumOpcodes; } + + /// get - Return the machine instruction descriptor that corresponds to the + /// specified instruction opcode. + /// + const TargetInstrDesc &get(unsigned Opcode) const { + assert(Opcode < NumOpcodes && "Invalid opcode!"); + return Descriptors[Opcode]; + } + + /// isTriviallyReMaterializable - Return true if the instruction is trivially + /// rematerializable, meaning it has no side effects and requires no operands + /// that aren't always available. + bool isTriviallyReMaterializable(const MachineInstr *MI, + AliasAnalysis *AA = 0) const { + return MI->getOpcode() == IMPLICIT_DEF || + (MI->getDesc().isRematerializable() && + (isReallyTriviallyReMaterializable(MI, AA) || + isReallyTriviallyReMaterializableGeneric(MI, AA))); + } + +protected: + /// isReallyTriviallyReMaterializable - For instructions with opcodes for + /// which the M_REMATERIALIZABLE flag is set, this hook lets the target + /// specify whether the instruction is actually trivially rematerializable, + /// taking into consideration its operands. This predicate must return false + /// if the instruction has any side effects other than producing a value, or + /// if it requres any address registers that are not always available. + virtual bool isReallyTriviallyReMaterializable(const MachineInstr *MI, + AliasAnalysis *AA) const { + return false; + } + +private: + /// isReallyTriviallyReMaterializableGeneric - For instructions with opcodes + /// for which the M_REMATERIALIZABLE flag is set and the target hook + /// isReallyTriviallyReMaterializable returns false, this function does + /// target-independent tests to determine if the instruction is really + /// trivially rematerializable. + bool isReallyTriviallyReMaterializableGeneric(const MachineInstr *MI, + AliasAnalysis *AA) const; + +public: + /// isMoveInstr - Return true if the instruction is a register to register + /// move and return the source and dest operands and their sub-register + /// indices by reference. + virtual bool isMoveInstr(const MachineInstr& MI, + unsigned& SrcReg, unsigned& DstReg, + unsigned& SrcSubIdx, unsigned& DstSubIdx) const { + return false; + } + + /// isIdentityCopy - Return true if the instruction is a copy (or + /// extract_subreg, insert_subreg, subreg_to_reg) where the source and + /// destination registers are the same. + bool isIdentityCopy(const MachineInstr &MI) const { + unsigned SrcReg, DstReg, SrcSubIdx, DstSubIdx; + if (isMoveInstr(MI, SrcReg, DstReg, SrcSubIdx, DstSubIdx) && + SrcReg == DstReg) + return true; + + if (MI.getOpcode() == TargetInstrInfo::EXTRACT_SUBREG && + MI.getOperand(0).getReg() == MI.getOperand(1).getReg()) + return true; + + if ((MI.getOpcode() == TargetInstrInfo::INSERT_SUBREG || + MI.getOpcode() == TargetInstrInfo::SUBREG_TO_REG) && + MI.getOperand(0).getReg() == MI.getOperand(2).getReg()) + return true; + return false; + } + + /// isLoadFromStackSlot - If the specified machine instruction is a direct + /// load from a stack slot, return the virtual or physical register number of + /// the destination along with the FrameIndex of the loaded stack slot. If + /// not, return 0. This predicate must return 0 if the instruction has + /// any side effects other than loading from the stack slot. + virtual unsigned isLoadFromStackSlot(const MachineInstr *MI, + int &FrameIndex) const { + return 0; + } + + /// isLoadFromStackSlotPostFE - Check for post-frame ptr elimination + /// stack locations as well. This uses a heuristic so it isn't + /// reliable for correctness. + virtual unsigned isLoadFromStackSlotPostFE(const MachineInstr *MI, + int &FrameIndex) const { + return 0; + } + + /// hasLoadFromStackSlot - If the specified machine instruction has + /// a load from a stack slot, return true along with the FrameIndex + /// of the loaded stack slot. If not, return false. Unlike + /// isLoadFromStackSlot, this returns true for any instructions that + /// loads from the stack. This is just a hint, as some cases may be + /// missed. + virtual bool hasLoadFromStackSlot(const MachineInstr *MI, + int &FrameIndex) const { + return 0; + } + + /// isStoreToStackSlot - If the specified machine instruction is a direct + /// store to a stack slot, return the virtual or physical register number of + /// the source reg along with the FrameIndex of the loaded stack slot. If + /// not, return 0. This predicate must return 0 if the instruction has + /// any side effects other than storing to the stack slot. + virtual unsigned isStoreToStackSlot(const MachineInstr *MI, + int &FrameIndex) const { + return 0; + } + + /// isStoreToStackSlotPostFE - Check for post-frame ptr elimination + /// stack locations as well. This uses a heuristic so it isn't + /// reliable for correctness. + virtual unsigned isStoreToStackSlotPostFE(const MachineInstr *MI, + int &FrameIndex) const { + return 0; + } + + /// hasStoreToStackSlot - If the specified machine instruction has a + /// store to a stack slot, return true along with the FrameIndex of + /// the loaded stack slot. If not, return false. Unlike + /// isStoreToStackSlot, this returns true for any instructions that + /// loads from the stack. This is just a hint, as some cases may be + /// missed. + virtual bool hasStoreToStackSlot(const MachineInstr *MI, + int &FrameIndex) const { + return 0; + } + + /// reMaterialize - Re-issue the specified 'original' instruction at the + /// specific location targeting a new destination register. + virtual void reMaterialize(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + unsigned DestReg, unsigned SubIdx, + const MachineInstr *Orig, + const TargetRegisterInfo *TRI) const = 0; + + /// convertToThreeAddress - This method must be implemented by targets that + /// set the M_CONVERTIBLE_TO_3_ADDR flag. When this flag is set, the target + /// may be able to convert a two-address instruction into one or more true + /// three-address instructions on demand. This allows the X86 target (for + /// example) to convert ADD and SHL instructions into LEA instructions if they + /// would require register copies due to two-addressness. + /// + /// This method returns a null pointer if the transformation cannot be + /// performed, otherwise it returns the last new instruction. + /// + virtual MachineInstr * + convertToThreeAddress(MachineFunction::iterator &MFI, + MachineBasicBlock::iterator &MBBI, LiveVariables *LV) const { + return 0; + } + + /// commuteInstruction - If a target has any instructions that are commutable, + /// but require converting to a different instruction or making non-trivial + /// changes to commute them, this method can overloaded to do this. The + /// default implementation of this method simply swaps the first two operands + /// of MI and returns it. + /// + /// If a target wants to make more aggressive changes, they can construct and + /// return a new machine instruction. If an instruction cannot commute, it + /// can also return null. + /// + /// If NewMI is true, then a new machine instruction must be created. + /// + virtual MachineInstr *commuteInstruction(MachineInstr *MI, + bool NewMI = false) const = 0; + + /// findCommutedOpIndices - If specified MI is commutable, return the two + /// operand indices that would swap value. Return true if the instruction + /// is not in a form which this routine understands. + virtual bool findCommutedOpIndices(MachineInstr *MI, unsigned &SrcOpIdx1, + unsigned &SrcOpIdx2) const = 0; + + /// isIdentical - Return true if two instructions are identical. This differs + /// from MachineInstr::isIdenticalTo() in that it does not require the + /// virtual destination registers to be the same. This is used by MachineLICM + /// and other MI passes to perform CSE. + virtual bool isIdentical(const MachineInstr *MI, + const MachineInstr *Other, + const MachineRegisterInfo *MRI) const = 0; + + /// AnalyzeBranch - Analyze the branching code at the end of MBB, returning + /// true if it cannot be understood (e.g. it's a switch dispatch or isn't + /// implemented for a target). Upon success, this returns false and returns + /// with the following information in various cases: + /// + /// 1. If this block ends with no branches (it just falls through to its succ) + /// just return false, leaving TBB/FBB null. + /// 2. If this block ends with only an unconditional branch, it sets TBB to be + /// the destination block. + /// 3. If this block ends with an conditional branch and it falls through to + /// a successor block, it sets TBB to be the branch destination block and + /// a list of operands that evaluate the condition. These + /// operands can be passed to other TargetInstrInfo methods to create new + /// branches. + /// 4. If this block ends with a conditional branch followed by an + /// unconditional branch, it returns the 'true' destination in TBB, the + /// 'false' destination in FBB, and a list of operands that evaluate the + /// condition. These operands can be passed to other TargetInstrInfo + /// methods to create new branches. + /// + /// Note that RemoveBranch and InsertBranch must be implemented to support + /// cases where this method returns success. + /// + /// If AllowModify is true, then this routine is allowed to modify the basic + /// block (e.g. delete instructions after the unconditional branch). + /// + virtual bool AnalyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, + MachineBasicBlock *&FBB, + SmallVectorImpl &Cond, + bool AllowModify = false) const { + return true; + } + + /// RemoveBranch - Remove the branching code at the end of the specific MBB. + /// This is only invoked in cases where AnalyzeBranch returns success. It + /// returns the number of instructions that were removed. + virtual unsigned RemoveBranch(MachineBasicBlock &MBB) const { + assert(0 && "Target didn't implement TargetInstrInfo::RemoveBranch!"); + return 0; + } + + /// InsertBranch - Insert branch code into the end of the specified + /// MachineBasicBlock. The operands to this method are the same as those + /// returned by AnalyzeBranch. This is only invoked in cases where + /// AnalyzeBranch returns success. It returns the number of instructions + /// inserted. + /// + /// It is also invoked by tail merging to add unconditional branches in + /// cases where AnalyzeBranch doesn't apply because there was no original + /// branch to analyze. At least this much must be implemented, else tail + /// merging needs to be disabled. + virtual unsigned InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, + MachineBasicBlock *FBB, + const SmallVectorImpl &Cond) const { + assert(0 && "Target didn't implement TargetInstrInfo::InsertBranch!"); + return 0; + } + + /// copyRegToReg - Emit instructions to copy between a pair of registers. It + /// returns false if the target does not how to copy between the specified + /// registers. + virtual bool copyRegToReg(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + unsigned DestReg, unsigned SrcReg, + const TargetRegisterClass *DestRC, + const TargetRegisterClass *SrcRC) const { + assert(0 && "Target didn't implement TargetInstrInfo::copyRegToReg!"); + return false; + } + + /// storeRegToStackSlot - Store the specified register of the given register + /// class to the specified stack frame index. The store instruction is to be + /// added to the given machine basic block before the specified machine + /// instruction. If isKill is true, the register operand is the last use and + /// must be marked kill. + virtual void storeRegToStackSlot(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + unsigned SrcReg, bool isKill, int FrameIndex, + const TargetRegisterClass *RC) const { + assert(0 && "Target didn't implement TargetInstrInfo::storeRegToStackSlot!"); + } + + /// loadRegFromStackSlot - Load the specified register of the given register + /// class from the specified stack frame index. The load instruction is to be + /// added to the given machine basic block before the specified machine + /// instruction. + virtual void loadRegFromStackSlot(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + unsigned DestReg, int FrameIndex, + const TargetRegisterClass *RC) const { + assert(0 && "Target didn't implement TargetInstrInfo::loadRegFromStackSlot!"); + } + + /// spillCalleeSavedRegisters - Issues instruction(s) to spill all callee + /// saved registers and returns true if it isn't possible / profitable to do + /// so by issuing a series of store instructions via + /// storeRegToStackSlot(). Returns false otherwise. + virtual bool spillCalleeSavedRegisters(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + const std::vector &CSI) const { + return false; + } + + /// restoreCalleeSavedRegisters - Issues instruction(s) to restore all callee + /// saved registers and returns true if it isn't possible / profitable to do + /// so by issuing a series of load instructions via loadRegToStackSlot(). + /// Returns false otherwise. + virtual bool restoreCalleeSavedRegisters(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + const std::vector &CSI) const { + return false; + } + + /// foldMemoryOperand - Attempt to fold a load or store of the specified stack + /// slot into the specified machine instruction for the specified operand(s). + /// If this is possible, a new instruction is returned with the specified + /// operand folded, otherwise NULL is returned. The client is responsible for + /// removing the old instruction and adding the new one in the instruction + /// stream. + MachineInstr* foldMemoryOperand(MachineFunction &MF, + MachineInstr* MI, + const SmallVectorImpl &Ops, + int FrameIndex) const; + + /// foldMemoryOperand - Same as the previous version except it allows folding + /// of any load and store from / to any address, not just from a specific + /// stack slot. + MachineInstr* foldMemoryOperand(MachineFunction &MF, + MachineInstr* MI, + const SmallVectorImpl &Ops, + MachineInstr* LoadMI) const; + +protected: + /// foldMemoryOperandImpl - Target-dependent implementation for + /// foldMemoryOperand. Target-independent code in foldMemoryOperand will + /// take care of adding a MachineMemOperand to the newly created instruction. + virtual MachineInstr* foldMemoryOperandImpl(MachineFunction &MF, + MachineInstr* MI, + const SmallVectorImpl &Ops, + int FrameIndex) const { + return 0; + } + + /// foldMemoryOperandImpl - Target-dependent implementation for + /// foldMemoryOperand. Target-independent code in foldMemoryOperand will + /// take care of adding a MachineMemOperand to the newly created instruction. + virtual MachineInstr* foldMemoryOperandImpl(MachineFunction &MF, + MachineInstr* MI, + const SmallVectorImpl &Ops, + MachineInstr* LoadMI) const { + return 0; + } + +public: + /// canFoldMemoryOperand - Returns true for the specified load / store if + /// folding is possible. + virtual + bool canFoldMemoryOperand(const MachineInstr *MI, + const SmallVectorImpl &Ops) const { + return false; + } + + /// unfoldMemoryOperand - Separate a single instruction which folded a load or + /// a store or a load and a store into two or more instruction. If this is + /// possible, returns true as well as the new instructions by reference. + virtual bool unfoldMemoryOperand(MachineFunction &MF, MachineInstr *MI, + unsigned Reg, bool UnfoldLoad, bool UnfoldStore, + SmallVectorImpl &NewMIs) const{ + return false; + } + + virtual bool unfoldMemoryOperand(SelectionDAG &DAG, SDNode *N, + SmallVectorImpl &NewNodes) const { + return false; + } + + /// getOpcodeAfterMemoryUnfold - Returns the opcode of the would be new + /// instruction after load / store are unfolded from an instruction of the + /// specified opcode. It returns zero if the specified unfolding is not + /// possible. If LoadRegIndex is non-null, it is filled in with the operand + /// index of the operand which will hold the register holding the loaded + /// value. + virtual unsigned getOpcodeAfterMemoryUnfold(unsigned Opc, + bool UnfoldLoad, bool UnfoldStore, + unsigned *LoadRegIndex = 0) const { + return 0; + } + + /// BlockHasNoFallThrough - Return true if the specified block does not + /// fall-through into its successor block. This is primarily used when a + /// branch is unanalyzable. It is useful for things like unconditional + /// indirect branches (jump tables). + virtual bool BlockHasNoFallThrough(const MachineBasicBlock &MBB) const { + return false; + } + + /// ReverseBranchCondition - Reverses the branch condition of the specified + /// condition list, returning false on success and true if it cannot be + /// reversed. + virtual + bool ReverseBranchCondition(SmallVectorImpl &Cond) const { + return true; + } + + /// insertNoop - Insert a noop into the instruction stream at the specified + /// point. + virtual void insertNoop(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI) const; + + /// isPredicated - Returns true if the instruction is already predicated. + /// + virtual bool isPredicated(const MachineInstr *MI) const { + return false; + } + + /// isUnpredicatedTerminator - Returns true if the instruction is a + /// terminator instruction that has not been predicated. + virtual bool isUnpredicatedTerminator(const MachineInstr *MI) const; + + /// PredicateInstruction - Convert the instruction into a predicated + /// instruction. It returns true if the operation was successful. + virtual + bool PredicateInstruction(MachineInstr *MI, + const SmallVectorImpl &Pred) const = 0; + + /// SubsumesPredicate - Returns true if the first specified predicate + /// subsumes the second, e.g. GE subsumes GT. + virtual + bool SubsumesPredicate(const SmallVectorImpl &Pred1, + const SmallVectorImpl &Pred2) const { + return false; + } + + /// DefinesPredicate - If the specified instruction defines any predicate + /// or condition code register(s) used for predication, returns true as well + /// as the definition predicate(s) by reference. + virtual bool DefinesPredicate(MachineInstr *MI, + std::vector &Pred) const { + return false; + } + + /// isPredicable - Return true if the specified instruction can be predicated. + /// By default, this returns true for every instruction with a + /// PredicateOperand. + virtual bool isPredicable(MachineInstr *MI) const { + return MI->getDesc().isPredicable(); + } + + /// isSafeToMoveRegClassDefs - Return true if it's safe to move a machine + /// instruction that defines the specified register class. + virtual bool isSafeToMoveRegClassDefs(const TargetRegisterClass *RC) const { + return true; + } + + /// GetInstSize - Returns the size of the specified Instruction. + /// + virtual unsigned GetInstSizeInBytes(const MachineInstr *MI) const { + assert(0 && "Target didn't implement TargetInstrInfo::GetInstSize!"); + return 0; + } + + /// GetFunctionSizeInBytes - Returns the size of the specified + /// MachineFunction. + /// + virtual unsigned GetFunctionSizeInBytes(const MachineFunction &MF) const = 0; + + /// Measure the specified inline asm to determine an approximation of its + /// length. + virtual unsigned getInlineAsmLength(const char *Str, + const MCAsmInfo &MAI) const; + + /// isProfitableToDuplicateIndirectBranch - Returns true if tail duplication + /// is especially profitable for indirect branches. + virtual bool isProfitableToDuplicateIndirectBranch() const { return false; } +}; + +/// TargetInstrInfoImpl - This is the default implementation of +/// TargetInstrInfo, which just provides a couple of default implementations +/// for various methods. This separated out because it is implemented in +/// libcodegen, not in libtarget. +class TargetInstrInfoImpl : public TargetInstrInfo { +protected: + TargetInstrInfoImpl(const TargetInstrDesc *desc, unsigned NumOpcodes) + : TargetInstrInfo(desc, NumOpcodes) {} +public: + virtual MachineInstr *commuteInstruction(MachineInstr *MI, + bool NewMI = false) const; + virtual bool findCommutedOpIndices(MachineInstr *MI, unsigned &SrcOpIdx1, + unsigned &SrcOpIdx2) const; + virtual bool PredicateInstruction(MachineInstr *MI, + const SmallVectorImpl &Pred) const; + virtual void reMaterialize(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + unsigned DestReg, unsigned SubReg, + const MachineInstr *Orig, + const TargetRegisterInfo *TRI) const; + virtual bool isIdentical(const MachineInstr *MI, + const MachineInstr *Other, + const MachineRegisterInfo *MRI) const; + + virtual unsigned GetFunctionSizeInBytes(const MachineFunction &MF) const; +}; + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Target/TargetInstrItineraries.h b/libclamav/c++/llvm/include/llvm/Target/TargetInstrItineraries.h new file mode 100644 index 000000000..420fa94ce --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Target/TargetInstrItineraries.h @@ -0,0 +1,169 @@ +//===-- llvm/Target/TargetInstrItineraries.h - Scheduling -------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file describes the structures used for instruction +// itineraries, stages, and operand reads/writes. This is used by +// schedulers to determine instruction stages and latencies. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TARGET_TARGETINSTRITINERARIES_H +#define LLVM_TARGET_TARGETINSTRITINERARIES_H + +#include + +namespace llvm { + +//===----------------------------------------------------------------------===// +/// Instruction stage - These values represent a non-pipelined step in +/// the execution of an instruction. Cycles represents the number of +/// discrete time slots needed to complete the stage. Units represent +/// the choice of functional units that can be used to complete the +/// stage. Eg. IntUnit1, IntUnit2. NextCycles indicates how many +/// cycles should elapse from the start of this stage to the start of +/// the next stage in the itinerary. A value of -1 indicates that the +/// next stage should start immediately after the current one. +/// For example: +/// +/// { 1, x, -1 } +/// indicates that the stage occupies FU x for 1 cycle and that +/// the next stage starts immediately after this one. +/// +/// { 2, x|y, 1 } +/// indicates that the stage occupies either FU x or FU y for 2 +/// consecuative cycles and that the next stage starts one cycle +/// after this stage starts. That is, the stage requirements +/// overlap in time. +/// +/// { 1, x, 0 } +/// indicates that the stage occupies FU x for 1 cycle and that +/// the next stage starts in this same cycle. This can be used to +/// indicate that the instruction requires multiple stages at the +/// same time. +/// +struct InstrStage { + unsigned Cycles_; ///< Length of stage in machine cycles + unsigned Units_; ///< Choice of functional units + int NextCycles_; ///< Number of machine cycles to next stage + + /// getCycles - returns the number of cycles the stage is occupied + unsigned getCycles() const { + return Cycles_; + } + + /// getUnits - returns the choice of FUs + unsigned getUnits() const { + return Units_; + } + + /// getNextCycles - returns the number of cycles from the start of + /// this stage to the start of the next stage in the itinerary + unsigned getNextCycles() const { + return (NextCycles_ >= 0) ? (unsigned)NextCycles_ : Cycles_; + } +}; + + +//===----------------------------------------------------------------------===// +/// Instruction itinerary - An itinerary represents the scheduling +/// information for an instruction. This includes a set of stages +/// occupies by the instruction, and the pipeline cycle in which +/// operands are read and written. +/// +struct InstrItinerary { + unsigned FirstStage; ///< Index of first stage in itinerary + unsigned LastStage; ///< Index of last + 1 stage in itinerary + unsigned FirstOperandCycle; ///< Index of first operand rd/wr + unsigned LastOperandCycle; ///< Index of last + 1 operand rd/wr +}; + + +//===----------------------------------------------------------------------===// +/// Instruction itinerary Data - Itinerary data supplied by a subtarget to be +/// used by a target. +/// +struct InstrItineraryData { + const InstrStage *Stages; ///< Array of stages selected + const unsigned *OperandCycles; ///< Array of operand cycles selected + const InstrItinerary *Itineratries; ///< Array of itineraries selected + + /// Ctors. + /// + InstrItineraryData() : Stages(0), OperandCycles(0), Itineratries(0) {} + InstrItineraryData(const InstrStage *S, const unsigned *OS, + const InstrItinerary *I) + : Stages(S), OperandCycles(OS), Itineratries(I) {} + + /// isEmpty - Returns true if there are no itineraries. + /// + bool isEmpty() const { return Itineratries == 0; } + + /// isEndMarker - Returns true if the index is for the end marker + /// itinerary. + /// + bool isEndMarker(unsigned ItinClassIndx) const { + return ((Itineratries[ItinClassIndx].FirstStage == ~0U) && + (Itineratries[ItinClassIndx].LastStage == ~0U)); + } + + /// beginStage - Return the first stage of the itinerary. + /// + const InstrStage *beginStage(unsigned ItinClassIndx) const { + unsigned StageIdx = Itineratries[ItinClassIndx].FirstStage; + return Stages + StageIdx; + } + + /// endStage - Return the last+1 stage of the itinerary. + /// + const InstrStage *endStage(unsigned ItinClassIndx) const { + unsigned StageIdx = Itineratries[ItinClassIndx].LastStage; + return Stages + StageIdx; + } + + /// getStageLatency - Return the total stage latency of the given + /// class. The latency is the maximum completion time for any stage + /// in the itinerary. + /// + unsigned getStageLatency(unsigned ItinClassIndx) const { + // If the target doesn't provide itinerary information, use a + // simple non-zero default value for all instructions. + if (isEmpty()) + return 1; + + // Calculate the maximum completion time for any stage. + unsigned Latency = 0, StartCycle = 0; + for (const InstrStage *IS = beginStage(ItinClassIndx), + *E = endStage(ItinClassIndx); IS != E; ++IS) { + Latency = std::max(Latency, StartCycle + IS->getCycles()); + StartCycle += IS->getNextCycles(); + } + + return Latency; + } + + /// getOperandCycle - Return the cycle for the given class and + /// operand. Return -1 if no cycle is specified for the operand. + /// + int getOperandCycle(unsigned ItinClassIndx, unsigned OperandIdx) const { + if (isEmpty()) + return -1; + + unsigned FirstIdx = Itineratries[ItinClassIndx].FirstOperandCycle; + unsigned LastIdx = Itineratries[ItinClassIndx].LastOperandCycle; + if ((FirstIdx + OperandIdx) >= LastIdx) + return -1; + + return (int)OperandCycles[FirstIdx + OperandIdx]; + } +}; + + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Target/TargetIntrinsicInfo.h b/libclamav/c++/llvm/include/llvm/Target/TargetIntrinsicInfo.h new file mode 100644 index 000000000..ad8ac925e --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Target/TargetIntrinsicInfo.h @@ -0,0 +1,64 @@ +//===-- llvm/Target/TargetIntrinsicInfo.h - Instruction 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 describes the target intrinsic instructions to the code generator. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TARGET_TARGETINTRINSICINFO_H +#define LLVM_TARGET_TARGETINTRINSICINFO_H + +#include + +namespace llvm { + +class Function; +class Module; +class Type; + +//--------------------------------------------------------------------------- +/// +/// TargetIntrinsicInfo - Interface to description of machine instruction set +/// +class TargetIntrinsicInfo { + TargetIntrinsicInfo(const TargetIntrinsicInfo &); // DO NOT IMPLEMENT + void operator=(const TargetIntrinsicInfo &); // DO NOT IMPLEMENT +public: + TargetIntrinsicInfo(); + virtual ~TargetIntrinsicInfo(); + + /// Return the name of a target intrinsic, e.g. "llvm.bfin.ssync". + /// The Tys and numTys parameters are for intrinsics with overloaded types + /// (e.g., those using iAny or fAny). For a declaration for an overloaded + /// intrinsic, Tys should point to an array of numTys pointers to Type, + /// and must provide exactly one type for each overloaded type in the + /// intrinsic. + virtual std::string getName(unsigned IID, const Type **Tys = 0, + unsigned numTys = 0) const = 0; + + /// Look up target intrinsic by name. Return intrinsic ID or 0 for unknown + /// names. + virtual unsigned lookupName(const char *Name, unsigned Len) const =0; + + /// Return the target intrinsic ID of a function, or 0. + virtual unsigned getIntrinsicID(Function *F) const; + + /// Returns true if the intrinsic can be overloaded. + virtual bool isOverloaded(unsigned IID) const = 0; + + /// Create or insert an LLVM Function declaration for an intrinsic, + /// and return it. The Tys and numTys are for intrinsics with overloaded + /// types. See above for more information. + virtual Function *getDeclaration(Module *M, unsigned ID, const Type **Tys = 0, + unsigned numTys = 0) const = 0; +}; + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Target/TargetJITInfo.h b/libclamav/c++/llvm/include/llvm/Target/TargetJITInfo.h new file mode 100644 index 000000000..7208a8dc4 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Target/TargetJITInfo.h @@ -0,0 +1,142 @@ +//===- Target/TargetJITInfo.h - Target Information for JIT ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file exposes an abstract interface used by the Just-In-Time code +// generator to perform target-specific activities, such as emitting stubs. If +// a TargetMachine supports JIT code generation, it should provide one of these +// objects through the getJITInfo() method. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TARGET_TARGETJITINFO_H +#define LLVM_TARGET_TARGETJITINFO_H + +#include +#include "llvm/Support/ErrorHandling.h" +#include "llvm/System/DataTypes.h" + +namespace llvm { + class Function; + class GlobalValue; + class JITCodeEmitter; + class MachineRelocation; + + /// TargetJITInfo - Target specific information required by the Just-In-Time + /// code generator. + class TargetJITInfo { + public: + virtual ~TargetJITInfo() {} + + /// replaceMachineCodeForFunction - Make it so that calling the function + /// whose machine code is at OLD turns into a call to NEW, perhaps by + /// overwriting OLD with a branch to NEW. This is used for self-modifying + /// code. + /// + virtual void replaceMachineCodeForFunction(void *Old, void *New) = 0; + + /// emitGlobalValueIndirectSym - Use the specified JITCodeEmitter object + /// to emit an indirect symbol which contains the address of the specified + /// ptr. + virtual void *emitGlobalValueIndirectSym(const GlobalValue* GV, void *ptr, + JITCodeEmitter &JCE) { + assert(0 && "This target doesn't implement emitGlobalValueIndirectSym!"); + return 0; + } + + /// Records the required size and alignment for a call stub in bytes. + struct StubLayout { + size_t Size; + size_t Alignment; + }; + /// Returns the maximum size and alignment for a call stub on this target. + virtual StubLayout getStubLayout() { + llvm_unreachable("This target doesn't implement getStubLayout!"); + StubLayout Result = {0, 0}; + return Result; + } + + /// emitFunctionStub - Use the specified JITCodeEmitter object to emit a + /// small native function that simply calls the function at the specified + /// address. The JITCodeEmitter must already have storage allocated for the + /// stub. Return the address of the resultant function, which may have been + /// aligned from the address the JCE was set up to emit at. + virtual void *emitFunctionStub(const Function* F, void *Target, + JITCodeEmitter &JCE) { + assert(0 && "This target doesn't implement emitFunctionStub!"); + return 0; + } + + /// getPICJumpTableEntry - Returns the value of the jumptable entry for the + /// specific basic block. + virtual uintptr_t getPICJumpTableEntry(uintptr_t BB, uintptr_t JTBase) { + assert(0 && "This target doesn't implement getPICJumpTableEntry!"); + return 0; + } + + /// LazyResolverFn - This typedef is used to represent the function that + /// unresolved call points should invoke. This is a target specific + /// function that knows how to walk the stack and find out which stub the + /// call is coming from. + typedef void (*LazyResolverFn)(); + + /// JITCompilerFn - This typedef is used to represent the JIT function that + /// lazily compiles the function corresponding to a stub. The JIT keeps + /// track of the mapping between stubs and LLVM Functions, the target + /// provides the ability to figure out the address of a stub that is called + /// by the LazyResolverFn. + typedef void* (*JITCompilerFn)(void *); + + /// getLazyResolverFunction - This method is used to initialize the JIT, + /// giving the target the function that should be used to compile a + /// function, and giving the JIT the target function used to do the lazy + /// resolving. + virtual LazyResolverFn getLazyResolverFunction(JITCompilerFn) { + assert(0 && "Not implemented for this target!"); + return 0; + } + + /// relocate - Before the JIT can run a block of code that has been emitted, + /// it must rewrite the code to contain the actual addresses of any + /// referenced global symbols. + virtual void relocate(void *Function, MachineRelocation *MR, + unsigned NumRelocs, unsigned char* GOTBase) { + assert(NumRelocs == 0 && "This target does not have relocations!"); + } + + + /// allocateThreadLocalMemory - Each target has its own way of + /// handling thread local variables. This method returns a value only + /// meaningful to the target. + virtual char* allocateThreadLocalMemory(size_t size) { + assert(0 && "This target does not implement thread local storage!"); + return 0; + } + + /// needsGOT - Allows a target to specify that it would like the + /// JIT to manage a GOT for it. + bool needsGOT() const { return useGOT; } + + /// hasCustomConstantPool - Allows a target to specify that constant + /// pool address resolution is handled by the target. + virtual bool hasCustomConstantPool() const { return false; } + + /// hasCustomJumpTables - Allows a target to specify that jumptables + /// are emitted by the target. + virtual bool hasCustomJumpTables() const { return false; } + + /// allocateSeparateGVMemory - If true, globals should be placed in + /// separately allocated heap memory rather than in the same + /// code memory allocated by JITCodeEmitter. + virtual bool allocateSeparateGVMemory() const { return false; } + protected: + bool useGOT; + }; +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Target/TargetLowering.h b/libclamav/c++/llvm/include/llvm/Target/TargetLowering.h new file mode 100644 index 000000000..ca511027d --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Target/TargetLowering.h @@ -0,0 +1,1783 @@ +//===-- llvm/Target/TargetLowering.h - Target Lowering 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 describes how to lower LLVM code to machine code. This has two +// main components: +// +// 1. Which ValueTypes are natively supported by the target. +// 2. Which operations are supported for supported ValueTypes. +// 3. Cost thresholds for alternative implementations of certain operations. +// +// In addition it has a few other components, like information about FP +// immediates. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TARGET_TARGETLOWERING_H +#define LLVM_TARGET_TARGETLOWERING_H + +#include "llvm/CallingConv.h" +#include "llvm/InlineAsm.h" +#include "llvm/CodeGen/SelectionDAGNodes.h" +#include "llvm/CodeGen/RuntimeLibcalls.h" +#include "llvm/ADT/APFloat.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallSet.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/Support/DebugLoc.h" +#include "llvm/Target/TargetMachine.h" +#include +#include +#include + +namespace llvm { + class AllocaInst; + class CallInst; + class Function; + class FastISel; + class MachineBasicBlock; + class MachineFunction; + class MachineFrameInfo; + class MachineInstr; + class MachineModuleInfo; + class DwarfWriter; + class SDNode; + class SDValue; + class SelectionDAG; + class TargetData; + class TargetMachine; + class TargetRegisterClass; + class TargetSubtarget; + class TargetLoweringObjectFile; + class Value; + + // FIXME: should this be here? + namespace TLSModel { + enum Model { + GeneralDynamic, + LocalDynamic, + InitialExec, + LocalExec + }; + } + TLSModel::Model getTLSModel(const GlobalValue *GV, Reloc::Model reloc); + + +//===----------------------------------------------------------------------===// +/// TargetLowering - This class defines information used to lower LLVM code to +/// legal SelectionDAG operators that the target instruction selector can accept +/// natively. +/// +/// This class also defines callbacks that targets must implement to lower +/// target-specific constructs to SelectionDAG operators. +/// +class TargetLowering { + TargetLowering(const TargetLowering&); // DO NOT IMPLEMENT + void operator=(const TargetLowering&); // DO NOT IMPLEMENT +public: + /// LegalizeAction - This enum indicates whether operations are valid for a + /// target, and if not, what action should be used to make them valid. + enum LegalizeAction { + Legal, // The target natively supports this operation. + Promote, // This operation should be executed in a larger type. + Expand, // Try to expand this to other ops, otherwise use a libcall. + Custom // Use the LowerOperation hook to implement custom lowering. + }; + + enum BooleanContent { // How the target represents true/false values. + UndefinedBooleanContent, // Only bit 0 counts, the rest can hold garbage. + ZeroOrOneBooleanContent, // All bits zero except for bit 0. + ZeroOrNegativeOneBooleanContent // All bits equal to bit 0. + }; + + enum SchedPreference { + SchedulingForLatency, // Scheduling for shortest total latency. + SchedulingForRegPressure // Scheduling for lowest register pressure. + }; + + /// NOTE: The constructor takes ownership of TLOF. + explicit TargetLowering(TargetMachine &TM, TargetLoweringObjectFile *TLOF); + virtual ~TargetLowering(); + + TargetMachine &getTargetMachine() const { return TM; } + const TargetData *getTargetData() const { return TD; } + TargetLoweringObjectFile &getObjFileLowering() const { return TLOF; } + + bool isBigEndian() const { return !IsLittleEndian; } + bool isLittleEndian() const { return IsLittleEndian; } + MVT getPointerTy() const { return PointerTy; } + MVT getShiftAmountTy() const { return ShiftAmountTy; } + + /// usesGlobalOffsetTable - Return true if this target uses a GOT for PIC + /// codegen. + bool usesGlobalOffsetTable() const { return UsesGlobalOffsetTable; } + + /// isSelectExpensive - Return true if the select operation is expensive for + /// this target. + bool isSelectExpensive() const { return SelectIsExpensive; } + + /// isIntDivCheap() - Return true if integer divide is usually cheaper than + /// a sequence of several shifts, adds, and multiplies for this target. + bool isIntDivCheap() const { return IntDivIsCheap; } + + /// isPow2DivCheap() - Return true if pow2 div is cheaper than a chain of + /// srl/add/sra. + bool isPow2DivCheap() const { return Pow2DivIsCheap; } + + /// getSetCCResultType - Return the ValueType of the result of SETCC + /// operations. Also used to obtain the target's preferred type for + /// the condition operand of SELECT and BRCOND nodes. In the case of + /// BRCOND the argument passed is MVT::Other since there are no other + /// operands to get a type hint from. + virtual + MVT::SimpleValueType getSetCCResultType(EVT VT) const; + + /// getBooleanContents - For targets without i1 registers, this gives the + /// nature of the high-bits of boolean values held in types wider than i1. + /// "Boolean values" are special true/false values produced by nodes like + /// SETCC and consumed (as the condition) by nodes like SELECT and BRCOND. + /// Not to be confused with general values promoted from i1. + BooleanContent getBooleanContents() const { return BooleanContents;} + + /// getSchedulingPreference - Return target scheduling preference. + SchedPreference getSchedulingPreference() const { + return SchedPreferenceInfo; + } + + /// getRegClassFor - Return the register class that should be used for the + /// specified value type. This may only be called on legal types. + TargetRegisterClass *getRegClassFor(EVT VT) const { + assert(VT.isSimple() && "getRegClassFor called on illegal type!"); + TargetRegisterClass *RC = RegClassForVT[VT.getSimpleVT().SimpleTy]; + assert(RC && "This value type is not natively supported!"); + return RC; + } + + /// isTypeLegal - Return true if the target has native support for the + /// specified value type. This means that it has a register that directly + /// holds it without promotions or expansions. + bool isTypeLegal(EVT VT) const { + assert(!VT.isSimple() || + (unsigned)VT.getSimpleVT().SimpleTy < array_lengthof(RegClassForVT)); + return VT.isSimple() && RegClassForVT[VT.getSimpleVT().SimpleTy] != 0; + } + + class ValueTypeActionImpl { + /// ValueTypeActions - This is a bitvector that contains two bits for each + /// value type, where the two bits correspond to the LegalizeAction enum. + /// This can be queried with "getTypeAction(VT)". + /// dimension by (MVT::MAX_ALLOWED_VALUETYPE/32) * 2 + uint32_t ValueTypeActions[(MVT::MAX_ALLOWED_VALUETYPE/32)*2]; + public: + ValueTypeActionImpl() { + ValueTypeActions[0] = ValueTypeActions[1] = 0; + ValueTypeActions[2] = ValueTypeActions[3] = 0; + } + ValueTypeActionImpl(const ValueTypeActionImpl &RHS) { + ValueTypeActions[0] = RHS.ValueTypeActions[0]; + ValueTypeActions[1] = RHS.ValueTypeActions[1]; + ValueTypeActions[2] = RHS.ValueTypeActions[2]; + ValueTypeActions[3] = RHS.ValueTypeActions[3]; + } + + LegalizeAction getTypeAction(LLVMContext &Context, EVT VT) const { + if (VT.isExtended()) { + if (VT.isVector()) { + return VT.isPow2VectorType() ? Expand : Promote; + } + if (VT.isInteger()) + // First promote to a power-of-two size, then expand if necessary. + return VT == VT.getRoundIntegerType(Context) ? Expand : Promote; + assert(0 && "Unsupported extended type!"); + return Legal; + } + unsigned I = VT.getSimpleVT().SimpleTy; + assert(I<4*array_lengthof(ValueTypeActions)*sizeof(ValueTypeActions[0])); + return (LegalizeAction)((ValueTypeActions[I>>4] >> ((2*I) & 31)) & 3); + } + void setTypeAction(EVT VT, LegalizeAction Action) { + unsigned I = VT.getSimpleVT().SimpleTy; + assert(I<4*array_lengthof(ValueTypeActions)*sizeof(ValueTypeActions[0])); + ValueTypeActions[I>>4] |= Action << ((I*2) & 31); + } + }; + + const ValueTypeActionImpl &getValueTypeActions() const { + return ValueTypeActions; + } + + /// getTypeAction - Return how we should legalize values of this type, either + /// it is already legal (return 'Legal') or we need to promote it to a larger + /// type (return 'Promote'), or we need to expand it into multiple registers + /// of smaller integer type (return 'Expand'). 'Custom' is not an option. + LegalizeAction getTypeAction(LLVMContext &Context, EVT VT) const { + return ValueTypeActions.getTypeAction(Context, VT); + } + + /// getTypeToTransformTo - For types supported by the target, this is an + /// identity function. For types that must be promoted to larger types, this + /// returns the larger type to promote to. For integer types that are larger + /// than the largest integer register, this contains one step in the expansion + /// to get to the smaller register. For illegal floating point types, this + /// returns the integer type to transform to. + EVT getTypeToTransformTo(LLVMContext &Context, EVT VT) const { + if (VT.isSimple()) { + assert((unsigned)VT.getSimpleVT().SimpleTy < + array_lengthof(TransformToType)); + EVT NVT = TransformToType[VT.getSimpleVT().SimpleTy]; + assert(getTypeAction(Context, NVT) != Promote && + "Promote may not follow Expand or Promote"); + return NVT; + } + + if (VT.isVector()) { + EVT NVT = VT.getPow2VectorType(Context); + if (NVT == VT) { + // Vector length is a power of 2 - split to half the size. + unsigned NumElts = VT.getVectorNumElements(); + EVT EltVT = VT.getVectorElementType(); + return (NumElts == 1) ? + EltVT : EVT::getVectorVT(Context, EltVT, NumElts / 2); + } + // Promote to a power of two size, avoiding multi-step promotion. + return getTypeAction(Context, NVT) == Promote ? + getTypeToTransformTo(Context, NVT) : NVT; + } else if (VT.isInteger()) { + EVT NVT = VT.getRoundIntegerType(Context); + if (NVT == VT) + // Size is a power of two - expand to half the size. + return EVT::getIntegerVT(Context, VT.getSizeInBits() / 2); + else + // Promote to a power of two size, avoiding multi-step promotion. + return getTypeAction(Context, NVT) == Promote ? + getTypeToTransformTo(Context, NVT) : NVT; + } + assert(0 && "Unsupported extended type!"); + return MVT(MVT::Other); // Not reached + } + + /// getTypeToExpandTo - For types supported by the target, this is an + /// identity function. For types that must be expanded (i.e. integer types + /// that are larger than the largest integer register or illegal floating + /// point types), this returns the largest legal type it will be expanded to. + EVT getTypeToExpandTo(LLVMContext &Context, EVT VT) const { + assert(!VT.isVector()); + while (true) { + switch (getTypeAction(Context, VT)) { + case Legal: + return VT; + case Expand: + VT = getTypeToTransformTo(Context, VT); + break; + default: + assert(false && "Type is not legal nor is it to be expanded!"); + return VT; + } + } + return VT; + } + + /// getVectorTypeBreakdown - Vector types are broken down into some number of + /// legal first class types. For example, EVT::v8f32 maps to 2 EVT::v4f32 + /// with Altivec or SSE1, or 8 promoted EVT::f64 values with the X86 FP stack. + /// Similarly, EVT::v2i64 turns into 4 EVT::i32 values with both PPC and X86. + /// + /// This method returns the number of registers needed, and the VT for each + /// register. It also returns the VT and quantity of the intermediate values + /// before they are promoted/expanded. + /// + unsigned getVectorTypeBreakdown(LLVMContext &Context, EVT VT, + EVT &IntermediateVT, + unsigned &NumIntermediates, + EVT &RegisterVT) const; + + /// getTgtMemIntrinsic: Given an intrinsic, checks if on the target the + /// intrinsic will need to map to a MemIntrinsicNode (touches memory). If + /// this is the case, it returns true and store the intrinsic + /// information into the IntrinsicInfo that was passed to the function. + typedef struct IntrinsicInfo { + unsigned opc; // target opcode + EVT memVT; // memory VT + const Value* ptrVal; // value representing memory location + int offset; // offset off of ptrVal + unsigned align; // alignment + bool vol; // is volatile? + bool readMem; // reads memory? + bool writeMem; // writes memory? + } IntrinisicInfo; + + virtual bool getTgtMemIntrinsic(IntrinsicInfo& Info, + CallInst &I, unsigned Intrinsic) { + return false; + } + + /// getWidenVectorType: given a vector type, returns the type to widen to + /// (e.g., v7i8 to v8i8). If the vector type is legal, it returns itself. + /// If there is no vector type that we want to widen to, returns MVT::Other + /// When and were to widen is target dependent based on the cost of + /// scalarizing vs using the wider vector type. + virtual EVT getWidenVectorType(EVT VT) const; + + /// isFPImmLegal - Returns true if the target can instruction select the + /// specified FP immediate natively. If false, the legalizer will materialize + /// the FP immediate as a load from a constant pool. + virtual bool isFPImmLegal(const APFloat &Imm, EVT VT) const { + return false; + } + + /// isShuffleMaskLegal - Targets can use this to indicate that they only + /// support *some* VECTOR_SHUFFLE operations, those with specific masks. + /// By default, if a target supports the VECTOR_SHUFFLE node, all mask values + /// are assumed to be legal. + virtual bool isShuffleMaskLegal(const SmallVectorImpl &Mask, + EVT VT) const { + return true; + } + + /// isVectorClearMaskLegal - Similar to isShuffleMaskLegal. This is + /// used by Targets can use this to indicate if there is a suitable + /// VECTOR_SHUFFLE that can be used to replace a VAND with a constant + /// pool entry. + virtual bool isVectorClearMaskLegal(const SmallVectorImpl &Mask, + EVT VT) const { + return false; + } + + /// getOperationAction - Return how this operation should be treated: either + /// it is legal, needs to be promoted to a larger size, needs to be + /// expanded to some other code sequence, or the target has a custom expander + /// for it. + LegalizeAction getOperationAction(unsigned Op, EVT VT) const { + if (VT.isExtended()) return Expand; + assert(Op < array_lengthof(OpActions[0]) && + (unsigned)VT.getSimpleVT().SimpleTy < sizeof(OpActions[0][0])*8 && + "Table isn't big enough!"); + unsigned I = (unsigned) VT.getSimpleVT().SimpleTy; + unsigned J = I & 31; + I = I >> 5; + return (LegalizeAction)((OpActions[I][Op] >> (J*2) ) & 3); + } + + /// isOperationLegalOrCustom - Return true if the specified operation is + /// legal on this target or can be made legal with custom lowering. This + /// is used to help guide high-level lowering decisions. + bool isOperationLegalOrCustom(unsigned Op, EVT VT) const { + return (VT == MVT::Other || isTypeLegal(VT)) && + (getOperationAction(Op, VT) == Legal || + getOperationAction(Op, VT) == Custom); + } + + /// isOperationLegal - Return true if the specified operation is legal on this + /// target. + bool isOperationLegal(unsigned Op, EVT VT) const { + return (VT == MVT::Other || isTypeLegal(VT)) && + getOperationAction(Op, VT) == Legal; + } + + /// getLoadExtAction - Return how this load with extension should be treated: + /// either it is legal, needs to be promoted to a larger size, needs to be + /// expanded to some other code sequence, or the target has a custom expander + /// for it. + LegalizeAction getLoadExtAction(unsigned LType, EVT VT) const { + assert(LType < array_lengthof(LoadExtActions) && + (unsigned)VT.getSimpleVT().SimpleTy < sizeof(LoadExtActions[0])*4 && + "Table isn't big enough!"); + return (LegalizeAction)((LoadExtActions[LType] >> + (2*VT.getSimpleVT().SimpleTy)) & 3); + } + + /// isLoadExtLegal - Return true if the specified load with extension is legal + /// on this target. + bool isLoadExtLegal(unsigned LType, EVT VT) const { + return VT.isSimple() && + (getLoadExtAction(LType, VT) == Legal || + getLoadExtAction(LType, VT) == Custom); + } + + /// getTruncStoreAction - Return how this store with truncation should be + /// treated: either it is legal, needs to be promoted to a larger size, needs + /// to be expanded to some other code sequence, or the target has a custom + /// expander for it. + LegalizeAction getTruncStoreAction(EVT ValVT, + EVT MemVT) const { + assert((unsigned)ValVT.getSimpleVT().SimpleTy < + array_lengthof(TruncStoreActions) && + (unsigned)MemVT.getSimpleVT().SimpleTy < + sizeof(TruncStoreActions[0])*4 && + "Table isn't big enough!"); + return (LegalizeAction)((TruncStoreActions[ValVT.getSimpleVT().SimpleTy] >> + (2*MemVT.getSimpleVT().SimpleTy)) & 3); + } + + /// isTruncStoreLegal - Return true if the specified store with truncation is + /// legal on this target. + bool isTruncStoreLegal(EVT ValVT, EVT MemVT) const { + return isTypeLegal(ValVT) && MemVT.isSimple() && + (getTruncStoreAction(ValVT, MemVT) == Legal || + getTruncStoreAction(ValVT, MemVT) == Custom); + } + + /// getIndexedLoadAction - Return how the indexed load should be treated: + /// either it is legal, needs to be promoted to a larger size, needs to be + /// expanded to some other code sequence, or the target has a custom expander + /// for it. + LegalizeAction + getIndexedLoadAction(unsigned IdxMode, EVT VT) const { + assert( IdxMode < array_lengthof(IndexedModeActions[0][0]) && + ((unsigned)VT.getSimpleVT().SimpleTy) < MVT::LAST_VALUETYPE && + "Table isn't big enough!"); + return (LegalizeAction)((IndexedModeActions[ + (unsigned)VT.getSimpleVT().SimpleTy][0][IdxMode])); + } + + /// isIndexedLoadLegal - Return true if the specified indexed load is legal + /// on this target. + bool isIndexedLoadLegal(unsigned IdxMode, EVT VT) const { + return VT.isSimple() && + (getIndexedLoadAction(IdxMode, VT) == Legal || + getIndexedLoadAction(IdxMode, VT) == Custom); + } + + /// getIndexedStoreAction - Return how the indexed store should be treated: + /// either it is legal, needs to be promoted to a larger size, needs to be + /// expanded to some other code sequence, or the target has a custom expander + /// for it. + LegalizeAction + getIndexedStoreAction(unsigned IdxMode, EVT VT) const { + assert(IdxMode < array_lengthof(IndexedModeActions[0][1]) && + (unsigned)VT.getSimpleVT().SimpleTy < MVT::LAST_VALUETYPE && + "Table isn't big enough!"); + return (LegalizeAction)((IndexedModeActions[ + (unsigned)VT.getSimpleVT().SimpleTy][1][IdxMode])); + } + + /// isIndexedStoreLegal - Return true if the specified indexed load is legal + /// on this target. + bool isIndexedStoreLegal(unsigned IdxMode, EVT VT) const { + return VT.isSimple() && + (getIndexedStoreAction(IdxMode, VT) == Legal || + getIndexedStoreAction(IdxMode, VT) == Custom); + } + + /// getConvertAction - Return how the conversion should be treated: + /// either it is legal, needs to be promoted to a larger size, needs to be + /// expanded to some other code sequence, or the target has a custom expander + /// for it. + LegalizeAction + getConvertAction(EVT FromVT, EVT ToVT) const { + assert((unsigned)FromVT.getSimpleVT().SimpleTy < + array_lengthof(ConvertActions) && + (unsigned)ToVT.getSimpleVT().SimpleTy < + sizeof(ConvertActions[0])*4 && + "Table isn't big enough!"); + return (LegalizeAction)((ConvertActions[FromVT.getSimpleVT().SimpleTy] >> + (2*ToVT.getSimpleVT().SimpleTy)) & 3); + } + + /// isConvertLegal - Return true if the specified conversion is legal + /// on this target. + bool isConvertLegal(EVT FromVT, EVT ToVT) const { + return isTypeLegal(FromVT) && isTypeLegal(ToVT) && + (getConvertAction(FromVT, ToVT) == Legal || + getConvertAction(FromVT, ToVT) == Custom); + } + + /// getCondCodeAction - Return how the condition code should be treated: + /// either it is legal, needs to be expanded to some other code sequence, + /// or the target has a custom expander for it. + LegalizeAction + getCondCodeAction(ISD::CondCode CC, EVT VT) const { + assert((unsigned)CC < array_lengthof(CondCodeActions) && + (unsigned)VT.getSimpleVT().SimpleTy < sizeof(CondCodeActions[0])*4 && + "Table isn't big enough!"); + LegalizeAction Action = (LegalizeAction) + ((CondCodeActions[CC] >> (2*VT.getSimpleVT().SimpleTy)) & 3); + assert(Action != Promote && "Can't promote condition code!"); + return Action; + } + + /// isCondCodeLegal - Return true if the specified condition code is legal + /// on this target. + bool isCondCodeLegal(ISD::CondCode CC, EVT VT) const { + return getCondCodeAction(CC, VT) == Legal || + getCondCodeAction(CC, VT) == Custom; + } + + + /// getTypeToPromoteTo - If the action for this operation is to promote, this + /// method returns the ValueType to promote to. + EVT getTypeToPromoteTo(unsigned Op, EVT VT) const { + assert(getOperationAction(Op, VT) == Promote && + "This operation isn't promoted!"); + + // See if this has an explicit type specified. + std::map, + MVT::SimpleValueType>::const_iterator PTTI = + PromoteToType.find(std::make_pair(Op, VT.getSimpleVT().SimpleTy)); + if (PTTI != PromoteToType.end()) return PTTI->second; + + assert((VT.isInteger() || VT.isFloatingPoint()) && + "Cannot autopromote this type, add it with AddPromotedToType."); + + EVT NVT = VT; + do { + NVT = (MVT::SimpleValueType)(NVT.getSimpleVT().SimpleTy+1); + assert(NVT.isInteger() == VT.isInteger() && NVT != MVT::isVoid && + "Didn't find type to promote to!"); + } while (!isTypeLegal(NVT) || + getOperationAction(Op, NVT) == Promote); + return NVT; + } + + /// getValueType - Return the EVT corresponding to this LLVM type. + /// This is fixed by the LLVM operations except for the pointer size. If + /// AllowUnknown is true, this will return MVT::Other for types with no EVT + /// counterpart (e.g. structs), otherwise it will assert. + EVT getValueType(const Type *Ty, bool AllowUnknown = false) const { + EVT VT = EVT::getEVT(Ty, AllowUnknown); + return VT == MVT:: iPTR ? PointerTy : VT; + } + + /// getByValTypeAlignment - Return the desired alignment for ByVal aggregate + /// function arguments in the caller parameter area. This is the actual + /// alignment, not its logarithm. + virtual unsigned getByValTypeAlignment(const Type *Ty) const; + + /// getRegisterType - Return the type of registers that this ValueType will + /// eventually require. + EVT getRegisterType(MVT VT) const { + assert((unsigned)VT.SimpleTy < array_lengthof(RegisterTypeForVT)); + return RegisterTypeForVT[VT.SimpleTy]; + } + + /// getRegisterType - Return the type of registers that this ValueType will + /// eventually require. + EVT getRegisterType(LLVMContext &Context, EVT VT) const { + if (VT.isSimple()) { + assert((unsigned)VT.getSimpleVT().SimpleTy < + array_lengthof(RegisterTypeForVT)); + return RegisterTypeForVT[VT.getSimpleVT().SimpleTy]; + } + if (VT.isVector()) { + EVT VT1, RegisterVT; + unsigned NumIntermediates; + (void)getVectorTypeBreakdown(Context, VT, VT1, + NumIntermediates, RegisterVT); + return RegisterVT; + } + if (VT.isInteger()) { + return getRegisterType(Context, getTypeToTransformTo(Context, VT)); + } + assert(0 && "Unsupported extended type!"); + return EVT(MVT::Other); // Not reached + } + + /// getNumRegisters - Return the number of registers that this ValueType will + /// eventually require. This is one for any types promoted to live in larger + /// registers, but may be more than one for types (like i64) that are split + /// into pieces. For types like i140, which are first promoted then expanded, + /// it is the number of registers needed to hold all the bits of the original + /// type. For an i140 on a 32 bit machine this means 5 registers. + unsigned getNumRegisters(LLVMContext &Context, EVT VT) const { + if (VT.isSimple()) { + assert((unsigned)VT.getSimpleVT().SimpleTy < + array_lengthof(NumRegistersForVT)); + return NumRegistersForVT[VT.getSimpleVT().SimpleTy]; + } + if (VT.isVector()) { + EVT VT1, VT2; + unsigned NumIntermediates; + return getVectorTypeBreakdown(Context, VT, VT1, NumIntermediates, VT2); + } + if (VT.isInteger()) { + unsigned BitWidth = VT.getSizeInBits(); + unsigned RegWidth = getRegisterType(Context, VT).getSizeInBits(); + return (BitWidth + RegWidth - 1) / RegWidth; + } + assert(0 && "Unsupported extended type!"); + return 0; // Not reached + } + + /// ShouldShrinkFPConstant - If true, then instruction selection should + /// seek to shrink the FP constant of the specified type to a smaller type + /// in order to save space and / or reduce runtime. + virtual bool ShouldShrinkFPConstant(EVT VT) const { return true; } + + /// hasTargetDAGCombine - If true, the target has custom DAG combine + /// transformations that it can perform for the specified node. + bool hasTargetDAGCombine(ISD::NodeType NT) const { + assert(unsigned(NT >> 3) < array_lengthof(TargetDAGCombineArray)); + return TargetDAGCombineArray[NT >> 3] & (1 << (NT&7)); + } + + /// This function returns the maximum number of store operations permitted + /// to replace a call to llvm.memset. The value is set by the target at the + /// performance threshold for such a replacement. + /// @brief Get maximum # of store operations permitted for llvm.memset + unsigned getMaxStoresPerMemset() const { return maxStoresPerMemset; } + + /// This function returns the maximum number of store operations permitted + /// to replace a call to llvm.memcpy. The value is set by the target at the + /// performance threshold for such a replacement. + /// @brief Get maximum # of store operations permitted for llvm.memcpy + unsigned getMaxStoresPerMemcpy() const { return maxStoresPerMemcpy; } + + /// This function returns the maximum number of store operations permitted + /// to replace a call to llvm.memmove. The value is set by the target at the + /// performance threshold for such a replacement. + /// @brief Get maximum # of store operations permitted for llvm.memmove + unsigned getMaxStoresPerMemmove() const { return maxStoresPerMemmove; } + + /// This function returns true if the target allows unaligned memory accesses. + /// of the specified type. This is used, for example, in situations where an + /// array copy/move/set is converted to a sequence of store operations. It's + /// use helps to ensure that such replacements don't generate code that causes + /// an alignment error (trap) on the target machine. + /// @brief Determine if the target supports unaligned memory accesses. + virtual bool allowsUnalignedMemoryAccesses(EVT VT) const { + return false; + } + + /// This function returns true if the target would benefit from code placement + /// optimization. + /// @brief Determine if the target should perform code placement optimization. + bool shouldOptimizeCodePlacement() const { + return benefitFromCodePlacementOpt; + } + + /// getOptimalMemOpType - Returns the target specific optimal type for load + /// and store operations as a result of memset, memcpy, and memmove lowering. + /// It returns EVT::iAny if SelectionDAG should be responsible for + /// determining it. + virtual EVT getOptimalMemOpType(uint64_t Size, unsigned Align, + bool isSrcConst, bool isSrcStr, + SelectionDAG &DAG) const { + return MVT::iAny; + } + + /// usesUnderscoreSetJmp - Determine if we should use _setjmp or setjmp + /// to implement llvm.setjmp. + bool usesUnderscoreSetJmp() const { + return UseUnderscoreSetJmp; + } + + /// usesUnderscoreLongJmp - Determine if we should use _longjmp or longjmp + /// to implement llvm.longjmp. + bool usesUnderscoreLongJmp() const { + return UseUnderscoreLongJmp; + } + + /// getStackPointerRegisterToSaveRestore - If a physical register, this + /// specifies the register that llvm.savestack/llvm.restorestack should save + /// and restore. + unsigned getStackPointerRegisterToSaveRestore() const { + return StackPointerRegisterToSaveRestore; + } + + /// getExceptionAddressRegister - If a physical register, this returns + /// the register that receives the exception address on entry to a landing + /// pad. + unsigned getExceptionAddressRegister() const { + return ExceptionPointerRegister; + } + + /// getExceptionSelectorRegister - If a physical register, this returns + /// the register that receives the exception typeid on entry to a landing + /// pad. + unsigned getExceptionSelectorRegister() const { + return ExceptionSelectorRegister; + } + + /// getJumpBufSize - returns the target's jmp_buf size in bytes (if never + /// set, the default is 200) + unsigned getJumpBufSize() const { + return JumpBufSize; + } + + /// getJumpBufAlignment - returns the target's jmp_buf alignment in bytes + /// (if never set, the default is 0) + unsigned getJumpBufAlignment() const { + return JumpBufAlignment; + } + + /// getIfCvtBlockLimit - returns the target specific if-conversion block size + /// limit. Any block whose size is greater should not be predicated. + unsigned getIfCvtBlockSizeLimit() const { + return IfCvtBlockSizeLimit; + } + + /// getIfCvtDupBlockLimit - returns the target specific size limit for a + /// block to be considered for duplication. Any block whose size is greater + /// should not be duplicated to facilitate its predication. + unsigned getIfCvtDupBlockSizeLimit() const { + return IfCvtDupBlockSizeLimit; + } + + /// getPrefLoopAlignment - return the preferred loop alignment. + /// + unsigned getPrefLoopAlignment() const { + return PrefLoopAlignment; + } + + /// getPreIndexedAddressParts - returns true by value, base pointer and + /// offset pointer and addressing mode by reference if the node's address + /// can be legally represented as pre-indexed load / store address. + virtual bool getPreIndexedAddressParts(SDNode *N, SDValue &Base, + SDValue &Offset, + ISD::MemIndexedMode &AM, + SelectionDAG &DAG) const { + return false; + } + + /// getPostIndexedAddressParts - returns true by value, base pointer and + /// offset pointer and addressing mode by reference if this node can be + /// combined with a load / store to form a post-indexed load / store. + virtual bool getPostIndexedAddressParts(SDNode *N, SDNode *Op, + SDValue &Base, SDValue &Offset, + ISD::MemIndexedMode &AM, + SelectionDAG &DAG) const { + return false; + } + + /// getPICJumpTableRelocaBase - Returns relocation base for the given PIC + /// jumptable. + virtual SDValue getPICJumpTableRelocBase(SDValue Table, + SelectionDAG &DAG) const; + + /// isOffsetFoldingLegal - Return true if folding a constant offset + /// with the given GlobalAddress is legal. It is frequently not legal in + /// PIC relocation models. + virtual bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const; + + /// getFunctionAlignment - Return the Log2 alignment of this function. + virtual unsigned getFunctionAlignment(const Function *) const = 0; + + //===--------------------------------------------------------------------===// + // TargetLowering Optimization Methods + // + + /// TargetLoweringOpt - A convenience struct that encapsulates a DAG, and two + /// SDValues for returning information from TargetLowering to its clients + /// that want to combine + struct TargetLoweringOpt { + SelectionDAG &DAG; + SDValue Old; + SDValue New; + + explicit TargetLoweringOpt(SelectionDAG &InDAG) : DAG(InDAG) {} + + bool CombineTo(SDValue O, SDValue N) { + Old = O; + New = N; + return true; + } + + /// ShrinkDemandedConstant - Check to see if the specified operand of the + /// specified instruction is a constant integer. If so, check to see if + /// there are any bits set in the constant that are not demanded. If so, + /// shrink the constant and return true. + bool ShrinkDemandedConstant(SDValue Op, const APInt &Demanded); + + /// ShrinkDemandedOp - Convert x+y to (VT)((SmallVT)x+(SmallVT)y) if the + /// casts are free. This uses isZExtFree and ZERO_EXTEND for the widening + /// cast, but it could be generalized for targets with other types of + /// implicit widening casts. + bool ShrinkDemandedOp(SDValue Op, unsigned BitWidth, const APInt &Demanded, + DebugLoc dl); + }; + + /// SimplifyDemandedBits - Look at Op. At this point, we know that only the + /// DemandedMask bits of the result of Op are ever used downstream. If we can + /// use this information to simplify Op, create a new simplified DAG node and + /// return true, returning the original and new nodes in Old and New. + /// Otherwise, analyze the expression and return a mask of KnownOne and + /// KnownZero bits for the expression (used to simplify the caller). + /// The KnownZero/One bits may only be accurate for those bits in the + /// DemandedMask. + bool SimplifyDemandedBits(SDValue Op, const APInt &DemandedMask, + APInt &KnownZero, APInt &KnownOne, + TargetLoweringOpt &TLO, unsigned Depth = 0) const; + + /// computeMaskedBitsForTargetNode - Determine which of the bits specified in + /// Mask are known to be either zero or one and return them in the + /// KnownZero/KnownOne bitsets. + virtual void computeMaskedBitsForTargetNode(const SDValue Op, + const APInt &Mask, + APInt &KnownZero, + APInt &KnownOne, + const SelectionDAG &DAG, + unsigned Depth = 0) const; + + /// ComputeNumSignBitsForTargetNode - This method can be implemented by + /// targets that want to expose additional information about sign bits to the + /// DAG Combiner. + virtual unsigned ComputeNumSignBitsForTargetNode(SDValue Op, + unsigned Depth = 0) const; + + struct DAGCombinerInfo { + void *DC; // The DAG Combiner object. + bool BeforeLegalize; + bool BeforeLegalizeOps; + bool CalledByLegalizer; + public: + SelectionDAG &DAG; + + DAGCombinerInfo(SelectionDAG &dag, bool bl, bool blo, bool cl, void *dc) + : DC(dc), BeforeLegalize(bl), BeforeLegalizeOps(blo), + CalledByLegalizer(cl), DAG(dag) {} + + bool isBeforeLegalize() const { return BeforeLegalize; } + bool isBeforeLegalizeOps() const { return BeforeLegalizeOps; } + bool isCalledByLegalizer() const { return CalledByLegalizer; } + + void AddToWorklist(SDNode *N); + SDValue CombineTo(SDNode *N, const std::vector &To, + bool AddTo = true); + SDValue CombineTo(SDNode *N, SDValue Res, bool AddTo = true); + SDValue CombineTo(SDNode *N, SDValue Res0, SDValue Res1, bool AddTo = true); + + void CommitTargetLoweringOpt(const TargetLoweringOpt &TLO); + }; + + /// SimplifySetCC - Try to simplify a setcc built with the specified operands + /// and cc. If it is unable to simplify it, return a null SDValue. + SDValue SimplifySetCC(EVT VT, SDValue N0, SDValue N1, + ISD::CondCode Cond, bool foldBooleans, + DAGCombinerInfo &DCI, DebugLoc dl) const; + + /// isGAPlusOffset - Returns true (and the GlobalValue and the offset) if the + /// node is a GlobalAddress + offset. + virtual bool + isGAPlusOffset(SDNode *N, GlobalValue* &GA, int64_t &Offset) const; + + /// isConsecutiveLoad - Return true if LD is loading 'Bytes' bytes from a + /// location that is 'Dist' units away from the location that the 'Base' load + /// is loading from. + bool isConsecutiveLoad(LoadSDNode *LD, LoadSDNode *Base, unsigned Bytes, + int Dist, const MachineFrameInfo *MFI) const; + + /// PerformDAGCombine - This method will be invoked for all target nodes and + /// for any target-independent nodes that the target has registered with + /// invoke it for. + /// + /// The semantics are as follows: + /// Return Value: + /// SDValue.Val == 0 - No change was made + /// SDValue.Val == N - N was replaced, is dead, and is already handled. + /// otherwise - N should be replaced by the returned Operand. + /// + /// In addition, methods provided by DAGCombinerInfo may be used to perform + /// more complex transformations. + /// + virtual SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const; + + //===--------------------------------------------------------------------===// + // TargetLowering Configuration Methods - These methods should be invoked by + // the derived class constructor to configure this object for the target. + // + +protected: + /// setUsesGlobalOffsetTable - Specify that this target does or doesn't use a + /// GOT for PC-relative code. + void setUsesGlobalOffsetTable(bool V) { UsesGlobalOffsetTable = V; } + + /// setShiftAmountType - Describe the type that should be used for shift + /// amounts. This type defaults to the pointer type. + void setShiftAmountType(MVT VT) { ShiftAmountTy = VT; } + + /// setBooleanContents - Specify how the target extends the result of a + /// boolean value from i1 to a wider type. See getBooleanContents. + void setBooleanContents(BooleanContent Ty) { BooleanContents = Ty; } + + /// setSchedulingPreference - Specify the target scheduling preference. + void setSchedulingPreference(SchedPreference Pref) { + SchedPreferenceInfo = Pref; + } + + /// setUseUnderscoreSetJmp - Indicate whether this target prefers to + /// use _setjmp to implement llvm.setjmp or the non _ version. + /// Defaults to false. + void setUseUnderscoreSetJmp(bool Val) { + UseUnderscoreSetJmp = Val; + } + + /// setUseUnderscoreLongJmp - Indicate whether this target prefers to + /// use _longjmp to implement llvm.longjmp or the non _ version. + /// Defaults to false. + void setUseUnderscoreLongJmp(bool Val) { + UseUnderscoreLongJmp = Val; + } + + /// setStackPointerRegisterToSaveRestore - If set to a physical register, this + /// specifies the register that llvm.savestack/llvm.restorestack should save + /// and restore. + void setStackPointerRegisterToSaveRestore(unsigned R) { + StackPointerRegisterToSaveRestore = R; + } + + /// setExceptionPointerRegister - If set to a physical register, this sets + /// the register that receives the exception address on entry to a landing + /// pad. + void setExceptionPointerRegister(unsigned R) { + ExceptionPointerRegister = R; + } + + /// setExceptionSelectorRegister - If set to a physical register, this sets + /// the register that receives the exception typeid on entry to a landing + /// pad. + void setExceptionSelectorRegister(unsigned R) { + ExceptionSelectorRegister = R; + } + + /// SelectIsExpensive - Tells the code generator not to expand operations + /// into sequences that use the select operations if possible. + void setSelectIsExpensive() { SelectIsExpensive = true; } + + /// setIntDivIsCheap - Tells the code generator that integer divide is + /// expensive, and if possible, should be replaced by an alternate sequence + /// of instructions not containing an integer divide. + void setIntDivIsCheap(bool isCheap = true) { IntDivIsCheap = isCheap; } + + /// setPow2DivIsCheap - Tells the code generator that it shouldn't generate + /// srl/add/sra for a signed divide by power of two, and let the target handle + /// it. + void setPow2DivIsCheap(bool isCheap = true) { Pow2DivIsCheap = isCheap; } + + /// addRegisterClass - Add the specified register class as an available + /// regclass for the specified value type. This indicates the selector can + /// handle values of that class natively. + void addRegisterClass(EVT VT, TargetRegisterClass *RC) { + assert((unsigned)VT.getSimpleVT().SimpleTy < array_lengthof(RegClassForVT)); + AvailableRegClasses.push_back(std::make_pair(VT, RC)); + RegClassForVT[VT.getSimpleVT().SimpleTy] = RC; + } + + /// computeRegisterProperties - Once all of the register classes are added, + /// this allows us to compute derived properties we expose. + void computeRegisterProperties(); + + /// setOperationAction - Indicate that the specified operation does not work + /// with the specified type and indicate what to do about it. + void setOperationAction(unsigned Op, MVT VT, + LegalizeAction Action) { + unsigned I = (unsigned)VT.SimpleTy; + unsigned J = I & 31; + I = I >> 5; + OpActions[I][Op] &= ~(uint64_t(3UL) << (J*2)); + OpActions[I][Op] |= (uint64_t)Action << (J*2); + } + + /// setLoadExtAction - Indicate that the specified load with extension does + /// not work with the with specified type and indicate what to do about it. + void setLoadExtAction(unsigned ExtType, MVT VT, + LegalizeAction Action) { + assert((unsigned)VT.SimpleTy < MVT::LAST_VALUETYPE && + ExtType < array_lengthof(LoadExtActions) && + "Table isn't big enough!"); + LoadExtActions[ExtType] &= ~(uint64_t(3UL) << VT.SimpleTy*2); + LoadExtActions[ExtType] |= (uint64_t)Action << VT.SimpleTy*2; + } + + /// setTruncStoreAction - Indicate that the specified truncating store does + /// not work with the with specified type and indicate what to do about it. + void setTruncStoreAction(MVT ValVT, MVT MemVT, + LegalizeAction Action) { + assert((unsigned)ValVT.SimpleTy < array_lengthof(TruncStoreActions) && + (unsigned)MemVT.SimpleTy < MVT::LAST_VALUETYPE && + "Table isn't big enough!"); + TruncStoreActions[ValVT.SimpleTy] &= ~(uint64_t(3UL) << MemVT.SimpleTy*2); + TruncStoreActions[ValVT.SimpleTy] |= (uint64_t)Action << MemVT.SimpleTy*2; + } + + /// setIndexedLoadAction - Indicate that the specified indexed load does or + /// does not work with the with specified type and indicate what to do abort + /// it. NOTE: All indexed mode loads are initialized to Expand in + /// TargetLowering.cpp + void setIndexedLoadAction(unsigned IdxMode, MVT VT, + LegalizeAction Action) { + assert((unsigned)VT.SimpleTy < MVT::LAST_VALUETYPE && + IdxMode < array_lengthof(IndexedModeActions[0][0]) && + "Table isn't big enough!"); + IndexedModeActions[(unsigned)VT.SimpleTy][0][IdxMode] = (uint8_t)Action; + } + + /// setIndexedStoreAction - Indicate that the specified indexed store does or + /// does not work with the with specified type and indicate what to do about + /// it. NOTE: All indexed mode stores are initialized to Expand in + /// TargetLowering.cpp + void setIndexedStoreAction(unsigned IdxMode, MVT VT, + LegalizeAction Action) { + assert((unsigned)VT.SimpleTy < MVT::LAST_VALUETYPE && + IdxMode < array_lengthof(IndexedModeActions[0][1] ) && + "Table isn't big enough!"); + IndexedModeActions[(unsigned)VT.SimpleTy][1][IdxMode] = (uint8_t)Action; + } + + /// setConvertAction - Indicate that the specified conversion does or does + /// not work with the with specified type and indicate what to do about it. + void setConvertAction(MVT FromVT, MVT ToVT, + LegalizeAction Action) { + assert((unsigned)FromVT.SimpleTy < array_lengthof(ConvertActions) && + (unsigned)ToVT.SimpleTy < MVT::LAST_VALUETYPE && + "Table isn't big enough!"); + ConvertActions[FromVT.SimpleTy] &= ~(uint64_t(3UL) << ToVT.SimpleTy*2); + ConvertActions[FromVT.SimpleTy] |= (uint64_t)Action << ToVT.SimpleTy*2; + } + + /// setCondCodeAction - Indicate that the specified condition code is or isn't + /// supported on the target and indicate what to do about it. + void setCondCodeAction(ISD::CondCode CC, MVT VT, + LegalizeAction Action) { + assert((unsigned)VT.SimpleTy < MVT::LAST_VALUETYPE && + (unsigned)CC < array_lengthof(CondCodeActions) && + "Table isn't big enough!"); + CondCodeActions[(unsigned)CC] &= ~(uint64_t(3UL) << VT.SimpleTy*2); + CondCodeActions[(unsigned)CC] |= (uint64_t)Action << VT.SimpleTy*2; + } + + /// AddPromotedToType - If Opc/OrigVT is specified as being promoted, the + /// promotion code defaults to trying a larger integer/fp until it can find + /// one that works. If that default is insufficient, this method can be used + /// by the target to override the default. + void AddPromotedToType(unsigned Opc, MVT OrigVT, MVT DestVT) { + PromoteToType[std::make_pair(Opc, OrigVT.SimpleTy)] = DestVT.SimpleTy; + } + + /// setTargetDAGCombine - Targets should invoke this method for each target + /// independent node that they want to provide a custom DAG combiner for by + /// implementing the PerformDAGCombine virtual method. + void setTargetDAGCombine(ISD::NodeType NT) { + assert(unsigned(NT >> 3) < array_lengthof(TargetDAGCombineArray)); + TargetDAGCombineArray[NT >> 3] |= 1 << (NT&7); + } + + /// setJumpBufSize - Set the target's required jmp_buf buffer size (in + /// bytes); default is 200 + void setJumpBufSize(unsigned Size) { + JumpBufSize = Size; + } + + /// setJumpBufAlignment - Set the target's required jmp_buf buffer + /// alignment (in bytes); default is 0 + void setJumpBufAlignment(unsigned Align) { + JumpBufAlignment = Align; + } + + /// setIfCvtBlockSizeLimit - Set the target's if-conversion block size + /// limit (in number of instructions); default is 2. + void setIfCvtBlockSizeLimit(unsigned Limit) { + IfCvtBlockSizeLimit = Limit; + } + + /// setIfCvtDupBlockSizeLimit - Set the target's block size limit (in number + /// of instructions) to be considered for code duplication during + /// if-conversion; default is 2. + void setIfCvtDupBlockSizeLimit(unsigned Limit) { + IfCvtDupBlockSizeLimit = Limit; + } + + /// setPrefLoopAlignment - Set the target's preferred loop alignment. Default + /// alignment is zero, it means the target does not care about loop alignment. + void setPrefLoopAlignment(unsigned Align) { + PrefLoopAlignment = Align; + } + +public: + + virtual const TargetSubtarget *getSubtarget() { + assert(0 && "Not Implemented"); + return NULL; // this is here to silence compiler errors + } + + //===--------------------------------------------------------------------===// + // Lowering methods - These methods must be implemented by targets so that + // the SelectionDAGLowering code knows how to lower these. + // + + /// LowerFormalArguments - This hook must be implemented to lower the + /// incoming (formal) arguments, described by the Ins array, into the + /// specified DAG. The implementation should fill in the InVals array + /// with legal-type argument values, and return the resulting token + /// chain value. + /// + virtual SDValue + LowerFormalArguments(SDValue Chain, + CallingConv::ID CallConv, bool isVarArg, + const SmallVectorImpl &Ins, + DebugLoc dl, SelectionDAG &DAG, + SmallVectorImpl &InVals) { + assert(0 && "Not Implemented"); + return SDValue(); // this is here to silence compiler errors + } + + /// LowerCallTo - This function lowers an abstract call to a function into an + /// actual call. This returns a pair of operands. The first element is the + /// return value for the function (if RetTy is not VoidTy). The second + /// element is the outgoing token chain. It calls LowerCall to do the actual + /// lowering. + struct ArgListEntry { + SDValue Node; + const Type* Ty; + bool isSExt : 1; + bool isZExt : 1; + bool isInReg : 1; + bool isSRet : 1; + bool isNest : 1; + bool isByVal : 1; + uint16_t Alignment; + + ArgListEntry() : isSExt(false), isZExt(false), isInReg(false), + isSRet(false), isNest(false), isByVal(false), Alignment(0) { } + }; + typedef std::vector ArgListTy; + std::pair + LowerCallTo(SDValue Chain, const Type *RetTy, bool RetSExt, bool RetZExt, + bool isVarArg, bool isInreg, unsigned NumFixedArgs, + CallingConv::ID CallConv, bool isTailCall, + bool isReturnValueUsed, SDValue Callee, ArgListTy &Args, + SelectionDAG &DAG, DebugLoc dl); + + /// LowerCall - This hook must be implemented to lower calls into the + /// the specified DAG. The outgoing arguments to the call are described + /// by the Outs array, and the values to be returned by the call are + /// described by the Ins array. The implementation should fill in the + /// InVals array with legal-type return values from the call, and return + /// the resulting token chain value. + /// + /// The isTailCall flag here is normative. If it is true, the + /// implementation must emit a tail call. The + /// IsEligibleForTailCallOptimization hook should be used to catch + /// cases that cannot be handled. + /// + virtual SDValue + LowerCall(SDValue Chain, SDValue Callee, + CallingConv::ID CallConv, bool isVarArg, bool isTailCall, + const SmallVectorImpl &Outs, + const SmallVectorImpl &Ins, + DebugLoc dl, SelectionDAG &DAG, + SmallVectorImpl &InVals) { + assert(0 && "Not Implemented"); + return SDValue(); // this is here to silence compiler errors + } + + /// CanLowerReturn - This hook should be implemented to check whether the + /// return values described by the Outs array can fit into the return + /// registers. If false is returned, an sret-demotion is performed. + /// + virtual bool CanLowerReturn(CallingConv::ID CallConv, bool isVarArg, + const SmallVectorImpl &OutTys, + const SmallVectorImpl &ArgsFlags, + SelectionDAG &DAG) + { + // Return true by default to get preexisting behavior. + return true; + } + /// LowerReturn - This hook must be implemented to lower outgoing + /// return values, described by the Outs array, into the specified + /// DAG. The implementation should return the resulting token chain + /// value. + /// + virtual SDValue + LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool isVarArg, + const SmallVectorImpl &Outs, + DebugLoc dl, SelectionDAG &DAG) { + assert(0 && "Not Implemented"); + return SDValue(); // this is here to silence compiler errors + } + + /// EmitTargetCodeForMemcpy - Emit target-specific code that performs a + /// memcpy. This can be used by targets to provide code sequences for cases + /// that don't fit the target's parameters for simple loads/stores and can be + /// more efficient than using a library call. This function can return a null + /// SDValue if the target declines to use custom code and a different + /// lowering strategy should be used. + /// + /// If AlwaysInline is true, the size is constant and the target should not + /// emit any calls and is strongly encouraged to attempt to emit inline code + /// even if it is beyond the usual threshold because this intrinsic is being + /// expanded in a place where calls are not feasible (e.g. within the prologue + /// for another call). If the target chooses to decline an AlwaysInline + /// request here, legalize will resort to using simple loads and stores. + virtual SDValue + EmitTargetCodeForMemcpy(SelectionDAG &DAG, DebugLoc dl, + SDValue Chain, + SDValue Op1, SDValue Op2, + SDValue Op3, unsigned Align, + bool AlwaysInline, + const Value *DstSV, uint64_t DstOff, + const Value *SrcSV, uint64_t SrcOff) { + return SDValue(); + } + + /// EmitTargetCodeForMemmove - Emit target-specific code that performs a + /// memmove. This can be used by targets to provide code sequences for cases + /// that don't fit the target's parameters for simple loads/stores and can be + /// more efficient than using a library call. This function can return a null + /// SDValue if the target declines to use custom code and a different + /// lowering strategy should be used. + virtual SDValue + EmitTargetCodeForMemmove(SelectionDAG &DAG, DebugLoc dl, + SDValue Chain, + SDValue Op1, SDValue Op2, + SDValue Op3, unsigned Align, + const Value *DstSV, uint64_t DstOff, + const Value *SrcSV, uint64_t SrcOff) { + return SDValue(); + } + + /// EmitTargetCodeForMemset - Emit target-specific code that performs a + /// memset. This can be used by targets to provide code sequences for cases + /// that don't fit the target's parameters for simple stores and can be more + /// efficient than using a library call. This function can return a null + /// SDValue if the target declines to use custom code and a different + /// lowering strategy should be used. + virtual SDValue + EmitTargetCodeForMemset(SelectionDAG &DAG, DebugLoc dl, + SDValue Chain, + SDValue Op1, SDValue Op2, + SDValue Op3, unsigned Align, + const Value *DstSV, uint64_t DstOff) { + return SDValue(); + } + + /// LowerOperationWrapper - This callback is invoked by the type legalizer + /// to legalize nodes with an illegal operand type but legal result types. + /// It replaces the LowerOperation callback in the type Legalizer. + /// The reason we can not do away with LowerOperation entirely is that + /// LegalizeDAG isn't yet ready to use this callback. + /// TODO: Consider merging with ReplaceNodeResults. + + /// The target places new result values for the node in Results (their number + /// and types must exactly match those of the original return values of + /// the node), or leaves Results empty, which indicates that the node is not + /// to be custom lowered after all. + /// The default implementation calls LowerOperation. + virtual void LowerOperationWrapper(SDNode *N, + SmallVectorImpl &Results, + SelectionDAG &DAG); + + /// LowerOperation - This callback is invoked for operations that are + /// unsupported by the target, which are registered to use 'custom' lowering, + /// and whose defined values are all legal. + /// If the target has no operations that require custom lowering, it need not + /// implement this. The default implementation of this aborts. + virtual SDValue LowerOperation(SDValue Op, SelectionDAG &DAG); + + /// ReplaceNodeResults - This callback is invoked when a node result type is + /// illegal for the target, and the operation was registered to use 'custom' + /// lowering for that result type. The target places new result values for + /// the node in Results (their number and types must exactly match those of + /// the original return values of the node), or leaves Results empty, which + /// indicates that the node is not to be custom lowered after all. + /// + /// If the target has no operations that require custom lowering, it need not + /// implement this. The default implementation aborts. + virtual void ReplaceNodeResults(SDNode *N, SmallVectorImpl &Results, + SelectionDAG &DAG) { + assert(0 && "ReplaceNodeResults not implemented for this target!"); + } + + /// IsEligibleForTailCallOptimization - Check whether the call is eligible for + /// tail call optimization. Targets which want to do tail call optimization + /// should override this function. + virtual bool + IsEligibleForTailCallOptimization(SDValue Callee, + CallingConv::ID CalleeCC, + bool isVarArg, + const SmallVectorImpl &Ins, + SelectionDAG& DAG) const { + // Conservative default: no calls are eligible. + return false; + } + + /// GetPossiblePreceedingTailCall - Get preceeding TailCallNodeOpCode node if + /// it exists. Skip a possible ISD::TokenFactor. + static SDValue GetPossiblePreceedingTailCall(SDValue Chain, + unsigned TailCallNodeOpCode) { + if (Chain.getOpcode() == TailCallNodeOpCode) { + return Chain; + } else if (Chain.getOpcode() == ISD::TokenFactor) { + if (Chain.getNumOperands() && + Chain.getOperand(0).getOpcode() == TailCallNodeOpCode) + return Chain.getOperand(0); + } + return Chain; + } + + /// getTargetNodeName() - This method returns the name of a target specific + /// DAG node. + virtual const char *getTargetNodeName(unsigned Opcode) const; + + /// createFastISel - This method returns a target specific FastISel object, + /// or null if the target does not support "fast" ISel. + virtual FastISel * + createFastISel(MachineFunction &, + MachineModuleInfo *, DwarfWriter *, + DenseMap &, + DenseMap &, + DenseMap & +#ifndef NDEBUG + , SmallSet &CatchInfoLost +#endif + ) { + return 0; + } + + //===--------------------------------------------------------------------===// + // Inline Asm Support hooks + // + + /// ExpandInlineAsm - This hook allows the target to expand an inline asm + /// call to be explicit llvm code if it wants to. This is useful for + /// turning simple inline asms into LLVM intrinsics, which gives the + /// compiler more information about the behavior of the code. + virtual bool ExpandInlineAsm(CallInst *CI) const { + return false; + } + + enum ConstraintType { + C_Register, // Constraint represents specific register(s). + C_RegisterClass, // Constraint represents any of register(s) in class. + C_Memory, // Memory constraint. + C_Other, // Something else. + C_Unknown // Unsupported constraint. + }; + + /// AsmOperandInfo - This contains information for each constraint that we are + /// lowering. + struct AsmOperandInfo : public InlineAsm::ConstraintInfo { + /// ConstraintCode - This contains the actual string for the code, like "m". + /// TargetLowering picks the 'best' code from ConstraintInfo::Codes that + /// most closely matches the operand. + std::string ConstraintCode; + + /// ConstraintType - Information about the constraint code, e.g. Register, + /// RegisterClass, Memory, Other, Unknown. + TargetLowering::ConstraintType ConstraintType; + + /// CallOperandval - If this is the result output operand or a + /// clobber, this is null, otherwise it is the incoming operand to the + /// CallInst. This gets modified as the asm is processed. + Value *CallOperandVal; + + /// ConstraintVT - The ValueType for the operand value. + EVT ConstraintVT; + + /// isMatchingInputConstraint - Return true of this is an input operand that + /// is a matching constraint like "4". + bool isMatchingInputConstraint() const; + + /// getMatchedOperand - If this is an input matching constraint, this method + /// returns the output operand it matches. + unsigned getMatchedOperand() const; + + AsmOperandInfo(const InlineAsm::ConstraintInfo &info) + : InlineAsm::ConstraintInfo(info), + ConstraintType(TargetLowering::C_Unknown), + CallOperandVal(0), ConstraintVT(MVT::Other) { + } + }; + + /// ComputeConstraintToUse - Determines the constraint code and constraint + /// type to use for the specific AsmOperandInfo, setting + /// OpInfo.ConstraintCode and OpInfo.ConstraintType. If the actual operand + /// being passed in is available, it can be passed in as Op, otherwise an + /// empty SDValue can be passed. If hasMemory is true it means one of the asm + /// constraint of the inline asm instruction being processed is 'm'. + virtual void ComputeConstraintToUse(AsmOperandInfo &OpInfo, + SDValue Op, + bool hasMemory, + SelectionDAG *DAG = 0) const; + + /// getConstraintType - Given a constraint, return the type of constraint it + /// is for this target. + virtual ConstraintType getConstraintType(const std::string &Constraint) const; + + /// getRegClassForInlineAsmConstraint - Given a constraint letter (e.g. "r"), + /// return a list of registers that can be used to satisfy the constraint. + /// This should only be used for C_RegisterClass constraints. + virtual std::vector + getRegClassForInlineAsmConstraint(const std::string &Constraint, + EVT VT) const; + + /// getRegForInlineAsmConstraint - Given a physical register constraint (e.g. + /// {edx}), return the register number and the register class for the + /// register. + /// + /// Given a register class constraint, like 'r', if this corresponds directly + /// to an LLVM register class, return a register of 0 and the register class + /// pointer. + /// + /// This should only be used for C_Register constraints. On error, + /// this returns a register number of 0 and a null register class pointer.. + virtual std::pair + getRegForInlineAsmConstraint(const std::string &Constraint, + EVT VT) const; + + /// LowerXConstraint - try to replace an X constraint, which matches anything, + /// with another that has more specific requirements based on the type of the + /// corresponding operand. This returns null if there is no replacement to + /// make. + virtual const char *LowerXConstraint(EVT ConstraintVT) const; + + /// LowerAsmOperandForConstraint - Lower the specified operand into the Ops + /// vector. If it is invalid, don't add anything to Ops. If hasMemory is true + /// it means one of the asm constraint of the inline asm instruction being + /// processed is 'm'. + virtual void LowerAsmOperandForConstraint(SDValue Op, char ConstraintLetter, + bool hasMemory, + std::vector &Ops, + SelectionDAG &DAG) const; + + //===--------------------------------------------------------------------===// + // Instruction Emitting Hooks + // + + // EmitInstrWithCustomInserter - This method should be implemented by targets + // that mark instructions with the 'usesCustomInserter' flag. These + // instructions are special in various ways, which require special support to + // insert. The specified MachineInstr is created but not inserted into any + // basic blocks, and this method is called to expand it into a sequence of + // instructions, potentially also creating new basic blocks and control flow. + // When new basic blocks are inserted and the edges from MBB to its successors + // are modified, the method should insert pairs of into the + // DenseMap. + virtual MachineBasicBlock *EmitInstrWithCustomInserter(MachineInstr *MI, + MachineBasicBlock *MBB, + DenseMap *EM) const; + + //===--------------------------------------------------------------------===// + // Addressing mode description hooks (used by LSR etc). + // + + /// AddrMode - This represents an addressing mode of: + /// BaseGV + BaseOffs + BaseReg + Scale*ScaleReg + /// If BaseGV is null, there is no BaseGV. + /// If BaseOffs is zero, there is no base offset. + /// If HasBaseReg is false, there is no base register. + /// If Scale is zero, there is no ScaleReg. Scale of 1 indicates a reg with + /// no scale. + /// + struct AddrMode { + GlobalValue *BaseGV; + int64_t BaseOffs; + bool HasBaseReg; + int64_t Scale; + AddrMode() : BaseGV(0), BaseOffs(0), HasBaseReg(false), Scale(0) {} + }; + + /// isLegalAddressingMode - Return true if the addressing mode represented by + /// AM is legal for this target, for a load/store of the specified type. + /// The type may be VoidTy, in which case only return true if the addressing + /// mode is legal for a load/store of any legal type. + /// TODO: Handle pre/postinc as well. + virtual bool isLegalAddressingMode(const AddrMode &AM, const Type *Ty) const; + + /// isTruncateFree - Return true if it's free to truncate a value of + /// type Ty1 to type Ty2. e.g. On x86 it's free to truncate a i32 value in + /// register EAX to i16 by referencing its sub-register AX. + virtual bool isTruncateFree(const Type *Ty1, const Type *Ty2) const { + return false; + } + + virtual bool isTruncateFree(EVT VT1, EVT VT2) const { + return false; + } + + /// isZExtFree - Return true if any actual instruction that defines a + /// value of type Ty1 implicit zero-extends the value to Ty2 in the result + /// register. This does not necessarily include registers defined in + /// unknown ways, such as incoming arguments, or copies from unknown + /// virtual registers. Also, if isTruncateFree(Ty2, Ty1) is true, this + /// does not necessarily apply to truncate instructions. e.g. on x86-64, + /// all instructions that define 32-bit values implicit zero-extend the + /// result out to 64 bits. + virtual bool isZExtFree(const Type *Ty1, const Type *Ty2) const { + return false; + } + + virtual bool isZExtFree(EVT VT1, EVT VT2) const { + return false; + } + + /// isNarrowingProfitable - Return true if it's profitable to narrow + /// operations of type VT1 to VT2. e.g. on x86, it's profitable to narrow + /// from i32 to i8 but not from i32 to i16. + virtual bool isNarrowingProfitable(EVT VT1, EVT VT2) const { + return false; + } + + /// isLegalICmpImmediate - Return true if the specified immediate is legal + /// icmp immediate, that is the target has icmp instructions which can compare + /// a register against the immediate without having to materialize the + /// immediate into a register. + virtual bool isLegalICmpImmediate(int64_t Imm) const { + return true; + } + + //===--------------------------------------------------------------------===// + // Div utility functions + // + SDValue BuildSDIV(SDNode *N, SelectionDAG &DAG, + std::vector* Created) const; + SDValue BuildUDIV(SDNode *N, SelectionDAG &DAG, + std::vector* Created) const; + + + //===--------------------------------------------------------------------===// + // Runtime Library hooks + // + + /// setLibcallName - Rename the default libcall routine name for the specified + /// libcall. + void setLibcallName(RTLIB::Libcall Call, const char *Name) { + LibcallRoutineNames[Call] = Name; + } + + /// getLibcallName - Get the libcall routine name for the specified libcall. + /// + const char *getLibcallName(RTLIB::Libcall Call) const { + return LibcallRoutineNames[Call]; + } + + /// setCmpLibcallCC - Override the default CondCode to be used to test the + /// result of the comparison libcall against zero. + void setCmpLibcallCC(RTLIB::Libcall Call, ISD::CondCode CC) { + CmpLibcallCCs[Call] = CC; + } + + /// getCmpLibcallCC - Get the CondCode that's to be used to test the result of + /// the comparison libcall against zero. + ISD::CondCode getCmpLibcallCC(RTLIB::Libcall Call) const { + return CmpLibcallCCs[Call]; + } + + /// setLibcallCallingConv - Set the CallingConv that should be used for the + /// specified libcall. + void setLibcallCallingConv(RTLIB::Libcall Call, CallingConv::ID CC) { + LibcallCallingConvs[Call] = CC; + } + + /// getLibcallCallingConv - Get the CallingConv that should be used for the + /// specified libcall. + CallingConv::ID getLibcallCallingConv(RTLIB::Libcall Call) const { + return LibcallCallingConvs[Call]; + } + +private: + TargetMachine &TM; + const TargetData *TD; + TargetLoweringObjectFile &TLOF; + + /// PointerTy - The type to use for pointers, usually i32 or i64. + /// + MVT PointerTy; + + /// IsLittleEndian - True if this is a little endian target. + /// + bool IsLittleEndian; + + /// UsesGlobalOffsetTable - True if this target uses a GOT for PIC codegen. + /// + bool UsesGlobalOffsetTable; + + /// SelectIsExpensive - Tells the code generator not to expand operations + /// into sequences that use the select operations if possible. + bool SelectIsExpensive; + + /// IntDivIsCheap - Tells the code generator not to expand integer divides by + /// constants into a sequence of muls, adds, and shifts. This is a hack until + /// a real cost model is in place. If we ever optimize for size, this will be + /// set to true unconditionally. + bool IntDivIsCheap; + + /// Pow2DivIsCheap - Tells the code generator that it shouldn't generate + /// srl/add/sra for a signed divide by power of two, and let the target handle + /// it. + bool Pow2DivIsCheap; + + /// UseUnderscoreSetJmp - This target prefers to use _setjmp to implement + /// llvm.setjmp. Defaults to false. + bool UseUnderscoreSetJmp; + + /// UseUnderscoreLongJmp - This target prefers to use _longjmp to implement + /// llvm.longjmp. Defaults to false. + bool UseUnderscoreLongJmp; + + /// ShiftAmountTy - The type to use for shift amounts, usually i8 or whatever + /// PointerTy is. + MVT ShiftAmountTy; + + /// BooleanContents - Information about the contents of the high-bits in + /// boolean values held in a type wider than i1. See getBooleanContents. + BooleanContent BooleanContents; + + /// SchedPreferenceInfo - The target scheduling preference: shortest possible + /// total cycles or lowest register usage. + SchedPreference SchedPreferenceInfo; + + /// JumpBufSize - The size, in bytes, of the target's jmp_buf buffers + unsigned JumpBufSize; + + /// JumpBufAlignment - The alignment, in bytes, of the target's jmp_buf + /// buffers + unsigned JumpBufAlignment; + + /// IfCvtBlockSizeLimit - The maximum allowed size for a block to be + /// if-converted. + unsigned IfCvtBlockSizeLimit; + + /// IfCvtDupBlockSizeLimit - The maximum allowed size for a block to be + /// duplicated during if-conversion. + unsigned IfCvtDupBlockSizeLimit; + + /// PrefLoopAlignment - The perferred loop alignment. + /// + unsigned PrefLoopAlignment; + + /// StackPointerRegisterToSaveRestore - If set to a physical register, this + /// specifies the register that llvm.savestack/llvm.restorestack should save + /// and restore. + unsigned StackPointerRegisterToSaveRestore; + + /// ExceptionPointerRegister - If set to a physical register, this specifies + /// the register that receives the exception address on entry to a landing + /// pad. + unsigned ExceptionPointerRegister; + + /// ExceptionSelectorRegister - If set to a physical register, this specifies + /// the register that receives the exception typeid on entry to a landing + /// pad. + unsigned ExceptionSelectorRegister; + + /// RegClassForVT - This indicates the default register class to use for + /// each ValueType the target supports natively. + TargetRegisterClass *RegClassForVT[MVT::LAST_VALUETYPE]; + unsigned char NumRegistersForVT[MVT::LAST_VALUETYPE]; + EVT RegisterTypeForVT[MVT::LAST_VALUETYPE]; + + /// TransformToType - For any value types we are promoting or expanding, this + /// contains the value type that we are changing to. For Expanded types, this + /// contains one step of the expand (e.g. i64 -> i32), even if there are + /// multiple steps required (e.g. i64 -> i16). For types natively supported + /// by the system, this holds the same type (e.g. i32 -> i32). + EVT TransformToType[MVT::LAST_VALUETYPE]; + + /// OpActions - For each operation and each value type, keep a LegalizeAction + /// that indicates how instruction selection should deal with the operation. + /// Most operations are Legal (aka, supported natively by the target), but + /// operations that are not should be described. Note that operations on + /// non-legal value types are not described here. + /// This array is accessed using VT.getSimpleVT(), so it is subject to + /// the MVT::MAX_ALLOWED_VALUETYPE * 2 bits. + uint64_t OpActions[MVT::MAX_ALLOWED_VALUETYPE/(sizeof(uint64_t)*4)][ISD::BUILTIN_OP_END]; + + /// LoadExtActions - For each load of load extension type and each value type, + /// keep a LegalizeAction that indicates how instruction selection should deal + /// with the load. + uint64_t LoadExtActions[ISD::LAST_LOADEXT_TYPE]; + + /// TruncStoreActions - For each truncating store, keep a LegalizeAction that + /// indicates how instruction selection should deal with the store. + uint64_t TruncStoreActions[MVT::LAST_VALUETYPE]; + + /// IndexedModeActions - For each indexed mode and each value type, + /// keep a pair of LegalizeAction that indicates how instruction + /// selection should deal with the load / store. The first + /// dimension is now the value_type for the reference. The second + /// dimension is the load [0] vs. store[1]. The third dimension + /// represents the various modes for load store. + uint8_t IndexedModeActions[MVT::LAST_VALUETYPE][2][ISD::LAST_INDEXED_MODE]; + + /// ConvertActions - For each conversion from source type to destination type, + /// keep a LegalizeAction that indicates how instruction selection should + /// deal with the conversion. + /// Currently, this is used only for floating->floating conversions + /// (FP_EXTEND and FP_ROUND). + uint64_t ConvertActions[MVT::LAST_VALUETYPE]; + + /// CondCodeActions - For each condition code (ISD::CondCode) keep a + /// LegalizeAction that indicates how instruction selection should + /// deal with the condition code. + uint64_t CondCodeActions[ISD::SETCC_INVALID]; + + ValueTypeActionImpl ValueTypeActions; + + std::vector > AvailableRegClasses; + + /// TargetDAGCombineArray - Targets can specify ISD nodes that they would + /// like PerformDAGCombine callbacks for by calling setTargetDAGCombine(), + /// which sets a bit in this array. + unsigned char + TargetDAGCombineArray[(ISD::BUILTIN_OP_END+CHAR_BIT-1)/CHAR_BIT]; + + /// PromoteToType - For operations that must be promoted to a specific type, + /// this holds the destination type. This map should be sparse, so don't hold + /// it as an array. + /// + /// Targets add entries to this map with AddPromotedToType(..), clients access + /// this with getTypeToPromoteTo(..). + std::map, MVT::SimpleValueType> + PromoteToType; + + /// LibcallRoutineNames - Stores the name each libcall. + /// + const char *LibcallRoutineNames[RTLIB::UNKNOWN_LIBCALL]; + + /// CmpLibcallCCs - The ISD::CondCode that should be used to test the result + /// of each of the comparison libcall against zero. + ISD::CondCode CmpLibcallCCs[RTLIB::UNKNOWN_LIBCALL]; + + /// LibcallCallingConvs - Stores the CallingConv that should be used for each + /// libcall. + CallingConv::ID LibcallCallingConvs[RTLIB::UNKNOWN_LIBCALL]; + +protected: + /// When lowering \@llvm.memset this field specifies the maximum number of + /// store operations that may be substituted for the call to memset. Targets + /// must set this value based on the cost threshold for that target. Targets + /// should assume that the memset will be done using as many of the largest + /// store operations first, followed by smaller ones, if necessary, per + /// alignment restrictions. For example, storing 9 bytes on a 32-bit machine + /// with 16-bit alignment would result in four 2-byte stores and one 1-byte + /// store. This only applies to setting a constant array of a constant size. + /// @brief Specify maximum number of store instructions per memset call. + unsigned maxStoresPerMemset; + + /// When lowering \@llvm.memcpy this field specifies the maximum number of + /// store operations that may be substituted for a call to memcpy. Targets + /// must set this value based on the cost threshold for that target. Targets + /// should assume that the memcpy will be done using as many of the largest + /// store operations first, followed by smaller ones, if necessary, per + /// alignment restrictions. For example, storing 7 bytes on a 32-bit machine + /// with 32-bit alignment would result in one 4-byte store, a one 2-byte store + /// and one 1-byte store. This only applies to copying a constant array of + /// constant size. + /// @brief Specify maximum bytes of store instructions per memcpy call. + unsigned maxStoresPerMemcpy; + + /// When lowering \@llvm.memmove this field specifies the maximum number of + /// store instructions that may be substituted for a call to memmove. Targets + /// must set this value based on the cost threshold for that target. Targets + /// should assume that the memmove will be done using as many of the largest + /// store operations first, followed by smaller ones, if necessary, per + /// alignment restrictions. For example, moving 9 bytes on a 32-bit machine + /// with 8-bit alignment would result in nine 1-byte stores. This only + /// applies to copying a constant array of constant size. + /// @brief Specify maximum bytes of store instructions per memmove call. + unsigned maxStoresPerMemmove; + + /// This field specifies whether the target can benefit from code placement + /// optimization. + bool benefitFromCodePlacementOpt; +}; +} // end llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Target/TargetLoweringObjectFile.h b/libclamav/c++/llvm/include/llvm/Target/TargetLoweringObjectFile.h new file mode 100644 index 000000000..9a641914a --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Target/TargetLoweringObjectFile.h @@ -0,0 +1,361 @@ +//===-- llvm/Target/TargetLoweringObjectFile.h - Object 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 classes used to handle lowerings specific to common +// object file formats. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TARGET_TARGETLOWERINGOBJECTFILE_H +#define LLVM_TARGET_TARGETLOWERINGOBJECTFILE_H + +#include "llvm/ADT/StringRef.h" +#include "llvm/MC/SectionKind.h" + +namespace llvm { + class MachineModuleInfo; + class Mangler; + class MCAsmInfo; + class MCExpr; + class MCSection; + class MCSectionMachO; + class MCContext; + class GlobalValue; + class TargetMachine; + +class TargetLoweringObjectFile { + MCContext *Ctx; + + TargetLoweringObjectFile(const TargetLoweringObjectFile&); // DO NOT IMPLEMENT + void operator=(const TargetLoweringObjectFile&); // DO NOT IMPLEMENT +protected: + + TargetLoweringObjectFile(); + + /// TextSection - Section directive for standard text. + /// + const MCSection *TextSection; + + /// DataSection - Section directive for standard data. + /// + const MCSection *DataSection; + + /// BSSSection - Section that is default initialized to zero. + const MCSection *BSSSection; + + /// ReadOnlySection - Section that is readonly and can contain arbitrary + /// initialized data. Targets are not required to have a readonly section. + /// If they don't, various bits of code will fall back to using the data + /// section for constants. + const MCSection *ReadOnlySection; + + /// StaticCtorSection - This section contains the static constructor pointer + /// list. + const MCSection *StaticCtorSection; + + /// StaticDtorSection - This section contains the static destructor pointer + /// list. + const MCSection *StaticDtorSection; + + /// LSDASection - If exception handling is supported by the target, this is + /// the section the Language Specific Data Area information is emitted to. + const MCSection *LSDASection; + + /// EHFrameSection - If exception handling is supported by the target, this is + /// the section the EH Frame is emitted to. + const MCSection *EHFrameSection; + + // Dwarf sections for debug info. If a target supports debug info, these must + // be set. + const MCSection *DwarfAbbrevSection; + const MCSection *DwarfInfoSection; + const MCSection *DwarfLineSection; + const MCSection *DwarfFrameSection; + const MCSection *DwarfPubNamesSection; + const MCSection *DwarfPubTypesSection; + const MCSection *DwarfDebugInlineSection; + const MCSection *DwarfStrSection; + const MCSection *DwarfLocSection; + const MCSection *DwarfARangesSection; + const MCSection *DwarfRangesSection; + const MCSection *DwarfMacroInfoSection; + +public: + + MCContext &getContext() const { return *Ctx; } + + + virtual ~TargetLoweringObjectFile(); + + /// Initialize - this method must be called before any actual lowering is + /// done. This specifies the current context for codegen, and gives the + /// lowering implementations a chance to set up their default sections. + virtual void Initialize(MCContext &ctx, const TargetMachine &TM) { + Ctx = &ctx; + } + + + const MCSection *getTextSection() const { return TextSection; } + const MCSection *getDataSection() const { return DataSection; } + const MCSection *getBSSSection() const { return BSSSection; } + const MCSection *getStaticCtorSection() const { return StaticCtorSection; } + const MCSection *getStaticDtorSection() const { return StaticDtorSection; } + const MCSection *getLSDASection() const { return LSDASection; } + const MCSection *getEHFrameSection() const { return EHFrameSection; } + const MCSection *getDwarfAbbrevSection() const { return DwarfAbbrevSection; } + const MCSection *getDwarfInfoSection() const { return DwarfInfoSection; } + const MCSection *getDwarfLineSection() const { return DwarfLineSection; } + const MCSection *getDwarfFrameSection() const { return DwarfFrameSection; } + const MCSection *getDwarfPubNamesSection() const{return DwarfPubNamesSection;} + const MCSection *getDwarfPubTypesSection() const{return DwarfPubTypesSection;} + const MCSection *getDwarfDebugInlineSection() const { + return DwarfDebugInlineSection; + } + const MCSection *getDwarfStrSection() const { return DwarfStrSection; } + const MCSection *getDwarfLocSection() const { return DwarfLocSection; } + const MCSection *getDwarfARangesSection() const { return DwarfARangesSection;} + const MCSection *getDwarfRangesSection() const { return DwarfRangesSection; } + const MCSection *getDwarfMacroInfoSection() const { + return DwarfMacroInfoSection; + } + + /// shouldEmitUsedDirectiveFor - This hook allows targets to selectively + /// decide not to emit the UsedDirective for some symbols in llvm.used. + /// FIXME: REMOVE this (rdar://7071300) + virtual bool shouldEmitUsedDirectiveFor(const GlobalValue *GV, + Mangler *) const { + return GV != 0; + } + + /// getSectionForConstant - Given a constant with the SectionKind, return a + /// section that it should be placed in. + virtual const MCSection *getSectionForConstant(SectionKind Kind) const; + + /// getKindForGlobal - Classify the specified global variable into a set of + /// target independent categories embodied in SectionKind. + static SectionKind getKindForGlobal(const GlobalValue *GV, + const TargetMachine &TM); + + /// SectionForGlobal - This method computes the appropriate section to emit + /// the specified global variable or function definition. This should not + /// be passed external (or available externally) globals. + const MCSection *SectionForGlobal(const GlobalValue *GV, + SectionKind Kind, Mangler *Mang, + const TargetMachine &TM) const; + + /// SectionForGlobal - This method computes the appropriate section to emit + /// the specified global variable or function definition. This should not + /// be passed external (or available externally) globals. + const MCSection *SectionForGlobal(const GlobalValue *GV, + Mangler *Mang, + const TargetMachine &TM) const { + return SectionForGlobal(GV, getKindForGlobal(GV, TM), Mang, TM); + } + + + + /// getExplicitSectionGlobal - Targets should implement this method to assign + /// a section to globals with an explicit section specfied. The + /// implementation of this method can assume that GV->hasSection() is true. + virtual const MCSection * + getExplicitSectionGlobal(const GlobalValue *GV, SectionKind Kind, + Mangler *Mang, const TargetMachine &TM) const = 0; + + /// getSpecialCasedSectionGlobals - Allow the target to completely override + /// section assignment of a global. + virtual const MCSection * + getSpecialCasedSectionGlobals(const GlobalValue *GV, Mangler *Mang, + SectionKind Kind) const { + return 0; + } + + /// getSymbolForDwarfGlobalReference - Return an MCExpr to use for a + /// pc-relative reference to the specified global variable from exception + /// handling information. In addition to the symbol, this returns + /// by-reference: + /// + /// IsIndirect - True if the returned symbol is actually a stub that contains + /// the address of the symbol, false if the symbol is the global itself. + /// + /// IsPCRel - True if the symbol reference is already pc-relative, false if + /// the caller needs to subtract off the address of the reference from the + /// symbol. + /// + virtual const MCExpr * + getSymbolForDwarfGlobalReference(const GlobalValue *GV, Mangler *Mang, + MachineModuleInfo *MMI, + bool &IsIndirect, bool &IsPCRel) const; + +protected: + virtual const MCSection * + SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind, + Mangler *Mang, const TargetMachine &TM) const; +}; + + + + +class TargetLoweringObjectFileELF : public TargetLoweringObjectFile { + mutable void *UniquingMap; +protected: + /// TLSDataSection - Section directive for Thread Local data. + /// + const MCSection *TLSDataSection; // Defaults to ".tdata". + + /// TLSBSSSection - Section directive for Thread Local uninitialized data. + /// Null if this target doesn't support a BSS section. + /// + const MCSection *TLSBSSSection; // Defaults to ".tbss". + + const MCSection *DataRelSection; + const MCSection *DataRelLocalSection; + const MCSection *DataRelROSection; + const MCSection *DataRelROLocalSection; + + const MCSection *MergeableConst4Section; + const MCSection *MergeableConst8Section; + const MCSection *MergeableConst16Section; + +protected: + const MCSection *getELFSection(StringRef Section, unsigned Type, + unsigned Flags, SectionKind Kind, + bool IsExplicit = false) const; +public: + TargetLoweringObjectFileELF() : UniquingMap(0) {} + ~TargetLoweringObjectFileELF(); + + virtual void Initialize(MCContext &Ctx, const TargetMachine &TM); + + /// getSectionForConstant - Given a constant with the SectionKind, return a + /// section that it should be placed in. + virtual const MCSection *getSectionForConstant(SectionKind Kind) const; + + + virtual const MCSection * + getExplicitSectionGlobal(const GlobalValue *GV, SectionKind Kind, + Mangler *Mang, const TargetMachine &TM) const; + + virtual const MCSection * + SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind, + Mangler *Mang, const TargetMachine &TM) const; +}; + + + +class TargetLoweringObjectFileMachO : public TargetLoweringObjectFile { + mutable void *UniquingMap; + + const MCSection *CStringSection; + const MCSection *UStringSection; + const MCSection *TextCoalSection; + const MCSection *ConstTextCoalSection; + const MCSection *ConstDataCoalSection; + const MCSection *ConstDataSection; + const MCSection *DataCoalSection; + const MCSection *FourByteConstantSection; + const MCSection *EightByteConstantSection; + const MCSection *SixteenByteConstantSection; + + const MCSection *LazySymbolPointerSection; + const MCSection *NonLazySymbolPointerSection; +public: + TargetLoweringObjectFileMachO() : UniquingMap(0) {} + ~TargetLoweringObjectFileMachO(); + + virtual void Initialize(MCContext &Ctx, const TargetMachine &TM); + + virtual const MCSection * + SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind, + Mangler *Mang, const TargetMachine &TM) const; + + virtual const MCSection * + getExplicitSectionGlobal(const GlobalValue *GV, SectionKind Kind, + Mangler *Mang, const TargetMachine &TM) const; + + virtual const MCSection *getSectionForConstant(SectionKind Kind) const; + + /// shouldEmitUsedDirectiveFor - This hook allows targets to selectively + /// decide not to emit the UsedDirective for some symbols in llvm.used. + /// FIXME: REMOVE this (rdar://7071300) + virtual bool shouldEmitUsedDirectiveFor(const GlobalValue *GV, + Mangler *) const; + + /// getMachOSection - Return the MCSection for the specified mach-o section. + /// This requires the operands to be valid. + const MCSectionMachO *getMachOSection(StringRef Segment, + StringRef Section, + unsigned TypeAndAttributes, + SectionKind K) const { + return getMachOSection(Segment, Section, TypeAndAttributes, 0, K); + } + const MCSectionMachO *getMachOSection(StringRef Segment, + StringRef Section, + unsigned TypeAndAttributes, + unsigned Reserved2, + SectionKind K) const; + + /// getTextCoalSection - Return the "__TEXT,__textcoal_nt" section we put weak + /// text symbols into. + const MCSection *getTextCoalSection() const { + return TextCoalSection; + } + + /// getConstTextCoalSection - Return the "__TEXT,__const_coal" section + /// we put weak read-only symbols into. + const MCSection *getConstTextCoalSection() const { + return ConstTextCoalSection; + } + + /// getLazySymbolPointerSection - Return the section corresponding to + /// the .lazy_symbol_pointer directive. + const MCSection *getLazySymbolPointerSection() const { + return LazySymbolPointerSection; + } + + /// getNonLazySymbolPointerSection - Return the section corresponding to + /// the .non_lazy_symbol_pointer directive. + const MCSection *getNonLazySymbolPointerSection() const { + return NonLazySymbolPointerSection; + } + + /// getSymbolForDwarfGlobalReference - The mach-o version of this method + /// defaults to returning a stub reference. + virtual const MCExpr * + getSymbolForDwarfGlobalReference(const GlobalValue *GV, Mangler *Mang, + MachineModuleInfo *MMI, + bool &IsIndirect, bool &IsPCRel) const; +}; + + + +class TargetLoweringObjectFileCOFF : public TargetLoweringObjectFile { + mutable void *UniquingMap; +public: + TargetLoweringObjectFileCOFF() : UniquingMap(0) {} + ~TargetLoweringObjectFileCOFF(); + + virtual void Initialize(MCContext &Ctx, const TargetMachine &TM); + + virtual const MCSection * + getExplicitSectionGlobal(const GlobalValue *GV, SectionKind Kind, + Mangler *Mang, const TargetMachine &TM) const; + + virtual const MCSection * + SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind, + Mangler *Mang, const TargetMachine &TM) const; + + /// getCOFFSection - Return the MCSection for the specified COFF section. + /// FIXME: Switch this to a semantic view eventually. + const MCSection *getCOFFSection(const char *Name, bool isDirective, + SectionKind K) const; +}; + +} // end namespace llvm + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Target/TargetMachOWriterInfo.h b/libclamav/c++/llvm/include/llvm/Target/TargetMachOWriterInfo.h new file mode 100644 index 000000000..f723bb5be --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Target/TargetMachOWriterInfo.h @@ -0,0 +1,112 @@ +//===-- llvm/Target/TargetMachOWriterInfo.h - MachO Writer 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 defines the TargetMachOWriterInfo class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TARGET_TARGETMACHOWRITERINFO_H +#define LLVM_TARGET_TARGETMACHOWRITERINFO_H + +#include "llvm/CodeGen/MachineRelocation.h" + +namespace llvm { + + class MachineBasicBlock; + class OutputBuffer; + + //===--------------------------------------------------------------------===// + // TargetMachOWriterInfo + //===--------------------------------------------------------------------===// + + class TargetMachOWriterInfo { + uint32_t CPUType; // CPU specifier + uint32_t CPUSubType; // Machine specifier + public: + // The various CPU_TYPE_* constants are already defined by at least one + // system header file and create compilation errors if not respected. +#if !defined(CPU_TYPE_I386) +#define CPU_TYPE_I386 7 +#endif +#if !defined(CPU_TYPE_X86_64) +#define CPU_TYPE_X86_64 (CPU_TYPE_I386 | 0x1000000) +#endif +#if !defined(CPU_TYPE_ARM) +#define CPU_TYPE_ARM 12 +#endif +#if !defined(CPU_TYPE_SPARC) +#define CPU_TYPE_SPARC 14 +#endif +#if !defined(CPU_TYPE_POWERPC) +#define CPU_TYPE_POWERPC 18 +#endif +#if !defined(CPU_TYPE_POWERPC64) +#define CPU_TYPE_POWERPC64 (CPU_TYPE_POWERPC | 0x1000000) +#endif + + // Constants for the cputype field + // see + enum { + HDR_CPU_TYPE_I386 = CPU_TYPE_I386, + HDR_CPU_TYPE_X86_64 = CPU_TYPE_X86_64, + HDR_CPU_TYPE_ARM = CPU_TYPE_ARM, + HDR_CPU_TYPE_SPARC = CPU_TYPE_SPARC, + HDR_CPU_TYPE_POWERPC = CPU_TYPE_POWERPC, + HDR_CPU_TYPE_POWERPC64 = CPU_TYPE_POWERPC64 + }; + +#if !defined(CPU_SUBTYPE_I386_ALL) +#define CPU_SUBTYPE_I386_ALL 3 +#endif +#if !defined(CPU_SUBTYPE_X86_64_ALL) +#define CPU_SUBTYPE_X86_64_ALL 3 +#endif +#if !defined(CPU_SUBTYPE_ARM_ALL) +#define CPU_SUBTYPE_ARM_ALL 0 +#endif +#if !defined(CPU_SUBTYPE_SPARC_ALL) +#define CPU_SUBTYPE_SPARC_ALL 0 +#endif +#if !defined(CPU_SUBTYPE_POWERPC_ALL) +#define CPU_SUBTYPE_POWERPC_ALL 0 +#endif + + // Constants for the cpusubtype field + // see + enum { + HDR_CPU_SUBTYPE_I386_ALL = CPU_SUBTYPE_I386_ALL, + HDR_CPU_SUBTYPE_X86_64_ALL = CPU_SUBTYPE_X86_64_ALL, + HDR_CPU_SUBTYPE_ARM_ALL = CPU_SUBTYPE_ARM_ALL, + HDR_CPU_SUBTYPE_SPARC_ALL = CPU_SUBTYPE_SPARC_ALL, + HDR_CPU_SUBTYPE_POWERPC_ALL = CPU_SUBTYPE_POWERPC_ALL + }; + + TargetMachOWriterInfo(uint32_t cputype, uint32_t cpusubtype) + : CPUType(cputype), CPUSubType(cpusubtype) {} + virtual ~TargetMachOWriterInfo(); + + virtual MachineRelocation GetJTRelocation(unsigned Offset, + MachineBasicBlock *MBB) const; + + virtual unsigned GetTargetRelocation(MachineRelocation &MR, + unsigned FromIdx, + unsigned ToAddr, + unsigned ToIdx, + OutputBuffer &RelocOut, + OutputBuffer &SecOut, + bool Scattered, + bool Extern) const { return 0; } + + uint32_t getCPUType() const { return CPUType; } + uint32_t getCPUSubType() const { return CPUSubType; } + }; + +} // end llvm namespace + +#endif // LLVM_TARGET_TARGETMACHOWRITERINFO_H diff --git a/libclamav/c++/llvm/include/llvm/Target/TargetMachine.h b/libclamav/c++/llvm/include/llvm/Target/TargetMachine.h new file mode 100644 index 000000000..11046359d --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Target/TargetMachine.h @@ -0,0 +1,452 @@ +//===-- llvm/Target/TargetMachine.h - Target Information --------*- 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 the TargetMachine and LLVMTargetMachine classes. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TARGET_TARGETMACHINE_H +#define LLVM_TARGET_TARGETMACHINE_H + +#include "llvm/Target/TargetInstrItineraries.h" +#include +#include + +namespace llvm { + +class Target; +class MCAsmInfo; +class TargetData; +class TargetSubtarget; +class TargetInstrInfo; +class TargetIntrinsicInfo; +class TargetJITInfo; +class TargetLowering; +class TargetFrameInfo; +class MachineCodeEmitter; +class JITCodeEmitter; +class ObjectCodeEmitter; +class TargetRegisterInfo; +class PassManagerBase; +class PassManager; +class Pass; +class TargetMachOWriterInfo; +class TargetELFWriterInfo; +class formatted_raw_ostream; + +// Relocation model types. +namespace Reloc { + enum Model { + Default, + Static, + PIC_, // Cannot be named PIC due to collision with -DPIC + DynamicNoPIC + }; +} + +// Code model types. +namespace CodeModel { + enum Model { + Default, + Small, + Kernel, + Medium, + Large + }; +} + +namespace FileModel { + enum Model { + Error, + None, + AsmFile, + MachOFile, + ElfFile + }; +} + +// Code generation optimization level. +namespace CodeGenOpt { + enum Level { + None, // -O0 + Less, // -O1 + Default, // -O2, -Os + Aggressive // -O3 + }; +} + + +//===----------------------------------------------------------------------===// +/// +/// TargetMachine - Primary interface to the complete machine description for +/// the target machine. All target-specific information should be accessible +/// through this interface. +/// +class TargetMachine { + TargetMachine(const TargetMachine &); // DO NOT IMPLEMENT + void operator=(const TargetMachine &); // DO NOT IMPLEMENT +protected: // Can only create subclasses. + TargetMachine(const Target &); + + /// getSubtargetImpl - virtual method implemented by subclasses that returns + /// a reference to that target's TargetSubtarget-derived member variable. + virtual const TargetSubtarget *getSubtargetImpl() const { return 0; } + + /// TheTarget - The Target that this machine was created for. + const Target &TheTarget; + + /// AsmInfo - Contains target specific asm information. + /// + const MCAsmInfo *AsmInfo; + +public: + virtual ~TargetMachine(); + + const Target &getTarget() const { return TheTarget; } + + // Interfaces to the major aspects of target machine information: + // -- Instruction opcode and operand information + // -- Pipelines and scheduling information + // -- Stack frame information + // -- Selection DAG lowering information + // + virtual const TargetInstrInfo *getInstrInfo() const { return 0; } + virtual const TargetFrameInfo *getFrameInfo() const { return 0; } + virtual TargetLowering *getTargetLowering() const { return 0; } + virtual const TargetData *getTargetData() const { return 0; } + + /// getMCAsmInfo - Return target specific asm information. + /// + const MCAsmInfo *getMCAsmInfo() const { return AsmInfo; } + + /// getSubtarget - This method returns a pointer to the specified type of + /// TargetSubtarget. In debug builds, it verifies that the object being + /// returned is of the correct type. + template const STC &getSubtarget() const { + const TargetSubtarget *TST = getSubtargetImpl(); + assert(TST && dynamic_cast(TST) && + "Not the right kind of subtarget!"); + return *static_cast(TST); + } + + /// getRegisterInfo - If register information is available, return it. If + /// not, return null. This is kept separate from RegInfo until RegInfo has + /// details of graph coloring register allocation removed from it. + /// + virtual const TargetRegisterInfo *getRegisterInfo() const { return 0; } + + /// getIntrinsicInfo - If intrinsic information is available, return it. If + /// not, return null. + /// + virtual const TargetIntrinsicInfo *getIntrinsicInfo() const { return 0; } + + /// getJITInfo - If this target supports a JIT, return information for it, + /// otherwise return null. + /// + virtual TargetJITInfo *getJITInfo() { return 0; } + + /// getInstrItineraryData - Returns instruction itinerary data for the target + /// or specific subtarget. + /// + virtual const InstrItineraryData getInstrItineraryData() const { + return InstrItineraryData(); + } + + /// getMachOWriterInfo - If this target supports a Mach-O writer, return + /// information for it, otherwise return null. + /// + virtual const TargetMachOWriterInfo *getMachOWriterInfo() const { return 0; } + + /// getELFWriterInfo - If this target supports an ELF writer, return + /// information for it, otherwise return null. + /// + virtual const TargetELFWriterInfo *getELFWriterInfo() const { return 0; } + + /// getRelocationModel - Returns the code generation relocation model. The + /// choices are static, PIC, and dynamic-no-pic, and target default. + static Reloc::Model getRelocationModel(); + + /// setRelocationModel - Sets the code generation relocation model. + /// + static void setRelocationModel(Reloc::Model Model); + + /// getCodeModel - Returns the code model. The choices are small, kernel, + /// medium, large, and target default. + static CodeModel::Model getCodeModel(); + + /// setCodeModel - Sets the code model. + /// + static void setCodeModel(CodeModel::Model Model); + + /// getAsmVerbosityDefault - Returns the default value of asm verbosity. + /// + static bool getAsmVerbosityDefault(); + + /// setAsmVerbosityDefault - Set the default value of asm verbosity. Default + /// is false. + static void setAsmVerbosityDefault(bool); + + /// CodeGenFileType - These enums are meant to be passed into + /// addPassesToEmitFile to indicate what type of file to emit. + enum CodeGenFileType { + AssemblyFile, ObjectFile, DynamicLibrary + }; + + /// getEnableTailMergeDefault - the default setting for -enable-tail-merge + /// on this target. User flag overrides. + virtual bool getEnableTailMergeDefault() const { return true; } + + /// addPassesToEmitFile - Add passes to the specified pass manager to get the + /// specified file emitted. Typically this will involve several steps of code + /// generation. + /// This method should return FileModel::Error if emission of this file type + /// is not supported. + /// + virtual FileModel::Model addPassesToEmitFile(PassManagerBase &, + formatted_raw_ostream &, + CodeGenFileType, + CodeGenOpt::Level) { + return FileModel::None; + } + + /// addPassesToEmitFileFinish - If the passes to emit the specified file had + /// to be split up (e.g., to add an object writer pass), this method can be + /// used to finish up adding passes to emit the file, if necessary. + /// + virtual bool addPassesToEmitFileFinish(PassManagerBase &, + MachineCodeEmitter *, + CodeGenOpt::Level) { + return true; + } + + /// addPassesToEmitFileFinish - If the passes to emit the specified file had + /// to be split up (e.g., to add an object writer pass), this method can be + /// used to finish up adding passes to emit the file, if necessary. + /// + virtual bool addPassesToEmitFileFinish(PassManagerBase &, + JITCodeEmitter *, + CodeGenOpt::Level) { + return true; + } + + /// addPassesToEmitFileFinish - If the passes to emit the specified file had + /// to be split up (e.g., to add an object writer pass), this method can be + /// used to finish up adding passes to emit the file, if necessary. + /// + virtual bool addPassesToEmitFileFinish(PassManagerBase &, + ObjectCodeEmitter *, + CodeGenOpt::Level) { + return true; + } + + /// addPassesToEmitMachineCode - Add passes to the specified pass manager to + /// get machine code emitted. This uses a MachineCodeEmitter object to handle + /// actually outputting the machine code and resolving things like the address + /// of functions. This method returns true if machine code emission is + /// not supported. + /// + virtual bool addPassesToEmitMachineCode(PassManagerBase &, + MachineCodeEmitter &, + CodeGenOpt::Level) { + return true; + } + + /// addPassesToEmitMachineCode - Add passes to the specified pass manager to + /// get machine code emitted. This uses a MachineCodeEmitter object to handle + /// actually outputting the machine code and resolving things like the address + /// of functions. This method returns true if machine code emission is + /// not supported. + /// + virtual bool addPassesToEmitMachineCode(PassManagerBase &, + JITCodeEmitter &, + CodeGenOpt::Level) { + return true; + } + + /// addPassesToEmitWholeFile - This method can be implemented by targets that + /// require having the entire module at once. This is not recommended, do not + /// use this. + virtual bool WantsWholeFile() const { return false; } + virtual bool addPassesToEmitWholeFile(PassManager &, formatted_raw_ostream &, + CodeGenFileType, + CodeGenOpt::Level) { + return true; + } +}; + +/// LLVMTargetMachine - This class describes a target machine that is +/// implemented with the LLVM target-independent code generator. +/// +class LLVMTargetMachine : public TargetMachine { +protected: // Can only create subclasses. + LLVMTargetMachine(const Target &T, const std::string &TargetTriple); + + /// addCommonCodeGenPasses - Add standard LLVM codegen passes used for + /// both emitting to assembly files or machine code output. + /// + bool addCommonCodeGenPasses(PassManagerBase &, CodeGenOpt::Level); + +public: + + /// addPassesToEmitFile - Add passes to the specified pass manager to get the + /// specified file emitted. Typically this will involve several steps of code + /// generation. If OptLevel is None, the code generator should emit code as fast + /// as possible, though the generated code may be less efficient. This method + /// should return FileModel::Error if emission of this file type is not + /// supported. + /// + /// The default implementation of this method adds components from the + /// LLVM retargetable code generator, invoking the methods below to get + /// target-specific passes in standard locations. + /// + virtual FileModel::Model addPassesToEmitFile(PassManagerBase &PM, + formatted_raw_ostream &Out, + CodeGenFileType FileType, + CodeGenOpt::Level); + + /// addPassesToEmitFileFinish - If the passes to emit the specified file had + /// to be split up (e.g., to add an object writer pass), this method can be + /// used to finish up adding passes to emit the file, if necessary. + /// + virtual bool addPassesToEmitFileFinish(PassManagerBase &PM, + MachineCodeEmitter *MCE, + CodeGenOpt::Level); + + /// addPassesToEmitFileFinish - If the passes to emit the specified file had + /// to be split up (e.g., to add an object writer pass), this method can be + /// used to finish up adding passes to emit the file, if necessary. + /// + virtual bool addPassesToEmitFileFinish(PassManagerBase &PM, + JITCodeEmitter *JCE, + CodeGenOpt::Level); + + /// addPassesToEmitFileFinish - If the passes to emit the specified file had + /// to be split up (e.g., to add an object writer pass), this method can be + /// used to finish up adding passes to emit the file, if necessary. + /// + virtual bool addPassesToEmitFileFinish(PassManagerBase &PM, + ObjectCodeEmitter *OCE, + CodeGenOpt::Level); + + /// addPassesToEmitMachineCode - Add passes to the specified pass manager to + /// get machine code emitted. This uses a MachineCodeEmitter object to handle + /// actually outputting the machine code and resolving things like the address + /// of functions. This method returns true if machine code emission is + /// not supported. + /// + virtual bool addPassesToEmitMachineCode(PassManagerBase &PM, + MachineCodeEmitter &MCE, + CodeGenOpt::Level); + + /// addPassesToEmitMachineCode - Add passes to the specified pass manager to + /// get machine code emitted. This uses a MachineCodeEmitter object to handle + /// actually outputting the machine code and resolving things like the address + /// of functions. This method returns true if machine code emission is + /// not supported. + /// + virtual bool addPassesToEmitMachineCode(PassManagerBase &PM, + JITCodeEmitter &MCE, + CodeGenOpt::Level); + + /// Target-Independent Code Generator Pass Configuration Options. + + /// addInstSelector - This method should add any "last minute" LLVM->LLVM + /// passes, then install an instruction selector pass, which converts from + /// LLVM code to machine instructions. + virtual bool addInstSelector(PassManagerBase &, CodeGenOpt::Level) { + return true; + } + + /// addPreRegAlloc - This method may be implemented by targets that want to + /// run passes immediately before register allocation. This should return + /// true if -print-machineinstrs should print after these passes. + virtual bool addPreRegAlloc(PassManagerBase &, CodeGenOpt::Level) { + return false; + } + + /// addPostRegAlloc - This method may be implemented by targets that want + /// to run passes after register allocation but before prolog-epilog + /// insertion. This should return true if -print-machineinstrs should print + /// after these passes. + virtual bool addPostRegAlloc(PassManagerBase &, CodeGenOpt::Level) { + return false; + } + + /// addPreSched2 - This method may be implemented by targets that want to + /// run passes after prolog-epilog insertion and before the second instruction + /// scheduling pass. This should return true if -print-machineinstrs should + /// print after these passes. + virtual bool addPreSched2(PassManagerBase &, CodeGenOpt::Level) { + return false; + } + + /// addPreEmitPass - This pass may be implemented by targets that want to run + /// passes immediately before machine code is emitted. This should return + /// true if -print-machineinstrs should print out the code after the passes. + virtual bool addPreEmitPass(PassManagerBase &, CodeGenOpt::Level) { + return false; + } + + + /// addCodeEmitter - This pass should be overridden by the target to add a + /// code emitter, if supported. If this is not supported, 'true' should be + /// returned. + virtual bool addCodeEmitter(PassManagerBase &, CodeGenOpt::Level, + MachineCodeEmitter &) { + return true; + } + + /// addCodeEmitter - This pass should be overridden by the target to add a + /// code emitter, if supported. If this is not supported, 'true' should be + /// returned. + virtual bool addCodeEmitter(PassManagerBase &, CodeGenOpt::Level, + JITCodeEmitter &) { + return true; + } + + /// addSimpleCodeEmitter - This pass should be overridden by the target to add + /// a code emitter (without setting flags), if supported. If this is not + /// supported, 'true' should be returned. + virtual bool addSimpleCodeEmitter(PassManagerBase &, CodeGenOpt::Level, + MachineCodeEmitter &) { + return true; + } + + /// addSimpleCodeEmitter - This pass should be overridden by the target to add + /// a code emitter (without setting flags), if supported. If this is not + /// supported, 'true' should be returned. + virtual bool addSimpleCodeEmitter(PassManagerBase &, CodeGenOpt::Level, + JITCodeEmitter &) { + return true; + } + + /// addSimpleCodeEmitter - This pass should be overridden by the target to add + /// a code emitter (without setting flags), if supported. If this is not + /// supported, 'true' should be returned. + virtual bool addSimpleCodeEmitter(PassManagerBase &, CodeGenOpt::Level, + ObjectCodeEmitter &) { + return true; + } + + /// getEnableTailMergeDefault - the default setting for -enable-tail-merge + /// on this target. User flag overrides. + virtual bool getEnableTailMergeDefault() const { return true; } + + /// addAssemblyEmitter - Helper function which creates a target specific + /// assembly printer, if available. + /// + /// \return Returns 'false' on success. + bool addAssemblyEmitter(PassManagerBase &, CodeGenOpt::Level, + bool /* VerboseAsmDefault */, + formatted_raw_ostream &); +}; + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Target/TargetOptions.h b/libclamav/c++/llvm/include/llvm/Target/TargetOptions.h new file mode 100644 index 000000000..8d52dadc2 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Target/TargetOptions.h @@ -0,0 +1,146 @@ +//===-- llvm/Target/TargetOptions.h - Target Options ------------*- 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 command line option flags that are shared across various +// targets. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TARGET_TARGETOPTIONS_H +#define LLVM_TARGET_TARGETOPTIONS_H + +namespace llvm { + // Possible float ABI settings. Used with FloatABIType in TargetOptions.h. + namespace FloatABI { + enum ABIType { + Default, // Target-specific (either soft of hard depending on triple, etc). + Soft, // Soft float. + Hard // Hard float. + }; + } + + /// PrintMachineCode - This flag is enabled when the -print-machineinstrs + /// option is specified on the command line, and should enable debugging + /// output from the code generator. + extern bool PrintMachineCode; + + /// NoFramePointerElim - This flag is enabled when the -disable-fp-elim is + /// specified on the command line. If the target supports the frame pointer + /// elimination optimization, this option should disable it. + extern bool NoFramePointerElim; + + /// LessPreciseFPMAD - This flag is enabled when the + /// -enable-fp-mad is specified on the command line. When this flag is off + /// (the default), the code generator is not allowed to generate mad + /// (multiply add) if the result is "less precise" than doing those operations + /// individually. + extern bool LessPreciseFPMADOption; + extern bool LessPreciseFPMAD(); + + /// NoExcessFPPrecision - This flag is enabled when the + /// -disable-excess-fp-precision flag is specified on the command line. When + /// this flag is off (the default), the code generator is allowed to produce + /// results that are "more precise" than IEEE allows. This includes use of + /// FMA-like operations and use of the X86 FP registers without rounding all + /// over the place. + extern bool NoExcessFPPrecision; + + /// UnsafeFPMath - This flag is enabled when the + /// -enable-unsafe-fp-math flag is specified on the command line. When + /// this flag is off (the default), the code generator is not allowed to + /// produce results that are "less precise" than IEEE allows. This includes + /// use of X86 instructions like FSIN and FCOS instead of libcalls. + /// UnsafeFPMath implies FiniteOnlyFPMath and LessPreciseFPMAD. + extern bool UnsafeFPMath; + + /// FiniteOnlyFPMath - This returns true when the -enable-finite-only-fp-math + /// option is specified on the command line. If this returns false (default), + /// the code generator is not allowed to assume that FP arithmetic arguments + /// and results are never NaNs or +-Infs. + extern bool FiniteOnlyFPMathOption; + extern bool FiniteOnlyFPMath(); + + /// HonorSignDependentRoundingFPMath - This returns true when the + /// -enable-sign-dependent-rounding-fp-math is specified. If this returns + /// false (the default), the code generator is allowed to assume that the + /// rounding behavior is the default (round-to-zero for all floating point to + /// integer conversions, and round-to-nearest for all other arithmetic + /// truncations). If this is enabled (set to true), the code generator must + /// assume that the rounding mode may dynamically change. + extern bool HonorSignDependentRoundingFPMathOption; + extern bool HonorSignDependentRoundingFPMath(); + + /// UseSoftFloat - This flag is enabled when the -soft-float flag is specified + /// on the command line. When this flag is on, the code generator will + /// generate libcalls to the software floating point library instead of + /// target FP instructions. + extern bool UseSoftFloat; + + /// FloatABIType - This setting is set by -float-abi=xxx option is specfied + /// on the command line. This setting may either be Default, Soft, or Hard. + /// Default selects the target's default behavior. Soft selects the ABI for + /// UseSoftFloat, but does not inidcate that FP hardware may not be used. + /// Such a combination is unfortunately popular (e.g. arm-apple-darwin). + /// Hard presumes that the normal FP ABI is used. + extern FloatABI::ABIType FloatABIType; + + /// NoZerosInBSS - By default some codegens place zero-initialized data to + /// .bss section. This flag disables such behaviour (necessary, e.g. for + /// crt*.o compiling). + extern bool NoZerosInBSS; + + /// DwarfExceptionHandling - This flag indicates that Dwarf exception + /// information should be emitted. + extern bool DwarfExceptionHandling; + + /// SjLjExceptionHandling - This flag indicates that SJLJ exception + /// information should be emitted. + extern bool SjLjExceptionHandling; + + /// JITEmitDebugInfo - This flag indicates that the JIT should try to emit + /// debug information and notify a debugger about it. + extern bool JITEmitDebugInfo; + + /// JITEmitDebugInfoToDisk - This flag indicates that the JIT should write + /// the object files generated by the JITEmitDebugInfo flag to disk. This + /// flag is hidden and is only for debugging the debug info. + extern bool JITEmitDebugInfoToDisk; + + /// UnwindTablesMandatory - This flag indicates that unwind tables should + /// be emitted for all functions. + extern bool UnwindTablesMandatory; + + /// PerformTailCallOpt - This flag is enabled when -tailcallopt is specified + /// on the commandline. When the flag is on, the target will perform tail call + /// optimization (pop the caller's stack) providing it supports it. + extern bool PerformTailCallOpt; + + /// StackAlignment - Override default stack alignment for target. + extern unsigned StackAlignment; + + /// RealignStack - This flag indicates, whether stack should be automatically + /// realigned, if needed. + extern bool RealignStack; + + /// DisableJumpTables - This flag indicates jump tables should not be + /// generated. + extern bool DisableJumpTables; + + /// EnableFastISel - This flag enables fast-path instruction selection + /// which trades away generated code quality in favor of reducing + /// compile time. + extern bool EnableFastISel; + + /// StrongPHIElim - This flag enables more aggressive PHI elimination + /// wth earlier copy coalescing. + extern bool StrongPHIElim; + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Target/TargetRegisterInfo.h b/libclamav/c++/llvm/include/llvm/Target/TargetRegisterInfo.h new file mode 100644 index 000000000..cb29c7306 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Target/TargetRegisterInfo.h @@ -0,0 +1,738 @@ +//=== Target/TargetRegisterInfo.h - Target Register Information -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file describes an abstract interface used to get information about a +// target machines register file. This information is used for a variety of +// purposed, especially register allocation. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TARGET_TARGETREGISTERINFO_H +#define LLVM_TARGET_TARGETREGISTERINFO_H + +#include "llvm/CodeGen/MachineBasicBlock.h" +#include "llvm/CodeGen/ValueTypes.h" +#include "llvm/ADT/DenseSet.h" +#include +#include + +namespace llvm { + +class BitVector; +class MachineFunction; +class MachineMove; +class RegScavenger; + +/// TargetRegisterDesc - This record contains all of the information known about +/// a particular register. The AliasSet field (if not null) contains a pointer +/// to a Zero terminated array of registers that this register aliases. This is +/// needed for architectures like X86 which have AL alias AX alias EAX. +/// Registers that this does not apply to simply should set this to null. +/// The SubRegs field is a zero terminated array of registers that are +/// sub-registers of the specific register, e.g. AL, AH are sub-registers of AX. +/// The SuperRegs field is a zero terminated array of registers that are +/// super-registers of the specific register, e.g. RAX, EAX, are super-registers +/// of AX. +/// +struct TargetRegisterDesc { + const char *Name; // Printable name for the reg (for debugging) + const unsigned *AliasSet; // Register Alias Set, described above + const unsigned *SubRegs; // Sub-register set, described above + const unsigned *SuperRegs; // Super-register set, described above +}; + +class TargetRegisterClass { +public: + typedef const unsigned* iterator; + typedef const unsigned* const_iterator; + + typedef const EVT* vt_iterator; + typedef const TargetRegisterClass* const * sc_iterator; +private: + unsigned ID; + const char *Name; + const vt_iterator VTs; + const sc_iterator SubClasses; + const sc_iterator SuperClasses; + const sc_iterator SubRegClasses; + const sc_iterator SuperRegClasses; + const unsigned RegSize, Alignment; // Size & Alignment of register in bytes + const int CopyCost; + const iterator RegsBegin, RegsEnd; + DenseSet RegSet; +public: + TargetRegisterClass(unsigned id, + const char *name, + const EVT *vts, + const TargetRegisterClass * const *subcs, + const TargetRegisterClass * const *supcs, + const TargetRegisterClass * const *subregcs, + const TargetRegisterClass * const *superregcs, + unsigned RS, unsigned Al, int CC, + iterator RB, iterator RE) + : ID(id), Name(name), VTs(vts), SubClasses(subcs), SuperClasses(supcs), + SubRegClasses(subregcs), SuperRegClasses(superregcs), + RegSize(RS), Alignment(Al), CopyCost(CC), RegsBegin(RB), RegsEnd(RE) { + for (iterator I = RegsBegin, E = RegsEnd; I != E; ++I) + RegSet.insert(*I); + } + virtual ~TargetRegisterClass() {} // Allow subclasses + + /// getID() - Return the register class ID number. + /// + unsigned getID() const { return ID; } + + /// getName() - Return the register class name for debugging. + /// + const char *getName() const { return Name; } + + /// begin/end - Return all of the registers in this class. + /// + iterator begin() const { return RegsBegin; } + iterator end() const { return RegsEnd; } + + /// getNumRegs - Return the number of registers in this class. + /// + unsigned getNumRegs() const { return (unsigned)(RegsEnd-RegsBegin); } + + /// getRegister - Return the specified register in the class. + /// + unsigned getRegister(unsigned i) const { + assert(i < getNumRegs() && "Register number out of range!"); + return RegsBegin[i]; + } + + /// contains - Return true if the specified register is included in this + /// register class. + bool contains(unsigned Reg) const { + return RegSet.count(Reg); + } + + /// hasType - return true if this TargetRegisterClass has the ValueType vt. + /// + bool hasType(EVT vt) const { + for(int i = 0; VTs[i].getSimpleVT().SimpleTy != MVT::Other; ++i) + if (VTs[i] == vt) + return true; + return false; + } + + /// vt_begin / vt_end - Loop over all of the value types that can be + /// represented by values in this register class. + vt_iterator vt_begin() const { + return VTs; + } + + vt_iterator vt_end() const { + vt_iterator I = VTs; + while (I->getSimpleVT().SimpleTy != MVT::Other) ++I; + return I; + } + + /// subregclasses_begin / subregclasses_end - Loop over all of + /// the subreg register classes of this register class. + sc_iterator subregclasses_begin() const { + return SubRegClasses; + } + + sc_iterator subregclasses_end() const { + sc_iterator I = SubRegClasses; + while (*I != NULL) ++I; + return I; + } + + /// getSubRegisterRegClass - Return the register class of subregisters with + /// index SubIdx, or NULL if no such class exists. + const TargetRegisterClass* getSubRegisterRegClass(unsigned SubIdx) const { + assert(SubIdx>0 && "Invalid subregister index"); + for (unsigned s = 0; s != SubIdx-1; ++s) + if (!SubRegClasses[s]) + return NULL; + return SubRegClasses[SubIdx-1]; + } + + /// superregclasses_begin / superregclasses_end - Loop over all of + /// the superreg register classes of this register class. + sc_iterator superregclasses_begin() const { + return SuperRegClasses; + } + + sc_iterator superregclasses_end() const { + sc_iterator I = SuperRegClasses; + while (*I != NULL) ++I; + return I; + } + + /// hasSubClass - return true if the the specified TargetRegisterClass + /// is a proper subset of this TargetRegisterClass. + bool hasSubClass(const TargetRegisterClass *cs) const { + for (int i = 0; SubClasses[i] != NULL; ++i) + if (SubClasses[i] == cs) + return true; + return false; + } + + /// subclasses_begin / subclasses_end - Loop over all of the classes + /// that are proper subsets of this register class. + sc_iterator subclasses_begin() const { + return SubClasses; + } + + sc_iterator subclasses_end() const { + sc_iterator I = SubClasses; + while (*I != NULL) ++I; + return I; + } + + /// hasSuperClass - return true if the specified TargetRegisterClass is a + /// proper superset of this TargetRegisterClass. + bool hasSuperClass(const TargetRegisterClass *cs) const { + for (int i = 0; SuperClasses[i] != NULL; ++i) + if (SuperClasses[i] == cs) + return true; + return false; + } + + /// superclasses_begin / superclasses_end - Loop over all of the classes + /// that are proper supersets of this register class. + sc_iterator superclasses_begin() const { + return SuperClasses; + } + + sc_iterator superclasses_end() const { + sc_iterator I = SuperClasses; + while (*I != NULL) ++I; + return I; + } + + /// isASubClass - return true if this TargetRegisterClass is a subset + /// class of at least one other TargetRegisterClass. + bool isASubClass() const { + return SuperClasses[0] != 0; + } + + /// allocation_order_begin/end - These methods define a range of registers + /// which specify the registers in this class that are valid to register + /// allocate, and the preferred order to allocate them in. For example, + /// callee saved registers should be at the end of the list, because it is + /// cheaper to allocate caller saved registers. + /// + /// These methods take a MachineFunction argument, which can be used to tune + /// the allocatable registers based on the characteristics of the function. + /// One simple example is that the frame pointer register can be used if + /// frame-pointer-elimination is performed. + /// + /// By default, these methods return all registers in the class. + /// + virtual iterator allocation_order_begin(const MachineFunction &MF) const { + return begin(); + } + virtual iterator allocation_order_end(const MachineFunction &MF) const { + return end(); + } + + /// getSize - Return the size of the register in bytes, which is also the size + /// of a stack slot allocated to hold a spilled copy of this register. + unsigned getSize() const { return RegSize; } + + /// getAlignment - Return the minimum required alignment for a register of + /// this class. + unsigned getAlignment() const { return Alignment; } + + /// getCopyCost - Return the cost of copying a value between two registers in + /// this class. A negative number means the register class is very expensive + /// to copy e.g. status flag register classes. + int getCopyCost() const { return CopyCost; } +}; + + +/// TargetRegisterInfo base class - We assume that the target defines a static +/// array of TargetRegisterDesc objects that represent all of the machine +/// registers that the target has. As such, we simply have to track a pointer +/// to this array so that we can turn register number into a register +/// descriptor. +/// +class TargetRegisterInfo { +protected: + const unsigned* SubregHash; + const unsigned SubregHashSize; + const unsigned* SuperregHash; + const unsigned SuperregHashSize; + const unsigned* AliasesHash; + const unsigned AliasesHashSize; +public: + typedef const TargetRegisterClass * const * regclass_iterator; +private: + const TargetRegisterDesc *Desc; // Pointer to the descriptor array + unsigned NumRegs; // Number of entries in the array + + regclass_iterator RegClassBegin, RegClassEnd; // List of regclasses + + int CallFrameSetupOpcode, CallFrameDestroyOpcode; + +protected: + TargetRegisterInfo(const TargetRegisterDesc *D, unsigned NR, + regclass_iterator RegClassBegin, + regclass_iterator RegClassEnd, + int CallFrameSetupOpcode = -1, + int CallFrameDestroyOpcode = -1, + const unsigned* subregs = 0, + const unsigned subregsize = 0, + const unsigned* superregs = 0, + const unsigned superregsize = 0, + const unsigned* aliases = 0, + const unsigned aliasessize = 0); + virtual ~TargetRegisterInfo(); +public: + + enum { // Define some target independent constants + /// NoRegister - This physical register is not a real target register. It + /// is useful as a sentinal. + NoRegister = 0, + + /// FirstVirtualRegister - This is the first register number that is + /// considered to be a 'virtual' register, which is part of the SSA + /// namespace. This must be the same for all targets, which means that each + /// target is limited to 1024 registers. + FirstVirtualRegister = 1024 + }; + + /// isPhysicalRegister - Return true if the specified register number is in + /// the physical register namespace. + static bool isPhysicalRegister(unsigned Reg) { + assert(Reg && "this is not a register!"); + return Reg < FirstVirtualRegister; + } + + /// isVirtualRegister - Return true if the specified register number is in + /// the virtual register namespace. + static bool isVirtualRegister(unsigned Reg) { + assert(Reg && "this is not a register!"); + return Reg >= FirstVirtualRegister; + } + + /// getPhysicalRegisterRegClass - Returns the Register Class of a physical + /// register of the given type. If type is EVT::Other, then just return any + /// register class the register belongs to. + virtual const TargetRegisterClass * + getPhysicalRegisterRegClass(unsigned Reg, EVT VT = MVT::Other) const; + + /// getAllocatableSet - Returns a bitset indexed by register number + /// indicating if a register is allocatable or not. If a register class is + /// specified, returns the subset for the class. + BitVector getAllocatableSet(const MachineFunction &MF, + const TargetRegisterClass *RC = NULL) const; + + const TargetRegisterDesc &operator[](unsigned RegNo) const { + assert(RegNo < NumRegs && + "Attempting to access record for invalid register number!"); + return Desc[RegNo]; + } + + /// Provide a get method, equivalent to [], but more useful if we have a + /// pointer to this object. + /// + const TargetRegisterDesc &get(unsigned RegNo) const { + return operator[](RegNo); + } + + /// getAliasSet - Return the set of registers aliased by the specified + /// register, or a null list of there are none. The list returned is zero + /// terminated. + /// + const unsigned *getAliasSet(unsigned RegNo) const { + return get(RegNo).AliasSet; + } + + /// getSubRegisters - Return the list of registers that are sub-registers of + /// the specified register, or a null list of there are none. The list + /// returned is zero terminated and sorted according to super-sub register + /// relations. e.g. X86::RAX's sub-register list is EAX, AX, AL, AH. + /// + const unsigned *getSubRegisters(unsigned RegNo) const { + return get(RegNo).SubRegs; + } + + /// getSuperRegisters - Return the list of registers that are super-registers + /// of the specified register, or a null list of there are none. The list + /// returned is zero terminated and sorted according to super-sub register + /// relations. e.g. X86::AL's super-register list is RAX, EAX, AX. + /// + const unsigned *getSuperRegisters(unsigned RegNo) const { + return get(RegNo).SuperRegs; + } + + /// getName - Return the human-readable symbolic target-specific name for the + /// specified physical register. + const char *getName(unsigned RegNo) const { + return get(RegNo).Name; + } + + /// getNumRegs - Return the number of registers this target has (useful for + /// sizing arrays holding per register information) + unsigned getNumRegs() const { + return NumRegs; + } + + /// regsOverlap - Returns true if the two registers are equal or alias each + /// other. The registers may be virtual register. + bool regsOverlap(unsigned regA, unsigned regB) const { + if (regA == regB) + return true; + + if (isVirtualRegister(regA) || isVirtualRegister(regB)) + return false; + + // regA and regB are distinct physical registers. Do they alias? + size_t index = (regA + regB * 37) & (AliasesHashSize-1); + unsigned ProbeAmt = 0; + while (AliasesHash[index*2] != 0 && + AliasesHash[index*2+1] != 0) { + if (AliasesHash[index*2] == regA && AliasesHash[index*2+1] == regB) + return true; + + index = (index + ProbeAmt) & (AliasesHashSize-1); + ProbeAmt += 2; + } + + return false; + } + + /// isSubRegister - Returns true if regB is a sub-register of regA. + /// + bool isSubRegister(unsigned regA, unsigned regB) const { + // SubregHash is a simple quadratically probed hash table. + size_t index = (regA + regB * 37) & (SubregHashSize-1); + unsigned ProbeAmt = 2; + while (SubregHash[index*2] != 0 && + SubregHash[index*2+1] != 0) { + if (SubregHash[index*2] == regA && SubregHash[index*2+1] == regB) + return true; + + index = (index + ProbeAmt) & (SubregHashSize-1); + ProbeAmt += 2; + } + + return false; + } + + /// isSuperRegister - Returns true if regB is a super-register of regA. + /// + bool isSuperRegister(unsigned regA, unsigned regB) const { + // SuperregHash is a simple quadratically probed hash table. + size_t index = (regA + regB * 37) & (SuperregHashSize-1); + unsigned ProbeAmt = 2; + while (SuperregHash[index*2] != 0 && + SuperregHash[index*2+1] != 0) { + if (SuperregHash[index*2] == regA && SuperregHash[index*2+1] == regB) + return true; + + index = (index + ProbeAmt) & (SuperregHashSize-1); + ProbeAmt += 2; + } + + return false; + } + + /// getCalleeSavedRegs - Return a null-terminated list of all of the + /// callee saved registers on this target. The register should be in the + /// order of desired callee-save stack frame offset. The first register is + /// closed to the incoming stack pointer if stack grows down, and vice versa. + virtual const unsigned* getCalleeSavedRegs(const MachineFunction *MF = 0) + const = 0; + + /// getCalleeSavedRegClasses - Return a null-terminated list of the preferred + /// register classes to spill each callee saved register with. The order and + /// length of this list match the getCalleeSaveRegs() list. + virtual const TargetRegisterClass* const *getCalleeSavedRegClasses( + const MachineFunction *MF) const =0; + + /// getReservedRegs - Returns a bitset indexed by physical register number + /// indicating if a register is a special register that has particular uses + /// and should be considered unavailable at all times, e.g. SP, RA. This is + /// used by register scavenger to determine what registers are free. + virtual BitVector getReservedRegs(const MachineFunction &MF) const = 0; + + /// getSubReg - Returns the physical register number of sub-register "Index" + /// for physical register RegNo. Return zero if the sub-register does not + /// exist. + virtual unsigned getSubReg(unsigned RegNo, unsigned Index) const = 0; + + /// getSubRegIndex - For a given register pair, return the sub-register index + /// if the are second register is a sub-register of the first. Return zero + /// otherwise. + virtual unsigned getSubRegIndex(unsigned RegNo, unsigned SubRegNo) const = 0; + + /// getMatchingSuperReg - Return a super-register of the specified register + /// Reg so its sub-register of index SubIdx is Reg. + unsigned getMatchingSuperReg(unsigned Reg, unsigned SubIdx, + const TargetRegisterClass *RC) const { + for (const unsigned *SRs = getSuperRegisters(Reg); unsigned SR = *SRs;++SRs) + if (Reg == getSubReg(SR, SubIdx) && RC->contains(SR)) + return SR; + return 0; + } + + /// getMatchingSuperRegClass - Return a subclass of the specified register + /// class A so that each register in it has a sub-register of the + /// specified sub-register index which is in the specified register class B. + virtual const TargetRegisterClass * + getMatchingSuperRegClass(const TargetRegisterClass *A, + const TargetRegisterClass *B, unsigned Idx) const { + return 0; + } + + //===--------------------------------------------------------------------===// + // Register Class Information + // + + /// Register class iterators + /// + regclass_iterator regclass_begin() const { return RegClassBegin; } + regclass_iterator regclass_end() const { return RegClassEnd; } + + unsigned getNumRegClasses() const { + return (unsigned)(regclass_end()-regclass_begin()); + } + + /// getRegClass - Returns the register class associated with the enumeration + /// value. See class TargetOperandInfo. + const TargetRegisterClass *getRegClass(unsigned i) const { + assert(i <= getNumRegClasses() && "Register Class ID out of range"); + return i ? RegClassBegin[i - 1] : NULL; + } + + /// getPointerRegClass - Returns a TargetRegisterClass used for pointer + /// values. If a target supports multiple different pointer register classes, + /// kind specifies which one is indicated. + virtual const TargetRegisterClass *getPointerRegClass(unsigned Kind=0) const { + assert(0 && "Target didn't implement getPointerRegClass!"); + return 0; // Must return a value in order to compile with VS 2005 + } + + /// getCrossCopyRegClass - Returns a legal register class to copy a register + /// in the specified class to or from. Returns NULL if it is possible to copy + /// between a two registers of the specified class. + virtual const TargetRegisterClass * + getCrossCopyRegClass(const TargetRegisterClass *RC) const { + return NULL; + } + + /// getAllocationOrder - Returns the register allocation order for a specified + /// register class in the form of a pair of TargetRegisterClass iterators. + virtual std::pair + getAllocationOrder(const TargetRegisterClass *RC, + unsigned HintType, unsigned HintReg, + const MachineFunction &MF) const { + return std::make_pair(RC->allocation_order_begin(MF), + RC->allocation_order_end(MF)); + } + + /// ResolveRegAllocHint - Resolves the specified register allocation hint + /// to a physical register. Returns the physical register if it is successful. + virtual unsigned ResolveRegAllocHint(unsigned Type, unsigned Reg, + const MachineFunction &MF) const { + if (Type == 0 && Reg && isPhysicalRegister(Reg)) + return Reg; + return 0; + } + + /// UpdateRegAllocHint - A callback to allow target a chance to update + /// register allocation hints when a register is "changed" (e.g. coalesced) + /// to another register. e.g. On ARM, some virtual registers should target + /// register pairs, if one of pair is coalesced to another register, the + /// allocation hint of the other half of the pair should be changed to point + /// to the new register. + virtual void UpdateRegAllocHint(unsigned Reg, unsigned NewReg, + MachineFunction &MF) const { + // Do nothing. + } + + /// targetHandlesStackFrameRounding - Returns true if the target is + /// responsible for rounding up the stack frame (probably at emitPrologue + /// time). + virtual bool targetHandlesStackFrameRounding() const { + return false; + } + + /// requiresRegisterScavenging - returns true if the target requires (and can + /// make use of) the register scavenger. + virtual bool requiresRegisterScavenging(const MachineFunction &MF) const { + return false; + } + + /// requiresFrameIndexScavenging - returns true if the target requires post + /// PEI scavenging of registers for materializing frame index constants. + virtual bool requiresFrameIndexScavenging(const MachineFunction &MF) const { + return false; + } + + /// hasFP - Return true if the specified function should have a dedicated + /// frame pointer register. For most targets this is true only if the function + /// has variable sized allocas or if frame pointer elimination is disabled. + virtual bool hasFP(const MachineFunction &MF) const = 0; + + /// hasReservedCallFrame - Under normal circumstances, when a frame pointer is + /// not required, we reserve argument space for call sites in the function + /// immediately on entry to the current function. This eliminates the need for + /// add/sub sp brackets around call sites. Returns true if the call frame is + /// included as part of the stack frame. + virtual bool hasReservedCallFrame(MachineFunction &MF) const { + return !hasFP(MF); + } + + /// hasReservedSpillSlot - Return true if target has reserved a spill slot in + /// the stack frame of the given function for the specified register. e.g. On + /// x86, if the frame register is required, the first fixed stack object is + /// reserved as its spill slot. This tells PEI not to create a new stack frame + /// object for the given register. It should be called only after + /// processFunctionBeforeCalleeSavedScan(). + virtual bool hasReservedSpillSlot(MachineFunction &MF, unsigned Reg, + int &FrameIdx) const { + return false; + } + + /// needsStackRealignment - true if storage within the function requires the + /// stack pointer to be aligned more than the normal calling convention calls + /// for. + virtual bool needsStackRealignment(const MachineFunction &MF) const { + return false; + } + + /// getCallFrameSetup/DestroyOpcode - These methods return the opcode of the + /// frame setup/destroy instructions if they exist (-1 otherwise). Some + /// targets use pseudo instructions in order to abstract away the difference + /// between operating with a frame pointer and operating without, through the + /// use of these two instructions. + /// + int getCallFrameSetupOpcode() const { return CallFrameSetupOpcode; } + int getCallFrameDestroyOpcode() const { return CallFrameDestroyOpcode; } + + /// eliminateCallFramePseudoInstr - This method is called during prolog/epilog + /// code insertion to eliminate call frame setup and destroy pseudo + /// instructions (but only if the Target is using them). It is responsible + /// for eliminating these instructions, replacing them with concrete + /// instructions. This method need only be implemented if using call frame + /// setup/destroy pseudo instructions. + /// + virtual void + eliminateCallFramePseudoInstr(MachineFunction &MF, + MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI) const { + assert(getCallFrameSetupOpcode()== -1 && getCallFrameDestroyOpcode()== -1 && + "eliminateCallFramePseudoInstr must be implemented if using" + " call frame setup/destroy pseudo instructions!"); + assert(0 && "Call Frame Pseudo Instructions do not exist on this target!"); + } + + /// processFunctionBeforeCalleeSavedScan - This method is called immediately + /// before PrologEpilogInserter scans the physical registers used to determine + /// what callee saved registers should be spilled. This method is optional. + virtual void processFunctionBeforeCalleeSavedScan(MachineFunction &MF, + RegScavenger *RS = NULL) const { + + } + + /// processFunctionBeforeFrameFinalized - This method is called immediately + /// before the specified functions frame layout (MF.getFrameInfo()) is + /// finalized. Once the frame is finalized, MO_FrameIndex operands are + /// replaced with direct constants. This method is optional. + /// + virtual void processFunctionBeforeFrameFinalized(MachineFunction &MF) const { + } + + /// saveScavengerRegister - Spill the register so it can be used by the + /// register scavenger. Return true if the register was spilled, false + /// otherwise. If this function does not spill the register, the scavenger + /// will instead spill it to the emergency spill slot. + /// + virtual bool saveScavengerRegister(MachineBasicBlock &MBB, + MachineBasicBlock::iterator I, + MachineBasicBlock::iterator &UseMI, + const TargetRegisterClass *RC, + unsigned Reg) const { + return false; + } + + /// eliminateFrameIndex - This method must be overriden to eliminate abstract + /// frame indices from instructions which may use them. The instruction + /// referenced by the iterator contains an MO_FrameIndex operand which must be + /// eliminated by this method. This method may modify or replace the + /// specified instruction, as long as it keeps the iterator pointing the the + /// finished product. SPAdj is the SP adjustment due to call frame setup + /// instruction. + /// + /// When -enable-frame-index-scavenging is enabled, the virtual register + /// allocated for this frame index is returned and its value is stored in + /// *Value. + virtual unsigned eliminateFrameIndex(MachineBasicBlock::iterator MI, + int SPAdj, int *Value = NULL, + RegScavenger *RS=NULL) const = 0; + + /// emitProlog/emitEpilog - These methods insert prolog and epilog code into + /// the function. + virtual void emitPrologue(MachineFunction &MF) const = 0; + virtual void emitEpilogue(MachineFunction &MF, + MachineBasicBlock &MBB) const = 0; + + //===--------------------------------------------------------------------===// + /// Debug information queries. + + /// getDwarfRegNum - Map a target register to an equivalent dwarf register + /// number. Returns -1 if there is no equivalent value. The second + /// parameter allows targets to use different numberings for EH info and + /// debugging info. + virtual int getDwarfRegNum(unsigned RegNum, bool isEH) const = 0; + + /// getFrameRegister - This method should return the register used as a base + /// for values allocated in the current stack frame. + virtual unsigned getFrameRegister(const MachineFunction &MF) const = 0; + + /// getFrameIndexOffset - Returns the displacement from the frame register to + /// the stack frame of the specified index. + virtual int getFrameIndexOffset(MachineFunction &MF, int FI) const; + + /// getFrameIndexReference - This method should return the base register + /// and offset used to reference a frame index location. The offset is + /// returned directly, and the base register is returned via FrameReg. + virtual int getFrameIndexReference(MachineFunction &MF, int FI, + unsigned &FrameReg) const { + // By default, assume all frame indices are referenced via whatever + // getFrameRegister() says. The target can override this if it's doing + // something different. + FrameReg = getFrameRegister(MF); + return getFrameIndexOffset(MF, FI); + } + + /// getRARegister - This method should return the register where the return + /// address can be found. + virtual unsigned getRARegister() const = 0; + + /// getInitialFrameState - Returns a list of machine moves that are assumed + /// on entry to all functions. Note that LabelID is ignored (assumed to be + /// the beginning of the function.) + virtual void getInitialFrameState(std::vector &Moves) const; +}; + + +// This is useful when building IndexedMaps keyed on virtual registers +struct VirtReg2IndexFunctor : public std::unary_function { + unsigned operator()(unsigned Reg) const { + return Reg - TargetRegisterInfo::FirstVirtualRegister; + } +}; + +/// getCommonSubClass - find the largest common subclass of A and B. Return NULL +/// if there is no common subclass. +const TargetRegisterClass *getCommonSubClass(const TargetRegisterClass *A, + const TargetRegisterClass *B); + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Target/TargetRegistry.h b/libclamav/c++/llvm/include/llvm/Target/TargetRegistry.h new file mode 100644 index 000000000..167e1d10d --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Target/TargetRegistry.h @@ -0,0 +1,569 @@ +//===-- Target/TargetRegistry.h - Target Registration -----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file exposes the TargetRegistry interface, which tools can use to access +// the appropriate target specific classes (TargetMachine, AsmPrinter, etc.) +// which have been registered. +// +// Target specific class implementations should register themselves using the +// appropriate TargetRegistry interfaces. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TARGET_TARGETREGISTRY_H +#define LLVM_TARGET_TARGETREGISTRY_H + +#include "llvm/ADT/Triple.h" +#include +#include + +namespace llvm { + class AsmPrinter; + class MCAsmParser; + class MCCodeEmitter; + class Module; + class MCAsmInfo; + class MCDisassembler; + class MCInstPrinter; + class TargetAsmParser; + class TargetMachine; + class formatted_raw_ostream; + class raw_ostream; + + /// Target - Wrapper for Target specific information. + /// + /// For registration purposes, this is a POD type so that targets can be + /// registered without the use of static constructors. + /// + /// Targets should implement a single global instance of this class (which + /// will be zero initialized), and pass that instance to the TargetRegistry as + /// part of their initialization. + class Target { + public: + friend struct TargetRegistry; + + typedef unsigned (*TripleMatchQualityFnTy)(const std::string &TT); + + typedef const MCAsmInfo *(*AsmInfoCtorFnTy)(const Target &T, + StringRef TT); + typedef TargetMachine *(*TargetMachineCtorTy)(const Target &T, + const std::string &TT, + const std::string &Features); + typedef AsmPrinter *(*AsmPrinterCtorTy)(formatted_raw_ostream &OS, + TargetMachine &TM, + const MCAsmInfo *MAI, + bool VerboseAsm); + typedef TargetAsmParser *(*AsmParserCtorTy)(const Target &T, + MCAsmParser &P); + typedef const MCDisassembler *(*MCDisassemblerCtorTy)(const Target &T); + typedef MCInstPrinter *(*MCInstPrinterCtorTy)(const Target &T, + unsigned SyntaxVariant, + const MCAsmInfo &MAI, + raw_ostream &O); + typedef MCCodeEmitter *(*CodeEmitterCtorTy)(const Target &T, + TargetMachine &TM); + + private: + /// Next - The next registered target in the linked list, maintained by the + /// TargetRegistry. + Target *Next; + + /// TripleMatchQualityFn - The target function for rating the match quality + /// of a triple. + TripleMatchQualityFnTy TripleMatchQualityFn; + + /// Name - The target name. + const char *Name; + + /// ShortDesc - A short description of the target. + const char *ShortDesc; + + /// HasJIT - Whether this target supports the JIT. + bool HasJIT; + + AsmInfoCtorFnTy AsmInfoCtorFn; + + /// TargetMachineCtorFn - Construction function for this target's + /// TargetMachine, if registered. + TargetMachineCtorTy TargetMachineCtorFn; + + /// AsmPrinterCtorFn - Construction function for this target's AsmPrinter, + /// if registered. + AsmPrinterCtorTy AsmPrinterCtorFn; + + /// AsmParserCtorFn - Construction function for this target's AsmParser, + /// if registered. + AsmParserCtorTy AsmParserCtorFn; + + /// MCDisassemblerCtorFn - Construction function for this target's + /// MCDisassembler, if registered. + MCDisassemblerCtorTy MCDisassemblerCtorFn; + + + /// MCInstPrinterCtorFn - Construction function for this target's + /// MCInstPrinter, if registered. + MCInstPrinterCtorTy MCInstPrinterCtorFn; + + /// CodeEmitterCtorFn - Construction function for this target's CodeEmitter, + /// if registered. + CodeEmitterCtorTy CodeEmitterCtorFn; + + public: + /// @name Target Information + /// @{ + + // getNext - Return the next registered target. + const Target *getNext() const { return Next; } + + /// getName - Get the target name. + const char *getName() const { return Name; } + + /// getShortDescription - Get a short description of the target. + const char *getShortDescription() const { return ShortDesc; } + + /// @} + /// @name Feature Predicates + /// @{ + + /// hasJIT - Check if this targets supports the just-in-time compilation. + bool hasJIT() const { return HasJIT; } + + /// hasTargetMachine - Check if this target supports code generation. + bool hasTargetMachine() const { return TargetMachineCtorFn != 0; } + + /// hasAsmPrinter - Check if this target supports .s printing. + bool hasAsmPrinter() const { return AsmPrinterCtorFn != 0; } + + /// hasAsmParser - Check if this target supports .s parsing. + bool hasAsmParser() const { return AsmParserCtorFn != 0; } + + /// hasMCDisassembler - Check if this target has a disassembler. + bool hasMCDisassembler() const { return MCDisassemblerCtorFn != 0; } + + /// hasMCInstPrinter - Check if this target has an instruction printer. + bool hasMCInstPrinter() const { return MCInstPrinterCtorFn != 0; } + + /// hasCodeEmitter - Check if this target supports instruction encoding. + bool hasCodeEmitter() const { return CodeEmitterCtorFn != 0; } + + /// @} + /// @name Feature Constructors + /// @{ + + /// createAsmInfo - Create a MCAsmInfo implementation for the specified + /// target triple. + /// + /// \arg Triple - This argument is used to determine the target machine + /// feature set; it should always be provided. Generally this should be + /// either the target triple from the module, or the target triple of the + /// host if that does not exist. + const MCAsmInfo *createAsmInfo(StringRef Triple) const { + if (!AsmInfoCtorFn) + return 0; + return AsmInfoCtorFn(*this, Triple); + } + + /// createTargetMachine - Create a target specific machine implementation + /// for the specified \arg Triple. + /// + /// \arg Triple - This argument is used to determine the target machine + /// feature set; it should always be provided. Generally this should be + /// either the target triple from the module, or the target triple of the + /// host if that does not exist. + TargetMachine *createTargetMachine(const std::string &Triple, + const std::string &Features) const { + if (!TargetMachineCtorFn) + return 0; + return TargetMachineCtorFn(*this, Triple, Features); + } + + /// createAsmPrinter - Create a target specific assembly printer pass. + AsmPrinter *createAsmPrinter(formatted_raw_ostream &OS, TargetMachine &TM, + const MCAsmInfo *MAI, bool Verbose) const { + if (!AsmPrinterCtorFn) + return 0; + return AsmPrinterCtorFn(OS, TM, MAI, Verbose); + } + + /// createAsmParser - Create a target specific assembly parser. + /// + /// \arg Parser - The target independent parser implementation to use for + /// parsing and lexing. + TargetAsmParser *createAsmParser(MCAsmParser &Parser) const { + if (!AsmParserCtorFn) + return 0; + return AsmParserCtorFn(*this, Parser); + } + + const MCDisassembler *createMCDisassembler() const { + if (!MCDisassemblerCtorFn) + return 0; + return MCDisassemblerCtorFn(*this); + } + + MCInstPrinter *createMCInstPrinter(unsigned SyntaxVariant, + const MCAsmInfo &MAI, + raw_ostream &O) const { + if (!MCInstPrinterCtorFn) + return 0; + return MCInstPrinterCtorFn(*this, SyntaxVariant, MAI, O); + } + + + /// createCodeEmitter - Create a target specific code emitter. + MCCodeEmitter *createCodeEmitter(TargetMachine &TM) const { + if (!CodeEmitterCtorFn) + return 0; + return CodeEmitterCtorFn(*this, TM); + } + + /// @} + }; + + /// TargetRegistry - Generic interface to target specific features. + struct TargetRegistry { + class iterator { + const Target *Current; + explicit iterator(Target *T) : Current(T) {} + friend struct TargetRegistry; + public: + iterator(const iterator &I) : Current(I.Current) {} + iterator() : Current(0) {} + + bool operator==(const iterator &x) const { + return Current == x.Current; + } + bool operator!=(const iterator &x) const { + return !operator==(x); + } + + // Iterator traversal: forward iteration only + iterator &operator++() { // Preincrement + assert(Current && "Cannot increment end iterator!"); + Current = Current->getNext(); + return *this; + } + iterator operator++(int) { // Postincrement + iterator tmp = *this; + ++*this; + return tmp; + } + + const Target &operator*() const { + assert(Current && "Cannot dereference end iterator!"); + return *Current; + } + + const Target *operator->() const { + return &operator*(); + } + }; + + /// @name Registry Access + /// @{ + + static iterator begin(); + + static iterator end() { return iterator(); } + + /// lookupTarget - Lookup a target based on a target triple. + /// + /// \param Triple - The triple to use for finding a target. + /// \param Error - On failure, an error string describing why no target was + /// found. + static const Target *lookupTarget(const std::string &Triple, + std::string &Error); + + /// getClosestTargetForJIT - Pick the best target that is compatible with + /// the current host. If no close target can be found, this returns null + /// and sets the Error string to a reason. + /// + /// Maintained for compatibility through 2.6. + static const Target *getClosestTargetForJIT(std::string &Error); + + /// @} + /// @name Target Registration + /// @{ + + /// RegisterTarget - Register the given target. Attempts to register a + /// target which has already been registered will be ignored. + /// + /// Clients are responsible for ensuring that registration doesn't occur + /// while another thread is attempting to access the registry. Typically + /// this is done by initializing all targets at program startup. + /// + /// @param T - The target being registered. + /// @param Name - The target name. This should be a static string. + /// @param ShortDesc - A short target description. This should be a static + /// string. + /// @param TQualityFn - The triple match quality computation function for + /// this target. + /// @param HasJIT - Whether the target supports JIT code + /// generation. + static void RegisterTarget(Target &T, + const char *Name, + const char *ShortDesc, + Target::TripleMatchQualityFnTy TQualityFn, + bool HasJIT = false); + + /// RegisterAsmInfo - Register a MCAsmInfo implementation for the + /// given target. + /// + /// Clients are responsible for ensuring that registration doesn't occur + /// while another thread is attempting to access the registry. Typically + /// this is done by initializing all targets at program startup. + /// + /// @param T - The target being registered. + /// @param Fn - A function to construct a MCAsmInfo for the target. + static void RegisterAsmInfo(Target &T, Target::AsmInfoCtorFnTy Fn) { + // Ignore duplicate registration. + if (!T.AsmInfoCtorFn) + T.AsmInfoCtorFn = Fn; + } + + /// RegisterTargetMachine - Register a TargetMachine implementation for the + /// given target. + /// + /// Clients are responsible for ensuring that registration doesn't occur + /// while another thread is attempting to access the registry. Typically + /// this is done by initializing all targets at program startup. + /// + /// @param T - The target being registered. + /// @param Fn - A function to construct a TargetMachine for the target. + static void RegisterTargetMachine(Target &T, + Target::TargetMachineCtorTy Fn) { + // Ignore duplicate registration. + if (!T.TargetMachineCtorFn) + T.TargetMachineCtorFn = Fn; + } + + /// RegisterAsmPrinter - Register an AsmPrinter implementation for the given + /// target. + /// + /// Clients are responsible for ensuring that registration doesn't occur + /// while another thread is attempting to access the registry. Typically + /// this is done by initializing all targets at program startup. + /// + /// @param T - The target being registered. + /// @param Fn - A function to construct an AsmPrinter for the target. + static void RegisterAsmPrinter(Target &T, Target::AsmPrinterCtorTy Fn) { + // Ignore duplicate registration. + if (!T.AsmPrinterCtorFn) + T.AsmPrinterCtorFn = Fn; + } + + /// RegisterAsmParser - Register a TargetAsmParser implementation for the + /// given target. + /// + /// Clients are responsible for ensuring that registration doesn't occur + /// while another thread is attempting to access the registry. Typically + /// this is done by initializing all targets at program startup. + /// + /// @param T - The target being registered. + /// @param Fn - A function to construct an AsmPrinter for the target. + static void RegisterAsmParser(Target &T, Target::AsmParserCtorTy Fn) { + if (!T.AsmParserCtorFn) + T.AsmParserCtorFn = Fn; + } + + /// RegisterMCDisassembler - Register a MCDisassembler implementation for + /// the given target. + /// + /// Clients are responsible for ensuring that registration doesn't occur + /// while another thread is attempting to access the registry. Typically + /// this is done by initializing all targets at program startup. + /// + /// @param T - The target being registered. + /// @param Fn - A function to construct an MCDisassembler for the target. + static void RegisterMCDisassembler(Target &T, + Target::MCDisassemblerCtorTy Fn) { + if (!T.MCDisassemblerCtorFn) + T.MCDisassemblerCtorFn = Fn; + } + + /// RegisterMCInstPrinter - Register a MCInstPrinter implementation for the + /// given target. + /// + /// Clients are responsible for ensuring that registration doesn't occur + /// while another thread is attempting to access the registry. Typically + /// this is done by initializing all targets at program startup. + /// + /// @param T - The target being registered. + /// @param Fn - A function to construct an MCInstPrinter for the target. + static void RegisterMCInstPrinter(Target &T, + Target::MCInstPrinterCtorTy Fn) { + if (!T.MCInstPrinterCtorFn) + T.MCInstPrinterCtorFn = Fn; + } + + /// RegisterCodeEmitter - Register a MCCodeEmitter implementation for the + /// given target. + /// + /// Clients are responsible for ensuring that registration doesn't occur + /// while another thread is attempting to access the registry. Typically + /// this is done by initializing all targets at program startup. + /// + /// @param T - The target being registered. + /// @param Fn - A function to construct an AsmPrinter for the target. + static void RegisterCodeEmitter(Target &T, Target::CodeEmitterCtorTy Fn) { + if (!T.CodeEmitterCtorFn) + T.CodeEmitterCtorFn = Fn; + } + + /// @} + }; + + + //===--------------------------------------------------------------------===// + + /// RegisterTarget - Helper template for registering a target, for use in the + /// target's initialization function. Usage: + /// + /// + /// Target TheFooTarget; // The global target instance. + /// + /// extern "C" void LLVMInitializeFooTargetInfo() { + /// RegisterTarget X(TheFooTarget, "foo", "Foo description"); + /// } + template + struct RegisterTarget { + RegisterTarget(Target &T, const char *Name, const char *Desc) { + TargetRegistry::RegisterTarget(T, Name, Desc, + &getTripleMatchQuality, + HasJIT); + } + + static unsigned getTripleMatchQuality(const std::string &TT) { + if (Triple(TT).getArch() == TargetArchType) + return 20; + return 0; + } + }; + + /// RegisterAsmInfo - Helper template for registering a target assembly info + /// implementation. This invokes the static "Create" method on the class to + /// actually do the construction. Usage: + /// + /// extern "C" void LLVMInitializeFooTarget() { + /// extern Target TheFooTarget; + /// RegisterAsmInfo X(TheFooTarget); + /// } + template + struct RegisterAsmInfo { + RegisterAsmInfo(Target &T) { + TargetRegistry::RegisterAsmInfo(T, &Allocator); + } + private: + static const MCAsmInfo *Allocator(const Target &T, StringRef TT) { + return new MCAsmInfoImpl(T, TT); + } + + }; + + /// RegisterAsmInfoFn - Helper template for registering a target assembly info + /// implementation. This invokes the specified function to do the + /// construction. Usage: + /// + /// extern "C" void LLVMInitializeFooTarget() { + /// extern Target TheFooTarget; + /// RegisterAsmInfoFn X(TheFooTarget, TheFunction); + /// } + struct RegisterAsmInfoFn { + RegisterAsmInfoFn(Target &T, Target::AsmInfoCtorFnTy Fn) { + TargetRegistry::RegisterAsmInfo(T, Fn); + } + }; + + + /// RegisterTargetMachine - Helper template for registering a target machine + /// implementation, for use in the target machine initialization + /// function. Usage: + /// + /// extern "C" void LLVMInitializeFooTarget() { + /// extern Target TheFooTarget; + /// RegisterTargetMachine X(TheFooTarget); + /// } + template + struct RegisterTargetMachine { + RegisterTargetMachine(Target &T) { + TargetRegistry::RegisterTargetMachine(T, &Allocator); + } + + private: + static TargetMachine *Allocator(const Target &T, const std::string &TT, + const std::string &FS) { + return new TargetMachineImpl(T, TT, FS); + } + }; + + /// RegisterAsmPrinter - Helper template for registering a target specific + /// assembly printer, for use in the target machine initialization + /// function. Usage: + /// + /// extern "C" void LLVMInitializeFooAsmPrinter() { + /// extern Target TheFooTarget; + /// RegisterAsmPrinter X(TheFooTarget); + /// } + template + struct RegisterAsmPrinter { + RegisterAsmPrinter(Target &T) { + TargetRegistry::RegisterAsmPrinter(T, &Allocator); + } + + private: + static AsmPrinter *Allocator(formatted_raw_ostream &OS, TargetMachine &TM, + const MCAsmInfo *MAI, bool Verbose) { + return new AsmPrinterImpl(OS, TM, MAI, Verbose); + } + }; + + /// RegisterAsmParser - Helper template for registering a target specific + /// assembly parser, for use in the target machine initialization + /// function. Usage: + /// + /// extern "C" void LLVMInitializeFooAsmParser() { + /// extern Target TheFooTarget; + /// RegisterAsmParser X(TheFooTarget); + /// } + template + struct RegisterAsmParser { + RegisterAsmParser(Target &T) { + TargetRegistry::RegisterAsmParser(T, &Allocator); + } + + private: + static TargetAsmParser *Allocator(const Target &T, MCAsmParser &P) { + return new AsmParserImpl(T, P); + } + }; + + /// RegisterCodeEmitter - Helper template for registering a target specific + /// machine code emitter, for use in the target initialization + /// function. Usage: + /// + /// extern "C" void LLVMInitializeFooCodeEmitter() { + /// extern Target TheFooTarget; + /// RegisterCodeEmitter X(TheFooTarget); + /// } + template + struct RegisterCodeEmitter { + RegisterCodeEmitter(Target &T) { + TargetRegistry::RegisterCodeEmitter(T, &Allocator); + } + + private: + static MCCodeEmitter *Allocator(const Target &T, TargetMachine &TM) { + return new CodeEmitterImpl(T, TM); + } + }; + +} + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Target/TargetSchedule.td b/libclamav/c++/llvm/include/llvm/Target/TargetSchedule.td new file mode 100644 index 000000000..dcc09921d --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Target/TargetSchedule.td @@ -0,0 +1,83 @@ +//===- TargetSchedule.td - Target Independent Scheduling ---*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the target-independent scheduling interfaces which should +// be implemented by each target which is using TableGen based scheduling. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// Processor functional unit - These values represent the function units +// available across all chip sets for the target. Eg., IntUnit, FPUnit, ... +// These may be independent values for each chip set or may be shared across +// all chip sets of the target. Each functional unit is treated as a resource +// during scheduling and has an affect instruction order based on availability +// during a time interval. +// +class FuncUnit; + +//===----------------------------------------------------------------------===// +// Instruction stage - These values represent a non-pipelined step in +// the execution of an instruction. Cycles represents the number of +// discrete time slots needed to complete the stage. Units represent +// the choice of functional units that can be used to complete the +// stage. Eg. IntUnit1, IntUnit2. NextCycles indicates how many +// cycles should elapse from the start of this stage to the start of +// the next stage in the itinerary. For example: +// +// A stage is specified in one of two ways: +// +// InstrStage<1, [FU_x, FU_y]> - TimeInc defaults to Cycles +// InstrStage<1, [FU_x, FU_y], 0> - TimeInc explicit +// +class InstrStage units, int timeinc = -1> { + int Cycles = cycles; // length of stage in machine cycles + list Units = units; // choice of functional units + int TimeInc = timeinc; // cycles till start of next stage +} + +//===----------------------------------------------------------------------===// +// Instruction itinerary - An itinerary represents a sequential series of steps +// required to complete an instruction. Itineraries are represented as lists of +// instruction stages. +// + +//===----------------------------------------------------------------------===// +// Instruction itinerary classes - These values represent 'named' instruction +// itinerary. Using named itineraries simplifies managing groups of +// instructions across chip sets. An instruction uses the same itinerary class +// across all chip sets. Thus a new chip set can be added without modifying +// instruction information. +// +class InstrItinClass; +def NoItinerary : InstrItinClass; + +//===----------------------------------------------------------------------===// +// Instruction itinerary data - These values provide a runtime map of an +// instruction itinerary class (name) to its itinerary data. +// +class InstrItinData stages, + list operandcycles = []> { + InstrItinClass TheClass = Class; + list Stages = stages; + list OperandCycles = operandcycles; +} + +//===----------------------------------------------------------------------===// +// Processor itineraries - These values represent the set of all itinerary +// classes for a given chip set. +// +class ProcessorItineraries iid> { + list IID = iid; +} + +// NoItineraries - A marker that can be used by processors without schedule +// info. +def NoItineraries : ProcessorItineraries<[]>; + diff --git a/libclamav/c++/llvm/include/llvm/Target/TargetSelect.h b/libclamav/c++/llvm/include/llvm/Target/TargetSelect.h new file mode 100644 index 000000000..951e7fa86 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Target/TargetSelect.h @@ -0,0 +1,118 @@ +//===- TargetSelect.h - Target Selection & Registration ---------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides utilities to make sure that certain classes of targets are +// linked into the main application executable, and initialize them as +// appropriate. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TARGET_TARGETSELECT_H +#define LLVM_TARGET_TARGETSELECT_H + +#include "llvm/Config/config.h" + +extern "C" { + // Declare all of the target-initialization functions that are available. +#define LLVM_TARGET(TargetName) void LLVMInitialize##TargetName##TargetInfo(); +#include "llvm/Config/Targets.def" + +#define LLVM_TARGET(TargetName) void LLVMInitialize##TargetName##Target(); +#include "llvm/Config/Targets.def" + + // Declare all of the available assembly printer initialization functions. +#define LLVM_ASM_PRINTER(TargetName) void LLVMInitialize##TargetName##AsmPrinter(); +#include "llvm/Config/AsmPrinters.def" + + // Declare all of the available assembly parser initialization functions. +#define LLVM_ASM_PARSER(TargetName) void LLVMInitialize##TargetName##AsmParser(); +#include "llvm/Config/AsmParsers.def" + + // Declare all of the available disassembler initialization functions. +#define LLVM_DISASSEMBLER(TargetName) void LLVMInitialize##TargetName##Disassembler(); +#include "llvm/Config/Disassemblers.def" +} + +namespace llvm { + /// InitializeAllTargetInfos - The main program should call this function if + /// it wants access to all available targets that LLVM is configured to + /// support, to make them available via the TargetRegistry. + /// + /// It is legal for a client to make multiple calls to this function. + inline void InitializeAllTargetInfos() { +#define LLVM_TARGET(TargetName) LLVMInitialize##TargetName##TargetInfo(); +#include "llvm/Config/Targets.def" + } + + /// InitializeAllTargets - The main program should call this function if it + /// wants access to all available target machines that LLVM is configured to + /// support, to make them available via the TargetRegistry. + /// + /// It is legal for a client to make multiple calls to this function. + inline void InitializeAllTargets() { + // FIXME: Remove this, clients should do it. + InitializeAllTargetInfos(); + +#define LLVM_TARGET(TargetName) LLVMInitialize##TargetName##Target(); +#include "llvm/Config/Targets.def" + } + + /// InitializeAllAsmPrinters - The main program should call this function if + /// it wants all asm printers that LLVM is configured to support, to make them + /// available via the TargetRegistry. + /// + /// It is legal for a client to make multiple calls to this function. + inline void InitializeAllAsmPrinters() { +#define LLVM_ASM_PRINTER(TargetName) LLVMInitialize##TargetName##AsmPrinter(); +#include "llvm/Config/AsmPrinters.def" + } + + /// InitializeAllAsmParsers - The main program should call this function if it + /// wants all asm parsers that LLVM is configured to support, to make them + /// available via the TargetRegistry. + /// + /// It is legal for a client to make multiple calls to this function. + inline void InitializeAllAsmParsers() { +#define LLVM_ASM_PARSER(TargetName) LLVMInitialize##TargetName##AsmParser(); +#include "llvm/Config/AsmParsers.def" + } + + /// InitializeAllDisassemblers - The main program should call this function if + /// it wants all disassemblers that LLVM is configured to support, to make + /// them available via the TargetRegistry. + /// + /// It is legal for a client to make multiple calls to this function. + inline void InitializeAllDisassemblers() { +#define LLVM_DISASSEMBLER(TargetName) LLVMInitialize##TargetName##Disassembler(); +#include "llvm/Config/Disassemblers.def" + } + + /// InitializeNativeTarget - The main program should call this function to + /// initialize the native target corresponding to the host. This is useful + /// for JIT applications to ensure that the target gets linked in correctly. + /// + /// It is legal for a client to make multiple calls to this function. + inline bool InitializeNativeTarget() { + // If we have a native target, initialize it to ensure it is linked in. +#ifdef LLVM_NATIVE_ARCH +#define DoInit2(TARG) \ + LLVMInitialize ## TARG ## Info (); \ + LLVMInitialize ## TARG () +#define DoInit(T) DoInit2(T) + DoInit(LLVM_NATIVE_ARCH); + return false; +#undef DoInit +#undef DoInit2 +#else + return true; +#endif + } +} + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Target/TargetSelectionDAG.td b/libclamav/c++/llvm/include/llvm/Target/TargetSelectionDAG.td new file mode 100644 index 000000000..7f54f819a --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Target/TargetSelectionDAG.td @@ -0,0 +1,866 @@ +//===- TargetSelectionDAG.td - Common code for DAG isels ---*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the target-independent interfaces used by SelectionDAG +// instruction selection generators. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// Selection DAG Type Constraint definitions. +// +// Note that the semantics of these constraints are hard coded into tblgen. To +// modify or add constraints, you have to hack tblgen. +// + +class SDTypeConstraint { + int OperandNum = opnum; +} + +// SDTCisVT - The specified operand has exactly this VT. +class SDTCisVT : SDTypeConstraint { + ValueType VT = vt; +} + +class SDTCisPtrTy : SDTypeConstraint; + +// SDTCisInt - The specified operand has integer type. +class SDTCisInt : SDTypeConstraint; + +// SDTCisFP - The specified operand has floating-point type. +class SDTCisFP : SDTypeConstraint; + +// SDTCisVec - The specified operand has a vector type. +class SDTCisVec : SDTypeConstraint; + +// SDTCisSameAs - The two specified operands have identical types. +class SDTCisSameAs : SDTypeConstraint { + int OtherOperandNum = OtherOp; +} + +// SDTCisVTSmallerThanOp - The specified operand is a VT SDNode, and its type is +// smaller than the 'Other' operand. +class SDTCisVTSmallerThanOp : SDTypeConstraint { + int OtherOperandNum = OtherOp; +} + +class SDTCisOpSmallerThanOp : SDTypeConstraint{ + int BigOperandNum = BigOp; +} + +/// SDTCisEltOfVec - This indicates that ThisOp is a scalar type of the same +/// type as the element type of OtherOp, which is a vector type. +class SDTCisEltOfVec + : SDTypeConstraint { + int OtherOpNum = OtherOp; +} + +//===----------------------------------------------------------------------===// +// Selection DAG Type Profile definitions. +// +// These use the constraints defined above to describe the type requirements of +// the various nodes. These are not hard coded into tblgen, allowing targets to +// add their own if needed. +// + +// SDTypeProfile - This profile describes the type requirements of a Selection +// DAG node. +class SDTypeProfile constraints> { + int NumResults = numresults; + int NumOperands = numoperands; + list Constraints = constraints; +} + +// Builtin profiles. +def SDTIntLeaf: SDTypeProfile<1, 0, [SDTCisInt<0>]>; // for 'imm'. +def SDTFPLeaf : SDTypeProfile<1, 0, [SDTCisFP<0>]>; // for 'fpimm'. +def SDTPtrLeaf: SDTypeProfile<1, 0, [SDTCisPtrTy<0>]>; // for '&g'. +def SDTOther : SDTypeProfile<1, 0, [SDTCisVT<0, OtherVT>]>; // for 'vt'. +def SDTUNDEF : SDTypeProfile<1, 0, []>; // for 'undef'. +def SDTUnaryOp : SDTypeProfile<1, 1, []>; // for bitconvert. + +def SDTIntBinOp : SDTypeProfile<1, 2, [ // add, and, or, xor, udiv, etc. + SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>, SDTCisInt<0> +]>; +def SDTIntShiftOp : SDTypeProfile<1, 2, [ // shl, sra, srl + SDTCisSameAs<0, 1>, SDTCisInt<0>, SDTCisInt<2> +]>; +def SDTFPBinOp : SDTypeProfile<1, 2, [ // fadd, fmul, etc. + SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>, SDTCisFP<0> +]>; +def SDTFPSignOp : SDTypeProfile<1, 2, [ // fcopysign. + SDTCisSameAs<0, 1>, SDTCisFP<0>, SDTCisFP<2> +]>; +def SDTFPTernaryOp : SDTypeProfile<1, 3, [ // fmadd, fnmsub, etc. + SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>, SDTCisSameAs<0, 3>, SDTCisFP<0> +]>; +def SDTIntUnaryOp : SDTypeProfile<1, 1, [ // ctlz + SDTCisSameAs<0, 1>, SDTCisInt<0> +]>; +def SDTIntExtendOp : SDTypeProfile<1, 1, [ // sext, zext, anyext + SDTCisInt<0>, SDTCisInt<1>, SDTCisOpSmallerThanOp<1, 0> +]>; +def SDTIntTruncOp : SDTypeProfile<1, 1, [ // trunc + SDTCisInt<0>, SDTCisInt<1>, SDTCisOpSmallerThanOp<0, 1> +]>; +def SDTFPUnaryOp : SDTypeProfile<1, 1, [ // fneg, fsqrt, etc + SDTCisSameAs<0, 1>, SDTCisFP<0> +]>; +def SDTFPRoundOp : SDTypeProfile<1, 1, [ // fround + SDTCisFP<0>, SDTCisFP<1>, SDTCisOpSmallerThanOp<0, 1> +]>; +def SDTFPExtendOp : SDTypeProfile<1, 1, [ // fextend + SDTCisFP<0>, SDTCisFP<1>, SDTCisOpSmallerThanOp<1, 0> +]>; +def SDTIntToFPOp : SDTypeProfile<1, 1, [ // [su]int_to_fp + SDTCisFP<0>, SDTCisInt<1> +]>; +def SDTFPToIntOp : SDTypeProfile<1, 1, [ // fp_to_[su]int + SDTCisInt<0>, SDTCisFP<1> +]>; +def SDTExtInreg : SDTypeProfile<1, 2, [ // sext_inreg + SDTCisSameAs<0, 1>, SDTCisInt<0>, SDTCisVT<2, OtherVT>, + SDTCisVTSmallerThanOp<2, 1> +]>; + +def SDTSetCC : SDTypeProfile<1, 3, [ // setcc + SDTCisInt<0>, SDTCisSameAs<1, 2>, SDTCisVT<3, OtherVT> +]>; + +def SDTSelect : SDTypeProfile<1, 3, [ // select + SDTCisInt<1>, SDTCisSameAs<0, 2>, SDTCisSameAs<2, 3> +]>; + +def SDTSelectCC : SDTypeProfile<1, 5, [ // select_cc + SDTCisSameAs<1, 2>, SDTCisSameAs<3, 4>, SDTCisSameAs<0, 3>, + SDTCisVT<5, OtherVT> +]>; + +def SDTBr : SDTypeProfile<0, 1, [ // br + SDTCisVT<0, OtherVT> +]>; + +def SDTBrcond : SDTypeProfile<0, 2, [ // brcond + SDTCisInt<0>, SDTCisVT<1, OtherVT> +]>; + +def SDTBrind : SDTypeProfile<0, 1, [ // brind + SDTCisPtrTy<0> +]>; + +def SDTNone : SDTypeProfile<0, 0, []>; // ret, trap + +def SDTLoad : SDTypeProfile<1, 1, [ // load + SDTCisPtrTy<1> +]>; + +def SDTStore : SDTypeProfile<0, 2, [ // store + SDTCisPtrTy<1> +]>; + +def SDTIStore : SDTypeProfile<1, 3, [ // indexed store + SDTCisSameAs<0, 2>, SDTCisPtrTy<0>, SDTCisPtrTy<3> +]>; + +def SDTVecShuffle : SDTypeProfile<1, 2, [ + SDTCisSameAs<0, 1>, SDTCisSameAs<1, 2> +]>; +def SDTVecExtract : SDTypeProfile<1, 2, [ // vector extract + SDTCisEltOfVec<0, 1>, SDTCisPtrTy<2> +]>; +def SDTVecInsert : SDTypeProfile<1, 3, [ // vector insert + SDTCisEltOfVec<2, 1>, SDTCisSameAs<0, 1>, SDTCisPtrTy<3> +]>; + +def STDPrefetch : SDTypeProfile<0, 3, [ // prefetch + SDTCisPtrTy<0>, SDTCisSameAs<1, 2>, SDTCisInt<1> +]>; + +def STDMemBarrier : SDTypeProfile<0, 5, [ // memory barier + SDTCisSameAs<0,1>, SDTCisSameAs<0,2>, SDTCisSameAs<0,3>, SDTCisSameAs<0,4>, + SDTCisInt<0> +]>; +def STDAtomic3 : SDTypeProfile<1, 3, [ + SDTCisSameAs<0,2>, SDTCisSameAs<0,3>, SDTCisInt<0>, SDTCisPtrTy<1> +]>; +def STDAtomic2 : SDTypeProfile<1, 2, [ + SDTCisSameAs<0,2>, SDTCisInt<0>, SDTCisPtrTy<1> +]>; + +def SDTConvertOp : SDTypeProfile<1, 5, [ //cvtss, su, us, uu, ff, fs, fu, sf, su + SDTCisVT<2, OtherVT>, SDTCisVT<3, OtherVT>, SDTCisPtrTy<4>, SDTCisPtrTy<5> +]>; + +class SDCallSeqStart constraints> : + SDTypeProfile<0, 1, constraints>; +class SDCallSeqEnd constraints> : + SDTypeProfile<0, 2, constraints>; + +//===----------------------------------------------------------------------===// +// Selection DAG Node Properties. +// +// Note: These are hard coded into tblgen. +// +class SDNodeProperty; +def SDNPCommutative : SDNodeProperty; // X op Y == Y op X +def SDNPAssociative : SDNodeProperty; // (X op Y) op Z == X op (Y op Z) +def SDNPHasChain : SDNodeProperty; // R/W chain operand and result +def SDNPOutFlag : SDNodeProperty; // Write a flag result +def SDNPInFlag : SDNodeProperty; // Read a flag operand +def SDNPOptInFlag : SDNodeProperty; // Optionally read a flag operand +def SDNPMayStore : SDNodeProperty; // May write to memory, sets 'mayStore'. +def SDNPMayLoad : SDNodeProperty; // May read memory, sets 'mayLoad'. +def SDNPSideEffect : SDNodeProperty; // Sets 'HasUnmodelledSideEffects'. +def SDNPMemOperand : SDNodeProperty; // Touches memory, has assoc MemOperand + +//===----------------------------------------------------------------------===// +// Selection DAG Node definitions. +// +class SDNode props = [], string sdclass = "SDNode"> { + string Opcode = opcode; + string SDClass = sdclass; + list Properties = props; + SDTypeProfile TypeProfile = typeprof; +} + +// Special TableGen-recognized dag nodes +def set; +def implicit; +def parallel; +def node; +def srcvalue; + +def imm : SDNode<"ISD::Constant" , SDTIntLeaf , [], "ConstantSDNode">; +def timm : SDNode<"ISD::TargetConstant",SDTIntLeaf, [], "ConstantSDNode">; +def fpimm : SDNode<"ISD::ConstantFP", SDTFPLeaf , [], "ConstantFPSDNode">; +def vt : SDNode<"ISD::VALUETYPE" , SDTOther , [], "VTSDNode">; +def bb : SDNode<"ISD::BasicBlock", SDTOther , [], "BasicBlockSDNode">; +def cond : SDNode<"ISD::CONDCODE" , SDTOther , [], "CondCodeSDNode">; +def undef : SDNode<"ISD::UNDEF" , SDTUNDEF , []>; +def globaladdr : SDNode<"ISD::GlobalAddress", SDTPtrLeaf, [], + "GlobalAddressSDNode">; +def tglobaladdr : SDNode<"ISD::TargetGlobalAddress", SDTPtrLeaf, [], + "GlobalAddressSDNode">; +def globaltlsaddr : SDNode<"ISD::GlobalTLSAddress", SDTPtrLeaf, [], + "GlobalAddressSDNode">; +def tglobaltlsaddr : SDNode<"ISD::TargetGlobalTLSAddress", SDTPtrLeaf, [], + "GlobalAddressSDNode">; +def constpool : SDNode<"ISD::ConstantPool", SDTPtrLeaf, [], + "ConstantPoolSDNode">; +def tconstpool : SDNode<"ISD::TargetConstantPool", SDTPtrLeaf, [], + "ConstantPoolSDNode">; +def jumptable : SDNode<"ISD::JumpTable", SDTPtrLeaf, [], + "JumpTableSDNode">; +def tjumptable : SDNode<"ISD::TargetJumpTable", SDTPtrLeaf, [], + "JumpTableSDNode">; +def frameindex : SDNode<"ISD::FrameIndex", SDTPtrLeaf, [], + "FrameIndexSDNode">; +def tframeindex : SDNode<"ISD::TargetFrameIndex", SDTPtrLeaf, [], + "FrameIndexSDNode">; +def externalsym : SDNode<"ISD::ExternalSymbol", SDTPtrLeaf, [], + "ExternalSymbolSDNode">; +def texternalsym: SDNode<"ISD::TargetExternalSymbol", SDTPtrLeaf, [], + "ExternalSymbolSDNode">; +def blockaddress : SDNode<"ISD::BlockAddress", SDTPtrLeaf, [], + "BlockAddressSDNode">; +def tblockaddress: SDNode<"ISD::TargetBlockAddress", SDTPtrLeaf, [], + "BlockAddressSDNode">; + +def add : SDNode<"ISD::ADD" , SDTIntBinOp , + [SDNPCommutative, SDNPAssociative]>; +def sub : SDNode<"ISD::SUB" , SDTIntBinOp>; +def mul : SDNode<"ISD::MUL" , SDTIntBinOp, + [SDNPCommutative, SDNPAssociative]>; +def mulhs : SDNode<"ISD::MULHS" , SDTIntBinOp, [SDNPCommutative]>; +def mulhu : SDNode<"ISD::MULHU" , SDTIntBinOp, [SDNPCommutative]>; +def sdiv : SDNode<"ISD::SDIV" , SDTIntBinOp>; +def udiv : SDNode<"ISD::UDIV" , SDTIntBinOp>; +def srem : SDNode<"ISD::SREM" , SDTIntBinOp>; +def urem : SDNode<"ISD::UREM" , SDTIntBinOp>; +def srl : SDNode<"ISD::SRL" , SDTIntShiftOp>; +def sra : SDNode<"ISD::SRA" , SDTIntShiftOp>; +def shl : SDNode<"ISD::SHL" , SDTIntShiftOp>; +def rotl : SDNode<"ISD::ROTL" , SDTIntShiftOp>; +def rotr : SDNode<"ISD::ROTR" , SDTIntShiftOp>; +def and : SDNode<"ISD::AND" , SDTIntBinOp, + [SDNPCommutative, SDNPAssociative]>; +def or : SDNode<"ISD::OR" , SDTIntBinOp, + [SDNPCommutative, SDNPAssociative]>; +def xor : SDNode<"ISD::XOR" , SDTIntBinOp, + [SDNPCommutative, SDNPAssociative]>; +def addc : SDNode<"ISD::ADDC" , SDTIntBinOp, + [SDNPCommutative, SDNPOutFlag]>; +def adde : SDNode<"ISD::ADDE" , SDTIntBinOp, + [SDNPCommutative, SDNPOutFlag, SDNPInFlag]>; +def subc : SDNode<"ISD::SUBC" , SDTIntBinOp, + [SDNPOutFlag]>; +def sube : SDNode<"ISD::SUBE" , SDTIntBinOp, + [SDNPOutFlag, SDNPInFlag]>; + +def sext_inreg : SDNode<"ISD::SIGN_EXTEND_INREG", SDTExtInreg>; +def bswap : SDNode<"ISD::BSWAP" , SDTIntUnaryOp>; +def ctlz : SDNode<"ISD::CTLZ" , SDTIntUnaryOp>; +def cttz : SDNode<"ISD::CTTZ" , SDTIntUnaryOp>; +def ctpop : SDNode<"ISD::CTPOP" , SDTIntUnaryOp>; +def sext : SDNode<"ISD::SIGN_EXTEND", SDTIntExtendOp>; +def zext : SDNode<"ISD::ZERO_EXTEND", SDTIntExtendOp>; +def anyext : SDNode<"ISD::ANY_EXTEND" , SDTIntExtendOp>; +def trunc : SDNode<"ISD::TRUNCATE" , SDTIntTruncOp>; +def bitconvert : SDNode<"ISD::BIT_CONVERT", SDTUnaryOp>; +def extractelt : SDNode<"ISD::EXTRACT_VECTOR_ELT", SDTVecExtract>; +def insertelt : SDNode<"ISD::INSERT_VECTOR_ELT", SDTVecInsert>; + + +def fadd : SDNode<"ISD::FADD" , SDTFPBinOp, [SDNPCommutative]>; +def fsub : SDNode<"ISD::FSUB" , SDTFPBinOp>; +def fmul : SDNode<"ISD::FMUL" , SDTFPBinOp, [SDNPCommutative]>; +def fdiv : SDNode<"ISD::FDIV" , SDTFPBinOp>; +def frem : SDNode<"ISD::FREM" , SDTFPBinOp>; +def fabs : SDNode<"ISD::FABS" , SDTFPUnaryOp>; +def fneg : SDNode<"ISD::FNEG" , SDTFPUnaryOp>; +def fsqrt : SDNode<"ISD::FSQRT" , SDTFPUnaryOp>; +def fsin : SDNode<"ISD::FSIN" , SDTFPUnaryOp>; +def fcos : SDNode<"ISD::FCOS" , SDTFPUnaryOp>; +def fexp2 : SDNode<"ISD::FEXP2" , SDTFPUnaryOp>; +def flog2 : SDNode<"ISD::FLOG2" , SDTFPUnaryOp>; +def frint : SDNode<"ISD::FRINT" , SDTFPUnaryOp>; +def ftrunc : SDNode<"ISD::FTRUNC" , SDTFPUnaryOp>; +def fceil : SDNode<"ISD::FCEIL" , SDTFPUnaryOp>; +def ffloor : SDNode<"ISD::FFLOOR" , SDTFPUnaryOp>; +def fnearbyint : SDNode<"ISD::FNEARBYINT" , SDTFPUnaryOp>; + +def fround : SDNode<"ISD::FP_ROUND" , SDTFPRoundOp>; +def fextend : SDNode<"ISD::FP_EXTEND" , SDTFPExtendOp>; +def fcopysign : SDNode<"ISD::FCOPYSIGN" , SDTFPSignOp>; + +def sint_to_fp : SDNode<"ISD::SINT_TO_FP" , SDTIntToFPOp>; +def uint_to_fp : SDNode<"ISD::UINT_TO_FP" , SDTIntToFPOp>; +def fp_to_sint : SDNode<"ISD::FP_TO_SINT" , SDTFPToIntOp>; +def fp_to_uint : SDNode<"ISD::FP_TO_UINT" , SDTFPToIntOp>; + +def setcc : SDNode<"ISD::SETCC" , SDTSetCC>; +def select : SDNode<"ISD::SELECT" , SDTSelect>; +def selectcc : SDNode<"ISD::SELECT_CC" , SDTSelectCC>; +def vsetcc : SDNode<"ISD::VSETCC" , SDTSetCC>; + +def brcond : SDNode<"ISD::BRCOND" , SDTBrcond, [SDNPHasChain]>; +def brind : SDNode<"ISD::BRIND" , SDTBrind, [SDNPHasChain]>; +def br : SDNode<"ISD::BR" , SDTBr, [SDNPHasChain]>; +def trap : SDNode<"ISD::TRAP" , SDTNone, + [SDNPHasChain, SDNPSideEffect]>; + +def prefetch : SDNode<"ISD::PREFETCH" , STDPrefetch, + [SDNPHasChain, SDNPMayLoad, SDNPMayStore]>; + +def membarrier : SDNode<"ISD::MEMBARRIER" , STDMemBarrier, + [SDNPHasChain, SDNPSideEffect]>; + +def atomic_cmp_swap : SDNode<"ISD::ATOMIC_CMP_SWAP" , STDAtomic3, + [SDNPHasChain, SDNPMayStore, SDNPMayLoad, SDNPMemOperand]>; +def atomic_load_add : SDNode<"ISD::ATOMIC_LOAD_ADD" , STDAtomic2, + [SDNPHasChain, SDNPMayStore, SDNPMayLoad, SDNPMemOperand]>; +def atomic_swap : SDNode<"ISD::ATOMIC_SWAP", STDAtomic2, + [SDNPHasChain, SDNPMayStore, SDNPMayLoad, SDNPMemOperand]>; +def atomic_load_sub : SDNode<"ISD::ATOMIC_LOAD_SUB" , STDAtomic2, + [SDNPHasChain, SDNPMayStore, SDNPMayLoad, SDNPMemOperand]>; +def atomic_load_and : SDNode<"ISD::ATOMIC_LOAD_AND" , STDAtomic2, + [SDNPHasChain, SDNPMayStore, SDNPMayLoad, SDNPMemOperand]>; +def atomic_load_or : SDNode<"ISD::ATOMIC_LOAD_OR" , STDAtomic2, + [SDNPHasChain, SDNPMayStore, SDNPMayLoad, SDNPMemOperand]>; +def atomic_load_xor : SDNode<"ISD::ATOMIC_LOAD_XOR" , STDAtomic2, + [SDNPHasChain, SDNPMayStore, SDNPMayLoad, SDNPMemOperand]>; +def atomic_load_nand: SDNode<"ISD::ATOMIC_LOAD_NAND", STDAtomic2, + [SDNPHasChain, SDNPMayStore, SDNPMayLoad, SDNPMemOperand]>; +def atomic_load_min : SDNode<"ISD::ATOMIC_LOAD_MIN", STDAtomic2, + [SDNPHasChain, SDNPMayStore, SDNPMayLoad, SDNPMemOperand]>; +def atomic_load_max : SDNode<"ISD::ATOMIC_LOAD_MAX", STDAtomic2, + [SDNPHasChain, SDNPMayStore, SDNPMayLoad, SDNPMemOperand]>; +def atomic_load_umin : SDNode<"ISD::ATOMIC_LOAD_UMIN", STDAtomic2, + [SDNPHasChain, SDNPMayStore, SDNPMayLoad, SDNPMemOperand]>; +def atomic_load_umax : SDNode<"ISD::ATOMIC_LOAD_UMAX", STDAtomic2, + [SDNPHasChain, SDNPMayStore, SDNPMayLoad, SDNPMemOperand]>; + +// Do not use ld, st directly. Use load, extload, sextload, zextload, store, +// and truncst (see below). +def ld : SDNode<"ISD::LOAD" , SDTLoad, + [SDNPHasChain, SDNPMayLoad, SDNPMemOperand]>; +def st : SDNode<"ISD::STORE" , SDTStore, + [SDNPHasChain, SDNPMayStore, SDNPMemOperand]>; +def ist : SDNode<"ISD::STORE" , SDTIStore, + [SDNPHasChain, SDNPMayStore, SDNPMemOperand]>; + +def vector_shuffle : SDNode<"ISD::VECTOR_SHUFFLE", SDTVecShuffle, []>; +def build_vector : SDNode<"ISD::BUILD_VECTOR", SDTypeProfile<1, -1, []>, []>; +def scalar_to_vector : SDNode<"ISD::SCALAR_TO_VECTOR", SDTypeProfile<1, 1, []>, + []>; +def vector_extract : SDNode<"ISD::EXTRACT_VECTOR_ELT", + SDTypeProfile<1, 2, [SDTCisPtrTy<2>]>, []>; +def vector_insert : SDNode<"ISD::INSERT_VECTOR_ELT", + SDTypeProfile<1, 3, [SDTCisSameAs<0, 1>, SDTCisPtrTy<3>]>, []>; + +// Nodes for intrinsics, you should use the intrinsic itself and let tblgen use +// these internally. Don't reference these directly. +def intrinsic_void : SDNode<"ISD::INTRINSIC_VOID", + SDTypeProfile<0, -1, [SDTCisPtrTy<0>]>, + [SDNPHasChain]>; +def intrinsic_w_chain : SDNode<"ISD::INTRINSIC_W_CHAIN", + SDTypeProfile<1, -1, [SDTCisPtrTy<1>]>, + [SDNPHasChain]>; +def intrinsic_wo_chain : SDNode<"ISD::INTRINSIC_WO_CHAIN", + SDTypeProfile<1, -1, [SDTCisPtrTy<1>]>, []>; + +// Do not use cvt directly. Use cvt forms below +def cvt : SDNode<"ISD::CONVERT_RNDSAT", SDTConvertOp>; + +//===----------------------------------------------------------------------===// +// Selection DAG Condition Codes + +class CondCode; // ISD::CondCode enums +def SETOEQ : CondCode; def SETOGT : CondCode; +def SETOGE : CondCode; def SETOLT : CondCode; def SETOLE : CondCode; +def SETONE : CondCode; def SETO : CondCode; def SETUO : CondCode; +def SETUEQ : CondCode; def SETUGT : CondCode; def SETUGE : CondCode; +def SETULT : CondCode; def SETULE : CondCode; def SETUNE : CondCode; + +def SETEQ : CondCode; def SETGT : CondCode; def SETGE : CondCode; +def SETLT : CondCode; def SETLE : CondCode; def SETNE : CondCode; + + +//===----------------------------------------------------------------------===// +// Selection DAG Node Transformation Functions. +// +// This mechanism allows targets to manipulate nodes in the output DAG once a +// match has been formed. This is typically used to manipulate immediate +// values. +// +class SDNodeXForm { + SDNode Opcode = opc; + code XFormFunction = xformFunction; +} + +def NOOP_SDNodeXForm : SDNodeXForm; + + +//===----------------------------------------------------------------------===// +// Selection DAG Pattern Fragments. +// +// Pattern fragments are reusable chunks of dags that match specific things. +// They can take arguments and have C++ predicates that control whether they +// match. They are intended to make the patterns for common instructions more +// compact and readable. +// + +/// PatFrag - Represents a pattern fragment. This can match something on the +/// DAG, frame a single node to multiply nested other fragments. +/// +class PatFrag { + dag Operands = ops; + dag Fragment = frag; + code Predicate = pred; + SDNodeXForm OperandTransform = xform; +} + +// PatLeaf's are pattern fragments that have no operands. This is just a helper +// to define immediates and other common things concisely. +class PatLeaf + : PatFrag<(ops), frag, pred, xform>; + +// Leaf fragments. + +def vtInt : PatLeaf<(vt), [{ return N->getVT().isInteger(); }]>; +def vtFP : PatLeaf<(vt), [{ return N->getVT().isFloatingPoint(); }]>; + +def immAllOnes : PatLeaf<(imm), [{ return N->isAllOnesValue(); }]>; +def immAllOnesV: PatLeaf<(build_vector), [{ + return ISD::isBuildVectorAllOnes(N); +}]>; +def immAllOnesV_bc: PatLeaf<(bitconvert), [{ + return ISD::isBuildVectorAllOnes(N); +}]>; +def immAllZerosV: PatLeaf<(build_vector), [{ + return ISD::isBuildVectorAllZeros(N); +}]>; +def immAllZerosV_bc: PatLeaf<(bitconvert), [{ + return ISD::isBuildVectorAllZeros(N); +}]>; + + + +// Other helper fragments. +def not : PatFrag<(ops node:$in), (xor node:$in, immAllOnes)>; +def vnot : PatFrag<(ops node:$in), (xor node:$in, immAllOnesV)>; +def vnot_conv : PatFrag<(ops node:$in), (xor node:$in, immAllOnesV_bc)>; +def ineg : PatFrag<(ops node:$in), (sub 0, node:$in)>; + +// load fragments. +def unindexedload : PatFrag<(ops node:$ptr), (ld node:$ptr), [{ + return cast(N)->getAddressingMode() == ISD::UNINDEXED; +}]>; +def load : PatFrag<(ops node:$ptr), (unindexedload node:$ptr), [{ + return cast(N)->getExtensionType() == ISD::NON_EXTLOAD; +}]>; + +// extending load fragments. +def extload : PatFrag<(ops node:$ptr), (unindexedload node:$ptr), [{ + return cast(N)->getExtensionType() == ISD::EXTLOAD; +}]>; +def sextload : PatFrag<(ops node:$ptr), (unindexedload node:$ptr), [{ + return cast(N)->getExtensionType() == ISD::SEXTLOAD; +}]>; +def zextload : PatFrag<(ops node:$ptr), (unindexedload node:$ptr), [{ + return cast(N)->getExtensionType() == ISD::ZEXTLOAD; +}]>; + +def extloadi1 : PatFrag<(ops node:$ptr), (extload node:$ptr), [{ + return cast(N)->getMemoryVT() == MVT::i1; +}]>; +def extloadi8 : PatFrag<(ops node:$ptr), (extload node:$ptr), [{ + return cast(N)->getMemoryVT() == MVT::i8; +}]>; +def extloadi16 : PatFrag<(ops node:$ptr), (extload node:$ptr), [{ + return cast(N)->getMemoryVT() == MVT::i16; +}]>; +def extloadi32 : PatFrag<(ops node:$ptr), (extload node:$ptr), [{ + return cast(N)->getMemoryVT() == MVT::i32; +}]>; +def extloadf32 : PatFrag<(ops node:$ptr), (extload node:$ptr), [{ + return cast(N)->getMemoryVT() == MVT::f32; +}]>; +def extloadf64 : PatFrag<(ops node:$ptr), (extload node:$ptr), [{ + return cast(N)->getMemoryVT() == MVT::f64; +}]>; + +def sextloadi1 : PatFrag<(ops node:$ptr), (sextload node:$ptr), [{ + return cast(N)->getMemoryVT() == MVT::i1; +}]>; +def sextloadi8 : PatFrag<(ops node:$ptr), (sextload node:$ptr), [{ + return cast(N)->getMemoryVT() == MVT::i8; +}]>; +def sextloadi16 : PatFrag<(ops node:$ptr), (sextload node:$ptr), [{ + return cast(N)->getMemoryVT() == MVT::i16; +}]>; +def sextloadi32 : PatFrag<(ops node:$ptr), (sextload node:$ptr), [{ + return cast(N)->getMemoryVT() == MVT::i32; +}]>; + +def zextloadi1 : PatFrag<(ops node:$ptr), (zextload node:$ptr), [{ + return cast(N)->getMemoryVT() == MVT::i1; +}]>; +def zextloadi8 : PatFrag<(ops node:$ptr), (zextload node:$ptr), [{ + return cast(N)->getMemoryVT() == MVT::i8; +}]>; +def zextloadi16 : PatFrag<(ops node:$ptr), (zextload node:$ptr), [{ + return cast(N)->getMemoryVT() == MVT::i16; +}]>; +def zextloadi32 : PatFrag<(ops node:$ptr), (zextload node:$ptr), [{ + return cast(N)->getMemoryVT() == MVT::i32; +}]>; + +// store fragments. +def unindexedstore : PatFrag<(ops node:$val, node:$ptr), + (st node:$val, node:$ptr), [{ + return cast(N)->getAddressingMode() == ISD::UNINDEXED; +}]>; +def store : PatFrag<(ops node:$val, node:$ptr), + (unindexedstore node:$val, node:$ptr), [{ + return !cast(N)->isTruncatingStore(); +}]>; + +// truncstore fragments. +def truncstore : PatFrag<(ops node:$val, node:$ptr), + (unindexedstore node:$val, node:$ptr), [{ + return cast(N)->isTruncatingStore(); +}]>; +def truncstorei8 : PatFrag<(ops node:$val, node:$ptr), + (truncstore node:$val, node:$ptr), [{ + return cast(N)->getMemoryVT() == MVT::i8; +}]>; +def truncstorei16 : PatFrag<(ops node:$val, node:$ptr), + (truncstore node:$val, node:$ptr), [{ + return cast(N)->getMemoryVT() == MVT::i16; +}]>; +def truncstorei32 : PatFrag<(ops node:$val, node:$ptr), + (truncstore node:$val, node:$ptr), [{ + return cast(N)->getMemoryVT() == MVT::i32; +}]>; +def truncstoref32 : PatFrag<(ops node:$val, node:$ptr), + (truncstore node:$val, node:$ptr), [{ + return cast(N)->getMemoryVT() == MVT::f32; +}]>; +def truncstoref64 : PatFrag<(ops node:$val, node:$ptr), + (truncstore node:$val, node:$ptr), [{ + return cast(N)->getMemoryVT() == MVT::f64; +}]>; + +// indexed store fragments. +def istore : PatFrag<(ops node:$val, node:$base, node:$offset), + (ist node:$val, node:$base, node:$offset), [{ + return !cast(N)->isTruncatingStore(); +}]>; + +def pre_store : PatFrag<(ops node:$val, node:$base, node:$offset), + (istore node:$val, node:$base, node:$offset), [{ + ISD::MemIndexedMode AM = cast(N)->getAddressingMode(); + return AM == ISD::PRE_INC || AM == ISD::PRE_DEC; +}]>; + +def itruncstore : PatFrag<(ops node:$val, node:$base, node:$offset), + (ist node:$val, node:$base, node:$offset), [{ + return cast(N)->isTruncatingStore(); +}]>; +def pre_truncst : PatFrag<(ops node:$val, node:$base, node:$offset), + (itruncstore node:$val, node:$base, node:$offset), [{ + ISD::MemIndexedMode AM = cast(N)->getAddressingMode(); + return AM == ISD::PRE_INC || AM == ISD::PRE_DEC; +}]>; +def pre_truncsti1 : PatFrag<(ops node:$val, node:$base, node:$offset), + (pre_truncst node:$val, node:$base, node:$offset), [{ + return cast(N)->getMemoryVT() == MVT::i1; +}]>; +def pre_truncsti8 : PatFrag<(ops node:$val, node:$base, node:$offset), + (pre_truncst node:$val, node:$base, node:$offset), [{ + return cast(N)->getMemoryVT() == MVT::i8; +}]>; +def pre_truncsti16 : PatFrag<(ops node:$val, node:$base, node:$offset), + (pre_truncst node:$val, node:$base, node:$offset), [{ + return cast(N)->getMemoryVT() == MVT::i16; +}]>; +def pre_truncsti32 : PatFrag<(ops node:$val, node:$base, node:$offset), + (pre_truncst node:$val, node:$base, node:$offset), [{ + return cast(N)->getMemoryVT() == MVT::i32; +}]>; +def pre_truncstf32 : PatFrag<(ops node:$val, node:$base, node:$offset), + (pre_truncst node:$val, node:$base, node:$offset), [{ + return cast(N)->getMemoryVT() == MVT::f32; +}]>; + +def post_store : PatFrag<(ops node:$val, node:$ptr, node:$offset), + (istore node:$val, node:$ptr, node:$offset), [{ + ISD::MemIndexedMode AM = cast(N)->getAddressingMode(); + return AM == ISD::POST_INC || AM == ISD::POST_DEC; +}]>; + +def post_truncst : PatFrag<(ops node:$val, node:$base, node:$offset), + (itruncstore node:$val, node:$base, node:$offset), [{ + ISD::MemIndexedMode AM = cast(N)->getAddressingMode(); + return AM == ISD::POST_INC || AM == ISD::POST_DEC; +}]>; +def post_truncsti1 : PatFrag<(ops node:$val, node:$base, node:$offset), + (post_truncst node:$val, node:$base, node:$offset), [{ + return cast(N)->getMemoryVT() == MVT::i1; +}]>; +def post_truncsti8 : PatFrag<(ops node:$val, node:$base, node:$offset), + (post_truncst node:$val, node:$base, node:$offset), [{ + return cast(N)->getMemoryVT() == MVT::i8; +}]>; +def post_truncsti16 : PatFrag<(ops node:$val, node:$base, node:$offset), + (post_truncst node:$val, node:$base, node:$offset), [{ + return cast(N)->getMemoryVT() == MVT::i16; +}]>; +def post_truncsti32 : PatFrag<(ops node:$val, node:$base, node:$offset), + (post_truncst node:$val, node:$base, node:$offset), [{ + return cast(N)->getMemoryVT() == MVT::i32; +}]>; +def post_truncstf32 : PatFrag<(ops node:$val, node:$base, node:$offset), + (post_truncst node:$val, node:$base, node:$offset), [{ + return cast(N)->getMemoryVT() == MVT::f32; +}]>; + +// setcc convenience fragments. +def setoeq : PatFrag<(ops node:$lhs, node:$rhs), + (setcc node:$lhs, node:$rhs, SETOEQ)>; +def setogt : PatFrag<(ops node:$lhs, node:$rhs), + (setcc node:$lhs, node:$rhs, SETOGT)>; +def setoge : PatFrag<(ops node:$lhs, node:$rhs), + (setcc node:$lhs, node:$rhs, SETOGE)>; +def setolt : PatFrag<(ops node:$lhs, node:$rhs), + (setcc node:$lhs, node:$rhs, SETOLT)>; +def setole : PatFrag<(ops node:$lhs, node:$rhs), + (setcc node:$lhs, node:$rhs, SETOLE)>; +def setone : PatFrag<(ops node:$lhs, node:$rhs), + (setcc node:$lhs, node:$rhs, SETONE)>; +def seto : PatFrag<(ops node:$lhs, node:$rhs), + (setcc node:$lhs, node:$rhs, SETO)>; +def setuo : PatFrag<(ops node:$lhs, node:$rhs), + (setcc node:$lhs, node:$rhs, SETUO)>; +def setueq : PatFrag<(ops node:$lhs, node:$rhs), + (setcc node:$lhs, node:$rhs, SETUEQ)>; +def setugt : PatFrag<(ops node:$lhs, node:$rhs), + (setcc node:$lhs, node:$rhs, SETUGT)>; +def setuge : PatFrag<(ops node:$lhs, node:$rhs), + (setcc node:$lhs, node:$rhs, SETUGE)>; +def setult : PatFrag<(ops node:$lhs, node:$rhs), + (setcc node:$lhs, node:$rhs, SETULT)>; +def setule : PatFrag<(ops node:$lhs, node:$rhs), + (setcc node:$lhs, node:$rhs, SETULE)>; +def setune : PatFrag<(ops node:$lhs, node:$rhs), + (setcc node:$lhs, node:$rhs, SETUNE)>; +def seteq : PatFrag<(ops node:$lhs, node:$rhs), + (setcc node:$lhs, node:$rhs, SETEQ)>; +def setgt : PatFrag<(ops node:$lhs, node:$rhs), + (setcc node:$lhs, node:$rhs, SETGT)>; +def setge : PatFrag<(ops node:$lhs, node:$rhs), + (setcc node:$lhs, node:$rhs, SETGE)>; +def setlt : PatFrag<(ops node:$lhs, node:$rhs), + (setcc node:$lhs, node:$rhs, SETLT)>; +def setle : PatFrag<(ops node:$lhs, node:$rhs), + (setcc node:$lhs, node:$rhs, SETLE)>; +def setne : PatFrag<(ops node:$lhs, node:$rhs), + (setcc node:$lhs, node:$rhs, SETNE)>; + +def atomic_cmp_swap_8 : + PatFrag<(ops node:$ptr, node:$cmp, node:$swap), + (atomic_cmp_swap node:$ptr, node:$cmp, node:$swap), [{ + return cast(N)->getMemoryVT() == MVT::i8; +}]>; +def atomic_cmp_swap_16 : + PatFrag<(ops node:$ptr, node:$cmp, node:$swap), + (atomic_cmp_swap node:$ptr, node:$cmp, node:$swap), [{ + return cast(N)->getMemoryVT() == MVT::i16; +}]>; +def atomic_cmp_swap_32 : + PatFrag<(ops node:$ptr, node:$cmp, node:$swap), + (atomic_cmp_swap node:$ptr, node:$cmp, node:$swap), [{ + return cast(N)->getMemoryVT() == MVT::i32; +}]>; +def atomic_cmp_swap_64 : + PatFrag<(ops node:$ptr, node:$cmp, node:$swap), + (atomic_cmp_swap node:$ptr, node:$cmp, node:$swap), [{ + return cast(N)->getMemoryVT() == MVT::i64; +}]>; + +multiclass binary_atomic_op { + def _8 : PatFrag<(ops node:$ptr, node:$val), + (atomic_op node:$ptr, node:$val), [{ + return cast(N)->getMemoryVT() == MVT::i8; + }]>; + def _16 : PatFrag<(ops node:$ptr, node:$val), + (atomic_op node:$ptr, node:$val), [{ + return cast(N)->getMemoryVT() == MVT::i16; + }]>; + def _32 : PatFrag<(ops node:$ptr, node:$val), + (atomic_op node:$ptr, node:$val), [{ + return cast(N)->getMemoryVT() == MVT::i32; + }]>; + def _64 : PatFrag<(ops node:$ptr, node:$val), + (atomic_op node:$ptr, node:$val), [{ + return cast(N)->getMemoryVT() == MVT::i64; + }]>; +} + +defm atomic_load_add : binary_atomic_op; +defm atomic_swap : binary_atomic_op; +defm atomic_load_sub : binary_atomic_op; +defm atomic_load_and : binary_atomic_op; +defm atomic_load_or : binary_atomic_op; +defm atomic_load_xor : binary_atomic_op; +defm atomic_load_nand : binary_atomic_op; +defm atomic_load_min : binary_atomic_op; +defm atomic_load_max : binary_atomic_op; +defm atomic_load_umin : binary_atomic_op; +defm atomic_load_umax : binary_atomic_op; + +//===----------------------------------------------------------------------===// +// Selection DAG CONVERT_RNDSAT patterns + +def cvtff : PatFrag<(ops node:$val, node:$dty, node:$sty, node:$rd, node:$sat), + (cvt node:$val, node:$dty, node:$sty, node:$rd, node:$sat), [{ + return cast(N)->getCvtCode() == ISD::CVT_FF; + }]>; + +def cvtss : PatFrag<(ops node:$val, node:$dty, node:$sty, node:$rd, node:$sat), + (cvt node:$val, node:$dty, node:$sty, node:$rd, node:$sat), [{ + return cast(N)->getCvtCode() == ISD::CVT_SS; + }]>; + +def cvtsu : PatFrag<(ops node:$val, node:$dty, node:$sty, node:$rd, node:$sat), + (cvt node:$val, node:$dty, node:$sty, node:$rd, node:$sat), [{ + return cast(N)->getCvtCode() == ISD::CVT_SU; + }]>; + +def cvtus : PatFrag<(ops node:$val, node:$dty, node:$sty, node:$rd, node:$sat), + (cvt node:$val, node:$dty, node:$sty, node:$rd, node:$sat), [{ + return cast(N)->getCvtCode() == ISD::CVT_US; + }]>; + +def cvtuu : PatFrag<(ops node:$val, node:$dty, node:$sty, node:$rd, node:$sat), + (cvt node:$val, node:$dty, node:$sty, node:$rd, node:$sat), [{ + return cast(N)->getCvtCode() == ISD::CVT_UU; + }]>; + +def cvtsf : PatFrag<(ops node:$val, node:$dty, node:$sty, node:$rd, node:$sat), + (cvt node:$val, node:$dty, node:$sty, node:$rd, node:$sat), [{ + return cast(N)->getCvtCode() == ISD::CVT_SF; + }]>; + +def cvtuf : PatFrag<(ops node:$val, node:$dty, node:$sty, node:$rd, node:$sat), + (cvt node:$val, node:$dty, node:$sty, node:$rd, node:$sat), [{ + return cast(N)->getCvtCode() == ISD::CVT_UF; + }]>; + +def cvtfs : PatFrag<(ops node:$val, node:$dty, node:$sty, node:$rd, node:$sat), + (cvt node:$val, node:$dty, node:$sty, node:$rd, node:$sat), [{ + return cast(N)->getCvtCode() == ISD::CVT_FS; + }]>; + +def cvtfu : PatFrag<(ops node:$val, node:$dty, node:$sty, node:$rd, node:$sat), + (cvt node:$val, node:$dty, node:$sty, node:$rd, node:$sat), [{ + return cast(N)->getCvtCode() == ISD::CVT_FU; + }]>; + +//===----------------------------------------------------------------------===// +// Selection DAG Pattern Support. +// +// Patterns are what are actually matched against the target-flavored +// instruction selection DAG. Instructions defined by the target implicitly +// define patterns in most cases, but patterns can also be explicitly added when +// an operation is defined by a sequence of instructions (e.g. loading a large +// immediate value on RISC targets that do not support immediates as large as +// their GPRs). +// + +class Pattern resultInstrs> { + dag PatternToMatch = patternToMatch; + list ResultInstrs = resultInstrs; + list Predicates = []; // See class Instruction in Target.td. + int AddedComplexity = 0; // See class Instruction in Target.td. +} + +// Pat - A simple (but common) form of a pattern, which produces a simple result +// not needing a full list. +class Pat : Pattern; + +//===----------------------------------------------------------------------===// +// Complex pattern definitions. +// + +class CPAttribute; +// Pass the parent Operand as root to CP function rather +// than the root of the sub-DAG +def CPAttrParentAsRoot : CPAttribute; + +// Complex patterns, e.g. X86 addressing mode, requires pattern matching code +// in C++. NumOperands is the number of operands returned by the select function; +// SelectFunc is the name of the function used to pattern match the max. pattern; +// RootNodes are the list of possible root nodes of the sub-dags to match. +// e.g. X86 addressing mode - def addr : ComplexPattern<4, "SelectAddr", [add]>; +// +class ComplexPattern roots = [], list props = [], + list attrs = []> { + ValueType Ty = ty; + int NumOperands = numops; + string SelectFunc = fn; + list RootNodes = roots; + list Properties = props; + list Attributes = attrs; +} diff --git a/libclamav/c++/llvm/include/llvm/Target/TargetSubtarget.h b/libclamav/c++/llvm/include/llvm/Target/TargetSubtarget.h new file mode 100644 index 000000000..22b09bac0 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Target/TargetSubtarget.h @@ -0,0 +1,67 @@ +//==-- llvm/Target/TargetSubtarget.h - Target Information --------*- C++ -*-==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file describes the subtarget options of a Target machine. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TARGET_TARGETSUBTARGET_H +#define LLVM_TARGET_TARGETSUBTARGET_H + +#include "llvm/Target/TargetMachine.h" + +namespace llvm { + +class SDep; +class SUnit; +class TargetRegisterClass; +template class SmallVectorImpl; + +//===----------------------------------------------------------------------===// +/// +/// TargetSubtarget - Generic base class for all target subtargets. All +/// Target-specific options that control code generation and printing should +/// be exposed through a TargetSubtarget-derived class. +/// +class TargetSubtarget { + TargetSubtarget(const TargetSubtarget&); // DO NOT IMPLEMENT + void operator=(const TargetSubtarget&); // DO NOT IMPLEMENT +protected: // Can only create subclasses... + TargetSubtarget(); +public: + // AntiDepBreakMode - Type of anti-dependence breaking that should + // be performed before post-RA scheduling. + typedef enum { ANTIDEP_NONE, ANTIDEP_CRITICAL, ANTIDEP_ALL } AntiDepBreakMode; + typedef SmallVectorImpl RegClassVector; + + virtual ~TargetSubtarget(); + + /// getSpecialAddressLatency - For targets where it is beneficial to + /// backschedule instructions that compute addresses, return a value + /// indicating the number of scheduling cycles of backscheduling that + /// should be attempted. + virtual unsigned getSpecialAddressLatency() const { return 0; } + + // enablePostRAScheduler - If the target can benefit from post-regalloc + // scheduling and the specified optimization level meets the requirement + // return true to enable post-register-allocation scheduling. In + // CriticalPathRCs return any register classes that should only be broken + // if on the critical path. + virtual bool enablePostRAScheduler(CodeGenOpt::Level OptLevel, + AntiDepBreakMode& Mode, + RegClassVector& CriticalPathRCs) const; + // adjustSchedDependency - Perform target specific adjustments to + // the latency of a schedule dependency. + virtual void adjustSchedDependency(SUnit *def, SUnit *use, + SDep& dep) const { } +}; + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Transforms/IPO.h b/libclamav/c++/llvm/include/llvm/Transforms/IPO.h new file mode 100644 index 000000000..5e1790442 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Transforms/IPO.h @@ -0,0 +1,212 @@ +//===- llvm/Transforms/IPO.h - Interprocedural Transformations --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This header file defines prototypes for accessor functions that expose passes +// in the IPO transformations library. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TRANSFORMS_IPO_H +#define LLVM_TRANSFORMS_IPO_H + +#include + +namespace llvm { + +class ModulePass; +class Pass; +class Function; +class BasicBlock; +class GlobalValue; + +//===----------------------------------------------------------------------===// +// +// These functions removes symbols from functions and modules. If OnlyDebugInfo +// is true, only debugging information is removed from the module. +// +ModulePass *createStripSymbolsPass(bool OnlyDebugInfo = false); + +//===----------------------------------------------------------------------===// +// +// These functions strips symbols from functions and modules. +// Only debugging information is not stripped. +// +ModulePass *createStripNonDebugSymbolsPass(); + +//===----------------------------------------------------------------------===// +// +// These pass removes llvm.dbg.declare intrinsics. +ModulePass *createStripDebugDeclarePass(); + +//===----------------------------------------------------------------------===// +/// createLowerSetJmpPass - This function lowers the setjmp/longjmp intrinsics +/// to invoke/unwind instructions. This should really be part of the C/C++ +/// front-end, but it's so much easier to write transformations in LLVM proper. +/// +ModulePass *createLowerSetJmpPass(); + +//===----------------------------------------------------------------------===// +/// createConstantMergePass - This function returns a new pass that merges +/// duplicate global constants together into a single constant that is shared. +/// This is useful because some passes (ie TraceValues) insert a lot of string +/// constants into the program, regardless of whether or not they duplicate an +/// existing string. +/// +ModulePass *createConstantMergePass(); + + +//===----------------------------------------------------------------------===// +/// createGlobalOptimizerPass - This function returns a new pass that optimizes +/// non-address taken internal globals. +/// +ModulePass *createGlobalOptimizerPass(); + + +//===----------------------------------------------------------------------===// +/// createDeadTypeEliminationPass - Return a new pass that eliminates symbol +/// table entries for types that are never used. +/// +ModulePass *createDeadTypeEliminationPass(); + + +//===----------------------------------------------------------------------===// +/// createGlobalDCEPass - This transform is designed to eliminate unreachable +/// internal globals (functions or global variables) +/// +ModulePass *createGlobalDCEPass(); + + +//===----------------------------------------------------------------------===// +/// createGVExtractionPass - If deleteFn is true, this pass deletes as +/// the specified global values. Otherwise, it deletes as much of the module as +/// possible, except for the global values specified. +/// +ModulePass *createGVExtractionPass(std::vector& GVs, bool + deleteFn = false, + bool relinkCallees = false); + +//===----------------------------------------------------------------------===// +/// createFunctionInliningPass - Return a new pass object that uses a heuristic +/// to inline direct function calls to small functions. +/// +Pass *createFunctionInliningPass(); +Pass *createFunctionInliningPass(int Threshold); + +//===----------------------------------------------------------------------===// +/// createAlwaysInlinerPass - Return a new pass object that inlines only +/// functions that are marked as "always_inline". +Pass *createAlwaysInlinerPass(); + +//===----------------------------------------------------------------------===// +/// createPruneEHPass - Return a new pass object which transforms invoke +/// instructions into calls, if the callee can _not_ unwind the stack. +/// +Pass *createPruneEHPass(); + +//===----------------------------------------------------------------------===// +/// createInternalizePass - This pass loops over all of the functions in the +/// input module, internalizing all globals (functions and variables) not part +/// of the api. If a list of symbols is specified with the +/// -internalize-public-api-* command line options, those symbols are not +/// internalized and all others are. Otherwise if AllButMain is set and the +/// main function is found, all other globals are marked as internal. If no api +/// is supplied and AllButMain is not set, or no main function is found, nothing +/// is internalized. +/// +ModulePass *createInternalizePass(bool AllButMain); + +/// createInternalizePass - This pass loops over all of the functions in the +/// input module, internalizing all globals (functions and variables) not in the +/// given exportList. +/// +/// Note that commandline options that are used with the above function are not +/// used now! Also, when exportList is empty, nothing is internalized. +ModulePass *createInternalizePass(const std::vector &exportList); + +//===----------------------------------------------------------------------===// +/// createDeadArgEliminationPass - This pass removes arguments from functions +/// which are not used by the body of the function. +/// +ModulePass *createDeadArgEliminationPass(); + +/// DeadArgHacking pass - Same as DAE, but delete arguments of external +/// functions as well. This is definitely not safe, and should only be used by +/// bugpoint. +ModulePass *createDeadArgHackingPass(); + +//===----------------------------------------------------------------------===// +/// createArgumentPromotionPass - This pass promotes "by reference" arguments to +/// be passed by value if the number of elements passed is smaller or +/// equal to maxElements (maxElements == 0 means always promote). +/// +Pass *createArgumentPromotionPass(unsigned maxElements = 3); +Pass *createStructRetPromotionPass(); + +//===----------------------------------------------------------------------===// +/// createIPConstantPropagationPass - This pass propagates constants from call +/// sites into the bodies of functions. +/// +ModulePass *createIPConstantPropagationPass(); + +//===----------------------------------------------------------------------===// +/// createIPSCCPPass - This pass propagates constants from call sites into the +/// bodies of functions, and keeps track of whether basic blocks are executable +/// in the process. +/// +ModulePass *createIPSCCPPass(); + +//===----------------------------------------------------------------------===// +// +/// createLoopExtractorPass - This pass extracts all natural loops from the +/// program into a function if it can. +/// +Pass *createLoopExtractorPass(); + +/// createSingleLoopExtractorPass - This pass extracts one natural loop from the +/// program into a function if it can. This is used by bugpoint. +/// +Pass *createSingleLoopExtractorPass(); + +/// createBlockExtractorPass - This pass extracts all blocks (except those +/// specified in the argument list) from the functions in the module. +/// +ModulePass *createBlockExtractorPass(const std::vector &BTNE); + +/// createStripDeadPrototypesPass - This pass removes any function declarations +/// (prototypes) that are not used. +ModulePass *createStripDeadPrototypesPass(); + +//===----------------------------------------------------------------------===// +/// createPartialSpecializationPass - This pass specializes functions for +/// constant arguments. +/// +ModulePass *createPartialSpecializationPass(); + +//===----------------------------------------------------------------------===// +/// createFunctionAttrsPass - This pass discovers functions that do not access +/// memory, or only read memory, and gives them the readnone/readonly attribute. +/// It also discovers function arguments that are not captured by the function +/// and marks them with the nocapture attribute. +/// +Pass *createFunctionAttrsPass(); + +//===----------------------------------------------------------------------===// +/// createMergeFunctionsPass - This pass discovers identical functions and +/// collapses them. +/// +ModulePass *createMergeFunctionsPass(); + +//===----------------------------------------------------------------------===// +/// createPartialInliningPass - This pass inlines parts of functions. +/// +ModulePass *createPartialInliningPass(); + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Transforms/IPO/InlinerPass.h b/libclamav/c++/llvm/include/llvm/Transforms/IPO/InlinerPass.h new file mode 100644 index 000000000..5d00f4215 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Transforms/IPO/InlinerPass.h @@ -0,0 +1,86 @@ +//===- InlinerPass.h - Code common to all inliners --------------*- 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 a simple policy-based bottom-up inliner. This file +// implements all of the boring mechanics of the bottom-up inlining, while the +// subclass determines WHAT to inline, which is the much more interesting +// component. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TRANSFORMS_IPO_INLINERPASS_H +#define LLVM_TRANSFORMS_IPO_INLINERPASS_H + +#include "llvm/CallGraphSCCPass.h" + +namespace llvm { + class CallSite; + class TargetData; + class InlineCost; + template + class SmallPtrSet; + +/// Inliner - This class contains all of the helper code which is used to +/// perform the inlining operations that do not depend on the policy. +/// +struct Inliner : public CallGraphSCCPass { + explicit Inliner(void *ID); + explicit Inliner(void *ID, int Threshold); + + /// getAnalysisUsage - For this class, we declare that we require and preserve + /// the call graph. If the derived class implements this method, it should + /// always explicitly call the implementation here. + virtual void getAnalysisUsage(AnalysisUsage &Info) const; + + // Main run interface method, this implements the interface required by the + // Pass class. + virtual bool runOnSCC(std::vector &SCC); + + // doFinalization - Remove now-dead linkonce functions at the end of + // processing to avoid breaking the SCC traversal. + virtual bool doFinalization(CallGraph &CG); + + /// This method returns the value specified by the -inline-threshold value, + /// specified on the command line. This is typically not directly needed. + /// + unsigned getInlineThreshold() const { return InlineThreshold; } + + /// getInlineCost - This method must be implemented by the subclass to + /// determine the cost of inlining the specified call site. If the cost + /// returned is greater than the current inline threshold, the call site is + /// not inlined. + /// + virtual InlineCost getInlineCost(CallSite CS) = 0; + + // getInlineFudgeFactor - Return a > 1.0 factor if the inliner should use a + // higher threshold to determine if the function call should be inlined. + /// + virtual float getInlineFudgeFactor(CallSite CS) = 0; + + /// resetCachedCostInfo - erase any cached cost data from the derived class. + /// If the derived class has no such data this can be empty. + /// + virtual void resetCachedCostInfo(Function* Caller) = 0; + + /// removeDeadFunctions - Remove dead functions that are not included in + /// DNR (Do Not Remove) list. + bool removeDeadFunctions(CallGraph &CG, + SmallPtrSet *DNR = NULL); +private: + // InlineThreshold - Cache the value here for easy access. + unsigned InlineThreshold; + + /// shouldInline - Return true if the inliner should attempt to + /// inline at the given CallSite. + bool shouldInline(CallSite CS); +}; + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Transforms/Instrumentation.h b/libclamav/c++/llvm/include/llvm/Transforms/Instrumentation.h new file mode 100644 index 000000000..9794ffd42 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Transforms/Instrumentation.h @@ -0,0 +1,40 @@ +//===- Transforms/Instrumentation.h - Instrumentation passes ----*- 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 constructor functions for instrumentation passes. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TRANSFORMS_INSTRUMENTATION_H +#define LLVM_TRANSFORMS_INSTRUMENTATION_H + +namespace llvm { + +class ModulePass; +class FunctionPass; + +// Insert function profiling instrumentation +ModulePass *createFunctionProfilerPass(); + +// Insert block profiling instrumentation +ModulePass *createBlockProfilerPass(); + +// Insert edge profiling instrumentation +ModulePass *createEdgeProfilerPass(); + +// Insert optimal edge profiling instrumentation +ModulePass *createOptimalEdgeProfilerPass(); + +// Random Sampling Profiling Framework +ModulePass* createNullProfilerRSPass(); +FunctionPass* createRSProfilingPass(); + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Transforms/RSProfiling.h b/libclamav/c++/llvm/include/llvm/Transforms/RSProfiling.h new file mode 100644 index 000000000..02439e8e2 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Transforms/RSProfiling.h @@ -0,0 +1,42 @@ +//===- RSProfiling.cpp - Various profiling using random sampling ----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the abstract interface that a profiler must implement to +// support the random profiling transform. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TRANSFORMS_RSPROFILING_H +#define LLVM_TRANSFORMS_RSPROFILING_H + +#include "llvm/Pass.h" + +namespace llvm { + class Value; + + //===--------------------------------------------------------------------===// + /// RSProfilers - The basic Random Sampling Profiler Interface Any profiler + /// that implements this interface can be transformed by the random sampling + /// pass to be sample based rather than always on. + /// + /// The only exposed function can be queried to find out if an instruction + /// was original or if it was inserted by the profiler. Implementations of + /// this interface are expected to chain to other implementations, such that + /// multiple profilers can be support simultaniously. + struct RSProfilers : public ModulePass { + static char ID; // Pass identification, replacement for typeinfo + RSProfilers() : ModulePass(&ID) {} + + /// isProfiling - This method returns true if the value passed it was + /// inserted by the profiler. + virtual bool isProfiling(Value* v) = 0; + }; +} + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Transforms/Scalar.h b/libclamav/c++/llvm/include/llvm/Transforms/Scalar.h new file mode 100644 index 000000000..7159f86e1 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Transforms/Scalar.h @@ -0,0 +1,341 @@ +//===-- Scalar.h - Scalar Transformations -----------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This header file defines prototypes for accessor functions that expose passes +// in the Scalar transformations library. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TRANSFORMS_SCALAR_H +#define LLVM_TRANSFORMS_SCALAR_H + +namespace llvm { + +class FunctionPass; +class Pass; +class GetElementPtrInst; +class PassInfo; +class TerminatorInst; +class TargetLowering; + +//===----------------------------------------------------------------------===// +// +// ConstantPropagation - A worklist driven constant propagation pass +// +FunctionPass *createConstantPropagationPass(); + +//===----------------------------------------------------------------------===// +// +// SCCP - Sparse conditional constant propagation. +// +FunctionPass *createSCCPPass(); + +//===----------------------------------------------------------------------===// +// +// DeadInstElimination - This pass quickly removes trivially dead instructions +// without modifying the CFG of the function. It is a BasicBlockPass, so it +// runs efficiently when queued next to other BasicBlockPass's. +// +Pass *createDeadInstEliminationPass(); + +//===----------------------------------------------------------------------===// +// +// DeadCodeElimination - This pass is more powerful than DeadInstElimination, +// because it is worklist driven that can potentially revisit instructions when +// their other instructions become dead, to eliminate chains of dead +// computations. +// +FunctionPass *createDeadCodeEliminationPass(); + +//===----------------------------------------------------------------------===// +// +// DeadStoreElimination - This pass deletes stores that are post-dominated by +// must-aliased stores and are not loaded used between the stores. +// +FunctionPass *createDeadStoreEliminationPass(); + +//===----------------------------------------------------------------------===// +// +// AggressiveDCE - This pass uses the SSA based Aggressive DCE algorithm. This +// algorithm assumes instructions are dead until proven otherwise, which makes +// it more successful are removing non-obviously dead instructions. +// +FunctionPass *createAggressiveDCEPass(); + +//===----------------------------------------------------------------------===// +// +// ScalarReplAggregates - Break up alloca's of aggregates into multiple allocas +// if possible. +// +FunctionPass *createScalarReplAggregatesPass(signed Threshold = -1); + +//===----------------------------------------------------------------------===// +// +// InductionVariableSimplify - Transform induction variables in a program to all +// use a single canonical induction variable per loop. +// +Pass *createIndVarSimplifyPass(); + +//===----------------------------------------------------------------------===// +// +// InstructionCombining - Combine instructions to form fewer, simple +// instructions. This pass does not modify the CFG, and has a tendency to make +// instructions dead, so a subsequent DCE pass is useful. +// +// This pass combines things like: +// %Y = add int 1, %X +// %Z = add int 1, %Y +// into: +// %Z = add int 2, %X +// +FunctionPass *createInstructionCombiningPass(); + +//===----------------------------------------------------------------------===// +// +// LICM - This pass is a loop invariant code motion and memory promotion pass. +// +Pass *createLICMPass(); + +//===----------------------------------------------------------------------===// +// +// LoopStrengthReduce - This pass is strength reduces GEP instructions that use +// a loop's canonical induction variable as one of their indices. It takes an +// optional parameter used to consult the target machine whether certain +// transformations are profitable. +// +Pass *createLoopStrengthReducePass(const TargetLowering *TLI = 0); + +//===----------------------------------------------------------------------===// +// +// LoopUnswitch - This pass is a simple loop unswitching pass. +// +Pass *createLoopUnswitchPass(bool OptimizeForSize = false); + +//===----------------------------------------------------------------------===// +// +// LoopUnroll - This pass is a simple loop unrolling pass. +// +Pass *createLoopUnrollPass(); + +//===----------------------------------------------------------------------===// +// +// LoopRotate - This pass is a simple loop rotating pass. +// +Pass *createLoopRotatePass(); + +//===----------------------------------------------------------------------===// +// +// LoopIndexSplit - This pass divides loop's iteration range by spliting loop +// such that each individual loop is executed efficiently. +// +Pass *createLoopIndexSplitPass(); + +//===----------------------------------------------------------------------===// +// +// PromoteMemoryToRegister - This pass is used to promote memory references to +// be register references. A simple example of the transformation performed by +// this pass is: +// +// FROM CODE TO CODE +// %X = alloca i32, i32 1 ret i32 42 +// store i32 42, i32 *%X +// %Y = load i32* %X +// ret i32 %Y +// +FunctionPass *createPromoteMemoryToRegisterPass(); +extern const PassInfo *const PromoteMemoryToRegisterID; + +//===----------------------------------------------------------------------===// +// +// DemoteRegisterToMemoryPass - This pass is used to demote registers to memory +// references. In basically undoes the PromoteMemoryToRegister pass to make cfg +// hacking easier. +// +FunctionPass *createDemoteRegisterToMemoryPass(); +extern const PassInfo *const DemoteRegisterToMemoryID; + +//===----------------------------------------------------------------------===// +// +// Reassociate - This pass reassociates commutative expressions in an order that +// is designed to promote better constant propagation, GCSE, LICM, PRE... +// +// For example: 4 + (x + 5) -> x + (4 + 5) +// +FunctionPass *createReassociatePass(); + +//===----------------------------------------------------------------------===// +// +// TailDuplication - Eliminate unconditional branches through controlled code +// duplication, creating simpler CFG structures. +// +FunctionPass *createTailDuplicationPass(); + +//===----------------------------------------------------------------------===// +// +// JumpThreading - Thread control through mult-pred/multi-succ blocks where some +// preds always go to some succ. +// +FunctionPass *createJumpThreadingPass(); + +//===----------------------------------------------------------------------===// +// +// CFGSimplification - Merge basic blocks, eliminate unreachable blocks, +// simplify terminator instructions, etc... +// +FunctionPass *createCFGSimplificationPass(); + +//===----------------------------------------------------------------------===// +// +// BreakCriticalEdges - Break all of the critical edges in the CFG by inserting +// a dummy basic block. This pass may be "required" by passes that cannot deal +// with critical edges. For this usage, a pass must call: +// +// AU.addRequiredID(BreakCriticalEdgesID); +// +// This pass obviously invalidates the CFG, but can update forward dominator +// (set, immediate dominators, tree, and frontier) information. +// +FunctionPass *createBreakCriticalEdgesPass(); +extern const PassInfo *const BreakCriticalEdgesID; + +//===----------------------------------------------------------------------===// +// +// LoopSimplify - Insert Pre-header blocks into the CFG for every function in +// the module. This pass updates dominator information, loop information, and +// does not add critical edges to the CFG. +// +// AU.addRequiredID(LoopSimplifyID); +// +Pass *createLoopSimplifyPass(); +extern const PassInfo *const LoopSimplifyID; + +//===----------------------------------------------------------------------===// +// +// TailCallElimination - This pass eliminates call instructions to the current +// function which occur immediately before return instructions. +// +FunctionPass *createTailCallEliminationPass(); + +//===----------------------------------------------------------------------===// +// +// LowerSwitch - This pass converts SwitchInst instructions into a sequence of +// chained binary branch instructions. +// +FunctionPass *createLowerSwitchPass(); +extern const PassInfo *const LowerSwitchID; + +//===----------------------------------------------------------------------===// +// +// LowerInvoke - This pass converts invoke and unwind instructions to use sjlj +// exception handling mechanisms. Note that after this pass runs the CFG is not +// entirely accurate (exceptional control flow edges are not correct anymore) so +// only very simple things should be done after the lowerinvoke pass has run +// (like generation of native code). This should *NOT* be used as a general +// purpose "my LLVM-to-LLVM pass doesn't support the invoke instruction yet" +// lowering pass. +// +FunctionPass *createLowerInvokePass(const TargetLowering *TLI = 0); +extern const PassInfo *const LowerInvokePassID; + +//===----------------------------------------------------------------------===// +// +// BlockPlacement - This pass reorders basic blocks in order to increase the +// number of fall-through conditional branches. +// +FunctionPass *createBlockPlacementPass(); + +//===----------------------------------------------------------------------===// +// +// LCSSA - This pass inserts phi nodes at loop boundaries to simplify other loop +// optimizations. +// +Pass *createLCSSAPass(); +extern const PassInfo *const LCSSAID; + +//===----------------------------------------------------------------------===// +// +// GVN - This pass performs global value numbering and redundant load +// elimination cotemporaneously. +// +FunctionPass *createGVNPass(bool NoPRE = false, bool NoLoads = false); + +//===----------------------------------------------------------------------===// +// +// MemCpyOpt - This pass performs optimizations related to eliminating memcpy +// calls and/or combining multiple stores into memset's. +// +FunctionPass *createMemCpyOptPass(); + +//===----------------------------------------------------------------------===// +// +// LoopDeletion - This pass performs DCE of non-infinite loops that it +// can prove are dead. +// +Pass *createLoopDeletionPass(); + +//===----------------------------------------------------------------------===// +// +/// createSimplifyLibCallsPass - This pass optimizes specific calls to +/// specific well-known (library) functions. +FunctionPass *createSimplifyLibCallsPass(); + +//===----------------------------------------------------------------------===// +// +/// createSimplifyHalfPowrLibCallsPass - This is an experimental pass that +/// optimizes specific half_pow functions. +FunctionPass *createSimplifyHalfPowrLibCallsPass(); + +//===----------------------------------------------------------------------===// +// +// CodeGenPrepare - This pass prepares a function for instruction selection. +// +FunctionPass *createCodeGenPreparePass(const TargetLowering *TLI = 0); + +//===----------------------------------------------------------------------===// +// +// InstructionNamer - Give any unnamed non-void instructions "tmp" names. +// +FunctionPass *createInstructionNamerPass(); +extern const PassInfo *const InstructionNamerID; + +//===----------------------------------------------------------------------===// +// +// SSI - This pass converts instructions to Static Single Information form +// on demand. +// +FunctionPass *createSSIPass(); + +//===----------------------------------------------------------------------===// +// +// SSI - This pass converts every non-void instuction to Static Single +// Information form. +// +FunctionPass *createSSIEverythingPass(); + +//===----------------------------------------------------------------------===// +// +// GEPSplitter - Split complex GEPs into simple ones +// +FunctionPass *createGEPSplitterPass(); + +//===----------------------------------------------------------------------===// +// +// SCCVN - Aggressively eliminate redundant scalar values +// +FunctionPass *createSCCVNPass(); + +//===----------------------------------------------------------------------===// +// +// ABCD - Elimination of Array Bounds Checks on Demand +// +FunctionPass *createABCDPass(); + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Transforms/Utils/AddrModeMatcher.h b/libclamav/c++/llvm/include/llvm/Transforms/Utils/AddrModeMatcher.h new file mode 100644 index 000000000..be601e257 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Transforms/Utils/AddrModeMatcher.h @@ -0,0 +1,102 @@ +//===- AddrModeMatcher.h - Addressing mode matching facility ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// AddressingModeMatcher - This class exposes a single public method, which is +// used to construct a "maximal munch" of the addressing mode for the target +// specified by TLI for an access to "V" with an access type of AccessTy. This +// returns the addressing mode that is actually matched by value, but also +// returns the list of instructions involved in that addressing computation in +// AddrModeInsts. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TRANSFORMS_UTILS_ADDRMODEMATCHER_H +#define LLVM_TRANSFORMS_UTILS_ADDRMODEMATCHER_H + +#include "llvm/ADT/SmallVector.h" +#include "llvm/Target/TargetLowering.h" + +namespace llvm { + +class GlobalValue; +class Instruction; +class Value; +class Type; +class User; +class raw_ostream; + +/// ExtAddrMode - This is an extended version of TargetLowering::AddrMode +/// which holds actual Value*'s for register values. +struct ExtAddrMode : public TargetLowering::AddrMode { + Value *BaseReg; + Value *ScaledReg; + ExtAddrMode() : BaseReg(0), ScaledReg(0) {} + void print(raw_ostream &OS) const; + void dump() const; +}; + +static inline raw_ostream &operator<<(raw_ostream &OS, const ExtAddrMode &AM) { + AM.print(OS); + return OS; +} + +class AddressingModeMatcher { + SmallVectorImpl &AddrModeInsts; + const TargetLowering &TLI; + + /// AccessTy/MemoryInst - This is the type for the access (e.g. double) and + /// the memory instruction that we're computing this address for. + const Type *AccessTy; + Instruction *MemoryInst; + + /// AddrMode - This is the addressing mode that we're building up. This is + /// part of the return value of this addressing mode matching stuff. + ExtAddrMode &AddrMode; + + /// IgnoreProfitability - This is set to true when we should not do + /// profitability checks. When true, IsProfitableToFoldIntoAddressingMode + /// always returns true. + bool IgnoreProfitability; + + AddressingModeMatcher(SmallVectorImpl &AMI, + const TargetLowering &T, const Type *AT, + Instruction *MI, ExtAddrMode &AM) + : AddrModeInsts(AMI), TLI(T), AccessTy(AT), MemoryInst(MI), AddrMode(AM) { + IgnoreProfitability = false; + } +public: + + /// Match - Find the maximal addressing mode that a load/store of V can fold, + /// give an access type of AccessTy. This returns a list of involved + /// instructions in AddrModeInsts. + static ExtAddrMode Match(Value *V, const Type *AccessTy, + Instruction *MemoryInst, + SmallVectorImpl &AddrModeInsts, + const TargetLowering &TLI) { + ExtAddrMode Result; + + bool Success = + AddressingModeMatcher(AddrModeInsts, TLI, AccessTy, + MemoryInst, Result).MatchAddr(V, 0); + Success = Success; assert(Success && "Couldn't select *anything*?"); + return Result; + } +private: + bool MatchScaledValue(Value *ScaleReg, int64_t Scale, unsigned Depth); + bool MatchAddr(Value *V, unsigned Depth); + bool MatchOperationAddr(User *Operation, unsigned Opcode, unsigned Depth); + bool IsProfitableToFoldIntoAddressingMode(Instruction *I, + ExtAddrMode &AMBefore, + ExtAddrMode &AMAfter); + bool ValueAlreadyLiveAtInst(Value *Val, Value *KnownLive1, Value *KnownLive2); +}; + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Transforms/Utils/BasicBlockUtils.h b/libclamav/c++/llvm/include/llvm/Transforms/Utils/BasicBlockUtils.h new file mode 100644 index 000000000..8172114d8 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Transforms/Utils/BasicBlockUtils.h @@ -0,0 +1,202 @@ +//===-- Transform/Utils/BasicBlockUtils.h - BasicBlock Utils ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This family of functions perform manipulations on basic blocks, and +// instructions contained within basic blocks. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TRANSFORMS_UTILS_BASICBLOCK_H +#define LLVM_TRANSFORMS_UTILS_BASICBLOCK_H + +// FIXME: Move to this file: BasicBlock::removePredecessor, BB::splitBasicBlock + +#include "llvm/BasicBlock.h" +#include "llvm/Support/CFG.h" + +namespace llvm { + +class Instruction; +class Pass; +class AliasAnalysis; + +/// DeleteDeadBlock - Delete the specified block, which must have no +/// predecessors. +void DeleteDeadBlock(BasicBlock *BB); + + +/// FoldSingleEntryPHINodes - We know that BB has one predecessor. If there are +/// any single-entry PHI nodes in it, fold them away. This handles the case +/// when all entries to the PHI nodes in a block are guaranteed equal, such as +/// when the block has exactly one predecessor. +void FoldSingleEntryPHINodes(BasicBlock *BB); + +/// DeleteDeadPHIs - Examine each PHI in the given block and delete it if it +/// is dead. Also recursively delete any operands that become dead as +/// a result. This includes tracing the def-use list from the PHI to see if +/// it is ultimately unused or if it reaches an unused cycle. +void DeleteDeadPHIs(BasicBlock *BB); + +/// MergeBlockIntoPredecessor - Attempts to merge a block into its predecessor, +/// if possible. The return value indicates success or failure. +bool MergeBlockIntoPredecessor(BasicBlock* BB, Pass* P = 0); + +// ReplaceInstWithValue - Replace all uses of an instruction (specified by BI) +// with a value, then remove and delete the original instruction. +// +void ReplaceInstWithValue(BasicBlock::InstListType &BIL, + BasicBlock::iterator &BI, Value *V); + +// ReplaceInstWithInst - Replace the instruction specified by BI with the +// instruction specified by I. The original instruction is deleted and BI is +// updated to point to the new instruction. +// +void ReplaceInstWithInst(BasicBlock::InstListType &BIL, + BasicBlock::iterator &BI, Instruction *I); + +// ReplaceInstWithInst - Replace the instruction specified by From with the +// instruction specified by To. +// +void ReplaceInstWithInst(Instruction *From, Instruction *To); + +/// CopyPrecedingStopPoint - If I is immediately preceded by a StopPoint, +/// make a copy of the stoppoint before InsertPos (presumably before copying +/// or moving I). +void CopyPrecedingStopPoint(Instruction *I, BasicBlock::iterator InsertPos); + +/// FindAvailableLoadedValue - Scan the ScanBB block backwards (starting at the +/// instruction before ScanFrom) checking to see if we have the value at the +/// memory address *Ptr locally available within a small number of instructions. +/// If the value is available, return it. +/// +/// If not, return the iterator for the last validated instruction that the +/// value would be live through. If we scanned the entire block and didn't find +/// something that invalidates *Ptr or provides it, ScanFrom would be left at +/// begin() and this returns null. ScanFrom could also be left +/// +/// MaxInstsToScan specifies the maximum instructions to scan in the block. If +/// it is set to 0, it will scan the whole block. You can also optionally +/// specify an alias analysis implementation, which makes this more precise. +Value *FindAvailableLoadedValue(Value *Ptr, BasicBlock *ScanBB, + BasicBlock::iterator &ScanFrom, + unsigned MaxInstsToScan = 6, + AliasAnalysis *AA = 0); + +/// FindFunctionBackedges - Analyze the specified function to find all of the +/// loop backedges in the function and return them. This is a relatively cheap +/// (compared to computing dominators and loop info) analysis. +/// +/// The output is added to Result, as pairs of edge info. +void FindFunctionBackedges(const Function &F, + SmallVectorImpl > &Result); + + +// RemoveSuccessor - Change the specified terminator instruction such that its +// successor #SuccNum no longer exists. Because this reduces the outgoing +// degree of the current basic block, the actual terminator instruction itself +// may have to be changed. In the case where the last successor of the block is +// deleted, a return instruction is inserted in its place which can cause a +// suprising change in program behavior if it is not expected. +// +void RemoveSuccessor(TerminatorInst *TI, unsigned SuccNum); + +/// isCriticalEdge - Return true if the specified edge is a critical edge. +/// Critical edges are edges from a block with multiple successors to a block +/// with multiple predecessors. +/// +bool isCriticalEdge(const TerminatorInst *TI, unsigned SuccNum, + bool AllowIdenticalEdges = false); + +/// SplitCriticalEdge - If this edge is a critical edge, insert a new node to +/// split the critical edge. This will update DominatorTree and +/// DominatorFrontier information if it is available, thus calling this pass +/// will not invalidate either of them. This returns the new block if the edge +/// was split, null otherwise. +/// +/// If MergeIdenticalEdges is true (not the default), *all* edges from TI to the +/// specified successor will be merged into the same critical edge block. +/// This is most commonly interesting with switch instructions, which may +/// have many edges to any one destination. This ensures that all edges to that +/// dest go to one block instead of each going to a different block, but isn't +/// the standard definition of a "critical edge". +/// +/// It is invalid to call this function on a critical edge that starts at an +/// IndirectBrInst. Splitting these edges will almost always create an invalid +/// program because the address of the new block won't be the one that is jumped +/// to. +/// +BasicBlock *SplitCriticalEdge(TerminatorInst *TI, unsigned SuccNum, + Pass *P = 0, bool MergeIdenticalEdges = false); + +inline BasicBlock *SplitCriticalEdge(BasicBlock *BB, succ_iterator SI, + Pass *P = 0) { + return SplitCriticalEdge(BB->getTerminator(), SI.getSuccessorIndex(), P); +} + +/// SplitCriticalEdge - If the edge from *PI to BB is not critical, return +/// false. Otherwise, split all edges between the two blocks and return true. +/// This updates all of the same analyses as the other SplitCriticalEdge +/// function. If P is specified, it updates the analyses +/// described above. +inline bool SplitCriticalEdge(BasicBlock *Succ, pred_iterator PI, Pass *P = 0) { + bool MadeChange = false; + TerminatorInst *TI = (*PI)->getTerminator(); + for (unsigned i = 0, e = TI->getNumSuccessors(); i != e; ++i) + if (TI->getSuccessor(i) == Succ) + MadeChange |= !!SplitCriticalEdge(TI, i, P); + return MadeChange; +} + +/// SplitCriticalEdge - If an edge from Src to Dst is critical, split the edge +/// and return true, otherwise return false. This method requires that there be +/// an edge between the two blocks. If P is specified, it updates the analyses +/// described above. +inline BasicBlock *SplitCriticalEdge(BasicBlock *Src, BasicBlock *Dst, + Pass *P = 0, + bool MergeIdenticalEdges = false) { + TerminatorInst *TI = Src->getTerminator(); + unsigned i = 0; + while (1) { + assert(i != TI->getNumSuccessors() && "Edge doesn't exist!"); + if (TI->getSuccessor(i) == Dst) + return SplitCriticalEdge(TI, i, P, MergeIdenticalEdges); + ++i; + } +} + +/// SplitEdge - Split the edge connecting specified block. Pass P must +/// not be NULL. +BasicBlock *SplitEdge(BasicBlock *From, BasicBlock *To, Pass *P); + +/// SplitBlock - Split the specified block at the specified instruction - every +/// thing before SplitPt stays in Old and everything starting with SplitPt moves +/// to a new block. The two blocks are joined by an unconditional branch and +/// the loop info is updated. +/// +BasicBlock *SplitBlock(BasicBlock *Old, Instruction *SplitPt, Pass *P); + +/// SplitBlockPredecessors - This method transforms BB by introducing a new +/// basic block into the function, and moving some of the predecessors of BB to +/// be predecessors of the new block. The new predecessors are indicated by the +/// Preds array, which has NumPreds elements in it. The new block is given a +/// suffix of 'Suffix'. This function returns the new block. +/// +/// This currently updates the LLVM IR, AliasAnalysis, DominatorTree, +/// DominanceFrontier, LoopInfo, and LCCSA but no other analyses. +/// In particular, it does not preserve LoopSimplify (because it's +/// complicated to handle the case where one of the edges being split +/// is an exit of a loop with other exits). +/// +BasicBlock *SplitBlockPredecessors(BasicBlock *BB, BasicBlock *const *Preds, + unsigned NumPreds, const char *Suffix, + Pass *P = 0); + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Transforms/Utils/BasicInliner.h b/libclamav/c++/llvm/include/llvm/Transforms/Utils/BasicInliner.h new file mode 100644 index 000000000..4bca6b8c4 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Transforms/Utils/BasicInliner.h @@ -0,0 +1,55 @@ +//===- BasicInliner.h - Basic function level inliner ------------*- 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 a simple function based inliner that does not use +// call graph information. +// +//===----------------------------------------------------------------------===// + +#ifndef BASICINLINER_H +#define BASICINLINER_H + +#include "llvm/Analysis/InlineCost.h" + +namespace llvm { + + class Function; + class TargetData; + struct BasicInlinerImpl; + + /// BasicInliner - BasicInliner provides function level inlining interface. + /// Clients provide list of functions which are inline without using + /// module level call graph information. Note that the BasicInliner is + /// free to delete a function if it is inlined into all call sites. + class BasicInliner { + public: + + explicit BasicInliner(TargetData *T = NULL); + ~BasicInliner(); + + /// addFunction - Add function into the list of functions to process. + /// All functions must be inserted using this interface before invoking + /// inlineFunctions(). + void addFunction(Function *F); + + /// neverInlineFunction - Sometimes a function is never to be inlined + /// because of one or other reason. + void neverInlineFunction(Function *F); + + /// inlineFuctions - Walk all call sites in all functions supplied by + /// client. Inline as many call sites as possible. Delete completely + /// inlined functions. + void inlineFunctions(); + + private: + BasicInlinerImpl *Impl; + }; +} + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Transforms/Utils/Cloning.h b/libclamav/c++/llvm/include/llvm/Transforms/Utils/Cloning.h new file mode 100644 index 000000000..e9099f878 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Transforms/Utils/Cloning.h @@ -0,0 +1,186 @@ +//===- Cloning.h - Clone various parts of LLVM programs ---------*- 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 various functions that are used to clone chunks of LLVM +// code for various purposes. This varies from copying whole modules into new +// modules, to cloning functions with different arguments, to inlining +// functions, to copying basic blocks to support loop unrolling or superblock +// formation, etc. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TRANSFORMS_UTILS_CLONING_H +#define LLVM_TRANSFORMS_UTILS_CLONING_H + +#include "llvm/ADT/DenseMap.h" + +namespace llvm { + +class Module; +class Function; +class Instruction; +class Pass; +class LPPassManager; +class BasicBlock; +class Value; +class CallInst; +class InvokeInst; +class ReturnInst; +class CallSite; +class Trace; +class CallGraph; +class TargetData; +class Loop; +class LoopInfo; +class LLVMContext; +class AllocaInst; +template class SmallVectorImpl; + +/// CloneModule - Return an exact copy of the specified module +/// +Module *CloneModule(const Module *M); +Module *CloneModule(const Module *M, DenseMap &ValueMap); + +/// ClonedCodeInfo - This struct can be used to capture information about code +/// being cloned, while it is being cloned. +struct ClonedCodeInfo { + /// ContainsCalls - This is set to true if the cloned code contains a normal + /// call instruction. + bool ContainsCalls; + + /// ContainsUnwinds - This is set to true if the cloned code contains an + /// unwind instruction. + bool ContainsUnwinds; + + /// ContainsDynamicAllocas - This is set to true if the cloned code contains + /// a 'dynamic' alloca. Dynamic allocas are allocas that are either not in + /// the entry block or they are in the entry block but are not a constant + /// size. + bool ContainsDynamicAllocas; + + ClonedCodeInfo() { + ContainsCalls = false; + ContainsUnwinds = false; + ContainsDynamicAllocas = false; + } +}; + + +/// CloneBasicBlock - Return a copy of the specified basic block, but without +/// embedding the block into a particular function. The block returned is an +/// exact copy of the specified basic block, without any remapping having been +/// performed. Because of this, this is only suitable for applications where +/// the basic block will be inserted into the same function that it was cloned +/// from (loop unrolling would use this, for example). +/// +/// Also, note that this function makes a direct copy of the basic block, and +/// can thus produce illegal LLVM code. In particular, it will copy any PHI +/// nodes from the original block, even though there are no predecessors for the +/// newly cloned block (thus, phi nodes will have to be updated). Also, this +/// block will branch to the old successors of the original block: these +/// successors will have to have any PHI nodes updated to account for the new +/// incoming edges. +/// +/// The correlation between instructions in the source and result basic blocks +/// is recorded in the ValueMap map. +/// +/// If you have a particular suffix you'd like to use to add to any cloned +/// names, specify it as the optional third parameter. +/// +/// If you would like the basic block to be auto-inserted into the end of a +/// function, you can specify it as the optional fourth parameter. +/// +/// If you would like to collect additional information about the cloned +/// function, you can specify a ClonedCodeInfo object with the optional fifth +/// parameter. +/// +BasicBlock *CloneBasicBlock(const BasicBlock *BB, + DenseMap &ValueMap, + const char *NameSuffix = "", Function *F = 0, + ClonedCodeInfo *CodeInfo = 0); + + +/// CloneLoop - Clone Loop. Clone dominator info for loop insiders. Populate +/// ValueMap using old blocks to new blocks mapping. +Loop *CloneLoop(Loop *L, LPPassManager *LPM, LoopInfo *LI, + DenseMap &ValueMap, Pass *P); + +/// CloneFunction - Return a copy of the specified function, but without +/// embedding the function into another module. Also, any references specified +/// in the ValueMap are changed to refer to their mapped value instead of the +/// original one. If any of the arguments to the function are in the ValueMap, +/// the arguments are deleted from the resultant function. The ValueMap is +/// updated to include mappings from all of the instructions and basicblocks in +/// the function from their old to new values. The final argument captures +/// information about the cloned code if non-null. +/// +Function *CloneFunction(const Function *F, + DenseMap &ValueMap, + ClonedCodeInfo *CodeInfo = 0); + +/// CloneFunction - Version of the function that doesn't need the ValueMap. +/// +inline Function *CloneFunction(const Function *F, ClonedCodeInfo *CodeInfo = 0){ + DenseMap ValueMap; + return CloneFunction(F, ValueMap, CodeInfo); +} + +/// Clone OldFunc into NewFunc, transforming the old arguments into references +/// to ArgMap values. Note that if NewFunc already has basic blocks, the ones +/// cloned into it will be added to the end of the function. This function +/// fills in a list of return instructions, and can optionally append the +/// specified suffix to all values cloned. +/// +void CloneFunctionInto(Function *NewFunc, const Function *OldFunc, + DenseMap &ValueMap, + SmallVectorImpl &Returns, + const char *NameSuffix = "", + ClonedCodeInfo *CodeInfo = 0); + +/// CloneAndPruneFunctionInto - This works exactly like CloneFunctionInto, +/// except that it does some simple constant prop and DCE on the fly. The +/// effect of this is to copy significantly less code in cases where (for +/// example) a function call with constant arguments is inlined, and those +/// constant arguments cause a significant amount of code in the callee to be +/// dead. Since this doesn't produce an exactly copy of the input, it can't be +/// used for things like CloneFunction or CloneModule. +void CloneAndPruneFunctionInto(Function *NewFunc, const Function *OldFunc, + DenseMap &ValueMap, + SmallVectorImpl &Returns, + const char *NameSuffix = "", + ClonedCodeInfo *CodeInfo = 0, + const TargetData *TD = 0, + Instruction *TheCall = 0); + +/// InlineFunction - This function inlines the called function into the basic +/// block of the caller. This returns false if it is not possible to inline +/// this call. The program is still in a well defined state if this occurs +/// though. +/// +/// Note that this only does one level of inlining. For example, if the +/// instruction 'call B' is inlined, and 'B' calls 'C', then the call to 'C' now +/// exists in the instruction stream. Similiarly this will inline a recursive +/// function by one level. +/// +/// If a non-null callgraph pointer is provided, these functions update the +/// CallGraph to represent the program after inlining. +/// +/// If StaticAllocas is non-null, InlineFunction populates it with all of the +/// static allocas that it inlines into the caller. +/// +bool InlineFunction(CallInst *C, CallGraph *CG = 0, const TargetData *TD = 0, + SmallVectorImpl *StaticAllocas = 0); +bool InlineFunction(InvokeInst *II, CallGraph *CG = 0, const TargetData *TD = 0, + SmallVectorImpl *StaticAllocas = 0); +bool InlineFunction(CallSite CS, CallGraph *CG = 0, const TargetData *TD = 0, + SmallVectorImpl *StaticAllocas = 0); + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Transforms/Utils/FunctionUtils.h b/libclamav/c++/llvm/include/llvm/Transforms/Utils/FunctionUtils.h new file mode 100644 index 000000000..785b08f82 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Transforms/Utils/FunctionUtils.h @@ -0,0 +1,41 @@ +//===-- Transform/Utils/FunctionUtils.h - Function Utils --------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This family of transformations manipulate LLVM functions. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TRANSFORMS_UTILS_FUNCTION_H +#define LLVM_TRANSFORMS_UTILS_FUNCTION_H + +#include + +namespace llvm { + class BasicBlock; + class DominatorTree; + class Function; + class Loop; + + /// ExtractCodeRegion - rip out a sequence of basic blocks into a new function + /// + Function* ExtractCodeRegion(DominatorTree& DT, + const std::vector &code, + bool AggregateArgs = false); + + /// ExtractLoop - rip out a natural loop into a new function + /// + Function* ExtractLoop(DominatorTree& DT, Loop *L, + bool AggregateArgs = false); + + /// ExtractBasicBlock - rip out a basic block into a new function + /// + Function* ExtractBasicBlock(BasicBlock *BB, bool AggregateArgs = false); +} + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Transforms/Utils/Local.h b/libclamav/c++/llvm/include/llvm/Transforms/Utils/Local.h new file mode 100644 index 000000000..e6687bb24 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Transforms/Utils/Local.h @@ -0,0 +1,157 @@ +//===-- Local.h - Functions to perform local transformations ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This family of functions perform various local transformations to the +// program. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TRANSFORMS_UTILS_LOCAL_H +#define LLVM_TRANSFORMS_UTILS_LOCAL_H + +namespace llvm { + +class User; +class BasicBlock; +class BranchInst; +class Instruction; +class Value; +class Pass; +class PHINode; +class AllocaInst; +class ConstantExpr; +class TargetData; +class LLVMContext; +struct DbgInfoIntrinsic; + +template class SmallVectorImpl; + +//===----------------------------------------------------------------------===// +// Local analysis. +// + +/// isSafeToLoadUnconditionally - Return true if we know that executing a load +/// from this value cannot trap. If it is not obviously safe to load from the +/// specified pointer, we do a quick local scan of the basic block containing +/// ScanFrom, to determine if the address is already accessed. +bool isSafeToLoadUnconditionally(Value *V, Instruction *ScanFrom); + +//===----------------------------------------------------------------------===// +// Local constant propagation. +// + +/// ConstantFoldTerminator - If a terminator instruction is predicated on a +/// constant value, convert it into an unconditional branch to the constant +/// destination. This is a nontrivial operation because the successors of this +/// basic block must have their PHI nodes updated. +/// +bool ConstantFoldTerminator(BasicBlock *BB); + +//===----------------------------------------------------------------------===// +// Local dead code elimination. +// + +/// isInstructionTriviallyDead - Return true if the result produced by the +/// instruction is not used, and the instruction has no side effects. +/// +bool isInstructionTriviallyDead(Instruction *I); + +/// RecursivelyDeleteTriviallyDeadInstructions - If the specified value is a +/// trivially dead instruction, delete it. If that makes any of its operands +/// trivially dead, delete them too, recursively. +void RecursivelyDeleteTriviallyDeadInstructions(Value *V); + +/// RecursivelyDeleteDeadPHINode - If the specified value is an effectively +/// dead PHI node, due to being a def-use chain of single-use nodes that +/// either forms a cycle or is terminated by a trivially dead instruction, +/// delete it. If that makes any of its operands trivially dead, delete them +/// too, recursively. +void RecursivelyDeleteDeadPHINode(PHINode *PN); + +//===----------------------------------------------------------------------===// +// Control Flow Graph Restructuring. +// + +/// RemovePredecessorAndSimplify - Like BasicBlock::removePredecessor, this +/// method is called when we're about to delete Pred as a predecessor of BB. If +/// BB contains any PHI nodes, this drops the entries in the PHI nodes for Pred. +/// +/// Unlike the removePredecessor method, this attempts to simplify uses of PHI +/// nodes that collapse into identity values. For example, if we have: +/// x = phi(1, 0, 0, 0) +/// y = and x, z +/// +/// .. and delete the predecessor corresponding to the '1', this will attempt to +/// recursively fold the 'and' to 0. +void RemovePredecessorAndSimplify(BasicBlock *BB, BasicBlock *Pred, + TargetData *TD = 0); + + +/// MergeBasicBlockIntoOnlyPred - BB is a block with one predecessor and its +/// predecessor is known to have one successor (BB!). Eliminate the edge +/// between them, moving the instructions in the predecessor into BB. This +/// deletes the predecessor block. +/// +void MergeBasicBlockIntoOnlyPred(BasicBlock *BB, Pass *P = 0); + + +/// TryToSimplifyUncondBranchFromEmptyBlock - BB is known to contain an +/// unconditional branch, and contains no instructions other than PHI nodes, +/// potential debug intrinsics and the branch. If possible, eliminate BB by +/// rewriting all the predecessors to branch to the successor block and return +/// true. If we can't transform, return false. +bool TryToSimplifyUncondBranchFromEmptyBlock(BasicBlock *BB); + +/// EliminateDuplicatePHINodes - Check for and eliminate duplicate PHI +/// nodes in this block. This doesn't try to be clever about PHI nodes +/// which differ only in the order of the incoming values, but instcombine +/// orders them so it usually won't matter. +/// +bool EliminateDuplicatePHINodes(BasicBlock *BB); + +/// SimplifyCFG - This function is used to do simplification of a CFG. For +/// example, it adjusts branches to branches to eliminate the extra hop, it +/// eliminates unreachable basic blocks, and does other "peephole" optimization +/// of the CFG. It returns true if a modification was made, possibly deleting +/// the basic block that was pointed to. +/// +/// WARNING: The entry node of a method may not be simplified. +/// +bool SimplifyCFG(BasicBlock *BB); + +/// FoldBranchToCommonDest - If this basic block is ONLY a setcc and a branch, +/// and if a predecessor branches to us and one of our successors, fold the +/// setcc into the predecessor and use logical operations to pick the right +/// destination. +bool FoldBranchToCommonDest(BranchInst *BI); + +/// DemoteRegToStack - This function takes a virtual register computed by an +/// Instruction and replaces it with a slot in the stack frame, allocated via +/// alloca. This allows the CFG to be changed around without fear of +/// invalidating the SSA information for the value. It returns the pointer to +/// the alloca inserted to create a stack slot for X. +/// +AllocaInst *DemoteRegToStack(Instruction &X, + bool VolatileLoads = false, + Instruction *AllocaPoint = 0); + +/// DemotePHIToStack - This function takes a virtual register computed by a phi +/// node and replaces it with a slot in the stack frame, allocated via alloca. +/// The phi node is deleted and it returns the pointer to the alloca inserted. +AllocaInst *DemotePHIToStack(PHINode *P, Instruction *AllocaPoint = 0); + +/// OnlyUsedByDbgIntrinsics - Return true if the instruction I is only used +/// by DbgIntrinsics. If DbgInUses is specified then the vector is filled +/// with DbgInfoIntrinsic that use the instruction I. +bool OnlyUsedByDbgInfoIntrinsics(Instruction *I, + SmallVectorImpl *DbgInUses = 0); + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Transforms/Utils/PromoteMemToReg.h b/libclamav/c++/llvm/include/llvm/Transforms/Utils/PromoteMemToReg.h new file mode 100644 index 000000000..35cfaddb7 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Transforms/Utils/PromoteMemToReg.h @@ -0,0 +1,46 @@ +//===- PromoteMemToReg.h - Promote Allocas to Scalars -----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file exposes an interface to promote alloca instructions to SSA +// registers, by using the SSA construction algorithm. +// +//===----------------------------------------------------------------------===// + +#ifndef TRANSFORMS_UTILS_PROMOTEMEMTOREG_H +#define TRANSFORMS_UTILS_PROMOTEMEMTOREG_H + +#include + +namespace llvm { + +class AllocaInst; +class DominatorTree; +class DominanceFrontier; +class AliasSetTracker; + +/// isAllocaPromotable - Return true if this alloca is legal for promotion. +/// This is true if there are only loads and stores to the alloca... +/// +bool isAllocaPromotable(const AllocaInst *AI); + +/// PromoteMemToReg - Promote the specified list of alloca instructions into +/// scalar registers, inserting PHI nodes as appropriate. This function makes +/// use of DominanceFrontier information. This function does not modify the CFG +/// of the function at all. All allocas must be from the same function. +/// +/// If AST is specified, the specified tracker is updated to reflect changes +/// made to the IR. +/// +void PromoteMemToReg(const std::vector &Allocas, + DominatorTree &DT, DominanceFrontier &DF, + AliasSetTracker *AST = 0); + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Transforms/Utils/SSAUpdater.h b/libclamav/c++/llvm/include/llvm/Transforms/Utils/SSAUpdater.h new file mode 100644 index 000000000..23643301a --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Transforms/Utils/SSAUpdater.h @@ -0,0 +1,108 @@ +//===-- SSAUpdater.h - Unstructured SSA Update Tool -------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the SSAUpdater class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TRANSFORMS_UTILS_SSAUPDATER_H +#define LLVM_TRANSFORMS_UTILS_SSAUPDATER_H + +namespace llvm { + class Value; + class BasicBlock; + class Use; + class PHINode; + template + class SmallVectorImpl; + +/// SSAUpdater - This class updates SSA form for a set of values defined in +/// multiple blocks. This is used when code duplication or another unstructured +/// transformation wants to rewrite a set of uses of one value with uses of a +/// set of values. +class SSAUpdater { + /// AvailableVals - This keeps track of which value to use on a per-block + /// basis. When we insert PHI nodes, we keep track of them here. We use + /// WeakVH's for the value of the map because we RAUW PHI nodes when we + /// eliminate them, and want the WeakVH to track this. + //typedef DenseMap > AvailableValsTy; + void *AV; + + /// PrototypeValue is an arbitrary representative value, which we derive names + /// and a type for PHI nodes. + Value *PrototypeValue; + + /// IncomingPredInfo - We use this as scratch space when doing our recursive + /// walk. This should only be used in GetValueInBlockInternal, normally it + /// should be empty. + //std::vector > > IncomingPredInfo; + void *IPI; + + /// InsertedPHIs - If this is non-null, the SSAUpdater adds all PHI nodes that + /// it creates to the vector. + SmallVectorImpl *InsertedPHIs; +public: + /// SSAUpdater constructor. If InsertedPHIs is specified, it will be filled + /// in with all PHI Nodes created by rewriting. + explicit SSAUpdater(SmallVectorImpl *InsertedPHIs = 0); + ~SSAUpdater(); + + /// Initialize - Reset this object to get ready for a new set of SSA + /// updates. ProtoValue is the value used to name PHI nodes. + void Initialize(Value *ProtoValue); + + /// AddAvailableValue - Indicate that a rewritten value is available at the + /// end of the specified block with the specified value. + void AddAvailableValue(BasicBlock *BB, Value *V); + + /// HasValueForBlock - Return true if the SSAUpdater already has a value for + /// the specified block. + bool HasValueForBlock(BasicBlock *BB) const; + + /// GetValueAtEndOfBlock - Construct SSA form, materializing a value that is + /// live at the end of the specified block. + Value *GetValueAtEndOfBlock(BasicBlock *BB); + + /// GetValueInMiddleOfBlock - Construct SSA form, materializing a value that + /// is live in the middle of the specified block. + /// + /// GetValueInMiddleOfBlock is the same as GetValueAtEndOfBlock except in one + /// important case: if there is a definition of the rewritten value after the + /// 'use' in BB. Consider code like this: + /// + /// X1 = ... + /// SomeBB: + /// use(X) + /// X2 = ... + /// br Cond, SomeBB, OutBB + /// + /// In this case, there are two values (X1 and X2) added to the AvailableVals + /// set by the client of the rewriter, and those values are both live out of + /// their respective blocks. However, the use of X happens in the *middle* of + /// a block. Because of this, we need to insert a new PHI node in SomeBB to + /// merge the appropriate values, and this value isn't live out of the block. + /// + Value *GetValueInMiddleOfBlock(BasicBlock *BB); + + /// RewriteUse - Rewrite a use of the symbolic value. This handles PHI nodes, + /// which use their value in the corresponding predecessor. Note that this + /// will not work if the use is supposed to be rewritten to a value defined in + /// the same block as the use, but above it. Any 'AddAvailableValue's added + /// for the use's block will be considered to be below it. + void RewriteUse(Use &U); + +private: + Value *GetValueAtEndOfBlockInternal(BasicBlock *BB); + void operator=(const SSAUpdater&); // DO NOT IMPLEMENT + SSAUpdater(const SSAUpdater&); // DO NOT IMPLEMENT +}; + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Transforms/Utils/SSI.h b/libclamav/c++/llvm/include/llvm/Transforms/Utils/SSI.h new file mode 100644 index 000000000..198fc827b --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Transforms/Utils/SSI.h @@ -0,0 +1,93 @@ +//===------------------- SSI.h - Creates SSI Representation -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This pass converts a list of variables to the Static Single Information +// form. This is a program representation described by Scott Ananian in his +// Master Thesis: "The Static Single Information Form (1999)". +// We are building an on-demand representation, that is, we do not convert +// every single variable in the target function to SSI form. Rather, we receive +// a list of target variables that must be converted. We also do not +// completely convert a target variable to the SSI format. Instead, we only +// change the variable in the points where new information can be attached +// to its live range, that is, at branch points. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TRANSFORMS_UTILS_SSI_H +#define LLVM_TRANSFORMS_UTILS_SSI_H + +#include "llvm/InstrTypes.h" +#include "llvm/Pass.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallVector.h" + +namespace llvm { + + class DominatorTree; + class PHINode; + class Instruction; + class CmpInst; + + class SSI : public FunctionPass { + public: + static char ID; // Pass identification, replacement for typeid. + SSI() : + FunctionPass(&ID) { + } + + void getAnalysisUsage(AnalysisUsage &AU) const; + + bool runOnFunction(Function&); + + void createSSI(SmallVectorImpl &value); + + private: + // Variables always live + DominatorTree *DT_; + + // Stores variables created by SSI + SmallPtrSet created; + + // Phis created by SSI + DenseMap phis; + + // Sigmas created by SSI + DenseMap sigmas; + + // Phi nodes that have a phi as operand and has to be fixed + SmallPtrSet phisToFix; + + // List of definition points for every variable + DenseMap > defsites; + + // Basic Block of the original definition of each variable + DenseMap value_original; + + // Stack of last seen definition of a variable + DenseMap > value_stack; + + void insertSigmaFunctions(SmallPtrSet &value); + void insertSigma(TerminatorInst *TI, Instruction *I); + void insertPhiFunctions(SmallPtrSet &value); + void renameInit(SmallPtrSet &value); + void rename(BasicBlock *BB); + + void substituteUse(Instruction *I); + bool dominateAny(BasicBlock *BB, Instruction *value); + void fixPhis(); + + Instruction* getPositionPhi(PHINode *PN); + Instruction* getPositionSigma(PHINode *PN); + + void init(SmallVectorImpl &value); + void clean(); + }; +} // end namespace +#endif diff --git a/libclamav/c++/llvm/include/llvm/Transforms/Utils/UnifyFunctionExitNodes.h b/libclamav/c++/llvm/include/llvm/Transforms/Utils/UnifyFunctionExitNodes.h new file mode 100644 index 000000000..c2d09935e --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Transforms/Utils/UnifyFunctionExitNodes.h @@ -0,0 +1,49 @@ +//===-- UnifyFunctionExitNodes.h - Ensure fn's have one return --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This pass is used to ensure that functions have at most one return and one +// unwind instruction in them. Additionally, it keeps track of which node is +// the new exit node of the CFG. If there are no return or unwind instructions +// in the function, the getReturnBlock/getUnwindBlock methods will return a null +// pointer. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TRANSFORMS_UNIFYFUNCTIONEXITNODES_H +#define LLVM_TRANSFORMS_UNIFYFUNCTIONEXITNODES_H + +#include "llvm/Pass.h" + +namespace llvm { + +struct UnifyFunctionExitNodes : public FunctionPass { + BasicBlock *ReturnBlock, *UnwindBlock, *UnreachableBlock; +public: + static char ID; // Pass identification, replacement for typeid + UnifyFunctionExitNodes() : FunctionPass(&ID), + ReturnBlock(0), UnwindBlock(0) {} + + // We can preserve non-critical-edgeness when we unify function exit nodes + virtual void getAnalysisUsage(AnalysisUsage &AU) const; + + // getReturn|Unwind|UnreachableBlock - Return the new single (or nonexistant) + // return, unwind, or unreachable basic blocks in the CFG. + // + BasicBlock *getReturnBlock() const { return ReturnBlock; } + BasicBlock *getUnwindBlock() const { return UnwindBlock; } + BasicBlock *getUnreachableBlock() const { return UnreachableBlock; } + + virtual bool runOnFunction(Function &F); +}; + +Pass *createUnifyFunctionExitNodesPass(); + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Transforms/Utils/UnrollLoop.h b/libclamav/c++/llvm/include/llvm/Transforms/Utils/UnrollLoop.h new file mode 100644 index 000000000..3d5ee1a62 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Transforms/Utils/UnrollLoop.h @@ -0,0 +1,29 @@ +//===- llvm/Transforms/Utils/UnrollLoop.h - Unrolling utilities -*- 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 some loop unrolling utilities. It does not define any +// actual pass or policy, but provides a single function to perform loop +// unrolling. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TRANSFORMS_UTILS_UNROLLLOOP_H +#define LLVM_TRANSFORMS_UTILS_UNROLLLOOP_H + +namespace llvm { + +class Loop; +class LoopInfo; +class LPPassManager; + +bool UnrollLoop(Loop *L, unsigned Count, LoopInfo* LI, LPPassManager* LPM); + +} + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Transforms/Utils/ValueMapper.h b/libclamav/c++/llvm/include/llvm/Transforms/Utils/ValueMapper.h new file mode 100644 index 000000000..ed3341364 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Transforms/Utils/ValueMapper.h @@ -0,0 +1,29 @@ +//===- ValueMapper.h - Interface shared by lib/Transforms/Utils -*- 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 the MapValue interface which is used by various parts of +// the Transforms/Utils library to implement cloning and linking facilities. +// +//===----------------------------------------------------------------------===// + +#ifndef VALUEMAPPER_H +#define VALUEMAPPER_H + +#include "llvm/ADT/DenseMap.h" + +namespace llvm { + class Value; + class Instruction; + typedef DenseMap ValueMapTy; + + Value *MapValue(const Value *V, ValueMapTy &VM); + void RemapInstruction(Instruction *I, ValueMapTy &VM); +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Type.h b/libclamav/c++/llvm/include/llvm/Type.h new file mode 100644 index 000000000..752635c68 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Type.h @@ -0,0 +1,529 @@ +//===-- llvm/Type.h - Classes for handling data types -----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + + +#ifndef LLVM_TYPE_H +#define LLVM_TYPE_H + +#include "llvm/AbstractTypeUser.h" +#include "llvm/Support/Casting.h" +#include "llvm/System/DataTypes.h" +#include "llvm/System/Atomic.h" +#include "llvm/ADT/GraphTraits.h" +#include +#include + +namespace llvm { + +class DerivedType; +class PointerType; +class IntegerType; +class TypeMapBase; +class raw_ostream; +class Module; +class LLVMContext; + +/// This file contains the declaration of the Type class. For more "Type" type +/// stuff, look in DerivedTypes.h. +/// +/// The instances of the Type class are immutable: once they are created, +/// they are never changed. Also note that only one instance of a particular +/// type is ever created. Thus seeing if two types are equal is a matter of +/// doing a trivial pointer comparison. To enforce that no two equal instances +/// are created, Type instances can only be created via static factory methods +/// in class Type and in derived classes. +/// +/// Once allocated, Types are never free'd, unless they are an abstract type +/// that is resolved to a more concrete type. +/// +/// Types themself don't have a name, and can be named either by: +/// - using SymbolTable instance, typically from some Module, +/// - using convenience methods in the Module class (which uses module's +/// SymbolTable too). +/// +/// Opaque types are simple derived types with no state. There may be many +/// different Opaque type objects floating around, but two are only considered +/// identical if they are pointer equals of each other. This allows us to have +/// two opaque types that end up resolving to different concrete types later. +/// +/// Opaque types are also kinda weird and scary and different because they have +/// to keep a list of uses of the type. When, through linking, parsing, or +/// bitcode reading, they become resolved, they need to find and update all +/// users of the unknown type, causing them to reference a new, more concrete +/// type. Opaque types are deleted when their use list dwindles to zero users. +/// +/// @brief Root of type hierarchy +class Type : public AbstractTypeUser { +public: + //===-------------------------------------------------------------------===// + /// Definitions of all of the base types for the Type system. Based on this + /// value, you can cast to a "DerivedType" subclass (see DerivedTypes.h) + /// Note: If you add an element to this, you need to add an element to the + /// Type::getPrimitiveType function, or else things will break! + /// Also update LLVMTypeKind and LLVMGetTypeKind () in the C binding. + /// + enum TypeID { + // PrimitiveTypes .. make sure LastPrimitiveTyID stays up to date + VoidTyID = 0, ///< 0: type with no size + FloatTyID, ///< 1: 32 bit floating point type + DoubleTyID, ///< 2: 64 bit floating point type + X86_FP80TyID, ///< 3: 80 bit floating point type (X87) + FP128TyID, ///< 4: 128 bit floating point type (112-bit mantissa) + PPC_FP128TyID, ///< 5: 128 bit floating point type (two 64-bits) + LabelTyID, ///< 6: Labels + MetadataTyID, ///< 7: Metadata + + // Derived types... see DerivedTypes.h file... + // Make sure FirstDerivedTyID stays up to date!!! + IntegerTyID, ///< 8: Arbitrary bit width integers + FunctionTyID, ///< 9: Functions + StructTyID, ///< 10: Structures + ArrayTyID, ///< 11: Arrays + PointerTyID, ///< 12: Pointers + OpaqueTyID, ///< 13: Opaque: type with unknown structure + VectorTyID, ///< 14: SIMD 'packed' format, or other vector type + + NumTypeIDs, // Must remain as last defined ID + LastPrimitiveTyID = LabelTyID, + FirstDerivedTyID = IntegerTyID + }; + +private: + TypeID ID : 8; // The current base type of this type. + bool Abstract : 1; // True if type contains an OpaqueType + unsigned SubclassData : 23; //Space for subclasses to store data + + /// RefCount - This counts the number of PATypeHolders that are pointing to + /// this type. When this number falls to zero, if the type is abstract and + /// has no AbstractTypeUsers, the type is deleted. This is only sensical for + /// derived types. + /// + mutable sys::cas_flag RefCount; + + /// Context - This refers to the LLVMContext in which this type was uniqued. + LLVMContext &Context; + friend class LLVMContextImpl; + + const Type *getForwardedTypeInternal() const; + + // Some Type instances are allocated as arrays, some aren't. So we provide + // this method to get the right kind of destruction for the type of Type. + void destroy() const; // const is a lie, this does "delete this"! + +protected: + explicit Type(LLVMContext &C, TypeID id) : + ID(id), Abstract(false), SubclassData(0), + RefCount(0), Context(C), + ForwardType(0), NumContainedTys(0), + ContainedTys(0) {} + virtual ~Type() { + assert(AbstractTypeUsers.empty() && "Abstract types remain"); + } + + /// Types can become nonabstract later, if they are refined. + /// + inline void setAbstract(bool Val) { Abstract = Val; } + + unsigned getRefCount() const { return RefCount; } + + unsigned getSubclassData() const { return SubclassData; } + void setSubclassData(unsigned val) { SubclassData = val; } + + /// ForwardType - This field is used to implement the union find scheme for + /// abstract types. When types are refined to other types, this field is set + /// to the more refined type. Only abstract types can be forwarded. + mutable const Type *ForwardType; + + + /// AbstractTypeUsers - Implement a list of the users that need to be notified + /// if I am a type, and I get resolved into a more concrete type. + /// + mutable std::vector AbstractTypeUsers; + + /// NumContainedTys - Keeps track of how many PATypeHandle instances there + /// are at the end of this type instance for the list of contained types. It + /// is the subclasses responsibility to set this up. Set to 0 if there are no + /// contained types in this type. + unsigned NumContainedTys; + + /// ContainedTys - A pointer to the array of Types (PATypeHandle) contained + /// by this Type. For example, this includes the arguments of a function + /// type, the elements of a structure, the pointee of a pointer, the element + /// type of an array, etc. This pointer may be 0 for types that don't + /// contain other types (Integer, Double, Float). In general, the subclass + /// should arrange for space for the PATypeHandles to be included in the + /// allocation of the type object and set this pointer to the address of the + /// first element. This allows the Type class to manipulate the ContainedTys + /// without understanding the subclass's placement for this array. keeping + /// it here also allows the subtype_* members to be implemented MUCH more + /// efficiently, and dynamically very few types do not contain any elements. + PATypeHandle *ContainedTys; + +public: + void print(raw_ostream &O) const; + + /// @brief Debugging support: print to stderr + void dump() const; + + /// @brief Debugging support: print to stderr (use type names from context + /// module). + void dump(const Module *Context) const; + + /// getContext - Fetch the LLVMContext in which this type was uniqued. + LLVMContext &getContext() const { return Context; } + + //===--------------------------------------------------------------------===// + // Property accessors for dealing with types... Some of these virtual methods + // are defined in private classes defined in Type.cpp for primitive types. + // + + /// getTypeID - Return the type id for the type. This will return one + /// of the TypeID enum elements defined above. + /// + inline TypeID getTypeID() const { return ID; } + + /// isVoidTy - Return true if this is 'void'. + bool isVoidTy() const { return ID == VoidTyID; } + + /// isFloatTy - Return true if this is 'float', a 32-bit IEEE fp type. + bool isFloatTy() const { return ID == FloatTyID; } + + /// isDoubleTy - Return true if this is 'double', a 64-bit IEEE fp type. + bool isDoubleTy() const { return ID == DoubleTyID; } + + /// isX86_FP80Ty - Return true if this is x86 long double. + bool isX86_FP80Ty() const { return ID == X86_FP80TyID; } + + /// isFP128Ty - Return true if this is 'fp128'. + bool isFP128Ty() const { return ID == FP128TyID; } + + /// isPPC_FP128Ty - Return true if this is powerpc long double. + bool isPPC_FP128Ty() const { return ID == PPC_FP128TyID; } + + /// isLabelTy - Return true if this is 'label'. + bool isLabelTy() const { return ID == LabelTyID; } + + /// isMetadataTy - Return true if this is 'metadata'. + bool isMetadataTy() const { return ID == MetadataTyID; } + + /// getDescription - Return the string representation of the type. + std::string getDescription() const; + + /// isInteger - True if this is an instance of IntegerType. + /// + bool isInteger() const { return ID == IntegerTyID; } + + /// isIntOrIntVector - Return true if this is an integer type or a vector of + /// integer types. + /// + bool isIntOrIntVector() const; + + /// isFloatingPoint - Return true if this is one of the five floating point + /// types + bool isFloatingPoint() const { return ID == FloatTyID || ID == DoubleTyID || + ID == X86_FP80TyID || ID == FP128TyID || ID == PPC_FP128TyID; } + + /// isFPOrFPVector - Return true if this is a FP type or a vector of FP types. + /// + bool isFPOrFPVector() const; + + /// isAbstract - True if the type is either an Opaque type, or is a derived + /// type that includes an opaque type somewhere in it. + /// + inline bool isAbstract() const { return Abstract; } + + /// canLosslesslyBitCastTo - Return true if this type could be converted + /// with a lossless BitCast to type 'Ty'. For example, i8* to i32*. BitCasts + /// are valid for types of the same size only where no re-interpretation of + /// the bits is done. + /// @brief Determine if this type could be losslessly bitcast to Ty + bool canLosslesslyBitCastTo(const Type *Ty) const; + + + /// Here are some useful little methods to query what type derived types are + /// Note that all other types can just compare to see if this == Type::xxxTy; + /// + inline bool isPrimitiveType() const { return ID <= LastPrimitiveTyID; } + inline bool isDerivedType() const { return ID >= FirstDerivedTyID; } + + /// isFirstClassType - Return true if the type is "first class", meaning it + /// is a valid type for a Value. + /// + inline bool isFirstClassType() const { + // There are more first-class kinds than non-first-class kinds, so a + // negative test is simpler than a positive one. + return ID != FunctionTyID && ID != VoidTyID && ID != OpaqueTyID; + } + + /// isSingleValueType - Return true if the type is a valid type for a + /// virtual register in codegen. This includes all first-class types + /// except struct and array types. + /// + inline bool isSingleValueType() const { + return (ID != VoidTyID && ID <= LastPrimitiveTyID) || + ID == IntegerTyID || ID == PointerTyID || ID == VectorTyID; + } + + /// isAggregateType - Return true if the type is an aggregate type. This + /// means it is valid as the first operand of an insertvalue or + /// extractvalue instruction. This includes struct and array types, but + /// does not include vector types. + /// + inline bool isAggregateType() const { + return ID == StructTyID || ID == ArrayTyID; + } + + /// isSized - Return true if it makes sense to take the size of this type. To + /// get the actual size for a particular target, it is reasonable to use the + /// TargetData subsystem to do this. + /// + bool isSized() const { + // If it's a primitive, it is always sized. + if (ID == IntegerTyID || isFloatingPoint() || ID == PointerTyID) + return true; + // If it is not something that can have a size (e.g. a function or label), + // it doesn't have a size. + if (ID != StructTyID && ID != ArrayTyID && ID != VectorTyID) + return false; + // If it is something that can have a size and it's concrete, it definitely + // has a size, otherwise we have to try harder to decide. + return !isAbstract() || isSizedDerivedType(); + } + + /// getPrimitiveSizeInBits - Return the basic size of this type if it is a + /// primitive type. These are fixed by LLVM and are not target dependent. + /// This will return zero if the type does not have a size or is not a + /// primitive type. + /// + /// Note that this may not reflect the size of memory allocated for an + /// instance of the type or the number of bytes that are written when an + /// instance of the type is stored to memory. The TargetData class provides + /// additional query functions to provide this information. + /// + unsigned getPrimitiveSizeInBits() const; + + /// getScalarSizeInBits - If this is a vector type, return the + /// getPrimitiveSizeInBits value for the element type. Otherwise return the + /// getPrimitiveSizeInBits value for this type. + unsigned getScalarSizeInBits() const; + + /// getFPMantissaWidth - Return the width of the mantissa of this type. This + /// is only valid on floating point types. If the FP type does not + /// have a stable mantissa (e.g. ppc long double), this method returns -1. + int getFPMantissaWidth() const; + + /// getForwardedType - Return the type that this type has been resolved to if + /// it has been resolved to anything. This is used to implement the + /// union-find algorithm for type resolution, and shouldn't be used by general + /// purpose clients. + const Type *getForwardedType() const { + if (!ForwardType) return 0; + return getForwardedTypeInternal(); + } + + /// getVAArgsPromotedType - Return the type an argument of this type + /// will be promoted to if passed through a variable argument + /// function. + const Type *getVAArgsPromotedType(LLVMContext &C) const; + + /// getScalarType - If this is a vector type, return the element type, + /// otherwise return this. + const Type *getScalarType() const; + + //===--------------------------------------------------------------------===// + // Type Iteration support + // + typedef PATypeHandle *subtype_iterator; + subtype_iterator subtype_begin() const { return ContainedTys; } + subtype_iterator subtype_end() const { return &ContainedTys[NumContainedTys];} + + /// getContainedType - This method is used to implement the type iterator + /// (defined a the end of the file). For derived types, this returns the + /// types 'contained' in the derived type. + /// + const Type *getContainedType(unsigned i) const { + assert(i < NumContainedTys && "Index out of range!"); + return ContainedTys[i].get(); + } + + /// getNumContainedTypes - Return the number of types in the derived type. + /// + unsigned getNumContainedTypes() const { return NumContainedTys; } + + //===--------------------------------------------------------------------===// + // Static members exported by the Type class itself. Useful for getting + // instances of Type. + // + + /// getPrimitiveType - Return a type based on an identifier. + static const Type *getPrimitiveType(LLVMContext &C, TypeID IDNumber); + + //===--------------------------------------------------------------------===// + // These are the builtin types that are always available... + // + static const Type *getVoidTy(LLVMContext &C); + static const Type *getLabelTy(LLVMContext &C); + static const Type *getFloatTy(LLVMContext &C); + static const Type *getDoubleTy(LLVMContext &C); + static const Type *getMetadataTy(LLVMContext &C); + static const Type *getX86_FP80Ty(LLVMContext &C); + static const Type *getFP128Ty(LLVMContext &C); + static const Type *getPPC_FP128Ty(LLVMContext &C); + static const IntegerType *getInt1Ty(LLVMContext &C); + static const IntegerType *getInt8Ty(LLVMContext &C); + static const IntegerType *getInt16Ty(LLVMContext &C); + static const IntegerType *getInt32Ty(LLVMContext &C); + static const IntegerType *getInt64Ty(LLVMContext &C); + + //===--------------------------------------------------------------------===// + // Convenience methods for getting pointer types with one of the above builtin + // types as pointee. + // + static const PointerType *getFloatPtrTy(LLVMContext &C, unsigned AS = 0); + static const PointerType *getDoublePtrTy(LLVMContext &C, unsigned AS = 0); + static const PointerType *getX86_FP80PtrTy(LLVMContext &C, unsigned AS = 0); + static const PointerType *getFP128PtrTy(LLVMContext &C, unsigned AS = 0); + static const PointerType *getPPC_FP128PtrTy(LLVMContext &C, unsigned AS = 0); + static const PointerType *getInt1PtrTy(LLVMContext &C, unsigned AS = 0); + static const PointerType *getInt8PtrTy(LLVMContext &C, unsigned AS = 0); + static const PointerType *getInt16PtrTy(LLVMContext &C, unsigned AS = 0); + static const PointerType *getInt32PtrTy(LLVMContext &C, unsigned AS = 0); + static const PointerType *getInt64PtrTy(LLVMContext &C, unsigned AS = 0); + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const Type *) { return true; } + + void addRef() const { + assert(isAbstract() && "Cannot add a reference to a non-abstract type!"); + sys::AtomicIncrement(&RefCount); + } + + void dropRef() const { + assert(isAbstract() && "Cannot drop a reference to a non-abstract type!"); + assert(RefCount && "No objects are currently referencing this object!"); + + // If this is the last PATypeHolder using this object, and there are no + // PATypeHandles using it, the type is dead, delete it now. + sys::cas_flag OldCount = sys::AtomicDecrement(&RefCount); + if (OldCount == 0 && AbstractTypeUsers.empty()) + this->destroy(); + } + + /// addAbstractTypeUser - Notify an abstract type that there is a new user of + /// it. This function is called primarily by the PATypeHandle class. + /// + void addAbstractTypeUser(AbstractTypeUser *U) const; + + /// removeAbstractTypeUser - Notify an abstract type that a user of the class + /// no longer has a handle to the type. This function is called primarily by + /// the PATypeHandle class. When there are no users of the abstract type, it + /// is annihilated, because there is no way to get a reference to it ever + /// again. + /// + void removeAbstractTypeUser(AbstractTypeUser *U) const; + + /// getPointerTo - Return a pointer to the current type. This is equivalent + /// to PointerType::get(Foo, AddrSpace). + const PointerType *getPointerTo(unsigned AddrSpace = 0) const; + +private: + /// isSizedDerivedType - Derived types like structures and arrays are sized + /// iff all of the members of the type are sized as well. Since asking for + /// their size is relatively uncommon, move this operation out of line. + bool isSizedDerivedType() const; + + virtual void refineAbstractType(const DerivedType *OldTy, const Type *NewTy); + virtual void typeBecameConcrete(const DerivedType *AbsTy); + +protected: + // PromoteAbstractToConcrete - This is an internal method used to calculate + // change "Abstract" from true to false when types are refined. + void PromoteAbstractToConcrete(); + friend class TypeMapBase; +}; + +//===----------------------------------------------------------------------===// +// Define some inline methods for the AbstractTypeUser.h:PATypeHandle class. +// These are defined here because they MUST be inlined, yet are dependent on +// the definition of the Type class. +// +inline void PATypeHandle::addUser() { + assert(Ty && "Type Handle has a null type!"); + if (Ty->isAbstract()) + Ty->addAbstractTypeUser(User); +} +inline void PATypeHandle::removeUser() { + if (Ty->isAbstract()) + Ty->removeAbstractTypeUser(User); +} + +// Define inline methods for PATypeHolder. + +/// get - This implements the forwarding part of the union-find algorithm for +/// abstract types. Before every access to the Type*, we check to see if the +/// type we are pointing to is forwarding to a new type. If so, we drop our +/// reference to the type. +/// +inline Type* PATypeHolder::get() const { + const Type *NewTy = Ty->getForwardedType(); + if (!NewTy) return const_cast(Ty); + return *const_cast(this) = NewTy; +} + +inline void PATypeHolder::addRef() { + assert(Ty && "Type Holder has a null type!"); + if (Ty->isAbstract()) + Ty->addRef(); +} + +inline void PATypeHolder::dropRef() { + if (Ty->isAbstract()) + Ty->dropRef(); +} + + +//===----------------------------------------------------------------------===// +// Provide specializations of GraphTraits to be able to treat a type as a +// graph of sub types... + +template <> struct GraphTraits { + typedef Type NodeType; + typedef Type::subtype_iterator ChildIteratorType; + + static inline NodeType *getEntryNode(Type *T) { return T; } + static inline ChildIteratorType child_begin(NodeType *N) { + return N->subtype_begin(); + } + static inline ChildIteratorType child_end(NodeType *N) { + return N->subtype_end(); + } +}; + +template <> struct GraphTraits { + typedef const Type NodeType; + typedef Type::subtype_iterator ChildIteratorType; + + static inline NodeType *getEntryNode(const Type *T) { return T; } + static inline ChildIteratorType child_begin(NodeType *N) { + return N->subtype_begin(); + } + static inline ChildIteratorType child_end(NodeType *N) { + return N->subtype_end(); + } +}; + +template <> inline bool isa_impl(const Type &Ty) { + return Ty.getTypeID() == Type::PointerTyID; +} + +raw_ostream &operator<<(raw_ostream &OS, const Type &T); + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/TypeSymbolTable.h b/libclamav/c++/llvm/include/llvm/TypeSymbolTable.h new file mode 100644 index 000000000..26b1dbf2d --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/TypeSymbolTable.h @@ -0,0 +1,153 @@ +//===-- llvm/TypeSymbolTable.h - Implement a Type Symtab --------*- 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 the name/type symbol table for LLVM. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TYPE_SYMBOL_TABLE_H +#define LLVM_TYPE_SYMBOL_TABLE_H + +#include "llvm/Type.h" +#include "llvm/ADT/StringRef.h" +#include + +namespace llvm { + +class StringRef; + +/// This class provides a symbol table of name/type pairs with operations to +/// support constructing, searching and iterating over the symbol table. The +/// class derives from AbstractTypeUser so that the contents of the symbol +/// table can be updated when abstract types become concrete. +class TypeSymbolTable : public AbstractTypeUser { + +/// @name Types +/// @{ +public: + + /// @brief A mapping of names to types. + typedef std::map TypeMap; + + /// @brief An iterator over the TypeMap. + typedef TypeMap::iterator iterator; + + /// @brief A const_iterator over the TypeMap. + typedef TypeMap::const_iterator const_iterator; + +/// @} +/// @name Constructors +/// @{ +public: + + TypeSymbolTable():LastUnique(0) {} + ~TypeSymbolTable(); + +/// @} +/// @name Accessors +/// @{ +public: + + /// Generates a unique name for a type based on the \p BaseName by + /// incrementing an integer and appending it to the name, if necessary + /// @returns the unique name + /// @brief Get a unique name for a type + std::string getUniqueName(StringRef BaseName) const; + + /// This method finds the type with the given \p name in the type map + /// and returns it. + /// @returns null if the name is not found, otherwise the Type + /// associated with the \p name. + /// @brief Lookup a type by name. + Type *lookup(StringRef name) const; + + /// Lookup the type associated with name. + /// @returns end() if the name is not found, or an iterator at the entry for + /// Type. + iterator find(StringRef Name) { + return tmap.find(Name); + } + + /// Lookup the type associated with name. + /// @returns end() if the name is not found, or an iterator at the entry for + /// Type. + const_iterator find(StringRef Name) const { + return tmap.find(Name); + } + + /// @returns true iff the symbol table is empty. + /// @brief Determine if the symbol table is empty + inline bool empty() const { return tmap.empty(); } + + /// @returns the size of the symbol table + /// @brief The number of name/type pairs is returned. + inline unsigned size() const { return unsigned(tmap.size()); } + + /// This function can be used from the debugger to display the + /// content of the symbol table while debugging. + /// @brief Print out symbol table on stderr + void dump() const; + +/// @} +/// @name Iteration +/// @{ +public: + /// Get an iterator to the start of the symbol table + inline iterator begin() { return tmap.begin(); } + + /// @brief Get a const_iterator to the start of the symbol table + inline const_iterator begin() const { return tmap.begin(); } + + /// Get an iterator to the end of the symbol table. + inline iterator end() { return tmap.end(); } + + /// Get a const_iterator to the end of the symbol table. + inline const_iterator end() const { return tmap.end(); } + +/// @} +/// @name Mutators +/// @{ +public: + + /// Inserts a type into the symbol table with the specified name. There can be + /// a many-to-one mapping between names and types. This method allows a type + /// with an existing entry in the symbol table to get a new name. + /// @brief Insert a type under a new name. + void insert(StringRef Name, const Type *Typ); + + /// Remove a type at the specified position in the symbol table. + /// @returns the removed Type. + /// @returns the Type that was erased from the symbol table. + Type* remove(iterator TI); + +/// @} +/// @name AbstractTypeUser Methods +/// @{ +private: + /// This function is called when one of the types in the type plane + /// is refined. + virtual void refineAbstractType(const DerivedType *OldTy, const Type *NewTy); + + /// This function markes a type as being concrete (defined). + virtual void typeBecameConcrete(const DerivedType *AbsTy); + +/// @} +/// @name Internal Data +/// @{ +private: + TypeMap tmap; ///< This is the mapping of names to types. + mutable uint32_t LastUnique; ///< Counter for tracking unique names + +/// @} + +}; + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Use.h b/libclamav/c++/llvm/include/llvm/Use.h new file mode 100644 index 000000000..970f69b9d --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Use.h @@ -0,0 +1,238 @@ +//===-- llvm/Use.h - Definition of the Use class ----------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This defines the Use class. The Use class represents the operand of an +// instruction or some other User instance which refers to a Value. The Use +// class keeps the "use list" of the referenced value up to date. +// +// Pointer tagging is used to efficiently find the User corresponding +// to a Use without having to store a User pointer in every Use. A +// User is preceded in memory by all the Uses corresponding to its +// operands, and the low bits of one of the fields (Prev) of the Use +// class are used to encode offsets to be able to find that User given +// a pointer to any Use. For details, see: +// +// http://www.llvm.org/docs/ProgrammersManual.html#UserLayout +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_USE_H +#define LLVM_USE_H + +#include "llvm/Support/Casting.h" +#include "llvm/ADT/PointerIntPair.h" +#include + +namespace llvm { + +class Value; +class User; +class Use; + +/// Tag - generic tag type for (at least 32 bit) pointers +enum Tag { noTag, tagOne, tagTwo, tagThree }; + +// Use** is only 4-byte aligned. +template<> +class PointerLikeTypeTraits { +public: + static inline void *getAsVoidPointer(Use** P) { return P; } + static inline Use **getFromVoidPointer(void *P) { + return static_cast(P); + } + enum { NumLowBitsAvailable = 2 }; +}; + +//===----------------------------------------------------------------------===// +// Use Class +//===----------------------------------------------------------------------===// + +/// Use is here to make keeping the "use" list of a Value up-to-date really +/// easy. +class Use { +public: + /// swap - provide a fast substitute to std::swap + /// that also works with less standard-compliant compilers + void swap(Use &RHS); + +private: + /// Copy ctor - do not implement + Use(const Use &U); + + /// Destructor - Only for zap() + inline ~Use() { + if (Val) removeFromList(); + } + + /// Default ctor - This leaves the Use completely uninitialized. The only + /// thing that is valid to do with this use is to call the "init" method. + inline Use() {} + enum PrevPtrTag { zeroDigitTag = noTag + , oneDigitTag = tagOne + , stopTag = tagTwo + , fullStopTag = tagThree }; + +public: + /// Normally Use will just implicitly convert to a Value* that it holds. + operator Value*() const { return Val; } + + /// If implicit conversion to Value* doesn't work, the get() method returns + /// the Value*. + Value *get() const { return Val; } + + /// getUser - This returns the User that contains this Use. For an + /// instruction operand, for example, this will return the instruction. + User *getUser() const; + + inline void set(Value *Val); + + Value *operator=(Value *RHS) { + set(RHS); + return RHS; + } + const Use &operator=(const Use &RHS) { + set(RHS.Val); + return *this; + } + + Value *operator->() { return Val; } + const Value *operator->() const { return Val; } + + Use *getNext() const { return Next; } + + + /// zap - This is used to destroy Use operands when the number of operands of + /// a User changes. + static void zap(Use *Start, const Use *Stop, bool del = false); + + /// getPrefix - Return deletable pointer if appropriate + Use *getPrefix(); +private: + const Use* getImpliedUser() const; + static Use *initTags(Use *Start, Use *Stop, ptrdiff_t Done = 0); + + Value *Val; + Use *Next; + PointerIntPair Prev; + + void setPrev(Use **NewPrev) { + Prev.setPointer(NewPrev); + } + void addToList(Use **List) { + Next = *List; + if (Next) Next->setPrev(&Next); + setPrev(List); + *List = this; + } + void removeFromList() { + Use **StrippedPrev = Prev.getPointer(); + *StrippedPrev = Next; + if (Next) Next->setPrev(StrippedPrev); + } + + friend class Value; + friend class User; +}; + +// simplify_type - Allow clients to treat uses just like values when using +// casting operators. +template<> struct simplify_type { + typedef Value* SimpleType; + static SimpleType getSimplifiedValue(const Use &Val) { + return static_cast(Val.get()); + } +}; +template<> struct simplify_type { + typedef Value* SimpleType; + static SimpleType getSimplifiedValue(const Use &Val) { + return static_cast(Val.get()); + } +}; + + + +template // UserTy == 'User' or 'const User' +class value_use_iterator : public std::iterator { + typedef std::iterator super; + typedef value_use_iterator _Self; + + Use *U; + explicit value_use_iterator(Use *u) : U(u) {} + friend class Value; +public: + typedef typename super::reference reference; + typedef typename super::pointer pointer; + + value_use_iterator(const _Self &I) : U(I.U) {} + value_use_iterator() {} + + bool operator==(const _Self &x) const { + return U == x.U; + } + bool operator!=(const _Self &x) const { + return !operator==(x); + } + + /// atEnd - return true if this iterator is equal to use_end() on the value. + bool atEnd() const { return U == 0; } + + // Iterator traversal: forward iteration only + _Self &operator++() { // Preincrement + assert(U && "Cannot increment end iterator!"); + U = U->getNext(); + return *this; + } + _Self operator++(int) { // Postincrement + _Self tmp = *this; ++*this; return tmp; + } + + // Retrieve a pointer to the current User. + UserTy *operator*() const { + assert(U && "Cannot dereference end iterator!"); + return U->getUser(); + } + + UserTy *operator->() const { return operator*(); } + + Use &getUse() const { return *U; } + + /// getOperandNo - Return the operand # of this use in its User. Defined in + /// User.h + /// + unsigned getOperandNo() const; +}; + + +template<> struct simplify_type > { + typedef User* SimpleType; + + static SimpleType getSimplifiedValue(const value_use_iterator &Val) { + return *Val; + } +}; + +template<> struct simplify_type > + : public simplify_type > {}; + +template<> struct simplify_type > { + typedef const User* SimpleType; + + static SimpleType getSimplifiedValue(const + value_use_iterator &Val) { + return *Val; + } +}; + +template<> struct simplify_type > + : public simplify_type > {}; + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/User.h b/libclamav/c++/llvm/include/llvm/User.h new file mode 100644 index 000000000..f8277952e --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/User.h @@ -0,0 +1,204 @@ +//===-- llvm/User.h - User class definition ---------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This class defines the interface that one who 'use's a Value must implement. +// Each instance of the Value class keeps track of what User's have handles +// to it. +// +// * Instructions are the largest class of User's. +// * Constants may be users of other constants (think arrays and stuff) +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_USER_H +#define LLVM_USER_H + +#include "llvm/Value.h" + +namespace llvm { + +/// OperandTraits - Compile-time customization of +/// operand-related allocators and accessors +/// for use of the User class +template +struct OperandTraits; + +class User; + +/// OperandTraits - specialization to User +template <> +struct OperandTraits { + static inline Use *op_begin(User*); + static inline Use *op_end(User*); + static inline unsigned operands(const User*); + template + struct Layout { + typedef U overlay; + }; +}; + +class User : public Value { + User(const User &); // Do not implement + void *operator new(size_t); // Do not implement + template + friend struct HungoffOperandTraits; +protected: + /// OperandList - This is a pointer to the array of Uses for this User. + /// For nodes of fixed arity (e.g. a binary operator) this array will live + /// prefixed to some derived class instance. For nodes of resizable variable + /// arity (e.g. PHINodes, SwitchInst etc.), this memory will be dynamically + /// allocated and should be destroyed by the classes' virtual dtor. + Use *OperandList; + + /// NumOperands - The number of values used by this User. + /// + unsigned NumOperands; + + void *operator new(size_t s, unsigned Us); + void *operator new(size_t s, unsigned Us, bool Prefix); + User(const Type *ty, unsigned vty, Use *OpList, unsigned NumOps) + : Value(ty, vty), OperandList(OpList), NumOperands(NumOps) {} + Use *allocHungoffUses(unsigned) const; + void dropHungoffUses(Use *U) { + if (OperandList == U) { + OperandList = 0; + NumOperands = 0; + } + Use::zap(U, U->getImpliedUser(), true); + } +public: + ~User() { + if ((intptr_t(OperandList) & 1) == 0) + Use::zap(OperandList, OperandList + NumOperands); + } + /// operator delete - free memory allocated for User and Use objects + void operator delete(void *Usr); + /// placement delete - required by std, but never called. + void operator delete(void*, unsigned) { + assert(0 && "Constructor throws?"); + } + /// placement delete - required by std, but never called. + void operator delete(void*, unsigned, bool) { + assert(0 && "Constructor throws?"); + } +protected: + template static Use &OpFrom(const U *that) { + return Idx < 0 + ? OperandTraits::op_end(const_cast(that))[Idx] + : OperandTraits::op_begin(const_cast(that))[Idx]; + } + template Use &Op() { + return OpFrom(this); + } + template const Use &Op() const { + return OpFrom(this); + } +public: + Value *getOperand(unsigned i) const { + assert(i < NumOperands && "getOperand() out of range!"); + return OperandList[i]; + } + void setOperand(unsigned i, Value *Val) { + assert(i < NumOperands && "setOperand() out of range!"); + assert((!isa((const Value*)this) || + isa((const Value*)this)) && + "Cannot mutate a constant with setOperand!"); + OperandList[i] = Val; + } + const Use &getOperandUse(unsigned i) const { + assert(i < NumOperands && "getOperand() out of range!"); + return OperandList[i]; + } + Use &getOperandUse(unsigned i) { + assert(i < NumOperands && "getOperand() out of range!"); + return OperandList[i]; + } + + unsigned getNumOperands() const { return NumOperands; } + + // --------------------------------------------------------------------------- + // Operand Iterator interface... + // + typedef Use* op_iterator; + typedef const Use* const_op_iterator; + + inline op_iterator op_begin() { return OperandList; } + inline const_op_iterator op_begin() const { return OperandList; } + inline op_iterator op_end() { return OperandList+NumOperands; } + inline const_op_iterator op_end() const { return OperandList+NumOperands; } + + // dropAllReferences() - This function is in charge of "letting go" of all + // objects that this User refers to. This allows one to + // 'delete' a whole class at a time, even though there may be circular + // references... First all references are dropped, and all use counts go to + // zero. Then everything is deleted for real. Note that no operations are + // valid on an object that has "dropped all references", except operator + // delete. + // + void dropAllReferences() { + for (op_iterator i = op_begin(), e = op_end(); i != e; ++i) + i->set(0); + } + + /// replaceUsesOfWith - Replaces all references to the "From" definition with + /// references to the "To" definition. + /// + void replaceUsesOfWith(Value *From, Value *To); + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const User *) { return true; } + static inline bool classof(const Value *V) { + return isa(V) || isa(V); + } +}; + +inline Use *OperandTraits::op_begin(User *U) { + return U->op_begin(); +} + +inline Use *OperandTraits::op_end(User *U) { + return U->op_end(); +} + +inline unsigned OperandTraits::operands(const User *U) { + return U->getNumOperands(); +} + +template<> struct simplify_type { + typedef Value* SimpleType; + + static SimpleType getSimplifiedValue(const User::op_iterator &Val) { + return static_cast(Val->get()); + } +}; + +template<> struct simplify_type + : public simplify_type {}; + +template<> struct simplify_type { + typedef Value* SimpleType; + + static SimpleType getSimplifiedValue(const User::const_op_iterator &Val) { + return static_cast(Val->get()); + } +}; + +template<> struct simplify_type + : public simplify_type {}; + + +// value_use_iterator::getOperandNo - Requires the definition of the User class. +template +unsigned value_use_iterator::getOperandNo() const { + return U - U->getUser()->op_begin(); +} + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/Value.h b/libclamav/c++/llvm/include/llvm/Value.h new file mode 100644 index 000000000..0960346cb --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/Value.h @@ -0,0 +1,371 @@ +//===-- llvm/Value.h - Definition of the Value class ------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the Value class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_VALUE_H +#define LLVM_VALUE_H + +#include "llvm/AbstractTypeUser.h" +#include "llvm/Use.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/Twine.h" +#include "llvm/Support/Casting.h" +#include + +namespace llvm { + +class Constant; +class Argument; +class Instruction; +class BasicBlock; +class GlobalValue; +class Function; +class GlobalVariable; +class GlobalAlias; +class InlineAsm; +class ValueSymbolTable; +class TypeSymbolTable; +template class StringMapEntry; +template +class AssertingVH; +typedef StringMapEntry ValueName; +class raw_ostream; +class AssemblyAnnotationWriter; +class ValueHandleBase; +class LLVMContext; +class MetadataContextImpl; + +//===----------------------------------------------------------------------===// +// Value Class +//===----------------------------------------------------------------------===// + +/// This is a very important LLVM class. It is the base class of all values +/// computed by a program that may be used as operands to other values. Value is +/// the super class of other important classes such as Instruction and Function. +/// All Values have a Type. Type is not a subclass of Value. All types can have +/// a name and they should belong to some Module. Setting the name on the Value +/// automatically updates the module's symbol table. +/// +/// Every value has a "use list" that keeps track of which other Values are +/// using this Value. A Value can also have an arbitrary number of ValueHandle +/// objects that watch it and listen to RAUW and Destroy events see +/// llvm/Support/ValueHandle.h for details. +/// +/// @brief LLVM Value Representation +class Value { + const unsigned char SubclassID; // Subclass identifier (for isa/dyn_cast) + unsigned char HasValueHandle : 1; // Has a ValueHandle pointing to this? + unsigned char HasMetadata : 1; // Has a metadata attached to this ? +protected: + /// SubclassOptionalData - This member is similar to SubclassData, however it + /// is for holding information which may be used to aid optimization, but + /// which may be cleared to zero without affecting conservative + /// interpretation. + unsigned char SubclassOptionalData : 7; + + /// SubclassData - This member is defined by this class, but is not used for + /// anything. Subclasses can use it to hold whatever state they find useful. + /// This field is initialized to zero by the ctor. + unsigned short SubclassData; +private: + PATypeHolder VTy; + Use *UseList; + + friend class ValueSymbolTable; // Allow ValueSymbolTable to directly mod Name. + friend class SymbolTable; // Allow SymbolTable to directly poke Name. + friend class ValueHandleBase; + friend class MetadataContextImpl; + friend class AbstractTypeUser; + ValueName *Name; + + void operator=(const Value &); // Do not implement + Value(const Value &); // Do not implement + +protected: + /// printCustom - Value subclasses can override this to implement custom + /// printing behavior. + virtual void printCustom(raw_ostream &O) const; + +public: + Value(const Type *Ty, unsigned scid); + virtual ~Value(); + + /// dump - Support for debugging, callable in GDB: V->dump() + // + void dump() const; + + /// print - Implement operator<< on Value. + /// + void print(raw_ostream &O, AssemblyAnnotationWriter *AAW = 0) const; + + /// All values are typed, get the type of this value. + /// + inline const Type *getType() const { return VTy; } + + /// All values hold a context through their type. + LLVMContext &getContext() const; + + // All values can potentially be named... + inline bool hasName() const { return Name != 0; } + ValueName *getValueName() const { return Name; } + + /// getName() - Return a constant reference to the value's name. This is cheap + /// and guaranteed to return the same reference as long as the value is not + /// modified. + /// + /// This is currently guaranteed to return a StringRef for which data() points + /// to a valid null terminated string. The use of StringRef.data() is + /// deprecated here, however, and clients should not rely on it. If such + /// behavior is needed, clients should use expensive getNameStr(), or switch + /// to an interface that does not depend on null termination. + StringRef getName() const; + + /// getNameStr() - Return the name of the specified value, *constructing a + /// string* to hold it. This is guaranteed to construct a string and is very + /// expensive, clients should use getName() unless necessary. + std::string getNameStr() const; + + /// setName() - Change the name of the value, choosing a new unique name if + /// the provided name is taken. + /// + /// \arg Name - The new name; or "" if the value's name should be removed. + void setName(const Twine &Name); + + + /// takeName - transfer the name from V to this value, setting V's name to + /// empty. It is an error to call V->takeName(V). + void takeName(Value *V); + + /// replaceAllUsesWith - Go through the uses list for this definition and make + /// each use point to "V" instead of "this". After this completes, 'this's + /// use list is guaranteed to be empty. + /// + void replaceAllUsesWith(Value *V); + + // uncheckedReplaceAllUsesWith - Just like replaceAllUsesWith but dangerous. + // Only use when in type resolution situations! + void uncheckedReplaceAllUsesWith(Value *V); + + //---------------------------------------------------------------------- + // Methods for handling the chain of uses of this Value. + // + typedef value_use_iterator use_iterator; + typedef value_use_iterator use_const_iterator; + + bool use_empty() const { return UseList == 0; } + use_iterator use_begin() { return use_iterator(UseList); } + use_const_iterator use_begin() const { return use_const_iterator(UseList); } + use_iterator use_end() { return use_iterator(0); } + use_const_iterator use_end() const { return use_const_iterator(0); } + User *use_back() { return *use_begin(); } + const User *use_back() const { return *use_begin(); } + + /// hasOneUse - Return true if there is exactly one user of this value. This + /// is specialized because it is a common request and does not require + /// traversing the whole use list. + /// + bool hasOneUse() const { + use_const_iterator I = use_begin(), E = use_end(); + if (I == E) return false; + return ++I == E; + } + + /// hasNUses - Return true if this Value has exactly N users. + /// + bool hasNUses(unsigned N) const; + + /// hasNUsesOrMore - Return true if this value has N users or more. This is + /// logically equivalent to getNumUses() >= N. + /// + bool hasNUsesOrMore(unsigned N) const; + + bool isUsedInBasicBlock(const BasicBlock *BB) const; + + /// getNumUses - This method computes the number of uses of this Value. This + /// is a linear time operation. Use hasOneUse, hasNUses, or hasMoreThanNUses + /// to check for specific values. + unsigned getNumUses() const; + + /// addUse - This method should only be used by the Use class. + /// + void addUse(Use &U) { U.addToList(&UseList); } + + /// An enumeration for keeping track of the concrete subclass of Value that + /// is actually instantiated. Values of this enumeration are kept in the + /// Value classes SubclassID field. They are used for concrete type + /// identification. + enum ValueTy { + ArgumentVal, // This is an instance of Argument + BasicBlockVal, // This is an instance of BasicBlock + FunctionVal, // This is an instance of Function + GlobalAliasVal, // This is an instance of GlobalAlias + GlobalVariableVal, // This is an instance of GlobalVariable + UndefValueVal, // This is an instance of UndefValue + BlockAddressVal, // This is an instance of BlockAddress + ConstantExprVal, // This is an instance of ConstantExpr + ConstantAggregateZeroVal, // This is an instance of ConstantAggregateNull + ConstantIntVal, // This is an instance of ConstantInt + ConstantFPVal, // This is an instance of ConstantFP + ConstantArrayVal, // This is an instance of ConstantArray + ConstantStructVal, // This is an instance of ConstantStruct + ConstantVectorVal, // This is an instance of ConstantVector + ConstantPointerNullVal, // This is an instance of ConstantPointerNull + MDNodeVal, // This is an instance of MDNode + MDStringVal, // This is an instance of MDString + NamedMDNodeVal, // This is an instance of NamedMDNode + InlineAsmVal, // This is an instance of InlineAsm + PseudoSourceValueVal, // This is an instance of PseudoSourceValue + FixedStackPseudoSourceValueVal, // This is an instance of + // FixedStackPseudoSourceValue + InstructionVal, // This is an instance of Instruction + // Enum values starting at InstructionVal are used for Instructions; + // don't add new values here! + + // Markers: + ConstantFirstVal = FunctionVal, + ConstantLastVal = ConstantPointerNullVal + }; + + /// getValueID - Return an ID for the concrete type of this object. This is + /// used to implement the classof checks. This should not be used for any + /// other purpose, as the values may change as LLVM evolves. Also, note that + /// for instructions, the Instruction's opcode is added to InstructionVal. So + /// this means three things: + /// # there is no value with code InstructionVal (no opcode==0). + /// # there are more possible values for the value type than in ValueTy enum. + /// # the InstructionVal enumerator must be the highest valued enumerator in + /// the ValueTy enum. + unsigned getValueID() const { + return SubclassID; + } + + /// getRawSubclassOptionalData - Return the raw optional flags value + /// contained in this value. This should only be used when testing two + /// Values for equivalence. + unsigned getRawSubclassOptionalData() const { + return SubclassOptionalData; + } + + /// hasSameSubclassOptionalData - Test whether the optional flags contained + /// in this value are equal to the optional flags in the given value. + bool hasSameSubclassOptionalData(const Value *V) const { + return SubclassOptionalData == V->SubclassOptionalData; + } + + /// intersectOptionalDataWith - Clear any optional flags in this value + /// that are not also set in the given value. + void intersectOptionalDataWith(const Value *V) { + SubclassOptionalData &= V->SubclassOptionalData; + } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const Value *) { + return true; // Values are always values. + } + + /// getRawType - This should only be used to implement the vmcore library. + /// + const Type *getRawType() const { return VTy.getRawType(); } + + /// stripPointerCasts - This method strips off any unneeded pointer + /// casts from the specified value, returning the original uncasted value. + /// Note that the returned value has pointer type if the specified value does. + Value *stripPointerCasts(); + const Value *stripPointerCasts() const { + return const_cast(this)->stripPointerCasts(); + } + + /// getUnderlyingObject - This method strips off any GEP address adjustments + /// and pointer casts from the specified value, returning the original object + /// being addressed. Note that the returned value has pointer type if the + /// specified value does. + Value *getUnderlyingObject(); + const Value *getUnderlyingObject() const { + return const_cast(this)->getUnderlyingObject(); + } + + /// DoPHITranslation - If this value is a PHI node with CurBB as its parent, + /// return the value in the PHI node corresponding to PredBB. If not, return + /// ourself. This is useful if you want to know the value something has in a + /// predecessor block. + Value *DoPHITranslation(const BasicBlock *CurBB, const BasicBlock *PredBB); + + const Value *DoPHITranslation(const BasicBlock *CurBB, + const BasicBlock *PredBB) const{ + return const_cast(this)->DoPHITranslation(CurBB, PredBB); + } + + /// hasMetadata - Return true if metadata is attached with this value. + bool hasMetadata() const { return HasMetadata; } +}; + +inline raw_ostream &operator<<(raw_ostream &OS, const Value &V) { + V.print(OS); + return OS; +} + +void Use::set(Value *V) { + if (Val) removeFromList(); + Val = V; + if (V) V->addUse(*this); +} + + +// isa - Provide some specializations of isa so that we don't have to include +// the subtype header files to test to see if the value is a subclass... +// +template <> inline bool isa_impl(const Value &Val) { + return Val.getValueID() >= Value::ConstantFirstVal && + Val.getValueID() <= Value::ConstantLastVal; +} +template <> inline bool isa_impl(const Value &Val) { + return Val.getValueID() == Value::ArgumentVal; +} +template <> inline bool isa_impl(const Value &Val) { + return Val.getValueID() == Value::InlineAsmVal; +} +template <> inline bool isa_impl(const Value &Val) { + return Val.getValueID() >= Value::InstructionVal; +} +template <> inline bool isa_impl(const Value &Val) { + return Val.getValueID() == Value::BasicBlockVal; +} +template <> inline bool isa_impl(const Value &Val) { + return Val.getValueID() == Value::FunctionVal; +} +template <> inline bool isa_impl(const Value &Val) { + return Val.getValueID() == Value::GlobalVariableVal; +} +template <> inline bool isa_impl(const Value &Val) { + return Val.getValueID() == Value::GlobalAliasVal; +} +template <> inline bool isa_impl(const Value &Val) { + return isa(Val) || isa(Val) || + isa(Val); +} + + +// Value* is only 4-byte aligned. +template<> +class PointerLikeTypeTraits { + typedef Value* PT; +public: + static inline void *getAsVoidPointer(PT P) { return P; } + static inline PT getFromVoidPointer(void *P) { + return static_cast(P); + } + enum { NumLowBitsAvailable = 2 }; +}; + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/include/llvm/ValueSymbolTable.h b/libclamav/c++/llvm/include/llvm/ValueSymbolTable.h new file mode 100644 index 000000000..e05fdbd08 --- /dev/null +++ b/libclamav/c++/llvm/include/llvm/ValueSymbolTable.h @@ -0,0 +1,134 @@ +//===-- llvm/ValueSymbolTable.h - Implement a Value Symtab ------*- 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 the name/Value symbol table for LLVM. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_VALUE_SYMBOL_TABLE_H +#define LLVM_VALUE_SYMBOL_TABLE_H + +#include "llvm/Value.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/System/DataTypes.h" + +namespace llvm { + template + class SymbolTableListTraits; + class BasicBlock; + class Function; + class NamedMDNode; + class Module; + class StringRef; + +/// This class provides a symbol table of name/value pairs. It is essentially +/// a std::map but has a controlled interface provided by +/// LLVM as well as ensuring uniqueness of names. +/// +class ValueSymbolTable { + friend class Value; + friend class SymbolTableListTraits; + friend class SymbolTableListTraits; + friend class SymbolTableListTraits; + friend class SymbolTableListTraits; + friend class SymbolTableListTraits; + friend class SymbolTableListTraits; + friend class SymbolTableListTraits; +/// @name Types +/// @{ +public: + /// @brief A mapping of names to values. + typedef StringMap ValueMap; + + /// @brief An iterator over a ValueMap. + typedef ValueMap::iterator iterator; + + /// @brief A const_iterator over a ValueMap. + typedef ValueMap::const_iterator const_iterator; + +/// @} +/// @name Constructors +/// @{ +public: + + ValueSymbolTable() : vmap(0), LastUnique(0) {} + ~ValueSymbolTable(); + +/// @} +/// @name Accessors +/// @{ +public: + + /// This method finds the value with the given \p Name in the + /// the symbol table. + /// @returns the value associated with the \p Name + /// @brief Lookup a named Value. + Value *lookup(StringRef Name) const { return vmap.lookup(Name); } + + /// @returns true iff the symbol table is empty + /// @brief Determine if the symbol table is empty + inline bool empty() const { return vmap.empty(); } + + /// @brief The number of name/type pairs is returned. + inline unsigned size() const { return unsigned(vmap.size()); } + + /// This function can be used from the debugger to display the + /// content of the symbol table while debugging. + /// @brief Print out symbol table on stderr + void dump() const; + +/// @} +/// @name Iteration +/// @{ +public: + /// @brief Get an iterator that from the beginning of the symbol table. + inline iterator begin() { return vmap.begin(); } + + /// @brief Get a const_iterator that from the beginning of the symbol table. + inline const_iterator begin() const { return vmap.begin(); } + + /// @brief Get an iterator to the end of the symbol table. + inline iterator end() { return vmap.end(); } + + /// @brief Get a const_iterator to the end of the symbol table. + inline const_iterator end() const { return vmap.end(); } + +/// @} +/// @name Mutators +/// @{ +private: + /// This method adds the provided value \p N to the symbol table. The Value + /// must have a name which is used to place the value in the symbol table. + /// If the inserted name conflicts, this renames the value. + /// @brief Add a named value to the symbol table + void reinsertValue(Value *V); + + /// createValueName - This method attempts to create a value name and insert + /// it into the symbol table with the specified name. If it conflicts, it + /// auto-renames the name and returns that instead. + ValueName *createValueName(StringRef Name, Value *V); + + /// This method removes a value from the symbol table. It leaves the + /// ValueName attached to the value, but it is no longer inserted in the + /// symtab. + void removeValueName(ValueName *V); + +/// @} +/// @name Internal Data +/// @{ +private: + ValueMap vmap; ///< The map that holds the symbol table. + mutable uint32_t LastUnique; ///< Counter for tracking unique names + +/// @} +}; + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/lib/Analysis/AliasAnalysis.cpp b/libclamav/c++/llvm/lib/Analysis/AliasAnalysis.cpp new file mode 100644 index 000000000..dee9b5358 --- /dev/null +++ b/libclamav/c++/llvm/lib/Analysis/AliasAnalysis.cpp @@ -0,0 +1,246 @@ +//===- AliasAnalysis.cpp - Generic Alias Analysis Interface Implementation -==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the generic AliasAnalysis interface which is used as the +// common interface used by all clients and implementations of alias analysis. +// +// This file also implements the default version of the AliasAnalysis interface +// that is to be used when no other implementation is specified. This does some +// simple tests that detect obvious cases: two different global pointers cannot +// alias, a global cannot alias a malloc, two different mallocs cannot alias, +// etc. +// +// This alias analysis implementation really isn't very good for anything, but +// it is very fast, and makes a nice clean default implementation. Because it +// handles lots of little corner cases, other, more complex, alias analysis +// implementations may choose to rely on this pass to resolve these simple and +// easy cases. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/Pass.h" +#include "llvm/BasicBlock.h" +#include "llvm/Function.h" +#include "llvm/IntrinsicInst.h" +#include "llvm/Instructions.h" +#include "llvm/Type.h" +#include "llvm/Target/TargetData.h" +using namespace llvm; + +// Register the AliasAnalysis interface, providing a nice name to refer to. +static RegisterAnalysisGroup Z("Alias Analysis"); +char AliasAnalysis::ID = 0; + +//===----------------------------------------------------------------------===// +// Default chaining methods +//===----------------------------------------------------------------------===// + +AliasAnalysis::AliasResult +AliasAnalysis::alias(const Value *V1, unsigned V1Size, + const Value *V2, unsigned V2Size) { + assert(AA && "AA didn't call InitializeAliasAnalysis in its run method!"); + return AA->alias(V1, V1Size, V2, V2Size); +} + +bool AliasAnalysis::pointsToConstantMemory(const Value *P) { + assert(AA && "AA didn't call InitializeAliasAnalysis in its run method!"); + return AA->pointsToConstantMemory(P); +} + +void AliasAnalysis::deleteValue(Value *V) { + assert(AA && "AA didn't call InitializeAliasAnalysis in its run method!"); + AA->deleteValue(V); +} + +void AliasAnalysis::copyValue(Value *From, Value *To) { + assert(AA && "AA didn't call InitializeAliasAnalysis in its run method!"); + AA->copyValue(From, To); +} + +AliasAnalysis::ModRefResult +AliasAnalysis::getModRefInfo(CallSite CS1, CallSite CS2) { + // FIXME: we can do better. + assert(AA && "AA didn't call InitializeAliasAnalysis in its run method!"); + return AA->getModRefInfo(CS1, CS2); +} + + +//===----------------------------------------------------------------------===// +// AliasAnalysis non-virtual helper method implementation +//===----------------------------------------------------------------------===// + +AliasAnalysis::ModRefResult +AliasAnalysis::getModRefInfo(LoadInst *L, Value *P, unsigned Size) { + return alias(L->getOperand(0), getTypeStoreSize(L->getType()), + P, Size) ? Ref : NoModRef; +} + +AliasAnalysis::ModRefResult +AliasAnalysis::getModRefInfo(StoreInst *S, Value *P, unsigned Size) { + // If the stored address cannot alias the pointer in question, then the + // pointer cannot be modified by the store. + if (!alias(S->getOperand(1), + getTypeStoreSize(S->getOperand(0)->getType()), P, Size)) + return NoModRef; + + // If the pointer is a pointer to constant memory, then it could not have been + // modified by this store. + return pointsToConstantMemory(P) ? NoModRef : Mod; +} + +AliasAnalysis::ModRefBehavior +AliasAnalysis::getModRefBehavior(CallSite CS, + std::vector *Info) { + if (CS.doesNotAccessMemory()) + // Can't do better than this. + return DoesNotAccessMemory; + ModRefBehavior MRB = getModRefBehavior(CS.getCalledFunction(), Info); + if (MRB != DoesNotAccessMemory && CS.onlyReadsMemory()) + return OnlyReadsMemory; + return MRB; +} + +AliasAnalysis::ModRefBehavior +AliasAnalysis::getModRefBehavior(Function *F, + std::vector *Info) { + if (F) { + if (F->doesNotAccessMemory()) + // Can't do better than this. + return DoesNotAccessMemory; + if (F->onlyReadsMemory()) + return OnlyReadsMemory; + if (unsigned id = F->getIntrinsicID()) { +#define GET_INTRINSIC_MODREF_BEHAVIOR +#include "llvm/Intrinsics.gen" +#undef GET_INTRINSIC_MODREF_BEHAVIOR + } + } + return UnknownModRefBehavior; +} + +AliasAnalysis::ModRefResult +AliasAnalysis::getModRefInfo(CallSite CS, Value *P, unsigned Size) { + ModRefBehavior MRB = getModRefBehavior(CS); + if (MRB == DoesNotAccessMemory) + return NoModRef; + + ModRefResult Mask = ModRef; + if (MRB == OnlyReadsMemory) + Mask = Ref; + else if (MRB == AliasAnalysis::AccessesArguments) { + bool doesAlias = false; + for (CallSite::arg_iterator AI = CS.arg_begin(), AE = CS.arg_end(); + AI != AE; ++AI) + if (!isNoAlias(*AI, ~0U, P, Size)) { + doesAlias = true; + break; + } + + if (!doesAlias) + return NoModRef; + } + + if (!AA) return Mask; + + // If P points to a constant memory location, the call definitely could not + // modify the memory location. + if ((Mask & Mod) && AA->pointsToConstantMemory(P)) + Mask = ModRefResult(Mask & ~Mod); + + return ModRefResult(Mask & AA->getModRefInfo(CS, P, Size)); +} + +// AliasAnalysis destructor: DO NOT move this to the header file for +// AliasAnalysis or else clients of the AliasAnalysis class may not depend on +// the AliasAnalysis.o file in the current .a file, causing alias analysis +// support to not be included in the tool correctly! +// +AliasAnalysis::~AliasAnalysis() {} + +/// InitializeAliasAnalysis - Subclasses must call this method to initialize the +/// AliasAnalysis interface before any other methods are called. +/// +void AliasAnalysis::InitializeAliasAnalysis(Pass *P) { + TD = P->getAnalysisIfAvailable(); + AA = &P->getAnalysis(); +} + +// getAnalysisUsage - All alias analysis implementations should invoke this +// directly (using AliasAnalysis::getAnalysisUsage(AU)). +void AliasAnalysis::getAnalysisUsage(AnalysisUsage &AU) const { + AU.addRequired(); // All AA's chain +} + +/// getTypeStoreSize - Return the TargetData store size for the given type, +/// if known, or a conservative value otherwise. +/// +unsigned AliasAnalysis::getTypeStoreSize(const Type *Ty) { + return TD ? TD->getTypeStoreSize(Ty) : ~0u; +} + +/// canBasicBlockModify - Return true if it is possible for execution of the +/// specified basic block to modify the value pointed to by Ptr. +/// +bool AliasAnalysis::canBasicBlockModify(const BasicBlock &BB, + const Value *Ptr, unsigned Size) { + return canInstructionRangeModify(BB.front(), BB.back(), Ptr, Size); +} + +/// canInstructionRangeModify - Return true if it is possible for the execution +/// of the specified instructions to modify the value pointed to by Ptr. The +/// instructions to consider are all of the instructions in the range of [I1,I2] +/// INCLUSIVE. I1 and I2 must be in the same basic block. +/// +bool AliasAnalysis::canInstructionRangeModify(const Instruction &I1, + const Instruction &I2, + const Value *Ptr, unsigned Size) { + assert(I1.getParent() == I2.getParent() && + "Instructions not in same basic block!"); + BasicBlock::iterator I = const_cast(&I1); + BasicBlock::iterator E = const_cast(&I2); + ++E; // Convert from inclusive to exclusive range. + + for (; I != E; ++I) // Check every instruction in range + if (getModRefInfo(I, const_cast(Ptr), Size) & Mod) + return true; + return false; +} + +/// isNoAliasCall - Return true if this pointer is returned by a noalias +/// function. +bool llvm::isNoAliasCall(const Value *V) { + if (isa(V) || isa(V)) + return CallSite(const_cast(cast(V))) + .paramHasAttr(0, Attribute::NoAlias); + return false; +} + +/// isIdentifiedObject - Return true if this pointer refers to a distinct and +/// identifiable object. This returns true for: +/// Global Variables and Functions (but not Global Aliases) +/// Allocas and Mallocs +/// ByVal and NoAlias Arguments +/// NoAlias returns +/// +bool llvm::isIdentifiedObject(const Value *V) { + if (isa(V) || isNoAliasCall(V)) + return true; + if (isa(V) && !isa(V)) + return true; + if (const Argument *A = dyn_cast(V)) + return A->hasNoAliasAttr() || A->hasByValAttr(); + return false; +} + +// Because of the way .a files work, we must force the BasicAA implementation to +// be pulled in if the AliasAnalysis classes are pulled in. Otherwise we run +// the risk of AliasAnalysis being used, but the default implementation not +// being linked into the tool that uses it. +DEFINING_FILE_FOR(AliasAnalysis) diff --git a/libclamav/c++/llvm/lib/Analysis/AliasAnalysisCounter.cpp b/libclamav/c++/llvm/lib/Analysis/AliasAnalysisCounter.cpp new file mode 100644 index 000000000..030bcd26f --- /dev/null +++ b/libclamav/c++/llvm/lib/Analysis/AliasAnalysisCounter.cpp @@ -0,0 +1,159 @@ +//===- AliasAnalysisCounter.cpp - Alias Analysis Query Counter ------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements a pass which can be used to count how many alias queries +// are being made and how the alias analysis implementation being used responds. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Analysis/Passes.h" +#include "llvm/Pass.h" +#include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/Assembly/Writer.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +static cl::opt +PrintAll("count-aa-print-all-queries", cl::ReallyHidden, cl::init(true)); +static cl::opt +PrintAllFailures("count-aa-print-all-failed-queries", cl::ReallyHidden); + +namespace { + class AliasAnalysisCounter : public ModulePass, public AliasAnalysis { + unsigned No, May, Must; + unsigned NoMR, JustRef, JustMod, MR; + const char *Name; + Module *M; + public: + static char ID; // Class identification, replacement for typeinfo + AliasAnalysisCounter() : ModulePass(&ID) { + No = May = Must = 0; + NoMR = JustRef = JustMod = MR = 0; + } + + void printLine(const char *Desc, unsigned Val, unsigned Sum) { + errs() << " " << Val << " " << Desc << " responses (" + << Val*100/Sum << "%)\n"; + } + ~AliasAnalysisCounter() { + unsigned AASum = No+May+Must; + unsigned MRSum = NoMR+JustRef+JustMod+MR; + if (AASum + MRSum) { // Print a report if any counted queries occurred... + errs() << "\n===== Alias Analysis Counter Report =====\n" + << " Analysis counted: " << Name << "\n" + << " " << AASum << " Total Alias Queries Performed\n"; + if (AASum) { + printLine("no alias", No, AASum); + printLine("may alias", May, AASum); + printLine("must alias", Must, AASum); + errs() << " Alias Analysis Counter Summary: " << No*100/AASum << "%/" + << May*100/AASum << "%/" << Must*100/AASum<<"%\n\n"; + } + + errs() << " " << MRSum << " Total Mod/Ref Queries Performed\n"; + if (MRSum) { + printLine("no mod/ref", NoMR, MRSum); + printLine("ref", JustRef, MRSum); + printLine("mod", JustMod, MRSum); + printLine("mod/ref", MR, MRSum); + errs() << " Mod/Ref Analysis Counter Summary: " <M = &M; + InitializeAliasAnalysis(this); + Name = dynamic_cast(&getAnalysis())->getPassName(); + return false; + } + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AliasAnalysis::getAnalysisUsage(AU); + AU.addRequired(); + AU.setPreservesAll(); + } + + // FIXME: We could count these too... + bool pointsToConstantMemory(const Value *P) { + return getAnalysis().pointsToConstantMemory(P); + } + + // Forwarding functions: just delegate to a real AA implementation, counting + // the number of responses... + AliasResult alias(const Value *V1, unsigned V1Size, + const Value *V2, unsigned V2Size); + + ModRefResult getModRefInfo(CallSite CS, Value *P, unsigned Size); + ModRefResult getModRefInfo(CallSite CS1, CallSite CS2) { + return AliasAnalysis::getModRefInfo(CS1,CS2); + } + }; +} + +char AliasAnalysisCounter::ID = 0; +static RegisterPass +X("count-aa", "Count Alias Analysis Query Responses", false, true); +static RegisterAnalysisGroup Y(X); + +ModulePass *llvm::createAliasAnalysisCounterPass() { + return new AliasAnalysisCounter(); +} + +AliasAnalysis::AliasResult +AliasAnalysisCounter::alias(const Value *V1, unsigned V1Size, + const Value *V2, unsigned V2Size) { + AliasResult R = getAnalysis().alias(V1, V1Size, V2, V2Size); + + const char *AliasString; + switch (R) { + default: llvm_unreachable("Unknown alias type!"); + case NoAlias: No++; AliasString = "No alias"; break; + case MayAlias: May++; AliasString = "May alias"; break; + case MustAlias: Must++; AliasString = "Must alias"; break; + } + + if (PrintAll || (PrintAllFailures && R == MayAlias)) { + errs() << AliasString << ":\t"; + errs() << "[" << V1Size << "B] "; + WriteAsOperand(errs(), V1, true, M); + errs() << ", "; + errs() << "[" << V2Size << "B] "; + WriteAsOperand(errs(), V2, true, M); + errs() << "\n"; + } + + return R; +} + +AliasAnalysis::ModRefResult +AliasAnalysisCounter::getModRefInfo(CallSite CS, Value *P, unsigned Size) { + ModRefResult R = getAnalysis().getModRefInfo(CS, P, Size); + + const char *MRString; + switch (R) { + default: llvm_unreachable("Unknown mod/ref type!"); + case NoModRef: NoMR++; MRString = "NoModRef"; break; + case Ref: JustRef++; MRString = "JustRef"; break; + case Mod: JustMod++; MRString = "JustMod"; break; + case ModRef: MR++; MRString = "ModRef"; break; + } + + if (PrintAll || (PrintAllFailures && R == ModRef)) { + errs() << MRString << ": Ptr: "; + errs() << "[" << Size << "B] "; + WriteAsOperand(errs(), P, true, M); + errs() << "\t<->" << *CS.getInstruction(); + } + return R; +} diff --git a/libclamav/c++/llvm/lib/Analysis/AliasAnalysisEvaluator.cpp b/libclamav/c++/llvm/lib/Analysis/AliasAnalysisEvaluator.cpp new file mode 100644 index 000000000..6a2564cbe --- /dev/null +++ b/libclamav/c++/llvm/lib/Analysis/AliasAnalysisEvaluator.cpp @@ -0,0 +1,245 @@ +//===- AliasAnalysisEvaluator.cpp - Alias Analysis Accuracy Evaluator -----===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements a simple N^2 alias analysis accuracy evaluator. +// Basically, for each function in the program, it simply queries to see how the +// alias analysis implementation answers alias queries between each pair of +// pointers in the function. +// +// This is inspired and adapted from code by: Naveen Neelakantam, Francesco +// Spadini, and Wojciech Stryjewski. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Function.h" +#include "llvm/Instructions.h" +#include "llvm/Pass.h" +#include "llvm/Analysis/Passes.h" +#include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/Assembly/Writer.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Support/InstIterator.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/ADT/SetVector.h" +using namespace llvm; + +static cl::opt PrintAll("print-all-alias-modref-info", cl::ReallyHidden); + +static cl::opt PrintNoAlias("print-no-aliases", cl::ReallyHidden); +static cl::opt PrintMayAlias("print-may-aliases", cl::ReallyHidden); +static cl::opt PrintMustAlias("print-must-aliases", cl::ReallyHidden); + +static cl::opt PrintNoModRef("print-no-modref", cl::ReallyHidden); +static cl::opt PrintMod("print-mod", cl::ReallyHidden); +static cl::opt PrintRef("print-ref", cl::ReallyHidden); +static cl::opt PrintModRef("print-modref", cl::ReallyHidden); + +namespace { + class AAEval : public FunctionPass { + unsigned NoAlias, MayAlias, MustAlias; + unsigned NoModRef, Mod, Ref, ModRef; + + public: + static char ID; // Pass identification, replacement for typeid + AAEval() : FunctionPass(&ID) {} + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.addRequired(); + AU.setPreservesAll(); + } + + bool doInitialization(Module &M) { + NoAlias = MayAlias = MustAlias = 0; + NoModRef = Mod = Ref = ModRef = 0; + + if (PrintAll) { + PrintNoAlias = PrintMayAlias = PrintMustAlias = true; + PrintNoModRef = PrintMod = PrintRef = PrintModRef = true; + } + return false; + } + + bool runOnFunction(Function &F); + bool doFinalization(Module &M); + }; +} + +char AAEval::ID = 0; +static RegisterPass +X("aa-eval", "Exhaustive Alias Analysis Precision Evaluator", false, true); + +FunctionPass *llvm::createAAEvalPass() { return new AAEval(); } + +static void PrintResults(const char *Msg, bool P, const Value *V1, + const Value *V2, const Module *M) { + if (P) { + std::string o1, o2; + { + raw_string_ostream os1(o1), os2(o2); + WriteAsOperand(os1, V1, true, M); + WriteAsOperand(os2, V2, true, M); + } + + if (o2 < o1) + std::swap(o1, o2); + errs() << " " << Msg << ":\t" + << o1 << ", " + << o2 << "\n"; + } +} + +static inline void +PrintModRefResults(const char *Msg, bool P, Instruction *I, Value *Ptr, + Module *M) { + if (P) { + errs() << " " << Msg << ": Ptr: "; + WriteAsOperand(errs(), Ptr, true, M); + errs() << "\t<->" << *I << '\n'; + } +} + +bool AAEval::runOnFunction(Function &F) { + AliasAnalysis &AA = getAnalysis(); + + SetVector Pointers; + SetVector CallSites; + + for (Function::arg_iterator I = F.arg_begin(), E = F.arg_end(); I != E; ++I) + if (isa(I->getType())) // Add all pointer arguments + Pointers.insert(I); + + for (inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I) { + if (isa(I->getType())) // Add all pointer instructions + Pointers.insert(&*I); + Instruction &Inst = *I; + User::op_iterator OI = Inst.op_begin(); + CallSite CS = CallSite::get(&Inst); + if (CS.getInstruction() && + isa(CS.getCalledValue())) + ++OI; // Skip actual functions for direct function calls. + for (; OI != Inst.op_end(); ++OI) + if (isa((*OI)->getType()) && !isa(*OI)) + Pointers.insert(*OI); + + if (CS.getInstruction()) CallSites.insert(CS); + } + + if (PrintNoAlias || PrintMayAlias || PrintMustAlias || + PrintNoModRef || PrintMod || PrintRef || PrintModRef) + errs() << "Function: " << F.getName() << ": " << Pointers.size() + << " pointers, " << CallSites.size() << " call sites\n"; + + // iterate over the worklist, and run the full (n^2)/2 disambiguations + for (SetVector::iterator I1 = Pointers.begin(), E = Pointers.end(); + I1 != E; ++I1) { + unsigned I1Size = ~0u; + const Type *I1ElTy = cast((*I1)->getType())->getElementType(); + if (I1ElTy->isSized()) I1Size = AA.getTypeStoreSize(I1ElTy); + + for (SetVector::iterator I2 = Pointers.begin(); I2 != I1; ++I2) { + unsigned I2Size = ~0u; + const Type *I2ElTy =cast((*I2)->getType())->getElementType(); + if (I2ElTy->isSized()) I2Size = AA.getTypeStoreSize(I2ElTy); + + switch (AA.alias(*I1, I1Size, *I2, I2Size)) { + case AliasAnalysis::NoAlias: + PrintResults("NoAlias", PrintNoAlias, *I1, *I2, F.getParent()); + ++NoAlias; break; + case AliasAnalysis::MayAlias: + PrintResults("MayAlias", PrintMayAlias, *I1, *I2, F.getParent()); + ++MayAlias; break; + case AliasAnalysis::MustAlias: + PrintResults("MustAlias", PrintMustAlias, *I1, *I2, F.getParent()); + ++MustAlias; break; + default: + errs() << "Unknown alias query result!\n"; + } + } + } + + // Mod/ref alias analysis: compare all pairs of calls and values + for (SetVector::iterator C = CallSites.begin(), + Ce = CallSites.end(); C != Ce; ++C) { + Instruction *I = C->getInstruction(); + + for (SetVector::iterator V = Pointers.begin(), Ve = Pointers.end(); + V != Ve; ++V) { + unsigned Size = ~0u; + const Type *ElTy = cast((*V)->getType())->getElementType(); + if (ElTy->isSized()) Size = AA.getTypeStoreSize(ElTy); + + switch (AA.getModRefInfo(*C, *V, Size)) { + case AliasAnalysis::NoModRef: + PrintModRefResults("NoModRef", PrintNoModRef, I, *V, F.getParent()); + ++NoModRef; break; + case AliasAnalysis::Mod: + PrintModRefResults(" Mod", PrintMod, I, *V, F.getParent()); + ++Mod; break; + case AliasAnalysis::Ref: + PrintModRefResults(" Ref", PrintRef, I, *V, F.getParent()); + ++Ref; break; + case AliasAnalysis::ModRef: + PrintModRefResults(" ModRef", PrintModRef, I, *V, F.getParent()); + ++ModRef; break; + default: + errs() << "Unknown alias query result!\n"; + } + } + } + + return false; +} + +static void PrintPercent(unsigned Num, unsigned Sum) { + errs() << "(" << Num*100ULL/Sum << "." + << ((Num*1000ULL/Sum) % 10) << "%)\n"; +} + +bool AAEval::doFinalization(Module &M) { + unsigned AliasSum = NoAlias + MayAlias + MustAlias; + errs() << "===== Alias Analysis Evaluator Report =====\n"; + if (AliasSum == 0) { + errs() << " Alias Analysis Evaluator Summary: No pointers!\n"; + } else { + errs() << " " << AliasSum << " Total Alias Queries Performed\n"; + errs() << " " << NoAlias << " no alias responses "; + PrintPercent(NoAlias, AliasSum); + errs() << " " << MayAlias << " may alias responses "; + PrintPercent(MayAlias, AliasSum); + errs() << " " << MustAlias << " must alias responses "; + PrintPercent(MustAlias, AliasSum); + errs() << " Alias Analysis Evaluator Pointer Alias Summary: " + << NoAlias*100/AliasSum << "%/" << MayAlias*100/AliasSum << "%/" + << MustAlias*100/AliasSum << "%\n"; + } + + // Display the summary for mod/ref analysis + unsigned ModRefSum = NoModRef + Mod + Ref + ModRef; + if (ModRefSum == 0) { + errs() << " Alias Analysis Mod/Ref Evaluator Summary: no mod/ref!\n"; + } else { + errs() << " " << ModRefSum << " Total ModRef Queries Performed\n"; + errs() << " " << NoModRef << " no mod/ref responses "; + PrintPercent(NoModRef, ModRefSum); + errs() << " " << Mod << " mod responses "; + PrintPercent(Mod, ModRefSum); + errs() << " " << Ref << " ref responses "; + PrintPercent(Ref, ModRefSum); + errs() << " " << ModRef << " mod & ref responses "; + PrintPercent(ModRef, ModRefSum); + errs() << " Alias Analysis Evaluator Mod/Ref Summary: " + << NoModRef*100/ModRefSum << "%/" << Mod*100/ModRefSum << "%/" + << Ref*100/ModRefSum << "%/" << ModRef*100/ModRefSum << "%\n"; + } + + return false; +} diff --git a/libclamav/c++/llvm/lib/Analysis/AliasDebugger.cpp b/libclamav/c++/llvm/lib/Analysis/AliasDebugger.cpp new file mode 100644 index 000000000..6868e3f2c --- /dev/null +++ b/libclamav/c++/llvm/lib/Analysis/AliasDebugger.cpp @@ -0,0 +1,116 @@ +//===- AliasDebugger.cpp - Simple Alias Analysis Use Checker --------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This simple pass checks alias analysis users to ensure that if they +// create a new value, they do not query AA without informing it of the value. +// It acts as a shim over any other AA pass you want. +// +// Yes keeping track of every value in the program is expensive, but this is +// a debugging pass. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Analysis/Passes.h" +#include "llvm/Module.h" +#include "llvm/Pass.h" +#include "llvm/Instructions.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Analysis/AliasAnalysis.h" +#include +using namespace llvm; + +namespace { + + class AliasDebugger : public ModulePass, public AliasAnalysis { + + //What we do is simple. Keep track of every value the AA could + //know about, and verify that queries are one of those. + //A query to a value that didn't exist when the AA was created + //means someone forgot to update the AA when creating new values + + std::set Vals; + + public: + static char ID; // Class identification, replacement for typeinfo + AliasDebugger() : ModulePass(&ID) {} + + bool runOnModule(Module &M) { + InitializeAliasAnalysis(this); // set up super class + + for(Module::global_iterator I = M.global_begin(), + E = M.global_end(); I != E; ++I) + Vals.insert(&*I); + + for(Module::iterator I = M.begin(), + E = M.end(); I != E; ++I){ + Vals.insert(&*I); + if(!I->isDeclaration()) { + for (Function::arg_iterator AI = I->arg_begin(), AE = I->arg_end(); + AI != AE; ++AI) + Vals.insert(&*AI); + for (Function::const_iterator FI = I->begin(), FE = I->end(); + FI != FE; ++FI) + for (BasicBlock::const_iterator BI = FI->begin(), BE = FI->end(); + BI != BE; ++BI) + Vals.insert(&*BI); + } + + } + return false; + } + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AliasAnalysis::getAnalysisUsage(AU); + AU.setPreservesAll(); // Does not transform code + } + + //------------------------------------------------ + // Implement the AliasAnalysis API + // + AliasResult alias(const Value *V1, unsigned V1Size, + const Value *V2, unsigned V2Size) { + assert(Vals.find(V1) != Vals.end() && "Never seen value in AA before"); + assert(Vals.find(V2) != Vals.end() && "Never seen value in AA before"); + return AliasAnalysis::alias(V1, V1Size, V2, V2Size); + } + + ModRefResult getModRefInfo(CallSite CS, Value *P, unsigned Size) { + assert(Vals.find(P) != Vals.end() && "Never seen value in AA before"); + return AliasAnalysis::getModRefInfo(CS, P, Size); + } + + ModRefResult getModRefInfo(CallSite CS1, CallSite CS2) { + return AliasAnalysis::getModRefInfo(CS1,CS2); + } + + bool pointsToConstantMemory(const Value *P) { + assert(Vals.find(P) != Vals.end() && "Never seen value in AA before"); + return AliasAnalysis::pointsToConstantMemory(P); + } + + virtual void deleteValue(Value *V) { + assert(Vals.find(V) != Vals.end() && "Never seen value in AA before"); + AliasAnalysis::deleteValue(V); + } + virtual void copyValue(Value *From, Value *To) { + Vals.insert(To); + AliasAnalysis::copyValue(From, To); + } + + }; +} + +char AliasDebugger::ID = 0; +static RegisterPass +X("debug-aa", "AA use debugger", false, true); +static RegisterAnalysisGroup Y(X); + +Pass *llvm::createAliasDebugger() { return new AliasDebugger(); } + diff --git a/libclamav/c++/llvm/lib/Analysis/AliasSetTracker.cpp b/libclamav/c++/llvm/lib/Analysis/AliasSetTracker.cpp new file mode 100644 index 000000000..663460037 --- /dev/null +++ b/libclamav/c++/llvm/lib/Analysis/AliasSetTracker.cpp @@ -0,0 +1,603 @@ +//===- AliasSetTracker.cpp - Alias Sets Tracker implementation-------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the AliasSetTracker and AliasSet classes. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Analysis/AliasSetTracker.h" +#include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/Instructions.h" +#include "llvm/IntrinsicInst.h" +#include "llvm/Pass.h" +#include "llvm/Type.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Assembly/Writer.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/InstIterator.h" +#include "llvm/Support/Format.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +/// mergeSetIn - Merge the specified alias set into this alias set. +/// +void AliasSet::mergeSetIn(AliasSet &AS, AliasSetTracker &AST) { + assert(!AS.Forward && "Alias set is already forwarding!"); + assert(!Forward && "This set is a forwarding set!!"); + + // Update the alias and access types of this set... + AccessTy |= AS.AccessTy; + AliasTy |= AS.AliasTy; + + if (AliasTy == MustAlias) { + // Check that these two merged sets really are must aliases. Since both + // used to be must-alias sets, we can just check any pointer from each set + // for aliasing. + AliasAnalysis &AA = AST.getAliasAnalysis(); + PointerRec *L = getSomePointer(); + PointerRec *R = AS.getSomePointer(); + + // If the pointers are not a must-alias pair, this set becomes a may alias. + if (AA.alias(L->getValue(), L->getSize(), R->getValue(), R->getSize()) + != AliasAnalysis::MustAlias) + AliasTy = MayAlias; + } + + if (CallSites.empty()) { // Merge call sites... + if (!AS.CallSites.empty()) + std::swap(CallSites, AS.CallSites); + } else if (!AS.CallSites.empty()) { + CallSites.insert(CallSites.end(), AS.CallSites.begin(), AS.CallSites.end()); + AS.CallSites.clear(); + } + + AS.Forward = this; // Forward across AS now... + addRef(); // AS is now pointing to us... + + // Merge the list of constituent pointers... + if (AS.PtrList) { + *PtrListEnd = AS.PtrList; + AS.PtrList->setPrevInList(PtrListEnd); + PtrListEnd = AS.PtrListEnd; + + AS.PtrList = 0; + AS.PtrListEnd = &AS.PtrList; + assert(*AS.PtrListEnd == 0 && "End of list is not null?"); + } +} + +void AliasSetTracker::removeAliasSet(AliasSet *AS) { + if (AliasSet *Fwd = AS->Forward) { + Fwd->dropRef(*this); + AS->Forward = 0; + } + AliasSets.erase(AS); +} + +void AliasSet::removeFromTracker(AliasSetTracker &AST) { + assert(RefCount == 0 && "Cannot remove non-dead alias set from tracker!"); + AST.removeAliasSet(this); +} + +void AliasSet::addPointer(AliasSetTracker &AST, PointerRec &Entry, + unsigned Size, bool KnownMustAlias) { + assert(!Entry.hasAliasSet() && "Entry already in set!"); + + // Check to see if we have to downgrade to _may_ alias. + if (isMustAlias() && !KnownMustAlias) + if (PointerRec *P = getSomePointer()) { + AliasAnalysis &AA = AST.getAliasAnalysis(); + AliasAnalysis::AliasResult Result = + AA.alias(P->getValue(), P->getSize(), Entry.getValue(), Size); + if (Result == AliasAnalysis::MayAlias) + AliasTy = MayAlias; + else // First entry of must alias must have maximum size! + P->updateSize(Size); + assert(Result != AliasAnalysis::NoAlias && "Cannot be part of must set!"); + } + + Entry.setAliasSet(this); + Entry.updateSize(Size); + + // Add it to the end of the list... + assert(*PtrListEnd == 0 && "End of list is not null?"); + *PtrListEnd = &Entry; + PtrListEnd = Entry.setPrevInList(PtrListEnd); + assert(*PtrListEnd == 0 && "End of list is not null?"); + addRef(); // Entry points to alias set... +} + +void AliasSet::addCallSite(CallSite CS, AliasAnalysis &AA) { + CallSites.push_back(CS); + + AliasAnalysis::ModRefBehavior Behavior = AA.getModRefBehavior(CS); + if (Behavior == AliasAnalysis::DoesNotAccessMemory) + return; + else if (Behavior == AliasAnalysis::OnlyReadsMemory) { + AliasTy = MayAlias; + AccessTy |= Refs; + return; + } + + // FIXME: This should use mod/ref information to make this not suck so bad + AliasTy = MayAlias; + AccessTy = ModRef; +} + +/// aliasesPointer - Return true if the specified pointer "may" (or must) +/// alias one of the members in the set. +/// +bool AliasSet::aliasesPointer(const Value *Ptr, unsigned Size, + AliasAnalysis &AA) const { + if (AliasTy == MustAlias) { + assert(CallSites.empty() && "Illegal must alias set!"); + + // If this is a set of MustAliases, only check to see if the pointer aliases + // SOME value in the set... + PointerRec *SomePtr = getSomePointer(); + assert(SomePtr && "Empty must-alias set??"); + return AA.alias(SomePtr->getValue(), SomePtr->getSize(), Ptr, Size); + } + + // If this is a may-alias set, we have to check all of the pointers in the set + // to be sure it doesn't alias the set... + for (iterator I = begin(), E = end(); I != E; ++I) + if (AA.alias(Ptr, Size, I.getPointer(), I.getSize())) + return true; + + // Check the call sites list and invoke list... + if (!CallSites.empty()) { + for (unsigned i = 0, e = CallSites.size(); i != e; ++i) + if (AA.getModRefInfo(CallSites[i], const_cast(Ptr), Size) + != AliasAnalysis::NoModRef) + return true; + } + + return false; +} + +bool AliasSet::aliasesCallSite(CallSite CS, AliasAnalysis &AA) const { + if (AA.doesNotAccessMemory(CS)) + return false; + + for (unsigned i = 0, e = CallSites.size(); i != e; ++i) + if (AA.getModRefInfo(CallSites[i], CS) != AliasAnalysis::NoModRef || + AA.getModRefInfo(CS, CallSites[i]) != AliasAnalysis::NoModRef) + return true; + + for (iterator I = begin(), E = end(); I != E; ++I) + if (AA.getModRefInfo(CS, I.getPointer(), I.getSize()) != + AliasAnalysis::NoModRef) + return true; + + return false; +} + +void AliasSetTracker::clear() { + // Delete all the PointerRec entries. + for (PointerMapType::iterator I = PointerMap.begin(), E = PointerMap.end(); + I != E; ++I) + I->second->eraseFromList(); + + PointerMap.clear(); + + // The alias sets should all be clear now. + AliasSets.clear(); +} + + +/// findAliasSetForPointer - Given a pointer, find the one alias set to put the +/// instruction referring to the pointer into. If there are multiple alias sets +/// that may alias the pointer, merge them together and return the unified set. +/// +AliasSet *AliasSetTracker::findAliasSetForPointer(const Value *Ptr, + unsigned Size) { + AliasSet *FoundSet = 0; + for (iterator I = begin(), E = end(); I != E; ++I) + if (!I->Forward && I->aliasesPointer(Ptr, Size, AA)) { + if (FoundSet == 0) { // If this is the first alias set ptr can go into. + FoundSet = I; // Remember it. + } else { // Otherwise, we must merge the sets. + FoundSet->mergeSetIn(*I, *this); // Merge in contents. + } + } + + return FoundSet; +} + +/// containsPointer - Return true if the specified location is represented by +/// this alias set, false otherwise. This does not modify the AST object or +/// alias sets. +bool AliasSetTracker::containsPointer(Value *Ptr, unsigned Size) const { + for (const_iterator I = begin(), E = end(); I != E; ++I) + if (!I->Forward && I->aliasesPointer(Ptr, Size, AA)) + return true; + return false; +} + + + +AliasSet *AliasSetTracker::findAliasSetForCallSite(CallSite CS) { + AliasSet *FoundSet = 0; + for (iterator I = begin(), E = end(); I != E; ++I) + if (!I->Forward && I->aliasesCallSite(CS, AA)) { + if (FoundSet == 0) { // If this is the first alias set ptr can go into. + FoundSet = I; // Remember it. + } else if (!I->Forward) { // Otherwise, we must merge the sets. + FoundSet->mergeSetIn(*I, *this); // Merge in contents. + } + } + + return FoundSet; +} + + + + +/// getAliasSetForPointer - Return the alias set that the specified pointer +/// lives in. +AliasSet &AliasSetTracker::getAliasSetForPointer(Value *Pointer, unsigned Size, + bool *New) { + AliasSet::PointerRec &Entry = getEntryFor(Pointer); + + // Check to see if the pointer is already known... + if (Entry.hasAliasSet()) { + Entry.updateSize(Size); + // Return the set! + return *Entry.getAliasSet(*this)->getForwardedTarget(*this); + } else if (AliasSet *AS = findAliasSetForPointer(Pointer, Size)) { + // Add it to the alias set it aliases... + AS->addPointer(*this, Entry, Size); + return *AS; + } else { + if (New) *New = true; + // Otherwise create a new alias set to hold the loaded pointer... + AliasSets.push_back(new AliasSet()); + AliasSets.back().addPointer(*this, Entry, Size); + return AliasSets.back(); + } +} + +bool AliasSetTracker::add(Value *Ptr, unsigned Size) { + bool NewPtr; + addPointer(Ptr, Size, AliasSet::NoModRef, NewPtr); + return NewPtr; +} + + +bool AliasSetTracker::add(LoadInst *LI) { + bool NewPtr; + AliasSet &AS = addPointer(LI->getOperand(0), + AA.getTypeStoreSize(LI->getType()), + AliasSet::Refs, NewPtr); + if (LI->isVolatile()) AS.setVolatile(); + return NewPtr; +} + +bool AliasSetTracker::add(StoreInst *SI) { + bool NewPtr; + Value *Val = SI->getOperand(0); + AliasSet &AS = addPointer(SI->getOperand(1), + AA.getTypeStoreSize(Val->getType()), + AliasSet::Mods, NewPtr); + if (SI->isVolatile()) AS.setVolatile(); + return NewPtr; +} + +bool AliasSetTracker::add(VAArgInst *VAAI) { + bool NewPtr; + addPointer(VAAI->getOperand(0), ~0, AliasSet::ModRef, NewPtr); + return NewPtr; +} + + +bool AliasSetTracker::add(CallSite CS) { + if (isa(CS.getInstruction())) + return true; // Ignore DbgInfo Intrinsics. + if (AA.doesNotAccessMemory(CS)) + return true; // doesn't alias anything + + AliasSet *AS = findAliasSetForCallSite(CS); + if (!AS) { + AliasSets.push_back(new AliasSet()); + AS = &AliasSets.back(); + AS->addCallSite(CS, AA); + return true; + } else { + AS->addCallSite(CS, AA); + return false; + } +} + +bool AliasSetTracker::add(Instruction *I) { + // Dispatch to one of the other add methods... + if (LoadInst *LI = dyn_cast(I)) + return add(LI); + else if (StoreInst *SI = dyn_cast(I)) + return add(SI); + else if (CallInst *CI = dyn_cast(I)) + return add(CI); + else if (InvokeInst *II = dyn_cast(I)) + return add(II); + else if (VAArgInst *VAAI = dyn_cast(I)) + return add(VAAI); + return true; +} + +void AliasSetTracker::add(BasicBlock &BB) { + for (BasicBlock::iterator I = BB.begin(), E = BB.end(); I != E; ++I) + add(I); +} + +void AliasSetTracker::add(const AliasSetTracker &AST) { + assert(&AA == &AST.AA && + "Merging AliasSetTracker objects with different Alias Analyses!"); + + // Loop over all of the alias sets in AST, adding the pointers contained + // therein into the current alias sets. This can cause alias sets to be + // merged together in the current AST. + for (const_iterator I = AST.begin(), E = AST.end(); I != E; ++I) + if (!I->Forward) { // Ignore forwarding alias sets + AliasSet &AS = const_cast(*I); + + // If there are any call sites in the alias set, add them to this AST. + for (unsigned i = 0, e = AS.CallSites.size(); i != e; ++i) + add(AS.CallSites[i]); + + // Loop over all of the pointers in this alias set... + AliasSet::iterator I = AS.begin(), E = AS.end(); + bool X; + for (; I != E; ++I) { + AliasSet &NewAS = addPointer(I.getPointer(), I.getSize(), + (AliasSet::AccessType)AS.AccessTy, X); + if (AS.isVolatile()) NewAS.setVolatile(); + } + } +} + +/// remove - Remove the specified (potentially non-empty) alias set from the +/// tracker. +void AliasSetTracker::remove(AliasSet &AS) { + // Drop all call sites. + AS.CallSites.clear(); + + // Clear the alias set. + unsigned NumRefs = 0; + while (!AS.empty()) { + AliasSet::PointerRec *P = AS.PtrList; + + Value *ValToRemove = P->getValue(); + + // Unlink and delete entry from the list of values. + P->eraseFromList(); + + // Remember how many references need to be dropped. + ++NumRefs; + + // Finally, remove the entry. + PointerMap.erase(ValToRemove); + } + + // Stop using the alias set, removing it. + AS.RefCount -= NumRefs; + if (AS.RefCount == 0) + AS.removeFromTracker(*this); +} + +bool AliasSetTracker::remove(Value *Ptr, unsigned Size) { + AliasSet *AS = findAliasSetForPointer(Ptr, Size); + if (!AS) return false; + remove(*AS); + return true; +} + +bool AliasSetTracker::remove(LoadInst *LI) { + unsigned Size = AA.getTypeStoreSize(LI->getType()); + AliasSet *AS = findAliasSetForPointer(LI->getOperand(0), Size); + if (!AS) return false; + remove(*AS); + return true; +} + +bool AliasSetTracker::remove(StoreInst *SI) { + unsigned Size = AA.getTypeStoreSize(SI->getOperand(0)->getType()); + AliasSet *AS = findAliasSetForPointer(SI->getOperand(1), Size); + if (!AS) return false; + remove(*AS); + return true; +} + +bool AliasSetTracker::remove(VAArgInst *VAAI) { + AliasSet *AS = findAliasSetForPointer(VAAI->getOperand(0), ~0); + if (!AS) return false; + remove(*AS); + return true; +} + +bool AliasSetTracker::remove(CallSite CS) { + if (AA.doesNotAccessMemory(CS)) + return false; // doesn't alias anything + + AliasSet *AS = findAliasSetForCallSite(CS); + if (!AS) return false; + remove(*AS); + return true; +} + +bool AliasSetTracker::remove(Instruction *I) { + // Dispatch to one of the other remove methods... + if (LoadInst *LI = dyn_cast(I)) + return remove(LI); + else if (StoreInst *SI = dyn_cast(I)) + return remove(SI); + else if (CallInst *CI = dyn_cast(I)) + return remove(CI); + else if (VAArgInst *VAAI = dyn_cast(I)) + return remove(VAAI); + return true; +} + + +// deleteValue method - This method is used to remove a pointer value from the +// AliasSetTracker entirely. It should be used when an instruction is deleted +// from the program to update the AST. If you don't use this, you would have +// dangling pointers to deleted instructions. +// +void AliasSetTracker::deleteValue(Value *PtrVal) { + // Notify the alias analysis implementation that this value is gone. + AA.deleteValue(PtrVal); + + // If this is a call instruction, remove the callsite from the appropriate + // AliasSet. + CallSite CS = CallSite::get(PtrVal); + if (CS.getInstruction()) + if (!AA.doesNotAccessMemory(CS)) + if (AliasSet *AS = findAliasSetForCallSite(CS)) + AS->removeCallSite(CS); + + // First, look up the PointerRec for this pointer. + PointerMapType::iterator I = PointerMap.find(PtrVal); + if (I == PointerMap.end()) return; // Noop + + // If we found one, remove the pointer from the alias set it is in. + AliasSet::PointerRec *PtrValEnt = I->second; + AliasSet *AS = PtrValEnt->getAliasSet(*this); + + // Unlink and delete from the list of values. + PtrValEnt->eraseFromList(); + + // Stop using the alias set. + AS->dropRef(*this); + + PointerMap.erase(I); +} + +// copyValue - This method should be used whenever a preexisting value in the +// program is copied or cloned, introducing a new value. Note that it is ok for +// clients that use this method to introduce the same value multiple times: if +// the tracker already knows about a value, it will ignore the request. +// +void AliasSetTracker::copyValue(Value *From, Value *To) { + // Notify the alias analysis implementation that this value is copied. + AA.copyValue(From, To); + + // First, look up the PointerRec for this pointer. + PointerMapType::iterator I = PointerMap.find(From); + if (I == PointerMap.end()) + return; // Noop + assert(I->second->hasAliasSet() && "Dead entry?"); + + AliasSet::PointerRec &Entry = getEntryFor(To); + if (Entry.hasAliasSet()) return; // Already in the tracker! + + // Add it to the alias set it aliases... + I = PointerMap.find(From); + AliasSet *AS = I->second->getAliasSet(*this); + AS->addPointer(*this, Entry, I->second->getSize(), true); +} + + + +//===----------------------------------------------------------------------===// +// AliasSet/AliasSetTracker Printing Support +//===----------------------------------------------------------------------===// + +void AliasSet::print(raw_ostream &OS) const { + OS << " AliasSet[" << format("0x%p", (void*)this) << "," << RefCount << "] "; + OS << (AliasTy == MustAlias ? "must" : "may") << " alias, "; + switch (AccessTy) { + case NoModRef: OS << "No access "; break; + case Refs : OS << "Ref "; break; + case Mods : OS << "Mod "; break; + case ModRef : OS << "Mod/Ref "; break; + default: llvm_unreachable("Bad value for AccessTy!"); + } + if (isVolatile()) OS << "[volatile] "; + if (Forward) + OS << " forwarding to " << (void*)Forward; + + + if (!empty()) { + OS << "Pointers: "; + for (iterator I = begin(), E = end(); I != E; ++I) { + if (I != begin()) OS << ", "; + WriteAsOperand(OS << "(", I.getPointer()); + OS << ", " << I.getSize() << ")"; + } + } + if (!CallSites.empty()) { + OS << "\n " << CallSites.size() << " Call Sites: "; + for (unsigned i = 0, e = CallSites.size(); i != e; ++i) { + if (i) OS << ", "; + WriteAsOperand(OS, CallSites[i].getCalledValue()); + } + } + OS << "\n"; +} + +void AliasSetTracker::print(raw_ostream &OS) const { + OS << "Alias Set Tracker: " << AliasSets.size() << " alias sets for " + << PointerMap.size() << " pointer values.\n"; + for (const_iterator I = begin(), E = end(); I != E; ++I) + I->print(OS); + OS << "\n"; +} + +void AliasSet::dump() const { print(errs()); } +void AliasSetTracker::dump() const { print(errs()); } + +//===----------------------------------------------------------------------===// +// ASTCallbackVH Class Implementation +//===----------------------------------------------------------------------===// + +void AliasSetTracker::ASTCallbackVH::deleted() { + assert(AST && "ASTCallbackVH called with a null AliasSetTracker!"); + AST->deleteValue(getValPtr()); + // this now dangles! +} + +AliasSetTracker::ASTCallbackVH::ASTCallbackVH(Value *V, AliasSetTracker *ast) + : CallbackVH(V), AST(ast) {} + +AliasSetTracker::ASTCallbackVH & +AliasSetTracker::ASTCallbackVH::operator=(Value *V) { + return *this = ASTCallbackVH(V, AST); +} + +//===----------------------------------------------------------------------===// +// AliasSetPrinter Pass +//===----------------------------------------------------------------------===// + +namespace { + class AliasSetPrinter : public FunctionPass { + AliasSetTracker *Tracker; + public: + static char ID; // Pass identification, replacement for typeid + AliasSetPrinter() : FunctionPass(&ID) {} + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + AU.addRequired(); + } + + virtual bool runOnFunction(Function &F) { + Tracker = new AliasSetTracker(getAnalysis()); + + for (inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I) + Tracker->add(&*I); + Tracker->print(errs()); + delete Tracker; + return false; + } + }; +} + +char AliasSetPrinter::ID = 0; +static RegisterPass +X("print-alias-sets", "Alias Set Printer", false, true); diff --git a/libclamav/c++/llvm/lib/Analysis/Analysis.cpp b/libclamav/c++/llvm/lib/Analysis/Analysis.cpp new file mode 100644 index 000000000..f8cb32321 --- /dev/null +++ b/libclamav/c++/llvm/lib/Analysis/Analysis.cpp @@ -0,0 +1,43 @@ +//===-- Analysis.cpp ------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm-c/Analysis.h" +#include "llvm/Analysis/Verifier.h" +#include + +using namespace llvm; + +int LLVMVerifyModule(LLVMModuleRef M, LLVMVerifierFailureAction Action, + char **OutMessages) { + std::string Messages; + + int Result = verifyModule(*unwrap(M), + static_cast(Action), + OutMessages? &Messages : 0); + + if (OutMessages) + *OutMessages = strdup(Messages.c_str()); + + return Result; +} + +int LLVMVerifyFunction(LLVMValueRef Fn, LLVMVerifierFailureAction Action) { + return verifyFunction(*unwrap(Fn), + static_cast(Action)); +} + +void LLVMViewFunctionCFG(LLVMValueRef Fn) { + Function *F = unwrap(Fn); + F->viewCFG(); +} + +void LLVMViewFunctionCFGOnly(LLVMValueRef Fn) { + Function *F = unwrap(Fn); + F->viewCFGOnly(); +} diff --git a/libclamav/c++/llvm/lib/Analysis/BasicAliasAnalysis.cpp b/libclamav/c++/llvm/lib/Analysis/BasicAliasAnalysis.cpp new file mode 100644 index 000000000..b2983c722 --- /dev/null +++ b/libclamav/c++/llvm/lib/Analysis/BasicAliasAnalysis.cpp @@ -0,0 +1,733 @@ +//===- BasicAliasAnalysis.cpp - Local Alias Analysis Impl -----------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the default implementation of the Alias Analysis interface +// that simply implements a few identities (two different globals cannot alias, +// etc), but otherwise does no analysis. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/Analysis/Passes.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Function.h" +#include "llvm/GlobalVariable.h" +#include "llvm/Instructions.h" +#include "llvm/IntrinsicInst.h" +#include "llvm/Operator.h" +#include "llvm/Pass.h" +#include "llvm/Analysis/CaptureTracking.h" +#include "llvm/Analysis/MemoryBuiltins.h" +#include "llvm/Analysis/ValueTracking.h" +#include "llvm/Target/TargetData.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/ErrorHandling.h" +#include +using namespace llvm; + +//===----------------------------------------------------------------------===// +// Useful predicates +//===----------------------------------------------------------------------===// + +/// isKnownNonNull - Return true if we know that the specified value is never +/// null. +static bool isKnownNonNull(const Value *V) { + // Alloca never returns null, malloc might. + if (isa(V)) return true; + + // A byval argument is never null. + if (const Argument *A = dyn_cast(V)) + return A->hasByValAttr(); + + // Global values are not null unless extern weak. + if (const GlobalValue *GV = dyn_cast(V)) + return !GV->hasExternalWeakLinkage(); + return false; +} + +/// isNonEscapingLocalObject - Return true if the pointer is to a function-local +/// object that never escapes from the function. +static bool isNonEscapingLocalObject(const Value *V) { + // If this is a local allocation, check to see if it escapes. + if (isa(V) || isNoAliasCall(V)) + // Set StoreCaptures to True so that we can assume in our callers that the + // pointer is not the result of a load instruction. Currently + // PointerMayBeCaptured doesn't have any special analysis for the + // StoreCaptures=false case; if it did, our callers could be refined to be + // more precise. + return !PointerMayBeCaptured(V, false, /*StoreCaptures=*/true); + + // If this is an argument that corresponds to a byval or noalias argument, + // then it has not escaped before entering the function. Check if it escapes + // inside the function. + if (const Argument *A = dyn_cast(V)) + if (A->hasByValAttr() || A->hasNoAliasAttr()) { + // Don't bother analyzing arguments already known not to escape. + if (A->hasNoCaptureAttr()) + return true; + return !PointerMayBeCaptured(V, false, /*StoreCaptures=*/true); + } + return false; +} + + +/// isObjectSmallerThan - Return true if we can prove that the object specified +/// by V is smaller than Size. +static bool isObjectSmallerThan(const Value *V, unsigned Size, + const TargetData &TD) { + const Type *AccessTy; + if (const GlobalVariable *GV = dyn_cast(V)) { + AccessTy = GV->getType()->getElementType(); + } else if (const AllocaInst *AI = dyn_cast(V)) { + if (!AI->isArrayAllocation()) + AccessTy = AI->getType()->getElementType(); + else + return false; + } else if (const CallInst* CI = extractMallocCall(V)) { + if (!isArrayMalloc(V, &TD)) + // The size is the argument to the malloc call. + if (const ConstantInt* C = dyn_cast(CI->getOperand(1))) + return (C->getZExtValue() < Size); + return false; + } else if (const Argument *A = dyn_cast(V)) { + if (A->hasByValAttr()) + AccessTy = cast(A->getType())->getElementType(); + else + return false; + } else { + return false; + } + + if (AccessTy->isSized()) + return TD.getTypeAllocSize(AccessTy) < Size; + return false; +} + +//===----------------------------------------------------------------------===// +// NoAA Pass +//===----------------------------------------------------------------------===// + +namespace { + /// NoAA - This class implements the -no-aa pass, which always returns "I + /// don't know" for alias queries. NoAA is unlike other alias analysis + /// implementations, in that it does not chain to a previous analysis. As + /// such it doesn't follow many of the rules that other alias analyses must. + /// + struct NoAA : public ImmutablePass, public AliasAnalysis { + static char ID; // Class identification, replacement for typeinfo + NoAA() : ImmutablePass(&ID) {} + explicit NoAA(void *PID) : ImmutablePass(PID) { } + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + } + + virtual void initializePass() { + TD = getAnalysisIfAvailable(); + } + + virtual AliasResult alias(const Value *V1, unsigned V1Size, + const Value *V2, unsigned V2Size) { + return MayAlias; + } + + virtual void getArgumentAccesses(Function *F, CallSite CS, + std::vector &Info) { + llvm_unreachable("This method may not be called on this function!"); + } + + virtual bool pointsToConstantMemory(const Value *P) { return false; } + virtual ModRefResult getModRefInfo(CallSite CS, Value *P, unsigned Size) { + return ModRef; + } + virtual ModRefResult getModRefInfo(CallSite CS1, CallSite CS2) { + return ModRef; + } + + virtual void deleteValue(Value *V) {} + virtual void copyValue(Value *From, Value *To) {} + }; +} // End of anonymous namespace + +// Register this pass... +char NoAA::ID = 0; +static RegisterPass +U("no-aa", "No Alias Analysis (always returns 'may' alias)", true, true); + +// Declare that we implement the AliasAnalysis interface +static RegisterAnalysisGroup V(U); + +ImmutablePass *llvm::createNoAAPass() { return new NoAA(); } + +//===----------------------------------------------------------------------===// +// BasicAA Pass +//===----------------------------------------------------------------------===// + +namespace { + /// BasicAliasAnalysis - This is the default alias analysis implementation. + /// Because it doesn't chain to a previous alias analysis (like -no-aa), it + /// derives from the NoAA class. + struct BasicAliasAnalysis : public NoAA { + static char ID; // Class identification, replacement for typeinfo + BasicAliasAnalysis() : NoAA(&ID) {} + AliasResult alias(const Value *V1, unsigned V1Size, + const Value *V2, unsigned V2Size) { + assert(VisitedPHIs.empty() && "VisitedPHIs must be cleared after use!"); + AliasResult Alias = aliasCheck(V1, V1Size, V2, V2Size); + VisitedPHIs.clear(); + return Alias; + } + + ModRefResult getModRefInfo(CallSite CS, Value *P, unsigned Size); + ModRefResult getModRefInfo(CallSite CS1, CallSite CS2); + + /// pointsToConstantMemory - Chase pointers until we find a (constant + /// global) or not. + bool pointsToConstantMemory(const Value *P); + + private: + // VisitedPHIs - Track PHI nodes visited by a aliasCheck() call. + SmallPtrSet VisitedPHIs; + + // aliasGEP - Provide a bunch of ad-hoc rules to disambiguate a GEP + // instruction against another. + AliasResult aliasGEP(const GEPOperator *V1, unsigned V1Size, + const Value *V2, unsigned V2Size, + const Value *UnderlyingV1, const Value *UnderlyingV2); + + // aliasPHI - Provide a bunch of ad-hoc rules to disambiguate a PHI + // instruction against another. + AliasResult aliasPHI(const PHINode *PN, unsigned PNSize, + const Value *V2, unsigned V2Size); + + /// aliasSelect - Disambiguate a Select instruction against another value. + AliasResult aliasSelect(const SelectInst *SI, unsigned SISize, + const Value *V2, unsigned V2Size); + + AliasResult aliasCheck(const Value *V1, unsigned V1Size, + const Value *V2, unsigned V2Size); + }; +} // End of anonymous namespace + +// Register this pass... +char BasicAliasAnalysis::ID = 0; +static RegisterPass +X("basicaa", "Basic Alias Analysis (default AA impl)", false, true); + +// Declare that we implement the AliasAnalysis interface +static RegisterAnalysisGroup Y(X); + +ImmutablePass *llvm::createBasicAliasAnalysisPass() { + return new BasicAliasAnalysis(); +} + + +/// pointsToConstantMemory - Chase pointers until we find a (constant +/// global) or not. +bool BasicAliasAnalysis::pointsToConstantMemory(const Value *P) { + if (const GlobalVariable *GV = + dyn_cast(P->getUnderlyingObject())) + // Note: this doesn't require GV to be "ODR" because it isn't legal for a + // global to be marked constant in some modules and non-constant in others. + // GV may even be a declaration, not a definition. + return GV->isConstant(); + return false; +} + + +/// getModRefInfo - Check to see if the specified callsite can clobber the +/// specified memory object. Since we only look at local properties of this +/// function, we really can't say much about this query. We do, however, use +/// simple "address taken" analysis on local objects. +AliasAnalysis::ModRefResult +BasicAliasAnalysis::getModRefInfo(CallSite CS, Value *P, unsigned Size) { + const Value *Object = P->getUnderlyingObject(); + + // If this is a tail call and P points to a stack location, we know that + // the tail call cannot access or modify the local stack. + // We cannot exclude byval arguments here; these belong to the caller of + // the current function not to the current function, and a tail callee + // may reference them. + if (isa(Object)) + if (CallInst *CI = dyn_cast(CS.getInstruction())) + if (CI->isTailCall()) + return NoModRef; + + // If the pointer is to a locally allocated object that does not escape, + // then the call can not mod/ref the pointer unless the call takes the pointer + // as an argument, and itself doesn't capture it. + if (!isa(Object) && CS.getInstruction() != Object && + isNonEscapingLocalObject(Object)) { + bool PassedAsArg = false; + unsigned ArgNo = 0; + for (CallSite::arg_iterator CI = CS.arg_begin(), CE = CS.arg_end(); + CI != CE; ++CI, ++ArgNo) { + // Only look at the no-capture pointer arguments. + if (!isa((*CI)->getType()) || + !CS.paramHasAttr(ArgNo+1, Attribute::NoCapture)) + continue; + + // If this is a no-capture pointer argument, see if we can tell that it + // is impossible to alias the pointer we're checking. If not, we have to + // assume that the call could touch the pointer, even though it doesn't + // escape. + if (!isNoAlias(cast(CI), ~0U, P, ~0U)) { + PassedAsArg = true; + break; + } + } + + if (!PassedAsArg) + return NoModRef; + } + + // Finally, handle specific knowledge of intrinsics. + IntrinsicInst *II = dyn_cast(CS.getInstruction()); + if (II == 0) + return AliasAnalysis::getModRefInfo(CS, P, Size); + + switch (II->getIntrinsicID()) { + default: break; + case Intrinsic::memcpy: + case Intrinsic::memmove: { + unsigned Len = ~0U; + if (ConstantInt *LenCI = dyn_cast(II->getOperand(3))) + Len = LenCI->getZExtValue(); + Value *Dest = II->getOperand(1); + Value *Src = II->getOperand(2); + if (isNoAlias(Dest, Len, P, Size)) { + if (isNoAlias(Src, Len, P, Size)) + return NoModRef; + return Ref; + } + break; + } + case Intrinsic::memset: + // Since memset is 'accesses arguments' only, the AliasAnalysis base class + // will handle it for the variable length case. + if (ConstantInt *LenCI = dyn_cast(II->getOperand(3))) { + unsigned Len = LenCI->getZExtValue(); + Value *Dest = II->getOperand(1); + if (isNoAlias(Dest, Len, P, Size)) + return NoModRef; + } + break; + case Intrinsic::atomic_cmp_swap: + case Intrinsic::atomic_swap: + case Intrinsic::atomic_load_add: + case Intrinsic::atomic_load_sub: + case Intrinsic::atomic_load_and: + case Intrinsic::atomic_load_nand: + case Intrinsic::atomic_load_or: + case Intrinsic::atomic_load_xor: + case Intrinsic::atomic_load_max: + case Intrinsic::atomic_load_min: + case Intrinsic::atomic_load_umax: + case Intrinsic::atomic_load_umin: + if (TD) { + Value *Op1 = II->getOperand(1); + unsigned Op1Size = TD->getTypeStoreSize(Op1->getType()); + if (isNoAlias(Op1, Op1Size, P, Size)) + return NoModRef; + } + break; + case Intrinsic::lifetime_start: + case Intrinsic::lifetime_end: + case Intrinsic::invariant_start: { + unsigned PtrSize = cast(II->getOperand(1))->getZExtValue(); + if (isNoAlias(II->getOperand(2), PtrSize, P, Size)) + return NoModRef; + break; + } + case Intrinsic::invariant_end: { + unsigned PtrSize = cast(II->getOperand(2))->getZExtValue(); + if (isNoAlias(II->getOperand(3), PtrSize, P, Size)) + return NoModRef; + break; + } + } + + // The AliasAnalysis base class has some smarts, lets use them. + return AliasAnalysis::getModRefInfo(CS, P, Size); +} + + +AliasAnalysis::ModRefResult +BasicAliasAnalysis::getModRefInfo(CallSite CS1, CallSite CS2) { + // If CS1 or CS2 are readnone, they don't interact. + ModRefBehavior CS1B = AliasAnalysis::getModRefBehavior(CS1); + if (CS1B == DoesNotAccessMemory) return NoModRef; + + ModRefBehavior CS2B = AliasAnalysis::getModRefBehavior(CS2); + if (CS2B == DoesNotAccessMemory) return NoModRef; + + // If they both only read from memory, just return ref. + if (CS1B == OnlyReadsMemory && CS2B == OnlyReadsMemory) + return Ref; + + // Otherwise, fall back to NoAA (mod+ref). + return NoAA::getModRefInfo(CS1, CS2); +} + +/// GetIndiceDifference - Dest and Src are the variable indices from two +/// decomposed GetElementPtr instructions GEP1 and GEP2 which have common base +/// pointers. Subtract the GEP2 indices from GEP1 to find the symbolic +/// difference between the two pointers. +static void GetIndiceDifference( + SmallVectorImpl > &Dest, + const SmallVectorImpl > &Src) { + if (Src.empty()) return; + + for (unsigned i = 0, e = Src.size(); i != e; ++i) { + const Value *V = Src[i].first; + int64_t Scale = Src[i].second; + + // Find V in Dest. This is N^2, but pointer indices almost never have more + // than a few variable indexes. + for (unsigned j = 0, e = Dest.size(); j != e; ++j) { + if (Dest[j].first != V) continue; + + // If we found it, subtract off Scale V's from the entry in Dest. If it + // goes to zero, remove the entry. + if (Dest[j].second != Scale) + Dest[j].second -= Scale; + else + Dest.erase(Dest.begin()+j); + Scale = 0; + break; + } + + // If we didn't consume this entry, add it to the end of the Dest list. + if (Scale) + Dest.push_back(std::make_pair(V, -Scale)); + } +} + +/// aliasGEP - Provide a bunch of ad-hoc rules to disambiguate a GEP instruction +/// against another pointer. We know that V1 is a GEP, but we don't know +/// anything about V2. UnderlyingV1 is GEP1->getUnderlyingObject(), +/// UnderlyingV2 is the same for V2. +/// +AliasAnalysis::AliasResult +BasicAliasAnalysis::aliasGEP(const GEPOperator *GEP1, unsigned V1Size, + const Value *V2, unsigned V2Size, + const Value *UnderlyingV1, + const Value *UnderlyingV2) { + int64_t GEP1BaseOffset; + SmallVector, 4> GEP1VariableIndices; + + // If we have two gep instructions with must-alias'ing base pointers, figure + // out if the indexes to the GEP tell us anything about the derived pointer. + if (const GEPOperator *GEP2 = dyn_cast(V2)) { + // Do the base pointers alias? + AliasResult BaseAlias = aliasCheck(UnderlyingV1, ~0U, UnderlyingV2, ~0U); + + // If we get a No or May, then return it immediately, no amount of analysis + // will improve this situation. + if (BaseAlias != MustAlias) return BaseAlias; + + // Otherwise, we have a MustAlias. Since the base pointers alias each other + // exactly, see if the computed offset from the common pointer tells us + // about the relation of the resulting pointer. + const Value *GEP1BasePtr = + DecomposeGEPExpression(GEP1, GEP1BaseOffset, GEP1VariableIndices, TD); + + int64_t GEP2BaseOffset; + SmallVector, 4> GEP2VariableIndices; + const Value *GEP2BasePtr = + DecomposeGEPExpression(GEP2, GEP2BaseOffset, GEP2VariableIndices, TD); + + // If DecomposeGEPExpression isn't able to look all the way through the + // addressing operation, we must not have TD and this is too complex for us + // to handle without it. + if (GEP1BasePtr != UnderlyingV1 || GEP2BasePtr != UnderlyingV2) { + assert(TD == 0 && + "DecomposeGEPExpression and getUnderlyingObject disagree!"); + return MayAlias; + } + + // Subtract the GEP2 pointer from the GEP1 pointer to find out their + // symbolic difference. + GEP1BaseOffset -= GEP2BaseOffset; + GetIndiceDifference(GEP1VariableIndices, GEP2VariableIndices); + + } else { + // Check to see if these two pointers are related by the getelementptr + // instruction. If one pointer is a GEP with a non-zero index of the other + // pointer, we know they cannot alias. + + // If both accesses are unknown size, we can't do anything useful here. + if (V1Size == ~0U && V2Size == ~0U) + return MayAlias; + + AliasResult R = aliasCheck(UnderlyingV1, ~0U, V2, V2Size); + if (R != MustAlias) + // If V2 may alias GEP base pointer, conservatively returns MayAlias. + // If V2 is known not to alias GEP base pointer, then the two values + // cannot alias per GEP semantics: "A pointer value formed from a + // getelementptr instruction is associated with the addresses associated + // with the first operand of the getelementptr". + return R; + + const Value *GEP1BasePtr = + DecomposeGEPExpression(GEP1, GEP1BaseOffset, GEP1VariableIndices, TD); + + // If DecomposeGEPExpression isn't able to look all the way through the + // addressing operation, we must not have TD and this is too complex for us + // to handle without it. + if (GEP1BasePtr != UnderlyingV1) { + assert(TD == 0 && + "DecomposeGEPExpression and getUnderlyingObject disagree!"); + return MayAlias; + } + } + + // In the two GEP Case, if there is no difference in the offsets of the + // computed pointers, the resultant pointers are a must alias. This + // hapens when we have two lexically identical GEP's (for example). + // + // In the other case, if we have getelementptr , 0, 0, 0, 0, ... and V2 + // must aliases the GEP, the end result is a must alias also. + if (GEP1BaseOffset == 0 && GEP1VariableIndices.empty()) + return MustAlias; + + // If we have a known constant offset, see if this offset is larger than the + // access size being queried. If so, and if no variable indices can remove + // pieces of this constant, then we know we have a no-alias. For example, + // &A[100] != &A. + + // In order to handle cases like &A[100][i] where i is an out of range + // subscript, we have to ignore all constant offset pieces that are a multiple + // of a scaled index. Do this by removing constant offsets that are a + // multiple of any of our variable indices. This allows us to transform + // things like &A[i][1] because i has a stride of (e.g.) 8 bytes but the 1 + // provides an offset of 4 bytes (assuming a <= 4 byte access). + for (unsigned i = 0, e = GEP1VariableIndices.size(); + i != e && GEP1BaseOffset;++i) + if (int64_t RemovedOffset = GEP1BaseOffset/GEP1VariableIndices[i].second) + GEP1BaseOffset -= RemovedOffset*GEP1VariableIndices[i].second; + + // If our known offset is bigger than the access size, we know we don't have + // an alias. + if (GEP1BaseOffset) { + if (GEP1BaseOffset >= (int64_t)V2Size || + GEP1BaseOffset <= -(int64_t)V1Size) + return NoAlias; + } + + return MayAlias; +} + +/// aliasSelect - Provide a bunch of ad-hoc rules to disambiguate a Select +/// instruction against another. +AliasAnalysis::AliasResult +BasicAliasAnalysis::aliasSelect(const SelectInst *SI, unsigned SISize, + const Value *V2, unsigned V2Size) { + // If the values are Selects with the same condition, we can do a more precise + // check: just check for aliases between the values on corresponding arms. + if (const SelectInst *SI2 = dyn_cast(V2)) + if (SI->getCondition() == SI2->getCondition()) { + AliasResult Alias = + aliasCheck(SI->getTrueValue(), SISize, + SI2->getTrueValue(), V2Size); + if (Alias == MayAlias) + return MayAlias; + AliasResult ThisAlias = + aliasCheck(SI->getFalseValue(), SISize, + SI2->getFalseValue(), V2Size); + if (ThisAlias != Alias) + return MayAlias; + return Alias; + } + + // If both arms of the Select node NoAlias or MustAlias V2, then returns + // NoAlias / MustAlias. Otherwise, returns MayAlias. + AliasResult Alias = + aliasCheck(SI->getTrueValue(), SISize, V2, V2Size); + if (Alias == MayAlias) + return MayAlias; + AliasResult ThisAlias = + aliasCheck(SI->getFalseValue(), SISize, V2, V2Size); + if (ThisAlias != Alias) + return MayAlias; + return Alias; +} + +// aliasPHI - Provide a bunch of ad-hoc rules to disambiguate a PHI instruction +// against another. +AliasAnalysis::AliasResult +BasicAliasAnalysis::aliasPHI(const PHINode *PN, unsigned PNSize, + const Value *V2, unsigned V2Size) { + // The PHI node has already been visited, avoid recursion any further. + if (!VisitedPHIs.insert(PN)) + return MayAlias; + + // If the values are PHIs in the same block, we can do a more precise + // as well as efficient check: just check for aliases between the values + // on corresponding edges. + if (const PHINode *PN2 = dyn_cast(V2)) + if (PN2->getParent() == PN->getParent()) { + AliasResult Alias = + aliasCheck(PN->getIncomingValue(0), PNSize, + PN2->getIncomingValueForBlock(PN->getIncomingBlock(0)), + V2Size); + if (Alias == MayAlias) + return MayAlias; + for (unsigned i = 1, e = PN->getNumIncomingValues(); i != e; ++i) { + AliasResult ThisAlias = + aliasCheck(PN->getIncomingValue(i), PNSize, + PN2->getIncomingValueForBlock(PN->getIncomingBlock(i)), + V2Size); + if (ThisAlias != Alias) + return MayAlias; + } + return Alias; + } + + SmallPtrSet UniqueSrc; + SmallVector V1Srcs; + for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) { + Value *PV1 = PN->getIncomingValue(i); + if (isa(PV1)) + // If any of the source itself is a PHI, return MayAlias conservatively + // to avoid compile time explosion. The worst possible case is if both + // sides are PHI nodes. In which case, this is O(m x n) time where 'm' + // and 'n' are the number of PHI sources. + return MayAlias; + if (UniqueSrc.insert(PV1)) + V1Srcs.push_back(PV1); + } + + AliasResult Alias = aliasCheck(V2, V2Size, V1Srcs[0], PNSize); + // Early exit if the check of the first PHI source against V2 is MayAlias. + // Other results are not possible. + if (Alias == MayAlias) + return MayAlias; + + // If all sources of the PHI node NoAlias or MustAlias V2, then returns + // NoAlias / MustAlias. Otherwise, returns MayAlias. + for (unsigned i = 1, e = V1Srcs.size(); i != e; ++i) { + Value *V = V1Srcs[i]; + + // If V2 is a PHI, the recursive case will have been caught in the + // above aliasCheck call, so these subsequent calls to aliasCheck + // don't need to assume that V2 is being visited recursively. + VisitedPHIs.erase(V2); + + AliasResult ThisAlias = aliasCheck(V2, V2Size, V, PNSize); + if (ThisAlias != Alias || ThisAlias == MayAlias) + return MayAlias; + } + + return Alias; +} + +// aliasCheck - Provide a bunch of ad-hoc rules to disambiguate in common cases, +// such as array references. +// +AliasAnalysis::AliasResult +BasicAliasAnalysis::aliasCheck(const Value *V1, unsigned V1Size, + const Value *V2, unsigned V2Size) { + // Strip off any casts if they exist. + V1 = V1->stripPointerCasts(); + V2 = V2->stripPointerCasts(); + + // Are we checking for alias of the same value? + if (V1 == V2) return MustAlias; + + if (!isa(V1->getType()) || !isa(V2->getType())) + return NoAlias; // Scalars cannot alias each other + + // Figure out what objects these things are pointing to if we can. + const Value *O1 = V1->getUnderlyingObject(); + const Value *O2 = V2->getUnderlyingObject(); + + // Null values in the default address space don't point to any object, so they + // don't alias any other pointer. + if (const ConstantPointerNull *CPN = dyn_cast(O1)) + if (CPN->getType()->getAddressSpace() == 0) + return NoAlias; + if (const ConstantPointerNull *CPN = dyn_cast(O2)) + if (CPN->getType()->getAddressSpace() == 0) + return NoAlias; + + if (O1 != O2) { + // If V1/V2 point to two different objects we know that we have no alias. + if (isIdentifiedObject(O1) && isIdentifiedObject(O2)) + return NoAlias; + + // Constant pointers can't alias with non-const isIdentifiedObject objects. + if ((isa(O1) && isIdentifiedObject(O2) && !isa(O2)) || + (isa(O2) && isIdentifiedObject(O1) && !isa(O1))) + return NoAlias; + + // Arguments can't alias with local allocations or noalias calls. + if ((isa(O1) && (isa(O2) || isNoAliasCall(O2))) || + (isa(O2) && (isa(O1) || isNoAliasCall(O1)))) + return NoAlias; + + // Most objects can't alias null. + if ((isa(V2) && isKnownNonNull(O1)) || + (isa(V1) && isKnownNonNull(O2))) + return NoAlias; + } + + // If the size of one access is larger than the entire object on the other + // side, then we know such behavior is undefined and can assume no alias. + if (TD) + if ((V1Size != ~0U && isObjectSmallerThan(O2, V1Size, *TD)) || + (V2Size != ~0U && isObjectSmallerThan(O1, V2Size, *TD))) + return NoAlias; + + // If one pointer is the result of a call/invoke or load and the other is a + // non-escaping local object, then we know the object couldn't escape to a + // point where the call could return it. The load case works because + // isNonEscapingLocalObject considers all stores to be escapes (it + // passes true for the StoreCaptures argument to PointerMayBeCaptured). + if (O1 != O2) { + if ((isa(O1) || isa(O1) || isa(O1) || + isa(O1)) && + isNonEscapingLocalObject(O2)) + return NoAlias; + if ((isa(O2) || isa(O2) || isa(O2) || + isa(O2)) && + isNonEscapingLocalObject(O1)) + return NoAlias; + } + + // FIXME: This isn't aggressively handling alias(GEP, PHI) for example: if the + // GEP can't simplify, we don't even look at the PHI cases. + if (!isa(V1) && isa(V2)) { + std::swap(V1, V2); + std::swap(V1Size, V2Size); + std::swap(O1, O2); + } + if (const GEPOperator *GV1 = dyn_cast(V1)) + return aliasGEP(GV1, V1Size, V2, V2Size, O1, O2); + + if (isa(V2) && !isa(V1)) { + std::swap(V1, V2); + std::swap(V1Size, V2Size); + } + if (const PHINode *PN = dyn_cast(V1)) + return aliasPHI(PN, V1Size, V2, V2Size); + + if (isa(V2) && !isa(V1)) { + std::swap(V1, V2); + std::swap(V1Size, V2Size); + } + if (const SelectInst *S1 = dyn_cast(V1)) + return aliasSelect(S1, V1Size, V2, V2Size); + + return MayAlias; +} + +// Make sure that anything that uses AliasAnalysis pulls in this file. +DEFINING_FILE_FOR(BasicAliasAnalysis) diff --git a/libclamav/c++/llvm/lib/Analysis/CFGPrinter.cpp b/libclamav/c++/llvm/lib/Analysis/CFGPrinter.cpp new file mode 100644 index 000000000..e06704bd8 --- /dev/null +++ b/libclamav/c++/llvm/lib/Analysis/CFGPrinter.cpp @@ -0,0 +1,160 @@ +//===- CFGPrinter.cpp - DOT printer for the control flow graph ------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines a '-dot-cfg' analysis pass, which emits the +// cfg..dot file for each function in the program, with a graph of the +// CFG for that function. +// +// The other main feature of this file is that it implements the +// Function::viewCFG method, which is useful for debugging passes which operate +// on the CFG. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Analysis/CFGPrinter.h" + +#include "llvm/Pass.h" +using namespace llvm; + +namespace { + struct CFGViewer : public FunctionPass { + static char ID; // Pass identifcation, replacement for typeid + CFGViewer() : FunctionPass(&ID) {} + + virtual bool runOnFunction(Function &F) { + F.viewCFG(); + return false; + } + + void print(raw_ostream &OS, const Module* = 0) const {} + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + } + }; +} + +char CFGViewer::ID = 0; +static RegisterPass +V0("view-cfg", "View CFG of function", false, true); + +namespace { + struct CFGOnlyViewer : public FunctionPass { + static char ID; // Pass identifcation, replacement for typeid + CFGOnlyViewer() : FunctionPass(&ID) {} + + virtual bool runOnFunction(Function &F) { + F.viewCFGOnly(); + return false; + } + + void print(raw_ostream &OS, const Module* = 0) const {} + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + } + }; +} + +char CFGOnlyViewer::ID = 0; +static RegisterPass +V1("view-cfg-only", + "View CFG of function (with no function bodies)", false, true); + +namespace { + struct CFGPrinter : public FunctionPass { + static char ID; // Pass identification, replacement for typeid + CFGPrinter() : FunctionPass(&ID) {} + explicit CFGPrinter(void *pid) : FunctionPass(pid) {} + + virtual bool runOnFunction(Function &F) { + std::string Filename = "cfg." + F.getNameStr() + ".dot"; + errs() << "Writing '" << Filename << "'..."; + + std::string ErrorInfo; + raw_fd_ostream File(Filename.c_str(), ErrorInfo); + + if (ErrorInfo.empty()) + WriteGraph(File, (const Function*)&F); + else + errs() << " error opening file for writing!"; + errs() << "\n"; + return false; + } + + void print(raw_ostream &OS, const Module* = 0) const {} + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + } + }; +} + +char CFGPrinter::ID = 0; +static RegisterPass +P1("dot-cfg", "Print CFG of function to 'dot' file", false, true); + +namespace { + struct CFGOnlyPrinter : public FunctionPass { + static char ID; // Pass identification, replacement for typeid + CFGOnlyPrinter() : FunctionPass(&ID) {} + explicit CFGOnlyPrinter(void *pid) : FunctionPass(pid) {} + virtual bool runOnFunction(Function &F) { + std::string Filename = "cfg." + F.getNameStr() + ".dot"; + errs() << "Writing '" << Filename << "'..."; + + std::string ErrorInfo; + raw_fd_ostream File(Filename.c_str(), ErrorInfo); + + if (ErrorInfo.empty()) + WriteGraph(File, (const Function*)&F, true); + else + errs() << " error opening file for writing!"; + errs() << "\n"; + return false; + } + void print(raw_ostream &OS, const Module* = 0) const {} + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + } + }; +} + +char CFGOnlyPrinter::ID = 0; +static RegisterPass +P2("dot-cfg-only", + "Print CFG of function to 'dot' file (with no function bodies)", false, true); + +/// viewCFG - This function is meant for use from the debugger. You can just +/// say 'call F->viewCFG()' and a ghostview window should pop up from the +/// program, displaying the CFG of the current function. This depends on there +/// being a 'dot' and 'gv' program in your path. +/// +void Function::viewCFG() const { + ViewGraph(this, "cfg" + getNameStr()); +} + +/// viewCFGOnly - This function is meant for use from the debugger. It works +/// just like viewCFG, but it does not include the contents of basic blocks +/// into the nodes, just the label. If you are only interested in the CFG t +/// his can make the graph smaller. +/// +void Function::viewCFGOnly() const { + ViewGraph(this, "cfg" + getNameStr(), true); +} + +FunctionPass *llvm::createCFGPrinterPass () { + return new CFGPrinter(); +} + +FunctionPass *llvm::createCFGOnlyPrinterPass () { + return new CFGOnlyPrinter(); +} + diff --git a/libclamav/c++/llvm/lib/Analysis/CMakeLists.txt b/libclamav/c++/llvm/lib/Analysis/CMakeLists.txt new file mode 100644 index 000000000..0a83c3db8 --- /dev/null +++ b/libclamav/c++/llvm/lib/Analysis/CMakeLists.txt @@ -0,0 +1,45 @@ +add_llvm_library(LLVMAnalysis + AliasAnalysis.cpp + AliasAnalysisCounter.cpp + AliasAnalysisEvaluator.cpp + AliasDebugger.cpp + AliasSetTracker.cpp + Analysis.cpp + BasicAliasAnalysis.cpp + CFGPrinter.cpp + CaptureTracking.cpp + ConstantFolding.cpp + DbgInfoPrinter.cpp + DebugInfo.cpp + DomPrinter.cpp + IVUsers.cpp + InlineCost.cpp + InstCount.cpp + InstructionSimplify.cpp + Interval.cpp + IntervalPartition.cpp + LazyValueInfo.cpp + LibCallAliasAnalysis.cpp + LibCallSemantics.cpp + LiveValues.cpp + LoopDependenceAnalysis.cpp + LoopInfo.cpp + LoopPass.cpp + MemoryBuiltins.cpp + MemoryDependenceAnalysis.cpp + PointerTracking.cpp + PostDominators.cpp + ProfileEstimatorPass.cpp + ProfileInfo.cpp + ProfileInfoLoader.cpp + ProfileInfoLoaderPass.cpp + ProfileVerifierPass.cpp + ScalarEvolution.cpp + ScalarEvolutionAliasAnalysis.cpp + ScalarEvolutionExpander.cpp + SparsePropagation.cpp + Trace.cpp + ValueTracking.cpp + ) + +target_link_libraries (LLVMAnalysis LLVMSupport) diff --git a/libclamav/c++/llvm/lib/Analysis/CaptureTracking.cpp b/libclamav/c++/llvm/lib/Analysis/CaptureTracking.cpp new file mode 100644 index 000000000..a276c64c9 --- /dev/null +++ b/libclamav/c++/llvm/lib/Analysis/CaptureTracking.cpp @@ -0,0 +1,128 @@ +//===--- CaptureTracking.cpp - Determine whether a pointer is captured ----===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains routines that help determine which pointers are captured. +// A pointer value is captured if the function makes a copy of any part of the +// pointer that outlives the call. Not being captured means, more or less, that +// the pointer is only dereferenced and not stored in a global. Returning part +// of the pointer as the function return value may or may not count as capturing +// the pointer, depending on the context. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Analysis/CaptureTracking.h" +#include "llvm/Instructions.h" +#include "llvm/Value.h" +#include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/ADT/SmallSet.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/CallSite.h" +using namespace llvm; + +/// PointerMayBeCaptured - Return true if this pointer value may be captured +/// by the enclosing function (which is required to exist). This routine can +/// be expensive, so consider caching the results. The boolean ReturnCaptures +/// specifies whether returning the value (or part of it) from the function +/// counts as capturing it or not. The boolean StoreCaptures specified whether +/// storing the value (or part of it) into memory anywhere automatically +/// counts as capturing it or not. +bool llvm::PointerMayBeCaptured(const Value *V, + bool ReturnCaptures, bool StoreCaptures) { + assert(isa(V->getType()) && "Capture is for pointers only!"); + SmallVector Worklist; + SmallSet Visited; + + for (Value::use_const_iterator UI = V->use_begin(), UE = V->use_end(); + UI != UE; ++UI) { + Use *U = &UI.getUse(); + Visited.insert(U); + Worklist.push_back(U); + } + + while (!Worklist.empty()) { + Use *U = Worklist.pop_back_val(); + Instruction *I = cast(U->getUser()); + V = U->get(); + + switch (I->getOpcode()) { + case Instruction::Call: + case Instruction::Invoke: { + CallSite CS = CallSite::get(I); + // Not captured if the callee is readonly, doesn't return a copy through + // its return value and doesn't unwind (a readonly function can leak bits + // by throwing an exception or not depending on the input value). + if (CS.onlyReadsMemory() && CS.doesNotThrow() && I->getType()->isVoidTy()) + break; + + // Not captured if only passed via 'nocapture' arguments. Note that + // calling a function pointer does not in itself cause the pointer to + // be captured. This is a subtle point considering that (for example) + // the callee might return its own address. It is analogous to saying + // that loading a value from a pointer does not cause the pointer to be + // captured, even though the loaded value might be the pointer itself + // (think of self-referential objects). + CallSite::arg_iterator B = CS.arg_begin(), E = CS.arg_end(); + for (CallSite::arg_iterator A = B; A != E; ++A) + if (A->get() == V && !CS.paramHasAttr(A - B + 1, Attribute::NoCapture)) + // The parameter is not marked 'nocapture' - captured. + return true; + // Only passed via 'nocapture' arguments, or is the called function - not + // captured. + break; + } + case Instruction::Load: + // Loading from a pointer does not cause it to be captured. + break; + case Instruction::Ret: + if (ReturnCaptures) + return true; + break; + case Instruction::Store: + if (V == I->getOperand(0)) + // Stored the pointer - conservatively assume it may be captured. + // TODO: If StoreCaptures is not true, we could do Fancy analysis + // to determine whether this store is not actually an escape point. + // In that case, BasicAliasAnalysis should be updated as well to + // take advantage of this. + return true; + // Storing to the pointee does not cause the pointer to be captured. + break; + case Instruction::BitCast: + case Instruction::GetElementPtr: + case Instruction::PHI: + case Instruction::Select: + // The original value is not captured via this if the new value isn't. + for (Instruction::use_iterator UI = I->use_begin(), UE = I->use_end(); + UI != UE; ++UI) { + Use *U = &UI.getUse(); + if (Visited.insert(U)) + Worklist.push_back(U); + } + break; + case Instruction::ICmp: + // Don't count comparisons of a no-alias return value against null as + // captures. This allows us to ignore comparisons of malloc results + // with null, for example. + if (isNoAliasCall(V->stripPointerCasts())) + if (ConstantPointerNull *CPN = + dyn_cast(I->getOperand(1))) + if (CPN->getType()->getAddressSpace() == 0) + break; + // Otherwise, be conservative. There are crazy ways to capture pointers + // using comparisons. + return true; + default: + // Something else - be conservative and say it is captured. + return true; + } + } + + // All uses examined - not captured. + return false; +} diff --git a/libclamav/c++/llvm/lib/Analysis/ConstantFolding.cpp b/libclamav/c++/llvm/lib/Analysis/ConstantFolding.cpp new file mode 100644 index 000000000..8d60907f8 --- /dev/null +++ b/libclamav/c++/llvm/lib/Analysis/ConstantFolding.cpp @@ -0,0 +1,1210 @@ +//===-- ConstantFolding.cpp - Fold instructions into constants ------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines routines for folding instructions into constants. +// +// Also, to supplement the basic VMCore ConstantExpr simplifications, +// this file defines some additional folding routines that can make use of +// TargetData information. These functions cannot go in VMCore due to library +// dependency issues. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Analysis/ConstantFolding.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Function.h" +#include "llvm/GlobalVariable.h" +#include "llvm/Instructions.h" +#include "llvm/Intrinsics.h" +#include "llvm/Analysis/ValueTracking.h" +#include "llvm/Target/TargetData.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/GetElementPtrTypeIterator.h" +#include "llvm/Support/MathExtras.h" +#include +#include +using namespace llvm; + +//===----------------------------------------------------------------------===// +// Constant Folding internal helper functions +//===----------------------------------------------------------------------===// + +/// FoldBitCast - Constant fold bitcast, symbolically evaluating it with +/// TargetData. This always returns a non-null constant, but it may be a +/// ConstantExpr if unfoldable. +static Constant *FoldBitCast(Constant *C, const Type *DestTy, + const TargetData &TD) { + + // This only handles casts to vectors currently. + const VectorType *DestVTy = dyn_cast(DestTy); + if (DestVTy == 0) + return ConstantExpr::getBitCast(C, DestTy); + + // If this is a scalar -> vector cast, convert the input into a <1 x scalar> + // vector so the code below can handle it uniformly. + if (isa(C) || isa(C)) { + Constant *Ops = C; // don't take the address of C! + return FoldBitCast(ConstantVector::get(&Ops, 1), DestTy, TD); + } + + // If this is a bitcast from constant vector -> vector, fold it. + ConstantVector *CV = dyn_cast(C); + if (CV == 0) + return ConstantExpr::getBitCast(C, DestTy); + + // If the element types match, VMCore can fold it. + unsigned NumDstElt = DestVTy->getNumElements(); + unsigned NumSrcElt = CV->getNumOperands(); + if (NumDstElt == NumSrcElt) + return ConstantExpr::getBitCast(C, DestTy); + + const Type *SrcEltTy = CV->getType()->getElementType(); + const Type *DstEltTy = DestVTy->getElementType(); + + // Otherwise, we're changing the number of elements in a vector, which + // requires endianness information to do the right thing. For example, + // bitcast (<2 x i64> to <4 x i32>) + // folds to (little endian): + // <4 x i32> + // and to (big endian): + // <4 x i32> + + // First thing is first. We only want to think about integer here, so if + // we have something in FP form, recast it as integer. + if (DstEltTy->isFloatingPoint()) { + // Fold to an vector of integers with same size as our FP type. + unsigned FPWidth = DstEltTy->getPrimitiveSizeInBits(); + const Type *DestIVTy = + VectorType::get(IntegerType::get(C->getContext(), FPWidth), NumDstElt); + // Recursively handle this integer conversion, if possible. + C = FoldBitCast(C, DestIVTy, TD); + if (!C) return ConstantExpr::getBitCast(C, DestTy); + + // Finally, VMCore can handle this now that #elts line up. + return ConstantExpr::getBitCast(C, DestTy); + } + + // Okay, we know the destination is integer, if the input is FP, convert + // it to integer first. + if (SrcEltTy->isFloatingPoint()) { + unsigned FPWidth = SrcEltTy->getPrimitiveSizeInBits(); + const Type *SrcIVTy = + VectorType::get(IntegerType::get(C->getContext(), FPWidth), NumSrcElt); + // Ask VMCore to do the conversion now that #elts line up. + C = ConstantExpr::getBitCast(C, SrcIVTy); + CV = dyn_cast(C); + if (!CV) // If VMCore wasn't able to fold it, bail out. + return C; + } + + // Now we know that the input and output vectors are both integer vectors + // of the same size, and that their #elements is not the same. Do the + // conversion here, which depends on whether the input or output has + // more elements. + bool isLittleEndian = TD.isLittleEndian(); + + SmallVector Result; + if (NumDstElt < NumSrcElt) { + // Handle: bitcast (<4 x i32> to <2 x i64>) + Constant *Zero = Constant::getNullValue(DstEltTy); + unsigned Ratio = NumSrcElt/NumDstElt; + unsigned SrcBitSize = SrcEltTy->getPrimitiveSizeInBits(); + unsigned SrcElt = 0; + for (unsigned i = 0; i != NumDstElt; ++i) { + // Build each element of the result. + Constant *Elt = Zero; + unsigned ShiftAmt = isLittleEndian ? 0 : SrcBitSize*(Ratio-1); + for (unsigned j = 0; j != Ratio; ++j) { + Constant *Src = dyn_cast(CV->getOperand(SrcElt++)); + if (!Src) // Reject constantexpr elements. + return ConstantExpr::getBitCast(C, DestTy); + + // Zero extend the element to the right size. + Src = ConstantExpr::getZExt(Src, Elt->getType()); + + // Shift it to the right place, depending on endianness. + Src = ConstantExpr::getShl(Src, + ConstantInt::get(Src->getType(), ShiftAmt)); + ShiftAmt += isLittleEndian ? SrcBitSize : -SrcBitSize; + + // Mix it in. + Elt = ConstantExpr::getOr(Elt, Src); + } + Result.push_back(Elt); + } + } else { + // Handle: bitcast (<2 x i64> to <4 x i32>) + unsigned Ratio = NumDstElt/NumSrcElt; + unsigned DstBitSize = DstEltTy->getPrimitiveSizeInBits(); + + // Loop over each source value, expanding into multiple results. + for (unsigned i = 0; i != NumSrcElt; ++i) { + Constant *Src = dyn_cast(CV->getOperand(i)); + if (!Src) // Reject constantexpr elements. + return ConstantExpr::getBitCast(C, DestTy); + + unsigned ShiftAmt = isLittleEndian ? 0 : DstBitSize*(Ratio-1); + for (unsigned j = 0; j != Ratio; ++j) { + // Shift the piece of the value into the right place, depending on + // endianness. + Constant *Elt = ConstantExpr::getLShr(Src, + ConstantInt::get(Src->getType(), ShiftAmt)); + ShiftAmt += isLittleEndian ? DstBitSize : -DstBitSize; + + // Truncate and remember this piece. + Result.push_back(ConstantExpr::getTrunc(Elt, DstEltTy)); + } + } + } + + return ConstantVector::get(Result.data(), Result.size()); +} + + +/// IsConstantOffsetFromGlobal - If this constant is actually a constant offset +/// from a global, return the global and the constant. Because of +/// constantexprs, this function is recursive. +static bool IsConstantOffsetFromGlobal(Constant *C, GlobalValue *&GV, + int64_t &Offset, const TargetData &TD) { + // Trivial case, constant is the global. + if ((GV = dyn_cast(C))) { + Offset = 0; + return true; + } + + // Otherwise, if this isn't a constant expr, bail out. + ConstantExpr *CE = dyn_cast(C); + if (!CE) return false; + + // Look through ptr->int and ptr->ptr casts. + if (CE->getOpcode() == Instruction::PtrToInt || + CE->getOpcode() == Instruction::BitCast) + return IsConstantOffsetFromGlobal(CE->getOperand(0), GV, Offset, TD); + + // i32* getelementptr ([5 x i32]* @a, i32 0, i32 5) + if (CE->getOpcode() == Instruction::GetElementPtr) { + // Cannot compute this if the element type of the pointer is missing size + // info. + if (!cast(CE->getOperand(0)->getType()) + ->getElementType()->isSized()) + return false; + + // If the base isn't a global+constant, we aren't either. + if (!IsConstantOffsetFromGlobal(CE->getOperand(0), GV, Offset, TD)) + return false; + + // Otherwise, add any offset that our operands provide. + gep_type_iterator GTI = gep_type_begin(CE); + for (User::const_op_iterator i = CE->op_begin() + 1, e = CE->op_end(); + i != e; ++i, ++GTI) { + ConstantInt *CI = dyn_cast(*i); + if (!CI) return false; // Index isn't a simple constant? + if (CI->getZExtValue() == 0) continue; // Not adding anything. + + if (const StructType *ST = dyn_cast(*GTI)) { + // N = N + Offset + Offset += TD.getStructLayout(ST)->getElementOffset(CI->getZExtValue()); + } else { + const SequentialType *SQT = cast(*GTI); + Offset += TD.getTypeAllocSize(SQT->getElementType())*CI->getSExtValue(); + } + } + return true; + } + + return false; +} + +/// ReadDataFromGlobal - Recursive helper to read bits out of global. C is the +/// constant being copied out of. ByteOffset is an offset into C. CurPtr is the +/// pointer to copy results into and BytesLeft is the number of bytes left in +/// the CurPtr buffer. TD is the target data. +static bool ReadDataFromGlobal(Constant *C, uint64_t ByteOffset, + unsigned char *CurPtr, unsigned BytesLeft, + const TargetData &TD) { + assert(ByteOffset <= TD.getTypeAllocSize(C->getType()) && + "Out of range access"); + + // If this element is zero or undefined, we can just return since *CurPtr is + // zero initialized. + if (isa(C) || isa(C)) + return true; + + if (ConstantInt *CI = dyn_cast(C)) { + if (CI->getBitWidth() > 64 || + (CI->getBitWidth() & 7) != 0) + return false; + + uint64_t Val = CI->getZExtValue(); + unsigned IntBytes = unsigned(CI->getBitWidth()/8); + + for (unsigned i = 0; i != BytesLeft && ByteOffset != IntBytes; ++i) { + CurPtr[i] = (unsigned char)(Val >> (ByteOffset * 8)); + ++ByteOffset; + } + return true; + } + + if (ConstantFP *CFP = dyn_cast(C)) { + if (CFP->getType()->isDoubleTy()) { + C = FoldBitCast(C, Type::getInt64Ty(C->getContext()), TD); + return ReadDataFromGlobal(C, ByteOffset, CurPtr, BytesLeft, TD); + } + if (CFP->getType()->isFloatTy()){ + C = FoldBitCast(C, Type::getInt32Ty(C->getContext()), TD); + return ReadDataFromGlobal(C, ByteOffset, CurPtr, BytesLeft, TD); + } + return false; + } + + if (ConstantStruct *CS = dyn_cast(C)) { + const StructLayout *SL = TD.getStructLayout(CS->getType()); + unsigned Index = SL->getElementContainingOffset(ByteOffset); + uint64_t CurEltOffset = SL->getElementOffset(Index); + ByteOffset -= CurEltOffset; + + while (1) { + // If the element access is to the element itself and not to tail padding, + // read the bytes from the element. + uint64_t EltSize = TD.getTypeAllocSize(CS->getOperand(Index)->getType()); + + if (ByteOffset < EltSize && + !ReadDataFromGlobal(CS->getOperand(Index), ByteOffset, CurPtr, + BytesLeft, TD)) + return false; + + ++Index; + + // Check to see if we read from the last struct element, if so we're done. + if (Index == CS->getType()->getNumElements()) + return true; + + // If we read all of the bytes we needed from this element we're done. + uint64_t NextEltOffset = SL->getElementOffset(Index); + + if (BytesLeft <= NextEltOffset-CurEltOffset-ByteOffset) + return true; + + // Move to the next element of the struct. + CurPtr += NextEltOffset-CurEltOffset-ByteOffset; + BytesLeft -= NextEltOffset-CurEltOffset-ByteOffset; + ByteOffset = 0; + CurEltOffset = NextEltOffset; + } + // not reached. + } + + if (ConstantArray *CA = dyn_cast(C)) { + uint64_t EltSize = TD.getTypeAllocSize(CA->getType()->getElementType()); + uint64_t Index = ByteOffset / EltSize; + uint64_t Offset = ByteOffset - Index * EltSize; + for (; Index != CA->getType()->getNumElements(); ++Index) { + if (!ReadDataFromGlobal(CA->getOperand(Index), Offset, CurPtr, + BytesLeft, TD)) + return false; + if (EltSize >= BytesLeft) + return true; + + Offset = 0; + BytesLeft -= EltSize; + CurPtr += EltSize; + } + return true; + } + + if (ConstantVector *CV = dyn_cast(C)) { + uint64_t EltSize = TD.getTypeAllocSize(CV->getType()->getElementType()); + uint64_t Index = ByteOffset / EltSize; + uint64_t Offset = ByteOffset - Index * EltSize; + for (; Index != CV->getType()->getNumElements(); ++Index) { + if (!ReadDataFromGlobal(CV->getOperand(Index), Offset, CurPtr, + BytesLeft, TD)) + return false; + if (EltSize >= BytesLeft) + return true; + + Offset = 0; + BytesLeft -= EltSize; + CurPtr += EltSize; + } + return true; + } + + // Otherwise, unknown initializer type. + return false; +} + +static Constant *FoldReinterpretLoadFromConstPtr(Constant *C, + const TargetData &TD) { + const Type *LoadTy = cast(C->getType())->getElementType(); + const IntegerType *IntType = dyn_cast(LoadTy); + + // If this isn't an integer load we can't fold it directly. + if (!IntType) { + // If this is a float/double load, we can try folding it as an int32/64 load + // and then bitcast the result. This can be useful for union cases. Note + // that address spaces don't matter here since we're not going to result in + // an actual new load. + const Type *MapTy; + if (LoadTy->isFloatTy()) + MapTy = Type::getInt32PtrTy(C->getContext()); + else if (LoadTy->isDoubleTy()) + MapTy = Type::getInt64PtrTy(C->getContext()); + else if (isa(LoadTy)) { + MapTy = IntegerType::get(C->getContext(), + TD.getTypeAllocSizeInBits(LoadTy)); + MapTy = PointerType::getUnqual(MapTy); + } else + return 0; + + C = FoldBitCast(C, MapTy, TD); + if (Constant *Res = FoldReinterpretLoadFromConstPtr(C, TD)) + return FoldBitCast(Res, LoadTy, TD); + return 0; + } + + unsigned BytesLoaded = (IntType->getBitWidth() + 7) / 8; + if (BytesLoaded > 32 || BytesLoaded == 0) return 0; + + GlobalValue *GVal; + int64_t Offset; + if (!IsConstantOffsetFromGlobal(C, GVal, Offset, TD)) + return 0; + + GlobalVariable *GV = dyn_cast(GVal); + if (!GV || !GV->isConstant() || !GV->hasDefinitiveInitializer() || + !GV->getInitializer()->getType()->isSized()) + return 0; + + // If we're loading off the beginning of the global, some bytes may be valid, + // but we don't try to handle this. + if (Offset < 0) return 0; + + // If we're not accessing anything in this constant, the result is undefined. + if (uint64_t(Offset) >= TD.getTypeAllocSize(GV->getInitializer()->getType())) + return UndefValue::get(IntType); + + unsigned char RawBytes[32] = {0}; + if (!ReadDataFromGlobal(GV->getInitializer(), Offset, RawBytes, + BytesLoaded, TD)) + return 0; + + APInt ResultVal(IntType->getBitWidth(), 0); + for (unsigned i = 0; i != BytesLoaded; ++i) { + ResultVal <<= 8; + ResultVal |= APInt(IntType->getBitWidth(), RawBytes[BytesLoaded-1-i]); + } + + return ConstantInt::get(IntType->getContext(), ResultVal); +} + +/// ConstantFoldLoadFromConstPtr - Return the value that a load from C would +/// produce if it is constant and determinable. If this is not determinable, +/// return null. +Constant *llvm::ConstantFoldLoadFromConstPtr(Constant *C, + const TargetData *TD) { + // First, try the easy cases: + if (GlobalVariable *GV = dyn_cast(C)) + if (GV->isConstant() && GV->hasDefinitiveInitializer()) + return GV->getInitializer(); + + // If the loaded value isn't a constant expr, we can't handle it. + ConstantExpr *CE = dyn_cast(C); + if (!CE) return 0; + + if (CE->getOpcode() == Instruction::GetElementPtr) { + if (GlobalVariable *GV = dyn_cast(CE->getOperand(0))) + if (GV->isConstant() && GV->hasDefinitiveInitializer()) + if (Constant *V = + ConstantFoldLoadThroughGEPConstantExpr(GV->getInitializer(), CE)) + return V; + } + + // Instead of loading constant c string, use corresponding integer value + // directly if string length is small enough. + std::string Str; + if (TD && GetConstantStringInfo(CE->getOperand(0), Str) && !Str.empty()) { + unsigned StrLen = Str.length(); + const Type *Ty = cast(CE->getType())->getElementType(); + unsigned NumBits = Ty->getPrimitiveSizeInBits(); + // Replace LI with immediate integer store. + if ((NumBits >> 3) == StrLen + 1) { + APInt StrVal(NumBits, 0); + APInt SingleChar(NumBits, 0); + if (TD->isLittleEndian()) { + for (signed i = StrLen-1; i >= 0; i--) { + SingleChar = (uint64_t) Str[i] & UCHAR_MAX; + StrVal = (StrVal << 8) | SingleChar; + } + } else { + for (unsigned i = 0; i < StrLen; i++) { + SingleChar = (uint64_t) Str[i] & UCHAR_MAX; + StrVal = (StrVal << 8) | SingleChar; + } + // Append NULL at the end. + SingleChar = 0; + StrVal = (StrVal << 8) | SingleChar; + } + return ConstantInt::get(CE->getContext(), StrVal); + } + } + + // If this load comes from anywhere in a constant global, and if the global + // is all undef or zero, we know what it loads. + if (GlobalVariable *GV = dyn_cast(CE->getUnderlyingObject())){ + if (GV->isConstant() && GV->hasDefinitiveInitializer()) { + const Type *ResTy = cast(C->getType())->getElementType(); + if (GV->getInitializer()->isNullValue()) + return Constant::getNullValue(ResTy); + if (isa(GV->getInitializer())) + return UndefValue::get(ResTy); + } + } + + // Try hard to fold loads from bitcasted strange and non-type-safe things. We + // currently don't do any of this for big endian systems. It can be + // generalized in the future if someone is interested. + if (TD && TD->isLittleEndian()) + return FoldReinterpretLoadFromConstPtr(CE, *TD); + return 0; +} + +static Constant *ConstantFoldLoadInst(const LoadInst *LI, const TargetData *TD){ + if (LI->isVolatile()) return 0; + + if (Constant *C = dyn_cast(LI->getOperand(0))) + return ConstantFoldLoadFromConstPtr(C, TD); + + return 0; +} + +/// SymbolicallyEvaluateBinop - One of Op0/Op1 is a constant expression. +/// Attempt to symbolically evaluate the result of a binary operator merging +/// these together. If target data info is available, it is provided as TD, +/// otherwise TD is null. +static Constant *SymbolicallyEvaluateBinop(unsigned Opc, Constant *Op0, + Constant *Op1, const TargetData *TD){ + // SROA + + // Fold (and 0xffffffff00000000, (shl x, 32)) -> shl. + // Fold (lshr (or X, Y), 32) -> (lshr [X/Y], 32) if one doesn't contribute + // bits. + + + // If the constant expr is something like &A[123] - &A[4].f, fold this into a + // constant. This happens frequently when iterating over a global array. + if (Opc == Instruction::Sub && TD) { + GlobalValue *GV1, *GV2; + int64_t Offs1, Offs2; + + if (IsConstantOffsetFromGlobal(Op0, GV1, Offs1, *TD)) + if (IsConstantOffsetFromGlobal(Op1, GV2, Offs2, *TD) && + GV1 == GV2) { + // (&GV+C1) - (&GV+C2) -> C1-C2, pointer arithmetic cannot overflow. + return ConstantInt::get(Op0->getType(), Offs1-Offs2); + } + } + + return 0; +} + +/// SymbolicallyEvaluateGEP - If we can symbolically evaluate the specified GEP +/// constant expression, do so. +static Constant *SymbolicallyEvaluateGEP(Constant *const *Ops, unsigned NumOps, + const Type *ResultTy, + const TargetData *TD) { + Constant *Ptr = Ops[0]; + if (!TD || !cast(Ptr->getType())->getElementType()->isSized()) + return 0; + + unsigned BitWidth = + TD->getTypeSizeInBits(TD->getIntPtrType(Ptr->getContext())); + APInt BasePtr(BitWidth, 0); + bool BaseIsInt = true; + if (!Ptr->isNullValue()) { + // If this is a inttoptr from a constant int, we can fold this as the base, + // otherwise we can't. + if (ConstantExpr *CE = dyn_cast(Ptr)) + if (CE->getOpcode() == Instruction::IntToPtr) + if (ConstantInt *Base = dyn_cast(CE->getOperand(0))) { + BasePtr = Base->getValue(); + BasePtr.zextOrTrunc(BitWidth); + } + + if (BasePtr == 0) + BaseIsInt = false; + } + + // If this is a constant expr gep that is effectively computing an + // "offsetof", fold it into 'cast int Size to T*' instead of 'gep 0, 0, 12' + for (unsigned i = 1; i != NumOps; ++i) + if (!isa(Ops[i])) + return 0; + + APInt Offset = APInt(BitWidth, + TD->getIndexedOffset(Ptr->getType(), + (Value**)Ops+1, NumOps-1)); + // If the base value for this address is a literal integer value, fold the + // getelementptr to the resulting integer value casted to the pointer type. + if (BaseIsInt) { + Constant *C = ConstantInt::get(Ptr->getContext(), Offset+BasePtr); + return ConstantExpr::getIntToPtr(C, ResultTy); + } + + // Otherwise form a regular getelementptr. Recompute the indices so that + // we eliminate over-indexing of the notional static type array bounds. + // This makes it easy to determine if the getelementptr is "inbounds". + // Also, this helps GlobalOpt do SROA on GlobalVariables. + const Type *Ty = Ptr->getType(); + SmallVector NewIdxs; + do { + if (const SequentialType *ATy = dyn_cast(Ty)) { + // The only pointer indexing we'll do is on the first index of the GEP. + if (isa(ATy) && !NewIdxs.empty()) + break; + // Determine which element of the array the offset points into. + APInt ElemSize(BitWidth, TD->getTypeAllocSize(ATy->getElementType())); + if (ElemSize == 0) + return 0; + APInt NewIdx = Offset.udiv(ElemSize); + Offset -= NewIdx * ElemSize; + NewIdxs.push_back(ConstantInt::get(TD->getIntPtrType(Ty->getContext()), + NewIdx)); + Ty = ATy->getElementType(); + } else if (const StructType *STy = dyn_cast(Ty)) { + // Determine which field of the struct the offset points into. The + // getZExtValue is at least as safe as the StructLayout API because we + // know the offset is within the struct at this point. + const StructLayout &SL = *TD->getStructLayout(STy); + unsigned ElIdx = SL.getElementContainingOffset(Offset.getZExtValue()); + NewIdxs.push_back(ConstantInt::get(Type::getInt32Ty(Ty->getContext()), + ElIdx)); + Offset -= APInt(BitWidth, SL.getElementOffset(ElIdx)); + Ty = STy->getTypeAtIndex(ElIdx); + } else { + // We've reached some non-indexable type. + break; + } + } while (Ty != cast(ResultTy)->getElementType()); + + // If we haven't used up the entire offset by descending the static + // type, then the offset is pointing into the middle of an indivisible + // member, so we can't simplify it. + if (Offset != 0) + return 0; + + // Create a GEP. + Constant *C = + ConstantExpr::getGetElementPtr(Ptr, &NewIdxs[0], NewIdxs.size()); + assert(cast(C->getType())->getElementType() == Ty && + "Computed GetElementPtr has unexpected type!"); + + // If we ended up indexing a member with a type that doesn't match + // the type of what the original indices indexed, add a cast. + if (Ty != cast(ResultTy)->getElementType()) + C = FoldBitCast(C, ResultTy, *TD); + + return C; +} + + + +//===----------------------------------------------------------------------===// +// Constant Folding public APIs +//===----------------------------------------------------------------------===// + + +/// ConstantFoldInstruction - Attempt to constant fold the specified +/// instruction. If successful, the constant result is returned, if not, null +/// is returned. Note that this function can only fail when attempting to fold +/// instructions like loads and stores, which have no constant expression form. +/// +Constant *llvm::ConstantFoldInstruction(Instruction *I, const TargetData *TD) { + if (PHINode *PN = dyn_cast(I)) { + if (PN->getNumIncomingValues() == 0) + return UndefValue::get(PN->getType()); + + Constant *Result = dyn_cast(PN->getIncomingValue(0)); + if (Result == 0) return 0; + + // Handle PHI nodes specially here... + for (unsigned i = 1, e = PN->getNumIncomingValues(); i != e; ++i) + if (PN->getIncomingValue(i) != Result && PN->getIncomingValue(i) != PN) + return 0; // Not all the same incoming constants... + + // If we reach here, all incoming values are the same constant. + return Result; + } + + // Scan the operand list, checking to see if they are all constants, if so, + // hand off to ConstantFoldInstOperands. + SmallVector Ops; + for (User::op_iterator i = I->op_begin(), e = I->op_end(); i != e; ++i) + if (Constant *Op = dyn_cast(*i)) + Ops.push_back(Op); + else + return 0; // All operands not constant! + + if (const CmpInst *CI = dyn_cast(I)) + return ConstantFoldCompareInstOperands(CI->getPredicate(), Ops[0], Ops[1], + TD); + + if (const LoadInst *LI = dyn_cast(I)) + return ConstantFoldLoadInst(LI, TD); + + return ConstantFoldInstOperands(I->getOpcode(), I->getType(), + Ops.data(), Ops.size(), TD); +} + +/// ConstantFoldConstantExpression - Attempt to fold the constant expression +/// using the specified TargetData. If successful, the constant result is +/// result is returned, if not, null is returned. +Constant *llvm::ConstantFoldConstantExpression(ConstantExpr *CE, + const TargetData *TD) { + SmallVector Ops; + for (User::op_iterator i = CE->op_begin(), e = CE->op_end(); i != e; ++i) { + Constant *NewC = cast(*i); + // Recursively fold the ConstantExpr's operands. + if (ConstantExpr *NewCE = dyn_cast(NewC)) + NewC = ConstantFoldConstantExpression(NewCE, TD); + Ops.push_back(NewC); + } + + if (CE->isCompare()) + return ConstantFoldCompareInstOperands(CE->getPredicate(), Ops[0], Ops[1], + TD); + return ConstantFoldInstOperands(CE->getOpcode(), CE->getType(), + Ops.data(), Ops.size(), TD); +} + +/// ConstantFoldInstOperands - Attempt to constant fold an instruction with the +/// specified opcode and operands. If successful, the constant result is +/// returned, if not, null is returned. Note that this function can fail when +/// attempting to fold instructions like loads and stores, which have no +/// constant expression form. +/// +/// TODO: This function neither utilizes nor preserves nsw/nuw/inbounds/etc +/// information, due to only being passed an opcode and operands. Constant +/// folding using this function strips this information. +/// +Constant *llvm::ConstantFoldInstOperands(unsigned Opcode, const Type *DestTy, + Constant* const* Ops, unsigned NumOps, + const TargetData *TD) { + // Handle easy binops first. + if (Instruction::isBinaryOp(Opcode)) { + if (isa(Ops[0]) || isa(Ops[1])) + if (Constant *C = SymbolicallyEvaluateBinop(Opcode, Ops[0], Ops[1], TD)) + return C; + + return ConstantExpr::get(Opcode, Ops[0], Ops[1]); + } + + switch (Opcode) { + default: return 0; + case Instruction::Call: + if (Function *F = dyn_cast(Ops[0])) + if (canConstantFoldCallTo(F)) + return ConstantFoldCall(F, Ops+1, NumOps-1); + return 0; + case Instruction::ICmp: + case Instruction::FCmp: + llvm_unreachable("This function is invalid for compares: no predicate specified"); + case Instruction::PtrToInt: + // If the input is a inttoptr, eliminate the pair. This requires knowing + // the width of a pointer, so it can't be done in ConstantExpr::getCast. + if (ConstantExpr *CE = dyn_cast(Ops[0])) { + if (TD && CE->getOpcode() == Instruction::IntToPtr) { + Constant *Input = CE->getOperand(0); + unsigned InWidth = Input->getType()->getScalarSizeInBits(); + if (TD->getPointerSizeInBits() < InWidth) { + Constant *Mask = + ConstantInt::get(CE->getContext(), APInt::getLowBitsSet(InWidth, + TD->getPointerSizeInBits())); + Input = ConstantExpr::getAnd(Input, Mask); + } + // Do a zext or trunc to get to the dest size. + return ConstantExpr::getIntegerCast(Input, DestTy, false); + } + } + return ConstantExpr::getCast(Opcode, Ops[0], DestTy); + case Instruction::IntToPtr: + // If the input is a ptrtoint, turn the pair into a ptr to ptr bitcast if + // the int size is >= the ptr size. This requires knowing the width of a + // pointer, so it can't be done in ConstantExpr::getCast. + if (ConstantExpr *CE = dyn_cast(Ops[0])) { + if (TD && + TD->getPointerSizeInBits() <= + CE->getType()->getScalarSizeInBits()) { + if (CE->getOpcode() == Instruction::PtrToInt) + return FoldBitCast(CE->getOperand(0), DestTy, *TD); + + // If there's a constant offset added to the integer value before + // it is casted back to a pointer, see if the expression can be + // converted into a GEP. + if (CE->getOpcode() == Instruction::Add) + if (ConstantInt *L = dyn_cast(CE->getOperand(0))) + if (ConstantExpr *R = dyn_cast(CE->getOperand(1))) + if (R->getOpcode() == Instruction::PtrToInt) + if (GlobalVariable *GV = + dyn_cast(R->getOperand(0))) { + const PointerType *GVTy = cast(GV->getType()); + if (const ArrayType *AT = + dyn_cast(GVTy->getElementType())) { + const Type *ElTy = AT->getElementType(); + uint64_t AllocSize = TD->getTypeAllocSize(ElTy); + APInt PSA(L->getValue().getBitWidth(), AllocSize); + if (ElTy == cast(DestTy)->getElementType() && + L->getValue().urem(PSA) == 0) { + APInt ElemIdx = L->getValue().udiv(PSA); + if (ElemIdx.ult(APInt(ElemIdx.getBitWidth(), + AT->getNumElements()))) { + Constant *Index[] = { + Constant::getNullValue(CE->getType()), + ConstantInt::get(ElTy->getContext(), ElemIdx) + }; + return + ConstantExpr::getGetElementPtr(GV, &Index[0], 2); + } + } + } + } + } + } + return ConstantExpr::getCast(Opcode, Ops[0], DestTy); + case Instruction::Trunc: + case Instruction::ZExt: + case Instruction::SExt: + case Instruction::FPTrunc: + case Instruction::FPExt: + case Instruction::UIToFP: + case Instruction::SIToFP: + case Instruction::FPToUI: + case Instruction::FPToSI: + return ConstantExpr::getCast(Opcode, Ops[0], DestTy); + case Instruction::BitCast: + if (TD) + return FoldBitCast(Ops[0], DestTy, *TD); + return ConstantExpr::getBitCast(Ops[0], DestTy); + case Instruction::Select: + return ConstantExpr::getSelect(Ops[0], Ops[1], Ops[2]); + case Instruction::ExtractElement: + return ConstantExpr::getExtractElement(Ops[0], Ops[1]); + case Instruction::InsertElement: + return ConstantExpr::getInsertElement(Ops[0], Ops[1], Ops[2]); + case Instruction::ShuffleVector: + return ConstantExpr::getShuffleVector(Ops[0], Ops[1], Ops[2]); + case Instruction::GetElementPtr: + if (Constant *C = SymbolicallyEvaluateGEP(Ops, NumOps, DestTy, TD)) + return C; + + return ConstantExpr::getGetElementPtr(Ops[0], Ops+1, NumOps-1); + } +} + +/// ConstantFoldCompareInstOperands - Attempt to constant fold a compare +/// instruction (icmp/fcmp) with the specified operands. If it fails, it +/// returns a constant expression of the specified operands. +/// +Constant *llvm::ConstantFoldCompareInstOperands(unsigned Predicate, + Constant *Ops0, Constant *Ops1, + const TargetData *TD) { + // fold: icmp (inttoptr x), null -> icmp x, 0 + // fold: icmp (ptrtoint x), 0 -> icmp x, null + // fold: icmp (inttoptr x), (inttoptr y) -> icmp trunc/zext x, trunc/zext y + // fold: icmp (ptrtoint x), (ptrtoint y) -> icmp x, y + // + // ConstantExpr::getCompare cannot do this, because it doesn't have TD + // around to know if bit truncation is happening. + if (ConstantExpr *CE0 = dyn_cast(Ops0)) { + if (TD && Ops1->isNullValue()) { + const Type *IntPtrTy = TD->getIntPtrType(CE0->getContext()); + if (CE0->getOpcode() == Instruction::IntToPtr) { + // Convert the integer value to the right size to ensure we get the + // proper extension or truncation. + Constant *C = ConstantExpr::getIntegerCast(CE0->getOperand(0), + IntPtrTy, false); + Constant *Null = Constant::getNullValue(C->getType()); + return ConstantFoldCompareInstOperands(Predicate, C, Null, TD); + } + + // Only do this transformation if the int is intptrty in size, otherwise + // there is a truncation or extension that we aren't modeling. + if (CE0->getOpcode() == Instruction::PtrToInt && + CE0->getType() == IntPtrTy) { + Constant *C = CE0->getOperand(0); + Constant *Null = Constant::getNullValue(C->getType()); + return ConstantFoldCompareInstOperands(Predicate, C, Null, TD); + } + } + + if (ConstantExpr *CE1 = dyn_cast(Ops1)) { + if (TD && CE0->getOpcode() == CE1->getOpcode()) { + const Type *IntPtrTy = TD->getIntPtrType(CE0->getContext()); + + if (CE0->getOpcode() == Instruction::IntToPtr) { + // Convert the integer value to the right size to ensure we get the + // proper extension or truncation. + Constant *C0 = ConstantExpr::getIntegerCast(CE0->getOperand(0), + IntPtrTy, false); + Constant *C1 = ConstantExpr::getIntegerCast(CE1->getOperand(0), + IntPtrTy, false); + return ConstantFoldCompareInstOperands(Predicate, C0, C1, TD); + } + + // Only do this transformation if the int is intptrty in size, otherwise + // there is a truncation or extension that we aren't modeling. + if ((CE0->getOpcode() == Instruction::PtrToInt && + CE0->getType() == IntPtrTy && + CE0->getOperand(0)->getType() == CE1->getOperand(0)->getType())) + return ConstantFoldCompareInstOperands(Predicate, CE0->getOperand(0), + CE1->getOperand(0), TD); + } + } + } + + return ConstantExpr::getCompare(Predicate, Ops0, Ops1); +} + + +/// ConstantFoldLoadThroughGEPConstantExpr - Given a constant and a +/// getelementptr constantexpr, return the constant value being addressed by the +/// constant expression, or null if something is funny and we can't decide. +Constant *llvm::ConstantFoldLoadThroughGEPConstantExpr(Constant *C, + ConstantExpr *CE) { + if (CE->getOperand(1) != Constant::getNullValue(CE->getOperand(1)->getType())) + return 0; // Do not allow stepping over the value! + + // Loop over all of the operands, tracking down which value we are + // addressing... + gep_type_iterator I = gep_type_begin(CE), E = gep_type_end(CE); + for (++I; I != E; ++I) + if (const StructType *STy = dyn_cast(*I)) { + ConstantInt *CU = cast(I.getOperand()); + assert(CU->getZExtValue() < STy->getNumElements() && + "Struct index out of range!"); + unsigned El = (unsigned)CU->getZExtValue(); + if (ConstantStruct *CS = dyn_cast(C)) { + C = CS->getOperand(El); + } else if (isa(C)) { + C = Constant::getNullValue(STy->getElementType(El)); + } else if (isa(C)) { + C = UndefValue::get(STy->getElementType(El)); + } else { + return 0; + } + } else if (ConstantInt *CI = dyn_cast(I.getOperand())) { + if (const ArrayType *ATy = dyn_cast(*I)) { + if (CI->getZExtValue() >= ATy->getNumElements()) + return 0; + if (ConstantArray *CA = dyn_cast(C)) + C = CA->getOperand(CI->getZExtValue()); + else if (isa(C)) + C = Constant::getNullValue(ATy->getElementType()); + else if (isa(C)) + C = UndefValue::get(ATy->getElementType()); + else + return 0; + } else if (const VectorType *VTy = dyn_cast(*I)) { + if (CI->getZExtValue() >= VTy->getNumElements()) + return 0; + if (ConstantVector *CP = dyn_cast(C)) + C = CP->getOperand(CI->getZExtValue()); + else if (isa(C)) + C = Constant::getNullValue(VTy->getElementType()); + else if (isa(C)) + C = UndefValue::get(VTy->getElementType()); + else + return 0; + } else { + return 0; + } + } else { + return 0; + } + return C; +} + + +//===----------------------------------------------------------------------===// +// Constant Folding for Calls +// + +/// canConstantFoldCallTo - Return true if its even possible to fold a call to +/// the specified function. +bool +llvm::canConstantFoldCallTo(const Function *F) { + switch (F->getIntrinsicID()) { + case Intrinsic::sqrt: + case Intrinsic::powi: + case Intrinsic::bswap: + case Intrinsic::ctpop: + case Intrinsic::ctlz: + case Intrinsic::cttz: + case Intrinsic::uadd_with_overflow: + case Intrinsic::usub_with_overflow: + case Intrinsic::sadd_with_overflow: + case Intrinsic::ssub_with_overflow: + return true; + default: + return false; + case 0: break; + } + + if (!F->hasName()) return false; + StringRef Name = F->getName(); + + // In these cases, the check of the length is required. We don't want to + // return true for a name like "cos\0blah" which strcmp would return equal to + // "cos", but has length 8. + switch (Name[0]) { + default: return false; + case 'a': + return Name == "acos" || Name == "asin" || + Name == "atan" || Name == "atan2"; + case 'c': + return Name == "cos" || Name == "ceil" || Name == "cosf" || Name == "cosh"; + case 'e': + return Name == "exp"; + case 'f': + return Name == "fabs" || Name == "fmod" || Name == "floor"; + case 'l': + return Name == "log" || Name == "log10"; + case 'p': + return Name == "pow"; + case 's': + return Name == "sin" || Name == "sinh" || Name == "sqrt" || + Name == "sinf" || Name == "sqrtf"; + case 't': + return Name == "tan" || Name == "tanh"; + } +} + +static Constant *ConstantFoldFP(double (*NativeFP)(double), double V, + const Type *Ty) { + errno = 0; + V = NativeFP(V); + if (errno != 0) { + errno = 0; + return 0; + } + + if (Ty->isFloatTy()) + return ConstantFP::get(Ty->getContext(), APFloat((float)V)); + if (Ty->isDoubleTy()) + return ConstantFP::get(Ty->getContext(), APFloat(V)); + llvm_unreachable("Can only constant fold float/double"); + return 0; // dummy return to suppress warning +} + +static Constant *ConstantFoldBinaryFP(double (*NativeFP)(double, double), + double V, double W, const Type *Ty) { + errno = 0; + V = NativeFP(V, W); + if (errno != 0) { + errno = 0; + return 0; + } + + if (Ty->isFloatTy()) + return ConstantFP::get(Ty->getContext(), APFloat((float)V)); + if (Ty->isDoubleTy()) + return ConstantFP::get(Ty->getContext(), APFloat(V)); + llvm_unreachable("Can only constant fold float/double"); + return 0; // dummy return to suppress warning +} + +/// ConstantFoldCall - Attempt to constant fold a call to the specified function +/// with the specified arguments, returning null if unsuccessful. +Constant * +llvm::ConstantFoldCall(Function *F, + Constant *const *Operands, unsigned NumOperands) { + if (!F->hasName()) return 0; + StringRef Name = F->getName(); + + const Type *Ty = F->getReturnType(); + if (NumOperands == 1) { + if (ConstantFP *Op = dyn_cast(Operands[0])) { + if (!Ty->isFloatTy() && !Ty->isDoubleTy()) + return 0; + /// Currently APFloat versions of these functions do not exist, so we use + /// the host native double versions. Float versions are not called + /// directly but for all these it is true (float)(f((double)arg)) == + /// f(arg). Long double not supported yet. + double V = Ty->isFloatTy() ? (double)Op->getValueAPF().convertToFloat() : + Op->getValueAPF().convertToDouble(); + switch (Name[0]) { + case 'a': + if (Name == "acos") + return ConstantFoldFP(acos, V, Ty); + else if (Name == "asin") + return ConstantFoldFP(asin, V, Ty); + else if (Name == "atan") + return ConstantFoldFP(atan, V, Ty); + break; + case 'c': + if (Name == "ceil") + return ConstantFoldFP(ceil, V, Ty); + else if (Name == "cos") + return ConstantFoldFP(cos, V, Ty); + else if (Name == "cosh") + return ConstantFoldFP(cosh, V, Ty); + else if (Name == "cosf") + return ConstantFoldFP(cos, V, Ty); + break; + case 'e': + if (Name == "exp") + return ConstantFoldFP(exp, V, Ty); + break; + case 'f': + if (Name == "fabs") + return ConstantFoldFP(fabs, V, Ty); + else if (Name == "floor") + return ConstantFoldFP(floor, V, Ty); + break; + case 'l': + if (Name == "log" && V > 0) + return ConstantFoldFP(log, V, Ty); + else if (Name == "log10" && V > 0) + return ConstantFoldFP(log10, V, Ty); + else if (Name == "llvm.sqrt.f32" || + Name == "llvm.sqrt.f64") { + if (V >= -0.0) + return ConstantFoldFP(sqrt, V, Ty); + else // Undefined + return Constant::getNullValue(Ty); + } + break; + case 's': + if (Name == "sin") + return ConstantFoldFP(sin, V, Ty); + else if (Name == "sinh") + return ConstantFoldFP(sinh, V, Ty); + else if (Name == "sqrt" && V >= 0) + return ConstantFoldFP(sqrt, V, Ty); + else if (Name == "sqrtf" && V >= 0) + return ConstantFoldFP(sqrt, V, Ty); + else if (Name == "sinf") + return ConstantFoldFP(sin, V, Ty); + break; + case 't': + if (Name == "tan") + return ConstantFoldFP(tan, V, Ty); + else if (Name == "tanh") + return ConstantFoldFP(tanh, V, Ty); + break; + default: + break; + } + return 0; + } + + + if (ConstantInt *Op = dyn_cast(Operands[0])) { + if (Name.startswith("llvm.bswap")) + return ConstantInt::get(F->getContext(), Op->getValue().byteSwap()); + else if (Name.startswith("llvm.ctpop")) + return ConstantInt::get(Ty, Op->getValue().countPopulation()); + else if (Name.startswith("llvm.cttz")) + return ConstantInt::get(Ty, Op->getValue().countTrailingZeros()); + else if (Name.startswith("llvm.ctlz")) + return ConstantInt::get(Ty, Op->getValue().countLeadingZeros()); + return 0; + } + + return 0; + } + + if (NumOperands == 2) { + if (ConstantFP *Op1 = dyn_cast(Operands[0])) { + if (!Ty->isFloatTy() && !Ty->isDoubleTy()) + return 0; + double Op1V = Ty->isFloatTy() ? + (double)Op1->getValueAPF().convertToFloat() : + Op1->getValueAPF().convertToDouble(); + if (ConstantFP *Op2 = dyn_cast(Operands[1])) { + if (Op2->getType() != Op1->getType()) + return 0; + + double Op2V = Ty->isFloatTy() ? + (double)Op2->getValueAPF().convertToFloat(): + Op2->getValueAPF().convertToDouble(); + + if (Name == "pow") + return ConstantFoldBinaryFP(pow, Op1V, Op2V, Ty); + if (Name == "fmod") + return ConstantFoldBinaryFP(fmod, Op1V, Op2V, Ty); + if (Name == "atan2") + return ConstantFoldBinaryFP(atan2, Op1V, Op2V, Ty); + } else if (ConstantInt *Op2C = dyn_cast(Operands[1])) { + if (Name == "llvm.powi.f32") + return ConstantFP::get(F->getContext(), + APFloat((float)std::pow((float)Op1V, + (int)Op2C->getZExtValue()))); + if (Name == "llvm.powi.f64") + return ConstantFP::get(F->getContext(), + APFloat((double)std::pow((double)Op1V, + (int)Op2C->getZExtValue()))); + } + return 0; + } + + + if (ConstantInt *Op1 = dyn_cast(Operands[0])) { + if (ConstantInt *Op2 = dyn_cast(Operands[1])) { + switch (F->getIntrinsicID()) { + default: break; + case Intrinsic::uadd_with_overflow: { + Constant *Res = ConstantExpr::getAdd(Op1, Op2); // result. + Constant *Ops[] = { + Res, ConstantExpr::getICmp(CmpInst::ICMP_ULT, Res, Op1) // overflow. + }; + return ConstantStruct::get(F->getContext(), Ops, 2, false); + } + case Intrinsic::usub_with_overflow: { + Constant *Res = ConstantExpr::getSub(Op1, Op2); // result. + Constant *Ops[] = { + Res, ConstantExpr::getICmp(CmpInst::ICMP_UGT, Res, Op1) // overflow. + }; + return ConstantStruct::get(F->getContext(), Ops, 2, false); + } + case Intrinsic::sadd_with_overflow: { + Constant *Res = ConstantExpr::getAdd(Op1, Op2); // result. + Constant *Overflow = ConstantExpr::getSelect( + ConstantExpr::getICmp(CmpInst::ICMP_SGT, + ConstantInt::get(Op1->getType(), 0), Op1), + ConstantExpr::getICmp(CmpInst::ICMP_SGT, Res, Op2), + ConstantExpr::getICmp(CmpInst::ICMP_SLT, Res, Op2)); // overflow. + + Constant *Ops[] = { Res, Overflow }; + return ConstantStruct::get(F->getContext(), Ops, 2, false); + } + case Intrinsic::ssub_with_overflow: { + Constant *Res = ConstantExpr::getSub(Op1, Op2); // result. + Constant *Overflow = ConstantExpr::getSelect( + ConstantExpr::getICmp(CmpInst::ICMP_SGT, + ConstantInt::get(Op2->getType(), 0), Op2), + ConstantExpr::getICmp(CmpInst::ICMP_SLT, Res, Op1), + ConstantExpr::getICmp(CmpInst::ICMP_SGT, Res, Op1)); // overflow. + + Constant *Ops[] = { Res, Overflow }; + return ConstantStruct::get(F->getContext(), Ops, 2, false); + } + } + } + + return 0; + } + return 0; + } + return 0; +} + diff --git a/libclamav/c++/llvm/lib/Analysis/DbgInfoPrinter.cpp b/libclamav/c++/llvm/lib/Analysis/DbgInfoPrinter.cpp new file mode 100644 index 000000000..ab92e3f9b --- /dev/null +++ b/libclamav/c++/llvm/lib/Analysis/DbgInfoPrinter.cpp @@ -0,0 +1,166 @@ +//===- DbgInfoPrinter.cpp - Print debug info in a human readable form ------==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements a pass that prints instructions, and associated debug +// info: +// +// - source/line/col information +// - original variable name +// - original type name +// +//===----------------------------------------------------------------------===// + +#include "llvm/Pass.h" +#include "llvm/Function.h" +#include "llvm/IntrinsicInst.h" +#include "llvm/Assembly/Writer.h" +#include "llvm/Analysis/DebugInfo.h" +#include "llvm/Analysis/Passes.h" +#include "llvm/Analysis/ValueTracking.h" +#include "llvm/Support/CFG.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/raw_ostream.h" + +using namespace llvm; + +static cl::opt +PrintDirectory("print-fullpath", + cl::desc("Print fullpath when printing debug info"), + cl::Hidden); + +namespace { + class PrintDbgInfo : public FunctionPass { + raw_ostream &Out; + void printStopPoint(const DbgStopPointInst *DSI); + void printFuncStart(const DbgFuncStartInst *FS); + void printVariableDeclaration(const Value *V); + public: + static char ID; // Pass identification + PrintDbgInfo() : FunctionPass(&ID), Out(outs()) {} + + virtual bool runOnFunction(Function &F); + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + } + }; + char PrintDbgInfo::ID = 0; + static RegisterPass X("print-dbginfo", + "Print debug info in human readable form"); +} + +FunctionPass *llvm::createDbgInfoPrinterPass() { return new PrintDbgInfo(); } + +void PrintDbgInfo::printVariableDeclaration(const Value *V) { + std::string DisplayName, File, Directory, Type; + unsigned LineNo; + + if (!getLocationInfo(V, DisplayName, Type, LineNo, File, Directory)) + return; + + Out << "; "; + WriteAsOperand(Out, V, false, 0); + Out << " is variable " << DisplayName + << " of type " << Type << " declared at "; + + if (PrintDirectory) + Out << Directory << "/"; + + Out << File << ":" << LineNo << "\n"; +} + +void PrintDbgInfo::printStopPoint(const DbgStopPointInst *DSI) { + if (PrintDirectory) { + std::string dir; + GetConstantStringInfo(DSI->getDirectory(), dir); + Out << dir << "/"; + } + + std::string file; + GetConstantStringInfo(DSI->getFileName(), file); + Out << file << ":" << DSI->getLine(); + + if (unsigned Col = DSI->getColumn()) + Out << ":" << Col; +} + +void PrintDbgInfo::printFuncStart(const DbgFuncStartInst *FS) { + DISubprogram Subprogram(FS->getSubprogram()); + Out << "; fully qualified function name: " << Subprogram.getDisplayName() + << " return type: " << Subprogram.getReturnTypeName() + << " at line " << Subprogram.getLineNumber() + << "\n\n"; +} + +bool PrintDbgInfo::runOnFunction(Function &F) { + if (F.isDeclaration()) + return false; + + Out << "function " << F.getName() << "\n\n"; + + for (Function::iterator I = F.begin(), E = F.end(); I != E; ++I) { + BasicBlock *BB = I; + + if (I != F.begin() && (pred_begin(BB) == pred_end(BB))) + // Skip dead blocks. + continue; + + const DbgStopPointInst *DSI = findBBStopPoint(BB); + Out << BB->getName(); + Out << ":"; + + if (DSI) { + Out << "; ("; + printStopPoint(DSI); + Out << ")"; + } + + Out << "\n"; + + // A dbgstoppoint's information is valid until we encounter a new one. + const DbgStopPointInst *LastDSP = DSI; + bool Printed = DSI != 0; + for (BasicBlock::const_iterator i = BB->begin(), e = BB->end(); + i != e; ++i) { + if (isa(i)) { + if ((DSI = dyn_cast(i))) { + if (DSI->getContext() == LastDSP->getContext() && + DSI->getLineValue() == LastDSP->getLineValue() && + DSI->getColumnValue() == LastDSP->getColumnValue()) + // Don't print same location twice. + continue; + + LastDSP = cast(i); + + // Don't print consecutive stoppoints, use a flag to know which one we + // printed. + Printed = false; + } else if (const DbgFuncStartInst *FS = dyn_cast(i)) { + printFuncStart(FS); + } + } else { + if (!Printed && LastDSP) { + Out << "; "; + printStopPoint(LastDSP); + Out << "\n"; + Printed = true; + } + + Out << *i << '\n'; + printVariableDeclaration(i); + + if (const User *U = dyn_cast(i)) { + for(unsigned i=0;igetNumOperands();i++) + printVariableDeclaration(U->getOperand(i)); + } + } + } + } + + return false; +} diff --git a/libclamav/c++/llvm/lib/Analysis/DebugInfo.cpp b/libclamav/c++/llvm/lib/Analysis/DebugInfo.cpp new file mode 100644 index 000000000..41d803c69 --- /dev/null +++ b/libclamav/c++/llvm/lib/Analysis/DebugInfo.cpp @@ -0,0 +1,1450 @@ +//===--- DebugInfo.cpp - Debug Information Helper Classes -----------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the helper classes used to build and interpret debug +// information in LLVM IR form. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Analysis/DebugInfo.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Intrinsics.h" +#include "llvm/IntrinsicInst.h" +#include "llvm/Instructions.h" +#include "llvm/LLVMContext.h" +#include "llvm/Module.h" +#include "llvm/Analysis/ValueTracking.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/Support/Dwarf.h" +#include "llvm/Support/DebugLoc.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; +using namespace llvm::dwarf; + +//===----------------------------------------------------------------------===// +// DIDescriptor +//===----------------------------------------------------------------------===// + +/// ValidDebugInfo - Return true if V represents valid debug info value. +/// FIXME : Add DIDescriptor.isValid() +bool DIDescriptor::ValidDebugInfo(MDNode *N, CodeGenOpt::Level OptLevel) { + if (!N) + return false; + + DIDescriptor DI(N); + + // Check current version. Allow Version6 for now. + unsigned Version = DI.getVersion(); + if (Version != LLVMDebugVersion && Version != LLVMDebugVersion6) + return false; + + unsigned Tag = DI.getTag(); + switch (Tag) { + case DW_TAG_variable: + assert(DIVariable(N).Verify() && "Invalid DebugInfo value"); + break; + case DW_TAG_compile_unit: + assert(DICompileUnit(N).Verify() && "Invalid DebugInfo value"); + break; + case DW_TAG_subprogram: + assert(DISubprogram(N).Verify() && "Invalid DebugInfo value"); + break; + case DW_TAG_lexical_block: + // FIXME: This interfers with the quality of generated code during + // optimization. + if (OptLevel != CodeGenOpt::None) + return false; + // FALLTHROUGH + default: + break; + } + + return true; +} + +DIDescriptor::DIDescriptor(MDNode *N, unsigned RequiredTag) { + DbgNode = N; + + // If this is non-null, check to see if the Tag matches. If not, set to null. + if (N && getTag() != RequiredTag) { + DbgNode = 0; + } +} + +StringRef +DIDescriptor::getStringField(unsigned Elt) const { + if (DbgNode == 0) + return StringRef(); + + if (Elt < DbgNode->getNumElements()) + if (MDString *MDS = dyn_cast_or_null(DbgNode->getElement(Elt))) + return MDS->getString(); + + return StringRef(); +} + +uint64_t DIDescriptor::getUInt64Field(unsigned Elt) const { + if (DbgNode == 0) + return 0; + + if (Elt < DbgNode->getNumElements()) + if (ConstantInt *CI = dyn_cast(DbgNode->getElement(Elt))) + return CI->getZExtValue(); + + return 0; +} + +DIDescriptor DIDescriptor::getDescriptorField(unsigned Elt) const { + if (DbgNode == 0) + return DIDescriptor(); + + if (Elt < DbgNode->getNumElements() && DbgNode->getElement(Elt)) + return DIDescriptor(dyn_cast(DbgNode->getElement(Elt))); + + return DIDescriptor(); +} + +GlobalVariable *DIDescriptor::getGlobalVariableField(unsigned Elt) const { + if (DbgNode == 0) + return 0; + + if (Elt < DbgNode->getNumElements()) + return dyn_cast_or_null(DbgNode->getElement(Elt)); + return 0; +} + +//===----------------------------------------------------------------------===// +// Predicates +//===----------------------------------------------------------------------===// + +/// isBasicType - Return true if the specified tag is legal for +/// DIBasicType. +bool DIDescriptor::isBasicType() const { + assert (!isNull() && "Invalid descriptor!"); + unsigned Tag = getTag(); + + return Tag == dwarf::DW_TAG_base_type; +} + +/// isDerivedType - Return true if the specified tag is legal for DIDerivedType. +bool DIDescriptor::isDerivedType() const { + assert (!isNull() && "Invalid descriptor!"); + unsigned Tag = getTag(); + + switch (Tag) { + case dwarf::DW_TAG_typedef: + case dwarf::DW_TAG_pointer_type: + case dwarf::DW_TAG_reference_type: + case dwarf::DW_TAG_const_type: + case dwarf::DW_TAG_volatile_type: + case dwarf::DW_TAG_restrict_type: + case dwarf::DW_TAG_member: + case dwarf::DW_TAG_inheritance: + return true; + default: + // CompositeTypes are currently modelled as DerivedTypes. + return isCompositeType(); + } +} + +/// isCompositeType - Return true if the specified tag is legal for +/// DICompositeType. +bool DIDescriptor::isCompositeType() const { + assert (!isNull() && "Invalid descriptor!"); + unsigned Tag = getTag(); + + switch (Tag) { + case dwarf::DW_TAG_array_type: + case dwarf::DW_TAG_structure_type: + case dwarf::DW_TAG_union_type: + case dwarf::DW_TAG_enumeration_type: + case dwarf::DW_TAG_vector_type: + case dwarf::DW_TAG_subroutine_type: + case dwarf::DW_TAG_class_type: + return true; + default: + return false; + } +} + +/// isVariable - Return true if the specified tag is legal for DIVariable. +bool DIDescriptor::isVariable() const { + assert (!isNull() && "Invalid descriptor!"); + unsigned Tag = getTag(); + + switch (Tag) { + case dwarf::DW_TAG_auto_variable: + case dwarf::DW_TAG_arg_variable: + case dwarf::DW_TAG_return_variable: + return true; + default: + return false; + } +} + +/// isType - Return true if the specified tag is legal for DIType. +bool DIDescriptor::isType() const { + return isBasicType() || isCompositeType() || isDerivedType(); +} + +/// isSubprogram - Return true if the specified tag is legal for +/// DISubprogram. +bool DIDescriptor::isSubprogram() const { + assert (!isNull() && "Invalid descriptor!"); + unsigned Tag = getTag(); + + return Tag == dwarf::DW_TAG_subprogram; +} + +/// isGlobalVariable - Return true if the specified tag is legal for +/// DIGlobalVariable. +bool DIDescriptor::isGlobalVariable() const { + assert (!isNull() && "Invalid descriptor!"); + unsigned Tag = getTag(); + + return Tag == dwarf::DW_TAG_variable; +} + +/// isGlobal - Return true if the specified tag is legal for DIGlobal. +bool DIDescriptor::isGlobal() const { + return isGlobalVariable(); +} + +/// isScope - Return true if the specified tag is one of the scope +/// related tag. +bool DIDescriptor::isScope() const { + assert (!isNull() && "Invalid descriptor!"); + unsigned Tag = getTag(); + + switch (Tag) { + case dwarf::DW_TAG_compile_unit: + case dwarf::DW_TAG_lexical_block: + case dwarf::DW_TAG_subprogram: + return true; + default: + break; + } + return false; +} + +/// isCompileUnit - Return true if the specified tag is DW_TAG_compile_unit. +bool DIDescriptor::isCompileUnit() const { + assert (!isNull() && "Invalid descriptor!"); + unsigned Tag = getTag(); + + return Tag == dwarf::DW_TAG_compile_unit; +} + +/// isLexicalBlock - Return true if the specified tag is DW_TAG_lexical_block. +bool DIDescriptor::isLexicalBlock() const { + assert (!isNull() && "Invalid descriptor!"); + unsigned Tag = getTag(); + + return Tag == dwarf::DW_TAG_lexical_block; +} + +/// isSubrange - Return true if the specified tag is DW_TAG_subrange_type. +bool DIDescriptor::isSubrange() const { + assert (!isNull() && "Invalid descriptor!"); + unsigned Tag = getTag(); + + return Tag == dwarf::DW_TAG_subrange_type; +} + +/// isEnumerator - Return true if the specified tag is DW_TAG_enumerator. +bool DIDescriptor::isEnumerator() const { + assert (!isNull() && "Invalid descriptor!"); + unsigned Tag = getTag(); + + return Tag == dwarf::DW_TAG_enumerator; +} + +//===----------------------------------------------------------------------===// +// Simple Descriptor Constructors and other Methods +//===----------------------------------------------------------------------===// + +DIType::DIType(MDNode *N) : DIDescriptor(N) { + if (!N) return; + if (!isBasicType() && !isDerivedType() && !isCompositeType()) { + DbgNode = 0; + } +} + +unsigned DIArray::getNumElements() const { + assert (DbgNode && "Invalid DIArray"); + return DbgNode->getNumElements(); +} + +/// replaceAllUsesWith - Replace all uses of debug info referenced by +/// this descriptor. After this completes, the current debug info value +/// is erased. +void DIDerivedType::replaceAllUsesWith(DIDescriptor &D) { + if (isNull()) + return; + + assert (!D.isNull() && "Can not replace with null"); + + // Since we use a TrackingVH for the node, its easy for clients to manufacture + // legitimate situations where they want to replaceAllUsesWith() on something + // which, due to uniquing, has merged with the source. We shield clients from + // this detail by allowing a value to be replaced with replaceAllUsesWith() + // itself. + if (getNode() != D.getNode()) { + MDNode *Node = DbgNode; + Node->replaceAllUsesWith(D.getNode()); + delete Node; + } +} + +/// Verify - Verify that a compile unit is well formed. +bool DICompileUnit::Verify() const { + if (isNull()) + return false; + StringRef N = getFilename(); + if (N.empty()) + return false; + // It is possible that directory and produce string is empty. + return true; +} + +/// Verify - Verify that a type descriptor is well formed. +bool DIType::Verify() const { + if (isNull()) + return false; + if (getContext().isNull()) + return false; + + DICompileUnit CU = getCompileUnit(); + if (!CU.isNull() && !CU.Verify()) + return false; + return true; +} + +/// Verify - Verify that a composite type descriptor is well formed. +bool DICompositeType::Verify() const { + if (isNull()) + return false; + if (getContext().isNull()) + return false; + + DICompileUnit CU = getCompileUnit(); + if (!CU.isNull() && !CU.Verify()) + return false; + return true; +} + +/// Verify - Verify that a subprogram descriptor is well formed. +bool DISubprogram::Verify() const { + if (isNull()) + return false; + + if (getContext().isNull()) + return false; + + DICompileUnit CU = getCompileUnit(); + if (!CU.Verify()) + return false; + + DICompositeType Ty = getType(); + if (!Ty.isNull() && !Ty.Verify()) + return false; + return true; +} + +/// Verify - Verify that a global variable descriptor is well formed. +bool DIGlobalVariable::Verify() const { + if (isNull()) + return false; + + if (getDisplayName().empty()) + return false; + + if (getContext().isNull()) + return false; + + DICompileUnit CU = getCompileUnit(); + if (!CU.isNull() && !CU.Verify()) + return false; + + DIType Ty = getType(); + if (!Ty.Verify()) + return false; + + if (!getGlobal()) + return false; + + return true; +} + +/// Verify - Verify that a variable descriptor is well formed. +bool DIVariable::Verify() const { + if (isNull()) + return false; + + if (getContext().isNull()) + return false; + + DIType Ty = getType(); + if (!Ty.Verify()) + return false; + + return true; +} + +/// getOriginalTypeSize - If this type is derived from a base type then +/// return base type size. +uint64_t DIDerivedType::getOriginalTypeSize() const { + unsigned Tag = getTag(); + if (Tag == dwarf::DW_TAG_member || Tag == dwarf::DW_TAG_typedef || + Tag == dwarf::DW_TAG_const_type || Tag == dwarf::DW_TAG_volatile_type || + Tag == dwarf::DW_TAG_restrict_type) { + DIType BaseType = getTypeDerivedFrom(); + // If this type is not derived from any type then take conservative + // approach. + if (BaseType.isNull()) + return getSizeInBits(); + if (BaseType.isDerivedType()) + return DIDerivedType(BaseType.getNode()).getOriginalTypeSize(); + else + return BaseType.getSizeInBits(); + } + + return getSizeInBits(); +} + +/// describes - Return true if this subprogram provides debugging +/// information for the function F. +bool DISubprogram::describes(const Function *F) { + assert (F && "Invalid function"); + StringRef Name = getLinkageName(); + if (Name.empty()) + Name = getName(); + if (F->getName() == Name) + return true; + return false; +} + +StringRef DIScope::getFilename() const { + if (isLexicalBlock()) + return DILexicalBlock(DbgNode).getFilename(); + else if (isSubprogram()) + return DISubprogram(DbgNode).getFilename(); + else if (isCompileUnit()) + return DICompileUnit(DbgNode).getFilename(); + else + assert (0 && "Invalid DIScope!"); + return StringRef(); +} + +StringRef DIScope::getDirectory() const { + if (isLexicalBlock()) + return DILexicalBlock(DbgNode).getDirectory(); + else if (isSubprogram()) + return DISubprogram(DbgNode).getDirectory(); + else if (isCompileUnit()) + return DICompileUnit(DbgNode).getDirectory(); + else + assert (0 && "Invalid DIScope!"); + return StringRef(); +} + +//===----------------------------------------------------------------------===// +// DIDescriptor: dump routines for all descriptors. +//===----------------------------------------------------------------------===// + + +/// dump - Print descriptor. +void DIDescriptor::dump() const { + errs() << "[" << dwarf::TagString(getTag()) << "] "; + errs().write_hex((intptr_t) &*DbgNode) << ']'; +} + +/// dump - Print compile unit. +void DICompileUnit::dump() const { + if (getLanguage()) + errs() << " [" << dwarf::LanguageString(getLanguage()) << "] "; + + errs() << " [" << getDirectory() << "/" << getFilename() << " ]"; +} + +/// dump - Print type. +void DIType::dump() const { + if (isNull()) return; + + StringRef Res = getName(); + if (!Res.empty()) + errs() << " [" << Res << "] "; + + unsigned Tag = getTag(); + errs() << " [" << dwarf::TagString(Tag) << "] "; + + // TODO : Print context + getCompileUnit().dump(); + errs() << " [" + << getLineNumber() << ", " + << getSizeInBits() << ", " + << getAlignInBits() << ", " + << getOffsetInBits() + << "] "; + + if (isPrivate()) + errs() << " [private] "; + else if (isProtected()) + errs() << " [protected] "; + + if (isForwardDecl()) + errs() << " [fwd] "; + + if (isBasicType()) + DIBasicType(DbgNode).dump(); + else if (isDerivedType()) + DIDerivedType(DbgNode).dump(); + else if (isCompositeType()) + DICompositeType(DbgNode).dump(); + else { + errs() << "Invalid DIType\n"; + return; + } + + errs() << "\n"; +} + +/// dump - Print basic type. +void DIBasicType::dump() const { + errs() << " [" << dwarf::AttributeEncodingString(getEncoding()) << "] "; +} + +/// dump - Print derived type. +void DIDerivedType::dump() const { + errs() << "\n\t Derived From: "; getTypeDerivedFrom().dump(); +} + +/// dump - Print composite type. +void DICompositeType::dump() const { + DIArray A = getTypeArray(); + if (A.isNull()) + return; + errs() << " [" << A.getNumElements() << " elements]"; +} + +/// dump - Print global. +void DIGlobal::dump() const { + StringRef Res = getName(); + if (!Res.empty()) + errs() << " [" << Res << "] "; + + unsigned Tag = getTag(); + errs() << " [" << dwarf::TagString(Tag) << "] "; + + // TODO : Print context + getCompileUnit().dump(); + errs() << " [" << getLineNumber() << "] "; + + if (isLocalToUnit()) + errs() << " [local] "; + + if (isDefinition()) + errs() << " [def] "; + + if (isGlobalVariable()) + DIGlobalVariable(DbgNode).dump(); + + errs() << "\n"; +} + +/// dump - Print subprogram. +void DISubprogram::dump() const { + StringRef Res = getName(); + if (!Res.empty()) + errs() << " [" << Res << "] "; + + unsigned Tag = getTag(); + errs() << " [" << dwarf::TagString(Tag) << "] "; + + // TODO : Print context + getCompileUnit().dump(); + errs() << " [" << getLineNumber() << "] "; + + if (isLocalToUnit()) + errs() << " [local] "; + + if (isDefinition()) + errs() << " [def] "; + + errs() << "\n"; +} + +/// dump - Print global variable. +void DIGlobalVariable::dump() const { + errs() << " ["; + getGlobal()->dump(); + errs() << "] "; +} + +/// dump - Print variable. +void DIVariable::dump() const { + StringRef Res = getName(); + if (!Res.empty()) + errs() << " [" << Res << "] "; + + getCompileUnit().dump(); + errs() << " [" << getLineNumber() << "] "; + getType().dump(); + errs() << "\n"; + + // FIXME: Dump complex addresses +} + +//===----------------------------------------------------------------------===// +// DIFactory: Basic Helpers +//===----------------------------------------------------------------------===// + +DIFactory::DIFactory(Module &m) + : M(m), VMContext(M.getContext()), DeclareFn(0) { + EmptyStructPtr = PointerType::getUnqual(StructType::get(VMContext)); +} + +Constant *DIFactory::GetTagConstant(unsigned TAG) { + assert((TAG & LLVMDebugVersionMask) == 0 && + "Tag too large for debug encoding!"); + return ConstantInt::get(Type::getInt32Ty(VMContext), TAG | LLVMDebugVersion); +} + +//===----------------------------------------------------------------------===// +// DIFactory: Primary Constructors +//===----------------------------------------------------------------------===// + +/// GetOrCreateArray - Create an descriptor for an array of descriptors. +/// This implicitly uniques the arrays created. +DIArray DIFactory::GetOrCreateArray(DIDescriptor *Tys, unsigned NumTys) { + SmallVector Elts; + + if (NumTys == 0) + Elts.push_back(llvm::Constant::getNullValue(Type::getInt32Ty(VMContext))); + else + for (unsigned i = 0; i != NumTys; ++i) + Elts.push_back(Tys[i].getNode()); + + return DIArray(MDNode::get(VMContext,Elts.data(), Elts.size())); +} + +/// GetOrCreateSubrange - Create a descriptor for a value range. This +/// implicitly uniques the values returned. +DISubrange DIFactory::GetOrCreateSubrange(int64_t Lo, int64_t Hi) { + Value *Elts[] = { + GetTagConstant(dwarf::DW_TAG_subrange_type), + ConstantInt::get(Type::getInt64Ty(VMContext), Lo), + ConstantInt::get(Type::getInt64Ty(VMContext), Hi) + }; + + return DISubrange(MDNode::get(VMContext, &Elts[0], 3)); +} + + + +/// CreateCompileUnit - Create a new descriptor for the specified compile +/// unit. Note that this does not unique compile units within the module. +DICompileUnit DIFactory::CreateCompileUnit(unsigned LangID, + StringRef Filename, + StringRef Directory, + StringRef Producer, + bool isMain, + bool isOptimized, + StringRef Flags, + unsigned RunTimeVer) { + Value *Elts[] = { + GetTagConstant(dwarf::DW_TAG_compile_unit), + llvm::Constant::getNullValue(Type::getInt32Ty(VMContext)), + ConstantInt::get(Type::getInt32Ty(VMContext), LangID), + MDString::get(VMContext, Filename), + MDString::get(VMContext, Directory), + MDString::get(VMContext, Producer), + ConstantInt::get(Type::getInt1Ty(VMContext), isMain), + ConstantInt::get(Type::getInt1Ty(VMContext), isOptimized), + MDString::get(VMContext, Flags), + ConstantInt::get(Type::getInt32Ty(VMContext), RunTimeVer) + }; + + return DICompileUnit(MDNode::get(VMContext, &Elts[0], 10)); +} + +/// CreateEnumerator - Create a single enumerator value. +DIEnumerator DIFactory::CreateEnumerator(StringRef Name, uint64_t Val){ + Value *Elts[] = { + GetTagConstant(dwarf::DW_TAG_enumerator), + MDString::get(VMContext, Name), + ConstantInt::get(Type::getInt64Ty(VMContext), Val) + }; + return DIEnumerator(MDNode::get(VMContext, &Elts[0], 3)); +} + + +/// CreateBasicType - Create a basic type like int, float, etc. +DIBasicType DIFactory::CreateBasicType(DIDescriptor Context, + StringRef Name, + DICompileUnit CompileUnit, + unsigned LineNumber, + uint64_t SizeInBits, + uint64_t AlignInBits, + uint64_t OffsetInBits, unsigned Flags, + unsigned Encoding) { + Value *Elts[] = { + GetTagConstant(dwarf::DW_TAG_base_type), + Context.getNode(), + MDString::get(VMContext, Name), + CompileUnit.getNode(), + ConstantInt::get(Type::getInt32Ty(VMContext), LineNumber), + ConstantInt::get(Type::getInt64Ty(VMContext), SizeInBits), + ConstantInt::get(Type::getInt64Ty(VMContext), AlignInBits), + ConstantInt::get(Type::getInt64Ty(VMContext), OffsetInBits), + ConstantInt::get(Type::getInt32Ty(VMContext), Flags), + ConstantInt::get(Type::getInt32Ty(VMContext), Encoding) + }; + return DIBasicType(MDNode::get(VMContext, &Elts[0], 10)); +} + + +/// CreateBasicType - Create a basic type like int, float, etc. +DIBasicType DIFactory::CreateBasicTypeEx(DIDescriptor Context, + StringRef Name, + DICompileUnit CompileUnit, + unsigned LineNumber, + Constant *SizeInBits, + Constant *AlignInBits, + Constant *OffsetInBits, unsigned Flags, + unsigned Encoding) { + Value *Elts[] = { + GetTagConstant(dwarf::DW_TAG_base_type), + Context.getNode(), + MDString::get(VMContext, Name), + CompileUnit.getNode(), + ConstantInt::get(Type::getInt32Ty(VMContext), LineNumber), + SizeInBits, + AlignInBits, + OffsetInBits, + ConstantInt::get(Type::getInt32Ty(VMContext), Flags), + ConstantInt::get(Type::getInt32Ty(VMContext), Encoding) + }; + return DIBasicType(MDNode::get(VMContext, &Elts[0], 10)); +} + + +/// CreateDerivedType - Create a derived type like const qualified type, +/// pointer, typedef, etc. +DIDerivedType DIFactory::CreateDerivedType(unsigned Tag, + DIDescriptor Context, + StringRef Name, + DICompileUnit CompileUnit, + unsigned LineNumber, + uint64_t SizeInBits, + uint64_t AlignInBits, + uint64_t OffsetInBits, + unsigned Flags, + DIType DerivedFrom) { + Value *Elts[] = { + GetTagConstant(Tag), + Context.getNode(), + MDString::get(VMContext, Name), + CompileUnit.getNode(), + ConstantInt::get(Type::getInt32Ty(VMContext), LineNumber), + ConstantInt::get(Type::getInt64Ty(VMContext), SizeInBits), + ConstantInt::get(Type::getInt64Ty(VMContext), AlignInBits), + ConstantInt::get(Type::getInt64Ty(VMContext), OffsetInBits), + ConstantInt::get(Type::getInt32Ty(VMContext), Flags), + DerivedFrom.getNode(), + }; + return DIDerivedType(MDNode::get(VMContext, &Elts[0], 10)); +} + + +/// CreateDerivedType - Create a derived type like const qualified type, +/// pointer, typedef, etc. +DIDerivedType DIFactory::CreateDerivedTypeEx(unsigned Tag, + DIDescriptor Context, + StringRef Name, + DICompileUnit CompileUnit, + unsigned LineNumber, + Constant *SizeInBits, + Constant *AlignInBits, + Constant *OffsetInBits, + unsigned Flags, + DIType DerivedFrom) { + Value *Elts[] = { + GetTagConstant(Tag), + Context.getNode(), + MDString::get(VMContext, Name), + CompileUnit.getNode(), + ConstantInt::get(Type::getInt32Ty(VMContext), LineNumber), + SizeInBits, + AlignInBits, + OffsetInBits, + ConstantInt::get(Type::getInt32Ty(VMContext), Flags), + DerivedFrom.getNode(), + }; + return DIDerivedType(MDNode::get(VMContext, &Elts[0], 10)); +} + + +/// CreateCompositeType - Create a composite type like array, struct, etc. +DICompositeType DIFactory::CreateCompositeType(unsigned Tag, + DIDescriptor Context, + StringRef Name, + DICompileUnit CompileUnit, + unsigned LineNumber, + uint64_t SizeInBits, + uint64_t AlignInBits, + uint64_t OffsetInBits, + unsigned Flags, + DIType DerivedFrom, + DIArray Elements, + unsigned RuntimeLang) { + + Value *Elts[] = { + GetTagConstant(Tag), + Context.getNode(), + MDString::get(VMContext, Name), + CompileUnit.getNode(), + ConstantInt::get(Type::getInt32Ty(VMContext), LineNumber), + ConstantInt::get(Type::getInt64Ty(VMContext), SizeInBits), + ConstantInt::get(Type::getInt64Ty(VMContext), AlignInBits), + ConstantInt::get(Type::getInt64Ty(VMContext), OffsetInBits), + ConstantInt::get(Type::getInt32Ty(VMContext), Flags), + DerivedFrom.getNode(), + Elements.getNode(), + ConstantInt::get(Type::getInt32Ty(VMContext), RuntimeLang) + }; + return DICompositeType(MDNode::get(VMContext, &Elts[0], 12)); +} + + +/// CreateCompositeType - Create a composite type like array, struct, etc. +DICompositeType DIFactory::CreateCompositeTypeEx(unsigned Tag, + DIDescriptor Context, + StringRef Name, + DICompileUnit CompileUnit, + unsigned LineNumber, + Constant *SizeInBits, + Constant *AlignInBits, + Constant *OffsetInBits, + unsigned Flags, + DIType DerivedFrom, + DIArray Elements, + unsigned RuntimeLang) { + + Value *Elts[] = { + GetTagConstant(Tag), + Context.getNode(), + MDString::get(VMContext, Name), + CompileUnit.getNode(), + ConstantInt::get(Type::getInt32Ty(VMContext), LineNumber), + SizeInBits, + AlignInBits, + OffsetInBits, + ConstantInt::get(Type::getInt32Ty(VMContext), Flags), + DerivedFrom.getNode(), + Elements.getNode(), + ConstantInt::get(Type::getInt32Ty(VMContext), RuntimeLang) + }; + return DICompositeType(MDNode::get(VMContext, &Elts[0], 12)); +} + + +/// CreateSubprogram - Create a new descriptor for the specified subprogram. +/// See comments in DISubprogram for descriptions of these fields. This +/// method does not unique the generated descriptors. +DISubprogram DIFactory::CreateSubprogram(DIDescriptor Context, + StringRef Name, + StringRef DisplayName, + StringRef LinkageName, + DICompileUnit CompileUnit, + unsigned LineNo, DIType Type, + bool isLocalToUnit, + bool isDefinition) { + + Value *Elts[] = { + GetTagConstant(dwarf::DW_TAG_subprogram), + llvm::Constant::getNullValue(Type::getInt32Ty(VMContext)), + Context.getNode(), + MDString::get(VMContext, Name), + MDString::get(VMContext, DisplayName), + MDString::get(VMContext, LinkageName), + CompileUnit.getNode(), + ConstantInt::get(Type::getInt32Ty(VMContext), LineNo), + Type.getNode(), + ConstantInt::get(Type::getInt1Ty(VMContext), isLocalToUnit), + ConstantInt::get(Type::getInt1Ty(VMContext), isDefinition) + }; + return DISubprogram(MDNode::get(VMContext, &Elts[0], 11)); +} + +/// CreateGlobalVariable - Create a new descriptor for the specified global. +DIGlobalVariable +DIFactory::CreateGlobalVariable(DIDescriptor Context, StringRef Name, + StringRef DisplayName, + StringRef LinkageName, + DICompileUnit CompileUnit, + unsigned LineNo, DIType Type,bool isLocalToUnit, + bool isDefinition, llvm::GlobalVariable *Val) { + Value *Elts[] = { + GetTagConstant(dwarf::DW_TAG_variable), + llvm::Constant::getNullValue(Type::getInt32Ty(VMContext)), + Context.getNode(), + MDString::get(VMContext, Name), + MDString::get(VMContext, DisplayName), + MDString::get(VMContext, LinkageName), + CompileUnit.getNode(), + ConstantInt::get(Type::getInt32Ty(VMContext), LineNo), + Type.getNode(), + ConstantInt::get(Type::getInt1Ty(VMContext), isLocalToUnit), + ConstantInt::get(Type::getInt1Ty(VMContext), isDefinition), + Val + }; + + Value *const *Vs = &Elts[0]; + MDNode *Node = MDNode::get(VMContext,Vs, 12); + + // Create a named metadata so that we do not lose this mdnode. + NamedMDNode *NMD = M.getOrInsertNamedMetadata("llvm.dbg.gv"); + NMD->addElement(Node); + + return DIGlobalVariable(Node); +} + + +/// CreateVariable - Create a new descriptor for the specified variable. +DIVariable DIFactory::CreateVariable(unsigned Tag, DIDescriptor Context, + StringRef Name, + DICompileUnit CompileUnit, unsigned LineNo, + DIType Type) { + Value *Elts[] = { + GetTagConstant(Tag), + Context.getNode(), + MDString::get(VMContext, Name), + CompileUnit.getNode(), + ConstantInt::get(Type::getInt32Ty(VMContext), LineNo), + Type.getNode(), + }; + return DIVariable(MDNode::get(VMContext, &Elts[0], 6)); +} + + +/// CreateComplexVariable - Create a new descriptor for the specified variable +/// which has a complex address expression for its address. +DIVariable DIFactory::CreateComplexVariable(unsigned Tag, DIDescriptor Context, + const std::string &Name, + DICompileUnit CompileUnit, + unsigned LineNo, + DIType Type, SmallVector &addr) { + SmallVector Elts; + Elts.push_back(GetTagConstant(Tag)); + Elts.push_back(Context.getNode()); + Elts.push_back(MDString::get(VMContext, Name)); + Elts.push_back(CompileUnit.getNode()); + Elts.push_back(ConstantInt::get(Type::getInt32Ty(VMContext), LineNo)); + Elts.push_back(Type.getNode()); + Elts.insert(Elts.end(), addr.begin(), addr.end()); + + return DIVariable(MDNode::get(VMContext, &Elts[0], 6+addr.size())); +} + + +/// CreateBlock - This creates a descriptor for a lexical block with the +/// specified parent VMContext. +DILexicalBlock DIFactory::CreateLexicalBlock(DIDescriptor Context) { + Value *Elts[] = { + GetTagConstant(dwarf::DW_TAG_lexical_block), + Context.getNode() + }; + return DILexicalBlock(MDNode::get(VMContext, &Elts[0], 2)); +} + +/// CreateLocation - Creates a debug info location. +DILocation DIFactory::CreateLocation(unsigned LineNo, unsigned ColumnNo, + DIScope S, DILocation OrigLoc) { + Value *Elts[] = { + ConstantInt::get(Type::getInt32Ty(VMContext), LineNo), + ConstantInt::get(Type::getInt32Ty(VMContext), ColumnNo), + S.getNode(), + OrigLoc.getNode(), + }; + return DILocation(MDNode::get(VMContext, &Elts[0], 4)); +} + +/// CreateLocation - Creates a debug info location. +DILocation DIFactory::CreateLocation(unsigned LineNo, unsigned ColumnNo, + DIScope S, MDNode *OrigLoc) { + Value *Elts[] = { + ConstantInt::get(Type::getInt32Ty(VMContext), LineNo), + ConstantInt::get(Type::getInt32Ty(VMContext), ColumnNo), + S.getNode(), + OrigLoc + }; + return DILocation(MDNode::get(VMContext, &Elts[0], 4)); +} + +//===----------------------------------------------------------------------===// +// DIFactory: Routines for inserting code into a function +//===----------------------------------------------------------------------===// + +/// InsertDeclare - Insert a new llvm.dbg.declare intrinsic call. +Instruction *DIFactory::InsertDeclare(Value *Storage, DIVariable D, + Instruction *InsertBefore) { + // Cast the storage to a {}* for the call to llvm.dbg.declare. + Storage = new BitCastInst(Storage, EmptyStructPtr, "", InsertBefore); + + if (!DeclareFn) + DeclareFn = Intrinsic::getDeclaration(&M, Intrinsic::dbg_declare); + + Value *Args[] = { Storage, D.getNode() }; + return CallInst::Create(DeclareFn, Args, Args+2, "", InsertBefore); +} + +/// InsertDeclare - Insert a new llvm.dbg.declare intrinsic call. +Instruction *DIFactory::InsertDeclare(Value *Storage, DIVariable D, + BasicBlock *InsertAtEnd) { + // Cast the storage to a {}* for the call to llvm.dbg.declare. + Storage = new BitCastInst(Storage, EmptyStructPtr, "", InsertAtEnd); + + if (!DeclareFn) + DeclareFn = Intrinsic::getDeclaration(&M, Intrinsic::dbg_declare); + + Value *Args[] = { Storage, D.getNode() }; + return CallInst::Create(DeclareFn, Args, Args+2, "", InsertAtEnd); +} + + +//===----------------------------------------------------------------------===// +// DebugInfoFinder implementations. +//===----------------------------------------------------------------------===// + +/// processModule - Process entire module and collect debug info. +void DebugInfoFinder::processModule(Module &M) { + + MetadataContext &TheMetadata = M.getContext().getMetadata(); + unsigned MDDbgKind = TheMetadata.getMDKind("dbg"); + + for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) + for (Function::iterator FI = (*I).begin(), FE = (*I).end(); FI != FE; ++FI) + for (BasicBlock::iterator BI = (*FI).begin(), BE = (*FI).end(); BI != BE; + ++BI) { + if (DbgDeclareInst *DDI = dyn_cast(BI)) + processDeclare(DDI); + else if (MDDbgKind) + if (MDNode *L = TheMetadata.getMD(MDDbgKind, BI)) + processLocation(DILocation(L)); + } + + NamedMDNode *NMD = M.getNamedMetadata("llvm.dbg.gv"); + if (!NMD) + return; + + for (unsigned i = 0, e = NMD->getNumElements(); i != e; ++i) { + DIGlobalVariable DIG(cast(NMD->getElement(i))); + if (addGlobalVariable(DIG)) { + addCompileUnit(DIG.getCompileUnit()); + processType(DIG.getType()); + } + } +} + +/// processLocation - Process DILocation. +void DebugInfoFinder::processLocation(DILocation Loc) { + if (Loc.isNull()) return; + DIScope S(Loc.getScope().getNode()); + if (S.isNull()) return; + if (S.isCompileUnit()) + addCompileUnit(DICompileUnit(S.getNode())); + else if (S.isSubprogram()) + processSubprogram(DISubprogram(S.getNode())); + else if (S.isLexicalBlock()) + processLexicalBlock(DILexicalBlock(S.getNode())); + processLocation(Loc.getOrigLocation()); +} + +/// processType - Process DIType. +void DebugInfoFinder::processType(DIType DT) { + if (!addType(DT)) + return; + + addCompileUnit(DT.getCompileUnit()); + if (DT.isCompositeType()) { + DICompositeType DCT(DT.getNode()); + processType(DCT.getTypeDerivedFrom()); + DIArray DA = DCT.getTypeArray(); + if (!DA.isNull()) + for (unsigned i = 0, e = DA.getNumElements(); i != e; ++i) { + DIDescriptor D = DA.getElement(i); + DIType TypeE = DIType(D.getNode()); + if (!TypeE.isNull()) + processType(TypeE); + else + processSubprogram(DISubprogram(D.getNode())); + } + } else if (DT.isDerivedType()) { + DIDerivedType DDT(DT.getNode()); + if (!DDT.isNull()) + processType(DDT.getTypeDerivedFrom()); + } +} + +/// processLexicalBlock +void DebugInfoFinder::processLexicalBlock(DILexicalBlock LB) { + if (LB.isNull()) + return; + DIScope Context = LB.getContext(); + if (Context.isLexicalBlock()) + return processLexicalBlock(DILexicalBlock(Context.getNode())); + else + return processSubprogram(DISubprogram(Context.getNode())); +} + +/// processSubprogram - Process DISubprogram. +void DebugInfoFinder::processSubprogram(DISubprogram SP) { + if (SP.isNull()) + return; + if (!addSubprogram(SP)) + return; + addCompileUnit(SP.getCompileUnit()); + processType(SP.getType()); +} + +/// processDeclare - Process DbgDeclareInst. +void DebugInfoFinder::processDeclare(DbgDeclareInst *DDI) { + DIVariable DV(cast(DDI->getVariable())); + if (DV.isNull()) + return; + + if (!NodesSeen.insert(DV.getNode())) + return; + + addCompileUnit(DV.getCompileUnit()); + processType(DV.getType()); +} + +/// addType - Add type into Tys. +bool DebugInfoFinder::addType(DIType DT) { + if (DT.isNull()) + return false; + + if (!NodesSeen.insert(DT.getNode())) + return false; + + TYs.push_back(DT.getNode()); + return true; +} + +/// addCompileUnit - Add compile unit into CUs. +bool DebugInfoFinder::addCompileUnit(DICompileUnit CU) { + if (CU.isNull()) + return false; + + if (!NodesSeen.insert(CU.getNode())) + return false; + + CUs.push_back(CU.getNode()); + return true; +} + +/// addGlobalVariable - Add global variable into GVs. +bool DebugInfoFinder::addGlobalVariable(DIGlobalVariable DIG) { + if (DIG.isNull()) + return false; + + if (!NodesSeen.insert(DIG.getNode())) + return false; + + GVs.push_back(DIG.getNode()); + return true; +} + +// addSubprogram - Add subprgoram into SPs. +bool DebugInfoFinder::addSubprogram(DISubprogram SP) { + if (SP.isNull()) + return false; + + if (!NodesSeen.insert(SP.getNode())) + return false; + + SPs.push_back(SP.getNode()); + return true; +} + +namespace llvm { + /// findStopPoint - Find the stoppoint coressponding to this instruction, that + /// is the stoppoint that dominates this instruction. + const DbgStopPointInst *findStopPoint(const Instruction *Inst) { + if (const DbgStopPointInst *DSI = dyn_cast(Inst)) + return DSI; + + const BasicBlock *BB = Inst->getParent(); + BasicBlock::const_iterator I = Inst, B; + while (BB) { + B = BB->begin(); + + // A BB consisting only of a terminator can't have a stoppoint. + while (I != B) { + --I; + if (const DbgStopPointInst *DSI = dyn_cast(I)) + return DSI; + } + + // This BB didn't have a stoppoint: if there is only one predecessor, look + // for a stoppoint there. We could use getIDom(), but that would require + // dominator info. + BB = I->getParent()->getUniquePredecessor(); + if (BB) + I = BB->getTerminator(); + } + + return 0; + } + + /// findBBStopPoint - Find the stoppoint corresponding to first real + /// (non-debug intrinsic) instruction in this Basic Block, and return the + /// stoppoint for it. + const DbgStopPointInst *findBBStopPoint(const BasicBlock *BB) { + for(BasicBlock::const_iterator I = BB->begin(), E = BB->end(); I != E; ++I) + if (const DbgStopPointInst *DSI = dyn_cast(I)) + return DSI; + + // Fallback to looking for stoppoint of unique predecessor. Useful if this + // BB contains no stoppoints, but unique predecessor does. + BB = BB->getUniquePredecessor(); + if (BB) + return findStopPoint(BB->getTerminator()); + + return 0; + } + + Value *findDbgGlobalDeclare(GlobalVariable *V) { + const Module *M = V->getParent(); + NamedMDNode *NMD = M->getNamedMetadata("llvm.dbg.gv"); + if (!NMD) + return 0; + + for (unsigned i = 0, e = NMD->getNumElements(); i != e; ++i) { + DIGlobalVariable DIG(cast_or_null(NMD->getElement(i))); + if (DIG.isNull()) + continue; + if (DIG.getGlobal() == V) + return DIG.getNode(); + } + return 0; + } + + /// Finds the llvm.dbg.declare intrinsic corresponding to this value if any. + /// It looks through pointer casts too. + const DbgDeclareInst *findDbgDeclare(const Value *V, bool stripCasts) { + if (stripCasts) { + V = V->stripPointerCasts(); + + // Look for the bitcast. + for (Value::use_const_iterator I = V->use_begin(), E =V->use_end(); + I != E; ++I) + if (isa(I)) { + const DbgDeclareInst *DDI = findDbgDeclare(*I, false); + if (DDI) return DDI; + } + return 0; + } + + // Find llvm.dbg.declare among uses of the instruction. + for (Value::use_const_iterator I = V->use_begin(), E =V->use_end(); + I != E; ++I) + if (const DbgDeclareInst *DDI = dyn_cast(I)) + return DDI; + + return 0; + } + +bool getLocationInfo(const Value *V, std::string &DisplayName, + std::string &Type, unsigned &LineNo, std::string &File, + std::string &Dir) { + DICompileUnit Unit; + DIType TypeD; + + if (GlobalVariable *GV = dyn_cast(const_cast(V))) { + Value *DIGV = findDbgGlobalDeclare(GV); + if (!DIGV) return false; + DIGlobalVariable Var(cast(DIGV)); + + StringRef D = Var.getDisplayName(); + if (!D.empty()) + DisplayName = D; + LineNo = Var.getLineNumber(); + Unit = Var.getCompileUnit(); + TypeD = Var.getType(); + } else { + const DbgDeclareInst *DDI = findDbgDeclare(V); + if (!DDI) return false; + DIVariable Var(cast(DDI->getVariable())); + + StringRef D = Var.getName(); + if (!D.empty()) + DisplayName = D; + LineNo = Var.getLineNumber(); + Unit = Var.getCompileUnit(); + TypeD = Var.getType(); + } + + StringRef T = TypeD.getName(); + if (!T.empty()) + Type = T; + StringRef F = Unit.getFilename(); + if (!F.empty()) + File = F; + StringRef D = Unit.getDirectory(); + if (!D.empty()) + Dir = D; + return true; + } + + /// isValidDebugInfoIntrinsic - Return true if SPI is a valid debug + /// info intrinsic. + bool isValidDebugInfoIntrinsic(DbgStopPointInst &SPI, + CodeGenOpt::Level OptLev) { + return DIDescriptor::ValidDebugInfo(SPI.getContext(), OptLev); + } + + /// isValidDebugInfoIntrinsic - Return true if FSI is a valid debug + /// info intrinsic. + bool isValidDebugInfoIntrinsic(DbgFuncStartInst &FSI, + CodeGenOpt::Level OptLev) { + return DIDescriptor::ValidDebugInfo(FSI.getSubprogram(), OptLev); + } + + /// isValidDebugInfoIntrinsic - Return true if RSI is a valid debug + /// info intrinsic. + bool isValidDebugInfoIntrinsic(DbgRegionStartInst &RSI, + CodeGenOpt::Level OptLev) { + return DIDescriptor::ValidDebugInfo(RSI.getContext(), OptLev); + } + + /// isValidDebugInfoIntrinsic - Return true if REI is a valid debug + /// info intrinsic. + bool isValidDebugInfoIntrinsic(DbgRegionEndInst &REI, + CodeGenOpt::Level OptLev) { + return DIDescriptor::ValidDebugInfo(REI.getContext(), OptLev); + } + + + /// isValidDebugInfoIntrinsic - Return true if DI is a valid debug + /// info intrinsic. + bool isValidDebugInfoIntrinsic(DbgDeclareInst &DI, + CodeGenOpt::Level OptLev) { + return DIDescriptor::ValidDebugInfo(DI.getVariable(), OptLev); + } + + /// ExtractDebugLocation - Extract debug location information + /// from llvm.dbg.stoppoint intrinsic. + DebugLoc ExtractDebugLocation(DbgStopPointInst &SPI, + DebugLocTracker &DebugLocInfo) { + DebugLoc DL; + Value *Context = SPI.getContext(); + + // If this location is already tracked then use it. + DebugLocTuple Tuple(cast(Context), NULL, SPI.getLine(), + SPI.getColumn()); + DenseMap::iterator II + = DebugLocInfo.DebugIdMap.find(Tuple); + if (II != DebugLocInfo.DebugIdMap.end()) + return DebugLoc::get(II->second); + + // Add a new location entry. + unsigned Id = DebugLocInfo.DebugLocations.size(); + DebugLocInfo.DebugLocations.push_back(Tuple); + DebugLocInfo.DebugIdMap[Tuple] = Id; + + return DebugLoc::get(Id); + } + + /// ExtractDebugLocation - Extract debug location information + /// from DILocation. + DebugLoc ExtractDebugLocation(DILocation &Loc, + DebugLocTracker &DebugLocInfo) { + DebugLoc DL; + MDNode *Context = Loc.getScope().getNode(); + MDNode *InlinedLoc = NULL; + if (!Loc.getOrigLocation().isNull()) + InlinedLoc = Loc.getOrigLocation().getNode(); + // If this location is already tracked then use it. + DebugLocTuple Tuple(Context, InlinedLoc, Loc.getLineNumber(), + Loc.getColumnNumber()); + DenseMap::iterator II + = DebugLocInfo.DebugIdMap.find(Tuple); + if (II != DebugLocInfo.DebugIdMap.end()) + return DebugLoc::get(II->second); + + // Add a new location entry. + unsigned Id = DebugLocInfo.DebugLocations.size(); + DebugLocInfo.DebugLocations.push_back(Tuple); + DebugLocInfo.DebugIdMap[Tuple] = Id; + + return DebugLoc::get(Id); + } + + /// ExtractDebugLocation - Extract debug location information + /// from llvm.dbg.func_start intrinsic. + DebugLoc ExtractDebugLocation(DbgFuncStartInst &FSI, + DebugLocTracker &DebugLocInfo) { + DebugLoc DL; + Value *SP = FSI.getSubprogram(); + + DISubprogram Subprogram(cast(SP)); + unsigned Line = Subprogram.getLineNumber(); + DICompileUnit CU(Subprogram.getCompileUnit()); + + // If this location is already tracked then use it. + DebugLocTuple Tuple(CU.getNode(), NULL, Line, /* Column */ 0); + DenseMap::iterator II + = DebugLocInfo.DebugIdMap.find(Tuple); + if (II != DebugLocInfo.DebugIdMap.end()) + return DebugLoc::get(II->second); + + // Add a new location entry. + unsigned Id = DebugLocInfo.DebugLocations.size(); + DebugLocInfo.DebugLocations.push_back(Tuple); + DebugLocInfo.DebugIdMap[Tuple] = Id; + + return DebugLoc::get(Id); + } + + /// getDISubprogram - Find subprogram that is enclosing this scope. + DISubprogram getDISubprogram(MDNode *Scope) { + DIDescriptor D(Scope); + if (D.isNull()) + return DISubprogram(); + + if (D.isCompileUnit()) + return DISubprogram(); + + if (D.isSubprogram()) + return DISubprogram(Scope); + + if (D.isLexicalBlock()) + return getDISubprogram(DILexicalBlock(Scope).getContext().getNode()); + + return DISubprogram(); + } + + /// getDICompositeType - Find underlying composite type. + DICompositeType getDICompositeType(DIType T) { + if (T.isNull()) + return DICompositeType(); + + if (T.isCompositeType()) + return DICompositeType(T.getNode()); + + if (T.isDerivedType()) + return getDICompositeType(DIDerivedType(T.getNode()).getTypeDerivedFrom()); + + return DICompositeType(); + } +} diff --git a/libclamav/c++/llvm/lib/Analysis/DomPrinter.cpp b/libclamav/c++/llvm/lib/Analysis/DomPrinter.cpp new file mode 100644 index 000000000..f1b44d035 --- /dev/null +++ b/libclamav/c++/llvm/lib/Analysis/DomPrinter.cpp @@ -0,0 +1,265 @@ +//===- DomPrinter.cpp - DOT printer for the dominance trees ------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines '-dot-dom' and '-dot-postdom' analysis passes, which emit +// a dom..dot or postdom..dot file for each function in the +// program, with a graph of the dominance/postdominance tree of that +// function. +// +// There are also passes available to directly call dotty ('-view-dom' or +// '-view-postdom'). By appending '-only' like '-dot-dom-only' only the +// names of the bbs are printed, but the content is hidden. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Analysis/DomPrinter.h" +#include "llvm/Pass.h" +#include "llvm/Function.h" +#include "llvm/Analysis/CFGPrinter.h" +#include "llvm/Analysis/Dominators.h" +#include "llvm/Analysis/PostDominators.h" + +using namespace llvm; + +namespace llvm { +template<> +struct DOTGraphTraits : public DefaultDOTGraphTraits { + static std::string getNodeLabel(DomTreeNode *Node, DomTreeNode *Graph, + bool ShortNames) { + + BasicBlock *BB = Node->getBlock(); + + if (!BB) + return "Post dominance root node"; + + return DOTGraphTraits::getNodeLabel(BB, BB->getParent(), + ShortNames); + } +}; + +template<> +struct DOTGraphTraits : public DOTGraphTraits { + + static std::string getGraphName(DominatorTree *DT) { + return "Dominator tree"; + } + + static std::string getNodeLabel(DomTreeNode *Node, + DominatorTree *G, + bool ShortNames) { + return DOTGraphTraits::getNodeLabel(Node, G->getRootNode(), + ShortNames); + } +}; + +template<> +struct DOTGraphTraits + : public DOTGraphTraits { + static std::string getGraphName(PostDominatorTree *DT) { + return "Post dominator tree"; + } + static std::string getNodeLabel(DomTreeNode *Node, + PostDominatorTree *G, + bool ShortNames) { + return DOTGraphTraits::getNodeLabel(Node, + G->getRootNode(), + ShortNames); + } +}; +} + +namespace { +template +struct GenericGraphViewer : public FunctionPass { + std::string Name; + + GenericGraphViewer(std::string GraphName, const void *ID) : FunctionPass(ID) { + Name = GraphName; + } + + virtual bool runOnFunction(Function &F) { + Analysis *Graph; + + Graph = &getAnalysis(); + ViewGraph(Graph, Name, OnlyBBS); + + return false; + } + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + AU.addRequired(); + } +}; + +struct DomViewer + : public GenericGraphViewer { + static char ID; + DomViewer() : GenericGraphViewer("dom", &ID){} +}; + +struct DomOnlyViewer + : public GenericGraphViewer { + static char ID; + DomOnlyViewer() : GenericGraphViewer("domonly", &ID){} +}; + +struct PostDomViewer + : public GenericGraphViewer { + static char ID; + PostDomViewer() : + GenericGraphViewer("postdom", &ID){} +}; + +struct PostDomOnlyViewer + : public GenericGraphViewer { + static char ID; + PostDomOnlyViewer() : + GenericGraphViewer("postdomonly", &ID){} +}; +} // end anonymous namespace + +char DomViewer::ID = 0; +RegisterPass A("view-dom", + "View dominance tree of function"); + +char DomOnlyViewer::ID = 0; +RegisterPass B("view-dom-only", + "View dominance tree of function " + "(with no function bodies)"); + +char PostDomViewer::ID = 0; +RegisterPass C("view-postdom", + "View postdominance tree of function"); + +char PostDomOnlyViewer::ID = 0; +RegisterPass D("view-postdom-only", + "View postdominance tree of function " + "(with no function bodies)"); + +namespace { +template +struct GenericGraphPrinter : public FunctionPass { + + std::string Name; + + GenericGraphPrinter(std::string GraphName, const void *ID) + : FunctionPass(ID) { + Name = GraphName; + } + + virtual bool runOnFunction(Function &F) { + Analysis *Graph; + std::string Filename = Name + "." + F.getNameStr() + ".dot"; + errs() << "Writing '" << Filename << "'..."; + + std::string ErrorInfo; + raw_fd_ostream File(Filename.c_str(), ErrorInfo); + Graph = &getAnalysis(); + + if (ErrorInfo.empty()) + WriteGraph(File, Graph, OnlyBBS); + else + errs() << " error opening file for writing!"; + errs() << "\n"; + return false; + } + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + AU.addRequired(); + } +}; + +struct DomPrinter + : public GenericGraphPrinter { + static char ID; + DomPrinter() : GenericGraphPrinter("dom", &ID) {} +}; + +struct DomOnlyPrinter + : public GenericGraphPrinter { + static char ID; + DomOnlyPrinter() : GenericGraphPrinter("domonly", &ID) {} +}; + +struct PostDomPrinter + : public GenericGraphPrinter { + static char ID; + PostDomPrinter() : + GenericGraphPrinter("postdom", &ID) {} +}; + +struct PostDomOnlyPrinter + : public GenericGraphPrinter { + static char ID; + PostDomOnlyPrinter() : + GenericGraphPrinter("postdomonly", &ID) {} +}; +} // end anonymous namespace + + + +char DomPrinter::ID = 0; +RegisterPass E("dot-dom", + "Print dominance tree of function " + "to 'dot' file"); + +char DomOnlyPrinter::ID = 0; +RegisterPass F("dot-dom-only", + "Print dominance tree of function " + "to 'dot' file " + "(with no function bodies)"); + +char PostDomPrinter::ID = 0; +RegisterPass G("dot-postdom", + "Print postdominance tree of function " + "to 'dot' file"); + +char PostDomOnlyPrinter::ID = 0; +RegisterPass H("dot-postdom-only", + "Print postdominance tree of function " + "to 'dot' file " + "(with no function bodies)"); + +// Create methods available outside of this file, to use them +// "include/llvm/LinkAllPasses.h". Otherwise the pass would be deleted by +// the link time optimization. + +FunctionPass *llvm::createDomPrinterPass() { + return new DomPrinter(); +} + +FunctionPass *llvm::createDomOnlyPrinterPass() { + return new DomOnlyPrinter(); +} + +FunctionPass *llvm::createDomViewerPass() { + return new DomViewer(); +} + +FunctionPass *llvm::createDomOnlyViewerPass() { + return new DomOnlyViewer(); +} + +FunctionPass *llvm::createPostDomPrinterPass() { + return new PostDomPrinter(); +} + +FunctionPass *llvm::createPostDomOnlyPrinterPass() { + return new PostDomOnlyPrinter(); +} + +FunctionPass *llvm::createPostDomViewerPass() { + return new PostDomViewer(); +} + +FunctionPass *llvm::createPostDomOnlyViewerPass() { + return new PostDomOnlyViewer(); +} diff --git a/libclamav/c++/llvm/lib/Analysis/IPA/Andersens.cpp b/libclamav/c++/llvm/lib/Analysis/IPA/Andersens.cpp new file mode 100644 index 000000000..e12db8174 --- /dev/null +++ b/libclamav/c++/llvm/lib/Analysis/IPA/Andersens.cpp @@ -0,0 +1,2860 @@ +//===- Andersens.cpp - Andersen's Interprocedural Alias Analysis ----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines an implementation of Andersen's interprocedural alias +// analysis +// +// In pointer analysis terms, this is a subset-based, flow-insensitive, +// field-sensitive, and context-insensitive algorithm pointer algorithm. +// +// This algorithm is implemented as three stages: +// 1. Object identification. +// 2. Inclusion constraint identification. +// 3. Offline constraint graph optimization +// 4. Inclusion constraint solving. +// +// The object identification stage identifies all of the memory objects in the +// program, which includes globals, heap allocated objects, and stack allocated +// objects. +// +// The inclusion constraint identification stage finds all inclusion constraints +// in the program by scanning the program, looking for pointer assignments and +// other statements that effect the points-to graph. For a statement like "A = +// B", this statement is processed to indicate that A can point to anything that +// B can point to. Constraints can handle copies, loads, and stores, and +// address taking. +// +// The offline constraint graph optimization portion includes offline variable +// substitution algorithms intended to compute pointer and location +// equivalences. Pointer equivalences are those pointers that will have the +// same points-to sets, and location equivalences are those variables that +// always appear together in points-to sets. It also includes an offline +// cycle detection algorithm that allows cycles to be collapsed sooner +// during solving. +// +// The inclusion constraint solving phase iteratively propagates the inclusion +// constraints until a fixed point is reached. This is an O(N^3) algorithm. +// +// Function constraints are handled as if they were structs with X fields. +// Thus, an access to argument X of function Y is an access to node index +// getNode(Y) + X. This representation allows handling of indirect calls +// without any issues. To wit, an indirect call Y(a,b) is equivalent to +// *(Y + 1) = a, *(Y + 2) = b. +// The return node for a function is always located at getNode(F) + +// CallReturnPos. The arguments start at getNode(F) + CallArgPos. +// +// Future Improvements: +// Use of BDD's. +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "anders-aa" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Instructions.h" +#include "llvm/Module.h" +#include "llvm/Pass.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/InstIterator.h" +#include "llvm/Support/InstVisitor.h" +#include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/Analysis/MemoryBuiltins.h" +#include "llvm/Analysis/Passes.h" +#include "llvm/Support/Debug.h" +#include "llvm/System/Atomic.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/ADT/SparseBitVector.h" +#include "llvm/ADT/DenseSet.h" +#include +#include +#include +#include +#include +#include +#include + +// Determining the actual set of nodes the universal set can consist of is very +// expensive because it means propagating around very large sets. We rely on +// other analysis being able to determine which nodes can never be pointed to in +// order to disambiguate further than "points-to anything". +#define FULL_UNIVERSAL 0 + +using namespace llvm; +#ifndef NDEBUG +STATISTIC(NumIters , "Number of iterations to reach convergence"); +#endif +STATISTIC(NumConstraints, "Number of constraints"); +STATISTIC(NumNodes , "Number of nodes"); +STATISTIC(NumUnified , "Number of variables unified"); +STATISTIC(NumErased , "Number of redundant constraints erased"); + +static const unsigned SelfRep = (unsigned)-1; +static const unsigned Unvisited = (unsigned)-1; +// Position of the function return node relative to the function node. +static const unsigned CallReturnPos = 1; +// Position of the function call node relative to the function node. +static const unsigned CallFirstArgPos = 2; + +namespace { + struct BitmapKeyInfo { + static inline SparseBitVector<> *getEmptyKey() { + return reinterpret_cast *>(-1); + } + static inline SparseBitVector<> *getTombstoneKey() { + return reinterpret_cast *>(-2); + } + static unsigned getHashValue(const SparseBitVector<> *bitmap) { + return bitmap->getHashValue(); + } + static bool isEqual(const SparseBitVector<> *LHS, + const SparseBitVector<> *RHS) { + if (LHS == RHS) + return true; + else if (LHS == getEmptyKey() || RHS == getEmptyKey() + || LHS == getTombstoneKey() || RHS == getTombstoneKey()) + return false; + + return *LHS == *RHS; + } + + static bool isPod() { return true; } + }; + + class Andersens : public ModulePass, public AliasAnalysis, + private InstVisitor { + struct Node; + + /// Constraint - Objects of this structure are used to represent the various + /// constraints identified by the algorithm. The constraints are 'copy', + /// for statements like "A = B", 'load' for statements like "A = *B", + /// 'store' for statements like "*A = B", and AddressOf for statements like + /// A = alloca; The Offset is applied as *(A + K) = B for stores, + /// A = *(B + K) for loads, and A = B + K for copies. It is + /// illegal on addressof constraints (because it is statically + /// resolvable to A = &C where C = B + K) + + struct Constraint { + enum ConstraintType { Copy, Load, Store, AddressOf } Type; + unsigned Dest; + unsigned Src; + unsigned Offset; + + Constraint(ConstraintType Ty, unsigned D, unsigned S, unsigned O = 0) + : Type(Ty), Dest(D), Src(S), Offset(O) { + assert((Offset == 0 || Ty != AddressOf) && + "Offset is illegal on addressof constraints"); + } + + bool operator==(const Constraint &RHS) const { + return RHS.Type == Type + && RHS.Dest == Dest + && RHS.Src == Src + && RHS.Offset == Offset; + } + + bool operator!=(const Constraint &RHS) const { + return !(*this == RHS); + } + + bool operator<(const Constraint &RHS) const { + if (RHS.Type != Type) + return RHS.Type < Type; + else if (RHS.Dest != Dest) + return RHS.Dest < Dest; + else if (RHS.Src != Src) + return RHS.Src < Src; + return RHS.Offset < Offset; + } + }; + + // Information DenseSet requires implemented in order to be able to do + // it's thing + struct PairKeyInfo { + static inline std::pair getEmptyKey() { + return std::make_pair(~0U, ~0U); + } + static inline std::pair getTombstoneKey() { + return std::make_pair(~0U - 1, ~0U - 1); + } + static unsigned getHashValue(const std::pair &P) { + return P.first ^ P.second; + } + static unsigned isEqual(const std::pair &LHS, + const std::pair &RHS) { + return LHS == RHS; + } + }; + + struct ConstraintKeyInfo { + static inline Constraint getEmptyKey() { + return Constraint(Constraint::Copy, ~0U, ~0U, ~0U); + } + static inline Constraint getTombstoneKey() { + return Constraint(Constraint::Copy, ~0U - 1, ~0U - 1, ~0U - 1); + } + static unsigned getHashValue(const Constraint &C) { + return C.Src ^ C.Dest ^ C.Type ^ C.Offset; + } + static bool isEqual(const Constraint &LHS, + const Constraint &RHS) { + return LHS.Type == RHS.Type && LHS.Dest == RHS.Dest + && LHS.Src == RHS.Src && LHS.Offset == RHS.Offset; + } + }; + + // Node class - This class is used to represent a node in the constraint + // graph. Due to various optimizations, it is not always the case that + // there is a mapping from a Node to a Value. In particular, we add + // artificial Node's that represent the set of pointed-to variables shared + // for each location equivalent Node. + struct Node { + private: + static volatile sys::cas_flag Counter; + + public: + Value *Val; + SparseBitVector<> *Edges; + SparseBitVector<> *PointsTo; + SparseBitVector<> *OldPointsTo; + std::list Constraints; + + // Pointer and location equivalence labels + unsigned PointerEquivLabel; + unsigned LocationEquivLabel; + // Predecessor edges, both real and implicit + SparseBitVector<> *PredEdges; + SparseBitVector<> *ImplicitPredEdges; + // Set of nodes that point to us, only use for location equivalence. + SparseBitVector<> *PointedToBy; + // Number of incoming edges, used during variable substitution to early + // free the points-to sets + unsigned NumInEdges; + // True if our points-to set is in the Set2PEClass map + bool StoredInHash; + // True if our node has no indirect constraints (complex or otherwise) + bool Direct; + // True if the node is address taken, *or* it is part of a group of nodes + // that must be kept together. This is set to true for functions and + // their arg nodes, which must be kept at the same position relative to + // their base function node. + bool AddressTaken; + + // Nodes in cycles (or in equivalence classes) are united together using a + // standard union-find representation with path compression. NodeRep + // gives the index into GraphNodes for the representative Node. + unsigned NodeRep; + + // Modification timestamp. Assigned from Counter. + // Used for work list prioritization. + unsigned Timestamp; + + explicit Node(bool direct = true) : + Val(0), Edges(0), PointsTo(0), OldPointsTo(0), + PointerEquivLabel(0), LocationEquivLabel(0), PredEdges(0), + ImplicitPredEdges(0), PointedToBy(0), NumInEdges(0), + StoredInHash(false), Direct(direct), AddressTaken(false), + NodeRep(SelfRep), Timestamp(0) { } + + Node *setValue(Value *V) { + assert(Val == 0 && "Value already set for this node!"); + Val = V; + return this; + } + + /// getValue - Return the LLVM value corresponding to this node. + /// + Value *getValue() const { return Val; } + + /// addPointerTo - Add a pointer to the list of pointees of this node, + /// returning true if this caused a new pointer to be added, or false if + /// we already knew about the points-to relation. + bool addPointerTo(unsigned Node) { + return PointsTo->test_and_set(Node); + } + + /// intersects - Return true if the points-to set of this node intersects + /// with the points-to set of the specified node. + bool intersects(Node *N) const; + + /// intersectsIgnoring - Return true if the points-to set of this node + /// intersects with the points-to set of the specified node on any nodes + /// except for the specified node to ignore. + bool intersectsIgnoring(Node *N, unsigned) const; + + // Timestamp a node (used for work list prioritization) + void Stamp() { + Timestamp = sys::AtomicIncrement(&Counter); + --Timestamp; + } + + bool isRep() const { + return( (int) NodeRep < 0 ); + } + }; + + struct WorkListElement { + Node* node; + unsigned Timestamp; + WorkListElement(Node* n, unsigned t) : node(n), Timestamp(t) {} + + // Note that we reverse the sense of the comparison because we + // actually want to give low timestamps the priority over high, + // whereas priority is typically interpreted as a greater value is + // given high priority. + bool operator<(const WorkListElement& that) const { + return( this->Timestamp > that.Timestamp ); + } + }; + + // Priority-queue based work list specialized for Nodes. + class WorkList { + std::priority_queue Q; + + public: + void insert(Node* n) { + Q.push( WorkListElement(n, n->Timestamp) ); + } + + // We automatically discard non-representative nodes and nodes + // that were in the work list twice (we keep a copy of the + // timestamp in the work list so we can detect this situation by + // comparing against the node's current timestamp). + Node* pop() { + while( !Q.empty() ) { + WorkListElement x = Q.top(); Q.pop(); + Node* INode = x.node; + + if( INode->isRep() && + INode->Timestamp == x.Timestamp ) { + return(x.node); + } + } + return(0); + } + + bool empty() { + return Q.empty(); + } + }; + + /// GraphNodes - This vector is populated as part of the object + /// identification stage of the analysis, which populates this vector with a + /// node for each memory object and fills in the ValueNodes map. + std::vector GraphNodes; + + /// ValueNodes - This map indicates the Node that a particular Value* is + /// represented by. This contains entries for all pointers. + DenseMap ValueNodes; + + /// ObjectNodes - This map contains entries for each memory object in the + /// program: globals, alloca's and mallocs. + DenseMap ObjectNodes; + + /// ReturnNodes - This map contains an entry for each function in the + /// program that returns a value. + DenseMap ReturnNodes; + + /// VarargNodes - This map contains the entry used to represent all pointers + /// passed through the varargs portion of a function call for a particular + /// function. An entry is not present in this map for functions that do not + /// take variable arguments. + DenseMap VarargNodes; + + + /// Constraints - This vector contains a list of all of the constraints + /// identified by the program. + std::vector Constraints; + + // Map from graph node to maximum K value that is allowed (for functions, + // this is equivalent to the number of arguments + CallFirstArgPos) + std::map MaxK; + + /// This enum defines the GraphNodes indices that correspond to important + /// fixed sets. + enum { + UniversalSet = 0, + NullPtr = 1, + NullObject = 2, + NumberSpecialNodes + }; + // Stack for Tarjan's + std::stack SCCStack; + // Map from Graph Node to DFS number + std::vector Node2DFS; + // Map from Graph Node to Deleted from graph. + std::vector Node2Deleted; + // Same as Node Maps, but implemented as std::map because it is faster to + // clear + std::map Tarjan2DFS; + std::map Tarjan2Deleted; + // Current DFS number + unsigned DFSNumber; + + // Work lists. + WorkList w1, w2; + WorkList *CurrWL, *NextWL; // "current" and "next" work lists + + // Offline variable substitution related things + + // Temporary rep storage, used because we can't collapse SCC's in the + // predecessor graph by uniting the variables permanently, we can only do so + // for the successor graph. + std::vector VSSCCRep; + // Mapping from node to whether we have visited it during SCC finding yet. + std::vector Node2Visited; + // During variable substitution, we create unknowns to represent the unknown + // value that is a dereference of a variable. These nodes are known as + // "ref" nodes (since they represent the value of dereferences). + unsigned FirstRefNode; + // During HVN, we create represent address taken nodes as if they were + // unknown (since HVN, unlike HU, does not evaluate unions). + unsigned FirstAdrNode; + // Current pointer equivalence class number + unsigned PEClass; + // Mapping from points-to sets to equivalence classes + typedef DenseMap *, unsigned, BitmapKeyInfo> BitVectorMap; + BitVectorMap Set2PEClass; + // Mapping from pointer equivalences to the representative node. -1 if we + // have no representative node for this pointer equivalence class yet. + std::vector PEClass2Node; + // Mapping from pointer equivalences to representative node. This includes + // pointer equivalent but not location equivalent variables. -1 if we have + // no representative node for this pointer equivalence class yet. + std::vector PENLEClass2Node; + // Union/Find for HCD + std::vector HCDSCCRep; + // HCD's offline-detected cycles; "Statically DeTected" + // -1 if not part of such a cycle, otherwise a representative node. + std::vector SDT; + // Whether to use SDT (UniteNodes can use it during solving, but not before) + bool SDTActive; + + public: + static char ID; + Andersens() : ModulePass(&ID) {} + + bool runOnModule(Module &M) { + InitializeAliasAnalysis(this); + IdentifyObjects(M); + CollectConstraints(M); +#undef DEBUG_TYPE +#define DEBUG_TYPE "anders-aa-constraints" + DEBUG(PrintConstraints()); +#undef DEBUG_TYPE +#define DEBUG_TYPE "anders-aa" + SolveConstraints(); + DEBUG(PrintPointsToGraph()); + + // Free the constraints list, as we don't need it to respond to alias + // requests. + std::vector().swap(Constraints); + //These are needed for Print() (-analyze in opt) + //ObjectNodes.clear(); + //ReturnNodes.clear(); + //VarargNodes.clear(); + return false; + } + + void releaseMemory() { + // FIXME: Until we have transitively required passes working correctly, + // this cannot be enabled! Otherwise, using -count-aa with the pass + // causes memory to be freed too early. :( +#if 0 + // The memory objects and ValueNodes data structures at the only ones that + // are still live after construction. + std::vector().swap(GraphNodes); + ValueNodes.clear(); +#endif + } + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AliasAnalysis::getAnalysisUsage(AU); + AU.setPreservesAll(); // Does not transform code + } + + //------------------------------------------------ + // Implement the AliasAnalysis API + // + AliasResult alias(const Value *V1, unsigned V1Size, + const Value *V2, unsigned V2Size); + virtual ModRefResult getModRefInfo(CallSite CS, Value *P, unsigned Size); + virtual ModRefResult getModRefInfo(CallSite CS1, CallSite CS2); + bool pointsToConstantMemory(const Value *P); + + virtual void deleteValue(Value *V) { + ValueNodes.erase(V); + getAnalysis().deleteValue(V); + } + + virtual void copyValue(Value *From, Value *To) { + ValueNodes[To] = ValueNodes[From]; + getAnalysis().copyValue(From, To); + } + + private: + /// getNode - Return the node corresponding to the specified pointer scalar. + /// + unsigned getNode(Value *V) { + if (Constant *C = dyn_cast(V)) + if (!isa(C)) + return getNodeForConstantPointer(C); + + DenseMap::iterator I = ValueNodes.find(V); + if (I == ValueNodes.end()) { +#ifndef NDEBUG + V->dump(); +#endif + llvm_unreachable("Value does not have a node in the points-to graph!"); + } + return I->second; + } + + /// getObject - Return the node corresponding to the memory object for the + /// specified global or allocation instruction. + unsigned getObject(Value *V) const { + DenseMap::const_iterator I = ObjectNodes.find(V); + assert(I != ObjectNodes.end() && + "Value does not have an object in the points-to graph!"); + return I->second; + } + + /// getReturnNode - Return the node representing the return value for the + /// specified function. + unsigned getReturnNode(Function *F) const { + DenseMap::const_iterator I = ReturnNodes.find(F); + assert(I != ReturnNodes.end() && "Function does not return a value!"); + return I->second; + } + + /// getVarargNode - Return the node representing the variable arguments + /// formal for the specified function. + unsigned getVarargNode(Function *F) const { + DenseMap::const_iterator I = VarargNodes.find(F); + assert(I != VarargNodes.end() && "Function does not take var args!"); + return I->second; + } + + /// getNodeValue - Get the node for the specified LLVM value and set the + /// value for it to be the specified value. + unsigned getNodeValue(Value &V) { + unsigned Index = getNode(&V); + GraphNodes[Index].setValue(&V); + return Index; + } + + unsigned UniteNodes(unsigned First, unsigned Second, + bool UnionByRank = true); + unsigned FindNode(unsigned Node); + unsigned FindNode(unsigned Node) const; + + void IdentifyObjects(Module &M); + void CollectConstraints(Module &M); + bool AnalyzeUsesOfFunction(Value *); + void CreateConstraintGraph(); + void OptimizeConstraints(); + unsigned FindEquivalentNode(unsigned, unsigned); + void ClumpAddressTaken(); + void RewriteConstraints(); + void HU(); + void HVN(); + void HCD(); + void Search(unsigned Node); + void UnitePointerEquivalences(); + void SolveConstraints(); + bool QueryNode(unsigned Node); + void Condense(unsigned Node); + void HUValNum(unsigned Node); + void HVNValNum(unsigned Node); + unsigned getNodeForConstantPointer(Constant *C); + unsigned getNodeForConstantPointerTarget(Constant *C); + void AddGlobalInitializerConstraints(unsigned, Constant *C); + + void AddConstraintsForNonInternalLinkage(Function *F); + void AddConstraintsForCall(CallSite CS, Function *F); + bool AddConstraintsForExternalCall(CallSite CS, Function *F); + + + void PrintNode(const Node *N) const; + void PrintConstraints() const ; + void PrintConstraint(const Constraint &) const; + void PrintLabels() const; + void PrintPointsToGraph() const; + + //===------------------------------------------------------------------===// + // Instruction visitation methods for adding constraints + // + friend class InstVisitor; + void visitReturnInst(ReturnInst &RI); + void visitInvokeInst(InvokeInst &II) { visitCallSite(CallSite(&II)); } + void visitCallInst(CallInst &CI) { + if (isMalloc(&CI)) visitAlloc(CI); + else visitCallSite(CallSite(&CI)); + } + void visitCallSite(CallSite CS); + void visitAllocaInst(AllocaInst &I); + void visitAlloc(Instruction &I); + void visitLoadInst(LoadInst &LI); + void visitStoreInst(StoreInst &SI); + void visitGetElementPtrInst(GetElementPtrInst &GEP); + void visitPHINode(PHINode &PN); + void visitCastInst(CastInst &CI); + void visitICmpInst(ICmpInst &ICI) {} // NOOP! + void visitFCmpInst(FCmpInst &ICI) {} // NOOP! + void visitSelectInst(SelectInst &SI); + void visitVAArg(VAArgInst &I); + void visitInstruction(Instruction &I); + + //===------------------------------------------------------------------===// + // Implement Analyize interface + // + void print(raw_ostream &O, const Module*) const { + PrintPointsToGraph(); + } + }; +} + +char Andersens::ID = 0; +static RegisterPass +X("anders-aa", "Andersen's Interprocedural Alias Analysis (experimental)", + false, true); +static RegisterAnalysisGroup Y(X); + +// Initialize Timestamp Counter (static). +volatile llvm::sys::cas_flag Andersens::Node::Counter = 0; + +ModulePass *llvm::createAndersensPass() { return new Andersens(); } + +//===----------------------------------------------------------------------===// +// AliasAnalysis Interface Implementation +//===----------------------------------------------------------------------===// + +AliasAnalysis::AliasResult Andersens::alias(const Value *V1, unsigned V1Size, + const Value *V2, unsigned V2Size) { + Node *N1 = &GraphNodes[FindNode(getNode(const_cast(V1)))]; + Node *N2 = &GraphNodes[FindNode(getNode(const_cast(V2)))]; + + // Check to see if the two pointers are known to not alias. They don't alias + // if their points-to sets do not intersect. + if (!N1->intersectsIgnoring(N2, NullObject)) + return NoAlias; + + return AliasAnalysis::alias(V1, V1Size, V2, V2Size); +} + +AliasAnalysis::ModRefResult +Andersens::getModRefInfo(CallSite CS, Value *P, unsigned Size) { + // The only thing useful that we can contribute for mod/ref information is + // when calling external function calls: if we know that memory never escapes + // from the program, it cannot be modified by an external call. + // + // NOTE: This is not really safe, at least not when the entire program is not + // available. The deal is that the external function could call back into the + // program and modify stuff. We ignore this technical niggle for now. This + // is, after all, a "research quality" implementation of Andersen's analysis. + if (Function *F = CS.getCalledFunction()) + if (F->isDeclaration()) { + Node *N1 = &GraphNodes[FindNode(getNode(P))]; + + if (N1->PointsTo->empty()) + return NoModRef; +#if FULL_UNIVERSAL + if (!UniversalSet->PointsTo->test(FindNode(getNode(P)))) + return NoModRef; // Universal set does not contain P +#else + if (!N1->PointsTo->test(UniversalSet)) + return NoModRef; // P doesn't point to the universal set. +#endif + } + + return AliasAnalysis::getModRefInfo(CS, P, Size); +} + +AliasAnalysis::ModRefResult +Andersens::getModRefInfo(CallSite CS1, CallSite CS2) { + return AliasAnalysis::getModRefInfo(CS1,CS2); +} + +/// pointsToConstantMemory - If we can determine that this pointer only points +/// to constant memory, return true. In practice, this means that if the +/// pointer can only point to constant globals, functions, or the null pointer, +/// return true. +/// +bool Andersens::pointsToConstantMemory(const Value *P) { + Node *N = &GraphNodes[FindNode(getNode(const_cast(P)))]; + unsigned i; + + for (SparseBitVector<>::iterator bi = N->PointsTo->begin(); + bi != N->PointsTo->end(); + ++bi) { + i = *bi; + Node *Pointee = &GraphNodes[i]; + if (Value *V = Pointee->getValue()) { + if (!isa(V) || (isa(V) && + !cast(V)->isConstant())) + return AliasAnalysis::pointsToConstantMemory(P); + } else { + if (i != NullObject) + return AliasAnalysis::pointsToConstantMemory(P); + } + } + + return true; +} + +//===----------------------------------------------------------------------===// +// Object Identification Phase +//===----------------------------------------------------------------------===// + +/// IdentifyObjects - This stage scans the program, adding an entry to the +/// GraphNodes list for each memory object in the program (global stack or +/// heap), and populates the ValueNodes and ObjectNodes maps for these objects. +/// +void Andersens::IdentifyObjects(Module &M) { + unsigned NumObjects = 0; + + // Object #0 is always the universal set: the object that we don't know + // anything about. + assert(NumObjects == UniversalSet && "Something changed!"); + ++NumObjects; + + // Object #1 always represents the null pointer. + assert(NumObjects == NullPtr && "Something changed!"); + ++NumObjects; + + // Object #2 always represents the null object (the object pointed to by null) + assert(NumObjects == NullObject && "Something changed!"); + ++NumObjects; + + // Add all the globals first. + for (Module::global_iterator I = M.global_begin(), E = M.global_end(); + I != E; ++I) { + ObjectNodes[I] = NumObjects++; + ValueNodes[I] = NumObjects++; + } + + // Add nodes for all of the functions and the instructions inside of them. + for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F) { + // The function itself is a memory object. + unsigned First = NumObjects; + ValueNodes[F] = NumObjects++; + if (isa(F->getFunctionType()->getReturnType())) + ReturnNodes[F] = NumObjects++; + if (F->getFunctionType()->isVarArg()) + VarargNodes[F] = NumObjects++; + + + // Add nodes for all of the incoming pointer arguments. + for (Function::arg_iterator I = F->arg_begin(), E = F->arg_end(); + I != E; ++I) + { + if (isa(I->getType())) + ValueNodes[I] = NumObjects++; + } + MaxK[First] = NumObjects - First; + + // Scan the function body, creating a memory object for each heap/stack + // allocation in the body of the function and a node to represent all + // pointer values defined by instructions and used as operands. + for (inst_iterator II = inst_begin(F), E = inst_end(F); II != E; ++II) { + // If this is an heap or stack allocation, create a node for the memory + // object. + if (isa(II->getType())) { + ValueNodes[&*II] = NumObjects++; + if (AllocaInst *AI = dyn_cast(&*II)) + ObjectNodes[AI] = NumObjects++; + else if (isMalloc(&*II)) + ObjectNodes[&*II] = NumObjects++; + } + + // Calls to inline asm need to be added as well because the callee isn't + // referenced anywhere else. + if (CallInst *CI = dyn_cast(&*II)) { + Value *Callee = CI->getCalledValue(); + if (isa(Callee)) + ValueNodes[Callee] = NumObjects++; + } + } + } + + // Now that we know how many objects to create, make them all now! + GraphNodes.resize(NumObjects); + NumNodes += NumObjects; +} + +//===----------------------------------------------------------------------===// +// Constraint Identification Phase +//===----------------------------------------------------------------------===// + +/// getNodeForConstantPointer - Return the node corresponding to the constant +/// pointer itself. +unsigned Andersens::getNodeForConstantPointer(Constant *C) { + assert(isa(C->getType()) && "Not a constant pointer!"); + + if (isa(C) || isa(C)) + return NullPtr; + else if (GlobalValue *GV = dyn_cast(C)) + return getNode(GV); + else if (ConstantExpr *CE = dyn_cast(C)) { + switch (CE->getOpcode()) { + case Instruction::GetElementPtr: + return getNodeForConstantPointer(CE->getOperand(0)); + case Instruction::IntToPtr: + return UniversalSet; + case Instruction::BitCast: + return getNodeForConstantPointer(CE->getOperand(0)); + default: + errs() << "Constant Expr not yet handled: " << *CE << "\n"; + llvm_unreachable(0); + } + } else { + llvm_unreachable("Unknown constant pointer!"); + } + return 0; +} + +/// getNodeForConstantPointerTarget - Return the node POINTED TO by the +/// specified constant pointer. +unsigned Andersens::getNodeForConstantPointerTarget(Constant *C) { + assert(isa(C->getType()) && "Not a constant pointer!"); + + if (isa(C)) + return NullObject; + else if (GlobalValue *GV = dyn_cast(C)) + return getObject(GV); + else if (ConstantExpr *CE = dyn_cast(C)) { + switch (CE->getOpcode()) { + case Instruction::GetElementPtr: + return getNodeForConstantPointerTarget(CE->getOperand(0)); + case Instruction::IntToPtr: + return UniversalSet; + case Instruction::BitCast: + return getNodeForConstantPointerTarget(CE->getOperand(0)); + default: + errs() << "Constant Expr not yet handled: " << *CE << "\n"; + llvm_unreachable(0); + } + } else { + llvm_unreachable("Unknown constant pointer!"); + } + return 0; +} + +/// AddGlobalInitializerConstraints - Add inclusion constraints for the memory +/// object N, which contains values indicated by C. +void Andersens::AddGlobalInitializerConstraints(unsigned NodeIndex, + Constant *C) { + if (C->getType()->isSingleValueType()) { + if (isa(C->getType())) + Constraints.push_back(Constraint(Constraint::Copy, NodeIndex, + getNodeForConstantPointer(C))); + } else if (C->isNullValue()) { + Constraints.push_back(Constraint(Constraint::Copy, NodeIndex, + NullObject)); + return; + } else if (!isa(C)) { + // If this is an array or struct, include constraints for each element. + assert(isa(C) || isa(C)); + for (unsigned i = 0, e = C->getNumOperands(); i != e; ++i) + AddGlobalInitializerConstraints(NodeIndex, + cast(C->getOperand(i))); + } +} + +/// AddConstraintsForNonInternalLinkage - If this function does not have +/// internal linkage, realize that we can't trust anything passed into or +/// returned by this function. +void Andersens::AddConstraintsForNonInternalLinkage(Function *F) { + for (Function::arg_iterator I = F->arg_begin(), E = F->arg_end(); I != E; ++I) + if (isa(I->getType())) + // If this is an argument of an externally accessible function, the + // incoming pointer might point to anything. + Constraints.push_back(Constraint(Constraint::Copy, getNode(I), + UniversalSet)); +} + +/// AddConstraintsForCall - If this is a call to a "known" function, add the +/// constraints and return true. If this is a call to an unknown function, +/// return false. +bool Andersens::AddConstraintsForExternalCall(CallSite CS, Function *F) { + assert(F->isDeclaration() && "Not an external function!"); + + // These functions don't induce any points-to constraints. + if (F->getName() == "atoi" || F->getName() == "atof" || + F->getName() == "atol" || F->getName() == "atoll" || + F->getName() == "remove" || F->getName() == "unlink" || + F->getName() == "rename" || F->getName() == "memcmp" || + F->getName() == "llvm.memset" || + F->getName() == "strcmp" || F->getName() == "strncmp" || + F->getName() == "execl" || F->getName() == "execlp" || + F->getName() == "execle" || F->getName() == "execv" || + F->getName() == "execvp" || F->getName() == "chmod" || + F->getName() == "puts" || F->getName() == "write" || + F->getName() == "open" || F->getName() == "create" || + F->getName() == "truncate" || F->getName() == "chdir" || + F->getName() == "mkdir" || F->getName() == "rmdir" || + F->getName() == "read" || F->getName() == "pipe" || + F->getName() == "wait" || F->getName() == "time" || + F->getName() == "stat" || F->getName() == "fstat" || + F->getName() == "lstat" || F->getName() == "strtod" || + F->getName() == "strtof" || F->getName() == "strtold" || + F->getName() == "fopen" || F->getName() == "fdopen" || + F->getName() == "freopen" || + F->getName() == "fflush" || F->getName() == "feof" || + F->getName() == "fileno" || F->getName() == "clearerr" || + F->getName() == "rewind" || F->getName() == "ftell" || + F->getName() == "ferror" || F->getName() == "fgetc" || + F->getName() == "fgetc" || F->getName() == "_IO_getc" || + F->getName() == "fwrite" || F->getName() == "fread" || + F->getName() == "fgets" || F->getName() == "ungetc" || + F->getName() == "fputc" || + F->getName() == "fputs" || F->getName() == "putc" || + F->getName() == "ftell" || F->getName() == "rewind" || + F->getName() == "_IO_putc" || F->getName() == "fseek" || + F->getName() == "fgetpos" || F->getName() == "fsetpos" || + F->getName() == "printf" || F->getName() == "fprintf" || + F->getName() == "sprintf" || F->getName() == "vprintf" || + F->getName() == "vfprintf" || F->getName() == "vsprintf" || + F->getName() == "scanf" || F->getName() == "fscanf" || + F->getName() == "sscanf" || F->getName() == "__assert_fail" || + F->getName() == "modf") + return true; + + + // These functions do induce points-to edges. + if (F->getName() == "llvm.memcpy" || + F->getName() == "llvm.memmove" || + F->getName() == "memmove") { + + const FunctionType *FTy = F->getFunctionType(); + if (FTy->getNumParams() > 1 && + isa(FTy->getParamType(0)) && + isa(FTy->getParamType(1))) { + + // *Dest = *Src, which requires an artificial graph node to represent the + // constraint. It is broken up into *Dest = temp, temp = *Src + unsigned FirstArg = getNode(CS.getArgument(0)); + unsigned SecondArg = getNode(CS.getArgument(1)); + unsigned TempArg = GraphNodes.size(); + GraphNodes.push_back(Node()); + Constraints.push_back(Constraint(Constraint::Store, + FirstArg, TempArg)); + Constraints.push_back(Constraint(Constraint::Load, + TempArg, SecondArg)); + // In addition, Dest = Src + Constraints.push_back(Constraint(Constraint::Copy, + FirstArg, SecondArg)); + return true; + } + } + + // Result = Arg0 + if (F->getName() == "realloc" || F->getName() == "strchr" || + F->getName() == "strrchr" || F->getName() == "strstr" || + F->getName() == "strtok") { + const FunctionType *FTy = F->getFunctionType(); + if (FTy->getNumParams() > 0 && + isa(FTy->getParamType(0))) { + Constraints.push_back(Constraint(Constraint::Copy, + getNode(CS.getInstruction()), + getNode(CS.getArgument(0)))); + return true; + } + } + + return false; +} + + + +/// AnalyzeUsesOfFunction - Look at all of the users of the specified function. +/// If this is used by anything complex (i.e., the address escapes), return +/// true. +bool Andersens::AnalyzeUsesOfFunction(Value *V) { + + if (!isa(V->getType())) return true; + + for (Value::use_iterator UI = V->use_begin(), E = V->use_end(); UI != E; ++UI) + if (isa(*UI)) { + return false; + } else if (StoreInst *SI = dyn_cast(*UI)) { + if (V == SI->getOperand(1)) { + return false; + } else if (SI->getOperand(1)) { + return true; // Storing the pointer + } + } else if (GetElementPtrInst *GEP = dyn_cast(*UI)) { + if (AnalyzeUsesOfFunction(GEP)) return true; + } else if (isFreeCall(*UI)) { + return false; + } else if (CallInst *CI = dyn_cast(*UI)) { + // Make sure that this is just the function being called, not that it is + // passing into the function. + for (unsigned i = 1, e = CI->getNumOperands(); i != e; ++i) + if (CI->getOperand(i) == V) return true; + } else if (InvokeInst *II = dyn_cast(*UI)) { + // Make sure that this is just the function being called, not that it is + // passing into the function. + for (unsigned i = 3, e = II->getNumOperands(); i != e; ++i) + if (II->getOperand(i) == V) return true; + } else if (ConstantExpr *CE = dyn_cast(*UI)) { + if (CE->getOpcode() == Instruction::GetElementPtr || + CE->getOpcode() == Instruction::BitCast) { + if (AnalyzeUsesOfFunction(CE)) + return true; + } else { + return true; + } + } else if (ICmpInst *ICI = dyn_cast(*UI)) { + if (!isa(ICI->getOperand(1))) + return true; // Allow comparison against null. + } else { + return true; + } + return false; +} + +/// CollectConstraints - This stage scans the program, adding a constraint to +/// the Constraints list for each instruction in the program that induces a +/// constraint, and setting up the initial points-to graph. +/// +void Andersens::CollectConstraints(Module &M) { + // First, the universal set points to itself. + Constraints.push_back(Constraint(Constraint::AddressOf, UniversalSet, + UniversalSet)); + Constraints.push_back(Constraint(Constraint::Store, UniversalSet, + UniversalSet)); + + // Next, the null pointer points to the null object. + Constraints.push_back(Constraint(Constraint::AddressOf, NullPtr, NullObject)); + + // Next, add any constraints on global variables and their initializers. + for (Module::global_iterator I = M.global_begin(), E = M.global_end(); + I != E; ++I) { + // Associate the address of the global object as pointing to the memory for + // the global: &G = + unsigned ObjectIndex = getObject(I); + Node *Object = &GraphNodes[ObjectIndex]; + Object->setValue(I); + Constraints.push_back(Constraint(Constraint::AddressOf, getNodeValue(*I), + ObjectIndex)); + + if (I->hasDefinitiveInitializer()) { + AddGlobalInitializerConstraints(ObjectIndex, I->getInitializer()); + } else { + // If it doesn't have an initializer (i.e. it's defined in another + // translation unit), it points to the universal set. + Constraints.push_back(Constraint(Constraint::Copy, ObjectIndex, + UniversalSet)); + } + } + + for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F) { + // Set up the return value node. + if (isa(F->getFunctionType()->getReturnType())) + GraphNodes[getReturnNode(F)].setValue(F); + if (F->getFunctionType()->isVarArg()) + GraphNodes[getVarargNode(F)].setValue(F); + + // Set up incoming argument nodes. + for (Function::arg_iterator I = F->arg_begin(), E = F->arg_end(); + I != E; ++I) + if (isa(I->getType())) + getNodeValue(*I); + + // At some point we should just add constraints for the escaping functions + // at solve time, but this slows down solving. For now, we simply mark + // address taken functions as escaping and treat them as external. + if (!F->hasLocalLinkage() || AnalyzeUsesOfFunction(F)) + AddConstraintsForNonInternalLinkage(F); + + if (!F->isDeclaration()) { + // Scan the function body, creating a memory object for each heap/stack + // allocation in the body of the function and a node to represent all + // pointer values defined by instructions and used as operands. + visit(F); + } else { + // External functions that return pointers return the universal set. + if (isa(F->getFunctionType()->getReturnType())) + Constraints.push_back(Constraint(Constraint::Copy, + getReturnNode(F), + UniversalSet)); + + // Any pointers that are passed into the function have the universal set + // stored into them. + for (Function::arg_iterator I = F->arg_begin(), E = F->arg_end(); + I != E; ++I) + if (isa(I->getType())) { + // Pointers passed into external functions could have anything stored + // through them. + Constraints.push_back(Constraint(Constraint::Store, getNode(I), + UniversalSet)); + // Memory objects passed into external function calls can have the + // universal set point to them. +#if FULL_UNIVERSAL + Constraints.push_back(Constraint(Constraint::Copy, + UniversalSet, + getNode(I))); +#else + Constraints.push_back(Constraint(Constraint::Copy, + getNode(I), + UniversalSet)); +#endif + } + + // If this is an external varargs function, it can also store pointers + // into any pointers passed through the varargs section. + if (F->getFunctionType()->isVarArg()) + Constraints.push_back(Constraint(Constraint::Store, getVarargNode(F), + UniversalSet)); + } + } + NumConstraints += Constraints.size(); +} + + +void Andersens::visitInstruction(Instruction &I) { +#ifdef NDEBUG + return; // This function is just a big assert. +#endif + if (isa(I)) + return; + // Most instructions don't have any effect on pointer values. + switch (I.getOpcode()) { + case Instruction::Br: + case Instruction::Switch: + case Instruction::Unwind: + case Instruction::Unreachable: + case Instruction::ICmp: + case Instruction::FCmp: + return; + default: + // Is this something we aren't handling yet? + errs() << "Unknown instruction: " << I; + llvm_unreachable(0); + } +} + +void Andersens::visitAllocaInst(AllocaInst &I) { + visitAlloc(I); +} + +void Andersens::visitAlloc(Instruction &I) { + unsigned ObjectIndex = getObject(&I); + GraphNodes[ObjectIndex].setValue(&I); + Constraints.push_back(Constraint(Constraint::AddressOf, getNodeValue(I), + ObjectIndex)); +} + +void Andersens::visitReturnInst(ReturnInst &RI) { + if (RI.getNumOperands() && isa(RI.getOperand(0)->getType())) + // return V --> + Constraints.push_back(Constraint(Constraint::Copy, + getReturnNode(RI.getParent()->getParent()), + getNode(RI.getOperand(0)))); +} + +void Andersens::visitLoadInst(LoadInst &LI) { + if (isa(LI.getType())) + // P1 = load P2 --> + Constraints.push_back(Constraint(Constraint::Load, getNodeValue(LI), + getNode(LI.getOperand(0)))); +} + +void Andersens::visitStoreInst(StoreInst &SI) { + if (isa(SI.getOperand(0)->getType())) + // store P1, P2 --> + Constraints.push_back(Constraint(Constraint::Store, + getNode(SI.getOperand(1)), + getNode(SI.getOperand(0)))); +} + +void Andersens::visitGetElementPtrInst(GetElementPtrInst &GEP) { + // P1 = getelementptr P2, ... --> + Constraints.push_back(Constraint(Constraint::Copy, getNodeValue(GEP), + getNode(GEP.getOperand(0)))); +} + +void Andersens::visitPHINode(PHINode &PN) { + if (isa(PN.getType())) { + unsigned PNN = getNodeValue(PN); + for (unsigned i = 0, e = PN.getNumIncomingValues(); i != e; ++i) + // P1 = phi P2, P3 --> , , ... + Constraints.push_back(Constraint(Constraint::Copy, PNN, + getNode(PN.getIncomingValue(i)))); + } +} + +void Andersens::visitCastInst(CastInst &CI) { + Value *Op = CI.getOperand(0); + if (isa(CI.getType())) { + if (isa(Op->getType())) { + // P1 = cast P2 --> + Constraints.push_back(Constraint(Constraint::Copy, getNodeValue(CI), + getNode(CI.getOperand(0)))); + } else { + // P1 = cast int --> +#if 0 + Constraints.push_back(Constraint(Constraint::Copy, getNodeValue(CI), + UniversalSet)); +#else + getNodeValue(CI); +#endif + } + } else if (isa(Op->getType())) { + // int = cast P1 --> +#if 0 + Constraints.push_back(Constraint(Constraint::Copy, + UniversalSet, + getNode(CI.getOperand(0)))); +#else + getNode(CI.getOperand(0)); +#endif + } +} + +void Andersens::visitSelectInst(SelectInst &SI) { + if (isa(SI.getType())) { + unsigned SIN = getNodeValue(SI); + // P1 = select C, P2, P3 ---> , + Constraints.push_back(Constraint(Constraint::Copy, SIN, + getNode(SI.getOperand(1)))); + Constraints.push_back(Constraint(Constraint::Copy, SIN, + getNode(SI.getOperand(2)))); + } +} + +void Andersens::visitVAArg(VAArgInst &I) { + llvm_unreachable("vaarg not handled yet!"); +} + +/// AddConstraintsForCall - Add constraints for a call with actual arguments +/// specified by CS to the function specified by F. Note that the types of +/// arguments might not match up in the case where this is an indirect call and +/// the function pointer has been casted. If this is the case, do something +/// reasonable. +void Andersens::AddConstraintsForCall(CallSite CS, Function *F) { + Value *CallValue = CS.getCalledValue(); + bool IsDeref = F == NULL; + + // If this is a call to an external function, try to handle it directly to get + // some taste of context sensitivity. + if (F && F->isDeclaration() && AddConstraintsForExternalCall(CS, F)) + return; + + if (isa(CS.getType())) { + unsigned CSN = getNode(CS.getInstruction()); + if (!F || isa(F->getFunctionType()->getReturnType())) { + if (IsDeref) + Constraints.push_back(Constraint(Constraint::Load, CSN, + getNode(CallValue), CallReturnPos)); + else + Constraints.push_back(Constraint(Constraint::Copy, CSN, + getNode(CallValue) + CallReturnPos)); + } else { + // If the function returns a non-pointer value, handle this just like we + // treat a nonpointer cast to pointer. + Constraints.push_back(Constraint(Constraint::Copy, CSN, + UniversalSet)); + } + } else if (F && isa(F->getFunctionType()->getReturnType())) { +#if FULL_UNIVERSAL + Constraints.push_back(Constraint(Constraint::Copy, + UniversalSet, + getNode(CallValue) + CallReturnPos)); +#else + Constraints.push_back(Constraint(Constraint::Copy, + getNode(CallValue) + CallReturnPos, + UniversalSet)); +#endif + + + } + + CallSite::arg_iterator ArgI = CS.arg_begin(), ArgE = CS.arg_end(); + bool external = !F || F->isDeclaration(); + if (F) { + // Direct Call + Function::arg_iterator AI = F->arg_begin(), AE = F->arg_end(); + for (; AI != AE && ArgI != ArgE; ++AI, ++ArgI) + { +#if !FULL_UNIVERSAL + if (external && isa((*ArgI)->getType())) + { + // Add constraint that ArgI can now point to anything due to + // escaping, as can everything it points to. The second portion of + // this should be taken care of by universal = *universal + Constraints.push_back(Constraint(Constraint::Copy, + getNode(*ArgI), + UniversalSet)); + } +#endif + if (isa(AI->getType())) { + if (isa((*ArgI)->getType())) { + // Copy the actual argument into the formal argument. + Constraints.push_back(Constraint(Constraint::Copy, getNode(AI), + getNode(*ArgI))); + } else { + Constraints.push_back(Constraint(Constraint::Copy, getNode(AI), + UniversalSet)); + } + } else if (isa((*ArgI)->getType())) { +#if FULL_UNIVERSAL + Constraints.push_back(Constraint(Constraint::Copy, + UniversalSet, + getNode(*ArgI))); +#else + Constraints.push_back(Constraint(Constraint::Copy, + getNode(*ArgI), + UniversalSet)); +#endif + } + } + } else { + //Indirect Call + unsigned ArgPos = CallFirstArgPos; + for (; ArgI != ArgE; ++ArgI) { + if (isa((*ArgI)->getType())) { + // Copy the actual argument into the formal argument. + Constraints.push_back(Constraint(Constraint::Store, + getNode(CallValue), + getNode(*ArgI), ArgPos++)); + } else { + Constraints.push_back(Constraint(Constraint::Store, + getNode (CallValue), + UniversalSet, ArgPos++)); + } + } + } + // Copy all pointers passed through the varargs section to the varargs node. + if (F && F->getFunctionType()->isVarArg()) + for (; ArgI != ArgE; ++ArgI) + if (isa((*ArgI)->getType())) + Constraints.push_back(Constraint(Constraint::Copy, getVarargNode(F), + getNode(*ArgI))); + // If more arguments are passed in than we track, just drop them on the floor. +} + +void Andersens::visitCallSite(CallSite CS) { + if (isa(CS.getType())) + getNodeValue(*CS.getInstruction()); + + if (Function *F = CS.getCalledFunction()) { + AddConstraintsForCall(CS, F); + } else { + AddConstraintsForCall(CS, NULL); + } +} + +//===----------------------------------------------------------------------===// +// Constraint Solving Phase +//===----------------------------------------------------------------------===// + +/// intersects - Return true if the points-to set of this node intersects +/// with the points-to set of the specified node. +bool Andersens::Node::intersects(Node *N) const { + return PointsTo->intersects(N->PointsTo); +} + +/// intersectsIgnoring - Return true if the points-to set of this node +/// intersects with the points-to set of the specified node on any nodes +/// except for the specified node to ignore. +bool Andersens::Node::intersectsIgnoring(Node *N, unsigned Ignoring) const { + // TODO: If we are only going to call this with the same value for Ignoring, + // we should move the special values out of the points-to bitmap. + bool WeHadIt = PointsTo->test(Ignoring); + bool NHadIt = N->PointsTo->test(Ignoring); + bool Result = false; + if (WeHadIt) + PointsTo->reset(Ignoring); + if (NHadIt) + N->PointsTo->reset(Ignoring); + Result = PointsTo->intersects(N->PointsTo); + if (WeHadIt) + PointsTo->set(Ignoring); + if (NHadIt) + N->PointsTo->set(Ignoring); + return Result; +} + + +/// Clump together address taken variables so that the points-to sets use up +/// less space and can be operated on faster. + +void Andersens::ClumpAddressTaken() { +#undef DEBUG_TYPE +#define DEBUG_TYPE "anders-aa-renumber" + std::vector Translate; + std::vector NewGraphNodes; + + Translate.resize(GraphNodes.size()); + unsigned NewPos = 0; + + for (unsigned i = 0; i < Constraints.size(); ++i) { + Constraint &C = Constraints[i]; + if (C.Type == Constraint::AddressOf) { + GraphNodes[C.Src].AddressTaken = true; + } + } + for (unsigned i = 0; i < NumberSpecialNodes; ++i) { + unsigned Pos = NewPos++; + Translate[i] = Pos; + NewGraphNodes.push_back(GraphNodes[i]); + DEBUG(errs() << "Renumbering node " << i << " to node " << Pos << "\n"); + } + + // I believe this ends up being faster than making two vectors and splicing + // them. + for (unsigned i = NumberSpecialNodes; i < GraphNodes.size(); ++i) { + if (GraphNodes[i].AddressTaken) { + unsigned Pos = NewPos++; + Translate[i] = Pos; + NewGraphNodes.push_back(GraphNodes[i]); + DEBUG(errs() << "Renumbering node " << i << " to node " << Pos << "\n"); + } + } + + for (unsigned i = NumberSpecialNodes; i < GraphNodes.size(); ++i) { + if (!GraphNodes[i].AddressTaken) { + unsigned Pos = NewPos++; + Translate[i] = Pos; + NewGraphNodes.push_back(GraphNodes[i]); + DEBUG(errs() << "Renumbering node " << i << " to node " << Pos << "\n"); + } + } + + for (DenseMap::iterator Iter = ValueNodes.begin(); + Iter != ValueNodes.end(); + ++Iter) + Iter->second = Translate[Iter->second]; + + for (DenseMap::iterator Iter = ObjectNodes.begin(); + Iter != ObjectNodes.end(); + ++Iter) + Iter->second = Translate[Iter->second]; + + for (DenseMap::iterator Iter = ReturnNodes.begin(); + Iter != ReturnNodes.end(); + ++Iter) + Iter->second = Translate[Iter->second]; + + for (DenseMap::iterator Iter = VarargNodes.begin(); + Iter != VarargNodes.end(); + ++Iter) + Iter->second = Translate[Iter->second]; + + for (unsigned i = 0; i < Constraints.size(); ++i) { + Constraint &C = Constraints[i]; + C.Src = Translate[C.Src]; + C.Dest = Translate[C.Dest]; + } + + GraphNodes.swap(NewGraphNodes); +#undef DEBUG_TYPE +#define DEBUG_TYPE "anders-aa" +} + +/// The technique used here is described in "Exploiting Pointer and Location +/// Equivalence to Optimize Pointer Analysis. In the 14th International Static +/// Analysis Symposium (SAS), August 2007." It is known as the "HVN" algorithm, +/// and is equivalent to value numbering the collapsed constraint graph without +/// evaluating unions. This is used as a pre-pass to HU in order to resolve +/// first order pointer dereferences and speed up/reduce memory usage of HU. +/// Running both is equivalent to HRU without the iteration +/// HVN in more detail: +/// Imagine the set of constraints was simply straight line code with no loops +/// (we eliminate cycles, so there are no loops), such as: +/// E = &D +/// E = &C +/// E = F +/// F = G +/// G = F +/// Applying value numbering to this code tells us: +/// G == F == E +/// +/// For HVN, this is as far as it goes. We assign new value numbers to every +/// "address node", and every "reference node". +/// To get the optimal result for this, we use a DFS + SCC (since all nodes in a +/// cycle must have the same value number since the = operation is really +/// inclusion, not overwrite), and value number nodes we receive points-to sets +/// before we value our own node. +/// The advantage of HU over HVN is that HU considers the inclusion property, so +/// that if you have +/// E = &D +/// E = &C +/// E = F +/// F = G +/// F = &D +/// G = F +/// HU will determine that G == F == E. HVN will not, because it cannot prove +/// that the points to information ends up being the same because they all +/// receive &D from E anyway. + +void Andersens::HVN() { + DEBUG(errs() << "Beginning HVN\n"); + // Build a predecessor graph. This is like our constraint graph with the + // edges going in the opposite direction, and there are edges for all the + // constraints, instead of just copy constraints. We also build implicit + // edges for constraints are implied but not explicit. I.E for the constraint + // a = &b, we add implicit edges *a = b. This helps us capture more cycles + for (unsigned i = 0, e = Constraints.size(); i != e; ++i) { + Constraint &C = Constraints[i]; + if (C.Type == Constraint::AddressOf) { + GraphNodes[C.Src].AddressTaken = true; + GraphNodes[C.Src].Direct = false; + + // Dest = &src edge + unsigned AdrNode = C.Src + FirstAdrNode; + if (!GraphNodes[C.Dest].PredEdges) + GraphNodes[C.Dest].PredEdges = new SparseBitVector<>; + GraphNodes[C.Dest].PredEdges->set(AdrNode); + + // *Dest = src edge + unsigned RefNode = C.Dest + FirstRefNode; + if (!GraphNodes[RefNode].ImplicitPredEdges) + GraphNodes[RefNode].ImplicitPredEdges = new SparseBitVector<>; + GraphNodes[RefNode].ImplicitPredEdges->set(C.Src); + } else if (C.Type == Constraint::Load) { + if (C.Offset == 0) { + // dest = *src edge + if (!GraphNodes[C.Dest].PredEdges) + GraphNodes[C.Dest].PredEdges = new SparseBitVector<>; + GraphNodes[C.Dest].PredEdges->set(C.Src + FirstRefNode); + } else { + GraphNodes[C.Dest].Direct = false; + } + } else if (C.Type == Constraint::Store) { + if (C.Offset == 0) { + // *dest = src edge + unsigned RefNode = C.Dest + FirstRefNode; + if (!GraphNodes[RefNode].PredEdges) + GraphNodes[RefNode].PredEdges = new SparseBitVector<>; + GraphNodes[RefNode].PredEdges->set(C.Src); + } + } else { + // Dest = Src edge and *Dest = *Src edge + if (!GraphNodes[C.Dest].PredEdges) + GraphNodes[C.Dest].PredEdges = new SparseBitVector<>; + GraphNodes[C.Dest].PredEdges->set(C.Src); + unsigned RefNode = C.Dest + FirstRefNode; + if (!GraphNodes[RefNode].ImplicitPredEdges) + GraphNodes[RefNode].ImplicitPredEdges = new SparseBitVector<>; + GraphNodes[RefNode].ImplicitPredEdges->set(C.Src + FirstRefNode); + } + } + PEClass = 1; + // Do SCC finding first to condense our predecessor graph + DFSNumber = 0; + Node2DFS.insert(Node2DFS.begin(), GraphNodes.size(), 0); + Node2Deleted.insert(Node2Deleted.begin(), GraphNodes.size(), false); + Node2Visited.insert(Node2Visited.begin(), GraphNodes.size(), false); + + for (unsigned i = 0; i < FirstRefNode; ++i) { + unsigned Node = VSSCCRep[i]; + if (!Node2Visited[Node]) + HVNValNum(Node); + } + for (BitVectorMap::iterator Iter = Set2PEClass.begin(); + Iter != Set2PEClass.end(); + ++Iter) + delete Iter->first; + Set2PEClass.clear(); + Node2DFS.clear(); + Node2Deleted.clear(); + Node2Visited.clear(); + DEBUG(errs() << "Finished HVN\n"); + +} + +/// This is the workhorse of HVN value numbering. We combine SCC finding at the +/// same time because it's easy. +void Andersens::HVNValNum(unsigned NodeIndex) { + unsigned MyDFS = DFSNumber++; + Node *N = &GraphNodes[NodeIndex]; + Node2Visited[NodeIndex] = true; + Node2DFS[NodeIndex] = MyDFS; + + // First process all our explicit edges + if (N->PredEdges) + for (SparseBitVector<>::iterator Iter = N->PredEdges->begin(); + Iter != N->PredEdges->end(); + ++Iter) { + unsigned j = VSSCCRep[*Iter]; + if (!Node2Deleted[j]) { + if (!Node2Visited[j]) + HVNValNum(j); + if (Node2DFS[NodeIndex] > Node2DFS[j]) + Node2DFS[NodeIndex] = Node2DFS[j]; + } + } + + // Now process all the implicit edges + if (N->ImplicitPredEdges) + for (SparseBitVector<>::iterator Iter = N->ImplicitPredEdges->begin(); + Iter != N->ImplicitPredEdges->end(); + ++Iter) { + unsigned j = VSSCCRep[*Iter]; + if (!Node2Deleted[j]) { + if (!Node2Visited[j]) + HVNValNum(j); + if (Node2DFS[NodeIndex] > Node2DFS[j]) + Node2DFS[NodeIndex] = Node2DFS[j]; + } + } + + // See if we found any cycles + if (MyDFS == Node2DFS[NodeIndex]) { + while (!SCCStack.empty() && Node2DFS[SCCStack.top()] >= MyDFS) { + unsigned CycleNodeIndex = SCCStack.top(); + Node *CycleNode = &GraphNodes[CycleNodeIndex]; + VSSCCRep[CycleNodeIndex] = NodeIndex; + // Unify the nodes + N->Direct &= CycleNode->Direct; + + if (CycleNode->PredEdges) { + if (!N->PredEdges) + N->PredEdges = new SparseBitVector<>; + *(N->PredEdges) |= CycleNode->PredEdges; + delete CycleNode->PredEdges; + CycleNode->PredEdges = NULL; + } + if (CycleNode->ImplicitPredEdges) { + if (!N->ImplicitPredEdges) + N->ImplicitPredEdges = new SparseBitVector<>; + *(N->ImplicitPredEdges) |= CycleNode->ImplicitPredEdges; + delete CycleNode->ImplicitPredEdges; + CycleNode->ImplicitPredEdges = NULL; + } + + SCCStack.pop(); + } + + Node2Deleted[NodeIndex] = true; + + if (!N->Direct) { + GraphNodes[NodeIndex].PointerEquivLabel = PEClass++; + return; + } + + // Collect labels of successor nodes + bool AllSame = true; + unsigned First = ~0; + SparseBitVector<> *Labels = new SparseBitVector<>; + bool Used = false; + + if (N->PredEdges) + for (SparseBitVector<>::iterator Iter = N->PredEdges->begin(); + Iter != N->PredEdges->end(); + ++Iter) { + unsigned j = VSSCCRep[*Iter]; + unsigned Label = GraphNodes[j].PointerEquivLabel; + // Ignore labels that are equal to us or non-pointers + if (j == NodeIndex || Label == 0) + continue; + if (First == (unsigned)~0) + First = Label; + else if (First != Label) + AllSame = false; + Labels->set(Label); + } + + // We either have a non-pointer, a copy of an existing node, or a new node. + // Assign the appropriate pointer equivalence label. + if (Labels->empty()) { + GraphNodes[NodeIndex].PointerEquivLabel = 0; + } else if (AllSame) { + GraphNodes[NodeIndex].PointerEquivLabel = First; + } else { + GraphNodes[NodeIndex].PointerEquivLabel = Set2PEClass[Labels]; + if (GraphNodes[NodeIndex].PointerEquivLabel == 0) { + unsigned EquivClass = PEClass++; + Set2PEClass[Labels] = EquivClass; + GraphNodes[NodeIndex].PointerEquivLabel = EquivClass; + Used = true; + } + } + if (!Used) + delete Labels; + } else { + SCCStack.push(NodeIndex); + } +} + +/// The technique used here is described in "Exploiting Pointer and Location +/// Equivalence to Optimize Pointer Analysis. In the 14th International Static +/// Analysis Symposium (SAS), August 2007." It is known as the "HU" algorithm, +/// and is equivalent to value numbering the collapsed constraint graph +/// including evaluating unions. +void Andersens::HU() { + DEBUG(errs() << "Beginning HU\n"); + // Build a predecessor graph. This is like our constraint graph with the + // edges going in the opposite direction, and there are edges for all the + // constraints, instead of just copy constraints. We also build implicit + // edges for constraints are implied but not explicit. I.E for the constraint + // a = &b, we add implicit edges *a = b. This helps us capture more cycles + for (unsigned i = 0, e = Constraints.size(); i != e; ++i) { + Constraint &C = Constraints[i]; + if (C.Type == Constraint::AddressOf) { + GraphNodes[C.Src].AddressTaken = true; + GraphNodes[C.Src].Direct = false; + + GraphNodes[C.Dest].PointsTo->set(C.Src); + // *Dest = src edge + unsigned RefNode = C.Dest + FirstRefNode; + if (!GraphNodes[RefNode].ImplicitPredEdges) + GraphNodes[RefNode].ImplicitPredEdges = new SparseBitVector<>; + GraphNodes[RefNode].ImplicitPredEdges->set(C.Src); + GraphNodes[C.Src].PointedToBy->set(C.Dest); + } else if (C.Type == Constraint::Load) { + if (C.Offset == 0) { + // dest = *src edge + if (!GraphNodes[C.Dest].PredEdges) + GraphNodes[C.Dest].PredEdges = new SparseBitVector<>; + GraphNodes[C.Dest].PredEdges->set(C.Src + FirstRefNode); + } else { + GraphNodes[C.Dest].Direct = false; + } + } else if (C.Type == Constraint::Store) { + if (C.Offset == 0) { + // *dest = src edge + unsigned RefNode = C.Dest + FirstRefNode; + if (!GraphNodes[RefNode].PredEdges) + GraphNodes[RefNode].PredEdges = new SparseBitVector<>; + GraphNodes[RefNode].PredEdges->set(C.Src); + } + } else { + // Dest = Src edge and *Dest = *Src edg + if (!GraphNodes[C.Dest].PredEdges) + GraphNodes[C.Dest].PredEdges = new SparseBitVector<>; + GraphNodes[C.Dest].PredEdges->set(C.Src); + unsigned RefNode = C.Dest + FirstRefNode; + if (!GraphNodes[RefNode].ImplicitPredEdges) + GraphNodes[RefNode].ImplicitPredEdges = new SparseBitVector<>; + GraphNodes[RefNode].ImplicitPredEdges->set(C.Src + FirstRefNode); + } + } + PEClass = 1; + // Do SCC finding first to condense our predecessor graph + DFSNumber = 0; + Node2DFS.insert(Node2DFS.begin(), GraphNodes.size(), 0); + Node2Deleted.insert(Node2Deleted.begin(), GraphNodes.size(), false); + Node2Visited.insert(Node2Visited.begin(), GraphNodes.size(), false); + + for (unsigned i = 0; i < FirstRefNode; ++i) { + if (FindNode(i) == i) { + unsigned Node = VSSCCRep[i]; + if (!Node2Visited[Node]) + Condense(Node); + } + } + + // Reset tables for actual labeling + Node2DFS.clear(); + Node2Visited.clear(); + Node2Deleted.clear(); + // Pre-grow our densemap so that we don't get really bad behavior + Set2PEClass.resize(GraphNodes.size()); + + // Visit the condensed graph and generate pointer equivalence labels. + Node2Visited.insert(Node2Visited.begin(), GraphNodes.size(), false); + for (unsigned i = 0; i < FirstRefNode; ++i) { + if (FindNode(i) == i) { + unsigned Node = VSSCCRep[i]; + if (!Node2Visited[Node]) + HUValNum(Node); + } + } + // PEClass nodes will be deleted by the deleting of N->PointsTo in our caller. + Set2PEClass.clear(); + DEBUG(errs() << "Finished HU\n"); +} + + +/// Implementation of standard Tarjan SCC algorithm as modified by Nuutilla. +void Andersens::Condense(unsigned NodeIndex) { + unsigned MyDFS = DFSNumber++; + Node *N = &GraphNodes[NodeIndex]; + Node2Visited[NodeIndex] = true; + Node2DFS[NodeIndex] = MyDFS; + + // First process all our explicit edges + if (N->PredEdges) + for (SparseBitVector<>::iterator Iter = N->PredEdges->begin(); + Iter != N->PredEdges->end(); + ++Iter) { + unsigned j = VSSCCRep[*Iter]; + if (!Node2Deleted[j]) { + if (!Node2Visited[j]) + Condense(j); + if (Node2DFS[NodeIndex] > Node2DFS[j]) + Node2DFS[NodeIndex] = Node2DFS[j]; + } + } + + // Now process all the implicit edges + if (N->ImplicitPredEdges) + for (SparseBitVector<>::iterator Iter = N->ImplicitPredEdges->begin(); + Iter != N->ImplicitPredEdges->end(); + ++Iter) { + unsigned j = VSSCCRep[*Iter]; + if (!Node2Deleted[j]) { + if (!Node2Visited[j]) + Condense(j); + if (Node2DFS[NodeIndex] > Node2DFS[j]) + Node2DFS[NodeIndex] = Node2DFS[j]; + } + } + + // See if we found any cycles + if (MyDFS == Node2DFS[NodeIndex]) { + while (!SCCStack.empty() && Node2DFS[SCCStack.top()] >= MyDFS) { + unsigned CycleNodeIndex = SCCStack.top(); + Node *CycleNode = &GraphNodes[CycleNodeIndex]; + VSSCCRep[CycleNodeIndex] = NodeIndex; + // Unify the nodes + N->Direct &= CycleNode->Direct; + + *(N->PointsTo) |= CycleNode->PointsTo; + delete CycleNode->PointsTo; + CycleNode->PointsTo = NULL; + if (CycleNode->PredEdges) { + if (!N->PredEdges) + N->PredEdges = new SparseBitVector<>; + *(N->PredEdges) |= CycleNode->PredEdges; + delete CycleNode->PredEdges; + CycleNode->PredEdges = NULL; + } + if (CycleNode->ImplicitPredEdges) { + if (!N->ImplicitPredEdges) + N->ImplicitPredEdges = new SparseBitVector<>; + *(N->ImplicitPredEdges) |= CycleNode->ImplicitPredEdges; + delete CycleNode->ImplicitPredEdges; + CycleNode->ImplicitPredEdges = NULL; + } + SCCStack.pop(); + } + + Node2Deleted[NodeIndex] = true; + + // Set up number of incoming edges for other nodes + if (N->PredEdges) + for (SparseBitVector<>::iterator Iter = N->PredEdges->begin(); + Iter != N->PredEdges->end(); + ++Iter) + ++GraphNodes[VSSCCRep[*Iter]].NumInEdges; + } else { + SCCStack.push(NodeIndex); + } +} + +void Andersens::HUValNum(unsigned NodeIndex) { + Node *N = &GraphNodes[NodeIndex]; + Node2Visited[NodeIndex] = true; + + // Eliminate dereferences of non-pointers for those non-pointers we have + // already identified. These are ref nodes whose non-ref node: + // 1. Has already been visited determined to point to nothing (and thus, a + // dereference of it must point to nothing) + // 2. Any direct node with no predecessor edges in our graph and with no + // points-to set (since it can't point to anything either, being that it + // receives no points-to sets and has none). + if (NodeIndex >= FirstRefNode) { + unsigned j = VSSCCRep[FindNode(NodeIndex - FirstRefNode)]; + if ((Node2Visited[j] && !GraphNodes[j].PointerEquivLabel) + || (GraphNodes[j].Direct && !GraphNodes[j].PredEdges + && GraphNodes[j].PointsTo->empty())){ + return; + } + } + // Process all our explicit edges + if (N->PredEdges) + for (SparseBitVector<>::iterator Iter = N->PredEdges->begin(); + Iter != N->PredEdges->end(); + ++Iter) { + unsigned j = VSSCCRep[*Iter]; + if (!Node2Visited[j]) + HUValNum(j); + + // If this edge turned out to be the same as us, or got no pointer + // equivalence label (and thus points to nothing) , just decrement our + // incoming edges and continue. + if (j == NodeIndex || GraphNodes[j].PointerEquivLabel == 0) { + --GraphNodes[j].NumInEdges; + continue; + } + + *(N->PointsTo) |= GraphNodes[j].PointsTo; + + // If we didn't end up storing this in the hash, and we're done with all + // the edges, we don't need the points-to set anymore. + --GraphNodes[j].NumInEdges; + if (!GraphNodes[j].NumInEdges && !GraphNodes[j].StoredInHash) { + delete GraphNodes[j].PointsTo; + GraphNodes[j].PointsTo = NULL; + } + } + // If this isn't a direct node, generate a fresh variable. + if (!N->Direct) { + N->PointsTo->set(FirstRefNode + NodeIndex); + } + + // See If we have something equivalent to us, if not, generate a new + // equivalence class. + if (N->PointsTo->empty()) { + delete N->PointsTo; + N->PointsTo = NULL; + } else { + if (N->Direct) { + N->PointerEquivLabel = Set2PEClass[N->PointsTo]; + if (N->PointerEquivLabel == 0) { + unsigned EquivClass = PEClass++; + N->StoredInHash = true; + Set2PEClass[N->PointsTo] = EquivClass; + N->PointerEquivLabel = EquivClass; + } + } else { + N->PointerEquivLabel = PEClass++; + } + } +} + +/// Rewrite our list of constraints so that pointer equivalent nodes are +/// replaced by their the pointer equivalence class representative. +void Andersens::RewriteConstraints() { + std::vector NewConstraints; + DenseSet Seen; + + PEClass2Node.clear(); + PENLEClass2Node.clear(); + + // We may have from 1 to Graphnodes + 1 equivalence classes. + PEClass2Node.insert(PEClass2Node.begin(), GraphNodes.size() + 1, -1); + PENLEClass2Node.insert(PENLEClass2Node.begin(), GraphNodes.size() + 1, -1); + + // Rewrite constraints, ignoring non-pointer constraints, uniting equivalent + // nodes, and rewriting constraints to use the representative nodes. + for (unsigned i = 0, e = Constraints.size(); i != e; ++i) { + Constraint &C = Constraints[i]; + unsigned RHSNode = FindNode(C.Src); + unsigned LHSNode = FindNode(C.Dest); + unsigned RHSLabel = GraphNodes[VSSCCRep[RHSNode]].PointerEquivLabel; + unsigned LHSLabel = GraphNodes[VSSCCRep[LHSNode]].PointerEquivLabel; + + // First we try to eliminate constraints for things we can prove don't point + // to anything. + if (LHSLabel == 0) { + DEBUG(PrintNode(&GraphNodes[LHSNode])); + DEBUG(errs() << " is a non-pointer, ignoring constraint.\n"); + continue; + } + if (RHSLabel == 0) { + DEBUG(PrintNode(&GraphNodes[RHSNode])); + DEBUG(errs() << " is a non-pointer, ignoring constraint.\n"); + continue; + } + // This constraint may be useless, and it may become useless as we translate + // it. + if (C.Src == C.Dest && C.Type == Constraint::Copy) + continue; + + C.Src = FindEquivalentNode(RHSNode, RHSLabel); + C.Dest = FindEquivalentNode(FindNode(LHSNode), LHSLabel); + if ((C.Src == C.Dest && C.Type == Constraint::Copy) + || Seen.count(C)) + continue; + + Seen.insert(C); + NewConstraints.push_back(C); + } + Constraints.swap(NewConstraints); + PEClass2Node.clear(); +} + +/// See if we have a node that is pointer equivalent to the one being asked +/// about, and if so, unite them and return the equivalent node. Otherwise, +/// return the original node. +unsigned Andersens::FindEquivalentNode(unsigned NodeIndex, + unsigned NodeLabel) { + if (!GraphNodes[NodeIndex].AddressTaken) { + if (PEClass2Node[NodeLabel] != -1) { + // We found an existing node with the same pointer label, so unify them. + // We specifically request that Union-By-Rank not be used so that + // PEClass2Node[NodeLabel] U= NodeIndex and not the other way around. + return UniteNodes(PEClass2Node[NodeLabel], NodeIndex, false); + } else { + PEClass2Node[NodeLabel] = NodeIndex; + PENLEClass2Node[NodeLabel] = NodeIndex; + } + } else if (PENLEClass2Node[NodeLabel] == -1) { + PENLEClass2Node[NodeLabel] = NodeIndex; + } + + return NodeIndex; +} + +void Andersens::PrintLabels() const { + for (unsigned i = 0; i < GraphNodes.size(); ++i) { + if (i < FirstRefNode) { + PrintNode(&GraphNodes[i]); + } else if (i < FirstAdrNode) { + DEBUG(errs() << "REF("); + PrintNode(&GraphNodes[i-FirstRefNode]); + DEBUG(errs() <<")"); + } else { + DEBUG(errs() << "ADR("); + PrintNode(&GraphNodes[i-FirstAdrNode]); + DEBUG(errs() <<")"); + } + + DEBUG(errs() << " has pointer label " << GraphNodes[i].PointerEquivLabel + << " and SCC rep " << VSSCCRep[i] + << " and is " << (GraphNodes[i].Direct ? "Direct" : "Not direct") + << "\n"); + } +} + +/// The technique used here is described in "The Ant and the +/// Grasshopper: Fast and Accurate Pointer Analysis for Millions of +/// Lines of Code. In Programming Language Design and Implementation +/// (PLDI), June 2007." It is known as the "HCD" (Hybrid Cycle +/// Detection) algorithm. It is called a hybrid because it performs an +/// offline analysis and uses its results during the solving (online) +/// phase. This is just the offline portion; the results of this +/// operation are stored in SDT and are later used in SolveContraints() +/// and UniteNodes(). +void Andersens::HCD() { + DEBUG(errs() << "Starting HCD.\n"); + HCDSCCRep.resize(GraphNodes.size()); + + for (unsigned i = 0; i < GraphNodes.size(); ++i) { + GraphNodes[i].Edges = new SparseBitVector<>; + HCDSCCRep[i] = i; + } + + for (unsigned i = 0, e = Constraints.size(); i != e; ++i) { + Constraint &C = Constraints[i]; + assert (C.Src < GraphNodes.size() && C.Dest < GraphNodes.size()); + if (C.Type == Constraint::AddressOf) { + continue; + } else if (C.Type == Constraint::Load) { + if( C.Offset == 0 ) + GraphNodes[C.Dest].Edges->set(C.Src + FirstRefNode); + } else if (C.Type == Constraint::Store) { + if( C.Offset == 0 ) + GraphNodes[C.Dest + FirstRefNode].Edges->set(C.Src); + } else { + GraphNodes[C.Dest].Edges->set(C.Src); + } + } + + Node2DFS.insert(Node2DFS.begin(), GraphNodes.size(), 0); + Node2Deleted.insert(Node2Deleted.begin(), GraphNodes.size(), false); + Node2Visited.insert(Node2Visited.begin(), GraphNodes.size(), false); + SDT.insert(SDT.begin(), GraphNodes.size() / 2, -1); + + DFSNumber = 0; + for (unsigned i = 0; i < GraphNodes.size(); ++i) { + unsigned Node = HCDSCCRep[i]; + if (!Node2Deleted[Node]) + Search(Node); + } + + for (unsigned i = 0; i < GraphNodes.size(); ++i) + if (GraphNodes[i].Edges != NULL) { + delete GraphNodes[i].Edges; + GraphNodes[i].Edges = NULL; + } + + while( !SCCStack.empty() ) + SCCStack.pop(); + + Node2DFS.clear(); + Node2Visited.clear(); + Node2Deleted.clear(); + HCDSCCRep.clear(); + DEBUG(errs() << "HCD complete.\n"); +} + +// Component of HCD: +// Use Nuutila's variant of Tarjan's algorithm to detect +// Strongly-Connected Components (SCCs). For non-trivial SCCs +// containing ref nodes, insert the appropriate information in SDT. +void Andersens::Search(unsigned Node) { + unsigned MyDFS = DFSNumber++; + + Node2Visited[Node] = true; + Node2DFS[Node] = MyDFS; + + for (SparseBitVector<>::iterator Iter = GraphNodes[Node].Edges->begin(), + End = GraphNodes[Node].Edges->end(); + Iter != End; + ++Iter) { + unsigned J = HCDSCCRep[*Iter]; + assert(GraphNodes[J].isRep() && "Debug check; must be representative"); + if (!Node2Deleted[J]) { + if (!Node2Visited[J]) + Search(J); + if (Node2DFS[Node] > Node2DFS[J]) + Node2DFS[Node] = Node2DFS[J]; + } + } + + if( MyDFS != Node2DFS[Node] ) { + SCCStack.push(Node); + return; + } + + // This node is the root of a SCC, so process it. + // + // If the SCC is "non-trivial" (not a singleton) and contains a reference + // node, we place this SCC into SDT. We unite the nodes in any case. + if (!SCCStack.empty() && Node2DFS[SCCStack.top()] >= MyDFS) { + SparseBitVector<> SCC; + + SCC.set(Node); + + bool Ref = (Node >= FirstRefNode); + + Node2Deleted[Node] = true; + + do { + unsigned P = SCCStack.top(); SCCStack.pop(); + Ref |= (P >= FirstRefNode); + SCC.set(P); + HCDSCCRep[P] = Node; + } while (!SCCStack.empty() && Node2DFS[SCCStack.top()] >= MyDFS); + + if (Ref) { + unsigned Rep = SCC.find_first(); + assert(Rep < FirstRefNode && "The SCC didn't have a non-Ref node!"); + + SparseBitVector<>::iterator i = SCC.begin(); + + // Skip over the non-ref nodes + while( *i < FirstRefNode ) + ++i; + + while( i != SCC.end() ) + SDT[ (*i++) - FirstRefNode ] = Rep; + } + } +} + + +/// Optimize the constraints by performing offline variable substitution and +/// other optimizations. +void Andersens::OptimizeConstraints() { + DEBUG(errs() << "Beginning constraint optimization\n"); + + SDTActive = false; + + // Function related nodes need to stay in the same relative position and can't + // be location equivalent. + for (std::map::iterator Iter = MaxK.begin(); + Iter != MaxK.end(); + ++Iter) { + for (unsigned i = Iter->first; + i != Iter->first + Iter->second; + ++i) { + GraphNodes[i].AddressTaken = true; + GraphNodes[i].Direct = false; + } + } + + ClumpAddressTaken(); + FirstRefNode = GraphNodes.size(); + FirstAdrNode = FirstRefNode + GraphNodes.size(); + GraphNodes.insert(GraphNodes.end(), 2 * GraphNodes.size(), + Node(false)); + VSSCCRep.resize(GraphNodes.size()); + for (unsigned i = 0; i < GraphNodes.size(); ++i) { + VSSCCRep[i] = i; + } + HVN(); + for (unsigned i = 0; i < GraphNodes.size(); ++i) { + Node *N = &GraphNodes[i]; + delete N->PredEdges; + N->PredEdges = NULL; + delete N->ImplicitPredEdges; + N->ImplicitPredEdges = NULL; + } +#undef DEBUG_TYPE +#define DEBUG_TYPE "anders-aa-labels" + DEBUG(PrintLabels()); +#undef DEBUG_TYPE +#define DEBUG_TYPE "anders-aa" + RewriteConstraints(); + // Delete the adr nodes. + GraphNodes.resize(FirstRefNode * 2); + + // Now perform HU + for (unsigned i = 0; i < GraphNodes.size(); ++i) { + Node *N = &GraphNodes[i]; + if (FindNode(i) == i) { + N->PointsTo = new SparseBitVector<>; + N->PointedToBy = new SparseBitVector<>; + // Reset our labels + } + VSSCCRep[i] = i; + N->PointerEquivLabel = 0; + } + HU(); +#undef DEBUG_TYPE +#define DEBUG_TYPE "anders-aa-labels" + DEBUG(PrintLabels()); +#undef DEBUG_TYPE +#define DEBUG_TYPE "anders-aa" + RewriteConstraints(); + for (unsigned i = 0; i < GraphNodes.size(); ++i) { + if (FindNode(i) == i) { + Node *N = &GraphNodes[i]; + delete N->PointsTo; + N->PointsTo = NULL; + delete N->PredEdges; + N->PredEdges = NULL; + delete N->ImplicitPredEdges; + N->ImplicitPredEdges = NULL; + delete N->PointedToBy; + N->PointedToBy = NULL; + } + } + + // perform Hybrid Cycle Detection (HCD) + HCD(); + SDTActive = true; + + // No longer any need for the upper half of GraphNodes (for ref nodes). + GraphNodes.erase(GraphNodes.begin() + FirstRefNode, GraphNodes.end()); + + // HCD complete. + + DEBUG(errs() << "Finished constraint optimization\n"); + FirstRefNode = 0; + FirstAdrNode = 0; +} + +/// Unite pointer but not location equivalent variables, now that the constraint +/// graph is built. +void Andersens::UnitePointerEquivalences() { + DEBUG(errs() << "Uniting remaining pointer equivalences\n"); + for (unsigned i = 0; i < GraphNodes.size(); ++i) { + if (GraphNodes[i].AddressTaken && GraphNodes[i].isRep()) { + unsigned Label = GraphNodes[i].PointerEquivLabel; + + if (Label && PENLEClass2Node[Label] != -1) + UniteNodes(i, PENLEClass2Node[Label]); + } + } + DEBUG(errs() << "Finished remaining pointer equivalences\n"); + PENLEClass2Node.clear(); +} + +/// Create the constraint graph used for solving points-to analysis. +/// +void Andersens::CreateConstraintGraph() { + for (unsigned i = 0, e = Constraints.size(); i != e; ++i) { + Constraint &C = Constraints[i]; + assert (C.Src < GraphNodes.size() && C.Dest < GraphNodes.size()); + if (C.Type == Constraint::AddressOf) + GraphNodes[C.Dest].PointsTo->set(C.Src); + else if (C.Type == Constraint::Load) + GraphNodes[C.Src].Constraints.push_back(C); + else if (C.Type == Constraint::Store) + GraphNodes[C.Dest].Constraints.push_back(C); + else if (C.Offset != 0) + GraphNodes[C.Src].Constraints.push_back(C); + else + GraphNodes[C.Src].Edges->set(C.Dest); + } +} + +// Perform DFS and cycle detection. +bool Andersens::QueryNode(unsigned Node) { + assert(GraphNodes[Node].isRep() && "Querying a non-rep node"); + unsigned OurDFS = ++DFSNumber; + SparseBitVector<> ToErase; + SparseBitVector<> NewEdges; + Tarjan2DFS[Node] = OurDFS; + + // Changed denotes a change from a recursive call that we will bubble up. + // Merged is set if we actually merge a node ourselves. + bool Changed = false, Merged = false; + + for (SparseBitVector<>::iterator bi = GraphNodes[Node].Edges->begin(); + bi != GraphNodes[Node].Edges->end(); + ++bi) { + unsigned RepNode = FindNode(*bi); + // If this edge points to a non-representative node but we are + // already planning to add an edge to its representative, we have no + // need for this edge anymore. + if (RepNode != *bi && NewEdges.test(RepNode)){ + ToErase.set(*bi); + continue; + } + + // Continue about our DFS. + if (!Tarjan2Deleted[RepNode]){ + if (Tarjan2DFS[RepNode] == 0) { + Changed |= QueryNode(RepNode); + // May have been changed by QueryNode + RepNode = FindNode(RepNode); + } + if (Tarjan2DFS[RepNode] < Tarjan2DFS[Node]) + Tarjan2DFS[Node] = Tarjan2DFS[RepNode]; + } + + // We may have just discovered that this node is part of a cycle, in + // which case we can also erase it. + if (RepNode != *bi) { + ToErase.set(*bi); + NewEdges.set(RepNode); + } + } + + GraphNodes[Node].Edges->intersectWithComplement(ToErase); + GraphNodes[Node].Edges |= NewEdges; + + // If this node is a root of a non-trivial SCC, place it on our + // worklist to be processed. + if (OurDFS == Tarjan2DFS[Node]) { + while (!SCCStack.empty() && Tarjan2DFS[SCCStack.top()] >= OurDFS) { + Node = UniteNodes(Node, SCCStack.top()); + + SCCStack.pop(); + Merged = true; + } + Tarjan2Deleted[Node] = true; + + if (Merged) + NextWL->insert(&GraphNodes[Node]); + } else { + SCCStack.push(Node); + } + + return(Changed | Merged); +} + +/// SolveConstraints - This stage iteratively processes the constraints list +/// propagating constraints (adding edges to the Nodes in the points-to graph) +/// until a fixed point is reached. +/// +/// We use a variant of the technique called "Lazy Cycle Detection", which is +/// described in "The Ant and the Grasshopper: Fast and Accurate Pointer +/// Analysis for Millions of Lines of Code. In Programming Language Design and +/// Implementation (PLDI), June 2007." +/// The paper describes performing cycle detection one node at a time, which can +/// be expensive if there are no cycles, but there are long chains of nodes that +/// it heuristically believes are cycles (because it will DFS from each node +/// without state from previous nodes). +/// Instead, we use the heuristic to build a worklist of nodes to check, then +/// cycle detect them all at the same time to do this more cheaply. This +/// catches cycles slightly later than the original technique did, but does it +/// make significantly cheaper. + +void Andersens::SolveConstraints() { + CurrWL = &w1; + NextWL = &w2; + + OptimizeConstraints(); +#undef DEBUG_TYPE +#define DEBUG_TYPE "anders-aa-constraints" + DEBUG(PrintConstraints()); +#undef DEBUG_TYPE +#define DEBUG_TYPE "anders-aa" + + for (unsigned i = 0; i < GraphNodes.size(); ++i) { + Node *N = &GraphNodes[i]; + N->PointsTo = new SparseBitVector<>; + N->OldPointsTo = new SparseBitVector<>; + N->Edges = new SparseBitVector<>; + } + CreateConstraintGraph(); + UnitePointerEquivalences(); + assert(SCCStack.empty() && "SCC Stack should be empty by now!"); + Node2DFS.clear(); + Node2Deleted.clear(); + Node2DFS.insert(Node2DFS.begin(), GraphNodes.size(), 0); + Node2Deleted.insert(Node2Deleted.begin(), GraphNodes.size(), false); + DFSNumber = 0; + DenseSet Seen; + DenseSet, PairKeyInfo> EdgesChecked; + + // Order graph and add initial nodes to work list. + for (unsigned i = 0; i < GraphNodes.size(); ++i) { + Node *INode = &GraphNodes[i]; + + // Add to work list if it's a representative and can contribute to the + // calculation right now. + if (INode->isRep() && !INode->PointsTo->empty() + && (!INode->Edges->empty() || !INode->Constraints.empty())) { + INode->Stamp(); + CurrWL->insert(INode); + } + } + std::queue TarjanWL; +#if !FULL_UNIVERSAL + // "Rep and special variables" - in order for HCD to maintain conservative + // results when !FULL_UNIVERSAL, we need to treat the special variables in + // the same way that the !FULL_UNIVERSAL tweak does throughout the rest of + // the analysis - it's ok to add edges from the special nodes, but never + // *to* the special nodes. + std::vector RSV; +#endif + while( !CurrWL->empty() ) { + DEBUG(errs() << "Starting iteration #" << ++NumIters << "\n"); + + Node* CurrNode; + unsigned CurrNodeIndex; + + // Actual cycle checking code. We cycle check all of the lazy cycle + // candidates from the last iteration in one go. + if (!TarjanWL.empty()) { + DFSNumber = 0; + + Tarjan2DFS.clear(); + Tarjan2Deleted.clear(); + while (!TarjanWL.empty()) { + unsigned int ToTarjan = TarjanWL.front(); + TarjanWL.pop(); + if (!Tarjan2Deleted[ToTarjan] + && GraphNodes[ToTarjan].isRep() + && Tarjan2DFS[ToTarjan] == 0) + QueryNode(ToTarjan); + } + } + + // Add to work list if it's a representative and can contribute to the + // calculation right now. + while( (CurrNode = CurrWL->pop()) != NULL ) { + CurrNodeIndex = CurrNode - &GraphNodes[0]; + CurrNode->Stamp(); + + + // Figure out the changed points to bits + SparseBitVector<> CurrPointsTo; + CurrPointsTo.intersectWithComplement(CurrNode->PointsTo, + CurrNode->OldPointsTo); + if (CurrPointsTo.empty()) + continue; + + *(CurrNode->OldPointsTo) |= CurrPointsTo; + + // Check the offline-computed equivalencies from HCD. + bool SCC = false; + unsigned Rep; + + if (SDT[CurrNodeIndex] >= 0) { + SCC = true; + Rep = FindNode(SDT[CurrNodeIndex]); + +#if !FULL_UNIVERSAL + RSV.clear(); +#endif + for (SparseBitVector<>::iterator bi = CurrPointsTo.begin(); + bi != CurrPointsTo.end(); ++bi) { + unsigned Node = FindNode(*bi); +#if !FULL_UNIVERSAL + if (Node < NumberSpecialNodes) { + RSV.push_back(Node); + continue; + } +#endif + Rep = UniteNodes(Rep,Node); + } +#if !FULL_UNIVERSAL + RSV.push_back(Rep); +#endif + + NextWL->insert(&GraphNodes[Rep]); + + if ( ! CurrNode->isRep() ) + continue; + } + + Seen.clear(); + + /* Now process the constraints for this node. */ + for (std::list::iterator li = CurrNode->Constraints.begin(); + li != CurrNode->Constraints.end(); ) { + li->Src = FindNode(li->Src); + li->Dest = FindNode(li->Dest); + + // Delete redundant constraints + if( Seen.count(*li) ) { + std::list::iterator lk = li; li++; + + CurrNode->Constraints.erase(lk); + ++NumErased; + continue; + } + Seen.insert(*li); + + // Src and Dest will be the vars we are going to process. + // This may look a bit ugly, but what it does is allow us to process + // both store and load constraints with the same code. + // Load constraints say that every member of our RHS solution has K + // added to it, and that variable gets an edge to LHS. We also union + // RHS+K's solution into the LHS solution. + // Store constraints say that every member of our LHS solution has K + // added to it, and that variable gets an edge from RHS. We also union + // RHS's solution into the LHS+K solution. + unsigned *Src; + unsigned *Dest; + unsigned K = li->Offset; + unsigned CurrMember; + if (li->Type == Constraint::Load) { + Src = &CurrMember; + Dest = &li->Dest; + } else if (li->Type == Constraint::Store) { + Src = &li->Src; + Dest = &CurrMember; + } else { + // TODO Handle offseted copy constraint + li++; + continue; + } + + // See if we can use Hybrid Cycle Detection (that is, check + // if it was a statically detected offline equivalence that + // involves pointers; if so, remove the redundant constraints). + if( SCC && K == 0 ) { +#if FULL_UNIVERSAL + CurrMember = Rep; + + if (GraphNodes[*Src].Edges->test_and_set(*Dest)) + if (GraphNodes[*Dest].PointsTo |= *(GraphNodes[*Src].PointsTo)) + NextWL->insert(&GraphNodes[*Dest]); +#else + for (unsigned i=0; i < RSV.size(); ++i) { + CurrMember = RSV[i]; + + if (*Dest < NumberSpecialNodes) + continue; + if (GraphNodes[*Src].Edges->test_and_set(*Dest)) + if (GraphNodes[*Dest].PointsTo |= *(GraphNodes[*Src].PointsTo)) + NextWL->insert(&GraphNodes[*Dest]); + } +#endif + // since all future elements of the points-to set will be + // equivalent to the current ones, the complex constraints + // become redundant. + // + std::list::iterator lk = li; li++; +#if !FULL_UNIVERSAL + // In this case, we can still erase the constraints when the + // elements of the points-to sets are referenced by *Dest, + // but not when they are referenced by *Src (i.e. for a Load + // constraint). This is because if another special variable is + // put into the points-to set later, we still need to add the + // new edge from that special variable. + if( lk->Type != Constraint::Load) +#endif + GraphNodes[CurrNodeIndex].Constraints.erase(lk); + } else { + const SparseBitVector<> &Solution = CurrPointsTo; + + for (SparseBitVector<>::iterator bi = Solution.begin(); + bi != Solution.end(); + ++bi) { + CurrMember = *bi; + + // Need to increment the member by K since that is where we are + // supposed to copy to/from. Note that in positive weight cycles, + // which occur in address taking of fields, K can go past + // MaxK[CurrMember] elements, even though that is all it could point + // to. + if (K > 0 && K > MaxK[CurrMember]) + continue; + else + CurrMember = FindNode(CurrMember + K); + + // Add an edge to the graph, so we can just do regular + // bitmap ior next time. It may also let us notice a cycle. +#if !FULL_UNIVERSAL + if (*Dest < NumberSpecialNodes) + continue; +#endif + if (GraphNodes[*Src].Edges->test_and_set(*Dest)) + if (GraphNodes[*Dest].PointsTo |= *(GraphNodes[*Src].PointsTo)) + NextWL->insert(&GraphNodes[*Dest]); + + } + li++; + } + } + SparseBitVector<> NewEdges; + SparseBitVector<> ToErase; + + // Now all we have left to do is propagate points-to info along the + // edges, erasing the redundant edges. + for (SparseBitVector<>::iterator bi = CurrNode->Edges->begin(); + bi != CurrNode->Edges->end(); + ++bi) { + + unsigned DestVar = *bi; + unsigned Rep = FindNode(DestVar); + + // If we ended up with this node as our destination, or we've already + // got an edge for the representative, delete the current edge. + if (Rep == CurrNodeIndex || + (Rep != DestVar && NewEdges.test(Rep))) { + ToErase.set(DestVar); + continue; + } + + std::pair edge(CurrNodeIndex,Rep); + + // This is where we do lazy cycle detection. + // If this is a cycle candidate (equal points-to sets and this + // particular edge has not been cycle-checked previously), add to the + // list to check for cycles on the next iteration. + if (!EdgesChecked.count(edge) && + *(GraphNodes[Rep].PointsTo) == *(CurrNode->PointsTo)) { + EdgesChecked.insert(edge); + TarjanWL.push(Rep); + } + // Union the points-to sets into the dest +#if !FULL_UNIVERSAL + if (Rep >= NumberSpecialNodes) +#endif + if (GraphNodes[Rep].PointsTo |= CurrPointsTo) { + NextWL->insert(&GraphNodes[Rep]); + } + // If this edge's destination was collapsed, rewrite the edge. + if (Rep != DestVar) { + ToErase.set(DestVar); + NewEdges.set(Rep); + } + } + CurrNode->Edges->intersectWithComplement(ToErase); + CurrNode->Edges |= NewEdges; + } + + // Switch to other work list. + WorkList* t = CurrWL; CurrWL = NextWL; NextWL = t; + } + + + Node2DFS.clear(); + Node2Deleted.clear(); + for (unsigned i = 0; i < GraphNodes.size(); ++i) { + Node *N = &GraphNodes[i]; + delete N->OldPointsTo; + delete N->Edges; + } + SDTActive = false; + SDT.clear(); +} + +//===----------------------------------------------------------------------===// +// Union-Find +//===----------------------------------------------------------------------===// + +// Unite nodes First and Second, returning the one which is now the +// representative node. First and Second are indexes into GraphNodes +unsigned Andersens::UniteNodes(unsigned First, unsigned Second, + bool UnionByRank) { + assert (First < GraphNodes.size() && Second < GraphNodes.size() && + "Attempting to merge nodes that don't exist"); + + Node *FirstNode = &GraphNodes[First]; + Node *SecondNode = &GraphNodes[Second]; + + assert (SecondNode->isRep() && FirstNode->isRep() && + "Trying to unite two non-representative nodes!"); + if (First == Second) + return First; + + if (UnionByRank) { + int RankFirst = (int) FirstNode ->NodeRep; + int RankSecond = (int) SecondNode->NodeRep; + + // Rank starts at -1 and gets decremented as it increases. + // Translation: higher rank, lower NodeRep value, which is always negative. + if (RankFirst > RankSecond) { + unsigned t = First; First = Second; Second = t; + Node* tp = FirstNode; FirstNode = SecondNode; SecondNode = tp; + } else if (RankFirst == RankSecond) { + FirstNode->NodeRep = (unsigned) (RankFirst - 1); + } + } + + SecondNode->NodeRep = First; +#if !FULL_UNIVERSAL + if (First >= NumberSpecialNodes) +#endif + if (FirstNode->PointsTo && SecondNode->PointsTo) + FirstNode->PointsTo |= *(SecondNode->PointsTo); + if (FirstNode->Edges && SecondNode->Edges) + FirstNode->Edges |= *(SecondNode->Edges); + if (!SecondNode->Constraints.empty()) + FirstNode->Constraints.splice(FirstNode->Constraints.begin(), + SecondNode->Constraints); + if (FirstNode->OldPointsTo) { + delete FirstNode->OldPointsTo; + FirstNode->OldPointsTo = new SparseBitVector<>; + } + + // Destroy interesting parts of the merged-from node. + delete SecondNode->OldPointsTo; + delete SecondNode->Edges; + delete SecondNode->PointsTo; + SecondNode->Edges = NULL; + SecondNode->PointsTo = NULL; + SecondNode->OldPointsTo = NULL; + + NumUnified++; + DEBUG(errs() << "Unified Node "); + DEBUG(PrintNode(FirstNode)); + DEBUG(errs() << " and Node "); + DEBUG(PrintNode(SecondNode)); + DEBUG(errs() << "\n"); + + if (SDTActive) + if (SDT[Second] >= 0) { + if (SDT[First] < 0) + SDT[First] = SDT[Second]; + else { + UniteNodes( FindNode(SDT[First]), FindNode(SDT[Second]) ); + First = FindNode(First); + } + } + + return First; +} + +// Find the index into GraphNodes of the node representing Node, performing +// path compression along the way +unsigned Andersens::FindNode(unsigned NodeIndex) { + assert (NodeIndex < GraphNodes.size() + && "Attempting to find a node that can't exist"); + Node *N = &GraphNodes[NodeIndex]; + if (N->isRep()) + return NodeIndex; + else + return (N->NodeRep = FindNode(N->NodeRep)); +} + +// Find the index into GraphNodes of the node representing Node, +// don't perform path compression along the way (for Print) +unsigned Andersens::FindNode(unsigned NodeIndex) const { + assert (NodeIndex < GraphNodes.size() + && "Attempting to find a node that can't exist"); + const Node *N = &GraphNodes[NodeIndex]; + if (N->isRep()) + return NodeIndex; + else + return FindNode(N->NodeRep); +} + +//===----------------------------------------------------------------------===// +// Debugging Output +//===----------------------------------------------------------------------===// + +void Andersens::PrintNode(const Node *N) const { + if (N == &GraphNodes[UniversalSet]) { + errs() << ""; + return; + } else if (N == &GraphNodes[NullPtr]) { + errs() << ""; + return; + } else if (N == &GraphNodes[NullObject]) { + errs() << ""; + return; + } + if (!N->getValue()) { + errs() << "artificial" << (intptr_t) N; + return; + } + + assert(N->getValue() != 0 && "Never set node label!"); + Value *V = N->getValue(); + if (Function *F = dyn_cast(V)) { + if (isa(F->getFunctionType()->getReturnType()) && + N == &GraphNodes[getReturnNode(F)]) { + errs() << F->getName() << ":retval"; + return; + } else if (F->getFunctionType()->isVarArg() && + N == &GraphNodes[getVarargNode(F)]) { + errs() << F->getName() << ":vararg"; + return; + } + } + + if (Instruction *I = dyn_cast(V)) + errs() << I->getParent()->getParent()->getName() << ":"; + else if (Argument *Arg = dyn_cast(V)) + errs() << Arg->getParent()->getName() << ":"; + + if (V->hasName()) + errs() << V->getName(); + else + errs() << "(unnamed)"; + + if (isa(V) || isa(V) || isMalloc(V)) + if (N == &GraphNodes[getObject(V)]) + errs() << ""; +} +void Andersens::PrintConstraint(const Constraint &C) const { + if (C.Type == Constraint::Store) { + errs() << "*"; + if (C.Offset != 0) + errs() << "("; + } + PrintNode(&GraphNodes[C.Dest]); + if (C.Type == Constraint::Store && C.Offset != 0) + errs() << " + " << C.Offset << ")"; + errs() << " = "; + if (C.Type == Constraint::Load) { + errs() << "*"; + if (C.Offset != 0) + errs() << "("; + } + else if (C.Type == Constraint::AddressOf) + errs() << "&"; + PrintNode(&GraphNodes[C.Src]); + if (C.Offset != 0 && C.Type != Constraint::Store) + errs() << " + " << C.Offset; + if (C.Type == Constraint::Load && C.Offset != 0) + errs() << ")"; + errs() << "\n"; +} + +void Andersens::PrintConstraints() const { + errs() << "Constraints:\n"; + + for (unsigned i = 0, e = Constraints.size(); i != e; ++i) + PrintConstraint(Constraints[i]); +} + +void Andersens::PrintPointsToGraph() const { + errs() << "Points-to graph:\n"; + for (unsigned i = 0, e = GraphNodes.size(); i != e; ++i) { + const Node *N = &GraphNodes[i]; + if (FindNode(i) != i) { + PrintNode(N); + errs() << "\t--> same as "; + PrintNode(&GraphNodes[FindNode(i)]); + errs() << "\n"; + } else { + errs() << "[" << (N->PointsTo->count()) << "] "; + PrintNode(N); + errs() << "\t--> "; + + bool first = true; + for (SparseBitVector<>::iterator bi = N->PointsTo->begin(); + bi != N->PointsTo->end(); + ++bi) { + if (!first) + errs() << ", "; + PrintNode(&GraphNodes[*bi]); + first = false; + } + errs() << "\n"; + } + } +} diff --git a/libclamav/c++/llvm/lib/Analysis/IPA/CMakeLists.txt b/libclamav/c++/llvm/lib/Analysis/IPA/CMakeLists.txt new file mode 100644 index 000000000..1ebb0bea3 --- /dev/null +++ b/libclamav/c++/llvm/lib/Analysis/IPA/CMakeLists.txt @@ -0,0 +1,7 @@ +add_llvm_library(LLVMipa + Andersens.cpp + CallGraph.cpp + CallGraphSCCPass.cpp + FindUsedTypes.cpp + GlobalsModRef.cpp + ) diff --git a/libclamav/c++/llvm/lib/Analysis/IPA/CallGraph.cpp b/libclamav/c++/llvm/lib/Analysis/IPA/CallGraph.cpp new file mode 100644 index 000000000..9cd8bb8c2 --- /dev/null +++ b/libclamav/c++/llvm/lib/Analysis/IPA/CallGraph.cpp @@ -0,0 +1,299 @@ +//===- CallGraph.cpp - Build a Module's call graph ------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the CallGraph class and provides the BasicCallGraph +// default implementation. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Analysis/CallGraph.h" +#include "llvm/Module.h" +#include "llvm/Instructions.h" +#include "llvm/IntrinsicInst.h" +#include "llvm/Support/CallSite.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +namespace { + +//===----------------------------------------------------------------------===// +// BasicCallGraph class definition +// +class BasicCallGraph : public CallGraph, public ModulePass { + // Root is root of the call graph, or the external node if a 'main' function + // couldn't be found. + // + CallGraphNode *Root; + + // ExternalCallingNode - This node has edges to all external functions and + // those internal functions that have their address taken. + CallGraphNode *ExternalCallingNode; + + // CallsExternalNode - This node has edges to it from all functions making + // indirect calls or calling an external function. + CallGraphNode *CallsExternalNode; + +public: + static char ID; // Class identification, replacement for typeinfo + BasicCallGraph() : ModulePass(&ID), Root(0), + ExternalCallingNode(0), CallsExternalNode(0) {} + + // runOnModule - Compute the call graph for the specified module. + virtual bool runOnModule(Module &M) { + CallGraph::initialize(M); + + ExternalCallingNode = getOrInsertFunction(0); + CallsExternalNode = new CallGraphNode(0); + Root = 0; + + // Add every function to the call graph. + for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) + addToCallGraph(I); + + // If we didn't find a main function, use the external call graph node + if (Root == 0) Root = ExternalCallingNode; + + return false; + } + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + } + + virtual void print(raw_ostream &OS, const Module *) const { + OS << "CallGraph Root is: "; + if (Function *F = getRoot()->getFunction()) + OS << F->getName() << "\n"; + else { + OS << "<>\n"; + } + + CallGraph::print(OS, 0); + } + + virtual void releaseMemory() { + destroy(); + } + + CallGraphNode* getExternalCallingNode() const { return ExternalCallingNode; } + CallGraphNode* getCallsExternalNode() const { return CallsExternalNode; } + + // getRoot - Return the root of the call graph, which is either main, or if + // main cannot be found, the external node. + // + CallGraphNode *getRoot() { return Root; } + const CallGraphNode *getRoot() const { return Root; } + +private: + //===--------------------------------------------------------------------- + // Implementation of CallGraph construction + // + + // addToCallGraph - Add a function to the call graph, and link the node to all + // of the functions that it calls. + // + void addToCallGraph(Function *F) { + CallGraphNode *Node = getOrInsertFunction(F); + + // If this function has external linkage, anything could call it. + if (!F->hasLocalLinkage()) { + ExternalCallingNode->addCalledFunction(CallSite(), Node); + + // Found the entry point? + if (F->getName() == "main") { + if (Root) // Found multiple external mains? Don't pick one. + Root = ExternalCallingNode; + else + Root = Node; // Found a main, keep track of it! + } + } + + // Loop over all of the users of the function, looking for non-call uses. + for (Value::use_iterator I = F->use_begin(), E = F->use_end(); I != E; ++I) + if ((!isa(I) && !isa(I)) + || !CallSite(cast(I)).isCallee(I)) { + // Not a call, or being used as a parameter rather than as the callee. + ExternalCallingNode->addCalledFunction(CallSite(), Node); + break; + } + + // If this function is not defined in this translation unit, it could call + // anything. + if (F->isDeclaration() && !F->isIntrinsic()) + Node->addCalledFunction(CallSite(), CallsExternalNode); + + // Look for calls by this function. + for (Function::iterator BB = F->begin(), BBE = F->end(); BB != BBE; ++BB) + for (BasicBlock::iterator II = BB->begin(), IE = BB->end(); + II != IE; ++II) { + CallSite CS = CallSite::get(II); + if (CS.getInstruction() && !isa(II)) { + const Function *Callee = CS.getCalledFunction(); + if (Callee) + Node->addCalledFunction(CS, getOrInsertFunction(Callee)); + else + Node->addCalledFunction(CS, CallsExternalNode); + } + } + } + + // + // destroy - Release memory for the call graph + virtual void destroy() { + /// CallsExternalNode is not in the function map, delete it explicitly. + delete CallsExternalNode; + CallsExternalNode = 0; + CallGraph::destroy(); + } +}; + +} //End anonymous namespace + +static RegisterAnalysisGroup X("Call Graph"); +static RegisterPass +Y("basiccg", "Basic CallGraph Construction", false, true); +static RegisterAnalysisGroup Z(Y); + +char CallGraph::ID = 0; +char BasicCallGraph::ID = 0; + +void CallGraph::initialize(Module &M) { + Mod = &M; +} + +void CallGraph::destroy() { + if (FunctionMap.empty()) return; + + for (FunctionMapTy::iterator I = FunctionMap.begin(), E = FunctionMap.end(); + I != E; ++I) + delete I->second; + FunctionMap.clear(); +} + +void CallGraph::print(raw_ostream &OS, Module*) const { + for (CallGraph::const_iterator I = begin(), E = end(); I != E; ++I) + I->second->print(OS); +} +void CallGraph::dump() const { + print(errs(), 0); +} + +//===----------------------------------------------------------------------===// +// Implementations of public modification methods +// + +// removeFunctionFromModule - Unlink the function from this module, returning +// it. Because this removes the function from the module, the call graph node +// is destroyed. This is only valid if the function does not call any other +// functions (ie, there are no edges in it's CGN). The easiest way to do this +// is to dropAllReferences before calling this. +// +Function *CallGraph::removeFunctionFromModule(CallGraphNode *CGN) { + assert(CGN->empty() && "Cannot remove function from call " + "graph if it references other functions!"); + Function *F = CGN->getFunction(); // Get the function for the call graph node + delete CGN; // Delete the call graph node for this func + FunctionMap.erase(F); // Remove the call graph node from the map + + Mod->getFunctionList().remove(F); + return F; +} + +// getOrInsertFunction - This method is identical to calling operator[], but +// it will insert a new CallGraphNode for the specified function if one does +// not already exist. +CallGraphNode *CallGraph::getOrInsertFunction(const Function *F) { + CallGraphNode *&CGN = FunctionMap[F]; + if (CGN) return CGN; + + assert((!F || F->getParent() == Mod) && "Function not in current module!"); + return CGN = new CallGraphNode(const_cast(F)); +} + +void CallGraphNode::print(raw_ostream &OS) const { + if (Function *F = getFunction()) + OS << "Call graph node for function: '" << F->getName() << "'"; + else + OS << "Call graph node <>"; + + OS << "<<0x" << this << ">> #uses=" << getNumReferences() << '\n'; + + for (const_iterator I = begin(), E = end(); I != E; ++I) + if (Function *FI = I->second->getFunction()) + OS << " Calls function '" << FI->getName() <<"'\n"; + else + OS << " Calls external node\n"; + OS << "\n"; +} + +void CallGraphNode::dump() const { print(errs()); } + +/// removeCallEdgeFor - This method removes the edge in the node for the +/// specified call site. Note that this method takes linear time, so it +/// should be used sparingly. +void CallGraphNode::removeCallEdgeFor(CallSite CS) { + for (CalledFunctionsVector::iterator I = CalledFunctions.begin(); ; ++I) { + assert(I != CalledFunctions.end() && "Cannot find callsite to remove!"); + if (I->first == CS.getInstruction()) { + I->second->DropRef(); + *I = CalledFunctions.back(); + CalledFunctions.pop_back(); + return; + } + } +} + + +// removeAnyCallEdgeTo - This method removes any call edges from this node to +// the specified callee function. This takes more time to execute than +// removeCallEdgeTo, so it should not be used unless necessary. +void CallGraphNode::removeAnyCallEdgeTo(CallGraphNode *Callee) { + for (unsigned i = 0, e = CalledFunctions.size(); i != e; ++i) + if (CalledFunctions[i].second == Callee) { + Callee->DropRef(); + CalledFunctions[i] = CalledFunctions.back(); + CalledFunctions.pop_back(); + --i; --e; + } +} + +/// removeOneAbstractEdgeTo - Remove one edge associated with a null callsite +/// from this node to the specified callee function. +void CallGraphNode::removeOneAbstractEdgeTo(CallGraphNode *Callee) { + for (CalledFunctionsVector::iterator I = CalledFunctions.begin(); ; ++I) { + assert(I != CalledFunctions.end() && "Cannot find callee to remove!"); + CallRecord &CR = *I; + if (CR.second == Callee && CR.first == 0) { + Callee->DropRef(); + *I = CalledFunctions.back(); + CalledFunctions.pop_back(); + return; + } + } +} + +/// replaceCallEdge - This method replaces the edge in the node for the +/// specified call site with a new one. Note that this method takes linear +/// time, so it should be used sparingly. +void CallGraphNode::replaceCallEdge(CallSite CS, + CallSite NewCS, CallGraphNode *NewNode){ + for (CalledFunctionsVector::iterator I = CalledFunctions.begin(); ; ++I) { + assert(I != CalledFunctions.end() && "Cannot find callsite to remove!"); + if (I->first == CS.getInstruction()) { + I->second->DropRef(); + I->first = NewCS.getInstruction(); + I->second = NewNode; + NewNode->AddRef(); + return; + } + } +} + +// Enuse that users of CallGraph.h also link with this file +DEFINING_FILE_FOR(CallGraph) diff --git a/libclamav/c++/llvm/lib/Analysis/IPA/CallGraphSCCPass.cpp b/libclamav/c++/llvm/lib/Analysis/IPA/CallGraphSCCPass.cpp new file mode 100644 index 000000000..a96a5c591 --- /dev/null +++ b/libclamav/c++/llvm/lib/Analysis/IPA/CallGraphSCCPass.cpp @@ -0,0 +1,434 @@ +//===- CallGraphSCCPass.cpp - Pass that operates BU on call graph ---------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the CallGraphSCCPass class, which is used for passes +// which are implemented as bottom-up traversals on the call graph. Because +// there may be cycles in the call graph, passes of this type operate on the +// call-graph in SCC order: that is, they process function bottom-up, except for +// recursive functions, which they process all at once. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "cgscc-passmgr" +#include "llvm/CallGraphSCCPass.h" +#include "llvm/Analysis/CallGraph.h" +#include "llvm/ADT/SCCIterator.h" +#include "llvm/PassManagers.h" +#include "llvm/Function.h" +#include "llvm/Support/Debug.h" +#include "llvm/IntrinsicInst.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +//===----------------------------------------------------------------------===// +// CGPassManager +// +/// CGPassManager manages FPPassManagers and CallGraphSCCPasses. + +namespace { + +class CGPassManager : public ModulePass, public PMDataManager { +public: + static char ID; + explicit CGPassManager(int Depth) + : ModulePass(&ID), PMDataManager(Depth) { } + + /// 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. + bool runOnModule(Module &M); + + bool doInitialization(CallGraph &CG); + bool doFinalization(CallGraph &CG); + + /// Pass Manager itself does not invalidate any analysis info. + void getAnalysisUsage(AnalysisUsage &Info) const { + // CGPassManager walks SCC and it needs CallGraph. + Info.addRequired(); + Info.setPreservesAll(); + } + + virtual const char *getPassName() const { + return "CallGraph Pass Manager"; + } + + // Print passes managed by this manager + void dumpPassStructure(unsigned Offset) { + errs().indent(Offset*2) << "Call Graph SCC Pass Manager\n"; + for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) { + Pass *P = getContainedPass(Index); + P->dumpPassStructure(Offset + 1); + dumpLastUses(P, Offset+1); + } + } + + Pass *getContainedPass(unsigned N) { + assert(N < PassVector.size() && "Pass number out of range!"); + return static_cast(PassVector[N]); + } + + virtual PassManagerType getPassManagerType() const { + return PMT_CallGraphPassManager; + } + +private: + bool RunPassOnSCC(Pass *P, std::vector &CurSCC, + CallGraph &CG, bool &CallGraphUpToDate); + void RefreshCallGraph(std::vector &CurSCC, CallGraph &CG, + bool IsCheckingMode); +}; + +} // end anonymous namespace. + +char CGPassManager::ID = 0; + +bool CGPassManager::RunPassOnSCC(Pass *P, std::vector &CurSCC, + CallGraph &CG, bool &CallGraphUpToDate) { + bool Changed = false; + if (CallGraphSCCPass *CGSP = dynamic_cast(P)) { + if (!CallGraphUpToDate) { + RefreshCallGraph(CurSCC, CG, false); + CallGraphUpToDate = true; + } + + Timer *T = StartPassTimer(CGSP); + Changed = CGSP->runOnSCC(CurSCC); + StopPassTimer(CGSP, T); + + // After the CGSCCPass is done, when assertions are enabled, use + // RefreshCallGraph to verify that the callgraph was correctly updated. +#ifndef NDEBUG + if (Changed) + RefreshCallGraph(CurSCC, CG, true); +#endif + + return Changed; + } + + FPPassManager *FPP = dynamic_cast(P); + assert(FPP && "Invalid CGPassManager member"); + + // Run pass P on all functions in the current SCC. + for (unsigned i = 0, e = CurSCC.size(); i != e; ++i) { + if (Function *F = CurSCC[i]->getFunction()) { + dumpPassInfo(P, EXECUTION_MSG, ON_FUNCTION_MSG, F->getName()); + Timer *T = StartPassTimer(FPP); + Changed |= FPP->runOnFunction(*F); + StopPassTimer(FPP, T); + } + } + + // The function pass(es) modified the IR, they may have clobbered the + // callgraph. + if (Changed && CallGraphUpToDate) { + DEBUG(errs() << "CGSCCPASSMGR: Pass Dirtied SCC: " + << P->getPassName() << '\n'); + CallGraphUpToDate = false; + } + return Changed; +} + + +/// RefreshCallGraph - Scan the functions in the specified CFG and resync the +/// callgraph with the call sites found in it. This is used after +/// FunctionPasses have potentially munged the callgraph, and can be used after +/// CallGraphSCC passes to verify that they correctly updated the callgraph. +/// +void CGPassManager::RefreshCallGraph(std::vector &CurSCC, + CallGraph &CG, bool CheckingMode) { + DenseMap CallSites; + + DEBUG(errs() << "CGSCCPASSMGR: Refreshing SCC with " << CurSCC.size() + << " nodes:\n"; + for (unsigned i = 0, e = CurSCC.size(); i != e; ++i) + CurSCC[i]->dump(); + ); + + bool MadeChange = false; + + // Scan all functions in the SCC. + for (unsigned sccidx = 0, e = CurSCC.size(); sccidx != e; ++sccidx) { + CallGraphNode *CGN = CurSCC[sccidx]; + Function *F = CGN->getFunction(); + if (F == 0 || F->isDeclaration()) continue; + + // Walk the function body looking for call sites. Sync up the call sites in + // CGN with those actually in the function. + + // Get the set of call sites currently in the function. + for (CallGraphNode::iterator I = CGN->begin(), E = CGN->end(); I != E; ) { + // If this call site is null, then the function pass deleted the call + // entirely and the WeakVH nulled it out. + if (I->first == 0 || + // If we've already seen this call site, then the FunctionPass RAUW'd + // one call with another, which resulted in two "uses" in the edge + // list of the same call. + CallSites.count(I->first) || + + // If the call edge is not from a call or invoke, then the function + // pass RAUW'd a call with another value. This can happen when + // constant folding happens of well known functions etc. + CallSite::get(I->first).getInstruction() == 0) { + assert(!CheckingMode && + "CallGraphSCCPass did not update the CallGraph correctly!"); + + // Just remove the edge from the set of callees, keep track of whether + // I points to the last element of the vector. + bool WasLast = I + 1 == E; + CGN->removeCallEdge(I); + + // If I pointed to the last element of the vector, we have to bail out: + // iterator checking rejects comparisons of the resultant pointer with + // end. + if (WasLast) + break; + E = CGN->end(); + continue; + } + + assert(!CallSites.count(I->first) && + "Call site occurs in node multiple times"); + CallSites.insert(std::make_pair(I->first, I->second)); + ++I; + } + + // Loop over all of the instructions in the function, getting the callsites. + for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) + for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ++I) { + CallSite CS = CallSite::get(I); + if (!CS.getInstruction() || isa(I)) continue; + + // If this call site already existed in the callgraph, just verify it + // matches up to expectations and remove it from CallSites. + DenseMap::iterator ExistingIt = + CallSites.find(CS.getInstruction()); + if (ExistingIt != CallSites.end()) { + CallGraphNode *ExistingNode = ExistingIt->second; + + // Remove from CallSites since we have now seen it. + CallSites.erase(ExistingIt); + + // Verify that the callee is right. + if (ExistingNode->getFunction() == CS.getCalledFunction()) + continue; + + // If we are in checking mode, we are not allowed to actually mutate + // the callgraph. If this is a case where we can infer that the + // callgraph is less precise than it could be (e.g. an indirect call + // site could be turned direct), don't reject it in checking mode, and + // don't tweak it to be more precise. + if (CheckingMode && CS.getCalledFunction() && + ExistingNode->getFunction() == 0) + continue; + + assert(!CheckingMode && + "CallGraphSCCPass did not update the CallGraph correctly!"); + + // If not, we either went from a direct call to indirect, indirect to + // direct, or direct to different direct. + CallGraphNode *CalleeNode; + if (Function *Callee = CS.getCalledFunction()) + CalleeNode = CG.getOrInsertFunction(Callee); + else + CalleeNode = CG.getCallsExternalNode(); + + // Update the edge target in CGN. + for (CallGraphNode::iterator I = CGN->begin(); ; ++I) { + assert(I != CGN->end() && "Didn't find call entry"); + if (I->first == CS.getInstruction()) { + I->second = CalleeNode; + break; + } + } + MadeChange = true; + continue; + } + + assert(!CheckingMode && + "CallGraphSCCPass did not update the CallGraph correctly!"); + + // If the call site didn't exist in the CGN yet, add it. We assume that + // newly introduced call sites won't be indirect. This could be fixed + // in the future. + CallGraphNode *CalleeNode; + if (Function *Callee = CS.getCalledFunction()) + CalleeNode = CG.getOrInsertFunction(Callee); + else + CalleeNode = CG.getCallsExternalNode(); + + CGN->addCalledFunction(CS, CalleeNode); + MadeChange = true; + } + + // After scanning this function, if we still have entries in callsites, then + // they are dangling pointers. WeakVH should save us for this, so abort if + // this happens. + assert(CallSites.empty() && "Dangling pointers found in call sites map"); + + // Periodically do an explicit clear to remove tombstones when processing + // large scc's. + if ((sccidx & 15) == 0) + CallSites.clear(); + } + + DEBUG(if (MadeChange) { + errs() << "CGSCCPASSMGR: Refreshed SCC is now:\n"; + for (unsigned i = 0, e = CurSCC.size(); i != e; ++i) + CurSCC[i]->dump(); + } else { + errs() << "CGSCCPASSMGR: SCC Refresh didn't change call graph.\n"; + } + ); +} + +/// 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. +bool CGPassManager::runOnModule(Module &M) { + CallGraph &CG = getAnalysis(); + bool Changed = doInitialization(CG); + + std::vector CurSCC; + + // Walk the callgraph in bottom-up SCC order. + for (scc_iterator CGI = scc_begin(&CG), E = scc_end(&CG); + CGI != E;) { + // Copy the current SCC and increment past it so that the pass can hack + // on the SCC if it wants to without invalidating our iterator. + CurSCC = *CGI; + ++CGI; + + + // CallGraphUpToDate - Keep track of whether the callgraph is known to be + // up-to-date or not. The CGSSC pass manager runs two types of passes: + // CallGraphSCC Passes and other random function passes. Because other + // random function passes are not CallGraph aware, they may clobber the + // call graph by introducing new calls or deleting other ones. This flag + // is set to false when we run a function pass so that we know to clean up + // the callgraph when we need to run a CGSCCPass again. + bool CallGraphUpToDate = true; + + // Run all passes on current SCC. + for (unsigned PassNo = 0, e = getNumContainedPasses(); + PassNo != e; ++PassNo) { + Pass *P = getContainedPass(PassNo); + + // If we're in -debug-pass=Executions mode, construct the SCC node list, + // otherwise avoid constructing this string as it is expensive. + if (isPassDebuggingExecutionsOrMore()) { + std::string Functions; +#ifndef NDEBUG + raw_string_ostream OS(Functions); + for (unsigned i = 0, e = CurSCC.size(); i != e; ++i) { + if (i) OS << ", "; + CurSCC[i]->print(OS); + } + OS.flush(); +#endif + dumpPassInfo(P, EXECUTION_MSG, ON_CG_MSG, Functions); + } + dumpRequiredSet(P); + + initializeAnalysisImpl(P); + + // Actually run this pass on the current SCC. + Changed |= RunPassOnSCC(P, CurSCC, CG, CallGraphUpToDate); + + if (Changed) + dumpPassInfo(P, MODIFICATION_MSG, ON_CG_MSG, ""); + dumpPreservedSet(P); + + verifyPreservedAnalysis(P); + removeNotPreservedAnalysis(P); + recordAvailableAnalysis(P); + removeDeadPasses(P, "", ON_CG_MSG); + } + + // If the callgraph was left out of date (because the last pass run was a + // functionpass), refresh it before we move on to the next SCC. + if (!CallGraphUpToDate) + RefreshCallGraph(CurSCC, CG, false); + } + Changed |= doFinalization(CG); + return Changed; +} + +/// Initialize CG +bool CGPassManager::doInitialization(CallGraph &CG) { + bool Changed = false; + for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) { + Pass *P = getContainedPass(Index); + if (CallGraphSCCPass *CGSP = dynamic_cast(P)) { + Changed |= CGSP->doInitialization(CG); + } else { + FPPassManager *FP = dynamic_cast(P); + assert (FP && "Invalid CGPassManager member"); + Changed |= FP->doInitialization(CG.getModule()); + } + } + return Changed; +} + +/// Finalize CG +bool CGPassManager::doFinalization(CallGraph &CG) { + bool Changed = false; + for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) { + Pass *P = getContainedPass(Index); + if (CallGraphSCCPass *CGSP = dynamic_cast(P)) { + Changed |= CGSP->doFinalization(CG); + } else { + FPPassManager *FP = dynamic_cast(P); + assert (FP && "Invalid CGPassManager member"); + Changed |= FP->doFinalization(CG.getModule()); + } + } + return Changed; +} + +/// Assign pass manager to manage this pass. +void CallGraphSCCPass::assignPassManager(PMStack &PMS, + PassManagerType PreferredType) { + // Find CGPassManager + while (!PMS.empty() && + PMS.top()->getPassManagerType() > PMT_CallGraphPassManager) + PMS.pop(); + + assert (!PMS.empty() && "Unable to handle Call Graph Pass"); + CGPassManager *CGP = dynamic_cast(PMS.top()); + + // Create new Call Graph SCC Pass Manager if it does not exist. + if (!CGP) { + + assert (!PMS.empty() && "Unable to create Call Graph Pass Manager"); + PMDataManager *PMD = PMS.top(); + + // [1] Create new Call Graph Pass Manager + CGP = new CGPassManager(PMD->getDepth() + 1); + + // [2] Set up new manager's top level manager + PMTopLevelManager *TPM = PMD->getTopLevelManager(); + TPM->addIndirectPassManager(CGP); + + // [3] Assign manager to manage this new manager. This may create + // and push new managers into PMS + Pass *P = dynamic_cast(CGP); + TPM->schedulePass(P); + + // [4] Push new manager into PMS + PMS.push(CGP); + } + + CGP->add(this); +} + +/// getAnalysisUsage - For this class, we declare that we require and preserve +/// the call graph. If the derived class implements this method, it should +/// always explicitly call the implementation here. +void CallGraphSCCPass::getAnalysisUsage(AnalysisUsage &AU) const { + AU.addRequired(); + AU.addPreserved(); +} diff --git a/libclamav/c++/llvm/lib/Analysis/IPA/FindUsedTypes.cpp b/libclamav/c++/llvm/lib/Analysis/IPA/FindUsedTypes.cpp new file mode 100644 index 000000000..c4fb0b9a4 --- /dev/null +++ b/libclamav/c++/llvm/lib/Analysis/IPA/FindUsedTypes.cpp @@ -0,0 +1,103 @@ +//===- FindUsedTypes.cpp - Find all Types used by a module ----------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This pass is used to seek out all of the types in use by the program. Note +// that this analysis explicitly does not include types only used by the symbol +// table. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Analysis/FindUsedTypes.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Module.h" +#include "llvm/Assembly/Writer.h" +#include "llvm/Support/InstIterator.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +char FindUsedTypes::ID = 0; +static RegisterPass +X("print-used-types", "Find Used Types", false, true); + +// IncorporateType - Incorporate one type and all of its subtypes into the +// collection of used types. +// +void FindUsedTypes::IncorporateType(const Type *Ty) { + // If ty doesn't already exist in the used types map, add it now, otherwise + // return. + if (!UsedTypes.insert(Ty).second) return; // Already contain Ty. + + // Make sure to add any types this type references now. + // + for (Type::subtype_iterator I = Ty->subtype_begin(), E = Ty->subtype_end(); + I != E; ++I) + IncorporateType(*I); +} + +void FindUsedTypes::IncorporateValue(const Value *V) { + IncorporateType(V->getType()); + + // If this is a constant, it could be using other types... + if (const Constant *C = dyn_cast(V)) { + if (!isa(C)) + for (User::const_op_iterator OI = C->op_begin(), OE = C->op_end(); + OI != OE; ++OI) + IncorporateValue(*OI); + } +} + + +// run - This incorporates all types used by the specified module +// +bool FindUsedTypes::runOnModule(Module &m) { + UsedTypes.clear(); // reset if run multiple times... + + // Loop over global variables, incorporating their types + for (Module::const_global_iterator I = m.global_begin(), E = m.global_end(); + I != E; ++I) { + IncorporateType(I->getType()); + if (I->hasInitializer()) + IncorporateValue(I->getInitializer()); + } + + for (Module::iterator MI = m.begin(), ME = m.end(); MI != ME; ++MI) { + IncorporateType(MI->getType()); + const Function &F = *MI; + + // Loop over all of the instructions in the function, adding their return + // type as well as the types of their operands. + // + for (const_inst_iterator II = inst_begin(F), IE = inst_end(F); + II != IE; ++II) { + const Instruction &I = *II; + + IncorporateType(I.getType()); // Incorporate the type of the instruction + for (User::const_op_iterator OI = I.op_begin(), OE = I.op_end(); + OI != OE; ++OI) + IncorporateValue(*OI); // Insert inst operand types as well + } + } + + return false; +} + +// 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 +// symbol table from the module. +// +void FindUsedTypes::print(raw_ostream &OS, const Module *M) const { + OS << "Types in use by this module:\n"; + for (std::set::const_iterator I = UsedTypes.begin(), + E = UsedTypes.end(); I != E; ++I) { + OS << " "; + WriteTypeSymbolic(OS, *I, M); + OS << '\n'; + } +} diff --git a/libclamav/c++/llvm/lib/Analysis/IPA/GlobalsModRef.cpp b/libclamav/c++/llvm/lib/Analysis/IPA/GlobalsModRef.cpp new file mode 100644 index 000000000..a979a99a4 --- /dev/null +++ b/libclamav/c++/llvm/lib/Analysis/IPA/GlobalsModRef.cpp @@ -0,0 +1,569 @@ +//===- GlobalsModRef.cpp - Simple Mod/Ref Analysis for Globals ------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This simple pass provides alias and mod/ref information for global values +// that do not have their address taken, and keeps track of whether functions +// read or write memory (are "pure"). For this simple (but very common) case, +// we can provide pretty accurate and useful information. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "globalsmodref-aa" +#include "llvm/Analysis/Passes.h" +#include "llvm/Module.h" +#include "llvm/Pass.h" +#include "llvm/Instructions.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/Analysis/CallGraph.h" +#include "llvm/Analysis/MemoryBuiltins.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/InstIterator.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/ADT/SCCIterator.h" +#include +using namespace llvm; + +STATISTIC(NumNonAddrTakenGlobalVars, + "Number of global vars without address taken"); +STATISTIC(NumNonAddrTakenFunctions,"Number of functions without address taken"); +STATISTIC(NumNoMemFunctions, "Number of functions that do not access memory"); +STATISTIC(NumReadMemFunctions, "Number of functions that only read memory"); +STATISTIC(NumIndirectGlobalVars, "Number of indirect global objects"); + +namespace { + /// FunctionRecord - One instance of this structure is stored for every + /// function in the program. Later, the entries for these functions are + /// removed if the function is found to call an external function (in which + /// case we know nothing about it. + struct FunctionRecord { + /// GlobalInfo - Maintain mod/ref info for all of the globals without + /// addresses taken that are read or written (transitively) by this + /// function. + std::map GlobalInfo; + + /// MayReadAnyGlobal - May read global variables, but it is not known which. + bool MayReadAnyGlobal; + + unsigned getInfoForGlobal(GlobalValue *GV) const { + unsigned Effect = MayReadAnyGlobal ? AliasAnalysis::Ref : 0; + std::map::const_iterator I = GlobalInfo.find(GV); + if (I != GlobalInfo.end()) + Effect |= I->second; + return Effect; + } + + /// FunctionEffect - Capture whether or not this function reads or writes to + /// ANY memory. If not, we can do a lot of aggressive analysis on it. + unsigned FunctionEffect; + + FunctionRecord() : MayReadAnyGlobal (false), FunctionEffect(0) {} + }; + + /// GlobalsModRef - The actual analysis pass. + class GlobalsModRef : public ModulePass, public AliasAnalysis { + /// NonAddressTakenGlobals - The globals that do not have their addresses + /// taken. + std::set NonAddressTakenGlobals; + + /// IndirectGlobals - The memory pointed to by this global is known to be + /// 'owned' by the global. + std::set IndirectGlobals; + + /// AllocsForIndirectGlobals - If an instruction allocates memory for an + /// indirect global, this map indicates which one. + std::map AllocsForIndirectGlobals; + + /// FunctionInfo - For each function, keep track of what globals are + /// modified or read. + std::map FunctionInfo; + + public: + static char ID; + GlobalsModRef() : ModulePass(&ID) {} + + bool runOnModule(Module &M) { + InitializeAliasAnalysis(this); // set up super class + AnalyzeGlobals(M); // find non-addr taken globals + AnalyzeCallGraph(getAnalysis(), M); // Propagate on CG + return false; + } + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AliasAnalysis::getAnalysisUsage(AU); + AU.addRequired(); + AU.setPreservesAll(); // Does not transform code + } + + //------------------------------------------------ + // Implement the AliasAnalysis API + // + AliasResult alias(const Value *V1, unsigned V1Size, + const Value *V2, unsigned V2Size); + ModRefResult getModRefInfo(CallSite CS, Value *P, unsigned Size); + ModRefResult getModRefInfo(CallSite CS1, CallSite CS2) { + return AliasAnalysis::getModRefInfo(CS1,CS2); + } + + /// getModRefBehavior - Return the behavior of the specified function if + /// called from the specified call site. The call site may be null in which + /// case the most generic behavior of this function should be returned. + ModRefBehavior getModRefBehavior(Function *F, + std::vector *Info) { + if (FunctionRecord *FR = getFunctionInfo(F)) { + if (FR->FunctionEffect == 0) + return DoesNotAccessMemory; + else if ((FR->FunctionEffect & Mod) == 0) + return OnlyReadsMemory; + } + return AliasAnalysis::getModRefBehavior(F, Info); + } + + /// getModRefBehavior - Return the behavior of the specified function if + /// called from the specified call site. The call site may be null in which + /// case the most generic behavior of this function should be returned. + ModRefBehavior getModRefBehavior(CallSite CS, + std::vector *Info) { + Function* F = CS.getCalledFunction(); + if (!F) return AliasAnalysis::getModRefBehavior(CS, Info); + if (FunctionRecord *FR = getFunctionInfo(F)) { + if (FR->FunctionEffect == 0) + return DoesNotAccessMemory; + else if ((FR->FunctionEffect & Mod) == 0) + return OnlyReadsMemory; + } + return AliasAnalysis::getModRefBehavior(CS, Info); + } + + virtual void deleteValue(Value *V); + virtual void copyValue(Value *From, Value *To); + + private: + /// getFunctionInfo - Return the function info for the function, or null if + /// we don't have anything useful to say about it. + FunctionRecord *getFunctionInfo(Function *F) { + std::map::iterator I = FunctionInfo.find(F); + if (I != FunctionInfo.end()) + return &I->second; + return 0; + } + + void AnalyzeGlobals(Module &M); + void AnalyzeCallGraph(CallGraph &CG, Module &M); + bool AnalyzeUsesOfPointer(Value *V, std::vector &Readers, + std::vector &Writers, + GlobalValue *OkayStoreDest = 0); + bool AnalyzeIndirectGlobalMemory(GlobalValue *GV); + }; +} + +char GlobalsModRef::ID = 0; +static RegisterPass +X("globalsmodref-aa", "Simple mod/ref analysis for globals", false, true); +static RegisterAnalysisGroup Y(X); + +Pass *llvm::createGlobalsModRefPass() { return new GlobalsModRef(); } + +/// AnalyzeGlobals - Scan through the users of all of the internal +/// GlobalValue's in the program. If none of them have their "address taken" +/// (really, their address passed to something nontrivial), record this fact, +/// and record the functions that they are used directly in. +void GlobalsModRef::AnalyzeGlobals(Module &M) { + std::vector Readers, Writers; + for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) + if (I->hasLocalLinkage()) { + if (!AnalyzeUsesOfPointer(I, Readers, Writers)) { + // Remember that we are tracking this global. + NonAddressTakenGlobals.insert(I); + ++NumNonAddrTakenFunctions; + } + Readers.clear(); Writers.clear(); + } + + for (Module::global_iterator I = M.global_begin(), E = M.global_end(); + I != E; ++I) + if (I->hasLocalLinkage()) { + if (!AnalyzeUsesOfPointer(I, Readers, Writers)) { + // Remember that we are tracking this global, and the mod/ref fns + NonAddressTakenGlobals.insert(I); + + for (unsigned i = 0, e = Readers.size(); i != e; ++i) + FunctionInfo[Readers[i]].GlobalInfo[I] |= Ref; + + if (!I->isConstant()) // No need to keep track of writers to constants + for (unsigned i = 0, e = Writers.size(); i != e; ++i) + FunctionInfo[Writers[i]].GlobalInfo[I] |= Mod; + ++NumNonAddrTakenGlobalVars; + + // If this global holds a pointer type, see if it is an indirect global. + if (isa(I->getType()->getElementType()) && + AnalyzeIndirectGlobalMemory(I)) + ++NumIndirectGlobalVars; + } + Readers.clear(); Writers.clear(); + } +} + +/// AnalyzeUsesOfPointer - Look at all of the users of the specified pointer. +/// If this is used by anything complex (i.e., the address escapes), return +/// true. Also, while we are at it, keep track of those functions that read and +/// write to the value. +/// +/// If OkayStoreDest is non-null, stores into this global are allowed. +bool GlobalsModRef::AnalyzeUsesOfPointer(Value *V, + std::vector &Readers, + std::vector &Writers, + GlobalValue *OkayStoreDest) { + if (!isa(V->getType())) return true; + + for (Value::use_iterator UI = V->use_begin(), E = V->use_end(); UI != E; ++UI) + if (LoadInst *LI = dyn_cast(*UI)) { + Readers.push_back(LI->getParent()->getParent()); + } else if (StoreInst *SI = dyn_cast(*UI)) { + if (V == SI->getOperand(1)) { + Writers.push_back(SI->getParent()->getParent()); + } else if (SI->getOperand(1) != OkayStoreDest) { + return true; // Storing the pointer + } + } else if (GetElementPtrInst *GEP = dyn_cast(*UI)) { + if (AnalyzeUsesOfPointer(GEP, Readers, Writers)) return true; + } else if (BitCastInst *BCI = dyn_cast(*UI)) { + if (AnalyzeUsesOfPointer(BCI, Readers, Writers, OkayStoreDest)) + return true; + } else if (isFreeCall(*UI)) { + Writers.push_back(cast(*UI)->getParent()->getParent()); + } else if (CallInst *CI = dyn_cast(*UI)) { + // Make sure that this is just the function being called, not that it is + // passing into the function. + for (unsigned i = 1, e = CI->getNumOperands(); i != e; ++i) + if (CI->getOperand(i) == V) return true; + } else if (InvokeInst *II = dyn_cast(*UI)) { + // Make sure that this is just the function being called, not that it is + // passing into the function. + for (unsigned i = 3, e = II->getNumOperands(); i != e; ++i) + if (II->getOperand(i) == V) return true; + } else if (ConstantExpr *CE = dyn_cast(*UI)) { + if (CE->getOpcode() == Instruction::GetElementPtr || + CE->getOpcode() == Instruction::BitCast) { + if (AnalyzeUsesOfPointer(CE, Readers, Writers)) + return true; + } else { + return true; + } + } else if (ICmpInst *ICI = dyn_cast(*UI)) { + if (!isa(ICI->getOperand(1))) + return true; // Allow comparison against null. + } else { + return true; + } + return false; +} + +/// AnalyzeIndirectGlobalMemory - We found an non-address-taken global variable +/// which holds a pointer type. See if the global always points to non-aliased +/// heap memory: that is, all initializers of the globals are allocations, and +/// those allocations have no use other than initialization of the global. +/// Further, all loads out of GV must directly use the memory, not store the +/// pointer somewhere. If this is true, we consider the memory pointed to by +/// GV to be owned by GV and can disambiguate other pointers from it. +bool GlobalsModRef::AnalyzeIndirectGlobalMemory(GlobalValue *GV) { + // Keep track of values related to the allocation of the memory, f.e. the + // value produced by the malloc call and any casts. + std::vector AllocRelatedValues; + + // Walk the user list of the global. If we find anything other than a direct + // load or store, bail out. + for (Value::use_iterator I = GV->use_begin(), E = GV->use_end(); I != E; ++I){ + if (LoadInst *LI = dyn_cast(*I)) { + // The pointer loaded from the global can only be used in simple ways: + // we allow addressing of it and loading storing to it. We do *not* allow + // storing the loaded pointer somewhere else or passing to a function. + std::vector ReadersWriters; + if (AnalyzeUsesOfPointer(LI, ReadersWriters, ReadersWriters)) + return false; // Loaded pointer escapes. + // TODO: Could try some IP mod/ref of the loaded pointer. + } else if (StoreInst *SI = dyn_cast(*I)) { + // Storing the global itself. + if (SI->getOperand(0) == GV) return false; + + // If storing the null pointer, ignore it. + if (isa(SI->getOperand(0))) + continue; + + // Check the value being stored. + Value *Ptr = SI->getOperand(0)->getUnderlyingObject(); + + if (isMalloc(Ptr)) { + // Okay, easy case. + } else if (CallInst *CI = dyn_cast(Ptr)) { + Function *F = CI->getCalledFunction(); + if (!F || !F->isDeclaration()) return false; // Too hard to analyze. + if (F->getName() != "calloc") return false; // Not calloc. + } else { + return false; // Too hard to analyze. + } + + // Analyze all uses of the allocation. If any of them are used in a + // non-simple way (e.g. stored to another global) bail out. + std::vector ReadersWriters; + if (AnalyzeUsesOfPointer(Ptr, ReadersWriters, ReadersWriters, GV)) + return false; // Loaded pointer escapes. + + // Remember that this allocation is related to the indirect global. + AllocRelatedValues.push_back(Ptr); + } else { + // Something complex, bail out. + return false; + } + } + + // Okay, this is an indirect global. Remember all of the allocations for + // this global in AllocsForIndirectGlobals. + while (!AllocRelatedValues.empty()) { + AllocsForIndirectGlobals[AllocRelatedValues.back()] = GV; + AllocRelatedValues.pop_back(); + } + IndirectGlobals.insert(GV); + return true; +} + +/// AnalyzeCallGraph - At this point, we know the functions where globals are +/// immediately stored to and read from. Propagate this information up the call +/// graph to all callers and compute the mod/ref info for all memory for each +/// function. +void GlobalsModRef::AnalyzeCallGraph(CallGraph &CG, Module &M) { + // We do a bottom-up SCC traversal of the call graph. In other words, we + // visit all callees before callers (leaf-first). + for (scc_iterator I = scc_begin(&CG), E = scc_end(&CG); I != E; + ++I) { + std::vector &SCC = *I; + assert(!SCC.empty() && "SCC with no functions?"); + + if (!SCC[0]->getFunction()) { + // Calls externally - can't say anything useful. Remove any existing + // function records (may have been created when scanning globals). + for (unsigned i = 0, e = SCC.size(); i != e; ++i) + FunctionInfo.erase(SCC[i]->getFunction()); + continue; + } + + FunctionRecord &FR = FunctionInfo[SCC[0]->getFunction()]; + + bool KnowNothing = false; + unsigned FunctionEffect = 0; + + // Collect the mod/ref properties due to called functions. We only compute + // one mod-ref set. + for (unsigned i = 0, e = SCC.size(); i != e && !KnowNothing; ++i) { + Function *F = SCC[i]->getFunction(); + if (!F) { + KnowNothing = true; + break; + } + + if (F->isDeclaration()) { + // Try to get mod/ref behaviour from function attributes. + if (F->doesNotAccessMemory()) { + // Can't do better than that! + } else if (F->onlyReadsMemory()) { + FunctionEffect |= Ref; + if (!F->isIntrinsic()) + // This function might call back into the module and read a global - + // consider every global as possibly being read by this function. + FR.MayReadAnyGlobal = true; + } else { + FunctionEffect |= ModRef; + // Can't say anything useful unless it's an intrinsic - they don't + // read or write global variables of the kind considered here. + KnowNothing = !F->isIntrinsic(); + } + continue; + } + + for (CallGraphNode::iterator CI = SCC[i]->begin(), E = SCC[i]->end(); + CI != E && !KnowNothing; ++CI) + if (Function *Callee = CI->second->getFunction()) { + if (FunctionRecord *CalleeFR = getFunctionInfo(Callee)) { + // Propagate function effect up. + FunctionEffect |= CalleeFR->FunctionEffect; + + // Incorporate callee's effects on globals into our info. + for (std::map::iterator GI = + CalleeFR->GlobalInfo.begin(), E = CalleeFR->GlobalInfo.end(); + GI != E; ++GI) + FR.GlobalInfo[GI->first] |= GI->second; + FR.MayReadAnyGlobal |= CalleeFR->MayReadAnyGlobal; + } else { + // Can't say anything about it. However, if it is inside our SCC, + // then nothing needs to be done. + CallGraphNode *CalleeNode = CG[Callee]; + if (std::find(SCC.begin(), SCC.end(), CalleeNode) == SCC.end()) + KnowNothing = true; + } + } else { + KnowNothing = true; + } + } + + // If we can't say anything useful about this SCC, remove all SCC functions + // from the FunctionInfo map. + if (KnowNothing) { + for (unsigned i = 0, e = SCC.size(); i != e; ++i) + FunctionInfo.erase(SCC[i]->getFunction()); + continue; + } + + // Scan the function bodies for explicit loads or stores. + for (unsigned i = 0, e = SCC.size(); i != e && FunctionEffect != ModRef;++i) + for (inst_iterator II = inst_begin(SCC[i]->getFunction()), + E = inst_end(SCC[i]->getFunction()); + II != E && FunctionEffect != ModRef; ++II) + if (isa(*II)) { + FunctionEffect |= Ref; + if (cast(*II).isVolatile()) + // Volatile loads may have side-effects, so mark them as writing + // memory (for example, a flag inside the processor). + FunctionEffect |= Mod; + } else if (isa(*II)) { + FunctionEffect |= Mod; + if (cast(*II).isVolatile()) + // Treat volatile stores as reading memory somewhere. + FunctionEffect |= Ref; + } else if (isMalloc(&cast(*II)) || + isFreeCall(&cast(*II))) { + FunctionEffect |= ModRef; + } + + if ((FunctionEffect & Mod) == 0) + ++NumReadMemFunctions; + if (FunctionEffect == 0) + ++NumNoMemFunctions; + FR.FunctionEffect = FunctionEffect; + + // Finally, now that we know the full effect on this SCC, clone the + // information to each function in the SCC. + for (unsigned i = 1, e = SCC.size(); i != e; ++i) + FunctionInfo[SCC[i]->getFunction()] = FR; + } +} + + + +/// alias - If one of the pointers is to a global that we are tracking, and the +/// other is some random pointer, we know there cannot be an alias, because the +/// address of the global isn't taken. +AliasAnalysis::AliasResult +GlobalsModRef::alias(const Value *V1, unsigned V1Size, + const Value *V2, unsigned V2Size) { + // Get the base object these pointers point to. + Value *UV1 = const_cast(V1->getUnderlyingObject()); + Value *UV2 = const_cast(V2->getUnderlyingObject()); + + // If either of the underlying values is a global, they may be non-addr-taken + // globals, which we can answer queries about. + GlobalValue *GV1 = dyn_cast(UV1); + GlobalValue *GV2 = dyn_cast(UV2); + if (GV1 || GV2) { + // If the global's address is taken, pretend we don't know it's a pointer to + // the global. + if (GV1 && !NonAddressTakenGlobals.count(GV1)) GV1 = 0; + if (GV2 && !NonAddressTakenGlobals.count(GV2)) GV2 = 0; + + // If the the two pointers are derived from two different non-addr-taken + // globals, or if one is and the other isn't, we know these can't alias. + if ((GV1 || GV2) && GV1 != GV2) + return NoAlias; + + // Otherwise if they are both derived from the same addr-taken global, we + // can't know the two accesses don't overlap. + } + + // These pointers may be based on the memory owned by an indirect global. If + // so, we may be able to handle this. First check to see if the base pointer + // is a direct load from an indirect global. + GV1 = GV2 = 0; + if (LoadInst *LI = dyn_cast(UV1)) + if (GlobalVariable *GV = dyn_cast(LI->getOperand(0))) + if (IndirectGlobals.count(GV)) + GV1 = GV; + if (LoadInst *LI = dyn_cast(UV2)) + if (GlobalVariable *GV = dyn_cast(LI->getOperand(0))) + if (IndirectGlobals.count(GV)) + GV2 = GV; + + // These pointers may also be from an allocation for the indirect global. If + // so, also handle them. + if (AllocsForIndirectGlobals.count(UV1)) + GV1 = AllocsForIndirectGlobals[UV1]; + if (AllocsForIndirectGlobals.count(UV2)) + GV2 = AllocsForIndirectGlobals[UV2]; + + // Now that we know whether the two pointers are related to indirect globals, + // use this to disambiguate the pointers. If either pointer is based on an + // indirect global and if they are not both based on the same indirect global, + // they cannot alias. + if ((GV1 || GV2) && GV1 != GV2) + return NoAlias; + + return AliasAnalysis::alias(V1, V1Size, V2, V2Size); +} + +AliasAnalysis::ModRefResult +GlobalsModRef::getModRefInfo(CallSite CS, Value *P, unsigned Size) { + unsigned Known = ModRef; + + // If we are asking for mod/ref info of a direct call with a pointer to a + // global we are tracking, return information if we have it. + if (GlobalValue *GV = dyn_cast(P->getUnderlyingObject())) + if (GV->hasLocalLinkage()) + if (Function *F = CS.getCalledFunction()) + if (NonAddressTakenGlobals.count(GV)) + if (FunctionRecord *FR = getFunctionInfo(F)) + Known = FR->getInfoForGlobal(GV); + + if (Known == NoModRef) + return NoModRef; // No need to query other mod/ref analyses + return ModRefResult(Known & AliasAnalysis::getModRefInfo(CS, P, Size)); +} + + +//===----------------------------------------------------------------------===// +// Methods to update the analysis as a result of the client transformation. +// +void GlobalsModRef::deleteValue(Value *V) { + if (GlobalValue *GV = dyn_cast(V)) { + if (NonAddressTakenGlobals.erase(GV)) { + // This global might be an indirect global. If so, remove it and remove + // any AllocRelatedValues for it. + if (IndirectGlobals.erase(GV)) { + // Remove any entries in AllocsForIndirectGlobals for this global. + for (std::map::iterator + I = AllocsForIndirectGlobals.begin(), + E = AllocsForIndirectGlobals.end(); I != E; ) { + if (I->second == GV) { + AllocsForIndirectGlobals.erase(I++); + } else { + ++I; + } + } + } + } + } + + // Otherwise, if this is an allocation related to an indirect global, remove + // it. + AllocsForIndirectGlobals.erase(V); + + AliasAnalysis::deleteValue(V); +} + +void GlobalsModRef::copyValue(Value *From, Value *To) { + AliasAnalysis::copyValue(From, To); +} diff --git a/libclamav/c++/llvm/lib/Analysis/IPA/Makefile b/libclamav/c++/llvm/lib/Analysis/IPA/Makefile new file mode 100644 index 000000000..adacb16ea --- /dev/null +++ b/libclamav/c++/llvm/lib/Analysis/IPA/Makefile @@ -0,0 +1,14 @@ +##===- lib/Analysis/IPA/Makefile ---------------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LEVEL = ../../.. +LIBRARYNAME = LLVMipa +BUILD_ARCHIVE = 1 +include $(LEVEL)/Makefile.common + diff --git a/libclamav/c++/llvm/lib/Analysis/IVUsers.cpp b/libclamav/c++/llvm/lib/Analysis/IVUsers.cpp new file mode 100644 index 000000000..37747b651 --- /dev/null +++ b/libclamav/c++/llvm/lib/Analysis/IVUsers.cpp @@ -0,0 +1,379 @@ +//===- IVUsers.cpp - Induction Variable Users -------------------*- 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 bookkeeping for "interesting" users of expressions +// computed from induction variables. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "iv-users" +#include "llvm/Analysis/IVUsers.h" +#include "llvm/Constants.h" +#include "llvm/Instructions.h" +#include "llvm/Type.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Analysis/Dominators.h" +#include "llvm/Analysis/LoopPass.h" +#include "llvm/Analysis/ScalarEvolutionExpressions.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" +#include +using namespace llvm; + +char IVUsers::ID = 0; +static RegisterPass +X("iv-users", "Induction Variable Users", false, true); + +Pass *llvm::createIVUsersPass() { + return new IVUsers(); +} + +/// containsAddRecFromDifferentLoop - Determine whether expression S involves a +/// subexpression that is an AddRec from a loop other than L. An outer loop +/// of L is OK, but not an inner loop nor a disjoint loop. +static bool containsAddRecFromDifferentLoop(const SCEV *S, Loop *L) { + // This is very common, put it first. + if (isa(S)) + return false; + if (const SCEVCommutativeExpr *AE = dyn_cast(S)) { + for (unsigned int i=0; i< AE->getNumOperands(); i++) + if (containsAddRecFromDifferentLoop(AE->getOperand(i), L)) + return true; + return false; + } + if (const SCEVAddRecExpr *AE = dyn_cast(S)) { + if (const Loop *newLoop = AE->getLoop()) { + if (newLoop == L) + return false; + // if newLoop is an outer loop of L, this is OK. + if (!LoopInfo::isNotAlreadyContainedIn(L, newLoop)) + return false; + } + return true; + } + if (const SCEVUDivExpr *DE = dyn_cast(S)) + return containsAddRecFromDifferentLoop(DE->getLHS(), L) || + containsAddRecFromDifferentLoop(DE->getRHS(), L); +#if 0 + // SCEVSDivExpr has been backed out temporarily, but will be back; we'll + // need this when it is. + if (const SCEVSDivExpr *DE = dyn_cast(S)) + return containsAddRecFromDifferentLoop(DE->getLHS(), L) || + containsAddRecFromDifferentLoop(DE->getRHS(), L); +#endif + if (const SCEVCastExpr *CE = dyn_cast(S)) + return containsAddRecFromDifferentLoop(CE->getOperand(), L); + return false; +} + +/// getSCEVStartAndStride - Compute the start and stride of this expression, +/// returning false if the expression is not a start/stride pair, or true if it +/// is. The stride must be a loop invariant expression, but the start may be +/// a mix of loop invariant and loop variant expressions. The start cannot, +/// however, contain an AddRec from a different loop, unless that loop is an +/// outer loop of the current loop. +static bool getSCEVStartAndStride(const SCEV *&SH, Loop *L, Loop *UseLoop, + const SCEV *&Start, const SCEV *&Stride, + ScalarEvolution *SE, DominatorTree *DT) { + const SCEV *TheAddRec = Start; // Initialize to zero. + + // If the outer level is an AddExpr, the operands are all start values except + // for a nested AddRecExpr. + if (const SCEVAddExpr *AE = dyn_cast(SH)) { + for (unsigned i = 0, e = AE->getNumOperands(); i != e; ++i) + if (const SCEVAddRecExpr *AddRec = + dyn_cast(AE->getOperand(i))) { + if (AddRec->getLoop() == L) + TheAddRec = SE->getAddExpr(AddRec, TheAddRec); + else + return false; // Nested IV of some sort? + } else { + Start = SE->getAddExpr(Start, AE->getOperand(i)); + } + } else if (isa(SH)) { + TheAddRec = SH; + } else { + return false; // not analyzable. + } + + const SCEVAddRecExpr *AddRec = dyn_cast(TheAddRec); + if (!AddRec || AddRec->getLoop() != L) return false; + + // Use getSCEVAtScope to attempt to simplify other loops out of + // the picture. + const SCEV *AddRecStart = AddRec->getStart(); + AddRecStart = SE->getSCEVAtScope(AddRecStart, UseLoop); + const SCEV *AddRecStride = AddRec->getStepRecurrence(*SE); + + // FIXME: If Start contains an SCEVAddRecExpr from a different loop, other + // than an outer loop of the current loop, reject it. LSR has no concept of + // operating on more than one loop at a time so don't confuse it with such + // expressions. + if (containsAddRecFromDifferentLoop(AddRecStart, L)) + return false; + + Start = SE->getAddExpr(Start, AddRecStart); + + // If stride is an instruction, make sure it properly dominates the header. + // Otherwise we could end up with a use before def situation. + if (!isa(AddRecStride)) { + BasicBlock *Header = L->getHeader(); + if (!AddRecStride->properlyDominates(Header, DT)) + return false; + + DEBUG(errs() << "[" << L->getHeader()->getName() + << "] Variable stride: " << *AddRec << "\n"); + } + + Stride = AddRecStride; + return true; +} + +/// IVUseShouldUsePostIncValue - We have discovered a "User" of an IV expression +/// and now we need to decide whether the user should use the preinc or post-inc +/// value. If this user should use the post-inc version of the IV, return true. +/// +/// Choosing wrong here can break dominance properties (if we choose to use the +/// post-inc value when we cannot) or it can end up adding extra live-ranges to +/// the loop, resulting in reg-reg copies (if we use the pre-inc value when we +/// should use the post-inc value). +static bool IVUseShouldUsePostIncValue(Instruction *User, Instruction *IV, + Loop *L, LoopInfo *LI, DominatorTree *DT, + Pass *P) { + // If the user is in the loop, use the preinc value. + if (L->contains(User->getParent())) return false; + + BasicBlock *LatchBlock = L->getLoopLatch(); + if (!LatchBlock) + return false; + + // Ok, the user is outside of the loop. If it is dominated by the latch + // block, use the post-inc value. + if (DT->dominates(LatchBlock, User->getParent())) + return true; + + // There is one case we have to be careful of: PHI nodes. These little guys + // can live in blocks that are not dominated by the latch block, but (since + // their uses occur in the predecessor block, not the block the PHI lives in) + // should still use the post-inc value. Check for this case now. + PHINode *PN = dyn_cast(User); + if (!PN) return false; // not a phi, not dominated by latch block. + + // Look at all of the uses of IV by the PHI node. If any use corresponds to + // a block that is not dominated by the latch block, give up and use the + // preincremented value. + unsigned NumUses = 0; + for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) + if (PN->getIncomingValue(i) == IV) { + ++NumUses; + if (!DT->dominates(LatchBlock, PN->getIncomingBlock(i))) + return false; + } + + // Okay, all uses of IV by PN are in predecessor blocks that really are + // dominated by the latch block. Use the post-incremented value. + return true; +} + +/// AddUsersIfInteresting - Inspect the specified instruction. If it is a +/// reducible SCEV, recursively add its users to the IVUsesByStride set and +/// return true. Otherwise, return false. +bool IVUsers::AddUsersIfInteresting(Instruction *I) { + if (!SE->isSCEVable(I->getType())) + return false; // Void and FP expressions cannot be reduced. + + // LSR is not APInt clean, do not touch integers bigger than 64-bits. + if (SE->getTypeSizeInBits(I->getType()) > 64) + return false; + + if (!Processed.insert(I)) + return true; // Instruction already handled. + + // Get the symbolic expression for this instruction. + const SCEV *ISE = SE->getSCEV(I); + if (isa(ISE)) return false; + + // Get the start and stride for this expression. + Loop *UseLoop = LI->getLoopFor(I->getParent()); + const SCEV *Start = SE->getIntegerSCEV(0, ISE->getType()); + const SCEV *Stride = Start; + + if (!getSCEVStartAndStride(ISE, L, UseLoop, Start, Stride, SE, DT)) + return false; // Non-reducible symbolic expression, bail out. + + // Keep things simple. Don't touch loop-variant strides. + if (!Stride->isLoopInvariant(L) && L->contains(I->getParent())) + return false; + + SmallPtrSet UniqueUsers; + for (Value::use_iterator UI = I->use_begin(), E = I->use_end(); + UI != E; ++UI) { + Instruction *User = cast(*UI); + if (!UniqueUsers.insert(User)) + continue; + + // Do not infinitely recurse on PHI nodes. + if (isa(User) && Processed.count(User)) + continue; + + // Descend recursively, but not into PHI nodes outside the current loop. + // It's important to see the entire expression outside the loop to get + // choices that depend on addressing mode use right, although we won't + // consider references ouside the loop in all cases. + // If User is already in Processed, we don't want to recurse into it again, + // but do want to record a second reference in the same instruction. + bool AddUserToIVUsers = false; + if (LI->getLoopFor(User->getParent()) != L) { + if (isa(User) || Processed.count(User) || + !AddUsersIfInteresting(User)) { + DEBUG(errs() << "FOUND USER in other loop: " << *User << '\n' + << " OF SCEV: " << *ISE << '\n'); + AddUserToIVUsers = true; + } + } else if (Processed.count(User) || + !AddUsersIfInteresting(User)) { + DEBUG(errs() << "FOUND USER: " << *User << '\n' + << " OF SCEV: " << *ISE << '\n'); + AddUserToIVUsers = true; + } + + if (AddUserToIVUsers) { + IVUsersOfOneStride *StrideUses = IVUsesByStride[Stride]; + if (!StrideUses) { // First occurrence of this stride? + StrideOrder.push_back(Stride); + StrideUses = new IVUsersOfOneStride(Stride); + IVUses.push_back(StrideUses); + IVUsesByStride[Stride] = StrideUses; + } + + // Okay, we found a user that we cannot reduce. Analyze the instruction + // and decide what to do with it. If we are a use inside of the loop, use + // the value before incrementation, otherwise use it after incrementation. + if (IVUseShouldUsePostIncValue(User, I, L, LI, DT, this)) { + // The value used will be incremented by the stride more than we are + // expecting, so subtract this off. + const SCEV *NewStart = SE->getMinusSCEV(Start, Stride); + StrideUses->addUser(NewStart, User, I); + StrideUses->Users.back().setIsUseOfPostIncrementedValue(true); + DEBUG(errs() << " USING POSTINC SCEV, START=" << *NewStart<< "\n"); + } else { + StrideUses->addUser(Start, User, I); + } + } + } + return true; +} + +void IVUsers::AddUser(const SCEV *Stride, const SCEV *Offset, + Instruction *User, Value *Operand) { + IVUsersOfOneStride *StrideUses = IVUsesByStride[Stride]; + if (!StrideUses) { // First occurrence of this stride? + StrideOrder.push_back(Stride); + StrideUses = new IVUsersOfOneStride(Stride); + IVUses.push_back(StrideUses); + IVUsesByStride[Stride] = StrideUses; + } + IVUsesByStride[Stride]->addUser(Offset, User, Operand); +} + +IVUsers::IVUsers() + : LoopPass(&ID) { +} + +void IVUsers::getAnalysisUsage(AnalysisUsage &AU) const { + AU.addRequired(); + AU.addRequired(); + AU.addRequired(); + AU.setPreservesAll(); +} + +bool IVUsers::runOnLoop(Loop *l, LPPassManager &LPM) { + + L = l; + LI = &getAnalysis(); + DT = &getAnalysis(); + SE = &getAnalysis(); + + // Find all uses of induction variables in this loop, and categorize + // them by stride. Start by finding all of the PHI nodes in the header for + // this loop. If they are induction variables, inspect their uses. + for (BasicBlock::iterator I = L->getHeader()->begin(); isa(I); ++I) + AddUsersIfInteresting(I); + + return false; +} + +/// getReplacementExpr - Return a SCEV expression which computes the +/// value of the OperandValToReplace of the given IVStrideUse. +const SCEV *IVUsers::getReplacementExpr(const IVStrideUse &U) const { + // Start with zero. + const SCEV *RetVal = SE->getIntegerSCEV(0, U.getParent()->Stride->getType()); + // Create the basic add recurrence. + RetVal = SE->getAddRecExpr(RetVal, U.getParent()->Stride, L); + // Add the offset in a separate step, because it may be loop-variant. + RetVal = SE->getAddExpr(RetVal, U.getOffset()); + // For uses of post-incremented values, add an extra stride to compute + // the actual replacement value. + if (U.isUseOfPostIncrementedValue()) + RetVal = SE->getAddExpr(RetVal, U.getParent()->Stride); + // Evaluate the expression out of the loop, if possible. + if (!L->contains(U.getUser()->getParent())) { + const SCEV *ExitVal = SE->getSCEVAtScope(RetVal, L->getParentLoop()); + if (ExitVal->isLoopInvariant(L)) + RetVal = ExitVal; + } + return RetVal; +} + +void IVUsers::print(raw_ostream &OS, const Module *M) const { + OS << "IV Users for loop "; + WriteAsOperand(OS, L->getHeader(), false); + if (SE->hasLoopInvariantBackedgeTakenCount(L)) { + OS << " with backedge-taken count " + << *SE->getBackedgeTakenCount(L); + } + OS << ":\n"; + + for (unsigned Stride = 0, e = StrideOrder.size(); Stride != e; ++Stride) { + std::map::const_iterator SI = + IVUsesByStride.find(StrideOrder[Stride]); + assert(SI != IVUsesByStride.end() && "Stride doesn't exist!"); + OS << " Stride " << *SI->first->getType() << " " << *SI->first << ":\n"; + + for (ilist::const_iterator UI = SI->second->Users.begin(), + E = SI->second->Users.end(); UI != E; ++UI) { + OS << " "; + WriteAsOperand(OS, UI->getOperandValToReplace(), false); + OS << " = "; + OS << *getReplacementExpr(*UI); + if (UI->isUseOfPostIncrementedValue()) + OS << " (post-inc)"; + OS << " in "; + UI->getUser()->print(OS); + OS << '\n'; + } + } +} + +void IVUsers::dump() const { + print(errs()); +} + +void IVUsers::releaseMemory() { + IVUsesByStride.clear(); + StrideOrder.clear(); + Processed.clear(); +} + +void IVStrideUse::deleted() { + // Remove this user from the list. + Parent->Users.erase(this); + // this now dangles! +} diff --git a/libclamav/c++/llvm/lib/Analysis/InlineCost.cpp b/libclamav/c++/llvm/lib/Analysis/InlineCost.cpp new file mode 100644 index 000000000..bd9377bf8 --- /dev/null +++ b/libclamav/c++/llvm/lib/Analysis/InlineCost.cpp @@ -0,0 +1,344 @@ +//===- InlineCost.cpp - Cost analysis for inliner -------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements inline cost analysis. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Analysis/InlineCost.h" +#include "llvm/Support/CallSite.h" +#include "llvm/CallingConv.h" +#include "llvm/IntrinsicInst.h" +#include "llvm/ADT/SmallPtrSet.h" +using namespace llvm; + +// CountCodeReductionForConstant - Figure out an approximation for how many +// instructions will be constant folded if the specified value is constant. +// +unsigned InlineCostAnalyzer::FunctionInfo:: + CountCodeReductionForConstant(Value *V) { + unsigned Reduction = 0; + for (Value::use_iterator UI = V->use_begin(), E = V->use_end(); UI != E; ++UI) + if (isa(*UI)) + Reduction += 40; // Eliminating a conditional branch is a big win + else if (SwitchInst *SI = dyn_cast(*UI)) + // Eliminating a switch is a big win, proportional to the number of edges + // deleted. + Reduction += (SI->getNumSuccessors()-1) * 40; + else if (isa(*UI)) + // Eliminating an indirect branch is a big win. + Reduction += 200; + else if (CallInst *CI = dyn_cast(*UI)) { + // Turning an indirect call into a direct call is a BIG win + Reduction += CI->getCalledValue() == V ? 500 : 0; + } else if (InvokeInst *II = dyn_cast(*UI)) { + // Turning an indirect call into a direct call is a BIG win + Reduction += II->getCalledValue() == V ? 500 : 0; + } else { + // Figure out if this instruction will be removed due to simple constant + // propagation. + Instruction &Inst = cast(**UI); + + // We can't constant propagate instructions which have effects or + // read memory. + // + // FIXME: It would be nice to capture the fact that a load from a + // pointer-to-constant-global is actually a *really* good thing to zap. + // Unfortunately, we don't know the pointer that may get propagated here, + // so we can't make this decision. + if (Inst.mayReadFromMemory() || Inst.mayHaveSideEffects() || + isa(Inst)) + continue; + + bool AllOperandsConstant = true; + for (unsigned i = 0, e = Inst.getNumOperands(); i != e; ++i) + if (!isa(Inst.getOperand(i)) && Inst.getOperand(i) != V) { + AllOperandsConstant = false; + break; + } + + if (AllOperandsConstant) { + // We will get to remove this instruction... + Reduction += 7; + + // And any other instructions that use it which become constants + // themselves. + Reduction += CountCodeReductionForConstant(&Inst); + } + } + + return Reduction; +} + +// CountCodeReductionForAlloca - Figure out an approximation of how much smaller +// the function will be if it is inlined into a context where an argument +// becomes an alloca. +// +unsigned InlineCostAnalyzer::FunctionInfo:: + CountCodeReductionForAlloca(Value *V) { + if (!isa(V->getType())) return 0; // Not a pointer + unsigned Reduction = 0; + for (Value::use_iterator UI = V->use_begin(), E = V->use_end(); UI != E;++UI){ + Instruction *I = cast(*UI); + if (isa(I) || isa(I)) + Reduction += 10; + else if (GetElementPtrInst *GEP = dyn_cast(I)) { + // If the GEP has variable indices, we won't be able to do much with it. + if (!GEP->hasAllConstantIndices()) + Reduction += CountCodeReductionForAlloca(GEP)+15; + } else { + // If there is some other strange instruction, we're not going to be able + // to do much if we inline this. + return 0; + } + } + + return Reduction; +} + +/// analyzeBasicBlock - Fill in the current structure with information gleaned +/// from the specified block. +void CodeMetrics::analyzeBasicBlock(const BasicBlock *BB) { + ++NumBlocks; + + for (BasicBlock::const_iterator II = BB->begin(), E = BB->end(); + II != E; ++II) { + if (isa(II)) continue; // PHI nodes don't count. + + // Special handling for calls. + if (isa(II) || isa(II)) { + if (isa(II)) + continue; // Debug intrinsics don't count as size. + + CallSite CS = CallSite::get(const_cast(&*II)); + + // If this function contains a call to setjmp or _setjmp, never inline + // it. This is a hack because we depend on the user marking their local + // variables as volatile if they are live across a setjmp call, and they + // probably won't do this in callers. + if (Function *F = CS.getCalledFunction()) + if (F->isDeclaration() && + (F->getName() == "setjmp" || F->getName() == "_setjmp")) + NeverInline = true; + + // Calls often compile into many machine instructions. Bump up their + // cost to reflect this. + if (!isa(II)) + NumInsts += InlineConstants::CallPenalty; + } + + if (const AllocaInst *AI = dyn_cast(II)) { + if (!AI->isStaticAlloca()) + this->usesDynamicAlloca = true; + } + + if (isa(II) || isa(II->getType())) + ++NumVectorInsts; + + // Noop casts, including ptr <-> int, don't count. + if (const CastInst *CI = dyn_cast(II)) { + if (CI->isLosslessCast() || isa(CI) || + isa(CI)) + continue; + } else if (const GetElementPtrInst *GEPI = dyn_cast(II)){ + // If a GEP has all constant indices, it will probably be folded with + // a load/store. + if (GEPI->hasAllConstantIndices()) + continue; + } + + ++NumInsts; + } + + if (isa(BB->getTerminator())) + ++NumRets; + + // We never want to inline functions that contain an indirectbr. This is + // incorrect because all the blockaddress's (in static global initializers + // for example) would be referring to the original function, and this indirect + // jump would jump from the inlined copy of the function into the original + // function which is extremely undefined behavior. + if (isa(BB->getTerminator())) + NeverInline = true; +} + +/// analyzeFunction - Fill in the current structure with information gleaned +/// from the specified function. +void CodeMetrics::analyzeFunction(Function *F) { + // Look at the size of the callee. + for (Function::const_iterator BB = F->begin(), E = F->end(); BB != E; ++BB) + analyzeBasicBlock(&*BB); +} + +/// analyzeFunction - Fill in the current structure with information gleaned +/// from the specified function. +void InlineCostAnalyzer::FunctionInfo::analyzeFunction(Function *F) { + Metrics.analyzeFunction(F); + + // A function with exactly one return has it removed during the inlining + // process (see InlineFunction), so don't count it. + // FIXME: This knowledge should really be encoded outside of FunctionInfo. + if (Metrics.NumRets==1) + --Metrics.NumInsts; + + // Check out all of the arguments to the function, figuring out how much + // code can be eliminated if one of the arguments is a constant. + for (Function::arg_iterator I = F->arg_begin(), E = F->arg_end(); I != E; ++I) + ArgumentWeights.push_back(ArgInfo(CountCodeReductionForConstant(I), + CountCodeReductionForAlloca(I))); +} + +// getInlineCost - The heuristic used to determine if we should inline the +// function call or not. +// +InlineCost InlineCostAnalyzer::getInlineCost(CallSite CS, + SmallPtrSet &NeverInline) { + Instruction *TheCall = CS.getInstruction(); + Function *Callee = CS.getCalledFunction(); + Function *Caller = TheCall->getParent()->getParent(); + + // Don't inline functions which can be redefined at link-time to mean + // something else. Don't inline functions marked noinline. + if (Callee->mayBeOverridden() || + Callee->hasFnAttr(Attribute::NoInline) || NeverInline.count(Callee)) + return llvm::InlineCost::getNever(); + + // InlineCost - This value measures how good of an inline candidate this call + // site is to inline. A lower inline cost make is more likely for the call to + // be inlined. This value may go negative. + // + int InlineCost = 0; + + // If there is only one call of the function, and it has internal linkage, + // make it almost guaranteed to be inlined. + // + if (Callee->hasLocalLinkage() && Callee->hasOneUse()) + InlineCost += InlineConstants::LastCallToStaticBonus; + + // If this function uses the coldcc calling convention, prefer not to inline + // it. + if (Callee->getCallingConv() == CallingConv::Cold) + InlineCost += InlineConstants::ColdccPenalty; + + // If the instruction after the call, or if the normal destination of the + // invoke is an unreachable instruction, the function is noreturn. As such, + // there is little point in inlining this. + if (InvokeInst *II = dyn_cast(TheCall)) { + if (isa(II->getNormalDest()->begin())) + InlineCost += InlineConstants::NoreturnPenalty; + } else if (isa(++BasicBlock::iterator(TheCall))) + InlineCost += InlineConstants::NoreturnPenalty; + + // Get information about the callee... + FunctionInfo &CalleeFI = CachedFunctionInfo[Callee]; + + // If we haven't calculated this information yet, do so now. + if (CalleeFI.Metrics.NumBlocks == 0) + CalleeFI.analyzeFunction(Callee); + + // If we should never inline this, return a huge cost. + if (CalleeFI.Metrics.NeverInline) + return InlineCost::getNever(); + + // FIXME: It would be nice to kill off CalleeFI.NeverInline. Then we + // could move this up and avoid computing the FunctionInfo for + // things we are going to just return always inline for. This + // requires handling setjmp somewhere else, however. + if (!Callee->isDeclaration() && Callee->hasFnAttr(Attribute::AlwaysInline)) + return InlineCost::getAlways(); + + if (CalleeFI.Metrics.usesDynamicAlloca) { + // Get infomation about the caller... + FunctionInfo &CallerFI = CachedFunctionInfo[Caller]; + + // If we haven't calculated this information yet, do so now. + if (CallerFI.Metrics.NumBlocks == 0) + CallerFI.analyzeFunction(Caller); + + // Don't inline a callee with dynamic alloca into a caller without them. + // Functions containing dynamic alloca's are inefficient in various ways; + // don't create more inefficiency. + if (!CallerFI.Metrics.usesDynamicAlloca) + return InlineCost::getNever(); + } + + // Add to the inline quality for properties that make the call valuable to + // inline. This includes factors that indicate that the result of inlining + // the function will be optimizable. Currently this just looks at arguments + // passed into the function. + // + unsigned ArgNo = 0; + for (CallSite::arg_iterator I = CS.arg_begin(), E = CS.arg_end(); + I != E; ++I, ++ArgNo) { + // Each argument passed in has a cost at both the caller and the callee + // sides. This favors functions that take many arguments over functions + // that take few arguments. + InlineCost -= 20; + + // If this is a function being passed in, it is very likely that we will be + // able to turn an indirect function call into a direct function call. + if (isa(I)) + InlineCost -= 100; + + // If an alloca is passed in, inlining this function is likely to allow + // significant future optimization possibilities (like scalar promotion, and + // scalarization), so encourage the inlining of the function. + // + else if (isa(I)) { + if (ArgNo < CalleeFI.ArgumentWeights.size()) + InlineCost -= CalleeFI.ArgumentWeights[ArgNo].AllocaWeight; + + // If this is a constant being passed into the function, use the argument + // weights calculated for the callee to determine how much will be folded + // away with this information. + } else if (isa(I)) { + if (ArgNo < CalleeFI.ArgumentWeights.size()) + InlineCost -= CalleeFI.ArgumentWeights[ArgNo].ConstantWeight; + } + } + + // Now that we have considered all of the factors that make the call site more + // likely to be inlined, look at factors that make us not want to inline it. + + // Don't inline into something too big, which would make it bigger. + // "size" here is the number of basic blocks, not instructions. + // + InlineCost += Caller->size()/15; + + // Look at the size of the callee. Each instruction counts as 5. + InlineCost += CalleeFI.Metrics.NumInsts*5; + + return llvm::InlineCost::get(InlineCost); +} + +// getInlineFudgeFactor - Return a > 1.0 factor if the inliner should use a +// higher threshold to determine if the function call should be inlined. +float InlineCostAnalyzer::getInlineFudgeFactor(CallSite CS) { + Function *Callee = CS.getCalledFunction(); + + // Get information about the callee... + FunctionInfo &CalleeFI = CachedFunctionInfo[Callee]; + + // If we haven't calculated this information yet, do so now. + if (CalleeFI.Metrics.NumBlocks == 0) + CalleeFI.analyzeFunction(Callee); + + float Factor = 1.0f; + // Single BB functions are often written to be inlined. + if (CalleeFI.Metrics.NumBlocks == 1) + Factor += 0.5f; + + // Be more aggressive if the function contains a good chunk (if it mades up + // at least 10% of the instructions) of vector instructions. + if (CalleeFI.Metrics.NumVectorInsts > CalleeFI.Metrics.NumInsts/2) + Factor += 2.0f; + else if (CalleeFI.Metrics.NumVectorInsts > CalleeFI.Metrics.NumInsts/10) + Factor += 1.5f; + return Factor; +} diff --git a/libclamav/c++/llvm/lib/Analysis/InstCount.cpp b/libclamav/c++/llvm/lib/Analysis/InstCount.cpp new file mode 100644 index 000000000..a4b041f02 --- /dev/null +++ b/libclamav/c++/llvm/lib/Analysis/InstCount.cpp @@ -0,0 +1,84 @@ +//===-- InstCount.cpp - Collects the count of all instructions ------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This pass collects the count of all instructions and reports them +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "instcount" +#include "llvm/Analysis/Passes.h" +#include "llvm/Pass.h" +#include "llvm/Function.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/InstVisitor.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/ADT/Statistic.h" +using namespace llvm; + +STATISTIC(TotalInsts , "Number of instructions (of all types)"); +STATISTIC(TotalBlocks, "Number of basic blocks"); +STATISTIC(TotalFuncs , "Number of non-external functions"); +STATISTIC(TotalMemInst, "Number of memory instructions"); + +#define HANDLE_INST(N, OPCODE, CLASS) \ + STATISTIC(Num ## OPCODE ## Inst, "Number of " #OPCODE " insts"); + +#include "llvm/Instruction.def" + + +namespace { + class InstCount : public FunctionPass, public InstVisitor { + friend class InstVisitor; + + void visitFunction (Function &F) { ++TotalFuncs; } + void visitBasicBlock(BasicBlock &BB) { ++TotalBlocks; } + +#define HANDLE_INST(N, OPCODE, CLASS) \ + void visit##OPCODE(CLASS &) { ++Num##OPCODE##Inst; ++TotalInsts; } + +#include "llvm/Instruction.def" + + void visitInstruction(Instruction &I) { + errs() << "Instruction Count does not know about " << I; + llvm_unreachable(0); + } + public: + static char ID; // Pass identification, replacement for typeid + InstCount() : FunctionPass(&ID) {} + + virtual bool runOnFunction(Function &F); + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + } + virtual void print(raw_ostream &O, const Module *M) const {} + + }; +} + +char InstCount::ID = 0; +static RegisterPass +X("instcount", "Counts the various types of Instructions", false, true); + +FunctionPass *llvm::createInstCountPass() { return new InstCount(); } + +// InstCount::run - This is the main Analysis entry point for a +// function. +// +bool InstCount::runOnFunction(Function &F) { + unsigned StartMemInsts = + NumGetElementPtrInst + NumLoadInst + NumStoreInst + NumCallInst + + NumInvokeInst + NumAllocaInst; + visit(F); + unsigned EndMemInsts = + NumGetElementPtrInst + NumLoadInst + NumStoreInst + NumCallInst + + NumInvokeInst + NumAllocaInst; + TotalMemInst += EndMemInsts-StartMemInsts; + return false; +} diff --git a/libclamav/c++/llvm/lib/Analysis/InstructionSimplify.cpp b/libclamav/c++/llvm/lib/Analysis/InstructionSimplify.cpp new file mode 100644 index 000000000..7a7eb6b68 --- /dev/null +++ b/libclamav/c++/llvm/lib/Analysis/InstructionSimplify.cpp @@ -0,0 +1,380 @@ +//===- InstructionSimplify.cpp - Fold instruction operands ----------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements routines for folding instructions into simpler forms +// that do not require creating new instructions. For example, this does +// constant folding, and can handle identities like (X&0)->0. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Analysis/InstructionSimplify.h" +#include "llvm/Analysis/ConstantFolding.h" +#include "llvm/Support/ValueHandle.h" +#include "llvm/Instructions.h" +#include "llvm/Support/PatternMatch.h" +using namespace llvm; +using namespace llvm::PatternMatch; + +/// SimplifyAndInst - Given operands for an And, see if we can +/// fold the result. If not, this returns null. +Value *llvm::SimplifyAndInst(Value *Op0, Value *Op1, + const TargetData *TD) { + if (Constant *CLHS = dyn_cast(Op0)) { + if (Constant *CRHS = dyn_cast(Op1)) { + Constant *Ops[] = { CLHS, CRHS }; + return ConstantFoldInstOperands(Instruction::And, CLHS->getType(), + Ops, 2, TD); + } + + // Canonicalize the constant to the RHS. + std::swap(Op0, Op1); + } + + // X & undef -> 0 + if (isa(Op1)) + return Constant::getNullValue(Op0->getType()); + + // X & X = X + if (Op0 == Op1) + return Op0; + + // X & <0,0> = <0,0> + if (isa(Op1)) + return Op1; + + // X & <-1,-1> = X + if (ConstantVector *CP = dyn_cast(Op1)) + if (CP->isAllOnesValue()) + return Op0; + + if (ConstantInt *Op1CI = dyn_cast(Op1)) { + // X & 0 = 0 + if (Op1CI->isZero()) + return Op1CI; + // X & -1 = X + if (Op1CI->isAllOnesValue()) + return Op0; + } + + // A & ~A = ~A & A = 0 + Value *A, *B; + if ((match(Op0, m_Not(m_Value(A))) && A == Op1) || + (match(Op1, m_Not(m_Value(A))) && A == Op0)) + return Constant::getNullValue(Op0->getType()); + + // (A | ?) & A = A + if (match(Op0, m_Or(m_Value(A), m_Value(B))) && + (A == Op1 || B == Op1)) + return Op1; + + // A & (A | ?) = A + if (match(Op1, m_Or(m_Value(A), m_Value(B))) && + (A == Op0 || B == Op0)) + return Op0; + + return 0; +} + +/// SimplifyOrInst - Given operands for an Or, see if we can +/// fold the result. If not, this returns null. +Value *llvm::SimplifyOrInst(Value *Op0, Value *Op1, + const TargetData *TD) { + if (Constant *CLHS = dyn_cast(Op0)) { + if (Constant *CRHS = dyn_cast(Op1)) { + Constant *Ops[] = { CLHS, CRHS }; + return ConstantFoldInstOperands(Instruction::Or, CLHS->getType(), + Ops, 2, TD); + } + + // Canonicalize the constant to the RHS. + std::swap(Op0, Op1); + } + + // X | undef -> -1 + if (isa(Op1)) + return Constant::getAllOnesValue(Op0->getType()); + + // X | X = X + if (Op0 == Op1) + return Op0; + + // X | <0,0> = X + if (isa(Op1)) + return Op0; + + // X | <-1,-1> = <-1,-1> + if (ConstantVector *CP = dyn_cast(Op1)) + if (CP->isAllOnesValue()) + return Op1; + + if (ConstantInt *Op1CI = dyn_cast(Op1)) { + // X | 0 = X + if (Op1CI->isZero()) + return Op0; + // X | -1 = -1 + if (Op1CI->isAllOnesValue()) + return Op1CI; + } + + // A | ~A = ~A | A = -1 + Value *A, *B; + if ((match(Op0, m_Not(m_Value(A))) && A == Op1) || + (match(Op1, m_Not(m_Value(A))) && A == Op0)) + return Constant::getAllOnesValue(Op0->getType()); + + // (A & ?) | A = A + if (match(Op0, m_And(m_Value(A), m_Value(B))) && + (A == Op1 || B == Op1)) + return Op1; + + // A | (A & ?) = A + if (match(Op1, m_And(m_Value(A), m_Value(B))) && + (A == Op0 || B == Op0)) + return Op0; + + return 0; +} + + + + +static const Type *GetCompareTy(Value *Op) { + return CmpInst::makeCmpResultType(Op->getType()); +} + + +/// SimplifyICmpInst - Given operands for an ICmpInst, see if we can +/// fold the result. If not, this returns null. +Value *llvm::SimplifyICmpInst(unsigned Predicate, Value *LHS, Value *RHS, + const TargetData *TD) { + CmpInst::Predicate Pred = (CmpInst::Predicate)Predicate; + assert(CmpInst::isIntPredicate(Pred) && "Not an integer compare!"); + + if (Constant *CLHS = dyn_cast(LHS)) { + if (Constant *CRHS = dyn_cast(RHS)) + return ConstantFoldCompareInstOperands(Pred, CLHS, CRHS, TD); + + // If we have a constant, make sure it is on the RHS. + std::swap(LHS, RHS); + Pred = CmpInst::getSwappedPredicate(Pred); + } + + // ITy - This is the return type of the compare we're considering. + const Type *ITy = GetCompareTy(LHS); + + // icmp X, X -> true/false + if (LHS == RHS) + return ConstantInt::get(ITy, CmpInst::isTrueWhenEqual(Pred)); + + if (isa(RHS)) // X icmp undef -> undef + return UndefValue::get(ITy); + + // icmp , - Global/Stack value + // addresses never equal each other! We already know that Op0 != Op1. + if ((isa(LHS) || isa(LHS) || + isa(LHS)) && + (isa(RHS) || isa(RHS) || + isa(RHS))) + return ConstantInt::get(ITy, CmpInst::isFalseWhenEqual(Pred)); + + // See if we are doing a comparison with a constant. + if (ConstantInt *CI = dyn_cast(RHS)) { + // If we have an icmp le or icmp ge instruction, turn it into the + // appropriate icmp lt or icmp gt instruction. This allows us to rely on + // them being folded in the code below. + switch (Pred) { + default: break; + case ICmpInst::ICMP_ULE: + if (CI->isMaxValue(false)) // A <=u MAX -> TRUE + return ConstantInt::getTrue(CI->getContext()); + break; + case ICmpInst::ICMP_SLE: + if (CI->isMaxValue(true)) // A <=s MAX -> TRUE + return ConstantInt::getTrue(CI->getContext()); + break; + case ICmpInst::ICMP_UGE: + if (CI->isMinValue(false)) // A >=u MIN -> TRUE + return ConstantInt::getTrue(CI->getContext()); + break; + case ICmpInst::ICMP_SGE: + if (CI->isMinValue(true)) // A >=s MIN -> TRUE + return ConstantInt::getTrue(CI->getContext()); + break; + } + } + + + return 0; +} + +/// SimplifyFCmpInst - Given operands for an FCmpInst, see if we can +/// fold the result. If not, this returns null. +Value *llvm::SimplifyFCmpInst(unsigned Predicate, Value *LHS, Value *RHS, + const TargetData *TD) { + CmpInst::Predicate Pred = (CmpInst::Predicate)Predicate; + assert(CmpInst::isFPPredicate(Pred) && "Not an FP compare!"); + + if (Constant *CLHS = dyn_cast(LHS)) { + if (Constant *CRHS = dyn_cast(RHS)) + return ConstantFoldCompareInstOperands(Pred, CLHS, CRHS, TD); + + // If we have a constant, make sure it is on the RHS. + std::swap(LHS, RHS); + Pred = CmpInst::getSwappedPredicate(Pred); + } + + // Fold trivial predicates. + if (Pred == FCmpInst::FCMP_FALSE) + return ConstantInt::get(GetCompareTy(LHS), 0); + if (Pred == FCmpInst::FCMP_TRUE) + return ConstantInt::get(GetCompareTy(LHS), 1); + + if (isa(RHS)) // fcmp pred X, undef -> undef + return UndefValue::get(GetCompareTy(LHS)); + + // fcmp x,x -> true/false. Not all compares are foldable. + if (LHS == RHS) { + if (CmpInst::isTrueWhenEqual(Pred)) + return ConstantInt::get(GetCompareTy(LHS), 1); + if (CmpInst::isFalseWhenEqual(Pred)) + return ConstantInt::get(GetCompareTy(LHS), 0); + } + + // Handle fcmp with constant RHS + if (Constant *RHSC = dyn_cast(RHS)) { + // If the constant is a nan, see if we can fold the comparison based on it. + if (ConstantFP *CFP = dyn_cast(RHSC)) { + if (CFP->getValueAPF().isNaN()) { + if (FCmpInst::isOrdered(Pred)) // True "if ordered and foo" + return ConstantInt::getFalse(CFP->getContext()); + assert(FCmpInst::isUnordered(Pred) && + "Comparison must be either ordered or unordered!"); + // True if unordered. + return ConstantInt::getTrue(CFP->getContext()); + } + } + } + + return 0; +} + +/// SimplifyGEPInst - Given operands for an GetElementPtrInst, see if we can +/// fold the result. If not, this returns null. +Value *llvm::SimplifyGEPInst(Value *const *Ops, unsigned NumOps, + const TargetData *TD) { + // getelementptr P -> P. + if (NumOps == 1) + return Ops[0]; + + // TODO. + //if (isa(Ops[0])) + // return UndefValue::get(GEP.getType()); + + // getelementptr P, 0 -> P. + if (NumOps == 2) + if (ConstantInt *C = dyn_cast(Ops[1])) + if (C->isZero()) + return Ops[0]; + + // Check to see if this is constant foldable. + for (unsigned i = 0; i != NumOps; ++i) + if (!isa(Ops[i])) + return 0; + + return ConstantExpr::getGetElementPtr(cast(Ops[0]), + (Constant *const*)Ops+1, NumOps-1); +} + + +//=== Helper functions for higher up the class hierarchy. + +/// SimplifyBinOp - Given operands for a BinaryOperator, see if we can +/// fold the result. If not, this returns null. +Value *llvm::SimplifyBinOp(unsigned Opcode, Value *LHS, Value *RHS, + const TargetData *TD) { + switch (Opcode) { + case Instruction::And: return SimplifyAndInst(LHS, RHS, TD); + case Instruction::Or: return SimplifyOrInst(LHS, RHS, TD); + default: + if (Constant *CLHS = dyn_cast(LHS)) + if (Constant *CRHS = dyn_cast(RHS)) { + Constant *COps[] = {CLHS, CRHS}; + return ConstantFoldInstOperands(Opcode, LHS->getType(), COps, 2, TD); + } + return 0; + } +} + +/// SimplifyCmpInst - Given operands for a CmpInst, see if we can +/// fold the result. +Value *llvm::SimplifyCmpInst(unsigned Predicate, Value *LHS, Value *RHS, + const TargetData *TD) { + if (CmpInst::isIntPredicate((CmpInst::Predicate)Predicate)) + return SimplifyICmpInst(Predicate, LHS, RHS, TD); + return SimplifyFCmpInst(Predicate, LHS, RHS, TD); +} + + +/// SimplifyInstruction - See if we can compute a simplified version of this +/// instruction. If not, this returns null. +Value *llvm::SimplifyInstruction(Instruction *I, const TargetData *TD) { + switch (I->getOpcode()) { + default: + return ConstantFoldInstruction(I, TD); + case Instruction::And: + return SimplifyAndInst(I->getOperand(0), I->getOperand(1), TD); + case Instruction::Or: + return SimplifyOrInst(I->getOperand(0), I->getOperand(1), TD); + case Instruction::ICmp: + return SimplifyICmpInst(cast(I)->getPredicate(), + I->getOperand(0), I->getOperand(1), TD); + case Instruction::FCmp: + return SimplifyFCmpInst(cast(I)->getPredicate(), + I->getOperand(0), I->getOperand(1), TD); + case Instruction::GetElementPtr: { + SmallVector Ops(I->op_begin(), I->op_end()); + return SimplifyGEPInst(&Ops[0], Ops.size(), TD); + } + } +} + +/// ReplaceAndSimplifyAllUses - Perform From->replaceAllUsesWith(To) and then +/// delete the From instruction. In addition to a basic RAUW, this does a +/// recursive simplification of the newly formed instructions. This catches +/// things where one simplification exposes other opportunities. This only +/// simplifies and deletes scalar operations, it does not change the CFG. +/// +void llvm::ReplaceAndSimplifyAllUses(Instruction *From, Value *To, + const TargetData *TD) { + assert(From != To && "ReplaceAndSimplifyAllUses(X,X) is not valid!"); + + // FromHandle - This keeps a weakvh on the from value so that we can know if + // it gets deleted out from under us in a recursive simplification. + WeakVH FromHandle(From); + + while (!From->use_empty()) { + // Update the instruction to use the new value. + Use &U = From->use_begin().getUse(); + Instruction *User = cast(U.getUser()); + U = To; + + // See if we can simplify it. + if (Value *V = SimplifyInstruction(User, TD)) { + // Recursively simplify this. + ReplaceAndSimplifyAllUses(User, V, TD); + + // If the recursive simplification ended up revisiting and deleting 'From' + // then we're done. + if (FromHandle == 0) + return; + } + } + From->eraseFromParent(); +} + diff --git a/libclamav/c++/llvm/lib/Analysis/Interval.cpp b/libclamav/c++/llvm/lib/Analysis/Interval.cpp new file mode 100644 index 000000000..ca9cdcaf2 --- /dev/null +++ b/libclamav/c++/llvm/lib/Analysis/Interval.cpp @@ -0,0 +1,58 @@ +//===- Interval.cpp - Interval class code ---------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the definition of the Interval class, which represents a +// partition of a control flow graph of some kind. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Analysis/Interval.h" +#include "llvm/BasicBlock.h" +#include "llvm/Support/CFG.h" +#include "llvm/Support/raw_ostream.h" +#include + +using namespace llvm; + +//===----------------------------------------------------------------------===// +// Interval Implementation +//===----------------------------------------------------------------------===// + +// isLoop - Find out if there is a back edge in this interval... +// +bool Interval::isLoop() const { + // There is a loop in this interval iff one of the predecessors of the header + // node lives in the interval. + for (::pred_iterator I = ::pred_begin(HeaderNode), E = ::pred_end(HeaderNode); + I != E; ++I) + if (contains(*I)) + return true; + return false; +} + + +void Interval::print(raw_ostream &OS) const { + OS << "-------------------------------------------------------------\n" + << "Interval Contents:\n"; + + // Print out all of the basic blocks in the interval... + for (std::vector::const_iterator I = Nodes.begin(), + E = Nodes.end(); I != E; ++I) + OS << **I << "\n"; + + OS << "Interval Predecessors:\n"; + for (std::vector::const_iterator I = Predecessors.begin(), + E = Predecessors.end(); I != E; ++I) + OS << **I << "\n"; + + OS << "Interval Successors:\n"; + for (std::vector::const_iterator I = Successors.begin(), + E = Successors.end(); I != E; ++I) + OS << **I << "\n"; +} diff --git a/libclamav/c++/llvm/lib/Analysis/IntervalPartition.cpp b/libclamav/c++/llvm/lib/Analysis/IntervalPartition.cpp new file mode 100644 index 000000000..1f17b77a5 --- /dev/null +++ b/libclamav/c++/llvm/lib/Analysis/IntervalPartition.cpp @@ -0,0 +1,114 @@ +//===- IntervalPartition.cpp - Interval Partition module code -------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the definition of the IntervalPartition class, which +// calculates and represent the interval partition of a function. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Analysis/IntervalIterator.h" +using namespace llvm; + +char IntervalPartition::ID = 0; +static RegisterPass +X("intervals", "Interval Partition Construction", true, true); + +//===----------------------------------------------------------------------===// +// IntervalPartition Implementation +//===----------------------------------------------------------------------===// + +// releaseMemory - Reset state back to before function was analyzed +void IntervalPartition::releaseMemory() { + for (unsigned i = 0, e = Intervals.size(); i != e; ++i) + delete Intervals[i]; + IntervalMap.clear(); + Intervals.clear(); + RootInterval = 0; +} + +void IntervalPartition::print(raw_ostream &O, const Module*) const { + for(unsigned i = 0, e = Intervals.size(); i != e; ++i) + Intervals[i]->print(O); +} + +// addIntervalToPartition - Add an interval to the internal list of intervals, +// and then add mappings from all of the basic blocks in the interval to the +// interval itself (in the IntervalMap). +// +void IntervalPartition::addIntervalToPartition(Interval *I) { + Intervals.push_back(I); + + // Add mappings for all of the basic blocks in I to the IntervalPartition + for (Interval::node_iterator It = I->Nodes.begin(), End = I->Nodes.end(); + It != End; ++It) + IntervalMap.insert(std::make_pair(*It, I)); +} + +// updatePredecessors - Interval generation only sets the successor fields of +// the interval data structures. After interval generation is complete, +// run through all of the intervals and propagate successor info as +// predecessor info. +// +void IntervalPartition::updatePredecessors(Interval *Int) { + BasicBlock *Header = Int->getHeaderNode(); + for (Interval::succ_iterator I = Int->Successors.begin(), + E = Int->Successors.end(); I != E; ++I) + getBlockInterval(*I)->Predecessors.push_back(Header); +} + +// IntervalPartition ctor - Build the first level interval partition for the +// specified function... +// +bool IntervalPartition::runOnFunction(Function &F) { + // Pass false to intervals_begin because we take ownership of it's memory + function_interval_iterator I = intervals_begin(&F, false); + assert(I != intervals_end(&F) && "No intervals in function!?!?!"); + + addIntervalToPartition(RootInterval = *I); + + ++I; // After the first one... + + // Add the rest of the intervals to the partition. + for (function_interval_iterator E = intervals_end(&F); I != E; ++I) + addIntervalToPartition(*I); + + // Now that we know all of the successor information, propagate this to the + // predecessors for each block. + for (unsigned i = 0, e = Intervals.size(); i != e; ++i) + updatePredecessors(Intervals[i]); + return false; +} + + +// IntervalPartition ctor - Build a reduced interval partition from an +// existing interval graph. This takes an additional boolean parameter to +// distinguish it from a copy constructor. Always pass in false for now. +// +IntervalPartition::IntervalPartition(IntervalPartition &IP, bool) + : FunctionPass(&ID) { + assert(IP.getRootInterval() && "Cannot operate on empty IntervalPartitions!"); + + // Pass false to intervals_begin because we take ownership of it's memory + interval_part_interval_iterator I = intervals_begin(IP, false); + assert(I != intervals_end(IP) && "No intervals in interval partition!?!?!"); + + addIntervalToPartition(RootInterval = *I); + + ++I; // After the first one... + + // Add the rest of the intervals to the partition. + for (interval_part_interval_iterator E = intervals_end(IP); I != E; ++I) + addIntervalToPartition(*I); + + // Now that we know all of the successor information, propagate this to the + // predecessors for each block. + for (unsigned i = 0, e = Intervals.size(); i != e; ++i) + updatePredecessors(Intervals[i]); +} + diff --git a/libclamav/c++/llvm/lib/Analysis/LazyValueInfo.cpp b/libclamav/c++/llvm/lib/Analysis/LazyValueInfo.cpp new file mode 100644 index 000000000..5796c6fe1 --- /dev/null +++ b/libclamav/c++/llvm/lib/Analysis/LazyValueInfo.cpp @@ -0,0 +1,582 @@ +//===- LazyValueInfo.cpp - Value constraint analysis ----------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the interface for lazy computation of value constraint +// information. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "lazy-value-info" +#include "llvm/Analysis/LazyValueInfo.h" +#include "llvm/Constants.h" +#include "llvm/Instructions.h" +#include "llvm/Analysis/ConstantFolding.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Support/CFG.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/PointerIntPair.h" +#include "llvm/ADT/STLExtras.h" +using namespace llvm; + +char LazyValueInfo::ID = 0; +static RegisterPass +X("lazy-value-info", "Lazy Value Information Analysis", false, true); + +namespace llvm { + FunctionPass *createLazyValueInfoPass() { return new LazyValueInfo(); } +} + + +//===----------------------------------------------------------------------===// +// LVILatticeVal +//===----------------------------------------------------------------------===// + +/// LVILatticeVal - This is the information tracked by LazyValueInfo for each +/// value. +/// +/// FIXME: This is basically just for bringup, this can be made a lot more rich +/// in the future. +/// +namespace { +class LVILatticeVal { + enum LatticeValueTy { + /// undefined - This LLVM Value has no known value yet. + undefined, + /// constant - This LLVM Value has a specific constant value. + constant, + + /// notconstant - This LLVM value is known to not have the specified value. + notconstant, + + /// overdefined - This instruction is not known to be constant, and we know + /// it has a value. + overdefined + }; + + /// Val: This stores the current lattice value along with the Constant* for + /// the constant if this is a 'constant' or 'notconstant' value. + PointerIntPair Val; + +public: + LVILatticeVal() : Val(0, undefined) {} + + static LVILatticeVal get(Constant *C) { + LVILatticeVal Res; + Res.markConstant(C); + return Res; + } + static LVILatticeVal getNot(Constant *C) { + LVILatticeVal Res; + Res.markNotConstant(C); + return Res; + } + + bool isUndefined() const { return Val.getInt() == undefined; } + bool isConstant() const { return Val.getInt() == constant; } + bool isNotConstant() const { return Val.getInt() == notconstant; } + bool isOverdefined() const { return Val.getInt() == overdefined; } + + Constant *getConstant() const { + assert(isConstant() && "Cannot get the constant of a non-constant!"); + return Val.getPointer(); + } + + Constant *getNotConstant() const { + assert(isNotConstant() && "Cannot get the constant of a non-notconstant!"); + return Val.getPointer(); + } + + /// markOverdefined - Return true if this is a change in status. + bool markOverdefined() { + if (isOverdefined()) + return false; + Val.setInt(overdefined); + return true; + } + + /// markConstant - Return true if this is a change in status. + bool markConstant(Constant *V) { + if (isConstant()) { + assert(getConstant() == V && "Marking constant with different value"); + return false; + } + + assert(isUndefined()); + Val.setInt(constant); + assert(V && "Marking constant with NULL"); + Val.setPointer(V); + return true; + } + + /// markNotConstant - Return true if this is a change in status. + bool markNotConstant(Constant *V) { + if (isNotConstant()) { + assert(getNotConstant() == V && "Marking !constant with different value"); + return false; + } + + if (isConstant()) + assert(getConstant() != V && "Marking not constant with different value"); + else + assert(isUndefined()); + + Val.setInt(notconstant); + assert(V && "Marking constant with NULL"); + Val.setPointer(V); + return true; + } + + /// mergeIn - Merge the specified lattice value into this one, updating this + /// one and returning true if anything changed. + bool mergeIn(const LVILatticeVal &RHS) { + if (RHS.isUndefined() || isOverdefined()) return false; + if (RHS.isOverdefined()) return markOverdefined(); + + if (RHS.isNotConstant()) { + if (isNotConstant()) { + if (getNotConstant() != RHS.getNotConstant() || + isa(getNotConstant()) || + isa(RHS.getNotConstant())) + return markOverdefined(); + return false; + } + if (isConstant()) { + if (getConstant() == RHS.getNotConstant() || + isa(RHS.getNotConstant()) || + isa(getConstant())) + return markOverdefined(); + return markNotConstant(RHS.getNotConstant()); + } + + assert(isUndefined() && "Unexpected lattice"); + return markNotConstant(RHS.getNotConstant()); + } + + // RHS must be a constant, we must be undef, constant, or notconstant. + if (isUndefined()) + return markConstant(RHS.getConstant()); + + if (isConstant()) { + if (getConstant() != RHS.getConstant()) + return markOverdefined(); + return false; + } + + // If we are known "!=4" and RHS is "==5", stay at "!=4". + if (getNotConstant() == RHS.getConstant() || + isa(getNotConstant()) || + isa(RHS.getConstant())) + return markOverdefined(); + return false; + } + +}; + +} // end anonymous namespace. + +namespace llvm { +raw_ostream &operator<<(raw_ostream &OS, const LVILatticeVal &Val) { + if (Val.isUndefined()) + return OS << "undefined"; + if (Val.isOverdefined()) + return OS << "overdefined"; + + if (Val.isNotConstant()) + return OS << "notconstant<" << *Val.getNotConstant() << '>'; + return OS << "constant<" << *Val.getConstant() << '>'; +} +} + +//===----------------------------------------------------------------------===// +// LazyValueInfoCache Decl +//===----------------------------------------------------------------------===// + +namespace { + /// LazyValueInfoCache - This is the cache kept by LazyValueInfo which + /// maintains information about queries across the clients' queries. + class LazyValueInfoCache { + public: + /// BlockCacheEntryTy - This is a computed lattice value at the end of the + /// specified basic block for a Value* that depends on context. + typedef std::pair BlockCacheEntryTy; + + /// ValueCacheEntryTy - This is all of the cached block information for + /// exactly one Value*. The entries are sorted by the BasicBlock* of the + /// entries, allowing us to do a lookup with a binary search. + typedef std::vector ValueCacheEntryTy; + + private: + /// ValueCache - This is all of the cached information for all values, + /// mapped from Value* to key information. + DenseMap ValueCache; + public: + + /// getValueInBlock - This is the query interface to determine the lattice + /// value for the specified Value* at the end of the specified block. + LVILatticeVal getValueInBlock(Value *V, BasicBlock *BB); + + /// getValueOnEdge - This is the query interface to determine the lattice + /// value for the specified Value* that is true on the specified edge. + LVILatticeVal getValueOnEdge(Value *V, BasicBlock *FromBB,BasicBlock *ToBB); + }; +} // end anonymous namespace + +namespace { + struct BlockCacheEntryComparator { + static int Compare(const void *LHSv, const void *RHSv) { + const LazyValueInfoCache::BlockCacheEntryTy *LHS = + static_cast(LHSv); + const LazyValueInfoCache::BlockCacheEntryTy *RHS = + static_cast(RHSv); + if (LHS->first < RHS->first) + return -1; + if (LHS->first > RHS->first) + return 1; + return 0; + } + + bool operator()(const LazyValueInfoCache::BlockCacheEntryTy &LHS, + const LazyValueInfoCache::BlockCacheEntryTy &RHS) const { + return LHS.first < RHS.first; + } + }; +} + +//===----------------------------------------------------------------------===// +// LVIQuery Impl +//===----------------------------------------------------------------------===// + +namespace { + /// LVIQuery - This is a transient object that exists while a query is + /// being performed. + /// + /// TODO: Reuse LVIQuery instead of recreating it for every query, this avoids + /// reallocation of the densemap on every query. + class LVIQuery { + typedef LazyValueInfoCache::BlockCacheEntryTy BlockCacheEntryTy; + typedef LazyValueInfoCache::ValueCacheEntryTy ValueCacheEntryTy; + + /// This is the current value being queried for. + Value *Val; + + /// This is all of the cached information about this value. + ValueCacheEntryTy &Cache; + + /// NewBlocks - This is a mapping of the new BasicBlocks which have been + /// added to cache but that are not in sorted order. + DenseMap NewBlockInfo; + public: + + LVIQuery(Value *V, ValueCacheEntryTy &VC) : Val(V), Cache(VC) { + } + + ~LVIQuery() { + // When the query is done, insert the newly discovered facts into the + // cache in sorted order. + if (NewBlockInfo.empty()) return; + + // Grow the cache to exactly fit the new data. + Cache.reserve(Cache.size() + NewBlockInfo.size()); + + // If we only have one new entry, insert it instead of doing a full-on + // sort. + if (NewBlockInfo.size() == 1) { + BlockCacheEntryTy Entry = *NewBlockInfo.begin(); + ValueCacheEntryTy::iterator I = + std::lower_bound(Cache.begin(), Cache.end(), Entry, + BlockCacheEntryComparator()); + assert((I == Cache.end() || I->first != Entry.first) && + "Entry already in map!"); + + Cache.insert(I, Entry); + return; + } + + // TODO: If we only have two new elements, INSERT them both. + + Cache.insert(Cache.end(), NewBlockInfo.begin(), NewBlockInfo.end()); + array_pod_sort(Cache.begin(), Cache.end(), + BlockCacheEntryComparator::Compare); + + } + + LVILatticeVal getBlockValue(BasicBlock *BB); + LVILatticeVal getEdgeValue(BasicBlock *FromBB, BasicBlock *ToBB); + + private: + LVILatticeVal &getCachedEntryForBlock(BasicBlock *BB); + }; +} // end anonymous namespace + +/// getCachedEntryForBlock - See if we already have a value for this block. If +/// so, return it, otherwise create a new entry in the NewBlockInfo map to use. +LVILatticeVal &LVIQuery::getCachedEntryForBlock(BasicBlock *BB) { + + // Do a binary search to see if we already have an entry for this block in + // the cache set. If so, find it. + if (!Cache.empty()) { + ValueCacheEntryTy::iterator Entry = + std::lower_bound(Cache.begin(), Cache.end(), + BlockCacheEntryTy(BB, LVILatticeVal()), + BlockCacheEntryComparator()); + if (Entry != Cache.end() && Entry->first == BB) + return Entry->second; + } + + // Otherwise, check to see if it's in NewBlockInfo or create a new entry if + // not. + return NewBlockInfo[BB]; +} + +LVILatticeVal LVIQuery::getBlockValue(BasicBlock *BB) { + // See if we already have a value for this block. + LVILatticeVal &BBLV = getCachedEntryForBlock(BB); + + // If we've already computed this block's value, return it. + if (!BBLV.isUndefined()) { + DEBUG(errs() << " reuse BB '" << BB->getName() << "' val=" << BBLV <<'\n'); + return BBLV; + } + + // Otherwise, this is the first time we're seeing this block. Reset the + // lattice value to overdefined, so that cycles will terminate and be + // conservatively correct. + BBLV.markOverdefined(); + + // If V is live into BB, see if our predecessors know anything about it. + Instruction *BBI = dyn_cast(Val); + if (BBI == 0 || BBI->getParent() != BB) { + LVILatticeVal Result; // Start Undefined. + unsigned NumPreds = 0; + + // Loop over all of our predecessors, merging what we know from them into + // result. + for (pred_iterator PI = pred_begin(BB), E = pred_end(BB); PI != E; ++PI) { + Result.mergeIn(getEdgeValue(*PI, BB)); + + // If we hit overdefined, exit early. The BlockVals entry is already set + // to overdefined. + if (Result.isOverdefined()) { + DEBUG(errs() << " compute BB '" << BB->getName() + << "' - overdefined because of pred.\n"); + return Result; + } + ++NumPreds; + } + + // If this is the entry block, we must be asking about an argument. The + // value is overdefined. + if (NumPreds == 0 && BB == &BB->getParent()->front()) { + assert(isa(Val) && "Unknown live-in to the entry block"); + Result.markOverdefined(); + return Result; + } + + // Return the merged value, which is more precise than 'overdefined'. + assert(!Result.isOverdefined()); + return getCachedEntryForBlock(BB) = Result; + } + + // If this value is defined by an instruction in this block, we have to + // process it here somehow or return overdefined. + if (PHINode *PN = dyn_cast(BBI)) { + (void)PN; + // TODO: PHI Translation in preds. + } else { + + } + + DEBUG(errs() << " compute BB '" << BB->getName() + << "' - overdefined because inst def found.\n"); + + LVILatticeVal Result; + Result.markOverdefined(); + return getCachedEntryForBlock(BB) = Result; +} + + +/// getEdgeValue - This method attempts to infer more complex +LVILatticeVal LVIQuery::getEdgeValue(BasicBlock *BBFrom, BasicBlock *BBTo) { + // TODO: Handle more complex conditionals. If (v == 0 || v2 < 1) is false, we + // know that v != 0. + if (BranchInst *BI = dyn_cast(BBFrom->getTerminator())) { + // If this is a conditional branch and only one successor goes to BBTo, then + // we maybe able to infer something from the condition. + if (BI->isConditional() && + BI->getSuccessor(0) != BI->getSuccessor(1)) { + bool isTrueDest = BI->getSuccessor(0) == BBTo; + assert(BI->getSuccessor(!isTrueDest) == BBTo && + "BBTo isn't a successor of BBFrom"); + + // If V is the condition of the branch itself, then we know exactly what + // it is. + if (BI->getCondition() == Val) + return LVILatticeVal::get(ConstantInt::get( + Type::getInt1Ty(Val->getContext()), isTrueDest)); + + // If the condition of the branch is an equality comparison, we may be + // able to infer the value. + if (ICmpInst *ICI = dyn_cast(BI->getCondition())) + if (ICI->isEquality() && ICI->getOperand(0) == Val && + isa(ICI->getOperand(1))) { + // We know that V has the RHS constant if this is a true SETEQ or + // false SETNE. + if (isTrueDest == (ICI->getPredicate() == ICmpInst::ICMP_EQ)) + return LVILatticeVal::get(cast(ICI->getOperand(1))); + return LVILatticeVal::getNot(cast(ICI->getOperand(1))); + } + } + } + + // If the edge was formed by a switch on the value, then we may know exactly + // what it is. + if (SwitchInst *SI = dyn_cast(BBFrom->getTerminator())) { + // If BBTo is the default destination of the switch, we don't know anything. + // Given a more powerful range analysis we could know stuff. + if (SI->getCondition() == Val && SI->getDefaultDest() != BBTo) { + // We only know something if there is exactly one value that goes from + // BBFrom to BBTo. + unsigned NumEdges = 0; + ConstantInt *EdgeVal = 0; + for (unsigned i = 1, e = SI->getNumSuccessors(); i != e; ++i) { + if (SI->getSuccessor(i) != BBTo) continue; + if (NumEdges++) break; + EdgeVal = SI->getCaseValue(i); + } + assert(EdgeVal && "Missing successor?"); + if (NumEdges == 1) + return LVILatticeVal::get(EdgeVal); + } + } + + // Otherwise see if the value is known in the block. + return getBlockValue(BBFrom); +} + + +//===----------------------------------------------------------------------===// +// LazyValueInfoCache Impl +//===----------------------------------------------------------------------===// + +LVILatticeVal LazyValueInfoCache::getValueInBlock(Value *V, BasicBlock *BB) { + // If already a constant, there is nothing to compute. + if (Constant *VC = dyn_cast(V)) + return LVILatticeVal::get(VC); + + DEBUG(errs() << "LVI Getting block end value " << *V << " at '" + << BB->getName() << "'\n"); + + LVILatticeVal Result = LVIQuery(V, ValueCache[V]).getBlockValue(BB); + + DEBUG(errs() << " Result = " << Result << "\n"); + return Result; +} + +LVILatticeVal LazyValueInfoCache:: +getValueOnEdge(Value *V, BasicBlock *FromBB, BasicBlock *ToBB) { + // If already a constant, there is nothing to compute. + if (Constant *VC = dyn_cast(V)) + return LVILatticeVal::get(VC); + + DEBUG(errs() << "LVI Getting edge value " << *V << " from '" + << FromBB->getName() << "' to '" << ToBB->getName() << "'\n"); + LVILatticeVal Result = + LVIQuery(V, ValueCache[V]).getEdgeValue(FromBB, ToBB); + + DEBUG(errs() << " Result = " << Result << "\n"); + + return Result; +} + +//===----------------------------------------------------------------------===// +// LazyValueInfo Impl +//===----------------------------------------------------------------------===// + +bool LazyValueInfo::runOnFunction(Function &F) { + TD = getAnalysisIfAvailable(); + // Fully lazy. + return false; +} + +/// getCache - This lazily constructs the LazyValueInfoCache. +static LazyValueInfoCache &getCache(void *&PImpl) { + if (!PImpl) + PImpl = new LazyValueInfoCache(); + return *static_cast(PImpl); +} + +void LazyValueInfo::releaseMemory() { + // If the cache was allocated, free it. + if (PImpl) { + delete &getCache(PImpl); + PImpl = 0; + } +} + +Constant *LazyValueInfo::getConstant(Value *V, BasicBlock *BB) { + LVILatticeVal Result = getCache(PImpl).getValueInBlock(V, BB); + + if (Result.isConstant()) + return Result.getConstant(); + return 0; +} + +/// getConstantOnEdge - Determine whether the specified value is known to be a +/// constant on the specified edge. Return null if not. +Constant *LazyValueInfo::getConstantOnEdge(Value *V, BasicBlock *FromBB, + BasicBlock *ToBB) { + LVILatticeVal Result = getCache(PImpl).getValueOnEdge(V, FromBB, ToBB); + + if (Result.isConstant()) + return Result.getConstant(); + return 0; +} + +/// getPredicateOnEdge - Determine whether the specified value comparison +/// with a constant is known to be true or false on the specified CFG edge. +/// Pred is a CmpInst predicate. +LazyValueInfo::Tristate +LazyValueInfo::getPredicateOnEdge(unsigned Pred, Value *V, Constant *C, + BasicBlock *FromBB, BasicBlock *ToBB) { + LVILatticeVal Result = getCache(PImpl).getValueOnEdge(V, FromBB, ToBB); + + // If we know the value is a constant, evaluate the conditional. + Constant *Res = 0; + if (Result.isConstant()) { + Res = ConstantFoldCompareInstOperands(Pred, Result.getConstant(), C, TD); + if (ConstantInt *ResCI = dyn_cast_or_null(Res)) + return ResCI->isZero() ? False : True; + return Unknown; + } + + if (Result.isNotConstant()) { + // If this is an equality comparison, we can try to fold it knowing that + // "V != C1". + if (Pred == ICmpInst::ICMP_EQ) { + // !C1 == C -> false iff C1 == C. + Res = ConstantFoldCompareInstOperands(ICmpInst::ICMP_NE, + Result.getNotConstant(), C, TD); + if (Res->isNullValue()) + return False; + } else if (Pred == ICmpInst::ICMP_NE) { + // !C1 != C -> true iff C1 == C. + Res = ConstantFoldCompareInstOperands(ICmpInst::ICMP_NE, + Result.getNotConstant(), C, TD); + if (Res->isNullValue()) + return True; + } + return Unknown; + } + + return Unknown; +} + + diff --git a/libclamav/c++/llvm/lib/Analysis/LibCallAliasAnalysis.cpp b/libclamav/c++/llvm/lib/Analysis/LibCallAliasAnalysis.cpp new file mode 100644 index 000000000..741965929 --- /dev/null +++ b/libclamav/c++/llvm/lib/Analysis/LibCallAliasAnalysis.cpp @@ -0,0 +1,139 @@ +//===- LibCallAliasAnalysis.cpp - Implement AliasAnalysis for libcalls ----===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the LibCallAliasAnalysis class. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Analysis/LibCallAliasAnalysis.h" +#include "llvm/Analysis/Passes.h" +#include "llvm/Analysis/LibCallSemantics.h" +#include "llvm/Function.h" +#include "llvm/Pass.h" +using namespace llvm; + +// Register this pass... +char LibCallAliasAnalysis::ID = 0; +static RegisterPass +X("libcall-aa", "LibCall Alias Analysis", false, true); + +// Declare that we implement the AliasAnalysis interface +static RegisterAnalysisGroup Y(X); + +FunctionPass *llvm::createLibCallAliasAnalysisPass(LibCallInfo *LCI) { + return new LibCallAliasAnalysis(LCI); +} + +LibCallAliasAnalysis::~LibCallAliasAnalysis() { + delete LCI; +} + +void LibCallAliasAnalysis::getAnalysisUsage(AnalysisUsage &AU) const { + AliasAnalysis::getAnalysisUsage(AU); + AU.setPreservesAll(); // Does not transform code +} + + + +/// AnalyzeLibCallDetails - Given a call to a function with the specified +/// LibCallFunctionInfo, see if we can improve the mod/ref footprint of the call +/// vs the specified pointer/size. +AliasAnalysis::ModRefResult +LibCallAliasAnalysis::AnalyzeLibCallDetails(const LibCallFunctionInfo *FI, + CallSite CS, Value *P, + unsigned Size) { + // If we have a function, check to see what kind of mod/ref effects it + // has. Start by including any info globally known about the function. + AliasAnalysis::ModRefResult MRInfo = FI->UniversalBehavior; + if (MRInfo == NoModRef) return MRInfo; + + // If that didn't tell us that the function is 'readnone', check to see + // if we have detailed info and if 'P' is any of the locations we know + // about. + const LibCallFunctionInfo::LocationMRInfo *Details = FI->LocationDetails; + if (Details == 0) + return MRInfo; + + // If the details array is of the 'DoesNot' kind, we only know something if + // the pointer is a match for one of the locations in 'Details'. If we find a + // match, we can prove some interactions cannot happen. + // + if (FI->DetailsType == LibCallFunctionInfo::DoesNot) { + // Find out if the pointer refers to a known location. + for (unsigned i = 0; Details[i].LocationID != ~0U; ++i) { + const LibCallLocationInfo &Loc = + LCI->getLocationInfo(Details[i].LocationID); + LibCallLocationInfo::LocResult Res = Loc.isLocation(CS, P, Size); + if (Res != LibCallLocationInfo::Yes) continue; + + // If we find a match against a location that we 'do not' interact with, + // learn this info into MRInfo. + return ModRefResult(MRInfo & ~Details[i].MRInfo); + } + return MRInfo; + } + + // If the details are of the 'DoesOnly' sort, we know something if the pointer + // is a match for one of the locations in 'Details'. Also, if we can prove + // that the pointers is *not* one of the locations in 'Details', we know that + // the call is NoModRef. + assert(FI->DetailsType == LibCallFunctionInfo::DoesOnly); + + // Find out if the pointer refers to a known location. + bool NoneMatch = true; + for (unsigned i = 0; Details[i].LocationID != ~0U; ++i) { + const LibCallLocationInfo &Loc = + LCI->getLocationInfo(Details[i].LocationID); + LibCallLocationInfo::LocResult Res = Loc.isLocation(CS, P, Size); + if (Res == LibCallLocationInfo::No) continue; + + // If we don't know if this pointer points to the location, then we have to + // assume it might alias in some case. + if (Res == LibCallLocationInfo::Unknown) { + NoneMatch = false; + continue; + } + + // If we know that this pointer definitely is pointing into the location, + // merge in this information. + return ModRefResult(MRInfo & Details[i].MRInfo); + } + + // If we found that the pointer is guaranteed to not match any of the + // locations in our 'DoesOnly' rule, then we know that the pointer must point + // to some other location. Since the libcall doesn't mod/ref any other + // locations, return NoModRef. + if (NoneMatch) + return NoModRef; + + // Otherwise, return any other info gained so far. + return MRInfo; +} + +// getModRefInfo - Check to see if the specified callsite can clobber the +// specified memory object. +// +AliasAnalysis::ModRefResult +LibCallAliasAnalysis::getModRefInfo(CallSite CS, Value *P, unsigned Size) { + ModRefResult MRInfo = ModRef; + + // If this is a direct call to a function that LCI knows about, get the + // information about the runtime function. + if (LCI) { + if (Function *F = CS.getCalledFunction()) { + if (const LibCallFunctionInfo *FI = LCI->getFunctionInfo(F)) { + MRInfo = ModRefResult(MRInfo & AnalyzeLibCallDetails(FI, CS, P, Size)); + if (MRInfo == NoModRef) return NoModRef; + } + } + } + + // The AliasAnalysis base class has some smarts, lets use them. + return (ModRefResult)(MRInfo | AliasAnalysis::getModRefInfo(CS, P, Size)); +} diff --git a/libclamav/c++/llvm/lib/Analysis/LibCallSemantics.cpp b/libclamav/c++/llvm/lib/Analysis/LibCallSemantics.cpp new file mode 100644 index 000000000..e0060c3e8 --- /dev/null +++ b/libclamav/c++/llvm/lib/Analysis/LibCallSemantics.cpp @@ -0,0 +1,62 @@ +//===- LibCallSemantics.cpp - Describe library semantics ------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements interfaces that can be used to describe language +// specific runtime library interfaces (e.g. libc, libm, etc) to LLVM +// optimizers. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Analysis/LibCallSemantics.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/Function.h" +using namespace llvm; + +/// getMap - This impl pointer in ~LibCallInfo is actually a StringMap. This +/// helper does the cast. +static StringMap *getMap(void *Ptr) { + return static_cast *>(Ptr); +} + +LibCallInfo::~LibCallInfo() { + delete getMap(Impl); +} + +const LibCallLocationInfo &LibCallInfo::getLocationInfo(unsigned LocID) const { + // Get location info on the first call. + if (NumLocations == 0) + NumLocations = getLocationInfo(Locations); + + assert(LocID < NumLocations && "Invalid location ID!"); + return Locations[LocID]; +} + + +/// getFunctionInfo - Return the LibCallFunctionInfo object corresponding to +/// the specified function if we have it. If not, return null. +const LibCallFunctionInfo *LibCallInfo::getFunctionInfo(Function *F) const { + StringMap *Map = getMap(Impl); + + /// If this is the first time we are querying for this info, lazily construct + /// the StringMap to index it. + if (Map == 0) { + Impl = Map = new StringMap(); + + const LibCallFunctionInfo *Array = getFunctionInfoArray(); + if (Array == 0) return 0; + + // We now have the array of entries. Populate the StringMap. + for (unsigned i = 0; Array[i].Name; ++i) + (*Map)[Array[i].Name] = Array+i; + } + + // Look up this function in the string map. + return Map->lookup(F->getName()); +} + diff --git a/libclamav/c++/llvm/lib/Analysis/LiveValues.cpp b/libclamav/c++/llvm/lib/Analysis/LiveValues.cpp new file mode 100644 index 000000000..02ec7d318 --- /dev/null +++ b/libclamav/c++/llvm/lib/Analysis/LiveValues.cpp @@ -0,0 +1,193 @@ +//===- LiveValues.cpp - Liveness information for LLVM IR Values. ----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the implementation for the LLVM IR Value liveness +// analysis pass. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Analysis/LiveValues.h" +#include "llvm/Analysis/Dominators.h" +#include "llvm/Analysis/LoopInfo.h" +using namespace llvm; + +namespace llvm { + FunctionPass *createLiveValuesPass() { return new LiveValues(); } +} + +char LiveValues::ID = 0; +static RegisterPass +X("live-values", "Value Liveness Analysis", false, true); + +LiveValues::LiveValues() : FunctionPass(&ID) {} + +void LiveValues::getAnalysisUsage(AnalysisUsage &AU) const { + AU.addRequired(); + AU.addRequired(); + AU.setPreservesAll(); +} + +bool LiveValues::runOnFunction(Function &F) { + DT = &getAnalysis(); + LI = &getAnalysis(); + + // This pass' values are computed lazily, so there's nothing to do here. + + return false; +} + +void LiveValues::releaseMemory() { + Memos.clear(); +} + +/// isUsedInBlock - Test if the given value is used in the given block. +/// +bool LiveValues::isUsedInBlock(const Value *V, const BasicBlock *BB) { + Memo &M = getMemo(V); + return M.Used.count(BB); +} + +/// isLiveThroughBlock - Test if the given value is known to be +/// live-through the given block, meaning that the block is properly +/// dominated by the value's definition, and there exists a block +/// reachable from it that contains a use. This uses a conservative +/// approximation that errs on the side of returning false. +/// +bool LiveValues::isLiveThroughBlock(const Value *V, + const BasicBlock *BB) { + Memo &M = getMemo(V); + return M.LiveThrough.count(BB); +} + +/// isKilledInBlock - Test if the given value is known to be killed in +/// the given block, meaning that the block contains a use of the value, +/// and no blocks reachable from the block contain a use. This uses a +/// conservative approximation that errs on the side of returning false. +/// +bool LiveValues::isKilledInBlock(const Value *V, const BasicBlock *BB) { + Memo &M = getMemo(V); + return M.Killed.count(BB); +} + +/// getMemo - Retrieve an existing Memo for the given value if one +/// is available, otherwise compute a new one. +/// +LiveValues::Memo &LiveValues::getMemo(const Value *V) { + DenseMap::iterator I = Memos.find(V); + if (I != Memos.end()) + return I->second; + return compute(V); +} + +/// getImmediateDominator - A handy utility for the specific DominatorTree +/// query that we need here. +/// +static const BasicBlock *getImmediateDominator(const BasicBlock *BB, + const DominatorTree *DT) { + DomTreeNode *Node = DT->getNode(const_cast(BB))->getIDom(); + return Node ? Node->getBlock() : 0; +} + +/// compute - Compute a new Memo for the given value. +/// +LiveValues::Memo &LiveValues::compute(const Value *V) { + Memo &M = Memos[V]; + + // Determine the block containing the definition. + const BasicBlock *DefBB; + // Instructions define values with meaningful live ranges. + if (const Instruction *I = dyn_cast(V)) + DefBB = I->getParent(); + // Arguments can be analyzed as values defined in the entry block. + else if (const Argument *A = dyn_cast(V)) + DefBB = &A->getParent()->getEntryBlock(); + // Constants and other things aren't meaningful here, so just + // return having computed an empty Memo so that we don't come + // here again. The assumption here is that client code won't + // be asking about such values very often. + else + return M; + + // Determine if the value is defined inside a loop. This is used + // to track whether the value is ever used outside the loop, so + // it'll be set to null if the value is either not defined in a + // loop or used outside the loop in which it is defined. + const Loop *L = LI->getLoopFor(DefBB); + + // Track whether the value is used anywhere outside of the block + // in which it is defined. + bool LiveOutOfDefBB = false; + + // Examine each use of the value. + for (Value::use_const_iterator I = V->use_begin(), E = V->use_end(); + I != E; ++I) { + const User *U = *I; + const BasicBlock *UseBB = cast(U)->getParent(); + + // Note the block in which this use occurs. + M.Used.insert(UseBB); + + // If the use block doesn't have successors, the value can be + // considered killed. + if (succ_begin(UseBB) == succ_end(UseBB)) + M.Killed.insert(UseBB); + + // Observe whether the value is used outside of the loop in which + // it is defined. Switch to an enclosing loop if necessary. + for (; L; L = L->getParentLoop()) + if (L->contains(UseBB)) + break; + + // Search for live-through blocks. + const BasicBlock *BB; + if (const PHINode *PHI = dyn_cast(U)) { + // For PHI nodes, start the search at the incoming block paired with the + // incoming value, which must be dominated by the definition. + unsigned Num = PHI->getIncomingValueNumForOperand(I.getOperandNo()); + BB = PHI->getIncomingBlock(Num); + + // A PHI-node use means the value is live-out of it's defining block + // even if that block also contains the only use. + LiveOutOfDefBB = true; + } else { + // Otherwise just start the search at the use. + BB = UseBB; + + // Note if the use is outside the defining block. + LiveOutOfDefBB |= UseBB != DefBB; + } + + // Climb the immediate dominator tree from the use to the definition + // and mark all intermediate blocks as live-through. + for (; BB != DefBB; BB = getImmediateDominator(BB, DT)) { + if (BB != UseBB && !M.LiveThrough.insert(BB)) + break; + } + } + + // If the value is defined inside a loop and is not live outside + // the loop, then each exit block of the loop in which the value + // is used is a kill block. + if (L) { + SmallVector ExitingBlocks; + L->getExitingBlocks(ExitingBlocks); + for (unsigned i = 0, e = ExitingBlocks.size(); i != e; ++i) { + const BasicBlock *ExitingBlock = ExitingBlocks[i]; + if (M.Used.count(ExitingBlock)) + M.Killed.insert(ExitingBlock); + } + } + + // If the value was never used outside the the block in which it was + // defined, it's killed in that block. + if (!LiveOutOfDefBB) + M.Killed.insert(DefBB); + + return M; +} diff --git a/libclamav/c++/llvm/lib/Analysis/LoopDependenceAnalysis.cpp b/libclamav/c++/llvm/lib/Analysis/LoopDependenceAnalysis.cpp new file mode 100644 index 000000000..32d22662c --- /dev/null +++ b/libclamav/c++/llvm/lib/Analysis/LoopDependenceAnalysis.cpp @@ -0,0 +1,352 @@ +//===- LoopDependenceAnalysis.cpp - LDA Implementation ----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This is the (beginning) of an implementation of a loop dependence analysis +// framework, which is used to detect dependences in memory accesses in loops. +// +// Please note that this is work in progress and the interface is subject to +// change. +// +// TODO: adapt as implementation progresses. +// +// TODO: document lingo (pair, subscript, index) +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "lda" +#include "llvm/ADT/DenseSet.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/Analysis/LoopDependenceAnalysis.h" +#include "llvm/Analysis/LoopPass.h" +#include "llvm/Analysis/ScalarEvolution.h" +#include "llvm/Analysis/ScalarEvolutionExpressions.h" +#include "llvm/Instructions.h" +#include "llvm/Operator.h" +#include "llvm/Support/Allocator.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Target/TargetData.h" +using namespace llvm; + +STATISTIC(NumAnswered, "Number of dependence queries answered"); +STATISTIC(NumAnalysed, "Number of distinct dependence pairs analysed"); +STATISTIC(NumDependent, "Number of pairs with dependent accesses"); +STATISTIC(NumIndependent, "Number of pairs with independent accesses"); +STATISTIC(NumUnknown, "Number of pairs with unknown accesses"); + +LoopPass *llvm::createLoopDependenceAnalysisPass() { + return new LoopDependenceAnalysis(); +} + +static RegisterPass +R("lda", "Loop Dependence Analysis", false, true); +char LoopDependenceAnalysis::ID = 0; + +//===----------------------------------------------------------------------===// +// Utility Functions +//===----------------------------------------------------------------------===// + +static inline bool IsMemRefInstr(const Value *V) { + const Instruction *I = dyn_cast(V); + return I && (I->mayReadFromMemory() || I->mayWriteToMemory()); +} + +static void GetMemRefInstrs(const Loop *L, + SmallVectorImpl &Memrefs) { + for (Loop::block_iterator b = L->block_begin(), be = L->block_end(); + b != be; ++b) + for (BasicBlock::iterator i = (*b)->begin(), ie = (*b)->end(); + i != ie; ++i) + if (IsMemRefInstr(i)) + Memrefs.push_back(i); +} + +static bool IsLoadOrStoreInst(Value *I) { + return isa(I) || isa(I); +} + +static Value *GetPointerOperand(Value *I) { + if (LoadInst *i = dyn_cast(I)) + return i->getPointerOperand(); + if (StoreInst *i = dyn_cast(I)) + return i->getPointerOperand(); + llvm_unreachable("Value is no load or store instruction!"); + // Never reached. + return 0; +} + +static AliasAnalysis::AliasResult UnderlyingObjectsAlias(AliasAnalysis *AA, + const Value *A, + const Value *B) { + const Value *aObj = A->getUnderlyingObject(); + const Value *bObj = B->getUnderlyingObject(); + return AA->alias(aObj, AA->getTypeStoreSize(aObj->getType()), + bObj, AA->getTypeStoreSize(bObj->getType())); +} + +static inline const SCEV *GetZeroSCEV(ScalarEvolution *SE) { + return SE->getConstant(Type::getInt32Ty(SE->getContext()), 0L); +} + +//===----------------------------------------------------------------------===// +// Dependence Testing +//===----------------------------------------------------------------------===// + +bool LoopDependenceAnalysis::isDependencePair(const Value *A, + const Value *B) const { + return IsMemRefInstr(A) && + IsMemRefInstr(B) && + (cast(A)->mayWriteToMemory() || + cast(B)->mayWriteToMemory()); +} + +bool LoopDependenceAnalysis::findOrInsertDependencePair(Value *A, + Value *B, + DependencePair *&P) { + void *insertPos = 0; + FoldingSetNodeID id; + id.AddPointer(A); + id.AddPointer(B); + + P = Pairs.FindNodeOrInsertPos(id, insertPos); + if (P) return true; + + P = PairAllocator.Allocate(); + new (P) DependencePair(id, A, B); + Pairs.InsertNode(P, insertPos); + return false; +} + +void LoopDependenceAnalysis::getLoops(const SCEV *S, + DenseSet* Loops) const { + // Refactor this into an SCEVVisitor, if efficiency becomes a concern. + for (const Loop *L = this->L; L != 0; L = L->getParentLoop()) + if (!S->isLoopInvariant(L)) + Loops->insert(L); +} + +bool LoopDependenceAnalysis::isLoopInvariant(const SCEV *S) const { + DenseSet loops; + getLoops(S, &loops); + return loops.empty(); +} + +bool LoopDependenceAnalysis::isAffine(const SCEV *S) const { + const SCEVAddRecExpr *rec = dyn_cast(S); + return isLoopInvariant(S) || (rec && rec->isAffine()); +} + +bool LoopDependenceAnalysis::isZIVPair(const SCEV *A, const SCEV *B) const { + return isLoopInvariant(A) && isLoopInvariant(B); +} + +bool LoopDependenceAnalysis::isSIVPair(const SCEV *A, const SCEV *B) const { + DenseSet loops; + getLoops(A, &loops); + getLoops(B, &loops); + return loops.size() == 1; +} + +LoopDependenceAnalysis::DependenceResult +LoopDependenceAnalysis::analyseZIV(const SCEV *A, + const SCEV *B, + Subscript *S) const { + assert(isZIVPair(A, B) && "Attempted to ZIV-test non-ZIV SCEVs!"); + return A == B ? Dependent : Independent; +} + +LoopDependenceAnalysis::DependenceResult +LoopDependenceAnalysis::analyseSIV(const SCEV *A, + const SCEV *B, + Subscript *S) const { + return Unknown; // TODO: Implement. +} + +LoopDependenceAnalysis::DependenceResult +LoopDependenceAnalysis::analyseMIV(const SCEV *A, + const SCEV *B, + Subscript *S) const { + return Unknown; // TODO: Implement. +} + +LoopDependenceAnalysis::DependenceResult +LoopDependenceAnalysis::analyseSubscript(const SCEV *A, + const SCEV *B, + Subscript *S) const { + DEBUG(errs() << " Testing subscript: " << *A << ", " << *B << "\n"); + + if (A == B) { + DEBUG(errs() << " -> [D] same SCEV\n"); + return Dependent; + } + + if (!isAffine(A) || !isAffine(B)) { + DEBUG(errs() << " -> [?] not affine\n"); + return Unknown; + } + + if (isZIVPair(A, B)) + return analyseZIV(A, B, S); + + if (isSIVPair(A, B)) + return analyseSIV(A, B, S); + + return analyseMIV(A, B, S); +} + +LoopDependenceAnalysis::DependenceResult +LoopDependenceAnalysis::analysePair(DependencePair *P) const { + DEBUG(errs() << "Analysing:\n" << *P->A << "\n" << *P->B << "\n"); + + // We only analyse loads and stores but no possible memory accesses by e.g. + // free, call, or invoke instructions. + if (!IsLoadOrStoreInst(P->A) || !IsLoadOrStoreInst(P->B)) { + DEBUG(errs() << "--> [?] no load/store\n"); + return Unknown; + } + + Value *aPtr = GetPointerOperand(P->A); + Value *bPtr = GetPointerOperand(P->B); + + switch (UnderlyingObjectsAlias(AA, aPtr, bPtr)) { + case AliasAnalysis::MayAlias: + // We can not analyse objects if we do not know about their aliasing. + DEBUG(errs() << "---> [?] may alias\n"); + return Unknown; + + case AliasAnalysis::NoAlias: + // If the objects noalias, they are distinct, accesses are independent. + DEBUG(errs() << "---> [I] no alias\n"); + return Independent; + + case AliasAnalysis::MustAlias: + break; // The underlying objects alias, test accesses for dependence. + } + + const GEPOperator *aGEP = dyn_cast(aPtr); + const GEPOperator *bGEP = dyn_cast(bPtr); + + if (!aGEP || !bGEP) + return Unknown; + + // FIXME: Is filtering coupled subscripts necessary? + + // Collect GEP operand pairs (FIXME: use GetGEPOperands from BasicAA), adding + // trailing zeroes to the smaller GEP, if needed. + typedef SmallVector, 4> GEPOpdPairsTy; + GEPOpdPairsTy opds; + for(GEPOperator::const_op_iterator aIdx = aGEP->idx_begin(), + aEnd = aGEP->idx_end(), + bIdx = bGEP->idx_begin(), + bEnd = bGEP->idx_end(); + aIdx != aEnd && bIdx != bEnd; + aIdx += (aIdx != aEnd), bIdx += (bIdx != bEnd)) { + const SCEV* aSCEV = (aIdx != aEnd) ? SE->getSCEV(*aIdx) : GetZeroSCEV(SE); + const SCEV* bSCEV = (bIdx != bEnd) ? SE->getSCEV(*bIdx) : GetZeroSCEV(SE); + opds.push_back(std::make_pair(aSCEV, bSCEV)); + } + + if (!opds.empty() && opds[0].first != opds[0].second) { + // We cannot (yet) handle arbitrary GEP pointer offsets. By limiting + // + // TODO: this could be relaxed by adding the size of the underlying object + // to the first subscript. If we have e.g. (GEP x,0,i; GEP x,2,-i) and we + // know that x is a [100 x i8]*, we could modify the first subscript to be + // (i, 200-i) instead of (i, -i). + return Unknown; + } + + // Now analyse the collected operand pairs (skipping the GEP ptr offsets). + for (GEPOpdPairsTy::const_iterator i = opds.begin() + 1, end = opds.end(); + i != end; ++i) { + Subscript subscript; + DependenceResult result = analyseSubscript(i->first, i->second, &subscript); + if (result != Dependent) { + // We either proved independence or failed to analyse this subscript. + // Further subscripts will not improve the situation, so abort early. + return result; + } + P->Subscripts.push_back(subscript); + } + // We successfully analysed all subscripts but failed to prove independence. + return Dependent; +} + +bool LoopDependenceAnalysis::depends(Value *A, Value *B) { + assert(isDependencePair(A, B) && "Values form no dependence pair!"); + ++NumAnswered; + + DependencePair *p; + if (!findOrInsertDependencePair(A, B, p)) { + // The pair is not cached, so analyse it. + ++NumAnalysed; + switch (p->Result = analysePair(p)) { + case Dependent: ++NumDependent; break; + case Independent: ++NumIndependent; break; + case Unknown: ++NumUnknown; break; + } + } + return p->Result != Independent; +} + +//===----------------------------------------------------------------------===// +// LoopDependenceAnalysis Implementation +//===----------------------------------------------------------------------===// + +bool LoopDependenceAnalysis::runOnLoop(Loop *L, LPPassManager &) { + this->L = L; + AA = &getAnalysis(); + SE = &getAnalysis(); + return false; +} + +void LoopDependenceAnalysis::releaseMemory() { + Pairs.clear(); + PairAllocator.Reset(); +} + +void LoopDependenceAnalysis::getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + AU.addRequiredTransitive(); + AU.addRequiredTransitive(); +} + +static void PrintLoopInfo(raw_ostream &OS, + LoopDependenceAnalysis *LDA, const Loop *L) { + if (!L->empty()) return; // ignore non-innermost loops + + SmallVector memrefs; + GetMemRefInstrs(L, memrefs); + + OS << "Loop at depth " << L->getLoopDepth() << ", header block: "; + WriteAsOperand(OS, L->getHeader(), false); + OS << "\n"; + + OS << " Load/store instructions: " << memrefs.size() << "\n"; + for (SmallVector::const_iterator x = memrefs.begin(), + end = memrefs.end(); x != end; ++x) + OS << "\t" << (x - memrefs.begin()) << ": " << **x << "\n"; + + OS << " Pairwise dependence results:\n"; + for (SmallVector::const_iterator x = memrefs.begin(), + end = memrefs.end(); x != end; ++x) + for (SmallVector::const_iterator y = x + 1; + y != end; ++y) + if (LDA->isDependencePair(*x, *y)) + OS << "\t" << (x - memrefs.begin()) << "," << (y - memrefs.begin()) + << ": " << (LDA->depends(*x, *y) ? "dependent" : "independent") + << "\n"; +} + +void LoopDependenceAnalysis::print(raw_ostream &OS, const Module*) const { + // TODO: doc why const_cast is safe + PrintLoopInfo(OS, const_cast(this), this->L); +} diff --git a/libclamav/c++/llvm/lib/Analysis/LoopInfo.cpp b/libclamav/c++/llvm/lib/Analysis/LoopInfo.cpp new file mode 100644 index 000000000..4de756c41 --- /dev/null +++ b/libclamav/c++/llvm/lib/Analysis/LoopInfo.cpp @@ -0,0 +1,422 @@ +//===- LoopInfo.cpp - Natural Loop Calculator -----------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the LoopInfo class that is used to identify natural loops +// and determine the loop depth of various nodes of the CFG. Note that the +// loops identified may actually be several natural loops that share the same +// header node... not just a single natural loop. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Analysis/LoopInfo.h" +#include "llvm/Constants.h" +#include "llvm/Instructions.h" +#include "llvm/Analysis/Dominators.h" +#include "llvm/Assembly/Writer.h" +#include "llvm/Support/CFG.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/ADT/DepthFirstIterator.h" +#include "llvm/ADT/SmallPtrSet.h" +#include +using namespace llvm; + +// Always verify loopinfo if expensive checking is enabled. +#ifdef XDEBUG +bool VerifyLoopInfo = true; +#else +bool VerifyLoopInfo = false; +#endif +static cl::opt +VerifyLoopInfoX("verify-loop-info", cl::location(VerifyLoopInfo), + cl::desc("Verify loop info (time consuming)")); + +char LoopInfo::ID = 0; +static RegisterPass +X("loops", "Natural Loop Information", true, true); + +//===----------------------------------------------------------------------===// +// Loop implementation +// + +/// isLoopInvariant - Return true if the specified value is loop invariant +/// +bool Loop::isLoopInvariant(Value *V) const { + if (Instruction *I = dyn_cast(V)) + return isLoopInvariant(I); + return true; // All non-instructions are loop invariant +} + +/// isLoopInvariant - Return true if the specified instruction is +/// loop-invariant. +/// +bool Loop::isLoopInvariant(Instruction *I) const { + return !contains(I->getParent()); +} + +/// makeLoopInvariant - If the given value is an instruciton inside of the +/// loop and it can be hoisted, do so to make it trivially loop-invariant. +/// Return true if the value after any hoisting is loop invariant. This +/// function can be used as a slightly more aggressive replacement for +/// isLoopInvariant. +/// +/// If InsertPt is specified, it is the point to hoist instructions to. +/// If null, the terminator of the loop preheader is used. +/// +bool Loop::makeLoopInvariant(Value *V, bool &Changed, + Instruction *InsertPt) const { + if (Instruction *I = dyn_cast(V)) + return makeLoopInvariant(I, Changed, InsertPt); + return true; // All non-instructions are loop-invariant. +} + +/// makeLoopInvariant - If the given instruction is inside of the +/// loop and it can be hoisted, do so to make it trivially loop-invariant. +/// Return true if the instruction after any hoisting is loop invariant. This +/// function can be used as a slightly more aggressive replacement for +/// isLoopInvariant. +/// +/// If InsertPt is specified, it is the point to hoist instructions to. +/// If null, the terminator of the loop preheader is used. +/// +bool Loop::makeLoopInvariant(Instruction *I, bool &Changed, + Instruction *InsertPt) const { + // Test if the value is already loop-invariant. + if (isLoopInvariant(I)) + return true; + if (!I->isSafeToSpeculativelyExecute()) + return false; + if (I->mayReadFromMemory()) + return false; + // Determine the insertion point, unless one was given. + if (!InsertPt) { + BasicBlock *Preheader = getLoopPreheader(); + // Without a preheader, hoisting is not feasible. + if (!Preheader) + return false; + InsertPt = Preheader->getTerminator(); + } + // Don't hoist instructions with loop-variant operands. + for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i) + if (!makeLoopInvariant(I->getOperand(i), Changed, InsertPt)) + return false; + // Hoist. + I->moveBefore(InsertPt); + Changed = true; + return true; +} + +/// getCanonicalInductionVariable - Check to see if the loop has a canonical +/// induction variable: an integer recurrence that starts at 0 and increments +/// by one each time through the loop. If so, return the phi node that +/// corresponds to it. +/// +/// The IndVarSimplify pass transforms loops to have a canonical induction +/// variable. +/// +PHINode *Loop::getCanonicalInductionVariable() const { + BasicBlock *H = getHeader(); + + BasicBlock *Incoming = 0, *Backedge = 0; + typedef GraphTraits > InvBlockTraits; + InvBlockTraits::ChildIteratorType PI = InvBlockTraits::child_begin(H); + assert(PI != InvBlockTraits::child_end(H) && + "Loop must have at least one backedge!"); + Backedge = *PI++; + if (PI == InvBlockTraits::child_end(H)) return 0; // dead loop + Incoming = *PI++; + if (PI != InvBlockTraits::child_end(H)) return 0; // multiple backedges? + + if (contains(Incoming)) { + if (contains(Backedge)) + return 0; + std::swap(Incoming, Backedge); + } else if (!contains(Backedge)) + return 0; + + // Loop over all of the PHI nodes, looking for a canonical indvar. + for (BasicBlock::iterator I = H->begin(); isa(I); ++I) { + PHINode *PN = cast(I); + if (ConstantInt *CI = + dyn_cast(PN->getIncomingValueForBlock(Incoming))) + if (CI->isNullValue()) + if (Instruction *Inc = + dyn_cast(PN->getIncomingValueForBlock(Backedge))) + if (Inc->getOpcode() == Instruction::Add && + Inc->getOperand(0) == PN) + if (ConstantInt *CI = dyn_cast(Inc->getOperand(1))) + if (CI->equalsInt(1)) + return PN; + } + return 0; +} + +/// getCanonicalInductionVariableIncrement - Return the LLVM value that holds +/// the canonical induction variable value for the "next" iteration of the +/// loop. This always succeeds if getCanonicalInductionVariable succeeds. +/// +Instruction *Loop::getCanonicalInductionVariableIncrement() const { + if (PHINode *PN = getCanonicalInductionVariable()) { + bool P1InLoop = contains(PN->getIncomingBlock(1)); + return cast(PN->getIncomingValue(P1InLoop)); + } + return 0; +} + +/// getTripCount - Return a loop-invariant LLVM value indicating the number of +/// times the loop will be executed. Note that this means that the backedge +/// of the loop executes N-1 times. If the trip-count cannot be determined, +/// this returns null. +/// +/// The IndVarSimplify pass transforms loops to have a form that this +/// function easily understands. +/// +Value *Loop::getTripCount() const { + // Canonical loops will end with a 'cmp ne I, V', where I is the incremented + // canonical induction variable and V is the trip count of the loop. + Instruction *Inc = getCanonicalInductionVariableIncrement(); + if (Inc == 0) return 0; + PHINode *IV = cast(Inc->getOperand(0)); + + BasicBlock *BackedgeBlock = + IV->getIncomingBlock(contains(IV->getIncomingBlock(1))); + + if (BranchInst *BI = dyn_cast(BackedgeBlock->getTerminator())) + if (BI->isConditional()) { + if (ICmpInst *ICI = dyn_cast(BI->getCondition())) { + if (ICI->getOperand(0) == Inc) { + if (BI->getSuccessor(0) == getHeader()) { + if (ICI->getPredicate() == ICmpInst::ICMP_NE) + return ICI->getOperand(1); + } else if (ICI->getPredicate() == ICmpInst::ICMP_EQ) { + return ICI->getOperand(1); + } + } + } + } + + return 0; +} + +/// getSmallConstantTripCount - Returns the trip count of this loop as a +/// normal unsigned value, if possible. Returns 0 if the trip count is unknown +/// of not constant. Will also return 0 if the trip count is very large +/// (>= 2^32) +unsigned Loop::getSmallConstantTripCount() const { + Value* TripCount = this->getTripCount(); + if (TripCount) { + if (ConstantInt *TripCountC = dyn_cast(TripCount)) { + // Guard against huge trip counts. + if (TripCountC->getValue().getActiveBits() <= 32) { + return (unsigned)TripCountC->getZExtValue(); + } + } + } + return 0; +} + +/// 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!). +/// +/// Returns 1 if the trip count is unknown or not guaranteed to be the +/// multiple of a constant (which is also the case if the trip count is simply +/// constant, use getSmallConstantTripCount for that case), Will also return 1 +/// if the trip count is very large (>= 2^32). +unsigned Loop::getSmallConstantTripMultiple() const { + Value* TripCount = this->getTripCount(); + // This will hold the ConstantInt result, if any + ConstantInt *Result = NULL; + if (TripCount) { + // See if the trip count is constant itself + Result = dyn_cast(TripCount); + // if not, see if it is a multiplication + if (!Result) + if (BinaryOperator *BO = dyn_cast(TripCount)) { + switch (BO->getOpcode()) { + case BinaryOperator::Mul: + Result = dyn_cast(BO->getOperand(1)); + break; + case BinaryOperator::Shl: + if (ConstantInt *CI = dyn_cast(BO->getOperand(1))) + if (CI->getValue().getActiveBits() <= 5) + return 1u << CI->getZExtValue(); + break; + default: + break; + } + } + } + // Guard against huge trip counts. + if (Result && Result->getValue().getActiveBits() <= 32) { + return (unsigned)Result->getZExtValue(); + } else { + return 1; + } +} + +/// isLCSSAForm - Return true if the Loop is in LCSSA form +bool Loop::isLCSSAForm() const { + // Sort the blocks vector so that we can use binary search to do quick + // lookups. + SmallPtrSet LoopBBs(block_begin(), block_end()); + + for (block_iterator BI = block_begin(), E = block_end(); BI != E; ++BI) { + BasicBlock *BB = *BI; + for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E;++I) + for (Value::use_iterator UI = I->use_begin(), E = I->use_end(); UI != E; + ++UI) { + BasicBlock *UserBB = cast(*UI)->getParent(); + if (PHINode *P = dyn_cast(*UI)) + UserBB = P->getIncomingBlock(UI); + + // Check the current block, as a fast-path. Most values are used in + // the same block they are defined in. + if (UserBB != BB && !LoopBBs.count(UserBB)) + return false; + } + } + + return true; +} + +/// isLoopSimplifyForm - Return true if the Loop is in the form that +/// the LoopSimplify form transforms loops to, which is sometimes called +/// normal form. +bool Loop::isLoopSimplifyForm() const { + // Normal-form loops have a preheader, a single backedge, and all of their + // exits have all their predecessors inside the loop. + return getLoopPreheader() && getLoopLatch() && hasDedicatedExits(); +} + +/// hasDedicatedExits - Return true if no exit block for the loop +/// has a predecessor that is outside the loop. +bool Loop::hasDedicatedExits() const { + // Sort the blocks vector so that we can use binary search to do quick + // lookups. + SmallPtrSet LoopBBs(block_begin(), block_end()); + // Each predecessor of each exit block of a normal loop is contained + // within the loop. + SmallVector ExitBlocks; + getExitBlocks(ExitBlocks); + for (unsigned i = 0, e = ExitBlocks.size(); i != e; ++i) + for (pred_iterator PI = pred_begin(ExitBlocks[i]), + PE = pred_end(ExitBlocks[i]); PI != PE; ++PI) + if (!LoopBBs.count(*PI)) + return false; + // All the requirements are met. + return true; +} + +/// getUniqueExitBlocks - Return all unique successor blocks of this loop. +/// These are the blocks _outside of the current loop_ which are branched to. +/// This assumes that loop is in canonical form. +/// +void +Loop::getUniqueExitBlocks(SmallVectorImpl &ExitBlocks) const { + assert(isLoopSimplifyForm() && + "getUniqueExitBlocks assumes the loop is in canonical form!"); + + // Sort the blocks vector so that we can use binary search to do quick + // lookups. + SmallVector LoopBBs(block_begin(), block_end()); + std::sort(LoopBBs.begin(), LoopBBs.end()); + + SmallVector switchExitBlocks; + + for (block_iterator BI = block_begin(), BE = block_end(); BI != BE; ++BI) { + + BasicBlock *current = *BI; + switchExitBlocks.clear(); + + typedef GraphTraits BlockTraits; + typedef GraphTraits > InvBlockTraits; + for (BlockTraits::ChildIteratorType I = + BlockTraits::child_begin(*BI), E = BlockTraits::child_end(*BI); + I != E; ++I) { + // If block is inside the loop then it is not a exit block. + if (std::binary_search(LoopBBs.begin(), LoopBBs.end(), *I)) + continue; + + InvBlockTraits::ChildIteratorType PI = InvBlockTraits::child_begin(*I); + BasicBlock *firstPred = *PI; + + // If current basic block is this exit block's first predecessor + // then only insert exit block in to the output ExitBlocks vector. + // This ensures that same exit block is not inserted twice into + // ExitBlocks vector. + if (current != firstPred) + continue; + + // If a terminator has more then two successors, for example SwitchInst, + // then it is possible that there are multiple edges from current block + // to one exit block. + if (std::distance(BlockTraits::child_begin(current), + BlockTraits::child_end(current)) <= 2) { + ExitBlocks.push_back(*I); + continue; + } + + // In case of multiple edges from current block to exit block, collect + // only one edge in ExitBlocks. Use switchExitBlocks to keep track of + // duplicate edges. + if (std::find(switchExitBlocks.begin(), switchExitBlocks.end(), *I) + == switchExitBlocks.end()) { + switchExitBlocks.push_back(*I); + ExitBlocks.push_back(*I); + } + } + } +} + +/// getUniqueExitBlock - If getUniqueExitBlocks would return exactly one +/// block, return that block. Otherwise return null. +BasicBlock *Loop::getUniqueExitBlock() const { + SmallVector UniqueExitBlocks; + getUniqueExitBlocks(UniqueExitBlocks); + if (UniqueExitBlocks.size() == 1) + return UniqueExitBlocks[0]; + return 0; +} + +//===----------------------------------------------------------------------===// +// LoopInfo implementation +// +bool LoopInfo::runOnFunction(Function &) { + releaseMemory(); + LI.Calculate(getAnalysis().getBase()); // Update + return false; +} + +void LoopInfo::verifyAnalysis() const { + // LoopInfo is a FunctionPass, but verifying every loop in the function + // each time verifyAnalysis is called is very expensive. The + // -verify-loop-info option can enable this. In order to perform some + // checking by default, LoopPass has been taught to call verifyLoop + // manually during loop pass sequences. + + if (!VerifyLoopInfo) return; + + for (iterator I = begin(), E = end(); I != E; ++I) { + assert(!(*I)->getParentLoop() && "Top-level loop has a parent!"); + (*I)->verifyLoopNest(); + } + + // TODO: check BBMap consistency. +} + +void LoopInfo::getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + AU.addRequired(); +} + +void LoopInfo::print(raw_ostream &OS, const Module*) const { + LI.print(OS); +} + diff --git a/libclamav/c++/llvm/lib/Analysis/LoopPass.cpp b/libclamav/c++/llvm/lib/Analysis/LoopPass.cpp new file mode 100644 index 000000000..43463cd8e --- /dev/null +++ b/libclamav/c++/llvm/lib/Analysis/LoopPass.cpp @@ -0,0 +1,371 @@ +//===- LoopPass.cpp - Loop Pass and Loop Pass Manager ---------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements LoopPass and LPPassManager. All loop optimization +// and transformation passes are derived from LoopPass. LPPassManager is +// responsible for managing LoopPasses. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Analysis/LoopPass.h" +using namespace llvm; + +//===----------------------------------------------------------------------===// +// LPPassManager +// + +char LPPassManager::ID = 0; + +LPPassManager::LPPassManager(int Depth) + : FunctionPass(&ID), PMDataManager(Depth) { + skipThisLoop = false; + redoThisLoop = false; + LI = NULL; + CurrentLoop = NULL; +} + +/// Delete loop from the loop queue and loop hierarchy (LoopInfo). +void LPPassManager::deleteLoopFromQueue(Loop *L) { + + if (Loop *ParentLoop = L->getParentLoop()) { // Not a top-level loop. + // Reparent all of the blocks in this loop. Since BBLoop had a parent, + // they are now all in it. + for (Loop::block_iterator I = L->block_begin(), E = L->block_end(); + I != E; ++I) + if (LI->getLoopFor(*I) == L) // Don't change blocks in subloops. + LI->changeLoopFor(*I, ParentLoop); + + // Remove the loop from its parent loop. + for (Loop::iterator I = ParentLoop->begin(), E = ParentLoop->end();; + ++I) { + assert(I != E && "Couldn't find loop"); + if (*I == L) { + ParentLoop->removeChildLoop(I); + break; + } + } + + // Move all subloops into the parent loop. + while (!L->empty()) + ParentLoop->addChildLoop(L->removeChildLoop(L->end()-1)); + } else { + // Reparent all of the blocks in this loop. Since BBLoop had no parent, + // they no longer in a loop at all. + + for (unsigned i = 0; i != L->getBlocks().size(); ++i) { + // Don't change blocks in subloops. + if (LI->getLoopFor(L->getBlocks()[i]) == L) { + LI->removeBlock(L->getBlocks()[i]); + --i; + } + } + + // Remove the loop from the top-level LoopInfo object. + for (LoopInfo::iterator I = LI->begin(), E = LI->end();; ++I) { + assert(I != E && "Couldn't find loop"); + if (*I == L) { + LI->removeLoop(I); + break; + } + } + + // Move all of the subloops to the top-level. + while (!L->empty()) + LI->addTopLevelLoop(L->removeChildLoop(L->end()-1)); + } + + delete L; + + // If L is current loop then skip rest of the passes and let + // runOnFunction remove L from LQ. Otherwise, remove L from LQ now + // and continue applying other passes on CurrentLoop. + if (CurrentLoop == L) { + skipThisLoop = true; + return; + } + + for (std::deque::iterator I = LQ.begin(), + E = LQ.end(); I != E; ++I) { + if (*I == L) { + LQ.erase(I); + break; + } + } +} + +// Inset loop into loop nest (LoopInfo) and loop queue (LQ). +void LPPassManager::insertLoop(Loop *L, Loop *ParentLoop) { + + assert (CurrentLoop != L && "Cannot insert CurrentLoop"); + + // Insert into loop nest + if (ParentLoop) + ParentLoop->addChildLoop(L); + else + LI->addTopLevelLoop(L); + + insertLoopIntoQueue(L); +} + +void LPPassManager::insertLoopIntoQueue(Loop *L) { + // Insert L into loop queue + if (L == CurrentLoop) + redoLoop(L); + else if (!L->getParentLoop()) + // This is top level loop. + LQ.push_front(L); + else { + // Insert L after the parent loop. + for (std::deque::iterator I = LQ.begin(), + E = LQ.end(); I != E; ++I) { + if (*I == L->getParentLoop()) { + // deque does not support insert after. + ++I; + LQ.insert(I, 1, L); + break; + } + } + } +} + +// Reoptimize this loop. LPPassManager will re-insert this loop into the +// queue. This allows LoopPass to change loop nest for the loop. This +// utility may send LPPassManager into infinite loops so use caution. +void LPPassManager::redoLoop(Loop *L) { + assert (CurrentLoop == L && "Can redo only CurrentLoop"); + redoThisLoop = true; +} + +/// cloneBasicBlockSimpleAnalysis - Invoke cloneBasicBlockAnalysis hook for +/// all loop passes. +void LPPassManager::cloneBasicBlockSimpleAnalysis(BasicBlock *From, + BasicBlock *To, Loop *L) { + for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) { + Pass *P = getContainedPass(Index); + LoopPass *LP = dynamic_cast(P); + LP->cloneBasicBlockAnalysis(From, To, L); + } +} + +/// deleteSimpleAnalysisValue - Invoke deleteAnalysisValue hook for all passes. +void LPPassManager::deleteSimpleAnalysisValue(Value *V, Loop *L) { + if (BasicBlock *BB = dyn_cast(V)) { + for (BasicBlock::iterator BI = BB->begin(), BE = BB->end(); BI != BE; + ++BI) { + Instruction &I = *BI; + deleteSimpleAnalysisValue(&I, L); + } + } + for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) { + Pass *P = getContainedPass(Index); + LoopPass *LP = dynamic_cast(P); + LP->deleteAnalysisValue(V, L); + } +} + + +// Recurse through all subloops and all loops into LQ. +static void addLoopIntoQueue(Loop *L, std::deque &LQ) { + LQ.push_back(L); + for (Loop::iterator I = L->begin(), E = L->end(); I != E; ++I) + addLoopIntoQueue(*I, LQ); +} + +/// Pass Manager itself does not invalidate any analysis info. +void LPPassManager::getAnalysisUsage(AnalysisUsage &Info) const { + // LPPassManager needs LoopInfo. In the long term LoopInfo class will + // become part of LPPassManager. + Info.addRequired(); + Info.setPreservesAll(); +} + +/// run - Execute all of the passes scheduled for execution. Keep track of +/// whether any of the passes modifies the function, and if so, return true. +bool LPPassManager::runOnFunction(Function &F) { + LI = &getAnalysis(); + bool Changed = false; + + // Collect inherited analysis from Module level pass manager. + populateInheritedAnalysis(TPM->activeStack); + + // Populate Loop Queue + for (LoopInfo::iterator I = LI->begin(), E = LI->end(); I != E; ++I) + addLoopIntoQueue(*I, LQ); + + if (LQ.empty()) // No loops, skip calling finalizers + return false; + + // Initialization + for (std::deque::const_iterator I = LQ.begin(), E = LQ.end(); + I != E; ++I) { + Loop *L = *I; + for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) { + Pass *P = getContainedPass(Index); + LoopPass *LP = dynamic_cast(P); + if (LP) + Changed |= LP->doInitialization(L, *this); + } + } + + // Walk Loops + while (!LQ.empty()) { + + CurrentLoop = LQ.back(); + skipThisLoop = false; + redoThisLoop = false; + + // Run all passes on the current Loop. + for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) { + Pass *P = getContainedPass(Index); + + dumpPassInfo(P, EXECUTION_MSG, ON_LOOP_MSG, + CurrentLoop->getHeader()->getNameStr()); + dumpRequiredSet(P); + + initializeAnalysisImpl(P); + + LoopPass *LP = dynamic_cast(P); + assert(LP && "Invalid LPPassManager member"); + { + PassManagerPrettyStackEntry X(LP, *CurrentLoop->getHeader()); + Timer *T = StartPassTimer(P); + Changed |= LP->runOnLoop(CurrentLoop, *this); + StopPassTimer(P, T); + } + + if (Changed) + dumpPassInfo(P, MODIFICATION_MSG, ON_LOOP_MSG, + skipThisLoop ? "" : + CurrentLoop->getHeader()->getNameStr()); + dumpPreservedSet(P); + + if (!skipThisLoop) { + // Manually check that this loop is still healthy. This is done + // instead of relying on LoopInfo::verifyLoop since LoopInfo + // is a function pass and it's really expensive to verify every + // loop in the function every time. That level of checking can be + // enabled with the -verify-loop-info option. + Timer *T = StartPassTimer(LI); + CurrentLoop->verifyLoop(); + StopPassTimer(LI, T); + + // Then call the regular verifyAnalysis functions. + verifyPreservedAnalysis(LP); + } + + removeNotPreservedAnalysis(P); + recordAvailableAnalysis(P); + removeDeadPasses(P, + skipThisLoop ? "" : + CurrentLoop->getHeader()->getNameStr(), + ON_LOOP_MSG); + + if (skipThisLoop) + // Do not run other passes on this loop. + break; + } + + // If the loop was deleted, release all the loop passes. This frees up + // some memory, and avoids trouble with the pass manager trying to call + // verifyAnalysis on them. + if (skipThisLoop) + for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) { + Pass *P = getContainedPass(Index); + freePass(P, "", ON_LOOP_MSG); + } + + // Pop the loop from queue after running all passes. + LQ.pop_back(); + + if (redoThisLoop) + LQ.push_back(CurrentLoop); + } + + // Finalization + for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) { + Pass *P = getContainedPass(Index); + LoopPass *LP = dynamic_cast (P); + if (LP) + Changed |= LP->doFinalization(); + } + + return Changed; +} + +/// Print passes managed by this manager +void LPPassManager::dumpPassStructure(unsigned Offset) { + errs().indent(Offset*2) << "Loop Pass Manager\n"; + for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) { + Pass *P = getContainedPass(Index); + P->dumpPassStructure(Offset + 1); + dumpLastUses(P, Offset+1); + } +} + + +//===----------------------------------------------------------------------===// +// LoopPass + +// Check if this pass is suitable for the current LPPassManager, if +// available. This pass P is not suitable for a LPPassManager if P +// is not preserving higher level analysis info used by other +// LPPassManager passes. In such case, pop LPPassManager from the +// stack. This will force assignPassManager() to create new +// LPPassManger as expected. +void LoopPass::preparePassManager(PMStack &PMS) { + + // Find LPPassManager + while (!PMS.empty() && + PMS.top()->getPassManagerType() > PMT_LoopPassManager) + PMS.pop(); + + LPPassManager *LPPM = dynamic_cast(PMS.top()); + + // If this pass is destroying high level information that is used + // by other passes that are managed by LPM then do not insert + // this pass in current LPM. Use new LPPassManager. + if (LPPM && !LPPM->preserveHigherLevelAnalysis(this)) + PMS.pop(); +} + +/// Assign pass manager to manage this pass. +void LoopPass::assignPassManager(PMStack &PMS, + PassManagerType PreferredType) { + // Find LPPassManager + while (!PMS.empty() && + PMS.top()->getPassManagerType() > PMT_LoopPassManager) + PMS.pop(); + + LPPassManager *LPPM = dynamic_cast(PMS.top()); + + // Create new Loop Pass Manager if it does not exist. + if (!LPPM) { + + assert (!PMS.empty() && "Unable to create Loop Pass Manager"); + PMDataManager *PMD = PMS.top(); + + // [1] Create new Call Graph Pass Manager + LPPM = new LPPassManager(PMD->getDepth() + 1); + LPPM->populateInheritedAnalysis(PMS); + + // [2] Set up new manager's top level manager + PMTopLevelManager *TPM = PMD->getTopLevelManager(); + TPM->addIndirectPassManager(LPPM); + + // [3] Assign manager to manage this new manager. This may create + // and push new managers into PMS + Pass *P = dynamic_cast(LPPM); + TPM->schedulePass(P); + + // [4] Push new manager into PMS + PMS.push(LPPM); + } + + LPPM->add(this); +} diff --git a/libclamav/c++/llvm/lib/Analysis/Makefile b/libclamav/c++/llvm/lib/Analysis/Makefile new file mode 100644 index 000000000..4af6d350a --- /dev/null +++ b/libclamav/c++/llvm/lib/Analysis/Makefile @@ -0,0 +1,16 @@ +##===- lib/Analysis/Makefile -------------------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LEVEL = ../.. +LIBRARYNAME = LLVMAnalysis +DIRS = IPA +BUILD_ARCHIVE = 1 + +include $(LEVEL)/Makefile.common + diff --git a/libclamav/c++/llvm/lib/Analysis/MemoryBuiltins.cpp b/libclamav/c++/llvm/lib/Analysis/MemoryBuiltins.cpp new file mode 100644 index 000000000..b4486283f --- /dev/null +++ b/libclamav/c++/llvm/lib/Analysis/MemoryBuiltins.cpp @@ -0,0 +1,207 @@ +//===------ MemoryBuiltins.cpp - Identify calls to memory builtins --------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This family of functions identifies calls to builtin functions that allocate +// or free memory. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Analysis/MemoryBuiltins.h" +#include "llvm/Constants.h" +#include "llvm/Instructions.h" +#include "llvm/Module.h" +#include "llvm/Analysis/ValueTracking.h" +#include "llvm/Target/TargetData.h" +using namespace llvm; + +//===----------------------------------------------------------------------===// +// malloc Call Utility Functions. +// + +/// isMalloc - Returns true if the the value is either a malloc call or a +/// bitcast of the result of a malloc call. +bool llvm::isMalloc(const Value *I) { + return extractMallocCall(I) || extractMallocCallFromBitCast(I); +} + +static bool isMallocCall(const CallInst *CI) { + if (!CI) + return false; + + Function *Callee = CI->getCalledFunction(); + if (Callee == 0 || !Callee->isDeclaration() || Callee->getName() != "malloc") + return false; + + // Check malloc prototype. + // FIXME: workaround for PR5130, this will be obsolete when a nobuiltin + // attribute will exist. + const FunctionType *FTy = Callee->getFunctionType(); + if (FTy->getNumParams() != 1) + return false; + if (IntegerType *ITy = dyn_cast(FTy->param_begin()->get())) { + if (ITy->getBitWidth() != 32 && ITy->getBitWidth() != 64) + return false; + return true; + } + + return false; +} + +/// extractMallocCall - Returns the corresponding CallInst if the instruction +/// is a malloc call. Since CallInst::CreateMalloc() only creates calls, we +/// ignore InvokeInst here. +const CallInst *llvm::extractMallocCall(const Value *I) { + const CallInst *CI = dyn_cast(I); + return (isMallocCall(CI)) ? CI : NULL; +} + +CallInst *llvm::extractMallocCall(Value *I) { + CallInst *CI = dyn_cast(I); + return (isMallocCall(CI)) ? CI : NULL; +} + +static bool isBitCastOfMallocCall(const BitCastInst *BCI) { + if (!BCI) + return false; + + return isMallocCall(dyn_cast(BCI->getOperand(0))); +} + +/// extractMallocCallFromBitCast - Returns the corresponding CallInst if the +/// instruction is a bitcast of the result of a malloc call. +CallInst *llvm::extractMallocCallFromBitCast(Value *I) { + BitCastInst *BCI = dyn_cast(I); + return (isBitCastOfMallocCall(BCI)) ? cast(BCI->getOperand(0)) + : NULL; +} + +const CallInst *llvm::extractMallocCallFromBitCast(const Value *I) { + const BitCastInst *BCI = dyn_cast(I); + return (isBitCastOfMallocCall(BCI)) ? cast(BCI->getOperand(0)) + : NULL; +} + +static Value *computeArraySize(const CallInst *CI, const TargetData *TD, + bool LookThroughSExt = false) { + if (!CI) + return NULL; + + // The size of the malloc's result type must be known to determine array size. + const Type *T = getMallocAllocatedType(CI); + if (!T || !T->isSized() || !TD) + return NULL; + + unsigned ElementSize = TD->getTypeAllocSize(T); + if (const StructType *ST = dyn_cast(T)) + ElementSize = TD->getStructLayout(ST)->getSizeInBytes(); + + // If malloc calls' arg can be determined to be a multiple of ElementSize, + // return the multiple. Otherwise, return NULL. + Value *MallocArg = CI->getOperand(1); + Value *Multiple = NULL; + if (ComputeMultiple(MallocArg, ElementSize, Multiple, + LookThroughSExt)) + return Multiple; + + return NULL; +} + +/// isArrayMalloc - Returns the corresponding CallInst if the instruction +/// is a call to malloc whose array size can be determined and the array size +/// is not constant 1. Otherwise, return NULL. +const CallInst *llvm::isArrayMalloc(const Value *I, const TargetData *TD) { + const CallInst *CI = extractMallocCall(I); + Value *ArraySize = computeArraySize(CI, TD); + + if (ArraySize && + ArraySize != ConstantInt::get(CI->getOperand(1)->getType(), 1)) + return CI; + + // CI is a non-array malloc or we can't figure out that it is an array malloc. + return NULL; +} + +/// getMallocType - Returns the PointerType resulting from the malloc call. +/// The PointerType depends on the number of bitcast uses of the malloc call: +/// 0: PointerType is the calls' return type. +/// 1: PointerType is the bitcast's result type. +/// >1: Unique PointerType cannot be determined, return NULL. +const PointerType *llvm::getMallocType(const CallInst *CI) { + assert(isMalloc(CI) && "getMallocType and not malloc call"); + + const PointerType *MallocType = NULL; + unsigned NumOfBitCastUses = 0; + + // Determine if CallInst has a bitcast use. + for (Value::use_const_iterator UI = CI->use_begin(), E = CI->use_end(); + UI != E; ) + if (const BitCastInst *BCI = dyn_cast(*UI++)) { + MallocType = cast(BCI->getDestTy()); + NumOfBitCastUses++; + } + + // Malloc call has 1 bitcast use, so type is the bitcast's destination type. + if (NumOfBitCastUses == 1) + return MallocType; + + // Malloc call was not bitcast, so type is the malloc function's return type. + if (NumOfBitCastUses == 0) + return cast(CI->getType()); + + // Type could not be determined. + return NULL; +} + +/// getMallocAllocatedType - Returns the Type allocated by malloc call. +/// The Type depends on the number of bitcast uses of the malloc call: +/// 0: PointerType is the malloc calls' return type. +/// 1: PointerType is the bitcast's result type. +/// >1: Unique PointerType cannot be determined, return NULL. +const Type *llvm::getMallocAllocatedType(const CallInst *CI) { + const PointerType *PT = getMallocType(CI); + return PT ? PT->getElementType() : NULL; +} + +/// 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, +/// then return that multiple. For non-array mallocs, the multiple is +/// constant 1. Otherwise, return NULL for mallocs whose array size cannot be +/// determined. +Value *llvm::getMallocArraySize(CallInst *CI, const TargetData *TD, + bool LookThroughSExt) { + assert(isMalloc(CI) && "getMallocArraySize and not malloc call"); + return computeArraySize(CI, TD, LookThroughSExt); +} + +//===----------------------------------------------------------------------===// +// free Call Utility Functions. +// + +/// isFreeCall - Returns true if the the value is a call to the builtin free() +bool llvm::isFreeCall(const Value *I) { + const CallInst *CI = dyn_cast(I); + if (!CI) + return false; + Function *Callee = CI->getCalledFunction(); + if (Callee == 0 || !Callee->isDeclaration() || Callee->getName() != "free") + return false; + + // Check free prototype. + // FIXME: workaround for PR5130, this will be obsolete when a nobuiltin + // attribute will exist. + const FunctionType *FTy = Callee->getFunctionType(); + if (!FTy->getReturnType()->isVoidTy()) + return false; + if (FTy->getNumParams() != 1) + return false; + if (FTy->param_begin()->get() != Type::getInt8PtrTy(Callee->getContext())) + return false; + + return true; +} diff --git a/libclamav/c++/llvm/lib/Analysis/MemoryDependenceAnalysis.cpp b/libclamav/c++/llvm/lib/Analysis/MemoryDependenceAnalysis.cpp new file mode 100644 index 000000000..f958e7504 --- /dev/null +++ b/libclamav/c++/llvm/lib/Analysis/MemoryDependenceAnalysis.cpp @@ -0,0 +1,1370 @@ +//===- MemoryDependenceAnalysis.cpp - Mem Deps Implementation --*- 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 an analysis that determines, for a given memory +// operation, what preceding memory operations it depends on. It builds on +// alias analysis information, and tries to provide a lazy, caching interface to +// a common kind of alias information query. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "memdep" +#include "llvm/Analysis/MemoryDependenceAnalysis.h" +#include "llvm/Instructions.h" +#include "llvm/IntrinsicInst.h" +#include "llvm/Function.h" +#include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/Analysis/InstructionSimplify.h" +#include "llvm/Analysis/MemoryBuiltins.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/Support/PredIteratorCache.h" +#include "llvm/Support/Debug.h" +using namespace llvm; + +STATISTIC(NumCacheNonLocal, "Number of fully cached non-local responses"); +STATISTIC(NumCacheDirtyNonLocal, "Number of dirty cached non-local responses"); +STATISTIC(NumUncacheNonLocal, "Number of uncached non-local responses"); + +STATISTIC(NumCacheNonLocalPtr, + "Number of fully cached non-local ptr responses"); +STATISTIC(NumCacheDirtyNonLocalPtr, + "Number of cached, but dirty, non-local ptr responses"); +STATISTIC(NumUncacheNonLocalPtr, + "Number of uncached non-local ptr responses"); +STATISTIC(NumCacheCompleteNonLocalPtr, + "Number of block queries that were completely cached"); + +char MemoryDependenceAnalysis::ID = 0; + +// Register this pass... +static RegisterPass X("memdep", + "Memory Dependence Analysis", false, true); + +MemoryDependenceAnalysis::MemoryDependenceAnalysis() +: FunctionPass(&ID), PredCache(0) { +} +MemoryDependenceAnalysis::~MemoryDependenceAnalysis() { +} + +/// Clean up memory in between runs +void MemoryDependenceAnalysis::releaseMemory() { + LocalDeps.clear(); + NonLocalDeps.clear(); + NonLocalPointerDeps.clear(); + ReverseLocalDeps.clear(); + ReverseNonLocalDeps.clear(); + ReverseNonLocalPtrDeps.clear(); + PredCache->clear(); +} + + + +/// getAnalysisUsage - Does not modify anything. It uses Alias Analysis. +/// +void MemoryDependenceAnalysis::getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + AU.addRequiredTransitive(); +} + +bool MemoryDependenceAnalysis::runOnFunction(Function &) { + AA = &getAnalysis(); + if (PredCache == 0) + PredCache.reset(new PredIteratorCache()); + return false; +} + +/// RemoveFromReverseMap - This is a helper function that removes Val from +/// 'Inst's set in ReverseMap. If the set becomes empty, remove Inst's entry. +template +static void RemoveFromReverseMap(DenseMap > &ReverseMap, + Instruction *Inst, KeyTy Val) { + typename DenseMap >::iterator + InstIt = ReverseMap.find(Inst); + assert(InstIt != ReverseMap.end() && "Reverse map out of sync?"); + bool Found = InstIt->second.erase(Val); + assert(Found && "Invalid reverse map!"); Found=Found; + if (InstIt->second.empty()) + ReverseMap.erase(InstIt); +} + + +/// getCallSiteDependencyFrom - Private helper for finding the local +/// dependencies of a call site. +MemDepResult MemoryDependenceAnalysis:: +getCallSiteDependencyFrom(CallSite CS, bool isReadOnlyCall, + BasicBlock::iterator ScanIt, BasicBlock *BB) { + // Walk backwards through the block, looking for dependencies + while (ScanIt != BB->begin()) { + Instruction *Inst = --ScanIt; + + // If this inst is a memory op, get the pointer it accessed + Value *Pointer = 0; + uint64_t PointerSize = 0; + if (StoreInst *S = dyn_cast(Inst)) { + Pointer = S->getPointerOperand(); + PointerSize = AA->getTypeStoreSize(S->getOperand(0)->getType()); + } else if (VAArgInst *V = dyn_cast(Inst)) { + Pointer = V->getOperand(0); + PointerSize = AA->getTypeStoreSize(V->getType()); + } else if (isFreeCall(Inst)) { + Pointer = Inst->getOperand(1); + // calls to free() erase the entire structure + PointerSize = ~0ULL; + } else if (isa(Inst) || isa(Inst)) { + // Debug intrinsics don't cause dependences. + if (isa(Inst)) continue; + CallSite InstCS = CallSite::get(Inst); + // If these two calls do not interfere, look past it. + switch (AA->getModRefInfo(CS, InstCS)) { + case AliasAnalysis::NoModRef: + // If the two calls don't interact (e.g. InstCS is readnone) keep + // scanning. + continue; + case AliasAnalysis::Ref: + // If the two calls read the same memory locations and CS is a readonly + // function, then we have two cases: 1) the calls may not interfere with + // each other at all. 2) the calls may produce the same value. In case + // #1 we want to ignore the values, in case #2, we want to return Inst + // as a Def dependence. This allows us to CSE in cases like: + // X = strlen(P); + // memchr(...); + // Y = strlen(P); // Y = X + if (isReadOnlyCall) { + if (CS.getCalledFunction() != 0 && + CS.getCalledFunction() == InstCS.getCalledFunction()) + return MemDepResult::getDef(Inst); + // Ignore unrelated read/read call dependences. + continue; + } + // FALL THROUGH + default: + return MemDepResult::getClobber(Inst); + } + } else { + // Non-memory instruction. + continue; + } + + if (AA->getModRefInfo(CS, Pointer, PointerSize) != AliasAnalysis::NoModRef) + return MemDepResult::getClobber(Inst); + } + + // No dependence found. If this is the entry block of the function, it is a + // clobber, otherwise it is non-local. + if (BB != &BB->getParent()->getEntryBlock()) + return MemDepResult::getNonLocal(); + return MemDepResult::getClobber(ScanIt); +} + +/// getPointerDependencyFrom - Return the instruction on which a memory +/// location depends. If isLoad is true, this routine ignore may-aliases with +/// read-only operations. +MemDepResult MemoryDependenceAnalysis:: +getPointerDependencyFrom(Value *MemPtr, uint64_t MemSize, bool isLoad, + BasicBlock::iterator ScanIt, BasicBlock *BB) { + + Value *invariantTag = 0; + + // Walk backwards through the basic block, looking for dependencies. + while (ScanIt != BB->begin()) { + Instruction *Inst = --ScanIt; + + // If we're in an invariant region, no dependencies can be found before + // we pass an invariant-begin marker. + if (invariantTag == Inst) { + invariantTag = 0; + continue; + } else if (IntrinsicInst *II = dyn_cast(Inst)) { + // If we pass an invariant-end marker, then we've just entered an + // invariant region and can start ignoring dependencies. + if (II->getIntrinsicID() == Intrinsic::invariant_end) { + uint64_t invariantSize = ~0ULL; + if (ConstantInt *CI = dyn_cast(II->getOperand(2))) + invariantSize = CI->getZExtValue(); + + AliasAnalysis::AliasResult R = + AA->alias(II->getOperand(3), invariantSize, MemPtr, MemSize); + if (R == AliasAnalysis::MustAlias) { + invariantTag = II->getOperand(1); + continue; + } + + // If we reach a lifetime begin or end marker, then the query ends here + // because the value is undefined. + } else if (II->getIntrinsicID() == Intrinsic::lifetime_start || + II->getIntrinsicID() == Intrinsic::lifetime_end) { + uint64_t invariantSize = ~0ULL; + if (ConstantInt *CI = dyn_cast(II->getOperand(1))) + invariantSize = CI->getZExtValue(); + + AliasAnalysis::AliasResult R = + AA->alias(II->getOperand(2), invariantSize, MemPtr, MemSize); + if (R == AliasAnalysis::MustAlias) + return MemDepResult::getDef(II); + } + } + + // If we're querying on a load and we're in an invariant region, we're done + // at this point. Nothing a load depends on can live in an invariant region. + if (isLoad && invariantTag) continue; + + // Debug intrinsics don't cause dependences. + if (isa(Inst)) continue; + + // Values depend on loads if the pointers are must aliased. This means that + // a load depends on another must aliased load from the same value. + if (LoadInst *LI = dyn_cast(Inst)) { + Value *Pointer = LI->getPointerOperand(); + uint64_t PointerSize = AA->getTypeStoreSize(LI->getType()); + + // If we found a pointer, check if it could be the same as our pointer. + AliasAnalysis::AliasResult R = + AA->alias(Pointer, PointerSize, MemPtr, MemSize); + if (R == AliasAnalysis::NoAlias) + continue; + + // May-alias loads don't depend on each other without a dependence. + if (isLoad && R == AliasAnalysis::MayAlias) + continue; + // Stores depend on may and must aliased loads, loads depend on must-alias + // loads. + return MemDepResult::getDef(Inst); + } + + if (StoreInst *SI = dyn_cast(Inst)) { + // There can't be stores to the value we care about inside an + // invariant region. + if (invariantTag) continue; + + // If alias analysis can tell that this store is guaranteed to not modify + // the query pointer, ignore it. Use getModRefInfo to handle cases where + // the query pointer points to constant memory etc. + if (AA->getModRefInfo(SI, MemPtr, MemSize) == AliasAnalysis::NoModRef) + continue; + + // Ok, this store might clobber the query pointer. Check to see if it is + // a must alias: in this case, we want to return this as a def. + Value *Pointer = SI->getPointerOperand(); + uint64_t PointerSize = AA->getTypeStoreSize(SI->getOperand(0)->getType()); + + // If we found a pointer, check if it could be the same as our pointer. + AliasAnalysis::AliasResult R = + AA->alias(Pointer, PointerSize, MemPtr, MemSize); + + if (R == AliasAnalysis::NoAlias) + continue; + if (R == AliasAnalysis::MayAlias) + return MemDepResult::getClobber(Inst); + return MemDepResult::getDef(Inst); + } + + // If this is an allocation, and if we know that the accessed pointer is to + // the allocation, return Def. This means that there is no dependence and + // the access can be optimized based on that. For example, a load could + // turn into undef. + // Note: Only determine this to be a malloc if Inst is the malloc call, not + // a subsequent bitcast of the malloc call result. There can be stores to + // the malloced memory between the malloc call and its bitcast uses, and we + // need to continue scanning until the malloc call. + if (isa(Inst) || extractMallocCall(Inst)) { + Value *AccessPtr = MemPtr->getUnderlyingObject(); + + if (AccessPtr == Inst || + AA->alias(Inst, 1, AccessPtr, 1) == AliasAnalysis::MustAlias) + return MemDepResult::getDef(Inst); + continue; + } + + // See if this instruction (e.g. a call or vaarg) mod/ref's the pointer. + switch (AA->getModRefInfo(Inst, MemPtr, MemSize)) { + case AliasAnalysis::NoModRef: + // If the call has no effect on the queried pointer, just ignore it. + continue; + case AliasAnalysis::Mod: + // If we're in an invariant region, we can ignore calls that ONLY + // modify the pointer. + if (invariantTag) continue; + return MemDepResult::getClobber(Inst); + case AliasAnalysis::Ref: + // If the call is known to never store to the pointer, and if this is a + // load query, we can safely ignore it (scan past it). + if (isLoad) + continue; + default: + // Otherwise, there is a potential dependence. Return a clobber. + return MemDepResult::getClobber(Inst); + } + } + + // No dependence found. If this is the entry block of the function, it is a + // clobber, otherwise it is non-local. + if (BB != &BB->getParent()->getEntryBlock()) + return MemDepResult::getNonLocal(); + return MemDepResult::getClobber(ScanIt); +} + +/// getDependency - Return the instruction on which a memory operation +/// depends. +MemDepResult MemoryDependenceAnalysis::getDependency(Instruction *QueryInst) { + Instruction *ScanPos = QueryInst; + + // Check for a cached result + MemDepResult &LocalCache = LocalDeps[QueryInst]; + + // If the cached entry is non-dirty, just return it. Note that this depends + // on MemDepResult's default constructing to 'dirty'. + if (!LocalCache.isDirty()) + return LocalCache; + + // Otherwise, if we have a dirty entry, we know we can start the scan at that + // instruction, which may save us some work. + if (Instruction *Inst = LocalCache.getInst()) { + ScanPos = Inst; + + RemoveFromReverseMap(ReverseLocalDeps, Inst, QueryInst); + } + + BasicBlock *QueryParent = QueryInst->getParent(); + + Value *MemPtr = 0; + uint64_t MemSize = 0; + + // Do the scan. + if (BasicBlock::iterator(QueryInst) == QueryParent->begin()) { + // No dependence found. If this is the entry block of the function, it is a + // clobber, otherwise it is non-local. + if (QueryParent != &QueryParent->getParent()->getEntryBlock()) + LocalCache = MemDepResult::getNonLocal(); + else + LocalCache = MemDepResult::getClobber(QueryInst); + } else if (StoreInst *SI = dyn_cast(QueryInst)) { + // If this is a volatile store, don't mess around with it. Just return the + // previous instruction as a clobber. + if (SI->isVolatile()) + LocalCache = MemDepResult::getClobber(--BasicBlock::iterator(ScanPos)); + else { + MemPtr = SI->getPointerOperand(); + MemSize = AA->getTypeStoreSize(SI->getOperand(0)->getType()); + } + } else if (LoadInst *LI = dyn_cast(QueryInst)) { + // If this is a volatile load, don't mess around with it. Just return the + // previous instruction as a clobber. + if (LI->isVolatile()) + LocalCache = MemDepResult::getClobber(--BasicBlock::iterator(ScanPos)); + else { + MemPtr = LI->getPointerOperand(); + MemSize = AA->getTypeStoreSize(LI->getType()); + } + } else if (isFreeCall(QueryInst)) { + MemPtr = QueryInst->getOperand(1); + // calls to free() erase the entire structure, not just a field. + MemSize = ~0UL; + } else if (isa(QueryInst) || isa(QueryInst)) { + CallSite QueryCS = CallSite::get(QueryInst); + bool isReadOnly = AA->onlyReadsMemory(QueryCS); + LocalCache = getCallSiteDependencyFrom(QueryCS, isReadOnly, ScanPos, + QueryParent); + } else { + // Non-memory instruction. + LocalCache = MemDepResult::getClobber(--BasicBlock::iterator(ScanPos)); + } + + // If we need to do a pointer scan, make it happen. + if (MemPtr) + LocalCache = getPointerDependencyFrom(MemPtr, MemSize, + isa(QueryInst), + ScanPos, QueryParent); + + // Remember the result! + if (Instruction *I = LocalCache.getInst()) + ReverseLocalDeps[I].insert(QueryInst); + + return LocalCache; +} + +#ifndef NDEBUG +/// AssertSorted - This method is used when -debug is specified to verify that +/// cache arrays are properly kept sorted. +static void AssertSorted(MemoryDependenceAnalysis::NonLocalDepInfo &Cache, + int Count = -1) { + if (Count == -1) Count = Cache.size(); + if (Count == 0) return; + + for (unsigned i = 1; i != unsigned(Count); ++i) + assert(Cache[i-1] <= Cache[i] && "Cache isn't sorted!"); +} +#endif + +/// getNonLocalCallDependency - Perform a full dependency query for the +/// specified call, returning the set of blocks that the value is +/// potentially live across. The returned set of results will include a +/// "NonLocal" result for all blocks where the value is live across. +/// +/// This method assumes the instruction returns a "NonLocal" dependency +/// within its own block. +/// +/// This returns a reference to an internal data structure that may be +/// invalidated on the next non-local query or when an instruction is +/// removed. Clients must copy this data if they want it around longer than +/// that. +const MemoryDependenceAnalysis::NonLocalDepInfo & +MemoryDependenceAnalysis::getNonLocalCallDependency(CallSite QueryCS) { + assert(getDependency(QueryCS.getInstruction()).isNonLocal() && + "getNonLocalCallDependency should only be used on calls with non-local deps!"); + PerInstNLInfo &CacheP = NonLocalDeps[QueryCS.getInstruction()]; + NonLocalDepInfo &Cache = CacheP.first; + + /// DirtyBlocks - This is the set of blocks that need to be recomputed. In + /// the cached case, this can happen due to instructions being deleted etc. In + /// the uncached case, this starts out as the set of predecessors we care + /// about. + SmallVector DirtyBlocks; + + if (!Cache.empty()) { + // Okay, we have a cache entry. If we know it is not dirty, just return it + // with no computation. + if (!CacheP.second) { + NumCacheNonLocal++; + return Cache; + } + + // If we already have a partially computed set of results, scan them to + // determine what is dirty, seeding our initial DirtyBlocks worklist. + for (NonLocalDepInfo::iterator I = Cache.begin(), E = Cache.end(); + I != E; ++I) + if (I->second.isDirty()) + DirtyBlocks.push_back(I->first); + + // Sort the cache so that we can do fast binary search lookups below. + std::sort(Cache.begin(), Cache.end()); + + ++NumCacheDirtyNonLocal; + //cerr << "CACHED CASE: " << DirtyBlocks.size() << " dirty: " + // << Cache.size() << " cached: " << *QueryInst; + } else { + // Seed DirtyBlocks with each of the preds of QueryInst's block. + BasicBlock *QueryBB = QueryCS.getInstruction()->getParent(); + for (BasicBlock **PI = PredCache->GetPreds(QueryBB); *PI; ++PI) + DirtyBlocks.push_back(*PI); + NumUncacheNonLocal++; + } + + // isReadonlyCall - If this is a read-only call, we can be more aggressive. + bool isReadonlyCall = AA->onlyReadsMemory(QueryCS); + + SmallPtrSet Visited; + + unsigned NumSortedEntries = Cache.size(); + DEBUG(AssertSorted(Cache)); + + // Iterate while we still have blocks to update. + while (!DirtyBlocks.empty()) { + BasicBlock *DirtyBB = DirtyBlocks.back(); + DirtyBlocks.pop_back(); + + // Already processed this block? + if (!Visited.insert(DirtyBB)) + continue; + + // Do a binary search to see if we already have an entry for this block in + // the cache set. If so, find it. + DEBUG(AssertSorted(Cache, NumSortedEntries)); + NonLocalDepInfo::iterator Entry = + std::upper_bound(Cache.begin(), Cache.begin()+NumSortedEntries, + std::make_pair(DirtyBB, MemDepResult())); + if (Entry != Cache.begin() && prior(Entry)->first == DirtyBB) + --Entry; + + MemDepResult *ExistingResult = 0; + if (Entry != Cache.begin()+NumSortedEntries && + Entry->first == DirtyBB) { + // If we already have an entry, and if it isn't already dirty, the block + // is done. + if (!Entry->second.isDirty()) + continue; + + // Otherwise, remember this slot so we can update the value. + ExistingResult = &Entry->second; + } + + // If the dirty entry has a pointer, start scanning from it so we don't have + // to rescan the entire block. + BasicBlock::iterator ScanPos = DirtyBB->end(); + if (ExistingResult) { + if (Instruction *Inst = ExistingResult->getInst()) { + ScanPos = Inst; + // We're removing QueryInst's use of Inst. + RemoveFromReverseMap(ReverseNonLocalDeps, Inst, + QueryCS.getInstruction()); + } + } + + // Find out if this block has a local dependency for QueryInst. + MemDepResult Dep; + + if (ScanPos != DirtyBB->begin()) { + Dep = getCallSiteDependencyFrom(QueryCS, isReadonlyCall,ScanPos, DirtyBB); + } else if (DirtyBB != &DirtyBB->getParent()->getEntryBlock()) { + // No dependence found. If this is the entry block of the function, it is + // a clobber, otherwise it is non-local. + Dep = MemDepResult::getNonLocal(); + } else { + Dep = MemDepResult::getClobber(ScanPos); + } + + // If we had a dirty entry for the block, update it. Otherwise, just add + // a new entry. + if (ExistingResult) + *ExistingResult = Dep; + else + Cache.push_back(std::make_pair(DirtyBB, Dep)); + + // If the block has a dependency (i.e. it isn't completely transparent to + // the value), remember the association! + if (!Dep.isNonLocal()) { + // Keep the ReverseNonLocalDeps map up to date so we can efficiently + // update this when we remove instructions. + if (Instruction *Inst = Dep.getInst()) + ReverseNonLocalDeps[Inst].insert(QueryCS.getInstruction()); + } else { + + // If the block *is* completely transparent to the load, we need to check + // the predecessors of this block. Add them to our worklist. + for (BasicBlock **PI = PredCache->GetPreds(DirtyBB); *PI; ++PI) + DirtyBlocks.push_back(*PI); + } + } + + return Cache; +} + +/// getNonLocalPointerDependency - Perform a full dependency query for an +/// access to the specified (non-volatile) memory location, returning the +/// set of instructions that either define or clobber the value. +/// +/// This method assumes the pointer has a "NonLocal" dependency within its +/// own block. +/// +void MemoryDependenceAnalysis:: +getNonLocalPointerDependency(Value *Pointer, bool isLoad, BasicBlock *FromBB, + SmallVectorImpl &Result) { + assert(isa(Pointer->getType()) && + "Can't get pointer deps of a non-pointer!"); + Result.clear(); + + // We know that the pointer value is live into FromBB find the def/clobbers + // from presecessors. + const Type *EltTy = cast(Pointer->getType())->getElementType(); + uint64_t PointeeSize = AA->getTypeStoreSize(EltTy); + + // This is the set of blocks we've inspected, and the pointer we consider in + // each block. Because of critical edges, we currently bail out if querying + // a block with multiple different pointers. This can happen during PHI + // translation. + DenseMap Visited; + if (!getNonLocalPointerDepFromBB(Pointer, PointeeSize, isLoad, FromBB, + Result, Visited, true)) + return; + Result.clear(); + Result.push_back(std::make_pair(FromBB, + MemDepResult::getClobber(FromBB->begin()))); +} + +/// GetNonLocalInfoForBlock - Compute the memdep value for BB with +/// Pointer/PointeeSize using either cached information in Cache or by doing a +/// lookup (which may use dirty cache info if available). If we do a lookup, +/// add the result to the cache. +MemDepResult MemoryDependenceAnalysis:: +GetNonLocalInfoForBlock(Value *Pointer, uint64_t PointeeSize, + bool isLoad, BasicBlock *BB, + NonLocalDepInfo *Cache, unsigned NumSortedEntries) { + + // Do a binary search to see if we already have an entry for this block in + // the cache set. If so, find it. + NonLocalDepInfo::iterator Entry = + std::upper_bound(Cache->begin(), Cache->begin()+NumSortedEntries, + std::make_pair(BB, MemDepResult())); + if (Entry != Cache->begin() && prior(Entry)->first == BB) + --Entry; + + MemDepResult *ExistingResult = 0; + if (Entry != Cache->begin()+NumSortedEntries && Entry->first == BB) + ExistingResult = &Entry->second; + + // If we have a cached entry, and it is non-dirty, use it as the value for + // this dependency. + if (ExistingResult && !ExistingResult->isDirty()) { + ++NumCacheNonLocalPtr; + return *ExistingResult; + } + + // Otherwise, we have to scan for the value. If we have a dirty cache + // entry, start scanning from its position, otherwise we scan from the end + // of the block. + BasicBlock::iterator ScanPos = BB->end(); + if (ExistingResult && ExistingResult->getInst()) { + assert(ExistingResult->getInst()->getParent() == BB && + "Instruction invalidated?"); + ++NumCacheDirtyNonLocalPtr; + ScanPos = ExistingResult->getInst(); + + // Eliminating the dirty entry from 'Cache', so update the reverse info. + ValueIsLoadPair CacheKey(Pointer, isLoad); + RemoveFromReverseMap(ReverseNonLocalPtrDeps, ScanPos, CacheKey); + } else { + ++NumUncacheNonLocalPtr; + } + + // Scan the block for the dependency. + MemDepResult Dep = getPointerDependencyFrom(Pointer, PointeeSize, isLoad, + ScanPos, BB); + + // If we had a dirty entry for the block, update it. Otherwise, just add + // a new entry. + if (ExistingResult) + *ExistingResult = Dep; + else + Cache->push_back(std::make_pair(BB, Dep)); + + // If the block has a dependency (i.e. it isn't completely transparent to + // the value), remember the reverse association because we just added it + // to Cache! + if (Dep.isNonLocal()) + return Dep; + + // Keep the ReverseNonLocalPtrDeps map up to date so we can efficiently + // update MemDep when we remove instructions. + Instruction *Inst = Dep.getInst(); + assert(Inst && "Didn't depend on anything?"); + ValueIsLoadPair CacheKey(Pointer, isLoad); + ReverseNonLocalPtrDeps[Inst].insert(CacheKey); + return Dep; +} + +/// SortNonLocalDepInfoCache - Sort the a NonLocalDepInfo cache, given a certain +/// number of elements in the array that are already properly ordered. This is +/// optimized for the case when only a few entries are added. +static void +SortNonLocalDepInfoCache(MemoryDependenceAnalysis::NonLocalDepInfo &Cache, + unsigned NumSortedEntries) { + switch (Cache.size() - NumSortedEntries) { + case 0: + // done, no new entries. + break; + case 2: { + // Two new entries, insert the last one into place. + MemoryDependenceAnalysis::NonLocalDepEntry Val = Cache.back(); + Cache.pop_back(); + MemoryDependenceAnalysis::NonLocalDepInfo::iterator Entry = + std::upper_bound(Cache.begin(), Cache.end()-1, Val); + Cache.insert(Entry, Val); + // FALL THROUGH. + } + case 1: + // One new entry, Just insert the new value at the appropriate position. + if (Cache.size() != 1) { + MemoryDependenceAnalysis::NonLocalDepEntry Val = Cache.back(); + Cache.pop_back(); + MemoryDependenceAnalysis::NonLocalDepInfo::iterator Entry = + std::upper_bound(Cache.begin(), Cache.end(), Val); + Cache.insert(Entry, Val); + } + break; + default: + // Added many values, do a full scale sort. + std::sort(Cache.begin(), Cache.end()); + break; + } +} + +/// isPHITranslatable - Return true if the specified computation is derived from +/// a PHI node in the current block and if it is simple enough for us to handle. +static bool isPHITranslatable(Instruction *Inst) { + if (isa(Inst)) + return true; + + // We can handle bitcast of a PHI, but the PHI needs to be in the same block + // as the bitcast. + if (BitCastInst *BC = dyn_cast(Inst)) + if (PHINode *PN = dyn_cast(BC->getOperand(0))) + if (PN->getParent() == BC->getParent()) + return true; + + // We can translate a GEP that uses a PHI in the current block for at least + // one of its operands. + if (GetElementPtrInst *GEP = dyn_cast(Inst)) { + for (unsigned i = 0, e = GEP->getNumOperands(); i != e; ++i) + if (PHINode *PN = dyn_cast(GEP->getOperand(i))) + if (PN->getParent() == GEP->getParent()) + return true; + } + + // cerr << "MEMDEP: Could not PHI translate: " << *Pointer; + // if (isa(PtrInst) || isa(PtrInst)) + // cerr << "OP:\t\t\t\t" << *PtrInst->getOperand(0); + + return false; +} + +/// PHITranslateForPred - Given a computation that satisfied the +/// isPHITranslatable predicate, see if we can translate the computation into +/// the specified predecessor block. If so, return that value. +Value *MemoryDependenceAnalysis:: +PHITranslatePointer(Value *InVal, BasicBlock *CurBB, BasicBlock *Pred, + const TargetData *TD) const { + // If the input value is not an instruction, or if it is not defined in CurBB, + // then we don't need to phi translate it. + Instruction *Inst = dyn_cast(InVal); + if (Inst == 0 || Inst->getParent() != CurBB) + return InVal; + + if (PHINode *PN = dyn_cast(Inst)) + return PN->getIncomingValueForBlock(Pred); + + // Handle bitcast of PHI. + if (BitCastInst *BC = dyn_cast(Inst)) { + PHINode *BCPN = cast(BC->getOperand(0)); + Value *PHIIn = BCPN->getIncomingValueForBlock(Pred); + + // Constants are trivial to phi translate. + if (Constant *C = dyn_cast(PHIIn)) + return ConstantExpr::getBitCast(C, BC->getType()); + + // Otherwise we have to see if a bitcasted version of the incoming pointer + // is available. If so, we can use it, otherwise we have to fail. + for (Value::use_iterator UI = PHIIn->use_begin(), E = PHIIn->use_end(); + UI != E; ++UI) { + if (BitCastInst *BCI = dyn_cast(*UI)) + if (BCI->getType() == BC->getType()) + return BCI; + } + return 0; + } + + // Handle getelementptr with at least one PHI operand. + if (GetElementPtrInst *GEP = dyn_cast(Inst)) { + SmallVector GEPOps; + BasicBlock *CurBB = GEP->getParent(); + for (unsigned i = 0, e = GEP->getNumOperands(); i != e; ++i) { + Value *GEPOp = GEP->getOperand(i); + // No PHI translation is needed of operands whose values are live in to + // the predecessor block. + if (!isa(GEPOp) || + cast(GEPOp)->getParent() != CurBB) { + GEPOps.push_back(GEPOp); + continue; + } + + // If the operand is a phi node, do phi translation. + if (PHINode *PN = dyn_cast(GEPOp)) { + GEPOps.push_back(PN->getIncomingValueForBlock(Pred)); + continue; + } + + // Otherwise, we can't PHI translate this random value defined in this + // block. + return 0; + } + + // Simplify the GEP to handle 'gep x, 0' -> x etc. + if (Value *V = SimplifyGEPInst(&GEPOps[0], GEPOps.size(), TD)) + return V; + + + // Scan to see if we have this GEP available. + Value *APHIOp = GEPOps[0]; + for (Value::use_iterator UI = APHIOp->use_begin(), E = APHIOp->use_end(); + UI != E; ++UI) { + if (GetElementPtrInst *GEPI = dyn_cast(*UI)) + if (GEPI->getType() == GEP->getType() && + GEPI->getNumOperands() == GEPOps.size() && + GEPI->getParent()->getParent() == CurBB->getParent()) { + bool Mismatch = false; + for (unsigned i = 0, e = GEPOps.size(); i != e; ++i) + if (GEPI->getOperand(i) != GEPOps[i]) { + Mismatch = true; + break; + } + if (!Mismatch) + return GEPI; + } + } + return 0; + } + + return 0; +} + +/// InsertPHITranslatedPointer - Insert a computation of the PHI translated +/// version of 'V' for the edge PredBB->CurBB into the end of the PredBB +/// block. +/// +/// This is only called when PHITranslatePointer returns a value that doesn't +/// dominate the block, so we don't need to handle the trivial cases here. +Value *MemoryDependenceAnalysis:: +InsertPHITranslatedPointer(Value *InVal, BasicBlock *CurBB, + BasicBlock *PredBB, const TargetData *TD) const { + // If the input value isn't an instruction in CurBB, it doesn't need phi + // translation. + Instruction *Inst = cast(InVal); + assert(Inst->getParent() == CurBB && "Doesn't need phi trans"); + + // Handle bitcast of PHI. + if (BitCastInst *BC = dyn_cast(Inst)) { + PHINode *BCPN = cast(BC->getOperand(0)); + Value *PHIIn = BCPN->getIncomingValueForBlock(PredBB); + + // Otherwise insert a bitcast at the end of PredBB. + return new BitCastInst(PHIIn, InVal->getType(), + InVal->getName()+".phi.trans.insert", + PredBB->getTerminator()); + } + + // Handle getelementptr with at least one PHI operand. + if (GetElementPtrInst *GEP = dyn_cast(Inst)) { + SmallVector GEPOps; + Value *APHIOp = 0; + BasicBlock *CurBB = GEP->getParent(); + for (unsigned i = 0, e = GEP->getNumOperands(); i != e; ++i) { + GEPOps.push_back(GEP->getOperand(i)->DoPHITranslation(CurBB, PredBB)); + if (!isa(GEPOps.back())) + APHIOp = GEPOps.back(); + } + + GetElementPtrInst *Result = + GetElementPtrInst::Create(GEPOps[0], GEPOps.begin()+1, GEPOps.end(), + InVal->getName()+".phi.trans.insert", + PredBB->getTerminator()); + Result->setIsInBounds(GEP->isInBounds()); + return Result; + } + + return 0; +} + +/// getNonLocalPointerDepFromBB - Perform a dependency query based on +/// pointer/pointeesize starting at the end of StartBB. Add any clobber/def +/// results to the results vector and keep track of which blocks are visited in +/// 'Visited'. +/// +/// This has special behavior for the first block queries (when SkipFirstBlock +/// is true). In this special case, it ignores the contents of the specified +/// block and starts returning dependence info for its predecessors. +/// +/// This function returns false on success, or true to indicate that it could +/// not compute dependence information for some reason. This should be treated +/// as a clobber dependence on the first instruction in the predecessor block. +bool MemoryDependenceAnalysis:: +getNonLocalPointerDepFromBB(Value *Pointer, uint64_t PointeeSize, + bool isLoad, BasicBlock *StartBB, + SmallVectorImpl &Result, + DenseMap &Visited, + bool SkipFirstBlock) { + + // Look up the cached info for Pointer. + ValueIsLoadPair CacheKey(Pointer, isLoad); + + std::pair *CacheInfo = + &NonLocalPointerDeps[CacheKey]; + NonLocalDepInfo *Cache = &CacheInfo->second; + + // If we have valid cached information for exactly the block we are + // investigating, just return it with no recomputation. + if (CacheInfo->first == BBSkipFirstBlockPair(StartBB, SkipFirstBlock)) { + // We have a fully cached result for this query then we can just return the + // cached results and populate the visited set. However, we have to verify + // that we don't already have conflicting results for these blocks. Check + // to ensure that if a block in the results set is in the visited set that + // it was for the same pointer query. + if (!Visited.empty()) { + for (NonLocalDepInfo::iterator I = Cache->begin(), E = Cache->end(); + I != E; ++I) { + DenseMap::iterator VI = Visited.find(I->first); + if (VI == Visited.end() || VI->second == Pointer) continue; + + // We have a pointer mismatch in a block. Just return clobber, saying + // that something was clobbered in this result. We could also do a + // non-fully cached query, but there is little point in doing this. + return true; + } + } + + for (NonLocalDepInfo::iterator I = Cache->begin(), E = Cache->end(); + I != E; ++I) { + Visited.insert(std::make_pair(I->first, Pointer)); + if (!I->second.isNonLocal()) + Result.push_back(*I); + } + ++NumCacheCompleteNonLocalPtr; + return false; + } + + // Otherwise, either this is a new block, a block with an invalid cache + // pointer or one that we're about to invalidate by putting more info into it + // than its valid cache info. If empty, the result will be valid cache info, + // otherwise it isn't. + if (Cache->empty()) + CacheInfo->first = BBSkipFirstBlockPair(StartBB, SkipFirstBlock); + else + CacheInfo->first = BBSkipFirstBlockPair(); + + SmallVector Worklist; + Worklist.push_back(StartBB); + + // Keep track of the entries that we know are sorted. Previously cached + // entries will all be sorted. The entries we add we only sort on demand (we + // don't insert every element into its sorted position). We know that we + // won't get any reuse from currently inserted values, because we don't + // revisit blocks after we insert info for them. + unsigned NumSortedEntries = Cache->size(); + DEBUG(AssertSorted(*Cache)); + + while (!Worklist.empty()) { + BasicBlock *BB = Worklist.pop_back_val(); + + // Skip the first block if we have it. + if (!SkipFirstBlock) { + // Analyze the dependency of *Pointer in FromBB. See if we already have + // been here. + assert(Visited.count(BB) && "Should check 'visited' before adding to WL"); + + // Get the dependency info for Pointer in BB. If we have cached + // information, we will use it, otherwise we compute it. + DEBUG(AssertSorted(*Cache, NumSortedEntries)); + MemDepResult Dep = GetNonLocalInfoForBlock(Pointer, PointeeSize, isLoad, + BB, Cache, NumSortedEntries); + + // If we got a Def or Clobber, add this to the list of results. + if (!Dep.isNonLocal()) { + Result.push_back(NonLocalDepEntry(BB, Dep)); + continue; + } + } + + // If 'Pointer' is an instruction defined in this block, then we need to do + // phi translation to change it into a value live in the predecessor block. + // If phi translation fails, then we can't continue dependence analysis. + Instruction *PtrInst = dyn_cast(Pointer); + bool NeedsPHITranslation = PtrInst && PtrInst->getParent() == BB; + + // If no PHI translation is needed, just add all the predecessors of this + // block to scan them as well. + if (!NeedsPHITranslation) { + SkipFirstBlock = false; + for (BasicBlock **PI = PredCache->GetPreds(BB); *PI; ++PI) { + // Verify that we haven't looked at this block yet. + std::pair::iterator, bool> + InsertRes = Visited.insert(std::make_pair(*PI, Pointer)); + if (InsertRes.second) { + // First time we've looked at *PI. + Worklist.push_back(*PI); + continue; + } + + // If we have seen this block before, but it was with a different + // pointer then we have a phi translation failure and we have to treat + // this as a clobber. + if (InsertRes.first->second != Pointer) + goto PredTranslationFailure; + } + continue; + } + + // If we do need to do phi translation, then there are a bunch of different + // cases, because we have to find a Value* live in the predecessor block. We + // know that PtrInst is defined in this block at least. + + // We may have added values to the cache list before this PHI translation. + // If so, we haven't done anything to ensure that the cache remains sorted. + // Sort it now (if needed) so that recursive invocations of + // getNonLocalPointerDepFromBB and other routines that could reuse the cache + // value will only see properly sorted cache arrays. + if (Cache && NumSortedEntries != Cache->size()) { + SortNonLocalDepInfoCache(*Cache, NumSortedEntries); + NumSortedEntries = Cache->size(); + } + + // If this is a computation derived from a PHI node, use the suitably + // translated incoming values for each pred as the phi translated version. + if (!isPHITranslatable(PtrInst)) + goto PredTranslationFailure; + + Cache = 0; + + for (BasicBlock **PI = PredCache->GetPreds(BB); *PI; ++PI) { + BasicBlock *Pred = *PI; + Value *PredPtr = PHITranslatePointer(PtrInst, BB, Pred, TD); + + // If PHI translation fails, bail out. + if (PredPtr == 0) { + // FIXME: Instead of modelling this as a phi trans failure, we should + // model this as a clobber in the one predecessor. This will allow + // us to PRE values that are only available in some preds but not all. + goto PredTranslationFailure; + } + + // Check to see if we have already visited this pred block with another + // pointer. If so, we can't do this lookup. This failure can occur + // with PHI translation when a critical edge exists and the PHI node in + // the successor translates to a pointer value different than the + // pointer the block was first analyzed with. + std::pair::iterator, bool> + InsertRes = Visited.insert(std::make_pair(Pred, PredPtr)); + + if (!InsertRes.second) { + // If the predecessor was visited with PredPtr, then we already did + // the analysis and can ignore it. + if (InsertRes.first->second == PredPtr) + continue; + + // Otherwise, the block was previously analyzed with a different + // pointer. We can't represent the result of this case, so we just + // treat this as a phi translation failure. + goto PredTranslationFailure; + } + + // FIXME: it is entirely possible that PHI translating will end up with + // the same value. Consider PHI translating something like: + // X = phi [x, bb1], [y, bb2]. PHI translating for bb1 doesn't *need* + // to recurse here, pedantically speaking. + + // If we have a problem phi translating, fall through to the code below + // to handle the failure condition. + if (getNonLocalPointerDepFromBB(PredPtr, PointeeSize, isLoad, Pred, + Result, Visited)) + goto PredTranslationFailure; + } + + // Refresh the CacheInfo/Cache pointer so that it isn't invalidated. + CacheInfo = &NonLocalPointerDeps[CacheKey]; + Cache = &CacheInfo->second; + NumSortedEntries = Cache->size(); + + // Since we did phi translation, the "Cache" set won't contain all of the + // results for the query. This is ok (we can still use it to accelerate + // specific block queries) but we can't do the fastpath "return all + // results from the set" Clear out the indicator for this. + CacheInfo->first = BBSkipFirstBlockPair(); + SkipFirstBlock = false; + continue; + + PredTranslationFailure: + + if (Cache == 0) { + // Refresh the CacheInfo/Cache pointer if it got invalidated. + CacheInfo = &NonLocalPointerDeps[CacheKey]; + Cache = &CacheInfo->second; + NumSortedEntries = Cache->size(); + } + + // Since we did phi translation, the "Cache" set won't contain all of the + // results for the query. This is ok (we can still use it to accelerate + // specific block queries) but we can't do the fastpath "return all + // results from the set" Clear out the indicator for this. + CacheInfo->first = BBSkipFirstBlockPair(); + + // If *nothing* works, mark the pointer as being clobbered by the first + // instruction in this block. + // + // If this is the magic first block, return this as a clobber of the whole + // incoming value. Since we can't phi translate to one of the predecessors, + // we have to bail out. + if (SkipFirstBlock) + return true; + + for (NonLocalDepInfo::reverse_iterator I = Cache->rbegin(); ; ++I) { + assert(I != Cache->rend() && "Didn't find current block??"); + if (I->first != BB) + continue; + + assert(I->second.isNonLocal() && + "Should only be here with transparent block"); + I->second = MemDepResult::getClobber(BB->begin()); + ReverseNonLocalPtrDeps[BB->begin()].insert(CacheKey); + Result.push_back(*I); + break; + } + } + + // Okay, we're done now. If we added new values to the cache, re-sort it. + SortNonLocalDepInfoCache(*Cache, NumSortedEntries); + DEBUG(AssertSorted(*Cache)); + return false; +} + +/// RemoveCachedNonLocalPointerDependencies - If P exists in +/// CachedNonLocalPointerInfo, remove it. +void MemoryDependenceAnalysis:: +RemoveCachedNonLocalPointerDependencies(ValueIsLoadPair P) { + CachedNonLocalPointerInfo::iterator It = + NonLocalPointerDeps.find(P); + if (It == NonLocalPointerDeps.end()) return; + + // Remove all of the entries in the BB->val map. This involves removing + // instructions from the reverse map. + NonLocalDepInfo &PInfo = It->second.second; + + for (unsigned i = 0, e = PInfo.size(); i != e; ++i) { + Instruction *Target = PInfo[i].second.getInst(); + if (Target == 0) continue; // Ignore non-local dep results. + assert(Target->getParent() == PInfo[i].first); + + // Eliminating the dirty entry from 'Cache', so update the reverse info. + RemoveFromReverseMap(ReverseNonLocalPtrDeps, Target, P); + } + + // Remove P from NonLocalPointerDeps (which deletes NonLocalDepInfo). + NonLocalPointerDeps.erase(It); +} + + +/// invalidateCachedPointerInfo - This method is used to invalidate cached +/// information about the specified pointer, because it may be too +/// conservative in memdep. This is an optional call that can be used when +/// the client detects an equivalence between the pointer and some other +/// value and replaces the other value with ptr. This can make Ptr available +/// in more places that cached info does not necessarily keep. +void MemoryDependenceAnalysis::invalidateCachedPointerInfo(Value *Ptr) { + // If Ptr isn't really a pointer, just ignore it. + if (!isa(Ptr->getType())) return; + // Flush store info for the pointer. + RemoveCachedNonLocalPointerDependencies(ValueIsLoadPair(Ptr, false)); + // Flush load info for the pointer. + RemoveCachedNonLocalPointerDependencies(ValueIsLoadPair(Ptr, true)); +} + +/// removeInstruction - Remove an instruction from the dependence analysis, +/// updating the dependence of instructions that previously depended on it. +/// This method attempts to keep the cache coherent using the reverse map. +void MemoryDependenceAnalysis::removeInstruction(Instruction *RemInst) { + // Walk through the Non-local dependencies, removing this one as the value + // for any cached queries. + NonLocalDepMapType::iterator NLDI = NonLocalDeps.find(RemInst); + if (NLDI != NonLocalDeps.end()) { + NonLocalDepInfo &BlockMap = NLDI->second.first; + for (NonLocalDepInfo::iterator DI = BlockMap.begin(), DE = BlockMap.end(); + DI != DE; ++DI) + if (Instruction *Inst = DI->second.getInst()) + RemoveFromReverseMap(ReverseNonLocalDeps, Inst, RemInst); + NonLocalDeps.erase(NLDI); + } + + // If we have a cached local dependence query for this instruction, remove it. + // + LocalDepMapType::iterator LocalDepEntry = LocalDeps.find(RemInst); + if (LocalDepEntry != LocalDeps.end()) { + // Remove us from DepInst's reverse set now that the local dep info is gone. + if (Instruction *Inst = LocalDepEntry->second.getInst()) + RemoveFromReverseMap(ReverseLocalDeps, Inst, RemInst); + + // Remove this local dependency info. + LocalDeps.erase(LocalDepEntry); + } + + // If we have any cached pointer dependencies on this instruction, remove + // them. If the instruction has non-pointer type, then it can't be a pointer + // base. + + // Remove it from both the load info and the store info. The instruction + // can't be in either of these maps if it is non-pointer. + if (isa(RemInst->getType())) { + RemoveCachedNonLocalPointerDependencies(ValueIsLoadPair(RemInst, false)); + RemoveCachedNonLocalPointerDependencies(ValueIsLoadPair(RemInst, true)); + } + + // Loop over all of the things that depend on the instruction we're removing. + // + SmallVector, 8> ReverseDepsToAdd; + + // If we find RemInst as a clobber or Def in any of the maps for other values, + // we need to replace its entry with a dirty version of the instruction after + // it. If RemInst is a terminator, we use a null dirty value. + // + // Using a dirty version of the instruction after RemInst saves having to scan + // the entire block to get to this point. + MemDepResult NewDirtyVal; + if (!RemInst->isTerminator()) + NewDirtyVal = MemDepResult::getDirty(++BasicBlock::iterator(RemInst)); + + ReverseDepMapType::iterator ReverseDepIt = ReverseLocalDeps.find(RemInst); + if (ReverseDepIt != ReverseLocalDeps.end()) { + SmallPtrSet &ReverseDeps = ReverseDepIt->second; + // RemInst can't be the terminator if it has local stuff depending on it. + assert(!ReverseDeps.empty() && !isa(RemInst) && + "Nothing can locally depend on a terminator"); + + for (SmallPtrSet::iterator I = ReverseDeps.begin(), + E = ReverseDeps.end(); I != E; ++I) { + Instruction *InstDependingOnRemInst = *I; + assert(InstDependingOnRemInst != RemInst && + "Already removed our local dep info"); + + LocalDeps[InstDependingOnRemInst] = NewDirtyVal; + + // Make sure to remember that new things depend on NewDepInst. + assert(NewDirtyVal.getInst() && "There is no way something else can have " + "a local dep on this if it is a terminator!"); + ReverseDepsToAdd.push_back(std::make_pair(NewDirtyVal.getInst(), + InstDependingOnRemInst)); + } + + ReverseLocalDeps.erase(ReverseDepIt); + + // Add new reverse deps after scanning the set, to avoid invalidating the + // 'ReverseDeps' reference. + while (!ReverseDepsToAdd.empty()) { + ReverseLocalDeps[ReverseDepsToAdd.back().first] + .insert(ReverseDepsToAdd.back().second); + ReverseDepsToAdd.pop_back(); + } + } + + ReverseDepIt = ReverseNonLocalDeps.find(RemInst); + if (ReverseDepIt != ReverseNonLocalDeps.end()) { + SmallPtrSet &Set = ReverseDepIt->second; + for (SmallPtrSet::iterator I = Set.begin(), E = Set.end(); + I != E; ++I) { + assert(*I != RemInst && "Already removed NonLocalDep info for RemInst"); + + PerInstNLInfo &INLD = NonLocalDeps[*I]; + // The information is now dirty! + INLD.second = true; + + for (NonLocalDepInfo::iterator DI = INLD.first.begin(), + DE = INLD.first.end(); DI != DE; ++DI) { + if (DI->second.getInst() != RemInst) continue; + + // Convert to a dirty entry for the subsequent instruction. + DI->second = NewDirtyVal; + + if (Instruction *NextI = NewDirtyVal.getInst()) + ReverseDepsToAdd.push_back(std::make_pair(NextI, *I)); + } + } + + ReverseNonLocalDeps.erase(ReverseDepIt); + + // Add new reverse deps after scanning the set, to avoid invalidating 'Set' + while (!ReverseDepsToAdd.empty()) { + ReverseNonLocalDeps[ReverseDepsToAdd.back().first] + .insert(ReverseDepsToAdd.back().second); + ReverseDepsToAdd.pop_back(); + } + } + + // If the instruction is in ReverseNonLocalPtrDeps then it appears as a + // value in the NonLocalPointerDeps info. + ReverseNonLocalPtrDepTy::iterator ReversePtrDepIt = + ReverseNonLocalPtrDeps.find(RemInst); + if (ReversePtrDepIt != ReverseNonLocalPtrDeps.end()) { + SmallPtrSet &Set = ReversePtrDepIt->second; + SmallVector,8> ReversePtrDepsToAdd; + + for (SmallPtrSet::iterator I = Set.begin(), + E = Set.end(); I != E; ++I) { + ValueIsLoadPair P = *I; + assert(P.getPointer() != RemInst && + "Already removed NonLocalPointerDeps info for RemInst"); + + NonLocalDepInfo &NLPDI = NonLocalPointerDeps[P].second; + + // The cache is not valid for any specific block anymore. + NonLocalPointerDeps[P].first = BBSkipFirstBlockPair(); + + // Update any entries for RemInst to use the instruction after it. + for (NonLocalDepInfo::iterator DI = NLPDI.begin(), DE = NLPDI.end(); + DI != DE; ++DI) { + if (DI->second.getInst() != RemInst) continue; + + // Convert to a dirty entry for the subsequent instruction. + DI->second = NewDirtyVal; + + if (Instruction *NewDirtyInst = NewDirtyVal.getInst()) + ReversePtrDepsToAdd.push_back(std::make_pair(NewDirtyInst, P)); + } + + // Re-sort the NonLocalDepInfo. Changing the dirty entry to its + // subsequent value may invalidate the sortedness. + std::sort(NLPDI.begin(), NLPDI.end()); + } + + ReverseNonLocalPtrDeps.erase(ReversePtrDepIt); + + while (!ReversePtrDepsToAdd.empty()) { + ReverseNonLocalPtrDeps[ReversePtrDepsToAdd.back().first] + .insert(ReversePtrDepsToAdd.back().second); + ReversePtrDepsToAdd.pop_back(); + } + } + + + assert(!NonLocalDeps.count(RemInst) && "RemInst got reinserted?"); + AA->deleteValue(RemInst); + DEBUG(verifyRemoved(RemInst)); +} +/// verifyRemoved - Verify that the specified instruction does not occur +/// in our internal data structures. +void MemoryDependenceAnalysis::verifyRemoved(Instruction *D) const { + for (LocalDepMapType::const_iterator I = LocalDeps.begin(), + E = LocalDeps.end(); I != E; ++I) { + assert(I->first != D && "Inst occurs in data structures"); + assert(I->second.getInst() != D && + "Inst occurs in data structures"); + } + + for (CachedNonLocalPointerInfo::const_iterator I =NonLocalPointerDeps.begin(), + E = NonLocalPointerDeps.end(); I != E; ++I) { + assert(I->first.getPointer() != D && "Inst occurs in NLPD map key"); + const NonLocalDepInfo &Val = I->second.second; + for (NonLocalDepInfo::const_iterator II = Val.begin(), E = Val.end(); + II != E; ++II) + assert(II->second.getInst() != D && "Inst occurs as NLPD value"); + } + + for (NonLocalDepMapType::const_iterator I = NonLocalDeps.begin(), + E = NonLocalDeps.end(); I != E; ++I) { + assert(I->first != D && "Inst occurs in data structures"); + const PerInstNLInfo &INLD = I->second; + for (NonLocalDepInfo::const_iterator II = INLD.first.begin(), + EE = INLD.first.end(); II != EE; ++II) + assert(II->second.getInst() != D && "Inst occurs in data structures"); + } + + for (ReverseDepMapType::const_iterator I = ReverseLocalDeps.begin(), + E = ReverseLocalDeps.end(); I != E; ++I) { + assert(I->first != D && "Inst occurs in data structures"); + for (SmallPtrSet::const_iterator II = I->second.begin(), + EE = I->second.end(); II != EE; ++II) + assert(*II != D && "Inst occurs in data structures"); + } + + for (ReverseDepMapType::const_iterator I = ReverseNonLocalDeps.begin(), + E = ReverseNonLocalDeps.end(); + I != E; ++I) { + assert(I->first != D && "Inst occurs in data structures"); + for (SmallPtrSet::const_iterator II = I->second.begin(), + EE = I->second.end(); II != EE; ++II) + assert(*II != D && "Inst occurs in data structures"); + } + + for (ReverseNonLocalPtrDepTy::const_iterator + I = ReverseNonLocalPtrDeps.begin(), + E = ReverseNonLocalPtrDeps.end(); I != E; ++I) { + assert(I->first != D && "Inst occurs in rev NLPD map"); + + for (SmallPtrSet::const_iterator II = I->second.begin(), + E = I->second.end(); II != E; ++II) + assert(*II != ValueIsLoadPair(D, false) && + *II != ValueIsLoadPair(D, true) && + "Inst occurs in ReverseNonLocalPtrDeps map"); + } + +} diff --git a/libclamav/c++/llvm/lib/Analysis/PointerTracking.cpp b/libclamav/c++/llvm/lib/Analysis/PointerTracking.cpp new file mode 100644 index 000000000..8da07e756 --- /dev/null +++ b/libclamav/c++/llvm/lib/Analysis/PointerTracking.cpp @@ -0,0 +1,267 @@ +//===- PointerTracking.cpp - Pointer Bounds Tracking ------------*- 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 tracking of pointer bounds. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Analysis/ConstantFolding.h" +#include "llvm/Analysis/Dominators.h" +#include "llvm/Analysis/LoopInfo.h" +#include "llvm/Analysis/MemoryBuiltins.h" +#include "llvm/Analysis/PointerTracking.h" +#include "llvm/Analysis/ScalarEvolution.h" +#include "llvm/Analysis/ScalarEvolutionExpressions.h" +#include "llvm/Constants.h" +#include "llvm/Module.h" +#include "llvm/Value.h" +#include "llvm/Support/CallSite.h" +#include "llvm/Support/InstIterator.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Target/TargetData.h" +using namespace llvm; + +char PointerTracking::ID = 0; +PointerTracking::PointerTracking() : FunctionPass(&ID) {} + +bool PointerTracking::runOnFunction(Function &F) { + predCache.clear(); + assert(analyzing.empty()); + FF = &F; + TD = getAnalysisIfAvailable(); + SE = &getAnalysis(); + LI = &getAnalysis(); + DT = &getAnalysis(); + return false; +} + +void PointerTracking::getAnalysisUsage(AnalysisUsage &AU) const { + AU.addRequiredTransitive(); + AU.addRequiredTransitive(); + AU.addRequiredTransitive(); + AU.setPreservesAll(); +} + +bool PointerTracking::doInitialization(Module &M) { + const Type *PTy = Type::getInt8PtrTy(M.getContext()); + + // Find calloc(i64, i64) or calloc(i32, i32). + callocFunc = M.getFunction("calloc"); + if (callocFunc) { + const FunctionType *Ty = callocFunc->getFunctionType(); + + std::vector args, args2; + args.push_back(Type::getInt64Ty(M.getContext())); + args.push_back(Type::getInt64Ty(M.getContext())); + args2.push_back(Type::getInt32Ty(M.getContext())); + args2.push_back(Type::getInt32Ty(M.getContext())); + const FunctionType *Calloc1Type = + FunctionType::get(PTy, args, false); + const FunctionType *Calloc2Type = + FunctionType::get(PTy, args2, false); + if (Ty != Calloc1Type && Ty != Calloc2Type) + callocFunc = 0; // Give up + } + + // Find realloc(i8*, i64) or realloc(i8*, i32). + reallocFunc = M.getFunction("realloc"); + if (reallocFunc) { + const FunctionType *Ty = reallocFunc->getFunctionType(); + std::vector args, args2; + args.push_back(PTy); + args.push_back(Type::getInt64Ty(M.getContext())); + args2.push_back(PTy); + args2.push_back(Type::getInt32Ty(M.getContext())); + + const FunctionType *Realloc1Type = + FunctionType::get(PTy, args, false); + const FunctionType *Realloc2Type = + FunctionType::get(PTy, args2, false); + if (Ty != Realloc1Type && Ty != Realloc2Type) + reallocFunc = 0; // Give up + } + return false; +} + +// Calculates the number of elements allocated for pointer P, +// the type of the element is stored in Ty. +const SCEV *PointerTracking::computeAllocationCount(Value *P, + const Type *&Ty) const { + Value *V = P->stripPointerCasts(); + if (AllocaInst *AI = dyn_cast(V)) { + Value *arraySize = AI->getArraySize(); + Ty = AI->getAllocatedType(); + // arraySize elements of type Ty. + return SE->getSCEV(arraySize); + } + + if (CallInst *CI = extractMallocCall(V)) { + Value *arraySize = getMallocArraySize(CI, TD); + const Type* AllocTy = getMallocAllocatedType(CI); + if (!AllocTy || !arraySize) return SE->getCouldNotCompute(); + Ty = AllocTy; + // arraySize elements of type Ty. + return SE->getSCEV(arraySize); + } + + if (GlobalVariable *GV = dyn_cast(V)) { + if (GV->hasDefinitiveInitializer()) { + Constant *C = GV->getInitializer(); + if (const ArrayType *ATy = dyn_cast(C->getType())) { + Ty = ATy->getElementType(); + return SE->getConstant(Type::getInt32Ty(P->getContext()), + ATy->getNumElements()); + } + } + Ty = GV->getType(); + return SE->getConstant(Type::getInt32Ty(P->getContext()), 1); + //TODO: implement more tracking for globals + } + + if (CallInst *CI = dyn_cast(V)) { + CallSite CS(CI); + Function *F = dyn_cast(CS.getCalledValue()->stripPointerCasts()); + const Loop *L = LI->getLoopFor(CI->getParent()); + if (F == callocFunc) { + Ty = Type::getInt8Ty(P->getContext()); + // calloc allocates arg0*arg1 bytes. + return SE->getSCEVAtScope(SE->getMulExpr(SE->getSCEV(CS.getArgument(0)), + SE->getSCEV(CS.getArgument(1))), + L); + } else if (F == reallocFunc) { + Ty = Type::getInt8Ty(P->getContext()); + // realloc allocates arg1 bytes. + return SE->getSCEVAtScope(CS.getArgument(1), L); + } + } + + return SE->getCouldNotCompute(); +} + +// Calculates the number of elements of type Ty allocated for P. +const SCEV *PointerTracking::computeAllocationCountForType(Value *P, + const Type *Ty) + const { + const Type *elementTy; + const SCEV *Count = computeAllocationCount(P, elementTy); + if (isa(Count)) + return Count; + if (elementTy == Ty) + return Count; + + if (!TD) // need TargetData from this point forward + return SE->getCouldNotCompute(); + + uint64_t elementSize = TD->getTypeAllocSize(elementTy); + uint64_t wantSize = TD->getTypeAllocSize(Ty); + if (elementSize == wantSize) + return Count; + if (elementSize % wantSize) //fractional counts not possible + return SE->getCouldNotCompute(); + return SE->getMulExpr(Count, SE->getConstant(Count->getType(), + elementSize/wantSize)); +} + +const SCEV *PointerTracking::getAllocationElementCount(Value *V) const { + // We only deal with pointers. + const PointerType *PTy = cast(V->getType()); + return computeAllocationCountForType(V, PTy->getElementType()); +} + +const SCEV *PointerTracking::getAllocationSizeInBytes(Value *V) const { + return computeAllocationCountForType(V, Type::getInt8Ty(V->getContext())); +} + +// Helper for isLoopGuardedBy that checks the swapped and inverted predicate too +enum SolverResult PointerTracking::isLoopGuardedBy(const Loop *L, + Predicate Pred, + const SCEV *A, + const SCEV *B) const { + if (SE->isLoopGuardedByCond(L, Pred, A, B)) + return AlwaysTrue; + Pred = ICmpInst::getSwappedPredicate(Pred); + if (SE->isLoopGuardedByCond(L, Pred, B, A)) + return AlwaysTrue; + + Pred = ICmpInst::getInversePredicate(Pred); + if (SE->isLoopGuardedByCond(L, Pred, B, A)) + return AlwaysFalse; + Pred = ICmpInst::getSwappedPredicate(Pred); + if (SE->isLoopGuardedByCond(L, Pred, A, B)) + return AlwaysTrue; + return Unknown; +} + +enum SolverResult PointerTracking::checkLimits(const SCEV *Offset, + const SCEV *Limit, + BasicBlock *BB) +{ + //FIXME: merge implementation + return Unknown; +} + +void PointerTracking::getPointerOffset(Value *Pointer, Value *&Base, + const SCEV *&Limit, + const SCEV *&Offset) const +{ + Pointer = Pointer->stripPointerCasts(); + Base = Pointer->getUnderlyingObject(); + Limit = getAllocationSizeInBytes(Base); + if (isa(Limit)) { + Base = 0; + Offset = Limit; + return; + } + + Offset = SE->getMinusSCEV(SE->getSCEV(Pointer), SE->getSCEV(Base)); + if (isa(Offset)) { + Base = 0; + Limit = Offset; + } +} + +void PointerTracking::print(raw_ostream &OS, const Module* M) const { + // Calling some PT methods may cause caches to be updated, however + // this should be safe for the same reason its safe for SCEV. + PointerTracking &PT = *const_cast(this); + for (inst_iterator I=inst_begin(*FF), E=inst_end(*FF); I != E; ++I) { + if (!isa(I->getType())) + continue; + Value *Base; + const SCEV *Limit, *Offset; + getPointerOffset(&*I, Base, Limit, Offset); + if (!Base) + continue; + + if (Base == &*I) { + const SCEV *S = getAllocationElementCount(Base); + OS << *Base << " ==> " << *S << " elements, "; + OS << *Limit << " bytes allocated\n"; + continue; + } + OS << &*I << " -- base: " << *Base; + OS << " offset: " << *Offset; + + enum SolverResult res = PT.checkLimits(Offset, Limit, I->getParent()); + switch (res) { + case AlwaysTrue: + OS << " always safe\n"; + break; + case AlwaysFalse: + OS << " always unsafe\n"; + break; + case Unknown: + OS << " <>\n"; + break; + } + } +} + +static RegisterPass X("pointertracking", + "Track pointer bounds", false, true); diff --git a/libclamav/c++/llvm/lib/Analysis/PostDominators.cpp b/libclamav/c++/llvm/lib/Analysis/PostDominators.cpp new file mode 100644 index 000000000..69d6b47bb --- /dev/null +++ b/libclamav/c++/llvm/lib/Analysis/PostDominators.cpp @@ -0,0 +1,98 @@ +//===- PostDominators.cpp - Post-Dominator Calculation --------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the post-dominator construction algorithms. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "postdomtree" + +#include "llvm/Analysis/PostDominators.h" +#include "llvm/Instructions.h" +#include "llvm/Support/CFG.h" +#include "llvm/Support/Debug.h" +#include "llvm/ADT/DepthFirstIterator.h" +#include "llvm/ADT/SetOperations.h" +#include "llvm/Analysis/DominatorInternals.h" +using namespace llvm; + +//===----------------------------------------------------------------------===// +// PostDominatorTree Implementation +//===----------------------------------------------------------------------===// + +char PostDominatorTree::ID = 0; +char PostDominanceFrontier::ID = 0; +static RegisterPass +F("postdomtree", "Post-Dominator Tree Construction", true, true); + +bool PostDominatorTree::runOnFunction(Function &F) { + DT->recalculate(F); + DEBUG(DT->print(errs())); + return false; +} + +PostDominatorTree::~PostDominatorTree() { + delete DT; +} + +void PostDominatorTree::print(raw_ostream &OS, const Module *) const { + DT->print(OS); +} + + +FunctionPass* llvm::createPostDomTree() { + return new PostDominatorTree(); +} + +//===----------------------------------------------------------------------===// +// PostDominanceFrontier Implementation +//===----------------------------------------------------------------------===// + +static RegisterPass +H("postdomfrontier", "Post-Dominance Frontier Construction", true, true); + +const DominanceFrontier::DomSetType & +PostDominanceFrontier::calculate(const PostDominatorTree &DT, + const DomTreeNode *Node) { + // Loop over CFG successors to calculate DFlocal[Node] + BasicBlock *BB = Node->getBlock(); + DomSetType &S = Frontiers[BB]; // The new set to fill in... + if (getRoots().empty()) return S; + + if (BB) + for (pred_iterator SI = pred_begin(BB), SE = pred_end(BB); + SI != SE; ++SI) { + // Does Node immediately dominate this predecessor? + DomTreeNode *SINode = DT[*SI]; + if (SINode && SINode->getIDom() != Node) + S.insert(*SI); + } + + // At this point, S is DFlocal. Now we union in DFup's of our children... + // Loop through and visit the nodes that Node immediately dominates (Node's + // children in the IDomTree) + // + for (DomTreeNode::const_iterator + NI = Node->begin(), NE = Node->end(); NI != NE; ++NI) { + DomTreeNode *IDominee = *NI; + const DomSetType &ChildDF = calculate(DT, IDominee); + + DomSetType::const_iterator CDFI = ChildDF.begin(), CDFE = ChildDF.end(); + for (; CDFI != CDFE; ++CDFI) { + if (!DT.properlyDominates(Node, DT[*CDFI])) + S.insert(*CDFI); + } + } + + return S; +} + +FunctionPass* llvm::createPostDomFrontier() { + return new PostDominanceFrontier(); +} diff --git a/libclamav/c++/llvm/lib/Analysis/ProfileEstimatorPass.cpp b/libclamav/c++/llvm/lib/Analysis/ProfileEstimatorPass.cpp new file mode 100644 index 000000000..e767891ea --- /dev/null +++ b/libclamav/c++/llvm/lib/Analysis/ProfileEstimatorPass.cpp @@ -0,0 +1,309 @@ +//===- ProfileEstimatorPass.cpp - LLVM Pass to estimate profile info ------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements a concrete implementation of profiling information that +// estimates the profiling information in a very crude and unimaginative way. +// +//===----------------------------------------------------------------------===// +#define DEBUG_TYPE "profile-estimator" +#include "llvm/Pass.h" +#include "llvm/Analysis/Passes.h" +#include "llvm/Analysis/ProfileInfo.h" +#include "llvm/Analysis/LoopInfo.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/Format.h" +using namespace llvm; + +static cl::opt +LoopWeight( + "profile-estimator-loop-weight", cl::init(10), + cl::value_desc("loop-weight"), + cl::desc("Number of loop executions used for profile-estimator") +); + +namespace { + class ProfileEstimatorPass : public FunctionPass, public ProfileInfo { + double ExecCount; + LoopInfo *LI; + std::set BBToVisit; + std::map LoopExitWeights; + public: + static char ID; // Class identification, replacement for typeinfo + explicit ProfileEstimatorPass(const double execcount = 0) + : FunctionPass(&ID), ExecCount(execcount) { + if (execcount == 0) ExecCount = LoopWeight; + } + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + AU.addRequired(); + } + + virtual const char *getPassName() const { + return "Profiling information estimator"; + } + + /// run - Estimate the profile information from the specified file. + virtual bool runOnFunction(Function &F); + + virtual void recurseBasicBlock(BasicBlock *BB); + + void inline printEdgeWeight(Edge); + }; +} // End of anonymous namespace + +char ProfileEstimatorPass::ID = 0; +static RegisterPass +X("profile-estimator", "Estimate profiling information", false, true); + +static RegisterAnalysisGroup Y(X); + +namespace llvm { + const PassInfo *ProfileEstimatorPassID = &X; + + FunctionPass *createProfileEstimatorPass() { + return new ProfileEstimatorPass(); + } + + /// createProfileEstimatorPass - This function returns a Pass that estimates + /// profiling information using the given loop execution count. + Pass *createProfileEstimatorPass(const unsigned execcount) { + return new ProfileEstimatorPass(execcount); + } +} + +static double ignoreMissing(double w) { + if (w == ProfileInfo::MissingValue) return 0; + return w; +} + +static void inline printEdgeError(ProfileInfo::Edge e, const char *M) { + DEBUG(errs() << "-- Edge " << e << " is not calculated, " << M << "\n"); +} + +void inline ProfileEstimatorPass::printEdgeWeight(Edge E) { + DEBUG(errs() << "-- Weight of Edge " << E << ":" + << format("%g", getEdgeWeight(E)) << "\n"); +} + +// recurseBasicBlock() - This calculates the ProfileInfo estimation for a +// single block and then recurses into the successors. +// The algorithm preserves the flow condition, meaning that the sum of the +// weight of the incoming edges must be equal the block weight which must in +// turn be equal to the sume of the weights of the outgoing edges. +// Since the flow of an block is deterimined from the current state of the +// flow, once an edge has a flow assigned this flow is never changed again, +// otherwise it would be possible to violate the flow condition in another +// block. +void ProfileEstimatorPass::recurseBasicBlock(BasicBlock *BB) { + + // Break the recursion if this BasicBlock was already visited. + if (BBToVisit.find(BB) == BBToVisit.end()) return; + + // Read the LoopInfo for this block. + bool BBisHeader = LI->isLoopHeader(BB); + Loop* BBLoop = LI->getLoopFor(BB); + + // To get the block weight, read all incoming edges. + double BBWeight = 0; + std::set ProcessedPreds; + for ( pred_iterator bbi = pred_begin(BB), bbe = pred_end(BB); + bbi != bbe; ++bbi ) { + // If this block was not considered already, add weight. + Edge edge = getEdge(*bbi,BB); + double w = getEdgeWeight(edge); + if (ProcessedPreds.insert(*bbi).second) { + BBWeight += ignoreMissing(w); + } + // If this block is a loop header and the predecessor is contained in this + // loop, thus the edge is a backedge, continue and do not check if the + // value is valid. + if (BBisHeader && BBLoop->contains(*bbi)) { + printEdgeError(edge, "but is backedge, continueing"); + continue; + } + // If the edges value is missing (and this is no loop header, and this is + // no backedge) return, this block is currently non estimatable. + if (w == MissingValue) { + printEdgeError(edge, "returning"); + return; + } + } + if (getExecutionCount(BB) != MissingValue) { + BBWeight = getExecutionCount(BB); + } + + // Fetch all necessary information for current block. + SmallVector ExitEdges; + SmallVector Edges; + if (BBLoop) { + BBLoop->getExitEdges(ExitEdges); + } + + // If this is a loop header, consider the following: + // Exactly the flow that is entering this block, must exit this block too. So + // do the following: + // *) get all the exit edges, read the flow that is already leaving this + // loop, remember the edges that do not have any flow on them right now. + // (The edges that have already flow on them are most likely exiting edges of + // other loops, do not touch those flows because the previously caclulated + // loopheaders would not be exact anymore.) + // *) In case there is not a single exiting edge left, create one at the loop + // latch to prevent the flow from building up in the loop. + // *) Take the flow that is not leaving the loop already and distribute it on + // the remaining exiting edges. + // (This ensures that all flow that enters the loop also leaves it.) + // *) Increase the flow into the loop by increasing the weight of this block. + // There is at least one incoming backedge that will bring us this flow later + // on. (So that the flow condition in this node is valid again.) + if (BBisHeader) { + double incoming = BBWeight; + // Subtract the flow leaving the loop. + std::set ProcessedExits; + for (SmallVector::iterator ei = ExitEdges.begin(), + ee = ExitEdges.end(); ei != ee; ++ei) { + if (ProcessedExits.insert(*ei).second) { + double w = getEdgeWeight(*ei); + if (w == MissingValue) { + Edges.push_back(*ei); + } else { + incoming -= w; + } + } + } + // If no exit edges, create one: + if (Edges.size() == 0) { + BasicBlock *Latch = BBLoop->getLoopLatch(); + if (Latch) { + Edge edge = getEdge(Latch,0); + EdgeInformation[BB->getParent()][edge] = BBWeight; + printEdgeWeight(edge); + edge = getEdge(Latch, BB); + EdgeInformation[BB->getParent()][edge] = BBWeight * ExecCount; + printEdgeWeight(edge); + } + } + // Distribute remaining weight onto the exit edges. + for (SmallVector::iterator ei = Edges.begin(), ee = Edges.end(); + ei != ee; ++ei) { + EdgeInformation[BB->getParent()][*ei] += incoming/Edges.size(); + printEdgeWeight(*ei); + } + // Increase flow into the loop. + BBWeight *= (ExecCount+1); + } + + BlockInformation[BB->getParent()][BB] = BBWeight; + // Up until now we considered only the loop exiting edges, now we have a + // definite block weight and must ditribute this onto the outgoing edges. + // Since there may be already flow attached to some of the edges, read this + // flow first and remember the edges that have still now flow attached. + Edges.clear(); + std::set ProcessedSuccs; + + succ_iterator bbi = succ_begin(BB), bbe = succ_end(BB); + // Also check for (BB,0) edges that may already contain some flow. (But only + // in case there are no successors.) + if (bbi == bbe) { + Edge edge = getEdge(BB,0); + EdgeInformation[BB->getParent()][edge] = BBWeight; + printEdgeWeight(edge); + } + for ( ; bbi != bbe; ++bbi ) { + if (ProcessedSuccs.insert(*bbi).second) { + Edge edge = getEdge(BB,*bbi); + double w = getEdgeWeight(edge); + if (w != MissingValue) { + BBWeight -= getEdgeWeight(edge); + } else { + Edges.push_back(edge); + } + } + } + + // Finally we know what flow is still not leaving the block, distribute this + // flow onto the empty edges. + for (SmallVector::iterator ei = Edges.begin(), ee = Edges.end(); + ei != ee; ++ei) { + EdgeInformation[BB->getParent()][*ei] += BBWeight/Edges.size(); + printEdgeWeight(*ei); + } + + // This block is visited, mark this before the recursion. + BBToVisit.erase(BB); + + // Recurse into successors. + for (succ_iterator bbi = succ_begin(BB), bbe = succ_end(BB); + bbi != bbe; ++bbi) { + recurseBasicBlock(*bbi); + } +} + +bool ProfileEstimatorPass::runOnFunction(Function &F) { + if (F.isDeclaration()) return false; + + // Fetch LoopInfo and clear ProfileInfo for this function. + LI = &getAnalysis(); + FunctionInformation.erase(&F); + BlockInformation[&F].clear(); + EdgeInformation[&F].clear(); + + // Mark all blocks as to visit. + for (Function::iterator bi = F.begin(), be = F.end(); bi != be; ++bi) + BBToVisit.insert(bi); + + DEBUG(errs() << "Working on function " << F.getNameStr() << "\n"); + + // Since the entry block is the first one and has no predecessors, the edge + // (0,entry) is inserted with the starting weight of 1. + BasicBlock *entry = &F.getEntryBlock(); + BlockInformation[&F][entry] = 1; + Edge edge = getEdge(0,entry); + EdgeInformation[&F][edge] = 1; + printEdgeWeight(edge); + + // Since recurseBasicBlock() maybe returns with a block which was not fully + // estimated, use recurseBasicBlock() until everything is calculated. + recurseBasicBlock(entry); + while (BBToVisit.size() > 0) { + // Remember number of open blocks, this is later used to check if progress + // was made. + unsigned size = BBToVisit.size(); + + // Try to calculate all blocks in turn. + for (std::set::iterator bi = BBToVisit.begin(), + be = BBToVisit.end(); bi != be; ++bi) { + recurseBasicBlock(*bi); + // If at least one block was finished, break because iterator may be + // invalid. + if (BBToVisit.size() < size) break; + } + + // If there was not a single block resovled, make some assumptions. + if (BBToVisit.size() == size) { + BasicBlock *BB = *(BBToVisit.begin()); + // Since this BB was not calculated because of missing incoming edges, + // set these edges to zero. + for (pred_iterator bbi = pred_begin(BB), bbe = pred_end(BB); + bbi != bbe; ++bbi) { + Edge e = getEdge(*bbi,BB); + double w = getEdgeWeight(e); + if (w == MissingValue) { + EdgeInformation[&F][e] = 0; + DEBUG(errs() << "Assuming edge weight: "); + printEdgeWeight(e); + } + } + } + } + + return false; +} diff --git a/libclamav/c++/llvm/lib/Analysis/ProfileInfo.cpp b/libclamav/c++/llvm/lib/Analysis/ProfileInfo.cpp new file mode 100644 index 000000000..7f24f5a23 --- /dev/null +++ b/libclamav/c++/llvm/lib/Analysis/ProfileInfo.cpp @@ -0,0 +1,194 @@ +//===- ProfileInfo.cpp - Profile Info Interface ---------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the abstract ProfileInfo interface, and the default +// "no profile" implementation. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Analysis/Passes.h" +#include "llvm/Analysis/ProfileInfo.h" +#include "llvm/Pass.h" +#include "llvm/Support/CFG.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/Format.h" +#include +using namespace llvm; + +// Register the ProfileInfo interface, providing a nice name to refer to. +static RegisterAnalysisGroup Z("Profile Information"); +char ProfileInfo::ID = 0; + +ProfileInfo::~ProfileInfo() {} + +const double ProfileInfo::MissingValue = -1; + +double ProfileInfo::getExecutionCount(const BasicBlock *BB) { + std::map::iterator J = + BlockInformation.find(BB->getParent()); + if (J != BlockInformation.end()) { + BlockCounts::iterator I = J->second.find(BB); + if (I != J->second.end()) + return I->second; + } + + pred_const_iterator PI = pred_begin(BB), PE = pred_end(BB); + + // Are there zero predecessors of this block? + if (PI == PE) { + // If this is the entry block, look for the Null -> Entry edge. + if (BB == &BB->getParent()->getEntryBlock()) + return getEdgeWeight(getEdge(0, BB)); + else + return 0; // Otherwise, this is a dead block. + } + + // Otherwise, if there are predecessors, the execution count of this block is + // the sum of the edge frequencies from the incoming edges. + std::set ProcessedPreds; + double Count = 0; + for (; PI != PE; ++PI) + if (ProcessedPreds.insert(*PI).second) { + double w = getEdgeWeight(getEdge(*PI, BB)); + if (w == MissingValue) { + Count = MissingValue; + break; + } + Count += w; + } + + if (Count != MissingValue) BlockInformation[BB->getParent()][BB] = Count; + return Count; +} + +double ProfileInfo::getExecutionCount(const Function *F) { + std::map::iterator J = + FunctionInformation.find(F); + if (J != FunctionInformation.end()) + return J->second; + + // isDeclaration() is checked here and not at start of function to allow + // functions without a body still to have a execution count. + if (F->isDeclaration()) return MissingValue; + + double Count = getExecutionCount(&F->getEntryBlock()); + if (Count != MissingValue) FunctionInformation[F] = Count; + return Count; +} + +/// Replaces all occurences of RmBB in the ProfilingInfo with DestBB. +/// This checks all edges of the function the blocks reside in and replaces the +/// occurences of RmBB with DestBB. +void ProfileInfo::replaceAllUses(const BasicBlock *RmBB, + const BasicBlock *DestBB) { + DEBUG(errs() << "Replacing " << RmBB->getNameStr() + << " with " << DestBB->getNameStr() << "\n"); + const Function *F = DestBB->getParent(); + std::map::iterator J = + EdgeInformation.find(F); + if (J == EdgeInformation.end()) return; + + for (EdgeWeights::iterator I = J->second.begin(), E = J->second.end(); + I != E; ++I) { + Edge e = I->first; + Edge newedge; bool foundedge = false; + if (e.first == RmBB) { + newedge = getEdge(DestBB, e.second); + foundedge = true; + } + if (e.second == RmBB) { + newedge = getEdge(e.first, DestBB); + foundedge = true; + } + if (foundedge) { + double w = getEdgeWeight(e); + EdgeInformation[F][newedge] = w; + DEBUG(errs() << "Replacing " << e << " with " << newedge << "\n"); + J->second.erase(e); + } + } +} + +/// Splits an edge in the ProfileInfo and redirects flow over NewBB. +/// Since its possible that there is more than one edge in the CFG from FristBB +/// to SecondBB its necessary to redirect the flow proporionally. +void ProfileInfo::splitEdge(const BasicBlock *FirstBB, + const BasicBlock *SecondBB, + const BasicBlock *NewBB, + bool MergeIdenticalEdges) { + const Function *F = FirstBB->getParent(); + std::map::iterator J = + EdgeInformation.find(F); + if (J == EdgeInformation.end()) return; + + // Generate edges and read current weight. + Edge e = getEdge(FirstBB, SecondBB); + Edge n1 = getEdge(FirstBB, NewBB); + Edge n2 = getEdge(NewBB, SecondBB); + EdgeWeights &ECs = J->second; + double w = ECs[e]; + + int succ_count = 0; + if (!MergeIdenticalEdges) { + // First count the edges from FristBB to SecondBB, if there is more than + // one, only slice out a proporional part for NewBB. + for(succ_const_iterator BBI = succ_begin(FirstBB), BBE = succ_end(FirstBB); + BBI != BBE; ++BBI) { + if (*BBI == SecondBB) succ_count++; + } + // When the NewBB is completely new, increment the count by one so that + // the counts are properly distributed. + if (getExecutionCount(NewBB) == ProfileInfo::MissingValue) succ_count++; + } else { + // When the edges are merged anyway, then redirect all flow. + succ_count = 1; + } + + // We know now how many edges there are from FirstBB to SecondBB, reroute a + // proportional part of the edge weight over NewBB. + double neww = w / succ_count; + ECs[n1] += neww; + ECs[n2] += neww; + BlockInformation[F][NewBB] += neww; + if (succ_count == 1) { + ECs.erase(e); + } else { + ECs[e] -= neww; + } +} + +raw_ostream& llvm::operator<<(raw_ostream &O, ProfileInfo::Edge E) { + O << "("; + O << (E.first ? E.first->getNameStr() : "0"); + O << ","; + O << (E.second ? E.second->getNameStr() : "0"); + return O << ")"; +} + +//===----------------------------------------------------------------------===// +// NoProfile ProfileInfo implementation +// + +namespace { + struct NoProfileInfo : public ImmutablePass, public ProfileInfo { + static char ID; // Class identification, replacement for typeinfo + NoProfileInfo() : ImmutablePass(&ID) {} + }; +} // End of anonymous namespace + +char NoProfileInfo::ID = 0; +// Register this pass... +static RegisterPass +X("no-profile", "No Profile Information", false, true); + +// Declare that we implement the ProfileInfo interface +static RegisterAnalysisGroup Y(X); + +ImmutablePass *llvm::createNoProfileInfoPass() { return new NoProfileInfo(); } diff --git a/libclamav/c++/llvm/lib/Analysis/ProfileInfoLoader.cpp b/libclamav/c++/llvm/lib/Analysis/ProfileInfoLoader.cpp new file mode 100644 index 000000000..25481b2ee --- /dev/null +++ b/libclamav/c++/llvm/lib/Analysis/ProfileInfoLoader.cpp @@ -0,0 +1,158 @@ +//===- ProfileInfoLoad.cpp - Load profile information from disk -----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// The ProfileInfoLoader class is used to load and represent profiling +// information read in from the dump file. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Analysis/ProfileInfoLoader.h" +#include "llvm/Analysis/ProfileInfoTypes.h" +#include "llvm/Module.h" +#include "llvm/InstrTypes.h" +#include "llvm/Support/raw_ostream.h" +#include +#include +#include +using namespace llvm; + +// ByteSwap - Byteswap 'Var' if 'Really' is true. +// +static inline unsigned ByteSwap(unsigned Var, bool Really) { + if (!Really) return Var; + return ((Var & (255U<< 0U)) << 24U) | + ((Var & (255U<< 8U)) << 8U) | + ((Var & (255U<<16U)) >> 8U) | + ((Var & (255U<<24U)) >> 24U); +} + +static unsigned AddCounts(unsigned A, unsigned B) { + // If either value is undefined, use the other. + if (A == ProfileInfoLoader::Uncounted) return B; + if (B == ProfileInfoLoader::Uncounted) return A; + return A + B; +} + +static void ReadProfilingBlock(const char *ToolName, FILE *F, + bool ShouldByteSwap, + std::vector &Data) { + // Read the number of entries... + unsigned NumEntries; + if (fread(&NumEntries, sizeof(unsigned), 1, F) != 1) { + errs() << ToolName << ": data packet truncated!\n"; + perror(0); + exit(1); + } + NumEntries = ByteSwap(NumEntries, ShouldByteSwap); + + // Read the counts... + std::vector TempSpace(NumEntries); + + // Read in the block of data... + if (fread(&TempSpace[0], sizeof(unsigned)*NumEntries, 1, F) != 1) { + errs() << ToolName << ": data packet truncated!\n"; + perror(0); + exit(1); + } + + // Make sure we have enough space... The space is initialised to -1 to + // facitiltate the loading of missing values for OptimalEdgeProfiling. + if (Data.size() < NumEntries) + Data.resize(NumEntries, ProfileInfoLoader::Uncounted); + + // Accumulate the data we just read into the data. + if (!ShouldByteSwap) { + for (unsigned i = 0; i != NumEntries; ++i) { + Data[i] = AddCounts(TempSpace[i], Data[i]); + } + } else { + for (unsigned i = 0; i != NumEntries; ++i) { + Data[i] = AddCounts(ByteSwap(TempSpace[i], true), Data[i]); + } + } +} + +const unsigned ProfileInfoLoader::Uncounted = ~0U; + +// ProfileInfoLoader ctor - Read the specified profiling data file, exiting the +// program if the file is invalid or broken. +// +ProfileInfoLoader::ProfileInfoLoader(const char *ToolName, + const std::string &Filename, + Module &TheModule) : + Filename(Filename), + M(TheModule), Warned(false) { + FILE *F = fopen(Filename.c_str(), "rb"); + if (F == 0) { + errs() << ToolName << ": Error opening '" << Filename << "': "; + perror(0); + exit(1); + } + + // Keep reading packets until we run out of them. + unsigned PacketType; + while (fread(&PacketType, sizeof(unsigned), 1, F) == 1) { + // If the low eight bits of the packet are zero, we must be dealing with an + // endianness mismatch. Byteswap all words read from the profiling + // information. + bool ShouldByteSwap = (char)PacketType == 0; + PacketType = ByteSwap(PacketType, ShouldByteSwap); + + switch (PacketType) { + case ArgumentInfo: { + unsigned ArgLength; + if (fread(&ArgLength, sizeof(unsigned), 1, F) != 1) { + errs() << ToolName << ": arguments packet truncated!\n"; + perror(0); + exit(1); + } + ArgLength = ByteSwap(ArgLength, ShouldByteSwap); + + // Read in the arguments... + std::vector Chars(ArgLength+4); + + if (ArgLength) + if (fread(&Chars[0], (ArgLength+3) & ~3, 1, F) != 1) { + errs() << ToolName << ": arguments packet truncated!\n"; + perror(0); + exit(1); + } + CommandLines.push_back(std::string(&Chars[0], &Chars[ArgLength])); + break; + } + + case FunctionInfo: + ReadProfilingBlock(ToolName, F, ShouldByteSwap, FunctionCounts); + break; + + case BlockInfo: + ReadProfilingBlock(ToolName, F, ShouldByteSwap, BlockCounts); + break; + + case EdgeInfo: + ReadProfilingBlock(ToolName, F, ShouldByteSwap, EdgeCounts); + break; + + case OptEdgeInfo: + ReadProfilingBlock(ToolName, F, ShouldByteSwap, OptimalEdgeCounts); + break; + + case BBTraceInfo: + ReadProfilingBlock(ToolName, F, ShouldByteSwap, BBTrace); + break; + + default: + errs() << ToolName << ": Unknown packet type #" << PacketType << "!\n"; + exit(1); + } + } + + fclose(F); +} + diff --git a/libclamav/c++/llvm/lib/Analysis/ProfileInfoLoaderPass.cpp b/libclamav/c++/llvm/lib/Analysis/ProfileInfoLoaderPass.cpp new file mode 100644 index 000000000..9e1dfb6ff --- /dev/null +++ b/libclamav/c++/llvm/lib/Analysis/ProfileInfoLoaderPass.cpp @@ -0,0 +1,294 @@ +//===- ProfileInfoLoaderPass.cpp - LLVM Pass to load profile info ---------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements a concrete implementation of profiling information that +// loads the information from a profile dump file. +// +//===----------------------------------------------------------------------===// +#define DEBUG_TYPE "profile-loader" +#include "llvm/BasicBlock.h" +#include "llvm/InstrTypes.h" +#include "llvm/Module.h" +#include "llvm/Pass.h" +#include "llvm/Analysis/Passes.h" +#include "llvm/Analysis/ProfileInfo.h" +#include "llvm/Analysis/ProfileInfoLoader.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/CFG.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/Format.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/ADT/SmallSet.h" +#include +using namespace llvm; + +STATISTIC(NumEdgesRead, "The # of edges read."); + +static cl::opt +ProfileInfoFilename("profile-info-file", cl::init("llvmprof.out"), + cl::value_desc("filename"), + cl::desc("Profile file loaded by -profile-loader")); + +namespace { + class LoaderPass : public ModulePass, public ProfileInfo { + std::string Filename; + std::set SpanningTree; + std::set BBisUnvisited; + unsigned ReadCount; + public: + static char ID; // Class identification, replacement for typeinfo + explicit LoaderPass(const std::string &filename = "") + : ModulePass(&ID), Filename(filename) { + if (filename.empty()) Filename = ProfileInfoFilename; + } + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + } + + virtual const char *getPassName() const { + return "Profiling information loader"; + } + + // recurseBasicBlock() - Calculates the edge weights for as much basic + // blocks as possbile. + virtual void recurseBasicBlock(const BasicBlock *BB); + virtual void readEdgeOrRemember(Edge, Edge&, unsigned &, double &); + virtual void readEdge(ProfileInfo::Edge, std::vector&); + + /// run - Load the profile information from the specified file. + virtual bool runOnModule(Module &M); + }; +} // End of anonymous namespace + +char LoaderPass::ID = 0; +static RegisterPass +X("profile-loader", "Load profile information from llvmprof.out", false, true); + +static RegisterAnalysisGroup Y(X); + +ModulePass *llvm::createProfileLoaderPass() { return new LoaderPass(); } + +/// createProfileLoaderPass - This function returns a Pass that loads the +/// profiling information for the module from the specified filename, making it +/// available to the optimizers. +Pass *llvm::createProfileLoaderPass(const std::string &Filename) { + return new LoaderPass(Filename); +} + +void LoaderPass::readEdgeOrRemember(Edge edge, Edge &tocalc, + unsigned &uncalc, double &count) { + double w; + if ((w = getEdgeWeight(edge)) == MissingValue) { + tocalc = edge; + uncalc++; + } else { + count+=w; + } +} + +// recurseBasicBlock - Visits all neighbours of a block and then tries to +// calculate the missing edge values. +void LoaderPass::recurseBasicBlock(const BasicBlock *BB) { + + // break recursion if already visited + if (BBisUnvisited.find(BB) == BBisUnvisited.end()) return; + BBisUnvisited.erase(BB); + if (!BB) return; + + for (succ_const_iterator bbi = succ_begin(BB), bbe = succ_end(BB); + bbi != bbe; ++bbi) { + recurseBasicBlock(*bbi); + } + for (pred_const_iterator bbi = pred_begin(BB), bbe = pred_end(BB); + bbi != bbe; ++bbi) { + recurseBasicBlock(*bbi); + } + + Edge edgetocalc; + unsigned uncalculated = 0; + + // collect weights of all incoming and outgoing edges, rememer edges that + // have no value + double incount = 0; + SmallSet pred_visited; + pred_const_iterator bbi = pred_begin(BB), bbe = pred_end(BB); + if (bbi==bbe) { + readEdgeOrRemember(getEdge(0, BB),edgetocalc,uncalculated,incount); + } + for (;bbi != bbe; ++bbi) { + if (pred_visited.insert(*bbi)) { + readEdgeOrRemember(getEdge(*bbi, BB),edgetocalc,uncalculated,incount); + } + } + + double outcount = 0; + SmallSet succ_visited; + succ_const_iterator sbbi = succ_begin(BB), sbbe = succ_end(BB); + if (sbbi==sbbe) { + readEdgeOrRemember(getEdge(BB, 0),edgetocalc,uncalculated,outcount); + } + for (;sbbi != sbbe; ++sbbi) { + if (succ_visited.insert(*sbbi)) { + readEdgeOrRemember(getEdge(BB, *sbbi),edgetocalc,uncalculated,outcount); + } + } + + // if exactly one edge weight was missing, calculate it and remove it from + // spanning tree + if (uncalculated == 1) { + if (incount < outcount) { + EdgeInformation[BB->getParent()][edgetocalc] = outcount-incount; + } else { + EdgeInformation[BB->getParent()][edgetocalc] = incount-outcount; + } + DEBUG(errs() << "--Calc Edge Counter for " << edgetocalc << ": " + << format("%g", getEdgeWeight(edgetocalc)) << "\n"); + SpanningTree.erase(edgetocalc); + } +} + +void LoaderPass::readEdge(ProfileInfo::Edge e, + std::vector &ECs) { + if (ReadCount < ECs.size()) { + double weight = ECs[ReadCount++]; + if (weight != ProfileInfoLoader::Uncounted) { + // Here the data realm changes from the unsigned of the file to the + // double of the ProfileInfo. This conversion is save because we know + // that everything thats representable in unsinged is also representable + // in double. + EdgeInformation[getFunction(e)][e] += (double)weight; + + DEBUG(errs() << "--Read Edge Counter for " << e + << " (# "<< (ReadCount-1) << "): " + << (unsigned)getEdgeWeight(e) << "\n"); + } else { + // This happens only if reading optimal profiling information, not when + // reading regular profiling information. + SpanningTree.insert(e); + } + } +} + +bool LoaderPass::runOnModule(Module &M) { + ProfileInfoLoader PIL("profile-loader", Filename, M); + + EdgeInformation.clear(); + std::vector Counters = PIL.getRawEdgeCounts(); + if (Counters.size() > 0) { + ReadCount = 0; + for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F) { + if (F->isDeclaration()) continue; + DEBUG(errs()<<"Working on "<getNameStr()<<"\n"); + readEdge(getEdge(0,&F->getEntryBlock()), Counters); + for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) { + TerminatorInst *TI = BB->getTerminator(); + for (unsigned s = 0, e = TI->getNumSuccessors(); s != e; ++s) { + readEdge(getEdge(BB,TI->getSuccessor(s)), Counters); + } + } + } + if (ReadCount != Counters.size()) { + errs() << "WARNING: profile information is inconsistent with " + << "the current program!\n"; + } + NumEdgesRead = ReadCount; + } + + Counters = PIL.getRawOptimalEdgeCounts(); + if (Counters.size() > 0) { + ReadCount = 0; + for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F) { + if (F->isDeclaration()) continue; + DEBUG(errs()<<"Working on "<getNameStr()<<"\n"); + readEdge(getEdge(0,&F->getEntryBlock()), Counters); + for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) { + TerminatorInst *TI = BB->getTerminator(); + if (TI->getNumSuccessors() == 0) { + readEdge(getEdge(BB,0), Counters); + } + for (unsigned s = 0, e = TI->getNumSuccessors(); s != e; ++s) { + readEdge(getEdge(BB,TI->getSuccessor(s)), Counters); + } + } + while (SpanningTree.size() > 0) { +#if 0 + unsigned size = SpanningTree.size(); +#endif + BBisUnvisited.clear(); + for (std::set::iterator ei = SpanningTree.begin(), + ee = SpanningTree.end(); ei != ee; ++ei) { + BBisUnvisited.insert(ei->first); + BBisUnvisited.insert(ei->second); + } + while (BBisUnvisited.size() > 0) { + recurseBasicBlock(*BBisUnvisited.begin()); + } +#if 0 + if (SpanningTree.size() == size) { + DEBUG(errs()<<"{"); + for (std::set::iterator ei = SpanningTree.begin(), + ee = SpanningTree.end(); ei != ee; ++ei) { + DEBUG(errs()<<"("<<(ei->first?ei->first->getName():"0")<<"," + <<(ei->second?ei->second->getName():"0")<<"),"); + } + assert(0 && "No edge calculated!"); + } +#endif + } + } + if (ReadCount != Counters.size()) { + errs() << "WARNING: profile information is inconsistent with " + << "the current program!\n"; + } + NumEdgesRead = ReadCount; + } + + BlockInformation.clear(); + Counters = PIL.getRawBlockCounts(); + if (Counters.size() > 0) { + ReadCount = 0; + for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F) { + if (F->isDeclaration()) continue; + for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) + if (ReadCount < Counters.size()) + // Here the data realm changes from the unsigned of the file to the + // double of the ProfileInfo. This conversion is save because we know + // that everything thats representable in unsinged is also + // representable in double. + BlockInformation[F][BB] = (double)Counters[ReadCount++]; + } + if (ReadCount != Counters.size()) { + errs() << "WARNING: profile information is inconsistent with " + << "the current program!\n"; + } + } + + FunctionInformation.clear(); + Counters = PIL.getRawFunctionCounts(); + if (Counters.size() > 0) { + ReadCount = 0; + for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F) { + if (F->isDeclaration()) continue; + if (ReadCount < Counters.size()) + // Here the data realm changes from the unsigned of the file to the + // double of the ProfileInfo. This conversion is save because we know + // that everything thats representable in unsinged is also + // representable in double. + FunctionInformation[F] = (double)Counters[ReadCount++]; + } + if (ReadCount != Counters.size()) { + errs() << "WARNING: profile information is inconsistent with " + << "the current program!\n"; + } + } + + return false; +} diff --git a/libclamav/c++/llvm/lib/Analysis/ProfileVerifierPass.cpp b/libclamav/c++/llvm/lib/Analysis/ProfileVerifierPass.cpp new file mode 100644 index 000000000..5f362944d --- /dev/null +++ b/libclamav/c++/llvm/lib/Analysis/ProfileVerifierPass.cpp @@ -0,0 +1,344 @@ +//===- ProfileVerifierPass.cpp - LLVM Pass to estimate profile info -------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements a pass that checks profiling information for +// plausibility. +// +//===----------------------------------------------------------------------===// +#define DEBUG_TYPE "profile-verifier" +#include "llvm/Instructions.h" +#include "llvm/Module.h" +#include "llvm/Pass.h" +#include "llvm/Analysis/ProfileInfo.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/CallSite.h" +#include "llvm/Support/CFG.h" +#include "llvm/Support/InstIterator.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/Debug.h" +#include +using namespace llvm; + +static cl::opt +ProfileVerifierDisableAssertions("profile-verifier-noassert", + cl::desc("Disable assertions")); + +namespace { + class ProfileVerifierPass : public FunctionPass { + + struct DetailedBlockInfo { + const BasicBlock *BB; + double BBWeight; + double inWeight; + int inCount; + double outWeight; + int outCount; + }; + + ProfileInfo *PI; + std::set BBisVisited; + std::set FisVisited; + bool DisableAssertions; + + // When debugging is enabled, the verifier prints a whole slew of debug + // information, otherwise its just the assert. These are all the helper + // functions. + bool PrintedDebugTree; + std::set BBisPrinted; + void debugEntry(DetailedBlockInfo*); + void printDebugInfo(const BasicBlock *BB); + + public: + static char ID; // Class identification, replacement for typeinfo + + explicit ProfileVerifierPass () : FunctionPass(&ID) { + DisableAssertions = ProfileVerifierDisableAssertions; + } + explicit ProfileVerifierPass (bool da) : FunctionPass(&ID), + DisableAssertions(da) { + } + + void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + AU.addRequired(); + } + + const char *getPassName() const { + return "Profiling information verifier"; + } + + /// run - Verify the profile information. + bool runOnFunction(Function &F); + void recurseBasicBlock(const BasicBlock*); + + bool exitReachable(const Function*); + double ReadOrAssert(ProfileInfo::Edge); + void CheckValue(bool, const char*, DetailedBlockInfo*); + }; +} // End of anonymous namespace + +char ProfileVerifierPass::ID = 0; +static RegisterPass +X("profile-verifier", "Verify profiling information", false, true); + +namespace llvm { + FunctionPass *createProfileVerifierPass() { + return new ProfileVerifierPass(ProfileVerifierDisableAssertions); + } +} + +void ProfileVerifierPass::printDebugInfo(const BasicBlock *BB) { + + if (BBisPrinted.find(BB) != BBisPrinted.end()) return; + + double BBWeight = PI->getExecutionCount(BB); + if (BBWeight == ProfileInfo::MissingValue) { BBWeight = 0; } + double inWeight = 0; + int inCount = 0; + std::set ProcessedPreds; + for ( pred_const_iterator bbi = pred_begin(BB), bbe = pred_end(BB); + bbi != bbe; ++bbi ) { + if (ProcessedPreds.insert(*bbi).second) { + ProfileInfo::Edge E = PI->getEdge(*bbi,BB); + double EdgeWeight = PI->getEdgeWeight(E); + if (EdgeWeight == ProfileInfo::MissingValue) { EdgeWeight = 0; } + errs() << "calculated in-edge " << E << ": " << EdgeWeight << "\n"; + inWeight += EdgeWeight; + inCount++; + } + } + double outWeight = 0; + int outCount = 0; + std::set ProcessedSuccs; + for ( succ_const_iterator bbi = succ_begin(BB), bbe = succ_end(BB); + bbi != bbe; ++bbi ) { + if (ProcessedSuccs.insert(*bbi).second) { + ProfileInfo::Edge E = PI->getEdge(BB,*bbi); + double EdgeWeight = PI->getEdgeWeight(E); + if (EdgeWeight == ProfileInfo::MissingValue) { EdgeWeight = 0; } + errs() << "calculated out-edge " << E << ": " << EdgeWeight << "\n"; + outWeight += EdgeWeight; + outCount++; + } + } + errs()<<"Block "<getNameStr()<<" in "<getParent()->getNameStr() + <<",BBWeight="<BB->getNameStr() << " in " + << DI->BB->getParent()->getNameStr() << ":"; + errs() << "BBWeight=" << DI->BBWeight << ","; + errs() << "inWeight=" << DI->inWeight << ","; + errs() << "inCount=" << DI->inCount << ","; + errs() << "outWeight=" << DI->outWeight << ","; + errs() << "outCount=" << DI->outCount << "\n"; + if (!PrintedDebugTree) { + PrintedDebugTree = true; + printDebugInfo(&(DI->BB->getParent()->getEntryBlock())); + } +} + +// This compares A and B but considering maybe small differences. +static bool Equals(double A, double B) { + double maxRelativeError = 0.0000001; + if (A == B) + return true; + double relativeError; + if (fabs(B) > fabs(A)) + relativeError = fabs((A - B) / B); + else + relativeError = fabs((A - B) / A); + if (relativeError <= maxRelativeError) return true; + return false; +} + +// This checks if the function "exit" is reachable from an given function +// via calls, this is necessary to check if a profile is valid despite the +// counts not fitting exactly. +bool ProfileVerifierPass::exitReachable(const Function *F) { + if (!F) return false; + + if (FisVisited.count(F)) return false; + + Function *Exit = F->getParent()->getFunction("exit"); + if (Exit == F) { + return true; + } + + FisVisited.insert(F); + bool exits = false; + for (const_inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I) { + if (const CallInst *CI = dyn_cast(&*I)) { + exits |= exitReachable(CI->getCalledFunction()); + if (exits) break; + } + } + return exits; +} + +#define ASSERTMESSAGE(M) \ + errs() << (M) << "\n"; \ + if (!DisableAssertions) assert(0 && (M)); + +double ProfileVerifierPass::ReadOrAssert(ProfileInfo::Edge E) { + double EdgeWeight = PI->getEdgeWeight(E); + if (EdgeWeight == ProfileInfo::MissingValue) { + errs() << "Edge " << E << " in Function " + << ProfileInfo::getFunction(E)->getNameStr() << ": "; + ASSERTMESSAGE("ASSERT:Edge has missing value"); + return 0; + } else { + return EdgeWeight; + } +} + +void ProfileVerifierPass::CheckValue(bool Error, const char *Message, + DetailedBlockInfo *DI) { + if (Error) { + DEBUG(debugEntry(DI)); + errs() << "Block " << DI->BB->getNameStr() << " in Function " + << DI->BB->getParent()->getNameStr() << ": "; + ASSERTMESSAGE(Message); + } + return; +} + +// This calculates the Information for a block and then recurses into the +// successors. +void ProfileVerifierPass::recurseBasicBlock(const BasicBlock *BB) { + + // Break the recursion by remembering all visited blocks. + if (BBisVisited.find(BB) != BBisVisited.end()) return; + + // Use a data structure to store all the information, this can then be handed + // to debug printers. + DetailedBlockInfo DI; + DI.BB = BB; + DI.outCount = DI.inCount = 0; + DI.inWeight = DI.outWeight = 0.0; + + // Read predecessors. + std::set ProcessedPreds; + pred_const_iterator bpi = pred_begin(BB), bpe = pred_end(BB); + // If there are none, check for (0,BB) edge. + if (bpi == bpe) { + DI.inWeight += ReadOrAssert(PI->getEdge(0,BB)); + DI.inCount++; + } + for (;bpi != bpe; ++bpi) { + if (ProcessedPreds.insert(*bpi).second) { + DI.inWeight += ReadOrAssert(PI->getEdge(*bpi,BB)); + DI.inCount++; + } + } + + // Read successors. + std::set ProcessedSuccs; + succ_const_iterator bbi = succ_begin(BB), bbe = succ_end(BB); + // If there is an (0,BB) edge, consider it too. (This is done not only when + // there are no successors, but every time; not every function contains + // return blocks with no successors (think loop latch as return block)). + double w = PI->getEdgeWeight(PI->getEdge(BB,0)); + if (w != ProfileInfo::MissingValue) { + DI.outWeight += w; + DI.outCount++; + } + for (;bbi != bbe; ++bbi) { + if (ProcessedSuccs.insert(*bbi).second) { + DI.outWeight += ReadOrAssert(PI->getEdge(BB,*bbi)); + DI.outCount++; + } + } + + // Read block weight. + DI.BBWeight = PI->getExecutionCount(BB); + CheckValue(DI.BBWeight == ProfileInfo::MissingValue, + "ASSERT:BasicBlock has missing value", &DI); + + // Check if this block is a setjmp target. + bool isSetJmpTarget = false; + if (DI.outWeight > DI.inWeight) { + for (BasicBlock::const_iterator i = BB->begin(), ie = BB->end(); + i != ie; ++i) { + if (const CallInst *CI = dyn_cast(&*i)) { + Function *F = CI->getCalledFunction(); + if (F && (F->getNameStr() == "_setjmp")) { + isSetJmpTarget = true; break; + } + } + } + } + // Check if this block is eventually reaching exit. + bool isExitReachable = false; + if (DI.inWeight > DI.outWeight) { + for (BasicBlock::const_iterator i = BB->begin(), ie = BB->end(); + i != ie; ++i) { + if (const CallInst *CI = dyn_cast(&*i)) { + FisVisited.clear(); + isExitReachable |= exitReachable(CI->getCalledFunction()); + if (isExitReachable) break; + } + } + } + + if (DI.inCount > 0 && DI.outCount == 0) { + // If this is a block with no successors. + if (!isSetJmpTarget) { + CheckValue(!Equals(DI.inWeight,DI.BBWeight), + "ASSERT:inWeight and BBWeight do not match", &DI); + } + } else if (DI.inCount == 0 && DI.outCount > 0) { + // If this is a block with no predecessors. + if (!isExitReachable) + CheckValue(!Equals(DI.BBWeight,DI.outWeight), + "ASSERT:BBWeight and outWeight do not match", &DI); + } else { + // If this block has successors and predecessors. + if (DI.inWeight > DI.outWeight && !isExitReachable) + CheckValue(!Equals(DI.inWeight,DI.outWeight), + "ASSERT:inWeight and outWeight do not match", &DI); + if (DI.inWeight < DI.outWeight && !isSetJmpTarget) + CheckValue(!Equals(DI.inWeight,DI.outWeight), + "ASSERT:inWeight and outWeight do not match", &DI); + } + + + // Mark this block as visited, rescurse into successors. + BBisVisited.insert(BB); + for ( succ_const_iterator bbi = succ_begin(BB), bbe = succ_end(BB); + bbi != bbe; ++bbi ) { + recurseBasicBlock(*bbi); + } +} + +bool ProfileVerifierPass::runOnFunction(Function &F) { + PI = &getAnalysis(); + + // Prepare global variables. + PrintedDebugTree = false; + BBisVisited.clear(); + + // Fetch entry block and recurse into it. + const BasicBlock *entry = &F.getEntryBlock(); + recurseBasicBlock(entry); + + if (!DisableAssertions) + assert((PI->getExecutionCount(&F)==PI->getExecutionCount(entry)) && + "Function count and entry block count do not match"); + return false; +} diff --git a/libclamav/c++/llvm/lib/Analysis/README.txt b/libclamav/c++/llvm/lib/Analysis/README.txt new file mode 100644 index 000000000..c40109027 --- /dev/null +++ b/libclamav/c++/llvm/lib/Analysis/README.txt @@ -0,0 +1,18 @@ +Analysis Opportunities: + +//===---------------------------------------------------------------------===// + +In test/Transforms/LoopStrengthReduce/quadradic-exit-value.ll, the +ScalarEvolution expression for %r is this: + + {1,+,3,+,2} + +Outside the loop, this could be evaluated simply as (%n * %n), however +ScalarEvolution currently evaluates it as + + (-2 + (2 * (trunc i65 (((zext i64 (-2 + %n) to i65) * (zext i64 (-1 + %n) to i65)) /u 2) to i64)) + (3 * %n)) + +In addition to being much more complicated, it involves i65 arithmetic, +which is very inefficient when expanded into code. + +//===---------------------------------------------------------------------===// diff --git a/libclamav/c++/llvm/lib/Analysis/ScalarEvolution.cpp b/libclamav/c++/llvm/lib/Analysis/ScalarEvolution.cpp new file mode 100644 index 000000000..c6835ef08 --- /dev/null +++ b/libclamav/c++/llvm/lib/Analysis/ScalarEvolution.cpp @@ -0,0 +1,5251 @@ +//===- ScalarEvolution.cpp - Scalar Evolution Analysis ----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the implementation of the scalar evolution analysis +// engine, which is used primarily to analyze expressions involving induction +// variables in loops. +// +// There are several aspects to this library. First is the representation of +// scalar expressions, which are represented as subclasses of the SCEV class. +// These classes are used to represent certain types of subexpressions that we +// can handle. We only create one SCEV of a particular shape, so +// pointer-comparisons for equality are legal. +// +// One important aspect of the SCEV objects is that they are never cyclic, even +// if there is a cycle in the dataflow for an expression (ie, a PHI node). If +// the PHI node is one of the idioms that we can represent (e.g., a polynomial +// recurrence) then we represent it directly as a recurrence node, otherwise we +// represent it as a SCEVUnknown node. +// +// In addition to being able to represent expressions of various types, we also +// have folders that are used to build the *canonical* representation for a +// particular expression. These folders are capable of using a variety of +// rewrite rules to simplify the expressions. +// +// Once the folders are defined, we can implement the more interesting +// higher-level code, such as the code that recognizes PHI nodes of various +// types, computes the execution count of a loop, etc. +// +// TODO: We should use these routines and value representations to implement +// dependence analysis! +// +//===----------------------------------------------------------------------===// +// +// There are several good references for the techniques used in this analysis. +// +// Chains of recurrences -- a method to expedite the evaluation +// of closed-form functions +// Olaf Bachmann, Paul S. Wang, Eugene V. Zima +// +// On computational properties of chains of recurrences +// Eugene V. Zima +// +// Symbolic Evaluation of Chains of Recurrences for Loop Optimization +// Robert A. van Engelen +// +// Efficient Symbolic Analysis for Optimizing Compilers +// Robert A. van Engelen +// +// Using the chains of recurrences algebra for data dependence testing and +// induction variable substitution +// MS Thesis, Johnie Birch +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "scalar-evolution" +#include "llvm/Analysis/ScalarEvolutionExpressions.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/GlobalVariable.h" +#include "llvm/GlobalAlias.h" +#include "llvm/Instructions.h" +#include "llvm/LLVMContext.h" +#include "llvm/Operator.h" +#include "llvm/Analysis/ConstantFolding.h" +#include "llvm/Analysis/Dominators.h" +#include "llvm/Analysis/LoopInfo.h" +#include "llvm/Analysis/ValueTracking.h" +#include "llvm/Assembly/Writer.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/ConstantRange.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/GetElementPtrTypeIterator.h" +#include "llvm/Support/InstIterator.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallPtrSet.h" +#include +using namespace llvm; + +STATISTIC(NumArrayLenItCounts, + "Number of trip counts computed with array length"); +STATISTIC(NumTripCountsComputed, + "Number of loops with predictable loop counts"); +STATISTIC(NumTripCountsNotComputed, + "Number of loops without predictable loop counts"); +STATISTIC(NumBruteForceTripCountsComputed, + "Number of loops with trip counts computed by force"); + +static cl::opt +MaxBruteForceIterations("scalar-evolution-max-iterations", cl::ReallyHidden, + cl::desc("Maximum number of iterations SCEV will " + "symbolically execute a constant " + "derived loop"), + cl::init(100)); + +static RegisterPass +R("scalar-evolution", "Scalar Evolution Analysis", false, true); +char ScalarEvolution::ID = 0; + +//===----------------------------------------------------------------------===// +// SCEV class definitions +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// Implementation of the SCEV class. +// + +SCEV::~SCEV() {} + +void SCEV::dump() const { + print(errs()); + errs() << '\n'; +} + +bool SCEV::isZero() const { + if (const SCEVConstant *SC = dyn_cast(this)) + return SC->getValue()->isZero(); + return false; +} + +bool SCEV::isOne() const { + if (const SCEVConstant *SC = dyn_cast(this)) + return SC->getValue()->isOne(); + return false; +} + +bool SCEV::isAllOnesValue() const { + if (const SCEVConstant *SC = dyn_cast(this)) + return SC->getValue()->isAllOnesValue(); + return false; +} + +SCEVCouldNotCompute::SCEVCouldNotCompute() : + SCEV(FoldingSetNodeID(), scCouldNotCompute) {} + +bool SCEVCouldNotCompute::isLoopInvariant(const Loop *L) const { + llvm_unreachable("Attempt to use a SCEVCouldNotCompute object!"); + return false; +} + +const Type *SCEVCouldNotCompute::getType() const { + llvm_unreachable("Attempt to use a SCEVCouldNotCompute object!"); + return 0; +} + +bool SCEVCouldNotCompute::hasComputableLoopEvolution(const Loop *L) const { + llvm_unreachable("Attempt to use a SCEVCouldNotCompute object!"); + return false; +} + +bool SCEVCouldNotCompute::hasOperand(const SCEV *) const { + llvm_unreachable("Attempt to use a SCEVCouldNotCompute object!"); + return false; +} + +void SCEVCouldNotCompute::print(raw_ostream &OS) const { + OS << "***COULDNOTCOMPUTE***"; +} + +bool SCEVCouldNotCompute::classof(const SCEV *S) { + return S->getSCEVType() == scCouldNotCompute; +} + +const SCEV *ScalarEvolution::getConstant(ConstantInt *V) { + FoldingSetNodeID ID; + ID.AddInteger(scConstant); + ID.AddPointer(V); + void *IP = 0; + if (const SCEV *S = UniqueSCEVs.FindNodeOrInsertPos(ID, IP)) return S; + SCEV *S = SCEVAllocator.Allocate(); + new (S) SCEVConstant(ID, V); + UniqueSCEVs.InsertNode(S, IP); + return S; +} + +const SCEV *ScalarEvolution::getConstant(const APInt& Val) { + return getConstant(ConstantInt::get(getContext(), Val)); +} + +const SCEV * +ScalarEvolution::getConstant(const Type *Ty, uint64_t V, bool isSigned) { + return getConstant( + ConstantInt::get(cast(Ty), V, isSigned)); +} + +const Type *SCEVConstant::getType() const { return V->getType(); } + +void SCEVConstant::print(raw_ostream &OS) const { + WriteAsOperand(OS, V, false); +} + +SCEVCastExpr::SCEVCastExpr(const FoldingSetNodeID &ID, + unsigned SCEVTy, const SCEV *op, const Type *ty) + : SCEV(ID, SCEVTy), Op(op), Ty(ty) {} + +bool SCEVCastExpr::dominates(BasicBlock *BB, DominatorTree *DT) const { + return Op->dominates(BB, DT); +} + +bool SCEVCastExpr::properlyDominates(BasicBlock *BB, DominatorTree *DT) const { + return Op->properlyDominates(BB, DT); +} + +SCEVTruncateExpr::SCEVTruncateExpr(const FoldingSetNodeID &ID, + const SCEV *op, const Type *ty) + : SCEVCastExpr(ID, scTruncate, op, ty) { + assert((Op->getType()->isInteger() || isa(Op->getType())) && + (Ty->isInteger() || isa(Ty)) && + "Cannot truncate non-integer value!"); +} + +void SCEVTruncateExpr::print(raw_ostream &OS) const { + OS << "(trunc " << *Op->getType() << " " << *Op << " to " << *Ty << ")"; +} + +SCEVZeroExtendExpr::SCEVZeroExtendExpr(const FoldingSetNodeID &ID, + const SCEV *op, const Type *ty) + : SCEVCastExpr(ID, scZeroExtend, op, ty) { + assert((Op->getType()->isInteger() || isa(Op->getType())) && + (Ty->isInteger() || isa(Ty)) && + "Cannot zero extend non-integer value!"); +} + +void SCEVZeroExtendExpr::print(raw_ostream &OS) const { + OS << "(zext " << *Op->getType() << " " << *Op << " to " << *Ty << ")"; +} + +SCEVSignExtendExpr::SCEVSignExtendExpr(const FoldingSetNodeID &ID, + const SCEV *op, const Type *ty) + : SCEVCastExpr(ID, scSignExtend, op, ty) { + assert((Op->getType()->isInteger() || isa(Op->getType())) && + (Ty->isInteger() || isa(Ty)) && + "Cannot sign extend non-integer value!"); +} + +void SCEVSignExtendExpr::print(raw_ostream &OS) const { + OS << "(sext " << *Op->getType() << " " << *Op << " to " << *Ty << ")"; +} + +void SCEVCommutativeExpr::print(raw_ostream &OS) const { + assert(Operands.size() > 1 && "This plus expr shouldn't exist!"); + const char *OpStr = getOperationStr(); + OS << "(" << *Operands[0]; + for (unsigned i = 1, e = Operands.size(); i != e; ++i) + OS << OpStr << *Operands[i]; + OS << ")"; +} + +bool SCEVNAryExpr::dominates(BasicBlock *BB, DominatorTree *DT) const { + for (unsigned i = 0, e = getNumOperands(); i != e; ++i) { + if (!getOperand(i)->dominates(BB, DT)) + return false; + } + return true; +} + +bool SCEVNAryExpr::properlyDominates(BasicBlock *BB, DominatorTree *DT) const { + for (unsigned i = 0, e = getNumOperands(); i != e; ++i) { + if (!getOperand(i)->properlyDominates(BB, DT)) + return false; + } + return true; +} + +bool SCEVUDivExpr::dominates(BasicBlock *BB, DominatorTree *DT) const { + return LHS->dominates(BB, DT) && RHS->dominates(BB, DT); +} + +bool SCEVUDivExpr::properlyDominates(BasicBlock *BB, DominatorTree *DT) const { + return LHS->properlyDominates(BB, DT) && RHS->properlyDominates(BB, DT); +} + +void SCEVUDivExpr::print(raw_ostream &OS) const { + OS << "(" << *LHS << " /u " << *RHS << ")"; +} + +const Type *SCEVUDivExpr::getType() const { + // 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 + // depend on the type for correctness, but handling types carefully can + // avoid extra casts in the SCEVExpander. The LHS is more likely to be + // a pointer type than the RHS, so use the RHS' type here. + return RHS->getType(); +} + +bool SCEVAddRecExpr::isLoopInvariant(const Loop *QueryLoop) const { + // Add recurrences are never invariant in the function-body (null loop). + if (!QueryLoop) + return false; + + // This recurrence is variant w.r.t. QueryLoop if QueryLoop contains L. + if (QueryLoop->contains(L->getHeader())) + return false; + + // This recurrence is variant w.r.t. QueryLoop if any of its operands + // are variant. + for (unsigned i = 0, e = getNumOperands(); i != e; ++i) + if (!getOperand(i)->isLoopInvariant(QueryLoop)) + return false; + + // Otherwise it's loop-invariant. + return true; +} + +void SCEVAddRecExpr::print(raw_ostream &OS) const { + OS << "{" << *Operands[0]; + for (unsigned i = 1, e = Operands.size(); i != e; ++i) + OS << ",+," << *Operands[i]; + OS << "}<" << L->getHeader()->getName() + ">"; +} + +void SCEVFieldOffsetExpr::print(raw_ostream &OS) const { + // LLVM struct fields don't have names, so just print the field number. + OS << "offsetof(" << *STy << ", " << FieldNo << ")"; +} + +void SCEVAllocSizeExpr::print(raw_ostream &OS) const { + OS << "sizeof(" << *AllocTy << ")"; +} + +bool SCEVUnknown::isLoopInvariant(const Loop *L) const { + // All non-instruction values are loop invariant. All instructions are loop + // invariant if they are not contained in the specified loop. + // Instructions are never considered invariant in the function body + // (null loop) because they are defined within the "loop". + if (Instruction *I = dyn_cast(V)) + return L && !L->contains(I->getParent()); + return true; +} + +bool SCEVUnknown::dominates(BasicBlock *BB, DominatorTree *DT) const { + if (Instruction *I = dyn_cast(getValue())) + return DT->dominates(I->getParent(), BB); + return true; +} + +bool SCEVUnknown::properlyDominates(BasicBlock *BB, DominatorTree *DT) const { + if (Instruction *I = dyn_cast(getValue())) + return DT->properlyDominates(I->getParent(), BB); + return true; +} + +const Type *SCEVUnknown::getType() const { + return V->getType(); +} + +void SCEVUnknown::print(raw_ostream &OS) const { + WriteAsOperand(OS, V, false); +} + +//===----------------------------------------------------------------------===// +// SCEV Utilities +//===----------------------------------------------------------------------===// + +static bool CompareTypes(const Type *A, const Type *B) { + if (A->getTypeID() != B->getTypeID()) + return A->getTypeID() < B->getTypeID(); + if (const IntegerType *AI = dyn_cast(A)) { + const IntegerType *BI = cast(B); + return AI->getBitWidth() < BI->getBitWidth(); + } + if (const PointerType *AI = dyn_cast(A)) { + const PointerType *BI = cast(B); + return CompareTypes(AI->getElementType(), BI->getElementType()); + } + if (const ArrayType *AI = dyn_cast(A)) { + const ArrayType *BI = cast(B); + if (AI->getNumElements() != BI->getNumElements()) + return AI->getNumElements() < BI->getNumElements(); + return CompareTypes(AI->getElementType(), BI->getElementType()); + } + if (const VectorType *AI = dyn_cast(A)) { + const VectorType *BI = cast(B); + if (AI->getNumElements() != BI->getNumElements()) + return AI->getNumElements() < BI->getNumElements(); + return CompareTypes(AI->getElementType(), BI->getElementType()); + } + if (const StructType *AI = dyn_cast(A)) { + const StructType *BI = cast(B); + if (AI->getNumElements() != BI->getNumElements()) + return AI->getNumElements() < BI->getNumElements(); + for (unsigned i = 0, e = AI->getNumElements(); i != e; ++i) + if (CompareTypes(AI->getElementType(i), BI->getElementType(i)) || + CompareTypes(BI->getElementType(i), AI->getElementType(i))) + return CompareTypes(AI->getElementType(i), BI->getElementType(i)); + } + return false; +} + +namespace { + /// SCEVComplexityCompare - Return true if the complexity of the LHS is less + /// than the complexity of the RHS. This comparator is used to canonicalize + /// expressions. + class SCEVComplexityCompare { + LoopInfo *LI; + public: + explicit SCEVComplexityCompare(LoopInfo *li) : LI(li) {} + + bool operator()(const SCEV *LHS, const SCEV *RHS) const { + // Fast-path: SCEVs are uniqued so we can do a quick equality check. + if (LHS == RHS) + return false; + + // Primarily, sort the SCEVs by their getSCEVType(). + if (LHS->getSCEVType() != RHS->getSCEVType()) + return LHS->getSCEVType() < RHS->getSCEVType(); + + // Aside from the getSCEVType() ordering, the particular ordering + // isn't very important except that it's beneficial to be consistent, + // so that (a + b) and (b + a) don't end up as different expressions. + + // Sort SCEVUnknown values with some loose heuristics. TODO: This is + // not as complete as it could be. + if (const SCEVUnknown *LU = dyn_cast(LHS)) { + const SCEVUnknown *RU = cast(RHS); + + // Order pointer values after integer values. This helps SCEVExpander + // form GEPs. + if (isa(LU->getType()) && !isa(RU->getType())) + return false; + if (isa(RU->getType()) && !isa(LU->getType())) + return true; + + // Compare getValueID values. + if (LU->getValue()->getValueID() != RU->getValue()->getValueID()) + return LU->getValue()->getValueID() < RU->getValue()->getValueID(); + + // Sort arguments by their position. + if (const Argument *LA = dyn_cast(LU->getValue())) { + const Argument *RA = cast(RU->getValue()); + return LA->getArgNo() < RA->getArgNo(); + } + + // For instructions, compare their loop depth, and their opcode. + // This is pretty loose. + if (Instruction *LV = dyn_cast(LU->getValue())) { + Instruction *RV = cast(RU->getValue()); + + // Compare loop depths. + if (LI->getLoopDepth(LV->getParent()) != + LI->getLoopDepth(RV->getParent())) + return LI->getLoopDepth(LV->getParent()) < + LI->getLoopDepth(RV->getParent()); + + // Compare opcodes. + if (LV->getOpcode() != RV->getOpcode()) + return LV->getOpcode() < RV->getOpcode(); + + // Compare the number of operands. + if (LV->getNumOperands() != RV->getNumOperands()) + return LV->getNumOperands() < RV->getNumOperands(); + } + + return false; + } + + // Compare constant values. + if (const SCEVConstant *LC = dyn_cast(LHS)) { + const SCEVConstant *RC = cast(RHS); + if (LC->getValue()->getBitWidth() != RC->getValue()->getBitWidth()) + return LC->getValue()->getBitWidth() < RC->getValue()->getBitWidth(); + return LC->getValue()->getValue().ult(RC->getValue()->getValue()); + } + + // Compare addrec loop depths. + if (const SCEVAddRecExpr *LA = dyn_cast(LHS)) { + const SCEVAddRecExpr *RA = cast(RHS); + if (LA->getLoop()->getLoopDepth() != RA->getLoop()->getLoopDepth()) + return LA->getLoop()->getLoopDepth() < RA->getLoop()->getLoopDepth(); + } + + // Lexicographically compare n-ary expressions. + if (const SCEVNAryExpr *LC = dyn_cast(LHS)) { + const SCEVNAryExpr *RC = cast(RHS); + for (unsigned i = 0, e = LC->getNumOperands(); i != e; ++i) { + if (i >= RC->getNumOperands()) + return false; + if (operator()(LC->getOperand(i), RC->getOperand(i))) + return true; + if (operator()(RC->getOperand(i), LC->getOperand(i))) + return false; + } + return LC->getNumOperands() < RC->getNumOperands(); + } + + // Lexicographically compare udiv expressions. + if (const SCEVUDivExpr *LC = dyn_cast(LHS)) { + const SCEVUDivExpr *RC = cast(RHS); + if (operator()(LC->getLHS(), RC->getLHS())) + return true; + if (operator()(RC->getLHS(), LC->getLHS())) + return false; + if (operator()(LC->getRHS(), RC->getRHS())) + return true; + if (operator()(RC->getRHS(), LC->getRHS())) + return false; + return false; + } + + // Compare cast expressions by operand. + if (const SCEVCastExpr *LC = dyn_cast(LHS)) { + const SCEVCastExpr *RC = cast(RHS); + return operator()(LC->getOperand(), RC->getOperand()); + } + + // Compare offsetof expressions. + if (const SCEVFieldOffsetExpr *LA = dyn_cast(LHS)) { + const SCEVFieldOffsetExpr *RA = cast(RHS); + if (CompareTypes(LA->getStructType(), RA->getStructType()) || + CompareTypes(RA->getStructType(), LA->getStructType())) + return CompareTypes(LA->getStructType(), RA->getStructType()); + return LA->getFieldNo() < RA->getFieldNo(); + } + + // Compare sizeof expressions by the allocation type. + if (const SCEVAllocSizeExpr *LA = dyn_cast(LHS)) { + const SCEVAllocSizeExpr *RA = cast(RHS); + return CompareTypes(LA->getAllocType(), RA->getAllocType()); + } + + llvm_unreachable("Unknown SCEV kind!"); + return false; + } + }; +} + +/// GroupByComplexity - Given a list of SCEV objects, order them by their +/// complexity, and group objects of the same complexity together by value. +/// When this routine is finished, we know that any duplicates in the vector are +/// consecutive and that complexity is monotonically increasing. +/// +/// Note that we go take special precautions to ensure that we get determinstic +/// results from this routine. In other words, we don't want the results of +/// this to depend on where the addresses of various SCEV objects happened to +/// land in memory. +/// +static void GroupByComplexity(SmallVectorImpl &Ops, + LoopInfo *LI) { + if (Ops.size() < 2) return; // Noop + if (Ops.size() == 2) { + // This is the common case, which also happens to be trivially simple. + // Special case it. + if (SCEVComplexityCompare(LI)(Ops[1], Ops[0])) + std::swap(Ops[0], Ops[1]); + return; + } + + // Do the rough sort by complexity. + std::stable_sort(Ops.begin(), Ops.end(), SCEVComplexityCompare(LI)); + + // Now that we are sorted by complexity, group elements of the same + // complexity. Note that this is, at worst, N^2, but the vector is likely to + // be extremely short in practice. Note that we take this approach because we + // do not want to depend on the addresses of the objects we are grouping. + for (unsigned i = 0, e = Ops.size(); i != e-2; ++i) { + const SCEV *S = Ops[i]; + unsigned Complexity = S->getSCEVType(); + + // If there are any objects of the same complexity and same value as this + // one, group them. + for (unsigned j = i+1; j != e && Ops[j]->getSCEVType() == Complexity; ++j) { + if (Ops[j] == S) { // Found a duplicate. + // Move it to immediately after i'th element. + std::swap(Ops[i+1], Ops[j]); + ++i; // no need to rescan it. + if (i == e-2) return; // Done! + } + } + } +} + + + +//===----------------------------------------------------------------------===// +// Simple SCEV method implementations +//===----------------------------------------------------------------------===// + +/// BinomialCoefficient - Compute BC(It, K). The result has width W. +/// Assume, K > 0. +static const SCEV *BinomialCoefficient(const SCEV *It, unsigned K, + ScalarEvolution &SE, + const Type* ResultTy) { + // Handle the simplest case efficiently. + if (K == 1) + return SE.getTruncateOrZeroExtend(It, ResultTy); + + // We are using the following formula for BC(It, K): + // + // BC(It, K) = (It * (It - 1) * ... * (It - K + 1)) / K! + // + // Suppose, W is the bitwidth of the return value. We must be prepared for + // overflow. Hence, we must assure that the result of our computation is + // equal to the accurate one modulo 2^W. Unfortunately, division isn't + // safe in modular arithmetic. + // + // However, this code doesn't use exactly that formula; the formula it uses + // is something like the following, where T is the number of factors of 2 in + // K! (i.e. trailing zeros in the binary representation of K!), and ^ is + // exponentiation: + // + // BC(It, K) = (It * (It - 1) * ... * (It - K + 1)) / 2^T / (K! / 2^T) + // + // This formula is trivially equivalent to the previous formula. However, + // this formula can be implemented much more efficiently. The trick is that + // K! / 2^T is odd, and exact division by an odd number *is* safe in modular + // arithmetic. To do exact division in modular arithmetic, all we have + // to do is multiply by the inverse. Therefore, this step can be done at + // width W. + // + // The next issue is how to safely do the division by 2^T. The way this + // is done is by doing the multiplication step at a width of at least W + T + // bits. This way, the bottom W+T bits of the product are accurate. Then, + // when we perform the division by 2^T (which is equivalent to a right shift + // by T), the bottom W bits are accurate. Extra bits are okay; they'll get + // truncated out after the division by 2^T. + // + // In comparison to just directly using the first formula, this technique + // is much more efficient; using the first formula requires W * K bits, + // but this formula less than W + K bits. Also, the first formula requires + // a division step, whereas this formula only requires multiplies and shifts. + // + // It doesn't matter whether the subtraction step is done in the calculation + // width or the input iteration count's width; if the subtraction overflows, + // the result must be zero anyway. We prefer here to do it in the width of + // the induction variable because it helps a lot for certain cases; CodeGen + // isn't smart enough to ignore the overflow, which leads to much less + // efficient code if the width of the subtraction is wider than the native + // register width. + // + // (It's possible to not widen at all by pulling out factors of 2 before + // the multiplication; for example, K=2 can be calculated as + // It/2*(It+(It*INT_MIN/INT_MIN)+-1). However, it requires + // extra arithmetic, so it's not an obvious win, and it gets + // much more complicated for K > 3.) + + // Protection from insane SCEVs; this bound is conservative, + // but it probably doesn't matter. + if (K > 1000) + return SE.getCouldNotCompute(); + + unsigned W = SE.getTypeSizeInBits(ResultTy); + + // Calculate K! / 2^T and T; we divide out the factors of two before + // multiplying for calculating K! / 2^T to avoid overflow. + // Other overflow doesn't matter because we only care about the bottom + // W bits of the result. + APInt OddFactorial(W, 1); + unsigned T = 1; + for (unsigned i = 3; i <= K; ++i) { + APInt Mult(W, i); + unsigned TwoFactors = Mult.countTrailingZeros(); + T += TwoFactors; + Mult = Mult.lshr(TwoFactors); + OddFactorial *= Mult; + } + + // We need at least W + T bits for the multiplication step + unsigned CalculationBits = W + T; + + // Calcuate 2^T, at width T+W. + APInt DivFactor = APInt(CalculationBits, 1).shl(T); + + // Calculate the multiplicative inverse of K! / 2^T; + // this multiplication factor will perform the exact division by + // K! / 2^T. + APInt Mod = APInt::getSignedMinValue(W+1); + APInt MultiplyFactor = OddFactorial.zext(W+1); + MultiplyFactor = MultiplyFactor.multiplicativeInverse(Mod); + MultiplyFactor = MultiplyFactor.trunc(W); + + // Calculate the product, at width T+W + const IntegerType *CalculationTy = IntegerType::get(SE.getContext(), + CalculationBits); + const SCEV *Dividend = SE.getTruncateOrZeroExtend(It, CalculationTy); + for (unsigned i = 1; i != K; ++i) { + const SCEV *S = SE.getMinusSCEV(It, SE.getIntegerSCEV(i, It->getType())); + Dividend = SE.getMulExpr(Dividend, + SE.getTruncateOrZeroExtend(S, CalculationTy)); + } + + // Divide by 2^T + const SCEV *DivResult = SE.getUDivExpr(Dividend, SE.getConstant(DivFactor)); + + // Truncate the result, and divide by K! / 2^T. + + return SE.getMulExpr(SE.getConstant(MultiplyFactor), + SE.getTruncateOrZeroExtend(DivResult, ResultTy)); +} + +/// evaluateAtIteration - Return the value of this chain of recurrences at +/// the specified iteration number. We can evaluate this recurrence by +/// multiplying each element in the chain by the binomial coefficient +/// corresponding to it. In other words, we can evaluate {A,+,B,+,C,+,D} as: +/// +/// A*BC(It, 0) + B*BC(It, 1) + C*BC(It, 2) + D*BC(It, 3) +/// +/// where BC(It, k) stands for binomial coefficient. +/// +const SCEV *SCEVAddRecExpr::evaluateAtIteration(const SCEV *It, + ScalarEvolution &SE) const { + const SCEV *Result = getStart(); + for (unsigned i = 1, e = getNumOperands(); i != e; ++i) { + // The computation is correct in the face of overflow provided that the + // multiplication is performed _after_ the evaluation of the binomial + // coefficient. + const SCEV *Coeff = BinomialCoefficient(It, i, SE, getType()); + if (isa(Coeff)) + return Coeff; + + Result = SE.getAddExpr(Result, SE.getMulExpr(getOperand(i), Coeff)); + } + return Result; +} + +//===----------------------------------------------------------------------===// +// SCEV Expression folder implementations +//===----------------------------------------------------------------------===// + +const SCEV *ScalarEvolution::getTruncateExpr(const SCEV *Op, + const Type *Ty) { + assert(getTypeSizeInBits(Op->getType()) > getTypeSizeInBits(Ty) && + "This is not a truncating conversion!"); + assert(isSCEVable(Ty) && + "This is not a conversion to a SCEVable type!"); + Ty = getEffectiveSCEVType(Ty); + + FoldingSetNodeID ID; + ID.AddInteger(scTruncate); + ID.AddPointer(Op); + ID.AddPointer(Ty); + void *IP = 0; + if (const SCEV *S = UniqueSCEVs.FindNodeOrInsertPos(ID, IP)) return S; + + // Fold if the operand is constant. + if (const SCEVConstant *SC = dyn_cast(Op)) + return getConstant( + cast(ConstantExpr::getTrunc(SC->getValue(), Ty))); + + // trunc(trunc(x)) --> trunc(x) + if (const SCEVTruncateExpr *ST = dyn_cast(Op)) + return getTruncateExpr(ST->getOperand(), Ty); + + // trunc(sext(x)) --> sext(x) if widening or trunc(x) if narrowing + if (const SCEVSignExtendExpr *SS = dyn_cast(Op)) + return getTruncateOrSignExtend(SS->getOperand(), Ty); + + // trunc(zext(x)) --> zext(x) if widening or trunc(x) if narrowing + if (const SCEVZeroExtendExpr *SZ = dyn_cast(Op)) + return getTruncateOrZeroExtend(SZ->getOperand(), Ty); + + // If the input value is a chrec scev, truncate the chrec's operands. + if (const SCEVAddRecExpr *AddRec = dyn_cast(Op)) { + SmallVector Operands; + for (unsigned i = 0, e = AddRec->getNumOperands(); i != e; ++i) + Operands.push_back(getTruncateExpr(AddRec->getOperand(i), Ty)); + return getAddRecExpr(Operands, AddRec->getLoop()); + } + + // The cast wasn't folded; create an explicit cast node. + // Recompute the insert position, as it may have been invalidated. + if (const SCEV *S = UniqueSCEVs.FindNodeOrInsertPos(ID, IP)) return S; + SCEV *S = SCEVAllocator.Allocate(); + new (S) SCEVTruncateExpr(ID, Op, Ty); + UniqueSCEVs.InsertNode(S, IP); + return S; +} + +const SCEV *ScalarEvolution::getZeroExtendExpr(const SCEV *Op, + const Type *Ty) { + assert(getTypeSizeInBits(Op->getType()) < getTypeSizeInBits(Ty) && + "This is not an extending conversion!"); + assert(isSCEVable(Ty) && + "This is not a conversion to a SCEVable type!"); + Ty = getEffectiveSCEVType(Ty); + + // Fold if the operand is constant. + if (const SCEVConstant *SC = dyn_cast(Op)) { + const Type *IntTy = getEffectiveSCEVType(Ty); + Constant *C = ConstantExpr::getZExt(SC->getValue(), IntTy); + if (IntTy != Ty) C = ConstantExpr::getIntToPtr(C, Ty); + return getConstant(cast(C)); + } + + // zext(zext(x)) --> zext(x) + if (const SCEVZeroExtendExpr *SZ = dyn_cast(Op)) + return getZeroExtendExpr(SZ->getOperand(), Ty); + + // Before doing any expensive analysis, check to see if we've already + // computed a SCEV for this Op and Ty. + FoldingSetNodeID ID; + ID.AddInteger(scZeroExtend); + ID.AddPointer(Op); + ID.AddPointer(Ty); + void *IP = 0; + if (const SCEV *S = UniqueSCEVs.FindNodeOrInsertPos(ID, IP)) return S; + + // If the input value is a chrec scev, and we can prove that the value + // did not overflow the old, smaller, value, we can zero extend all of the + // operands (often constants). This allows analysis of something like + // this: for (unsigned char X = 0; X < 100; ++X) { int Y = X; } + if (const SCEVAddRecExpr *AR = dyn_cast(Op)) + if (AR->isAffine()) { + const SCEV *Start = AR->getStart(); + const SCEV *Step = AR->getStepRecurrence(*this); + unsigned BitWidth = getTypeSizeInBits(AR->getType()); + const Loop *L = AR->getLoop(); + + // If we have special knowledge that this addrec won't overflow, + // we don't need to do any further analysis. + if (AR->hasNoUnsignedWrap()) + return getAddRecExpr(getZeroExtendExpr(Start, Ty), + getZeroExtendExpr(Step, Ty), + L); + + // Check whether the backedge-taken count is SCEVCouldNotCompute. + // Note that this serves two purposes: It filters out loops that are + // simply not analyzable, and it covers the case where this code is + // being called from within backedge-taken count analysis, such that + // attempting to ask for the backedge-taken count would likely result + // in infinite recursion. In the later case, the analysis code will + // cope with a conservative value, and it will take care to purge + // that value once it has finished. + const SCEV *MaxBECount = getMaxBackedgeTakenCount(L); + if (!isa(MaxBECount)) { + // Manually compute the final value for AR, checking for + // overflow. + + // Check whether the backedge-taken count can be losslessly casted to + // the addrec's type. The count is always unsigned. + const SCEV *CastedMaxBECount = + getTruncateOrZeroExtend(MaxBECount, Start->getType()); + const SCEV *RecastedMaxBECount = + getTruncateOrZeroExtend(CastedMaxBECount, MaxBECount->getType()); + if (MaxBECount == RecastedMaxBECount) { + const Type *WideTy = IntegerType::get(getContext(), BitWidth * 2); + // Check whether Start+Step*MaxBECount has no unsigned overflow. + const SCEV *ZMul = + getMulExpr(CastedMaxBECount, + getTruncateOrZeroExtend(Step, Start->getType())); + const SCEV *Add = getAddExpr(Start, ZMul); + const SCEV *OperandExtendedAdd = + getAddExpr(getZeroExtendExpr(Start, WideTy), + getMulExpr(getZeroExtendExpr(CastedMaxBECount, WideTy), + getZeroExtendExpr(Step, WideTy))); + if (getZeroExtendExpr(Add, WideTy) == OperandExtendedAdd) + // Return the expression with the addrec on the outside. + return getAddRecExpr(getZeroExtendExpr(Start, Ty), + getZeroExtendExpr(Step, Ty), + L); + + // Similar to above, only this time treat the step value as signed. + // This covers loops that count down. + const SCEV *SMul = + getMulExpr(CastedMaxBECount, + getTruncateOrSignExtend(Step, Start->getType())); + Add = getAddExpr(Start, SMul); + OperandExtendedAdd = + getAddExpr(getZeroExtendExpr(Start, WideTy), + getMulExpr(getZeroExtendExpr(CastedMaxBECount, WideTy), + getSignExtendExpr(Step, WideTy))); + if (getZeroExtendExpr(Add, WideTy) == OperandExtendedAdd) + // Return the expression with the addrec on the outside. + return getAddRecExpr(getZeroExtendExpr(Start, Ty), + getSignExtendExpr(Step, Ty), + L); + } + + // If the backedge is guarded by a comparison with the pre-inc value + // the addrec is safe. Also, if the entry is guarded by a comparison + // with the start value and the backedge is guarded by a comparison + // with the post-inc value, the addrec is safe. + if (isKnownPositive(Step)) { + const SCEV *N = getConstant(APInt::getMinValue(BitWidth) - + getUnsignedRange(Step).getUnsignedMax()); + if (isLoopBackedgeGuardedByCond(L, ICmpInst::ICMP_ULT, AR, N) || + (isLoopGuardedByCond(L, ICmpInst::ICMP_ULT, Start, N) && + isLoopBackedgeGuardedByCond(L, ICmpInst::ICMP_ULT, + AR->getPostIncExpr(*this), N))) + // Return the expression with the addrec on the outside. + return getAddRecExpr(getZeroExtendExpr(Start, Ty), + getZeroExtendExpr(Step, Ty), + L); + } else if (isKnownNegative(Step)) { + const SCEV *N = getConstant(APInt::getMaxValue(BitWidth) - + getSignedRange(Step).getSignedMin()); + if (isLoopBackedgeGuardedByCond(L, ICmpInst::ICMP_UGT, AR, N) && + (isLoopGuardedByCond(L, ICmpInst::ICMP_UGT, Start, N) || + isLoopBackedgeGuardedByCond(L, ICmpInst::ICMP_UGT, + AR->getPostIncExpr(*this), N))) + // Return the expression with the addrec on the outside. + return getAddRecExpr(getZeroExtendExpr(Start, Ty), + getSignExtendExpr(Step, Ty), + L); + } + } + } + + // The cast wasn't folded; create an explicit cast node. + // Recompute the insert position, as it may have been invalidated. + if (const SCEV *S = UniqueSCEVs.FindNodeOrInsertPos(ID, IP)) return S; + SCEV *S = SCEVAllocator.Allocate(); + new (S) SCEVZeroExtendExpr(ID, Op, Ty); + UniqueSCEVs.InsertNode(S, IP); + return S; +} + +const SCEV *ScalarEvolution::getSignExtendExpr(const SCEV *Op, + const Type *Ty) { + assert(getTypeSizeInBits(Op->getType()) < getTypeSizeInBits(Ty) && + "This is not an extending conversion!"); + assert(isSCEVable(Ty) && + "This is not a conversion to a SCEVable type!"); + Ty = getEffectiveSCEVType(Ty); + + // Fold if the operand is constant. + if (const SCEVConstant *SC = dyn_cast(Op)) { + const Type *IntTy = getEffectiveSCEVType(Ty); + Constant *C = ConstantExpr::getSExt(SC->getValue(), IntTy); + if (IntTy != Ty) C = ConstantExpr::getIntToPtr(C, Ty); + return getConstant(cast(C)); + } + + // sext(sext(x)) --> sext(x) + if (const SCEVSignExtendExpr *SS = dyn_cast(Op)) + return getSignExtendExpr(SS->getOperand(), Ty); + + // Before doing any expensive analysis, check to see if we've already + // computed a SCEV for this Op and Ty. + FoldingSetNodeID ID; + ID.AddInteger(scSignExtend); + ID.AddPointer(Op); + ID.AddPointer(Ty); + void *IP = 0; + if (const SCEV *S = UniqueSCEVs.FindNodeOrInsertPos(ID, IP)) return S; + + // If the input value is a chrec scev, and we can prove that the value + // did not overflow the old, smaller, value, we can sign extend all of the + // operands (often constants). This allows analysis of something like + // this: for (signed char X = 0; X < 100; ++X) { int Y = X; } + if (const SCEVAddRecExpr *AR = dyn_cast(Op)) + if (AR->isAffine()) { + const SCEV *Start = AR->getStart(); + const SCEV *Step = AR->getStepRecurrence(*this); + unsigned BitWidth = getTypeSizeInBits(AR->getType()); + const Loop *L = AR->getLoop(); + + // If we have special knowledge that this addrec won't overflow, + // we don't need to do any further analysis. + if (AR->hasNoSignedWrap()) + return getAddRecExpr(getSignExtendExpr(Start, Ty), + getSignExtendExpr(Step, Ty), + L); + + // Check whether the backedge-taken count is SCEVCouldNotCompute. + // Note that this serves two purposes: It filters out loops that are + // simply not analyzable, and it covers the case where this code is + // being called from within backedge-taken count analysis, such that + // attempting to ask for the backedge-taken count would likely result + // in infinite recursion. In the later case, the analysis code will + // cope with a conservative value, and it will take care to purge + // that value once it has finished. + const SCEV *MaxBECount = getMaxBackedgeTakenCount(L); + if (!isa(MaxBECount)) { + // Manually compute the final value for AR, checking for + // overflow. + + // Check whether the backedge-taken count can be losslessly casted to + // the addrec's type. The count is always unsigned. + const SCEV *CastedMaxBECount = + getTruncateOrZeroExtend(MaxBECount, Start->getType()); + const SCEV *RecastedMaxBECount = + getTruncateOrZeroExtend(CastedMaxBECount, MaxBECount->getType()); + if (MaxBECount == RecastedMaxBECount) { + const Type *WideTy = IntegerType::get(getContext(), BitWidth * 2); + // Check whether Start+Step*MaxBECount has no signed overflow. + const SCEV *SMul = + getMulExpr(CastedMaxBECount, + getTruncateOrSignExtend(Step, Start->getType())); + const SCEV *Add = getAddExpr(Start, SMul); + const SCEV *OperandExtendedAdd = + getAddExpr(getSignExtendExpr(Start, WideTy), + getMulExpr(getZeroExtendExpr(CastedMaxBECount, WideTy), + getSignExtendExpr(Step, WideTy))); + if (getSignExtendExpr(Add, WideTy) == OperandExtendedAdd) + // Return the expression with the addrec on the outside. + return getAddRecExpr(getSignExtendExpr(Start, Ty), + getSignExtendExpr(Step, Ty), + L); + + // Similar to above, only this time treat the step value as unsigned. + // This covers loops that count up with an unsigned step. + const SCEV *UMul = + getMulExpr(CastedMaxBECount, + getTruncateOrZeroExtend(Step, Start->getType())); + Add = getAddExpr(Start, UMul); + OperandExtendedAdd = + getAddExpr(getSignExtendExpr(Start, WideTy), + getMulExpr(getZeroExtendExpr(CastedMaxBECount, WideTy), + getZeroExtendExpr(Step, WideTy))); + if (getSignExtendExpr(Add, WideTy) == OperandExtendedAdd) + // Return the expression with the addrec on the outside. + return getAddRecExpr(getSignExtendExpr(Start, Ty), + getZeroExtendExpr(Step, Ty), + L); + } + + // If the backedge is guarded by a comparison with the pre-inc value + // the addrec is safe. Also, if the entry is guarded by a comparison + // with the start value and the backedge is guarded by a comparison + // with the post-inc value, the addrec is safe. + if (isKnownPositive(Step)) { + const SCEV *N = getConstant(APInt::getSignedMinValue(BitWidth) - + getSignedRange(Step).getSignedMax()); + if (isLoopBackedgeGuardedByCond(L, ICmpInst::ICMP_SLT, AR, N) || + (isLoopGuardedByCond(L, ICmpInst::ICMP_SLT, Start, N) && + isLoopBackedgeGuardedByCond(L, ICmpInst::ICMP_SLT, + AR->getPostIncExpr(*this), N))) + // Return the expression with the addrec on the outside. + return getAddRecExpr(getSignExtendExpr(Start, Ty), + getSignExtendExpr(Step, Ty), + L); + } else if (isKnownNegative(Step)) { + const SCEV *N = getConstant(APInt::getSignedMaxValue(BitWidth) - + getSignedRange(Step).getSignedMin()); + if (isLoopBackedgeGuardedByCond(L, ICmpInst::ICMP_SGT, AR, N) || + (isLoopGuardedByCond(L, ICmpInst::ICMP_SGT, Start, N) && + isLoopBackedgeGuardedByCond(L, ICmpInst::ICMP_SGT, + AR->getPostIncExpr(*this), N))) + // Return the expression with the addrec on the outside. + return getAddRecExpr(getSignExtendExpr(Start, Ty), + getSignExtendExpr(Step, Ty), + L); + } + } + } + + // The cast wasn't folded; create an explicit cast node. + // Recompute the insert position, as it may have been invalidated. + if (const SCEV *S = UniqueSCEVs.FindNodeOrInsertPos(ID, IP)) return S; + SCEV *S = SCEVAllocator.Allocate(); + new (S) SCEVSignExtendExpr(ID, Op, Ty); + UniqueSCEVs.InsertNode(S, IP); + return S; +} + +/// getAnyExtendExpr - Return a SCEV for the given operand extended with +/// unspecified bits out to the given type. +/// +const SCEV *ScalarEvolution::getAnyExtendExpr(const SCEV *Op, + const Type *Ty) { + assert(getTypeSizeInBits(Op->getType()) < getTypeSizeInBits(Ty) && + "This is not an extending conversion!"); + assert(isSCEVable(Ty) && + "This is not a conversion to a SCEVable type!"); + Ty = getEffectiveSCEVType(Ty); + + // Sign-extend negative constants. + if (const SCEVConstant *SC = dyn_cast(Op)) + if (SC->getValue()->getValue().isNegative()) + return getSignExtendExpr(Op, Ty); + + // Peel off a truncate cast. + if (const SCEVTruncateExpr *T = dyn_cast(Op)) { + const SCEV *NewOp = T->getOperand(); + if (getTypeSizeInBits(NewOp->getType()) < getTypeSizeInBits(Ty)) + return getAnyExtendExpr(NewOp, Ty); + return getTruncateOrNoop(NewOp, Ty); + } + + // Next try a zext cast. If the cast is folded, use it. + const SCEV *ZExt = getZeroExtendExpr(Op, Ty); + if (!isa(ZExt)) + return ZExt; + + // Next try a sext cast. If the cast is folded, use it. + const SCEV *SExt = getSignExtendExpr(Op, Ty); + if (!isa(SExt)) + return SExt; + + // If the expression is obviously signed, use the sext cast value. + if (isa(Op)) + return SExt; + + // Absent any other information, use the zext cast value. + return ZExt; +} + +/// CollectAddOperandsWithScales - Process the given Ops list, which is +/// a list of operands to be added under the given scale, update the given +/// map. This is a helper function for getAddRecExpr. As an example of +/// what it does, given a sequence of operands that would form an add +/// expression like this: +/// +/// m + n + 13 + (A * (o + p + (B * q + m + 29))) + r + (-1 * r) +/// +/// where A and B are constants, update the map with these values: +/// +/// (m, 1+A*B), (n, 1), (o, A), (p, A), (q, A*B), (r, 0) +/// +/// and add 13 + A*B*29 to AccumulatedConstant. +/// This will allow getAddRecExpr to produce this: +/// +/// 13+A*B*29 + n + (m * (1+A*B)) + ((o + p) * A) + (q * A*B) +/// +/// This form often exposes folding opportunities that are hidden in +/// the original operand list. +/// +/// Return true iff it appears that any interesting folding opportunities +/// may be exposed. This helps getAddRecExpr short-circuit extra work in +/// the common case where no interesting opportunities are present, and +/// is also used as a check to avoid infinite recursion. +/// +static bool +CollectAddOperandsWithScales(DenseMap &M, + SmallVector &NewOps, + APInt &AccumulatedConstant, + const SmallVectorImpl &Ops, + const APInt &Scale, + ScalarEvolution &SE) { + bool Interesting = false; + + // Iterate over the add operands. + for (unsigned i = 0, e = Ops.size(); i != e; ++i) { + const SCEVMulExpr *Mul = dyn_cast(Ops[i]); + if (Mul && isa(Mul->getOperand(0))) { + APInt NewScale = + Scale * cast(Mul->getOperand(0))->getValue()->getValue(); + if (Mul->getNumOperands() == 2 && isa(Mul->getOperand(1))) { + // A multiplication of a constant with another add; recurse. + Interesting |= + CollectAddOperandsWithScales(M, NewOps, AccumulatedConstant, + cast(Mul->getOperand(1)) + ->getOperands(), + NewScale, SE); + } else { + // A multiplication of a constant with some other value. Update + // the map. + SmallVector MulOps(Mul->op_begin()+1, Mul->op_end()); + const SCEV *Key = SE.getMulExpr(MulOps); + std::pair::iterator, bool> Pair = + M.insert(std::make_pair(Key, NewScale)); + if (Pair.second) { + NewOps.push_back(Pair.first->first); + } else { + Pair.first->second += NewScale; + // The map already had an entry for this value, which may indicate + // a folding opportunity. + Interesting = true; + } + } + } else if (const SCEVConstant *C = dyn_cast(Ops[i])) { + // Pull a buried constant out to the outside. + if (Scale != 1 || AccumulatedConstant != 0 || C->isZero()) + Interesting = true; + AccumulatedConstant += Scale * C->getValue()->getValue(); + } else { + // An ordinary operand. Update the map. + std::pair::iterator, bool> Pair = + M.insert(std::make_pair(Ops[i], Scale)); + if (Pair.second) { + NewOps.push_back(Pair.first->first); + } else { + Pair.first->second += Scale; + // The map already had an entry for this value, which may indicate + // a folding opportunity. + Interesting = true; + } + } + } + + return Interesting; +} + +namespace { + struct APIntCompare { + bool operator()(const APInt &LHS, const APInt &RHS) const { + return LHS.ult(RHS); + } + }; +} + +/// getAddExpr - Get a canonical add expression, or something simpler if +/// possible. +const SCEV *ScalarEvolution::getAddExpr(SmallVectorImpl &Ops, + bool HasNUW, bool HasNSW) { + assert(!Ops.empty() && "Cannot get empty add!"); + if (Ops.size() == 1) return Ops[0]; +#ifndef NDEBUG + for (unsigned i = 1, e = Ops.size(); i != e; ++i) + assert(getEffectiveSCEVType(Ops[i]->getType()) == + getEffectiveSCEVType(Ops[0]->getType()) && + "SCEVAddExpr operand types don't match!"); +#endif + + // Sort by complexity, this groups all similar expression types together. + GroupByComplexity(Ops, LI); + + // If there are any constants, fold them together. + unsigned Idx = 0; + if (const SCEVConstant *LHSC = dyn_cast(Ops[0])) { + ++Idx; + assert(Idx < Ops.size()); + while (const SCEVConstant *RHSC = dyn_cast(Ops[Idx])) { + // We found two constants, fold them together! + Ops[0] = getConstant(LHSC->getValue()->getValue() + + RHSC->getValue()->getValue()); + if (Ops.size() == 2) return Ops[0]; + Ops.erase(Ops.begin()+1); // Erase the folded element + LHSC = cast(Ops[0]); + } + + // If we are left with a constant zero being added, strip it off. + if (cast(Ops[0])->getValue()->isZero()) { + Ops.erase(Ops.begin()); + --Idx; + } + } + + if (Ops.size() == 1) return Ops[0]; + + // Okay, check to see if the same value occurs in the operand list twice. If + // so, merge them together into an multiply expression. Since we sorted the + // list, these values are required to be adjacent. + const Type *Ty = Ops[0]->getType(); + for (unsigned i = 0, e = Ops.size()-1; i != e; ++i) + if (Ops[i] == Ops[i+1]) { // X + Y + Y --> X + Y*2 + // Found a match, merge the two values into a multiply, and add any + // remaining values to the result. + const SCEV *Two = getIntegerSCEV(2, Ty); + const SCEV *Mul = getMulExpr(Ops[i], Two); + if (Ops.size() == 2) + return Mul; + Ops.erase(Ops.begin()+i, Ops.begin()+i+2); + Ops.push_back(Mul); + return getAddExpr(Ops, HasNUW, HasNSW); + } + + // Check for truncates. If all the operands are truncated from the same + // type, see if factoring out the truncate would permit the result to be + // folded. eg., trunc(x) + m*trunc(n) --> trunc(x + trunc(m)*n) + // if the contents of the resulting outer trunc fold to something simple. + for (; Idx < Ops.size() && isa(Ops[Idx]); ++Idx) { + const SCEVTruncateExpr *Trunc = cast(Ops[Idx]); + const Type *DstType = Trunc->getType(); + const Type *SrcType = Trunc->getOperand()->getType(); + SmallVector LargeOps; + bool Ok = true; + // Check all the operands to see if they can be represented in the + // source type of the truncate. + for (unsigned i = 0, e = Ops.size(); i != e; ++i) { + if (const SCEVTruncateExpr *T = dyn_cast(Ops[i])) { + if (T->getOperand()->getType() != SrcType) { + Ok = false; + break; + } + LargeOps.push_back(T->getOperand()); + } else if (const SCEVConstant *C = dyn_cast(Ops[i])) { + // This could be either sign or zero extension, but sign extension + // is much more likely to be foldable here. + LargeOps.push_back(getSignExtendExpr(C, SrcType)); + } else if (const SCEVMulExpr *M = dyn_cast(Ops[i])) { + SmallVector LargeMulOps; + for (unsigned j = 0, f = M->getNumOperands(); j != f && Ok; ++j) { + if (const SCEVTruncateExpr *T = + dyn_cast(M->getOperand(j))) { + if (T->getOperand()->getType() != SrcType) { + Ok = false; + break; + } + LargeMulOps.push_back(T->getOperand()); + } else if (const SCEVConstant *C = + dyn_cast(M->getOperand(j))) { + // This could be either sign or zero extension, but sign extension + // is much more likely to be foldable here. + LargeMulOps.push_back(getSignExtendExpr(C, SrcType)); + } else { + Ok = false; + break; + } + } + if (Ok) + LargeOps.push_back(getMulExpr(LargeMulOps)); + } else { + Ok = false; + break; + } + } + if (Ok) { + // Evaluate the expression in the larger type. + const SCEV *Fold = getAddExpr(LargeOps, HasNUW, HasNSW); + // If it folds to something simple, use it. Otherwise, don't. + if (isa(Fold) || isa(Fold)) + return getTruncateExpr(Fold, DstType); + } + } + + // Skip past any other cast SCEVs. + while (Idx < Ops.size() && Ops[Idx]->getSCEVType() < scAddExpr) + ++Idx; + + // If there are add operands they would be next. + if (Idx < Ops.size()) { + bool DeletedAdd = false; + while (const SCEVAddExpr *Add = dyn_cast(Ops[Idx])) { + // If we have an add, expand the add operands onto the end of the operands + // list. + Ops.insert(Ops.end(), Add->op_begin(), Add->op_end()); + Ops.erase(Ops.begin()+Idx); + DeletedAdd = true; + } + + // If we deleted at least one add, we added operands to the end of the list, + // and they are not necessarily sorted. Recurse to resort and resimplify + // any operands we just aquired. + if (DeletedAdd) + return getAddExpr(Ops); + } + + // Skip over the add expression until we get to a multiply. + while (Idx < Ops.size() && Ops[Idx]->getSCEVType() < scMulExpr) + ++Idx; + + // Check to see if there are any folding opportunities present with + // operands multiplied by constant values. + if (Idx < Ops.size() && isa(Ops[Idx])) { + uint64_t BitWidth = getTypeSizeInBits(Ty); + DenseMap M; + SmallVector NewOps; + APInt AccumulatedConstant(BitWidth, 0); + if (CollectAddOperandsWithScales(M, NewOps, AccumulatedConstant, + Ops, APInt(BitWidth, 1), *this)) { + // Some interesting folding opportunity is present, so its worthwhile to + // re-generate the operands list. Group the operands by constant scale, + // to avoid multiplying by the same constant scale multiple times. + std::map, APIntCompare> MulOpLists; + for (SmallVector::iterator I = NewOps.begin(), + E = NewOps.end(); I != E; ++I) + MulOpLists[M.find(*I)->second].push_back(*I); + // Re-generate the operands list. + Ops.clear(); + if (AccumulatedConstant != 0) + Ops.push_back(getConstant(AccumulatedConstant)); + for (std::map, APIntCompare>::iterator + I = MulOpLists.begin(), E = MulOpLists.end(); I != E; ++I) + if (I->first != 0) + Ops.push_back(getMulExpr(getConstant(I->first), + getAddExpr(I->second))); + if (Ops.empty()) + return getIntegerSCEV(0, Ty); + if (Ops.size() == 1) + return Ops[0]; + return getAddExpr(Ops); + } + } + + // If we are adding something to a multiply expression, make sure the + // something is not already an operand of the multiply. If so, merge it into + // the multiply. + for (; Idx < Ops.size() && isa(Ops[Idx]); ++Idx) { + const SCEVMulExpr *Mul = cast(Ops[Idx]); + for (unsigned MulOp = 0, e = Mul->getNumOperands(); MulOp != e; ++MulOp) { + const SCEV *MulOpSCEV = Mul->getOperand(MulOp); + for (unsigned AddOp = 0, e = Ops.size(); AddOp != e; ++AddOp) + if (MulOpSCEV == Ops[AddOp] && !isa(Ops[AddOp])) { + // Fold W + X + (X * Y * Z) --> W + (X * ((Y*Z)+1)) + const SCEV *InnerMul = Mul->getOperand(MulOp == 0); + if (Mul->getNumOperands() != 2) { + // If the multiply has more than two operands, we must get the + // Y*Z term. + SmallVector MulOps(Mul->op_begin(), Mul->op_end()); + MulOps.erase(MulOps.begin()+MulOp); + InnerMul = getMulExpr(MulOps); + } + const SCEV *One = getIntegerSCEV(1, Ty); + const SCEV *AddOne = getAddExpr(InnerMul, One); + const SCEV *OuterMul = getMulExpr(AddOne, Ops[AddOp]); + if (Ops.size() == 2) return OuterMul; + if (AddOp < Idx) { + Ops.erase(Ops.begin()+AddOp); + Ops.erase(Ops.begin()+Idx-1); + } else { + Ops.erase(Ops.begin()+Idx); + Ops.erase(Ops.begin()+AddOp-1); + } + Ops.push_back(OuterMul); + return getAddExpr(Ops); + } + + // Check this multiply against other multiplies being added together. + for (unsigned OtherMulIdx = Idx+1; + OtherMulIdx < Ops.size() && isa(Ops[OtherMulIdx]); + ++OtherMulIdx) { + const SCEVMulExpr *OtherMul = cast(Ops[OtherMulIdx]); + // If MulOp occurs in OtherMul, we can fold the two multiplies + // together. + for (unsigned OMulOp = 0, e = OtherMul->getNumOperands(); + OMulOp != e; ++OMulOp) + if (OtherMul->getOperand(OMulOp) == MulOpSCEV) { + // Fold X + (A*B*C) + (A*D*E) --> X + (A*(B*C+D*E)) + const SCEV *InnerMul1 = Mul->getOperand(MulOp == 0); + if (Mul->getNumOperands() != 2) { + SmallVector MulOps(Mul->op_begin(), + Mul->op_end()); + MulOps.erase(MulOps.begin()+MulOp); + InnerMul1 = getMulExpr(MulOps); + } + const SCEV *InnerMul2 = OtherMul->getOperand(OMulOp == 0); + if (OtherMul->getNumOperands() != 2) { + SmallVector MulOps(OtherMul->op_begin(), + OtherMul->op_end()); + MulOps.erase(MulOps.begin()+OMulOp); + InnerMul2 = getMulExpr(MulOps); + } + const SCEV *InnerMulSum = getAddExpr(InnerMul1,InnerMul2); + const SCEV *OuterMul = getMulExpr(MulOpSCEV, InnerMulSum); + if (Ops.size() == 2) return OuterMul; + Ops.erase(Ops.begin()+Idx); + Ops.erase(Ops.begin()+OtherMulIdx-1); + Ops.push_back(OuterMul); + return getAddExpr(Ops); + } + } + } + } + + // If there are any add recurrences in the operands list, see if any other + // added values are loop invariant. If so, we can fold them into the + // recurrence. + while (Idx < Ops.size() && Ops[Idx]->getSCEVType() < scAddRecExpr) + ++Idx; + + // Scan over all recurrences, trying to fold loop invariants into them. + for (; Idx < Ops.size() && isa(Ops[Idx]); ++Idx) { + // Scan all of the other operands to this add and add them to the vector if + // they are loop invariant w.r.t. the recurrence. + SmallVector LIOps; + const SCEVAddRecExpr *AddRec = cast(Ops[Idx]); + for (unsigned i = 0, e = Ops.size(); i != e; ++i) + if (Ops[i]->isLoopInvariant(AddRec->getLoop())) { + LIOps.push_back(Ops[i]); + Ops.erase(Ops.begin()+i); + --i; --e; + } + + // If we found some loop invariants, fold them into the recurrence. + if (!LIOps.empty()) { + // NLI + LI + {Start,+,Step} --> NLI + {LI+Start,+,Step} + LIOps.push_back(AddRec->getStart()); + + SmallVector AddRecOps(AddRec->op_begin(), + AddRec->op_end()); + AddRecOps[0] = getAddExpr(LIOps); + + const SCEV *NewRec = getAddRecExpr(AddRecOps, AddRec->getLoop()); + // If all of the other operands were loop invariant, we are done. + if (Ops.size() == 1) return NewRec; + + // Otherwise, add the folded AddRec by the non-liv parts. + for (unsigned i = 0;; ++i) + if (Ops[i] == AddRec) { + Ops[i] = NewRec; + break; + } + return getAddExpr(Ops); + } + + // Okay, if there weren't any loop invariants to be folded, check to see if + // there are multiple AddRec's with the same loop induction variable being + // added together. If so, we can fold them. + for (unsigned OtherIdx = Idx+1; + OtherIdx < Ops.size() && isa(Ops[OtherIdx]);++OtherIdx) + if (OtherIdx != Idx) { + const SCEVAddRecExpr *OtherAddRec = cast(Ops[OtherIdx]); + if (AddRec->getLoop() == OtherAddRec->getLoop()) { + // Other + {A,+,B} + {C,+,D} --> Other + {A+C,+,B+D} + SmallVector NewOps(AddRec->op_begin(), + AddRec->op_end()); + for (unsigned i = 0, e = OtherAddRec->getNumOperands(); i != e; ++i) { + if (i >= NewOps.size()) { + NewOps.insert(NewOps.end(), OtherAddRec->op_begin()+i, + OtherAddRec->op_end()); + break; + } + NewOps[i] = getAddExpr(NewOps[i], OtherAddRec->getOperand(i)); + } + const SCEV *NewAddRec = getAddRecExpr(NewOps, AddRec->getLoop()); + + if (Ops.size() == 2) return NewAddRec; + + Ops.erase(Ops.begin()+Idx); + Ops.erase(Ops.begin()+OtherIdx-1); + Ops.push_back(NewAddRec); + return getAddExpr(Ops); + } + } + + // Otherwise couldn't fold anything into this recurrence. Move onto the + // next one. + } + + // Okay, it looks like we really DO need an add expr. Check to see if we + // already have one, otherwise create a new one. + FoldingSetNodeID ID; + ID.AddInteger(scAddExpr); + ID.AddInteger(Ops.size()); + for (unsigned i = 0, e = Ops.size(); i != e; ++i) + ID.AddPointer(Ops[i]); + void *IP = 0; + if (const SCEV *S = UniqueSCEVs.FindNodeOrInsertPos(ID, IP)) return S; + SCEVAddExpr *S = SCEVAllocator.Allocate(); + new (S) SCEVAddExpr(ID, Ops); + UniqueSCEVs.InsertNode(S, IP); + if (HasNUW) S->setHasNoUnsignedWrap(true); + if (HasNSW) S->setHasNoSignedWrap(true); + return S; +} + + +/// getMulExpr - Get a canonical multiply expression, or something simpler if +/// possible. +const SCEV *ScalarEvolution::getMulExpr(SmallVectorImpl &Ops, + bool HasNUW, bool HasNSW) { + assert(!Ops.empty() && "Cannot get empty mul!"); +#ifndef NDEBUG + for (unsigned i = 1, e = Ops.size(); i != e; ++i) + assert(getEffectiveSCEVType(Ops[i]->getType()) == + getEffectiveSCEVType(Ops[0]->getType()) && + "SCEVMulExpr operand types don't match!"); +#endif + + // Sort by complexity, this groups all similar expression types together. + GroupByComplexity(Ops, LI); + + // If there are any constants, fold them together. + unsigned Idx = 0; + if (const SCEVConstant *LHSC = dyn_cast(Ops[0])) { + + // C1*(C2+V) -> C1*C2 + C1*V + if (Ops.size() == 2) + if (const SCEVAddExpr *Add = dyn_cast(Ops[1])) + if (Add->getNumOperands() == 2 && + isa(Add->getOperand(0))) + return getAddExpr(getMulExpr(LHSC, Add->getOperand(0)), + getMulExpr(LHSC, Add->getOperand(1))); + + + ++Idx; + while (const SCEVConstant *RHSC = dyn_cast(Ops[Idx])) { + // We found two constants, fold them together! + ConstantInt *Fold = ConstantInt::get(getContext(), + LHSC->getValue()->getValue() * + RHSC->getValue()->getValue()); + Ops[0] = getConstant(Fold); + Ops.erase(Ops.begin()+1); // Erase the folded element + if (Ops.size() == 1) return Ops[0]; + LHSC = cast(Ops[0]); + } + + // If we are left with a constant one being multiplied, strip it off. + if (cast(Ops[0])->getValue()->equalsInt(1)) { + Ops.erase(Ops.begin()); + --Idx; + } else if (cast(Ops[0])->getValue()->isZero()) { + // If we have a multiply of zero, it will always be zero. + return Ops[0]; + } + } + + // Skip over the add expression until we get to a multiply. + while (Idx < Ops.size() && Ops[Idx]->getSCEVType() < scMulExpr) + ++Idx; + + if (Ops.size() == 1) + return Ops[0]; + + // If there are mul operands inline them all into this expression. + if (Idx < Ops.size()) { + bool DeletedMul = false; + while (const SCEVMulExpr *Mul = dyn_cast(Ops[Idx])) { + // If we have an mul, expand the mul operands onto the end of the operands + // list. + Ops.insert(Ops.end(), Mul->op_begin(), Mul->op_end()); + Ops.erase(Ops.begin()+Idx); + DeletedMul = true; + } + + // If we deleted at least one mul, we added operands to the end of the list, + // and they are not necessarily sorted. Recurse to resort and resimplify + // any operands we just aquired. + if (DeletedMul) + return getMulExpr(Ops); + } + + // If there are any add recurrences in the operands list, see if any other + // added values are loop invariant. If so, we can fold them into the + // recurrence. + while (Idx < Ops.size() && Ops[Idx]->getSCEVType() < scAddRecExpr) + ++Idx; + + // Scan over all recurrences, trying to fold loop invariants into them. + for (; Idx < Ops.size() && isa(Ops[Idx]); ++Idx) { + // Scan all of the other operands to this mul and add them to the vector if + // they are loop invariant w.r.t. the recurrence. + SmallVector LIOps; + const SCEVAddRecExpr *AddRec = cast(Ops[Idx]); + for (unsigned i = 0, e = Ops.size(); i != e; ++i) + if (Ops[i]->isLoopInvariant(AddRec->getLoop())) { + LIOps.push_back(Ops[i]); + Ops.erase(Ops.begin()+i); + --i; --e; + } + + // If we found some loop invariants, fold them into the recurrence. + if (!LIOps.empty()) { + // NLI * LI * {Start,+,Step} --> NLI * {LI*Start,+,LI*Step} + SmallVector NewOps; + NewOps.reserve(AddRec->getNumOperands()); + if (LIOps.size() == 1) { + const SCEV *Scale = LIOps[0]; + for (unsigned i = 0, e = AddRec->getNumOperands(); i != e; ++i) + NewOps.push_back(getMulExpr(Scale, AddRec->getOperand(i))); + } else { + for (unsigned i = 0, e = AddRec->getNumOperands(); i != e; ++i) { + SmallVector MulOps(LIOps.begin(), LIOps.end()); + MulOps.push_back(AddRec->getOperand(i)); + NewOps.push_back(getMulExpr(MulOps)); + } + } + + const SCEV *NewRec = getAddRecExpr(NewOps, AddRec->getLoop()); + + // If all of the other operands were loop invariant, we are done. + if (Ops.size() == 1) return NewRec; + + // Otherwise, multiply the folded AddRec by the non-liv parts. + for (unsigned i = 0;; ++i) + if (Ops[i] == AddRec) { + Ops[i] = NewRec; + break; + } + return getMulExpr(Ops); + } + + // Okay, if there weren't any loop invariants to be folded, check to see if + // there are multiple AddRec's with the same loop induction variable being + // multiplied together. If so, we can fold them. + for (unsigned OtherIdx = Idx+1; + OtherIdx < Ops.size() && isa(Ops[OtherIdx]);++OtherIdx) + if (OtherIdx != Idx) { + const SCEVAddRecExpr *OtherAddRec = cast(Ops[OtherIdx]); + if (AddRec->getLoop() == OtherAddRec->getLoop()) { + // F * G --> {A,+,B} * {C,+,D} --> {A*C,+,F*D + G*B + B*D} + const SCEVAddRecExpr *F = AddRec, *G = OtherAddRec; + const SCEV *NewStart = getMulExpr(F->getStart(), + G->getStart()); + const SCEV *B = F->getStepRecurrence(*this); + const SCEV *D = G->getStepRecurrence(*this); + const SCEV *NewStep = getAddExpr(getMulExpr(F, D), + getMulExpr(G, B), + getMulExpr(B, D)); + const SCEV *NewAddRec = getAddRecExpr(NewStart, NewStep, + F->getLoop()); + if (Ops.size() == 2) return NewAddRec; + + Ops.erase(Ops.begin()+Idx); + Ops.erase(Ops.begin()+OtherIdx-1); + Ops.push_back(NewAddRec); + return getMulExpr(Ops); + } + } + + // Otherwise couldn't fold anything into this recurrence. Move onto the + // next one. + } + + // Okay, it looks like we really DO need an mul expr. Check to see if we + // already have one, otherwise create a new one. + FoldingSetNodeID ID; + ID.AddInteger(scMulExpr); + ID.AddInteger(Ops.size()); + for (unsigned i = 0, e = Ops.size(); i != e; ++i) + ID.AddPointer(Ops[i]); + void *IP = 0; + if (const SCEV *S = UniqueSCEVs.FindNodeOrInsertPos(ID, IP)) return S; + SCEVMulExpr *S = SCEVAllocator.Allocate(); + new (S) SCEVMulExpr(ID, Ops); + UniqueSCEVs.InsertNode(S, IP); + if (HasNUW) S->setHasNoUnsignedWrap(true); + if (HasNSW) S->setHasNoSignedWrap(true); + return S; +} + +/// getUDivExpr - Get a canonical unsigned division expression, or something +/// simpler if possible. +const SCEV *ScalarEvolution::getUDivExpr(const SCEV *LHS, + const SCEV *RHS) { + assert(getEffectiveSCEVType(LHS->getType()) == + getEffectiveSCEVType(RHS->getType()) && + "SCEVUDivExpr operand types don't match!"); + + if (const SCEVConstant *RHSC = dyn_cast(RHS)) { + if (RHSC->getValue()->equalsInt(1)) + return LHS; // X udiv 1 --> x + if (RHSC->isZero()) + return getIntegerSCEV(0, LHS->getType()); // value is undefined + + // Determine if the division can be folded into the operands of + // its operands. + // TODO: Generalize this to non-constants by using known-bits information. + const Type *Ty = LHS->getType(); + unsigned LZ = RHSC->getValue()->getValue().countLeadingZeros(); + unsigned MaxShiftAmt = getTypeSizeInBits(Ty) - LZ; + // For non-power-of-two values, effectively round the value up to the + // nearest power of two. + if (!RHSC->getValue()->getValue().isPowerOf2()) + ++MaxShiftAmt; + const IntegerType *ExtTy = + IntegerType::get(getContext(), getTypeSizeInBits(Ty) + MaxShiftAmt); + // {X,+,N}/C --> {X/C,+,N/C} if safe and N/C can be folded. + if (const SCEVAddRecExpr *AR = dyn_cast(LHS)) + if (const SCEVConstant *Step = + dyn_cast(AR->getStepRecurrence(*this))) + if (!Step->getValue()->getValue() + .urem(RHSC->getValue()->getValue()) && + getZeroExtendExpr(AR, ExtTy) == + getAddRecExpr(getZeroExtendExpr(AR->getStart(), ExtTy), + getZeroExtendExpr(Step, ExtTy), + AR->getLoop())) { + SmallVector Operands; + for (unsigned i = 0, e = AR->getNumOperands(); i != e; ++i) + Operands.push_back(getUDivExpr(AR->getOperand(i), RHS)); + return getAddRecExpr(Operands, AR->getLoop()); + } + // (A*B)/C --> A*(B/C) if safe and B/C can be folded. + if (const SCEVMulExpr *M = dyn_cast(LHS)) { + SmallVector Operands; + for (unsigned i = 0, e = M->getNumOperands(); i != e; ++i) + Operands.push_back(getZeroExtendExpr(M->getOperand(i), ExtTy)); + if (getZeroExtendExpr(M, ExtTy) == getMulExpr(Operands)) + // Find an operand that's safely divisible. + for (unsigned i = 0, e = M->getNumOperands(); i != e; ++i) { + const SCEV *Op = M->getOperand(i); + const SCEV *Div = getUDivExpr(Op, RHSC); + if (!isa(Div) && getMulExpr(Div, RHSC) == Op) { + const SmallVectorImpl &MOperands = M->getOperands(); + Operands = SmallVector(MOperands.begin(), + MOperands.end()); + Operands[i] = Div; + return getMulExpr(Operands); + } + } + } + // (A+B)/C --> (A/C + B/C) if safe and A/C and B/C can be folded. + if (const SCEVAddRecExpr *A = dyn_cast(LHS)) { + SmallVector Operands; + for (unsigned i = 0, e = A->getNumOperands(); i != e; ++i) + Operands.push_back(getZeroExtendExpr(A->getOperand(i), ExtTy)); + if (getZeroExtendExpr(A, ExtTy) == getAddExpr(Operands)) { + Operands.clear(); + for (unsigned i = 0, e = A->getNumOperands(); i != e; ++i) { + const SCEV *Op = getUDivExpr(A->getOperand(i), RHS); + if (isa(Op) || getMulExpr(Op, RHS) != A->getOperand(i)) + break; + Operands.push_back(Op); + } + if (Operands.size() == A->getNumOperands()) + return getAddExpr(Operands); + } + } + + // Fold if both operands are constant. + if (const SCEVConstant *LHSC = dyn_cast(LHS)) { + Constant *LHSCV = LHSC->getValue(); + Constant *RHSCV = RHSC->getValue(); + return getConstant(cast(ConstantExpr::getUDiv(LHSCV, + RHSCV))); + } + } + + FoldingSetNodeID ID; + ID.AddInteger(scUDivExpr); + ID.AddPointer(LHS); + ID.AddPointer(RHS); + void *IP = 0; + if (const SCEV *S = UniqueSCEVs.FindNodeOrInsertPos(ID, IP)) return S; + SCEV *S = SCEVAllocator.Allocate(); + new (S) SCEVUDivExpr(ID, LHS, RHS); + UniqueSCEVs.InsertNode(S, IP); + return S; +} + + +/// getAddRecExpr - Get an add recurrence expression for the specified loop. +/// Simplify the expression as much as possible. +const SCEV *ScalarEvolution::getAddRecExpr(const SCEV *Start, + const SCEV *Step, const Loop *L, + bool HasNUW, bool HasNSW) { + SmallVector Operands; + Operands.push_back(Start); + if (const SCEVAddRecExpr *StepChrec = dyn_cast(Step)) + if (StepChrec->getLoop() == L) { + Operands.insert(Operands.end(), StepChrec->op_begin(), + StepChrec->op_end()); + return getAddRecExpr(Operands, L); + } + + Operands.push_back(Step); + return getAddRecExpr(Operands, L, HasNUW, HasNSW); +} + +/// getAddRecExpr - Get an add recurrence expression for the specified loop. +/// Simplify the expression as much as possible. +const SCEV * +ScalarEvolution::getAddRecExpr(SmallVectorImpl &Operands, + const Loop *L, + bool HasNUW, bool HasNSW) { + if (Operands.size() == 1) return Operands[0]; +#ifndef NDEBUG + for (unsigned i = 1, e = Operands.size(); i != e; ++i) + assert(getEffectiveSCEVType(Operands[i]->getType()) == + getEffectiveSCEVType(Operands[0]->getType()) && + "SCEVAddRecExpr operand types don't match!"); +#endif + + if (Operands.back()->isZero()) { + Operands.pop_back(); + return getAddRecExpr(Operands, L, HasNUW, HasNSW); // {X,+,0} --> X + } + + // Canonicalize nested AddRecs in by nesting them in order of loop depth. + if (const SCEVAddRecExpr *NestedAR = dyn_cast(Operands[0])) { + const Loop* NestedLoop = NestedAR->getLoop(); + if (L->getLoopDepth() < NestedLoop->getLoopDepth()) { + SmallVector NestedOperands(NestedAR->op_begin(), + NestedAR->op_end()); + Operands[0] = NestedAR->getStart(); + // AddRecs require their operands be loop-invariant with respect to their + // loops. Don't perform this transformation if it would break this + // requirement. + bool AllInvariant = true; + for (unsigned i = 0, e = Operands.size(); i != e; ++i) + if (!Operands[i]->isLoopInvariant(L)) { + AllInvariant = false; + break; + } + if (AllInvariant) { + NestedOperands[0] = getAddRecExpr(Operands, L); + AllInvariant = true; + for (unsigned i = 0, e = NestedOperands.size(); i != e; ++i) + if (!NestedOperands[i]->isLoopInvariant(NestedLoop)) { + AllInvariant = false; + break; + } + if (AllInvariant) + // Ok, both add recurrences are valid after the transformation. + return getAddRecExpr(NestedOperands, NestedLoop, HasNUW, HasNSW); + } + // Reset Operands to its original state. + Operands[0] = NestedAR; + } + } + + FoldingSetNodeID ID; + ID.AddInteger(scAddRecExpr); + ID.AddInteger(Operands.size()); + for (unsigned i = 0, e = Operands.size(); i != e; ++i) + ID.AddPointer(Operands[i]); + ID.AddPointer(L); + void *IP = 0; + if (const SCEV *S = UniqueSCEVs.FindNodeOrInsertPos(ID, IP)) return S; + SCEVAddRecExpr *S = SCEVAllocator.Allocate(); + new (S) SCEVAddRecExpr(ID, Operands, L); + UniqueSCEVs.InsertNode(S, IP); + if (HasNUW) S->setHasNoUnsignedWrap(true); + if (HasNSW) S->setHasNoSignedWrap(true); + return S; +} + +const SCEV *ScalarEvolution::getSMaxExpr(const SCEV *LHS, + const SCEV *RHS) { + SmallVector Ops; + Ops.push_back(LHS); + Ops.push_back(RHS); + return getSMaxExpr(Ops); +} + +const SCEV * +ScalarEvolution::getSMaxExpr(SmallVectorImpl &Ops) { + assert(!Ops.empty() && "Cannot get empty smax!"); + if (Ops.size() == 1) return Ops[0]; +#ifndef NDEBUG + for (unsigned i = 1, e = Ops.size(); i != e; ++i) + assert(getEffectiveSCEVType(Ops[i]->getType()) == + getEffectiveSCEVType(Ops[0]->getType()) && + "SCEVSMaxExpr operand types don't match!"); +#endif + + // Sort by complexity, this groups all similar expression types together. + GroupByComplexity(Ops, LI); + + // If there are any constants, fold them together. + unsigned Idx = 0; + if (const SCEVConstant *LHSC = dyn_cast(Ops[0])) { + ++Idx; + assert(Idx < Ops.size()); + while (const SCEVConstant *RHSC = dyn_cast(Ops[Idx])) { + // We found two constants, fold them together! + ConstantInt *Fold = ConstantInt::get(getContext(), + APIntOps::smax(LHSC->getValue()->getValue(), + RHSC->getValue()->getValue())); + Ops[0] = getConstant(Fold); + Ops.erase(Ops.begin()+1); // Erase the folded element + if (Ops.size() == 1) return Ops[0]; + LHSC = cast(Ops[0]); + } + + // If we are left with a constant minimum-int, strip it off. + if (cast(Ops[0])->getValue()->isMinValue(true)) { + Ops.erase(Ops.begin()); + --Idx; + } else if (cast(Ops[0])->getValue()->isMaxValue(true)) { + // If we have an smax with a constant maximum-int, it will always be + // maximum-int. + return Ops[0]; + } + } + + if (Ops.size() == 1) return Ops[0]; + + // Find the first SMax + while (Idx < Ops.size() && Ops[Idx]->getSCEVType() < scSMaxExpr) + ++Idx; + + // Check to see if one of the operands is an SMax. If so, expand its operands + // onto our operand list, and recurse to simplify. + if (Idx < Ops.size()) { + bool DeletedSMax = false; + while (const SCEVSMaxExpr *SMax = dyn_cast(Ops[Idx])) { + Ops.insert(Ops.end(), SMax->op_begin(), SMax->op_end()); + Ops.erase(Ops.begin()+Idx); + DeletedSMax = true; + } + + if (DeletedSMax) + return getSMaxExpr(Ops); + } + + // Okay, check to see if the same value occurs in the operand list twice. If + // so, delete one. Since we sorted the list, these values are required to + // be adjacent. + for (unsigned i = 0, e = Ops.size()-1; i != e; ++i) + if (Ops[i] == Ops[i+1]) { // X smax Y smax Y --> X smax Y + Ops.erase(Ops.begin()+i, Ops.begin()+i+1); + --i; --e; + } + + if (Ops.size() == 1) return Ops[0]; + + assert(!Ops.empty() && "Reduced smax down to nothing!"); + + // Okay, it looks like we really DO need an smax expr. Check to see if we + // already have one, otherwise create a new one. + FoldingSetNodeID ID; + ID.AddInteger(scSMaxExpr); + ID.AddInteger(Ops.size()); + for (unsigned i = 0, e = Ops.size(); i != e; ++i) + ID.AddPointer(Ops[i]); + void *IP = 0; + if (const SCEV *S = UniqueSCEVs.FindNodeOrInsertPos(ID, IP)) return S; + SCEV *S = SCEVAllocator.Allocate(); + new (S) SCEVSMaxExpr(ID, Ops); + UniqueSCEVs.InsertNode(S, IP); + return S; +} + +const SCEV *ScalarEvolution::getUMaxExpr(const SCEV *LHS, + const SCEV *RHS) { + SmallVector Ops; + Ops.push_back(LHS); + Ops.push_back(RHS); + return getUMaxExpr(Ops); +} + +const SCEV * +ScalarEvolution::getUMaxExpr(SmallVectorImpl &Ops) { + assert(!Ops.empty() && "Cannot get empty umax!"); + if (Ops.size() == 1) return Ops[0]; +#ifndef NDEBUG + for (unsigned i = 1, e = Ops.size(); i != e; ++i) + assert(getEffectiveSCEVType(Ops[i]->getType()) == + getEffectiveSCEVType(Ops[0]->getType()) && + "SCEVUMaxExpr operand types don't match!"); +#endif + + // Sort by complexity, this groups all similar expression types together. + GroupByComplexity(Ops, LI); + + // If there are any constants, fold them together. + unsigned Idx = 0; + if (const SCEVConstant *LHSC = dyn_cast(Ops[0])) { + ++Idx; + assert(Idx < Ops.size()); + while (const SCEVConstant *RHSC = dyn_cast(Ops[Idx])) { + // We found two constants, fold them together! + ConstantInt *Fold = ConstantInt::get(getContext(), + APIntOps::umax(LHSC->getValue()->getValue(), + RHSC->getValue()->getValue())); + Ops[0] = getConstant(Fold); + Ops.erase(Ops.begin()+1); // Erase the folded element + if (Ops.size() == 1) return Ops[0]; + LHSC = cast(Ops[0]); + } + + // If we are left with a constant minimum-int, strip it off. + if (cast(Ops[0])->getValue()->isMinValue(false)) { + Ops.erase(Ops.begin()); + --Idx; + } else if (cast(Ops[0])->getValue()->isMaxValue(false)) { + // If we have an umax with a constant maximum-int, it will always be + // maximum-int. + return Ops[0]; + } + } + + if (Ops.size() == 1) return Ops[0]; + + // Find the first UMax + while (Idx < Ops.size() && Ops[Idx]->getSCEVType() < scUMaxExpr) + ++Idx; + + // Check to see if one of the operands is a UMax. If so, expand its operands + // onto our operand list, and recurse to simplify. + if (Idx < Ops.size()) { + bool DeletedUMax = false; + while (const SCEVUMaxExpr *UMax = dyn_cast(Ops[Idx])) { + Ops.insert(Ops.end(), UMax->op_begin(), UMax->op_end()); + Ops.erase(Ops.begin()+Idx); + DeletedUMax = true; + } + + if (DeletedUMax) + return getUMaxExpr(Ops); + } + + // Okay, check to see if the same value occurs in the operand list twice. If + // so, delete one. Since we sorted the list, these values are required to + // be adjacent. + for (unsigned i = 0, e = Ops.size()-1; i != e; ++i) + if (Ops[i] == Ops[i+1]) { // X umax Y umax Y --> X umax Y + Ops.erase(Ops.begin()+i, Ops.begin()+i+1); + --i; --e; + } + + if (Ops.size() == 1) return Ops[0]; + + assert(!Ops.empty() && "Reduced umax down to nothing!"); + + // Okay, it looks like we really DO need a umax expr. Check to see if we + // already have one, otherwise create a new one. + FoldingSetNodeID ID; + ID.AddInteger(scUMaxExpr); + ID.AddInteger(Ops.size()); + for (unsigned i = 0, e = Ops.size(); i != e; ++i) + ID.AddPointer(Ops[i]); + void *IP = 0; + if (const SCEV *S = UniqueSCEVs.FindNodeOrInsertPos(ID, IP)) return S; + SCEV *S = SCEVAllocator.Allocate(); + new (S) SCEVUMaxExpr(ID, Ops); + UniqueSCEVs.InsertNode(S, IP); + return S; +} + +const SCEV *ScalarEvolution::getSMinExpr(const SCEV *LHS, + const SCEV *RHS) { + // ~smax(~x, ~y) == smin(x, y). + return getNotSCEV(getSMaxExpr(getNotSCEV(LHS), getNotSCEV(RHS))); +} + +const SCEV *ScalarEvolution::getUMinExpr(const SCEV *LHS, + const SCEV *RHS) { + // ~umax(~x, ~y) == umin(x, y) + return getNotSCEV(getUMaxExpr(getNotSCEV(LHS), getNotSCEV(RHS))); +} + +const SCEV *ScalarEvolution::getFieldOffsetExpr(const StructType *STy, + unsigned FieldNo) { + // If we have TargetData we can determine the constant offset. + if (TD) { + const Type *IntPtrTy = TD->getIntPtrType(getContext()); + const StructLayout &SL = *TD->getStructLayout(STy); + uint64_t Offset = SL.getElementOffset(FieldNo); + return getIntegerSCEV(Offset, IntPtrTy); + } + + // Field 0 is always at offset 0. + if (FieldNo == 0) { + const Type *Ty = getEffectiveSCEVType(PointerType::getUnqual(STy)); + return getIntegerSCEV(0, Ty); + } + + // Okay, it looks like we really DO need an offsetof expr. Check to see if we + // already have one, otherwise create a new one. + FoldingSetNodeID ID; + ID.AddInteger(scFieldOffset); + ID.AddPointer(STy); + ID.AddInteger(FieldNo); + void *IP = 0; + if (const SCEV *S = UniqueSCEVs.FindNodeOrInsertPos(ID, IP)) return S; + SCEV *S = SCEVAllocator.Allocate(); + const Type *Ty = getEffectiveSCEVType(PointerType::getUnqual(STy)); + new (S) SCEVFieldOffsetExpr(ID, Ty, STy, FieldNo); + UniqueSCEVs.InsertNode(S, IP); + return S; +} + +const SCEV *ScalarEvolution::getAllocSizeExpr(const Type *AllocTy) { + // If we have TargetData we can determine the constant size. + if (TD && AllocTy->isSized()) { + const Type *IntPtrTy = TD->getIntPtrType(getContext()); + return getIntegerSCEV(TD->getTypeAllocSize(AllocTy), IntPtrTy); + } + + // Expand an array size into the element size times the number + // of elements. + if (const ArrayType *ATy = dyn_cast(AllocTy)) { + const SCEV *E = getAllocSizeExpr(ATy->getElementType()); + return getMulExpr( + E, getConstant(ConstantInt::get(cast(E->getType()), + ATy->getNumElements()))); + } + + // Expand a vector size into the element size times the number + // of elements. + if (const VectorType *VTy = dyn_cast(AllocTy)) { + const SCEV *E = getAllocSizeExpr(VTy->getElementType()); + return getMulExpr( + E, getConstant(ConstantInt::get(cast(E->getType()), + VTy->getNumElements()))); + } + + // Okay, it looks like we really DO need a sizeof expr. Check to see if we + // already have one, otherwise create a new one. + FoldingSetNodeID ID; + ID.AddInteger(scAllocSize); + ID.AddPointer(AllocTy); + void *IP = 0; + if (const SCEV *S = UniqueSCEVs.FindNodeOrInsertPos(ID, IP)) return S; + SCEV *S = SCEVAllocator.Allocate(); + const Type *Ty = getEffectiveSCEVType(PointerType::getUnqual(AllocTy)); + new (S) SCEVAllocSizeExpr(ID, Ty, AllocTy); + UniqueSCEVs.InsertNode(S, IP); + return S; +} + +const SCEV *ScalarEvolution::getUnknown(Value *V) { + // Don't attempt to do anything other than create a SCEVUnknown object + // here. createSCEV only calls getUnknown after checking for all other + // interesting possibilities, and any other code that calls getUnknown + // is doing so in order to hide a value from SCEV canonicalization. + + FoldingSetNodeID ID; + ID.AddInteger(scUnknown); + ID.AddPointer(V); + void *IP = 0; + if (const SCEV *S = UniqueSCEVs.FindNodeOrInsertPos(ID, IP)) return S; + SCEV *S = SCEVAllocator.Allocate(); + new (S) SCEVUnknown(ID, V); + UniqueSCEVs.InsertNode(S, IP); + return S; +} + +//===----------------------------------------------------------------------===// +// Basic SCEV Analysis and PHI Idiom Recognition Code +// + +/// isSCEVable - Test if values of the given type are analyzable within +/// the SCEV framework. This primarily includes integer types, and it +/// can optionally include pointer types if the ScalarEvolution class +/// has access to target-specific information. +bool ScalarEvolution::isSCEVable(const Type *Ty) const { + // Integers and pointers are always SCEVable. + return Ty->isInteger() || isa(Ty); +} + +/// getTypeSizeInBits - Return the size in bits of the specified type, +/// for which isSCEVable must return true. +uint64_t ScalarEvolution::getTypeSizeInBits(const Type *Ty) const { + assert(isSCEVable(Ty) && "Type is not SCEVable!"); + + // If we have a TargetData, use it! + if (TD) + return TD->getTypeSizeInBits(Ty); + + // Integer types have fixed sizes. + if (Ty->isInteger()) + return Ty->getPrimitiveSizeInBits(); + + // The only other support type is pointer. Without TargetData, conservatively + // assume pointers are 64-bit. + assert(isa(Ty) && "isSCEVable permitted a non-SCEVable type!"); + return 64; +} + +/// getEffectiveSCEVType - Return a type with the same bitwidth as +/// the given type and which represents how SCEV will treat the given +/// type, for which isSCEVable must return true. For pointer types, +/// this is the pointer-sized integer type. +const Type *ScalarEvolution::getEffectiveSCEVType(const Type *Ty) const { + assert(isSCEVable(Ty) && "Type is not SCEVable!"); + + if (Ty->isInteger()) + return Ty; + + // The only other support type is pointer. + assert(isa(Ty) && "Unexpected non-pointer non-integer type!"); + if (TD) return TD->getIntPtrType(getContext()); + + // Without TargetData, conservatively assume pointers are 64-bit. + return Type::getInt64Ty(getContext()); +} + +const SCEV *ScalarEvolution::getCouldNotCompute() { + return &CouldNotCompute; +} + +/// getSCEV - Return an existing SCEV if it exists, otherwise analyze the +/// expression and create a new one. +const SCEV *ScalarEvolution::getSCEV(Value *V) { + assert(isSCEVable(V->getType()) && "Value is not SCEVable!"); + + std::map::iterator I = Scalars.find(V); + if (I != Scalars.end()) return I->second; + const SCEV *S = createSCEV(V); + Scalars.insert(std::make_pair(SCEVCallbackVH(V, this), S)); + return S; +} + +/// getIntegerSCEV - Given a SCEVable type, create a constant for the +/// specified signed integer value and return a SCEV for the constant. +const SCEV *ScalarEvolution::getIntegerSCEV(int Val, const Type *Ty) { + const IntegerType *ITy = cast(getEffectiveSCEVType(Ty)); + return getConstant(ConstantInt::get(ITy, Val)); +} + +/// getNegativeSCEV - Return a SCEV corresponding to -V = -1*V +/// +const SCEV *ScalarEvolution::getNegativeSCEV(const SCEV *V) { + if (const SCEVConstant *VC = dyn_cast(V)) + return getConstant( + cast(ConstantExpr::getNeg(VC->getValue()))); + + const Type *Ty = V->getType(); + Ty = getEffectiveSCEVType(Ty); + return getMulExpr(V, + getConstant(cast(Constant::getAllOnesValue(Ty)))); +} + +/// getNotSCEV - Return a SCEV corresponding to ~V = -1-V +const SCEV *ScalarEvolution::getNotSCEV(const SCEV *V) { + if (const SCEVConstant *VC = dyn_cast(V)) + return getConstant( + cast(ConstantExpr::getNot(VC->getValue()))); + + const Type *Ty = V->getType(); + Ty = getEffectiveSCEVType(Ty); + const SCEV *AllOnes = + getConstant(cast(Constant::getAllOnesValue(Ty))); + return getMinusSCEV(AllOnes, V); +} + +/// getMinusSCEV - Return a SCEV corresponding to LHS - RHS. +/// +const SCEV *ScalarEvolution::getMinusSCEV(const SCEV *LHS, + const SCEV *RHS) { + // X - Y --> X + -Y + return getAddExpr(LHS, getNegativeSCEV(RHS)); +} + +/// getTruncateOrZeroExtend - Return a SCEV corresponding to a conversion of the +/// input value to the specified type. If the type must be extended, it is zero +/// extended. +const SCEV * +ScalarEvolution::getTruncateOrZeroExtend(const SCEV *V, + const Type *Ty) { + const Type *SrcTy = V->getType(); + assert((SrcTy->isInteger() || isa(SrcTy)) && + (Ty->isInteger() || isa(Ty)) && + "Cannot truncate or zero extend with non-integer arguments!"); + if (getTypeSizeInBits(SrcTy) == getTypeSizeInBits(Ty)) + return V; // No conversion + if (getTypeSizeInBits(SrcTy) > getTypeSizeInBits(Ty)) + return getTruncateExpr(V, Ty); + return getZeroExtendExpr(V, Ty); +} + +/// getTruncateOrSignExtend - Return a SCEV corresponding to a conversion of the +/// input value to the specified type. If the type must be extended, it is sign +/// extended. +const SCEV * +ScalarEvolution::getTruncateOrSignExtend(const SCEV *V, + const Type *Ty) { + const Type *SrcTy = V->getType(); + assert((SrcTy->isInteger() || isa(SrcTy)) && + (Ty->isInteger() || isa(Ty)) && + "Cannot truncate or zero extend with non-integer arguments!"); + if (getTypeSizeInBits(SrcTy) == getTypeSizeInBits(Ty)) + return V; // No conversion + if (getTypeSizeInBits(SrcTy) > getTypeSizeInBits(Ty)) + return getTruncateExpr(V, Ty); + return getSignExtendExpr(V, Ty); +} + +/// getNoopOrZeroExtend - Return a SCEV corresponding to a conversion of the +/// input value to the specified type. If the type must be extended, it is zero +/// extended. The conversion must not be narrowing. +const SCEV * +ScalarEvolution::getNoopOrZeroExtend(const SCEV *V, const Type *Ty) { + const Type *SrcTy = V->getType(); + assert((SrcTy->isInteger() || isa(SrcTy)) && + (Ty->isInteger() || isa(Ty)) && + "Cannot noop or zero extend with non-integer arguments!"); + assert(getTypeSizeInBits(SrcTy) <= getTypeSizeInBits(Ty) && + "getNoopOrZeroExtend cannot truncate!"); + if (getTypeSizeInBits(SrcTy) == getTypeSizeInBits(Ty)) + return V; // No conversion + return getZeroExtendExpr(V, Ty); +} + +/// getNoopOrSignExtend - Return a SCEV corresponding to a conversion of the +/// input value to the specified type. If the type must be extended, it is sign +/// extended. The conversion must not be narrowing. +const SCEV * +ScalarEvolution::getNoopOrSignExtend(const SCEV *V, const Type *Ty) { + const Type *SrcTy = V->getType(); + assert((SrcTy->isInteger() || isa(SrcTy)) && + (Ty->isInteger() || isa(Ty)) && + "Cannot noop or sign extend with non-integer arguments!"); + assert(getTypeSizeInBits(SrcTy) <= getTypeSizeInBits(Ty) && + "getNoopOrSignExtend cannot truncate!"); + if (getTypeSizeInBits(SrcTy) == getTypeSizeInBits(Ty)) + return V; // No conversion + return getSignExtendExpr(V, Ty); +} + +/// getNoopOrAnyExtend - Return a SCEV corresponding to a conversion of +/// the input value to the specified type. If the type must be extended, +/// it is extended with unspecified bits. The conversion must not be +/// narrowing. +const SCEV * +ScalarEvolution::getNoopOrAnyExtend(const SCEV *V, const Type *Ty) { + const Type *SrcTy = V->getType(); + assert((SrcTy->isInteger() || isa(SrcTy)) && + (Ty->isInteger() || isa(Ty)) && + "Cannot noop or any extend with non-integer arguments!"); + assert(getTypeSizeInBits(SrcTy) <= getTypeSizeInBits(Ty) && + "getNoopOrAnyExtend cannot truncate!"); + if (getTypeSizeInBits(SrcTy) == getTypeSizeInBits(Ty)) + return V; // No conversion + return getAnyExtendExpr(V, Ty); +} + +/// getTruncateOrNoop - Return a SCEV corresponding to a conversion of the +/// input value to the specified type. The conversion must not be widening. +const SCEV * +ScalarEvolution::getTruncateOrNoop(const SCEV *V, const Type *Ty) { + const Type *SrcTy = V->getType(); + assert((SrcTy->isInteger() || isa(SrcTy)) && + (Ty->isInteger() || isa(Ty)) && + "Cannot truncate or noop with non-integer arguments!"); + assert(getTypeSizeInBits(SrcTy) >= getTypeSizeInBits(Ty) && + "getTruncateOrNoop cannot extend!"); + if (getTypeSizeInBits(SrcTy) == getTypeSizeInBits(Ty)) + return V; // No conversion + return getTruncateExpr(V, Ty); +} + +/// getUMaxFromMismatchedTypes - Promote the operands to the wider of +/// the types using zero-extension, and then perform a umax operation +/// with them. +const SCEV *ScalarEvolution::getUMaxFromMismatchedTypes(const SCEV *LHS, + const SCEV *RHS) { + const SCEV *PromotedLHS = LHS; + const SCEV *PromotedRHS = RHS; + + if (getTypeSizeInBits(LHS->getType()) > getTypeSizeInBits(RHS->getType())) + PromotedRHS = getZeroExtendExpr(RHS, LHS->getType()); + else + PromotedLHS = getNoopOrZeroExtend(LHS, RHS->getType()); + + return getUMaxExpr(PromotedLHS, PromotedRHS); +} + +/// getUMinFromMismatchedTypes - Promote the operands to the wider of +/// the types using zero-extension, and then perform a umin operation +/// with them. +const SCEV *ScalarEvolution::getUMinFromMismatchedTypes(const SCEV *LHS, + const SCEV *RHS) { + const SCEV *PromotedLHS = LHS; + const SCEV *PromotedRHS = RHS; + + if (getTypeSizeInBits(LHS->getType()) > getTypeSizeInBits(RHS->getType())) + PromotedRHS = getZeroExtendExpr(RHS, LHS->getType()); + else + PromotedLHS = getNoopOrZeroExtend(LHS, RHS->getType()); + + return getUMinExpr(PromotedLHS, PromotedRHS); +} + +/// PushDefUseChildren - Push users of the given Instruction +/// onto the given Worklist. +static void +PushDefUseChildren(Instruction *I, + SmallVectorImpl &Worklist) { + // Push the def-use children onto the Worklist stack. + for (Value::use_iterator UI = I->use_begin(), UE = I->use_end(); + UI != UE; ++UI) + Worklist.push_back(cast(UI)); +} + +/// ForgetSymbolicValue - This looks up computed SCEV values for all +/// instructions that depend on the given instruction and removes them from +/// the Scalars map if they reference SymName. This is used during PHI +/// resolution. +void +ScalarEvolution::ForgetSymbolicName(Instruction *I, const SCEV *SymName) { + SmallVector Worklist; + PushDefUseChildren(I, Worklist); + + SmallPtrSet Visited; + Visited.insert(I); + while (!Worklist.empty()) { + Instruction *I = Worklist.pop_back_val(); + if (!Visited.insert(I)) continue; + + std::map::iterator It = + Scalars.find(static_cast(I)); + if (It != Scalars.end()) { + // Short-circuit the def-use traversal if the symbolic name + // ceases to appear in expressions. + if (!It->second->hasOperand(SymName)) + continue; + + // SCEVUnknown for a PHI either means that it has an unrecognized + // structure, or it's a PHI that's in the progress of being computed + // by createNodeForPHI. In the former case, additional loop trip + // count information isn't going to change anything. In the later + // case, createNodeForPHI will perform the necessary updates on its + // own when it gets to that point. + if (!isa(I) || !isa(It->second)) { + ValuesAtScopes.erase(It->second); + Scalars.erase(It); + } + } + + PushDefUseChildren(I, Worklist); + } +} + +/// createNodeForPHI - PHI nodes have two cases. Either the PHI node exists in +/// a loop header, making it a potential recurrence, or it doesn't. +/// +const SCEV *ScalarEvolution::createNodeForPHI(PHINode *PN) { + if (PN->getNumIncomingValues() == 2) // The loops have been canonicalized. + if (const Loop *L = LI->getLoopFor(PN->getParent())) + if (L->getHeader() == PN->getParent()) { + // If it lives in the loop header, it has two incoming values, one + // from outside the loop, and one from inside. + unsigned IncomingEdge = L->contains(PN->getIncomingBlock(0)); + unsigned BackEdge = IncomingEdge^1; + + // While we are analyzing this PHI node, handle its value symbolically. + const SCEV *SymbolicName = getUnknown(PN); + assert(Scalars.find(PN) == Scalars.end() && + "PHI node already processed?"); + Scalars.insert(std::make_pair(SCEVCallbackVH(PN, this), SymbolicName)); + + // Using this symbolic name for the PHI, analyze the value coming around + // the back-edge. + Value *BEValueV = PN->getIncomingValue(BackEdge); + const SCEV *BEValue = getSCEV(BEValueV); + + // NOTE: If BEValue is loop invariant, we know that the PHI node just + // has a special value for the first iteration of the loop. + + // If the value coming around the backedge is an add with the symbolic + // value we just inserted, then we found a simple induction variable! + if (const SCEVAddExpr *Add = dyn_cast(BEValue)) { + // If there is a single occurrence of the symbolic value, replace it + // with a recurrence. + unsigned FoundIndex = Add->getNumOperands(); + for (unsigned i = 0, e = Add->getNumOperands(); i != e; ++i) + if (Add->getOperand(i) == SymbolicName) + if (FoundIndex == e) { + FoundIndex = i; + break; + } + + if (FoundIndex != Add->getNumOperands()) { + // Create an add with everything but the specified operand. + SmallVector Ops; + for (unsigned i = 0, e = Add->getNumOperands(); i != e; ++i) + if (i != FoundIndex) + Ops.push_back(Add->getOperand(i)); + const SCEV *Accum = getAddExpr(Ops); + + // This is not a valid addrec if the step amount is varying each + // loop iteration, but is not itself an addrec in this loop. + if (Accum->isLoopInvariant(L) || + (isa(Accum) && + cast(Accum)->getLoop() == L)) { + const SCEV *StartVal = + getSCEV(PN->getIncomingValue(IncomingEdge)); + const SCEVAddRecExpr *PHISCEV = + cast(getAddRecExpr(StartVal, Accum, L)); + + // If the increment doesn't overflow, then neither the addrec nor the + // post-increment will overflow. + if (const AddOperator *OBO = dyn_cast(BEValueV)) + if (OBO->getOperand(0) == PN && + getSCEV(OBO->getOperand(1)) == + PHISCEV->getStepRecurrence(*this)) { + const SCEVAddRecExpr *PostInc = PHISCEV->getPostIncExpr(*this); + if (OBO->hasNoUnsignedWrap()) { + const_cast(PHISCEV) + ->setHasNoUnsignedWrap(true); + const_cast(PostInc) + ->setHasNoUnsignedWrap(true); + } + if (OBO->hasNoSignedWrap()) { + const_cast(PHISCEV) + ->setHasNoSignedWrap(true); + const_cast(PostInc) + ->setHasNoSignedWrap(true); + } + } + + // Okay, for the entire analysis of this edge we assumed the PHI + // to be symbolic. We now need to go back and purge all of the + // entries for the scalars that use the symbolic expression. + ForgetSymbolicName(PN, SymbolicName); + Scalars[SCEVCallbackVH(PN, this)] = PHISCEV; + return PHISCEV; + } + } + } else if (const SCEVAddRecExpr *AddRec = + dyn_cast(BEValue)) { + // Otherwise, this could be a loop like this: + // i = 0; for (j = 1; ..; ++j) { .... i = j; } + // In this case, j = {1,+,1} and BEValue is j. + // Because the other in-value of i (0) fits the evolution of BEValue + // i really is an addrec evolution. + if (AddRec->getLoop() == L && AddRec->isAffine()) { + const SCEV *StartVal = getSCEV(PN->getIncomingValue(IncomingEdge)); + + // If StartVal = j.start - j.stride, we can use StartVal as the + // initial step of the addrec evolution. + if (StartVal == getMinusSCEV(AddRec->getOperand(0), + AddRec->getOperand(1))) { + const SCEV *PHISCEV = + getAddRecExpr(StartVal, AddRec->getOperand(1), L); + + // Okay, for the entire analysis of this edge we assumed the PHI + // to be symbolic. We now need to go back and purge all of the + // entries for the scalars that use the symbolic expression. + ForgetSymbolicName(PN, SymbolicName); + Scalars[SCEVCallbackVH(PN, this)] = PHISCEV; + return PHISCEV; + } + } + } + + return SymbolicName; + } + + // It's tempting to recognize PHIs with a unique incoming value, however + // this leads passes like indvars to break LCSSA form. Fortunately, such + // PHIs are rare, as instcombine zaps them. + + // If it's not a loop phi, we can't handle it yet. + return getUnknown(PN); +} + +/// createNodeForGEP - Expand GEP instructions into add and multiply +/// operations. This allows them to be analyzed by regular SCEV code. +/// +const SCEV *ScalarEvolution::createNodeForGEP(Operator *GEP) { + + const Type *IntPtrTy = getEffectiveSCEVType(GEP->getType()); + Value *Base = GEP->getOperand(0); + // Don't attempt to analyze GEPs over unsized objects. + if (!cast(Base->getType())->getElementType()->isSized()) + return getUnknown(GEP); + const SCEV *TotalOffset = getIntegerSCEV(0, IntPtrTy); + gep_type_iterator GTI = gep_type_begin(GEP); + for (GetElementPtrInst::op_iterator I = next(GEP->op_begin()), + E = GEP->op_end(); + I != E; ++I) { + Value *Index = *I; + // Compute the (potentially symbolic) offset in bytes for this index. + if (const StructType *STy = dyn_cast(*GTI++)) { + // For a struct, add the member offset. + unsigned FieldNo = cast(Index)->getZExtValue(); + TotalOffset = getAddExpr(TotalOffset, + getFieldOffsetExpr(STy, FieldNo)); + } else { + // For an array, add the element offset, explicitly scaled. + const SCEV *LocalOffset = getSCEV(Index); + if (!isa(LocalOffset->getType())) + // Getelementptr indicies are signed. + LocalOffset = getTruncateOrSignExtend(LocalOffset, IntPtrTy); + LocalOffset = getMulExpr(LocalOffset, getAllocSizeExpr(*GTI)); + TotalOffset = getAddExpr(TotalOffset, LocalOffset); + } + } + return getAddExpr(getSCEV(Base), TotalOffset); +} + +/// GetMinTrailingZeros - Determine the minimum number of zero bits that S is +/// guaranteed to end in (at every loop iteration). It is, at the same time, +/// the minimum number of times S is divisible by 2. For example, given {4,+,8} +/// it returns 2. If S is guaranteed to be 0, it returns the bitwidth of S. +uint32_t +ScalarEvolution::GetMinTrailingZeros(const SCEV *S) { + if (const SCEVConstant *C = dyn_cast(S)) + return C->getValue()->getValue().countTrailingZeros(); + + if (const SCEVTruncateExpr *T = dyn_cast(S)) + return std::min(GetMinTrailingZeros(T->getOperand()), + (uint32_t)getTypeSizeInBits(T->getType())); + + if (const SCEVZeroExtendExpr *E = dyn_cast(S)) { + uint32_t OpRes = GetMinTrailingZeros(E->getOperand()); + return OpRes == getTypeSizeInBits(E->getOperand()->getType()) ? + getTypeSizeInBits(E->getType()) : OpRes; + } + + if (const SCEVSignExtendExpr *E = dyn_cast(S)) { + uint32_t OpRes = GetMinTrailingZeros(E->getOperand()); + return OpRes == getTypeSizeInBits(E->getOperand()->getType()) ? + getTypeSizeInBits(E->getType()) : OpRes; + } + + if (const SCEVAddExpr *A = dyn_cast(S)) { + // The result is the min of all operands results. + uint32_t MinOpRes = GetMinTrailingZeros(A->getOperand(0)); + for (unsigned i = 1, e = A->getNumOperands(); MinOpRes && i != e; ++i) + MinOpRes = std::min(MinOpRes, GetMinTrailingZeros(A->getOperand(i))); + return MinOpRes; + } + + if (const SCEVMulExpr *M = dyn_cast(S)) { + // The result is the sum of all operands results. + uint32_t SumOpRes = GetMinTrailingZeros(M->getOperand(0)); + uint32_t BitWidth = getTypeSizeInBits(M->getType()); + for (unsigned i = 1, e = M->getNumOperands(); + SumOpRes != BitWidth && i != e; ++i) + SumOpRes = std::min(SumOpRes + GetMinTrailingZeros(M->getOperand(i)), + BitWidth); + return SumOpRes; + } + + if (const SCEVAddRecExpr *A = dyn_cast(S)) { + // The result is the min of all operands results. + uint32_t MinOpRes = GetMinTrailingZeros(A->getOperand(0)); + for (unsigned i = 1, e = A->getNumOperands(); MinOpRes && i != e; ++i) + MinOpRes = std::min(MinOpRes, GetMinTrailingZeros(A->getOperand(i))); + return MinOpRes; + } + + if (const SCEVSMaxExpr *M = dyn_cast(S)) { + // The result is the min of all operands results. + uint32_t MinOpRes = GetMinTrailingZeros(M->getOperand(0)); + for (unsigned i = 1, e = M->getNumOperands(); MinOpRes && i != e; ++i) + MinOpRes = std::min(MinOpRes, GetMinTrailingZeros(M->getOperand(i))); + return MinOpRes; + } + + if (const SCEVUMaxExpr *M = dyn_cast(S)) { + // The result is the min of all operands results. + uint32_t MinOpRes = GetMinTrailingZeros(M->getOperand(0)); + for (unsigned i = 1, e = M->getNumOperands(); MinOpRes && i != e; ++i) + MinOpRes = std::min(MinOpRes, GetMinTrailingZeros(M->getOperand(i))); + return MinOpRes; + } + + if (const SCEVUnknown *U = dyn_cast(S)) { + // For a SCEVUnknown, ask ValueTracking. + unsigned BitWidth = getTypeSizeInBits(U->getType()); + APInt Mask = APInt::getAllOnesValue(BitWidth); + APInt Zeros(BitWidth, 0), Ones(BitWidth, 0); + ComputeMaskedBits(U->getValue(), Mask, Zeros, Ones); + return Zeros.countTrailingOnes(); + } + + // SCEVUDivExpr + return 0; +} + +/// getUnsignedRange - Determine the unsigned range for a particular SCEV. +/// +ConstantRange +ScalarEvolution::getUnsignedRange(const SCEV *S) { + + if (const SCEVConstant *C = dyn_cast(S)) + return ConstantRange(C->getValue()->getValue()); + + if (const SCEVAddExpr *Add = dyn_cast(S)) { + ConstantRange X = getUnsignedRange(Add->getOperand(0)); + for (unsigned i = 1, e = Add->getNumOperands(); i != e; ++i) + X = X.add(getUnsignedRange(Add->getOperand(i))); + return X; + } + + if (const SCEVMulExpr *Mul = dyn_cast(S)) { + ConstantRange X = getUnsignedRange(Mul->getOperand(0)); + for (unsigned i = 1, e = Mul->getNumOperands(); i != e; ++i) + X = X.multiply(getUnsignedRange(Mul->getOperand(i))); + return X; + } + + if (const SCEVSMaxExpr *SMax = dyn_cast(S)) { + ConstantRange X = getUnsignedRange(SMax->getOperand(0)); + for (unsigned i = 1, e = SMax->getNumOperands(); i != e; ++i) + X = X.smax(getUnsignedRange(SMax->getOperand(i))); + return X; + } + + if (const SCEVUMaxExpr *UMax = dyn_cast(S)) { + ConstantRange X = getUnsignedRange(UMax->getOperand(0)); + for (unsigned i = 1, e = UMax->getNumOperands(); i != e; ++i) + X = X.umax(getUnsignedRange(UMax->getOperand(i))); + return X; + } + + if (const SCEVUDivExpr *UDiv = dyn_cast(S)) { + ConstantRange X = getUnsignedRange(UDiv->getLHS()); + ConstantRange Y = getUnsignedRange(UDiv->getRHS()); + return X.udiv(Y); + } + + if (const SCEVZeroExtendExpr *ZExt = dyn_cast(S)) { + ConstantRange X = getUnsignedRange(ZExt->getOperand()); + return X.zeroExtend(cast(ZExt->getType())->getBitWidth()); + } + + if (const SCEVSignExtendExpr *SExt = dyn_cast(S)) { + ConstantRange X = getUnsignedRange(SExt->getOperand()); + return X.signExtend(cast(SExt->getType())->getBitWidth()); + } + + if (const SCEVTruncateExpr *Trunc = dyn_cast(S)) { + ConstantRange X = getUnsignedRange(Trunc->getOperand()); + return X.truncate(cast(Trunc->getType())->getBitWidth()); + } + + ConstantRange FullSet(getTypeSizeInBits(S->getType()), true); + + if (const SCEVAddRecExpr *AddRec = dyn_cast(S)) { + const SCEV *T = getBackedgeTakenCount(AddRec->getLoop()); + const SCEVConstant *Trip = dyn_cast(T); + if (!Trip) return FullSet; + + // TODO: non-affine addrec + if (AddRec->isAffine()) { + const Type *Ty = AddRec->getType(); + const SCEV *MaxBECount = getMaxBackedgeTakenCount(AddRec->getLoop()); + if (getTypeSizeInBits(MaxBECount->getType()) <= getTypeSizeInBits(Ty)) { + MaxBECount = getNoopOrZeroExtend(MaxBECount, Ty); + + const SCEV *Start = AddRec->getStart(); + const SCEV *Step = AddRec->getStepRecurrence(*this); + const SCEV *End = AddRec->evaluateAtIteration(MaxBECount, *this); + + // Check for overflow. + // TODO: This is very conservative. + if (!(Step->isOne() && + isKnownPredicate(ICmpInst::ICMP_ULT, Start, End)) && + !(Step->isAllOnesValue() && + isKnownPredicate(ICmpInst::ICMP_UGT, Start, End))) + return FullSet; + + ConstantRange StartRange = getUnsignedRange(Start); + ConstantRange EndRange = getUnsignedRange(End); + APInt Min = APIntOps::umin(StartRange.getUnsignedMin(), + EndRange.getUnsignedMin()); + APInt Max = APIntOps::umax(StartRange.getUnsignedMax(), + EndRange.getUnsignedMax()); + if (Min.isMinValue() && Max.isMaxValue()) + return FullSet; + return ConstantRange(Min, Max+1); + } + } + } + + if (const SCEVUnknown *U = dyn_cast(S)) { + // For a SCEVUnknown, ask ValueTracking. + unsigned BitWidth = getTypeSizeInBits(U->getType()); + APInt Mask = APInt::getAllOnesValue(BitWidth); + APInt Zeros(BitWidth, 0), Ones(BitWidth, 0); + ComputeMaskedBits(U->getValue(), Mask, Zeros, Ones, TD); + if (Ones == ~Zeros + 1) + return FullSet; + return ConstantRange(Ones, ~Zeros + 1); + } + + return FullSet; +} + +/// getSignedRange - Determine the signed range for a particular SCEV. +/// +ConstantRange +ScalarEvolution::getSignedRange(const SCEV *S) { + + if (const SCEVConstant *C = dyn_cast(S)) + return ConstantRange(C->getValue()->getValue()); + + if (const SCEVAddExpr *Add = dyn_cast(S)) { + ConstantRange X = getSignedRange(Add->getOperand(0)); + for (unsigned i = 1, e = Add->getNumOperands(); i != e; ++i) + X = X.add(getSignedRange(Add->getOperand(i))); + return X; + } + + if (const SCEVMulExpr *Mul = dyn_cast(S)) { + ConstantRange X = getSignedRange(Mul->getOperand(0)); + for (unsigned i = 1, e = Mul->getNumOperands(); i != e; ++i) + X = X.multiply(getSignedRange(Mul->getOperand(i))); + return X; + } + + if (const SCEVSMaxExpr *SMax = dyn_cast(S)) { + ConstantRange X = getSignedRange(SMax->getOperand(0)); + for (unsigned i = 1, e = SMax->getNumOperands(); i != e; ++i) + X = X.smax(getSignedRange(SMax->getOperand(i))); + return X; + } + + if (const SCEVUMaxExpr *UMax = dyn_cast(S)) { + ConstantRange X = getSignedRange(UMax->getOperand(0)); + for (unsigned i = 1, e = UMax->getNumOperands(); i != e; ++i) + X = X.umax(getSignedRange(UMax->getOperand(i))); + return X; + } + + if (const SCEVUDivExpr *UDiv = dyn_cast(S)) { + ConstantRange X = getSignedRange(UDiv->getLHS()); + ConstantRange Y = getSignedRange(UDiv->getRHS()); + return X.udiv(Y); + } + + if (const SCEVZeroExtendExpr *ZExt = dyn_cast(S)) { + ConstantRange X = getSignedRange(ZExt->getOperand()); + return X.zeroExtend(cast(ZExt->getType())->getBitWidth()); + } + + if (const SCEVSignExtendExpr *SExt = dyn_cast(S)) { + ConstantRange X = getSignedRange(SExt->getOperand()); + return X.signExtend(cast(SExt->getType())->getBitWidth()); + } + + if (const SCEVTruncateExpr *Trunc = dyn_cast(S)) { + ConstantRange X = getSignedRange(Trunc->getOperand()); + return X.truncate(cast(Trunc->getType())->getBitWidth()); + } + + ConstantRange FullSet(getTypeSizeInBits(S->getType()), true); + + if (const SCEVAddRecExpr *AddRec = dyn_cast(S)) { + const SCEV *T = getBackedgeTakenCount(AddRec->getLoop()); + const SCEVConstant *Trip = dyn_cast(T); + if (!Trip) return FullSet; + + // TODO: non-affine addrec + if (AddRec->isAffine()) { + const Type *Ty = AddRec->getType(); + const SCEV *MaxBECount = getMaxBackedgeTakenCount(AddRec->getLoop()); + if (getTypeSizeInBits(MaxBECount->getType()) <= getTypeSizeInBits(Ty)) { + MaxBECount = getNoopOrZeroExtend(MaxBECount, Ty); + + const SCEV *Start = AddRec->getStart(); + const SCEV *Step = AddRec->getStepRecurrence(*this); + const SCEV *End = AddRec->evaluateAtIteration(MaxBECount, *this); + + // Check for overflow. + // TODO: This is very conservative. + if (!(Step->isOne() && + isKnownPredicate(ICmpInst::ICMP_SLT, Start, End)) && + !(Step->isAllOnesValue() && + isKnownPredicate(ICmpInst::ICMP_SGT, Start, End))) + return FullSet; + + ConstantRange StartRange = getSignedRange(Start); + ConstantRange EndRange = getSignedRange(End); + APInt Min = APIntOps::smin(StartRange.getSignedMin(), + EndRange.getSignedMin()); + APInt Max = APIntOps::smax(StartRange.getSignedMax(), + EndRange.getSignedMax()); + if (Min.isMinSignedValue() && Max.isMaxSignedValue()) + return FullSet; + return ConstantRange(Min, Max+1); + } + } + } + + if (const SCEVUnknown *U = dyn_cast(S)) { + // For a SCEVUnknown, ask ValueTracking. + unsigned BitWidth = getTypeSizeInBits(U->getType()); + unsigned NS = ComputeNumSignBits(U->getValue(), TD); + if (NS == 1) + return FullSet; + return + ConstantRange(APInt::getSignedMinValue(BitWidth).ashr(NS - 1), + APInt::getSignedMaxValue(BitWidth).ashr(NS - 1)+1); + } + + return FullSet; +} + +/// createSCEV - We know that there is no SCEV for the specified value. +/// Analyze the expression. +/// +const SCEV *ScalarEvolution::createSCEV(Value *V) { + if (!isSCEVable(V->getType())) + return getUnknown(V); + + unsigned Opcode = Instruction::UserOp1; + if (Instruction *I = dyn_cast(V)) + Opcode = I->getOpcode(); + else if (ConstantExpr *CE = dyn_cast(V)) + Opcode = CE->getOpcode(); + else if (ConstantInt *CI = dyn_cast(V)) + return getConstant(CI); + else if (isa(V)) + return getIntegerSCEV(0, V->getType()); + else if (isa(V)) + return getIntegerSCEV(0, V->getType()); + else if (GlobalAlias *GA = dyn_cast(V)) + return GA->mayBeOverridden() ? getUnknown(V) : getSCEV(GA->getAliasee()); + else + return getUnknown(V); + + Operator *U = cast(V); + switch (Opcode) { + case Instruction::Add: + // Don't transfer the NSW and NUW bits from the Add instruction to the + // Add expression, because the Instruction may be guarded by control + // flow and the no-overflow bits may not be valid for the expression in + // any context. + return getAddExpr(getSCEV(U->getOperand(0)), + getSCEV(U->getOperand(1))); + case Instruction::Mul: + // Don't transfer the NSW and NUW bits from the Mul instruction to the + // Mul expression, as with Add. + return getMulExpr(getSCEV(U->getOperand(0)), + getSCEV(U->getOperand(1))); + case Instruction::UDiv: + return getUDivExpr(getSCEV(U->getOperand(0)), + getSCEV(U->getOperand(1))); + case Instruction::Sub: + return getMinusSCEV(getSCEV(U->getOperand(0)), + getSCEV(U->getOperand(1))); + case Instruction::And: + // For an expression like x&255 that merely masks off the high bits, + // use zext(trunc(x)) as the SCEV expression. + if (ConstantInt *CI = dyn_cast(U->getOperand(1))) { + if (CI->isNullValue()) + return getSCEV(U->getOperand(1)); + if (CI->isAllOnesValue()) + return getSCEV(U->getOperand(0)); + const APInt &A = CI->getValue(); + + // Instcombine's ShrinkDemandedConstant may strip bits out of + // constants, obscuring what would otherwise be a low-bits mask. + // Use ComputeMaskedBits to compute what ShrinkDemandedConstant + // knew about to reconstruct a low-bits mask value. + unsigned LZ = A.countLeadingZeros(); + unsigned BitWidth = A.getBitWidth(); + APInt AllOnes = APInt::getAllOnesValue(BitWidth); + APInt KnownZero(BitWidth, 0), KnownOne(BitWidth, 0); + ComputeMaskedBits(U->getOperand(0), AllOnes, KnownZero, KnownOne, TD); + + APInt EffectiveMask = APInt::getLowBitsSet(BitWidth, BitWidth - LZ); + + if (LZ != 0 && !((~A & ~KnownZero) & EffectiveMask)) + return + getZeroExtendExpr(getTruncateExpr(getSCEV(U->getOperand(0)), + IntegerType::get(getContext(), BitWidth - LZ)), + U->getType()); + } + break; + + case Instruction::Or: + // If the RHS of the Or is a constant, we may have something like: + // X*4+1 which got turned into X*4|1. Handle this as an Add so loop + // optimizations will transparently handle this case. + // + // In order for this transformation to be safe, the LHS must be of the + // form X*(2^n) and the Or constant must be less than 2^n. + if (ConstantInt *CI = dyn_cast(U->getOperand(1))) { + const SCEV *LHS = getSCEV(U->getOperand(0)); + const APInt &CIVal = CI->getValue(); + if (GetMinTrailingZeros(LHS) >= + (CIVal.getBitWidth() - CIVal.countLeadingZeros())) { + // Build a plain add SCEV. + const SCEV *S = getAddExpr(LHS, getSCEV(CI)); + // If the LHS of the add was an addrec and it has no-wrap flags, + // transfer the no-wrap flags, since an or won't introduce a wrap. + if (const SCEVAddRecExpr *NewAR = dyn_cast(S)) { + const SCEVAddRecExpr *OldAR = cast(LHS); + if (OldAR->hasNoUnsignedWrap()) + const_cast(NewAR)->setHasNoUnsignedWrap(true); + if (OldAR->hasNoSignedWrap()) + const_cast(NewAR)->setHasNoSignedWrap(true); + } + return S; + } + } + break; + case Instruction::Xor: + if (ConstantInt *CI = dyn_cast(U->getOperand(1))) { + // If the RHS of the xor is a signbit, then this is just an add. + // Instcombine turns add of signbit into xor as a strength reduction step. + if (CI->getValue().isSignBit()) + return getAddExpr(getSCEV(U->getOperand(0)), + getSCEV(U->getOperand(1))); + + // If the RHS of xor is -1, then this is a not operation. + if (CI->isAllOnesValue()) + return getNotSCEV(getSCEV(U->getOperand(0))); + + // Model xor(and(x, C), C) as and(~x, C), if C is a low-bits mask. + // This is a variant of the check for xor with -1, and it handles + // the case where instcombine has trimmed non-demanded bits out + // of an xor with -1. + if (BinaryOperator *BO = dyn_cast(U->getOperand(0))) + if (ConstantInt *LCI = dyn_cast(BO->getOperand(1))) + if (BO->getOpcode() == Instruction::And && + LCI->getValue() == CI->getValue()) + if (const SCEVZeroExtendExpr *Z = + dyn_cast(getSCEV(U->getOperand(0)))) { + const Type *UTy = U->getType(); + const SCEV *Z0 = Z->getOperand(); + const Type *Z0Ty = Z0->getType(); + unsigned Z0TySize = getTypeSizeInBits(Z0Ty); + + // If C is a low-bits mask, the zero extend is zerving to + // mask off the high bits. Complement the operand and + // re-apply the zext. + if (APIntOps::isMask(Z0TySize, CI->getValue())) + return getZeroExtendExpr(getNotSCEV(Z0), UTy); + + // If C is a single bit, it may be in the sign-bit position + // before the zero-extend. In this case, represent the xor + // using an add, which is equivalent, and re-apply the zext. + APInt Trunc = APInt(CI->getValue()).trunc(Z0TySize); + if (APInt(Trunc).zext(getTypeSizeInBits(UTy)) == CI->getValue() && + Trunc.isSignBit()) + return getZeroExtendExpr(getAddExpr(Z0, getConstant(Trunc)), + UTy); + } + } + break; + + case Instruction::Shl: + // Turn shift left of a constant amount into a multiply. + if (ConstantInt *SA = dyn_cast(U->getOperand(1))) { + uint32_t BitWidth = cast(V->getType())->getBitWidth(); + Constant *X = ConstantInt::get(getContext(), + APInt(BitWidth, 1).shl(SA->getLimitedValue(BitWidth))); + return getMulExpr(getSCEV(U->getOperand(0)), getSCEV(X)); + } + break; + + case Instruction::LShr: + // Turn logical shift right of a constant into a unsigned divide. + if (ConstantInt *SA = dyn_cast(U->getOperand(1))) { + uint32_t BitWidth = cast(V->getType())->getBitWidth(); + Constant *X = ConstantInt::get(getContext(), + APInt(BitWidth, 1).shl(SA->getLimitedValue(BitWidth))); + return getUDivExpr(getSCEV(U->getOperand(0)), getSCEV(X)); + } + break; + + case Instruction::AShr: + // For a two-shift sext-inreg, use sext(trunc(x)) as the SCEV expression. + if (ConstantInt *CI = dyn_cast(U->getOperand(1))) + if (Instruction *L = dyn_cast(U->getOperand(0))) + if (L->getOpcode() == Instruction::Shl && + L->getOperand(1) == U->getOperand(1)) { + unsigned BitWidth = getTypeSizeInBits(U->getType()); + uint64_t Amt = BitWidth - CI->getZExtValue(); + if (Amt == BitWidth) + return getSCEV(L->getOperand(0)); // shift by zero --> noop + if (Amt > BitWidth) + return getIntegerSCEV(0, U->getType()); // value is undefined + return + getSignExtendExpr(getTruncateExpr(getSCEV(L->getOperand(0)), + IntegerType::get(getContext(), Amt)), + U->getType()); + } + break; + + case Instruction::Trunc: + return getTruncateExpr(getSCEV(U->getOperand(0)), U->getType()); + + case Instruction::ZExt: + return getZeroExtendExpr(getSCEV(U->getOperand(0)), U->getType()); + + case Instruction::SExt: + return getSignExtendExpr(getSCEV(U->getOperand(0)), U->getType()); + + case Instruction::BitCast: + // BitCasts are no-op casts so we just eliminate the cast. + if (isSCEVable(U->getType()) && isSCEVable(U->getOperand(0)->getType())) + return getSCEV(U->getOperand(0)); + break; + + // It's tempting to handle inttoptr and ptrtoint, however this can + // lead to pointer expressions which cannot be expanded to GEPs + // (because they may overflow). For now, the only pointer-typed + // expressions we handle are GEPs and address literals. + + case Instruction::GetElementPtr: + return createNodeForGEP(U); + + case Instruction::PHI: + return createNodeForPHI(cast(U)); + + case Instruction::Select: + // This could be a smax or umax that was lowered earlier. + // Try to recover it. + if (ICmpInst *ICI = dyn_cast(U->getOperand(0))) { + Value *LHS = ICI->getOperand(0); + Value *RHS = ICI->getOperand(1); + switch (ICI->getPredicate()) { + case ICmpInst::ICMP_SLT: + case ICmpInst::ICMP_SLE: + std::swap(LHS, RHS); + // fall through + case ICmpInst::ICMP_SGT: + case ICmpInst::ICMP_SGE: + if (LHS == U->getOperand(1) && RHS == U->getOperand(2)) + return getSMaxExpr(getSCEV(LHS), getSCEV(RHS)); + else if (LHS == U->getOperand(2) && RHS == U->getOperand(1)) + return getSMinExpr(getSCEV(LHS), getSCEV(RHS)); + break; + case ICmpInst::ICMP_ULT: + case ICmpInst::ICMP_ULE: + std::swap(LHS, RHS); + // fall through + case ICmpInst::ICMP_UGT: + case ICmpInst::ICMP_UGE: + if (LHS == U->getOperand(1) && RHS == U->getOperand(2)) + return getUMaxExpr(getSCEV(LHS), getSCEV(RHS)); + else if (LHS == U->getOperand(2) && RHS == U->getOperand(1)) + return getUMinExpr(getSCEV(LHS), getSCEV(RHS)); + break; + case ICmpInst::ICMP_NE: + // n != 0 ? n : 1 -> umax(n, 1) + if (LHS == U->getOperand(1) && + isa(U->getOperand(2)) && + cast(U->getOperand(2))->isOne() && + isa(RHS) && + cast(RHS)->isZero()) + return getUMaxExpr(getSCEV(LHS), getSCEV(U->getOperand(2))); + break; + case ICmpInst::ICMP_EQ: + // n == 0 ? 1 : n -> umax(n, 1) + if (LHS == U->getOperand(2) && + isa(U->getOperand(1)) && + cast(U->getOperand(1))->isOne() && + isa(RHS) && + cast(RHS)->isZero()) + return getUMaxExpr(getSCEV(LHS), getSCEV(U->getOperand(1))); + break; + default: + break; + } + } + + default: // We cannot analyze this expression. + break; + } + + return getUnknown(V); +} + + + +//===----------------------------------------------------------------------===// +// Iteration Count Computation Code +// + +/// getBackedgeTakenCount - If the specified loop has a predictable +/// backedge-taken count, return it, otherwise return a SCEVCouldNotCompute +/// object. The backedge-taken count is the number of times the loop header +/// will be branched to from within the loop. This is one less than the +/// trip count of the loop, since it doesn't count the first iteration, +/// when the header is branched to from outside the loop. +/// +/// Note that it is not valid to call this method on a loop without a +/// loop-invariant backedge-taken count (see +/// hasLoopInvariantBackedgeTakenCount). +/// +const SCEV *ScalarEvolution::getBackedgeTakenCount(const Loop *L) { + return getBackedgeTakenInfo(L).Exact; +} + +/// getMaxBackedgeTakenCount - Similar to getBackedgeTakenCount, except +/// return the least SCEV value that is known never to be less than the +/// actual backedge taken count. +const SCEV *ScalarEvolution::getMaxBackedgeTakenCount(const Loop *L) { + return getBackedgeTakenInfo(L).Max; +} + +/// PushLoopPHIs - Push PHI nodes in the header of the given loop +/// onto the given Worklist. +static void +PushLoopPHIs(const Loop *L, SmallVectorImpl &Worklist) { + BasicBlock *Header = L->getHeader(); + + // Push all Loop-header PHIs onto the Worklist stack. + for (BasicBlock::iterator I = Header->begin(); + PHINode *PN = dyn_cast(I); ++I) + Worklist.push_back(PN); +} + +const ScalarEvolution::BackedgeTakenInfo & +ScalarEvolution::getBackedgeTakenInfo(const Loop *L) { + // Initially insert a CouldNotCompute for this loop. If the insertion + // succeeds, procede to actually compute a backedge-taken count and + // update the value. The temporary CouldNotCompute value tells SCEV + // code elsewhere that it shouldn't attempt to request a new + // backedge-taken count, which could result in infinite recursion. + std::pair::iterator, bool> Pair = + BackedgeTakenCounts.insert(std::make_pair(L, getCouldNotCompute())); + if (Pair.second) { + BackedgeTakenInfo ItCount = ComputeBackedgeTakenCount(L); + if (ItCount.Exact != getCouldNotCompute()) { + assert(ItCount.Exact->isLoopInvariant(L) && + ItCount.Max->isLoopInvariant(L) && + "Computed trip count isn't loop invariant for loop!"); + ++NumTripCountsComputed; + + // Update the value in the map. + Pair.first->second = ItCount; + } else { + if (ItCount.Max != getCouldNotCompute()) + // Update the value in the map. + Pair.first->second = ItCount; + if (isa(L->getHeader()->begin())) + // Only count loops that have phi nodes as not being computable. + ++NumTripCountsNotComputed; + } + + // Now that we know more about the trip count for this loop, forget any + // existing SCEV values for PHI nodes in this loop since they are only + // conservative estimates made without the benefit of trip count + // information. This is similar to the code in forgetLoop, except that + // it handles SCEVUnknown PHI nodes specially. + if (ItCount.hasAnyInfo()) { + SmallVector Worklist; + PushLoopPHIs(L, Worklist); + + SmallPtrSet Visited; + while (!Worklist.empty()) { + Instruction *I = Worklist.pop_back_val(); + if (!Visited.insert(I)) continue; + + std::map::iterator It = + Scalars.find(static_cast(I)); + if (It != Scalars.end()) { + // SCEVUnknown for a PHI either means that it has an unrecognized + // structure, or it's a PHI that's in the progress of being computed + // by createNodeForPHI. In the former case, additional loop trip + // count information isn't going to change anything. In the later + // case, createNodeForPHI will perform the necessary updates on its + // own when it gets to that point. + if (!isa(I) || !isa(It->second)) { + ValuesAtScopes.erase(It->second); + Scalars.erase(It); + } + if (PHINode *PN = dyn_cast(I)) + ConstantEvolutionLoopExitValue.erase(PN); + } + + PushDefUseChildren(I, Worklist); + } + } + } + return Pair.first->second; +} + +/// forgetLoop - This method should be called by the client when it has +/// changed a loop in a way that may effect ScalarEvolution's ability to +/// compute a trip count, or if the loop is deleted. +void ScalarEvolution::forgetLoop(const Loop *L) { + // Drop any stored trip count value. + BackedgeTakenCounts.erase(L); + + // Drop information about expressions based on loop-header PHIs. + SmallVector Worklist; + PushLoopPHIs(L, Worklist); + + SmallPtrSet Visited; + while (!Worklist.empty()) { + Instruction *I = Worklist.pop_back_val(); + if (!Visited.insert(I)) continue; + + std::map::iterator It = + Scalars.find(static_cast(I)); + if (It != Scalars.end()) { + ValuesAtScopes.erase(It->second); + Scalars.erase(It); + if (PHINode *PN = dyn_cast(I)) + ConstantEvolutionLoopExitValue.erase(PN); + } + + PushDefUseChildren(I, Worklist); + } +} + +/// ComputeBackedgeTakenCount - Compute the number of times the backedge +/// of the specified loop will execute. +ScalarEvolution::BackedgeTakenInfo +ScalarEvolution::ComputeBackedgeTakenCount(const Loop *L) { + SmallVector ExitingBlocks; + L->getExitingBlocks(ExitingBlocks); + + // Examine all exits and pick the most conservative values. + const SCEV *BECount = getCouldNotCompute(); + const SCEV *MaxBECount = getCouldNotCompute(); + bool CouldNotComputeBECount = false; + for (unsigned i = 0, e = ExitingBlocks.size(); i != e; ++i) { + BackedgeTakenInfo NewBTI = + ComputeBackedgeTakenCountFromExit(L, ExitingBlocks[i]); + + if (NewBTI.Exact == getCouldNotCompute()) { + // We couldn't compute an exact value for this exit, so + // we won't be able to compute an exact value for the loop. + CouldNotComputeBECount = true; + BECount = getCouldNotCompute(); + } else if (!CouldNotComputeBECount) { + if (BECount == getCouldNotCompute()) + BECount = NewBTI.Exact; + else + BECount = getUMinFromMismatchedTypes(BECount, NewBTI.Exact); + } + if (MaxBECount == getCouldNotCompute()) + MaxBECount = NewBTI.Max; + else if (NewBTI.Max != getCouldNotCompute()) + MaxBECount = getUMinFromMismatchedTypes(MaxBECount, NewBTI.Max); + } + + return BackedgeTakenInfo(BECount, MaxBECount); +} + +/// ComputeBackedgeTakenCountFromExit - Compute the number of times the backedge +/// of the specified loop will execute if it exits via the specified block. +ScalarEvolution::BackedgeTakenInfo +ScalarEvolution::ComputeBackedgeTakenCountFromExit(const Loop *L, + BasicBlock *ExitingBlock) { + + // Okay, we've chosen an exiting block. See what condition causes us to + // exit at this block. + // + // FIXME: we should be able to handle switch instructions (with a single exit) + BranchInst *ExitBr = dyn_cast(ExitingBlock->getTerminator()); + if (ExitBr == 0) return getCouldNotCompute(); + assert(ExitBr->isConditional() && "If unconditional, it can't be in loop!"); + + // At this point, we know we have a conditional branch that determines whether + // the loop is exited. However, we don't know if the branch is executed each + // time through the loop. If not, then the execution count of the branch will + // not be equal to the trip count of the loop. + // + // Currently we check for this by checking to see if the Exit branch goes to + // the loop header. If so, we know it will always execute the same number of + // times as the loop. We also handle the case where the exit block *is* the + // loop header. This is common for un-rotated loops. + // + // If both of those tests fail, walk up the unique predecessor chain to the + // header, stopping if there is an edge that doesn't exit the loop. If the + // header is reached, the execution count of the branch will be equal to the + // trip count of the loop. + // + // More extensive analysis could be done to handle more cases here. + // + if (ExitBr->getSuccessor(0) != L->getHeader() && + ExitBr->getSuccessor(1) != L->getHeader() && + ExitBr->getParent() != L->getHeader()) { + // The simple checks failed, try climbing the unique predecessor chain + // up to the header. + bool Ok = false; + for (BasicBlock *BB = ExitBr->getParent(); BB; ) { + BasicBlock *Pred = BB->getUniquePredecessor(); + if (!Pred) + return getCouldNotCompute(); + TerminatorInst *PredTerm = Pred->getTerminator(); + for (unsigned i = 0, e = PredTerm->getNumSuccessors(); i != e; ++i) { + BasicBlock *PredSucc = PredTerm->getSuccessor(i); + if (PredSucc == BB) + continue; + // If the predecessor has a successor that isn't BB and isn't + // outside the loop, assume the worst. + if (L->contains(PredSucc)) + return getCouldNotCompute(); + } + if (Pred == L->getHeader()) { + Ok = true; + break; + } + BB = Pred; + } + if (!Ok) + return getCouldNotCompute(); + } + + // Procede to the next level to examine the exit condition expression. + return ComputeBackedgeTakenCountFromExitCond(L, ExitBr->getCondition(), + ExitBr->getSuccessor(0), + ExitBr->getSuccessor(1)); +} + +/// ComputeBackedgeTakenCountFromExitCond - Compute the number of times the +/// backedge of the specified loop will execute if its exit condition +/// were a conditional branch of ExitCond, TBB, and FBB. +ScalarEvolution::BackedgeTakenInfo +ScalarEvolution::ComputeBackedgeTakenCountFromExitCond(const Loop *L, + Value *ExitCond, + BasicBlock *TBB, + BasicBlock *FBB) { + // Check if the controlling expression for this loop is an And or Or. + if (BinaryOperator *BO = dyn_cast(ExitCond)) { + if (BO->getOpcode() == Instruction::And) { + // Recurse on the operands of the and. + BackedgeTakenInfo BTI0 = + ComputeBackedgeTakenCountFromExitCond(L, BO->getOperand(0), TBB, FBB); + BackedgeTakenInfo BTI1 = + ComputeBackedgeTakenCountFromExitCond(L, BO->getOperand(1), TBB, FBB); + const SCEV *BECount = getCouldNotCompute(); + const SCEV *MaxBECount = getCouldNotCompute(); + if (L->contains(TBB)) { + // Both conditions must be true for the loop to continue executing. + // Choose the less conservative count. + if (BTI0.Exact == getCouldNotCompute() || + BTI1.Exact == getCouldNotCompute()) + BECount = getCouldNotCompute(); + else + BECount = getUMinFromMismatchedTypes(BTI0.Exact, BTI1.Exact); + if (BTI0.Max == getCouldNotCompute()) + MaxBECount = BTI1.Max; + else if (BTI1.Max == getCouldNotCompute()) + MaxBECount = BTI0.Max; + else + MaxBECount = getUMinFromMismatchedTypes(BTI0.Max, BTI1.Max); + } else { + // Both conditions must be true for the loop to exit. + assert(L->contains(FBB) && "Loop block has no successor in loop!"); + if (BTI0.Exact != getCouldNotCompute() && + BTI1.Exact != getCouldNotCompute()) + BECount = getUMaxFromMismatchedTypes(BTI0.Exact, BTI1.Exact); + if (BTI0.Max != getCouldNotCompute() && + BTI1.Max != getCouldNotCompute()) + MaxBECount = getUMaxFromMismatchedTypes(BTI0.Max, BTI1.Max); + } + + return BackedgeTakenInfo(BECount, MaxBECount); + } + if (BO->getOpcode() == Instruction::Or) { + // Recurse on the operands of the or. + BackedgeTakenInfo BTI0 = + ComputeBackedgeTakenCountFromExitCond(L, BO->getOperand(0), TBB, FBB); + BackedgeTakenInfo BTI1 = + ComputeBackedgeTakenCountFromExitCond(L, BO->getOperand(1), TBB, FBB); + const SCEV *BECount = getCouldNotCompute(); + const SCEV *MaxBECount = getCouldNotCompute(); + if (L->contains(FBB)) { + // Both conditions must be false for the loop to continue executing. + // Choose the less conservative count. + if (BTI0.Exact == getCouldNotCompute() || + BTI1.Exact == getCouldNotCompute()) + BECount = getCouldNotCompute(); + else + BECount = getUMinFromMismatchedTypes(BTI0.Exact, BTI1.Exact); + if (BTI0.Max == getCouldNotCompute()) + MaxBECount = BTI1.Max; + else if (BTI1.Max == getCouldNotCompute()) + MaxBECount = BTI0.Max; + else + MaxBECount = getUMinFromMismatchedTypes(BTI0.Max, BTI1.Max); + } else { + // Both conditions must be false for the loop to exit. + assert(L->contains(TBB) && "Loop block has no successor in loop!"); + if (BTI0.Exact != getCouldNotCompute() && + BTI1.Exact != getCouldNotCompute()) + BECount = getUMaxFromMismatchedTypes(BTI0.Exact, BTI1.Exact); + if (BTI0.Max != getCouldNotCompute() && + BTI1.Max != getCouldNotCompute()) + MaxBECount = getUMaxFromMismatchedTypes(BTI0.Max, BTI1.Max); + } + + return BackedgeTakenInfo(BECount, MaxBECount); + } + } + + // With an icmp, it may be feasible to compute an exact backedge-taken count. + // Procede to the next level to examine the icmp. + if (ICmpInst *ExitCondICmp = dyn_cast(ExitCond)) + return ComputeBackedgeTakenCountFromExitCondICmp(L, ExitCondICmp, TBB, FBB); + + // If it's not an integer or pointer comparison then compute it the hard way. + return ComputeBackedgeTakenCountExhaustively(L, ExitCond, !L->contains(TBB)); +} + +/// ComputeBackedgeTakenCountFromExitCondICmp - Compute the number of times the +/// backedge of the specified loop will execute if its exit condition +/// were a conditional branch of the ICmpInst ExitCond, TBB, and FBB. +ScalarEvolution::BackedgeTakenInfo +ScalarEvolution::ComputeBackedgeTakenCountFromExitCondICmp(const Loop *L, + ICmpInst *ExitCond, + BasicBlock *TBB, + BasicBlock *FBB) { + + // If the condition was exit on true, convert the condition to exit on false + ICmpInst::Predicate Cond; + if (!L->contains(FBB)) + Cond = ExitCond->getPredicate(); + else + Cond = ExitCond->getInversePredicate(); + + // Handle common loops like: for (X = "string"; *X; ++X) + if (LoadInst *LI = dyn_cast(ExitCond->getOperand(0))) + if (Constant *RHS = dyn_cast(ExitCond->getOperand(1))) { + const SCEV *ItCnt = + ComputeLoadConstantCompareBackedgeTakenCount(LI, RHS, L, Cond); + if (!isa(ItCnt)) { + unsigned BitWidth = getTypeSizeInBits(ItCnt->getType()); + return BackedgeTakenInfo(ItCnt, + isa(ItCnt) ? ItCnt : + getConstant(APInt::getMaxValue(BitWidth)-1)); + } + } + + const SCEV *LHS = getSCEV(ExitCond->getOperand(0)); + const SCEV *RHS = getSCEV(ExitCond->getOperand(1)); + + // Try to evaluate any dependencies out of the loop. + LHS = getSCEVAtScope(LHS, L); + RHS = getSCEVAtScope(RHS, L); + + // At this point, we would like to compute how many iterations of the + // loop the predicate will return true for these inputs. + if (LHS->isLoopInvariant(L) && !RHS->isLoopInvariant(L)) { + // If there is a loop-invariant, force it into the RHS. + std::swap(LHS, RHS); + Cond = ICmpInst::getSwappedPredicate(Cond); + } + + // If we have a comparison of a chrec against a constant, try to use value + // ranges to answer this query. + if (const SCEVConstant *RHSC = dyn_cast(RHS)) + if (const SCEVAddRecExpr *AddRec = dyn_cast(LHS)) + if (AddRec->getLoop() == L) { + // Form the constant range. + ConstantRange CompRange( + ICmpInst::makeConstantRange(Cond, RHSC->getValue()->getValue())); + + const SCEV *Ret = AddRec->getNumIterationsInRange(CompRange, *this); + if (!isa(Ret)) return Ret; + } + + switch (Cond) { + case ICmpInst::ICMP_NE: { // while (X != Y) + // Convert to: while (X-Y != 0) + const SCEV *TC = HowFarToZero(getMinusSCEV(LHS, RHS), L); + if (!isa(TC)) return TC; + break; + } + case ICmpInst::ICMP_EQ: { // while (X == Y) + // Convert to: while (X-Y == 0) + const SCEV *TC = HowFarToNonZero(getMinusSCEV(LHS, RHS), L); + if (!isa(TC)) return TC; + break; + } + case ICmpInst::ICMP_SLT: { + BackedgeTakenInfo BTI = HowManyLessThans(LHS, RHS, L, true); + if (BTI.hasAnyInfo()) return BTI; + break; + } + case ICmpInst::ICMP_SGT: { + BackedgeTakenInfo BTI = HowManyLessThans(getNotSCEV(LHS), + getNotSCEV(RHS), L, true); + if (BTI.hasAnyInfo()) return BTI; + break; + } + case ICmpInst::ICMP_ULT: { + BackedgeTakenInfo BTI = HowManyLessThans(LHS, RHS, L, false); + if (BTI.hasAnyInfo()) return BTI; + break; + } + case ICmpInst::ICMP_UGT: { + BackedgeTakenInfo BTI = HowManyLessThans(getNotSCEV(LHS), + getNotSCEV(RHS), L, false); + if (BTI.hasAnyInfo()) return BTI; + break; + } + default: +#if 0 + errs() << "ComputeBackedgeTakenCount "; + if (ExitCond->getOperand(0)->getType()->isUnsigned()) + errs() << "[unsigned] "; + errs() << *LHS << " " + << Instruction::getOpcodeName(Instruction::ICmp) + << " " << *RHS << "\n"; +#endif + break; + } + return + ComputeBackedgeTakenCountExhaustively(L, ExitCond, !L->contains(TBB)); +} + +static ConstantInt * +EvaluateConstantChrecAtConstant(const SCEVAddRecExpr *AddRec, ConstantInt *C, + ScalarEvolution &SE) { + const SCEV *InVal = SE.getConstant(C); + const SCEV *Val = AddRec->evaluateAtIteration(InVal, SE); + assert(isa(Val) && + "Evaluation of SCEV at constant didn't fold correctly?"); + return cast(Val)->getValue(); +} + +/// GetAddressedElementFromGlobal - Given a global variable with an initializer +/// and a GEP expression (missing the pointer index) indexing into it, return +/// the addressed element of the initializer or null if the index expression is +/// invalid. +static Constant * +GetAddressedElementFromGlobal(GlobalVariable *GV, + const std::vector &Indices) { + Constant *Init = GV->getInitializer(); + for (unsigned i = 0, e = Indices.size(); i != e; ++i) { + uint64_t Idx = Indices[i]->getZExtValue(); + if (ConstantStruct *CS = dyn_cast(Init)) { + assert(Idx < CS->getNumOperands() && "Bad struct index!"); + Init = cast(CS->getOperand(Idx)); + } else if (ConstantArray *CA = dyn_cast(Init)) { + if (Idx >= CA->getNumOperands()) return 0; // Bogus program + Init = cast(CA->getOperand(Idx)); + } else if (isa(Init)) { + if (const StructType *STy = dyn_cast(Init->getType())) { + assert(Idx < STy->getNumElements() && "Bad struct index!"); + Init = Constant::getNullValue(STy->getElementType(Idx)); + } else if (const ArrayType *ATy = dyn_cast(Init->getType())) { + if (Idx >= ATy->getNumElements()) return 0; // Bogus program + Init = Constant::getNullValue(ATy->getElementType()); + } else { + llvm_unreachable("Unknown constant aggregate type!"); + } + return 0; + } else { + return 0; // Unknown initializer type + } + } + return Init; +} + +/// ComputeLoadConstantCompareBackedgeTakenCount - Given an exit condition of +/// 'icmp op load X, cst', try to see if we can compute the backedge +/// execution count. +const SCEV * +ScalarEvolution::ComputeLoadConstantCompareBackedgeTakenCount( + LoadInst *LI, + Constant *RHS, + const Loop *L, + ICmpInst::Predicate predicate) { + if (LI->isVolatile()) return getCouldNotCompute(); + + // Check to see if the loaded pointer is a getelementptr of a global. + GetElementPtrInst *GEP = dyn_cast(LI->getOperand(0)); + if (!GEP) return getCouldNotCompute(); + + // Make sure that it is really a constant global we are gepping, with an + // initializer, and make sure the first IDX is really 0. + GlobalVariable *GV = dyn_cast(GEP->getOperand(0)); + if (!GV || !GV->isConstant() || !GV->hasDefinitiveInitializer() || + GEP->getNumOperands() < 3 || !isa(GEP->getOperand(1)) || + !cast(GEP->getOperand(1))->isNullValue()) + return getCouldNotCompute(); + + // Okay, we allow one non-constant index into the GEP instruction. + Value *VarIdx = 0; + std::vector Indexes; + unsigned VarIdxNum = 0; + for (unsigned i = 2, e = GEP->getNumOperands(); i != e; ++i) + if (ConstantInt *CI = dyn_cast(GEP->getOperand(i))) { + Indexes.push_back(CI); + } else if (!isa(GEP->getOperand(i))) { + if (VarIdx) return getCouldNotCompute(); // Multiple non-constant idx's. + VarIdx = GEP->getOperand(i); + VarIdxNum = i-2; + Indexes.push_back(0); + } + + // Okay, we know we have a (load (gep GV, 0, X)) comparison with a constant. + // Check to see if X is a loop variant variable value now. + const SCEV *Idx = getSCEV(VarIdx); + Idx = getSCEVAtScope(Idx, L); + + // We can only recognize very limited forms of loop index expressions, in + // particular, only affine AddRec's like {C1,+,C2}. + const SCEVAddRecExpr *IdxExpr = dyn_cast(Idx); + if (!IdxExpr || !IdxExpr->isAffine() || IdxExpr->isLoopInvariant(L) || + !isa(IdxExpr->getOperand(0)) || + !isa(IdxExpr->getOperand(1))) + return getCouldNotCompute(); + + unsigned MaxSteps = MaxBruteForceIterations; + for (unsigned IterationNum = 0; IterationNum != MaxSteps; ++IterationNum) { + ConstantInt *ItCst = ConstantInt::get( + cast(IdxExpr->getType()), IterationNum); + ConstantInt *Val = EvaluateConstantChrecAtConstant(IdxExpr, ItCst, *this); + + // Form the GEP offset. + Indexes[VarIdxNum] = Val; + + Constant *Result = GetAddressedElementFromGlobal(GV, Indexes); + if (Result == 0) break; // Cannot compute! + + // Evaluate the condition for this iteration. + Result = ConstantExpr::getICmp(predicate, Result, RHS); + if (!isa(Result)) break; // Couldn't decide for sure + if (cast(Result)->getValue().isMinValue()) { +#if 0 + errs() << "\n***\n*** Computed loop count " << *ItCst + << "\n*** From global " << *GV << "*** BB: " << *L->getHeader() + << "***\n"; +#endif + ++NumArrayLenItCounts; + return getConstant(ItCst); // Found terminating iteration! + } + } + return getCouldNotCompute(); +} + + +/// CanConstantFold - Return true if we can constant fold an instruction of the +/// specified type, assuming that all operands were constants. +static bool CanConstantFold(const Instruction *I) { + if (isa(I) || isa(I) || + isa(I) || isa(I) || isa(I)) + return true; + + if (const CallInst *CI = dyn_cast(I)) + if (const Function *F = CI->getCalledFunction()) + return canConstantFoldCallTo(F); + return false; +} + +/// getConstantEvolvingPHI - Given an LLVM value and a loop, return a PHI node +/// in the loop that V is derived from. We allow arbitrary operations along the +/// way, but the operands of an operation must either be constants or a value +/// derived from a constant PHI. If this expression does not fit with these +/// constraints, return null. +static PHINode *getConstantEvolvingPHI(Value *V, const Loop *L) { + // If this is not an instruction, or if this is an instruction outside of the + // loop, it can't be derived from a loop PHI. + Instruction *I = dyn_cast(V); + if (I == 0 || !L->contains(I->getParent())) return 0; + + if (PHINode *PN = dyn_cast(I)) { + if (L->getHeader() == I->getParent()) + return PN; + else + // We don't currently keep track of the control flow needed to evaluate + // PHIs, so we cannot handle PHIs inside of loops. + return 0; + } + + // If we won't be able to constant fold this expression even if the operands + // are constants, return early. + if (!CanConstantFold(I)) return 0; + + // Otherwise, we can evaluate this instruction if all of its operands are + // constant or derived from a PHI node themselves. + PHINode *PHI = 0; + for (unsigned Op = 0, e = I->getNumOperands(); Op != e; ++Op) + if (!(isa(I->getOperand(Op)) || + isa(I->getOperand(Op)))) { + PHINode *P = getConstantEvolvingPHI(I->getOperand(Op), L); + if (P == 0) return 0; // Not evolving from PHI + if (PHI == 0) + PHI = P; + else if (PHI != P) + return 0; // Evolving from multiple different PHIs. + } + + // This is a expression evolving from a constant PHI! + return PHI; +} + +/// EvaluateExpression - Given an expression that passes the +/// getConstantEvolvingPHI predicate, evaluate its value assuming the PHI node +/// in the loop has the value PHIVal. If we can't fold this expression for some +/// reason, return null. +static Constant *EvaluateExpression(Value *V, Constant *PHIVal, + const TargetData *TD) { + if (isa(V)) return PHIVal; + if (Constant *C = dyn_cast(V)) return C; + if (GlobalValue *GV = dyn_cast(V)) return GV; + Instruction *I = cast(V); + + std::vector Operands; + Operands.resize(I->getNumOperands()); + + for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i) { + Operands[i] = EvaluateExpression(I->getOperand(i), PHIVal, TD); + if (Operands[i] == 0) return 0; + } + + if (const CmpInst *CI = dyn_cast(I)) + return ConstantFoldCompareInstOperands(CI->getPredicate(), Operands[0], + Operands[1], TD); + return ConstantFoldInstOperands(I->getOpcode(), I->getType(), + &Operands[0], Operands.size(), TD); +} + +/// getConstantEvolutionLoopExitValue - If we know that the specified Phi is +/// in the header of its containing loop, we know the loop executes a +/// constant number of times, and the PHI node is just a recurrence +/// involving constants, fold it. +Constant * +ScalarEvolution::getConstantEvolutionLoopExitValue(PHINode *PN, + const APInt& BEs, + const Loop *L) { + std::map::iterator I = + ConstantEvolutionLoopExitValue.find(PN); + if (I != ConstantEvolutionLoopExitValue.end()) + return I->second; + + if (BEs.ugt(APInt(BEs.getBitWidth(),MaxBruteForceIterations))) + return ConstantEvolutionLoopExitValue[PN] = 0; // Not going to evaluate it. + + Constant *&RetVal = ConstantEvolutionLoopExitValue[PN]; + + // Since the loop is canonicalized, the PHI node must have two entries. One + // entry must be a constant (coming in from outside of the loop), and the + // second must be derived from the same PHI. + bool SecondIsBackedge = L->contains(PN->getIncomingBlock(1)); + Constant *StartCST = + dyn_cast(PN->getIncomingValue(!SecondIsBackedge)); + if (StartCST == 0) + return RetVal = 0; // Must be a constant. + + Value *BEValue = PN->getIncomingValue(SecondIsBackedge); + PHINode *PN2 = getConstantEvolvingPHI(BEValue, L); + if (PN2 != PN) + return RetVal = 0; // Not derived from same PHI. + + // Execute the loop symbolically to determine the exit value. + if (BEs.getActiveBits() >= 32) + return RetVal = 0; // More than 2^32-1 iterations?? Not doing it! + + unsigned NumIterations = BEs.getZExtValue(); // must be in range + unsigned IterationNum = 0; + for (Constant *PHIVal = StartCST; ; ++IterationNum) { + if (IterationNum == NumIterations) + return RetVal = PHIVal; // Got exit value! + + // Compute the value of the PHI node for the next iteration. + Constant *NextPHI = EvaluateExpression(BEValue, PHIVal, TD); + if (NextPHI == PHIVal) + return RetVal = NextPHI; // Stopped evolving! + if (NextPHI == 0) + return 0; // Couldn't evaluate! + PHIVal = NextPHI; + } +} + +/// ComputeBackedgeTakenCountExhaustively - If the loop is known to execute a +/// constant number of times (the condition evolves only from constants), +/// 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 +/// evaluate the trip count of the loop, return getCouldNotCompute(). +const SCEV * +ScalarEvolution::ComputeBackedgeTakenCountExhaustively(const Loop *L, + Value *Cond, + bool ExitWhen) { + PHINode *PN = getConstantEvolvingPHI(Cond, L); + if (PN == 0) return getCouldNotCompute(); + + // Since the loop is canonicalized, the PHI node must have two entries. One + // entry must be a constant (coming in from outside of the loop), and the + // second must be derived from the same PHI. + bool SecondIsBackedge = L->contains(PN->getIncomingBlock(1)); + Constant *StartCST = + dyn_cast(PN->getIncomingValue(!SecondIsBackedge)); + if (StartCST == 0) return getCouldNotCompute(); // Must be a constant. + + Value *BEValue = PN->getIncomingValue(SecondIsBackedge); + PHINode *PN2 = getConstantEvolvingPHI(BEValue, L); + if (PN2 != PN) return getCouldNotCompute(); // Not derived from same PHI. + + // Okay, we find a PHI node that defines the trip count of this loop. Execute + // the loop symbolically to determine when the condition gets a value of + // "ExitWhen". + unsigned IterationNum = 0; + unsigned MaxIterations = MaxBruteForceIterations; // Limit analysis. + for (Constant *PHIVal = StartCST; + IterationNum != MaxIterations; ++IterationNum) { + ConstantInt *CondVal = + dyn_cast_or_null(EvaluateExpression(Cond, PHIVal, TD)); + + // Couldn't symbolically evaluate. + if (!CondVal) return getCouldNotCompute(); + + if (CondVal->getValue() == uint64_t(ExitWhen)) { + ++NumBruteForceTripCountsComputed; + return getConstant(Type::getInt32Ty(getContext()), IterationNum); + } + + // Compute the value of the PHI node for the next iteration. + Constant *NextPHI = EvaluateExpression(BEValue, PHIVal, TD); + if (NextPHI == 0 || NextPHI == PHIVal) + return getCouldNotCompute();// Couldn't evaluate or not making progress... + PHIVal = NextPHI; + } + + // Too many iterations were needed to evaluate. + return getCouldNotCompute(); +} + +/// getSCEVAtScope - Return a SCEV expression for the specified value +/// at the specified scope in the program. The L value specifies a loop +/// nest to evaluate the expression at, where null is the top-level or a +/// specified loop is immediately inside of the loop. +/// +/// This method can be used to compute the exit value for a variable defined +/// in a loop by querying what the value will hold in the parent loop. +/// +/// In the case that a relevant loop exit value cannot be computed, the +/// original value V is returned. +const SCEV *ScalarEvolution::getSCEVAtScope(const SCEV *V, const Loop *L) { + // Check to see if we've folded this expression at this loop before. + std::map &Values = ValuesAtScopes[V]; + std::pair::iterator, bool> Pair = + Values.insert(std::make_pair(L, static_cast(0))); + if (!Pair.second) + return Pair.first->second ? Pair.first->second : V; + + // Otherwise compute it. + const SCEV *C = computeSCEVAtScope(V, L); + ValuesAtScopes[V][L] = C; + return C; +} + +const SCEV *ScalarEvolution::computeSCEVAtScope(const SCEV *V, const Loop *L) { + if (isa(V)) return V; + + // If this instruction is evolved from a constant-evolving PHI, compute the + // exit value from the loop without using SCEVs. + if (const SCEVUnknown *SU = dyn_cast(V)) { + if (Instruction *I = dyn_cast(SU->getValue())) { + const Loop *LI = (*this->LI)[I->getParent()]; + if (LI && LI->getParentLoop() == L) // Looking for loop exit value. + if (PHINode *PN = dyn_cast(I)) + if (PN->getParent() == LI->getHeader()) { + // Okay, there is no closed form solution for the PHI node. Check + // to see if the loop that contains it has a known backedge-taken + // count. If so, we may be able to force computation of the exit + // value. + const SCEV *BackedgeTakenCount = getBackedgeTakenCount(LI); + if (const SCEVConstant *BTCC = + dyn_cast(BackedgeTakenCount)) { + // Okay, we know how many times the containing loop executes. If + // this is a constant evolving PHI node, get the final value at + // the specified iteration number. + Constant *RV = getConstantEvolutionLoopExitValue(PN, + BTCC->getValue()->getValue(), + LI); + if (RV) return getSCEV(RV); + } + } + + // Okay, this is an expression that we cannot symbolically evaluate + // into a SCEV. Check to see if it's possible to symbolically evaluate + // the arguments into constants, and if so, try to constant propagate the + // result. This is particularly useful for computing loop exit values. + if (CanConstantFold(I)) { + std::vector Operands; + Operands.reserve(I->getNumOperands()); + for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i) { + Value *Op = I->getOperand(i); + if (Constant *C = dyn_cast(Op)) { + Operands.push_back(C); + } else { + // If any of the operands is non-constant and if they are + // non-integer and non-pointer, don't even try to analyze them + // with scev techniques. + if (!isSCEVable(Op->getType())) + return V; + + const SCEV* OpV = getSCEVAtScope(Op, L); + if (const SCEVConstant *SC = dyn_cast(OpV)) { + Constant *C = SC->getValue(); + if (C->getType() != Op->getType()) + C = ConstantExpr::getCast(CastInst::getCastOpcode(C, false, + Op->getType(), + false), + C, Op->getType()); + Operands.push_back(C); + } else if (const SCEVUnknown *SU = dyn_cast(OpV)) { + if (Constant *C = dyn_cast(SU->getValue())) { + if (C->getType() != Op->getType()) + C = + ConstantExpr::getCast(CastInst::getCastOpcode(C, false, + Op->getType(), + false), + C, Op->getType()); + Operands.push_back(C); + } else + return V; + } else { + return V; + } + } + } + + Constant *C; + if (const CmpInst *CI = dyn_cast(I)) + C = ConstantFoldCompareInstOperands(CI->getPredicate(), + Operands[0], Operands[1], TD); + else + C = ConstantFoldInstOperands(I->getOpcode(), I->getType(), + &Operands[0], Operands.size(), TD); + return getSCEV(C); + } + } + + // This is some other type of SCEVUnknown, just return it. + return V; + } + + if (const SCEVCommutativeExpr *Comm = dyn_cast(V)) { + // Avoid performing the look-up in the common case where the specified + // expression has no loop-variant portions. + for (unsigned i = 0, e = Comm->getNumOperands(); i != e; ++i) { + const SCEV *OpAtScope = getSCEVAtScope(Comm->getOperand(i), L); + if (OpAtScope != Comm->getOperand(i)) { + // Okay, at least one of these operands is loop variant but might be + // foldable. Build a new instance of the folded commutative expression. + SmallVector NewOps(Comm->op_begin(), + Comm->op_begin()+i); + NewOps.push_back(OpAtScope); + + for (++i; i != e; ++i) { + OpAtScope = getSCEVAtScope(Comm->getOperand(i), L); + NewOps.push_back(OpAtScope); + } + if (isa(Comm)) + return getAddExpr(NewOps); + if (isa(Comm)) + return getMulExpr(NewOps); + if (isa(Comm)) + return getSMaxExpr(NewOps); + if (isa(Comm)) + return getUMaxExpr(NewOps); + llvm_unreachable("Unknown commutative SCEV type!"); + } + } + // If we got here, all operands are loop invariant. + return Comm; + } + + if (const SCEVUDivExpr *Div = dyn_cast(V)) { + const SCEV *LHS = getSCEVAtScope(Div->getLHS(), L); + const SCEV *RHS = getSCEVAtScope(Div->getRHS(), L); + if (LHS == Div->getLHS() && RHS == Div->getRHS()) + return Div; // must be loop invariant + return getUDivExpr(LHS, RHS); + } + + // If this is a loop recurrence for a loop that does not contain L, then we + // are dealing with the final value computed by the loop. + if (const SCEVAddRecExpr *AddRec = dyn_cast(V)) { + if (!L || !AddRec->getLoop()->contains(L->getHeader())) { + // To evaluate this recurrence, we need to know how many times the AddRec + // loop iterates. Compute this now. + const SCEV *BackedgeTakenCount = getBackedgeTakenCount(AddRec->getLoop()); + if (BackedgeTakenCount == getCouldNotCompute()) return AddRec; + + // Then, evaluate the AddRec. + return AddRec->evaluateAtIteration(BackedgeTakenCount, *this); + } + return AddRec; + } + + if (const SCEVZeroExtendExpr *Cast = dyn_cast(V)) { + const SCEV *Op = getSCEVAtScope(Cast->getOperand(), L); + if (Op == Cast->getOperand()) + return Cast; // must be loop invariant + return getZeroExtendExpr(Op, Cast->getType()); + } + + if (const SCEVSignExtendExpr *Cast = dyn_cast(V)) { + const SCEV *Op = getSCEVAtScope(Cast->getOperand(), L); + if (Op == Cast->getOperand()) + return Cast; // must be loop invariant + return getSignExtendExpr(Op, Cast->getType()); + } + + if (const SCEVTruncateExpr *Cast = dyn_cast(V)) { + const SCEV *Op = getSCEVAtScope(Cast->getOperand(), L); + if (Op == Cast->getOperand()) + return Cast; // must be loop invariant + return getTruncateExpr(Op, Cast->getType()); + } + + if (isa(V)) + return V; + + llvm_unreachable("Unknown SCEV type!"); + return 0; +} + +/// getSCEVAtScope - This is a convenience function which does +/// getSCEVAtScope(getSCEV(V), L). +const SCEV *ScalarEvolution::getSCEVAtScope(Value *V, const Loop *L) { + return getSCEVAtScope(getSCEV(V), L); +} + +/// SolveLinEquationWithOverflow - Finds the minimum unsigned root of the +/// following equation: +/// +/// A * X = B (mod N) +/// +/// where N = 2^BW and BW is the common bit width of A and B. The signedness of +/// A and B isn't important. +/// +/// If the equation does not have a solution, SCEVCouldNotCompute is returned. +static const SCEV *SolveLinEquationWithOverflow(const APInt &A, const APInt &B, + ScalarEvolution &SE) { + uint32_t BW = A.getBitWidth(); + assert(BW == B.getBitWidth() && "Bit widths must be the same."); + assert(A != 0 && "A must be non-zero."); + + // 1. D = gcd(A, N) + // + // The gcd of A and N may have only one prime factor: 2. The number of + // trailing zeros in A is its multiplicity + uint32_t Mult2 = A.countTrailingZeros(); + // D = 2^Mult2 + + // 2. Check if B is divisible by D. + // + // B is divisible by D if and only if the multiplicity of prime factor 2 for B + // is not less than multiplicity of this prime factor for D. + if (B.countTrailingZeros() < Mult2) + return SE.getCouldNotCompute(); + + // 3. Compute I: the multiplicative inverse of (A / D) in arithmetic + // modulo (N / D). + // + // (N / D) may need BW+1 bits in its representation. Hence, we'll use this + // bit width during computations. + APInt AD = A.lshr(Mult2).zext(BW + 1); // AD = A / D + APInt Mod(BW + 1, 0); + Mod.set(BW - Mult2); // Mod = N / D + APInt I = AD.multiplicativeInverse(Mod); + + // 4. Compute the minimum unsigned root of the equation: + // I * (B / D) mod (N / D) + APInt Result = (I * B.lshr(Mult2).zext(BW + 1)).urem(Mod); + + // The result is guaranteed to be less than 2^BW so we may truncate it to BW + // bits. + return SE.getConstant(Result.trunc(BW)); +} + +/// SolveQuadraticEquation - Find the roots of the quadratic equation for the +/// given quadratic chrec {L,+,M,+,N}. This returns either the two roots (which +/// might be the same) or two SCEVCouldNotCompute objects. +/// +static std::pair +SolveQuadraticEquation(const SCEVAddRecExpr *AddRec, ScalarEvolution &SE) { + assert(AddRec->getNumOperands() == 3 && "This is not a quadratic chrec!"); + const SCEVConstant *LC = dyn_cast(AddRec->getOperand(0)); + const SCEVConstant *MC = dyn_cast(AddRec->getOperand(1)); + const SCEVConstant *NC = dyn_cast(AddRec->getOperand(2)); + + // We currently can only solve this if the coefficients are constants. + if (!LC || !MC || !NC) { + const SCEV *CNC = SE.getCouldNotCompute(); + return std::make_pair(CNC, CNC); + } + + uint32_t BitWidth = LC->getValue()->getValue().getBitWidth(); + const APInt &L = LC->getValue()->getValue(); + const APInt &M = MC->getValue()->getValue(); + const APInt &N = NC->getValue()->getValue(); + APInt Two(BitWidth, 2); + APInt Four(BitWidth, 4); + + { + using namespace APIntOps; + const APInt& C = L; + // Convert from chrec coefficients to polynomial coefficients AX^2+BX+C + // The B coefficient is M-N/2 + APInt B(M); + B -= sdiv(N,Two); + + // The A coefficient is N/2 + APInt A(N.sdiv(Two)); + + // Compute the B^2-4ac term. + APInt SqrtTerm(B); + SqrtTerm *= B; + SqrtTerm -= Four * (A * C); + + // Compute sqrt(B^2-4ac). This is guaranteed to be the nearest + // integer value or else APInt::sqrt() will assert. + APInt SqrtVal(SqrtTerm.sqrt()); + + // Compute the two solutions for the quadratic formula. + // The divisions must be performed as signed divisions. + APInt NegB(-B); + APInt TwoA( A << 1 ); + if (TwoA.isMinValue()) { + const SCEV *CNC = SE.getCouldNotCompute(); + return std::make_pair(CNC, CNC); + } + + LLVMContext &Context = SE.getContext(); + + ConstantInt *Solution1 = + ConstantInt::get(Context, (NegB + SqrtVal).sdiv(TwoA)); + ConstantInt *Solution2 = + ConstantInt::get(Context, (NegB - SqrtVal).sdiv(TwoA)); + + return std::make_pair(SE.getConstant(Solution1), + SE.getConstant(Solution2)); + } // end APIntOps namespace +} + +/// HowFarToZero - Return the number of times a backedge comparing the specified +/// value to zero will execute. If not computable, return CouldNotCompute. +const SCEV *ScalarEvolution::HowFarToZero(const SCEV *V, const Loop *L) { + // If the value is a constant + if (const SCEVConstant *C = dyn_cast(V)) { + // If the value is already zero, the branch will execute zero times. + if (C->getValue()->isZero()) return C; + return getCouldNotCompute(); // Otherwise it will loop infinitely. + } + + const SCEVAddRecExpr *AddRec = dyn_cast(V); + if (!AddRec || AddRec->getLoop() != L) + return getCouldNotCompute(); + + if (AddRec->isAffine()) { + // If this is an affine expression, the execution count of this branch is + // the minimum unsigned root of the following equation: + // + // Start + Step*N = 0 (mod 2^BW) + // + // equivalent to: + // + // Step*N = -Start (mod 2^BW) + // + // where BW is the common bit width of Start and Step. + + // Get the initial value for the loop. + const SCEV *Start = getSCEVAtScope(AddRec->getStart(), + L->getParentLoop()); + const SCEV *Step = getSCEVAtScope(AddRec->getOperand(1), + L->getParentLoop()); + + if (const SCEVConstant *StepC = dyn_cast(Step)) { + // For now we handle only constant steps. + + // First, handle unitary steps. + if (StepC->getValue()->equalsInt(1)) // 1*N = -Start (mod 2^BW), so: + return getNegativeSCEV(Start); // N = -Start (as unsigned) + if (StepC->getValue()->isAllOnesValue()) // -1*N = -Start (mod 2^BW), so: + return Start; // N = Start (as unsigned) + + // Then, try to solve the above equation provided that Start is constant. + if (const SCEVConstant *StartC = dyn_cast(Start)) + return SolveLinEquationWithOverflow(StepC->getValue()->getValue(), + -StartC->getValue()->getValue(), + *this); + } + } else if (AddRec->isQuadratic() && AddRec->getType()->isInteger()) { + // If this is a quadratic (3-term) AddRec {L,+,M,+,N}, find the roots of + // the quadratic equation to solve it. + std::pair Roots = SolveQuadraticEquation(AddRec, + *this); + const SCEVConstant *R1 = dyn_cast(Roots.first); + const SCEVConstant *R2 = dyn_cast(Roots.second); + if (R1) { +#if 0 + errs() << "HFTZ: " << *V << " - sol#1: " << *R1 + << " sol#2: " << *R2 << "\n"; +#endif + // Pick the smallest positive root value. + if (ConstantInt *CB = + dyn_cast(ConstantExpr::getICmp(ICmpInst::ICMP_ULT, + R1->getValue(), R2->getValue()))) { + if (CB->getZExtValue() == false) + std::swap(R1, R2); // R1 is the minimum root now. + + // We can only use this value if the chrec ends up with an exact zero + // value at this index. When solving for "X*X != 5", for example, we + // should not accept a root of 2. + const SCEV *Val = AddRec->evaluateAtIteration(R1, *this); + if (Val->isZero()) + return R1; // We found a quadratic root! + } + } + } + + return getCouldNotCompute(); +} + +/// HowFarToNonZero - Return the number of times a backedge checking the +/// specified value for nonzero will execute. If not computable, return +/// CouldNotCompute +const SCEV *ScalarEvolution::HowFarToNonZero(const SCEV *V, const Loop *L) { + // Loops that look like: while (X == 0) are very strange indeed. We don't + // handle them yet except for the trivial case. This could be expanded in the + // future as needed. + + // If the value is a constant, check to see if it is known to be non-zero + // already. If so, the backedge will execute zero times. + if (const SCEVConstant *C = dyn_cast(V)) { + if (!C->getValue()->isNullValue()) + return getIntegerSCEV(0, C->getType()); + return getCouldNotCompute(); // Otherwise it will loop infinitely. + } + + // We could implement others, but I really doubt anyone writes loops like + // this, and if they did, they would already be constant folded. + return getCouldNotCompute(); +} + +/// getLoopPredecessor - If the given loop's header has exactly one unique +/// predecessor outside the loop, return it. Otherwise return null. +/// +BasicBlock *ScalarEvolution::getLoopPredecessor(const Loop *L) { + BasicBlock *Header = L->getHeader(); + BasicBlock *Pred = 0; + for (pred_iterator PI = pred_begin(Header), E = pred_end(Header); + PI != E; ++PI) + if (!L->contains(*PI)) { + if (Pred && Pred != *PI) return 0; // Multiple predecessors. + Pred = *PI; + } + return Pred; +} + +/// getPredecessorWithUniqueSuccessorForBB - Return a predecessor of BB +/// (which may not be an immediate predecessor) which has exactly one +/// successor from which BB is reachable, or null if no such block is +/// found. +/// +BasicBlock * +ScalarEvolution::getPredecessorWithUniqueSuccessorForBB(BasicBlock *BB) { + // If the block has a unique predecessor, then there is no path from the + // predecessor to the block that does not go through the direct edge + // from the predecessor to the block. + if (BasicBlock *Pred = BB->getSinglePredecessor()) + return Pred; + + // A loop's header is defined to be a block that dominates the loop. + // If the header has a unique predecessor outside the loop, it must be + // a block that has exactly one successor that can reach the loop. + if (Loop *L = LI->getLoopFor(BB)) + return getLoopPredecessor(L); + + return 0; +} + +/// HasSameValue - SCEV structural equivalence is usually sufficient for +/// testing whether two expressions are equal, however for the purposes of +/// looking for a condition guarding a loop, it can be useful to be a little +/// more general, since a front-end may have replicated the controlling +/// expression. +/// +static bool HasSameValue(const SCEV *A, const SCEV *B) { + // Quick check to see if they are the same SCEV. + if (A == B) return true; + + // Otherwise, if they're both SCEVUnknown, it's possible that they hold + // two different instructions with the same value. Check for this case. + if (const SCEVUnknown *AU = dyn_cast(A)) + if (const SCEVUnknown *BU = dyn_cast(B)) + if (const Instruction *AI = dyn_cast(AU->getValue())) + if (const Instruction *BI = dyn_cast(BU->getValue())) + if (AI->isIdenticalTo(BI) && !AI->mayReadFromMemory()) + return true; + + // Otherwise assume they may have a different value. + return false; +} + +bool ScalarEvolution::isKnownNegative(const SCEV *S) { + return getSignedRange(S).getSignedMax().isNegative(); +} + +bool ScalarEvolution::isKnownPositive(const SCEV *S) { + return getSignedRange(S).getSignedMin().isStrictlyPositive(); +} + +bool ScalarEvolution::isKnownNonNegative(const SCEV *S) { + return !getSignedRange(S).getSignedMin().isNegative(); +} + +bool ScalarEvolution::isKnownNonPositive(const SCEV *S) { + return !getSignedRange(S).getSignedMax().isStrictlyPositive(); +} + +bool ScalarEvolution::isKnownNonZero(const SCEV *S) { + return isKnownNegative(S) || isKnownPositive(S); +} + +bool ScalarEvolution::isKnownPredicate(ICmpInst::Predicate Pred, + const SCEV *LHS, const SCEV *RHS) { + + if (HasSameValue(LHS, RHS)) + return ICmpInst::isTrueWhenEqual(Pred); + + switch (Pred) { + default: + llvm_unreachable("Unexpected ICmpInst::Predicate value!"); + break; + case ICmpInst::ICMP_SGT: + Pred = ICmpInst::ICMP_SLT; + std::swap(LHS, RHS); + case ICmpInst::ICMP_SLT: { + ConstantRange LHSRange = getSignedRange(LHS); + ConstantRange RHSRange = getSignedRange(RHS); + if (LHSRange.getSignedMax().slt(RHSRange.getSignedMin())) + return true; + if (LHSRange.getSignedMin().sge(RHSRange.getSignedMax())) + return false; + break; + } + case ICmpInst::ICMP_SGE: + Pred = ICmpInst::ICMP_SLE; + std::swap(LHS, RHS); + case ICmpInst::ICMP_SLE: { + ConstantRange LHSRange = getSignedRange(LHS); + ConstantRange RHSRange = getSignedRange(RHS); + if (LHSRange.getSignedMax().sle(RHSRange.getSignedMin())) + return true; + if (LHSRange.getSignedMin().sgt(RHSRange.getSignedMax())) + return false; + break; + } + case ICmpInst::ICMP_UGT: + Pred = ICmpInst::ICMP_ULT; + std::swap(LHS, RHS); + case ICmpInst::ICMP_ULT: { + ConstantRange LHSRange = getUnsignedRange(LHS); + ConstantRange RHSRange = getUnsignedRange(RHS); + if (LHSRange.getUnsignedMax().ult(RHSRange.getUnsignedMin())) + return true; + if (LHSRange.getUnsignedMin().uge(RHSRange.getUnsignedMax())) + return false; + break; + } + case ICmpInst::ICMP_UGE: + Pred = ICmpInst::ICMP_ULE; + std::swap(LHS, RHS); + case ICmpInst::ICMP_ULE: { + ConstantRange LHSRange = getUnsignedRange(LHS); + ConstantRange RHSRange = getUnsignedRange(RHS); + if (LHSRange.getUnsignedMax().ule(RHSRange.getUnsignedMin())) + return true; + if (LHSRange.getUnsignedMin().ugt(RHSRange.getUnsignedMax())) + return false; + break; + } + case ICmpInst::ICMP_NE: { + if (getUnsignedRange(LHS).intersectWith(getUnsignedRange(RHS)).isEmptySet()) + return true; + if (getSignedRange(LHS).intersectWith(getSignedRange(RHS)).isEmptySet()) + return true; + + const SCEV *Diff = getMinusSCEV(LHS, RHS); + if (isKnownNonZero(Diff)) + return true; + break; + } + case ICmpInst::ICMP_EQ: + // The check at the top of the function catches the case where + // the values are known to be equal. + break; + } + return false; +} + +/// isLoopBackedgeGuardedByCond - Test whether the backedge of the loop is +/// protected by a conditional between LHS and RHS. This is used to +/// to eliminate casts. +bool +ScalarEvolution::isLoopBackedgeGuardedByCond(const Loop *L, + ICmpInst::Predicate Pred, + const SCEV *LHS, const SCEV *RHS) { + // Interpret a null as meaning no loop, where there is obviously no guard + // (interprocedural conditions notwithstanding). + if (!L) return true; + + BasicBlock *Latch = L->getLoopLatch(); + if (!Latch) + return false; + + BranchInst *LoopContinuePredicate = + dyn_cast(Latch->getTerminator()); + if (!LoopContinuePredicate || + LoopContinuePredicate->isUnconditional()) + return false; + + return isImpliedCond(LoopContinuePredicate->getCondition(), Pred, LHS, RHS, + LoopContinuePredicate->getSuccessor(0) != L->getHeader()); +} + +/// isLoopGuardedByCond - Test whether entry to the loop is protected +/// by a conditional between LHS and RHS. This is used to help avoid max +/// expressions in loop trip counts, and to eliminate casts. +bool +ScalarEvolution::isLoopGuardedByCond(const Loop *L, + ICmpInst::Predicate Pred, + const SCEV *LHS, const SCEV *RHS) { + // Interpret a null as meaning no loop, where there is obviously no guard + // (interprocedural conditions notwithstanding). + if (!L) return false; + + BasicBlock *Predecessor = getLoopPredecessor(L); + BasicBlock *PredecessorDest = L->getHeader(); + + // Starting at the loop predecessor, climb up the predecessor chain, as long + // as there are predecessors that can be found that have unique successors + // leading to the original header. + for (; Predecessor; + PredecessorDest = Predecessor, + Predecessor = getPredecessorWithUniqueSuccessorForBB(Predecessor)) { + + BranchInst *LoopEntryPredicate = + dyn_cast(Predecessor->getTerminator()); + if (!LoopEntryPredicate || + LoopEntryPredicate->isUnconditional()) + continue; + + if (isImpliedCond(LoopEntryPredicate->getCondition(), Pred, LHS, RHS, + LoopEntryPredicate->getSuccessor(0) != PredecessorDest)) + return true; + } + + return false; +} + +/// isImpliedCond - Test whether the condition described by Pred, LHS, +/// and RHS is true whenever the given Cond value evaluates to true. +bool ScalarEvolution::isImpliedCond(Value *CondValue, + ICmpInst::Predicate Pred, + const SCEV *LHS, const SCEV *RHS, + bool Inverse) { + // Recursivly handle And and Or conditions. + if (BinaryOperator *BO = dyn_cast(CondValue)) { + if (BO->getOpcode() == Instruction::And) { + if (!Inverse) + return isImpliedCond(BO->getOperand(0), Pred, LHS, RHS, Inverse) || + isImpliedCond(BO->getOperand(1), Pred, LHS, RHS, Inverse); + } else if (BO->getOpcode() == Instruction::Or) { + if (Inverse) + return isImpliedCond(BO->getOperand(0), Pred, LHS, RHS, Inverse) || + isImpliedCond(BO->getOperand(1), Pred, LHS, RHS, Inverse); + } + } + + ICmpInst *ICI = dyn_cast(CondValue); + if (!ICI) return false; + + // Bail if the ICmp's operands' types are wider than the needed type + // before attempting to call getSCEV on them. This avoids infinite + // recursion, since the analysis of widening casts can require loop + // exit condition information for overflow checking, which would + // lead back here. + if (getTypeSizeInBits(LHS->getType()) < + getTypeSizeInBits(ICI->getOperand(0)->getType())) + return false; + + // Now that we found a conditional branch that dominates the loop, check to + // see if it is the comparison we are looking for. + ICmpInst::Predicate FoundPred; + if (Inverse) + FoundPred = ICI->getInversePredicate(); + else + FoundPred = ICI->getPredicate(); + + const SCEV *FoundLHS = getSCEV(ICI->getOperand(0)); + const SCEV *FoundRHS = getSCEV(ICI->getOperand(1)); + + // Balance the types. The case where FoundLHS' type is wider than + // LHS' type is checked for above. + if (getTypeSizeInBits(LHS->getType()) > + getTypeSizeInBits(FoundLHS->getType())) { + if (CmpInst::isSigned(Pred)) { + FoundLHS = getSignExtendExpr(FoundLHS, LHS->getType()); + FoundRHS = getSignExtendExpr(FoundRHS, LHS->getType()); + } else { + FoundLHS = getZeroExtendExpr(FoundLHS, LHS->getType()); + FoundRHS = getZeroExtendExpr(FoundRHS, LHS->getType()); + } + } + + // Canonicalize the query to match the way instcombine will have + // canonicalized the comparison. + // First, put a constant operand on the right. + if (isa(LHS)) { + std::swap(LHS, RHS); + Pred = ICmpInst::getSwappedPredicate(Pred); + } + // Then, canonicalize comparisons with boundary cases. + if (const SCEVConstant *RC = dyn_cast(RHS)) { + const APInt &RA = RC->getValue()->getValue(); + switch (Pred) { + default: llvm_unreachable("Unexpected ICmpInst::Predicate value!"); + case ICmpInst::ICMP_EQ: + case ICmpInst::ICMP_NE: + break; + case ICmpInst::ICMP_UGE: + if ((RA - 1).isMinValue()) { + Pred = ICmpInst::ICMP_NE; + RHS = getConstant(RA - 1); + break; + } + if (RA.isMaxValue()) { + Pred = ICmpInst::ICMP_EQ; + break; + } + if (RA.isMinValue()) return true; + break; + case ICmpInst::ICMP_ULE: + if ((RA + 1).isMaxValue()) { + Pred = ICmpInst::ICMP_NE; + RHS = getConstant(RA + 1); + break; + } + if (RA.isMinValue()) { + Pred = ICmpInst::ICMP_EQ; + break; + } + if (RA.isMaxValue()) return true; + break; + case ICmpInst::ICMP_SGE: + if ((RA - 1).isMinSignedValue()) { + Pred = ICmpInst::ICMP_NE; + RHS = getConstant(RA - 1); + break; + } + if (RA.isMaxSignedValue()) { + Pred = ICmpInst::ICMP_EQ; + break; + } + if (RA.isMinSignedValue()) return true; + break; + case ICmpInst::ICMP_SLE: + if ((RA + 1).isMaxSignedValue()) { + Pred = ICmpInst::ICMP_NE; + RHS = getConstant(RA + 1); + break; + } + if (RA.isMinSignedValue()) { + Pred = ICmpInst::ICMP_EQ; + break; + } + if (RA.isMaxSignedValue()) return true; + break; + case ICmpInst::ICMP_UGT: + if (RA.isMinValue()) { + Pred = ICmpInst::ICMP_NE; + break; + } + if ((RA + 1).isMaxValue()) { + Pred = ICmpInst::ICMP_EQ; + RHS = getConstant(RA + 1); + break; + } + if (RA.isMaxValue()) return false; + break; + case ICmpInst::ICMP_ULT: + if (RA.isMaxValue()) { + Pred = ICmpInst::ICMP_NE; + break; + } + if ((RA - 1).isMinValue()) { + Pred = ICmpInst::ICMP_EQ; + RHS = getConstant(RA - 1); + break; + } + if (RA.isMinValue()) return false; + break; + case ICmpInst::ICMP_SGT: + if (RA.isMinSignedValue()) { + Pred = ICmpInst::ICMP_NE; + break; + } + if ((RA + 1).isMaxSignedValue()) { + Pred = ICmpInst::ICMP_EQ; + RHS = getConstant(RA + 1); + break; + } + if (RA.isMaxSignedValue()) return false; + break; + case ICmpInst::ICMP_SLT: + if (RA.isMaxSignedValue()) { + Pred = ICmpInst::ICMP_NE; + break; + } + if ((RA - 1).isMinSignedValue()) { + Pred = ICmpInst::ICMP_EQ; + RHS = getConstant(RA - 1); + break; + } + if (RA.isMinSignedValue()) return false; + break; + } + } + + // Check to see if we can make the LHS or RHS match. + if (LHS == FoundRHS || RHS == FoundLHS) { + if (isa(RHS)) { + std::swap(FoundLHS, FoundRHS); + FoundPred = ICmpInst::getSwappedPredicate(FoundPred); + } else { + std::swap(LHS, RHS); + Pred = ICmpInst::getSwappedPredicate(Pred); + } + } + + // Check whether the found predicate is the same as the desired predicate. + if (FoundPred == Pred) + return isImpliedCondOperands(Pred, LHS, RHS, FoundLHS, FoundRHS); + + // Check whether swapping the found predicate makes it the same as the + // desired predicate. + if (ICmpInst::getSwappedPredicate(FoundPred) == Pred) { + if (isa(RHS)) + return isImpliedCondOperands(Pred, LHS, RHS, FoundRHS, FoundLHS); + else + return isImpliedCondOperands(ICmpInst::getSwappedPredicate(Pred), + RHS, LHS, FoundLHS, FoundRHS); + } + + // Check whether the actual condition is beyond sufficient. + if (FoundPred == ICmpInst::ICMP_EQ) + if (ICmpInst::isTrueWhenEqual(Pred)) + if (isImpliedCondOperands(Pred, LHS, RHS, FoundLHS, FoundRHS)) + return true; + if (Pred == ICmpInst::ICMP_NE) + if (!ICmpInst::isTrueWhenEqual(FoundPred)) + if (isImpliedCondOperands(FoundPred, LHS, RHS, FoundLHS, FoundRHS)) + return true; + + // Otherwise assume the worst. + return false; +} + +/// isImpliedCondOperands - Test whether the condition described by Pred, +/// LHS, and RHS is true whenever the condition desribed by Pred, FoundLHS, +/// and FoundRHS is true. +bool ScalarEvolution::isImpliedCondOperands(ICmpInst::Predicate Pred, + const SCEV *LHS, const SCEV *RHS, + const SCEV *FoundLHS, + const SCEV *FoundRHS) { + return isImpliedCondOperandsHelper(Pred, LHS, RHS, + FoundLHS, FoundRHS) || + // ~x < ~y --> x > y + isImpliedCondOperandsHelper(Pred, LHS, RHS, + getNotSCEV(FoundRHS), + getNotSCEV(FoundLHS)); +} + +/// isImpliedCondOperandsHelper - Test whether the condition described by +/// Pred, LHS, and RHS is true whenever the condition desribed by Pred, +/// FoundLHS, and FoundRHS is true. +bool +ScalarEvolution::isImpliedCondOperandsHelper(ICmpInst::Predicate Pred, + const SCEV *LHS, const SCEV *RHS, + const SCEV *FoundLHS, + const SCEV *FoundRHS) { + switch (Pred) { + default: llvm_unreachable("Unexpected ICmpInst::Predicate value!"); + case ICmpInst::ICMP_EQ: + case ICmpInst::ICMP_NE: + if (HasSameValue(LHS, FoundLHS) && HasSameValue(RHS, FoundRHS)) + return true; + break; + case ICmpInst::ICMP_SLT: + case ICmpInst::ICMP_SLE: + if (isKnownPredicate(ICmpInst::ICMP_SLE, LHS, FoundLHS) && + isKnownPredicate(ICmpInst::ICMP_SGE, RHS, FoundRHS)) + return true; + break; + case ICmpInst::ICMP_SGT: + case ICmpInst::ICMP_SGE: + if (isKnownPredicate(ICmpInst::ICMP_SGE, LHS, FoundLHS) && + isKnownPredicate(ICmpInst::ICMP_SLE, RHS, FoundRHS)) + return true; + break; + case ICmpInst::ICMP_ULT: + case ICmpInst::ICMP_ULE: + if (isKnownPredicate(ICmpInst::ICMP_ULE, LHS, FoundLHS) && + isKnownPredicate(ICmpInst::ICMP_UGE, RHS, FoundRHS)) + return true; + break; + case ICmpInst::ICMP_UGT: + case ICmpInst::ICMP_UGE: + if (isKnownPredicate(ICmpInst::ICMP_UGE, LHS, FoundLHS) && + isKnownPredicate(ICmpInst::ICMP_ULE, RHS, FoundRHS)) + return true; + break; + } + + return false; +} + +/// getBECount - Subtract the end and start values and divide by the step, +/// rounding up, to get the number of times the backedge is executed. Return +/// CouldNotCompute if an intermediate computation overflows. +const SCEV *ScalarEvolution::getBECount(const SCEV *Start, + const SCEV *End, + const SCEV *Step, + bool NoWrap) { + const Type *Ty = Start->getType(); + const SCEV *NegOne = getIntegerSCEV(-1, Ty); + const SCEV *Diff = getMinusSCEV(End, Start); + const SCEV *RoundUp = getAddExpr(Step, NegOne); + + // Add an adjustment to the difference between End and Start so that + // the division will effectively round up. + const SCEV *Add = getAddExpr(Diff, RoundUp); + + if (!NoWrap) { + // Check Add for unsigned overflow. + // TODO: More sophisticated things could be done here. + const Type *WideTy = IntegerType::get(getContext(), + getTypeSizeInBits(Ty) + 1); + const SCEV *EDiff = getZeroExtendExpr(Diff, WideTy); + const SCEV *ERoundUp = getZeroExtendExpr(RoundUp, WideTy); + const SCEV *OperandExtendedAdd = getAddExpr(EDiff, ERoundUp); + if (getZeroExtendExpr(Add, WideTy) != OperandExtendedAdd) + return getCouldNotCompute(); + } + + return getUDivExpr(Add, Step); +} + +/// HowManyLessThans - Return the number of times a backedge containing the +/// specified less-than comparison will execute. If not computable, return +/// CouldNotCompute. +ScalarEvolution::BackedgeTakenInfo +ScalarEvolution::HowManyLessThans(const SCEV *LHS, const SCEV *RHS, + const Loop *L, bool isSigned) { + // Only handle: "ADDREC < LoopInvariant". + if (!RHS->isLoopInvariant(L)) return getCouldNotCompute(); + + const SCEVAddRecExpr *AddRec = dyn_cast(LHS); + if (!AddRec || AddRec->getLoop() != L) + return getCouldNotCompute(); + + // Check to see if we have a flag which makes analysis easy. + bool NoWrap = isSigned ? AddRec->hasNoSignedWrap() : + AddRec->hasNoUnsignedWrap(); + + if (AddRec->isAffine()) { + // FORNOW: We only support unit strides. + unsigned BitWidth = getTypeSizeInBits(AddRec->getType()); + const SCEV *Step = AddRec->getStepRecurrence(*this); + + // TODO: handle non-constant strides. + const SCEVConstant *CStep = dyn_cast(Step); + if (!CStep || CStep->isZero()) + return getCouldNotCompute(); + if (CStep->isOne()) { + // With unit stride, the iteration never steps past the limit value. + } else if (CStep->getValue()->getValue().isStrictlyPositive()) { + if (NoWrap) { + // We know the iteration won't step past the maximum value for its type. + ; + } else if (const SCEVConstant *CLimit = dyn_cast(RHS)) { + // Test whether a positive iteration iteration can step past the limit + // value and past the maximum value for its type in a single step. + if (isSigned) { + APInt Max = APInt::getSignedMaxValue(BitWidth); + if ((Max - CStep->getValue()->getValue()) + .slt(CLimit->getValue()->getValue())) + return getCouldNotCompute(); + } else { + APInt Max = APInt::getMaxValue(BitWidth); + if ((Max - CStep->getValue()->getValue()) + .ult(CLimit->getValue()->getValue())) + return getCouldNotCompute(); + } + } else + // TODO: handle non-constant limit values below. + return getCouldNotCompute(); + } else + // TODO: handle negative strides below. + return getCouldNotCompute(); + + // We know the LHS is of the form {n,+,s} and the RHS is some loop-invariant + // m. So, we count the number of iterations in which {n,+,s} < m is true. + // Note that we cannot simply return max(m-n,0)/s because it's not safe to + // treat m-n as signed nor unsigned due to overflow possibility. + + // First, we get the value of the LHS in the first iteration: n + const SCEV *Start = AddRec->getOperand(0); + + // Determine the minimum constant start value. + const SCEV *MinStart = getConstant(isSigned ? + getSignedRange(Start).getSignedMin() : + getUnsignedRange(Start).getUnsignedMin()); + + // If we know that the condition is true in order to enter the loop, + // then we know that it will run exactly (m-n)/s times. Otherwise, we + // only know that it will execute (max(m,n)-n)/s times. In both cases, + // the division must round up. + const SCEV *End = RHS; + if (!isLoopGuardedByCond(L, + isSigned ? ICmpInst::ICMP_SLT : + ICmpInst::ICMP_ULT, + getMinusSCEV(Start, Step), RHS)) + End = isSigned ? getSMaxExpr(RHS, Start) + : getUMaxExpr(RHS, Start); + + // Determine the maximum constant end value. + const SCEV *MaxEnd = getConstant(isSigned ? + getSignedRange(End).getSignedMax() : + getUnsignedRange(End).getUnsignedMax()); + + // Finally, we subtract these two values and divide, rounding up, to get + // the number of times the backedge is executed. + const SCEV *BECount = getBECount(Start, End, Step, NoWrap); + + // The maximum backedge count is similar, except using the minimum start + // value and the maximum end value. + const SCEV *MaxBECount = getBECount(MinStart, MaxEnd, Step, NoWrap); + + return BackedgeTakenInfo(BECount, MaxBECount); + } + + return getCouldNotCompute(); +} + +/// getNumIterationsInRange - Return the number of iterations of this loop that +/// produce values in the specified constant range. Another way of looking at +/// this is that it returns the first iteration number where the value is not in +/// the condition, thus computing the exit count. If the iteration count can't +/// be computed, an instance of SCEVCouldNotCompute is returned. +const SCEV *SCEVAddRecExpr::getNumIterationsInRange(ConstantRange Range, + ScalarEvolution &SE) const { + if (Range.isFullSet()) // Infinite loop. + return SE.getCouldNotCompute(); + + // If the start is a non-zero constant, shift the range to simplify things. + if (const SCEVConstant *SC = dyn_cast(getStart())) + if (!SC->getValue()->isZero()) { + SmallVector Operands(op_begin(), op_end()); + Operands[0] = SE.getIntegerSCEV(0, SC->getType()); + const SCEV *Shifted = SE.getAddRecExpr(Operands, getLoop()); + if (const SCEVAddRecExpr *ShiftedAddRec = + dyn_cast(Shifted)) + return ShiftedAddRec->getNumIterationsInRange( + Range.subtract(SC->getValue()->getValue()), SE); + // This is strange and shouldn't happen. + return SE.getCouldNotCompute(); + } + + // The only time we can solve this is when we have all constant indices. + // Otherwise, we cannot determine the overflow conditions. + for (unsigned i = 0, e = getNumOperands(); i != e; ++i) + if (!isa(getOperand(i))) + return SE.getCouldNotCompute(); + + + // Okay at this point we know that all elements of the chrec are constants and + // that the start element is zero. + + // First check to see if the range contains zero. If not, the first + // iteration exits. + unsigned BitWidth = SE.getTypeSizeInBits(getType()); + if (!Range.contains(APInt(BitWidth, 0))) + return SE.getIntegerSCEV(0, getType()); + + if (isAffine()) { + // If this is an affine expression then we have this situation: + // Solve {0,+,A} in Range === Ax in Range + + // We know that zero is in the range. If A is positive then we know that + // the upper value of the range must be the first possible exit value. + // If A is negative then the lower of the range is the last possible loop + // value. Also note that we already checked for a full range. + APInt One(BitWidth,1); + APInt A = cast(getOperand(1))->getValue()->getValue(); + APInt End = A.sge(One) ? (Range.getUpper() - One) : Range.getLower(); + + // The exit value should be (End+A)/A. + APInt ExitVal = (End + A).udiv(A); + ConstantInt *ExitValue = ConstantInt::get(SE.getContext(), ExitVal); + + // Evaluate at the exit value. If we really did fall out of the valid + // range, then we computed our trip count, otherwise wrap around or other + // things must have happened. + ConstantInt *Val = EvaluateConstantChrecAtConstant(this, ExitValue, SE); + if (Range.contains(Val->getValue())) + return SE.getCouldNotCompute(); // Something strange happened + + // Ensure that the previous value is in the range. This is a sanity check. + assert(Range.contains( + EvaluateConstantChrecAtConstant(this, + ConstantInt::get(SE.getContext(), ExitVal - One), SE)->getValue()) && + "Linear scev computation is off in a bad way!"); + return SE.getConstant(ExitValue); + } else if (isQuadratic()) { + // If this is a quadratic (3-term) AddRec {L,+,M,+,N}, find the roots of the + // quadratic equation to solve it. To do this, we must frame our problem in + // terms of figuring out when zero is crossed, instead of when + // Range.getUpper() is crossed. + SmallVector NewOps(op_begin(), op_end()); + NewOps[0] = SE.getNegativeSCEV(SE.getConstant(Range.getUpper())); + const SCEV *NewAddRec = SE.getAddRecExpr(NewOps, getLoop()); + + // Next, solve the constructed addrec + std::pair Roots = + SolveQuadraticEquation(cast(NewAddRec), SE); + const SCEVConstant *R1 = dyn_cast(Roots.first); + const SCEVConstant *R2 = dyn_cast(Roots.second); + if (R1) { + // Pick the smallest positive root value. + if (ConstantInt *CB = + dyn_cast(ConstantExpr::getICmp(ICmpInst::ICMP_ULT, + R1->getValue(), R2->getValue()))) { + if (CB->getZExtValue() == false) + std::swap(R1, R2); // R1 is the minimum root now. + + // Make sure the root is not off by one. The returned iteration should + // not be in the range, but the previous one should be. When solving + // for "X*X < 5", for example, we should not return a root of 2. + ConstantInt *R1Val = EvaluateConstantChrecAtConstant(this, + R1->getValue(), + SE); + if (Range.contains(R1Val->getValue())) { + // The next iteration must be out of the range... + ConstantInt *NextVal = + ConstantInt::get(SE.getContext(), R1->getValue()->getValue()+1); + + R1Val = EvaluateConstantChrecAtConstant(this, NextVal, SE); + if (!Range.contains(R1Val->getValue())) + return SE.getConstant(NextVal); + return SE.getCouldNotCompute(); // Something strange happened + } + + // If R1 was not in the range, then it is a good return value. Make + // sure that R1-1 WAS in the range though, just in case. + ConstantInt *NextVal = + ConstantInt::get(SE.getContext(), R1->getValue()->getValue()-1); + R1Val = EvaluateConstantChrecAtConstant(this, NextVal, SE); + if (Range.contains(R1Val->getValue())) + return R1; + return SE.getCouldNotCompute(); // Something strange happened + } + } + } + + return SE.getCouldNotCompute(); +} + + + +//===----------------------------------------------------------------------===// +// SCEVCallbackVH Class Implementation +//===----------------------------------------------------------------------===// + +void ScalarEvolution::SCEVCallbackVH::deleted() { + assert(SE && "SCEVCallbackVH called with a null ScalarEvolution!"); + if (PHINode *PN = dyn_cast(getValPtr())) + SE->ConstantEvolutionLoopExitValue.erase(PN); + SE->Scalars.erase(getValPtr()); + // this now dangles! +} + +void ScalarEvolution::SCEVCallbackVH::allUsesReplacedWith(Value *) { + assert(SE && "SCEVCallbackVH called with a null ScalarEvolution!"); + + // Forget all the expressions associated with users of the old value, + // so that future queries will recompute the expressions using the new + // value. + SmallVector Worklist; + SmallPtrSet Visited; + Value *Old = getValPtr(); + bool DeleteOld = false; + for (Value::use_iterator UI = Old->use_begin(), UE = Old->use_end(); + UI != UE; ++UI) + Worklist.push_back(*UI); + while (!Worklist.empty()) { + User *U = Worklist.pop_back_val(); + // Deleting the Old value will cause this to dangle. Postpone + // that until everything else is done. + if (U == Old) { + DeleteOld = true; + continue; + } + if (!Visited.insert(U)) + continue; + if (PHINode *PN = dyn_cast(U)) + SE->ConstantEvolutionLoopExitValue.erase(PN); + SE->Scalars.erase(U); + for (Value::use_iterator UI = U->use_begin(), UE = U->use_end(); + UI != UE; ++UI) + Worklist.push_back(*UI); + } + // Delete the Old value if it (indirectly) references itself. + if (DeleteOld) { + if (PHINode *PN = dyn_cast(Old)) + SE->ConstantEvolutionLoopExitValue.erase(PN); + SE->Scalars.erase(Old); + // this now dangles! + } + // this may dangle! +} + +ScalarEvolution::SCEVCallbackVH::SCEVCallbackVH(Value *V, ScalarEvolution *se) + : CallbackVH(V), SE(se) {} + +//===----------------------------------------------------------------------===// +// ScalarEvolution Class Implementation +//===----------------------------------------------------------------------===// + +ScalarEvolution::ScalarEvolution() + : FunctionPass(&ID) { +} + +bool ScalarEvolution::runOnFunction(Function &F) { + this->F = &F; + LI = &getAnalysis(); + TD = getAnalysisIfAvailable(); + return false; +} + +void ScalarEvolution::releaseMemory() { + Scalars.clear(); + BackedgeTakenCounts.clear(); + ConstantEvolutionLoopExitValue.clear(); + ValuesAtScopes.clear(); + UniqueSCEVs.clear(); + SCEVAllocator.Reset(); +} + +void ScalarEvolution::getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + AU.addRequiredTransitive(); +} + +bool ScalarEvolution::hasLoopInvariantBackedgeTakenCount(const Loop *L) { + return !isa(getBackedgeTakenCount(L)); +} + +static void PrintLoopInfo(raw_ostream &OS, ScalarEvolution *SE, + const Loop *L) { + // Print all inner loops first + for (Loop::iterator I = L->begin(), E = L->end(); I != E; ++I) + PrintLoopInfo(OS, SE, *I); + + OS << "Loop " << L->getHeader()->getName() << ": "; + + SmallVector ExitBlocks; + L->getExitBlocks(ExitBlocks); + if (ExitBlocks.size() != 1) + OS << " "; + + if (SE->hasLoopInvariantBackedgeTakenCount(L)) { + OS << "backedge-taken count is " << *SE->getBackedgeTakenCount(L); + } else { + OS << "Unpredictable backedge-taken count. "; + } + + OS << "\n"; + OS << "Loop " << L->getHeader()->getName() << ": "; + + if (!isa(SE->getMaxBackedgeTakenCount(L))) { + OS << "max backedge-taken count is " << *SE->getMaxBackedgeTakenCount(L); + } else { + OS << "Unpredictable max backedge-taken count. "; + } + + OS << "\n"; +} + +void ScalarEvolution::print(raw_ostream &OS, const Module* ) const { + // ScalarEvolution's implementaiton of the print method is to print + // out SCEV values of all instructions that are interesting. Doing + // this potentially causes it to create new SCEV objects though, + // which technically conflicts with the const qualifier. This isn't + // observable from outside the class though, so casting away the + // const isn't dangerous. + ScalarEvolution &SE = *const_cast(this); + + OS << "Classifying expressions for: " << F->getName() << "\n"; + for (inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I) + if (isSCEVable(I->getType())) { + OS << *I << '\n'; + OS << " --> "; + const SCEV *SV = SE.getSCEV(&*I); + SV->print(OS); + + const Loop *L = LI->getLoopFor((*I).getParent()); + + const SCEV *AtUse = SE.getSCEVAtScope(SV, L); + if (AtUse != SV) { + OS << " --> "; + AtUse->print(OS); + } + + if (L) { + OS << "\t\t" "Exits: "; + const SCEV *ExitValue = SE.getSCEVAtScope(SV, L->getParentLoop()); + if (!ExitValue->isLoopInvariant(L)) { + OS << "<>"; + } else { + OS << *ExitValue; + } + } + + OS << "\n"; + } + + OS << "Determining loop execution counts for: " << F->getName() << "\n"; + for (LoopInfo::iterator I = LI->begin(), E = LI->end(); I != E; ++I) + PrintLoopInfo(OS, &SE, *I); +} + diff --git a/libclamav/c++/llvm/lib/Analysis/ScalarEvolutionAliasAnalysis.cpp b/libclamav/c++/llvm/lib/Analysis/ScalarEvolutionAliasAnalysis.cpp new file mode 100644 index 000000000..ef0e97b6e --- /dev/null +++ b/libclamav/c++/llvm/lib/Analysis/ScalarEvolutionAliasAnalysis.cpp @@ -0,0 +1,129 @@ +//===- ScalarEvolutionAliasAnalysis.cpp - SCEV-based Alias Analysis -------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the ScalarEvolutionAliasAnalysis pass, which implements a +// simple alias analysis implemented in terms of ScalarEvolution queries. +// +// ScalarEvolution has a more complete understanding of pointer arithmetic +// than BasicAliasAnalysis' collection of ad-hoc analyses. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/Analysis/ScalarEvolutionExpressions.h" +#include "llvm/Analysis/Passes.h" +#include "llvm/Pass.h" +using namespace llvm; + +namespace { + /// ScalarEvolutionAliasAnalysis - This is a simple alias analysis + /// implementation that uses ScalarEvolution to answer queries. + class ScalarEvolutionAliasAnalysis : public FunctionPass, + public AliasAnalysis { + ScalarEvolution *SE; + + public: + static char ID; // Class identification, replacement for typeinfo + ScalarEvolutionAliasAnalysis() : FunctionPass(&ID), SE(0) {} + + private: + virtual void getAnalysisUsage(AnalysisUsage &AU) const; + virtual bool runOnFunction(Function &F); + virtual AliasResult alias(const Value *V1, unsigned V1Size, + const Value *V2, unsigned V2Size); + + Value *GetBaseValue(const SCEV *S); + }; +} // End of anonymous namespace + +// Register this pass... +char ScalarEvolutionAliasAnalysis::ID = 0; +static RegisterPass +X("scev-aa", "ScalarEvolution-based Alias Analysis", false, true); + +// Declare that we implement the AliasAnalysis interface +static RegisterAnalysisGroup Y(X); + +FunctionPass *llvm::createScalarEvolutionAliasAnalysisPass() { + return new ScalarEvolutionAliasAnalysis(); +} + +void +ScalarEvolutionAliasAnalysis::getAnalysisUsage(AnalysisUsage &AU) const { + AU.addRequiredTransitive(); + AU.setPreservesAll(); + AliasAnalysis::getAnalysisUsage(AU); +} + +bool +ScalarEvolutionAliasAnalysis::runOnFunction(Function &F) { + InitializeAliasAnalysis(this); + SE = &getAnalysis(); + return false; +} + +/// GetBaseValue - Given an expression, try to find a +/// base value. Return null is none was found. +Value * +ScalarEvolutionAliasAnalysis::GetBaseValue(const SCEV *S) { + if (const SCEVAddRecExpr *AR = dyn_cast(S)) { + // In an addrec, assume that the base will be in the start, rather + // than the step. + return GetBaseValue(AR->getStart()); + } else if (const SCEVAddExpr *A = dyn_cast(S)) { + // If there's a pointer operand, it'll be sorted at the end of the list. + const SCEV *Last = A->getOperand(A->getNumOperands()-1); + if (isa(Last->getType())) + return GetBaseValue(Last); + } else if (const SCEVUnknown *U = dyn_cast(S)) { + // This is a leaf node. + return U->getValue(); + } + // No Identified object found. + return 0; +} + +AliasAnalysis::AliasResult +ScalarEvolutionAliasAnalysis::alias(const Value *A, unsigned ASize, + const Value *B, unsigned BSize) { + // This is ScalarEvolutionAliasAnalysis. Get the SCEVs! + const SCEV *AS = SE->getSCEV(const_cast(A)); + const SCEV *BS = SE->getSCEV(const_cast(B)); + + // If they evaluate to the same expression, it's a MustAlias. + if (AS == BS) return MustAlias; + + // If something is known about the difference between the two addresses, + // see if it's enough to prove a NoAlias. + if (SE->getEffectiveSCEVType(AS->getType()) == + SE->getEffectiveSCEVType(BS->getType())) { + unsigned BitWidth = SE->getTypeSizeInBits(AS->getType()); + APInt AI(BitWidth, ASize); + const SCEV *BA = SE->getMinusSCEV(BS, AS); + if (AI.ule(SE->getUnsignedRange(BA).getUnsignedMin())) { + APInt BI(BitWidth, BSize); + const SCEV *AB = SE->getMinusSCEV(AS, BS); + if (BI.ule(SE->getUnsignedRange(AB).getUnsignedMin())) + return NoAlias; + } + } + + // If ScalarEvolution can find an underlying object, form a new query. + // The correctness of this depends on ScalarEvolution not recognizing + // inttoptr and ptrtoint operators. + Value *AO = GetBaseValue(AS); + Value *BO = GetBaseValue(BS); + if ((AO && AO != A) || (BO && BO != B)) + if (alias(AO ? AO : A, AO ? ~0u : ASize, + BO ? BO : B, BO ? ~0u : BSize) == NoAlias) + return NoAlias; + + // Forward the query to the next analysis. + return AliasAnalysis::alias(A, ASize, B, BSize); +} diff --git a/libclamav/c++/llvm/lib/Analysis/ScalarEvolutionExpander.cpp b/libclamav/c++/llvm/lib/Analysis/ScalarEvolutionExpander.cpp new file mode 100644 index 000000000..d674ee847 --- /dev/null +++ b/libclamav/c++/llvm/lib/Analysis/ScalarEvolutionExpander.cpp @@ -0,0 +1,888 @@ +//===- ScalarEvolutionExpander.cpp - Scalar Evolution Analysis --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the implementation of the scalar evolution expander, +// which is used to generate the code corresponding to a given scalar evolution +// expression. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Analysis/ScalarEvolutionExpander.h" +#include "llvm/Analysis/LoopInfo.h" +#include "llvm/LLVMContext.h" +#include "llvm/Target/TargetData.h" +#include "llvm/ADT/STLExtras.h" +using namespace llvm; + +/// InsertNoopCastOfTo - Insert a cast of V to the specified type, +/// which must be possible with a noop cast, doing what we can to share +/// the casts. +Value *SCEVExpander::InsertNoopCastOfTo(Value *V, const Type *Ty) { + Instruction::CastOps Op = CastInst::getCastOpcode(V, false, Ty, false); + assert((Op == Instruction::BitCast || + Op == Instruction::PtrToInt || + Op == Instruction::IntToPtr) && + "InsertNoopCastOfTo cannot perform non-noop casts!"); + assert(SE.getTypeSizeInBits(V->getType()) == SE.getTypeSizeInBits(Ty) && + "InsertNoopCastOfTo cannot change sizes!"); + + // Short-circuit unnecessary bitcasts. + if (Op == Instruction::BitCast && V->getType() == Ty) + return V; + + // Short-circuit unnecessary inttoptr<->ptrtoint casts. + if ((Op == Instruction::PtrToInt || Op == Instruction::IntToPtr) && + SE.getTypeSizeInBits(Ty) == SE.getTypeSizeInBits(V->getType())) { + if (CastInst *CI = dyn_cast(V)) + if ((CI->getOpcode() == Instruction::PtrToInt || + CI->getOpcode() == Instruction::IntToPtr) && + SE.getTypeSizeInBits(CI->getType()) == + SE.getTypeSizeInBits(CI->getOperand(0)->getType())) + return CI->getOperand(0); + if (ConstantExpr *CE = dyn_cast(V)) + if ((CE->getOpcode() == Instruction::PtrToInt || + CE->getOpcode() == Instruction::IntToPtr) && + SE.getTypeSizeInBits(CE->getType()) == + SE.getTypeSizeInBits(CE->getOperand(0)->getType())) + return CE->getOperand(0); + } + + if (Constant *C = dyn_cast(V)) + return ConstantExpr::getCast(Op, C, Ty); + + if (Argument *A = dyn_cast(V)) { + // Check to see if there is already a cast! + for (Value::use_iterator UI = A->use_begin(), E = A->use_end(); + UI != E; ++UI) + if ((*UI)->getType() == Ty) + if (CastInst *CI = dyn_cast(cast(*UI))) + if (CI->getOpcode() == Op) { + // If the cast isn't the first instruction of the function, move it. + if (BasicBlock::iterator(CI) != + A->getParent()->getEntryBlock().begin()) { + // Recreate the cast at the beginning of the entry block. + // The old cast is left in place in case it is being used + // as an insert point. + Instruction *NewCI = + CastInst::Create(Op, V, Ty, "", + A->getParent()->getEntryBlock().begin()); + NewCI->takeName(CI); + CI->replaceAllUsesWith(NewCI); + return NewCI; + } + return CI; + } + + Instruction *I = CastInst::Create(Op, V, Ty, V->getName(), + A->getParent()->getEntryBlock().begin()); + InsertedValues.insert(I); + return I; + } + + Instruction *I = cast(V); + + // Check to see if there is already a cast. If there is, use it. + for (Value::use_iterator UI = I->use_begin(), E = I->use_end(); + UI != E; ++UI) { + if ((*UI)->getType() == Ty) + if (CastInst *CI = dyn_cast(cast(*UI))) + if (CI->getOpcode() == Op) { + BasicBlock::iterator It = I; ++It; + if (isa(I)) + It = cast(I)->getNormalDest()->begin(); + while (isa(It)) ++It; + if (It != BasicBlock::iterator(CI)) { + // Recreate the cast at the beginning of the entry block. + // The old cast is left in place in case it is being used + // as an insert point. + Instruction *NewCI = CastInst::Create(Op, V, Ty, "", It); + NewCI->takeName(CI); + CI->replaceAllUsesWith(NewCI); + return NewCI; + } + return CI; + } + } + BasicBlock::iterator IP = I; ++IP; + if (InvokeInst *II = dyn_cast(I)) + IP = II->getNormalDest()->begin(); + while (isa(IP)) ++IP; + Instruction *CI = CastInst::Create(Op, V, Ty, V->getName(), IP); + InsertedValues.insert(CI); + return CI; +} + +/// InsertBinop - Insert the specified binary operator, doing a small amount +/// of work to avoid inserting an obviously redundant operation. +Value *SCEVExpander::InsertBinop(Instruction::BinaryOps Opcode, + Value *LHS, Value *RHS) { + // Fold a binop with constant operands. + if (Constant *CLHS = dyn_cast(LHS)) + if (Constant *CRHS = dyn_cast(RHS)) + return ConstantExpr::get(Opcode, CLHS, CRHS); + + // Do a quick scan to see if we have this binop nearby. If so, reuse it. + unsigned ScanLimit = 6; + BasicBlock::iterator BlockBegin = Builder.GetInsertBlock()->begin(); + // Scanning starts from the last instruction before the insertion point. + BasicBlock::iterator IP = Builder.GetInsertPoint(); + if (IP != BlockBegin) { + --IP; + for (; ScanLimit; --IP, --ScanLimit) { + if (IP->getOpcode() == (unsigned)Opcode && IP->getOperand(0) == LHS && + IP->getOperand(1) == RHS) + return IP; + if (IP == BlockBegin) break; + } + } + + // If we haven't found this binop, insert it. + Value *BO = Builder.CreateBinOp(Opcode, LHS, RHS, "tmp"); + InsertedValues.insert(BO); + return BO; +} + +/// FactorOutConstant - Test if S is divisible by Factor, using signed +/// division. If so, update S with Factor divided out and return true. +/// S need not be evenly divisble if a reasonable remainder can be +/// computed. +/// TODO: When ScalarEvolution gets a SCEVSDivExpr, this can be made +/// unnecessary; in its place, just signed-divide Ops[i] by the scale and +/// check to see if the divide was folded. +static bool FactorOutConstant(const SCEV *&S, + const SCEV *&Remainder, + const SCEV *Factor, + ScalarEvolution &SE, + const TargetData *TD) { + // Everything is divisible by one. + if (Factor->isOne()) + return true; + + // x/x == 1. + if (S == Factor) { + S = SE.getIntegerSCEV(1, S->getType()); + return true; + } + + // For a Constant, check for a multiple of the given factor. + if (const SCEVConstant *C = dyn_cast(S)) { + // 0/x == 0. + if (C->isZero()) + return true; + // Check for divisibility. + if (const SCEVConstant *FC = dyn_cast(Factor)) { + ConstantInt *CI = + ConstantInt::get(SE.getContext(), + C->getValue()->getValue().sdiv( + FC->getValue()->getValue())); + // If the quotient is zero and the remainder is non-zero, reject + // the value at this scale. It will be considered for subsequent + // smaller scales. + if (!CI->isZero()) { + const SCEV *Div = SE.getConstant(CI); + S = Div; + Remainder = + SE.getAddExpr(Remainder, + SE.getConstant(C->getValue()->getValue().srem( + FC->getValue()->getValue()))); + return true; + } + } + } + + // In a Mul, check if there is a constant operand which is a multiple + // of the given factor. + if (const SCEVMulExpr *M = dyn_cast(S)) { + if (TD) { + // With TargetData, the size is known. Check if there is a constant + // operand which is a multiple of the given factor. If so, we can + // factor it. + const SCEVConstant *FC = cast(Factor); + if (const SCEVConstant *C = dyn_cast(M->getOperand(0))) + if (!C->getValue()->getValue().srem(FC->getValue()->getValue())) { + const SmallVectorImpl &MOperands = M->getOperands(); + SmallVector NewMulOps(MOperands.begin(), + MOperands.end()); + NewMulOps[0] = + SE.getConstant(C->getValue()->getValue().sdiv( + FC->getValue()->getValue())); + S = SE.getMulExpr(NewMulOps); + return true; + } + } else { + // Without TargetData, check if Factor can be factored out of any of the + // Mul's operands. If so, we can just remove it. + for (unsigned i = 0, e = M->getNumOperands(); i != e; ++i) { + const SCEV *SOp = M->getOperand(i); + const SCEV *Remainder = SE.getIntegerSCEV(0, SOp->getType()); + if (FactorOutConstant(SOp, Remainder, Factor, SE, TD) && + Remainder->isZero()) { + const SmallVectorImpl &MOperands = M->getOperands(); + SmallVector NewMulOps(MOperands.begin(), + MOperands.end()); + NewMulOps[i] = SOp; + S = SE.getMulExpr(NewMulOps); + return true; + } + } + } + } + + // In an AddRec, check if both start and step are divisible. + if (const SCEVAddRecExpr *A = dyn_cast(S)) { + const SCEV *Step = A->getStepRecurrence(SE); + const SCEV *StepRem = SE.getIntegerSCEV(0, Step->getType()); + if (!FactorOutConstant(Step, StepRem, Factor, SE, TD)) + return false; + if (!StepRem->isZero()) + return false; + const SCEV *Start = A->getStart(); + if (!FactorOutConstant(Start, Remainder, Factor, SE, TD)) + return false; + S = SE.getAddRecExpr(Start, Step, A->getLoop()); + return true; + } + + return false; +} + +/// SimplifyAddOperands - Sort and simplify a list of add operands. NumAddRecs +/// is the number of SCEVAddRecExprs present, which are kept at the end of +/// the list. +/// +static void SimplifyAddOperands(SmallVectorImpl &Ops, + const Type *Ty, + ScalarEvolution &SE) { + unsigned NumAddRecs = 0; + for (unsigned i = Ops.size(); i > 0 && isa(Ops[i-1]); --i) + ++NumAddRecs; + // Group Ops into non-addrecs and addrecs. + SmallVector NoAddRecs(Ops.begin(), Ops.end() - NumAddRecs); + SmallVector AddRecs(Ops.end() - NumAddRecs, Ops.end()); + // Let ScalarEvolution sort and simplify the non-addrecs list. + const SCEV *Sum = NoAddRecs.empty() ? + SE.getIntegerSCEV(0, Ty) : + SE.getAddExpr(NoAddRecs); + // If it returned an add, use the operands. Otherwise it simplified + // the sum into a single value, so just use that. + if (const SCEVAddExpr *Add = dyn_cast(Sum)) + Ops = Add->getOperands(); + else { + Ops.clear(); + if (!Sum->isZero()) + Ops.push_back(Sum); + } + // Then append the addrecs. + Ops.insert(Ops.end(), AddRecs.begin(), AddRecs.end()); +} + +/// SplitAddRecs - Flatten a list of add operands, moving addrec start values +/// out to the top level. For example, convert {a + b,+,c} to a, b, {0,+,d}. +/// This helps expose more opportunities for folding parts of the expressions +/// into GEP indices. +/// +static void SplitAddRecs(SmallVectorImpl &Ops, + const Type *Ty, + ScalarEvolution &SE) { + // Find the addrecs. + SmallVector AddRecs; + for (unsigned i = 0, e = Ops.size(); i != e; ++i) + while (const SCEVAddRecExpr *A = dyn_cast(Ops[i])) { + const SCEV *Start = A->getStart(); + if (Start->isZero()) break; + const SCEV *Zero = SE.getIntegerSCEV(0, Ty); + AddRecs.push_back(SE.getAddRecExpr(Zero, + A->getStepRecurrence(SE), + A->getLoop())); + if (const SCEVAddExpr *Add = dyn_cast(Start)) { + Ops[i] = Zero; + Ops.insert(Ops.end(), Add->op_begin(), Add->op_end()); + e += Add->getNumOperands(); + } else { + Ops[i] = Start; + } + } + if (!AddRecs.empty()) { + // Add the addrecs onto the end of the list. + Ops.insert(Ops.end(), AddRecs.begin(), AddRecs.end()); + // Resort the operand list, moving any constants to the front. + SimplifyAddOperands(Ops, Ty, SE); + } +} + +/// expandAddToGEP - Expand an addition expression with a pointer type into +/// a GEP instead of using ptrtoint+arithmetic+inttoptr. This helps +/// BasicAliasAnalysis and other passes analyze the result. See the rules +/// for getelementptr vs. inttoptr in +/// http://llvm.org/docs/LangRef.html#pointeraliasing +/// for details. +/// +/// Design note: The correctness of using getelmeentptr here depends on +/// ScalarEvolution not recognizing inttoptr and ptrtoint operators, as +/// they may introduce pointer arithmetic which may not be safely converted +/// into getelementptr. +/// +/// Design note: It might seem desirable for this function to be more +/// loop-aware. If some of the indices are loop-invariant while others +/// aren't, it might seem desirable to emit multiple GEPs, keeping the +/// loop-invariant portions of the overall computation outside the loop. +/// However, there are a few reasons this is not done here. Hoisting simple +/// arithmetic is a low-level optimization that often isn't very +/// important until late in the optimization process. In fact, passes +/// like InstructionCombining will combine GEPs, even if it means +/// pushing loop-invariant computation down into loops, so even if the +/// GEPs were split here, the work would quickly be undone. The +/// LoopStrengthReduction pass, which is usually run quite late (and +/// after the last InstructionCombining pass), takes care of hoisting +/// loop-invariant portions of expressions, after considering what +/// can be folded using target addressing modes. +/// +Value *SCEVExpander::expandAddToGEP(const SCEV *const *op_begin, + const SCEV *const *op_end, + const PointerType *PTy, + const Type *Ty, + Value *V) { + const Type *ElTy = PTy->getElementType(); + SmallVector GepIndices; + SmallVector Ops(op_begin, op_end); + bool AnyNonZeroIndices = false; + + // Split AddRecs up into parts as either of the parts may be usable + // without the other. + SplitAddRecs(Ops, Ty, SE); + + // Decend down the pointer's type and attempt to convert the other + // operands into GEP indices, at each level. The first index in a GEP + // indexes into the array implied by the pointer operand; the rest of + // the indices index into the element or field type selected by the + // preceding index. + for (;;) { + const SCEV *ElSize = SE.getAllocSizeExpr(ElTy); + // If the scale size is not 0, attempt to factor out a scale for + // array indexing. + SmallVector ScaledOps; + if (ElTy->isSized() && !ElSize->isZero()) { + SmallVector NewOps; + for (unsigned i = 0, e = Ops.size(); i != e; ++i) { + const SCEV *Op = Ops[i]; + const SCEV *Remainder = SE.getIntegerSCEV(0, Ty); + if (FactorOutConstant(Op, Remainder, ElSize, SE, SE.TD)) { + // Op now has ElSize factored out. + ScaledOps.push_back(Op); + if (!Remainder->isZero()) + NewOps.push_back(Remainder); + AnyNonZeroIndices = true; + } else { + // The operand was not divisible, so add it to the list of operands + // we'll scan next iteration. + NewOps.push_back(Ops[i]); + } + } + // If we made any changes, update Ops. + if (!ScaledOps.empty()) { + Ops = NewOps; + SimplifyAddOperands(Ops, Ty, SE); + } + } + + // Record the scaled array index for this level of the type. If + // we didn't find any operands that could be factored, tentatively + // assume that element zero was selected (since the zero offset + // would obviously be folded away). + Value *Scaled = ScaledOps.empty() ? + Constant::getNullValue(Ty) : + expandCodeFor(SE.getAddExpr(ScaledOps), Ty); + GepIndices.push_back(Scaled); + + // Collect struct field index operands. + while (const StructType *STy = dyn_cast(ElTy)) { + bool FoundFieldNo = false; + // An empty struct has no fields. + if (STy->getNumElements() == 0) break; + if (SE.TD) { + // With TargetData, field offsets are known. See if a constant offset + // falls within any of the struct fields. + if (Ops.empty()) break; + if (const SCEVConstant *C = dyn_cast(Ops[0])) + if (SE.getTypeSizeInBits(C->getType()) <= 64) { + const StructLayout &SL = *SE.TD->getStructLayout(STy); + uint64_t FullOffset = C->getValue()->getZExtValue(); + if (FullOffset < SL.getSizeInBytes()) { + unsigned ElIdx = SL.getElementContainingOffset(FullOffset); + GepIndices.push_back( + ConstantInt::get(Type::getInt32Ty(Ty->getContext()), ElIdx)); + ElTy = STy->getTypeAtIndex(ElIdx); + Ops[0] = + SE.getConstant(Ty, FullOffset - SL.getElementOffset(ElIdx)); + AnyNonZeroIndices = true; + FoundFieldNo = true; + } + } + } else { + // Without TargetData, just check for a SCEVFieldOffsetExpr of the + // appropriate struct type. + for (unsigned i = 0, e = Ops.size(); i != e; ++i) + if (const SCEVFieldOffsetExpr *FO = + dyn_cast(Ops[i])) + if (FO->getStructType() == STy) { + unsigned FieldNo = FO->getFieldNo(); + GepIndices.push_back( + ConstantInt::get(Type::getInt32Ty(Ty->getContext()), + FieldNo)); + ElTy = STy->getTypeAtIndex(FieldNo); + Ops[i] = SE.getConstant(Ty, 0); + AnyNonZeroIndices = true; + FoundFieldNo = true; + break; + } + } + // If no struct field offsets were found, tentatively assume that + // field zero was selected (since the zero offset would obviously + // be folded away). + if (!FoundFieldNo) { + ElTy = STy->getTypeAtIndex(0u); + GepIndices.push_back( + Constant::getNullValue(Type::getInt32Ty(Ty->getContext()))); + } + } + + if (const ArrayType *ATy = dyn_cast(ElTy)) + ElTy = ATy->getElementType(); + else + break; + } + + // If none of the operands were convertable to proper GEP indices, cast + // the base to i8* and do an ugly getelementptr with that. It's still + // better than ptrtoint+arithmetic+inttoptr at least. + if (!AnyNonZeroIndices) { + // Cast the base to i8*. + V = InsertNoopCastOfTo(V, + Type::getInt8PtrTy(Ty->getContext(), PTy->getAddressSpace())); + + // Expand the operands for a plain byte offset. + Value *Idx = expandCodeFor(SE.getAddExpr(Ops), Ty); + + // Fold a GEP with constant operands. + if (Constant *CLHS = dyn_cast(V)) + if (Constant *CRHS = dyn_cast(Idx)) + return ConstantExpr::getGetElementPtr(CLHS, &CRHS, 1); + + // Do a quick scan to see if we have this GEP nearby. If so, reuse it. + unsigned ScanLimit = 6; + BasicBlock::iterator BlockBegin = Builder.GetInsertBlock()->begin(); + // Scanning starts from the last instruction before the insertion point. + BasicBlock::iterator IP = Builder.GetInsertPoint(); + if (IP != BlockBegin) { + --IP; + for (; ScanLimit; --IP, --ScanLimit) { + if (IP->getOpcode() == Instruction::GetElementPtr && + IP->getOperand(0) == V && IP->getOperand(1) == Idx) + return IP; + if (IP == BlockBegin) break; + } + } + + // Emit a GEP. + Value *GEP = Builder.CreateGEP(V, Idx, "uglygep"); + InsertedValues.insert(GEP); + return GEP; + } + + // Insert a pretty getelementptr. Note that this GEP is not marked inbounds, + // because ScalarEvolution may have changed the address arithmetic to + // compute a value which is beyond the end of the allocated object. + Value *GEP = Builder.CreateGEP(V, + GepIndices.begin(), + GepIndices.end(), + "scevgep"); + Ops.push_back(SE.getUnknown(GEP)); + InsertedValues.insert(GEP); + return expand(SE.getAddExpr(Ops)); +} + +Value *SCEVExpander::visitAddExpr(const SCEVAddExpr *S) { + int NumOperands = S->getNumOperands(); + const Type *Ty = SE.getEffectiveSCEVType(S->getType()); + + // Find the index of an operand to start with. Choose the operand with + // pointer type, if there is one, or the last operand otherwise. + int PIdx = 0; + for (; PIdx != NumOperands - 1; ++PIdx) + if (isa(S->getOperand(PIdx)->getType())) break; + + // Expand code for the operand that we chose. + Value *V = expand(S->getOperand(PIdx)); + + // Turn things like ptrtoint+arithmetic+inttoptr into GEP. See the + // comments on expandAddToGEP for details. + if (const PointerType *PTy = dyn_cast(V->getType())) { + // Take the operand at PIdx out of the list. + const SmallVectorImpl &Ops = S->getOperands(); + SmallVector NewOps; + NewOps.insert(NewOps.end(), Ops.begin(), Ops.begin() + PIdx); + NewOps.insert(NewOps.end(), Ops.begin() + PIdx + 1, Ops.end()); + // Make a GEP. + return expandAddToGEP(NewOps.begin(), NewOps.end(), PTy, Ty, V); + } + + // Otherwise, we'll expand the rest of the SCEVAddExpr as plain integer + // arithmetic. + V = InsertNoopCastOfTo(V, Ty); + + // Emit a bunch of add instructions + for (int i = NumOperands-1; i >= 0; --i) { + if (i == PIdx) continue; + Value *W = expandCodeFor(S->getOperand(i), Ty); + V = InsertBinop(Instruction::Add, V, W); + } + return V; +} + +Value *SCEVExpander::visitMulExpr(const SCEVMulExpr *S) { + const Type *Ty = SE.getEffectiveSCEVType(S->getType()); + int FirstOp = 0; // Set if we should emit a subtract. + if (const SCEVConstant *SC = dyn_cast(S->getOperand(0))) + if (SC->getValue()->isAllOnesValue()) + FirstOp = 1; + + int i = S->getNumOperands()-2; + Value *V = expandCodeFor(S->getOperand(i+1), Ty); + + // Emit a bunch of multiply instructions + for (; i >= FirstOp; --i) { + Value *W = expandCodeFor(S->getOperand(i), Ty); + V = InsertBinop(Instruction::Mul, V, W); + } + + // -1 * ... ---> 0 - ... + if (FirstOp == 1) + V = InsertBinop(Instruction::Sub, Constant::getNullValue(Ty), V); + return V; +} + +Value *SCEVExpander::visitUDivExpr(const SCEVUDivExpr *S) { + const Type *Ty = SE.getEffectiveSCEVType(S->getType()); + + Value *LHS = expandCodeFor(S->getLHS(), Ty); + if (const SCEVConstant *SC = dyn_cast(S->getRHS())) { + const APInt &RHS = SC->getValue()->getValue(); + if (RHS.isPowerOf2()) + return InsertBinop(Instruction::LShr, LHS, + ConstantInt::get(Ty, RHS.logBase2())); + } + + Value *RHS = expandCodeFor(S->getRHS(), Ty); + return InsertBinop(Instruction::UDiv, LHS, RHS); +} + +/// Move parts of Base into Rest to leave Base with the minimal +/// expression that provides a pointer operand suitable for a +/// GEP expansion. +static void ExposePointerBase(const SCEV *&Base, const SCEV *&Rest, + ScalarEvolution &SE) { + while (const SCEVAddRecExpr *A = dyn_cast(Base)) { + Base = A->getStart(); + Rest = SE.getAddExpr(Rest, + SE.getAddRecExpr(SE.getIntegerSCEV(0, A->getType()), + A->getStepRecurrence(SE), + A->getLoop())); + } + if (const SCEVAddExpr *A = dyn_cast(Base)) { + Base = A->getOperand(A->getNumOperands()-1); + SmallVector NewAddOps(A->op_begin(), A->op_end()); + NewAddOps.back() = Rest; + Rest = SE.getAddExpr(NewAddOps); + ExposePointerBase(Base, Rest, SE); + } +} + +Value *SCEVExpander::visitAddRecExpr(const SCEVAddRecExpr *S) { + const Type *Ty = SE.getEffectiveSCEVType(S->getType()); + const Loop *L = S->getLoop(); + + // First check for an existing canonical IV in a suitable type. + PHINode *CanonicalIV = 0; + if (PHINode *PN = L->getCanonicalInductionVariable()) + if (SE.isSCEVable(PN->getType()) && + isa(SE.getEffectiveSCEVType(PN->getType())) && + SE.getTypeSizeInBits(PN->getType()) >= SE.getTypeSizeInBits(Ty)) + CanonicalIV = PN; + + // Rewrite an AddRec in terms of the canonical induction variable, if + // its type is more narrow. + if (CanonicalIV && + SE.getTypeSizeInBits(CanonicalIV->getType()) > + SE.getTypeSizeInBits(Ty)) { + const SmallVectorImpl &Ops = S->getOperands(); + SmallVector NewOps(Ops.size()); + for (unsigned i = 0, e = Ops.size(); i != e; ++i) + NewOps[i] = SE.getAnyExtendExpr(Ops[i], CanonicalIV->getType()); + Value *V = expand(SE.getAddRecExpr(NewOps, S->getLoop())); + BasicBlock *SaveInsertBB = Builder.GetInsertBlock(); + BasicBlock::iterator SaveInsertPt = Builder.GetInsertPoint(); + BasicBlock::iterator NewInsertPt = + next(BasicBlock::iterator(cast(V))); + while (isa(NewInsertPt)) ++NewInsertPt; + V = expandCodeFor(SE.getTruncateExpr(SE.getUnknown(V), Ty), 0, + NewInsertPt); + Builder.SetInsertPoint(SaveInsertBB, SaveInsertPt); + return V; + } + + // {X,+,F} --> X + {0,+,F} + if (!S->getStart()->isZero()) { + const SmallVectorImpl &SOperands = S->getOperands(); + SmallVector NewOps(SOperands.begin(), SOperands.end()); + NewOps[0] = SE.getIntegerSCEV(0, Ty); + const SCEV *Rest = SE.getAddRecExpr(NewOps, L); + + // Turn things like ptrtoint+arithmetic+inttoptr into GEP. See the + // comments on expandAddToGEP for details. + const SCEV *Base = S->getStart(); + const SCEV *RestArray[1] = { Rest }; + // Dig into the expression to find the pointer base for a GEP. + ExposePointerBase(Base, RestArray[0], SE); + // If we found a pointer, expand the AddRec with a GEP. + if (const PointerType *PTy = dyn_cast(Base->getType())) { + // Make sure the Base isn't something exotic, such as a multiplied + // or divided pointer value. In those cases, the result type isn't + // actually a pointer type. + if (!isa(Base) && !isa(Base)) { + Value *StartV = expand(Base); + assert(StartV->getType() == PTy && "Pointer type mismatch for GEP!"); + return expandAddToGEP(RestArray, RestArray+1, PTy, Ty, StartV); + } + } + + // Just do a normal add. Pre-expand the operands to suppress folding. + return expand(SE.getAddExpr(SE.getUnknown(expand(S->getStart())), + SE.getUnknown(expand(Rest)))); + } + + // {0,+,1} --> Insert a canonical induction variable into the loop! + if (S->isAffine() && + S->getOperand(1) == SE.getIntegerSCEV(1, Ty)) { + // If there's a canonical IV, just use it. + if (CanonicalIV) { + assert(Ty == SE.getEffectiveSCEVType(CanonicalIV->getType()) && + "IVs with types different from the canonical IV should " + "already have been handled!"); + return CanonicalIV; + } + + // Create and insert the PHI node for the induction variable in the + // specified loop. + BasicBlock *Header = L->getHeader(); + PHINode *PN = PHINode::Create(Ty, "indvar", Header->begin()); + InsertedValues.insert(PN); + + Constant *One = ConstantInt::get(Ty, 1); + for (pred_iterator HPI = pred_begin(Header), HPE = pred_end(Header); + HPI != HPE; ++HPI) + if (L->contains(*HPI)) { + // Insert a unit add instruction right before the terminator corresponding + // to the back-edge. + Instruction *Add = BinaryOperator::CreateAdd(PN, One, "indvar.next", + (*HPI)->getTerminator()); + InsertedValues.insert(Add); + PN->addIncoming(Add, *HPI); + } else { + PN->addIncoming(Constant::getNullValue(Ty), *HPI); + } + } + + // {0,+,F} --> {0,+,1} * F + // Get the canonical induction variable I for this loop. + Value *I = CanonicalIV ? + CanonicalIV : + getOrInsertCanonicalInductionVariable(L, Ty); + + // If this is a simple linear addrec, emit it now as a special case. + if (S->isAffine()) // {0,+,F} --> i*F + return + expand(SE.getTruncateOrNoop( + SE.getMulExpr(SE.getUnknown(I), + SE.getNoopOrAnyExtend(S->getOperand(1), + I->getType())), + Ty)); + + // If this is a chain of recurrences, turn it into a closed form, using the + // folders, then expandCodeFor the closed form. This allows the folders to + // simplify the expression without having to build a bunch of special code + // into this folder. + const SCEV *IH = SE.getUnknown(I); // Get I as a "symbolic" SCEV. + + // Promote S up to the canonical IV type, if the cast is foldable. + const SCEV *NewS = S; + const SCEV *Ext = SE.getNoopOrAnyExtend(S, I->getType()); + if (isa(Ext)) + NewS = Ext; + + const SCEV *V = cast(NewS)->evaluateAtIteration(IH, SE); + //cerr << "Evaluated: " << *this << "\n to: " << *V << "\n"; + + // Truncate the result down to the original type, if needed. + const SCEV *T = SE.getTruncateOrNoop(V, Ty); + return expand(T); +} + +Value *SCEVExpander::visitTruncateExpr(const SCEVTruncateExpr *S) { + const Type *Ty = SE.getEffectiveSCEVType(S->getType()); + Value *V = expandCodeFor(S->getOperand(), + SE.getEffectiveSCEVType(S->getOperand()->getType())); + Value *I = Builder.CreateTrunc(V, Ty, "tmp"); + InsertedValues.insert(I); + return I; +} + +Value *SCEVExpander::visitZeroExtendExpr(const SCEVZeroExtendExpr *S) { + const Type *Ty = SE.getEffectiveSCEVType(S->getType()); + Value *V = expandCodeFor(S->getOperand(), + SE.getEffectiveSCEVType(S->getOperand()->getType())); + Value *I = Builder.CreateZExt(V, Ty, "tmp"); + InsertedValues.insert(I); + return I; +} + +Value *SCEVExpander::visitSignExtendExpr(const SCEVSignExtendExpr *S) { + const Type *Ty = SE.getEffectiveSCEVType(S->getType()); + Value *V = expandCodeFor(S->getOperand(), + SE.getEffectiveSCEVType(S->getOperand()->getType())); + Value *I = Builder.CreateSExt(V, Ty, "tmp"); + InsertedValues.insert(I); + return I; +} + +Value *SCEVExpander::visitSMaxExpr(const SCEVSMaxExpr *S) { + Value *LHS = expand(S->getOperand(S->getNumOperands()-1)); + const Type *Ty = LHS->getType(); + for (int i = S->getNumOperands()-2; i >= 0; --i) { + // In the case of mixed integer and pointer types, do the + // rest of the comparisons as integer. + if (S->getOperand(i)->getType() != Ty) { + Ty = SE.getEffectiveSCEVType(Ty); + LHS = InsertNoopCastOfTo(LHS, Ty); + } + Value *RHS = expandCodeFor(S->getOperand(i), Ty); + Value *ICmp = Builder.CreateICmpSGT(LHS, RHS, "tmp"); + InsertedValues.insert(ICmp); + Value *Sel = Builder.CreateSelect(ICmp, LHS, RHS, "smax"); + InsertedValues.insert(Sel); + LHS = Sel; + } + // In the case of mixed integer and pointer types, cast the + // final result back to the pointer type. + if (LHS->getType() != S->getType()) + LHS = InsertNoopCastOfTo(LHS, S->getType()); + return LHS; +} + +Value *SCEVExpander::visitUMaxExpr(const SCEVUMaxExpr *S) { + Value *LHS = expand(S->getOperand(S->getNumOperands()-1)); + const Type *Ty = LHS->getType(); + for (int i = S->getNumOperands()-2; i >= 0; --i) { + // In the case of mixed integer and pointer types, do the + // rest of the comparisons as integer. + if (S->getOperand(i)->getType() != Ty) { + Ty = SE.getEffectiveSCEVType(Ty); + LHS = InsertNoopCastOfTo(LHS, Ty); + } + Value *RHS = expandCodeFor(S->getOperand(i), Ty); + Value *ICmp = Builder.CreateICmpUGT(LHS, RHS, "tmp"); + InsertedValues.insert(ICmp); + Value *Sel = Builder.CreateSelect(ICmp, LHS, RHS, "umax"); + InsertedValues.insert(Sel); + LHS = Sel; + } + // In the case of mixed integer and pointer types, cast the + // final result back to the pointer type. + if (LHS->getType() != S->getType()) + LHS = InsertNoopCastOfTo(LHS, S->getType()); + return LHS; +} + +Value *SCEVExpander::visitFieldOffsetExpr(const SCEVFieldOffsetExpr *S) { + return ConstantExpr::getOffsetOf(S->getStructType(), S->getFieldNo()); +} + +Value *SCEVExpander::visitAllocSizeExpr(const SCEVAllocSizeExpr *S) { + return ConstantExpr::getSizeOf(S->getAllocType()); +} + +Value *SCEVExpander::expandCodeFor(const SCEV *SH, const Type *Ty) { + // Expand the code for this SCEV. + Value *V = expand(SH); + if (Ty) { + assert(SE.getTypeSizeInBits(Ty) == SE.getTypeSizeInBits(SH->getType()) && + "non-trivial casts should be done with the SCEVs directly!"); + V = InsertNoopCastOfTo(V, Ty); + } + return V; +} + +Value *SCEVExpander::expand(const SCEV *S) { + // Compute an insertion point for this SCEV object. Hoist the instructions + // as far out in the loop nest as possible. + Instruction *InsertPt = Builder.GetInsertPoint(); + for (Loop *L = SE.LI->getLoopFor(Builder.GetInsertBlock()); ; + L = L->getParentLoop()) + if (S->isLoopInvariant(L)) { + if (!L) break; + if (BasicBlock *Preheader = L->getLoopPreheader()) + InsertPt = Preheader->getTerminator(); + } else { + // If the SCEV is computable at this level, insert it into the header + // after the PHIs (and after any other instructions that we've inserted + // there) so that it is guaranteed to dominate any user inside the loop. + if (L && S->hasComputableLoopEvolution(L)) + InsertPt = L->getHeader()->getFirstNonPHI(); + while (isInsertedInstruction(InsertPt)) + InsertPt = next(BasicBlock::iterator(InsertPt)); + break; + } + + // Check to see if we already expanded this here. + std::map, + AssertingVH >::iterator I = + InsertedExpressions.find(std::make_pair(S, InsertPt)); + if (I != InsertedExpressions.end()) + return I->second; + + BasicBlock *SaveInsertBB = Builder.GetInsertBlock(); + BasicBlock::iterator SaveInsertPt = Builder.GetInsertPoint(); + Builder.SetInsertPoint(InsertPt->getParent(), InsertPt); + + // Expand the expression into instructions. + Value *V = visit(S); + + // Remember the expanded value for this SCEV at this location. + InsertedExpressions[std::make_pair(S, InsertPt)] = V; + + Builder.SetInsertPoint(SaveInsertBB, SaveInsertPt); + return V; +} + +/// getOrInsertCanonicalInductionVariable - This method returns the +/// canonical induction variable of the specified type for the specified +/// loop (inserting one if there is none). A canonical induction variable +/// starts at zero and steps by one on each iteration. +Value * +SCEVExpander::getOrInsertCanonicalInductionVariable(const Loop *L, + const Type *Ty) { + assert(Ty->isInteger() && "Can only insert integer induction variables!"); + const SCEV *H = SE.getAddRecExpr(SE.getIntegerSCEV(0, Ty), + SE.getIntegerSCEV(1, Ty), L); + BasicBlock *SaveInsertBB = Builder.GetInsertBlock(); + BasicBlock::iterator SaveInsertPt = Builder.GetInsertPoint(); + Value *V = expandCodeFor(H, 0, L->getHeader()->begin()); + if (SaveInsertBB) + Builder.SetInsertPoint(SaveInsertBB, SaveInsertPt); + return V; +} diff --git a/libclamav/c++/llvm/lib/Analysis/SparsePropagation.cpp b/libclamav/c++/llvm/lib/Analysis/SparsePropagation.cpp new file mode 100644 index 000000000..d7bcac2b1 --- /dev/null +++ b/libclamav/c++/llvm/lib/Analysis/SparsePropagation.cpp @@ -0,0 +1,348 @@ +//===- SparsePropagation.cpp - Sparse Conditional Property Propagation ----===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements an abstract sparse conditional propagation algorithm, +// modeled after SCCP, but with a customizable lattice function. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "sparseprop" +#include "llvm/Analysis/SparsePropagation.h" +#include "llvm/Constants.h" +#include "llvm/Function.h" +#include "llvm/Instructions.h" +#include "llvm/LLVMContext.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +//===----------------------------------------------------------------------===// +// AbstractLatticeFunction Implementation +//===----------------------------------------------------------------------===// + +AbstractLatticeFunction::~AbstractLatticeFunction() {} + +/// PrintValue - Render the specified lattice value to the specified stream. +void AbstractLatticeFunction::PrintValue(LatticeVal V, raw_ostream &OS) { + if (V == UndefVal) + OS << "undefined"; + else if (V == OverdefinedVal) + OS << "overdefined"; + else if (V == UntrackedVal) + OS << "untracked"; + else + OS << "unknown lattice value"; +} + +//===----------------------------------------------------------------------===// +// SparseSolver Implementation +//===----------------------------------------------------------------------===// + +/// getOrInitValueState - Return the LatticeVal object that corresponds to the +/// value, initializing the value's state if it hasn't been entered into the +/// map yet. This function is necessary because not all values should start +/// out in the underdefined state... Arguments should be overdefined, and +/// constants should be marked as constants. +/// +SparseSolver::LatticeVal SparseSolver::getOrInitValueState(Value *V) { + DenseMap::iterator I = ValueState.find(V); + if (I != ValueState.end()) return I->second; // Common case, in the map + + LatticeVal LV; + if (LatticeFunc->IsUntrackedValue(V)) + return LatticeFunc->getUntrackedVal(); + else if (Constant *C = dyn_cast(V)) + LV = LatticeFunc->ComputeConstant(C); + else if (Argument *A = dyn_cast(V)) + LV = LatticeFunc->ComputeArgument(A); + else if (!isa(V)) + // All other non-instructions are overdefined. + LV = LatticeFunc->getOverdefinedVal(); + else + // All instructions are underdefined by default. + LV = LatticeFunc->getUndefVal(); + + // If this value is untracked, don't add it to the map. + if (LV == LatticeFunc->getUntrackedVal()) + return LV; + return ValueState[V] = LV; +} + +/// UpdateState - When the state for some instruction is potentially updated, +/// this function notices and adds I to the worklist if needed. +void SparseSolver::UpdateState(Instruction &Inst, LatticeVal V) { + DenseMap::iterator I = ValueState.find(&Inst); + if (I != ValueState.end() && I->second == V) + return; // No change. + + // An update. Visit uses of I. + ValueState[&Inst] = V; + InstWorkList.push_back(&Inst); +} + +/// MarkBlockExecutable - This method can be used by clients to mark all of +/// the blocks that are known to be intrinsically live in the processed unit. +void SparseSolver::MarkBlockExecutable(BasicBlock *BB) { + DEBUG(errs() << "Marking Block Executable: " << BB->getName() << "\n"); + BBExecutable.insert(BB); // Basic block is executable! + BBWorkList.push_back(BB); // Add the block to the work list! +} + +/// markEdgeExecutable - Mark a basic block as executable, adding it to the BB +/// work list if it is not already executable... +void SparseSolver::markEdgeExecutable(BasicBlock *Source, BasicBlock *Dest) { + if (!KnownFeasibleEdges.insert(Edge(Source, Dest)).second) + return; // This edge is already known to be executable! + + DEBUG(errs() << "Marking Edge Executable: " << Source->getName() + << " -> " << Dest->getName() << "\n"); + + if (BBExecutable.count(Dest)) { + // The destination is already executable, but we just made an edge + // feasible that wasn't before. Revisit the PHI nodes in the block + // because they have potentially new operands. + for (BasicBlock::iterator I = Dest->begin(); isa(I); ++I) + visitPHINode(*cast(I)); + + } else { + MarkBlockExecutable(Dest); + } +} + + +/// getFeasibleSuccessors - Return a vector of booleans to indicate which +/// successors are reachable from a given terminator instruction. +void SparseSolver::getFeasibleSuccessors(TerminatorInst &TI, + SmallVectorImpl &Succs, + bool AggressiveUndef) { + Succs.resize(TI.getNumSuccessors()); + if (TI.getNumSuccessors() == 0) return; + + if (BranchInst *BI = dyn_cast(&TI)) { + if (BI->isUnconditional()) { + Succs[0] = true; + return; + } + + LatticeVal BCValue; + if (AggressiveUndef) + BCValue = getOrInitValueState(BI->getCondition()); + else + BCValue = getLatticeState(BI->getCondition()); + + if (BCValue == LatticeFunc->getOverdefinedVal() || + BCValue == LatticeFunc->getUntrackedVal()) { + // Overdefined condition variables can branch either way. + Succs[0] = Succs[1] = true; + return; + } + + // If undefined, neither is feasible yet. + if (BCValue == LatticeFunc->getUndefVal()) + return; + + Constant *C = LatticeFunc->GetConstant(BCValue, BI->getCondition(), *this); + if (C == 0 || !isa(C)) { + // Non-constant values can go either way. + Succs[0] = Succs[1] = true; + return; + } + + // Constant condition variables mean the branch can only go a single way + Succs[C == ConstantInt::getFalse(*Context)] = true; + return; + } + + if (isa(TI)) { + // Invoke instructions successors are always executable. + // TODO: Could ask the lattice function if the value can throw. + Succs[0] = Succs[1] = true; + return; + } + + if (isa(TI)) { + Succs.assign(Succs.size(), true); + return; + } + + SwitchInst &SI = cast(TI); + LatticeVal SCValue; + if (AggressiveUndef) + SCValue = getOrInitValueState(SI.getCondition()); + else + SCValue = getLatticeState(SI.getCondition()); + + if (SCValue == LatticeFunc->getOverdefinedVal() || + SCValue == LatticeFunc->getUntrackedVal()) { + // All destinations are executable! + Succs.assign(TI.getNumSuccessors(), true); + return; + } + + // If undefined, neither is feasible yet. + if (SCValue == LatticeFunc->getUndefVal()) + return; + + Constant *C = LatticeFunc->GetConstant(SCValue, SI.getCondition(), *this); + if (C == 0 || !isa(C)) { + // All destinations are executable! + Succs.assign(TI.getNumSuccessors(), true); + return; + } + + Succs[SI.findCaseValue(cast(C))] = true; +} + + +/// isEdgeFeasible - Return true if the control flow edge from the 'From' +/// basic block to the 'To' basic block is currently feasible... +bool SparseSolver::isEdgeFeasible(BasicBlock *From, BasicBlock *To, + bool AggressiveUndef) { + SmallVector SuccFeasible; + TerminatorInst *TI = From->getTerminator(); + getFeasibleSuccessors(*TI, SuccFeasible, AggressiveUndef); + + for (unsigned i = 0, e = TI->getNumSuccessors(); i != e; ++i) + if (TI->getSuccessor(i) == To && SuccFeasible[i]) + return true; + + return false; +} + +void SparseSolver::visitTerminatorInst(TerminatorInst &TI) { + SmallVector SuccFeasible; + getFeasibleSuccessors(TI, SuccFeasible, true); + + BasicBlock *BB = TI.getParent(); + + // Mark all feasible successors executable... + for (unsigned i = 0, e = SuccFeasible.size(); i != e; ++i) + if (SuccFeasible[i]) + markEdgeExecutable(BB, TI.getSuccessor(i)); +} + +void SparseSolver::visitPHINode(PHINode &PN) { + // The lattice function may store more information on a PHINode than could be + // computed from its incoming values. For example, SSI form stores its sigma + // functions as PHINodes with a single incoming value. + if (LatticeFunc->IsSpecialCasedPHI(&PN)) { + LatticeVal IV = LatticeFunc->ComputeInstructionState(PN, *this); + if (IV != LatticeFunc->getUntrackedVal()) + UpdateState(PN, IV); + return; + } + + LatticeVal PNIV = getOrInitValueState(&PN); + LatticeVal Overdefined = LatticeFunc->getOverdefinedVal(); + + // If this value is already overdefined (common) just return. + if (PNIV == Overdefined || PNIV == LatticeFunc->getUntrackedVal()) + return; // Quick exit + + // Super-extra-high-degree PHI nodes are unlikely to ever be interesting, + // and slow us down a lot. Just mark them overdefined. + if (PN.getNumIncomingValues() > 64) { + UpdateState(PN, Overdefined); + return; + } + + // Look at all of the executable operands of the PHI node. If any of them + // are overdefined, the PHI becomes overdefined as well. Otherwise, ask the + // transfer function to give us the merge of the incoming values. + for (unsigned i = 0, e = PN.getNumIncomingValues(); i != e; ++i) { + // If the edge is not yet known to be feasible, it doesn't impact the PHI. + if (!isEdgeFeasible(PN.getIncomingBlock(i), PN.getParent(), true)) + continue; + + // Merge in this value. + LatticeVal OpVal = getOrInitValueState(PN.getIncomingValue(i)); + if (OpVal != PNIV) + PNIV = LatticeFunc->MergeValues(PNIV, OpVal); + + if (PNIV == Overdefined) + break; // Rest of input values don't matter. + } + + // Update the PHI with the compute value, which is the merge of the inputs. + UpdateState(PN, PNIV); +} + + +void SparseSolver::visitInst(Instruction &I) { + // PHIs are handled by the propagation logic, they are never passed into the + // transfer functions. + if (PHINode *PN = dyn_cast(&I)) + return visitPHINode(*PN); + + // Otherwise, ask the transfer function what the result is. If this is + // something that we care about, remember it. + LatticeVal IV = LatticeFunc->ComputeInstructionState(I, *this); + if (IV != LatticeFunc->getUntrackedVal()) + UpdateState(I, IV); + + if (TerminatorInst *TI = dyn_cast(&I)) + visitTerminatorInst(*TI); +} + +void SparseSolver::Solve(Function &F) { + MarkBlockExecutable(&F.getEntryBlock()); + + // Process the work lists until they are empty! + while (!BBWorkList.empty() || !InstWorkList.empty()) { + // Process the instruction work list. + while (!InstWorkList.empty()) { + Instruction *I = InstWorkList.back(); + InstWorkList.pop_back(); + + DEBUG(errs() << "\nPopped off I-WL: " << *I << "\n"); + + // "I" got into the work list because it made a transition. See if any + // users are both live and in need of updating. + for (Value::use_iterator UI = I->use_begin(), E = I->use_end(); + UI != E; ++UI) { + Instruction *U = cast(*UI); + if (BBExecutable.count(U->getParent())) // Inst is executable? + visitInst(*U); + } + } + + // Process the basic block work list. + while (!BBWorkList.empty()) { + BasicBlock *BB = BBWorkList.back(); + BBWorkList.pop_back(); + + DEBUG(errs() << "\nPopped off BBWL: " << *BB); + + // Notify all instructions in this basic block that they are newly + // executable. + for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ++I) + visitInst(*I); + } + } +} + +void SparseSolver::Print(Function &F, raw_ostream &OS) const { + OS << "\nFUNCTION: " << F.getNameStr() << "\n"; + for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB) { + if (!BBExecutable.count(BB)) + OS << "INFEASIBLE: "; + OS << "\t"; + if (BB->hasName()) + OS << BB->getNameStr() << ":\n"; + else + OS << "; anon bb\n"; + for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ++I) { + LatticeFunc->PrintValue(getLatticeState(I), OS); + OS << *I << "\n"; + } + + OS << "\n"; + } +} + diff --git a/libclamav/c++/llvm/lib/Analysis/Trace.cpp b/libclamav/c++/llvm/lib/Analysis/Trace.cpp new file mode 100644 index 000000000..c9b303b48 --- /dev/null +++ b/libclamav/c++/llvm/lib/Analysis/Trace.cpp @@ -0,0 +1,50 @@ +//===- Trace.cpp - Implementation of Trace class --------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This class represents a single trace of LLVM basic blocks. A trace is a +// single entry, multiple exit, region of code that is often hot. Trace-based +// optimizations treat traces almost like they are a large, strange, basic +// block: because the trace path is assumed to be hot, optimizations for the +// fall-through path are made at the expense of the non-fall-through paths. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Analysis/Trace.h" +#include "llvm/Function.h" +#include "llvm/Assembly/Writer.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +Function *Trace::getFunction() const { + return getEntryBasicBlock()->getParent(); +} + +Module *Trace::getModule() const { + return getFunction()->getParent(); +} + +/// print - Write trace to output stream. +/// +void Trace::print(raw_ostream &O) const { + Function *F = getFunction(); + O << "; Trace from function " << F->getNameStr() << ", blocks:\n"; + for (const_iterator i = begin(), e = end(); i != e; ++i) { + O << "; "; + WriteAsOperand(O, *i, true, getModule()); + O << "\n"; + } + O << "; Trace parent function: \n" << *F; +} + +/// dump - Debugger convenience method; writes trace to standard error +/// output stream. +/// +void Trace::dump() const { + print(errs()); +} diff --git a/libclamav/c++/llvm/lib/Analysis/ValueTracking.cpp b/libclamav/c++/llvm/lib/Analysis/ValueTracking.cpp new file mode 100644 index 000000000..3e6af58aa --- /dev/null +++ b/libclamav/c++/llvm/lib/Analysis/ValueTracking.cpp @@ -0,0 +1,1415 @@ +//===- ValueTracking.cpp - Walk computations to compute properties --------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains routines that help analyze properties that chains of +// computations have. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Analysis/ValueTracking.h" +#include "llvm/Constants.h" +#include "llvm/Instructions.h" +#include "llvm/GlobalVariable.h" +#include "llvm/GlobalAlias.h" +#include "llvm/IntrinsicInst.h" +#include "llvm/LLVMContext.h" +#include "llvm/Operator.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Support/GetElementPtrTypeIterator.h" +#include "llvm/Support/MathExtras.h" +#include +using namespace llvm; + +/// ComputeMaskedBits - Determine which of the bits specified in Mask are +/// known to be either zero or one and return them in the KnownZero/KnownOne +/// bit sets. This code only analyzes bits in Mask, in order to short-circuit +/// processing. +/// NOTE: we cannot consider 'undef' to be "IsZero" here. The problem is that +/// we cannot optimize based on the assumption that it is zero without changing +/// it to be an explicit zero. If we don't change it to zero, other code could +/// optimized based on the contradictory assumption that it is non-zero. +/// Because instcombine aggressively folds operations with undef args anyway, +/// this won't lose us code quality. +/// +/// This function is defined on values with integer type, values with pointer +/// type (but only if TD is non-null), and vectors of integers. In the case +/// where V is a vector, the mask, known zero, and known one values are the +/// same width as the vector element, and the bit is set only if it is true +/// for all of the elements in the vector. +void llvm::ComputeMaskedBits(Value *V, const APInt &Mask, + APInt &KnownZero, APInt &KnownOne, + const TargetData *TD, unsigned Depth) { + const unsigned MaxDepth = 6; + assert(V && "No Value?"); + assert(Depth <= MaxDepth && "Limit Search Depth"); + unsigned BitWidth = Mask.getBitWidth(); + assert((V->getType()->isIntOrIntVector() || isa(V->getType())) && + "Not integer or pointer type!"); + assert((!TD || + TD->getTypeSizeInBits(V->getType()->getScalarType()) == BitWidth) && + (!V->getType()->isIntOrIntVector() || + V->getType()->getScalarSizeInBits() == BitWidth) && + KnownZero.getBitWidth() == BitWidth && + KnownOne.getBitWidth() == BitWidth && + "V, Mask, KnownOne and KnownZero should have same BitWidth"); + + if (ConstantInt *CI = dyn_cast(V)) { + // We know all of the bits for a constant! + KnownOne = CI->getValue() & Mask; + KnownZero = ~KnownOne & Mask; + return; + } + // Null and aggregate-zero are all-zeros. + if (isa(V) || + isa(V)) { + KnownOne.clear(); + KnownZero = Mask; + return; + } + // Handle a constant vector by taking the intersection of the known bits of + // each element. + if (ConstantVector *CV = dyn_cast(V)) { + KnownZero.set(); KnownOne.set(); + for (unsigned i = 0, e = CV->getNumOperands(); i != e; ++i) { + APInt KnownZero2(BitWidth, 0), KnownOne2(BitWidth, 0); + ComputeMaskedBits(CV->getOperand(i), Mask, KnownZero2, KnownOne2, + TD, Depth); + KnownZero &= KnownZero2; + KnownOne &= KnownOne2; + } + return; + } + // The address of an aligned GlobalValue has trailing zeros. + if (GlobalValue *GV = dyn_cast(V)) { + unsigned Align = GV->getAlignment(); + if (Align == 0 && TD && GV->getType()->getElementType()->isSized()) { + const Type *ObjectType = GV->getType()->getElementType(); + // If the object is defined in the current Module, we'll be giving + // it the preferred alignment. Otherwise, we have to assume that it + // may only have the minimum ABI alignment. + if (!GV->isDeclaration() && !GV->mayBeOverridden()) + Align = TD->getPrefTypeAlignment(ObjectType); + else + Align = TD->getABITypeAlignment(ObjectType); + } + if (Align > 0) + KnownZero = Mask & APInt::getLowBitsSet(BitWidth, + CountTrailingZeros_32(Align)); + else + KnownZero.clear(); + KnownOne.clear(); + return; + } + // A weak GlobalAlias is totally unknown. A non-weak GlobalAlias has + // the bits of its aliasee. + if (GlobalAlias *GA = dyn_cast(V)) { + if (GA->mayBeOverridden()) { + KnownZero.clear(); KnownOne.clear(); + } else { + ComputeMaskedBits(GA->getAliasee(), Mask, KnownZero, KnownOne, + TD, Depth+1); + } + return; + } + + KnownZero.clear(); KnownOne.clear(); // Start out not knowing anything. + + if (Depth == MaxDepth || Mask == 0) + return; // Limit search depth. + + Operator *I = dyn_cast(V); + if (!I) return; + + APInt KnownZero2(KnownZero), KnownOne2(KnownOne); + switch (I->getOpcode()) { + default: break; + case Instruction::And: { + // If either the LHS or the RHS are Zero, the result is zero. + ComputeMaskedBits(I->getOperand(1), Mask, KnownZero, KnownOne, TD, Depth+1); + APInt Mask2(Mask & ~KnownZero); + ComputeMaskedBits(I->getOperand(0), Mask2, KnownZero2, KnownOne2, TD, + Depth+1); + assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?"); + assert((KnownZero2 & KnownOne2) == 0 && "Bits known to be one AND zero?"); + + // Output known-1 bits are only known if set in both the LHS & RHS. + KnownOne &= KnownOne2; + // Output known-0 are known to be clear if zero in either the LHS | RHS. + KnownZero |= KnownZero2; + return; + } + case Instruction::Or: { + ComputeMaskedBits(I->getOperand(1), Mask, KnownZero, KnownOne, TD, Depth+1); + APInt Mask2(Mask & ~KnownOne); + ComputeMaskedBits(I->getOperand(0), Mask2, KnownZero2, KnownOne2, TD, + Depth+1); + assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?"); + assert((KnownZero2 & KnownOne2) == 0 && "Bits known to be one AND zero?"); + + // Output known-0 bits are only known if clear in both the LHS & RHS. + KnownZero &= KnownZero2; + // Output known-1 are known to be set if set in either the LHS | RHS. + KnownOne |= KnownOne2; + return; + } + case Instruction::Xor: { + ComputeMaskedBits(I->getOperand(1), Mask, KnownZero, KnownOne, TD, Depth+1); + ComputeMaskedBits(I->getOperand(0), Mask, KnownZero2, KnownOne2, TD, + Depth+1); + assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?"); + assert((KnownZero2 & KnownOne2) == 0 && "Bits known to be one AND zero?"); + + // Output known-0 bits are known if clear or set in both the LHS & RHS. + APInt KnownZeroOut = (KnownZero & KnownZero2) | (KnownOne & KnownOne2); + // Output known-1 are known to be set if set in only one of the LHS, RHS. + KnownOne = (KnownZero & KnownOne2) | (KnownOne & KnownZero2); + KnownZero = KnownZeroOut; + return; + } + case Instruction::Mul: { + APInt Mask2 = APInt::getAllOnesValue(BitWidth); + ComputeMaskedBits(I->getOperand(1), Mask2, KnownZero, KnownOne, TD,Depth+1); + ComputeMaskedBits(I->getOperand(0), Mask2, KnownZero2, KnownOne2, TD, + Depth+1); + assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?"); + assert((KnownZero2 & KnownOne2) == 0 && "Bits known to be one AND zero?"); + + // If low bits are zero in either operand, output low known-0 bits. + // Also compute a conserative estimate for high known-0 bits. + // More trickiness is possible, but this is sufficient for the + // interesting case of alignment computation. + KnownOne.clear(); + unsigned TrailZ = KnownZero.countTrailingOnes() + + KnownZero2.countTrailingOnes(); + unsigned LeadZ = std::max(KnownZero.countLeadingOnes() + + KnownZero2.countLeadingOnes(), + BitWidth) - BitWidth; + + TrailZ = std::min(TrailZ, BitWidth); + LeadZ = std::min(LeadZ, BitWidth); + KnownZero = APInt::getLowBitsSet(BitWidth, TrailZ) | + APInt::getHighBitsSet(BitWidth, LeadZ); + KnownZero &= Mask; + return; + } + case Instruction::UDiv: { + // For the purposes of computing leading zeros we can conservatively + // treat a udiv as a logical right shift by the power of 2 known to + // be less than the denominator. + APInt AllOnes = APInt::getAllOnesValue(BitWidth); + ComputeMaskedBits(I->getOperand(0), + AllOnes, KnownZero2, KnownOne2, TD, Depth+1); + unsigned LeadZ = KnownZero2.countLeadingOnes(); + + KnownOne2.clear(); + KnownZero2.clear(); + ComputeMaskedBits(I->getOperand(1), + AllOnes, KnownZero2, KnownOne2, TD, Depth+1); + unsigned RHSUnknownLeadingOnes = KnownOne2.countLeadingZeros(); + if (RHSUnknownLeadingOnes != BitWidth) + LeadZ = std::min(BitWidth, + LeadZ + BitWidth - RHSUnknownLeadingOnes - 1); + + KnownZero = APInt::getHighBitsSet(BitWidth, LeadZ) & Mask; + return; + } + case Instruction::Select: + ComputeMaskedBits(I->getOperand(2), Mask, KnownZero, KnownOne, TD, Depth+1); + ComputeMaskedBits(I->getOperand(1), Mask, KnownZero2, KnownOne2, TD, + Depth+1); + assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?"); + assert((KnownZero2 & KnownOne2) == 0 && "Bits known to be one AND zero?"); + + // Only known if known in both the LHS and RHS. + KnownOne &= KnownOne2; + KnownZero &= KnownZero2; + return; + case Instruction::FPTrunc: + case Instruction::FPExt: + case Instruction::FPToUI: + case Instruction::FPToSI: + case Instruction::SIToFP: + case Instruction::UIToFP: + return; // Can't work with floating point. + case Instruction::PtrToInt: + case Instruction::IntToPtr: + // We can't handle these if we don't know the pointer size. + if (!TD) return; + // FALL THROUGH and handle them the same as zext/trunc. + case Instruction::ZExt: + case Instruction::Trunc: { + const Type *SrcTy = I->getOperand(0)->getType(); + + unsigned SrcBitWidth; + // Note that we handle pointer operands here because of inttoptr/ptrtoint + // which fall through here. + if (isa(SrcTy)) + SrcBitWidth = TD->getTypeSizeInBits(SrcTy); + else + SrcBitWidth = SrcTy->getScalarSizeInBits(); + + APInt MaskIn(Mask); + MaskIn.zextOrTrunc(SrcBitWidth); + KnownZero.zextOrTrunc(SrcBitWidth); + KnownOne.zextOrTrunc(SrcBitWidth); + ComputeMaskedBits(I->getOperand(0), MaskIn, KnownZero, KnownOne, TD, + Depth+1); + KnownZero.zextOrTrunc(BitWidth); + KnownOne.zextOrTrunc(BitWidth); + // Any top bits are known to be zero. + if (BitWidth > SrcBitWidth) + KnownZero |= APInt::getHighBitsSet(BitWidth, BitWidth - SrcBitWidth); + return; + } + case Instruction::BitCast: { + const Type *SrcTy = I->getOperand(0)->getType(); + if ((SrcTy->isInteger() || isa(SrcTy)) && + // TODO: For now, not handling conversions like: + // (bitcast i64 %x to <2 x i32>) + !isa(I->getType())) { + ComputeMaskedBits(I->getOperand(0), Mask, KnownZero, KnownOne, TD, + Depth+1); + return; + } + break; + } + case Instruction::SExt: { + // Compute the bits in the result that are not present in the input. + unsigned SrcBitWidth = I->getOperand(0)->getType()->getScalarSizeInBits(); + + APInt MaskIn(Mask); + MaskIn.trunc(SrcBitWidth); + KnownZero.trunc(SrcBitWidth); + KnownOne.trunc(SrcBitWidth); + ComputeMaskedBits(I->getOperand(0), MaskIn, KnownZero, KnownOne, TD, + Depth+1); + assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?"); + KnownZero.zext(BitWidth); + KnownOne.zext(BitWidth); + + // If the sign bit of the input is known set or clear, then we know the + // top bits of the result. + if (KnownZero[SrcBitWidth-1]) // Input sign bit known zero + KnownZero |= APInt::getHighBitsSet(BitWidth, BitWidth - SrcBitWidth); + else if (KnownOne[SrcBitWidth-1]) // Input sign bit known set + KnownOne |= APInt::getHighBitsSet(BitWidth, BitWidth - SrcBitWidth); + return; + } + case Instruction::Shl: + // (shl X, C1) & C2 == 0 iff (X & C2 >>u C1) == 0 + if (ConstantInt *SA = dyn_cast(I->getOperand(1))) { + uint64_t ShiftAmt = SA->getLimitedValue(BitWidth); + APInt Mask2(Mask.lshr(ShiftAmt)); + ComputeMaskedBits(I->getOperand(0), Mask2, KnownZero, KnownOne, TD, + Depth+1); + assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?"); + KnownZero <<= ShiftAmt; + KnownOne <<= ShiftAmt; + KnownZero |= APInt::getLowBitsSet(BitWidth, ShiftAmt); // low bits known 0 + return; + } + break; + case Instruction::LShr: + // (ushr X, C1) & C2 == 0 iff (-1 >> C1) & C2 == 0 + if (ConstantInt *SA = dyn_cast(I->getOperand(1))) { + // Compute the new bits that are at the top now. + uint64_t ShiftAmt = SA->getLimitedValue(BitWidth); + + // Unsigned shift right. + APInt Mask2(Mask.shl(ShiftAmt)); + ComputeMaskedBits(I->getOperand(0), Mask2, KnownZero,KnownOne, TD, + Depth+1); + assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?"); + KnownZero = APIntOps::lshr(KnownZero, ShiftAmt); + KnownOne = APIntOps::lshr(KnownOne, ShiftAmt); + // high bits known zero. + KnownZero |= APInt::getHighBitsSet(BitWidth, ShiftAmt); + return; + } + break; + case Instruction::AShr: + // (ashr X, C1) & C2 == 0 iff (-1 >> C1) & C2 == 0 + if (ConstantInt *SA = dyn_cast(I->getOperand(1))) { + // Compute the new bits that are at the top now. + uint64_t ShiftAmt = SA->getLimitedValue(BitWidth); + + // Signed shift right. + APInt Mask2(Mask.shl(ShiftAmt)); + ComputeMaskedBits(I->getOperand(0), Mask2, KnownZero, KnownOne, TD, + Depth+1); + assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?"); + KnownZero = APIntOps::lshr(KnownZero, ShiftAmt); + KnownOne = APIntOps::lshr(KnownOne, ShiftAmt); + + APInt HighBits(APInt::getHighBitsSet(BitWidth, ShiftAmt)); + if (KnownZero[BitWidth-ShiftAmt-1]) // New bits are known zero. + KnownZero |= HighBits; + else if (KnownOne[BitWidth-ShiftAmt-1]) // New bits are known one. + KnownOne |= HighBits; + return; + } + break; + case Instruction::Sub: { + if (ConstantInt *CLHS = dyn_cast(I->getOperand(0))) { + // We know that the top bits of C-X are clear if X contains less bits + // than C (i.e. no wrap-around can happen). For example, 20-X is + // positive if we can prove that X is >= 0 and < 16. + if (!CLHS->getValue().isNegative()) { + unsigned NLZ = (CLHS->getValue()+1).countLeadingZeros(); + // NLZ can't be BitWidth with no sign bit + APInt MaskV = APInt::getHighBitsSet(BitWidth, NLZ+1); + ComputeMaskedBits(I->getOperand(1), MaskV, KnownZero2, KnownOne2, + TD, Depth+1); + + // If all of the MaskV bits are known to be zero, then we know the + // output top bits are zero, because we now know that the output is + // from [0-C]. + if ((KnownZero2 & MaskV) == MaskV) { + unsigned NLZ2 = CLHS->getValue().countLeadingZeros(); + // Top bits known zero. + KnownZero = APInt::getHighBitsSet(BitWidth, NLZ2) & Mask; + } + } + } + } + // fall through + case Instruction::Add: { + // If one of the operands has trailing zeros, then the bits that the + // other operand has in those bit positions will be preserved in the + // result. For an add, this works with either operand. For a subtract, + // this only works if the known zeros are in the right operand. + APInt LHSKnownZero(BitWidth, 0), LHSKnownOne(BitWidth, 0); + APInt Mask2 = APInt::getLowBitsSet(BitWidth, + BitWidth - Mask.countLeadingZeros()); + ComputeMaskedBits(I->getOperand(0), Mask2, LHSKnownZero, LHSKnownOne, TD, + Depth+1); + assert((LHSKnownZero & LHSKnownOne) == 0 && + "Bits known to be one AND zero?"); + unsigned LHSKnownZeroOut = LHSKnownZero.countTrailingOnes(); + + ComputeMaskedBits(I->getOperand(1), Mask2, KnownZero2, KnownOne2, TD, + Depth+1); + assert((KnownZero2 & KnownOne2) == 0 && "Bits known to be one AND zero?"); + unsigned RHSKnownZeroOut = KnownZero2.countTrailingOnes(); + + // Determine which operand has more trailing zeros, and use that + // many bits from the other operand. + if (LHSKnownZeroOut > RHSKnownZeroOut) { + if (I->getOpcode() == Instruction::Add) { + APInt Mask = APInt::getLowBitsSet(BitWidth, LHSKnownZeroOut); + KnownZero |= KnownZero2 & Mask; + KnownOne |= KnownOne2 & Mask; + } else { + // If the known zeros are in the left operand for a subtract, + // fall back to the minimum known zeros in both operands. + KnownZero |= APInt::getLowBitsSet(BitWidth, + std::min(LHSKnownZeroOut, + RHSKnownZeroOut)); + } + } else if (RHSKnownZeroOut >= LHSKnownZeroOut) { + APInt Mask = APInt::getLowBitsSet(BitWidth, RHSKnownZeroOut); + KnownZero |= LHSKnownZero & Mask; + KnownOne |= LHSKnownOne & Mask; + } + return; + } + case Instruction::SRem: + if (ConstantInt *Rem = dyn_cast(I->getOperand(1))) { + APInt RA = Rem->getValue(); + if (RA.isPowerOf2() || (-RA).isPowerOf2()) { + APInt LowBits = RA.isStrictlyPositive() ? (RA - 1) : ~RA; + APInt Mask2 = LowBits | APInt::getSignBit(BitWidth); + ComputeMaskedBits(I->getOperand(0), Mask2, KnownZero2, KnownOne2, TD, + Depth+1); + + // If the sign bit of the first operand is zero, the sign bit of + // the result is zero. If the first operand has no one bits below + // the second operand's single 1 bit, its sign will be zero. + if (KnownZero2[BitWidth-1] || ((KnownZero2 & LowBits) == LowBits)) + KnownZero2 |= ~LowBits; + + KnownZero |= KnownZero2 & Mask; + + assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?"); + } + } + break; + case Instruction::URem: { + if (ConstantInt *Rem = dyn_cast(I->getOperand(1))) { + APInt RA = Rem->getValue(); + if (RA.isPowerOf2()) { + APInt LowBits = (RA - 1); + APInt Mask2 = LowBits & Mask; + KnownZero |= ~LowBits & Mask; + ComputeMaskedBits(I->getOperand(0), Mask2, KnownZero, KnownOne, TD, + Depth+1); + assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?"); + break; + } + } + + // Since the result is less than or equal to either operand, any leading + // zero bits in either operand must also exist in the result. + APInt AllOnes = APInt::getAllOnesValue(BitWidth); + ComputeMaskedBits(I->getOperand(0), AllOnes, KnownZero, KnownOne, + TD, Depth+1); + ComputeMaskedBits(I->getOperand(1), AllOnes, KnownZero2, KnownOne2, + TD, Depth+1); + + unsigned Leaders = std::max(KnownZero.countLeadingOnes(), + KnownZero2.countLeadingOnes()); + KnownOne.clear(); + KnownZero = APInt::getHighBitsSet(BitWidth, Leaders) & Mask; + break; + } + + case Instruction::Alloca: { + AllocaInst *AI = cast(V); + unsigned Align = AI->getAlignment(); + if (Align == 0 && TD) + Align = TD->getABITypeAlignment(AI->getType()->getElementType()); + + if (Align > 0) + KnownZero = Mask & APInt::getLowBitsSet(BitWidth, + CountTrailingZeros_32(Align)); + break; + } + case Instruction::GetElementPtr: { + // Analyze all of the subscripts of this getelementptr instruction + // to determine if we can prove known low zero bits. + APInt LocalMask = APInt::getAllOnesValue(BitWidth); + APInt LocalKnownZero(BitWidth, 0), LocalKnownOne(BitWidth, 0); + ComputeMaskedBits(I->getOperand(0), LocalMask, + LocalKnownZero, LocalKnownOne, TD, Depth+1); + unsigned TrailZ = LocalKnownZero.countTrailingOnes(); + + gep_type_iterator GTI = gep_type_begin(I); + for (unsigned i = 1, e = I->getNumOperands(); i != e; ++i, ++GTI) { + Value *Index = I->getOperand(i); + if (const StructType *STy = dyn_cast(*GTI)) { + // Handle struct member offset arithmetic. + if (!TD) return; + const StructLayout *SL = TD->getStructLayout(STy); + unsigned Idx = cast(Index)->getZExtValue(); + uint64_t Offset = SL->getElementOffset(Idx); + TrailZ = std::min(TrailZ, + CountTrailingZeros_64(Offset)); + } else { + // Handle array index arithmetic. + const Type *IndexedTy = GTI.getIndexedType(); + if (!IndexedTy->isSized()) return; + unsigned GEPOpiBits = Index->getType()->getScalarSizeInBits(); + uint64_t TypeSize = TD ? TD->getTypeAllocSize(IndexedTy) : 1; + LocalMask = APInt::getAllOnesValue(GEPOpiBits); + LocalKnownZero = LocalKnownOne = APInt(GEPOpiBits, 0); + ComputeMaskedBits(Index, LocalMask, + LocalKnownZero, LocalKnownOne, TD, Depth+1); + TrailZ = std::min(TrailZ, + unsigned(CountTrailingZeros_64(TypeSize) + + LocalKnownZero.countTrailingOnes())); + } + } + + KnownZero = APInt::getLowBitsSet(BitWidth, TrailZ) & Mask; + break; + } + case Instruction::PHI: { + PHINode *P = cast(I); + // Handle the case of a simple two-predecessor recurrence PHI. + // There's a lot more that could theoretically be done here, but + // this is sufficient to catch some interesting cases. + if (P->getNumIncomingValues() == 2) { + for (unsigned i = 0; i != 2; ++i) { + Value *L = P->getIncomingValue(i); + Value *R = P->getIncomingValue(!i); + Operator *LU = dyn_cast(L); + if (!LU) + continue; + unsigned Opcode = LU->getOpcode(); + // Check for operations that have the property that if + // both their operands have low zero bits, the result + // will have low zero bits. + if (Opcode == Instruction::Add || + Opcode == Instruction::Sub || + Opcode == Instruction::And || + Opcode == Instruction::Or || + Opcode == Instruction::Mul) { + Value *LL = LU->getOperand(0); + Value *LR = LU->getOperand(1); + // Find a recurrence. + if (LL == I) + L = LR; + else if (LR == I) + L = LL; + else + break; + // Ok, we have a PHI of the form L op= R. Check for low + // zero bits. + APInt Mask2 = APInt::getAllOnesValue(BitWidth); + ComputeMaskedBits(R, Mask2, KnownZero2, KnownOne2, TD, Depth+1); + Mask2 = APInt::getLowBitsSet(BitWidth, + KnownZero2.countTrailingOnes()); + + // We need to take the minimum number of known bits + APInt KnownZero3(KnownZero), KnownOne3(KnownOne); + ComputeMaskedBits(L, Mask2, KnownZero3, KnownOne3, TD, Depth+1); + + KnownZero = Mask & + APInt::getLowBitsSet(BitWidth, + std::min(KnownZero2.countTrailingOnes(), + KnownZero3.countTrailingOnes())); + break; + } + } + } + + // Otherwise take the unions of the known bit sets of the operands, + // taking conservative care to avoid excessive recursion. + if (Depth < MaxDepth - 1 && !KnownZero && !KnownOne) { + KnownZero = APInt::getAllOnesValue(BitWidth); + KnownOne = APInt::getAllOnesValue(BitWidth); + for (unsigned i = 0, e = P->getNumIncomingValues(); i != e; ++i) { + // Skip direct self references. + if (P->getIncomingValue(i) == P) continue; + + KnownZero2 = APInt(BitWidth, 0); + KnownOne2 = APInt(BitWidth, 0); + // Recurse, but cap the recursion to one level, because we don't + // want to waste time spinning around in loops. + ComputeMaskedBits(P->getIncomingValue(i), KnownZero | KnownOne, + KnownZero2, KnownOne2, TD, MaxDepth-1); + KnownZero &= KnownZero2; + KnownOne &= KnownOne2; + // If all bits have been ruled out, there's no need to check + // more operands. + if (!KnownZero && !KnownOne) + break; + } + } + break; + } + case Instruction::Call: + if (IntrinsicInst *II = dyn_cast(I)) { + switch (II->getIntrinsicID()) { + default: break; + case Intrinsic::ctpop: + case Intrinsic::ctlz: + case Intrinsic::cttz: { + unsigned LowBits = Log2_32(BitWidth)+1; + KnownZero = APInt::getHighBitsSet(BitWidth, BitWidth - LowBits); + break; + } + } + } + break; + } +} + +/// MaskedValueIsZero - Return true if 'V & Mask' is known to be zero. We use +/// this predicate to simplify operations downstream. Mask is known to be zero +/// for bits that V cannot have. +/// +/// This function is defined on values with integer type, values with pointer +/// type (but only if TD is non-null), and vectors of integers. In the case +/// where V is a vector, the mask, known zero, and known one values are the +/// same width as the vector element, and the bit is set only if it is true +/// for all of the elements in the vector. +bool llvm::MaskedValueIsZero(Value *V, const APInt &Mask, + const TargetData *TD, unsigned Depth) { + APInt KnownZero(Mask.getBitWidth(), 0), KnownOne(Mask.getBitWidth(), 0); + ComputeMaskedBits(V, Mask, KnownZero, KnownOne, TD, Depth); + assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?"); + return (KnownZero & Mask) == Mask; +} + + + +/// ComputeNumSignBits - Return the number of times the sign bit of the +/// register is replicated into the other bits. We know that at least 1 bit +/// is always equal to the sign bit (itself), but other cases can give us +/// information. For example, immediately after an "ashr X, 2", we know that +/// the top 3 bits are all equal to each other, so we return 3. +/// +/// 'Op' must have a scalar integer type. +/// +unsigned llvm::ComputeNumSignBits(Value *V, const TargetData *TD, + unsigned Depth) { + assert((TD || V->getType()->isIntOrIntVector()) && + "ComputeNumSignBits requires a TargetData object to operate " + "on non-integer values!"); + const Type *Ty = V->getType(); + unsigned TyBits = TD ? TD->getTypeSizeInBits(V->getType()->getScalarType()) : + Ty->getScalarSizeInBits(); + unsigned Tmp, Tmp2; + unsigned FirstAnswer = 1; + + // Note that ConstantInt is handled by the general ComputeMaskedBits case + // below. + + if (Depth == 6) + return 1; // Limit search depth. + + Operator *U = dyn_cast(V); + switch (Operator::getOpcode(V)) { + default: break; + case Instruction::SExt: + Tmp = TyBits-cast(U->getOperand(0)->getType())->getBitWidth(); + return ComputeNumSignBits(U->getOperand(0), TD, Depth+1) + Tmp; + + case Instruction::AShr: + Tmp = ComputeNumSignBits(U->getOperand(0), TD, Depth+1); + // ashr X, C -> adds C sign bits. + if (ConstantInt *C = dyn_cast(U->getOperand(1))) { + Tmp += C->getZExtValue(); + if (Tmp > TyBits) Tmp = TyBits; + } + return Tmp; + case Instruction::Shl: + if (ConstantInt *C = dyn_cast(U->getOperand(1))) { + // shl destroys sign bits. + Tmp = ComputeNumSignBits(U->getOperand(0), TD, Depth+1); + if (C->getZExtValue() >= TyBits || // Bad shift. + C->getZExtValue() >= Tmp) break; // Shifted all sign bits out. + return Tmp - C->getZExtValue(); + } + break; + case Instruction::And: + case Instruction::Or: + case Instruction::Xor: // NOT is handled here. + // Logical binary ops preserve the number of sign bits at the worst. + Tmp = ComputeNumSignBits(U->getOperand(0), TD, Depth+1); + if (Tmp != 1) { + Tmp2 = ComputeNumSignBits(U->getOperand(1), TD, Depth+1); + FirstAnswer = std::min(Tmp, Tmp2); + // We computed what we know about the sign bits as our first + // answer. Now proceed to the generic code that uses + // ComputeMaskedBits, and pick whichever answer is better. + } + break; + + case Instruction::Select: + Tmp = ComputeNumSignBits(U->getOperand(1), TD, Depth+1); + if (Tmp == 1) return 1; // Early out. + Tmp2 = ComputeNumSignBits(U->getOperand(2), TD, Depth+1); + return std::min(Tmp, Tmp2); + + case Instruction::Add: + // Add can have at most one carry bit. Thus we know that the output + // is, at worst, one more bit than the inputs. + Tmp = ComputeNumSignBits(U->getOperand(0), TD, Depth+1); + if (Tmp == 1) return 1; // Early out. + + // Special case decrementing a value (ADD X, -1): + if (ConstantInt *CRHS = dyn_cast(U->getOperand(1))) + if (CRHS->isAllOnesValue()) { + APInt KnownZero(TyBits, 0), KnownOne(TyBits, 0); + APInt Mask = APInt::getAllOnesValue(TyBits); + ComputeMaskedBits(U->getOperand(0), Mask, KnownZero, KnownOne, TD, + Depth+1); + + // If the input is known to be 0 or 1, the output is 0/-1, which is all + // sign bits set. + if ((KnownZero | APInt(TyBits, 1)) == Mask) + return TyBits; + + // If we are subtracting one from a positive number, there is no carry + // out of the result. + if (KnownZero.isNegative()) + return Tmp; + } + + Tmp2 = ComputeNumSignBits(U->getOperand(1), TD, Depth+1); + if (Tmp2 == 1) return 1; + return std::min(Tmp, Tmp2)-1; + break; + + case Instruction::Sub: + Tmp2 = ComputeNumSignBits(U->getOperand(1), TD, Depth+1); + if (Tmp2 == 1) return 1; + + // Handle NEG. + if (ConstantInt *CLHS = dyn_cast(U->getOperand(0))) + if (CLHS->isNullValue()) { + APInt KnownZero(TyBits, 0), KnownOne(TyBits, 0); + APInt Mask = APInt::getAllOnesValue(TyBits); + ComputeMaskedBits(U->getOperand(1), Mask, KnownZero, KnownOne, + TD, Depth+1); + // If the input is known to be 0 or 1, the output is 0/-1, which is all + // sign bits set. + if ((KnownZero | APInt(TyBits, 1)) == Mask) + return TyBits; + + // If the input is known to be positive (the sign bit is known clear), + // the output of the NEG has the same number of sign bits as the input. + if (KnownZero.isNegative()) + return Tmp2; + + // Otherwise, we treat this like a SUB. + } + + // Sub can have at most one carry bit. Thus we know that the output + // is, at worst, one more bit than the inputs. + Tmp = ComputeNumSignBits(U->getOperand(0), TD, Depth+1); + if (Tmp == 1) return 1; // Early out. + return std::min(Tmp, Tmp2)-1; + break; + case Instruction::Trunc: + // FIXME: it's tricky to do anything useful for this, but it is an important + // case for targets like X86. + break; + } + + // Finally, if we can prove that the top bits of the result are 0's or 1's, + // use this information. + APInt KnownZero(TyBits, 0), KnownOne(TyBits, 0); + APInt Mask = APInt::getAllOnesValue(TyBits); + ComputeMaskedBits(V, Mask, KnownZero, KnownOne, TD, Depth); + + if (KnownZero.isNegative()) { // sign bit is 0 + Mask = KnownZero; + } else if (KnownOne.isNegative()) { // sign bit is 1; + Mask = KnownOne; + } else { + // Nothing known. + return FirstAnswer; + } + + // Okay, we know that the sign bit in Mask is set. Use CLZ to determine + // the number of identical bits in the top of the input value. + Mask = ~Mask; + Mask <<= Mask.getBitWidth()-TyBits; + // Return # leading zeros. We use 'min' here in case Val was zero before + // shifting. We don't want to return '64' as for an i32 "0". + return std::max(FirstAnswer, std::min(TyBits, Mask.countLeadingZeros())); +} + +/// ComputeMultiple - This function computes the integer multiple of Base that +/// equals V. If successful, it returns true and returns the multiple in +/// Multiple. If unsuccessful, it returns false. It looks +/// through SExt instructions only if LookThroughSExt is true. +bool llvm::ComputeMultiple(Value *V, unsigned Base, Value *&Multiple, + bool LookThroughSExt, unsigned Depth) { + const unsigned MaxDepth = 6; + + assert(V && "No Value?"); + assert(Depth <= MaxDepth && "Limit Search Depth"); + assert(V->getType()->isInteger() && "Not integer or pointer type!"); + + const Type *T = V->getType(); + + ConstantInt *CI = dyn_cast(V); + + if (Base == 0) + return false; + + if (Base == 1) { + Multiple = V; + return true; + } + + ConstantExpr *CO = dyn_cast(V); + Constant *BaseVal = ConstantInt::get(T, Base); + if (CO && CO == BaseVal) { + // Multiple is 1. + Multiple = ConstantInt::get(T, 1); + return true; + } + + if (CI && CI->getZExtValue() % Base == 0) { + Multiple = ConstantInt::get(T, CI->getZExtValue() / Base); + return true; + } + + if (Depth == MaxDepth) return false; // Limit search depth. + + Operator *I = dyn_cast(V); + if (!I) return false; + + switch (I->getOpcode()) { + default: break; + case Instruction::SExt: + if (!LookThroughSExt) return false; + // otherwise fall through to ZExt + case Instruction::ZExt: + return ComputeMultiple(I->getOperand(0), Base, Multiple, + LookThroughSExt, Depth+1); + case Instruction::Shl: + case Instruction::Mul: { + Value *Op0 = I->getOperand(0); + Value *Op1 = I->getOperand(1); + + if (I->getOpcode() == Instruction::Shl) { + ConstantInt *Op1CI = dyn_cast(Op1); + if (!Op1CI) return false; + // Turn Op0 << Op1 into Op0 * 2^Op1 + APInt Op1Int = Op1CI->getValue(); + uint64_t BitToSet = Op1Int.getLimitedValue(Op1Int.getBitWidth() - 1); + Op1 = ConstantInt::get(V->getContext(), + APInt(Op1Int.getBitWidth(), 0).set(BitToSet)); + } + + Value *Mul0 = NULL; + Value *Mul1 = NULL; + bool M0 = ComputeMultiple(Op0, Base, Mul0, + LookThroughSExt, Depth+1); + bool M1 = ComputeMultiple(Op1, Base, Mul1, + LookThroughSExt, Depth+1); + + if (M0) { + if (isa(Op1) && isa(Mul0)) { + // V == Base * (Mul0 * Op1), so return (Mul0 * Op1) + Multiple = ConstantExpr::getMul(cast(Mul0), + cast(Op1)); + return true; + } + + if (ConstantInt *Mul0CI = dyn_cast(Mul0)) + if (Mul0CI->getValue() == 1) { + // V == Base * Op1, so return Op1 + Multiple = Op1; + return true; + } + } + + if (M1) { + if (isa(Op0) && isa(Mul1)) { + // V == Base * (Mul1 * Op0), so return (Mul1 * Op0) + Multiple = ConstantExpr::getMul(cast(Mul1), + cast(Op0)); + return true; + } + + if (ConstantInt *Mul1CI = dyn_cast(Mul1)) + if (Mul1CI->getValue() == 1) { + // V == Base * Op0, so return Op0 + Multiple = Op0; + return true; + } + } + } + } + + // We could not determine if V is a multiple of Base. + return false; +} + +/// CannotBeNegativeZero - Return true if we can prove that the specified FP +/// value is never equal to -0.0. +/// +/// NOTE: this function will need to be revisited when we support non-default +/// rounding modes! +/// +bool llvm::CannotBeNegativeZero(const Value *V, unsigned Depth) { + if (const ConstantFP *CFP = dyn_cast(V)) + return !CFP->getValueAPF().isNegZero(); + + if (Depth == 6) + return 1; // Limit search depth. + + const Operator *I = dyn_cast(V); + if (I == 0) return false; + + // (add x, 0.0) is guaranteed to return +0.0, not -0.0. + if (I->getOpcode() == Instruction::FAdd && + isa(I->getOperand(1)) && + cast(I->getOperand(1))->isNullValue()) + return true; + + // sitofp and uitofp turn into +0.0 for zero. + if (isa(I) || isa(I)) + return true; + + if (const IntrinsicInst *II = dyn_cast(I)) + // sqrt(-0.0) = -0.0, no other negative results are possible. + if (II->getIntrinsicID() == Intrinsic::sqrt) + return CannotBeNegativeZero(II->getOperand(1), Depth+1); + + if (const CallInst *CI = dyn_cast(I)) + if (const Function *F = CI->getCalledFunction()) { + if (F->isDeclaration()) { + // abs(x) != -0.0 + if (F->getName() == "abs") return true; + // fabs[lf](x) != -0.0 + if (F->getName() == "fabs") return true; + if (F->getName() == "fabsf") return true; + if (F->getName() == "fabsl") return true; + if (F->getName() == "sqrt" || F->getName() == "sqrtf" || + F->getName() == "sqrtl") + return CannotBeNegativeZero(CI->getOperand(1), Depth+1); + } + } + + return false; +} + + +/// GetLinearExpression - Analyze the specified value as a linear expression: +/// "A*V + B", where A and B are constant integers. Return the scale and offset +/// values as APInts and return V as a Value*. The incoming Value is known to +/// have IntegerType. Note that this looks through extends, so the high bits +/// may not be represented in the result. +static Value *GetLinearExpression(Value *V, APInt &Scale, APInt &Offset, + const TargetData *TD, unsigned Depth) { + assert(isa(V->getType()) && "Not an integer value"); + + // Limit our recursion depth. + if (Depth == 6) { + Scale = 1; + Offset = 0; + return V; + } + + if (BinaryOperator *BOp = dyn_cast(V)) { + if (ConstantInt *RHSC = dyn_cast(BOp->getOperand(1))) { + switch (BOp->getOpcode()) { + default: break; + case Instruction::Or: + // X|C == X+C if all the bits in C are unset in X. Otherwise we can't + // analyze it. + if (!MaskedValueIsZero(BOp->getOperand(0), RHSC->getValue(), TD)) + break; + // FALL THROUGH. + case Instruction::Add: + V = GetLinearExpression(BOp->getOperand(0), Scale, Offset, TD, Depth+1); + Offset += RHSC->getValue(); + return V; + case Instruction::Mul: + V = GetLinearExpression(BOp->getOperand(0), Scale, Offset, TD, Depth+1); + Offset *= RHSC->getValue(); + Scale *= RHSC->getValue(); + return V; + case Instruction::Shl: + V = GetLinearExpression(BOp->getOperand(0), Scale, Offset, TD, Depth+1); + Offset <<= RHSC->getValue().getLimitedValue(); + Scale <<= RHSC->getValue().getLimitedValue(); + return V; + } + } + } + + // Since clients don't care about the high bits of the value, just scales and + // offsets, we can look through extensions. + if (isa(V) || isa(V)) { + Value *CastOp = cast(V)->getOperand(0); + unsigned OldWidth = Scale.getBitWidth(); + unsigned SmallWidth = CastOp->getType()->getPrimitiveSizeInBits(); + Scale.trunc(SmallWidth); + Offset.trunc(SmallWidth); + Value *Result = GetLinearExpression(CastOp, Scale, Offset, TD, Depth+1); + Scale.zext(OldWidth); + Offset.zext(OldWidth); + return Result; + } + + Scale = 1; + Offset = 0; + return V; +} + +/// DecomposeGEPExpression - If V is a symbolic pointer expression, decompose it +/// into a base pointer with a constant offset and a number of scaled symbolic +/// offsets. +/// +/// The scaled symbolic offsets (represented by pairs of a Value* and a scale in +/// the VarIndices vector) are Value*'s that are known to be scaled by the +/// specified amount, but which may have other unrepresented high bits. As such, +/// the gep cannot necessarily be reconstructed from its decomposed form. +/// +/// When TargetData is around, this function is capable of analyzing everything +/// that Value::getUnderlyingObject() can look through. When not, it just looks +/// through pointer casts. +/// +const Value *llvm::DecomposeGEPExpression(const Value *V, int64_t &BaseOffs, + SmallVectorImpl > &VarIndices, + const TargetData *TD) { + // FIXME: Should limit depth like getUnderlyingObject? + BaseOffs = 0; + while (1) { + // See if this is a bitcast or GEP. + const Operator *Op = dyn_cast(V); + if (Op == 0) { + // The only non-operator case we can handle are GlobalAliases. + if (const GlobalAlias *GA = dyn_cast(V)) { + if (!GA->mayBeOverridden()) { + V = GA->getAliasee(); + continue; + } + } + return V; + } + + if (Op->getOpcode() == Instruction::BitCast) { + V = Op->getOperand(0); + continue; + } + + const GEPOperator *GEPOp = dyn_cast(Op); + if (GEPOp == 0) + return V; + + // Don't attempt to analyze GEPs over unsized objects. + if (!cast(GEPOp->getOperand(0)->getType()) + ->getElementType()->isSized()) + return V; + + // If we are lacking TargetData information, we can't compute the offets of + // elements computed by GEPs. However, we can handle bitcast equivalent + // GEPs. + if (!TD) { + if (!GEPOp->hasAllZeroIndices()) + return V; + V = GEPOp->getOperand(0); + continue; + } + + // Walk the indices of the GEP, accumulating them into BaseOff/VarIndices. + gep_type_iterator GTI = gep_type_begin(GEPOp); + for (User::const_op_iterator I = GEPOp->op_begin()+1, + E = GEPOp->op_end(); I != E; ++I) { + Value *Index = *I; + // Compute the (potentially symbolic) offset in bytes for this index. + if (const StructType *STy = dyn_cast(*GTI++)) { + // For a struct, add the member offset. + unsigned FieldNo = cast(Index)->getZExtValue(); + if (FieldNo == 0) continue; + + BaseOffs += TD->getStructLayout(STy)->getElementOffset(FieldNo); + continue; + } + + // For an array/pointer, add the element offset, explicitly scaled. + if (ConstantInt *CIdx = dyn_cast(Index)) { + if (CIdx->isZero()) continue; + BaseOffs += TD->getTypeAllocSize(*GTI)*CIdx->getSExtValue(); + continue; + } + + uint64_t Scale = TD->getTypeAllocSize(*GTI); + + // Use GetLinearExpression to decompose the index into a C1*V+C2 form. + unsigned Width = cast(Index->getType())->getBitWidth(); + APInt IndexScale(Width, 0), IndexOffset(Width, 0); + Index = GetLinearExpression(Index, IndexScale, IndexOffset, TD, 0); + + // The GEP index scale ("Scale") scales C1*V+C2, yielding (C1*V+C2)*Scale. + // This gives us an aggregate computation of (C1*Scale)*V + C2*Scale. + BaseOffs += IndexOffset.getZExtValue()*Scale; + Scale *= IndexScale.getZExtValue(); + + + // If we already had an occurrance of this index variable, merge this + // scale into it. For example, we want to handle: + // A[x][x] -> x*16 + x*4 -> x*20 + // This also ensures that 'x' only appears in the index list once. + for (unsigned i = 0, e = VarIndices.size(); i != e; ++i) { + if (VarIndices[i].first == Index) { + Scale += VarIndices[i].second; + VarIndices.erase(VarIndices.begin()+i); + break; + } + } + + // Make sure that we have a scale that makes sense for this target's + // pointer size. + if (unsigned ShiftBits = 64-TD->getPointerSizeInBits()) { + Scale <<= ShiftBits; + Scale >>= ShiftBits; + } + + if (Scale) + VarIndices.push_back(std::make_pair(Index, Scale)); + } + + // Analyze the base pointer next. + V = GEPOp->getOperand(0); + } +} + + +// This is the recursive version of BuildSubAggregate. It takes a few different +// arguments. Idxs is the index within the nested struct From that we are +// looking at now (which is of type IndexedType). IdxSkip is the number of +// indices from Idxs that should be left out when inserting into the resulting +// struct. To is the result struct built so far, new insertvalue instructions +// build on that. +static Value *BuildSubAggregate(Value *From, Value* To, const Type *IndexedType, + SmallVector &Idxs, + unsigned IdxSkip, + Instruction *InsertBefore) { + const llvm::StructType *STy = llvm::dyn_cast(IndexedType); + if (STy) { + // Save the original To argument so we can modify it + Value *OrigTo = To; + // General case, the type indexed by Idxs is a struct + for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) { + // Process each struct element recursively + Idxs.push_back(i); + Value *PrevTo = To; + To = BuildSubAggregate(From, To, STy->getElementType(i), Idxs, IdxSkip, + InsertBefore); + Idxs.pop_back(); + if (!To) { + // Couldn't find any inserted value for this index? Cleanup + while (PrevTo != OrigTo) { + InsertValueInst* Del = cast(PrevTo); + PrevTo = Del->getAggregateOperand(); + Del->eraseFromParent(); + } + // Stop processing elements + break; + } + } + // If we succesfully found a value for each of our subaggregates + if (To) + return To; + } + // Base case, the type indexed by SourceIdxs is not a struct, or not all of + // the struct's elements had a value that was inserted directly. In the latter + // case, perhaps we can't determine each of the subelements individually, but + // we might be able to find the complete struct somewhere. + + // Find the value that is at that particular spot + Value *V = FindInsertedValue(From, Idxs.begin(), Idxs.end()); + + if (!V) + return NULL; + + // Insert the value in the new (sub) aggregrate + return llvm::InsertValueInst::Create(To, V, Idxs.begin() + IdxSkip, + Idxs.end(), "tmp", InsertBefore); +} + +// This helper takes a nested struct and extracts a part of it (which is again a +// struct) into a new value. For example, given the struct: +// { a, { b, { c, d }, e } } +// and the indices "1, 1" this returns +// { c, d }. +// +// It does this by inserting an insertvalue for each element in the resulting +// struct, as opposed to just inserting a single struct. This will only work if +// each of the elements of the substruct are known (ie, inserted into From by an +// insertvalue instruction somewhere). +// +// All inserted insertvalue instructions are inserted before InsertBefore +static Value *BuildSubAggregate(Value *From, const unsigned *idx_begin, + const unsigned *idx_end, + Instruction *InsertBefore) { + assert(InsertBefore && "Must have someplace to insert!"); + const Type *IndexedType = ExtractValueInst::getIndexedType(From->getType(), + idx_begin, + idx_end); + Value *To = UndefValue::get(IndexedType); + SmallVector Idxs(idx_begin, idx_end); + unsigned IdxSkip = Idxs.size(); + + return BuildSubAggregate(From, To, IndexedType, Idxs, IdxSkip, InsertBefore); +} + +/// FindInsertedValue - Given an aggregrate and an sequence of indices, see if +/// the scalar value indexed is already around as a register, for example if it +/// were inserted directly into the aggregrate. +/// +/// If InsertBefore is not null, this function will duplicate (modified) +/// insertvalues when a part of a nested struct is extracted. +Value *llvm::FindInsertedValue(Value *V, const unsigned *idx_begin, + const unsigned *idx_end, Instruction *InsertBefore) { + // Nothing to index? Just return V then (this is useful at the end of our + // recursion) + if (idx_begin == idx_end) + return V; + // We have indices, so V should have an indexable type + assert((isa(V->getType()) || isa(V->getType())) + && "Not looking at a struct or array?"); + assert(ExtractValueInst::getIndexedType(V->getType(), idx_begin, idx_end) + && "Invalid indices for type?"); + const CompositeType *PTy = cast(V->getType()); + + if (isa(V)) + return UndefValue::get(ExtractValueInst::getIndexedType(PTy, + idx_begin, + idx_end)); + else if (isa(V)) + return Constant::getNullValue(ExtractValueInst::getIndexedType(PTy, + idx_begin, + idx_end)); + else if (Constant *C = dyn_cast(V)) { + if (isa(C) || isa(C)) + // Recursively process this constant + return FindInsertedValue(C->getOperand(*idx_begin), idx_begin + 1, + idx_end, InsertBefore); + } else if (InsertValueInst *I = dyn_cast(V)) { + // Loop the indices for the insertvalue instruction in parallel with the + // requested indices + const unsigned *req_idx = idx_begin; + for (const unsigned *i = I->idx_begin(), *e = I->idx_end(); + i != e; ++i, ++req_idx) { + if (req_idx == idx_end) { + if (InsertBefore) + // The requested index identifies a part of a nested aggregate. Handle + // this specially. For example, + // %A = insertvalue { i32, {i32, i32 } } undef, i32 10, 1, 0 + // %B = insertvalue { i32, {i32, i32 } } %A, i32 11, 1, 1 + // %C = extractvalue {i32, { i32, i32 } } %B, 1 + // This can be changed into + // %A = insertvalue {i32, i32 } undef, i32 10, 0 + // %C = insertvalue {i32, i32 } %A, i32 11, 1 + // which allows the unused 0,0 element from the nested struct to be + // removed. + return BuildSubAggregate(V, idx_begin, req_idx, InsertBefore); + else + // We can't handle this without inserting insertvalues + return 0; + } + + // This insert value inserts something else than what we are looking for. + // See if the (aggregrate) value inserted into has the value we are + // looking for, then. + if (*req_idx != *i) + return FindInsertedValue(I->getAggregateOperand(), idx_begin, idx_end, + InsertBefore); + } + // If we end up here, the indices of the insertvalue match with those + // requested (though possibly only partially). Now we recursively look at + // the inserted value, passing any remaining indices. + return FindInsertedValue(I->getInsertedValueOperand(), req_idx, idx_end, + InsertBefore); + } else if (ExtractValueInst *I = dyn_cast(V)) { + // If we're extracting a value from an aggregrate that was extracted from + // something else, we can extract from that something else directly instead. + // However, we will need to chain I's indices with the requested indices. + + // Calculate the number of indices required + unsigned size = I->getNumIndices() + (idx_end - idx_begin); + // Allocate some space to put the new indices in + SmallVector Idxs; + Idxs.reserve(size); + // Add indices from the extract value instruction + for (const unsigned *i = I->idx_begin(), *e = I->idx_end(); + i != e; ++i) + Idxs.push_back(*i); + + // Add requested indices + for (const unsigned *i = idx_begin, *e = idx_end; i != e; ++i) + Idxs.push_back(*i); + + assert(Idxs.size() == size + && "Number of indices added not correct?"); + + return FindInsertedValue(I->getAggregateOperand(), Idxs.begin(), Idxs.end(), + InsertBefore); + } + // Otherwise, we don't know (such as, extracting from a function return value + // or load instruction) + return 0; +} + +/// GetConstantStringInfo - This function computes the length of a +/// null-terminated C string pointed to by V. If successful, it returns true +/// and returns the string in Str. If unsuccessful, it returns false. +bool llvm::GetConstantStringInfo(Value *V, std::string &Str, uint64_t Offset, + bool StopAtNul) { + // If V is NULL then return false; + if (V == NULL) return false; + + // Look through bitcast instructions. + if (BitCastInst *BCI = dyn_cast(V)) + return GetConstantStringInfo(BCI->getOperand(0), Str, Offset, StopAtNul); + + // If the value is not a GEP instruction nor a constant expression with a + // GEP instruction, then return false because ConstantArray can't occur + // any other way + User *GEP = 0; + if (GetElementPtrInst *GEPI = dyn_cast(V)) { + GEP = GEPI; + } else if (ConstantExpr *CE = dyn_cast(V)) { + if (CE->getOpcode() == Instruction::BitCast) + return GetConstantStringInfo(CE->getOperand(0), Str, Offset, StopAtNul); + if (CE->getOpcode() != Instruction::GetElementPtr) + return false; + GEP = CE; + } + + if (GEP) { + // Make sure the GEP has exactly three arguments. + if (GEP->getNumOperands() != 3) + return false; + + // Make sure the index-ee is a pointer to array of i8. + const PointerType *PT = cast(GEP->getOperand(0)->getType()); + const ArrayType *AT = dyn_cast(PT->getElementType()); + if (AT == 0 || AT->getElementType() != Type::getInt8Ty(V->getContext())) + return false; + + // Check to make sure that the first operand of the GEP is an integer and + // has value 0 so that we are sure we're indexing into the initializer. + ConstantInt *FirstIdx = dyn_cast(GEP->getOperand(1)); + if (FirstIdx == 0 || !FirstIdx->isZero()) + return false; + + // If the second index isn't a ConstantInt, then this is a variable index + // into the array. If this occurs, we can't say anything meaningful about + // the string. + uint64_t StartIdx = 0; + if (ConstantInt *CI = dyn_cast(GEP->getOperand(2))) + StartIdx = CI->getZExtValue(); + else + return false; + return GetConstantStringInfo(GEP->getOperand(0), Str, StartIdx+Offset, + StopAtNul); + } + + if (MDString *MDStr = dyn_cast(V)) { + Str = MDStr->getString(); + return true; + } + + // The GEP instruction, constant or instruction, must reference a global + // variable that is a constant and is initialized. The referenced constant + // initializer is the array that we'll use for optimization. + GlobalVariable* GV = dyn_cast(V); + if (!GV || !GV->isConstant() || !GV->hasDefinitiveInitializer()) + return false; + Constant *GlobalInit = GV->getInitializer(); + + // Handle the ConstantAggregateZero case + if (isa(GlobalInit)) { + // This is a degenerate case. The initializer is constant zero so the + // length of the string must be zero. + Str.clear(); + return true; + } + + // Must be a Constant Array + ConstantArray *Array = dyn_cast(GlobalInit); + if (Array == 0 || + Array->getType()->getElementType() != Type::getInt8Ty(V->getContext())) + return false; + + // Get the number of elements in the array + uint64_t NumElts = Array->getType()->getNumElements(); + + if (Offset > NumElts) + return false; + + // Traverse the constant array from 'Offset' which is the place the GEP refers + // to in the array. + Str.reserve(NumElts-Offset); + for (unsigned i = Offset; i != NumElts; ++i) { + Constant *Elt = Array->getOperand(i); + ConstantInt *CI = dyn_cast(Elt); + if (!CI) // This array isn't suitable, non-int initializer. + return false; + if (StopAtNul && CI->isZero()) + return true; // we found end of string, success! + Str += (char)CI->getZExtValue(); + } + + // The array isn't null terminated, but maybe this is a memcpy, not a strcpy. + return true; +} diff --git a/libclamav/c++/llvm/lib/AsmParser/CMakeLists.txt b/libclamav/c++/llvm/lib/AsmParser/CMakeLists.txt new file mode 100644 index 000000000..985ebe200 --- /dev/null +++ b/libclamav/c++/llvm/lib/AsmParser/CMakeLists.txt @@ -0,0 +1,6 @@ +# AsmParser +add_llvm_library(LLVMAsmParser + LLLexer.cpp + LLParser.cpp + Parser.cpp + ) diff --git a/libclamav/c++/llvm/lib/AsmParser/LLLexer.cpp b/libclamav/c++/llvm/lib/AsmParser/LLLexer.cpp new file mode 100644 index 000000000..1b7c9c6d0 --- /dev/null +++ b/libclamav/c++/llvm/lib/AsmParser/LLLexer.cpp @@ -0,0 +1,863 @@ +//===- LLLexer.cpp - Lexer for .ll Files ----------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Implement the Lexer for .ll files. +// +//===----------------------------------------------------------------------===// + +#include "LLLexer.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Instruction.h" +#include "llvm/LLVMContext.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/Support/SourceMgr.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Assembly/Parser.h" +#include +#include +#include +using namespace llvm; + +bool LLLexer::Error(LocTy ErrorLoc, const std::string &Msg) const { + ErrorInfo = SM.GetMessage(ErrorLoc, Msg, "error"); + return true; +} + +//===----------------------------------------------------------------------===// +// Helper functions. +//===----------------------------------------------------------------------===// + +// atoull - Convert an ascii string of decimal digits into the unsigned long +// long representation... this does not have to do input error checking, +// because we know that the input will be matched by a suitable regex... +// +uint64_t LLLexer::atoull(const char *Buffer, const char *End) { + uint64_t Result = 0; + for (; Buffer != End; Buffer++) { + uint64_t OldRes = Result; + Result *= 10; + Result += *Buffer-'0'; + if (Result < OldRes) { // Uh, oh, overflow detected!!! + Error("constant bigger than 64 bits detected!"); + return 0; + } + } + return Result; +} + +uint64_t LLLexer::HexIntToVal(const char *Buffer, const char *End) { + uint64_t Result = 0; + for (; Buffer != End; ++Buffer) { + uint64_t OldRes = Result; + Result *= 16; + char C = *Buffer; + if (C >= '0' && C <= '9') + Result += C-'0'; + else if (C >= 'A' && C <= 'F') + Result += C-'A'+10; + else if (C >= 'a' && C <= 'f') + Result += C-'a'+10; + + if (Result < OldRes) { // Uh, oh, overflow detected!!! + Error("constant bigger than 64 bits detected!"); + return 0; + } + } + return Result; +} + +void LLLexer::HexToIntPair(const char *Buffer, const char *End, + uint64_t Pair[2]) { + Pair[0] = 0; + for (int i=0; i<16; i++, Buffer++) { + assert(Buffer != End); + Pair[0] *= 16; + char C = *Buffer; + if (C >= '0' && C <= '9') + Pair[0] += C-'0'; + else if (C >= 'A' && C <= 'F') + Pair[0] += C-'A'+10; + else if (C >= 'a' && C <= 'f') + Pair[0] += C-'a'+10; + } + Pair[1] = 0; + for (int i=0; i<16 && Buffer != End; i++, Buffer++) { + Pair[1] *= 16; + char C = *Buffer; + if (C >= '0' && C <= '9') + Pair[1] += C-'0'; + else if (C >= 'A' && C <= 'F') + Pair[1] += C-'A'+10; + else if (C >= 'a' && C <= 'f') + Pair[1] += C-'a'+10; + } + if (Buffer != End) + Error("constant bigger than 128 bits detected!"); +} + +/// FP80HexToIntPair - translate an 80 bit FP80 number (20 hexits) into +/// { low64, high16 } as usual for an APInt. +void LLLexer::FP80HexToIntPair(const char *Buffer, const char *End, + uint64_t Pair[2]) { + Pair[1] = 0; + for (int i=0; i<4 && Buffer != End; i++, Buffer++) { + assert(Buffer != End); + Pair[1] *= 16; + char C = *Buffer; + if (C >= '0' && C <= '9') + Pair[1] += C-'0'; + else if (C >= 'A' && C <= 'F') + Pair[1] += C-'A'+10; + else if (C >= 'a' && C <= 'f') + Pair[1] += C-'a'+10; + } + Pair[0] = 0; + for (int i=0; i<16; i++, Buffer++) { + Pair[0] *= 16; + char C = *Buffer; + if (C >= '0' && C <= '9') + Pair[0] += C-'0'; + else if (C >= 'A' && C <= 'F') + Pair[0] += C-'A'+10; + else if (C >= 'a' && C <= 'f') + Pair[0] += C-'a'+10; + } + if (Buffer != End) + Error("constant bigger than 128 bits detected!"); +} + +// UnEscapeLexed - Run through the specified buffer and change \xx codes to the +// appropriate character. +static void UnEscapeLexed(std::string &Str) { + if (Str.empty()) return; + + char *Buffer = &Str[0], *EndBuffer = Buffer+Str.size(); + char *BOut = Buffer; + for (char *BIn = Buffer; BIn != EndBuffer; ) { + if (BIn[0] == '\\') { + if (BIn < EndBuffer-1 && BIn[1] == '\\') { + *BOut++ = '\\'; // Two \ becomes one + BIn += 2; + } else if (BIn < EndBuffer-2 && isxdigit(BIn[1]) && isxdigit(BIn[2])) { + char Tmp = BIn[3]; BIn[3] = 0; // Terminate string + *BOut = (char)strtol(BIn+1, 0, 16); // Convert to number + BIn[3] = Tmp; // Restore character + BIn += 3; // Skip over handled chars + ++BOut; + } else { + *BOut++ = *BIn++; + } + } else { + *BOut++ = *BIn++; + } + } + Str.resize(BOut-Buffer); +} + +/// isLabelChar - Return true for [-a-zA-Z$._0-9]. +static bool isLabelChar(char C) { + return isalnum(C) || C == '-' || C == '$' || C == '.' || C == '_'; +} + + +/// isLabelTail - Return true if this pointer points to a valid end of a label. +static const char *isLabelTail(const char *CurPtr) { + while (1) { + if (CurPtr[0] == ':') return CurPtr+1; + if (!isLabelChar(CurPtr[0])) return 0; + ++CurPtr; + } +} + + + +//===----------------------------------------------------------------------===// +// Lexer definition. +//===----------------------------------------------------------------------===// + +LLLexer::LLLexer(MemoryBuffer *StartBuf, SourceMgr &sm, SMDiagnostic &Err, + LLVMContext &C) + : CurBuf(StartBuf), ErrorInfo(Err), SM(sm), Context(C), APFloatVal(0.0) { + CurPtr = CurBuf->getBufferStart(); +} + +std::string LLLexer::getFilename() const { + return CurBuf->getBufferIdentifier(); +} + +int LLLexer::getNextChar() { + char CurChar = *CurPtr++; + switch (CurChar) { + default: return (unsigned char)CurChar; + case 0: + // A nul character in the stream is either the end of the current buffer or + // a random nul in the file. Disambiguate that here. + if (CurPtr-1 != CurBuf->getBufferEnd()) + return 0; // Just whitespace. + + // Otherwise, return end of file. + --CurPtr; // Another call to lex will return EOF again. + return EOF; + } +} + + +lltok::Kind LLLexer::LexToken() { + TokStart = CurPtr; + + int CurChar = getNextChar(); + switch (CurChar) { + default: + // Handle letters: [a-zA-Z_] + if (isalpha(CurChar) || CurChar == '_') + return LexIdentifier(); + + return lltok::Error; + case EOF: return lltok::Eof; + case 0: + case ' ': + case '\t': + case '\n': + case '\r': + // Ignore whitespace. + return LexToken(); + case '+': return LexPositive(); + case '@': return LexAt(); + case '%': return LexPercent(); + case '"': return LexQuote(); + case '.': + if (const char *Ptr = isLabelTail(CurPtr)) { + CurPtr = Ptr; + StrVal.assign(TokStart, CurPtr-1); + return lltok::LabelStr; + } + if (CurPtr[0] == '.' && CurPtr[1] == '.') { + CurPtr += 2; + return lltok::dotdotdot; + } + return lltok::Error; + case '$': + if (const char *Ptr = isLabelTail(CurPtr)) { + CurPtr = Ptr; + StrVal.assign(TokStart, CurPtr-1); + return lltok::LabelStr; + } + return lltok::Error; + case ';': + SkipLineComment(); + return LexToken(); + case '!': return LexMetadata(); + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + case '-': + return LexDigitOrNegative(); + case '=': return lltok::equal; + case '[': return lltok::lsquare; + case ']': return lltok::rsquare; + case '{': return lltok::lbrace; + case '}': return lltok::rbrace; + case '<': return lltok::less; + case '>': return lltok::greater; + case '(': return lltok::lparen; + case ')': return lltok::rparen; + case ',': return lltok::comma; + case '*': return lltok::star; + case '\\': return lltok::backslash; + } +} + +void LLLexer::SkipLineComment() { + while (1) { + if (CurPtr[0] == '\n' || CurPtr[0] == '\r' || getNextChar() == EOF) + return; + } +} + +/// LexAt - Lex all tokens that start with an @ character: +/// GlobalVar @\"[^\"]*\" +/// GlobalVar @[-a-zA-Z$._][-a-zA-Z$._0-9]* +/// GlobalVarID @[0-9]+ +lltok::Kind LLLexer::LexAt() { + // Handle AtStringConstant: @\"[^\"]*\" + if (CurPtr[0] == '"') { + ++CurPtr; + + while (1) { + int CurChar = getNextChar(); + + if (CurChar == EOF) { + Error("end of file in global variable name"); + return lltok::Error; + } + if (CurChar == '"') { + StrVal.assign(TokStart+2, CurPtr-1); + UnEscapeLexed(StrVal); + return lltok::GlobalVar; + } + } + } + + // Handle GlobalVarName: @[-a-zA-Z$._][-a-zA-Z$._0-9]* + if (isalpha(CurPtr[0]) || CurPtr[0] == '-' || CurPtr[0] == '$' || + CurPtr[0] == '.' || CurPtr[0] == '_') { + ++CurPtr; + while (isalnum(CurPtr[0]) || CurPtr[0] == '-' || CurPtr[0] == '$' || + CurPtr[0] == '.' || CurPtr[0] == '_') + ++CurPtr; + + StrVal.assign(TokStart+1, CurPtr); // Skip @ + return lltok::GlobalVar; + } + + // Handle GlobalVarID: @[0-9]+ + if (isdigit(CurPtr[0])) { + for (++CurPtr; isdigit(CurPtr[0]); ++CurPtr) + /*empty*/; + + uint64_t Val = atoull(TokStart+1, CurPtr); + if ((unsigned)Val != Val) + Error("invalid value number (too large)!"); + UIntVal = unsigned(Val); + return lltok::GlobalID; + } + + return lltok::Error; +} + + +/// LexPercent - Lex all tokens that start with a % character: +/// LocalVar ::= %\"[^\"]*\" +/// LocalVar ::= %[-a-zA-Z$._][-a-zA-Z$._0-9]* +/// LocalVarID ::= %[0-9]+ +lltok::Kind LLLexer::LexPercent() { + // Handle LocalVarName: %\"[^\"]*\" + if (CurPtr[0] == '"') { + ++CurPtr; + + while (1) { + int CurChar = getNextChar(); + + if (CurChar == EOF) { + Error("end of file in string constant"); + return lltok::Error; + } + if (CurChar == '"') { + StrVal.assign(TokStart+2, CurPtr-1); + UnEscapeLexed(StrVal); + return lltok::LocalVar; + } + } + } + + // Handle LocalVarName: %[-a-zA-Z$._][-a-zA-Z$._0-9]* + if (isalpha(CurPtr[0]) || CurPtr[0] == '-' || CurPtr[0] == '$' || + CurPtr[0] == '.' || CurPtr[0] == '_') { + ++CurPtr; + while (isalnum(CurPtr[0]) || CurPtr[0] == '-' || CurPtr[0] == '$' || + CurPtr[0] == '.' || CurPtr[0] == '_') + ++CurPtr; + + StrVal.assign(TokStart+1, CurPtr); // Skip % + return lltok::LocalVar; + } + + // Handle LocalVarID: %[0-9]+ + if (isdigit(CurPtr[0])) { + for (++CurPtr; isdigit(CurPtr[0]); ++CurPtr) + /*empty*/; + + uint64_t Val = atoull(TokStart+1, CurPtr); + if ((unsigned)Val != Val) + Error("invalid value number (too large)!"); + UIntVal = unsigned(Val); + return lltok::LocalVarID; + } + + return lltok::Error; +} + +/// LexQuote - Lex all tokens that start with a " character: +/// QuoteLabel "[^"]+": +/// StringConstant "[^"]*" +lltok::Kind LLLexer::LexQuote() { + while (1) { + int CurChar = getNextChar(); + + if (CurChar == EOF) { + Error("end of file in quoted string"); + return lltok::Error; + } + + if (CurChar != '"') continue; + + if (CurPtr[0] != ':') { + StrVal.assign(TokStart+1, CurPtr-1); + UnEscapeLexed(StrVal); + return lltok::StringConstant; + } + + ++CurPtr; + StrVal.assign(TokStart+1, CurPtr-2); + UnEscapeLexed(StrVal); + return lltok::LabelStr; + } +} + +static bool JustWhitespaceNewLine(const char *&Ptr) { + const char *ThisPtr = Ptr; + while (*ThisPtr == ' ' || *ThisPtr == '\t') + ++ThisPtr; + if (*ThisPtr == '\n' || *ThisPtr == '\r') { + Ptr = ThisPtr; + return true; + } + return false; +} + +/// LexMetadata: +/// !{...} +/// !42 +/// !foo +lltok::Kind LLLexer::LexMetadata() { + if (isalpha(CurPtr[0])) { + ++CurPtr; + while (isalnum(CurPtr[0]) || CurPtr[0] == '-' || CurPtr[0] == '$' || + CurPtr[0] == '.' || CurPtr[0] == '_') + ++CurPtr; + + StrVal.assign(TokStart+1, CurPtr); // Skip ! + return lltok::NamedOrCustomMD; + } + return lltok::Metadata; +} + +/// LexIdentifier: Handle several related productions: +/// Label [-a-zA-Z$._0-9]+: +/// IntegerType i[0-9]+ +/// Keyword sdiv, float, ... +/// HexIntConstant [us]0x[0-9A-Fa-f]+ +lltok::Kind LLLexer::LexIdentifier() { + const char *StartChar = CurPtr; + const char *IntEnd = CurPtr[-1] == 'i' ? 0 : StartChar; + const char *KeywordEnd = 0; + + for (; isLabelChar(*CurPtr); ++CurPtr) { + // If we decide this is an integer, remember the end of the sequence. + if (!IntEnd && !isdigit(*CurPtr)) IntEnd = CurPtr; + if (!KeywordEnd && !isalnum(*CurPtr) && *CurPtr != '_') KeywordEnd = CurPtr; + } + + // If we stopped due to a colon, this really is a label. + if (*CurPtr == ':') { + StrVal.assign(StartChar-1, CurPtr++); + return lltok::LabelStr; + } + + // Otherwise, this wasn't a label. If this was valid as an integer type, + // return it. + if (IntEnd == 0) IntEnd = CurPtr; + if (IntEnd != StartChar) { + CurPtr = IntEnd; + uint64_t NumBits = atoull(StartChar, CurPtr); + if (NumBits < IntegerType::MIN_INT_BITS || + NumBits > IntegerType::MAX_INT_BITS) { + Error("bitwidth for integer type out of range!"); + return lltok::Error; + } + TyVal = IntegerType::get(Context, NumBits); + return lltok::Type; + } + + // Otherwise, this was a letter sequence. See which keyword this is. + if (KeywordEnd == 0) KeywordEnd = CurPtr; + CurPtr = KeywordEnd; + --StartChar; + unsigned Len = CurPtr-StartChar; +#define KEYWORD(STR) \ + if (Len == strlen(#STR) && !memcmp(StartChar, #STR, strlen(#STR))) \ + return lltok::kw_##STR; + + KEYWORD(begin); KEYWORD(end); + KEYWORD(true); KEYWORD(false); + KEYWORD(declare); KEYWORD(define); + KEYWORD(global); KEYWORD(constant); + + KEYWORD(private); + KEYWORD(linker_private); + KEYWORD(internal); + KEYWORD(available_externally); + KEYWORD(linkonce); + KEYWORD(linkonce_odr); + KEYWORD(weak); + KEYWORD(weak_odr); + KEYWORD(appending); + KEYWORD(dllimport); + KEYWORD(dllexport); + KEYWORD(common); + KEYWORD(default); + KEYWORD(hidden); + KEYWORD(protected); + KEYWORD(extern_weak); + KEYWORD(external); + KEYWORD(thread_local); + KEYWORD(zeroinitializer); + KEYWORD(undef); + KEYWORD(null); + KEYWORD(to); + KEYWORD(tail); + KEYWORD(target); + KEYWORD(triple); + KEYWORD(deplibs); + KEYWORD(datalayout); + KEYWORD(volatile); + KEYWORD(nuw); + KEYWORD(nsw); + KEYWORD(exact); + KEYWORD(inbounds); + KEYWORD(align); + KEYWORD(addrspace); + KEYWORD(section); + KEYWORD(alias); + KEYWORD(module); + KEYWORD(asm); + KEYWORD(sideeffect); + KEYWORD(alignstack); + KEYWORD(gc); + + KEYWORD(ccc); + KEYWORD(fastcc); + KEYWORD(coldcc); + KEYWORD(x86_stdcallcc); + KEYWORD(x86_fastcallcc); + KEYWORD(arm_apcscc); + KEYWORD(arm_aapcscc); + KEYWORD(arm_aapcs_vfpcc); + + KEYWORD(cc); + KEYWORD(c); + + KEYWORD(signext); + KEYWORD(zeroext); + KEYWORD(inreg); + KEYWORD(sret); + KEYWORD(nounwind); + KEYWORD(noreturn); + KEYWORD(noalias); + KEYWORD(nocapture); + KEYWORD(byval); + KEYWORD(nest); + KEYWORD(readnone); + KEYWORD(readonly); + + KEYWORD(inlinehint); + KEYWORD(noinline); + KEYWORD(alwaysinline); + KEYWORD(optsize); + KEYWORD(ssp); + KEYWORD(sspreq); + KEYWORD(noredzone); + KEYWORD(noimplicitfloat); + KEYWORD(naked); + + KEYWORD(type); + KEYWORD(opaque); + + KEYWORD(eq); KEYWORD(ne); KEYWORD(slt); KEYWORD(sgt); KEYWORD(sle); + KEYWORD(sge); KEYWORD(ult); KEYWORD(ugt); KEYWORD(ule); KEYWORD(uge); + KEYWORD(oeq); KEYWORD(one); KEYWORD(olt); KEYWORD(ogt); KEYWORD(ole); + KEYWORD(oge); KEYWORD(ord); KEYWORD(uno); KEYWORD(ueq); KEYWORD(une); + + KEYWORD(x); + KEYWORD(blockaddress); +#undef KEYWORD + + // Keywords for types. +#define TYPEKEYWORD(STR, LLVMTY) \ + if (Len == strlen(STR) && !memcmp(StartChar, STR, strlen(STR))) { \ + TyVal = LLVMTY; return lltok::Type; } + TYPEKEYWORD("void", Type::getVoidTy(Context)); + TYPEKEYWORD("float", Type::getFloatTy(Context)); + TYPEKEYWORD("double", Type::getDoubleTy(Context)); + TYPEKEYWORD("x86_fp80", Type::getX86_FP80Ty(Context)); + TYPEKEYWORD("fp128", Type::getFP128Ty(Context)); + TYPEKEYWORD("ppc_fp128", Type::getPPC_FP128Ty(Context)); + TYPEKEYWORD("label", Type::getLabelTy(Context)); + TYPEKEYWORD("metadata", Type::getMetadataTy(Context)); +#undef TYPEKEYWORD + + // Handle special forms for autoupgrading. Drop these in LLVM 3.0. This is + // to avoid conflicting with the sext/zext instructions, below. + if (Len == 4 && !memcmp(StartChar, "sext", 4)) { + // Scan CurPtr ahead, seeing if there is just whitespace before the newline. + if (JustWhitespaceNewLine(CurPtr)) + return lltok::kw_signext; + } else if (Len == 4 && !memcmp(StartChar, "zext", 4)) { + // Scan CurPtr ahead, seeing if there is just whitespace before the newline. + if (JustWhitespaceNewLine(CurPtr)) + return lltok::kw_zeroext; + } else if (Len == 6 && !memcmp(StartChar, "malloc", 6)) { + // FIXME: Remove in LLVM 3.0. + // Autoupgrade malloc instruction. + return lltok::kw_malloc; + } else if (Len == 4 && !memcmp(StartChar, "free", 4)) { + // FIXME: Remove in LLVM 3.0. + // Autoupgrade malloc instruction. + return lltok::kw_free; + } + + // Keywords for instructions. +#define INSTKEYWORD(STR, Enum) \ + if (Len == strlen(#STR) && !memcmp(StartChar, #STR, strlen(#STR))) { \ + UIntVal = Instruction::Enum; return lltok::kw_##STR; } + + INSTKEYWORD(add, Add); INSTKEYWORD(fadd, FAdd); + INSTKEYWORD(sub, Sub); INSTKEYWORD(fsub, FSub); + INSTKEYWORD(mul, Mul); INSTKEYWORD(fmul, FMul); + INSTKEYWORD(udiv, UDiv); INSTKEYWORD(sdiv, SDiv); INSTKEYWORD(fdiv, FDiv); + INSTKEYWORD(urem, URem); INSTKEYWORD(srem, SRem); INSTKEYWORD(frem, FRem); + INSTKEYWORD(shl, Shl); INSTKEYWORD(lshr, LShr); INSTKEYWORD(ashr, AShr); + INSTKEYWORD(and, And); INSTKEYWORD(or, Or); INSTKEYWORD(xor, Xor); + INSTKEYWORD(icmp, ICmp); INSTKEYWORD(fcmp, FCmp); + + INSTKEYWORD(phi, PHI); + INSTKEYWORD(call, Call); + INSTKEYWORD(trunc, Trunc); + INSTKEYWORD(zext, ZExt); + INSTKEYWORD(sext, SExt); + INSTKEYWORD(fptrunc, FPTrunc); + INSTKEYWORD(fpext, FPExt); + INSTKEYWORD(uitofp, UIToFP); + INSTKEYWORD(sitofp, SIToFP); + INSTKEYWORD(fptoui, FPToUI); + INSTKEYWORD(fptosi, FPToSI); + INSTKEYWORD(inttoptr, IntToPtr); + INSTKEYWORD(ptrtoint, PtrToInt); + INSTKEYWORD(bitcast, BitCast); + INSTKEYWORD(select, Select); + INSTKEYWORD(va_arg, VAArg); + INSTKEYWORD(ret, Ret); + INSTKEYWORD(br, Br); + INSTKEYWORD(switch, Switch); + INSTKEYWORD(indirectbr, IndirectBr); + INSTKEYWORD(invoke, Invoke); + INSTKEYWORD(unwind, Unwind); + INSTKEYWORD(unreachable, Unreachable); + + INSTKEYWORD(alloca, Alloca); + INSTKEYWORD(load, Load); + INSTKEYWORD(store, Store); + INSTKEYWORD(getelementptr, GetElementPtr); + + INSTKEYWORD(extractelement, ExtractElement); + INSTKEYWORD(insertelement, InsertElement); + INSTKEYWORD(shufflevector, ShuffleVector); + INSTKEYWORD(getresult, ExtractValue); + INSTKEYWORD(extractvalue, ExtractValue); + INSTKEYWORD(insertvalue, InsertValue); +#undef INSTKEYWORD + + // Check for [us]0x[0-9A-Fa-f]+ which are Hexadecimal constant generated by + // the CFE to avoid forcing it to deal with 64-bit numbers. + if ((TokStart[0] == 'u' || TokStart[0] == 's') && + TokStart[1] == '0' && TokStart[2] == 'x' && isxdigit(TokStart[3])) { + int len = CurPtr-TokStart-3; + uint32_t bits = len * 4; + APInt Tmp(bits, StringRef(TokStart+3, len), 16); + uint32_t activeBits = Tmp.getActiveBits(); + if (activeBits > 0 && activeBits < bits) + Tmp.trunc(activeBits); + APSIntVal = APSInt(Tmp, TokStart[0] == 'u'); + return lltok::APSInt; + } + + // If this is "cc1234", return this as just "cc". + if (TokStart[0] == 'c' && TokStart[1] == 'c') { + CurPtr = TokStart+2; + return lltok::kw_cc; + } + + // If this starts with "call", return it as CALL. This is to support old + // broken .ll files. FIXME: remove this with LLVM 3.0. + if (CurPtr-TokStart > 4 && !memcmp(TokStart, "call", 4)) { + CurPtr = TokStart+4; + UIntVal = Instruction::Call; + return lltok::kw_call; + } + + // Finally, if this isn't known, return an error. + CurPtr = TokStart+1; + return lltok::Error; +} + + +/// Lex0x: Handle productions that start with 0x, knowing that it matches and +/// that this is not a label: +/// HexFPConstant 0x[0-9A-Fa-f]+ +/// HexFP80Constant 0xK[0-9A-Fa-f]+ +/// HexFP128Constant 0xL[0-9A-Fa-f]+ +/// HexPPC128Constant 0xM[0-9A-Fa-f]+ +lltok::Kind LLLexer::Lex0x() { + CurPtr = TokStart + 2; + + char Kind; + if (CurPtr[0] >= 'K' && CurPtr[0] <= 'M') { + Kind = *CurPtr++; + } else { + Kind = 'J'; + } + + if (!isxdigit(CurPtr[0])) { + // Bad token, return it as an error. + CurPtr = TokStart+1; + return lltok::Error; + } + + while (isxdigit(CurPtr[0])) + ++CurPtr; + + if (Kind == 'J') { + // HexFPConstant - Floating point constant represented in IEEE format as a + // hexadecimal number for when exponential notation is not precise enough. + // Float and double only. + APFloatVal = APFloat(BitsToDouble(HexIntToVal(TokStart+2, CurPtr))); + return lltok::APFloat; + } + + uint64_t Pair[2]; + switch (Kind) { + default: llvm_unreachable("Unknown kind!"); + case 'K': + // F80HexFPConstant - x87 long double in hexadecimal format (10 bytes) + FP80HexToIntPair(TokStart+3, CurPtr, Pair); + APFloatVal = APFloat(APInt(80, 2, Pair)); + return lltok::APFloat; + case 'L': + // F128HexFPConstant - IEEE 128-bit in hexadecimal format (16 bytes) + HexToIntPair(TokStart+3, CurPtr, Pair); + APFloatVal = APFloat(APInt(128, 2, Pair), true); + return lltok::APFloat; + case 'M': + // PPC128HexFPConstant - PowerPC 128-bit in hexadecimal format (16 bytes) + HexToIntPair(TokStart+3, CurPtr, Pair); + APFloatVal = APFloat(APInt(128, 2, Pair)); + return lltok::APFloat; + } +} + +/// LexIdentifier: Handle several related productions: +/// Label [-a-zA-Z$._0-9]+: +/// NInteger -[0-9]+ +/// FPConstant [-+]?[0-9]+[.][0-9]*([eE][-+]?[0-9]+)? +/// PInteger [0-9]+ +/// HexFPConstant 0x[0-9A-Fa-f]+ +/// HexFP80Constant 0xK[0-9A-Fa-f]+ +/// HexFP128Constant 0xL[0-9A-Fa-f]+ +/// HexPPC128Constant 0xM[0-9A-Fa-f]+ +lltok::Kind LLLexer::LexDigitOrNegative() { + // If the letter after the negative is a number, this is probably a label. + if (!isdigit(TokStart[0]) && !isdigit(CurPtr[0])) { + // Okay, this is not a number after the -, it's probably a label. + if (const char *End = isLabelTail(CurPtr)) { + StrVal.assign(TokStart, End-1); + CurPtr = End; + return lltok::LabelStr; + } + + return lltok::Error; + } + + // At this point, it is either a label, int or fp constant. + + // Skip digits, we have at least one. + for (; isdigit(CurPtr[0]); ++CurPtr) + /*empty*/; + + // Check to see if this really is a label afterall, e.g. "-1:". + if (isLabelChar(CurPtr[0]) || CurPtr[0] == ':') { + if (const char *End = isLabelTail(CurPtr)) { + StrVal.assign(TokStart, End-1); + CurPtr = End; + return lltok::LabelStr; + } + } + + // If the next character is a '.', then it is a fp value, otherwise its + // integer. + if (CurPtr[0] != '.') { + if (TokStart[0] == '0' && TokStart[1] == 'x') + return Lex0x(); + unsigned Len = CurPtr-TokStart; + uint32_t numBits = ((Len * 64) / 19) + 2; + APInt Tmp(numBits, StringRef(TokStart, Len), 10); + if (TokStart[0] == '-') { + uint32_t minBits = Tmp.getMinSignedBits(); + if (minBits > 0 && minBits < numBits) + Tmp.trunc(minBits); + APSIntVal = APSInt(Tmp, false); + } else { + uint32_t activeBits = Tmp.getActiveBits(); + if (activeBits > 0 && activeBits < numBits) + Tmp.trunc(activeBits); + APSIntVal = APSInt(Tmp, true); + } + return lltok::APSInt; + } + + ++CurPtr; + + // Skip over [0-9]*([eE][-+]?[0-9]+)? + while (isdigit(CurPtr[0])) ++CurPtr; + + if (CurPtr[0] == 'e' || CurPtr[0] == 'E') { + if (isdigit(CurPtr[1]) || + ((CurPtr[1] == '-' || CurPtr[1] == '+') && isdigit(CurPtr[2]))) { + CurPtr += 2; + while (isdigit(CurPtr[0])) ++CurPtr; + } + } + + APFloatVal = APFloat(atof(TokStart)); + return lltok::APFloat; +} + +/// FPConstant [-+]?[0-9]+[.][0-9]*([eE][-+]?[0-9]+)? +lltok::Kind LLLexer::LexPositive() { + // If the letter after the negative is a number, this is probably not a + // label. + if (!isdigit(CurPtr[0])) + return lltok::Error; + + // Skip digits. + for (++CurPtr; isdigit(CurPtr[0]); ++CurPtr) + /*empty*/; + + // At this point, we need a '.'. + if (CurPtr[0] != '.') { + CurPtr = TokStart+1; + return lltok::Error; + } + + ++CurPtr; + + // Skip over [0-9]*([eE][-+]?[0-9]+)? + while (isdigit(CurPtr[0])) ++CurPtr; + + if (CurPtr[0] == 'e' || CurPtr[0] == 'E') { + if (isdigit(CurPtr[1]) || + ((CurPtr[1] == '-' || CurPtr[1] == '+') && isdigit(CurPtr[2]))) { + CurPtr += 2; + while (isdigit(CurPtr[0])) ++CurPtr; + } + } + + APFloatVal = APFloat(atof(TokStart)); + return lltok::APFloat; +} diff --git a/libclamav/c++/llvm/lib/AsmParser/LLLexer.h b/libclamav/c++/llvm/lib/AsmParser/LLLexer.h new file mode 100644 index 000000000..de39272f4 --- /dev/null +++ b/libclamav/c++/llvm/lib/AsmParser/LLLexer.h @@ -0,0 +1,90 @@ +//===- LLLexer.h - Lexer for LLVM Assembly Files ----------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This class represents the Lexer for .ll files. +// +//===----------------------------------------------------------------------===// + +#ifndef LIB_ASMPARSER_LLLEXER_H +#define LIB_ASMPARSER_LLLEXER_H + +#include "LLToken.h" +#include "llvm/ADT/APSInt.h" +#include "llvm/ADT/APFloat.h" +#include "llvm/Support/SourceMgr.h" +#include + +namespace llvm { + class MemoryBuffer; + class Type; + class SMDiagnostic; + class LLVMContext; + + class LLLexer { + const char *CurPtr; + MemoryBuffer *CurBuf; + SMDiagnostic &ErrorInfo; + SourceMgr &SM; + LLVMContext &Context; + + // Information about the current token. + const char *TokStart; + lltok::Kind CurKind; + std::string StrVal; + unsigned UIntVal; + const Type *TyVal; + APFloat APFloatVal; + APSInt APSIntVal; + + std::string TheError; + public: + explicit LLLexer(MemoryBuffer *StartBuf, SourceMgr &SM, SMDiagnostic &, + LLVMContext &C); + ~LLLexer() {} + + lltok::Kind Lex() { + return CurKind = LexToken(); + } + + typedef SMLoc LocTy; + LocTy getLoc() const { return SMLoc::getFromPointer(TokStart); } + lltok::Kind getKind() const { return CurKind; } + const std::string getStrVal() const { return StrVal; } + const Type *getTyVal() const { return TyVal; } + unsigned getUIntVal() const { return UIntVal; } + const APSInt &getAPSIntVal() const { return APSIntVal; } + const APFloat &getAPFloatVal() const { return APFloatVal; } + + + bool Error(LocTy L, const std::string &Msg) const; + bool Error(const std::string &Msg) const { return Error(getLoc(), Msg); } + std::string getFilename() const; + + private: + lltok::Kind LexToken(); + + int getNextChar(); + void SkipLineComment(); + lltok::Kind LexIdentifier(); + lltok::Kind LexDigitOrNegative(); + lltok::Kind LexPositive(); + lltok::Kind LexAt(); + lltok::Kind LexMetadata(); + lltok::Kind LexPercent(); + lltok::Kind LexQuote(); + lltok::Kind Lex0x(); + + uint64_t atoull(const char *Buffer, const char *End); + uint64_t HexIntToVal(const char *Buffer, const char *End); + void HexToIntPair(const char *Buffer, const char *End, uint64_t Pair[2]); + void FP80HexToIntPair(const char *Buff, const char *End, uint64_t Pair[2]); + }; +} // end namespace llvm + +#endif diff --git a/libclamav/c++/llvm/lib/AsmParser/LLParser.cpp b/libclamav/c++/llvm/lib/AsmParser/LLParser.cpp new file mode 100644 index 000000000..a92dbf82a --- /dev/null +++ b/libclamav/c++/llvm/lib/AsmParser/LLParser.cpp @@ -0,0 +1,3828 @@ +//===-- LLParser.cpp - Parser Class ---------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the parser class for .ll files. +// +//===----------------------------------------------------------------------===// + +#include "LLParser.h" +#include "llvm/AutoUpgrade.h" +#include "llvm/CallingConv.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/InlineAsm.h" +#include "llvm/Instructions.h" +#include "llvm/LLVMContext.h" +#include "llvm/Metadata.h" +#include "llvm/Module.h" +#include "llvm/Operator.h" +#include "llvm/ValueSymbolTable.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +/// Run: module ::= toplevelentity* +bool LLParser::Run() { + // Prime the lexer. + Lex.Lex(); + + return ParseTopLevelEntities() || + ValidateEndOfModule(); +} + +/// ValidateEndOfModule - Do final validity and sanity checks at the end of the +/// module. +bool LLParser::ValidateEndOfModule() { + // Update auto-upgraded malloc calls to "malloc". + // FIXME: Remove in LLVM 3.0. + if (MallocF) { + MallocF->setName("malloc"); + // If setName() does not set the name to "malloc", then there is already a + // declaration of "malloc". In that case, iterate over all calls to MallocF + // and get them to call the declared "malloc" instead. + if (MallocF->getName() != "malloc") { + Constant *RealMallocF = M->getFunction("malloc"); + if (RealMallocF->getType() != MallocF->getType()) + RealMallocF = ConstantExpr::getBitCast(RealMallocF, MallocF->getType()); + MallocF->replaceAllUsesWith(RealMallocF); + MallocF->eraseFromParent(); + MallocF = NULL; + } + } + + + // If there are entries in ForwardRefBlockAddresses at this point, they are + // references after the function was defined. Resolve those now. + while (!ForwardRefBlockAddresses.empty()) { + // Okay, we are referencing an already-parsed function, resolve them now. + Function *TheFn = 0; + const ValID &Fn = ForwardRefBlockAddresses.begin()->first; + if (Fn.Kind == ValID::t_GlobalName) + TheFn = M->getFunction(Fn.StrVal); + else if (Fn.UIntVal < NumberedVals.size()) + TheFn = dyn_cast(NumberedVals[Fn.UIntVal]); + + if (TheFn == 0) + return Error(Fn.Loc, "unknown function referenced by blockaddress"); + + // Resolve all these references. + if (ResolveForwardRefBlockAddresses(TheFn, + ForwardRefBlockAddresses.begin()->second, + 0)) + return true; + + ForwardRefBlockAddresses.erase(ForwardRefBlockAddresses.begin()); + } + + + if (!ForwardRefTypes.empty()) + return Error(ForwardRefTypes.begin()->second.second, + "use of undefined type named '" + + ForwardRefTypes.begin()->first + "'"); + if (!ForwardRefTypeIDs.empty()) + return Error(ForwardRefTypeIDs.begin()->second.second, + "use of undefined type '%" + + utostr(ForwardRefTypeIDs.begin()->first) + "'"); + + if (!ForwardRefVals.empty()) + return Error(ForwardRefVals.begin()->second.second, + "use of undefined value '@" + ForwardRefVals.begin()->first + + "'"); + + if (!ForwardRefValIDs.empty()) + return Error(ForwardRefValIDs.begin()->second.second, + "use of undefined value '@" + + utostr(ForwardRefValIDs.begin()->first) + "'"); + + if (!ForwardRefMDNodes.empty()) + return Error(ForwardRefMDNodes.begin()->second.second, + "use of undefined metadata '!" + + utostr(ForwardRefMDNodes.begin()->first) + "'"); + + + // Look for intrinsic functions and CallInst that need to be upgraded + for (Module::iterator FI = M->begin(), FE = M->end(); FI != FE; ) + UpgradeCallsToIntrinsic(FI++); // must be post-increment, as we remove + + // Check debug info intrinsics. + CheckDebugInfoIntrinsics(M); + return false; +} + +bool LLParser::ResolveForwardRefBlockAddresses(Function *TheFn, + std::vector > &Refs, + PerFunctionState *PFS) { + // Loop over all the references, resolving them. + for (unsigned i = 0, e = Refs.size(); i != e; ++i) { + BasicBlock *Res; + if (PFS) { + if (Refs[i].first.Kind == ValID::t_LocalName) + Res = PFS->GetBB(Refs[i].first.StrVal, Refs[i].first.Loc); + else + Res = PFS->GetBB(Refs[i].first.UIntVal, Refs[i].first.Loc); + } else if (Refs[i].first.Kind == ValID::t_LocalID) { + return Error(Refs[i].first.Loc, + "cannot take address of numeric label after the function is defined"); + } else { + Res = dyn_cast_or_null( + TheFn->getValueSymbolTable().lookup(Refs[i].first.StrVal)); + } + + if (Res == 0) + return Error(Refs[i].first.Loc, + "referenced value is not a basic block"); + + // Get the BlockAddress for this and update references to use it. + BlockAddress *BA = BlockAddress::get(TheFn, Res); + Refs[i].second->replaceAllUsesWith(BA); + Refs[i].second->eraseFromParent(); + } + return false; +} + + +//===----------------------------------------------------------------------===// +// Top-Level Entities +//===----------------------------------------------------------------------===// + +bool LLParser::ParseTopLevelEntities() { + while (1) { + switch (Lex.getKind()) { + default: return TokError("expected top-level entity"); + case lltok::Eof: return false; + //case lltok::kw_define: + case lltok::kw_declare: if (ParseDeclare()) return true; break; + case lltok::kw_define: if (ParseDefine()) return true; break; + case lltok::kw_module: if (ParseModuleAsm()) return true; break; + case lltok::kw_target: if (ParseTargetDefinition()) return true; break; + case lltok::kw_deplibs: if (ParseDepLibs()) return true; break; + case lltok::kw_type: if (ParseUnnamedType()) return true; break; + case lltok::LocalVarID: if (ParseUnnamedType()) return true; break; + case lltok::StringConstant: // FIXME: REMOVE IN LLVM 3.0 + case lltok::LocalVar: if (ParseNamedType()) return true; break; + case lltok::GlobalID: if (ParseUnnamedGlobal()) return true; break; + case lltok::GlobalVar: if (ParseNamedGlobal()) return true; break; + case lltok::Metadata: if (ParseStandaloneMetadata()) return true; break; + case lltok::NamedOrCustomMD: if (ParseNamedMetadata()) return true; break; + + // The Global variable production with no name can have many different + // optional leading prefixes, the production is: + // GlobalVar ::= OptionalLinkage OptionalVisibility OptionalThreadLocal + // OptionalAddrSpace ('constant'|'global') ... + case lltok::kw_private : // OptionalLinkage + case lltok::kw_linker_private: // OptionalLinkage + case lltok::kw_internal: // OptionalLinkage + case lltok::kw_weak: // OptionalLinkage + case lltok::kw_weak_odr: // OptionalLinkage + case lltok::kw_linkonce: // OptionalLinkage + case lltok::kw_linkonce_odr: // OptionalLinkage + case lltok::kw_appending: // OptionalLinkage + case lltok::kw_dllexport: // OptionalLinkage + case lltok::kw_common: // OptionalLinkage + case lltok::kw_dllimport: // OptionalLinkage + case lltok::kw_extern_weak: // OptionalLinkage + case lltok::kw_external: { // OptionalLinkage + unsigned Linkage, Visibility; + if (ParseOptionalLinkage(Linkage) || + ParseOptionalVisibility(Visibility) || + ParseGlobal("", SMLoc(), Linkage, true, Visibility)) + return true; + break; + } + case lltok::kw_default: // OptionalVisibility + case lltok::kw_hidden: // OptionalVisibility + case lltok::kw_protected: { // OptionalVisibility + unsigned Visibility; + if (ParseOptionalVisibility(Visibility) || + ParseGlobal("", SMLoc(), 0, false, Visibility)) + return true; + break; + } + + case lltok::kw_thread_local: // OptionalThreadLocal + case lltok::kw_addrspace: // OptionalAddrSpace + case lltok::kw_constant: // GlobalType + case lltok::kw_global: // GlobalType + if (ParseGlobal("", SMLoc(), 0, false, 0)) return true; + break; + } + } +} + + +/// toplevelentity +/// ::= 'module' 'asm' STRINGCONSTANT +bool LLParser::ParseModuleAsm() { + assert(Lex.getKind() == lltok::kw_module); + Lex.Lex(); + + std::string AsmStr; + if (ParseToken(lltok::kw_asm, "expected 'module asm'") || + ParseStringConstant(AsmStr)) return true; + + const std::string &AsmSoFar = M->getModuleInlineAsm(); + if (AsmSoFar.empty()) + M->setModuleInlineAsm(AsmStr); + else + M->setModuleInlineAsm(AsmSoFar+"\n"+AsmStr); + return false; +} + +/// toplevelentity +/// ::= 'target' 'triple' '=' STRINGCONSTANT +/// ::= 'target' 'datalayout' '=' STRINGCONSTANT +bool LLParser::ParseTargetDefinition() { + assert(Lex.getKind() == lltok::kw_target); + std::string Str; + switch (Lex.Lex()) { + default: return TokError("unknown target property"); + case lltok::kw_triple: + Lex.Lex(); + if (ParseToken(lltok::equal, "expected '=' after target triple") || + ParseStringConstant(Str)) + return true; + M->setTargetTriple(Str); + return false; + case lltok::kw_datalayout: + Lex.Lex(); + if (ParseToken(lltok::equal, "expected '=' after target datalayout") || + ParseStringConstant(Str)) + return true; + M->setDataLayout(Str); + return false; + } +} + +/// toplevelentity +/// ::= 'deplibs' '=' '[' ']' +/// ::= 'deplibs' '=' '[' STRINGCONSTANT (',' STRINGCONSTANT)* ']' +bool LLParser::ParseDepLibs() { + assert(Lex.getKind() == lltok::kw_deplibs); + Lex.Lex(); + if (ParseToken(lltok::equal, "expected '=' after deplibs") || + ParseToken(lltok::lsquare, "expected '=' after deplibs")) + return true; + + if (EatIfPresent(lltok::rsquare)) + return false; + + std::string Str; + if (ParseStringConstant(Str)) return true; + M->addLibrary(Str); + + while (EatIfPresent(lltok::comma)) { + if (ParseStringConstant(Str)) return true; + M->addLibrary(Str); + } + + return ParseToken(lltok::rsquare, "expected ']' at end of list"); +} + +/// ParseUnnamedType: +/// ::= 'type' type +/// ::= LocalVarID '=' 'type' type +bool LLParser::ParseUnnamedType() { + unsigned TypeID = NumberedTypes.size(); + + // Handle the LocalVarID form. + if (Lex.getKind() == lltok::LocalVarID) { + if (Lex.getUIntVal() != TypeID) + return Error(Lex.getLoc(), "type expected to be numbered '%" + + utostr(TypeID) + "'"); + Lex.Lex(); // eat LocalVarID; + + if (ParseToken(lltok::equal, "expected '=' after name")) + return true; + } + + assert(Lex.getKind() == lltok::kw_type); + LocTy TypeLoc = Lex.getLoc(); + Lex.Lex(); // eat kw_type + + PATypeHolder Ty(Type::getVoidTy(Context)); + if (ParseType(Ty)) return true; + + // See if this type was previously referenced. + std::map >::iterator + FI = ForwardRefTypeIDs.find(TypeID); + if (FI != ForwardRefTypeIDs.end()) { + if (FI->second.first.get() == Ty) + return Error(TypeLoc, "self referential type is invalid"); + + cast(FI->second.first.get())->refineAbstractTypeTo(Ty); + Ty = FI->second.first.get(); + ForwardRefTypeIDs.erase(FI); + } + + NumberedTypes.push_back(Ty); + + return false; +} + +/// toplevelentity +/// ::= LocalVar '=' 'type' type +bool LLParser::ParseNamedType() { + std::string Name = Lex.getStrVal(); + LocTy NameLoc = Lex.getLoc(); + Lex.Lex(); // eat LocalVar. + + PATypeHolder Ty(Type::getVoidTy(Context)); + + if (ParseToken(lltok::equal, "expected '=' after name") || + ParseToken(lltok::kw_type, "expected 'type' after name") || + ParseType(Ty)) + return true; + + // Set the type name, checking for conflicts as we do so. + bool AlreadyExists = M->addTypeName(Name, Ty); + if (!AlreadyExists) return false; + + // See if this type is a forward reference. We need to eagerly resolve + // types to allow recursive type redefinitions below. + std::map >::iterator + FI = ForwardRefTypes.find(Name); + if (FI != ForwardRefTypes.end()) { + if (FI->second.first.get() == Ty) + return Error(NameLoc, "self referential type is invalid"); + + cast(FI->second.first.get())->refineAbstractTypeTo(Ty); + Ty = FI->second.first.get(); + ForwardRefTypes.erase(FI); + } + + // Inserting a name that is already defined, get the existing name. + const Type *Existing = M->getTypeByName(Name); + assert(Existing && "Conflict but no matching type?!"); + + // Otherwise, this is an attempt to redefine a type. That's okay if + // the redefinition is identical to the original. + // FIXME: REMOVE REDEFINITIONS IN LLVM 3.0 + if (Existing == Ty) return false; + + // Any other kind of (non-equivalent) redefinition is an error. + return Error(NameLoc, "redefinition of type named '" + Name + "' of type '" + + Ty->getDescription() + "'"); +} + + +/// toplevelentity +/// ::= 'declare' FunctionHeader +bool LLParser::ParseDeclare() { + assert(Lex.getKind() == lltok::kw_declare); + Lex.Lex(); + + Function *F; + return ParseFunctionHeader(F, false); +} + +/// toplevelentity +/// ::= 'define' FunctionHeader '{' ... +bool LLParser::ParseDefine() { + assert(Lex.getKind() == lltok::kw_define); + Lex.Lex(); + + Function *F; + return ParseFunctionHeader(F, true) || + ParseFunctionBody(*F); +} + +/// ParseGlobalType +/// ::= 'constant' +/// ::= 'global' +bool LLParser::ParseGlobalType(bool &IsConstant) { + if (Lex.getKind() == lltok::kw_constant) + IsConstant = true; + else if (Lex.getKind() == lltok::kw_global) + IsConstant = false; + else { + IsConstant = false; + return TokError("expected 'global' or 'constant'"); + } + Lex.Lex(); + return false; +} + +/// ParseUnnamedGlobal: +/// OptionalVisibility ALIAS ... +/// OptionalLinkage OptionalVisibility ... -> global variable +/// GlobalID '=' OptionalVisibility ALIAS ... +/// GlobalID '=' OptionalLinkage OptionalVisibility ... -> global variable +bool LLParser::ParseUnnamedGlobal() { + unsigned VarID = NumberedVals.size(); + std::string Name; + LocTy NameLoc = Lex.getLoc(); + + // Handle the GlobalID form. + if (Lex.getKind() == lltok::GlobalID) { + if (Lex.getUIntVal() != VarID) + return Error(Lex.getLoc(), "variable expected to be numbered '%" + + utostr(VarID) + "'"); + Lex.Lex(); // eat GlobalID; + + if (ParseToken(lltok::equal, "expected '=' after name")) + return true; + } + + bool HasLinkage; + unsigned Linkage, Visibility; + if (ParseOptionalLinkage(Linkage, HasLinkage) || + ParseOptionalVisibility(Visibility)) + return true; + + if (HasLinkage || Lex.getKind() != lltok::kw_alias) + return ParseGlobal(Name, NameLoc, Linkage, HasLinkage, Visibility); + return ParseAlias(Name, NameLoc, Visibility); +} + +/// ParseNamedGlobal: +/// GlobalVar '=' OptionalVisibility ALIAS ... +/// GlobalVar '=' OptionalLinkage OptionalVisibility ... -> global variable +bool LLParser::ParseNamedGlobal() { + assert(Lex.getKind() == lltok::GlobalVar); + LocTy NameLoc = Lex.getLoc(); + std::string Name = Lex.getStrVal(); + Lex.Lex(); + + bool HasLinkage; + unsigned Linkage, Visibility; + if (ParseToken(lltok::equal, "expected '=' in global variable") || + ParseOptionalLinkage(Linkage, HasLinkage) || + ParseOptionalVisibility(Visibility)) + return true; + + if (HasLinkage || Lex.getKind() != lltok::kw_alias) + return ParseGlobal(Name, NameLoc, Linkage, HasLinkage, Visibility); + return ParseAlias(Name, NameLoc, Visibility); +} + +// MDString: +// ::= '!' STRINGCONSTANT +bool LLParser::ParseMDString(MetadataBase *&MDS) { + std::string Str; + if (ParseStringConstant(Str)) return true; + MDS = MDString::get(Context, Str); + return false; +} + +// MDNode: +// ::= '!' MDNodeNumber +bool LLParser::ParseMDNode(MetadataBase *&Node) { + // !{ ..., !42, ... } + unsigned MID = 0; + if (ParseUInt32(MID)) return true; + + // Check existing MDNode. + std::map::iterator I = MetadataCache.find(MID); + if (I != MetadataCache.end()) { + Node = cast(I->second); + return false; + } + + // Check known forward references. + std::map >::iterator + FI = ForwardRefMDNodes.find(MID); + if (FI != ForwardRefMDNodes.end()) { + Node = cast(FI->second.first); + return false; + } + + // Create MDNode forward reference + SmallVector Elts; + std::string FwdRefName = "llvm.mdnode.fwdref." + utostr(MID); + Elts.push_back(MDString::get(Context, FwdRefName)); + MDNode *FwdNode = MDNode::get(Context, Elts.data(), Elts.size()); + ForwardRefMDNodes[MID] = std::make_pair(FwdNode, Lex.getLoc()); + Node = FwdNode; + return false; +} + +///ParseNamedMetadata: +/// !foo = !{ !1, !2 } +bool LLParser::ParseNamedMetadata() { + assert(Lex.getKind() == lltok::NamedOrCustomMD); + Lex.Lex(); + std::string Name = Lex.getStrVal(); + + if (ParseToken(lltok::equal, "expected '=' here")) + return true; + + if (Lex.getKind() != lltok::Metadata) + return TokError("Expected '!' here"); + Lex.Lex(); + + if (Lex.getKind() != lltok::lbrace) + return TokError("Expected '{' here"); + Lex.Lex(); + SmallVector Elts; + do { + if (Lex.getKind() != lltok::Metadata) + return TokError("Expected '!' here"); + Lex.Lex(); + MetadataBase *N = 0; + if (ParseMDNode(N)) return true; + Elts.push_back(N); + } while (EatIfPresent(lltok::comma)); + + if (ParseToken(lltok::rbrace, "expected end of metadata node")) + return true; + + NamedMDNode::Create(Context, Name, Elts.data(), Elts.size(), M); + return false; +} + +/// ParseStandaloneMetadata: +/// !42 = !{...} +bool LLParser::ParseStandaloneMetadata() { + assert(Lex.getKind() == lltok::Metadata); + Lex.Lex(); + unsigned MetadataID = 0; + if (ParseUInt32(MetadataID)) + return true; + if (MetadataCache.find(MetadataID) != MetadataCache.end()) + return TokError("Metadata id is already used"); + if (ParseToken(lltok::equal, "expected '=' here")) + return true; + + LocTy TyLoc; + PATypeHolder Ty(Type::getVoidTy(Context)); + if (ParseType(Ty, TyLoc)) + return true; + + if (Lex.getKind() != lltok::Metadata) + return TokError("Expected metadata here"); + + Lex.Lex(); + if (Lex.getKind() != lltok::lbrace) + return TokError("Expected '{' here"); + + SmallVector Elts; + if (ParseMDNodeVector(Elts) + || ParseToken(lltok::rbrace, "expected end of metadata node")) + return true; + + MDNode *Init = MDNode::get(Context, Elts.data(), Elts.size()); + MetadataCache[MetadataID] = Init; + std::map >::iterator + FI = ForwardRefMDNodes.find(MetadataID); + if (FI != ForwardRefMDNodes.end()) { + MDNode *FwdNode = cast(FI->second.first); + FwdNode->replaceAllUsesWith(Init); + ForwardRefMDNodes.erase(FI); + } + + return false; +} + +/// ParseAlias: +/// ::= GlobalVar '=' OptionalVisibility 'alias' OptionalLinkage Aliasee +/// Aliasee +/// ::= TypeAndValue +/// ::= 'bitcast' '(' TypeAndValue 'to' Type ')' +/// ::= 'getelementptr' 'inbounds'? '(' ... ')' +/// +/// Everything through visibility has already been parsed. +/// +bool LLParser::ParseAlias(const std::string &Name, LocTy NameLoc, + unsigned Visibility) { + assert(Lex.getKind() == lltok::kw_alias); + Lex.Lex(); + unsigned Linkage; + LocTy LinkageLoc = Lex.getLoc(); + if (ParseOptionalLinkage(Linkage)) + return true; + + if (Linkage != GlobalValue::ExternalLinkage && + Linkage != GlobalValue::WeakAnyLinkage && + Linkage != GlobalValue::WeakODRLinkage && + Linkage != GlobalValue::InternalLinkage && + Linkage != GlobalValue::PrivateLinkage && + Linkage != GlobalValue::LinkerPrivateLinkage) + return Error(LinkageLoc, "invalid linkage type for alias"); + + Constant *Aliasee; + LocTy AliaseeLoc = Lex.getLoc(); + if (Lex.getKind() != lltok::kw_bitcast && + Lex.getKind() != lltok::kw_getelementptr) { + if (ParseGlobalTypeAndValue(Aliasee)) return true; + } else { + // The bitcast dest type is not present, it is implied by the dest type. + ValID ID; + if (ParseValID(ID)) return true; + if (ID.Kind != ValID::t_Constant) + return Error(AliaseeLoc, "invalid aliasee"); + Aliasee = ID.ConstantVal; + } + + if (!isa(Aliasee->getType())) + return Error(AliaseeLoc, "alias must have pointer type"); + + // Okay, create the alias but do not insert it into the module yet. + GlobalAlias* GA = new GlobalAlias(Aliasee->getType(), + (GlobalValue::LinkageTypes)Linkage, Name, + Aliasee); + GA->setVisibility((GlobalValue::VisibilityTypes)Visibility); + + // See if this value already exists in the symbol table. If so, it is either + // a redefinition or a definition of a forward reference. + if (GlobalValue *Val = M->getNamedValue(Name)) { + // See if this was a redefinition. If so, there is no entry in + // ForwardRefVals. + std::map >::iterator + I = ForwardRefVals.find(Name); + if (I == ForwardRefVals.end()) + return Error(NameLoc, "redefinition of global named '@" + Name + "'"); + + // Otherwise, this was a definition of forward ref. Verify that types + // agree. + if (Val->getType() != GA->getType()) + return Error(NameLoc, + "forward reference and definition of alias have different types"); + + // If they agree, just RAUW the old value with the alias and remove the + // forward ref info. + Val->replaceAllUsesWith(GA); + Val->eraseFromParent(); + ForwardRefVals.erase(I); + } + + // Insert into the module, we know its name won't collide now. + M->getAliasList().push_back(GA); + assert(GA->getNameStr() == Name && "Should not be a name conflict!"); + + return false; +} + +/// ParseGlobal +/// ::= GlobalVar '=' OptionalLinkage OptionalVisibility OptionalThreadLocal +/// OptionalAddrSpace GlobalType Type Const +/// ::= OptionalLinkage OptionalVisibility OptionalThreadLocal +/// OptionalAddrSpace GlobalType Type Const +/// +/// Everything through visibility has been parsed already. +/// +bool LLParser::ParseGlobal(const std::string &Name, LocTy NameLoc, + unsigned Linkage, bool HasLinkage, + unsigned Visibility) { + unsigned AddrSpace; + bool ThreadLocal, IsConstant; + LocTy TyLoc; + + PATypeHolder Ty(Type::getVoidTy(Context)); + if (ParseOptionalToken(lltok::kw_thread_local, ThreadLocal) || + ParseOptionalAddrSpace(AddrSpace) || + ParseGlobalType(IsConstant) || + ParseType(Ty, TyLoc)) + return true; + + // If the linkage is specified and is external, then no initializer is + // present. + Constant *Init = 0; + if (!HasLinkage || (Linkage != GlobalValue::DLLImportLinkage && + Linkage != GlobalValue::ExternalWeakLinkage && + Linkage != GlobalValue::ExternalLinkage)) { + if (ParseGlobalValue(Ty, Init)) + return true; + } + + if (isa(Ty) || Ty->isLabelTy()) + return Error(TyLoc, "invalid type for global variable"); + + GlobalVariable *GV = 0; + + // See if the global was forward referenced, if so, use the global. + if (!Name.empty()) { + if (GlobalValue *GVal = M->getNamedValue(Name)) { + if (!ForwardRefVals.erase(Name) || !isa(GVal)) + return Error(NameLoc, "redefinition of global '@" + Name + "'"); + GV = cast(GVal); + } + } else { + std::map >::iterator + I = ForwardRefValIDs.find(NumberedVals.size()); + if (I != ForwardRefValIDs.end()) { + GV = cast(I->second.first); + ForwardRefValIDs.erase(I); + } + } + + if (GV == 0) { + GV = new GlobalVariable(*M, Ty, false, GlobalValue::ExternalLinkage, 0, + Name, 0, false, AddrSpace); + } else { + if (GV->getType()->getElementType() != Ty) + return Error(TyLoc, + "forward reference and definition of global have different types"); + + // Move the forward-reference to the correct spot in the module. + M->getGlobalList().splice(M->global_end(), M->getGlobalList(), GV); + } + + if (Name.empty()) + NumberedVals.push_back(GV); + + // Set the parsed properties on the global. + if (Init) + GV->setInitializer(Init); + GV->setConstant(IsConstant); + GV->setLinkage((GlobalValue::LinkageTypes)Linkage); + GV->setVisibility((GlobalValue::VisibilityTypes)Visibility); + GV->setThreadLocal(ThreadLocal); + + // Parse attributes on the global. + while (Lex.getKind() == lltok::comma) { + Lex.Lex(); + + if (Lex.getKind() == lltok::kw_section) { + Lex.Lex(); + GV->setSection(Lex.getStrVal()); + if (ParseToken(lltok::StringConstant, "expected global section string")) + return true; + } else if (Lex.getKind() == lltok::kw_align) { + unsigned Alignment; + if (ParseOptionalAlignment(Alignment)) return true; + GV->setAlignment(Alignment); + } else { + TokError("unknown global variable property!"); + } + } + + return false; +} + + +//===----------------------------------------------------------------------===// +// GlobalValue Reference/Resolution Routines. +//===----------------------------------------------------------------------===// + +/// GetGlobalVal - Get a value with the specified name or ID, creating a +/// forward reference record if needed. This can return null if the value +/// exists but does not have the right type. +GlobalValue *LLParser::GetGlobalVal(const std::string &Name, const Type *Ty, + LocTy Loc) { + const PointerType *PTy = dyn_cast(Ty); + if (PTy == 0) { + Error(Loc, "global variable reference must have pointer type"); + return 0; + } + + // Look this name up in the normal function symbol table. + GlobalValue *Val = + cast_or_null(M->getValueSymbolTable().lookup(Name)); + + // If this is a forward reference for the value, see if we already created a + // forward ref record. + if (Val == 0) { + std::map >::iterator + I = ForwardRefVals.find(Name); + if (I != ForwardRefVals.end()) + Val = I->second.first; + } + + // If we have the value in the symbol table or fwd-ref table, return it. + if (Val) { + if (Val->getType() == Ty) return Val; + Error(Loc, "'@" + Name + "' defined with type '" + + Val->getType()->getDescription() + "'"); + return 0; + } + + // Otherwise, create a new forward reference for this value and remember it. + GlobalValue *FwdVal; + if (const FunctionType *FT = dyn_cast(PTy->getElementType())) { + // Function types can return opaque but functions can't. + if (isa(FT->getReturnType())) { + Error(Loc, "function may not return opaque type"); + return 0; + } + + FwdVal = Function::Create(FT, GlobalValue::ExternalWeakLinkage, Name, M); + } else { + FwdVal = new GlobalVariable(*M, PTy->getElementType(), false, + GlobalValue::ExternalWeakLinkage, 0, Name); + } + + ForwardRefVals[Name] = std::make_pair(FwdVal, Loc); + return FwdVal; +} + +GlobalValue *LLParser::GetGlobalVal(unsigned ID, const Type *Ty, LocTy Loc) { + const PointerType *PTy = dyn_cast(Ty); + if (PTy == 0) { + Error(Loc, "global variable reference must have pointer type"); + return 0; + } + + GlobalValue *Val = ID < NumberedVals.size() ? NumberedVals[ID] : 0; + + // If this is a forward reference for the value, see if we already created a + // forward ref record. + if (Val == 0) { + std::map >::iterator + I = ForwardRefValIDs.find(ID); + if (I != ForwardRefValIDs.end()) + Val = I->second.first; + } + + // If we have the value in the symbol table or fwd-ref table, return it. + if (Val) { + if (Val->getType() == Ty) return Val; + Error(Loc, "'@" + utostr(ID) + "' defined with type '" + + Val->getType()->getDescription() + "'"); + return 0; + } + + // Otherwise, create a new forward reference for this value and remember it. + GlobalValue *FwdVal; + if (const FunctionType *FT = dyn_cast(PTy->getElementType())) { + // Function types can return opaque but functions can't. + if (isa(FT->getReturnType())) { + Error(Loc, "function may not return opaque type"); + return 0; + } + FwdVal = Function::Create(FT, GlobalValue::ExternalWeakLinkage, "", M); + } else { + FwdVal = new GlobalVariable(*M, PTy->getElementType(), false, + GlobalValue::ExternalWeakLinkage, 0, ""); + } + + ForwardRefValIDs[ID] = std::make_pair(FwdVal, Loc); + return FwdVal; +} + + +//===----------------------------------------------------------------------===// +// Helper Routines. +//===----------------------------------------------------------------------===// + +/// ParseToken - If the current token has the specified kind, eat it and return +/// success. Otherwise, emit the specified error and return failure. +bool LLParser::ParseToken(lltok::Kind T, const char *ErrMsg) { + if (Lex.getKind() != T) + return TokError(ErrMsg); + Lex.Lex(); + return false; +} + +/// ParseStringConstant +/// ::= StringConstant +bool LLParser::ParseStringConstant(std::string &Result) { + if (Lex.getKind() != lltok::StringConstant) + return TokError("expected string constant"); + Result = Lex.getStrVal(); + Lex.Lex(); + return false; +} + +/// ParseUInt32 +/// ::= uint32 +bool LLParser::ParseUInt32(unsigned &Val) { + if (Lex.getKind() != lltok::APSInt || Lex.getAPSIntVal().isSigned()) + return TokError("expected integer"); + uint64_t Val64 = Lex.getAPSIntVal().getLimitedValue(0xFFFFFFFFULL+1); + if (Val64 != unsigned(Val64)) + return TokError("expected 32-bit integer (too large)"); + Val = Val64; + Lex.Lex(); + return false; +} + + +/// ParseOptionalAddrSpace +/// := /*empty*/ +/// := 'addrspace' '(' uint32 ')' +bool LLParser::ParseOptionalAddrSpace(unsigned &AddrSpace) { + AddrSpace = 0; + if (!EatIfPresent(lltok::kw_addrspace)) + return false; + return ParseToken(lltok::lparen, "expected '(' in address space") || + ParseUInt32(AddrSpace) || + ParseToken(lltok::rparen, "expected ')' in address space"); +} + +/// ParseOptionalAttrs - Parse a potentially empty attribute list. AttrKind +/// indicates what kind of attribute list this is: 0: function arg, 1: result, +/// 2: function attr. +/// 3: function arg after value: FIXME: REMOVE IN LLVM 3.0 +bool LLParser::ParseOptionalAttrs(unsigned &Attrs, unsigned AttrKind) { + Attrs = Attribute::None; + LocTy AttrLoc = Lex.getLoc(); + + while (1) { + switch (Lex.getKind()) { + case lltok::kw_sext: + case lltok::kw_zext: + // Treat these as signext/zeroext if they occur in the argument list after + // the value, as in "call i8 @foo(i8 10 sext)". If they occur before the + // value, as in "call i8 @foo(i8 sext (" then it is part of a constant + // expr. + // FIXME: REMOVE THIS IN LLVM 3.0 + if (AttrKind == 3) { + if (Lex.getKind() == lltok::kw_sext) + Attrs |= Attribute::SExt; + else + Attrs |= Attribute::ZExt; + break; + } + // FALL THROUGH. + default: // End of attributes. + if (AttrKind != 2 && (Attrs & Attribute::FunctionOnly)) + return Error(AttrLoc, "invalid use of function-only attribute"); + + if (AttrKind != 0 && AttrKind != 3 && (Attrs & Attribute::ParameterOnly)) + return Error(AttrLoc, "invalid use of parameter-only attribute"); + + return false; + case lltok::kw_zeroext: Attrs |= Attribute::ZExt; break; + case lltok::kw_signext: Attrs |= Attribute::SExt; break; + case lltok::kw_inreg: Attrs |= Attribute::InReg; break; + case lltok::kw_sret: Attrs |= Attribute::StructRet; break; + case lltok::kw_noalias: Attrs |= Attribute::NoAlias; break; + case lltok::kw_nocapture: Attrs |= Attribute::NoCapture; break; + case lltok::kw_byval: Attrs |= Attribute::ByVal; break; + case lltok::kw_nest: Attrs |= Attribute::Nest; break; + + case lltok::kw_noreturn: Attrs |= Attribute::NoReturn; break; + case lltok::kw_nounwind: Attrs |= Attribute::NoUnwind; break; + case lltok::kw_noinline: Attrs |= Attribute::NoInline; break; + case lltok::kw_readnone: Attrs |= Attribute::ReadNone; break; + case lltok::kw_readonly: Attrs |= Attribute::ReadOnly; break; + case lltok::kw_inlinehint: Attrs |= Attribute::InlineHint; break; + case lltok::kw_alwaysinline: Attrs |= Attribute::AlwaysInline; break; + case lltok::kw_optsize: Attrs |= Attribute::OptimizeForSize; break; + case lltok::kw_ssp: Attrs |= Attribute::StackProtect; break; + case lltok::kw_sspreq: Attrs |= Attribute::StackProtectReq; break; + case lltok::kw_noredzone: Attrs |= Attribute::NoRedZone; break; + case lltok::kw_noimplicitfloat: Attrs |= Attribute::NoImplicitFloat; break; + case lltok::kw_naked: Attrs |= Attribute::Naked; break; + + case lltok::kw_align: { + unsigned Alignment; + if (ParseOptionalAlignment(Alignment)) + return true; + Attrs |= Attribute::constructAlignmentFromInt(Alignment); + continue; + } + } + Lex.Lex(); + } +} + +/// ParseOptionalLinkage +/// ::= /*empty*/ +/// ::= 'private' +/// ::= 'linker_private' +/// ::= 'internal' +/// ::= 'weak' +/// ::= 'weak_odr' +/// ::= 'linkonce' +/// ::= 'linkonce_odr' +/// ::= 'appending' +/// ::= 'dllexport' +/// ::= 'common' +/// ::= 'dllimport' +/// ::= 'extern_weak' +/// ::= 'external' +bool LLParser::ParseOptionalLinkage(unsigned &Res, bool &HasLinkage) { + HasLinkage = false; + switch (Lex.getKind()) { + default: Res=GlobalValue::ExternalLinkage; return false; + case lltok::kw_private: Res = GlobalValue::PrivateLinkage; break; + case lltok::kw_linker_private: Res = GlobalValue::LinkerPrivateLinkage; break; + case lltok::kw_internal: Res = GlobalValue::InternalLinkage; break; + case lltok::kw_weak: Res = GlobalValue::WeakAnyLinkage; break; + case lltok::kw_weak_odr: Res = GlobalValue::WeakODRLinkage; break; + case lltok::kw_linkonce: Res = GlobalValue::LinkOnceAnyLinkage; break; + case lltok::kw_linkonce_odr: Res = GlobalValue::LinkOnceODRLinkage; break; + case lltok::kw_available_externally: + Res = GlobalValue::AvailableExternallyLinkage; + break; + case lltok::kw_appending: Res = GlobalValue::AppendingLinkage; break; + case lltok::kw_dllexport: Res = GlobalValue::DLLExportLinkage; break; + case lltok::kw_common: Res = GlobalValue::CommonLinkage; break; + case lltok::kw_dllimport: Res = GlobalValue::DLLImportLinkage; break; + case lltok::kw_extern_weak: Res = GlobalValue::ExternalWeakLinkage; break; + case lltok::kw_external: Res = GlobalValue::ExternalLinkage; break; + } + Lex.Lex(); + HasLinkage = true; + return false; +} + +/// ParseOptionalVisibility +/// ::= /*empty*/ +/// ::= 'default' +/// ::= 'hidden' +/// ::= 'protected' +/// +bool LLParser::ParseOptionalVisibility(unsigned &Res) { + switch (Lex.getKind()) { + default: Res = GlobalValue::DefaultVisibility; return false; + case lltok::kw_default: Res = GlobalValue::DefaultVisibility; break; + case lltok::kw_hidden: Res = GlobalValue::HiddenVisibility; break; + case lltok::kw_protected: Res = GlobalValue::ProtectedVisibility; break; + } + Lex.Lex(); + return false; +} + +/// ParseOptionalCallingConv +/// ::= /*empty*/ +/// ::= 'ccc' +/// ::= 'fastcc' +/// ::= 'coldcc' +/// ::= 'x86_stdcallcc' +/// ::= 'x86_fastcallcc' +/// ::= 'arm_apcscc' +/// ::= 'arm_aapcscc' +/// ::= 'arm_aapcs_vfpcc' +/// ::= 'cc' UINT +/// +bool LLParser::ParseOptionalCallingConv(CallingConv::ID &CC) { + switch (Lex.getKind()) { + default: CC = CallingConv::C; return false; + case lltok::kw_ccc: CC = CallingConv::C; break; + case lltok::kw_fastcc: CC = CallingConv::Fast; break; + case lltok::kw_coldcc: CC = CallingConv::Cold; break; + case lltok::kw_x86_stdcallcc: CC = CallingConv::X86_StdCall; break; + case lltok::kw_x86_fastcallcc: CC = CallingConv::X86_FastCall; break; + case lltok::kw_arm_apcscc: CC = CallingConv::ARM_APCS; break; + case lltok::kw_arm_aapcscc: CC = CallingConv::ARM_AAPCS; break; + case lltok::kw_arm_aapcs_vfpcc:CC = CallingConv::ARM_AAPCS_VFP; break; + case lltok::kw_cc: { + unsigned ArbitraryCC; + Lex.Lex(); + if (ParseUInt32(ArbitraryCC)) { + return true; + } else + CC = static_cast(ArbitraryCC); + return false; + } + break; + } + + Lex.Lex(); + return false; +} + +/// ParseOptionalCustomMetadata +/// ::= /* empty */ +/// ::= !dbg !42 +bool LLParser::ParseOptionalCustomMetadata() { + if (Lex.getKind() != lltok::NamedOrCustomMD) + return false; + + std::string Name = Lex.getStrVal(); + Lex.Lex(); + + if (Lex.getKind() != lltok::Metadata) + return TokError("Expected '!' here"); + Lex.Lex(); + + MetadataBase *Node; + if (ParseMDNode(Node)) return true; + + MetadataContext &TheMetadata = M->getContext().getMetadata(); + unsigned MDK = TheMetadata.getMDKind(Name.c_str()); + if (!MDK) + MDK = TheMetadata.registerMDKind(Name.c_str()); + MDsOnInst.push_back(std::make_pair(MDK, cast(Node))); + + return false; +} + +/// ParseOptionalAlignment +/// ::= /* empty */ +/// ::= 'align' 4 +bool LLParser::ParseOptionalAlignment(unsigned &Alignment) { + Alignment = 0; + if (!EatIfPresent(lltok::kw_align)) + return false; + LocTy AlignLoc = Lex.getLoc(); + if (ParseUInt32(Alignment)) return true; + if (!isPowerOf2_32(Alignment)) + return Error(AlignLoc, "alignment is not a power of two"); + return false; +} + +/// ParseOptionalInfo +/// ::= OptionalInfo (',' OptionalInfo)+ +bool LLParser::ParseOptionalInfo(unsigned &Alignment) { + + // FIXME: Handle customized metadata info attached with an instruction. + do { + if (Lex.getKind() == lltok::NamedOrCustomMD) { + if (ParseOptionalCustomMetadata()) return true; + } else if (Lex.getKind() == lltok::kw_align) { + if (ParseOptionalAlignment(Alignment)) return true; + } else + return true; + } while (EatIfPresent(lltok::comma)); + + return false; +} + + +/// ParseIndexList +/// ::= (',' uint32)+ +bool LLParser::ParseIndexList(SmallVectorImpl &Indices) { + if (Lex.getKind() != lltok::comma) + return TokError("expected ',' as start of index list"); + + while (EatIfPresent(lltok::comma)) { + if (Lex.getKind() == lltok::NamedOrCustomMD) + break; + unsigned Idx; + if (ParseUInt32(Idx)) return true; + Indices.push_back(Idx); + } + + return false; +} + +//===----------------------------------------------------------------------===// +// Type Parsing. +//===----------------------------------------------------------------------===// + +/// ParseType - Parse and resolve a full type. +bool LLParser::ParseType(PATypeHolder &Result, bool AllowVoid) { + LocTy TypeLoc = Lex.getLoc(); + if (ParseTypeRec(Result)) return true; + + // Verify no unresolved uprefs. + if (!UpRefs.empty()) + return Error(UpRefs.back().Loc, "invalid unresolved type up reference"); + + if (!AllowVoid && Result.get()->isVoidTy()) + return Error(TypeLoc, "void type only allowed for function results"); + + return false; +} + +/// HandleUpRefs - Every time we finish a new layer of types, this function is +/// called. It loops through the UpRefs vector, which is a list of the +/// currently active types. For each type, if the up-reference is contained in +/// the newly completed type, we decrement the level count. When the level +/// count reaches zero, the up-referenced type is the type that is passed in: +/// thus we can complete the cycle. +/// +PATypeHolder LLParser::HandleUpRefs(const Type *ty) { + // If Ty isn't abstract, or if there are no up-references in it, then there is + // nothing to resolve here. + if (!ty->isAbstract() || UpRefs.empty()) return ty; + + PATypeHolder Ty(ty); +#if 0 + errs() << "Type '" << Ty->getDescription() + << "' newly formed. Resolving upreferences.\n" + << UpRefs.size() << " upreferences active!\n"; +#endif + + // If we find any resolvable upreferences (i.e., those whose NestingLevel goes + // to zero), we resolve them all together before we resolve them to Ty. At + // the end of the loop, if there is anything to resolve to Ty, it will be in + // this variable. + OpaqueType *TypeToResolve = 0; + + for (unsigned i = 0; i != UpRefs.size(); ++i) { + // Determine if 'Ty' directly contains this up-references 'LastContainedTy'. + bool ContainsType = + std::find(Ty->subtype_begin(), Ty->subtype_end(), + UpRefs[i].LastContainedTy) != Ty->subtype_end(); + +#if 0 + errs() << " UR#" << i << " - TypeContains(" << Ty->getDescription() << ", " + << UpRefs[i].LastContainedTy->getDescription() << ") = " + << (ContainsType ? "true" : "false") + << " level=" << UpRefs[i].NestingLevel << "\n"; +#endif + if (!ContainsType) + continue; + + // Decrement level of upreference + unsigned Level = --UpRefs[i].NestingLevel; + UpRefs[i].LastContainedTy = Ty; + + // If the Up-reference has a non-zero level, it shouldn't be resolved yet. + if (Level != 0) + continue; + +#if 0 + errs() << " * Resolving upreference for " << UpRefs[i].UpRefTy << "\n"; +#endif + if (!TypeToResolve) + TypeToResolve = UpRefs[i].UpRefTy; + else + UpRefs[i].UpRefTy->refineAbstractTypeTo(TypeToResolve); + UpRefs.erase(UpRefs.begin()+i); // Remove from upreference list. + --i; // Do not skip the next element. + } + + if (TypeToResolve) + TypeToResolve->refineAbstractTypeTo(Ty); + + return Ty; +} + + +/// ParseTypeRec - The recursive function used to process the internal +/// implementation details of types. +bool LLParser::ParseTypeRec(PATypeHolder &Result) { + switch (Lex.getKind()) { + default: + return TokError("expected type"); + case lltok::Type: + // TypeRec ::= 'float' | 'void' (etc) + Result = Lex.getTyVal(); + Lex.Lex(); + break; + case lltok::kw_opaque: + // TypeRec ::= 'opaque' + Result = OpaqueType::get(Context); + Lex.Lex(); + break; + case lltok::lbrace: + // TypeRec ::= '{' ... '}' + if (ParseStructType(Result, false)) + return true; + break; + case lltok::lsquare: + // TypeRec ::= '[' ... ']' + Lex.Lex(); // eat the lsquare. + if (ParseArrayVectorType(Result, false)) + return true; + break; + case lltok::less: // Either vector or packed struct. + // TypeRec ::= '<' ... '>' + Lex.Lex(); + if (Lex.getKind() == lltok::lbrace) { + if (ParseStructType(Result, true) || + ParseToken(lltok::greater, "expected '>' at end of packed struct")) + return true; + } else if (ParseArrayVectorType(Result, true)) + return true; + break; + case lltok::LocalVar: + case lltok::StringConstant: // FIXME: REMOVE IN LLVM 3.0 + // TypeRec ::= %foo + if (const Type *T = M->getTypeByName(Lex.getStrVal())) { + Result = T; + } else { + Result = OpaqueType::get(Context); + ForwardRefTypes.insert(std::make_pair(Lex.getStrVal(), + std::make_pair(Result, + Lex.getLoc()))); + M->addTypeName(Lex.getStrVal(), Result.get()); + } + Lex.Lex(); + break; + + case lltok::LocalVarID: + // TypeRec ::= %4 + if (Lex.getUIntVal() < NumberedTypes.size()) + Result = NumberedTypes[Lex.getUIntVal()]; + else { + std::map >::iterator + I = ForwardRefTypeIDs.find(Lex.getUIntVal()); + if (I != ForwardRefTypeIDs.end()) + Result = I->second.first; + else { + Result = OpaqueType::get(Context); + ForwardRefTypeIDs.insert(std::make_pair(Lex.getUIntVal(), + std::make_pair(Result, + Lex.getLoc()))); + } + } + Lex.Lex(); + break; + case lltok::backslash: { + // TypeRec ::= '\' 4 + Lex.Lex(); + unsigned Val; + if (ParseUInt32(Val)) return true; + OpaqueType *OT = OpaqueType::get(Context); //Use temporary placeholder. + UpRefs.push_back(UpRefRecord(Lex.getLoc(), Val, OT)); + Result = OT; + break; + } + } + + // Parse the type suffixes. + while (1) { + switch (Lex.getKind()) { + // End of type. + default: return false; + + // TypeRec ::= TypeRec '*' + case lltok::star: + if (Result.get()->isLabelTy()) + return TokError("basic block pointers are invalid"); + if (Result.get()->isVoidTy()) + return TokError("pointers to void are invalid; use i8* instead"); + if (!PointerType::isValidElementType(Result.get())) + return TokError("pointer to this type is invalid"); + Result = HandleUpRefs(PointerType::getUnqual(Result.get())); + Lex.Lex(); + break; + + // TypeRec ::= TypeRec 'addrspace' '(' uint32 ')' '*' + case lltok::kw_addrspace: { + if (Result.get()->isLabelTy()) + return TokError("basic block pointers are invalid"); + if (Result.get()->isVoidTy()) + return TokError("pointers to void are invalid; use i8* instead"); + if (!PointerType::isValidElementType(Result.get())) + return TokError("pointer to this type is invalid"); + unsigned AddrSpace; + if (ParseOptionalAddrSpace(AddrSpace) || + ParseToken(lltok::star, "expected '*' in address space")) + return true; + + Result = HandleUpRefs(PointerType::get(Result.get(), AddrSpace)); + break; + } + + /// Types '(' ArgTypeListI ')' OptFuncAttrs + case lltok::lparen: + if (ParseFunctionType(Result)) + return true; + break; + } + } +} + +/// ParseParameterList +/// ::= '(' ')' +/// ::= '(' Arg (',' Arg)* ')' +/// Arg +/// ::= Type OptionalAttributes Value OptionalAttributes +bool LLParser::ParseParameterList(SmallVectorImpl &ArgList, + PerFunctionState &PFS) { + if (ParseToken(lltok::lparen, "expected '(' in call")) + return true; + + while (Lex.getKind() != lltok::rparen) { + // If this isn't the first argument, we need a comma. + if (!ArgList.empty() && + ParseToken(lltok::comma, "expected ',' in argument list")) + return true; + + // Parse the argument. + LocTy ArgLoc; + PATypeHolder ArgTy(Type::getVoidTy(Context)); + unsigned ArgAttrs1, ArgAttrs2; + Value *V; + if (ParseType(ArgTy, ArgLoc) || + ParseOptionalAttrs(ArgAttrs1, 0) || + ParseValue(ArgTy, V, PFS) || + // FIXME: Should not allow attributes after the argument, remove this in + // LLVM 3.0. + ParseOptionalAttrs(ArgAttrs2, 3)) + return true; + ArgList.push_back(ParamInfo(ArgLoc, V, ArgAttrs1|ArgAttrs2)); + } + + Lex.Lex(); // Lex the ')'. + return false; +} + + + +/// ParseArgumentList - Parse the argument list for a function type or function +/// prototype. If 'inType' is true then we are parsing a FunctionType. +/// ::= '(' ArgTypeListI ')' +/// ArgTypeListI +/// ::= /*empty*/ +/// ::= '...' +/// ::= ArgTypeList ',' '...' +/// ::= ArgType (',' ArgType)* +/// +bool LLParser::ParseArgumentList(std::vector &ArgList, + bool &isVarArg, bool inType) { + isVarArg = false; + assert(Lex.getKind() == lltok::lparen); + Lex.Lex(); // eat the (. + + if (Lex.getKind() == lltok::rparen) { + // empty + } else if (Lex.getKind() == lltok::dotdotdot) { + isVarArg = true; + Lex.Lex(); + } else { + LocTy TypeLoc = Lex.getLoc(); + PATypeHolder ArgTy(Type::getVoidTy(Context)); + unsigned Attrs; + std::string Name; + + // If we're parsing a type, use ParseTypeRec, because we allow recursive + // types (such as a function returning a pointer to itself). If parsing a + // function prototype, we require fully resolved types. + if ((inType ? ParseTypeRec(ArgTy) : ParseType(ArgTy)) || + ParseOptionalAttrs(Attrs, 0)) return true; + + if (ArgTy->isVoidTy()) + return Error(TypeLoc, "argument can not have void type"); + + if (Lex.getKind() == lltok::LocalVar || + Lex.getKind() == lltok::StringConstant) { // FIXME: REMOVE IN LLVM 3.0 + Name = Lex.getStrVal(); + Lex.Lex(); + } + + if (!FunctionType::isValidArgumentType(ArgTy)) + return Error(TypeLoc, "invalid type for function argument"); + + ArgList.push_back(ArgInfo(TypeLoc, ArgTy, Attrs, Name)); + + while (EatIfPresent(lltok::comma)) { + // Handle ... at end of arg list. + if (EatIfPresent(lltok::dotdotdot)) { + isVarArg = true; + break; + } + + // Otherwise must be an argument type. + TypeLoc = Lex.getLoc(); + if ((inType ? ParseTypeRec(ArgTy) : ParseType(ArgTy)) || + ParseOptionalAttrs(Attrs, 0)) return true; + + if (ArgTy->isVoidTy()) + return Error(TypeLoc, "argument can not have void type"); + + if (Lex.getKind() == lltok::LocalVar || + Lex.getKind() == lltok::StringConstant) { // FIXME: REMOVE IN LLVM 3.0 + Name = Lex.getStrVal(); + Lex.Lex(); + } else { + Name = ""; + } + + if (!ArgTy->isFirstClassType() && !isa(ArgTy)) + return Error(TypeLoc, "invalid type for function argument"); + + ArgList.push_back(ArgInfo(TypeLoc, ArgTy, Attrs, Name)); + } + } + + return ParseToken(lltok::rparen, "expected ')' at end of argument list"); +} + +/// ParseFunctionType +/// ::= Type ArgumentList OptionalAttrs +bool LLParser::ParseFunctionType(PATypeHolder &Result) { + assert(Lex.getKind() == lltok::lparen); + + if (!FunctionType::isValidReturnType(Result)) + return TokError("invalid function return type"); + + std::vector ArgList; + bool isVarArg; + unsigned Attrs; + if (ParseArgumentList(ArgList, isVarArg, true) || + // FIXME: Allow, but ignore attributes on function types! + // FIXME: Remove in LLVM 3.0 + ParseOptionalAttrs(Attrs, 2)) + return true; + + // Reject names on the arguments lists. + for (unsigned i = 0, e = ArgList.size(); i != e; ++i) { + if (!ArgList[i].Name.empty()) + return Error(ArgList[i].Loc, "argument name invalid in function type"); + if (!ArgList[i].Attrs != 0) { + // Allow but ignore attributes on function types; this permits + // auto-upgrade. + // FIXME: REJECT ATTRIBUTES ON FUNCTION TYPES in LLVM 3.0 + } + } + + std::vector ArgListTy; + for (unsigned i = 0, e = ArgList.size(); i != e; ++i) + ArgListTy.push_back(ArgList[i].Type); + + Result = HandleUpRefs(FunctionType::get(Result.get(), + ArgListTy, isVarArg)); + return false; +} + +/// ParseStructType: Handles packed and unpacked types. parsed elsewhere. +/// TypeRec +/// ::= '{' '}' +/// ::= '{' TypeRec (',' TypeRec)* '}' +/// ::= '<' '{' '}' '>' +/// ::= '<' '{' TypeRec (',' TypeRec)* '}' '>' +bool LLParser::ParseStructType(PATypeHolder &Result, bool Packed) { + assert(Lex.getKind() == lltok::lbrace); + Lex.Lex(); // Consume the '{' + + if (EatIfPresent(lltok::rbrace)) { + Result = StructType::get(Context, Packed); + return false; + } + + std::vector ParamsList; + LocTy EltTyLoc = Lex.getLoc(); + if (ParseTypeRec(Result)) return true; + ParamsList.push_back(Result); + + if (Result->isVoidTy()) + return Error(EltTyLoc, "struct element can not have void type"); + if (!StructType::isValidElementType(Result)) + return Error(EltTyLoc, "invalid element type for struct"); + + while (EatIfPresent(lltok::comma)) { + EltTyLoc = Lex.getLoc(); + if (ParseTypeRec(Result)) return true; + + if (Result->isVoidTy()) + return Error(EltTyLoc, "struct element can not have void type"); + if (!StructType::isValidElementType(Result)) + return Error(EltTyLoc, "invalid element type for struct"); + + ParamsList.push_back(Result); + } + + if (ParseToken(lltok::rbrace, "expected '}' at end of struct")) + return true; + + std::vector ParamsListTy; + for (unsigned i = 0, e = ParamsList.size(); i != e; ++i) + ParamsListTy.push_back(ParamsList[i].get()); + Result = HandleUpRefs(StructType::get(Context, ParamsListTy, Packed)); + return false; +} + +/// ParseArrayVectorType - Parse an array or vector type, assuming the first +/// token has already been consumed. +/// TypeRec +/// ::= '[' APSINTVAL 'x' Types ']' +/// ::= '<' APSINTVAL 'x' Types '>' +bool LLParser::ParseArrayVectorType(PATypeHolder &Result, bool isVector) { + if (Lex.getKind() != lltok::APSInt || Lex.getAPSIntVal().isSigned() || + Lex.getAPSIntVal().getBitWidth() > 64) + return TokError("expected number in address space"); + + LocTy SizeLoc = Lex.getLoc(); + uint64_t Size = Lex.getAPSIntVal().getZExtValue(); + Lex.Lex(); + + if (ParseToken(lltok::kw_x, "expected 'x' after element count")) + return true; + + LocTy TypeLoc = Lex.getLoc(); + PATypeHolder EltTy(Type::getVoidTy(Context)); + if (ParseTypeRec(EltTy)) return true; + + if (EltTy->isVoidTy()) + return Error(TypeLoc, "array and vector element type cannot be void"); + + if (ParseToken(isVector ? lltok::greater : lltok::rsquare, + "expected end of sequential type")) + return true; + + if (isVector) { + if (Size == 0) + return Error(SizeLoc, "zero element vector is illegal"); + if ((unsigned)Size != Size) + return Error(SizeLoc, "size too large for vector"); + if (!VectorType::isValidElementType(EltTy)) + return Error(TypeLoc, "vector element type must be fp or integer"); + Result = VectorType::get(EltTy, unsigned(Size)); + } else { + if (!ArrayType::isValidElementType(EltTy)) + return Error(TypeLoc, "invalid array element type"); + Result = HandleUpRefs(ArrayType::get(EltTy, Size)); + } + return false; +} + +//===----------------------------------------------------------------------===// +// Function Semantic Analysis. +//===----------------------------------------------------------------------===// + +LLParser::PerFunctionState::PerFunctionState(LLParser &p, Function &f, + int functionNumber) + : P(p), F(f), FunctionNumber(functionNumber) { + + // Insert unnamed arguments into the NumberedVals list. + for (Function::arg_iterator AI = F.arg_begin(), E = F.arg_end(); + AI != E; ++AI) + if (!AI->hasName()) + NumberedVals.push_back(AI); +} + +LLParser::PerFunctionState::~PerFunctionState() { + // If there were any forward referenced non-basicblock values, delete them. + for (std::map >::iterator + I = ForwardRefVals.begin(), E = ForwardRefVals.end(); I != E; ++I) + if (!isa(I->second.first)) { + I->second.first->replaceAllUsesWith( + UndefValue::get(I->second.first->getType())); + delete I->second.first; + I->second.first = 0; + } + + for (std::map >::iterator + I = ForwardRefValIDs.begin(), E = ForwardRefValIDs.end(); I != E; ++I) + if (!isa(I->second.first)) { + I->second.first->replaceAllUsesWith( + UndefValue::get(I->second.first->getType())); + delete I->second.first; + I->second.first = 0; + } +} + +bool LLParser::PerFunctionState::FinishFunction() { + // Check to see if someone took the address of labels in this block. + if (!P.ForwardRefBlockAddresses.empty()) { + ValID FunctionID; + if (!F.getName().empty()) { + FunctionID.Kind = ValID::t_GlobalName; + FunctionID.StrVal = F.getName(); + } else { + FunctionID.Kind = ValID::t_GlobalID; + FunctionID.UIntVal = FunctionNumber; + } + + std::map > >::iterator + FRBAI = P.ForwardRefBlockAddresses.find(FunctionID); + if (FRBAI != P.ForwardRefBlockAddresses.end()) { + // Resolve all these references. + if (P.ResolveForwardRefBlockAddresses(&F, FRBAI->second, this)) + return true; + + P.ForwardRefBlockAddresses.erase(FRBAI); + } + } + + if (!ForwardRefVals.empty()) + return P.Error(ForwardRefVals.begin()->second.second, + "use of undefined value '%" + ForwardRefVals.begin()->first + + "'"); + if (!ForwardRefValIDs.empty()) + return P.Error(ForwardRefValIDs.begin()->second.second, + "use of undefined value '%" + + utostr(ForwardRefValIDs.begin()->first) + "'"); + return false; +} + + +/// GetVal - Get a value with the specified name or ID, creating a +/// forward reference record if needed. This can return null if the value +/// exists but does not have the right type. +Value *LLParser::PerFunctionState::GetVal(const std::string &Name, + const Type *Ty, LocTy Loc) { + // Look this name up in the normal function symbol table. + Value *Val = F.getValueSymbolTable().lookup(Name); + + // If this is a forward reference for the value, see if we already created a + // forward ref record. + if (Val == 0) { + std::map >::iterator + I = ForwardRefVals.find(Name); + if (I != ForwardRefVals.end()) + Val = I->second.first; + } + + // If we have the value in the symbol table or fwd-ref table, return it. + if (Val) { + if (Val->getType() == Ty) return Val; + if (Ty->isLabelTy()) + P.Error(Loc, "'%" + Name + "' is not a basic block"); + else + P.Error(Loc, "'%" + Name + "' defined with type '" + + Val->getType()->getDescription() + "'"); + return 0; + } + + // Don't make placeholders with invalid type. + if (!Ty->isFirstClassType() && !isa(Ty) && + Ty != Type::getLabelTy(F.getContext())) { + P.Error(Loc, "invalid use of a non-first-class type"); + return 0; + } + + // Otherwise, create a new forward reference for this value and remember it. + Value *FwdVal; + if (Ty->isLabelTy()) + FwdVal = BasicBlock::Create(F.getContext(), Name, &F); + else + FwdVal = new Argument(Ty, Name); + + ForwardRefVals[Name] = std::make_pair(FwdVal, Loc); + return FwdVal; +} + +Value *LLParser::PerFunctionState::GetVal(unsigned ID, const Type *Ty, + LocTy Loc) { + // Look this name up in the normal function symbol table. + Value *Val = ID < NumberedVals.size() ? NumberedVals[ID] : 0; + + // If this is a forward reference for the value, see if we already created a + // forward ref record. + if (Val == 0) { + std::map >::iterator + I = ForwardRefValIDs.find(ID); + if (I != ForwardRefValIDs.end()) + Val = I->second.first; + } + + // If we have the value in the symbol table or fwd-ref table, return it. + if (Val) { + if (Val->getType() == Ty) return Val; + if (Ty->isLabelTy()) + P.Error(Loc, "'%" + utostr(ID) + "' is not a basic block"); + else + P.Error(Loc, "'%" + utostr(ID) + "' defined with type '" + + Val->getType()->getDescription() + "'"); + return 0; + } + + if (!Ty->isFirstClassType() && !isa(Ty) && + Ty != Type::getLabelTy(F.getContext())) { + P.Error(Loc, "invalid use of a non-first-class type"); + return 0; + } + + // Otherwise, create a new forward reference for this value and remember it. + Value *FwdVal; + if (Ty->isLabelTy()) + FwdVal = BasicBlock::Create(F.getContext(), "", &F); + else + FwdVal = new Argument(Ty); + + ForwardRefValIDs[ID] = std::make_pair(FwdVal, Loc); + return FwdVal; +} + +/// SetInstName - After an instruction is parsed and inserted into its +/// basic block, this installs its name. +bool LLParser::PerFunctionState::SetInstName(int NameID, + const std::string &NameStr, + LocTy NameLoc, Instruction *Inst) { + // If this instruction has void type, it cannot have a name or ID specified. + if (Inst->getType()->isVoidTy()) { + if (NameID != -1 || !NameStr.empty()) + return P.Error(NameLoc, "instructions returning void cannot have a name"); + return false; + } + + // If this was a numbered instruction, verify that the instruction is the + // expected value and resolve any forward references. + if (NameStr.empty()) { + // If neither a name nor an ID was specified, just use the next ID. + if (NameID == -1) + NameID = NumberedVals.size(); + + if (unsigned(NameID) != NumberedVals.size()) + return P.Error(NameLoc, "instruction expected to be numbered '%" + + utostr(NumberedVals.size()) + "'"); + + std::map >::iterator FI = + ForwardRefValIDs.find(NameID); + if (FI != ForwardRefValIDs.end()) { + if (FI->second.first->getType() != Inst->getType()) + return P.Error(NameLoc, "instruction forward referenced with type '" + + FI->second.first->getType()->getDescription() + "'"); + FI->second.first->replaceAllUsesWith(Inst); + delete FI->second.first; + ForwardRefValIDs.erase(FI); + } + + NumberedVals.push_back(Inst); + return false; + } + + // Otherwise, the instruction had a name. Resolve forward refs and set it. + std::map >::iterator + FI = ForwardRefVals.find(NameStr); + if (FI != ForwardRefVals.end()) { + if (FI->second.first->getType() != Inst->getType()) + return P.Error(NameLoc, "instruction forward referenced with type '" + + FI->second.first->getType()->getDescription() + "'"); + FI->second.first->replaceAllUsesWith(Inst); + delete FI->second.first; + ForwardRefVals.erase(FI); + } + + // Set the name on the instruction. + Inst->setName(NameStr); + + if (Inst->getNameStr() != NameStr) + return P.Error(NameLoc, "multiple definition of local value named '" + + NameStr + "'"); + return false; +} + +/// GetBB - Get a basic block with the specified name or ID, creating a +/// forward reference record if needed. +BasicBlock *LLParser::PerFunctionState::GetBB(const std::string &Name, + LocTy Loc) { + return cast_or_null(GetVal(Name, + Type::getLabelTy(F.getContext()), Loc)); +} + +BasicBlock *LLParser::PerFunctionState::GetBB(unsigned ID, LocTy Loc) { + return cast_or_null(GetVal(ID, + Type::getLabelTy(F.getContext()), Loc)); +} + +/// DefineBB - Define the specified basic block, which is either named or +/// unnamed. If there is an error, this returns null otherwise it returns +/// the block being defined. +BasicBlock *LLParser::PerFunctionState::DefineBB(const std::string &Name, + LocTy Loc) { + BasicBlock *BB; + if (Name.empty()) + BB = GetBB(NumberedVals.size(), Loc); + else + BB = GetBB(Name, Loc); + if (BB == 0) return 0; // Already diagnosed error. + + // Move the block to the end of the function. Forward ref'd blocks are + // inserted wherever they happen to be referenced. + F.getBasicBlockList().splice(F.end(), F.getBasicBlockList(), BB); + + // Remove the block from forward ref sets. + if (Name.empty()) { + ForwardRefValIDs.erase(NumberedVals.size()); + NumberedVals.push_back(BB); + } else { + // BB forward references are already in the function symbol table. + ForwardRefVals.erase(Name); + } + + return BB; +} + +//===----------------------------------------------------------------------===// +// Constants. +//===----------------------------------------------------------------------===// + +/// ParseValID - Parse an abstract value that doesn't necessarily have a +/// type implied. For example, if we parse "4" we don't know what integer type +/// it has. The value will later be combined with its type and checked for +/// sanity. +bool LLParser::ParseValID(ValID &ID) { + ID.Loc = Lex.getLoc(); + switch (Lex.getKind()) { + default: return TokError("expected value token"); + case lltok::GlobalID: // @42 + ID.UIntVal = Lex.getUIntVal(); + ID.Kind = ValID::t_GlobalID; + break; + case lltok::GlobalVar: // @foo + ID.StrVal = Lex.getStrVal(); + ID.Kind = ValID::t_GlobalName; + break; + case lltok::LocalVarID: // %42 + ID.UIntVal = Lex.getUIntVal(); + ID.Kind = ValID::t_LocalID; + break; + case lltok::LocalVar: // %foo + case lltok::StringConstant: // "foo" - FIXME: REMOVE IN LLVM 3.0 + ID.StrVal = Lex.getStrVal(); + ID.Kind = ValID::t_LocalName; + break; + case lltok::Metadata: { // !{...} MDNode, !"foo" MDString + ID.Kind = ValID::t_Metadata; + Lex.Lex(); + if (Lex.getKind() == lltok::lbrace) { + SmallVector Elts; + if (ParseMDNodeVector(Elts) || + ParseToken(lltok::rbrace, "expected end of metadata node")) + return true; + + ID.MetadataVal = MDNode::get(Context, Elts.data(), Elts.size()); + return false; + } + + // Standalone metadata reference + // !{ ..., !42, ... } + if (!ParseMDNode(ID.MetadataVal)) + return false; + + // MDString: + // ::= '!' STRINGCONSTANT + if (ParseMDString(ID.MetadataVal)) return true; + ID.Kind = ValID::t_Metadata; + return false; + } + case lltok::APSInt: + ID.APSIntVal = Lex.getAPSIntVal(); + ID.Kind = ValID::t_APSInt; + break; + case lltok::APFloat: + ID.APFloatVal = Lex.getAPFloatVal(); + ID.Kind = ValID::t_APFloat; + break; + case lltok::kw_true: + ID.ConstantVal = ConstantInt::getTrue(Context); + ID.Kind = ValID::t_Constant; + break; + case lltok::kw_false: + ID.ConstantVal = ConstantInt::getFalse(Context); + ID.Kind = ValID::t_Constant; + break; + case lltok::kw_null: ID.Kind = ValID::t_Null; break; + case lltok::kw_undef: ID.Kind = ValID::t_Undef; break; + case lltok::kw_zeroinitializer: ID.Kind = ValID::t_Zero; break; + + case lltok::lbrace: { + // ValID ::= '{' ConstVector '}' + Lex.Lex(); + SmallVector Elts; + if (ParseGlobalValueVector(Elts) || + ParseToken(lltok::rbrace, "expected end of struct constant")) + return true; + + ID.ConstantVal = ConstantStruct::get(Context, Elts.data(), + Elts.size(), false); + ID.Kind = ValID::t_Constant; + return false; + } + case lltok::less: { + // ValID ::= '<' ConstVector '>' --> Vector. + // ValID ::= '<' '{' ConstVector '}' '>' --> Packed Struct. + Lex.Lex(); + bool isPackedStruct = EatIfPresent(lltok::lbrace); + + SmallVector Elts; + LocTy FirstEltLoc = Lex.getLoc(); + if (ParseGlobalValueVector(Elts) || + (isPackedStruct && + ParseToken(lltok::rbrace, "expected end of packed struct")) || + ParseToken(lltok::greater, "expected end of constant")) + return true; + + if (isPackedStruct) { + ID.ConstantVal = + ConstantStruct::get(Context, Elts.data(), Elts.size(), true); + ID.Kind = ValID::t_Constant; + return false; + } + + if (Elts.empty()) + return Error(ID.Loc, "constant vector must not be empty"); + + if (!Elts[0]->getType()->isInteger() && + !Elts[0]->getType()->isFloatingPoint()) + return Error(FirstEltLoc, + "vector elements must have integer or floating point type"); + + // Verify that all the vector elements have the same type. + for (unsigned i = 1, e = Elts.size(); i != e; ++i) + if (Elts[i]->getType() != Elts[0]->getType()) + return Error(FirstEltLoc, + "vector element #" + utostr(i) + + " is not of type '" + Elts[0]->getType()->getDescription()); + + ID.ConstantVal = ConstantVector::get(Elts.data(), Elts.size()); + ID.Kind = ValID::t_Constant; + return false; + } + case lltok::lsquare: { // Array Constant + Lex.Lex(); + SmallVector Elts; + LocTy FirstEltLoc = Lex.getLoc(); + if (ParseGlobalValueVector(Elts) || + ParseToken(lltok::rsquare, "expected end of array constant")) + return true; + + // Handle empty element. + if (Elts.empty()) { + // Use undef instead of an array because it's inconvenient to determine + // the element type at this point, there being no elements to examine. + ID.Kind = ValID::t_EmptyArray; + return false; + } + + if (!Elts[0]->getType()->isFirstClassType()) + return Error(FirstEltLoc, "invalid array element type: " + + Elts[0]->getType()->getDescription()); + + ArrayType *ATy = ArrayType::get(Elts[0]->getType(), Elts.size()); + + // Verify all elements are correct type! + for (unsigned i = 0, e = Elts.size(); i != e; ++i) { + if (Elts[i]->getType() != Elts[0]->getType()) + return Error(FirstEltLoc, + "array element #" + utostr(i) + + " is not of type '" +Elts[0]->getType()->getDescription()); + } + + ID.ConstantVal = ConstantArray::get(ATy, Elts.data(), Elts.size()); + ID.Kind = ValID::t_Constant; + return false; + } + case lltok::kw_c: // c "foo" + Lex.Lex(); + ID.ConstantVal = ConstantArray::get(Context, Lex.getStrVal(), false); + if (ParseToken(lltok::StringConstant, "expected string")) return true; + ID.Kind = ValID::t_Constant; + return false; + + case lltok::kw_asm: { + // ValID ::= 'asm' SideEffect? AlignStack? STRINGCONSTANT ',' STRINGCONSTANT + bool HasSideEffect, AlignStack; + Lex.Lex(); + if (ParseOptionalToken(lltok::kw_sideeffect, HasSideEffect) || + ParseOptionalToken(lltok::kw_alignstack, AlignStack) || + ParseStringConstant(ID.StrVal) || + ParseToken(lltok::comma, "expected comma in inline asm expression") || + ParseToken(lltok::StringConstant, "expected constraint string")) + return true; + ID.StrVal2 = Lex.getStrVal(); + ID.UIntVal = unsigned(HasSideEffect) | (unsigned(AlignStack)<<1); + ID.Kind = ValID::t_InlineAsm; + return false; + } + + case lltok::kw_blockaddress: { + // ValID ::= 'blockaddress' '(' @foo ',' %bar ')' + Lex.Lex(); + + ValID Fn, Label; + LocTy FnLoc, LabelLoc; + + if (ParseToken(lltok::lparen, "expected '(' in block address expression") || + ParseValID(Fn) || + ParseToken(lltok::comma, "expected comma in block address expression")|| + ParseValID(Label) || + ParseToken(lltok::rparen, "expected ')' in block address expression")) + return true; + + if (Fn.Kind != ValID::t_GlobalID && Fn.Kind != ValID::t_GlobalName) + return Error(Fn.Loc, "expected function name in blockaddress"); + if (Label.Kind != ValID::t_LocalID && Label.Kind != ValID::t_LocalName) + return Error(Label.Loc, "expected basic block name in blockaddress"); + + // Make a global variable as a placeholder for this reference. + GlobalVariable *FwdRef = new GlobalVariable(*M, Type::getInt8Ty(Context), + false, GlobalValue::InternalLinkage, + 0, ""); + ForwardRefBlockAddresses[Fn].push_back(std::make_pair(Label, FwdRef)); + ID.ConstantVal = FwdRef; + ID.Kind = ValID::t_Constant; + return false; + } + + case lltok::kw_trunc: + case lltok::kw_zext: + case lltok::kw_sext: + case lltok::kw_fptrunc: + case lltok::kw_fpext: + case lltok::kw_bitcast: + case lltok::kw_uitofp: + case lltok::kw_sitofp: + case lltok::kw_fptoui: + case lltok::kw_fptosi: + case lltok::kw_inttoptr: + case lltok::kw_ptrtoint: { + unsigned Opc = Lex.getUIntVal(); + PATypeHolder DestTy(Type::getVoidTy(Context)); + Constant *SrcVal; + Lex.Lex(); + if (ParseToken(lltok::lparen, "expected '(' after constantexpr cast") || + ParseGlobalTypeAndValue(SrcVal) || + ParseToken(lltok::kw_to, "expected 'to' in constantexpr cast") || + ParseType(DestTy) || + ParseToken(lltok::rparen, "expected ')' at end of constantexpr cast")) + return true; + if (!CastInst::castIsValid((Instruction::CastOps)Opc, SrcVal, DestTy)) + return Error(ID.Loc, "invalid cast opcode for cast from '" + + SrcVal->getType()->getDescription() + "' to '" + + DestTy->getDescription() + "'"); + ID.ConstantVal = ConstantExpr::getCast((Instruction::CastOps)Opc, + SrcVal, DestTy); + ID.Kind = ValID::t_Constant; + return false; + } + case lltok::kw_extractvalue: { + Lex.Lex(); + Constant *Val; + SmallVector Indices; + if (ParseToken(lltok::lparen, "expected '(' in extractvalue constantexpr")|| + ParseGlobalTypeAndValue(Val) || + ParseIndexList(Indices) || + ParseToken(lltok::rparen, "expected ')' in extractvalue constantexpr")) + return true; + if (Lex.getKind() == lltok::NamedOrCustomMD) + if (ParseOptionalCustomMetadata()) return true; + + if (!isa(Val->getType()) && !isa(Val->getType())) + return Error(ID.Loc, "extractvalue operand must be array or struct"); + if (!ExtractValueInst::getIndexedType(Val->getType(), Indices.begin(), + Indices.end())) + return Error(ID.Loc, "invalid indices for extractvalue"); + ID.ConstantVal = + ConstantExpr::getExtractValue(Val, Indices.data(), Indices.size()); + ID.Kind = ValID::t_Constant; + return false; + } + case lltok::kw_insertvalue: { + Lex.Lex(); + Constant *Val0, *Val1; + SmallVector Indices; + if (ParseToken(lltok::lparen, "expected '(' in insertvalue constantexpr")|| + ParseGlobalTypeAndValue(Val0) || + ParseToken(lltok::comma, "expected comma in insertvalue constantexpr")|| + ParseGlobalTypeAndValue(Val1) || + ParseIndexList(Indices) || + ParseToken(lltok::rparen, "expected ')' in insertvalue constantexpr")) + return true; + if (Lex.getKind() == lltok::NamedOrCustomMD) + if (ParseOptionalCustomMetadata()) return true; + if (!isa(Val0->getType()) && !isa(Val0->getType())) + return Error(ID.Loc, "extractvalue operand must be array or struct"); + if (!ExtractValueInst::getIndexedType(Val0->getType(), Indices.begin(), + Indices.end())) + return Error(ID.Loc, "invalid indices for insertvalue"); + ID.ConstantVal = ConstantExpr::getInsertValue(Val0, Val1, + Indices.data(), Indices.size()); + ID.Kind = ValID::t_Constant; + return false; + } + case lltok::kw_icmp: + case lltok::kw_fcmp: { + unsigned PredVal, Opc = Lex.getUIntVal(); + Constant *Val0, *Val1; + Lex.Lex(); + if (ParseCmpPredicate(PredVal, Opc) || + ParseToken(lltok::lparen, "expected '(' in compare constantexpr") || + ParseGlobalTypeAndValue(Val0) || + ParseToken(lltok::comma, "expected comma in compare constantexpr") || + ParseGlobalTypeAndValue(Val1) || + ParseToken(lltok::rparen, "expected ')' in compare constantexpr")) + return true; + + if (Val0->getType() != Val1->getType()) + return Error(ID.Loc, "compare operands must have the same type"); + + CmpInst::Predicate Pred = (CmpInst::Predicate)PredVal; + + if (Opc == Instruction::FCmp) { + if (!Val0->getType()->isFPOrFPVector()) + return Error(ID.Loc, "fcmp requires floating point operands"); + ID.ConstantVal = ConstantExpr::getFCmp(Pred, Val0, Val1); + } else { + assert(Opc == Instruction::ICmp && "Unexpected opcode for CmpInst!"); + if (!Val0->getType()->isIntOrIntVector() && + !isa(Val0->getType())) + return Error(ID.Loc, "icmp requires pointer or integer operands"); + ID.ConstantVal = ConstantExpr::getICmp(Pred, Val0, Val1); + } + ID.Kind = ValID::t_Constant; + return false; + } + + // Binary Operators. + case lltok::kw_add: + case lltok::kw_fadd: + case lltok::kw_sub: + case lltok::kw_fsub: + case lltok::kw_mul: + case lltok::kw_fmul: + case lltok::kw_udiv: + case lltok::kw_sdiv: + case lltok::kw_fdiv: + case lltok::kw_urem: + case lltok::kw_srem: + case lltok::kw_frem: { + bool NUW = false; + bool NSW = false; + bool Exact = false; + unsigned Opc = Lex.getUIntVal(); + Constant *Val0, *Val1; + Lex.Lex(); + LocTy ModifierLoc = Lex.getLoc(); + if (Opc == Instruction::Add || + Opc == Instruction::Sub || + Opc == Instruction::Mul) { + if (EatIfPresent(lltok::kw_nuw)) + NUW = true; + if (EatIfPresent(lltok::kw_nsw)) { + NSW = true; + if (EatIfPresent(lltok::kw_nuw)) + NUW = true; + } + } else if (Opc == Instruction::SDiv) { + if (EatIfPresent(lltok::kw_exact)) + Exact = true; + } + if (ParseToken(lltok::lparen, "expected '(' in binary constantexpr") || + ParseGlobalTypeAndValue(Val0) || + ParseToken(lltok::comma, "expected comma in binary constantexpr") || + ParseGlobalTypeAndValue(Val1) || + ParseToken(lltok::rparen, "expected ')' in binary constantexpr")) + return true; + if (Val0->getType() != Val1->getType()) + return Error(ID.Loc, "operands of constexpr must have same type"); + if (!Val0->getType()->isIntOrIntVector()) { + if (NUW) + return Error(ModifierLoc, "nuw only applies to integer operations"); + if (NSW) + return Error(ModifierLoc, "nsw only applies to integer operations"); + } + // API compatibility: Accept either integer or floating-point types with + // add, sub, and mul. + if (!Val0->getType()->isIntOrIntVector() && + !Val0->getType()->isFPOrFPVector()) + return Error(ID.Loc,"constexpr requires integer, fp, or vector operands"); + unsigned Flags = 0; + if (NUW) Flags |= OverflowingBinaryOperator::NoUnsignedWrap; + if (NSW) Flags |= OverflowingBinaryOperator::NoSignedWrap; + if (Exact) Flags |= SDivOperator::IsExact; + Constant *C = ConstantExpr::get(Opc, Val0, Val1, Flags); + ID.ConstantVal = C; + ID.Kind = ValID::t_Constant; + return false; + } + + // Logical Operations + case lltok::kw_shl: + case lltok::kw_lshr: + case lltok::kw_ashr: + case lltok::kw_and: + case lltok::kw_or: + case lltok::kw_xor: { + unsigned Opc = Lex.getUIntVal(); + Constant *Val0, *Val1; + Lex.Lex(); + if (ParseToken(lltok::lparen, "expected '(' in logical constantexpr") || + ParseGlobalTypeAndValue(Val0) || + ParseToken(lltok::comma, "expected comma in logical constantexpr") || + ParseGlobalTypeAndValue(Val1) || + ParseToken(lltok::rparen, "expected ')' in logical constantexpr")) + return true; + if (Val0->getType() != Val1->getType()) + return Error(ID.Loc, "operands of constexpr must have same type"); + if (!Val0->getType()->isIntOrIntVector()) + return Error(ID.Loc, + "constexpr requires integer or integer vector operands"); + ID.ConstantVal = ConstantExpr::get(Opc, Val0, Val1); + ID.Kind = ValID::t_Constant; + return false; + } + + case lltok::kw_getelementptr: + case lltok::kw_shufflevector: + case lltok::kw_insertelement: + case lltok::kw_extractelement: + case lltok::kw_select: { + unsigned Opc = Lex.getUIntVal(); + SmallVector Elts; + bool InBounds = false; + Lex.Lex(); + if (Opc == Instruction::GetElementPtr) + InBounds = EatIfPresent(lltok::kw_inbounds); + if (ParseToken(lltok::lparen, "expected '(' in constantexpr") || + ParseGlobalValueVector(Elts) || + ParseToken(lltok::rparen, "expected ')' in constantexpr")) + return true; + + if (Opc == Instruction::GetElementPtr) { + if (Elts.size() == 0 || !isa(Elts[0]->getType())) + return Error(ID.Loc, "getelementptr requires pointer operand"); + + if (!GetElementPtrInst::getIndexedType(Elts[0]->getType(), + (Value**)(Elts.data() + 1), + Elts.size() - 1)) + return Error(ID.Loc, "invalid indices for getelementptr"); + ID.ConstantVal = InBounds ? + ConstantExpr::getInBoundsGetElementPtr(Elts[0], + Elts.data() + 1, + Elts.size() - 1) : + ConstantExpr::getGetElementPtr(Elts[0], + Elts.data() + 1, Elts.size() - 1); + } else if (Opc == Instruction::Select) { + if (Elts.size() != 3) + return Error(ID.Loc, "expected three operands to select"); + if (const char *Reason = SelectInst::areInvalidOperands(Elts[0], Elts[1], + Elts[2])) + return Error(ID.Loc, Reason); + ID.ConstantVal = ConstantExpr::getSelect(Elts[0], Elts[1], Elts[2]); + } else if (Opc == Instruction::ShuffleVector) { + if (Elts.size() != 3) + return Error(ID.Loc, "expected three operands to shufflevector"); + if (!ShuffleVectorInst::isValidOperands(Elts[0], Elts[1], Elts[2])) + return Error(ID.Loc, "invalid operands to shufflevector"); + ID.ConstantVal = + ConstantExpr::getShuffleVector(Elts[0], Elts[1],Elts[2]); + } else if (Opc == Instruction::ExtractElement) { + if (Elts.size() != 2) + return Error(ID.Loc, "expected two operands to extractelement"); + if (!ExtractElementInst::isValidOperands(Elts[0], Elts[1])) + return Error(ID.Loc, "invalid extractelement operands"); + ID.ConstantVal = ConstantExpr::getExtractElement(Elts[0], Elts[1]); + } else { + assert(Opc == Instruction::InsertElement && "Unknown opcode"); + if (Elts.size() != 3) + return Error(ID.Loc, "expected three operands to insertelement"); + if (!InsertElementInst::isValidOperands(Elts[0], Elts[1], Elts[2])) + return Error(ID.Loc, "invalid insertelement operands"); + ID.ConstantVal = + ConstantExpr::getInsertElement(Elts[0], Elts[1],Elts[2]); + } + + ID.Kind = ValID::t_Constant; + return false; + } + } + + Lex.Lex(); + return false; +} + +/// ParseGlobalValue - Parse a global value with the specified type. +bool LLParser::ParseGlobalValue(const Type *Ty, Constant *&V) { + V = 0; + ValID ID; + return ParseValID(ID) || + ConvertGlobalValIDToValue(Ty, ID, V); +} + +/// ConvertGlobalValIDToValue - Apply a type to a ValID to get a fully resolved +/// constant. +bool LLParser::ConvertGlobalValIDToValue(const Type *Ty, ValID &ID, + Constant *&V) { + if (isa(Ty)) + return Error(ID.Loc, "functions are not values, refer to them as pointers"); + + switch (ID.Kind) { + default: llvm_unreachable("Unknown ValID!"); + case ValID::t_Metadata: + return Error(ID.Loc, "invalid use of metadata"); + case ValID::t_LocalID: + case ValID::t_LocalName: + return Error(ID.Loc, "invalid use of function-local name"); + case ValID::t_InlineAsm: + return Error(ID.Loc, "inline asm can only be an operand of call/invoke"); + case ValID::t_GlobalName: + V = GetGlobalVal(ID.StrVal, Ty, ID.Loc); + return V == 0; + case ValID::t_GlobalID: + V = GetGlobalVal(ID.UIntVal, Ty, ID.Loc); + return V == 0; + case ValID::t_APSInt: + if (!isa(Ty)) + return Error(ID.Loc, "integer constant must have integer type"); + ID.APSIntVal.extOrTrunc(Ty->getPrimitiveSizeInBits()); + V = ConstantInt::get(Context, ID.APSIntVal); + return false; + case ValID::t_APFloat: + if (!Ty->isFloatingPoint() || + !ConstantFP::isValueValidForType(Ty, ID.APFloatVal)) + return Error(ID.Loc, "floating point constant invalid for type"); + + // The lexer has no type info, so builds all float and double FP constants + // as double. Fix this here. Long double does not need this. + if (&ID.APFloatVal.getSemantics() == &APFloat::IEEEdouble && + Ty->isFloatTy()) { + bool Ignored; + ID.APFloatVal.convert(APFloat::IEEEsingle, APFloat::rmNearestTiesToEven, + &Ignored); + } + V = ConstantFP::get(Context, ID.APFloatVal); + + if (V->getType() != Ty) + return Error(ID.Loc, "floating point constant does not have type '" + + Ty->getDescription() + "'"); + + return false; + case ValID::t_Null: + if (!isa(Ty)) + return Error(ID.Loc, "null must be a pointer type"); + V = ConstantPointerNull::get(cast(Ty)); + return false; + case ValID::t_Undef: + // FIXME: LabelTy should not be a first-class type. + if ((!Ty->isFirstClassType() || Ty->isLabelTy()) && + !isa(Ty)) + return Error(ID.Loc, "invalid type for undef constant"); + V = UndefValue::get(Ty); + return false; + case ValID::t_EmptyArray: + if (!isa(Ty) || cast(Ty)->getNumElements() != 0) + return Error(ID.Loc, "invalid empty array initializer"); + V = UndefValue::get(Ty); + return false; + case ValID::t_Zero: + // FIXME: LabelTy should not be a first-class type. + if (!Ty->isFirstClassType() || Ty->isLabelTy()) + return Error(ID.Loc, "invalid type for null constant"); + V = Constant::getNullValue(Ty); + return false; + case ValID::t_Constant: + if (ID.ConstantVal->getType() != Ty) + return Error(ID.Loc, "constant expression type mismatch"); + V = ID.ConstantVal; + return false; + } +} + +bool LLParser::ParseGlobalTypeAndValue(Constant *&V) { + PATypeHolder Type(Type::getVoidTy(Context)); + return ParseType(Type) || + ParseGlobalValue(Type, V); +} + +/// ParseGlobalValueVector +/// ::= /*empty*/ +/// ::= TypeAndValue (',' TypeAndValue)* +bool LLParser::ParseGlobalValueVector(SmallVectorImpl &Elts) { + // Empty list. + if (Lex.getKind() == lltok::rbrace || + Lex.getKind() == lltok::rsquare || + Lex.getKind() == lltok::greater || + Lex.getKind() == lltok::rparen) + return false; + + Constant *C; + if (ParseGlobalTypeAndValue(C)) return true; + Elts.push_back(C); + + while (EatIfPresent(lltok::comma)) { + if (ParseGlobalTypeAndValue(C)) return true; + Elts.push_back(C); + } + + return false; +} + + +//===----------------------------------------------------------------------===// +// Function Parsing. +//===----------------------------------------------------------------------===// + +bool LLParser::ConvertValIDToValue(const Type *Ty, ValID &ID, Value *&V, + PerFunctionState &PFS) { + if (ID.Kind == ValID::t_LocalID) + V = PFS.GetVal(ID.UIntVal, Ty, ID.Loc); + else if (ID.Kind == ValID::t_LocalName) + V = PFS.GetVal(ID.StrVal, Ty, ID.Loc); + else if (ID.Kind == ValID::t_InlineAsm) { + const PointerType *PTy = dyn_cast(Ty); + const FunctionType *FTy = + PTy ? dyn_cast(PTy->getElementType()) : 0; + if (!FTy || !InlineAsm::Verify(FTy, ID.StrVal2)) + return Error(ID.Loc, "invalid type for inline asm constraint string"); + V = InlineAsm::get(FTy, ID.StrVal, ID.StrVal2, ID.UIntVal&1, ID.UIntVal>>1); + return false; + } else if (ID.Kind == ValID::t_Metadata) { + V = ID.MetadataVal; + } else { + Constant *C; + if (ConvertGlobalValIDToValue(Ty, ID, C)) return true; + V = C; + return false; + } + + return V == 0; +} + +bool LLParser::ParseValue(const Type *Ty, Value *&V, PerFunctionState &PFS) { + V = 0; + ValID ID; + return ParseValID(ID) || + ConvertValIDToValue(Ty, ID, V, PFS); +} + +bool LLParser::ParseTypeAndValue(Value *&V, PerFunctionState &PFS) { + PATypeHolder T(Type::getVoidTy(Context)); + return ParseType(T) || + ParseValue(T, V, PFS); +} + +bool LLParser::ParseTypeAndBasicBlock(BasicBlock *&BB, LocTy &Loc, + PerFunctionState &PFS) { + Value *V; + Loc = Lex.getLoc(); + if (ParseTypeAndValue(V, PFS)) return true; + if (!isa(V)) + return Error(Loc, "expected a basic block"); + BB = cast(V); + return false; +} + + +/// FunctionHeader +/// ::= OptionalLinkage OptionalVisibility OptionalCallingConv OptRetAttrs +/// Type GlobalName '(' ArgList ')' OptFuncAttrs OptSection +/// OptionalAlign OptGC +bool LLParser::ParseFunctionHeader(Function *&Fn, bool isDefine) { + // Parse the linkage. + LocTy LinkageLoc = Lex.getLoc(); + unsigned Linkage; + + unsigned Visibility, RetAttrs; + CallingConv::ID CC; + PATypeHolder RetType(Type::getVoidTy(Context)); + LocTy RetTypeLoc = Lex.getLoc(); + if (ParseOptionalLinkage(Linkage) || + ParseOptionalVisibility(Visibility) || + ParseOptionalCallingConv(CC) || + ParseOptionalAttrs(RetAttrs, 1) || + ParseType(RetType, RetTypeLoc, true /*void allowed*/)) + return true; + + // Verify that the linkage is ok. + switch ((GlobalValue::LinkageTypes)Linkage) { + case GlobalValue::ExternalLinkage: + break; // always ok. + case GlobalValue::DLLImportLinkage: + case GlobalValue::ExternalWeakLinkage: + if (isDefine) + return Error(LinkageLoc, "invalid linkage for function definition"); + break; + case GlobalValue::PrivateLinkage: + case GlobalValue::LinkerPrivateLinkage: + case GlobalValue::InternalLinkage: + case GlobalValue::AvailableExternallyLinkage: + case GlobalValue::LinkOnceAnyLinkage: + case GlobalValue::LinkOnceODRLinkage: + case GlobalValue::WeakAnyLinkage: + case GlobalValue::WeakODRLinkage: + case GlobalValue::DLLExportLinkage: + if (!isDefine) + return Error(LinkageLoc, "invalid linkage for function declaration"); + break; + case GlobalValue::AppendingLinkage: + case GlobalValue::GhostLinkage: + case GlobalValue::CommonLinkage: + return Error(LinkageLoc, "invalid function linkage type"); + } + + if (!FunctionType::isValidReturnType(RetType) || + isa(RetType)) + return Error(RetTypeLoc, "invalid function return type"); + + LocTy NameLoc = Lex.getLoc(); + + std::string FunctionName; + if (Lex.getKind() == lltok::GlobalVar) { + FunctionName = Lex.getStrVal(); + } else if (Lex.getKind() == lltok::GlobalID) { // @42 is ok. + unsigned NameID = Lex.getUIntVal(); + + if (NameID != NumberedVals.size()) + return TokError("function expected to be numbered '%" + + utostr(NumberedVals.size()) + "'"); + } else { + return TokError("expected function name"); + } + + Lex.Lex(); + + if (Lex.getKind() != lltok::lparen) + return TokError("expected '(' in function argument list"); + + std::vector ArgList; + bool isVarArg; + unsigned FuncAttrs; + std::string Section; + unsigned Alignment; + std::string GC; + + if (ParseArgumentList(ArgList, isVarArg, false) || + ParseOptionalAttrs(FuncAttrs, 2) || + (EatIfPresent(lltok::kw_section) && + ParseStringConstant(Section)) || + ParseOptionalAlignment(Alignment) || + (EatIfPresent(lltok::kw_gc) && + ParseStringConstant(GC))) + return true; + + // If the alignment was parsed as an attribute, move to the alignment field. + if (FuncAttrs & Attribute::Alignment) { + Alignment = Attribute::getAlignmentFromAttrs(FuncAttrs); + FuncAttrs &= ~Attribute::Alignment; + } + + // Okay, if we got here, the function is syntactically valid. Convert types + // and do semantic checks. + std::vector ParamTypeList; + SmallVector Attrs; + // FIXME : In 3.0, stop accepting zext, sext and inreg as optional function + // attributes. + unsigned ObsoleteFuncAttrs = Attribute::ZExt|Attribute::SExt|Attribute::InReg; + if (FuncAttrs & ObsoleteFuncAttrs) { + RetAttrs |= FuncAttrs & ObsoleteFuncAttrs; + FuncAttrs &= ~ObsoleteFuncAttrs; + } + + if (RetAttrs != Attribute::None) + Attrs.push_back(AttributeWithIndex::get(0, RetAttrs)); + + for (unsigned i = 0, e = ArgList.size(); i != e; ++i) { + ParamTypeList.push_back(ArgList[i].Type); + if (ArgList[i].Attrs != Attribute::None) + Attrs.push_back(AttributeWithIndex::get(i+1, ArgList[i].Attrs)); + } + + if (FuncAttrs != Attribute::None) + Attrs.push_back(AttributeWithIndex::get(~0, FuncAttrs)); + + AttrListPtr PAL = AttrListPtr::get(Attrs.begin(), Attrs.end()); + + if (PAL.paramHasAttr(1, Attribute::StructRet) && + RetType != Type::getVoidTy(Context)) + return Error(RetTypeLoc, "functions with 'sret' argument must return void"); + + const FunctionType *FT = + FunctionType::get(RetType, ParamTypeList, isVarArg); + const PointerType *PFT = PointerType::getUnqual(FT); + + Fn = 0; + if (!FunctionName.empty()) { + // If this was a definition of a forward reference, remove the definition + // from the forward reference table and fill in the forward ref. + std::map >::iterator FRVI = + ForwardRefVals.find(FunctionName); + if (FRVI != ForwardRefVals.end()) { + Fn = M->getFunction(FunctionName); + ForwardRefVals.erase(FRVI); + } else if ((Fn = M->getFunction(FunctionName))) { + // If this function already exists in the symbol table, then it is + // multiply defined. We accept a few cases for old backwards compat. + // FIXME: Remove this stuff for LLVM 3.0. + if (Fn->getType() != PFT || Fn->getAttributes() != PAL || + (!Fn->isDeclaration() && isDefine)) { + // If the redefinition has different type or different attributes, + // reject it. If both have bodies, reject it. + return Error(NameLoc, "invalid redefinition of function '" + + FunctionName + "'"); + } else if (Fn->isDeclaration()) { + // Make sure to strip off any argument names so we can't get conflicts. + for (Function::arg_iterator AI = Fn->arg_begin(), AE = Fn->arg_end(); + AI != AE; ++AI) + AI->setName(""); + } + } else if (M->getNamedValue(FunctionName)) { + return Error(NameLoc, "redefinition of function '@" + FunctionName + "'"); + } + + } else { + // If this is a definition of a forward referenced function, make sure the + // types agree. + std::map >::iterator I + = ForwardRefValIDs.find(NumberedVals.size()); + if (I != ForwardRefValIDs.end()) { + Fn = cast(I->second.first); + if (Fn->getType() != PFT) + return Error(NameLoc, "type of definition and forward reference of '@" + + utostr(NumberedVals.size()) +"' disagree"); + ForwardRefValIDs.erase(I); + } + } + + if (Fn == 0) + Fn = Function::Create(FT, GlobalValue::ExternalLinkage, FunctionName, M); + else // Move the forward-reference to the correct spot in the module. + M->getFunctionList().splice(M->end(), M->getFunctionList(), Fn); + + if (FunctionName.empty()) + NumberedVals.push_back(Fn); + + Fn->setLinkage((GlobalValue::LinkageTypes)Linkage); + Fn->setVisibility((GlobalValue::VisibilityTypes)Visibility); + Fn->setCallingConv(CC); + Fn->setAttributes(PAL); + Fn->setAlignment(Alignment); + Fn->setSection(Section); + if (!GC.empty()) Fn->setGC(GC.c_str()); + + // Add all of the arguments we parsed to the function. + Function::arg_iterator ArgIt = Fn->arg_begin(); + for (unsigned i = 0, e = ArgList.size(); i != e; ++i, ++ArgIt) { + // If we run out of arguments in the Function prototype, exit early. + // FIXME: REMOVE THIS IN LLVM 3.0, this is just for the mismatch case above. + if (ArgIt == Fn->arg_end()) break; + + // If the argument has a name, insert it into the argument symbol table. + if (ArgList[i].Name.empty()) continue; + + // Set the name, if it conflicted, it will be auto-renamed. + ArgIt->setName(ArgList[i].Name); + + if (ArgIt->getNameStr() != ArgList[i].Name) + return Error(ArgList[i].Loc, "redefinition of argument '%" + + ArgList[i].Name + "'"); + } + + return false; +} + + +/// ParseFunctionBody +/// ::= '{' BasicBlock+ '}' +/// ::= 'begin' BasicBlock+ 'end' // FIXME: remove in LLVM 3.0 +/// +bool LLParser::ParseFunctionBody(Function &Fn) { + if (Lex.getKind() != lltok::lbrace && Lex.getKind() != lltok::kw_begin) + return TokError("expected '{' in function body"); + Lex.Lex(); // eat the {. + + int FunctionNumber = -1; + if (!Fn.hasName()) FunctionNumber = NumberedVals.size()-1; + + PerFunctionState PFS(*this, Fn, FunctionNumber); + + while (Lex.getKind() != lltok::rbrace && Lex.getKind() != lltok::kw_end) + if (ParseBasicBlock(PFS)) return true; + + // Eat the }. + Lex.Lex(); + + // Verify function is ok. + return PFS.FinishFunction(); +} + +/// ParseBasicBlock +/// ::= LabelStr? Instruction* +bool LLParser::ParseBasicBlock(PerFunctionState &PFS) { + // If this basic block starts out with a name, remember it. + std::string Name; + LocTy NameLoc = Lex.getLoc(); + if (Lex.getKind() == lltok::LabelStr) { + Name = Lex.getStrVal(); + Lex.Lex(); + } + + BasicBlock *BB = PFS.DefineBB(Name, NameLoc); + if (BB == 0) return true; + + std::string NameStr; + + // Parse the instructions in this block until we get a terminator. + Instruction *Inst; + do { + // This instruction may have three possibilities for a name: a) none + // specified, b) name specified "%foo =", c) number specified: "%4 =". + LocTy NameLoc = Lex.getLoc(); + int NameID = -1; + NameStr = ""; + + if (Lex.getKind() == lltok::LocalVarID) { + NameID = Lex.getUIntVal(); + Lex.Lex(); + if (ParseToken(lltok::equal, "expected '=' after instruction id")) + return true; + } else if (Lex.getKind() == lltok::LocalVar || + // FIXME: REMOVE IN LLVM 3.0 + Lex.getKind() == lltok::StringConstant) { + NameStr = Lex.getStrVal(); + Lex.Lex(); + if (ParseToken(lltok::equal, "expected '=' after instruction name")) + return true; + } + + if (ParseInstruction(Inst, BB, PFS)) return true; + if (EatIfPresent(lltok::comma)) + ParseOptionalCustomMetadata(); + + // Set metadata attached with this instruction. + MetadataContext &TheMetadata = M->getContext().getMetadata(); + for (SmallVector, 2>::iterator + MDI = MDsOnInst.begin(), MDE = MDsOnInst.end(); MDI != MDE; ++MDI) + TheMetadata.addMD(MDI->first, MDI->second, Inst); + MDsOnInst.clear(); + + BB->getInstList().push_back(Inst); + + // Set the name on the instruction. + if (PFS.SetInstName(NameID, NameStr, NameLoc, Inst)) return true; + } while (!isa(Inst)); + + return false; +} + +//===----------------------------------------------------------------------===// +// Instruction Parsing. +//===----------------------------------------------------------------------===// + +/// ParseInstruction - Parse one of the many different instructions. +/// +bool LLParser::ParseInstruction(Instruction *&Inst, BasicBlock *BB, + PerFunctionState &PFS) { + lltok::Kind Token = Lex.getKind(); + if (Token == lltok::Eof) + return TokError("found end of file when expecting more instructions"); + LocTy Loc = Lex.getLoc(); + unsigned KeywordVal = Lex.getUIntVal(); + Lex.Lex(); // Eat the keyword. + + switch (Token) { + default: return Error(Loc, "expected instruction opcode"); + // Terminator Instructions. + case lltok::kw_unwind: Inst = new UnwindInst(Context); return false; + case lltok::kw_unreachable: Inst = new UnreachableInst(Context); return false; + case lltok::kw_ret: return ParseRet(Inst, BB, PFS); + case lltok::kw_br: return ParseBr(Inst, PFS); + case lltok::kw_switch: return ParseSwitch(Inst, PFS); + case lltok::kw_indirectbr: return ParseIndirectBr(Inst, PFS); + case lltok::kw_invoke: return ParseInvoke(Inst, PFS); + // Binary Operators. + case lltok::kw_add: + case lltok::kw_sub: + case lltok::kw_mul: { + bool NUW = false; + bool NSW = false; + LocTy ModifierLoc = Lex.getLoc(); + if (EatIfPresent(lltok::kw_nuw)) + NUW = true; + if (EatIfPresent(lltok::kw_nsw)) { + NSW = true; + if (EatIfPresent(lltok::kw_nuw)) + NUW = true; + } + // API compatibility: Accept either integer or floating-point types. + bool Result = ParseArithmetic(Inst, PFS, KeywordVal, 0); + if (!Result) { + if (!Inst->getType()->isIntOrIntVector()) { + if (NUW) + return Error(ModifierLoc, "nuw only applies to integer operations"); + if (NSW) + return Error(ModifierLoc, "nsw only applies to integer operations"); + } + if (NUW) + cast(Inst)->setHasNoUnsignedWrap(true); + if (NSW) + cast(Inst)->setHasNoSignedWrap(true); + } + return Result; + } + case lltok::kw_fadd: + case lltok::kw_fsub: + case lltok::kw_fmul: return ParseArithmetic(Inst, PFS, KeywordVal, 2); + + case lltok::kw_sdiv: { + bool Exact = false; + if (EatIfPresent(lltok::kw_exact)) + Exact = true; + bool Result = ParseArithmetic(Inst, PFS, KeywordVal, 1); + if (!Result) + if (Exact) + cast(Inst)->setIsExact(true); + return Result; + } + + case lltok::kw_udiv: + case lltok::kw_urem: + case lltok::kw_srem: return ParseArithmetic(Inst, PFS, KeywordVal, 1); + case lltok::kw_fdiv: + case lltok::kw_frem: return ParseArithmetic(Inst, PFS, KeywordVal, 2); + case lltok::kw_shl: + case lltok::kw_lshr: + case lltok::kw_ashr: + case lltok::kw_and: + case lltok::kw_or: + case lltok::kw_xor: return ParseLogical(Inst, PFS, KeywordVal); + case lltok::kw_icmp: + case lltok::kw_fcmp: return ParseCompare(Inst, PFS, KeywordVal); + // Casts. + case lltok::kw_trunc: + case lltok::kw_zext: + case lltok::kw_sext: + case lltok::kw_fptrunc: + case lltok::kw_fpext: + case lltok::kw_bitcast: + case lltok::kw_uitofp: + case lltok::kw_sitofp: + case lltok::kw_fptoui: + case lltok::kw_fptosi: + case lltok::kw_inttoptr: + case lltok::kw_ptrtoint: return ParseCast(Inst, PFS, KeywordVal); + // Other. + case lltok::kw_select: return ParseSelect(Inst, PFS); + case lltok::kw_va_arg: return ParseVA_Arg(Inst, PFS); + case lltok::kw_extractelement: return ParseExtractElement(Inst, PFS); + case lltok::kw_insertelement: return ParseInsertElement(Inst, PFS); + case lltok::kw_shufflevector: return ParseShuffleVector(Inst, PFS); + case lltok::kw_phi: return ParsePHI(Inst, PFS); + case lltok::kw_call: return ParseCall(Inst, PFS, false); + case lltok::kw_tail: return ParseCall(Inst, PFS, true); + // Memory. + case lltok::kw_alloca: return ParseAlloc(Inst, PFS); + case lltok::kw_malloc: return ParseAlloc(Inst, PFS, BB, false); + case lltok::kw_free: return ParseFree(Inst, PFS, BB); + case lltok::kw_load: return ParseLoad(Inst, PFS, false); + case lltok::kw_store: return ParseStore(Inst, PFS, false); + case lltok::kw_volatile: + if (EatIfPresent(lltok::kw_load)) + return ParseLoad(Inst, PFS, true); + else if (EatIfPresent(lltok::kw_store)) + return ParseStore(Inst, PFS, true); + else + return TokError("expected 'load' or 'store'"); + case lltok::kw_getresult: return ParseGetResult(Inst, PFS); + case lltok::kw_getelementptr: return ParseGetElementPtr(Inst, PFS); + case lltok::kw_extractvalue: return ParseExtractValue(Inst, PFS); + case lltok::kw_insertvalue: return ParseInsertValue(Inst, PFS); + } +} + +/// ParseCmpPredicate - Parse an integer or fp predicate, based on Kind. +bool LLParser::ParseCmpPredicate(unsigned &P, unsigned Opc) { + if (Opc == Instruction::FCmp) { + switch (Lex.getKind()) { + default: TokError("expected fcmp predicate (e.g. 'oeq')"); + case lltok::kw_oeq: P = CmpInst::FCMP_OEQ; break; + case lltok::kw_one: P = CmpInst::FCMP_ONE; break; + case lltok::kw_olt: P = CmpInst::FCMP_OLT; break; + case lltok::kw_ogt: P = CmpInst::FCMP_OGT; break; + case lltok::kw_ole: P = CmpInst::FCMP_OLE; break; + case lltok::kw_oge: P = CmpInst::FCMP_OGE; break; + case lltok::kw_ord: P = CmpInst::FCMP_ORD; break; + case lltok::kw_uno: P = CmpInst::FCMP_UNO; break; + case lltok::kw_ueq: P = CmpInst::FCMP_UEQ; break; + case lltok::kw_une: P = CmpInst::FCMP_UNE; break; + case lltok::kw_ult: P = CmpInst::FCMP_ULT; break; + case lltok::kw_ugt: P = CmpInst::FCMP_UGT; break; + case lltok::kw_ule: P = CmpInst::FCMP_ULE; break; + case lltok::kw_uge: P = CmpInst::FCMP_UGE; break; + case lltok::kw_true: P = CmpInst::FCMP_TRUE; break; + case lltok::kw_false: P = CmpInst::FCMP_FALSE; break; + } + } else { + switch (Lex.getKind()) { + default: TokError("expected icmp predicate (e.g. 'eq')"); + case lltok::kw_eq: P = CmpInst::ICMP_EQ; break; + case lltok::kw_ne: P = CmpInst::ICMP_NE; break; + case lltok::kw_slt: P = CmpInst::ICMP_SLT; break; + case lltok::kw_sgt: P = CmpInst::ICMP_SGT; break; + case lltok::kw_sle: P = CmpInst::ICMP_SLE; break; + case lltok::kw_sge: P = CmpInst::ICMP_SGE; break; + case lltok::kw_ult: P = CmpInst::ICMP_ULT; break; + case lltok::kw_ugt: P = CmpInst::ICMP_UGT; break; + case lltok::kw_ule: P = CmpInst::ICMP_ULE; break; + case lltok::kw_uge: P = CmpInst::ICMP_UGE; break; + } + } + Lex.Lex(); + return false; +} + +//===----------------------------------------------------------------------===// +// Terminator Instructions. +//===----------------------------------------------------------------------===// + +/// ParseRet - Parse a return instruction. +/// ::= 'ret' void (',' !dbg, !1) +/// ::= 'ret' TypeAndValue (',' !dbg, !1) +/// ::= 'ret' TypeAndValue (',' TypeAndValue)+ (',' !dbg, !1) +/// [[obsolete: LLVM 3.0]] +bool LLParser::ParseRet(Instruction *&Inst, BasicBlock *BB, + PerFunctionState &PFS) { + PATypeHolder Ty(Type::getVoidTy(Context)); + if (ParseType(Ty, true /*void allowed*/)) return true; + + if (Ty->isVoidTy()) { + Inst = ReturnInst::Create(Context); + return false; + } + + Value *RV; + if (ParseValue(Ty, RV, PFS)) return true; + + if (EatIfPresent(lltok::comma)) { + // Parse optional custom metadata, e.g. !dbg + if (Lex.getKind() == lltok::NamedOrCustomMD) { + if (ParseOptionalCustomMetadata()) return true; + } else { + // The normal case is one return value. + // FIXME: LLVM 3.0 remove MRV support for 'ret i32 1, i32 2', requiring use + // of 'ret {i32,i32} {i32 1, i32 2}' + SmallVector RVs; + RVs.push_back(RV); + + do { + // If optional custom metadata, e.g. !dbg is seen then this is the + // end of MRV. + if (Lex.getKind() == lltok::NamedOrCustomMD) + break; + if (ParseTypeAndValue(RV, PFS)) return true; + RVs.push_back(RV); + } while (EatIfPresent(lltok::comma)); + + RV = UndefValue::get(PFS.getFunction().getReturnType()); + for (unsigned i = 0, e = RVs.size(); i != e; ++i) { + Instruction *I = InsertValueInst::Create(RV, RVs[i], i, "mrv"); + BB->getInstList().push_back(I); + RV = I; + } + } + } + + Inst = ReturnInst::Create(Context, RV); + return false; +} + + +/// ParseBr +/// ::= 'br' TypeAndValue +/// ::= 'br' TypeAndValue ',' TypeAndValue ',' TypeAndValue +bool LLParser::ParseBr(Instruction *&Inst, PerFunctionState &PFS) { + LocTy Loc, Loc2; + Value *Op0; + BasicBlock *Op1, *Op2; + if (ParseTypeAndValue(Op0, Loc, PFS)) return true; + + if (BasicBlock *BB = dyn_cast(Op0)) { + Inst = BranchInst::Create(BB); + return false; + } + + if (Op0->getType() != Type::getInt1Ty(Context)) + return Error(Loc, "branch condition must have 'i1' type"); + + if (ParseToken(lltok::comma, "expected ',' after branch condition") || + ParseTypeAndBasicBlock(Op1, Loc, PFS) || + ParseToken(lltok::comma, "expected ',' after true destination") || + ParseTypeAndBasicBlock(Op2, Loc2, PFS)) + return true; + + Inst = BranchInst::Create(Op1, Op2, Op0); + return false; +} + +/// ParseSwitch +/// Instruction +/// ::= 'switch' TypeAndValue ',' TypeAndValue '[' JumpTable ']' +/// JumpTable +/// ::= (TypeAndValue ',' TypeAndValue)* +bool LLParser::ParseSwitch(Instruction *&Inst, PerFunctionState &PFS) { + LocTy CondLoc, BBLoc; + Value *Cond; + BasicBlock *DefaultBB; + if (ParseTypeAndValue(Cond, CondLoc, PFS) || + ParseToken(lltok::comma, "expected ',' after switch condition") || + ParseTypeAndBasicBlock(DefaultBB, BBLoc, PFS) || + ParseToken(lltok::lsquare, "expected '[' with switch table")) + return true; + + if (!isa(Cond->getType())) + return Error(CondLoc, "switch condition must have integer type"); + + // Parse the jump table pairs. + SmallPtrSet SeenCases; + SmallVector, 32> Table; + while (Lex.getKind() != lltok::rsquare) { + Value *Constant; + BasicBlock *DestBB; + + if (ParseTypeAndValue(Constant, CondLoc, PFS) || + ParseToken(lltok::comma, "expected ',' after case value") || + ParseTypeAndBasicBlock(DestBB, PFS)) + return true; + + if (!SeenCases.insert(Constant)) + return Error(CondLoc, "duplicate case value in switch"); + if (!isa(Constant)) + return Error(CondLoc, "case value is not a constant integer"); + + Table.push_back(std::make_pair(cast(Constant), DestBB)); + } + + Lex.Lex(); // Eat the ']'. + + SwitchInst *SI = SwitchInst::Create(Cond, DefaultBB, Table.size()); + for (unsigned i = 0, e = Table.size(); i != e; ++i) + SI->addCase(Table[i].first, Table[i].second); + Inst = SI; + return false; +} + +/// ParseIndirectBr +/// Instruction +/// ::= 'indirectbr' TypeAndValue ',' '[' LabelList ']' +bool LLParser::ParseIndirectBr(Instruction *&Inst, PerFunctionState &PFS) { + LocTy AddrLoc; + Value *Address; + if (ParseTypeAndValue(Address, AddrLoc, PFS) || + ParseToken(lltok::comma, "expected ',' after indirectbr address") || + ParseToken(lltok::lsquare, "expected '[' with indirectbr")) + return true; + + if (!isa(Address->getType())) + return Error(AddrLoc, "indirectbr address must have pointer type"); + + // Parse the destination list. + SmallVector DestList; + + if (Lex.getKind() != lltok::rsquare) { + BasicBlock *DestBB; + if (ParseTypeAndBasicBlock(DestBB, PFS)) + return true; + DestList.push_back(DestBB); + + while (EatIfPresent(lltok::comma)) { + if (ParseTypeAndBasicBlock(DestBB, PFS)) + return true; + DestList.push_back(DestBB); + } + } + + if (ParseToken(lltok::rsquare, "expected ']' at end of block list")) + return true; + + IndirectBrInst *IBI = IndirectBrInst::Create(Address, DestList.size()); + for (unsigned i = 0, e = DestList.size(); i != e; ++i) + IBI->addDestination(DestList[i]); + Inst = IBI; + return false; +} + + +/// ParseInvoke +/// ::= 'invoke' OptionalCallingConv OptionalAttrs Type Value ParamList +/// OptionalAttrs 'to' TypeAndValue 'unwind' TypeAndValue +bool LLParser::ParseInvoke(Instruction *&Inst, PerFunctionState &PFS) { + LocTy CallLoc = Lex.getLoc(); + unsigned RetAttrs, FnAttrs; + CallingConv::ID CC; + PATypeHolder RetType(Type::getVoidTy(Context)); + LocTy RetTypeLoc; + ValID CalleeID; + SmallVector ArgList; + + BasicBlock *NormalBB, *UnwindBB; + if (ParseOptionalCallingConv(CC) || + ParseOptionalAttrs(RetAttrs, 1) || + ParseType(RetType, RetTypeLoc, true /*void allowed*/) || + ParseValID(CalleeID) || + ParseParameterList(ArgList, PFS) || + ParseOptionalAttrs(FnAttrs, 2) || + ParseToken(lltok::kw_to, "expected 'to' in invoke") || + ParseTypeAndBasicBlock(NormalBB, PFS) || + ParseToken(lltok::kw_unwind, "expected 'unwind' in invoke") || + ParseTypeAndBasicBlock(UnwindBB, PFS)) + return true; + + // If RetType is a non-function pointer type, then this is the short syntax + // for the call, which means that RetType is just the return type. Infer the + // rest of the function argument types from the arguments that are present. + const PointerType *PFTy = 0; + const FunctionType *Ty = 0; + if (!(PFTy = dyn_cast(RetType)) || + !(Ty = dyn_cast(PFTy->getElementType()))) { + // Pull out the types of all of the arguments... + std::vector ParamTypes; + for (unsigned i = 0, e = ArgList.size(); i != e; ++i) + ParamTypes.push_back(ArgList[i].V->getType()); + + if (!FunctionType::isValidReturnType(RetType)) + return Error(RetTypeLoc, "Invalid result type for LLVM function"); + + Ty = FunctionType::get(RetType, ParamTypes, false); + PFTy = PointerType::getUnqual(Ty); + } + + // Look up the callee. + Value *Callee; + if (ConvertValIDToValue(PFTy, CalleeID, Callee, PFS)) return true; + + // FIXME: In LLVM 3.0, stop accepting zext, sext and inreg as optional + // function attributes. + unsigned ObsoleteFuncAttrs = Attribute::ZExt|Attribute::SExt|Attribute::InReg; + if (FnAttrs & ObsoleteFuncAttrs) { + RetAttrs |= FnAttrs & ObsoleteFuncAttrs; + FnAttrs &= ~ObsoleteFuncAttrs; + } + + // Set up the Attributes for the function. + SmallVector Attrs; + if (RetAttrs != Attribute::None) + Attrs.push_back(AttributeWithIndex::get(0, RetAttrs)); + + SmallVector Args; + + // Loop through FunctionType's arguments and ensure they are specified + // correctly. Also, gather any parameter attributes. + FunctionType::param_iterator I = Ty->param_begin(); + FunctionType::param_iterator E = Ty->param_end(); + for (unsigned i = 0, e = ArgList.size(); i != e; ++i) { + const Type *ExpectedTy = 0; + if (I != E) { + ExpectedTy = *I++; + } else if (!Ty->isVarArg()) { + return Error(ArgList[i].Loc, "too many arguments specified"); + } + + if (ExpectedTy && ExpectedTy != ArgList[i].V->getType()) + return Error(ArgList[i].Loc, "argument is not of expected type '" + + ExpectedTy->getDescription() + "'"); + Args.push_back(ArgList[i].V); + if (ArgList[i].Attrs != Attribute::None) + Attrs.push_back(AttributeWithIndex::get(i+1, ArgList[i].Attrs)); + } + + if (I != E) + return Error(CallLoc, "not enough parameters specified for call"); + + if (FnAttrs != Attribute::None) + Attrs.push_back(AttributeWithIndex::get(~0, FnAttrs)); + + // Finish off the Attributes and check them + AttrListPtr PAL = AttrListPtr::get(Attrs.begin(), Attrs.end()); + + InvokeInst *II = InvokeInst::Create(Callee, NormalBB, UnwindBB, + Args.begin(), Args.end()); + II->setCallingConv(CC); + II->setAttributes(PAL); + Inst = II; + return false; +} + + + +//===----------------------------------------------------------------------===// +// Binary Operators. +//===----------------------------------------------------------------------===// + +/// ParseArithmetic +/// ::= ArithmeticOps TypeAndValue ',' Value +/// +/// If OperandType is 0, then any FP or integer operand is allowed. If it is 1, +/// then any integer operand is allowed, if it is 2, any fp operand is allowed. +bool LLParser::ParseArithmetic(Instruction *&Inst, PerFunctionState &PFS, + unsigned Opc, unsigned OperandType) { + LocTy Loc; Value *LHS, *RHS; + if (ParseTypeAndValue(LHS, Loc, PFS) || + ParseToken(lltok::comma, "expected ',' in arithmetic operation") || + ParseValue(LHS->getType(), RHS, PFS)) + return true; + + bool Valid; + switch (OperandType) { + default: llvm_unreachable("Unknown operand type!"); + case 0: // int or FP. + Valid = LHS->getType()->isIntOrIntVector() || + LHS->getType()->isFPOrFPVector(); + break; + case 1: Valid = LHS->getType()->isIntOrIntVector(); break; + case 2: Valid = LHS->getType()->isFPOrFPVector(); break; + } + + if (!Valid) + return Error(Loc, "invalid operand type for instruction"); + + Inst = BinaryOperator::Create((Instruction::BinaryOps)Opc, LHS, RHS); + return false; +} + +/// ParseLogical +/// ::= ArithmeticOps TypeAndValue ',' Value { +bool LLParser::ParseLogical(Instruction *&Inst, PerFunctionState &PFS, + unsigned Opc) { + LocTy Loc; Value *LHS, *RHS; + if (ParseTypeAndValue(LHS, Loc, PFS) || + ParseToken(lltok::comma, "expected ',' in logical operation") || + ParseValue(LHS->getType(), RHS, PFS)) + return true; + + if (!LHS->getType()->isIntOrIntVector()) + return Error(Loc,"instruction requires integer or integer vector operands"); + + Inst = BinaryOperator::Create((Instruction::BinaryOps)Opc, LHS, RHS); + return false; +} + + +/// ParseCompare +/// ::= 'icmp' IPredicates TypeAndValue ',' Value +/// ::= 'fcmp' FPredicates TypeAndValue ',' Value +bool LLParser::ParseCompare(Instruction *&Inst, PerFunctionState &PFS, + unsigned Opc) { + // Parse the integer/fp comparison predicate. + LocTy Loc; + unsigned Pred; + Value *LHS, *RHS; + if (ParseCmpPredicate(Pred, Opc) || + ParseTypeAndValue(LHS, Loc, PFS) || + ParseToken(lltok::comma, "expected ',' after compare value") || + ParseValue(LHS->getType(), RHS, PFS)) + return true; + + if (Opc == Instruction::FCmp) { + if (!LHS->getType()->isFPOrFPVector()) + return Error(Loc, "fcmp requires floating point operands"); + Inst = new FCmpInst(CmpInst::Predicate(Pred), LHS, RHS); + } else { + assert(Opc == Instruction::ICmp && "Unknown opcode for CmpInst!"); + if (!LHS->getType()->isIntOrIntVector() && + !isa(LHS->getType())) + return Error(Loc, "icmp requires integer operands"); + Inst = new ICmpInst(CmpInst::Predicate(Pred), LHS, RHS); + } + return false; +} + +//===----------------------------------------------------------------------===// +// Other Instructions. +//===----------------------------------------------------------------------===// + + +/// ParseCast +/// ::= CastOpc TypeAndValue 'to' Type +bool LLParser::ParseCast(Instruction *&Inst, PerFunctionState &PFS, + unsigned Opc) { + LocTy Loc; Value *Op; + PATypeHolder DestTy(Type::getVoidTy(Context)); + if (ParseTypeAndValue(Op, Loc, PFS) || + ParseToken(lltok::kw_to, "expected 'to' after cast value") || + ParseType(DestTy)) + return true; + + if (!CastInst::castIsValid((Instruction::CastOps)Opc, Op, DestTy)) { + CastInst::castIsValid((Instruction::CastOps)Opc, Op, DestTy); + return Error(Loc, "invalid cast opcode for cast from '" + + Op->getType()->getDescription() + "' to '" + + DestTy->getDescription() + "'"); + } + Inst = CastInst::Create((Instruction::CastOps)Opc, Op, DestTy); + return false; +} + +/// ParseSelect +/// ::= 'select' TypeAndValue ',' TypeAndValue ',' TypeAndValue +bool LLParser::ParseSelect(Instruction *&Inst, PerFunctionState &PFS) { + LocTy Loc; + Value *Op0, *Op1, *Op2; + if (ParseTypeAndValue(Op0, Loc, PFS) || + ParseToken(lltok::comma, "expected ',' after select condition") || + ParseTypeAndValue(Op1, PFS) || + ParseToken(lltok::comma, "expected ',' after select value") || + ParseTypeAndValue(Op2, PFS)) + return true; + + if (const char *Reason = SelectInst::areInvalidOperands(Op0, Op1, Op2)) + return Error(Loc, Reason); + + Inst = SelectInst::Create(Op0, Op1, Op2); + return false; +} + +/// ParseVA_Arg +/// ::= 'va_arg' TypeAndValue ',' Type +bool LLParser::ParseVA_Arg(Instruction *&Inst, PerFunctionState &PFS) { + Value *Op; + PATypeHolder EltTy(Type::getVoidTy(Context)); + LocTy TypeLoc; + if (ParseTypeAndValue(Op, PFS) || + ParseToken(lltok::comma, "expected ',' after vaarg operand") || + ParseType(EltTy, TypeLoc)) + return true; + + if (!EltTy->isFirstClassType()) + return Error(TypeLoc, "va_arg requires operand with first class type"); + + Inst = new VAArgInst(Op, EltTy); + return false; +} + +/// ParseExtractElement +/// ::= 'extractelement' TypeAndValue ',' TypeAndValue +bool LLParser::ParseExtractElement(Instruction *&Inst, PerFunctionState &PFS) { + LocTy Loc; + Value *Op0, *Op1; + if (ParseTypeAndValue(Op0, Loc, PFS) || + ParseToken(lltok::comma, "expected ',' after extract value") || + ParseTypeAndValue(Op1, PFS)) + return true; + + if (!ExtractElementInst::isValidOperands(Op0, Op1)) + return Error(Loc, "invalid extractelement operands"); + + Inst = ExtractElementInst::Create(Op0, Op1); + return false; +} + +/// ParseInsertElement +/// ::= 'insertelement' TypeAndValue ',' TypeAndValue ',' TypeAndValue +bool LLParser::ParseInsertElement(Instruction *&Inst, PerFunctionState &PFS) { + LocTy Loc; + Value *Op0, *Op1, *Op2; + if (ParseTypeAndValue(Op0, Loc, PFS) || + ParseToken(lltok::comma, "expected ',' after insertelement value") || + ParseTypeAndValue(Op1, PFS) || + ParseToken(lltok::comma, "expected ',' after insertelement value") || + ParseTypeAndValue(Op2, PFS)) + return true; + + if (!InsertElementInst::isValidOperands(Op0, Op1, Op2)) + return Error(Loc, "invalid insertelement operands"); + + Inst = InsertElementInst::Create(Op0, Op1, Op2); + return false; +} + +/// ParseShuffleVector +/// ::= 'shufflevector' TypeAndValue ',' TypeAndValue ',' TypeAndValue +bool LLParser::ParseShuffleVector(Instruction *&Inst, PerFunctionState &PFS) { + LocTy Loc; + Value *Op0, *Op1, *Op2; + if (ParseTypeAndValue(Op0, Loc, PFS) || + ParseToken(lltok::comma, "expected ',' after shuffle mask") || + ParseTypeAndValue(Op1, PFS) || + ParseToken(lltok::comma, "expected ',' after shuffle value") || + ParseTypeAndValue(Op2, PFS)) + return true; + + if (!ShuffleVectorInst::isValidOperands(Op0, Op1, Op2)) + return Error(Loc, "invalid extractelement operands"); + + Inst = new ShuffleVectorInst(Op0, Op1, Op2); + return false; +} + +/// ParsePHI +/// ::= 'phi' Type '[' Value ',' Value ']' (',' '[' Value ',' Value ']')* +bool LLParser::ParsePHI(Instruction *&Inst, PerFunctionState &PFS) { + PATypeHolder Ty(Type::getVoidTy(Context)); + Value *Op0, *Op1; + LocTy TypeLoc = Lex.getLoc(); + + if (ParseType(Ty) || + ParseToken(lltok::lsquare, "expected '[' in phi value list") || + ParseValue(Ty, Op0, PFS) || + ParseToken(lltok::comma, "expected ',' after insertelement value") || + ParseValue(Type::getLabelTy(Context), Op1, PFS) || + ParseToken(lltok::rsquare, "expected ']' in phi value list")) + return true; + + SmallVector, 16> PHIVals; + while (1) { + PHIVals.push_back(std::make_pair(Op0, cast(Op1))); + + if (!EatIfPresent(lltok::comma)) + break; + + if (Lex.getKind() == lltok::NamedOrCustomMD) + break; + + if (ParseToken(lltok::lsquare, "expected '[' in phi value list") || + ParseValue(Ty, Op0, PFS) || + ParseToken(lltok::comma, "expected ',' after insertelement value") || + ParseValue(Type::getLabelTy(Context), Op1, PFS) || + ParseToken(lltok::rsquare, "expected ']' in phi value list")) + return true; + } + + if (Lex.getKind() == lltok::NamedOrCustomMD) + if (ParseOptionalCustomMetadata()) return true; + + if (!Ty->isFirstClassType()) + return Error(TypeLoc, "phi node must have first class type"); + + PHINode *PN = PHINode::Create(Ty); + PN->reserveOperandSpace(PHIVals.size()); + for (unsigned i = 0, e = PHIVals.size(); i != e; ++i) + PN->addIncoming(PHIVals[i].first, PHIVals[i].second); + Inst = PN; + return false; +} + +/// ParseCall +/// ::= 'tail'? 'call' OptionalCallingConv OptionalAttrs Type Value +/// ParameterList OptionalAttrs +bool LLParser::ParseCall(Instruction *&Inst, PerFunctionState &PFS, + bool isTail) { + unsigned RetAttrs, FnAttrs; + CallingConv::ID CC; + PATypeHolder RetType(Type::getVoidTy(Context)); + LocTy RetTypeLoc; + ValID CalleeID; + SmallVector ArgList; + LocTy CallLoc = Lex.getLoc(); + + if ((isTail && ParseToken(lltok::kw_call, "expected 'tail call'")) || + ParseOptionalCallingConv(CC) || + ParseOptionalAttrs(RetAttrs, 1) || + ParseType(RetType, RetTypeLoc, true /*void allowed*/) || + ParseValID(CalleeID) || + ParseParameterList(ArgList, PFS) || + ParseOptionalAttrs(FnAttrs, 2)) + return true; + + // If RetType is a non-function pointer type, then this is the short syntax + // for the call, which means that RetType is just the return type. Infer the + // rest of the function argument types from the arguments that are present. + const PointerType *PFTy = 0; + const FunctionType *Ty = 0; + if (!(PFTy = dyn_cast(RetType)) || + !(Ty = dyn_cast(PFTy->getElementType()))) { + // Pull out the types of all of the arguments... + std::vector ParamTypes; + for (unsigned i = 0, e = ArgList.size(); i != e; ++i) + ParamTypes.push_back(ArgList[i].V->getType()); + + if (!FunctionType::isValidReturnType(RetType)) + return Error(RetTypeLoc, "Invalid result type for LLVM function"); + + Ty = FunctionType::get(RetType, ParamTypes, false); + PFTy = PointerType::getUnqual(Ty); + } + + // Look up the callee. + Value *Callee; + if (ConvertValIDToValue(PFTy, CalleeID, Callee, PFS)) return true; + + // FIXME: In LLVM 3.0, stop accepting zext, sext and inreg as optional + // function attributes. + unsigned ObsoleteFuncAttrs = Attribute::ZExt|Attribute::SExt|Attribute::InReg; + if (FnAttrs & ObsoleteFuncAttrs) { + RetAttrs |= FnAttrs & ObsoleteFuncAttrs; + FnAttrs &= ~ObsoleteFuncAttrs; + } + + // Set up the Attributes for the function. + SmallVector Attrs; + if (RetAttrs != Attribute::None) + Attrs.push_back(AttributeWithIndex::get(0, RetAttrs)); + + SmallVector Args; + + // Loop through FunctionType's arguments and ensure they are specified + // correctly. Also, gather any parameter attributes. + FunctionType::param_iterator I = Ty->param_begin(); + FunctionType::param_iterator E = Ty->param_end(); + for (unsigned i = 0, e = ArgList.size(); i != e; ++i) { + const Type *ExpectedTy = 0; + if (I != E) { + ExpectedTy = *I++; + } else if (!Ty->isVarArg()) { + return Error(ArgList[i].Loc, "too many arguments specified"); + } + + if (ExpectedTy && ExpectedTy != ArgList[i].V->getType()) + return Error(ArgList[i].Loc, "argument is not of expected type '" + + ExpectedTy->getDescription() + "'"); + Args.push_back(ArgList[i].V); + if (ArgList[i].Attrs != Attribute::None) + Attrs.push_back(AttributeWithIndex::get(i+1, ArgList[i].Attrs)); + } + + if (I != E) + return Error(CallLoc, "not enough parameters specified for call"); + + if (FnAttrs != Attribute::None) + Attrs.push_back(AttributeWithIndex::get(~0, FnAttrs)); + + // Finish off the Attributes and check them + AttrListPtr PAL = AttrListPtr::get(Attrs.begin(), Attrs.end()); + + CallInst *CI = CallInst::Create(Callee, Args.begin(), Args.end()); + CI->setTailCall(isTail); + CI->setCallingConv(CC); + CI->setAttributes(PAL); + Inst = CI; + return false; +} + +//===----------------------------------------------------------------------===// +// Memory Instructions. +//===----------------------------------------------------------------------===// + +/// ParseAlloc +/// ::= 'malloc' Type (',' TypeAndValue)? (',' OptionalInfo)? +/// ::= 'alloca' Type (',' TypeAndValue)? (',' OptionalInfo)? +bool LLParser::ParseAlloc(Instruction *&Inst, PerFunctionState &PFS, + BasicBlock* BB, bool isAlloca) { + PATypeHolder Ty(Type::getVoidTy(Context)); + Value *Size = 0; + LocTy SizeLoc; + unsigned Alignment = 0; + if (ParseType(Ty)) return true; + + if (EatIfPresent(lltok::comma)) { + if (Lex.getKind() == lltok::kw_align + || Lex.getKind() == lltok::NamedOrCustomMD) { + if (ParseOptionalInfo(Alignment)) return true; + } else { + if (ParseTypeAndValue(Size, SizeLoc, PFS)) return true; + if (EatIfPresent(lltok::comma)) + if (ParseOptionalInfo(Alignment)) return true; + } + } + + if (Size && Size->getType() != Type::getInt32Ty(Context)) + return Error(SizeLoc, "element count must be i32"); + + if (isAlloca) { + Inst = new AllocaInst(Ty, Size, Alignment); + return false; + } + + // Autoupgrade old malloc instruction to malloc call. + // FIXME: Remove in LLVM 3.0. + const Type *IntPtrTy = Type::getInt32Ty(Context); + Constant *AllocSize = ConstantExpr::getSizeOf(Ty); + AllocSize = ConstantExpr::getTruncOrBitCast(AllocSize, IntPtrTy); + if (!MallocF) + // Prototype malloc as "void *(int32)". + // This function is renamed as "malloc" in ValidateEndOfModule(). + MallocF = cast( + M->getOrInsertFunction("", Type::getInt8PtrTy(Context), IntPtrTy, NULL)); + Inst = CallInst::CreateMalloc(BB, IntPtrTy, Ty, AllocSize, Size, MallocF); + return false; +} + +/// ParseFree +/// ::= 'free' TypeAndValue +bool LLParser::ParseFree(Instruction *&Inst, PerFunctionState &PFS, + BasicBlock* BB) { + Value *Val; LocTy Loc; + if (ParseTypeAndValue(Val, Loc, PFS)) return true; + if (!isa(Val->getType())) + return Error(Loc, "operand to free must be a pointer"); + Inst = CallInst::CreateFree(Val, BB); + return false; +} + +/// ParseLoad +/// ::= 'volatile'? 'load' TypeAndValue (',' OptionalInfo)? +bool LLParser::ParseLoad(Instruction *&Inst, PerFunctionState &PFS, + bool isVolatile) { + Value *Val; LocTy Loc; + unsigned Alignment = 0; + if (ParseTypeAndValue(Val, Loc, PFS)) return true; + + if (EatIfPresent(lltok::comma)) + if (ParseOptionalInfo(Alignment)) return true; + + if (!isa(Val->getType()) || + !cast(Val->getType())->getElementType()->isFirstClassType()) + return Error(Loc, "load operand must be a pointer to a first class type"); + + Inst = new LoadInst(Val, "", isVolatile, Alignment); + return false; +} + +/// ParseStore +/// ::= 'volatile'? 'store' TypeAndValue ',' TypeAndValue (',' 'align' i32)? +bool LLParser::ParseStore(Instruction *&Inst, PerFunctionState &PFS, + bool isVolatile) { + Value *Val, *Ptr; LocTy Loc, PtrLoc; + unsigned Alignment = 0; + if (ParseTypeAndValue(Val, Loc, PFS) || + ParseToken(lltok::comma, "expected ',' after store operand") || + ParseTypeAndValue(Ptr, PtrLoc, PFS)) + return true; + + if (EatIfPresent(lltok::comma)) + if (ParseOptionalInfo(Alignment)) return true; + + if (!isa(Ptr->getType())) + return Error(PtrLoc, "store operand must be a pointer"); + if (!Val->getType()->isFirstClassType()) + return Error(Loc, "store operand must be a first class value"); + if (cast(Ptr->getType())->getElementType() != Val->getType()) + return Error(Loc, "stored value and pointer type do not match"); + + Inst = new StoreInst(Val, Ptr, isVolatile, Alignment); + return false; +} + +/// ParseGetResult +/// ::= 'getresult' TypeAndValue ',' i32 +/// FIXME: Remove support for getresult in LLVM 3.0 +bool LLParser::ParseGetResult(Instruction *&Inst, PerFunctionState &PFS) { + Value *Val; LocTy ValLoc, EltLoc; + unsigned Element; + if (ParseTypeAndValue(Val, ValLoc, PFS) || + ParseToken(lltok::comma, "expected ',' after getresult operand") || + ParseUInt32(Element, EltLoc)) + return true; + + if (!isa(Val->getType()) && !isa(Val->getType())) + return Error(ValLoc, "getresult inst requires an aggregate operand"); + if (!ExtractValueInst::getIndexedType(Val->getType(), Element)) + return Error(EltLoc, "invalid getresult index for value"); + Inst = ExtractValueInst::Create(Val, Element); + return false; +} + +/// ParseGetElementPtr +/// ::= 'getelementptr' 'inbounds'? TypeAndValue (',' TypeAndValue)* +bool LLParser::ParseGetElementPtr(Instruction *&Inst, PerFunctionState &PFS) { + Value *Ptr, *Val; LocTy Loc, EltLoc; + + bool InBounds = EatIfPresent(lltok::kw_inbounds); + + if (ParseTypeAndValue(Ptr, Loc, PFS)) return true; + + if (!isa(Ptr->getType())) + return Error(Loc, "base of getelementptr must be a pointer"); + + SmallVector Indices; + while (EatIfPresent(lltok::comma)) { + if (Lex.getKind() == lltok::NamedOrCustomMD) + break; + if (ParseTypeAndValue(Val, EltLoc, PFS)) return true; + if (!isa(Val->getType())) + return Error(EltLoc, "getelementptr index must be an integer"); + Indices.push_back(Val); + } + if (Lex.getKind() == lltok::NamedOrCustomMD) + if (ParseOptionalCustomMetadata()) return true; + + if (!GetElementPtrInst::getIndexedType(Ptr->getType(), + Indices.begin(), Indices.end())) + return Error(Loc, "invalid getelementptr indices"); + Inst = GetElementPtrInst::Create(Ptr, Indices.begin(), Indices.end()); + if (InBounds) + cast(Inst)->setIsInBounds(true); + return false; +} + +/// ParseExtractValue +/// ::= 'extractvalue' TypeAndValue (',' uint32)+ +bool LLParser::ParseExtractValue(Instruction *&Inst, PerFunctionState &PFS) { + Value *Val; LocTy Loc; + SmallVector Indices; + if (ParseTypeAndValue(Val, Loc, PFS) || + ParseIndexList(Indices)) + return true; + if (Lex.getKind() == lltok::NamedOrCustomMD) + if (ParseOptionalCustomMetadata()) return true; + + if (!isa(Val->getType()) && !isa(Val->getType())) + return Error(Loc, "extractvalue operand must be array or struct"); + + if (!ExtractValueInst::getIndexedType(Val->getType(), Indices.begin(), + Indices.end())) + return Error(Loc, "invalid indices for extractvalue"); + Inst = ExtractValueInst::Create(Val, Indices.begin(), Indices.end()); + return false; +} + +/// ParseInsertValue +/// ::= 'insertvalue' TypeAndValue ',' TypeAndValue (',' uint32)+ +bool LLParser::ParseInsertValue(Instruction *&Inst, PerFunctionState &PFS) { + Value *Val0, *Val1; LocTy Loc0, Loc1; + SmallVector Indices; + if (ParseTypeAndValue(Val0, Loc0, PFS) || + ParseToken(lltok::comma, "expected comma after insertvalue operand") || + ParseTypeAndValue(Val1, Loc1, PFS) || + ParseIndexList(Indices)) + return true; + if (Lex.getKind() == lltok::NamedOrCustomMD) + if (ParseOptionalCustomMetadata()) return true; + + if (!isa(Val0->getType()) && !isa(Val0->getType())) + return Error(Loc0, "extractvalue operand must be array or struct"); + + if (!ExtractValueInst::getIndexedType(Val0->getType(), Indices.begin(), + Indices.end())) + return Error(Loc0, "invalid indices for insertvalue"); + Inst = InsertValueInst::Create(Val0, Val1, Indices.begin(), Indices.end()); + return false; +} + +//===----------------------------------------------------------------------===// +// Embedded metadata. +//===----------------------------------------------------------------------===// + +/// ParseMDNodeVector +/// ::= Element (',' Element)* +/// Element +/// ::= 'null' | TypeAndValue +bool LLParser::ParseMDNodeVector(SmallVectorImpl &Elts) { + assert(Lex.getKind() == lltok::lbrace); + Lex.Lex(); + do { + Value *V = 0; + if (Lex.getKind() == lltok::kw_null) { + Lex.Lex(); + V = 0; + } else { + PATypeHolder Ty(Type::getVoidTy(Context)); + if (ParseType(Ty)) return true; + if (Lex.getKind() == lltok::Metadata) { + Lex.Lex(); + MetadataBase *Node = 0; + if (!ParseMDNode(Node)) + V = Node; + else { + MetadataBase *MDS = 0; + if (ParseMDString(MDS)) return true; + V = MDS; + } + } else { + Constant *C; + if (ParseGlobalValue(Ty, C)) return true; + V = C; + } + } + Elts.push_back(V); + } while (EatIfPresent(lltok::comma)); + + return false; +} diff --git a/libclamav/c++/llvm/lib/AsmParser/LLParser.h b/libclamav/c++/llvm/lib/AsmParser/LLParser.h new file mode 100644 index 000000000..1112dc494 --- /dev/null +++ b/libclamav/c++/llvm/lib/AsmParser/LLParser.h @@ -0,0 +1,347 @@ +//===-- LLParser.h - Parser Class -------------------------------*- 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 the parser class for .ll files. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ASMPARSER_LLPARSER_H +#define LLVM_ASMPARSER_LLPARSER_H + +#include "LLLexer.h" +#include "llvm/Module.h" +#include "llvm/Type.h" +#include + +namespace llvm { + class Module; + class OpaqueType; + class Function; + class Value; + class BasicBlock; + class Instruction; + class Constant; + class GlobalValue; + class MetadataBase; + class MDString; + class MDNode; + + /// ValID - Represents a reference of a definition of some sort with no type. + /// There are several cases where we have to parse the value but where the + /// type can depend on later context. This may either be a numeric reference + /// or a symbolic (%var) reference. This is just a discriminated union. + struct ValID { + enum { + t_LocalID, t_GlobalID, // ID in UIntVal. + t_LocalName, t_GlobalName, // Name in StrVal. + t_APSInt, t_APFloat, // Value in APSIntVal/APFloatVal. + t_Null, t_Undef, t_Zero, // No value. + t_EmptyArray, // No value: [] + t_Constant, // Value in ConstantVal. + t_InlineAsm, // Value in StrVal/StrVal2/UIntVal. + t_Metadata // Value in MetadataVal. + } Kind; + + LLLexer::LocTy Loc; + unsigned UIntVal; + std::string StrVal, StrVal2; + APSInt APSIntVal; + APFloat APFloatVal; + Constant *ConstantVal; + MetadataBase *MetadataVal; + ValID() : APFloatVal(0.0) {} + + bool operator<(const ValID &RHS) const { + if (Kind == t_LocalID || Kind == t_GlobalID) + return UIntVal < RHS.UIntVal; + assert((Kind == t_LocalName || Kind == t_GlobalName) && + "Ordering not defined for this ValID kind yet"); + return StrVal < RHS.StrVal; + } + }; + + class LLParser { + public: + typedef LLLexer::LocTy LocTy; + private: + LLVMContext& Context; + LLLexer Lex; + Module *M; + + // Type resolution handling data structures. + std::map > ForwardRefTypes; + std::map > ForwardRefTypeIDs; + std::vector NumberedTypes; + /// MetadataCache - This map keeps track of parsed metadata constants. + std::map MetadataCache; + std::map > ForwardRefMDNodes; + SmallVector, 2> MDsOnInst; + struct UpRefRecord { + /// Loc - This is the location of the upref. + LocTy Loc; + + /// NestingLevel - The number of nesting levels that need to be popped + /// before this type is resolved. + unsigned NestingLevel; + + /// LastContainedTy - This is the type at the current binding level for + /// the type. Every time we reduce the nesting level, this gets updated. + const Type *LastContainedTy; + + /// UpRefTy - This is the actual opaque type that the upreference is + /// represented with. + OpaqueType *UpRefTy; + + UpRefRecord(LocTy L, unsigned NL, OpaqueType *URTy) + : Loc(L), NestingLevel(NL), LastContainedTy((Type*)URTy), + UpRefTy(URTy) {} + }; + std::vector UpRefs; + + // Global Value reference information. + std::map > ForwardRefVals; + std::map > ForwardRefValIDs; + std::vector NumberedVals; + + // References to blockaddress. The key is the function ValID, the value is + // a list of references to blocks in that function. + std::map > > + ForwardRefBlockAddresses; + + Function *MallocF; + public: + LLParser(MemoryBuffer *F, SourceMgr &SM, SMDiagnostic &Err, Module *m) : + Context(m->getContext()), Lex(F, SM, Err, m->getContext()), + M(m), MallocF(NULL) {} + bool Run(); + + LLVMContext& getContext() { return Context; } + + private: + + bool Error(LocTy L, const std::string &Msg) const { + return Lex.Error(L, Msg); + } + bool TokError(const std::string &Msg) const { + return Error(Lex.getLoc(), Msg); + } + + /// GetGlobalVal - Get a value with the specified name or ID, creating a + /// forward reference record if needed. This can return null if the value + /// exists but does not have the right type. + GlobalValue *GetGlobalVal(const std::string &N, const Type *Ty, LocTy Loc); + GlobalValue *GetGlobalVal(unsigned ID, const Type *Ty, LocTy Loc); + + // Helper Routines. + bool ParseToken(lltok::Kind T, const char *ErrMsg); + bool EatIfPresent(lltok::Kind T) { + if (Lex.getKind() != T) return false; + Lex.Lex(); + return true; + } + bool ParseOptionalToken(lltok::Kind T, bool &Present) { + if (Lex.getKind() != T) { + Present = false; + } else { + Lex.Lex(); + Present = true; + } + return false; + } + bool ParseStringConstant(std::string &Result); + bool ParseUInt32(unsigned &Val); + bool ParseUInt32(unsigned &Val, LocTy &Loc) { + Loc = Lex.getLoc(); + return ParseUInt32(Val); + } + bool ParseOptionalAddrSpace(unsigned &AddrSpace); + bool ParseOptionalAttrs(unsigned &Attrs, unsigned AttrKind); + bool ParseOptionalLinkage(unsigned &Linkage, bool &HasLinkage); + bool ParseOptionalLinkage(unsigned &Linkage) { + bool HasLinkage; return ParseOptionalLinkage(Linkage, HasLinkage); + } + bool ParseOptionalVisibility(unsigned &Visibility); + bool ParseOptionalCallingConv(CallingConv::ID &CC); + bool ParseOptionalAlignment(unsigned &Alignment); + bool ParseOptionalCustomMetadata(); + bool ParseOptionalInfo(unsigned &Alignment); + bool ParseIndexList(SmallVectorImpl &Indices); + + // Top-Level Entities + bool ParseTopLevelEntities(); + bool ValidateEndOfModule(); + bool ParseTargetDefinition(); + bool ParseDepLibs(); + bool ParseModuleAsm(); + bool ParseUnnamedType(); + bool ParseNamedType(); + bool ParseDeclare(); + bool ParseDefine(); + + bool ParseGlobalType(bool &IsConstant); + bool ParseUnnamedGlobal(); + bool ParseNamedGlobal(); + bool ParseGlobal(const std::string &Name, LocTy Loc, unsigned Linkage, + bool HasLinkage, unsigned Visibility); + bool ParseAlias(const std::string &Name, LocTy Loc, unsigned Visibility); + bool ParseStandaloneMetadata(); + bool ParseNamedMetadata(); + bool ParseMDString(MetadataBase *&S); + bool ParseMDNode(MetadataBase *&N); + + // Type Parsing. + bool ParseType(PATypeHolder &Result, bool AllowVoid = false); + bool ParseType(PATypeHolder &Result, LocTy &Loc, bool AllowVoid = false) { + Loc = Lex.getLoc(); + return ParseType(Result, AllowVoid); + } + bool ParseTypeRec(PATypeHolder &H); + bool ParseStructType(PATypeHolder &H, bool Packed); + bool ParseArrayVectorType(PATypeHolder &H, bool isVector); + bool ParseFunctionType(PATypeHolder &Result); + PATypeHolder HandleUpRefs(const Type *Ty); + + // Constants. + bool ParseValID(ValID &ID); + bool ConvertGlobalValIDToValue(const Type *Ty, ValID &ID, Constant *&V); + bool ParseGlobalValue(const Type *Ty, Constant *&V); + bool ParseGlobalTypeAndValue(Constant *&V); + bool ParseGlobalValueVector(SmallVectorImpl &Elts); + bool ParseMDNodeVector(SmallVectorImpl &); + + + // Function Semantic Analysis. + class PerFunctionState { + LLParser &P; + Function &F; + std::map > ForwardRefVals; + std::map > ForwardRefValIDs; + std::vector NumberedVals; + + /// FunctionNumber - If this is an unnamed function, this is the slot + /// number of it, otherwise it is -1. + int FunctionNumber; + public: + PerFunctionState(LLParser &p, Function &f, int FunctionNumber); + ~PerFunctionState(); + + Function &getFunction() const { return F; } + + bool FinishFunction(); + + /// GetVal - Get a value with the specified name or ID, creating a + /// forward reference record if needed. This can return null if the value + /// exists but does not have the right type. + Value *GetVal(const std::string &Name, const Type *Ty, LocTy Loc); + Value *GetVal(unsigned ID, const Type *Ty, LocTy Loc); + + /// SetInstName - After an instruction is parsed and inserted into its + /// basic block, this installs its name. + bool SetInstName(int NameID, const std::string &NameStr, LocTy NameLoc, + Instruction *Inst); + + /// GetBB - Get a basic block with the specified name or ID, creating a + /// forward reference record if needed. This can return null if the value + /// is not a BasicBlock. + BasicBlock *GetBB(const std::string &Name, LocTy Loc); + BasicBlock *GetBB(unsigned ID, LocTy Loc); + + /// DefineBB - Define the specified basic block, which is either named or + /// unnamed. If there is an error, this returns null otherwise it returns + /// the block being defined. + BasicBlock *DefineBB(const std::string &Name, LocTy Loc); + }; + + bool ConvertValIDToValue(const Type *Ty, ValID &ID, Value *&V, + PerFunctionState &PFS); + + bool ParseValue(const Type *Ty, Value *&V, PerFunctionState &PFS); + bool ParseValue(const Type *Ty, Value *&V, LocTy &Loc, + PerFunctionState &PFS) { + Loc = Lex.getLoc(); + return ParseValue(Ty, V, PFS); + } + + bool ParseTypeAndValue(Value *&V, PerFunctionState &PFS); + bool ParseTypeAndValue(Value *&V, LocTy &Loc, PerFunctionState &PFS) { + Loc = Lex.getLoc(); + return ParseTypeAndValue(V, PFS); + } + bool ParseTypeAndBasicBlock(BasicBlock *&BB, LocTy &Loc, + PerFunctionState &PFS); + bool ParseTypeAndBasicBlock(BasicBlock *&BB, PerFunctionState &PFS) { + LocTy Loc; + return ParseTypeAndBasicBlock(BB, Loc, PFS); + } + + struct ParamInfo { + LocTy Loc; + Value *V; + unsigned Attrs; + ParamInfo(LocTy loc, Value *v, unsigned attrs) + : Loc(loc), V(v), Attrs(attrs) {} + }; + bool ParseParameterList(SmallVectorImpl &ArgList, + PerFunctionState &PFS); + + // Function Parsing. + struct ArgInfo { + LocTy Loc; + PATypeHolder Type; + unsigned Attrs; + std::string Name; + ArgInfo(LocTy L, PATypeHolder Ty, unsigned Attr, const std::string &N) + : Loc(L), Type(Ty), Attrs(Attr), Name(N) {} + }; + bool ParseArgumentList(std::vector &ArgList, + bool &isVarArg, bool inType); + bool ParseFunctionHeader(Function *&Fn, bool isDefine); + bool ParseFunctionBody(Function &Fn); + bool ParseBasicBlock(PerFunctionState &PFS); + + // Instruction Parsing. + bool ParseInstruction(Instruction *&Inst, BasicBlock *BB, + PerFunctionState &PFS); + bool ParseCmpPredicate(unsigned &Pred, unsigned Opc); + + bool ParseRet(Instruction *&Inst, BasicBlock *BB, PerFunctionState &PFS); + bool ParseBr(Instruction *&Inst, PerFunctionState &PFS); + bool ParseSwitch(Instruction *&Inst, PerFunctionState &PFS); + bool ParseIndirectBr(Instruction *&Inst, PerFunctionState &PFS); + bool ParseInvoke(Instruction *&Inst, PerFunctionState &PFS); + + bool ParseArithmetic(Instruction *&I, PerFunctionState &PFS, unsigned Opc, + unsigned OperandType); + bool ParseLogical(Instruction *&I, PerFunctionState &PFS, unsigned Opc); + bool ParseCompare(Instruction *&I, PerFunctionState &PFS, unsigned Opc); + bool ParseCast(Instruction *&I, PerFunctionState &PFS, unsigned Opc); + bool ParseSelect(Instruction *&I, PerFunctionState &PFS); + bool ParseVA_Arg(Instruction *&I, PerFunctionState &PFS); + bool ParseExtractElement(Instruction *&I, PerFunctionState &PFS); + bool ParseInsertElement(Instruction *&I, PerFunctionState &PFS); + bool ParseShuffleVector(Instruction *&I, PerFunctionState &PFS); + bool ParsePHI(Instruction *&I, PerFunctionState &PFS); + bool ParseCall(Instruction *&I, PerFunctionState &PFS, bool isTail); + bool ParseAlloc(Instruction *&I, PerFunctionState &PFS, + BasicBlock *BB = 0, bool isAlloca = true); + bool ParseFree(Instruction *&I, PerFunctionState &PFS, BasicBlock *BB); + bool ParseLoad(Instruction *&I, PerFunctionState &PFS, bool isVolatile); + bool ParseStore(Instruction *&I, PerFunctionState &PFS, bool isVolatile); + bool ParseGetResult(Instruction *&I, PerFunctionState &PFS); + bool ParseGetElementPtr(Instruction *&I, PerFunctionState &PFS); + bool ParseExtractValue(Instruction *&I, PerFunctionState &PFS); + bool ParseInsertValue(Instruction *&I, PerFunctionState &PFS); + + bool ResolveForwardRefBlockAddresses(Function *TheFn, + std::vector > &Refs, + PerFunctionState *PFS); + }; +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/lib/AsmParser/LLToken.h b/libclamav/c++/llvm/lib/AsmParser/LLToken.h new file mode 100644 index 000000000..797c32ea6 --- /dev/null +++ b/libclamav/c++/llvm/lib/AsmParser/LLToken.h @@ -0,0 +1,145 @@ +//===- LLToken.h - Token Codes for LLVM Assembly Files ----------*- 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 the enums for the .ll lexer. +// +//===----------------------------------------------------------------------===// + +#ifndef LIBS_ASMPARSER_LLTOKEN_H +#define LIBS_ASMPARSER_LLTOKEN_H + +namespace llvm { +namespace lltok { + enum Kind { + // Markers + Eof, Error, + + // Tokens with no info. + dotdotdot, // ... + equal, comma, // = , + star, // * + lsquare, rsquare, // [ ] + lbrace, rbrace, // { } + less, greater, // < > + lparen, rparen, // ( ) + backslash, // \ (not /) + + kw_x, + kw_begin, kw_end, + kw_true, kw_false, + kw_declare, kw_define, + kw_global, kw_constant, + + kw_private, kw_linker_private, kw_internal, kw_linkonce, kw_linkonce_odr, + kw_weak, kw_weak_odr, kw_appending, kw_dllimport, kw_dllexport, kw_common, + kw_available_externally, + kw_default, kw_hidden, kw_protected, + kw_extern_weak, + kw_external, kw_thread_local, + kw_zeroinitializer, + kw_undef, kw_null, + kw_to, + kw_tail, + kw_target, + kw_triple, + kw_deplibs, + kw_datalayout, + kw_volatile, + kw_nuw, + kw_nsw, + kw_exact, + kw_inbounds, + kw_align, + kw_addrspace, + kw_section, + kw_alias, + kw_module, + kw_asm, + kw_sideeffect, + kw_alignstack, + kw_gc, + kw_c, + + kw_cc, kw_ccc, kw_fastcc, kw_coldcc, + kw_x86_stdcallcc, kw_x86_fastcallcc, + kw_arm_apcscc, kw_arm_aapcscc, kw_arm_aapcs_vfpcc, + + kw_signext, + kw_zeroext, + kw_inreg, + kw_sret, + kw_nounwind, + kw_noreturn, + kw_noalias, + kw_nocapture, + kw_byval, + kw_nest, + kw_readnone, + kw_readonly, + + kw_inlinehint, + kw_noinline, + kw_alwaysinline, + kw_optsize, + kw_ssp, + kw_sspreq, + kw_noredzone, + kw_noimplicitfloat, + kw_naked, + + kw_type, + kw_opaque, + + kw_eq, kw_ne, kw_slt, kw_sgt, kw_sle, kw_sge, kw_ult, kw_ugt, kw_ule, + kw_uge, kw_oeq, kw_one, kw_olt, kw_ogt, kw_ole, kw_oge, kw_ord, kw_uno, + kw_ueq, kw_une, + + // Instruction Opcodes (Opcode in UIntVal). + kw_add, kw_fadd, kw_sub, kw_fsub, kw_mul, kw_fmul, + kw_udiv, kw_sdiv, kw_fdiv, + kw_urem, kw_srem, kw_frem, kw_shl, kw_lshr, kw_ashr, + kw_and, kw_or, kw_xor, kw_icmp, kw_fcmp, + + kw_phi, kw_call, + kw_trunc, kw_zext, kw_sext, kw_fptrunc, kw_fpext, kw_uitofp, kw_sitofp, + kw_fptoui, kw_fptosi, kw_inttoptr, kw_ptrtoint, kw_bitcast, + kw_select, kw_va_arg, + + kw_ret, kw_br, kw_switch, kw_indirectbr, kw_invoke, kw_unwind, + kw_unreachable, + + kw_malloc, kw_alloca, kw_free, kw_load, kw_store, kw_getelementptr, + + kw_extractelement, kw_insertelement, kw_shufflevector, kw_getresult, + kw_extractvalue, kw_insertvalue, kw_blockaddress, + + // Unsigned Valued tokens (UIntVal). + GlobalID, // @42 + LocalVarID, // %42 + + // String valued tokens (StrVal). + LabelStr, // foo: + GlobalVar, // @foo @"foo" + LocalVar, // %foo %"foo" + StringConstant, // "foo" + NamedOrCustomMD, // !foo + + // Metadata valued tokens. + Metadata, // !"foo" !{i8 42} + + // Type valued tokens (TyVal). + Type, + + APFloat, // APFloatVal + APSInt // APSInt + }; +} // end namespace lltok +} // end namespace llvm + +#endif diff --git a/libclamav/c++/llvm/lib/AsmParser/Makefile b/libclamav/c++/llvm/lib/AsmParser/Makefile new file mode 100644 index 000000000..995bb0e13 --- /dev/null +++ b/libclamav/c++/llvm/lib/AsmParser/Makefile @@ -0,0 +1,14 @@ +##===- lib/AsmParser/Makefile ------------------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LEVEL = ../.. +LIBRARYNAME := LLVMAsmParser +BUILD_ARCHIVE = 1 + +include $(LEVEL)/Makefile.common diff --git a/libclamav/c++/llvm/lib/AsmParser/Parser.cpp b/libclamav/c++/llvm/lib/AsmParser/Parser.cpp new file mode 100644 index 000000000..331a23323 --- /dev/null +++ b/libclamav/c++/llvm/lib/AsmParser/Parser.cpp @@ -0,0 +1,62 @@ +//===- Parser.cpp - Main dispatch module for the Parser library -----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This library implements the functionality defined in llvm/Assembly/Parser.h +// +//===----------------------------------------------------------------------===// + +#include "llvm/Assembly/Parser.h" +#include "LLParser.h" +#include "llvm/Module.h" +#include "llvm/ADT/OwningPtr.h" +#include "llvm/Support/SourceMgr.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/raw_ostream.h" +#include +using namespace llvm; + +Module *llvm::ParseAssembly(MemoryBuffer *F, + Module *M, + SMDiagnostic &Err, + LLVMContext &Context) { + SourceMgr SM; + SM.AddNewSourceBuffer(F, SMLoc()); + + // If we are parsing into an existing module, do it. + if (M) + return LLParser(F, SM, Err, M).Run() ? 0 : M; + + // Otherwise create a new module. + OwningPtr M2(new Module(F->getBufferIdentifier(), Context)); + if (LLParser(F, SM, Err, M2.get()).Run()) + return 0; + return M2.take(); +} + +Module *llvm::ParseAssemblyFile(const std::string &Filename, SMDiagnostic &Err, + LLVMContext &Context) { + std::string ErrorStr; + MemoryBuffer *F = MemoryBuffer::getFileOrSTDIN(Filename.c_str(), &ErrorStr); + if (F == 0) { + Err = SMDiagnostic("", -1, -1, + "Could not open input file '" + Filename + "'", ""); + return 0; + } + + return ParseAssembly(F, 0, Err, Context); +} + +Module *llvm::ParseAssemblyString(const char *AsmString, Module *M, + SMDiagnostic &Err, LLVMContext &Context) { + MemoryBuffer *F = + MemoryBuffer::getMemBuffer(AsmString, AsmString+strlen(AsmString), + ""); + + return ParseAssembly(F, M, Err, Context); +} diff --git a/libclamav/c++/llvm/lib/Bitcode/Makefile b/libclamav/c++/llvm/lib/Bitcode/Makefile new file mode 100644 index 000000000..2d6b5ad1f --- /dev/null +++ b/libclamav/c++/llvm/lib/Bitcode/Makefile @@ -0,0 +1,14 @@ +##===- lib/Bitcode/Makefile --------------------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LEVEL = ../.. +PARALLEL_DIRS = Reader Writer + +include $(LEVEL)/Makefile.common + diff --git a/libclamav/c++/llvm/lib/Bitcode/Reader/BitReader.cpp b/libclamav/c++/llvm/lib/Bitcode/Reader/BitReader.cpp new file mode 100644 index 000000000..f513d41ce --- /dev/null +++ b/libclamav/c++/llvm/lib/Bitcode/Reader/BitReader.cpp @@ -0,0 +1,88 @@ +//===-- BitReader.cpp -----------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm-c/BitReader.h" +#include "llvm/Bitcode/ReaderWriter.h" +#include "llvm/LLVMContext.h" +#include "llvm/Support/MemoryBuffer.h" +#include +#include + +using namespace llvm; + +/* Builds a module from the bitcode in the specified memory buffer, returning a + reference to the module via the OutModule parameter. Returns 0 on success. + Optionally returns a human-readable error message via OutMessage. */ +int LLVMParseBitcode(LLVMMemoryBufferRef MemBuf, + LLVMModuleRef *OutModule, char **OutMessage) { + std::string Message; + + *OutModule = wrap(ParseBitcodeFile(unwrap(MemBuf), getGlobalContext(), + &Message)); + if (!*OutModule) { + if (OutMessage) + *OutMessage = strdup(Message.c_str()); + return 1; + } + + return 0; +} + +int LLVMParseBitcodeInContext(LLVMContextRef ContextRef, + LLVMMemoryBufferRef MemBuf, + LLVMModuleRef *OutModule, char **OutMessage) { + std::string Message; + + *OutModule = wrap(ParseBitcodeFile(unwrap(MemBuf), *unwrap(ContextRef), + &Message)); + if (!*OutModule) { + if (OutMessage) + *OutMessage = strdup(Message.c_str()); + return 1; + } + + return 0; +} + +/* Reads a module from the specified path, returning via the OutModule parameter + a module provider which performs lazy deserialization. Returns 0 on success. + Optionally returns a human-readable error message via OutMessage. */ +int LLVMGetBitcodeModuleProvider(LLVMMemoryBufferRef MemBuf, + LLVMModuleProviderRef *OutMP, + char **OutMessage) { + std::string Message; + + *OutMP = wrap(getBitcodeModuleProvider(unwrap(MemBuf), getGlobalContext(), + &Message)); + + if (!*OutMP) { + if (OutMessage) + *OutMessage = strdup(Message.c_str()); + return 1; + } + + return 0; +} + +int LLVMGetBitcodeModuleProviderInContext(LLVMContextRef ContextRef, + LLVMMemoryBufferRef MemBuf, + LLVMModuleProviderRef *OutMP, + char **OutMessage) { + std::string Message; + + *OutMP = wrap(getBitcodeModuleProvider(unwrap(MemBuf), *unwrap(ContextRef), + &Message)); + if (!*OutMP) { + if (OutMessage) + *OutMessage = strdup(Message.c_str()); + return 1; + } + + return 0; +} diff --git a/libclamav/c++/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/libclamav/c++/llvm/lib/Bitcode/Reader/BitcodeReader.cpp new file mode 100644 index 000000000..9916388da --- /dev/null +++ b/libclamav/c++/llvm/lib/Bitcode/Reader/BitcodeReader.cpp @@ -0,0 +1,2440 @@ +//===- BitcodeReader.cpp - Internal BitcodeReader implementation ----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This header defines the BitcodeReader class. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Bitcode/ReaderWriter.h" +#include "BitcodeReader.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/InlineAsm.h" +#include "llvm/IntrinsicInst.h" +#include "llvm/LLVMContext.h" +#include "llvm/Metadata.h" +#include "llvm/Module.h" +#include "llvm/Operator.h" +#include "llvm/AutoUpgrade.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/OperandTraits.h" +using namespace llvm; + +void BitcodeReader::FreeState() { + delete Buffer; + Buffer = 0; + std::vector().swap(TypeList); + ValueList.clear(); + MDValueList.clear(); + + std::vector().swap(MAttributes); + std::vector().swap(FunctionBBs); + std::vector().swap(FunctionsWithBodies); + DeferredFunctionInfo.clear(); +} + +//===----------------------------------------------------------------------===// +// Helper functions to implement forward reference resolution, etc. +//===----------------------------------------------------------------------===// + +/// ConvertToString - Convert a string from a record into an std::string, return +/// true on failure. +template +static bool ConvertToString(SmallVector &Record, unsigned Idx, + StrTy &Result) { + if (Idx > Record.size()) + return true; + + for (unsigned i = Idx, e = Record.size(); i != e; ++i) + Result += (char)Record[i]; + return false; +} + +static GlobalValue::LinkageTypes GetDecodedLinkage(unsigned Val) { + switch (Val) { + default: // Map unknown/new linkages to external + case 0: return GlobalValue::ExternalLinkage; + case 1: return GlobalValue::WeakAnyLinkage; + case 2: return GlobalValue::AppendingLinkage; + case 3: return GlobalValue::InternalLinkage; + case 4: return GlobalValue::LinkOnceAnyLinkage; + case 5: return GlobalValue::DLLImportLinkage; + case 6: return GlobalValue::DLLExportLinkage; + case 7: return GlobalValue::ExternalWeakLinkage; + case 8: return GlobalValue::CommonLinkage; + case 9: return GlobalValue::PrivateLinkage; + case 10: return GlobalValue::WeakODRLinkage; + case 11: return GlobalValue::LinkOnceODRLinkage; + case 12: return GlobalValue::AvailableExternallyLinkage; + case 13: return GlobalValue::LinkerPrivateLinkage; + } +} + +static GlobalValue::VisibilityTypes GetDecodedVisibility(unsigned Val) { + switch (Val) { + default: // Map unknown visibilities to default. + case 0: return GlobalValue::DefaultVisibility; + case 1: return GlobalValue::HiddenVisibility; + case 2: return GlobalValue::ProtectedVisibility; + } +} + +static int GetDecodedCastOpcode(unsigned Val) { + switch (Val) { + default: return -1; + case bitc::CAST_TRUNC : return Instruction::Trunc; + case bitc::CAST_ZEXT : return Instruction::ZExt; + case bitc::CAST_SEXT : return Instruction::SExt; + case bitc::CAST_FPTOUI : return Instruction::FPToUI; + case bitc::CAST_FPTOSI : return Instruction::FPToSI; + case bitc::CAST_UITOFP : return Instruction::UIToFP; + case bitc::CAST_SITOFP : return Instruction::SIToFP; + case bitc::CAST_FPTRUNC : return Instruction::FPTrunc; + case bitc::CAST_FPEXT : return Instruction::FPExt; + case bitc::CAST_PTRTOINT: return Instruction::PtrToInt; + case bitc::CAST_INTTOPTR: return Instruction::IntToPtr; + case bitc::CAST_BITCAST : return Instruction::BitCast; + } +} +static int GetDecodedBinaryOpcode(unsigned Val, const Type *Ty) { + switch (Val) { + default: return -1; + case bitc::BINOP_ADD: + return Ty->isFPOrFPVector() ? Instruction::FAdd : Instruction::Add; + case bitc::BINOP_SUB: + return Ty->isFPOrFPVector() ? Instruction::FSub : Instruction::Sub; + case bitc::BINOP_MUL: + return Ty->isFPOrFPVector() ? Instruction::FMul : Instruction::Mul; + case bitc::BINOP_UDIV: return Instruction::UDiv; + case bitc::BINOP_SDIV: + return Ty->isFPOrFPVector() ? Instruction::FDiv : Instruction::SDiv; + case bitc::BINOP_UREM: return Instruction::URem; + case bitc::BINOP_SREM: + return Ty->isFPOrFPVector() ? Instruction::FRem : Instruction::SRem; + case bitc::BINOP_SHL: return Instruction::Shl; + case bitc::BINOP_LSHR: return Instruction::LShr; + case bitc::BINOP_ASHR: return Instruction::AShr; + case bitc::BINOP_AND: return Instruction::And; + case bitc::BINOP_OR: return Instruction::Or; + case bitc::BINOP_XOR: return Instruction::Xor; + } +} + +namespace llvm { +namespace { + /// @brief A class for maintaining the slot number definition + /// as a placeholder for the actual definition for forward constants defs. + class ConstantPlaceHolder : public ConstantExpr { + ConstantPlaceHolder(); // DO NOT IMPLEMENT + void operator=(const ConstantPlaceHolder &); // DO NOT IMPLEMENT + public: + // allocate space for exactly one operand + void *operator new(size_t s) { + return User::operator new(s, 1); + } + explicit ConstantPlaceHolder(const Type *Ty, LLVMContext& Context) + : ConstantExpr(Ty, Instruction::UserOp1, &Op<0>(), 1) { + Op<0>() = UndefValue::get(Type::getInt32Ty(Context)); + } + + /// @brief Methods to support type inquiry through isa, cast, and dyn_cast. + static inline bool classof(const ConstantPlaceHolder *) { return true; } + static bool classof(const Value *V) { + return isa(V) && + cast(V)->getOpcode() == Instruction::UserOp1; + } + + + /// Provide fast operand accessors + //DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); + }; +} + +// FIXME: can we inherit this from ConstantExpr? +template <> +struct OperandTraits : public FixedNumOperandTraits<1> { +}; +} + + +void BitcodeReaderValueList::AssignValue(Value *V, unsigned Idx) { + if (Idx == size()) { + push_back(V); + return; + } + + if (Idx >= size()) + resize(Idx+1); + + WeakVH &OldV = ValuePtrs[Idx]; + if (OldV == 0) { + OldV = V; + return; + } + + // Handle constants and non-constants (e.g. instrs) differently for + // efficiency. + if (Constant *PHC = dyn_cast(&*OldV)) { + ResolveConstants.push_back(std::make_pair(PHC, Idx)); + OldV = V; + } else { + // If there was a forward reference to this value, replace it. + Value *PrevVal = OldV; + OldV->replaceAllUsesWith(V); + delete PrevVal; + } +} + + +Constant *BitcodeReaderValueList::getConstantFwdRef(unsigned Idx, + const Type *Ty) { + if (Idx >= size()) + resize(Idx + 1); + + if (Value *V = ValuePtrs[Idx]) { + assert(Ty == V->getType() && "Type mismatch in constant table!"); + return cast(V); + } + + // Create and return a placeholder, which will later be RAUW'd. + Constant *C = new ConstantPlaceHolder(Ty, Context); + ValuePtrs[Idx] = C; + return C; +} + +Value *BitcodeReaderValueList::getValueFwdRef(unsigned Idx, const Type *Ty) { + if (Idx >= size()) + resize(Idx + 1); + + if (Value *V = ValuePtrs[Idx]) { + assert((Ty == 0 || Ty == V->getType()) && "Type mismatch in value table!"); + return V; + } + + // No type specified, must be invalid reference. + if (Ty == 0) return 0; + + // Create and return a placeholder, which will later be RAUW'd. + Value *V = new Argument(Ty); + ValuePtrs[Idx] = V; + return V; +} + +/// ResolveConstantForwardRefs - Once all constants are read, this method bulk +/// resolves any forward references. The idea behind this is that we sometimes +/// get constants (such as large arrays) which reference *many* forward ref +/// constants. Replacing each of these causes a lot of thrashing when +/// building/reuniquing the constant. Instead of doing this, we look at all the +/// uses and rewrite all the place holders at once for any constant that uses +/// a placeholder. +void BitcodeReaderValueList::ResolveConstantForwardRefs() { + // Sort the values by-pointer so that they are efficient to look up with a + // binary search. + std::sort(ResolveConstants.begin(), ResolveConstants.end()); + + SmallVector NewOps; + + while (!ResolveConstants.empty()) { + Value *RealVal = operator[](ResolveConstants.back().second); + Constant *Placeholder = ResolveConstants.back().first; + ResolveConstants.pop_back(); + + // Loop over all users of the placeholder, updating them to reference the + // new value. If they reference more than one placeholder, update them all + // at once. + while (!Placeholder->use_empty()) { + Value::use_iterator UI = Placeholder->use_begin(); + + // If the using object isn't uniqued, just update the operands. This + // handles instructions and initializers for global variables. + if (!isa(*UI) || isa(*UI)) { + UI.getUse().set(RealVal); + continue; + } + + // Otherwise, we have a constant that uses the placeholder. Replace that + // constant with a new constant that has *all* placeholder uses updated. + Constant *UserC = cast(*UI); + for (User::op_iterator I = UserC->op_begin(), E = UserC->op_end(); + I != E; ++I) { + Value *NewOp; + if (!isa(*I)) { + // Not a placeholder reference. + NewOp = *I; + } else if (*I == Placeholder) { + // Common case is that it just references this one placeholder. + NewOp = RealVal; + } else { + // Otherwise, look up the placeholder in ResolveConstants. + ResolveConstantsTy::iterator It = + std::lower_bound(ResolveConstants.begin(), ResolveConstants.end(), + std::pair(cast(*I), + 0)); + assert(It != ResolveConstants.end() && It->first == *I); + NewOp = operator[](It->second); + } + + NewOps.push_back(cast(NewOp)); + } + + // Make the new constant. + Constant *NewC; + if (ConstantArray *UserCA = dyn_cast(UserC)) { + NewC = ConstantArray::get(UserCA->getType(), &NewOps[0], + NewOps.size()); + } else if (ConstantStruct *UserCS = dyn_cast(UserC)) { + NewC = ConstantStruct::get(Context, &NewOps[0], NewOps.size(), + UserCS->getType()->isPacked()); + } else if (isa(UserC)) { + NewC = ConstantVector::get(&NewOps[0], NewOps.size()); + } else { + assert(isa(UserC) && "Must be a ConstantExpr."); + NewC = cast(UserC)->getWithOperands(&NewOps[0], + NewOps.size()); + } + + UserC->replaceAllUsesWith(NewC); + UserC->destroyConstant(); + NewOps.clear(); + } + + // Update all ValueHandles, they should be the only users at this point. + Placeholder->replaceAllUsesWith(RealVal); + delete Placeholder; + } +} + +void BitcodeReaderMDValueList::AssignValue(Value *V, unsigned Idx) { + if (Idx == size()) { + push_back(V); + return; + } + + if (Idx >= size()) + resize(Idx+1); + + WeakVH &OldV = MDValuePtrs[Idx]; + if (OldV == 0) { + OldV = V; + return; + } + + // If there was a forward reference to this value, replace it. + Value *PrevVal = OldV; + OldV->replaceAllUsesWith(V); + delete PrevVal; + // Deleting PrevVal sets Idx value in MDValuePtrs to null. Set new + // value for Idx. + MDValuePtrs[Idx] = V; +} + +Value *BitcodeReaderMDValueList::getValueFwdRef(unsigned Idx) { + if (Idx >= size()) + resize(Idx + 1); + + if (Value *V = MDValuePtrs[Idx]) { + assert(V->getType()->isMetadataTy() && "Type mismatch in value table!"); + return V; + } + + // Create and return a placeholder, which will later be RAUW'd. + Value *V = new Argument(Type::getMetadataTy(Context)); + MDValuePtrs[Idx] = V; + return V; +} + +const Type *BitcodeReader::getTypeByID(unsigned ID, bool isTypeTable) { + // If the TypeID is in range, return it. + if (ID < TypeList.size()) + return TypeList[ID].get(); + if (!isTypeTable) return 0; + + // The type table allows forward references. Push as many Opaque types as + // needed to get up to ID. + while (TypeList.size() <= ID) + TypeList.push_back(OpaqueType::get(Context)); + return TypeList.back().get(); +} + +//===----------------------------------------------------------------------===// +// Functions for parsing blocks from the bitcode file +//===----------------------------------------------------------------------===// + +bool BitcodeReader::ParseAttributeBlock() { + if (Stream.EnterSubBlock(bitc::PARAMATTR_BLOCK_ID)) + return Error("Malformed block record"); + + if (!MAttributes.empty()) + return Error("Multiple PARAMATTR blocks found!"); + + SmallVector Record; + + SmallVector Attrs; + + // Read all the records. + while (1) { + unsigned Code = Stream.ReadCode(); + if (Code == bitc::END_BLOCK) { + if (Stream.ReadBlockEnd()) + return Error("Error at end of PARAMATTR block"); + return false; + } + + if (Code == bitc::ENTER_SUBBLOCK) { + // No known subblocks, always skip them. + Stream.ReadSubBlockID(); + if (Stream.SkipBlock()) + return Error("Malformed block record"); + continue; + } + + if (Code == bitc::DEFINE_ABBREV) { + Stream.ReadAbbrevRecord(); + continue; + } + + // Read a record. + Record.clear(); + switch (Stream.ReadRecord(Code, Record)) { + default: // Default behavior: ignore. + break; + case bitc::PARAMATTR_CODE_ENTRY: { // ENTRY: [paramidx0, attr0, ...] + if (Record.size() & 1) + return Error("Invalid ENTRY record"); + + // FIXME : Remove this autoupgrade code in LLVM 3.0. + // If Function attributes are using index 0 then transfer them + // to index ~0. Index 0 is used for return value attributes but used to be + // used for function attributes. + Attributes RetAttribute = Attribute::None; + Attributes FnAttribute = Attribute::None; + for (unsigned i = 0, e = Record.size(); i != e; i += 2) { + // FIXME: remove in LLVM 3.0 + // The alignment is stored as a 16-bit raw value from bits 31--16. + // We shift the bits above 31 down by 11 bits. + + unsigned Alignment = (Record[i+1] & (0xffffull << 16)) >> 16; + if (Alignment && !isPowerOf2_32(Alignment)) + return Error("Alignment is not a power of two."); + + Attributes ReconstitutedAttr = Record[i+1] & 0xffff; + if (Alignment) + ReconstitutedAttr |= Attribute::constructAlignmentFromInt(Alignment); + ReconstitutedAttr |= (Record[i+1] & (0xffffull << 32)) >> 11; + Record[i+1] = ReconstitutedAttr; + + if (Record[i] == 0) + RetAttribute = Record[i+1]; + else if (Record[i] == ~0U) + FnAttribute = Record[i+1]; + } + + unsigned OldRetAttrs = (Attribute::NoUnwind|Attribute::NoReturn| + Attribute::ReadOnly|Attribute::ReadNone); + + if (FnAttribute == Attribute::None && RetAttribute != Attribute::None && + (RetAttribute & OldRetAttrs) != 0) { + if (FnAttribute == Attribute::None) { // add a slot so they get added. + Record.push_back(~0U); + Record.push_back(0); + } + + FnAttribute |= RetAttribute & OldRetAttrs; + RetAttribute &= ~OldRetAttrs; + } + + for (unsigned i = 0, e = Record.size(); i != e; i += 2) { + if (Record[i] == 0) { + if (RetAttribute != Attribute::None) + Attrs.push_back(AttributeWithIndex::get(0, RetAttribute)); + } else if (Record[i] == ~0U) { + if (FnAttribute != Attribute::None) + Attrs.push_back(AttributeWithIndex::get(~0U, FnAttribute)); + } else if (Record[i+1] != Attribute::None) + Attrs.push_back(AttributeWithIndex::get(Record[i], Record[i+1])); + } + + MAttributes.push_back(AttrListPtr::get(Attrs.begin(), Attrs.end())); + Attrs.clear(); + break; + } + } + } +} + + +bool BitcodeReader::ParseTypeTable() { + if (Stream.EnterSubBlock(bitc::TYPE_BLOCK_ID)) + return Error("Malformed block record"); + + if (!TypeList.empty()) + return Error("Multiple TYPE_BLOCKs found!"); + + SmallVector Record; + unsigned NumRecords = 0; + + // Read all the records for this type table. + while (1) { + unsigned Code = Stream.ReadCode(); + if (Code == bitc::END_BLOCK) { + if (NumRecords != TypeList.size()) + return Error("Invalid type forward reference in TYPE_BLOCK"); + if (Stream.ReadBlockEnd()) + return Error("Error at end of type table block"); + return false; + } + + if (Code == bitc::ENTER_SUBBLOCK) { + // No known subblocks, always skip them. + Stream.ReadSubBlockID(); + if (Stream.SkipBlock()) + return Error("Malformed block record"); + continue; + } + + if (Code == bitc::DEFINE_ABBREV) { + Stream.ReadAbbrevRecord(); + continue; + } + + // Read a record. + Record.clear(); + const Type *ResultTy = 0; + switch (Stream.ReadRecord(Code, Record)) { + default: // Default behavior: unknown type. + ResultTy = 0; + break; + case bitc::TYPE_CODE_NUMENTRY: // TYPE_CODE_NUMENTRY: [numentries] + // TYPE_CODE_NUMENTRY contains a count of the number of types in the + // type list. This allows us to reserve space. + if (Record.size() < 1) + return Error("Invalid TYPE_CODE_NUMENTRY record"); + TypeList.reserve(Record[0]); + continue; + case bitc::TYPE_CODE_VOID: // VOID + ResultTy = Type::getVoidTy(Context); + break; + case bitc::TYPE_CODE_FLOAT: // FLOAT + ResultTy = Type::getFloatTy(Context); + break; + case bitc::TYPE_CODE_DOUBLE: // DOUBLE + ResultTy = Type::getDoubleTy(Context); + break; + case bitc::TYPE_CODE_X86_FP80: // X86_FP80 + ResultTy = Type::getX86_FP80Ty(Context); + break; + case bitc::TYPE_CODE_FP128: // FP128 + ResultTy = Type::getFP128Ty(Context); + break; + case bitc::TYPE_CODE_PPC_FP128: // PPC_FP128 + ResultTy = Type::getPPC_FP128Ty(Context); + break; + case bitc::TYPE_CODE_LABEL: // LABEL + ResultTy = Type::getLabelTy(Context); + break; + case bitc::TYPE_CODE_OPAQUE: // OPAQUE + ResultTy = 0; + break; + case bitc::TYPE_CODE_METADATA: // METADATA + ResultTy = Type::getMetadataTy(Context); + break; + case bitc::TYPE_CODE_INTEGER: // INTEGER: [width] + if (Record.size() < 1) + return Error("Invalid Integer type record"); + + ResultTy = IntegerType::get(Context, Record[0]); + break; + case bitc::TYPE_CODE_POINTER: { // POINTER: [pointee type] or + // [pointee type, address space] + if (Record.size() < 1) + return Error("Invalid POINTER type record"); + unsigned AddressSpace = 0; + if (Record.size() == 2) + AddressSpace = Record[1]; + ResultTy = PointerType::get(getTypeByID(Record[0], true), + AddressSpace); + break; + } + case bitc::TYPE_CODE_FUNCTION: { + // FIXME: attrid is dead, remove it in LLVM 3.0 + // FUNCTION: [vararg, attrid, retty, paramty x N] + if (Record.size() < 3) + return Error("Invalid FUNCTION type record"); + std::vector ArgTys; + for (unsigned i = 3, e = Record.size(); i != e; ++i) + ArgTys.push_back(getTypeByID(Record[i], true)); + + ResultTy = FunctionType::get(getTypeByID(Record[2], true), ArgTys, + Record[0]); + break; + } + case bitc::TYPE_CODE_STRUCT: { // STRUCT: [ispacked, eltty x N] + if (Record.size() < 1) + return Error("Invalid STRUCT type record"); + std::vector EltTys; + for (unsigned i = 1, e = Record.size(); i != e; ++i) + EltTys.push_back(getTypeByID(Record[i], true)); + ResultTy = StructType::get(Context, EltTys, Record[0]); + break; + } + case bitc::TYPE_CODE_ARRAY: // ARRAY: [numelts, eltty] + if (Record.size() < 2) + return Error("Invalid ARRAY type record"); + ResultTy = ArrayType::get(getTypeByID(Record[1], true), Record[0]); + break; + case bitc::TYPE_CODE_VECTOR: // VECTOR: [numelts, eltty] + if (Record.size() < 2) + return Error("Invalid VECTOR type record"); + ResultTy = VectorType::get(getTypeByID(Record[1], true), Record[0]); + break; + } + + if (NumRecords == TypeList.size()) { + // If this is a new type slot, just append it. + TypeList.push_back(ResultTy ? ResultTy : OpaqueType::get(Context)); + ++NumRecords; + } else if (ResultTy == 0) { + // Otherwise, this was forward referenced, so an opaque type was created, + // but the result type is actually just an opaque. Leave the one we + // created previously. + ++NumRecords; + } else { + // Otherwise, this was forward referenced, so an opaque type was created. + // Resolve the opaque type to the real type now. + assert(NumRecords < TypeList.size() && "Typelist imbalance"); + const OpaqueType *OldTy = cast(TypeList[NumRecords++].get()); + + // Don't directly push the new type on the Tab. Instead we want to replace + // the opaque type we previously inserted with the new concrete value. The + // refinement from the abstract (opaque) type to the new type causes all + // uses of the abstract type to use the concrete type (NewTy). This will + // also cause the opaque type to be deleted. + const_cast(OldTy)->refineAbstractTypeTo(ResultTy); + + // This should have replaced the old opaque type with the new type in the + // value table... or with a preexisting type that was already in the + // system. Let's just make sure it did. + assert(TypeList[NumRecords-1].get() != OldTy && + "refineAbstractType didn't work!"); + } + } +} + + +bool BitcodeReader::ParseTypeSymbolTable() { + if (Stream.EnterSubBlock(bitc::TYPE_SYMTAB_BLOCK_ID)) + return Error("Malformed block record"); + + SmallVector Record; + + // Read all the records for this type table. + std::string TypeName; + while (1) { + unsigned Code = Stream.ReadCode(); + if (Code == bitc::END_BLOCK) { + if (Stream.ReadBlockEnd()) + return Error("Error at end of type symbol table block"); + return false; + } + + if (Code == bitc::ENTER_SUBBLOCK) { + // No known subblocks, always skip them. + Stream.ReadSubBlockID(); + if (Stream.SkipBlock()) + return Error("Malformed block record"); + continue; + } + + if (Code == bitc::DEFINE_ABBREV) { + Stream.ReadAbbrevRecord(); + continue; + } + + // Read a record. + Record.clear(); + switch (Stream.ReadRecord(Code, Record)) { + default: // Default behavior: unknown type. + break; + case bitc::TST_CODE_ENTRY: // TST_ENTRY: [typeid, namechar x N] + if (ConvertToString(Record, 1, TypeName)) + return Error("Invalid TST_ENTRY record"); + unsigned TypeID = Record[0]; + if (TypeID >= TypeList.size()) + return Error("Invalid Type ID in TST_ENTRY record"); + + TheModule->addTypeName(TypeName, TypeList[TypeID].get()); + TypeName.clear(); + break; + } + } +} + +bool BitcodeReader::ParseValueSymbolTable() { + if (Stream.EnterSubBlock(bitc::VALUE_SYMTAB_BLOCK_ID)) + return Error("Malformed block record"); + + SmallVector Record; + + // Read all the records for this value table. + SmallString<128> ValueName; + while (1) { + unsigned Code = Stream.ReadCode(); + if (Code == bitc::END_BLOCK) { + if (Stream.ReadBlockEnd()) + return Error("Error at end of value symbol table block"); + return false; + } + if (Code == bitc::ENTER_SUBBLOCK) { + // No known subblocks, always skip them. + Stream.ReadSubBlockID(); + if (Stream.SkipBlock()) + return Error("Malformed block record"); + continue; + } + + if (Code == bitc::DEFINE_ABBREV) { + Stream.ReadAbbrevRecord(); + continue; + } + + // Read a record. + Record.clear(); + switch (Stream.ReadRecord(Code, Record)) { + default: // Default behavior: unknown type. + break; + case bitc::VST_CODE_ENTRY: { // VST_ENTRY: [valueid, namechar x N] + if (ConvertToString(Record, 1, ValueName)) + return Error("Invalid VST_ENTRY record"); + unsigned ValueID = Record[0]; + if (ValueID >= ValueList.size()) + return Error("Invalid Value ID in VST_ENTRY record"); + Value *V = ValueList[ValueID]; + + V->setName(StringRef(ValueName.data(), ValueName.size())); + ValueName.clear(); + break; + } + case bitc::VST_CODE_BBENTRY: { + if (ConvertToString(Record, 1, ValueName)) + return Error("Invalid VST_BBENTRY record"); + BasicBlock *BB = getBasicBlock(Record[0]); + if (BB == 0) + return Error("Invalid BB ID in VST_BBENTRY record"); + + BB->setName(StringRef(ValueName.data(), ValueName.size())); + ValueName.clear(); + break; + } + } + } +} + +bool BitcodeReader::ParseMetadata() { + unsigned NextValueNo = MDValueList.size(); + + if (Stream.EnterSubBlock(bitc::METADATA_BLOCK_ID)) + return Error("Malformed block record"); + + SmallVector Record; + + // Read all the records. + while (1) { + unsigned Code = Stream.ReadCode(); + if (Code == bitc::END_BLOCK) { + if (Stream.ReadBlockEnd()) + return Error("Error at end of PARAMATTR block"); + return false; + } + + if (Code == bitc::ENTER_SUBBLOCK) { + // No known subblocks, always skip them. + Stream.ReadSubBlockID(); + if (Stream.SkipBlock()) + return Error("Malformed block record"); + continue; + } + + if (Code == bitc::DEFINE_ABBREV) { + Stream.ReadAbbrevRecord(); + continue; + } + + // Read a record. + Record.clear(); + switch (Stream.ReadRecord(Code, Record)) { + default: // Default behavior: ignore. + break; + case bitc::METADATA_NAME: { + // Read named of the named metadata. + unsigned NameLength = Record.size(); + SmallString<8> Name; + Name.resize(NameLength); + for (unsigned i = 0; i != NameLength; ++i) + Name[i] = Record[i]; + Record.clear(); + Code = Stream.ReadCode(); + + // METADATA_NAME is always followed by METADATA_NAMED_NODE. + if (Stream.ReadRecord(Code, Record) != bitc::METADATA_NAMED_NODE) + assert ( 0 && "Inavlid Named Metadata record"); + + // Read named metadata elements. + unsigned Size = Record.size(); + SmallVector Elts; + for (unsigned i = 0; i != Size; ++i) { + Value *MD = MDValueList.getValueFwdRef(Record[i]); + if (MetadataBase *B = dyn_cast(MD)) + Elts.push_back(B); + } + Value *V = NamedMDNode::Create(Context, Name.str(), Elts.data(), + Elts.size(), TheModule); + MDValueList.AssignValue(V, NextValueNo++); + break; + } + case bitc::METADATA_NODE: { + if (Record.empty() || Record.size() % 2 == 1) + return Error("Invalid METADATA_NODE record"); + + unsigned Size = Record.size(); + SmallVector Elts; + for (unsigned i = 0; i != Size; i += 2) { + const Type *Ty = getTypeByID(Record[i], false); + if (Ty->isMetadataTy()) + Elts.push_back(MDValueList.getValueFwdRef(Record[i+1])); + else if (Ty != Type::getVoidTy(Context)) + Elts.push_back(ValueList.getValueFwdRef(Record[i+1], Ty)); + else + Elts.push_back(NULL); + } + Value *V = MDNode::get(Context, &Elts[0], Elts.size()); + MDValueList.AssignValue(V, NextValueNo++); + break; + } + case bitc::METADATA_STRING: { + unsigned MDStringLength = Record.size(); + SmallString<8> String; + String.resize(MDStringLength); + for (unsigned i = 0; i != MDStringLength; ++i) + String[i] = Record[i]; + Value *V = MDString::get(Context, + StringRef(String.data(), String.size())); + MDValueList.AssignValue(V, NextValueNo++); + break; + } + case bitc::METADATA_KIND: { + unsigned RecordLength = Record.size(); + if (Record.empty() || RecordLength < 2) + return Error("Invalid METADATA_KIND record"); + SmallString<8> Name; + Name.resize(RecordLength-1); + unsigned Kind = Record[0]; + (void) Kind; + for (unsigned i = 1; i != RecordLength; ++i) + Name[i-1] = Record[i]; + MetadataContext &TheMetadata = Context.getMetadata(); + unsigned ExistingKind = TheMetadata.getMDKind(Name.str()); + if (ExistingKind == 0) { + unsigned NewKind = TheMetadata.registerMDKind(Name.str()); + (void) NewKind; + assert (Kind == NewKind + && "Unable to handle custom metadata mismatch!"); + } else { + assert (ExistingKind == Kind + && "Unable to handle custom metadata mismatch!"); + } + break; + } + } + } +} + +/// DecodeSignRotatedValue - Decode a signed value stored with the sign bit in +/// the LSB for dense VBR encoding. +static uint64_t DecodeSignRotatedValue(uint64_t V) { + if ((V & 1) == 0) + return V >> 1; + if (V != 1) + return -(V >> 1); + // There is no such thing as -0 with integers. "-0" really means MININT. + return 1ULL << 63; +} + +/// ResolveGlobalAndAliasInits - Resolve all of the initializers for global +/// values and aliases that we can. +bool BitcodeReader::ResolveGlobalAndAliasInits() { + std::vector > GlobalInitWorklist; + std::vector > AliasInitWorklist; + + GlobalInitWorklist.swap(GlobalInits); + AliasInitWorklist.swap(AliasInits); + + while (!GlobalInitWorklist.empty()) { + unsigned ValID = GlobalInitWorklist.back().second; + if (ValID >= ValueList.size()) { + // Not ready to resolve this yet, it requires something later in the file. + GlobalInits.push_back(GlobalInitWorklist.back()); + } else { + if (Constant *C = dyn_cast(ValueList[ValID])) + GlobalInitWorklist.back().first->setInitializer(C); + else + return Error("Global variable initializer is not a constant!"); + } + GlobalInitWorklist.pop_back(); + } + + while (!AliasInitWorklist.empty()) { + unsigned ValID = AliasInitWorklist.back().second; + if (ValID >= ValueList.size()) { + AliasInits.push_back(AliasInitWorklist.back()); + } else { + if (Constant *C = dyn_cast(ValueList[ValID])) + AliasInitWorklist.back().first->setAliasee(C); + else + return Error("Alias initializer is not a constant!"); + } + AliasInitWorklist.pop_back(); + } + return false; +} + +bool BitcodeReader::ParseConstants() { + if (Stream.EnterSubBlock(bitc::CONSTANTS_BLOCK_ID)) + return Error("Malformed block record"); + + SmallVector Record; + + // Read all the records for this value table. + const Type *CurTy = Type::getInt32Ty(Context); + unsigned NextCstNo = ValueList.size(); + while (1) { + unsigned Code = Stream.ReadCode(); + if (Code == bitc::END_BLOCK) + break; + + if (Code == bitc::ENTER_SUBBLOCK) { + // No known subblocks, always skip them. + Stream.ReadSubBlockID(); + if (Stream.SkipBlock()) + return Error("Malformed block record"); + continue; + } + + if (Code == bitc::DEFINE_ABBREV) { + Stream.ReadAbbrevRecord(); + continue; + } + + // Read a record. + Record.clear(); + Value *V = 0; + unsigned BitCode = Stream.ReadRecord(Code, Record); + switch (BitCode) { + default: // Default behavior: unknown constant + case bitc::CST_CODE_UNDEF: // UNDEF + V = UndefValue::get(CurTy); + break; + case bitc::CST_CODE_SETTYPE: // SETTYPE: [typeid] + if (Record.empty()) + return Error("Malformed CST_SETTYPE record"); + if (Record[0] >= TypeList.size()) + return Error("Invalid Type ID in CST_SETTYPE record"); + CurTy = TypeList[Record[0]]; + continue; // Skip the ValueList manipulation. + case bitc::CST_CODE_NULL: // NULL + V = Constant::getNullValue(CurTy); + break; + case bitc::CST_CODE_INTEGER: // INTEGER: [intval] + if (!isa(CurTy) || Record.empty()) + return Error("Invalid CST_INTEGER record"); + V = ConstantInt::get(CurTy, DecodeSignRotatedValue(Record[0])); + break; + case bitc::CST_CODE_WIDE_INTEGER: {// WIDE_INTEGER: [n x intval] + if (!isa(CurTy) || Record.empty()) + return Error("Invalid WIDE_INTEGER record"); + + unsigned NumWords = Record.size(); + SmallVector Words; + Words.resize(NumWords); + for (unsigned i = 0; i != NumWords; ++i) + Words[i] = DecodeSignRotatedValue(Record[i]); + V = ConstantInt::get(Context, + APInt(cast(CurTy)->getBitWidth(), + NumWords, &Words[0])); + break; + } + case bitc::CST_CODE_FLOAT: { // FLOAT: [fpval] + if (Record.empty()) + return Error("Invalid FLOAT record"); + if (CurTy->isFloatTy()) + V = ConstantFP::get(Context, APFloat(APInt(32, (uint32_t)Record[0]))); + else if (CurTy->isDoubleTy()) + V = ConstantFP::get(Context, APFloat(APInt(64, Record[0]))); + else if (CurTy->isX86_FP80Ty()) { + // Bits are not stored the same way as a normal i80 APInt, compensate. + uint64_t Rearrange[2]; + Rearrange[0] = (Record[1] & 0xffffLL) | (Record[0] << 16); + Rearrange[1] = Record[0] >> 48; + V = ConstantFP::get(Context, APFloat(APInt(80, 2, Rearrange))); + } else if (CurTy->isFP128Ty()) + V = ConstantFP::get(Context, APFloat(APInt(128, 2, &Record[0]), true)); + else if (CurTy->isPPC_FP128Ty()) + V = ConstantFP::get(Context, APFloat(APInt(128, 2, &Record[0]))); + else + V = UndefValue::get(CurTy); + break; + } + + case bitc::CST_CODE_AGGREGATE: {// AGGREGATE: [n x value number] + if (Record.empty()) + return Error("Invalid CST_AGGREGATE record"); + + unsigned Size = Record.size(); + std::vector Elts; + + if (const StructType *STy = dyn_cast(CurTy)) { + for (unsigned i = 0; i != Size; ++i) + Elts.push_back(ValueList.getConstantFwdRef(Record[i], + STy->getElementType(i))); + V = ConstantStruct::get(STy, Elts); + } else if (const ArrayType *ATy = dyn_cast(CurTy)) { + const Type *EltTy = ATy->getElementType(); + for (unsigned i = 0; i != Size; ++i) + Elts.push_back(ValueList.getConstantFwdRef(Record[i], EltTy)); + V = ConstantArray::get(ATy, Elts); + } else if (const VectorType *VTy = dyn_cast(CurTy)) { + const Type *EltTy = VTy->getElementType(); + for (unsigned i = 0; i != Size; ++i) + Elts.push_back(ValueList.getConstantFwdRef(Record[i], EltTy)); + V = ConstantVector::get(Elts); + } else { + V = UndefValue::get(CurTy); + } + break; + } + case bitc::CST_CODE_STRING: { // STRING: [values] + if (Record.empty()) + return Error("Invalid CST_AGGREGATE record"); + + const ArrayType *ATy = cast(CurTy); + const Type *EltTy = ATy->getElementType(); + + unsigned Size = Record.size(); + std::vector Elts; + for (unsigned i = 0; i != Size; ++i) + Elts.push_back(ConstantInt::get(EltTy, Record[i])); + V = ConstantArray::get(ATy, Elts); + break; + } + case bitc::CST_CODE_CSTRING: { // CSTRING: [values] + if (Record.empty()) + return Error("Invalid CST_AGGREGATE record"); + + const ArrayType *ATy = cast(CurTy); + const Type *EltTy = ATy->getElementType(); + + unsigned Size = Record.size(); + std::vector Elts; + for (unsigned i = 0; i != Size; ++i) + Elts.push_back(ConstantInt::get(EltTy, Record[i])); + Elts.push_back(Constant::getNullValue(EltTy)); + V = ConstantArray::get(ATy, Elts); + break; + } + case bitc::CST_CODE_CE_BINOP: { // CE_BINOP: [opcode, opval, opval] + if (Record.size() < 3) return Error("Invalid CE_BINOP record"); + int Opc = GetDecodedBinaryOpcode(Record[0], CurTy); + if (Opc < 0) { + V = UndefValue::get(CurTy); // Unknown binop. + } else { + Constant *LHS = ValueList.getConstantFwdRef(Record[1], CurTy); + Constant *RHS = ValueList.getConstantFwdRef(Record[2], CurTy); + unsigned Flags = 0; + if (Record.size() >= 4) { + if (Opc == Instruction::Add || + Opc == Instruction::Sub || + Opc == Instruction::Mul) { + if (Record[3] & (1 << bitc::OBO_NO_SIGNED_WRAP)) + Flags |= OverflowingBinaryOperator::NoSignedWrap; + if (Record[3] & (1 << bitc::OBO_NO_UNSIGNED_WRAP)) + Flags |= OverflowingBinaryOperator::NoUnsignedWrap; + } else if (Opc == Instruction::SDiv) { + if (Record[3] & (1 << bitc::SDIV_EXACT)) + Flags |= SDivOperator::IsExact; + } + } + V = ConstantExpr::get(Opc, LHS, RHS, Flags); + } + break; + } + case bitc::CST_CODE_CE_CAST: { // CE_CAST: [opcode, opty, opval] + if (Record.size() < 3) return Error("Invalid CE_CAST record"); + int Opc = GetDecodedCastOpcode(Record[0]); + if (Opc < 0) { + V = UndefValue::get(CurTy); // Unknown cast. + } else { + const Type *OpTy = getTypeByID(Record[1]); + if (!OpTy) return Error("Invalid CE_CAST record"); + Constant *Op = ValueList.getConstantFwdRef(Record[2], OpTy); + V = ConstantExpr::getCast(Opc, Op, CurTy); + } + break; + } + case bitc::CST_CODE_CE_INBOUNDS_GEP: + case bitc::CST_CODE_CE_GEP: { // CE_GEP: [n x operands] + if (Record.size() & 1) return Error("Invalid CE_GEP record"); + SmallVector Elts; + for (unsigned i = 0, e = Record.size(); i != e; i += 2) { + const Type *ElTy = getTypeByID(Record[i]); + if (!ElTy) return Error("Invalid CE_GEP record"); + Elts.push_back(ValueList.getConstantFwdRef(Record[i+1], ElTy)); + } + if (BitCode == bitc::CST_CODE_CE_INBOUNDS_GEP) + V = ConstantExpr::getInBoundsGetElementPtr(Elts[0], &Elts[1], + Elts.size()-1); + else + V = ConstantExpr::getGetElementPtr(Elts[0], &Elts[1], + Elts.size()-1); + break; + } + case bitc::CST_CODE_CE_SELECT: // CE_SELECT: [opval#, opval#, opval#] + if (Record.size() < 3) return Error("Invalid CE_SELECT record"); + V = ConstantExpr::getSelect(ValueList.getConstantFwdRef(Record[0], + Type::getInt1Ty(Context)), + ValueList.getConstantFwdRef(Record[1],CurTy), + ValueList.getConstantFwdRef(Record[2],CurTy)); + break; + case bitc::CST_CODE_CE_EXTRACTELT: { // CE_EXTRACTELT: [opty, opval, opval] + if (Record.size() < 3) return Error("Invalid CE_EXTRACTELT record"); + const VectorType *OpTy = + dyn_cast_or_null(getTypeByID(Record[0])); + if (OpTy == 0) return Error("Invalid CE_EXTRACTELT record"); + Constant *Op0 = ValueList.getConstantFwdRef(Record[1], OpTy); + Constant *Op1 = ValueList.getConstantFwdRef(Record[2], Type::getInt32Ty(Context)); + V = ConstantExpr::getExtractElement(Op0, Op1); + break; + } + case bitc::CST_CODE_CE_INSERTELT: { // CE_INSERTELT: [opval, opval, opval] + const VectorType *OpTy = dyn_cast(CurTy); + if (Record.size() < 3 || OpTy == 0) + return Error("Invalid CE_INSERTELT record"); + Constant *Op0 = ValueList.getConstantFwdRef(Record[0], OpTy); + Constant *Op1 = ValueList.getConstantFwdRef(Record[1], + OpTy->getElementType()); + Constant *Op2 = ValueList.getConstantFwdRef(Record[2], Type::getInt32Ty(Context)); + V = ConstantExpr::getInsertElement(Op0, Op1, Op2); + break; + } + case bitc::CST_CODE_CE_SHUFFLEVEC: { // CE_SHUFFLEVEC: [opval, opval, opval] + const VectorType *OpTy = dyn_cast(CurTy); + if (Record.size() < 3 || OpTy == 0) + return Error("Invalid CE_SHUFFLEVEC record"); + Constant *Op0 = ValueList.getConstantFwdRef(Record[0], OpTy); + Constant *Op1 = ValueList.getConstantFwdRef(Record[1], OpTy); + const Type *ShufTy = VectorType::get(Type::getInt32Ty(Context), + OpTy->getNumElements()); + Constant *Op2 = ValueList.getConstantFwdRef(Record[2], ShufTy); + V = ConstantExpr::getShuffleVector(Op0, Op1, Op2); + break; + } + case bitc::CST_CODE_CE_SHUFVEC_EX: { // [opty, opval, opval, opval] + const VectorType *RTy = dyn_cast(CurTy); + const VectorType *OpTy = dyn_cast(getTypeByID(Record[0])); + if (Record.size() < 4 || RTy == 0 || OpTy == 0) + return Error("Invalid CE_SHUFVEC_EX record"); + Constant *Op0 = ValueList.getConstantFwdRef(Record[1], OpTy); + Constant *Op1 = ValueList.getConstantFwdRef(Record[2], OpTy); + const Type *ShufTy = VectorType::get(Type::getInt32Ty(Context), + RTy->getNumElements()); + Constant *Op2 = ValueList.getConstantFwdRef(Record[3], ShufTy); + V = ConstantExpr::getShuffleVector(Op0, Op1, Op2); + break; + } + case bitc::CST_CODE_CE_CMP: { // CE_CMP: [opty, opval, opval, pred] + if (Record.size() < 4) return Error("Invalid CE_CMP record"); + const Type *OpTy = getTypeByID(Record[0]); + if (OpTy == 0) return Error("Invalid CE_CMP record"); + Constant *Op0 = ValueList.getConstantFwdRef(Record[1], OpTy); + Constant *Op1 = ValueList.getConstantFwdRef(Record[2], OpTy); + + if (OpTy->isFloatingPoint()) + V = ConstantExpr::getFCmp(Record[3], Op0, Op1); + else + V = ConstantExpr::getICmp(Record[3], Op0, Op1); + break; + } + case bitc::CST_CODE_INLINEASM: { + if (Record.size() < 2) return Error("Invalid INLINEASM record"); + std::string AsmStr, ConstrStr; + bool HasSideEffects = Record[0] & 1; + bool IsAlignStack = Record[0] >> 1; + unsigned AsmStrSize = Record[1]; + if (2+AsmStrSize >= Record.size()) + return Error("Invalid INLINEASM record"); + unsigned ConstStrSize = Record[2+AsmStrSize]; + if (3+AsmStrSize+ConstStrSize > Record.size()) + return Error("Invalid INLINEASM record"); + + for (unsigned i = 0; i != AsmStrSize; ++i) + AsmStr += (char)Record[2+i]; + for (unsigned i = 0; i != ConstStrSize; ++i) + ConstrStr += (char)Record[3+AsmStrSize+i]; + const PointerType *PTy = cast(CurTy); + V = InlineAsm::get(cast(PTy->getElementType()), + AsmStr, ConstrStr, HasSideEffects, IsAlignStack); + break; + } + case bitc::CST_CODE_BLOCKADDRESS:{ + if (Record.size() < 3) return Error("Invalid CE_BLOCKADDRESS record"); + const Type *FnTy = getTypeByID(Record[0]); + if (FnTy == 0) return Error("Invalid CE_BLOCKADDRESS record"); + Function *Fn = + dyn_cast_or_null(ValueList.getConstantFwdRef(Record[1],FnTy)); + if (Fn == 0) return Error("Invalid CE_BLOCKADDRESS record"); + + GlobalVariable *FwdRef = new GlobalVariable(*Fn->getParent(), + Type::getInt8Ty(Context), + false, GlobalValue::InternalLinkage, + 0, ""); + BlockAddrFwdRefs[Fn].push_back(std::make_pair(Record[2], FwdRef)); + V = FwdRef; + break; + } + } + + ValueList.AssignValue(V, NextCstNo); + ++NextCstNo; + } + + if (NextCstNo != ValueList.size()) + return Error("Invalid constant reference!"); + + if (Stream.ReadBlockEnd()) + return Error("Error at end of constants block"); + + // Once all the constants have been read, go through and resolve forward + // references. + ValueList.ResolveConstantForwardRefs(); + return false; +} + +/// RememberAndSkipFunctionBody - When we see the block for a function body, +/// remember where it is and then skip it. This lets us lazily deserialize the +/// functions. +bool BitcodeReader::RememberAndSkipFunctionBody() { + // Get the function we are talking about. + if (FunctionsWithBodies.empty()) + return Error("Insufficient function protos"); + + Function *Fn = FunctionsWithBodies.back(); + FunctionsWithBodies.pop_back(); + + // Save the current stream state. + uint64_t CurBit = Stream.GetCurrentBitNo(); + DeferredFunctionInfo[Fn] = std::make_pair(CurBit, Fn->getLinkage()); + + // Set the functions linkage to GhostLinkage so we know it is lazily + // deserialized. + Fn->setLinkage(GlobalValue::GhostLinkage); + + // Skip over the function block for now. + if (Stream.SkipBlock()) + return Error("Malformed block record"); + return false; +} + +bool BitcodeReader::ParseModule(const std::string &ModuleID) { + // Reject multiple MODULE_BLOCK's in a single bitstream. + if (TheModule) + return Error("Multiple MODULE_BLOCKs in same stream"); + + if (Stream.EnterSubBlock(bitc::MODULE_BLOCK_ID)) + return Error("Malformed block record"); + + // Otherwise, create the module. + TheModule = new Module(ModuleID, Context); + + SmallVector Record; + std::vector SectionTable; + std::vector GCTable; + + // Read all the records for this module. + while (!Stream.AtEndOfStream()) { + unsigned Code = Stream.ReadCode(); + if (Code == bitc::END_BLOCK) { + if (Stream.ReadBlockEnd()) + return Error("Error at end of module block"); + + // Patch the initializers for globals and aliases up. + ResolveGlobalAndAliasInits(); + if (!GlobalInits.empty() || !AliasInits.empty()) + return Error("Malformed global initializer set"); + if (!FunctionsWithBodies.empty()) + return Error("Too few function bodies found"); + + // Look for intrinsic functions which need to be upgraded at some point + for (Module::iterator FI = TheModule->begin(), FE = TheModule->end(); + FI != FE; ++FI) { + Function* NewFn; + if (UpgradeIntrinsicFunction(FI, NewFn)) + UpgradedIntrinsics.push_back(std::make_pair(FI, NewFn)); + } + + // Force deallocation of memory for these vectors to favor the client that + // want lazy deserialization. + std::vector >().swap(GlobalInits); + std::vector >().swap(AliasInits); + std::vector().swap(FunctionsWithBodies); + return false; + } + + if (Code == bitc::ENTER_SUBBLOCK) { + switch (Stream.ReadSubBlockID()) { + default: // Skip unknown content. + if (Stream.SkipBlock()) + return Error("Malformed block record"); + break; + case bitc::BLOCKINFO_BLOCK_ID: + if (Stream.ReadBlockInfoBlock()) + return Error("Malformed BlockInfoBlock"); + break; + case bitc::PARAMATTR_BLOCK_ID: + if (ParseAttributeBlock()) + return true; + break; + case bitc::TYPE_BLOCK_ID: + if (ParseTypeTable()) + return true; + break; + case bitc::TYPE_SYMTAB_BLOCK_ID: + if (ParseTypeSymbolTable()) + return true; + break; + case bitc::VALUE_SYMTAB_BLOCK_ID: + if (ParseValueSymbolTable()) + return true; + break; + case bitc::CONSTANTS_BLOCK_ID: + if (ParseConstants() || ResolveGlobalAndAliasInits()) + return true; + break; + case bitc::METADATA_BLOCK_ID: + if (ParseMetadata()) + return true; + break; + case bitc::FUNCTION_BLOCK_ID: + // If this is the first function body we've seen, reverse the + // FunctionsWithBodies list. + if (!HasReversedFunctionsWithBodies) { + std::reverse(FunctionsWithBodies.begin(), FunctionsWithBodies.end()); + HasReversedFunctionsWithBodies = true; + } + + if (RememberAndSkipFunctionBody()) + return true; + break; + } + continue; + } + + if (Code == bitc::DEFINE_ABBREV) { + Stream.ReadAbbrevRecord(); + continue; + } + + // Read a record. + switch (Stream.ReadRecord(Code, Record)) { + default: break; // Default behavior, ignore unknown content. + case bitc::MODULE_CODE_VERSION: // VERSION: [version#] + if (Record.size() < 1) + return Error("Malformed MODULE_CODE_VERSION"); + // Only version #0 is supported so far. + if (Record[0] != 0) + return Error("Unknown bitstream version!"); + break; + case bitc::MODULE_CODE_TRIPLE: { // TRIPLE: [strchr x N] + std::string S; + if (ConvertToString(Record, 0, S)) + return Error("Invalid MODULE_CODE_TRIPLE record"); + TheModule->setTargetTriple(S); + break; + } + case bitc::MODULE_CODE_DATALAYOUT: { // DATALAYOUT: [strchr x N] + std::string S; + if (ConvertToString(Record, 0, S)) + return Error("Invalid MODULE_CODE_DATALAYOUT record"); + TheModule->setDataLayout(S); + break; + } + case bitc::MODULE_CODE_ASM: { // ASM: [strchr x N] + std::string S; + if (ConvertToString(Record, 0, S)) + return Error("Invalid MODULE_CODE_ASM record"); + TheModule->setModuleInlineAsm(S); + break; + } + case bitc::MODULE_CODE_DEPLIB: { // DEPLIB: [strchr x N] + std::string S; + if (ConvertToString(Record, 0, S)) + return Error("Invalid MODULE_CODE_DEPLIB record"); + TheModule->addLibrary(S); + break; + } + case bitc::MODULE_CODE_SECTIONNAME: { // SECTIONNAME: [strchr x N] + std::string S; + if (ConvertToString(Record, 0, S)) + return Error("Invalid MODULE_CODE_SECTIONNAME record"); + SectionTable.push_back(S); + break; + } + case bitc::MODULE_CODE_GCNAME: { // SECTIONNAME: [strchr x N] + std::string S; + if (ConvertToString(Record, 0, S)) + return Error("Invalid MODULE_CODE_GCNAME record"); + GCTable.push_back(S); + break; + } + // GLOBALVAR: [pointer type, isconst, initid, + // linkage, alignment, section, visibility, threadlocal] + case bitc::MODULE_CODE_GLOBALVAR: { + if (Record.size() < 6) + return Error("Invalid MODULE_CODE_GLOBALVAR record"); + const Type *Ty = getTypeByID(Record[0]); + if (!isa(Ty)) + return Error("Global not a pointer type!"); + unsigned AddressSpace = cast(Ty)->getAddressSpace(); + Ty = cast(Ty)->getElementType(); + + bool isConstant = Record[1]; + GlobalValue::LinkageTypes Linkage = GetDecodedLinkage(Record[3]); + unsigned Alignment = (1 << Record[4]) >> 1; + std::string Section; + if (Record[5]) { + if (Record[5]-1 >= SectionTable.size()) + return Error("Invalid section ID"); + Section = SectionTable[Record[5]-1]; + } + GlobalValue::VisibilityTypes Visibility = GlobalValue::DefaultVisibility; + if (Record.size() > 6) + Visibility = GetDecodedVisibility(Record[6]); + bool isThreadLocal = false; + if (Record.size() > 7) + isThreadLocal = Record[7]; + + GlobalVariable *NewGV = + new GlobalVariable(*TheModule, Ty, isConstant, Linkage, 0, "", 0, + isThreadLocal, AddressSpace); + NewGV->setAlignment(Alignment); + if (!Section.empty()) + NewGV->setSection(Section); + NewGV->setVisibility(Visibility); + NewGV->setThreadLocal(isThreadLocal); + + ValueList.push_back(NewGV); + + // Remember which value to use for the global initializer. + if (unsigned InitID = Record[2]) + GlobalInits.push_back(std::make_pair(NewGV, InitID-1)); + break; + } + // FUNCTION: [type, callingconv, isproto, linkage, paramattr, + // alignment, section, visibility, gc] + case bitc::MODULE_CODE_FUNCTION: { + if (Record.size() < 8) + return Error("Invalid MODULE_CODE_FUNCTION record"); + const Type *Ty = getTypeByID(Record[0]); + if (!isa(Ty)) + return Error("Function not a pointer type!"); + const FunctionType *FTy = + dyn_cast(cast(Ty)->getElementType()); + if (!FTy) + return Error("Function not a pointer to function type!"); + + Function *Func = Function::Create(FTy, GlobalValue::ExternalLinkage, + "", TheModule); + + Func->setCallingConv(static_cast(Record[1])); + bool isProto = Record[2]; + Func->setLinkage(GetDecodedLinkage(Record[3])); + Func->setAttributes(getAttributes(Record[4])); + + Func->setAlignment((1 << Record[5]) >> 1); + if (Record[6]) { + if (Record[6]-1 >= SectionTable.size()) + return Error("Invalid section ID"); + Func->setSection(SectionTable[Record[6]-1]); + } + Func->setVisibility(GetDecodedVisibility(Record[7])); + if (Record.size() > 8 && Record[8]) { + if (Record[8]-1 > GCTable.size()) + return Error("Invalid GC ID"); + Func->setGC(GCTable[Record[8]-1].c_str()); + } + ValueList.push_back(Func); + + // If this is a function with a body, remember the prototype we are + // creating now, so that we can match up the body with them later. + if (!isProto) + FunctionsWithBodies.push_back(Func); + break; + } + // ALIAS: [alias type, aliasee val#, linkage] + // ALIAS: [alias type, aliasee val#, linkage, visibility] + case bitc::MODULE_CODE_ALIAS: { + if (Record.size() < 3) + return Error("Invalid MODULE_ALIAS record"); + const Type *Ty = getTypeByID(Record[0]); + if (!isa(Ty)) + return Error("Function not a pointer type!"); + + GlobalAlias *NewGA = new GlobalAlias(Ty, GetDecodedLinkage(Record[2]), + "", 0, TheModule); + // Old bitcode files didn't have visibility field. + if (Record.size() > 3) + NewGA->setVisibility(GetDecodedVisibility(Record[3])); + ValueList.push_back(NewGA); + AliasInits.push_back(std::make_pair(NewGA, Record[1])); + break; + } + /// MODULE_CODE_PURGEVALS: [numvals] + case bitc::MODULE_CODE_PURGEVALS: + // Trim down the value list to the specified size. + if (Record.size() < 1 || Record[0] > ValueList.size()) + return Error("Invalid MODULE_PURGEVALS record"); + ValueList.shrinkTo(Record[0]); + break; + } + Record.clear(); + } + + return Error("Premature end of bitstream"); +} + +bool BitcodeReader::ParseBitcode() { + TheModule = 0; + + if (Buffer->getBufferSize() & 3) + return Error("Bitcode stream should be a multiple of 4 bytes in length"); + + unsigned char *BufPtr = (unsigned char *)Buffer->getBufferStart(); + unsigned char *BufEnd = BufPtr+Buffer->getBufferSize(); + + // If we have a wrapper header, parse it and ignore the non-bc file contents. + // The magic number is 0x0B17C0DE stored in little endian. + if (isBitcodeWrapper(BufPtr, BufEnd)) + if (SkipBitcodeWrapperHeader(BufPtr, BufEnd)) + return Error("Invalid bitcode wrapper header"); + + StreamFile.init(BufPtr, BufEnd); + Stream.init(StreamFile); + + // Sniff for the signature. + if (Stream.Read(8) != 'B' || + Stream.Read(8) != 'C' || + Stream.Read(4) != 0x0 || + Stream.Read(4) != 0xC || + Stream.Read(4) != 0xE || + Stream.Read(4) != 0xD) + return Error("Invalid bitcode signature"); + + // We expect a number of well-defined blocks, though we don't necessarily + // need to understand them all. + while (!Stream.AtEndOfStream()) { + unsigned Code = Stream.ReadCode(); + + if (Code != bitc::ENTER_SUBBLOCK) + return Error("Invalid record at top-level"); + + unsigned BlockID = Stream.ReadSubBlockID(); + + // We only know the MODULE subblock ID. + switch (BlockID) { + case bitc::BLOCKINFO_BLOCK_ID: + if (Stream.ReadBlockInfoBlock()) + return Error("Malformed BlockInfoBlock"); + break; + case bitc::MODULE_BLOCK_ID: + if (ParseModule(Buffer->getBufferIdentifier())) + return true; + break; + default: + if (Stream.SkipBlock()) + return Error("Malformed block record"); + break; + } + } + + return false; +} + +/// ParseMetadataAttachment - Parse metadata attachments. +bool BitcodeReader::ParseMetadataAttachment() { + if (Stream.EnterSubBlock(bitc::METADATA_ATTACHMENT_ID)) + return Error("Malformed block record"); + + MetadataContext &TheMetadata = Context.getMetadata(); + SmallVector Record; + while(1) { + unsigned Code = Stream.ReadCode(); + if (Code == bitc::END_BLOCK) { + if (Stream.ReadBlockEnd()) + return Error("Error at end of PARAMATTR block"); + break; + } + if (Code == bitc::DEFINE_ABBREV) { + Stream.ReadAbbrevRecord(); + continue; + } + // Read a metadata attachment record. + Record.clear(); + switch (Stream.ReadRecord(Code, Record)) { + default: // Default behavior: ignore. + break; + case bitc::METADATA_ATTACHMENT: { + unsigned RecordLength = Record.size(); + if (Record.empty() || (RecordLength - 1) % 2 == 1) + return Error ("Invalid METADATA_ATTACHMENT reader!"); + Instruction *Inst = InstructionList[Record[0]]; + for (unsigned i = 1; i != RecordLength; i = i+2) { + unsigned Kind = Record[i]; + Value *Node = MDValueList.getValueFwdRef(Record[i+1]); + TheMetadata.addMD(Kind, cast(Node), Inst); + } + break; + } + } + } + return false; +} + +/// ParseFunctionBody - Lazily parse the specified function body block. +bool BitcodeReader::ParseFunctionBody(Function *F) { + if (Stream.EnterSubBlock(bitc::FUNCTION_BLOCK_ID)) + return Error("Malformed block record"); + + unsigned ModuleValueListSize = ValueList.size(); + + // Add all the function arguments to the value table. + for(Function::arg_iterator I = F->arg_begin(), E = F->arg_end(); I != E; ++I) + ValueList.push_back(I); + + unsigned NextValueNo = ValueList.size(); + BasicBlock *CurBB = 0; + unsigned CurBBNo = 0; + + // Read all the records. + SmallVector Record; + while (1) { + unsigned Code = Stream.ReadCode(); + if (Code == bitc::END_BLOCK) { + if (Stream.ReadBlockEnd()) + return Error("Error at end of function block"); + break; + } + + if (Code == bitc::ENTER_SUBBLOCK) { + switch (Stream.ReadSubBlockID()) { + default: // Skip unknown content. + if (Stream.SkipBlock()) + return Error("Malformed block record"); + break; + case bitc::CONSTANTS_BLOCK_ID: + if (ParseConstants()) return true; + NextValueNo = ValueList.size(); + break; + case bitc::VALUE_SYMTAB_BLOCK_ID: + if (ParseValueSymbolTable()) return true; + break; + case bitc::METADATA_ATTACHMENT_ID: + if (ParseMetadataAttachment()) return true; + break; + } + continue; + } + + if (Code == bitc::DEFINE_ABBREV) { + Stream.ReadAbbrevRecord(); + continue; + } + + // Read a record. + Record.clear(); + Instruction *I = 0; + unsigned BitCode = Stream.ReadRecord(Code, Record); + switch (BitCode) { + default: // Default behavior: reject + return Error("Unknown instruction"); + case bitc::FUNC_CODE_DECLAREBLOCKS: // DECLAREBLOCKS: [nblocks] + if (Record.size() < 1 || Record[0] == 0) + return Error("Invalid DECLAREBLOCKS record"); + // Create all the basic blocks for the function. + FunctionBBs.resize(Record[0]); + for (unsigned i = 0, e = FunctionBBs.size(); i != e; ++i) + FunctionBBs[i] = BasicBlock::Create(Context, "", F); + CurBB = FunctionBBs[0]; + continue; + + case bitc::FUNC_CODE_INST_BINOP: { // BINOP: [opval, ty, opval, opcode] + unsigned OpNum = 0; + Value *LHS, *RHS; + if (getValueTypePair(Record, OpNum, NextValueNo, LHS) || + getValue(Record, OpNum, LHS->getType(), RHS) || + OpNum+1 > Record.size()) + return Error("Invalid BINOP record"); + + int Opc = GetDecodedBinaryOpcode(Record[OpNum++], LHS->getType()); + if (Opc == -1) return Error("Invalid BINOP record"); + I = BinaryOperator::Create((Instruction::BinaryOps)Opc, LHS, RHS); + InstructionList.push_back(I); + if (OpNum < Record.size()) { + if (Opc == Instruction::Add || + Opc == Instruction::Sub || + Opc == Instruction::Mul) { + if (Record[3] & (1 << bitc::OBO_NO_SIGNED_WRAP)) + cast(I)->setHasNoSignedWrap(true); + if (Record[3] & (1 << bitc::OBO_NO_UNSIGNED_WRAP)) + cast(I)->setHasNoUnsignedWrap(true); + } else if (Opc == Instruction::SDiv) { + if (Record[3] & (1 << bitc::SDIV_EXACT)) + cast(I)->setIsExact(true); + } + } + break; + } + case bitc::FUNC_CODE_INST_CAST: { // CAST: [opval, opty, destty, castopc] + unsigned OpNum = 0; + Value *Op; + if (getValueTypePair(Record, OpNum, NextValueNo, Op) || + OpNum+2 != Record.size()) + return Error("Invalid CAST record"); + + const Type *ResTy = getTypeByID(Record[OpNum]); + int Opc = GetDecodedCastOpcode(Record[OpNum+1]); + if (Opc == -1 || ResTy == 0) + return Error("Invalid CAST record"); + I = CastInst::Create((Instruction::CastOps)Opc, Op, ResTy); + InstructionList.push_back(I); + break; + } + case bitc::FUNC_CODE_INST_INBOUNDS_GEP: + case bitc::FUNC_CODE_INST_GEP: { // GEP: [n x operands] + unsigned OpNum = 0; + Value *BasePtr; + if (getValueTypePair(Record, OpNum, NextValueNo, BasePtr)) + return Error("Invalid GEP record"); + + SmallVector GEPIdx; + while (OpNum != Record.size()) { + Value *Op; + if (getValueTypePair(Record, OpNum, NextValueNo, Op)) + return Error("Invalid GEP record"); + GEPIdx.push_back(Op); + } + + I = GetElementPtrInst::Create(BasePtr, GEPIdx.begin(), GEPIdx.end()); + InstructionList.push_back(I); + if (BitCode == bitc::FUNC_CODE_INST_INBOUNDS_GEP) + cast(I)->setIsInBounds(true); + break; + } + + case bitc::FUNC_CODE_INST_EXTRACTVAL: { + // EXTRACTVAL: [opty, opval, n x indices] + unsigned OpNum = 0; + Value *Agg; + if (getValueTypePair(Record, OpNum, NextValueNo, Agg)) + return Error("Invalid EXTRACTVAL record"); + + SmallVector EXTRACTVALIdx; + for (unsigned RecSize = Record.size(); + OpNum != RecSize; ++OpNum) { + uint64_t Index = Record[OpNum]; + if ((unsigned)Index != Index) + return Error("Invalid EXTRACTVAL index"); + EXTRACTVALIdx.push_back((unsigned)Index); + } + + I = ExtractValueInst::Create(Agg, + EXTRACTVALIdx.begin(), EXTRACTVALIdx.end()); + InstructionList.push_back(I); + break; + } + + case bitc::FUNC_CODE_INST_INSERTVAL: { + // INSERTVAL: [opty, opval, opty, opval, n x indices] + unsigned OpNum = 0; + Value *Agg; + if (getValueTypePair(Record, OpNum, NextValueNo, Agg)) + return Error("Invalid INSERTVAL record"); + Value *Val; + if (getValueTypePair(Record, OpNum, NextValueNo, Val)) + return Error("Invalid INSERTVAL record"); + + SmallVector INSERTVALIdx; + for (unsigned RecSize = Record.size(); + OpNum != RecSize; ++OpNum) { + uint64_t Index = Record[OpNum]; + if ((unsigned)Index != Index) + return Error("Invalid INSERTVAL index"); + INSERTVALIdx.push_back((unsigned)Index); + } + + I = InsertValueInst::Create(Agg, Val, + INSERTVALIdx.begin(), INSERTVALIdx.end()); + InstructionList.push_back(I); + break; + } + + case bitc::FUNC_CODE_INST_SELECT: { // SELECT: [opval, ty, opval, opval] + // obsolete form of select + // handles select i1 ... in old bitcode + unsigned OpNum = 0; + Value *TrueVal, *FalseVal, *Cond; + if (getValueTypePair(Record, OpNum, NextValueNo, TrueVal) || + getValue(Record, OpNum, TrueVal->getType(), FalseVal) || + getValue(Record, OpNum, Type::getInt1Ty(Context), Cond)) + return Error("Invalid SELECT record"); + + I = SelectInst::Create(Cond, TrueVal, FalseVal); + InstructionList.push_back(I); + break; + } + + case bitc::FUNC_CODE_INST_VSELECT: {// VSELECT: [ty,opval,opval,predty,pred] + // new form of select + // handles select i1 or select [N x i1] + unsigned OpNum = 0; + Value *TrueVal, *FalseVal, *Cond; + if (getValueTypePair(Record, OpNum, NextValueNo, TrueVal) || + getValue(Record, OpNum, TrueVal->getType(), FalseVal) || + getValueTypePair(Record, OpNum, NextValueNo, Cond)) + return Error("Invalid SELECT record"); + + // select condition can be either i1 or [N x i1] + if (const VectorType* vector_type = + dyn_cast(Cond->getType())) { + // expect + if (vector_type->getElementType() != Type::getInt1Ty(Context)) + return Error("Invalid SELECT condition type"); + } else { + // expect i1 + if (Cond->getType() != Type::getInt1Ty(Context)) + return Error("Invalid SELECT condition type"); + } + + I = SelectInst::Create(Cond, TrueVal, FalseVal); + InstructionList.push_back(I); + break; + } + + case bitc::FUNC_CODE_INST_EXTRACTELT: { // EXTRACTELT: [opty, opval, opval] + unsigned OpNum = 0; + Value *Vec, *Idx; + if (getValueTypePair(Record, OpNum, NextValueNo, Vec) || + getValue(Record, OpNum, Type::getInt32Ty(Context), Idx)) + return Error("Invalid EXTRACTELT record"); + I = ExtractElementInst::Create(Vec, Idx); + InstructionList.push_back(I); + break; + } + + case bitc::FUNC_CODE_INST_INSERTELT: { // INSERTELT: [ty, opval,opval,opval] + unsigned OpNum = 0; + Value *Vec, *Elt, *Idx; + if (getValueTypePair(Record, OpNum, NextValueNo, Vec) || + getValue(Record, OpNum, + cast(Vec->getType())->getElementType(), Elt) || + getValue(Record, OpNum, Type::getInt32Ty(Context), Idx)) + return Error("Invalid INSERTELT record"); + I = InsertElementInst::Create(Vec, Elt, Idx); + InstructionList.push_back(I); + break; + } + + case bitc::FUNC_CODE_INST_SHUFFLEVEC: {// SHUFFLEVEC: [opval,ty,opval,opval] + unsigned OpNum = 0; + Value *Vec1, *Vec2, *Mask; + if (getValueTypePair(Record, OpNum, NextValueNo, Vec1) || + getValue(Record, OpNum, Vec1->getType(), Vec2)) + return Error("Invalid SHUFFLEVEC record"); + + if (getValueTypePair(Record, OpNum, NextValueNo, Mask)) + return Error("Invalid SHUFFLEVEC record"); + I = new ShuffleVectorInst(Vec1, Vec2, Mask); + InstructionList.push_back(I); + break; + } + + case bitc::FUNC_CODE_INST_CMP: // CMP: [opty, opval, opval, pred] + // Old form of ICmp/FCmp returning bool + // Existed to differentiate between icmp/fcmp and vicmp/vfcmp which were + // both legal on vectors but had different behaviour. + case bitc::FUNC_CODE_INST_CMP2: { // CMP2: [opty, opval, opval, pred] + // FCmp/ICmp returning bool or vector of bool + + unsigned OpNum = 0; + Value *LHS, *RHS; + if (getValueTypePair(Record, OpNum, NextValueNo, LHS) || + getValue(Record, OpNum, LHS->getType(), RHS) || + OpNum+1 != Record.size()) + return Error("Invalid CMP record"); + + if (LHS->getType()->isFPOrFPVector()) + I = new FCmpInst((FCmpInst::Predicate)Record[OpNum], LHS, RHS); + else + I = new ICmpInst((ICmpInst::Predicate)Record[OpNum], LHS, RHS); + InstructionList.push_back(I); + break; + } + + case bitc::FUNC_CODE_INST_GETRESULT: { // GETRESULT: [ty, val, n] + if (Record.size() != 2) + return Error("Invalid GETRESULT record"); + unsigned OpNum = 0; + Value *Op; + getValueTypePair(Record, OpNum, NextValueNo, Op); + unsigned Index = Record[1]; + I = ExtractValueInst::Create(Op, Index); + InstructionList.push_back(I); + break; + } + + case bitc::FUNC_CODE_INST_RET: // RET: [opty,opval] + { + unsigned Size = Record.size(); + if (Size == 0) { + I = ReturnInst::Create(Context); + InstructionList.push_back(I); + break; + } + + unsigned OpNum = 0; + SmallVector Vs; + do { + Value *Op = NULL; + if (getValueTypePair(Record, OpNum, NextValueNo, Op)) + return Error("Invalid RET record"); + Vs.push_back(Op); + } while(OpNum != Record.size()); + + const Type *ReturnType = F->getReturnType(); + if (Vs.size() > 1 || + (isa(ReturnType) && + (Vs.empty() || Vs[0]->getType() != ReturnType))) { + Value *RV = UndefValue::get(ReturnType); + for (unsigned i = 0, e = Vs.size(); i != e; ++i) { + I = InsertValueInst::Create(RV, Vs[i], i, "mrv"); + InstructionList.push_back(I); + CurBB->getInstList().push_back(I); + ValueList.AssignValue(I, NextValueNo++); + RV = I; + } + I = ReturnInst::Create(Context, RV); + InstructionList.push_back(I); + break; + } + + I = ReturnInst::Create(Context, Vs[0]); + InstructionList.push_back(I); + break; + } + case bitc::FUNC_CODE_INST_BR: { // BR: [bb#, bb#, opval] or [bb#] + if (Record.size() != 1 && Record.size() != 3) + return Error("Invalid BR record"); + BasicBlock *TrueDest = getBasicBlock(Record[0]); + if (TrueDest == 0) + return Error("Invalid BR record"); + + if (Record.size() == 1) { + I = BranchInst::Create(TrueDest); + InstructionList.push_back(I); + } + else { + BasicBlock *FalseDest = getBasicBlock(Record[1]); + Value *Cond = getFnValueByID(Record[2], Type::getInt1Ty(Context)); + if (FalseDest == 0 || Cond == 0) + return Error("Invalid BR record"); + I = BranchInst::Create(TrueDest, FalseDest, Cond); + InstructionList.push_back(I); + } + break; + } + case bitc::FUNC_CODE_INST_SWITCH: { // SWITCH: [opty, op0, op1, ...] + if (Record.size() < 3 || (Record.size() & 1) == 0) + return Error("Invalid SWITCH record"); + const Type *OpTy = getTypeByID(Record[0]); + Value *Cond = getFnValueByID(Record[1], OpTy); + BasicBlock *Default = getBasicBlock(Record[2]); + if (OpTy == 0 || Cond == 0 || Default == 0) + return Error("Invalid SWITCH record"); + unsigned NumCases = (Record.size()-3)/2; + SwitchInst *SI = SwitchInst::Create(Cond, Default, NumCases); + InstructionList.push_back(SI); + for (unsigned i = 0, e = NumCases; i != e; ++i) { + ConstantInt *CaseVal = + dyn_cast_or_null(getFnValueByID(Record[3+i*2], OpTy)); + BasicBlock *DestBB = getBasicBlock(Record[1+3+i*2]); + if (CaseVal == 0 || DestBB == 0) { + delete SI; + return Error("Invalid SWITCH record!"); + } + SI->addCase(CaseVal, DestBB); + } + I = SI; + break; + } + case bitc::FUNC_CODE_INST_INDIRECTBR: { // INDIRECTBR: [opty, op0, op1, ...] + if (Record.size() < 2) + return Error("Invalid INDIRECTBR record"); + const Type *OpTy = getTypeByID(Record[0]); + Value *Address = getFnValueByID(Record[1], OpTy); + if (OpTy == 0 || Address == 0) + return Error("Invalid INDIRECTBR record"); + unsigned NumDests = Record.size()-2; + IndirectBrInst *IBI = IndirectBrInst::Create(Address, NumDests); + InstructionList.push_back(IBI); + for (unsigned i = 0, e = NumDests; i != e; ++i) { + if (BasicBlock *DestBB = getBasicBlock(Record[2+i])) { + IBI->addDestination(DestBB); + } else { + delete IBI; + return Error("Invalid INDIRECTBR record!"); + } + } + I = IBI; + break; + } + + case bitc::FUNC_CODE_INST_INVOKE: { + // INVOKE: [attrs, cc, normBB, unwindBB, fnty, op0,op1,op2, ...] + if (Record.size() < 4) return Error("Invalid INVOKE record"); + AttrListPtr PAL = getAttributes(Record[0]); + unsigned CCInfo = Record[1]; + BasicBlock *NormalBB = getBasicBlock(Record[2]); + BasicBlock *UnwindBB = getBasicBlock(Record[3]); + + unsigned OpNum = 4; + Value *Callee; + if (getValueTypePair(Record, OpNum, NextValueNo, Callee)) + return Error("Invalid INVOKE record"); + + const PointerType *CalleeTy = dyn_cast(Callee->getType()); + const FunctionType *FTy = !CalleeTy ? 0 : + dyn_cast(CalleeTy->getElementType()); + + // Check that the right number of fixed parameters are here. + if (FTy == 0 || NormalBB == 0 || UnwindBB == 0 || + Record.size() < OpNum+FTy->getNumParams()) + return Error("Invalid INVOKE record"); + + SmallVector Ops; + for (unsigned i = 0, e = FTy->getNumParams(); i != e; ++i, ++OpNum) { + Ops.push_back(getFnValueByID(Record[OpNum], FTy->getParamType(i))); + if (Ops.back() == 0) return Error("Invalid INVOKE record"); + } + + if (!FTy->isVarArg()) { + if (Record.size() != OpNum) + return Error("Invalid INVOKE record"); + } else { + // Read type/value pairs for varargs params. + while (OpNum != Record.size()) { + Value *Op; + if (getValueTypePair(Record, OpNum, NextValueNo, Op)) + return Error("Invalid INVOKE record"); + Ops.push_back(Op); + } + } + + I = InvokeInst::Create(Callee, NormalBB, UnwindBB, + Ops.begin(), Ops.end()); + InstructionList.push_back(I); + cast(I)->setCallingConv( + static_cast(CCInfo)); + cast(I)->setAttributes(PAL); + break; + } + case bitc::FUNC_CODE_INST_UNWIND: // UNWIND + I = new UnwindInst(Context); + InstructionList.push_back(I); + break; + case bitc::FUNC_CODE_INST_UNREACHABLE: // UNREACHABLE + I = new UnreachableInst(Context); + InstructionList.push_back(I); + break; + case bitc::FUNC_CODE_INST_PHI: { // PHI: [ty, val0,bb0, ...] + if (Record.size() < 1 || ((Record.size()-1)&1)) + return Error("Invalid PHI record"); + const Type *Ty = getTypeByID(Record[0]); + if (!Ty) return Error("Invalid PHI record"); + + PHINode *PN = PHINode::Create(Ty); + InstructionList.push_back(PN); + PN->reserveOperandSpace((Record.size()-1)/2); + + for (unsigned i = 0, e = Record.size()-1; i != e; i += 2) { + Value *V = getFnValueByID(Record[1+i], Ty); + BasicBlock *BB = getBasicBlock(Record[2+i]); + if (!V || !BB) return Error("Invalid PHI record"); + PN->addIncoming(V, BB); + } + I = PN; + break; + } + + case bitc::FUNC_CODE_INST_MALLOC: { // MALLOC: [instty, op, align] + // Autoupgrade malloc instruction to malloc call. + // FIXME: Remove in LLVM 3.0. + if (Record.size() < 3) + return Error("Invalid MALLOC record"); + const PointerType *Ty = + dyn_cast_or_null(getTypeByID(Record[0])); + Value *Size = getFnValueByID(Record[1], Type::getInt32Ty(Context)); + if (!Ty || !Size) return Error("Invalid MALLOC record"); + if (!CurBB) return Error("Invalid malloc instruction with no BB"); + const Type *Int32Ty = IntegerType::getInt32Ty(CurBB->getContext()); + Constant *AllocSize = ConstantExpr::getSizeOf(Ty->getElementType()); + AllocSize = ConstantExpr::getTruncOrBitCast(AllocSize, Int32Ty); + I = CallInst::CreateMalloc(CurBB, Int32Ty, Ty->getElementType(), + AllocSize, Size, NULL); + InstructionList.push_back(I); + break; + } + case bitc::FUNC_CODE_INST_FREE: { // FREE: [op, opty] + unsigned OpNum = 0; + Value *Op; + if (getValueTypePair(Record, OpNum, NextValueNo, Op) || + OpNum != Record.size()) + return Error("Invalid FREE record"); + if (!CurBB) return Error("Invalid free instruction with no BB"); + I = CallInst::CreateFree(Op, CurBB); + InstructionList.push_back(I); + break; + } + case bitc::FUNC_CODE_INST_ALLOCA: { // ALLOCA: [instty, op, align] + if (Record.size() < 3) + return Error("Invalid ALLOCA record"); + const PointerType *Ty = + dyn_cast_or_null(getTypeByID(Record[0])); + Value *Size = getFnValueByID(Record[1], Type::getInt32Ty(Context)); + unsigned Align = Record[2]; + if (!Ty || !Size) return Error("Invalid ALLOCA record"); + I = new AllocaInst(Ty->getElementType(), Size, (1 << Align) >> 1); + InstructionList.push_back(I); + break; + } + case bitc::FUNC_CODE_INST_LOAD: { // LOAD: [opty, op, align, vol] + unsigned OpNum = 0; + Value *Op; + if (getValueTypePair(Record, OpNum, NextValueNo, Op) || + OpNum+2 != Record.size()) + return Error("Invalid LOAD record"); + + I = new LoadInst(Op, "", Record[OpNum+1], (1 << Record[OpNum]) >> 1); + InstructionList.push_back(I); + break; + } + case bitc::FUNC_CODE_INST_STORE2: { // STORE2:[ptrty, ptr, val, align, vol] + unsigned OpNum = 0; + Value *Val, *Ptr; + if (getValueTypePair(Record, OpNum, NextValueNo, Ptr) || + getValue(Record, OpNum, + cast(Ptr->getType())->getElementType(), Val) || + OpNum+2 != Record.size()) + return Error("Invalid STORE record"); + + I = new StoreInst(Val, Ptr, Record[OpNum+1], (1 << Record[OpNum]) >> 1); + InstructionList.push_back(I); + break; + } + case bitc::FUNC_CODE_INST_STORE: { // STORE:[val, valty, ptr, align, vol] + // FIXME: Legacy form of store instruction. Should be removed in LLVM 3.0. + unsigned OpNum = 0; + Value *Val, *Ptr; + if (getValueTypePair(Record, OpNum, NextValueNo, Val) || + getValue(Record, OpNum, + PointerType::getUnqual(Val->getType()), Ptr)|| + OpNum+2 != Record.size()) + return Error("Invalid STORE record"); + + I = new StoreInst(Val, Ptr, Record[OpNum+1], (1 << Record[OpNum]) >> 1); + InstructionList.push_back(I); + break; + } + case bitc::FUNC_CODE_INST_CALL: { + // CALL: [paramattrs, cc, fnty, fnid, arg0, arg1...] + if (Record.size() < 3) + return Error("Invalid CALL record"); + + AttrListPtr PAL = getAttributes(Record[0]); + unsigned CCInfo = Record[1]; + + unsigned OpNum = 2; + Value *Callee; + if (getValueTypePair(Record, OpNum, NextValueNo, Callee)) + return Error("Invalid CALL record"); + + const PointerType *OpTy = dyn_cast(Callee->getType()); + const FunctionType *FTy = 0; + if (OpTy) FTy = dyn_cast(OpTy->getElementType()); + if (!FTy || Record.size() < FTy->getNumParams()+OpNum) + return Error("Invalid CALL record"); + + SmallVector Args; + // Read the fixed params. + for (unsigned i = 0, e = FTy->getNumParams(); i != e; ++i, ++OpNum) { + if (FTy->getParamType(i)->getTypeID()==Type::LabelTyID) + Args.push_back(getBasicBlock(Record[OpNum])); + else + Args.push_back(getFnValueByID(Record[OpNum], FTy->getParamType(i))); + if (Args.back() == 0) return Error("Invalid CALL record"); + } + + // Read type/value pairs for varargs params. + if (!FTy->isVarArg()) { + if (OpNum != Record.size()) + return Error("Invalid CALL record"); + } else { + while (OpNum != Record.size()) { + Value *Op; + if (getValueTypePair(Record, OpNum, NextValueNo, Op)) + return Error("Invalid CALL record"); + Args.push_back(Op); + } + } + + I = CallInst::Create(Callee, Args.begin(), Args.end()); + InstructionList.push_back(I); + cast(I)->setCallingConv( + static_cast(CCInfo>>1)); + cast(I)->setTailCall(CCInfo & 1); + cast(I)->setAttributes(PAL); + break; + } + case bitc::FUNC_CODE_INST_VAARG: { // VAARG: [valistty, valist, instty] + if (Record.size() < 3) + return Error("Invalid VAARG record"); + const Type *OpTy = getTypeByID(Record[0]); + Value *Op = getFnValueByID(Record[1], OpTy); + const Type *ResTy = getTypeByID(Record[2]); + if (!OpTy || !Op || !ResTy) + return Error("Invalid VAARG record"); + I = new VAArgInst(Op, ResTy); + InstructionList.push_back(I); + break; + } + } + + // Add instruction to end of current BB. If there is no current BB, reject + // this file. + if (CurBB == 0) { + delete I; + return Error("Invalid instruction with no BB"); + } + CurBB->getInstList().push_back(I); + + // If this was a terminator instruction, move to the next block. + if (isa(I)) { + ++CurBBNo; + CurBB = CurBBNo < FunctionBBs.size() ? FunctionBBs[CurBBNo] : 0; + } + + // Non-void values get registered in the value table for future use. + if (I && I->getType() != Type::getVoidTy(Context)) + ValueList.AssignValue(I, NextValueNo++); + } + + // Check the function list for unresolved values. + if (Argument *A = dyn_cast(ValueList.back())) { + if (A->getParent() == 0) { + // We found at least one unresolved value. Nuke them all to avoid leaks. + for (unsigned i = ModuleValueListSize, e = ValueList.size(); i != e; ++i){ + if ((A = dyn_cast(ValueList.back())) && A->getParent() == 0) { + A->replaceAllUsesWith(UndefValue::get(A->getType())); + delete A; + } + } + return Error("Never resolved value found in function!"); + } + } + + // See if anything took the address of blocks in this function. If so, + // resolve them now. + /// BlockAddrFwdRefs - These are blockaddr references to basic blocks. These + /// are resolved lazily when functions are loaded. + DenseMap >::iterator BAFRI = + BlockAddrFwdRefs.find(F); + if (BAFRI != BlockAddrFwdRefs.end()) { + std::vector &RefList = BAFRI->second; + for (unsigned i = 0, e = RefList.size(); i != e; ++i) { + unsigned BlockIdx = RefList[i].first; + if (BlockIdx >= FunctionBBs.size()) + return Error("Invalid blockaddress block #"); + + GlobalVariable *FwdRef = RefList[i].second; + FwdRef->replaceAllUsesWith(BlockAddress::get(F, FunctionBBs[BlockIdx])); + FwdRef->eraseFromParent(); + } + + BlockAddrFwdRefs.erase(BAFRI); + } + + // Trim the value list down to the size it was before we parsed this function. + ValueList.shrinkTo(ModuleValueListSize); + std::vector().swap(FunctionBBs); + + return false; +} + +//===----------------------------------------------------------------------===// +// ModuleProvider implementation +//===----------------------------------------------------------------------===// + + +bool BitcodeReader::materializeFunction(Function *F, std::string *ErrInfo) { + // If it already is material, ignore the request. + if (!F->hasNotBeenReadFromBitcode()) return false; + + DenseMap >::iterator DFII = + DeferredFunctionInfo.find(F); + assert(DFII != DeferredFunctionInfo.end() && "Deferred function not found!"); + + // Move the bit stream to the saved position of the deferred function body and + // restore the real linkage type for the function. + Stream.JumpToBit(DFII->second.first); + F->setLinkage((GlobalValue::LinkageTypes)DFII->second.second); + + if (ParseFunctionBody(F)) { + if (ErrInfo) *ErrInfo = ErrorString; + return true; + } + + // Upgrade any old intrinsic calls in the function. + for (UpgradedIntrinsicMap::iterator I = UpgradedIntrinsics.begin(), + E = UpgradedIntrinsics.end(); I != E; ++I) { + if (I->first != I->second) { + for (Value::use_iterator UI = I->first->use_begin(), + UE = I->first->use_end(); UI != UE; ) { + if (CallInst* CI = dyn_cast(*UI++)) + UpgradeIntrinsicCall(CI, I->second); + } + } + } + + return false; +} + +void BitcodeReader::dematerializeFunction(Function *F) { + // If this function isn't materialized, or if it is a proto, this is a noop. + if (F->hasNotBeenReadFromBitcode() || F->isDeclaration()) + return; + + assert(DeferredFunctionInfo.count(F) && "No info to read function later?"); + + // Just forget the function body, we can remat it later. + F->deleteBody(); + F->setLinkage(GlobalValue::GhostLinkage); +} + + +Module *BitcodeReader::materializeModule(std::string *ErrInfo) { + // Iterate over the module, deserializing any functions that are still on + // disk. + for (Module::iterator F = TheModule->begin(), E = TheModule->end(); + F != E; ++F) + if (F->hasNotBeenReadFromBitcode() && + materializeFunction(F, ErrInfo)) + return 0; + + // Upgrade any intrinsic calls that slipped through (should not happen!) and + // delete the old functions to clean up. We can't do this unless the entire + // module is materialized because there could always be another function body + // with calls to the old function. + for (std::vector >::iterator I = + UpgradedIntrinsics.begin(), E = UpgradedIntrinsics.end(); I != E; ++I) { + if (I->first != I->second) { + for (Value::use_iterator UI = I->first->use_begin(), + UE = I->first->use_end(); UI != UE; ) { + if (CallInst* CI = dyn_cast(*UI++)) + UpgradeIntrinsicCall(CI, I->second); + } + if (!I->first->use_empty()) + I->first->replaceAllUsesWith(I->second); + I->first->eraseFromParent(); + } + } + std::vector >().swap(UpgradedIntrinsics); + + // Check debug info intrinsics. + CheckDebugInfoIntrinsics(TheModule); + + return TheModule; +} + + +/// This method is provided by the parent ModuleProvde class and overriden +/// here. It simply releases the module from its provided and frees up our +/// state. +/// @brief Release our hold on the generated module +Module *BitcodeReader::releaseModule(std::string *ErrInfo) { + // Since we're losing control of this Module, we must hand it back complete + Module *M = ModuleProvider::releaseModule(ErrInfo); + FreeState(); + return M; +} + + +//===----------------------------------------------------------------------===// +// External interface +//===----------------------------------------------------------------------===// + +/// getBitcodeModuleProvider - lazy function-at-a-time loading from a file. +/// +ModuleProvider *llvm::getBitcodeModuleProvider(MemoryBuffer *Buffer, + LLVMContext& Context, + std::string *ErrMsg) { + BitcodeReader *R = new BitcodeReader(Buffer, Context); + if (R->ParseBitcode()) { + if (ErrMsg) + *ErrMsg = R->getErrorString(); + + // Don't let the BitcodeReader dtor delete 'Buffer'. + R->releaseMemoryBuffer(); + delete R; + return 0; + } + return R; +} + +/// ParseBitcodeFile - Read the specified bitcode file, returning the module. +/// If an error occurs, return null and fill in *ErrMsg if non-null. +Module *llvm::ParseBitcodeFile(MemoryBuffer *Buffer, LLVMContext& Context, + std::string *ErrMsg){ + BitcodeReader *R; + R = static_cast(getBitcodeModuleProvider(Buffer, Context, + ErrMsg)); + if (!R) return 0; + + // Read in the entire module. + Module *M = R->materializeModule(ErrMsg); + + // Don't let the BitcodeReader dtor delete 'Buffer', regardless of whether + // there was an error. + R->releaseMemoryBuffer(); + + // If there was no error, tell ModuleProvider not to delete it when its dtor + // is run. + if (M) + M = R->releaseModule(ErrMsg); + + delete R; + return M; +} diff --git a/libclamav/c++/llvm/lib/Bitcode/Reader/BitcodeReader.h b/libclamav/c++/llvm/lib/Bitcode/Reader/BitcodeReader.h new file mode 100644 index 000000000..7b3a1ae89 --- /dev/null +++ b/libclamav/c++/llvm/lib/Bitcode/Reader/BitcodeReader.h @@ -0,0 +1,266 @@ +//===- BitcodeReader.h - Internal BitcodeReader impl ------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This header defines the BitcodeReader class. +// +//===----------------------------------------------------------------------===// + +#ifndef BITCODE_READER_H +#define BITCODE_READER_H + +#include "llvm/ModuleProvider.h" +#include "llvm/Attributes.h" +#include "llvm/Type.h" +#include "llvm/OperandTraits.h" +#include "llvm/Bitcode/BitstreamReader.h" +#include "llvm/Bitcode/LLVMBitCodes.h" +#include "llvm/Support/ValueHandle.h" +#include "llvm/ADT/DenseMap.h" +#include + +namespace llvm { + class MemoryBuffer; + class LLVMContext; + +//===----------------------------------------------------------------------===// +// BitcodeReaderValueList Class +//===----------------------------------------------------------------------===// + +class BitcodeReaderValueList { + std::vector ValuePtrs; + + /// ResolveConstants - As we resolve forward-referenced constants, we add + /// information about them to this vector. This allows us to resolve them in + /// bulk instead of resolving each reference at a time. See the code in + /// ResolveConstantForwardRefs for more information about this. + /// + /// The key of this vector is the placeholder constant, the value is the slot + /// number that holds the resolved value. + typedef std::vector > ResolveConstantsTy; + ResolveConstantsTy ResolveConstants; + LLVMContext& Context; +public: + BitcodeReaderValueList(LLVMContext& C) : Context(C) {} + ~BitcodeReaderValueList() { + assert(ResolveConstants.empty() && "Constants not resolved?"); + } + + // vector compatibility methods + unsigned size() const { return ValuePtrs.size(); } + void resize(unsigned N) { ValuePtrs.resize(N); } + void push_back(Value *V) { + ValuePtrs.push_back(V); + } + + void clear() { + assert(ResolveConstants.empty() && "Constants not resolved?"); + ValuePtrs.clear(); + } + + Value *operator[](unsigned i) const { + assert(i < ValuePtrs.size()); + return ValuePtrs[i]; + } + + Value *back() const { return ValuePtrs.back(); } + void pop_back() { ValuePtrs.pop_back(); } + bool empty() const { return ValuePtrs.empty(); } + void shrinkTo(unsigned N) { + assert(N <= size() && "Invalid shrinkTo request!"); + ValuePtrs.resize(N); + } + + Constant *getConstantFwdRef(unsigned Idx, const Type *Ty); + Value *getValueFwdRef(unsigned Idx, const Type *Ty); + + void AssignValue(Value *V, unsigned Idx); + + /// ResolveConstantForwardRefs - Once all constants are read, this method bulk + /// resolves any forward references. + void ResolveConstantForwardRefs(); +}; + + +//===----------------------------------------------------------------------===// +// BitcodeReaderMDValueList Class +//===----------------------------------------------------------------------===// + +class BitcodeReaderMDValueList { + std::vector MDValuePtrs; + + LLVMContext &Context; +public: + BitcodeReaderMDValueList(LLVMContext& C) : Context(C) {} + + // vector compatibility methods + unsigned size() const { return MDValuePtrs.size(); } + void resize(unsigned N) { MDValuePtrs.resize(N); } + void push_back(Value *V) { MDValuePtrs.push_back(V); } + void clear() { MDValuePtrs.clear(); } + Value *back() const { return MDValuePtrs.back(); } + void pop_back() { MDValuePtrs.pop_back(); } + bool empty() const { return MDValuePtrs.empty(); } + + Value *operator[](unsigned i) const { + assert(i < MDValuePtrs.size()); + return MDValuePtrs[i]; + } + + void shrinkTo(unsigned N) { + assert(N <= size() && "Invalid shrinkTo request!"); + MDValuePtrs.resize(N); + } + + Value *getValueFwdRef(unsigned Idx); + void AssignValue(Value *V, unsigned Idx); +}; + +class BitcodeReader : public ModuleProvider { + LLVMContext &Context; + MemoryBuffer *Buffer; + BitstreamReader StreamFile; + BitstreamCursor Stream; + + const char *ErrorString; + + std::vector TypeList; + BitcodeReaderValueList ValueList; + BitcodeReaderMDValueList MDValueList; + SmallVector InstructionList; + + std::vector > GlobalInits; + std::vector > AliasInits; + + /// MAttributes - The set of attributes by index. Index zero in the + /// file is for null, and is thus not represented here. As such all indices + /// are off by one. + std::vector MAttributes; + + /// FunctionBBs - While parsing a function body, this is a list of the basic + /// blocks for the function. + std::vector FunctionBBs; + + // When reading the module header, this list is populated with functions that + // have bodies later in the file. + std::vector FunctionsWithBodies; + + // When intrinsic functions are encountered which require upgrading they are + // stored here with their replacement function. + typedef std::vector > UpgradedIntrinsicMap; + UpgradedIntrinsicMap UpgradedIntrinsics; + + // After the module header has been read, the FunctionsWithBodies list is + // reversed. This keeps track of whether we've done this yet. + bool HasReversedFunctionsWithBodies; + + /// DeferredFunctionInfo - When function bodies are initially scanned, this + /// map contains info about where to find deferred function body (in the + /// stream) and what linkage the original function had. + DenseMap > DeferredFunctionInfo; + + /// BlockAddrFwdRefs - These are blockaddr references to basic blocks. These + /// are resolved lazily when functions are loaded. + typedef std::pair BlockAddrRefTy; + DenseMap > BlockAddrFwdRefs; + +public: + explicit BitcodeReader(MemoryBuffer *buffer, LLVMContext& C) + : Context(C), Buffer(buffer), ErrorString(0), ValueList(C), MDValueList(C) { + HasReversedFunctionsWithBodies = false; + } + ~BitcodeReader() { + FreeState(); + } + + void FreeState(); + + /// releaseMemoryBuffer - This causes the reader to completely forget about + /// the memory buffer it contains, which prevents the buffer from being + /// destroyed when it is deleted. + void releaseMemoryBuffer() { + Buffer = 0; + } + + virtual bool materializeFunction(Function *F, std::string *ErrInfo = 0); + virtual Module *materializeModule(std::string *ErrInfo = 0); + virtual void dematerializeFunction(Function *F); + virtual Module *releaseModule(std::string *ErrInfo = 0); + + bool Error(const char *Str) { + ErrorString = Str; + return true; + } + const char *getErrorString() const { return ErrorString; } + + /// @brief Main interface to parsing a bitcode buffer. + /// @returns true if an error occurred. + bool ParseBitcode(); +private: + const Type *getTypeByID(unsigned ID, bool isTypeTable = false); + Value *getFnValueByID(unsigned ID, const Type *Ty) { + if (Ty == Type::getMetadataTy(Context)) + return MDValueList.getValueFwdRef(ID); + else + return ValueList.getValueFwdRef(ID, Ty); + } + BasicBlock *getBasicBlock(unsigned ID) const { + if (ID >= FunctionBBs.size()) return 0; // Invalid ID + return FunctionBBs[ID]; + } + AttrListPtr getAttributes(unsigned i) const { + if (i-1 < MAttributes.size()) + return MAttributes[i-1]; + return AttrListPtr(); + } + + /// getValueTypePair - Read a value/type pair out of the specified record from + /// slot 'Slot'. Increment Slot past the number of slots used in the record. + /// Return true on failure. + bool getValueTypePair(SmallVector &Record, unsigned &Slot, + unsigned InstNum, Value *&ResVal) { + if (Slot == Record.size()) return true; + unsigned ValNo = (unsigned)Record[Slot++]; + if (ValNo < InstNum) { + // If this is not a forward reference, just return the value we already + // have. + ResVal = getFnValueByID(ValNo, 0); + return ResVal == 0; + } else if (Slot == Record.size()) { + return true; + } + + unsigned TypeNo = (unsigned)Record[Slot++]; + ResVal = getFnValueByID(ValNo, getTypeByID(TypeNo)); + return ResVal == 0; + } + bool getValue(SmallVector &Record, unsigned &Slot, + const Type *Ty, Value *&ResVal) { + if (Slot == Record.size()) return true; + unsigned ValNo = (unsigned)Record[Slot++]; + ResVal = getFnValueByID(ValNo, Ty); + return ResVal == 0; + } + + + bool ParseModule(const std::string &ModuleID); + bool ParseAttributeBlock(); + bool ParseTypeTable(); + bool ParseTypeSymbolTable(); + bool ParseValueSymbolTable(); + bool ParseConstants(); + bool RememberAndSkipFunctionBody(); + bool ParseFunctionBody(Function *F); + bool ResolveGlobalAndAliasInits(); + bool ParseMetadata(); + bool ParseMetadataAttachment(); +}; + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/lib/Bitcode/Reader/CMakeLists.txt b/libclamav/c++/llvm/lib/Bitcode/Reader/CMakeLists.txt new file mode 100644 index 000000000..a19c79aac --- /dev/null +++ b/libclamav/c++/llvm/lib/Bitcode/Reader/CMakeLists.txt @@ -0,0 +1,7 @@ +add_llvm_library(LLVMBitReader + BitReader.cpp + BitcodeReader.cpp + Deserialize.cpp + DeserializeAPFloat.cpp + DeserializeAPInt.cpp + ) \ No newline at end of file diff --git a/libclamav/c++/llvm/lib/Bitcode/Reader/Deserialize.cpp b/libclamav/c++/llvm/lib/Bitcode/Reader/Deserialize.cpp new file mode 100644 index 000000000..67607efae --- /dev/null +++ b/libclamav/c++/llvm/lib/Bitcode/Reader/Deserialize.cpp @@ -0,0 +1,450 @@ +//==- Deserialize.cpp - Generic Object Serialization to Bitcode --*- 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 the internal methods used for object serialization. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Bitcode/Deserialize.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +Deserializer::Deserializer(BitstreamReader& stream) + : Stream(stream), RecIdx(0), FreeList(NULL), AbbrevNo(0), RecordCode(0) { + + StreamStart = Stream.GetCurrentBitNo(); +} + +Deserializer::~Deserializer() { + assert (RecIdx >= Record.size() && + "Still scanning bitcode record when deserialization completed."); + +#ifdef DEBUG_BACKPATCH + for (MapTy::iterator I=BPatchMap.begin(), E=BPatchMap.end(); I!=E; ++I) + assert (I->first.hasFinalPtr() && + "Some pointers were not backpatched."); +#endif +} + + +bool Deserializer::inRecord() { + if (Record.size() > 0) { + if (RecIdx >= Record.size()) { + RecIdx = 0; + Record.clear(); + AbbrevNo = 0; + return false; + } + else + return true; + } + + return false; +} + +bool Deserializer::AdvanceStream() { + assert (!inRecord() && + "Cannot advance stream. Still processing a record."); + + if (AbbrevNo == bitc::ENTER_SUBBLOCK || + AbbrevNo >= bitc::UNABBREV_RECORD) + return true; + + while (!Stream.AtEndOfStream()) { + + uint64_t Pos = Stream.GetCurrentBitNo(); + AbbrevNo = Stream.ReadCode(); + + switch (AbbrevNo) { + case bitc::ENTER_SUBBLOCK: { + unsigned id = Stream.ReadSubBlockID(); + + // Determine the extent of the block. This is useful for jumping around + // the stream. This is hack: we read the header of the block, save + // the length, and then revert the bitstream to a location just before + // the block is entered. + uint64_t BPos = Stream.GetCurrentBitNo(); + Stream.ReadVBR(bitc::CodeLenWidth); // Skip the code size. + Stream.SkipToWord(); + unsigned NumWords = Stream.Read(bitc::BlockSizeWidth); + Stream.JumpToBit(BPos); + + BlockStack.push_back(Location(Pos,id,NumWords)); + break; + } + + case bitc::END_BLOCK: { + bool x = Stream.ReadBlockEnd(); + assert(!x && "Error at block end."); x=x; + BlockStack.pop_back(); + continue; + } + + case bitc::DEFINE_ABBREV: + Stream.ReadAbbrevRecord(); + continue; + + default: + break; + } + + return true; + } + + return false; +} + +void Deserializer::ReadRecord() { + + while (AdvanceStream() && AbbrevNo == bitc::ENTER_SUBBLOCK) { + assert (!BlockStack.empty()); + Stream.EnterSubBlock(BlockStack.back().BlockID); + AbbrevNo = 0; + } + + if (Stream.AtEndOfStream()) + return; + + assert (Record.empty()); + assert (AbbrevNo >= bitc::UNABBREV_RECORD); + RecordCode = Stream.ReadRecord(AbbrevNo,Record); + assert (Record.size() > 0); +} + +void Deserializer::SkipBlock() { + assert (!inRecord()); + + if (AtEnd()) + return; + + AdvanceStream(); + + assert (AbbrevNo == bitc::ENTER_SUBBLOCK); + BlockStack.pop_back(); + Stream.SkipBlock(); + + AbbrevNo = 0; + AdvanceStream(); +} + +bool Deserializer::SkipToBlock(unsigned BlockID) { + assert (!inRecord()); + + AdvanceStream(); + assert (AbbrevNo == bitc::ENTER_SUBBLOCK); + + unsigned BlockLevel = BlockStack.size(); + + while (!AtEnd() && + BlockLevel == BlockStack.size() && + getCurrentBlockID() != BlockID) + SkipBlock(); + + return !(AtEnd() || BlockLevel != BlockStack.size()); +} + +Deserializer::Location Deserializer::getCurrentBlockLocation() { + if (!inRecord()) + AdvanceStream(); + + return BlockStack.back(); +} + +bool Deserializer::JumpTo(const Location& Loc) { + + assert (!inRecord()); + + AdvanceStream(); + + assert (!BlockStack.empty() || AtEnd()); + + uint64_t LastBPos = StreamStart; + + while (!BlockStack.empty()) { + + LastBPos = BlockStack.back().BitNo; + + // Determine of the current block contains the location of the block + // we are looking for. + if (BlockStack.back().contains(Loc)) { + // We found the enclosing block. We must first POP it off to + // destroy any accumulated context within the block scope. We then + // jump to the position of the block and enter it. + Stream.JumpToBit(LastBPos); + + if (BlockStack.size() == Stream.BlockScope.size()) + Stream.PopBlockScope(); + + BlockStack.pop_back(); + + AbbrevNo = 0; + AdvanceStream(); + assert (AbbrevNo == bitc::ENTER_SUBBLOCK); + + Stream.EnterSubBlock(BlockStack.back().BlockID); + break; + } + + // This block does not contain the block we are looking for. Pop it. + if (BlockStack.size() == Stream.BlockScope.size()) + Stream.PopBlockScope(); + + BlockStack.pop_back(); + + } + + // Check if we have popped our way to the outermost scope. If so, + // we need to adjust our position. + if (BlockStack.empty()) { + assert (Stream.BlockScope.empty()); + + Stream.JumpToBit(Loc.BitNo < LastBPos ? StreamStart : LastBPos); + AbbrevNo = 0; + AdvanceStream(); + } + + assert (AbbrevNo == bitc::ENTER_SUBBLOCK); + assert (!BlockStack.empty()); + + while (!AtEnd() && BlockStack.back() != Loc) { + if (BlockStack.back().contains(Loc)) { + Stream.EnterSubBlock(BlockStack.back().BlockID); + AbbrevNo = 0; + AdvanceStream(); + continue; + } + else + SkipBlock(); + } + + if (AtEnd()) + return false; + + assert (BlockStack.back() == Loc); + + return true; +} + +void Deserializer::Rewind() { + while (!Stream.BlockScope.empty()) + Stream.PopBlockScope(); + + while (!BlockStack.empty()) + BlockStack.pop_back(); + + Stream.JumpToBit(StreamStart); + AbbrevNo = 0; +} + + +unsigned Deserializer::getCurrentBlockID() { + if (!inRecord()) + AdvanceStream(); + + return BlockStack.back().BlockID; +} + +unsigned Deserializer::getRecordCode() { + if (!inRecord()) { + AdvanceStream(); + assert (AbbrevNo >= bitc::UNABBREV_RECORD); + ReadRecord(); + } + + return RecordCode; +} + +bool Deserializer::FinishedBlock(Location BlockLoc) { + if (!inRecord()) + AdvanceStream(); + + for (llvm::SmallVector::reverse_iterator + I=BlockStack.rbegin(), E=BlockStack.rend(); I!=E; ++I) + if (*I == BlockLoc) + return false; + + return true; +} + +unsigned Deserializer::getAbbrevNo() { + if (!inRecord()) + AdvanceStream(); + + return AbbrevNo; +} + +bool Deserializer::AtEnd() { + if (inRecord()) + return false; + + if (!AdvanceStream()) + return true; + + return false; +} + +uint64_t Deserializer::ReadInt() { + // FIXME: Any error recovery/handling with incomplete or bad files? + if (!inRecord()) + ReadRecord(); + + return Record[RecIdx++]; +} + +int64_t Deserializer::ReadSInt() { + uint64_t x = ReadInt(); + int64_t magnitude = x >> 1; + return x & 0x1 ? -magnitude : magnitude; +} + +char* Deserializer::ReadCStr(char* cstr, unsigned MaxLen, bool isNullTerm) { + if (cstr == NULL) + MaxLen = 0; // Zero this just in case someone does something funny. + + unsigned len = ReadInt(); + + assert (MaxLen == 0 || (len + (isNullTerm ? 1 : 0)) <= MaxLen); + + if (!cstr) + cstr = new char[len + (isNullTerm ? 1 : 0)]; + + assert (cstr != NULL); + + for (unsigned i = 0; i < len; ++i) + cstr[i] = (char) ReadInt(); + + if (isNullTerm) + cstr[len] = '\0'; + + return cstr; +} + +void Deserializer::ReadCStr(std::vector& buff, bool isNullTerm, + unsigned Idx) { + + unsigned len = ReadInt(); + + // If Idx is beyond the current before size, reduce Idx to refer to the + // element after the last element. + if (Idx > buff.size()) + Idx = buff.size(); + + buff.reserve(len+Idx); + buff.resize(Idx); + + for (unsigned i = 0; i < len; ++i) + buff.push_back((char) ReadInt()); + + if (isNullTerm) + buff.push_back('\0'); +} + +void Deserializer::RegisterPtr(const SerializedPtrID& PtrId, + const void* Ptr) { + + MapTy::value_type& E = BPatchMap.FindAndConstruct(BPKey(PtrId)); + + assert (!HasFinalPtr(E) && "Pointer already registered."); + +#ifdef DEBUG_BACKPATCH + errs() << "RegisterPtr: " << PtrId << " => " << Ptr << "\n"; +#endif + + SetPtr(E,Ptr); +} + +void Deserializer::ReadUIntPtr(uintptr_t& PtrRef, + const SerializedPtrID& PtrId, + bool AllowBackpatch) { + if (PtrId == 0) { + PtrRef = 0; + return; + } + + MapTy::value_type& E = BPatchMap.FindAndConstruct(BPKey(PtrId)); + + if (HasFinalPtr(E)) { + PtrRef = GetFinalPtr(E); + +#ifdef DEBUG_BACKPATCH + errs() << "ReadUintPtr: " << PtrId + << " <-- " << (void*) GetFinalPtr(E) << '\n'; +#endif + } + else { + assert (AllowBackpatch && + "Client forbids backpatching for this pointer."); + +#ifdef DEBUG_BACKPATCH + errs() << "ReadUintPtr: " << PtrId << " (NO PTR YET)\n"; +#endif + + // Register backpatch. Check the freelist for a BPNode. + BPNode* N; + + if (FreeList) { + N = FreeList; + FreeList = FreeList->Next; + } + else // No available BPNode. Allocate one. + N = (BPNode*) Allocator.Allocate(); + + new (N) BPNode(GetBPNode(E),PtrRef); + SetBPNode(E,N); + } +} + +uintptr_t Deserializer::ReadInternalRefPtr() { + SerializedPtrID PtrId = ReadPtrID(); + + assert (PtrId != 0 && "References cannot refer the NULL address."); + + MapTy::value_type& E = BPatchMap.FindAndConstruct(BPKey(PtrId)); + + assert (HasFinalPtr(E) && + "Cannot backpatch references. Object must be already deserialized."); + + return GetFinalPtr(E); +} + +void Deserializer::BPEntry::SetPtr(BPNode*& FreeList, void* P) { + BPNode* Last = NULL; + + for (BPNode* N = Head; N != NULL; N=N->Next) { + Last = N; + N->PtrRef |= reinterpret_cast(P); + } + + if (Last) { + Last->Next = FreeList; + FreeList = Head; + } + + Ptr = const_cast(P); +} + + +#define INT_READ(TYPE)\ +void SerializeTrait::Read(Deserializer& D, TYPE& X) {\ + X = (TYPE) D.ReadInt(); } + +INT_READ(bool) +INT_READ(unsigned char) +INT_READ(unsigned short) +INT_READ(unsigned int) +INT_READ(unsigned long) + +#define SINT_READ(TYPE)\ +void SerializeTrait::Read(Deserializer& D, TYPE& X) {\ + X = (TYPE) D.ReadSInt(); } + +INT_READ(signed char) +INT_READ(signed short) +INT_READ(signed int) +INT_READ(signed long) diff --git a/libclamav/c++/llvm/lib/Bitcode/Reader/DeserializeAPFloat.cpp b/libclamav/c++/llvm/lib/Bitcode/Reader/DeserializeAPFloat.cpp new file mode 100644 index 000000000..ee24b681f --- /dev/null +++ b/libclamav/c++/llvm/lib/Bitcode/Reader/DeserializeAPFloat.cpp @@ -0,0 +1,24 @@ +//===-- SerializeAPInt.cpp - Serialization for APFloat ---------*- 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 deserialization of APFloat. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/APFloat.h" +#include "llvm/Bitcode/Deserialize.h" + +using namespace llvm; + +APFloat APFloat::ReadVal(Deserializer& D) { + APInt x; + D.Read(x); + return APFloat(x); +} + diff --git a/libclamav/c++/llvm/lib/Bitcode/Reader/DeserializeAPInt.cpp b/libclamav/c++/llvm/lib/Bitcode/Reader/DeserializeAPInt.cpp new file mode 100644 index 000000000..1b5b2bf1f --- /dev/null +++ b/libclamav/c++/llvm/lib/Bitcode/Reader/DeserializeAPInt.cpp @@ -0,0 +1,33 @@ +//===-- DeserializeAPInt.cpp - Deserialization for APInts ------*- 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 deserialization of APInts. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/APInt.h" +#include "llvm/Bitcode/Deserialize.h" +#include + +using namespace llvm; + +void APInt::Read(Deserializer& D) { + BitWidth = D.ReadInt(); + + if (isSingleWord()) + VAL = D.ReadInt(); + else { + uint32_t NumWords = D.ReadInt(); + assert (NumWords > 1); + pVal = new uint64_t[NumWords]; + assert (pVal && "Allocation in deserialization of APInt failed."); + for (unsigned i = 0; i < NumWords; ++i) + pVal[i] = D.ReadInt(); + } +} diff --git a/libclamav/c++/llvm/lib/Bitcode/Reader/Makefile b/libclamav/c++/llvm/lib/Bitcode/Reader/Makefile new file mode 100644 index 000000000..59af8d53a --- /dev/null +++ b/libclamav/c++/llvm/lib/Bitcode/Reader/Makefile @@ -0,0 +1,15 @@ +##===- lib/Bitcode/Reader/Makefile -------------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LEVEL = ../../.. +LIBRARYNAME = LLVMBitReader +BUILD_ARCHIVE = 1 + +include $(LEVEL)/Makefile.common + diff --git a/libclamav/c++/llvm/lib/Bitcode/Writer/BitWriter.cpp b/libclamav/c++/llvm/lib/Bitcode/Writer/BitWriter.cpp new file mode 100644 index 000000000..7ed651b77 --- /dev/null +++ b/libclamav/c++/llvm/lib/Bitcode/Writer/BitWriter.cpp @@ -0,0 +1,46 @@ +//===-- BitWriter.cpp -----------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm-c/BitWriter.h" +#include "llvm/Bitcode/ReaderWriter.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + + +/*===-- Operations on modules ---------------------------------------------===*/ + +int LLVMWriteBitcodeToFile(LLVMModuleRef M, const char *Path) { + std::string ErrorInfo; + raw_fd_ostream OS(Path, ErrorInfo, + raw_fd_ostream::F_Binary); + + if (!ErrorInfo.empty()) + return -1; + + WriteBitcodeToFile(unwrap(M), OS); + return 0; +} + +#if defined(__GNUC__) && (__GNUC__ > 3 || __GNUC__ == 3 && __GNUC_MINOR >= 4) +#include + +int LLVMWriteBitcodeToFileHandle(LLVMModuleRef M, int FileHandle) { + raw_fd_ostream OS(FileHandle, false); + + WriteBitcodeToFile(unwrap(M), OS); + return 0; +} + +#else + +int LLVMWriteBitcodeToFileHandle(LLVMModuleRef M, int FileHandle) { + return -1; // Not supported. +} + +#endif diff --git a/libclamav/c++/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/libclamav/c++/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp new file mode 100644 index 000000000..af0b8acd4 --- /dev/null +++ b/libclamav/c++/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -0,0 +1,1587 @@ +//===--- Bitcode/Writer/BitcodeWriter.cpp - Bitcode Writer ----------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Bitcode writer implementation. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Bitcode/ReaderWriter.h" +#include "llvm/Bitcode/BitstreamWriter.h" +#include "llvm/Bitcode/LLVMBitCodes.h" +#include "ValueEnumerator.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/InlineAsm.h" +#include "llvm/Instructions.h" +#include "llvm/LLVMContext.h" +#include "llvm/Metadata.h" +#include "llvm/Module.h" +#include "llvm/Operator.h" +#include "llvm/TypeSymbolTable.h" +#include "llvm/ValueSymbolTable.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/System/Program.h" +using namespace llvm; + +/// These are manifest constants used by the bitcode writer. They do not need to +/// be kept in sync with the reader, but need to be consistent within this file. +enum { + CurVersion = 0, + + // VALUE_SYMTAB_BLOCK abbrev id's. + VST_ENTRY_8_ABBREV = bitc::FIRST_APPLICATION_ABBREV, + VST_ENTRY_7_ABBREV, + VST_ENTRY_6_ABBREV, + VST_BBENTRY_6_ABBREV, + + // CONSTANTS_BLOCK abbrev id's. + CONSTANTS_SETTYPE_ABBREV = bitc::FIRST_APPLICATION_ABBREV, + CONSTANTS_INTEGER_ABBREV, + CONSTANTS_CE_CAST_Abbrev, + CONSTANTS_NULL_Abbrev, + + // FUNCTION_BLOCK abbrev id's. + FUNCTION_INST_LOAD_ABBREV = bitc::FIRST_APPLICATION_ABBREV, + FUNCTION_INST_BINOP_ABBREV, + FUNCTION_INST_BINOP_FLAGS_ABBREV, + FUNCTION_INST_CAST_ABBREV, + FUNCTION_INST_RET_VOID_ABBREV, + FUNCTION_INST_RET_VAL_ABBREV, + FUNCTION_INST_UNREACHABLE_ABBREV +}; + + +static unsigned GetEncodedCastOpcode(unsigned Opcode) { + switch (Opcode) { + default: llvm_unreachable("Unknown cast instruction!"); + case Instruction::Trunc : return bitc::CAST_TRUNC; + case Instruction::ZExt : return bitc::CAST_ZEXT; + case Instruction::SExt : return bitc::CAST_SEXT; + case Instruction::FPToUI : return bitc::CAST_FPTOUI; + case Instruction::FPToSI : return bitc::CAST_FPTOSI; + case Instruction::UIToFP : return bitc::CAST_UITOFP; + case Instruction::SIToFP : return bitc::CAST_SITOFP; + case Instruction::FPTrunc : return bitc::CAST_FPTRUNC; + case Instruction::FPExt : return bitc::CAST_FPEXT; + case Instruction::PtrToInt: return bitc::CAST_PTRTOINT; + case Instruction::IntToPtr: return bitc::CAST_INTTOPTR; + case Instruction::BitCast : return bitc::CAST_BITCAST; + } +} + +static unsigned GetEncodedBinaryOpcode(unsigned Opcode) { + switch (Opcode) { + default: llvm_unreachable("Unknown binary instruction!"); + case Instruction::Add: + case Instruction::FAdd: return bitc::BINOP_ADD; + case Instruction::Sub: + case Instruction::FSub: return bitc::BINOP_SUB; + case Instruction::Mul: + case Instruction::FMul: return bitc::BINOP_MUL; + case Instruction::UDiv: return bitc::BINOP_UDIV; + case Instruction::FDiv: + case Instruction::SDiv: return bitc::BINOP_SDIV; + case Instruction::URem: return bitc::BINOP_UREM; + case Instruction::FRem: + case Instruction::SRem: return bitc::BINOP_SREM; + case Instruction::Shl: return bitc::BINOP_SHL; + case Instruction::LShr: return bitc::BINOP_LSHR; + case Instruction::AShr: return bitc::BINOP_ASHR; + case Instruction::And: return bitc::BINOP_AND; + case Instruction::Or: return bitc::BINOP_OR; + case Instruction::Xor: return bitc::BINOP_XOR; + } +} + + + +static void WriteStringRecord(unsigned Code, const std::string &Str, + unsigned AbbrevToUse, BitstreamWriter &Stream) { + SmallVector Vals; + + // Code: [strchar x N] + for (unsigned i = 0, e = Str.size(); i != e; ++i) + Vals.push_back(Str[i]); + + // Emit the finished record. + Stream.EmitRecord(Code, Vals, AbbrevToUse); +} + +// Emit information about parameter attributes. +static void WriteAttributeTable(const ValueEnumerator &VE, + BitstreamWriter &Stream) { + const std::vector &Attrs = VE.getAttributes(); + if (Attrs.empty()) return; + + Stream.EnterSubblock(bitc::PARAMATTR_BLOCK_ID, 3); + + SmallVector Record; + for (unsigned i = 0, e = Attrs.size(); i != e; ++i) { + const AttrListPtr &A = Attrs[i]; + for (unsigned i = 0, e = A.getNumSlots(); i != e; ++i) { + const AttributeWithIndex &PAWI = A.getSlot(i); + Record.push_back(PAWI.Index); + + // FIXME: remove in LLVM 3.0 + // Store the alignment in the bitcode as a 16-bit raw value instead of a + // 5-bit log2 encoded value. Shift the bits above the alignment up by + // 11 bits. + uint64_t FauxAttr = PAWI.Attrs & 0xffff; + if (PAWI.Attrs & Attribute::Alignment) + FauxAttr |= (1ull<<16)<<(((PAWI.Attrs & Attribute::Alignment)-1) >> 16); + FauxAttr |= (PAWI.Attrs & (0x3FFull << 21)) << 11; + + Record.push_back(FauxAttr); + } + + Stream.EmitRecord(bitc::PARAMATTR_CODE_ENTRY, Record); + Record.clear(); + } + + Stream.ExitBlock(); +} + +/// WriteTypeTable - Write out the type table for a module. +static void WriteTypeTable(const ValueEnumerator &VE, BitstreamWriter &Stream) { + const ValueEnumerator::TypeList &TypeList = VE.getTypes(); + + Stream.EnterSubblock(bitc::TYPE_BLOCK_ID, 4 /*count from # abbrevs */); + SmallVector TypeVals; + + // Abbrev for TYPE_CODE_POINTER. + BitCodeAbbrev *Abbv = new BitCodeAbbrev(); + Abbv->Add(BitCodeAbbrevOp(bitc::TYPE_CODE_POINTER)); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, + Log2_32_Ceil(VE.getTypes().size()+1))); + Abbv->Add(BitCodeAbbrevOp(0)); // Addrspace = 0 + unsigned PtrAbbrev = Stream.EmitAbbrev(Abbv); + + // Abbrev for TYPE_CODE_FUNCTION. + Abbv = new BitCodeAbbrev(); + Abbv->Add(BitCodeAbbrevOp(bitc::TYPE_CODE_FUNCTION)); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isvararg + Abbv->Add(BitCodeAbbrevOp(0)); // FIXME: DEAD value, remove in LLVM 3.0 + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, + Log2_32_Ceil(VE.getTypes().size()+1))); + unsigned FunctionAbbrev = Stream.EmitAbbrev(Abbv); + + // Abbrev for TYPE_CODE_STRUCT. + Abbv = new BitCodeAbbrev(); + Abbv->Add(BitCodeAbbrevOp(bitc::TYPE_CODE_STRUCT)); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // ispacked + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, + Log2_32_Ceil(VE.getTypes().size()+1))); + unsigned StructAbbrev = Stream.EmitAbbrev(Abbv); + + // Abbrev for TYPE_CODE_ARRAY. + Abbv = new BitCodeAbbrev(); + Abbv->Add(BitCodeAbbrevOp(bitc::TYPE_CODE_ARRAY)); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // size + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, + Log2_32_Ceil(VE.getTypes().size()+1))); + unsigned ArrayAbbrev = Stream.EmitAbbrev(Abbv); + + // Emit an entry count so the reader can reserve space. + TypeVals.push_back(TypeList.size()); + Stream.EmitRecord(bitc::TYPE_CODE_NUMENTRY, TypeVals); + TypeVals.clear(); + + // Loop over all of the types, emitting each in turn. + for (unsigned i = 0, e = TypeList.size(); i != e; ++i) { + const Type *T = TypeList[i].first; + int AbbrevToUse = 0; + unsigned Code = 0; + + switch (T->getTypeID()) { + default: llvm_unreachable("Unknown type!"); + case Type::VoidTyID: Code = bitc::TYPE_CODE_VOID; break; + case Type::FloatTyID: Code = bitc::TYPE_CODE_FLOAT; break; + case Type::DoubleTyID: Code = bitc::TYPE_CODE_DOUBLE; break; + case Type::X86_FP80TyID: Code = bitc::TYPE_CODE_X86_FP80; break; + case Type::FP128TyID: Code = bitc::TYPE_CODE_FP128; break; + case Type::PPC_FP128TyID: Code = bitc::TYPE_CODE_PPC_FP128; break; + case Type::LabelTyID: Code = bitc::TYPE_CODE_LABEL; break; + case Type::OpaqueTyID: Code = bitc::TYPE_CODE_OPAQUE; break; + case Type::MetadataTyID: Code = bitc::TYPE_CODE_METADATA; break; + case Type::IntegerTyID: + // INTEGER: [width] + Code = bitc::TYPE_CODE_INTEGER; + TypeVals.push_back(cast(T)->getBitWidth()); + break; + case Type::PointerTyID: { + const PointerType *PTy = cast(T); + // POINTER: [pointee type, address space] + Code = bitc::TYPE_CODE_POINTER; + TypeVals.push_back(VE.getTypeID(PTy->getElementType())); + unsigned AddressSpace = PTy->getAddressSpace(); + TypeVals.push_back(AddressSpace); + if (AddressSpace == 0) AbbrevToUse = PtrAbbrev; + break; + } + case Type::FunctionTyID: { + const FunctionType *FT = cast(T); + // FUNCTION: [isvararg, attrid, retty, paramty x N] + Code = bitc::TYPE_CODE_FUNCTION; + TypeVals.push_back(FT->isVarArg()); + TypeVals.push_back(0); // FIXME: DEAD: remove in llvm 3.0 + TypeVals.push_back(VE.getTypeID(FT->getReturnType())); + for (unsigned i = 0, e = FT->getNumParams(); i != e; ++i) + TypeVals.push_back(VE.getTypeID(FT->getParamType(i))); + AbbrevToUse = FunctionAbbrev; + break; + } + case Type::StructTyID: { + const StructType *ST = cast(T); + // STRUCT: [ispacked, eltty x N] + Code = bitc::TYPE_CODE_STRUCT; + TypeVals.push_back(ST->isPacked()); + // Output all of the element types. + for (StructType::element_iterator I = ST->element_begin(), + E = ST->element_end(); I != E; ++I) + TypeVals.push_back(VE.getTypeID(*I)); + AbbrevToUse = StructAbbrev; + break; + } + case Type::ArrayTyID: { + const ArrayType *AT = cast(T); + // ARRAY: [numelts, eltty] + Code = bitc::TYPE_CODE_ARRAY; + TypeVals.push_back(AT->getNumElements()); + TypeVals.push_back(VE.getTypeID(AT->getElementType())); + AbbrevToUse = ArrayAbbrev; + break; + } + case Type::VectorTyID: { + const VectorType *VT = cast(T); + // VECTOR [numelts, eltty] + Code = bitc::TYPE_CODE_VECTOR; + TypeVals.push_back(VT->getNumElements()); + TypeVals.push_back(VE.getTypeID(VT->getElementType())); + break; + } + } + + // Emit the finished record. + Stream.EmitRecord(Code, TypeVals, AbbrevToUse); + TypeVals.clear(); + } + + Stream.ExitBlock(); +} + +static unsigned getEncodedLinkage(const GlobalValue *GV) { + switch (GV->getLinkage()) { + default: llvm_unreachable("Invalid linkage!"); + case GlobalValue::GhostLinkage: // Map ghost linkage onto external. + case GlobalValue::ExternalLinkage: return 0; + case GlobalValue::WeakAnyLinkage: return 1; + case GlobalValue::AppendingLinkage: return 2; + case GlobalValue::InternalLinkage: return 3; + case GlobalValue::LinkOnceAnyLinkage: return 4; + case GlobalValue::DLLImportLinkage: return 5; + case GlobalValue::DLLExportLinkage: return 6; + case GlobalValue::ExternalWeakLinkage: return 7; + case GlobalValue::CommonLinkage: return 8; + case GlobalValue::PrivateLinkage: return 9; + case GlobalValue::WeakODRLinkage: return 10; + case GlobalValue::LinkOnceODRLinkage: return 11; + case GlobalValue::AvailableExternallyLinkage: return 12; + case GlobalValue::LinkerPrivateLinkage: return 13; + } +} + +static unsigned getEncodedVisibility(const GlobalValue *GV) { + switch (GV->getVisibility()) { + default: llvm_unreachable("Invalid visibility!"); + case GlobalValue::DefaultVisibility: return 0; + case GlobalValue::HiddenVisibility: return 1; + case GlobalValue::ProtectedVisibility: return 2; + } +} + +// Emit top-level description of module, including target triple, inline asm, +// descriptors for global variables, and function prototype info. +static void WriteModuleInfo(const Module *M, const ValueEnumerator &VE, + BitstreamWriter &Stream) { + // Emit the list of dependent libraries for the Module. + for (Module::lib_iterator I = M->lib_begin(), E = M->lib_end(); I != E; ++I) + WriteStringRecord(bitc::MODULE_CODE_DEPLIB, *I, 0/*TODO*/, Stream); + + // Emit various pieces of data attached to a module. + if (!M->getTargetTriple().empty()) + WriteStringRecord(bitc::MODULE_CODE_TRIPLE, M->getTargetTriple(), + 0/*TODO*/, Stream); + if (!M->getDataLayout().empty()) + WriteStringRecord(bitc::MODULE_CODE_DATALAYOUT, M->getDataLayout(), + 0/*TODO*/, Stream); + if (!M->getModuleInlineAsm().empty()) + WriteStringRecord(bitc::MODULE_CODE_ASM, M->getModuleInlineAsm(), + 0/*TODO*/, Stream); + + // Emit information about sections and GC, computing how many there are. Also + // compute the maximum alignment value. + std::map SectionMap; + std::map GCMap; + unsigned MaxAlignment = 0; + unsigned MaxGlobalType = 0; + for (Module::const_global_iterator GV = M->global_begin(),E = M->global_end(); + GV != E; ++GV) { + MaxAlignment = std::max(MaxAlignment, GV->getAlignment()); + MaxGlobalType = std::max(MaxGlobalType, VE.getTypeID(GV->getType())); + + if (!GV->hasSection()) continue; + // Give section names unique ID's. + unsigned &Entry = SectionMap[GV->getSection()]; + if (Entry != 0) continue; + WriteStringRecord(bitc::MODULE_CODE_SECTIONNAME, GV->getSection(), + 0/*TODO*/, Stream); + Entry = SectionMap.size(); + } + for (Module::const_iterator F = M->begin(), E = M->end(); F != E; ++F) { + MaxAlignment = std::max(MaxAlignment, F->getAlignment()); + if (F->hasSection()) { + // Give section names unique ID's. + unsigned &Entry = SectionMap[F->getSection()]; + if (!Entry) { + WriteStringRecord(bitc::MODULE_CODE_SECTIONNAME, F->getSection(), + 0/*TODO*/, Stream); + Entry = SectionMap.size(); + } + } + if (F->hasGC()) { + // Same for GC names. + unsigned &Entry = GCMap[F->getGC()]; + if (!Entry) { + WriteStringRecord(bitc::MODULE_CODE_GCNAME, F->getGC(), + 0/*TODO*/, Stream); + Entry = GCMap.size(); + } + } + } + + // Emit abbrev for globals, now that we know # sections and max alignment. + unsigned SimpleGVarAbbrev = 0; + if (!M->global_empty()) { + // Add an abbrev for common globals with no visibility or thread localness. + BitCodeAbbrev *Abbv = new BitCodeAbbrev(); + Abbv->Add(BitCodeAbbrevOp(bitc::MODULE_CODE_GLOBALVAR)); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, + Log2_32_Ceil(MaxGlobalType+1))); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Constant. + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Initializer. + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 4)); // Linkage. + if (MaxAlignment == 0) // Alignment. + Abbv->Add(BitCodeAbbrevOp(0)); + else { + unsigned MaxEncAlignment = Log2_32(MaxAlignment)+1; + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, + Log2_32_Ceil(MaxEncAlignment+1))); + } + if (SectionMap.empty()) // Section. + Abbv->Add(BitCodeAbbrevOp(0)); + else + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, + Log2_32_Ceil(SectionMap.size()+1))); + // Don't bother emitting vis + thread local. + SimpleGVarAbbrev = Stream.EmitAbbrev(Abbv); + } + + // Emit the global variable information. + SmallVector Vals; + for (Module::const_global_iterator GV = M->global_begin(),E = M->global_end(); + GV != E; ++GV) { + unsigned AbbrevToUse = 0; + + // GLOBALVAR: [type, isconst, initid, + // linkage, alignment, section, visibility, threadlocal] + Vals.push_back(VE.getTypeID(GV->getType())); + Vals.push_back(GV->isConstant()); + Vals.push_back(GV->isDeclaration() ? 0 : + (VE.getValueID(GV->getInitializer()) + 1)); + Vals.push_back(getEncodedLinkage(GV)); + Vals.push_back(Log2_32(GV->getAlignment())+1); + Vals.push_back(GV->hasSection() ? SectionMap[GV->getSection()] : 0); + if (GV->isThreadLocal() || + GV->getVisibility() != GlobalValue::DefaultVisibility) { + Vals.push_back(getEncodedVisibility(GV)); + Vals.push_back(GV->isThreadLocal()); + } else { + AbbrevToUse = SimpleGVarAbbrev; + } + + Stream.EmitRecord(bitc::MODULE_CODE_GLOBALVAR, Vals, AbbrevToUse); + Vals.clear(); + } + + // Emit the function proto information. + for (Module::const_iterator F = M->begin(), E = M->end(); F != E; ++F) { + // FUNCTION: [type, callingconv, isproto, paramattr, + // linkage, alignment, section, visibility, gc] + Vals.push_back(VE.getTypeID(F->getType())); + Vals.push_back(F->getCallingConv()); + Vals.push_back(F->isDeclaration()); + Vals.push_back(getEncodedLinkage(F)); + Vals.push_back(VE.getAttributeID(F->getAttributes())); + Vals.push_back(Log2_32(F->getAlignment())+1); + Vals.push_back(F->hasSection() ? SectionMap[F->getSection()] : 0); + Vals.push_back(getEncodedVisibility(F)); + Vals.push_back(F->hasGC() ? GCMap[F->getGC()] : 0); + + unsigned AbbrevToUse = 0; + Stream.EmitRecord(bitc::MODULE_CODE_FUNCTION, Vals, AbbrevToUse); + Vals.clear(); + } + + + // Emit the alias information. + for (Module::const_alias_iterator AI = M->alias_begin(), E = M->alias_end(); + AI != E; ++AI) { + Vals.push_back(VE.getTypeID(AI->getType())); + Vals.push_back(VE.getValueID(AI->getAliasee())); + Vals.push_back(getEncodedLinkage(AI)); + Vals.push_back(getEncodedVisibility(AI)); + unsigned AbbrevToUse = 0; + Stream.EmitRecord(bitc::MODULE_CODE_ALIAS, Vals, AbbrevToUse); + Vals.clear(); + } +} + +static uint64_t GetOptimizationFlags(const Value *V) { + uint64_t Flags = 0; + + if (const OverflowingBinaryOperator *OBO = + dyn_cast(V)) { + if (OBO->hasNoSignedWrap()) + Flags |= 1 << bitc::OBO_NO_SIGNED_WRAP; + if (OBO->hasNoUnsignedWrap()) + Flags |= 1 << bitc::OBO_NO_UNSIGNED_WRAP; + } else if (const SDivOperator *Div = dyn_cast(V)) { + if (Div->isExact()) + Flags |= 1 << bitc::SDIV_EXACT; + } + + return Flags; +} + +static void WriteMDNode(const MDNode *N, + const ValueEnumerator &VE, + BitstreamWriter &Stream, + SmallVector &Record) { + for (unsigned i = 0, e = N->getNumElements(); i != e; ++i) { + if (N->getElement(i)) { + Record.push_back(VE.getTypeID(N->getElement(i)->getType())); + Record.push_back(VE.getValueID(N->getElement(i))); + } else { + Record.push_back(VE.getTypeID(Type::getVoidTy(N->getContext()))); + Record.push_back(0); + } + } + Stream.EmitRecord(bitc::METADATA_NODE, Record, 0); + Record.clear(); +} + +static void WriteModuleMetadata(const ValueEnumerator &VE, + BitstreamWriter &Stream) { + const ValueEnumerator::ValueList &Vals = VE.getMDValues(); + bool StartedMetadataBlock = false; + unsigned MDSAbbrev = 0; + SmallVector Record; + for (unsigned i = 0, e = Vals.size(); i != e; ++i) { + + if (const MDNode *N = dyn_cast(Vals[i].first)) { + if (!StartedMetadataBlock) { + Stream.EnterSubblock(bitc::METADATA_BLOCK_ID, 3); + StartedMetadataBlock = true; + } + WriteMDNode(N, VE, Stream, Record); + } else if (const MDString *MDS = dyn_cast(Vals[i].first)) { + if (!StartedMetadataBlock) { + Stream.EnterSubblock(bitc::METADATA_BLOCK_ID, 3); + + // Abbrev for METADATA_STRING. + BitCodeAbbrev *Abbv = new BitCodeAbbrev(); + Abbv->Add(BitCodeAbbrevOp(bitc::METADATA_STRING)); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 8)); + MDSAbbrev = Stream.EmitAbbrev(Abbv); + StartedMetadataBlock = true; + } + + // Code: [strchar x N] + Record.append(MDS->begin(), MDS->end()); + + // Emit the finished record. + Stream.EmitRecord(bitc::METADATA_STRING, Record, MDSAbbrev); + Record.clear(); + } else if (const NamedMDNode *NMD = dyn_cast(Vals[i].first)) { + if (!StartedMetadataBlock) { + Stream.EnterSubblock(bitc::METADATA_BLOCK_ID, 3); + StartedMetadataBlock = true; + } + + // Write name. + std::string Str = NMD->getNameStr(); + const char *StrBegin = Str.c_str(); + for (unsigned i = 0, e = Str.length(); i != e; ++i) + Record.push_back(StrBegin[i]); + Stream.EmitRecord(bitc::METADATA_NAME, Record, 0/*TODO*/); + Record.clear(); + + // Write named metadata elements. + for (unsigned i = 0, e = NMD->getNumElements(); i != e; ++i) { + if (NMD->getElement(i)) + Record.push_back(VE.getValueID(NMD->getElement(i))); + else + Record.push_back(0); + } + Stream.EmitRecord(bitc::METADATA_NAMED_NODE, Record, 0); + Record.clear(); + } + } + + if (StartedMetadataBlock) + Stream.ExitBlock(); +} + +static void WriteMetadataAttachment(const Function &F, + const ValueEnumerator &VE, + BitstreamWriter &Stream) { + bool StartedMetadataBlock = false; + SmallVector Record; + + // Write metadata attachments + // METADATA_ATTACHMENT - [m x [value, [n x [id, mdnode]]] + MetadataContext &TheMetadata = F.getContext().getMetadata(); + typedef SmallVector >, 2> MDMapTy; + MDMapTy MDs; + for (Function::const_iterator BB = F.begin(), E = F.end(); BB != E; ++BB) + for (BasicBlock::const_iterator I = BB->begin(), E = BB->end(); + I != E; ++I) { + MDs.clear(); + TheMetadata.getMDs(I, MDs); + bool RecordedInstruction = false; + for (MDMapTy::const_iterator PI = MDs.begin(), PE = MDs.end(); + PI != PE; ++PI) { + if (RecordedInstruction == false) { + Record.push_back(VE.getInstructionID(I)); + RecordedInstruction = true; + } + Record.push_back(PI->first); + Record.push_back(VE.getValueID(PI->second)); + } + if (!Record.empty()) { + if (!StartedMetadataBlock) { + Stream.EnterSubblock(bitc::METADATA_ATTACHMENT_ID, 3); + StartedMetadataBlock = true; + } + Stream.EmitRecord(bitc::METADATA_ATTACHMENT, Record, 0); + Record.clear(); + } + } + + if (StartedMetadataBlock) + Stream.ExitBlock(); +} + +static void WriteModuleMetadataStore(const Module *M, + const ValueEnumerator &VE, + BitstreamWriter &Stream) { + + bool StartedMetadataBlock = false; + SmallVector Record; + + // Write metadata kinds + // METADATA_KIND - [n x [id, name]] + MetadataContext &TheMetadata = M->getContext().getMetadata(); + SmallVector, 4> Names; + TheMetadata.getHandlerNames(Names); + for (SmallVector, 4>::iterator + I = Names.begin(), + E = Names.end(); I != E; ++I) { + Record.push_back(I->first); + StringRef KName = I->second; + for (unsigned i = 0, e = KName.size(); i != e; ++i) + Record.push_back(KName[i]); + if (!StartedMetadataBlock) { + Stream.EnterSubblock(bitc::METADATA_BLOCK_ID, 3); + StartedMetadataBlock = true; + } + Stream.EmitRecord(bitc::METADATA_KIND, Record, 0); + Record.clear(); + } + + if (StartedMetadataBlock) + Stream.ExitBlock(); +} + +static void WriteConstants(unsigned FirstVal, unsigned LastVal, + const ValueEnumerator &VE, + BitstreamWriter &Stream, bool isGlobal) { + if (FirstVal == LastVal) return; + + Stream.EnterSubblock(bitc::CONSTANTS_BLOCK_ID, 4); + + unsigned AggregateAbbrev = 0; + unsigned String8Abbrev = 0; + unsigned CString7Abbrev = 0; + unsigned CString6Abbrev = 0; + // If this is a constant pool for the module, emit module-specific abbrevs. + if (isGlobal) { + // Abbrev for CST_CODE_AGGREGATE. + BitCodeAbbrev *Abbv = new BitCodeAbbrev(); + Abbv->Add(BitCodeAbbrevOp(bitc::CST_CODE_AGGREGATE)); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, Log2_32_Ceil(LastVal+1))); + AggregateAbbrev = Stream.EmitAbbrev(Abbv); + + // Abbrev for CST_CODE_STRING. + Abbv = new BitCodeAbbrev(); + Abbv->Add(BitCodeAbbrevOp(bitc::CST_CODE_STRING)); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 8)); + String8Abbrev = Stream.EmitAbbrev(Abbv); + // Abbrev for CST_CODE_CSTRING. + Abbv = new BitCodeAbbrev(); + Abbv->Add(BitCodeAbbrevOp(bitc::CST_CODE_CSTRING)); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 7)); + CString7Abbrev = Stream.EmitAbbrev(Abbv); + // Abbrev for CST_CODE_CSTRING. + Abbv = new BitCodeAbbrev(); + Abbv->Add(BitCodeAbbrevOp(bitc::CST_CODE_CSTRING)); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Char6)); + CString6Abbrev = Stream.EmitAbbrev(Abbv); + } + + SmallVector Record; + + const ValueEnumerator::ValueList &Vals = VE.getValues(); + const Type *LastTy = 0; + for (unsigned i = FirstVal; i != LastVal; ++i) { + const Value *V = Vals[i].first; + // If we need to switch types, do so now. + if (V->getType() != LastTy) { + LastTy = V->getType(); + Record.push_back(VE.getTypeID(LastTy)); + Stream.EmitRecord(bitc::CST_CODE_SETTYPE, Record, + CONSTANTS_SETTYPE_ABBREV); + Record.clear(); + } + + if (const InlineAsm *IA = dyn_cast(V)) { + Record.push_back(unsigned(IA->hasSideEffects()) | + unsigned(IA->isAlignStack()) << 1); + + // Add the asm string. + const std::string &AsmStr = IA->getAsmString(); + Record.push_back(AsmStr.size()); + for (unsigned i = 0, e = AsmStr.size(); i != e; ++i) + Record.push_back(AsmStr[i]); + + // Add the constraint string. + const std::string &ConstraintStr = IA->getConstraintString(); + Record.push_back(ConstraintStr.size()); + for (unsigned i = 0, e = ConstraintStr.size(); i != e; ++i) + Record.push_back(ConstraintStr[i]); + Stream.EmitRecord(bitc::CST_CODE_INLINEASM, Record); + Record.clear(); + continue; + } + const Constant *C = cast(V); + unsigned Code = -1U; + unsigned AbbrevToUse = 0; + if (C->isNullValue()) { + Code = bitc::CST_CODE_NULL; + } else if (isa(C)) { + Code = bitc::CST_CODE_UNDEF; + } else if (const ConstantInt *IV = dyn_cast(C)) { + if (IV->getBitWidth() <= 64) { + int64_t V = IV->getSExtValue(); + if (V >= 0) + Record.push_back(V << 1); + else + Record.push_back((-V << 1) | 1); + Code = bitc::CST_CODE_INTEGER; + AbbrevToUse = CONSTANTS_INTEGER_ABBREV; + } else { // Wide integers, > 64 bits in size. + // We have an arbitrary precision integer value to write whose + // bit width is > 64. However, in canonical unsigned integer + // format it is likely that the high bits are going to be zero. + // So, we only write the number of active words. + unsigned NWords = IV->getValue().getActiveWords(); + const uint64_t *RawWords = IV->getValue().getRawData(); + for (unsigned i = 0; i != NWords; ++i) { + int64_t V = RawWords[i]; + if (V >= 0) + Record.push_back(V << 1); + else + Record.push_back((-V << 1) | 1); + } + Code = bitc::CST_CODE_WIDE_INTEGER; + } + } else if (const ConstantFP *CFP = dyn_cast(C)) { + Code = bitc::CST_CODE_FLOAT; + const Type *Ty = CFP->getType(); + if (Ty->isFloatTy() || Ty->isDoubleTy()) { + Record.push_back(CFP->getValueAPF().bitcastToAPInt().getZExtValue()); + } else if (Ty->isX86_FP80Ty()) { + // api needed to prevent premature destruction + // bits are not in the same order as a normal i80 APInt, compensate. + APInt api = CFP->getValueAPF().bitcastToAPInt(); + const uint64_t *p = api.getRawData(); + Record.push_back((p[1] << 48) | (p[0] >> 16)); + Record.push_back(p[0] & 0xffffLL); + } else if (Ty->isFP128Ty() || Ty->isPPC_FP128Ty()) { + APInt api = CFP->getValueAPF().bitcastToAPInt(); + const uint64_t *p = api.getRawData(); + Record.push_back(p[0]); + Record.push_back(p[1]); + } else { + assert (0 && "Unknown FP type!"); + } + } else if (isa(C) && cast(C)->isString()) { + const ConstantArray *CA = cast(C); + // Emit constant strings specially. + unsigned NumOps = CA->getNumOperands(); + // If this is a null-terminated string, use the denser CSTRING encoding. + if (CA->getOperand(NumOps-1)->isNullValue()) { + Code = bitc::CST_CODE_CSTRING; + --NumOps; // Don't encode the null, which isn't allowed by char6. + } else { + Code = bitc::CST_CODE_STRING; + AbbrevToUse = String8Abbrev; + } + bool isCStr7 = Code == bitc::CST_CODE_CSTRING; + bool isCStrChar6 = Code == bitc::CST_CODE_CSTRING; + for (unsigned i = 0; i != NumOps; ++i) { + unsigned char V = cast(CA->getOperand(i))->getZExtValue(); + Record.push_back(V); + isCStr7 &= (V & 128) == 0; + if (isCStrChar6) + isCStrChar6 = BitCodeAbbrevOp::isChar6(V); + } + + if (isCStrChar6) + AbbrevToUse = CString6Abbrev; + else if (isCStr7) + AbbrevToUse = CString7Abbrev; + } else if (isa(C) || isa(V) || + isa(V)) { + Code = bitc::CST_CODE_AGGREGATE; + for (unsigned i = 0, e = C->getNumOperands(); i != e; ++i) + Record.push_back(VE.getValueID(C->getOperand(i))); + AbbrevToUse = AggregateAbbrev; + } else if (const ConstantExpr *CE = dyn_cast(C)) { + switch (CE->getOpcode()) { + default: + if (Instruction::isCast(CE->getOpcode())) { + Code = bitc::CST_CODE_CE_CAST; + Record.push_back(GetEncodedCastOpcode(CE->getOpcode())); + Record.push_back(VE.getTypeID(C->getOperand(0)->getType())); + Record.push_back(VE.getValueID(C->getOperand(0))); + AbbrevToUse = CONSTANTS_CE_CAST_Abbrev; + } else { + assert(CE->getNumOperands() == 2 && "Unknown constant expr!"); + Code = bitc::CST_CODE_CE_BINOP; + Record.push_back(GetEncodedBinaryOpcode(CE->getOpcode())); + Record.push_back(VE.getValueID(C->getOperand(0))); + Record.push_back(VE.getValueID(C->getOperand(1))); + uint64_t Flags = GetOptimizationFlags(CE); + if (Flags != 0) + Record.push_back(Flags); + } + break; + case Instruction::GetElementPtr: + Code = bitc::CST_CODE_CE_GEP; + if (cast(C)->isInBounds()) + Code = bitc::CST_CODE_CE_INBOUNDS_GEP; + for (unsigned i = 0, e = CE->getNumOperands(); i != e; ++i) { + Record.push_back(VE.getTypeID(C->getOperand(i)->getType())); + Record.push_back(VE.getValueID(C->getOperand(i))); + } + break; + case Instruction::Select: + Code = bitc::CST_CODE_CE_SELECT; + Record.push_back(VE.getValueID(C->getOperand(0))); + Record.push_back(VE.getValueID(C->getOperand(1))); + Record.push_back(VE.getValueID(C->getOperand(2))); + break; + case Instruction::ExtractElement: + Code = bitc::CST_CODE_CE_EXTRACTELT; + Record.push_back(VE.getTypeID(C->getOperand(0)->getType())); + Record.push_back(VE.getValueID(C->getOperand(0))); + Record.push_back(VE.getValueID(C->getOperand(1))); + break; + case Instruction::InsertElement: + Code = bitc::CST_CODE_CE_INSERTELT; + Record.push_back(VE.getValueID(C->getOperand(0))); + Record.push_back(VE.getValueID(C->getOperand(1))); + Record.push_back(VE.getValueID(C->getOperand(2))); + break; + case Instruction::ShuffleVector: + // If the return type and argument types are the same, this is a + // standard shufflevector instruction. If the types are different, + // then the shuffle is widening or truncating the input vectors, and + // the argument type must also be encoded. + if (C->getType() == C->getOperand(0)->getType()) { + Code = bitc::CST_CODE_CE_SHUFFLEVEC; + } else { + Code = bitc::CST_CODE_CE_SHUFVEC_EX; + Record.push_back(VE.getTypeID(C->getOperand(0)->getType())); + } + Record.push_back(VE.getValueID(C->getOperand(0))); + Record.push_back(VE.getValueID(C->getOperand(1))); + Record.push_back(VE.getValueID(C->getOperand(2))); + break; + case Instruction::ICmp: + case Instruction::FCmp: + Code = bitc::CST_CODE_CE_CMP; + Record.push_back(VE.getTypeID(C->getOperand(0)->getType())); + Record.push_back(VE.getValueID(C->getOperand(0))); + Record.push_back(VE.getValueID(C->getOperand(1))); + Record.push_back(CE->getPredicate()); + break; + } + } else if (const BlockAddress *BA = dyn_cast(C)) { + assert(BA->getFunction() == BA->getBasicBlock()->getParent() && + "Malformed blockaddress"); + Code = bitc::CST_CODE_BLOCKADDRESS; + Record.push_back(VE.getTypeID(BA->getFunction()->getType())); + Record.push_back(VE.getValueID(BA->getFunction())); + Record.push_back(VE.getGlobalBasicBlockID(BA->getBasicBlock())); + } else { + llvm_unreachable("Unknown constant!"); + } + Stream.EmitRecord(Code, Record, AbbrevToUse); + Record.clear(); + } + + Stream.ExitBlock(); +} + +static void WriteModuleConstants(const ValueEnumerator &VE, + BitstreamWriter &Stream) { + const ValueEnumerator::ValueList &Vals = VE.getValues(); + + // Find the first constant to emit, which is the first non-globalvalue value. + // We know globalvalues have been emitted by WriteModuleInfo. + for (unsigned i = 0, e = Vals.size(); i != e; ++i) { + if (!isa(Vals[i].first)) { + WriteConstants(i, Vals.size(), VE, Stream, true); + return; + } + } +} + +/// PushValueAndType - The file has to encode both the value and type id for +/// many values, because we need to know what type to create for forward +/// references. However, most operands are not forward references, so this type +/// field is not needed. +/// +/// This function adds V's value ID to Vals. If the value ID is higher than the +/// instruction ID, then it is a forward reference, and it also includes the +/// type ID. +static bool PushValueAndType(const Value *V, unsigned InstID, + SmallVector &Vals, + ValueEnumerator &VE) { + unsigned ValID = VE.getValueID(V); + Vals.push_back(ValID); + if (ValID >= InstID) { + Vals.push_back(VE.getTypeID(V->getType())); + return true; + } + return false; +} + +/// WriteInstruction - Emit an instruction to the specified stream. +static void WriteInstruction(const Instruction &I, unsigned InstID, + ValueEnumerator &VE, BitstreamWriter &Stream, + SmallVector &Vals) { + unsigned Code = 0; + unsigned AbbrevToUse = 0; + VE.setInstructionID(&I); + switch (I.getOpcode()) { + default: + if (Instruction::isCast(I.getOpcode())) { + Code = bitc::FUNC_CODE_INST_CAST; + if (!PushValueAndType(I.getOperand(0), InstID, Vals, VE)) + AbbrevToUse = FUNCTION_INST_CAST_ABBREV; + Vals.push_back(VE.getTypeID(I.getType())); + Vals.push_back(GetEncodedCastOpcode(I.getOpcode())); + } else { + assert(isa(I) && "Unknown instruction!"); + Code = bitc::FUNC_CODE_INST_BINOP; + if (!PushValueAndType(I.getOperand(0), InstID, Vals, VE)) + AbbrevToUse = FUNCTION_INST_BINOP_ABBREV; + Vals.push_back(VE.getValueID(I.getOperand(1))); + Vals.push_back(GetEncodedBinaryOpcode(I.getOpcode())); + uint64_t Flags = GetOptimizationFlags(&I); + if (Flags != 0) { + if (AbbrevToUse == FUNCTION_INST_BINOP_ABBREV) + AbbrevToUse = FUNCTION_INST_BINOP_FLAGS_ABBREV; + Vals.push_back(Flags); + } + } + break; + + case Instruction::GetElementPtr: + Code = bitc::FUNC_CODE_INST_GEP; + if (cast(&I)->isInBounds()) + Code = bitc::FUNC_CODE_INST_INBOUNDS_GEP; + for (unsigned i = 0, e = I.getNumOperands(); i != e; ++i) + PushValueAndType(I.getOperand(i), InstID, Vals, VE); + break; + case Instruction::ExtractValue: { + Code = bitc::FUNC_CODE_INST_EXTRACTVAL; + PushValueAndType(I.getOperand(0), InstID, Vals, VE); + const ExtractValueInst *EVI = cast(&I); + for (const unsigned *i = EVI->idx_begin(), *e = EVI->idx_end(); i != e; ++i) + Vals.push_back(*i); + break; + } + case Instruction::InsertValue: { + Code = bitc::FUNC_CODE_INST_INSERTVAL; + PushValueAndType(I.getOperand(0), InstID, Vals, VE); + PushValueAndType(I.getOperand(1), InstID, Vals, VE); + const InsertValueInst *IVI = cast(&I); + for (const unsigned *i = IVI->idx_begin(), *e = IVI->idx_end(); i != e; ++i) + Vals.push_back(*i); + break; + } + case Instruction::Select: + Code = bitc::FUNC_CODE_INST_VSELECT; + PushValueAndType(I.getOperand(1), InstID, Vals, VE); + Vals.push_back(VE.getValueID(I.getOperand(2))); + PushValueAndType(I.getOperand(0), InstID, Vals, VE); + break; + case Instruction::ExtractElement: + Code = bitc::FUNC_CODE_INST_EXTRACTELT; + PushValueAndType(I.getOperand(0), InstID, Vals, VE); + Vals.push_back(VE.getValueID(I.getOperand(1))); + break; + case Instruction::InsertElement: + Code = bitc::FUNC_CODE_INST_INSERTELT; + PushValueAndType(I.getOperand(0), InstID, Vals, VE); + Vals.push_back(VE.getValueID(I.getOperand(1))); + Vals.push_back(VE.getValueID(I.getOperand(2))); + break; + case Instruction::ShuffleVector: + Code = bitc::FUNC_CODE_INST_SHUFFLEVEC; + PushValueAndType(I.getOperand(0), InstID, Vals, VE); + Vals.push_back(VE.getValueID(I.getOperand(1))); + Vals.push_back(VE.getValueID(I.getOperand(2))); + break; + case Instruction::ICmp: + case Instruction::FCmp: + // compare returning Int1Ty or vector of Int1Ty + Code = bitc::FUNC_CODE_INST_CMP2; + PushValueAndType(I.getOperand(0), InstID, Vals, VE); + Vals.push_back(VE.getValueID(I.getOperand(1))); + Vals.push_back(cast(I).getPredicate()); + break; + + case Instruction::Ret: + { + Code = bitc::FUNC_CODE_INST_RET; + unsigned NumOperands = I.getNumOperands(); + if (NumOperands == 0) + AbbrevToUse = FUNCTION_INST_RET_VOID_ABBREV; + else if (NumOperands == 1) { + if (!PushValueAndType(I.getOperand(0), InstID, Vals, VE)) + AbbrevToUse = FUNCTION_INST_RET_VAL_ABBREV; + } else { + for (unsigned i = 0, e = NumOperands; i != e; ++i) + PushValueAndType(I.getOperand(i), InstID, Vals, VE); + } + } + break; + case Instruction::Br: + { + Code = bitc::FUNC_CODE_INST_BR; + BranchInst &II = cast(I); + Vals.push_back(VE.getValueID(II.getSuccessor(0))); + if (II.isConditional()) { + Vals.push_back(VE.getValueID(II.getSuccessor(1))); + Vals.push_back(VE.getValueID(II.getCondition())); + } + } + break; + case Instruction::Switch: + Code = bitc::FUNC_CODE_INST_SWITCH; + Vals.push_back(VE.getTypeID(I.getOperand(0)->getType())); + for (unsigned i = 0, e = I.getNumOperands(); i != e; ++i) + Vals.push_back(VE.getValueID(I.getOperand(i))); + break; + case Instruction::IndirectBr: + Code = bitc::FUNC_CODE_INST_INDIRECTBR; + Vals.push_back(VE.getTypeID(I.getOperand(0)->getType())); + for (unsigned i = 0, e = I.getNumOperands(); i != e; ++i) + Vals.push_back(VE.getValueID(I.getOperand(i))); + break; + + case Instruction::Invoke: { + const InvokeInst *II = cast(&I); + const Value *Callee(II->getCalledValue()); + const PointerType *PTy = cast(Callee->getType()); + const FunctionType *FTy = cast(PTy->getElementType()); + Code = bitc::FUNC_CODE_INST_INVOKE; + + Vals.push_back(VE.getAttributeID(II->getAttributes())); + Vals.push_back(II->getCallingConv()); + Vals.push_back(VE.getValueID(II->getNormalDest())); + Vals.push_back(VE.getValueID(II->getUnwindDest())); + PushValueAndType(Callee, InstID, Vals, VE); + + // Emit value #'s for the fixed parameters. + for (unsigned i = 0, e = FTy->getNumParams(); i != e; ++i) + Vals.push_back(VE.getValueID(I.getOperand(i+3))); // fixed param. + + // Emit type/value pairs for varargs params. + if (FTy->isVarArg()) { + for (unsigned i = 3+FTy->getNumParams(), e = I.getNumOperands(); + i != e; ++i) + PushValueAndType(I.getOperand(i), InstID, Vals, VE); // vararg + } + break; + } + case Instruction::Unwind: + Code = bitc::FUNC_CODE_INST_UNWIND; + break; + case Instruction::Unreachable: + Code = bitc::FUNC_CODE_INST_UNREACHABLE; + AbbrevToUse = FUNCTION_INST_UNREACHABLE_ABBREV; + break; + + case Instruction::PHI: + Code = bitc::FUNC_CODE_INST_PHI; + Vals.push_back(VE.getTypeID(I.getType())); + for (unsigned i = 0, e = I.getNumOperands(); i != e; ++i) + Vals.push_back(VE.getValueID(I.getOperand(i))); + break; + + case Instruction::Alloca: + Code = bitc::FUNC_CODE_INST_ALLOCA; + Vals.push_back(VE.getTypeID(I.getType())); + Vals.push_back(VE.getValueID(I.getOperand(0))); // size. + Vals.push_back(Log2_32(cast(I).getAlignment())+1); + break; + + case Instruction::Load: + Code = bitc::FUNC_CODE_INST_LOAD; + if (!PushValueAndType(I.getOperand(0), InstID, Vals, VE)) // ptr + AbbrevToUse = FUNCTION_INST_LOAD_ABBREV; + + Vals.push_back(Log2_32(cast(I).getAlignment())+1); + Vals.push_back(cast(I).isVolatile()); + break; + case Instruction::Store: + Code = bitc::FUNC_CODE_INST_STORE2; + PushValueAndType(I.getOperand(1), InstID, Vals, VE); // ptrty + ptr + Vals.push_back(VE.getValueID(I.getOperand(0))); // val. + Vals.push_back(Log2_32(cast(I).getAlignment())+1); + Vals.push_back(cast(I).isVolatile()); + break; + case Instruction::Call: { + const PointerType *PTy = cast(I.getOperand(0)->getType()); + const FunctionType *FTy = cast(PTy->getElementType()); + + Code = bitc::FUNC_CODE_INST_CALL; + + const CallInst *CI = cast(&I); + Vals.push_back(VE.getAttributeID(CI->getAttributes())); + Vals.push_back((CI->getCallingConv() << 1) | unsigned(CI->isTailCall())); + PushValueAndType(CI->getOperand(0), InstID, Vals, VE); // Callee + + // Emit value #'s for the fixed parameters. + for (unsigned i = 0, e = FTy->getNumParams(); i != e; ++i) + Vals.push_back(VE.getValueID(I.getOperand(i+1))); // fixed param. + + // Emit type/value pairs for varargs params. + if (FTy->isVarArg()) { + unsigned NumVarargs = I.getNumOperands()-1-FTy->getNumParams(); + for (unsigned i = I.getNumOperands()-NumVarargs, e = I.getNumOperands(); + i != e; ++i) + PushValueAndType(I.getOperand(i), InstID, Vals, VE); // varargs + } + break; + } + case Instruction::VAArg: + Code = bitc::FUNC_CODE_INST_VAARG; + Vals.push_back(VE.getTypeID(I.getOperand(0)->getType())); // valistty + Vals.push_back(VE.getValueID(I.getOperand(0))); // valist. + Vals.push_back(VE.getTypeID(I.getType())); // restype. + break; + } + + Stream.EmitRecord(Code, Vals, AbbrevToUse); + Vals.clear(); +} + +// Emit names for globals/functions etc. +static void WriteValueSymbolTable(const ValueSymbolTable &VST, + const ValueEnumerator &VE, + BitstreamWriter &Stream) { + if (VST.empty()) return; + Stream.EnterSubblock(bitc::VALUE_SYMTAB_BLOCK_ID, 4); + + // FIXME: Set up the abbrev, we know how many values there are! + // FIXME: We know if the type names can use 7-bit ascii. + SmallVector NameVals; + + for (ValueSymbolTable::const_iterator SI = VST.begin(), SE = VST.end(); + SI != SE; ++SI) { + + const ValueName &Name = *SI; + + // Figure out the encoding to use for the name. + bool is7Bit = true; + bool isChar6 = true; + for (const char *C = Name.getKeyData(), *E = C+Name.getKeyLength(); + C != E; ++C) { + if (isChar6) + isChar6 = BitCodeAbbrevOp::isChar6(*C); + if ((unsigned char)*C & 128) { + is7Bit = false; + break; // don't bother scanning the rest. + } + } + + unsigned AbbrevToUse = VST_ENTRY_8_ABBREV; + + // VST_ENTRY: [valueid, namechar x N] + // VST_BBENTRY: [bbid, namechar x N] + unsigned Code; + if (isa(SI->getValue())) { + Code = bitc::VST_CODE_BBENTRY; + if (isChar6) + AbbrevToUse = VST_BBENTRY_6_ABBREV; + } else { + Code = bitc::VST_CODE_ENTRY; + if (isChar6) + AbbrevToUse = VST_ENTRY_6_ABBREV; + else if (is7Bit) + AbbrevToUse = VST_ENTRY_7_ABBREV; + } + + NameVals.push_back(VE.getValueID(SI->getValue())); + for (const char *P = Name.getKeyData(), + *E = Name.getKeyData()+Name.getKeyLength(); P != E; ++P) + NameVals.push_back((unsigned char)*P); + + // Emit the finished record. + Stream.EmitRecord(Code, NameVals, AbbrevToUse); + NameVals.clear(); + } + Stream.ExitBlock(); +} + +/// WriteFunction - Emit a function body to the module stream. +static void WriteFunction(const Function &F, ValueEnumerator &VE, + BitstreamWriter &Stream) { + Stream.EnterSubblock(bitc::FUNCTION_BLOCK_ID, 4); + VE.incorporateFunction(F); + + SmallVector Vals; + + // Emit the number of basic blocks, so the reader can create them ahead of + // time. + Vals.push_back(VE.getBasicBlocks().size()); + Stream.EmitRecord(bitc::FUNC_CODE_DECLAREBLOCKS, Vals); + Vals.clear(); + + // If there are function-local constants, emit them now. + unsigned CstStart, CstEnd; + VE.getFunctionConstantRange(CstStart, CstEnd); + WriteConstants(CstStart, CstEnd, VE, Stream, false); + + // Keep a running idea of what the instruction ID is. + unsigned InstID = CstEnd; + + // Finally, emit all the instructions, in order. + for (Function::const_iterator BB = F.begin(), E = F.end(); BB != E; ++BB) + for (BasicBlock::const_iterator I = BB->begin(), E = BB->end(); + I != E; ++I) { + WriteInstruction(*I, InstID, VE, Stream, Vals); + if (I->getType() != Type::getVoidTy(F.getContext())) + ++InstID; + } + + // Emit names for all the instructions etc. + WriteValueSymbolTable(F.getValueSymbolTable(), VE, Stream); + + WriteMetadataAttachment(F, VE, Stream); + VE.purgeFunction(); + Stream.ExitBlock(); +} + +/// WriteTypeSymbolTable - Emit a block for the specified type symtab. +static void WriteTypeSymbolTable(const TypeSymbolTable &TST, + const ValueEnumerator &VE, + BitstreamWriter &Stream) { + if (TST.empty()) return; + + Stream.EnterSubblock(bitc::TYPE_SYMTAB_BLOCK_ID, 3); + + // 7-bit fixed width VST_CODE_ENTRY strings. + BitCodeAbbrev *Abbv = new BitCodeAbbrev(); + Abbv->Add(BitCodeAbbrevOp(bitc::VST_CODE_ENTRY)); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, + Log2_32_Ceil(VE.getTypes().size()+1))); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 7)); + unsigned V7Abbrev = Stream.EmitAbbrev(Abbv); + + SmallVector NameVals; + + for (TypeSymbolTable::const_iterator TI = TST.begin(), TE = TST.end(); + TI != TE; ++TI) { + // TST_ENTRY: [typeid, namechar x N] + NameVals.push_back(VE.getTypeID(TI->second)); + + const std::string &Str = TI->first; + bool is7Bit = true; + for (unsigned i = 0, e = Str.size(); i != e; ++i) { + NameVals.push_back((unsigned char)Str[i]); + if (Str[i] & 128) + is7Bit = false; + } + + // Emit the finished record. + Stream.EmitRecord(bitc::VST_CODE_ENTRY, NameVals, is7Bit ? V7Abbrev : 0); + NameVals.clear(); + } + + Stream.ExitBlock(); +} + +// Emit blockinfo, which defines the standard abbreviations etc. +static void WriteBlockInfo(const ValueEnumerator &VE, BitstreamWriter &Stream) { + // We only want to emit block info records for blocks that have multiple + // instances: CONSTANTS_BLOCK, FUNCTION_BLOCK and VALUE_SYMTAB_BLOCK. Other + // blocks can defined their abbrevs inline. + Stream.EnterBlockInfoBlock(2); + + { // 8-bit fixed-width VST_ENTRY/VST_BBENTRY strings. + BitCodeAbbrev *Abbv = new BitCodeAbbrev(); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 8)); + if (Stream.EmitBlockInfoAbbrev(bitc::VALUE_SYMTAB_BLOCK_ID, + Abbv) != VST_ENTRY_8_ABBREV) + llvm_unreachable("Unexpected abbrev ordering!"); + } + + { // 7-bit fixed width VST_ENTRY strings. + BitCodeAbbrev *Abbv = new BitCodeAbbrev(); + Abbv->Add(BitCodeAbbrevOp(bitc::VST_CODE_ENTRY)); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 7)); + if (Stream.EmitBlockInfoAbbrev(bitc::VALUE_SYMTAB_BLOCK_ID, + Abbv) != VST_ENTRY_7_ABBREV) + llvm_unreachable("Unexpected abbrev ordering!"); + } + { // 6-bit char6 VST_ENTRY strings. + BitCodeAbbrev *Abbv = new BitCodeAbbrev(); + Abbv->Add(BitCodeAbbrevOp(bitc::VST_CODE_ENTRY)); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Char6)); + if (Stream.EmitBlockInfoAbbrev(bitc::VALUE_SYMTAB_BLOCK_ID, + Abbv) != VST_ENTRY_6_ABBREV) + llvm_unreachable("Unexpected abbrev ordering!"); + } + { // 6-bit char6 VST_BBENTRY strings. + BitCodeAbbrev *Abbv = new BitCodeAbbrev(); + Abbv->Add(BitCodeAbbrevOp(bitc::VST_CODE_BBENTRY)); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Char6)); + if (Stream.EmitBlockInfoAbbrev(bitc::VALUE_SYMTAB_BLOCK_ID, + Abbv) != VST_BBENTRY_6_ABBREV) + llvm_unreachable("Unexpected abbrev ordering!"); + } + + + + { // SETTYPE abbrev for CONSTANTS_BLOCK. + BitCodeAbbrev *Abbv = new BitCodeAbbrev(); + Abbv->Add(BitCodeAbbrevOp(bitc::CST_CODE_SETTYPE)); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, + Log2_32_Ceil(VE.getTypes().size()+1))); + if (Stream.EmitBlockInfoAbbrev(bitc::CONSTANTS_BLOCK_ID, + Abbv) != CONSTANTS_SETTYPE_ABBREV) + llvm_unreachable("Unexpected abbrev ordering!"); + } + + { // INTEGER abbrev for CONSTANTS_BLOCK. + BitCodeAbbrev *Abbv = new BitCodeAbbrev(); + Abbv->Add(BitCodeAbbrevOp(bitc::CST_CODE_INTEGER)); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); + if (Stream.EmitBlockInfoAbbrev(bitc::CONSTANTS_BLOCK_ID, + Abbv) != CONSTANTS_INTEGER_ABBREV) + llvm_unreachable("Unexpected abbrev ordering!"); + } + + { // CE_CAST abbrev for CONSTANTS_BLOCK. + BitCodeAbbrev *Abbv = new BitCodeAbbrev(); + Abbv->Add(BitCodeAbbrevOp(bitc::CST_CODE_CE_CAST)); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 4)); // cast opc + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, // typeid + Log2_32_Ceil(VE.getTypes().size()+1))); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // value id + + if (Stream.EmitBlockInfoAbbrev(bitc::CONSTANTS_BLOCK_ID, + Abbv) != CONSTANTS_CE_CAST_Abbrev) + llvm_unreachable("Unexpected abbrev ordering!"); + } + { // NULL abbrev for CONSTANTS_BLOCK. + BitCodeAbbrev *Abbv = new BitCodeAbbrev(); + Abbv->Add(BitCodeAbbrevOp(bitc::CST_CODE_NULL)); + if (Stream.EmitBlockInfoAbbrev(bitc::CONSTANTS_BLOCK_ID, + Abbv) != CONSTANTS_NULL_Abbrev) + llvm_unreachable("Unexpected abbrev ordering!"); + } + + // FIXME: This should only use space for first class types! + + { // INST_LOAD abbrev for FUNCTION_BLOCK. + BitCodeAbbrev *Abbv = new BitCodeAbbrev(); + Abbv->Add(BitCodeAbbrevOp(bitc::FUNC_CODE_INST_LOAD)); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Ptr + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 4)); // Align + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // volatile + if (Stream.EmitBlockInfoAbbrev(bitc::FUNCTION_BLOCK_ID, + Abbv) != FUNCTION_INST_LOAD_ABBREV) + llvm_unreachable("Unexpected abbrev ordering!"); + } + { // INST_BINOP abbrev for FUNCTION_BLOCK. + BitCodeAbbrev *Abbv = new BitCodeAbbrev(); + Abbv->Add(BitCodeAbbrevOp(bitc::FUNC_CODE_INST_BINOP)); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // LHS + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // RHS + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 4)); // opc + if (Stream.EmitBlockInfoAbbrev(bitc::FUNCTION_BLOCK_ID, + Abbv) != FUNCTION_INST_BINOP_ABBREV) + llvm_unreachable("Unexpected abbrev ordering!"); + } + { // INST_BINOP_FLAGS abbrev for FUNCTION_BLOCK. + BitCodeAbbrev *Abbv = new BitCodeAbbrev(); + Abbv->Add(BitCodeAbbrevOp(bitc::FUNC_CODE_INST_BINOP)); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // LHS + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // RHS + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 4)); // opc + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 7)); // flags + if (Stream.EmitBlockInfoAbbrev(bitc::FUNCTION_BLOCK_ID, + Abbv) != FUNCTION_INST_BINOP_FLAGS_ABBREV) + llvm_unreachable("Unexpected abbrev ordering!"); + } + { // INST_CAST abbrev for FUNCTION_BLOCK. + BitCodeAbbrev *Abbv = new BitCodeAbbrev(); + Abbv->Add(BitCodeAbbrevOp(bitc::FUNC_CODE_INST_CAST)); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // OpVal + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, // dest ty + Log2_32_Ceil(VE.getTypes().size()+1))); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 4)); // opc + if (Stream.EmitBlockInfoAbbrev(bitc::FUNCTION_BLOCK_ID, + Abbv) != FUNCTION_INST_CAST_ABBREV) + llvm_unreachable("Unexpected abbrev ordering!"); + } + + { // INST_RET abbrev for FUNCTION_BLOCK. + BitCodeAbbrev *Abbv = new BitCodeAbbrev(); + Abbv->Add(BitCodeAbbrevOp(bitc::FUNC_CODE_INST_RET)); + if (Stream.EmitBlockInfoAbbrev(bitc::FUNCTION_BLOCK_ID, + Abbv) != FUNCTION_INST_RET_VOID_ABBREV) + llvm_unreachable("Unexpected abbrev ordering!"); + } + { // INST_RET abbrev for FUNCTION_BLOCK. + BitCodeAbbrev *Abbv = new BitCodeAbbrev(); + Abbv->Add(BitCodeAbbrevOp(bitc::FUNC_CODE_INST_RET)); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // ValID + if (Stream.EmitBlockInfoAbbrev(bitc::FUNCTION_BLOCK_ID, + Abbv) != FUNCTION_INST_RET_VAL_ABBREV) + llvm_unreachable("Unexpected abbrev ordering!"); + } + { // INST_UNREACHABLE abbrev for FUNCTION_BLOCK. + BitCodeAbbrev *Abbv = new BitCodeAbbrev(); + Abbv->Add(BitCodeAbbrevOp(bitc::FUNC_CODE_INST_UNREACHABLE)); + if (Stream.EmitBlockInfoAbbrev(bitc::FUNCTION_BLOCK_ID, + Abbv) != FUNCTION_INST_UNREACHABLE_ABBREV) + llvm_unreachable("Unexpected abbrev ordering!"); + } + + Stream.ExitBlock(); +} + + +/// WriteModule - Emit the specified module to the bitstream. +static void WriteModule(const Module *M, BitstreamWriter &Stream) { + Stream.EnterSubblock(bitc::MODULE_BLOCK_ID, 3); + + // Emit the version number if it is non-zero. + if (CurVersion) { + SmallVector Vals; + Vals.push_back(CurVersion); + Stream.EmitRecord(bitc::MODULE_CODE_VERSION, Vals); + } + + // Analyze the module, enumerating globals, functions, etc. + ValueEnumerator VE(M); + + // Emit blockinfo, which defines the standard abbreviations etc. + WriteBlockInfo(VE, Stream); + + // Emit information about parameter attributes. + WriteAttributeTable(VE, Stream); + + // Emit information describing all of the types in the module. + WriteTypeTable(VE, Stream); + + // Emit top-level description of module, including target triple, inline asm, + // descriptors for global variables, and function prototype info. + WriteModuleInfo(M, VE, Stream); + + // Emit constants. + WriteModuleConstants(VE, Stream); + + // Emit metadata. + WriteModuleMetadata(VE, Stream); + + // Emit function bodies. + for (Module::const_iterator I = M->begin(), E = M->end(); I != E; ++I) + if (!I->isDeclaration()) + WriteFunction(*I, VE, Stream); + + // Emit metadata. + WriteModuleMetadataStore(M, VE, Stream); + + // Emit the type symbol table information. + WriteTypeSymbolTable(M->getTypeSymbolTable(), VE, Stream); + + // Emit names for globals/functions etc. + WriteValueSymbolTable(M->getValueSymbolTable(), VE, Stream); + + Stream.ExitBlock(); +} + +/// EmitDarwinBCHeader - If generating a bc file on darwin, we have to emit a +/// header and trailer to make it compatible with the system archiver. To do +/// this we emit the following header, and then emit a trailer that pads the +/// file out to be a multiple of 16 bytes. +/// +/// struct bc_header { +/// uint32_t Magic; // 0x0B17C0DE +/// uint32_t Version; // Version, currently always 0. +/// uint32_t BitcodeOffset; // Offset to traditional bitcode file. +/// uint32_t BitcodeSize; // Size of traditional bitcode file. +/// uint32_t CPUType; // CPU specifier. +/// ... potentially more later ... +/// }; +enum { + DarwinBCSizeFieldOffset = 3*4, // Offset to bitcode_size. + DarwinBCHeaderSize = 5*4 +}; + +static void EmitDarwinBCHeader(BitstreamWriter &Stream, + const std::string &TT) { + unsigned CPUType = ~0U; + + // Match x86_64-*, i[3-9]86-*, powerpc-*, powerpc64-*. The CPUType is a + // magic number from /usr/include/mach/machine.h. It is ok to reproduce the + // specific constants here because they are implicitly part of the Darwin ABI. + enum { + DARWIN_CPU_ARCH_ABI64 = 0x01000000, + DARWIN_CPU_TYPE_X86 = 7, + DARWIN_CPU_TYPE_POWERPC = 18 + }; + + if (TT.find("x86_64-") == 0) + CPUType = DARWIN_CPU_TYPE_X86 | DARWIN_CPU_ARCH_ABI64; + else if (TT.size() >= 5 && TT[0] == 'i' && TT[2] == '8' && TT[3] == '6' && + TT[4] == '-' && TT[1] - '3' < 6) + CPUType = DARWIN_CPU_TYPE_X86; + else if (TT.find("powerpc-") == 0) + CPUType = DARWIN_CPU_TYPE_POWERPC; + else if (TT.find("powerpc64-") == 0) + CPUType = DARWIN_CPU_TYPE_POWERPC | DARWIN_CPU_ARCH_ABI64; + + // Traditional Bitcode starts after header. + unsigned BCOffset = DarwinBCHeaderSize; + + Stream.Emit(0x0B17C0DE, 32); + Stream.Emit(0 , 32); // Version. + Stream.Emit(BCOffset , 32); + Stream.Emit(0 , 32); // Filled in later. + Stream.Emit(CPUType , 32); +} + +/// EmitDarwinBCTrailer - Emit the darwin epilog after the bitcode file and +/// finalize the header. +static void EmitDarwinBCTrailer(BitstreamWriter &Stream, unsigned BufferSize) { + // Update the size field in the header. + Stream.BackpatchWord(DarwinBCSizeFieldOffset, BufferSize-DarwinBCHeaderSize); + + // If the file is not a multiple of 16 bytes, insert dummy padding. + while (BufferSize & 15) { + Stream.Emit(0, 8); + ++BufferSize; + } +} + + +/// WriteBitcodeToFile - Write the specified module to the specified output +/// stream. +void llvm::WriteBitcodeToFile(const Module *M, raw_ostream &Out) { + std::vector Buffer; + BitstreamWriter Stream(Buffer); + + Buffer.reserve(256*1024); + + WriteBitcodeToStream( M, Stream ); + + // If writing to stdout, set binary mode. + if (&llvm::outs() == &Out) + sys::Program::ChangeStdoutToBinary(); + + // Write the generated bitstream to "Out". + Out.write((char*)&Buffer.front(), Buffer.size()); + + // Make sure it hits disk now. + Out.flush(); +} + +/// WriteBitcodeToStream - Write the specified module to the specified output +/// stream. +void llvm::WriteBitcodeToStream(const Module *M, BitstreamWriter &Stream) { + // If this is darwin, emit a file header and trailer if needed. + bool isDarwin = M->getTargetTriple().find("-darwin") != std::string::npos; + if (isDarwin) + EmitDarwinBCHeader(Stream, M->getTargetTriple()); + + // Emit the file header. + Stream.Emit((unsigned)'B', 8); + Stream.Emit((unsigned)'C', 8); + Stream.Emit(0x0, 4); + Stream.Emit(0xC, 4); + Stream.Emit(0xE, 4); + Stream.Emit(0xD, 4); + + // Emit the module. + WriteModule(M, Stream); + + if (isDarwin) + EmitDarwinBCTrailer(Stream, Stream.getBuffer().size()); +} diff --git a/libclamav/c++/llvm/lib/Bitcode/Writer/BitcodeWriterPass.cpp b/libclamav/c++/llvm/lib/Bitcode/Writer/BitcodeWriterPass.cpp new file mode 100644 index 000000000..3a0d3ce0b --- /dev/null +++ b/libclamav/c++/llvm/lib/Bitcode/Writer/BitcodeWriterPass.cpp @@ -0,0 +1,41 @@ +//===--- Bitcode/Writer/BitcodeWriterPass.cpp - Bitcode Writer ------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// BitcodeWriterPass implementation. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Bitcode/ReaderWriter.h" +#include "llvm/Pass.h" +using namespace llvm; + +namespace { + class WriteBitcodePass : public ModulePass { + raw_ostream &OS; // raw_ostream to print on + public: + static char ID; // Pass identification, replacement for typeid + explicit WriteBitcodePass(raw_ostream &o) + : ModulePass(&ID), OS(o) {} + + const char *getPassName() const { return "Bitcode Writer"; } + + bool runOnModule(Module &M) { + WriteBitcodeToFile(&M, OS); + return false; + } + }; +} + +char WriteBitcodePass::ID = 0; + +/// createBitcodeWriterPass - Create and return a pass that writes the module +/// to the specified ostream. +ModulePass *llvm::createBitcodeWriterPass(raw_ostream &Str) { + return new WriteBitcodePass(Str); +} diff --git a/libclamav/c++/llvm/lib/Bitcode/Writer/CMakeLists.txt b/libclamav/c++/llvm/lib/Bitcode/Writer/CMakeLists.txt new file mode 100644 index 000000000..ac5bb991a --- /dev/null +++ b/libclamav/c++/llvm/lib/Bitcode/Writer/CMakeLists.txt @@ -0,0 +1,9 @@ +add_llvm_library(LLVMBitWriter + BitWriter.cpp + BitcodeWriter.cpp + BitcodeWriterPass.cpp + Serialize.cpp + SerializeAPFloat.cpp + SerializeAPInt.cpp + ValueEnumerator.cpp + ) diff --git a/libclamav/c++/llvm/lib/Bitcode/Writer/Makefile b/libclamav/c++/llvm/lib/Bitcode/Writer/Makefile new file mode 100644 index 000000000..7b0bd7215 --- /dev/null +++ b/libclamav/c++/llvm/lib/Bitcode/Writer/Makefile @@ -0,0 +1,15 @@ +##===- lib/Bitcode/Reader/Makefile -------------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LEVEL = ../../.. +LIBRARYNAME = LLVMBitWriter +BUILD_ARCHIVE = 1 + +include $(LEVEL)/Makefile.common + diff --git a/libclamav/c++/llvm/lib/Bitcode/Writer/Serialize.cpp b/libclamav/c++/llvm/lib/Bitcode/Writer/Serialize.cpp new file mode 100644 index 000000000..a6beb1789 --- /dev/null +++ b/libclamav/c++/llvm/lib/Bitcode/Writer/Serialize.cpp @@ -0,0 +1,115 @@ +//==- Serialize.cpp - Generic Object Serialization to Bitcode ----*- 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 the internal methods used for object serialization. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Bitcode/Serialize.h" +#include "llvm/Support/raw_ostream.h" +#include + +using namespace llvm; + +Serializer::Serializer(BitstreamWriter& stream) + : Stream(stream), BlockLevel(0) {} + +Serializer::~Serializer() { + if (inRecord()) + EmitRecord(); + + while (BlockLevel > 0) + Stream.ExitBlock(); + + Stream.FlushToWord(); +} + +void Serializer::EmitRecord() { + assert(Record.size() > 0 && "Cannot emit empty record."); + Stream.EmitRecord(8,Record); + Record.clear(); +} + +void Serializer::EnterBlock(unsigned BlockID,unsigned CodeLen) { + FlushRecord(); + Stream.EnterSubblock(BlockID,CodeLen); + ++BlockLevel; +} + +void Serializer::ExitBlock() { + assert (BlockLevel > 0); + --BlockLevel; + FlushRecord(); + Stream.ExitBlock(); +} + +void Serializer::EmitInt(uint64_t X) { + assert (BlockLevel > 0); + Record.push_back(X); +} + +void Serializer::EmitSInt(int64_t X) { + if (X >= 0) + EmitInt(X << 1); + else + EmitInt((-X << 1) | 1); +} + +void Serializer::EmitCStr(const char* s, const char* end) { + Record.push_back(end - s); + + while(s != end) { + Record.push_back(*s); + ++s; + } +} + +void Serializer::EmitCStr(const char* s) { + EmitCStr(s,s+strlen(s)); +} + +SerializedPtrID Serializer::getPtrId(const void* ptr) { + if (!ptr) + return 0; + + MapTy::iterator I = PtrMap.find(ptr); + + if (I == PtrMap.end()) { + unsigned id = PtrMap.size()+1; +#ifdef DEBUG_BACKPATCH + errs() << "Registered PTR: " << ptr << " => " << id << "\n"; +#endif + PtrMap[ptr] = id; + return id; + } + else return I->second; +} + +bool Serializer::isRegistered(const void* ptr) const { + MapTy::const_iterator I = PtrMap.find(ptr); + return I != PtrMap.end(); +} + + +#define INT_EMIT(TYPE)\ +void SerializeTrait::Emit(Serializer&S, TYPE X) { S.EmitInt(X); } + +INT_EMIT(bool) +INT_EMIT(unsigned char) +INT_EMIT(unsigned short) +INT_EMIT(unsigned int) +INT_EMIT(unsigned long) + +#define SINT_EMIT(TYPE)\ +void SerializeTrait::Emit(Serializer&S, TYPE X) { S.EmitSInt(X); } + +SINT_EMIT(signed char) +SINT_EMIT(signed short) +SINT_EMIT(signed int) +SINT_EMIT(signed long) diff --git a/libclamav/c++/llvm/lib/Bitcode/Writer/SerializeAPFloat.cpp b/libclamav/c++/llvm/lib/Bitcode/Writer/SerializeAPFloat.cpp new file mode 100644 index 000000000..25d954faa --- /dev/null +++ b/libclamav/c++/llvm/lib/Bitcode/Writer/SerializeAPFloat.cpp @@ -0,0 +1,21 @@ +//===-- SerializeAPInt.cpp - Serialization for APFloat ---------*- 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 serialization of APFloat. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/APFloat.h" +#include "llvm/Bitcode/Serialize.h" + +using namespace llvm; + +void APFloat::Emit(Serializer& S) const { + S.Emit(bitcastToAPInt()); +} diff --git a/libclamav/c++/llvm/lib/Bitcode/Writer/SerializeAPInt.cpp b/libclamav/c++/llvm/lib/Bitcode/Writer/SerializeAPInt.cpp new file mode 100644 index 000000000..47792c7d0 --- /dev/null +++ b/libclamav/c++/llvm/lib/Bitcode/Writer/SerializeAPInt.cpp @@ -0,0 +1,31 @@ +//===-- SerializeAPInt.cpp - Serialization for APInts ----------*- 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 serialization of APInts. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/APInt.h" +#include "llvm/Bitcode/Serialize.h" +#include + +using namespace llvm; + +void APInt::Emit(Serializer& S) const { + S.EmitInt(BitWidth); + + if (isSingleWord()) + S.EmitInt(VAL); + else { + uint32_t NumWords = getNumWords(); + S.EmitInt(NumWords); + for (unsigned i = 0; i < NumWords; ++i) + S.EmitInt(pVal[i]); + } +} diff --git a/libclamav/c++/llvm/lib/Bitcode/Writer/ValueEnumerator.cpp b/libclamav/c++/llvm/lib/Bitcode/Writer/ValueEnumerator.cpp new file mode 100644 index 000000000..d840d4ae9 --- /dev/null +++ b/libclamav/c++/llvm/lib/Bitcode/Writer/ValueEnumerator.cpp @@ -0,0 +1,427 @@ +//===-- ValueEnumerator.cpp - Number values and types for bitcode writer --===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the ValueEnumerator class. +// +//===----------------------------------------------------------------------===// + +#include "ValueEnumerator.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/LLVMContext.h" +#include "llvm/Metadata.h" +#include "llvm/Module.h" +#include "llvm/TypeSymbolTable.h" +#include "llvm/ValueSymbolTable.h" +#include "llvm/Instructions.h" +#include +using namespace llvm; + +static bool isSingleValueType(const std::pair &P) { + return P.first->isSingleValueType(); +} + +static bool isIntegerValue(const std::pair &V) { + return isa(V.first->getType()); +} + +static bool CompareByFrequency(const std::pair &P1, + const std::pair &P2) { + return P1.second > P2.second; +} + +/// ValueEnumerator - Enumerate module-level information. +ValueEnumerator::ValueEnumerator(const Module *M) { + InstructionCount = 0; + + // Enumerate the global variables. + for (Module::const_global_iterator I = M->global_begin(), + E = M->global_end(); I != E; ++I) + EnumerateValue(I); + + // Enumerate the functions. + for (Module::const_iterator I = M->begin(), E = M->end(); I != E; ++I) { + EnumerateValue(I); + EnumerateAttributes(cast(I)->getAttributes()); + } + + // Enumerate the aliases. + for (Module::const_alias_iterator I = M->alias_begin(), E = M->alias_end(); + I != E; ++I) + EnumerateValue(I); + + // Remember what is the cutoff between globalvalue's and other constants. + unsigned FirstConstant = Values.size(); + + // Enumerate the global variable initializers. + for (Module::const_global_iterator I = M->global_begin(), + E = M->global_end(); I != E; ++I) + if (I->hasInitializer()) + EnumerateValue(I->getInitializer()); + + // Enumerate the aliasees. + for (Module::const_alias_iterator I = M->alias_begin(), E = M->alias_end(); + I != E; ++I) + EnumerateValue(I->getAliasee()); + + // Enumerate types used by the type symbol table. + EnumerateTypeSymbolTable(M->getTypeSymbolTable()); + + // Insert constants that are named at module level into the slot pool so that + // the module symbol table can refer to them... + EnumerateValueSymbolTable(M->getValueSymbolTable()); + + // Enumerate types used by function bodies and argument lists. + for (Module::const_iterator F = M->begin(), E = M->end(); F != E; ++F) { + + for (Function::const_arg_iterator I = F->arg_begin(), E = F->arg_end(); + I != E; ++I) + EnumerateType(I->getType()); + + MetadataContext &TheMetadata = F->getContext().getMetadata(); + typedef SmallVector >, 2> MDMapTy; + MDMapTy MDs; + for (Function::const_iterator BB = F->begin(), E = F->end(); BB != E; ++BB) + for (BasicBlock::const_iterator I = BB->begin(), E = BB->end(); I!=E;++I){ + for (User::const_op_iterator OI = I->op_begin(), E = I->op_end(); + OI != E; ++OI) + EnumerateOperandType(*OI); + EnumerateType(I->getType()); + if (const CallInst *CI = dyn_cast(I)) + EnumerateAttributes(CI->getAttributes()); + else if (const InvokeInst *II = dyn_cast(I)) + EnumerateAttributes(II->getAttributes()); + + // Enumerate metadata attached with this instruction. + MDs.clear(); + TheMetadata.getMDs(I, MDs); + for (MDMapTy::const_iterator MI = MDs.begin(), ME = MDs.end(); MI != ME; + ++MI) + EnumerateMetadata(MI->second); + } + } + + // Optimize constant ordering. + OptimizeConstants(FirstConstant, Values.size()); + + // Sort the type table by frequency so that most commonly used types are early + // in the table (have low bit-width). + std::stable_sort(Types.begin(), Types.end(), CompareByFrequency); + + // Partition the Type ID's so that the single-value types occur before the + // aggregate types. This allows the aggregate types to be dropped from the + // type table after parsing the global variable initializers. + std::partition(Types.begin(), Types.end(), isSingleValueType); + + // Now that we rearranged the type table, rebuild TypeMap. + for (unsigned i = 0, e = Types.size(); i != e; ++i) + TypeMap[Types[i].first] = i+1; +} + +unsigned ValueEnumerator::getInstructionID(const Instruction *Inst) const { + InstructionMapType::const_iterator I = InstructionMap.find(Inst); + assert (I != InstructionMap.end() && "Instruction is not mapped!"); + return I->second; +} + +void ValueEnumerator::setInstructionID(const Instruction *I) { + InstructionMap[I] = InstructionCount++; +} + +unsigned ValueEnumerator::getValueID(const Value *V) const { + if (isa(V)) { + ValueMapType::const_iterator I = MDValueMap.find(V); + assert(I != MDValueMap.end() && "Value not in slotcalculator!"); + return I->second-1; + } + + ValueMapType::const_iterator I = ValueMap.find(V); + assert(I != ValueMap.end() && "Value not in slotcalculator!"); + return I->second-1; +} + +// Optimize constant ordering. +namespace { + struct CstSortPredicate { + ValueEnumerator &VE; + explicit CstSortPredicate(ValueEnumerator &ve) : VE(ve) {} + bool operator()(const std::pair &LHS, + const std::pair &RHS) { + // Sort by plane. + if (LHS.first->getType() != RHS.first->getType()) + return VE.getTypeID(LHS.first->getType()) < + VE.getTypeID(RHS.first->getType()); + // Then by frequency. + return LHS.second > RHS.second; + } + }; +} + +/// OptimizeConstants - Reorder constant pool for denser encoding. +void ValueEnumerator::OptimizeConstants(unsigned CstStart, unsigned CstEnd) { + if (CstStart == CstEnd || CstStart+1 == CstEnd) return; + + CstSortPredicate P(*this); + std::stable_sort(Values.begin()+CstStart, Values.begin()+CstEnd, P); + + // Ensure that integer constants are at the start of the constant pool. This + // is important so that GEP structure indices come before gep constant exprs. + std::partition(Values.begin()+CstStart, Values.begin()+CstEnd, + isIntegerValue); + + // Rebuild the modified portion of ValueMap. + for (; CstStart != CstEnd; ++CstStart) + ValueMap[Values[CstStart].first] = CstStart+1; +} + + +/// EnumerateTypeSymbolTable - Insert all of the types in the specified symbol +/// table. +void ValueEnumerator::EnumerateTypeSymbolTable(const TypeSymbolTable &TST) { + for (TypeSymbolTable::const_iterator TI = TST.begin(), TE = TST.end(); + TI != TE; ++TI) + EnumerateType(TI->second); +} + +/// EnumerateValueSymbolTable - Insert all of the values in the specified symbol +/// table into the values table. +void ValueEnumerator::EnumerateValueSymbolTable(const ValueSymbolTable &VST) { + for (ValueSymbolTable::const_iterator VI = VST.begin(), VE = VST.end(); + VI != VE; ++VI) + EnumerateValue(VI->getValue()); +} + +void ValueEnumerator::EnumerateMetadata(const MetadataBase *MD) { + // Check to see if it's already in! + unsigned &MDValueID = MDValueMap[MD]; + if (MDValueID) { + // Increment use count. + MDValues[MDValueID-1].second++; + return; + } + + // Enumerate the type of this value. + EnumerateType(MD->getType()); + + if (const MDNode *N = dyn_cast(MD)) { + MDValues.push_back(std::make_pair(MD, 1U)); + MDValueMap[MD] = MDValues.size(); + MDValueID = MDValues.size(); + for (unsigned i = 0, e = N->getNumElements(); i != e; ++i) { + if (Value *V = N->getElement(i)) + EnumerateValue(V); + else + EnumerateType(Type::getVoidTy(MD->getContext())); + } + return; + } + + if (const NamedMDNode *N = dyn_cast(MD)) { + for(NamedMDNode::const_elem_iterator I = N->elem_begin(), + E = N->elem_end(); I != E; ++I) { + MetadataBase *M = *I; + EnumerateValue(M); + } + MDValues.push_back(std::make_pair(MD, 1U)); + MDValueMap[MD] = Values.size(); + return; + } + + // Add the value. + MDValues.push_back(std::make_pair(MD, 1U)); + MDValueID = MDValues.size(); +} + +void ValueEnumerator::EnumerateValue(const Value *V) { + assert(V->getType() != Type::getVoidTy(V->getContext()) && + "Can't insert void values!"); + if (const MetadataBase *MB = dyn_cast(V)) + return EnumerateMetadata(MB); + + // Check to see if it's already in! + unsigned &ValueID = ValueMap[V]; + if (ValueID) { + // Increment use count. + Values[ValueID-1].second++; + return; + } + + // Enumerate the type of this value. + EnumerateType(V->getType()); + + if (const Constant *C = dyn_cast(V)) { + if (isa(C)) { + // Initializers for globals are handled explicitly elsewhere. + } else if (isa(C) && cast(C)->isString()) { + // Do not enumerate the initializers for an array of simple characters. + // The initializers just polute the value table, and we emit the strings + // specially. + } else if (C->getNumOperands()) { + // If a constant has operands, enumerate them. This makes sure that if a + // constant has uses (for example an array of const ints), that they are + // inserted also. + + // We prefer to enumerate them with values before we enumerate the user + // itself. This makes it more likely that we can avoid forward references + // in the reader. We know that there can be no cycles in the constants + // graph that don't go through a global variable. + for (User::const_op_iterator I = C->op_begin(), E = C->op_end(); + I != E; ++I) + if (!isa(*I)) // Don't enumerate BB operand to BlockAddress. + EnumerateValue(*I); + + // Finally, add the value. Doing this could make the ValueID reference be + // dangling, don't reuse it. + Values.push_back(std::make_pair(V, 1U)); + ValueMap[V] = Values.size(); + return; + } + } + + // Add the value. + Values.push_back(std::make_pair(V, 1U)); + ValueID = Values.size(); +} + + +void ValueEnumerator::EnumerateType(const Type *Ty) { + unsigned &TypeID = TypeMap[Ty]; + + if (TypeID) { + // If we've already seen this type, just increase its occurrence count. + Types[TypeID-1].second++; + return; + } + + // First time we saw this type, add it. + Types.push_back(std::make_pair(Ty, 1U)); + TypeID = Types.size(); + + // Enumerate subtypes. + for (Type::subtype_iterator I = Ty->subtype_begin(), E = Ty->subtype_end(); + I != E; ++I) + EnumerateType(*I); +} + +// Enumerate the types for the specified value. If the value is a constant, +// walk through it, enumerating the types of the constant. +void ValueEnumerator::EnumerateOperandType(const Value *V) { + EnumerateType(V->getType()); + if (const Constant *C = dyn_cast(V)) { + // If this constant is already enumerated, ignore it, we know its type must + // be enumerated. + if (ValueMap.count(V)) return; + + // This constant may have operands, make sure to enumerate the types in + // them. + for (unsigned i = 0, e = C->getNumOperands(); i != e; ++i) { + const User *Op = C->getOperand(i); + + // Don't enumerate basic blocks here, this happens as operands to + // blockaddress. + if (isa(Op)) continue; + + EnumerateOperandType(cast(Op)); + } + + if (const MDNode *N = dyn_cast(V)) { + for (unsigned i = 0, e = N->getNumElements(); i != e; ++i) + if (Value *Elem = N->getElement(i)) + EnumerateOperandType(Elem); + } + } else if (isa(V) || isa(V)) + EnumerateValue(V); +} + +void ValueEnumerator::EnumerateAttributes(const AttrListPtr &PAL) { + if (PAL.isEmpty()) return; // null is always 0. + // Do a lookup. + unsigned &Entry = AttributeMap[PAL.getRawPointer()]; + if (Entry == 0) { + // Never saw this before, add it. + Attributes.push_back(PAL); + Entry = Attributes.size(); + } +} + + +void ValueEnumerator::incorporateFunction(const Function &F) { + NumModuleValues = Values.size(); + + // Adding function arguments to the value table. + for(Function::const_arg_iterator I = F.arg_begin(), E = F.arg_end(); + I != E; ++I) + EnumerateValue(I); + + FirstFuncConstantID = Values.size(); + + // Add all function-level constants to the value table. + for (Function::const_iterator BB = F.begin(), E = F.end(); BB != E; ++BB) { + for (BasicBlock::const_iterator I = BB->begin(), E = BB->end(); I!=E; ++I) + for (User::const_op_iterator OI = I->op_begin(), E = I->op_end(); + OI != E; ++OI) { + if ((isa(*OI) && !isa(*OI)) || + isa(*OI)) + EnumerateValue(*OI); + } + BasicBlocks.push_back(BB); + ValueMap[BB] = BasicBlocks.size(); + } + + // Optimize the constant layout. + OptimizeConstants(FirstFuncConstantID, Values.size()); + + // Add the function's parameter attributes so they are available for use in + // the function's instruction. + EnumerateAttributes(F.getAttributes()); + + FirstInstID = Values.size(); + + // Add all of the instructions. + for (Function::const_iterator BB = F.begin(), E = F.end(); BB != E; ++BB) { + for (BasicBlock::const_iterator I = BB->begin(), E = BB->end(); I!=E; ++I) { + if (I->getType() != Type::getVoidTy(F.getContext())) + EnumerateValue(I); + } + } +} + +void ValueEnumerator::purgeFunction() { + /// Remove purged values from the ValueMap. + for (unsigned i = NumModuleValues, e = Values.size(); i != e; ++i) + ValueMap.erase(Values[i].first); + for (unsigned i = 0, e = BasicBlocks.size(); i != e; ++i) + ValueMap.erase(BasicBlocks[i]); + + Values.resize(NumModuleValues); + BasicBlocks.clear(); +} + +static void IncorporateFunctionInfoGlobalBBIDs(const Function *F, + DenseMap &IDMap) { + unsigned Counter = 0; + for (Function::const_iterator BB = F->begin(), E = F->end(); BB != E; ++BB) + IDMap[BB] = ++Counter; +} + +/// getGlobalBasicBlockID - This returns the function-specific ID for the +/// specified basic block. This is relatively expensive information, so it +/// should only be used by rare constructs such as address-of-label. +unsigned ValueEnumerator::getGlobalBasicBlockID(const BasicBlock *BB) const { + unsigned &Idx = GlobalBasicBlockIDs[BB]; + if (Idx != 0) + return Idx-1; + + IncorporateFunctionInfoGlobalBBIDs(BB->getParent(), GlobalBasicBlockIDs); + return getGlobalBasicBlockID(BB); +} + diff --git a/libclamav/c++/llvm/lib/Bitcode/Writer/ValueEnumerator.h b/libclamav/c++/llvm/lib/Bitcode/Writer/ValueEnumerator.h new file mode 100644 index 000000000..3c83e3569 --- /dev/null +++ b/libclamav/c++/llvm/lib/Bitcode/Writer/ValueEnumerator.h @@ -0,0 +1,140 @@ +//===-- Bitcode/Writer/ValueEnumerator.h - Number values --------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This class gives values and types Unique ID's. +// +//===----------------------------------------------------------------------===// + +#ifndef VALUE_ENUMERATOR_H +#define VALUE_ENUMERATOR_H + +#include "llvm/ADT/DenseMap.h" +#include "llvm/Attributes.h" +#include + +namespace llvm { + +class Type; +class Value; +class Instruction; +class BasicBlock; +class Function; +class Module; +class MetadataBase; +class AttrListPtr; +class TypeSymbolTable; +class ValueSymbolTable; + +class ValueEnumerator { +public: + // For each type, we remember its Type* and occurrence frequency. + typedef std::vector > TypeList; + + // For each value, we remember its Value* and occurrence frequency. + typedef std::vector > ValueList; +private: + typedef DenseMap TypeMapType; + TypeMapType TypeMap; + TypeList Types; + + typedef DenseMap ValueMapType; + ValueMapType ValueMap; + ValueList Values; + ValueList MDValues; + ValueMapType MDValueMap; + + typedef DenseMap AttributeMapType; + AttributeMapType AttributeMap; + std::vector Attributes; + + /// GlobalBasicBlockIDs - This map memoizes the basic block ID's referenced by + /// the "getGlobalBasicBlockID" method. + mutable DenseMap GlobalBasicBlockIDs; + + typedef DenseMap InstructionMapType; + InstructionMapType InstructionMap; + unsigned InstructionCount; + + /// BasicBlocks - This contains all the basic blocks for the currently + /// incorporated function. Their reverse mapping is stored in ValueMap. + std::vector BasicBlocks; + + /// When a function is incorporated, this is the size of the Values list + /// before incorporation. + unsigned NumModuleValues; + unsigned FirstFuncConstantID; + unsigned FirstInstID; + + ValueEnumerator(const ValueEnumerator &); // DO NOT IMPLEMENT + void operator=(const ValueEnumerator &); // DO NOT IMPLEMENT +public: + ValueEnumerator(const Module *M); + + unsigned getValueID(const Value *V) const; + + unsigned getTypeID(const Type *T) const { + TypeMapType::const_iterator I = TypeMap.find(T); + assert(I != TypeMap.end() && "Type not in ValueEnumerator!"); + return I->second-1; + } + + unsigned getInstructionID(const Instruction *I) const; + void setInstructionID(const Instruction *I); + + unsigned getAttributeID(const AttrListPtr &PAL) const { + if (PAL.isEmpty()) return 0; // Null maps to zero. + AttributeMapType::const_iterator I = AttributeMap.find(PAL.getRawPointer()); + assert(I != AttributeMap.end() && "Attribute not in ValueEnumerator!"); + return I->second; + } + + /// getFunctionConstantRange - Return the range of values that corresponds to + /// function-local constants. + void getFunctionConstantRange(unsigned &Start, unsigned &End) const { + Start = FirstFuncConstantID; + End = FirstInstID; + } + + const ValueList &getValues() const { return Values; } + const ValueList &getMDValues() const { return MDValues; } + const TypeList &getTypes() const { return Types; } + const std::vector &getBasicBlocks() const { + return BasicBlocks; + } + const std::vector &getAttributes() const { + return Attributes; + } + + /// getGlobalBasicBlockID - This returns the function-specific ID for the + /// specified basic block. This is relatively expensive information, so it + /// should only be used by rare constructs such as address-of-label. + unsigned getGlobalBasicBlockID(const BasicBlock *BB) const; + + /// incorporateFunction/purgeFunction - If you'd like to deal with a function, + /// use these two methods to get its data into the ValueEnumerator! + /// + void incorporateFunction(const Function &F); + void purgeFunction(); + +private: + void OptimizeConstants(unsigned CstStart, unsigned CstEnd); + + void EnumerateMetadata(const MetadataBase *MD); + void EnumerateValue(const Value *V); + void EnumerateType(const Type *T); + void EnumerateOperandType(const Value *V); + void EnumerateAttributes(const AttrListPtr &PAL); + + void EnumerateTypeSymbolTable(const TypeSymbolTable &ST); + void EnumerateValueSymbolTable(const ValueSymbolTable &ST); +}; + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/lib/CodeGen/AggressiveAntiDepBreaker.cpp b/libclamav/c++/llvm/lib/CodeGen/AggressiveAntiDepBreaker.cpp new file mode 100644 index 000000000..8e3f8e770 --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/AggressiveAntiDepBreaker.cpp @@ -0,0 +1,926 @@ +//===----- AggressiveAntiDepBreaker.cpp - Anti-dep breaker -------- ---------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the AggressiveAntiDepBreaker class, which +// implements register anti-dependence breaking during post-RA +// scheduling. It attempts to break all anti-dependencies within a +// block. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "post-RA-sched" +#include "AggressiveAntiDepBreaker.h" +#include "llvm/CodeGen/MachineBasicBlock.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +// If DebugDiv > 0 then only break antidep with (ID % DebugDiv) == DebugMod +static cl::opt +DebugDiv("agg-antidep-debugdiv", + cl::desc("Debug control for aggressive anti-dep breaker"), + cl::init(0), cl::Hidden); +static cl::opt +DebugMod("agg-antidep-debugmod", + cl::desc("Debug control for aggressive anti-dep breaker"), + cl::init(0), cl::Hidden); + +AggressiveAntiDepState::AggressiveAntiDepState(MachineBasicBlock *BB) : + GroupNodes(TargetRegisterInfo::FirstVirtualRegister, 0) { + // Initialize all registers to be in their own group. Initially we + // assign the register to the same-indexed GroupNode. + for (unsigned i = 0; i < TargetRegisterInfo::FirstVirtualRegister; ++i) + GroupNodeIndices[i] = i; + + // Initialize the indices to indicate that no registers are live. + std::fill(KillIndices, array_endof(KillIndices), ~0u); + std::fill(DefIndices, array_endof(DefIndices), BB->size()); +} + +unsigned AggressiveAntiDepState::GetGroup(unsigned Reg) +{ + unsigned Node = GroupNodeIndices[Reg]; + while (GroupNodes[Node] != Node) + Node = GroupNodes[Node]; + + return Node; +} + +void AggressiveAntiDepState::GetGroupRegs( + unsigned Group, + std::vector &Regs, + std::multimap *RegRefs) +{ + for (unsigned Reg = 0; Reg != TargetRegisterInfo::FirstVirtualRegister; ++Reg) { + if ((GetGroup(Reg) == Group) && (RegRefs->count(Reg) > 0)) + Regs.push_back(Reg); + } +} + +unsigned AggressiveAntiDepState::UnionGroups(unsigned Reg1, unsigned Reg2) +{ + assert(GroupNodes[0] == 0 && "GroupNode 0 not parent!"); + assert(GroupNodeIndices[0] == 0 && "Reg 0 not in Group 0!"); + + // find group for each register + unsigned Group1 = GetGroup(Reg1); + unsigned Group2 = GetGroup(Reg2); + + // if either group is 0, then that must become the parent + unsigned Parent = (Group1 == 0) ? Group1 : Group2; + unsigned Other = (Parent == Group1) ? Group2 : Group1; + GroupNodes.at(Other) = Parent; + return Parent; +} + +unsigned AggressiveAntiDepState::LeaveGroup(unsigned Reg) +{ + // Create a new GroupNode for Reg. Reg's existing GroupNode must + // stay as is because there could be other GroupNodes referring to + // it. + unsigned idx = GroupNodes.size(); + GroupNodes.push_back(idx); + GroupNodeIndices[Reg] = idx; + return idx; +} + +bool AggressiveAntiDepState::IsLive(unsigned Reg) +{ + // KillIndex must be defined and DefIndex not defined for a register + // to be live. + return((KillIndices[Reg] != ~0u) && (DefIndices[Reg] == ~0u)); +} + + + +AggressiveAntiDepBreaker:: +AggressiveAntiDepBreaker(MachineFunction& MFi, + TargetSubtarget::RegClassVector& CriticalPathRCs) : + AntiDepBreaker(), MF(MFi), + MRI(MF.getRegInfo()), + TRI(MF.getTarget().getRegisterInfo()), + AllocatableSet(TRI->getAllocatableSet(MF)), + State(NULL) { + /* Collect a bitset of all registers that are only broken if they + are on the critical path. */ + for (unsigned i = 0, e = CriticalPathRCs.size(); i < e; ++i) { + BitVector CPSet = TRI->getAllocatableSet(MF, CriticalPathRCs[i]); + if (CriticalPathSet.none()) + CriticalPathSet = CPSet; + else + CriticalPathSet |= CPSet; + } + + DEBUG(errs() << "AntiDep Critical-Path Registers:"); + DEBUG(for (int r = CriticalPathSet.find_first(); r != -1; + r = CriticalPathSet.find_next(r)) + errs() << " " << TRI->getName(r)); + DEBUG(errs() << '\n'); +} + +AggressiveAntiDepBreaker::~AggressiveAntiDepBreaker() { + delete State; +} + +void AggressiveAntiDepBreaker::StartBlock(MachineBasicBlock *BB) { + assert(State == NULL); + State = new AggressiveAntiDepState(BB); + + bool IsReturnBlock = (!BB->empty() && BB->back().getDesc().isReturn()); + unsigned *KillIndices = State->GetKillIndices(); + unsigned *DefIndices = State->GetDefIndices(); + + // Determine the live-out physregs for this block. + if (IsReturnBlock) { + // In a return block, examine the function live-out regs. + for (MachineRegisterInfo::liveout_iterator I = MRI.liveout_begin(), + E = MRI.liveout_end(); I != E; ++I) { + unsigned Reg = *I; + State->UnionGroups(Reg, 0); + KillIndices[Reg] = BB->size(); + DefIndices[Reg] = ~0u; + // Repeat, for all aliases. + for (const unsigned *Alias = TRI->getAliasSet(Reg); *Alias; ++Alias) { + unsigned AliasReg = *Alias; + State->UnionGroups(AliasReg, 0); + KillIndices[AliasReg] = BB->size(); + DefIndices[AliasReg] = ~0u; + } + } + } else { + // In a non-return block, examine the live-in regs of all successors. + for (MachineBasicBlock::succ_iterator SI = BB->succ_begin(), + SE = BB->succ_end(); SI != SE; ++SI) + for (MachineBasicBlock::livein_iterator I = (*SI)->livein_begin(), + E = (*SI)->livein_end(); I != E; ++I) { + unsigned Reg = *I; + State->UnionGroups(Reg, 0); + KillIndices[Reg] = BB->size(); + DefIndices[Reg] = ~0u; + // Repeat, for all aliases. + for (const unsigned *Alias = TRI->getAliasSet(Reg); *Alias; ++Alias) { + unsigned AliasReg = *Alias; + State->UnionGroups(AliasReg, 0); + KillIndices[AliasReg] = BB->size(); + DefIndices[AliasReg] = ~0u; + } + } + } + + // Mark live-out callee-saved registers. In a return block this is + // all callee-saved registers. In non-return this is any + // callee-saved register that is not saved in the prolog. + const MachineFrameInfo *MFI = MF.getFrameInfo(); + BitVector Pristine = MFI->getPristineRegs(BB); + for (const unsigned *I = TRI->getCalleeSavedRegs(); *I; ++I) { + unsigned Reg = *I; + if (!IsReturnBlock && !Pristine.test(Reg)) continue; + State->UnionGroups(Reg, 0); + KillIndices[Reg] = BB->size(); + DefIndices[Reg] = ~0u; + // Repeat, for all aliases. + for (const unsigned *Alias = TRI->getAliasSet(Reg); *Alias; ++Alias) { + unsigned AliasReg = *Alias; + State->UnionGroups(AliasReg, 0); + KillIndices[AliasReg] = BB->size(); + DefIndices[AliasReg] = ~0u; + } + } +} + +void AggressiveAntiDepBreaker::FinishBlock() { + delete State; + State = NULL; +} + +void AggressiveAntiDepBreaker::Observe(MachineInstr *MI, unsigned Count, + unsigned InsertPosIndex) { + assert(Count < InsertPosIndex && "Instruction index out of expected range!"); + + std::set PassthruRegs; + GetPassthruRegs(MI, PassthruRegs); + PrescanInstruction(MI, Count, PassthruRegs); + ScanInstruction(MI, Count); + + DEBUG(errs() << "Observe: "); + DEBUG(MI->dump()); + DEBUG(errs() << "\tRegs:"); + + unsigned *DefIndices = State->GetDefIndices(); + for (unsigned Reg = 0; Reg != TargetRegisterInfo::FirstVirtualRegister; ++Reg) { + // If Reg is current live, then mark that it can't be renamed as + // we don't know the extent of its live-range anymore (now that it + // has been scheduled). If it is not live but was defined in the + // previous schedule region, then set its def index to the most + // conservative location (i.e. the beginning of the previous + // schedule region). + if (State->IsLive(Reg)) { + DEBUG(if (State->GetGroup(Reg) != 0) + errs() << " " << TRI->getName(Reg) << "=g" << + State->GetGroup(Reg) << "->g0(region live-out)"); + State->UnionGroups(Reg, 0); + } else if ((DefIndices[Reg] < InsertPosIndex) && (DefIndices[Reg] >= Count)) { + DefIndices[Reg] = Count; + } + } + DEBUG(errs() << '\n'); +} + +bool AggressiveAntiDepBreaker::IsImplicitDefUse(MachineInstr *MI, + MachineOperand& MO) +{ + if (!MO.isReg() || !MO.isImplicit()) + return false; + + unsigned Reg = MO.getReg(); + if (Reg == 0) + return false; + + MachineOperand *Op = NULL; + if (MO.isDef()) + Op = MI->findRegisterUseOperand(Reg, true); + else + Op = MI->findRegisterDefOperand(Reg); + + return((Op != NULL) && Op->isImplicit()); +} + +void AggressiveAntiDepBreaker::GetPassthruRegs(MachineInstr *MI, + std::set& PassthruRegs) { + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + MachineOperand &MO = MI->getOperand(i); + if (!MO.isReg()) continue; + if ((MO.isDef() && MI->isRegTiedToUseOperand(i)) || + IsImplicitDefUse(MI, MO)) { + const unsigned Reg = MO.getReg(); + PassthruRegs.insert(Reg); + for (const unsigned *Subreg = TRI->getSubRegisters(Reg); + *Subreg; ++Subreg) { + PassthruRegs.insert(*Subreg); + } + } + } +} + +/// AntiDepEdges - Return in Edges the anti- and output- dependencies +/// in SU that we want to consider for breaking. +static void AntiDepEdges(SUnit *SU, std::vector& Edges) { + SmallSet RegSet; + for (SUnit::pred_iterator P = SU->Preds.begin(), PE = SU->Preds.end(); + P != PE; ++P) { + if ((P->getKind() == SDep::Anti) || (P->getKind() == SDep::Output)) { + unsigned Reg = P->getReg(); + if (RegSet.count(Reg) == 0) { + Edges.push_back(&*P); + RegSet.insert(Reg); + } + } + } +} + +/// CriticalPathStep - Return the next SUnit after SU on the bottom-up +/// critical path. +static SUnit *CriticalPathStep(SUnit *SU) { + SDep *Next = 0; + unsigned NextDepth = 0; + // Find the predecessor edge with the greatest depth. + if (SU != 0) { + for (SUnit::pred_iterator P = SU->Preds.begin(), PE = SU->Preds.end(); + P != PE; ++P) { + SUnit *PredSU = P->getSUnit(); + unsigned PredLatency = P->getLatency(); + unsigned PredTotalLatency = PredSU->getDepth() + PredLatency; + // In the case of a latency tie, prefer an anti-dependency edge over + // other types of edges. + if (NextDepth < PredTotalLatency || + (NextDepth == PredTotalLatency && P->getKind() == SDep::Anti)) { + NextDepth = PredTotalLatency; + Next = &*P; + } + } + } + + return (Next) ? Next->getSUnit() : 0; +} + +void AggressiveAntiDepBreaker::HandleLastUse(unsigned Reg, unsigned KillIdx, + const char *tag, const char *header, + const char *footer) { + unsigned *KillIndices = State->GetKillIndices(); + unsigned *DefIndices = State->GetDefIndices(); + std::multimap& + RegRefs = State->GetRegRefs(); + + if (!State->IsLive(Reg)) { + KillIndices[Reg] = KillIdx; + DefIndices[Reg] = ~0u; + RegRefs.erase(Reg); + State->LeaveGroup(Reg); + DEBUG(if (header != NULL) { + errs() << header << TRI->getName(Reg); header = NULL; }); + DEBUG(errs() << "->g" << State->GetGroup(Reg) << tag); + } + // Repeat for subregisters. + for (const unsigned *Subreg = TRI->getSubRegisters(Reg); + *Subreg; ++Subreg) { + unsigned SubregReg = *Subreg; + if (!State->IsLive(SubregReg)) { + KillIndices[SubregReg] = KillIdx; + DefIndices[SubregReg] = ~0u; + RegRefs.erase(SubregReg); + State->LeaveGroup(SubregReg); + DEBUG(if (header != NULL) { + errs() << header << TRI->getName(Reg); header = NULL; }); + DEBUG(errs() << " " << TRI->getName(SubregReg) << "->g" << + State->GetGroup(SubregReg) << tag); + } + } + + DEBUG(if ((header == NULL) && (footer != NULL)) errs() << footer); +} + +void AggressiveAntiDepBreaker::PrescanInstruction(MachineInstr *MI, unsigned Count, + std::set& PassthruRegs) { + unsigned *DefIndices = State->GetDefIndices(); + std::multimap& + RegRefs = State->GetRegRefs(); + + // Handle dead defs by simulating a last-use of the register just + // after the def. A dead def can occur because the def is truely + // dead, or because only a subregister is live at the def. If we + // don't do this the dead def will be incorrectly merged into the + // previous def. + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + MachineOperand &MO = MI->getOperand(i); + if (!MO.isReg() || !MO.isDef()) continue; + unsigned Reg = MO.getReg(); + if (Reg == 0) continue; + + HandleLastUse(Reg, Count + 1, "", "\tDead Def: ", "\n"); + } + + DEBUG(errs() << "\tDef Groups:"); + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + MachineOperand &MO = MI->getOperand(i); + if (!MO.isReg() || !MO.isDef()) continue; + unsigned Reg = MO.getReg(); + if (Reg == 0) continue; + + DEBUG(errs() << " " << TRI->getName(Reg) << "=g" << State->GetGroup(Reg)); + + // If MI's defs have a special allocation requirement, don't allow + // any def registers to be changed. Also assume all registers + // defined in a call must not be changed (ABI). + if (MI->getDesc().isCall() || MI->getDesc().hasExtraDefRegAllocReq()) { + DEBUG(if (State->GetGroup(Reg) != 0) errs() << "->g0(alloc-req)"); + State->UnionGroups(Reg, 0); + } + + // Any aliased that are live at this point are completely or + // partially defined here, so group those aliases with Reg. + for (const unsigned *Alias = TRI->getAliasSet(Reg); *Alias; ++Alias) { + unsigned AliasReg = *Alias; + if (State->IsLive(AliasReg)) { + State->UnionGroups(Reg, AliasReg); + DEBUG(errs() << "->g" << State->GetGroup(Reg) << "(via " << + TRI->getName(AliasReg) << ")"); + } + } + + // Note register reference... + const TargetRegisterClass *RC = NULL; + if (i < MI->getDesc().getNumOperands()) + RC = MI->getDesc().OpInfo[i].getRegClass(TRI); + AggressiveAntiDepState::RegisterReference RR = { &MO, RC }; + RegRefs.insert(std::make_pair(Reg, RR)); + } + + DEBUG(errs() << '\n'); + + // Scan the register defs for this instruction and update + // live-ranges. + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + MachineOperand &MO = MI->getOperand(i); + if (!MO.isReg() || !MO.isDef()) continue; + unsigned Reg = MO.getReg(); + if (Reg == 0) continue; + // Ignore KILLs and passthru registers for liveness... + if ((MI->getOpcode() == TargetInstrInfo::KILL) || + (PassthruRegs.count(Reg) != 0)) + continue; + + // Update def for Reg and aliases. + DefIndices[Reg] = Count; + for (const unsigned *Alias = TRI->getAliasSet(Reg); + *Alias; ++Alias) { + unsigned AliasReg = *Alias; + DefIndices[AliasReg] = Count; + } + } +} + +void AggressiveAntiDepBreaker::ScanInstruction(MachineInstr *MI, + unsigned Count) { + DEBUG(errs() << "\tUse Groups:"); + std::multimap& + RegRefs = State->GetRegRefs(); + + // Scan the register uses for this instruction and update + // live-ranges, groups and RegRefs. + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + MachineOperand &MO = MI->getOperand(i); + if (!MO.isReg() || !MO.isUse()) continue; + unsigned Reg = MO.getReg(); + if (Reg == 0) continue; + + DEBUG(errs() << " " << TRI->getName(Reg) << "=g" << + State->GetGroup(Reg)); + + // It wasn't previously live but now it is, this is a kill. Forget + // the previous live-range information and start a new live-range + // for the register. + HandleLastUse(Reg, Count, "(last-use)"); + + // If MI's uses have special allocation requirement, don't allow + // any use registers to be changed. Also assume all registers + // used in a call must not be changed (ABI). + if (MI->getDesc().isCall() || MI->getDesc().hasExtraSrcRegAllocReq()) { + DEBUG(if (State->GetGroup(Reg) != 0) errs() << "->g0(alloc-req)"); + State->UnionGroups(Reg, 0); + } + + // Note register reference... + const TargetRegisterClass *RC = NULL; + if (i < MI->getDesc().getNumOperands()) + RC = MI->getDesc().OpInfo[i].getRegClass(TRI); + AggressiveAntiDepState::RegisterReference RR = { &MO, RC }; + RegRefs.insert(std::make_pair(Reg, RR)); + } + + DEBUG(errs() << '\n'); + + // Form a group of all defs and uses of a KILL instruction to ensure + // that all registers are renamed as a group. + if (MI->getOpcode() == TargetInstrInfo::KILL) { + DEBUG(errs() << "\tKill Group:"); + + unsigned FirstReg = 0; + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + MachineOperand &MO = MI->getOperand(i); + if (!MO.isReg()) continue; + unsigned Reg = MO.getReg(); + if (Reg == 0) continue; + + if (FirstReg != 0) { + DEBUG(errs() << "=" << TRI->getName(Reg)); + State->UnionGroups(FirstReg, Reg); + } else { + DEBUG(errs() << " " << TRI->getName(Reg)); + FirstReg = Reg; + } + } + + DEBUG(errs() << "->g" << State->GetGroup(FirstReg) << '\n'); + } +} + +BitVector AggressiveAntiDepBreaker::GetRenameRegisters(unsigned Reg) { + BitVector BV(TRI->getNumRegs(), false); + bool first = true; + + // Check all references that need rewriting for Reg. For each, use + // the corresponding register class to narrow the set of registers + // that are appropriate for renaming. + std::pair::iterator, + std::multimap::iterator> + Range = State->GetRegRefs().equal_range(Reg); + for (std::multimap::iterator + Q = Range.first, QE = Range.second; Q != QE; ++Q) { + const TargetRegisterClass *RC = Q->second.RC; + if (RC == NULL) continue; + + BitVector RCBV = TRI->getAllocatableSet(MF, RC); + if (first) { + BV |= RCBV; + first = false; + } else { + BV &= RCBV; + } + + DEBUG(errs() << " " << RC->getName()); + } + + return BV; +} + +bool AggressiveAntiDepBreaker::FindSuitableFreeRegisters( + unsigned AntiDepGroupIndex, + RenameOrderType& RenameOrder, + std::map &RenameMap) { + unsigned *KillIndices = State->GetKillIndices(); + unsigned *DefIndices = State->GetDefIndices(); + std::multimap& + RegRefs = State->GetRegRefs(); + + // Collect all referenced registers in the same group as + // AntiDepReg. These all need to be renamed together if we are to + // break the anti-dependence. + std::vector Regs; + State->GetGroupRegs(AntiDepGroupIndex, Regs, &RegRefs); + assert(Regs.size() > 0 && "Empty register group!"); + if (Regs.size() == 0) + return false; + + // Find the "superest" register in the group. At the same time, + // collect the BitVector of registers that can be used to rename + // each register. + DEBUG(errs() << "\tRename Candidates for Group g" << AntiDepGroupIndex << ":\n"); + std::map RenameRegisterMap; + unsigned SuperReg = 0; + for (unsigned i = 0, e = Regs.size(); i != e; ++i) { + unsigned Reg = Regs[i]; + if ((SuperReg == 0) || TRI->isSuperRegister(SuperReg, Reg)) + SuperReg = Reg; + + // If Reg has any references, then collect possible rename regs + if (RegRefs.count(Reg) > 0) { + DEBUG(errs() << "\t\t" << TRI->getName(Reg) << ":"); + + BitVector BV = GetRenameRegisters(Reg); + RenameRegisterMap.insert(std::pair(Reg, BV)); + + DEBUG(errs() << " ::"); + DEBUG(for (int r = BV.find_first(); r != -1; r = BV.find_next(r)) + errs() << " " << TRI->getName(r)); + DEBUG(errs() << "\n"); + } + } + + // All group registers should be a subreg of SuperReg. + for (unsigned i = 0, e = Regs.size(); i != e; ++i) { + unsigned Reg = Regs[i]; + if (Reg == SuperReg) continue; + bool IsSub = TRI->isSubRegister(SuperReg, Reg); + assert(IsSub && "Expecting group subregister"); + if (!IsSub) + return false; + } + +#ifndef NDEBUG + // If DebugDiv > 0 then only rename (renamecnt % DebugDiv) == DebugMod + if (DebugDiv > 0) { + static int renamecnt = 0; + if (renamecnt++ % DebugDiv != DebugMod) + return false; + + errs() << "*** Performing rename " << TRI->getName(SuperReg) << + " for debug ***\n"; + } +#endif + + // Check each possible rename register for SuperReg in round-robin + // order. If that register is available, and the corresponding + // registers are available for the other group subregisters, then we + // can use those registers to rename. + const TargetRegisterClass *SuperRC = + TRI->getPhysicalRegisterRegClass(SuperReg, MVT::Other); + + const TargetRegisterClass::iterator RB = SuperRC->allocation_order_begin(MF); + const TargetRegisterClass::iterator RE = SuperRC->allocation_order_end(MF); + if (RB == RE) { + DEBUG(errs() << "\tEmpty Super Regclass!!\n"); + return false; + } + + DEBUG(errs() << "\tFind Registers:"); + + if (RenameOrder.count(SuperRC) == 0) + RenameOrder.insert(RenameOrderType::value_type(SuperRC, RE)); + + const TargetRegisterClass::iterator OrigR = RenameOrder[SuperRC]; + const TargetRegisterClass::iterator EndR = ((OrigR == RE) ? RB : OrigR); + TargetRegisterClass::iterator R = OrigR; + do { + if (R == RB) R = RE; + --R; + const unsigned NewSuperReg = *R; + // Don't replace a register with itself. + if (NewSuperReg == SuperReg) continue; + + DEBUG(errs() << " [" << TRI->getName(NewSuperReg) << ':'); + RenameMap.clear(); + + // For each referenced group register (which must be a SuperReg or + // a subregister of SuperReg), find the corresponding subregister + // of NewSuperReg and make sure it is free to be renamed. + for (unsigned i = 0, e = Regs.size(); i != e; ++i) { + unsigned Reg = Regs[i]; + unsigned NewReg = 0; + if (Reg == SuperReg) { + NewReg = NewSuperReg; + } else { + unsigned NewSubRegIdx = TRI->getSubRegIndex(SuperReg, Reg); + if (NewSubRegIdx != 0) + NewReg = TRI->getSubReg(NewSuperReg, NewSubRegIdx); + } + + DEBUG(errs() << " " << TRI->getName(NewReg)); + + // Check if Reg can be renamed to NewReg. + BitVector BV = RenameRegisterMap[Reg]; + if (!BV.test(NewReg)) { + DEBUG(errs() << "(no rename)"); + goto next_super_reg; + } + + // If NewReg is dead and NewReg's most recent def is not before + // Regs's kill, it's safe to replace Reg with NewReg. We + // must also check all aliases of NewReg, because we can't define a + // register when any sub or super is already live. + if (State->IsLive(NewReg) || (KillIndices[Reg] > DefIndices[NewReg])) { + DEBUG(errs() << "(live)"); + goto next_super_reg; + } else { + bool found = false; + for (const unsigned *Alias = TRI->getAliasSet(NewReg); + *Alias; ++Alias) { + unsigned AliasReg = *Alias; + if (State->IsLive(AliasReg) || (KillIndices[Reg] > DefIndices[AliasReg])) { + DEBUG(errs() << "(alias " << TRI->getName(AliasReg) << " live)"); + found = true; + break; + } + } + if (found) + goto next_super_reg; + } + + // Record that 'Reg' can be renamed to 'NewReg'. + RenameMap.insert(std::pair(Reg, NewReg)); + } + + // If we fall-out here, then every register in the group can be + // renamed, as recorded in RenameMap. + RenameOrder.erase(SuperRC); + RenameOrder.insert(RenameOrderType::value_type(SuperRC, R)); + DEBUG(errs() << "]\n"); + return true; + + next_super_reg: + DEBUG(errs() << ']'); + } while (R != EndR); + + DEBUG(errs() << '\n'); + + // No registers are free and available! + return false; +} + +/// BreakAntiDependencies - Identifiy anti-dependencies within the +/// ScheduleDAG and break them by renaming registers. +/// +unsigned AggressiveAntiDepBreaker::BreakAntiDependencies( + std::vector& SUnits, + MachineBasicBlock::iterator& Begin, + MachineBasicBlock::iterator& End, + unsigned InsertPosIndex) { + unsigned *KillIndices = State->GetKillIndices(); + unsigned *DefIndices = State->GetDefIndices(); + std::multimap& + RegRefs = State->GetRegRefs(); + + // The code below assumes that there is at least one instruction, + // so just duck out immediately if the block is empty. + if (SUnits.empty()) return 0; + + // For each regclass the next register to use for renaming. + RenameOrderType RenameOrder; + + // ...need a map from MI to SUnit. + std::map MISUnitMap; + for (unsigned i = 0, e = SUnits.size(); i != e; ++i) { + SUnit *SU = &SUnits[i]; + MISUnitMap.insert(std::pair(SU->getInstr(), SU)); + } + + // Track progress along the critical path through the SUnit graph as + // we walk the instructions. This is needed for regclasses that only + // break critical-path anti-dependencies. + SUnit *CriticalPathSU = 0; + MachineInstr *CriticalPathMI = 0; + if (CriticalPathSet.any()) { + for (unsigned i = 0, e = SUnits.size(); i != e; ++i) { + SUnit *SU = &SUnits[i]; + if (!CriticalPathSU || + ((SU->getDepth() + SU->Latency) > + (CriticalPathSU->getDepth() + CriticalPathSU->Latency))) { + CriticalPathSU = SU; + } + } + + CriticalPathMI = CriticalPathSU->getInstr(); + } + +#ifndef NDEBUG + DEBUG(errs() << "\n===== Aggressive anti-dependency breaking\n"); + DEBUG(errs() << "Available regs:"); + for (unsigned Reg = 0; Reg < TRI->getNumRegs(); ++Reg) { + if (!State->IsLive(Reg)) + DEBUG(errs() << " " << TRI->getName(Reg)); + } + DEBUG(errs() << '\n'); +#endif + + // Attempt to break anti-dependence edges. Walk the instructions + // from the bottom up, tracking information about liveness as we go + // to help determine which registers are available. + unsigned Broken = 0; + unsigned Count = InsertPosIndex - 1; + for (MachineBasicBlock::iterator I = End, E = Begin; + I != E; --Count) { + MachineInstr *MI = --I; + + DEBUG(errs() << "Anti: "); + DEBUG(MI->dump()); + + std::set PassthruRegs; + GetPassthruRegs(MI, PassthruRegs); + + // Process the defs in MI... + PrescanInstruction(MI, Count, PassthruRegs); + + // The dependence edges that represent anti- and output- + // dependencies that are candidates for breaking. + std::vector Edges; + SUnit *PathSU = MISUnitMap[MI]; + AntiDepEdges(PathSU, Edges); + + // If MI is not on the critical path, then we don't rename + // registers in the CriticalPathSet. + BitVector *ExcludeRegs = NULL; + if (MI == CriticalPathMI) { + CriticalPathSU = CriticalPathStep(CriticalPathSU); + CriticalPathMI = (CriticalPathSU) ? CriticalPathSU->getInstr() : 0; + } else { + ExcludeRegs = &CriticalPathSet; + } + + // Ignore KILL instructions (they form a group in ScanInstruction + // but don't cause any anti-dependence breaking themselves) + if (MI->getOpcode() != TargetInstrInfo::KILL) { + // Attempt to break each anti-dependency... + for (unsigned i = 0, e = Edges.size(); i != e; ++i) { + SDep *Edge = Edges[i]; + SUnit *NextSU = Edge->getSUnit(); + + if ((Edge->getKind() != SDep::Anti) && + (Edge->getKind() != SDep::Output)) continue; + + unsigned AntiDepReg = Edge->getReg(); + DEBUG(errs() << "\tAntidep reg: " << TRI->getName(AntiDepReg)); + assert(AntiDepReg != 0 && "Anti-dependence on reg0?"); + + if (!AllocatableSet.test(AntiDepReg)) { + // Don't break anti-dependencies on non-allocatable registers. + DEBUG(errs() << " (non-allocatable)\n"); + continue; + } else if ((ExcludeRegs != NULL) && ExcludeRegs->test(AntiDepReg)) { + // Don't break anti-dependencies for critical path registers + // if not on the critical path + DEBUG(errs() << " (not critical-path)\n"); + continue; + } else if (PassthruRegs.count(AntiDepReg) != 0) { + // If the anti-dep register liveness "passes-thru", then + // don't try to change it. It will be changed along with + // the use if required to break an earlier antidep. + DEBUG(errs() << " (passthru)\n"); + continue; + } else { + // No anti-dep breaking for implicit deps + MachineOperand *AntiDepOp = MI->findRegisterDefOperand(AntiDepReg); + assert(AntiDepOp != NULL && "Can't find index for defined register operand"); + if ((AntiDepOp == NULL) || AntiDepOp->isImplicit()) { + DEBUG(errs() << " (implicit)\n"); + continue; + } + + // If the SUnit has other dependencies on the SUnit that + // it anti-depends on, don't bother breaking the + // anti-dependency since those edges would prevent such + // units from being scheduled past each other + // regardless. + // + // Also, if there are dependencies on other SUnits with the + // same register as the anti-dependency, don't attempt to + // break it. + for (SUnit::pred_iterator P = PathSU->Preds.begin(), + PE = PathSU->Preds.end(); P != PE; ++P) { + if (P->getSUnit() == NextSU ? + (P->getKind() != SDep::Anti || P->getReg() != AntiDepReg) : + (P->getKind() == SDep::Data && P->getReg() == AntiDepReg)) { + AntiDepReg = 0; + break; + } + } + for (SUnit::pred_iterator P = PathSU->Preds.begin(), + PE = PathSU->Preds.end(); P != PE; ++P) { + if ((P->getSUnit() == NextSU) && (P->getKind() != SDep::Anti) && + (P->getKind() != SDep::Output)) { + DEBUG(errs() << " (real dependency)\n"); + AntiDepReg = 0; + break; + } else if ((P->getSUnit() != NextSU) && + (P->getKind() == SDep::Data) && + (P->getReg() == AntiDepReg)) { + DEBUG(errs() << " (other dependency)\n"); + AntiDepReg = 0; + break; + } + } + + if (AntiDepReg == 0) continue; + } + + assert(AntiDepReg != 0); + if (AntiDepReg == 0) continue; + + // Determine AntiDepReg's register group. + const unsigned GroupIndex = State->GetGroup(AntiDepReg); + if (GroupIndex == 0) { + DEBUG(errs() << " (zero group)\n"); + continue; + } + + DEBUG(errs() << '\n'); + + // Look for a suitable register to use to break the anti-dependence. + std::map RenameMap; + if (FindSuitableFreeRegisters(GroupIndex, RenameOrder, RenameMap)) { + DEBUG(errs() << "\tBreaking anti-dependence edge on " + << TRI->getName(AntiDepReg) << ":"); + + // Handle each group register... + for (std::map::iterator + S = RenameMap.begin(), E = RenameMap.end(); S != E; ++S) { + unsigned CurrReg = S->first; + unsigned NewReg = S->second; + + DEBUG(errs() << " " << TRI->getName(CurrReg) << "->" << + TRI->getName(NewReg) << "(" << + RegRefs.count(CurrReg) << " refs)"); + + // Update the references to the old register CurrReg to + // refer to the new register NewReg. + std::pair::iterator, + std::multimap::iterator> + Range = RegRefs.equal_range(CurrReg); + for (std::multimap::iterator + Q = Range.first, QE = Range.second; Q != QE; ++Q) { + Q->second.Operand->setReg(NewReg); + } + + // We just went back in time and modified history; the + // liveness information for CurrReg is now inconsistent. Set + // the state as if it were dead. + State->UnionGroups(NewReg, 0); + RegRefs.erase(NewReg); + DefIndices[NewReg] = DefIndices[CurrReg]; + KillIndices[NewReg] = KillIndices[CurrReg]; + + State->UnionGroups(CurrReg, 0); + RegRefs.erase(CurrReg); + DefIndices[CurrReg] = KillIndices[CurrReg]; + KillIndices[CurrReg] = ~0u; + assert(((KillIndices[CurrReg] == ~0u) != + (DefIndices[CurrReg] == ~0u)) && + "Kill and Def maps aren't consistent for AntiDepReg!"); + } + + ++Broken; + DEBUG(errs() << '\n'); + } + } + } + + ScanInstruction(MI, Count); + } + + return Broken; +} diff --git a/libclamav/c++/llvm/lib/CodeGen/AggressiveAntiDepBreaker.h b/libclamav/c++/llvm/lib/CodeGen/AggressiveAntiDepBreaker.h new file mode 100644 index 000000000..8154d2dd5 --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/AggressiveAntiDepBreaker.h @@ -0,0 +1,177 @@ +//=- llvm/CodeGen/AggressiveAntiDepBreaker.h - Anti-Dep Support -*- 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 the AggressiveAntiDepBreaker class, which +// implements register anti-dependence breaking during post-RA +// scheduling. It attempts to break all anti-dependencies within a +// block. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_AGGRESSIVEANTIDEPBREAKER_H +#define LLVM_CODEGEN_AGGRESSIVEANTIDEPBREAKER_H + +#include "AntiDepBreaker.h" +#include "llvm/CodeGen/MachineBasicBlock.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/ScheduleDAG.h" +#include "llvm/Target/TargetSubtarget.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/ADT/BitVector.h" +#include "llvm/ADT/SmallSet.h" +#include + +namespace llvm { + /// Class AggressiveAntiDepState + /// Contains all the state necessary for anti-dep breaking. + class AggressiveAntiDepState { + public: + /// RegisterReference - Information about a register reference + /// within a liverange + typedef struct { + /// Operand - The registers operand + MachineOperand *Operand; + /// RC - The register class + const TargetRegisterClass *RC; + } RegisterReference; + + private: + /// GroupNodes - Implements a disjoint-union data structure to + /// form register groups. A node is represented by an index into + /// the vector. A node can "point to" itself to indicate that it + /// is the parent of a group, or point to another node to indicate + /// that it is a member of the same group as that node. + std::vector GroupNodes; + + /// GroupNodeIndices - For each register, the index of the GroupNode + /// currently representing the group that the register belongs to. + /// Register 0 is always represented by the 0 group, a group + /// composed of registers that are not eligible for anti-aliasing. + unsigned GroupNodeIndices[TargetRegisterInfo::FirstVirtualRegister]; + + /// RegRefs - Map registers to all their references within a live range. + std::multimap RegRefs; + + /// KillIndices - The index of the most recent kill (proceding bottom-up), + /// or ~0u if the register is not live. + unsigned KillIndices[TargetRegisterInfo::FirstVirtualRegister]; + + /// DefIndices - The index of the most recent complete def (proceding bottom + /// up), or ~0u if the register is live. + unsigned DefIndices[TargetRegisterInfo::FirstVirtualRegister]; + + public: + AggressiveAntiDepState(MachineBasicBlock *BB); + + /// GetKillIndices - Return the kill indices. + unsigned *GetKillIndices() { return KillIndices; } + + /// GetDefIndices - Return the define indices. + unsigned *GetDefIndices() { return DefIndices; } + + /// GetRegRefs - Return the RegRefs map. + std::multimap& GetRegRefs() { return RegRefs; } + + // GetGroup - Get the group for a register. The returned value is + // the index of the GroupNode representing the group. + unsigned GetGroup(unsigned Reg); + + // GetGroupRegs - Return a vector of the registers belonging to a + // group. If RegRefs is non-NULL then only included referenced registers. + void GetGroupRegs( + unsigned Group, + std::vector &Regs, + std::multimap *RegRefs); + + // UnionGroups - Union Reg1's and Reg2's groups to form a new + // group. Return the index of the GroupNode representing the + // group. + unsigned UnionGroups(unsigned Reg1, unsigned Reg2); + + // LeaveGroup - Remove a register from its current group and place + // it alone in its own group. Return the index of the GroupNode + // representing the registers new group. + unsigned LeaveGroup(unsigned Reg); + + /// IsLive - Return true if Reg is live + bool IsLive(unsigned Reg); + }; + + + /// Class AggressiveAntiDepBreaker + class AggressiveAntiDepBreaker : public AntiDepBreaker { + MachineFunction& MF; + MachineRegisterInfo &MRI; + const TargetRegisterInfo *TRI; + + /// AllocatableSet - The set of allocatable registers. + /// We'll be ignoring anti-dependencies on non-allocatable registers, + /// because they may not be safe to break. + const BitVector AllocatableSet; + + /// CriticalPathSet - The set of registers that should only be + /// renamed if they are on the critical path. + BitVector CriticalPathSet; + + /// State - The state used to identify and rename anti-dependence + /// registers. + AggressiveAntiDepState *State; + + public: + AggressiveAntiDepBreaker(MachineFunction& MFi, + TargetSubtarget::RegClassVector& CriticalPathRCs); + ~AggressiveAntiDepBreaker(); + + /// Start - Initialize anti-dep breaking for a new basic block. + void StartBlock(MachineBasicBlock *BB); + + /// BreakAntiDependencies - Identifiy anti-dependencies along the critical path + /// of the ScheduleDAG and break them by renaming registers. + /// + unsigned BreakAntiDependencies(std::vector& SUnits, + MachineBasicBlock::iterator& Begin, + MachineBasicBlock::iterator& End, + unsigned InsertPosIndex); + + /// Observe - Update liveness information to account for the current + /// instruction, which will not be scheduled. + /// + void Observe(MachineInstr *MI, unsigned Count, unsigned InsertPosIndex); + + /// Finish - Finish anti-dep breaking for a basic block. + void FinishBlock(); + + private: + typedef std::map RenameOrderType; + + /// IsImplicitDefUse - Return true if MO represents a register + /// that is both implicitly used and defined in MI + bool IsImplicitDefUse(MachineInstr *MI, MachineOperand& MO); + + /// GetPassthruRegs - If MI implicitly def/uses a register, then + /// return that register and all subregisters. + void GetPassthruRegs(MachineInstr *MI, std::set& PassthruRegs); + + void HandleLastUse(unsigned Reg, unsigned KillIdx, const char *tag, + const char *header =NULL, const char *footer =NULL); + + void PrescanInstruction(MachineInstr *MI, unsigned Count, + std::set& PassthruRegs); + void ScanInstruction(MachineInstr *MI, unsigned Count); + BitVector GetRenameRegisters(unsigned Reg); + bool FindSuitableFreeRegisters(unsigned AntiDepGroupIndex, + RenameOrderType& RenameOrder, + std::map &RenameMap); + }; +} + +#endif diff --git a/libclamav/c++/llvm/lib/CodeGen/AntiDepBreaker.h b/libclamav/c++/llvm/lib/CodeGen/AntiDepBreaker.h new file mode 100644 index 000000000..3ee30c6a1 --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/AntiDepBreaker.h @@ -0,0 +1,59 @@ +//=- llvm/CodeGen/AntiDepBreaker.h - Anti-Dependence Breaking -*- 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 the AntiDepBreaker class, which implements +// anti-dependence breaking heuristics for post-register-allocation scheduling. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_ANTIDEPBREAKER_H +#define LLVM_CODEGEN_ANTIDEPBREAKER_H + +#include "llvm/CodeGen/MachineBasicBlock.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/ScheduleDAG.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include + +namespace llvm { + +/// AntiDepBreaker - This class works into conjunction with the +/// post-RA scheduler to rename registers to break register +/// anti-dependencies. +class AntiDepBreaker { +public: + virtual ~AntiDepBreaker(); + + /// Start - Initialize anti-dep breaking for a new basic block. + virtual void StartBlock(MachineBasicBlock *BB) =0; + + /// BreakAntiDependencies - Identifiy anti-dependencies within a + /// basic-block region and break them by renaming registers. Return + /// the number of anti-dependencies broken. + /// + virtual unsigned BreakAntiDependencies(std::vector& SUnits, + MachineBasicBlock::iterator& Begin, + MachineBasicBlock::iterator& End, + unsigned InsertPosIndex) =0; + + /// Observe - Update liveness information to account for the current + /// instruction, which will not be scheduled. + /// + virtual void Observe(MachineInstr *MI, unsigned Count, + unsigned InsertPosIndex) =0; + + /// Finish - Finish anti-dep breaking for a basic block. + virtual void FinishBlock() =0; +}; + +} + +#endif diff --git a/libclamav/c++/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/libclamav/c++/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp new file mode 100644 index 000000000..993cdbfb7 --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -0,0 +1,1982 @@ +//===-- AsmPrinter.cpp - Common AsmPrinter code ---------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the AsmPrinter class. +// +//===----------------------------------------------------------------------===// + +#include "llvm/CodeGen/AsmPrinter.h" +#include "llvm/Assembly/Writer.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Constants.h" +#include "llvm/Module.h" +#include "llvm/CodeGen/GCMetadataPrinter.h" +#include "llvm/CodeGen/MachineConstantPool.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineJumpTableInfo.h" +#include "llvm/CodeGen/MachineLoopInfo.h" +#include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/CodeGen/DwarfWriter.h" +#include "llvm/Analysis/DebugInfo.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCInst.h" +#include "llvm/MC/MCSection.h" +#include "llvm/MC/MCStreamer.h" +#include "llvm/MC/MCSymbol.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/FormattedStream.h" +#include "llvm/Support/Mangler.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetLowering.h" +#include "llvm/Target/TargetLoweringObjectFile.h" +#include "llvm/Target/TargetOptions.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringExtras.h" +#include +using namespace llvm; + +static cl::opt +AsmVerbose("asm-verbose", cl::desc("Add comments to directives."), + cl::init(cl::BOU_UNSET)); + +char AsmPrinter::ID = 0; +AsmPrinter::AsmPrinter(formatted_raw_ostream &o, TargetMachine &tm, + const MCAsmInfo *T, bool VDef) + : MachineFunctionPass(&ID), FunctionNumber(0), O(o), + TM(tm), MAI(T), TRI(tm.getRegisterInfo()), + + OutContext(*new MCContext()), + // FIXME: Pass instprinter to streamer. + OutStreamer(*createAsmStreamer(OutContext, O, *T, 0)), + + LastMI(0), LastFn(0), Counter(~0U), + PrevDLT(0, 0, ~0U, ~0U) { + DW = 0; MMI = 0; + switch (AsmVerbose) { + case cl::BOU_UNSET: VerboseAsm = VDef; break; + case cl::BOU_TRUE: VerboseAsm = true; break; + case cl::BOU_FALSE: VerboseAsm = false; break; + } +} + +AsmPrinter::~AsmPrinter() { + for (gcp_iterator I = GCMetadataPrinters.begin(), + E = GCMetadataPrinters.end(); I != E; ++I) + delete I->second; + + delete &OutStreamer; + delete &OutContext; +} + +TargetLoweringObjectFile &AsmPrinter::getObjFileLowering() const { + return TM.getTargetLowering()->getObjFileLowering(); +} + +/// getCurrentSection() - Return the current section we are emitting to. +const MCSection *AsmPrinter::getCurrentSection() const { + return OutStreamer.getCurrentSection(); +} + + +void AsmPrinter::getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + MachineFunctionPass::getAnalysisUsage(AU); + AU.addRequired(); + if (VerboseAsm) + AU.addRequired(); +} + +bool AsmPrinter::doInitialization(Module &M) { + // Initialize TargetLoweringObjectFile. + const_cast(getObjFileLowering()) + .Initialize(OutContext, TM); + + Mang = new Mangler(M, MAI->getGlobalPrefix(), MAI->getPrivateGlobalPrefix(), + MAI->getLinkerPrivateGlobalPrefix()); + + if (MAI->doesAllowQuotesInName()) + Mang->setUseQuotes(true); + + if (MAI->doesAllowNameToStartWithDigit()) + Mang->setSymbolsCanStartWithDigit(true); + + // Allow the target to emit any magic that it wants at the start of the file. + EmitStartOfAsmFile(M); + + if (MAI->hasSingleParameterDotFile()) { + /* Very minimal debug info. It is ignored if we emit actual + debug info. If we don't, this at least helps the user find where + a function came from. */ + O << "\t.file\t\"" << M.getModuleIdentifier() << "\"\n"; + } + + GCModuleInfo *MI = getAnalysisIfAvailable(); + assert(MI && "AsmPrinter didn't require GCModuleInfo?"); + for (GCModuleInfo::iterator I = MI->begin(), E = MI->end(); I != E; ++I) + if (GCMetadataPrinter *MP = GetOrCreateGCPrinter(*I)) + MP->beginAssembly(O, *this, *MAI); + + if (!M.getModuleInlineAsm().empty()) + O << MAI->getCommentString() << " Start of file scope inline assembly\n" + << M.getModuleInlineAsm() + << '\n' << MAI->getCommentString() + << " End of file scope inline assembly\n"; + + MMI = getAnalysisIfAvailable(); + if (MMI) + MMI->AnalyzeModule(M); + DW = getAnalysisIfAvailable(); + if (DW) + DW->BeginModule(&M, MMI, O, this, MAI); + + return false; +} + +bool AsmPrinter::doFinalization(Module &M) { + // Emit global variables. + for (Module::const_global_iterator I = M.global_begin(), E = M.global_end(); + I != E; ++I) + PrintGlobalVariable(I); + + // Emit final debug information. + if (MAI->doesSupportDebugInformation() || MAI->doesSupportExceptionHandling()) + DW->EndModule(); + + // If the target wants to know about weak references, print them all. + if (MAI->getWeakRefDirective()) { + // FIXME: This is not lazy, it would be nice to only print weak references + // to stuff that is actually used. Note that doing so would require targets + // to notice uses in operands (due to constant exprs etc). This should + // happen with the MC stuff eventually. + + // Print out module-level global variables here. + for (Module::const_global_iterator I = M.global_begin(), E = M.global_end(); + I != E; ++I) { + if (I->hasExternalWeakLinkage()) + O << MAI->getWeakRefDirective() << Mang->getMangledName(I) << '\n'; + } + + for (Module::const_iterator I = M.begin(), E = M.end(); I != E; ++I) { + if (I->hasExternalWeakLinkage()) + O << MAI->getWeakRefDirective() << Mang->getMangledName(I) << '\n'; + } + } + + if (MAI->getSetDirective()) { + O << '\n'; + for (Module::const_alias_iterator I = M.alias_begin(), E = M.alias_end(); + I != E; ++I) { + std::string Name = Mang->getMangledName(I); + + const GlobalValue *GV = cast(I->getAliasedGlobal()); + std::string Target = Mang->getMangledName(GV); + + if (I->hasExternalLinkage() || !MAI->getWeakRefDirective()) + O << "\t.globl\t" << Name << '\n'; + else if (I->hasWeakLinkage()) + O << MAI->getWeakRefDirective() << Name << '\n'; + else if (!I->hasLocalLinkage()) + llvm_unreachable("Invalid alias linkage"); + + printVisibility(Name, I->getVisibility()); + + O << MAI->getSetDirective() << ' ' << Name << ", " << Target << '\n'; + } + } + + GCModuleInfo *MI = getAnalysisIfAvailable(); + assert(MI && "AsmPrinter didn't require GCModuleInfo?"); + for (GCModuleInfo::iterator I = MI->end(), E = MI->begin(); I != E; ) + if (GCMetadataPrinter *MP = GetOrCreateGCPrinter(*--I)) + MP->finishAssembly(O, *this, *MAI); + + // If we don't have any trampolines, then we don't require stack memory + // to be executable. Some targets have a directive to declare this. + Function *InitTrampolineIntrinsic = M.getFunction("llvm.init.trampoline"); + if (!InitTrampolineIntrinsic || InitTrampolineIntrinsic->use_empty()) + if (MAI->getNonexecutableStackDirective()) + O << MAI->getNonexecutableStackDirective() << '\n'; + + + // Allow the target to emit any magic that it wants at the end of the file, + // after everything else has gone out. + EmitEndOfAsmFile(M); + + delete Mang; Mang = 0; + DW = 0; MMI = 0; + + OutStreamer.Finish(); + return false; +} + +void AsmPrinter::SetupMachineFunction(MachineFunction &MF) { + // What's my mangled name? + CurrentFnName = Mang->getMangledName(MF.getFunction()); + IncrementFunctionNumber(); + + if (VerboseAsm) + LI = &getAnalysis(); +} + +namespace { + // SectionCPs - Keep track the alignment, constpool entries per Section. + struct SectionCPs { + const MCSection *S; + unsigned Alignment; + SmallVector CPEs; + SectionCPs(const MCSection *s, unsigned a) : S(s), Alignment(a) {}; + }; +} + +/// EmitConstantPool - Print to the current output stream assembly +/// representations of the constants in the constant pool MCP. This is +/// used to print out constants which have been "spilled to memory" by +/// the code generator. +/// +void AsmPrinter::EmitConstantPool(MachineConstantPool *MCP) { + const std::vector &CP = MCP->getConstants(); + if (CP.empty()) return; + + // Calculate sections for constant pool entries. We collect entries to go into + // the same section together to reduce amount of section switch statements. + SmallVector CPSections; + for (unsigned i = 0, e = CP.size(); i != e; ++i) { + const MachineConstantPoolEntry &CPE = CP[i]; + unsigned Align = CPE.getAlignment(); + + SectionKind Kind; + switch (CPE.getRelocationInfo()) { + default: llvm_unreachable("Unknown section kind"); + case 2: Kind = SectionKind::getReadOnlyWithRel(); break; + case 1: + Kind = SectionKind::getReadOnlyWithRelLocal(); + break; + case 0: + switch (TM.getTargetData()->getTypeAllocSize(CPE.getType())) { + case 4: Kind = SectionKind::getMergeableConst4(); break; + case 8: Kind = SectionKind::getMergeableConst8(); break; + case 16: Kind = SectionKind::getMergeableConst16();break; + default: Kind = SectionKind::getMergeableConst(); break; + } + } + + const MCSection *S = getObjFileLowering().getSectionForConstant(Kind); + + // The number of sections are small, just do a linear search from the + // last section to the first. + bool Found = false; + unsigned SecIdx = CPSections.size(); + while (SecIdx != 0) { + if (CPSections[--SecIdx].S == S) { + Found = true; + break; + } + } + if (!Found) { + SecIdx = CPSections.size(); + CPSections.push_back(SectionCPs(S, Align)); + } + + if (Align > CPSections[SecIdx].Alignment) + CPSections[SecIdx].Alignment = Align; + CPSections[SecIdx].CPEs.push_back(i); + } + + // Now print stuff into the calculated sections. + for (unsigned i = 0, e = CPSections.size(); i != e; ++i) { + OutStreamer.SwitchSection(CPSections[i].S); + EmitAlignment(Log2_32(CPSections[i].Alignment)); + + unsigned Offset = 0; + for (unsigned j = 0, ee = CPSections[i].CPEs.size(); j != ee; ++j) { + unsigned CPI = CPSections[i].CPEs[j]; + MachineConstantPoolEntry CPE = CP[CPI]; + + // Emit inter-object padding for alignment. + unsigned AlignMask = CPE.getAlignment() - 1; + unsigned NewOffset = (Offset + AlignMask) & ~AlignMask; + EmitZeros(NewOffset - Offset); + + const Type *Ty = CPE.getType(); + Offset = NewOffset + TM.getTargetData()->getTypeAllocSize(Ty); + + O << MAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << '_' + << CPI << ':'; + if (VerboseAsm) { + O.PadToColumn(MAI->getCommentColumn()); + O << MAI->getCommentString() << " constant "; + WriteTypeSymbolic(O, CPE.getType(), MF->getFunction()->getParent()); + } + O << '\n'; + if (CPE.isMachineConstantPoolEntry()) + EmitMachineConstantPoolValue(CPE.Val.MachineCPVal); + else + EmitGlobalConstant(CPE.Val.ConstVal); + } + } +} + +/// EmitJumpTableInfo - Print assembly representations of the jump tables used +/// by the current function to the current output stream. +/// +void AsmPrinter::EmitJumpTableInfo(MachineJumpTableInfo *MJTI, + MachineFunction &MF) { + const std::vector &JT = MJTI->getJumpTables(); + if (JT.empty()) return; + + bool IsPic = TM.getRelocationModel() == Reloc::PIC_; + + // Pick the directive to use to print the jump table entries, and switch to + // the appropriate section. + TargetLowering *LoweringInfo = TM.getTargetLowering(); + + const Function *F = MF.getFunction(); + bool JTInDiffSection = false; + if (F->isWeakForLinker() || + (IsPic && !LoweringInfo->usesGlobalOffsetTable())) { + // In PIC mode, we need to emit the jump table to the same section as the + // function body itself, otherwise the label differences won't make sense. + // We should also do if the section name is NULL or function is declared in + // discardable section. + OutStreamer.SwitchSection(getObjFileLowering().SectionForGlobal(F, Mang, + TM)); + } else { + // Otherwise, drop it in the readonly section. + const MCSection *ReadOnlySection = + getObjFileLowering().getSectionForConstant(SectionKind::getReadOnly()); + OutStreamer.SwitchSection(ReadOnlySection); + JTInDiffSection = true; + } + + EmitAlignment(Log2_32(MJTI->getAlignment())); + + for (unsigned i = 0, e = JT.size(); i != e; ++i) { + const std::vector &JTBBs = JT[i].MBBs; + + // If this jump table was deleted, ignore it. + if (JTBBs.empty()) continue; + + // For PIC codegen, if possible we want to use the SetDirective to reduce + // the number of relocations the assembler will generate for the jump table. + // Set directives are all printed before the jump table itself. + SmallPtrSet EmittedSets; + if (MAI->getSetDirective() && IsPic) + for (unsigned ii = 0, ee = JTBBs.size(); ii != ee; ++ii) + if (EmittedSets.insert(JTBBs[ii])) + printPICJumpTableSetLabel(i, JTBBs[ii]); + + // On some targets (e.g. Darwin) we want to emit two consequtive labels + // before each jump table. The first label is never referenced, but tells + // the assembler and linker the extents of the jump table object. The + // second label is actually referenced by the code. + if (JTInDiffSection && MAI->getLinkerPrivateGlobalPrefix()[0]) { + O << MAI->getLinkerPrivateGlobalPrefix() + << "JTI" << getFunctionNumber() << '_' << i << ":\n"; + } + + O << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() + << '_' << i << ":\n"; + + for (unsigned ii = 0, ee = JTBBs.size(); ii != ee; ++ii) { + printPICJumpTableEntry(MJTI, JTBBs[ii], i); + O << '\n'; + } + } +} + +void AsmPrinter::printPICJumpTableEntry(const MachineJumpTableInfo *MJTI, + const MachineBasicBlock *MBB, + unsigned uid) const { + bool isPIC = TM.getRelocationModel() == Reloc::PIC_; + + // Use JumpTableDirective otherwise honor the entry size from the jump table + // info. + const char *JTEntryDirective = MAI->getJumpTableDirective(isPIC); + bool HadJTEntryDirective = JTEntryDirective != NULL; + if (!HadJTEntryDirective) { + JTEntryDirective = MJTI->getEntrySize() == 4 ? + MAI->getData32bitsDirective() : MAI->getData64bitsDirective(); + } + + O << JTEntryDirective << ' '; + + // If we have emitted set directives for the jump table entries, print + // them rather than the entries themselves. If we're emitting PIC, then + // emit the table entries as differences between two text section labels. + // If we're emitting non-PIC code, then emit the entries as direct + // references to the target basic blocks. + if (!isPIC) { + GetMBBSymbol(MBB->getNumber())->print(O, MAI); + } else if (MAI->getSetDirective()) { + O << MAI->getPrivateGlobalPrefix() << getFunctionNumber() + << '_' << uid << "_set_" << MBB->getNumber(); + } else { + GetMBBSymbol(MBB->getNumber())->print(O, MAI); + // If the arch uses custom Jump Table directives, don't calc relative to + // JT + if (!HadJTEntryDirective) + O << '-' << MAI->getPrivateGlobalPrefix() << "JTI" + << getFunctionNumber() << '_' << uid; + } +} + + +/// EmitSpecialLLVMGlobal - Check to see if the specified global is a +/// special global used by LLVM. If so, emit it and return true, otherwise +/// do nothing and return false. +bool AsmPrinter::EmitSpecialLLVMGlobal(const GlobalVariable *GV) { + if (GV->getName() == "llvm.used") { + if (MAI->getUsedDirective() != 0) // No need to emit this at all. + EmitLLVMUsedList(GV->getInitializer()); + return true; + } + + // Ignore debug and non-emitted data. This handles llvm.compiler.used. + if (GV->getSection() == "llvm.metadata" || + GV->hasAvailableExternallyLinkage()) + return true; + + if (!GV->hasAppendingLinkage()) return false; + + assert(GV->hasInitializer() && "Not a special LLVM global!"); + + const TargetData *TD = TM.getTargetData(); + unsigned Align = Log2_32(TD->getPointerPrefAlignment()); + if (GV->getName() == "llvm.global_ctors") { + OutStreamer.SwitchSection(getObjFileLowering().getStaticCtorSection()); + EmitAlignment(Align, 0); + EmitXXStructorList(GV->getInitializer()); + return true; + } + + if (GV->getName() == "llvm.global_dtors") { + OutStreamer.SwitchSection(getObjFileLowering().getStaticDtorSection()); + EmitAlignment(Align, 0); + EmitXXStructorList(GV->getInitializer()); + return true; + } + + return false; +} + +/// EmitLLVMUsedList - For targets that define a MAI::UsedDirective, mark each +/// global in the specified llvm.used list for which emitUsedDirectiveFor +/// is true, as being used with this directive. +void AsmPrinter::EmitLLVMUsedList(Constant *List) { + const char *Directive = MAI->getUsedDirective(); + + // Should be an array of 'i8*'. + ConstantArray *InitList = dyn_cast(List); + if (InitList == 0) return; + + for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i) { + const GlobalValue *GV = + dyn_cast(InitList->getOperand(i)->stripPointerCasts()); + if (GV && getObjFileLowering().shouldEmitUsedDirectiveFor(GV, Mang)) { + O << Directive; + EmitConstantValueOnly(InitList->getOperand(i)); + O << '\n'; + } + } +} + +/// EmitXXStructorList - Emit the ctor or dtor list. This just prints out the +/// function pointers, ignoring the init priority. +void AsmPrinter::EmitXXStructorList(Constant *List) { + // Should be an array of '{ int, void ()* }' structs. The first value is the + // init priority, which we ignore. + if (!isa(List)) return; + ConstantArray *InitList = cast(List); + for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i) + if (ConstantStruct *CS = dyn_cast(InitList->getOperand(i))){ + if (CS->getNumOperands() != 2) return; // Not array of 2-element structs. + + if (CS->getOperand(1)->isNullValue()) + return; // Found a null terminator, exit printing. + // Emit the function pointer. + EmitGlobalConstant(CS->getOperand(1)); + } +} + + +//===----------------------------------------------------------------------===// +/// LEB 128 number encoding. + +/// PrintULEB128 - Print a series of hexadecimal values (separated by commas) +/// representing an unsigned leb128 value. +void AsmPrinter::PrintULEB128(unsigned Value) const { + char Buffer[20]; + do { + unsigned char Byte = static_cast(Value & 0x7f); + Value >>= 7; + if (Value) Byte |= 0x80; + O << "0x" << utohex_buffer(Byte, Buffer+20); + if (Value) O << ", "; + } while (Value); +} + +/// PrintSLEB128 - Print a series of hexadecimal values (separated by commas) +/// representing a signed leb128 value. +void AsmPrinter::PrintSLEB128(int Value) const { + int Sign = Value >> (8 * sizeof(Value) - 1); + bool IsMore; + char Buffer[20]; + + do { + unsigned char Byte = static_cast(Value & 0x7f); + Value >>= 7; + IsMore = Value != Sign || ((Byte ^ Sign) & 0x40) != 0; + if (IsMore) Byte |= 0x80; + O << "0x" << utohex_buffer(Byte, Buffer+20); + if (IsMore) O << ", "; + } while (IsMore); +} + +//===--------------------------------------------------------------------===// +// Emission and print routines +// + +/// PrintHex - Print a value as a hexadecimal value. +/// +void AsmPrinter::PrintHex(int Value) const { + char Buffer[20]; + O << "0x" << utohex_buffer(static_cast(Value), Buffer+20); +} + +/// EOL - Print a newline character to asm stream. If a comment is present +/// then it will be printed first. Comments should not contain '\n'. +void AsmPrinter::EOL() const { + O << '\n'; +} + +void AsmPrinter::EOL(const std::string &Comment) const { + if (VerboseAsm && !Comment.empty()) { + O.PadToColumn(MAI->getCommentColumn()); + O << MAI->getCommentString() + << ' ' + << Comment; + } + O << '\n'; +} + +void AsmPrinter::EOL(const char* Comment) const { + if (VerboseAsm && *Comment) { + O.PadToColumn(MAI->getCommentColumn()); + O << MAI->getCommentString() + << ' ' + << Comment; + } + O << '\n'; +} + +static const char *DecodeDWARFEncoding(unsigned Encoding) { + switch (Encoding) { + case dwarf::DW_EH_PE_absptr: + return "absptr"; + case dwarf::DW_EH_PE_omit: + return "omit"; + case dwarf::DW_EH_PE_pcrel: + return "pcrel"; + case dwarf::DW_EH_PE_udata4: + return "udata4"; + case dwarf::DW_EH_PE_udata8: + return "udata8"; + case dwarf::DW_EH_PE_sdata4: + return "sdata4"; + case dwarf::DW_EH_PE_sdata8: + return "sdata8"; + case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_udata4: + return "pcrel udata4"; + case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4: + return "pcrel sdata4"; + case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_udata8: + return "pcrel udata8"; + case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata8: + return "pcrel sdata8"; + case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |dwarf::DW_EH_PE_udata4: + return "indirect pcrel udata4"; + case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |dwarf::DW_EH_PE_sdata4: + return "indirect pcrel sdata4"; + case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |dwarf::DW_EH_PE_udata8: + return "indirect pcrel udata8"; + case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |dwarf::DW_EH_PE_sdata8: + return "indirect pcrel sdata8"; + } + + return 0; +} + +void AsmPrinter::EOL(const char *Comment, unsigned Encoding) const { + if (VerboseAsm && *Comment) { + O.PadToColumn(MAI->getCommentColumn()); + O << MAI->getCommentString() + << ' ' + << Comment; + + if (const char *EncStr = DecodeDWARFEncoding(Encoding)) + O << " (" << EncStr << ')'; + } + O << '\n'; +} + +/// EmitULEB128Bytes - Emit an assembler byte data directive to compose an +/// unsigned leb128 value. +void AsmPrinter::EmitULEB128Bytes(unsigned Value) const { + if (MAI->hasLEB128()) { + O << "\t.uleb128\t" + << Value; + } else { + O << MAI->getData8bitsDirective(); + PrintULEB128(Value); + } +} + +/// EmitSLEB128Bytes - print an assembler byte data directive to compose a +/// signed leb128 value. +void AsmPrinter::EmitSLEB128Bytes(int Value) const { + if (MAI->hasLEB128()) { + O << "\t.sleb128\t" + << Value; + } else { + O << MAI->getData8bitsDirective(); + PrintSLEB128(Value); + } +} + +/// EmitInt8 - Emit a byte directive and value. +/// +void AsmPrinter::EmitInt8(int Value) const { + O << MAI->getData8bitsDirective(); + PrintHex(Value & 0xFF); +} + +/// EmitInt16 - Emit a short directive and value. +/// +void AsmPrinter::EmitInt16(int Value) const { + O << MAI->getData16bitsDirective(); + PrintHex(Value & 0xFFFF); +} + +/// EmitInt32 - Emit a long directive and value. +/// +void AsmPrinter::EmitInt32(int Value) const { + O << MAI->getData32bitsDirective(); + PrintHex(Value); +} + +/// EmitInt64 - Emit a long long directive and value. +/// +void AsmPrinter::EmitInt64(uint64_t Value) const { + if (MAI->getData64bitsDirective()) { + O << MAI->getData64bitsDirective(); + PrintHex(Value); + } else { + if (TM.getTargetData()->isBigEndian()) { + EmitInt32(unsigned(Value >> 32)); O << '\n'; + EmitInt32(unsigned(Value)); + } else { + EmitInt32(unsigned(Value)); O << '\n'; + EmitInt32(unsigned(Value >> 32)); + } + } +} + +/// toOctal - Convert the low order bits of X into an octal digit. +/// +static inline char toOctal(int X) { + return (X&7)+'0'; +} + +/// printStringChar - Print a char, escaped if necessary. +/// +static void printStringChar(formatted_raw_ostream &O, unsigned char C) { + if (C == '"') { + O << "\\\""; + } else if (C == '\\') { + O << "\\\\"; + } else if (isprint((unsigned char)C)) { + O << C; + } else { + switch(C) { + case '\b': O << "\\b"; break; + case '\f': O << "\\f"; break; + case '\n': O << "\\n"; break; + case '\r': O << "\\r"; break; + case '\t': O << "\\t"; break; + default: + O << '\\'; + O << toOctal(C >> 6); + O << toOctal(C >> 3); + O << toOctal(C >> 0); + break; + } + } +} + +/// EmitString - Emit a string with quotes and a null terminator. +/// Special characters are emitted properly. +/// \literal (Eg. '\t') \endliteral +void AsmPrinter::EmitString(const StringRef String) const { + EmitString(String.data(), String.size()); +} + +void AsmPrinter::EmitString(const char *String, unsigned Size) const { + const char* AscizDirective = MAI->getAscizDirective(); + if (AscizDirective) + O << AscizDirective; + else + O << MAI->getAsciiDirective(); + O << '\"'; + for (unsigned i = 0; i < Size; ++i) + printStringChar(O, String[i]); + if (AscizDirective) + O << '\"'; + else + O << "\\0\""; +} + + +/// EmitFile - Emit a .file directive. +void AsmPrinter::EmitFile(unsigned Number, const std::string &Name) const { + O << "\t.file\t" << Number << " \""; + for (unsigned i = 0, N = Name.size(); i < N; ++i) + printStringChar(O, Name[i]); + O << '\"'; +} + + +//===----------------------------------------------------------------------===// + +// EmitAlignment - Emit an alignment directive to the specified power of +// two boundary. For example, if you pass in 3 here, you will get an 8 +// byte alignment. If a global value is specified, and if that global has +// an explicit alignment requested, it will unconditionally override the +// alignment request. However, if ForcedAlignBits is specified, this value +// has final say: the ultimate alignment will be the max of ForcedAlignBits +// and the alignment computed with NumBits and the global. +// +// The algorithm is: +// Align = NumBits; +// if (GV && GV->hasalignment) Align = GV->getalignment(); +// Align = std::max(Align, ForcedAlignBits); +// +void AsmPrinter::EmitAlignment(unsigned NumBits, const GlobalValue *GV, + unsigned ForcedAlignBits, + bool UseFillExpr) const { + if (GV && GV->getAlignment()) + NumBits = Log2_32(GV->getAlignment()); + NumBits = std::max(NumBits, ForcedAlignBits); + + if (NumBits == 0) return; // No need to emit alignment. + + unsigned FillValue = 0; + if (getCurrentSection()->getKind().isText()) + FillValue = MAI->getTextAlignFillValue(); + + OutStreamer.EmitValueToAlignment(1 << NumBits, FillValue, 1, 0); +} + +/// EmitZeros - Emit a block of zeros. +/// +void AsmPrinter::EmitZeros(uint64_t NumZeros, unsigned AddrSpace) const { + if (NumZeros) { + if (MAI->getZeroDirective()) { + O << MAI->getZeroDirective() << NumZeros; + if (MAI->getZeroDirectiveSuffix()) + O << MAI->getZeroDirectiveSuffix(); + O << '\n'; + } else { + for (; NumZeros; --NumZeros) + O << MAI->getData8bitsDirective(AddrSpace) << "0\n"; + } + } +} + +// Print out the specified constant, without a storage class. Only the +// constants valid in constant expressions can occur here. +void AsmPrinter::EmitConstantValueOnly(const Constant *CV) { + if (CV->isNullValue() || isa(CV)) + O << '0'; + else if (const ConstantInt *CI = dyn_cast(CV)) { + O << CI->getZExtValue(); + } else if (const GlobalValue *GV = dyn_cast(CV)) { + // This is a constant address for a global variable or function. Use the + // name of the variable or function as the address value. + O << Mang->getMangledName(GV); + } else if (const ConstantExpr *CE = dyn_cast(CV)) { + const TargetData *TD = TM.getTargetData(); + unsigned Opcode = CE->getOpcode(); + switch (Opcode) { + case Instruction::Trunc: + case Instruction::ZExt: + case Instruction::SExt: + case Instruction::FPTrunc: + case Instruction::FPExt: + case Instruction::UIToFP: + case Instruction::SIToFP: + case Instruction::FPToUI: + case Instruction::FPToSI: + llvm_unreachable("FIXME: Don't support this constant cast expr"); + case Instruction::GetElementPtr: { + // generate a symbolic expression for the byte address + const Constant *ptrVal = CE->getOperand(0); + SmallVector idxVec(CE->op_begin()+1, CE->op_end()); + if (int64_t Offset = TD->getIndexedOffset(ptrVal->getType(), &idxVec[0], + idxVec.size())) { + // Truncate/sext the offset to the pointer size. + if (TD->getPointerSizeInBits() != 64) { + int SExtAmount = 64-TD->getPointerSizeInBits(); + Offset = (Offset << SExtAmount) >> SExtAmount; + } + + if (Offset) + O << '('; + EmitConstantValueOnly(ptrVal); + if (Offset > 0) + O << ") + " << Offset; + else if (Offset < 0) + O << ") - " << -Offset; + } else { + EmitConstantValueOnly(ptrVal); + } + break; + } + case Instruction::BitCast: + return EmitConstantValueOnly(CE->getOperand(0)); + + case Instruction::IntToPtr: { + // Handle casts to pointers by changing them into casts to the appropriate + // integer type. This promotes constant folding and simplifies this code. + Constant *Op = CE->getOperand(0); + Op = ConstantExpr::getIntegerCast(Op, TD->getIntPtrType(CV->getContext()), + false/*ZExt*/); + return EmitConstantValueOnly(Op); + } + + + case Instruction::PtrToInt: { + // Support only foldable casts to/from pointers that can be eliminated by + // changing the pointer to the appropriately sized integer type. + Constant *Op = CE->getOperand(0); + const Type *Ty = CE->getType(); + + // We can emit the pointer value into this slot if the slot is an + // integer slot greater or equal to the size of the pointer. + if (TD->getTypeAllocSize(Ty) == TD->getTypeAllocSize(Op->getType())) + return EmitConstantValueOnly(Op); + + O << "(("; + EmitConstantValueOnly(Op); + APInt ptrMask = + APInt::getAllOnesValue(TD->getTypeAllocSizeInBits(Op->getType())); + + SmallString<40> S; + ptrMask.toStringUnsigned(S); + O << ") & " << S.str() << ')'; + break; + } + case Instruction::Add: + case Instruction::Sub: + case Instruction::And: + case Instruction::Or: + case Instruction::Xor: + O << '('; + EmitConstantValueOnly(CE->getOperand(0)); + O << ')'; + switch (Opcode) { + case Instruction::Add: + O << " + "; + break; + case Instruction::Sub: + O << " - "; + break; + case Instruction::And: + O << " & "; + break; + case Instruction::Or: + O << " | "; + break; + case Instruction::Xor: + O << " ^ "; + break; + default: + break; + } + O << '('; + EmitConstantValueOnly(CE->getOperand(1)); + O << ')'; + break; + default: + llvm_unreachable("Unsupported operator!"); + } + } else if (const BlockAddress *BA = dyn_cast(CV)) { + GetBlockAddressSymbol(BA)->print(O, MAI); + } else { + llvm_unreachable("Unknown constant value!"); + } +} + +/// printAsCString - Print the specified array as a C compatible string, only if +/// the predicate isString is true. +/// +static void printAsCString(formatted_raw_ostream &O, const ConstantArray *CVA, + unsigned LastElt) { + assert(CVA->isString() && "Array is not string compatible!"); + + O << '\"'; + for (unsigned i = 0; i != LastElt; ++i) { + unsigned char C = + (unsigned char)cast(CVA->getOperand(i))->getZExtValue(); + printStringChar(O, C); + } + O << '\"'; +} + +/// EmitString - Emit a zero-byte-terminated string constant. +/// +void AsmPrinter::EmitString(const ConstantArray *CVA) const { + unsigned NumElts = CVA->getNumOperands(); + if (MAI->getAscizDirective() && NumElts && + cast(CVA->getOperand(NumElts-1))->getZExtValue() == 0) { + O << MAI->getAscizDirective(); + printAsCString(O, CVA, NumElts-1); + } else { + O << MAI->getAsciiDirective(); + printAsCString(O, CVA, NumElts); + } + O << '\n'; +} + +void AsmPrinter::EmitGlobalConstantArray(const ConstantArray *CVA, + unsigned AddrSpace) { + if (CVA->isString()) { + EmitString(CVA); + } else { // Not a string. Print the values in successive locations + for (unsigned i = 0, e = CVA->getNumOperands(); i != e; ++i) + EmitGlobalConstant(CVA->getOperand(i), AddrSpace); + } +} + +void AsmPrinter::EmitGlobalConstantVector(const ConstantVector *CP) { + const VectorType *PTy = CP->getType(); + + for (unsigned I = 0, E = PTy->getNumElements(); I < E; ++I) + EmitGlobalConstant(CP->getOperand(I)); +} + +void AsmPrinter::EmitGlobalConstantStruct(const ConstantStruct *CVS, + unsigned AddrSpace) { + // Print the fields in successive locations. Pad to align if needed! + const TargetData *TD = TM.getTargetData(); + unsigned Size = TD->getTypeAllocSize(CVS->getType()); + const StructLayout *cvsLayout = TD->getStructLayout(CVS->getType()); + uint64_t sizeSoFar = 0; + for (unsigned i = 0, e = CVS->getNumOperands(); i != e; ++i) { + const Constant* field = CVS->getOperand(i); + + // Check if padding is needed and insert one or more 0s. + uint64_t fieldSize = TD->getTypeAllocSize(field->getType()); + uint64_t padSize = ((i == e-1 ? Size : cvsLayout->getElementOffset(i+1)) + - cvsLayout->getElementOffset(i)) - fieldSize; + sizeSoFar += fieldSize + padSize; + + // Now print the actual field value. + EmitGlobalConstant(field, AddrSpace); + + // Insert padding - this may include padding to increase the size of the + // current field up to the ABI size (if the struct is not packed) as well + // as padding to ensure that the next field starts at the right offset. + EmitZeros(padSize, AddrSpace); + } + assert(sizeSoFar == cvsLayout->getSizeInBytes() && + "Layout of constant struct may be incorrect!"); +} + +void AsmPrinter::EmitGlobalConstantFP(const ConstantFP *CFP, + unsigned AddrSpace) { + // FP Constants are printed as integer constants to avoid losing + // precision... + LLVMContext &Context = CFP->getContext(); + const TargetData *TD = TM.getTargetData(); + if (CFP->getType()->isDoubleTy()) { + double Val = CFP->getValueAPF().convertToDouble(); // for comment only + uint64_t i = CFP->getValueAPF().bitcastToAPInt().getZExtValue(); + if (MAI->getData64bitsDirective(AddrSpace)) { + O << MAI->getData64bitsDirective(AddrSpace) << i; + if (VerboseAsm) { + O.PadToColumn(MAI->getCommentColumn()); + O << MAI->getCommentString() << " double " << Val; + } + O << '\n'; + } else if (TD->isBigEndian()) { + O << MAI->getData32bitsDirective(AddrSpace) << unsigned(i >> 32); + if (VerboseAsm) { + O.PadToColumn(MAI->getCommentColumn()); + O << MAI->getCommentString() + << " most significant word of double " << Val; + } + O << '\n'; + O << MAI->getData32bitsDirective(AddrSpace) << unsigned(i); + if (VerboseAsm) { + O.PadToColumn(MAI->getCommentColumn()); + O << MAI->getCommentString() + << " least significant word of double " << Val; + } + O << '\n'; + } else { + O << MAI->getData32bitsDirective(AddrSpace) << unsigned(i); + if (VerboseAsm) { + O.PadToColumn(MAI->getCommentColumn()); + O << MAI->getCommentString() + << " least significant word of double " << Val; + } + O << '\n'; + O << MAI->getData32bitsDirective(AddrSpace) << unsigned(i >> 32); + if (VerboseAsm) { + O.PadToColumn(MAI->getCommentColumn()); + O << MAI->getCommentString() + << " most significant word of double " << Val; + } + O << '\n'; + } + return; + } + + if (CFP->getType()->isFloatTy()) { + float Val = CFP->getValueAPF().convertToFloat(); // for comment only + O << MAI->getData32bitsDirective(AddrSpace) + << CFP->getValueAPF().bitcastToAPInt().getZExtValue(); + if (VerboseAsm) { + O.PadToColumn(MAI->getCommentColumn()); + O << MAI->getCommentString() << " float " << Val; + } + O << '\n'; + return; + } + + if (CFP->getType()->isX86_FP80Ty()) { + // all long double variants are printed as hex + // api needed to prevent premature destruction + APInt api = CFP->getValueAPF().bitcastToAPInt(); + const uint64_t *p = api.getRawData(); + // Convert to double so we can print the approximate val as a comment. + APFloat DoubleVal = CFP->getValueAPF(); + bool ignored; + DoubleVal.convert(APFloat::IEEEdouble, APFloat::rmNearestTiesToEven, + &ignored); + if (TD->isBigEndian()) { + O << MAI->getData16bitsDirective(AddrSpace) << uint16_t(p[1]); + if (VerboseAsm) { + O.PadToColumn(MAI->getCommentColumn()); + O << MAI->getCommentString() + << " most significant halfword of x86_fp80 ~" + << DoubleVal.convertToDouble(); + } + O << '\n'; + O << MAI->getData16bitsDirective(AddrSpace) << uint16_t(p[0] >> 48); + if (VerboseAsm) { + O.PadToColumn(MAI->getCommentColumn()); + O << MAI->getCommentString() << " next halfword"; + } + O << '\n'; + O << MAI->getData16bitsDirective(AddrSpace) << uint16_t(p[0] >> 32); + if (VerboseAsm) { + O.PadToColumn(MAI->getCommentColumn()); + O << MAI->getCommentString() << " next halfword"; + } + O << '\n'; + O << MAI->getData16bitsDirective(AddrSpace) << uint16_t(p[0] >> 16); + if (VerboseAsm) { + O.PadToColumn(MAI->getCommentColumn()); + O << MAI->getCommentString() << " next halfword"; + } + O << '\n'; + O << MAI->getData16bitsDirective(AddrSpace) << uint16_t(p[0]); + if (VerboseAsm) { + O.PadToColumn(MAI->getCommentColumn()); + O << MAI->getCommentString() + << " least significant halfword"; + } + O << '\n'; + } else { + O << MAI->getData16bitsDirective(AddrSpace) << uint16_t(p[0]); + if (VerboseAsm) { + O.PadToColumn(MAI->getCommentColumn()); + O << MAI->getCommentString() + << " least significant halfword of x86_fp80 ~" + << DoubleVal.convertToDouble(); + } + O << '\n'; + O << MAI->getData16bitsDirective(AddrSpace) << uint16_t(p[0] >> 16); + if (VerboseAsm) { + O.PadToColumn(MAI->getCommentColumn()); + O << MAI->getCommentString() + << " next halfword"; + } + O << '\n'; + O << MAI->getData16bitsDirective(AddrSpace) << uint16_t(p[0] >> 32); + if (VerboseAsm) { + O.PadToColumn(MAI->getCommentColumn()); + O << MAI->getCommentString() + << " next halfword"; + } + O << '\n'; + O << MAI->getData16bitsDirective(AddrSpace) << uint16_t(p[0] >> 48); + if (VerboseAsm) { + O.PadToColumn(MAI->getCommentColumn()); + O << MAI->getCommentString() + << " next halfword"; + } + O << '\n'; + O << MAI->getData16bitsDirective(AddrSpace) << uint16_t(p[1]); + if (VerboseAsm) { + O.PadToColumn(MAI->getCommentColumn()); + O << MAI->getCommentString() + << " most significant halfword"; + } + O << '\n'; + } + EmitZeros(TD->getTypeAllocSize(Type::getX86_FP80Ty(Context)) - + TD->getTypeStoreSize(Type::getX86_FP80Ty(Context)), AddrSpace); + return; + } + + if (CFP->getType()->isPPC_FP128Ty()) { + // all long double variants are printed as hex + // api needed to prevent premature destruction + APInt api = CFP->getValueAPF().bitcastToAPInt(); + const uint64_t *p = api.getRawData(); + if (TD->isBigEndian()) { + O << MAI->getData32bitsDirective(AddrSpace) << uint32_t(p[0] >> 32); + if (VerboseAsm) { + O.PadToColumn(MAI->getCommentColumn()); + O << MAI->getCommentString() + << " most significant word of ppc_fp128"; + } + O << '\n'; + O << MAI->getData32bitsDirective(AddrSpace) << uint32_t(p[0]); + if (VerboseAsm) { + O.PadToColumn(MAI->getCommentColumn()); + O << MAI->getCommentString() + << " next word"; + } + O << '\n'; + O << MAI->getData32bitsDirective(AddrSpace) << uint32_t(p[1] >> 32); + if (VerboseAsm) { + O.PadToColumn(MAI->getCommentColumn()); + O << MAI->getCommentString() + << " next word"; + } + O << '\n'; + O << MAI->getData32bitsDirective(AddrSpace) << uint32_t(p[1]); + if (VerboseAsm) { + O.PadToColumn(MAI->getCommentColumn()); + O << MAI->getCommentString() + << " least significant word"; + } + O << '\n'; + } else { + O << MAI->getData32bitsDirective(AddrSpace) << uint32_t(p[1]); + if (VerboseAsm) { + O.PadToColumn(MAI->getCommentColumn()); + O << MAI->getCommentString() + << " least significant word of ppc_fp128"; + } + O << '\n'; + O << MAI->getData32bitsDirective(AddrSpace) << uint32_t(p[1] >> 32); + if (VerboseAsm) { + O.PadToColumn(MAI->getCommentColumn()); + O << MAI->getCommentString() + << " next word"; + } + O << '\n'; + O << MAI->getData32bitsDirective(AddrSpace) << uint32_t(p[0]); + if (VerboseAsm) { + O.PadToColumn(MAI->getCommentColumn()); + O << MAI->getCommentString() + << " next word"; + } + O << '\n'; + O << MAI->getData32bitsDirective(AddrSpace) << uint32_t(p[0] >> 32); + if (VerboseAsm) { + O.PadToColumn(MAI->getCommentColumn()); + O << MAI->getCommentString() + << " most significant word"; + } + O << '\n'; + } + return; + } else llvm_unreachable("Floating point constant type not handled"); +} + +void AsmPrinter::EmitGlobalConstantLargeInt(const ConstantInt *CI, + unsigned AddrSpace) { + const TargetData *TD = TM.getTargetData(); + unsigned BitWidth = CI->getBitWidth(); + assert(isPowerOf2_32(BitWidth) && + "Non-power-of-2-sized integers not handled!"); + + // We don't expect assemblers to support integer data directives + // for more than 64 bits, so we emit the data in at most 64-bit + // quantities at a time. + const uint64_t *RawData = CI->getValue().getRawData(); + for (unsigned i = 0, e = BitWidth / 64; i != e; ++i) { + uint64_t Val; + if (TD->isBigEndian()) + Val = RawData[e - i - 1]; + else + Val = RawData[i]; + + if (MAI->getData64bitsDirective(AddrSpace)) + O << MAI->getData64bitsDirective(AddrSpace) << Val << '\n'; + else if (TD->isBigEndian()) { + O << MAI->getData32bitsDirective(AddrSpace) << unsigned(Val >> 32); + if (VerboseAsm) { + O.PadToColumn(MAI->getCommentColumn()); + O << MAI->getCommentString() + << " most significant half of i64 " << Val; + } + O << '\n'; + O << MAI->getData32bitsDirective(AddrSpace) << unsigned(Val); + if (VerboseAsm) { + O.PadToColumn(MAI->getCommentColumn()); + O << MAI->getCommentString() + << " least significant half of i64 " << Val; + } + O << '\n'; + } else { + O << MAI->getData32bitsDirective(AddrSpace) << unsigned(Val); + if (VerboseAsm) { + O.PadToColumn(MAI->getCommentColumn()); + O << MAI->getCommentString() + << " least significant half of i64 " << Val; + } + O << '\n'; + O << MAI->getData32bitsDirective(AddrSpace) << unsigned(Val >> 32); + if (VerboseAsm) { + O.PadToColumn(MAI->getCommentColumn()); + O << MAI->getCommentString() + << " most significant half of i64 " << Val; + } + O << '\n'; + } + } +} + +/// EmitGlobalConstant - Print a general LLVM constant to the .s file. +void AsmPrinter::EmitGlobalConstant(const Constant *CV, unsigned AddrSpace) { + const TargetData *TD = TM.getTargetData(); + const Type *type = CV->getType(); + unsigned Size = TD->getTypeAllocSize(type); + + if (CV->isNullValue() || isa(CV)) { + EmitZeros(Size, AddrSpace); + return; + } else if (const ConstantArray *CVA = dyn_cast(CV)) { + EmitGlobalConstantArray(CVA , AddrSpace); + return; + } else if (const ConstantStruct *CVS = dyn_cast(CV)) { + EmitGlobalConstantStruct(CVS, AddrSpace); + return; + } else if (const ConstantFP *CFP = dyn_cast(CV)) { + EmitGlobalConstantFP(CFP, AddrSpace); + return; + } else if (const ConstantInt *CI = dyn_cast(CV)) { + // Small integers are handled below; large integers are handled here. + if (Size > 4) { + EmitGlobalConstantLargeInt(CI, AddrSpace); + return; + } + } else if (const ConstantVector *CP = dyn_cast(CV)) { + EmitGlobalConstantVector(CP); + return; + } + + printDataDirective(type, AddrSpace); + EmitConstantValueOnly(CV); + if (VerboseAsm) { + if (const ConstantInt *CI = dyn_cast(CV)) { + SmallString<40> S; + CI->getValue().toStringUnsigned(S, 16); + O.PadToColumn(MAI->getCommentColumn()); + O << MAI->getCommentString() << " 0x" << S.str(); + } + } + O << '\n'; +} + +void AsmPrinter::EmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV) { + // Target doesn't support this yet! + llvm_unreachable("Target does not support EmitMachineConstantPoolValue"); +} + +/// PrintSpecial - Print information related to the specified machine instr +/// that is independent of the operand, and may be independent of the instr +/// itself. This can be useful for portably encoding the comment character +/// or other bits of target-specific knowledge into the asmstrings. The +/// syntax used is ${:comment}. Targets can override this to add support +/// for their own strange codes. +void AsmPrinter::PrintSpecial(const MachineInstr *MI, const char *Code) const { + if (!strcmp(Code, "private")) { + O << MAI->getPrivateGlobalPrefix(); + } else if (!strcmp(Code, "comment")) { + if (VerboseAsm) + O << MAI->getCommentString(); + } else if (!strcmp(Code, "uid")) { + // Comparing the address of MI isn't sufficient, because machineinstrs may + // be allocated to the same address across functions. + const Function *ThisF = MI->getParent()->getParent()->getFunction(); + + // If this is a new LastFn instruction, bump the counter. + if (LastMI != MI || LastFn != ThisF) { + ++Counter; + LastMI = MI; + LastFn = ThisF; + } + O << Counter; + } else { + std::string msg; + raw_string_ostream Msg(msg); + Msg << "Unknown special formatter '" << Code + << "' for machine instr: " << *MI; + llvm_report_error(Msg.str()); + } +} + +/// processDebugLoc - Processes the debug information of each machine +/// instruction's DebugLoc. +void AsmPrinter::processDebugLoc(const MachineInstr *MI, + bool BeforePrintingInsn) { + if (!MAI || !DW || !MAI->doesSupportDebugInformation() + || !DW->ShouldEmitDwarfDebug()) + return; + DebugLoc DL = MI->getDebugLoc(); + if (DL.isUnknown()) + return; + DebugLocTuple CurDLT = MF->getDebugLocTuple(DL); + if (CurDLT.Scope == 0) + return; + + if (BeforePrintingInsn) { + if (CurDLT != PrevDLT) { + unsigned L = DW->RecordSourceLine(CurDLT.Line, CurDLT.Col, + CurDLT.Scope); + printLabel(L); + DW->BeginScope(MI, L); + PrevDLT = CurDLT; + } + } else { + // After printing instruction + DW->EndScope(MI); + } +} + + +/// printInlineAsm - This method formats and prints the specified machine +/// instruction that is an inline asm. +void AsmPrinter::printInlineAsm(const MachineInstr *MI) const { + unsigned NumOperands = MI->getNumOperands(); + + // Count the number of register definitions. + unsigned NumDefs = 0; + for (; MI->getOperand(NumDefs).isReg() && MI->getOperand(NumDefs).isDef(); + ++NumDefs) + assert(NumDefs != NumOperands-1 && "No asm string?"); + + assert(MI->getOperand(NumDefs).isSymbol() && "No asm string?"); + + // Disassemble the AsmStr, printing out the literal pieces, the operands, etc. + const char *AsmStr = MI->getOperand(NumDefs).getSymbolName(); + + O << '\t'; + + // If this asmstr is empty, just print the #APP/#NOAPP markers. + // These are useful to see where empty asm's wound up. + if (AsmStr[0] == 0) { + O << MAI->getCommentString() << MAI->getInlineAsmStart() << "\n\t"; + O << MAI->getCommentString() << MAI->getInlineAsmEnd() << '\n'; + return; + } + + O << MAI->getCommentString() << MAI->getInlineAsmStart() << "\n\t"; + + // The variant of the current asmprinter. + int AsmPrinterVariant = MAI->getAssemblerDialect(); + + int CurVariant = -1; // The number of the {.|.|.} region we are in. + const char *LastEmitted = AsmStr; // One past the last character emitted. + + while (*LastEmitted) { + switch (*LastEmitted) { + default: { + // Not a special case, emit the string section literally. + const char *LiteralEnd = LastEmitted+1; + while (*LiteralEnd && *LiteralEnd != '{' && *LiteralEnd != '|' && + *LiteralEnd != '}' && *LiteralEnd != '$' && *LiteralEnd != '\n') + ++LiteralEnd; + if (CurVariant == -1 || CurVariant == AsmPrinterVariant) + O.write(LastEmitted, LiteralEnd-LastEmitted); + LastEmitted = LiteralEnd; + break; + } + case '\n': + ++LastEmitted; // Consume newline character. + O << '\n'; // Indent code with newline. + break; + case '$': { + ++LastEmitted; // Consume '$' character. + bool Done = true; + + // Handle escapes. + switch (*LastEmitted) { + default: Done = false; break; + case '$': // $$ -> $ + if (CurVariant == -1 || CurVariant == AsmPrinterVariant) + O << '$'; + ++LastEmitted; // Consume second '$' character. + break; + case '(': // $( -> same as GCC's { character. + ++LastEmitted; // Consume '(' character. + if (CurVariant != -1) { + llvm_report_error("Nested variants found in inline asm string: '" + + std::string(AsmStr) + "'"); + } + CurVariant = 0; // We're in the first variant now. + break; + case '|': + ++LastEmitted; // consume '|' character. + if (CurVariant == -1) + O << '|'; // this is gcc's behavior for | outside a variant + else + ++CurVariant; // We're in the next variant. + break; + case ')': // $) -> same as GCC's } char. + ++LastEmitted; // consume ')' character. + if (CurVariant == -1) + O << '}'; // this is gcc's behavior for } outside a variant + else + CurVariant = -1; + break; + } + if (Done) break; + + bool HasCurlyBraces = false; + if (*LastEmitted == '{') { // ${variable} + ++LastEmitted; // Consume '{' character. + HasCurlyBraces = true; + } + + // If we have ${:foo}, then this is not a real operand reference, it is a + // "magic" string reference, just like in .td files. Arrange to call + // PrintSpecial. + if (HasCurlyBraces && *LastEmitted == ':') { + ++LastEmitted; + const char *StrStart = LastEmitted; + const char *StrEnd = strchr(StrStart, '}'); + if (StrEnd == 0) { + llvm_report_error("Unterminated ${:foo} operand in inline asm string: '" + + std::string(AsmStr) + "'"); + } + + std::string Val(StrStart, StrEnd); + PrintSpecial(MI, Val.c_str()); + LastEmitted = StrEnd+1; + break; + } + + const char *IDStart = LastEmitted; + char *IDEnd; + errno = 0; + long Val = strtol(IDStart, &IDEnd, 10); // We only accept numbers for IDs. + if (!isdigit(*IDStart) || (Val == 0 && errno == EINVAL)) { + llvm_report_error("Bad $ operand number in inline asm string: '" + + std::string(AsmStr) + "'"); + } + LastEmitted = IDEnd; + + char Modifier[2] = { 0, 0 }; + + if (HasCurlyBraces) { + // If we have curly braces, check for a modifier character. This + // supports syntax like ${0:u}, which correspond to "%u0" in GCC asm. + if (*LastEmitted == ':') { + ++LastEmitted; // Consume ':' character. + if (*LastEmitted == 0) { + llvm_report_error("Bad ${:} expression in inline asm string: '" + + std::string(AsmStr) + "'"); + } + + Modifier[0] = *LastEmitted; + ++LastEmitted; // Consume modifier character. + } + + if (*LastEmitted != '}') { + llvm_report_error("Bad ${} expression in inline asm string: '" + + std::string(AsmStr) + "'"); + } + ++LastEmitted; // Consume '}' character. + } + + if ((unsigned)Val >= NumOperands-1) { + llvm_report_error("Invalid $ operand number in inline asm string: '" + + std::string(AsmStr) + "'"); + } + + // Okay, we finally have a value number. Ask the target to print this + // operand! + if (CurVariant == -1 || CurVariant == AsmPrinterVariant) { + unsigned OpNo = 1; + + bool Error = false; + + // Scan to find the machine operand number for the operand. + for (; Val; --Val) { + if (OpNo >= MI->getNumOperands()) break; + unsigned OpFlags = MI->getOperand(OpNo).getImm(); + OpNo += InlineAsm::getNumOperandRegisters(OpFlags) + 1; + } + + if (OpNo >= MI->getNumOperands()) { + Error = true; + } else { + unsigned OpFlags = MI->getOperand(OpNo).getImm(); + ++OpNo; // Skip over the ID number. + + if (Modifier[0]=='l') // labels are target independent + GetMBBSymbol(MI->getOperand(OpNo).getMBB() + ->getNumber())->print(O, MAI); + else { + AsmPrinter *AP = const_cast(this); + if ((OpFlags & 7) == 4) { + Error = AP->PrintAsmMemoryOperand(MI, OpNo, AsmPrinterVariant, + Modifier[0] ? Modifier : 0); + } else { + Error = AP->PrintAsmOperand(MI, OpNo, AsmPrinterVariant, + Modifier[0] ? Modifier : 0); + } + } + } + if (Error) { + std::string msg; + raw_string_ostream Msg(msg); + Msg << "Invalid operand found in inline asm: '" + << AsmStr << "'\n"; + MI->print(Msg); + llvm_report_error(Msg.str()); + } + } + break; + } + } + } + O << "\n\t" << MAI->getCommentString() << MAI->getInlineAsmEnd(); +} + +/// printImplicitDef - This method prints the specified machine instruction +/// that is an implicit def. +void AsmPrinter::printImplicitDef(const MachineInstr *MI) const { + if (!VerboseAsm) return; + O.PadToColumn(MAI->getCommentColumn()); + O << MAI->getCommentString() << " implicit-def: " + << TRI->getName(MI->getOperand(0).getReg()); +} + +void AsmPrinter::printKill(const MachineInstr *MI) const { + if (!VerboseAsm) return; + O.PadToColumn(MAI->getCommentColumn()); + O << MAI->getCommentString() << " kill:"; + for (unsigned n = 0, e = MI->getNumOperands(); n != e; ++n) { + const MachineOperand &op = MI->getOperand(n); + assert(op.isReg() && "KILL instruction must have only register operands"); + O << ' ' << TRI->getName(op.getReg()) << (op.isDef() ? "" : ""); + } +} + +/// printLabel - This method prints a local label used by debug and +/// exception handling tables. +void AsmPrinter::printLabel(const MachineInstr *MI) const { + printLabel(MI->getOperand(0).getImm()); +} + +void AsmPrinter::printLabel(unsigned Id) const { + O << MAI->getPrivateGlobalPrefix() << "label" << Id << ':'; +} + +/// PrintAsmOperand - Print the specified operand of MI, an INLINEASM +/// instruction, using the specified assembler variant. Targets should +/// overried this to format as appropriate. +bool AsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, + unsigned AsmVariant, const char *ExtraCode) { + // Target doesn't support this yet! + return true; +} + +bool AsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo, + unsigned AsmVariant, + const char *ExtraCode) { + // Target doesn't support this yet! + return true; +} + +MCSymbol *AsmPrinter::GetBlockAddressSymbol(const BlockAddress *BA, + const char *Suffix) const { + return GetBlockAddressSymbol(BA->getFunction(), BA->getBasicBlock(), Suffix); +} + +MCSymbol *AsmPrinter::GetBlockAddressSymbol(const Function *F, + const BasicBlock *BB, + const char *Suffix) const { + assert(BB->hasName() && + "Address of anonymous basic block not supported yet!"); + + // This code must use the function name itself, and not the function number, + // since it must be possible to generate the label name from within other + // functions. + std::string FuncName = Mang->getMangledName(F); + + SmallString<60> Name; + raw_svector_ostream(Name) << MAI->getPrivateGlobalPrefix() << "BA" + << FuncName.size() << '_' << FuncName << '_' + << Mang->makeNameProper(BB->getName()) + << Suffix; + + return OutContext.GetOrCreateSymbol(Name.str()); +} + +MCSymbol *AsmPrinter::GetMBBSymbol(unsigned MBBID) const { + SmallString<60> Name; + raw_svector_ostream(Name) << MAI->getPrivateGlobalPrefix() << "BB" + << getFunctionNumber() << '_' << MBBID; + + return OutContext.GetOrCreateSymbol(Name.str()); +} + + +/// EmitBasicBlockStart - This method prints the label for the specified +/// MachineBasicBlock, an alignment (if present) and a comment describing +/// it if appropriate. +void AsmPrinter::EmitBasicBlockStart(const MachineBasicBlock *MBB) const { + // Emit an alignment directive for this block, if needed. + if (unsigned Align = MBB->getAlignment()) + EmitAlignment(Log2_32(Align)); + + // If the block has its address taken, emit a special label to satisfy + // references to the block. This is done so that we don't need to + // remember the number of this label, and so that we can make + // forward references to labels without knowing what their numbers + // will be. + if (MBB->hasAddressTaken()) { + GetBlockAddressSymbol(MBB->getBasicBlock()->getParent(), + MBB->getBasicBlock())->print(O, MAI); + O << ':'; + if (VerboseAsm) { + O.PadToColumn(MAI->getCommentColumn()); + O << MAI->getCommentString() << " Address Taken"; + } + O << '\n'; + } + + // Print the main label for the block. + if (MBB->pred_empty() || MBB->isOnlyReachableByFallthrough()) { + if (VerboseAsm) + O << MAI->getCommentString() << " BB#" << MBB->getNumber() << ':'; + } else { + GetMBBSymbol(MBB->getNumber())->print(O, MAI); + O << ':'; + if (!VerboseAsm) + O << '\n'; + } + + // Print some comments to accompany the label. + if (VerboseAsm) { + if (const BasicBlock *BB = MBB->getBasicBlock()) + if (BB->hasName()) { + O.PadToColumn(MAI->getCommentColumn()); + O << MAI->getCommentString() << ' '; + WriteAsOperand(O, BB, /*PrintType=*/false); + } + + EmitComments(*MBB); + O << '\n'; + } +} + +/// printPICJumpTableSetLabel - This method prints a set label for the +/// specified MachineBasicBlock for a jumptable entry. +void AsmPrinter::printPICJumpTableSetLabel(unsigned uid, + const MachineBasicBlock *MBB) const { + if (!MAI->getSetDirective()) + return; + + O << MAI->getSetDirective() << ' ' << MAI->getPrivateGlobalPrefix() + << getFunctionNumber() << '_' << uid << "_set_" << MBB->getNumber() << ','; + GetMBBSymbol(MBB->getNumber())->print(O, MAI); + O << '-' << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() + << '_' << uid << '\n'; +} + +void AsmPrinter::printPICJumpTableSetLabel(unsigned uid, unsigned uid2, + const MachineBasicBlock *MBB) const { + if (!MAI->getSetDirective()) + return; + + O << MAI->getSetDirective() << ' ' << MAI->getPrivateGlobalPrefix() + << getFunctionNumber() << '_' << uid << '_' << uid2 + << "_set_" << MBB->getNumber() << ','; + GetMBBSymbol(MBB->getNumber())->print(O, MAI); + O << '-' << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() + << '_' << uid << '_' << uid2 << '\n'; +} + +/// printDataDirective - This method prints the asm directive for the +/// specified type. +void AsmPrinter::printDataDirective(const Type *type, unsigned AddrSpace) { + const TargetData *TD = TM.getTargetData(); + switch (type->getTypeID()) { + case Type::FloatTyID: case Type::DoubleTyID: + case Type::X86_FP80TyID: case Type::FP128TyID: case Type::PPC_FP128TyID: + assert(0 && "Should have already output floating point constant."); + default: + assert(0 && "Can't handle printing this type of thing"); + case Type::IntegerTyID: { + unsigned BitWidth = cast(type)->getBitWidth(); + if (BitWidth <= 8) + O << MAI->getData8bitsDirective(AddrSpace); + else if (BitWidth <= 16) + O << MAI->getData16bitsDirective(AddrSpace); + else if (BitWidth <= 32) + O << MAI->getData32bitsDirective(AddrSpace); + else if (BitWidth <= 64) { + assert(MAI->getData64bitsDirective(AddrSpace) && + "Target cannot handle 64-bit constant exprs!"); + O << MAI->getData64bitsDirective(AddrSpace); + } else { + llvm_unreachable("Target cannot handle given data directive width!"); + } + break; + } + case Type::PointerTyID: + if (TD->getPointerSize() == 8) { + assert(MAI->getData64bitsDirective(AddrSpace) && + "Target cannot handle 64-bit pointer exprs!"); + O << MAI->getData64bitsDirective(AddrSpace); + } else if (TD->getPointerSize() == 2) { + O << MAI->getData16bitsDirective(AddrSpace); + } else if (TD->getPointerSize() == 1) { + O << MAI->getData8bitsDirective(AddrSpace); + } else { + O << MAI->getData32bitsDirective(AddrSpace); + } + break; + } +} + +void AsmPrinter::printVisibility(const std::string& Name, + unsigned Visibility) const { + if (Visibility == GlobalValue::HiddenVisibility) { + if (const char *Directive = MAI->getHiddenDirective()) + O << Directive << Name << '\n'; + } else if (Visibility == GlobalValue::ProtectedVisibility) { + if (const char *Directive = MAI->getProtectedDirective()) + O << Directive << Name << '\n'; + } +} + +void AsmPrinter::printOffset(int64_t Offset) const { + if (Offset > 0) + O << '+' << Offset; + else if (Offset < 0) + O << Offset; +} + +GCMetadataPrinter *AsmPrinter::GetOrCreateGCPrinter(GCStrategy *S) { + if (!S->usesMetadata()) + return 0; + + gcp_iterator GCPI = GCMetadataPrinters.find(S); + if (GCPI != GCMetadataPrinters.end()) + return GCPI->second; + + const char *Name = S->getName().c_str(); + + for (GCMetadataPrinterRegistry::iterator + I = GCMetadataPrinterRegistry::begin(), + E = GCMetadataPrinterRegistry::end(); I != E; ++I) + if (strcmp(Name, I->getName()) == 0) { + GCMetadataPrinter *GMP = I->instantiate(); + GMP->S = S; + GCMetadataPrinters.insert(std::make_pair(S, GMP)); + return GMP; + } + + errs() << "no GCMetadataPrinter registered for GC: " << Name << "\n"; + llvm_unreachable(0); +} + +/// EmitComments - Pretty-print comments for instructions +void AsmPrinter::EmitComments(const MachineInstr &MI) const { + if (!VerboseAsm) + return; + + bool Newline = false; + + if (!MI.getDebugLoc().isUnknown()) { + DebugLocTuple DLT = MF->getDebugLocTuple(MI.getDebugLoc()); + + // Print source line info. + O.PadToColumn(MAI->getCommentColumn()); + O << MAI->getCommentString() << " SrcLine "; + if (DLT.Scope) { + DICompileUnit CU(DLT.Scope); + if (!CU.isNull()) + O << CU.getFilename() << " "; + } + O << DLT.Line; + if (DLT.Col != 0) + O << ":" << DLT.Col; + Newline = true; + } + + // Check for spills and reloads + int FI; + + const MachineFrameInfo *FrameInfo = + MI.getParent()->getParent()->getFrameInfo(); + + // We assume a single instruction only has a spill or reload, not + // both. + if (TM.getInstrInfo()->isLoadFromStackSlotPostFE(&MI, FI)) { + if (FrameInfo->isSpillSlotObjectIndex(FI)) { + if (Newline) O << '\n'; + O.PadToColumn(MAI->getCommentColumn()); + O << MAI->getCommentString() << " Reload"; + Newline = true; + } + } + else if (TM.getInstrInfo()->hasLoadFromStackSlot(&MI, FI)) { + if (FrameInfo->isSpillSlotObjectIndex(FI)) { + if (Newline) O << '\n'; + O.PadToColumn(MAI->getCommentColumn()); + O << MAI->getCommentString() << " Folded Reload"; + Newline = true; + } + } + else if (TM.getInstrInfo()->isStoreToStackSlotPostFE(&MI, FI)) { + if (FrameInfo->isSpillSlotObjectIndex(FI)) { + if (Newline) O << '\n'; + O.PadToColumn(MAI->getCommentColumn()); + O << MAI->getCommentString() << " Spill"; + Newline = true; + } + } + else if (TM.getInstrInfo()->hasStoreToStackSlot(&MI, FI)) { + if (FrameInfo->isSpillSlotObjectIndex(FI)) { + if (Newline) O << '\n'; + O.PadToColumn(MAI->getCommentColumn()); + O << MAI->getCommentString() << " Folded Spill"; + Newline = true; + } + } + + // Check for spill-induced copies + unsigned SrcReg, DstReg, SrcSubIdx, DstSubIdx; + if (TM.getInstrInfo()->isMoveInstr(MI, SrcReg, DstReg, + SrcSubIdx, DstSubIdx)) { + if (MI.getAsmPrinterFlag(ReloadReuse)) { + if (Newline) O << '\n'; + O.PadToColumn(MAI->getCommentColumn()); + O << MAI->getCommentString() << " Reload Reuse"; + Newline = true; + } + } +} + +/// PrintChildLoopComment - Print comments about child loops within +/// the loop for this basic block, with nesting. +/// +static void PrintChildLoopComment(formatted_raw_ostream &O, + const MachineLoop *loop, + const MCAsmInfo *MAI, + int FunctionNumber) { + // Add child loop information + for(MachineLoop::iterator cl = loop->begin(), + clend = loop->end(); + cl != clend; + ++cl) { + MachineBasicBlock *Header = (*cl)->getHeader(); + assert(Header && "No header for loop"); + + O << '\n'; + O.PadToColumn(MAI->getCommentColumn()); + + O << MAI->getCommentString(); + O.indent(((*cl)->getLoopDepth()-1)*2) + << " Child Loop BB" << FunctionNumber << "_" + << Header->getNumber() << " Depth " << (*cl)->getLoopDepth(); + + PrintChildLoopComment(O, *cl, MAI, FunctionNumber); + } +} + +/// EmitComments - Pretty-print comments for basic blocks +void AsmPrinter::EmitComments(const MachineBasicBlock &MBB) const { + if (VerboseAsm) { + // Add loop depth information + const MachineLoop *loop = LI->getLoopFor(&MBB); + + if (loop) { + // Print a newline after bb# annotation. + O << "\n"; + O.PadToColumn(MAI->getCommentColumn()); + O << MAI->getCommentString() << " Loop Depth " << loop->getLoopDepth() + << '\n'; + + O.PadToColumn(MAI->getCommentColumn()); + + MachineBasicBlock *Header = loop->getHeader(); + assert(Header && "No header for loop"); + + if (Header == &MBB) { + O << MAI->getCommentString() << " Loop Header"; + PrintChildLoopComment(O, loop, MAI, getFunctionNumber()); + } + else { + O << MAI->getCommentString() << " Loop Header is BB" + << getFunctionNumber() << "_" << loop->getHeader()->getNumber(); + } + + if (loop->empty()) { + O << '\n'; + O.PadToColumn(MAI->getCommentColumn()); + O << MAI->getCommentString() << " Inner Loop"; + } + + // Add parent loop information + for (const MachineLoop *CurLoop = loop->getParentLoop(); + CurLoop; + CurLoop = CurLoop->getParentLoop()) { + MachineBasicBlock *Header = CurLoop->getHeader(); + assert(Header && "No header for loop"); + + O << '\n'; + O.PadToColumn(MAI->getCommentColumn()); + O << MAI->getCommentString(); + O.indent((CurLoop->getLoopDepth()-1)*2) + << " Inside Loop BB" << getFunctionNumber() << "_" + << Header->getNumber() << " Depth " << CurLoop->getLoopDepth(); + } + } + } +} diff --git a/libclamav/c++/llvm/lib/CodeGen/AsmPrinter/CMakeLists.txt b/libclamav/c++/llvm/lib/CodeGen/AsmPrinter/CMakeLists.txt new file mode 100644 index 000000000..066aaab48 --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/AsmPrinter/CMakeLists.txt @@ -0,0 +1,10 @@ +add_llvm_library(LLVMAsmPrinter + AsmPrinter.cpp + DIE.cpp + DwarfDebug.cpp + DwarfException.cpp + DwarfLabel.cpp + DwarfPrinter.cpp + DwarfWriter.cpp + OcamlGCPrinter.cpp + ) diff --git a/libclamav/c++/llvm/lib/CodeGen/AsmPrinter/DIE.cpp b/libclamav/c++/llvm/lib/CodeGen/AsmPrinter/DIE.cpp new file mode 100644 index 000000000..0e93b9849 --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/AsmPrinter/DIE.cpp @@ -0,0 +1,420 @@ +//===--- lib/CodeGen/DIE.cpp - DWARF Info Entries -------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Data structures for DWARF info entries. +// +//===----------------------------------------------------------------------===// + +#include "DIE.h" +#include "DwarfPrinter.h" +#include "llvm/CodeGen/AsmPrinter.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/Format.h" +using namespace llvm; + +//===----------------------------------------------------------------------===// +// DIEAbbrevData Implementation +//===----------------------------------------------------------------------===// + +/// Profile - Used to gather unique data for the abbreviation folding set. +/// +void DIEAbbrevData::Profile(FoldingSetNodeID &ID) const { + ID.AddInteger(Attribute); + ID.AddInteger(Form); +} + +//===----------------------------------------------------------------------===// +// DIEAbbrev Implementation +//===----------------------------------------------------------------------===// + +/// Profile - Used to gather unique data for the abbreviation folding set. +/// +void DIEAbbrev::Profile(FoldingSetNodeID &ID) const { + ID.AddInteger(Tag); + ID.AddInteger(ChildrenFlag); + + // For each attribute description. + for (unsigned i = 0, N = Data.size(); i < N; ++i) + Data[i].Profile(ID); +} + +/// Emit - Print the abbreviation using the specified asm printer. +/// +void DIEAbbrev::Emit(const AsmPrinter *Asm) const { + // Emit its Dwarf tag type. + Asm->EmitULEB128Bytes(Tag); + Asm->EOL(dwarf::TagString(Tag)); + + // Emit whether it has children DIEs. + Asm->EmitULEB128Bytes(ChildrenFlag); + Asm->EOL(dwarf::ChildrenString(ChildrenFlag)); + + // For each attribute description. + for (unsigned i = 0, N = Data.size(); i < N; ++i) { + const DIEAbbrevData &AttrData = Data[i]; + + // Emit attribute type. + Asm->EmitULEB128Bytes(AttrData.getAttribute()); + Asm->EOL(dwarf::AttributeString(AttrData.getAttribute())); + + // Emit form type. + Asm->EmitULEB128Bytes(AttrData.getForm()); + Asm->EOL(dwarf::FormEncodingString(AttrData.getForm())); + } + + // Mark end of abbreviation. + Asm->EmitULEB128Bytes(0); Asm->EOL("EOM(1)"); + Asm->EmitULEB128Bytes(0); Asm->EOL("EOM(2)"); +} + +#ifndef NDEBUG +void DIEAbbrev::print(raw_ostream &O) { + O << "Abbreviation @" + << format("0x%lx", (long)(intptr_t)this) + << " " + << dwarf::TagString(Tag) + << " " + << dwarf::ChildrenString(ChildrenFlag) + << '\n'; + + for (unsigned i = 0, N = Data.size(); i < N; ++i) { + O << " " + << dwarf::AttributeString(Data[i].getAttribute()) + << " " + << dwarf::FormEncodingString(Data[i].getForm()) + << '\n'; + } +} +void DIEAbbrev::dump() { print(errs()); } +#endif + +//===----------------------------------------------------------------------===// +// DIE Implementation +//===----------------------------------------------------------------------===// + +DIE::~DIE() { + for (unsigned i = 0, N = Children.size(); i < N; ++i) + delete Children[i]; +} + +/// addSiblingOffset - Add a sibling offset field to the front of the DIE. +/// +void DIE::addSiblingOffset() { + DIEInteger *DI = new DIEInteger(0); + Values.insert(Values.begin(), DI); + Abbrev.AddFirstAttribute(dwarf::DW_AT_sibling, dwarf::DW_FORM_ref4); +} + +#ifndef NDEBUG +void DIE::print(raw_ostream &O, unsigned IncIndent) { + IndentCount += IncIndent; + const std::string Indent(IndentCount, ' '); + bool isBlock = Abbrev.getTag() == 0; + + if (!isBlock) { + O << Indent + << "Die: " + << format("0x%lx", (long)(intptr_t)this) + << ", Offset: " << Offset + << ", Size: " << Size + << "\n"; + + O << Indent + << dwarf::TagString(Abbrev.getTag()) + << " " + << dwarf::ChildrenString(Abbrev.getChildrenFlag()); + } else { + O << "Size: " << Size; + } + O << "\n"; + + const SmallVector &Data = Abbrev.getData(); + + IndentCount += 2; + for (unsigned i = 0, N = Data.size(); i < N; ++i) { + O << Indent; + + if (!isBlock) + O << dwarf::AttributeString(Data[i].getAttribute()); + else + O << "Blk[" << i << "]"; + + O << " " + << dwarf::FormEncodingString(Data[i].getForm()) + << " "; + Values[i]->print(O); + O << "\n"; + } + IndentCount -= 2; + + for (unsigned j = 0, M = Children.size(); j < M; ++j) { + Children[j]->print(O, 4); + } + + if (!isBlock) O << "\n"; + IndentCount -= IncIndent; +} + +void DIE::dump() { + print(errs()); +} +#endif + + +#ifndef NDEBUG +void DIEValue::dump() { + print(errs()); +} +#endif + +//===----------------------------------------------------------------------===// +// DIEInteger Implementation +//===----------------------------------------------------------------------===// + +/// EmitValue - Emit integer of appropriate size. +/// +void DIEInteger::EmitValue(Dwarf *D, unsigned Form) const { + const AsmPrinter *Asm = D->getAsm(); + switch (Form) { + case dwarf::DW_FORM_flag: // Fall thru + case dwarf::DW_FORM_ref1: // Fall thru + case dwarf::DW_FORM_data1: Asm->EmitInt8(Integer); break; + case dwarf::DW_FORM_ref2: // Fall thru + case dwarf::DW_FORM_data2: Asm->EmitInt16(Integer); break; + case dwarf::DW_FORM_ref4: // Fall thru + case dwarf::DW_FORM_data4: Asm->EmitInt32(Integer); break; + case dwarf::DW_FORM_ref8: // Fall thru + case dwarf::DW_FORM_data8: Asm->EmitInt64(Integer); break; + case dwarf::DW_FORM_udata: Asm->EmitULEB128Bytes(Integer); break; + case dwarf::DW_FORM_sdata: Asm->EmitSLEB128Bytes(Integer); break; + default: llvm_unreachable("DIE Value form not supported yet"); + } +} + +/// SizeOf - Determine size of integer value in bytes. +/// +unsigned DIEInteger::SizeOf(const TargetData *TD, unsigned Form) const { + switch (Form) { + case dwarf::DW_FORM_flag: // Fall thru + case dwarf::DW_FORM_ref1: // Fall thru + case dwarf::DW_FORM_data1: return sizeof(int8_t); + case dwarf::DW_FORM_ref2: // Fall thru + case dwarf::DW_FORM_data2: return sizeof(int16_t); + case dwarf::DW_FORM_ref4: // Fall thru + case dwarf::DW_FORM_data4: return sizeof(int32_t); + case dwarf::DW_FORM_ref8: // Fall thru + case dwarf::DW_FORM_data8: return sizeof(int64_t); + case dwarf::DW_FORM_udata: return MCAsmInfo::getULEB128Size(Integer); + case dwarf::DW_FORM_sdata: return MCAsmInfo::getSLEB128Size(Integer); + default: llvm_unreachable("DIE Value form not supported yet"); break; + } + return 0; +} + +#ifndef NDEBUG +void DIEInteger::print(raw_ostream &O) { + O << "Int: " << (int64_t)Integer + << format(" 0x%llx", (unsigned long long)Integer); +} +#endif + +//===----------------------------------------------------------------------===// +// DIEString Implementation +//===----------------------------------------------------------------------===// + +/// EmitValue - Emit string value. +/// +void DIEString::EmitValue(Dwarf *D, unsigned Form) const { + D->getAsm()->EmitString(Str); +} + +#ifndef NDEBUG +void DIEString::print(raw_ostream &O) { + O << "Str: \"" << Str << "\""; +} +#endif + +//===----------------------------------------------------------------------===// +// DIEDwarfLabel Implementation +//===----------------------------------------------------------------------===// + +/// EmitValue - Emit label value. +/// +void DIEDwarfLabel::EmitValue(Dwarf *D, unsigned Form) const { + bool IsSmall = Form == dwarf::DW_FORM_data4; + D->EmitReference(Label, false, IsSmall); +} + +/// SizeOf - Determine size of label value in bytes. +/// +unsigned DIEDwarfLabel::SizeOf(const TargetData *TD, unsigned Form) const { + if (Form == dwarf::DW_FORM_data4) return 4; + return TD->getPointerSize(); +} + +#ifndef NDEBUG +void DIEDwarfLabel::print(raw_ostream &O) { + O << "Lbl: "; + Label.print(O); +} +#endif + +//===----------------------------------------------------------------------===// +// DIEObjectLabel Implementation +//===----------------------------------------------------------------------===// + +/// EmitValue - Emit label value. +/// +void DIEObjectLabel::EmitValue(Dwarf *D, unsigned Form) const { + bool IsSmall = Form == dwarf::DW_FORM_data4; + D->EmitReference(Label, false, IsSmall); +} + +/// SizeOf - Determine size of label value in bytes. +/// +unsigned DIEObjectLabel::SizeOf(const TargetData *TD, unsigned Form) const { + if (Form == dwarf::DW_FORM_data4) return 4; + return TD->getPointerSize(); +} + +#ifndef NDEBUG +void DIEObjectLabel::print(raw_ostream &O) { + O << "Obj: " << Label; +} +#endif + +//===----------------------------------------------------------------------===// +// DIESectionOffset Implementation +//===----------------------------------------------------------------------===// + +/// EmitValue - Emit delta value. +/// +void DIESectionOffset::EmitValue(Dwarf *D, unsigned Form) const { + bool IsSmall = Form == dwarf::DW_FORM_data4; + D->EmitSectionOffset(Label.getTag(), Section.getTag(), + Label.getNumber(), Section.getNumber(), + IsSmall, IsEH, UseSet); +} + +/// SizeOf - Determine size of delta value in bytes. +/// +unsigned DIESectionOffset::SizeOf(const TargetData *TD, unsigned Form) const { + if (Form == dwarf::DW_FORM_data4) return 4; + return TD->getPointerSize(); +} + +#ifndef NDEBUG +void DIESectionOffset::print(raw_ostream &O) { + O << "Off: "; + Label.print(O); + O << "-"; + Section.print(O); + O << "-" << IsEH << "-" << UseSet; +} +#endif + +//===----------------------------------------------------------------------===// +// DIEDelta Implementation +//===----------------------------------------------------------------------===// + +/// EmitValue - Emit delta value. +/// +void DIEDelta::EmitValue(Dwarf *D, unsigned Form) const { + bool IsSmall = Form == dwarf::DW_FORM_data4; + D->EmitDifference(LabelHi, LabelLo, IsSmall); +} + +/// SizeOf - Determine size of delta value in bytes. +/// +unsigned DIEDelta::SizeOf(const TargetData *TD, unsigned Form) const { + if (Form == dwarf::DW_FORM_data4) return 4; + return TD->getPointerSize(); +} + +#ifndef NDEBUG +void DIEDelta::print(raw_ostream &O) { + O << "Del: "; + LabelHi.print(O); + O << "-"; + LabelLo.print(O); +} +#endif + +//===----------------------------------------------------------------------===// +// DIEEntry Implementation +//===----------------------------------------------------------------------===// + +/// EmitValue - Emit debug information entry offset. +/// +void DIEEntry::EmitValue(Dwarf *D, unsigned Form) const { + D->getAsm()->EmitInt32(Entry->getOffset()); +} + +#ifndef NDEBUG +void DIEEntry::print(raw_ostream &O) { + O << format("Die: 0x%lx", (long)(intptr_t)Entry); +} +#endif + +//===----------------------------------------------------------------------===// +// DIEBlock Implementation +//===----------------------------------------------------------------------===// + +/// ComputeSize - calculate the size of the block. +/// +unsigned DIEBlock::ComputeSize(const TargetData *TD) { + if (!Size) { + const SmallVector &AbbrevData = Abbrev.getData(); + for (unsigned i = 0, N = Values.size(); i < N; ++i) + Size += Values[i]->SizeOf(TD, AbbrevData[i].getForm()); + } + + return Size; +} + +/// EmitValue - Emit block data. +/// +void DIEBlock::EmitValue(Dwarf *D, unsigned Form) const { + const AsmPrinter *Asm = D->getAsm(); + switch (Form) { + case dwarf::DW_FORM_block1: Asm->EmitInt8(Size); break; + case dwarf::DW_FORM_block2: Asm->EmitInt16(Size); break; + case dwarf::DW_FORM_block4: Asm->EmitInt32(Size); break; + case dwarf::DW_FORM_block: Asm->EmitULEB128Bytes(Size); break; + default: llvm_unreachable("Improper form for block"); break; + } + + const SmallVector &AbbrevData = Abbrev.getData(); + for (unsigned i = 0, N = Values.size(); i < N; ++i) { + Asm->EOL(); + Values[i]->EmitValue(D, AbbrevData[i].getForm()); + } +} + +/// SizeOf - Determine size of block data in bytes. +/// +unsigned DIEBlock::SizeOf(const TargetData *TD, unsigned Form) const { + switch (Form) { + case dwarf::DW_FORM_block1: return Size + sizeof(int8_t); + case dwarf::DW_FORM_block2: return Size + sizeof(int16_t); + case dwarf::DW_FORM_block4: return Size + sizeof(int32_t); + case dwarf::DW_FORM_block: return Size + MCAsmInfo::getULEB128Size(Size); + default: llvm_unreachable("Improper form for block"); break; + } + return 0; +} + +#ifndef NDEBUG +void DIEBlock::print(raw_ostream &O) { + O << "Blk: "; + DIE::print(O, 5); +} +#endif diff --git a/libclamav/c++/llvm/lib/CodeGen/AsmPrinter/DIE.h b/libclamav/c++/llvm/lib/CodeGen/AsmPrinter/DIE.h new file mode 100644 index 000000000..dc6a70a6b --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/AsmPrinter/DIE.h @@ -0,0 +1,489 @@ +//===--- lib/CodeGen/DIE.h - DWARF Info Entries -----------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Data structures for DWARF info entries. +// +//===----------------------------------------------------------------------===// + +#ifndef CODEGEN_ASMPRINTER_DIE_H__ +#define CODEGEN_ASMPRINTER_DIE_H__ + +#include "DwarfLabel.h" +#include "llvm/ADT/FoldingSet.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/Dwarf.h" +#include + +namespace llvm { + class AsmPrinter; + class Dwarf; + class TargetData; + + //===--------------------------------------------------------------------===// + /// DIEAbbrevData - Dwarf abbreviation data, describes the one attribute of a + /// Dwarf abbreviation. + class DIEAbbrevData { + /// Attribute - Dwarf attribute code. + /// + unsigned Attribute; + + /// Form - Dwarf form code. + /// + unsigned Form; + public: + DIEAbbrevData(unsigned A, unsigned F) : Attribute(A), Form(F) {} + + // Accessors. + unsigned getAttribute() const { return Attribute; } + unsigned getForm() const { return Form; } + + /// Profile - Used to gather unique data for the abbreviation folding set. + /// + void Profile(FoldingSetNodeID &ID) const; + }; + + //===--------------------------------------------------------------------===// + /// DIEAbbrev - Dwarf abbreviation, describes the organization of a debug + /// information object. + class DIEAbbrev : public FoldingSetNode { + /// Tag - Dwarf tag code. + /// + unsigned Tag; + + /// Unique number for node. + /// + unsigned Number; + + /// ChildrenFlag - Dwarf children flag. + /// + unsigned ChildrenFlag; + + /// Data - Raw data bytes for abbreviation. + /// + SmallVector Data; + public: + DIEAbbrev(unsigned T, unsigned C) : Tag(T), ChildrenFlag(C), Data() {} + virtual ~DIEAbbrev() {} + + // Accessors. + unsigned getTag() const { return Tag; } + unsigned getNumber() const { return Number; } + unsigned getChildrenFlag() const { return ChildrenFlag; } + const SmallVector &getData() const { return Data; } + void setTag(unsigned T) { Tag = T; } + void setChildrenFlag(unsigned CF) { ChildrenFlag = CF; } + void setNumber(unsigned N) { Number = N; } + + /// AddAttribute - Adds another set of attribute information to the + /// abbreviation. + void AddAttribute(unsigned Attribute, unsigned Form) { + Data.push_back(DIEAbbrevData(Attribute, Form)); + } + + /// AddFirstAttribute - Adds a set of attribute information to the front + /// of the abbreviation. + void AddFirstAttribute(unsigned Attribute, unsigned Form) { + Data.insert(Data.begin(), DIEAbbrevData(Attribute, Form)); + } + + /// Profile - Used to gather unique data for the abbreviation folding set. + /// + void Profile(FoldingSetNodeID &ID) const; + + /// Emit - Print the abbreviation using the specified asm printer. + /// + void Emit(const AsmPrinter *Asm) const; + +#ifndef NDEBUG + void print(raw_ostream &O); + void dump(); +#endif + }; + + //===--------------------------------------------------------------------===// + /// DIE - A structured debug information entry. Has an abbreviation which + /// describes it's organization. + class CompileUnit; + class DIEValue; + + class DIE { + protected: + /// Abbrev - Buffer for constructing abbreviation. + /// + DIEAbbrev Abbrev; + + /// Offset - Offset in debug info section. + /// + unsigned Offset; + + /// Size - Size of instance + children. + /// + unsigned Size; + + /// Children DIEs. + /// + std::vector Children; + + /// Attributes values. + /// + SmallVector Values; + + /// Abstract compile unit. + CompileUnit *AbstractCU; + + // Private data for print() + mutable unsigned IndentCount; + public: + explicit DIE(unsigned Tag) + : Abbrev(Tag, dwarf::DW_CHILDREN_no), Offset(0), + Size(0), IndentCount(0) {} + virtual ~DIE(); + + // Accessors. + DIEAbbrev &getAbbrev() { return Abbrev; } + unsigned getAbbrevNumber() const { return Abbrev.getNumber(); } + unsigned getTag() const { return Abbrev.getTag(); } + unsigned getOffset() const { return Offset; } + unsigned getSize() const { return Size; } + const std::vector &getChildren() const { return Children; } + SmallVector &getValues() { return Values; } + CompileUnit *getAbstractCompileUnit() const { return AbstractCU; } + + void setTag(unsigned Tag) { Abbrev.setTag(Tag); } + void setOffset(unsigned O) { Offset = O; } + void setSize(unsigned S) { Size = S; } + void setAbstractCompileUnit(CompileUnit *CU) { AbstractCU = CU; } + + /// addValue - Add a value and attributes to a DIE. + /// + void addValue(unsigned Attribute, unsigned Form, DIEValue *Value) { + Abbrev.AddAttribute(Attribute, Form); + Values.push_back(Value); + } + + /// SiblingOffset - Return the offset of the debug information entry's + /// sibling. + unsigned getSiblingOffset() const { return Offset + Size; } + + /// addSiblingOffset - Add a sibling offset field to the front of the DIE. + /// + void addSiblingOffset(); + + /// addChild - Add a child to the DIE. + /// + void addChild(DIE *Child) { + Abbrev.setChildrenFlag(dwarf::DW_CHILDREN_yes); + Children.push_back(Child); + } + +#ifndef NDEBUG + void print(raw_ostream &O, unsigned IncIndent = 0); + void dump(); +#endif + }; + + //===--------------------------------------------------------------------===// + /// DIEValue - A debug information entry value. + /// + class DIEValue { + public: + enum { + isInteger, + isString, + isLabel, + isAsIsLabel, + isSectionOffset, + isDelta, + isEntry, + isBlock + }; + protected: + /// Type - Type of data stored in the value. + /// + unsigned Type; + public: + explicit DIEValue(unsigned T) : Type(T) {} + virtual ~DIEValue() {} + + // Accessors + unsigned getType() const { return Type; } + + /// EmitValue - Emit value via the Dwarf writer. + /// + virtual void EmitValue(Dwarf *D, unsigned Form) const = 0; + + /// SizeOf - Return the size of a value in bytes. + /// + virtual unsigned SizeOf(const TargetData *TD, unsigned Form) const = 0; + + // Implement isa/cast/dyncast. + static bool classof(const DIEValue *) { return true; } + +#ifndef NDEBUG + virtual void print(raw_ostream &O) = 0; + void dump(); +#endif + }; + + //===--------------------------------------------------------------------===// + /// DIEInteger - An integer value DIE. + /// + class DIEInteger : public DIEValue { + uint64_t Integer; + public: + explicit DIEInteger(uint64_t I) : DIEValue(isInteger), Integer(I) {} + + /// BestForm - Choose the best form for integer. + /// + static unsigned BestForm(bool IsSigned, uint64_t Int) { + if (IsSigned) { + if ((char)Int == (signed)Int) return dwarf::DW_FORM_data1; + if ((short)Int == (signed)Int) return dwarf::DW_FORM_data2; + if ((int)Int == (signed)Int) return dwarf::DW_FORM_data4; + } else { + if ((unsigned char)Int == Int) return dwarf::DW_FORM_data1; + if ((unsigned short)Int == Int) return dwarf::DW_FORM_data2; + if ((unsigned int)Int == Int) return dwarf::DW_FORM_data4; + } + return dwarf::DW_FORM_data8; + } + + /// EmitValue - Emit integer of appropriate size. + /// + virtual void EmitValue(Dwarf *D, unsigned Form) const; + + /// SizeOf - Determine size of integer value in bytes. + /// + virtual unsigned SizeOf(const TargetData *TD, unsigned Form) const; + + + // Implement isa/cast/dyncast. + static bool classof(const DIEInteger *) { return true; } + static bool classof(const DIEValue *I) { return I->getType() == isInteger; } + +#ifndef NDEBUG + virtual void print(raw_ostream &O); +#endif + }; + + //===--------------------------------------------------------------------===// + /// DIEString - A string value DIE. + /// + class DIEString : public DIEValue { + const StringRef Str; + public: + explicit DIEString(const StringRef S) : DIEValue(isString), Str(S) {} + + /// EmitValue - Emit string value. + /// + virtual void EmitValue(Dwarf *D, unsigned Form) const; + + /// SizeOf - Determine size of string value in bytes. + /// + virtual unsigned SizeOf(const TargetData *, unsigned /*Form*/) const { + return Str.size() + sizeof(char); // sizeof('\0'); + } + + // Implement isa/cast/dyncast. + static bool classof(const DIEString *) { return true; } + static bool classof(const DIEValue *S) { return S->getType() == isString; } + +#ifndef NDEBUG + virtual void print(raw_ostream &O); +#endif + }; + + //===--------------------------------------------------------------------===// + /// DIEDwarfLabel - A Dwarf internal label expression DIE. + // + class DIEDwarfLabel : public DIEValue { + const DWLabel Label; + public: + explicit DIEDwarfLabel(const DWLabel &L) : DIEValue(isLabel), Label(L) {} + + /// EmitValue - Emit label value. + /// + virtual void EmitValue(Dwarf *D, unsigned Form) const; + + /// SizeOf - Determine size of label value in bytes. + /// + virtual unsigned SizeOf(const TargetData *TD, unsigned Form) const; + + // Implement isa/cast/dyncast. + static bool classof(const DIEDwarfLabel *) { return true; } + static bool classof(const DIEValue *L) { return L->getType() == isLabel; } + +#ifndef NDEBUG + virtual void print(raw_ostream &O); +#endif + }; + + //===--------------------------------------------------------------------===// + /// DIEObjectLabel - A label to an object in code or data. + // + class DIEObjectLabel : public DIEValue { + const std::string Label; + public: + explicit DIEObjectLabel(const std::string &L) + : DIEValue(isAsIsLabel), Label(L) {} + + /// EmitValue - Emit label value. + /// + virtual void EmitValue(Dwarf *D, unsigned Form) const; + + /// SizeOf - Determine size of label value in bytes. + /// + virtual unsigned SizeOf(const TargetData *TD, unsigned Form) const; + + // Implement isa/cast/dyncast. + static bool classof(const DIEObjectLabel *) { return true; } + static bool classof(const DIEValue *L) { + return L->getType() == isAsIsLabel; + } + +#ifndef NDEBUG + virtual void print(raw_ostream &O); +#endif + }; + + //===--------------------------------------------------------------------===// + /// DIESectionOffset - A section offset DIE. + /// + class DIESectionOffset : public DIEValue { + const DWLabel Label; + const DWLabel Section; + bool IsEH : 1; + bool UseSet : 1; + public: + DIESectionOffset(const DWLabel &Lab, const DWLabel &Sec, + bool isEH = false, bool useSet = true) + : DIEValue(isSectionOffset), Label(Lab), Section(Sec), + IsEH(isEH), UseSet(useSet) {} + + /// EmitValue - Emit section offset. + /// + virtual void EmitValue(Dwarf *D, unsigned Form) const; + + /// SizeOf - Determine size of section offset value in bytes. + /// + virtual unsigned SizeOf(const TargetData *TD, unsigned Form) const; + + // Implement isa/cast/dyncast. + static bool classof(const DIESectionOffset *) { return true; } + static bool classof(const DIEValue *D) { + return D->getType() == isSectionOffset; + } + +#ifndef NDEBUG + virtual void print(raw_ostream &O); +#endif + }; + + //===--------------------------------------------------------------------===// + /// DIEDelta - A simple label difference DIE. + /// + class DIEDelta : public DIEValue { + const DWLabel LabelHi; + const DWLabel LabelLo; + public: + DIEDelta(const DWLabel &Hi, const DWLabel &Lo) + : DIEValue(isDelta), LabelHi(Hi), LabelLo(Lo) {} + + /// EmitValue - Emit delta value. + /// + virtual void EmitValue(Dwarf *D, unsigned Form) const; + + /// SizeOf - Determine size of delta value in bytes. + /// + virtual unsigned SizeOf(const TargetData *TD, unsigned Form) const; + + // Implement isa/cast/dyncast. + static bool classof(const DIEDelta *) { return true; } + static bool classof(const DIEValue *D) { return D->getType() == isDelta; } + +#ifndef NDEBUG + virtual void print(raw_ostream &O); +#endif + }; + + //===--------------------------------------------------------------------===// + /// DIEntry - A pointer to another debug information entry. An instance of + /// this class can also be used as a proxy for a debug information entry not + /// yet defined (ie. types.) + class DIEEntry : public DIEValue { + DIE *Entry; + public: + explicit DIEEntry(DIE *E) : DIEValue(isEntry), Entry(E) {} + + DIE *getEntry() const { return Entry; } + void setEntry(DIE *E) { Entry = E; } + + /// EmitValue - Emit debug information entry offset. + /// + virtual void EmitValue(Dwarf *D, unsigned Form) const; + + /// SizeOf - Determine size of debug information entry in bytes. + /// + virtual unsigned SizeOf(const TargetData *TD, unsigned Form) const { + return sizeof(int32_t); + } + + // Implement isa/cast/dyncast. + static bool classof(const DIEEntry *) { return true; } + static bool classof(const DIEValue *E) { return E->getType() == isEntry; } + +#ifndef NDEBUG + virtual void print(raw_ostream &O); +#endif + }; + + //===--------------------------------------------------------------------===// + /// DIEBlock - A block of values. Primarily used for location expressions. + // + class DIEBlock : public DIEValue, public DIE { + unsigned Size; // Size in bytes excluding size header. + public: + DIEBlock() + : DIEValue(isBlock), DIE(0), Size(0) {} + virtual ~DIEBlock() {} + + /// ComputeSize - calculate the size of the block. + /// + unsigned ComputeSize(const TargetData *TD); + + /// BestForm - Choose the best form for data. + /// + unsigned BestForm() const { + if ((unsigned char)Size == Size) return dwarf::DW_FORM_block1; + if ((unsigned short)Size == Size) return dwarf::DW_FORM_block2; + if ((unsigned int)Size == Size) return dwarf::DW_FORM_block4; + return dwarf::DW_FORM_block; + } + + /// EmitValue - Emit block data. + /// + virtual void EmitValue(Dwarf *D, unsigned Form) const; + + /// SizeOf - Determine size of block data in bytes. + /// + virtual unsigned SizeOf(const TargetData *TD, unsigned Form) const; + + // Implement isa/cast/dyncast. + static bool classof(const DIEBlock *) { return true; } + static bool classof(const DIEValue *E) { return E->getType() == isBlock; } + +#ifndef NDEBUG + virtual void print(raw_ostream &O); +#endif + }; + +} // end llvm namespace + +#endif diff --git a/libclamav/c++/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/libclamav/c++/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp new file mode 100644 index 000000000..9dad574aa --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -0,0 +1,2931 @@ +//===-- llvm/CodeGen/DwarfDebug.cpp - Dwarf Debug Framework ---------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains support for writing dwarf debug info into asm files. +// +//===----------------------------------------------------------------------===// +#define DEBUG_TYPE "dwarfdebug" +#include "DwarfDebug.h" +#include "llvm/Module.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/MC/MCSection.h" +#include "llvm/MC/MCStreamer.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetFrameInfo.h" +#include "llvm/Target/TargetLoweringObjectFile.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/Mangler.h" +#include "llvm/Support/Timer.h" +#include "llvm/System/Path.h" +using namespace llvm; + +static TimerGroup &getDwarfTimerGroup() { + static TimerGroup DwarfTimerGroup("Dwarf Debugging"); + return DwarfTimerGroup; +} + +//===----------------------------------------------------------------------===// + +/// Configuration values for initial hash set sizes (log2). +/// +static const unsigned InitAbbreviationsSetSize = 9; // log2(512) + +namespace llvm { + +//===----------------------------------------------------------------------===// +/// CompileUnit - This dwarf writer support class manages information associate +/// with a source file. +class CompileUnit { + /// ID - File identifier for source. + /// + unsigned ID; + + /// Die - Compile unit debug information entry. + /// + DIE *CUDie; + + /// IndexTyDie - An anonymous type for index type. + DIE *IndexTyDie; + + /// GVToDieMap - Tracks the mapping of unit level debug informaton + /// variables to debug information entries. + /// FIXME : Rename GVToDieMap -> NodeToDieMap + ValueMap GVToDieMap; + + /// GVToDIEEntryMap - Tracks the mapping of unit level debug informaton + /// descriptors to debug information entries using a DIEEntry proxy. + /// FIXME : Rename + ValueMap GVToDIEEntryMap; + + /// Globals - A map of globally visible named entities for this unit. + /// + StringMap Globals; + + /// GlobalTypes - A map of globally visible types for this unit. + /// + StringMap GlobalTypes; + +public: + CompileUnit(unsigned I, DIE *D) + : ID(I), CUDie(D), IndexTyDie(0) {} + ~CompileUnit() { delete CUDie; delete IndexTyDie; } + + // Accessors. + unsigned getID() const { return ID; } + DIE* getCUDie() const { return CUDie; } + const StringMap &getGlobals() const { return Globals; } + const StringMap &getGlobalTypes() const { return GlobalTypes; } + + /// hasContent - Return true if this compile unit has something to write out. + /// + bool hasContent() const { return !CUDie->getChildren().empty(); } + + /// addGlobal - Add a new global entity to the compile unit. + /// + void addGlobal(const std::string &Name, DIE *Die) { Globals[Name] = Die; } + + /// addGlobalType - Add a new global type to the compile unit. + /// + void addGlobalType(const std::string &Name, DIE *Die) { + GlobalTypes[Name] = Die; + } + + /// getDIE - Returns the debug information entry map slot for the + /// specified debug variable. + DIE *getDIE(MDNode *N) { return GVToDieMap.lookup(N); } + + /// insertDIE - Insert DIE into the map. + void insertDIE(MDNode *N, DIE *D) { + GVToDieMap.insert(std::make_pair(N, D)); + } + + /// getDIEEntry - Returns the debug information entry for the speciefied + /// debug variable. + DIEEntry *getDIEEntry(MDNode *N) { return GVToDIEEntryMap.lookup(N); } + + /// insertDIEEntry - Insert debug information entry into the map. + void insertDIEEntry(MDNode *N, DIEEntry *E) { + GVToDIEEntryMap.insert(std::make_pair(N, E)); + } + + /// addDie - Adds or interns the DIE to the compile unit. + /// + void addDie(DIE *Buffer) { + this->CUDie->addChild(Buffer); + } + + // getIndexTyDie - Get an anonymous type for index type. + DIE *getIndexTyDie() { + return IndexTyDie; + } + + // setIndexTyDie - Set D as anonymous type for index which can be reused + // later. + void setIndexTyDie(DIE *D) { + IndexTyDie = D; + } + +}; + +//===----------------------------------------------------------------------===// +/// DbgVariable - This class is used to track local variable information. +/// +class DbgVariable { + DIVariable Var; // Variable Descriptor. + unsigned FrameIndex; // Variable frame index. + DbgVariable *AbstractVar; // Abstract variable for this variable. + DIE *TheDIE; +public: + DbgVariable(DIVariable V, unsigned I) + : Var(V), FrameIndex(I), AbstractVar(0), TheDIE(0) {} + + // Accessors. + DIVariable getVariable() const { return Var; } + unsigned getFrameIndex() const { return FrameIndex; } + void setAbstractVariable(DbgVariable *V) { AbstractVar = V; } + DbgVariable *getAbstractVariable() const { return AbstractVar; } + void setDIE(DIE *D) { TheDIE = D; } + DIE *getDIE() const { return TheDIE; } +}; + +//===----------------------------------------------------------------------===// +/// DbgScope - This class is used to track scope information. +/// +class DbgScope { + DbgScope *Parent; // Parent to this scope. + DIDescriptor Desc; // Debug info descriptor for scope. + WeakVH InlinedAtLocation; // Location at which scope is inlined. + bool AbstractScope; // Abstract Scope + unsigned StartLabelID; // Label ID of the beginning of scope. + unsigned EndLabelID; // Label ID of the end of scope. + const MachineInstr *LastInsn; // Last instruction of this scope. + const MachineInstr *FirstInsn; // First instruction of this scope. + SmallVector Scopes; // Scopes defined in scope. + SmallVector Variables;// Variables declared in scope. + + // Private state for dump() + mutable unsigned IndentLevel; +public: + DbgScope(DbgScope *P, DIDescriptor D, MDNode *I = 0) + : Parent(P), Desc(D), InlinedAtLocation(I), AbstractScope(false), + StartLabelID(0), EndLabelID(0), + LastInsn(0), FirstInsn(0), IndentLevel(0) {} + virtual ~DbgScope(); + + // Accessors. + DbgScope *getParent() const { return Parent; } + void setParent(DbgScope *P) { Parent = P; } + DIDescriptor getDesc() const { return Desc; } + MDNode *getInlinedAt() const { + return dyn_cast_or_null(InlinedAtLocation); + } + MDNode *getScopeNode() const { return Desc.getNode(); } + unsigned getStartLabelID() const { return StartLabelID; } + unsigned getEndLabelID() const { return EndLabelID; } + SmallVector &getScopes() { return Scopes; } + SmallVector &getVariables() { return Variables; } + void setStartLabelID(unsigned S) { StartLabelID = S; } + void setEndLabelID(unsigned E) { EndLabelID = E; } + void setLastInsn(const MachineInstr *MI) { LastInsn = MI; } + const MachineInstr *getLastInsn() { return LastInsn; } + void setFirstInsn(const MachineInstr *MI) { FirstInsn = MI; } + void setAbstractScope() { AbstractScope = true; } + bool isAbstractScope() const { return AbstractScope; } + const MachineInstr *getFirstInsn() { return FirstInsn; } + + /// addScope - Add a scope to the scope. + /// + void addScope(DbgScope *S) { Scopes.push_back(S); } + + /// addVariable - Add a variable to the scope. + /// + void addVariable(DbgVariable *V) { Variables.push_back(V); } + + void fixInstructionMarkers() { + assert (getFirstInsn() && "First instruction is missing!"); + if (getLastInsn()) + return; + + // If a scope does not have an instruction to mark an end then use + // the end of last child scope. + SmallVector &Scopes = getScopes(); + assert (!Scopes.empty() && "Inner most scope does not have last insn!"); + DbgScope *L = Scopes.back(); + if (!L->getLastInsn()) + L->fixInstructionMarkers(); + setLastInsn(L->getLastInsn()); + } + +#ifndef NDEBUG + void dump() const; +#endif +}; + +#ifndef NDEBUG +void DbgScope::dump() const { + raw_ostream &err = errs(); + err.indent(IndentLevel); + MDNode *N = Desc.getNode(); + N->dump(); + err << " [" << StartLabelID << ", " << EndLabelID << "]\n"; + if (AbstractScope) + err << "Abstract Scope\n"; + + IndentLevel += 2; + if (!Scopes.empty()) + err << "Children ...\n"; + for (unsigned i = 0, e = Scopes.size(); i != e; ++i) + if (Scopes[i] != this) + Scopes[i]->dump(); + + IndentLevel -= 2; +} +#endif + +DbgScope::~DbgScope() { + for (unsigned i = 0, N = Scopes.size(); i < N; ++i) + delete Scopes[i]; + for (unsigned j = 0, M = Variables.size(); j < M; ++j) + delete Variables[j]; +} + +} // end llvm namespace + +DwarfDebug::DwarfDebug(raw_ostream &OS, AsmPrinter *A, const MCAsmInfo *T) + : Dwarf(OS, A, T, "dbg"), ModuleCU(0), + AbbreviationsSet(InitAbbreviationsSetSize), Abbreviations(), + DIEValues(), StringPool(), + SectionSourceLines(), didInitial(false), shouldEmit(false), + CurrentFnDbgScope(0), DebugTimer(0) { + if (TimePassesIsEnabled) + DebugTimer = new Timer("Dwarf Debug Writer", + getDwarfTimerGroup()); +} +DwarfDebug::~DwarfDebug() { + for (unsigned j = 0, M = DIEValues.size(); j < M; ++j) + delete DIEValues[j]; + + delete DebugTimer; +} + +/// assignAbbrevNumber - Define a unique number for the abbreviation. +/// +void DwarfDebug::assignAbbrevNumber(DIEAbbrev &Abbrev) { + // Profile the node so that we can make it unique. + FoldingSetNodeID ID; + Abbrev.Profile(ID); + + // Check the set for priors. + DIEAbbrev *InSet = AbbreviationsSet.GetOrInsertNode(&Abbrev); + + // If it's newly added. + if (InSet == &Abbrev) { + // Add to abbreviation list. + Abbreviations.push_back(&Abbrev); + + // Assign the vector position + 1 as its number. + Abbrev.setNumber(Abbreviations.size()); + } else { + // Assign existing abbreviation number. + Abbrev.setNumber(InSet->getNumber()); + } +} + +/// createDIEEntry - Creates a new DIEEntry to be a proxy for a debug +/// information entry. +DIEEntry *DwarfDebug::createDIEEntry(DIE *Entry) { + DIEEntry *Value = new DIEEntry(Entry); + DIEValues.push_back(Value); + return Value; +} + +/// addUInt - Add an unsigned integer attribute data and value. +/// +void DwarfDebug::addUInt(DIE *Die, unsigned Attribute, + unsigned Form, uint64_t Integer) { + if (!Form) Form = DIEInteger::BestForm(false, Integer); + DIEValue *Value = new DIEInteger(Integer); + DIEValues.push_back(Value); + Die->addValue(Attribute, Form, Value); +} + +/// addSInt - Add an signed integer attribute data and value. +/// +void DwarfDebug::addSInt(DIE *Die, unsigned Attribute, + unsigned Form, int64_t Integer) { + if (!Form) Form = DIEInteger::BestForm(true, Integer); + DIEValue *Value = new DIEInteger(Integer); + DIEValues.push_back(Value); + Die->addValue(Attribute, Form, Value); +} + +/// addString - Add a string attribute data and value. +/// +void DwarfDebug::addString(DIE *Die, unsigned Attribute, unsigned Form, + const StringRef String) { + DIEValue *Value = new DIEString(String); + DIEValues.push_back(Value); + Die->addValue(Attribute, Form, Value); +} + +/// addLabel - Add a Dwarf label attribute data and value. +/// +void DwarfDebug::addLabel(DIE *Die, unsigned Attribute, unsigned Form, + const DWLabel &Label) { + DIEValue *Value = new DIEDwarfLabel(Label); + DIEValues.push_back(Value); + Die->addValue(Attribute, Form, Value); +} + +/// addObjectLabel - Add an non-Dwarf label attribute data and value. +/// +void DwarfDebug::addObjectLabel(DIE *Die, unsigned Attribute, unsigned Form, + const std::string &Label) { + DIEValue *Value = new DIEObjectLabel(Label); + DIEValues.push_back(Value); + Die->addValue(Attribute, Form, Value); +} + +/// addSectionOffset - Add a section offset label attribute data and value. +/// +void DwarfDebug::addSectionOffset(DIE *Die, unsigned Attribute, unsigned Form, + const DWLabel &Label, const DWLabel &Section, + bool isEH, bool useSet) { + DIEValue *Value = new DIESectionOffset(Label, Section, isEH, useSet); + DIEValues.push_back(Value); + Die->addValue(Attribute, Form, Value); +} + +/// addDelta - Add a label delta attribute data and value. +/// +void DwarfDebug::addDelta(DIE *Die, unsigned Attribute, unsigned Form, + const DWLabel &Hi, const DWLabel &Lo) { + DIEValue *Value = new DIEDelta(Hi, Lo); + DIEValues.push_back(Value); + Die->addValue(Attribute, Form, Value); +} + +/// addBlock - Add block data. +/// +void DwarfDebug::addBlock(DIE *Die, unsigned Attribute, unsigned Form, + DIEBlock *Block) { + Block->ComputeSize(TD); + DIEValues.push_back(Block); + Die->addValue(Attribute, Block->BestForm(), Block); +} + +/// addSourceLine - Add location information to specified debug information +/// entry. +void DwarfDebug::addSourceLine(DIE *Die, const DIVariable *V) { + // If there is no compile unit specified, don't add a line #. + if (V->getCompileUnit().isNull()) + return; + + unsigned Line = V->getLineNumber(); + unsigned FileID = findCompileUnit(V->getCompileUnit()).getID(); + assert(FileID && "Invalid file id"); + addUInt(Die, dwarf::DW_AT_decl_file, 0, FileID); + addUInt(Die, dwarf::DW_AT_decl_line, 0, Line); +} + +/// addSourceLine - Add location information to specified debug information +/// entry. +void DwarfDebug::addSourceLine(DIE *Die, const DIGlobal *G) { + // If there is no compile unit specified, don't add a line #. + if (G->getCompileUnit().isNull()) + return; + + unsigned Line = G->getLineNumber(); + unsigned FileID = findCompileUnit(G->getCompileUnit()).getID(); + assert(FileID && "Invalid file id"); + addUInt(Die, dwarf::DW_AT_decl_file, 0, FileID); + addUInt(Die, dwarf::DW_AT_decl_line, 0, Line); +} + +/// addSourceLine - Add location information to specified debug information +/// entry. +void DwarfDebug::addSourceLine(DIE *Die, const DISubprogram *SP) { + // If there is no compile unit specified, don't add a line #. + if (SP->getCompileUnit().isNull()) + return; + // If the line number is 0, don't add it. + if (SP->getLineNumber() == 0) + return; + + + unsigned Line = SP->getLineNumber(); + unsigned FileID = findCompileUnit(SP->getCompileUnit()).getID(); + assert(FileID && "Invalid file id"); + addUInt(Die, dwarf::DW_AT_decl_file, 0, FileID); + addUInt(Die, dwarf::DW_AT_decl_line, 0, Line); +} + +/// addSourceLine - Add location information to specified debug information +/// entry. +void DwarfDebug::addSourceLine(DIE *Die, const DIType *Ty) { + // If there is no compile unit specified, don't add a line #. + DICompileUnit CU = Ty->getCompileUnit(); + if (CU.isNull()) + return; + + unsigned Line = Ty->getLineNumber(); + unsigned FileID = findCompileUnit(CU).getID(); + assert(FileID && "Invalid file id"); + addUInt(Die, dwarf::DW_AT_decl_file, 0, FileID); + addUInt(Die, dwarf::DW_AT_decl_line, 0, Line); +} + +/* Byref variables, in Blocks, are declared by the programmer as + "SomeType VarName;", but the compiler creates a + __Block_byref_x_VarName struct, and gives the variable VarName + either the struct, or a pointer to the struct, as its type. This + is necessary for various behind-the-scenes things the compiler + needs to do with by-reference variables in blocks. + + However, as far as the original *programmer* is concerned, the + variable should still have type 'SomeType', as originally declared. + + The following function dives into the __Block_byref_x_VarName + struct to find the original type of the variable. This will be + passed back to the code generating the type for the Debug + Information Entry for the variable 'VarName'. 'VarName' will then + have the original type 'SomeType' in its debug information. + + The original type 'SomeType' will be the type of the field named + 'VarName' inside the __Block_byref_x_VarName struct. + + NOTE: In order for this to not completely fail on the debugger + side, the Debug Information Entry for the variable VarName needs to + have a DW_AT_location that tells the debugger how to unwind through + the pointers and __Block_byref_x_VarName struct to find the actual + value of the variable. The function addBlockByrefType does this. */ + +/// Find the type the programmer originally declared the variable to be +/// and return that type. +/// +DIType DwarfDebug::getBlockByrefType(DIType Ty, std::string Name) { + + DIType subType = Ty; + unsigned tag = Ty.getTag(); + + if (tag == dwarf::DW_TAG_pointer_type) { + DIDerivedType DTy = DIDerivedType(Ty.getNode()); + subType = DTy.getTypeDerivedFrom(); + } + + DICompositeType blockStruct = DICompositeType(subType.getNode()); + + DIArray Elements = blockStruct.getTypeArray(); + + if (Elements.isNull()) + return Ty; + + for (unsigned i = 0, N = Elements.getNumElements(); i < N; ++i) { + DIDescriptor Element = Elements.getElement(i); + DIDerivedType DT = DIDerivedType(Element.getNode()); + if (Name == DT.getName()) + return (DT.getTypeDerivedFrom()); + } + + return Ty; +} + +/// addComplexAddress - Start with the address based on the location provided, +/// and generate the DWARF information necessary to find the actual variable +/// given the extra address information encoded in the DIVariable, starting from +/// the starting location. Add the DWARF information to the die. +/// +void DwarfDebug::addComplexAddress(DbgVariable *&DV, DIE *Die, + unsigned Attribute, + const MachineLocation &Location) { + const DIVariable &VD = DV->getVariable(); + DIType Ty = VD.getType(); + + // Decode the original location, and use that as the start of the byref + // variable's location. + unsigned Reg = RI->getDwarfRegNum(Location.getReg(), false); + DIEBlock *Block = new DIEBlock(); + + if (Location.isReg()) { + if (Reg < 32) { + addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_reg0 + Reg); + } else { + Reg = Reg - dwarf::DW_OP_reg0; + addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_breg0 + Reg); + addUInt(Block, 0, dwarf::DW_FORM_udata, Reg); + } + } else { + if (Reg < 32) + addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_breg0 + Reg); + else { + addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_bregx); + addUInt(Block, 0, dwarf::DW_FORM_udata, Reg); + } + + addUInt(Block, 0, dwarf::DW_FORM_sdata, Location.getOffset()); + } + + for (unsigned i = 0, N = VD.getNumAddrElements(); i < N; ++i) { + uint64_t Element = VD.getAddrElement(i); + + if (Element == DIFactory::OpPlus) { + addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_plus_uconst); + addUInt(Block, 0, dwarf::DW_FORM_udata, VD.getAddrElement(++i)); + } else if (Element == DIFactory::OpDeref) { + addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_deref); + } else llvm_unreachable("unknown DIFactory Opcode"); + } + + // Now attach the location information to the DIE. + addBlock(Die, Attribute, 0, Block); +} + +/* Byref variables, in Blocks, are declared by the programmer as "SomeType + VarName;", but the compiler creates a __Block_byref_x_VarName struct, and + gives the variable VarName either the struct, or a pointer to the struct, as + its type. This is necessary for various behind-the-scenes things the + compiler needs to do with by-reference variables in Blocks. + + However, as far as the original *programmer* is concerned, the variable + should still have type 'SomeType', as originally declared. + + The function getBlockByrefType dives into the __Block_byref_x_VarName + struct to find the original type of the variable, which is then assigned to + the variable's Debug Information Entry as its real type. So far, so good. + However now the debugger will expect the variable VarName to have the type + SomeType. So we need the location attribute for the variable to be an + expression that explains to the debugger how to navigate through the + pointers and struct to find the actual variable of type SomeType. + + The following function does just that. We start by getting + the "normal" location for the variable. This will be the location + of either the struct __Block_byref_x_VarName or the pointer to the + struct __Block_byref_x_VarName. + + The struct will look something like: + + struct __Block_byref_x_VarName { + ... + struct __Block_byref_x_VarName *forwarding; + ... + SomeType VarName; + ... + }; + + If we are given the struct directly (as our starting point) we + need to tell the debugger to: + + 1). Add the offset of the forwarding field. + + 2). Follow that pointer to get the the real __Block_byref_x_VarName + struct to use (the real one may have been copied onto the heap). + + 3). Add the offset for the field VarName, to find the actual variable. + + If we started with a pointer to the struct, then we need to + dereference that pointer first, before the other steps. + Translating this into DWARF ops, we will need to append the following + to the current location description for the variable: + + DW_OP_deref -- optional, if we start with a pointer + DW_OP_plus_uconst + DW_OP_deref + DW_OP_plus_uconst + + That is what this function does. */ + +/// addBlockByrefAddress - Start with the address based on the location +/// provided, and generate the DWARF information necessary to find the +/// actual Block variable (navigating the Block struct) based on the +/// starting location. Add the DWARF information to the die. For +/// more information, read large comment just above here. +/// +void DwarfDebug::addBlockByrefAddress(DbgVariable *&DV, DIE *Die, + unsigned Attribute, + const MachineLocation &Location) { + const DIVariable &VD = DV->getVariable(); + DIType Ty = VD.getType(); + DIType TmpTy = Ty; + unsigned Tag = Ty.getTag(); + bool isPointer = false; + + StringRef varName = VD.getName(); + + if (Tag == dwarf::DW_TAG_pointer_type) { + DIDerivedType DTy = DIDerivedType(Ty.getNode()); + TmpTy = DTy.getTypeDerivedFrom(); + isPointer = true; + } + + DICompositeType blockStruct = DICompositeType(TmpTy.getNode()); + + // Find the __forwarding field and the variable field in the __Block_byref + // struct. + DIArray Fields = blockStruct.getTypeArray(); + DIDescriptor varField = DIDescriptor(); + DIDescriptor forwardingField = DIDescriptor(); + + + for (unsigned i = 0, N = Fields.getNumElements(); i < N; ++i) { + DIDescriptor Element = Fields.getElement(i); + DIDerivedType DT = DIDerivedType(Element.getNode()); + StringRef fieldName = DT.getName(); + if (fieldName == "__forwarding") + forwardingField = Element; + else if (fieldName == varName) + varField = Element; + } + + assert(!varField.isNull() && "Can't find byref variable in Block struct"); + assert(!forwardingField.isNull() + && "Can't find forwarding field in Block struct"); + + // Get the offsets for the forwarding field and the variable field. + unsigned int forwardingFieldOffset = + DIDerivedType(forwardingField.getNode()).getOffsetInBits() >> 3; + unsigned int varFieldOffset = + DIDerivedType(varField.getNode()).getOffsetInBits() >> 3; + + // Decode the original location, and use that as the start of the byref + // variable's location. + unsigned Reg = RI->getDwarfRegNum(Location.getReg(), false); + DIEBlock *Block = new DIEBlock(); + + if (Location.isReg()) { + if (Reg < 32) + addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_reg0 + Reg); + else { + Reg = Reg - dwarf::DW_OP_reg0; + addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_breg0 + Reg); + addUInt(Block, 0, dwarf::DW_FORM_udata, Reg); + } + } else { + if (Reg < 32) + addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_breg0 + Reg); + else { + addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_bregx); + addUInt(Block, 0, dwarf::DW_FORM_udata, Reg); + } + + addUInt(Block, 0, dwarf::DW_FORM_sdata, Location.getOffset()); + } + + // If we started with a pointer to the __Block_byref... struct, then + // the first thing we need to do is dereference the pointer (DW_OP_deref). + if (isPointer) + addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_deref); + + // Next add the offset for the '__forwarding' field: + // DW_OP_plus_uconst ForwardingFieldOffset. Note there's no point in + // adding the offset if it's 0. + if (forwardingFieldOffset > 0) { + addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_plus_uconst); + addUInt(Block, 0, dwarf::DW_FORM_udata, forwardingFieldOffset); + } + + // Now dereference the __forwarding field to get to the real __Block_byref + // struct: DW_OP_deref. + addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_deref); + + // Now that we've got the real __Block_byref... struct, add the offset + // for the variable's field to get to the location of the actual variable: + // DW_OP_plus_uconst varFieldOffset. Again, don't add if it's 0. + if (varFieldOffset > 0) { + addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_plus_uconst); + addUInt(Block, 0, dwarf::DW_FORM_udata, varFieldOffset); + } + + // Now attach the location information to the DIE. + addBlock(Die, Attribute, 0, Block); +} + +/// addAddress - Add an address attribute to a die based on the location +/// provided. +void DwarfDebug::addAddress(DIE *Die, unsigned Attribute, + const MachineLocation &Location) { + unsigned Reg = RI->getDwarfRegNum(Location.getReg(), false); + DIEBlock *Block = new DIEBlock(); + + if (Location.isReg()) { + if (Reg < 32) { + addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_reg0 + Reg); + } else { + addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_regx); + addUInt(Block, 0, dwarf::DW_FORM_udata, Reg); + } + } else { + if (Reg < 32) { + addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_breg0 + Reg); + } else { + addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_bregx); + addUInt(Block, 0, dwarf::DW_FORM_udata, Reg); + } + + addUInt(Block, 0, dwarf::DW_FORM_sdata, Location.getOffset()); + } + + addBlock(Die, Attribute, 0, Block); +} + +/// addType - Add a new type attribute to the specified entity. +void DwarfDebug::addType(CompileUnit *DW_Unit, DIE *Entity, DIType Ty) { + if (Ty.isNull()) + return; + + // Check for pre-existence. + DIEEntry *Entry = DW_Unit->getDIEEntry(Ty.getNode()); + + // If it exists then use the existing value. + if (Entry) { + Entity->addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, Entry); + return; + } + + // Set up proxy. + Entry = createDIEEntry(); + DW_Unit->insertDIEEntry(Ty.getNode(), Entry); + + // Construct type. + DIE *Buffer = new DIE(dwarf::DW_TAG_base_type); + if (Ty.isBasicType()) + constructTypeDIE(DW_Unit, *Buffer, DIBasicType(Ty.getNode())); + else if (Ty.isCompositeType()) + constructTypeDIE(DW_Unit, *Buffer, DICompositeType(Ty.getNode())); + else { + assert(Ty.isDerivedType() && "Unknown kind of DIType"); + constructTypeDIE(DW_Unit, *Buffer, DIDerivedType(Ty.getNode())); + } + + // Add debug information entry to entity and appropriate context. + DIE *Die = NULL; + DIDescriptor Context = Ty.getContext(); + if (!Context.isNull()) + Die = DW_Unit->getDIE(Context.getNode()); + + if (Die) + Die->addChild(Buffer); + else + DW_Unit->addDie(Buffer); + Entry->setEntry(Buffer); + Entity->addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, Entry); +} + +/// constructTypeDIE - Construct basic type die from DIBasicType. +void DwarfDebug::constructTypeDIE(CompileUnit *DW_Unit, DIE &Buffer, + DIBasicType BTy) { + // Get core information. + StringRef Name = BTy.getName(); + Buffer.setTag(dwarf::DW_TAG_base_type); + addUInt(&Buffer, dwarf::DW_AT_encoding, dwarf::DW_FORM_data1, + BTy.getEncoding()); + + // Add name if not anonymous or intermediate type. + if (!Name.empty()) + addString(&Buffer, dwarf::DW_AT_name, dwarf::DW_FORM_string, Name); + uint64_t Size = BTy.getSizeInBits() >> 3; + addUInt(&Buffer, dwarf::DW_AT_byte_size, 0, Size); +} + +/// constructTypeDIE - Construct derived type die from DIDerivedType. +void DwarfDebug::constructTypeDIE(CompileUnit *DW_Unit, DIE &Buffer, + DIDerivedType DTy) { + // Get core information. + StringRef Name = DTy.getName(); + uint64_t Size = DTy.getSizeInBits() >> 3; + unsigned Tag = DTy.getTag(); + + // FIXME - Workaround for templates. + if (Tag == dwarf::DW_TAG_inheritance) Tag = dwarf::DW_TAG_reference_type; + + Buffer.setTag(Tag); + + // Map to main type, void will not have a type. + DIType FromTy = DTy.getTypeDerivedFrom(); + addType(DW_Unit, &Buffer, FromTy); + + // Add name if not anonymous or intermediate type. + if (!Name.empty() && Tag != dwarf::DW_TAG_pointer_type) + addString(&Buffer, dwarf::DW_AT_name, dwarf::DW_FORM_string, Name); + + // Add size if non-zero (derived types might be zero-sized.) + if (Size) + addUInt(&Buffer, dwarf::DW_AT_byte_size, 0, Size); + + // Add source line info if available and TyDesc is not a forward declaration. + if (!DTy.isForwardDecl()) + addSourceLine(&Buffer, &DTy); +} + +/// constructTypeDIE - Construct type DIE from DICompositeType. +void DwarfDebug::constructTypeDIE(CompileUnit *DW_Unit, DIE &Buffer, + DICompositeType CTy) { + // Get core information. + StringRef Name = CTy.getName(); + + uint64_t Size = CTy.getSizeInBits() >> 3; + unsigned Tag = CTy.getTag(); + Buffer.setTag(Tag); + + switch (Tag) { + case dwarf::DW_TAG_vector_type: + case dwarf::DW_TAG_array_type: + constructArrayTypeDIE(DW_Unit, Buffer, &CTy); + break; + case dwarf::DW_TAG_enumeration_type: { + DIArray Elements = CTy.getTypeArray(); + + // Add enumerators to enumeration type. + for (unsigned i = 0, N = Elements.getNumElements(); i < N; ++i) { + DIE *ElemDie = NULL; + DIEnumerator Enum(Elements.getElement(i).getNode()); + if (!Enum.isNull()) { + ElemDie = constructEnumTypeDIE(DW_Unit, &Enum); + Buffer.addChild(ElemDie); + } + } + } + break; + case dwarf::DW_TAG_subroutine_type: { + // Add return type. + DIArray Elements = CTy.getTypeArray(); + DIDescriptor RTy = Elements.getElement(0); + addType(DW_Unit, &Buffer, DIType(RTy.getNode())); + + // Add prototype flag. + addUInt(&Buffer, dwarf::DW_AT_prototyped, dwarf::DW_FORM_flag, 1); + + // Add arguments. + for (unsigned i = 1, N = Elements.getNumElements(); i < N; ++i) { + DIE *Arg = new DIE(dwarf::DW_TAG_formal_parameter); + DIDescriptor Ty = Elements.getElement(i); + addType(DW_Unit, Arg, DIType(Ty.getNode())); + Buffer.addChild(Arg); + } + } + break; + case dwarf::DW_TAG_structure_type: + case dwarf::DW_TAG_union_type: + case dwarf::DW_TAG_class_type: { + // Add elements to structure type. + DIArray Elements = CTy.getTypeArray(); + + // A forward struct declared type may not have elements available. + if (Elements.isNull()) + break; + + // Add elements to structure type. + for (unsigned i = 0, N = Elements.getNumElements(); i < N; ++i) { + DIDescriptor Element = Elements.getElement(i); + if (Element.isNull()) + continue; + DIE *ElemDie = NULL; + if (Element.getTag() == dwarf::DW_TAG_subprogram) + ElemDie = createSubprogramDIE(DW_Unit, + DISubprogram(Element.getNode())); + else + ElemDie = createMemberDIE(DW_Unit, + DIDerivedType(Element.getNode())); + Buffer.addChild(ElemDie); + } + + if (CTy.isAppleBlockExtension()) + addUInt(&Buffer, dwarf::DW_AT_APPLE_block, dwarf::DW_FORM_flag, 1); + + unsigned RLang = CTy.getRunTimeLang(); + if (RLang) + addUInt(&Buffer, dwarf::DW_AT_APPLE_runtime_class, + dwarf::DW_FORM_data1, RLang); + break; + } + default: + break; + } + + // Add name if not anonymous or intermediate type. + if (!Name.empty()) + addString(&Buffer, dwarf::DW_AT_name, dwarf::DW_FORM_string, Name); + + if (Tag == dwarf::DW_TAG_enumeration_type || + Tag == dwarf::DW_TAG_structure_type || Tag == dwarf::DW_TAG_union_type) { + // Add size if non-zero (derived types might be zero-sized.) + if (Size) + addUInt(&Buffer, dwarf::DW_AT_byte_size, 0, Size); + else { + // Add zero size if it is not a forward declaration. + if (CTy.isForwardDecl()) + addUInt(&Buffer, dwarf::DW_AT_declaration, dwarf::DW_FORM_flag, 1); + else + addUInt(&Buffer, dwarf::DW_AT_byte_size, 0, 0); + } + + // Add source line info if available. + if (!CTy.isForwardDecl()) + addSourceLine(&Buffer, &CTy); + } +} + +/// constructSubrangeDIE - Construct subrange DIE from DISubrange. +void DwarfDebug::constructSubrangeDIE(DIE &Buffer, DISubrange SR, DIE *IndexTy){ + int64_t L = SR.getLo(); + int64_t H = SR.getHi(); + DIE *DW_Subrange = new DIE(dwarf::DW_TAG_subrange_type); + + addDIEEntry(DW_Subrange, dwarf::DW_AT_type, dwarf::DW_FORM_ref4, IndexTy); + if (L) + addSInt(DW_Subrange, dwarf::DW_AT_lower_bound, 0, L); + if (H) + addSInt(DW_Subrange, dwarf::DW_AT_upper_bound, 0, H); + + Buffer.addChild(DW_Subrange); +} + +/// constructArrayTypeDIE - Construct array type DIE from DICompositeType. +void DwarfDebug::constructArrayTypeDIE(CompileUnit *DW_Unit, DIE &Buffer, + DICompositeType *CTy) { + Buffer.setTag(dwarf::DW_TAG_array_type); + if (CTy->getTag() == dwarf::DW_TAG_vector_type) + addUInt(&Buffer, dwarf::DW_AT_GNU_vector, dwarf::DW_FORM_flag, 1); + + // Emit derived type. + addType(DW_Unit, &Buffer, CTy->getTypeDerivedFrom()); + DIArray Elements = CTy->getTypeArray(); + + // Get an anonymous type for index type. + DIE *IdxTy = DW_Unit->getIndexTyDie(); + if (!IdxTy) { + // Construct an anonymous type for index type. + IdxTy = new DIE(dwarf::DW_TAG_base_type); + addUInt(IdxTy, dwarf::DW_AT_byte_size, 0, sizeof(int32_t)); + addUInt(IdxTy, dwarf::DW_AT_encoding, dwarf::DW_FORM_data1, + dwarf::DW_ATE_signed); + DW_Unit->addDie(IdxTy); + DW_Unit->setIndexTyDie(IdxTy); + } + + // Add subranges to array type. + for (unsigned i = 0, N = Elements.getNumElements(); i < N; ++i) { + DIDescriptor Element = Elements.getElement(i); + if (Element.getTag() == dwarf::DW_TAG_subrange_type) + constructSubrangeDIE(Buffer, DISubrange(Element.getNode()), IdxTy); + } +} + +/// constructEnumTypeDIE - Construct enum type DIE from DIEnumerator. +DIE *DwarfDebug::constructEnumTypeDIE(CompileUnit *DW_Unit, DIEnumerator *ETy) { + DIE *Enumerator = new DIE(dwarf::DW_TAG_enumerator); + StringRef Name = ETy->getName(); + addString(Enumerator, dwarf::DW_AT_name, dwarf::DW_FORM_string, Name); + int64_t Value = ETy->getEnumValue(); + addSInt(Enumerator, dwarf::DW_AT_const_value, dwarf::DW_FORM_sdata, Value); + return Enumerator; +} + +/// createGlobalVariableDIE - Create new DIE using GV. +DIE *DwarfDebug::createGlobalVariableDIE(CompileUnit *DW_Unit, + const DIGlobalVariable &GV) { + // If the global variable was optmized out then no need to create debug info + // entry. + if (!GV.getGlobal()) return NULL; + if (GV.getDisplayName().empty()) return NULL; + + DIE *GVDie = new DIE(dwarf::DW_TAG_variable); + addString(GVDie, dwarf::DW_AT_name, dwarf::DW_FORM_string, + GV.getDisplayName()); + + StringRef LinkageName = GV.getLinkageName(); + if (!LinkageName.empty()) { + // Skip special LLVM prefix that is used to inform the asm printer to not + // emit usual symbol prefix before the symbol name. This happens for + // Objective-C symbol names and symbol whose name is replaced using GCC's + // __asm__ attribute. + if (LinkageName[0] == 1) + LinkageName = LinkageName.substr(1); + addString(GVDie, dwarf::DW_AT_MIPS_linkage_name, dwarf::DW_FORM_string, + LinkageName); + } + addType(DW_Unit, GVDie, GV.getType()); + if (!GV.isLocalToUnit()) + addUInt(GVDie, dwarf::DW_AT_external, dwarf::DW_FORM_flag, 1); + addSourceLine(GVDie, &GV); + + // Add address. + DIEBlock *Block = new DIEBlock(); + addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_addr); + addObjectLabel(Block, 0, dwarf::DW_FORM_udata, + Asm->Mang->getMangledName(GV.getGlobal())); + addBlock(GVDie, dwarf::DW_AT_location, 0, Block); + + return GVDie; +} + +/// createMemberDIE - Create new member DIE. +DIE *DwarfDebug::createMemberDIE(CompileUnit *DW_Unit, const DIDerivedType &DT){ + DIE *MemberDie = new DIE(DT.getTag()); + StringRef Name = DT.getName(); + if (!Name.empty()) + addString(MemberDie, dwarf::DW_AT_name, dwarf::DW_FORM_string, Name); + + addType(DW_Unit, MemberDie, DT.getTypeDerivedFrom()); + + addSourceLine(MemberDie, &DT); + + DIEBlock *MemLocationDie = new DIEBlock(); + addUInt(MemLocationDie, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_plus_uconst); + + uint64_t Size = DT.getSizeInBits(); + uint64_t FieldSize = DT.getOriginalTypeSize(); + + if (Size != FieldSize) { + // Handle bitfield. + addUInt(MemberDie, dwarf::DW_AT_byte_size, 0, DT.getOriginalTypeSize()>>3); + addUInt(MemberDie, dwarf::DW_AT_bit_size, 0, DT.getSizeInBits()); + + uint64_t Offset = DT.getOffsetInBits(); + uint64_t FieldOffset = Offset; + uint64_t AlignMask = ~(DT.getAlignInBits() - 1); + uint64_t HiMark = (Offset + FieldSize) & AlignMask; + FieldOffset = (HiMark - FieldSize); + Offset -= FieldOffset; + + // Maybe we need to work from the other end. + if (TD->isLittleEndian()) Offset = FieldSize - (Offset + Size); + addUInt(MemberDie, dwarf::DW_AT_bit_offset, 0, Offset); + + // Here WD_AT_data_member_location points to the anonymous + // field that includes this bit field. + addUInt(MemLocationDie, 0, dwarf::DW_FORM_udata, FieldOffset >> 3); + + } else + // This is not a bitfield. + addUInt(MemLocationDie, 0, dwarf::DW_FORM_udata, DT.getOffsetInBits() >> 3); + + addBlock(MemberDie, dwarf::DW_AT_data_member_location, 0, MemLocationDie); + + if (DT.isProtected()) + addUInt(MemberDie, dwarf::DW_AT_accessibility, 0, + dwarf::DW_ACCESS_protected); + else if (DT.isPrivate()) + addUInt(MemberDie, dwarf::DW_AT_accessibility, 0, + dwarf::DW_ACCESS_private); + + return MemberDie; +} + +/// createSubprogramDIE - Create new DIE using SP. +DIE *DwarfDebug::createSubprogramDIE(CompileUnit *DW_Unit, + const DISubprogram &SP, + bool IsConstructor, + bool IsInlined) { + DIE *SPDie = new DIE(dwarf::DW_TAG_subprogram); + addString(SPDie, dwarf::DW_AT_name, dwarf::DW_FORM_string, SP.getName()); + + StringRef LinkageName = SP.getLinkageName(); + if (!LinkageName.empty()) { + // Skip special LLVM prefix that is used to inform the asm printer to not + // emit usual symbol prefix before the symbol name. This happens for + // Objective-C symbol names and symbol whose name is replaced using GCC's + // __asm__ attribute. + if (LinkageName[0] == 1) + LinkageName = LinkageName.substr(1); + addString(SPDie, dwarf::DW_AT_MIPS_linkage_name, dwarf::DW_FORM_string, + LinkageName); + } + addSourceLine(SPDie, &SP); + + DICompositeType SPTy = SP.getType(); + DIArray Args = SPTy.getTypeArray(); + + // Add prototyped tag, if C or ObjC. + unsigned Lang = SP.getCompileUnit().getLanguage(); + if (Lang == dwarf::DW_LANG_C99 || Lang == dwarf::DW_LANG_C89 || + Lang == dwarf::DW_LANG_ObjC) + addUInt(SPDie, dwarf::DW_AT_prototyped, dwarf::DW_FORM_flag, 1); + + // Add Return Type. + unsigned SPTag = SPTy.getTag(); + if (!IsConstructor) { + if (Args.isNull() || SPTag != dwarf::DW_TAG_subroutine_type) + addType(DW_Unit, SPDie, SPTy); + else + addType(DW_Unit, SPDie, DIType(Args.getElement(0).getNode())); + } + + if (!SP.isDefinition()) { + addUInt(SPDie, dwarf::DW_AT_declaration, dwarf::DW_FORM_flag, 1); + + // Add arguments. Do not add arguments for subprogram definition. They will + // be handled through RecordVariable. + if (SPTag == dwarf::DW_TAG_subroutine_type) + for (unsigned i = 1, N = Args.getNumElements(); i < N; ++i) { + DIE *Arg = new DIE(dwarf::DW_TAG_formal_parameter); + addType(DW_Unit, Arg, DIType(Args.getElement(i).getNode())); + addUInt(Arg, dwarf::DW_AT_artificial, dwarf::DW_FORM_flag, 1); // ?? + SPDie->addChild(Arg); + } + } + + // DW_TAG_inlined_subroutine may refer to this DIE. + DW_Unit->insertDIE(SP.getNode(), SPDie); + return SPDie; +} + +/// findCompileUnit - Get the compile unit for the given descriptor. +/// +CompileUnit &DwarfDebug::findCompileUnit(DICompileUnit Unit) const { + DenseMap::const_iterator I = + CompileUnitMap.find(Unit.getNode()); + assert(I != CompileUnitMap.end() && "Missing compile unit."); + return *I->second; +} + +/// createDbgScopeVariable - Create a new scope variable. +/// +DIE *DwarfDebug::createDbgScopeVariable(DbgVariable *DV, CompileUnit *Unit) { + // Get the descriptor. + const DIVariable &VD = DV->getVariable(); + StringRef Name = VD.getName(); + if (Name.empty()) + return NULL; + + // Translate tag to proper Dwarf tag. The result variable is dropped for + // now. + unsigned Tag; + switch (VD.getTag()) { + case dwarf::DW_TAG_return_variable: + return NULL; + case dwarf::DW_TAG_arg_variable: + Tag = dwarf::DW_TAG_formal_parameter; + break; + case dwarf::DW_TAG_auto_variable: // fall thru + default: + Tag = dwarf::DW_TAG_variable; + break; + } + + // Define variable debug information entry. + DIE *VariableDie = new DIE(Tag); + addString(VariableDie, dwarf::DW_AT_name, dwarf::DW_FORM_string, Name); + + // Add source line info if available. + addSourceLine(VariableDie, &VD); + + // Add variable type. + // FIXME: isBlockByrefVariable should be reformulated in terms of complex + // addresses instead. + if (VD.isBlockByrefVariable()) + addType(Unit, VariableDie, getBlockByrefType(VD.getType(), Name)); + else + addType(Unit, VariableDie, VD.getType()); + + // Add variable address. + // Variables for abstract instances of inlined functions don't get a + // location. + MachineLocation Location; + unsigned FrameReg; + int Offset = RI->getFrameIndexReference(*MF, DV->getFrameIndex(), FrameReg); + Location.set(FrameReg, Offset); + + + if (VD.hasComplexAddress()) + addComplexAddress(DV, VariableDie, dwarf::DW_AT_location, Location); + else if (VD.isBlockByrefVariable()) + addBlockByrefAddress(DV, VariableDie, dwarf::DW_AT_location, Location); + else + addAddress(VariableDie, dwarf::DW_AT_location, Location); + + return VariableDie; +} + +/// getUpdatedDbgScope - Find or create DbgScope assicated with the instruction. +/// Initialize scope and update scope hierarchy. +DbgScope *DwarfDebug::getUpdatedDbgScope(MDNode *N, const MachineInstr *MI, + MDNode *InlinedAt) { + assert (N && "Invalid Scope encoding!"); + assert (MI && "Missing machine instruction!"); + bool GetConcreteScope = (MI && InlinedAt); + + DbgScope *NScope = NULL; + + if (InlinedAt) + NScope = DbgScopeMap.lookup(InlinedAt); + else + NScope = DbgScopeMap.lookup(N); + assert (NScope && "Unable to find working scope!"); + + if (NScope->getFirstInsn()) + return NScope; + + DbgScope *Parent = NULL; + if (GetConcreteScope) { + DILocation IL(InlinedAt); + Parent = getUpdatedDbgScope(IL.getScope().getNode(), MI, + IL.getOrigLocation().getNode()); + assert (Parent && "Unable to find Parent scope!"); + NScope->setParent(Parent); + Parent->addScope(NScope); + } else if (DIDescriptor(N).isLexicalBlock()) { + DILexicalBlock DB(N); + if (!DB.getContext().isNull()) { + Parent = getUpdatedDbgScope(DB.getContext().getNode(), MI, InlinedAt); + NScope->setParent(Parent); + Parent->addScope(NScope); + } + } + + NScope->setFirstInsn(MI); + + if (!Parent && !InlinedAt) { + StringRef SPName = DISubprogram(N).getLinkageName(); + if (SPName == MF->getFunction()->getName()) + CurrentFnDbgScope = NScope; + } + + if (GetConcreteScope) { + ConcreteScopes[InlinedAt] = NScope; + getOrCreateAbstractScope(N); + } + + return NScope; +} + +DbgScope *DwarfDebug::getOrCreateAbstractScope(MDNode *N) { + assert (N && "Invalid Scope encoding!"); + + DbgScope *AScope = AbstractScopes.lookup(N); + if (AScope) + return AScope; + + DbgScope *Parent = NULL; + + DIDescriptor Scope(N); + if (Scope.isLexicalBlock()) { + DILexicalBlock DB(N); + DIDescriptor ParentDesc = DB.getContext(); + if (!ParentDesc.isNull()) + Parent = getOrCreateAbstractScope(ParentDesc.getNode()); + } + + AScope = new DbgScope(Parent, DIDescriptor(N), NULL); + + if (Parent) + Parent->addScope(AScope); + AScope->setAbstractScope(); + AbstractScopes[N] = AScope; + if (DIDescriptor(N).isSubprogram()) + AbstractScopesList.push_back(AScope); + return AScope; +} + +/// updateSubprogramScopeDIE - Find DIE for the given subprogram and +/// attach appropriate DW_AT_low_pc and DW_AT_high_pc attributes. +/// If there are global variables in this scope then create and insert +/// DIEs for these variables. +DIE *DwarfDebug::updateSubprogramScopeDIE(MDNode *SPNode) { + + DIE *SPDie = ModuleCU->getDIE(SPNode); + assert (SPDie && "Unable to find subprogram DIE!"); + addLabel(SPDie, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr, + DWLabel("func_begin", SubprogramCount)); + addLabel(SPDie, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr, + DWLabel("func_end", SubprogramCount)); + MachineLocation Location(RI->getFrameRegister(*MF)); + addAddress(SPDie, dwarf::DW_AT_frame_base, Location); + + if (!DISubprogram(SPNode).isLocalToUnit()) + addUInt(SPDie, dwarf::DW_AT_external, dwarf::DW_FORM_flag, 1); + + // If there are global variables at this scope then add their dies. + for (SmallVector::iterator SGI = ScopedGVs.begin(), + SGE = ScopedGVs.end(); SGI != SGE; ++SGI) { + MDNode *N = dyn_cast_or_null(*SGI); + if (!N) continue; + DIGlobalVariable GV(N); + if (GV.getContext().getNode() == SPNode) { + DIE *ScopedGVDie = createGlobalVariableDIE(ModuleCU, GV); + if (ScopedGVDie) + SPDie->addChild(ScopedGVDie); + } + } + + return SPDie; +} + +/// constructLexicalScope - Construct new DW_TAG_lexical_block +/// for this scope and attach DW_AT_low_pc/DW_AT_high_pc labels. +DIE *DwarfDebug::constructLexicalScopeDIE(DbgScope *Scope) { + unsigned StartID = MMI->MappedLabel(Scope->getStartLabelID()); + unsigned EndID = MMI->MappedLabel(Scope->getEndLabelID()); + + // Ignore empty scopes. + if (StartID == EndID && StartID != 0) + return NULL; + + DIE *ScopeDIE = new DIE(dwarf::DW_TAG_lexical_block); + if (Scope->isAbstractScope()) + return ScopeDIE; + + addLabel(ScopeDIE, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr, + StartID ? + DWLabel("label", StartID) + : DWLabel("func_begin", SubprogramCount)); + addLabel(ScopeDIE, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr, + EndID ? + DWLabel("label", EndID) + : DWLabel("func_end", SubprogramCount)); + + + + return ScopeDIE; +} + +/// constructInlinedScopeDIE - This scope represents inlined body of +/// a function. Construct DIE to represent this concrete inlined copy +/// of the function. +DIE *DwarfDebug::constructInlinedScopeDIE(DbgScope *Scope) { + unsigned StartID = MMI->MappedLabel(Scope->getStartLabelID()); + unsigned EndID = MMI->MappedLabel(Scope->getEndLabelID()); + assert (StartID && "Invalid starting label for an inlined scope!"); + assert (EndID && "Invalid end label for an inlined scope!"); + // Ignore empty scopes. + if (StartID == EndID && StartID != 0) + return NULL; + + DIScope DS(Scope->getScopeNode()); + if (DS.isNull()) + return NULL; + DIE *ScopeDIE = new DIE(dwarf::DW_TAG_inlined_subroutine); + + DISubprogram InlinedSP = getDISubprogram(DS.getNode()); + DIE *OriginDIE = ModuleCU->getDIE(InlinedSP.getNode()); + assert (OriginDIE && "Unable to find Origin DIE!"); + addDIEEntry(ScopeDIE, dwarf::DW_AT_abstract_origin, + dwarf::DW_FORM_ref4, OriginDIE); + + addLabel(ScopeDIE, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr, + DWLabel("label", StartID)); + addLabel(ScopeDIE, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr, + DWLabel("label", EndID)); + + InlinedSubprogramDIEs.insert(OriginDIE); + + // Track the start label for this inlined function. + ValueMap >::iterator + I = InlineInfo.find(InlinedSP.getNode()); + + if (I == InlineInfo.end()) { + InlineInfo[InlinedSP.getNode()].push_back(std::make_pair(StartID, + ScopeDIE)); + InlinedSPNodes.push_back(InlinedSP.getNode()); + } else + I->second.push_back(std::make_pair(StartID, ScopeDIE)); + + StringPool.insert(InlinedSP.getName()); + StringPool.insert(InlinedSP.getLinkageName()); + DILocation DL(Scope->getInlinedAt()); + addUInt(ScopeDIE, dwarf::DW_AT_call_file, 0, ModuleCU->getID()); + addUInt(ScopeDIE, dwarf::DW_AT_call_line, 0, DL.getLineNumber()); + + return ScopeDIE; +} + + +/// constructVariableDIE - Construct a DIE for the given DbgVariable. +DIE *DwarfDebug::constructVariableDIE(DbgVariable *DV, + DbgScope *Scope, CompileUnit *Unit) { + // Get the descriptor. + const DIVariable &VD = DV->getVariable(); + StringRef Name = VD.getName(); + if (Name.empty()) + return NULL; + + // Translate tag to proper Dwarf tag. The result variable is dropped for + // now. + unsigned Tag; + switch (VD.getTag()) { + case dwarf::DW_TAG_return_variable: + return NULL; + case dwarf::DW_TAG_arg_variable: + Tag = dwarf::DW_TAG_formal_parameter; + break; + case dwarf::DW_TAG_auto_variable: // fall thru + default: + Tag = dwarf::DW_TAG_variable; + break; + } + + // Define variable debug information entry. + DIE *VariableDie = new DIE(Tag); + + + DIE *AbsDIE = NULL; + if (DbgVariable *AV = DV->getAbstractVariable()) + AbsDIE = AV->getDIE(); + + if (AbsDIE) { + DIScope DS(Scope->getScopeNode()); + DISubprogram InlinedSP = getDISubprogram(DS.getNode()); + DIE *OriginSPDIE = ModuleCU->getDIE(InlinedSP.getNode()); + (void) OriginSPDIE; + assert (OriginSPDIE && "Unable to find Origin DIE for the SP!"); + DIE *AbsDIE = DV->getAbstractVariable()->getDIE(); + assert (AbsDIE && "Unable to find Origin DIE for the Variable!"); + addDIEEntry(VariableDie, dwarf::DW_AT_abstract_origin, + dwarf::DW_FORM_ref4, AbsDIE); + } + else { + addString(VariableDie, dwarf::DW_AT_name, dwarf::DW_FORM_string, Name); + addSourceLine(VariableDie, &VD); + + // Add variable type. + // FIXME: isBlockByrefVariable should be reformulated in terms of complex + // addresses instead. + if (VD.isBlockByrefVariable()) + addType(Unit, VariableDie, getBlockByrefType(VD.getType(), Name)); + else + addType(Unit, VariableDie, VD.getType()); + } + + // Add variable address. + if (!Scope->isAbstractScope()) { + MachineLocation Location; + unsigned FrameReg; + int Offset = RI->getFrameIndexReference(*MF, DV->getFrameIndex(), FrameReg); + Location.set(FrameReg, Offset); + + if (VD.hasComplexAddress()) + addComplexAddress(DV, VariableDie, dwarf::DW_AT_location, Location); + else if (VD.isBlockByrefVariable()) + addBlockByrefAddress(DV, VariableDie, dwarf::DW_AT_location, Location); + else + addAddress(VariableDie, dwarf::DW_AT_location, Location); + } + DV->setDIE(VariableDie); + return VariableDie; + +} + +void DwarfDebug::addPubTypes(DISubprogram SP) { + DICompositeType SPTy = SP.getType(); + unsigned SPTag = SPTy.getTag(); + if (SPTag != dwarf::DW_TAG_subroutine_type) + return; + + DIArray Args = SPTy.getTypeArray(); + if (Args.isNull()) + return; + + for (unsigned i = 0, e = Args.getNumElements(); i != e; ++i) { + DIType ATy(Args.getElement(i).getNode()); + if (ATy.isNull()) + continue; + DICompositeType CATy = getDICompositeType(ATy); + if (!CATy.isNull() && !CATy.getName().empty()) { + if (DIEEntry *Entry = ModuleCU->getDIEEntry(CATy.getNode())) + ModuleCU->addGlobalType(CATy.getName(), Entry->getEntry()); + } + } +} + +/// constructScopeDIE - Construct a DIE for this scope. +DIE *DwarfDebug::constructScopeDIE(DbgScope *Scope) { + if (!Scope) + return NULL; + DIScope DS(Scope->getScopeNode()); + if (DS.isNull()) + return NULL; + + DIE *ScopeDIE = NULL; + if (Scope->getInlinedAt()) + ScopeDIE = constructInlinedScopeDIE(Scope); + else if (DS.isSubprogram()) { + if (Scope->isAbstractScope()) + ScopeDIE = ModuleCU->getDIE(DS.getNode()); + else + ScopeDIE = updateSubprogramScopeDIE(DS.getNode()); + } + else { + ScopeDIE = constructLexicalScopeDIE(Scope); + if (!ScopeDIE) return NULL; + } + + // Add variables to scope. + SmallVector &Variables = Scope->getVariables(); + for (unsigned i = 0, N = Variables.size(); i < N; ++i) { + DIE *VariableDIE = constructVariableDIE(Variables[i], Scope, ModuleCU); + if (VariableDIE) + ScopeDIE->addChild(VariableDIE); + } + + // Add nested scopes. + SmallVector &Scopes = Scope->getScopes(); + for (unsigned j = 0, M = Scopes.size(); j < M; ++j) { + // Define the Scope debug information entry. + DIE *NestedDIE = constructScopeDIE(Scopes[j]); + if (NestedDIE) + ScopeDIE->addChild(NestedDIE); + } + + if (DS.isSubprogram()) + addPubTypes(DISubprogram(DS.getNode())); + + return ScopeDIE; +} + +/// GetOrCreateSourceID - Look up the source id with the given directory and +/// source file names. If none currently exists, create a new id and insert it +/// in the SourceIds map. This can update DirectoryNames and SourceFileNames +/// maps as well. +unsigned DwarfDebug::GetOrCreateSourceID(StringRef DirName, StringRef FileName) { + unsigned DId; + StringMap::iterator DI = DirectoryIdMap.find(DirName); + if (DI != DirectoryIdMap.end()) { + DId = DI->getValue(); + } else { + DId = DirectoryNames.size() + 1; + DirectoryIdMap[DirName] = DId; + DirectoryNames.push_back(DirName); + } + + unsigned FId; + StringMap::iterator FI = SourceFileIdMap.find(FileName); + if (FI != SourceFileIdMap.end()) { + FId = FI->getValue(); + } else { + FId = SourceFileNames.size() + 1; + SourceFileIdMap[FileName] = FId; + SourceFileNames.push_back(FileName); + } + + DenseMap, unsigned>::iterator SI = + SourceIdMap.find(std::make_pair(DId, FId)); + if (SI != SourceIdMap.end()) + return SI->second; + + unsigned SrcId = SourceIds.size() + 1; // DW_AT_decl_file cannot be 0. + SourceIdMap[std::make_pair(DId, FId)] = SrcId; + SourceIds.push_back(std::make_pair(DId, FId)); + + return SrcId; +} + +void DwarfDebug::constructCompileUnit(MDNode *N) { + DICompileUnit DIUnit(N); + StringRef FN = DIUnit.getFilename(); + StringRef Dir = DIUnit.getDirectory(); + unsigned ID = GetOrCreateSourceID(Dir, FN); + + DIE *Die = new DIE(dwarf::DW_TAG_compile_unit); + addSectionOffset(Die, dwarf::DW_AT_stmt_list, dwarf::DW_FORM_data4, + DWLabel("section_line", 0), DWLabel("section_line", 0), + false); + addString(Die, dwarf::DW_AT_producer, dwarf::DW_FORM_string, + DIUnit.getProducer()); + addUInt(Die, dwarf::DW_AT_language, dwarf::DW_FORM_data1, + DIUnit.getLanguage()); + addString(Die, dwarf::DW_AT_name, dwarf::DW_FORM_string, FN); + + if (!Dir.empty()) + addString(Die, dwarf::DW_AT_comp_dir, dwarf::DW_FORM_string, Dir); + if (DIUnit.isOptimized()) + addUInt(Die, dwarf::DW_AT_APPLE_optimized, dwarf::DW_FORM_flag, 1); + + StringRef Flags = DIUnit.getFlags(); + if (!Flags.empty()) + addString(Die, dwarf::DW_AT_APPLE_flags, dwarf::DW_FORM_string, Flags); + + unsigned RVer = DIUnit.getRunTimeVersion(); + if (RVer) + addUInt(Die, dwarf::DW_AT_APPLE_major_runtime_vers, + dwarf::DW_FORM_data1, RVer); + + CompileUnit *Unit = new CompileUnit(ID, Die); + if (!ModuleCU && DIUnit.isMain()) { + // Use first compile unit marked as isMain as the compile unit + // for this module. + ModuleCU = Unit; + } + + CompileUnitMap[DIUnit.getNode()] = Unit; + CompileUnits.push_back(Unit); +} + +void DwarfDebug::constructGlobalVariableDIE(MDNode *N) { + DIGlobalVariable DI_GV(N); + + // If debug information is malformed then ignore it. + if (DI_GV.Verify() == false) + return; + + // Check for pre-existence. + if (ModuleCU->getDIE(DI_GV.getNode())) + return; + + DIE *VariableDie = createGlobalVariableDIE(ModuleCU, DI_GV); + + // Add to map. + ModuleCU->insertDIE(N, VariableDie); + + // Add to context owner. + ModuleCU->getCUDie()->addChild(VariableDie); + + // Expose as global. FIXME - need to check external flag. + ModuleCU->addGlobal(DI_GV.getName(), VariableDie); + + DIType GTy = DI_GV.getType(); + if (GTy.isCompositeType() && !GTy.getName().empty()) { + DIEEntry *Entry = ModuleCU->getDIEEntry(GTy.getNode()); + assert (Entry && "Missing global type!"); + ModuleCU->addGlobalType(GTy.getName(), Entry->getEntry()); + } + return; +} + +void DwarfDebug::constructSubprogramDIE(MDNode *N) { + DISubprogram SP(N); + + // Check for pre-existence. + if (ModuleCU->getDIE(N)) + return; + + if (!SP.isDefinition()) + // This is a method declaration which will be handled while constructing + // class type. + return; + + DIE *SubprogramDie = createSubprogramDIE(ModuleCU, SP); + + // Add to map. + ModuleCU->insertDIE(N, SubprogramDie); + + // Add to context owner. + ModuleCU->getCUDie()->addChild(SubprogramDie); + + // Expose as global. + ModuleCU->addGlobal(SP.getName(), SubprogramDie); + + return; +} + +/// beginModule - Emit all Dwarf sections that should come prior to the +/// content. Create global DIEs and emit initial debug info sections. +/// This is inovked by the target AsmPrinter. +void DwarfDebug::beginModule(Module *M, MachineModuleInfo *mmi) { + this->M = M; + + if (TimePassesIsEnabled) + DebugTimer->startTimer(); + + if (!MAI->doesSupportDebugInformation()) + return; + + DebugInfoFinder DbgFinder; + DbgFinder.processModule(*M); + + // Create all the compile unit DIEs. + for (DebugInfoFinder::iterator I = DbgFinder.compile_unit_begin(), + E = DbgFinder.compile_unit_end(); I != E; ++I) + constructCompileUnit(*I); + + if (CompileUnits.empty()) { + if (TimePassesIsEnabled) + DebugTimer->stopTimer(); + + return; + } + + // If main compile unit for this module is not seen than randomly + // select first compile unit. + if (!ModuleCU) + ModuleCU = CompileUnits[0]; + + // Create DIEs for each of the externally visible global variables. + for (DebugInfoFinder::iterator I = DbgFinder.global_variable_begin(), + E = DbgFinder.global_variable_end(); I != E; ++I) { + DIGlobalVariable GV(*I); + if (GV.getContext().getNode() != GV.getCompileUnit().getNode()) + ScopedGVs.push_back(*I); + else + constructGlobalVariableDIE(*I); + } + + // Create DIEs for each subprogram. + for (DebugInfoFinder::iterator I = DbgFinder.subprogram_begin(), + E = DbgFinder.subprogram_end(); I != E; ++I) + constructSubprogramDIE(*I); + + MMI = mmi; + shouldEmit = true; + MMI->setDebugInfoAvailability(true); + + // Prime section data. + SectionMap.insert(Asm->getObjFileLowering().getTextSection()); + + // Print out .file directives to specify files for .loc directives. These are + // printed out early so that they precede any .loc directives. + if (MAI->hasDotLocAndDotFile()) { + for (unsigned i = 1, e = getNumSourceIds()+1; i != e; ++i) { + // Remember source id starts at 1. + std::pair Id = getSourceDirectoryAndFileIds(i); + sys::Path FullPath(getSourceDirectoryName(Id.first)); + bool AppendOk = + FullPath.appendComponent(getSourceFileName(Id.second)); + assert(AppendOk && "Could not append filename to directory!"); + AppendOk = false; + Asm->EmitFile(i, FullPath.str()); + Asm->EOL(); + } + } + + // Emit initial sections + emitInitial(); + + if (TimePassesIsEnabled) + DebugTimer->stopTimer(); +} + +/// endModule - Emit all Dwarf sections that should come after the content. +/// +void DwarfDebug::endModule() { + if (!ModuleCU) + return; + + if (TimePassesIsEnabled) + DebugTimer->startTimer(); + + // Attach DW_AT_inline attribute with inlined subprogram DIEs. + for (SmallPtrSet::iterator AI = InlinedSubprogramDIEs.begin(), + AE = InlinedSubprogramDIEs.end(); AI != AE; ++AI) { + DIE *ISP = *AI; + addUInt(ISP, dwarf::DW_AT_inline, 0, dwarf::DW_INL_inlined); + } + + // Standard sections final addresses. + Asm->OutStreamer.SwitchSection(Asm->getObjFileLowering().getTextSection()); + EmitLabel("text_end", 0); + Asm->OutStreamer.SwitchSection(Asm->getObjFileLowering().getDataSection()); + EmitLabel("data_end", 0); + + // End text sections. + for (unsigned i = 1, N = SectionMap.size(); i <= N; ++i) { + Asm->OutStreamer.SwitchSection(SectionMap[i]); + EmitLabel("section_end", i); + } + + // Emit common frame information. + emitCommonDebugFrame(); + + // Emit function debug frame information + for (std::vector::iterator I = DebugFrames.begin(), + E = DebugFrames.end(); I != E; ++I) + emitFunctionDebugFrame(*I); + + // Compute DIE offsets and sizes. + computeSizeAndOffsets(); + + // Emit all the DIEs into a debug info section + emitDebugInfo(); + + // Corresponding abbreviations into a abbrev section. + emitAbbreviations(); + + // Emit source line correspondence into a debug line section. + emitDebugLines(); + + // Emit info into a debug pubnames section. + emitDebugPubNames(); + + // Emit info into a debug pubtypes section. + emitDebugPubTypes(); + + // Emit info into a debug str section. + emitDebugStr(); + + // Emit info into a debug loc section. + emitDebugLoc(); + + // Emit info into a debug aranges section. + EmitDebugARanges(); + + // Emit info into a debug ranges section. + emitDebugRanges(); + + // Emit info into a debug macinfo section. + emitDebugMacInfo(); + + // Emit inline info. + emitDebugInlineInfo(); + + if (TimePassesIsEnabled) + DebugTimer->stopTimer(); +} + +/// findAbstractVariable - Find abstract variable, if any, associated with Var. +DbgVariable *DwarfDebug::findAbstractVariable(DIVariable &Var, + unsigned FrameIdx, + DILocation &ScopeLoc) { + + DbgVariable *AbsDbgVariable = AbstractVariables.lookup(Var.getNode()); + if (AbsDbgVariable) + return AbsDbgVariable; + + DbgScope *Scope = AbstractScopes.lookup(ScopeLoc.getScope().getNode()); + if (!Scope) + return NULL; + + AbsDbgVariable = new DbgVariable(Var, FrameIdx); + Scope->addVariable(AbsDbgVariable); + AbstractVariables[Var.getNode()] = AbsDbgVariable; + return AbsDbgVariable; +} + +/// collectVariableInfo - Populate DbgScope entries with variables' info. +void DwarfDebug::collectVariableInfo() { + if (!MMI) return; + + MachineModuleInfo::VariableDbgInfoMapTy &VMap = MMI->getVariableDbgInfo(); + for (MachineModuleInfo::VariableDbgInfoMapTy::iterator VI = VMap.begin(), + VE = VMap.end(); VI != VE; ++VI) { + MetadataBase *MB = VI->first; + MDNode *Var = dyn_cast_or_null(MB); + if (!Var) continue; + DIVariable DV (Var); + std::pair< unsigned, MDNode *> VP = VI->second; + DILocation ScopeLoc(VP.second); + + DbgScope *Scope = + ConcreteScopes.lookup(ScopeLoc.getOrigLocation().getNode()); + if (!Scope) + Scope = DbgScopeMap.lookup(ScopeLoc.getScope().getNode()); + // If variable scope is not found then skip this variable. + if (!Scope) + continue; + + DbgVariable *RegVar = new DbgVariable(DV, VP.first); + Scope->addVariable(RegVar); + if (DbgVariable *AbsDbgVariable = findAbstractVariable(DV, VP.first, + ScopeLoc)) + RegVar->setAbstractVariable(AbsDbgVariable); + } +} + +/// beginScope - Process beginning of a scope starting at Label. +void DwarfDebug::beginScope(const MachineInstr *MI, unsigned Label) { + InsnToDbgScopeMapTy::iterator I = DbgScopeBeginMap.find(MI); + if (I == DbgScopeBeginMap.end()) + return; + ScopeVector &SD = I->second; + for (ScopeVector::iterator SDI = SD.begin(), SDE = SD.end(); + SDI != SDE; ++SDI) + (*SDI)->setStartLabelID(Label); +} + +/// endScope - Process end of a scope. +void DwarfDebug::endScope(const MachineInstr *MI) { + InsnToDbgScopeMapTy::iterator I = DbgScopeEndMap.find(MI); + if (I == DbgScopeEndMap.end()) + return; + + unsigned Label = MMI->NextLabelID(); + Asm->printLabel(Label); + + SmallVector &SD = I->second; + for (SmallVector::iterator SDI = SD.begin(), SDE = SD.end(); + SDI != SDE; ++SDI) + (*SDI)->setEndLabelID(Label); + return; +} + +/// createDbgScope - Create DbgScope for the scope. +void DwarfDebug::createDbgScope(MDNode *Scope, MDNode *InlinedAt) { + + if (!InlinedAt) { + DbgScope *WScope = DbgScopeMap.lookup(Scope); + if (WScope) + return; + WScope = new DbgScope(NULL, DIDescriptor(Scope), NULL); + DbgScopeMap.insert(std::make_pair(Scope, WScope)); + if (DIDescriptor(Scope).isLexicalBlock()) + createDbgScope(DILexicalBlock(Scope).getContext().getNode(), NULL); + return; + } + + DbgScope *WScope = DbgScopeMap.lookup(InlinedAt); + if (WScope) + return; + + WScope = new DbgScope(NULL, DIDescriptor(Scope), InlinedAt); + DbgScopeMap.insert(std::make_pair(InlinedAt, WScope)); + DILocation DL(InlinedAt); + createDbgScope(DL.getScope().getNode(), DL.getOrigLocation().getNode()); +} + +/// extractScopeInformation - Scan machine instructions in this function +/// and collect DbgScopes. Return true, if atleast one scope was found. +bool DwarfDebug::extractScopeInformation(MachineFunction *MF) { + // If scope information was extracted using .dbg intrinsics then there is not + // any need to extract these information by scanning each instruction. + if (!DbgScopeMap.empty()) + return false; + + // Scan each instruction and create scopes. First build working set of scopes. + for (MachineFunction::const_iterator I = MF->begin(), E = MF->end(); + I != E; ++I) { + for (MachineBasicBlock::const_iterator II = I->begin(), IE = I->end(); + II != IE; ++II) { + const MachineInstr *MInsn = II; + DebugLoc DL = MInsn->getDebugLoc(); + if (DL.isUnknown()) continue; + DebugLocTuple DLT = MF->getDebugLocTuple(DL); + if (!DLT.Scope) continue; + // There is no need to create another DIE for compile unit. For all + // other scopes, create one DbgScope now. This will be translated + // into a scope DIE at the end. + if (DIDescriptor(DLT.Scope).isCompileUnit()) continue; + createDbgScope(DLT.Scope, DLT.InlinedAtLoc); + } + } + + + // Build scope hierarchy using working set of scopes. + for (MachineFunction::const_iterator I = MF->begin(), E = MF->end(); + I != E; ++I) { + for (MachineBasicBlock::const_iterator II = I->begin(), IE = I->end(); + II != IE; ++II) { + const MachineInstr *MInsn = II; + DebugLoc DL = MInsn->getDebugLoc(); + if (DL.isUnknown()) continue; + DebugLocTuple DLT = MF->getDebugLocTuple(DL); + if (!DLT.Scope) continue; + // There is no need to create another DIE for compile unit. For all + // other scopes, create one DbgScope now. This will be translated + // into a scope DIE at the end. + if (DIDescriptor(DLT.Scope).isCompileUnit()) continue; + DbgScope *Scope = getUpdatedDbgScope(DLT.Scope, MInsn, DLT.InlinedAtLoc); + Scope->setLastInsn(MInsn); + } + } + + // If a scope's last instruction is not set then use its child scope's + // last instruction as this scope's last instrunction. + for (ValueMap::iterator DI = DbgScopeMap.begin(), + DE = DbgScopeMap.end(); DI != DE; ++DI) { + if (DI->second->isAbstractScope()) + continue; + assert (DI->second->getFirstInsn() && "Invalid first instruction!"); + DI->second->fixInstructionMarkers(); + assert (DI->second->getLastInsn() && "Invalid last instruction!"); + } + + // Each scope has first instruction and last instruction to mark beginning + // and end of a scope respectively. Create an inverse map that list scopes + // starts (and ends) with an instruction. One instruction may start (or end) + // multiple scopes. + for (ValueMap::iterator DI = DbgScopeMap.begin(), + DE = DbgScopeMap.end(); DI != DE; ++DI) { + DbgScope *S = DI->second; + if (S->isAbstractScope()) + continue; + const MachineInstr *MI = S->getFirstInsn(); + assert (MI && "DbgScope does not have first instruction!"); + + InsnToDbgScopeMapTy::iterator IDI = DbgScopeBeginMap.find(MI); + if (IDI != DbgScopeBeginMap.end()) + IDI->second.push_back(S); + else + DbgScopeBeginMap[MI].push_back(S); + + MI = S->getLastInsn(); + assert (MI && "DbgScope does not have last instruction!"); + IDI = DbgScopeEndMap.find(MI); + if (IDI != DbgScopeEndMap.end()) + IDI->second.push_back(S); + else + DbgScopeEndMap[MI].push_back(S); + } + + return !DbgScopeMap.empty(); +} + +/// beginFunction - Gather pre-function debug information. Assumes being +/// emitted immediately after the function entry point. +void DwarfDebug::beginFunction(MachineFunction *MF) { + this->MF = MF; + + if (!ShouldEmitDwarfDebug()) return; + + if (TimePassesIsEnabled) + DebugTimer->startTimer(); + + if (!extractScopeInformation(MF)) + return; + + collectVariableInfo(); + + // Begin accumulating function debug information. + MMI->BeginFunction(MF); + + // Assumes in correct section after the entry point. + EmitLabel("func_begin", ++SubprogramCount); + + // Emit label for the implicitly defined dbg.stoppoint at the start of the + // function. + DebugLoc FDL = MF->getDefaultDebugLoc(); + if (!FDL.isUnknown()) { + DebugLocTuple DLT = MF->getDebugLocTuple(FDL); + unsigned LabelID = 0; + DISubprogram SP = getDISubprogram(DLT.Scope); + if (!SP.isNull()) + LabelID = recordSourceLine(SP.getLineNumber(), 0, DLT.Scope); + else + LabelID = recordSourceLine(DLT.Line, DLT.Col, DLT.Scope); + Asm->printLabel(LabelID); + O << '\n'; + } + if (TimePassesIsEnabled) + DebugTimer->stopTimer(); +} + +/// endFunction - Gather and emit post-function debug information. +/// +void DwarfDebug::endFunction(MachineFunction *MF) { + if (!ShouldEmitDwarfDebug()) return; + + if (TimePassesIsEnabled) + DebugTimer->startTimer(); + + if (DbgScopeMap.empty()) + return; + + // Define end label for subprogram. + EmitLabel("func_end", SubprogramCount); + + // Get function line info. + if (!Lines.empty()) { + // Get section line info. + unsigned ID = SectionMap.insert(Asm->getCurrentSection()); + if (SectionSourceLines.size() < ID) SectionSourceLines.resize(ID); + std::vector &SectionLineInfos = SectionSourceLines[ID-1]; + // Append the function info to section info. + SectionLineInfos.insert(SectionLineInfos.end(), + Lines.begin(), Lines.end()); + } + + // Construct abstract scopes. + for (SmallVector::iterator AI = AbstractScopesList.begin(), + AE = AbstractScopesList.end(); AI != AE; ++AI) + constructScopeDIE(*AI); + + constructScopeDIE(CurrentFnDbgScope); + + DebugFrames.push_back(FunctionDebugFrameInfo(SubprogramCount, + MMI->getFrameMoves())); + + // Clear debug info + if (CurrentFnDbgScope) { + CurrentFnDbgScope = NULL; + DbgScopeMap.clear(); + DbgScopeBeginMap.clear(); + DbgScopeEndMap.clear(); + ConcreteScopes.clear(); + AbstractScopesList.clear(); + } + + Lines.clear(); + + if (TimePassesIsEnabled) + DebugTimer->stopTimer(); +} + +/// recordSourceLine - Records location information and associates it with a +/// label. Returns a unique label ID used to generate a label and provide +/// correspondence to the source line list. +unsigned DwarfDebug::recordSourceLine(unsigned Line, unsigned Col, + MDNode *S) { + if (!MMI) + return 0; + + if (TimePassesIsEnabled) + DebugTimer->startTimer(); + + StringRef Dir; + StringRef Fn; + + DIDescriptor Scope(S); + if (Scope.isCompileUnit()) { + DICompileUnit CU(S); + Dir = CU.getDirectory(); + Fn = CU.getFilename(); + } else if (Scope.isSubprogram()) { + DISubprogram SP(S); + Dir = SP.getDirectory(); + Fn = SP.getFilename(); + } else if (Scope.isLexicalBlock()) { + DILexicalBlock DB(S); + Dir = DB.getDirectory(); + Fn = DB.getFilename(); + } else + assert (0 && "Unexpected scope info"); + + unsigned Src = GetOrCreateSourceID(Dir, Fn); + unsigned ID = MMI->NextLabelID(); + Lines.push_back(SrcLineInfo(Line, Col, Src, ID)); + + if (TimePassesIsEnabled) + DebugTimer->stopTimer(); + + return ID; +} + +/// getOrCreateSourceID - Public version of GetOrCreateSourceID. This can be +/// timed. Look up the source id with the given directory and source file +/// names. If none currently exists, create a new id and insert it in the +/// SourceIds map. This can update DirectoryNames and SourceFileNames maps as +/// well. +unsigned DwarfDebug::getOrCreateSourceID(const std::string &DirName, + const std::string &FileName) { + if (TimePassesIsEnabled) + DebugTimer->startTimer(); + + unsigned SrcId = GetOrCreateSourceID(DirName.c_str(), FileName.c_str()); + + if (TimePassesIsEnabled) + DebugTimer->stopTimer(); + + return SrcId; +} + +//===----------------------------------------------------------------------===// +// Emit Methods +//===----------------------------------------------------------------------===// + +/// computeSizeAndOffset - Compute the size and offset of a DIE. +/// +unsigned +DwarfDebug::computeSizeAndOffset(DIE *Die, unsigned Offset, bool Last) { + // Get the children. + const std::vector &Children = Die->getChildren(); + + // If not last sibling and has children then add sibling offset attribute. + if (!Last && !Children.empty()) Die->addSiblingOffset(); + + // Record the abbreviation. + assignAbbrevNumber(Die->getAbbrev()); + + // Get the abbreviation for this DIE. + unsigned AbbrevNumber = Die->getAbbrevNumber(); + const DIEAbbrev *Abbrev = Abbreviations[AbbrevNumber - 1]; + + // Set DIE offset + Die->setOffset(Offset); + + // Start the size with the size of abbreviation code. + Offset += MCAsmInfo::getULEB128Size(AbbrevNumber); + + const SmallVector &Values = Die->getValues(); + const SmallVector &AbbrevData = Abbrev->getData(); + + // Size the DIE attribute values. + for (unsigned i = 0, N = Values.size(); i < N; ++i) + // Size attribute value. + Offset += Values[i]->SizeOf(TD, AbbrevData[i].getForm()); + + // Size the DIE children if any. + if (!Children.empty()) { + assert(Abbrev->getChildrenFlag() == dwarf::DW_CHILDREN_yes && + "Children flag not set"); + + for (unsigned j = 0, M = Children.size(); j < M; ++j) + Offset = computeSizeAndOffset(Children[j], Offset, (j + 1) == M); + + // End of children marker. + Offset += sizeof(int8_t); + } + + Die->setSize(Offset - Die->getOffset()); + return Offset; +} + +/// computeSizeAndOffsets - Compute the size and offset of all the DIEs. +/// +void DwarfDebug::computeSizeAndOffsets() { + // Compute size of compile unit header. + static unsigned Offset = + sizeof(int32_t) + // Length of Compilation Unit Info + sizeof(int16_t) + // DWARF version number + sizeof(int32_t) + // Offset Into Abbrev. Section + sizeof(int8_t); // Pointer Size (in bytes) + + computeSizeAndOffset(ModuleCU->getCUDie(), Offset, true); + CompileUnitOffsets[ModuleCU] = 0; +} + +/// emitInitial - Emit initial Dwarf declarations. This is necessary for cc +/// tools to recognize the object file contains Dwarf information. +void DwarfDebug::emitInitial() { + // Check to see if we already emitted intial headers. + if (didInitial) return; + didInitial = true; + + const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering(); + + // Dwarf sections base addresses. + if (MAI->doesDwarfRequireFrameSection()) { + Asm->OutStreamer.SwitchSection(TLOF.getDwarfFrameSection()); + EmitLabel("section_debug_frame", 0); + } + + Asm->OutStreamer.SwitchSection(TLOF.getDwarfInfoSection()); + EmitLabel("section_info", 0); + Asm->OutStreamer.SwitchSection(TLOF.getDwarfAbbrevSection()); + EmitLabel("section_abbrev", 0); + Asm->OutStreamer.SwitchSection(TLOF.getDwarfARangesSection()); + EmitLabel("section_aranges", 0); + + if (const MCSection *LineInfoDirective = TLOF.getDwarfMacroInfoSection()) { + Asm->OutStreamer.SwitchSection(LineInfoDirective); + EmitLabel("section_macinfo", 0); + } + + Asm->OutStreamer.SwitchSection(TLOF.getDwarfLineSection()); + EmitLabel("section_line", 0); + Asm->OutStreamer.SwitchSection(TLOF.getDwarfLocSection()); + EmitLabel("section_loc", 0); + Asm->OutStreamer.SwitchSection(TLOF.getDwarfPubNamesSection()); + EmitLabel("section_pubnames", 0); + Asm->OutStreamer.SwitchSection(TLOF.getDwarfPubTypesSection()); + EmitLabel("section_pubtypes", 0); + Asm->OutStreamer.SwitchSection(TLOF.getDwarfStrSection()); + EmitLabel("section_str", 0); + Asm->OutStreamer.SwitchSection(TLOF.getDwarfRangesSection()); + EmitLabel("section_ranges", 0); + + Asm->OutStreamer.SwitchSection(TLOF.getTextSection()); + EmitLabel("text_begin", 0); + Asm->OutStreamer.SwitchSection(TLOF.getDataSection()); + EmitLabel("data_begin", 0); +} + +/// emitDIE - Recusively Emits a debug information entry. +/// +void DwarfDebug::emitDIE(DIE *Die) { + // Get the abbreviation for this DIE. + unsigned AbbrevNumber = Die->getAbbrevNumber(); + const DIEAbbrev *Abbrev = Abbreviations[AbbrevNumber - 1]; + + Asm->EOL(); + + // Emit the code (index) for the abbreviation. + Asm->EmitULEB128Bytes(AbbrevNumber); + + if (Asm->isVerbose()) + Asm->EOL(std::string("Abbrev [" + + utostr(AbbrevNumber) + + "] 0x" + utohexstr(Die->getOffset()) + + ":0x" + utohexstr(Die->getSize()) + " " + + dwarf::TagString(Abbrev->getTag()))); + else + Asm->EOL(); + + SmallVector &Values = Die->getValues(); + const SmallVector &AbbrevData = Abbrev->getData(); + + // Emit the DIE attribute values. + for (unsigned i = 0, N = Values.size(); i < N; ++i) { + unsigned Attr = AbbrevData[i].getAttribute(); + unsigned Form = AbbrevData[i].getForm(); + assert(Form && "Too many attributes for DIE (check abbreviation)"); + + switch (Attr) { + case dwarf::DW_AT_sibling: + Asm->EmitInt32(Die->getSiblingOffset()); + break; + case dwarf::DW_AT_abstract_origin: { + DIEEntry *E = cast(Values[i]); + DIE *Origin = E->getEntry(); + unsigned Addr = Origin->getOffset(); + Asm->EmitInt32(Addr); + break; + } + default: + // Emit an attribute using the defined form. + Values[i]->EmitValue(this, Form); + break; + } + + Asm->EOL(dwarf::AttributeString(Attr)); + } + + // Emit the DIE children if any. + if (Abbrev->getChildrenFlag() == dwarf::DW_CHILDREN_yes) { + const std::vector &Children = Die->getChildren(); + + for (unsigned j = 0, M = Children.size(); j < M; ++j) + emitDIE(Children[j]); + + Asm->EmitInt8(0); Asm->EOL("End Of Children Mark"); + } +} + +/// emitDebugInfo / emitDebugInfoPerCU - Emit the debug info section. +/// +void DwarfDebug::emitDebugInfoPerCU(CompileUnit *Unit) { + DIE *Die = Unit->getCUDie(); + + // Emit the compile units header. + EmitLabel("info_begin", Unit->getID()); + + // Emit size of content not including length itself + unsigned ContentSize = Die->getSize() + + sizeof(int16_t) + // DWARF version number + sizeof(int32_t) + // Offset Into Abbrev. Section + sizeof(int8_t) + // Pointer Size (in bytes) + sizeof(int32_t); // FIXME - extra pad for gdb bug. + + Asm->EmitInt32(ContentSize); Asm->EOL("Length of Compilation Unit Info"); + Asm->EmitInt16(dwarf::DWARF_VERSION); Asm->EOL("DWARF version number"); + EmitSectionOffset("abbrev_begin", "section_abbrev", 0, 0, true, false); + Asm->EOL("Offset Into Abbrev. Section"); + Asm->EmitInt8(TD->getPointerSize()); Asm->EOL("Address Size (in bytes)"); + + emitDIE(Die); + // FIXME - extra padding for gdb bug. + Asm->EmitInt8(0); Asm->EOL("Extra Pad For GDB"); + Asm->EmitInt8(0); Asm->EOL("Extra Pad For GDB"); + Asm->EmitInt8(0); Asm->EOL("Extra Pad For GDB"); + Asm->EmitInt8(0); Asm->EOL("Extra Pad For GDB"); + EmitLabel("info_end", Unit->getID()); + + Asm->EOL(); +} + +void DwarfDebug::emitDebugInfo() { + // Start debug info section. + Asm->OutStreamer.SwitchSection( + Asm->getObjFileLowering().getDwarfInfoSection()); + + emitDebugInfoPerCU(ModuleCU); +} + +/// emitAbbreviations - Emit the abbreviation section. +/// +void DwarfDebug::emitAbbreviations() const { + // Check to see if it is worth the effort. + if (!Abbreviations.empty()) { + // Start the debug abbrev section. + Asm->OutStreamer.SwitchSection( + Asm->getObjFileLowering().getDwarfAbbrevSection()); + + EmitLabel("abbrev_begin", 0); + + // For each abbrevation. + for (unsigned i = 0, N = Abbreviations.size(); i < N; ++i) { + // Get abbreviation data + const DIEAbbrev *Abbrev = Abbreviations[i]; + + // Emit the abbrevations code (base 1 index.) + Asm->EmitULEB128Bytes(Abbrev->getNumber()); + Asm->EOL("Abbreviation Code"); + + // Emit the abbreviations data. + Abbrev->Emit(Asm); + + Asm->EOL(); + } + + // Mark end of abbreviations. + Asm->EmitULEB128Bytes(0); Asm->EOL("EOM(3)"); + + EmitLabel("abbrev_end", 0); + Asm->EOL(); + } +} + +/// emitEndOfLineMatrix - Emit the last address of the section and the end of +/// the line matrix. +/// +void DwarfDebug::emitEndOfLineMatrix(unsigned SectionEnd) { + // Define last address of section. + Asm->EmitInt8(0); Asm->EOL("Extended Op"); + Asm->EmitInt8(TD->getPointerSize() + 1); Asm->EOL("Op size"); + Asm->EmitInt8(dwarf::DW_LNE_set_address); Asm->EOL("DW_LNE_set_address"); + EmitReference("section_end", SectionEnd); Asm->EOL("Section end label"); + + // Mark end of matrix. + Asm->EmitInt8(0); Asm->EOL("DW_LNE_end_sequence"); + Asm->EmitULEB128Bytes(1); Asm->EOL(); + Asm->EmitInt8(1); Asm->EOL(); +} + +/// emitDebugLines - Emit source line information. +/// +void DwarfDebug::emitDebugLines() { + // If the target is using .loc/.file, the assembler will be emitting the + // .debug_line table automatically. + if (MAI->hasDotLocAndDotFile()) + return; + + // Minimum line delta, thus ranging from -10..(255-10). + const int MinLineDelta = -(dwarf::DW_LNS_fixed_advance_pc + 1); + // Maximum line delta, thus ranging from -10..(255-10). + const int MaxLineDelta = 255 + MinLineDelta; + + // Start the dwarf line section. + Asm->OutStreamer.SwitchSection( + Asm->getObjFileLowering().getDwarfLineSection()); + + // Construct the section header. + EmitDifference("line_end", 0, "line_begin", 0, true); + Asm->EOL("Length of Source Line Info"); + EmitLabel("line_begin", 0); + + Asm->EmitInt16(dwarf::DWARF_VERSION); Asm->EOL("DWARF version number"); + + EmitDifference("line_prolog_end", 0, "line_prolog_begin", 0, true); + Asm->EOL("Prolog Length"); + EmitLabel("line_prolog_begin", 0); + + Asm->EmitInt8(1); Asm->EOL("Minimum Instruction Length"); + + Asm->EmitInt8(1); Asm->EOL("Default is_stmt_start flag"); + + Asm->EmitInt8(MinLineDelta); Asm->EOL("Line Base Value (Special Opcodes)"); + + Asm->EmitInt8(MaxLineDelta); Asm->EOL("Line Range Value (Special Opcodes)"); + + Asm->EmitInt8(-MinLineDelta); Asm->EOL("Special Opcode Base"); + + // Line number standard opcode encodings argument count + Asm->EmitInt8(0); Asm->EOL("DW_LNS_copy arg count"); + Asm->EmitInt8(1); Asm->EOL("DW_LNS_advance_pc arg count"); + Asm->EmitInt8(1); Asm->EOL("DW_LNS_advance_line arg count"); + Asm->EmitInt8(1); Asm->EOL("DW_LNS_set_file arg count"); + Asm->EmitInt8(1); Asm->EOL("DW_LNS_set_column arg count"); + Asm->EmitInt8(0); Asm->EOL("DW_LNS_negate_stmt arg count"); + Asm->EmitInt8(0); Asm->EOL("DW_LNS_set_basic_block arg count"); + Asm->EmitInt8(0); Asm->EOL("DW_LNS_const_add_pc arg count"); + Asm->EmitInt8(1); Asm->EOL("DW_LNS_fixed_advance_pc arg count"); + + // Emit directories. + for (unsigned DI = 1, DE = getNumSourceDirectories()+1; DI != DE; ++DI) { + Asm->EmitString(getSourceDirectoryName(DI)); + Asm->EOL("Directory"); + } + + Asm->EmitInt8(0); Asm->EOL("End of directories"); + + // Emit files. + for (unsigned SI = 1, SE = getNumSourceIds()+1; SI != SE; ++SI) { + // Remember source id starts at 1. + std::pair Id = getSourceDirectoryAndFileIds(SI); + Asm->EmitString(getSourceFileName(Id.second)); + Asm->EOL("Source"); + Asm->EmitULEB128Bytes(Id.first); + Asm->EOL("Directory #"); + Asm->EmitULEB128Bytes(0); + Asm->EOL("Mod date"); + Asm->EmitULEB128Bytes(0); + Asm->EOL("File size"); + } + + Asm->EmitInt8(0); Asm->EOL("End of files"); + + EmitLabel("line_prolog_end", 0); + + // A sequence for each text section. + unsigned SecSrcLinesSize = SectionSourceLines.size(); + + for (unsigned j = 0; j < SecSrcLinesSize; ++j) { + // Isolate current sections line info. + const std::vector &LineInfos = SectionSourceLines[j]; + + /*if (Asm->isVerbose()) { + const MCSection *S = SectionMap[j + 1]; + O << '\t' << MAI->getCommentString() << " Section" + << S->getName() << '\n'; + }*/ + Asm->EOL(); + + // Dwarf assumes we start with first line of first source file. + unsigned Source = 1; + unsigned Line = 1; + + // Construct rows of the address, source, line, column matrix. + for (unsigned i = 0, N = LineInfos.size(); i < N; ++i) { + const SrcLineInfo &LineInfo = LineInfos[i]; + unsigned LabelID = MMI->MappedLabel(LineInfo.getLabelID()); + if (!LabelID) continue; + + if (LineInfo.getLine() == 0) continue; + + if (!Asm->isVerbose()) + Asm->EOL(); + else { + std::pair SourceID = + getSourceDirectoryAndFileIds(LineInfo.getSourceID()); + O << '\t' << MAI->getCommentString() << ' ' + << getSourceDirectoryName(SourceID.first) << ' ' + << getSourceFileName(SourceID.second) + <<" :" << utostr_32(LineInfo.getLine()) << '\n'; + } + + // Define the line address. + Asm->EmitInt8(0); Asm->EOL("Extended Op"); + Asm->EmitInt8(TD->getPointerSize() + 1); Asm->EOL("Op size"); + Asm->EmitInt8(dwarf::DW_LNE_set_address); Asm->EOL("DW_LNE_set_address"); + EmitReference("label", LabelID); Asm->EOL("Location label"); + + // If change of source, then switch to the new source. + if (Source != LineInfo.getSourceID()) { + Source = LineInfo.getSourceID(); + Asm->EmitInt8(dwarf::DW_LNS_set_file); Asm->EOL("DW_LNS_set_file"); + Asm->EmitULEB128Bytes(Source); Asm->EOL("New Source"); + } + + // If change of line. + if (Line != LineInfo.getLine()) { + // Determine offset. + int Offset = LineInfo.getLine() - Line; + int Delta = Offset - MinLineDelta; + + // Update line. + Line = LineInfo.getLine(); + + // If delta is small enough and in range... + if (Delta >= 0 && Delta < (MaxLineDelta - 1)) { + // ... then use fast opcode. + Asm->EmitInt8(Delta - MinLineDelta); Asm->EOL("Line Delta"); + } else { + // ... otherwise use long hand. + Asm->EmitInt8(dwarf::DW_LNS_advance_line); + Asm->EOL("DW_LNS_advance_line"); + Asm->EmitSLEB128Bytes(Offset); Asm->EOL("Line Offset"); + Asm->EmitInt8(dwarf::DW_LNS_copy); Asm->EOL("DW_LNS_copy"); + } + } else { + // Copy the previous row (different address or source) + Asm->EmitInt8(dwarf::DW_LNS_copy); Asm->EOL("DW_LNS_copy"); + } + } + + emitEndOfLineMatrix(j + 1); + } + + if (SecSrcLinesSize == 0) + // Because we're emitting a debug_line section, we still need a line + // table. The linker and friends expect it to exist. If there's nothing to + // put into it, emit an empty table. + emitEndOfLineMatrix(1); + + EmitLabel("line_end", 0); + Asm->EOL(); +} + +/// emitCommonDebugFrame - Emit common frame info into a debug frame section. +/// +void DwarfDebug::emitCommonDebugFrame() { + if (!MAI->doesDwarfRequireFrameSection()) + return; + + int stackGrowth = + Asm->TM.getFrameInfo()->getStackGrowthDirection() == + TargetFrameInfo::StackGrowsUp ? + TD->getPointerSize() : -TD->getPointerSize(); + + // Start the dwarf frame section. + Asm->OutStreamer.SwitchSection( + Asm->getObjFileLowering().getDwarfFrameSection()); + + EmitLabel("debug_frame_common", 0); + EmitDifference("debug_frame_common_end", 0, + "debug_frame_common_begin", 0, true); + Asm->EOL("Length of Common Information Entry"); + + EmitLabel("debug_frame_common_begin", 0); + Asm->EmitInt32((int)dwarf::DW_CIE_ID); + Asm->EOL("CIE Identifier Tag"); + Asm->EmitInt8(dwarf::DW_CIE_VERSION); + Asm->EOL("CIE Version"); + Asm->EmitString(""); + Asm->EOL("CIE Augmentation"); + Asm->EmitULEB128Bytes(1); + Asm->EOL("CIE Code Alignment Factor"); + Asm->EmitSLEB128Bytes(stackGrowth); + Asm->EOL("CIE Data Alignment Factor"); + Asm->EmitInt8(RI->getDwarfRegNum(RI->getRARegister(), false)); + Asm->EOL("CIE RA Column"); + + std::vector Moves; + RI->getInitialFrameState(Moves); + + EmitFrameMoves(NULL, 0, Moves, false); + + Asm->EmitAlignment(2, 0, 0, false); + EmitLabel("debug_frame_common_end", 0); + + Asm->EOL(); +} + +/// emitFunctionDebugFrame - Emit per function frame info into a debug frame +/// section. +void +DwarfDebug::emitFunctionDebugFrame(const FunctionDebugFrameInfo&DebugFrameInfo){ + if (!MAI->doesDwarfRequireFrameSection()) + return; + + // Start the dwarf frame section. + Asm->OutStreamer.SwitchSection( + Asm->getObjFileLowering().getDwarfFrameSection()); + + EmitDifference("debug_frame_end", DebugFrameInfo.Number, + "debug_frame_begin", DebugFrameInfo.Number, true); + Asm->EOL("Length of Frame Information Entry"); + + EmitLabel("debug_frame_begin", DebugFrameInfo.Number); + + EmitSectionOffset("debug_frame_common", "section_debug_frame", + 0, 0, true, false); + Asm->EOL("FDE CIE offset"); + + EmitReference("func_begin", DebugFrameInfo.Number); + Asm->EOL("FDE initial location"); + EmitDifference("func_end", DebugFrameInfo.Number, + "func_begin", DebugFrameInfo.Number); + Asm->EOL("FDE address range"); + + EmitFrameMoves("func_begin", DebugFrameInfo.Number, DebugFrameInfo.Moves, + false); + + Asm->EmitAlignment(2, 0, 0, false); + EmitLabel("debug_frame_end", DebugFrameInfo.Number); + + Asm->EOL(); +} + +void DwarfDebug::emitDebugPubNamesPerCU(CompileUnit *Unit) { + EmitDifference("pubnames_end", Unit->getID(), + "pubnames_begin", Unit->getID(), true); + Asm->EOL("Length of Public Names Info"); + + EmitLabel("pubnames_begin", Unit->getID()); + + Asm->EmitInt16(dwarf::DWARF_VERSION); Asm->EOL("DWARF Version"); + + EmitSectionOffset("info_begin", "section_info", + Unit->getID(), 0, true, false); + Asm->EOL("Offset of Compilation Unit Info"); + + EmitDifference("info_end", Unit->getID(), "info_begin", Unit->getID(), + true); + Asm->EOL("Compilation Unit Length"); + + const StringMap &Globals = Unit->getGlobals(); + for (StringMap::const_iterator + GI = Globals.begin(), GE = Globals.end(); GI != GE; ++GI) { + const char *Name = GI->getKeyData(); + DIE * Entity = GI->second; + + Asm->EmitInt32(Entity->getOffset()); Asm->EOL("DIE offset"); + Asm->EmitString(Name, strlen(Name)); Asm->EOL("External Name"); + } + + Asm->EmitInt32(0); Asm->EOL("End Mark"); + EmitLabel("pubnames_end", Unit->getID()); + + Asm->EOL(); +} + +/// emitDebugPubNames - Emit visible names into a debug pubnames section. +/// +void DwarfDebug::emitDebugPubNames() { + // Start the dwarf pubnames section. + Asm->OutStreamer.SwitchSection( + Asm->getObjFileLowering().getDwarfPubNamesSection()); + + emitDebugPubNamesPerCU(ModuleCU); +} + +void DwarfDebug::emitDebugPubTypes() { + // Start the dwarf pubnames section. + Asm->OutStreamer.SwitchSection( + Asm->getObjFileLowering().getDwarfPubTypesSection()); + EmitDifference("pubtypes_end", ModuleCU->getID(), + "pubtypes_begin", ModuleCU->getID(), true); + Asm->EOL("Length of Public Types Info"); + + EmitLabel("pubtypes_begin", ModuleCU->getID()); + + Asm->EmitInt16(dwarf::DWARF_VERSION); Asm->EOL("DWARF Version"); + + EmitSectionOffset("info_begin", "section_info", + ModuleCU->getID(), 0, true, false); + Asm->EOL("Offset of Compilation ModuleCU Info"); + + EmitDifference("info_end", ModuleCU->getID(), "info_begin", ModuleCU->getID(), + true); + Asm->EOL("Compilation ModuleCU Length"); + + const StringMap &Globals = ModuleCU->getGlobalTypes(); + for (StringMap::const_iterator + GI = Globals.begin(), GE = Globals.end(); GI != GE; ++GI) { + const char *Name = GI->getKeyData(); + DIE * Entity = GI->second; + + Asm->EmitInt32(Entity->getOffset()); Asm->EOL("DIE offset"); + Asm->EmitString(Name, strlen(Name)); Asm->EOL("External Name"); + } + + Asm->EmitInt32(0); Asm->EOL("End Mark"); + EmitLabel("pubtypes_end", ModuleCU->getID()); + + Asm->EOL(); +} + +/// emitDebugStr - Emit visible names into a debug str section. +/// +void DwarfDebug::emitDebugStr() { + // Check to see if it is worth the effort. + if (!StringPool.empty()) { + // Start the dwarf str section. + Asm->OutStreamer.SwitchSection( + Asm->getObjFileLowering().getDwarfStrSection()); + + // For each of strings in the string pool. + for (unsigned StringID = 1, N = StringPool.size(); + StringID <= N; ++StringID) { + // Emit a label for reference from debug information entries. + EmitLabel("string", StringID); + + // Emit the string itself. + const std::string &String = StringPool[StringID]; + Asm->EmitString(String); Asm->EOL(); + } + + Asm->EOL(); + } +} + +/// emitDebugLoc - Emit visible names into a debug loc section. +/// +void DwarfDebug::emitDebugLoc() { + // Start the dwarf loc section. + Asm->OutStreamer.SwitchSection( + Asm->getObjFileLowering().getDwarfLocSection()); + Asm->EOL(); +} + +/// EmitDebugARanges - Emit visible names into a debug aranges section. +/// +void DwarfDebug::EmitDebugARanges() { + // Start the dwarf aranges section. + Asm->OutStreamer.SwitchSection( + Asm->getObjFileLowering().getDwarfARangesSection()); + + // FIXME - Mock up +#if 0 + CompileUnit *Unit = GetBaseCompileUnit(); + + // Don't include size of length + Asm->EmitInt32(0x1c); Asm->EOL("Length of Address Ranges Info"); + + Asm->EmitInt16(dwarf::DWARF_VERSION); Asm->EOL("Dwarf Version"); + + EmitReference("info_begin", Unit->getID()); + Asm->EOL("Offset of Compilation Unit Info"); + + Asm->EmitInt8(TD->getPointerSize()); Asm->EOL("Size of Address"); + + Asm->EmitInt8(0); Asm->EOL("Size of Segment Descriptor"); + + Asm->EmitInt16(0); Asm->EOL("Pad (1)"); + Asm->EmitInt16(0); Asm->EOL("Pad (2)"); + + // Range 1 + EmitReference("text_begin", 0); Asm->EOL("Address"); + EmitDifference("text_end", 0, "text_begin", 0, true); Asm->EOL("Length"); + + Asm->EmitInt32(0); Asm->EOL("EOM (1)"); + Asm->EmitInt32(0); Asm->EOL("EOM (2)"); +#endif + + Asm->EOL(); +} + +/// emitDebugRanges - Emit visible names into a debug ranges section. +/// +void DwarfDebug::emitDebugRanges() { + // Start the dwarf ranges section. + Asm->OutStreamer.SwitchSection( + Asm->getObjFileLowering().getDwarfRangesSection()); + Asm->EOL(); +} + +/// emitDebugMacInfo - Emit visible names into a debug macinfo section. +/// +void DwarfDebug::emitDebugMacInfo() { + if (const MCSection *LineInfo = + Asm->getObjFileLowering().getDwarfMacroInfoSection()) { + // Start the dwarf macinfo section. + Asm->OutStreamer.SwitchSection(LineInfo); + Asm->EOL(); + } +} + +/// emitDebugInlineInfo - Emit inline info using following format. +/// Section Header: +/// 1. length of section +/// 2. Dwarf version number +/// 3. address size. +/// +/// Entries (one "entry" for each function that was inlined): +/// +/// 1. offset into __debug_str section for MIPS linkage name, if exists; +/// otherwise offset into __debug_str for regular function name. +/// 2. offset into __debug_str section for regular function name. +/// 3. an unsigned LEB128 number indicating the number of distinct inlining +/// instances for the function. +/// +/// The rest of the entry consists of a {die_offset, low_pc} pair for each +/// inlined instance; the die_offset points to the inlined_subroutine die in the +/// __debug_info section, and the low_pc is the starting address for the +/// inlining instance. +void DwarfDebug::emitDebugInlineInfo() { + if (!MAI->doesDwarfUsesInlineInfoSection()) + return; + + if (!ModuleCU) + return; + + Asm->OutStreamer.SwitchSection( + Asm->getObjFileLowering().getDwarfDebugInlineSection()); + Asm->EOL(); + EmitDifference("debug_inlined_end", 1, + "debug_inlined_begin", 1, true); + Asm->EOL("Length of Debug Inlined Information Entry"); + + EmitLabel("debug_inlined_begin", 1); + + Asm->EmitInt16(dwarf::DWARF_VERSION); Asm->EOL("Dwarf Version"); + Asm->EmitInt8(TD->getPointerSize()); Asm->EOL("Address Size (in bytes)"); + + for (SmallVector::iterator I = InlinedSPNodes.begin(), + E = InlinedSPNodes.end(); I != E; ++I) { + +// for (ValueMap >::iterator + // I = InlineInfo.begin(), E = InlineInfo.end(); I != E; ++I) { + MDNode *Node = *I; + ValueMap >::iterator II + = InlineInfo.find(Node); + SmallVector &Labels = II->second; + DISubprogram SP(Node); + StringRef LName = SP.getLinkageName(); + StringRef Name = SP.getName(); + + if (LName.empty()) + Asm->EmitString(Name); + else { + // Skip special LLVM prefix that is used to inform the asm printer to not + // emit usual symbol prefix before the symbol name. This happens for + // Objective-C symbol names and symbol whose name is replaced using GCC's + // __asm__ attribute. + if (LName[0] == 1) + LName = LName.substr(1); +// Asm->EmitString(LName); + EmitSectionOffset("string", "section_str", + StringPool.idFor(LName), false, true); + + } + Asm->EOL("MIPS linkage name"); +// Asm->EmitString(Name); + EmitSectionOffset("string", "section_str", + StringPool.idFor(Name), false, true); + Asm->EOL("Function name"); + Asm->EmitULEB128Bytes(Labels.size()); Asm->EOL("Inline count"); + + for (SmallVector::iterator LI = Labels.begin(), + LE = Labels.end(); LI != LE; ++LI) { + DIE *SP = LI->second; + Asm->EmitInt32(SP->getOffset()); Asm->EOL("DIE offset"); + + if (TD->getPointerSize() == sizeof(int32_t)) + O << MAI->getData32bitsDirective(); + else + O << MAI->getData64bitsDirective(); + + PrintLabelName("label", LI->first); Asm->EOL("low_pc"); + } + } + + EmitLabel("debug_inlined_end", 1); + Asm->EOL(); +} diff --git a/libclamav/c++/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h b/libclamav/c++/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h new file mode 100644 index 000000000..679d9b9d1 --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h @@ -0,0 +1,564 @@ +//===-- llvm/CodeGen/DwarfDebug.h - Dwarf Debug Framework ------*- C++ -*--===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains support for writing dwarf debug info into asm files. +// +//===----------------------------------------------------------------------===// + +#ifndef CODEGEN_ASMPRINTER_DWARFDEBUG_H__ +#define CODEGEN_ASMPRINTER_DWARFDEBUG_H__ + +#include "DIE.h" +#include "DwarfPrinter.h" +#include "llvm/CodeGen/AsmPrinter.h" +#include "llvm/CodeGen/MachineLocation.h" +#include "llvm/Analysis/DebugInfo.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/ADT/ValueMap.h" +#include "llvm/ADT/FoldingSet.h" +#include "llvm/ADT/SmallSet.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/UniqueVector.h" +#include + +namespace llvm { + +class CompileUnit; +class DbgConcreteScope; +class DbgScope; +class DbgVariable; +class MachineFrameInfo; +class MachineModuleInfo; +class MCAsmInfo; +class Timer; + +//===----------------------------------------------------------------------===// +/// SrcLineInfo - This class is used to record source line correspondence. +/// +class SrcLineInfo { + unsigned Line; // Source line number. + unsigned Column; // Source column. + unsigned SourceID; // Source ID number. + unsigned LabelID; // Label in code ID number. +public: + SrcLineInfo(unsigned L, unsigned C, unsigned S, unsigned I) + : Line(L), Column(C), SourceID(S), LabelID(I) {} + + // Accessors + unsigned getLine() const { return Line; } + unsigned getColumn() const { return Column; } + unsigned getSourceID() const { return SourceID; } + unsigned getLabelID() const { return LabelID; } +}; + +class DwarfDebug : public Dwarf { + //===--------------------------------------------------------------------===// + // Attributes used to construct specific Dwarf sections. + // + + /// CompileUnitMap - A map of global variables representing compile units to + /// compile units. + DenseMap CompileUnitMap; + + /// CompileUnits - All the compile units in this module. + /// + SmallVector CompileUnits; + + /// ModuleCU - All DIEs are inserted in ModuleCU. + CompileUnit *ModuleCU; + + /// AbbreviationsSet - Used to uniquely define abbreviations. + /// + FoldingSet AbbreviationsSet; + + /// Abbreviations - A list of all the unique abbreviations in use. + /// + std::vector Abbreviations; + + /// DirectoryIdMap - Directory name to directory id map. + /// + StringMap DirectoryIdMap; + + /// DirectoryNames - A list of directory names. + SmallVector DirectoryNames; + + /// SourceFileIdMap - Source file name to source file id map. + /// + StringMap SourceFileIdMap; + + /// SourceFileNames - A list of source file names. + SmallVector SourceFileNames; + + /// SourceIdMap - Source id map, i.e. pair of directory id and source file + /// id mapped to a unique id. + DenseMap, unsigned> SourceIdMap; + + /// SourceIds - Reverse map from source id to directory id + file id pair. + /// + SmallVector, 8> SourceIds; + + /// Lines - List of of source line correspondence. + std::vector Lines; + + /// DIEValues - A list of all the unique values in use. + /// + std::vector DIEValues; + + /// StringPool - A UniqueVector of strings used by indirect references. + /// + UniqueVector StringPool; + + /// SectionMap - Provides a unique id per text section. + /// + UniqueVector SectionMap; + + /// SectionSourceLines - Tracks line numbers per text section. + /// + std::vector > SectionSourceLines; + + /// didInitial - Flag to indicate if initial emission has been done. + /// + bool didInitial; + + /// shouldEmit - Flag to indicate if debug information should be emitted. + /// + bool shouldEmit; + + // CurrentFnDbgScope - Top level scope for the current function. + // + DbgScope *CurrentFnDbgScope; + + /// DbgScopeMap - Tracks the scopes in the current function. + /// + ValueMap DbgScopeMap; + + /// ConcreteScopes - Tracks the concrete scopees in the current function. + /// These scopes are also included in DbgScopeMap. + ValueMap ConcreteScopes; + + /// AbstractScopes - Tracks the abstract scopes a module. These scopes are + /// not included DbgScopeMap. + ValueMap AbstractScopes; + SmallVectorAbstractScopesList; + + /// AbstractVariables - Collection on abstract variables. + ValueMap AbstractVariables; + + /// InliendSubprogramDIEs - Collection of subprgram DIEs that are marked + /// (at the end of the module) as DW_AT_inline. + SmallPtrSet InlinedSubprogramDIEs; + + /// AbstractSubprogramDIEs - Collection of abstruct subprogram DIEs. + SmallPtrSet AbstractSubprogramDIEs; + + /// ScopedGVs - Tracks global variables that are not at file scope. + /// For example void f() { static int b = 42; } + SmallVector ScopedGVs; + + typedef SmallVector ScopeVector; + typedef DenseMap + InsnToDbgScopeMapTy; + + /// DbgScopeBeginMap - Maps instruction with a list of DbgScopes it starts. + InsnToDbgScopeMapTy DbgScopeBeginMap; + + /// DbgScopeEndMap - Maps instruction with a list DbgScopes it ends. + InsnToDbgScopeMapTy DbgScopeEndMap; + + /// InlineInfo - Keep track of inlined functions and their location. This + /// information is used to populate debug_inlined section. + typedef std::pair InlineInfoLabels; + ValueMap > InlineInfo; + SmallVector InlinedSPNodes; + + /// CompileUnitOffsets - A vector of the offsets of the compile units. This is + /// used when calculating the "origin" of a concrete instance of an inlined + /// function. + DenseMap CompileUnitOffsets; + + /// DebugTimer - Timer for the Dwarf debug writer. + Timer *DebugTimer; + + struct FunctionDebugFrameInfo { + unsigned Number; + std::vector Moves; + + FunctionDebugFrameInfo(unsigned Num, const std::vector &M) + : Number(Num), Moves(M) {} + }; + + std::vector DebugFrames; + + /// getSourceDirectoryAndFileIds - Return the directory and file ids that + /// maps to the source id. Source id starts at 1. + std::pair + getSourceDirectoryAndFileIds(unsigned SId) const { + return SourceIds[SId-1]; + } + + /// getNumSourceDirectories - Return the number of source directories in the + /// debug info. + unsigned getNumSourceDirectories() const { + return DirectoryNames.size(); + } + + /// getSourceDirectoryName - Return the name of the directory corresponding + /// to the id. + const std::string &getSourceDirectoryName(unsigned Id) const { + return DirectoryNames[Id - 1]; + } + + /// getSourceFileName - Return the name of the source file corresponding + /// to the id. + const std::string &getSourceFileName(unsigned Id) const { + return SourceFileNames[Id - 1]; + } + + /// getNumSourceIds - Return the number of unique source ids. + unsigned getNumSourceIds() const { + return SourceIds.size(); + } + + /// assignAbbrevNumber - Define a unique number for the abbreviation. + /// + void assignAbbrevNumber(DIEAbbrev &Abbrev); + + /// createDIEEntry - Creates a new DIEEntry to be a proxy for a debug + /// information entry. + DIEEntry *createDIEEntry(DIE *Entry = NULL); + + /// addUInt - Add an unsigned integer attribute data and value. + /// + void addUInt(DIE *Die, unsigned Attribute, unsigned Form, uint64_t Integer); + + /// addSInt - Add an signed integer attribute data and value. + /// + void addSInt(DIE *Die, unsigned Attribute, unsigned Form, int64_t Integer); + + /// addString - Add a string attribute data and value. + /// + void addString(DIE *Die, unsigned Attribute, unsigned Form, + const StringRef Str); + + /// addLabel - Add a Dwarf label attribute data and value. + /// + void addLabel(DIE *Die, unsigned Attribute, unsigned Form, + const DWLabel &Label); + + /// addObjectLabel - Add an non-Dwarf label attribute data and value. + /// + void addObjectLabel(DIE *Die, unsigned Attribute, unsigned Form, + const std::string &Label); + + /// addSectionOffset - Add a section offset label attribute data and value. + /// + void addSectionOffset(DIE *Die, unsigned Attribute, unsigned Form, + const DWLabel &Label, const DWLabel &Section, + bool isEH = false, bool useSet = true); + + /// addDelta - Add a label delta attribute data and value. + /// + void addDelta(DIE *Die, unsigned Attribute, unsigned Form, + const DWLabel &Hi, const DWLabel &Lo); + + /// addDIEEntry - Add a DIE attribute data and value. + /// + void addDIEEntry(DIE *Die, unsigned Attribute, unsigned Form, DIE *Entry) { + Die->addValue(Attribute, Form, createDIEEntry(Entry)); + } + + /// addBlock - Add block data. + /// + void addBlock(DIE *Die, unsigned Attribute, unsigned Form, DIEBlock *Block); + + /// addSourceLine - Add location information to specified debug information + /// entry. + void addSourceLine(DIE *Die, const DIVariable *V); + void addSourceLine(DIE *Die, const DIGlobal *G); + void addSourceLine(DIE *Die, const DISubprogram *SP); + void addSourceLine(DIE *Die, const DIType *Ty); + + /// addAddress - Add an address attribute to a die based on the location + /// provided. + void addAddress(DIE *Die, unsigned Attribute, + const MachineLocation &Location); + + /// addComplexAddress - Start with the address based on the location provided, + /// and generate the DWARF information necessary to find the actual variable + /// (navigating the extra location information encoded in the type) based on + /// the starting location. Add the DWARF information to the die. + /// + void addComplexAddress(DbgVariable *&DV, DIE *Die, unsigned Attribute, + const MachineLocation &Location); + + // FIXME: Should be reformulated in terms of addComplexAddress. + /// addBlockByrefAddress - Start with the address based on the location + /// provided, and generate the DWARF information necessary to find the + /// actual Block variable (navigating the Block struct) based on the + /// starting location. Add the DWARF information to the die. Obsolete, + /// please use addComplexAddress instead. + /// + void addBlockByrefAddress(DbgVariable *&DV, DIE *Die, unsigned Attribute, + const MachineLocation &Location); + + /// addType - Add a new type attribute to the specified entity. + void addType(CompileUnit *DW_Unit, DIE *Entity, DIType Ty); + + void addPubTypes(DISubprogram SP); + + /// constructTypeDIE - Construct basic type die from DIBasicType. + void constructTypeDIE(CompileUnit *DW_Unit, DIE &Buffer, + DIBasicType BTy); + + /// constructTypeDIE - Construct derived type die from DIDerivedType. + void constructTypeDIE(CompileUnit *DW_Unit, DIE &Buffer, + DIDerivedType DTy); + + /// constructTypeDIE - Construct type DIE from DICompositeType. + void constructTypeDIE(CompileUnit *DW_Unit, DIE &Buffer, + DICompositeType CTy); + + /// constructSubrangeDIE - Construct subrange DIE from DISubrange. + void constructSubrangeDIE(DIE &Buffer, DISubrange SR, DIE *IndexTy); + + /// constructArrayTypeDIE - Construct array type DIE from DICompositeType. + void constructArrayTypeDIE(CompileUnit *DW_Unit, DIE &Buffer, + DICompositeType *CTy); + + /// constructEnumTypeDIE - Construct enum type DIE from DIEnumerator. + DIE *constructEnumTypeDIE(CompileUnit *DW_Unit, DIEnumerator *ETy); + + /// createGlobalVariableDIE - Create new DIE using GV. + DIE *createGlobalVariableDIE(CompileUnit *DW_Unit, + const DIGlobalVariable &GV); + + /// createMemberDIE - Create new member DIE. + DIE *createMemberDIE(CompileUnit *DW_Unit, const DIDerivedType &DT); + + /// createSubprogramDIE - Create new DIE using SP. + DIE *createSubprogramDIE(CompileUnit *DW_Unit, + const DISubprogram &SP, + bool IsConstructor = false, + bool IsInlined = false); + + /// findCompileUnit - Get the compile unit for the given descriptor. + /// + CompileUnit &findCompileUnit(DICompileUnit Unit) const; + + /// createDbgScopeVariable - Create a new scope variable. + /// + DIE *createDbgScopeVariable(DbgVariable *DV, CompileUnit *Unit); + + /// getUpdatedDbgScope - Find or create DbgScope assicated with + /// the instruction. Initialize scope and update scope hierarchy. + DbgScope *getUpdatedDbgScope(MDNode *N, const MachineInstr *MI, MDNode *InlinedAt); + + /// createDbgScope - Create DbgScope for the scope. + void createDbgScope(MDNode *Scope, MDNode *InlinedAt); + + DbgScope *getOrCreateAbstractScope(MDNode *N); + + /// findAbstractVariable - Find abstract variable associated with Var. + DbgVariable *findAbstractVariable(DIVariable &Var, unsigned FrameIdx, + DILocation &Loc); + + /// updateSubprogramScopeDIE - Find DIE for the given subprogram and + /// attach appropriate DW_AT_low_pc and DW_AT_high_pc attributes. + /// If there are global variables in this scope then create and insert + /// DIEs for these variables. + DIE *updateSubprogramScopeDIE(MDNode *SPNode); + + /// constructLexicalScope - Construct new DW_TAG_lexical_block + /// for this scope and attach DW_AT_low_pc/DW_AT_high_pc labels. + DIE *constructLexicalScopeDIE(DbgScope *Scope); + + /// constructInlinedScopeDIE - This scope represents inlined body of + /// a function. Construct DIE to represent this concrete inlined copy + /// of the function. + DIE *constructInlinedScopeDIE(DbgScope *Scope); + + /// constructVariableDIE - Construct a DIE for the given DbgVariable. + DIE *constructVariableDIE(DbgVariable *DV, DbgScope *S, CompileUnit *Unit); + + /// constructScopeDIE - Construct a DIE for this scope. + DIE *constructScopeDIE(DbgScope *Scope); + + /// emitInitial - Emit initial Dwarf declarations. This is necessary for cc + /// tools to recognize the object file contains Dwarf information. + void emitInitial(); + + /// emitDIE - Recusively Emits a debug information entry. + /// + void emitDIE(DIE *Die); + + /// computeSizeAndOffset - Compute the size and offset of a DIE. + /// + unsigned computeSizeAndOffset(DIE *Die, unsigned Offset, bool Last); + + /// computeSizeAndOffsets - Compute the size and offset of all the DIEs. + /// + void computeSizeAndOffsets(); + + /// EmitDebugInfo / emitDebugInfoPerCU - Emit the debug info section. + /// + void emitDebugInfoPerCU(CompileUnit *Unit); + + void emitDebugInfo(); + + /// emitAbbreviations - Emit the abbreviation section. + /// + void emitAbbreviations() const; + + /// emitEndOfLineMatrix - Emit the last address of the section and the end of + /// the line matrix. + /// + void emitEndOfLineMatrix(unsigned SectionEnd); + + /// emitDebugLines - Emit source line information. + /// + void emitDebugLines(); + + /// emitCommonDebugFrame - Emit common frame info into a debug frame section. + /// + void emitCommonDebugFrame(); + + /// emitFunctionDebugFrame - Emit per function frame info into a debug frame + /// section. + void emitFunctionDebugFrame(const FunctionDebugFrameInfo &DebugFrameInfo); + + void emitDebugPubNamesPerCU(CompileUnit *Unit); + + /// emitDebugPubNames - Emit visible names into a debug pubnames section. + /// + void emitDebugPubNames(); + + /// emitDebugPubTypes - Emit visible types into a debug pubtypes section. + /// + void emitDebugPubTypes(); + + /// emitDebugStr - Emit visible names into a debug str section. + /// + void emitDebugStr(); + + /// emitDebugLoc - Emit visible names into a debug loc section. + /// + void emitDebugLoc(); + + /// EmitDebugARanges - Emit visible names into a debug aranges section. + /// + void EmitDebugARanges(); + + /// emitDebugRanges - Emit visible names into a debug ranges section. + /// + void emitDebugRanges(); + + /// emitDebugMacInfo - Emit visible names into a debug macinfo section. + /// + void emitDebugMacInfo(); + + /// emitDebugInlineInfo - Emit inline info using following format. + /// Section Header: + /// 1. length of section + /// 2. Dwarf version number + /// 3. address size. + /// + /// Entries (one "entry" for each function that was inlined): + /// + /// 1. offset into __debug_str section for MIPS linkage name, if exists; + /// otherwise offset into __debug_str for regular function name. + /// 2. offset into __debug_str section for regular function name. + /// 3. an unsigned LEB128 number indicating the number of distinct inlining + /// instances for the function. + /// + /// The rest of the entry consists of a {die_offset, low_pc} pair for each + /// inlined instance; the die_offset points to the inlined_subroutine die in + /// the __debug_info section, and the low_pc is the starting address for the + /// inlining instance. + void emitDebugInlineInfo(); + + /// GetOrCreateSourceID - Look up the source id with the given directory and + /// source file names. If none currently exists, create a new id and insert it + /// in the SourceIds map. This can update DirectoryNames and SourceFileNames maps + /// as well. + unsigned GetOrCreateSourceID(StringRef DirName, StringRef FileName); + + void constructCompileUnit(MDNode *N); + + void constructGlobalVariableDIE(MDNode *N); + + void constructSubprogramDIE(MDNode *N); + + // FIXME: This should go away in favor of complex addresses. + /// Find the type the programmer originally declared the variable to be + /// and return that type. Obsolete, use GetComplexAddrType instead. + /// + DIType getBlockByrefType(DIType Ty, std::string Name); + +public: + //===--------------------------------------------------------------------===// + // Main entry points. + // + DwarfDebug(raw_ostream &OS, AsmPrinter *A, const MCAsmInfo *T); + virtual ~DwarfDebug(); + + /// ShouldEmitDwarfDebug - Returns true if Dwarf debugging declarations should + /// be emitted. + bool ShouldEmitDwarfDebug() const { return shouldEmit; } + + /// beginModule - Emit all Dwarf sections that should come prior to the + /// content. + void beginModule(Module *M, MachineModuleInfo *MMI); + + /// endModule - Emit all Dwarf sections that should come after the content. + /// + void endModule(); + + /// beginFunction - Gather pre-function debug information. Assumes being + /// emitted immediately after the function entry point. + void beginFunction(MachineFunction *MF); + + /// endFunction - Gather and emit post-function debug information. + /// + void endFunction(MachineFunction *MF); + + /// recordSourceLine - Records location information and associates it with a + /// label. Returns a unique label ID used to generate a label and provide + /// correspondence to the source line list. + unsigned recordSourceLine(unsigned Line, unsigned Col, MDNode *Scope); + + /// getSourceLineCount - Return the number of source lines in the debug + /// info. + unsigned getSourceLineCount() const { + return Lines.size(); + } + + /// getOrCreateSourceID - Public version of GetOrCreateSourceID. This can be + /// timed. Look up the source id with the given directory and source file + /// names. If none currently exists, create a new id and insert it in the + /// SourceIds map. This can update DirectoryNames and SourceFileNames maps as + /// well. + unsigned getOrCreateSourceID(const std::string &DirName, + const std::string &FileName); + + /// extractScopeInformation - Scan machine instructions in this function + /// and collect DbgScopes. Return true, if atleast one scope was found. + bool extractScopeInformation(MachineFunction *MF); + + /// collectVariableInfo - Populate DbgScope entries with variables' info. + void collectVariableInfo(); + + /// beginScope - Process beginning of a scope starting at Label. + void beginScope(const MachineInstr *MI, unsigned Label); + + /// endScope - Prcess end of a scope. + void endScope(const MachineInstr *MI); +}; +} // End of namespace llvm + +#endif diff --git a/libclamav/c++/llvm/lib/CodeGen/AsmPrinter/DwarfException.cpp b/libclamav/c++/llvm/lib/CodeGen/AsmPrinter/DwarfException.cpp new file mode 100644 index 000000000..1c8b8f464 --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/AsmPrinter/DwarfException.cpp @@ -0,0 +1,1034 @@ +//===-- CodeGen/AsmPrinter/DwarfException.cpp - Dwarf Exception Impl ------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains support for writing DWARF exception info into asm files. +// +//===----------------------------------------------------------------------===// + +#include "DwarfException.h" +#include "llvm/Module.h" +#include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineLocation.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCSection.h" +#include "llvm/MC/MCStreamer.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetFrameInfo.h" +#include "llvm/Target/TargetLoweringObjectFile.h" +#include "llvm/Target/TargetOptions.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Support/Dwarf.h" +#include "llvm/Support/Mangler.h" +#include "llvm/Support/Timer.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringExtras.h" +using namespace llvm; + +static TimerGroup &getDwarfTimerGroup() { + static TimerGroup DwarfTimerGroup("DWARF Exception"); + return DwarfTimerGroup; +} + +DwarfException::DwarfException(raw_ostream &OS, AsmPrinter *A, + const MCAsmInfo *T) + : Dwarf(OS, A, T, "eh"), shouldEmitTable(false), shouldEmitMoves(false), + shouldEmitTableModule(false), shouldEmitMovesModule(false), + ExceptionTimer(0) { + if (TimePassesIsEnabled) + ExceptionTimer = new Timer("DWARF Exception Writer", + getDwarfTimerGroup()); +} + +DwarfException::~DwarfException() { + delete ExceptionTimer; +} + +/// SizeOfEncodedValue - Return the size of the encoding in bytes. +unsigned DwarfException::SizeOfEncodedValue(unsigned Encoding) { + if (Encoding == dwarf::DW_EH_PE_omit) + return 0; + + switch (Encoding & 0x07) { + case dwarf::DW_EH_PE_absptr: + return TD->getPointerSize(); + case dwarf::DW_EH_PE_udata2: + return 2; + case dwarf::DW_EH_PE_udata4: + return 4; + case dwarf::DW_EH_PE_udata8: + return 8; + } + + assert(0 && "Invalid encoded value."); + return 0; +} + +/// CreateLabelDiff - Emit a label and subtract it from the expression we +/// already have. This is equivalent to emitting "foo - .", but we have to emit +/// the label for "." directly. +const MCExpr *DwarfException::CreateLabelDiff(const MCExpr *ExprRef, + const char *LabelName, + unsigned Index) { + SmallString<64> Name; + raw_svector_ostream(Name) << MAI->getPrivateGlobalPrefix() + << LabelName << Asm->getFunctionNumber() + << "_" << Index; + MCSymbol *DotSym = Asm->OutContext.GetOrCreateSymbol(Name.str()); + Asm->OutStreamer.EmitLabel(DotSym); + + return MCBinaryExpr::CreateSub(ExprRef, + MCSymbolRefExpr::Create(DotSym, + Asm->OutContext), + Asm->OutContext); +} + +/// EmitCIE - Emit a Common Information Entry (CIE). This holds information that +/// is shared among many Frame Description Entries. There is at least one CIE +/// in every non-empty .debug_frame section. +void DwarfException::EmitCIE(const Function *PersonalityFn, unsigned Index) { + // Size and sign of stack growth. + int stackGrowth = + Asm->TM.getFrameInfo()->getStackGrowthDirection() == + TargetFrameInfo::StackGrowsUp ? + TD->getPointerSize() : -TD->getPointerSize(); + + const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering(); + + // Begin eh frame section. + Asm->OutStreamer.SwitchSection(TLOF.getEHFrameSection()); + + if (MAI->is_EHSymbolPrivate()) + O << MAI->getPrivateGlobalPrefix(); + O << "EH_frame" << Index << ":\n"; + + EmitLabel("section_eh_frame", Index); + + // Define base labels. + EmitLabel("eh_frame_common", Index); + + // Define the eh frame length. + EmitDifference("eh_frame_common_end", Index, + "eh_frame_common_begin", Index, true); + Asm->EOL("Length of Common Information Entry"); + + // EH frame header. + EmitLabel("eh_frame_common_begin", Index); + Asm->EmitInt32((int)0); + Asm->EOL("CIE Identifier Tag"); + Asm->EmitInt8(dwarf::DW_CIE_VERSION); + Asm->EOL("CIE Version"); + + // The personality presence indicates that language specific information will + // show up in the eh frame. Find out how we are supposed to lower the + // personality function reference: + const MCExpr *PersonalityRef = 0; + bool IsPersonalityIndirect = false, IsPersonalityPCRel = false; + if (PersonalityFn) { + // FIXME: HANDLE STATIC CODEGEN MODEL HERE. + + // In non-static mode, ask the object file how to represent this reference. + PersonalityRef = + TLOF.getSymbolForDwarfGlobalReference(PersonalityFn, Asm->Mang, + Asm->MMI, + IsPersonalityIndirect, + IsPersonalityPCRel); + } + + unsigned PerEncoding = dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4; + if (IsPersonalityIndirect) + PerEncoding |= dwarf::DW_EH_PE_indirect; + unsigned LSDAEncoding = dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4; + unsigned FDEEncoding = dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4; + + char Augmentation[5] = { 0 }; + unsigned AugmentationSize = 0; + char *APtr = Augmentation + 1; + + if (PersonalityRef) { + // There is a personality function. + *APtr++ = 'P'; + AugmentationSize += 1 + SizeOfEncodedValue(PerEncoding); + } + + if (UsesLSDA[Index]) { + // An LSDA pointer is in the FDE augmentation. + *APtr++ = 'L'; + ++AugmentationSize; + } + + if (FDEEncoding != dwarf::DW_EH_PE_absptr) { + // A non-default pointer encoding for the FDE. + *APtr++ = 'R'; + ++AugmentationSize; + } + + if (APtr != Augmentation + 1) + Augmentation[0] = 'z'; + + Asm->EmitString(Augmentation); + Asm->EOL("CIE Augmentation"); + + // Round out reader. + Asm->EmitULEB128Bytes(1); + Asm->EOL("CIE Code Alignment Factor"); + Asm->EmitSLEB128Bytes(stackGrowth); + Asm->EOL("CIE Data Alignment Factor"); + Asm->EmitInt8(RI->getDwarfRegNum(RI->getRARegister(), true)); + Asm->EOL("CIE Return Address Column"); + + Asm->EmitULEB128Bytes(AugmentationSize); + Asm->EOL("Augmentation Size"); + + Asm->EmitInt8(PerEncoding); + Asm->EOL("Personality", PerEncoding); + + // If there is a personality, we need to indicate the function's location. + if (PersonalityRef) { + if (!IsPersonalityPCRel) + PersonalityRef = CreateLabelDiff(PersonalityRef, "personalityref_addr", + Index); + + O << MAI->getData32bitsDirective(); + PersonalityRef->print(O, MAI); + Asm->EOL("Personality"); + + Asm->EmitInt8(LSDAEncoding); + Asm->EOL("LSDA Encoding", LSDAEncoding); + + Asm->EmitInt8(FDEEncoding); + Asm->EOL("FDE Encoding", FDEEncoding); + } + + // Indicate locations of general callee saved registers in frame. + std::vector Moves; + RI->getInitialFrameState(Moves); + EmitFrameMoves(NULL, 0, Moves, true); + + // On Darwin the linker honors the alignment of eh_frame, which means it must + // be 8-byte on 64-bit targets to match what gcc does. Otherwise you get + // holes which confuse readers of eh_frame. + Asm->EmitAlignment(TD->getPointerSize() == 4 ? 2 : 3, 0, 0, false); + EmitLabel("eh_frame_common_end", Index); + + Asm->EOL(); +} + +/// EmitFDE - Emit the Frame Description Entry (FDE) for the function. +void DwarfException::EmitFDE(const FunctionEHFrameInfo &EHFrameInfo) { + assert(!EHFrameInfo.function->hasAvailableExternallyLinkage() && + "Should not emit 'available externally' functions at all"); + + const Function *TheFunc = EHFrameInfo.function; + + Asm->OutStreamer.SwitchSection(Asm->getObjFileLowering().getEHFrameSection()); + + // Externally visible entry into the functions eh frame info. If the + // corresponding function is static, this should not be externally visible. + if (!TheFunc->hasLocalLinkage()) + if (const char *GlobalEHDirective = MAI->getGlobalEHDirective()) + O << GlobalEHDirective << EHFrameInfo.FnName << '\n'; + + // If corresponding function is weak definition, this should be too. + if (TheFunc->isWeakForLinker() && MAI->getWeakDefDirective()) + O << MAI->getWeakDefDirective() << EHFrameInfo.FnName << '\n'; + + // If corresponding function is hidden, this should be too. + if (TheFunc->hasHiddenVisibility()) + if (const char *HiddenDirective = MAI->getHiddenDirective()) + O << HiddenDirective << EHFrameInfo.FnName << '\n' ; + + // If there are no calls then you can't unwind. This may mean we can omit the + // EH Frame, but some environments do not handle weak absolute symbols. If + // UnwindTablesMandatory is set we cannot do this optimization; the unwind + // info is to be available for non-EH uses. + if (!EHFrameInfo.hasCalls && !UnwindTablesMandatory && + (!TheFunc->isWeakForLinker() || + !MAI->getWeakDefDirective() || + MAI->getSupportsWeakOmittedEHFrame())) { + O << EHFrameInfo.FnName << " = 0\n"; + // This name has no connection to the function, so it might get + // dead-stripped when the function is not, erroneously. Prohibit + // dead-stripping unconditionally. + if (const char *UsedDirective = MAI->getUsedDirective()) + O << UsedDirective << EHFrameInfo.FnName << "\n\n"; + } else { + O << EHFrameInfo.FnName << ":\n"; + + // EH frame header. + EmitDifference("eh_frame_end", EHFrameInfo.Number, + "eh_frame_begin", EHFrameInfo.Number, true); + Asm->EOL("Length of Frame Information Entry"); + + EmitLabel("eh_frame_begin", EHFrameInfo.Number); + + EmitSectionOffset("eh_frame_begin", "eh_frame_common", + EHFrameInfo.Number, EHFrameInfo.PersonalityIndex, + true, true, false); + + Asm->EOL("FDE CIE offset"); + + EmitReference("eh_func_begin", EHFrameInfo.Number, true, true); + Asm->EOL("FDE initial location"); + EmitDifference("eh_func_end", EHFrameInfo.Number, + "eh_func_begin", EHFrameInfo.Number, true); + Asm->EOL("FDE address range"); + + // If there is a personality and landing pads then point to the language + // specific data area in the exception table. + if (MMI->getPersonalities()[0] != NULL) { + bool is4Byte = TD->getPointerSize() == sizeof(int32_t); + + Asm->EmitULEB128Bytes(is4Byte ? 4 : 8); + Asm->EOL("Augmentation size"); + + if (EHFrameInfo.hasLandingPads) + EmitReference("exception", EHFrameInfo.Number, true, false); + else { + if (is4Byte) + Asm->EmitInt32((int)0); + else + Asm->EmitInt64((int)0); + } + Asm->EOL("Language Specific Data Area"); + } else { + Asm->EmitULEB128Bytes(0); + Asm->EOL("Augmentation size"); + } + + // Indicate locations of function specific callee saved registers in frame. + EmitFrameMoves("eh_func_begin", EHFrameInfo.Number, EHFrameInfo.Moves, + true); + + // On Darwin the linker honors the alignment of eh_frame, which means it + // must be 8-byte on 64-bit targets to match what gcc does. Otherwise you + // get holes which confuse readers of eh_frame. + Asm->EmitAlignment(TD->getPointerSize() == sizeof(int32_t) ? 2 : 3, + 0, 0, false); + EmitLabel("eh_frame_end", EHFrameInfo.Number); + + // If the function is marked used, this table should be also. We cannot + // make the mark unconditional in this case, since retaining the table also + // retains the function in this case, and there is code around that depends + // on unused functions (calling undefined externals) being dead-stripped to + // link correctly. Yes, there really is. + if (MMI->isUsedFunction(EHFrameInfo.function)) + if (const char *UsedDirective = MAI->getUsedDirective()) + O << UsedDirective << EHFrameInfo.FnName << "\n\n"; + } + + Asm->EOL(); +} + +/// SharedTypeIds - How many leading type ids two landing pads have in common. +unsigned DwarfException::SharedTypeIds(const LandingPadInfo *L, + const LandingPadInfo *R) { + const std::vector &LIds = L->TypeIds, &RIds = R->TypeIds; + unsigned LSize = LIds.size(), RSize = RIds.size(); + unsigned MinSize = LSize < RSize ? LSize : RSize; + unsigned Count = 0; + + for (; Count != MinSize; ++Count) + if (LIds[Count] != RIds[Count]) + return Count; + + return Count; +} + +/// PadLT - Order landing pads lexicographically by type id. +bool DwarfException::PadLT(const LandingPadInfo *L, const LandingPadInfo *R) { + const std::vector &LIds = L->TypeIds, &RIds = R->TypeIds; + unsigned LSize = LIds.size(), RSize = RIds.size(); + unsigned MinSize = LSize < RSize ? LSize : RSize; + + for (unsigned i = 0; i != MinSize; ++i) + if (LIds[i] != RIds[i]) + return LIds[i] < RIds[i]; + + return LSize < RSize; +} + +/// ComputeActionsTable - Compute the actions table and gather the first action +/// index for each landing pad site. +unsigned DwarfException:: +ComputeActionsTable(const SmallVectorImpl &LandingPads, + SmallVectorImpl &Actions, + SmallVectorImpl &FirstActions) { + + // The action table follows the call-site table in the LSDA. The individual + // records are of two types: + // + // * Catch clause + // * Exception specification + // + // The two record kinds have the same format, with only small differences. + // They are distinguished by the "switch value" field: Catch clauses + // (TypeInfos) have strictly positive switch values, and exception + // specifications (FilterIds) have strictly negative switch values. Value 0 + // indicates a catch-all clause. + // + // Negative type IDs index into FilterIds. Positive type IDs index into + // TypeInfos. The value written for a positive type ID is just the type ID + // itself. For a negative type ID, however, the value written is the + // (negative) byte offset of the corresponding FilterIds entry. The byte + // offset is usually equal to the type ID (because the FilterIds entries are + // written using a variable width encoding, which outputs one byte per entry + // as long as the value written is not too large) but can differ. This kind + // of complication does not occur for positive type IDs because type infos are + // output using a fixed width encoding. FilterOffsets[i] holds the byte + // offset corresponding to FilterIds[i]. + + const std::vector &FilterIds = MMI->getFilterIds(); + SmallVector FilterOffsets; + FilterOffsets.reserve(FilterIds.size()); + int Offset = -1; + + for (std::vector::const_iterator + I = FilterIds.begin(), E = FilterIds.end(); I != E; ++I) { + FilterOffsets.push_back(Offset); + Offset -= MCAsmInfo::getULEB128Size(*I); + } + + FirstActions.reserve(LandingPads.size()); + + int FirstAction = 0; + unsigned SizeActions = 0; + const LandingPadInfo *PrevLPI = 0; + + for (SmallVectorImpl::const_iterator + I = LandingPads.begin(), E = LandingPads.end(); I != E; ++I) { + const LandingPadInfo *LPI = *I; + const std::vector &TypeIds = LPI->TypeIds; + const unsigned NumShared = PrevLPI ? SharedTypeIds(LPI, PrevLPI) : 0; + unsigned SizeSiteActions = 0; + + if (NumShared < TypeIds.size()) { + unsigned SizeAction = 0; + ActionEntry *PrevAction = 0; + + if (NumShared) { + const unsigned SizePrevIds = PrevLPI->TypeIds.size(); + assert(Actions.size()); + PrevAction = &Actions.back(); + SizeAction = MCAsmInfo::getSLEB128Size(PrevAction->NextAction) + + MCAsmInfo::getSLEB128Size(PrevAction->ValueForTypeID); + + for (unsigned j = NumShared; j != SizePrevIds; ++j) { + SizeAction -= + MCAsmInfo::getSLEB128Size(PrevAction->ValueForTypeID); + SizeAction += -PrevAction->NextAction; + PrevAction = PrevAction->Previous; + } + } + + // Compute the actions. + for (unsigned J = NumShared, M = TypeIds.size(); J != M; ++J) { + int TypeID = TypeIds[J]; + assert(-1 - TypeID < (int)FilterOffsets.size() && "Unknown filter id!"); + int ValueForTypeID = TypeID < 0 ? FilterOffsets[-1 - TypeID] : TypeID; + unsigned SizeTypeID = MCAsmInfo::getSLEB128Size(ValueForTypeID); + + int NextAction = SizeAction ? -(SizeAction + SizeTypeID) : 0; + SizeAction = SizeTypeID + MCAsmInfo::getSLEB128Size(NextAction); + SizeSiteActions += SizeAction; + + ActionEntry Action = { ValueForTypeID, NextAction, PrevAction }; + Actions.push_back(Action); + PrevAction = &Actions.back(); + } + + // Record the first action of the landing pad site. + FirstAction = SizeActions + SizeSiteActions - SizeAction + 1; + } // else identical - re-use previous FirstAction + + // Information used when created the call-site table. The action record + // field of the call site record is the offset of the first associated + // action record, relative to the start of the actions table. This value is + // biased by 1 (1 in dicating the start of the actions table), and 0 + // indicates that there are no actions. + FirstActions.push_back(FirstAction); + + // Compute this sites contribution to size. + SizeActions += SizeSiteActions; + + PrevLPI = LPI; + } + + return SizeActions; +} + +/// CallToNoUnwindFunction - Return `true' if this is a call to a function +/// marked `nounwind'. Return `false' otherwise. +bool DwarfException::CallToNoUnwindFunction(const MachineInstr *MI) { + assert(MI->getDesc().isCall() && "This should be a call instruction!"); + + bool MarkedNoUnwind = false; + bool SawFunc = false; + + for (unsigned I = 0, E = MI->getNumOperands(); I != E; ++I) { + const MachineOperand &MO = MI->getOperand(I); + + if (MO.isGlobal()) { + if (Function *F = dyn_cast(MO.getGlobal())) { + if (SawFunc) { + // Be conservative. If we have more than one function operand for this + // call, then we can't make the assumption that it's the callee and + // not a parameter to the call. + // + // FIXME: Determine if there's a way to say that `F' is the callee or + // parameter. + MarkedNoUnwind = false; + break; + } + + MarkedNoUnwind = F->doesNotThrow(); + SawFunc = true; + } + } + } + + return MarkedNoUnwind; +} + +/// ComputeCallSiteTable - Compute the call-site table. The entry for an invoke +/// has a try-range containing the call, a non-zero landing pad, and an +/// appropriate action. The entry for an ordinary call has a try-range +/// containing the call and zero for the landing pad and the action. Calls +/// marked 'nounwind' have no entry and must not be contained in the try-range +/// of any entry - they form gaps in the table. Entries must be ordered by +/// try-range address. +void DwarfException:: +ComputeCallSiteTable(SmallVectorImpl &CallSites, + const RangeMapType &PadMap, + const SmallVectorImpl &LandingPads, + const SmallVectorImpl &FirstActions) { + // The end label of the previous invoke or nounwind try-range. + unsigned LastLabel = 0; + + // Whether there is a potentially throwing instruction (currently this means + // an ordinary call) between the end of the previous try-range and now. + bool SawPotentiallyThrowing = false; + + // Whether the last CallSite entry was for an invoke. + bool PreviousIsInvoke = false; + + // Visit all instructions in order of address. + for (MachineFunction::const_iterator I = MF->begin(), E = MF->end(); + I != E; ++I) { + for (MachineBasicBlock::const_iterator MI = I->begin(), E = I->end(); + MI != E; ++MI) { + if (!MI->isLabel()) { + if (MI->getDesc().isCall()) + SawPotentiallyThrowing |= !CallToNoUnwindFunction(MI); + + continue; + } + + unsigned BeginLabel = MI->getOperand(0).getImm(); + assert(BeginLabel && "Invalid label!"); + + // End of the previous try-range? + if (BeginLabel == LastLabel) + SawPotentiallyThrowing = false; + + // Beginning of a new try-range? + RangeMapType::const_iterator L = PadMap.find(BeginLabel); + if (L == PadMap.end()) + // Nope, it was just some random label. + continue; + + const PadRange &P = L->second; + const LandingPadInfo *LandingPad = LandingPads[P.PadIndex]; + assert(BeginLabel == LandingPad->BeginLabels[P.RangeIndex] && + "Inconsistent landing pad map!"); + + // For Dwarf exception handling (SjLj handling doesn't use this). If some + // instruction between the previous try-range and this one may throw, + // create a call-site entry with no landing pad for the region between the + // try-ranges. + if (SawPotentiallyThrowing && + MAI->getExceptionHandlingType() == ExceptionHandling::Dwarf) { + CallSiteEntry Site = { LastLabel, BeginLabel, 0, 0 }; + CallSites.push_back(Site); + PreviousIsInvoke = false; + } + + LastLabel = LandingPad->EndLabels[P.RangeIndex]; + assert(BeginLabel && LastLabel && "Invalid landing pad!"); + + if (LandingPad->LandingPadLabel) { + // This try-range is for an invoke. + CallSiteEntry Site = { + BeginLabel, + LastLabel, + LandingPad->LandingPadLabel, + FirstActions[P.PadIndex] + }; + + // Try to merge with the previous call-site. SJLJ doesn't do this + if (PreviousIsInvoke && + MAI->getExceptionHandlingType() == ExceptionHandling::Dwarf) { + CallSiteEntry &Prev = CallSites.back(); + if (Site.PadLabel == Prev.PadLabel && Site.Action == Prev.Action) { + // Extend the range of the previous entry. + Prev.EndLabel = Site.EndLabel; + continue; + } + } + + // Otherwise, create a new call-site. + CallSites.push_back(Site); + PreviousIsInvoke = true; + } else { + // Create a gap. + PreviousIsInvoke = false; + } + } + } + + // If some instruction between the previous try-range and the end of the + // function may throw, create a call-site entry with no landing pad for the + // region following the try-range. + if (SawPotentiallyThrowing && + MAI->getExceptionHandlingType() == ExceptionHandling::Dwarf) { + CallSiteEntry Site = { LastLabel, 0, 0, 0 }; + CallSites.push_back(Site); + } +} + +/// EmitExceptionTable - Emit landing pads and actions. +/// +/// The general organization of the table is complex, but the basic concepts are +/// easy. First there is a header which describes the location and organization +/// of the three components that follow. +/// +/// 1. The landing pad site information describes the range of code covered by +/// the try. In our case it's an accumulation of the ranges covered by the +/// invokes in the try. There is also a reference to the landing pad that +/// handles the exception once processed. Finally an index into the actions +/// table. +/// 2. The action table, in our case, is composed of pairs of type IDs and next +/// action offset. Starting with the action index from the landing pad +/// site, each type ID is checked for a match to the current exception. If +/// it matches then the exception and type id are passed on to the landing +/// pad. Otherwise the next action is looked up. This chain is terminated +/// with a next action of zero. If no type id is found then the frame is +/// unwound and handling continues. +/// 3. Type ID table contains references to all the C++ typeinfo for all +/// catches in the function. This tables is reverse indexed base 1. +void DwarfException::EmitExceptionTable() { + const std::vector &TypeInfos = MMI->getTypeInfos(); + const std::vector &FilterIds = MMI->getFilterIds(); + const std::vector &PadInfos = MMI->getLandingPads(); + if (PadInfos.empty()) return; + + // Sort the landing pads in order of their type ids. This is used to fold + // duplicate actions. + SmallVector LandingPads; + LandingPads.reserve(PadInfos.size()); + + for (unsigned i = 0, N = PadInfos.size(); i != N; ++i) + LandingPads.push_back(&PadInfos[i]); + + std::sort(LandingPads.begin(), LandingPads.end(), PadLT); + + // Compute the actions table and gather the first action index for each + // landing pad site. + SmallVector Actions; + SmallVector FirstActions; + unsigned SizeActions = ComputeActionsTable(LandingPads, Actions, + FirstActions); + + // Invokes and nounwind calls have entries in PadMap (due to being bracketed + // by try-range labels when lowered). Ordinary calls do not, so appropriate + // try-ranges for them need be deduced when using DWARF exception handling. + RangeMapType PadMap; + for (unsigned i = 0, N = LandingPads.size(); i != N; ++i) { + const LandingPadInfo *LandingPad = LandingPads[i]; + for (unsigned j = 0, E = LandingPad->BeginLabels.size(); j != E; ++j) { + unsigned BeginLabel = LandingPad->BeginLabels[j]; + assert(!PadMap.count(BeginLabel) && "Duplicate landing pad labels!"); + PadRange P = { i, j }; + PadMap[BeginLabel] = P; + } + } + + // Compute the call-site table. + SmallVector CallSites; + ComputeCallSiteTable(CallSites, PadMap, LandingPads, FirstActions); + + // Final tallies. + + // Call sites. + const unsigned SiteStartSize = SizeOfEncodedValue(dwarf::DW_EH_PE_udata4); + const unsigned SiteLengthSize = SizeOfEncodedValue(dwarf::DW_EH_PE_udata4); + const unsigned LandingPadSize = SizeOfEncodedValue(dwarf::DW_EH_PE_udata4); + bool IsSJLJ = MAI->getExceptionHandlingType() == ExceptionHandling::SjLj; + bool HaveTTData = IsSJLJ ? (!TypeInfos.empty() || !FilterIds.empty()) : true; + unsigned SizeSites; + + if (IsSJLJ) + SizeSites = 0; + else + SizeSites = CallSites.size() * + (SiteStartSize + SiteLengthSize + LandingPadSize); + + for (unsigned i = 0, e = CallSites.size(); i < e; ++i) { + SizeSites += MCAsmInfo::getULEB128Size(CallSites[i].Action); + if (IsSJLJ) + SizeSites += MCAsmInfo::getULEB128Size(i); + } + + // Type infos. + const MCSection *LSDASection = Asm->getObjFileLowering().getLSDASection(); + unsigned TTypeFormat; + unsigned TypeFormatSize; + + if (!HaveTTData) { + // For SjLj exceptions, if there is no TypeInfo, then we just explicitly say + // that we're omitting that bit. + TTypeFormat = dwarf::DW_EH_PE_omit; + TypeFormatSize = SizeOfEncodedValue(dwarf::DW_EH_PE_absptr); + } else { + // Okay, we have actual filters or typeinfos to emit. As such, we need to + // pick a type encoding for them. We're about to emit a list of pointers to + // typeinfo objects at the end of the LSDA. However, unless we're in static + // mode, this reference will require a relocation by the dynamic linker. + // + // Because of this, we have a couple of options: + // + // 1) If we are in -static mode, we can always use an absolute reference + // from the LSDA, because the static linker will resolve it. + // + // 2) Otherwise, if the LSDA section is writable, we can output the direct + // reference to the typeinfo and allow the dynamic linker to relocate + // it. Since it is in a writable section, the dynamic linker won't + // have a problem. + // + // 3) Finally, if we're in PIC mode and the LDSA section isn't writable, + // we need to use some form of indirection. For example, on Darwin, + // we can output a statically-relocatable reference to a dyld stub. The + // offset to the stub is constant, but the contents are in a section + // that is updated by the dynamic linker. This is easy enough, but we + // need to tell the personality function of the unwinder to indirect + // through the dyld stub. + // + // FIXME: When (3) is actually implemented, we'll have to emit the stubs + // somewhere. This predicate should be moved to a shared location that is + // in target-independent code. + // + if (LSDASection->getKind().isWriteable() || + Asm->TM.getRelocationModel() == Reloc::Static) + TTypeFormat = dwarf::DW_EH_PE_absptr; + else + TTypeFormat = dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel | + dwarf::DW_EH_PE_sdata4; + + TypeFormatSize = SizeOfEncodedValue(TTypeFormat); + } + + // Begin the exception table. + Asm->OutStreamer.SwitchSection(LSDASection); + Asm->EmitAlignment(2, 0, 0, false); + + O << "GCC_except_table" << SubprogramCount << ":\n"; + + // The type infos need to be aligned. GCC does this by inserting padding just + // before the type infos. However, this changes the size of the exception + // table, so you need to take this into account when you output the exception + // table size. However, the size is output using a variable length encoding. + // So by increasing the size by inserting padding, you may increase the number + // of bytes used for writing the size. If it increases, say by one byte, then + // you now need to output one less byte of padding to get the type infos + // aligned. However this decreases the size of the exception table. This + // changes the value you have to output for the exception table size. Due to + // the variable length encoding, the number of bytes used for writing the + // length may decrease. If so, you then have to increase the amount of + // padding. And so on. If you look carefully at the GCC code you will see that + // it indeed does this in a loop, going on and on until the values stabilize. + // We chose another solution: don't output padding inside the table like GCC + // does, instead output it before the table. + unsigned SizeTypes = TypeInfos.size() * TypeFormatSize; + unsigned TyOffset = sizeof(int8_t) + // Call site format + MCAsmInfo::getULEB128Size(SizeSites) + // Call-site table length + SizeSites + SizeActions + SizeTypes; + unsigned TotalSize = sizeof(int8_t) + // LPStart format + sizeof(int8_t) + // TType format + (HaveTTData ? + MCAsmInfo::getULEB128Size(TyOffset) : 0) + // TType base offset + TyOffset; + unsigned SizeAlign = (4 - TotalSize) & 3; + + for (unsigned i = 0; i != SizeAlign; ++i) { + Asm->EmitInt8(0); + Asm->EOL("Padding"); + } + + EmitLabel("exception", SubprogramCount); + + if (IsSJLJ) { + SmallString<16> LSDAName; + raw_svector_ostream(LSDAName) << MAI->getPrivateGlobalPrefix() << + "_LSDA_" << Asm->getFunctionNumber(); + O << LSDAName.str() << ":\n"; + } + + // Emit the header. + Asm->EmitInt8(dwarf::DW_EH_PE_omit); + Asm->EOL("@LPStart format", dwarf::DW_EH_PE_omit); + + Asm->EmitInt8(TTypeFormat); + Asm->EOL("@TType format", TTypeFormat); + + if (HaveTTData) { + Asm->EmitULEB128Bytes(TyOffset); + Asm->EOL("@TType base offset"); + } + + // SjLj Exception handling + if (IsSJLJ) { + Asm->EmitInt8(dwarf::DW_EH_PE_udata4); + Asm->EOL("Call site format", dwarf::DW_EH_PE_udata4); + Asm->EmitULEB128Bytes(SizeSites); + Asm->EOL("Call site table length"); + + // Emit the landing pad site information. + unsigned idx = 0; + for (SmallVectorImpl::const_iterator + I = CallSites.begin(), E = CallSites.end(); I != E; ++I, ++idx) { + const CallSiteEntry &S = *I; + + // Offset of the landing pad, counted in 16-byte bundles relative to the + // @LPStart address. + Asm->EmitULEB128Bytes(idx); + Asm->EOL("Landing pad"); + + // Offset of the first associated action record, relative to the start of + // the action table. This value is biased by 1 (1 indicates the start of + // the action table), and 0 indicates that there are no actions. + Asm->EmitULEB128Bytes(S.Action); + Asm->EOL("Action"); + } + } else { + // DWARF Exception handling + assert(MAI->getExceptionHandlingType() == ExceptionHandling::Dwarf); + + // The call-site table is a list of all call sites that may throw an + // exception (including C++ 'throw' statements) in the procedure + // fragment. It immediately follows the LSDA header. Each entry indicates, + // for a given call, the first corresponding action record and corresponding + // landing pad. + // + // The table begins with the number of bytes, stored as an LEB128 + // compressed, unsigned integer. The records immediately follow the record + // count. They are sorted in increasing call-site address. Each record + // indicates: + // + // * The position of the call-site. + // * The position of the landing pad. + // * The first action record for that call site. + // + // A missing entry in the call-site table indicates that a call is not + // supposed to throw. + + // Emit the landing pad call site table. + Asm->EmitInt8(dwarf::DW_EH_PE_udata4); + Asm->EOL("Call site format", dwarf::DW_EH_PE_udata4); + Asm->EmitULEB128Bytes(SizeSites); + Asm->EOL("Call site table size"); + + for (SmallVectorImpl::const_iterator + I = CallSites.begin(), E = CallSites.end(); I != E; ++I) { + const CallSiteEntry &S = *I; + const char *BeginTag; + unsigned BeginNumber; + + if (!S.BeginLabel) { + BeginTag = "eh_func_begin"; + BeginNumber = SubprogramCount; + } else { + BeginTag = "label"; + BeginNumber = S.BeginLabel; + } + + // Offset of the call site relative to the previous call site, counted in + // number of 16-byte bundles. The first call site is counted relative to + // the start of the procedure fragment. + EmitSectionOffset(BeginTag, "eh_func_begin", BeginNumber, SubprogramCount, + true, true); + Asm->EOL("Region start"); + + if (!S.EndLabel) + EmitDifference("eh_func_end", SubprogramCount, BeginTag, BeginNumber, + true); + else + EmitDifference("label", S.EndLabel, BeginTag, BeginNumber, true); + + Asm->EOL("Region length"); + + // Offset of the landing pad, counted in 16-byte bundles relative to the + // @LPStart address. + if (!S.PadLabel) + Asm->EmitInt32(0); + else + EmitSectionOffset("label", "eh_func_begin", S.PadLabel, SubprogramCount, + true, true); + + Asm->EOL("Landing pad"); + + // Offset of the first associated action record, relative to the start of + // the action table. This value is biased by 1 (1 indicates the start of + // the action table), and 0 indicates that there are no actions. + Asm->EmitULEB128Bytes(S.Action); + Asm->EOL("Action"); + } + } + + // Emit the Action Table. + for (SmallVectorImpl::const_iterator + I = Actions.begin(), E = Actions.end(); I != E; ++I) { + const ActionEntry &Action = *I; + + // Type Filter + // + // Used by the runtime to match the type of the thrown exception to the + // type of the catch clauses or the types in the exception specification. + + Asm->EmitSLEB128Bytes(Action.ValueForTypeID); + Asm->EOL("TypeInfo index"); + + // Action Record + // + // Self-relative signed displacement in bytes of the next action record, + // or 0 if there is no next action record. + + Asm->EmitSLEB128Bytes(Action.NextAction); + Asm->EOL("Next action"); + } + + // Emit the Catch TypeInfos. + for (std::vector::const_reverse_iterator + I = TypeInfos.rbegin(), E = TypeInfos.rend(); I != E; ++I) { + const GlobalVariable *GV = *I; + PrintRelDirective(); + + if (GV) { + O << Asm->Mang->getMangledName(GV); + } else { + O << "0x0"; + } + + Asm->EOL("TypeInfo"); + } + + // Emit the Exception Specifications. + for (std::vector::const_iterator + I = FilterIds.begin(), E = FilterIds.end(); I < E; ++I) { + unsigned TypeID = *I; + Asm->EmitULEB128Bytes(TypeID); + if (TypeID != 0) + Asm->EOL("Exception specification"); + else + Asm->EOL(); + } + + Asm->EmitAlignment(2, 0, 0, false); +} + +/// EndModule - Emit all exception information that should come after the +/// content. +void DwarfException::EndModule() { + if (MAI->getExceptionHandlingType() != ExceptionHandling::Dwarf) + return; + + if (!shouldEmitMovesModule && !shouldEmitTableModule) + return; + + if (TimePassesIsEnabled) + ExceptionTimer->startTimer(); + + const std::vector Personalities = MMI->getPersonalities(); + + for (unsigned I = 0, E = Personalities.size(); I < E; ++I) + EmitCIE(Personalities[I], I); + + for (std::vector::iterator + I = EHFrames.begin(), E = EHFrames.end(); I != E; ++I) + EmitFDE(*I); + + if (TimePassesIsEnabled) + ExceptionTimer->stopTimer(); +} + +/// BeginFunction - Gather pre-function exception information. Assumes it's +/// being emitted immediately after the function entry point. +void DwarfException::BeginFunction(MachineFunction *MF) { + if (!MMI || !MAI->doesSupportExceptionHandling()) return; + + if (TimePassesIsEnabled) + ExceptionTimer->startTimer(); + + this->MF = MF; + shouldEmitTable = shouldEmitMoves = false; + + // Map all labels and get rid of any dead landing pads. + MMI->TidyLandingPads(); + + // If any landing pads survive, we need an EH table. + if (!MMI->getLandingPads().empty()) + shouldEmitTable = true; + + // See if we need frame move info. + if (!MF->getFunction()->doesNotThrow() || UnwindTablesMandatory) + shouldEmitMoves = true; + + if (shouldEmitMoves || shouldEmitTable) + // Assumes in correct section after the entry point. + EmitLabel("eh_func_begin", ++SubprogramCount); + + shouldEmitTableModule |= shouldEmitTable; + shouldEmitMovesModule |= shouldEmitMoves; + + if (TimePassesIsEnabled) + ExceptionTimer->stopTimer(); +} + +/// EndFunction - Gather and emit post-function exception information. +/// +void DwarfException::EndFunction() { + if (!shouldEmitMoves && !shouldEmitTable) return; + + if (TimePassesIsEnabled) + ExceptionTimer->startTimer(); + + EmitLabel("eh_func_end", SubprogramCount); + EmitExceptionTable(); + + std::string FunctionEHName = + Asm->Mang->getMangledName(MF->getFunction(), ".eh", + Asm->MAI->is_EHSymbolPrivate()); + + // Save EH frame information + EHFrames.push_back(FunctionEHFrameInfo(FunctionEHName, SubprogramCount, + MMI->getPersonalityIndex(), + MF->getFrameInfo()->hasCalls(), + !MMI->getLandingPads().empty(), + MMI->getFrameMoves(), + MF->getFunction())); + + // Record if this personality index uses a landing pad. + UsesLSDA[MMI->getPersonalityIndex()] |= !MMI->getLandingPads().empty(); + + if (TimePassesIsEnabled) + ExceptionTimer->stopTimer(); +} diff --git a/libclamav/c++/llvm/lib/CodeGen/AsmPrinter/DwarfException.h b/libclamav/c++/llvm/lib/CodeGen/AsmPrinter/DwarfException.h new file mode 100644 index 000000000..aff1665e9 --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/AsmPrinter/DwarfException.h @@ -0,0 +1,209 @@ +//===-- DwarfException.h - Dwarf Exception Framework -----------*- C++ -*--===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains support for writing dwarf exception info into asm files. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_ASMPRINTER_DWARFEXCEPTION_H +#define LLVM_CODEGEN_ASMPRINTER_DWARFEXCEPTION_H + +#include "DIE.h" +#include "DwarfPrinter.h" +#include "llvm/CodeGen/AsmPrinter.h" +#include "llvm/ADT/DenseMap.h" +#include + +namespace llvm { + +struct LandingPadInfo; +class MachineModuleInfo; +class MCAsmInfo; +class MCExpr; +class Timer; +class raw_ostream; + +//===----------------------------------------------------------------------===// +/// DwarfException - Emits Dwarf exception handling directives. +/// +class DwarfException : public Dwarf { + struct FunctionEHFrameInfo { + std::string FnName; + unsigned Number; + unsigned PersonalityIndex; + bool hasCalls; + bool hasLandingPads; + std::vector Moves; + const Function * function; + + FunctionEHFrameInfo(const std::string &FN, unsigned Num, unsigned P, + bool hC, bool hL, + const std::vector &M, + const Function *f): + FnName(FN), Number(Num), PersonalityIndex(P), + hasCalls(hC), hasLandingPads(hL), Moves(M), function (f) { } + }; + + std::vector EHFrames; + + /// UsesLSDA - Indicates whether an FDE that uses the CIE at the given index + /// uses an LSDA. If so, then we need to encode that information in the CIE's + /// augmentation. + DenseMap UsesLSDA; + + /// shouldEmitTable - Per-function flag to indicate if EH tables should + /// be emitted. + bool shouldEmitTable; + + /// shouldEmitMoves - Per-function flag to indicate if frame moves info + /// should be emitted. + bool shouldEmitMoves; + + /// shouldEmitTableModule - Per-module flag to indicate if EH tables + /// should be emitted. + bool shouldEmitTableModule; + + /// shouldEmitFrameModule - Per-module flag to indicate if frame moves + /// should be emitted. + bool shouldEmitMovesModule; + + /// ExceptionTimer - Timer for the Dwarf exception writer. + Timer *ExceptionTimer; + + /// SizeOfEncodedValue - Return the size of the encoding in bytes. + unsigned SizeOfEncodedValue(unsigned Encoding); + + /// EmitCIE - Emit a Common Information Entry (CIE). This holds information + /// that is shared among many Frame Description Entries. There is at least + /// one CIE in every non-empty .debug_frame section. + void EmitCIE(const Function *Personality, unsigned Index); + + /// EmitFDE - Emit the Frame Description Entry (FDE) for the function. + void EmitFDE(const FunctionEHFrameInfo &EHFrameInfo); + + /// EmitExceptionTable - Emit landing pads and actions. + /// + /// The general organization of the table is complex, but the basic concepts + /// are easy. First there is a header which describes the location and + /// organization of the three components that follow. + /// 1. The landing pad site information describes the range of code covered + /// by the try. In our case it's an accumulation of the ranges covered + /// by the invokes in the try. There is also a reference to the landing + /// pad that handles the exception once processed. Finally an index into + /// the actions table. + /// 2. The action table, in our case, is composed of pairs of type ids + /// and next action offset. Starting with the action index from the + /// landing pad site, each type Id is checked for a match to the current + /// exception. If it matches then the exception and type id are passed + /// on to the landing pad. Otherwise the next action is looked up. This + /// chain is terminated with a next action of zero. If no type id is + /// found the the frame is unwound and handling continues. + /// 3. Type id table contains references to all the C++ typeinfo for all + /// catches in the function. This tables is reversed indexed base 1. + + /// SharedTypeIds - How many leading type ids two landing pads have in common. + static unsigned SharedTypeIds(const LandingPadInfo *L, + const LandingPadInfo *R); + + /// PadLT - Order landing pads lexicographically by type id. + static bool PadLT(const LandingPadInfo *L, const LandingPadInfo *R); + + struct KeyInfo { + static inline unsigned getEmptyKey() { return -1U; } + static inline unsigned getTombstoneKey() { return -2U; } + static unsigned getHashValue(const unsigned &Key) { return Key; } + static bool isEqual(unsigned LHS, unsigned RHS) { return LHS == RHS; } + static bool isPod() { return true; } + }; + + /// PadRange - Structure holding a try-range and the associated landing pad. + struct PadRange { + // The index of the landing pad. + unsigned PadIndex; + // The index of the begin and end labels in the landing pad's label lists. + unsigned RangeIndex; + }; + + typedef DenseMap RangeMapType; + + /// ActionEntry - Structure describing an entry in the actions table. + struct ActionEntry { + int ValueForTypeID; // The value to write - may not be equal to the type id. + int NextAction; + struct ActionEntry *Previous; + }; + + /// CallSiteEntry - Structure describing an entry in the call-site table. + struct CallSiteEntry { + // The 'try-range' is BeginLabel .. EndLabel. + unsigned BeginLabel; // zero indicates the start of the function. + unsigned EndLabel; // zero indicates the end of the function. + + // The landing pad starts at PadLabel. + unsigned PadLabel; // zero indicates that there is no landing pad. + unsigned Action; + }; + + /// ComputeActionsTable - Compute the actions table and gather the first + /// action index for each landing pad site. + unsigned ComputeActionsTable(const SmallVectorImpl&LPs, + SmallVectorImpl &Actions, + SmallVectorImpl &FirstActions); + + /// CallToNoUnwindFunction - Return `true' if this is a call to a function + /// marked `nounwind'. Return `false' otherwise. + bool CallToNoUnwindFunction(const MachineInstr *MI); + + /// ComputeCallSiteTable - Compute the call-site table. The entry for an + /// invoke has a try-range containing the call, a non-zero landing pad and an + /// appropriate action. The entry for an ordinary call has a try-range + /// containing the call and zero for the landing pad and the action. Calls + /// marked 'nounwind' have no entry and must not be contained in the try-range + /// of any entry - they form gaps in the table. Entries must be ordered by + /// try-range address. + void ComputeCallSiteTable(SmallVectorImpl &CallSites, + const RangeMapType &PadMap, + const SmallVectorImpl &LPs, + const SmallVectorImpl &FirstActions); + void EmitExceptionTable(); + + /// CreateLabelDiff - Emit a label and subtract it from the expression we + /// already have. This is equivalent to emitting "foo - .", but we have to + /// emit the label for "." directly. + const MCExpr *CreateLabelDiff(const MCExpr *ExprRef, const char *LabelName, + unsigned Index); +public: + //===--------------------------------------------------------------------===// + // Main entry points. + // + DwarfException(raw_ostream &OS, AsmPrinter *A, const MCAsmInfo *T); + virtual ~DwarfException(); + + /// BeginModule - Emit all exception information that should come prior to the + /// content. + void BeginModule(Module *m, MachineModuleInfo *mmi) { + this->M = m; + this->MMI = mmi; + } + + /// EndModule - Emit all exception information that should come after the + /// content. + void EndModule(); + + /// BeginFunction - Gather pre-function exception information. Assumes being + /// emitted immediately after the function entry point. + void BeginFunction(MachineFunction *MF); + + /// EndFunction - Gather and emit post-function exception information. + void EndFunction(); +}; + +} // End of namespace llvm + +#endif diff --git a/libclamav/c++/llvm/lib/CodeGen/AsmPrinter/DwarfLabel.cpp b/libclamav/c++/llvm/lib/CodeGen/AsmPrinter/DwarfLabel.cpp new file mode 100644 index 000000000..6e9293a03 --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/AsmPrinter/DwarfLabel.cpp @@ -0,0 +1,32 @@ +//===--- lib/CodeGen/DwarfLabel.cpp - Dwarf Label -------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// DWARF Labels +// +//===----------------------------------------------------------------------===// + +#include "DwarfLabel.h" +#include "llvm/ADT/FoldingSet.h" +#include "llvm/Support/raw_ostream.h" + +using namespace llvm; + +/// Profile - Used to gather unique data for the folding set. +/// +void DWLabel::Profile(FoldingSetNodeID &ID) const { + ID.AddString(Tag); + ID.AddInteger(Number); +} + +#ifndef NDEBUG +void DWLabel::print(raw_ostream &O) const { + O << "." << Tag; + if (Number) O << Number; +} +#endif diff --git a/libclamav/c++/llvm/lib/CodeGen/AsmPrinter/DwarfLabel.h b/libclamav/c++/llvm/lib/CodeGen/AsmPrinter/DwarfLabel.h new file mode 100644 index 000000000..0c0cc4bdc --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/AsmPrinter/DwarfLabel.h @@ -0,0 +1,52 @@ +//===--- lib/CodeGen/DwarfLabel.h - Dwarf Label -----------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// DWARF Labels. +// +//===----------------------------------------------------------------------===// + +#ifndef CODEGEN_ASMPRINTER_DWARFLABEL_H__ +#define CODEGEN_ASMPRINTER_DWARFLABEL_H__ + +namespace llvm { + class FoldingSetNodeID; + class raw_ostream; + + //===--------------------------------------------------------------------===// + /// DWLabel - Labels are used to track locations in the assembler file. + /// Labels appear in the form @verbatim @endverbatim, + /// where the tag is a category of label (Ex. location) and number is a value + /// unique in that category. + class DWLabel { + /// Tag - Label category tag. Should always be a statically declared C + /// string. + /// + const char *Tag; + + /// Number - Value to make label unique. + /// + unsigned Number; + public: + DWLabel(const char *T, unsigned N) : Tag(T), Number(N) {} + + // Accessors. + const char *getTag() const { return Tag; } + unsigned getNumber() const { return Number; } + + /// Profile - Used to gather unique data for the folding set. + /// + void Profile(FoldingSetNodeID &ID) const; + +#ifndef NDEBUG + void print(raw_ostream &O) const; +#endif + }; +} // end llvm namespace + +#endif diff --git a/libclamav/c++/llvm/lib/CodeGen/AsmPrinter/DwarfPrinter.cpp b/libclamav/c++/llvm/lib/CodeGen/AsmPrinter/DwarfPrinter.cpp new file mode 100644 index 000000000..20b959b91 --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/AsmPrinter/DwarfPrinter.cpp @@ -0,0 +1,236 @@ +//===--- lib/CodeGen/DwarfPrinter.cpp - Dwarf Printer ---------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Emit general DWARF directives. +// +//===----------------------------------------------------------------------===// + +#include "DwarfPrinter.h" +#include "llvm/Module.h" +#include "llvm/CodeGen/AsmPrinter.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetFrameInfo.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Support/Dwarf.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/ADT/StringExtras.h" +using namespace llvm; + +Dwarf::Dwarf(raw_ostream &OS, AsmPrinter *A, const MCAsmInfo *T, + const char *flavor) +: O(OS), Asm(A), MAI(T), TD(Asm->TM.getTargetData()), + RI(Asm->TM.getRegisterInfo()), M(NULL), MF(NULL), MMI(NULL), + SubprogramCount(0), Flavor(flavor), SetCounter(1) {} + +void Dwarf::PrintRelDirective(bool Force32Bit, bool isInSection) const { + if (isInSection && MAI->getDwarfSectionOffsetDirective()) + O << MAI->getDwarfSectionOffsetDirective(); + else if (Force32Bit || TD->getPointerSize() == sizeof(int32_t)) + O << MAI->getData32bitsDirective(); + else + O << MAI->getData64bitsDirective(); +} + +/// PrintLabelName - Print label name in form used by Dwarf writer. +/// +void Dwarf::PrintLabelName(const char *Tag, unsigned Number) const { + O << MAI->getPrivateGlobalPrefix() << Tag; + if (Number) O << Number; +} +void Dwarf::PrintLabelName(const char *Tag, unsigned Number, + const char *Suffix) const { + O << MAI->getPrivateGlobalPrefix() << Tag; + if (Number) O << Number; + O << Suffix; +} + +/// EmitLabel - Emit location label for internal use by Dwarf. +/// +void Dwarf::EmitLabel(const char *Tag, unsigned Number) const { + PrintLabelName(Tag, Number); + O << ":\n"; +} + +/// EmitReference - Emit a reference to a label. +/// +void Dwarf::EmitReference(const char *Tag, unsigned Number, + bool IsPCRelative, bool Force32Bit) const { + PrintRelDirective(Force32Bit); + PrintLabelName(Tag, Number); + if (IsPCRelative) O << "-" << MAI->getPCSymbol(); +} +void Dwarf::EmitReference(const std::string &Name, bool IsPCRelative, + bool Force32Bit) const { + PrintRelDirective(Force32Bit); + O << Name; + if (IsPCRelative) O << "-" << MAI->getPCSymbol(); +} + +/// EmitDifference - Emit the difference between two labels. Some assemblers do +/// not behave with absolute expressions with data directives, so there is an +/// option (needsSet) to use an intermediary set expression. +void Dwarf::EmitDifference(const char *TagHi, unsigned NumberHi, + const char *TagLo, unsigned NumberLo, + bool IsSmall) { + if (MAI->needsSet()) { + O << "\t.set\t"; + PrintLabelName("set", SetCounter, Flavor); + O << ","; + PrintLabelName(TagHi, NumberHi); + O << "-"; + PrintLabelName(TagLo, NumberLo); + O << "\n"; + + PrintRelDirective(IsSmall); + PrintLabelName("set", SetCounter, Flavor); + ++SetCounter; + } else { + PrintRelDirective(IsSmall); + PrintLabelName(TagHi, NumberHi); + O << "-"; + PrintLabelName(TagLo, NumberLo); + } +} + +void Dwarf::EmitSectionOffset(const char* Label, const char* Section, + unsigned LabelNumber, unsigned SectionNumber, + bool IsSmall, bool isEH, + bool useSet) { + bool printAbsolute = false; + if (isEH) + printAbsolute = MAI->isAbsoluteEHSectionOffsets(); + else + printAbsolute = MAI->isAbsoluteDebugSectionOffsets(); + + if (MAI->needsSet() && useSet) { + O << "\t.set\t"; + PrintLabelName("set", SetCounter, Flavor); + O << ","; + PrintLabelName(Label, LabelNumber); + + if (!printAbsolute) { + O << "-"; + PrintLabelName(Section, SectionNumber); + } + + O << "\n"; + PrintRelDirective(IsSmall); + PrintLabelName("set", SetCounter, Flavor); + ++SetCounter; + } else { + PrintRelDirective(IsSmall, true); + PrintLabelName(Label, LabelNumber); + + if (!printAbsolute) { + O << "-"; + PrintLabelName(Section, SectionNumber); + } + } +} + +/// EmitFrameMoves - Emit frame instructions to describe the layout of the +/// frame. +void Dwarf::EmitFrameMoves(const char *BaseLabel, unsigned BaseLabelID, + const std::vector &Moves, bool isEH) { + int stackGrowth = + Asm->TM.getFrameInfo()->getStackGrowthDirection() == + TargetFrameInfo::StackGrowsUp ? + TD->getPointerSize() : -TD->getPointerSize(); + bool IsLocal = BaseLabel && strcmp(BaseLabel, "label") == 0; + + for (unsigned i = 0, N = Moves.size(); i < N; ++i) { + const MachineMove &Move = Moves[i]; + unsigned LabelID = Move.getLabelID(); + + if (LabelID) { + LabelID = MMI->MappedLabel(LabelID); + + // Throw out move if the label is invalid. + if (!LabelID) continue; + } + + const MachineLocation &Dst = Move.getDestination(); + const MachineLocation &Src = Move.getSource(); + + // Advance row if new location. + if (BaseLabel && LabelID && (BaseLabelID != LabelID || !IsLocal)) { + Asm->EmitInt8(dwarf::DW_CFA_advance_loc4); + Asm->EOL("DW_CFA_advance_loc4"); + EmitDifference("label", LabelID, BaseLabel, BaseLabelID, true); + Asm->EOL(); + + BaseLabelID = LabelID; + BaseLabel = "label"; + IsLocal = true; + } + + // If advancing cfa. + if (Dst.isReg() && Dst.getReg() == MachineLocation::VirtualFP) { + if (!Src.isReg()) { + if (Src.getReg() == MachineLocation::VirtualFP) { + Asm->EmitInt8(dwarf::DW_CFA_def_cfa_offset); + Asm->EOL("DW_CFA_def_cfa_offset"); + } else { + Asm->EmitInt8(dwarf::DW_CFA_def_cfa); + Asm->EOL("DW_CFA_def_cfa"); + Asm->EmitULEB128Bytes(RI->getDwarfRegNum(Src.getReg(), isEH)); + Asm->EOL("Register"); + } + + int Offset = -Src.getOffset(); + + Asm->EmitULEB128Bytes(Offset); + Asm->EOL("Offset"); + } else { + llvm_unreachable("Machine move not supported yet."); + } + } else if (Src.isReg() && + Src.getReg() == MachineLocation::VirtualFP) { + if (Dst.isReg()) { + Asm->EmitInt8(dwarf::DW_CFA_def_cfa_register); + Asm->EOL("DW_CFA_def_cfa_register"); + Asm->EmitULEB128Bytes(RI->getDwarfRegNum(Dst.getReg(), isEH)); + Asm->EOL("Register"); + } else { + llvm_unreachable("Machine move not supported yet."); + } + } else { + unsigned Reg = RI->getDwarfRegNum(Src.getReg(), isEH); + int Offset = Dst.getOffset() / stackGrowth; + + if (Offset < 0) { + Asm->EmitInt8(dwarf::DW_CFA_offset_extended_sf); + Asm->EOL("DW_CFA_offset_extended_sf"); + Asm->EmitULEB128Bytes(Reg); + Asm->EOL("Reg"); + Asm->EmitSLEB128Bytes(Offset); + Asm->EOL("Offset"); + } else if (Reg < 64) { + Asm->EmitInt8(dwarf::DW_CFA_offset + Reg); + if (Asm->isVerbose()) + Asm->EOL("DW_CFA_offset + Reg (" + utostr(Reg) + ")"); + else + Asm->EOL(); + Asm->EmitULEB128Bytes(Offset); + Asm->EOL("Offset"); + } else { + Asm->EmitInt8(dwarf::DW_CFA_offset_extended); + Asm->EOL("DW_CFA_offset_extended"); + Asm->EmitULEB128Bytes(Reg); + Asm->EOL("Reg"); + Asm->EmitULEB128Bytes(Offset); + Asm->EOL("Offset"); + } + } + } +} diff --git a/libclamav/c++/llvm/lib/CodeGen/AsmPrinter/DwarfPrinter.h b/libclamav/c++/llvm/lib/CodeGen/AsmPrinter/DwarfPrinter.h new file mode 100644 index 000000000..dedd69539 --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/AsmPrinter/DwarfPrinter.h @@ -0,0 +1,153 @@ +//===--- lib/CodeGen/DwarfPrinter.h - Dwarf Printer -------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Emit general DWARF directives. +// +//===----------------------------------------------------------------------===// + +#ifndef CODEGEN_ASMPRINTER_DWARFPRINTER_H__ +#define CODEGEN_ASMPRINTER_DWARFPRINTER_H__ + +#include "DwarfLabel.h" +#include "llvm/CodeGen/MachineLocation.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/raw_ostream.h" +#include + +namespace llvm { + class AsmPrinter; + class MachineFunction; + class MachineModuleInfo; + class Module; + class MCAsmInfo; + class TargetData; + class TargetRegisterInfo; + + class Dwarf { + protected: + //===-------------------------------------------------------------==---===// + // Core attributes used by the DWARF printer. + // + + /// O - Stream to .s file. + /// + raw_ostream &O; + + /// Asm - Target of Dwarf emission. + /// + AsmPrinter *Asm; + + /// MAI - Target asm information. + /// + const MCAsmInfo *MAI; + + /// TD - Target data. + /// + const TargetData *TD; + + /// RI - Register Information. + /// + const TargetRegisterInfo *RI; + + /// M - Current module. + /// + Module *M; + + /// MF - Current machine function. + /// + MachineFunction *MF; + + /// MMI - Collected machine module information. + /// + MachineModuleInfo *MMI; + + /// SubprogramCount - The running count of functions being compiled. + /// + unsigned SubprogramCount; + + /// Flavor - A unique string indicating what dwarf producer this is, used to + /// unique labels. + /// + const char * const Flavor; + + /// SetCounter - A unique number for each '.set' directive. + /// + unsigned SetCounter; + + Dwarf(raw_ostream &OS, AsmPrinter *A, const MCAsmInfo *T, + const char *flavor); + public: + //===------------------------------------------------------------------===// + // Accessors. + // + const AsmPrinter *getAsm() const { return Asm; } + MachineModuleInfo *getMMI() const { return MMI; } + const MCAsmInfo *getMCAsmInfo() const { return MAI; } + const TargetData *getTargetData() const { return TD; } + + void PrintRelDirective(bool Force32Bit = false, + bool isInSection = false) const; + + + /// PrintLabelName - Print label name in form used by Dwarf writer. + /// + void PrintLabelName(const DWLabel &Label) const { + PrintLabelName(Label.getTag(), Label.getNumber()); + } + void PrintLabelName(const char *Tag, unsigned Number) const; + void PrintLabelName(const char *Tag, unsigned Number, + const char *Suffix) const; + + /// EmitLabel - Emit location label for internal use by Dwarf. + /// + void EmitLabel(const DWLabel &Label) const { + EmitLabel(Label.getTag(), Label.getNumber()); + } + void EmitLabel(const char *Tag, unsigned Number) const; + + /// EmitReference - Emit a reference to a label. + /// + void EmitReference(const DWLabel &Label, bool IsPCRelative = false, + bool Force32Bit = false) const { + EmitReference(Label.getTag(), Label.getNumber(), + IsPCRelative, Force32Bit); + } + void EmitReference(const char *Tag, unsigned Number, + bool IsPCRelative = false, + bool Force32Bit = false) const; + void EmitReference(const std::string &Name, bool IsPCRelative = false, + bool Force32Bit = false) const; + + /// EmitDifference - Emit the difference between two labels. Some + /// assemblers do not behave with absolute expressions with data directives, + /// so there is an option (needsSet) to use an intermediary set expression. + void EmitDifference(const DWLabel &LabelHi, const DWLabel &LabelLo, + bool IsSmall = false) { + EmitDifference(LabelHi.getTag(), LabelHi.getNumber(), + LabelLo.getTag(), LabelLo.getNumber(), + IsSmall); + } + void EmitDifference(const char *TagHi, unsigned NumberHi, + const char *TagLo, unsigned NumberLo, + bool IsSmall = false); + + void EmitSectionOffset(const char* Label, const char* Section, + unsigned LabelNumber, unsigned SectionNumber, + bool IsSmall = false, bool isEH = false, + bool useSet = true); + + /// EmitFrameMoves - Emit frame instructions to describe the layout of the + /// frame. + void EmitFrameMoves(const char *BaseLabel, unsigned BaseLabelID, + const std::vector &Moves, bool isEH); +}; + +} // end llvm namespace + +#endif diff --git a/libclamav/c++/llvm/lib/CodeGen/AsmPrinter/DwarfWriter.cpp b/libclamav/c++/llvm/lib/CodeGen/AsmPrinter/DwarfWriter.cpp new file mode 100644 index 000000000..dd8d88a2e --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/AsmPrinter/DwarfWriter.cpp @@ -0,0 +1,100 @@ +//===-- llvm/CodeGen/DwarfWriter.cpp - Dwarf Framework --------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains support for writing dwarf info into asm files. +// +//===----------------------------------------------------------------------===// + +#include "llvm/CodeGen/DwarfWriter.h" +#include "DwarfDebug.h" +#include "DwarfException.h" +#include "llvm/CodeGen/MachineModuleInfo.h" + +using namespace llvm; + +static RegisterPass +X("dwarfwriter", "DWARF Information Writer"); +char DwarfWriter::ID = 0; + +//===----------------------------------------------------------------------===// +/// DwarfWriter Implementation +/// + +DwarfWriter::DwarfWriter() + : ImmutablePass(&ID), DD(0), DE(0) {} + +DwarfWriter::~DwarfWriter() { + delete DE; + delete DD; +} + +/// BeginModule - Emit all Dwarf sections that should come prior to the +/// content. +void DwarfWriter::BeginModule(Module *M, + MachineModuleInfo *MMI, + raw_ostream &OS, AsmPrinter *A, + const MCAsmInfo *T) { + DE = new DwarfException(OS, A, T); + DD = new DwarfDebug(OS, A, T); + DE->BeginModule(M, MMI); + DD->beginModule(M, MMI); +} + +/// EndModule - Emit all Dwarf sections that should come after the content. +/// +void DwarfWriter::EndModule() { + DE->EndModule(); + DD->endModule(); + delete DD; DD = 0; + delete DE; DE = 0; +} + +/// BeginFunction - Gather pre-function debug information. Assumes being +/// emitted immediately after the function entry point. +void DwarfWriter::BeginFunction(MachineFunction *MF) { + DE->BeginFunction(MF); + DD->beginFunction(MF); +} + +/// EndFunction - Gather and emit post-function debug information. +/// +void DwarfWriter::EndFunction(MachineFunction *MF) { + DD->endFunction(MF); + DE->EndFunction(); + + if (MachineModuleInfo *MMI = DD->getMMI() ? DD->getMMI() : DE->getMMI()) + // Clear function debug information. + MMI->EndFunction(); +} + +/// RecordSourceLine - Records location information and associates it with a +/// label. Returns a unique label ID used to generate a label and provide +/// correspondence to the source line list. +unsigned DwarfWriter::RecordSourceLine(unsigned Line, unsigned Col, + MDNode *Scope) { + return DD->recordSourceLine(Line, Col, Scope); +} + +/// getRecordSourceLineCount - Count source lines. +unsigned DwarfWriter::getRecordSourceLineCount() { + return DD->getSourceLineCount(); +} + +/// ShouldEmitDwarfDebug - Returns true if Dwarf debugging declarations should +/// be emitted. +bool DwarfWriter::ShouldEmitDwarfDebug() const { + return DD && DD->ShouldEmitDwarfDebug(); +} + +void DwarfWriter::BeginScope(const MachineInstr *MI, unsigned L) { + DD->beginScope(MI, L); +} +void DwarfWriter::EndScope(const MachineInstr *MI) { + DD->endScope(MI); +} diff --git a/libclamav/c++/llvm/lib/CodeGen/AsmPrinter/Makefile b/libclamav/c++/llvm/lib/CodeGen/AsmPrinter/Makefile new file mode 100644 index 000000000..8f65d8d3f --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/AsmPrinter/Makefile @@ -0,0 +1,13 @@ +##===- lib/CodeGen/SelectionDAG/Makefile -------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## +LEVEL = ../../.. +LIBRARYNAME = LLVMAsmPrinter +PARALLEL_DIRS = + +include $(LEVEL)/Makefile.common diff --git a/libclamav/c++/llvm/lib/CodeGen/AsmPrinter/OcamlGCPrinter.cpp b/libclamav/c++/llvm/lib/CodeGen/AsmPrinter/OcamlGCPrinter.cpp new file mode 100644 index 000000000..9286ad518 --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/AsmPrinter/OcamlGCPrinter.cpp @@ -0,0 +1,165 @@ +//===-- OcamlGCPrinter.cpp - Ocaml frametable emitter ---------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements printing the assembly code for an Ocaml frametable. +// +//===----------------------------------------------------------------------===// + +#include "llvm/CodeGen/GCs.h" +#include "llvm/CodeGen/AsmPrinter.h" +#include "llvm/CodeGen/GCMetadataPrinter.h" +#include "llvm/Module.h" +#include "llvm/MC/MCStreamer.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetLoweringObjectFile.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +namespace { + + class OcamlGCMetadataPrinter : public GCMetadataPrinter { + public: + void beginAssembly(raw_ostream &OS, AsmPrinter &AP, + const MCAsmInfo &MAI); + + void finishAssembly(raw_ostream &OS, AsmPrinter &AP, + const MCAsmInfo &MAI); + }; + +} + +static GCMetadataPrinterRegistry::Add +Y("ocaml", "ocaml 3.10-compatible collector"); + +void llvm::linkOcamlGCPrinter() { } + +static void EmitCamlGlobal(const Module &M, raw_ostream &OS, AsmPrinter &AP, + const MCAsmInfo &MAI, const char *Id) { + const std::string &MId = M.getModuleIdentifier(); + + std::string Mangled; + Mangled += MAI.getGlobalPrefix(); + Mangled += "caml"; + size_t Letter = Mangled.size(); + Mangled.append(MId.begin(), std::find(MId.begin(), MId.end(), '.')); + Mangled += "__"; + Mangled += Id; + + // Capitalize the first letter of the module name. + Mangled[Letter] = toupper(Mangled[Letter]); + + if (const char *GlobalDirective = MAI.getGlobalDirective()) + OS << GlobalDirective << Mangled << "\n"; + OS << Mangled << ":\n"; +} + +void OcamlGCMetadataPrinter::beginAssembly(raw_ostream &OS, AsmPrinter &AP, + const MCAsmInfo &MAI) { + AP.OutStreamer.SwitchSection(AP.getObjFileLowering().getTextSection()); + EmitCamlGlobal(getModule(), OS, AP, MAI, "code_begin"); + + AP.OutStreamer.SwitchSection(AP.getObjFileLowering().getDataSection()); + EmitCamlGlobal(getModule(), OS, AP, MAI, "data_begin"); +} + +/// emitAssembly - Print the frametable. The ocaml frametable format is thus: +/// +/// extern "C" struct align(sizeof(intptr_t)) { +/// uint16_t NumDescriptors; +/// struct align(sizeof(intptr_t)) { +/// void *ReturnAddress; +/// uint16_t FrameSize; +/// uint16_t NumLiveOffsets; +/// uint16_t LiveOffsets[NumLiveOffsets]; +/// } Descriptors[NumDescriptors]; +/// } caml${module}__frametable; +/// +/// Note that this precludes programs from stack frames larger than 64K +/// (FrameSize and LiveOffsets would overflow). FrameTablePrinter will abort if +/// either condition is detected in a function which uses the GC. +/// +void OcamlGCMetadataPrinter::finishAssembly(raw_ostream &OS, AsmPrinter &AP, + const MCAsmInfo &MAI) { + const char *AddressDirective; + int AddressAlignLog; + if (AP.TM.getTargetData()->getPointerSize() == sizeof(int32_t)) { + AddressDirective = MAI.getData32bitsDirective(); + AddressAlignLog = 2; + } else { + AddressDirective = MAI.getData64bitsDirective(); + AddressAlignLog = 3; + } + + AP.OutStreamer.SwitchSection(AP.getObjFileLowering().getTextSection()); + EmitCamlGlobal(getModule(), OS, AP, MAI, "code_end"); + + AP.OutStreamer.SwitchSection(AP.getObjFileLowering().getDataSection()); + EmitCamlGlobal(getModule(), OS, AP, MAI, "data_end"); + + OS << AddressDirective << 0; // FIXME: Why does ocaml emit this?? + AP.EOL(); + + AP.OutStreamer.SwitchSection(AP.getObjFileLowering().getDataSection()); + EmitCamlGlobal(getModule(), OS, AP, MAI, "frametable"); + + for (iterator I = begin(), IE = end(); I != IE; ++I) { + GCFunctionInfo &FI = **I; + + uint64_t FrameSize = FI.getFrameSize(); + if (FrameSize >= 1<<16) { + std::string msg; + raw_string_ostream Msg(msg); + Msg << "Function '" << FI.getFunction().getName() + << "' is too large for the ocaml GC! " + << "Frame size " << FrameSize << " >= 65536.\n"; + Msg << "(" << uintptr_t(&FI) << ")"; + llvm_report_error(Msg.str()); // Very rude! + } + + OS << "\t" << MAI.getCommentString() << " live roots for " + << FI.getFunction().getName() << "\n"; + + for (GCFunctionInfo::iterator J = FI.begin(), JE = FI.end(); J != JE; ++J) { + size_t LiveCount = FI.live_size(J); + if (LiveCount >= 1<<16) { + std::string msg; + raw_string_ostream Msg(msg); + Msg << "Function '" << FI.getFunction().getName() + << "' is too large for the ocaml GC! " + << "Live root count " << LiveCount << " >= 65536."; + llvm_report_error(Msg.str()); // Very rude! + } + + OS << AddressDirective + << MAI.getPrivateGlobalPrefix() << "label" << J->Num; + AP.EOL("call return address"); + + AP.EmitInt16(FrameSize); + AP.EOL("stack frame size"); + + AP.EmitInt16(LiveCount); + AP.EOL("live root count"); + + for (GCFunctionInfo::live_iterator K = FI.live_begin(J), + KE = FI.live_end(J); K != KE; ++K) { + assert(K->StackOffset < 1<<16 && + "GC root stack offset is outside of fixed stack frame and out " + "of range for ocaml GC!"); + + OS << "\t.word\t" << K->StackOffset; + AP.EOL("stack offset"); + } + + AP.EmitAlignment(AddressAlignLog); + } + } +} diff --git a/libclamav/c++/llvm/lib/CodeGen/BranchFolding.cpp b/libclamav/c++/llvm/lib/CodeGen/BranchFolding.cpp new file mode 100644 index 000000000..8a62eb20b --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/BranchFolding.cpp @@ -0,0 +1,1290 @@ +//===-- BranchFolding.cpp - Fold machine code branch instructions ---------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This pass forwards branches to unconditional branches to make them branch +// directly to the target block. This pass often results in dead MBB's, which +// it then removes. +// +// Note that this pass must be run after register allocation, it cannot handle +// SSA form. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "branchfolding" +#include "BranchFolding.h" +#include "llvm/Function.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineJumpTableInfo.h" +#include "llvm/CodeGen/RegisterScavenging.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/ADT/SmallSet.h" +#include "llvm/ADT/SetVector.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/ADT/STLExtras.h" +#include +using namespace llvm; + +STATISTIC(NumDeadBlocks, "Number of dead blocks removed"); +STATISTIC(NumBranchOpts, "Number of branches optimized"); +STATISTIC(NumTailMerge , "Number of block tails merged"); + +static cl::opt FlagEnableTailMerge("enable-tail-merge", + cl::init(cl::BOU_UNSET), cl::Hidden); + +// Throttle for huge numbers of predecessors (compile speed problems) +static cl::opt +TailMergeThreshold("tail-merge-threshold", + cl::desc("Max number of predecessors to consider tail merging"), + cl::init(150), cl::Hidden); + +// Heuristic for tail merging (and, inversely, tail duplication). +// TODO: This should be replaced with a target query. +static cl::opt +TailMergeSize("tail-merge-size", + cl::desc("Min number of instructions to consider tail merging"), + cl::init(3), cl::Hidden); + +namespace { + /// BranchFolderPass - Wrap branch folder in a machine function pass. + class BranchFolderPass : public MachineFunctionPass, + public BranchFolder { + public: + static char ID; + explicit BranchFolderPass(bool defaultEnableTailMerge) + : MachineFunctionPass(&ID), BranchFolder(defaultEnableTailMerge) {} + + virtual bool runOnMachineFunction(MachineFunction &MF); + virtual const char *getPassName() const { return "Control Flow Optimizer"; } + }; +} + +char BranchFolderPass::ID = 0; + +FunctionPass *llvm::createBranchFoldingPass(bool DefaultEnableTailMerge) { + return new BranchFolderPass(DefaultEnableTailMerge); +} + +bool BranchFolderPass::runOnMachineFunction(MachineFunction &MF) { + return OptimizeFunction(MF, + MF.getTarget().getInstrInfo(), + MF.getTarget().getRegisterInfo(), + getAnalysisIfAvailable()); +} + + +BranchFolder::BranchFolder(bool defaultEnableTailMerge) { + switch (FlagEnableTailMerge) { + case cl::BOU_UNSET: EnableTailMerge = defaultEnableTailMerge; break; + case cl::BOU_TRUE: EnableTailMerge = true; break; + case cl::BOU_FALSE: EnableTailMerge = false; break; + } +} + +/// RemoveDeadBlock - Remove the specified dead machine basic block from the +/// function, updating the CFG. +void BranchFolder::RemoveDeadBlock(MachineBasicBlock *MBB) { + assert(MBB->pred_empty() && "MBB must be dead!"); + DEBUG(errs() << "\nRemoving MBB: " << *MBB); + + MachineFunction *MF = MBB->getParent(); + // drop all successors. + while (!MBB->succ_empty()) + MBB->removeSuccessor(MBB->succ_end()-1); + + // If there are any labels in the basic block, unregister them from + // MachineModuleInfo. + if (MMI && !MBB->empty()) { + for (MachineBasicBlock::iterator I = MBB->begin(), E = MBB->end(); + I != E; ++I) { + if (I->isLabel()) + // The label ID # is always operand #0, an immediate. + MMI->InvalidateLabel(I->getOperand(0).getImm()); + } + } + + // Remove the block. + MF->erase(MBB); +} + +/// OptimizeImpDefsBlock - If a basic block is just a bunch of implicit_def +/// followed by terminators, and if the implicitly defined registers are not +/// used by the terminators, remove those implicit_def's. e.g. +/// BB1: +/// r0 = implicit_def +/// r1 = implicit_def +/// br +/// This block can be optimized away later if the implicit instructions are +/// removed. +bool BranchFolder::OptimizeImpDefsBlock(MachineBasicBlock *MBB) { + SmallSet ImpDefRegs; + MachineBasicBlock::iterator I = MBB->begin(); + while (I != MBB->end()) { + if (I->getOpcode() != TargetInstrInfo::IMPLICIT_DEF) + break; + unsigned Reg = I->getOperand(0).getReg(); + ImpDefRegs.insert(Reg); + for (const unsigned *SubRegs = TRI->getSubRegisters(Reg); + unsigned SubReg = *SubRegs; ++SubRegs) + ImpDefRegs.insert(SubReg); + ++I; + } + if (ImpDefRegs.empty()) + return false; + + MachineBasicBlock::iterator FirstTerm = I; + while (I != MBB->end()) { + if (!TII->isUnpredicatedTerminator(I)) + return false; + // See if it uses any of the implicitly defined registers. + for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i) { + MachineOperand &MO = I->getOperand(i); + if (!MO.isReg() || !MO.isUse()) + continue; + unsigned Reg = MO.getReg(); + if (ImpDefRegs.count(Reg)) + return false; + } + ++I; + } + + I = MBB->begin(); + while (I != FirstTerm) { + MachineInstr *ImpDefMI = &*I; + ++I; + MBB->erase(ImpDefMI); + } + + return true; +} + +/// OptimizeFunction - Perhaps branch folding, tail merging and other +/// CFG optimizations on the given function. +bool BranchFolder::OptimizeFunction(MachineFunction &MF, + const TargetInstrInfo *tii, + const TargetRegisterInfo *tri, + MachineModuleInfo *mmi) { + if (!tii) return false; + + TII = tii; + TRI = tri; + MMI = mmi; + + RS = TRI->requiresRegisterScavenging(MF) ? new RegScavenger() : NULL; + + // Fix CFG. The later algorithms expect it to be right. + bool MadeChange = false; + for (MachineFunction::iterator I = MF.begin(), E = MF.end(); I != E; I++) { + MachineBasicBlock *MBB = I, *TBB = 0, *FBB = 0; + SmallVector Cond; + if (!TII->AnalyzeBranch(*MBB, TBB, FBB, Cond, true)) + MadeChange |= MBB->CorrectExtraCFGEdges(TBB, FBB, !Cond.empty()); + MadeChange |= OptimizeImpDefsBlock(MBB); + } + + bool MadeChangeThisIteration = true; + while (MadeChangeThisIteration) { + MadeChangeThisIteration = false; + MadeChangeThisIteration |= TailMergeBlocks(MF); + MadeChangeThisIteration |= OptimizeBranches(MF); + MadeChange |= MadeChangeThisIteration; + } + + // See if any jump tables have become mergable or dead as the code generator + // did its thing. + MachineJumpTableInfo *JTI = MF.getJumpTableInfo(); + const std::vector &JTs = JTI->getJumpTables(); + if (!JTs.empty()) { + // Figure out how these jump tables should be merged. + std::vector JTMapping; + JTMapping.reserve(JTs.size()); + + // We always keep the 0th jump table. + JTMapping.push_back(0); + + // Scan the jump tables, seeing if there are any duplicates. Note that this + // is N^2, which should be fixed someday. + for (unsigned i = 1, e = JTs.size(); i != e; ++i) { + if (JTs[i].MBBs.empty()) + JTMapping.push_back(i); + else + JTMapping.push_back(JTI->getJumpTableIndex(JTs[i].MBBs)); + } + + // If a jump table was merge with another one, walk the function rewriting + // references to jump tables to reference the new JT ID's. Keep track of + // whether we see a jump table idx, if not, we can delete the JT. + BitVector JTIsLive(JTs.size()); + for (MachineFunction::iterator BB = MF.begin(), E = MF.end(); + BB != E; ++BB) { + for (MachineBasicBlock::iterator I = BB->begin(), E = BB->end(); + I != E; ++I) + for (unsigned op = 0, e = I->getNumOperands(); op != e; ++op) { + MachineOperand &Op = I->getOperand(op); + if (!Op.isJTI()) continue; + unsigned NewIdx = JTMapping[Op.getIndex()]; + Op.setIndex(NewIdx); + + // Remember that this JT is live. + JTIsLive.set(NewIdx); + } + } + + // Finally, remove dead jump tables. This happens either because the + // indirect jump was unreachable (and thus deleted) or because the jump + // table was merged with some other one. + for (unsigned i = 0, e = JTIsLive.size(); i != e; ++i) + if (!JTIsLive.test(i)) { + JTI->RemoveJumpTable(i); + MadeChange = true; + } + } + + delete RS; + return MadeChange; +} + +//===----------------------------------------------------------------------===// +// Tail Merging of Blocks +//===----------------------------------------------------------------------===// + +/// HashMachineInstr - Compute a hash value for MI and its operands. +static unsigned HashMachineInstr(const MachineInstr *MI) { + unsigned Hash = MI->getOpcode(); + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + const MachineOperand &Op = MI->getOperand(i); + + // Merge in bits from the operand if easy. + unsigned OperandHash = 0; + switch (Op.getType()) { + case MachineOperand::MO_Register: OperandHash = Op.getReg(); break; + case MachineOperand::MO_Immediate: OperandHash = Op.getImm(); break; + case MachineOperand::MO_MachineBasicBlock: + OperandHash = Op.getMBB()->getNumber(); + break; + case MachineOperand::MO_FrameIndex: + case MachineOperand::MO_ConstantPoolIndex: + case MachineOperand::MO_JumpTableIndex: + OperandHash = Op.getIndex(); + break; + case MachineOperand::MO_GlobalAddress: + case MachineOperand::MO_ExternalSymbol: + // Global address / external symbol are too hard, don't bother, but do + // pull in the offset. + OperandHash = Op.getOffset(); + break; + default: break; + } + + Hash += ((OperandHash << 3) | Op.getType()) << (i&31); + } + return Hash; +} + +/// HashEndOfMBB - Hash the last few instructions in the MBB. For blocks +/// with no successors, we hash two instructions, because cross-jumping +/// only saves code when at least two instructions are removed (since a +/// branch must be inserted). For blocks with a successor, one of the +/// two blocks to be tail-merged will end with a branch already, so +/// it gains to cross-jump even for one instruction. +static unsigned HashEndOfMBB(const MachineBasicBlock *MBB, + unsigned minCommonTailLength) { + MachineBasicBlock::const_iterator I = MBB->end(); + if (I == MBB->begin()) + return 0; // Empty MBB. + + --I; + unsigned Hash = HashMachineInstr(I); + + if (I == MBB->begin() || minCommonTailLength == 1) + return Hash; // Single instr MBB. + + --I; + // Hash in the second-to-last instruction. + Hash ^= HashMachineInstr(I) << 2; + return Hash; +} + +/// ComputeCommonTailLength - Given two machine basic blocks, compute the number +/// of instructions they actually have in common together at their end. Return +/// iterators for the first shared instruction in each block. +static unsigned ComputeCommonTailLength(MachineBasicBlock *MBB1, + MachineBasicBlock *MBB2, + MachineBasicBlock::iterator &I1, + MachineBasicBlock::iterator &I2) { + I1 = MBB1->end(); + I2 = MBB2->end(); + + unsigned TailLen = 0; + while (I1 != MBB1->begin() && I2 != MBB2->begin()) { + --I1; --I2; + if (!I1->isIdenticalTo(I2) || + // FIXME: This check is dubious. It's used to get around a problem where + // people incorrectly expect inline asm directives to remain in the same + // relative order. This is untenable because normal compiler + // optimizations (like this one) may reorder and/or merge these + // directives. + I1->getOpcode() == TargetInstrInfo::INLINEASM) { + ++I1; ++I2; + break; + } + ++TailLen; + } + return TailLen; +} + +/// ReplaceTailWithBranchTo - Delete the instruction OldInst and everything +/// after it, replacing it with an unconditional branch to NewDest. This +/// returns true if OldInst's block is modified, false if NewDest is modified. +void BranchFolder::ReplaceTailWithBranchTo(MachineBasicBlock::iterator OldInst, + MachineBasicBlock *NewDest) { + MachineBasicBlock *OldBB = OldInst->getParent(); + + // Remove all the old successors of OldBB from the CFG. + while (!OldBB->succ_empty()) + OldBB->removeSuccessor(OldBB->succ_begin()); + + // Remove all the dead instructions from the end of OldBB. + OldBB->erase(OldInst, OldBB->end()); + + // If OldBB isn't immediately before OldBB, insert a branch to it. + if (++MachineFunction::iterator(OldBB) != MachineFunction::iterator(NewDest)) + TII->InsertBranch(*OldBB, NewDest, 0, SmallVector()); + OldBB->addSuccessor(NewDest); + ++NumTailMerge; +} + +/// SplitMBBAt - Given a machine basic block and an iterator into it, split the +/// MBB so that the part before the iterator falls into the part starting at the +/// iterator. This returns the new MBB. +MachineBasicBlock *BranchFolder::SplitMBBAt(MachineBasicBlock &CurMBB, + MachineBasicBlock::iterator BBI1) { + MachineFunction &MF = *CurMBB.getParent(); + + // Create the fall-through block. + MachineFunction::iterator MBBI = &CurMBB; + MachineBasicBlock *NewMBB =MF.CreateMachineBasicBlock(CurMBB.getBasicBlock()); + CurMBB.getParent()->insert(++MBBI, NewMBB); + + // Move all the successors of this block to the specified block. + NewMBB->transferSuccessors(&CurMBB); + + // Add an edge from CurMBB to NewMBB for the fall-through. + CurMBB.addSuccessor(NewMBB); + + // Splice the code over. + NewMBB->splice(NewMBB->end(), &CurMBB, BBI1, CurMBB.end()); + + // For targets that use the register scavenger, we must maintain LiveIns. + if (RS) { + RS->enterBasicBlock(&CurMBB); + if (!CurMBB.empty()) + RS->forward(prior(CurMBB.end())); + BitVector RegsLiveAtExit(TRI->getNumRegs()); + RS->getRegsUsed(RegsLiveAtExit, false); + for (unsigned int i = 0, e = TRI->getNumRegs(); i != e; i++) + if (RegsLiveAtExit[i]) + NewMBB->addLiveIn(i); + } + + return NewMBB; +} + +/// EstimateRuntime - Make a rough estimate for how long it will take to run +/// the specified code. +static unsigned EstimateRuntime(MachineBasicBlock::iterator I, + MachineBasicBlock::iterator E) { + unsigned Time = 0; + for (; I != E; ++I) { + const TargetInstrDesc &TID = I->getDesc(); + if (TID.isCall()) + Time += 10; + else if (TID.mayLoad() || TID.mayStore()) + Time += 2; + else + ++Time; + } + return Time; +} + +// CurMBB needs to add an unconditional branch to SuccMBB (we removed these +// branches temporarily for tail merging). In the case where CurMBB ends +// with a conditional branch to the next block, optimize by reversing the +// test and conditionally branching to SuccMBB instead. +static void FixTail(MachineBasicBlock *CurMBB, MachineBasicBlock *SuccBB, + const TargetInstrInfo *TII) { + MachineFunction *MF = CurMBB->getParent(); + MachineFunction::iterator I = next(MachineFunction::iterator(CurMBB)); + MachineBasicBlock *TBB = 0, *FBB = 0; + SmallVector Cond; + if (I != MF->end() && + !TII->AnalyzeBranch(*CurMBB, TBB, FBB, Cond, true)) { + MachineBasicBlock *NextBB = I; + if (TBB == NextBB && !Cond.empty() && !FBB) { + if (!TII->ReverseBranchCondition(Cond)) { + TII->RemoveBranch(*CurMBB); + TII->InsertBranch(*CurMBB, SuccBB, NULL, Cond); + return; + } + } + } + TII->InsertBranch(*CurMBB, SuccBB, NULL, SmallVector()); +} + +bool +BranchFolder::MergePotentialsElt::operator<(const MergePotentialsElt &o) const { + if (getHash() < o.getHash()) + return true; + else if (getHash() > o.getHash()) + return false; + else if (getBlock()->getNumber() < o.getBlock()->getNumber()) + return true; + else if (getBlock()->getNumber() > o.getBlock()->getNumber()) + return false; + else { + // _GLIBCXX_DEBUG checks strict weak ordering, which involves comparing + // an object with itself. +#ifndef _GLIBCXX_DEBUG + llvm_unreachable("Predecessor appears twice"); +#endif + return false; + } +} + +/// CountTerminators - Count the number of terminators in the given +/// block and set I to the position of the first non-terminator, if there +/// is one, or MBB->end() otherwise. +static unsigned CountTerminators(MachineBasicBlock *MBB, + MachineBasicBlock::iterator &I) { + I = MBB->end(); + unsigned NumTerms = 0; + for (;;) { + if (I == MBB->begin()) { + I = MBB->end(); + break; + } + --I; + if (!I->getDesc().isTerminator()) break; + ++NumTerms; + } + return NumTerms; +} + +/// ProfitableToMerge - Check if two machine basic blocks have a common tail +/// and decide if it would be profitable to merge those tails. Return the +/// length of the common tail and iterators to the first common instruction +/// in each block. +static bool ProfitableToMerge(MachineBasicBlock *MBB1, + MachineBasicBlock *MBB2, + unsigned minCommonTailLength, + unsigned &CommonTailLen, + MachineBasicBlock::iterator &I1, + MachineBasicBlock::iterator &I2, + MachineBasicBlock *SuccBB, + MachineBasicBlock *PredBB) { + CommonTailLen = ComputeCommonTailLength(MBB1, MBB2, I1, I2); + MachineFunction *MF = MBB1->getParent(); + + if (CommonTailLen == 0) + return false; + + // It's almost always profitable to merge any number of non-terminator + // instructions with the block that falls through into the common successor. + if (MBB1 == PredBB || MBB2 == PredBB) { + MachineBasicBlock::iterator I; + unsigned NumTerms = CountTerminators(MBB1 == PredBB ? MBB2 : MBB1, I); + if (CommonTailLen > NumTerms) + return true; + } + + // If one of the blocks can be completely merged and happens to be in + // a position where the other could fall through into it, merge any number + // of instructions, because it can be done without a branch. + // TODO: If the blocks are not adjacent, move one of them so that they are? + if (MBB1->isLayoutSuccessor(MBB2) && I2 == MBB2->begin()) + return true; + if (MBB2->isLayoutSuccessor(MBB1) && I1 == MBB1->begin()) + return true; + + // If both blocks have an unconditional branch temporarily stripped out, + // count that as an additional common instruction for the following + // heuristics. + unsigned EffectiveTailLen = CommonTailLen; + if (SuccBB && MBB1 != PredBB && MBB2 != PredBB && + !MBB1->back().getDesc().isBarrier() && + !MBB2->back().getDesc().isBarrier()) + ++EffectiveTailLen; + + // Check if the common tail is long enough to be worthwhile. + if (EffectiveTailLen >= minCommonTailLength) + return true; + + // If we are optimizing for code size, 2 instructions in common is enough if + // we don't have to split a block. At worst we will be introducing 1 new + // branch instruction, which is likely to be smaller than the 2 + // instructions that would be deleted in the merge. + if (EffectiveTailLen >= 2 && + MF->getFunction()->hasFnAttr(Attribute::OptimizeForSize) && + (I1 == MBB1->begin() || I2 == MBB2->begin())) + return true; + + return false; +} + +/// ComputeSameTails - Look through all the blocks in MergePotentials that have +/// hash CurHash (guaranteed to match the last element). Build the vector +/// SameTails of all those that have the (same) largest number of instructions +/// in common of any pair of these blocks. SameTails entries contain an +/// iterator into MergePotentials (from which the MachineBasicBlock can be +/// found) and a MachineBasicBlock::iterator into that MBB indicating the +/// instruction where the matching code sequence begins. +/// Order of elements in SameTails is the reverse of the order in which +/// those blocks appear in MergePotentials (where they are not necessarily +/// consecutive). +unsigned BranchFolder::ComputeSameTails(unsigned CurHash, + unsigned minCommonTailLength, + MachineBasicBlock *SuccBB, + MachineBasicBlock *PredBB) { + unsigned maxCommonTailLength = 0U; + SameTails.clear(); + MachineBasicBlock::iterator TrialBBI1, TrialBBI2; + MPIterator HighestMPIter = prior(MergePotentials.end()); + for (MPIterator CurMPIter = prior(MergePotentials.end()), + B = MergePotentials.begin(); + CurMPIter != B && CurMPIter->getHash() == CurHash; + --CurMPIter) { + for (MPIterator I = prior(CurMPIter); I->getHash() == CurHash ; --I) { + unsigned CommonTailLen; + if (ProfitableToMerge(CurMPIter->getBlock(), I->getBlock(), + minCommonTailLength, + CommonTailLen, TrialBBI1, TrialBBI2, + SuccBB, PredBB)) { + if (CommonTailLen > maxCommonTailLength) { + SameTails.clear(); + maxCommonTailLength = CommonTailLen; + HighestMPIter = CurMPIter; + SameTails.push_back(SameTailElt(CurMPIter, TrialBBI1)); + } + if (HighestMPIter == CurMPIter && + CommonTailLen == maxCommonTailLength) + SameTails.push_back(SameTailElt(I, TrialBBI2)); + } + if (I == B) + break; + } + } + return maxCommonTailLength; +} + +/// RemoveBlocksWithHash - Remove all blocks with hash CurHash from +/// MergePotentials, restoring branches at ends of blocks as appropriate. +void BranchFolder::RemoveBlocksWithHash(unsigned CurHash, + MachineBasicBlock *SuccBB, + MachineBasicBlock *PredBB) { + MPIterator CurMPIter, B; + for (CurMPIter = prior(MergePotentials.end()), B = MergePotentials.begin(); + CurMPIter->getHash() == CurHash; + --CurMPIter) { + // Put the unconditional branch back, if we need one. + MachineBasicBlock *CurMBB = CurMPIter->getBlock(); + if (SuccBB && CurMBB != PredBB) + FixTail(CurMBB, SuccBB, TII); + if (CurMPIter == B) + break; + } + if (CurMPIter->getHash() != CurHash) + CurMPIter++; + MergePotentials.erase(CurMPIter, MergePotentials.end()); +} + +/// CreateCommonTailOnlyBlock - None of the blocks to be tail-merged consist +/// only of the common tail. Create a block that does by splitting one. +unsigned BranchFolder::CreateCommonTailOnlyBlock(MachineBasicBlock *&PredBB, + unsigned maxCommonTailLength) { + unsigned commonTailIndex = 0; + unsigned TimeEstimate = ~0U; + for (unsigned i = 0, e = SameTails.size(); i != e; ++i) { + // Use PredBB if possible; that doesn't require a new branch. + if (SameTails[i].getBlock() == PredBB) { + commonTailIndex = i; + break; + } + // Otherwise, make a (fairly bogus) choice based on estimate of + // how long it will take the various blocks to execute. + unsigned t = EstimateRuntime(SameTails[i].getBlock()->begin(), + SameTails[i].getTailStartPos()); + if (t <= TimeEstimate) { + TimeEstimate = t; + commonTailIndex = i; + } + } + + MachineBasicBlock::iterator BBI = + SameTails[commonTailIndex].getTailStartPos(); + MachineBasicBlock *MBB = SameTails[commonTailIndex].getBlock(); + + DEBUG(errs() << "\nSplitting BB#" << MBB->getNumber() << ", size " + << maxCommonTailLength); + + MachineBasicBlock *newMBB = SplitMBBAt(*MBB, BBI); + SameTails[commonTailIndex].setBlock(newMBB); + SameTails[commonTailIndex].setTailStartPos(newMBB->begin()); + + // If we split PredBB, newMBB is the new predecessor. + if (PredBB == MBB) + PredBB = newMBB; + + return commonTailIndex; +} + +// See if any of the blocks in MergePotentials (which all have a common single +// successor, or all have no successor) can be tail-merged. If there is a +// successor, any blocks in MergePotentials that are not tail-merged and +// are not immediately before Succ must have an unconditional branch to +// Succ added (but the predecessor/successor lists need no adjustment). +// The lone predecessor of Succ that falls through into Succ, +// if any, is given in PredBB. + +bool BranchFolder::TryTailMergeBlocks(MachineBasicBlock *SuccBB, + MachineBasicBlock *PredBB) { + bool MadeChange = false; + + // Except for the special cases below, tail-merge if there are at least + // this many instructions in common. + unsigned minCommonTailLength = TailMergeSize; + + DEBUG(errs() << "\nTryTailMergeBlocks: "; + for (unsigned i = 0, e = MergePotentials.size(); i != e; ++i) + errs() << "BB#" << MergePotentials[i].getBlock()->getNumber() + << (i == e-1 ? "" : ", "); + errs() << "\n"; + if (SuccBB) { + errs() << " with successor BB#" << SuccBB->getNumber() << '\n'; + if (PredBB) + errs() << " which has fall-through from BB#" + << PredBB->getNumber() << "\n"; + } + errs() << "Looking for common tails of at least " + << minCommonTailLength << " instruction" + << (minCommonTailLength == 1 ? "" : "s") << '\n'; + ); + + // Sort by hash value so that blocks with identical end sequences sort + // together. + std::stable_sort(MergePotentials.begin(), MergePotentials.end()); + + // Walk through equivalence sets looking for actual exact matches. + while (MergePotentials.size() > 1) { + unsigned CurHash = MergePotentials.back().getHash(); + + // Build SameTails, identifying the set of blocks with this hash code + // and with the maximum number of instructions in common. + unsigned maxCommonTailLength = ComputeSameTails(CurHash, + minCommonTailLength, + SuccBB, PredBB); + + // If we didn't find any pair that has at least minCommonTailLength + // instructions in common, remove all blocks with this hash code and retry. + if (SameTails.empty()) { + RemoveBlocksWithHash(CurHash, SuccBB, PredBB); + continue; + } + + // If one of the blocks is the entire common tail (and not the entry + // block, which we can't jump to), we can treat all blocks with this same + // tail at once. Use PredBB if that is one of the possibilities, as that + // will not introduce any extra branches. + MachineBasicBlock *EntryBB = MergePotentials.begin()->getBlock()-> + getParent()->begin(); + unsigned commonTailIndex = SameTails.size(); + // If there are two blocks, check to see if one can be made to fall through + // into the other. + if (SameTails.size() == 2 && + SameTails[0].getBlock()->isLayoutSuccessor(SameTails[1].getBlock()) && + SameTails[1].tailIsWholeBlock()) + commonTailIndex = 1; + else if (SameTails.size() == 2 && + SameTails[1].getBlock()->isLayoutSuccessor( + SameTails[0].getBlock()) && + SameTails[0].tailIsWholeBlock()) + commonTailIndex = 0; + else { + // Otherwise just pick one, favoring the fall-through predecessor if + // there is one. + for (unsigned i = 0, e = SameTails.size(); i != e; ++i) { + MachineBasicBlock *MBB = SameTails[i].getBlock(); + if (MBB == EntryBB && SameTails[i].tailIsWholeBlock()) + continue; + if (MBB == PredBB) { + commonTailIndex = i; + break; + } + if (SameTails[i].tailIsWholeBlock()) + commonTailIndex = i; + } + } + + if (commonTailIndex == SameTails.size() || + (SameTails[commonTailIndex].getBlock() == PredBB && + !SameTails[commonTailIndex].tailIsWholeBlock())) { + // None of the blocks consist entirely of the common tail. + // Split a block so that one does. + commonTailIndex = CreateCommonTailOnlyBlock(PredBB, maxCommonTailLength); + } + + MachineBasicBlock *MBB = SameTails[commonTailIndex].getBlock(); + // MBB is common tail. Adjust all other BB's to jump to this one. + // Traversal must be forwards so erases work. + DEBUG(errs() << "\nUsing common tail in BB#" << MBB->getNumber() + << " for "); + for (unsigned int i=0, e = SameTails.size(); i != e; ++i) { + if (commonTailIndex == i) + continue; + DEBUG(errs() << "BB#" << SameTails[i].getBlock()->getNumber() + << (i == e-1 ? "" : ", ")); + // Hack the end off BB i, making it jump to BB commonTailIndex instead. + ReplaceTailWithBranchTo(SameTails[i].getTailStartPos(), MBB); + // BB i is no longer a predecessor of SuccBB; remove it from the worklist. + MergePotentials.erase(SameTails[i].getMPIter()); + } + DEBUG(errs() << "\n"); + // We leave commonTailIndex in the worklist in case there are other blocks + // that match it with a smaller number of instructions. + MadeChange = true; + } + return MadeChange; +} + +bool BranchFolder::TailMergeBlocks(MachineFunction &MF) { + + if (!EnableTailMerge) return false; + + bool MadeChange = false; + + // First find blocks with no successors. + MergePotentials.clear(); + for (MachineFunction::iterator I = MF.begin(), E = MF.end(); I != E; ++I) { + if (I->succ_empty()) + MergePotentials.push_back(MergePotentialsElt(HashEndOfMBB(I, 2U), I)); + } + + // See if we can do any tail merging on those. + if (MergePotentials.size() < TailMergeThreshold && + MergePotentials.size() >= 2) + MadeChange |= TryTailMergeBlocks(NULL, NULL); + + // Look at blocks (IBB) with multiple predecessors (PBB). + // We change each predecessor to a canonical form, by + // (1) temporarily removing any unconditional branch from the predecessor + // to IBB, and + // (2) alter conditional branches so they branch to the other block + // not IBB; this may require adding back an unconditional branch to IBB + // later, where there wasn't one coming in. E.g. + // Bcc IBB + // fallthrough to QBB + // here becomes + // Bncc QBB + // with a conceptual B to IBB after that, which never actually exists. + // With those changes, we see whether the predecessors' tails match, + // and merge them if so. We change things out of canonical form and + // back to the way they were later in the process. (OptimizeBranches + // would undo some of this, but we can't use it, because we'd get into + // a compile-time infinite loop repeatedly doing and undoing the same + // transformations.) + + for (MachineFunction::iterator I = next(MF.begin()), E = MF.end(); + I != E; ++I) { + if (I->pred_size() >= 2 && I->pred_size() < TailMergeThreshold) { + SmallPtrSet UniquePreds; + MachineBasicBlock *IBB = I; + MachineBasicBlock *PredBB = prior(I); + MergePotentials.clear(); + for (MachineBasicBlock::pred_iterator P = I->pred_begin(), + E2 = I->pred_end(); + P != E2; ++P) { + MachineBasicBlock *PBB = *P; + // Skip blocks that loop to themselves, can't tail merge these. + if (PBB == IBB) + continue; + // Visit each predecessor only once. + if (!UniquePreds.insert(PBB)) + continue; + MachineBasicBlock *TBB = 0, *FBB = 0; + SmallVector Cond; + if (!TII->AnalyzeBranch(*PBB, TBB, FBB, Cond, true)) { + // Failing case: IBB is the target of a cbr, and + // we cannot reverse the branch. + SmallVector NewCond(Cond); + if (!Cond.empty() && TBB == IBB) { + if (TII->ReverseBranchCondition(NewCond)) + continue; + // This is the QBB case described above + if (!FBB) + FBB = next(MachineFunction::iterator(PBB)); + } + // Failing case: the only way IBB can be reached from PBB is via + // exception handling. Happens for landing pads. Would be nice + // to have a bit in the edge so we didn't have to do all this. + if (IBB->isLandingPad()) { + MachineFunction::iterator IP = PBB; IP++; + MachineBasicBlock *PredNextBB = NULL; + if (IP != MF.end()) + PredNextBB = IP; + if (TBB == NULL) { + if (IBB != PredNextBB) // fallthrough + continue; + } else if (FBB) { + if (TBB != IBB && FBB != IBB) // cbr then ubr + continue; + } else if (Cond.empty()) { + if (TBB != IBB) // ubr + continue; + } else { + if (TBB != IBB && IBB != PredNextBB) // cbr + continue; + } + } + // Remove the unconditional branch at the end, if any. + if (TBB && (Cond.empty() || FBB)) { + TII->RemoveBranch(*PBB); + if (!Cond.empty()) + // reinsert conditional branch only, for now + TII->InsertBranch(*PBB, (TBB == IBB) ? FBB : TBB, 0, NewCond); + } + MergePotentials.push_back(MergePotentialsElt(HashEndOfMBB(PBB, 1U), + *P)); + } + } + if (MergePotentials.size() >= 2) + MadeChange |= TryTailMergeBlocks(IBB, PredBB); + // Reinsert an unconditional branch if needed. + // The 1 below can occur as a result of removing blocks in TryTailMergeBlocks. + PredBB = prior(I); // this may have been changed in TryTailMergeBlocks + if (MergePotentials.size() == 1 && + MergePotentials.begin()->getBlock() != PredBB) + FixTail(MergePotentials.begin()->getBlock(), IBB, TII); + } + } + return MadeChange; +} + +//===----------------------------------------------------------------------===// +// Branch Optimization +//===----------------------------------------------------------------------===// + +bool BranchFolder::OptimizeBranches(MachineFunction &MF) { + bool MadeChange = false; + + // Make sure blocks are numbered in order + MF.RenumberBlocks(); + + for (MachineFunction::iterator I = ++MF.begin(), E = MF.end(); I != E; ) { + MachineBasicBlock *MBB = I++; + MadeChange |= OptimizeBlock(MBB); + + // If it is dead, remove it. + if (MBB->pred_empty()) { + RemoveDeadBlock(MBB); + MadeChange = true; + ++NumDeadBlocks; + } + } + return MadeChange; +} + + +/// IsBetterFallthrough - Return true if it would be clearly better to +/// fall-through to MBB1 than to fall through into MBB2. This has to return +/// a strict ordering, returning true for both (MBB1,MBB2) and (MBB2,MBB1) will +/// result in infinite loops. +static bool IsBetterFallthrough(MachineBasicBlock *MBB1, + MachineBasicBlock *MBB2) { + // Right now, we use a simple heuristic. If MBB2 ends with a call, and + // MBB1 doesn't, we prefer to fall through into MBB1. This allows us to + // optimize branches that branch to either a return block or an assert block + // into a fallthrough to the return. + if (MBB1->empty() || MBB2->empty()) return false; + + // If there is a clear successor ordering we make sure that one block + // will fall through to the next + if (MBB1->isSuccessor(MBB2)) return true; + if (MBB2->isSuccessor(MBB1)) return false; + + MachineInstr *MBB1I = --MBB1->end(); + MachineInstr *MBB2I = --MBB2->end(); + return MBB2I->getDesc().isCall() && !MBB1I->getDesc().isCall(); +} + +/// OptimizeBlock - Analyze and optimize control flow related to the specified +/// block. This is never called on the entry block. +bool BranchFolder::OptimizeBlock(MachineBasicBlock *MBB) { + bool MadeChange = false; + MachineFunction &MF = *MBB->getParent(); +ReoptimizeBlock: + + MachineFunction::iterator FallThrough = MBB; + ++FallThrough; + + // If this block is empty, make everyone use its fall-through, not the block + // explicitly. Landing pads should not do this since the landing-pad table + // points to this block. Blocks with their addresses taken shouldn't be + // optimized away. + if (MBB->empty() && !MBB->isLandingPad() && !MBB->hasAddressTaken()) { + // Dead block? Leave for cleanup later. + if (MBB->pred_empty()) return MadeChange; + + if (FallThrough == MF.end()) { + // TODO: Simplify preds to not branch here if possible! + } else { + // Rewrite all predecessors of the old block to go to the fallthrough + // instead. + while (!MBB->pred_empty()) { + MachineBasicBlock *Pred = *(MBB->pred_end()-1); + Pred->ReplaceUsesOfBlockWith(MBB, FallThrough); + } + // If MBB was the target of a jump table, update jump tables to go to the + // fallthrough instead. + MF.getJumpTableInfo()->ReplaceMBBInJumpTables(MBB, FallThrough); + MadeChange = true; + } + return MadeChange; + } + + // Check to see if we can simplify the terminator of the block before this + // one. + MachineBasicBlock &PrevBB = *prior(MachineFunction::iterator(MBB)); + + MachineBasicBlock *PriorTBB = 0, *PriorFBB = 0; + SmallVector PriorCond; + bool PriorUnAnalyzable = + TII->AnalyzeBranch(PrevBB, PriorTBB, PriorFBB, PriorCond, true); + if (!PriorUnAnalyzable) { + // If the CFG for the prior block has extra edges, remove them. + MadeChange |= PrevBB.CorrectExtraCFGEdges(PriorTBB, PriorFBB, + !PriorCond.empty()); + + // If the previous branch is conditional and both conditions go to the same + // destination, remove the branch, replacing it with an unconditional one or + // a fall-through. + if (PriorTBB && PriorTBB == PriorFBB) { + TII->RemoveBranch(PrevBB); + PriorCond.clear(); + if (PriorTBB != MBB) + TII->InsertBranch(PrevBB, PriorTBB, 0, PriorCond); + MadeChange = true; + ++NumBranchOpts; + goto ReoptimizeBlock; + } + + // If the previous block unconditionally falls through to this block and + // this block has no other predecessors, move the contents of this block + // into the prior block. This doesn't usually happen when SimplifyCFG + // has been used, but it can happen if tail merging splits a fall-through + // predecessor of a block. + // This has to check PrevBB->succ_size() because EH edges are ignored by + // AnalyzeBranch. + if (PriorCond.empty() && !PriorTBB && MBB->pred_size() == 1 && + PrevBB.succ_size() == 1 && + !MBB->hasAddressTaken()) { + DEBUG(errs() << "\nMerging into block: " << PrevBB + << "From MBB: " << *MBB); + PrevBB.splice(PrevBB.end(), MBB, MBB->begin(), MBB->end()); + PrevBB.removeSuccessor(PrevBB.succ_begin());; + assert(PrevBB.succ_empty()); + PrevBB.transferSuccessors(MBB); + MadeChange = true; + return MadeChange; + } + + // If the previous branch *only* branches to *this* block (conditional or + // not) remove the branch. + if (PriorTBB == MBB && PriorFBB == 0) { + TII->RemoveBranch(PrevBB); + MadeChange = true; + ++NumBranchOpts; + goto ReoptimizeBlock; + } + + // If the prior block branches somewhere else on the condition and here if + // the condition is false, remove the uncond second branch. + if (PriorFBB == MBB) { + TII->RemoveBranch(PrevBB); + TII->InsertBranch(PrevBB, PriorTBB, 0, PriorCond); + MadeChange = true; + ++NumBranchOpts; + goto ReoptimizeBlock; + } + + // If the prior block branches here on true and somewhere else on false, and + // if the branch condition is reversible, reverse the branch to create a + // fall-through. + if (PriorTBB == MBB) { + SmallVector NewPriorCond(PriorCond); + if (!TII->ReverseBranchCondition(NewPriorCond)) { + TII->RemoveBranch(PrevBB); + TII->InsertBranch(PrevBB, PriorFBB, 0, NewPriorCond); + MadeChange = true; + ++NumBranchOpts; + goto ReoptimizeBlock; + } + } + + // If this block has no successors (e.g. it is a return block or ends with + // a call to a no-return function like abort or __cxa_throw) and if the pred + // falls through into this block, and if it would otherwise fall through + // into the block after this, move this block to the end of the function. + // + // We consider it more likely that execution will stay in the function (e.g. + // due to loops) than it is to exit it. This asserts in loops etc, moving + // the assert condition out of the loop body. + if (MBB->succ_empty() && !PriorCond.empty() && PriorFBB == 0 && + MachineFunction::iterator(PriorTBB) == FallThrough && + !MBB->canFallThrough()) { + bool DoTransform = true; + + // We have to be careful that the succs of PredBB aren't both no-successor + // blocks. If neither have successors and if PredBB is the second from + // last block in the function, we'd just keep swapping the two blocks for + // last. Only do the swap if one is clearly better to fall through than + // the other. + if (FallThrough == --MF.end() && + !IsBetterFallthrough(PriorTBB, MBB)) + DoTransform = false; + + // We don't want to do this transformation if we have control flow like: + // br cond BB2 + // BB1: + // .. + // jmp BBX + // BB2: + // .. + // ret + // + // In this case, we could actually be moving the return block *into* a + // loop! + if (DoTransform && !MBB->succ_empty() && + (!PriorTBB->canFallThrough() || PriorTBB->empty())) + DoTransform = false; + + + if (DoTransform) { + // Reverse the branch so we will fall through on the previous true cond. + SmallVector NewPriorCond(PriorCond); + if (!TII->ReverseBranchCondition(NewPriorCond)) { + DEBUG(errs() << "\nMoving MBB: " << *MBB + << "To make fallthrough to: " << *PriorTBB << "\n"); + + TII->RemoveBranch(PrevBB); + TII->InsertBranch(PrevBB, MBB, 0, NewPriorCond); + + // Move this block to the end of the function. + MBB->moveAfter(--MF.end()); + MadeChange = true; + ++NumBranchOpts; + return MadeChange; + } + } + } + } + + // Analyze the branch in the current block. + MachineBasicBlock *CurTBB = 0, *CurFBB = 0; + SmallVector CurCond; + bool CurUnAnalyzable= TII->AnalyzeBranch(*MBB, CurTBB, CurFBB, CurCond, true); + if (!CurUnAnalyzable) { + // If the CFG for the prior block has extra edges, remove them. + MadeChange |= MBB->CorrectExtraCFGEdges(CurTBB, CurFBB, !CurCond.empty()); + + // If this is a two-way branch, and the FBB branches to this block, reverse + // the condition so the single-basic-block loop is faster. Instead of: + // Loop: xxx; jcc Out; jmp Loop + // we want: + // Loop: xxx; jncc Loop; jmp Out + if (CurTBB && CurFBB && CurFBB == MBB && CurTBB != MBB) { + SmallVector NewCond(CurCond); + if (!TII->ReverseBranchCondition(NewCond)) { + TII->RemoveBranch(*MBB); + TII->InsertBranch(*MBB, CurFBB, CurTBB, NewCond); + MadeChange = true; + ++NumBranchOpts; + goto ReoptimizeBlock; + } + } + + // If this branch is the only thing in its block, see if we can forward + // other blocks across it. + if (CurTBB && CurCond.empty() && CurFBB == 0 && + MBB->begin()->getDesc().isBranch() && CurTBB != MBB && + !MBB->hasAddressTaken()) { + // This block may contain just an unconditional branch. Because there can + // be 'non-branch terminators' in the block, try removing the branch and + // then seeing if the block is empty. + TII->RemoveBranch(*MBB); + + // If this block is just an unconditional branch to CurTBB, we can + // usually completely eliminate the block. The only case we cannot + // completely eliminate the block is when the block before this one + // falls through into MBB and we can't understand the prior block's branch + // condition. + if (MBB->empty()) { + bool PredHasNoFallThrough = TII->BlockHasNoFallThrough(PrevBB); + if (PredHasNoFallThrough || !PriorUnAnalyzable || + !PrevBB.isSuccessor(MBB)) { + // If the prior block falls through into us, turn it into an + // explicit branch to us to make updates simpler. + if (!PredHasNoFallThrough && PrevBB.isSuccessor(MBB) && + PriorTBB != MBB && PriorFBB != MBB) { + if (PriorTBB == 0) { + assert(PriorCond.empty() && PriorFBB == 0 && + "Bad branch analysis"); + PriorTBB = MBB; + } else { + assert(PriorFBB == 0 && "Machine CFG out of date!"); + PriorFBB = MBB; + } + TII->RemoveBranch(PrevBB); + TII->InsertBranch(PrevBB, PriorTBB, PriorFBB, PriorCond); + } + + // Iterate through all the predecessors, revectoring each in-turn. + size_t PI = 0; + bool DidChange = false; + bool HasBranchToSelf = false; + while(PI != MBB->pred_size()) { + MachineBasicBlock *PMBB = *(MBB->pred_begin() + PI); + if (PMBB == MBB) { + // If this block has an uncond branch to itself, leave it. + ++PI; + HasBranchToSelf = true; + } else { + DidChange = true; + PMBB->ReplaceUsesOfBlockWith(MBB, CurTBB); + // If this change resulted in PMBB ending in a conditional + // branch where both conditions go to the same destination, + // change this to an unconditional branch (and fix the CFG). + MachineBasicBlock *NewCurTBB = 0, *NewCurFBB = 0; + SmallVector NewCurCond; + bool NewCurUnAnalyzable = TII->AnalyzeBranch(*PMBB, NewCurTBB, + NewCurFBB, NewCurCond, true); + if (!NewCurUnAnalyzable && NewCurTBB && NewCurTBB == NewCurFBB) { + TII->RemoveBranch(*PMBB); + NewCurCond.clear(); + TII->InsertBranch(*PMBB, NewCurTBB, 0, NewCurCond); + MadeChange = true; + ++NumBranchOpts; + PMBB->CorrectExtraCFGEdges(NewCurTBB, 0, false); + } + } + } + + // Change any jumptables to go to the new MBB. + MF.getJumpTableInfo()->ReplaceMBBInJumpTables(MBB, CurTBB); + if (DidChange) { + ++NumBranchOpts; + MadeChange = true; + if (!HasBranchToSelf) return MadeChange; + } + } + } + + // Add the branch back if the block is more than just an uncond branch. + TII->InsertBranch(*MBB, CurTBB, 0, CurCond); + } + } + + // If the prior block doesn't fall through into this block, and if this + // block doesn't fall through into some other block, see if we can find a + // place to move this block where a fall-through will happen. + if (!PrevBB.canFallThrough()) { + + // Now we know that there was no fall-through into this block, check to + // see if it has a fall-through into its successor. + bool CurFallsThru = MBB->canFallThrough(); + + if (!MBB->isLandingPad()) { + // Check all the predecessors of this block. If one of them has no fall + // throughs, move this block right after it. + for (MachineBasicBlock::pred_iterator PI = MBB->pred_begin(), + E = MBB->pred_end(); PI != E; ++PI) { + // Analyze the branch at the end of the pred. + MachineBasicBlock *PredBB = *PI; + MachineFunction::iterator PredFallthrough = PredBB; ++PredFallthrough; + MachineBasicBlock *PredTBB, *PredFBB; + SmallVector PredCond; + if (PredBB != MBB && !PredBB->canFallThrough() && + !TII->AnalyzeBranch(*PredBB, PredTBB, PredFBB, PredCond, true) + && (!CurFallsThru || !CurTBB || !CurFBB) + && (!CurFallsThru || MBB->getNumber() >= PredBB->getNumber())) { + // If the current block doesn't fall through, just move it. + // If the current block can fall through and does not end with a + // conditional branch, we need to append an unconditional jump to + // the (current) next block. To avoid a possible compile-time + // infinite loop, move blocks only backward in this case. + // Also, if there are already 2 branches here, we cannot add a third; + // this means we have the case + // Bcc next + // B elsewhere + // next: + if (CurFallsThru) { + MachineBasicBlock *NextBB = next(MachineFunction::iterator(MBB)); + CurCond.clear(); + TII->InsertBranch(*MBB, NextBB, 0, CurCond); + } + MBB->moveAfter(PredBB); + MadeChange = true; + goto ReoptimizeBlock; + } + } + } + + if (!CurFallsThru) { + // Check all successors to see if we can move this block before it. + for (MachineBasicBlock::succ_iterator SI = MBB->succ_begin(), + E = MBB->succ_end(); SI != E; ++SI) { + // Analyze the branch at the end of the block before the succ. + MachineBasicBlock *SuccBB = *SI; + MachineFunction::iterator SuccPrev = SuccBB; --SuccPrev; + + // If this block doesn't already fall-through to that successor, and if + // the succ doesn't already have a block that can fall through into it, + // and if the successor isn't an EH destination, we can arrange for the + // fallthrough to happen. + if (SuccBB != MBB && &*SuccPrev != MBB && + !SuccPrev->canFallThrough() && !CurUnAnalyzable && + !SuccBB->isLandingPad()) { + MBB->moveBefore(SuccBB); + MadeChange = true; + goto ReoptimizeBlock; + } + } + + // Okay, there is no really great place to put this block. If, however, + // the block before this one would be a fall-through if this block were + // removed, move this block to the end of the function. + MachineBasicBlock *PrevTBB, *PrevFBB; + SmallVector PrevCond; + if (FallThrough != MF.end() && + !TII->AnalyzeBranch(PrevBB, PrevTBB, PrevFBB, PrevCond, true) && + PrevBB.isSuccessor(FallThrough)) { + MBB->moveAfter(--MF.end()); + MadeChange = true; + return MadeChange; + } + } + } + + return MadeChange; +} diff --git a/libclamav/c++/llvm/lib/CodeGen/BranchFolding.h b/libclamav/c++/llvm/lib/CodeGen/BranchFolding.h new file mode 100644 index 000000000..b08739564 --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/BranchFolding.h @@ -0,0 +1,115 @@ +//===-- BranchFolding.h - Fold machine code branch instructions --*- C++ -*===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_BRANCHFOLDING_HPP +#define LLVM_CODEGEN_BRANCHFOLDING_HPP + +#include "llvm/CodeGen/MachineBasicBlock.h" +#include + +namespace llvm { + class MachineFunction; + class MachineModuleInfo; + class RegScavenger; + class TargetInstrInfo; + class TargetRegisterInfo; + template class SmallVectorImpl; + + class BranchFolder { + public: + explicit BranchFolder(bool defaultEnableTailMerge); + + bool OptimizeFunction(MachineFunction &MF, + const TargetInstrInfo *tii, + const TargetRegisterInfo *tri, + MachineModuleInfo *mmi); + private: + class MergePotentialsElt { + unsigned Hash; + MachineBasicBlock *Block; + public: + MergePotentialsElt(unsigned h, MachineBasicBlock *b) + : Hash(h), Block(b) {} + + unsigned getHash() const { return Hash; } + MachineBasicBlock *getBlock() const { return Block; } + + void setBlock(MachineBasicBlock *MBB) { + Block = MBB; + } + + bool operator<(const MergePotentialsElt &) const; + }; + typedef std::vector::iterator MPIterator; + std::vector MergePotentials; + + class SameTailElt { + MPIterator MPIter; + MachineBasicBlock::iterator TailStartPos; + public: + SameTailElt(MPIterator mp, MachineBasicBlock::iterator tsp) + : MPIter(mp), TailStartPos(tsp) {} + + MPIterator getMPIter() const { + return MPIter; + } + MergePotentialsElt &getMergePotentialsElt() const { + return *getMPIter(); + } + MachineBasicBlock::iterator getTailStartPos() const { + return TailStartPos; + } + unsigned getHash() const { + return getMergePotentialsElt().getHash(); + } + MachineBasicBlock *getBlock() const { + return getMergePotentialsElt().getBlock(); + } + bool tailIsWholeBlock() const { + return TailStartPos == getBlock()->begin(); + } + + void setBlock(MachineBasicBlock *MBB) { + getMergePotentialsElt().setBlock(MBB); + } + void setTailStartPos(MachineBasicBlock::iterator Pos) { + TailStartPos = Pos; + } + }; + std::vector SameTails; + + bool EnableTailMerge; + const TargetInstrInfo *TII; + const TargetRegisterInfo *TRI; + MachineModuleInfo *MMI; + RegScavenger *RS; + + bool TailMergeBlocks(MachineFunction &MF); + bool TryTailMergeBlocks(MachineBasicBlock* SuccBB, + MachineBasicBlock* PredBB); + void ReplaceTailWithBranchTo(MachineBasicBlock::iterator OldInst, + MachineBasicBlock *NewDest); + MachineBasicBlock *SplitMBBAt(MachineBasicBlock &CurMBB, + MachineBasicBlock::iterator BBI1); + unsigned ComputeSameTails(unsigned CurHash, unsigned minCommonTailLength, + MachineBasicBlock *SuccBB, + MachineBasicBlock *PredBB); + void RemoveBlocksWithHash(unsigned CurHash, MachineBasicBlock* SuccBB, + MachineBasicBlock* PredBB); + unsigned CreateCommonTailOnlyBlock(MachineBasicBlock *&PredBB, + unsigned maxCommonTailLength); + + bool OptimizeBranches(MachineFunction &MF); + bool OptimizeBlock(MachineBasicBlock *MBB); + void RemoveDeadBlock(MachineBasicBlock *MBB); + bool OptimizeImpDefsBlock(MachineBasicBlock *MBB); + }; +} + +#endif /* LLVM_CODEGEN_BRANCHFOLDING_HPP */ diff --git a/libclamav/c++/llvm/lib/CodeGen/CMakeLists.txt b/libclamav/c++/llvm/lib/CodeGen/CMakeLists.txt new file mode 100644 index 000000000..6f86614c9 --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/CMakeLists.txt @@ -0,0 +1,74 @@ +add_llvm_library(LLVMCodeGen + AggressiveAntiDepBreaker.cpp + BranchFolding.cpp + CodePlacementOpt.cpp + CriticalAntiDepBreaker.cpp + DeadMachineInstructionElim.cpp + DwarfEHPrepare.cpp + ELFCodeEmitter.cpp + ELFWriter.cpp + ExactHazardRecognizer.cpp + GCMetadata.cpp + GCMetadataPrinter.cpp + GCStrategy.cpp + IfConversion.cpp + IntrinsicLowering.cpp + LLVMTargetMachine.cpp + LatencyPriorityQueue.cpp + LiveInterval.cpp + LiveIntervalAnalysis.cpp + LiveStackAnalysis.cpp + LiveVariables.cpp + LowerSubregs.cpp + MachOCodeEmitter.cpp + MachOWriter.cpp + MachineBasicBlock.cpp + MachineDominators.cpp + MachineFunction.cpp + MachineFunctionAnalysis.cpp + MachineFunctionPass.cpp + MachineInstr.cpp + MachineLICM.cpp + MachineLoopInfo.cpp + MachineModuleInfo.cpp + MachineModuleInfoImpls.cpp + MachinePassRegistry.cpp + MachineRegisterInfo.cpp + MachineSink.cpp + MachineVerifier.cpp + ObjectCodeEmitter.cpp + OcamlGC.cpp + PHIElimination.cpp + Passes.cpp + PostRASchedulerList.cpp + PreAllocSplitting.cpp + ProcessImplicitDefs.cpp + PrologEpilogInserter.cpp + PseudoSourceValue.cpp + RegAllocLinearScan.cpp + RegAllocLocal.cpp + RegAllocPBQP.cpp + RegisterCoalescer.cpp + RegisterScavenging.cpp + ScheduleDAG.cpp + ScheduleDAGEmit.cpp + ScheduleDAGInstrs.cpp + ScheduleDAGPrinter.cpp + ShadowStackGC.cpp + ShrinkWrapping.cpp + SimpleRegisterCoalescing.cpp + SjLjEHPrepare.cpp + SlotIndexes.cpp + Spiller.cpp + StackProtector.cpp + StackSlotColoring.cpp + StrongPHIElimination.cpp + TailDuplication.cpp + TargetInstrInfoImpl.cpp + TwoAddressInstructionPass.cpp + UnreachableBlockElim.cpp + VirtRegMap.cpp + VirtRegRewriter.cpp + ) + +target_link_libraries (LLVMCodeGen LLVMCore LLVMScalarOpts) diff --git a/libclamav/c++/llvm/lib/CodeGen/CodePlacementOpt.cpp b/libclamav/c++/llvm/lib/CodeGen/CodePlacementOpt.cpp new file mode 100644 index 000000000..e9844d84c --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/CodePlacementOpt.cpp @@ -0,0 +1,420 @@ +//===-- CodePlacementOpt.cpp - Code Placement pass. -----------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the pass that optimize code placement and align loop +// headers to target specific alignment boundary. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "code-placement" +#include "llvm/CodeGen/MachineLoopInfo.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetLowering.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/Debug.h" +#include "llvm/ADT/Statistic.h" +using namespace llvm; + +STATISTIC(NumLoopsAligned, "Number of loops aligned"); +STATISTIC(NumIntraElim, "Number of intra loop branches eliminated"); +STATISTIC(NumIntraMoved, "Number of intra loop branches moved"); + +namespace { + class CodePlacementOpt : public MachineFunctionPass { + const MachineLoopInfo *MLI; + const TargetInstrInfo *TII; + const TargetLowering *TLI; + + public: + static char ID; + CodePlacementOpt() : MachineFunctionPass(&ID) {} + + virtual bool runOnMachineFunction(MachineFunction &MF); + virtual const char *getPassName() const { + return "Code Placement Optimizater"; + } + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.addRequired(); + AU.addPreservedID(MachineDominatorsID); + MachineFunctionPass::getAnalysisUsage(AU); + } + + private: + bool HasFallthrough(MachineBasicBlock *MBB); + bool HasAnalyzableTerminator(MachineBasicBlock *MBB); + void Splice(MachineFunction &MF, + MachineFunction::iterator InsertPt, + MachineFunction::iterator Begin, + MachineFunction::iterator End); + bool EliminateUnconditionalJumpsToTop(MachineFunction &MF, + MachineLoop *L); + bool MoveDiscontiguousLoopBlocks(MachineFunction &MF, + MachineLoop *L); + bool OptimizeIntraLoopEdgesInLoopNest(MachineFunction &MF, MachineLoop *L); + bool OptimizeIntraLoopEdges(MachineFunction &MF); + bool AlignLoops(MachineFunction &MF); + bool AlignLoop(MachineFunction &MF, MachineLoop *L, unsigned Align); + }; + + char CodePlacementOpt::ID = 0; +} // end anonymous namespace + +FunctionPass *llvm::createCodePlacementOptPass() { + return new CodePlacementOpt(); +} + +/// HasFallthrough - Test whether the given branch has a fallthrough, either as +/// a plain fallthrough or as a fallthrough case of a conditional branch. +/// +bool CodePlacementOpt::HasFallthrough(MachineBasicBlock *MBB) { + MachineBasicBlock *TBB = 0, *FBB = 0; + SmallVector Cond; + if (TII->AnalyzeBranch(*MBB, TBB, FBB, Cond)) + return false; + // This conditional branch has no fallthrough. + if (FBB) + return false; + // An unconditional branch has no fallthrough. + if (Cond.empty() && TBB) + return false; + // It has a fallthrough. + return true; +} + +/// HasAnalyzableTerminator - Test whether AnalyzeBranch will succeed on MBB. +/// This is called before major changes are begun to test whether it will be +/// possible to complete the changes. +/// +/// Target-specific code is hereby encouraged to make AnalyzeBranch succeed +/// whenever possible. +/// +bool CodePlacementOpt::HasAnalyzableTerminator(MachineBasicBlock *MBB) { + // Conservatively ignore EH landing pads. + if (MBB->isLandingPad()) return false; + + // Ignore blocks which look like they might have EH-related control flow. + // At the time of this writing, there are blocks which AnalyzeBranch + // thinks end in single uncoditional branches, yet which have two CFG + // successors. Code in this file is not prepared to reason about such things. + if (!MBB->empty() && MBB->back().getOpcode() == TargetInstrInfo::EH_LABEL) + return false; + + // Aggressively handle return blocks and similar constructs. + if (MBB->succ_empty()) return true; + + // Ask the target's AnalyzeBranch if it can handle this block. + MachineBasicBlock *TBB = 0, *FBB = 0; + SmallVector Cond; + // Make the the terminator is understood. + if (TII->AnalyzeBranch(*MBB, TBB, FBB, Cond)) + return false; + // Make sure we have the option of reversing the condition. + if (!Cond.empty() && TII->ReverseBranchCondition(Cond)) + return false; + return true; +} + +/// Splice - Move the sequence of instructions [Begin,End) to just before +/// InsertPt. Update branch instructions as needed to account for broken +/// fallthrough edges and to take advantage of newly exposed fallthrough +/// opportunities. +/// +void CodePlacementOpt::Splice(MachineFunction &MF, + MachineFunction::iterator InsertPt, + MachineFunction::iterator Begin, + MachineFunction::iterator End) { + assert(Begin != MF.begin() && End != MF.begin() && InsertPt != MF.begin() && + "Splice can't change the entry block!"); + MachineFunction::iterator OldBeginPrior = prior(Begin); + MachineFunction::iterator OldEndPrior = prior(End); + + MF.splice(InsertPt, Begin, End); + + prior(Begin)->updateTerminator(); + OldBeginPrior->updateTerminator(); + OldEndPrior->updateTerminator(); +} + +/// EliminateUnconditionalJumpsToTop - Move blocks which unconditionally jump +/// to the loop top to the top of the loop so that they have a fall through. +/// This can introduce a branch on entry to the loop, but it can eliminate a +/// branch within the loop. See the @simple case in +/// test/CodeGen/X86/loop_blocks.ll for an example of this. +bool CodePlacementOpt::EliminateUnconditionalJumpsToTop(MachineFunction &MF, + MachineLoop *L) { + bool Changed = false; + MachineBasicBlock *TopMBB = L->getTopBlock(); + + bool BotHasFallthrough = HasFallthrough(L->getBottomBlock()); + + if (TopMBB == MF.begin() || + HasAnalyzableTerminator(prior(MachineFunction::iterator(TopMBB)))) { + new_top: + for (MachineBasicBlock::pred_iterator PI = TopMBB->pred_begin(), + PE = TopMBB->pred_end(); PI != PE; ++PI) { + MachineBasicBlock *Pred = *PI; + if (Pred == TopMBB) continue; + if (HasFallthrough(Pred)) continue; + if (!L->contains(Pred)) continue; + + // Verify that we can analyze all the loop entry edges before beginning + // any changes which will require us to be able to analyze them. + if (Pred == MF.begin()) + continue; + if (!HasAnalyzableTerminator(Pred)) + continue; + if (!HasAnalyzableTerminator(prior(MachineFunction::iterator(Pred)))) + continue; + + // Move the block. + Changed = true; + + // Move it and all the blocks that can reach it via fallthrough edges + // exclusively, to keep existing fallthrough edges intact. + MachineFunction::iterator Begin = Pred; + MachineFunction::iterator End = next(Begin); + while (Begin != MF.begin()) { + MachineFunction::iterator Prior = prior(Begin); + if (Prior == MF.begin()) + break; + // Stop when a non-fallthrough edge is found. + if (!HasFallthrough(Prior)) + break; + // Stop if a block which could fall-through out of the loop is found. + if (Prior->isSuccessor(End)) + break; + // If we've reached the top, stop scanning. + if (Prior == MachineFunction::iterator(TopMBB)) { + // We know top currently has a fall through (because we just checked + // it) which would be lost if we do the transformation, so it isn't + // worthwhile to do the transformation unless it would expose a new + // fallthrough edge. + if (!Prior->isSuccessor(End)) + goto next_pred; + // Otherwise we can stop scanning and procede to move the blocks. + break; + } + // If we hit a switch or something complicated, don't move anything + // for this predecessor. + if (!HasAnalyzableTerminator(prior(MachineFunction::iterator(Prior)))) + break; + // Ok, the block prior to Begin will be moved along with the rest. + // Extend the range to include it. + Begin = Prior; + ++NumIntraMoved; + } + + // Move the blocks. + Splice(MF, TopMBB, Begin, End); + + // Update TopMBB. + TopMBB = L->getTopBlock(); + + // We have a new loop top. Iterate on it. We shouldn't have to do this + // too many times if BranchFolding has done a reasonable job. + goto new_top; + next_pred:; + } + } + + // If the loop previously didn't exit with a fall-through and it now does, + // we eliminated a branch. + if (Changed && + !BotHasFallthrough && + HasFallthrough(L->getBottomBlock())) { + ++NumIntraElim; + BotHasFallthrough = true; + } + + return Changed; +} + +/// MoveDiscontiguousLoopBlocks - Move any loop blocks that are not in the +/// portion of the loop contiguous with the header. This usually makes the loop +/// contiguous, provided that AnalyzeBranch can handle all the relevant +/// branching. See the @cfg_islands case in test/CodeGen/X86/loop_blocks.ll +/// for an example of this. +bool CodePlacementOpt::MoveDiscontiguousLoopBlocks(MachineFunction &MF, + MachineLoop *L) { + bool Changed = false; + MachineBasicBlock *TopMBB = L->getTopBlock(); + MachineBasicBlock *BotMBB = L->getBottomBlock(); + + // Determine a position to move orphaned loop blocks to. If TopMBB is not + // entered via fallthrough and BotMBB is exited via fallthrough, prepend them + // to the top of the loop to avoid loosing that fallthrough. Otherwise append + // them to the bottom, even if it previously had a fallthrough, on the theory + // that it's worth an extra branch to keep the loop contiguous. + MachineFunction::iterator InsertPt = next(MachineFunction::iterator(BotMBB)); + bool InsertAtTop = false; + if (TopMBB != MF.begin() && + !HasFallthrough(prior(MachineFunction::iterator(TopMBB))) && + HasFallthrough(BotMBB)) { + InsertPt = TopMBB; + InsertAtTop = true; + } + + // Keep a record of which blocks are in the portion of the loop contiguous + // with the loop header. + SmallPtrSet ContiguousBlocks; + for (MachineFunction::iterator I = TopMBB, + E = next(MachineFunction::iterator(BotMBB)); I != E; ++I) + ContiguousBlocks.insert(I); + + // Find non-contigous blocks and fix them. + if (InsertPt != MF.begin() && HasAnalyzableTerminator(prior(InsertPt))) + for (MachineLoop::block_iterator BI = L->block_begin(), BE = L->block_end(); + BI != BE; ++BI) { + MachineBasicBlock *BB = *BI; + + // Verify that we can analyze all the loop entry edges before beginning + // any changes which will require us to be able to analyze them. + if (!HasAnalyzableTerminator(BB)) + continue; + if (!HasAnalyzableTerminator(prior(MachineFunction::iterator(BB)))) + continue; + + // If the layout predecessor is part of the loop, this block will be + // processed along with it. This keeps them in their relative order. + if (BB != MF.begin() && + L->contains(prior(MachineFunction::iterator(BB)))) + continue; + + // Check to see if this block is already contiguous with the main + // portion of the loop. + if (!ContiguousBlocks.insert(BB)) + continue; + + // Move the block. + Changed = true; + + // Process this block and all loop blocks contiguous with it, to keep + // them in their relative order. + MachineFunction::iterator Begin = BB; + MachineFunction::iterator End = next(MachineFunction::iterator(BB)); + for (; End != MF.end(); ++End) { + if (!L->contains(End)) break; + if (!HasAnalyzableTerminator(End)) break; + ContiguousBlocks.insert(End); + ++NumIntraMoved; + } + + // If we're inserting at the bottom of the loop, and the code we're + // moving originally had fall-through successors, bring the sucessors + // up with the loop blocks to preserve the fall-through edges. + if (!InsertAtTop) + for (; End != MF.end(); ++End) { + if (L->contains(End)) break; + if (!HasAnalyzableTerminator(End)) break; + if (!HasFallthrough(prior(End))) break; + } + + // Move the blocks. This may invalidate TopMBB and/or BotMBB, but + // we don't need them anymore at this point. + Splice(MF, InsertPt, Begin, End); + } + + return Changed; +} + +/// OptimizeIntraLoopEdgesInLoopNest - Reposition loop blocks to minimize +/// intra-loop branching and to form contiguous loops. +/// +/// This code takes the approach of making minor changes to the existing +/// layout to fix specific loop-oriented problems. Also, it depends on +/// AnalyzeBranch, which can't understand complex control instructions. +/// +bool CodePlacementOpt::OptimizeIntraLoopEdgesInLoopNest(MachineFunction &MF, + MachineLoop *L) { + bool Changed = false; + + // Do optimization for nested loops. + for (MachineLoop::iterator I = L->begin(), E = L->end(); I != E; ++I) + Changed |= OptimizeIntraLoopEdgesInLoopNest(MF, *I); + + // Do optimization for this loop. + Changed |= EliminateUnconditionalJumpsToTop(MF, L); + Changed |= MoveDiscontiguousLoopBlocks(MF, L); + + return Changed; +} + +/// OptimizeIntraLoopEdges - Reposition loop blocks to minimize +/// intra-loop branching and to form contiguous loops. +/// +bool CodePlacementOpt::OptimizeIntraLoopEdges(MachineFunction &MF) { + bool Changed = false; + + if (!TLI->shouldOptimizeCodePlacement()) + return Changed; + + // Do optimization for each loop in the function. + for (MachineLoopInfo::iterator I = MLI->begin(), E = MLI->end(); + I != E; ++I) + if (!(*I)->getParentLoop()) + Changed |= OptimizeIntraLoopEdgesInLoopNest(MF, *I); + + return Changed; +} + +/// AlignLoops - Align loop headers to target preferred alignments. +/// +bool CodePlacementOpt::AlignLoops(MachineFunction &MF) { + const Function *F = MF.getFunction(); + if (F->hasFnAttr(Attribute::OptimizeForSize)) + return false; + + unsigned Align = TLI->getPrefLoopAlignment(); + if (!Align) + return false; // Don't care about loop alignment. + + bool Changed = false; + + for (MachineLoopInfo::iterator I = MLI->begin(), E = MLI->end(); + I != E; ++I) + Changed |= AlignLoop(MF, *I, Align); + + return Changed; +} + +/// AlignLoop - Align loop headers to target preferred alignments. +/// +bool CodePlacementOpt::AlignLoop(MachineFunction &MF, MachineLoop *L, + unsigned Align) { + bool Changed = false; + + // Do alignment for nested loops. + for (MachineLoop::iterator I = L->begin(), E = L->end(); I != E; ++I) + Changed |= AlignLoop(MF, *I, Align); + + L->getTopBlock()->setAlignment(Align); + Changed = true; + ++NumLoopsAligned; + + return Changed; +} + +bool CodePlacementOpt::runOnMachineFunction(MachineFunction &MF) { + MLI = &getAnalysis(); + if (MLI->empty()) + return false; // No loops. + + TLI = MF.getTarget().getTargetLowering(); + TII = MF.getTarget().getInstrInfo(); + + bool Changed = OptimizeIntraLoopEdges(MF); + + Changed |= AlignLoops(MF); + + return Changed; +} diff --git a/libclamav/c++/llvm/lib/CodeGen/CriticalAntiDepBreaker.cpp b/libclamav/c++/llvm/lib/CodeGen/CriticalAntiDepBreaker.cpp new file mode 100644 index 000000000..1b39fec39 --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/CriticalAntiDepBreaker.cpp @@ -0,0 +1,539 @@ +//===----- CriticalAntiDepBreaker.cpp - Anti-dep breaker -------- ---------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the CriticalAntiDepBreaker class, which +// implements register anti-dependence breaking along a blocks +// critical path during post-RA scheduler. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "post-RA-sched" +#include "CriticalAntiDepBreaker.h" +#include "llvm/CodeGen/MachineBasicBlock.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" + +using namespace llvm; + +CriticalAntiDepBreaker:: +CriticalAntiDepBreaker(MachineFunction& MFi) : + AntiDepBreaker(), MF(MFi), + MRI(MF.getRegInfo()), + TRI(MF.getTarget().getRegisterInfo()), + AllocatableSet(TRI->getAllocatableSet(MF)) +{ +} + +CriticalAntiDepBreaker::~CriticalAntiDepBreaker() { +} + +void CriticalAntiDepBreaker::StartBlock(MachineBasicBlock *BB) { + // Clear out the register class data. + std::fill(Classes, array_endof(Classes), + static_cast(0)); + + // Initialize the indices to indicate that no registers are live. + std::fill(KillIndices, array_endof(KillIndices), ~0u); + std::fill(DefIndices, array_endof(DefIndices), BB->size()); + + // Clear "do not change" set. + KeepRegs.clear(); + + bool IsReturnBlock = (!BB->empty() && BB->back().getDesc().isReturn()); + + // Determine the live-out physregs for this block. + if (IsReturnBlock) { + // In a return block, examine the function live-out regs. + for (MachineRegisterInfo::liveout_iterator I = MRI.liveout_begin(), + E = MRI.liveout_end(); I != E; ++I) { + unsigned Reg = *I; + Classes[Reg] = reinterpret_cast(-1); + KillIndices[Reg] = BB->size(); + DefIndices[Reg] = ~0u; + // Repeat, for all aliases. + for (const unsigned *Alias = TRI->getAliasSet(Reg); *Alias; ++Alias) { + unsigned AliasReg = *Alias; + Classes[AliasReg] = reinterpret_cast(-1); + KillIndices[AliasReg] = BB->size(); + DefIndices[AliasReg] = ~0u; + } + } + } else { + // In a non-return block, examine the live-in regs of all successors. + for (MachineBasicBlock::succ_iterator SI = BB->succ_begin(), + SE = BB->succ_end(); SI != SE; ++SI) + for (MachineBasicBlock::livein_iterator I = (*SI)->livein_begin(), + E = (*SI)->livein_end(); I != E; ++I) { + unsigned Reg = *I; + Classes[Reg] = reinterpret_cast(-1); + KillIndices[Reg] = BB->size(); + DefIndices[Reg] = ~0u; + // Repeat, for all aliases. + for (const unsigned *Alias = TRI->getAliasSet(Reg); *Alias; ++Alias) { + unsigned AliasReg = *Alias; + Classes[AliasReg] = reinterpret_cast(-1); + KillIndices[AliasReg] = BB->size(); + DefIndices[AliasReg] = ~0u; + } + } + } + + // Mark live-out callee-saved registers. In a return block this is + // all callee-saved registers. In non-return this is any + // callee-saved register that is not saved in the prolog. + const MachineFrameInfo *MFI = MF.getFrameInfo(); + BitVector Pristine = MFI->getPristineRegs(BB); + for (const unsigned *I = TRI->getCalleeSavedRegs(); *I; ++I) { + unsigned Reg = *I; + if (!IsReturnBlock && !Pristine.test(Reg)) continue; + Classes[Reg] = reinterpret_cast(-1); + KillIndices[Reg] = BB->size(); + DefIndices[Reg] = ~0u; + // Repeat, for all aliases. + for (const unsigned *Alias = TRI->getAliasSet(Reg); *Alias; ++Alias) { + unsigned AliasReg = *Alias; + Classes[AliasReg] = reinterpret_cast(-1); + KillIndices[AliasReg] = BB->size(); + DefIndices[AliasReg] = ~0u; + } + } +} + +void CriticalAntiDepBreaker::FinishBlock() { + RegRefs.clear(); + KeepRegs.clear(); +} + +void CriticalAntiDepBreaker::Observe(MachineInstr *MI, unsigned Count, + unsigned InsertPosIndex) { + assert(Count < InsertPosIndex && "Instruction index out of expected range!"); + + // Any register which was defined within the previous scheduling region + // may have been rescheduled and its lifetime may overlap with registers + // in ways not reflected in our current liveness state. For each such + // register, adjust the liveness state to be conservatively correct. + for (unsigned Reg = 0; Reg != TargetRegisterInfo::FirstVirtualRegister; ++Reg) + if (DefIndices[Reg] < InsertPosIndex && DefIndices[Reg] >= Count) { + assert(KillIndices[Reg] == ~0u && "Clobbered register is live!"); + // Mark this register to be non-renamable. + Classes[Reg] = reinterpret_cast(-1); + // Move the def index to the end of the previous region, to reflect + // that the def could theoretically have been scheduled at the end. + DefIndices[Reg] = InsertPosIndex; + } + + PrescanInstruction(MI); + ScanInstruction(MI, Count); +} + +/// CriticalPathStep - Return the next SUnit after SU on the bottom-up +/// critical path. +static SDep *CriticalPathStep(SUnit *SU) { + SDep *Next = 0; + unsigned NextDepth = 0; + // Find the predecessor edge with the greatest depth. + for (SUnit::pred_iterator P = SU->Preds.begin(), PE = SU->Preds.end(); + P != PE; ++P) { + SUnit *PredSU = P->getSUnit(); + unsigned PredLatency = P->getLatency(); + unsigned PredTotalLatency = PredSU->getDepth() + PredLatency; + // In the case of a latency tie, prefer an anti-dependency edge over + // other types of edges. + if (NextDepth < PredTotalLatency || + (NextDepth == PredTotalLatency && P->getKind() == SDep::Anti)) { + NextDepth = PredTotalLatency; + Next = &*P; + } + } + return Next; +} + +void CriticalAntiDepBreaker::PrescanInstruction(MachineInstr *MI) { + // Scan the register operands for this instruction and update + // Classes and RegRefs. + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + MachineOperand &MO = MI->getOperand(i); + if (!MO.isReg()) continue; + unsigned Reg = MO.getReg(); + if (Reg == 0) continue; + const TargetRegisterClass *NewRC = 0; + + if (i < MI->getDesc().getNumOperands()) + NewRC = MI->getDesc().OpInfo[i].getRegClass(TRI); + + // For now, only allow the register to be changed if its register + // class is consistent across all uses. + if (!Classes[Reg] && NewRC) + Classes[Reg] = NewRC; + else if (!NewRC || Classes[Reg] != NewRC) + Classes[Reg] = reinterpret_cast(-1); + + // Now check for aliases. + for (const unsigned *Alias = TRI->getAliasSet(Reg); *Alias; ++Alias) { + // If an alias of the reg is used during the live range, give up. + // Note that this allows us to skip checking if AntiDepReg + // overlaps with any of the aliases, among other things. + unsigned AliasReg = *Alias; + if (Classes[AliasReg]) { + Classes[AliasReg] = reinterpret_cast(-1); + Classes[Reg] = reinterpret_cast(-1); + } + } + + // If we're still willing to consider this register, note the reference. + if (Classes[Reg] != reinterpret_cast(-1)) + RegRefs.insert(std::make_pair(Reg, &MO)); + + // It's not safe to change register allocation for source operands of + // that have special allocation requirements. + if (MO.isUse() && MI->getDesc().hasExtraSrcRegAllocReq()) { + if (KeepRegs.insert(Reg)) { + for (const unsigned *Subreg = TRI->getSubRegisters(Reg); + *Subreg; ++Subreg) + KeepRegs.insert(*Subreg); + } + } + } +} + +void CriticalAntiDepBreaker::ScanInstruction(MachineInstr *MI, + unsigned Count) { + // Update liveness. + // Proceding upwards, registers that are defed but not used in this + // instruction are now dead. + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + MachineOperand &MO = MI->getOperand(i); + if (!MO.isReg()) continue; + unsigned Reg = MO.getReg(); + if (Reg == 0) continue; + if (!MO.isDef()) continue; + // Ignore two-addr defs. + if (MI->isRegTiedToUseOperand(i)) continue; + + DefIndices[Reg] = Count; + KillIndices[Reg] = ~0u; + assert(((KillIndices[Reg] == ~0u) != + (DefIndices[Reg] == ~0u)) && + "Kill and Def maps aren't consistent for Reg!"); + KeepRegs.erase(Reg); + Classes[Reg] = 0; + RegRefs.erase(Reg); + // Repeat, for all subregs. + for (const unsigned *Subreg = TRI->getSubRegisters(Reg); + *Subreg; ++Subreg) { + unsigned SubregReg = *Subreg; + DefIndices[SubregReg] = Count; + KillIndices[SubregReg] = ~0u; + KeepRegs.erase(SubregReg); + Classes[SubregReg] = 0; + RegRefs.erase(SubregReg); + } + // Conservatively mark super-registers as unusable. + for (const unsigned *Super = TRI->getSuperRegisters(Reg); + *Super; ++Super) { + unsigned SuperReg = *Super; + Classes[SuperReg] = reinterpret_cast(-1); + } + } + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + MachineOperand &MO = MI->getOperand(i); + if (!MO.isReg()) continue; + unsigned Reg = MO.getReg(); + if (Reg == 0) continue; + if (!MO.isUse()) continue; + + const TargetRegisterClass *NewRC = 0; + if (i < MI->getDesc().getNumOperands()) + NewRC = MI->getDesc().OpInfo[i].getRegClass(TRI); + + // For now, only allow the register to be changed if its register + // class is consistent across all uses. + if (!Classes[Reg] && NewRC) + Classes[Reg] = NewRC; + else if (!NewRC || Classes[Reg] != NewRC) + Classes[Reg] = reinterpret_cast(-1); + + RegRefs.insert(std::make_pair(Reg, &MO)); + + // It wasn't previously live but now it is, this is a kill. + if (KillIndices[Reg] == ~0u) { + KillIndices[Reg] = Count; + DefIndices[Reg] = ~0u; + assert(((KillIndices[Reg] == ~0u) != + (DefIndices[Reg] == ~0u)) && + "Kill and Def maps aren't consistent for Reg!"); + } + // Repeat, for all aliases. + for (const unsigned *Alias = TRI->getAliasSet(Reg); *Alias; ++Alias) { + unsigned AliasReg = *Alias; + if (KillIndices[AliasReg] == ~0u) { + KillIndices[AliasReg] = Count; + DefIndices[AliasReg] = ~0u; + } + } + } +} + +unsigned +CriticalAntiDepBreaker::findSuitableFreeRegister(unsigned AntiDepReg, + unsigned LastNewReg, + const TargetRegisterClass *RC) { + for (TargetRegisterClass::iterator R = RC->allocation_order_begin(MF), + RE = RC->allocation_order_end(MF); R != RE; ++R) { + unsigned NewReg = *R; + // Don't replace a register with itself. + if (NewReg == AntiDepReg) continue; + // Don't replace a register with one that was recently used to repair + // an anti-dependence with this AntiDepReg, because that would + // re-introduce that anti-dependence. + if (NewReg == LastNewReg) continue; + // If NewReg is dead and NewReg's most recent def is not before + // AntiDepReg's kill, it's safe to replace AntiDepReg with NewReg. + assert(((KillIndices[AntiDepReg] == ~0u) != (DefIndices[AntiDepReg] == ~0u)) && + "Kill and Def maps aren't consistent for AntiDepReg!"); + assert(((KillIndices[NewReg] == ~0u) != (DefIndices[NewReg] == ~0u)) && + "Kill and Def maps aren't consistent for NewReg!"); + if (KillIndices[NewReg] != ~0u || + Classes[NewReg] == reinterpret_cast(-1) || + KillIndices[AntiDepReg] > DefIndices[NewReg]) + continue; + return NewReg; + } + + // No registers are free and available! + return 0; +} + +unsigned CriticalAntiDepBreaker:: +BreakAntiDependencies(std::vector& SUnits, + MachineBasicBlock::iterator& Begin, + MachineBasicBlock::iterator& End, + unsigned InsertPosIndex) { + // The code below assumes that there is at least one instruction, + // so just duck out immediately if the block is empty. + if (SUnits.empty()) return 0; + + // Find the node at the bottom of the critical path. + SUnit *Max = 0; + for (unsigned i = 0, e = SUnits.size(); i != e; ++i) { + SUnit *SU = &SUnits[i]; + if (!Max || SU->getDepth() + SU->Latency > Max->getDepth() + Max->Latency) + Max = SU; + } + +#ifndef NDEBUG + { + DEBUG(errs() << "Critical path has total latency " + << (Max->getDepth() + Max->Latency) << "\n"); + DEBUG(errs() << "Available regs:"); + for (unsigned Reg = 0; Reg < TRI->getNumRegs(); ++Reg) { + if (KillIndices[Reg] == ~0u) + DEBUG(errs() << " " << TRI->getName(Reg)); + } + DEBUG(errs() << '\n'); + } +#endif + + // Track progress along the critical path through the SUnit graph as we walk + // the instructions. + SUnit *CriticalPathSU = Max; + MachineInstr *CriticalPathMI = CriticalPathSU->getInstr(); + + // Consider this pattern: + // A = ... + // ... = A + // A = ... + // ... = A + // A = ... + // ... = A + // A = ... + // ... = A + // There are three anti-dependencies here, and without special care, + // we'd break all of them using the same register: + // A = ... + // ... = A + // B = ... + // ... = B + // B = ... + // ... = B + // B = ... + // ... = B + // because at each anti-dependence, B is the first register that + // isn't A which is free. This re-introduces anti-dependencies + // at all but one of the original anti-dependencies that we were + // trying to break. To avoid this, keep track of the most recent + // register that each register was replaced with, avoid + // using it to repair an anti-dependence on the same register. + // This lets us produce this: + // A = ... + // ... = A + // B = ... + // ... = B + // C = ... + // ... = C + // B = ... + // ... = B + // This still has an anti-dependence on B, but at least it isn't on the + // original critical path. + // + // TODO: If we tracked more than one register here, we could potentially + // fix that remaining critical edge too. This is a little more involved, + // because unlike the most recent register, less recent registers should + // still be considered, though only if no other registers are available. + unsigned LastNewReg[TargetRegisterInfo::FirstVirtualRegister] = {}; + + // Attempt to break anti-dependence edges on the critical path. Walk the + // instructions from the bottom up, tracking information about liveness + // as we go to help determine which registers are available. + unsigned Broken = 0; + unsigned Count = InsertPosIndex - 1; + for (MachineBasicBlock::iterator I = End, E = Begin; + I != E; --Count) { + MachineInstr *MI = --I; + + // Check if this instruction has a dependence on the critical path that + // is an anti-dependence that we may be able to break. If it is, set + // AntiDepReg to the non-zero register associated with the anti-dependence. + // + // We limit our attention to the critical path as a heuristic to avoid + // breaking anti-dependence edges that aren't going to significantly + // impact the overall schedule. There are a limited number of registers + // and we want to save them for the important edges. + // + // TODO: Instructions with multiple defs could have multiple + // anti-dependencies. The current code here only knows how to break one + // edge per instruction. Note that we'd have to be able to break all of + // the anti-dependencies in an instruction in order to be effective. + unsigned AntiDepReg = 0; + if (MI == CriticalPathMI) { + if (SDep *Edge = CriticalPathStep(CriticalPathSU)) { + SUnit *NextSU = Edge->getSUnit(); + + // Only consider anti-dependence edges. + if (Edge->getKind() == SDep::Anti) { + AntiDepReg = Edge->getReg(); + assert(AntiDepReg != 0 && "Anti-dependence on reg0?"); + if (!AllocatableSet.test(AntiDepReg)) + // Don't break anti-dependencies on non-allocatable registers. + AntiDepReg = 0; + else if (KeepRegs.count(AntiDepReg)) + // Don't break anti-dependencies if an use down below requires + // this exact register. + AntiDepReg = 0; + else { + // If the SUnit has other dependencies on the SUnit that it + // anti-depends on, don't bother breaking the anti-dependency + // since those edges would prevent such units from being + // scheduled past each other regardless. + // + // Also, if there are dependencies on other SUnits with the + // same register as the anti-dependency, don't attempt to + // break it. + for (SUnit::pred_iterator P = CriticalPathSU->Preds.begin(), + PE = CriticalPathSU->Preds.end(); P != PE; ++P) + if (P->getSUnit() == NextSU ? + (P->getKind() != SDep::Anti || P->getReg() != AntiDepReg) : + (P->getKind() == SDep::Data && P->getReg() == AntiDepReg)) { + AntiDepReg = 0; + break; + } + } + } + CriticalPathSU = NextSU; + CriticalPathMI = CriticalPathSU->getInstr(); + } else { + // We've reached the end of the critical path. + CriticalPathSU = 0; + CriticalPathMI = 0; + } + } + + PrescanInstruction(MI); + + if (MI->getDesc().hasExtraDefRegAllocReq()) + // If this instruction's defs have special allocation requirement, don't + // break this anti-dependency. + AntiDepReg = 0; + else if (AntiDepReg) { + // If this instruction has a use of AntiDepReg, breaking it + // is invalid. + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + MachineOperand &MO = MI->getOperand(i); + if (!MO.isReg()) continue; + unsigned Reg = MO.getReg(); + if (Reg == 0) continue; + if (MO.isUse() && AntiDepReg == Reg) { + AntiDepReg = 0; + break; + } + } + } + + // Determine AntiDepReg's register class, if it is live and is + // consistently used within a single class. + const TargetRegisterClass *RC = AntiDepReg != 0 ? Classes[AntiDepReg] : 0; + assert((AntiDepReg == 0 || RC != NULL) && + "Register should be live if it's causing an anti-dependence!"); + if (RC == reinterpret_cast(-1)) + AntiDepReg = 0; + + // Look for a suitable register to use to break the anti-depenence. + // + // TODO: Instead of picking the first free register, consider which might + // be the best. + if (AntiDepReg != 0) { + if (unsigned NewReg = findSuitableFreeRegister(AntiDepReg, + LastNewReg[AntiDepReg], + RC)) { + DEBUG(errs() << "Breaking anti-dependence edge on " + << TRI->getName(AntiDepReg) + << " with " << RegRefs.count(AntiDepReg) << " references" + << " using " << TRI->getName(NewReg) << "!\n"); + + // Update the references to the old register to refer to the new + // register. + std::pair::iterator, + std::multimap::iterator> + Range = RegRefs.equal_range(AntiDepReg); + for (std::multimap::iterator + Q = Range.first, QE = Range.second; Q != QE; ++Q) + Q->second->setReg(NewReg); + + // We just went back in time and modified history; the + // liveness information for the anti-depenence reg is now + // inconsistent. Set the state as if it were dead. + Classes[NewReg] = Classes[AntiDepReg]; + DefIndices[NewReg] = DefIndices[AntiDepReg]; + KillIndices[NewReg] = KillIndices[AntiDepReg]; + assert(((KillIndices[NewReg] == ~0u) != + (DefIndices[NewReg] == ~0u)) && + "Kill and Def maps aren't consistent for NewReg!"); + + Classes[AntiDepReg] = 0; + DefIndices[AntiDepReg] = KillIndices[AntiDepReg]; + KillIndices[AntiDepReg] = ~0u; + assert(((KillIndices[AntiDepReg] == ~0u) != + (DefIndices[AntiDepReg] == ~0u)) && + "Kill and Def maps aren't consistent for AntiDepReg!"); + + RegRefs.erase(AntiDepReg); + LastNewReg[AntiDepReg] = NewReg; + ++Broken; + } + } + + ScanInstruction(MI, Count); + } + + return Broken; +} diff --git a/libclamav/c++/llvm/lib/CodeGen/CriticalAntiDepBreaker.h b/libclamav/c++/llvm/lib/CodeGen/CriticalAntiDepBreaker.h new file mode 100644 index 000000000..496888d45 --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/CriticalAntiDepBreaker.h @@ -0,0 +1,96 @@ +//=- llvm/CodeGen/CriticalAntiDepBreaker.h - Anti-Dep Support -*- 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 the CriticalAntiDepBreaker class, which +// implements register anti-dependence breaking along a blocks +// critical path during post-RA scheduler. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_CRITICALANTIDEPBREAKER_H +#define LLVM_CODEGEN_CRITICALANTIDEPBREAKER_H + +#include "AntiDepBreaker.h" +#include "llvm/CodeGen/MachineBasicBlock.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/ScheduleDAG.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/ADT/BitVector.h" +#include "llvm/ADT/SmallSet.h" +#include + +namespace llvm { + class CriticalAntiDepBreaker : public AntiDepBreaker { + MachineFunction& MF; + MachineRegisterInfo &MRI; + const TargetRegisterInfo *TRI; + + /// AllocatableSet - The set of allocatable registers. + /// We'll be ignoring anti-dependencies on non-allocatable registers, + /// because they may not be safe to break. + const BitVector AllocatableSet; + + /// Classes - For live regs that are only used in one register class in a + /// live range, the register class. If the register is not live, the + /// corresponding value is null. If the register is live but used in + /// multiple register classes, the corresponding value is -1 casted to a + /// pointer. + const TargetRegisterClass * + Classes[TargetRegisterInfo::FirstVirtualRegister]; + + /// RegRegs - Map registers to all their references within a live range. + std::multimap RegRefs; + + /// KillIndices - The index of the most recent kill (proceding bottom-up), + /// or ~0u if the register is not live. + unsigned KillIndices[TargetRegisterInfo::FirstVirtualRegister]; + + /// DefIndices - The index of the most recent complete def (proceding bottom + /// up), or ~0u if the register is live. + unsigned DefIndices[TargetRegisterInfo::FirstVirtualRegister]; + + /// KeepRegs - A set of registers which are live and cannot be changed to + /// break anti-dependencies. + SmallSet KeepRegs; + + public: + CriticalAntiDepBreaker(MachineFunction& MFi); + ~CriticalAntiDepBreaker(); + + /// Start - Initialize anti-dep breaking for a new basic block. + void StartBlock(MachineBasicBlock *BB); + + /// BreakAntiDependencies - Identifiy anti-dependencies along the critical path + /// of the ScheduleDAG and break them by renaming registers. + /// + unsigned BreakAntiDependencies(std::vector& SUnits, + MachineBasicBlock::iterator& Begin, + MachineBasicBlock::iterator& End, + unsigned InsertPosIndex); + + /// Observe - Update liveness information to account for the current + /// instruction, which will not be scheduled. + /// + void Observe(MachineInstr *MI, unsigned Count, unsigned InsertPosIndex); + + /// Finish - Finish anti-dep breaking for a basic block. + void FinishBlock(); + + private: + void PrescanInstruction(MachineInstr *MI); + void ScanInstruction(MachineInstr *MI, unsigned Count); + unsigned findSuitableFreeRegister(unsigned AntiDepReg, + unsigned LastNewReg, + const TargetRegisterClass *); + }; +} + +#endif diff --git a/libclamav/c++/llvm/lib/CodeGen/DeadMachineInstructionElim.cpp b/libclamav/c++/llvm/lib/CodeGen/DeadMachineInstructionElim.cpp new file mode 100644 index 000000000..07a5d38db --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/DeadMachineInstructionElim.cpp @@ -0,0 +1,160 @@ +//===- DeadMachineInstructionElim.cpp - Remove dead machine instructions --===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This is an extremely simple MachineInstr-level dead-code-elimination pass. +// +//===----------------------------------------------------------------------===// + +#include "llvm/CodeGen/Passes.h" +#include "llvm/Pass.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetMachine.h" +using namespace llvm; + +namespace { + class DeadMachineInstructionElim : public MachineFunctionPass { + virtual bool runOnMachineFunction(MachineFunction &MF); + + const TargetRegisterInfo *TRI; + const MachineRegisterInfo *MRI; + const TargetInstrInfo *TII; + BitVector LivePhysRegs; + + public: + static char ID; // Pass identification, replacement for typeid + DeadMachineInstructionElim() : MachineFunctionPass(&ID) {} + + private: + bool isDead(const MachineInstr *MI) const; + }; +} +char DeadMachineInstructionElim::ID = 0; + +static RegisterPass +Y("dead-mi-elimination", + "Remove dead machine instructions"); + +FunctionPass *llvm::createDeadMachineInstructionElimPass() { + return new DeadMachineInstructionElim(); +} + +bool DeadMachineInstructionElim::isDead(const MachineInstr *MI) const { + // Don't delete instructions with side effects. + bool SawStore = false; + if (!MI->isSafeToMove(TII, SawStore, 0)) + return false; + + // Examine each operand. + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + const MachineOperand &MO = MI->getOperand(i); + if (MO.isReg() && MO.isDef()) { + unsigned Reg = MO.getReg(); + if (TargetRegisterInfo::isPhysicalRegister(Reg) ? + LivePhysRegs[Reg] : !MRI->use_empty(Reg)) { + // This def has a use. Don't delete the instruction! + return false; + } + } + } + + // If there are no defs with uses, the instruction is dead. + return true; +} + +bool DeadMachineInstructionElim::runOnMachineFunction(MachineFunction &MF) { + bool AnyChanges = false; + MRI = &MF.getRegInfo(); + TRI = MF.getTarget().getRegisterInfo(); + TII = MF.getTarget().getInstrInfo(); + + // Compute a bitvector to represent all non-allocatable physregs. + BitVector NonAllocatableRegs = TRI->getAllocatableSet(MF); + NonAllocatableRegs.flip(); + + // Loop over all instructions in all blocks, from bottom to top, so that it's + // more likely that chains of dependent but ultimately dead instructions will + // be cleaned up. + for (MachineFunction::reverse_iterator I = MF.rbegin(), E = MF.rend(); + I != E; ++I) { + MachineBasicBlock *MBB = &*I; + + // Start out assuming that all non-allocatable registers are live + // out of this block. + LivePhysRegs = NonAllocatableRegs; + + // Also add any explicit live-out physregs for this block. + if (!MBB->empty() && MBB->back().getDesc().isReturn()) + for (MachineRegisterInfo::liveout_iterator LOI = MRI->liveout_begin(), + LOE = MRI->liveout_end(); LOI != LOE; ++LOI) { + unsigned Reg = *LOI; + if (TargetRegisterInfo::isPhysicalRegister(Reg)) + LivePhysRegs.set(Reg); + } + + // Now scan the instructions and delete dead ones, tracking physreg + // liveness as we go. + for (MachineBasicBlock::reverse_iterator MII = MBB->rbegin(), + MIE = MBB->rend(); MII != MIE; ) { + MachineInstr *MI = &*MII; + + // If the instruction is dead, delete it! + if (isDead(MI)) { + DEBUG(errs() << "DeadMachineInstructionElim: DELETING: " << *MI); + AnyChanges = true; + MI->eraseFromParent(); + MIE = MBB->rend(); + // MII is now pointing to the next instruction to process, + // so don't increment it. + continue; + } + + // Record the physreg defs. + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + const MachineOperand &MO = MI->getOperand(i); + if (MO.isReg() && MO.isDef()) { + unsigned Reg = MO.getReg(); + if (Reg != 0 && TargetRegisterInfo::isPhysicalRegister(Reg)) { + LivePhysRegs.reset(Reg); + // Check the subreg set, not the alias set, because a def + // of a super-register may still be partially live after + // this def. + for (const unsigned *SubRegs = TRI->getSubRegisters(Reg); + *SubRegs; ++SubRegs) + LivePhysRegs.reset(*SubRegs); + } + } + } + // Record the physreg uses, after the defs, in case a physreg is + // both defined and used in the same instruction. + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + const MachineOperand &MO = MI->getOperand(i); + if (MO.isReg() && MO.isUse()) { + unsigned Reg = MO.getReg(); + if (Reg != 0 && TargetRegisterInfo::isPhysicalRegister(Reg)) { + LivePhysRegs.set(Reg); + for (const unsigned *AliasSet = TRI->getAliasSet(Reg); + *AliasSet; ++AliasSet) + LivePhysRegs.set(*AliasSet); + } + } + } + + // We didn't delete the current instruction, so increment MII to + // the next one. + ++MII; + } + } + + LivePhysRegs.clear(); + return AnyChanges; +} diff --git a/libclamav/c++/llvm/lib/CodeGen/DwarfEHPrepare.cpp b/libclamav/c++/llvm/lib/CodeGen/DwarfEHPrepare.cpp new file mode 100644 index 000000000..9b516ed75 --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/DwarfEHPrepare.cpp @@ -0,0 +1,415 @@ +//===-- DwarfEHPrepare - Prepare exception handling for code generation ---===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This pass mulches exception handling code into a form adapted to code +// generation. Required if using dwarf exception handling. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "dwarfehprepare" +#include "llvm/ADT/Statistic.h" +#include "llvm/Analysis/Dominators.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/Function.h" +#include "llvm/Instructions.h" +#include "llvm/IntrinsicInst.h" +#include "llvm/Module.h" +#include "llvm/Pass.h" +#include "llvm/Target/TargetLowering.h" +#include "llvm/Transforms/Utils/BasicBlockUtils.h" +#include "llvm/Transforms/Utils/PromoteMemToReg.h" +using namespace llvm; + +STATISTIC(NumLandingPadsSplit, "Number of landing pads split"); +STATISTIC(NumUnwindsLowered, "Number of unwind instructions lowered"); +STATISTIC(NumExceptionValuesMoved, "Number of eh.exception calls moved"); +STATISTIC(NumStackTempsIntroduced, "Number of stack temporaries introduced"); + +namespace { + class DwarfEHPrepare : public FunctionPass { + const TargetLowering *TLI; + bool CompileFast; + + // The eh.exception intrinsic. + Function *ExceptionValueIntrinsic; + + // _Unwind_Resume or the target equivalent. + Constant *RewindFunction; + + // Dominator info is used when turning stack temporaries into registers. + DominatorTree *DT; + DominanceFrontier *DF; + + // The function we are running on. + Function *F; + + // The landing pads for this function. + typedef SmallPtrSet BBSet; + BBSet LandingPads; + + // Stack temporary used to hold eh.exception values. + AllocaInst *ExceptionValueVar; + + bool NormalizeLandingPads(); + bool LowerUnwinds(); + bool MoveExceptionValueCalls(); + bool FinishStackTemporaries(); + bool PromoteStackTemporaries(); + + Instruction *CreateExceptionValueCall(BasicBlock *BB); + Instruction *CreateValueLoad(BasicBlock *BB); + + /// CreateReadOfExceptionValue - Return the result of the eh.exception + /// intrinsic by calling the intrinsic if in a landing pad, or loading + /// it from the exception value variable otherwise. + Instruction *CreateReadOfExceptionValue(BasicBlock *BB) { + return LandingPads.count(BB) ? + CreateExceptionValueCall(BB) : CreateValueLoad(BB); + } + + public: + static char ID; // Pass identification, replacement for typeid. + DwarfEHPrepare(const TargetLowering *tli, bool fast) : + FunctionPass(&ID), TLI(tli), CompileFast(fast), + ExceptionValueIntrinsic(0), RewindFunction(0) {} + + virtual bool runOnFunction(Function &Fn); + + // getAnalysisUsage - We need dominance frontiers for memory promotion. + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + if (!CompileFast) + AU.addRequired(); + AU.addPreserved(); + if (!CompileFast) + AU.addRequired(); + AU.addPreserved(); + } + + const char *getPassName() const { + return "Exception handling preparation"; + } + + }; +} // end anonymous namespace + +char DwarfEHPrepare::ID = 0; + +FunctionPass *llvm::createDwarfEHPass(const TargetLowering *tli, bool fast) { + return new DwarfEHPrepare(tli, fast); +} + +/// NormalizeLandingPads - Normalize and discover landing pads, noting them +/// in the LandingPads set. A landing pad is normal if the only CFG edges +/// that end at it are unwind edges from invoke instructions. If we inlined +/// through an invoke we could have a normal branch from the previous +/// unwind block through to the landing pad for the original invoke. +/// Abnormal landing pads are fixed up by redirecting all unwind edges to +/// a new basic block which falls through to the original. +bool DwarfEHPrepare::NormalizeLandingPads() { + bool Changed = false; + + for (Function::iterator I = F->begin(), E = F->end(); I != E; ++I) { + TerminatorInst *TI = I->getTerminator(); + if (!isa(TI)) + continue; + BasicBlock *LPad = TI->getSuccessor(1); + // Skip landing pads that have already been normalized. + if (LandingPads.count(LPad)) + continue; + + // Check that only invoke unwind edges end at the landing pad. + bool OnlyUnwoundTo = true; + for (pred_iterator PI = pred_begin(LPad), PE = pred_end(LPad); + PI != PE; ++PI) { + TerminatorInst *PT = (*PI)->getTerminator(); + if (!isa(PT) || LPad == PT->getSuccessor(0)) { + OnlyUnwoundTo = false; + break; + } + } + + if (OnlyUnwoundTo) { + // Only unwind edges lead to the landing pad. Remember the landing pad. + LandingPads.insert(LPad); + continue; + } + + // At least one normal edge ends at the landing pad. Redirect the unwind + // edges to a new basic block which falls through into this one. + + // Create the new basic block. + BasicBlock *NewBB = BasicBlock::Create(F->getContext(), + LPad->getName() + "_unwind_edge"); + + // Insert it into the function right before the original landing pad. + LPad->getParent()->getBasicBlockList().insert(LPad, NewBB); + + // Redirect unwind edges from the original landing pad to NewBB. + for (pred_iterator PI = pred_begin(LPad), PE = pred_end(LPad); PI != PE; ) { + TerminatorInst *PT = (*PI++)->getTerminator(); + if (isa(PT) && PT->getSuccessor(1) == LPad) + // Unwind to the new block. + PT->setSuccessor(1, NewBB); + } + + // If there are any PHI nodes in LPad, we need to update them so that they + // merge incoming values from NewBB instead. + for (BasicBlock::iterator II = LPad->begin(); isa(II); ++II) { + PHINode *PN = cast(II); + pred_iterator PB = pred_begin(NewBB), PE = pred_end(NewBB); + + // Check to see if all of the values coming in via unwind edges are the + // same. If so, we don't need to create a new PHI node. + Value *InVal = PN->getIncomingValueForBlock(*PB); + for (pred_iterator PI = PB; PI != PE; ++PI) { + if (PI != PB && InVal != PN->getIncomingValueForBlock(*PI)) { + InVal = 0; + break; + } + } + + if (InVal == 0) { + // Different unwind edges have different values. Create a new PHI node + // in NewBB. + PHINode *NewPN = PHINode::Create(PN->getType(), PN->getName()+".unwind", + NewBB); + // Add an entry for each unwind edge, using the value from the old PHI. + for (pred_iterator PI = PB; PI != PE; ++PI) + NewPN->addIncoming(PN->getIncomingValueForBlock(*PI), *PI); + + // Now use this new PHI as the common incoming value for NewBB in PN. + InVal = NewPN; + } + + // Revector exactly one entry in the PHI node to come from NewBB + // and delete all other entries that come from unwind edges. If + // there are both normal and unwind edges from the same predecessor, + // this leaves an entry for the normal edge. + for (pred_iterator PI = PB; PI != PE; ++PI) + PN->removeIncomingValue(*PI); + PN->addIncoming(InVal, NewBB); + } + + // Add a fallthrough from NewBB to the original landing pad. + BranchInst::Create(LPad, NewBB); + + // Now update DominatorTree and DominanceFrontier analysis information. + if (DT) + DT->splitBlock(NewBB); + if (DF) + DF->splitBlock(NewBB); + + // Remember the newly constructed landing pad. The original landing pad + // LPad is no longer a landing pad now that all unwind edges have been + // revectored to NewBB. + LandingPads.insert(NewBB); + ++NumLandingPadsSplit; + Changed = true; + } + + return Changed; +} + +/// LowerUnwinds - Turn unwind instructions into calls to _Unwind_Resume, +/// rethrowing any previously caught exception. This will crash horribly +/// at runtime if there is no such exception: using unwind to throw a new +/// exception is currently not supported. +bool DwarfEHPrepare::LowerUnwinds() { + SmallVector UnwindInsts; + + for (Function::iterator I = F->begin(), E = F->end(); I != E; ++I) { + TerminatorInst *TI = I->getTerminator(); + if (isa(TI)) + UnwindInsts.push_back(TI); + } + + if (UnwindInsts.empty()) return false; + + // Find the rewind function if we didn't already. + if (!RewindFunction) { + LLVMContext &Ctx = UnwindInsts[0]->getContext(); + std::vector + Params(1, Type::getInt8PtrTy(Ctx)); + FunctionType *FTy = FunctionType::get(Type::getVoidTy(Ctx), + Params, false); + const char *RewindName = TLI->getLibcallName(RTLIB::UNWIND_RESUME); + RewindFunction = F->getParent()->getOrInsertFunction(RewindName, FTy); + } + + bool Changed = false; + + for (SmallVectorImpl::iterator + I = UnwindInsts.begin(), E = UnwindInsts.end(); I != E; ++I) { + TerminatorInst *TI = *I; + + // Replace the unwind instruction with a call to _Unwind_Resume (or the + // appropriate target equivalent) followed by an UnreachableInst. + + // Create the call... + CallInst *CI = CallInst::Create(RewindFunction, + CreateReadOfExceptionValue(TI->getParent()), + "", TI); + CI->setCallingConv(TLI->getLibcallCallingConv(RTLIB::UNWIND_RESUME)); + // ...followed by an UnreachableInst. + new UnreachableInst(TI->getContext(), TI); + + // Nuke the unwind instruction. + TI->eraseFromParent(); + ++NumUnwindsLowered; + Changed = true; + } + + return Changed; +} + +/// MoveExceptionValueCalls - Ensure that eh.exception is only ever called from +/// landing pads by replacing calls outside of landing pads with loads from a +/// stack temporary. Move eh.exception calls inside landing pads to the start +/// of the landing pad (optional, but may make things simpler for later passes). +bool DwarfEHPrepare::MoveExceptionValueCalls() { + // If the eh.exception intrinsic is not declared in the module then there is + // nothing to do. Speed up compilation by checking for this common case. + if (!ExceptionValueIntrinsic && + !F->getParent()->getFunction(Intrinsic::getName(Intrinsic::eh_exception))) + return false; + + bool Changed = false; + + for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) { + for (BasicBlock::iterator II = BB->begin(), E = BB->end(); II != E;) + if (IntrinsicInst *CI = dyn_cast(II++)) + if (CI->getIntrinsicID() == Intrinsic::eh_exception) { + if (!CI->use_empty()) { + Value *ExceptionValue = CreateReadOfExceptionValue(BB); + if (CI == ExceptionValue) { + // The call was at the start of a landing pad - leave it alone. + assert(LandingPads.count(BB) && + "Created eh.exception call outside landing pad!"); + continue; + } + CI->replaceAllUsesWith(ExceptionValue); + } + CI->eraseFromParent(); + ++NumExceptionValuesMoved; + Changed = true; + } + } + + return Changed; +} + +/// FinishStackTemporaries - If we introduced a stack variable to hold the +/// exception value then initialize it in each landing pad. +bool DwarfEHPrepare::FinishStackTemporaries() { + if (!ExceptionValueVar) + // Nothing to do. + return false; + + bool Changed = false; + + // Make sure that there is a store of the exception value at the start of + // each landing pad. + for (BBSet::iterator LI = LandingPads.begin(), LE = LandingPads.end(); + LI != LE; ++LI) { + Instruction *ExceptionValue = CreateReadOfExceptionValue(*LI); + Instruction *Store = new StoreInst(ExceptionValue, ExceptionValueVar); + Store->insertAfter(ExceptionValue); + Changed = true; + } + + return Changed; +} + +/// PromoteStackTemporaries - Turn any stack temporaries we introduced into +/// registers if possible. +bool DwarfEHPrepare::PromoteStackTemporaries() { + if (ExceptionValueVar && DT && DF && isAllocaPromotable(ExceptionValueVar)) { + // Turn the exception temporary into registers and phi nodes if possible. + std::vector Allocas(1, ExceptionValueVar); + PromoteMemToReg(Allocas, *DT, *DF); + return true; + } + return false; +} + +/// CreateExceptionValueCall - Insert a call to the eh.exception intrinsic at +/// the start of the basic block (unless there already is one, in which case +/// the existing call is returned). +Instruction *DwarfEHPrepare::CreateExceptionValueCall(BasicBlock *BB) { + Instruction *Start = BB->getFirstNonPHI(); + // Is this a call to eh.exception? + if (IntrinsicInst *CI = dyn_cast(Start)) + if (CI->getIntrinsicID() == Intrinsic::eh_exception) + // Reuse the existing call. + return Start; + + // Find the eh.exception intrinsic if we didn't already. + if (!ExceptionValueIntrinsic) + ExceptionValueIntrinsic = Intrinsic::getDeclaration(F->getParent(), + Intrinsic::eh_exception); + + // Create the call. + return CallInst::Create(ExceptionValueIntrinsic, "eh.value.call", Start); +} + +/// CreateValueLoad - Insert a load of the exception value stack variable +/// (creating it if necessary) at the start of the basic block (unless +/// there already is a load, in which case the existing load is returned). +Instruction *DwarfEHPrepare::CreateValueLoad(BasicBlock *BB) { + Instruction *Start = BB->getFirstNonPHI(); + // Is this a load of the exception temporary? + if (ExceptionValueVar) + if (LoadInst* LI = dyn_cast(Start)) + if (LI->getPointerOperand() == ExceptionValueVar) + // Reuse the existing load. + return Start; + + // Create the temporary if we didn't already. + if (!ExceptionValueVar) { + ExceptionValueVar = new AllocaInst(PointerType::getUnqual( + Type::getInt8Ty(BB->getContext())), "eh.value", F->begin()->begin()); + ++NumStackTempsIntroduced; + } + + // Load the value. + return new LoadInst(ExceptionValueVar, "eh.value.load", Start); +} + +bool DwarfEHPrepare::runOnFunction(Function &Fn) { + bool Changed = false; + + // Initialize internal state. + DT = getAnalysisIfAvailable(); + DF = getAnalysisIfAvailable(); + ExceptionValueVar = 0; + F = &Fn; + + // Ensure that only unwind edges end at landing pads (a landing pad is a + // basic block where an invoke unwind edge ends). + Changed |= NormalizeLandingPads(); + + // Turn unwind instructions into libcalls. + Changed |= LowerUnwinds(); + + // TODO: Move eh.selector calls to landing pads and combine them. + + // Move eh.exception calls to landing pads. + Changed |= MoveExceptionValueCalls(); + + // Initialize any stack temporaries we introduced. + Changed |= FinishStackTemporaries(); + + // Turn any stack temporaries into registers if possible. + if (!CompileFast) + Changed |= PromoteStackTemporaries(); + + LandingPads.clear(); + + return Changed; +} diff --git a/libclamav/c++/llvm/lib/CodeGen/ELF.h b/libclamav/c++/llvm/lib/CodeGen/ELF.h new file mode 100644 index 000000000..e303ebb0d --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/ELF.h @@ -0,0 +1,317 @@ +//===-- lib/CodeGen/ELF.h - ELF constants and data structures ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This header contains common, non-processor-specific data structures and +// constants for the ELF file format. +// +// The details of the ELF32 bits in this file are largely based on the Tool +// Interface Standard (TIS) Executable and Linking Format (ELF) Specification +// Version 1.2, May 1995. The ELF64 is based on HP/Intel definition of the +// ELF-64 object file format document, Version 1.5 Draft 2 May 27, 1998 +// +//===----------------------------------------------------------------------===// + +#ifndef CODEGEN_ELF_H +#define CODEGEN_ELF_H + +#include "llvm/CodeGen/BinaryObject.h" +#include "llvm/CodeGen/MachineRelocation.h" +#include "llvm/System/DataTypes.h" + +namespace llvm { + class GlobalValue; + + // Identification Indexes + enum { + EI_MAG0 = 0, + EI_MAG1 = 1, + EI_MAG2 = 2, + EI_MAG3 = 3 + }; + + // File types + enum { + ET_NONE = 0, // No file type + ET_REL = 1, // Relocatable file + ET_EXEC = 2, // Executable file + ET_DYN = 3, // Shared object file + ET_CORE = 4, // Core file + ET_LOPROC = 0xff00, // Beginning of processor-specific codes + ET_HIPROC = 0xffff // Processor-specific + }; + + // Versioning + enum { + EV_NONE = 0, + EV_CURRENT = 1 + }; + + /// ELFSym - This struct contains information about each symbol that is + /// added to logical symbol table for the module. This is eventually + /// turned into a real symbol table in the file. + struct ELFSym { + + // ELF symbols are related to llvm ones by being one of the two llvm + // types, for the other ones (section, file, func) a null pointer is + // assumed by default. + union { + const GlobalValue *GV; // If this is a pointer to a GV + const char *Ext; // If this is a pointer to a named symbol + } Source; + + // Describes from which source type this ELF symbol comes from, + // they can be GlobalValue, ExternalSymbol or neither. + enum { + isGV, // The Source.GV field is valid. + isExtSym, // The Source.ExtSym field is valid. + isOther // Not a GlobalValue or External Symbol + }; + unsigned SourceType; + + bool isGlobalValue() const { return SourceType == isGV; } + bool isExternalSym() const { return SourceType == isExtSym; } + + // getGlobalValue - If this is a global value which originated the + // elf symbol, return a reference to it. + const GlobalValue *getGlobalValue() const { + assert(SourceType == isGV && "This is not a global value"); + return Source.GV; + }; + + // getExternalSym - If this is an external symbol which originated the + // elf symbol, return a reference to it. + const char *getExternalSymbol() const { + assert(SourceType == isExtSym && "This is not an external symbol"); + return Source.Ext; + }; + + // getGV - From a global value return a elf symbol to represent it + static ELFSym *getGV(const GlobalValue *GV, unsigned Bind, + unsigned Type, unsigned Visibility) { + ELFSym *Sym = new ELFSym(); + Sym->Source.GV = GV; + Sym->setBind(Bind); + Sym->setType(Type); + Sym->setVisibility(Visibility); + Sym->SourceType = isGV; + return Sym; + } + + // getExtSym - Create and return an elf symbol to represent an + // external symbol + static ELFSym *getExtSym(const char *Ext) { + ELFSym *Sym = new ELFSym(); + Sym->Source.Ext = Ext; + Sym->setBind(STB_GLOBAL); + Sym->setType(STT_NOTYPE); + Sym->setVisibility(STV_DEFAULT); + Sym->SourceType = isExtSym; + return Sym; + } + + // getSectionSym - Returns a elf symbol to represent an elf section + static ELFSym *getSectionSym() { + ELFSym *Sym = new ELFSym(); + Sym->setBind(STB_LOCAL); + Sym->setType(STT_SECTION); + Sym->setVisibility(STV_DEFAULT); + Sym->SourceType = isOther; + return Sym; + } + + // getFileSym - Returns a elf symbol to represent the module identifier + static ELFSym *getFileSym() { + ELFSym *Sym = new ELFSym(); + Sym->setBind(STB_LOCAL); + Sym->setType(STT_FILE); + Sym->setVisibility(STV_DEFAULT); + Sym->SectionIdx = 0xfff1; // ELFSection::SHN_ABS; + Sym->SourceType = isOther; + return Sym; + } + + // getUndefGV - Returns a STT_NOTYPE symbol + static ELFSym *getUndefGV(const GlobalValue *GV, unsigned Bind) { + ELFSym *Sym = new ELFSym(); + Sym->Source.GV = GV; + Sym->setBind(Bind); + Sym->setType(STT_NOTYPE); + Sym->setVisibility(STV_DEFAULT); + Sym->SectionIdx = 0; //ELFSection::SHN_UNDEF; + Sym->SourceType = isGV; + return Sym; + } + + // ELF specific fields + unsigned NameIdx; // Index in .strtab of name, once emitted. + uint64_t Value; + unsigned Size; + uint8_t Info; + uint8_t Other; + unsigned short SectionIdx; + + // Symbol index into the Symbol table + unsigned SymTabIdx; + + enum { + STB_LOCAL = 0, // Local sym, not visible outside obj file containing def + STB_GLOBAL = 1, // Global sym, visible to all object files being combined + STB_WEAK = 2 // Weak symbol, like global but lower-precedence + }; + + enum { + STT_NOTYPE = 0, // Symbol's type is not specified + STT_OBJECT = 1, // Symbol is a data object (variable, array, etc.) + STT_FUNC = 2, // Symbol is executable code (function, etc.) + STT_SECTION = 3, // Symbol refers to a section + STT_FILE = 4 // Local, absolute symbol that refers to a file + }; + + enum { + STV_DEFAULT = 0, // Visibility is specified by binding type + STV_INTERNAL = 1, // Defined by processor supplements + STV_HIDDEN = 2, // Not visible to other components + STV_PROTECTED = 3 // Visible in other components but not preemptable + }; + + ELFSym() : SourceType(isOther), NameIdx(0), Value(0), + Size(0), Info(0), Other(STV_DEFAULT), SectionIdx(0), + SymTabIdx(0) {} + + unsigned getBind() const { return (Info >> 4) & 0xf; } + unsigned getType() const { return Info & 0xf; } + bool isLocalBind() const { return getBind() == STB_LOCAL; } + bool isFileType() const { return getType() == STT_FILE; } + + void setBind(unsigned X) { + assert(X == (X & 0xF) && "Bind value out of range!"); + Info = (Info & 0x0F) | (X << 4); + } + + void setType(unsigned X) { + assert(X == (X & 0xF) && "Type value out of range!"); + Info = (Info & 0xF0) | X; + } + + void setVisibility(unsigned V) { + assert(V == (V & 0x3) && "Visibility value out of range!"); + Other = V; + } + }; + + /// ELFSection - This struct contains information about each section that is + /// emitted to the file. This is eventually turned into the section header + /// table at the end of the file. + class ELFSection : public BinaryObject { + public: + // ELF specific fields + unsigned NameIdx; // sh_name - .shstrtab idx of name, once emitted. + unsigned Type; // sh_type - Section contents & semantics + unsigned Flags; // sh_flags - Section flags. + uint64_t Addr; // sh_addr - The mem addr this section is in. + unsigned Offset; // sh_offset - Offset from the file start + unsigned Size; // sh_size - The section size. + unsigned Link; // sh_link - Section header table index link. + unsigned Info; // sh_info - Auxillary information. + unsigned Align; // sh_addralign - Alignment of section. + unsigned EntSize; // sh_entsize - Size of entries in the section e + + // Section Header Flags + enum { + SHF_WRITE = 1 << 0, // Writable + SHF_ALLOC = 1 << 1, // Mapped into the process addr space + SHF_EXECINSTR = 1 << 2, // Executable + SHF_MERGE = 1 << 4, // Might be merged if equal + SHF_STRINGS = 1 << 5, // Contains null-terminated strings + SHF_INFO_LINK = 1 << 6, // 'sh_info' contains SHT index + SHF_LINK_ORDER = 1 << 7, // Preserve order after combining + SHF_OS_NONCONFORMING = 1 << 8, // nonstandard OS support required + SHF_GROUP = 1 << 9, // Section is a member of a group + SHF_TLS = 1 << 10 // Section holds thread-local data + }; + + // Section Types + enum { + SHT_NULL = 0, // No associated section (inactive entry). + SHT_PROGBITS = 1, // Program-defined contents. + SHT_SYMTAB = 2, // Symbol table. + SHT_STRTAB = 3, // String table. + SHT_RELA = 4, // Relocation entries; explicit addends. + SHT_HASH = 5, // Symbol hash table. + SHT_DYNAMIC = 6, // Information for dynamic linking. + SHT_NOTE = 7, // Information about the file. + SHT_NOBITS = 8, // Data occupies no space in the file. + SHT_REL = 9, // Relocation entries; no explicit addends. + SHT_SHLIB = 10, // Reserved. + SHT_DYNSYM = 11, // Symbol table. + SHT_LOPROC = 0x70000000, // Lowest processor arch-specific type. + SHT_HIPROC = 0x7fffffff, // Highest processor arch-specific type. + SHT_LOUSER = 0x80000000, // Lowest type reserved for applications. + SHT_HIUSER = 0xffffffff // Highest type reserved for applications. + }; + + // Special section indices. + enum { + SHN_UNDEF = 0, // Undefined, missing, irrelevant + SHN_LORESERVE = 0xff00, // Lowest reserved index + SHN_LOPROC = 0xff00, // Lowest processor-specific index + SHN_HIPROC = 0xff1f, // Highest processor-specific index + SHN_ABS = 0xfff1, // Symbol has absolute value; no relocation + SHN_COMMON = 0xfff2, // FORTRAN COMMON or C external global variables + SHN_HIRESERVE = 0xffff // Highest reserved index + }; + + /// SectionIdx - The number of the section in the Section Table. + unsigned short SectionIdx; + + /// Sym - The symbol to represent this section if it has one. + ELFSym *Sym; + + /// getSymIndex - Returns the symbol table index of the symbol + /// representing this section. + unsigned getSymbolTableIndex() const { + assert(Sym && "section not present in the symbol table"); + return Sym->SymTabIdx; + } + + ELFSection(const std::string &name, bool isLittleEndian, bool is64Bit) + : BinaryObject(name, isLittleEndian, is64Bit), Type(0), Flags(0), Addr(0), + Offset(0), Size(0), Link(0), Info(0), Align(0), EntSize(0), Sym(0) {} + }; + + /// ELFRelocation - This class contains all the information necessary to + /// to generate any 32-bit or 64-bit ELF relocation entry. + class ELFRelocation { + uint64_t r_offset; // offset in the section of the object this applies to + uint32_t r_symidx; // symbol table index of the symbol to use + uint32_t r_type; // machine specific relocation type + int64_t r_add; // explicit relocation addend + bool r_rela; // if true then the addend is part of the entry + // otherwise the addend is at the location specified + // by r_offset + public: + uint64_t getInfo(bool is64Bit) const { + if (is64Bit) + return ((uint64_t)r_symidx << 32) + ((uint64_t)r_type & 0xFFFFFFFFL); + else + return (r_symidx << 8) + (r_type & 0xFFL); + } + + uint64_t getOffset() const { return r_offset; } + int64_t getAddend() const { return r_add; } + + ELFRelocation(uint64_t off, uint32_t sym, uint32_t type, + bool rela = true, int64_t addend = 0) : + r_offset(off), r_symidx(sym), r_type(type), + r_add(addend), r_rela(rela) {} + }; + +} // end namespace llvm + +#endif diff --git a/libclamav/c++/llvm/lib/CodeGen/ELFCodeEmitter.cpp b/libclamav/c++/llvm/lib/CodeGen/ELFCodeEmitter.cpp new file mode 100644 index 000000000..a6429f700 --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/ELFCodeEmitter.cpp @@ -0,0 +1,204 @@ +//===-- lib/CodeGen/ELFCodeEmitter.cpp ------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "elfce" + +#include "ELF.h" +#include "ELFWriter.h" +#include "ELFCodeEmitter.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Function.h" +#include "llvm/CodeGen/BinaryObject.h" +#include "llvm/CodeGen/MachineConstantPool.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineJumpTableInfo.h" +#include "llvm/CodeGen/MachineRelocation.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetELFWriterInfo.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" + +//===----------------------------------------------------------------------===// +// ELFCodeEmitter Implementation +//===----------------------------------------------------------------------===// + +namespace llvm { + +/// startFunction - This callback is invoked when a new machine function is +/// about to be emitted. +void ELFCodeEmitter::startFunction(MachineFunction &MF) { + DEBUG(errs() << "processing function: " + << MF.getFunction()->getName() << "\n"); + + // Get the ELF Section that this function belongs in. + ES = &EW.getTextSection(MF.getFunction()); + + // Set the desired binary object to be used by the code emitters + setBinaryObject(ES); + + // Get the function alignment in bytes + unsigned Align = (1 << MF.getAlignment()); + + // The function must start on its required alignment + ES->emitAlignment(Align); + + // Update the section alignment if needed. + ES->Align = std::max(ES->Align, Align); + + // Record the function start offset + FnStartOff = ES->getCurrentPCOffset(); + + // Emit constant pool and jump tables to their appropriate sections. + // They need to be emitted before the function because in some targets + // the later may reference JT or CP entry address. + emitConstantPool(MF.getConstantPool()); + emitJumpTables(MF.getJumpTableInfo()); +} + +/// finishFunction - This callback is invoked after the function is completely +/// finished. +bool ELFCodeEmitter::finishFunction(MachineFunction &MF) { + // Add a symbol to represent the function. + const Function *F = MF.getFunction(); + ELFSym *FnSym = ELFSym::getGV(F, EW.getGlobalELFBinding(F), ELFSym::STT_FUNC, + EW.getGlobalELFVisibility(F)); + FnSym->SectionIdx = ES->SectionIdx; + FnSym->Size = ES->getCurrentPCOffset()-FnStartOff; + EW.AddPendingGlobalSymbol(F, true); + + // Offset from start of Section + FnSym->Value = FnStartOff; + + if (!F->hasPrivateLinkage()) + EW.SymbolList.push_back(FnSym); + + // Patch up Jump Table Section relocations to use the real MBBs offsets + // now that the MBB label offsets inside the function are known. + if (!MF.getJumpTableInfo()->isEmpty()) { + ELFSection &JTSection = EW.getJumpTableSection(); + for (std::vector::iterator MRI = JTRelocations.begin(), + MRE = JTRelocations.end(); MRI != MRE; ++MRI) { + MachineRelocation &MR = *MRI; + unsigned MBBOffset = getMachineBasicBlockAddress(MR.getBasicBlock()); + MR.setResultPointer((void*)MBBOffset); + MR.setConstantVal(ES->SectionIdx); + JTSection.addRelocation(MR); + } + } + + // If we have emitted any relocations to function-specific objects such as + // basic blocks, constant pools entries, or jump tables, record their + // addresses now so that we can rewrite them with the correct addresses later + for (unsigned i = 0, e = Relocations.size(); i != e; ++i) { + MachineRelocation &MR = Relocations[i]; + intptr_t Addr; + if (MR.isGlobalValue()) { + EW.AddPendingGlobalSymbol(MR.getGlobalValue()); + } else if (MR.isExternalSymbol()) { + EW.AddPendingExternalSymbol(MR.getExternalSymbol()); + } else if (MR.isBasicBlock()) { + Addr = getMachineBasicBlockAddress(MR.getBasicBlock()); + MR.setConstantVal(ES->SectionIdx); + MR.setResultPointer((void*)Addr); + } else if (MR.isConstantPoolIndex()) { + Addr = getConstantPoolEntryAddress(MR.getConstantPoolIndex()); + MR.setConstantVal(CPSections[MR.getConstantPoolIndex()]); + MR.setResultPointer((void*)Addr); + } else if (MR.isJumpTableIndex()) { + ELFSection &JTSection = EW.getJumpTableSection(); + Addr = getJumpTableEntryAddress(MR.getJumpTableIndex()); + MR.setConstantVal(JTSection.SectionIdx); + MR.setResultPointer((void*)Addr); + } else { + llvm_unreachable("Unhandled relocation type"); + } + ES->addRelocation(MR); + } + + // Clear per-function data structures. + JTRelocations.clear(); + Relocations.clear(); + CPLocations.clear(); + CPSections.clear(); + JTLocations.clear(); + MBBLocations.clear(); + return false; +} + +/// emitConstantPool - For each constant pool entry, figure out which section +/// the constant should live in and emit the constant +void ELFCodeEmitter::emitConstantPool(MachineConstantPool *MCP) { + const std::vector &CP = MCP->getConstants(); + if (CP.empty()) return; + + // TODO: handle PIC codegen + assert(TM.getRelocationModel() != Reloc::PIC_ && + "PIC codegen not yet handled for elf constant pools!"); + + for (unsigned i = 0, e = CP.size(); i != e; ++i) { + MachineConstantPoolEntry CPE = CP[i]; + + // Record the constant pool location and the section index + ELFSection &CstPool = EW.getConstantPoolSection(CPE); + CPLocations.push_back(CstPool.size()); + CPSections.push_back(CstPool.SectionIdx); + + if (CPE.isMachineConstantPoolEntry()) + assert("CPE.isMachineConstantPoolEntry not supported yet"); + + // Emit the constant to constant pool section + EW.EmitGlobalConstant(CPE.Val.ConstVal, CstPool); + } +} + +/// emitJumpTables - Emit all the jump tables for a given jump table info +/// record to the appropriate section. +void ELFCodeEmitter::emitJumpTables(MachineJumpTableInfo *MJTI) { + const std::vector &JT = MJTI->getJumpTables(); + if (JT.empty()) return; + + // FIXME: handle PIC codegen + assert(TM.getRelocationModel() != Reloc::PIC_ && + "PIC codegen not yet handled for elf jump tables!"); + + const TargetELFWriterInfo *TEW = TM.getELFWriterInfo(); + unsigned EntrySize = MJTI->getEntrySize(); + + // Get the ELF Section to emit the jump table + ELFSection &JTSection = EW.getJumpTableSection(); + + // For each JT, record its offset from the start of the section + for (unsigned i = 0, e = JT.size(); i != e; ++i) { + const std::vector &MBBs = JT[i].MBBs; + + // Record JT 'i' offset in the JT section + JTLocations.push_back(JTSection.size()); + + // Each MBB entry in the Jump table section has a relocation entry + // against the current text section. + for (unsigned mi = 0, me = MBBs.size(); mi != me; ++mi) { + unsigned MachineRelTy = TEW->getAbsoluteLabelMachineRelTy(); + MachineRelocation MR = + MachineRelocation::getBB(JTSection.size(), MachineRelTy, MBBs[mi]); + + // Add the relocation to the Jump Table section + JTRelocations.push_back(MR); + + // Output placeholder for MBB in the JT section + for (unsigned s=0; s < EntrySize; ++s) + JTSection.emitByte(0); + } + } +} + +} // end namespace llvm diff --git a/libclamav/c++/llvm/lib/CodeGen/ELFCodeEmitter.h b/libclamav/c++/llvm/lib/CodeGen/ELFCodeEmitter.h new file mode 100644 index 000000000..b5e9c844e --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/ELFCodeEmitter.h @@ -0,0 +1,78 @@ +//===-- lib/CodeGen/ELFCodeEmitter.h ----------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef ELFCODEEMITTER_H +#define ELFCODEEMITTER_H + +#include "llvm/CodeGen/ObjectCodeEmitter.h" +#include + +namespace llvm { + class ELFWriter; + class ELFSection; + + /// ELFCodeEmitter - This class is used by the ELFWriter to + /// emit the code for functions to the ELF file. + class ELFCodeEmitter : public ObjectCodeEmitter { + ELFWriter &EW; + + /// Target machine description + TargetMachine &TM; + + /// Section containing code for functions + ELFSection *ES; + + /// Relocations - Record relocations needed by the current function + std::vector Relocations; + + /// JTRelocations - Record relocations needed by the relocation + /// section. + std::vector JTRelocations; + + /// FnStartPtr - Function offset from the beginning of ELFSection 'ES' + uintptr_t FnStartOff; + public: + explicit ELFCodeEmitter(ELFWriter &ew) : EW(ew), TM(EW.TM) {} + + /// addRelocation - Register new relocations for this function + void addRelocation(const MachineRelocation &MR) { + Relocations.push_back(MR); + } + + /// emitConstantPool - For each constant pool entry, figure out which + /// section the constant should live in and emit data to it + void emitConstantPool(MachineConstantPool *MCP); + + /// emitJumpTables - Emit all the jump tables for a given jump table + /// info and record them to the appropriate section. + void emitJumpTables(MachineJumpTableInfo *MJTI); + + void startFunction(MachineFunction &F); + bool finishFunction(MachineFunction &F); + + /// emitLabel - Emits a label + virtual void emitLabel(uint64_t LabelID) { + assert("emitLabel not implemented"); + } + + /// getLabelAddress - Return the address of the specified LabelID, + /// only usable after the LabelID has been emitted. + virtual uintptr_t getLabelAddress(uint64_t Label) const { + assert("getLabelAddress not implemented"); + return 0; + } + + virtual void setModuleInfo(llvm::MachineModuleInfo* MMI) {} + +}; // end class ELFCodeEmitter + +} // end namespace llvm + +#endif + diff --git a/libclamav/c++/llvm/lib/CodeGen/ELFWriter.cpp b/libclamav/c++/llvm/lib/CodeGen/ELFWriter.cpp new file mode 100644 index 000000000..3e1ee11b2 --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/ELFWriter.cpp @@ -0,0 +1,1104 @@ +//===-- ELFWriter.cpp - Target-independent ELF Writer code ----------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the target-independent ELF writer. This file writes out +// the ELF file in the following order: +// +// #1. ELF Header +// #2. '.text' section +// #3. '.data' section +// #4. '.bss' section (conceptual position in file) +// ... +// #X. '.shstrtab' section +// #Y. Section Table +// +// The entries in the section table are laid out as: +// #0. Null entry [required] +// #1. ".text" entry - the program code +// #2. ".data" entry - global variables with initializers. [ if needed ] +// #3. ".bss" entry - global variables without initializers. [ if needed ] +// ... +// #N. ".shstrtab" entry - String table for the section names. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "elfwriter" +#include "ELF.h" +#include "ELFWriter.h" +#include "ELFCodeEmitter.h" +#include "llvm/Constants.h" +#include "llvm/Module.h" +#include "llvm/PassManager.h" +#include "llvm/DerivedTypes.h" +#include "llvm/CodeGen/BinaryObject.h" +#include "llvm/CodeGen/FileWriters.h" +#include "llvm/CodeGen/MachineCodeEmitter.h" +#include "llvm/CodeGen/ObjectCodeEmitter.h" +#include "llvm/CodeGen/MachineCodeEmitter.h" +#include "llvm/CodeGen/MachineConstantPool.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCSectionELF.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetELFWriterInfo.h" +#include "llvm/Target/TargetLowering.h" +#include "llvm/Target/TargetLoweringObjectFile.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/Mangler.h" +#include "llvm/Support/raw_ostream.h" + +using namespace llvm; + +char ELFWriter::ID = 0; + +/// AddELFWriter - Add the ELF writer to the function pass manager +ObjectCodeEmitter *llvm::AddELFWriter(PassManagerBase &PM, + raw_ostream &O, + TargetMachine &TM) { + ELFWriter *EW = new ELFWriter(O, TM); + PM.add(EW); + return EW->getObjectCodeEmitter(); +} + +//===----------------------------------------------------------------------===// +// ELFWriter Implementation +//===----------------------------------------------------------------------===// + +ELFWriter::ELFWriter(raw_ostream &o, TargetMachine &tm) + : MachineFunctionPass(&ID), O(o), TM(tm), + OutContext(*new MCContext()), + TLOF(TM.getTargetLowering()->getObjFileLowering()), + is64Bit(TM.getTargetData()->getPointerSizeInBits() == 64), + isLittleEndian(TM.getTargetData()->isLittleEndian()), + ElfHdr(isLittleEndian, is64Bit) { + + MAI = TM.getMCAsmInfo(); + TEW = TM.getELFWriterInfo(); + + // Create the object code emitter object for this target. + ElfCE = new ELFCodeEmitter(*this); + + // Inital number of sections + NumSections = 0; +} + +ELFWriter::~ELFWriter() { + delete ElfCE; + delete &OutContext; + + while(!SymbolList.empty()) { + delete SymbolList.back(); + SymbolList.pop_back(); + } + + while(!PrivateSyms.empty()) { + delete PrivateSyms.back(); + PrivateSyms.pop_back(); + } + + while(!SectionList.empty()) { + delete SectionList.back(); + SectionList.pop_back(); + } + + // Release the name mangler object. + delete Mang; Mang = 0; +} + +// doInitialization - Emit the file header and all of the global variables for +// the module to the ELF file. +bool ELFWriter::doInitialization(Module &M) { + // Initialize TargetLoweringObjectFile. + const_cast(TLOF).Initialize(OutContext, TM); + + Mang = new Mangler(M); + + // ELF Header + // ---------- + // Fields e_shnum e_shstrndx are only known after all section have + // been emitted. They locations in the ouput buffer are recorded so + // to be patched up later. + // + // Note + // ---- + // emitWord method behaves differently for ELF32 and ELF64, writing + // 4 bytes in the former and 8 in the last for *_off and *_addr elf types + + ElfHdr.emitByte(0x7f); // e_ident[EI_MAG0] + ElfHdr.emitByte('E'); // e_ident[EI_MAG1] + ElfHdr.emitByte('L'); // e_ident[EI_MAG2] + ElfHdr.emitByte('F'); // e_ident[EI_MAG3] + + ElfHdr.emitByte(TEW->getEIClass()); // e_ident[EI_CLASS] + ElfHdr.emitByte(TEW->getEIData()); // e_ident[EI_DATA] + ElfHdr.emitByte(EV_CURRENT); // e_ident[EI_VERSION] + ElfHdr.emitAlignment(16); // e_ident[EI_NIDENT-EI_PAD] + + ElfHdr.emitWord16(ET_REL); // e_type + ElfHdr.emitWord16(TEW->getEMachine()); // e_machine = target + ElfHdr.emitWord32(EV_CURRENT); // e_version + ElfHdr.emitWord(0); // e_entry, no entry point in .o file + ElfHdr.emitWord(0); // e_phoff, no program header for .o + ELFHdr_e_shoff_Offset = ElfHdr.size(); + ElfHdr.emitWord(0); // e_shoff = sec hdr table off in bytes + ElfHdr.emitWord32(TEW->getEFlags()); // e_flags = whatever the target wants + ElfHdr.emitWord16(TEW->getHdrSize()); // e_ehsize = ELF header size + ElfHdr.emitWord16(0); // e_phentsize = prog header entry size + ElfHdr.emitWord16(0); // e_phnum = # prog header entries = 0 + + // e_shentsize = Section header entry size + ElfHdr.emitWord16(TEW->getSHdrSize()); + + // e_shnum = # of section header ents + ELFHdr_e_shnum_Offset = ElfHdr.size(); + ElfHdr.emitWord16(0); // Placeholder + + // e_shstrndx = Section # of '.shstrtab' + ELFHdr_e_shstrndx_Offset = ElfHdr.size(); + ElfHdr.emitWord16(0); // Placeholder + + // Add the null section, which is required to be first in the file. + getNullSection(); + + // The first entry in the symtab is the null symbol and the second + // is a local symbol containing the module/file name + SymbolList.push_back(new ELFSym()); + SymbolList.push_back(ELFSym::getFileSym()); + + return false; +} + +// AddPendingGlobalSymbol - Add a global to be processed and to +// the global symbol lookup, use a zero index because the table +// index will be determined later. +void ELFWriter::AddPendingGlobalSymbol(const GlobalValue *GV, + bool AddToLookup /* = false */) { + PendingGlobals.insert(GV); + if (AddToLookup) + GblSymLookup[GV] = 0; +} + +// AddPendingExternalSymbol - Add the external to be processed +// and to the external symbol lookup, use a zero index because +// the symbol table index will be determined later. +void ELFWriter::AddPendingExternalSymbol(const char *External) { + PendingExternals.insert(External); + ExtSymLookup[External] = 0; +} + +ELFSection &ELFWriter::getDataSection() { + const MCSectionELF *Data = (const MCSectionELF *)TLOF.getDataSection(); + return getSection(Data->getSectionName(), Data->getType(), + Data->getFlags(), 4); +} + +ELFSection &ELFWriter::getBSSSection() { + const MCSectionELF *BSS = (const MCSectionELF *)TLOF.getBSSSection(); + return getSection(BSS->getSectionName(), BSS->getType(), BSS->getFlags(), 4); +} + +// getCtorSection - Get the static constructor section +ELFSection &ELFWriter::getCtorSection() { + const MCSectionELF *Ctor = (const MCSectionELF *)TLOF.getStaticCtorSection(); + return getSection(Ctor->getSectionName(), Ctor->getType(), Ctor->getFlags()); +} + +// getDtorSection - Get the static destructor section +ELFSection &ELFWriter::getDtorSection() { + const MCSectionELF *Dtor = (const MCSectionELF *)TLOF.getStaticDtorSection(); + return getSection(Dtor->getSectionName(), Dtor->getType(), Dtor->getFlags()); +} + +// getTextSection - Get the text section for the specified function +ELFSection &ELFWriter::getTextSection(Function *F) { + const MCSectionELF *Text = + (const MCSectionELF *)TLOF.SectionForGlobal(F, Mang, TM); + return getSection(Text->getSectionName(), Text->getType(), Text->getFlags()); +} + +// getJumpTableSection - Get a read only section for constants when +// emitting jump tables. TODO: add PIC support +ELFSection &ELFWriter::getJumpTableSection() { + const MCSectionELF *JT = + (const MCSectionELF *)TLOF.getSectionForConstant(SectionKind::getReadOnly()); + return getSection(JT->getSectionName(), JT->getType(), JT->getFlags(), + TM.getTargetData()->getPointerABIAlignment()); +} + +// getConstantPoolSection - Get a constant pool section based on the machine +// constant pool entry type and relocation info. +ELFSection &ELFWriter::getConstantPoolSection(MachineConstantPoolEntry &CPE) { + SectionKind Kind; + switch (CPE.getRelocationInfo()) { + default: llvm_unreachable("Unknown section kind"); + case 2: Kind = SectionKind::getReadOnlyWithRel(); break; + case 1: + Kind = SectionKind::getReadOnlyWithRelLocal(); + break; + case 0: + switch (TM.getTargetData()->getTypeAllocSize(CPE.getType())) { + case 4: Kind = SectionKind::getMergeableConst4(); break; + case 8: Kind = SectionKind::getMergeableConst8(); break; + case 16: Kind = SectionKind::getMergeableConst16(); break; + default: Kind = SectionKind::getMergeableConst(); break; + } + } + + const MCSectionELF *CPSect = + (const MCSectionELF *)TLOF.getSectionForConstant(Kind); + return getSection(CPSect->getSectionName(), CPSect->getType(), + CPSect->getFlags(), CPE.getAlignment()); +} + +// getRelocSection - Return the relocation section of section 'S'. 'RelA' +// is true if the relocation section contains entries with addends. +ELFSection &ELFWriter::getRelocSection(ELFSection &S) { + unsigned SectionType = TEW->hasRelocationAddend() ? + ELFSection::SHT_RELA : ELFSection::SHT_REL; + + std::string SectionName(".rel"); + if (TEW->hasRelocationAddend()) + SectionName.append("a"); + SectionName.append(S.getName()); + + return getSection(SectionName, SectionType, 0, TEW->getPrefELFAlignment()); +} + +// getGlobalELFVisibility - Returns the ELF specific visibility type +unsigned ELFWriter::getGlobalELFVisibility(const GlobalValue *GV) { + switch (GV->getVisibility()) { + default: + llvm_unreachable("unknown visibility type"); + case GlobalValue::DefaultVisibility: + return ELFSym::STV_DEFAULT; + case GlobalValue::HiddenVisibility: + return ELFSym::STV_HIDDEN; + case GlobalValue::ProtectedVisibility: + return ELFSym::STV_PROTECTED; + } + return 0; +} + +// getGlobalELFBinding - Returns the ELF specific binding type +unsigned ELFWriter::getGlobalELFBinding(const GlobalValue *GV) { + if (GV->hasInternalLinkage()) + return ELFSym::STB_LOCAL; + + if (GV->isWeakForLinker() && !GV->hasCommonLinkage()) + return ELFSym::STB_WEAK; + + return ELFSym::STB_GLOBAL; +} + +// getGlobalELFType - Returns the ELF specific type for a global +unsigned ELFWriter::getGlobalELFType(const GlobalValue *GV) { + if (GV->isDeclaration()) + return ELFSym::STT_NOTYPE; + + if (isa(GV)) + return ELFSym::STT_FUNC; + + return ELFSym::STT_OBJECT; +} + +// IsELFUndefSym - True if the global value must be marked as a symbol +// which points to a SHN_UNDEF section. This means that the symbol has +// no definition on the module. +static bool IsELFUndefSym(const GlobalValue *GV) { + return GV->isDeclaration() || (isa(GV)); +} + +// AddToSymbolList - Update the symbol lookup and If the symbol is +// private add it to PrivateSyms list, otherwise to SymbolList. +void ELFWriter::AddToSymbolList(ELFSym *GblSym) { + assert(GblSym->isGlobalValue() && "Symbol must be a global value"); + + const GlobalValue *GV = GblSym->getGlobalValue(); + if (GV->hasPrivateLinkage()) { + // For a private symbols, keep track of the index inside + // the private list since it will never go to the symbol + // table and won't be patched up later. + PrivateSyms.push_back(GblSym); + GblSymLookup[GV] = PrivateSyms.size()-1; + } else { + // Non private symbol are left with zero indices until + // they are patched up during the symbol table emition + // (where the indicies are created). + SymbolList.push_back(GblSym); + GblSymLookup[GV] = 0; + } +} + +// EmitGlobal - Choose the right section for global and emit it +void ELFWriter::EmitGlobal(const GlobalValue *GV) { + + // Check if the referenced symbol is already emitted + if (GblSymLookup.find(GV) != GblSymLookup.end()) + return; + + // Handle ELF Bind, Visibility and Type for the current symbol + unsigned SymBind = getGlobalELFBinding(GV); + unsigned SymType = getGlobalELFType(GV); + bool IsUndefSym = IsELFUndefSym(GV); + + ELFSym *GblSym = IsUndefSym ? ELFSym::getUndefGV(GV, SymBind) + : ELFSym::getGV(GV, SymBind, SymType, getGlobalELFVisibility(GV)); + + if (!IsUndefSym) { + assert(isa(GV) && "GV not a global variable!"); + const GlobalVariable *GVar = dyn_cast(GV); + + // Handle special llvm globals + if (EmitSpecialLLVMGlobal(GVar)) + return; + + // Get the ELF section where this global belongs from TLOF + const MCSectionELF *S = + (const MCSectionELF *)TLOF.SectionForGlobal(GV, Mang, TM); + ELFSection &ES = + getSection(S->getSectionName(), S->getType(), S->getFlags()); + SectionKind Kind = S->getKind(); + + // The symbol align should update the section alignment if needed + const TargetData *TD = TM.getTargetData(); + unsigned Align = TD->getPreferredAlignment(GVar); + unsigned Size = TD->getTypeAllocSize(GVar->getInitializer()->getType()); + GblSym->Size = Size; + + if (S->HasCommonSymbols()) { // Symbol must go to a common section + GblSym->SectionIdx = ELFSection::SHN_COMMON; + + // A new linkonce section is created for each global in the + // common section, the default alignment is 1 and the symbol + // value contains its alignment. + ES.Align = 1; + GblSym->Value = Align; + + } else if (Kind.isBSS() || Kind.isThreadBSS()) { // Symbol goes to BSS. + GblSym->SectionIdx = ES.SectionIdx; + + // Update the size with alignment and the next object can + // start in the right offset in the section + if (Align) ES.Size = (ES.Size + Align-1) & ~(Align-1); + ES.Align = std::max(ES.Align, Align); + + // GblSym->Value should contain the virtual offset inside the section. + // Virtual because the BSS space is not allocated on ELF objects + GblSym->Value = ES.Size; + ES.Size += Size; + + } else { // The symbol must go to some kind of data section + GblSym->SectionIdx = ES.SectionIdx; + + // GblSym->Value should contain the symbol offset inside the section, + // and all symbols should start on their required alignment boundary + ES.Align = std::max(ES.Align, Align); + ES.emitAlignment(Align); + GblSym->Value = ES.size(); + + // Emit the global to the data section 'ES' + EmitGlobalConstant(GVar->getInitializer(), ES); + } + } + + AddToSymbolList(GblSym); +} + +void ELFWriter::EmitGlobalConstantStruct(const ConstantStruct *CVS, + ELFSection &GblS) { + + // Print the fields in successive locations. Pad to align if needed! + const TargetData *TD = TM.getTargetData(); + unsigned Size = TD->getTypeAllocSize(CVS->getType()); + const StructLayout *cvsLayout = TD->getStructLayout(CVS->getType()); + uint64_t sizeSoFar = 0; + for (unsigned i = 0, e = CVS->getNumOperands(); i != e; ++i) { + const Constant* field = CVS->getOperand(i); + + // Check if padding is needed and insert one or more 0s. + uint64_t fieldSize = TD->getTypeAllocSize(field->getType()); + uint64_t padSize = ((i == e-1 ? Size : cvsLayout->getElementOffset(i+1)) + - cvsLayout->getElementOffset(i)) - fieldSize; + sizeSoFar += fieldSize + padSize; + + // Now print the actual field value. + EmitGlobalConstant(field, GblS); + + // Insert padding - this may include padding to increase the size of the + // current field up to the ABI size (if the struct is not packed) as well + // as padding to ensure that the next field starts at the right offset. + GblS.emitZeros(padSize); + } + assert(sizeSoFar == cvsLayout->getSizeInBytes() && + "Layout of constant struct may be incorrect!"); +} + +void ELFWriter::EmitGlobalConstant(const Constant *CV, ELFSection &GblS) { + const TargetData *TD = TM.getTargetData(); + unsigned Size = TD->getTypeAllocSize(CV->getType()); + + if (const ConstantArray *CVA = dyn_cast(CV)) { + for (unsigned i = 0, e = CVA->getNumOperands(); i != e; ++i) + EmitGlobalConstant(CVA->getOperand(i), GblS); + return; + } else if (isa(CV)) { + GblS.emitZeros(Size); + return; + } else if (const ConstantStruct *CVS = dyn_cast(CV)) { + EmitGlobalConstantStruct(CVS, GblS); + return; + } else if (const ConstantFP *CFP = dyn_cast(CV)) { + APInt Val = CFP->getValueAPF().bitcastToAPInt(); + if (CFP->getType()->isDoubleTy()) + GblS.emitWord64(Val.getZExtValue()); + else if (CFP->getType()->isFloatTy()) + GblS.emitWord32(Val.getZExtValue()); + else if (CFP->getType()->isX86_FP80Ty()) { + unsigned PadSize = TD->getTypeAllocSize(CFP->getType())- + TD->getTypeStoreSize(CFP->getType()); + GblS.emitWordFP80(Val.getRawData(), PadSize); + } else if (CFP->getType()->isPPC_FP128Ty()) + llvm_unreachable("PPC_FP128Ty global emission not implemented"); + return; + } else if (const ConstantInt *CI = dyn_cast(CV)) { + if (Size == 1) + GblS.emitByte(CI->getZExtValue()); + else if (Size == 2) + GblS.emitWord16(CI->getZExtValue()); + else if (Size == 4) + GblS.emitWord32(CI->getZExtValue()); + else + EmitGlobalConstantLargeInt(CI, GblS); + return; + } else if (const ConstantVector *CP = dyn_cast(CV)) { + const VectorType *PTy = CP->getType(); + for (unsigned I = 0, E = PTy->getNumElements(); I < E; ++I) + EmitGlobalConstant(CP->getOperand(I), GblS); + return; + } else if (const ConstantExpr *CE = dyn_cast(CV)) { + // Resolve a constant expression which returns a (Constant, Offset) + // pair. If 'Res.first' is a GlobalValue, emit a relocation with + // the offset 'Res.second', otherwise emit a global constant like + // it is always done for not contant expression types. + CstExprResTy Res = ResolveConstantExpr(CE); + const Constant *Op = Res.first; + + if (isa(Op)) + EmitGlobalDataRelocation(cast(Op), + TD->getTypeAllocSize(Op->getType()), + GblS, Res.second); + else + EmitGlobalConstant(Op, GblS); + + return; + } else if (CV->getType()->getTypeID() == Type::PointerTyID) { + // Fill the data entry with zeros or emit a relocation entry + if (isa(CV)) + GblS.emitZeros(Size); + else + EmitGlobalDataRelocation(cast(CV), + Size, GblS); + return; + } else if (const GlobalValue *GV = dyn_cast(CV)) { + // This is a constant address for a global variable or function and + // therefore must be referenced using a relocation entry. + EmitGlobalDataRelocation(GV, Size, GblS); + return; + } + + std::string msg; + raw_string_ostream ErrorMsg(msg); + ErrorMsg << "Constant unimp for type: " << *CV->getType(); + llvm_report_error(ErrorMsg.str()); +} + +// ResolveConstantExpr - Resolve the constant expression until it stop +// yielding other constant expressions. +CstExprResTy ELFWriter::ResolveConstantExpr(const Constant *CV) { + const TargetData *TD = TM.getTargetData(); + + // There ins't constant expression inside others anymore + if (!isa(CV)) + return std::make_pair(CV, 0); + + const ConstantExpr *CE = dyn_cast(CV); + switch (CE->getOpcode()) { + case Instruction::BitCast: + return ResolveConstantExpr(CE->getOperand(0)); + + case Instruction::GetElementPtr: { + const Constant *ptrVal = CE->getOperand(0); + SmallVector idxVec(CE->op_begin()+1, CE->op_end()); + int64_t Offset = TD->getIndexedOffset(ptrVal->getType(), &idxVec[0], + idxVec.size()); + return std::make_pair(ptrVal, Offset); + } + case Instruction::IntToPtr: { + Constant *Op = CE->getOperand(0); + Op = ConstantExpr::getIntegerCast(Op, TD->getIntPtrType(CV->getContext()), + false/*ZExt*/); + return ResolveConstantExpr(Op); + } + case Instruction::PtrToInt: { + Constant *Op = CE->getOperand(0); + const Type *Ty = CE->getType(); + + // We can emit the pointer value into this slot if the slot is an + // integer slot greater or equal to the size of the pointer. + if (TD->getTypeAllocSize(Ty) == TD->getTypeAllocSize(Op->getType())) + return ResolveConstantExpr(Op); + + llvm_unreachable("Integer size less then pointer size"); + } + case Instruction::Add: + case Instruction::Sub: { + // Only handle cases where there's a constant expression with GlobalValue + // as first operand and ConstantInt as second, which are the cases we can + // solve direclty using a relocation entry. GlobalValue=Op0, CstInt=Op1 + // 1) Instruction::Add => (global) + CstInt + // 2) Instruction::Sub => (global) + -CstInt + const Constant *Op0 = CE->getOperand(0); + const Constant *Op1 = CE->getOperand(1); + assert(isa(Op1) && "Op1 must be a ConstantInt"); + + CstExprResTy Res = ResolveConstantExpr(Op0); + assert(isa(Res.first) && "Op0 must be a GlobalValue"); + + const APInt &RHS = cast(Op1)->getValue(); + switch (CE->getOpcode()) { + case Instruction::Add: + return std::make_pair(Res.first, RHS.getSExtValue()); + case Instruction::Sub: + return std::make_pair(Res.first, (-RHS).getSExtValue()); + } + } + } + + std::string msg(CE->getOpcodeName()); + raw_string_ostream ErrorMsg(msg); + ErrorMsg << ": Unsupported ConstantExpr type"; + llvm_report_error(ErrorMsg.str()); + + return std::make_pair(CV, 0); // silence warning +} + +void ELFWriter::EmitGlobalDataRelocation(const GlobalValue *GV, unsigned Size, + ELFSection &GblS, int64_t Offset) { + // Create the relocation entry for the global value + MachineRelocation MR = + MachineRelocation::getGV(GblS.getCurrentPCOffset(), + TEW->getAbsoluteLabelMachineRelTy(), + const_cast(GV), + Offset); + + // Fill the data entry with zeros + GblS.emitZeros(Size); + + // Add the relocation entry for the current data section + GblS.addRelocation(MR); +} + +void ELFWriter::EmitGlobalConstantLargeInt(const ConstantInt *CI, + ELFSection &S) { + const TargetData *TD = TM.getTargetData(); + unsigned BitWidth = CI->getBitWidth(); + assert(isPowerOf2_32(BitWidth) && + "Non-power-of-2-sized integers not handled!"); + + const uint64_t *RawData = CI->getValue().getRawData(); + uint64_t Val = 0; + for (unsigned i = 0, e = BitWidth / 64; i != e; ++i) { + Val = (TD->isBigEndian()) ? RawData[e - i - 1] : RawData[i]; + S.emitWord64(Val); + } +} + +/// EmitSpecialLLVMGlobal - Check to see if the specified global is a +/// special global used by LLVM. If so, emit it and return true, otherwise +/// do nothing and return false. +bool ELFWriter::EmitSpecialLLVMGlobal(const GlobalVariable *GV) { + if (GV->getName() == "llvm.used") + llvm_unreachable("not implemented yet"); + + // Ignore debug and non-emitted data. This handles llvm.compiler.used. + if (GV->getSection() == "llvm.metadata" || + GV->hasAvailableExternallyLinkage()) + return true; + + if (!GV->hasAppendingLinkage()) return false; + + assert(GV->hasInitializer() && "Not a special LLVM global!"); + + const TargetData *TD = TM.getTargetData(); + unsigned Align = TD->getPointerPrefAlignment(); + if (GV->getName() == "llvm.global_ctors") { + ELFSection &Ctor = getCtorSection(); + Ctor.emitAlignment(Align); + EmitXXStructorList(GV->getInitializer(), Ctor); + return true; + } + + if (GV->getName() == "llvm.global_dtors") { + ELFSection &Dtor = getDtorSection(); + Dtor.emitAlignment(Align); + EmitXXStructorList(GV->getInitializer(), Dtor); + return true; + } + + return false; +} + +/// EmitXXStructorList - Emit the ctor or dtor list. This just emits out the +/// function pointers, ignoring the init priority. +void ELFWriter::EmitXXStructorList(Constant *List, ELFSection &Xtor) { + // Should be an array of '{ int, void ()* }' structs. The first value is the + // init priority, which we ignore. + if (!isa(List)) return; + ConstantArray *InitList = cast(List); + for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i) + if (ConstantStruct *CS = dyn_cast(InitList->getOperand(i))){ + if (CS->getNumOperands() != 2) return; // Not array of 2-element structs. + + if (CS->getOperand(1)->isNullValue()) + return; // Found a null terminator, exit printing. + // Emit the function pointer. + EmitGlobalConstant(CS->getOperand(1), Xtor); + } +} + +bool ELFWriter::runOnMachineFunction(MachineFunction &MF) { + // Nothing to do here, this is all done through the ElfCE object above. + return false; +} + +/// doFinalization - Now that the module has been completely processed, emit +/// the ELF file to 'O'. +bool ELFWriter::doFinalization(Module &M) { + // Emit .data section placeholder + getDataSection(); + + // Emit .bss section placeholder + getBSSSection(); + + // Build and emit data, bss and "common" sections. + for (Module::global_iterator I = M.global_begin(), E = M.global_end(); + I != E; ++I) + EmitGlobal(I); + + // Emit all pending globals + for (PendingGblsIter I = PendingGlobals.begin(), E = PendingGlobals.end(); + I != E; ++I) + EmitGlobal(*I); + + // Emit all pending externals + for (PendingExtsIter I = PendingExternals.begin(), E = PendingExternals.end(); + I != E; ++I) + SymbolList.push_back(ELFSym::getExtSym(*I)); + + // Emit non-executable stack note + if (MAI->getNonexecutableStackDirective()) + getNonExecStackSection(); + + // Emit a symbol for each section created until now, skip null section + for (unsigned i = 1, e = SectionList.size(); i < e; ++i) { + ELFSection &ES = *SectionList[i]; + ELFSym *SectionSym = ELFSym::getSectionSym(); + SectionSym->SectionIdx = ES.SectionIdx; + SymbolList.push_back(SectionSym); + ES.Sym = SymbolList.back(); + } + + // Emit string table + EmitStringTable(M.getModuleIdentifier()); + + // Emit the symbol table now, if non-empty. + EmitSymbolTable(); + + // Emit the relocation sections. + EmitRelocations(); + + // Emit the sections string table. + EmitSectionTableStringTable(); + + // Dump the sections and section table to the .o file. + OutputSectionsAndSectionTable(); + + return false; +} + +// RelocateField - Patch relocatable field with 'Offset' in 'BO' +// using a 'Value' of known 'Size' +void ELFWriter::RelocateField(BinaryObject &BO, uint32_t Offset, + int64_t Value, unsigned Size) { + if (Size == 32) + BO.fixWord32(Value, Offset); + else if (Size == 64) + BO.fixWord64(Value, Offset); + else + llvm_unreachable("don't know howto patch relocatable field"); +} + +/// EmitRelocations - Emit relocations +void ELFWriter::EmitRelocations() { + + // True if the target uses the relocation entry to hold the addend, + // otherwise the addend is written directly to the relocatable field. + bool HasRelA = TEW->hasRelocationAddend(); + + // Create Relocation sections for each section which needs it. + for (unsigned i=0, e=SectionList.size(); i != e; ++i) { + ELFSection &S = *SectionList[i]; + + // This section does not have relocations + if (!S.hasRelocations()) continue; + ELFSection &RelSec = getRelocSection(S); + + // 'Link' - Section hdr idx of the associated symbol table + // 'Info' - Section hdr idx of the section to which the relocation applies + ELFSection &SymTab = getSymbolTableSection(); + RelSec.Link = SymTab.SectionIdx; + RelSec.Info = S.SectionIdx; + RelSec.EntSize = TEW->getRelocationEntrySize(); + + // Get the relocations from Section + std::vector Relos = S.getRelocations(); + for (std::vector::iterator MRI = Relos.begin(), + MRE = Relos.end(); MRI != MRE; ++MRI) { + MachineRelocation &MR = *MRI; + + // Relocatable field offset from the section start + unsigned RelOffset = MR.getMachineCodeOffset(); + + // Symbol index in the symbol table + unsigned SymIdx = 0; + + // Target specific relocation field type and size + unsigned RelType = TEW->getRelocationType(MR.getRelocationType()); + unsigned RelTySize = TEW->getRelocationTySize(RelType); + int64_t Addend = 0; + + // There are several machine relocations types, and each one of + // them needs a different approach to retrieve the symbol table index. + if (MR.isGlobalValue()) { + const GlobalValue *G = MR.getGlobalValue(); + int64_t GlobalOffset = MR.getConstantVal(); + SymIdx = GblSymLookup[G]; + if (G->hasPrivateLinkage()) { + // If the target uses a section offset in the relocation: + // SymIdx + Addend = section sym for global + section offset + unsigned SectionIdx = PrivateSyms[SymIdx]->SectionIdx; + Addend = PrivateSyms[SymIdx]->Value + GlobalOffset; + SymIdx = SectionList[SectionIdx]->getSymbolTableIndex(); + } else { + Addend = TEW->getDefaultAddendForRelTy(RelType, GlobalOffset); + } + } else if (MR.isExternalSymbol()) { + const char *ExtSym = MR.getExternalSymbol(); + SymIdx = ExtSymLookup[ExtSym]; + Addend = TEW->getDefaultAddendForRelTy(RelType); + } else { + // Get the symbol index for the section symbol + unsigned SectionIdx = MR.getConstantVal(); + SymIdx = SectionList[SectionIdx]->getSymbolTableIndex(); + + // The symbol offset inside the section + int64_t SymOffset = (int64_t)MR.getResultPointer(); + + // For pc relative relocations where symbols are defined in the same + // section they are referenced, ignore the relocation entry and patch + // the relocatable field with the symbol offset directly. + if (S.SectionIdx == SectionIdx && TEW->isPCRelativeRel(RelType)) { + int64_t Value = TEW->computeRelocation(SymOffset, RelOffset, RelType); + RelocateField(S, RelOffset, Value, RelTySize); + continue; + } + + Addend = TEW->getDefaultAddendForRelTy(RelType, SymOffset); + } + + // The target without addend on the relocation symbol must be + // patched in the relocation place itself to contain the addend + // otherwise write zeros to make sure there is no garbage there + RelocateField(S, RelOffset, HasRelA ? 0 : Addend, RelTySize); + + // Get the relocation entry and emit to the relocation section + ELFRelocation Rel(RelOffset, SymIdx, RelType, HasRelA, Addend); + EmitRelocation(RelSec, Rel, HasRelA); + } + } +} + +/// EmitRelocation - Write relocation 'Rel' to the relocation section 'Rel' +void ELFWriter::EmitRelocation(BinaryObject &RelSec, ELFRelocation &Rel, + bool HasRelA) { + RelSec.emitWord(Rel.getOffset()); + RelSec.emitWord(Rel.getInfo(is64Bit)); + if (HasRelA) + RelSec.emitWord(Rel.getAddend()); +} + +/// EmitSymbol - Write symbol 'Sym' to the symbol table 'SymbolTable' +void ELFWriter::EmitSymbol(BinaryObject &SymbolTable, ELFSym &Sym) { + if (is64Bit) { + SymbolTable.emitWord32(Sym.NameIdx); + SymbolTable.emitByte(Sym.Info); + SymbolTable.emitByte(Sym.Other); + SymbolTable.emitWord16(Sym.SectionIdx); + SymbolTable.emitWord64(Sym.Value); + SymbolTable.emitWord64(Sym.Size); + } else { + SymbolTable.emitWord32(Sym.NameIdx); + SymbolTable.emitWord32(Sym.Value); + SymbolTable.emitWord32(Sym.Size); + SymbolTable.emitByte(Sym.Info); + SymbolTable.emitByte(Sym.Other); + SymbolTable.emitWord16(Sym.SectionIdx); + } +} + +/// EmitSectionHeader - Write section 'Section' header in 'SHdrTab' +/// Section Header Table +void ELFWriter::EmitSectionHeader(BinaryObject &SHdrTab, + const ELFSection &SHdr) { + SHdrTab.emitWord32(SHdr.NameIdx); + SHdrTab.emitWord32(SHdr.Type); + if (is64Bit) { + SHdrTab.emitWord64(SHdr.Flags); + SHdrTab.emitWord(SHdr.Addr); + SHdrTab.emitWord(SHdr.Offset); + SHdrTab.emitWord64(SHdr.Size); + SHdrTab.emitWord32(SHdr.Link); + SHdrTab.emitWord32(SHdr.Info); + SHdrTab.emitWord64(SHdr.Align); + SHdrTab.emitWord64(SHdr.EntSize); + } else { + SHdrTab.emitWord32(SHdr.Flags); + SHdrTab.emitWord(SHdr.Addr); + SHdrTab.emitWord(SHdr.Offset); + SHdrTab.emitWord32(SHdr.Size); + SHdrTab.emitWord32(SHdr.Link); + SHdrTab.emitWord32(SHdr.Info); + SHdrTab.emitWord32(SHdr.Align); + SHdrTab.emitWord32(SHdr.EntSize); + } +} + +/// EmitStringTable - If the current symbol table is non-empty, emit the string +/// table for it +void ELFWriter::EmitStringTable(const std::string &ModuleName) { + if (!SymbolList.size()) return; // Empty symbol table. + ELFSection &StrTab = getStringTableSection(); + + // Set the zero'th symbol to a null byte, as required. + StrTab.emitByte(0); + + // Walk on the symbol list and write symbol names into the string table. + unsigned Index = 1; + for (ELFSymIter I=SymbolList.begin(), E=SymbolList.end(); I != E; ++I) { + ELFSym &Sym = *(*I); + + std::string Name; + if (Sym.isGlobalValue()) + Name.append(Mang->getMangledName(Sym.getGlobalValue())); + else if (Sym.isExternalSym()) + Name.append(Sym.getExternalSymbol()); + else if (Sym.isFileType()) + Name.append(ModuleName); + + if (Name.empty()) { + Sym.NameIdx = 0; + } else { + Sym.NameIdx = Index; + StrTab.emitString(Name); + + // Keep track of the number of bytes emitted to this section. + Index += Name.size()+1; + } + } + assert(Index == StrTab.size()); + StrTab.Size = Index; +} + +// SortSymbols - On the symbol table local symbols must come before +// all other symbols with non-local bindings. The return value is +// the position of the first non local symbol. +unsigned ELFWriter::SortSymbols() { + unsigned FirstNonLocalSymbol; + std::vector LocalSyms, OtherSyms; + + for (ELFSymIter I=SymbolList.begin(), E=SymbolList.end(); I != E; ++I) { + if ((*I)->isLocalBind()) + LocalSyms.push_back(*I); + else + OtherSyms.push_back(*I); + } + SymbolList.clear(); + FirstNonLocalSymbol = LocalSyms.size(); + + for (unsigned i = 0; i < FirstNonLocalSymbol; ++i) + SymbolList.push_back(LocalSyms[i]); + + for (ELFSymIter I=OtherSyms.begin(), E=OtherSyms.end(); I != E; ++I) + SymbolList.push_back(*I); + + LocalSyms.clear(); + OtherSyms.clear(); + + return FirstNonLocalSymbol; +} + +/// EmitSymbolTable - Emit the symbol table itself. +void ELFWriter::EmitSymbolTable() { + if (!SymbolList.size()) return; // Empty symbol table. + + // Now that we have emitted the string table and know the offset into the + // string table of each symbol, emit the symbol table itself. + ELFSection &SymTab = getSymbolTableSection(); + SymTab.Align = TEW->getPrefELFAlignment(); + + // Section Index of .strtab. + SymTab.Link = getStringTableSection().SectionIdx; + + // Size of each symtab entry. + SymTab.EntSize = TEW->getSymTabEntrySize(); + + // Reorder the symbol table with local symbols first! + unsigned FirstNonLocalSymbol = SortSymbols(); + + // Emit all the symbols to the symbol table. + for (unsigned i = 0, e = SymbolList.size(); i < e; ++i) { + ELFSym &Sym = *SymbolList[i]; + + // Emit symbol to the symbol table + EmitSymbol(SymTab, Sym); + + // Record the symbol table index for each symbol + if (Sym.isGlobalValue()) + GblSymLookup[Sym.getGlobalValue()] = i; + else if (Sym.isExternalSym()) + ExtSymLookup[Sym.getExternalSymbol()] = i; + + // Keep track on the symbol index into the symbol table + Sym.SymTabIdx = i; + } + + // One greater than the symbol table index of the last local symbol + SymTab.Info = FirstNonLocalSymbol; + SymTab.Size = SymTab.size(); +} + +/// EmitSectionTableStringTable - This method adds and emits a section for the +/// ELF Section Table string table: the string table that holds all of the +/// section names. +void ELFWriter::EmitSectionTableStringTable() { + // First step: add the section for the string table to the list of sections: + ELFSection &SHStrTab = getSectionHeaderStringTableSection(); + + // Now that we know which section number is the .shstrtab section, update the + // e_shstrndx entry in the ELF header. + ElfHdr.fixWord16(SHStrTab.SectionIdx, ELFHdr_e_shstrndx_Offset); + + // Set the NameIdx of each section in the string table and emit the bytes for + // the string table. + unsigned Index = 0; + + for (ELFSectionIter I=SectionList.begin(), E=SectionList.end(); I != E; ++I) { + ELFSection &S = *(*I); + // Set the index into the table. Note if we have lots of entries with + // common suffixes, we could memoize them here if we cared. + S.NameIdx = Index; + SHStrTab.emitString(S.getName()); + + // Keep track of the number of bytes emitted to this section. + Index += S.getName().size()+1; + } + + // Set the size of .shstrtab now that we know what it is. + assert(Index == SHStrTab.size()); + SHStrTab.Size = Index; +} + +/// OutputSectionsAndSectionTable - Now that we have constructed the file header +/// and all of the sections, emit these to the ostream destination and emit the +/// SectionTable. +void ELFWriter::OutputSectionsAndSectionTable() { + // Pass #1: Compute the file offset for each section. + size_t FileOff = ElfHdr.size(); // File header first. + + // Adjust alignment of all section if needed, skip the null section. + for (unsigned i=1, e=SectionList.size(); i < e; ++i) { + ELFSection &ES = *SectionList[i]; + if (!ES.size()) { + ES.Offset = FileOff; + continue; + } + + // Update Section size + if (!ES.Size) + ES.Size = ES.size(); + + // Align FileOff to whatever the alignment restrictions of the section are. + if (ES.Align) + FileOff = (FileOff+ES.Align-1) & ~(ES.Align-1); + + ES.Offset = FileOff; + FileOff += ES.Size; + } + + // Align Section Header. + unsigned TableAlign = TEW->getPrefELFAlignment(); + FileOff = (FileOff+TableAlign-1) & ~(TableAlign-1); + + // Now that we know where all of the sections will be emitted, set the e_shnum + // entry in the ELF header. + ElfHdr.fixWord16(NumSections, ELFHdr_e_shnum_Offset); + + // Now that we know the offset in the file of the section table, update the + // e_shoff address in the ELF header. + ElfHdr.fixWord(FileOff, ELFHdr_e_shoff_Offset); + + // Now that we know all of the data in the file header, emit it and all of the + // sections! + O.write((char *)&ElfHdr.getData()[0], ElfHdr.size()); + FileOff = ElfHdr.size(); + + // Section Header Table blob + BinaryObject SHdrTable(isLittleEndian, is64Bit); + + // Emit all of sections to the file and build the section header table. + for (ELFSectionIter I=SectionList.begin(), E=SectionList.end(); I != E; ++I) { + ELFSection &S = *(*I); + DEBUG(errs() << "SectionIdx: " << S.SectionIdx << ", Name: " << S.getName() + << ", Size: " << S.Size << ", Offset: " << S.Offset + << ", SectionData Size: " << S.size() << "\n"); + + // Align FileOff to whatever the alignment restrictions of the section are. + if (S.size()) { + if (S.Align) { + for (size_t NewFileOff = (FileOff+S.Align-1) & ~(S.Align-1); + FileOff != NewFileOff; ++FileOff) + O << (char)0xAB; + } + O.write((char *)&S.getData()[0], S.Size); + FileOff += S.Size; + } + + EmitSectionHeader(SHdrTable, S); + } + + // Align output for the section table. + for (size_t NewFileOff = (FileOff+TableAlign-1) & ~(TableAlign-1); + FileOff != NewFileOff; ++FileOff) + O << (char)0xAB; + + // Emit the section table itself. + O.write((char *)&SHdrTable.getData()[0], SHdrTable.size()); +} diff --git a/libclamav/c++/llvm/lib/CodeGen/ELFWriter.h b/libclamav/c++/llvm/lib/CodeGen/ELFWriter.h new file mode 100644 index 000000000..b61b4848b --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/ELFWriter.h @@ -0,0 +1,250 @@ +//===-- ELFWriter.h - Target-independent ELF writer support -----*- 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 the ELFWriter class. +// +//===----------------------------------------------------------------------===// + +#ifndef ELFWRITER_H +#define ELFWRITER_H + +#include "llvm/ADT/SetVector.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include + +namespace llvm { + class BinaryObject; + class Constant; + class ConstantInt; + class ConstantStruct; + class ELFCodeEmitter; + class ELFRelocation; + class ELFSection; + struct ELFSym; + class GlobalVariable; + class JITDebugRegisterer; + class Mangler; + class MachineCodeEmitter; + class MachineConstantPoolEntry; + class ObjectCodeEmitter; + class MCAsmInfo; + class TargetELFWriterInfo; + class TargetLoweringObjectFile; + class raw_ostream; + class SectionKind; + class MCContext; + + typedef std::vector::iterator ELFSymIter; + typedef std::vector::iterator ELFSectionIter; + typedef SetVector::const_iterator PendingGblsIter; + typedef SetVector::const_iterator PendingExtsIter; + typedef std::pair CstExprResTy; + + /// ELFWriter - This class implements the common target-independent code for + /// writing ELF files. Targets should derive a class from this to + /// parameterize the output format. + /// + class ELFWriter : public MachineFunctionPass { + friend class ELFCodeEmitter; + friend class JITDebugRegisterer; + public: + static char ID; + + /// Return the ELFCodeEmitter as an instance of ObjectCodeEmitter + ObjectCodeEmitter *getObjectCodeEmitter() { + return reinterpret_cast(ElfCE); + } + + ELFWriter(raw_ostream &O, TargetMachine &TM); + ~ELFWriter(); + + protected: + /// Output stream to send the resultant object file to. + raw_ostream &O; + + /// Target machine description. + TargetMachine &TM; + + /// Context object for machine code objects. + MCContext &OutContext; + + /// Target Elf Writer description. + const TargetELFWriterInfo *TEW; + + /// Mang - The object used to perform name mangling for this module. + Mangler *Mang; + + /// MCE - The MachineCodeEmitter object that we are exposing to emit machine + /// code for functions to the .o file. + ELFCodeEmitter *ElfCE; + + /// TLOF - Target Lowering Object File, provide section names for globals + /// and other object file specific stuff + const TargetLoweringObjectFile &TLOF; + + /// MAI - Target Asm Info, provide information about section names for + /// globals and other target specific stuff. + const MCAsmInfo *MAI; + + //===------------------------------------------------------------------===// + // Properties inferred automatically from the target machine. + //===------------------------------------------------------------------===// + + /// is64Bit/isLittleEndian - This information is inferred from the target + /// machine directly, indicating whether to emit a 32- or 64-bit ELF file. + bool is64Bit, isLittleEndian; + + /// doInitialization - Emit the file header and all of the global variables + /// for the module to the ELF file. + bool doInitialization(Module &M); + bool runOnMachineFunction(MachineFunction &MF); + + /// doFinalization - Now that the module has been completely processed, emit + /// the ELF file to 'O'. + bool doFinalization(Module &M); + + private: + /// Blob containing the Elf header + BinaryObject ElfHdr; + + /// SectionList - This is the list of sections that we have emitted to the + /// file. Once the file has been completely built, the section header table + /// is constructed from this info. + std::vector SectionList; + unsigned NumSections; // Always = SectionList.size() + + /// SectionLookup - This is a mapping from section name to section number in + /// the SectionList. Used to quickly gather the Section Index from MAI names + std::map SectionLookup; + + /// PendingGlobals - Globals not processed as symbols yet. + SetVector PendingGlobals; + + /// GblSymLookup - This is a mapping from global value to a symbol index + /// in the symbol table or private symbols list. This is useful since reloc + /// symbol references must be quickly mapped to their indices on the lists. + std::map GblSymLookup; + + /// PendingExternals - Externals not processed as symbols yet. + SetVector PendingExternals; + + /// ExtSymLookup - This is a mapping from externals to a symbol index + /// in the symbol table list. This is useful since reloc symbol references + /// must be quickly mapped to their symbol table indices. + std::map ExtSymLookup; + + /// SymbolList - This is the list of symbols emitted to the symbol table. + /// When the SymbolList is finally built, local symbols must be placed in + /// the beginning while non-locals at the end. + std::vector SymbolList; + + /// PrivateSyms - Record private symbols, every symbol here must never be + /// present in the SymbolList. + std::vector PrivateSyms; + + /// getSection - Return the section with the specified name, creating a new + /// section if one does not already exist. + ELFSection &getSection(const std::string &Name, unsigned Type, + unsigned Flags = 0, unsigned Align = 0) { + ELFSection *&SN = SectionLookup[Name]; + if (SN) return *SN; + + SectionList.push_back(new ELFSection(Name, isLittleEndian, is64Bit)); + SN = SectionList.back(); + SN->SectionIdx = NumSections++; + SN->Type = Type; + SN->Flags = Flags; + SN->Link = ELFSection::SHN_UNDEF; + SN->Align = Align; + return *SN; + } + + ELFSection &getNonExecStackSection() { + return getSection(".note.GNU-stack", ELFSection::SHT_PROGBITS, 0, 1); + } + + ELFSection &getSymbolTableSection() { + return getSection(".symtab", ELFSection::SHT_SYMTAB, 0); + } + + ELFSection &getStringTableSection() { + return getSection(".strtab", ELFSection::SHT_STRTAB, 0, 1); + } + + ELFSection &getSectionHeaderStringTableSection() { + return getSection(".shstrtab", ELFSection::SHT_STRTAB, 0, 1); + } + + ELFSection &getNullSection() { + return getSection("", ELFSection::SHT_NULL, 0); + } + + ELFSection &getDataSection(); + ELFSection &getBSSSection(); + ELFSection &getCtorSection(); + ELFSection &getDtorSection(); + ELFSection &getJumpTableSection(); + ELFSection &getConstantPoolSection(MachineConstantPoolEntry &CPE); + ELFSection &getTextSection(Function *F); + ELFSection &getRelocSection(ELFSection &S); + + // Helpers for obtaining ELF specific info. + unsigned getGlobalELFBinding(const GlobalValue *GV); + unsigned getGlobalELFType(const GlobalValue *GV); + unsigned getGlobalELFVisibility(const GlobalValue *GV); + + // AddPendingGlobalSymbol - Add a global to be processed and to + // the global symbol lookup, use a zero index because the table + // index will be determined later. + void AddPendingGlobalSymbol(const GlobalValue *GV, + bool AddToLookup = false); + + // AddPendingExternalSymbol - Add the external to be processed + // and to the external symbol lookup, use a zero index because + // the symbol table index will be determined later. + void AddPendingExternalSymbol(const char *External); + + // AddToSymbolList - Update the symbol lookup and If the symbol is + // private add it to PrivateSyms list, otherwise to SymbolList. + void AddToSymbolList(ELFSym *GblSym); + + // As we complete the ELF file, we need to update fields in the ELF header + // (e.g. the location of the section table). These members keep track of + // the offset in ELFHeader of these various pieces to update and other + // locations in the file. + unsigned ELFHdr_e_shoff_Offset; // e_shoff in ELF header. + unsigned ELFHdr_e_shstrndx_Offset; // e_shstrndx in ELF header. + unsigned ELFHdr_e_shnum_Offset; // e_shnum in ELF header. + + private: + void EmitGlobal(const GlobalValue *GV); + void EmitGlobalConstant(const Constant *C, ELFSection &GblS); + void EmitGlobalConstantStruct(const ConstantStruct *CVS, + ELFSection &GblS); + void EmitGlobalConstantLargeInt(const ConstantInt *CI, ELFSection &S); + void EmitGlobalDataRelocation(const GlobalValue *GV, unsigned Size, + ELFSection &GblS, int64_t Offset = 0); + bool EmitSpecialLLVMGlobal(const GlobalVariable *GV); + void EmitXXStructorList(Constant *List, ELFSection &Xtor); + void EmitRelocations(); + void EmitRelocation(BinaryObject &RelSec, ELFRelocation &Rel, bool HasRelA); + void EmitSectionHeader(BinaryObject &SHdrTab, const ELFSection &SHdr); + void EmitSectionTableStringTable(); + void EmitSymbol(BinaryObject &SymbolTable, ELFSym &Sym); + void EmitSymbolTable(); + void EmitStringTable(const std::string &ModuleName); + void OutputSectionsAndSectionTable(); + void RelocateField(BinaryObject &BO, uint32_t Offset, int64_t Value, + unsigned Size); + unsigned SortSymbols(); + CstExprResTy ResolveConstantExpr(const Constant *CV); + }; +} + +#endif diff --git a/libclamav/c++/llvm/lib/CodeGen/ExactHazardRecognizer.cpp b/libclamav/c++/llvm/lib/CodeGen/ExactHazardRecognizer.cpp new file mode 100644 index 000000000..36925b1ff --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/ExactHazardRecognizer.cpp @@ -0,0 +1,161 @@ +//===----- ExactHazardRecognizer.cpp - hazard recognizer -------- ---------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This implements a a hazard recognizer using the instructions itineraries +// defined for the current target. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "post-RA-sched" +#include "ExactHazardRecognizer.h" +#include "llvm/CodeGen/ScheduleHazardRecognizer.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Target/TargetInstrItineraries.h" + +using namespace llvm; + +ExactHazardRecognizer:: +ExactHazardRecognizer(const InstrItineraryData &LItinData) : + ScheduleHazardRecognizer(), ItinData(LItinData) +{ + // Determine the maximum depth of any itinerary. This determines the + // depth of the scoreboard. We always make the scoreboard at least 1 + // cycle deep to avoid dealing with the boundary condition. + ScoreboardDepth = 1; + if (!ItinData.isEmpty()) { + for (unsigned idx = 0; ; ++idx) { + if (ItinData.isEndMarker(idx)) + break; + + const InstrStage *IS = ItinData.beginStage(idx); + const InstrStage *E = ItinData.endStage(idx); + unsigned ItinDepth = 0; + for (; IS != E; ++IS) + ItinDepth += IS->getCycles(); + + ScoreboardDepth = std::max(ScoreboardDepth, ItinDepth); + } + } + + Scoreboard = new unsigned[ScoreboardDepth]; + ScoreboardHead = 0; + + DEBUG(errs() << "Using exact hazard recognizer: ScoreboardDepth = " + << ScoreboardDepth << '\n'); +} + +ExactHazardRecognizer::~ExactHazardRecognizer() { + delete [] Scoreboard; +} + +void ExactHazardRecognizer::Reset() { + memset(Scoreboard, 0, ScoreboardDepth * sizeof(unsigned)); + ScoreboardHead = 0; +} + +unsigned ExactHazardRecognizer::getFutureIndex(unsigned offset) { + return (ScoreboardHead + offset) % ScoreboardDepth; +} + +void ExactHazardRecognizer::dumpScoreboard() { + errs() << "Scoreboard:\n"; + + unsigned last = ScoreboardDepth - 1; + while ((last > 0) && (Scoreboard[getFutureIndex(last)] == 0)) + last--; + + for (unsigned i = 0; i <= last; i++) { + unsigned FUs = Scoreboard[getFutureIndex(i)]; + errs() << "\t"; + for (int j = 31; j >= 0; j--) + errs() << ((FUs & (1 << j)) ? '1' : '0'); + errs() << '\n'; + } +} + +ExactHazardRecognizer::HazardType ExactHazardRecognizer::getHazardType(SUnit *SU) { + if (ItinData.isEmpty()) + return NoHazard; + + unsigned cycle = 0; + + // Use the itinerary for the underlying instruction to check for + // free FU's in the scoreboard at the appropriate future cycles. + unsigned idx = SU->getInstr()->getDesc().getSchedClass(); + for (const InstrStage *IS = ItinData.beginStage(idx), + *E = ItinData.endStage(idx); IS != E; ++IS) { + // We must find one of the stage's units free for every cycle the + // stage is occupied. FIXME it would be more accurate to find the + // same unit free in all the cycles. + for (unsigned int i = 0; i < IS->getCycles(); ++i) { + assert(((cycle + i) < ScoreboardDepth) && + "Scoreboard depth exceeded!"); + + unsigned index = getFutureIndex(cycle + i); + unsigned freeUnits = IS->getUnits() & ~Scoreboard[index]; + if (!freeUnits) { + DEBUG(errs() << "*** Hazard in cycle " << (cycle + i) << ", "); + DEBUG(errs() << "SU(" << SU->NodeNum << "): "); + DEBUG(SU->getInstr()->dump()); + return Hazard; + } + } + + // Advance the cycle to the next stage. + cycle += IS->getNextCycles(); + } + + return NoHazard; +} + +void ExactHazardRecognizer::EmitInstruction(SUnit *SU) { + if (ItinData.isEmpty()) + return; + + unsigned cycle = 0; + + // Use the itinerary for the underlying instruction to reserve FU's + // in the scoreboard at the appropriate future cycles. + unsigned idx = SU->getInstr()->getDesc().getSchedClass(); + for (const InstrStage *IS = ItinData.beginStage(idx), + *E = ItinData.endStage(idx); IS != E; ++IS) { + // We must reserve one of the stage's units for every cycle the + // stage is occupied. FIXME it would be more accurate to reserve + // the same unit free in all the cycles. + for (unsigned int i = 0; i < IS->getCycles(); ++i) { + assert(((cycle + i) < ScoreboardDepth) && + "Scoreboard depth exceeded!"); + + unsigned index = getFutureIndex(cycle + i); + unsigned freeUnits = IS->getUnits() & ~Scoreboard[index]; + + // reduce to a single unit + unsigned freeUnit = 0; + do { + freeUnit = freeUnits; + freeUnits = freeUnit & (freeUnit - 1); + } while (freeUnits); + + assert(freeUnit && "No function unit available!"); + Scoreboard[index] |= freeUnit; + } + + // Advance the cycle to the next stage. + cycle += IS->getNextCycles(); + } + + DEBUG(dumpScoreboard()); +} + +void ExactHazardRecognizer::AdvanceCycle() { + Scoreboard[ScoreboardHead] = 0; + ScoreboardHead = getFutureIndex(1); +} diff --git a/libclamav/c++/llvm/lib/CodeGen/ExactHazardRecognizer.h b/libclamav/c++/llvm/lib/CodeGen/ExactHazardRecognizer.h new file mode 100644 index 000000000..71ac979e6 --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/ExactHazardRecognizer.h @@ -0,0 +1,61 @@ +//=- llvm/CodeGen/ExactHazardRecognizer.h - Scheduling Support -*- 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 the ExactHazardRecognizer class, which +// implements hazard-avoidance heuristics for scheduling, based on the +// scheduling itineraries specified for the target. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_EXACTHAZARDRECOGNIZER_H +#define LLVM_CODEGEN_EXACTHAZARDRECOGNIZER_H + +#include "llvm/CodeGen/ScheduleHazardRecognizer.h" +#include "llvm/CodeGen/ScheduleDAG.h" +#include "llvm/Target/TargetInstrItineraries.h" + +namespace llvm { + class ExactHazardRecognizer : public ScheduleHazardRecognizer { + // Itinerary data for the target. + const InstrItineraryData &ItinData; + + // Scoreboard to track function unit usage. Scoreboard[0] is a + // mask of the FUs in use in the cycle currently being + // schedule. Scoreboard[1] is a mask for the next cycle. The + // Scoreboard is used as a circular buffer with the current cycle + // indicated by ScoreboardHead. + unsigned *Scoreboard; + + // The maximum number of cycles monitored by the Scoreboard. This + // value is determined based on the target itineraries to ensure + // that all hazards can be tracked. + unsigned ScoreboardDepth; + + // Indices into the Scoreboard that represent the current cycle. + unsigned ScoreboardHead; + + // Return the scoreboard index to use for 'offset' cycles in the + // future. 'offset' of 0 returns ScoreboardHead. + unsigned getFutureIndex(unsigned offset); + + // Print the scoreboard. + void dumpScoreboard(); + + public: + ExactHazardRecognizer(const InstrItineraryData &ItinData); + ~ExactHazardRecognizer(); + + virtual HazardType getHazardType(SUnit *SU); + virtual void Reset(); + virtual void EmitInstruction(SUnit *SU); + virtual void AdvanceCycle(); + }; +} + +#endif diff --git a/libclamav/c++/llvm/lib/CodeGen/GCMetadata.cpp b/libclamav/c++/llvm/lib/CodeGen/GCMetadata.cpp new file mode 100644 index 000000000..4d25dccff --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/GCMetadata.cpp @@ -0,0 +1,209 @@ +//===-- GCMetadata.cpp - Garbage collector metadata -----------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the GCFunctionInfo class and GCModuleInfo pass. +// +//===----------------------------------------------------------------------===// + +#include "llvm/CodeGen/GCMetadata.h" +#include "llvm/CodeGen/GCStrategy.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/Pass.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/Function.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +namespace { + + class Printer : public FunctionPass { + static char ID; + raw_ostream &OS; + + public: + Printer() : FunctionPass(&ID), OS(errs()) {} + explicit Printer(raw_ostream &OS) : FunctionPass(&ID), OS(OS) {} + + + const char *getPassName() const; + void getAnalysisUsage(AnalysisUsage &AU) const; + + bool runOnFunction(Function &F); + }; + + class Deleter : public FunctionPass { + static char ID; + + public: + Deleter(); + + const char *getPassName() const; + void getAnalysisUsage(AnalysisUsage &AU) const; + + bool runOnFunction(Function &F); + bool doFinalization(Module &M); + }; + +} + +static RegisterPass +X("collector-metadata", "Create Garbage Collector Module Metadata"); + +// ----------------------------------------------------------------------------- + +GCFunctionInfo::GCFunctionInfo(const Function &F, GCStrategy &S) + : F(F), S(S), FrameSize(~0LL) {} + +GCFunctionInfo::~GCFunctionInfo() {} + +// ----------------------------------------------------------------------------- + +char GCModuleInfo::ID = 0; + +GCModuleInfo::GCModuleInfo() + : ImmutablePass(&ID) {} + +GCModuleInfo::~GCModuleInfo() { + clear(); +} + +GCStrategy *GCModuleInfo::getOrCreateStrategy(const Module *M, + const std::string &Name) { + strategy_map_type::iterator NMI = StrategyMap.find(Name); + if (NMI != StrategyMap.end()) + return NMI->getValue(); + + for (GCRegistry::iterator I = GCRegistry::begin(), + E = GCRegistry::end(); I != E; ++I) { + if (Name == I->getName()) { + GCStrategy *S = I->instantiate(); + S->M = M; + S->Name = Name; + StrategyMap.GetOrCreateValue(Name).setValue(S); + StrategyList.push_back(S); + return S; + } + } + + errs() << "unsupported GC: " << Name << "\n"; + llvm_unreachable(0); +} + +GCFunctionInfo &GCModuleInfo::getFunctionInfo(const Function &F) { + assert(!F.isDeclaration() && "Can only get GCFunctionInfo for a definition!"); + assert(F.hasGC()); + + finfo_map_type::iterator I = FInfoMap.find(&F); + if (I != FInfoMap.end()) + return *I->second; + + GCStrategy *S = getOrCreateStrategy(F.getParent(), F.getGC()); + GCFunctionInfo *GFI = S->insertFunctionInfo(F); + FInfoMap[&F] = GFI; + return *GFI; +} + +void GCModuleInfo::clear() { + FInfoMap.clear(); + StrategyMap.clear(); + + for (iterator I = begin(), E = end(); I != E; ++I) + delete *I; + StrategyList.clear(); +} + +// ----------------------------------------------------------------------------- + +char Printer::ID = 0; + +FunctionPass *llvm::createGCInfoPrinter(raw_ostream &OS) { + return new Printer(OS); +} + + +const char *Printer::getPassName() const { + return "Print Garbage Collector Information"; +} + +void Printer::getAnalysisUsage(AnalysisUsage &AU) const { + FunctionPass::getAnalysisUsage(AU); + AU.setPreservesAll(); + AU.addRequired(); +} + +static const char *DescKind(GC::PointKind Kind) { + switch (Kind) { + default: llvm_unreachable("Unknown GC point kind"); + case GC::Loop: return "loop"; + case GC::Return: return "return"; + case GC::PreCall: return "pre-call"; + case GC::PostCall: return "post-call"; + } +} + +bool Printer::runOnFunction(Function &F) { + if (!F.hasGC()) { + GCFunctionInfo *FD = &getAnalysis().getFunctionInfo(F); + + OS << "GC roots for " << FD->getFunction().getNameStr() << ":\n"; + for (GCFunctionInfo::roots_iterator RI = FD->roots_begin(), + RE = FD->roots_end(); RI != RE; ++RI) + OS << "\t" << RI->Num << "\t" << RI->StackOffset << "[sp]\n"; + + OS << "GC safe points for " << FD->getFunction().getNameStr() << ":\n"; + for (GCFunctionInfo::iterator PI = FD->begin(), + PE = FD->end(); PI != PE; ++PI) { + + OS << "\tlabel " << PI->Num << ": " << DescKind(PI->Kind) << ", live = {"; + + for (GCFunctionInfo::live_iterator RI = FD->live_begin(PI), + RE = FD->live_end(PI);;) { + OS << " " << RI->Num; + if (++RI == RE) + break; + OS << ","; + } + + OS << " }\n"; + } + } + + return false; +} + +// ----------------------------------------------------------------------------- + +char Deleter::ID = 0; + +FunctionPass *llvm::createGCInfoDeleter() { + return new Deleter(); +} + +Deleter::Deleter() : FunctionPass(&ID) {} + +const char *Deleter::getPassName() const { + return "Delete Garbage Collector Information"; +} + +void Deleter::getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + AU.addRequired(); +} + +bool Deleter::runOnFunction(Function &MF) { + return false; +} + +bool Deleter::doFinalization(Module &M) { + GCModuleInfo *GMI = getAnalysisIfAvailable(); + assert(GMI && "Deleter didn't require GCModuleInfo?!"); + GMI->clear(); + return false; +} diff --git a/libclamav/c++/llvm/lib/CodeGen/GCMetadataPrinter.cpp b/libclamav/c++/llvm/lib/CodeGen/GCMetadataPrinter.cpp new file mode 100644 index 000000000..9cd2925e2 --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/GCMetadataPrinter.cpp @@ -0,0 +1,30 @@ +//===-- GCMetadataPrinter.cpp - Garbage collection infrastructure ---------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the abstract base class GCMetadataPrinter. +// +//===----------------------------------------------------------------------===// + +#include "llvm/CodeGen/GCMetadataPrinter.h" + +using namespace llvm; + +GCMetadataPrinter::GCMetadataPrinter() { } + +GCMetadataPrinter::~GCMetadataPrinter() { } + +void GCMetadataPrinter::beginAssembly(raw_ostream &OS, AsmPrinter &AP, + const MCAsmInfo &MAI) { + // Default is no action. +} + +void GCMetadataPrinter::finishAssembly(raw_ostream &OS, AsmPrinter &AP, + const MCAsmInfo &MAI) { + // Default is no action. +} diff --git a/libclamav/c++/llvm/lib/CodeGen/GCStrategy.cpp b/libclamav/c++/llvm/lib/CodeGen/GCStrategy.cpp new file mode 100644 index 000000000..6e0bde636 --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/GCStrategy.cpp @@ -0,0 +1,398 @@ +//===-- GCStrategy.cpp - Garbage collection infrastructure -----------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements target- and collector-independent garbage collection +// infrastructure. +// +// MachineCodeAnalysis identifies the GC safe points in the machine code. Roots +// are identified in SelectionDAGISel. +// +//===----------------------------------------------------------------------===// + +#include "llvm/CodeGen/GCStrategy.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/IntrinsicInst.h" +#include "llvm/Module.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/Target/TargetFrameInfo.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" + +using namespace llvm; + +namespace { + + /// LowerIntrinsics - This pass rewrites calls to the llvm.gcread or + /// llvm.gcwrite intrinsics, replacing them with simple loads and stores as + /// directed by the GCStrategy. It also performs automatic root initialization + /// and custom intrinsic lowering. + class LowerIntrinsics : public FunctionPass { + static bool NeedsDefaultLoweringPass(const GCStrategy &C); + static bool NeedsCustomLoweringPass(const GCStrategy &C); + static bool CouldBecomeSafePoint(Instruction *I); + bool PerformDefaultLowering(Function &F, GCStrategy &Coll); + static bool InsertRootInitializers(Function &F, + AllocaInst **Roots, unsigned Count); + + public: + static char ID; + + LowerIntrinsics(); + const char *getPassName() const; + void getAnalysisUsage(AnalysisUsage &AU) const; + + bool doInitialization(Module &M); + bool runOnFunction(Function &F); + }; + + + /// MachineCodeAnalysis - This is a target-independent pass over the machine + /// function representation to identify safe points for the garbage collector + /// in the machine code. It inserts labels at safe points and populates a + /// GCMetadata record for each function. + class MachineCodeAnalysis : public MachineFunctionPass { + const TargetMachine *TM; + GCFunctionInfo *FI; + MachineModuleInfo *MMI; + const TargetInstrInfo *TII; + + void FindSafePoints(MachineFunction &MF); + void VisitCallPoint(MachineBasicBlock::iterator MI); + unsigned InsertLabel(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + DebugLoc DL) const; + + void FindStackOffsets(MachineFunction &MF); + + public: + static char ID; + + MachineCodeAnalysis(); + const char *getPassName() const; + void getAnalysisUsage(AnalysisUsage &AU) const; + + bool runOnMachineFunction(MachineFunction &MF); + }; + +} + +// ----------------------------------------------------------------------------- + +GCStrategy::GCStrategy() : + NeededSafePoints(0), + CustomReadBarriers(false), + CustomWriteBarriers(false), + CustomRoots(false), + InitRoots(true), + UsesMetadata(false) +{} + +GCStrategy::~GCStrategy() { + for (iterator I = begin(), E = end(); I != E; ++I) + delete *I; + + Functions.clear(); +} + +bool GCStrategy::initializeCustomLowering(Module &M) { return false; } + +bool GCStrategy::performCustomLowering(Function &F) { + errs() << "gc " << getName() << " must override performCustomLowering.\n"; + llvm_unreachable(0); + return 0; +} + +GCFunctionInfo *GCStrategy::insertFunctionInfo(const Function &F) { + GCFunctionInfo *FI = new GCFunctionInfo(F, *this); + Functions.push_back(FI); + return FI; +} + +// ----------------------------------------------------------------------------- + +FunctionPass *llvm::createGCLoweringPass() { + return new LowerIntrinsics(); +} + +char LowerIntrinsics::ID = 0; + +LowerIntrinsics::LowerIntrinsics() + : FunctionPass(&ID) {} + +const char *LowerIntrinsics::getPassName() const { + return "Lower Garbage Collection Instructions"; +} + +void LowerIntrinsics::getAnalysisUsage(AnalysisUsage &AU) const { + FunctionPass::getAnalysisUsage(AU); + AU.addRequired(); +} + +/// doInitialization - If this module uses the GC intrinsics, find them now. +bool LowerIntrinsics::doInitialization(Module &M) { + // FIXME: This is rather antisocial in the context of a JIT since it performs + // work against the entire module. But this cannot be done at + // runFunction time (initializeCustomLowering likely needs to change + // the module). + GCModuleInfo *MI = getAnalysisIfAvailable(); + assert(MI && "LowerIntrinsics didn't require GCModuleInfo!?"); + for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) + if (!I->isDeclaration() && I->hasGC()) + MI->getFunctionInfo(*I); // Instantiate the GC strategy. + + bool MadeChange = false; + for (GCModuleInfo::iterator I = MI->begin(), E = MI->end(); I != E; ++I) + if (NeedsCustomLoweringPass(**I)) + if ((*I)->initializeCustomLowering(M)) + MadeChange = true; + + return MadeChange; +} + +bool LowerIntrinsics::InsertRootInitializers(Function &F, AllocaInst **Roots, + unsigned Count) { + // Scroll past alloca instructions. + BasicBlock::iterator IP = F.getEntryBlock().begin(); + while (isa(IP)) ++IP; + + // Search for initializers in the initial BB. + SmallPtrSet InitedRoots; + for (; !CouldBecomeSafePoint(IP); ++IP) + if (StoreInst *SI = dyn_cast(IP)) + if (AllocaInst *AI = + dyn_cast(SI->getOperand(1)->stripPointerCasts())) + InitedRoots.insert(AI); + + // Add root initializers. + bool MadeChange = false; + + for (AllocaInst **I = Roots, **E = Roots + Count; I != E; ++I) + if (!InitedRoots.count(*I)) { + new StoreInst(ConstantPointerNull::get(cast( + cast((*I)->getType())->getElementType())), + *I, IP); + MadeChange = true; + } + + return MadeChange; +} + +bool LowerIntrinsics::NeedsDefaultLoweringPass(const GCStrategy &C) { + // Default lowering is necessary only if read or write barriers have a default + // action. The default for roots is no action. + return !C.customWriteBarrier() + || !C.customReadBarrier() + || C.initializeRoots(); +} + +bool LowerIntrinsics::NeedsCustomLoweringPass(const GCStrategy &C) { + // Custom lowering is only necessary if enabled for some action. + return C.customWriteBarrier() + || C.customReadBarrier() + || C.customRoots(); +} + +/// CouldBecomeSafePoint - Predicate to conservatively determine whether the +/// instruction could introduce a safe point. +bool LowerIntrinsics::CouldBecomeSafePoint(Instruction *I) { + // The natural definition of instructions which could introduce safe points + // are: + // + // - call, invoke (AfterCall, BeforeCall) + // - phis (Loops) + // - invoke, ret, unwind (Exit) + // + // However, instructions as seemingly inoccuous as arithmetic can become + // libcalls upon lowering (e.g., div i64 on a 32-bit platform), so instead + // it is necessary to take a conservative approach. + + if (isa(I) || isa(I) || + isa(I) || isa(I)) + return false; + + // llvm.gcroot is safe because it doesn't do anything at runtime. + if (CallInst *CI = dyn_cast(I)) + if (Function *F = CI->getCalledFunction()) + if (unsigned IID = F->getIntrinsicID()) + if (IID == Intrinsic::gcroot) + return false; + + return true; +} + +/// runOnFunction - Replace gcread/gcwrite intrinsics with loads and stores. +/// Leave gcroot intrinsics; the code generator needs to see those. +bool LowerIntrinsics::runOnFunction(Function &F) { + // Quick exit for functions that do not use GC. + if (!F.hasGC()) + return false; + + GCFunctionInfo &FI = getAnalysis().getFunctionInfo(F); + GCStrategy &S = FI.getStrategy(); + + bool MadeChange = false; + + if (NeedsDefaultLoweringPass(S)) + MadeChange |= PerformDefaultLowering(F, S); + + if (NeedsCustomLoweringPass(S)) + MadeChange |= S.performCustomLowering(F); + + return MadeChange; +} + +bool LowerIntrinsics::PerformDefaultLowering(Function &F, GCStrategy &S) { + bool LowerWr = !S.customWriteBarrier(); + bool LowerRd = !S.customReadBarrier(); + bool InitRoots = S.initializeRoots(); + + SmallVector Roots; + + bool MadeChange = false; + for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB) { + for (BasicBlock::iterator II = BB->begin(), E = BB->end(); II != E;) { + if (IntrinsicInst *CI = dyn_cast(II++)) { + Function *F = CI->getCalledFunction(); + switch (F->getIntrinsicID()) { + case Intrinsic::gcwrite: + if (LowerWr) { + // Replace a write barrier with a simple store. + Value *St = new StoreInst(CI->getOperand(1), CI->getOperand(3), CI); + CI->replaceAllUsesWith(St); + CI->eraseFromParent(); + } + break; + case Intrinsic::gcread: + if (LowerRd) { + // Replace a read barrier with a simple load. + Value *Ld = new LoadInst(CI->getOperand(2), "", CI); + Ld->takeName(CI); + CI->replaceAllUsesWith(Ld); + CI->eraseFromParent(); + } + break; + case Intrinsic::gcroot: + if (InitRoots) { + // Initialize the GC root, but do not delete the intrinsic. The + // backend needs the intrinsic to flag the stack slot. + Roots.push_back(cast( + CI->getOperand(1)->stripPointerCasts())); + } + break; + default: + continue; + } + + MadeChange = true; + } + } + } + + if (Roots.size()) + MadeChange |= InsertRootInitializers(F, Roots.begin(), Roots.size()); + + return MadeChange; +} + +// ----------------------------------------------------------------------------- + +FunctionPass *llvm::createGCMachineCodeAnalysisPass() { + return new MachineCodeAnalysis(); +} + +char MachineCodeAnalysis::ID = 0; + +MachineCodeAnalysis::MachineCodeAnalysis() + : MachineFunctionPass(&ID) {} + +const char *MachineCodeAnalysis::getPassName() const { + return "Analyze Machine Code For Garbage Collection"; +} + +void MachineCodeAnalysis::getAnalysisUsage(AnalysisUsage &AU) const { + MachineFunctionPass::getAnalysisUsage(AU); + AU.setPreservesAll(); + AU.addRequired(); + AU.addRequired(); +} + +unsigned MachineCodeAnalysis::InsertLabel(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + DebugLoc DL) const { + unsigned Label = MMI->NextLabelID(); + + BuildMI(MBB, MI, DL, + TII->get(TargetInstrInfo::GC_LABEL)).addImm(Label); + + return Label; +} + +void MachineCodeAnalysis::VisitCallPoint(MachineBasicBlock::iterator CI) { + // Find the return address (next instruction), too, so as to bracket the call + // instruction. + MachineBasicBlock::iterator RAI = CI; + ++RAI; + + if (FI->getStrategy().needsSafePoint(GC::PreCall)) + FI->addSafePoint(GC::PreCall, InsertLabel(*CI->getParent(), CI, + CI->getDebugLoc())); + + if (FI->getStrategy().needsSafePoint(GC::PostCall)) + FI->addSafePoint(GC::PostCall, InsertLabel(*CI->getParent(), RAI, + CI->getDebugLoc())); +} + +void MachineCodeAnalysis::FindSafePoints(MachineFunction &MF) { + for (MachineFunction::iterator BBI = MF.begin(), + BBE = MF.end(); BBI != BBE; ++BBI) + for (MachineBasicBlock::iterator MI = BBI->begin(), + ME = BBI->end(); MI != ME; ++MI) + if (MI->getDesc().isCall()) + VisitCallPoint(MI); +} + +void MachineCodeAnalysis::FindStackOffsets(MachineFunction &MF) { + const TargetRegisterInfo *TRI = TM->getRegisterInfo(); + assert(TRI && "TargetRegisterInfo not available!"); + + for (GCFunctionInfo::roots_iterator RI = FI->roots_begin(), + RE = FI->roots_end(); RI != RE; ++RI) + RI->StackOffset = TRI->getFrameIndexOffset(MF, RI->Num); +} + +bool MachineCodeAnalysis::runOnMachineFunction(MachineFunction &MF) { + // Quick exit for functions that do not use GC. + if (!MF.getFunction()->hasGC()) + return false; + + FI = &getAnalysis().getFunctionInfo(*MF.getFunction()); + if (!FI->getStrategy().needsSafePoints()) + return false; + + TM = &MF.getTarget(); + MMI = &getAnalysis(); + TII = TM->getInstrInfo(); + + // Find the size of the stack frame. + FI->setFrameSize(MF.getFrameInfo()->getStackSize()); + + // Find all safe points. + FindSafePoints(MF); + + // Find the stack offsets for all roots. + FindStackOffsets(MF); + + return false; +} diff --git a/libclamav/c++/llvm/lib/CodeGen/IfConversion.cpp b/libclamav/c++/llvm/lib/CodeGen/IfConversion.cpp new file mode 100644 index 000000000..c23d7070a --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/IfConversion.cpp @@ -0,0 +1,1254 @@ +//===-- IfConversion.cpp - Machine code if conversion pass. ---------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the machine instruction level if-conversion pass. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "ifcvt" +#include "BranchFolding.h" +#include "llvm/Function.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetLowering.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/ADT/DepthFirstIterator.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/ADT/STLExtras.h" +using namespace llvm; + +// Hidden options for help debugging. +static cl::opt IfCvtFnStart("ifcvt-fn-start", cl::init(-1), cl::Hidden); +static cl::opt IfCvtFnStop("ifcvt-fn-stop", cl::init(-1), cl::Hidden); +static cl::opt IfCvtLimit("ifcvt-limit", cl::init(-1), cl::Hidden); +static cl::opt DisableSimple("disable-ifcvt-simple", + cl::init(false), cl::Hidden); +static cl::opt DisableSimpleF("disable-ifcvt-simple-false", + cl::init(false), cl::Hidden); +static cl::opt DisableTriangle("disable-ifcvt-triangle", + cl::init(false), cl::Hidden); +static cl::opt DisableTriangleR("disable-ifcvt-triangle-rev", + cl::init(false), cl::Hidden); +static cl::opt DisableTriangleF("disable-ifcvt-triangle-false", + cl::init(false), cl::Hidden); +static cl::opt DisableTriangleFR("disable-ifcvt-triangle-false-rev", + cl::init(false), cl::Hidden); +static cl::opt DisableDiamond("disable-ifcvt-diamond", + cl::init(false), cl::Hidden); + +STATISTIC(NumSimple, "Number of simple if-conversions performed"); +STATISTIC(NumSimpleFalse, "Number of simple (F) if-conversions performed"); +STATISTIC(NumTriangle, "Number of triangle if-conversions performed"); +STATISTIC(NumTriangleRev, "Number of triangle (R) if-conversions performed"); +STATISTIC(NumTriangleFalse,"Number of triangle (F) if-conversions performed"); +STATISTIC(NumTriangleFRev, "Number of triangle (F/R) if-conversions performed"); +STATISTIC(NumDiamonds, "Number of diamond if-conversions performed"); +STATISTIC(NumIfConvBBs, "Number of if-converted blocks"); +STATISTIC(NumDupBBs, "Number of duplicated blocks"); + +namespace { + class IfConverter : public MachineFunctionPass { + enum IfcvtKind { + ICNotClassfied, // BB data valid, but not classified. + ICSimpleFalse, // Same as ICSimple, but on the false path. + ICSimple, // BB is entry of an one split, no rejoin sub-CFG. + ICTriangleFRev, // Same as ICTriangleFalse, but false path rev condition. + ICTriangleRev, // Same as ICTriangle, but true path rev condition. + ICTriangleFalse, // Same as ICTriangle, but on the false path. + ICTriangle, // BB is entry of a triangle sub-CFG. + ICDiamond // BB is entry of a diamond sub-CFG. + }; + + /// BBInfo - One per MachineBasicBlock, this is used to cache the result + /// if-conversion feasibility analysis. This includes results from + /// TargetInstrInfo::AnalyzeBranch() (i.e. TBB, FBB, and Cond), and its + /// classification, and common tail block of its successors (if it's a + /// diamond shape), its size, whether it's predicable, and whether any + /// instruction can clobber the 'would-be' predicate. + /// + /// IsDone - True if BB is not to be considered for ifcvt. + /// IsBeingAnalyzed - True if BB is currently being analyzed. + /// IsAnalyzed - True if BB has been analyzed (info is still valid). + /// IsEnqueued - True if BB has been enqueued to be ifcvt'ed. + /// IsBrAnalyzable - True if AnalyzeBranch() returns false. + /// HasFallThrough - True if BB may fallthrough to the following BB. + /// IsUnpredicable - True if BB is known to be unpredicable. + /// ClobbersPred - True if BB could modify predicates (e.g. has + /// cmp, call, etc.) + /// NonPredSize - Number of non-predicated instructions. + /// BB - Corresponding MachineBasicBlock. + /// TrueBB / FalseBB- See AnalyzeBranch(). + /// BrCond - Conditions for end of block conditional branches. + /// Predicate - Predicate used in the BB. + struct BBInfo { + bool IsDone : 1; + bool IsBeingAnalyzed : 1; + bool IsAnalyzed : 1; + bool IsEnqueued : 1; + bool IsBrAnalyzable : 1; + bool HasFallThrough : 1; + bool IsUnpredicable : 1; + bool CannotBeCopied : 1; + bool ClobbersPred : 1; + unsigned NonPredSize; + MachineBasicBlock *BB; + MachineBasicBlock *TrueBB; + MachineBasicBlock *FalseBB; + SmallVector BrCond; + SmallVector Predicate; + BBInfo() : IsDone(false), IsBeingAnalyzed(false), + IsAnalyzed(false), IsEnqueued(false), IsBrAnalyzable(false), + HasFallThrough(false), IsUnpredicable(false), + CannotBeCopied(false), ClobbersPred(false), NonPredSize(0), + BB(0), TrueBB(0), FalseBB(0) {} + }; + + /// IfcvtToken - Record information about pending if-conversions to attemp: + /// BBI - Corresponding BBInfo. + /// Kind - Type of block. See IfcvtKind. + /// NeedSubsumption - True if the to-be-predicated BB has already been + /// predicated. + /// NumDups - Number of instructions that would be duplicated due + /// to this if-conversion. (For diamonds, the number of + /// identical instructions at the beginnings of both + /// paths). + /// NumDups2 - For diamonds, the number of identical instructions + /// at the ends of both paths. + struct IfcvtToken { + BBInfo &BBI; + IfcvtKind Kind; + bool NeedSubsumption; + unsigned NumDups; + unsigned NumDups2; + IfcvtToken(BBInfo &b, IfcvtKind k, bool s, unsigned d, unsigned d2 = 0) + : BBI(b), Kind(k), NeedSubsumption(s), NumDups(d), NumDups2(d2) {} + }; + + /// Roots - Basic blocks that do not have successors. These are the starting + /// points of Graph traversal. + std::vector Roots; + + /// BBAnalysis - Results of if-conversion feasibility analysis indexed by + /// basic block number. + std::vector BBAnalysis; + + const TargetLowering *TLI; + const TargetInstrInfo *TII; + bool MadeChange; + int FnNum; + public: + static char ID; + IfConverter() : MachineFunctionPass(&ID), FnNum(-1) {} + + virtual bool runOnMachineFunction(MachineFunction &MF); + virtual const char *getPassName() const { return "If Converter"; } + + private: + bool ReverseBranchCondition(BBInfo &BBI); + bool ValidSimple(BBInfo &TrueBBI, unsigned &Dups) const; + bool ValidTriangle(BBInfo &TrueBBI, BBInfo &FalseBBI, + bool FalseBranch, unsigned &Dups) const; + bool ValidDiamond(BBInfo &TrueBBI, BBInfo &FalseBBI, + unsigned &Dups1, unsigned &Dups2) const; + void ScanInstructions(BBInfo &BBI); + BBInfo &AnalyzeBlock(MachineBasicBlock *BB, + std::vector &Tokens); + bool FeasibilityAnalysis(BBInfo &BBI, SmallVectorImpl &Cond, + bool isTriangle = false, bool RevBranch = false); + bool AnalyzeBlocks(MachineFunction &MF, + std::vector &Tokens); + void InvalidatePreds(MachineBasicBlock *BB); + void RemoveExtraEdges(BBInfo &BBI); + bool IfConvertSimple(BBInfo &BBI, IfcvtKind Kind); + bool IfConvertTriangle(BBInfo &BBI, IfcvtKind Kind); + bool IfConvertDiamond(BBInfo &BBI, IfcvtKind Kind, + unsigned NumDups1, unsigned NumDups2); + void PredicateBlock(BBInfo &BBI, + MachineBasicBlock::iterator E, + SmallVectorImpl &Cond); + void CopyAndPredicateBlock(BBInfo &ToBBI, BBInfo &FromBBI, + SmallVectorImpl &Cond, + bool IgnoreBr = false); + void MergeBlocks(BBInfo &ToBBI, BBInfo &FromBBI); + + bool MeetIfcvtSizeLimit(unsigned Size) const { + return Size > 0 && Size <= TLI->getIfCvtBlockSizeLimit(); + } + + // blockAlwaysFallThrough - Block ends without a terminator. + bool blockAlwaysFallThrough(BBInfo &BBI) const { + return BBI.IsBrAnalyzable && BBI.TrueBB == NULL; + } + + // IfcvtTokenCmp - Used to sort if-conversion candidates. + static bool IfcvtTokenCmp(IfcvtToken *C1, IfcvtToken *C2) { + int Incr1 = (C1->Kind == ICDiamond) + ? -(int)(C1->NumDups + C1->NumDups2) : (int)C1->NumDups; + int Incr2 = (C2->Kind == ICDiamond) + ? -(int)(C2->NumDups + C2->NumDups2) : (int)C2->NumDups; + if (Incr1 > Incr2) + return true; + else if (Incr1 == Incr2) { + // Favors subsumption. + if (C1->NeedSubsumption == false && C2->NeedSubsumption == true) + return true; + else if (C1->NeedSubsumption == C2->NeedSubsumption) { + // Favors diamond over triangle, etc. + if ((unsigned)C1->Kind < (unsigned)C2->Kind) + return true; + else if (C1->Kind == C2->Kind) + return C1->BBI.BB->getNumber() < C2->BBI.BB->getNumber(); + } + } + return false; + } + }; + + char IfConverter::ID = 0; +} + +static RegisterPass +X("if-converter", "If Converter"); + +FunctionPass *llvm::createIfConverterPass() { return new IfConverter(); } + +bool IfConverter::runOnMachineFunction(MachineFunction &MF) { + TLI = MF.getTarget().getTargetLowering(); + TII = MF.getTarget().getInstrInfo(); + if (!TII) return false; + + DEBUG(errs() << "\nIfcvt: function (" << ++FnNum << ") \'" + << MF.getFunction()->getName() << "\'"); + + if (FnNum < IfCvtFnStart || (IfCvtFnStop != -1 && FnNum > IfCvtFnStop)) { + DEBUG(errs() << " skipped\n"); + return false; + } + DEBUG(errs() << "\n"); + + MF.RenumberBlocks(); + BBAnalysis.resize(MF.getNumBlockIDs()); + + // Look for root nodes, i.e. blocks without successors. + for (MachineFunction::iterator I = MF.begin(), E = MF.end(); I != E; ++I) + if (I->succ_empty()) + Roots.push_back(I); + + std::vector Tokens; + MadeChange = false; + unsigned NumIfCvts = NumSimple + NumSimpleFalse + NumTriangle + + NumTriangleRev + NumTriangleFalse + NumTriangleFRev + NumDiamonds; + while (IfCvtLimit == -1 || (int)NumIfCvts < IfCvtLimit) { + // Do an initial analysis for each basic block and find all the potential + // candidates to perform if-conversion. + bool Change = AnalyzeBlocks(MF, Tokens); + while (!Tokens.empty()) { + IfcvtToken *Token = Tokens.back(); + Tokens.pop_back(); + BBInfo &BBI = Token->BBI; + IfcvtKind Kind = Token->Kind; + unsigned NumDups = Token->NumDups; + unsigned NumDups2 = Token->NumDups2; + + delete Token; + + // If the block has been evicted out of the queue or it has already been + // marked dead (due to it being predicated), then skip it. + if (BBI.IsDone) + BBI.IsEnqueued = false; + if (!BBI.IsEnqueued) + continue; + + BBI.IsEnqueued = false; + + bool RetVal = false; + switch (Kind) { + default: assert(false && "Unexpected!"); + break; + case ICSimple: + case ICSimpleFalse: { + bool isFalse = Kind == ICSimpleFalse; + if ((isFalse && DisableSimpleF) || (!isFalse && DisableSimple)) break; + DEBUG(errs() << "Ifcvt (Simple" << (Kind == ICSimpleFalse ? " false" :"") + << "): BB#" << BBI.BB->getNumber() << " (" + << ((Kind == ICSimpleFalse) + ? BBI.FalseBB->getNumber() + : BBI.TrueBB->getNumber()) << ") "); + RetVal = IfConvertSimple(BBI, Kind); + DEBUG(errs() << (RetVal ? "succeeded!" : "failed!") << "\n"); + if (RetVal) { + if (isFalse) NumSimpleFalse++; + else NumSimple++; + } + break; + } + case ICTriangle: + case ICTriangleRev: + case ICTriangleFalse: + case ICTriangleFRev: { + bool isFalse = Kind == ICTriangleFalse; + bool isRev = (Kind == ICTriangleRev || Kind == ICTriangleFRev); + if (DisableTriangle && !isFalse && !isRev) break; + if (DisableTriangleR && !isFalse && isRev) break; + if (DisableTriangleF && isFalse && !isRev) break; + if (DisableTriangleFR && isFalse && isRev) break; + DEBUG(errs() << "Ifcvt (Triangle"); + if (isFalse) + DEBUG(errs() << " false"); + if (isRev) + DEBUG(errs() << " rev"); + DEBUG(errs() << "): BB#" << BBI.BB->getNumber() << " (T:" + << BBI.TrueBB->getNumber() << ",F:" + << BBI.FalseBB->getNumber() << ") "); + RetVal = IfConvertTriangle(BBI, Kind); + DEBUG(errs() << (RetVal ? "succeeded!" : "failed!") << "\n"); + if (RetVal) { + if (isFalse) { + if (isRev) NumTriangleFRev++; + else NumTriangleFalse++; + } else { + if (isRev) NumTriangleRev++; + else NumTriangle++; + } + } + break; + } + case ICDiamond: { + if (DisableDiamond) break; + DEBUG(errs() << "Ifcvt (Diamond): BB#" << BBI.BB->getNumber() << " (T:" + << BBI.TrueBB->getNumber() << ",F:" + << BBI.FalseBB->getNumber() << ") "); + RetVal = IfConvertDiamond(BBI, Kind, NumDups, NumDups2); + DEBUG(errs() << (RetVal ? "succeeded!" : "failed!") << "\n"); + if (RetVal) NumDiamonds++; + break; + } + } + + Change |= RetVal; + + NumIfCvts = NumSimple + NumSimpleFalse + NumTriangle + NumTriangleRev + + NumTriangleFalse + NumTriangleFRev + NumDiamonds; + if (IfCvtLimit != -1 && (int)NumIfCvts >= IfCvtLimit) + break; + } + + if (!Change) + break; + MadeChange |= Change; + } + + // Delete tokens in case of early exit. + while (!Tokens.empty()) { + IfcvtToken *Token = Tokens.back(); + Tokens.pop_back(); + delete Token; + } + + Tokens.clear(); + Roots.clear(); + BBAnalysis.clear(); + + if (MadeChange) { + BranchFolder BF(false); + BF.OptimizeFunction(MF, TII, + MF.getTarget().getRegisterInfo(), + getAnalysisIfAvailable()); + } + + return MadeChange; +} + +/// findFalseBlock - BB has a fallthrough. Find its 'false' successor given +/// its 'true' successor. +static MachineBasicBlock *findFalseBlock(MachineBasicBlock *BB, + MachineBasicBlock *TrueBB) { + for (MachineBasicBlock::succ_iterator SI = BB->succ_begin(), + E = BB->succ_end(); SI != E; ++SI) { + MachineBasicBlock *SuccBB = *SI; + if (SuccBB != TrueBB) + return SuccBB; + } + return NULL; +} + +/// ReverseBranchCondition - Reverse the condition of the end of the block +/// branch. Swap block's 'true' and 'false' successors. +bool IfConverter::ReverseBranchCondition(BBInfo &BBI) { + if (!TII->ReverseBranchCondition(BBI.BrCond)) { + TII->RemoveBranch(*BBI.BB); + TII->InsertBranch(*BBI.BB, BBI.FalseBB, BBI.TrueBB, BBI.BrCond); + std::swap(BBI.TrueBB, BBI.FalseBB); + return true; + } + return false; +} + +/// getNextBlock - Returns the next block in the function blocks ordering. If +/// it is the end, returns NULL. +static inline MachineBasicBlock *getNextBlock(MachineBasicBlock *BB) { + MachineFunction::iterator I = BB; + MachineFunction::iterator E = BB->getParent()->end(); + if (++I == E) + return NULL; + return I; +} + +/// ValidSimple - Returns true if the 'true' block (along with its +/// predecessor) forms a valid simple shape for ifcvt. It also returns the +/// number of instructions that the ifcvt would need to duplicate if performed +/// in Dups. +bool IfConverter::ValidSimple(BBInfo &TrueBBI, unsigned &Dups) const { + Dups = 0; + if (TrueBBI.IsBeingAnalyzed || TrueBBI.IsDone) + return false; + + if (TrueBBI.IsBrAnalyzable) + return false; + + if (TrueBBI.BB->pred_size() > 1) { + if (TrueBBI.CannotBeCopied || + TrueBBI.NonPredSize > TLI->getIfCvtDupBlockSizeLimit()) + return false; + Dups = TrueBBI.NonPredSize; + } + + return true; +} + +/// ValidTriangle - Returns true if the 'true' and 'false' blocks (along +/// with their common predecessor) forms a valid triangle shape for ifcvt. +/// If 'FalseBranch' is true, it checks if 'true' block's false branch +/// branches to the false branch rather than the other way around. It also +/// returns the number of instructions that the ifcvt would need to duplicate +/// if performed in 'Dups'. +bool IfConverter::ValidTriangle(BBInfo &TrueBBI, BBInfo &FalseBBI, + bool FalseBranch, unsigned &Dups) const { + Dups = 0; + if (TrueBBI.IsBeingAnalyzed || TrueBBI.IsDone) + return false; + + if (TrueBBI.BB->pred_size() > 1) { + if (TrueBBI.CannotBeCopied) + return false; + + unsigned Size = TrueBBI.NonPredSize; + if (TrueBBI.IsBrAnalyzable) { + if (TrueBBI.TrueBB && TrueBBI.BrCond.empty()) + // Ends with an unconditional branch. It will be removed. + --Size; + else { + MachineBasicBlock *FExit = FalseBranch + ? TrueBBI.TrueBB : TrueBBI.FalseBB; + if (FExit) + // Require a conditional branch + ++Size; + } + } + if (Size > TLI->getIfCvtDupBlockSizeLimit()) + return false; + Dups = Size; + } + + MachineBasicBlock *TExit = FalseBranch ? TrueBBI.FalseBB : TrueBBI.TrueBB; + if (!TExit && blockAlwaysFallThrough(TrueBBI)) { + MachineFunction::iterator I = TrueBBI.BB; + if (++I == TrueBBI.BB->getParent()->end()) + return false; + TExit = I; + } + return TExit && TExit == FalseBBI.BB; +} + +static +MachineBasicBlock::iterator firstNonBranchInst(MachineBasicBlock *BB, + const TargetInstrInfo *TII) { + MachineBasicBlock::iterator I = BB->end(); + while (I != BB->begin()) { + --I; + if (!I->getDesc().isBranch()) + break; + } + return I; +} + +/// ValidDiamond - Returns true if the 'true' and 'false' blocks (along +/// with their common predecessor) forms a valid diamond shape for ifcvt. +bool IfConverter::ValidDiamond(BBInfo &TrueBBI, BBInfo &FalseBBI, + unsigned &Dups1, unsigned &Dups2) const { + Dups1 = Dups2 = 0; + if (TrueBBI.IsBeingAnalyzed || TrueBBI.IsDone || + FalseBBI.IsBeingAnalyzed || FalseBBI.IsDone) + return false; + + MachineBasicBlock *TT = TrueBBI.TrueBB; + MachineBasicBlock *FT = FalseBBI.TrueBB; + + if (!TT && blockAlwaysFallThrough(TrueBBI)) + TT = getNextBlock(TrueBBI.BB); + if (!FT && blockAlwaysFallThrough(FalseBBI)) + FT = getNextBlock(FalseBBI.BB); + if (TT != FT) + return false; + if (TT == NULL && (TrueBBI.IsBrAnalyzable || FalseBBI.IsBrAnalyzable)) + return false; + if (TrueBBI.BB->pred_size() > 1 || FalseBBI.BB->pred_size() > 1) + return false; + + // FIXME: Allow true block to have an early exit? + if (TrueBBI.FalseBB || FalseBBI.FalseBB || + (TrueBBI.ClobbersPred && FalseBBI.ClobbersPred)) + return false; + + MachineBasicBlock::iterator TI = TrueBBI.BB->begin(); + MachineBasicBlock::iterator FI = FalseBBI.BB->begin(); + while (TI != TrueBBI.BB->end() && FI != FalseBBI.BB->end()) { + if (!TI->isIdenticalTo(FI)) + break; + ++Dups1; + ++TI; + ++FI; + } + + TI = firstNonBranchInst(TrueBBI.BB, TII); + FI = firstNonBranchInst(FalseBBI.BB, TII); + while (TI != TrueBBI.BB->begin() && FI != FalseBBI.BB->begin()) { + if (!TI->isIdenticalTo(FI)) + break; + ++Dups2; + --TI; + --FI; + } + + return true; +} + +/// ScanInstructions - Scan all the instructions in the block to determine if +/// the block is predicable. In most cases, that means all the instructions +/// in the block are isPredicable(). Also checks if the block contains any +/// instruction which can clobber a predicate (e.g. condition code register). +/// If so, the block is not predicable unless it's the last instruction. +void IfConverter::ScanInstructions(BBInfo &BBI) { + if (BBI.IsDone) + return; + + bool AlreadyPredicated = BBI.Predicate.size() > 0; + // First analyze the end of BB branches. + BBI.TrueBB = BBI.FalseBB = NULL; + BBI.BrCond.clear(); + BBI.IsBrAnalyzable = + !TII->AnalyzeBranch(*BBI.BB, BBI.TrueBB, BBI.FalseBB, BBI.BrCond); + BBI.HasFallThrough = BBI.IsBrAnalyzable && BBI.FalseBB == NULL; + + if (BBI.BrCond.size()) { + // No false branch. This BB must end with a conditional branch and a + // fallthrough. + if (!BBI.FalseBB) + BBI.FalseBB = findFalseBlock(BBI.BB, BBI.TrueBB); + if (!BBI.FalseBB) { + // Malformed bcc? True and false blocks are the same? + BBI.IsUnpredicable = true; + return; + } + } + + // Then scan all the instructions. + BBI.NonPredSize = 0; + BBI.ClobbersPred = false; + for (MachineBasicBlock::iterator I = BBI.BB->begin(), E = BBI.BB->end(); + I != E; ++I) { + const TargetInstrDesc &TID = I->getDesc(); + if (TID.isNotDuplicable()) + BBI.CannotBeCopied = true; + + bool isPredicated = TII->isPredicated(I); + bool isCondBr = BBI.IsBrAnalyzable && TID.isConditionalBranch(); + + if (!isCondBr) { + if (!isPredicated) + BBI.NonPredSize++; + else if (!AlreadyPredicated) { + // FIXME: This instruction is already predicated before the + // if-conversion pass. It's probably something like a conditional move. + // Mark this block unpredicable for now. + BBI.IsUnpredicable = true; + return; + } + } + + if (BBI.ClobbersPred && !isPredicated) { + // Predicate modification instruction should end the block (except for + // already predicated instructions and end of block branches). + if (isCondBr) { + // A conditional branch is not predicable, but it may be eliminated. + continue; + } + + // Predicate may have been modified, the subsequent (currently) + // unpredicated instructions cannot be correctly predicated. + BBI.IsUnpredicable = true; + return; + } + + // FIXME: Make use of PredDefs? e.g. ADDC, SUBC sets predicates but are + // still potentially predicable. + std::vector PredDefs; + if (TII->DefinesPredicate(I, PredDefs)) + BBI.ClobbersPred = true; + + if (!TII->isPredicable(I)) { + BBI.IsUnpredicable = true; + return; + } + } +} + +/// FeasibilityAnalysis - Determine if the block is a suitable candidate to be +/// predicated by the specified predicate. +bool IfConverter::FeasibilityAnalysis(BBInfo &BBI, + SmallVectorImpl &Pred, + bool isTriangle, bool RevBranch) { + // If the block is dead or unpredicable, then it cannot be predicated. + if (BBI.IsDone || BBI.IsUnpredicable) + return false; + + // If it is already predicated, check if its predicate subsumes the new + // predicate. + if (BBI.Predicate.size() && !TII->SubsumesPredicate(BBI.Predicate, Pred)) + return false; + + if (BBI.BrCond.size()) { + if (!isTriangle) + return false; + + // Test predicate subsumption. + SmallVector RevPred(Pred.begin(), Pred.end()); + SmallVector Cond(BBI.BrCond.begin(), BBI.BrCond.end()); + if (RevBranch) { + if (TII->ReverseBranchCondition(Cond)) + return false; + } + if (TII->ReverseBranchCondition(RevPred) || + !TII->SubsumesPredicate(Cond, RevPred)) + return false; + } + + return true; +} + +/// AnalyzeBlock - Analyze the structure of the sub-CFG starting from +/// the specified block. Record its successors and whether it looks like an +/// if-conversion candidate. +IfConverter::BBInfo &IfConverter::AnalyzeBlock(MachineBasicBlock *BB, + std::vector &Tokens) { + BBInfo &BBI = BBAnalysis[BB->getNumber()]; + + if (BBI.IsAnalyzed || BBI.IsBeingAnalyzed) + return BBI; + + BBI.BB = BB; + BBI.IsBeingAnalyzed = true; + + ScanInstructions(BBI); + + // Unanalyzable or ends with fallthrough or unconditional branch. + if (!BBI.IsBrAnalyzable || BBI.BrCond.empty()) { + BBI.IsBeingAnalyzed = false; + BBI.IsAnalyzed = true; + return BBI; + } + + // Do not ifcvt if either path is a back edge to the entry block. + if (BBI.TrueBB == BB || BBI.FalseBB == BB) { + BBI.IsBeingAnalyzed = false; + BBI.IsAnalyzed = true; + return BBI; + } + + // Do not ifcvt if true and false fallthrough blocks are the same. + if (!BBI.FalseBB) { + BBI.IsBeingAnalyzed = false; + BBI.IsAnalyzed = true; + return BBI; + } + + BBInfo &TrueBBI = AnalyzeBlock(BBI.TrueBB, Tokens); + BBInfo &FalseBBI = AnalyzeBlock(BBI.FalseBB, Tokens); + + if (TrueBBI.IsDone && FalseBBI.IsDone) { + BBI.IsBeingAnalyzed = false; + BBI.IsAnalyzed = true; + return BBI; + } + + SmallVector RevCond(BBI.BrCond.begin(), BBI.BrCond.end()); + bool CanRevCond = !TII->ReverseBranchCondition(RevCond); + + unsigned Dups = 0; + unsigned Dups2 = 0; + bool TNeedSub = TrueBBI.Predicate.size() > 0; + bool FNeedSub = FalseBBI.Predicate.size() > 0; + bool Enqueued = false; + if (CanRevCond && ValidDiamond(TrueBBI, FalseBBI, Dups, Dups2) && + MeetIfcvtSizeLimit(TrueBBI.NonPredSize - (Dups + Dups2)) && + MeetIfcvtSizeLimit(FalseBBI.NonPredSize - (Dups + Dups2)) && + FeasibilityAnalysis(TrueBBI, BBI.BrCond) && + FeasibilityAnalysis(FalseBBI, RevCond)) { + // Diamond: + // EBB + // / \_ + // | | + // TBB FBB + // \ / + // TailBB + // Note TailBB can be empty. + Tokens.push_back(new IfcvtToken(BBI, ICDiamond, TNeedSub|FNeedSub, Dups, + Dups2)); + Enqueued = true; + } + + if (ValidTriangle(TrueBBI, FalseBBI, false, Dups) && + MeetIfcvtSizeLimit(TrueBBI.NonPredSize) && + FeasibilityAnalysis(TrueBBI, BBI.BrCond, true)) { + // Triangle: + // EBB + // | \_ + // | | + // | TBB + // | / + // FBB + Tokens.push_back(new IfcvtToken(BBI, ICTriangle, TNeedSub, Dups)); + Enqueued = true; + } + + if (ValidTriangle(TrueBBI, FalseBBI, true, Dups) && + MeetIfcvtSizeLimit(TrueBBI.NonPredSize) && + FeasibilityAnalysis(TrueBBI, BBI.BrCond, true, true)) { + Tokens.push_back(new IfcvtToken(BBI, ICTriangleRev, TNeedSub, Dups)); + Enqueued = true; + } + + if (ValidSimple(TrueBBI, Dups) && + MeetIfcvtSizeLimit(TrueBBI.NonPredSize) && + FeasibilityAnalysis(TrueBBI, BBI.BrCond)) { + // Simple (split, no rejoin): + // EBB + // | \_ + // | | + // | TBB---> exit + // | + // FBB + Tokens.push_back(new IfcvtToken(BBI, ICSimple, TNeedSub, Dups)); + Enqueued = true; + } + + if (CanRevCond) { + // Try the other path... + if (ValidTriangle(FalseBBI, TrueBBI, false, Dups) && + MeetIfcvtSizeLimit(FalseBBI.NonPredSize) && + FeasibilityAnalysis(FalseBBI, RevCond, true)) { + Tokens.push_back(new IfcvtToken(BBI, ICTriangleFalse, FNeedSub, Dups)); + Enqueued = true; + } + + if (ValidTriangle(FalseBBI, TrueBBI, true, Dups) && + MeetIfcvtSizeLimit(FalseBBI.NonPredSize) && + FeasibilityAnalysis(FalseBBI, RevCond, true, true)) { + Tokens.push_back(new IfcvtToken(BBI, ICTriangleFRev, FNeedSub, Dups)); + Enqueued = true; + } + + if (ValidSimple(FalseBBI, Dups) && + MeetIfcvtSizeLimit(FalseBBI.NonPredSize) && + FeasibilityAnalysis(FalseBBI, RevCond)) { + Tokens.push_back(new IfcvtToken(BBI, ICSimpleFalse, FNeedSub, Dups)); + Enqueued = true; + } + } + + BBI.IsEnqueued = Enqueued; + BBI.IsBeingAnalyzed = false; + BBI.IsAnalyzed = true; + return BBI; +} + +/// AnalyzeBlocks - Analyze all blocks and find entries for all if-conversion +/// candidates. It returns true if any CFG restructuring is done to expose more +/// if-conversion opportunities. +bool IfConverter::AnalyzeBlocks(MachineFunction &MF, + std::vector &Tokens) { + bool Change = false; + std::set Visited; + for (unsigned i = 0, e = Roots.size(); i != e; ++i) { + for (idf_ext_iterator I=idf_ext_begin(Roots[i],Visited), + E = idf_ext_end(Roots[i], Visited); I != E; ++I) { + MachineBasicBlock *BB = *I; + AnalyzeBlock(BB, Tokens); + } + } + + // Sort to favor more complex ifcvt scheme. + std::stable_sort(Tokens.begin(), Tokens.end(), IfcvtTokenCmp); + + return Change; +} + +/// canFallThroughTo - Returns true either if ToBB is the next block after BB or +/// that all the intervening blocks are empty (given BB can fall through to its +/// next block). +static bool canFallThroughTo(MachineBasicBlock *BB, MachineBasicBlock *ToBB) { + MachineFunction::iterator I = BB; + MachineFunction::iterator TI = ToBB; + MachineFunction::iterator E = BB->getParent()->end(); + while (++I != TI) + if (I == E || !I->empty()) + return false; + return true; +} + +/// InvalidatePreds - Invalidate predecessor BB info so it would be re-analyzed +/// to determine if it can be if-converted. If predecessor is already enqueued, +/// dequeue it! +void IfConverter::InvalidatePreds(MachineBasicBlock *BB) { + for (MachineBasicBlock::pred_iterator PI = BB->pred_begin(), + E = BB->pred_end(); PI != E; ++PI) { + BBInfo &PBBI = BBAnalysis[(*PI)->getNumber()]; + if (PBBI.IsDone || PBBI.BB == BB) + continue; + PBBI.IsAnalyzed = false; + PBBI.IsEnqueued = false; + } +} + +/// InsertUncondBranch - Inserts an unconditional branch from BB to ToBB. +/// +static void InsertUncondBranch(MachineBasicBlock *BB, MachineBasicBlock *ToBB, + const TargetInstrInfo *TII) { + SmallVector NoCond; + TII->InsertBranch(*BB, ToBB, NULL, NoCond); +} + +/// RemoveExtraEdges - Remove true / false edges if either / both are no longer +/// successors. +void IfConverter::RemoveExtraEdges(BBInfo &BBI) { + MachineBasicBlock *TBB = NULL, *FBB = NULL; + SmallVector Cond; + if (!TII->AnalyzeBranch(*BBI.BB, TBB, FBB, Cond)) + BBI.BB->CorrectExtraCFGEdges(TBB, FBB, !Cond.empty()); +} + +/// IfConvertSimple - If convert a simple (split, no rejoin) sub-CFG. +/// +bool IfConverter::IfConvertSimple(BBInfo &BBI, IfcvtKind Kind) { + BBInfo &TrueBBI = BBAnalysis[BBI.TrueBB->getNumber()]; + BBInfo &FalseBBI = BBAnalysis[BBI.FalseBB->getNumber()]; + BBInfo *CvtBBI = &TrueBBI; + BBInfo *NextBBI = &FalseBBI; + + SmallVector Cond(BBI.BrCond.begin(), BBI.BrCond.end()); + if (Kind == ICSimpleFalse) + std::swap(CvtBBI, NextBBI); + + if (CvtBBI->IsDone || + (CvtBBI->CannotBeCopied && CvtBBI->BB->pred_size() > 1)) { + // Something has changed. It's no longer safe to predicate this block. + BBI.IsAnalyzed = false; + CvtBBI->IsAnalyzed = false; + return false; + } + + if (Kind == ICSimpleFalse) + if (TII->ReverseBranchCondition(Cond)) + assert(false && "Unable to reverse branch condition!"); + + if (CvtBBI->BB->pred_size() > 1) { + BBI.NonPredSize -= TII->RemoveBranch(*BBI.BB); + // Copy instructions in the true block, predicate them, and add them to + // the entry block. + CopyAndPredicateBlock(BBI, *CvtBBI, Cond); + } else { + PredicateBlock(*CvtBBI, CvtBBI->BB->end(), Cond); + + // Merge converted block into entry block. + BBI.NonPredSize -= TII->RemoveBranch(*BBI.BB); + MergeBlocks(BBI, *CvtBBI); + } + + bool IterIfcvt = true; + if (!canFallThroughTo(BBI.BB, NextBBI->BB)) { + InsertUncondBranch(BBI.BB, NextBBI->BB, TII); + BBI.HasFallThrough = false; + // Now ifcvt'd block will look like this: + // BB: + // ... + // t, f = cmp + // if t op + // b BBf + // + // We cannot further ifcvt this block because the unconditional branch + // will have to be predicated on the new condition, that will not be + // available if cmp executes. + IterIfcvt = false; + } + + RemoveExtraEdges(BBI); + + // Update block info. BB can be iteratively if-converted. + if (!IterIfcvt) + BBI.IsDone = true; + InvalidatePreds(BBI.BB); + CvtBBI->IsDone = true; + + // FIXME: Must maintain LiveIns. + return true; +} + +/// IfConvertTriangle - If convert a triangle sub-CFG. +/// +bool IfConverter::IfConvertTriangle(BBInfo &BBI, IfcvtKind Kind) { + BBInfo &TrueBBI = BBAnalysis[BBI.TrueBB->getNumber()]; + BBInfo &FalseBBI = BBAnalysis[BBI.FalseBB->getNumber()]; + BBInfo *CvtBBI = &TrueBBI; + BBInfo *NextBBI = &FalseBBI; + + SmallVector Cond(BBI.BrCond.begin(), BBI.BrCond.end()); + if (Kind == ICTriangleFalse || Kind == ICTriangleFRev) + std::swap(CvtBBI, NextBBI); + + if (CvtBBI->IsDone || + (CvtBBI->CannotBeCopied && CvtBBI->BB->pred_size() > 1)) { + // Something has changed. It's no longer safe to predicate this block. + BBI.IsAnalyzed = false; + CvtBBI->IsAnalyzed = false; + return false; + } + + if (Kind == ICTriangleFalse || Kind == ICTriangleFRev) + if (TII->ReverseBranchCondition(Cond)) + assert(false && "Unable to reverse branch condition!"); + + if (Kind == ICTriangleRev || Kind == ICTriangleFRev) { + if (ReverseBranchCondition(*CvtBBI)) { + // BB has been changed, modify its predecessors (except for this + // one) so they don't get ifcvt'ed based on bad intel. + for (MachineBasicBlock::pred_iterator PI = CvtBBI->BB->pred_begin(), + E = CvtBBI->BB->pred_end(); PI != E; ++PI) { + MachineBasicBlock *PBB = *PI; + if (PBB == BBI.BB) + continue; + BBInfo &PBBI = BBAnalysis[PBB->getNumber()]; + if (PBBI.IsEnqueued) { + PBBI.IsAnalyzed = false; + PBBI.IsEnqueued = false; + } + } + } + } + + bool HasEarlyExit = CvtBBI->FalseBB != NULL; + bool DupBB = CvtBBI->BB->pred_size() > 1; + if (DupBB) { + BBI.NonPredSize -= TII->RemoveBranch(*BBI.BB); + // Copy instructions in the true block, predicate them, and add them to + // the entry block. + CopyAndPredicateBlock(BBI, *CvtBBI, Cond, true); + } else { + // Predicate the 'true' block after removing its branch. + CvtBBI->NonPredSize -= TII->RemoveBranch(*CvtBBI->BB); + PredicateBlock(*CvtBBI, CvtBBI->BB->end(), Cond); + + // Now merge the entry of the triangle with the true block. + BBI.NonPredSize -= TII->RemoveBranch(*BBI.BB); + MergeBlocks(BBI, *CvtBBI); + } + + // If 'true' block has a 'false' successor, add an exit branch to it. + if (HasEarlyExit) { + SmallVector RevCond(CvtBBI->BrCond.begin(), + CvtBBI->BrCond.end()); + if (TII->ReverseBranchCondition(RevCond)) + assert(false && "Unable to reverse branch condition!"); + TII->InsertBranch(*BBI.BB, CvtBBI->FalseBB, NULL, RevCond); + BBI.BB->addSuccessor(CvtBBI->FalseBB); + } + + // Merge in the 'false' block if the 'false' block has no other + // predecessors. Otherwise, add an unconditional branch to 'false'. + bool FalseBBDead = false; + bool IterIfcvt = true; + bool isFallThrough = canFallThroughTo(BBI.BB, NextBBI->BB); + if (!isFallThrough) { + // Only merge them if the true block does not fallthrough to the false + // block. By not merging them, we make it possible to iteratively + // ifcvt the blocks. + if (!HasEarlyExit && + NextBBI->BB->pred_size() == 1 && !NextBBI->HasFallThrough) { + MergeBlocks(BBI, *NextBBI); + FalseBBDead = true; + } else { + InsertUncondBranch(BBI.BB, NextBBI->BB, TII); + BBI.HasFallThrough = false; + } + // Mixed predicated and unpredicated code. This cannot be iteratively + // predicated. + IterIfcvt = false; + } + + RemoveExtraEdges(BBI); + + // Update block info. BB can be iteratively if-converted. + if (!IterIfcvt) + BBI.IsDone = true; + InvalidatePreds(BBI.BB); + CvtBBI->IsDone = true; + if (FalseBBDead) + NextBBI->IsDone = true; + + // FIXME: Must maintain LiveIns. + return true; +} + +/// IfConvertDiamond - If convert a diamond sub-CFG. +/// +bool IfConverter::IfConvertDiamond(BBInfo &BBI, IfcvtKind Kind, + unsigned NumDups1, unsigned NumDups2) { + BBInfo &TrueBBI = BBAnalysis[BBI.TrueBB->getNumber()]; + BBInfo &FalseBBI = BBAnalysis[BBI.FalseBB->getNumber()]; + MachineBasicBlock *TailBB = TrueBBI.TrueBB; + // True block must fall through or end with an unanalyzable terminator. + if (!TailBB) { + if (blockAlwaysFallThrough(TrueBBI)) + TailBB = FalseBBI.TrueBB; + assert((TailBB || !TrueBBI.IsBrAnalyzable) && "Unexpected!"); + } + + if (TrueBBI.IsDone || FalseBBI.IsDone || + TrueBBI.BB->pred_size() > 1 || + FalseBBI.BB->pred_size() > 1) { + // Something has changed. It's no longer safe to predicate these blocks. + BBI.IsAnalyzed = false; + TrueBBI.IsAnalyzed = false; + FalseBBI.IsAnalyzed = false; + return false; + } + + // Merge the 'true' and 'false' blocks by copying the instructions + // from the 'false' block to the 'true' block. That is, unless the true + // block would clobber the predicate, in that case, do the opposite. + BBInfo *BBI1 = &TrueBBI; + BBInfo *BBI2 = &FalseBBI; + SmallVector RevCond(BBI.BrCond.begin(), BBI.BrCond.end()); + if (TII->ReverseBranchCondition(RevCond)) + assert(false && "Unable to reverse branch condition!"); + SmallVector *Cond1 = &BBI.BrCond; + SmallVector *Cond2 = &RevCond; + + // Figure out the more profitable ordering. + bool DoSwap = false; + if (TrueBBI.ClobbersPred && !FalseBBI.ClobbersPred) + DoSwap = true; + else if (TrueBBI.ClobbersPred == FalseBBI.ClobbersPred) { + if (TrueBBI.NonPredSize > FalseBBI.NonPredSize) + DoSwap = true; + } + if (DoSwap) { + std::swap(BBI1, BBI2); + std::swap(Cond1, Cond2); + } + + // Remove the conditional branch from entry to the blocks. + BBI.NonPredSize -= TII->RemoveBranch(*BBI.BB); + + // Remove the duplicated instructions at the beginnings of both paths. + MachineBasicBlock::iterator DI1 = BBI1->BB->begin(); + MachineBasicBlock::iterator DI2 = BBI2->BB->begin(); + BBI1->NonPredSize -= NumDups1; + BBI2->NonPredSize -= NumDups1; + while (NumDups1 != 0) { + ++DI1; + ++DI2; + --NumDups1; + } + BBI.BB->splice(BBI.BB->end(), BBI1->BB, BBI1->BB->begin(), DI1); + BBI2->BB->erase(BBI2->BB->begin(), DI2); + + // Predicate the 'true' block after removing its branch. + BBI1->NonPredSize -= TII->RemoveBranch(*BBI1->BB); + DI1 = BBI1->BB->end(); + for (unsigned i = 0; i != NumDups2; ++i) + --DI1; + BBI1->BB->erase(DI1, BBI1->BB->end()); + PredicateBlock(*BBI1, BBI1->BB->end(), *Cond1); + + // Predicate the 'false' block. + BBI2->NonPredSize -= TII->RemoveBranch(*BBI2->BB); + DI2 = BBI2->BB->end(); + while (NumDups2 != 0) { + --DI2; + --NumDups2; + } + PredicateBlock(*BBI2, DI2, *Cond2); + + // Merge the true block into the entry of the diamond. + MergeBlocks(BBI, *BBI1); + MergeBlocks(BBI, *BBI2); + + // If the if-converted block falls through or unconditionally branches into + // the tail block, and the tail block does not have other predecessors, then + // fold the tail block in as well. Otherwise, unless it falls through to the + // tail, add a unconditional branch to it. + if (TailBB) { + BBInfo TailBBI = BBAnalysis[TailBB->getNumber()]; + if (TailBB->pred_size() == 1 && !TailBBI.HasFallThrough) { + BBI.NonPredSize -= TII->RemoveBranch(*BBI.BB); + MergeBlocks(BBI, TailBBI); + TailBBI.IsDone = true; + } else { + InsertUncondBranch(BBI.BB, TailBB, TII); + BBI.HasFallThrough = false; + } + } + + RemoveExtraEdges(BBI); + + // Update block info. + BBI.IsDone = TrueBBI.IsDone = FalseBBI.IsDone = true; + InvalidatePreds(BBI.BB); + + // FIXME: Must maintain LiveIns. + return true; +} + +/// PredicateBlock - Predicate instructions from the start of the block to the +/// specified end with the specified condition. +void IfConverter::PredicateBlock(BBInfo &BBI, + MachineBasicBlock::iterator E, + SmallVectorImpl &Cond) { + for (MachineBasicBlock::iterator I = BBI.BB->begin(); I != E; ++I) { + if (TII->isPredicated(I)) + continue; + if (!TII->PredicateInstruction(I, Cond)) { +#ifndef NDEBUG + errs() << "Unable to predicate " << *I << "!\n"; +#endif + llvm_unreachable(0); + } + } + + std::copy(Cond.begin(), Cond.end(), std::back_inserter(BBI.Predicate)); + + BBI.IsAnalyzed = false; + BBI.NonPredSize = 0; + + NumIfConvBBs++; +} + +/// CopyAndPredicateBlock - Copy and predicate instructions from source BB to +/// the destination block. Skip end of block branches if IgnoreBr is true. +void IfConverter::CopyAndPredicateBlock(BBInfo &ToBBI, BBInfo &FromBBI, + SmallVectorImpl &Cond, + bool IgnoreBr) { + MachineFunction &MF = *ToBBI.BB->getParent(); + + for (MachineBasicBlock::iterator I = FromBBI.BB->begin(), + E = FromBBI.BB->end(); I != E; ++I) { + const TargetInstrDesc &TID = I->getDesc(); + bool isPredicated = TII->isPredicated(I); + // Do not copy the end of the block branches. + if (IgnoreBr && !isPredicated && TID.isBranch()) + break; + + MachineInstr *MI = MF.CloneMachineInstr(I); + ToBBI.BB->insert(ToBBI.BB->end(), MI); + ToBBI.NonPredSize++; + + if (!isPredicated) + if (!TII->PredicateInstruction(MI, Cond)) { +#ifndef NDEBUG + errs() << "Unable to predicate " << *I << "!\n"; +#endif + llvm_unreachable(0); + } + } + + std::vector Succs(FromBBI.BB->succ_begin(), + FromBBI.BB->succ_end()); + MachineBasicBlock *NBB = getNextBlock(FromBBI.BB); + MachineBasicBlock *FallThrough = FromBBI.HasFallThrough ? NBB : NULL; + + for (unsigned i = 0, e = Succs.size(); i != e; ++i) { + MachineBasicBlock *Succ = Succs[i]; + // Fallthrough edge can't be transferred. + if (Succ == FallThrough) + continue; + ToBBI.BB->addSuccessor(Succ); + } + + std::copy(FromBBI.Predicate.begin(), FromBBI.Predicate.end(), + std::back_inserter(ToBBI.Predicate)); + std::copy(Cond.begin(), Cond.end(), std::back_inserter(ToBBI.Predicate)); + + ToBBI.ClobbersPred |= FromBBI.ClobbersPred; + ToBBI.IsAnalyzed = false; + + NumDupBBs++; +} + +/// MergeBlocks - Move all instructions from FromBB to the end of ToBB. +/// +void IfConverter::MergeBlocks(BBInfo &ToBBI, BBInfo &FromBBI) { + ToBBI.BB->splice(ToBBI.BB->end(), + FromBBI.BB, FromBBI.BB->begin(), FromBBI.BB->end()); + + // Redirect all branches to FromBB to ToBB. + std::vector Preds(FromBBI.BB->pred_begin(), + FromBBI.BB->pred_end()); + for (unsigned i = 0, e = Preds.size(); i != e; ++i) { + MachineBasicBlock *Pred = Preds[i]; + if (Pred == ToBBI.BB) + continue; + Pred->ReplaceUsesOfBlockWith(FromBBI.BB, ToBBI.BB); + } + + std::vector Succs(FromBBI.BB->succ_begin(), + FromBBI.BB->succ_end()); + MachineBasicBlock *NBB = getNextBlock(FromBBI.BB); + MachineBasicBlock *FallThrough = FromBBI.HasFallThrough ? NBB : NULL; + + for (unsigned i = 0, e = Succs.size(); i != e; ++i) { + MachineBasicBlock *Succ = Succs[i]; + // Fallthrough edge can't be transferred. + if (Succ == FallThrough) + continue; + FromBBI.BB->removeSuccessor(Succ); + ToBBI.BB->addSuccessor(Succ); + } + + // Now FromBBI always falls through to the next block! + if (NBB && !FromBBI.BB->isSuccessor(NBB)) + FromBBI.BB->addSuccessor(NBB); + + std::copy(FromBBI.Predicate.begin(), FromBBI.Predicate.end(), + std::back_inserter(ToBBI.Predicate)); + FromBBI.Predicate.clear(); + + ToBBI.NonPredSize += FromBBI.NonPredSize; + FromBBI.NonPredSize = 0; + + ToBBI.ClobbersPred |= FromBBI.ClobbersPred; + ToBBI.HasFallThrough = FromBBI.HasFallThrough; + ToBBI.IsAnalyzed = false; + FromBBI.IsAnalyzed = false; +} diff --git a/libclamav/c++/llvm/lib/CodeGen/IntrinsicLowering.cpp b/libclamav/c++/llvm/lib/CodeGen/IntrinsicLowering.cpp new file mode 100644 index 000000000..8a3bd0bf4 --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/IntrinsicLowering.cpp @@ -0,0 +1,532 @@ +//===-- IntrinsicLowering.cpp - Intrinsic Lowering default implementation -===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the IntrinsicLowering class. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Module.h" +#include "llvm/Type.h" +#include "llvm/CodeGen/IntrinsicLowering.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/IRBuilder.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Target/TargetData.h" +#include "llvm/ADT/SmallVector.h" +using namespace llvm; + +template +static void EnsureFunctionExists(Module &M, const char *Name, + ArgIt ArgBegin, ArgIt ArgEnd, + const Type *RetTy) { + // Insert a correctly-typed definition now. + std::vector ParamTys; + for (ArgIt I = ArgBegin; I != ArgEnd; ++I) + ParamTys.push_back(I->getType()); + M.getOrInsertFunction(Name, FunctionType::get(RetTy, ParamTys, false)); +} + +static void EnsureFPIntrinsicsExist(Module &M, Function *Fn, + const char *FName, + const char *DName, const char *LDName) { + // Insert definitions for all the floating point types. + switch((int)Fn->arg_begin()->getType()->getTypeID()) { + case Type::FloatTyID: + EnsureFunctionExists(M, FName, Fn->arg_begin(), Fn->arg_end(), + Type::getFloatTy(M.getContext())); + break; + case Type::DoubleTyID: + EnsureFunctionExists(M, DName, Fn->arg_begin(), Fn->arg_end(), + Type::getDoubleTy(M.getContext())); + break; + case Type::X86_FP80TyID: + case Type::FP128TyID: + case Type::PPC_FP128TyID: + EnsureFunctionExists(M, LDName, Fn->arg_begin(), Fn->arg_end(), + Fn->arg_begin()->getType()); + break; + } +} + +/// ReplaceCallWith - This function is used when we want to lower an intrinsic +/// call to a call of an external function. This handles hard cases such as +/// when there was already a prototype for the external function, and if that +/// prototype doesn't match the arguments we expect to pass in. +template +static CallInst *ReplaceCallWith(const char *NewFn, CallInst *CI, + ArgIt ArgBegin, ArgIt ArgEnd, + const Type *RetTy) { + // If we haven't already looked up this function, check to see if the + // program already contains a function with this name. + Module *M = CI->getParent()->getParent()->getParent(); + // Get or insert the definition now. + std::vector ParamTys; + for (ArgIt I = ArgBegin; I != ArgEnd; ++I) + ParamTys.push_back((*I)->getType()); + Constant* FCache = M->getOrInsertFunction(NewFn, + FunctionType::get(RetTy, ParamTys, false)); + + IRBuilder<> Builder(CI->getParent(), CI); + SmallVector Args(ArgBegin, ArgEnd); + CallInst *NewCI = Builder.CreateCall(FCache, Args.begin(), Args.end()); + NewCI->setName(CI->getName()); + if (!CI->use_empty()) + CI->replaceAllUsesWith(NewCI); + return NewCI; +} + +void IntrinsicLowering::AddPrototypes(Module &M) { + LLVMContext &Context = M.getContext(); + for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) + if (I->isDeclaration() && !I->use_empty()) + switch (I->getIntrinsicID()) { + default: break; + case Intrinsic::setjmp: + EnsureFunctionExists(M, "setjmp", I->arg_begin(), I->arg_end(), + Type::getInt32Ty(M.getContext())); + break; + case Intrinsic::longjmp: + EnsureFunctionExists(M, "longjmp", I->arg_begin(), I->arg_end(), + Type::getVoidTy(M.getContext())); + break; + case Intrinsic::siglongjmp: + EnsureFunctionExists(M, "abort", I->arg_end(), I->arg_end(), + Type::getVoidTy(M.getContext())); + break; + case Intrinsic::memcpy: + M.getOrInsertFunction("memcpy", + Type::getInt8PtrTy(Context), + Type::getInt8PtrTy(Context), + Type::getInt8PtrTy(Context), + TD.getIntPtrType(Context), (Type *)0); + break; + case Intrinsic::memmove: + M.getOrInsertFunction("memmove", + Type::getInt8PtrTy(Context), + Type::getInt8PtrTy(Context), + Type::getInt8PtrTy(Context), + TD.getIntPtrType(Context), (Type *)0); + break; + case Intrinsic::memset: + M.getOrInsertFunction("memset", + Type::getInt8PtrTy(Context), + Type::getInt8PtrTy(Context), + Type::getInt32Ty(M.getContext()), + TD.getIntPtrType(Context), (Type *)0); + break; + case Intrinsic::sqrt: + EnsureFPIntrinsicsExist(M, I, "sqrtf", "sqrt", "sqrtl"); + break; + case Intrinsic::sin: + EnsureFPIntrinsicsExist(M, I, "sinf", "sin", "sinl"); + break; + case Intrinsic::cos: + EnsureFPIntrinsicsExist(M, I, "cosf", "cos", "cosl"); + break; + case Intrinsic::pow: + EnsureFPIntrinsicsExist(M, I, "powf", "pow", "powl"); + break; + case Intrinsic::log: + EnsureFPIntrinsicsExist(M, I, "logf", "log", "logl"); + break; + case Intrinsic::log2: + EnsureFPIntrinsicsExist(M, I, "log2f", "log2", "log2l"); + break; + case Intrinsic::log10: + EnsureFPIntrinsicsExist(M, I, "log10f", "log10", "log10l"); + break; + case Intrinsic::exp: + EnsureFPIntrinsicsExist(M, I, "expf", "exp", "expl"); + break; + case Intrinsic::exp2: + EnsureFPIntrinsicsExist(M, I, "exp2f", "exp2", "exp2l"); + break; + } +} + +/// LowerBSWAP - Emit the code to lower bswap of V before the specified +/// instruction IP. +static Value *LowerBSWAP(LLVMContext &Context, Value *V, Instruction *IP) { + assert(V->getType()->isInteger() && "Can't bswap a non-integer type!"); + + unsigned BitSize = V->getType()->getPrimitiveSizeInBits(); + + IRBuilder<> Builder(IP->getParent(), IP); + + switch(BitSize) { + default: llvm_unreachable("Unhandled type size of value to byteswap!"); + case 16: { + Value *Tmp1 = Builder.CreateShl(V, ConstantInt::get(V->getType(), 8), + "bswap.2"); + Value *Tmp2 = Builder.CreateLShr(V, ConstantInt::get(V->getType(), 8), + "bswap.1"); + V = Builder.CreateOr(Tmp1, Tmp2, "bswap.i16"); + break; + } + case 32: { + Value *Tmp4 = Builder.CreateShl(V, ConstantInt::get(V->getType(), 24), + "bswap.4"); + Value *Tmp3 = Builder.CreateShl(V, ConstantInt::get(V->getType(), 8), + "bswap.3"); + Value *Tmp2 = Builder.CreateLShr(V, ConstantInt::get(V->getType(), 8), + "bswap.2"); + Value *Tmp1 = Builder.CreateLShr(V,ConstantInt::get(V->getType(), 24), + "bswap.1"); + Tmp3 = Builder.CreateAnd(Tmp3, + ConstantInt::get(Type::getInt32Ty(Context), 0xFF0000), + "bswap.and3"); + Tmp2 = Builder.CreateAnd(Tmp2, + ConstantInt::get(Type::getInt32Ty(Context), 0xFF00), + "bswap.and2"); + Tmp4 = Builder.CreateOr(Tmp4, Tmp3, "bswap.or1"); + Tmp2 = Builder.CreateOr(Tmp2, Tmp1, "bswap.or2"); + V = Builder.CreateOr(Tmp4, Tmp2, "bswap.i32"); + break; + } + case 64: { + Value *Tmp8 = Builder.CreateShl(V, ConstantInt::get(V->getType(), 56), + "bswap.8"); + Value *Tmp7 = Builder.CreateShl(V, ConstantInt::get(V->getType(), 40), + "bswap.7"); + Value *Tmp6 = Builder.CreateShl(V, ConstantInt::get(V->getType(), 24), + "bswap.6"); + Value *Tmp5 = Builder.CreateShl(V, ConstantInt::get(V->getType(), 8), + "bswap.5"); + Value* Tmp4 = Builder.CreateLShr(V, ConstantInt::get(V->getType(), 8), + "bswap.4"); + Value* Tmp3 = Builder.CreateLShr(V, + ConstantInt::get(V->getType(), 24), + "bswap.3"); + Value* Tmp2 = Builder.CreateLShr(V, + ConstantInt::get(V->getType(), 40), + "bswap.2"); + Value* Tmp1 = Builder.CreateLShr(V, + ConstantInt::get(V->getType(), 56), + "bswap.1"); + Tmp7 = Builder.CreateAnd(Tmp7, + ConstantInt::get(Type::getInt64Ty(Context), + 0xFF000000000000ULL), + "bswap.and7"); + Tmp6 = Builder.CreateAnd(Tmp6, + ConstantInt::get(Type::getInt64Ty(Context), + 0xFF0000000000ULL), + "bswap.and6"); + Tmp5 = Builder.CreateAnd(Tmp5, + ConstantInt::get(Type::getInt64Ty(Context), + 0xFF00000000ULL), + "bswap.and5"); + Tmp4 = Builder.CreateAnd(Tmp4, + ConstantInt::get(Type::getInt64Ty(Context), + 0xFF000000ULL), + "bswap.and4"); + Tmp3 = Builder.CreateAnd(Tmp3, + ConstantInt::get(Type::getInt64Ty(Context), + 0xFF0000ULL), + "bswap.and3"); + Tmp2 = Builder.CreateAnd(Tmp2, + ConstantInt::get(Type::getInt64Ty(Context), + 0xFF00ULL), + "bswap.and2"); + Tmp8 = Builder.CreateOr(Tmp8, Tmp7, "bswap.or1"); + Tmp6 = Builder.CreateOr(Tmp6, Tmp5, "bswap.or2"); + Tmp4 = Builder.CreateOr(Tmp4, Tmp3, "bswap.or3"); + Tmp2 = Builder.CreateOr(Tmp2, Tmp1, "bswap.or4"); + Tmp8 = Builder.CreateOr(Tmp8, Tmp6, "bswap.or5"); + Tmp4 = Builder.CreateOr(Tmp4, Tmp2, "bswap.or6"); + V = Builder.CreateOr(Tmp8, Tmp4, "bswap.i64"); + break; + } + } + return V; +} + +/// LowerCTPOP - Emit the code to lower ctpop of V before the specified +/// instruction IP. +static Value *LowerCTPOP(LLVMContext &Context, Value *V, Instruction *IP) { + assert(V->getType()->isInteger() && "Can't ctpop a non-integer type!"); + + static const uint64_t MaskValues[6] = { + 0x5555555555555555ULL, 0x3333333333333333ULL, + 0x0F0F0F0F0F0F0F0FULL, 0x00FF00FF00FF00FFULL, + 0x0000FFFF0000FFFFULL, 0x00000000FFFFFFFFULL + }; + + IRBuilder<> Builder(IP->getParent(), IP); + + unsigned BitSize = V->getType()->getPrimitiveSizeInBits(); + unsigned WordSize = (BitSize + 63) / 64; + Value *Count = ConstantInt::get(V->getType(), 0); + + for (unsigned n = 0; n < WordSize; ++n) { + Value *PartValue = V; + for (unsigned i = 1, ct = 0; i < (BitSize>64 ? 64 : BitSize); + i <<= 1, ++ct) { + Value *MaskCst = ConstantInt::get(V->getType(), MaskValues[ct]); + Value *LHS = Builder.CreateAnd(PartValue, MaskCst, "cppop.and1"); + Value *VShift = Builder.CreateLShr(PartValue, + ConstantInt::get(V->getType(), i), + "ctpop.sh"); + Value *RHS = Builder.CreateAnd(VShift, MaskCst, "cppop.and2"); + PartValue = Builder.CreateAdd(LHS, RHS, "ctpop.step"); + } + Count = Builder.CreateAdd(PartValue, Count, "ctpop.part"); + if (BitSize > 64) { + V = Builder.CreateLShr(V, ConstantInt::get(V->getType(), 64), + "ctpop.part.sh"); + BitSize -= 64; + } + } + + return Count; +} + +/// LowerCTLZ - Emit the code to lower ctlz of V before the specified +/// instruction IP. +static Value *LowerCTLZ(LLVMContext &Context, Value *V, Instruction *IP) { + + IRBuilder<> Builder(IP->getParent(), IP); + + unsigned BitSize = V->getType()->getPrimitiveSizeInBits(); + for (unsigned i = 1; i < BitSize; i <<= 1) { + Value *ShVal = ConstantInt::get(V->getType(), i); + ShVal = Builder.CreateLShr(V, ShVal, "ctlz.sh"); + V = Builder.CreateOr(V, ShVal, "ctlz.step"); + } + + V = Builder.CreateNot(V); + return LowerCTPOP(Context, V, IP); +} + +static void ReplaceFPIntrinsicWithCall(CallInst *CI, const char *Fname, + const char *Dname, + const char *LDname) { + switch (CI->getOperand(1)->getType()->getTypeID()) { + default: llvm_unreachable("Invalid type in intrinsic"); + case Type::FloatTyID: + ReplaceCallWith(Fname, CI, CI->op_begin() + 1, CI->op_end(), + Type::getFloatTy(CI->getContext())); + break; + case Type::DoubleTyID: + ReplaceCallWith(Dname, CI, CI->op_begin() + 1, CI->op_end(), + Type::getDoubleTy(CI->getContext())); + break; + case Type::X86_FP80TyID: + case Type::FP128TyID: + case Type::PPC_FP128TyID: + ReplaceCallWith(LDname, CI, CI->op_begin() + 1, CI->op_end(), + CI->getOperand(1)->getType()); + break; + } +} + +void IntrinsicLowering::LowerIntrinsicCall(CallInst *CI) { + IRBuilder<> Builder(CI->getParent(), CI); + LLVMContext &Context = CI->getContext(); + + Function *Callee = CI->getCalledFunction(); + assert(Callee && "Cannot lower an indirect call!"); + + switch (Callee->getIntrinsicID()) { + case Intrinsic::not_intrinsic: + llvm_report_error("Cannot lower a call to a non-intrinsic function '"+ + Callee->getName() + "'!"); + default: + llvm_report_error("Code generator does not support intrinsic function '"+ + Callee->getName()+"'!"); + + // The setjmp/longjmp intrinsics should only exist in the code if it was + // never optimized (ie, right out of the CFE), or if it has been hacked on + // by the lowerinvoke pass. In both cases, the right thing to do is to + // convert the call to an explicit setjmp or longjmp call. + case Intrinsic::setjmp: { + Value *V = ReplaceCallWith("setjmp", CI, CI->op_begin() + 1, CI->op_end(), + Type::getInt32Ty(Context)); + if (CI->getType() != Type::getVoidTy(Context)) + CI->replaceAllUsesWith(V); + break; + } + case Intrinsic::sigsetjmp: + if (CI->getType() != Type::getVoidTy(Context)) + CI->replaceAllUsesWith(Constant::getNullValue(CI->getType())); + break; + + case Intrinsic::longjmp: { + ReplaceCallWith("longjmp", CI, CI->op_begin() + 1, CI->op_end(), + Type::getVoidTy(Context)); + break; + } + + case Intrinsic::siglongjmp: { + // Insert the call to abort + ReplaceCallWith("abort", CI, CI->op_end(), CI->op_end(), + Type::getVoidTy(Context)); + break; + } + case Intrinsic::ctpop: + CI->replaceAllUsesWith(LowerCTPOP(Context, CI->getOperand(1), CI)); + break; + + case Intrinsic::bswap: + CI->replaceAllUsesWith(LowerBSWAP(Context, CI->getOperand(1), CI)); + break; + + case Intrinsic::ctlz: + CI->replaceAllUsesWith(LowerCTLZ(Context, CI->getOperand(1), CI)); + break; + + case Intrinsic::cttz: { + // cttz(x) -> ctpop(~X & (X-1)) + Value *Src = CI->getOperand(1); + Value *NotSrc = Builder.CreateNot(Src); + NotSrc->setName(Src->getName() + ".not"); + Value *SrcM1 = ConstantInt::get(Src->getType(), 1); + SrcM1 = Builder.CreateSub(Src, SrcM1); + Src = LowerCTPOP(Context, Builder.CreateAnd(NotSrc, SrcM1), CI); + CI->replaceAllUsesWith(Src); + break; + } + + case Intrinsic::stacksave: + case Intrinsic::stackrestore: { + if (!Warned) + errs() << "WARNING: this target does not support the llvm.stack" + << (Callee->getIntrinsicID() == Intrinsic::stacksave ? + "save" : "restore") << " intrinsic.\n"; + Warned = true; + if (Callee->getIntrinsicID() == Intrinsic::stacksave) + CI->replaceAllUsesWith(Constant::getNullValue(CI->getType())); + break; + } + + case Intrinsic::returnaddress: + case Intrinsic::frameaddress: + errs() << "WARNING: this target does not support the llvm." + << (Callee->getIntrinsicID() == Intrinsic::returnaddress ? + "return" : "frame") << "address intrinsic.\n"; + CI->replaceAllUsesWith(ConstantPointerNull::get( + cast(CI->getType()))); + break; + + case Intrinsic::prefetch: + break; // Simply strip out prefetches on unsupported architectures + + case Intrinsic::pcmarker: + break; // Simply strip out pcmarker on unsupported architectures + case Intrinsic::readcyclecounter: { + errs() << "WARNING: this target does not support the llvm.readcyclecoun" + << "ter intrinsic. It is being lowered to a constant 0\n"; + CI->replaceAllUsesWith(ConstantInt::get(Type::getInt64Ty(Context), 0)); + break; + } + + case Intrinsic::dbg_stoppoint: + case Intrinsic::dbg_region_start: + case Intrinsic::dbg_region_end: + case Intrinsic::dbg_func_start: + case Intrinsic::dbg_declare: + break; // Simply strip out debugging intrinsics + + case Intrinsic::eh_exception: + case Intrinsic::eh_selector: + CI->replaceAllUsesWith(Constant::getNullValue(CI->getType())); + break; + + case Intrinsic::eh_typeid_for: + // Return something different to eh_selector. + CI->replaceAllUsesWith(ConstantInt::get(CI->getType(), 1)); + break; + + case Intrinsic::var_annotation: + break; // Strip out annotate intrinsic + + case Intrinsic::memcpy: { + const IntegerType *IntPtr = TD.getIntPtrType(Context); + Value *Size = Builder.CreateIntCast(CI->getOperand(3), IntPtr, + /* isSigned */ false); + Value *Ops[3]; + Ops[0] = CI->getOperand(1); + Ops[1] = CI->getOperand(2); + Ops[2] = Size; + ReplaceCallWith("memcpy", CI, Ops, Ops+3, CI->getOperand(1)->getType()); + break; + } + case Intrinsic::memmove: { + const IntegerType *IntPtr = TD.getIntPtrType(Context); + Value *Size = Builder.CreateIntCast(CI->getOperand(3), IntPtr, + /* isSigned */ false); + Value *Ops[3]; + Ops[0] = CI->getOperand(1); + Ops[1] = CI->getOperand(2); + Ops[2] = Size; + ReplaceCallWith("memmove", CI, Ops, Ops+3, CI->getOperand(1)->getType()); + break; + } + case Intrinsic::memset: { + const IntegerType *IntPtr = TD.getIntPtrType(Context); + Value *Size = Builder.CreateIntCast(CI->getOperand(3), IntPtr, + /* isSigned */ false); + Value *Ops[3]; + Ops[0] = CI->getOperand(1); + // Extend the amount to i32. + Ops[1] = Builder.CreateIntCast(CI->getOperand(2), Type::getInt32Ty(Context), + /* isSigned */ false); + Ops[2] = Size; + ReplaceCallWith("memset", CI, Ops, Ops+3, CI->getOperand(1)->getType()); + break; + } + case Intrinsic::sqrt: { + ReplaceFPIntrinsicWithCall(CI, "sqrtf", "sqrt", "sqrtl"); + break; + } + case Intrinsic::log: { + ReplaceFPIntrinsicWithCall(CI, "logf", "log", "logl"); + break; + } + case Intrinsic::log2: { + ReplaceFPIntrinsicWithCall(CI, "log2f", "log2", "log2l"); + break; + } + case Intrinsic::log10: { + ReplaceFPIntrinsicWithCall(CI, "log10f", "log10", "log10l"); + break; + } + case Intrinsic::exp: { + ReplaceFPIntrinsicWithCall(CI, "expf", "exp", "expl"); + break; + } + case Intrinsic::exp2: { + ReplaceFPIntrinsicWithCall(CI, "exp2f", "exp2", "exp2l"); + break; + } + case Intrinsic::pow: { + ReplaceFPIntrinsicWithCall(CI, "powf", "pow", "powl"); + break; + } + case Intrinsic::flt_rounds: + // Lower to "round to the nearest" + if (CI->getType() != Type::getVoidTy(Context)) + CI->replaceAllUsesWith(ConstantInt::get(CI->getType(), 1)); + break; + case Intrinsic::invariant_start: + case Intrinsic::lifetime_start: + // Discard region information. + CI->replaceAllUsesWith(UndefValue::get(CI->getType())); + break; + case Intrinsic::invariant_end: + case Intrinsic::lifetime_end: + // Discard region information. + break; + } + + assert(CI->use_empty() && + "Lowering should have eliminated any uses of the intrinsic call!"); + CI->eraseFromParent(); +} diff --git a/libclamav/c++/llvm/lib/CodeGen/LLVMTargetMachine.cpp b/libclamav/c++/llvm/lib/CodeGen/LLVMTargetMachine.cpp new file mode 100644 index 000000000..242cba5b6 --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/LLVMTargetMachine.cpp @@ -0,0 +1,369 @@ +//===-- LLVMTargetMachine.cpp - Implement the LLVMTargetMachine class -----===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the LLVMTargetMachine class. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Target/TargetMachine.h" +#include "llvm/PassManager.h" +#include "llvm/Pass.h" +#include "llvm/Assembly/PrintModulePass.h" +#include "llvm/CodeGen/AsmPrinter.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/CodeGen/GCStrategy.h" +#include "llvm/CodeGen/MachineFunctionAnalysis.h" +#include "llvm/Target/TargetOptions.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/Target/TargetRegistry.h" +#include "llvm/Transforms/Scalar.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/FormattedStream.h" +using namespace llvm; + +namespace llvm { + bool EnableFastISel; +} + +static cl::opt DisablePostRA("disable-post-ra", cl::Hidden, + cl::desc("Disable Post Regalloc")); +static cl::opt DisableBranchFold("disable-branch-fold", cl::Hidden, + cl::desc("Disable branch folding")); +static cl::opt DisableTailDuplicate("disable-tail-duplicate", cl::Hidden, + cl::desc("Disable tail duplication")); +static cl::opt DisableCodePlace("disable-code-place", cl::Hidden, + cl::desc("Disable code placement")); +static cl::opt DisableSSC("disable-ssc", cl::Hidden, + cl::desc("Disable Stack Slot Coloring")); +static cl::opt DisableMachineLICM("disable-machine-licm", cl::Hidden, + cl::desc("Disable Machine LICM")); +static cl::opt DisableMachineSink("disable-machine-sink", cl::Hidden, + cl::desc("Disable Machine Sinking")); +static cl::opt DisableLSR("disable-lsr", cl::Hidden, + cl::desc("Disable Loop Strength Reduction Pass")); +static cl::opt DisableCGP("disable-cgp", cl::Hidden, + cl::desc("Disable Codegen Prepare")); +static cl::opt PrintLSR("print-lsr-output", cl::Hidden, + cl::desc("Print LLVM IR produced by the loop-reduce pass")); +static cl::opt PrintISelInput("print-isel-input", cl::Hidden, + cl::desc("Print LLVM IR input to isel pass")); +static cl::opt PrintEmittedAsm("print-emitted-asm", cl::Hidden, + cl::desc("Dump emitter generated instructions as assembly")); +static cl::opt PrintGCInfo("print-gc", cl::Hidden, + cl::desc("Dump garbage collector data")); +static cl::opt VerifyMachineCode("verify-machineinstrs", cl::Hidden, + cl::desc("Verify generated machine code"), + cl::init(getenv("LLVM_VERIFY_MACHINEINSTRS")!=NULL)); + +// Enable or disable FastISel. Both options are needed, because +// FastISel is enabled by default with -fast, and we wish to be +// able to enable or disable fast-isel independently from -O0. +static cl::opt +EnableFastISelOption("fast-isel", cl::Hidden, + cl::desc("Enable the \"fast\" instruction selector")); + +// Enable or disable an experimental optimization to split GEPs +// and run a special GVN pass which does not examine loads, in +// an effort to factor out redundancy implicit in complex GEPs. +static cl::opt EnableSplitGEPGVN("split-gep-gvn", cl::Hidden, + cl::desc("Split GEPs and run no-load GVN")); + +LLVMTargetMachine::LLVMTargetMachine(const Target &T, + const std::string &TargetTriple) + : TargetMachine(T) { + AsmInfo = T.createAsmInfo(TargetTriple); +} + + + +FileModel::Model +LLVMTargetMachine::addPassesToEmitFile(PassManagerBase &PM, + formatted_raw_ostream &Out, + CodeGenFileType FileType, + CodeGenOpt::Level OptLevel) { + // Add common CodeGen passes. + if (addCommonCodeGenPasses(PM, OptLevel)) + return FileModel::Error; + + switch (FileType) { + default: + break; + case TargetMachine::AssemblyFile: + if (addAssemblyEmitter(PM, OptLevel, getAsmVerbosityDefault(), Out)) + return FileModel::Error; + return FileModel::AsmFile; + case TargetMachine::ObjectFile: + if (getMachOWriterInfo()) + return FileModel::MachOFile; + else if (getELFWriterInfo()) + return FileModel::ElfFile; + } + + return FileModel::Error; +} + +bool LLVMTargetMachine::addAssemblyEmitter(PassManagerBase &PM, + CodeGenOpt::Level OptLevel, + bool Verbose, + formatted_raw_ostream &Out) { + FunctionPass *Printer = + getTarget().createAsmPrinter(Out, *this, getMCAsmInfo(), Verbose); + if (!Printer) + return true; + + PM.add(Printer); + return false; +} + +/// addPassesToEmitFileFinish - If the passes to emit the specified file had to +/// be split up (e.g., to add an object writer pass), this method can be used to +/// finish up adding passes to emit the file, if necessary. +bool LLVMTargetMachine::addPassesToEmitFileFinish(PassManagerBase &PM, + MachineCodeEmitter *MCE, + CodeGenOpt::Level OptLevel) { + if (MCE) + addSimpleCodeEmitter(PM, OptLevel, *MCE); + if (PrintEmittedAsm) + addAssemblyEmitter(PM, OptLevel, true, ferrs()); + + PM.add(createGCInfoDeleter()); + + return false; // success! +} + +/// addPassesToEmitFileFinish - If the passes to emit the specified file had to +/// be split up (e.g., to add an object writer pass), this method can be used to +/// finish up adding passes to emit the file, if necessary. +bool LLVMTargetMachine::addPassesToEmitFileFinish(PassManagerBase &PM, + JITCodeEmitter *JCE, + CodeGenOpt::Level OptLevel) { + if (JCE) + addSimpleCodeEmitter(PM, OptLevel, *JCE); + if (PrintEmittedAsm) + addAssemblyEmitter(PM, OptLevel, true, ferrs()); + + PM.add(createGCInfoDeleter()); + + return false; // success! +} + +/// addPassesToEmitFileFinish - If the passes to emit the specified file had to +/// be split up (e.g., to add an object writer pass), this method can be used to +/// finish up adding passes to emit the file, if necessary. +bool LLVMTargetMachine::addPassesToEmitFileFinish(PassManagerBase &PM, + ObjectCodeEmitter *OCE, + CodeGenOpt::Level OptLevel) { + if (OCE) + addSimpleCodeEmitter(PM, OptLevel, *OCE); + if (PrintEmittedAsm) + addAssemblyEmitter(PM, OptLevel, true, ferrs()); + + PM.add(createGCInfoDeleter()); + + return false; // success! +} + +/// addPassesToEmitMachineCode - Add passes to the specified pass manager to +/// get machine code emitted. This uses a MachineCodeEmitter object to handle +/// actually outputting the machine code and resolving things like the address +/// of functions. This method should returns true if machine code emission is +/// not supported. +/// +bool LLVMTargetMachine::addPassesToEmitMachineCode(PassManagerBase &PM, + MachineCodeEmitter &MCE, + CodeGenOpt::Level OptLevel) { + // Add common CodeGen passes. + if (addCommonCodeGenPasses(PM, OptLevel)) + return true; + + addCodeEmitter(PM, OptLevel, MCE); + if (PrintEmittedAsm) + addAssemblyEmitter(PM, OptLevel, true, ferrs()); + + PM.add(createGCInfoDeleter()); + + return false; // success! +} + +/// addPassesToEmitMachineCode - Add passes to the specified pass manager to +/// get machine code emitted. This uses a MachineCodeEmitter object to handle +/// actually outputting the machine code and resolving things like the address +/// of functions. This method should returns true if machine code emission is +/// not supported. +/// +bool LLVMTargetMachine::addPassesToEmitMachineCode(PassManagerBase &PM, + JITCodeEmitter &JCE, + CodeGenOpt::Level OptLevel) { + // Add common CodeGen passes. + if (addCommonCodeGenPasses(PM, OptLevel)) + return true; + + addCodeEmitter(PM, OptLevel, JCE); + if (PrintEmittedAsm) + addAssemblyEmitter(PM, OptLevel, true, ferrs()); + + PM.add(createGCInfoDeleter()); + + return false; // success! +} + +static void printAndVerify(PassManagerBase &PM, + const char *Banner, + bool allowDoubleDefs = false) { + if (PrintMachineCode) + PM.add(createMachineFunctionPrinterPass(errs(), Banner)); + + if (VerifyMachineCode) + PM.add(createMachineVerifierPass(allowDoubleDefs)); +} + +/// addCommonCodeGenPasses - Add standard LLVM codegen passes used for both +/// emitting to assembly files or machine code output. +/// +bool LLVMTargetMachine::addCommonCodeGenPasses(PassManagerBase &PM, + CodeGenOpt::Level OptLevel) { + // Standard LLVM-Level Passes. + + // Optionally, tun split-GEPs and no-load GVN. + if (EnableSplitGEPGVN) { + PM.add(createGEPSplitterPass()); + PM.add(createGVNPass(/*NoPRE=*/false, /*NoLoads=*/true)); + } + + // Run loop strength reduction before anything else. + if (OptLevel != CodeGenOpt::None && !DisableLSR) { + PM.add(createLoopStrengthReducePass(getTargetLowering())); + if (PrintLSR) + PM.add(createPrintFunctionPass("\n\n*** Code after LSR ***\n", &errs())); + } + + // Turn exception handling constructs into something the code generators can + // handle. + switch (getMCAsmInfo()->getExceptionHandlingType()) + { + case ExceptionHandling::SjLj: + // SjLj piggy-backs on dwarf for this bit. The cleanups done apply to both + PM.add(createDwarfEHPass(getTargetLowering(), OptLevel==CodeGenOpt::None)); + PM.add(createSjLjEHPass(getTargetLowering())); + break; + case ExceptionHandling::Dwarf: + PM.add(createDwarfEHPass(getTargetLowering(), OptLevel==CodeGenOpt::None)); + break; + case ExceptionHandling::None: + PM.add(createLowerInvokePass(getTargetLowering())); + break; + } + + PM.add(createGCLoweringPass()); + + // Make sure that no unreachable blocks are instruction selected. + PM.add(createUnreachableBlockEliminationPass()); + + if (OptLevel != CodeGenOpt::None && !DisableCGP) + PM.add(createCodeGenPreparePass(getTargetLowering())); + + PM.add(createStackProtectorPass(getTargetLowering())); + + if (PrintISelInput) + PM.add(createPrintFunctionPass("\n\n" + "*** Final LLVM Code input to ISel ***\n", + &errs())); + + // Standard Lower-Level Passes. + + // Set up a MachineFunction for the rest of CodeGen to work on. + PM.add(new MachineFunctionAnalysis(*this, OptLevel)); + + // Enable FastISel with -fast, but allow that to be overridden. + if (EnableFastISelOption == cl::BOU_TRUE || + (OptLevel == CodeGenOpt::None && EnableFastISelOption != cl::BOU_FALSE)) + EnableFastISel = true; + + // Ask the target for an isel. + if (addInstSelector(PM, OptLevel)) + return true; + + // Print the instruction selected machine code... + printAndVerify(PM, "After Instruction Selection", + /* allowDoubleDefs= */ true); + + if (OptLevel != CodeGenOpt::None) { + if (!DisableMachineLICM) + PM.add(createMachineLICMPass()); + if (!DisableMachineSink) + PM.add(createMachineSinkingPass()); + printAndVerify(PM, "After MachineLICM and MachineSinking", + /* allowDoubleDefs= */ true); + } + + // Run pre-ra passes. + if (addPreRegAlloc(PM, OptLevel)) + printAndVerify(PM, "After PreRegAlloc passes", + /* allowDoubleDefs= */ true); + + // Perform register allocation. + PM.add(createRegisterAllocator()); + printAndVerify(PM, "After Register Allocation"); + + // Perform stack slot coloring. + if (OptLevel != CodeGenOpt::None && !DisableSSC) { + // FIXME: Re-enable coloring with register when it's capable of adding + // kill markers. + PM.add(createStackSlotColoringPass(false)); + printAndVerify(PM, "After StackSlotColoring"); + } + + // Run post-ra passes. + if (addPostRegAlloc(PM, OptLevel)) + printAndVerify(PM, "After PostRegAlloc passes"); + + PM.add(createLowerSubregsPass()); + printAndVerify(PM, "After LowerSubregs"); + + // Insert prolog/epilog code. Eliminate abstract frame index references... + PM.add(createPrologEpilogCodeInserter()); + printAndVerify(PM, "After PrologEpilogCodeInserter"); + + // Run pre-sched2 passes. + if (addPreSched2(PM, OptLevel)) + printAndVerify(PM, "After PreSched2 passes"); + + // Second pass scheduler. + if (OptLevel != CodeGenOpt::None && !DisablePostRA) { + PM.add(createPostRAScheduler(OptLevel)); + printAndVerify(PM, "After PostRAScheduler"); + } + + // Branch folding must be run after regalloc and prolog/epilog insertion. + if (OptLevel != CodeGenOpt::None && !DisableBranchFold) { + PM.add(createBranchFoldingPass(getEnableTailMergeDefault())); + printAndVerify(PM, "After BranchFolding"); + } + + // Tail duplication. + if (OptLevel != CodeGenOpt::None && !DisableTailDuplicate) { + PM.add(createTailDuplicatePass()); + printAndVerify(PM, "After TailDuplicate"); + } + + PM.add(createGCMachineCodeAnalysisPass()); + + if (PrintGCInfo) + PM.add(createGCInfoPrinter(errs())); + + if (OptLevel != CodeGenOpt::None && !DisableCodePlace) { + PM.add(createCodePlacementOptPass()); + printAndVerify(PM, "After CodePlacementOpt"); + } + + if (addPreEmitPass(PM, OptLevel)) + printAndVerify(PM, "After PreEmit passes"); + + return false; +} diff --git a/libclamav/c++/llvm/lib/CodeGen/LatencyPriorityQueue.cpp b/libclamav/c++/llvm/lib/CodeGen/LatencyPriorityQueue.cpp new file mode 100644 index 000000000..f1bd57354 --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/LatencyPriorityQueue.cpp @@ -0,0 +1,116 @@ +//===---- LatencyPriorityQueue.cpp - A latency-oriented priority queue ----===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the LatencyPriorityQueue class, which is a +// SchedulingPriorityQueue that schedules using latency information to +// reduce the length of the critical path through the basic block. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "scheduler" +#include "llvm/CodeGen/LatencyPriorityQueue.h" +#include "llvm/Support/Debug.h" +using namespace llvm; + +bool latency_sort::operator()(const SUnit *LHS, const SUnit *RHS) const { + // The isScheduleHigh flag allows nodes with wraparound dependencies that + // cannot easily be modeled as edges with latencies to be scheduled as + // soon as possible in a top-down schedule. + if (LHS->isScheduleHigh && !RHS->isScheduleHigh) + return false; + if (!LHS->isScheduleHigh && RHS->isScheduleHigh) + return true; + + unsigned LHSNum = LHS->NodeNum; + unsigned RHSNum = RHS->NodeNum; + + // The most important heuristic is scheduling the critical path. + unsigned LHSLatency = PQ->getLatency(LHSNum); + unsigned RHSLatency = PQ->getLatency(RHSNum); + if (LHSLatency < RHSLatency) return true; + if (LHSLatency > RHSLatency) return false; + + // After that, if two nodes have identical latencies, look to see if one will + // unblock more other nodes than the other. + unsigned LHSBlocked = PQ->getNumSolelyBlockNodes(LHSNum); + unsigned RHSBlocked = PQ->getNumSolelyBlockNodes(RHSNum); + if (LHSBlocked < RHSBlocked) return true; + if (LHSBlocked > RHSBlocked) return false; + + // Finally, just to provide a stable ordering, use the node number as a + // deciding factor. + return LHSNum < RHSNum; +} + + +/// getSingleUnscheduledPred - If there is exactly one unscheduled predecessor +/// of SU, return it, otherwise return null. +SUnit *LatencyPriorityQueue::getSingleUnscheduledPred(SUnit *SU) { + SUnit *OnlyAvailablePred = 0; + for (SUnit::const_pred_iterator I = SU->Preds.begin(), E = SU->Preds.end(); + I != E; ++I) { + SUnit &Pred = *I->getSUnit(); + if (!Pred.isScheduled) { + // We found an available, but not scheduled, predecessor. If it's the + // only one we have found, keep track of it... otherwise give up. + if (OnlyAvailablePred && OnlyAvailablePred != &Pred) + return 0; + OnlyAvailablePred = &Pred; + } + } + + return OnlyAvailablePred; +} + +void LatencyPriorityQueue::push_impl(SUnit *SU) { + // Look at all of the successors of this node. Count the number of nodes that + // this node is the sole unscheduled node for. + unsigned NumNodesBlocking = 0; + for (SUnit::const_succ_iterator I = SU->Succs.begin(), E = SU->Succs.end(); + I != E; ++I) { + if (getSingleUnscheduledPred(I->getSUnit()) == SU) + ++NumNodesBlocking; + } + NumNodesSolelyBlocking[SU->NodeNum] = NumNodesBlocking; + + Queue.push(SU); +} + + +// ScheduledNode - As nodes are scheduled, we look to see if there are any +// successor nodes that have a single unscheduled predecessor. If so, that +// single predecessor has a higher priority, since scheduling it will make +// the node available. +void LatencyPriorityQueue::ScheduledNode(SUnit *SU) { + for (SUnit::const_succ_iterator I = SU->Succs.begin(), E = SU->Succs.end(); + I != E; ++I) { + AdjustPriorityOfUnscheduledPreds(I->getSUnit()); + } +} + +/// AdjustPriorityOfUnscheduledPreds - One of the predecessors of SU was just +/// scheduled. If SU is not itself available, then there is at least one +/// predecessor node that has not been scheduled yet. If SU has exactly ONE +/// unscheduled predecessor, we want to increase its priority: it getting +/// scheduled will make this node available, so it is better than some other +/// node of the same priority that will not make a node available. +void LatencyPriorityQueue::AdjustPriorityOfUnscheduledPreds(SUnit *SU) { + if (SU->isAvailable) return; // All preds scheduled. + + SUnit *OnlyAvailablePred = getSingleUnscheduledPred(SU); + if (OnlyAvailablePred == 0 || !OnlyAvailablePred->isAvailable) return; + + // Okay, we found a single predecessor that is available, but not scheduled. + // Since it is available, it must be in the priority queue. First remove it. + remove(OnlyAvailablePred); + + // Reinsert the node into the priority queue, which recomputes its + // NumNodesSolelyBlocking value. + push(OnlyAvailablePred); +} diff --git a/libclamav/c++/llvm/lib/CodeGen/LiveInterval.cpp b/libclamav/c++/llvm/lib/CodeGen/LiveInterval.cpp new file mode 100644 index 000000000..8d632cb5c --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/LiveInterval.cpp @@ -0,0 +1,881 @@ +//===-- LiveInterval.cpp - Live Interval Representation -------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the LiveRange and LiveInterval classes. Given some +// numbering of each the machine instructions an interval [i, j) is said to be a +// live interval for register v if there is no instruction with number j' > j +// such that v is live at j' abd there is no instruction with number i' < i such +// that v is live at i'. In this implementation intervals can have holes, +// i.e. an interval might look like [1,20), [50,65), [1000,1001). Each +// individual range is represented as an instance of LiveRange, and the whole +// interval is represented as an instance of LiveInterval. +// +//===----------------------------------------------------------------------===// + +#include "llvm/CodeGen/LiveInterval.h" +#include "llvm/CodeGen/LiveIntervalAnalysis.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallSet.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include +using namespace llvm; + +// An example for liveAt(): +// +// this = [1,4), liveAt(0) will return false. The instruction defining this +// spans slots [0,3]. The interval belongs to an spilled definition of the +// variable it represents. This is because slot 1 is used (def slot) and spans +// up to slot 3 (store slot). +// +bool LiveInterval::liveAt(SlotIndex I) const { + Ranges::const_iterator r = std::upper_bound(ranges.begin(), ranges.end(), I); + + if (r == ranges.begin()) + return false; + + --r; + return r->contains(I); +} + +// liveBeforeAndAt - Check if the interval is live at the index and the index +// just before it. If index is liveAt, check if it starts a new live range. +// If it does, then check if the previous live range ends at index-1. +bool LiveInterval::liveBeforeAndAt(SlotIndex I) const { + Ranges::const_iterator r = std::upper_bound(ranges.begin(), ranges.end(), I); + + if (r == ranges.begin()) + return false; + + --r; + if (!r->contains(I)) + return false; + if (I != r->start) + return true; + // I is the start of a live range. Check if the previous live range ends + // at I-1. + if (r == ranges.begin()) + return false; + return r->end == I; +} + +// overlaps - Return true if the intersection of the two live intervals is +// not empty. +// +// An example for overlaps(): +// +// 0: A = ... +// 4: B = ... +// 8: C = A + B ;; last use of A +// +// The live intervals should look like: +// +// A = [3, 11) +// B = [7, x) +// C = [11, y) +// +// A->overlaps(C) should return false since we want to be able to join +// A and C. +// +bool LiveInterval::overlapsFrom(const LiveInterval& other, + const_iterator StartPos) const { + const_iterator i = begin(); + const_iterator ie = end(); + const_iterator j = StartPos; + const_iterator je = other.end(); + + assert((StartPos->start <= i->start || StartPos == other.begin()) && + StartPos != other.end() && "Bogus start position hint!"); + + if (i->start < j->start) { + i = std::upper_bound(i, ie, j->start); + if (i != ranges.begin()) --i; + } else if (j->start < i->start) { + ++StartPos; + if (StartPos != other.end() && StartPos->start <= i->start) { + assert(StartPos < other.end() && i < end()); + j = std::upper_bound(j, je, i->start); + if (j != other.ranges.begin()) --j; + } + } else { + return true; + } + + if (j == je) return false; + + while (i != ie) { + if (i->start > j->start) { + std::swap(i, j); + std::swap(ie, je); + } + + if (i->end > j->start) + return true; + ++i; + } + + return false; +} + +/// overlaps - Return true if the live interval overlaps a range specified +/// by [Start, End). +bool LiveInterval::overlaps(SlotIndex Start, SlotIndex End) const { + assert(Start < End && "Invalid range"); + const_iterator I = begin(); + const_iterator E = end(); + const_iterator si = std::upper_bound(I, E, Start); + const_iterator ei = std::upper_bound(I, E, End); + if (si != ei) + return true; + if (si == I) + return false; + --si; + return si->contains(Start); +} + +/// extendIntervalEndTo - This method is used when we want to extend the range +/// specified by I to end at the specified endpoint. To do this, we should +/// merge and eliminate all ranges that this will overlap with. The iterator is +/// not invalidated. +void LiveInterval::extendIntervalEndTo(Ranges::iterator I, SlotIndex NewEnd) { + assert(I != ranges.end() && "Not a valid interval!"); + VNInfo *ValNo = I->valno; + SlotIndex OldEnd = I->end; + + // Search for the first interval that we can't merge with. + Ranges::iterator MergeTo = next(I); + for (; MergeTo != ranges.end() && NewEnd >= MergeTo->end; ++MergeTo) { + assert(MergeTo->valno == ValNo && "Cannot merge with differing values!"); + } + + // If NewEnd was in the middle of an interval, make sure to get its endpoint. + I->end = std::max(NewEnd, prior(MergeTo)->end); + + // Erase any dead ranges. + ranges.erase(next(I), MergeTo); + + // Update kill info. + ValNo->removeKills(OldEnd, I->end.getPrevSlot()); + + // If the newly formed range now touches the range after it and if they have + // the same value number, merge the two ranges into one range. + Ranges::iterator Next = next(I); + if (Next != ranges.end() && Next->start <= I->end && Next->valno == ValNo) { + I->end = Next->end; + ranges.erase(Next); + } +} + + +/// extendIntervalStartTo - This method is used when we want to extend the range +/// specified by I to start at the specified endpoint. To do this, we should +/// merge and eliminate all ranges that this will overlap with. +LiveInterval::Ranges::iterator +LiveInterval::extendIntervalStartTo(Ranges::iterator I, SlotIndex NewStart) { + assert(I != ranges.end() && "Not a valid interval!"); + VNInfo *ValNo = I->valno; + + // Search for the first interval that we can't merge with. + Ranges::iterator MergeTo = I; + do { + if (MergeTo == ranges.begin()) { + I->start = NewStart; + ranges.erase(MergeTo, I); + return I; + } + assert(MergeTo->valno == ValNo && "Cannot merge with differing values!"); + --MergeTo; + } while (NewStart <= MergeTo->start); + + // If we start in the middle of another interval, just delete a range and + // extend that interval. + if (MergeTo->end >= NewStart && MergeTo->valno == ValNo) { + MergeTo->end = I->end; + } else { + // Otherwise, extend the interval right after. + ++MergeTo; + MergeTo->start = NewStart; + MergeTo->end = I->end; + } + + ranges.erase(next(MergeTo), next(I)); + return MergeTo; +} + +LiveInterval::iterator +LiveInterval::addRangeFrom(LiveRange LR, iterator From) { + SlotIndex Start = LR.start, End = LR.end; + iterator it = std::upper_bound(From, ranges.end(), Start); + + // If the inserted interval starts in the middle or right at the end of + // another interval, just extend that interval to contain the range of LR. + if (it != ranges.begin()) { + iterator B = prior(it); + if (LR.valno == B->valno) { + if (B->start <= Start && B->end >= Start) { + extendIntervalEndTo(B, End); + return B; + } + } else { + // Check to make sure that we are not overlapping two live ranges with + // different valno's. + assert(B->end <= Start && + "Cannot overlap two LiveRanges with differing ValID's" + " (did you def the same reg twice in a MachineInstr?)"); + } + } + + // Otherwise, if this range ends in the middle of, or right next to, another + // interval, merge it into that interval. + if (it != ranges.end()) { + if (LR.valno == it->valno) { + if (it->start <= End) { + it = extendIntervalStartTo(it, Start); + + // If LR is a complete superset of an interval, we may need to grow its + // endpoint as well. + if (End > it->end) + extendIntervalEndTo(it, End); + else if (End < it->end) + // Overlapping intervals, there might have been a kill here. + it->valno->removeKill(End); + return it; + } + } else { + // Check to make sure that we are not overlapping two live ranges with + // different valno's. + assert(it->start >= End && + "Cannot overlap two LiveRanges with differing ValID's"); + } + } + + // Otherwise, this is just a new range that doesn't interact with anything. + // Insert it. + return ranges.insert(it, LR); +} + +/// isInOneLiveRange - Return true if the range specified is entirely in +/// a single LiveRange of the live interval. +bool LiveInterval::isInOneLiveRange(SlotIndex Start, SlotIndex End) { + Ranges::iterator I = std::upper_bound(ranges.begin(), ranges.end(), Start); + if (I == ranges.begin()) + return false; + --I; + return I->containsRange(Start, End); +} + + +/// removeRange - Remove the specified range from this interval. Note that +/// the range must be in a single LiveRange in its entirety. +void LiveInterval::removeRange(SlotIndex Start, SlotIndex End, + bool RemoveDeadValNo) { + // Find the LiveRange containing this span. + Ranges::iterator I = std::upper_bound(ranges.begin(), ranges.end(), Start); + assert(I != ranges.begin() && "Range is not in interval!"); + --I; + assert(I->containsRange(Start, End) && "Range is not entirely in interval!"); + + // If the span we are removing is at the start of the LiveRange, adjust it. + VNInfo *ValNo = I->valno; + if (I->start == Start) { + if (I->end == End) { + ValNo->removeKills(Start, End); + if (RemoveDeadValNo) { + // Check if val# is dead. + bool isDead = true; + for (const_iterator II = begin(), EE = end(); II != EE; ++II) + if (II != I && II->valno == ValNo) { + isDead = false; + break; + } + if (isDead) { + // Now that ValNo is dead, remove it. If it is the largest value + // number, just nuke it (and any other deleted values neighboring it), + // otherwise mark it as ~1U so it can be nuked later. + if (ValNo->id == getNumValNums()-1) { + do { + VNInfo *VNI = valnos.back(); + valnos.pop_back(); + VNI->~VNInfo(); + } while (!valnos.empty() && valnos.back()->isUnused()); + } else { + ValNo->setIsUnused(true); + } + } + } + + ranges.erase(I); // Removed the whole LiveRange. + } else + I->start = End; + return; + } + + // Otherwise if the span we are removing is at the end of the LiveRange, + // adjust the other way. + if (I->end == End) { + ValNo->removeKills(Start, End); + I->end = Start; + return; + } + + // Otherwise, we are splitting the LiveRange into two pieces. + SlotIndex OldEnd = I->end; + I->end = Start; // Trim the old interval. + + // Insert the new one. + ranges.insert(next(I), LiveRange(End, OldEnd, ValNo)); +} + +/// removeValNo - Remove all the ranges defined by the specified value#. +/// Also remove the value# from value# list. +void LiveInterval::removeValNo(VNInfo *ValNo) { + if (empty()) return; + Ranges::iterator I = ranges.end(); + Ranges::iterator E = ranges.begin(); + do { + --I; + if (I->valno == ValNo) + ranges.erase(I); + } while (I != E); + // Now that ValNo is dead, remove it. If it is the largest value + // number, just nuke it (and any other deleted values neighboring it), + // otherwise mark it as ~1U so it can be nuked later. + if (ValNo->id == getNumValNums()-1) { + do { + VNInfo *VNI = valnos.back(); + valnos.pop_back(); + VNI->~VNInfo(); + } while (!valnos.empty() && valnos.back()->isUnused()); + } else { + ValNo->setIsUnused(true); + } +} + +/// getLiveRangeContaining - Return the live range that contains the +/// specified index, or null if there is none. +LiveInterval::const_iterator +LiveInterval::FindLiveRangeContaining(SlotIndex Idx) const { + const_iterator It = std::upper_bound(begin(), end(), Idx); + if (It != ranges.begin()) { + --It; + if (It->contains(Idx)) + return It; + } + + return end(); +} + +LiveInterval::iterator +LiveInterval::FindLiveRangeContaining(SlotIndex Idx) { + iterator It = std::upper_bound(begin(), end(), Idx); + if (It != begin()) { + --It; + if (It->contains(Idx)) + return It; + } + + return end(); +} + +/// findDefinedVNInfo - Find the VNInfo defined by the specified +/// index (register interval). +VNInfo *LiveInterval::findDefinedVNInfoForRegInt(SlotIndex Idx) const { + for (LiveInterval::const_vni_iterator i = vni_begin(), e = vni_end(); + i != e; ++i) { + if ((*i)->def == Idx) + return *i; + } + + return 0; +} + +/// findDefinedVNInfo - Find the VNInfo defined by the specified +/// register (stack inteval). +VNInfo *LiveInterval::findDefinedVNInfoForStackInt(unsigned reg) const { + for (LiveInterval::const_vni_iterator i = vni_begin(), e = vni_end(); + i != e; ++i) { + if ((*i)->getReg() == reg) + return *i; + } + return 0; +} + +/// join - Join two live intervals (this, and other) together. This applies +/// mappings to the value numbers in the LHS/RHS intervals as specified. If +/// the intervals are not joinable, this aborts. +void LiveInterval::join(LiveInterval &Other, + const int *LHSValNoAssignments, + const int *RHSValNoAssignments, + SmallVector &NewVNInfo, + MachineRegisterInfo *MRI) { + // Determine if any of our live range values are mapped. This is uncommon, so + // we want to avoid the interval scan if not. + bool MustMapCurValNos = false; + unsigned NumVals = getNumValNums(); + unsigned NumNewVals = NewVNInfo.size(); + for (unsigned i = 0; i != NumVals; ++i) { + unsigned LHSValID = LHSValNoAssignments[i]; + if (i != LHSValID || + (NewVNInfo[LHSValID] && NewVNInfo[LHSValID] != getValNumInfo(i))) + MustMapCurValNos = true; + } + + // If we have to apply a mapping to our base interval assignment, rewrite it + // now. + if (MustMapCurValNos) { + // Map the first live range. + iterator OutIt = begin(); + OutIt->valno = NewVNInfo[LHSValNoAssignments[OutIt->valno->id]]; + ++OutIt; + for (iterator I = OutIt, E = end(); I != E; ++I) { + OutIt->valno = NewVNInfo[LHSValNoAssignments[I->valno->id]]; + + // If this live range has the same value # as its immediate predecessor, + // and if they are neighbors, remove one LiveRange. This happens when we + // have [0,3:0)[4,7:1) and map 0/1 onto the same value #. + if (OutIt->valno == (OutIt-1)->valno && (OutIt-1)->end == OutIt->start) { + (OutIt-1)->end = OutIt->end; + } else { + if (I != OutIt) { + OutIt->start = I->start; + OutIt->end = I->end; + } + + // Didn't merge, on to the next one. + ++OutIt; + } + } + + // If we merge some live ranges, chop off the end. + ranges.erase(OutIt, end()); + } + + // Remember assignements because val# ids are changing. + SmallVector OtherAssignments; + for (iterator I = Other.begin(), E = Other.end(); I != E; ++I) + OtherAssignments.push_back(RHSValNoAssignments[I->valno->id]); + + // Update val# info. Renumber them and make sure they all belong to this + // LiveInterval now. Also remove dead val#'s. + unsigned NumValNos = 0; + for (unsigned i = 0; i < NumNewVals; ++i) { + VNInfo *VNI = NewVNInfo[i]; + if (VNI) { + if (NumValNos >= NumVals) + valnos.push_back(VNI); + else + valnos[NumValNos] = VNI; + VNI->id = NumValNos++; // Renumber val#. + } + } + if (NumNewVals < NumVals) + valnos.resize(NumNewVals); // shrinkify + + // Okay, now insert the RHS live ranges into the LHS. + iterator InsertPos = begin(); + unsigned RangeNo = 0; + for (iterator I = Other.begin(), E = Other.end(); I != E; ++I, ++RangeNo) { + // Map the valno in the other live range to the current live range. + I->valno = NewVNInfo[OtherAssignments[RangeNo]]; + assert(I->valno && "Adding a dead range?"); + InsertPos = addRangeFrom(*I, InsertPos); + } + + ComputeJoinedWeight(Other); + + // Update regalloc hint if currently there isn't one. + if (TargetRegisterInfo::isVirtualRegister(reg) && + TargetRegisterInfo::isVirtualRegister(Other.reg)) { + std::pair Hint = MRI->getRegAllocationHint(reg); + if (Hint.first == 0 && Hint.second == 0) { + std::pair OtherHint = + MRI->getRegAllocationHint(Other.reg); + if (OtherHint.first || OtherHint.second) + MRI->setRegAllocationHint(reg, OtherHint.first, OtherHint.second); + } + } +} + +/// MergeRangesInAsValue - Merge all of the intervals in RHS into this live +/// interval as the specified value number. The LiveRanges in RHS are +/// allowed to overlap with LiveRanges in the current interval, but only if +/// the overlapping LiveRanges have the specified value number. +void LiveInterval::MergeRangesInAsValue(const LiveInterval &RHS, + VNInfo *LHSValNo) { + // TODO: Make this more efficient. + iterator InsertPos = begin(); + for (const_iterator I = RHS.begin(), E = RHS.end(); I != E; ++I) { + // Map the valno in the other live range to the current live range. + LiveRange Tmp = *I; + Tmp.valno = LHSValNo; + InsertPos = addRangeFrom(Tmp, InsertPos); + } +} + + +/// MergeValueInAsValue - Merge all of the live ranges of a specific val# +/// in RHS into this live interval as the specified value number. +/// The LiveRanges in RHS are allowed to overlap with LiveRanges in the +/// current interval, it will replace the value numbers of the overlaped +/// live ranges with the specified value number. +void LiveInterval::MergeValueInAsValue( + const LiveInterval &RHS, + const VNInfo *RHSValNo, VNInfo *LHSValNo) { + SmallVector ReplacedValNos; + iterator IP = begin(); + for (const_iterator I = RHS.begin(), E = RHS.end(); I != E; ++I) { + if (I->valno != RHSValNo) + continue; + SlotIndex Start = I->start, End = I->end; + IP = std::upper_bound(IP, end(), Start); + // If the start of this range overlaps with an existing liverange, trim it. + if (IP != begin() && IP[-1].end > Start) { + if (IP[-1].valno != LHSValNo) { + ReplacedValNos.push_back(IP[-1].valno); + IP[-1].valno = LHSValNo; // Update val#. + } + Start = IP[-1].end; + // Trimmed away the whole range? + if (Start >= End) continue; + } + // If the end of this range overlaps with an existing liverange, trim it. + if (IP != end() && End > IP->start) { + if (IP->valno != LHSValNo) { + ReplacedValNos.push_back(IP->valno); + IP->valno = LHSValNo; // Update val#. + } + End = IP->start; + // If this trimmed away the whole range, ignore it. + if (Start == End) continue; + } + + // Map the valno in the other live range to the current live range. + IP = addRangeFrom(LiveRange(Start, End, LHSValNo), IP); + } + + + SmallSet Seen; + for (unsigned i = 0, e = ReplacedValNos.size(); i != e; ++i) { + VNInfo *V1 = ReplacedValNos[i]; + if (Seen.insert(V1)) { + bool isDead = true; + for (const_iterator I = begin(), E = end(); I != E; ++I) + if (I->valno == V1) { + isDead = false; + break; + } + if (isDead) { + // Now that V1 is dead, remove it. If it is the largest value number, + // just nuke it (and any other deleted values neighboring it), otherwise + // mark it as ~1U so it can be nuked later. + if (V1->id == getNumValNums()-1) { + do { + VNInfo *VNI = valnos.back(); + valnos.pop_back(); + VNI->~VNInfo(); + } while (!valnos.empty() && valnos.back()->isUnused()); + } else { + V1->setIsUnused(true); + } + } + } + } +} + + +/// MergeInClobberRanges - For any live ranges that are not defined in the +/// current interval, but are defined in the Clobbers interval, mark them +/// used with an unknown definition value. +void LiveInterval::MergeInClobberRanges(LiveIntervals &li_, + const LiveInterval &Clobbers, + BumpPtrAllocator &VNInfoAllocator) { + if (Clobbers.empty()) return; + + DenseMap ValNoMaps; + VNInfo *UnusedValNo = 0; + iterator IP = begin(); + for (const_iterator I = Clobbers.begin(), E = Clobbers.end(); I != E; ++I) { + // For every val# in the Clobbers interval, create a new "unknown" val#. + VNInfo *ClobberValNo = 0; + DenseMap::iterator VI = ValNoMaps.find(I->valno); + if (VI != ValNoMaps.end()) + ClobberValNo = VI->second; + else if (UnusedValNo) + ClobberValNo = UnusedValNo; + else { + UnusedValNo = ClobberValNo = + getNextValue(li_.getInvalidIndex(), 0, false, VNInfoAllocator); + ValNoMaps.insert(std::make_pair(I->valno, ClobberValNo)); + } + + bool Done = false; + SlotIndex Start = I->start, End = I->end; + // If a clobber range starts before an existing range and ends after + // it, the clobber range will need to be split into multiple ranges. + // Loop until the entire clobber range is handled. + while (!Done) { + Done = true; + IP = std::upper_bound(IP, end(), Start); + SlotIndex SubRangeStart = Start; + SlotIndex SubRangeEnd = End; + + // If the start of this range overlaps with an existing liverange, trim it. + if (IP != begin() && IP[-1].end > SubRangeStart) { + SubRangeStart = IP[-1].end; + // Trimmed away the whole range? + if (SubRangeStart >= SubRangeEnd) continue; + } + // If the end of this range overlaps with an existing liverange, trim it. + if (IP != end() && SubRangeEnd > IP->start) { + // If the clobber live range extends beyond the existing live range, + // it'll need at least another live range, so set the flag to keep + // iterating. + if (SubRangeEnd > IP->end) { + Start = IP->end; + Done = false; + } + SubRangeEnd = IP->start; + // If this trimmed away the whole range, ignore it. + if (SubRangeStart == SubRangeEnd) continue; + } + + // Insert the clobber interval. + IP = addRangeFrom(LiveRange(SubRangeStart, SubRangeEnd, ClobberValNo), + IP); + UnusedValNo = 0; + } + } + + if (UnusedValNo) { + // Delete the last unused val#. + valnos.pop_back(); + UnusedValNo->~VNInfo(); + } +} + +void LiveInterval::MergeInClobberRange(LiveIntervals &li_, + SlotIndex Start, + SlotIndex End, + BumpPtrAllocator &VNInfoAllocator) { + // Find a value # to use for the clobber ranges. If there is already a value# + // for unknown values, use it. + VNInfo *ClobberValNo = + getNextValue(li_.getInvalidIndex(), 0, false, VNInfoAllocator); + + iterator IP = begin(); + IP = std::upper_bound(IP, end(), Start); + + // If the start of this range overlaps with an existing liverange, trim it. + if (IP != begin() && IP[-1].end > Start) { + Start = IP[-1].end; + // Trimmed away the whole range? + if (Start >= End) return; + } + // If the end of this range overlaps with an existing liverange, trim it. + if (IP != end() && End > IP->start) { + End = IP->start; + // If this trimmed away the whole range, ignore it. + if (Start == End) return; + } + + // Insert the clobber interval. + addRangeFrom(LiveRange(Start, End, ClobberValNo), IP); +} + +/// MergeValueNumberInto - This method is called when two value nubmers +/// are found to be equivalent. This eliminates V1, replacing all +/// LiveRanges with the V1 value number with the V2 value number. This can +/// cause merging of V1/V2 values numbers and compaction of the value space. +VNInfo* LiveInterval::MergeValueNumberInto(VNInfo *V1, VNInfo *V2) { + assert(V1 != V2 && "Identical value#'s are always equivalent!"); + + // This code actually merges the (numerically) larger value number into the + // smaller value number, which is likely to allow us to compactify the value + // space. The only thing we have to be careful of is to preserve the + // instruction that defines the result value. + + // Make sure V2 is smaller than V1. + if (V1->id < V2->id) { + V1->copyFrom(*V2); + std::swap(V1, V2); + } + + // Merge V1 live ranges into V2. + for (iterator I = begin(); I != end(); ) { + iterator LR = I++; + if (LR->valno != V1) continue; // Not a V1 LiveRange. + + // Okay, we found a V1 live range. If it had a previous, touching, V2 live + // range, extend it. + if (LR != begin()) { + iterator Prev = LR-1; + if (Prev->valno == V2 && Prev->end == LR->start) { + Prev->end = LR->end; + + // Erase this live-range. + ranges.erase(LR); + I = Prev+1; + LR = Prev; + } + } + + // Okay, now we have a V1 or V2 live range that is maximally merged forward. + // Ensure that it is a V2 live-range. + LR->valno = V2; + + // If we can merge it into later V2 live ranges, do so now. We ignore any + // following V1 live ranges, as they will be merged in subsequent iterations + // of the loop. + if (I != end()) { + if (I->start == LR->end && I->valno == V2) { + LR->end = I->end; + ranges.erase(I); + I = LR+1; + } + } + } + + // Now that V1 is dead, remove it. If it is the largest value number, just + // nuke it (and any other deleted values neighboring it), otherwise mark it as + // ~1U so it can be nuked later. + if (V1->id == getNumValNums()-1) { + do { + VNInfo *VNI = valnos.back(); + valnos.pop_back(); + VNI->~VNInfo(); + } while (valnos.back()->isUnused()); + } else { + V1->setIsUnused(true); + } + + return V2; +} + +void LiveInterval::Copy(const LiveInterval &RHS, + MachineRegisterInfo *MRI, + BumpPtrAllocator &VNInfoAllocator) { + ranges.clear(); + valnos.clear(); + std::pair Hint = MRI->getRegAllocationHint(RHS.reg); + MRI->setRegAllocationHint(reg, Hint.first, Hint.second); + + weight = RHS.weight; + for (unsigned i = 0, e = RHS.getNumValNums(); i != e; ++i) { + const VNInfo *VNI = RHS.getValNumInfo(i); + createValueCopy(VNI, VNInfoAllocator); + } + for (unsigned i = 0, e = RHS.ranges.size(); i != e; ++i) { + const LiveRange &LR = RHS.ranges[i]; + addRange(LiveRange(LR.start, LR.end, getValNumInfo(LR.valno->id))); + } +} + +unsigned LiveInterval::getSize() const { + unsigned Sum = 0; + for (const_iterator I = begin(), E = end(); I != E; ++I) + Sum += I->start.distance(I->end); + return Sum; +} + +/// ComputeJoinedWeight - Set the weight of a live interval Joined +/// after Other has been merged into it. +void LiveInterval::ComputeJoinedWeight(const LiveInterval &Other) { + // If either of these intervals was spilled, the weight is the + // weight of the non-spilled interval. This can only happen with + // iterative coalescers. + + if (Other.weight != HUGE_VALF) { + weight += Other.weight; + } + else if (weight == HUGE_VALF && + !TargetRegisterInfo::isPhysicalRegister(reg)) { + // Remove this assert if you have an iterative coalescer + assert(0 && "Joining to spilled interval"); + weight = Other.weight; + } + else { + // Otherwise the weight stays the same + // Remove this assert if you have an iterative coalescer + assert(0 && "Joining from spilled interval"); + } +} + +raw_ostream& llvm::operator<<(raw_ostream& os, const LiveRange &LR) { + return os << '[' << LR.start << ',' << LR.end << ':' << LR.valno->id << ")"; +} + +void LiveRange::dump() const { + errs() << *this << "\n"; +} + +void LiveInterval::print(raw_ostream &OS, const TargetRegisterInfo *TRI) const { + if (isStackSlot()) + OS << "SS#" << getStackSlotIndex(); + else if (TRI && TargetRegisterInfo::isPhysicalRegister(reg)) + OS << TRI->getName(reg); + else + OS << "%reg" << reg; + + OS << ',' << weight; + + if (empty()) + OS << " EMPTY"; + else { + OS << " = "; + for (LiveInterval::Ranges::const_iterator I = ranges.begin(), + E = ranges.end(); I != E; ++I) + OS << *I; + } + + // Print value number info. + if (getNumValNums()) { + OS << " "; + unsigned vnum = 0; + for (const_vni_iterator i = vni_begin(), e = vni_end(); i != e; + ++i, ++vnum) { + const VNInfo *vni = *i; + if (vnum) OS << " "; + OS << vnum << "@"; + if (vni->isUnused()) { + OS << "x"; + } else { + if (!vni->isDefAccurate()) + OS << "?"; + else + OS << vni->def; + unsigned ee = vni->kills.size(); + if (ee || vni->hasPHIKill()) { + OS << "-("; + for (unsigned j = 0; j != ee; ++j) { + OS << vni->kills[j]; + if (j != ee-1) + OS << " "; + } + if (vni->hasPHIKill()) { + if (ee) + OS << " "; + OS << "phi"; + } + OS << ")"; + } + } + } + } +} + +void LiveInterval::dump() const { + errs() << *this << "\n"; +} + + +void LiveRange::print(raw_ostream &os) const { + os << *this; +} diff --git a/libclamav/c++/llvm/lib/CodeGen/LiveIntervalAnalysis.cpp b/libclamav/c++/llvm/lib/CodeGen/LiveIntervalAnalysis.cpp new file mode 100644 index 000000000..4412c1b02 --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/LiveIntervalAnalysis.cpp @@ -0,0 +1,2065 @@ +//===-- LiveIntervalAnalysis.cpp - Live Interval Analysis -----------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the LiveInterval analysis pass which is used +// by the Linear Scan Register allocator. This pass linearizes the +// basic blocks of the function in DFS order and uses the +// LiveVariables pass to conservatively compute live intervals for +// each virtual and physical register. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "liveintervals" +#include "llvm/CodeGen/LiveIntervalAnalysis.h" +#include "VirtRegMap.h" +#include "llvm/Value.h" +#include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/CodeGen/LiveVariables.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineLoopInfo.h" +#include "llvm/CodeGen/MachineMemOperand.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/CodeGen/ProcessImplicitDefs.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetOptions.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/ADT/DepthFirstIterator.h" +#include "llvm/ADT/SmallSet.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/ADT/STLExtras.h" +#include +#include +#include +using namespace llvm; + +// Hidden options for help debugging. +static cl::opt DisableReMat("disable-rematerialization", + cl::init(false), cl::Hidden); + +static cl::opt EnableFastSpilling("fast-spill", + cl::init(false), cl::Hidden); + +STATISTIC(numIntervals , "Number of original intervals"); +STATISTIC(numFolds , "Number of loads/stores folded into instructions"); +STATISTIC(numSplits , "Number of intervals split"); + +char LiveIntervals::ID = 0; +static RegisterPass X("liveintervals", "Live Interval Analysis"); + +void LiveIntervals::getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesCFG(); + AU.addRequired(); + AU.addPreserved(); + AU.addPreserved(); + AU.addRequired(); + AU.addPreservedID(MachineLoopInfoID); + AU.addPreservedID(MachineDominatorsID); + + if (!StrongPHIElim) { + AU.addPreservedID(PHIEliminationID); + AU.addRequiredID(PHIEliminationID); + } + + AU.addRequiredID(TwoAddressInstructionPassID); + AU.addPreserved(); + AU.addRequired(); + AU.addPreserved(); + AU.addRequiredTransitive(); + MachineFunctionPass::getAnalysisUsage(AU); +} + +void LiveIntervals::releaseMemory() { + // Free the live intervals themselves. + for (DenseMap::iterator I = r2iMap_.begin(), + E = r2iMap_.end(); I != E; ++I) + delete I->second; + + r2iMap_.clear(); + + // Release VNInfo memroy regions after all VNInfo objects are dtor'd. + VNInfoAllocator.Reset(); + while (!CloneMIs.empty()) { + MachineInstr *MI = CloneMIs.back(); + CloneMIs.pop_back(); + mf_->DeleteMachineInstr(MI); + } +} + +/// runOnMachineFunction - Register allocate the whole function +/// +bool LiveIntervals::runOnMachineFunction(MachineFunction &fn) { + mf_ = &fn; + mri_ = &mf_->getRegInfo(); + tm_ = &fn.getTarget(); + tri_ = tm_->getRegisterInfo(); + tii_ = tm_->getInstrInfo(); + aa_ = &getAnalysis(); + lv_ = &getAnalysis(); + indexes_ = &getAnalysis(); + allocatableRegs_ = tri_->getAllocatableSet(fn); + + computeIntervals(); + + numIntervals += getNumIntervals(); + + DEBUG(dump()); + return true; +} + +/// print - Implement the dump method. +void LiveIntervals::print(raw_ostream &OS, const Module* ) const { + OS << "********** INTERVALS **********\n"; + for (const_iterator I = begin(), E = end(); I != E; ++I) { + I->second->print(OS, tri_); + OS << "\n"; + } + + printInstrs(OS); +} + +void LiveIntervals::printInstrs(raw_ostream &OS) const { + OS << "********** MACHINEINSTRS **********\n"; + + for (MachineFunction::iterator mbbi = mf_->begin(), mbbe = mf_->end(); + mbbi != mbbe; ++mbbi) { + OS << "BB#" << mbbi->getNumber() + << ":\t\t# derived from " << mbbi->getName() << "\n"; + for (MachineBasicBlock::iterator mii = mbbi->begin(), + mie = mbbi->end(); mii != mie; ++mii) { + OS << getInstructionIndex(mii) << '\t' << *mii; + } + } +} + +void LiveIntervals::dumpInstrs() const { + printInstrs(errs()); +} + +/// conflictsWithPhysRegDef - Returns true if the specified register +/// is defined during the duration of the specified interval. +bool LiveIntervals::conflictsWithPhysRegDef(const LiveInterval &li, + VirtRegMap &vrm, unsigned reg) { + for (LiveInterval::Ranges::const_iterator + I = li.ranges.begin(), E = li.ranges.end(); I != E; ++I) { + for (SlotIndex index = I->start.getBaseIndex(), + end = I->end.getPrevSlot().getBaseIndex().getNextIndex(); + index != end; + index = index.getNextIndex()) { + // skip deleted instructions + while (index != end && !getInstructionFromIndex(index)) + index = index.getNextIndex(); + if (index == end) break; + + MachineInstr *MI = getInstructionFromIndex(index); + unsigned SrcReg, DstReg, SrcSubReg, DstSubReg; + if (tii_->isMoveInstr(*MI, SrcReg, DstReg, SrcSubReg, DstSubReg)) + if (SrcReg == li.reg || DstReg == li.reg) + continue; + for (unsigned i = 0; i != MI->getNumOperands(); ++i) { + MachineOperand& mop = MI->getOperand(i); + if (!mop.isReg()) + continue; + unsigned PhysReg = mop.getReg(); + if (PhysReg == 0 || PhysReg == li.reg) + continue; + if (TargetRegisterInfo::isVirtualRegister(PhysReg)) { + if (!vrm.hasPhys(PhysReg)) + continue; + PhysReg = vrm.getPhys(PhysReg); + } + if (PhysReg && tri_->regsOverlap(PhysReg, reg)) + return true; + } + } + } + + return false; +} + +/// conflictsWithPhysRegRef - Similar to conflictsWithPhysRegRef except +/// it can check use as well. +bool LiveIntervals::conflictsWithPhysRegRef(LiveInterval &li, + unsigned Reg, bool CheckUse, + SmallPtrSet &JoinedCopies) { + for (LiveInterval::Ranges::const_iterator + I = li.ranges.begin(), E = li.ranges.end(); I != E; ++I) { + for (SlotIndex index = I->start.getBaseIndex(), + end = I->end.getPrevSlot().getBaseIndex().getNextIndex(); + index != end; + index = index.getNextIndex()) { + // Skip deleted instructions. + MachineInstr *MI = 0; + while (index != end) { + MI = getInstructionFromIndex(index); + if (MI) + break; + index = index.getNextIndex(); + } + if (index == end) break; + + if (JoinedCopies.count(MI)) + continue; + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + MachineOperand& MO = MI->getOperand(i); + if (!MO.isReg()) + continue; + if (MO.isUse() && !CheckUse) + continue; + unsigned PhysReg = MO.getReg(); + if (PhysReg == 0 || TargetRegisterInfo::isVirtualRegister(PhysReg)) + continue; + if (tri_->isSubRegister(Reg, PhysReg)) + return true; + } + } + } + + return false; +} + +#ifndef NDEBUG +static void printRegName(unsigned reg, const TargetRegisterInfo* tri_) { + if (TargetRegisterInfo::isPhysicalRegister(reg)) + errs() << tri_->getName(reg); + else + errs() << "%reg" << reg; +} +#endif + +void LiveIntervals::handleVirtualRegisterDef(MachineBasicBlock *mbb, + MachineBasicBlock::iterator mi, + SlotIndex MIIdx, + MachineOperand& MO, + unsigned MOIdx, + LiveInterval &interval) { + DEBUG({ + errs() << "\t\tregister: "; + printRegName(interval.reg, tri_); + }); + + // Virtual registers may be defined multiple times (due to phi + // elimination and 2-addr elimination). Much of what we do only has to be + // done once for the vreg. We use an empty interval to detect the first + // time we see a vreg. + LiveVariables::VarInfo& vi = lv_->getVarInfo(interval.reg); + if (interval.empty()) { + // Get the Idx of the defining instructions. + SlotIndex defIndex = MIIdx.getDefIndex(); + // Earlyclobbers move back one, so that they overlap the live range + // of inputs. + if (MO.isEarlyClobber()) + defIndex = MIIdx.getUseIndex(); + VNInfo *ValNo; + MachineInstr *CopyMI = NULL; + unsigned SrcReg, DstReg, SrcSubReg, DstSubReg; + if (mi->getOpcode() == TargetInstrInfo::EXTRACT_SUBREG || + mi->getOpcode() == TargetInstrInfo::INSERT_SUBREG || + mi->getOpcode() == TargetInstrInfo::SUBREG_TO_REG || + tii_->isMoveInstr(*mi, SrcReg, DstReg, SrcSubReg, DstSubReg)) + CopyMI = mi; + // Earlyclobbers move back one. + ValNo = interval.getNextValue(defIndex, CopyMI, true, VNInfoAllocator); + + assert(ValNo->id == 0 && "First value in interval is not 0?"); + + // Loop over all of the blocks that the vreg is defined in. There are + // two cases we have to handle here. The most common case is a vreg + // whose lifetime is contained within a basic block. In this case there + // will be a single kill, in MBB, which comes after the definition. + if (vi.Kills.size() == 1 && vi.Kills[0]->getParent() == mbb) { + // FIXME: what about dead vars? + SlotIndex killIdx; + if (vi.Kills[0] != mi) + killIdx = getInstructionIndex(vi.Kills[0]).getDefIndex(); + else + killIdx = defIndex.getStoreIndex(); + + // If the kill happens after the definition, we have an intra-block + // live range. + if (killIdx > defIndex) { + assert(vi.AliveBlocks.empty() && + "Shouldn't be alive across any blocks!"); + LiveRange LR(defIndex, killIdx, ValNo); + interval.addRange(LR); + DEBUG(errs() << " +" << LR << "\n"); + ValNo->addKill(killIdx); + return; + } + } + + // The other case we handle is when a virtual register lives to the end + // of the defining block, potentially live across some blocks, then is + // live into some number of blocks, but gets killed. Start by adding a + // range that goes from this definition to the end of the defining block. + LiveRange NewLR(defIndex, getMBBEndIdx(mbb).getNextIndex().getLoadIndex(), + ValNo); + DEBUG(errs() << " +" << NewLR); + interval.addRange(NewLR); + + // Iterate over all of the blocks that the variable is completely + // live in, adding [insrtIndex(begin), instrIndex(end)+4) to the + // live interval. + for (SparseBitVector<>::iterator I = vi.AliveBlocks.begin(), + E = vi.AliveBlocks.end(); I != E; ++I) { + LiveRange LR( + getMBBStartIdx(mf_->getBlockNumbered(*I)), + getMBBEndIdx(mf_->getBlockNumbered(*I)).getNextIndex().getLoadIndex(), + ValNo); + interval.addRange(LR); + DEBUG(errs() << " +" << LR); + } + + // Finally, this virtual register is live from the start of any killing + // block to the 'use' slot of the killing instruction. + for (unsigned i = 0, e = vi.Kills.size(); i != e; ++i) { + MachineInstr *Kill = vi.Kills[i]; + SlotIndex killIdx = + getInstructionIndex(Kill).getDefIndex(); + LiveRange LR(getMBBStartIdx(Kill->getParent()), killIdx, ValNo); + interval.addRange(LR); + ValNo->addKill(killIdx); + DEBUG(errs() << " +" << LR); + } + + } else { + // If this is the second time we see a virtual register definition, it + // must be due to phi elimination or two addr elimination. If this is + // the result of two address elimination, then the vreg is one of the + // def-and-use register operand. + if (mi->isRegTiedToUseOperand(MOIdx)) { + // If this is a two-address definition, then we have already processed + // the live range. The only problem is that we didn't realize there + // are actually two values in the live interval. Because of this we + // need to take the LiveRegion that defines this register and split it + // into two values. + assert(interval.containsOneValue()); + SlotIndex DefIndex = interval.getValNumInfo(0)->def.getDefIndex(); + SlotIndex RedefIndex = MIIdx.getDefIndex(); + if (MO.isEarlyClobber()) + RedefIndex = MIIdx.getUseIndex(); + + const LiveRange *OldLR = + interval.getLiveRangeContaining(RedefIndex.getUseIndex()); + VNInfo *OldValNo = OldLR->valno; + + // Delete the initial value, which should be short and continuous, + // because the 2-addr copy must be in the same MBB as the redef. + interval.removeRange(DefIndex, RedefIndex); + + // Two-address vregs should always only be redefined once. This means + // that at this point, there should be exactly one value number in it. + assert(interval.containsOneValue() && "Unexpected 2-addr liveint!"); + + // The new value number (#1) is defined by the instruction we claimed + // defined value #0. + VNInfo *ValNo = interval.getNextValue(OldValNo->def, OldValNo->getCopy(), + false, // update at * + VNInfoAllocator); + ValNo->setFlags(OldValNo->getFlags()); // * <- updating here + + // Value#0 is now defined by the 2-addr instruction. + OldValNo->def = RedefIndex; + OldValNo->setCopy(0); + if (MO.isEarlyClobber()) + OldValNo->setHasRedefByEC(true); + + // Add the new live interval which replaces the range for the input copy. + LiveRange LR(DefIndex, RedefIndex, ValNo); + DEBUG(errs() << " replace range with " << LR); + interval.addRange(LR); + ValNo->addKill(RedefIndex); + + // If this redefinition is dead, we need to add a dummy unit live + // range covering the def slot. + if (MO.isDead()) + interval.addRange(LiveRange(RedefIndex, RedefIndex.getStoreIndex(), + OldValNo)); + + DEBUG({ + errs() << " RESULT: "; + interval.print(errs(), tri_); + }); + } else { + // Otherwise, this must be because of phi elimination. If this is the + // first redefinition of the vreg that we have seen, go back and change + // the live range in the PHI block to be a different value number. + if (interval.containsOneValue()) { + // Remove the old range that we now know has an incorrect number. + VNInfo *VNI = interval.getValNumInfo(0); + MachineInstr *Killer = vi.Kills[0]; + SlotIndex Start = getMBBStartIdx(Killer->getParent()); + SlotIndex End = getInstructionIndex(Killer).getDefIndex(); + DEBUG({ + errs() << " Removing [" << Start << "," << End << "] from: "; + interval.print(errs(), tri_); + errs() << "\n"; + }); + interval.removeRange(Start, End); + assert(interval.ranges.size() == 1 && + "Newly discovered PHI interval has >1 ranges."); + MachineBasicBlock *killMBB = getMBBFromIndex(interval.endIndex()); + VNI->addKill(indexes_->getTerminatorGap(killMBB)); + VNI->setHasPHIKill(true); + DEBUG({ + errs() << " RESULT: "; + interval.print(errs(), tri_); + }); + + // Replace the interval with one of a NEW value number. Note that this + // value number isn't actually defined by an instruction, weird huh? :) + LiveRange LR(Start, End, + interval.getNextValue(SlotIndex(getMBBStartIdx(mbb), true), + 0, false, VNInfoAllocator)); + LR.valno->setIsPHIDef(true); + DEBUG(errs() << " replace range with " << LR); + interval.addRange(LR); + LR.valno->addKill(End); + DEBUG({ + errs() << " RESULT: "; + interval.print(errs(), tri_); + }); + } + + // In the case of PHI elimination, each variable definition is only + // live until the end of the block. We've already taken care of the + // rest of the live range. + SlotIndex defIndex = MIIdx.getDefIndex(); + if (MO.isEarlyClobber()) + defIndex = MIIdx.getUseIndex(); + + VNInfo *ValNo; + MachineInstr *CopyMI = NULL; + unsigned SrcReg, DstReg, SrcSubReg, DstSubReg; + if (mi->getOpcode() == TargetInstrInfo::EXTRACT_SUBREG || + mi->getOpcode() == TargetInstrInfo::INSERT_SUBREG || + mi->getOpcode() == TargetInstrInfo::SUBREG_TO_REG || + tii_->isMoveInstr(*mi, SrcReg, DstReg, SrcSubReg, DstSubReg)) + CopyMI = mi; + ValNo = interval.getNextValue(defIndex, CopyMI, true, VNInfoAllocator); + + SlotIndex killIndex = getMBBEndIdx(mbb).getNextIndex().getLoadIndex(); + LiveRange LR(defIndex, killIndex, ValNo); + interval.addRange(LR); + ValNo->addKill(indexes_->getTerminatorGap(mbb)); + ValNo->setHasPHIKill(true); + DEBUG(errs() << " +" << LR); + } + } + + DEBUG(errs() << '\n'); +} + +void LiveIntervals::handlePhysicalRegisterDef(MachineBasicBlock *MBB, + MachineBasicBlock::iterator mi, + SlotIndex MIIdx, + MachineOperand& MO, + LiveInterval &interval, + MachineInstr *CopyMI) { + // A physical register cannot be live across basic block, so its + // lifetime must end somewhere in its defining basic block. + DEBUG({ + errs() << "\t\tregister: "; + printRegName(interval.reg, tri_); + }); + + SlotIndex baseIndex = MIIdx; + SlotIndex start = baseIndex.getDefIndex(); + // Earlyclobbers move back one. + if (MO.isEarlyClobber()) + start = MIIdx.getUseIndex(); + SlotIndex end = start; + + // If it is not used after definition, it is considered dead at + // the instruction defining it. Hence its interval is: + // [defSlot(def), defSlot(def)+1) + // For earlyclobbers, the defSlot was pushed back one; the extra + // advance below compensates. + if (MO.isDead()) { + DEBUG(errs() << " dead"); + end = start.getStoreIndex(); + goto exit; + } + + // If it is not dead on definition, it must be killed by a + // subsequent instruction. Hence its interval is: + // [defSlot(def), useSlot(kill)+1) + baseIndex = baseIndex.getNextIndex(); + while (++mi != MBB->end()) { + + if (getInstructionFromIndex(baseIndex) == 0) + baseIndex = indexes_->getNextNonNullIndex(baseIndex); + + if (mi->killsRegister(interval.reg, tri_)) { + DEBUG(errs() << " killed"); + end = baseIndex.getDefIndex(); + goto exit; + } else { + int DefIdx = mi->findRegisterDefOperandIdx(interval.reg, false, tri_); + if (DefIdx != -1) { + if (mi->isRegTiedToUseOperand(DefIdx)) { + // Two-address instruction. + end = baseIndex.getDefIndex(); + assert(!mi->getOperand(DefIdx).isEarlyClobber() && + "Two address instruction is an early clobber?"); + } else { + // Another instruction redefines the register before it is ever read. + // Then the register is essentially dead at the instruction that defines + // it. Hence its interval is: + // [defSlot(def), defSlot(def)+1) + DEBUG(errs() << " dead"); + end = start.getStoreIndex(); + } + goto exit; + } + } + + baseIndex = baseIndex.getNextIndex(); + } + + // The only case we should have a dead physreg here without a killing or + // instruction where we know it's dead is if it is live-in to the function + // and never used. Another possible case is the implicit use of the + // physical register has been deleted by two-address pass. + end = start.getStoreIndex(); + +exit: + assert(start < end && "did not find end of interval?"); + + // Already exists? Extend old live interval. + LiveInterval::iterator OldLR = interval.FindLiveRangeContaining(start); + bool Extend = OldLR != interval.end(); + VNInfo *ValNo = Extend + ? OldLR->valno : interval.getNextValue(start, CopyMI, true, VNInfoAllocator); + if (MO.isEarlyClobber() && Extend) + ValNo->setHasRedefByEC(true); + LiveRange LR(start, end, ValNo); + interval.addRange(LR); + LR.valno->addKill(end); + DEBUG(errs() << " +" << LR << '\n'); +} + +void LiveIntervals::handleRegisterDef(MachineBasicBlock *MBB, + MachineBasicBlock::iterator MI, + SlotIndex MIIdx, + MachineOperand& MO, + unsigned MOIdx) { + if (TargetRegisterInfo::isVirtualRegister(MO.getReg())) + handleVirtualRegisterDef(MBB, MI, MIIdx, MO, MOIdx, + getOrCreateInterval(MO.getReg())); + else if (allocatableRegs_[MO.getReg()]) { + MachineInstr *CopyMI = NULL; + unsigned SrcReg, DstReg, SrcSubReg, DstSubReg; + if (MI->getOpcode() == TargetInstrInfo::EXTRACT_SUBREG || + MI->getOpcode() == TargetInstrInfo::INSERT_SUBREG || + MI->getOpcode() == TargetInstrInfo::SUBREG_TO_REG || + tii_->isMoveInstr(*MI, SrcReg, DstReg, SrcSubReg, DstSubReg)) + CopyMI = MI; + handlePhysicalRegisterDef(MBB, MI, MIIdx, MO, + getOrCreateInterval(MO.getReg()), CopyMI); + // Def of a register also defines its sub-registers. + for (const unsigned* AS = tri_->getSubRegisters(MO.getReg()); *AS; ++AS) + // If MI also modifies the sub-register explicitly, avoid processing it + // more than once. Do not pass in TRI here so it checks for exact match. + if (!MI->modifiesRegister(*AS)) + handlePhysicalRegisterDef(MBB, MI, MIIdx, MO, + getOrCreateInterval(*AS), 0); + } +} + +void LiveIntervals::handleLiveInRegister(MachineBasicBlock *MBB, + SlotIndex MIIdx, + LiveInterval &interval, bool isAlias) { + DEBUG({ + errs() << "\t\tlivein register: "; + printRegName(interval.reg, tri_); + }); + + // Look for kills, if it reaches a def before it's killed, then it shouldn't + // be considered a livein. + MachineBasicBlock::iterator mi = MBB->begin(); + SlotIndex baseIndex = MIIdx; + SlotIndex start = baseIndex; + if (getInstructionFromIndex(baseIndex) == 0) + baseIndex = indexes_->getNextNonNullIndex(baseIndex); + + SlotIndex end = baseIndex; + bool SeenDefUse = false; + + while (mi != MBB->end()) { + if (mi->killsRegister(interval.reg, tri_)) { + DEBUG(errs() << " killed"); + end = baseIndex.getDefIndex(); + SeenDefUse = true; + break; + } else if (mi->modifiesRegister(interval.reg, tri_)) { + // Another instruction redefines the register before it is ever read. + // Then the register is essentially dead at the instruction that defines + // it. Hence its interval is: + // [defSlot(def), defSlot(def)+1) + DEBUG(errs() << " dead"); + end = start.getStoreIndex(); + SeenDefUse = true; + break; + } + + ++mi; + if (mi != MBB->end()) { + baseIndex = indexes_->getNextNonNullIndex(baseIndex); + } + } + + // Live-in register might not be used at all. + if (!SeenDefUse) { + if (isAlias) { + DEBUG(errs() << " dead"); + end = MIIdx.getStoreIndex(); + } else { + DEBUG(errs() << " live through"); + end = baseIndex; + } + } + + VNInfo *vni = + interval.getNextValue(SlotIndex(getMBBStartIdx(MBB), true), + 0, false, VNInfoAllocator); + vni->setIsPHIDef(true); + LiveRange LR(start, end, vni); + + interval.addRange(LR); + LR.valno->addKill(end); + DEBUG(errs() << " +" << LR << '\n'); +} + +/// computeIntervals - computes the live intervals for virtual +/// registers. for some ordering of the machine instructions [1,N] a +/// live interval is an interval [i, j) where 1 <= i <= j < N for +/// which a variable is live +void LiveIntervals::computeIntervals() { + DEBUG(errs() << "********** COMPUTING LIVE INTERVALS **********\n" + << "********** Function: " + << ((Value*)mf_->getFunction())->getName() << '\n'); + + SmallVector UndefUses; + for (MachineFunction::iterator MBBI = mf_->begin(), E = mf_->end(); + MBBI != E; ++MBBI) { + MachineBasicBlock *MBB = MBBI; + // Track the index of the current machine instr. + SlotIndex MIIndex = getMBBStartIdx(MBB); + DEBUG(errs() << MBB->getName() << ":\n"); + + MachineBasicBlock::iterator MI = MBB->begin(), miEnd = MBB->end(); + + // Create intervals for live-ins to this BB first. + for (MachineBasicBlock::const_livein_iterator LI = MBB->livein_begin(), + LE = MBB->livein_end(); LI != LE; ++LI) { + handleLiveInRegister(MBB, MIIndex, getOrCreateInterval(*LI)); + // Multiple live-ins can alias the same register. + for (const unsigned* AS = tri_->getSubRegisters(*LI); *AS; ++AS) + if (!hasInterval(*AS)) + handleLiveInRegister(MBB, MIIndex, getOrCreateInterval(*AS), + true); + } + + // Skip over empty initial indices. + if (getInstructionFromIndex(MIIndex) == 0) + MIIndex = indexes_->getNextNonNullIndex(MIIndex); + + for (; MI != miEnd; ++MI) { + DEBUG(errs() << MIIndex << "\t" << *MI); + + // Handle defs. + for (int i = MI->getNumOperands() - 1; i >= 0; --i) { + MachineOperand &MO = MI->getOperand(i); + if (!MO.isReg() || !MO.getReg()) + continue; + + // handle register defs - build intervals + if (MO.isDef()) + handleRegisterDef(MBB, MI, MIIndex, MO, i); + else if (MO.isUndef()) + UndefUses.push_back(MO.getReg()); + } + + // Move to the next instr slot. + MIIndex = indexes_->getNextNonNullIndex(MIIndex); + } + } + + // Create empty intervals for registers defined by implicit_def's (except + // for those implicit_def that define values which are liveout of their + // blocks. + for (unsigned i = 0, e = UndefUses.size(); i != e; ++i) { + unsigned UndefReg = UndefUses[i]; + (void)getOrCreateInterval(UndefReg); + } +} + +LiveInterval* LiveIntervals::createInterval(unsigned reg) { + float Weight = TargetRegisterInfo::isPhysicalRegister(reg) ? HUGE_VALF : 0.0F; + return new LiveInterval(reg, Weight); +} + +/// dupInterval - Duplicate a live interval. The caller is responsible for +/// managing the allocated memory. +LiveInterval* LiveIntervals::dupInterval(LiveInterval *li) { + LiveInterval *NewLI = createInterval(li->reg); + NewLI->Copy(*li, mri_, getVNInfoAllocator()); + return NewLI; +} + +/// getVNInfoSourceReg - Helper function that parses the specified VNInfo +/// copy field and returns the source register that defines it. +unsigned LiveIntervals::getVNInfoSourceReg(const VNInfo *VNI) const { + if (!VNI->getCopy()) + return 0; + + if (VNI->getCopy()->getOpcode() == TargetInstrInfo::EXTRACT_SUBREG) { + // If it's extracting out of a physical register, return the sub-register. + unsigned Reg = VNI->getCopy()->getOperand(1).getReg(); + if (TargetRegisterInfo::isPhysicalRegister(Reg)) + Reg = tri_->getSubReg(Reg, VNI->getCopy()->getOperand(2).getImm()); + return Reg; + } else if (VNI->getCopy()->getOpcode() == TargetInstrInfo::INSERT_SUBREG || + VNI->getCopy()->getOpcode() == TargetInstrInfo::SUBREG_TO_REG) + return VNI->getCopy()->getOperand(2).getReg(); + + unsigned SrcReg, DstReg, SrcSubReg, DstSubReg; + if (tii_->isMoveInstr(*VNI->getCopy(), SrcReg, DstReg, SrcSubReg, DstSubReg)) + return SrcReg; + llvm_unreachable("Unrecognized copy instruction!"); + return 0; +} + +//===----------------------------------------------------------------------===// +// Register allocator hooks. +// + +/// getReMatImplicitUse - If the remat definition MI has one (for now, we only +/// allow one) virtual register operand, then its uses are implicitly using +/// the register. Returns the virtual register. +unsigned LiveIntervals::getReMatImplicitUse(const LiveInterval &li, + MachineInstr *MI) const { + unsigned RegOp = 0; + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + MachineOperand &MO = MI->getOperand(i); + if (!MO.isReg() || !MO.isUse()) + continue; + unsigned Reg = MO.getReg(); + if (Reg == 0 || Reg == li.reg) + continue; + + if (TargetRegisterInfo::isPhysicalRegister(Reg) && + !allocatableRegs_[Reg]) + continue; + // FIXME: For now, only remat MI with at most one register operand. + assert(!RegOp && + "Can't rematerialize instruction with multiple register operand!"); + RegOp = MO.getReg(); +#ifndef NDEBUG + break; +#endif + } + return RegOp; +} + +/// isValNoAvailableAt - Return true if the val# of the specified interval +/// which reaches the given instruction also reaches the specified use index. +bool LiveIntervals::isValNoAvailableAt(const LiveInterval &li, MachineInstr *MI, + SlotIndex UseIdx) const { + SlotIndex Index = getInstructionIndex(MI); + VNInfo *ValNo = li.FindLiveRangeContaining(Index)->valno; + LiveInterval::const_iterator UI = li.FindLiveRangeContaining(UseIdx); + return UI != li.end() && UI->valno == ValNo; +} + +/// isReMaterializable - Returns true if the definition MI of the specified +/// val# of the specified interval is re-materializable. +bool LiveIntervals::isReMaterializable(const LiveInterval &li, + const VNInfo *ValNo, MachineInstr *MI, + SmallVectorImpl &SpillIs, + bool &isLoad) { + if (DisableReMat) + return false; + + if (!tii_->isTriviallyReMaterializable(MI, aa_)) + return false; + + // Target-specific code can mark an instruction as being rematerializable + // if it has one virtual reg use, though it had better be something like + // a PIC base register which is likely to be live everywhere. + unsigned ImpUse = getReMatImplicitUse(li, MI); + if (ImpUse) { + const LiveInterval &ImpLi = getInterval(ImpUse); + for (MachineRegisterInfo::use_iterator ri = mri_->use_begin(li.reg), + re = mri_->use_end(); ri != re; ++ri) { + MachineInstr *UseMI = &*ri; + SlotIndex UseIdx = getInstructionIndex(UseMI); + if (li.FindLiveRangeContaining(UseIdx)->valno != ValNo) + continue; + if (!isValNoAvailableAt(ImpLi, MI, UseIdx)) + return false; + } + + // If a register operand of the re-materialized instruction is going to + // be spilled next, then it's not legal to re-materialize this instruction. + for (unsigned i = 0, e = SpillIs.size(); i != e; ++i) + if (ImpUse == SpillIs[i]->reg) + return false; + } + return true; +} + +/// isReMaterializable - Returns true if the definition MI of the specified +/// val# of the specified interval is re-materializable. +bool LiveIntervals::isReMaterializable(const LiveInterval &li, + const VNInfo *ValNo, MachineInstr *MI) { + SmallVector Dummy1; + bool Dummy2; + return isReMaterializable(li, ValNo, MI, Dummy1, Dummy2); +} + +/// isReMaterializable - Returns true if every definition of MI of every +/// val# of the specified interval is re-materializable. +bool LiveIntervals::isReMaterializable(const LiveInterval &li, + SmallVectorImpl &SpillIs, + bool &isLoad) { + isLoad = false; + for (LiveInterval::const_vni_iterator i = li.vni_begin(), e = li.vni_end(); + i != e; ++i) { + const VNInfo *VNI = *i; + if (VNI->isUnused()) + continue; // Dead val#. + // Is the def for the val# rematerializable? + if (!VNI->isDefAccurate()) + return false; + MachineInstr *ReMatDefMI = getInstructionFromIndex(VNI->def); + bool DefIsLoad = false; + if (!ReMatDefMI || + !isReMaterializable(li, VNI, ReMatDefMI, SpillIs, DefIsLoad)) + return false; + isLoad |= DefIsLoad; + } + return true; +} + +/// FilterFoldedOps - Filter out two-address use operands. Return +/// true if it finds any issue with the operands that ought to prevent +/// folding. +static bool FilterFoldedOps(MachineInstr *MI, + SmallVector &Ops, + unsigned &MRInfo, + SmallVector &FoldOps) { + MRInfo = 0; + for (unsigned i = 0, e = Ops.size(); i != e; ++i) { + unsigned OpIdx = Ops[i]; + MachineOperand &MO = MI->getOperand(OpIdx); + // FIXME: fold subreg use. + if (MO.getSubReg()) + return true; + if (MO.isDef()) + MRInfo |= (unsigned)VirtRegMap::isMod; + else { + // Filter out two-address use operand(s). + if (MI->isRegTiedToDefOperand(OpIdx)) { + MRInfo = VirtRegMap::isModRef; + continue; + } + MRInfo |= (unsigned)VirtRegMap::isRef; + } + FoldOps.push_back(OpIdx); + } + return false; +} + + +/// tryFoldMemoryOperand - Attempts to fold either a spill / restore from +/// slot / to reg or any rematerialized load into ith operand of specified +/// MI. If it is successul, MI is updated with the newly created MI and +/// returns true. +bool LiveIntervals::tryFoldMemoryOperand(MachineInstr* &MI, + VirtRegMap &vrm, MachineInstr *DefMI, + SlotIndex InstrIdx, + SmallVector &Ops, + bool isSS, int Slot, unsigned Reg) { + // If it is an implicit def instruction, just delete it. + if (MI->getOpcode() == TargetInstrInfo::IMPLICIT_DEF) { + RemoveMachineInstrFromMaps(MI); + vrm.RemoveMachineInstrFromMaps(MI); + MI->eraseFromParent(); + ++numFolds; + return true; + } + + // Filter the list of operand indexes that are to be folded. Abort if + // any operand will prevent folding. + unsigned MRInfo = 0; + SmallVector FoldOps; + if (FilterFoldedOps(MI, Ops, MRInfo, FoldOps)) + return false; + + // The only time it's safe to fold into a two address instruction is when + // it's folding reload and spill from / into a spill stack slot. + if (DefMI && (MRInfo & VirtRegMap::isMod)) + return false; + + MachineInstr *fmi = isSS ? tii_->foldMemoryOperand(*mf_, MI, FoldOps, Slot) + : tii_->foldMemoryOperand(*mf_, MI, FoldOps, DefMI); + if (fmi) { + // Remember this instruction uses the spill slot. + if (isSS) vrm.addSpillSlotUse(Slot, fmi); + + // Attempt to fold the memory reference into the instruction. If + // we can do this, we don't need to insert spill code. + MachineBasicBlock &MBB = *MI->getParent(); + if (isSS && !mf_->getFrameInfo()->isImmutableObjectIndex(Slot)) + vrm.virtFolded(Reg, MI, fmi, (VirtRegMap::ModRef)MRInfo); + vrm.transferSpillPts(MI, fmi); + vrm.transferRestorePts(MI, fmi); + vrm.transferEmergencySpills(MI, fmi); + ReplaceMachineInstrInMaps(MI, fmi); + MI = MBB.insert(MBB.erase(MI), fmi); + ++numFolds; + return true; + } + return false; +} + +/// canFoldMemoryOperand - Returns true if the specified load / store +/// folding is possible. +bool LiveIntervals::canFoldMemoryOperand(MachineInstr *MI, + SmallVector &Ops, + bool ReMat) const { + // Filter the list of operand indexes that are to be folded. Abort if + // any operand will prevent folding. + unsigned MRInfo = 0; + SmallVector FoldOps; + if (FilterFoldedOps(MI, Ops, MRInfo, FoldOps)) + return false; + + // It's only legal to remat for a use, not a def. + if (ReMat && (MRInfo & VirtRegMap::isMod)) + return false; + + return tii_->canFoldMemoryOperand(MI, FoldOps); +} + +bool LiveIntervals::intervalIsInOneMBB(const LiveInterval &li) const { + LiveInterval::Ranges::const_iterator itr = li.ranges.begin(); + + MachineBasicBlock *mbb = indexes_->getMBBCoveringRange(itr->start, itr->end); + + if (mbb == 0) + return false; + + for (++itr; itr != li.ranges.end(); ++itr) { + MachineBasicBlock *mbb2 = + indexes_->getMBBCoveringRange(itr->start, itr->end); + + if (mbb2 != mbb) + return false; + } + + return true; +} + +/// rewriteImplicitOps - Rewrite implicit use operands of MI (i.e. uses of +/// interval on to-be re-materialized operands of MI) with new register. +void LiveIntervals::rewriteImplicitOps(const LiveInterval &li, + MachineInstr *MI, unsigned NewVReg, + VirtRegMap &vrm) { + // There is an implicit use. That means one of the other operand is + // being remat'ed and the remat'ed instruction has li.reg as an + // use operand. Make sure we rewrite that as well. + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + MachineOperand &MO = MI->getOperand(i); + if (!MO.isReg()) + continue; + unsigned Reg = MO.getReg(); + if (Reg == 0 || TargetRegisterInfo::isPhysicalRegister(Reg)) + continue; + if (!vrm.isReMaterialized(Reg)) + continue; + MachineInstr *ReMatMI = vrm.getReMaterializedMI(Reg); + MachineOperand *UseMO = ReMatMI->findRegisterUseOperand(li.reg); + if (UseMO) + UseMO->setReg(NewVReg); + } +} + +/// rewriteInstructionForSpills, rewriteInstructionsForSpills - Helper functions +/// for addIntervalsForSpills to rewrite uses / defs for the given live range. +bool LiveIntervals:: +rewriteInstructionForSpills(const LiveInterval &li, const VNInfo *VNI, + bool TrySplit, SlotIndex index, SlotIndex end, + MachineInstr *MI, + MachineInstr *ReMatOrigDefMI, MachineInstr *ReMatDefMI, + unsigned Slot, int LdSlot, + bool isLoad, bool isLoadSS, bool DefIsReMat, bool CanDelete, + VirtRegMap &vrm, + const TargetRegisterClass* rc, + SmallVector &ReMatIds, + const MachineLoopInfo *loopInfo, + unsigned &NewVReg, unsigned ImpUse, bool &HasDef, bool &HasUse, + DenseMap &MBBVRegsMap, + std::vector &NewLIs) { + bool CanFold = false; + RestartInstruction: + for (unsigned i = 0; i != MI->getNumOperands(); ++i) { + MachineOperand& mop = MI->getOperand(i); + if (!mop.isReg()) + continue; + unsigned Reg = mop.getReg(); + unsigned RegI = Reg; + if (Reg == 0 || TargetRegisterInfo::isPhysicalRegister(Reg)) + continue; + if (Reg != li.reg) + continue; + + bool TryFold = !DefIsReMat; + bool FoldSS = true; // Default behavior unless it's a remat. + int FoldSlot = Slot; + if (DefIsReMat) { + // If this is the rematerializable definition MI itself and + // all of its uses are rematerialized, simply delete it. + if (MI == ReMatOrigDefMI && CanDelete) { + DEBUG(errs() << "\t\t\t\tErasing re-materlizable def: " + << MI << '\n'); + RemoveMachineInstrFromMaps(MI); + vrm.RemoveMachineInstrFromMaps(MI); + MI->eraseFromParent(); + break; + } + + // If def for this use can't be rematerialized, then try folding. + // If def is rematerializable and it's a load, also try folding. + TryFold = !ReMatDefMI || (ReMatDefMI && (MI == ReMatOrigDefMI || isLoad)); + if (isLoad) { + // Try fold loads (from stack slot, constant pool, etc.) into uses. + FoldSS = isLoadSS; + FoldSlot = LdSlot; + } + } + + // Scan all of the operands of this instruction rewriting operands + // to use NewVReg instead of li.reg as appropriate. We do this for + // two reasons: + // + // 1. If the instr reads the same spilled vreg multiple times, we + // want to reuse the NewVReg. + // 2. If the instr is a two-addr instruction, we are required to + // keep the src/dst regs pinned. + // + // Keep track of whether we replace a use and/or def so that we can + // create the spill interval with the appropriate range. + + HasUse = mop.isUse(); + HasDef = mop.isDef(); + SmallVector Ops; + Ops.push_back(i); + for (unsigned j = i+1, e = MI->getNumOperands(); j != e; ++j) { + const MachineOperand &MOj = MI->getOperand(j); + if (!MOj.isReg()) + continue; + unsigned RegJ = MOj.getReg(); + if (RegJ == 0 || TargetRegisterInfo::isPhysicalRegister(RegJ)) + continue; + if (RegJ == RegI) { + Ops.push_back(j); + if (!MOj.isUndef()) { + HasUse |= MOj.isUse(); + HasDef |= MOj.isDef(); + } + } + } + + // Create a new virtual register for the spill interval. + // Create the new register now so we can map the fold instruction + // to the new register so when it is unfolded we get the correct + // answer. + bool CreatedNewVReg = false; + if (NewVReg == 0) { + NewVReg = mri_->createVirtualRegister(rc); + vrm.grow(); + CreatedNewVReg = true; + } + + if (!TryFold) + CanFold = false; + else { + // Do not fold load / store here if we are splitting. We'll find an + // optimal point to insert a load / store later. + if (!TrySplit) { + if (tryFoldMemoryOperand(MI, vrm, ReMatDefMI, index, + Ops, FoldSS, FoldSlot, NewVReg)) { + // Folding the load/store can completely change the instruction in + // unpredictable ways, rescan it from the beginning. + + if (FoldSS) { + // We need to give the new vreg the same stack slot as the + // spilled interval. + vrm.assignVirt2StackSlot(NewVReg, FoldSlot); + } + + HasUse = false; + HasDef = false; + CanFold = false; + if (isNotInMIMap(MI)) + break; + goto RestartInstruction; + } + } else { + // We'll try to fold it later if it's profitable. + CanFold = canFoldMemoryOperand(MI, Ops, DefIsReMat); + } + } + + mop.setReg(NewVReg); + if (mop.isImplicit()) + rewriteImplicitOps(li, MI, NewVReg, vrm); + + // Reuse NewVReg for other reads. + for (unsigned j = 0, e = Ops.size(); j != e; ++j) { + MachineOperand &mopj = MI->getOperand(Ops[j]); + mopj.setReg(NewVReg); + if (mopj.isImplicit()) + rewriteImplicitOps(li, MI, NewVReg, vrm); + } + + if (CreatedNewVReg) { + if (DefIsReMat) { + vrm.setVirtIsReMaterialized(NewVReg, ReMatDefMI); + if (ReMatIds[VNI->id] == VirtRegMap::MAX_STACK_SLOT) { + // Each valnum may have its own remat id. + ReMatIds[VNI->id] = vrm.assignVirtReMatId(NewVReg); + } else { + vrm.assignVirtReMatId(NewVReg, ReMatIds[VNI->id]); + } + if (!CanDelete || (HasUse && HasDef)) { + // If this is a two-addr instruction then its use operands are + // rematerializable but its def is not. It should be assigned a + // stack slot. + vrm.assignVirt2StackSlot(NewVReg, Slot); + } + } else { + vrm.assignVirt2StackSlot(NewVReg, Slot); + } + } else if (HasUse && HasDef && + vrm.getStackSlot(NewVReg) == VirtRegMap::NO_STACK_SLOT) { + // If this interval hasn't been assigned a stack slot (because earlier + // def is a deleted remat def), do it now. + assert(Slot != VirtRegMap::NO_STACK_SLOT); + vrm.assignVirt2StackSlot(NewVReg, Slot); + } + + // Re-matting an instruction with virtual register use. Add the + // register as an implicit use on the use MI. + if (DefIsReMat && ImpUse) + MI->addOperand(MachineOperand::CreateReg(ImpUse, false, true)); + + // Create a new register interval for this spill / remat. + LiveInterval &nI = getOrCreateInterval(NewVReg); + if (CreatedNewVReg) { + NewLIs.push_back(&nI); + MBBVRegsMap.insert(std::make_pair(MI->getParent()->getNumber(), NewVReg)); + if (TrySplit) + vrm.setIsSplitFromReg(NewVReg, li.reg); + } + + if (HasUse) { + if (CreatedNewVReg) { + LiveRange LR(index.getLoadIndex(), index.getDefIndex(), + nI.getNextValue(SlotIndex(), 0, false, VNInfoAllocator)); + DEBUG(errs() << " +" << LR); + nI.addRange(LR); + } else { + // Extend the split live interval to this def / use. + SlotIndex End = index.getDefIndex(); + LiveRange LR(nI.ranges[nI.ranges.size()-1].end, End, + nI.getValNumInfo(nI.getNumValNums()-1)); + DEBUG(errs() << " +" << LR); + nI.addRange(LR); + } + } + if (HasDef) { + LiveRange LR(index.getDefIndex(), index.getStoreIndex(), + nI.getNextValue(SlotIndex(), 0, false, VNInfoAllocator)); + DEBUG(errs() << " +" << LR); + nI.addRange(LR); + } + + DEBUG({ + errs() << "\t\t\t\tAdded new interval: "; + nI.print(errs(), tri_); + errs() << '\n'; + }); + } + return CanFold; +} +bool LiveIntervals::anyKillInMBBAfterIdx(const LiveInterval &li, + const VNInfo *VNI, + MachineBasicBlock *MBB, + SlotIndex Idx) const { + SlotIndex End = getMBBEndIdx(MBB); + for (unsigned j = 0, ee = VNI->kills.size(); j != ee; ++j) { + if (VNI->kills[j].isPHI()) + continue; + + SlotIndex KillIdx = VNI->kills[j]; + if (KillIdx > Idx && KillIdx < End) + return true; + } + return false; +} + +/// RewriteInfo - Keep track of machine instrs that will be rewritten +/// during spilling. +namespace { + struct RewriteInfo { + SlotIndex Index; + MachineInstr *MI; + bool HasUse; + bool HasDef; + RewriteInfo(SlotIndex i, MachineInstr *mi, bool u, bool d) + : Index(i), MI(mi), HasUse(u), HasDef(d) {} + }; + + struct RewriteInfoCompare { + bool operator()(const RewriteInfo &LHS, const RewriteInfo &RHS) const { + return LHS.Index < RHS.Index; + } + }; +} + +void LiveIntervals:: +rewriteInstructionsForSpills(const LiveInterval &li, bool TrySplit, + LiveInterval::Ranges::const_iterator &I, + MachineInstr *ReMatOrigDefMI, MachineInstr *ReMatDefMI, + unsigned Slot, int LdSlot, + bool isLoad, bool isLoadSS, bool DefIsReMat, bool CanDelete, + VirtRegMap &vrm, + const TargetRegisterClass* rc, + SmallVector &ReMatIds, + const MachineLoopInfo *loopInfo, + BitVector &SpillMBBs, + DenseMap > &SpillIdxes, + BitVector &RestoreMBBs, + DenseMap > &RestoreIdxes, + DenseMap &MBBVRegsMap, + std::vector &NewLIs) { + bool AllCanFold = true; + unsigned NewVReg = 0; + SlotIndex start = I->start.getBaseIndex(); + SlotIndex end = I->end.getPrevSlot().getBaseIndex().getNextIndex(); + + // First collect all the def / use in this live range that will be rewritten. + // Make sure they are sorted according to instruction index. + std::vector RewriteMIs; + for (MachineRegisterInfo::reg_iterator ri = mri_->reg_begin(li.reg), + re = mri_->reg_end(); ri != re; ) { + MachineInstr *MI = &*ri; + MachineOperand &O = ri.getOperand(); + ++ri; + assert(!O.isImplicit() && "Spilling register that's used as implicit use?"); + SlotIndex index = getInstructionIndex(MI); + if (index < start || index >= end) + continue; + + if (O.isUndef()) + // Must be defined by an implicit def. It should not be spilled. Note, + // this is for correctness reason. e.g. + // 8 %reg1024 = IMPLICIT_DEF + // 12 %reg1024 = INSERT_SUBREG %reg1024, %reg1025, 2 + // The live range [12, 14) are not part of the r1024 live interval since + // it's defined by an implicit def. It will not conflicts with live + // interval of r1025. Now suppose both registers are spilled, you can + // easily see a situation where both registers are reloaded before + // the INSERT_SUBREG and both target registers that would overlap. + continue; + RewriteMIs.push_back(RewriteInfo(index, MI, O.isUse(), O.isDef())); + } + std::sort(RewriteMIs.begin(), RewriteMIs.end(), RewriteInfoCompare()); + + unsigned ImpUse = DefIsReMat ? getReMatImplicitUse(li, ReMatDefMI) : 0; + // Now rewrite the defs and uses. + for (unsigned i = 0, e = RewriteMIs.size(); i != e; ) { + RewriteInfo &rwi = RewriteMIs[i]; + ++i; + SlotIndex index = rwi.Index; + bool MIHasUse = rwi.HasUse; + bool MIHasDef = rwi.HasDef; + MachineInstr *MI = rwi.MI; + // If MI def and/or use the same register multiple times, then there + // are multiple entries. + unsigned NumUses = MIHasUse; + while (i != e && RewriteMIs[i].MI == MI) { + assert(RewriteMIs[i].Index == index); + bool isUse = RewriteMIs[i].HasUse; + if (isUse) ++NumUses; + MIHasUse |= isUse; + MIHasDef |= RewriteMIs[i].HasDef; + ++i; + } + MachineBasicBlock *MBB = MI->getParent(); + + if (ImpUse && MI != ReMatDefMI) { + // Re-matting an instruction with virtual register use. Update the + // register interval's spill weight to HUGE_VALF to prevent it from + // being spilled. + LiveInterval &ImpLi = getInterval(ImpUse); + ImpLi.weight = HUGE_VALF; + } + + unsigned MBBId = MBB->getNumber(); + unsigned ThisVReg = 0; + if (TrySplit) { + DenseMap::iterator NVI = MBBVRegsMap.find(MBBId); + if (NVI != MBBVRegsMap.end()) { + ThisVReg = NVI->second; + // One common case: + // x = use + // ... + // ... + // def = ... + // = use + // It's better to start a new interval to avoid artifically + // extend the new interval. + if (MIHasDef && !MIHasUse) { + MBBVRegsMap.erase(MBB->getNumber()); + ThisVReg = 0; + } + } + } + + bool IsNew = ThisVReg == 0; + if (IsNew) { + // This ends the previous live interval. If all of its def / use + // can be folded, give it a low spill weight. + if (NewVReg && TrySplit && AllCanFold) { + LiveInterval &nI = getOrCreateInterval(NewVReg); + nI.weight /= 10.0F; + } + AllCanFold = true; + } + NewVReg = ThisVReg; + + bool HasDef = false; + bool HasUse = false; + bool CanFold = rewriteInstructionForSpills(li, I->valno, TrySplit, + index, end, MI, ReMatOrigDefMI, ReMatDefMI, + Slot, LdSlot, isLoad, isLoadSS, DefIsReMat, + CanDelete, vrm, rc, ReMatIds, loopInfo, NewVReg, + ImpUse, HasDef, HasUse, MBBVRegsMap, NewLIs); + if (!HasDef && !HasUse) + continue; + + AllCanFold &= CanFold; + + // Update weight of spill interval. + LiveInterval &nI = getOrCreateInterval(NewVReg); + if (!TrySplit) { + // The spill weight is now infinity as it cannot be spilled again. + nI.weight = HUGE_VALF; + continue; + } + + // Keep track of the last def and first use in each MBB. + if (HasDef) { + if (MI != ReMatOrigDefMI || !CanDelete) { + bool HasKill = false; + if (!HasUse) + HasKill = anyKillInMBBAfterIdx(li, I->valno, MBB, index.getDefIndex()); + else { + // If this is a two-address code, then this index starts a new VNInfo. + const VNInfo *VNI = li.findDefinedVNInfoForRegInt(index.getDefIndex()); + if (VNI) + HasKill = anyKillInMBBAfterIdx(li, VNI, MBB, index.getDefIndex()); + } + DenseMap >::iterator SII = + SpillIdxes.find(MBBId); + if (!HasKill) { + if (SII == SpillIdxes.end()) { + std::vector S; + S.push_back(SRInfo(index, NewVReg, true)); + SpillIdxes.insert(std::make_pair(MBBId, S)); + } else if (SII->second.back().vreg != NewVReg) { + SII->second.push_back(SRInfo(index, NewVReg, true)); + } else if (index > SII->second.back().index) { + // If there is an earlier def and this is a two-address + // instruction, then it's not possible to fold the store (which + // would also fold the load). + SRInfo &Info = SII->second.back(); + Info.index = index; + Info.canFold = !HasUse; + } + SpillMBBs.set(MBBId); + } else if (SII != SpillIdxes.end() && + SII->second.back().vreg == NewVReg && + index > SII->second.back().index) { + // There is an earlier def that's not killed (must be two-address). + // The spill is no longer needed. + SII->second.pop_back(); + if (SII->second.empty()) { + SpillIdxes.erase(MBBId); + SpillMBBs.reset(MBBId); + } + } + } + } + + if (HasUse) { + DenseMap >::iterator SII = + SpillIdxes.find(MBBId); + if (SII != SpillIdxes.end() && + SII->second.back().vreg == NewVReg && + index > SII->second.back().index) + // Use(s) following the last def, it's not safe to fold the spill. + SII->second.back().canFold = false; + DenseMap >::iterator RII = + RestoreIdxes.find(MBBId); + if (RII != RestoreIdxes.end() && RII->second.back().vreg == NewVReg) + // If we are splitting live intervals, only fold if it's the first + // use and there isn't another use later in the MBB. + RII->second.back().canFold = false; + else if (IsNew) { + // Only need a reload if there isn't an earlier def / use. + if (RII == RestoreIdxes.end()) { + std::vector Infos; + Infos.push_back(SRInfo(index, NewVReg, true)); + RestoreIdxes.insert(std::make_pair(MBBId, Infos)); + } else { + RII->second.push_back(SRInfo(index, NewVReg, true)); + } + RestoreMBBs.set(MBBId); + } + } + + // Update spill weight. + unsigned loopDepth = loopInfo->getLoopDepth(MBB); + nI.weight += getSpillWeight(HasDef, HasUse, loopDepth); + } + + if (NewVReg && TrySplit && AllCanFold) { + // If all of its def / use can be folded, give it a low spill weight. + LiveInterval &nI = getOrCreateInterval(NewVReg); + nI.weight /= 10.0F; + } +} + +bool LiveIntervals::alsoFoldARestore(int Id, SlotIndex index, + unsigned vr, BitVector &RestoreMBBs, + DenseMap > &RestoreIdxes) { + if (!RestoreMBBs[Id]) + return false; + std::vector &Restores = RestoreIdxes[Id]; + for (unsigned i = 0, e = Restores.size(); i != e; ++i) + if (Restores[i].index == index && + Restores[i].vreg == vr && + Restores[i].canFold) + return true; + return false; +} + +void LiveIntervals::eraseRestoreInfo(int Id, SlotIndex index, + unsigned vr, BitVector &RestoreMBBs, + DenseMap > &RestoreIdxes) { + if (!RestoreMBBs[Id]) + return; + std::vector &Restores = RestoreIdxes[Id]; + for (unsigned i = 0, e = Restores.size(); i != e; ++i) + if (Restores[i].index == index && Restores[i].vreg) + Restores[i].index = SlotIndex(); +} + +/// handleSpilledImpDefs - Remove IMPLICIT_DEF instructions which are being +/// spilled and create empty intervals for their uses. +void +LiveIntervals::handleSpilledImpDefs(const LiveInterval &li, VirtRegMap &vrm, + const TargetRegisterClass* rc, + std::vector &NewLIs) { + for (MachineRegisterInfo::reg_iterator ri = mri_->reg_begin(li.reg), + re = mri_->reg_end(); ri != re; ) { + MachineOperand &O = ri.getOperand(); + MachineInstr *MI = &*ri; + ++ri; + if (O.isDef()) { + assert(MI->getOpcode() == TargetInstrInfo::IMPLICIT_DEF && + "Register def was not rewritten?"); + RemoveMachineInstrFromMaps(MI); + vrm.RemoveMachineInstrFromMaps(MI); + MI->eraseFromParent(); + } else { + // This must be an use of an implicit_def so it's not part of the live + // interval. Create a new empty live interval for it. + // FIXME: Can we simply erase some of the instructions? e.g. Stores? + unsigned NewVReg = mri_->createVirtualRegister(rc); + vrm.grow(); + vrm.setIsImplicitlyDefined(NewVReg); + NewLIs.push_back(&getOrCreateInterval(NewVReg)); + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + MachineOperand &MO = MI->getOperand(i); + if (MO.isReg() && MO.getReg() == li.reg) { + MO.setReg(NewVReg); + MO.setIsUndef(); + } + } + } + } +} + +std::vector LiveIntervals:: +addIntervalsForSpillsFast(const LiveInterval &li, + const MachineLoopInfo *loopInfo, + VirtRegMap &vrm) { + unsigned slot = vrm.assignVirt2StackSlot(li.reg); + + std::vector added; + + assert(li.weight != HUGE_VALF && + "attempt to spill already spilled interval!"); + + DEBUG({ + errs() << "\t\t\t\tadding intervals for spills for interval: "; + li.dump(); + errs() << '\n'; + }); + + const TargetRegisterClass* rc = mri_->getRegClass(li.reg); + + MachineRegisterInfo::reg_iterator RI = mri_->reg_begin(li.reg); + while (RI != mri_->reg_end()) { + MachineInstr* MI = &*RI; + + SmallVector Indices; + bool HasUse = false; + bool HasDef = false; + + for (unsigned i = 0; i != MI->getNumOperands(); ++i) { + MachineOperand& mop = MI->getOperand(i); + if (!mop.isReg() || mop.getReg() != li.reg) continue; + + HasUse |= MI->getOperand(i).isUse(); + HasDef |= MI->getOperand(i).isDef(); + + Indices.push_back(i); + } + + if (!tryFoldMemoryOperand(MI, vrm, NULL, getInstructionIndex(MI), + Indices, true, slot, li.reg)) { + unsigned NewVReg = mri_->createVirtualRegister(rc); + vrm.grow(); + vrm.assignVirt2StackSlot(NewVReg, slot); + + // create a new register for this spill + LiveInterval &nI = getOrCreateInterval(NewVReg); + + // the spill weight is now infinity as it + // cannot be spilled again + nI.weight = HUGE_VALF; + + // Rewrite register operands to use the new vreg. + for (SmallVectorImpl::iterator I = Indices.begin(), + E = Indices.end(); I != E; ++I) { + MI->getOperand(*I).setReg(NewVReg); + + if (MI->getOperand(*I).isUse()) + MI->getOperand(*I).setIsKill(true); + } + + // Fill in the new live interval. + SlotIndex index = getInstructionIndex(MI); + if (HasUse) { + LiveRange LR(index.getLoadIndex(), index.getUseIndex(), + nI.getNextValue(SlotIndex(), 0, false, + getVNInfoAllocator())); + DEBUG(errs() << " +" << LR); + nI.addRange(LR); + vrm.addRestorePoint(NewVReg, MI); + } + if (HasDef) { + LiveRange LR(index.getDefIndex(), index.getStoreIndex(), + nI.getNextValue(SlotIndex(), 0, false, + getVNInfoAllocator())); + DEBUG(errs() << " +" << LR); + nI.addRange(LR); + vrm.addSpillPoint(NewVReg, true, MI); + } + + added.push_back(&nI); + + DEBUG({ + errs() << "\t\t\t\tadded new interval: "; + nI.dump(); + errs() << '\n'; + }); + } + + + RI = mri_->reg_begin(li.reg); + } + + return added; +} + +std::vector LiveIntervals:: +addIntervalsForSpills(const LiveInterval &li, + SmallVectorImpl &SpillIs, + const MachineLoopInfo *loopInfo, VirtRegMap &vrm) { + + if (EnableFastSpilling) + return addIntervalsForSpillsFast(li, loopInfo, vrm); + + assert(li.weight != HUGE_VALF && + "attempt to spill already spilled interval!"); + + DEBUG({ + errs() << "\t\t\t\tadding intervals for spills for interval: "; + li.print(errs(), tri_); + errs() << '\n'; + }); + + // Each bit specify whether a spill is required in the MBB. + BitVector SpillMBBs(mf_->getNumBlockIDs()); + DenseMap > SpillIdxes; + BitVector RestoreMBBs(mf_->getNumBlockIDs()); + DenseMap > RestoreIdxes; + DenseMap MBBVRegsMap; + std::vector NewLIs; + const TargetRegisterClass* rc = mri_->getRegClass(li.reg); + + unsigned NumValNums = li.getNumValNums(); + SmallVector ReMatDefs; + ReMatDefs.resize(NumValNums, NULL); + SmallVector ReMatOrigDefs; + ReMatOrigDefs.resize(NumValNums, NULL); + SmallVector ReMatIds; + ReMatIds.resize(NumValNums, VirtRegMap::MAX_STACK_SLOT); + BitVector ReMatDelete(NumValNums); + unsigned Slot = VirtRegMap::MAX_STACK_SLOT; + + // Spilling a split live interval. It cannot be split any further. Also, + // it's also guaranteed to be a single val# / range interval. + if (vrm.getPreSplitReg(li.reg)) { + vrm.setIsSplitFromReg(li.reg, 0); + // Unset the split kill marker on the last use. + SlotIndex KillIdx = vrm.getKillPoint(li.reg); + if (KillIdx != SlotIndex()) { + MachineInstr *KillMI = getInstructionFromIndex(KillIdx); + assert(KillMI && "Last use disappeared?"); + int KillOp = KillMI->findRegisterUseOperandIdx(li.reg, true); + assert(KillOp != -1 && "Last use disappeared?"); + KillMI->getOperand(KillOp).setIsKill(false); + } + vrm.removeKillPoint(li.reg); + bool DefIsReMat = vrm.isReMaterialized(li.reg); + Slot = vrm.getStackSlot(li.reg); + assert(Slot != VirtRegMap::MAX_STACK_SLOT); + MachineInstr *ReMatDefMI = DefIsReMat ? + vrm.getReMaterializedMI(li.reg) : NULL; + int LdSlot = 0; + bool isLoadSS = DefIsReMat && tii_->isLoadFromStackSlot(ReMatDefMI, LdSlot); + bool isLoad = isLoadSS || + (DefIsReMat && (ReMatDefMI->getDesc().canFoldAsLoad())); + bool IsFirstRange = true; + for (LiveInterval::Ranges::const_iterator + I = li.ranges.begin(), E = li.ranges.end(); I != E; ++I) { + // If this is a split live interval with multiple ranges, it means there + // are two-address instructions that re-defined the value. Only the + // first def can be rematerialized! + if (IsFirstRange) { + // Note ReMatOrigDefMI has already been deleted. + rewriteInstructionsForSpills(li, false, I, NULL, ReMatDefMI, + Slot, LdSlot, isLoad, isLoadSS, DefIsReMat, + false, vrm, rc, ReMatIds, loopInfo, + SpillMBBs, SpillIdxes, RestoreMBBs, RestoreIdxes, + MBBVRegsMap, NewLIs); + } else { + rewriteInstructionsForSpills(li, false, I, NULL, 0, + Slot, 0, false, false, false, + false, vrm, rc, ReMatIds, loopInfo, + SpillMBBs, SpillIdxes, RestoreMBBs, RestoreIdxes, + MBBVRegsMap, NewLIs); + } + IsFirstRange = false; + } + + handleSpilledImpDefs(li, vrm, rc, NewLIs); + return NewLIs; + } + + bool TrySplit = !intervalIsInOneMBB(li); + if (TrySplit) + ++numSplits; + bool NeedStackSlot = false; + for (LiveInterval::const_vni_iterator i = li.vni_begin(), e = li.vni_end(); + i != e; ++i) { + const VNInfo *VNI = *i; + unsigned VN = VNI->id; + if (VNI->isUnused()) + continue; // Dead val#. + // Is the def for the val# rematerializable? + MachineInstr *ReMatDefMI = VNI->isDefAccurate() + ? getInstructionFromIndex(VNI->def) : 0; + bool dummy; + if (ReMatDefMI && isReMaterializable(li, VNI, ReMatDefMI, SpillIs, dummy)) { + // Remember how to remat the def of this val#. + ReMatOrigDefs[VN] = ReMatDefMI; + // Original def may be modified so we have to make a copy here. + MachineInstr *Clone = mf_->CloneMachineInstr(ReMatDefMI); + CloneMIs.push_back(Clone); + ReMatDefs[VN] = Clone; + + bool CanDelete = true; + if (VNI->hasPHIKill()) { + // A kill is a phi node, not all of its uses can be rematerialized. + // It must not be deleted. + CanDelete = false; + // Need a stack slot if there is any live range where uses cannot be + // rematerialized. + NeedStackSlot = true; + } + if (CanDelete) + ReMatDelete.set(VN); + } else { + // Need a stack slot if there is any live range where uses cannot be + // rematerialized. + NeedStackSlot = true; + } + } + + // One stack slot per live interval. + if (NeedStackSlot && vrm.getPreSplitReg(li.reg) == 0) { + if (vrm.getStackSlot(li.reg) == VirtRegMap::NO_STACK_SLOT) + Slot = vrm.assignVirt2StackSlot(li.reg); + + // This case only occurs when the prealloc splitter has already assigned + // a stack slot to this vreg. + else + Slot = vrm.getStackSlot(li.reg); + } + + // Create new intervals and rewrite defs and uses. + for (LiveInterval::Ranges::const_iterator + I = li.ranges.begin(), E = li.ranges.end(); I != E; ++I) { + MachineInstr *ReMatDefMI = ReMatDefs[I->valno->id]; + MachineInstr *ReMatOrigDefMI = ReMatOrigDefs[I->valno->id]; + bool DefIsReMat = ReMatDefMI != NULL; + bool CanDelete = ReMatDelete[I->valno->id]; + int LdSlot = 0; + bool isLoadSS = DefIsReMat && tii_->isLoadFromStackSlot(ReMatDefMI, LdSlot); + bool isLoad = isLoadSS || + (DefIsReMat && ReMatDefMI->getDesc().canFoldAsLoad()); + rewriteInstructionsForSpills(li, TrySplit, I, ReMatOrigDefMI, ReMatDefMI, + Slot, LdSlot, isLoad, isLoadSS, DefIsReMat, + CanDelete, vrm, rc, ReMatIds, loopInfo, + SpillMBBs, SpillIdxes, RestoreMBBs, RestoreIdxes, + MBBVRegsMap, NewLIs); + } + + // Insert spills / restores if we are splitting. + if (!TrySplit) { + handleSpilledImpDefs(li, vrm, rc, NewLIs); + return NewLIs; + } + + SmallPtrSet AddedKill; + SmallVector Ops; + if (NeedStackSlot) { + int Id = SpillMBBs.find_first(); + while (Id != -1) { + std::vector &spills = SpillIdxes[Id]; + for (unsigned i = 0, e = spills.size(); i != e; ++i) { + SlotIndex index = spills[i].index; + unsigned VReg = spills[i].vreg; + LiveInterval &nI = getOrCreateInterval(VReg); + bool isReMat = vrm.isReMaterialized(VReg); + MachineInstr *MI = getInstructionFromIndex(index); + bool CanFold = false; + bool FoundUse = false; + Ops.clear(); + if (spills[i].canFold) { + CanFold = true; + for (unsigned j = 0, ee = MI->getNumOperands(); j != ee; ++j) { + MachineOperand &MO = MI->getOperand(j); + if (!MO.isReg() || MO.getReg() != VReg) + continue; + + Ops.push_back(j); + if (MO.isDef()) + continue; + if (isReMat || + (!FoundUse && !alsoFoldARestore(Id, index, VReg, + RestoreMBBs, RestoreIdxes))) { + // MI has two-address uses of the same register. If the use + // isn't the first and only use in the BB, then we can't fold + // it. FIXME: Move this to rewriteInstructionsForSpills. + CanFold = false; + break; + } + FoundUse = true; + } + } + // Fold the store into the def if possible. + bool Folded = false; + if (CanFold && !Ops.empty()) { + if (tryFoldMemoryOperand(MI, vrm, NULL, index, Ops, true, Slot,VReg)){ + Folded = true; + if (FoundUse) { + // Also folded uses, do not issue a load. + eraseRestoreInfo(Id, index, VReg, RestoreMBBs, RestoreIdxes); + nI.removeRange(index.getLoadIndex(), index.getDefIndex()); + } + nI.removeRange(index.getDefIndex(), index.getStoreIndex()); + } + } + + // Otherwise tell the spiller to issue a spill. + if (!Folded) { + LiveRange *LR = &nI.ranges[nI.ranges.size()-1]; + bool isKill = LR->end == index.getStoreIndex(); + if (!MI->registerDefIsDead(nI.reg)) + // No need to spill a dead def. + vrm.addSpillPoint(VReg, isKill, MI); + if (isKill) + AddedKill.insert(&nI); + } + } + Id = SpillMBBs.find_next(Id); + } + } + + int Id = RestoreMBBs.find_first(); + while (Id != -1) { + std::vector &restores = RestoreIdxes[Id]; + for (unsigned i = 0, e = restores.size(); i != e; ++i) { + SlotIndex index = restores[i].index; + if (index == SlotIndex()) + continue; + unsigned VReg = restores[i].vreg; + LiveInterval &nI = getOrCreateInterval(VReg); + bool isReMat = vrm.isReMaterialized(VReg); + MachineInstr *MI = getInstructionFromIndex(index); + bool CanFold = false; + Ops.clear(); + if (restores[i].canFold) { + CanFold = true; + for (unsigned j = 0, ee = MI->getNumOperands(); j != ee; ++j) { + MachineOperand &MO = MI->getOperand(j); + if (!MO.isReg() || MO.getReg() != VReg) + continue; + + if (MO.isDef()) { + // If this restore were to be folded, it would have been folded + // already. + CanFold = false; + break; + } + Ops.push_back(j); + } + } + + // Fold the load into the use if possible. + bool Folded = false; + if (CanFold && !Ops.empty()) { + if (!isReMat) + Folded = tryFoldMemoryOperand(MI, vrm, NULL,index,Ops,true,Slot,VReg); + else { + MachineInstr *ReMatDefMI = vrm.getReMaterializedMI(VReg); + int LdSlot = 0; + bool isLoadSS = tii_->isLoadFromStackSlot(ReMatDefMI, LdSlot); + // If the rematerializable def is a load, also try to fold it. + if (isLoadSS || ReMatDefMI->getDesc().canFoldAsLoad()) + Folded = tryFoldMemoryOperand(MI, vrm, ReMatDefMI, index, + Ops, isLoadSS, LdSlot, VReg); + if (!Folded) { + unsigned ImpUse = getReMatImplicitUse(li, ReMatDefMI); + if (ImpUse) { + // Re-matting an instruction with virtual register use. Add the + // register as an implicit use on the use MI and update the register + // interval's spill weight to HUGE_VALF to prevent it from being + // spilled. + LiveInterval &ImpLi = getInterval(ImpUse); + ImpLi.weight = HUGE_VALF; + MI->addOperand(MachineOperand::CreateReg(ImpUse, false, true)); + } + } + } + } + // If folding is not possible / failed, then tell the spiller to issue a + // load / rematerialization for us. + if (Folded) + nI.removeRange(index.getLoadIndex(), index.getDefIndex()); + else + vrm.addRestorePoint(VReg, MI); + } + Id = RestoreMBBs.find_next(Id); + } + + // Finalize intervals: add kills, finalize spill weights, and filter out + // dead intervals. + std::vector RetNewLIs; + for (unsigned i = 0, e = NewLIs.size(); i != e; ++i) { + LiveInterval *LI = NewLIs[i]; + if (!LI->empty()) { + LI->weight /= SlotIndex::NUM * getApproximateInstructionCount(*LI); + if (!AddedKill.count(LI)) { + LiveRange *LR = &LI->ranges[LI->ranges.size()-1]; + SlotIndex LastUseIdx = LR->end.getBaseIndex(); + MachineInstr *LastUse = getInstructionFromIndex(LastUseIdx); + int UseIdx = LastUse->findRegisterUseOperandIdx(LI->reg, false); + assert(UseIdx != -1); + if (!LastUse->isRegTiedToDefOperand(UseIdx)) { + LastUse->getOperand(UseIdx).setIsKill(); + vrm.addKillPoint(LI->reg, LastUseIdx); + } + } + RetNewLIs.push_back(LI); + } + } + + handleSpilledImpDefs(li, vrm, rc, RetNewLIs); + return RetNewLIs; +} + +/// hasAllocatableSuperReg - Return true if the specified physical register has +/// any super register that's allocatable. +bool LiveIntervals::hasAllocatableSuperReg(unsigned Reg) const { + for (const unsigned* AS = tri_->getSuperRegisters(Reg); *AS; ++AS) + if (allocatableRegs_[*AS] && hasInterval(*AS)) + return true; + return false; +} + +/// getRepresentativeReg - Find the largest super register of the specified +/// physical register. +unsigned LiveIntervals::getRepresentativeReg(unsigned Reg) const { + // Find the largest super-register that is allocatable. + unsigned BestReg = Reg; + for (const unsigned* AS = tri_->getSuperRegisters(Reg); *AS; ++AS) { + unsigned SuperReg = *AS; + if (!hasAllocatableSuperReg(SuperReg) && hasInterval(SuperReg)) { + BestReg = SuperReg; + break; + } + } + return BestReg; +} + +/// getNumConflictsWithPhysReg - Return the number of uses and defs of the +/// specified interval that conflicts with the specified physical register. +unsigned LiveIntervals::getNumConflictsWithPhysReg(const LiveInterval &li, + unsigned PhysReg) const { + unsigned NumConflicts = 0; + const LiveInterval &pli = getInterval(getRepresentativeReg(PhysReg)); + for (MachineRegisterInfo::reg_iterator I = mri_->reg_begin(li.reg), + E = mri_->reg_end(); I != E; ++I) { + MachineOperand &O = I.getOperand(); + MachineInstr *MI = O.getParent(); + SlotIndex Index = getInstructionIndex(MI); + if (pli.liveAt(Index)) + ++NumConflicts; + } + return NumConflicts; +} + +/// spillPhysRegAroundRegDefsUses - Spill the specified physical register +/// around all defs and uses of the specified interval. Return true if it +/// was able to cut its interval. +bool LiveIntervals::spillPhysRegAroundRegDefsUses(const LiveInterval &li, + unsigned PhysReg, VirtRegMap &vrm) { + unsigned SpillReg = getRepresentativeReg(PhysReg); + + for (const unsigned *AS = tri_->getAliasSet(PhysReg); *AS; ++AS) + // If there are registers which alias PhysReg, but which are not a + // sub-register of the chosen representative super register. Assert + // since we can't handle it yet. + assert(*AS == SpillReg || !allocatableRegs_[*AS] || !hasInterval(*AS) || + tri_->isSuperRegister(*AS, SpillReg)); + + bool Cut = false; + SmallVector PRegs; + if (hasInterval(SpillReg)) + PRegs.push_back(SpillReg); + else { + SmallSet Added; + for (const unsigned* AS = tri_->getSubRegisters(SpillReg); *AS; ++AS) + if (Added.insert(*AS) && hasInterval(*AS)) { + PRegs.push_back(*AS); + for (const unsigned* ASS = tri_->getSubRegisters(*AS); *ASS; ++ASS) + Added.insert(*ASS); + } + } + + SmallPtrSet SeenMIs; + for (MachineRegisterInfo::reg_iterator I = mri_->reg_begin(li.reg), + E = mri_->reg_end(); I != E; ++I) { + MachineOperand &O = I.getOperand(); + MachineInstr *MI = O.getParent(); + if (SeenMIs.count(MI)) + continue; + SeenMIs.insert(MI); + SlotIndex Index = getInstructionIndex(MI); + for (unsigned i = 0, e = PRegs.size(); i != e; ++i) { + unsigned PReg = PRegs[i]; + LiveInterval &pli = getInterval(PReg); + if (!pli.liveAt(Index)) + continue; + vrm.addEmergencySpill(PReg, MI); + SlotIndex StartIdx = Index.getLoadIndex(); + SlotIndex EndIdx = Index.getNextIndex().getBaseIndex(); + if (pli.isInOneLiveRange(StartIdx, EndIdx)) { + pli.removeRange(StartIdx, EndIdx); + Cut = true; + } else { + std::string msg; + raw_string_ostream Msg(msg); + Msg << "Ran out of registers during register allocation!"; + if (MI->getOpcode() == TargetInstrInfo::INLINEASM) { + Msg << "\nPlease check your inline asm statement for invalid " + << "constraints:\n"; + MI->print(Msg, tm_); + } + llvm_report_error(Msg.str()); + } + for (const unsigned* AS = tri_->getSubRegisters(PReg); *AS; ++AS) { + if (!hasInterval(*AS)) + continue; + LiveInterval &spli = getInterval(*AS); + if (spli.liveAt(Index)) + spli.removeRange(Index.getLoadIndex(), + Index.getNextIndex().getBaseIndex()); + } + } + } + return Cut; +} + +LiveRange LiveIntervals::addLiveRangeToEndOfBlock(unsigned reg, + MachineInstr* startInst) { + LiveInterval& Interval = getOrCreateInterval(reg); + VNInfo* VN = Interval.getNextValue( + SlotIndex(getInstructionIndex(startInst).getDefIndex()), + startInst, true, getVNInfoAllocator()); + VN->setHasPHIKill(true); + VN->kills.push_back(indexes_->getTerminatorGap(startInst->getParent())); + LiveRange LR( + SlotIndex(getInstructionIndex(startInst).getDefIndex()), + getMBBEndIdx(startInst->getParent()).getNextIndex().getBaseIndex(), VN); + Interval.addRange(LR); + + return LR; +} + diff --git a/libclamav/c++/llvm/lib/CodeGen/LiveStackAnalysis.cpp b/libclamav/c++/llvm/lib/CodeGen/LiveStackAnalysis.cpp new file mode 100644 index 000000000..d2f377528 --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/LiveStackAnalysis.cpp @@ -0,0 +1,63 @@ +//===-- LiveStackAnalysis.cpp - Live Stack Slot Analysis ------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the live stack slot analysis pass. It is analogous to +// live interval analysis except it's analyzing liveness of stack slots rather +// than registers. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "livestacks" +#include "llvm/CodeGen/LiveStackAnalysis.h" +#include "llvm/CodeGen/LiveIntervalAnalysis.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/ADT/Statistic.h" +#include +using namespace llvm; + +char LiveStacks::ID = 0; +static RegisterPass X("livestacks", "Live Stack Slot Analysis"); + +void LiveStacks::getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + AU.addPreserved(); + AU.addRequiredTransitive(); + MachineFunctionPass::getAnalysisUsage(AU); +} + +void LiveStacks::releaseMemory() { + // Release VNInfo memroy regions after all VNInfo objects are dtor'd. + VNInfoAllocator.Reset(); + S2IMap.clear(); + S2RCMap.clear(); +} + +bool LiveStacks::runOnMachineFunction(MachineFunction &) { + // FIXME: No analysis is being done right now. We are relying on the + // register allocators to provide the information. + return false; +} + +/// print - Implement the dump method. +void LiveStacks::print(raw_ostream &OS, const Module*) const { + + OS << "********** INTERVALS **********\n"; + for (const_iterator I = begin(), E = end(); I != E; ++I) { + I->second.print(OS); + int Slot = I->first; + const TargetRegisterClass *RC = getIntervalRegClass(Slot); + if (RC) + OS << " [" << RC->getName() << "]\n"; + else + OS << " [Unknown]\n"; + } +} diff --git a/libclamav/c++/llvm/lib/CodeGen/LiveVariables.cpp b/libclamav/c++/llvm/lib/CodeGen/LiveVariables.cpp new file mode 100644 index 000000000..bfc2d0852 --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/LiveVariables.cpp @@ -0,0 +1,700 @@ +//===-- LiveVariables.cpp - Live Variable Analysis for Machine Code -------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the LiveVariable analysis pass. For each machine +// instruction in the function, this pass calculates the set of registers that +// are immediately dead after the instruction (i.e., the instruction calculates +// the value, but it is never used) and the set of registers that are used by +// the instruction, but are never used after the instruction (i.e., they are +// killed). +// +// This class computes live variables using are sparse implementation based on +// the machine code SSA form. This class computes live variable information for +// each virtual and _register allocatable_ physical register in a function. It +// uses the dominance properties of SSA form to efficiently compute live +// variables for virtual registers, and assumes that physical registers are only +// live within a single basic block (allowing it to do a single local analysis +// to resolve physical register lifetimes in each basic block). If a physical +// register is not register allocatable, it is not tracked. This is useful for +// things like the stack pointer and condition codes. +// +//===----------------------------------------------------------------------===// + +#include "llvm/CodeGen/LiveVariables.h" +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/ADT/DepthFirstIterator.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallSet.h" +#include "llvm/ADT/STLExtras.h" +#include +using namespace llvm; + +char LiveVariables::ID = 0; +static RegisterPass X("livevars", "Live Variable Analysis"); + + +void LiveVariables::getAnalysisUsage(AnalysisUsage &AU) const { + AU.addRequiredID(UnreachableMachineBlockElimID); + AU.setPreservesAll(); + MachineFunctionPass::getAnalysisUsage(AU); +} + +MachineInstr * +LiveVariables::VarInfo::findKill(const MachineBasicBlock *MBB) const { + for (unsigned i = 0, e = Kills.size(); i != e; ++i) + if (Kills[i]->getParent() == MBB) + return Kills[i]; + return NULL; +} + +void LiveVariables::VarInfo::dump() const { + errs() << " Alive in blocks: "; + for (SparseBitVector<>::iterator I = AliveBlocks.begin(), + E = AliveBlocks.end(); I != E; ++I) + errs() << *I << ", "; + errs() << "\n Killed by:"; + if (Kills.empty()) + errs() << " No instructions.\n"; + else { + for (unsigned i = 0, e = Kills.size(); i != e; ++i) + errs() << "\n #" << i << ": " << *Kills[i]; + errs() << "\n"; + } +} + +/// getVarInfo - Get (possibly creating) a VarInfo object for the given vreg. +LiveVariables::VarInfo &LiveVariables::getVarInfo(unsigned RegIdx) { + assert(TargetRegisterInfo::isVirtualRegister(RegIdx) && + "getVarInfo: not a virtual register!"); + RegIdx -= TargetRegisterInfo::FirstVirtualRegister; + if (RegIdx >= VirtRegInfo.size()) { + if (RegIdx >= 2*VirtRegInfo.size()) + VirtRegInfo.resize(RegIdx*2); + else + VirtRegInfo.resize(2*VirtRegInfo.size()); + } + return VirtRegInfo[RegIdx]; +} + +void LiveVariables::MarkVirtRegAliveInBlock(VarInfo& VRInfo, + MachineBasicBlock *DefBlock, + MachineBasicBlock *MBB, + std::vector &WorkList) { + unsigned BBNum = MBB->getNumber(); + + // Check to see if this basic block is one of the killing blocks. If so, + // remove it. + for (unsigned i = 0, e = VRInfo.Kills.size(); i != e; ++i) + if (VRInfo.Kills[i]->getParent() == MBB) { + VRInfo.Kills.erase(VRInfo.Kills.begin()+i); // Erase entry + break; + } + + if (MBB == DefBlock) return; // Terminate recursion + + if (VRInfo.AliveBlocks.test(BBNum)) + return; // We already know the block is live + + // Mark the variable known alive in this bb + VRInfo.AliveBlocks.set(BBNum); + + for (MachineBasicBlock::const_pred_reverse_iterator PI = MBB->pred_rbegin(), + E = MBB->pred_rend(); PI != E; ++PI) + WorkList.push_back(*PI); +} + +void LiveVariables::MarkVirtRegAliveInBlock(VarInfo &VRInfo, + MachineBasicBlock *DefBlock, + MachineBasicBlock *MBB) { + std::vector WorkList; + MarkVirtRegAliveInBlock(VRInfo, DefBlock, MBB, WorkList); + + while (!WorkList.empty()) { + MachineBasicBlock *Pred = WorkList.back(); + WorkList.pop_back(); + MarkVirtRegAliveInBlock(VRInfo, DefBlock, Pred, WorkList); + } +} + +void LiveVariables::HandleVirtRegUse(unsigned reg, MachineBasicBlock *MBB, + MachineInstr *MI) { + assert(MRI->getVRegDef(reg) && "Register use before def!"); + + unsigned BBNum = MBB->getNumber(); + + VarInfo& VRInfo = getVarInfo(reg); + VRInfo.NumUses++; + + // Check to see if this basic block is already a kill block. + if (!VRInfo.Kills.empty() && VRInfo.Kills.back()->getParent() == MBB) { + // Yes, this register is killed in this basic block already. Increase the + // live range by updating the kill instruction. + VRInfo.Kills.back() = MI; + return; + } + +#ifndef NDEBUG + for (unsigned i = 0, e = VRInfo.Kills.size(); i != e; ++i) + assert(VRInfo.Kills[i]->getParent() != MBB && "entry should be at end!"); +#endif + + // This situation can occur: + // + // ,------. + // | | + // | v + // | t2 = phi ... t1 ... + // | | + // | v + // | t1 = ... + // | ... = ... t1 ... + // | | + // `------' + // + // where there is a use in a PHI node that's a predecessor to the defining + // block. We don't want to mark all predecessors as having the value "alive" + // in this case. + if (MBB == MRI->getVRegDef(reg)->getParent()) return; + + // Add a new kill entry for this basic block. If this virtual register is + // already marked as alive in this basic block, that means it is alive in at + // least one of the successor blocks, it's not a kill. + if (!VRInfo.AliveBlocks.test(BBNum)) + VRInfo.Kills.push_back(MI); + + // Update all dominating blocks to mark them as "known live". + for (MachineBasicBlock::const_pred_iterator PI = MBB->pred_begin(), + E = MBB->pred_end(); PI != E; ++PI) + MarkVirtRegAliveInBlock(VRInfo, MRI->getVRegDef(reg)->getParent(), *PI); +} + +void LiveVariables::HandleVirtRegDef(unsigned Reg, MachineInstr *MI) { + VarInfo &VRInfo = getVarInfo(Reg); + + if (VRInfo.AliveBlocks.empty()) + // If vr is not alive in any block, then defaults to dead. + VRInfo.Kills.push_back(MI); +} + +/// FindLastPartialDef - Return the last partial def of the specified register. +/// Also returns the sub-registers that're defined by the instruction. +MachineInstr *LiveVariables::FindLastPartialDef(unsigned Reg, + SmallSet &PartDefRegs) { + unsigned LastDefReg = 0; + unsigned LastDefDist = 0; + MachineInstr *LastDef = NULL; + for (const unsigned *SubRegs = TRI->getSubRegisters(Reg); + unsigned SubReg = *SubRegs; ++SubRegs) { + MachineInstr *Def = PhysRegDef[SubReg]; + if (!Def) + continue; + unsigned Dist = DistanceMap[Def]; + if (Dist > LastDefDist) { + LastDefReg = SubReg; + LastDef = Def; + LastDefDist = Dist; + } + } + + if (!LastDef) + return 0; + + PartDefRegs.insert(LastDefReg); + for (unsigned i = 0, e = LastDef->getNumOperands(); i != e; ++i) { + MachineOperand &MO = LastDef->getOperand(i); + if (!MO.isReg() || !MO.isDef() || MO.getReg() == 0) + continue; + unsigned DefReg = MO.getReg(); + if (TRI->isSubRegister(Reg, DefReg)) { + PartDefRegs.insert(DefReg); + for (const unsigned *SubRegs = TRI->getSubRegisters(DefReg); + unsigned SubReg = *SubRegs; ++SubRegs) + PartDefRegs.insert(SubReg); + } + } + return LastDef; +} + +/// HandlePhysRegUse - Turn previous partial def's into read/mod/writes. Add +/// implicit defs to a machine instruction if there was an earlier def of its +/// super-register. +void LiveVariables::HandlePhysRegUse(unsigned Reg, MachineInstr *MI) { + MachineInstr *LastDef = PhysRegDef[Reg]; + // If there was a previous use or a "full" def all is well. + if (!LastDef && !PhysRegUse[Reg]) { + // Otherwise, the last sub-register def implicitly defines this register. + // e.g. + // AH = + // AL = ... , + // = AH + // ... + // = EAX + // All of the sub-registers must have been defined before the use of Reg! + SmallSet PartDefRegs; + MachineInstr *LastPartialDef = FindLastPartialDef(Reg, PartDefRegs); + // If LastPartialDef is NULL, it must be using a livein register. + if (LastPartialDef) { + LastPartialDef->addOperand(MachineOperand::CreateReg(Reg, true/*IsDef*/, + true/*IsImp*/)); + PhysRegDef[Reg] = LastPartialDef; + SmallSet Processed; + for (const unsigned *SubRegs = TRI->getSubRegisters(Reg); + unsigned SubReg = *SubRegs; ++SubRegs) { + if (Processed.count(SubReg)) + continue; + if (PartDefRegs.count(SubReg)) + continue; + // This part of Reg was defined before the last partial def. It's killed + // here. + LastPartialDef->addOperand(MachineOperand::CreateReg(SubReg, + false/*IsDef*/, + true/*IsImp*/)); + PhysRegDef[SubReg] = LastPartialDef; + for (const unsigned *SS = TRI->getSubRegisters(SubReg); *SS; ++SS) + Processed.insert(*SS); + } + } + } + else if (LastDef && !PhysRegUse[Reg] && + !LastDef->findRegisterDefOperand(Reg)) + // Last def defines the super register, add an implicit def of reg. + LastDef->addOperand(MachineOperand::CreateReg(Reg, + true/*IsDef*/, true/*IsImp*/)); + + // Remember this use. + PhysRegUse[Reg] = MI; + for (const unsigned *SubRegs = TRI->getSubRegisters(Reg); + unsigned SubReg = *SubRegs; ++SubRegs) + PhysRegUse[SubReg] = MI; +} + +bool LiveVariables::HandlePhysRegKill(unsigned Reg, MachineInstr *MI) { + MachineInstr *LastDef = PhysRegDef[Reg]; + MachineInstr *LastUse = PhysRegUse[Reg]; + if (!LastDef && !LastUse) + return false; + + MachineInstr *LastRefOrPartRef = LastUse ? LastUse : LastDef; + unsigned LastRefOrPartRefDist = DistanceMap[LastRefOrPartRef]; + // The whole register is used. + // AL = + // AH = + // + // = AX + // = AL, AX + // AX = + // + // Or whole register is defined, but not used at all. + // AX = + // ... + // AX = + // + // Or whole register is defined, but only partly used. + // AX = AL + // = AL + // AX = + MachineInstr *LastPartDef = 0; + unsigned LastPartDefDist = 0; + SmallSet PartUses; + for (const unsigned *SubRegs = TRI->getSubRegisters(Reg); + unsigned SubReg = *SubRegs; ++SubRegs) { + MachineInstr *Def = PhysRegDef[SubReg]; + if (Def && Def != LastDef) { + // There was a def of this sub-register in between. This is a partial + // def, keep track of the last one. + unsigned Dist = DistanceMap[Def]; + if (Dist > LastPartDefDist) { + LastPartDefDist = Dist; + LastPartDef = Def; + } + continue; + } + if (MachineInstr *Use = PhysRegUse[SubReg]) { + PartUses.insert(SubReg); + for (const unsigned *SS = TRI->getSubRegisters(SubReg); *SS; ++SS) + PartUses.insert(*SS); + unsigned Dist = DistanceMap[Use]; + if (Dist > LastRefOrPartRefDist) { + LastRefOrPartRefDist = Dist; + LastRefOrPartRef = Use; + } + } + } + + if (LastRefOrPartRef == PhysRegDef[Reg] && LastRefOrPartRef != MI) { + if (LastPartDef) + // The last partial def kills the register. + LastPartDef->addOperand(MachineOperand::CreateReg(Reg, false/*IsDef*/, + true/*IsImp*/, true/*IsKill*/)); + else { + MachineOperand *MO = + LastRefOrPartRef->findRegisterDefOperand(Reg, false, TRI); + bool NeedEC = MO->isEarlyClobber() && MO->getReg() != Reg; + // If the last reference is the last def, then it's not used at all. + // That is, unless we are currently processing the last reference itself. + LastRefOrPartRef->addRegisterDead(Reg, TRI, true); + if (NeedEC) { + // If we are adding a subreg def and the superreg def is marked early + // clobber, add an early clobber marker to the subreg def. + MO = LastRefOrPartRef->findRegisterDefOperand(Reg); + if (MO) + MO->setIsEarlyClobber(); + } + } + } else if (!PhysRegUse[Reg]) { + // Partial uses. Mark register def dead and add implicit def of + // sub-registers which are used. + // EAX = op AL + // That is, EAX def is dead but AL def extends pass it. + PhysRegDef[Reg]->addRegisterDead(Reg, TRI, true); + for (const unsigned *SubRegs = TRI->getSubRegisters(Reg); + unsigned SubReg = *SubRegs; ++SubRegs) { + if (!PartUses.count(SubReg)) + continue; + bool NeedDef = true; + if (PhysRegDef[Reg] == PhysRegDef[SubReg]) { + MachineOperand *MO = PhysRegDef[Reg]->findRegisterDefOperand(SubReg); + if (MO) { + NeedDef = false; + assert(!MO->isDead()); + } + } + if (NeedDef) + PhysRegDef[Reg]->addOperand(MachineOperand::CreateReg(SubReg, + true/*IsDef*/, true/*IsImp*/)); + LastRefOrPartRef->addRegisterKilled(SubReg, TRI, true); + for (const unsigned *SS = TRI->getSubRegisters(SubReg); *SS; ++SS) + PartUses.erase(*SS); + } + } else + LastRefOrPartRef->addRegisterKilled(Reg, TRI, true); + return true; +} + +void LiveVariables::HandlePhysRegDef(unsigned Reg, MachineInstr *MI, + SmallVector &Defs) { + // What parts of the register are previously defined? + SmallSet Live; + if (PhysRegDef[Reg] || PhysRegUse[Reg]) { + Live.insert(Reg); + for (const unsigned *SS = TRI->getSubRegisters(Reg); *SS; ++SS) + Live.insert(*SS); + } else { + for (const unsigned *SubRegs = TRI->getSubRegisters(Reg); + unsigned SubReg = *SubRegs; ++SubRegs) { + // If a register isn't itself defined, but all parts that make up of it + // are defined, then consider it also defined. + // e.g. + // AL = + // AH = + // = AX + if (Live.count(SubReg)) + continue; + if (PhysRegDef[SubReg] || PhysRegUse[SubReg]) { + Live.insert(SubReg); + for (const unsigned *SS = TRI->getSubRegisters(SubReg); *SS; ++SS) + Live.insert(*SS); + } + } + } + + // Start from the largest piece, find the last time any part of the register + // is referenced. + HandlePhysRegKill(Reg, MI); + // Only some of the sub-registers are used. + for (const unsigned *SubRegs = TRI->getSubRegisters(Reg); + unsigned SubReg = *SubRegs; ++SubRegs) { + if (!Live.count(SubReg)) + // Skip if this sub-register isn't defined. + continue; + HandlePhysRegKill(SubReg, MI); + } + + if (MI) + Defs.push_back(Reg); // Remember this def. +} + +void LiveVariables::UpdatePhysRegDefs(MachineInstr *MI, + SmallVector &Defs) { + while (!Defs.empty()) { + unsigned Reg = Defs.back(); + Defs.pop_back(); + PhysRegDef[Reg] = MI; + PhysRegUse[Reg] = NULL; + for (const unsigned *SubRegs = TRI->getSubRegisters(Reg); + unsigned SubReg = *SubRegs; ++SubRegs) { + PhysRegDef[SubReg] = MI; + PhysRegUse[SubReg] = NULL; + } + } +} + +namespace { + struct RegSorter { + const TargetRegisterInfo *TRI; + + RegSorter(const TargetRegisterInfo *tri) : TRI(tri) { } + bool operator()(unsigned A, unsigned B) { + if (TRI->isSubRegister(A, B)) + return true; + else if (TRI->isSubRegister(B, A)) + return false; + return A < B; + } + }; +} + +bool LiveVariables::runOnMachineFunction(MachineFunction &mf) { + MF = &mf; + MRI = &mf.getRegInfo(); + TRI = MF->getTarget().getRegisterInfo(); + + ReservedRegisters = TRI->getReservedRegs(mf); + + unsigned NumRegs = TRI->getNumRegs(); + PhysRegDef = new MachineInstr*[NumRegs]; + PhysRegUse = new MachineInstr*[NumRegs]; + PHIVarInfo = new SmallVector[MF->getNumBlockIDs()]; + std::fill(PhysRegDef, PhysRegDef + NumRegs, (MachineInstr*)0); + std::fill(PhysRegUse, PhysRegUse + NumRegs, (MachineInstr*)0); + + /// Get some space for a respectable number of registers. + VirtRegInfo.resize(64); + + analyzePHINodes(mf); + + // Calculate live variable information in depth first order on the CFG of the + // function. This guarantees that we will see the definition of a virtual + // register before its uses due to dominance properties of SSA (except for PHI + // nodes, which are treated as a special case). + MachineBasicBlock *Entry = MF->begin(); + SmallPtrSet Visited; + + for (df_ext_iterator > + DFI = df_ext_begin(Entry, Visited), E = df_ext_end(Entry, Visited); + DFI != E; ++DFI) { + MachineBasicBlock *MBB = *DFI; + + // Mark live-in registers as live-in. + SmallVector Defs; + for (MachineBasicBlock::const_livein_iterator II = MBB->livein_begin(), + EE = MBB->livein_end(); II != EE; ++II) { + assert(TargetRegisterInfo::isPhysicalRegister(*II) && + "Cannot have a live-in virtual register!"); + HandlePhysRegDef(*II, 0, Defs); + } + + // Loop over all of the instructions, processing them. + DistanceMap.clear(); + unsigned Dist = 0; + for (MachineBasicBlock::iterator I = MBB->begin(), E = MBB->end(); + I != E; ++I) { + MachineInstr *MI = I; + DistanceMap.insert(std::make_pair(MI, Dist++)); + + // Process all of the operands of the instruction... + unsigned NumOperandsToProcess = MI->getNumOperands(); + + // Unless it is a PHI node. In this case, ONLY process the DEF, not any + // of the uses. They will be handled in other basic blocks. + if (MI->getOpcode() == TargetInstrInfo::PHI) + NumOperandsToProcess = 1; + + SmallVector UseRegs; + SmallVector DefRegs; + for (unsigned i = 0; i != NumOperandsToProcess; ++i) { + const MachineOperand &MO = MI->getOperand(i); + if (!MO.isReg() || MO.getReg() == 0) + continue; + unsigned MOReg = MO.getReg(); + if (MO.isUse()) + UseRegs.push_back(MOReg); + if (MO.isDef()) + DefRegs.push_back(MOReg); + } + + // Process all uses. + for (unsigned i = 0, e = UseRegs.size(); i != e; ++i) { + unsigned MOReg = UseRegs[i]; + if (TargetRegisterInfo::isVirtualRegister(MOReg)) + HandleVirtRegUse(MOReg, MBB, MI); + else if (!ReservedRegisters[MOReg]) + HandlePhysRegUse(MOReg, MI); + } + + // Process all defs. + for (unsigned i = 0, e = DefRegs.size(); i != e; ++i) { + unsigned MOReg = DefRegs[i]; + if (TargetRegisterInfo::isVirtualRegister(MOReg)) + HandleVirtRegDef(MOReg, MI); + else if (!ReservedRegisters[MOReg]) + HandlePhysRegDef(MOReg, MI, Defs); + } + UpdatePhysRegDefs(MI, Defs); + } + + // Handle any virtual assignments from PHI nodes which might be at the + // bottom of this basic block. We check all of our successor blocks to see + // if they have PHI nodes, and if so, we simulate an assignment at the end + // of the current block. + if (!PHIVarInfo[MBB->getNumber()].empty()) { + SmallVector& VarInfoVec = PHIVarInfo[MBB->getNumber()]; + + for (SmallVector::iterator I = VarInfoVec.begin(), + E = VarInfoVec.end(); I != E; ++I) + // Mark it alive only in the block we are representing. + MarkVirtRegAliveInBlock(getVarInfo(*I),MRI->getVRegDef(*I)->getParent(), + MBB); + } + + // Finally, if the last instruction in the block is a return, make sure to + // mark it as using all of the live-out values in the function. + if (!MBB->empty() && MBB->back().getDesc().isReturn()) { + MachineInstr *Ret = &MBB->back(); + + for (MachineRegisterInfo::liveout_iterator + I = MF->getRegInfo().liveout_begin(), + E = MF->getRegInfo().liveout_end(); I != E; ++I) { + assert(TargetRegisterInfo::isPhysicalRegister(*I) && + "Cannot have a live-out virtual register!"); + HandlePhysRegUse(*I, Ret); + + // Add live-out registers as implicit uses. + if (!Ret->readsRegister(*I)) + Ret->addOperand(MachineOperand::CreateReg(*I, false, true)); + } + } + + // Loop over PhysRegDef / PhysRegUse, killing any registers that are + // available at the end of the basic block. + for (unsigned i = 0; i != NumRegs; ++i) + if (PhysRegDef[i] || PhysRegUse[i]) + HandlePhysRegDef(i, 0, Defs); + + std::fill(PhysRegDef, PhysRegDef + NumRegs, (MachineInstr*)0); + std::fill(PhysRegUse, PhysRegUse + NumRegs, (MachineInstr*)0); + } + + // Convert and transfer the dead / killed information we have gathered into + // VirtRegInfo onto MI's. + for (unsigned i = 0, e1 = VirtRegInfo.size(); i != e1; ++i) + for (unsigned j = 0, e2 = VirtRegInfo[i].Kills.size(); j != e2; ++j) + if (VirtRegInfo[i].Kills[j] == + MRI->getVRegDef(i + TargetRegisterInfo::FirstVirtualRegister)) + VirtRegInfo[i] + .Kills[j]->addRegisterDead(i + + TargetRegisterInfo::FirstVirtualRegister, + TRI); + else + VirtRegInfo[i] + .Kills[j]->addRegisterKilled(i + + TargetRegisterInfo::FirstVirtualRegister, + TRI); + + // Check to make sure there are no unreachable blocks in the MC CFG for the + // function. If so, it is due to a bug in the instruction selector or some + // other part of the code generator if this happens. +#ifndef NDEBUG + for(MachineFunction::iterator i = MF->begin(), e = MF->end(); i != e; ++i) + assert(Visited.count(&*i) != 0 && "unreachable basic block found"); +#endif + + delete[] PhysRegDef; + delete[] PhysRegUse; + delete[] PHIVarInfo; + + return false; +} + +/// replaceKillInstruction - Update register kill info by replacing a kill +/// instruction with a new one. +void LiveVariables::replaceKillInstruction(unsigned Reg, MachineInstr *OldMI, + MachineInstr *NewMI) { + VarInfo &VI = getVarInfo(Reg); + std::replace(VI.Kills.begin(), VI.Kills.end(), OldMI, NewMI); +} + +/// removeVirtualRegistersKilled - Remove all killed info for the specified +/// instruction. +void LiveVariables::removeVirtualRegistersKilled(MachineInstr *MI) { + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + MachineOperand &MO = MI->getOperand(i); + if (MO.isReg() && MO.isKill()) { + MO.setIsKill(false); + unsigned Reg = MO.getReg(); + if (TargetRegisterInfo::isVirtualRegister(Reg)) { + bool removed = getVarInfo(Reg).removeKill(MI); + assert(removed && "kill not in register's VarInfo?"); + removed = true; + } + } + } +} + +/// analyzePHINodes - Gather information about the PHI nodes in here. In +/// particular, we want to map the variable information of a virtual register +/// which is used in a PHI node. We map that to the BB the vreg is coming from. +/// +void LiveVariables::analyzePHINodes(const MachineFunction& Fn) { + for (MachineFunction::const_iterator I = Fn.begin(), E = Fn.end(); + I != E; ++I) + for (MachineBasicBlock::const_iterator BBI = I->begin(), BBE = I->end(); + BBI != BBE && BBI->getOpcode() == TargetInstrInfo::PHI; ++BBI) + for (unsigned i = 1, e = BBI->getNumOperands(); i != e; i += 2) + PHIVarInfo[BBI->getOperand(i + 1).getMBB()->getNumber()] + .push_back(BBI->getOperand(i).getReg()); +} + +bool LiveVariables::VarInfo::isLiveIn(const MachineBasicBlock &MBB, + unsigned Reg, + MachineRegisterInfo &MRI) { + unsigned Num = MBB.getNumber(); + + // Reg is live-through. + if (AliveBlocks.test(Num)) + return true; + + // Registers defined in MBB cannot be live in. + const MachineInstr *Def = MRI.getVRegDef(Reg); + if (Def && Def->getParent() == &MBB) + return false; + + // Reg was not defined in MBB, was it killed here? + return findKill(&MBB); +} + +/// addNewBlock - Add a new basic block BB as an empty succcessor to DomBB. All +/// variables that are live out of DomBB will be marked as passing live through +/// BB. +void LiveVariables::addNewBlock(MachineBasicBlock *BB, + MachineBasicBlock *DomBB, + MachineBasicBlock *SuccBB) { + const unsigned NumNew = BB->getNumber(); + + // All registers used by PHI nodes in SuccBB must be live through BB. + for (MachineBasicBlock::const_iterator BBI = SuccBB->begin(), + BBE = SuccBB->end(); + BBI != BBE && BBI->getOpcode() == TargetInstrInfo::PHI; ++BBI) + for (unsigned i = 1, e = BBI->getNumOperands(); i != e; i += 2) + if (BBI->getOperand(i+1).getMBB() == BB) + getVarInfo(BBI->getOperand(i).getReg()).AliveBlocks.set(NumNew); + + // Update info for all live variables + for (unsigned Reg = TargetRegisterInfo::FirstVirtualRegister, + E = MRI->getLastVirtReg()+1; Reg != E; ++Reg) { + VarInfo &VI = getVarInfo(Reg); + if (!VI.AliveBlocks.test(NumNew) && VI.isLiveIn(*SuccBB, Reg, *MRI)) + VI.AliveBlocks.set(NumNew); + } +} diff --git a/libclamav/c++/llvm/lib/CodeGen/LowerSubregs.cpp b/libclamav/c++/llvm/lib/CodeGen/LowerSubregs.cpp new file mode 100644 index 000000000..30636a8ed --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/LowerSubregs.cpp @@ -0,0 +1,329 @@ +//===-- LowerSubregs.cpp - Subregister Lowering instruction pass ----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines a MachineFunction pass which runs after register +// allocation that turns subreg insert/extract instructions into register +// copies, as needed. This ensures correct codegen even if the coalescer +// isn't able to remove all subreg instructions. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "lowersubregs" +#include "llvm/CodeGen/Passes.h" +#include "llvm/Function.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +namespace { + struct LowerSubregsInstructionPass : public MachineFunctionPass { + private: + const TargetRegisterInfo *TRI; + const TargetInstrInfo *TII; + + public: + static char ID; // Pass identification, replacement for typeid + LowerSubregsInstructionPass() : MachineFunctionPass(&ID) {} + + const char *getPassName() const { + return "Subregister lowering instruction pass"; + } + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesCFG(); + AU.addPreservedID(MachineLoopInfoID); + AU.addPreservedID(MachineDominatorsID); + MachineFunctionPass::getAnalysisUsage(AU); + } + + /// runOnMachineFunction - pass entry point + bool runOnMachineFunction(MachineFunction&); + + private: + bool LowerExtract(MachineInstr *MI); + bool LowerInsert(MachineInstr *MI); + bool LowerSubregToReg(MachineInstr *MI); + + void TransferDeadFlag(MachineInstr *MI, unsigned DstReg, + const TargetRegisterInfo *TRI); + void TransferKillFlag(MachineInstr *MI, unsigned SrcReg, + const TargetRegisterInfo *TRI, + bool AddIfNotFound = false); + }; + + char LowerSubregsInstructionPass::ID = 0; +} + +FunctionPass *llvm::createLowerSubregsPass() { + return new LowerSubregsInstructionPass(); +} + +/// TransferDeadFlag - MI is a pseudo-instruction with DstReg dead, +/// and the lowered replacement instructions immediately precede it. +/// Mark the replacement instructions with the dead flag. +void +LowerSubregsInstructionPass::TransferDeadFlag(MachineInstr *MI, + unsigned DstReg, + const TargetRegisterInfo *TRI) { + for (MachineBasicBlock::iterator MII = + prior(MachineBasicBlock::iterator(MI)); ; --MII) { + if (MII->addRegisterDead(DstReg, TRI)) + break; + assert(MII != MI->getParent()->begin() && + "copyRegToReg output doesn't reference destination register!"); + } +} + +/// TransferKillFlag - MI is a pseudo-instruction with SrcReg killed, +/// and the lowered replacement instructions immediately precede it. +/// Mark the replacement instructions with the kill flag. +void +LowerSubregsInstructionPass::TransferKillFlag(MachineInstr *MI, + unsigned SrcReg, + const TargetRegisterInfo *TRI, + bool AddIfNotFound) { + for (MachineBasicBlock::iterator MII = + prior(MachineBasicBlock::iterator(MI)); ; --MII) { + if (MII->addRegisterKilled(SrcReg, TRI, AddIfNotFound)) + break; + assert(MII != MI->getParent()->begin() && + "copyRegToReg output doesn't reference source register!"); + } +} + +bool LowerSubregsInstructionPass::LowerExtract(MachineInstr *MI) { + MachineBasicBlock *MBB = MI->getParent(); + + assert(MI->getOperand(0).isReg() && MI->getOperand(0).isDef() && + MI->getOperand(1).isReg() && MI->getOperand(1).isUse() && + MI->getOperand(2).isImm() && "Malformed extract_subreg"); + + unsigned DstReg = MI->getOperand(0).getReg(); + unsigned SuperReg = MI->getOperand(1).getReg(); + unsigned SubIdx = MI->getOperand(2).getImm(); + unsigned SrcReg = TRI->getSubReg(SuperReg, SubIdx); + + assert(TargetRegisterInfo::isPhysicalRegister(SuperReg) && + "Extract supperg source must be a physical register"); + assert(TargetRegisterInfo::isPhysicalRegister(DstReg) && + "Extract destination must be in a physical register"); + assert(SrcReg && "invalid subregister index for register"); + + DEBUG(errs() << "subreg: CONVERTING: " << *MI); + + if (SrcReg == DstReg) { + // No need to insert an identity copy instruction. + if (MI->getOperand(1).isKill()) { + // We must make sure the super-register gets killed. Replace the + // instruction with KILL. + MI->setDesc(TII->get(TargetInstrInfo::KILL)); + MI->RemoveOperand(2); // SubIdx + DEBUG(errs() << "subreg: replace by: " << *MI); + return true; + } + + DEBUG(errs() << "subreg: eliminated!"); + } else { + // Insert copy + const TargetRegisterClass *TRCS = TRI->getPhysicalRegisterRegClass(DstReg); + const TargetRegisterClass *TRCD = TRI->getPhysicalRegisterRegClass(SrcReg); + bool Emitted = TII->copyRegToReg(*MBB, MI, DstReg, SrcReg, TRCD, TRCS); + (void)Emitted; + assert(Emitted && "Subreg and Dst must be of compatible register class"); + // Transfer the kill/dead flags, if needed. + if (MI->getOperand(0).isDead()) + TransferDeadFlag(MI, DstReg, TRI); + if (MI->getOperand(1).isKill()) + TransferKillFlag(MI, SuperReg, TRI, true); + DEBUG({ + MachineBasicBlock::iterator dMI = MI; + errs() << "subreg: " << *(--dMI); + }); + } + + DEBUG(errs() << '\n'); + MBB->erase(MI); + return true; +} + +bool LowerSubregsInstructionPass::LowerSubregToReg(MachineInstr *MI) { + MachineBasicBlock *MBB = MI->getParent(); + assert((MI->getOperand(0).isReg() && MI->getOperand(0).isDef()) && + MI->getOperand(1).isImm() && + (MI->getOperand(2).isReg() && MI->getOperand(2).isUse()) && + MI->getOperand(3).isImm() && "Invalid subreg_to_reg"); + + unsigned DstReg = MI->getOperand(0).getReg(); + unsigned InsReg = MI->getOperand(2).getReg(); + unsigned InsSIdx = MI->getOperand(2).getSubReg(); + unsigned SubIdx = MI->getOperand(3).getImm(); + + assert(SubIdx != 0 && "Invalid index for insert_subreg"); + unsigned DstSubReg = TRI->getSubReg(DstReg, SubIdx); + + assert(TargetRegisterInfo::isPhysicalRegister(DstReg) && + "Insert destination must be in a physical register"); + assert(TargetRegisterInfo::isPhysicalRegister(InsReg) && + "Inserted value must be in a physical register"); + + DEBUG(errs() << "subreg: CONVERTING: " << *MI); + + if (DstSubReg == InsReg && InsSIdx == 0) { + // No need to insert an identify copy instruction. + // Watch out for case like this: + // %RAX = ... + // %RAX = SUBREG_TO_REG 0, %EAX:3, 3 + // The first def is defining RAX, not EAX so the top bits were not + // zero extended. + DEBUG(errs() << "subreg: eliminated!"); + } else { + // Insert sub-register copy + const TargetRegisterClass *TRC0= TRI->getPhysicalRegisterRegClass(DstSubReg); + const TargetRegisterClass *TRC1= TRI->getPhysicalRegisterRegClass(InsReg); + bool Emitted = TII->copyRegToReg(*MBB, MI, DstSubReg, InsReg, TRC0, TRC1); + (void)Emitted; + assert(Emitted && "Subreg and Dst must be of compatible register class"); + // Transfer the kill/dead flags, if needed. + if (MI->getOperand(0).isDead()) + TransferDeadFlag(MI, DstSubReg, TRI); + if (MI->getOperand(2).isKill()) + TransferKillFlag(MI, InsReg, TRI); + DEBUG({ + MachineBasicBlock::iterator dMI = MI; + errs() << "subreg: " << *(--dMI); + }); + } + + DEBUG(errs() << '\n'); + MBB->erase(MI); + return true; +} + +bool LowerSubregsInstructionPass::LowerInsert(MachineInstr *MI) { + MachineBasicBlock *MBB = MI->getParent(); + assert((MI->getOperand(0).isReg() && MI->getOperand(0).isDef()) && + (MI->getOperand(1).isReg() && MI->getOperand(1).isUse()) && + (MI->getOperand(2).isReg() && MI->getOperand(2).isUse()) && + MI->getOperand(3).isImm() && "Invalid insert_subreg"); + + unsigned DstReg = MI->getOperand(0).getReg(); +#ifndef NDEBUG + unsigned SrcReg = MI->getOperand(1).getReg(); +#endif + unsigned InsReg = MI->getOperand(2).getReg(); + unsigned SubIdx = MI->getOperand(3).getImm(); + + assert(DstReg == SrcReg && "insert_subreg not a two-address instruction?"); + assert(SubIdx != 0 && "Invalid index for insert_subreg"); + unsigned DstSubReg = TRI->getSubReg(DstReg, SubIdx); + assert(DstSubReg && "invalid subregister index for register"); + assert(TargetRegisterInfo::isPhysicalRegister(SrcReg) && + "Insert superreg source must be in a physical register"); + assert(TargetRegisterInfo::isPhysicalRegister(InsReg) && + "Inserted value must be in a physical register"); + + DEBUG(errs() << "subreg: CONVERTING: " << *MI); + + if (DstSubReg == InsReg) { + // No need to insert an identity copy instruction. If the SrcReg was + // , we need to make sure it is alive by inserting a KILL + if (MI->getOperand(1).isUndef() && !MI->getOperand(0).isDead()) { + MachineInstrBuilder MIB = BuildMI(*MBB, MI, MI->getDebugLoc(), + TII->get(TargetInstrInfo::KILL), DstReg); + if (MI->getOperand(2).isUndef()) + MIB.addReg(InsReg, RegState::Undef); + else + MIB.addReg(InsReg, RegState::Kill); + } else { + DEBUG(errs() << "subreg: eliminated!\n"); + MBB->erase(MI); + return true; + } + } else { + // Insert sub-register copy + const TargetRegisterClass *TRC0= TRI->getPhysicalRegisterRegClass(DstSubReg); + const TargetRegisterClass *TRC1= TRI->getPhysicalRegisterRegClass(InsReg); + if (MI->getOperand(2).isUndef()) + // If the source register being inserted is undef, then this becomes a + // KILL. + BuildMI(*MBB, MI, MI->getDebugLoc(), + TII->get(TargetInstrInfo::KILL), DstSubReg); + else { + bool Emitted = TII->copyRegToReg(*MBB, MI, DstSubReg, InsReg, TRC0, TRC1); + (void)Emitted; + assert(Emitted && "Subreg and Dst must be of compatible register class"); + } + MachineBasicBlock::iterator CopyMI = MI; + --CopyMI; + + // INSERT_SUBREG is a two-address instruction so it implicitly kills SrcReg. + if (!MI->getOperand(1).isUndef()) + CopyMI->addOperand(MachineOperand::CreateReg(DstReg, false, true, true)); + + // Transfer the kill/dead flags, if needed. + if (MI->getOperand(0).isDead()) { + TransferDeadFlag(MI, DstSubReg, TRI); + } else { + // Make sure the full DstReg is live after this replacement. + CopyMI->addOperand(MachineOperand::CreateReg(DstReg, true, true)); + } + + // Make sure the inserted register gets killed + if (MI->getOperand(2).isKill() && !MI->getOperand(2).isUndef()) + TransferKillFlag(MI, InsReg, TRI); + } + + DEBUG({ + MachineBasicBlock::iterator dMI = MI; + errs() << "subreg: " << *(--dMI) << "\n"; + }); + + MBB->erase(MI); + return true; +} + +/// runOnMachineFunction - Reduce subregister inserts and extracts to register +/// copies. +/// +bool LowerSubregsInstructionPass::runOnMachineFunction(MachineFunction &MF) { + DEBUG(errs() << "Machine Function\n" + << "********** LOWERING SUBREG INSTRS **********\n" + << "********** Function: " + << MF.getFunction()->getName() << '\n'); + TRI = MF.getTarget().getRegisterInfo(); + TII = MF.getTarget().getInstrInfo(); + + bool MadeChange = false; + + for (MachineFunction::iterator mbbi = MF.begin(), mbbe = MF.end(); + mbbi != mbbe; ++mbbi) { + for (MachineBasicBlock::iterator mi = mbbi->begin(), me = mbbi->end(); + mi != me;) { + MachineBasicBlock::iterator nmi = next(mi); + MachineInstr *MI = mi; + if (MI->getOpcode() == TargetInstrInfo::EXTRACT_SUBREG) { + MadeChange |= LowerExtract(MI); + } else if (MI->getOpcode() == TargetInstrInfo::INSERT_SUBREG) { + MadeChange |= LowerInsert(MI); + } else if (MI->getOpcode() == TargetInstrInfo::SUBREG_TO_REG) { + MadeChange |= LowerSubregToReg(MI); + } + mi = nmi; + } + } + + return MadeChange; +} diff --git a/libclamav/c++/llvm/lib/CodeGen/MachO.h b/libclamav/c++/llvm/lib/CodeGen/MachO.h new file mode 100644 index 000000000..f2b40fe58 --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/MachO.h @@ -0,0 +1,412 @@ +//=== MachO.h - Mach-O structures and constants -----------------*- 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 MachO . +// +//===----------------------------------------------------------------------===// + +#ifndef MACHO_H +#define MACHO_H + +#include "llvm/CodeGen/BinaryObject.h" +#include +#include + +namespace llvm { + +class GlobalValue; +class MCAsmInfo; + +/// MachOSym - This struct contains information about each symbol that is +/// added to logical symbol table for the module. This is eventually +/// turned into a real symbol table in the file. +struct MachOSym { + const GlobalValue *GV; // The global value this corresponds to. + std::string GVName; // The mangled name of the global value. + uint32_t n_strx; // index into the string table + uint8_t n_type; // type flag + uint8_t n_sect; // section number or NO_SECT + int16_t n_desc; // see + uint64_t n_value; // value for this symbol (or stab offset) + + // Constants for the n_sect field + // see + enum { NO_SECT = 0 }; // symbol is not in any section + + // Constants for the n_type field + // see + enum { N_UNDF = 0x0, // undefined, n_sect == NO_SECT + N_ABS = 0x2, // absolute, n_sect == NO_SECT + N_SECT = 0xe, // defined in section number n_sect + N_PBUD = 0xc, // prebound undefined (defined in a dylib) + N_INDR = 0xa // indirect + }; + // The following bits are OR'd into the types above. For example, a type + // of 0x0f would be an external N_SECT symbol (0x0e | 0x01). + enum { N_EXT = 0x01, // external symbol bit + N_PEXT = 0x10 // private external symbol bit + }; + + // Constants for the n_desc field + // see + enum { REFERENCE_FLAG_UNDEFINED_NON_LAZY = 0, + REFERENCE_FLAG_UNDEFINED_LAZY = 1, + REFERENCE_FLAG_DEFINED = 2, + REFERENCE_FLAG_PRIVATE_DEFINED = 3, + REFERENCE_FLAG_PRIVATE_UNDEFINED_NON_LAZY = 4, + REFERENCE_FLAG_PRIVATE_UNDEFINED_LAZY = 5 + }; + enum { N_NO_DEAD_STRIP = 0x0020, // symbol is not to be dead stripped + N_WEAK_REF = 0x0040, // symbol is weak referenced + N_WEAK_DEF = 0x0080 // coalesced symbol is a weak definition + }; + + MachOSym(const GlobalValue *gv, std::string name, uint8_t sect, + const MCAsmInfo *MAI); + + struct SymCmp { + // FIXME: this does not appear to be sorting 'f' after 'F' + bool operator()(const MachOSym &LHS, const MachOSym &RHS) { + return LHS.GVName < RHS.GVName; + } + }; + + + /// PartitionByLocal - Simple boolean predicate that returns true if Sym is + /// a local symbol rather than an external symbol. + + static inline bool PartitionByLocal(const MachOSym &Sym) { + return (Sym.n_type & (MachOSym::N_EXT | MachOSym::N_PEXT)) == 0; + } + + /// PartitionByDefined - Simple boolean predicate that returns true if Sym is + /// defined in this module. + + static inline bool PartitionByDefined(const MachOSym &Sym) { + // FIXME: Do N_ABS or N_INDR count as defined? + return (Sym.n_type & MachOSym::N_SECT) == MachOSym::N_SECT; + } + +}; // end struct MachOSym + +/// MachOHeader - This struct contains the header information about a +/// specific architecture type/subtype pair that is emitted to the file. + +struct MachOHeader { + uint32_t magic; // mach magic number identifier + uint32_t filetype; // type of file + uint32_t ncmds; // number of load commands + uint32_t sizeofcmds; // the size of all the load commands + uint32_t flags; // flags + uint32_t reserved; // 64-bit only + + /// HeaderData - The actual data for the header which we are building + /// up for emission to the file. + std::vector HeaderData; + + // Constants for the filetype field + // see for additional info on the various types + enum { MH_OBJECT = 1, // relocatable object file + MH_EXECUTE = 2, // demand paged executable file + MH_FVMLIB = 3, // fixed VM shared library file + MH_CORE = 4, // core file + MH_PRELOAD = 5, // preloaded executable file + MH_DYLIB = 6, // dynamically bound shared library + MH_DYLINKER = 7, // dynamic link editor + MH_BUNDLE = 8, // dynamically bound bundle file + MH_DYLIB_STUB = 9, // shared library stub for static linking only + MH_DSYM = 10 // companion file wiht only debug sections + }; + + // Constants for the flags field + enum { MH_NOUNDEFS = 1 << 0, + // the object file has no undefined references + MH_INCRLINK = 1 << 1, + // the object file is the output of an incremental link against + // a base file and cannot be link edited again + MH_DYLDLINK = 1 << 2, + // the object file is input for the dynamic linker and cannot be + // statically link edited again. + MH_BINDATLOAD = 1 << 3, + // the object file's undefined references are bound by the + // dynamic linker when loaded. + MH_PREBOUND = 1 << 4, + // the file has its dynamic undefined references prebound + MH_SPLIT_SEGS = 1 << 5, + // the file has its read-only and read-write segments split + // see + MH_LAZY_INIT = 1 << 6, + // the shared library init routine is to be run lazily via + // catching memory faults to its writable segments (obsolete) + MH_TWOLEVEL = 1 << 7, + // the image is using two-level namespace bindings + MH_FORCE_FLAT = 1 << 8, + // the executable is forcing all images to use flat namespace + // bindings. + MH_NOMULTIDEFS = 1 << 8, + // this umbrella guarantees no multiple definitions of symbols + // in its sub-images so the two-level namespace hints can + // always be used. + MH_NOFIXPREBINDING = 1 << 10, + // do not have dyld notify the prebidning agent about this + // executable. + MH_PREBINDABLE = 1 << 11, + // the binary is not prebound but can have its prebinding + // redone. only used when MH_PREBOUND is not set. + MH_ALLMODSBOUND = 1 << 12, + // indicates that this binary binds to all two-level namespace + // modules of its dependent libraries. Only used when + // MH_PREBINDABLE and MH_TWOLEVEL are both set. + MH_SUBSECTIONS_VIA_SYMBOLS = 1 << 13, + // safe to divide up the sections into sub-sections via symbols + // for dead code stripping. + MH_CANONICAL = 1 << 14, + // the binary has been canonicalized via the unprebind operation + MH_WEAK_DEFINES = 1 << 15, + // the final linked image contains external weak symbols + MH_BINDS_TO_WEAK = 1 << 16, + // the final linked image uses weak symbols + MH_ALLOW_STACK_EXECUTION = 1 << 17 + // When this bit is set, all stacks in the task will be given + // stack execution privilege. Only used in MH_EXECUTE filetype + }; + + MachOHeader() : magic(0), filetype(0), ncmds(0), sizeofcmds(0), flags(0), + reserved(0) {} + + /// cmdSize - This routine returns the size of the MachOSection as written + /// to disk, depending on whether the destination is a 64 bit Mach-O file. + unsigned cmdSize(bool is64Bit) const { + if (is64Bit) + return 8 * sizeof(uint32_t); + else + return 7 * sizeof(uint32_t); + } + + /// setMagic - This routine sets the appropriate value for the 'magic' + /// field based on pointer size and endianness. + void setMagic(bool isLittleEndian, bool is64Bit) { + if (isLittleEndian) + if (is64Bit) magic = 0xcffaedfe; + else magic = 0xcefaedfe; + else + if (is64Bit) magic = 0xfeedfacf; + else magic = 0xfeedface; + } + +}; // end struct MachOHeader + +/// MachOSegment - This struct contains the necessary information to +/// emit the load commands for each section in the file. +struct MachOSegment { + uint32_t cmd; // LC_SEGMENT or LC_SEGMENT_64 + uint32_t cmdsize; // Total size of this struct and section commands + std::string segname; // segment name + uint64_t vmaddr; // address of this segment + uint64_t vmsize; // size of this segment, may be larger than filesize + uint64_t fileoff; // offset in file + uint64_t filesize; // amount to read from file + uint32_t maxprot; // maximum VM protection + uint32_t initprot; // initial VM protection + uint32_t nsects; // number of sections in this segment + uint32_t flags; // flags + + // The following constants are getting pulled in by one of the + // system headers, which creates a neat clash with the enum. +#if !defined(VM_PROT_NONE) +#define VM_PROT_NONE 0x00 +#endif +#if !defined(VM_PROT_READ) +#define VM_PROT_READ 0x01 +#endif +#if !defined(VM_PROT_WRITE) +#define VM_PROT_WRITE 0x02 +#endif +#if !defined(VM_PROT_EXECUTE) +#define VM_PROT_EXECUTE 0x04 +#endif +#if !defined(VM_PROT_ALL) +#define VM_PROT_ALL 0x07 +#endif + + // Constants for the vm protection fields + // see + enum { SEG_VM_PROT_NONE = VM_PROT_NONE, + SEG_VM_PROT_READ = VM_PROT_READ, // read permission + SEG_VM_PROT_WRITE = VM_PROT_WRITE, // write permission + SEG_VM_PROT_EXECUTE = VM_PROT_EXECUTE, + SEG_VM_PROT_ALL = VM_PROT_ALL + }; + + // Constants for the cmd field + // see + enum { LC_SEGMENT = 0x01, // segment of this file to be mapped + LC_SEGMENT_64 = 0x19 // 64-bit segment of this file to be mapped + }; + + /// cmdSize - This routine returns the size of the MachOSection as written + /// to disk, depending on whether the destination is a 64 bit Mach-O file. + unsigned cmdSize(bool is64Bit) const { + if (is64Bit) + return 6 * sizeof(uint32_t) + 4 * sizeof(uint64_t) + 16; + else + return 10 * sizeof(uint32_t) + 16; // addresses only 32 bits + } + + MachOSegment(const std::string &seg, bool is64Bit) + : cmd(is64Bit ? LC_SEGMENT_64 : LC_SEGMENT), cmdsize(0), segname(seg), + vmaddr(0), vmsize(0), fileoff(0), filesize(0), maxprot(VM_PROT_ALL), + initprot(VM_PROT_ALL), nsects(0), flags(0) { } +}; + +/// MachOSection - This struct contains information about each section in a +/// particular segment that is emitted to the file. This is eventually +/// turned into the SectionCommand in the load command for a particlar +/// segment. + +struct MachOSection : public BinaryObject { + std::string sectname; // name of this section, + std::string segname; // segment this section goes in + uint64_t addr; // memory address of this section + uint32_t offset; // file offset of this section + uint32_t align; // section alignment (power of 2) + uint32_t reloff; // file offset of relocation entries + uint32_t nreloc; // number of relocation entries + uint32_t flags; // flags (section type and attributes) + uint32_t reserved1; // reserved (for offset or index) + uint32_t reserved2; // reserved (for count or sizeof) + uint32_t reserved3; // reserved (64 bit only) + + /// A unique number for this section, which will be used to match symbols + /// to the correct section. + uint32_t Index; + + /// RelocBuffer - A buffer to hold the mach-o relocations before we write + /// them out at the appropriate location in the file. + std::vector RelocBuffer; + + // Constants for the section types (low 8 bits of flags field) + // see + enum { S_REGULAR = 0, + // regular section + S_ZEROFILL = 1, + // zero fill on demand section + S_CSTRING_LITERALS = 2, + // section with only literal C strings + S_4BYTE_LITERALS = 3, + // section with only 4 byte literals + S_8BYTE_LITERALS = 4, + // section with only 8 byte literals + S_LITERAL_POINTERS = 5, + // section with only pointers to literals + S_NON_LAZY_SYMBOL_POINTERS = 6, + // section with only non-lazy symbol pointers + S_LAZY_SYMBOL_POINTERS = 7, + // section with only lazy symbol pointers + S_SYMBOL_STUBS = 8, + // section with only symbol stubs + // byte size of stub in the reserved2 field + S_MOD_INIT_FUNC_POINTERS = 9, + // section with only function pointers for initialization + S_MOD_TERM_FUNC_POINTERS = 10, + // section with only function pointers for termination + S_COALESCED = 11, + // section contains symbols that are coalesced + S_GB_ZEROFILL = 12, + // zero fill on demand section (that can be larger than 4GB) + S_INTERPOSING = 13, + // section with only pairs of function pointers for interposing + S_16BYTE_LITERALS = 14 + // section with only 16 byte literals + }; + + // Constants for the section flags (high 24 bits of flags field) + // see + enum { S_ATTR_PURE_INSTRUCTIONS = 1 << 31, + // section contains only true machine instructions + S_ATTR_NO_TOC = 1 << 30, + // section contains coalesced symbols that are not to be in a + // ranlib table of contents + S_ATTR_STRIP_STATIC_SYMS = 1 << 29, + // ok to strip static symbols in this section in files with the + // MY_DYLDLINK flag + S_ATTR_NO_DEAD_STRIP = 1 << 28, + // no dead stripping + S_ATTR_LIVE_SUPPORT = 1 << 27, + // blocks are live if they reference live blocks + S_ATTR_SELF_MODIFYING_CODE = 1 << 26, + // used with i386 code stubs written on by dyld + S_ATTR_DEBUG = 1 << 25, + // a debug section + S_ATTR_SOME_INSTRUCTIONS = 1 << 10, + // section contains some machine instructions + S_ATTR_EXT_RELOC = 1 << 9, + // section has external relocation entries + S_ATTR_LOC_RELOC = 1 << 8 + // section has local relocation entries + }; + + /// cmdSize - This routine returns the size of the MachOSection as written + /// to disk, depending on whether the destination is a 64 bit Mach-O file. + unsigned cmdSize(bool is64Bit) const { + if (is64Bit) + return 7 * sizeof(uint32_t) + 2 * sizeof(uint64_t) + 32; + else + return 9 * sizeof(uint32_t) + 32; // addresses only 32 bits + } + + MachOSection(const std::string &seg, const std::string §) + : BinaryObject(), sectname(sect), segname(seg), addr(0), offset(0), + align(2), reloff(0), nreloc(0), flags(0), reserved1(0), reserved2(0), + reserved3(0) { } + +}; // end struct MachOSection + +/// MachOSymTab - This struct contains information about the offsets and +/// size of symbol table information. +/// segment. +struct MachODySymTab { + uint32_t cmd; // LC_DYSYMTAB + uint32_t cmdsize; // sizeof(MachODySymTab) + uint32_t ilocalsym; // index to local symbols + uint32_t nlocalsym; // number of local symbols + uint32_t iextdefsym; // index to externally defined symbols + uint32_t nextdefsym; // number of externally defined symbols + uint32_t iundefsym; // index to undefined symbols + uint32_t nundefsym; // number of undefined symbols + uint32_t tocoff; // file offset to table of contents + uint32_t ntoc; // number of entries in table of contents + uint32_t modtaboff; // file offset to module table + uint32_t nmodtab; // number of module table entries + uint32_t extrefsymoff; // offset to referenced symbol table + uint32_t nextrefsyms; // number of referenced symbol table entries + uint32_t indirectsymoff; // file offset to the indirect symbol table + uint32_t nindirectsyms; // number of indirect symbol table entries + uint32_t extreloff; // offset to external relocation entries + uint32_t nextrel; // number of external relocation entries + uint32_t locreloff; // offset to local relocation entries + uint32_t nlocrel; // number of local relocation entries + + // Constants for the cmd field + // see + enum { LC_DYSYMTAB = 0x0B // dynamic link-edit symbol table info + }; + + MachODySymTab() : cmd(LC_DYSYMTAB), cmdsize(20 * sizeof(uint32_t)), + ilocalsym(0), nlocalsym(0), iextdefsym(0), nextdefsym(0), + iundefsym(0), nundefsym(0), tocoff(0), ntoc(0), modtaboff(0), + nmodtab(0), extrefsymoff(0), nextrefsyms(0), indirectsymoff(0), + nindirectsyms(0), extreloff(0), nextrel(0), locreloff(0), nlocrel(0) {} + +}; // end struct MachODySymTab + +} // end namespace llvm + +#endif + diff --git a/libclamav/c++/llvm/lib/CodeGen/MachOCodeEmitter.cpp b/libclamav/c++/llvm/lib/CodeGen/MachOCodeEmitter.cpp new file mode 100644 index 000000000..13184772c --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/MachOCodeEmitter.cpp @@ -0,0 +1,193 @@ +//===-- MachOEmitter.cpp - Target-independent Mach-O Emitter code --------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "MachO.h" +#include "MachOWriter.h" +#include "MachOCodeEmitter.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Function.h" +#include "llvm/CodeGen/MachineConstantPool.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineJumpTableInfo.h" +#include "llvm/CodeGen/MachineRelocation.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/Mangler.h" +#include "llvm/Support/OutputBuffer.h" +#include + +//===----------------------------------------------------------------------===// +// MachOCodeEmitter Implementation +//===----------------------------------------------------------------------===// + +namespace llvm { + +MachOCodeEmitter::MachOCodeEmitter(MachOWriter &mow, MachOSection &mos) : + ObjectCodeEmitter(&mos), MOW(mow), TM(MOW.TM) { + is64Bit = TM.getTargetData()->getPointerSizeInBits() == 64; + isLittleEndian = TM.getTargetData()->isLittleEndian(); + MAI = TM.getMCAsmInfo(); +} + +/// startFunction - This callback is invoked when a new machine function is +/// about to be emitted. + +void MachOCodeEmitter::startFunction(MachineFunction &MF) { + const TargetData *TD = TM.getTargetData(); + const Function *F = MF.getFunction(); + + // Align the output buffer to the appropriate alignment, power of 2. + unsigned FnAlign = F->getAlignment(); + unsigned TDAlign = TD->getPrefTypeAlignment(F->getType()); + unsigned Align = Log2_32(std::max(FnAlign, TDAlign)); + assert(!(Align & (Align-1)) && "Alignment is not a power of two!"); + + // Get the Mach-O Section that this function belongs in. + MachOSection *MOS = MOW.getTextSection(); + + // Upgrade the section alignment if required. + if (MOS->align < Align) MOS->align = Align; + + MOS->emitAlignment(Align); + + // Create symbol for function entry + const GlobalValue *FuncV = MF.getFunction(); + MachOSym FnSym(FuncV, MOW.Mang->getMangledName(FuncV), MOS->Index, MAI); + FnSym.n_value = getCurrentPCOffset(); + + // add it to the symtab. + MOW.SymbolTable.push_back(FnSym); +} + +/// finishFunction - This callback is invoked after the function is completely +/// finished. + +bool MachOCodeEmitter::finishFunction(MachineFunction &MF) { + + // Get the Mach-O Section that this function belongs in. + MachOSection *MOS = MOW.getTextSection(); + + // Emit constant pool to appropriate section(s) + emitConstantPool(MF.getConstantPool()); + + // Emit jump tables to appropriate section + emitJumpTables(MF.getJumpTableInfo()); + + // If we have emitted any relocations to function-specific objects such as + // basic blocks, constant pools entries, or jump tables, record their + // addresses now so that we can rewrite them with the correct addresses + // later. + for (unsigned i = 0, e = Relocations.size(); i != e; ++i) { + MachineRelocation &MR = Relocations[i]; + intptr_t Addr; + + if (MR.isBasicBlock()) { + Addr = getMachineBasicBlockAddress(MR.getBasicBlock()); + MR.setConstantVal(MOS->Index); + MR.setResultPointer((void*)Addr); + } else if (MR.isJumpTableIndex()) { + Addr = getJumpTableEntryAddress(MR.getJumpTableIndex()); + MR.setConstantVal(MOW.getJumpTableSection()->Index); + MR.setResultPointer((void*)Addr); + } else if (MR.isConstantPoolIndex()) { + Addr = getConstantPoolEntryAddress(MR.getConstantPoolIndex()); + MR.setConstantVal(CPSections[MR.getConstantPoolIndex()]); + MR.setResultPointer((void*)Addr); + } else if (MR.isGlobalValue()) { + // FIXME: This should be a set or something that uniques + MOW.PendingGlobals.push_back(MR.getGlobalValue()); + } else { + llvm_unreachable("Unhandled relocation type"); + } + MOS->addRelocation(MR); + } + Relocations.clear(); + + // Clear per-function data structures. + CPLocations.clear(); + CPSections.clear(); + JTLocations.clear(); + MBBLocations.clear(); + + return false; +} + +/// emitConstantPool - For each constant pool entry, figure out which section +/// the constant should live in, allocate space for it, and emit it to the +/// Section data buffer. +void MachOCodeEmitter::emitConstantPool(MachineConstantPool *MCP) { + const std::vector &CP = MCP->getConstants(); + if (CP.empty()) return; + + // FIXME: handle PIC codegen + assert(TM.getRelocationModel() != Reloc::PIC_ && + "PIC codegen not yet handled for mach-o jump tables!"); + + // Although there is no strict necessity that I am aware of, we will do what + // gcc for OS X does and put each constant pool entry in a section of constant + // objects of a certain size. That means that float constants go in the + // literal4 section, and double objects go in literal8, etc. + // + // FIXME: revisit this decision if we ever do the "stick everything into one + // "giant object for PIC" optimization. + for (unsigned i = 0, e = CP.size(); i != e; ++i) { + const Type *Ty = CP[i].getType(); + unsigned Size = TM.getTargetData()->getTypeAllocSize(Ty); + + MachOSection *Sec = MOW.getConstSection(CP[i].Val.ConstVal); + OutputBuffer SecDataOut(Sec->getData(), is64Bit, isLittleEndian); + + CPLocations.push_back(Sec->size()); + CPSections.push_back(Sec->Index); + + // Allocate space in the section for the global. + // FIXME: need alignment? + // FIXME: share between here and AddSymbolToSection? + for (unsigned j = 0; j < Size; ++j) + SecDataOut.outbyte(0); + + MachOWriter::InitMem(CP[i].Val.ConstVal, CPLocations[i], + TM.getTargetData(), Sec); + } +} + +/// emitJumpTables - Emit all the jump tables for a given jump table info +/// record to the appropriate section. +void MachOCodeEmitter::emitJumpTables(MachineJumpTableInfo *MJTI) { + const std::vector &JT = MJTI->getJumpTables(); + if (JT.empty()) return; + + // FIXME: handle PIC codegen + assert(TM.getRelocationModel() != Reloc::PIC_ && + "PIC codegen not yet handled for mach-o jump tables!"); + + MachOSection *Sec = MOW.getJumpTableSection(); + unsigned TextSecIndex = MOW.getTextSection()->Index; + OutputBuffer SecDataOut(Sec->getData(), is64Bit, isLittleEndian); + + for (unsigned i = 0, e = JT.size(); i != e; ++i) { + // For each jump table, record its offset from the start of the section, + // reserve space for the relocations to the MBBs, and add the relocations. + const std::vector &MBBs = JT[i].MBBs; + JTLocations.push_back(Sec->size()); + for (unsigned mi = 0, me = MBBs.size(); mi != me; ++mi) { + MachineRelocation MR(MOW.GetJTRelocation(Sec->size(), MBBs[mi])); + MR.setResultPointer((void *)JTLocations[i]); + MR.setConstantVal(TextSecIndex); + Sec->addRelocation(MR); + SecDataOut.outaddr(0); + } + } +} + +} // end namespace llvm + diff --git a/libclamav/c++/llvm/lib/CodeGen/MachOCodeEmitter.h b/libclamav/c++/llvm/lib/CodeGen/MachOCodeEmitter.h new file mode 100644 index 000000000..475244646 --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/MachOCodeEmitter.h @@ -0,0 +1,69 @@ +//===-- MachOEmitter.h - Target-independent Mach-O Emitter class ----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef MACHOCODEEMITTER_H +#define MACHOCODEEMITTER_H + +#include "llvm/CodeGen/ObjectCodeEmitter.h" +#include + +namespace llvm { + +class MachOWriter; + +/// MachOCodeEmitter - This class is used by the MachOWriter to emit the code +/// for functions to the Mach-O file. + +class MachOCodeEmitter : public ObjectCodeEmitter { + MachOWriter &MOW; + + /// Target machine description. + TargetMachine &TM; + + /// is64Bit/isLittleEndian - This information is inferred from the target + /// machine directly, indicating what header values and flags to set. + bool is64Bit, isLittleEndian; + + const MCAsmInfo *MAI; + + /// Relocations - These are the relocations that the function needs, as + /// emitted. + std::vector Relocations; + + std::map Labels; + +public: + MachOCodeEmitter(MachOWriter &mow, MachOSection &mos); + + virtual void startFunction(MachineFunction &MF); + virtual bool finishFunction(MachineFunction &MF); + + virtual void addRelocation(const MachineRelocation &MR) { + Relocations.push_back(MR); + } + + void emitConstantPool(MachineConstantPool *MCP); + void emitJumpTables(MachineJumpTableInfo *MJTI); + + virtual void emitLabel(uint64_t LabelID) { + Labels[LabelID] = getCurrentPCOffset(); + } + + virtual uintptr_t getLabelAddress(uint64_t Label) const { + return Labels.find(Label)->second; + } + + virtual void setModuleInfo(llvm::MachineModuleInfo* MMI) { } + +}; // end class MachOCodeEmitter + +} // end namespace llvm + +#endif + diff --git a/libclamav/c++/llvm/lib/CodeGen/MachOWriter.cpp b/libclamav/c++/llvm/lib/CodeGen/MachOWriter.cpp new file mode 100644 index 000000000..73b15edba --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/MachOWriter.cpp @@ -0,0 +1,777 @@ +//===-- MachOWriter.cpp - Target-independent Mach-O Writer code -----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the target-independent Mach-O writer. This file writes +// out the Mach-O file in the following order: +// +// #1 FatHeader (universal-only) +// #2 FatArch (universal-only, 1 per universal arch) +// Per arch: +// #3 Header +// #4 Load Commands +// #5 Sections +// #6 Relocations +// #7 Symbols +// #8 Strings +// +//===----------------------------------------------------------------------===// + +#include "MachO.h" +#include "MachOWriter.h" +#include "MachOCodeEmitter.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Module.h" +#include "llvm/PassManager.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetMachOWriterInfo.h" +#include "llvm/Support/Mangler.h" +#include "llvm/Support/OutputBuffer.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" + +namespace llvm { + +/// AddMachOWriter - Concrete function to add the Mach-O writer to the function +/// pass manager. +ObjectCodeEmitter *AddMachOWriter(PassManagerBase &PM, + raw_ostream &O, + TargetMachine &TM) { + MachOWriter *MOW = new MachOWriter(O, TM); + PM.add(MOW); + return MOW->getObjectCodeEmitter(); +} + +//===----------------------------------------------------------------------===// +// MachOWriter Implementation +//===----------------------------------------------------------------------===// + +char MachOWriter::ID = 0; + +MachOWriter::MachOWriter(raw_ostream &o, TargetMachine &tm) + : MachineFunctionPass(&ID), O(o), TM(tm) { + is64Bit = TM.getTargetData()->getPointerSizeInBits() == 64; + isLittleEndian = TM.getTargetData()->isLittleEndian(); + + MAI = TM.getMCAsmInfo(); + + // Create the machine code emitter object for this target. + MachOCE = new MachOCodeEmitter(*this, *getTextSection(true)); +} + +MachOWriter::~MachOWriter() { + delete MachOCE; +} + +bool MachOWriter::doInitialization(Module &M) { + // Set the magic value, now that we know the pointer size and endianness + Header.setMagic(isLittleEndian, is64Bit); + + // Set the file type + // FIXME: this only works for object files, we do not support the creation + // of dynamic libraries or executables at this time. + Header.filetype = MachOHeader::MH_OBJECT; + + Mang = new Mangler(M); + return false; +} + +bool MachOWriter::runOnMachineFunction(MachineFunction &MF) { + return false; +} + +/// doFinalization - Now that the module has been completely processed, emit +/// the Mach-O file to 'O'. +bool MachOWriter::doFinalization(Module &M) { + // FIXME: we don't handle debug info yet, we should probably do that. + // Okay, the.text section has been completed, build the .data, .bss, and + // "common" sections next. + + for (Module::global_iterator I = M.global_begin(), E = M.global_end(); + I != E; ++I) + EmitGlobal(I); + + // Emit the header and load commands. + EmitHeaderAndLoadCommands(); + + // Emit the various sections and their relocation info. + EmitSections(); + EmitRelocations(); + + // Write the symbol table and the string table to the end of the file. + O.write((char*)&SymT[0], SymT.size()); + O.write((char*)&StrT[0], StrT.size()); + + // We are done with the abstract symbols. + SectionList.clear(); + SymbolTable.clear(); + DynamicSymbolTable.clear(); + + // Release the name mangler object. + delete Mang; Mang = 0; + return false; +} + +// getConstSection - Get constant section for Constant 'C' +MachOSection *MachOWriter::getConstSection(Constant *C) { + const ConstantArray *CVA = dyn_cast(C); + if (CVA && CVA->isCString()) + return getSection("__TEXT", "__cstring", + MachOSection::S_CSTRING_LITERALS); + + const Type *Ty = C->getType(); + if (Ty->isPrimitiveType() || Ty->isInteger()) { + unsigned Size = TM.getTargetData()->getTypeAllocSize(Ty); + switch(Size) { + default: break; // Fall through to __TEXT,__const + case 4: + return getSection("__TEXT", "__literal4", + MachOSection::S_4BYTE_LITERALS); + case 8: + return getSection("__TEXT", "__literal8", + MachOSection::S_8BYTE_LITERALS); + case 16: + return getSection("__TEXT", "__literal16", + MachOSection::S_16BYTE_LITERALS); + } + } + return getSection("__TEXT", "__const"); +} + +// getJumpTableSection - Select the Jump Table section +MachOSection *MachOWriter::getJumpTableSection() { + if (TM.getRelocationModel() == Reloc::PIC_) + return getTextSection(false); + else + return getSection("__TEXT", "__const"); +} + +// getSection - Return the section with the specified name, creating a new +// section if one does not already exist. +MachOSection *MachOWriter::getSection(const std::string &seg, + const std::string §, + unsigned Flags /* = 0 */ ) { + MachOSection *MOS = SectionLookup[seg+sect]; + if (MOS) return MOS; + + MOS = new MachOSection(seg, sect); + SectionList.push_back(MOS); + MOS->Index = SectionList.size(); + MOS->flags = MachOSection::S_REGULAR | Flags; + SectionLookup[seg+sect] = MOS; + return MOS; +} + +// getTextSection - Return text section with different flags for code/data +MachOSection *MachOWriter::getTextSection(bool isCode /* = true */ ) { + if (isCode) + return getSection("__TEXT", "__text", + MachOSection::S_ATTR_PURE_INSTRUCTIONS | + MachOSection::S_ATTR_SOME_INSTRUCTIONS); + else + return getSection("__TEXT", "__text"); +} + +MachOSection *MachOWriter::getBSSSection() { + return getSection("__DATA", "__bss", MachOSection::S_ZEROFILL); +} + +// GetJTRelocation - Get a relocation a new BB relocation based +// on target information. +MachineRelocation MachOWriter::GetJTRelocation(unsigned Offset, + MachineBasicBlock *MBB) const { + return TM.getMachOWriterInfo()->GetJTRelocation(Offset, MBB); +} + +// GetTargetRelocation - Returns the number of relocations. +unsigned MachOWriter::GetTargetRelocation(MachineRelocation &MR, + unsigned FromIdx, unsigned ToAddr, + unsigned ToIndex, OutputBuffer &RelocOut, + OutputBuffer &SecOut, bool Scattered, + bool Extern) { + return TM.getMachOWriterInfo()->GetTargetRelocation(MR, FromIdx, ToAddr, + ToIndex, RelocOut, + SecOut, Scattered, + Extern); +} + +void MachOWriter::AddSymbolToSection(MachOSection *Sec, GlobalVariable *GV) { + const Type *Ty = GV->getType()->getElementType(); + unsigned Size = TM.getTargetData()->getTypeAllocSize(Ty); + unsigned Align = TM.getTargetData()->getPreferredAlignment(GV); + + // Reserve space in the .bss section for this symbol while maintaining the + // desired section alignment, which must be at least as much as required by + // this symbol. + OutputBuffer SecDataOut(Sec->getData(), is64Bit, isLittleEndian); + + if (Align) { + Align = Log2_32(Align); + Sec->align = std::max(unsigned(Sec->align), Align); + + Sec->emitAlignment(Sec->align); + } + // Globals without external linkage apparently do not go in the symbol table. + if (!GV->hasLocalLinkage()) { + MachOSym Sym(GV, Mang->getMangledName(GV), Sec->Index, MAI); + Sym.n_value = Sec->size(); + SymbolTable.push_back(Sym); + } + + // Record the offset of the symbol, and then allocate space for it. + // FIXME: remove when we have unified size + output buffer + + // Now that we know what section the GlovalVariable is going to be emitted + // into, update our mappings. + // FIXME: We may also need to update this when outputting non-GlobalVariable + // GlobalValues such as functions. + + GVSection[GV] = Sec; + GVOffset[GV] = Sec->size(); + + // Allocate space in the section for the global. + for (unsigned i = 0; i < Size; ++i) + SecDataOut.outbyte(0); +} + +void MachOWriter::EmitGlobal(GlobalVariable *GV) { + const Type *Ty = GV->getType()->getElementType(); + unsigned Size = TM.getTargetData()->getTypeAllocSize(Ty); + bool NoInit = !GV->hasInitializer(); + + // If this global has a zero initializer, it is part of the .bss or common + // section. + if (NoInit || GV->getInitializer()->isNullValue()) { + // If this global is part of the common block, add it now. Variables are + // part of the common block if they are zero initialized and allowed to be + // merged with other symbols. + if (NoInit || GV->hasLinkOnceLinkage() || GV->hasWeakLinkage() || + GV->hasCommonLinkage()) { + MachOSym ExtOrCommonSym(GV, Mang->getMangledName(GV), + MachOSym::NO_SECT, MAI); + // For undefined (N_UNDF) external (N_EXT) types, n_value is the size in + // bytes of the symbol. + ExtOrCommonSym.n_value = Size; + SymbolTable.push_back(ExtOrCommonSym); + // Remember that we've seen this symbol + GVOffset[GV] = Size; + return; + } + // Otherwise, this symbol is part of the .bss section. + MachOSection *BSS = getBSSSection(); + AddSymbolToSection(BSS, GV); + return; + } + + // Scalar read-only data goes in a literal section if the scalar is 4, 8, or + // 16 bytes, or a cstring. Other read only data goes into a regular const + // section. Read-write data goes in the data section. + MachOSection *Sec = GV->isConstant() ? getConstSection(GV->getInitializer()) : + getDataSection(); + AddSymbolToSection(Sec, GV); + InitMem(GV->getInitializer(), GVOffset[GV], TM.getTargetData(), Sec); +} + + + +void MachOWriter::EmitHeaderAndLoadCommands() { + // Step #0: Fill in the segment load command size, since we need it to figure + // out the rest of the header fields + + MachOSegment SEG("", is64Bit); + SEG.nsects = SectionList.size(); + SEG.cmdsize = SEG.cmdSize(is64Bit) + + SEG.nsects * SectionList[0]->cmdSize(is64Bit); + + // Step #1: calculate the number of load commands. We always have at least + // one, for the LC_SEGMENT load command, plus two for the normal + // and dynamic symbol tables, if there are any symbols. + Header.ncmds = SymbolTable.empty() ? 1 : 3; + + // Step #2: calculate the size of the load commands + Header.sizeofcmds = SEG.cmdsize; + if (!SymbolTable.empty()) + Header.sizeofcmds += SymTab.cmdsize + DySymTab.cmdsize; + + // Step #3: write the header to the file + // Local alias to shortenify coming code. + std::vector &FH = Header.HeaderData; + OutputBuffer FHOut(FH, is64Bit, isLittleEndian); + + FHOut.outword(Header.magic); + FHOut.outword(TM.getMachOWriterInfo()->getCPUType()); + FHOut.outword(TM.getMachOWriterInfo()->getCPUSubType()); + FHOut.outword(Header.filetype); + FHOut.outword(Header.ncmds); + FHOut.outword(Header.sizeofcmds); + FHOut.outword(Header.flags); + if (is64Bit) + FHOut.outword(Header.reserved); + + // Step #4: Finish filling in the segment load command and write it out + for (std::vector::iterator I = SectionList.begin(), + E = SectionList.end(); I != E; ++I) + SEG.filesize += (*I)->size(); + + SEG.vmsize = SEG.filesize; + SEG.fileoff = Header.cmdSize(is64Bit) + Header.sizeofcmds; + + FHOut.outword(SEG.cmd); + FHOut.outword(SEG.cmdsize); + FHOut.outstring(SEG.segname, 16); + FHOut.outaddr(SEG.vmaddr); + FHOut.outaddr(SEG.vmsize); + FHOut.outaddr(SEG.fileoff); + FHOut.outaddr(SEG.filesize); + FHOut.outword(SEG.maxprot); + FHOut.outword(SEG.initprot); + FHOut.outword(SEG.nsects); + FHOut.outword(SEG.flags); + + // Step #5: Finish filling in the fields of the MachOSections + uint64_t currentAddr = 0; + for (std::vector::iterator I = SectionList.begin(), + E = SectionList.end(); I != E; ++I) { + MachOSection *MOS = *I; + MOS->addr = currentAddr; + MOS->offset = currentAddr + SEG.fileoff; + // FIXME: do we need to do something with alignment here? + currentAddr += MOS->size(); + } + + // Step #6: Emit the symbol table to temporary buffers, so that we know the + // size of the string table when we write the next load command. This also + // sorts and assigns indices to each of the symbols, which is necessary for + // emitting relocations to externally-defined objects. + BufferSymbolAndStringTable(); + + // Step #7: Calculate the number of relocations for each section and write out + // the section commands for each section + currentAddr += SEG.fileoff; + for (std::vector::iterator I = SectionList.begin(), + E = SectionList.end(); I != E; ++I) { + MachOSection *MOS = *I; + + // Convert the relocations to target-specific relocations, and fill in the + // relocation offset for this section. + CalculateRelocations(*MOS); + MOS->reloff = MOS->nreloc ? currentAddr : 0; + currentAddr += MOS->nreloc * 8; + + // write the finalized section command to the output buffer + FHOut.outstring(MOS->sectname, 16); + FHOut.outstring(MOS->segname, 16); + FHOut.outaddr(MOS->addr); + FHOut.outaddr(MOS->size()); + FHOut.outword(MOS->offset); + FHOut.outword(MOS->align); + FHOut.outword(MOS->reloff); + FHOut.outword(MOS->nreloc); + FHOut.outword(MOS->flags); + FHOut.outword(MOS->reserved1); + FHOut.outword(MOS->reserved2); + if (is64Bit) + FHOut.outword(MOS->reserved3); + } + + // Step #8: Emit LC_SYMTAB/LC_DYSYMTAB load commands + SymTab.symoff = currentAddr; + SymTab.nsyms = SymbolTable.size(); + SymTab.stroff = SymTab.symoff + SymT.size(); + SymTab.strsize = StrT.size(); + FHOut.outword(SymTab.cmd); + FHOut.outword(SymTab.cmdsize); + FHOut.outword(SymTab.symoff); + FHOut.outword(SymTab.nsyms); + FHOut.outword(SymTab.stroff); + FHOut.outword(SymTab.strsize); + + // FIXME: set DySymTab fields appropriately + // We should probably just update these in BufferSymbolAndStringTable since + // thats where we're partitioning up the different kinds of symbols. + FHOut.outword(DySymTab.cmd); + FHOut.outword(DySymTab.cmdsize); + FHOut.outword(DySymTab.ilocalsym); + FHOut.outword(DySymTab.nlocalsym); + FHOut.outword(DySymTab.iextdefsym); + FHOut.outword(DySymTab.nextdefsym); + FHOut.outword(DySymTab.iundefsym); + FHOut.outword(DySymTab.nundefsym); + FHOut.outword(DySymTab.tocoff); + FHOut.outword(DySymTab.ntoc); + FHOut.outword(DySymTab.modtaboff); + FHOut.outword(DySymTab.nmodtab); + FHOut.outword(DySymTab.extrefsymoff); + FHOut.outword(DySymTab.nextrefsyms); + FHOut.outword(DySymTab.indirectsymoff); + FHOut.outword(DySymTab.nindirectsyms); + FHOut.outword(DySymTab.extreloff); + FHOut.outword(DySymTab.nextrel); + FHOut.outword(DySymTab.locreloff); + FHOut.outword(DySymTab.nlocrel); + + O.write((char*)&FH[0], FH.size()); +} + +/// EmitSections - Now that we have constructed the file header and load +/// commands, emit the data for each section to the file. +void MachOWriter::EmitSections() { + for (std::vector::iterator I = SectionList.begin(), + E = SectionList.end(); I != E; ++I) + // Emit the contents of each section + if ((*I)->size()) + O.write((char*)&(*I)->getData()[0], (*I)->size()); +} + +/// EmitRelocations - emit relocation data from buffer. +void MachOWriter::EmitRelocations() { + for (std::vector::iterator I = SectionList.begin(), + E = SectionList.end(); I != E; ++I) + // Emit the relocation entry data for each section. + if ((*I)->RelocBuffer.size()) + O.write((char*)&(*I)->RelocBuffer[0], (*I)->RelocBuffer.size()); +} + +/// BufferSymbolAndStringTable - Sort the symbols we encountered and assign them +/// each a string table index so that they appear in the correct order in the +/// output file. +void MachOWriter::BufferSymbolAndStringTable() { + // The order of the symbol table is: + // 1. local symbols + // 2. defined external symbols (sorted by name) + // 3. undefined external symbols (sorted by name) + + // Before sorting the symbols, check the PendingGlobals for any undefined + // globals that need to be put in the symbol table. + for (std::vector::iterator I = PendingGlobals.begin(), + E = PendingGlobals.end(); I != E; ++I) { + if (GVOffset[*I] == 0 && GVSection[*I] == 0) { + MachOSym UndfSym(*I, Mang->getMangledName(*I), MachOSym::NO_SECT, MAI); + SymbolTable.push_back(UndfSym); + GVOffset[*I] = -1; + } + } + + // Sort the symbols by name, so that when we partition the symbols by scope + // of definition, we won't have to sort by name within each partition. + std::sort(SymbolTable.begin(), SymbolTable.end(), MachOSym::SymCmp()); + + // Parition the symbol table entries so that all local symbols come before + // all symbols with external linkage. { 1 | 2 3 } + std::partition(SymbolTable.begin(), SymbolTable.end(), + MachOSym::PartitionByLocal); + + // Advance iterator to beginning of external symbols and partition so that + // all external symbols defined in this module come before all external + // symbols defined elsewhere. { 1 | 2 | 3 } + for (std::vector::iterator I = SymbolTable.begin(), + E = SymbolTable.end(); I != E; ++I) { + if (!MachOSym::PartitionByLocal(*I)) { + std::partition(I, E, MachOSym::PartitionByDefined); + break; + } + } + + // Calculate the starting index for each of the local, extern defined, and + // undefined symbols, as well as the number of each to put in the LC_DYSYMTAB + // load command. + for (std::vector::iterator I = SymbolTable.begin(), + E = SymbolTable.end(); I != E; ++I) { + if (MachOSym::PartitionByLocal(*I)) { + ++DySymTab.nlocalsym; + ++DySymTab.iextdefsym; + ++DySymTab.iundefsym; + } else if (MachOSym::PartitionByDefined(*I)) { + ++DySymTab.nextdefsym; + ++DySymTab.iundefsym; + } else { + ++DySymTab.nundefsym; + } + } + + // Write out a leading zero byte when emitting string table, for n_strx == 0 + // which means an empty string. + OutputBuffer StrTOut(StrT, is64Bit, isLittleEndian); + StrTOut.outbyte(0); + + // The order of the string table is: + // 1. strings for external symbols + // 2. strings for local symbols + // Since this is the opposite order from the symbol table, which we have just + // sorted, we can walk the symbol table backwards to output the string table. + for (std::vector::reverse_iterator I = SymbolTable.rbegin(), + E = SymbolTable.rend(); I != E; ++I) { + if (I->GVName == "") { + I->n_strx = 0; + } else { + I->n_strx = StrT.size(); + StrTOut.outstring(I->GVName, I->GVName.length()+1); + } + } + + OutputBuffer SymTOut(SymT, is64Bit, isLittleEndian); + + unsigned index = 0; + for (std::vector::iterator I = SymbolTable.begin(), + E = SymbolTable.end(); I != E; ++I, ++index) { + // Add the section base address to the section offset in the n_value field + // to calculate the full address. + // FIXME: handle symbols where the n_value field is not the address + GlobalValue *GV = const_cast(I->GV); + if (GV && GVSection[GV]) + I->n_value += GVSection[GV]->addr; + if (GV && (GVOffset[GV] == -1)) + GVOffset[GV] = index; + + // Emit nlist to buffer + SymTOut.outword(I->n_strx); + SymTOut.outbyte(I->n_type); + SymTOut.outbyte(I->n_sect); + SymTOut.outhalf(I->n_desc); + SymTOut.outaddr(I->n_value); + } +} + +/// CalculateRelocations - For each MachineRelocation in the current section, +/// calculate the index of the section containing the object to be relocated, +/// and the offset into that section. From this information, create the +/// appropriate target-specific MachORelocation type and add buffer it to be +/// written out after we are finished writing out sections. +void MachOWriter::CalculateRelocations(MachOSection &MOS) { + std::vector Relocations = MOS.getRelocations(); + for (unsigned i = 0, e = Relocations.size(); i != e; ++i) { + MachineRelocation &MR = Relocations[i]; + unsigned TargetSection = MR.getConstantVal(); + unsigned TargetAddr = 0; + unsigned TargetIndex = 0; + + // This is a scattered relocation entry if it points to a global value with + // a non-zero offset. + bool Scattered = false; + bool Extern = false; + + // Since we may not have seen the GlobalValue we were interested in yet at + // the time we emitted the relocation for it, fix it up now so that it + // points to the offset into the correct section. + if (MR.isGlobalValue()) { + GlobalValue *GV = MR.getGlobalValue(); + MachOSection *MOSPtr = GVSection[GV]; + intptr_t Offset = GVOffset[GV]; + + // If we have never seen the global before, it must be to a symbol + // defined in another module (N_UNDF). + if (!MOSPtr) { + // FIXME: need to append stub suffix + Extern = true; + TargetAddr = 0; + TargetIndex = GVOffset[GV]; + } else { + Scattered = TargetSection != 0; + TargetSection = MOSPtr->Index; + } + MR.setResultPointer((void*)Offset); + } + + // If the symbol is locally defined, pass in the address of the section and + // the section index to the code which will generate the target relocation. + if (!Extern) { + MachOSection &To = *SectionList[TargetSection - 1]; + TargetAddr = To.addr; + TargetIndex = To.Index; + } + + OutputBuffer RelocOut(MOS.RelocBuffer, is64Bit, isLittleEndian); + OutputBuffer SecOut(MOS.getData(), is64Bit, isLittleEndian); + + MOS.nreloc += GetTargetRelocation(MR, MOS.Index, TargetAddr, TargetIndex, + RelocOut, SecOut, Scattered, Extern); + } +} + +// InitMem - Write the value of a Constant to the specified memory location, +// converting it into bytes and relocations. +void MachOWriter::InitMem(const Constant *C, uintptr_t Offset, + const TargetData *TD, MachOSection* mos) { + typedef std::pair CPair; + std::vector WorkList; + uint8_t *Addr = &mos->getData()[0]; + + WorkList.push_back(CPair(C,(intptr_t)Addr + Offset)); + + intptr_t ScatteredOffset = 0; + + while (!WorkList.empty()) { + const Constant *PC = WorkList.back().first; + intptr_t PA = WorkList.back().second; + WorkList.pop_back(); + + if (isa(PC)) { + continue; + } else if (const ConstantVector *CP = dyn_cast(PC)) { + unsigned ElementSize = + TD->getTypeAllocSize(CP->getType()->getElementType()); + for (unsigned i = 0, e = CP->getNumOperands(); i != e; ++i) + WorkList.push_back(CPair(CP->getOperand(i), PA+i*ElementSize)); + } else if (const ConstantExpr *CE = dyn_cast(PC)) { + // + // FIXME: Handle ConstantExpression. See EE::getConstantValue() + // + switch (CE->getOpcode()) { + case Instruction::GetElementPtr: { + SmallVector Indices(CE->op_begin()+1, CE->op_end()); + ScatteredOffset = TD->getIndexedOffset(CE->getOperand(0)->getType(), + &Indices[0], Indices.size()); + WorkList.push_back(CPair(CE->getOperand(0), PA)); + break; + } + case Instruction::Add: + default: + errs() << "ConstantExpr not handled as global var init: " << *CE <<"\n"; + llvm_unreachable(0); + } + } else if (PC->getType()->isSingleValueType()) { + unsigned char *ptr = (unsigned char *)PA; + switch (PC->getType()->getTypeID()) { + case Type::IntegerTyID: { + unsigned NumBits = cast(PC->getType())->getBitWidth(); + uint64_t val = cast(PC)->getZExtValue(); + if (NumBits <= 8) + ptr[0] = val; + else if (NumBits <= 16) { + if (TD->isBigEndian()) + val = ByteSwap_16(val); + ptr[0] = val; + ptr[1] = val >> 8; + } else if (NumBits <= 32) { + if (TD->isBigEndian()) + val = ByteSwap_32(val); + ptr[0] = val; + ptr[1] = val >> 8; + ptr[2] = val >> 16; + ptr[3] = val >> 24; + } else if (NumBits <= 64) { + if (TD->isBigEndian()) + val = ByteSwap_64(val); + ptr[0] = val; + ptr[1] = val >> 8; + ptr[2] = val >> 16; + ptr[3] = val >> 24; + ptr[4] = val >> 32; + ptr[5] = val >> 40; + ptr[6] = val >> 48; + ptr[7] = val >> 56; + } else { + llvm_unreachable("Not implemented: bit widths > 64"); + } + break; + } + case Type::FloatTyID: { + uint32_t val = cast(PC)->getValueAPF().bitcastToAPInt(). + getZExtValue(); + if (TD->isBigEndian()) + val = ByteSwap_32(val); + ptr[0] = val; + ptr[1] = val >> 8; + ptr[2] = val >> 16; + ptr[3] = val >> 24; + break; + } + case Type::DoubleTyID: { + uint64_t val = cast(PC)->getValueAPF().bitcastToAPInt(). + getZExtValue(); + if (TD->isBigEndian()) + val = ByteSwap_64(val); + ptr[0] = val; + ptr[1] = val >> 8; + ptr[2] = val >> 16; + ptr[3] = val >> 24; + ptr[4] = val >> 32; + ptr[5] = val >> 40; + ptr[6] = val >> 48; + ptr[7] = val >> 56; + break; + } + case Type::PointerTyID: + if (isa(PC)) + memset(ptr, 0, TD->getPointerSize()); + else if (const GlobalValue* GV = dyn_cast(PC)) { + // FIXME: what about function stubs? + mos->addRelocation(MachineRelocation::getGV(PA-(intptr_t)Addr, + MachineRelocation::VANILLA, + const_cast(GV), + ScatteredOffset)); + ScatteredOffset = 0; + } else + llvm_unreachable("Unknown constant pointer type!"); + break; + default: + std::string msg; + raw_string_ostream Msg(msg); + Msg << "ERROR: Constant unimp for type: " << *PC->getType(); + llvm_report_error(Msg.str()); + } + } else if (isa(PC)) { + memset((void*)PA, 0, (size_t)TD->getTypeAllocSize(PC->getType())); + } else if (const ConstantArray *CPA = dyn_cast(PC)) { + unsigned ElementSize = + TD->getTypeAllocSize(CPA->getType()->getElementType()); + for (unsigned i = 0, e = CPA->getNumOperands(); i != e; ++i) + WorkList.push_back(CPair(CPA->getOperand(i), PA+i*ElementSize)); + } else if (const ConstantStruct *CPS = dyn_cast(PC)) { + const StructLayout *SL = + TD->getStructLayout(cast(CPS->getType())); + for (unsigned i = 0, e = CPS->getNumOperands(); i != e; ++i) + WorkList.push_back(CPair(CPS->getOperand(i), + PA+SL->getElementOffset(i))); + } else { + errs() << "Bad Type: " << *PC->getType() << "\n"; + llvm_unreachable("Unknown constant type to initialize memory with!"); + } + } +} + +//===----------------------------------------------------------------------===// +// MachOSym Implementation +//===----------------------------------------------------------------------===// + +MachOSym::MachOSym(const GlobalValue *gv, std::string name, uint8_t sect, + const MCAsmInfo *MAI) : + GV(gv), n_strx(0), n_type(sect == NO_SECT ? N_UNDF : N_SECT), n_sect(sect), + n_desc(0), n_value(0) { + + // FIXME: This is completely broken, it should use the mangler interface. + switch (GV->getLinkage()) { + default: + llvm_unreachable("Unexpected linkage type!"); + break; + case GlobalValue::WeakAnyLinkage: + case GlobalValue::WeakODRLinkage: + case GlobalValue::LinkOnceAnyLinkage: + case GlobalValue::LinkOnceODRLinkage: + case GlobalValue::CommonLinkage: + assert(!isa(gv) && "Unexpected linkage type for Function!"); + case GlobalValue::ExternalLinkage: + GVName = MAI->getGlobalPrefix() + name; + n_type |= GV->hasHiddenVisibility() ? N_PEXT : N_EXT; + break; + case GlobalValue::PrivateLinkage: + GVName = MAI->getPrivateGlobalPrefix() + name; + break; + case GlobalValue::LinkerPrivateLinkage: + GVName = MAI->getLinkerPrivateGlobalPrefix() + name; + break; + case GlobalValue::InternalLinkage: + GVName = MAI->getGlobalPrefix() + name; + break; + } +} + +} // end namespace llvm diff --git a/libclamav/c++/llvm/lib/CodeGen/MachOWriter.h b/libclamav/c++/llvm/lib/CodeGen/MachOWriter.h new file mode 100644 index 000000000..9273f3854 --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/MachOWriter.h @@ -0,0 +1,206 @@ +//=== MachOWriter.h - Target-independent Mach-O writer support --*- 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 the MachOWriter class. +// +//===----------------------------------------------------------------------===// + +#ifndef MACHOWRITER_H +#define MACHOWRITER_H + +#include "llvm/CodeGen/MachineFunctionPass.h" +#include +#include + +namespace llvm { + class Constant; + class GlobalVariable; + class Mangler; + class MachineBasicBlock; + class MachineRelocation; + class MachOCodeEmitter; + struct MachODySymTab; + struct MachOHeader; + struct MachOSection; + struct MachOSym; + class TargetData; + class TargetMachine; + class MCAsmInfo; + class ObjectCodeEmitter; + class OutputBuffer; + class raw_ostream; + + /// MachOWriter - This class implements the common target-independent code for + /// writing Mach-O files. Targets should derive a class from this to + /// parameterize the output format. + /// + class MachOWriter : public MachineFunctionPass { + friend class MachOCodeEmitter; + public: + static char ID; + + ObjectCodeEmitter *getObjectCodeEmitter() { + return reinterpret_cast(MachOCE); + } + + MachOWriter(raw_ostream &O, TargetMachine &TM); + virtual ~MachOWriter(); + + virtual const char *getPassName() const { + return "Mach-O Writer"; + } + + protected: + /// Output stream to send the resultant object file to. + /// + raw_ostream &O; + + /// Target machine description. + /// + TargetMachine &TM; + + /// Mang - The object used to perform name mangling for this module. + /// + Mangler *Mang; + + /// MachOCE - The MachineCodeEmitter object that we are exposing to emit + /// machine code for functions to the .o file. + MachOCodeEmitter *MachOCE; + + /// is64Bit/isLittleEndian - This information is inferred from the target + /// machine directly, indicating what header values and flags to set. + bool is64Bit, isLittleEndian; + + // Target Asm Info + const MCAsmInfo *MAI; + + /// Header - An instance of MachOHeader that we will update while we build + /// the file, and then emit during finalization. + MachOHeader Header; + + /// doInitialization - Emit the file header and all of the global variables + /// for the module to the Mach-O file. + bool doInitialization(Module &M); + + bool runOnMachineFunction(MachineFunction &MF); + + /// doFinalization - Now that the module has been completely processed, emit + /// the Mach-O file to 'O'. + bool doFinalization(Module &M); + + private: + + /// SectionList - This is the list of sections that we have emitted to the + /// file. Once the file has been completely built, the segment load command + /// SectionCommands are constructed from this info. + std::vector SectionList; + + /// SectionLookup - This is a mapping from section name to SectionList entry + std::map SectionLookup; + + /// GVSection - This is a mapping from a GlobalValue to a MachOSection, + /// to aid in emitting relocations. + std::map GVSection; + + /// GVOffset - This is a mapping from a GlobalValue to an offset from the + /// start of the section in which the GV resides, to aid in emitting + /// relocations. + std::map GVOffset; + + /// getSection - Return the section with the specified name, creating a new + /// section if one does not already exist. + MachOSection *getSection(const std::string &seg, const std::string §, + unsigned Flags = 0); + + /// getTextSection - Return text section with different flags for code/data + MachOSection *getTextSection(bool isCode = true); + + MachOSection *getDataSection() { + return getSection("__DATA", "__data"); + } + + MachOSection *getBSSSection(); + MachOSection *getConstSection(Constant *C); + MachOSection *getJumpTableSection(); + + /// MachOSymTab - This struct contains information about the offsets and + /// size of symbol table information. + /// segment. + struct MachOSymTab { + uint32_t cmd; // LC_SYMTAB + uint32_t cmdsize; // sizeof( MachOSymTab ) + uint32_t symoff; // symbol table offset + uint32_t nsyms; // number of symbol table entries + uint32_t stroff; // string table offset + uint32_t strsize; // string table size in bytes + + // Constants for the cmd field + // see + enum { LC_SYMTAB = 0x02 // link-edit stab symbol table info + }; + + MachOSymTab() : cmd(LC_SYMTAB), cmdsize(6 * sizeof(uint32_t)), symoff(0), + nsyms(0), stroff(0), strsize(0) { } + }; + + /// SymTab - The "stab" style symbol table information + MachOSymTab SymTab; + /// DySymTab - symbol table info for the dynamic link editor + MachODySymTab DySymTab; + + protected: + + /// SymbolTable - This is the list of symbols we have emitted to the file. + /// This actually gets rearranged before emission to the file (to put the + /// local symbols first in the list). + std::vector SymbolTable; + + /// SymT - A buffer to hold the symbol table before we write it out at the + /// appropriate location in the file. + std::vector SymT; + + /// StrT - A buffer to hold the string table before we write it out at the + /// appropriate location in the file. + std::vector StrT; + + /// PendingSyms - This is a list of externally defined symbols that we have + /// been asked to emit, but have not seen a reference to. When a reference + /// is seen, the symbol will move from this list to the SymbolTable. + std::vector PendingGlobals; + + /// DynamicSymbolTable - This is just a vector of indices into + /// SymbolTable to aid in emitting the DYSYMTAB load command. + std::vector DynamicSymbolTable; + + static void InitMem(const Constant *C, uintptr_t Offset, + const TargetData *TD, MachOSection* mos); + + private: + void AddSymbolToSection(MachOSection *MOS, GlobalVariable *GV); + void EmitGlobal(GlobalVariable *GV); + void EmitHeaderAndLoadCommands(); + void EmitSections(); + void EmitRelocations(); + void BufferSymbolAndStringTable(); + void CalculateRelocations(MachOSection &MOS); + + // GetJTRelocation - Get a relocation a new BB relocation based + // on target information. + MachineRelocation GetJTRelocation(unsigned Offset, + MachineBasicBlock *MBB) const; + + /// GetTargetRelocation - Returns the number of relocations. + unsigned GetTargetRelocation(MachineRelocation &MR, unsigned FromIdx, + unsigned ToAddr, unsigned ToIndex, + OutputBuffer &RelocOut, OutputBuffer &SecOut, + bool Scattered, bool Extern); + }; +} + +#endif diff --git a/libclamav/c++/llvm/lib/CodeGen/MachineBasicBlock.cpp b/libclamav/c++/llvm/lib/CodeGen/MachineBasicBlock.cpp new file mode 100644 index 000000000..e55e3694b --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/MachineBasicBlock.cpp @@ -0,0 +1,512 @@ +//===-- llvm/CodeGen/MachineBasicBlock.cpp ----------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Collect the sequence of machine instructions for a basic block. +// +//===----------------------------------------------------------------------===// + +#include "llvm/CodeGen/MachineBasicBlock.h" +#include "llvm/BasicBlock.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetInstrDesc.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Support/LeakDetector.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Assembly/Writer.h" +#include +using namespace llvm; + +MachineBasicBlock::MachineBasicBlock(MachineFunction &mf, const BasicBlock *bb) + : BB(bb), Number(-1), xParent(&mf), Alignment(0), IsLandingPad(false), + AddressTaken(false) { + Insts.Parent = this; +} + +MachineBasicBlock::~MachineBasicBlock() { + LeakDetector::removeGarbageObject(this); +} + +raw_ostream &llvm::operator<<(raw_ostream &OS, const MachineBasicBlock &MBB) { + MBB.print(OS); + return OS; +} + +/// addNodeToList (MBB) - When an MBB is added to an MF, we need to update the +/// parent pointer of the MBB, the MBB numbering, and any instructions in the +/// MBB to be on the right operand list for registers. +/// +/// MBBs start out as #-1. When a MBB is added to a MachineFunction, it +/// gets the next available unique MBB number. If it is removed from a +/// MachineFunction, it goes back to being #-1. +void ilist_traits::addNodeToList(MachineBasicBlock *N) { + MachineFunction &MF = *N->getParent(); + N->Number = MF.addToMBBNumbering(N); + + // Make sure the instructions have their operands in the reginfo lists. + MachineRegisterInfo &RegInfo = MF.getRegInfo(); + for (MachineBasicBlock::iterator I = N->begin(), E = N->end(); I != E; ++I) + I->AddRegOperandsToUseLists(RegInfo); + + LeakDetector::removeGarbageObject(N); +} + +void ilist_traits::removeNodeFromList(MachineBasicBlock *N) { + N->getParent()->removeFromMBBNumbering(N->Number); + N->Number = -1; + LeakDetector::addGarbageObject(N); +} + + +/// addNodeToList (MI) - When we add an instruction to a basic block +/// list, we update its parent pointer and add its operands from reg use/def +/// lists if appropriate. +void ilist_traits::addNodeToList(MachineInstr *N) { + assert(N->getParent() == 0 && "machine instruction already in a basic block"); + N->setParent(Parent); + + // Add the instruction's register operands to their corresponding + // use/def lists. + MachineFunction *MF = Parent->getParent(); + N->AddRegOperandsToUseLists(MF->getRegInfo()); + + LeakDetector::removeGarbageObject(N); +} + +/// removeNodeFromList (MI) - When we remove an instruction from a basic block +/// list, we update its parent pointer and remove its operands from reg use/def +/// lists if appropriate. +void ilist_traits::removeNodeFromList(MachineInstr *N) { + assert(N->getParent() != 0 && "machine instruction not in a basic block"); + + // Remove from the use/def lists. + N->RemoveRegOperandsFromUseLists(); + + N->setParent(0); + + LeakDetector::addGarbageObject(N); +} + +/// transferNodesFromList (MI) - When moving a range of instructions from one +/// MBB list to another, we need to update the parent pointers and the use/def +/// lists. +void ilist_traits:: +transferNodesFromList(ilist_traits &fromList, + MachineBasicBlock::iterator first, + MachineBasicBlock::iterator last) { + assert(Parent->getParent() == fromList.Parent->getParent() && + "MachineInstr parent mismatch!"); + + // Splice within the same MBB -> no change. + if (Parent == fromList.Parent) return; + + // If splicing between two blocks within the same function, just update the + // parent pointers. + for (; first != last; ++first) + first->setParent(Parent); +} + +void ilist_traits::deleteNode(MachineInstr* MI) { + assert(!MI->getParent() && "MI is still in a block!"); + Parent->getParent()->DeleteMachineInstr(MI); +} + +MachineBasicBlock::iterator MachineBasicBlock::getFirstTerminator() { + iterator I = end(); + while (I != begin() && (--I)->getDesc().isTerminator()) + ; /*noop */ + if (I != end() && !I->getDesc().isTerminator()) ++I; + return I; +} + +/// isOnlyReachableViaFallthough - Return true if this basic block has +/// exactly one predecessor and the control transfer mechanism between +/// the predecessor and this block is a fall-through. +bool MachineBasicBlock::isOnlyReachableByFallthrough() const { + // If this is a landing pad, it isn't a fall through. If it has no preds, + // then nothing falls through to it. + if (isLandingPad() || pred_empty()) + return false; + + // If there isn't exactly one predecessor, it can't be a fall through. + const_pred_iterator PI = pred_begin(), PI2 = PI; + ++PI2; + if (PI2 != pred_end()) + return false; + + // The predecessor has to be immediately before this block. + const MachineBasicBlock *Pred = *PI; + + if (!Pred->isLayoutSuccessor(this)) + return false; + + // If the block is completely empty, then it definitely does fall through. + if (Pred->empty()) + return true; + + // Otherwise, check the last instruction. + const MachineInstr &LastInst = Pred->back(); + return !LastInst.getDesc().isBarrier(); +} + +void MachineBasicBlock::dump() const { + print(errs()); +} + +static inline void OutputReg(raw_ostream &os, unsigned RegNo, + const TargetRegisterInfo *TRI = 0) { + if (RegNo != 0 && TargetRegisterInfo::isPhysicalRegister(RegNo)) { + if (TRI) + os << " %" << TRI->get(RegNo).Name; + else + os << " %physreg" << RegNo; + } else + os << " %reg" << RegNo; +} + +StringRef MachineBasicBlock::getName() const { + if (const BasicBlock *LBB = getBasicBlock()) + return LBB->getName(); + else + return "(null)"; +} + +void MachineBasicBlock::print(raw_ostream &OS) const { + const MachineFunction *MF = getParent(); + if (!MF) { + OS << "Can't print out MachineBasicBlock because parent MachineFunction" + << " is null\n"; + return; + } + + if (Alignment) { OS << "Alignment " << Alignment << "\n"; } + + OS << "BB#" << getNumber() << ": "; + + const char *Comma = ""; + if (const BasicBlock *LBB = getBasicBlock()) { + OS << Comma << "derived from LLVM BB "; + WriteAsOperand(OS, LBB, /*PrintType=*/false); + Comma = ", "; + } + if (isLandingPad()) { OS << Comma << "EH LANDING PAD"; Comma = ", "; } + if (hasAddressTaken()) { OS << Comma << "ADDRESS TAKEN"; Comma = ", "; } + OS << '\n'; + + const TargetRegisterInfo *TRI = MF->getTarget().getRegisterInfo(); + if (!livein_empty()) { + OS << " Live Ins:"; + for (const_livein_iterator I = livein_begin(),E = livein_end(); I != E; ++I) + OutputReg(OS, *I, TRI); + OS << '\n'; + } + // Print the preds of this block according to the CFG. + if (!pred_empty()) { + OS << " Predecessors according to CFG:"; + for (const_pred_iterator PI = pred_begin(), E = pred_end(); PI != E; ++PI) + OS << " BB#" << (*PI)->getNumber(); + OS << '\n'; + } + + for (const_iterator I = begin(); I != end(); ++I) { + OS << '\t'; + I->print(OS, &getParent()->getTarget()); + } + + // Print the successors of this block according to the CFG. + if (!succ_empty()) { + OS << " Successors according to CFG:"; + for (const_succ_iterator SI = succ_begin(), E = succ_end(); SI != E; ++SI) + OS << " BB#" << (*SI)->getNumber(); + OS << '\n'; + } +} + +void MachineBasicBlock::removeLiveIn(unsigned Reg) { + livein_iterator I = std::find(livein_begin(), livein_end(), Reg); + assert(I != livein_end() && "Not a live in!"); + LiveIns.erase(I); +} + +bool MachineBasicBlock::isLiveIn(unsigned Reg) const { + const_livein_iterator I = std::find(livein_begin(), livein_end(), Reg); + return I != livein_end(); +} + +void MachineBasicBlock::moveBefore(MachineBasicBlock *NewAfter) { + getParent()->splice(NewAfter, this); +} + +void MachineBasicBlock::moveAfter(MachineBasicBlock *NewBefore) { + MachineFunction::iterator BBI = NewBefore; + getParent()->splice(++BBI, this); +} + +void MachineBasicBlock::updateTerminator() { + const TargetInstrInfo *TII = getParent()->getTarget().getInstrInfo(); + // A block with no successors has no concerns with fall-through edges. + if (this->succ_empty()) return; + + MachineBasicBlock *TBB = 0, *FBB = 0; + SmallVector Cond; + bool B = TII->AnalyzeBranch(*this, TBB, FBB, Cond); + (void) B; + assert(!B && "UpdateTerminators requires analyzable predecessors!"); + if (Cond.empty()) { + if (TBB) { + // The block has an unconditional branch. If its successor is now + // its layout successor, delete the branch. + if (isLayoutSuccessor(TBB)) + TII->RemoveBranch(*this); + } else { + // The block has an unconditional fallthrough. If its successor is not + // its layout successor, insert a branch. + TBB = *succ_begin(); + if (!isLayoutSuccessor(TBB)) + TII->InsertBranch(*this, TBB, 0, Cond); + } + } else { + if (FBB) { + // The block has a non-fallthrough conditional branch. If one of its + // successors is its layout successor, rewrite it to a fallthrough + // conditional branch. + if (isLayoutSuccessor(TBB)) { + if (TII->ReverseBranchCondition(Cond)) + return; + TII->RemoveBranch(*this); + TII->InsertBranch(*this, FBB, 0, Cond); + } else if (isLayoutSuccessor(FBB)) { + TII->RemoveBranch(*this); + TII->InsertBranch(*this, TBB, 0, Cond); + } + } else { + // The block has a fallthrough conditional branch. + MachineBasicBlock *MBBA = *succ_begin(); + MachineBasicBlock *MBBB = *next(succ_begin()); + if (MBBA == TBB) std::swap(MBBB, MBBA); + if (isLayoutSuccessor(TBB)) { + if (TII->ReverseBranchCondition(Cond)) { + // We can't reverse the condition, add an unconditional branch. + Cond.clear(); + TII->InsertBranch(*this, MBBA, 0, Cond); + return; + } + TII->RemoveBranch(*this); + TII->InsertBranch(*this, MBBA, 0, Cond); + } else if (!isLayoutSuccessor(MBBA)) { + TII->RemoveBranch(*this); + TII->InsertBranch(*this, TBB, MBBA, Cond); + } + } + } +} + +void MachineBasicBlock::addSuccessor(MachineBasicBlock *succ) { + Successors.push_back(succ); + succ->addPredecessor(this); +} + +void MachineBasicBlock::removeSuccessor(MachineBasicBlock *succ) { + succ->removePredecessor(this); + succ_iterator I = std::find(Successors.begin(), Successors.end(), succ); + assert(I != Successors.end() && "Not a current successor!"); + Successors.erase(I); +} + +MachineBasicBlock::succ_iterator +MachineBasicBlock::removeSuccessor(succ_iterator I) { + assert(I != Successors.end() && "Not a current successor!"); + (*I)->removePredecessor(this); + return Successors.erase(I); +} + +void MachineBasicBlock::addPredecessor(MachineBasicBlock *pred) { + Predecessors.push_back(pred); +} + +void MachineBasicBlock::removePredecessor(MachineBasicBlock *pred) { + std::vector::iterator I = + std::find(Predecessors.begin(), Predecessors.end(), pred); + assert(I != Predecessors.end() && "Pred is not a predecessor of this block!"); + Predecessors.erase(I); +} + +void MachineBasicBlock::transferSuccessors(MachineBasicBlock *fromMBB) { + if (this == fromMBB) + return; + + for (MachineBasicBlock::succ_iterator I = fromMBB->succ_begin(), + E = fromMBB->succ_end(); I != E; ++I) + addSuccessor(*I); + + while (!fromMBB->succ_empty()) + fromMBB->removeSuccessor(fromMBB->succ_begin()); +} + +bool MachineBasicBlock::isSuccessor(const MachineBasicBlock *MBB) const { + std::vector::const_iterator I = + std::find(Successors.begin(), Successors.end(), MBB); + return I != Successors.end(); +} + +bool MachineBasicBlock::isLayoutSuccessor(const MachineBasicBlock *MBB) const { + MachineFunction::const_iterator I(this); + return next(I) == MachineFunction::const_iterator(MBB); +} + +bool MachineBasicBlock::canFallThrough() { + MachineBasicBlock *TBB = 0, *FBB = 0; + SmallVector Cond; + const TargetInstrInfo *TII = getParent()->getTarget().getInstrInfo(); + bool BranchUnAnalyzable = TII->AnalyzeBranch(*this, TBB, FBB, Cond, true); + + MachineFunction::iterator Fallthrough = this; + ++Fallthrough; + // If FallthroughBlock is off the end of the function, it can't fall through. + if (Fallthrough == getParent()->end()) + return false; + + // If FallthroughBlock isn't a successor, no fallthrough is possible. + if (!isSuccessor(Fallthrough)) + return false; + + // If we couldn't analyze the branch, examine the last instruction. + // If the block doesn't end in a known control barrier, assume fallthrough + // is possible. The isPredicable check is needed because this code can be + // called during IfConversion, where an instruction which is normally a + // Barrier is predicated and thus no longer an actual control barrier. This + // is over-conservative though, because if an instruction isn't actually + // predicated we could still treat it like a barrier. + if (BranchUnAnalyzable) + return empty() || !back().getDesc().isBarrier() || + back().getDesc().isPredicable(); + + // If there is no branch, control always falls through. + if (TBB == 0) return true; + + // If there is some explicit branch to the fallthrough block, it can obviously + // reach, even though the branch should get folded to fall through implicitly. + if (MachineFunction::iterator(TBB) == Fallthrough || + MachineFunction::iterator(FBB) == Fallthrough) + return true; + + // If it's an unconditional branch to some block not the fall through, it + // doesn't fall through. + if (Cond.empty()) return false; + + // Otherwise, if it is conditional and has no explicit false block, it falls + // through. + return FBB == 0; +} + +/// removeFromParent - This method unlinks 'this' from the containing function, +/// and returns it, but does not delete it. +MachineBasicBlock *MachineBasicBlock::removeFromParent() { + assert(getParent() && "Not embedded in a function!"); + getParent()->remove(this); + return this; +} + + +/// eraseFromParent - This method unlinks 'this' from the containing function, +/// and deletes it. +void MachineBasicBlock::eraseFromParent() { + assert(getParent() && "Not embedded in a function!"); + getParent()->erase(this); +} + + +/// ReplaceUsesOfBlockWith - Given a machine basic block that branched to +/// 'Old', change the code and CFG so that it branches to 'New' instead. +void MachineBasicBlock::ReplaceUsesOfBlockWith(MachineBasicBlock *Old, + MachineBasicBlock *New) { + assert(Old != New && "Cannot replace self with self!"); + + MachineBasicBlock::iterator I = end(); + while (I != begin()) { + --I; + if (!I->getDesc().isTerminator()) break; + + // Scan the operands of this machine instruction, replacing any uses of Old + // with New. + for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i) + if (I->getOperand(i).isMBB() && + I->getOperand(i).getMBB() == Old) + I->getOperand(i).setMBB(New); + } + + // Update the successor information. + removeSuccessor(Old); + addSuccessor(New); +} + +/// CorrectExtraCFGEdges - Various pieces of code can cause excess edges in the +/// CFG to be inserted. If we have proven that MBB can only branch to DestA and +/// DestB, remove any other MBB successors from the CFG. DestA and DestB can +/// be null. +/// Besides DestA and DestB, retain other edges leading to LandingPads +/// (currently there can be only one; we don't check or require that here). +/// Note it is possible that DestA and/or DestB are LandingPads. +bool MachineBasicBlock::CorrectExtraCFGEdges(MachineBasicBlock *DestA, + MachineBasicBlock *DestB, + bool isCond) { + bool MadeChange = false; + bool AddedFallThrough = false; + + MachineFunction::iterator FallThru = next(MachineFunction::iterator(this)); + + // If this block ends with a conditional branch that falls through to its + // successor, set DestB as the successor. + if (isCond) { + if (DestB == 0 && FallThru != getParent()->end()) { + DestB = FallThru; + AddedFallThrough = true; + } + } else { + // If this is an unconditional branch with no explicit dest, it must just be + // a fallthrough into DestB. + if (DestA == 0 && FallThru != getParent()->end()) { + DestA = FallThru; + AddedFallThrough = true; + } + } + + MachineBasicBlock::succ_iterator SI = succ_begin(); + MachineBasicBlock *OrigDestA = DestA, *OrigDestB = DestB; + while (SI != succ_end()) { + if (*SI == DestA) { + DestA = 0; + ++SI; + } else if (*SI == DestB) { + DestB = 0; + ++SI; + } else if ((*SI)->isLandingPad() && + *SI!=OrigDestA && *SI!=OrigDestB) { + ++SI; + } else { + // Otherwise, this is a superfluous edge, remove it. + SI = removeSuccessor(SI); + MadeChange = true; + } + } + if (!AddedFallThrough) { + assert(DestA == 0 && DestB == 0 && + "MachineCFG is missing edges!"); + } else if (isCond) { + assert(DestA == 0 && "MachineCFG is missing edges!"); + } + return MadeChange; +} + +void llvm::WriteAsOperand(raw_ostream &OS, const MachineBasicBlock *MBB, + bool t) { + OS << "BB#" << MBB->getNumber(); +} diff --git a/libclamav/c++/llvm/lib/CodeGen/MachineDominators.cpp b/libclamav/c++/llvm/lib/CodeGen/MachineDominators.cpp new file mode 100644 index 000000000..0f796f395 --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/MachineDominators.cpp @@ -0,0 +1,57 @@ +//===- MachineDominators.cpp - Machine Dominator Calculation --------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements simple dominator construction algorithms for finding +// forward dominators on machine functions. +// +//===----------------------------------------------------------------------===// + +#include "llvm/CodeGen/MachineDominators.h" +#include "llvm/CodeGen/Passes.h" + +using namespace llvm; + +TEMPLATE_INSTANTIATION(class DomTreeNodeBase); +TEMPLATE_INSTANTIATION(class DominatorTreeBase); + +char MachineDominatorTree::ID = 0; + +static RegisterPass +E("machinedomtree", "MachineDominator Tree Construction", true); + +const PassInfo *const llvm::MachineDominatorsID = &E; + +void MachineDominatorTree::getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + MachineFunctionPass::getAnalysisUsage(AU); +} + +bool MachineDominatorTree::runOnMachineFunction(MachineFunction &F) { + DT->recalculate(F); + + return false; +} + +MachineDominatorTree::MachineDominatorTree() + : MachineFunctionPass(&ID) { + DT = new DominatorTreeBase(false); +} + +MachineDominatorTree::~MachineDominatorTree() { + DT->releaseMemory(); + delete DT; +} + +void MachineDominatorTree::releaseMemory() { + DT->releaseMemory(); +} + +void MachineDominatorTree::print(raw_ostream &OS, const Module*) const { + DT->print(OS); +} diff --git a/libclamav/c++/llvm/lib/CodeGen/MachineFunction.cpp b/libclamav/c++/llvm/lib/CodeGen/MachineFunction.cpp new file mode 100644 index 000000000..81d130133 --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/MachineFunction.cpp @@ -0,0 +1,703 @@ +//===-- MachineFunction.cpp -----------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Collect native machine code information for a function. This allows +// target-specific information about the generated code to be stored with each +// function. +// +//===----------------------------------------------------------------------===// + +#include "llvm/DerivedTypes.h" +#include "llvm/Function.h" +#include "llvm/Instructions.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/Config/config.h" +#include "llvm/CodeGen/MachineConstantPool.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/CodeGen/MachineJumpTableInfo.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetLowering.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetFrameInfo.h" +#include "llvm/Support/GraphWriter.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +namespace { + struct Printer : public MachineFunctionPass { + static char ID; + + raw_ostream &OS; + const std::string Banner; + + Printer(raw_ostream &os, const std::string &banner) + : MachineFunctionPass(&ID), OS(os), Banner(banner) {} + + const char *getPassName() const { return "MachineFunction Printer"; } + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + MachineFunctionPass::getAnalysisUsage(AU); + } + + bool runOnMachineFunction(MachineFunction &MF) { + OS << "# " << Banner << ":\n"; + MF.print(OS); + return false; + } + }; + char Printer::ID = 0; +} + +/// Returns a newly-created MachineFunction Printer pass. The default banner is +/// empty. +/// +FunctionPass *llvm::createMachineFunctionPrinterPass(raw_ostream &OS, + const std::string &Banner){ + return new Printer(OS, Banner); +} + +//===---------------------------------------------------------------------===// +// MachineFunction implementation +//===---------------------------------------------------------------------===// + +// Out of line virtual method. +MachineFunctionInfo::~MachineFunctionInfo() {} + +void ilist_traits::deleteNode(MachineBasicBlock *MBB) { + MBB->getParent()->DeleteMachineBasicBlock(MBB); +} + +MachineFunction::MachineFunction(Function *F, + const TargetMachine &TM) + : Fn(F), Target(TM) { + if (TM.getRegisterInfo()) + RegInfo = new (Allocator.Allocate()) + MachineRegisterInfo(*TM.getRegisterInfo()); + else + RegInfo = 0; + MFInfo = 0; + FrameInfo = new (Allocator.Allocate()) + MachineFrameInfo(*TM.getFrameInfo()); + ConstantPool = new (Allocator.Allocate()) + MachineConstantPool(TM.getTargetData()); + Alignment = TM.getTargetLowering()->getFunctionAlignment(F); + + // Set up jump table. + const TargetData &TD = *TM.getTargetData(); + bool IsPic = TM.getRelocationModel() == Reloc::PIC_; + unsigned EntrySize = IsPic ? 4 : TD.getPointerSize(); + unsigned TyAlignment = IsPic ? + TD.getABITypeAlignment(Type::getInt32Ty(F->getContext())) + : TD.getPointerABIAlignment(); + JumpTableInfo = new (Allocator.Allocate()) + MachineJumpTableInfo(EntrySize, TyAlignment); +} + +MachineFunction::~MachineFunction() { + BasicBlocks.clear(); + InstructionRecycler.clear(Allocator); + BasicBlockRecycler.clear(Allocator); + if (RegInfo) { + RegInfo->~MachineRegisterInfo(); + Allocator.Deallocate(RegInfo); + } + if (MFInfo) { + MFInfo->~MachineFunctionInfo(); + Allocator.Deallocate(MFInfo); + } + FrameInfo->~MachineFrameInfo(); Allocator.Deallocate(FrameInfo); + ConstantPool->~MachineConstantPool(); Allocator.Deallocate(ConstantPool); + JumpTableInfo->~MachineJumpTableInfo(); Allocator.Deallocate(JumpTableInfo); +} + + +/// RenumberBlocks - This discards all of the MachineBasicBlock numbers and +/// recomputes them. This guarantees that the MBB numbers are sequential, +/// dense, and match the ordering of the blocks within the function. If a +/// specific MachineBasicBlock is specified, only that block and those after +/// it are renumbered. +void MachineFunction::RenumberBlocks(MachineBasicBlock *MBB) { + if (empty()) { MBBNumbering.clear(); return; } + MachineFunction::iterator MBBI, E = end(); + if (MBB == 0) + MBBI = begin(); + else + MBBI = MBB; + + // Figure out the block number this should have. + unsigned BlockNo = 0; + if (MBBI != begin()) + BlockNo = prior(MBBI)->getNumber()+1; + + for (; MBBI != E; ++MBBI, ++BlockNo) { + if (MBBI->getNumber() != (int)BlockNo) { + // Remove use of the old number. + if (MBBI->getNumber() != -1) { + assert(MBBNumbering[MBBI->getNumber()] == &*MBBI && + "MBB number mismatch!"); + MBBNumbering[MBBI->getNumber()] = 0; + } + + // If BlockNo is already taken, set that block's number to -1. + if (MBBNumbering[BlockNo]) + MBBNumbering[BlockNo]->setNumber(-1); + + MBBNumbering[BlockNo] = MBBI; + MBBI->setNumber(BlockNo); + } + } + + // Okay, all the blocks are renumbered. If we have compactified the block + // numbering, shrink MBBNumbering now. + assert(BlockNo <= MBBNumbering.size() && "Mismatch!"); + MBBNumbering.resize(BlockNo); +} + +/// CreateMachineInstr - Allocate a new MachineInstr. Use this instead +/// of `new MachineInstr'. +/// +MachineInstr * +MachineFunction::CreateMachineInstr(const TargetInstrDesc &TID, + DebugLoc DL, bool NoImp) { + return new (InstructionRecycler.Allocate(Allocator)) + MachineInstr(TID, DL, NoImp); +} + +/// CloneMachineInstr - Create a new MachineInstr which is a copy of the +/// 'Orig' instruction, identical in all ways except the the instruction +/// has no parent, prev, or next. +/// +MachineInstr * +MachineFunction::CloneMachineInstr(const MachineInstr *Orig) { + return new (InstructionRecycler.Allocate(Allocator)) + MachineInstr(*this, *Orig); +} + +/// DeleteMachineInstr - Delete the given MachineInstr. +/// +void +MachineFunction::DeleteMachineInstr(MachineInstr *MI) { + MI->~MachineInstr(); + InstructionRecycler.Deallocate(Allocator, MI); +} + +/// CreateMachineBasicBlock - Allocate a new MachineBasicBlock. Use this +/// instead of `new MachineBasicBlock'. +/// +MachineBasicBlock * +MachineFunction::CreateMachineBasicBlock(const BasicBlock *bb) { + return new (BasicBlockRecycler.Allocate(Allocator)) + MachineBasicBlock(*this, bb); +} + +/// DeleteMachineBasicBlock - Delete the given MachineBasicBlock. +/// +void +MachineFunction::DeleteMachineBasicBlock(MachineBasicBlock *MBB) { + assert(MBB->getParent() == this && "MBB parent mismatch!"); + MBB->~MachineBasicBlock(); + BasicBlockRecycler.Deallocate(Allocator, MBB); +} + +MachineMemOperand * +MachineFunction::getMachineMemOperand(const Value *v, unsigned f, + int64_t o, uint64_t s, + unsigned base_alignment) { + return new (Allocator.Allocate()) + MachineMemOperand(v, f, o, s, base_alignment); +} + +MachineMemOperand * +MachineFunction::getMachineMemOperand(const MachineMemOperand *MMO, + int64_t Offset, uint64_t Size) { + return new (Allocator.Allocate()) + MachineMemOperand(MMO->getValue(), MMO->getFlags(), + int64_t(uint64_t(MMO->getOffset()) + + uint64_t(Offset)), + Size, MMO->getBaseAlignment()); +} + +MachineInstr::mmo_iterator +MachineFunction::allocateMemRefsArray(unsigned long Num) { + return Allocator.Allocate(Num); +} + +std::pair +MachineFunction::extractLoadMemRefs(MachineInstr::mmo_iterator Begin, + MachineInstr::mmo_iterator End) { + // Count the number of load mem refs. + unsigned Num = 0; + for (MachineInstr::mmo_iterator I = Begin; I != End; ++I) + if ((*I)->isLoad()) + ++Num; + + // Allocate a new array and populate it with the load information. + MachineInstr::mmo_iterator Result = allocateMemRefsArray(Num); + unsigned Index = 0; + for (MachineInstr::mmo_iterator I = Begin; I != End; ++I) { + if ((*I)->isLoad()) { + if (!(*I)->isStore()) + // Reuse the MMO. + Result[Index] = *I; + else { + // Clone the MMO and unset the store flag. + MachineMemOperand *JustLoad = + getMachineMemOperand((*I)->getValue(), + (*I)->getFlags() & ~MachineMemOperand::MOStore, + (*I)->getOffset(), (*I)->getSize(), + (*I)->getBaseAlignment()); + Result[Index] = JustLoad; + } + ++Index; + } + } + return std::make_pair(Result, Result + Num); +} + +std::pair +MachineFunction::extractStoreMemRefs(MachineInstr::mmo_iterator Begin, + MachineInstr::mmo_iterator End) { + // Count the number of load mem refs. + unsigned Num = 0; + for (MachineInstr::mmo_iterator I = Begin; I != End; ++I) + if ((*I)->isStore()) + ++Num; + + // Allocate a new array and populate it with the store information. + MachineInstr::mmo_iterator Result = allocateMemRefsArray(Num); + unsigned Index = 0; + for (MachineInstr::mmo_iterator I = Begin; I != End; ++I) { + if ((*I)->isStore()) { + if (!(*I)->isLoad()) + // Reuse the MMO. + Result[Index] = *I; + else { + // Clone the MMO and unset the load flag. + MachineMemOperand *JustStore = + getMachineMemOperand((*I)->getValue(), + (*I)->getFlags() & ~MachineMemOperand::MOLoad, + (*I)->getOffset(), (*I)->getSize(), + (*I)->getBaseAlignment()); + Result[Index] = JustStore; + } + ++Index; + } + } + return std::make_pair(Result, Result + Num); +} + +void MachineFunction::dump() const { + print(errs()); +} + +void MachineFunction::print(raw_ostream &OS) const { + OS << "# Machine code for function " << Fn->getName() << ":\n"; + + // Print Frame Information + FrameInfo->print(*this, OS); + + // Print JumpTable Information + JumpTableInfo->print(OS); + + // Print Constant Pool + ConstantPool->print(OS); + + const TargetRegisterInfo *TRI = getTarget().getRegisterInfo(); + + if (RegInfo && !RegInfo->livein_empty()) { + OS << "Function Live Ins: "; + for (MachineRegisterInfo::livein_iterator + I = RegInfo->livein_begin(), E = RegInfo->livein_end(); I != E; ++I) { + if (TRI) + OS << "%" << TRI->getName(I->first); + else + OS << " %physreg" << I->first; + + if (I->second) + OS << " in reg%" << I->second; + + if (next(I) != E) + OS << ", "; + } + OS << '\n'; + } + if (RegInfo && !RegInfo->liveout_empty()) { + OS << "Function Live Outs: "; + for (MachineRegisterInfo::liveout_iterator + I = RegInfo->liveout_begin(), E = RegInfo->liveout_end(); I != E; ++I){ + if (TRI) + OS << '%' << TRI->getName(*I); + else + OS << "%physreg" << *I; + + if (next(I) != E) + OS << " "; + } + OS << '\n'; + } + + for (const_iterator BB = begin(), E = end(); BB != E; ++BB) { + OS << '\n'; + BB->print(OS); + } + + OS << "\n# End machine code for function " << Fn->getName() << ".\n\n"; +} + +namespace llvm { + template<> + struct DOTGraphTraits : public DefaultDOTGraphTraits { + static std::string getGraphName(const MachineFunction *F) { + return "CFG for '" + F->getFunction()->getNameStr() + "' function"; + } + + static std::string getNodeLabel(const MachineBasicBlock *Node, + const MachineFunction *Graph, + bool ShortNames) { + if (ShortNames && Node->getBasicBlock() && + !Node->getBasicBlock()->getName().empty()) + return Node->getBasicBlock()->getNameStr() + ":"; + + std::string OutStr; + { + raw_string_ostream OSS(OutStr); + + if (ShortNames) + OSS << Node->getNumber() << ':'; + else + Node->print(OSS); + } + + if (OutStr[0] == '\n') OutStr.erase(OutStr.begin()); + + // Process string output to make it nicer... + for (unsigned i = 0; i != OutStr.length(); ++i) + if (OutStr[i] == '\n') { // Left justify + OutStr[i] = '\\'; + OutStr.insert(OutStr.begin()+i+1, 'l'); + } + return OutStr; + } + }; +} + +void MachineFunction::viewCFG() const +{ +#ifndef NDEBUG + ViewGraph(this, "mf" + getFunction()->getNameStr()); +#else + errs() << "SelectionDAG::viewGraph is only available in debug builds on " + << "systems with Graphviz or gv!\n"; +#endif // NDEBUG +} + +void MachineFunction::viewCFGOnly() const +{ +#ifndef NDEBUG + ViewGraph(this, "mf" + getFunction()->getNameStr(), true); +#else + errs() << "SelectionDAG::viewGraph is only available in debug builds on " + << "systems with Graphviz or gv!\n"; +#endif // NDEBUG +} + +/// addLiveIn - Add the specified physical register as a live-in value and +/// create a corresponding virtual register for it. +unsigned MachineFunction::addLiveIn(unsigned PReg, + const TargetRegisterClass *RC) { + assert(RC->contains(PReg) && "Not the correct regclass!"); + unsigned VReg = getRegInfo().createVirtualRegister(RC); + getRegInfo().addLiveIn(PReg, VReg); + return VReg; +} + +/// getDebugLocTuple - Get the DebugLocTuple for a given DebugLoc object. +DebugLocTuple MachineFunction::getDebugLocTuple(DebugLoc DL) const { + unsigned Idx = DL.getIndex(); + assert(Idx < DebugLocInfo.DebugLocations.size() && + "Invalid index into debug locations!"); + return DebugLocInfo.DebugLocations[Idx]; +} + +//===----------------------------------------------------------------------===// +// MachineFrameInfo implementation +//===----------------------------------------------------------------------===// + +/// CreateFixedObject - Create a new object at a fixed location on the stack. +/// All fixed objects should be created before other objects are created for +/// efficiency. By default, fixed objects are immutable. This returns an +/// index with a negative value. +/// +int MachineFrameInfo::CreateFixedObject(uint64_t Size, int64_t SPOffset, + bool Immutable, bool isSS) { + assert(Size != 0 && "Cannot allocate zero size fixed stack objects!"); + Objects.insert(Objects.begin(), StackObject(Size, 1, SPOffset, Immutable, + isSS)); + return -++NumFixedObjects; +} + + +BitVector +MachineFrameInfo::getPristineRegs(const MachineBasicBlock *MBB) const { + assert(MBB && "MBB must be valid"); + const MachineFunction *MF = MBB->getParent(); + assert(MF && "MBB must be part of a MachineFunction"); + const TargetMachine &TM = MF->getTarget(); + const TargetRegisterInfo *TRI = TM.getRegisterInfo(); + BitVector BV(TRI->getNumRegs()); + + // Before CSI is calculated, no registers are considered pristine. They can be + // freely used and PEI will make sure they are saved. + if (!isCalleeSavedInfoValid()) + return BV; + + for (const unsigned *CSR = TRI->getCalleeSavedRegs(MF); CSR && *CSR; ++CSR) + BV.set(*CSR); + + // The entry MBB always has all CSRs pristine. + if (MBB == &MF->front()) + return BV; + + // On other MBBs the saved CSRs are not pristine. + const std::vector &CSI = getCalleeSavedInfo(); + for (std::vector::const_iterator I = CSI.begin(), + E = CSI.end(); I != E; ++I) + BV.reset(I->getReg()); + + return BV; +} + + +void MachineFrameInfo::print(const MachineFunction &MF, raw_ostream &OS) const{ + if (Objects.empty()) return; + + const TargetFrameInfo *FI = MF.getTarget().getFrameInfo(); + int ValOffset = (FI ? FI->getOffsetOfLocalArea() : 0); + + OS << "Frame Objects:\n"; + + for (unsigned i = 0, e = Objects.size(); i != e; ++i) { + const StackObject &SO = Objects[i]; + OS << " fi#" << (int)(i-NumFixedObjects) << ": "; + if (SO.Size == ~0ULL) { + OS << "dead\n"; + continue; + } + if (SO.Size == 0) + OS << "variable sized"; + else + OS << "size=" << SO.Size; + OS << ", align=" << SO.Alignment; + + if (i < NumFixedObjects) + OS << ", fixed"; + if (i < NumFixedObjects || SO.SPOffset != -1) { + int64_t Off = SO.SPOffset - ValOffset; + OS << ", at location [SP"; + if (Off > 0) + OS << "+" << Off; + else if (Off < 0) + OS << Off; + OS << "]"; + } + OS << "\n"; + } +} + +void MachineFrameInfo::dump(const MachineFunction &MF) const { + print(MF, errs()); +} + +//===----------------------------------------------------------------------===// +// MachineJumpTableInfo implementation +//===----------------------------------------------------------------------===// + +/// getJumpTableIndex - Create a new jump table entry in the jump table info +/// or return an existing one. +/// +unsigned MachineJumpTableInfo::getJumpTableIndex( + const std::vector &DestBBs) { + assert(!DestBBs.empty() && "Cannot create an empty jump table!"); + JumpTables.push_back(MachineJumpTableEntry(DestBBs)); + return JumpTables.size()-1; +} + +/// ReplaceMBBInJumpTables - If Old is the target of any jump tables, update +/// the jump tables to branch to New instead. +bool +MachineJumpTableInfo::ReplaceMBBInJumpTables(MachineBasicBlock *Old, + MachineBasicBlock *New) { + assert(Old != New && "Not making a change?"); + bool MadeChange = false; + for (size_t i = 0, e = JumpTables.size(); i != e; ++i) + ReplaceMBBInJumpTable(i, Old, New); + return MadeChange; +} + +/// ReplaceMBBInJumpTable - If Old is a target of the jump tables, update +/// the jump table to branch to New instead. +bool +MachineJumpTableInfo::ReplaceMBBInJumpTable(unsigned Idx, + MachineBasicBlock *Old, + MachineBasicBlock *New) { + assert(Old != New && "Not making a change?"); + bool MadeChange = false; + MachineJumpTableEntry &JTE = JumpTables[Idx]; + for (size_t j = 0, e = JTE.MBBs.size(); j != e; ++j) + if (JTE.MBBs[j] == Old) { + JTE.MBBs[j] = New; + MadeChange = true; + } + return MadeChange; +} + +void MachineJumpTableInfo::print(raw_ostream &OS) const { + if (JumpTables.empty()) return; + + OS << "Jump Tables:\n"; + + for (unsigned i = 0, e = JumpTables.size(); i != e; ++i) { + OS << " jt#" << i << ": "; + for (unsigned j = 0, f = JumpTables[i].MBBs.size(); j != f; ++j) + OS << " BB#" << JumpTables[i].MBBs[j]->getNumber(); + } + + OS << '\n'; +} + +void MachineJumpTableInfo::dump() const { print(errs()); } + + +//===----------------------------------------------------------------------===// +// MachineConstantPool implementation +//===----------------------------------------------------------------------===// + +const Type *MachineConstantPoolEntry::getType() const { + if (isMachineConstantPoolEntry()) + return Val.MachineCPVal->getType(); + return Val.ConstVal->getType(); +} + + +unsigned MachineConstantPoolEntry::getRelocationInfo() const { + if (isMachineConstantPoolEntry()) + return Val.MachineCPVal->getRelocationInfo(); + return Val.ConstVal->getRelocationInfo(); +} + +MachineConstantPool::~MachineConstantPool() { + for (unsigned i = 0, e = Constants.size(); i != e; ++i) + if (Constants[i].isMachineConstantPoolEntry()) + delete Constants[i].Val.MachineCPVal; +} + +/// CanShareConstantPoolEntry - Test whether the given two constants +/// can be allocated the same constant pool entry. +static bool CanShareConstantPoolEntry(Constant *A, Constant *B, + const TargetData *TD) { + // Handle the trivial case quickly. + if (A == B) return true; + + // If they have the same type but weren't the same constant, quickly + // reject them. + if (A->getType() == B->getType()) return false; + + // For now, only support constants with the same size. + if (TD->getTypeStoreSize(A->getType()) != TD->getTypeStoreSize(B->getType())) + return false; + + // If a floating-point value and an integer value have the same encoding, + // they can share a constant-pool entry. + if (ConstantFP *AFP = dyn_cast(A)) + if (ConstantInt *BI = dyn_cast(B)) + return AFP->getValueAPF().bitcastToAPInt() == BI->getValue(); + if (ConstantFP *BFP = dyn_cast(B)) + if (ConstantInt *AI = dyn_cast(A)) + return BFP->getValueAPF().bitcastToAPInt() == AI->getValue(); + + // Two vectors can share an entry if each pair of corresponding + // elements could. + if (ConstantVector *AV = dyn_cast(A)) + if (ConstantVector *BV = dyn_cast(B)) { + if (AV->getType()->getNumElements() != BV->getType()->getNumElements()) + return false; + for (unsigned i = 0, e = AV->getType()->getNumElements(); i != e; ++i) + if (!CanShareConstantPoolEntry(AV->getOperand(i), + BV->getOperand(i), TD)) + return false; + return true; + } + + // TODO: Handle other cases. + + return false; +} + +/// getConstantPoolIndex - Create a new entry in the constant pool or return +/// an existing one. User must specify the log2 of the minimum required +/// alignment for the object. +/// +unsigned MachineConstantPool::getConstantPoolIndex(Constant *C, + unsigned Alignment) { + assert(Alignment && "Alignment must be specified!"); + if (Alignment > PoolAlignment) PoolAlignment = Alignment; + + // Check to see if we already have this constant. + // + // FIXME, this could be made much more efficient for large constant pools. + for (unsigned i = 0, e = Constants.size(); i != e; ++i) + if (!Constants[i].isMachineConstantPoolEntry() && + CanShareConstantPoolEntry(Constants[i].Val.ConstVal, C, TD)) { + if ((unsigned)Constants[i].getAlignment() < Alignment) + Constants[i].Alignment = Alignment; + return i; + } + + Constants.push_back(MachineConstantPoolEntry(C, Alignment)); + return Constants.size()-1; +} + +unsigned MachineConstantPool::getConstantPoolIndex(MachineConstantPoolValue *V, + unsigned Alignment) { + assert(Alignment && "Alignment must be specified!"); + if (Alignment > PoolAlignment) PoolAlignment = Alignment; + + // Check to see if we already have this constant. + // + // FIXME, this could be made much more efficient for large constant pools. + int Idx = V->getExistingMachineCPValue(this, Alignment); + if (Idx != -1) + return (unsigned)Idx; + + Constants.push_back(MachineConstantPoolEntry(V, Alignment)); + return Constants.size()-1; +} + +void MachineConstantPool::print(raw_ostream &OS) const { + if (Constants.empty()) return; + + OS << "Constant Pool:\n"; + for (unsigned i = 0, e = Constants.size(); i != e; ++i) { + OS << " cp#" << i << ": "; + if (Constants[i].isMachineConstantPoolEntry()) + Constants[i].Val.MachineCPVal->print(OS); + else + OS << *(Value*)Constants[i].Val.ConstVal; + OS << ", align=" << Constants[i].getAlignment(); + OS << "\n"; + } +} + +void MachineConstantPool::dump() const { print(errs()); } diff --git a/libclamav/c++/llvm/lib/CodeGen/MachineFunctionAnalysis.cpp b/libclamav/c++/llvm/lib/CodeGen/MachineFunctionAnalysis.cpp new file mode 100644 index 000000000..f5febc5a4 --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/MachineFunctionAnalysis.cpp @@ -0,0 +1,50 @@ +//===-- MachineFunctionAnalysis.cpp ---------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the definitions of the MachineFunctionAnalysis members. +// +//===----------------------------------------------------------------------===// + +#include "llvm/CodeGen/MachineFunctionAnalysis.h" +#include "llvm/CodeGen/MachineFunction.h" +using namespace llvm; + +// Register this pass with PassInfo directly to avoid having to define +// a default constructor. +static PassInfo +X("Machine Function Analysis", "machine-function-analysis", + intptr_t(&MachineFunctionAnalysis::ID), 0, + /*CFGOnly=*/false, /*is_analysis=*/true); + +char MachineFunctionAnalysis::ID = 0; + +MachineFunctionAnalysis::MachineFunctionAnalysis(const TargetMachine &tm, + CodeGenOpt::Level OL) : + FunctionPass(&ID), TM(tm), OptLevel(OL), MF(0) { +} + +MachineFunctionAnalysis::~MachineFunctionAnalysis() { + releaseMemory(); + assert(!MF && "MachineFunctionAnalysis left initialized!"); +} + +bool MachineFunctionAnalysis::runOnFunction(Function &F) { + assert(!MF && "MachineFunctionAnalysis already initialized!"); + MF = new MachineFunction(&F, TM); + return false; +} + +void MachineFunctionAnalysis::releaseMemory() { + delete MF; + MF = 0; +} + +void MachineFunctionAnalysis::getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); +} diff --git a/libclamav/c++/llvm/lib/CodeGen/MachineFunctionPass.cpp b/libclamav/c++/llvm/lib/CodeGen/MachineFunctionPass.cpp new file mode 100644 index 000000000..2f8d4c9e7 --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/MachineFunctionPass.cpp @@ -0,0 +1,50 @@ +//===-- MachineFunctionPass.cpp -------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the definitions of the MachineFunctionPass members. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Function.h" +#include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/CodeGen/MachineFunctionAnalysis.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +using namespace llvm; + +bool MachineFunctionPass::runOnFunction(Function &F) { + // Do not codegen any 'available_externally' functions at all, they have + // definitions outside the translation unit. + if (F.hasAvailableExternallyLinkage()) + return false; + + MachineFunction &MF = getAnalysis().getMF(); + return runOnMachineFunction(MF); +} + +void MachineFunctionPass::getAnalysisUsage(AnalysisUsage &AU) const { + AU.addRequired(); + AU.addPreserved(); + + // MachineFunctionPass preserves all LLVM IR passes, but there's no + // high-level way to express this. Instead, just list a bunch of + // passes explicitly. This does not include setPreservesCFG, + // because CodeGen overloads that to mean preserving the MachineBasicBlock + // CFG in addition to the LLVM IR CFG. + AU.addPreserved(); + AU.addPreserved("scalar-evolution"); + AU.addPreserved("iv-users"); + AU.addPreserved("memdep"); + AU.addPreserved("live-values"); + AU.addPreserved("domtree"); + AU.addPreserved("domfrontier"); + AU.addPreserved("loops"); + AU.addPreserved("lda"); + + FunctionPass::getAnalysisUsage(AU); +} diff --git a/libclamav/c++/llvm/lib/CodeGen/MachineInstr.cpp b/libclamav/c++/llvm/lib/CodeGen/MachineInstr.cpp new file mode 100644 index 000000000..f11026fde --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/MachineInstr.cpp @@ -0,0 +1,1275 @@ +//===-- lib/CodeGen/MachineInstr.cpp --------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Methods common to all machine instructions. +// +//===----------------------------------------------------------------------===// + +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/Constants.h" +#include "llvm/Function.h" +#include "llvm/InlineAsm.h" +#include "llvm/Value.h" +#include "llvm/Assembly/Writer.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineMemOperand.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/PseudoSourceValue.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetInstrDesc.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/Analysis/DebugInfo.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/LeakDetector.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/ADT/FoldingSet.h" +using namespace llvm; + +//===----------------------------------------------------------------------===// +// MachineOperand Implementation +//===----------------------------------------------------------------------===// + +/// AddRegOperandToRegInfo - Add this register operand to the specified +/// MachineRegisterInfo. If it is null, then the next/prev fields should be +/// explicitly nulled out. +void MachineOperand::AddRegOperandToRegInfo(MachineRegisterInfo *RegInfo) { + assert(isReg() && "Can only add reg operand to use lists"); + + // If the reginfo pointer is null, just explicitly null out or next/prev + // pointers, to ensure they are not garbage. + if (RegInfo == 0) { + Contents.Reg.Prev = 0; + Contents.Reg.Next = 0; + return; + } + + // Otherwise, add this operand to the head of the registers use/def list. + MachineOperand **Head = &RegInfo->getRegUseDefListHead(getReg()); + + // For SSA values, we prefer to keep the definition at the start of the list. + // we do this by skipping over the definition if it is at the head of the + // list. + if (*Head && (*Head)->isDef()) + Head = &(*Head)->Contents.Reg.Next; + + Contents.Reg.Next = *Head; + if (Contents.Reg.Next) { + assert(getReg() == Contents.Reg.Next->getReg() && + "Different regs on the same list!"); + Contents.Reg.Next->Contents.Reg.Prev = &Contents.Reg.Next; + } + + Contents.Reg.Prev = Head; + *Head = this; +} + +/// RemoveRegOperandFromRegInfo - Remove this register operand from the +/// MachineRegisterInfo it is linked with. +void MachineOperand::RemoveRegOperandFromRegInfo() { + assert(isOnRegUseList() && "Reg operand is not on a use list"); + // Unlink this from the doubly linked list of operands. + MachineOperand *NextOp = Contents.Reg.Next; + *Contents.Reg.Prev = NextOp; + if (NextOp) { + assert(NextOp->getReg() == getReg() && "Corrupt reg use/def chain!"); + NextOp->Contents.Reg.Prev = Contents.Reg.Prev; + } + Contents.Reg.Prev = 0; + Contents.Reg.Next = 0; +} + +void MachineOperand::setReg(unsigned Reg) { + if (getReg() == Reg) return; // No change. + + // Otherwise, we have to change the register. If this operand is embedded + // into a machine function, we need to update the old and new register's + // use/def lists. + if (MachineInstr *MI = getParent()) + if (MachineBasicBlock *MBB = MI->getParent()) + if (MachineFunction *MF = MBB->getParent()) { + RemoveRegOperandFromRegInfo(); + Contents.Reg.RegNo = Reg; + AddRegOperandToRegInfo(&MF->getRegInfo()); + return; + } + + // Otherwise, just change the register, no problem. :) + Contents.Reg.RegNo = Reg; +} + +/// ChangeToImmediate - Replace this operand with a new immediate operand of +/// the specified value. If an operand is known to be an immediate already, +/// the setImm method should be used. +void MachineOperand::ChangeToImmediate(int64_t ImmVal) { + // If this operand is currently a register operand, and if this is in a + // function, deregister the operand from the register's use/def list. + if (isReg() && getParent() && getParent()->getParent() && + getParent()->getParent()->getParent()) + RemoveRegOperandFromRegInfo(); + + OpKind = MO_Immediate; + Contents.ImmVal = ImmVal; +} + +/// ChangeToRegister - Replace this operand with a new register operand of +/// the specified value. If an operand is known to be an register already, +/// the setReg method should be used. +void MachineOperand::ChangeToRegister(unsigned Reg, bool isDef, bool isImp, + bool isKill, bool isDead, bool isUndef) { + // If this operand is already a register operand, use setReg to update the + // register's use/def lists. + if (isReg()) { + assert(!isEarlyClobber()); + setReg(Reg); + } else { + // Otherwise, change this to a register and set the reg#. + OpKind = MO_Register; + Contents.Reg.RegNo = Reg; + + // If this operand is embedded in a function, add the operand to the + // register's use/def list. + if (MachineInstr *MI = getParent()) + if (MachineBasicBlock *MBB = MI->getParent()) + if (MachineFunction *MF = MBB->getParent()) + AddRegOperandToRegInfo(&MF->getRegInfo()); + } + + IsDef = isDef; + IsImp = isImp; + IsKill = isKill; + IsDead = isDead; + IsUndef = isUndef; + IsEarlyClobber = false; + SubReg = 0; +} + +/// isIdenticalTo - Return true if this operand is identical to the specified +/// operand. +bool MachineOperand::isIdenticalTo(const MachineOperand &Other) const { + if (getType() != Other.getType() || + getTargetFlags() != Other.getTargetFlags()) + return false; + + switch (getType()) { + default: llvm_unreachable("Unrecognized operand type"); + case MachineOperand::MO_Register: + return getReg() == Other.getReg() && isDef() == Other.isDef() && + getSubReg() == Other.getSubReg(); + case MachineOperand::MO_Immediate: + return getImm() == Other.getImm(); + case MachineOperand::MO_FPImmediate: + return getFPImm() == Other.getFPImm(); + case MachineOperand::MO_MachineBasicBlock: + return getMBB() == Other.getMBB(); + case MachineOperand::MO_FrameIndex: + return getIndex() == Other.getIndex(); + case MachineOperand::MO_ConstantPoolIndex: + return getIndex() == Other.getIndex() && getOffset() == Other.getOffset(); + case MachineOperand::MO_JumpTableIndex: + return getIndex() == Other.getIndex(); + case MachineOperand::MO_GlobalAddress: + return getGlobal() == Other.getGlobal() && getOffset() == Other.getOffset(); + case MachineOperand::MO_ExternalSymbol: + return !strcmp(getSymbolName(), Other.getSymbolName()) && + getOffset() == Other.getOffset(); + case MachineOperand::MO_BlockAddress: + return getBlockAddress() == Other.getBlockAddress(); + } +} + +/// print - Print the specified machine operand. +/// +void MachineOperand::print(raw_ostream &OS, const TargetMachine *TM) const { + // If the instruction is embedded into a basic block, we can find the + // target info for the instruction. + if (!TM) + if (const MachineInstr *MI = getParent()) + if (const MachineBasicBlock *MBB = MI->getParent()) + if (const MachineFunction *MF = MBB->getParent()) + TM = &MF->getTarget(); + + switch (getType()) { + case MachineOperand::MO_Register: + if (getReg() == 0 || TargetRegisterInfo::isVirtualRegister(getReg())) { + OS << "%reg" << getReg(); + } else { + if (TM) + OS << "%" << TM->getRegisterInfo()->get(getReg()).Name; + else + OS << "%physreg" << getReg(); + } + + if (getSubReg() != 0) + OS << ':' << getSubReg(); + + if (isDef() || isKill() || isDead() || isImplicit() || isUndef() || + isEarlyClobber()) { + OS << '<'; + bool NeedComma = false; + if (isDef()) { + if (NeedComma) OS << ','; + if (isEarlyClobber()) + OS << "earlyclobber,"; + if (isImplicit()) + OS << "imp-"; + OS << "def"; + NeedComma = true; + } else if (isImplicit()) { + OS << "imp-use"; + NeedComma = true; + } + + if (isKill() || isDead() || isUndef()) { + if (NeedComma) OS << ','; + if (isKill()) OS << "kill"; + if (isDead()) OS << "dead"; + if (isUndef()) { + if (isKill() || isDead()) + OS << ','; + OS << "undef"; + } + } + OS << '>'; + } + break; + case MachineOperand::MO_Immediate: + OS << getImm(); + break; + case MachineOperand::MO_FPImmediate: + if (getFPImm()->getType()->isFloatTy()) + OS << getFPImm()->getValueAPF().convertToFloat(); + else + OS << getFPImm()->getValueAPF().convertToDouble(); + break; + case MachineOperand::MO_MachineBasicBlock: + OS << "getNumber() << ">"; + break; + case MachineOperand::MO_FrameIndex: + OS << "'; + break; + case MachineOperand::MO_ConstantPoolIndex: + OS << "'; + break; + case MachineOperand::MO_JumpTableIndex: + OS << "'; + break; + case MachineOperand::MO_GlobalAddress: + OS << "'; + break; + case MachineOperand::MO_ExternalSymbol: + OS << "'; + break; + case MachineOperand::MO_BlockAddress: + OS << "<"; + WriteAsOperand(OS, getBlockAddress(), /*PrintType=*/false); + OS << '>'; + break; + default: + llvm_unreachable("Unrecognized operand type"); + } + + if (unsigned TF = getTargetFlags()) + OS << "[TF=" << TF << ']'; +} + +//===----------------------------------------------------------------------===// +// MachineMemOperand Implementation +//===----------------------------------------------------------------------===// + +MachineMemOperand::MachineMemOperand(const Value *v, unsigned int f, + int64_t o, uint64_t s, unsigned int a) + : Offset(o), Size(s), V(v), + Flags((f & 7) | ((Log2_32(a) + 1) << 3)) { + assert(getBaseAlignment() == a && "Alignment is not a power of 2!"); + assert((isLoad() || isStore()) && "Not a load/store!"); +} + +/// Profile - Gather unique data for the object. +/// +void MachineMemOperand::Profile(FoldingSetNodeID &ID) const { + ID.AddInteger(Offset); + ID.AddInteger(Size); + ID.AddPointer(V); + ID.AddInteger(Flags); +} + +void MachineMemOperand::refineAlignment(const MachineMemOperand *MMO) { + // The Value and Offset may differ due to CSE. But the flags and size + // should be the same. + assert(MMO->getFlags() == getFlags() && "Flags mismatch!"); + assert(MMO->getSize() == getSize() && "Size mismatch!"); + + if (MMO->getBaseAlignment() >= getBaseAlignment()) { + // Update the alignment value. + Flags = (Flags & 7) | ((Log2_32(MMO->getBaseAlignment()) + 1) << 3); + // Also update the base and offset, because the new alignment may + // not be applicable with the old ones. + V = MMO->getValue(); + Offset = MMO->getOffset(); + } +} + +/// getAlignment - Return the minimum known alignment in bytes of the +/// actual memory reference. +uint64_t MachineMemOperand::getAlignment() const { + return MinAlign(getBaseAlignment(), getOffset()); +} + +raw_ostream &llvm::operator<<(raw_ostream &OS, const MachineMemOperand &MMO) { + assert((MMO.isLoad() || MMO.isStore()) && + "SV has to be a load, store or both."); + + if (MMO.isVolatile()) + OS << "Volatile "; + + if (MMO.isLoad()) + OS << "LD"; + if (MMO.isStore()) + OS << "ST"; + OS << MMO.getSize(); + + // Print the address information. + OS << "["; + if (!MMO.getValue()) + OS << ""; + else + WriteAsOperand(OS, MMO.getValue(), /*PrintType=*/false); + + // If the alignment of the memory reference itself differs from the alignment + // of the base pointer, print the base alignment explicitly, next to the base + // pointer. + if (MMO.getBaseAlignment() != MMO.getAlignment()) + OS << "(align=" << MMO.getBaseAlignment() << ")"; + + if (MMO.getOffset() != 0) + OS << "+" << MMO.getOffset(); + OS << "]"; + + // Print the alignment of the reference. + if (MMO.getBaseAlignment() != MMO.getAlignment() || + MMO.getBaseAlignment() != MMO.getSize()) + OS << "(align=" << MMO.getAlignment() << ")"; + + return OS; +} + +//===----------------------------------------------------------------------===// +// MachineInstr Implementation +//===----------------------------------------------------------------------===// + +/// MachineInstr ctor - This constructor creates a dummy MachineInstr with +/// TID NULL and no operands. +MachineInstr::MachineInstr() + : TID(0), NumImplicitOps(0), AsmPrinterFlags(0), MemRefs(0), MemRefsEnd(0), + Parent(0), debugLoc(DebugLoc::getUnknownLoc()) { + // Make sure that we get added to a machine basicblock + LeakDetector::addGarbageObject(this); +} + +void MachineInstr::addImplicitDefUseOperands() { + if (TID->ImplicitDefs) + for (const unsigned *ImpDefs = TID->ImplicitDefs; *ImpDefs; ++ImpDefs) + addOperand(MachineOperand::CreateReg(*ImpDefs, true, true)); + if (TID->ImplicitUses) + for (const unsigned *ImpUses = TID->ImplicitUses; *ImpUses; ++ImpUses) + addOperand(MachineOperand::CreateReg(*ImpUses, false, true)); +} + +/// MachineInstr ctor - This constructor create a MachineInstr and add the +/// implicit operands. It reserves space for number of operands specified by +/// TargetInstrDesc or the numOperands if it is not zero. (for +/// instructions with variable number of operands). +MachineInstr::MachineInstr(const TargetInstrDesc &tid, bool NoImp) + : TID(&tid), NumImplicitOps(0), AsmPrinterFlags(0), + MemRefs(0), MemRefsEnd(0), Parent(0), + debugLoc(DebugLoc::getUnknownLoc()) { + if (!NoImp && TID->getImplicitDefs()) + for (const unsigned *ImpDefs = TID->getImplicitDefs(); *ImpDefs; ++ImpDefs) + NumImplicitOps++; + if (!NoImp && TID->getImplicitUses()) + for (const unsigned *ImpUses = TID->getImplicitUses(); *ImpUses; ++ImpUses) + NumImplicitOps++; + Operands.reserve(NumImplicitOps + TID->getNumOperands()); + if (!NoImp) + addImplicitDefUseOperands(); + // Make sure that we get added to a machine basicblock + LeakDetector::addGarbageObject(this); +} + +/// MachineInstr ctor - As above, but with a DebugLoc. +MachineInstr::MachineInstr(const TargetInstrDesc &tid, const DebugLoc dl, + bool NoImp) + : TID(&tid), NumImplicitOps(0), AsmPrinterFlags(0), MemRefs(0), MemRefsEnd(0), + Parent(0), debugLoc(dl) { + if (!NoImp && TID->getImplicitDefs()) + for (const unsigned *ImpDefs = TID->getImplicitDefs(); *ImpDefs; ++ImpDefs) + NumImplicitOps++; + if (!NoImp && TID->getImplicitUses()) + for (const unsigned *ImpUses = TID->getImplicitUses(); *ImpUses; ++ImpUses) + NumImplicitOps++; + Operands.reserve(NumImplicitOps + TID->getNumOperands()); + if (!NoImp) + addImplicitDefUseOperands(); + // Make sure that we get added to a machine basicblock + LeakDetector::addGarbageObject(this); +} + +/// MachineInstr ctor - Work exactly the same as the ctor two above, except +/// that the MachineInstr is created and added to the end of the specified +/// basic block. +/// +MachineInstr::MachineInstr(MachineBasicBlock *MBB, const TargetInstrDesc &tid) + : TID(&tid), NumImplicitOps(0), AsmPrinterFlags(0), + MemRefs(0), MemRefsEnd(0), Parent(0), + debugLoc(DebugLoc::getUnknownLoc()) { + assert(MBB && "Cannot use inserting ctor with null basic block!"); + if (TID->ImplicitDefs) + for (const unsigned *ImpDefs = TID->getImplicitDefs(); *ImpDefs; ++ImpDefs) + NumImplicitOps++; + if (TID->ImplicitUses) + for (const unsigned *ImpUses = TID->getImplicitUses(); *ImpUses; ++ImpUses) + NumImplicitOps++; + Operands.reserve(NumImplicitOps + TID->getNumOperands()); + addImplicitDefUseOperands(); + // Make sure that we get added to a machine basicblock + LeakDetector::addGarbageObject(this); + MBB->push_back(this); // Add instruction to end of basic block! +} + +/// MachineInstr ctor - As above, but with a DebugLoc. +/// +MachineInstr::MachineInstr(MachineBasicBlock *MBB, const DebugLoc dl, + const TargetInstrDesc &tid) + : TID(&tid), NumImplicitOps(0), AsmPrinterFlags(0), MemRefs(0), MemRefsEnd(0), + Parent(0), debugLoc(dl) { + assert(MBB && "Cannot use inserting ctor with null basic block!"); + if (TID->ImplicitDefs) + for (const unsigned *ImpDefs = TID->getImplicitDefs(); *ImpDefs; ++ImpDefs) + NumImplicitOps++; + if (TID->ImplicitUses) + for (const unsigned *ImpUses = TID->getImplicitUses(); *ImpUses; ++ImpUses) + NumImplicitOps++; + Operands.reserve(NumImplicitOps + TID->getNumOperands()); + addImplicitDefUseOperands(); + // Make sure that we get added to a machine basicblock + LeakDetector::addGarbageObject(this); + MBB->push_back(this); // Add instruction to end of basic block! +} + +/// MachineInstr ctor - Copies MachineInstr arg exactly +/// +MachineInstr::MachineInstr(MachineFunction &MF, const MachineInstr &MI) + : TID(&MI.getDesc()), NumImplicitOps(0), AsmPrinterFlags(0), + MemRefs(MI.MemRefs), MemRefsEnd(MI.MemRefsEnd), + Parent(0), debugLoc(MI.getDebugLoc()) { + Operands.reserve(MI.getNumOperands()); + + // Add operands + for (unsigned i = 0; i != MI.getNumOperands(); ++i) + addOperand(MI.getOperand(i)); + NumImplicitOps = MI.NumImplicitOps; + + // Set parent to null. + Parent = 0; + + LeakDetector::addGarbageObject(this); +} + +MachineInstr::~MachineInstr() { + LeakDetector::removeGarbageObject(this); +#ifndef NDEBUG + for (unsigned i = 0, e = Operands.size(); i != e; ++i) { + assert(Operands[i].ParentMI == this && "ParentMI mismatch!"); + assert((!Operands[i].isReg() || !Operands[i].isOnRegUseList()) && + "Reg operand def/use list corrupted"); + } +#endif +} + +/// getRegInfo - If this instruction is embedded into a MachineFunction, +/// return the MachineRegisterInfo object for the current function, otherwise +/// return null. +MachineRegisterInfo *MachineInstr::getRegInfo() { + if (MachineBasicBlock *MBB = getParent()) + return &MBB->getParent()->getRegInfo(); + return 0; +} + +/// RemoveRegOperandsFromUseLists - Unlink all of the register operands in +/// this instruction from their respective use lists. This requires that the +/// operands already be on their use lists. +void MachineInstr::RemoveRegOperandsFromUseLists() { + for (unsigned i = 0, e = Operands.size(); i != e; ++i) { + if (Operands[i].isReg()) + Operands[i].RemoveRegOperandFromRegInfo(); + } +} + +/// AddRegOperandsToUseLists - Add all of the register operands in +/// this instruction from their respective use lists. This requires that the +/// operands not be on their use lists yet. +void MachineInstr::AddRegOperandsToUseLists(MachineRegisterInfo &RegInfo) { + for (unsigned i = 0, e = Operands.size(); i != e; ++i) { + if (Operands[i].isReg()) + Operands[i].AddRegOperandToRegInfo(&RegInfo); + } +} + + +/// addOperand - Add the specified operand to the instruction. If it is an +/// implicit operand, it is added to the end of the operand list. If it is +/// an explicit operand it is added at the end of the explicit operand list +/// (before the first implicit operand). +void MachineInstr::addOperand(const MachineOperand &Op) { + bool isImpReg = Op.isReg() && Op.isImplicit(); + assert((isImpReg || !OperandsComplete()) && + "Trying to add an operand to a machine instr that is already done!"); + + MachineRegisterInfo *RegInfo = getRegInfo(); + + // If we are adding the operand to the end of the list, our job is simpler. + // This is true most of the time, so this is a reasonable optimization. + if (isImpReg || NumImplicitOps == 0) { + // We can only do this optimization if we know that the operand list won't + // reallocate. + if (Operands.empty() || Operands.size()+1 <= Operands.capacity()) { + Operands.push_back(Op); + + // Set the parent of the operand. + Operands.back().ParentMI = this; + + // If the operand is a register, update the operand's use list. + if (Op.isReg()) + Operands.back().AddRegOperandToRegInfo(RegInfo); + return; + } + } + + // Otherwise, we have to insert a real operand before any implicit ones. + unsigned OpNo = Operands.size()-NumImplicitOps; + + // If this instruction isn't embedded into a function, then we don't need to + // update any operand lists. + if (RegInfo == 0) { + // Simple insertion, no reginfo update needed for other register operands. + Operands.insert(Operands.begin()+OpNo, Op); + Operands[OpNo].ParentMI = this; + + // Do explicitly set the reginfo for this operand though, to ensure the + // next/prev fields are properly nulled out. + if (Operands[OpNo].isReg()) + Operands[OpNo].AddRegOperandToRegInfo(0); + + } else if (Operands.size()+1 <= Operands.capacity()) { + // Otherwise, we have to remove register operands from their register use + // list, add the operand, then add the register operands back to their use + // list. This also must handle the case when the operand list reallocates + // to somewhere else. + + // If insertion of this operand won't cause reallocation of the operand + // list, just remove the implicit operands, add the operand, then re-add all + // the rest of the operands. + for (unsigned i = OpNo, e = Operands.size(); i != e; ++i) { + assert(Operands[i].isReg() && "Should only be an implicit reg!"); + Operands[i].RemoveRegOperandFromRegInfo(); + } + + // Add the operand. If it is a register, add it to the reg list. + Operands.insert(Operands.begin()+OpNo, Op); + Operands[OpNo].ParentMI = this; + + if (Operands[OpNo].isReg()) + Operands[OpNo].AddRegOperandToRegInfo(RegInfo); + + // Re-add all the implicit ops. + for (unsigned i = OpNo+1, e = Operands.size(); i != e; ++i) { + assert(Operands[i].isReg() && "Should only be an implicit reg!"); + Operands[i].AddRegOperandToRegInfo(RegInfo); + } + } else { + // Otherwise, we will be reallocating the operand list. Remove all reg + // operands from their list, then readd them after the operand list is + // reallocated. + RemoveRegOperandsFromUseLists(); + + Operands.insert(Operands.begin()+OpNo, Op); + Operands[OpNo].ParentMI = this; + + // Re-add all the operands. + AddRegOperandsToUseLists(*RegInfo); + } +} + +/// RemoveOperand - Erase an operand from an instruction, leaving it with one +/// fewer operand than it started with. +/// +void MachineInstr::RemoveOperand(unsigned OpNo) { + assert(OpNo < Operands.size() && "Invalid operand number"); + + // Special case removing the last one. + if (OpNo == Operands.size()-1) { + // If needed, remove from the reg def/use list. + if (Operands.back().isReg() && Operands.back().isOnRegUseList()) + Operands.back().RemoveRegOperandFromRegInfo(); + + Operands.pop_back(); + return; + } + + // Otherwise, we are removing an interior operand. If we have reginfo to + // update, remove all operands that will be shifted down from their reg lists, + // move everything down, then re-add them. + MachineRegisterInfo *RegInfo = getRegInfo(); + if (RegInfo) { + for (unsigned i = OpNo, e = Operands.size(); i != e; ++i) { + if (Operands[i].isReg()) + Operands[i].RemoveRegOperandFromRegInfo(); + } + } + + Operands.erase(Operands.begin()+OpNo); + + if (RegInfo) { + for (unsigned i = OpNo, e = Operands.size(); i != e; ++i) { + if (Operands[i].isReg()) + Operands[i].AddRegOperandToRegInfo(RegInfo); + } + } +} + +/// addMemOperand - Add a MachineMemOperand to the machine instruction. +/// This function should be used only occasionally. The setMemRefs function +/// is the primary method for setting up a MachineInstr's MemRefs list. +void MachineInstr::addMemOperand(MachineFunction &MF, + MachineMemOperand *MO) { + mmo_iterator OldMemRefs = MemRefs; + mmo_iterator OldMemRefsEnd = MemRefsEnd; + + size_t NewNum = (MemRefsEnd - MemRefs) + 1; + mmo_iterator NewMemRefs = MF.allocateMemRefsArray(NewNum); + mmo_iterator NewMemRefsEnd = NewMemRefs + NewNum; + + std::copy(OldMemRefs, OldMemRefsEnd, NewMemRefs); + NewMemRefs[NewNum - 1] = MO; + + MemRefs = NewMemRefs; + MemRefsEnd = NewMemRefsEnd; +} + +/// removeFromParent - This method unlinks 'this' from the containing basic +/// block, and returns it, but does not delete it. +MachineInstr *MachineInstr::removeFromParent() { + assert(getParent() && "Not embedded in a basic block!"); + getParent()->remove(this); + return this; +} + + +/// eraseFromParent - This method unlinks 'this' from the containing basic +/// block, and deletes it. +void MachineInstr::eraseFromParent() { + assert(getParent() && "Not embedded in a basic block!"); + getParent()->erase(this); +} + + +/// OperandComplete - Return true if it's illegal to add a new operand +/// +bool MachineInstr::OperandsComplete() const { + unsigned short NumOperands = TID->getNumOperands(); + if (!TID->isVariadic() && getNumOperands()-NumImplicitOps >= NumOperands) + return true; // Broken: we have all the operands of this instruction! + return false; +} + +/// getNumExplicitOperands - Returns the number of non-implicit operands. +/// +unsigned MachineInstr::getNumExplicitOperands() const { + unsigned NumOperands = TID->getNumOperands(); + if (!TID->isVariadic()) + return NumOperands; + + for (unsigned i = NumOperands, e = getNumOperands(); i != e; ++i) { + const MachineOperand &MO = getOperand(i); + if (!MO.isReg() || !MO.isImplicit()) + NumOperands++; + } + return NumOperands; +} + + +/// isLabel - Returns true if the MachineInstr represents a label. +/// +bool MachineInstr::isLabel() const { + return getOpcode() == TargetInstrInfo::DBG_LABEL || + getOpcode() == TargetInstrInfo::EH_LABEL || + getOpcode() == TargetInstrInfo::GC_LABEL; +} + +/// isDebugLabel - Returns true if the MachineInstr represents a debug label. +/// +bool MachineInstr::isDebugLabel() const { + return getOpcode() == TargetInstrInfo::DBG_LABEL; +} + +/// findRegisterUseOperandIdx() - Returns the MachineOperand that is a use of +/// the specific register or -1 if it is not found. It further tightens +/// the search criteria to a use that kills the register if isKill is true. +int MachineInstr::findRegisterUseOperandIdx(unsigned Reg, bool isKill, + const TargetRegisterInfo *TRI) const { + for (unsigned i = 0, e = getNumOperands(); i != e; ++i) { + const MachineOperand &MO = getOperand(i); + if (!MO.isReg() || !MO.isUse()) + continue; + unsigned MOReg = MO.getReg(); + if (!MOReg) + continue; + if (MOReg == Reg || + (TRI && + TargetRegisterInfo::isPhysicalRegister(MOReg) && + TargetRegisterInfo::isPhysicalRegister(Reg) && + TRI->isSubRegister(MOReg, Reg))) + if (!isKill || MO.isKill()) + return i; + } + return -1; +} + +/// findRegisterDefOperandIdx() - Returns the operand index that is a def of +/// the specified register or -1 if it is not found. If isDead is true, defs +/// that are not dead are skipped. If TargetRegisterInfo is non-null, then it +/// also checks if there is a def of a super-register. +int MachineInstr::findRegisterDefOperandIdx(unsigned Reg, bool isDead, + const TargetRegisterInfo *TRI) const { + for (unsigned i = 0, e = getNumOperands(); i != e; ++i) { + const MachineOperand &MO = getOperand(i); + if (!MO.isReg() || !MO.isDef()) + continue; + unsigned MOReg = MO.getReg(); + if (MOReg == Reg || + (TRI && + TargetRegisterInfo::isPhysicalRegister(MOReg) && + TargetRegisterInfo::isPhysicalRegister(Reg) && + TRI->isSubRegister(MOReg, Reg))) + if (!isDead || MO.isDead()) + return i; + } + return -1; +} + +/// findFirstPredOperandIdx() - Find the index of the first operand in the +/// operand list that is used to represent the predicate. It returns -1 if +/// none is found. +int MachineInstr::findFirstPredOperandIdx() const { + const TargetInstrDesc &TID = getDesc(); + if (TID.isPredicable()) { + for (unsigned i = 0, e = getNumOperands(); i != e; ++i) + if (TID.OpInfo[i].isPredicate()) + return i; + } + + return -1; +} + +/// isRegTiedToUseOperand - Given the index of a register def operand, +/// check if the register def is tied to a source operand, due to either +/// two-address elimination or inline assembly constraints. Returns the +/// first tied use operand index by reference is UseOpIdx is not null. +bool MachineInstr:: +isRegTiedToUseOperand(unsigned DefOpIdx, unsigned *UseOpIdx) const { + if (getOpcode() == TargetInstrInfo::INLINEASM) { + assert(DefOpIdx >= 2); + const MachineOperand &MO = getOperand(DefOpIdx); + if (!MO.isReg() || !MO.isDef() || MO.getReg() == 0) + return false; + // Determine the actual operand index that corresponds to this index. + unsigned DefNo = 0; + unsigned DefPart = 0; + for (unsigned i = 1, e = getNumOperands(); i < e; ) { + const MachineOperand &FMO = getOperand(i); + // After the normal asm operands there may be additional imp-def regs. + if (!FMO.isImm()) + return false; + // Skip over this def. + unsigned NumOps = InlineAsm::getNumOperandRegisters(FMO.getImm()); + unsigned PrevDef = i + 1; + i = PrevDef + NumOps; + if (i > DefOpIdx) { + DefPart = DefOpIdx - PrevDef; + break; + } + ++DefNo; + } + for (unsigned i = 1, e = getNumOperands(); i != e; ++i) { + const MachineOperand &FMO = getOperand(i); + if (!FMO.isImm()) + continue; + if (i+1 >= e || !getOperand(i+1).isReg() || !getOperand(i+1).isUse()) + continue; + unsigned Idx; + if (InlineAsm::isUseOperandTiedToDef(FMO.getImm(), Idx) && + Idx == DefNo) { + if (UseOpIdx) + *UseOpIdx = (unsigned)i + 1 + DefPart; + return true; + } + } + return false; + } + + assert(getOperand(DefOpIdx).isDef() && "DefOpIdx is not a def!"); + const TargetInstrDesc &TID = getDesc(); + for (unsigned i = 0, e = TID.getNumOperands(); i != e; ++i) { + const MachineOperand &MO = getOperand(i); + if (MO.isReg() && MO.isUse() && + TID.getOperandConstraint(i, TOI::TIED_TO) == (int)DefOpIdx) { + if (UseOpIdx) + *UseOpIdx = (unsigned)i; + return true; + } + } + return false; +} + +/// isRegTiedToDefOperand - Return true if the operand of the specified index +/// is a register use and it is tied to an def operand. It also returns the def +/// operand index by reference. +bool MachineInstr:: +isRegTiedToDefOperand(unsigned UseOpIdx, unsigned *DefOpIdx) const { + if (getOpcode() == TargetInstrInfo::INLINEASM) { + const MachineOperand &MO = getOperand(UseOpIdx); + if (!MO.isReg() || !MO.isUse() || MO.getReg() == 0) + return false; + + // Find the flag operand corresponding to UseOpIdx + unsigned FlagIdx, NumOps=0; + for (FlagIdx = 1; FlagIdx < UseOpIdx; FlagIdx += NumOps+1) { + const MachineOperand &UFMO = getOperand(FlagIdx); + // After the normal asm operands there may be additional imp-def regs. + if (!UFMO.isImm()) + return false; + NumOps = InlineAsm::getNumOperandRegisters(UFMO.getImm()); + assert(NumOps < getNumOperands() && "Invalid inline asm flag"); + if (UseOpIdx < FlagIdx+NumOps+1) + break; + } + if (FlagIdx >= UseOpIdx) + return false; + const MachineOperand &UFMO = getOperand(FlagIdx); + unsigned DefNo; + if (InlineAsm::isUseOperandTiedToDef(UFMO.getImm(), DefNo)) { + if (!DefOpIdx) + return true; + + unsigned DefIdx = 1; + // Remember to adjust the index. First operand is asm string, then there + // is a flag for each. + while (DefNo) { + const MachineOperand &FMO = getOperand(DefIdx); + assert(FMO.isImm()); + // Skip over this def. + DefIdx += InlineAsm::getNumOperandRegisters(FMO.getImm()) + 1; + --DefNo; + } + *DefOpIdx = DefIdx + UseOpIdx - FlagIdx; + return true; + } + return false; + } + + const TargetInstrDesc &TID = getDesc(); + if (UseOpIdx >= TID.getNumOperands()) + return false; + const MachineOperand &MO = getOperand(UseOpIdx); + if (!MO.isReg() || !MO.isUse()) + return false; + int DefIdx = TID.getOperandConstraint(UseOpIdx, TOI::TIED_TO); + if (DefIdx == -1) + return false; + if (DefOpIdx) + *DefOpIdx = (unsigned)DefIdx; + return true; +} + +/// copyKillDeadInfo - Copies kill / dead operand properties from MI. +/// +void MachineInstr::copyKillDeadInfo(const MachineInstr *MI) { + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + const MachineOperand &MO = MI->getOperand(i); + if (!MO.isReg() || (!MO.isKill() && !MO.isDead())) + continue; + for (unsigned j = 0, ee = getNumOperands(); j != ee; ++j) { + MachineOperand &MOp = getOperand(j); + if (!MOp.isIdenticalTo(MO)) + continue; + if (MO.isKill()) + MOp.setIsKill(); + else + MOp.setIsDead(); + break; + } + } +} + +/// copyPredicates - Copies predicate operand(s) from MI. +void MachineInstr::copyPredicates(const MachineInstr *MI) { + const TargetInstrDesc &TID = MI->getDesc(); + if (!TID.isPredicable()) + return; + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + if (TID.OpInfo[i].isPredicate()) { + // Predicated operands must be last operands. + addOperand(MI->getOperand(i)); + } + } +} + +/// isSafeToMove - Return true if it is safe to move this instruction. If +/// SawStore is set to true, it means that there is a store (or call) between +/// the instruction's location and its intended destination. +bool MachineInstr::isSafeToMove(const TargetInstrInfo *TII, + bool &SawStore, + AliasAnalysis *AA) const { + // Ignore stuff that we obviously can't move. + if (TID->mayStore() || TID->isCall()) { + SawStore = true; + return false; + } + if (TID->isTerminator() || TID->hasUnmodeledSideEffects()) + return false; + + // See if this instruction does a load. If so, we have to guarantee that the + // loaded value doesn't change between the load and the its intended + // destination. The check for isInvariantLoad gives the targe the chance to + // classify the load as always returning a constant, e.g. a constant pool + // load. + if (TID->mayLoad() && !isInvariantLoad(AA)) + // Otherwise, this is a real load. If there is a store between the load and + // end of block, or if the load is volatile, we can't move it. + return !SawStore && !hasVolatileMemoryRef(); + + return true; +} + +/// isSafeToReMat - Return true if it's safe to rematerialize the specified +/// instruction which defined the specified register instead of copying it. +bool MachineInstr::isSafeToReMat(const TargetInstrInfo *TII, + unsigned DstReg, + AliasAnalysis *AA) const { + bool SawStore = false; + if (!TII->isTriviallyReMaterializable(this, AA) || + !isSafeToMove(TII, SawStore, AA)) + return false; + for (unsigned i = 0, e = getNumOperands(); i != e; ++i) { + const MachineOperand &MO = getOperand(i); + if (!MO.isReg()) + continue; + // FIXME: For now, do not remat any instruction with register operands. + // Later on, we can loosen the restriction is the register operands have + // not been modified between the def and use. Note, this is different from + // MachineSink because the code is no longer in two-address form (at least + // partially). + if (MO.isUse()) + return false; + else if (!MO.isDead() && MO.getReg() != DstReg) + return false; + } + return true; +} + +/// hasVolatileMemoryRef - Return true if this instruction may have a +/// volatile memory reference, or if the information describing the +/// memory reference is not available. Return false if it is known to +/// have no volatile memory references. +bool MachineInstr::hasVolatileMemoryRef() const { + // An instruction known never to access memory won't have a volatile access. + if (!TID->mayStore() && + !TID->mayLoad() && + !TID->isCall() && + !TID->hasUnmodeledSideEffects()) + return false; + + // Otherwise, if the instruction has no memory reference information, + // conservatively assume it wasn't preserved. + if (memoperands_empty()) + return true; + + // Check the memory reference information for volatile references. + for (mmo_iterator I = memoperands_begin(), E = memoperands_end(); I != E; ++I) + if ((*I)->isVolatile()) + return true; + + return false; +} + +/// isInvariantLoad - Return true if this instruction is loading from a +/// location whose value is invariant across the function. For example, +/// loading a value from the constant pool or from from the argument area +/// of a function if it does not change. This should only return true of +/// *all* loads the instruction does are invariant (if it does multiple loads). +bool MachineInstr::isInvariantLoad(AliasAnalysis *AA) const { + // If the instruction doesn't load at all, it isn't an invariant load. + if (!TID->mayLoad()) + return false; + + // If the instruction has lost its memoperands, conservatively assume that + // it may not be an invariant load. + if (memoperands_empty()) + return false; + + const MachineFrameInfo *MFI = getParent()->getParent()->getFrameInfo(); + + for (mmo_iterator I = memoperands_begin(), + E = memoperands_end(); I != E; ++I) { + if ((*I)->isVolatile()) return false; + if ((*I)->isStore()) return false; + + if (const Value *V = (*I)->getValue()) { + // A load from a constant PseudoSourceValue is invariant. + if (const PseudoSourceValue *PSV = dyn_cast(V)) + if (PSV->isConstant(MFI)) + continue; + // If we have an AliasAnalysis, ask it whether the memory is constant. + if (AA && AA->pointsToConstantMemory(V)) + continue; + } + + // Otherwise assume conservatively. + return false; + } + + // Everything checks out. + return true; +} + +void MachineInstr::dump() const { + errs() << " " << *this; +} + +void MachineInstr::print(raw_ostream &OS, const TargetMachine *TM) const { + // We can be a bit tidier if we know the TargetMachine and/or MachineFunction. + const MachineFunction *MF = 0; + if (const MachineBasicBlock *MBB = getParent()) { + MF = MBB->getParent(); + if (!TM && MF) + TM = &MF->getTarget(); + } + + // Print explicitly defined operands on the left of an assignment syntax. + unsigned StartOp = 0, e = getNumOperands(); + for (; StartOp < e && getOperand(StartOp).isReg() && + getOperand(StartOp).isDef() && + !getOperand(StartOp).isImplicit(); + ++StartOp) { + if (StartOp != 0) OS << ", "; + getOperand(StartOp).print(OS, TM); + } + + if (StartOp != 0) + OS << " = "; + + // Print the opcode name. + OS << getDesc().getName(); + + // Print the rest of the operands. + bool OmittedAnyCallClobbers = false; + bool FirstOp = true; + for (unsigned i = StartOp, e = getNumOperands(); i != e; ++i) { + const MachineOperand &MO = getOperand(i); + + // Omit call-clobbered registers which aren't used anywhere. This makes + // call instructions much less noisy on targets where calls clobber lots + // of registers. Don't rely on MO.isDead() because we may be called before + // LiveVariables is run, or we may be looking at a non-allocatable reg. + if (MF && getDesc().isCall() && + MO.isReg() && MO.isImplicit() && MO.isDef()) { + unsigned Reg = MO.getReg(); + if (Reg != 0 && TargetRegisterInfo::isPhysicalRegister(Reg)) { + const MachineRegisterInfo &MRI = MF->getRegInfo(); + if (MRI.use_empty(Reg) && !MRI.isLiveOut(Reg)) { + bool HasAliasLive = false; + for (const unsigned *Alias = TM->getRegisterInfo()->getAliasSet(Reg); + unsigned AliasReg = *Alias; ++Alias) + if (!MRI.use_empty(AliasReg) || MRI.isLiveOut(AliasReg)) { + HasAliasLive = true; + break; + } + if (!HasAliasLive) { + OmittedAnyCallClobbers = true; + continue; + } + } + } + } + + if (FirstOp) FirstOp = false; else OS << ","; + OS << " "; + MO.print(OS, TM); + } + + // Briefly indicate whether any call clobbers were omitted. + if (OmittedAnyCallClobbers) { + if (FirstOp) FirstOp = false; else OS << ","; + OS << " ..."; + } + + bool HaveSemi = false; + if (!memoperands_empty()) { + if (!HaveSemi) OS << ";"; HaveSemi = true; + + OS << " mem:"; + for (mmo_iterator i = memoperands_begin(), e = memoperands_end(); + i != e; ++i) { + OS << **i; + if (next(i) != e) + OS << " "; + } + } + + if (!debugLoc.isUnknown() && MF) { + if (!HaveSemi) OS << ";"; HaveSemi = true; + + // TODO: print InlinedAtLoc information + + DebugLocTuple DLT = MF->getDebugLocTuple(debugLoc); + DICompileUnit CU(DLT.Scope); + OS << " dbg:"; + if (!CU.isNull()) + OS << CU.getDirectory() << '/' << CU.getFilename() << ":"; + OS << DLT.Line << ":" << DLT.Col; + } + + OS << "\n"; +} + +bool MachineInstr::addRegisterKilled(unsigned IncomingReg, + const TargetRegisterInfo *RegInfo, + bool AddIfNotFound) { + bool isPhysReg = TargetRegisterInfo::isPhysicalRegister(IncomingReg); + bool hasAliases = isPhysReg && RegInfo->getAliasSet(IncomingReg); + bool Found = false; + SmallVector DeadOps; + for (unsigned i = 0, e = getNumOperands(); i != e; ++i) { + MachineOperand &MO = getOperand(i); + if (!MO.isReg() || !MO.isUse() || MO.isUndef()) + continue; + unsigned Reg = MO.getReg(); + if (!Reg) + continue; + + if (Reg == IncomingReg) { + if (!Found) { + if (MO.isKill()) + // The register is already marked kill. + return true; + if (isPhysReg && isRegTiedToDefOperand(i)) + // Two-address uses of physregs must not be marked kill. + return true; + MO.setIsKill(); + Found = true; + } + } else if (hasAliases && MO.isKill() && + TargetRegisterInfo::isPhysicalRegister(Reg)) { + // A super-register kill already exists. + if (RegInfo->isSuperRegister(IncomingReg, Reg)) + return true; + if (RegInfo->isSubRegister(IncomingReg, Reg)) + DeadOps.push_back(i); + } + } + + // Trim unneeded kill operands. + while (!DeadOps.empty()) { + unsigned OpIdx = DeadOps.back(); + if (getOperand(OpIdx).isImplicit()) + RemoveOperand(OpIdx); + else + getOperand(OpIdx).setIsKill(false); + DeadOps.pop_back(); + } + + // If not found, this means an alias of one of the operands is killed. Add a + // new implicit operand if required. + if (!Found && AddIfNotFound) { + addOperand(MachineOperand::CreateReg(IncomingReg, + false /*IsDef*/, + true /*IsImp*/, + true /*IsKill*/)); + return true; + } + return Found; +} + +bool MachineInstr::addRegisterDead(unsigned IncomingReg, + const TargetRegisterInfo *RegInfo, + bool AddIfNotFound) { + bool isPhysReg = TargetRegisterInfo::isPhysicalRegister(IncomingReg); + bool hasAliases = isPhysReg && RegInfo->getAliasSet(IncomingReg); + bool Found = false; + SmallVector DeadOps; + for (unsigned i = 0, e = getNumOperands(); i != e; ++i) { + MachineOperand &MO = getOperand(i); + if (!MO.isReg() || !MO.isDef()) + continue; + unsigned Reg = MO.getReg(); + if (!Reg) + continue; + + if (Reg == IncomingReg) { + if (!Found) { + if (MO.isDead()) + // The register is already marked dead. + return true; + MO.setIsDead(); + Found = true; + } + } else if (hasAliases && MO.isDead() && + TargetRegisterInfo::isPhysicalRegister(Reg)) { + // There exists a super-register that's marked dead. + if (RegInfo->isSuperRegister(IncomingReg, Reg)) + return true; + if (RegInfo->getSubRegisters(IncomingReg) && + RegInfo->getSuperRegisters(Reg) && + RegInfo->isSubRegister(IncomingReg, Reg)) + DeadOps.push_back(i); + } + } + + // Trim unneeded dead operands. + while (!DeadOps.empty()) { + unsigned OpIdx = DeadOps.back(); + if (getOperand(OpIdx).isImplicit()) + RemoveOperand(OpIdx); + else + getOperand(OpIdx).setIsDead(false); + DeadOps.pop_back(); + } + + // If not found, this means an alias of one of the operands is dead. Add a + // new implicit operand if required. + if (Found || !AddIfNotFound) + return Found; + + addOperand(MachineOperand::CreateReg(IncomingReg, + true /*IsDef*/, + true /*IsImp*/, + false /*IsKill*/, + true /*IsDead*/)); + return true; +} diff --git a/libclamav/c++/llvm/lib/CodeGen/MachineLICM.cpp b/libclamav/c++/llvm/lib/CodeGen/MachineLICM.cpp new file mode 100644 index 000000000..66de5359d --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/MachineLICM.cpp @@ -0,0 +1,543 @@ +//===-- MachineLICM.cpp - Machine Loop Invariant Code Motion Pass ---------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This pass performs loop invariant code motion on machine instructions. We +// attempt to remove as much code from the body of a loop as possible. +// +// This pass does not attempt to throttle itself to limit register pressure. +// The register allocation phases are expected to perform rematerialization +// to recover when register pressure is high. +// +// This pass is not intended to be a replacement or a complete alternative +// for the LLVM-IR-level LICM pass. It is only designed to hoist simple +// constructs that are not exposed before lowering and instruction selection. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "machine-licm" +#include "llvm/CodeGen/Passes.h" +#include "llvm/CodeGen/MachineConstantPool.h" +#include "llvm/CodeGen/MachineDominators.h" +#include "llvm/CodeGen/MachineLoopInfo.h" +#include "llvm/CodeGen/MachineMemOperand.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/PseudoSourceValue.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" + +using namespace llvm; + +STATISTIC(NumHoisted, "Number of machine instructions hoisted out of loops"); +STATISTIC(NumCSEed, "Number of hoisted machine instructions CSEed"); + +namespace { + class MachineLICM : public MachineFunctionPass { + MachineConstantPool *MCP; + const TargetMachine *TM; + const TargetInstrInfo *TII; + const TargetRegisterInfo *TRI; + BitVector AllocatableSet; + + // Various analyses that we use... + AliasAnalysis *AA; // Alias analysis info. + MachineLoopInfo *LI; // Current MachineLoopInfo + MachineDominatorTree *DT; // Machine dominator tree for the cur loop + MachineRegisterInfo *RegInfo; // Machine register information + + // State that is updated as we process loops + bool Changed; // True if a loop is changed. + bool FirstInLoop; // True if it's the first LICM in the loop. + MachineLoop *CurLoop; // The current loop we are working on. + MachineBasicBlock *CurPreheader; // The preheader for CurLoop. + + // For each opcode, keep a list of potentail CSE instructions. + DenseMap > CSEMap; + public: + static char ID; // Pass identification, replacement for typeid + MachineLICM() : MachineFunctionPass(&ID) {} + + virtual bool runOnMachineFunction(MachineFunction &MF); + + const char *getPassName() const { return "Machine Instruction LICM"; } + + // FIXME: Loop preheaders? + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesCFG(); + AU.addRequired(); + AU.addRequired(); + AU.addRequired(); + AU.addPreserved(); + AU.addPreserved(); + MachineFunctionPass::getAnalysisUsage(AU); + } + + virtual void releaseMemory() { + CSEMap.clear(); + } + + private: + /// IsLoopInvariantInst - Returns true if the instruction is loop + /// invariant. I.e., all virtual register operands are defined outside of + /// the loop, physical registers aren't accessed (explicitly or implicitly), + /// and the instruction is hoistable. + /// + bool IsLoopInvariantInst(MachineInstr &I); + + /// IsProfitableToHoist - Return true if it is potentially profitable to + /// hoist the given loop invariant. + bool IsProfitableToHoist(MachineInstr &MI); + + /// HoistRegion - Walk the specified region of the CFG (defined by all + /// blocks dominated by the specified block, and that are in the current + /// loop) in depth first order w.r.t the DominatorTree. This allows us to + /// visit definitions before uses, allowing us to hoist a loop body in one + /// pass without iteration. + /// + void HoistRegion(MachineDomTreeNode *N); + + /// isLoadFromConstantMemory - Return true if the given instruction is a + /// load from constant memory. + bool isLoadFromConstantMemory(MachineInstr *MI); + + /// ExtractHoistableLoad - Unfold a load from the given machineinstr if + /// the load itself could be hoisted. Return the unfolded and hoistable + /// load, or null if the load couldn't be unfolded or if it wouldn't + /// be hoistable. + MachineInstr *ExtractHoistableLoad(MachineInstr *MI); + + /// LookForDuplicate - Find an instruction amount PrevMIs that is a + /// duplicate of MI. Return this instruction if it's found. + const MachineInstr *LookForDuplicate(const MachineInstr *MI, + std::vector &PrevMIs); + + /// EliminateCSE - Given a LICM'ed instruction, look for an instruction on + /// the preheader that compute the same value. If it's found, do a RAU on + /// with the definition of the existing instruction rather than hoisting + /// the instruction to the preheader. + bool EliminateCSE(MachineInstr *MI, + DenseMap >::iterator &CI); + + /// Hoist - When an instruction is found to only use loop invariant operands + /// that is safe to hoist, this instruction is called to do the dirty work. + /// + void Hoist(MachineInstr *MI); + + /// InitCSEMap - Initialize the CSE map with instructions that are in the + /// current loop preheader that may become duplicates of instructions that + /// are hoisted out of the loop. + void InitCSEMap(MachineBasicBlock *BB); + }; +} // end anonymous namespace + +char MachineLICM::ID = 0; +static RegisterPass +X("machinelicm", "Machine Loop Invariant Code Motion"); + +FunctionPass *llvm::createMachineLICMPass() { return new MachineLICM(); } + +/// LoopIsOuterMostWithPreheader - Test if the given loop is the outer-most +/// loop that has a preheader. +static bool LoopIsOuterMostWithPreheader(MachineLoop *CurLoop) { + for (MachineLoop *L = CurLoop->getParentLoop(); L; L = L->getParentLoop()) + if (L->getLoopPreheader()) + return false; + return true; +} + +/// Hoist expressions out of the specified loop. Note, alias info for inner loop +/// is not preserved so it is not a good idea to run LICM multiple times on one +/// loop. +/// +bool MachineLICM::runOnMachineFunction(MachineFunction &MF) { + DEBUG(errs() << "******** Machine LICM ********\n"); + + Changed = FirstInLoop = false; + MCP = MF.getConstantPool(); + TM = &MF.getTarget(); + TII = TM->getInstrInfo(); + TRI = TM->getRegisterInfo(); + RegInfo = &MF.getRegInfo(); + AllocatableSet = TRI->getAllocatableSet(MF); + + // Get our Loop information... + LI = &getAnalysis(); + DT = &getAnalysis(); + AA = &getAnalysis(); + + for (MachineLoopInfo::iterator I = LI->begin(), E = LI->end(); I != E; ++I) { + CurLoop = *I; + + // Only visit outer-most preheader-sporting loops. + if (!LoopIsOuterMostWithPreheader(CurLoop)) + continue; + + // Determine the block to which to hoist instructions. If we can't find a + // suitable loop preheader, we can't do any hoisting. + // + // FIXME: We are only hoisting if the basic block coming into this loop + // has only one successor. This isn't the case in general because we haven't + // broken critical edges or added preheaders. + CurPreheader = CurLoop->getLoopPreheader(); + if (!CurPreheader) + continue; + + // CSEMap is initialized for loop header when the first instruction is + // being hoisted. + FirstInLoop = true; + HoistRegion(DT->getNode(CurLoop->getHeader())); + CSEMap.clear(); + } + + return Changed; +} + +/// HoistRegion - Walk the specified region of the CFG (defined by all blocks +/// dominated by the specified block, and that are in the current loop) in depth +/// first order w.r.t the DominatorTree. This allows us to visit definitions +/// before uses, allowing us to hoist a loop body in one pass without iteration. +/// +void MachineLICM::HoistRegion(MachineDomTreeNode *N) { + assert(N != 0 && "Null dominator tree node?"); + MachineBasicBlock *BB = N->getBlock(); + + // If this subregion is not in the top level loop at all, exit. + if (!CurLoop->contains(BB)) return; + + for (MachineBasicBlock::iterator + MII = BB->begin(), E = BB->end(); MII != E; ) { + MachineBasicBlock::iterator NextMII = MII; ++NextMII; + Hoist(&*MII); + MII = NextMII; + } + + const std::vector &Children = N->getChildren(); + + for (unsigned I = 0, E = Children.size(); I != E; ++I) + HoistRegion(Children[I]); +} + +/// IsLoopInvariantInst - Returns true if the instruction is loop +/// invariant. I.e., all virtual register operands are defined outside of the +/// loop, physical registers aren't accessed explicitly, and there are no side +/// effects that aren't captured by the operands or other flags. +/// +bool MachineLICM::IsLoopInvariantInst(MachineInstr &I) { + const TargetInstrDesc &TID = I.getDesc(); + + // Ignore stuff that we obviously can't hoist. + if (TID.mayStore() || TID.isCall() || TID.isTerminator() || + TID.hasUnmodeledSideEffects()) + return false; + + if (TID.mayLoad()) { + // Okay, this instruction does a load. As a refinement, we allow the target + // to decide whether the loaded value is actually a constant. If so, we can + // actually use it as a load. + if (!I.isInvariantLoad(AA)) + // FIXME: we should be able to hoist loads with no other side effects if + // there are no other instructions which can change memory in this loop. + // This is a trivial form of alias analysis. + return false; + } + + DEBUG({ + errs() << "--- Checking if we can hoist " << I; + if (I.getDesc().getImplicitUses()) { + errs() << " * Instruction has implicit uses:\n"; + + const TargetRegisterInfo *TRI = TM->getRegisterInfo(); + for (const unsigned *ImpUses = I.getDesc().getImplicitUses(); + *ImpUses; ++ImpUses) + errs() << " -> " << TRI->getName(*ImpUses) << "\n"; + } + + if (I.getDesc().getImplicitDefs()) { + errs() << " * Instruction has implicit defines:\n"; + + const TargetRegisterInfo *TRI = TM->getRegisterInfo(); + for (const unsigned *ImpDefs = I.getDesc().getImplicitDefs(); + *ImpDefs; ++ImpDefs) + errs() << " -> " << TRI->getName(*ImpDefs) << "\n"; + } + }); + + if (I.getDesc().getImplicitDefs() || I.getDesc().getImplicitUses()) { + DEBUG(errs() << "Cannot hoist with implicit defines or uses\n"); + return false; + } + + // The instruction is loop invariant if all of its operands are. + for (unsigned i = 0, e = I.getNumOperands(); i != e; ++i) { + const MachineOperand &MO = I.getOperand(i); + + if (!MO.isReg()) + continue; + + unsigned Reg = MO.getReg(); + if (Reg == 0) continue; + + // Don't hoist an instruction that uses or defines a physical register. + if (TargetRegisterInfo::isPhysicalRegister(Reg)) { + if (MO.isUse()) { + // If the physreg has no defs anywhere, it's just an ambient register + // and we can freely move its uses. Alternatively, if it's allocatable, + // it could get allocated to something with a def during allocation. + if (!RegInfo->def_empty(Reg)) + return false; + if (AllocatableSet.test(Reg)) + return false; + // Check for a def among the register's aliases too. + for (const unsigned *Alias = TRI->getAliasSet(Reg); *Alias; ++Alias) { + unsigned AliasReg = *Alias; + if (!RegInfo->def_empty(AliasReg)) + return false; + if (AllocatableSet.test(AliasReg)) + return false; + } + // Otherwise it's safe to move. + continue; + } else if (!MO.isDead()) { + // A def that isn't dead. We can't move it. + return false; + } + } + + if (!MO.isUse()) + continue; + + assert(RegInfo->getVRegDef(Reg) && + "Machine instr not mapped for this vreg?!"); + + // If the loop contains the definition of an operand, then the instruction + // isn't loop invariant. + if (CurLoop->contains(RegInfo->getVRegDef(Reg)->getParent())) + return false; + } + + // If we got this far, the instruction is loop invariant! + return true; +} + + +/// HasPHIUses - Return true if the specified register has any PHI use. +static bool HasPHIUses(unsigned Reg, MachineRegisterInfo *RegInfo) { + for (MachineRegisterInfo::use_iterator UI = RegInfo->use_begin(Reg), + UE = RegInfo->use_end(); UI != UE; ++UI) { + MachineInstr *UseMI = &*UI; + if (UseMI->getOpcode() == TargetInstrInfo::PHI) + return true; + } + return false; +} + +/// isLoadFromConstantMemory - Return true if the given instruction is a +/// load from constant memory. Machine LICM will hoist these even if they are +/// not re-materializable. +bool MachineLICM::isLoadFromConstantMemory(MachineInstr *MI) { + if (!MI->getDesc().mayLoad()) return false; + if (!MI->hasOneMemOperand()) return false; + MachineMemOperand *MMO = *MI->memoperands_begin(); + if (MMO->isVolatile()) return false; + if (!MMO->getValue()) return false; + const PseudoSourceValue *PSV = dyn_cast(MMO->getValue()); + if (PSV) { + MachineFunction &MF = *MI->getParent()->getParent(); + return PSV->isConstant(MF.getFrameInfo()); + } else { + return AA->pointsToConstantMemory(MMO->getValue()); + } +} + +/// IsProfitableToHoist - Return true if it is potentially profitable to hoist +/// the given loop invariant. +bool MachineLICM::IsProfitableToHoist(MachineInstr &MI) { + if (MI.getOpcode() == TargetInstrInfo::IMPLICIT_DEF) + return false; + + // FIXME: For now, only hoist re-materilizable instructions. LICM will + // increase register pressure. We want to make sure it doesn't increase + // spilling. + // Also hoist loads from constant memory, e.g. load from stubs, GOT. Hoisting + // these tend to help performance in low register pressure situation. The + // trade off is it may cause spill in high pressure situation. It will end up + // adding a store in the loop preheader. But the reload is no more expensive. + // The side benefit is these loads are frequently CSE'ed. + if (!TII->isTriviallyReMaterializable(&MI, AA)) { + if (!isLoadFromConstantMemory(&MI)) + return false; + } + + // If result(s) of this instruction is used by PHIs, then don't hoist it. + // The presence of joins makes it difficult for current register allocator + // implementation to perform remat. + for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) { + const MachineOperand &MO = MI.getOperand(i); + if (!MO.isReg() || !MO.isDef()) + continue; + if (HasPHIUses(MO.getReg(), RegInfo)) + return false; + } + + return true; +} + +MachineInstr *MachineLICM::ExtractHoistableLoad(MachineInstr *MI) { + // If not, we may be able to unfold a load and hoist that. + // First test whether the instruction is loading from an amenable + // memory location. + if (!isLoadFromConstantMemory(MI)) + return 0; + + // Next determine the register class for a temporary register. + unsigned LoadRegIndex; + unsigned NewOpc = + TII->getOpcodeAfterMemoryUnfold(MI->getOpcode(), + /*UnfoldLoad=*/true, + /*UnfoldStore=*/false, + &LoadRegIndex); + if (NewOpc == 0) return 0; + const TargetInstrDesc &TID = TII->get(NewOpc); + if (TID.getNumDefs() != 1) return 0; + const TargetRegisterClass *RC = TID.OpInfo[LoadRegIndex].getRegClass(TRI); + // Ok, we're unfolding. Create a temporary register and do the unfold. + unsigned Reg = RegInfo->createVirtualRegister(RC); + + MachineFunction &MF = *MI->getParent()->getParent(); + SmallVector NewMIs; + bool Success = + TII->unfoldMemoryOperand(MF, MI, Reg, + /*UnfoldLoad=*/true, /*UnfoldStore=*/false, + NewMIs); + (void)Success; + assert(Success && + "unfoldMemoryOperand failed when getOpcodeAfterMemoryUnfold " + "succeeded!"); + assert(NewMIs.size() == 2 && + "Unfolded a load into multiple instructions!"); + MachineBasicBlock *MBB = MI->getParent(); + MBB->insert(MI, NewMIs[0]); + MBB->insert(MI, NewMIs[1]); + // If unfolding produced a load that wasn't loop-invariant or profitable to + // hoist, discard the new instructions and bail. + if (!IsLoopInvariantInst(*NewMIs[0]) || !IsProfitableToHoist(*NewMIs[0])) { + NewMIs[0]->eraseFromParent(); + NewMIs[1]->eraseFromParent(); + return 0; + } + // Otherwise we successfully unfolded a load that we can hoist. + MI->eraseFromParent(); + return NewMIs[0]; +} + +void MachineLICM::InitCSEMap(MachineBasicBlock *BB) { + for (MachineBasicBlock::iterator I = BB->begin(),E = BB->end(); I != E; ++I) { + const MachineInstr *MI = &*I; + // FIXME: For now, only hoist re-materilizable instructions. LICM will + // increase register pressure. We want to make sure it doesn't increase + // spilling. + if (TII->isTriviallyReMaterializable(MI, AA)) { + unsigned Opcode = MI->getOpcode(); + DenseMap >::iterator + CI = CSEMap.find(Opcode); + if (CI != CSEMap.end()) + CI->second.push_back(MI); + else { + std::vector CSEMIs; + CSEMIs.push_back(MI); + CSEMap.insert(std::make_pair(Opcode, CSEMIs)); + } + } + } +} + +const MachineInstr* +MachineLICM::LookForDuplicate(const MachineInstr *MI, + std::vector &PrevMIs) { + for (unsigned i = 0, e = PrevMIs.size(); i != e; ++i) { + const MachineInstr *PrevMI = PrevMIs[i]; + if (TII->isIdentical(MI, PrevMI, RegInfo)) + return PrevMI; + } + return 0; +} + +bool MachineLICM::EliminateCSE(MachineInstr *MI, + DenseMap >::iterator &CI) { + if (CI == CSEMap.end()) + return false; + + if (const MachineInstr *Dup = LookForDuplicate(MI, CI->second)) { + DEBUG(errs() << "CSEing " << *MI << " with " << *Dup); + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + const MachineOperand &MO = MI->getOperand(i); + if (MO.isReg() && MO.isDef()) + RegInfo->replaceRegWith(MO.getReg(), Dup->getOperand(i).getReg()); + } + MI->eraseFromParent(); + ++NumCSEed; + return true; + } + return false; +} + +/// Hoist - When an instruction is found to use only loop invariant operands +/// that are safe to hoist, this instruction is called to do the dirty work. +/// +void MachineLICM::Hoist(MachineInstr *MI) { + // First check whether we should hoist this instruction. + if (!IsLoopInvariantInst(*MI) || !IsProfitableToHoist(*MI)) { + // If not, try unfolding a hoistable load. + MI = ExtractHoistableLoad(MI); + if (!MI) return; + } + + // Now move the instructions to the predecessor, inserting it before any + // terminator instructions. + DEBUG({ + errs() << "Hoisting " << *MI; + if (CurPreheader->getBasicBlock()) + errs() << " to MachineBasicBlock " + << CurPreheader->getName(); + if (MI->getParent()->getBasicBlock()) + errs() << " from MachineBasicBlock " + << MI->getParent()->getName(); + errs() << "\n"; + }); + + // If this is the first instruction being hoisted to the preheader, + // initialize the CSE map with potential common expressions. + InitCSEMap(CurPreheader); + + // Look for opportunity to CSE the hoisted instruction. + unsigned Opcode = MI->getOpcode(); + DenseMap >::iterator + CI = CSEMap.find(Opcode); + if (!EliminateCSE(MI, CI)) { + // Otherwise, splice the instruction to the preheader. + CurPreheader->splice(CurPreheader->getFirstTerminator(),MI->getParent(),MI); + + // Add to the CSE map. + if (CI != CSEMap.end()) + CI->second.push_back(MI); + else { + std::vector CSEMIs; + CSEMIs.push_back(MI); + CSEMap.insert(std::make_pair(Opcode, CSEMIs)); + } + } + + ++NumHoisted; + Changed = true; +} diff --git a/libclamav/c++/llvm/lib/CodeGen/MachineLoopInfo.cpp b/libclamav/c++/llvm/lib/CodeGen/MachineLoopInfo.cpp new file mode 100644 index 000000000..db77d192c --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/MachineLoopInfo.cpp @@ -0,0 +1,73 @@ +//===- MachineLoopInfo.cpp - Natural Loop Calculator ----------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the MachineLoopInfo class that is used to identify natural +// loops and determine the loop depth of various nodes of the CFG. Note that +// the loops identified may actually be several natural loops that share the +// same header node... not just a single natural loop. +// +//===----------------------------------------------------------------------===// + +#include "llvm/CodeGen/MachineLoopInfo.h" +#include "llvm/CodeGen/MachineDominators.h" +#include "llvm/CodeGen/Passes.h" +using namespace llvm; + +#define MLB class LoopBase +TEMPLATE_INSTANTIATION(MLB); +#undef MLB +#define MLIB class LoopInfoBase +TEMPLATE_INSTANTIATION(MLIB); +#undef MLIB + +char MachineLoopInfo::ID = 0; +static RegisterPass +X("machine-loops", "Machine Natural Loop Construction", true); + +const PassInfo *const llvm::MachineLoopInfoID = &X; + +bool MachineLoopInfo::runOnMachineFunction(MachineFunction &) { + releaseMemory(); + LI.Calculate(getAnalysis().getBase()); // Update + return false; +} + +void MachineLoopInfo::getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + AU.addRequired(); + MachineFunctionPass::getAnalysisUsage(AU); +} + +MachineBasicBlock *MachineLoop::getTopBlock() { + MachineBasicBlock *TopMBB = getHeader(); + MachineFunction::iterator Begin = TopMBB->getParent()->begin(); + if (TopMBB != Begin) { + MachineBasicBlock *PriorMBB = prior(MachineFunction::iterator(TopMBB)); + while (contains(PriorMBB)) { + TopMBB = PriorMBB; + if (TopMBB == Begin) break; + PriorMBB = prior(MachineFunction::iterator(TopMBB)); + } + } + return TopMBB; +} + +MachineBasicBlock *MachineLoop::getBottomBlock() { + MachineBasicBlock *BotMBB = getHeader(); + MachineFunction::iterator End = BotMBB->getParent()->end(); + if (BotMBB != prior(End)) { + MachineBasicBlock *NextMBB = next(MachineFunction::iterator(BotMBB)); + while (contains(NextMBB)) { + BotMBB = NextMBB; + if (BotMBB == next(MachineFunction::iterator(BotMBB))) break; + NextMBB = next(MachineFunction::iterator(BotMBB)); + } + } + return BotMBB; +} diff --git a/libclamav/c++/llvm/lib/CodeGen/MachineModuleInfo.cpp b/libclamav/c++/llvm/lib/CodeGen/MachineModuleInfo.cpp new file mode 100644 index 000000000..ed5bb5e54 --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/MachineModuleInfo.cpp @@ -0,0 +1,295 @@ +//===-- llvm/CodeGen/MachineModuleInfo.cpp ----------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/CodeGen/MachineModuleInfo.h" + +#include "llvm/Constants.h" +#include "llvm/Analysis/ValueTracking.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetOptions.h" +#include "llvm/DerivedTypes.h" +#include "llvm/GlobalVariable.h" +#include "llvm/Intrinsics.h" +#include "llvm/Instructions.h" +#include "llvm/Module.h" +#include "llvm/Support/Dwarf.h" +#include "llvm/Support/ErrorHandling.h" +using namespace llvm; +using namespace llvm::dwarf; + +// Handle the Pass registration stuff necessary to use TargetData's. +static RegisterPass +X("machinemoduleinfo", "Module Information"); +char MachineModuleInfo::ID = 0; + +// Out of line virtual method. +MachineModuleInfoImpl::~MachineModuleInfoImpl() {} + +//===----------------------------------------------------------------------===// + +MachineModuleInfo::MachineModuleInfo() +: ImmutablePass(&ID) +, ObjFileMMI(0) +, CallsEHReturn(0) +, CallsUnwindInit(0) +, DbgInfoAvailable(false) { + // Always emit some info, by default "no personality" info. + Personalities.push_back(NULL); +} + +MachineModuleInfo::~MachineModuleInfo() { + delete ObjFileMMI; +} + +/// doInitialization - Initialize the state for a new module. +/// +bool MachineModuleInfo::doInitialization() { + return false; +} + +/// doFinalization - Tear down the state after completion of a module. +/// +bool MachineModuleInfo::doFinalization() { + return false; +} + +/// EndFunction - Discard function meta information. +/// +void MachineModuleInfo::EndFunction() { + // Clean up frame info. + FrameMoves.clear(); + + // Clean up exception info. + LandingPads.clear(); + TypeInfos.clear(); + FilterIds.clear(); + FilterEnds.clear(); + CallsEHReturn = 0; + CallsUnwindInit = 0; + VariableDbgInfo.clear(); +} + +/// AnalyzeModule - Scan the module for global debug information. +/// +void MachineModuleInfo::AnalyzeModule(Module &M) { + // Insert functions in the llvm.used array (but not llvm.compiler.used) into + // UsedFunctions. + GlobalVariable *GV = M.getGlobalVariable("llvm.used"); + if (!GV || !GV->hasInitializer()) return; + + // Should be an array of 'i8*'. + ConstantArray *InitList = dyn_cast(GV->getInitializer()); + if (InitList == 0) return; + + for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i) + if (Function *F = + dyn_cast(InitList->getOperand(i)->stripPointerCasts())) + UsedFunctions.insert(F); +} + +//===-EH-------------------------------------------------------------------===// + +/// getOrCreateLandingPadInfo - Find or create an LandingPadInfo for the +/// specified MachineBasicBlock. +LandingPadInfo &MachineModuleInfo::getOrCreateLandingPadInfo + (MachineBasicBlock *LandingPad) { + unsigned N = LandingPads.size(); + for (unsigned i = 0; i < N; ++i) { + LandingPadInfo &LP = LandingPads[i]; + if (LP.LandingPadBlock == LandingPad) + return LP; + } + + LandingPads.push_back(LandingPadInfo(LandingPad)); + return LandingPads[N]; +} + +/// addInvoke - Provide the begin and end labels of an invoke style call and +/// associate it with a try landing pad block. +void MachineModuleInfo::addInvoke(MachineBasicBlock *LandingPad, + unsigned BeginLabel, unsigned EndLabel) { + LandingPadInfo &LP = getOrCreateLandingPadInfo(LandingPad); + LP.BeginLabels.push_back(BeginLabel); + LP.EndLabels.push_back(EndLabel); +} + +/// addLandingPad - Provide the label of a try LandingPad block. +/// +unsigned MachineModuleInfo::addLandingPad(MachineBasicBlock *LandingPad) { + unsigned LandingPadLabel = NextLabelID(); + LandingPadInfo &LP = getOrCreateLandingPadInfo(LandingPad); + LP.LandingPadLabel = LandingPadLabel; + return LandingPadLabel; +} + +/// addPersonality - Provide the personality function for the exception +/// information. +void MachineModuleInfo::addPersonality(MachineBasicBlock *LandingPad, + Function *Personality) { + LandingPadInfo &LP = getOrCreateLandingPadInfo(LandingPad); + LP.Personality = Personality; + + for (unsigned i = 0; i < Personalities.size(); ++i) + if (Personalities[i] == Personality) + return; + + // If this is the first personality we're adding go + // ahead and add it at the beginning. + if (Personalities[0] == NULL) + Personalities[0] = Personality; + else + Personalities.push_back(Personality); +} + +/// addCatchTypeInfo - Provide the catch typeinfo for a landing pad. +/// +void MachineModuleInfo::addCatchTypeInfo(MachineBasicBlock *LandingPad, + std::vector &TyInfo) { + LandingPadInfo &LP = getOrCreateLandingPadInfo(LandingPad); + for (unsigned N = TyInfo.size(); N; --N) + LP.TypeIds.push_back(getTypeIDFor(TyInfo[N - 1])); +} + +/// addFilterTypeInfo - Provide the filter typeinfo for a landing pad. +/// +void MachineModuleInfo::addFilterTypeInfo(MachineBasicBlock *LandingPad, + std::vector &TyInfo) { + LandingPadInfo &LP = getOrCreateLandingPadInfo(LandingPad); + std::vector IdsInFilter(TyInfo.size()); + for (unsigned I = 0, E = TyInfo.size(); I != E; ++I) + IdsInFilter[I] = getTypeIDFor(TyInfo[I]); + LP.TypeIds.push_back(getFilterIDFor(IdsInFilter)); +} + +/// addCleanup - Add a cleanup action for a landing pad. +/// +void MachineModuleInfo::addCleanup(MachineBasicBlock *LandingPad) { + LandingPadInfo &LP = getOrCreateLandingPadInfo(LandingPad); + LP.TypeIds.push_back(0); +} + +/// TidyLandingPads - Remap landing pad labels and remove any deleted landing +/// pads. +void MachineModuleInfo::TidyLandingPads() { + for (unsigned i = 0; i != LandingPads.size(); ) { + LandingPadInfo &LandingPad = LandingPads[i]; + LandingPad.LandingPadLabel = MappedLabel(LandingPad.LandingPadLabel); + + // Special case: we *should* emit LPs with null LP MBB. This indicates + // "nounwind" case. + if (!LandingPad.LandingPadLabel && LandingPad.LandingPadBlock) { + LandingPads.erase(LandingPads.begin() + i); + continue; + } + + for (unsigned j=0; j != LandingPads[i].BeginLabels.size(); ) { + unsigned BeginLabel = MappedLabel(LandingPad.BeginLabels[j]); + unsigned EndLabel = MappedLabel(LandingPad.EndLabels[j]); + + if (!BeginLabel || !EndLabel) { + LandingPad.BeginLabels.erase(LandingPad.BeginLabels.begin() + j); + LandingPad.EndLabels.erase(LandingPad.EndLabels.begin() + j); + continue; + } + + LandingPad.BeginLabels[j] = BeginLabel; + LandingPad.EndLabels[j] = EndLabel; + ++j; + } + + // Remove landing pads with no try-ranges. + if (LandingPads[i].BeginLabels.empty()) { + LandingPads.erase(LandingPads.begin() + i); + continue; + } + + // If there is no landing pad, ensure that the list of typeids is empty. + // If the only typeid is a cleanup, this is the same as having no typeids. + if (!LandingPad.LandingPadBlock || + (LandingPad.TypeIds.size() == 1 && !LandingPad.TypeIds[0])) + LandingPad.TypeIds.clear(); + + ++i; + } +} + +/// getTypeIDFor - Return the type id for the specified typeinfo. This is +/// function wide. +unsigned MachineModuleInfo::getTypeIDFor(GlobalVariable *TI) { + for (unsigned i = 0, N = TypeInfos.size(); i != N; ++i) + if (TypeInfos[i] == TI) return i + 1; + + TypeInfos.push_back(TI); + return TypeInfos.size(); +} + +/// getFilterIDFor - Return the filter id for the specified typeinfos. This is +/// function wide. +int MachineModuleInfo::getFilterIDFor(std::vector &TyIds) { + // If the new filter coincides with the tail of an existing filter, then + // re-use the existing filter. Folding filters more than this requires + // re-ordering filters and/or their elements - probably not worth it. + for (std::vector::iterator I = FilterEnds.begin(), + E = FilterEnds.end(); I != E; ++I) { + unsigned i = *I, j = TyIds.size(); + + while (i && j) + if (FilterIds[--i] != TyIds[--j]) + goto try_next; + + if (!j) + // The new filter coincides with range [i, end) of the existing filter. + return -(1 + i); + +try_next:; + } + + // Add the new filter. + int FilterID = -(1 + FilterIds.size()); + FilterIds.reserve(FilterIds.size() + TyIds.size() + 1); + for (unsigned I = 0, N = TyIds.size(); I != N; ++I) + FilterIds.push_back(TyIds[I]); + FilterEnds.push_back(FilterIds.size()); + FilterIds.push_back(0); // terminator + return FilterID; +} + +/// getPersonality - Return the personality function for the current function. +Function *MachineModuleInfo::getPersonality() const { + // FIXME: Until PR1414 will be fixed, we're using 1 personality function per + // function + return !LandingPads.empty() ? LandingPads[0].Personality : NULL; +} + +/// getPersonalityIndex - Return unique index for current personality +/// function. NULL/first personality function should always get zero index. +unsigned MachineModuleInfo::getPersonalityIndex() const { + const Function* Personality = NULL; + + // Scan landing pads. If there is at least one non-NULL personality - use it. + for (unsigned i = 0; i != LandingPads.size(); ++i) + if (LandingPads[i].Personality) { + Personality = LandingPads[i].Personality; + break; + } + + for (unsigned i = 0; i < Personalities.size(); ++i) { + if (Personalities[i] == Personality) + return i; + } + + // This will happen if the current personality function is + // in the zero index. + return 0; +} + diff --git a/libclamav/c++/llvm/lib/CodeGen/MachineModuleInfoImpls.cpp b/libclamav/c++/llvm/lib/CodeGen/MachineModuleInfoImpls.cpp new file mode 100644 index 000000000..7a6292910 --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/MachineModuleInfoImpls.cpp @@ -0,0 +1,45 @@ +//===-- llvm/CodeGen/MachineModuleInfoImpls.cpp ---------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements object-file format specific implementations of +// MachineModuleInfoImpl. +// +//===----------------------------------------------------------------------===// + +#include "llvm/CodeGen/MachineModuleInfoImpls.h" +#include "llvm/MC/MCSymbol.h" +using namespace llvm; + +//===----------------------------------------------------------------------===// +// MachineModuleInfoMachO +//===----------------------------------------------------------------------===// + +// Out of line virtual method. +void MachineModuleInfoMachO::Anchor() {} + + +static int SortSymbolPair(const void *LHS, const void *RHS) { + const MCSymbol *LHSS = + ((const std::pair*)LHS)->first; + const MCSymbol *RHSS = + ((const std::pair*)RHS)->first; + return LHSS->getName().compare(RHSS->getName()); +} + +/// GetSortedStubs - Return the entries from a DenseMap in a deterministic +/// sorted orer. +MachineModuleInfoMachO::SymbolListTy +MachineModuleInfoMachO::GetSortedStubs(const DenseMap &Map) { + MachineModuleInfoMachO::SymbolListTy List(Map.begin(), Map.end()); + if (!List.empty()) + qsort(&List[0], List.size(), sizeof(List[0]), SortSymbolPair); + return List; +} + diff --git a/libclamav/c++/llvm/lib/CodeGen/MachinePassRegistry.cpp b/libclamav/c++/llvm/lib/CodeGen/MachinePassRegistry.cpp new file mode 100644 index 000000000..9f4ef1287 --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/MachinePassRegistry.cpp @@ -0,0 +1,41 @@ +//===-- CodeGen/MachineInstr.cpp ------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the machine function pass registry for register allocators +// and instruction schedulers. +// +//===----------------------------------------------------------------------===// + +#include "llvm/CodeGen/MachinePassRegistry.h" + +using namespace llvm; + + +/// Add - Adds a function pass to the registration list. +/// +void MachinePassRegistry::Add(MachinePassRegistryNode *Node) { + Node->setNext(List); + List = Node; + if (Listener) Listener->NotifyAdd(Node->getName(), + Node->getCtor(), + Node->getDescription()); +} + + +/// Remove - Removes a function pass from the registration list. +/// +void MachinePassRegistry::Remove(MachinePassRegistryNode *Node) { + for (MachinePassRegistryNode **I = &List; *I; I = (*I)->getNextAddress()) { + if (*I == Node) { + if (Listener) Listener->NotifyRemove(Node->getName()); + *I = (*I)->getNext(); + break; + } + } +} diff --git a/libclamav/c++/llvm/lib/CodeGen/MachineRegisterInfo.cpp b/libclamav/c++/llvm/lib/CodeGen/MachineRegisterInfo.cpp new file mode 100644 index 000000000..b31973e04 --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/MachineRegisterInfo.cpp @@ -0,0 +1,125 @@ +//===-- lib/Codegen/MachineRegisterInfo.cpp -------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Implementation of the MachineRegisterInfo class. +// +//===----------------------------------------------------------------------===// + +#include "llvm/CodeGen/MachineRegisterInfo.h" +using namespace llvm; + +MachineRegisterInfo::MachineRegisterInfo(const TargetRegisterInfo &TRI) { + VRegInfo.reserve(256); + RegAllocHints.reserve(256); + RegClass2VRegMap.resize(TRI.getNumRegClasses()+1); // RC ID starts at 1. + UsedPhysRegs.resize(TRI.getNumRegs()); + + // Create the physreg use/def lists. + PhysRegUseDefLists = new MachineOperand*[TRI.getNumRegs()]; + memset(PhysRegUseDefLists, 0, sizeof(MachineOperand*)*TRI.getNumRegs()); +} + +MachineRegisterInfo::~MachineRegisterInfo() { +#ifndef NDEBUG + for (unsigned i = 0, e = VRegInfo.size(); i != e; ++i) + assert(VRegInfo[i].second == 0 && "Vreg use list non-empty still?"); + for (unsigned i = 0, e = UsedPhysRegs.size(); i != e; ++i) + assert(!PhysRegUseDefLists[i] && + "PhysRegUseDefLists has entries after all instructions are deleted"); +#endif + delete [] PhysRegUseDefLists; +} + +/// setRegClass - Set the register class of the specified virtual register. +/// +void +MachineRegisterInfo::setRegClass(unsigned Reg, const TargetRegisterClass *RC) { + unsigned VR = Reg; + Reg -= TargetRegisterInfo::FirstVirtualRegister; + assert(Reg < VRegInfo.size() && "Invalid vreg!"); + const TargetRegisterClass *OldRC = VRegInfo[Reg].first; + VRegInfo[Reg].first = RC; + + // Remove from old register class's vregs list. This may be slow but + // fortunately this operation is rarely needed. + std::vector &VRegs = RegClass2VRegMap[OldRC->getID()]; + std::vector::iterator I=std::find(VRegs.begin(), VRegs.end(), VR); + VRegs.erase(I); + + // Add to new register class's vregs list. + RegClass2VRegMap[RC->getID()].push_back(VR); +} + +/// createVirtualRegister - Create and return a new virtual register in the +/// function with the specified register class. +/// +unsigned +MachineRegisterInfo::createVirtualRegister(const TargetRegisterClass *RegClass){ + assert(RegClass && "Cannot create register without RegClass!"); + // Add a reg, but keep track of whether the vector reallocated or not. + void *ArrayBase = VRegInfo.empty() ? 0 : &VRegInfo[0]; + VRegInfo.push_back(std::make_pair(RegClass, (MachineOperand*)0)); + RegAllocHints.push_back(std::make_pair(0, 0)); + + if (!((&VRegInfo[0] == ArrayBase || VRegInfo.size() == 1))) + // The vector reallocated, handle this now. + HandleVRegListReallocation(); + unsigned VR = getLastVirtReg(); + RegClass2VRegMap[RegClass->getID()].push_back(VR); + return VR; +} + +/// HandleVRegListReallocation - We just added a virtual register to the +/// VRegInfo info list and it reallocated. Update the use/def lists info +/// pointers. +void MachineRegisterInfo::HandleVRegListReallocation() { + // The back pointers for the vreg lists point into the previous vector. + // Update them to point to their correct slots. + for (unsigned i = 0, e = VRegInfo.size(); i != e; ++i) { + MachineOperand *List = VRegInfo[i].second; + if (!List) continue; + // Update the back-pointer to be accurate once more. + List->Contents.Reg.Prev = &VRegInfo[i].second; + } +} + +/// replaceRegWith - Replace all instances of FromReg with ToReg in the +/// machine function. This is like llvm-level X->replaceAllUsesWith(Y), +/// except that it also changes any definitions of the register as well. +void MachineRegisterInfo::replaceRegWith(unsigned FromReg, unsigned ToReg) { + assert(FromReg != ToReg && "Cannot replace a reg with itself"); + + // TODO: This could be more efficient by bulk changing the operands. + for (reg_iterator I = reg_begin(FromReg), E = reg_end(); I != E; ) { + MachineOperand &O = I.getOperand(); + ++I; + O.setReg(ToReg); + } +} + + +/// getVRegDef - Return the machine instr that defines the specified virtual +/// register or null if none is found. This assumes that the code is in SSA +/// form, so there should only be one definition. +MachineInstr *MachineRegisterInfo::getVRegDef(unsigned Reg) const { + assert(Reg-TargetRegisterInfo::FirstVirtualRegister < VRegInfo.size() && + "Invalid vreg!"); + // Since we are in SSA form, we can use the first definition. + if (!def_empty(Reg)) + return &*def_begin(Reg); + return 0; +} + + +#ifndef NDEBUG +void MachineRegisterInfo::dumpUses(unsigned Reg) const { + for (use_iterator I = use_begin(Reg), E = use_end(); I != E; ++I) + I.getOperand().getParent()->dump(); +} +#endif diff --git a/libclamav/c++/llvm/lib/CodeGen/MachineSink.cpp b/libclamav/c++/llvm/lib/CodeGen/MachineSink.cpp new file mode 100644 index 000000000..e04073884 --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/MachineSink.cpp @@ -0,0 +1,280 @@ +//===-- MachineSink.cpp - Sinking for machine instructions ----------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This pass moves instructions into successor blocks, when possible, so that +// they aren't executed on paths where their results aren't needed. +// +// This pass is not intended to be a replacement or a complete alternative +// for an LLVM-IR-level sinking pass. It is only designed to sink simple +// constructs that are not exposed before lowering and instruction selection. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "machine-sink" +#include "llvm/CodeGen/Passes.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/MachineDominators.h" +#include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +STATISTIC(NumSunk, "Number of machine instructions sunk"); + +namespace { + class MachineSinking : public MachineFunctionPass { + const TargetInstrInfo *TII; + const TargetRegisterInfo *TRI; + MachineRegisterInfo *RegInfo; // Machine register information + MachineDominatorTree *DT; // Machine dominator tree + AliasAnalysis *AA; + BitVector AllocatableSet; // Which physregs are allocatable? + + public: + static char ID; // Pass identification + MachineSinking() : MachineFunctionPass(&ID) {} + + virtual bool runOnMachineFunction(MachineFunction &MF); + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesCFG(); + MachineFunctionPass::getAnalysisUsage(AU); + AU.addRequired(); + AU.addRequired(); + AU.addPreserved(); + } + private: + bool ProcessBlock(MachineBasicBlock &MBB); + bool SinkInstruction(MachineInstr *MI, bool &SawStore); + bool AllUsesDominatedByBlock(unsigned Reg, MachineBasicBlock *MBB) const; + }; +} // end anonymous namespace + +char MachineSinking::ID = 0; +static RegisterPass +X("machine-sink", "Machine code sinking"); + +FunctionPass *llvm::createMachineSinkingPass() { return new MachineSinking(); } + +/// AllUsesDominatedByBlock - Return true if all uses of the specified register +/// occur in blocks dominated by the specified block. +bool MachineSinking::AllUsesDominatedByBlock(unsigned Reg, + MachineBasicBlock *MBB) const { + assert(TargetRegisterInfo::isVirtualRegister(Reg) && + "Only makes sense for vregs"); + for (MachineRegisterInfo::use_iterator I = RegInfo->use_begin(Reg), + E = RegInfo->use_end(); I != E; ++I) { + // Determine the block of the use. + MachineInstr *UseInst = &*I; + MachineBasicBlock *UseBlock = UseInst->getParent(); + if (UseInst->getOpcode() == TargetInstrInfo::PHI) { + // PHI nodes use the operand in the predecessor block, not the block with + // the PHI. + UseBlock = UseInst->getOperand(I.getOperandNo()+1).getMBB(); + } + // Check that it dominates. + if (!DT->dominates(MBB, UseBlock)) + return false; + } + return true; +} + +bool MachineSinking::runOnMachineFunction(MachineFunction &MF) { + DEBUG(errs() << "******** Machine Sinking ********\n"); + + const TargetMachine &TM = MF.getTarget(); + TII = TM.getInstrInfo(); + TRI = TM.getRegisterInfo(); + RegInfo = &MF.getRegInfo(); + DT = &getAnalysis(); + AA = &getAnalysis(); + AllocatableSet = TRI->getAllocatableSet(MF); + + bool EverMadeChange = false; + + while (1) { + bool MadeChange = false; + + // Process all basic blocks. + for (MachineFunction::iterator I = MF.begin(), E = MF.end(); + I != E; ++I) + MadeChange |= ProcessBlock(*I); + + // If this iteration over the code changed anything, keep iterating. + if (!MadeChange) break; + EverMadeChange = true; + } + return EverMadeChange; +} + +bool MachineSinking::ProcessBlock(MachineBasicBlock &MBB) { + // Can't sink anything out of a block that has less than two successors. + if (MBB.succ_size() <= 1 || MBB.empty()) return false; + + bool MadeChange = false; + + // Walk the basic block bottom-up. Remember if we saw a store. + MachineBasicBlock::iterator I = MBB.end(); + --I; + bool ProcessedBegin, SawStore = false; + do { + MachineInstr *MI = I; // The instruction to sink. + + // Predecrement I (if it's not begin) so that it isn't invalidated by + // sinking. + ProcessedBegin = I == MBB.begin(); + if (!ProcessedBegin) + --I; + + if (SinkInstruction(MI, SawStore)) + ++NumSunk, MadeChange = true; + + // If we just processed the first instruction in the block, we're done. + } while (!ProcessedBegin); + + return MadeChange; +} + +/// SinkInstruction - Determine whether it is safe to sink the specified machine +/// instruction out of its current block into a successor. +bool MachineSinking::SinkInstruction(MachineInstr *MI, bool &SawStore) { + // Check if it's safe to move the instruction. + if (!MI->isSafeToMove(TII, SawStore, AA)) + return false; + + // FIXME: This should include support for sinking instructions within the + // block they are currently in to shorten the live ranges. We often get + // instructions sunk into the top of a large block, but it would be better to + // also sink them down before their first use in the block. This xform has to + // be careful not to *increase* register pressure though, e.g. sinking + // "x = y + z" down if it kills y and z would increase the live ranges of y + // and z and only shrink the live range of x. + + // Loop over all the operands of the specified instruction. If there is + // anything we can't handle, bail out. + MachineBasicBlock *ParentBlock = MI->getParent(); + + // SuccToSinkTo - This is the successor to sink this instruction to, once we + // decide. + MachineBasicBlock *SuccToSinkTo = 0; + + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + const MachineOperand &MO = MI->getOperand(i); + if (!MO.isReg()) continue; // Ignore non-register operands. + + unsigned Reg = MO.getReg(); + if (Reg == 0) continue; + + if (TargetRegisterInfo::isPhysicalRegister(Reg)) { + if (MO.isUse()) { + // If the physreg has no defs anywhere, it's just an ambient register + // and we can freely move its uses. Alternatively, if it's allocatable, + // it could get allocated to something with a def during allocation. + if (!RegInfo->def_empty(Reg)) + return false; + if (AllocatableSet.test(Reg)) + return false; + // Check for a def among the register's aliases too. + for (const unsigned *Alias = TRI->getAliasSet(Reg); *Alias; ++Alias) { + unsigned AliasReg = *Alias; + if (!RegInfo->def_empty(AliasReg)) + return false; + if (AllocatableSet.test(AliasReg)) + return false; + } + } else if (!MO.isDead()) { + // A def that isn't dead. We can't move it. + return false; + } + } else { + // Virtual register uses are always safe to sink. + if (MO.isUse()) continue; + + // If it's not safe to move defs of the register class, then abort. + if (!TII->isSafeToMoveRegClassDefs(RegInfo->getRegClass(Reg))) + return false; + + // FIXME: This picks a successor to sink into based on having one + // successor that dominates all the uses. However, there are cases where + // sinking can happen but where the sink point isn't a successor. For + // example: + // x = computation + // if () {} else {} + // use x + // the instruction could be sunk over the whole diamond for the + // if/then/else (or loop, etc), allowing it to be sunk into other blocks + // after that. + + // Virtual register defs can only be sunk if all their uses are in blocks + // dominated by one of the successors. + if (SuccToSinkTo) { + // If a previous operand picked a block to sink to, then this operand + // must be sinkable to the same block. + if (!AllUsesDominatedByBlock(Reg, SuccToSinkTo)) + return false; + continue; + } + + // Otherwise, we should look at all the successors and decide which one + // we should sink to. + for (MachineBasicBlock::succ_iterator SI = ParentBlock->succ_begin(), + E = ParentBlock->succ_end(); SI != E; ++SI) { + if (AllUsesDominatedByBlock(Reg, *SI)) { + SuccToSinkTo = *SI; + break; + } + } + + // If we couldn't find a block to sink to, ignore this instruction. + if (SuccToSinkTo == 0) + return false; + } + } + + // If there are no outputs, it must have side-effects. + if (SuccToSinkTo == 0) + return false; + + // It's not safe to sink instructions to EH landing pad. Control flow into + // landing pad is implicitly defined. + if (SuccToSinkTo->isLandingPad()) + return false; + + // It is not possible to sink an instruction into its own block. This can + // happen with loops. + if (MI->getParent() == SuccToSinkTo) + return false; + + DEBUG(errs() << "Sink instr " << *MI); + DEBUG(errs() << "to block " << *SuccToSinkTo); + + // If the block has multiple predecessors, this would introduce computation on + // a path that it doesn't already exist. We could split the critical edge, + // but for now we just punt. + // FIXME: Split critical edges if not backedges. + if (SuccToSinkTo->pred_size() > 1) { + DEBUG(errs() << " *** PUNTING: Critical edge found\n"); + return false; + } + + // Determine where to insert into. Skip phi nodes. + MachineBasicBlock::iterator InsertPos = SuccToSinkTo->begin(); + while (InsertPos != SuccToSinkTo->end() && + InsertPos->getOpcode() == TargetInstrInfo::PHI) + ++InsertPos; + + // Move the instruction. + SuccToSinkTo->splice(InsertPos, ParentBlock, MI, + ++MachineBasicBlock::iterator(MI)); + return true; +} diff --git a/libclamav/c++/llvm/lib/CodeGen/MachineVerifier.cpp b/libclamav/c++/llvm/lib/CodeGen/MachineVerifier.cpp new file mode 100644 index 000000000..d9f4c997b --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/MachineVerifier.cpp @@ -0,0 +1,995 @@ +//===-- MachineVerifier.cpp - Machine Code Verifier -------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Pass to verify generated machine code. The following is checked: +// +// Operand counts: All explicit operands must be present. +// +// Register classes: All physical and virtual register operands must be +// compatible with the register class required by the instruction descriptor. +// +// Register live intervals: Registers must be defined only once, and must be +// defined before use. +// +// The machine code verifier is enabled from LLVMTargetMachine.cpp with the +// command-line option -verify-machineinstrs, or by defining the environment +// variable LLVM_VERIFY_MACHINEINSTRS to the name of a file that will receive +// the verifier errors. +//===----------------------------------------------------------------------===// + +#include "llvm/Function.h" +#include "llvm/CodeGen/LiveVariables.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineMemOperand.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/ADT/DenseSet.h" +#include "llvm/ADT/SetOperations.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +namespace { + struct MachineVerifier { + + MachineVerifier(Pass *pass, bool allowDoubleDefs) : + PASS(pass), + allowVirtDoubleDefs(allowDoubleDefs), + allowPhysDoubleDefs(allowDoubleDefs), + OutFileName(getenv("LLVM_VERIFY_MACHINEINSTRS")) + {} + + bool runOnMachineFunction(MachineFunction &MF); + + Pass *const PASS; + const bool allowVirtDoubleDefs; + const bool allowPhysDoubleDefs; + + const char *const OutFileName; + raw_ostream *OS; + const MachineFunction *MF; + const TargetMachine *TM; + const TargetRegisterInfo *TRI; + const MachineRegisterInfo *MRI; + + unsigned foundErrors; + + typedef SmallVector RegVector; + typedef DenseSet RegSet; + typedef DenseMap RegMap; + + BitVector regsReserved; + RegSet regsLive; + RegVector regsDefined, regsDead, regsKilled; + RegSet regsLiveInButUnused; + + // Add Reg and any sub-registers to RV + void addRegWithSubRegs(RegVector &RV, unsigned Reg) { + RV.push_back(Reg); + if (TargetRegisterInfo::isPhysicalRegister(Reg)) + for (const unsigned *R = TRI->getSubRegisters(Reg); *R; R++) + RV.push_back(*R); + } + + struct BBInfo { + // Is this MBB reachable from the MF entry point? + bool reachable; + + // Vregs that must be live in because they are used without being + // defined. Map value is the user. + RegMap vregsLiveIn; + + // Vregs that must be dead in because they are defined without being + // killed first. Map value is the defining instruction. + RegMap vregsDeadIn; + + // Regs killed in MBB. They may be defined again, and will then be in both + // regsKilled and regsLiveOut. + RegSet regsKilled; + + // Regs defined in MBB and live out. Note that vregs passing through may + // be live out without being mentioned here. + RegSet regsLiveOut; + + // Vregs that pass through MBB untouched. This set is disjoint from + // regsKilled and regsLiveOut. + RegSet vregsPassed; + + // Vregs that must pass through MBB because they are needed by a successor + // block. This set is disjoint from regsLiveOut. + RegSet vregsRequired; + + BBInfo() : reachable(false) {} + + // Add register to vregsPassed if it belongs there. Return true if + // anything changed. + bool addPassed(unsigned Reg) { + if (!TargetRegisterInfo::isVirtualRegister(Reg)) + return false; + if (regsKilled.count(Reg) || regsLiveOut.count(Reg)) + return false; + return vregsPassed.insert(Reg).second; + } + + // Same for a full set. + bool addPassed(const RegSet &RS) { + bool changed = false; + for (RegSet::const_iterator I = RS.begin(), E = RS.end(); I != E; ++I) + if (addPassed(*I)) + changed = true; + return changed; + } + + // Add register to vregsRequired if it belongs there. Return true if + // anything changed. + bool addRequired(unsigned Reg) { + if (!TargetRegisterInfo::isVirtualRegister(Reg)) + return false; + if (regsLiveOut.count(Reg)) + return false; + return vregsRequired.insert(Reg).second; + } + + // Same for a full set. + bool addRequired(const RegSet &RS) { + bool changed = false; + for (RegSet::const_iterator I = RS.begin(), E = RS.end(); I != E; ++I) + if (addRequired(*I)) + changed = true; + return changed; + } + + // Same for a full map. + bool addRequired(const RegMap &RM) { + bool changed = false; + for (RegMap::const_iterator I = RM.begin(), E = RM.end(); I != E; ++I) + if (addRequired(I->first)) + changed = true; + return changed; + } + + // Live-out registers are either in regsLiveOut or vregsPassed. + bool isLiveOut(unsigned Reg) const { + return regsLiveOut.count(Reg) || vregsPassed.count(Reg); + } + }; + + // Extra register info per MBB. + DenseMap MBBInfoMap; + + bool isReserved(unsigned Reg) { + return Reg < regsReserved.size() && regsReserved.test(Reg); + } + + // Analysis information if available + LiveVariables *LiveVars; + + void visitMachineFunctionBefore(); + void visitMachineBasicBlockBefore(const MachineBasicBlock *MBB); + void visitMachineInstrBefore(const MachineInstr *MI); + void visitMachineOperand(const MachineOperand *MO, unsigned MONum); + void visitMachineInstrAfter(const MachineInstr *MI); + void visitMachineBasicBlockAfter(const MachineBasicBlock *MBB); + void visitMachineFunctionAfter(); + + void report(const char *msg, const MachineFunction *MF); + void report(const char *msg, const MachineBasicBlock *MBB); + void report(const char *msg, const MachineInstr *MI); + void report(const char *msg, const MachineOperand *MO, unsigned MONum); + + void markReachable(const MachineBasicBlock *MBB); + void calcMaxRegsPassed(); + void calcMinRegsPassed(); + void checkPHIOps(const MachineBasicBlock *MBB); + + void calcRegsRequired(); + void verifyLiveVariables(); + }; + + struct MachineVerifierPass : public MachineFunctionPass { + static char ID; // Pass ID, replacement for typeid + bool AllowDoubleDefs; + + explicit MachineVerifierPass(bool allowDoubleDefs = false) + : MachineFunctionPass(&ID), + AllowDoubleDefs(allowDoubleDefs) {} + + void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + MachineFunctionPass::getAnalysisUsage(AU); + } + + bool runOnMachineFunction(MachineFunction &MF) { + MF.verify(this, AllowDoubleDefs); + return false; + } + }; + +} + +char MachineVerifierPass::ID = 0; +static RegisterPass +MachineVer("machineverifier", "Verify generated machine code"); +static const PassInfo *const MachineVerifyID = &MachineVer; + +FunctionPass *llvm::createMachineVerifierPass(bool allowPhysDoubleDefs) { + return new MachineVerifierPass(allowPhysDoubleDefs); +} + +void MachineFunction::verify(Pass *p, bool allowDoubleDefs) const { + MachineVerifier(p, allowDoubleDefs) + .runOnMachineFunction(const_cast(*this)); +} + +bool MachineVerifier::runOnMachineFunction(MachineFunction &MF) { + raw_ostream *OutFile = 0; + if (OutFileName) { + std::string ErrorInfo; + OutFile = new raw_fd_ostream(OutFileName, ErrorInfo, + raw_fd_ostream::F_Append); + if (!ErrorInfo.empty()) { + errs() << "Error opening '" << OutFileName << "': " << ErrorInfo << '\n'; + exit(1); + } + + OS = OutFile; + } else { + OS = &errs(); + } + + foundErrors = 0; + + this->MF = &MF; + TM = &MF.getTarget(); + TRI = TM->getRegisterInfo(); + MRI = &MF.getRegInfo(); + + if (PASS) { + LiveVars = PASS->getAnalysisIfAvailable(); + } else { + LiveVars = NULL; + } + + visitMachineFunctionBefore(); + for (MachineFunction::const_iterator MFI = MF.begin(), MFE = MF.end(); + MFI!=MFE; ++MFI) { + visitMachineBasicBlockBefore(MFI); + for (MachineBasicBlock::const_iterator MBBI = MFI->begin(), + MBBE = MFI->end(); MBBI != MBBE; ++MBBI) { + visitMachineInstrBefore(MBBI); + for (unsigned I = 0, E = MBBI->getNumOperands(); I != E; ++I) + visitMachineOperand(&MBBI->getOperand(I), I); + visitMachineInstrAfter(MBBI); + } + visitMachineBasicBlockAfter(MFI); + } + visitMachineFunctionAfter(); + + if (OutFile) + delete OutFile; + else if (foundErrors) + llvm_report_error("Found "+Twine(foundErrors)+" machine code errors."); + + // Clean up. + regsLive.clear(); + regsDefined.clear(); + regsDead.clear(); + regsKilled.clear(); + regsLiveInButUnused.clear(); + MBBInfoMap.clear(); + + return false; // no changes +} + +void MachineVerifier::report(const char *msg, const MachineFunction *MF) { + assert(MF); + *OS << '\n'; + if (!foundErrors++) + MF->print(*OS); + *OS << "*** Bad machine code: " << msg << " ***\n" + << "- function: " << MF->getFunction()->getNameStr() << "\n"; +} + +void MachineVerifier::report(const char *msg, const MachineBasicBlock *MBB) { + assert(MBB); + report(msg, MBB->getParent()); + *OS << "- basic block: " << MBB->getName() + << " " << (void*)MBB + << " (BB#" << MBB->getNumber() << ")\n"; +} + +void MachineVerifier::report(const char *msg, const MachineInstr *MI) { + assert(MI); + report(msg, MI->getParent()); + *OS << "- instruction: "; + MI->print(*OS, TM); +} + +void MachineVerifier::report(const char *msg, + const MachineOperand *MO, unsigned MONum) { + assert(MO); + report(msg, MO->getParent()); + *OS << "- operand " << MONum << ": "; + MO->print(*OS, TM); + *OS << "\n"; +} + +void MachineVerifier::markReachable(const MachineBasicBlock *MBB) { + BBInfo &MInfo = MBBInfoMap[MBB]; + if (!MInfo.reachable) { + MInfo.reachable = true; + for (MachineBasicBlock::const_succ_iterator SuI = MBB->succ_begin(), + SuE = MBB->succ_end(); SuI != SuE; ++SuI) + markReachable(*SuI); + } +} + +void MachineVerifier::visitMachineFunctionBefore() { + regsReserved = TRI->getReservedRegs(*MF); + + // A sub-register of a reserved register is also reserved + for (int Reg = regsReserved.find_first(); Reg>=0; + Reg = regsReserved.find_next(Reg)) { + for (const unsigned *Sub = TRI->getSubRegisters(Reg); *Sub; ++Sub) { + // FIXME: This should probably be: + // assert(regsReserved.test(*Sub) && "Non-reserved sub-register"); + regsReserved.set(*Sub); + } + } + markReachable(&MF->front()); +} + +// Does iterator point to a and b as the first two elements? +bool matchPair(MachineBasicBlock::const_succ_iterator i, + const MachineBasicBlock *a, const MachineBasicBlock *b) { + if (*i == a) + return *++i == b; + if (*i == b) + return *++i == a; + return false; +} + +void +MachineVerifier::visitMachineBasicBlockBefore(const MachineBasicBlock *MBB) { + const TargetInstrInfo *TII = MF->getTarget().getInstrInfo(); + + // Start with minimal CFG sanity checks. + MachineFunction::const_iterator MBBI = MBB; + ++MBBI; + if (MBBI != MF->end()) { + // Block is not last in function. + if (!MBB->isSuccessor(MBBI)) { + // Block does not fall through. + if (MBB->empty()) { + report("MBB doesn't fall through but is empty!", MBB); + } + } + if (TII->BlockHasNoFallThrough(*MBB)) { + if (MBB->empty()) { + report("TargetInstrInfo says the block has no fall through, but the " + "block is empty!", MBB); + } else if (!MBB->back().getDesc().isBarrier()) { + report("TargetInstrInfo says the block has no fall through, but the " + "block does not end in a barrier!", MBB); + } + } + } else { + // Block is last in function. + if (MBB->empty()) { + report("MBB is last in function but is empty!", MBB); + } + } + + // Call AnalyzeBranch. If it succeeds, there several more conditions to check. + MachineBasicBlock *TBB = 0, *FBB = 0; + SmallVector Cond; + if (!TII->AnalyzeBranch(*const_cast(MBB), + TBB, FBB, Cond)) { + // Ok, AnalyzeBranch thinks it knows what's going on with this block. Let's + // check whether its answers match up with reality. + if (!TBB && !FBB) { + // Block falls through to its successor. + MachineFunction::const_iterator MBBI = MBB; + ++MBBI; + if (MBBI == MF->end()) { + // It's possible that the block legitimately ends with a noreturn + // call or an unreachable, in which case it won't actually fall + // out the bottom of the function. + } else if (MBB->succ_empty()) { + // It's possible that the block legitimately ends with a noreturn + // call or an unreachable, in which case it won't actuall fall + // out of the block. + } else if (MBB->succ_size() != 1) { + report("MBB exits via unconditional fall-through but doesn't have " + "exactly one CFG successor!", MBB); + } else if (MBB->succ_begin()[0] != MBBI) { + report("MBB exits via unconditional fall-through but its successor " + "differs from its CFG successor!", MBB); + } + if (!MBB->empty() && MBB->back().getDesc().isBarrier()) { + report("MBB exits via unconditional fall-through but ends with a " + "barrier instruction!", MBB); + } + if (!Cond.empty()) { + report("MBB exits via unconditional fall-through but has a condition!", + MBB); + } + } else if (TBB && !FBB && Cond.empty()) { + // Block unconditionally branches somewhere. + if (MBB->succ_size() != 1) { + report("MBB exits via unconditional branch but doesn't have " + "exactly one CFG successor!", MBB); + } else if (MBB->succ_begin()[0] != TBB) { + report("MBB exits via unconditional branch but the CFG " + "successor doesn't match the actual successor!", MBB); + } + if (MBB->empty()) { + report("MBB exits via unconditional branch but doesn't contain " + "any instructions!", MBB); + } else if (!MBB->back().getDesc().isBarrier()) { + report("MBB exits via unconditional branch but doesn't end with a " + "barrier instruction!", MBB); + } else if (!MBB->back().getDesc().isTerminator()) { + report("MBB exits via unconditional branch but the branch isn't a " + "terminator instruction!", MBB); + } + } else if (TBB && !FBB && !Cond.empty()) { + // Block conditionally branches somewhere, otherwise falls through. + MachineFunction::const_iterator MBBI = MBB; + ++MBBI; + if (MBBI == MF->end()) { + report("MBB conditionally falls through out of function!", MBB); + } if (MBB->succ_size() != 2) { + report("MBB exits via conditional branch/fall-through but doesn't have " + "exactly two CFG successors!", MBB); + } else if (!matchPair(MBB->succ_begin(), TBB, MBBI)) { + report("MBB exits via conditional branch/fall-through but the CFG " + "successors don't match the actual successors!", MBB); + } + if (MBB->empty()) { + report("MBB exits via conditional branch/fall-through but doesn't " + "contain any instructions!", MBB); + } else if (MBB->back().getDesc().isBarrier()) { + report("MBB exits via conditional branch/fall-through but ends with a " + "barrier instruction!", MBB); + } else if (!MBB->back().getDesc().isTerminator()) { + report("MBB exits via conditional branch/fall-through but the branch " + "isn't a terminator instruction!", MBB); + } + } else if (TBB && FBB) { + // Block conditionally branches somewhere, otherwise branches + // somewhere else. + if (MBB->succ_size() != 2) { + report("MBB exits via conditional branch/branch but doesn't have " + "exactly two CFG successors!", MBB); + } else if (!matchPair(MBB->succ_begin(), TBB, FBB)) { + report("MBB exits via conditional branch/branch but the CFG " + "successors don't match the actual successors!", MBB); + } + if (MBB->empty()) { + report("MBB exits via conditional branch/branch but doesn't " + "contain any instructions!", MBB); + } else if (!MBB->back().getDesc().isBarrier()) { + report("MBB exits via conditional branch/branch but doesn't end with a " + "barrier instruction!", MBB); + } else if (!MBB->back().getDesc().isTerminator()) { + report("MBB exits via conditional branch/branch but the branch " + "isn't a terminator instruction!", MBB); + } + if (Cond.empty()) { + report("MBB exits via conditinal branch/branch but there's no " + "condition!", MBB); + } + } else { + report("AnalyzeBranch returned invalid data!", MBB); + } + } + + regsLive.clear(); + for (MachineBasicBlock::const_livein_iterator I = MBB->livein_begin(), + E = MBB->livein_end(); I != E; ++I) { + if (!TargetRegisterInfo::isPhysicalRegister(*I)) { + report("MBB live-in list contains non-physical register", MBB); + continue; + } + regsLive.insert(*I); + for (const unsigned *R = TRI->getSubRegisters(*I); *R; R++) + regsLive.insert(*R); + } + regsLiveInButUnused = regsLive; + + const MachineFrameInfo *MFI = MF->getFrameInfo(); + assert(MFI && "Function has no frame info"); + BitVector PR = MFI->getPristineRegs(MBB); + for (int I = PR.find_first(); I>0; I = PR.find_next(I)) { + regsLive.insert(I); + for (const unsigned *R = TRI->getSubRegisters(I); *R; R++) + regsLive.insert(*R); + } + + regsKilled.clear(); + regsDefined.clear(); +} + +void MachineVerifier::visitMachineInstrBefore(const MachineInstr *MI) { + const TargetInstrDesc &TI = MI->getDesc(); + if (MI->getNumOperands() < TI.getNumOperands()) { + report("Too few operands", MI); + *OS << TI.getNumOperands() << " operands expected, but " + << MI->getNumExplicitOperands() << " given.\n"; + } + + // Check the MachineMemOperands for basic consistency. + for (MachineInstr::mmo_iterator I = MI->memoperands_begin(), + E = MI->memoperands_end(); I != E; ++I) { + if ((*I)->isLoad() && !TI.mayLoad()) + report("Missing mayLoad flag", MI); + if ((*I)->isStore() && !TI.mayStore()) + report("Missing mayStore flag", MI); + } +} + +void +MachineVerifier::visitMachineOperand(const MachineOperand *MO, unsigned MONum) { + const MachineInstr *MI = MO->getParent(); + const TargetInstrDesc &TI = MI->getDesc(); + + // The first TI.NumDefs operands must be explicit register defines + if (MONum < TI.getNumDefs()) { + if (!MO->isReg()) + report("Explicit definition must be a register", MO, MONum); + else if (!MO->isDef()) + report("Explicit definition marked as use", MO, MONum); + else if (MO->isImplicit()) + report("Explicit definition marked as implicit", MO, MONum); + } else if (MONum < TI.getNumOperands()) { + if (MO->isReg()) { + if (MO->isDef()) + report("Explicit operand marked as def", MO, MONum); + if (MO->isImplicit()) + report("Explicit operand marked as implicit", MO, MONum); + } + } else { + if (MO->isReg() && !MO->isImplicit() && !TI.isVariadic()) + report("Extra explicit operand on non-variadic instruction", MO, MONum); + } + + switch (MO->getType()) { + case MachineOperand::MO_Register: { + const unsigned Reg = MO->getReg(); + if (!Reg) + return; + + // Check Live Variables. + if (MO->isUndef()) { + // An doesn't refer to any register, so just skip it. + } else if (MO->isUse()) { + regsLiveInButUnused.erase(Reg); + + bool isKill = false; + if (MO->isKill()) { + isKill = true; + // Tied operands on two-address instuctions MUST NOT have a flag. + if (MI->isRegTiedToDefOperand(MONum)) + report("Illegal kill flag on two-address instruction operand", + MO, MONum); + } else { + // TwoAddress instr modifying a reg is treated as kill+def. + unsigned defIdx; + if (MI->isRegTiedToDefOperand(MONum, &defIdx) && + MI->getOperand(defIdx).getReg() == Reg) + isKill = true; + } + if (isKill) { + addRegWithSubRegs(regsKilled, Reg); + + // Check that LiveVars knows this kill + if (LiveVars && TargetRegisterInfo::isVirtualRegister(Reg)) { + LiveVariables::VarInfo &VI = LiveVars->getVarInfo(Reg); + if (std::find(VI.Kills.begin(), + VI.Kills.end(), MI) == VI.Kills.end()) + report("Kill missing from LiveVariables", MO, MONum); + } + } + + // Use of a dead register. + if (!regsLive.count(Reg)) { + if (TargetRegisterInfo::isPhysicalRegister(Reg)) { + // Reserved registers may be used even when 'dead'. + if (!isReserved(Reg)) + report("Using an undefined physical register", MO, MONum); + } else { + BBInfo &MInfo = MBBInfoMap[MI->getParent()]; + // We don't know which virtual registers are live in, so only complain + // if vreg was killed in this MBB. Otherwise keep track of vregs that + // must be live in. PHI instructions are handled separately. + if (MInfo.regsKilled.count(Reg)) + report("Using a killed virtual register", MO, MONum); + else if (MI->getOpcode() != TargetInstrInfo::PHI) + MInfo.vregsLiveIn.insert(std::make_pair(Reg, MI)); + } + } + } else { + assert(MO->isDef()); + // Register defined. + // TODO: verify that earlyclobber ops are not used. + if (MO->isDead()) + addRegWithSubRegs(regsDead, Reg); + else + addRegWithSubRegs(regsDefined, Reg); + } + + // Check register classes. + if (MONum < TI.getNumOperands() && !MO->isImplicit()) { + const TargetOperandInfo &TOI = TI.OpInfo[MONum]; + unsigned SubIdx = MO->getSubReg(); + + if (TargetRegisterInfo::isPhysicalRegister(Reg)) { + unsigned sr = Reg; + if (SubIdx) { + unsigned s = TRI->getSubReg(Reg, SubIdx); + if (!s) { + report("Invalid subregister index for physical register", + MO, MONum); + return; + } + sr = s; + } + if (const TargetRegisterClass *DRC = TOI.getRegClass(TRI)) { + if (!DRC->contains(sr)) { + report("Illegal physical register for instruction", MO, MONum); + *OS << TRI->getName(sr) << " is not a " + << DRC->getName() << " register.\n"; + } + } + } else { + // Virtual register. + const TargetRegisterClass *RC = MRI->getRegClass(Reg); + if (SubIdx) { + if (RC->subregclasses_begin()+SubIdx >= RC->subregclasses_end()) { + report("Invalid subregister index for virtual register", MO, MONum); + return; + } + RC = *(RC->subregclasses_begin()+SubIdx); + } + if (const TargetRegisterClass *DRC = TOI.getRegClass(TRI)) { + if (RC != DRC && !RC->hasSuperClass(DRC)) { + report("Illegal virtual register for instruction", MO, MONum); + *OS << "Expected a " << DRC->getName() << " register, but got a " + << RC->getName() << " register\n"; + } + } + } + } + break; + } + + case MachineOperand::MO_MachineBasicBlock: + if (MI->getOpcode() == TargetInstrInfo::PHI) { + if (!MO->getMBB()->isSuccessor(MI->getParent())) + report("PHI operand is not in the CFG", MO, MONum); + } + break; + + default: + break; + } +} + +void MachineVerifier::visitMachineInstrAfter(const MachineInstr *MI) { + BBInfo &MInfo = MBBInfoMap[MI->getParent()]; + set_union(MInfo.regsKilled, regsKilled); + set_subtract(regsLive, regsKilled); + regsKilled.clear(); + + // Verify that both and operands refer to dead registers. + RegVector defs(regsDefined); + defs.append(regsDead.begin(), regsDead.end()); + + for (RegVector::const_iterator I = defs.begin(), E = defs.end(); + I != E; ++I) { + if (regsLive.count(*I)) { + if (TargetRegisterInfo::isPhysicalRegister(*I)) { + if (!allowPhysDoubleDefs && !isReserved(*I) && + !regsLiveInButUnused.count(*I)) { + report("Redefining a live physical register", MI); + *OS << "Register " << TRI->getName(*I) + << " was defined but already live.\n"; + } + } else { + if (!allowVirtDoubleDefs) { + report("Redefining a live virtual register", MI); + *OS << "Virtual register %reg" << *I + << " was defined but already live.\n"; + } + } + } else if (TargetRegisterInfo::isVirtualRegister(*I) && + !MInfo.regsKilled.count(*I)) { + // Virtual register defined without being killed first must be dead on + // entry. + MInfo.vregsDeadIn.insert(std::make_pair(*I, MI)); + } + } + + set_subtract(regsLive, regsDead); regsDead.clear(); + set_union(regsLive, regsDefined); regsDefined.clear(); +} + +void +MachineVerifier::visitMachineBasicBlockAfter(const MachineBasicBlock *MBB) { + MBBInfoMap[MBB].regsLiveOut = regsLive; + regsLive.clear(); +} + +// Calculate the largest possible vregsPassed sets. These are the registers that +// can pass through an MBB live, but may not be live every time. It is assumed +// that all vregsPassed sets are empty before the call. +void MachineVerifier::calcMaxRegsPassed() { + // First push live-out regs to successors' vregsPassed. Remember the MBBs that + // have any vregsPassed. + DenseSet todo; + for (MachineFunction::const_iterator MFI = MF->begin(), MFE = MF->end(); + MFI != MFE; ++MFI) { + const MachineBasicBlock &MBB(*MFI); + BBInfo &MInfo = MBBInfoMap[&MBB]; + if (!MInfo.reachable) + continue; + for (MachineBasicBlock::const_succ_iterator SuI = MBB.succ_begin(), + SuE = MBB.succ_end(); SuI != SuE; ++SuI) { + BBInfo &SInfo = MBBInfoMap[*SuI]; + if (SInfo.addPassed(MInfo.regsLiveOut)) + todo.insert(*SuI); + } + } + + // Iteratively push vregsPassed to successors. This will converge to the same + // final state regardless of DenseSet iteration order. + while (!todo.empty()) { + const MachineBasicBlock *MBB = *todo.begin(); + todo.erase(MBB); + BBInfo &MInfo = MBBInfoMap[MBB]; + for (MachineBasicBlock::const_succ_iterator SuI = MBB->succ_begin(), + SuE = MBB->succ_end(); SuI != SuE; ++SuI) { + if (*SuI == MBB) + continue; + BBInfo &SInfo = MBBInfoMap[*SuI]; + if (SInfo.addPassed(MInfo.vregsPassed)) + todo.insert(*SuI); + } + } +} + +// Calculate the minimum vregsPassed set. These are the registers that always +// pass live through an MBB. The calculation assumes that calcMaxRegsPassed has +// been called earlier. +void MachineVerifier::calcMinRegsPassed() { + DenseSet todo; + for (MachineFunction::const_iterator MFI = MF->begin(), MFE = MF->end(); + MFI != MFE; ++MFI) + todo.insert(MFI); + + while (!todo.empty()) { + const MachineBasicBlock *MBB = *todo.begin(); + todo.erase(MBB); + BBInfo &MInfo = MBBInfoMap[MBB]; + + // Remove entries from vRegsPassed that are not live out from all + // reachable predecessors. + RegSet dead; + for (RegSet::iterator I = MInfo.vregsPassed.begin(), + E = MInfo.vregsPassed.end(); I != E; ++I) { + for (MachineBasicBlock::const_pred_iterator PrI = MBB->pred_begin(), + PrE = MBB->pred_end(); PrI != PrE; ++PrI) { + BBInfo &PrInfo = MBBInfoMap[*PrI]; + if (PrInfo.reachable && !PrInfo.isLiveOut(*I)) { + dead.insert(*I); + break; + } + } + } + // If any regs removed, we need to recheck successors. + if (!dead.empty()) { + set_subtract(MInfo.vregsPassed, dead); + todo.insert(MBB->succ_begin(), MBB->succ_end()); + } + } +} + +// Calculate the set of virtual registers that must be passed through each basic +// block in order to satisfy the requirements of successor blocks. This is very +// similar to calcMaxRegsPassed, only backwards. +void MachineVerifier::calcRegsRequired() { + // First push live-in regs to predecessors' vregsRequired. + DenseSet todo; + for (MachineFunction::const_iterator MFI = MF->begin(), MFE = MF->end(); + MFI != MFE; ++MFI) { + const MachineBasicBlock &MBB(*MFI); + BBInfo &MInfo = MBBInfoMap[&MBB]; + for (MachineBasicBlock::const_pred_iterator PrI = MBB.pred_begin(), + PrE = MBB.pred_end(); PrI != PrE; ++PrI) { + BBInfo &PInfo = MBBInfoMap[*PrI]; + if (PInfo.addRequired(MInfo.vregsLiveIn)) + todo.insert(*PrI); + } + } + + // Iteratively push vregsRequired to predecessors. This will converge to the + // same final state regardless of DenseSet iteration order. + while (!todo.empty()) { + const MachineBasicBlock *MBB = *todo.begin(); + todo.erase(MBB); + BBInfo &MInfo = MBBInfoMap[MBB]; + for (MachineBasicBlock::const_pred_iterator PrI = MBB->pred_begin(), + PrE = MBB->pred_end(); PrI != PrE; ++PrI) { + if (*PrI == MBB) + continue; + BBInfo &SInfo = MBBInfoMap[*PrI]; + if (SInfo.addRequired(MInfo.vregsRequired)) + todo.insert(*PrI); + } + } +} + +// Check PHI instructions at the beginning of MBB. It is assumed that +// calcMinRegsPassed has been run so BBInfo::isLiveOut is valid. +void MachineVerifier::checkPHIOps(const MachineBasicBlock *MBB) { + for (MachineBasicBlock::const_iterator BBI = MBB->begin(), BBE = MBB->end(); + BBI != BBE && BBI->getOpcode() == TargetInstrInfo::PHI; ++BBI) { + DenseSet seen; + + for (unsigned i = 1, e = BBI->getNumOperands(); i != e; i += 2) { + unsigned Reg = BBI->getOperand(i).getReg(); + const MachineBasicBlock *Pre = BBI->getOperand(i + 1).getMBB(); + if (!Pre->isSuccessor(MBB)) + continue; + seen.insert(Pre); + BBInfo &PrInfo = MBBInfoMap[Pre]; + if (PrInfo.reachable && !PrInfo.isLiveOut(Reg)) + report("PHI operand is not live-out from predecessor", + &BBI->getOperand(i), i); + } + + // Did we see all predecessors? + for (MachineBasicBlock::const_pred_iterator PrI = MBB->pred_begin(), + PrE = MBB->pred_end(); PrI != PrE; ++PrI) { + if (!seen.count(*PrI)) { + report("Missing PHI operand", BBI); + *OS << "BB#" << (*PrI)->getNumber() + << " is a predecessor according to the CFG.\n"; + } + } + } +} + +void MachineVerifier::visitMachineFunctionAfter() { + calcMaxRegsPassed(); + + // With the maximal set of vregsPassed we can verify dead-in registers. + for (MachineFunction::const_iterator MFI = MF->begin(), MFE = MF->end(); + MFI != MFE; ++MFI) { + BBInfo &MInfo = MBBInfoMap[MFI]; + + // Skip unreachable MBBs. + if (!MInfo.reachable) + continue; + + for (MachineBasicBlock::const_pred_iterator PrI = MFI->pred_begin(), + PrE = MFI->pred_end(); PrI != PrE; ++PrI) { + BBInfo &PrInfo = MBBInfoMap[*PrI]; + if (!PrInfo.reachable) + continue; + + // Verify physical live-ins. EH landing pads have magic live-ins so we + // ignore them. + if (!MFI->isLandingPad()) { + for (MachineBasicBlock::const_livein_iterator I = MFI->livein_begin(), + E = MFI->livein_end(); I != E; ++I) { + if (TargetRegisterInfo::isPhysicalRegister(*I) && + !isReserved (*I) && !PrInfo.isLiveOut(*I)) { + report("Live-in physical register is not live-out from predecessor", + MFI); + *OS << "Register " << TRI->getName(*I) + << " is not live-out from BB#" << (*PrI)->getNumber() + << ".\n"; + } + } + } + + + // Verify dead-in virtual registers. + if (!allowVirtDoubleDefs) { + for (RegMap::iterator I = MInfo.vregsDeadIn.begin(), + E = MInfo.vregsDeadIn.end(); I != E; ++I) { + // DeadIn register must be in neither regsLiveOut or vregsPassed of + // any predecessor. + if (PrInfo.isLiveOut(I->first)) { + report("Live-in virtual register redefined", I->second); + *OS << "Register %reg" << I->first + << " was live-out from predecessor MBB #" + << (*PrI)->getNumber() << ".\n"; + } + } + } + } + } + + calcMinRegsPassed(); + + // With the minimal set of vregsPassed we can verify live-in virtual + // registers, including PHI instructions. + for (MachineFunction::const_iterator MFI = MF->begin(), MFE = MF->end(); + MFI != MFE; ++MFI) { + BBInfo &MInfo = MBBInfoMap[MFI]; + + // Skip unreachable MBBs. + if (!MInfo.reachable) + continue; + + checkPHIOps(MFI); + + for (MachineBasicBlock::const_pred_iterator PrI = MFI->pred_begin(), + PrE = MFI->pred_end(); PrI != PrE; ++PrI) { + BBInfo &PrInfo = MBBInfoMap[*PrI]; + if (!PrInfo.reachable) + continue; + + for (RegMap::iterator I = MInfo.vregsLiveIn.begin(), + E = MInfo.vregsLiveIn.end(); I != E; ++I) { + if (!PrInfo.isLiveOut(I->first)) { + report("Used virtual register is not live-in", I->second); + *OS << "Register %reg" << I->first + << " is not live-out from predecessor MBB #" + << (*PrI)->getNumber() + << ".\n"; + } + } + } + } + + // Now check LiveVariables info if available + if (LiveVars) { + calcRegsRequired(); + verifyLiveVariables(); + } +} + +void MachineVerifier::verifyLiveVariables() { + assert(LiveVars && "Don't call verifyLiveVariables without LiveVars"); + for (unsigned Reg = TargetRegisterInfo::FirstVirtualRegister, + RegE = MRI->getLastVirtReg()-1; Reg != RegE; ++Reg) { + LiveVariables::VarInfo &VI = LiveVars->getVarInfo(Reg); + for (MachineFunction::const_iterator MFI = MF->begin(), MFE = MF->end(); + MFI != MFE; ++MFI) { + BBInfo &MInfo = MBBInfoMap[MFI]; + + // Our vregsRequired should be identical to LiveVariables' AliveBlocks + if (MInfo.vregsRequired.count(Reg)) { + if (!VI.AliveBlocks.test(MFI->getNumber())) { + report("LiveVariables: Block missing from AliveBlocks", MFI); + *OS << "Virtual register %reg" << Reg + << " must be live through the block.\n"; + } + } else { + if (VI.AliveBlocks.test(MFI->getNumber())) { + report("LiveVariables: Block should not be in AliveBlocks", MFI); + *OS << "Virtual register %reg" << Reg + << " is not needed live through the block.\n"; + } + } + } + } +} + + diff --git a/libclamav/c++/llvm/lib/CodeGen/Makefile b/libclamav/c++/llvm/lib/CodeGen/Makefile new file mode 100644 index 000000000..4ab3e3c00 --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/Makefile @@ -0,0 +1,22 @@ +##===- lib/CodeGen/Makefile --------------------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LEVEL = ../.. +LIBRARYNAME = LLVMCodeGen +PARALLEL_DIRS = SelectionDAG AsmPrinter +BUILD_ARCHIVE = 1 + +include $(LEVEL)/Makefile.common + +# Xcode prior to 2.4 generates an error in -pedantic mode with use of HUGE_VAL +# in this directory. Disable -pedantic for this broken compiler. +ifneq ($(HUGE_VAL_SANITY),yes) +CompileCommonOpts := $(filter-out -pedantic, $(CompileCommonOpts)) +endif + diff --git a/libclamav/c++/llvm/lib/CodeGen/ObjectCodeEmitter.cpp b/libclamav/c++/llvm/lib/CodeGen/ObjectCodeEmitter.cpp new file mode 100644 index 000000000..cf05275d7 --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/ObjectCodeEmitter.cpp @@ -0,0 +1,141 @@ +//===-- llvm/CodeGen/ObjectCodeEmitter.cpp -------------------- -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/CodeGen/BinaryObject.h" +#include "llvm/CodeGen/MachineBasicBlock.h" +#include "llvm/CodeGen/MachineRelocation.h" +#include "llvm/CodeGen/ObjectCodeEmitter.h" + +//===----------------------------------------------------------------------===// +// ObjectCodeEmitter Implementation +//===----------------------------------------------------------------------===// + +namespace llvm { + +ObjectCodeEmitter::ObjectCodeEmitter() : BO(0) {} +ObjectCodeEmitter::ObjectCodeEmitter(BinaryObject *bo) : BO(bo) {} +ObjectCodeEmitter::~ObjectCodeEmitter() {} + +/// setBinaryObject - set the BinaryObject we are writting to +void ObjectCodeEmitter::setBinaryObject(BinaryObject *bo) { BO = bo; } + +/// emitByte - This callback is invoked when a byte needs to be +/// written to the data stream, without buffer overflow testing. +void ObjectCodeEmitter::emitByte(uint8_t B) { + BO->emitByte(B); +} + +/// emitWordLE - This callback is invoked when a 32-bit word needs to be +/// written to the data stream in little-endian format. +void ObjectCodeEmitter::emitWordLE(uint32_t W) { + BO->emitWordLE(W); +} + +/// emitWordBE - This callback is invoked when a 32-bit word needs to be +/// written to the data stream in big-endian format. +void ObjectCodeEmitter::emitWordBE(uint32_t W) { + BO->emitWordBE(W); +} + +/// emitDWordLE - This callback is invoked when a 64-bit word needs to be +/// written to the data stream in little-endian format. +void ObjectCodeEmitter::emitDWordLE(uint64_t W) { + BO->emitDWordLE(W); +} + +/// emitDWordBE - This callback is invoked when a 64-bit word needs to be +/// written to the data stream in big-endian format. +void ObjectCodeEmitter::emitDWordBE(uint64_t W) { + BO->emitDWordBE(W); +} + +/// emitAlignment - Align 'BO' to the necessary alignment boundary. +void ObjectCodeEmitter::emitAlignment(unsigned Alignment /* 0 */, + uint8_t fill /* 0 */) { + BO->emitAlignment(Alignment, fill); +} + +/// emitULEB128Bytes - This callback is invoked when a ULEB128 needs to be +/// written to the data stream. +void ObjectCodeEmitter::emitULEB128Bytes(uint64_t Value) { + BO->emitULEB128Bytes(Value); +} + +/// emitSLEB128Bytes - This callback is invoked when a SLEB128 needs to be +/// written to the data stream. +void ObjectCodeEmitter::emitSLEB128Bytes(uint64_t Value) { + BO->emitSLEB128Bytes(Value); +} + +/// emitString - This callback is invoked when a String needs to be +/// written to the data stream. +void ObjectCodeEmitter::emitString(const std::string &String) { + BO->emitString(String); +} + +/// getCurrentPCValue - This returns the address that the next emitted byte +/// will be output to. +uintptr_t ObjectCodeEmitter::getCurrentPCValue() const { + return BO->getCurrentPCOffset(); +} + +/// getCurrentPCOffset - Return the offset from the start of the emitted +/// buffer that we are currently writing to. +uintptr_t ObjectCodeEmitter::getCurrentPCOffset() const { + return BO->getCurrentPCOffset(); +} + +/// addRelocation - Whenever a relocatable address is needed, it should be +/// noted with this interface. +void ObjectCodeEmitter::addRelocation(const MachineRelocation& relocation) { + BO->addRelocation(relocation); +} + +/// StartMachineBasicBlock - This should be called by the target when a new +/// basic block is about to be emitted. This way the MCE knows where the +/// start of the block is, and can implement getMachineBasicBlockAddress. +void ObjectCodeEmitter::StartMachineBasicBlock(MachineBasicBlock *MBB) { + if (MBBLocations.size() <= (unsigned)MBB->getNumber()) + MBBLocations.resize((MBB->getNumber()+1)*2); + MBBLocations[MBB->getNumber()] = getCurrentPCOffset(); +} + +/// getMachineBasicBlockAddress - Return the address of the specified +/// MachineBasicBlock, only usable after the label for the MBB has been +/// emitted. +uintptr_t +ObjectCodeEmitter::getMachineBasicBlockAddress(MachineBasicBlock *MBB) const { + assert(MBBLocations.size() > (unsigned)MBB->getNumber() && + MBBLocations[MBB->getNumber()] && "MBB not emitted!"); + return MBBLocations[MBB->getNumber()]; +} + +/// getJumpTableEntryAddress - Return the address of the jump table with index +/// 'Index' in the function that last called initJumpTableInfo. +uintptr_t ObjectCodeEmitter::getJumpTableEntryAddress(unsigned Index) const { + assert(JTLocations.size() > Index && "JT not emitted!"); + return JTLocations[Index]; +} + +/// getConstantPoolEntryAddress - Return the address of the 'Index' entry in +/// the constant pool that was last emitted with the emitConstantPool method. +uintptr_t ObjectCodeEmitter::getConstantPoolEntryAddress(unsigned Index) const { + assert(CPLocations.size() > Index && "CP not emitted!"); + return CPLocations[Index]; +} + +/// getConstantPoolEntrySection - Return the section of the 'Index' entry in +/// the constant pool that was last emitted with the emitConstantPool method. +uintptr_t ObjectCodeEmitter::getConstantPoolEntrySection(unsigned Index) const { + assert(CPSections.size() > Index && "CP not emitted!"); + return CPSections[Index]; +} + +} // end namespace llvm + diff --git a/libclamav/c++/llvm/lib/CodeGen/OcamlGC.cpp b/libclamav/c++/llvm/lib/CodeGen/OcamlGC.cpp new file mode 100644 index 000000000..48db200c5 --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/OcamlGC.cpp @@ -0,0 +1,37 @@ +//===-- OcamlGC.cpp - Ocaml frametable GC strategy ------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements lowering for the llvm.gc* intrinsics compatible with +// Objective Caml 3.10.0, which uses a liveness-accurate static stack map. +// +// The frametable emitter is in OcamlGCPrinter.cpp. +// +//===----------------------------------------------------------------------===// + +#include "llvm/CodeGen/GCs.h" +#include "llvm/CodeGen/GCStrategy.h" + +using namespace llvm; + +namespace { + class OcamlGC : public GCStrategy { + public: + OcamlGC(); + }; +} + +static GCRegistry::Add +X("ocaml", "ocaml 3.10-compatible GC"); + +void llvm::linkOcamlGC() { } + +OcamlGC::OcamlGC() { + NeededSafePoints = 1 << GC::PostCall; + UsesMetadata = true; +} diff --git a/libclamav/c++/llvm/lib/CodeGen/PBQP/AnnotatedGraph.h b/libclamav/c++/llvm/lib/CodeGen/PBQP/AnnotatedGraph.h new file mode 100644 index 000000000..904061ca4 --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/PBQP/AnnotatedGraph.h @@ -0,0 +1,184 @@ +//===-- AnnotatedGraph.h - Annotated PBQP Graph ----------------*- C++ --*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Annotated PBQP Graph class. This class is used internally by the PBQP solver +// to cache information to speed up reduction. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_PBQP_ANNOTATEDGRAPH_H +#define LLVM_CODEGEN_PBQP_ANNOTATEDGRAPH_H + +#include "GraphBase.h" + +namespace PBQP { + + +template class AnnotatedEdge; + +template +class AnnotatedNode : public NodeBase, + AnnotatedEdge > { +private: + + NodeData nodeData; + +public: + + AnnotatedNode(const Vector &costs, const NodeData &nodeData) : + NodeBase, + AnnotatedEdge >(costs), + nodeData(nodeData) {} + + NodeData& getNodeData() { return nodeData; } + const NodeData& getNodeData() const { return nodeData; } + +}; + +template +class AnnotatedEdge : public EdgeBase, + AnnotatedEdge > { +private: + + typedef typename GraphBase, + AnnotatedEdge >::NodeIterator + NodeIterator; + + EdgeData edgeData; + +public: + + + AnnotatedEdge(const NodeIterator &node1Itr, const NodeIterator &node2Itr, + const Matrix &costs, const EdgeData &edgeData) : + EdgeBase, + AnnotatedEdge >(node1Itr, node2Itr, costs), + edgeData(edgeData) {} + + EdgeData& getEdgeData() { return edgeData; } + const EdgeData& getEdgeData() const { return edgeData; } + +}; + +template +class AnnotatedGraph : public GraphBase, + AnnotatedEdge > { +private: + + typedef GraphBase, + AnnotatedEdge > PGraph; + + typedef AnnotatedNode NodeEntry; + typedef AnnotatedEdge EdgeEntry; + + + void copyFrom(const AnnotatedGraph &other) { + if (!other.areNodeIDsValid()) { + other.assignNodeIDs(); + } + std::vector newNodeItrs(other.getNumNodes()); + + for (ConstNodeIterator nItr = other.nodesBegin(), nEnd = other.nodesEnd(); + nItr != nEnd; ++nItr) { + newNodeItrs[other.getNodeID(nItr)] = addNode(other.getNodeCosts(nItr)); + } + + for (ConstEdgeIterator eItr = other.edgesBegin(), eEnd = other.edgesEnd(); + eItr != eEnd; ++eItr) { + + unsigned node1ID = other.getNodeID(other.getEdgeNode1(eItr)), + node2ID = other.getNodeID(other.getEdgeNode2(eItr)); + + addEdge(newNodeItrs[node1ID], newNodeItrs[node2ID], + other.getEdgeCosts(eItr), other.getEdgeData(eItr)); + } + + } + +public: + + typedef typename PGraph::NodeIterator NodeIterator; + typedef typename PGraph::ConstNodeIterator ConstNodeIterator; + typedef typename PGraph::EdgeIterator EdgeIterator; + typedef typename PGraph::ConstEdgeIterator ConstEdgeIterator; + + AnnotatedGraph() {} + + AnnotatedGraph(const AnnotatedGraph &other) { + copyFrom(other); + } + + AnnotatedGraph& operator=(const AnnotatedGraph &other) { + PGraph::clear(); + copyFrom(other); + return *this; + } + + NodeIterator addNode(const Vector &costs, const NodeData &data) { + return PGraph::addConstructedNode(NodeEntry(costs, data)); + } + + EdgeIterator addEdge(const NodeIterator &node1Itr, + const NodeIterator &node2Itr, + const Matrix &costs, const EdgeData &data) { + return PGraph::addConstructedEdge(EdgeEntry(node1Itr, node2Itr, + costs, data)); + } + + NodeData& getNodeData(const NodeIterator &nodeItr) { + return getNodeEntry(nodeItr).getNodeData(); + } + + const NodeData& getNodeData(const NodeIterator &nodeItr) const { + return getNodeEntry(nodeItr).getNodeData(); + } + + EdgeData& getEdgeData(const EdgeIterator &edgeItr) { + return getEdgeEntry(edgeItr).getEdgeData(); + } + + const EdgeEntry& getEdgeData(const EdgeIterator &edgeItr) const { + return getEdgeEntry(edgeItr).getEdgeData(); + } + + SimpleGraph toSimpleGraph() const { + SimpleGraph g; + + if (!PGraph::areNodeIDsValid()) { + PGraph::assignNodeIDs(); + } + std::vector newNodeItrs(PGraph::getNumNodes()); + + for (ConstNodeIterator nItr = PGraph::nodesBegin(), + nEnd = PGraph::nodesEnd(); + nItr != nEnd; ++nItr) { + + newNodeItrs[getNodeID(nItr)] = g.addNode(getNodeCosts(nItr)); + } + + for (ConstEdgeIterator + eItr = PGraph::edgesBegin(), eEnd = PGraph::edgesEnd(); + eItr != eEnd; ++eItr) { + + unsigned node1ID = getNodeID(getEdgeNode1(eItr)), + node2ID = getNodeID(getEdgeNode2(eItr)); + + g.addEdge(newNodeItrs[node1ID], newNodeItrs[node2ID], + getEdgeCosts(eItr)); + } + + return g; + } + +}; + + +} + +#endif // LLVM_CODEGEN_PBQP_ANNOTATEDGRAPH_H diff --git a/libclamav/c++/llvm/lib/CodeGen/PBQP/ExhaustiveSolver.h b/libclamav/c++/llvm/lib/CodeGen/PBQP/ExhaustiveSolver.h new file mode 100644 index 000000000..b2f2e6f62 --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/PBQP/ExhaustiveSolver.h @@ -0,0 +1,110 @@ +//===-- ExhaustiveSolver.h - Brute Force PBQP Solver -----------*- C++ --*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Uses a trivial brute force algorithm to solve a PBQP problem. +// PBQP is NP-HARD - This solver should only be used for debugging small +// problems. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_PBQP_EXHAUSTIVESOLVER_H +#define LLVM_CODEGEN_PBQP_EXHAUSTIVESOLVER_H + +#include "Solver.h" + +namespace PBQP { + +/// A brute force PBQP solver. This solver takes exponential time. It should +/// only be used for debugging purposes. +class ExhaustiveSolverImpl { +private: + + const SimpleGraph &g; + + PBQPNum getSolutionCost(const Solution &solution) const { + PBQPNum cost = 0.0; + + for (SimpleGraph::ConstNodeIterator + nodeItr = g.nodesBegin(), nodeEnd = g.nodesEnd(); + nodeItr != nodeEnd; ++nodeItr) { + + unsigned nodeId = g.getNodeID(nodeItr); + + cost += g.getNodeCosts(nodeItr)[solution.getSelection(nodeId)]; + } + + for (SimpleGraph::ConstEdgeIterator + edgeItr = g.edgesBegin(), edgeEnd = g.edgesEnd(); + edgeItr != edgeEnd; ++edgeItr) { + + SimpleGraph::ConstNodeIterator n1 = g.getEdgeNode1Itr(edgeItr), + n2 = g.getEdgeNode2Itr(edgeItr); + unsigned sol1 = solution.getSelection(g.getNodeID(n1)), + sol2 = solution.getSelection(g.getNodeID(n2)); + + cost += g.getEdgeCosts(edgeItr)[sol1][sol2]; + } + + return cost; + } + +public: + + ExhaustiveSolverImpl(const SimpleGraph &g) : g(g) {} + + Solution solve() const { + Solution current(g.getNumNodes(), true), optimal(current); + + PBQPNum bestCost = std::numeric_limits::infinity(); + bool finished = false; + + while (!finished) { + PBQPNum currentCost = getSolutionCost(current); + + if (currentCost < bestCost) { + optimal = current; + bestCost = currentCost; + } + + // assume we're done. + finished = true; + + for (unsigned i = 0; i < g.getNumNodes(); ++i) { + if (current.getSelection(i) == + (g.getNodeCosts(g.getNodeItr(i)).getLength() - 1)) { + current.setSelection(i, 0); + } + else { + current.setSelection(i, current.getSelection(i) + 1); + finished = false; + break; + } + } + + } + + optimal.setSolutionCost(bestCost); + + return optimal; + } + +}; + +class ExhaustiveSolver : public Solver { +public: + ~ExhaustiveSolver() {} + Solution solve(const SimpleGraph &g) const { + ExhaustiveSolverImpl solver(g); + return solver.solve(); + } +}; + +} + +#endif // LLVM_CODGEN_PBQP_EXHAUSTIVESOLVER_HPP diff --git a/libclamav/c++/llvm/lib/CodeGen/PBQP/GraphBase.h b/libclamav/c++/llvm/lib/CodeGen/PBQP/GraphBase.h new file mode 100644 index 000000000..cc3e017ad --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/PBQP/GraphBase.h @@ -0,0 +1,582 @@ +//===-- GraphBase.h - Abstract Base PBQP Graph -----------------*- C++ --*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Base class for PBQP Graphs. +// +//===----------------------------------------------------------------------===// + + +#ifndef LLVM_CODEGEN_PBQP_GRAPHBASE_H +#define LLVM_CODEGEN_PBQP_GRAPHBASE_H + +#include "PBQPMath.h" + +#include +#include + +namespace PBQP { + +// UGLY, but I'm not sure there's a good way around this: We need to be able to +// look up a Node's "adjacent edge list" structure type before the Node type is +// fully constructed. We can enable this by pushing the choice of data type +// out into this traits class. +template +class NodeBaseTraits { + public: + typedef std::list AdjEdgeList; + typedef typename AdjEdgeList::iterator AdjEdgeIterator; + typedef typename AdjEdgeList::const_iterator ConstAdjEdgeIterator; +}; + +/// \brief Base for concrete graph classes. Provides a basic set of graph +/// operations which are useful for PBQP solvers. +template +class GraphBase { +private: + + typedef GraphBase ThisGraphT; + + typedef std::list NodeList; + typedef std::list EdgeList; + + NodeList nodeList; + unsigned nodeListSize; + + EdgeList edgeList; + unsigned edgeListSize; + + GraphBase(const ThisGraphT &other) { abort(); } + void operator=(const ThisGraphT &other) { abort(); } + +public: + + /// \brief Iterates over the nodes of a graph. + typedef typename NodeList::iterator NodeIterator; + /// \brief Iterates over the nodes of a const graph. + typedef typename NodeList::const_iterator ConstNodeIterator; + /// \brief Iterates over the edges of a graph. + typedef typename EdgeList::iterator EdgeIterator; + /// \brief Iterates over the edges of a const graph. + typedef typename EdgeList::const_iterator ConstEdgeIterator; + + /// \brief Iterates over the edges attached to a node. + typedef typename NodeBaseTraits::AdjEdgeIterator + AdjEdgeIterator; + + /// \brief Iterates over the edges attached to a node in a const graph. + typedef typename NodeBaseTraits::ConstAdjEdgeIterator + ConstAdjEdgeIterator; + +private: + + typedef std::vector IDToNodeMap; + + IDToNodeMap idToNodeMap; + bool nodeIDsValid; + + void invalidateNodeIDs() { + if (nodeIDsValid) { + idToNodeMap.clear(); + nodeIDsValid = false; + } + } + + template + bool iteratorInRange(ItrT itr, const ItrT &begin, const ItrT &end) { + for (ItrT t = begin; t != end; ++t) { + if (itr == t) + return true; + } + + return false; + } + +protected: + + GraphBase() : nodeListSize(0), edgeListSize(0), nodeIDsValid(false) {} + + NodeEntry& getNodeEntry(const NodeIterator &nodeItr) { return *nodeItr; } + const NodeEntry& getNodeEntry(const ConstNodeIterator &nodeItr) const { + return *nodeItr; + } + + EdgeEntry& getEdgeEntry(const EdgeIterator &edgeItr) { return *edgeItr; } + const EdgeEntry& getEdgeEntry(const ConstEdgeIterator &edgeItr) const { + return *edgeItr; + } + + NodeIterator addConstructedNode(const NodeEntry &nodeEntry) { + ++nodeListSize; + + invalidateNodeIDs(); + + NodeIterator newNodeItr = nodeList.insert(nodeList.end(), nodeEntry); + + return newNodeItr; + } + + EdgeIterator addConstructedEdge(const EdgeEntry &edgeEntry) { + + assert((findEdge(edgeEntry.getNode1Itr(), edgeEntry.getNode2Itr()) + == edgeList.end()) && "Attempt to add duplicate edge."); + + ++edgeListSize; + + // Add the edge to the graph. + EdgeIterator edgeItr = edgeList.insert(edgeList.end(), edgeEntry); + + // Get a reference to the version in the graph. + EdgeEntry &newEdgeEntry = getEdgeEntry(edgeItr); + + // Node entries: + NodeEntry &node1Entry = getNodeEntry(newEdgeEntry.getNode1Itr()), + &node2Entry = getNodeEntry(newEdgeEntry.getNode2Itr()); + + // Sanity check on matrix dimensions. + assert((node1Entry.getCosts().getLength() == + newEdgeEntry.getCosts().getRows()) && + (node2Entry.getCosts().getLength() == + newEdgeEntry.getCosts().getCols()) && + "Matrix dimensions do not match cost vector dimensions."); + + // Create links between nodes and edges. + newEdgeEntry.setNode1ThisEdgeItr( + node1Entry.addAdjEdge(edgeItr)); + newEdgeEntry.setNode2ThisEdgeItr( + node2Entry.addAdjEdge(edgeItr)); + + return edgeItr; + } + +public: + + /// \brief Returns the number of nodes in this graph. + unsigned getNumNodes() const { return nodeListSize; } + + /// \brief Returns the number of edges in this graph. + unsigned getNumEdges() const { return edgeListSize; } + + /// \brief Return the cost vector for the given node. + Vector& getNodeCosts(const NodeIterator &nodeItr) { + return getNodeEntry(nodeItr).getCosts(); + } + + /// \brief Return the cost vector for the give node. + const Vector& getNodeCosts(const ConstNodeIterator &nodeItr) const { + return getNodeEntry(nodeItr).getCosts(); + } + + /// \brief Return the degree of the given node. + unsigned getNodeDegree(const NodeIterator &nodeItr) const { + return getNodeEntry(nodeItr).getDegree(); + } + + /// \brief Assigns sequential IDs to the nodes, starting at 0, which + /// remain valid until the next addition or removal of a node. + void assignNodeIDs() { + unsigned curID = 0; + idToNodeMap.resize(getNumNodes()); + for (NodeIterator nodeItr = nodesBegin(), nodeEnd = nodesEnd(); + nodeItr != nodeEnd; ++nodeItr, ++curID) { + getNodeEntry(nodeItr).setID(curID); + idToNodeMap[curID] = nodeItr; + } + nodeIDsValid = true; + } + + /// \brief Assigns sequential IDs to the nodes using the ordering of the + /// given vector. + void assignNodeIDs(const std::vector &nodeOrdering) { + assert((getNumNodes() == nodeOrdering.size()) && + "Wrong number of nodes in node ordering."); + idToNodeMap = nodeOrdering; + for (unsigned nodeID = 0; nodeID < idToNodeMap.size(); ++nodeID) { + getNodeEntry(idToNodeMap[nodeID]).setID(nodeID); + } + nodeIDsValid = true; + } + + /// \brief Returns true if valid node IDs are assigned, false otherwise. + bool areNodeIDsValid() const { return nodeIDsValid; } + + /// \brief Return the numeric ID of the given node. + /// + /// Calls to this method will result in an assertion failure if there have + /// been any node additions or removals since the last call to + /// assignNodeIDs(). + unsigned getNodeID(const ConstNodeIterator &nodeItr) const { + assert(nodeIDsValid && "Attempt to retrieve invalid ID."); + return getNodeEntry(nodeItr).getID(); + } + + /// \brief Returns the iterator associated with the given node ID. + NodeIterator getNodeItr(unsigned nodeID) { + assert(nodeIDsValid && "Attempt to retrieve iterator with invalid ID."); + return idToNodeMap[nodeID]; + } + + /// \brief Returns the iterator associated with the given node ID. + ConstNodeIterator getNodeItr(unsigned nodeID) const { + assert(nodeIDsValid && "Attempt to retrieve iterator with invalid ID."); + return idToNodeMap[nodeID]; + } + + /// \brief Removes the given node (and all attached edges) from the graph. + void removeNode(const NodeIterator &nodeItr) { + assert(iteratorInRange(nodeItr, nodeList.begin(), nodeList.end()) && + "Iterator does not belong to this graph!"); + + invalidateNodeIDs(); + + NodeEntry &nodeEntry = getNodeEntry(nodeItr); + + // We need to copy this out because it will be destroyed as the edges are + // removed. + typedef std::vector AdjEdgeList; + typedef typename AdjEdgeList::iterator AdjEdgeListItr; + + AdjEdgeList adjEdges; + adjEdges.reserve(nodeEntry.getDegree()); + std::copy(nodeEntry.adjEdgesBegin(), nodeEntry.adjEdgesEnd(), + std::back_inserter(adjEdges)); + + // Iterate over the copied out edges and remove them from the graph. + for (AdjEdgeListItr itr = adjEdges.begin(), end = adjEdges.end(); + itr != end; ++itr) { + removeEdge(*itr); + } + + // Erase the node from the nodelist. + nodeList.erase(nodeItr); + --nodeListSize; + } + + NodeIterator nodesBegin() { return nodeList.begin(); } + ConstNodeIterator nodesBegin() const { return nodeList.begin(); } + NodeIterator nodesEnd() { return nodeList.end(); } + ConstNodeIterator nodesEnd() const { return nodeList.end(); } + + AdjEdgeIterator adjEdgesBegin(const NodeIterator &nodeItr) { + return getNodeEntry(nodeItr).adjEdgesBegin(); + } + + ConstAdjEdgeIterator adjEdgesBegin(const ConstNodeIterator &nodeItr) const { + return getNodeEntry(nodeItr).adjEdgesBegin(); + } + + AdjEdgeIterator adjEdgesEnd(const NodeIterator &nodeItr) { + return getNodeEntry(nodeItr).adjEdgesEnd(); + } + + ConstAdjEdgeIterator adjEdgesEnd(const ConstNodeIterator &nodeItr) const { + getNodeEntry(nodeItr).adjEdgesEnd(); + } + + EdgeIterator findEdge(const NodeIterator &node1Itr, + const NodeIterator &node2Itr) { + + for (AdjEdgeIterator adjEdgeItr = adjEdgesBegin(node1Itr), + adjEdgeEnd = adjEdgesEnd(node1Itr); + adjEdgeItr != adjEdgeEnd; ++adjEdgeItr) { + if ((getEdgeNode1Itr(*adjEdgeItr) == node2Itr) || + (getEdgeNode2Itr(*adjEdgeItr) == node2Itr)) { + return *adjEdgeItr; + } + } + + return edgeList.end(); + } + + ConstEdgeIterator findEdge(const ConstNodeIterator &node1Itr, + const ConstNodeIterator &node2Itr) const { + + for (ConstAdjEdgeIterator adjEdgeItr = adjEdgesBegin(node1Itr), + adjEdgeEnd = adjEdgesEnd(node1Itr); + adjEdgeItr != adjEdgesEnd; ++adjEdgeItr) { + if ((getEdgeNode1Itr(*adjEdgeItr) == node2Itr) || + (getEdgeNode2Itr(*adjEdgeItr) == node2Itr)) { + return *adjEdgeItr; + } + } + + return edgeList.end(); + } + + Matrix& getEdgeCosts(const EdgeIterator &edgeItr) { + return getEdgeEntry(edgeItr).getCosts(); + } + + const Matrix& getEdgeCosts(const ConstEdgeIterator &edgeItr) const { + return getEdgeEntry(edgeItr).getCosts(); + } + + NodeIterator getEdgeNode1Itr(const EdgeIterator &edgeItr) { + return getEdgeEntry(edgeItr).getNode1Itr(); + } + + ConstNodeIterator getEdgeNode1Itr(const ConstEdgeIterator &edgeItr) const { + return getEdgeEntry(edgeItr).getNode1Itr(); + } + + NodeIterator getEdgeNode2Itr(const EdgeIterator &edgeItr) { + return getEdgeEntry(edgeItr).getNode2Itr(); + } + + ConstNodeIterator getEdgeNode2Itr(const ConstEdgeIterator &edgeItr) const { + return getEdgeEntry(edgeItr).getNode2Itr(); + } + + NodeIterator getEdgeOtherNode(const EdgeIterator &edgeItr, + const NodeIterator &nodeItr) { + + EdgeEntry &edgeEntry = getEdgeEntry(edgeItr); + if (nodeItr == edgeEntry.getNode1Itr()) { + return edgeEntry.getNode2Itr(); + } + //else + return edgeEntry.getNode1Itr(); + } + + ConstNodeIterator getEdgeOtherNode(const ConstEdgeIterator &edgeItr, + const ConstNodeIterator &nodeItr) const { + + const EdgeEntry &edgeEntry = getEdgeEntry(edgeItr); + if (nodeItr == edgeEntry.getNode1Itr()) { + return edgeEntry.getNode2Itr(); + } + //else + return edgeEntry.getNode1Itr(); + } + + void removeEdge(const EdgeIterator &edgeItr) { + assert(iteratorInRange(edgeItr, edgeList.begin(), edgeList.end()) && + "Iterator does not belong to this graph!"); + + --edgeListSize; + + // Get the edge entry. + EdgeEntry &edgeEntry = getEdgeEntry(edgeItr); + + // Get the nodes entry. + NodeEntry &node1Entry(getNodeEntry(edgeEntry.getNode1Itr())), + &node2Entry(getNodeEntry(edgeEntry.getNode2Itr())); + + // Disconnect the edge from the nodes. + node1Entry.removeAdjEdge(edgeEntry.getNode1ThisEdgeItr()); + node2Entry.removeAdjEdge(edgeEntry.getNode2ThisEdgeItr()); + + // Remove the edge from the graph. + edgeList.erase(edgeItr); + } + + EdgeIterator edgesBegin() { return edgeList.begin(); } + ConstEdgeIterator edgesBegin() const { return edgeList.begin(); } + EdgeIterator edgesEnd() { return edgeList.end(); } + ConstEdgeIterator edgesEnd() const { return edgeList.end(); } + + void clear() { + nodeList.clear(); + nodeListSize = 0; + edgeList.clear(); + edgeListSize = 0; + idToNodeMap.clear(); + } + + template + void printDot(OStream &os) const { + + assert(areNodeIDsValid() && + "Cannot print a .dot of a graph unless IDs have been assigned."); + + os << "graph {\n"; + + for (ConstNodeIterator nodeItr = nodesBegin(), nodeEnd = nodesEnd(); + nodeItr != nodeEnd; ++nodeItr) { + + os << " node" << getNodeID(nodeItr) << " [ label=\"" + << getNodeID(nodeItr) << ": " << getNodeCosts(nodeItr) << "\" ]\n"; + } + + os << " edge [ len=" << getNumNodes() << " ]\n"; + + for (ConstEdgeIterator edgeItr = edgesBegin(), edgeEnd = edgesEnd(); + edgeItr != edgeEnd; ++edgeItr) { + + os << " node" << getNodeID(getEdgeNode1Itr(edgeItr)) + << " -- node" << getNodeID(getEdgeNode2Itr(edgeItr)) + << " [ label=\""; + + const Matrix &edgeCosts = getEdgeCosts(edgeItr); + + for (unsigned i = 0; i < edgeCosts.getRows(); ++i) { + os << edgeCosts.getRowAsVector(i) << "\\n"; + } + + os << "\" ]\n"; + } + + os << "}\n"; + } + + template + void printDot(OStream &os) { + if (!areNodeIDsValid()) { + assignNodeIDs(); + } + + const_cast(this)->printDot(os); + } + + template + void dumpTo(OStream &os) const { + typedef ConstNodeIterator ConstNodeID; + + assert(areNodeIDsValid() && + "Cannot dump a graph unless IDs have been assigned."); + + for (ConstNodeIterator nItr = nodesBegin(), nEnd = nodesEnd(); + nItr != nEnd; ++nItr) { + os << getNodeID(nItr) << "\n"; + } + + unsigned edgeNumber = 1; + for (ConstEdgeIterator eItr = edgesBegin(), eEnd = edgesEnd(); + eItr != eEnd; ++eItr) { + + os << edgeNumber++ << ": { " + << getNodeID(getEdgeNode1Itr(eItr)) << ", " + << getNodeID(getEdgeNode2Itr(eItr)) << " }\n"; + } + + } + + template + void dumpTo(OStream &os) { + if (!areNodeIDsValid()) { + assignNodeIDs(); + } + + const_cast(this)->dumpTo(os); + } + +}; + +/// \brief Provides a base from which to derive nodes for GraphBase. +template +class NodeBase { +private: + + typedef GraphBase GraphBaseT; + typedef NodeBaseTraits ThisNodeBaseTraits; + +public: + typedef typename GraphBaseT::EdgeIterator EdgeIterator; + +private: + typedef typename ThisNodeBaseTraits::AdjEdgeList AdjEdgeList; + + unsigned degree, id; + Vector costs; + AdjEdgeList adjEdges; + + void operator=(const NodeBase& other) { + assert(false && "Can't assign NodeEntrys."); + } + +public: + + typedef typename ThisNodeBaseTraits::AdjEdgeIterator AdjEdgeIterator; + typedef typename ThisNodeBaseTraits::ConstAdjEdgeIterator + ConstAdjEdgeIterator; + + NodeBase(const Vector &costs) : degree(0), costs(costs) { + assert((costs.getLength() > 0) && "Can't have zero-length cost vector."); + } + + Vector& getCosts() { return costs; } + const Vector& getCosts() const { return costs; } + + unsigned getDegree() const { return degree; } + + void setID(unsigned id) { this->id = id; } + unsigned getID() const { return id; } + + AdjEdgeIterator addAdjEdge(const EdgeIterator &edgeItr) { + ++degree; + return adjEdges.insert(adjEdges.end(), edgeItr); + } + + void removeAdjEdge(const AdjEdgeIterator &adjEdgeItr) { + --degree; + adjEdges.erase(adjEdgeItr); + } + + AdjEdgeIterator adjEdgesBegin() { return adjEdges.begin(); } + ConstAdjEdgeIterator adjEdgesBegin() const { return adjEdges.begin(); } + AdjEdgeIterator adjEdgesEnd() { return adjEdges.end(); } + ConstAdjEdgeIterator adjEdgesEnd() const { return adjEdges.end(); } + +}; + +template +class EdgeBase { +public: + typedef typename GraphBase::NodeIterator NodeIterator; + typedef typename GraphBase::EdgeIterator EdgeIterator; + + typedef typename NodeImpl::AdjEdgeIterator NodeAdjEdgeIterator; + +private: + + NodeIterator node1Itr, node2Itr; + NodeAdjEdgeIterator node1ThisEdgeItr, node2ThisEdgeItr; + Matrix costs; + + void operator=(const EdgeBase &other) { + assert(false && "Can't assign EdgeEntrys."); + } + +public: + + EdgeBase(const NodeIterator &node1Itr, const NodeIterator &node2Itr, + const Matrix &costs) : + node1Itr(node1Itr), node2Itr(node2Itr), costs(costs) { + + assert((costs.getRows() > 0) && (costs.getCols() > 0) && + "Can't have zero-dimensioned cost matrices"); + } + + Matrix& getCosts() { return costs; } + const Matrix& getCosts() const { return costs; } + + const NodeIterator& getNode1Itr() const { return node1Itr; } + const NodeIterator& getNode2Itr() const { return node2Itr; } + + void setNode1ThisEdgeItr(const NodeAdjEdgeIterator &node1ThisEdgeItr) { + this->node1ThisEdgeItr = node1ThisEdgeItr; + } + + const NodeAdjEdgeIterator& getNode1ThisEdgeItr() const { + return node1ThisEdgeItr; + } + + void setNode2ThisEdgeItr(const NodeAdjEdgeIterator &node2ThisEdgeItr) { + this->node2ThisEdgeItr = node2ThisEdgeItr; + } + + const NodeAdjEdgeIterator& getNode2ThisEdgeItr() const { + return node2ThisEdgeItr; + } + +}; + + +} + +#endif // LLVM_CODEGEN_PBQP_GRAPHBASE_HPP diff --git a/libclamav/c++/llvm/lib/CodeGen/PBQP/HeuristicSolver.h b/libclamav/c++/llvm/lib/CodeGen/PBQP/HeuristicSolver.h new file mode 100644 index 000000000..e786246b4 --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/PBQP/HeuristicSolver.h @@ -0,0 +1,789 @@ +//===-- HeuristicSolver.h - Heuristic PBQP Solver --------------*- C++ --*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Heuristic PBQP solver. This solver is able to perform optimal reductions for +// nodes of degree 0, 1 or 2. For nodes of degree >2 a plugable heuristic is +// used to to select a node for reduction. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_PBQP_HEURISTICSOLVER_H +#define LLVM_CODEGEN_PBQP_HEURISTICSOLVER_H + +#include "Solver.h" +#include "AnnotatedGraph.h" +#include "llvm/Support/raw_ostream.h" +#include + +namespace PBQP { + +/// \brief Important types for the HeuristicSolverImpl. +/// +/// Declared seperately to allow access to heuristic classes before the solver +/// is fully constructed. +template +class HSITypes { +public: + + class NodeData; + class EdgeData; + + typedef AnnotatedGraph SolverGraph; + typedef typename SolverGraph::NodeIterator GraphNodeIterator; + typedef typename SolverGraph::EdgeIterator GraphEdgeIterator; + typedef typename SolverGraph::AdjEdgeIterator GraphAdjEdgeIterator; + + typedef std::list NodeList; + typedef typename NodeList::iterator NodeListIterator; + + typedef std::vector NodeStack; + typedef typename NodeStack::iterator NodeStackIterator; + + class NodeData { + friend class EdgeData; + + private: + + typedef std::list LinksList; + + unsigned numLinks; + LinksList links, solvedLinks; + NodeListIterator bucketItr; + HeuristicNodeData heuristicData; + + public: + + typedef typename LinksList::iterator AdjLinkIterator; + + private: + + AdjLinkIterator addLink(const GraphEdgeIterator &edgeItr) { + ++numLinks; + return links.insert(links.end(), edgeItr); + } + + void delLink(const AdjLinkIterator &adjLinkItr) { + --numLinks; + links.erase(adjLinkItr); + } + + public: + + NodeData() : numLinks(0) {} + + unsigned getLinkDegree() const { return numLinks; } + + HeuristicNodeData& getHeuristicData() { return heuristicData; } + const HeuristicNodeData& getHeuristicData() const { + return heuristicData; + } + + void setBucketItr(const NodeListIterator &bucketItr) { + this->bucketItr = bucketItr; + } + + const NodeListIterator& getBucketItr() const { + return bucketItr; + } + + AdjLinkIterator adjLinksBegin() { + return links.begin(); + } + + AdjLinkIterator adjLinksEnd() { + return links.end(); + } + + void addSolvedLink(const GraphEdgeIterator &solvedLinkItr) { + solvedLinks.push_back(solvedLinkItr); + } + + AdjLinkIterator solvedLinksBegin() { + return solvedLinks.begin(); + } + + AdjLinkIterator solvedLinksEnd() { + return solvedLinks.end(); + } + + }; + + class EdgeData { + private: + + SolverGraph &g; + GraphNodeIterator node1Itr, node2Itr; + HeuristicEdgeData heuristicData; + typename NodeData::AdjLinkIterator node1ThisEdgeItr, node2ThisEdgeItr; + + public: + + EdgeData(SolverGraph &g) : g(g) {} + + HeuristicEdgeData& getHeuristicData() { return heuristicData; } + const HeuristicEdgeData& getHeuristicData() const { + return heuristicData; + } + + void setup(const GraphEdgeIterator &thisEdgeItr) { + node1Itr = g.getEdgeNode1Itr(thisEdgeItr); + node2Itr = g.getEdgeNode2Itr(thisEdgeItr); + + node1ThisEdgeItr = g.getNodeData(node1Itr).addLink(thisEdgeItr); + node2ThisEdgeItr = g.getNodeData(node2Itr).addLink(thisEdgeItr); + } + + void unlink() { + g.getNodeData(node1Itr).delLink(node1ThisEdgeItr); + g.getNodeData(node2Itr).delLink(node2ThisEdgeItr); + } + + }; + +}; + +template +class HeuristicSolverImpl { +public: + // Typedefs to make life easier: + typedef HSITypes HSIT; + typedef typename HSIT::SolverGraph SolverGraph; + typedef typename HSIT::NodeData NodeData; + typedef typename HSIT::EdgeData EdgeData; + typedef typename HSIT::GraphNodeIterator GraphNodeIterator; + typedef typename HSIT::GraphEdgeIterator GraphEdgeIterator; + typedef typename HSIT::GraphAdjEdgeIterator GraphAdjEdgeIterator; + + typedef typename HSIT::NodeList NodeList; + typedef typename HSIT::NodeListIterator NodeListIterator; + + typedef std::vector NodeStack; + typedef typename NodeStack::iterator NodeStackIterator; + + /// \brief Constructor, which performs all the actual solver work. + HeuristicSolverImpl(const SimpleGraph &orig) : + solution(orig.getNumNodes(), true) + { + copyGraph(orig); + simplify(); + setup(); + computeSolution(); + computeSolutionCost(orig); + } + + /// \brief Returns the graph for this solver. + SolverGraph& getGraph() { return g; } + + /// \brief Return the solution found by this solver. + const Solution& getSolution() const { return solution; } + +private: + + /// \brief Add the given node to the appropriate bucket for its link + /// degree. + void addToBucket(const GraphNodeIterator &nodeItr) { + NodeData &nodeData = g.getNodeData(nodeItr); + + switch (nodeData.getLinkDegree()) { + case 0: nodeData.setBucketItr( + r0Bucket.insert(r0Bucket.end(), nodeItr)); + break; + case 1: nodeData.setBucketItr( + r1Bucket.insert(r1Bucket.end(), nodeItr)); + break; + case 2: nodeData.setBucketItr( + r2Bucket.insert(r2Bucket.end(), nodeItr)); + break; + default: heuristic.addToRNBucket(nodeItr); + break; + } + } + + /// \brief Remove the given node from the appropriate bucket for its link + /// degree. + void removeFromBucket(const GraphNodeIterator &nodeItr) { + NodeData &nodeData = g.getNodeData(nodeItr); + + switch (nodeData.getLinkDegree()) { + case 0: r0Bucket.erase(nodeData.getBucketItr()); break; + case 1: r1Bucket.erase(nodeData.getBucketItr()); break; + case 2: r2Bucket.erase(nodeData.getBucketItr()); break; + default: heuristic.removeFromRNBucket(nodeItr); break; + } + } + +public: + + /// \brief Add a link. + void addLink(const GraphEdgeIterator &edgeItr) { + g.getEdgeData(edgeItr).setup(edgeItr); + + if ((g.getNodeData(g.getEdgeNode1Itr(edgeItr)).getLinkDegree() > 2) || + (g.getNodeData(g.getEdgeNode2Itr(edgeItr)).getLinkDegree() > 2)) { + heuristic.handleAddLink(edgeItr); + } + } + + /// \brief Remove link, update info for node. + /// + /// Only updates information for the given node, since usually the other + /// is about to be removed. + void removeLink(const GraphEdgeIterator &edgeItr, + const GraphNodeIterator &nodeItr) { + + if (g.getNodeData(nodeItr).getLinkDegree() > 2) { + heuristic.handleRemoveLink(edgeItr, nodeItr); + } + g.getEdgeData(edgeItr).unlink(); + } + + /// \brief Remove link, update info for both nodes. Useful for R2 only. + void removeLinkR2(const GraphEdgeIterator &edgeItr) { + GraphNodeIterator node1Itr = g.getEdgeNode1Itr(edgeItr); + + if (g.getNodeData(node1Itr).getLinkDegree() > 2) { + heuristic.handleRemoveLink(edgeItr, node1Itr); + } + removeLink(edgeItr, g.getEdgeNode2Itr(edgeItr)); + } + + /// \brief Removes all links connected to the given node. + void unlinkNode(const GraphNodeIterator &nodeItr) { + NodeData &nodeData = g.getNodeData(nodeItr); + + typedef std::vector TempEdgeList; + + TempEdgeList edgesToUnlink; + edgesToUnlink.reserve(nodeData.getLinkDegree()); + + // Copy adj edges into a temp vector. We want to destroy them during + // the unlink, and we can't do that while we're iterating over them. + std::copy(nodeData.adjLinksBegin(), nodeData.adjLinksEnd(), + std::back_inserter(edgesToUnlink)); + + for (typename TempEdgeList::iterator + edgeItr = edgesToUnlink.begin(), edgeEnd = edgesToUnlink.end(); + edgeItr != edgeEnd; ++edgeItr) { + + GraphNodeIterator otherNode = g.getEdgeOtherNode(*edgeItr, nodeItr); + + removeFromBucket(otherNode); + removeLink(*edgeItr, otherNode); + addToBucket(otherNode); + } + } + + /// \brief Push the given node onto the stack to be solved with + /// backpropagation. + void pushStack(const GraphNodeIterator &nodeItr) { + stack.push_back(nodeItr); + } + + /// \brief Set the solution of the given node. + void setSolution(const GraphNodeIterator &nodeItr, unsigned solIndex) { + solution.setSelection(g.getNodeID(nodeItr), solIndex); + + for (GraphAdjEdgeIterator adjEdgeItr = g.adjEdgesBegin(nodeItr), + adjEdgeEnd = g.adjEdgesEnd(nodeItr); + adjEdgeItr != adjEdgeEnd; ++adjEdgeItr) { + GraphEdgeIterator edgeItr(*adjEdgeItr); + GraphNodeIterator adjNodeItr(g.getEdgeOtherNode(edgeItr, nodeItr)); + g.getNodeData(adjNodeItr).addSolvedLink(edgeItr); + } + } + +private: + + SolverGraph g; + Heuristic heuristic; + Solution solution; + + NodeList r0Bucket, + r1Bucket, + r2Bucket; + + NodeStack stack; + + // Copy the SimpleGraph into an annotated graph which we can use for reduction. + void copyGraph(const SimpleGraph &orig) { + + assert((g.getNumEdges() == 0) && (g.getNumNodes() == 0) && + "Graph should be empty prior to solver setup."); + + assert(orig.areNodeIDsValid() && + "Cannot copy from a graph with invalid node IDs."); + + std::vector newNodeItrs; + + for (unsigned nodeID = 0; nodeID < orig.getNumNodes(); ++nodeID) { + newNodeItrs.push_back( + g.addNode(orig.getNodeCosts(orig.getNodeItr(nodeID)), NodeData())); + } + + for (SimpleGraph::ConstEdgeIterator + origEdgeItr = orig.edgesBegin(), origEdgeEnd = orig.edgesEnd(); + origEdgeItr != origEdgeEnd; ++origEdgeItr) { + + unsigned id1 = orig.getNodeID(orig.getEdgeNode1Itr(origEdgeItr)), + id2 = orig.getNodeID(orig.getEdgeNode2Itr(origEdgeItr)); + + g.addEdge(newNodeItrs[id1], newNodeItrs[id2], + orig.getEdgeCosts(origEdgeItr), EdgeData(g)); + } + + // Assign IDs to the new nodes using the ordering from the old graph, + // this will lead to nodes in the new graph getting the same ID as the + // corresponding node in the old graph. + g.assignNodeIDs(newNodeItrs); + } + + // Simplify the annotated graph by eliminating independent edges and trivial + // nodes. + void simplify() { + disconnectTrivialNodes(); + eliminateIndependentEdges(); + } + + // Eliminate trivial nodes. + void disconnectTrivialNodes() { + for (GraphNodeIterator nodeItr = g.nodesBegin(), nodeEnd = g.nodesEnd(); + nodeItr != nodeEnd; ++nodeItr) { + + if (g.getNodeCosts(nodeItr).getLength() == 1) { + + std::vector edgesToRemove; + + for (GraphAdjEdgeIterator adjEdgeItr = g.adjEdgesBegin(nodeItr), + adjEdgeEnd = g.adjEdgesEnd(nodeItr); + adjEdgeItr != adjEdgeEnd; ++adjEdgeItr) { + + GraphEdgeIterator edgeItr = *adjEdgeItr; + + if (g.getEdgeNode1Itr(edgeItr) == nodeItr) { + GraphNodeIterator otherNodeItr = g.getEdgeNode2Itr(edgeItr); + g.getNodeCosts(otherNodeItr) += + g.getEdgeCosts(edgeItr).getRowAsVector(0); + } + else { + GraphNodeIterator otherNodeItr = g.getEdgeNode1Itr(edgeItr); + g.getNodeCosts(otherNodeItr) += + g.getEdgeCosts(edgeItr).getColAsVector(0); + } + + edgesToRemove.push_back(edgeItr); + } + + while (!edgesToRemove.empty()) { + g.removeEdge(edgesToRemove.back()); + edgesToRemove.pop_back(); + } + } + } + } + + void eliminateIndependentEdges() { + std::vector edgesToProcess; + + for (GraphEdgeIterator edgeItr = g.edgesBegin(), edgeEnd = g.edgesEnd(); + edgeItr != edgeEnd; ++edgeItr) { + edgesToProcess.push_back(edgeItr); + } + + while (!edgesToProcess.empty()) { + tryToEliminateEdge(edgesToProcess.back()); + edgesToProcess.pop_back(); + } + } + + void tryToEliminateEdge(const GraphEdgeIterator &edgeItr) { + if (tryNormaliseEdgeMatrix(edgeItr)) { + g.removeEdge(edgeItr); + } + } + + bool tryNormaliseEdgeMatrix(const GraphEdgeIterator &edgeItr) { + + Matrix &edgeCosts = g.getEdgeCosts(edgeItr); + Vector &uCosts = g.getNodeCosts(g.getEdgeNode1Itr(edgeItr)), + &vCosts = g.getNodeCosts(g.getEdgeNode2Itr(edgeItr)); + + for (unsigned r = 0; r < edgeCosts.getRows(); ++r) { + PBQPNum rowMin = edgeCosts.getRowMin(r); + uCosts[r] += rowMin; + if (rowMin != std::numeric_limits::infinity()) { + edgeCosts.subFromRow(r, rowMin); + } + else { + edgeCosts.setRow(r, 0); + } + } + + for (unsigned c = 0; c < edgeCosts.getCols(); ++c) { + PBQPNum colMin = edgeCosts.getColMin(c); + vCosts[c] += colMin; + if (colMin != std::numeric_limits::infinity()) { + edgeCosts.subFromCol(c, colMin); + } + else { + edgeCosts.setCol(c, 0); + } + } + + return edgeCosts.isZero(); + } + + void setup() { + setupLinks(); + heuristic.initialise(*this); + setupBuckets(); + } + + void setupLinks() { + for (GraphEdgeIterator edgeItr = g.edgesBegin(), edgeEnd = g.edgesEnd(); + edgeItr != edgeEnd; ++edgeItr) { + g.getEdgeData(edgeItr).setup(edgeItr); + } + } + + void setupBuckets() { + for (GraphNodeIterator nodeItr = g.nodesBegin(), nodeEnd = g.nodesEnd(); + nodeItr != nodeEnd; ++nodeItr) { + addToBucket(nodeItr); + } + } + + void computeSolution() { + assert(g.areNodeIDsValid() && + "Nodes cannot be added/removed during reduction."); + + reduce(); + computeTrivialSolutions(); + backpropagate(); + } + + void printNode(const GraphNodeIterator &nodeItr) { + llvm::errs() << "Node " << g.getNodeID(nodeItr) << " (" << &*nodeItr << "):\n" + << " costs = " << g.getNodeCosts(nodeItr) << "\n" + << " link degree = " << g.getNodeData(nodeItr).getLinkDegree() << "\n" + << " links = [ "; + + for (typename HSIT::NodeData::AdjLinkIterator + aeItr = g.getNodeData(nodeItr).adjLinksBegin(), + aeEnd = g.getNodeData(nodeItr).adjLinksEnd(); + aeItr != aeEnd; ++aeItr) { + llvm::errs() << "(" << g.getNodeID(g.getEdgeNode1Itr(*aeItr)) + << ", " << g.getNodeID(g.getEdgeNode2Itr(*aeItr)) + << ") "; + } + llvm::errs() << "]\n"; + } + + void dumpState() { + llvm::errs() << "\n"; + + for (GraphNodeIterator nodeItr = g.nodesBegin(), nodeEnd = g.nodesEnd(); + nodeItr != nodeEnd; ++nodeItr) { + printNode(nodeItr); + } + + NodeList* buckets[] = { &r0Bucket, &r1Bucket, &r2Bucket }; + + for (unsigned b = 0; b < 3; ++b) { + NodeList &bucket = *buckets[b]; + + llvm::errs() << "Bucket " << b << ": [ "; + + for (NodeListIterator nItr = bucket.begin(), nEnd = bucket.end(); + nItr != nEnd; ++nItr) { + llvm::errs() << g.getNodeID(*nItr) << " "; + } + + llvm::errs() << "]\n"; + } + + llvm::errs() << "Stack: [ "; + for (NodeStackIterator nsItr = stack.begin(), nsEnd = stack.end(); + nsItr != nsEnd; ++nsItr) { + llvm::errs() << g.getNodeID(*nsItr) << " "; + } + llvm::errs() << "]\n"; + } + + void reduce() { + bool reductionFinished = r1Bucket.empty() && r2Bucket.empty() && + heuristic.rNBucketEmpty(); + + while (!reductionFinished) { + + if (!r1Bucket.empty()) { + processR1(); + } + else if (!r2Bucket.empty()) { + processR2(); + } + else if (!heuristic.rNBucketEmpty()) { + solution.setProvedOptimal(false); + solution.incRNReductions(); + heuristic.processRN(); + } + else reductionFinished = true; + } + + }; + + void processR1() { + + // Remove the first node in the R0 bucket: + GraphNodeIterator xNodeItr = r1Bucket.front(); + r1Bucket.pop_front(); + + solution.incR1Reductions(); + + //llvm::errs() << "Applying R1 to " << g.getNodeID(xNodeItr) << "\n"; + + assert((g.getNodeData(xNodeItr).getLinkDegree() == 1) && + "Node in R1 bucket has degree != 1"); + + GraphEdgeIterator edgeItr = *g.getNodeData(xNodeItr).adjLinksBegin(); + + const Matrix &edgeCosts = g.getEdgeCosts(edgeItr); + + const Vector &xCosts = g.getNodeCosts(xNodeItr); + unsigned xLen = xCosts.getLength(); + + // Duplicate a little code to avoid transposing matrices: + if (xNodeItr == g.getEdgeNode1Itr(edgeItr)) { + GraphNodeIterator yNodeItr = g.getEdgeNode2Itr(edgeItr); + Vector &yCosts = g.getNodeCosts(yNodeItr); + unsigned yLen = yCosts.getLength(); + + for (unsigned j = 0; j < yLen; ++j) { + PBQPNum min = edgeCosts[0][j] + xCosts[0]; + for (unsigned i = 1; i < xLen; ++i) { + PBQPNum c = edgeCosts[i][j] + xCosts[i]; + if (c < min) + min = c; + } + yCosts[j] += min; + } + } + else { + GraphNodeIterator yNodeItr = g.getEdgeNode1Itr(edgeItr); + Vector &yCosts = g.getNodeCosts(yNodeItr); + unsigned yLen = yCosts.getLength(); + + for (unsigned i = 0; i < yLen; ++i) { + PBQPNum min = edgeCosts[i][0] + xCosts[0]; + + for (unsigned j = 1; j < xLen; ++j) { + PBQPNum c = edgeCosts[i][j] + xCosts[j]; + if (c < min) + min = c; + } + yCosts[i] += min; + } + } + + unlinkNode(xNodeItr); + pushStack(xNodeItr); + } + + void processR2() { + + GraphNodeIterator xNodeItr = r2Bucket.front(); + r2Bucket.pop_front(); + + solution.incR2Reductions(); + + // Unlink is unsafe here. At some point it may optimistically more a node + // to a lower-degree list when its degree will later rise, or vice versa, + // violating the assumption that node degrees monotonically decrease + // during the reduction phase. Instead we'll bucket shuffle manually. + pushStack(xNodeItr); + + assert((g.getNodeData(xNodeItr).getLinkDegree() == 2) && + "Node in R2 bucket has degree != 2"); + + const Vector &xCosts = g.getNodeCosts(xNodeItr); + + typename NodeData::AdjLinkIterator tempItr = + g.getNodeData(xNodeItr).adjLinksBegin(); + + GraphEdgeIterator yxEdgeItr = *tempItr, + zxEdgeItr = *(++tempItr); + + GraphNodeIterator yNodeItr = g.getEdgeOtherNode(yxEdgeItr, xNodeItr), + zNodeItr = g.getEdgeOtherNode(zxEdgeItr, xNodeItr); + + removeFromBucket(yNodeItr); + removeFromBucket(zNodeItr); + + removeLink(yxEdgeItr, yNodeItr); + removeLink(zxEdgeItr, zNodeItr); + + // Graph some of the costs: + bool flipEdge1 = (g.getEdgeNode1Itr(yxEdgeItr) == xNodeItr), + flipEdge2 = (g.getEdgeNode1Itr(zxEdgeItr) == xNodeItr); + + const Matrix *yxCosts = flipEdge1 ? + new Matrix(g.getEdgeCosts(yxEdgeItr).transpose()) : + &g.getEdgeCosts(yxEdgeItr), + *zxCosts = flipEdge2 ? + new Matrix(g.getEdgeCosts(zxEdgeItr).transpose()) : + &g.getEdgeCosts(zxEdgeItr); + + unsigned xLen = xCosts.getLength(), + yLen = yxCosts->getRows(), + zLen = zxCosts->getRows(); + + // Compute delta: + Matrix delta(yLen, zLen); + + for (unsigned i = 0; i < yLen; ++i) { + for (unsigned j = 0; j < zLen; ++j) { + PBQPNum min = (*yxCosts)[i][0] + (*zxCosts)[j][0] + xCosts[0]; + for (unsigned k = 1; k < xLen; ++k) { + PBQPNum c = (*yxCosts)[i][k] + (*zxCosts)[j][k] + xCosts[k]; + if (c < min) { + min = c; + } + } + delta[i][j] = min; + } + } + + if (flipEdge1) + delete yxCosts; + + if (flipEdge2) + delete zxCosts; + + // Deal with the potentially induced yz edge. + GraphEdgeIterator yzEdgeItr = g.findEdge(yNodeItr, zNodeItr); + if (yzEdgeItr == g.edgesEnd()) { + yzEdgeItr = g.addEdge(yNodeItr, zNodeItr, delta, EdgeData(g)); + } + else { + // There was an edge, but we're going to screw with it. Delete the old + // link, update the costs. We'll re-link it later. + removeLinkR2(yzEdgeItr); + g.getEdgeCosts(yzEdgeItr) += + (yNodeItr == g.getEdgeNode1Itr(yzEdgeItr)) ? + delta : delta.transpose(); + } + + bool nullCostEdge = tryNormaliseEdgeMatrix(yzEdgeItr); + + // Nulled the edge, remove it entirely. + if (nullCostEdge) { + g.removeEdge(yzEdgeItr); + } + else { + // Edge remains - re-link it. + addLink(yzEdgeItr); + } + + addToBucket(yNodeItr); + addToBucket(zNodeItr); + } + + void computeTrivialSolutions() { + + for (NodeListIterator r0Itr = r0Bucket.begin(), r0End = r0Bucket.end(); + r0Itr != r0End; ++r0Itr) { + GraphNodeIterator nodeItr = *r0Itr; + + solution.incR0Reductions(); + setSolution(nodeItr, g.getNodeCosts(nodeItr).minIndex()); + } + + } + + void backpropagate() { + while (!stack.empty()) { + computeSolution(stack.back()); + stack.pop_back(); + } + } + + void computeSolution(const GraphNodeIterator &nodeItr) { + + NodeData &nodeData = g.getNodeData(nodeItr); + + Vector v(g.getNodeCosts(nodeItr)); + + // Solve based on existing links. + for (typename NodeData::AdjLinkIterator + solvedLinkItr = nodeData.solvedLinksBegin(), + solvedLinkEnd = nodeData.solvedLinksEnd(); + solvedLinkItr != solvedLinkEnd; ++solvedLinkItr) { + + GraphEdgeIterator solvedEdgeItr(*solvedLinkItr); + Matrix &edgeCosts = g.getEdgeCosts(solvedEdgeItr); + + if (nodeItr == g.getEdgeNode1Itr(solvedEdgeItr)) { + GraphNodeIterator adjNode(g.getEdgeNode2Itr(solvedEdgeItr)); + unsigned adjSolution = + solution.getSelection(g.getNodeID(adjNode)); + v += edgeCosts.getColAsVector(adjSolution); + } + else { + GraphNodeIterator adjNode(g.getEdgeNode1Itr(solvedEdgeItr)); + unsigned adjSolution = + solution.getSelection(g.getNodeID(adjNode)); + v += edgeCosts.getRowAsVector(adjSolution); + } + + } + + setSolution(nodeItr, v.minIndex()); + } + + void computeSolutionCost(const SimpleGraph &orig) { + PBQPNum cost = 0.0; + + for (SimpleGraph::ConstNodeIterator + nodeItr = orig.nodesBegin(), nodeEnd = orig.nodesEnd(); + nodeItr != nodeEnd; ++nodeItr) { + + unsigned nodeId = orig.getNodeID(nodeItr); + + cost += orig.getNodeCosts(nodeItr)[solution.getSelection(nodeId)]; + } + + for (SimpleGraph::ConstEdgeIterator + edgeItr = orig.edgesBegin(), edgeEnd = orig.edgesEnd(); + edgeItr != edgeEnd; ++edgeItr) { + + SimpleGraph::ConstNodeIterator n1 = orig.getEdgeNode1Itr(edgeItr), + n2 = orig.getEdgeNode2Itr(edgeItr); + unsigned sol1 = solution.getSelection(orig.getNodeID(n1)), + sol2 = solution.getSelection(orig.getNodeID(n2)); + + cost += orig.getEdgeCosts(edgeItr)[sol1][sol2]; + } + + solution.setSolutionCost(cost); + } + +}; + +template +class HeuristicSolver : public Solver { +public: + Solution solve(const SimpleGraph &g) const { + HeuristicSolverImpl solverImpl(g); + return solverImpl.getSolution(); + } +}; + +} + +#endif // LLVM_CODEGEN_PBQP_HEURISTICSOLVER_H diff --git a/libclamav/c++/llvm/lib/CodeGen/PBQP/Heuristics/Briggs.h b/libclamav/c++/llvm/lib/CodeGen/PBQP/Heuristics/Briggs.h new file mode 100644 index 000000000..3ac9e707b --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/PBQP/Heuristics/Briggs.h @@ -0,0 +1,383 @@ +//===-- Briggs.h --- Briggs Heuristic for PBQP -----------------*- C++ --*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This class implements the Briggs test for "allocability" of nodes in a +// PBQP graph representing a register allocation problem. Nodes which can be +// proven allocable (by a safe and relatively accurate test) are removed from +// the PBQP graph first. If no provably allocable node is present in the graph +// then the node with the minimal spill-cost to degree ratio is removed. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_PBQP_HEURISTICS_BRIGGS_H +#define LLVM_CODEGEN_PBQP_HEURISTICS_BRIGGS_H + +#include "../HeuristicSolver.h" + +#include + +namespace PBQP { +namespace Heuristics { + +class Briggs { + public: + + class NodeData; + class EdgeData; + + private: + + typedef HeuristicSolverImpl Solver; + typedef HSITypes HSIT; + typedef HSIT::SolverGraph SolverGraph; + typedef HSIT::GraphNodeIterator GraphNodeIterator; + typedef HSIT::GraphEdgeIterator GraphEdgeIterator; + + class LinkDegreeComparator { + public: + LinkDegreeComparator() : g(0) {} + LinkDegreeComparator(SolverGraph *g) : g(g) {} + + bool operator()(const GraphNodeIterator &node1Itr, + const GraphNodeIterator &node2Itr) const { + assert((g != 0) && "Graph object not set, cannot access node data."); + unsigned n1Degree = g->getNodeData(node1Itr).getLinkDegree(), + n2Degree = g->getNodeData(node2Itr).getLinkDegree(); + if (n1Degree > n2Degree) { + return true; + } + else if (n1Degree < n2Degree) { + return false; + } + // else they're "equal" by degree, differentiate based on ID. + return g->getNodeID(node1Itr) < g->getNodeID(node2Itr); + } + + private: + SolverGraph *g; + }; + + class SpillPriorityComparator { + public: + SpillPriorityComparator() : g(0) {} + SpillPriorityComparator(SolverGraph *g) : g(g) {} + + bool operator()(const GraphNodeIterator &node1Itr, + const GraphNodeIterator &node2Itr) const { + assert((g != 0) && "Graph object not set, cannot access node data."); + PBQPNum cost1 = + g->getNodeCosts(node1Itr)[0] / + g->getNodeData(node1Itr).getLinkDegree(), + cost2 = + g->getNodeCosts(node2Itr)[0] / + g->getNodeData(node2Itr).getLinkDegree(); + + if (cost1 < cost2) { + return true; + } + else if (cost1 > cost2) { + return false; + } + // else they'er "equal" again, differentiate based on address again. + return g->getNodeID(node1Itr) < g->getNodeID(node2Itr); + } + + private: + SolverGraph *g; + }; + + typedef std::set + RNAllocableNodeList; + typedef RNAllocableNodeList::iterator RNAllocableNodeListIterator; + + typedef std::set + RNUnallocableNodeList; + typedef RNUnallocableNodeList::iterator RNUnallocableNodeListIterator; + + public: + + class NodeData { + private: + RNAllocableNodeListIterator rNAllocableNodeListItr; + RNUnallocableNodeListIterator rNUnallocableNodeListItr; + unsigned numRegOptions, numDenied, numSafe; + std::vector unsafeDegrees; + bool allocable; + + void addRemoveLink(SolverGraph &g, const GraphNodeIterator &nodeItr, + const GraphEdgeIterator &edgeItr, bool add) { + + //assume we're adding... + unsigned udTarget = 0, dir = 1; + + if (!add) { + udTarget = 1; + dir = ~0; + } + + EdgeData &linkEdgeData = g.getEdgeData(edgeItr).getHeuristicData(); + + EdgeData::ConstUnsafeIterator edgeUnsafeBegin, edgeUnsafeEnd; + + if (nodeItr == g.getEdgeNode1Itr(edgeItr)) { + numDenied += (dir * linkEdgeData.getWorstDegree()); + edgeUnsafeBegin = linkEdgeData.unsafeBegin(); + edgeUnsafeEnd = linkEdgeData.unsafeEnd(); + } + else { + numDenied += (dir * linkEdgeData.getReverseWorstDegree()); + edgeUnsafeBegin = linkEdgeData.reverseUnsafeBegin(); + edgeUnsafeEnd = linkEdgeData.reverseUnsafeEnd(); + } + + assert((unsafeDegrees.size() == + static_cast( + std::distance(edgeUnsafeBegin, edgeUnsafeEnd))) + && "Unsafe array size mismatch."); + + std::vector::iterator unsafeDegreesItr = + unsafeDegrees.begin(); + + for (EdgeData::ConstUnsafeIterator edgeUnsafeItr = edgeUnsafeBegin; + edgeUnsafeItr != edgeUnsafeEnd; + ++edgeUnsafeItr, ++unsafeDegreesItr) { + + if ((*edgeUnsafeItr == 1) && (*unsafeDegreesItr == udTarget)) { + numSafe -= dir; + } + *unsafeDegreesItr += (dir * (*edgeUnsafeItr)); + } + + allocable = (numDenied < numRegOptions) || (numSafe > 0); + } + + public: + + void setup(SolverGraph &g, const GraphNodeIterator &nodeItr) { + + numRegOptions = g.getNodeCosts(nodeItr).getLength() - 1; + + numSafe = numRegOptions; // Optimistic, correct below. + numDenied = 0; // Also optimistic. + unsafeDegrees.resize(numRegOptions, 0); + + HSIT::NodeData &nodeData = g.getNodeData(nodeItr); + + for (HSIT::NodeData::AdjLinkIterator + adjLinkItr = nodeData.adjLinksBegin(), + adjLinkEnd = nodeData.adjLinksEnd(); + adjLinkItr != adjLinkEnd; ++adjLinkItr) { + + addRemoveLink(g, nodeItr, *adjLinkItr, true); + } + } + + bool isAllocable() const { return allocable; } + + void handleAddLink(SolverGraph &g, const GraphNodeIterator &nodeItr, + const GraphEdgeIterator &adjEdge) { + addRemoveLink(g, nodeItr, adjEdge, true); + } + + void handleRemoveLink(SolverGraph &g, const GraphNodeIterator &nodeItr, + const GraphEdgeIterator &adjEdge) { + addRemoveLink(g, nodeItr, adjEdge, false); + } + + void setRNAllocableNodeListItr( + const RNAllocableNodeListIterator &rNAllocableNodeListItr) { + + this->rNAllocableNodeListItr = rNAllocableNodeListItr; + } + + RNAllocableNodeListIterator getRNAllocableNodeListItr() const { + return rNAllocableNodeListItr; + } + + void setRNUnallocableNodeListItr( + const RNUnallocableNodeListIterator &rNUnallocableNodeListItr) { + + this->rNUnallocableNodeListItr = rNUnallocableNodeListItr; + } + + RNUnallocableNodeListIterator getRNUnallocableNodeListItr() const { + return rNUnallocableNodeListItr; + } + + + }; + + class EdgeData { + private: + + typedef std::vector UnsafeArray; + + unsigned worstDegree, + reverseWorstDegree; + UnsafeArray unsafe, reverseUnsafe; + + public: + + EdgeData() : worstDegree(0), reverseWorstDegree(0) {} + + typedef UnsafeArray::const_iterator ConstUnsafeIterator; + + void setup(SolverGraph &g, const GraphEdgeIterator &edgeItr) { + const Matrix &edgeCosts = g.getEdgeCosts(edgeItr); + unsigned numRegs = edgeCosts.getRows() - 1, + numReverseRegs = edgeCosts.getCols() - 1; + + unsafe.resize(numRegs, 0); + reverseUnsafe.resize(numReverseRegs, 0); + + std::vector rowInfCounts(numRegs, 0), + colInfCounts(numReverseRegs, 0); + + for (unsigned i = 0; i < numRegs; ++i) { + for (unsigned j = 0; j < numReverseRegs; ++j) { + if (edgeCosts[i + 1][j + 1] == + std::numeric_limits::infinity()) { + unsafe[i] = 1; + reverseUnsafe[j] = 1; + ++rowInfCounts[i]; + ++colInfCounts[j]; + + if (colInfCounts[j] > worstDegree) { + worstDegree = colInfCounts[j]; + } + + if (rowInfCounts[i] > reverseWorstDegree) { + reverseWorstDegree = rowInfCounts[i]; + } + } + } + } + } + + unsigned getWorstDegree() const { return worstDegree; } + unsigned getReverseWorstDegree() const { return reverseWorstDegree; } + ConstUnsafeIterator unsafeBegin() const { return unsafe.begin(); } + ConstUnsafeIterator unsafeEnd() const { return unsafe.end(); } + ConstUnsafeIterator reverseUnsafeBegin() const { + return reverseUnsafe.begin(); + } + ConstUnsafeIterator reverseUnsafeEnd() const { + return reverseUnsafe.end(); + } + }; + + void initialise(Solver &solver) { + this->s = &solver; + g = &s->getGraph(); + rNAllocableBucket = RNAllocableNodeList(LinkDegreeComparator(g)); + rNUnallocableBucket = + RNUnallocableNodeList(SpillPriorityComparator(g)); + + for (GraphEdgeIterator + edgeItr = g->edgesBegin(), edgeEnd = g->edgesEnd(); + edgeItr != edgeEnd; ++edgeItr) { + + g->getEdgeData(edgeItr).getHeuristicData().setup(*g, edgeItr); + } + + for (GraphNodeIterator + nodeItr = g->nodesBegin(), nodeEnd = g->nodesEnd(); + nodeItr != nodeEnd; ++nodeItr) { + + g->getNodeData(nodeItr).getHeuristicData().setup(*g, nodeItr); + } + } + + void addToRNBucket(const GraphNodeIterator &nodeItr) { + NodeData &nodeData = g->getNodeData(nodeItr).getHeuristicData(); + + if (nodeData.isAllocable()) { + nodeData.setRNAllocableNodeListItr( + rNAllocableBucket.insert(rNAllocableBucket.begin(), nodeItr)); + } + else { + nodeData.setRNUnallocableNodeListItr( + rNUnallocableBucket.insert(rNUnallocableBucket.begin(), nodeItr)); + } + } + + void removeFromRNBucket(const GraphNodeIterator &nodeItr) { + NodeData &nodeData = g->getNodeData(nodeItr).getHeuristicData(); + + if (nodeData.isAllocable()) { + rNAllocableBucket.erase(nodeData.getRNAllocableNodeListItr()); + } + else { + rNUnallocableBucket.erase(nodeData.getRNUnallocableNodeListItr()); + } + } + + void handleAddLink(const GraphEdgeIterator &edgeItr) { + // We assume that if we got here this edge is attached to at least + // one high degree node. + g->getEdgeData(edgeItr).getHeuristicData().setup(*g, edgeItr); + + GraphNodeIterator n1Itr = g->getEdgeNode1Itr(edgeItr), + n2Itr = g->getEdgeNode2Itr(edgeItr); + + HSIT::NodeData &n1Data = g->getNodeData(n1Itr), + &n2Data = g->getNodeData(n2Itr); + + if (n1Data.getLinkDegree() > 2) { + n1Data.getHeuristicData().handleAddLink(*g, n1Itr, edgeItr); + } + if (n2Data.getLinkDegree() > 2) { + n2Data.getHeuristicData().handleAddLink(*g, n2Itr, edgeItr); + } + } + + void handleRemoveLink(const GraphEdgeIterator &edgeItr, + const GraphNodeIterator &nodeItr) { + NodeData &nodeData = g->getNodeData(nodeItr).getHeuristicData(); + nodeData.handleRemoveLink(*g, nodeItr, edgeItr); + } + + void processRN() { + + if (!rNAllocableBucket.empty()) { + GraphNodeIterator selectedNodeItr = *rNAllocableBucket.begin(); + //std::cerr << "RN safely pushing " << g->getNodeID(selectedNodeItr) << "\n"; + rNAllocableBucket.erase(rNAllocableBucket.begin()); + s->pushStack(selectedNodeItr); + s->unlinkNode(selectedNodeItr); + } + else { + GraphNodeIterator selectedNodeItr = *rNUnallocableBucket.begin(); + //std::cerr << "RN optimistically pushing " << g->getNodeID(selectedNodeItr) << "\n"; + rNUnallocableBucket.erase(rNUnallocableBucket.begin()); + s->pushStack(selectedNodeItr); + s->unlinkNode(selectedNodeItr); + } + + } + + bool rNBucketEmpty() const { + return (rNAllocableBucket.empty() && rNUnallocableBucket.empty()); + } + +private: + + Solver *s; + SolverGraph *g; + RNAllocableNodeList rNAllocableBucket; + RNUnallocableNodeList rNUnallocableBucket; +}; + + + +} +} + + +#endif // LLVM_CODEGEN_PBQP_HEURISTICS_BRIGGS_H diff --git a/libclamav/c++/llvm/lib/CodeGen/PBQP/PBQPMath.h b/libclamav/c++/llvm/lib/CodeGen/PBQP/PBQPMath.h new file mode 100644 index 000000000..11f4b4b4e --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/PBQP/PBQPMath.h @@ -0,0 +1,288 @@ +//===-- PBQPMath.h - PBQP Vector and Matrix classes ------------*- C++ --*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_PBQP_PBQPMATH_H +#define LLVM_CODEGEN_PBQP_PBQPMATH_H + +#include +#include +#include + +namespace PBQP { + +typedef double PBQPNum; + +/// \brief PBQP Vector class. +class Vector { + public: + + /// \brief Construct a PBQP vector of the given size. + explicit Vector(unsigned length) : + length(length), data(new PBQPNum[length]) { + } + + /// \brief Construct a PBQP vector with initializer. + Vector(unsigned length, PBQPNum initVal) : + length(length), data(new PBQPNum[length]) { + std::fill(data, data + length, initVal); + } + + /// \brief Copy construct a PBQP vector. + Vector(const Vector &v) : + length(v.length), data(new PBQPNum[length]) { + std::copy(v.data, v.data + length, data); + } + + /// \brief Destroy this vector, return its memory. + ~Vector() { delete[] data; } + + /// \brief Assignment operator. + Vector& operator=(const Vector &v) { + delete[] data; + length = v.length; + data = new PBQPNum[length]; + std::copy(v.data, v.data + length, data); + return *this; + } + + /// \brief Return the length of the vector + unsigned getLength() const { + return length; + } + + /// \brief Element access. + PBQPNum& operator[](unsigned index) { + assert(index < length && "Vector element access out of bounds."); + return data[index]; + } + + /// \brief Const element access. + const PBQPNum& operator[](unsigned index) const { + assert(index < length && "Vector element access out of bounds."); + return data[index]; + } + + /// \brief Add another vector to this one. + Vector& operator+=(const Vector &v) { + assert(length == v.length && "Vector length mismatch."); + std::transform(data, data + length, v.data, data, std::plus()); + return *this; + } + + /// \brief Subtract another vector from this one. + Vector& operator-=(const Vector &v) { + assert(length == v.length && "Vector length mismatch."); + std::transform(data, data + length, v.data, data, std::minus()); + return *this; + } + + /// \brief Returns the index of the minimum value in this vector + unsigned minIndex() const { + return std::min_element(data, data + length) - data; + } + + private: + unsigned length; + PBQPNum *data; +}; + +/// \brief Output a textual representation of the given vector on the given +/// output stream. +template +OStream& operator<<(OStream &os, const Vector &v) { + assert((v.getLength() != 0) && "Zero-length vector badness."); + + os << "[ " << v[0]; + for (unsigned i = 1; i < v.getLength(); ++i) { + os << ", " << v[i]; + } + os << " ]"; + + return os; +} + + +/// \brief PBQP Matrix class +class Matrix { + public: + + /// \brief Construct a PBQP Matrix with the given dimensions. + Matrix(unsigned rows, unsigned cols) : + rows(rows), cols(cols), data(new PBQPNum[rows * cols]) { + } + + /// \brief Construct a PBQP Matrix with the given dimensions and initial + /// value. + Matrix(unsigned rows, unsigned cols, PBQPNum initVal) : + rows(rows), cols(cols), data(new PBQPNum[rows * cols]) { + std::fill(data, data + (rows * cols), initVal); + } + + /// \brief Copy construct a PBQP matrix. + Matrix(const Matrix &m) : + rows(m.rows), cols(m.cols), data(new PBQPNum[rows * cols]) { + std::copy(m.data, m.data + (rows * cols), data); + } + + /// \brief Destroy this matrix, return its memory. + ~Matrix() { delete[] data; } + + /// \brief Assignment operator. + Matrix& operator=(const Matrix &m) { + delete[] data; + rows = m.rows; cols = m.cols; + data = new PBQPNum[rows * cols]; + std::copy(m.data, m.data + (rows * cols), data); + return *this; + } + + /// \brief Return the number of rows in this matrix. + unsigned getRows() const { return rows; } + + /// \brief Return the number of cols in this matrix. + unsigned getCols() const { return cols; } + + /// \brief Matrix element access. + PBQPNum* operator[](unsigned r) { + assert(r < rows && "Row out of bounds."); + return data + (r * cols); + } + + /// \brief Matrix element access. + const PBQPNum* operator[](unsigned r) const { + assert(r < rows && "Row out of bounds."); + return data + (r * cols); + } + + /// \brief Returns the given row as a vector. + Vector getRowAsVector(unsigned r) const { + Vector v(cols); + for (unsigned c = 0; c < cols; ++c) + v[c] = (*this)[r][c]; + return v; + } + + /// \brief Returns the given column as a vector. + Vector getColAsVector(unsigned c) const { + Vector v(rows); + for (unsigned r = 0; r < rows; ++r) + v[r] = (*this)[r][c]; + return v; + } + + /// \brief Reset the matrix to the given value. + Matrix& reset(PBQPNum val = 0) { + std::fill(data, data + (rows * cols), val); + return *this; + } + + /// \brief Set a single row of this matrix to the given value. + Matrix& setRow(unsigned r, PBQPNum val) { + assert(r < rows && "Row out of bounds."); + std::fill(data + (r * cols), data + ((r + 1) * cols), val); + return *this; + } + + /// \brief Set a single column of this matrix to the given value. + Matrix& setCol(unsigned c, PBQPNum val) { + assert(c < cols && "Column out of bounds."); + for (unsigned r = 0; r < rows; ++r) + (*this)[r][c] = val; + return *this; + } + + /// \brief Matrix transpose. + Matrix transpose() const { + Matrix m(cols, rows); + for (unsigned r = 0; r < rows; ++r) + for (unsigned c = 0; c < cols; ++c) + m[c][r] = (*this)[r][c]; + return m; + } + + /// \brief Returns the diagonal of the matrix as a vector. + /// + /// Matrix must be square. + Vector diagonalize() const { + assert(rows == cols && "Attempt to diagonalize non-square matrix."); + + Vector v(rows); + for (unsigned r = 0; r < rows; ++r) + v[r] = (*this)[r][r]; + return v; + } + + /// \brief Add the given matrix to this one. + Matrix& operator+=(const Matrix &m) { + assert(rows == m.rows && cols == m.cols && + "Matrix dimensions mismatch."); + std::transform(data, data + (rows * cols), m.data, data, + std::plus()); + return *this; + } + + /// \brief Returns the minimum of the given row + PBQPNum getRowMin(unsigned r) const { + assert(r < rows && "Row out of bounds"); + return *std::min_element(data + (r * cols), data + ((r + 1) * cols)); + } + + /// \brief Returns the minimum of the given column + PBQPNum getColMin(unsigned c) const { + PBQPNum minElem = (*this)[0][c]; + for (unsigned r = 1; r < rows; ++r) + if ((*this)[r][c] < minElem) minElem = (*this)[r][c]; + return minElem; + } + + /// \brief Subtracts the given scalar from the elements of the given row. + Matrix& subFromRow(unsigned r, PBQPNum val) { + assert(r < rows && "Row out of bounds"); + std::transform(data + (r * cols), data + ((r + 1) * cols), + data + (r * cols), + std::bind2nd(std::minus(), val)); + return *this; + } + + /// \brief Subtracts the given scalar from the elements of the given column. + Matrix& subFromCol(unsigned c, PBQPNum val) { + for (unsigned r = 0; r < rows; ++r) + (*this)[r][c] -= val; + return *this; + } + + /// \brief Returns true if this is a zero matrix. + bool isZero() const { + return find_if(data, data + (rows * cols), + std::bind2nd(std::not_equal_to(), 0)) == + data + (rows * cols); + } + + private: + unsigned rows, cols; + PBQPNum *data; +}; + +/// \brief Output a textual representation of the given matrix on the given +/// output stream. +template +OStream& operator<<(OStream &os, const Matrix &m) { + + assert((m.getRows() != 0) && "Zero-row matrix badness."); + + for (unsigned i = 0; i < m.getRows(); ++i) { + os << m.getRowAsVector(i); + } + + return os; +} + +} + +#endif // LLVM_CODEGEN_PBQP_PBQPMATH_HPP diff --git a/libclamav/c++/llvm/lib/CodeGen/PBQP/SimpleGraph.h b/libclamav/c++/llvm/lib/CodeGen/PBQP/SimpleGraph.h new file mode 100644 index 000000000..1ca9caee3 --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/PBQP/SimpleGraph.h @@ -0,0 +1,100 @@ +//===-- SimpleGraph.h - Simple PBQP Graph ----------------------*- C++ --*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Simple PBQP graph class representing a PBQP problem. Graphs of this type +// can be passed to a PBQPSolver instance to solve the PBQP problem. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_PBQP_SIMPLEGRAPH_H +#define LLVM_CODEGEN_PBQP_SIMPLEGRAPH_H + +#include "GraphBase.h" + +namespace PBQP { + +class SimpleEdge; + +class SimpleNode : public NodeBase { +public: + SimpleNode(const Vector &costs) : + NodeBase(costs) {} +}; + +class SimpleEdge : public EdgeBase { +public: + SimpleEdge(const NodeIterator &node1Itr, const NodeIterator &node2Itr, + const Matrix &costs) : + EdgeBase(node1Itr, node2Itr, costs) {} +}; + +class SimpleGraph : public GraphBase { +private: + + typedef GraphBase PGraph; + + void copyFrom(const SimpleGraph &other) { + assert(other.areNodeIDsValid() && + "Cannot copy from another graph unless IDs have been assigned."); + + std::vector newNodeItrs(other.getNumNodes()); + + for (ConstNodeIterator nItr = other.nodesBegin(), nEnd = other.nodesEnd(); + nItr != nEnd; ++nItr) { + newNodeItrs[other.getNodeID(nItr)] = addNode(other.getNodeCosts(nItr)); + } + + for (ConstEdgeIterator eItr = other.edgesBegin(), eEnd = other.edgesEnd(); + eItr != eEnd; ++eItr) { + + unsigned node1ID = other.getNodeID(other.getEdgeNode1Itr(eItr)), + node2ID = other.getNodeID(other.getEdgeNode2Itr(eItr)); + + addEdge(newNodeItrs[node1ID], newNodeItrs[node2ID], + other.getEdgeCosts(eItr)); + } + } + + void copyFrom(SimpleGraph &other) { + if (!other.areNodeIDsValid()) { + other.assignNodeIDs(); + } + copyFrom(const_cast(other)); + } + +public: + + SimpleGraph() {} + + + SimpleGraph(const SimpleGraph &other) : PGraph() { + copyFrom(other); + } + + SimpleGraph& operator=(const SimpleGraph &other) { + clear(); + copyFrom(other); + return *this; + } + + NodeIterator addNode(const Vector &costs) { + return PGraph::addConstructedNode(SimpleNode(costs)); + } + + EdgeIterator addEdge(const NodeIterator &node1Itr, + const NodeIterator &node2Itr, + const Matrix &costs) { + return PGraph::addConstructedEdge(SimpleEdge(node1Itr, node2Itr, costs)); + } + +}; + +} + +#endif // LLVM_CODEGEN_PBQP_SIMPLEGRAPH_H diff --git a/libclamav/c++/llvm/lib/CodeGen/PBQP/Solution.h b/libclamav/c++/llvm/lib/CodeGen/PBQP/Solution.h new file mode 100644 index 000000000..c91e2fa56 --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/PBQP/Solution.h @@ -0,0 +1,88 @@ +//===-- Solution.h ------- PBQP Solution -----------------------*- C++ --*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Annotated PBQP Graph class. This class is used internally by the PBQP solver +// to cache information to speed up reduction. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_PBQP_SOLUTION_H +#define LLVM_CODEGEN_PBQP_SOLUTION_H + +#include "PBQPMath.h" + +namespace PBQP { + +class Solution { + + friend class SolverImplementation; + +private: + + std::vector selections; + PBQPNum solutionCost; + bool provedOptimal; + unsigned r0Reductions, r1Reductions, + r2Reductions, rNReductions; + +public: + + Solution() : + solutionCost(0.0), provedOptimal(false), + r0Reductions(0), r1Reductions(0), r2Reductions(0), rNReductions(0) {} + + Solution(unsigned length, bool assumeOptimal) : + selections(length), solutionCost(0.0), provedOptimal(assumeOptimal), + r0Reductions(0), r1Reductions(0), r2Reductions(0), rNReductions(0) {} + + void setProvedOptimal(bool provedOptimal) { + this->provedOptimal = provedOptimal; + } + + void setSelection(unsigned nodeID, unsigned selection) { + selections[nodeID] = selection; + } + + void setSolutionCost(PBQPNum solutionCost) { + this->solutionCost = solutionCost; + } + + void incR0Reductions() { ++r0Reductions; } + void incR1Reductions() { ++r1Reductions; } + void incR2Reductions() { ++r2Reductions; } + void incRNReductions() { ++rNReductions; } + + unsigned numNodes() const { return selections.size(); } + + unsigned getSelection(unsigned nodeID) const { + return selections[nodeID]; + } + + PBQPNum getCost() const { return solutionCost; } + + bool isProvedOptimal() const { return provedOptimal; } + + unsigned getR0Reductions() const { return r0Reductions; } + unsigned getR1Reductions() const { return r1Reductions; } + unsigned getR2Reductions() const { return r2Reductions; } + unsigned getRNReductions() const { return rNReductions; } + + bool operator==(const Solution &other) const { + return (selections == other.selections); + } + + bool operator!=(const Solution &other) const { + return !(*this == other); + } + +}; + +} + +#endif // LLVM_CODEGEN_PBQP_SOLUTION_H diff --git a/libclamav/c++/llvm/lib/CodeGen/PBQP/Solver.h b/libclamav/c++/llvm/lib/CodeGen/PBQP/Solver.h new file mode 100644 index 000000000..a9c5f837c --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/PBQP/Solver.h @@ -0,0 +1,31 @@ +//===-- Solver.h ------- PBQP solver interface -----------------*- C++ --*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + + +#ifndef LLVM_CODEGEN_PBQP_SOLVER_H +#define LLVM_CODEGEN_PBQP_SOLVER_H + +#include "SimpleGraph.h" +#include "Solution.h" + +namespace PBQP { + +/// \brief Interface for solver classes. +class Solver { +public: + + virtual ~Solver() = 0; + virtual Solution solve(const SimpleGraph &orig) const = 0; +}; + +Solver::~Solver() {} + +} + +#endif // LLVM_CODEGEN_PBQP_SOLVER_H diff --git a/libclamav/c++/llvm/lib/CodeGen/PHIElimination.cpp b/libclamav/c++/llvm/lib/CodeGen/PHIElimination.cpp new file mode 100644 index 000000000..2e30cc6ab --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/PHIElimination.cpp @@ -0,0 +1,456 @@ +//===-- PhiElimination.cpp - Eliminate PHI nodes by inserting copies ------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This pass eliminates machine instruction PHI nodes by inserting copy +// instructions. This destroys SSA information, but is the desired input for +// some register allocators. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "phielim" +#include "PHIElimination.h" +#include "llvm/CodeGen/LiveVariables.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/CodeGen/MachineDominators.h" +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/Function.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/Debug.h" +#include +#include +using namespace llvm; + +STATISTIC(NumAtomic, "Number of atomic phis lowered"); +STATISTIC(NumSplits, "Number of critical edges split on demand"); + +char PHIElimination::ID = 0; +static RegisterPass +X("phi-node-elimination", "Eliminate PHI nodes for register allocation"); + +const PassInfo *const llvm::PHIEliminationID = &X; + +void llvm::PHIElimination::getAnalysisUsage(AnalysisUsage &AU) const { + AU.addPreserved(); + AU.addPreserved(); + // rdar://7401784 This would be nice: + // AU.addPreservedID(MachineLoopInfoID); + MachineFunctionPass::getAnalysisUsage(AU); +} + +bool llvm::PHIElimination::runOnMachineFunction(MachineFunction &Fn) { + MRI = &Fn.getRegInfo(); + + PHIDefs.clear(); + PHIKills.clear(); + bool Changed = false; + + // Split critical edges to help the coalescer + if (LiveVariables *LV = getAnalysisIfAvailable()) + for (MachineFunction::iterator I = Fn.begin(), E = Fn.end(); I != E; ++I) + Changed |= SplitPHIEdges(Fn, *I, *LV); + + // Populate VRegPHIUseCount + analyzePHINodes(Fn); + + // Eliminate PHI instructions by inserting copies into predecessor blocks. + for (MachineFunction::iterator I = Fn.begin(), E = Fn.end(); I != E; ++I) + Changed |= EliminatePHINodes(Fn, *I); + + // Remove dead IMPLICIT_DEF instructions. + for (SmallPtrSet::iterator I = ImpDefs.begin(), + E = ImpDefs.end(); I != E; ++I) { + MachineInstr *DefMI = *I; + unsigned DefReg = DefMI->getOperand(0).getReg(); + if (MRI->use_empty(DefReg)) + DefMI->eraseFromParent(); + } + + ImpDefs.clear(); + VRegPHIUseCount.clear(); + return Changed; +} + +/// EliminatePHINodes - Eliminate phi nodes by inserting copy instructions in +/// predecessor basic blocks. +/// +bool llvm::PHIElimination::EliminatePHINodes(MachineFunction &MF, + MachineBasicBlock &MBB) { + if (MBB.empty() || MBB.front().getOpcode() != TargetInstrInfo::PHI) + return false; // Quick exit for basic blocks without PHIs. + + // Get an iterator to the first instruction after the last PHI node (this may + // also be the end of the basic block). + MachineBasicBlock::iterator AfterPHIsIt = SkipPHIsAndLabels(MBB, MBB.begin()); + + while (MBB.front().getOpcode() == TargetInstrInfo::PHI) + LowerAtomicPHINode(MBB, AfterPHIsIt); + + return true; +} + +/// isSourceDefinedByImplicitDef - Return true if all sources of the phi node +/// are implicit_def's. +static bool isSourceDefinedByImplicitDef(const MachineInstr *MPhi, + const MachineRegisterInfo *MRI) { + for (unsigned i = 1; i != MPhi->getNumOperands(); i += 2) { + unsigned SrcReg = MPhi->getOperand(i).getReg(); + const MachineInstr *DefMI = MRI->getVRegDef(SrcReg); + if (!DefMI || DefMI->getOpcode() != TargetInstrInfo::IMPLICIT_DEF) + return false; + } + return true; +} + +// FindCopyInsertPoint - Find a safe place in MBB to insert a copy from SrcReg +// when following the CFG edge to SuccMBB. This needs to be after any def of +// SrcReg, but before any subsequent point where control flow might jump out of +// the basic block. +MachineBasicBlock::iterator +llvm::PHIElimination::FindCopyInsertPoint(MachineBasicBlock &MBB, + MachineBasicBlock &SuccMBB, + unsigned SrcReg) { + // Handle the trivial case trivially. + if (MBB.empty()) + return MBB.begin(); + + // Usually, we just want to insert the copy before the first terminator + // instruction. However, for the edge going to a landing pad, we must insert + // the copy before the call/invoke instruction. + if (!SuccMBB.isLandingPad()) + return MBB.getFirstTerminator(); + + // Discover any defs/uses in this basic block. + SmallPtrSet DefUsesInMBB; + for (MachineRegisterInfo::reg_iterator RI = MRI->reg_begin(SrcReg), + RE = MRI->reg_end(); RI != RE; ++RI) { + MachineInstr *DefUseMI = &*RI; + if (DefUseMI->getParent() == &MBB) + DefUsesInMBB.insert(DefUseMI); + } + + MachineBasicBlock::iterator InsertPoint; + if (DefUsesInMBB.empty()) { + // No defs. Insert the copy at the start of the basic block. + InsertPoint = MBB.begin(); + } else if (DefUsesInMBB.size() == 1) { + // Insert the copy immediately after the def/use. + InsertPoint = *DefUsesInMBB.begin(); + ++InsertPoint; + } else { + // Insert the copy immediately after the last def/use. + InsertPoint = MBB.end(); + while (!DefUsesInMBB.count(&*--InsertPoint)) {} + ++InsertPoint; + } + + // Make sure the copy goes after any phi nodes however. + return SkipPHIsAndLabels(MBB, InsertPoint); +} + +/// LowerAtomicPHINode - Lower the PHI node at the top of the specified block, +/// under the assuption that it needs to be lowered in a way that supports +/// atomic execution of PHIs. This lowering method is always correct all of the +/// time. +/// +void llvm::PHIElimination::LowerAtomicPHINode( + MachineBasicBlock &MBB, + MachineBasicBlock::iterator AfterPHIsIt) { + // Unlink the PHI node from the basic block, but don't delete the PHI yet. + MachineInstr *MPhi = MBB.remove(MBB.begin()); + + unsigned NumSrcs = (MPhi->getNumOperands() - 1) / 2; + unsigned DestReg = MPhi->getOperand(0).getReg(); + bool isDead = MPhi->getOperand(0).isDead(); + + // Create a new register for the incoming PHI arguments. + MachineFunction &MF = *MBB.getParent(); + const TargetRegisterClass *RC = MF.getRegInfo().getRegClass(DestReg); + unsigned IncomingReg = 0; + + // Insert a register to register copy at the top of the current block (but + // after any remaining phi nodes) which copies the new incoming register + // into the phi node destination. + const TargetInstrInfo *TII = MF.getTarget().getInstrInfo(); + if (isSourceDefinedByImplicitDef(MPhi, MRI)) + // If all sources of a PHI node are implicit_def, just emit an + // implicit_def instead of a copy. + BuildMI(MBB, AfterPHIsIt, MPhi->getDebugLoc(), + TII->get(TargetInstrInfo::IMPLICIT_DEF), DestReg); + else { + IncomingReg = MF.getRegInfo().createVirtualRegister(RC); + TII->copyRegToReg(MBB, AfterPHIsIt, DestReg, IncomingReg, RC, RC); + } + + // Record PHI def. + assert(!hasPHIDef(DestReg) && "Vreg has multiple phi-defs?"); + PHIDefs[DestReg] = &MBB; + + // Update live variable information if there is any. + LiveVariables *LV = getAnalysisIfAvailable(); + if (LV) { + MachineInstr *PHICopy = prior(AfterPHIsIt); + + if (IncomingReg) { + // Increment use count of the newly created virtual register. + LV->getVarInfo(IncomingReg).NumUses++; + + // Add information to LiveVariables to know that the incoming value is + // killed. Note that because the value is defined in several places (once + // each for each incoming block), the "def" block and instruction fields + // for the VarInfo is not filled in. + LV->addVirtualRegisterKilled(IncomingReg, PHICopy); + } + + // Since we are going to be deleting the PHI node, if it is the last use of + // any registers, or if the value itself is dead, we need to move this + // information over to the new copy we just inserted. + LV->removeVirtualRegistersKilled(MPhi); + + // If the result is dead, update LV. + if (isDead) { + LV->addVirtualRegisterDead(DestReg, PHICopy); + LV->removeVirtualRegisterDead(DestReg, MPhi); + } + } + + // Adjust the VRegPHIUseCount map to account for the removal of this PHI node. + for (unsigned i = 1; i != MPhi->getNumOperands(); i += 2) + --VRegPHIUseCount[BBVRegPair(MPhi->getOperand(i + 1).getMBB(), + MPhi->getOperand(i).getReg())]; + + // Now loop over all of the incoming arguments, changing them to copy into the + // IncomingReg register in the corresponding predecessor basic block. + SmallPtrSet MBBsInsertedInto; + for (int i = NumSrcs - 1; i >= 0; --i) { + unsigned SrcReg = MPhi->getOperand(i*2+1).getReg(); + assert(TargetRegisterInfo::isVirtualRegister(SrcReg) && + "Machine PHI Operands must all be virtual registers!"); + + // Get the MachineBasicBlock equivalent of the BasicBlock that is the source + // path the PHI. + MachineBasicBlock &opBlock = *MPhi->getOperand(i*2+2).getMBB(); + + // Record the kill. + PHIKills[SrcReg].insert(&opBlock); + + // If source is defined by an implicit def, there is no need to insert a + // copy. + MachineInstr *DefMI = MRI->getVRegDef(SrcReg); + if (DefMI->getOpcode() == TargetInstrInfo::IMPLICIT_DEF) { + ImpDefs.insert(DefMI); + continue; + } + + // Check to make sure we haven't already emitted the copy for this block. + // This can happen because PHI nodes may have multiple entries for the same + // basic block. + if (!MBBsInsertedInto.insert(&opBlock)) + continue; // If the copy has already been emitted, we're done. + + // Find a safe location to insert the copy, this may be the first terminator + // in the block (or end()). + MachineBasicBlock::iterator InsertPos = + FindCopyInsertPoint(opBlock, MBB, SrcReg); + + // Insert the copy. + TII->copyRegToReg(opBlock, InsertPos, IncomingReg, SrcReg, RC, RC); + + // Now update live variable information if we have it. Otherwise we're done + if (!LV) continue; + + // We want to be able to insert a kill of the register if this PHI (aka, the + // copy we just inserted) is the last use of the source value. Live + // variable analysis conservatively handles this by saying that the value is + // live until the end of the block the PHI entry lives in. If the value + // really is dead at the PHI copy, there will be no successor blocks which + // have the value live-in. + + // Also check to see if this register is in use by another PHI node which + // has not yet been eliminated. If so, it will be killed at an appropriate + // point later. + + // Is it used by any PHI instructions in this block? + bool ValueIsUsed = VRegPHIUseCount[BBVRegPair(&opBlock, SrcReg)] != 0; + + // Okay, if we now know that the value is not live out of the block, we can + // add a kill marker in this block saying that it kills the incoming value! + if (!ValueIsUsed && !isLiveOut(SrcReg, opBlock, *LV)) { + // In our final twist, we have to decide which instruction kills the + // register. In most cases this is the copy, however, the first + // terminator instruction at the end of the block may also use the value. + // In this case, we should mark *it* as being the killing block, not the + // copy. + MachineBasicBlock::iterator KillInst = prior(InsertPos); + MachineBasicBlock::iterator Term = opBlock.getFirstTerminator(); + if (Term != opBlock.end()) { + if (Term->readsRegister(SrcReg)) + KillInst = Term; + + // Check that no other terminators use values. +#ifndef NDEBUG + for (MachineBasicBlock::iterator TI = next(Term); TI != opBlock.end(); + ++TI) { + assert(!TI->readsRegister(SrcReg) && + "Terminator instructions cannot use virtual registers unless" + "they are the first terminator in a block!"); + } +#endif + } + + // Finally, mark it killed. + LV->addVirtualRegisterKilled(SrcReg, KillInst); + + // This vreg no longer lives all of the way through opBlock. + unsigned opBlockNum = opBlock.getNumber(); + LV->getVarInfo(SrcReg).AliveBlocks.reset(opBlockNum); + } + } + + // Really delete the PHI instruction now! + MF.DeleteMachineInstr(MPhi); + ++NumAtomic; +} + +/// analyzePHINodes - Gather information about the PHI nodes in here. In +/// particular, we want to map the number of uses of a virtual register which is +/// used in a PHI node. We map that to the BB the vreg is coming from. This is +/// used later to determine when the vreg is killed in the BB. +/// +void llvm::PHIElimination::analyzePHINodes(const MachineFunction& Fn) { + for (MachineFunction::const_iterator I = Fn.begin(), E = Fn.end(); + I != E; ++I) + for (MachineBasicBlock::const_iterator BBI = I->begin(), BBE = I->end(); + BBI != BBE && BBI->getOpcode() == TargetInstrInfo::PHI; ++BBI) + for (unsigned i = 1, e = BBI->getNumOperands(); i != e; i += 2) + ++VRegPHIUseCount[BBVRegPair(BBI->getOperand(i + 1).getMBB(), + BBI->getOperand(i).getReg())]; +} + +bool llvm::PHIElimination::SplitPHIEdges(MachineFunction &MF, + MachineBasicBlock &MBB, + LiveVariables &LV) { + if (MBB.empty() || MBB.front().getOpcode() != TargetInstrInfo::PHI) + return false; // Quick exit for basic blocks without PHIs. + + for (MachineBasicBlock::const_iterator BBI = MBB.begin(), BBE = MBB.end(); + BBI != BBE && BBI->getOpcode() == TargetInstrInfo::PHI; ++BBI) { + for (unsigned i = 1, e = BBI->getNumOperands(); i != e; i += 2) { + unsigned Reg = BBI->getOperand(i).getReg(); + MachineBasicBlock *PreMBB = BBI->getOperand(i+1).getMBB(); + // We break edges when registers are live out from the predecessor block + // (not considering PHI nodes). If the register is live in to this block + // anyway, we would gain nothing from splitting. + if (!LV.isLiveIn(Reg, MBB) && isLiveOut(Reg, *PreMBB, LV)) + SplitCriticalEdge(PreMBB, &MBB); + } + } + return true; +} + +bool llvm::PHIElimination::isLiveOut(unsigned Reg, const MachineBasicBlock &MBB, + LiveVariables &LV) { + LiveVariables::VarInfo &VI = LV.getVarInfo(Reg); + + // Loop over all of the successors of the basic block, checking to see if + // the value is either live in the block, or if it is killed in the block. + std::vector OpSuccBlocks; + for (MachineBasicBlock::const_succ_iterator SI = MBB.succ_begin(), + E = MBB.succ_end(); SI != E; ++SI) { + MachineBasicBlock *SuccMBB = *SI; + + // Is it alive in this successor? + unsigned SuccIdx = SuccMBB->getNumber(); + if (VI.AliveBlocks.test(SuccIdx)) + return true; + OpSuccBlocks.push_back(SuccMBB); + } + + // Check to see if this value is live because there is a use in a successor + // that kills it. + switch (OpSuccBlocks.size()) { + case 1: { + MachineBasicBlock *SuccMBB = OpSuccBlocks[0]; + for (unsigned i = 0, e = VI.Kills.size(); i != e; ++i) + if (VI.Kills[i]->getParent() == SuccMBB) + return true; + break; + } + case 2: { + MachineBasicBlock *SuccMBB1 = OpSuccBlocks[0], *SuccMBB2 = OpSuccBlocks[1]; + for (unsigned i = 0, e = VI.Kills.size(); i != e; ++i) + if (VI.Kills[i]->getParent() == SuccMBB1 || + VI.Kills[i]->getParent() == SuccMBB2) + return true; + break; + } + default: + std::sort(OpSuccBlocks.begin(), OpSuccBlocks.end()); + for (unsigned i = 0, e = VI.Kills.size(); i != e; ++i) + if (std::binary_search(OpSuccBlocks.begin(), OpSuccBlocks.end(), + VI.Kills[i]->getParent())) + return true; + } + return false; +} + +MachineBasicBlock *PHIElimination::SplitCriticalEdge(MachineBasicBlock *A, + MachineBasicBlock *B) { + assert(A && B && "Missing MBB end point"); + + MachineFunction *MF = A->getParent(); + + // We may need to update A's terminator, but we can't do that if AnalyzeBranch + // fails. If A uses a jump table, we won't touch it. + const TargetInstrInfo *TII = MF->getTarget().getInstrInfo(); + MachineBasicBlock *TBB = 0, *FBB = 0; + SmallVector Cond; + if (TII->AnalyzeBranch(*A, TBB, FBB, Cond)) + return NULL; + + ++NumSplits; + + MachineBasicBlock *NMBB = MF->CreateMachineBasicBlock(); + MF->insert(next(MachineFunction::iterator(A)), NMBB); + DEBUG(errs() << "PHIElimination splitting critical edge:" + " BB#" << A->getNumber() + << " -- BB#" << NMBB->getNumber() + << " -- BB#" << B->getNumber() << '\n'); + + A->ReplaceUsesOfBlockWith(B, NMBB); + A->updateTerminator(); + + // Insert unconditional "jump B" instruction in NMBB if necessary. + NMBB->addSuccessor(B); + if (!NMBB->isLayoutSuccessor(B)) { + Cond.clear(); + MF->getTarget().getInstrInfo()->InsertBranch(*NMBB, B, NULL, Cond); + } + + // Fix PHI nodes in B so they refer to NMBB instead of A + for (MachineBasicBlock::iterator i = B->begin(), e = B->end(); + i != e && i->getOpcode() == TargetInstrInfo::PHI; ++i) + for (unsigned ni = 1, ne = i->getNumOperands(); ni != ne; ni += 2) + if (i->getOperand(ni+1).getMBB() == A) + i->getOperand(ni+1).setMBB(NMBB); + + if (LiveVariables *LV=getAnalysisIfAvailable()) + LV->addNewBlock(NMBB, A, B); + + if (MachineDominatorTree *MDT=getAnalysisIfAvailable()) + MDT->addNewBlock(NMBB, A); + + return NMBB; +} diff --git a/libclamav/c++/llvm/lib/CodeGen/PHIElimination.h b/libclamav/c++/llvm/lib/CodeGen/PHIElimination.h new file mode 100644 index 000000000..f5872cbe8 --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/PHIElimination.h @@ -0,0 +1,142 @@ +//===-- lib/CodeGen/PHIElimination.h ----------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_PHIELIMINATION_HPP +#define LLVM_CODEGEN_PHIELIMINATION_HPP + +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallSet.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/Target/TargetInstrInfo.h" + +#include + +namespace llvm { + + /// Lower PHI instructions to copies. + class PHIElimination : public MachineFunctionPass { + MachineRegisterInfo *MRI; // Machine register information + private: + + typedef SmallSet PHIKillList; + typedef DenseMap PHIKillMap; + typedef DenseMap PHIDefMap; + + public: + + typedef PHIKillList::iterator phi_kill_iterator; + typedef PHIKillList::const_iterator const_phi_kill_iterator; + + static char ID; // Pass identification, replacement for typeid + PHIElimination() : MachineFunctionPass(&ID) {} + + virtual bool runOnMachineFunction(MachineFunction &Fn); + + virtual void getAnalysisUsage(AnalysisUsage &AU) const; + + /// Return true if the given vreg was defined by a PHI intsr prior to + /// lowering. + bool hasPHIDef(unsigned vreg) const { + return PHIDefs.count(vreg); + } + + /// Returns the block in which the PHI instruction which defined the + /// given vreg used to reside. + MachineBasicBlock* getPHIDefBlock(unsigned vreg) { + PHIDefMap::iterator phiDefItr = PHIDefs.find(vreg); + assert(phiDefItr != PHIDefs.end() && "vreg has no phi-def."); + return phiDefItr->second; + } + + /// Returns true if the given vreg was killed by a PHI instr. + bool hasPHIKills(unsigned vreg) const { + return PHIKills.count(vreg); + } + + /// Returns an iterator over the BasicBlocks which contained PHI + /// kills of this register prior to lowering. + phi_kill_iterator phiKillsBegin(unsigned vreg) { + PHIKillMap::iterator phiKillItr = PHIKills.find(vreg); + assert(phiKillItr != PHIKills.end() && "vreg has no phi-kills."); + return phiKillItr->second.begin(); + } + phi_kill_iterator phiKillsEnd(unsigned vreg) { + PHIKillMap::iterator phiKillItr = PHIKills.find(vreg); + assert(phiKillItr != PHIKills.end() && "vreg has no phi-kills."); + return phiKillItr->second.end(); + } + + private: + /// EliminatePHINodes - Eliminate phi nodes by inserting copy instructions + /// in predecessor basic blocks. + /// + bool EliminatePHINodes(MachineFunction &MF, MachineBasicBlock &MBB); + void LowerAtomicPHINode(MachineBasicBlock &MBB, + MachineBasicBlock::iterator AfterPHIsIt); + + /// analyzePHINodes - Gather information about the PHI nodes in + /// here. In particular, we want to map the number of uses of a virtual + /// register which is used in a PHI node. We map that to the BB the + /// vreg is coming from. This is used later to determine when the vreg + /// is killed in the BB. + /// + void analyzePHINodes(const MachineFunction& Fn); + + /// Split critical edges where necessary for good coalescer performance. + bool SplitPHIEdges(MachineFunction &MF, MachineBasicBlock &MBB, + LiveVariables &LV); + + /// isLiveOut - Determine if Reg is live out from MBB, when not + /// considering PHI nodes. This means that Reg is either killed by + /// a successor block or passed through one. + bool isLiveOut(unsigned Reg, const MachineBasicBlock &MBB, + LiveVariables &LV); + + /// SplitCriticalEdge - Split a critical edge from A to B by + /// inserting a new MBB. Update branches in A and PHI instructions + /// in B. Return the new block. + MachineBasicBlock *SplitCriticalEdge(MachineBasicBlock *A, + MachineBasicBlock *B); + + /// FindCopyInsertPoint - Find a safe place in MBB to insert a copy from + /// SrcReg when following the CFG edge to SuccMBB. This needs to be after + /// any def of SrcReg, but before any subsequent point where control flow + /// might jump out of the basic block. + MachineBasicBlock::iterator FindCopyInsertPoint(MachineBasicBlock &MBB, + MachineBasicBlock &SuccMBB, + unsigned SrcReg); + + // SkipPHIsAndLabels - Copies need to be inserted after phi nodes and + // also after any exception handling labels: in landing pads execution + // starts at the label, so any copies placed before it won't be executed! + MachineBasicBlock::iterator SkipPHIsAndLabels(MachineBasicBlock &MBB, + MachineBasicBlock::iterator I) { + // Rather than assuming that EH labels come before other kinds of labels, + // just skip all labels. + while (I != MBB.end() && + (I->getOpcode() == TargetInstrInfo::PHI || I->isLabel())) + ++I; + return I; + } + + typedef std::pair BBVRegPair; + typedef std::map VRegPHIUse; + + VRegPHIUse VRegPHIUseCount; + PHIDefMap PHIDefs; + PHIKillMap PHIKills; + + // Defs of PHI sources which are implicit_def. + SmallPtrSet ImpDefs; + }; + +} + +#endif /* LLVM_CODEGEN_PHIELIMINATION_HPP */ diff --git a/libclamav/c++/llvm/lib/CodeGen/Passes.cpp b/libclamav/c++/llvm/lib/CodeGen/Passes.cpp new file mode 100644 index 000000000..f67eb79be --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/Passes.cpp @@ -0,0 +1,54 @@ +//===-- Passes.cpp - Target independent code generation passes ------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines interfaces to access the target independent code +// generation passes provided by the LLVM backend. +// +//===---------------------------------------------------------------------===// + +#include "llvm/CodeGen/RegAllocRegistry.h" +#include "llvm/CodeGen/Passes.h" + +using namespace llvm; + +//===---------------------------------------------------------------------===// +/// +/// RegisterRegAlloc class - Track the registration of register allocators. +/// +//===---------------------------------------------------------------------===// +MachinePassRegistry RegisterRegAlloc::Registry; + + +//===---------------------------------------------------------------------===// +/// +/// RegAlloc command line options. +/// +//===---------------------------------------------------------------------===// +static cl::opt > +RegAlloc("regalloc", + cl::init(&createLinearScanRegisterAllocator), + cl::desc("Register allocator to use: (default = linearscan)")); + + +//===---------------------------------------------------------------------===// +/// +/// createRegisterAllocator - choose the appropriate register allocator. +/// +//===---------------------------------------------------------------------===// +FunctionPass *llvm::createRegisterAllocator() { + RegisterRegAlloc::FunctionPassCtor Ctor = RegisterRegAlloc::getDefault(); + + if (!Ctor) { + Ctor = RegAlloc; + RegisterRegAlloc::setDefault(RegAlloc); + } + + return Ctor(); +} diff --git a/libclamav/c++/llvm/lib/CodeGen/PostRASchedulerList.cpp b/libclamav/c++/llvm/lib/CodeGen/PostRASchedulerList.cpp new file mode 100644 index 000000000..9101fce27 --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/PostRASchedulerList.cpp @@ -0,0 +1,728 @@ +//===----- SchedulePostRAList.cpp - list scheduler ------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This implements a top-down list scheduler, using standard algorithms. +// The basic approach uses a priority queue of available nodes to schedule. +// One at a time, nodes are taken from the priority queue (thus in priority +// order), checked for legality to schedule, and emitted if legal. +// +// Nodes may not be legal to schedule either due to structural hazards (e.g. +// pipeline or resource constraints) or because an input to the instruction has +// not completed execution. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "post-RA-sched" +#include "AntiDepBreaker.h" +#include "AggressiveAntiDepBreaker.h" +#include "CriticalAntiDepBreaker.h" +#include "ExactHazardRecognizer.h" +#include "SimpleHazardRecognizer.h" +#include "ScheduleDAGInstrs.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/CodeGen/LatencyPriorityQueue.h" +#include "llvm/CodeGen/SchedulerRegistry.h" +#include "llvm/CodeGen/MachineDominators.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineLoopInfo.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/ScheduleHazardRecognizer.h" +#include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/Target/TargetLowering.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Target/TargetSubtarget.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/ADT/BitVector.h" +#include "llvm/ADT/Statistic.h" +#include +#include +using namespace llvm; + +STATISTIC(NumNoops, "Number of noops inserted"); +STATISTIC(NumStalls, "Number of pipeline stalls"); +STATISTIC(NumFixedAnti, "Number of fixed anti-dependencies"); + +// Post-RA scheduling is enabled with +// TargetSubtarget.enablePostRAScheduler(). This flag can be used to +// override the target. +static cl::opt +EnablePostRAScheduler("post-RA-scheduler", + cl::desc("Enable scheduling after register allocation"), + cl::init(false), cl::Hidden); +static cl::opt +EnableAntiDepBreaking("break-anti-dependencies", + cl::desc("Break post-RA scheduling anti-dependencies: " + "\"critical\", \"all\", or \"none\""), + cl::init("none"), cl::Hidden); +static cl::opt +EnablePostRAHazardAvoidance("avoid-hazards", + cl::desc("Enable exact hazard avoidance"), + cl::init(true), cl::Hidden); + +// If DebugDiv > 0 then only schedule MBB with (ID % DebugDiv) == DebugMod +static cl::opt +DebugDiv("postra-sched-debugdiv", + cl::desc("Debug control MBBs that are scheduled"), + cl::init(0), cl::Hidden); +static cl::opt +DebugMod("postra-sched-debugmod", + cl::desc("Debug control MBBs that are scheduled"), + cl::init(0), cl::Hidden); + +AntiDepBreaker::~AntiDepBreaker() { } + +namespace { + class PostRAScheduler : public MachineFunctionPass { + AliasAnalysis *AA; + CodeGenOpt::Level OptLevel; + + public: + static char ID; + PostRAScheduler(CodeGenOpt::Level ol) : + MachineFunctionPass(&ID), OptLevel(ol) {} + + void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesCFG(); + AU.addRequired(); + AU.addRequired(); + AU.addPreserved(); + AU.addRequired(); + AU.addPreserved(); + MachineFunctionPass::getAnalysisUsage(AU); + } + + const char *getPassName() const { + return "Post RA top-down list latency scheduler"; + } + + bool runOnMachineFunction(MachineFunction &Fn); + }; + char PostRAScheduler::ID = 0; + + class SchedulePostRATDList : public ScheduleDAGInstrs { + /// AvailableQueue - The priority queue to use for the available SUnits. + /// + LatencyPriorityQueue AvailableQueue; + + /// PendingQueue - This contains all of the instructions whose operands have + /// been issued, but their results are not ready yet (due to the latency of + /// the operation). Once the operands becomes available, the instruction is + /// added to the AvailableQueue. + std::vector PendingQueue; + + /// Topo - A topological ordering for SUnits. + ScheduleDAGTopologicalSort Topo; + + /// HazardRec - The hazard recognizer to use. + ScheduleHazardRecognizer *HazardRec; + + /// AntiDepBreak - Anti-dependence breaking object, or NULL if none + AntiDepBreaker *AntiDepBreak; + + /// AA - AliasAnalysis for making memory reference queries. + AliasAnalysis *AA; + + /// KillIndices - The index of the most recent kill (proceding bottom-up), + /// or ~0u if the register is not live. + unsigned KillIndices[TargetRegisterInfo::FirstVirtualRegister]; + + public: + SchedulePostRATDList(MachineFunction &MF, + const MachineLoopInfo &MLI, + const MachineDominatorTree &MDT, + ScheduleHazardRecognizer *HR, + AntiDepBreaker *ADB, + AliasAnalysis *aa) + : ScheduleDAGInstrs(MF, MLI, MDT), Topo(SUnits), + HazardRec(HR), AntiDepBreak(ADB), AA(aa) {} + + ~SchedulePostRATDList() { + } + + /// StartBlock - Initialize register live-range state for scheduling in + /// this block. + /// + void StartBlock(MachineBasicBlock *BB); + + /// Schedule - Schedule the instruction range using list scheduling. + /// + void Schedule(); + + /// Observe - Update liveness information to account for the current + /// instruction, which will not be scheduled. + /// + void Observe(MachineInstr *MI, unsigned Count); + + /// FinishBlock - Clean up register live-range state. + /// + void FinishBlock(); + + /// FixupKills - Fix register kill flags that have been made + /// invalid due to scheduling + /// + void FixupKills(MachineBasicBlock *MBB); + + private: + void ReleaseSucc(SUnit *SU, SDep *SuccEdge); + void ReleaseSuccessors(SUnit *SU); + void ScheduleNodeTopDown(SUnit *SU, unsigned CurCycle); + void ListScheduleTopDown(); + void StartBlockForKills(MachineBasicBlock *BB); + + // ToggleKillFlag - Toggle a register operand kill flag. Other + // adjustments may be made to the instruction if necessary. Return + // true if the operand has been deleted, false if not. + bool ToggleKillFlag(MachineInstr *MI, MachineOperand &MO); + }; +} + +/// isSchedulingBoundary - Test if the given instruction should be +/// considered a scheduling boundary. This primarily includes labels +/// and terminators. +/// +static bool isSchedulingBoundary(const MachineInstr *MI, + const MachineFunction &MF) { + // Terminators and labels can't be scheduled around. + if (MI->getDesc().isTerminator() || MI->isLabel()) + return true; + + // Don't attempt to schedule around any instruction that modifies + // a stack-oriented pointer, as it's unlikely to be profitable. This + // saves compile time, because it doesn't require every single + // stack slot reference to depend on the instruction that does the + // modification. + const TargetLowering &TLI = *MF.getTarget().getTargetLowering(); + if (MI->modifiesRegister(TLI.getStackPointerRegisterToSaveRestore())) + return true; + + return false; +} + +bool PostRAScheduler::runOnMachineFunction(MachineFunction &Fn) { + AA = &getAnalysis(); + + // Check for explicit enable/disable of post-ra scheduling. + TargetSubtarget::AntiDepBreakMode AntiDepMode = TargetSubtarget::ANTIDEP_NONE; + SmallVector CriticalPathRCs; + if (EnablePostRAScheduler.getPosition() > 0) { + if (!EnablePostRAScheduler) + return false; + } else { + // Check that post-RA scheduling is enabled for this target. + const TargetSubtarget &ST = Fn.getTarget().getSubtarget(); + if (!ST.enablePostRAScheduler(OptLevel, AntiDepMode, CriticalPathRCs)) + return false; + } + + // Check for antidep breaking override... + if (EnableAntiDepBreaking.getPosition() > 0) { + AntiDepMode = (EnableAntiDepBreaking == "all") ? TargetSubtarget::ANTIDEP_ALL : + (EnableAntiDepBreaking == "critical") ? TargetSubtarget::ANTIDEP_CRITICAL : + TargetSubtarget::ANTIDEP_NONE; + } + + DEBUG(errs() << "PostRAScheduler\n"); + + const MachineLoopInfo &MLI = getAnalysis(); + const MachineDominatorTree &MDT = getAnalysis(); + const InstrItineraryData &InstrItins = Fn.getTarget().getInstrItineraryData(); + ScheduleHazardRecognizer *HR = EnablePostRAHazardAvoidance ? + (ScheduleHazardRecognizer *)new ExactHazardRecognizer(InstrItins) : + (ScheduleHazardRecognizer *)new SimpleHazardRecognizer(); + AntiDepBreaker *ADB = + ((AntiDepMode == TargetSubtarget::ANTIDEP_ALL) ? + (AntiDepBreaker *)new AggressiveAntiDepBreaker(Fn, CriticalPathRCs) : + ((AntiDepMode == TargetSubtarget::ANTIDEP_CRITICAL) ? + (AntiDepBreaker *)new CriticalAntiDepBreaker(Fn) : NULL)); + + SchedulePostRATDList Scheduler(Fn, MLI, MDT, HR, ADB, AA); + + // Loop over all of the basic blocks + for (MachineFunction::iterator MBB = Fn.begin(), MBBe = Fn.end(); + MBB != MBBe; ++MBB) { +#ifndef NDEBUG + // If DebugDiv > 0 then only schedule MBB with (ID % DebugDiv) == DebugMod + if (DebugDiv > 0) { + static int bbcnt = 0; + if (bbcnt++ % DebugDiv != DebugMod) + continue; + errs() << "*** DEBUG scheduling " << Fn.getFunction()->getNameStr() << + ":BB#" << MBB->getNumber() << " ***\n"; + } +#endif + + // Initialize register live-range state for scheduling in this block. + Scheduler.StartBlock(MBB); + + // Schedule each sequence of instructions not interrupted by a label + // or anything else that effectively needs to shut down scheduling. + MachineBasicBlock::iterator Current = MBB->end(); + unsigned Count = MBB->size(), CurrentCount = Count; + for (MachineBasicBlock::iterator I = Current; I != MBB->begin(); ) { + MachineInstr *MI = prior(I); + if (isSchedulingBoundary(MI, Fn)) { + Scheduler.Run(MBB, I, Current, CurrentCount); + Scheduler.EmitSchedule(0); + Current = MI; + CurrentCount = Count - 1; + Scheduler.Observe(MI, CurrentCount); + } + I = MI; + --Count; + } + assert(Count == 0 && "Instruction count mismatch!"); + assert((MBB->begin() == Current || CurrentCount != 0) && + "Instruction count mismatch!"); + Scheduler.Run(MBB, MBB->begin(), Current, CurrentCount); + Scheduler.EmitSchedule(0); + + // Clean up register live-range state. + Scheduler.FinishBlock(); + + // Update register kills + Scheduler.FixupKills(MBB); + } + + delete HR; + delete ADB; + + return true; +} + +/// StartBlock - Initialize register live-range state for scheduling in +/// this block. +/// +void SchedulePostRATDList::StartBlock(MachineBasicBlock *BB) { + // Call the superclass. + ScheduleDAGInstrs::StartBlock(BB); + + // Reset the hazard recognizer and anti-dep breaker. + HazardRec->Reset(); + if (AntiDepBreak != NULL) + AntiDepBreak->StartBlock(BB); +} + +/// Schedule - Schedule the instruction range using list scheduling. +/// +void SchedulePostRATDList::Schedule() { + // Build the scheduling graph. + BuildSchedGraph(AA); + + if (AntiDepBreak != NULL) { + unsigned Broken = + AntiDepBreak->BreakAntiDependencies(SUnits, Begin, InsertPos, + InsertPosIndex); + + if (Broken != 0) { + // We made changes. Update the dependency graph. + // Theoretically we could update the graph in place: + // When a live range is changed to use a different register, remove + // the def's anti-dependence *and* output-dependence edges due to + // that register, and add new anti-dependence and output-dependence + // edges based on the next live range of the register. + SUnits.clear(); + Sequence.clear(); + EntrySU = SUnit(); + ExitSU = SUnit(); + BuildSchedGraph(AA); + + NumFixedAnti += Broken; + } + } + + DEBUG(errs() << "********** List Scheduling **********\n"); + DEBUG(for (unsigned su = 0, e = SUnits.size(); su != e; ++su) + SUnits[su].dumpAll(this)); + + AvailableQueue.initNodes(SUnits); + ListScheduleTopDown(); + AvailableQueue.releaseState(); +} + +/// Observe - Update liveness information to account for the current +/// instruction, which will not be scheduled. +/// +void SchedulePostRATDList::Observe(MachineInstr *MI, unsigned Count) { + if (AntiDepBreak != NULL) + AntiDepBreak->Observe(MI, Count, InsertPosIndex); +} + +/// FinishBlock - Clean up register live-range state. +/// +void SchedulePostRATDList::FinishBlock() { + if (AntiDepBreak != NULL) + AntiDepBreak->FinishBlock(); + + // Call the superclass. + ScheduleDAGInstrs::FinishBlock(); +} + +/// StartBlockForKills - Initialize register live-range state for updating kills +/// +void SchedulePostRATDList::StartBlockForKills(MachineBasicBlock *BB) { + // Initialize the indices to indicate that no registers are live. + std::fill(KillIndices, array_endof(KillIndices), ~0u); + + // Determine the live-out physregs for this block. + if (!BB->empty() && BB->back().getDesc().isReturn()) { + // In a return block, examine the function live-out regs. + for (MachineRegisterInfo::liveout_iterator I = MRI.liveout_begin(), + E = MRI.liveout_end(); I != E; ++I) { + unsigned Reg = *I; + KillIndices[Reg] = BB->size(); + // Repeat, for all subregs. + for (const unsigned *Subreg = TRI->getSubRegisters(Reg); + *Subreg; ++Subreg) { + KillIndices[*Subreg] = BB->size(); + } + } + } + else { + // In a non-return block, examine the live-in regs of all successors. + for (MachineBasicBlock::succ_iterator SI = BB->succ_begin(), + SE = BB->succ_end(); SI != SE; ++SI) { + for (MachineBasicBlock::livein_iterator I = (*SI)->livein_begin(), + E = (*SI)->livein_end(); I != E; ++I) { + unsigned Reg = *I; + KillIndices[Reg] = BB->size(); + // Repeat, for all subregs. + for (const unsigned *Subreg = TRI->getSubRegisters(Reg); + *Subreg; ++Subreg) { + KillIndices[*Subreg] = BB->size(); + } + } + } + } +} + +bool SchedulePostRATDList::ToggleKillFlag(MachineInstr *MI, + MachineOperand &MO) { + // Setting kill flag... + if (!MO.isKill()) { + MO.setIsKill(true); + return false; + } + + // If MO itself is live, clear the kill flag... + if (KillIndices[MO.getReg()] != ~0u) { + MO.setIsKill(false); + return false; + } + + // If any subreg of MO is live, then create an imp-def for that + // subreg and keep MO marked as killed. + MO.setIsKill(false); + bool AllDead = true; + const unsigned SuperReg = MO.getReg(); + for (const unsigned *Subreg = TRI->getSubRegisters(SuperReg); + *Subreg; ++Subreg) { + if (KillIndices[*Subreg] != ~0u) { + MI->addOperand(MachineOperand::CreateReg(*Subreg, + true /*IsDef*/, + true /*IsImp*/, + false /*IsKill*/, + false /*IsDead*/)); + AllDead = false; + } + } + + if(AllDead) + MO.setIsKill(true); + return false; +} + +/// FixupKills - Fix the register kill flags, they may have been made +/// incorrect by instruction reordering. +/// +void SchedulePostRATDList::FixupKills(MachineBasicBlock *MBB) { + DEBUG(errs() << "Fixup kills for BB#" << MBB->getNumber() << '\n'); + + std::set killedRegs; + BitVector ReservedRegs = TRI->getReservedRegs(MF); + + StartBlockForKills(MBB); + + // Examine block from end to start... + unsigned Count = MBB->size(); + for (MachineBasicBlock::iterator I = MBB->end(), E = MBB->begin(); + I != E; --Count) { + MachineInstr *MI = --I; + + // Update liveness. Registers that are defed but not used in this + // instruction are now dead. Mark register and all subregs as they + // are completely defined. + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + MachineOperand &MO = MI->getOperand(i); + if (!MO.isReg()) continue; + unsigned Reg = MO.getReg(); + if (Reg == 0) continue; + if (!MO.isDef()) continue; + // Ignore two-addr defs. + if (MI->isRegTiedToUseOperand(i)) continue; + + KillIndices[Reg] = ~0u; + + // Repeat for all subregs. + for (const unsigned *Subreg = TRI->getSubRegisters(Reg); + *Subreg; ++Subreg) { + KillIndices[*Subreg] = ~0u; + } + } + + // Examine all used registers and set/clear kill flag. When a + // register is used multiple times we only set the kill flag on + // the first use. + killedRegs.clear(); + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + MachineOperand &MO = MI->getOperand(i); + if (!MO.isReg() || !MO.isUse()) continue; + unsigned Reg = MO.getReg(); + if ((Reg == 0) || ReservedRegs.test(Reg)) continue; + + bool kill = false; + if (killedRegs.find(Reg) == killedRegs.end()) { + kill = true; + // A register is not killed if any subregs are live... + for (const unsigned *Subreg = TRI->getSubRegisters(Reg); + *Subreg; ++Subreg) { + if (KillIndices[*Subreg] != ~0u) { + kill = false; + break; + } + } + + // If subreg is not live, then register is killed if it became + // live in this instruction + if (kill) + kill = (KillIndices[Reg] == ~0u); + } + + if (MO.isKill() != kill) { + bool removed = ToggleKillFlag(MI, MO); + if (removed) { + DEBUG(errs() << "Fixed in "); + } else { + DEBUG(errs() << "Fixed " << MO << " in "); + } + DEBUG(MI->dump()); + } + + killedRegs.insert(Reg); + } + + // Mark any used register (that is not using undef) and subregs as + // now live... + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + MachineOperand &MO = MI->getOperand(i); + if (!MO.isReg() || !MO.isUse() || MO.isUndef()) continue; + unsigned Reg = MO.getReg(); + if ((Reg == 0) || ReservedRegs.test(Reg)) continue; + + KillIndices[Reg] = Count; + + for (const unsigned *Subreg = TRI->getSubRegisters(Reg); + *Subreg; ++Subreg) { + KillIndices[*Subreg] = Count; + } + } + } +} + +//===----------------------------------------------------------------------===// +// Top-Down Scheduling +//===----------------------------------------------------------------------===// + +/// ReleaseSucc - Decrement the NumPredsLeft count of a successor. Add it to +/// the PendingQueue if the count reaches zero. Also update its cycle bound. +void SchedulePostRATDList::ReleaseSucc(SUnit *SU, SDep *SuccEdge) { + SUnit *SuccSU = SuccEdge->getSUnit(); + +#ifndef NDEBUG + if (SuccSU->NumPredsLeft == 0) { + errs() << "*** Scheduling failed! ***\n"; + SuccSU->dump(this); + errs() << " has been released too many times!\n"; + llvm_unreachable(0); + } +#endif + --SuccSU->NumPredsLeft; + + // Compute how many cycles it will be before this actually becomes + // available. This is the max of the start time of all predecessors plus + // their latencies. + SuccSU->setDepthToAtLeast(SU->getDepth() + SuccEdge->getLatency()); + + // If all the node's predecessors are scheduled, this node is ready + // to be scheduled. Ignore the special ExitSU node. + if (SuccSU->NumPredsLeft == 0 && SuccSU != &ExitSU) + PendingQueue.push_back(SuccSU); +} + +/// ReleaseSuccessors - Call ReleaseSucc on each of SU's successors. +void SchedulePostRATDList::ReleaseSuccessors(SUnit *SU) { + for (SUnit::succ_iterator I = SU->Succs.begin(), E = SU->Succs.end(); + I != E; ++I) { + ReleaseSucc(SU, &*I); + } +} + +/// ScheduleNodeTopDown - Add the node to the schedule. Decrement the pending +/// count of its successors. If a successor pending count is zero, add it to +/// the Available queue. +void SchedulePostRATDList::ScheduleNodeTopDown(SUnit *SU, unsigned CurCycle) { + DEBUG(errs() << "*** Scheduling [" << CurCycle << "]: "); + DEBUG(SU->dump(this)); + + Sequence.push_back(SU); + assert(CurCycle >= SU->getDepth() && + "Node scheduled above its depth!"); + SU->setDepthToAtLeast(CurCycle); + + ReleaseSuccessors(SU); + SU->isScheduled = true; + AvailableQueue.ScheduledNode(SU); +} + +/// ListScheduleTopDown - The main loop of list scheduling for top-down +/// schedulers. +void SchedulePostRATDList::ListScheduleTopDown() { + unsigned CurCycle = 0; + + // We're scheduling top-down but we're visiting the regions in + // bottom-up order, so we don't know the hazards at the start of a + // region. So assume no hazards (this should usually be ok as most + // blocks are a single region). + HazardRec->Reset(); + + // Release any successors of the special Entry node. + ReleaseSuccessors(&EntrySU); + + // Add all leaves to Available queue. + for (unsigned i = 0, e = SUnits.size(); i != e; ++i) { + // It is available if it has no predecessors. + bool available = SUnits[i].Preds.empty(); + if (available) { + AvailableQueue.push(&SUnits[i]); + SUnits[i].isAvailable = true; + } + } + + // In any cycle where we can't schedule any instructions, we must + // stall or emit a noop, depending on the target. + bool CycleHasInsts = false; + + // While Available queue is not empty, grab the node with the highest + // priority. If it is not ready put it back. Schedule the node. + std::vector NotReady; + Sequence.reserve(SUnits.size()); + while (!AvailableQueue.empty() || !PendingQueue.empty()) { + // Check to see if any of the pending instructions are ready to issue. If + // so, add them to the available queue. + unsigned MinDepth = ~0u; + for (unsigned i = 0, e = PendingQueue.size(); i != e; ++i) { + if (PendingQueue[i]->getDepth() <= CurCycle) { + AvailableQueue.push(PendingQueue[i]); + PendingQueue[i]->isAvailable = true; + PendingQueue[i] = PendingQueue.back(); + PendingQueue.pop_back(); + --i; --e; + } else if (PendingQueue[i]->getDepth() < MinDepth) + MinDepth = PendingQueue[i]->getDepth(); + } + + DEBUG(errs() << "\n*** Examining Available\n"; + LatencyPriorityQueue q = AvailableQueue; + while (!q.empty()) { + SUnit *su = q.pop(); + errs() << "Height " << su->getHeight() << ": "; + su->dump(this); + }); + + SUnit *FoundSUnit = 0; + bool HasNoopHazards = false; + while (!AvailableQueue.empty()) { + SUnit *CurSUnit = AvailableQueue.pop(); + + ScheduleHazardRecognizer::HazardType HT = + HazardRec->getHazardType(CurSUnit); + if (HT == ScheduleHazardRecognizer::NoHazard) { + FoundSUnit = CurSUnit; + break; + } + + // Remember if this is a noop hazard. + HasNoopHazards |= HT == ScheduleHazardRecognizer::NoopHazard; + + NotReady.push_back(CurSUnit); + } + + // Add the nodes that aren't ready back onto the available list. + if (!NotReady.empty()) { + AvailableQueue.push_all(NotReady); + NotReady.clear(); + } + + // If we found a node to schedule... + if (FoundSUnit) { + // ... schedule the node... + ScheduleNodeTopDown(FoundSUnit, CurCycle); + HazardRec->EmitInstruction(FoundSUnit); + CycleHasInsts = true; + + // If we are using the target-specific hazards, then don't + // advance the cycle time just because we schedule a node. If + // the target allows it we can schedule multiple nodes in the + // same cycle. + if (!EnablePostRAHazardAvoidance) { + if (FoundSUnit->Latency) // Don't increment CurCycle for pseudo-ops! + ++CurCycle; + } + } else { + if (CycleHasInsts) { + DEBUG(errs() << "*** Finished cycle " << CurCycle << '\n'); + HazardRec->AdvanceCycle(); + } else if (!HasNoopHazards) { + // Otherwise, we have a pipeline stall, but no other problem, + // just advance the current cycle and try again. + DEBUG(errs() << "*** Stall in cycle " << CurCycle << '\n'); + HazardRec->AdvanceCycle(); + ++NumStalls; + } else { + // Otherwise, we have no instructions to issue and we have instructions + // that will fault if we don't do this right. This is the case for + // processors without pipeline interlocks and other cases. + DEBUG(errs() << "*** Emitting noop in cycle " << CurCycle << '\n'); + HazardRec->EmitNoop(); + Sequence.push_back(0); // NULL here means noop + ++NumNoops; + } + + ++CurCycle; + CycleHasInsts = false; + } + } + +#ifndef NDEBUG + VerifySchedule(/*isBottomUp=*/false); +#endif +} + +//===----------------------------------------------------------------------===// +// Public Constructor Functions +//===----------------------------------------------------------------------===// + +FunctionPass *llvm::createPostRAScheduler(CodeGenOpt::Level OptLevel) { + return new PostRAScheduler(OptLevel); +} diff --git a/libclamav/c++/llvm/lib/CodeGen/PreAllocSplitting.cpp b/libclamav/c++/llvm/lib/CodeGen/PreAllocSplitting.cpp new file mode 100644 index 000000000..8f623452e --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/PreAllocSplitting.cpp @@ -0,0 +1,1494 @@ +//===-- PreAllocSplitting.cpp - Pre-allocation Interval Spltting Pass. ----===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the machine instruction level pre-register allocation +// live interval splitting pass. It finds live interval barriers, i.e. +// instructions which will kill all physical registers in certain register +// classes, and split all live intervals which cross the barrier. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "pre-alloc-split" +#include "VirtRegMap.h" +#include "llvm/CodeGen/LiveIntervalAnalysis.h" +#include "llvm/CodeGen/LiveStackAnalysis.h" +#include "llvm/CodeGen/MachineDominators.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineLoopInfo.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/CodeGen/RegisterCoalescer.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetOptions.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/DepthFirstIterator.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/Statistic.h" +using namespace llvm; + +static cl::opt PreSplitLimit("pre-split-limit", cl::init(-1), cl::Hidden); +static cl::opt DeadSplitLimit("dead-split-limit", cl::init(-1), + cl::Hidden); +static cl::opt RestoreFoldLimit("restore-fold-limit", cl::init(-1), + cl::Hidden); + +STATISTIC(NumSplits, "Number of intervals split"); +STATISTIC(NumRemats, "Number of intervals split by rematerialization"); +STATISTIC(NumFolds, "Number of intervals split with spill folding"); +STATISTIC(NumRestoreFolds, "Number of intervals split with restore folding"); +STATISTIC(NumRenumbers, "Number of intervals renumbered into new registers"); +STATISTIC(NumDeadSpills, "Number of dead spills removed"); + +namespace { + class PreAllocSplitting : public MachineFunctionPass { + MachineFunction *CurrMF; + const TargetMachine *TM; + const TargetInstrInfo *TII; + const TargetRegisterInfo* TRI; + MachineFrameInfo *MFI; + MachineRegisterInfo *MRI; + SlotIndexes *SIs; + LiveIntervals *LIs; + LiveStacks *LSs; + VirtRegMap *VRM; + + // Barrier - Current barrier being processed. + MachineInstr *Barrier; + + // BarrierMBB - Basic block where the barrier resides in. + MachineBasicBlock *BarrierMBB; + + // Barrier - Current barrier index. + SlotIndex BarrierIdx; + + // CurrLI - Current live interval being split. + LiveInterval *CurrLI; + + // CurrSLI - Current stack slot live interval. + LiveInterval *CurrSLI; + + // CurrSValNo - Current val# for the stack slot live interval. + VNInfo *CurrSValNo; + + // IntervalSSMap - A map from live interval to spill slots. + DenseMap IntervalSSMap; + + // Def2SpillMap - A map from a def instruction index to spill index. + DenseMap Def2SpillMap; + + public: + static char ID; + PreAllocSplitting() + : MachineFunctionPass(&ID) {} + + virtual bool runOnMachineFunction(MachineFunction &MF); + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesCFG(); + AU.addRequired(); + AU.addPreserved(); + AU.addRequired(); + AU.addPreserved(); + AU.addRequired(); + AU.addPreserved(); + AU.addPreserved(); + if (StrongPHIElim) + AU.addPreservedID(StrongPHIEliminationID); + else + AU.addPreservedID(PHIEliminationID); + AU.addRequired(); + AU.addRequired(); + AU.addRequired(); + AU.addPreserved(); + AU.addPreserved(); + AU.addPreserved(); + MachineFunctionPass::getAnalysisUsage(AU); + } + + virtual void releaseMemory() { + IntervalSSMap.clear(); + Def2SpillMap.clear(); + } + + virtual const char *getPassName() const { + return "Pre-Register Allocaton Live Interval Splitting"; + } + + /// print - Implement the dump method. + virtual void print(raw_ostream &O, const Module* M = 0) const { + LIs->print(O, M); + } + + + private: + + MachineBasicBlock::iterator + findSpillPoint(MachineBasicBlock*, MachineInstr*, MachineInstr*, + SmallPtrSet&); + + MachineBasicBlock::iterator + findRestorePoint(MachineBasicBlock*, MachineInstr*, SlotIndex, + SmallPtrSet&); + + int CreateSpillStackSlot(unsigned, const TargetRegisterClass *); + + bool IsAvailableInStack(MachineBasicBlock*, unsigned, + SlotIndex, SlotIndex, + SlotIndex&, int&) const; + + void UpdateSpillSlotInterval(VNInfo*, SlotIndex, SlotIndex); + + bool SplitRegLiveInterval(LiveInterval*); + + bool SplitRegLiveIntervals(const TargetRegisterClass **, + SmallPtrSet&); + + bool createsNewJoin(LiveRange* LR, MachineBasicBlock* DefMBB, + MachineBasicBlock* BarrierMBB); + bool Rematerialize(unsigned vreg, VNInfo* ValNo, + MachineInstr* DefMI, + MachineBasicBlock::iterator RestorePt, + SmallPtrSet& RefsInMBB); + MachineInstr* FoldSpill(unsigned vreg, const TargetRegisterClass* RC, + MachineInstr* DefMI, + MachineInstr* Barrier, + MachineBasicBlock* MBB, + int& SS, + SmallPtrSet& RefsInMBB); + MachineInstr* FoldRestore(unsigned vreg, + const TargetRegisterClass* RC, + MachineInstr* Barrier, + MachineBasicBlock* MBB, + int SS, + SmallPtrSet& RefsInMBB); + void RenumberValno(VNInfo* VN); + void ReconstructLiveInterval(LiveInterval* LI); + bool removeDeadSpills(SmallPtrSet& split); + unsigned getNumberOfNonSpills(SmallPtrSet& MIs, + unsigned Reg, int FrameIndex, bool& TwoAddr); + VNInfo* PerformPHIConstruction(MachineBasicBlock::iterator Use, + MachineBasicBlock* MBB, LiveInterval* LI, + SmallPtrSet& Visited, + DenseMap >& Defs, + DenseMap >& Uses, + DenseMap& NewVNs, + DenseMap& LiveOut, + DenseMap& Phis, + bool IsTopLevel, bool IsIntraBlock); + VNInfo* PerformPHIConstructionFallBack(MachineBasicBlock::iterator Use, + MachineBasicBlock* MBB, LiveInterval* LI, + SmallPtrSet& Visited, + DenseMap >& Defs, + DenseMap >& Uses, + DenseMap& NewVNs, + DenseMap& LiveOut, + DenseMap& Phis, + bool IsTopLevel, bool IsIntraBlock); +}; +} // end anonymous namespace + +char PreAllocSplitting::ID = 0; + +static RegisterPass +X("pre-alloc-splitting", "Pre-Register Allocation Live Interval Splitting"); + +const PassInfo *const llvm::PreAllocSplittingID = &X; + +/// findSpillPoint - Find a gap as far away from the given MI that's suitable +/// for spilling the current live interval. The index must be before any +/// defs and uses of the live interval register in the mbb. Return begin() if +/// none is found. +MachineBasicBlock::iterator +PreAllocSplitting::findSpillPoint(MachineBasicBlock *MBB, MachineInstr *MI, + MachineInstr *DefMI, + SmallPtrSet &RefsInMBB) { + MachineBasicBlock::iterator Pt = MBB->begin(); + + MachineBasicBlock::iterator MII = MI; + MachineBasicBlock::iterator EndPt = DefMI + ? MachineBasicBlock::iterator(DefMI) : MBB->begin(); + + while (MII != EndPt && !RefsInMBB.count(MII) && + MII->getOpcode() != TRI->getCallFrameSetupOpcode()) + --MII; + if (MII == EndPt || RefsInMBB.count(MII)) return Pt; + + while (MII != EndPt && !RefsInMBB.count(MII)) { + // We can't insert the spill between the barrier (a call), and its + // corresponding call frame setup. + if (MII->getOpcode() == TRI->getCallFrameDestroyOpcode()) { + while (MII->getOpcode() != TRI->getCallFrameSetupOpcode()) { + --MII; + if (MII == EndPt) { + return Pt; + } + } + continue; + } else { + Pt = MII; + } + + if (RefsInMBB.count(MII)) + return Pt; + + + --MII; + } + + return Pt; +} + +/// findRestorePoint - Find a gap in the instruction index map that's suitable +/// for restoring the current live interval value. The index must be before any +/// uses of the live interval register in the mbb. Return end() if none is +/// found. +MachineBasicBlock::iterator +PreAllocSplitting::findRestorePoint(MachineBasicBlock *MBB, MachineInstr *MI, + SlotIndex LastIdx, + SmallPtrSet &RefsInMBB) { + // FIXME: Allow spill to be inserted to the beginning of the mbb. Update mbb + // begin index accordingly. + MachineBasicBlock::iterator Pt = MBB->end(); + MachineBasicBlock::iterator EndPt = MBB->getFirstTerminator(); + + // We start at the call, so walk forward until we find the call frame teardown + // since we can't insert restores before that. Bail if we encounter a use + // during this time. + MachineBasicBlock::iterator MII = MI; + if (MII == EndPt) return Pt; + + while (MII != EndPt && !RefsInMBB.count(MII) && + MII->getOpcode() != TRI->getCallFrameDestroyOpcode()) + ++MII; + if (MII == EndPt || RefsInMBB.count(MII)) return Pt; + ++MII; + + // FIXME: Limit the number of instructions to examine to reduce + // compile time? + while (MII != EndPt) { + SlotIndex Index = LIs->getInstructionIndex(MII); + if (Index > LastIdx) + break; + + // We can't insert a restore between the barrier (a call) and its + // corresponding call frame teardown. + if (MII->getOpcode() == TRI->getCallFrameSetupOpcode()) { + do { + if (MII == EndPt || RefsInMBB.count(MII)) return Pt; + ++MII; + } while (MII->getOpcode() != TRI->getCallFrameDestroyOpcode()); + } else { + Pt = MII; + } + + if (RefsInMBB.count(MII)) + return Pt; + + ++MII; + } + + return Pt; +} + +/// CreateSpillStackSlot - Create a stack slot for the live interval being +/// split. If the live interval was previously split, just reuse the same +/// slot. +int PreAllocSplitting::CreateSpillStackSlot(unsigned Reg, + const TargetRegisterClass *RC) { + int SS; + DenseMap::iterator I = IntervalSSMap.find(Reg); + if (I != IntervalSSMap.end()) { + SS = I->second; + } else { + SS = MFI->CreateSpillStackObject(RC->getSize(), RC->getAlignment()); + IntervalSSMap[Reg] = SS; + } + + // Create live interval for stack slot. + CurrSLI = &LSs->getOrCreateInterval(SS, RC); + if (CurrSLI->hasAtLeastOneValue()) + CurrSValNo = CurrSLI->getValNumInfo(0); + else + CurrSValNo = CurrSLI->getNextValue(SlotIndex(), 0, false, + LSs->getVNInfoAllocator()); + return SS; +} + +/// IsAvailableInStack - Return true if register is available in a split stack +/// slot at the specified index. +bool +PreAllocSplitting::IsAvailableInStack(MachineBasicBlock *DefMBB, + unsigned Reg, SlotIndex DefIndex, + SlotIndex RestoreIndex, + SlotIndex &SpillIndex, + int& SS) const { + if (!DefMBB) + return false; + + DenseMap::const_iterator I = IntervalSSMap.find(Reg); + if (I == IntervalSSMap.end()) + return false; + DenseMap::const_iterator + II = Def2SpillMap.find(DefIndex); + if (II == Def2SpillMap.end()) + return false; + + // If last spill of def is in the same mbb as barrier mbb (where restore will + // be), make sure it's not below the intended restore index. + // FIXME: Undo the previous spill? + assert(LIs->getMBBFromIndex(II->second) == DefMBB); + if (DefMBB == BarrierMBB && II->second >= RestoreIndex) + return false; + + SS = I->second; + SpillIndex = II->second; + return true; +} + +/// UpdateSpillSlotInterval - Given the specified val# of the register live +/// interval being split, and the spill and restore indicies, update the live +/// interval of the spill stack slot. +void +PreAllocSplitting::UpdateSpillSlotInterval(VNInfo *ValNo, SlotIndex SpillIndex, + SlotIndex RestoreIndex) { + assert(LIs->getMBBFromIndex(RestoreIndex) == BarrierMBB && + "Expect restore in the barrier mbb"); + + MachineBasicBlock *MBB = LIs->getMBBFromIndex(SpillIndex); + if (MBB == BarrierMBB) { + // Intra-block spill + restore. We are done. + LiveRange SLR(SpillIndex, RestoreIndex, CurrSValNo); + CurrSLI->addRange(SLR); + return; + } + + SmallPtrSet Processed; + SlotIndex EndIdx = LIs->getMBBEndIdx(MBB); + LiveRange SLR(SpillIndex, EndIdx.getNextSlot(), CurrSValNo); + CurrSLI->addRange(SLR); + Processed.insert(MBB); + + // Start from the spill mbb, figure out the extend of the spill slot's + // live interval. + SmallVector WorkList; + const LiveRange *LR = CurrLI->getLiveRangeContaining(SpillIndex); + if (LR->end > EndIdx) + // If live range extend beyond end of mbb, add successors to work list. + for (MachineBasicBlock::succ_iterator SI = MBB->succ_begin(), + SE = MBB->succ_end(); SI != SE; ++SI) + WorkList.push_back(*SI); + + while (!WorkList.empty()) { + MachineBasicBlock *MBB = WorkList.back(); + WorkList.pop_back(); + if (Processed.count(MBB)) + continue; + SlotIndex Idx = LIs->getMBBStartIdx(MBB); + LR = CurrLI->getLiveRangeContaining(Idx); + if (LR && LR->valno == ValNo) { + EndIdx = LIs->getMBBEndIdx(MBB); + if (Idx <= RestoreIndex && RestoreIndex < EndIdx) { + // Spill slot live interval stops at the restore. + LiveRange SLR(Idx, RestoreIndex, CurrSValNo); + CurrSLI->addRange(SLR); + } else if (LR->end > EndIdx) { + // Live range extends beyond end of mbb, process successors. + LiveRange SLR(Idx, EndIdx.getNextIndex(), CurrSValNo); + CurrSLI->addRange(SLR); + for (MachineBasicBlock::succ_iterator SI = MBB->succ_begin(), + SE = MBB->succ_end(); SI != SE; ++SI) + WorkList.push_back(*SI); + } else { + LiveRange SLR(Idx, LR->end, CurrSValNo); + CurrSLI->addRange(SLR); + } + Processed.insert(MBB); + } + } +} + +/// PerformPHIConstruction - From properly set up use and def lists, use a PHI +/// construction algorithm to compute the ranges and valnos for an interval. +VNInfo* +PreAllocSplitting::PerformPHIConstruction(MachineBasicBlock::iterator UseI, + MachineBasicBlock* MBB, LiveInterval* LI, + SmallPtrSet& Visited, + DenseMap >& Defs, + DenseMap >& Uses, + DenseMap& NewVNs, + DenseMap& LiveOut, + DenseMap& Phis, + bool IsTopLevel, bool IsIntraBlock) { + // Return memoized result if it's available. + if (IsTopLevel && Visited.count(UseI) && NewVNs.count(UseI)) + return NewVNs[UseI]; + else if (!IsTopLevel && IsIntraBlock && NewVNs.count(UseI)) + return NewVNs[UseI]; + else if (!IsIntraBlock && LiveOut.count(MBB)) + return LiveOut[MBB]; + + // Check if our block contains any uses or defs. + bool ContainsDefs = Defs.count(MBB); + bool ContainsUses = Uses.count(MBB); + + VNInfo* RetVNI = 0; + + // Enumerate the cases of use/def contaning blocks. + if (!ContainsDefs && !ContainsUses) { + return PerformPHIConstructionFallBack(UseI, MBB, LI, Visited, Defs, Uses, + NewVNs, LiveOut, Phis, + IsTopLevel, IsIntraBlock); + } else if (ContainsDefs && !ContainsUses) { + SmallPtrSet& BlockDefs = Defs[MBB]; + + // Search for the def in this block. If we don't find it before the + // instruction we care about, go to the fallback case. Note that that + // should never happen: this cannot be intrablock, so use should + // always be an end() iterator. + assert(UseI == MBB->end() && "No use marked in intrablock"); + + MachineBasicBlock::iterator Walker = UseI; + --Walker; + while (Walker != MBB->begin()) { + if (BlockDefs.count(Walker)) + break; + --Walker; + } + + // Once we've found it, extend its VNInfo to our instruction. + SlotIndex DefIndex = LIs->getInstructionIndex(Walker); + DefIndex = DefIndex.getDefIndex(); + SlotIndex EndIndex = LIs->getMBBEndIdx(MBB); + + RetVNI = NewVNs[Walker]; + LI->addRange(LiveRange(DefIndex, EndIndex.getNextSlot(), RetVNI)); + } else if (!ContainsDefs && ContainsUses) { + SmallPtrSet& BlockUses = Uses[MBB]; + + // Search for the use in this block that precedes the instruction we care + // about, going to the fallback case if we don't find it. + if (UseI == MBB->begin()) + return PerformPHIConstructionFallBack(UseI, MBB, LI, Visited, Defs, + Uses, NewVNs, LiveOut, Phis, + IsTopLevel, IsIntraBlock); + + MachineBasicBlock::iterator Walker = UseI; + --Walker; + bool found = false; + while (Walker != MBB->begin()) { + if (BlockUses.count(Walker)) { + found = true; + break; + } + --Walker; + } + + // Must check begin() too. + if (!found) { + if (BlockUses.count(Walker)) + found = true; + else + return PerformPHIConstructionFallBack(UseI, MBB, LI, Visited, Defs, + Uses, NewVNs, LiveOut, Phis, + IsTopLevel, IsIntraBlock); + } + + SlotIndex UseIndex = LIs->getInstructionIndex(Walker); + UseIndex = UseIndex.getUseIndex(); + SlotIndex EndIndex; + if (IsIntraBlock) { + EndIndex = LIs->getInstructionIndex(UseI); + EndIndex = EndIndex.getUseIndex(); + } else + EndIndex = LIs->getMBBEndIdx(MBB); + + // Now, recursively phi construct the VNInfo for the use we found, + // and then extend it to include the instruction we care about + RetVNI = PerformPHIConstruction(Walker, MBB, LI, Visited, Defs, Uses, + NewVNs, LiveOut, Phis, false, true); + + LI->addRange(LiveRange(UseIndex, EndIndex.getNextSlot(), RetVNI)); + + // FIXME: Need to set kills properly for inter-block stuff. + if (RetVNI->isKill(UseIndex)) RetVNI->removeKill(UseIndex); + if (IsIntraBlock) + RetVNI->addKill(EndIndex); + } else if (ContainsDefs && ContainsUses) { + SmallPtrSet& BlockDefs = Defs[MBB]; + SmallPtrSet& BlockUses = Uses[MBB]; + + // This case is basically a merging of the two preceding case, with the + // special note that checking for defs must take precedence over checking + // for uses, because of two-address instructions. + + if (UseI == MBB->begin()) + return PerformPHIConstructionFallBack(UseI, MBB, LI, Visited, Defs, Uses, + NewVNs, LiveOut, Phis, + IsTopLevel, IsIntraBlock); + + MachineBasicBlock::iterator Walker = UseI; + --Walker; + bool foundDef = false; + bool foundUse = false; + while (Walker != MBB->begin()) { + if (BlockDefs.count(Walker)) { + foundDef = true; + break; + } else if (BlockUses.count(Walker)) { + foundUse = true; + break; + } + --Walker; + } + + // Must check begin() too. + if (!foundDef && !foundUse) { + if (BlockDefs.count(Walker)) + foundDef = true; + else if (BlockUses.count(Walker)) + foundUse = true; + else + return PerformPHIConstructionFallBack(UseI, MBB, LI, Visited, Defs, + Uses, NewVNs, LiveOut, Phis, + IsTopLevel, IsIntraBlock); + } + + SlotIndex StartIndex = LIs->getInstructionIndex(Walker); + StartIndex = foundDef ? StartIndex.getDefIndex() : StartIndex.getUseIndex(); + SlotIndex EndIndex; + if (IsIntraBlock) { + EndIndex = LIs->getInstructionIndex(UseI); + EndIndex = EndIndex.getUseIndex(); + } else + EndIndex = LIs->getMBBEndIdx(MBB); + + if (foundDef) + RetVNI = NewVNs[Walker]; + else + RetVNI = PerformPHIConstruction(Walker, MBB, LI, Visited, Defs, Uses, + NewVNs, LiveOut, Phis, false, true); + + LI->addRange(LiveRange(StartIndex, EndIndex.getNextSlot(), RetVNI)); + + if (foundUse && RetVNI->isKill(StartIndex)) + RetVNI->removeKill(StartIndex); + if (IsIntraBlock) { + RetVNI->addKill(EndIndex); + } + } + + // Memoize results so we don't have to recompute them. + if (!IsIntraBlock) LiveOut[MBB] = RetVNI; + else { + if (!NewVNs.count(UseI)) + NewVNs[UseI] = RetVNI; + Visited.insert(UseI); + } + + return RetVNI; +} + +/// PerformPHIConstructionFallBack - PerformPHIConstruction fall back path. +/// +VNInfo* +PreAllocSplitting::PerformPHIConstructionFallBack(MachineBasicBlock::iterator UseI, + MachineBasicBlock* MBB, LiveInterval* LI, + SmallPtrSet& Visited, + DenseMap >& Defs, + DenseMap >& Uses, + DenseMap& NewVNs, + DenseMap& LiveOut, + DenseMap& Phis, + bool IsTopLevel, bool IsIntraBlock) { + // NOTE: Because this is the fallback case from other cases, we do NOT + // assume that we are not intrablock here. + if (Phis.count(MBB)) return Phis[MBB]; + + SlotIndex StartIndex = LIs->getMBBStartIdx(MBB); + VNInfo *RetVNI = Phis[MBB] = + LI->getNextValue(SlotIndex(), /*FIXME*/ 0, false, + LIs->getVNInfoAllocator()); + + if (!IsIntraBlock) LiveOut[MBB] = RetVNI; + + // If there are no uses or defs between our starting point and the + // beginning of the block, then recursive perform phi construction + // on our predecessors. + DenseMap IncomingVNs; + for (MachineBasicBlock::pred_iterator PI = MBB->pred_begin(), + PE = MBB->pred_end(); PI != PE; ++PI) { + VNInfo* Incoming = PerformPHIConstruction((*PI)->end(), *PI, LI, + Visited, Defs, Uses, NewVNs, + LiveOut, Phis, false, false); + if (Incoming != 0) + IncomingVNs[*PI] = Incoming; + } + + if (MBB->pred_size() == 1 && !RetVNI->hasPHIKill()) { + VNInfo* OldVN = RetVNI; + VNInfo* NewVN = IncomingVNs.begin()->second; + VNInfo* MergedVN = LI->MergeValueNumberInto(OldVN, NewVN); + if (MergedVN == OldVN) std::swap(OldVN, NewVN); + + for (DenseMap::iterator LOI = LiveOut.begin(), + LOE = LiveOut.end(); LOI != LOE; ++LOI) + if (LOI->second == OldVN) + LOI->second = MergedVN; + for (DenseMap::iterator NVI = NewVNs.begin(), + NVE = NewVNs.end(); NVI != NVE; ++NVI) + if (NVI->second == OldVN) + NVI->second = MergedVN; + for (DenseMap::iterator PI = Phis.begin(), + PE = Phis.end(); PI != PE; ++PI) + if (PI->second == OldVN) + PI->second = MergedVN; + RetVNI = MergedVN; + } else { + // Otherwise, merge the incoming VNInfos with a phi join. Create a new + // VNInfo to represent the joined value. + for (DenseMap::iterator I = + IncomingVNs.begin(), E = IncomingVNs.end(); I != E; ++I) { + I->second->setHasPHIKill(true); + SlotIndex KillIndex = LIs->getMBBEndIdx(I->first); + if (!I->second->isKill(KillIndex)) + I->second->addKill(KillIndex); + } + } + + SlotIndex EndIndex; + if (IsIntraBlock) { + EndIndex = LIs->getInstructionIndex(UseI); + EndIndex = EndIndex.getUseIndex(); + } else + EndIndex = LIs->getMBBEndIdx(MBB); + LI->addRange(LiveRange(StartIndex, EndIndex.getNextSlot(), RetVNI)); + if (IsIntraBlock) + RetVNI->addKill(EndIndex); + + // Memoize results so we don't have to recompute them. + if (!IsIntraBlock) + LiveOut[MBB] = RetVNI; + else { + if (!NewVNs.count(UseI)) + NewVNs[UseI] = RetVNI; + Visited.insert(UseI); + } + + return RetVNI; +} + +/// ReconstructLiveInterval - Recompute a live interval from scratch. +void PreAllocSplitting::ReconstructLiveInterval(LiveInterval* LI) { + BumpPtrAllocator& Alloc = LIs->getVNInfoAllocator(); + + // Clear the old ranges and valnos; + LI->clear(); + + // Cache the uses and defs of the register + typedef DenseMap > RegMap; + RegMap Defs, Uses; + + // Keep track of the new VNs we're creating. + DenseMap NewVNs; + SmallPtrSet PhiVNs; + + // Cache defs, and create a new VNInfo for each def. + for (MachineRegisterInfo::def_iterator DI = MRI->def_begin(LI->reg), + DE = MRI->def_end(); DI != DE; ++DI) { + Defs[(*DI).getParent()].insert(&*DI); + + SlotIndex DefIdx = LIs->getInstructionIndex(&*DI); + DefIdx = DefIdx.getDefIndex(); + + assert(DI->getOpcode() != TargetInstrInfo::PHI && + "PHI instr in code during pre-alloc splitting."); + VNInfo* NewVN = LI->getNextValue(DefIdx, 0, true, Alloc); + + // If the def is a move, set the copy field. + unsigned SrcReg, DstReg, SrcSubIdx, DstSubIdx; + if (TII->isMoveInstr(*DI, SrcReg, DstReg, SrcSubIdx, DstSubIdx)) + if (DstReg == LI->reg) + NewVN->setCopy(&*DI); + + NewVNs[&*DI] = NewVN; + } + + // Cache uses as a separate pass from actually processing them. + for (MachineRegisterInfo::use_iterator UI = MRI->use_begin(LI->reg), + UE = MRI->use_end(); UI != UE; ++UI) + Uses[(*UI).getParent()].insert(&*UI); + + // Now, actually process every use and use a phi construction algorithm + // to walk from it to its reaching definitions, building VNInfos along + // the way. + DenseMap LiveOut; + DenseMap Phis; + SmallPtrSet Visited; + for (MachineRegisterInfo::use_iterator UI = MRI->use_begin(LI->reg), + UE = MRI->use_end(); UI != UE; ++UI) { + PerformPHIConstruction(&*UI, UI->getParent(), LI, Visited, Defs, + Uses, NewVNs, LiveOut, Phis, true, true); + } + + // Add ranges for dead defs + for (MachineRegisterInfo::def_iterator DI = MRI->def_begin(LI->reg), + DE = MRI->def_end(); DI != DE; ++DI) { + SlotIndex DefIdx = LIs->getInstructionIndex(&*DI); + DefIdx = DefIdx.getDefIndex(); + + if (LI->liveAt(DefIdx)) continue; + + VNInfo* DeadVN = NewVNs[&*DI]; + LI->addRange(LiveRange(DefIdx, DefIdx.getNextSlot(), DeadVN)); + DeadVN->addKill(DefIdx); + } + + // Update kill markers. + for (LiveInterval::vni_iterator VI = LI->vni_begin(), VE = LI->vni_end(); + VI != VE; ++VI) { + VNInfo* VNI = *VI; + for (unsigned i = 0, e = VNI->kills.size(); i != e; ++i) { + SlotIndex KillIdx = VNI->kills[i]; + if (KillIdx.isPHI()) + continue; + MachineInstr *KillMI = LIs->getInstructionFromIndex(KillIdx); + if (KillMI) { + MachineOperand *KillMO = KillMI->findRegisterUseOperand(CurrLI->reg); + if (KillMO) + // It could be a dead def. + KillMO->setIsKill(); + } + } + } +} + +/// RenumberValno - Split the given valno out into a new vreg, allowing it to +/// be allocated to a different register. This function creates a new vreg, +/// copies the valno and its live ranges over to the new vreg's interval, +/// removes them from the old interval, and rewrites all uses and defs of +/// the original reg to the new vreg within those ranges. +void PreAllocSplitting::RenumberValno(VNInfo* VN) { + SmallVector Stack; + SmallVector VNsToCopy; + Stack.push_back(VN); + + // Walk through and copy the valno we care about, and any other valnos + // that are two-address redefinitions of the one we care about. These + // will need to be rewritten as well. We also check for safety of the + // renumbering here, by making sure that none of the valno involved has + // phi kills. + while (!Stack.empty()) { + VNInfo* OldVN = Stack.back(); + Stack.pop_back(); + + // Bail out if we ever encounter a valno that has a PHI kill. We can't + // renumber these. + if (OldVN->hasPHIKill()) return; + + VNsToCopy.push_back(OldVN); + + // Locate two-address redefinitions + for (VNInfo::KillSet::iterator KI = OldVN->kills.begin(), + KE = OldVN->kills.end(); KI != KE; ++KI) { + assert(!KI->isPHI() && + "VN previously reported having no PHI kills."); + MachineInstr* MI = LIs->getInstructionFromIndex(*KI); + unsigned DefIdx = MI->findRegisterDefOperandIdx(CurrLI->reg); + if (DefIdx == ~0U) continue; + if (MI->isRegTiedToUseOperand(DefIdx)) { + VNInfo* NextVN = + CurrLI->findDefinedVNInfoForRegInt(KI->getDefIndex()); + if (NextVN == OldVN) continue; + Stack.push_back(NextVN); + } + } + } + + // Create the new vreg + unsigned NewVReg = MRI->createVirtualRegister(MRI->getRegClass(CurrLI->reg)); + + // Create the new live interval + LiveInterval& NewLI = LIs->getOrCreateInterval(NewVReg); + + for (SmallVector::iterator OI = VNsToCopy.begin(), OE = + VNsToCopy.end(); OI != OE; ++OI) { + VNInfo* OldVN = *OI; + + // Copy the valno over + VNInfo* NewVN = NewLI.createValueCopy(OldVN, LIs->getVNInfoAllocator()); + NewLI.MergeValueInAsValue(*CurrLI, OldVN, NewVN); + + // Remove the valno from the old interval + CurrLI->removeValNo(OldVN); + } + + // Rewrite defs and uses. This is done in two stages to avoid invalidating + // the reg_iterator. + SmallVector, 8> OpsToChange; + + for (MachineRegisterInfo::reg_iterator I = MRI->reg_begin(CurrLI->reg), + E = MRI->reg_end(); I != E; ++I) { + MachineOperand& MO = I.getOperand(); + SlotIndex InstrIdx = LIs->getInstructionIndex(&*I); + + if ((MO.isUse() && NewLI.liveAt(InstrIdx.getUseIndex())) || + (MO.isDef() && NewLI.liveAt(InstrIdx.getDefIndex()))) + OpsToChange.push_back(std::make_pair(&*I, I.getOperandNo())); + } + + for (SmallVector, 8>::iterator I = + OpsToChange.begin(), E = OpsToChange.end(); I != E; ++I) { + MachineInstr* Inst = I->first; + unsigned OpIdx = I->second; + MachineOperand& MO = Inst->getOperand(OpIdx); + MO.setReg(NewVReg); + } + + // Grow the VirtRegMap, since we've created a new vreg. + VRM->grow(); + + // The renumbered vreg shares a stack slot with the old register. + if (IntervalSSMap.count(CurrLI->reg)) + IntervalSSMap[NewVReg] = IntervalSSMap[CurrLI->reg]; + + NumRenumbers++; +} + +bool PreAllocSplitting::Rematerialize(unsigned VReg, VNInfo* ValNo, + MachineInstr* DefMI, + MachineBasicBlock::iterator RestorePt, + SmallPtrSet& RefsInMBB) { + MachineBasicBlock& MBB = *RestorePt->getParent(); + + MachineBasicBlock::iterator KillPt = BarrierMBB->end(); + if (!ValNo->isDefAccurate() || DefMI->getParent() == BarrierMBB) + KillPt = findSpillPoint(BarrierMBB, Barrier, NULL, RefsInMBB); + else + KillPt = next(MachineBasicBlock::iterator(DefMI)); + + if (KillPt == DefMI->getParent()->end()) + return false; + + TII->reMaterialize(MBB, RestorePt, VReg, 0, DefMI, TRI); + SlotIndex RematIdx = LIs->InsertMachineInstrInMaps(prior(RestorePt)); + + ReconstructLiveInterval(CurrLI); + RematIdx = RematIdx.getDefIndex(); + RenumberValno(CurrLI->findDefinedVNInfoForRegInt(RematIdx)); + + ++NumSplits; + ++NumRemats; + return true; +} + +MachineInstr* PreAllocSplitting::FoldSpill(unsigned vreg, + const TargetRegisterClass* RC, + MachineInstr* DefMI, + MachineInstr* Barrier, + MachineBasicBlock* MBB, + int& SS, + SmallPtrSet& RefsInMBB) { + MachineBasicBlock::iterator Pt = MBB->begin(); + + // Go top down if RefsInMBB is empty. + if (RefsInMBB.empty()) + return 0; + + MachineBasicBlock::iterator FoldPt = Barrier; + while (&*FoldPt != DefMI && FoldPt != MBB->begin() && + !RefsInMBB.count(FoldPt)) + --FoldPt; + + int OpIdx = FoldPt->findRegisterDefOperandIdx(vreg, false); + if (OpIdx == -1) + return 0; + + SmallVector Ops; + Ops.push_back(OpIdx); + + if (!TII->canFoldMemoryOperand(FoldPt, Ops)) + return 0; + + DenseMap::iterator I = IntervalSSMap.find(vreg); + if (I != IntervalSSMap.end()) { + SS = I->second; + } else { + SS = MFI->CreateSpillStackObject(RC->getSize(), RC->getAlignment()); + } + + MachineInstr* FMI = TII->foldMemoryOperand(*MBB->getParent(), + FoldPt, Ops, SS); + + if (FMI) { + LIs->ReplaceMachineInstrInMaps(FoldPt, FMI); + FMI = MBB->insert(MBB->erase(FoldPt), FMI); + ++NumFolds; + + IntervalSSMap[vreg] = SS; + CurrSLI = &LSs->getOrCreateInterval(SS, RC); + if (CurrSLI->hasAtLeastOneValue()) + CurrSValNo = CurrSLI->getValNumInfo(0); + else + CurrSValNo = CurrSLI->getNextValue(SlotIndex(), 0, false, + LSs->getVNInfoAllocator()); + } + + return FMI; +} + +MachineInstr* PreAllocSplitting::FoldRestore(unsigned vreg, + const TargetRegisterClass* RC, + MachineInstr* Barrier, + MachineBasicBlock* MBB, + int SS, + SmallPtrSet& RefsInMBB) { + if ((int)RestoreFoldLimit != -1 && RestoreFoldLimit == (int)NumRestoreFolds) + return 0; + + // Go top down if RefsInMBB is empty. + if (RefsInMBB.empty()) + return 0; + + // Can't fold a restore between a call stack setup and teardown. + MachineBasicBlock::iterator FoldPt = Barrier; + + // Advance from barrier to call frame teardown. + while (FoldPt != MBB->getFirstTerminator() && + FoldPt->getOpcode() != TRI->getCallFrameDestroyOpcode()) { + if (RefsInMBB.count(FoldPt)) + return 0; + + ++FoldPt; + } + + if (FoldPt == MBB->getFirstTerminator()) + return 0; + else + ++FoldPt; + + // Now find the restore point. + while (FoldPt != MBB->getFirstTerminator() && !RefsInMBB.count(FoldPt)) { + if (FoldPt->getOpcode() == TRI->getCallFrameSetupOpcode()) { + while (FoldPt != MBB->getFirstTerminator() && + FoldPt->getOpcode() != TRI->getCallFrameDestroyOpcode()) { + if (RefsInMBB.count(FoldPt)) + return 0; + + ++FoldPt; + } + + if (FoldPt == MBB->getFirstTerminator()) + return 0; + } + + ++FoldPt; + } + + if (FoldPt == MBB->getFirstTerminator()) + return 0; + + int OpIdx = FoldPt->findRegisterUseOperandIdx(vreg, true); + if (OpIdx == -1) + return 0; + + SmallVector Ops; + Ops.push_back(OpIdx); + + if (!TII->canFoldMemoryOperand(FoldPt, Ops)) + return 0; + + MachineInstr* FMI = TII->foldMemoryOperand(*MBB->getParent(), + FoldPt, Ops, SS); + + if (FMI) { + LIs->ReplaceMachineInstrInMaps(FoldPt, FMI); + FMI = MBB->insert(MBB->erase(FoldPt), FMI); + ++NumRestoreFolds; + } + + return FMI; +} + +/// SplitRegLiveInterval - Split (spill and restore) the given live interval +/// so it would not cross the barrier that's being processed. Shrink wrap +/// (minimize) the live interval to the last uses. +bool PreAllocSplitting::SplitRegLiveInterval(LiveInterval *LI) { + DEBUG(errs() << "Pre-alloc splitting " << LI->reg << " for " << *Barrier + << " result: "); + + CurrLI = LI; + + // Find live range where current interval cross the barrier. + LiveInterval::iterator LR = + CurrLI->FindLiveRangeContaining(BarrierIdx.getUseIndex()); + VNInfo *ValNo = LR->valno; + + assert(!ValNo->isUnused() && "Val# is defined by a dead def?"); + + MachineInstr *DefMI = ValNo->isDefAccurate() + ? LIs->getInstructionFromIndex(ValNo->def) : NULL; + + // If this would create a new join point, do not split. + if (DefMI && createsNewJoin(LR, DefMI->getParent(), Barrier->getParent())) { + DEBUG(errs() << "FAILED (would create a new join point).\n"); + return false; + } + + // Find all references in the barrier mbb. + SmallPtrSet RefsInMBB; + for (MachineRegisterInfo::reg_iterator I = MRI->reg_begin(CurrLI->reg), + E = MRI->reg_end(); I != E; ++I) { + MachineInstr *RefMI = &*I; + if (RefMI->getParent() == BarrierMBB) + RefsInMBB.insert(RefMI); + } + + // Find a point to restore the value after the barrier. + MachineBasicBlock::iterator RestorePt = + findRestorePoint(BarrierMBB, Barrier, LR->end, RefsInMBB); + if (RestorePt == BarrierMBB->end()) { + DEBUG(errs() << "FAILED (could not find a suitable restore point).\n"); + return false; + } + + if (DefMI && LIs->isReMaterializable(*LI, ValNo, DefMI)) + if (Rematerialize(LI->reg, ValNo, DefMI, RestorePt, RefsInMBB)) { + DEBUG(errs() << "success (remat).\n"); + return true; + } + + // Add a spill either before the barrier or after the definition. + MachineBasicBlock *DefMBB = DefMI ? DefMI->getParent() : NULL; + const TargetRegisterClass *RC = MRI->getRegClass(CurrLI->reg); + SlotIndex SpillIndex; + MachineInstr *SpillMI = NULL; + int SS = -1; + if (!ValNo->isDefAccurate()) { + // If we don't know where the def is we must split just before the barrier. + if ((SpillMI = FoldSpill(LI->reg, RC, 0, Barrier, + BarrierMBB, SS, RefsInMBB))) { + SpillIndex = LIs->getInstructionIndex(SpillMI); + } else { + MachineBasicBlock::iterator SpillPt = + findSpillPoint(BarrierMBB, Barrier, NULL, RefsInMBB); + if (SpillPt == BarrierMBB->begin()) { + DEBUG(errs() << "FAILED (could not find a suitable spill point).\n"); + return false; // No gap to insert spill. + } + // Add spill. + + SS = CreateSpillStackSlot(CurrLI->reg, RC); + TII->storeRegToStackSlot(*BarrierMBB, SpillPt, CurrLI->reg, true, SS, RC); + SpillMI = prior(SpillPt); + SpillIndex = LIs->InsertMachineInstrInMaps(SpillMI); + } + } else if (!IsAvailableInStack(DefMBB, CurrLI->reg, ValNo->def, + LIs->getZeroIndex(), SpillIndex, SS)) { + // If it's already split, just restore the value. There is no need to spill + // the def again. + if (!DefMI) { + DEBUG(errs() << "FAILED (def is dead).\n"); + return false; // Def is dead. Do nothing. + } + + if ((SpillMI = FoldSpill(LI->reg, RC, DefMI, Barrier, + BarrierMBB, SS, RefsInMBB))) { + SpillIndex = LIs->getInstructionIndex(SpillMI); + } else { + // Check if it's possible to insert a spill after the def MI. + MachineBasicBlock::iterator SpillPt; + if (DefMBB == BarrierMBB) { + // Add spill after the def and the last use before the barrier. + SpillPt = findSpillPoint(BarrierMBB, Barrier, DefMI, + RefsInMBB); + if (SpillPt == DefMBB->begin()) { + DEBUG(errs() << "FAILED (could not find a suitable spill point).\n"); + return false; // No gap to insert spill. + } + } else { + SpillPt = next(MachineBasicBlock::iterator(DefMI)); + if (SpillPt == DefMBB->end()) { + DEBUG(errs() << "FAILED (could not find a suitable spill point).\n"); + return false; // No gap to insert spill. + } + } + // Add spill. + SS = CreateSpillStackSlot(CurrLI->reg, RC); + TII->storeRegToStackSlot(*DefMBB, SpillPt, CurrLI->reg, false, SS, RC); + SpillMI = prior(SpillPt); + SpillIndex = LIs->InsertMachineInstrInMaps(SpillMI); + } + } + + // Remember def instruction index to spill index mapping. + if (DefMI && SpillMI) + Def2SpillMap[ValNo->def] = SpillIndex; + + // Add restore. + bool FoldedRestore = false; + SlotIndex RestoreIndex; + if (MachineInstr* LMI = FoldRestore(CurrLI->reg, RC, Barrier, + BarrierMBB, SS, RefsInMBB)) { + RestorePt = LMI; + RestoreIndex = LIs->getInstructionIndex(RestorePt); + FoldedRestore = true; + } else { + TII->loadRegFromStackSlot(*BarrierMBB, RestorePt, CurrLI->reg, SS, RC); + MachineInstr *LoadMI = prior(RestorePt); + RestoreIndex = LIs->InsertMachineInstrInMaps(LoadMI); + } + + // Update spill stack slot live interval. + UpdateSpillSlotInterval(ValNo, SpillIndex.getUseIndex().getNextSlot(), + RestoreIndex.getDefIndex()); + + ReconstructLiveInterval(CurrLI); + + if (!FoldedRestore) { + SlotIndex RestoreIdx = LIs->getInstructionIndex(prior(RestorePt)); + RestoreIdx = RestoreIdx.getDefIndex(); + RenumberValno(CurrLI->findDefinedVNInfoForRegInt(RestoreIdx)); + } + + ++NumSplits; + DEBUG(errs() << "success.\n"); + return true; +} + +/// SplitRegLiveIntervals - Split all register live intervals that cross the +/// barrier that's being processed. +bool +PreAllocSplitting::SplitRegLiveIntervals(const TargetRegisterClass **RCs, + SmallPtrSet& Split) { + // First find all the virtual registers whose live intervals are intercepted + // by the current barrier. + SmallVector Intervals; + for (const TargetRegisterClass **RC = RCs; *RC; ++RC) { + // FIXME: If it's not safe to move any instruction that defines the barrier + // register class, then it means there are some special dependencies which + // codegen is not modelling. Ignore these barriers for now. + if (!TII->isSafeToMoveRegClassDefs(*RC)) + continue; + std::vector &VRs = MRI->getRegClassVirtRegs(*RC); + for (unsigned i = 0, e = VRs.size(); i != e; ++i) { + unsigned Reg = VRs[i]; + if (!LIs->hasInterval(Reg)) + continue; + LiveInterval *LI = &LIs->getInterval(Reg); + if (LI->liveAt(BarrierIdx) && !Barrier->readsRegister(Reg)) + // Virtual register live interval is intercepted by the barrier. We + // should split and shrink wrap its interval if possible. + Intervals.push_back(LI); + } + } + + // Process the affected live intervals. + bool Change = false; + while (!Intervals.empty()) { + if (PreSplitLimit != -1 && (int)NumSplits == PreSplitLimit) + break; + LiveInterval *LI = Intervals.back(); + Intervals.pop_back(); + bool result = SplitRegLiveInterval(LI); + if (result) Split.insert(LI); + Change |= result; + } + + return Change; +} + +unsigned PreAllocSplitting::getNumberOfNonSpills( + SmallPtrSet& MIs, + unsigned Reg, int FrameIndex, + bool& FeedsTwoAddr) { + unsigned NonSpills = 0; + for (SmallPtrSet::iterator UI = MIs.begin(), UE = MIs.end(); + UI != UE; ++UI) { + int StoreFrameIndex; + unsigned StoreVReg = TII->isStoreToStackSlot(*UI, StoreFrameIndex); + if (StoreVReg != Reg || StoreFrameIndex != FrameIndex) + NonSpills++; + + int DefIdx = (*UI)->findRegisterDefOperandIdx(Reg); + if (DefIdx != -1 && (*UI)->isRegTiedToUseOperand(DefIdx)) + FeedsTwoAddr = true; + } + + return NonSpills; +} + +/// removeDeadSpills - After doing splitting, filter through all intervals we've +/// split, and see if any of the spills are unnecessary. If so, remove them. +bool PreAllocSplitting::removeDeadSpills(SmallPtrSet& split) { + bool changed = false; + + // Walk over all of the live intervals that were touched by the splitter, + // and see if we can do any DCE and/or folding. + for (SmallPtrSet::iterator LI = split.begin(), + LE = split.end(); LI != LE; ++LI) { + DenseMap > VNUseCount; + + // First, collect all the uses of the vreg, and sort them by their + // reaching definition (VNInfo). + for (MachineRegisterInfo::use_iterator UI = MRI->use_begin((*LI)->reg), + UE = MRI->use_end(); UI != UE; ++UI) { + SlotIndex index = LIs->getInstructionIndex(&*UI); + index = index.getUseIndex(); + + const LiveRange* LR = (*LI)->getLiveRangeContaining(index); + VNUseCount[LR->valno].insert(&*UI); + } + + // Now, take the definitions (VNInfo's) one at a time and try to DCE + // and/or fold them away. + for (LiveInterval::vni_iterator VI = (*LI)->vni_begin(), + VE = (*LI)->vni_end(); VI != VE; ++VI) { + + if (DeadSplitLimit != -1 && (int)NumDeadSpills == DeadSplitLimit) + return changed; + + VNInfo* CurrVN = *VI; + + // We don't currently try to handle definitions with PHI kills, because + // it would involve processing more than one VNInfo at once. + if (CurrVN->hasPHIKill()) continue; + + // We also don't try to handle the results of PHI joins, since there's + // no defining instruction to analyze. + if (!CurrVN->isDefAccurate() || CurrVN->isUnused()) continue; + + // We're only interested in eliminating cruft introduced by the splitter, + // is of the form load-use or load-use-store. First, check that the + // definition is a load, and remember what stack slot we loaded it from. + MachineInstr* DefMI = LIs->getInstructionFromIndex(CurrVN->def); + int FrameIndex; + if (!TII->isLoadFromStackSlot(DefMI, FrameIndex)) continue; + + // If the definition has no uses at all, just DCE it. + if (VNUseCount[CurrVN].size() == 0) { + LIs->RemoveMachineInstrFromMaps(DefMI); + (*LI)->removeValNo(CurrVN); + DefMI->eraseFromParent(); + VNUseCount.erase(CurrVN); + NumDeadSpills++; + changed = true; + continue; + } + + // Second, get the number of non-store uses of the definition, as well as + // a flag indicating whether it feeds into a later two-address definition. + bool FeedsTwoAddr = false; + unsigned NonSpillCount = getNumberOfNonSpills(VNUseCount[CurrVN], + (*LI)->reg, FrameIndex, + FeedsTwoAddr); + + // If there's one non-store use and it doesn't feed a two-addr, then + // this is a load-use-store case that we can try to fold. + if (NonSpillCount == 1 && !FeedsTwoAddr) { + // Start by finding the non-store use MachineInstr. + SmallPtrSet::iterator UI = VNUseCount[CurrVN].begin(); + int StoreFrameIndex; + unsigned StoreVReg = TII->isStoreToStackSlot(*UI, StoreFrameIndex); + while (UI != VNUseCount[CurrVN].end() && + (StoreVReg == (*LI)->reg && StoreFrameIndex == FrameIndex)) { + ++UI; + if (UI != VNUseCount[CurrVN].end()) + StoreVReg = TII->isStoreToStackSlot(*UI, StoreFrameIndex); + } + if (UI == VNUseCount[CurrVN].end()) continue; + + MachineInstr* use = *UI; + + // Attempt to fold it away! + int OpIdx = use->findRegisterUseOperandIdx((*LI)->reg, false); + if (OpIdx == -1) continue; + SmallVector Ops; + Ops.push_back(OpIdx); + if (!TII->canFoldMemoryOperand(use, Ops)) continue; + + MachineInstr* NewMI = + TII->foldMemoryOperand(*use->getParent()->getParent(), + use, Ops, FrameIndex); + + if (!NewMI) continue; + + // Update relevant analyses. + LIs->RemoveMachineInstrFromMaps(DefMI); + LIs->ReplaceMachineInstrInMaps(use, NewMI); + (*LI)->removeValNo(CurrVN); + + DefMI->eraseFromParent(); + MachineBasicBlock* MBB = use->getParent(); + NewMI = MBB->insert(MBB->erase(use), NewMI); + VNUseCount[CurrVN].erase(use); + + // Remove deleted instructions. Note that we need to remove them from + // the VNInfo->use map as well, just to be safe. + for (SmallPtrSet::iterator II = + VNUseCount[CurrVN].begin(), IE = VNUseCount[CurrVN].end(); + II != IE; ++II) { + for (DenseMap >::iterator + VNI = VNUseCount.begin(), VNE = VNUseCount.end(); VNI != VNE; + ++VNI) + if (VNI->first != CurrVN) + VNI->second.erase(*II); + LIs->RemoveMachineInstrFromMaps(*II); + (*II)->eraseFromParent(); + } + + VNUseCount.erase(CurrVN); + + for (DenseMap >::iterator + VI = VNUseCount.begin(), VE = VNUseCount.end(); VI != VE; ++VI) + if (VI->second.erase(use)) + VI->second.insert(NewMI); + + NumDeadSpills++; + changed = true; + continue; + } + + // If there's more than one non-store instruction, we can't profitably + // fold it, so bail. + if (NonSpillCount) continue; + + // Otherwise, this is a load-store case, so DCE them. + for (SmallPtrSet::iterator UI = + VNUseCount[CurrVN].begin(), UE = VNUseCount[CurrVN].end(); + UI != UE; ++UI) { + LIs->RemoveMachineInstrFromMaps(*UI); + (*UI)->eraseFromParent(); + } + + VNUseCount.erase(CurrVN); + + LIs->RemoveMachineInstrFromMaps(DefMI); + (*LI)->removeValNo(CurrVN); + DefMI->eraseFromParent(); + NumDeadSpills++; + changed = true; + } + } + + return changed; +} + +bool PreAllocSplitting::createsNewJoin(LiveRange* LR, + MachineBasicBlock* DefMBB, + MachineBasicBlock* BarrierMBB) { + if (DefMBB == BarrierMBB) + return false; + + if (LR->valno->hasPHIKill()) + return false; + + SlotIndex MBBEnd = LIs->getMBBEndIdx(BarrierMBB); + if (LR->end < MBBEnd) + return false; + + MachineLoopInfo& MLI = getAnalysis(); + if (MLI.getLoopFor(DefMBB) != MLI.getLoopFor(BarrierMBB)) + return true; + + MachineDominatorTree& MDT = getAnalysis(); + SmallPtrSet Visited; + typedef std::pair ItPair; + SmallVector Stack; + Stack.push_back(std::make_pair(BarrierMBB, BarrierMBB->succ_begin())); + + while (!Stack.empty()) { + ItPair P = Stack.back(); + Stack.pop_back(); + + MachineBasicBlock* PredMBB = P.first; + MachineBasicBlock::succ_iterator S = P.second; + + if (S == PredMBB->succ_end()) + continue; + else if (Visited.count(*S)) { + Stack.push_back(std::make_pair(PredMBB, ++S)); + continue; + } else + Stack.push_back(std::make_pair(PredMBB, S+1)); + + MachineBasicBlock* MBB = *S; + Visited.insert(MBB); + + if (MBB == BarrierMBB) + return true; + + MachineDomTreeNode* DefMDTN = MDT.getNode(DefMBB); + MachineDomTreeNode* BarrierMDTN = MDT.getNode(BarrierMBB); + MachineDomTreeNode* MDTN = MDT.getNode(MBB)->getIDom(); + while (MDTN) { + if (MDTN == DefMDTN) + return true; + else if (MDTN == BarrierMDTN) + break; + MDTN = MDTN->getIDom(); + } + + MBBEnd = LIs->getMBBEndIdx(MBB); + if (LR->end > MBBEnd) + Stack.push_back(std::make_pair(MBB, MBB->succ_begin())); + } + + return false; +} + + +bool PreAllocSplitting::runOnMachineFunction(MachineFunction &MF) { + CurrMF = &MF; + TM = &MF.getTarget(); + TRI = TM->getRegisterInfo(); + TII = TM->getInstrInfo(); + MFI = MF.getFrameInfo(); + MRI = &MF.getRegInfo(); + SIs = &getAnalysis(); + LIs = &getAnalysis(); + LSs = &getAnalysis(); + VRM = &getAnalysis(); + + bool MadeChange = false; + + // Make sure blocks are numbered in order. + MF.RenumberBlocks(); + + MachineBasicBlock *Entry = MF.begin(); + SmallPtrSet Visited; + + SmallPtrSet Split; + + for (df_ext_iterator > + DFI = df_ext_begin(Entry, Visited), E = df_ext_end(Entry, Visited); + DFI != E; ++DFI) { + BarrierMBB = *DFI; + for (MachineBasicBlock::iterator I = BarrierMBB->begin(), + E = BarrierMBB->end(); I != E; ++I) { + Barrier = &*I; + const TargetRegisterClass **BarrierRCs = + Barrier->getDesc().getRegClassBarriers(); + if (!BarrierRCs) + continue; + BarrierIdx = LIs->getInstructionIndex(Barrier); + MadeChange |= SplitRegLiveIntervals(BarrierRCs, Split); + } + } + + MadeChange |= removeDeadSpills(Split); + + return MadeChange; +} diff --git a/libclamav/c++/llvm/lib/CodeGen/ProcessImplicitDefs.cpp b/libclamav/c++/llvm/lib/CodeGen/ProcessImplicitDefs.cpp new file mode 100644 index 000000000..c9a33d885 --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/ProcessImplicitDefs.cpp @@ -0,0 +1,275 @@ +//===---------------------- ProcessImplicitDefs.cpp -----------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "processimplicitdefs" + +#include "llvm/CodeGen/ProcessImplicitDefs.h" + +#include "llvm/ADT/DepthFirstIterator.h" +#include "llvm/ADT/SmallSet.h" +#include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/CodeGen/LiveVariables.h" +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/Support/Debug.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetRegisterInfo.h" + + +using namespace llvm; + +char ProcessImplicitDefs::ID = 0; +static RegisterPass X("processimpdefs", + "Process Implicit Definitions."); + +void ProcessImplicitDefs::getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesCFG(); + AU.addPreserved(); + AU.addPreserved(); + AU.addRequired(); + AU.addPreservedID(MachineLoopInfoID); + AU.addPreservedID(MachineDominatorsID); + AU.addPreservedID(TwoAddressInstructionPassID); + AU.addPreservedID(PHIEliminationID); + MachineFunctionPass::getAnalysisUsage(AU); +} + +bool ProcessImplicitDefs::CanTurnIntoImplicitDef(MachineInstr *MI, + unsigned Reg, unsigned OpIdx, + const TargetInstrInfo *tii_) { + unsigned SrcReg, DstReg, SrcSubReg, DstSubReg; + if (tii_->isMoveInstr(*MI, SrcReg, DstReg, SrcSubReg, DstSubReg) && + Reg == SrcReg) + return true; + + if (OpIdx == 2 && MI->getOpcode() == TargetInstrInfo::SUBREG_TO_REG) + return true; + if (OpIdx == 1 && MI->getOpcode() == TargetInstrInfo::EXTRACT_SUBREG) + return true; + return false; +} + +/// processImplicitDefs - Process IMPLICIT_DEF instructions and make sure +/// there is one implicit_def for each use. Add isUndef marker to +/// implicit_def defs and their uses. +bool ProcessImplicitDefs::runOnMachineFunction(MachineFunction &fn) { + + DEBUG(errs() << "********** PROCESS IMPLICIT DEFS **********\n" + << "********** Function: " + << ((Value*)fn.getFunction())->getName() << '\n'); + + bool Changed = false; + + const TargetInstrInfo *tii_ = fn.getTarget().getInstrInfo(); + const TargetRegisterInfo *tri_ = fn.getTarget().getRegisterInfo(); + MachineRegisterInfo *mri_ = &fn.getRegInfo(); + + LiveVariables *lv_ = &getAnalysis(); + + SmallSet ImpDefRegs; + SmallVector ImpDefMIs; + SmallVector RUses; + SmallPtrSet Visited; + SmallPtrSet ModInsts; + + MachineBasicBlock *Entry = fn.begin(); + for (df_ext_iterator > + DFI = df_ext_begin(Entry, Visited), E = df_ext_end(Entry, Visited); + DFI != E; ++DFI) { + MachineBasicBlock *MBB = *DFI; + for (MachineBasicBlock::iterator I = MBB->begin(), E = MBB->end(); + I != E; ) { + MachineInstr *MI = &*I; + ++I; + if (MI->getOpcode() == TargetInstrInfo::IMPLICIT_DEF) { + unsigned Reg = MI->getOperand(0).getReg(); + ImpDefRegs.insert(Reg); + if (TargetRegisterInfo::isPhysicalRegister(Reg)) { + for (const unsigned *SS = tri_->getSubRegisters(Reg); *SS; ++SS) + ImpDefRegs.insert(*SS); + } + ImpDefMIs.push_back(MI); + continue; + } + + if (MI->getOpcode() == TargetInstrInfo::INSERT_SUBREG) { + MachineOperand &MO = MI->getOperand(2); + if (ImpDefRegs.count(MO.getReg())) { + // %reg1032 = INSERT_SUBREG %reg1032, undef, 2 + // This is an identity copy, eliminate it now. + if (MO.isKill()) { + LiveVariables::VarInfo& vi = lv_->getVarInfo(MO.getReg()); + vi.removeKill(MI); + } + MI->eraseFromParent(); + Changed = true; + continue; + } + } + + bool ChangedToImpDef = false; + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + MachineOperand& MO = MI->getOperand(i); + if (!MO.isReg() || !MO.isUse() || MO.isUndef()) + continue; + unsigned Reg = MO.getReg(); + if (!Reg) + continue; + if (!ImpDefRegs.count(Reg)) + continue; + // Use is a copy, just turn it into an implicit_def. + if (CanTurnIntoImplicitDef(MI, Reg, i, tii_)) { + bool isKill = MO.isKill(); + MI->setDesc(tii_->get(TargetInstrInfo::IMPLICIT_DEF)); + for (int j = MI->getNumOperands() - 1, ee = 0; j > ee; --j) + MI->RemoveOperand(j); + if (isKill) { + ImpDefRegs.erase(Reg); + LiveVariables::VarInfo& vi = lv_->getVarInfo(Reg); + vi.removeKill(MI); + } + ChangedToImpDef = true; + Changed = true; + break; + } + + Changed = true; + MO.setIsUndef(); + if (MO.isKill() || MI->isRegTiedToDefOperand(i)) { + // Make sure other uses of + for (unsigned j = i+1; j != e; ++j) { + MachineOperand &MOJ = MI->getOperand(j); + if (MOJ.isReg() && MOJ.isUse() && MOJ.getReg() == Reg) + MOJ.setIsUndef(); + } + ImpDefRegs.erase(Reg); + } + } + + if (ChangedToImpDef) { + // Backtrack to process this new implicit_def. + --I; + } else { + for (unsigned i = 0; i != MI->getNumOperands(); ++i) { + MachineOperand& MO = MI->getOperand(i); + if (!MO.isReg() || !MO.isDef()) + continue; + ImpDefRegs.erase(MO.getReg()); + } + } + } + + // Any outstanding liveout implicit_def's? + for (unsigned i = 0, e = ImpDefMIs.size(); i != e; ++i) { + MachineInstr *MI = ImpDefMIs[i]; + unsigned Reg = MI->getOperand(0).getReg(); + if (TargetRegisterInfo::isPhysicalRegister(Reg) || + !ImpDefRegs.count(Reg)) { + // Delete all "local" implicit_def's. That include those which define + // physical registers since they cannot be liveout. + MI->eraseFromParent(); + Changed = true; + continue; + } + + // If there are multiple defs of the same register and at least one + // is not an implicit_def, do not insert implicit_def's before the + // uses. + bool Skip = false; + SmallVector DeadImpDefs; + for (MachineRegisterInfo::def_iterator DI = mri_->def_begin(Reg), + DE = mri_->def_end(); DI != DE; ++DI) { + MachineInstr *DeadImpDef = &*DI; + if (DeadImpDef->getOpcode() != TargetInstrInfo::IMPLICIT_DEF) { + Skip = true; + break; + } + DeadImpDefs.push_back(DeadImpDef); + } + if (Skip) + continue; + + // The only implicit_def which we want to keep are those that are live + // out of its block. + for (unsigned j = 0, ee = DeadImpDefs.size(); j != ee; ++j) + DeadImpDefs[j]->eraseFromParent(); + Changed = true; + + // Process each use instruction once. + for (MachineRegisterInfo::use_iterator UI = mri_->use_begin(Reg), + UE = mri_->use_end(); UI != UE; ++UI) { + MachineInstr *RMI = &*UI; + MachineBasicBlock *RMBB = RMI->getParent(); + if (RMBB == MBB) + continue; + if (ModInsts.insert(RMI)) + RUses.push_back(RMI); + } + + for (unsigned i = 0, e = RUses.size(); i != e; ++i) { + MachineInstr *RMI = RUses[i]; + + // Turn a copy use into an implicit_def. + unsigned SrcReg, DstReg, SrcSubReg, DstSubReg; + if (tii_->isMoveInstr(*RMI, SrcReg, DstReg, SrcSubReg, DstSubReg) && + Reg == SrcReg) { + RMI->setDesc(tii_->get(TargetInstrInfo::IMPLICIT_DEF)); + + bool isKill = false; + SmallVector Ops; + for (unsigned j = 0, ee = RMI->getNumOperands(); j != ee; ++j) { + MachineOperand &RRMO = RMI->getOperand(j); + if (RRMO.isReg() && RRMO.getReg() == Reg) { + Ops.push_back(j); + if (RRMO.isKill()) + isKill = true; + } + } + // Leave the other operands along. + for (unsigned j = 0, ee = Ops.size(); j != ee; ++j) { + unsigned OpIdx = Ops[j]; + RMI->RemoveOperand(OpIdx-j); + } + + // Update LiveVariables varinfo if the instruction is a kill. + if (isKill) { + LiveVariables::VarInfo& vi = lv_->getVarInfo(Reg); + vi.removeKill(RMI); + } + continue; + } + + // Replace Reg with a new vreg that's marked implicit. + const TargetRegisterClass* RC = mri_->getRegClass(Reg); + unsigned NewVReg = mri_->createVirtualRegister(RC); + bool isKill = true; + for (unsigned j = 0, ee = RMI->getNumOperands(); j != ee; ++j) { + MachineOperand &RRMO = RMI->getOperand(j); + if (RRMO.isReg() && RRMO.getReg() == Reg) { + RRMO.setReg(NewVReg); + RRMO.setIsUndef(); + if (isKill) { + // Only the first operand of NewVReg is marked kill. + RRMO.setIsKill(); + isKill = false; + } + } + } + } + RUses.clear(); + } + ModInsts.clear(); + ImpDefRegs.clear(); + ImpDefMIs.clear(); + } + + return Changed; +} + diff --git a/libclamav/c++/llvm/lib/CodeGen/PrologEpilogInserter.cpp b/libclamav/c++/llvm/lib/CodeGen/PrologEpilogInserter.cpp new file mode 100644 index 000000000..8905f757a --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/PrologEpilogInserter.cpp @@ -0,0 +1,920 @@ +//===-- PrologEpilogInserter.cpp - Insert Prolog/Epilog code in function --===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This pass is responsible for finalizing the functions frame layout, saving +// callee saved registers, and for emitting prolog & epilog code for the +// function. +// +// This pass must be run after register allocation. After this pass is +// executed, it is illegal to construct MO_FrameIndex operands. +// +// This pass provides an optional shrink wrapping variant of prolog/epilog +// insertion, enabled via --shrink-wrap. See ShrinkWrapping.cpp. +// +//===----------------------------------------------------------------------===// + +#include "PrologEpilogInserter.h" +#include "llvm/CodeGen/MachineDominators.h" +#include "llvm/CodeGen/MachineLoopInfo.h" +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/RegisterScavenging.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Target/TargetFrameInfo.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Compiler.h" +#include "llvm/ADT/IndexedMap.h" +#include "llvm/ADT/STLExtras.h" +#include + +using namespace llvm; + +char PEI::ID = 0; + +static RegisterPass +X("prologepilog", "Prologue/Epilogue Insertion"); + +/// createPrologEpilogCodeInserter - This function returns a pass that inserts +/// prolog and epilog code, and eliminates abstract frame references. +/// +FunctionPass *llvm::createPrologEpilogCodeInserter() { return new PEI(); } + +/// runOnMachineFunction - Insert prolog/epilog code and replace abstract +/// frame indexes with appropriate references. +/// +bool PEI::runOnMachineFunction(MachineFunction &Fn) { + const Function* F = Fn.getFunction(); + const TargetRegisterInfo *TRI = Fn.getTarget().getRegisterInfo(); + RS = TRI->requiresRegisterScavenging(Fn) ? new RegScavenger() : NULL; + FrameIndexVirtualScavenging = TRI->requiresFrameIndexScavenging(Fn); + + // Get MachineModuleInfo so that we can track the construction of the + // frame. + if (MachineModuleInfo *MMI = getAnalysisIfAvailable()) + Fn.getFrameInfo()->setMachineModuleInfo(MMI); + + // Calculate the MaxCallFrameSize and HasCalls variables for the function's + // frame information. Also eliminates call frame pseudo instructions. + calculateCallsInformation(Fn); + + // Allow the target machine to make some adjustments to the function + // e.g. UsedPhysRegs before calculateCalleeSavedRegisters. + TRI->processFunctionBeforeCalleeSavedScan(Fn, RS); + + // Scan the function for modified callee saved registers and insert spill code + // for any callee saved registers that are modified. + calculateCalleeSavedRegisters(Fn); + + // Determine placement of CSR spill/restore code: + // - with shrink wrapping, place spills and restores to tightly + // enclose regions in the Machine CFG of the function where + // they are used. Without shrink wrapping + // - default (no shrink wrapping), place all spills in the + // entry block, all restores in return blocks. + placeCSRSpillsAndRestores(Fn); + + // Add the code to save and restore the callee saved registers + if (!F->hasFnAttr(Attribute::Naked)) + insertCSRSpillsAndRestores(Fn); + + // Allow the target machine to make final modifications to the function + // before the frame layout is finalized. + TRI->processFunctionBeforeFrameFinalized(Fn); + + // Calculate actual frame offsets for all abstract stack objects... + calculateFrameObjectOffsets(Fn); + + // Add prolog and epilog code to the function. This function is required + // to align the stack frame as necessary for any stack variables or + // called functions. Because of this, calculateCalleeSavedRegisters + // must be called before this function in order to set the HasCalls + // and MaxCallFrameSize variables. + if (!F->hasFnAttr(Attribute::Naked)) + insertPrologEpilogCode(Fn); + + // Replace all MO_FrameIndex operands with physical register references + // and actual offsets. + // + replaceFrameIndices(Fn); + + // If register scavenging is needed, as we've enabled doing it as a + // post-pass, scavenge the virtual registers that frame index elimiation + // inserted. + if (TRI->requiresRegisterScavenging(Fn) && FrameIndexVirtualScavenging) + scavengeFrameVirtualRegs(Fn); + + delete RS; + clearAllSets(); + return true; +} + +#if 0 +void PEI::getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesCFG(); + if (ShrinkWrapping || ShrinkWrapFunc != "") { + AU.addRequired(); + AU.addRequired(); + } + AU.addPreserved(); + AU.addPreserved(); + MachineFunctionPass::getAnalysisUsage(AU); +} +#endif + +/// calculateCallsInformation - Calculate the MaxCallFrameSize and HasCalls +/// variables for the function's frame information and eliminate call frame +/// pseudo instructions. +void PEI::calculateCallsInformation(MachineFunction &Fn) { + const TargetRegisterInfo *RegInfo = Fn.getTarget().getRegisterInfo(); + + unsigned MaxCallFrameSize = 0; + bool HasCalls = false; + + // Get the function call frame set-up and tear-down instruction opcode + int FrameSetupOpcode = RegInfo->getCallFrameSetupOpcode(); + int FrameDestroyOpcode = RegInfo->getCallFrameDestroyOpcode(); + + // Early exit for targets which have no call frame setup/destroy pseudo + // instructions. + if (FrameSetupOpcode == -1 && FrameDestroyOpcode == -1) + return; + + std::vector FrameSDOps; + for (MachineFunction::iterator BB = Fn.begin(), E = Fn.end(); BB != E; ++BB) + for (MachineBasicBlock::iterator I = BB->begin(); I != BB->end(); ++I) + if (I->getOpcode() == FrameSetupOpcode || + I->getOpcode() == FrameDestroyOpcode) { + assert(I->getNumOperands() >= 1 && "Call Frame Setup/Destroy Pseudo" + " instructions should have a single immediate argument!"); + unsigned Size = I->getOperand(0).getImm(); + if (Size > MaxCallFrameSize) MaxCallFrameSize = Size; + HasCalls = true; + FrameSDOps.push_back(I); + } else if (I->getOpcode() == TargetInstrInfo::INLINEASM) { + // An InlineAsm might be a call; assume it is to get the stack frame + // aligned correctly for calls. + HasCalls = true; + } + + MachineFrameInfo *FFI = Fn.getFrameInfo(); + FFI->setHasCalls(HasCalls); + FFI->setMaxCallFrameSize(MaxCallFrameSize); + + for (std::vector::iterator + i = FrameSDOps.begin(), e = FrameSDOps.end(); i != e; ++i) { + MachineBasicBlock::iterator I = *i; + + // If call frames are not being included as part of the stack frame, and + // there is no dynamic allocation (therefore referencing frame slots off + // sp), leave the pseudo ops alone. We'll eliminate them later. + if (RegInfo->hasReservedCallFrame(Fn) || RegInfo->hasFP(Fn)) + RegInfo->eliminateCallFramePseudoInstr(Fn, *I->getParent(), I); + } +} + + +/// calculateCalleeSavedRegisters - Scan the function for modified callee saved +/// registers. +void PEI::calculateCalleeSavedRegisters(MachineFunction &Fn) { + const TargetRegisterInfo *RegInfo = Fn.getTarget().getRegisterInfo(); + const TargetFrameInfo *TFI = Fn.getTarget().getFrameInfo(); + MachineFrameInfo *FFI = Fn.getFrameInfo(); + + // Get the callee saved register list... + const unsigned *CSRegs = RegInfo->getCalleeSavedRegs(&Fn); + + // These are used to keep track the callee-save area. Initialize them. + MinCSFrameIndex = INT_MAX; + MaxCSFrameIndex = 0; + + // Early exit for targets which have no callee saved registers. + if (CSRegs == 0 || CSRegs[0] == 0) + return; + + // Figure out which *callee saved* registers are modified by the current + // function, thus needing to be saved and restored in the prolog/epilog. + const TargetRegisterClass * const *CSRegClasses = + RegInfo->getCalleeSavedRegClasses(&Fn); + + std::vector CSI; + for (unsigned i = 0; CSRegs[i]; ++i) { + unsigned Reg = CSRegs[i]; + if (Fn.getRegInfo().isPhysRegUsed(Reg)) { + // If the reg is modified, save it! + CSI.push_back(CalleeSavedInfo(Reg, CSRegClasses[i])); + } else { + for (const unsigned *AliasSet = RegInfo->getAliasSet(Reg); + *AliasSet; ++AliasSet) { // Check alias registers too. + if (Fn.getRegInfo().isPhysRegUsed(*AliasSet)) { + CSI.push_back(CalleeSavedInfo(Reg, CSRegClasses[i])); + break; + } + } + } + } + + if (CSI.empty()) + return; // Early exit if no callee saved registers are modified! + + unsigned NumFixedSpillSlots; + const TargetFrameInfo::SpillSlot *FixedSpillSlots = + TFI->getCalleeSavedSpillSlots(NumFixedSpillSlots); + + // Now that we know which registers need to be saved and restored, allocate + // stack slots for them. + for (std::vector::iterator + I = CSI.begin(), E = CSI.end(); I != E; ++I) { + unsigned Reg = I->getReg(); + const TargetRegisterClass *RC = I->getRegClass(); + + int FrameIdx; + if (RegInfo->hasReservedSpillSlot(Fn, Reg, FrameIdx)) { + I->setFrameIdx(FrameIdx); + continue; + } + + // Check to see if this physreg must be spilled to a particular stack slot + // on this target. + const TargetFrameInfo::SpillSlot *FixedSlot = FixedSpillSlots; + while (FixedSlot != FixedSpillSlots+NumFixedSpillSlots && + FixedSlot->Reg != Reg) + ++FixedSlot; + + if (FixedSlot == FixedSpillSlots + NumFixedSpillSlots) { + // Nope, just spill it anywhere convenient. + unsigned Align = RC->getAlignment(); + unsigned StackAlign = TFI->getStackAlignment(); + + // We may not be able to satisfy the desired alignment specification of + // the TargetRegisterClass if the stack alignment is smaller. Use the + // min. + Align = std::min(Align, StackAlign); + FrameIdx = FFI->CreateStackObject(RC->getSize(), Align, true); + if ((unsigned)FrameIdx < MinCSFrameIndex) MinCSFrameIndex = FrameIdx; + if ((unsigned)FrameIdx > MaxCSFrameIndex) MaxCSFrameIndex = FrameIdx; + } else { + // Spill it to the stack where we must. + FrameIdx = FFI->CreateFixedObject(RC->getSize(), FixedSlot->Offset, + true, false); + } + + I->setFrameIdx(FrameIdx); + } + + FFI->setCalleeSavedInfo(CSI); +} + +/// insertCSRSpillsAndRestores - Insert spill and restore code for +/// callee saved registers used in the function, handling shrink wrapping. +/// +void PEI::insertCSRSpillsAndRestores(MachineFunction &Fn) { + // Get callee saved register information. + MachineFrameInfo *FFI = Fn.getFrameInfo(); + const std::vector &CSI = FFI->getCalleeSavedInfo(); + + FFI->setCalleeSavedInfoValid(true); + + // Early exit if no callee saved registers are modified! + if (CSI.empty()) + return; + + const TargetInstrInfo &TII = *Fn.getTarget().getInstrInfo(); + MachineBasicBlock::iterator I; + + if (! ShrinkWrapThisFunction) { + // Spill using target interface. + I = EntryBlock->begin(); + if (!TII.spillCalleeSavedRegisters(*EntryBlock, I, CSI)) { + for (unsigned i = 0, e = CSI.size(); i != e; ++i) { + // Add the callee-saved register as live-in. + // It's killed at the spill. + EntryBlock->addLiveIn(CSI[i].getReg()); + + // Insert the spill to the stack frame. + TII.storeRegToStackSlot(*EntryBlock, I, CSI[i].getReg(), true, + CSI[i].getFrameIdx(), CSI[i].getRegClass()); + } + } + + // Restore using target interface. + for (unsigned ri = 0, re = ReturnBlocks.size(); ri != re; ++ri) { + MachineBasicBlock* MBB = ReturnBlocks[ri]; + I = MBB->end(); --I; + + // Skip over all terminator instructions, which are part of the return + // sequence. + MachineBasicBlock::iterator I2 = I; + while (I2 != MBB->begin() && (--I2)->getDesc().isTerminator()) + I = I2; + + bool AtStart = I == MBB->begin(); + MachineBasicBlock::iterator BeforeI = I; + if (!AtStart) + --BeforeI; + + // Restore all registers immediately before the return and any + // terminators that preceed it. + if (!TII.restoreCalleeSavedRegisters(*MBB, I, CSI)) { + for (unsigned i = 0, e = CSI.size(); i != e; ++i) { + TII.loadRegFromStackSlot(*MBB, I, CSI[i].getReg(), + CSI[i].getFrameIdx(), + CSI[i].getRegClass()); + assert(I != MBB->begin() && + "loadRegFromStackSlot didn't insert any code!"); + // Insert in reverse order. loadRegFromStackSlot can insert + // multiple instructions. + if (AtStart) + I = MBB->begin(); + else { + I = BeforeI; + ++I; + } + } + } + } + return; + } + + // Insert spills. + std::vector blockCSI; + for (CSRegBlockMap::iterator BI = CSRSave.begin(), + BE = CSRSave.end(); BI != BE; ++BI) { + MachineBasicBlock* MBB = BI->first; + CSRegSet save = BI->second; + + if (save.empty()) + continue; + + blockCSI.clear(); + for (CSRegSet::iterator RI = save.begin(), + RE = save.end(); RI != RE; ++RI) { + blockCSI.push_back(CSI[*RI]); + } + assert(blockCSI.size() > 0 && + "Could not collect callee saved register info"); + + I = MBB->begin(); + + // When shrink wrapping, use stack slot stores/loads. + for (unsigned i = 0, e = blockCSI.size(); i != e; ++i) { + // Add the callee-saved register as live-in. + // It's killed at the spill. + MBB->addLiveIn(blockCSI[i].getReg()); + + // Insert the spill to the stack frame. + TII.storeRegToStackSlot(*MBB, I, blockCSI[i].getReg(), + true, + blockCSI[i].getFrameIdx(), + blockCSI[i].getRegClass()); + } + } + + for (CSRegBlockMap::iterator BI = CSRRestore.begin(), + BE = CSRRestore.end(); BI != BE; ++BI) { + MachineBasicBlock* MBB = BI->first; + CSRegSet restore = BI->second; + + if (restore.empty()) + continue; + + blockCSI.clear(); + for (CSRegSet::iterator RI = restore.begin(), + RE = restore.end(); RI != RE; ++RI) { + blockCSI.push_back(CSI[*RI]); + } + assert(blockCSI.size() > 0 && + "Could not find callee saved register info"); + + // If MBB is empty and needs restores, insert at the _beginning_. + if (MBB->empty()) { + I = MBB->begin(); + } else { + I = MBB->end(); + --I; + + // Skip over all terminator instructions, which are part of the + // return sequence. + if (! I->getDesc().isTerminator()) { + ++I; + } else { + MachineBasicBlock::iterator I2 = I; + while (I2 != MBB->begin() && (--I2)->getDesc().isTerminator()) + I = I2; + } + } + + bool AtStart = I == MBB->begin(); + MachineBasicBlock::iterator BeforeI = I; + if (!AtStart) + --BeforeI; + + // Restore all registers immediately before the return and any + // terminators that preceed it. + for (unsigned i = 0, e = blockCSI.size(); i != e; ++i) { + TII.loadRegFromStackSlot(*MBB, I, blockCSI[i].getReg(), + blockCSI[i].getFrameIdx(), + blockCSI[i].getRegClass()); + assert(I != MBB->begin() && + "loadRegFromStackSlot didn't insert any code!"); + // Insert in reverse order. loadRegFromStackSlot can insert + // multiple instructions. + if (AtStart) + I = MBB->begin(); + else { + I = BeforeI; + ++I; + } + } + } +} + +/// AdjustStackOffset - Helper function used to adjust the stack frame offset. +static inline void +AdjustStackOffset(MachineFrameInfo *FFI, int FrameIdx, + bool StackGrowsDown, int64_t &Offset, + unsigned &MaxAlign) { + // If the stack grows down, add the object size to find the lowest address. + if (StackGrowsDown) + Offset += FFI->getObjectSize(FrameIdx); + + unsigned Align = FFI->getObjectAlignment(FrameIdx); + + // If the alignment of this object is greater than that of the stack, then + // increase the stack alignment to match. + MaxAlign = std::max(MaxAlign, Align); + + // Adjust to alignment boundary. + Offset = (Offset + Align - 1) / Align * Align; + + if (StackGrowsDown) { + FFI->setObjectOffset(FrameIdx, -Offset); // Set the computed offset + } else { + FFI->setObjectOffset(FrameIdx, Offset); + Offset += FFI->getObjectSize(FrameIdx); + } +} + +/// calculateFrameObjectOffsets - Calculate actual frame offsets for all of the +/// abstract stack objects. +/// +void PEI::calculateFrameObjectOffsets(MachineFunction &Fn) { + const TargetFrameInfo &TFI = *Fn.getTarget().getFrameInfo(); + + bool StackGrowsDown = + TFI.getStackGrowthDirection() == TargetFrameInfo::StackGrowsDown; + + // Loop over all of the stack objects, assigning sequential addresses... + MachineFrameInfo *FFI = Fn.getFrameInfo(); + + unsigned MaxAlign = 1; + + // Start at the beginning of the local area. + // The Offset is the distance from the stack top in the direction + // of stack growth -- so it's always nonnegative. + int LocalAreaOffset = TFI.getOffsetOfLocalArea(); + if (StackGrowsDown) + LocalAreaOffset = -LocalAreaOffset; + assert(LocalAreaOffset >= 0 + && "Local area offset should be in direction of stack growth"); + int64_t Offset = LocalAreaOffset; + + // If there are fixed sized objects that are preallocated in the local area, + // non-fixed objects can't be allocated right at the start of local area. + // We currently don't support filling in holes in between fixed sized + // objects, so we adjust 'Offset' to point to the end of last fixed sized + // preallocated object. + for (int i = FFI->getObjectIndexBegin(); i != 0; ++i) { + int64_t FixedOff; + if (StackGrowsDown) { + // The maximum distance from the stack pointer is at lower address of + // the object -- which is given by offset. For down growing stack + // the offset is negative, so we negate the offset to get the distance. + FixedOff = -FFI->getObjectOffset(i); + } else { + // The maximum distance from the start pointer is at the upper + // address of the object. + FixedOff = FFI->getObjectOffset(i) + FFI->getObjectSize(i); + } + if (FixedOff > Offset) Offset = FixedOff; + } + + // First assign frame offsets to stack objects that are used to spill + // callee saved registers. + if (StackGrowsDown) { + for (unsigned i = MinCSFrameIndex; i <= MaxCSFrameIndex; ++i) { + // If stack grows down, we need to add size of find the lowest + // address of the object. + Offset += FFI->getObjectSize(i); + + unsigned Align = FFI->getObjectAlignment(i); + // If the alignment of this object is greater than that of the stack, + // then increase the stack alignment to match. + MaxAlign = std::max(MaxAlign, Align); + // Adjust to alignment boundary + Offset = (Offset+Align-1)/Align*Align; + + FFI->setObjectOffset(i, -Offset); // Set the computed offset + } + } else { + int MaxCSFI = MaxCSFrameIndex, MinCSFI = MinCSFrameIndex; + for (int i = MaxCSFI; i >= MinCSFI ; --i) { + unsigned Align = FFI->getObjectAlignment(i); + // If the alignment of this object is greater than that of the stack, + // then increase the stack alignment to match. + MaxAlign = std::max(MaxAlign, Align); + // Adjust to alignment boundary + Offset = (Offset+Align-1)/Align*Align; + + FFI->setObjectOffset(i, Offset); + Offset += FFI->getObjectSize(i); + } + } + + // Make sure the special register scavenging spill slot is closest to the + // frame pointer if a frame pointer is required. + const TargetRegisterInfo *RegInfo = Fn.getTarget().getRegisterInfo(); + if (RS && RegInfo->hasFP(Fn) && !RegInfo->needsStackRealignment(Fn)) { + int SFI = RS->getScavengingFrameIndex(); + if (SFI >= 0) + AdjustStackOffset(FFI, SFI, StackGrowsDown, Offset, MaxAlign); + } + + // Make sure that the stack protector comes before the local variables on the + // stack. + if (FFI->getStackProtectorIndex() >= 0) + AdjustStackOffset(FFI, FFI->getStackProtectorIndex(), StackGrowsDown, + Offset, MaxAlign); + + // Then assign frame offsets to stack objects that are not used to spill + // callee saved registers. + for (unsigned i = 0, e = FFI->getObjectIndexEnd(); i != e; ++i) { + if (i >= MinCSFrameIndex && i <= MaxCSFrameIndex) + continue; + if (RS && (int)i == RS->getScavengingFrameIndex()) + continue; + if (FFI->isDeadObjectIndex(i)) + continue; + if (FFI->getStackProtectorIndex() == (int)i) + continue; + + AdjustStackOffset(FFI, i, StackGrowsDown, Offset, MaxAlign); + } + + // Make sure the special register scavenging spill slot is closest to the + // stack pointer. + if (RS && (!RegInfo->hasFP(Fn) || RegInfo->needsStackRealignment(Fn))) { + int SFI = RS->getScavengingFrameIndex(); + if (SFI >= 0) + AdjustStackOffset(FFI, SFI, StackGrowsDown, Offset, MaxAlign); + } + + if (!RegInfo->targetHandlesStackFrameRounding()) { + // If we have reserved argument space for call sites in the function + // immediately on entry to the current function, count it as part of the + // overall stack size. + if (FFI->hasCalls() && RegInfo->hasReservedCallFrame(Fn)) + Offset += FFI->getMaxCallFrameSize(); + + // Round up the size to a multiple of the alignment. If the function has + // any calls or alloca's, align to the target's StackAlignment value to + // ensure that the callee's frame or the alloca data is suitably aligned; + // otherwise, for leaf functions, align to the TransientStackAlignment + // value. + unsigned StackAlign; + if (FFI->hasCalls() || FFI->hasVarSizedObjects() || + (RegInfo->needsStackRealignment(Fn) && FFI->getObjectIndexEnd() != 0)) + StackAlign = TFI.getStackAlignment(); + else + StackAlign = TFI.getTransientStackAlignment(); + // If the frame pointer is eliminated, all frame offsets will be relative + // to SP not FP; align to MaxAlign so this works. + StackAlign = std::max(StackAlign, MaxAlign); + unsigned AlignMask = StackAlign - 1; + Offset = (Offset + AlignMask) & ~uint64_t(AlignMask); + } + + // Update frame info to pretend that this is part of the stack... + FFI->setStackSize(Offset - LocalAreaOffset); + + // Remember the required stack alignment in case targets need it to perform + // dynamic stack alignment. + if (MaxAlign > FFI->getMaxAlignment()) + FFI->setMaxAlignment(MaxAlign); +} + + +/// insertPrologEpilogCode - Scan the function for modified callee saved +/// registers, insert spill code for these callee saved registers, then add +/// prolog and epilog code to the function. +/// +void PEI::insertPrologEpilogCode(MachineFunction &Fn) { + const TargetRegisterInfo *TRI = Fn.getTarget().getRegisterInfo(); + + // Add prologue to the function... + TRI->emitPrologue(Fn); + + // Add epilogue to restore the callee-save registers in each exiting block + for (MachineFunction::iterator I = Fn.begin(), E = Fn.end(); I != E; ++I) { + // If last instruction is a return instruction, add an epilogue + if (!I->empty() && I->back().getDesc().isReturn()) + TRI->emitEpilogue(Fn, *I); + } +} + + +/// replaceFrameIndices - Replace all MO_FrameIndex operands with physical +/// register references and actual offsets. +/// +void PEI::replaceFrameIndices(MachineFunction &Fn) { + if (!Fn.getFrameInfo()->hasStackObjects()) return; // Nothing to do? + + const TargetMachine &TM = Fn.getTarget(); + assert(TM.getRegisterInfo() && "TM::getRegisterInfo() must be implemented!"); + const TargetRegisterInfo &TRI = *TM.getRegisterInfo(); + const TargetFrameInfo *TFI = TM.getFrameInfo(); + bool StackGrowsDown = + TFI->getStackGrowthDirection() == TargetFrameInfo::StackGrowsDown; + int FrameSetupOpcode = TRI.getCallFrameSetupOpcode(); + int FrameDestroyOpcode = TRI.getCallFrameDestroyOpcode(); + + for (MachineFunction::iterator BB = Fn.begin(), + E = Fn.end(); BB != E; ++BB) { + int SPAdj = 0; // SP offset due to call frame setup / destroy. + if (RS && !FrameIndexVirtualScavenging) RS->enterBasicBlock(BB); + + for (MachineBasicBlock::iterator I = BB->begin(); I != BB->end(); ) { + + if (I->getOpcode() == FrameSetupOpcode || + I->getOpcode() == FrameDestroyOpcode) { + // Remember how much SP has been adjusted to create the call + // frame. + int Size = I->getOperand(0).getImm(); + + if ((!StackGrowsDown && I->getOpcode() == FrameSetupOpcode) || + (StackGrowsDown && I->getOpcode() == FrameDestroyOpcode)) + Size = -Size; + + SPAdj += Size; + + MachineBasicBlock::iterator PrevI = BB->end(); + if (I != BB->begin()) PrevI = prior(I); + TRI.eliminateCallFramePseudoInstr(Fn, *BB, I); + + // Visit the instructions created by eliminateCallFramePseudoInstr(). + if (PrevI == BB->end()) + I = BB->begin(); // The replaced instr was the first in the block. + else + I = next(PrevI); + continue; + } + + MachineInstr *MI = I; + bool DoIncr = true; + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) + if (MI->getOperand(i).isFI()) { + // Some instructions (e.g. inline asm instructions) can have + // multiple frame indices and/or cause eliminateFrameIndex + // to insert more than one instruction. We need the register + // scavenger to go through all of these instructions so that + // it can update its register information. We keep the + // iterator at the point before insertion so that we can + // revisit them in full. + bool AtBeginning = (I == BB->begin()); + if (!AtBeginning) --I; + + // If this instruction has a FrameIndex operand, we need to + // use that target machine register info object to eliminate + // it. + int Value; + unsigned VReg = + TRI.eliminateFrameIndex(MI, SPAdj, &Value, + FrameIndexVirtualScavenging ? NULL : RS); + if (VReg) { + assert (FrameIndexVirtualScavenging && + "Not scavenging, but virtual returned from " + "eliminateFrameIndex()!"); + FrameConstantRegMap[VReg] = FrameConstantEntry(Value, SPAdj); + } + + // Reset the iterator if we were at the beginning of the BB. + if (AtBeginning) { + I = BB->begin(); + DoIncr = false; + } + + MI = 0; + break; + } + + if (DoIncr && I != BB->end()) ++I; + + // Update register states. + if (RS && !FrameIndexVirtualScavenging && MI) RS->forward(MI); + } + + assert(SPAdj == 0 && "Unbalanced call frame setup / destroy pairs?"); + } +} + +/// findLastUseReg - find the killing use of the specified register within +/// the instruciton range. Return the operand number of the kill in Operand. +static MachineBasicBlock::iterator +findLastUseReg(MachineBasicBlock::iterator I, MachineBasicBlock::iterator ME, + unsigned Reg) { + // Scan forward to find the last use of this virtual register + for (++I; I != ME; ++I) { + MachineInstr *MI = I; + bool isDefInsn = false; + bool isKillInsn = false; + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) + if (MI->getOperand(i).isReg()) { + unsigned OpReg = MI->getOperand(i).getReg(); + if (OpReg == 0 || !TargetRegisterInfo::isVirtualRegister(OpReg)) + continue; + assert (OpReg == Reg + && "overlapping use of scavenged index register!"); + // If this is the killing use, we have a candidate. + if (MI->getOperand(i).isKill()) + isKillInsn = true; + else if (MI->getOperand(i).isDef()) + isDefInsn = true; + } + if (isKillInsn && !isDefInsn) + return I; + } + // If we hit the end of the basic block, there was no kill of + // the virtual register, which is wrong. + assert (0 && "scavenged index register never killed!"); + return ME; +} + +/// scavengeFrameVirtualRegs - Replace all frame index virtual registers +/// with physical registers. Use the register scavenger to find an +/// appropriate register to use. +void PEI::scavengeFrameVirtualRegs(MachineFunction &Fn) { + // Run through the instructions and find any virtual registers. + for (MachineFunction::iterator BB = Fn.begin(), + E = Fn.end(); BB != E; ++BB) { + RS->enterBasicBlock(BB); + + // FIXME: The logic flow in this function is still too convoluted. + // It needs a cleanup refactoring. Do that in preparation for tracking + // more than one scratch register value and using ranges to find + // available scratch registers. + unsigned CurrentVirtReg = 0; + unsigned CurrentScratchReg = 0; + bool havePrevValue = false; + int PrevValue = 0; + MachineInstr *PrevLastUseMI = NULL; + unsigned PrevLastUseOp = 0; + bool trackingCurrentValue = false; + int SPAdj = 0; + int Value = 0; + + // The instruction stream may change in the loop, so check BB->end() + // directly. + for (MachineBasicBlock::iterator I = BB->begin(); I != BB->end(); ) { + MachineInstr *MI = I; + bool isDefInsn = false; + bool isKillInsn = false; + bool clobbersScratchReg = false; + bool DoIncr = true; + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + if (MI->getOperand(i).isReg()) { + MachineOperand &MO = MI->getOperand(i); + unsigned Reg = MO.getReg(); + if (Reg == 0) + continue; + if (!TargetRegisterInfo::isVirtualRegister(Reg)) { + // If we have a previous scratch reg, check and see if anything + // here kills whatever value is in there. + if (Reg == CurrentScratchReg) { + if (MO.isUse()) { + // Two-address operands implicitly kill + if (MO.isKill() || MI->isRegTiedToDefOperand(i)) + clobbersScratchReg = true; + } else { + assert (MO.isDef()); + clobbersScratchReg = true; + } + } + continue; + } + // If this is a def, remember that this insn defines the value. + // This lets us properly consider insns which re-use the scratch + // register, such as r2 = sub r2, #imm, in the middle of the + // scratch range. + if (MO.isDef()) + isDefInsn = true; + + // Have we already allocated a scratch register for this virtual? + if (Reg != CurrentVirtReg) { + // When we first encounter a new virtual register, it + // must be a definition. + assert(MI->getOperand(i).isDef() && + "frame index virtual missing def!"); + // We can't have nested virtual register live ranges because + // there's only a guarantee of one scavenged register at a time. + assert (CurrentVirtReg == 0 && + "overlapping frame index virtual registers!"); + + // If the target gave us information about what's in the register, + // we can use that to re-use scratch regs. + DenseMap::iterator Entry = + FrameConstantRegMap.find(Reg); + trackingCurrentValue = Entry != FrameConstantRegMap.end(); + if (trackingCurrentValue) { + SPAdj = (*Entry).second.second; + Value = (*Entry).second.first; + } else + SPAdj = Value = 0; + + // If the scratch register from the last allocation is still + // available, see if the value matches. If it does, just re-use it. + if (trackingCurrentValue && havePrevValue && PrevValue == Value) { + // FIXME: This assumes that the instructions in the live range + // for the virtual register are exclusively for the purpose + // of populating the value in the register. That's reasonable + // for these frame index registers, but it's still a very, very + // strong assumption. rdar://7322732. Better would be to + // explicitly check each instruction in the range for references + // to the virtual register. Only delete those insns that + // touch the virtual register. + + // Find the last use of the new virtual register. Remove all + // instruction between here and there, and update the current + // instruction to reference the last use insn instead. + MachineBasicBlock::iterator LastUseMI = + findLastUseReg(I, BB->end(), Reg); + + // Remove all instructions up 'til the last use, since they're + // just calculating the value we already have. + BB->erase(I, LastUseMI); + MI = I = LastUseMI; + + // Extend the live range of the scratch register + PrevLastUseMI->getOperand(PrevLastUseOp).setIsKill(false); + RS->setUsed(CurrentScratchReg); + CurrentVirtReg = Reg; + + // We deleted the instruction we were scanning the operands of. + // Jump back to the instruction iterator loop. Don't increment + // past this instruction since we updated the iterator already. + DoIncr = false; + break; + } + + // Scavenge a new scratch register + CurrentVirtReg = Reg; + const TargetRegisterClass *RC = Fn.getRegInfo().getRegClass(Reg); + CurrentScratchReg = RS->FindUnusedReg(RC); + if (CurrentScratchReg == 0) + // No register is "free". Scavenge a register. + CurrentScratchReg = RS->scavengeRegister(RC, I, SPAdj); + + PrevValue = Value; + } + // replace this reference to the virtual register with the + // scratch register. + assert (CurrentScratchReg && "Missing scratch register!"); + MI->getOperand(i).setReg(CurrentScratchReg); + + if (MI->getOperand(i).isKill()) { + isKillInsn = true; + PrevLastUseOp = i; + PrevLastUseMI = MI; + } + } + } + // If this is the last use of the scratch, stop tracking it. The + // last use will be a kill operand in an instruction that does + // not also define the scratch register. + if (isKillInsn && !isDefInsn) { + CurrentVirtReg = 0; + havePrevValue = trackingCurrentValue; + } + // Similarly, notice if instruction clobbered the value in the + // register we're tracking for possible later reuse. This is noted + // above, but enforced here since the value is still live while we + // process the rest of the operands of the instruction. + if (clobbersScratchReg) { + havePrevValue = false; + CurrentScratchReg = 0; + } + if (DoIncr) { + RS->forward(I); + ++I; + } + } + } +} diff --git a/libclamav/c++/llvm/lib/CodeGen/PrologEpilogInserter.h b/libclamav/c++/llvm/lib/CodeGen/PrologEpilogInserter.h new file mode 100644 index 000000000..931f1eb23 --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/PrologEpilogInserter.h @@ -0,0 +1,181 @@ +//===-- PrologEpilogInserter.h - Prolog/Epilog code insertion -*- C++ -* --===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This pass is responsible for finalizing the functions frame layout, saving +// callee saved registers, and for emitting prolog & epilog code for the +// function. +// +// This pass must be run after register allocation. After this pass is +// executed, it is illegal to construct MO_FrameIndex operands. +// +// This pass also implements a shrink wrapping variant of prolog/epilog +// insertion. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_PEI_H +#define LLVM_CODEGEN_PEI_H + +#include "llvm/CodeGen/Passes.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineLoopInfo.h" +#include "llvm/ADT/SparseBitVector.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/Target/TargetRegisterInfo.h" + +namespace llvm { + class RegScavenger; + class MachineBasicBlock; + + class PEI : public MachineFunctionPass { + public: + static char ID; + PEI() : MachineFunctionPass(&ID) {} + + const char *getPassName() const { + return "Prolog/Epilog Insertion & Frame Finalization"; + } + + virtual void getAnalysisUsage(AnalysisUsage &AU) const; + + /// runOnMachineFunction - Insert prolog/epilog code and replace abstract + /// frame indexes with appropriate references. + /// + bool runOnMachineFunction(MachineFunction &Fn); + + private: + RegScavenger *RS; + + // MinCSFrameIndex, MaxCSFrameIndex - Keeps the range of callee saved + // stack frame indexes. + unsigned MinCSFrameIndex, MaxCSFrameIndex; + + // Analysis info for spill/restore placement. + // "CSR": "callee saved register". + + // CSRegSet contains indices into the Callee Saved Register Info + // vector built by calculateCalleeSavedRegisters() and accessed + // via MF.getFrameInfo()->getCalleeSavedInfo(). + typedef SparseBitVector<> CSRegSet; + + // CSRegBlockMap maps MachineBasicBlocks to sets of callee + // saved register indices. + typedef DenseMap CSRegBlockMap; + + // Set and maps for computing CSR spill/restore placement: + // used in function (UsedCSRegs) + // used in a basic block (CSRUsed) + // anticipatable in a basic block (Antic{In,Out}) + // available in a basic block (Avail{In,Out}) + // to be spilled at the entry to a basic block (CSRSave) + // to be restored at the end of a basic block (CSRRestore) + CSRegSet UsedCSRegs; + CSRegBlockMap CSRUsed; + CSRegBlockMap AnticIn, AnticOut; + CSRegBlockMap AvailIn, AvailOut; + CSRegBlockMap CSRSave; + CSRegBlockMap CSRRestore; + + // Entry and return blocks of the current function. + MachineBasicBlock* EntryBlock; + SmallVector ReturnBlocks; + + // Map of MBBs to top level MachineLoops. + DenseMap TLLoops; + + // Flag to control shrink wrapping per-function: + // may choose to skip shrink wrapping for certain + // functions. + bool ShrinkWrapThisFunction; + + // Flag to control whether to use the register scavenger to resolve + // frame index materialization registers. Set according to + // TRI->requiresFrameIndexScavenging() for the curren function. + bool FrameIndexVirtualScavenging; + + // When using the scavenger post-pass to resolve frame reference + // materialization registers, maintain a map of the registers to + // the constant value and SP adjustment associated with it. + typedef std::pair FrameConstantEntry; + DenseMap FrameConstantRegMap; + +#ifndef NDEBUG + // Machine function handle. + MachineFunction* MF; + + // Flag indicating that the current function + // has at least one "short" path in the machine + // CFG from the entry block to an exit block. + bool HasFastExitPath; +#endif + + bool calculateSets(MachineFunction &Fn); + bool calcAnticInOut(MachineBasicBlock* MBB); + bool calcAvailInOut(MachineBasicBlock* MBB); + void calculateAnticAvail(MachineFunction &Fn); + bool addUsesForMEMERegion(MachineBasicBlock* MBB, + SmallVector& blks); + bool addUsesForTopLevelLoops(SmallVector& blks); + bool calcSpillPlacements(MachineBasicBlock* MBB, + SmallVector &blks, + CSRegBlockMap &prevSpills); + bool calcRestorePlacements(MachineBasicBlock* MBB, + SmallVector &blks, + CSRegBlockMap &prevRestores); + void placeSpillsAndRestores(MachineFunction &Fn); + void placeCSRSpillsAndRestores(MachineFunction &Fn); + void calculateCallsInformation(MachineFunction &Fn); + void calculateCalleeSavedRegisters(MachineFunction &Fn); + void insertCSRSpillsAndRestores(MachineFunction &Fn); + void calculateFrameObjectOffsets(MachineFunction &Fn); + void replaceFrameIndices(MachineFunction &Fn); + void scavengeFrameVirtualRegs(MachineFunction &Fn); + void insertPrologEpilogCode(MachineFunction &Fn); + + // Initialize DFA sets, called before iterations. + void clearAnticAvailSets(); + // Clear all sets constructed by shrink wrapping. + void clearAllSets(); + + // Initialize all shrink wrapping data. + void initShrinkWrappingInfo(); + + // Convienences for dealing with machine loops. + MachineBasicBlock* getTopLevelLoopPreheader(MachineLoop* LP); + MachineLoop* getTopLevelLoopParent(MachineLoop *LP); + + // Propgate CSRs used in MBB to all MBBs of loop LP. + void propagateUsesAroundLoop(MachineBasicBlock* MBB, MachineLoop* LP); + + // Convenience for recognizing return blocks. + bool isReturnBlock(MachineBasicBlock* MBB); + +#ifndef NDEBUG + // Debugging methods. + + // Mark this function as having fast exit paths. + void findFastExitPath(); + + // Verify placement of spills/restores. + void verifySpillRestorePlacement(); + + std::string getBasicBlockName(const MachineBasicBlock* MBB); + std::string stringifyCSRegSet(const CSRegSet& s); + void dumpSet(const CSRegSet& s); + void dumpUsed(MachineBasicBlock* MBB); + void dumpAllUsed(); + void dumpSets(MachineBasicBlock* MBB); + void dumpSets1(MachineBasicBlock* MBB); + void dumpAllSets(); + void dumpSRSets(); +#endif + + }; +} // End llvm namespace +#endif diff --git a/libclamav/c++/llvm/lib/CodeGen/PseudoSourceValue.cpp b/libclamav/c++/llvm/lib/CodeGen/PseudoSourceValue.cpp new file mode 100644 index 000000000..7fb3e6e6d --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/PseudoSourceValue.cpp @@ -0,0 +1,115 @@ +//===-- llvm/CodeGen/PseudoSourceValue.cpp ----------------------*- 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 the PseudoSourceValue class. +// +//===----------------------------------------------------------------------===// + +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/PseudoSourceValue.h" +#include "llvm/DerivedTypes.h" +#include "llvm/LLVMContext.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/ManagedStatic.h" +#include "llvm/Support/raw_ostream.h" +#include +using namespace llvm; + +static ManagedStatic PSVs; + +const PseudoSourceValue *PseudoSourceValue::getStack() +{ return &(*PSVs)[0]; } +const PseudoSourceValue *PseudoSourceValue::getGOT() +{ return &(*PSVs)[1]; } +const PseudoSourceValue *PseudoSourceValue::getJumpTable() +{ return &(*PSVs)[2]; } +const PseudoSourceValue *PseudoSourceValue::getConstantPool() +{ return &(*PSVs)[3]; } + +static const char *const PSVNames[] = { + "Stack", + "GOT", + "JumpTable", + "ConstantPool" +}; + +// FIXME: THIS IS A HACK!!!! +// Eventually these should be uniqued on LLVMContext rather than in a managed +// static. For now, we can safely use the global context for the time being to +// squeak by. +PseudoSourceValue::PseudoSourceValue(enum ValueTy Subclass) : + Value(Type::getInt8PtrTy(getGlobalContext()), + Subclass) {} + +void PseudoSourceValue::printCustom(raw_ostream &O) const { + O << PSVNames[this - *PSVs]; +} + +static ManagedStatic > FSValues; + +const PseudoSourceValue *PseudoSourceValue::getFixedStack(int FI) { + const PseudoSourceValue *&V = (*FSValues)[FI]; + if (!V) + V = new FixedStackPseudoSourceValue(FI); + return V; +} + +bool PseudoSourceValue::isConstant(const MachineFrameInfo *) const { + if (this == getStack()) + return false; + if (this == getGOT() || + this == getConstantPool() || + this == getJumpTable()) + return true; + llvm_unreachable("Unknown PseudoSourceValue!"); + return false; +} + +bool PseudoSourceValue::isAliased(const MachineFrameInfo *MFI) const { + if (this == getStack() || + this == getGOT() || + this == getConstantPool() || + this == getJumpTable()) + return false; + llvm_unreachable("Unknown PseudoSourceValue!"); + return true; +} + +bool PseudoSourceValue::mayAlias(const MachineFrameInfo *MFI) const { + if (this == getGOT() || + this == getConstantPool() || + this == getJumpTable()) + return false; + return true; +} + +bool FixedStackPseudoSourceValue::isConstant(const MachineFrameInfo *MFI) const{ + return MFI && MFI->isImmutableObjectIndex(FI); +} + +bool FixedStackPseudoSourceValue::isAliased(const MachineFrameInfo *MFI) const { + // Negative frame indices are used for special things that don't + // appear in LLVM IR. Non-negative indices may be used for things + // like static allocas. + if (!MFI) + return FI >= 0; + // Spill slots should not alias others. + return !MFI->isFixedObjectIndex(FI) && !MFI->isSpillSlotObjectIndex(FI); +} + +bool FixedStackPseudoSourceValue::mayAlias(const MachineFrameInfo *MFI) const { + if (!MFI) + return true; + // Spill slots will not alias any LLVM IR value. + return !MFI->isSpillSlotObjectIndex(FI); +} + +void FixedStackPseudoSourceValue::printCustom(raw_ostream &OS) const { + OS << "FixedStack" << FI; +} diff --git a/libclamav/c++/llvm/lib/CodeGen/README.txt b/libclamav/c++/llvm/lib/CodeGen/README.txt new file mode 100644 index 000000000..b655dda41 --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/README.txt @@ -0,0 +1,199 @@ +//===---------------------------------------------------------------------===// + +Common register allocation / spilling problem: + + mul lr, r4, lr + str lr, [sp, #+52] + ldr lr, [r1, #+32] + sxth r3, r3 + ldr r4, [sp, #+52] + mla r4, r3, lr, r4 + +can be: + + mul lr, r4, lr + mov r4, lr + str lr, [sp, #+52] + ldr lr, [r1, #+32] + sxth r3, r3 + mla r4, r3, lr, r4 + +and then "merge" mul and mov: + + mul r4, r4, lr + str lr, [sp, #+52] + ldr lr, [r1, #+32] + sxth r3, r3 + mla r4, r3, lr, r4 + +It also increase the likelyhood the store may become dead. + +//===---------------------------------------------------------------------===// + +bb27 ... + ... + %reg1037 = ADDri %reg1039, 1 + %reg1038 = ADDrs %reg1032, %reg1039, %NOREG, 10 + Successors according to CFG: 0x8b03bf0 (#5) + +bb76 (0x8b03bf0, LLVM BB @0x8b032d0, ID#5): + Predecessors according to CFG: 0x8b0c5f0 (#3) 0x8b0a7c0 (#4) + %reg1039 = PHI %reg1070, mbb, %reg1037, mbb + +Note ADDri is not a two-address instruction. However, its result %reg1037 is an +operand of the PHI node in bb76 and its operand %reg1039 is the result of the +PHI node. We should treat it as a two-address code and make sure the ADDri is +scheduled after any node that reads %reg1039. + +//===---------------------------------------------------------------------===// + +Use local info (i.e. register scavenger) to assign it a free register to allow +reuse: + ldr r3, [sp, #+4] + add r3, r3, #3 + ldr r2, [sp, #+8] + add r2, r2, #2 + ldr r1, [sp, #+4] <== + add r1, r1, #1 + ldr r0, [sp, #+4] + add r0, r0, #2 + +//===---------------------------------------------------------------------===// + +LLVM aggressively lift CSE out of loop. Sometimes this can be negative side- +effects: + +R1 = X + 4 +R2 = X + 7 +R3 = X + 15 + +loop: +load [i + R1] +... +load [i + R2] +... +load [i + R3] + +Suppose there is high register pressure, R1, R2, R3, can be spilled. We need +to implement proper re-materialization to handle this: + +R1 = X + 4 +R2 = X + 7 +R3 = X + 15 + +loop: +R1 = X + 4 @ re-materialized +load [i + R1] +... +R2 = X + 7 @ re-materialized +load [i + R2] +... +R3 = X + 15 @ re-materialized +load [i + R3] + +Furthermore, with re-association, we can enable sharing: + +R1 = X + 4 +R2 = X + 7 +R3 = X + 15 + +loop: +T = i + X +load [T + 4] +... +load [T + 7] +... +load [T + 15] +//===---------------------------------------------------------------------===// + +It's not always a good idea to choose rematerialization over spilling. If all +the load / store instructions would be folded then spilling is cheaper because +it won't require new live intervals / registers. See 2003-05-31-LongShifts for +an example. + +//===---------------------------------------------------------------------===// + +With a copying garbage collector, derived pointers must not be retained across +collector safe points; the collector could move the objects and invalidate the +derived pointer. This is bad enough in the first place, but safe points can +crop up unpredictably. Consider: + + %array = load { i32, [0 x %obj] }** %array_addr + %nth_el = getelementptr { i32, [0 x %obj] }* %array, i32 0, i32 %n + %old = load %obj** %nth_el + %z = div i64 %x, %y + store %obj* %new, %obj** %nth_el + +If the i64 division is lowered to a libcall, then a safe point will (must) +appear for the call site. If a collection occurs, %array and %nth_el no longer +point into the correct object. + +The fix for this is to copy address calculations so that dependent pointers +are never live across safe point boundaries. But the loads cannot be copied +like this if there was an intervening store, so may be hard to get right. + +Only a concurrent mutator can trigger a collection at the libcall safe point. +So single-threaded programs do not have this requirement, even with a copying +collector. Still, LLVM optimizations would probably undo a front-end's careful +work. + +//===---------------------------------------------------------------------===// + +The ocaml frametable structure supports liveness information. It would be good +to support it. + +//===---------------------------------------------------------------------===// + +The FIXME in ComputeCommonTailLength in BranchFolding.cpp needs to be +revisited. The check is there to work around a misuse of directives in inline +assembly. + +//===---------------------------------------------------------------------===// + +It would be good to detect collector/target compatibility instead of silently +doing the wrong thing. + +//===---------------------------------------------------------------------===// + +It would be really nice to be able to write patterns in .td files for copies, +which would eliminate a bunch of explicit predicates on them (e.g. no side +effects). Once this is in place, it would be even better to have tblgen +synthesize the various copy insertion/inspection methods in TargetInstrInfo. + +//===---------------------------------------------------------------------===// + +Stack coloring improvments: + +1. Do proper LiveStackAnalysis on all stack objects including those which are + not spill slots. +2. Reorder objects to fill in gaps between objects. + e.g. 4, 1, , 4, 1, 1, 1, , 4 => 4, 1, 1, 1, 1, 4, 4 + +//===---------------------------------------------------------------------===// + +The scheduler should be able to sort nearby instructions by their address. For +example, in an expanded memset sequence it's not uncommon to see code like this: + + movl $0, 4(%rdi) + movl $0, 8(%rdi) + movl $0, 12(%rdi) + movl $0, 0(%rdi) + +Each of the stores is independent, and the scheduler is currently making an +arbitrary decision about the order. + +//===---------------------------------------------------------------------===// + +Another opportunitiy in this code is that the $0 could be moved to a register: + + movl $0, 4(%rdi) + movl $0, 8(%rdi) + movl $0, 12(%rdi) + movl $0, 0(%rdi) + +This would save substantial code size, especially for longer sequences like +this. It would be easy to have a rule telling isel to avoid matching MOV32mi +if the immediate has more than some fixed number of uses. It's more involved +to teach the register allocator how to do late folding to recover from +excessive register pressure. + diff --git a/libclamav/c++/llvm/lib/CodeGen/RegAllocLinearScan.cpp b/libclamav/c++/llvm/lib/CodeGen/RegAllocLinearScan.cpp new file mode 100644 index 000000000..4ff512932 --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/RegAllocLinearScan.cpp @@ -0,0 +1,1503 @@ +//===-- RegAllocLinearScan.cpp - Linear Scan register allocator -----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements a linear scan register allocator. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "regalloc" +#include "VirtRegMap.h" +#include "VirtRegRewriter.h" +#include "Spiller.h" +#include "llvm/Function.h" +#include "llvm/CodeGen/LiveIntervalAnalysis.h" +#include "llvm/CodeGen/LiveStackAnalysis.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/CodeGen/MachineLoopInfo.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/CodeGen/RegAllocRegistry.h" +#include "llvm/CodeGen/RegisterCoalescer.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetOptions.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/ADT/EquivalenceClasses.h" +#include "llvm/ADT/SmallSet.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +#include +#include +#include +#include +#include + +using namespace llvm; + +STATISTIC(NumIters , "Number of iterations performed"); +STATISTIC(NumBacktracks, "Number of times we had to backtrack"); +STATISTIC(NumCoalesce, "Number of copies coalesced"); +STATISTIC(NumDowngrade, "Number of registers downgraded"); + +static cl::opt +NewHeuristic("new-spilling-heuristic", + cl::desc("Use new spilling heuristic"), + cl::init(false), cl::Hidden); + +static cl::opt +PreSplitIntervals("pre-alloc-split", + cl::desc("Pre-register allocation live interval splitting"), + cl::init(false), cl::Hidden); + +static RegisterRegAlloc +linearscanRegAlloc("linearscan", "linear scan register allocator", + createLinearScanRegisterAllocator); + +namespace { + // When we allocate a register, add it to a fixed-size queue of + // registers to skip in subsequent allocations. This trades a small + // amount of register pressure and increased spills for flexibility in + // the post-pass scheduler. + // + // Note that in a the number of registers used for reloading spills + // will be one greater than the value of this option. + // + // One big limitation of this is that it doesn't differentiate between + // different register classes. So on x86-64, if there is xmm register + // pressure, it can caused fewer GPRs to be held in the queue. + static cl::opt + NumRecentlyUsedRegs("linearscan-skip-count", + cl::desc("Number of registers for linearscan to remember to skip."), + cl::init(0), + cl::Hidden); + + struct RALinScan : public MachineFunctionPass { + static char ID; + RALinScan() : MachineFunctionPass(&ID) { + // Initialize the queue to record recently-used registers. + if (NumRecentlyUsedRegs > 0) + RecentRegs.resize(NumRecentlyUsedRegs, 0); + RecentNext = RecentRegs.begin(); + } + + typedef std::pair IntervalPtr; + typedef SmallVector IntervalPtrs; + private: + /// RelatedRegClasses - This structure is built the first time a function is + /// compiled, and keeps track of which register classes have registers that + /// belong to multiple classes or have aliases that are in other classes. + EquivalenceClasses RelatedRegClasses; + DenseMap OneClassForEachPhysReg; + + // NextReloadMap - For each register in the map, it maps to the another + // register which is defined by a reload from the same stack slot and + // both reloads are in the same basic block. + DenseMap NextReloadMap; + + // DowngradedRegs - A set of registers which are being "downgraded", i.e. + // un-favored for allocation. + SmallSet DowngradedRegs; + + // DowngradeMap - A map from virtual registers to physical registers being + // downgraded for the virtual registers. + DenseMap DowngradeMap; + + MachineFunction* mf_; + MachineRegisterInfo* mri_; + const TargetMachine* tm_; + const TargetRegisterInfo* tri_; + const TargetInstrInfo* tii_; + BitVector allocatableRegs_; + LiveIntervals* li_; + LiveStacks* ls_; + const MachineLoopInfo *loopInfo; + + /// handled_ - Intervals are added to the handled_ set in the order of their + /// start value. This is uses for backtracking. + std::vector handled_; + + /// fixed_ - Intervals that correspond to machine registers. + /// + IntervalPtrs fixed_; + + /// active_ - Intervals that are currently being processed, and which have a + /// live range active for the current point. + IntervalPtrs active_; + + /// inactive_ - Intervals that are currently being processed, but which have + /// a hold at the current point. + IntervalPtrs inactive_; + + typedef std::priority_queue, + greater_ptr > IntervalHeap; + IntervalHeap unhandled_; + + /// regUse_ - Tracks register usage. + SmallVector regUse_; + SmallVector regUseBackUp_; + + /// vrm_ - Tracks register assignments. + VirtRegMap* vrm_; + + std::auto_ptr rewriter_; + + std::auto_ptr spiller_; + + // The queue of recently-used registers. + SmallVector RecentRegs; + SmallVector::iterator RecentNext; + + // Record that we just picked this register. + void recordRecentlyUsed(unsigned reg) { + assert(reg != 0 && "Recently used register is NOREG!"); + if (!RecentRegs.empty()) { + *RecentNext++ = reg; + if (RecentNext == RecentRegs.end()) + RecentNext = RecentRegs.begin(); + } + } + + public: + virtual const char* getPassName() const { + return "Linear Scan Register Allocator"; + } + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesCFG(); + AU.addRequired(); + AU.addPreserved(); + if (StrongPHIElim) + AU.addRequiredID(StrongPHIEliminationID); + // Make sure PassManager knows which analyses to make available + // to coalescing and which analyses coalescing invalidates. + AU.addRequiredTransitive(); + if (PreSplitIntervals) + AU.addRequiredID(PreAllocSplittingID); + AU.addRequired(); + AU.addPreserved(); + AU.addRequired(); + AU.addPreserved(); + AU.addRequired(); + AU.addPreserved(); + AU.addPreservedID(MachineDominatorsID); + MachineFunctionPass::getAnalysisUsage(AU); + } + + /// runOnMachineFunction - register allocate the whole function + bool runOnMachineFunction(MachineFunction&); + + // Determine if we skip this register due to its being recently used. + bool isRecentlyUsed(unsigned reg) const { + return std::find(RecentRegs.begin(), RecentRegs.end(), reg) != + RecentRegs.end(); + } + + private: + /// linearScan - the linear scan algorithm + void linearScan(); + + /// initIntervalSets - initialize the interval sets. + /// + void initIntervalSets(); + + /// processActiveIntervals - expire old intervals and move non-overlapping + /// ones to the inactive list. + void processActiveIntervals(SlotIndex CurPoint); + + /// processInactiveIntervals - expire old intervals and move overlapping + /// ones to the active list. + void processInactiveIntervals(SlotIndex CurPoint); + + /// hasNextReloadInterval - Return the next liveinterval that's being + /// defined by a reload from the same SS as the specified one. + LiveInterval *hasNextReloadInterval(LiveInterval *cur); + + /// DowngradeRegister - Downgrade a register for allocation. + void DowngradeRegister(LiveInterval *li, unsigned Reg); + + /// UpgradeRegister - Upgrade a register for allocation. + void UpgradeRegister(unsigned Reg); + + /// assignRegOrStackSlotAtInterval - assign a register if one + /// is available, or spill. + void assignRegOrStackSlotAtInterval(LiveInterval* cur); + + void updateSpillWeights(std::vector &Weights, + unsigned reg, float weight, + const TargetRegisterClass *RC); + + /// findIntervalsToSpill - Determine the intervals to spill for the + /// specified interval. It's passed the physical registers whose spill + /// weight is the lowest among all the registers whose live intervals + /// conflict with the interval. + void findIntervalsToSpill(LiveInterval *cur, + std::vector > &Candidates, + unsigned NumCands, + SmallVector &SpillIntervals); + + /// attemptTrivialCoalescing - If a simple interval is defined by a copy, + /// try allocate the definition the same register as the source register + /// if the register is not defined during live time of the interval. This + /// eliminate a copy. This is used to coalesce copies which were not + /// coalesced away before allocation either due to dest and src being in + /// different register classes or because the coalescer was overly + /// conservative. + unsigned attemptTrivialCoalescing(LiveInterval &cur, unsigned Reg); + + /// + /// Register usage / availability tracking helpers. + /// + + void initRegUses() { + regUse_.resize(tri_->getNumRegs(), 0); + regUseBackUp_.resize(tri_->getNumRegs(), 0); + } + + void finalizeRegUses() { +#ifndef NDEBUG + // Verify all the registers are "freed". + bool Error = false; + for (unsigned i = 0, e = tri_->getNumRegs(); i != e; ++i) { + if (regUse_[i] != 0) { + errs() << tri_->getName(i) << " is still in use!\n"; + Error = true; + } + } + if (Error) + llvm_unreachable(0); +#endif + regUse_.clear(); + regUseBackUp_.clear(); + } + + void addRegUse(unsigned physReg) { + assert(TargetRegisterInfo::isPhysicalRegister(physReg) && + "should be physical register!"); + ++regUse_[physReg]; + for (const unsigned* as = tri_->getAliasSet(physReg); *as; ++as) + ++regUse_[*as]; + } + + void delRegUse(unsigned physReg) { + assert(TargetRegisterInfo::isPhysicalRegister(physReg) && + "should be physical register!"); + assert(regUse_[physReg] != 0); + --regUse_[physReg]; + for (const unsigned* as = tri_->getAliasSet(physReg); *as; ++as) { + assert(regUse_[*as] != 0); + --regUse_[*as]; + } + } + + bool isRegAvail(unsigned physReg) const { + assert(TargetRegisterInfo::isPhysicalRegister(physReg) && + "should be physical register!"); + return regUse_[physReg] == 0; + } + + void backUpRegUses() { + regUseBackUp_ = regUse_; + } + + void restoreRegUses() { + regUse_ = regUseBackUp_; + } + + /// + /// Register handling helpers. + /// + + /// getFreePhysReg - return a free physical register for this virtual + /// register interval if we have one, otherwise return 0. + unsigned getFreePhysReg(LiveInterval* cur); + unsigned getFreePhysReg(LiveInterval* cur, + const TargetRegisterClass *RC, + unsigned MaxInactiveCount, + SmallVector &inactiveCounts, + bool SkipDGRegs); + + /// assignVirt2StackSlot - assigns this virtual register to a + /// stack slot. returns the stack slot + int assignVirt2StackSlot(unsigned virtReg); + + void ComputeRelatedRegClasses(); + + template + void printIntervals(const char* const str, ItTy i, ItTy e) const { + DEBUG({ + if (str) + errs() << str << " intervals:\n"; + + for (; i != e; ++i) { + errs() << "\t" << *i->first << " -> "; + + unsigned reg = i->first->reg; + if (TargetRegisterInfo::isVirtualRegister(reg)) + reg = vrm_->getPhys(reg); + + errs() << tri_->getName(reg) << '\n'; + } + }); + } + }; + char RALinScan::ID = 0; +} + +static RegisterPass +X("linearscan-regalloc", "Linear Scan Register Allocator"); + +void RALinScan::ComputeRelatedRegClasses() { + // First pass, add all reg classes to the union, and determine at least one + // reg class that each register is in. + bool HasAliases = false; + for (TargetRegisterInfo::regclass_iterator RCI = tri_->regclass_begin(), + E = tri_->regclass_end(); RCI != E; ++RCI) { + RelatedRegClasses.insert(*RCI); + for (TargetRegisterClass::iterator I = (*RCI)->begin(), E = (*RCI)->end(); + I != E; ++I) { + HasAliases = HasAliases || *tri_->getAliasSet(*I) != 0; + + const TargetRegisterClass *&PRC = OneClassForEachPhysReg[*I]; + if (PRC) { + // Already processed this register. Just make sure we know that + // multiple register classes share a register. + RelatedRegClasses.unionSets(PRC, *RCI); + } else { + PRC = *RCI; + } + } + } + + // Second pass, now that we know conservatively what register classes each reg + // belongs to, add info about aliases. We don't need to do this for targets + // without register aliases. + if (HasAliases) + for (DenseMap::iterator + I = OneClassForEachPhysReg.begin(), E = OneClassForEachPhysReg.end(); + I != E; ++I) + for (const unsigned *AS = tri_->getAliasSet(I->first); *AS; ++AS) + RelatedRegClasses.unionSets(I->second, OneClassForEachPhysReg[*AS]); +} + +/// attemptTrivialCoalescing - If a simple interval is defined by a copy, +/// try allocate the definition the same register as the source register +/// if the register is not defined during live time of the interval. This +/// eliminate a copy. This is used to coalesce copies which were not +/// coalesced away before allocation either due to dest and src being in +/// different register classes or because the coalescer was overly +/// conservative. +unsigned RALinScan::attemptTrivialCoalescing(LiveInterval &cur, unsigned Reg) { + unsigned Preference = vrm_->getRegAllocPref(cur.reg); + if ((Preference && Preference == Reg) || !cur.containsOneValue()) + return Reg; + + VNInfo *vni = cur.begin()->valno; + if ((vni->def == SlotIndex()) || + vni->isUnused() || !vni->isDefAccurate()) + return Reg; + MachineInstr *CopyMI = li_->getInstructionFromIndex(vni->def); + unsigned SrcReg, DstReg, SrcSubReg, DstSubReg, PhysReg; + if (!CopyMI || + !tii_->isMoveInstr(*CopyMI, SrcReg, DstReg, SrcSubReg, DstSubReg)) + return Reg; + PhysReg = SrcReg; + if (TargetRegisterInfo::isVirtualRegister(SrcReg)) { + if (!vrm_->isAssignedReg(SrcReg)) + return Reg; + PhysReg = vrm_->getPhys(SrcReg); + } + if (Reg == PhysReg) + return Reg; + + const TargetRegisterClass *RC = mri_->getRegClass(cur.reg); + if (!RC->contains(PhysReg)) + return Reg; + + // Try to coalesce. + if (!li_->conflictsWithPhysRegDef(cur, *vrm_, PhysReg)) { + DEBUG(errs() << "Coalescing: " << cur << " -> " << tri_->getName(PhysReg) + << '\n'); + vrm_->clearVirt(cur.reg); + vrm_->assignVirt2Phys(cur.reg, PhysReg); + + // Remove unnecessary kills since a copy does not clobber the register. + if (li_->hasInterval(SrcReg)) { + LiveInterval &SrcLI = li_->getInterval(SrcReg); + for (MachineRegisterInfo::use_iterator I = mri_->use_begin(cur.reg), + E = mri_->use_end(); I != E; ++I) { + MachineOperand &O = I.getOperand(); + if (!O.isKill()) + continue; + MachineInstr *MI = &*I; + if (SrcLI.liveAt(li_->getInstructionIndex(MI).getDefIndex())) + O.setIsKill(false); + } + } + + ++NumCoalesce; + return PhysReg; + } + + return Reg; +} + +bool RALinScan::runOnMachineFunction(MachineFunction &fn) { + mf_ = &fn; + mri_ = &fn.getRegInfo(); + tm_ = &fn.getTarget(); + tri_ = tm_->getRegisterInfo(); + tii_ = tm_->getInstrInfo(); + allocatableRegs_ = tri_->getAllocatableSet(fn); + li_ = &getAnalysis(); + ls_ = &getAnalysis(); + loopInfo = &getAnalysis(); + + // We don't run the coalescer here because we have no reason to + // interact with it. If the coalescer requires interaction, it + // won't do anything. If it doesn't require interaction, we assume + // it was run as a separate pass. + + // If this is the first function compiled, compute the related reg classes. + if (RelatedRegClasses.empty()) + ComputeRelatedRegClasses(); + + // Also resize register usage trackers. + initRegUses(); + + vrm_ = &getAnalysis(); + if (!rewriter_.get()) rewriter_.reset(createVirtRegRewriter()); + + spiller_.reset(createSpiller(mf_, li_, loopInfo, vrm_)); + + initIntervalSets(); + + linearScan(); + + // Rewrite spill code and update the PhysRegsUsed set. + rewriter_->runOnMachineFunction(*mf_, *vrm_, li_); + + assert(unhandled_.empty() && "Unhandled live intervals remain!"); + + finalizeRegUses(); + + fixed_.clear(); + active_.clear(); + inactive_.clear(); + handled_.clear(); + NextReloadMap.clear(); + DowngradedRegs.clear(); + DowngradeMap.clear(); + spiller_.reset(0); + + return true; +} + +/// initIntervalSets - initialize the interval sets. +/// +void RALinScan::initIntervalSets() +{ + assert(unhandled_.empty() && fixed_.empty() && + active_.empty() && inactive_.empty() && + "interval sets should be empty on initialization"); + + handled_.reserve(li_->getNumIntervals()); + + for (LiveIntervals::iterator i = li_->begin(), e = li_->end(); i != e; ++i) { + if (TargetRegisterInfo::isPhysicalRegister(i->second->reg)) { + if (!i->second->empty()) { + mri_->setPhysRegUsed(i->second->reg); + fixed_.push_back(std::make_pair(i->second, i->second->begin())); + } + } else { + if (i->second->empty()) { + assignRegOrStackSlotAtInterval(i->second); + } + else + unhandled_.push(i->second); + } + } +} + +void RALinScan::linearScan() { + // linear scan algorithm + DEBUG({ + errs() << "********** LINEAR SCAN **********\n" + << "********** Function: " + << mf_->getFunction()->getName() << '\n'; + printIntervals("fixed", fixed_.begin(), fixed_.end()); + }); + + while (!unhandled_.empty()) { + // pick the interval with the earliest start point + LiveInterval* cur = unhandled_.top(); + unhandled_.pop(); + ++NumIters; + DEBUG(errs() << "\n*** CURRENT ***: " << *cur << '\n'); + + assert(!cur->empty() && "Empty interval in unhandled set."); + + processActiveIntervals(cur->beginIndex()); + processInactiveIntervals(cur->beginIndex()); + + assert(TargetRegisterInfo::isVirtualRegister(cur->reg) && + "Can only allocate virtual registers!"); + + // Allocating a virtual register. try to find a free + // physical register or spill an interval (possibly this one) in order to + // assign it one. + assignRegOrStackSlotAtInterval(cur); + + DEBUG({ + printIntervals("active", active_.begin(), active_.end()); + printIntervals("inactive", inactive_.begin(), inactive_.end()); + }); + } + + // Expire any remaining active intervals + while (!active_.empty()) { + IntervalPtr &IP = active_.back(); + unsigned reg = IP.first->reg; + DEBUG(errs() << "\tinterval " << *IP.first << " expired\n"); + assert(TargetRegisterInfo::isVirtualRegister(reg) && + "Can only allocate virtual registers!"); + reg = vrm_->getPhys(reg); + delRegUse(reg); + active_.pop_back(); + } + + // Expire any remaining inactive intervals + DEBUG({ + for (IntervalPtrs::reverse_iterator + i = inactive_.rbegin(); i != inactive_.rend(); ++i) + errs() << "\tinterval " << *i->first << " expired\n"; + }); + inactive_.clear(); + + // Add live-ins to every BB except for entry. Also perform trivial coalescing. + MachineFunction::iterator EntryMBB = mf_->begin(); + SmallVector LiveInMBBs; + for (LiveIntervals::iterator i = li_->begin(), e = li_->end(); i != e; ++i) { + LiveInterval &cur = *i->second; + unsigned Reg = 0; + bool isPhys = TargetRegisterInfo::isPhysicalRegister(cur.reg); + if (isPhys) + Reg = cur.reg; + else if (vrm_->isAssignedReg(cur.reg)) + Reg = attemptTrivialCoalescing(cur, vrm_->getPhys(cur.reg)); + if (!Reg) + continue; + // Ignore splited live intervals. + if (!isPhys && vrm_->getPreSplitReg(cur.reg)) + continue; + + for (LiveInterval::Ranges::const_iterator I = cur.begin(), E = cur.end(); + I != E; ++I) { + const LiveRange &LR = *I; + if (li_->findLiveInMBBs(LR.start, LR.end, LiveInMBBs)) { + for (unsigned i = 0, e = LiveInMBBs.size(); i != e; ++i) + if (LiveInMBBs[i] != EntryMBB) { + assert(TargetRegisterInfo::isPhysicalRegister(Reg) && + "Adding a virtual register to livein set?"); + LiveInMBBs[i]->addLiveIn(Reg); + } + LiveInMBBs.clear(); + } + } + } + + DEBUG(errs() << *vrm_); + + // Look for physical registers that end up not being allocated even though + // register allocator had to spill other registers in its register class. + if (ls_->getNumIntervals() == 0) + return; + if (!vrm_->FindUnusedRegisters(li_)) + return; +} + +/// processActiveIntervals - expire old intervals and move non-overlapping ones +/// to the inactive list. +void RALinScan::processActiveIntervals(SlotIndex CurPoint) +{ + DEBUG(errs() << "\tprocessing active intervals:\n"); + + for (unsigned i = 0, e = active_.size(); i != e; ++i) { + LiveInterval *Interval = active_[i].first; + LiveInterval::iterator IntervalPos = active_[i].second; + unsigned reg = Interval->reg; + + IntervalPos = Interval->advanceTo(IntervalPos, CurPoint); + + if (IntervalPos == Interval->end()) { // Remove expired intervals. + DEBUG(errs() << "\t\tinterval " << *Interval << " expired\n"); + assert(TargetRegisterInfo::isVirtualRegister(reg) && + "Can only allocate virtual registers!"); + reg = vrm_->getPhys(reg); + delRegUse(reg); + + // Pop off the end of the list. + active_[i] = active_.back(); + active_.pop_back(); + --i; --e; + + } else if (IntervalPos->start > CurPoint) { + // Move inactive intervals to inactive list. + DEBUG(errs() << "\t\tinterval " << *Interval << " inactive\n"); + assert(TargetRegisterInfo::isVirtualRegister(reg) && + "Can only allocate virtual registers!"); + reg = vrm_->getPhys(reg); + delRegUse(reg); + // add to inactive. + inactive_.push_back(std::make_pair(Interval, IntervalPos)); + + // Pop off the end of the list. + active_[i] = active_.back(); + active_.pop_back(); + --i; --e; + } else { + // Otherwise, just update the iterator position. + active_[i].second = IntervalPos; + } + } +} + +/// processInactiveIntervals - expire old intervals and move overlapping +/// ones to the active list. +void RALinScan::processInactiveIntervals(SlotIndex CurPoint) +{ + DEBUG(errs() << "\tprocessing inactive intervals:\n"); + + for (unsigned i = 0, e = inactive_.size(); i != e; ++i) { + LiveInterval *Interval = inactive_[i].first; + LiveInterval::iterator IntervalPos = inactive_[i].second; + unsigned reg = Interval->reg; + + IntervalPos = Interval->advanceTo(IntervalPos, CurPoint); + + if (IntervalPos == Interval->end()) { // remove expired intervals. + DEBUG(errs() << "\t\tinterval " << *Interval << " expired\n"); + + // Pop off the end of the list. + inactive_[i] = inactive_.back(); + inactive_.pop_back(); + --i; --e; + } else if (IntervalPos->start <= CurPoint) { + // move re-activated intervals in active list + DEBUG(errs() << "\t\tinterval " << *Interval << " active\n"); + assert(TargetRegisterInfo::isVirtualRegister(reg) && + "Can only allocate virtual registers!"); + reg = vrm_->getPhys(reg); + addRegUse(reg); + // add to active + active_.push_back(std::make_pair(Interval, IntervalPos)); + + // Pop off the end of the list. + inactive_[i] = inactive_.back(); + inactive_.pop_back(); + --i; --e; + } else { + // Otherwise, just update the iterator position. + inactive_[i].second = IntervalPos; + } + } +} + +/// updateSpillWeights - updates the spill weights of the specifed physical +/// register and its weight. +void RALinScan::updateSpillWeights(std::vector &Weights, + unsigned reg, float weight, + const TargetRegisterClass *RC) { + SmallSet Processed; + SmallSet SuperAdded; + SmallVector Supers; + Weights[reg] += weight; + Processed.insert(reg); + for (const unsigned* as = tri_->getAliasSet(reg); *as; ++as) { + Weights[*as] += weight; + Processed.insert(*as); + if (tri_->isSubRegister(*as, reg) && + SuperAdded.insert(*as) && + RC->contains(*as)) { + Supers.push_back(*as); + } + } + + // If the alias is a super-register, and the super-register is in the + // register class we are trying to allocate. Then add the weight to all + // sub-registers of the super-register even if they are not aliases. + // e.g. allocating for GR32, bh is not used, updating bl spill weight. + // bl should get the same spill weight otherwise it will be choosen + // as a spill candidate since spilling bh doesn't make ebx available. + for (unsigned i = 0, e = Supers.size(); i != e; ++i) { + for (const unsigned *sr = tri_->getSubRegisters(Supers[i]); *sr; ++sr) + if (!Processed.count(*sr)) + Weights[*sr] += weight; + } +} + +static +RALinScan::IntervalPtrs::iterator +FindIntervalInVector(RALinScan::IntervalPtrs &IP, LiveInterval *LI) { + for (RALinScan::IntervalPtrs::iterator I = IP.begin(), E = IP.end(); + I != E; ++I) + if (I->first == LI) return I; + return IP.end(); +} + +static void RevertVectorIteratorsTo(RALinScan::IntervalPtrs &V, SlotIndex Point){ + for (unsigned i = 0, e = V.size(); i != e; ++i) { + RALinScan::IntervalPtr &IP = V[i]; + LiveInterval::iterator I = std::upper_bound(IP.first->begin(), + IP.second, Point); + if (I != IP.first->begin()) --I; + IP.second = I; + } +} + +/// addStackInterval - Create a LiveInterval for stack if the specified live +/// interval has been spilled. +static void addStackInterval(LiveInterval *cur, LiveStacks *ls_, + LiveIntervals *li_, + MachineRegisterInfo* mri_, VirtRegMap &vrm_) { + int SS = vrm_.getStackSlot(cur->reg); + if (SS == VirtRegMap::NO_STACK_SLOT) + return; + + const TargetRegisterClass *RC = mri_->getRegClass(cur->reg); + LiveInterval &SI = ls_->getOrCreateInterval(SS, RC); + + VNInfo *VNI; + if (SI.hasAtLeastOneValue()) + VNI = SI.getValNumInfo(0); + else + VNI = SI.getNextValue(SlotIndex(), 0, false, + ls_->getVNInfoAllocator()); + + LiveInterval &RI = li_->getInterval(cur->reg); + // FIXME: This may be overly conservative. + SI.MergeRangesInAsValue(RI, VNI); +} + +/// getConflictWeight - Return the number of conflicts between cur +/// live interval and defs and uses of Reg weighted by loop depthes. +static +float getConflictWeight(LiveInterval *cur, unsigned Reg, LiveIntervals *li_, + MachineRegisterInfo *mri_, + const MachineLoopInfo *loopInfo) { + float Conflicts = 0; + for (MachineRegisterInfo::reg_iterator I = mri_->reg_begin(Reg), + E = mri_->reg_end(); I != E; ++I) { + MachineInstr *MI = &*I; + if (cur->liveAt(li_->getInstructionIndex(MI))) { + unsigned loopDepth = loopInfo->getLoopDepth(MI->getParent()); + Conflicts += powf(10.0f, (float)loopDepth); + } + } + return Conflicts; +} + +/// findIntervalsToSpill - Determine the intervals to spill for the +/// specified interval. It's passed the physical registers whose spill +/// weight is the lowest among all the registers whose live intervals +/// conflict with the interval. +void RALinScan::findIntervalsToSpill(LiveInterval *cur, + std::vector > &Candidates, + unsigned NumCands, + SmallVector &SpillIntervals) { + // We have figured out the *best* register to spill. But there are other + // registers that are pretty good as well (spill weight within 3%). Spill + // the one that has fewest defs and uses that conflict with cur. + float Conflicts[3] = { 0.0f, 0.0f, 0.0f }; + SmallVector SLIs[3]; + + DEBUG({ + errs() << "\tConsidering " << NumCands << " candidates: "; + for (unsigned i = 0; i != NumCands; ++i) + errs() << tri_->getName(Candidates[i].first) << " "; + errs() << "\n"; + }); + + // Calculate the number of conflicts of each candidate. + for (IntervalPtrs::iterator i = active_.begin(); i != active_.end(); ++i) { + unsigned Reg = i->first->reg; + unsigned PhysReg = vrm_->getPhys(Reg); + if (!cur->overlapsFrom(*i->first, i->second)) + continue; + for (unsigned j = 0; j < NumCands; ++j) { + unsigned Candidate = Candidates[j].first; + if (tri_->regsOverlap(PhysReg, Candidate)) { + if (NumCands > 1) + Conflicts[j] += getConflictWeight(cur, Reg, li_, mri_, loopInfo); + SLIs[j].push_back(i->first); + } + } + } + + for (IntervalPtrs::iterator i = inactive_.begin(); i != inactive_.end(); ++i){ + unsigned Reg = i->first->reg; + unsigned PhysReg = vrm_->getPhys(Reg); + if (!cur->overlapsFrom(*i->first, i->second-1)) + continue; + for (unsigned j = 0; j < NumCands; ++j) { + unsigned Candidate = Candidates[j].first; + if (tri_->regsOverlap(PhysReg, Candidate)) { + if (NumCands > 1) + Conflicts[j] += getConflictWeight(cur, Reg, li_, mri_, loopInfo); + SLIs[j].push_back(i->first); + } + } + } + + // Which is the best candidate? + unsigned BestCandidate = 0; + float MinConflicts = Conflicts[0]; + for (unsigned i = 1; i != NumCands; ++i) { + if (Conflicts[i] < MinConflicts) { + BestCandidate = i; + MinConflicts = Conflicts[i]; + } + } + + std::copy(SLIs[BestCandidate].begin(), SLIs[BestCandidate].end(), + std::back_inserter(SpillIntervals)); +} + +namespace { + struct WeightCompare { + private: + const RALinScan &Allocator; + + public: + WeightCompare(const RALinScan &Alloc) : Allocator(Alloc) {}; + + typedef std::pair RegWeightPair; + bool operator()(const RegWeightPair &LHS, const RegWeightPair &RHS) const { + return LHS.second < RHS.second && !Allocator.isRecentlyUsed(LHS.first); + } + }; +} + +static bool weightsAreClose(float w1, float w2) { + if (!NewHeuristic) + return false; + + float diff = w1 - w2; + if (diff <= 0.02f) // Within 0.02f + return true; + return (diff / w2) <= 0.05f; // Within 5%. +} + +LiveInterval *RALinScan::hasNextReloadInterval(LiveInterval *cur) { + DenseMap::iterator I = NextReloadMap.find(cur->reg); + if (I == NextReloadMap.end()) + return 0; + return &li_->getInterval(I->second); +} + +void RALinScan::DowngradeRegister(LiveInterval *li, unsigned Reg) { + bool isNew = DowngradedRegs.insert(Reg); + isNew = isNew; // Silence compiler warning. + assert(isNew && "Multiple reloads holding the same register?"); + DowngradeMap.insert(std::make_pair(li->reg, Reg)); + for (const unsigned *AS = tri_->getAliasSet(Reg); *AS; ++AS) { + isNew = DowngradedRegs.insert(*AS); + isNew = isNew; // Silence compiler warning. + assert(isNew && "Multiple reloads holding the same register?"); + DowngradeMap.insert(std::make_pair(li->reg, *AS)); + } + ++NumDowngrade; +} + +void RALinScan::UpgradeRegister(unsigned Reg) { + if (Reg) { + DowngradedRegs.erase(Reg); + for (const unsigned *AS = tri_->getAliasSet(Reg); *AS; ++AS) + DowngradedRegs.erase(*AS); + } +} + +namespace { + struct LISorter { + bool operator()(LiveInterval* A, LiveInterval* B) { + return A->beginIndex() < B->beginIndex(); + } + }; +} + +/// assignRegOrStackSlotAtInterval - assign a register if one is available, or +/// spill. +void RALinScan::assignRegOrStackSlotAtInterval(LiveInterval* cur) { + DEBUG(errs() << "\tallocating current interval: "); + + // This is an implicitly defined live interval, just assign any register. + const TargetRegisterClass *RC = mri_->getRegClass(cur->reg); + if (cur->empty()) { + unsigned physReg = vrm_->getRegAllocPref(cur->reg); + if (!physReg) + physReg = *RC->allocation_order_begin(*mf_); + DEBUG(errs() << tri_->getName(physReg) << '\n'); + // Note the register is not really in use. + vrm_->assignVirt2Phys(cur->reg, physReg); + return; + } + + backUpRegUses(); + + std::vector > SpillWeightsToAdd; + SlotIndex StartPosition = cur->beginIndex(); + const TargetRegisterClass *RCLeader = RelatedRegClasses.getLeaderValue(RC); + + // If start of this live interval is defined by a move instruction and its + // source is assigned a physical register that is compatible with the target + // register class, then we should try to assign it the same register. + // This can happen when the move is from a larger register class to a smaller + // one, e.g. X86::mov32to32_. These move instructions are not coalescable. + if (!vrm_->getRegAllocPref(cur->reg) && cur->hasAtLeastOneValue()) { + VNInfo *vni = cur->begin()->valno; + if ((vni->def != SlotIndex()) && !vni->isUnused() && + vni->isDefAccurate()) { + MachineInstr *CopyMI = li_->getInstructionFromIndex(vni->def); + unsigned SrcReg, DstReg, SrcSubReg, DstSubReg; + if (CopyMI && + tii_->isMoveInstr(*CopyMI, SrcReg, DstReg, SrcSubReg, DstSubReg)) { + unsigned Reg = 0; + if (TargetRegisterInfo::isPhysicalRegister(SrcReg)) + Reg = SrcReg; + else if (vrm_->isAssignedReg(SrcReg)) + Reg = vrm_->getPhys(SrcReg); + if (Reg) { + if (SrcSubReg) + Reg = tri_->getSubReg(Reg, SrcSubReg); + if (DstSubReg) + Reg = tri_->getMatchingSuperReg(Reg, DstSubReg, RC); + if (Reg && allocatableRegs_[Reg] && RC->contains(Reg)) + mri_->setRegAllocationHint(cur->reg, 0, Reg); + } + } + } + } + + // For every interval in inactive we overlap with, mark the + // register as not free and update spill weights. + for (IntervalPtrs::const_iterator i = inactive_.begin(), + e = inactive_.end(); i != e; ++i) { + unsigned Reg = i->first->reg; + assert(TargetRegisterInfo::isVirtualRegister(Reg) && + "Can only allocate virtual registers!"); + const TargetRegisterClass *RegRC = mri_->getRegClass(Reg); + // If this is not in a related reg class to the register we're allocating, + // don't check it. + if (RelatedRegClasses.getLeaderValue(RegRC) == RCLeader && + cur->overlapsFrom(*i->first, i->second-1)) { + Reg = vrm_->getPhys(Reg); + addRegUse(Reg); + SpillWeightsToAdd.push_back(std::make_pair(Reg, i->first->weight)); + } + } + + // Speculatively check to see if we can get a register right now. If not, + // we know we won't be able to by adding more constraints. If so, we can + // check to see if it is valid. Doing an exhaustive search of the fixed_ list + // is very bad (it contains all callee clobbered registers for any functions + // with a call), so we want to avoid doing that if possible. + unsigned physReg = getFreePhysReg(cur); + unsigned BestPhysReg = physReg; + if (physReg) { + // We got a register. However, if it's in the fixed_ list, we might + // conflict with it. Check to see if we conflict with it or any of its + // aliases. + SmallSet RegAliases; + for (const unsigned *AS = tri_->getAliasSet(physReg); *AS; ++AS) + RegAliases.insert(*AS); + + bool ConflictsWithFixed = false; + for (unsigned i = 0, e = fixed_.size(); i != e; ++i) { + IntervalPtr &IP = fixed_[i]; + if (physReg == IP.first->reg || RegAliases.count(IP.first->reg)) { + // Okay, this reg is on the fixed list. Check to see if we actually + // conflict. + LiveInterval *I = IP.first; + if (I->endIndex() > StartPosition) { + LiveInterval::iterator II = I->advanceTo(IP.second, StartPosition); + IP.second = II; + if (II != I->begin() && II->start > StartPosition) + --II; + if (cur->overlapsFrom(*I, II)) { + ConflictsWithFixed = true; + break; + } + } + } + } + + // Okay, the register picked by our speculative getFreePhysReg call turned + // out to be in use. Actually add all of the conflicting fixed registers to + // regUse_ so we can do an accurate query. + if (ConflictsWithFixed) { + // For every interval in fixed we overlap with, mark the register as not + // free and update spill weights. + for (unsigned i = 0, e = fixed_.size(); i != e; ++i) { + IntervalPtr &IP = fixed_[i]; + LiveInterval *I = IP.first; + + const TargetRegisterClass *RegRC = OneClassForEachPhysReg[I->reg]; + if (RelatedRegClasses.getLeaderValue(RegRC) == RCLeader && + I->endIndex() > StartPosition) { + LiveInterval::iterator II = I->advanceTo(IP.second, StartPosition); + IP.second = II; + if (II != I->begin() && II->start > StartPosition) + --II; + if (cur->overlapsFrom(*I, II)) { + unsigned reg = I->reg; + addRegUse(reg); + SpillWeightsToAdd.push_back(std::make_pair(reg, I->weight)); + } + } + } + + // Using the newly updated regUse_ object, which includes conflicts in the + // future, see if there are any registers available. + physReg = getFreePhysReg(cur); + } + } + + // Restore the physical register tracker, removing information about the + // future. + restoreRegUses(); + + // If we find a free register, we are done: assign this virtual to + // the free physical register and add this interval to the active + // list. + if (physReg) { + DEBUG(errs() << tri_->getName(physReg) << '\n'); + vrm_->assignVirt2Phys(cur->reg, physReg); + addRegUse(physReg); + active_.push_back(std::make_pair(cur, cur->begin())); + handled_.push_back(cur); + + // "Upgrade" the physical register since it has been allocated. + UpgradeRegister(physReg); + if (LiveInterval *NextReloadLI = hasNextReloadInterval(cur)) { + // "Downgrade" physReg to try to keep physReg from being allocated until + // the next reload from the same SS is allocated. + mri_->setRegAllocationHint(NextReloadLI->reg, 0, physReg); + DowngradeRegister(cur, physReg); + } + return; + } + DEBUG(errs() << "no free registers\n"); + + // Compile the spill weights into an array that is better for scanning. + std::vector SpillWeights(tri_->getNumRegs(), 0.0f); + for (std::vector >::iterator + I = SpillWeightsToAdd.begin(), E = SpillWeightsToAdd.end(); I != E; ++I) + updateSpillWeights(SpillWeights, I->first, I->second, RC); + + // for each interval in active, update spill weights. + for (IntervalPtrs::const_iterator i = active_.begin(), e = active_.end(); + i != e; ++i) { + unsigned reg = i->first->reg; + assert(TargetRegisterInfo::isVirtualRegister(reg) && + "Can only allocate virtual registers!"); + reg = vrm_->getPhys(reg); + updateSpillWeights(SpillWeights, reg, i->first->weight, RC); + } + + DEBUG(errs() << "\tassigning stack slot at interval "<< *cur << ":\n"); + + // Find a register to spill. + float minWeight = HUGE_VALF; + unsigned minReg = 0; + + bool Found = false; + std::vector > RegsWeights; + if (!minReg || SpillWeights[minReg] == HUGE_VALF) + for (TargetRegisterClass::iterator i = RC->allocation_order_begin(*mf_), + e = RC->allocation_order_end(*mf_); i != e; ++i) { + unsigned reg = *i; + float regWeight = SpillWeights[reg]; + // Skip recently allocated registers. + if (minWeight > regWeight && !isRecentlyUsed(reg)) + Found = true; + RegsWeights.push_back(std::make_pair(reg, regWeight)); + } + + // If we didn't find a register that is spillable, try aliases? + if (!Found) { + for (TargetRegisterClass::iterator i = RC->allocation_order_begin(*mf_), + e = RC->allocation_order_end(*mf_); i != e; ++i) { + unsigned reg = *i; + // No need to worry about if the alias register size < regsize of RC. + // We are going to spill all registers that alias it anyway. + for (const unsigned* as = tri_->getAliasSet(reg); *as; ++as) + RegsWeights.push_back(std::make_pair(*as, SpillWeights[*as])); + } + } + + // Sort all potential spill candidates by weight. + std::sort(RegsWeights.begin(), RegsWeights.end(), WeightCompare(*this)); + minReg = RegsWeights[0].first; + minWeight = RegsWeights[0].second; + if (minWeight == HUGE_VALF) { + // All registers must have inf weight. Just grab one! + minReg = BestPhysReg ? BestPhysReg : *RC->allocation_order_begin(*mf_); + if (cur->weight == HUGE_VALF || + li_->getApproximateInstructionCount(*cur) == 0) { + // Spill a physical register around defs and uses. + if (li_->spillPhysRegAroundRegDefsUses(*cur, minReg, *vrm_)) { + // spillPhysRegAroundRegDefsUses may have invalidated iterator stored + // in fixed_. Reset them. + for (unsigned i = 0, e = fixed_.size(); i != e; ++i) { + IntervalPtr &IP = fixed_[i]; + LiveInterval *I = IP.first; + if (I->reg == minReg || tri_->isSubRegister(minReg, I->reg)) + IP.second = I->advanceTo(I->begin(), StartPosition); + } + + DowngradedRegs.clear(); + assignRegOrStackSlotAtInterval(cur); + } else { + assert(false && "Ran out of registers during register allocation!"); + llvm_report_error("Ran out of registers during register allocation!"); + } + return; + } + } + + // Find up to 3 registers to consider as spill candidates. + unsigned LastCandidate = RegsWeights.size() >= 3 ? 3 : 1; + while (LastCandidate > 1) { + if (weightsAreClose(RegsWeights[LastCandidate-1].second, minWeight)) + break; + --LastCandidate; + } + + DEBUG({ + errs() << "\t\tregister(s) with min weight(s): "; + + for (unsigned i = 0; i != LastCandidate; ++i) + errs() << tri_->getName(RegsWeights[i].first) + << " (" << RegsWeights[i].second << ")\n"; + }); + + // If the current has the minimum weight, we need to spill it and + // add any added intervals back to unhandled, and restart + // linearscan. + if (cur->weight != HUGE_VALF && cur->weight <= minWeight) { + DEBUG(errs() << "\t\t\tspilling(c): " << *cur << '\n'); + SmallVector spillIs; + std::vector added; + + added = spiller_->spill(cur, spillIs); + + std::sort(added.begin(), added.end(), LISorter()); + addStackInterval(cur, ls_, li_, mri_, *vrm_); + if (added.empty()) + return; // Early exit if all spills were folded. + + // Merge added with unhandled. Note that we have already sorted + // intervals returned by addIntervalsForSpills by their starting + // point. + // This also update the NextReloadMap. That is, it adds mapping from a + // register defined by a reload from SS to the next reload from SS in the + // same basic block. + MachineBasicBlock *LastReloadMBB = 0; + LiveInterval *LastReload = 0; + int LastReloadSS = VirtRegMap::NO_STACK_SLOT; + for (unsigned i = 0, e = added.size(); i != e; ++i) { + LiveInterval *ReloadLi = added[i]; + if (ReloadLi->weight == HUGE_VALF && + li_->getApproximateInstructionCount(*ReloadLi) == 0) { + SlotIndex ReloadIdx = ReloadLi->beginIndex(); + MachineBasicBlock *ReloadMBB = li_->getMBBFromIndex(ReloadIdx); + int ReloadSS = vrm_->getStackSlot(ReloadLi->reg); + if (LastReloadMBB == ReloadMBB && LastReloadSS == ReloadSS) { + // Last reload of same SS is in the same MBB. We want to try to + // allocate both reloads the same register and make sure the reg + // isn't clobbered in between if at all possible. + assert(LastReload->beginIndex() < ReloadIdx); + NextReloadMap.insert(std::make_pair(LastReload->reg, ReloadLi->reg)); + } + LastReloadMBB = ReloadMBB; + LastReload = ReloadLi; + LastReloadSS = ReloadSS; + } + unhandled_.push(ReloadLi); + } + return; + } + + ++NumBacktracks; + + // Push the current interval back to unhandled since we are going + // to re-run at least this iteration. Since we didn't modify it it + // should go back right in the front of the list + unhandled_.push(cur); + + assert(TargetRegisterInfo::isPhysicalRegister(minReg) && + "did not choose a register to spill?"); + + // We spill all intervals aliasing the register with + // minimum weight, rollback to the interval with the earliest + // start point and let the linear scan algorithm run again + SmallVector spillIs; + + // Determine which intervals have to be spilled. + findIntervalsToSpill(cur, RegsWeights, LastCandidate, spillIs); + + // Set of spilled vregs (used later to rollback properly) + SmallSet spilled; + + // The earliest start of a Spilled interval indicates up to where + // in handled we need to roll back + + LiveInterval *earliestStartInterval = cur; + + // Spill live intervals of virtual regs mapped to the physical register we + // want to clear (and its aliases). We only spill those that overlap with the + // current interval as the rest do not affect its allocation. we also keep + // track of the earliest start of all spilled live intervals since this will + // mark our rollback point. + std::vector added; + while (!spillIs.empty()) { + LiveInterval *sli = spillIs.back(); + spillIs.pop_back(); + DEBUG(errs() << "\t\t\tspilling(a): " << *sli << '\n'); + earliestStartInterval = + (earliestStartInterval->beginIndex() < sli->beginIndex()) ? + earliestStartInterval : sli; + + std::vector newIs; + newIs = spiller_->spill(sli, spillIs); + addStackInterval(sli, ls_, li_, mri_, *vrm_); + std::copy(newIs.begin(), newIs.end(), std::back_inserter(added)); + spilled.insert(sli->reg); + } + + SlotIndex earliestStart = earliestStartInterval->beginIndex(); + + DEBUG(errs() << "\t\trolling back to: " << earliestStart << '\n'); + + // Scan handled in reverse order up to the earliest start of a + // spilled live interval and undo each one, restoring the state of + // unhandled. + while (!handled_.empty()) { + LiveInterval* i = handled_.back(); + // If this interval starts before t we are done. + if (i->beginIndex() < earliestStart) + break; + DEBUG(errs() << "\t\t\tundo changes for: " << *i << '\n'); + handled_.pop_back(); + + // When undoing a live interval allocation we must know if it is active or + // inactive to properly update regUse_ and the VirtRegMap. + IntervalPtrs::iterator it; + if ((it = FindIntervalInVector(active_, i)) != active_.end()) { + active_.erase(it); + assert(!TargetRegisterInfo::isPhysicalRegister(i->reg)); + if (!spilled.count(i->reg)) + unhandled_.push(i); + delRegUse(vrm_->getPhys(i->reg)); + vrm_->clearVirt(i->reg); + } else if ((it = FindIntervalInVector(inactive_, i)) != inactive_.end()) { + inactive_.erase(it); + assert(!TargetRegisterInfo::isPhysicalRegister(i->reg)); + if (!spilled.count(i->reg)) + unhandled_.push(i); + vrm_->clearVirt(i->reg); + } else { + assert(TargetRegisterInfo::isVirtualRegister(i->reg) && + "Can only allocate virtual registers!"); + vrm_->clearVirt(i->reg); + unhandled_.push(i); + } + + DenseMap::iterator ii = DowngradeMap.find(i->reg); + if (ii == DowngradeMap.end()) + // It interval has a preference, it must be defined by a copy. Clear the + // preference now since the source interval allocation may have been + // undone as well. + mri_->setRegAllocationHint(i->reg, 0, 0); + else { + UpgradeRegister(ii->second); + } + } + + // Rewind the iterators in the active, inactive, and fixed lists back to the + // point we reverted to. + RevertVectorIteratorsTo(active_, earliestStart); + RevertVectorIteratorsTo(inactive_, earliestStart); + RevertVectorIteratorsTo(fixed_, earliestStart); + + // Scan the rest and undo each interval that expired after t and + // insert it in active (the next iteration of the algorithm will + // put it in inactive if required) + for (unsigned i = 0, e = handled_.size(); i != e; ++i) { + LiveInterval *HI = handled_[i]; + if (!HI->expiredAt(earliestStart) && + HI->expiredAt(cur->beginIndex())) { + DEBUG(errs() << "\t\t\tundo changes for: " << *HI << '\n'); + active_.push_back(std::make_pair(HI, HI->begin())); + assert(!TargetRegisterInfo::isPhysicalRegister(HI->reg)); + addRegUse(vrm_->getPhys(HI->reg)); + } + } + + // Merge added with unhandled. + // This also update the NextReloadMap. That is, it adds mapping from a + // register defined by a reload from SS to the next reload from SS in the + // same basic block. + MachineBasicBlock *LastReloadMBB = 0; + LiveInterval *LastReload = 0; + int LastReloadSS = VirtRegMap::NO_STACK_SLOT; + std::sort(added.begin(), added.end(), LISorter()); + for (unsigned i = 0, e = added.size(); i != e; ++i) { + LiveInterval *ReloadLi = added[i]; + if (ReloadLi->weight == HUGE_VALF && + li_->getApproximateInstructionCount(*ReloadLi) == 0) { + SlotIndex ReloadIdx = ReloadLi->beginIndex(); + MachineBasicBlock *ReloadMBB = li_->getMBBFromIndex(ReloadIdx); + int ReloadSS = vrm_->getStackSlot(ReloadLi->reg); + if (LastReloadMBB == ReloadMBB && LastReloadSS == ReloadSS) { + // Last reload of same SS is in the same MBB. We want to try to + // allocate both reloads the same register and make sure the reg + // isn't clobbered in between if at all possible. + assert(LastReload->beginIndex() < ReloadIdx); + NextReloadMap.insert(std::make_pair(LastReload->reg, ReloadLi->reg)); + } + LastReloadMBB = ReloadMBB; + LastReload = ReloadLi; + LastReloadSS = ReloadSS; + } + unhandled_.push(ReloadLi); + } +} + +unsigned RALinScan::getFreePhysReg(LiveInterval* cur, + const TargetRegisterClass *RC, + unsigned MaxInactiveCount, + SmallVector &inactiveCounts, + bool SkipDGRegs) { + unsigned FreeReg = 0; + unsigned FreeRegInactiveCount = 0; + + std::pair Hint = mri_->getRegAllocationHint(cur->reg); + // Resolve second part of the hint (if possible) given the current allocation. + unsigned physReg = Hint.second; + if (physReg && + TargetRegisterInfo::isVirtualRegister(physReg) && vrm_->hasPhys(physReg)) + physReg = vrm_->getPhys(physReg); + + TargetRegisterClass::iterator I, E; + tie(I, E) = tri_->getAllocationOrder(RC, Hint.first, physReg, *mf_); + assert(I != E && "No allocatable register in this register class!"); + + // Scan for the first available register. + for (; I != E; ++I) { + unsigned Reg = *I; + // Ignore "downgraded" registers. + if (SkipDGRegs && DowngradedRegs.count(Reg)) + continue; + // Skip recently allocated registers. + if (isRegAvail(Reg) && !isRecentlyUsed(Reg)) { + FreeReg = Reg; + if (FreeReg < inactiveCounts.size()) + FreeRegInactiveCount = inactiveCounts[FreeReg]; + else + FreeRegInactiveCount = 0; + break; + } + } + + // If there are no free regs, or if this reg has the max inactive count, + // return this register. + if (FreeReg == 0 || FreeRegInactiveCount == MaxInactiveCount) { + // Remember what register we picked so we can skip it next time. + if (FreeReg != 0) recordRecentlyUsed(FreeReg); + return FreeReg; + } + + // Continue scanning the registers, looking for the one with the highest + // inactive count. Alkis found that this reduced register pressure very + // slightly on X86 (in rev 1.94 of this file), though this should probably be + // reevaluated now. + for (; I != E; ++I) { + unsigned Reg = *I; + // Ignore "downgraded" registers. + if (SkipDGRegs && DowngradedRegs.count(Reg)) + continue; + if (isRegAvail(Reg) && Reg < inactiveCounts.size() && + FreeRegInactiveCount < inactiveCounts[Reg] && !isRecentlyUsed(Reg)) { + FreeReg = Reg; + FreeRegInactiveCount = inactiveCounts[Reg]; + if (FreeRegInactiveCount == MaxInactiveCount) + break; // We found the one with the max inactive count. + } + } + + // Remember what register we picked so we can skip it next time. + recordRecentlyUsed(FreeReg); + + return FreeReg; +} + +/// getFreePhysReg - return a free physical register for this virtual register +/// interval if we have one, otherwise return 0. +unsigned RALinScan::getFreePhysReg(LiveInterval *cur) { + SmallVector inactiveCounts; + unsigned MaxInactiveCount = 0; + + const TargetRegisterClass *RC = mri_->getRegClass(cur->reg); + const TargetRegisterClass *RCLeader = RelatedRegClasses.getLeaderValue(RC); + + for (IntervalPtrs::iterator i = inactive_.begin(), e = inactive_.end(); + i != e; ++i) { + unsigned reg = i->first->reg; + assert(TargetRegisterInfo::isVirtualRegister(reg) && + "Can only allocate virtual registers!"); + + // If this is not in a related reg class to the register we're allocating, + // don't check it. + const TargetRegisterClass *RegRC = mri_->getRegClass(reg); + if (RelatedRegClasses.getLeaderValue(RegRC) == RCLeader) { + reg = vrm_->getPhys(reg); + if (inactiveCounts.size() <= reg) + inactiveCounts.resize(reg+1); + ++inactiveCounts[reg]; + MaxInactiveCount = std::max(MaxInactiveCount, inactiveCounts[reg]); + } + } + + // If copy coalescer has assigned a "preferred" register, check if it's + // available first. + unsigned Preference = vrm_->getRegAllocPref(cur->reg); + if (Preference) { + DEBUG(errs() << "(preferred: " << tri_->getName(Preference) << ") "); + if (isRegAvail(Preference) && + RC->contains(Preference)) + return Preference; + } + + if (!DowngradedRegs.empty()) { + unsigned FreeReg = getFreePhysReg(cur, RC, MaxInactiveCount, inactiveCounts, + true); + if (FreeReg) + return FreeReg; + } + return getFreePhysReg(cur, RC, MaxInactiveCount, inactiveCounts, false); +} + +FunctionPass* llvm::createLinearScanRegisterAllocator() { + return new RALinScan(); +} diff --git a/libclamav/c++/llvm/lib/CodeGen/RegAllocLocal.cpp b/libclamav/c++/llvm/lib/CodeGen/RegAllocLocal.cpp new file mode 100644 index 000000000..7bb020a65 --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/RegAllocLocal.cpp @@ -0,0 +1,1079 @@ +//===-- RegAllocLocal.cpp - A BasicBlock generic register allocator -------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This register allocator allocates registers to a basic block at a time, +// attempting to keep values in registers and reusing registers as appropriate. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "regalloc" +#include "llvm/BasicBlock.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/CodeGen/RegAllocRegistry.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/IndexedMap.h" +#include "llvm/ADT/SmallSet.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/ADT/STLExtras.h" +#include +using namespace llvm; + +STATISTIC(NumStores, "Number of stores added"); +STATISTIC(NumLoads , "Number of loads added"); + +static RegisterRegAlloc + localRegAlloc("local", "local register allocator", + createLocalRegisterAllocator); + +namespace { + class RALocal : public MachineFunctionPass { + public: + static char ID; + RALocal() : MachineFunctionPass(&ID), StackSlotForVirtReg(-1) {} + private: + const TargetMachine *TM; + MachineFunction *MF; + const TargetRegisterInfo *TRI; + const TargetInstrInfo *TII; + + // StackSlotForVirtReg - Maps virtual regs to the frame index where these + // values are spilled. + IndexedMap StackSlotForVirtReg; + + // Virt2PhysRegMap - This map contains entries for each virtual register + // that is currently available in a physical register. + IndexedMap Virt2PhysRegMap; + + unsigned &getVirt2PhysRegMapSlot(unsigned VirtReg) { + return Virt2PhysRegMap[VirtReg]; + } + + // PhysRegsUsed - This array is effectively a map, containing entries for + // each physical register that currently has a value (ie, it is in + // Virt2PhysRegMap). The value mapped to is the virtual register + // corresponding to the physical register (the inverse of the + // Virt2PhysRegMap), or 0. The value is set to 0 if this register is pinned + // because it is used by a future instruction, and to -2 if it is not + // allocatable. If the entry for a physical register is -1, then the + // physical register is "not in the map". + // + std::vector PhysRegsUsed; + + // PhysRegsUseOrder - This contains a list of the physical registers that + // currently have a virtual register value in them. This list provides an + // ordering of registers, imposing a reallocation order. This list is only + // used if all registers are allocated and we have to spill one, in which + // case we spill the least recently used register. Entries at the front of + // the list are the least recently used registers, entries at the back are + // the most recently used. + // + std::vector PhysRegsUseOrder; + + // Virt2LastUseMap - This maps each virtual register to its last use + // (MachineInstr*, operand index pair). + IndexedMap, VirtReg2IndexFunctor> + Virt2LastUseMap; + + std::pair& getVirtRegLastUse(unsigned Reg) { + assert(TargetRegisterInfo::isVirtualRegister(Reg) && "Illegal VirtReg!"); + return Virt2LastUseMap[Reg]; + } + + // VirtRegModified - This bitset contains information about which virtual + // registers need to be spilled back to memory when their registers are + // scavenged. If a virtual register has simply been rematerialized, there + // is no reason to spill it to memory when we need the register back. + // + BitVector VirtRegModified; + + // UsedInMultipleBlocks - Tracks whether a particular register is used in + // more than one block. + BitVector UsedInMultipleBlocks; + + void markVirtRegModified(unsigned Reg, bool Val = true) { + assert(TargetRegisterInfo::isVirtualRegister(Reg) && "Illegal VirtReg!"); + Reg -= TargetRegisterInfo::FirstVirtualRegister; + if (Val) + VirtRegModified.set(Reg); + else + VirtRegModified.reset(Reg); + } + + bool isVirtRegModified(unsigned Reg) const { + assert(TargetRegisterInfo::isVirtualRegister(Reg) && "Illegal VirtReg!"); + assert(Reg - TargetRegisterInfo::FirstVirtualRegister < VirtRegModified.size() + && "Illegal virtual register!"); + return VirtRegModified[Reg - TargetRegisterInfo::FirstVirtualRegister]; + } + + void AddToPhysRegsUseOrder(unsigned Reg) { + std::vector::iterator It = + std::find(PhysRegsUseOrder.begin(), PhysRegsUseOrder.end(), Reg); + if (It != PhysRegsUseOrder.end()) + PhysRegsUseOrder.erase(It); + PhysRegsUseOrder.push_back(Reg); + } + + void MarkPhysRegRecentlyUsed(unsigned Reg) { + if (PhysRegsUseOrder.empty() || + PhysRegsUseOrder.back() == Reg) return; // Already most recently used + + for (unsigned i = PhysRegsUseOrder.size(); i != 0; --i) + if (areRegsEqual(Reg, PhysRegsUseOrder[i-1])) { + unsigned RegMatch = PhysRegsUseOrder[i-1]; // remove from middle + PhysRegsUseOrder.erase(PhysRegsUseOrder.begin()+i-1); + // Add it to the end of the list + PhysRegsUseOrder.push_back(RegMatch); + if (RegMatch == Reg) + return; // Found an exact match, exit early + } + } + + public: + virtual const char *getPassName() const { + return "Local Register Allocator"; + } + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesCFG(); + AU.addRequiredID(PHIEliminationID); + AU.addRequiredID(TwoAddressInstructionPassID); + MachineFunctionPass::getAnalysisUsage(AU); + } + + private: + /// runOnMachineFunction - Register allocate the whole function + bool runOnMachineFunction(MachineFunction &Fn); + + /// AllocateBasicBlock - Register allocate the specified basic block. + void AllocateBasicBlock(MachineBasicBlock &MBB); + + + /// areRegsEqual - This method returns true if the specified registers are + /// related to each other. To do this, it checks to see if they are equal + /// or if the first register is in the alias set of the second register. + /// + bool areRegsEqual(unsigned R1, unsigned R2) const { + if (R1 == R2) return true; + for (const unsigned *AliasSet = TRI->getAliasSet(R2); + *AliasSet; ++AliasSet) { + if (*AliasSet == R1) return true; + } + return false; + } + + /// getStackSpaceFor - This returns the frame index of the specified virtual + /// register on the stack, allocating space if necessary. + int getStackSpaceFor(unsigned VirtReg, const TargetRegisterClass *RC); + + /// removePhysReg - This method marks the specified physical register as no + /// longer being in use. + /// + void removePhysReg(unsigned PhysReg); + + /// spillVirtReg - This method spills the value specified by PhysReg into + /// the virtual register slot specified by VirtReg. It then updates the RA + /// data structures to indicate the fact that PhysReg is now available. + /// + void spillVirtReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, + unsigned VirtReg, unsigned PhysReg); + + /// spillPhysReg - This method spills the specified physical register into + /// the virtual register slot associated with it. If OnlyVirtRegs is set to + /// true, then the request is ignored if the physical register does not + /// contain a virtual register. + /// + void spillPhysReg(MachineBasicBlock &MBB, MachineInstr *I, + unsigned PhysReg, bool OnlyVirtRegs = false); + + /// assignVirtToPhysReg - This method updates local state so that we know + /// that PhysReg is the proper container for VirtReg now. The physical + /// register must not be used for anything else when this is called. + /// + void assignVirtToPhysReg(unsigned VirtReg, unsigned PhysReg); + + /// isPhysRegAvailable - Return true if the specified physical register is + /// free and available for use. This also includes checking to see if + /// aliased registers are all free... + /// + bool isPhysRegAvailable(unsigned PhysReg) const; + + /// getFreeReg - Look to see if there is a free register available in the + /// specified register class. If not, return 0. + /// + unsigned getFreeReg(const TargetRegisterClass *RC); + + /// getReg - Find a physical register to hold the specified virtual + /// register. If all compatible physical registers are used, this method + /// spills the last used virtual register to the stack, and uses that + /// register. If NoFree is true, that means the caller knows there isn't + /// a free register, do not call getFreeReg(). + unsigned getReg(MachineBasicBlock &MBB, MachineInstr *MI, + unsigned VirtReg, bool NoFree = false); + + /// reloadVirtReg - This method transforms the specified virtual + /// register use to refer to a physical register. This method may do this + /// in one of several ways: if the register is available in a physical + /// register already, it uses that physical register. If the value is not + /// in a physical register, and if there are physical registers available, + /// it loads it into a register. If register pressure is high, and it is + /// possible, it tries to fold the load of the virtual register into the + /// instruction itself. It avoids doing this if register pressure is low to + /// improve the chance that subsequent instructions can use the reloaded + /// value. This method returns the modified instruction. + /// + MachineInstr *reloadVirtReg(MachineBasicBlock &MBB, MachineInstr *MI, + unsigned OpNum, SmallSet &RRegs); + + /// ComputeLocalLiveness - Computes liveness of registers within a basic + /// block, setting the killed/dead flags as appropriate. + void ComputeLocalLiveness(MachineBasicBlock& MBB); + + void reloadPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator &I, + unsigned PhysReg); + }; + char RALocal::ID = 0; +} + +/// getStackSpaceFor - This allocates space for the specified virtual register +/// to be held on the stack. +int RALocal::getStackSpaceFor(unsigned VirtReg, const TargetRegisterClass *RC) { + // Find the location Reg would belong... + int SS = StackSlotForVirtReg[VirtReg]; + if (SS != -1) + return SS; // Already has space allocated? + + // Allocate a new stack object for this spill location... + int FrameIdx = MF->getFrameInfo()->CreateSpillStackObject(RC->getSize(), + RC->getAlignment()); + + // Assign the slot... + StackSlotForVirtReg[VirtReg] = FrameIdx; + return FrameIdx; +} + + +/// removePhysReg - This method marks the specified physical register as no +/// longer being in use. +/// +void RALocal::removePhysReg(unsigned PhysReg) { + PhysRegsUsed[PhysReg] = -1; // PhyReg no longer used + + std::vector::iterator It = + std::find(PhysRegsUseOrder.begin(), PhysRegsUseOrder.end(), PhysReg); + if (It != PhysRegsUseOrder.end()) + PhysRegsUseOrder.erase(It); +} + + +/// spillVirtReg - This method spills the value specified by PhysReg into the +/// virtual register slot specified by VirtReg. It then updates the RA data +/// structures to indicate the fact that PhysReg is now available. +/// +void RALocal::spillVirtReg(MachineBasicBlock &MBB, + MachineBasicBlock::iterator I, + unsigned VirtReg, unsigned PhysReg) { + assert(VirtReg && "Spilling a physical register is illegal!" + " Must not have appropriate kill for the register or use exists beyond" + " the intended one."); + DEBUG(errs() << " Spilling register " << TRI->getName(PhysReg) + << " containing %reg" << VirtReg); + + if (!isVirtRegModified(VirtReg)) { + DEBUG(errs() << " which has not been modified, so no store necessary!"); + std::pair &LastUse = getVirtRegLastUse(VirtReg); + if (LastUse.first) + LastUse.first->getOperand(LastUse.second).setIsKill(); + } else { + // Otherwise, there is a virtual register corresponding to this physical + // register. We only need to spill it into its stack slot if it has been + // modified. + const TargetRegisterClass *RC = MF->getRegInfo().getRegClass(VirtReg); + int FrameIndex = getStackSpaceFor(VirtReg, RC); + DEBUG(errs() << " to stack slot #" << FrameIndex); + // If the instruction reads the register that's spilled, (e.g. this can + // happen if it is a move to a physical register), then the spill + // instruction is not a kill. + bool isKill = !(I != MBB.end() && I->readsRegister(PhysReg)); + TII->storeRegToStackSlot(MBB, I, PhysReg, isKill, FrameIndex, RC); + ++NumStores; // Update statistics + } + + getVirt2PhysRegMapSlot(VirtReg) = 0; // VirtReg no longer available + + DEBUG(errs() << '\n'); + removePhysReg(PhysReg); +} + + +/// spillPhysReg - This method spills the specified physical register into the +/// virtual register slot associated with it. If OnlyVirtRegs is set to true, +/// then the request is ignored if the physical register does not contain a +/// virtual register. +/// +void RALocal::spillPhysReg(MachineBasicBlock &MBB, MachineInstr *I, + unsigned PhysReg, bool OnlyVirtRegs) { + if (PhysRegsUsed[PhysReg] != -1) { // Only spill it if it's used! + assert(PhysRegsUsed[PhysReg] != -2 && "Non allocable reg used!"); + if (PhysRegsUsed[PhysReg] || !OnlyVirtRegs) + spillVirtReg(MBB, I, PhysRegsUsed[PhysReg], PhysReg); + } else { + // If the selected register aliases any other registers, we must make + // sure that one of the aliases isn't alive. + for (const unsigned *AliasSet = TRI->getAliasSet(PhysReg); + *AliasSet; ++AliasSet) + if (PhysRegsUsed[*AliasSet] != -1 && // Spill aliased register. + PhysRegsUsed[*AliasSet] != -2) // If allocatable. + if (PhysRegsUsed[*AliasSet]) + spillVirtReg(MBB, I, PhysRegsUsed[*AliasSet], *AliasSet); + } +} + + +/// assignVirtToPhysReg - This method updates local state so that we know +/// that PhysReg is the proper container for VirtReg now. The physical +/// register must not be used for anything else when this is called. +/// +void RALocal::assignVirtToPhysReg(unsigned VirtReg, unsigned PhysReg) { + assert(PhysRegsUsed[PhysReg] == -1 && "Phys reg already assigned!"); + // Update information to note the fact that this register was just used, and + // it holds VirtReg. + PhysRegsUsed[PhysReg] = VirtReg; + getVirt2PhysRegMapSlot(VirtReg) = PhysReg; + AddToPhysRegsUseOrder(PhysReg); // New use of PhysReg +} + + +/// isPhysRegAvailable - Return true if the specified physical register is free +/// and available for use. This also includes checking to see if aliased +/// registers are all free... +/// +bool RALocal::isPhysRegAvailable(unsigned PhysReg) const { + if (PhysRegsUsed[PhysReg] != -1) return false; + + // If the selected register aliases any other allocated registers, it is + // not free! + for (const unsigned *AliasSet = TRI->getAliasSet(PhysReg); + *AliasSet; ++AliasSet) + if (PhysRegsUsed[*AliasSet] >= 0) // Aliased register in use? + return false; // Can't use this reg then. + return true; +} + + +/// getFreeReg - Look to see if there is a free register available in the +/// specified register class. If not, return 0. +/// +unsigned RALocal::getFreeReg(const TargetRegisterClass *RC) { + // Get iterators defining the range of registers that are valid to allocate in + // this class, which also specifies the preferred allocation order. + TargetRegisterClass::iterator RI = RC->allocation_order_begin(*MF); + TargetRegisterClass::iterator RE = RC->allocation_order_end(*MF); + + for (; RI != RE; ++RI) + if (isPhysRegAvailable(*RI)) { // Is reg unused? + assert(*RI != 0 && "Cannot use register!"); + return *RI; // Found an unused register! + } + return 0; +} + + +/// getReg - Find a physical register to hold the specified virtual +/// register. If all compatible physical registers are used, this method spills +/// the last used virtual register to the stack, and uses that register. +/// +unsigned RALocal::getReg(MachineBasicBlock &MBB, MachineInstr *I, + unsigned VirtReg, bool NoFree) { + const TargetRegisterClass *RC = MF->getRegInfo().getRegClass(VirtReg); + + // First check to see if we have a free register of the requested type... + unsigned PhysReg = NoFree ? 0 : getFreeReg(RC); + + // If we didn't find an unused register, scavenge one now! + if (PhysReg == 0) { + assert(!PhysRegsUseOrder.empty() && "No allocated registers??"); + + // Loop over all of the preallocated registers from the least recently used + // to the most recently used. When we find one that is capable of holding + // our register, use it. + for (unsigned i = 0; PhysReg == 0; ++i) { + assert(i != PhysRegsUseOrder.size() && + "Couldn't find a register of the appropriate class!"); + + unsigned R = PhysRegsUseOrder[i]; + + // We can only use this register if it holds a virtual register (ie, it + // can be spilled). Do not use it if it is an explicitly allocated + // physical register! + assert(PhysRegsUsed[R] != -1 && + "PhysReg in PhysRegsUseOrder, but is not allocated?"); + if (PhysRegsUsed[R] && PhysRegsUsed[R] != -2) { + // If the current register is compatible, use it. + if (RC->contains(R)) { + PhysReg = R; + break; + } else { + // If one of the registers aliased to the current register is + // compatible, use it. + for (const unsigned *AliasIt = TRI->getAliasSet(R); + *AliasIt; ++AliasIt) { + if (RC->contains(*AliasIt) && + // If this is pinned down for some reason, don't use it. For + // example, if CL is pinned, and we run across CH, don't use + // CH as justification for using scavenging ECX (which will + // fail). + PhysRegsUsed[*AliasIt] != 0 && + + // Make sure the register is allocatable. Don't allocate SIL on + // x86-32. + PhysRegsUsed[*AliasIt] != -2) { + PhysReg = *AliasIt; // Take an aliased register + break; + } + } + } + } + } + + assert(PhysReg && "Physical register not assigned!?!?"); + + // At this point PhysRegsUseOrder[i] is the least recently used register of + // compatible register class. Spill it to memory and reap its remains. + spillPhysReg(MBB, I, PhysReg); + } + + // Now that we know which register we need to assign this to, do it now! + assignVirtToPhysReg(VirtReg, PhysReg); + return PhysReg; +} + + +/// reloadVirtReg - This method transforms the specified virtual +/// register use to refer to a physical register. This method may do this in +/// one of several ways: if the register is available in a physical register +/// already, it uses that physical register. If the value is not in a physical +/// register, and if there are physical registers available, it loads it into a +/// register. If register pressure is high, and it is possible, it tries to +/// fold the load of the virtual register into the instruction itself. It +/// avoids doing this if register pressure is low to improve the chance that +/// subsequent instructions can use the reloaded value. This method returns the +/// modified instruction. +/// +MachineInstr *RALocal::reloadVirtReg(MachineBasicBlock &MBB, MachineInstr *MI, + unsigned OpNum, + SmallSet &ReloadedRegs) { + unsigned VirtReg = MI->getOperand(OpNum).getReg(); + + // If the virtual register is already available, just update the instruction + // and return. + if (unsigned PR = getVirt2PhysRegMapSlot(VirtReg)) { + MarkPhysRegRecentlyUsed(PR); // Already have this value available! + MI->getOperand(OpNum).setReg(PR); // Assign the input register + getVirtRegLastUse(VirtReg) = std::make_pair(MI, OpNum); + return MI; + } + + // Otherwise, we need to fold it into the current instruction, or reload it. + // If we have registers available to hold the value, use them. + const TargetRegisterClass *RC = MF->getRegInfo().getRegClass(VirtReg); + unsigned PhysReg = getFreeReg(RC); + int FrameIndex = getStackSpaceFor(VirtReg, RC); + + if (PhysReg) { // Register is available, allocate it! + assignVirtToPhysReg(VirtReg, PhysReg); + } else { // No registers available. + // Force some poor hapless value out of the register file to + // make room for the new register, and reload it. + PhysReg = getReg(MBB, MI, VirtReg, true); + } + + markVirtRegModified(VirtReg, false); // Note that this reg was just reloaded + + DEBUG(errs() << " Reloading %reg" << VirtReg << " into " + << TRI->getName(PhysReg) << "\n"); + + // Add move instruction(s) + TII->loadRegFromStackSlot(MBB, MI, PhysReg, FrameIndex, RC); + ++NumLoads; // Update statistics + + MF->getRegInfo().setPhysRegUsed(PhysReg); + MI->getOperand(OpNum).setReg(PhysReg); // Assign the input register + getVirtRegLastUse(VirtReg) = std::make_pair(MI, OpNum); + + if (!ReloadedRegs.insert(PhysReg)) { + std::string msg; + raw_string_ostream Msg(msg); + Msg << "Ran out of registers during register allocation!"; + if (MI->getOpcode() == TargetInstrInfo::INLINEASM) { + Msg << "\nPlease check your inline asm statement for invalid " + << "constraints:\n"; + MI->print(Msg, TM); + } + llvm_report_error(Msg.str()); + } + for (const unsigned *SubRegs = TRI->getSubRegisters(PhysReg); + *SubRegs; ++SubRegs) { + if (!ReloadedRegs.insert(*SubRegs)) { + std::string msg; + raw_string_ostream Msg(msg); + Msg << "Ran out of registers during register allocation!"; + if (MI->getOpcode() == TargetInstrInfo::INLINEASM) { + Msg << "\nPlease check your inline asm statement for invalid " + << "constraints:\n"; + MI->print(Msg, TM); + } + llvm_report_error(Msg.str()); + } + } + + return MI; +} + +/// isReadModWriteImplicitKill - True if this is an implicit kill for a +/// read/mod/write register, i.e. update partial register. +static bool isReadModWriteImplicitKill(MachineInstr *MI, unsigned Reg) { + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + MachineOperand& MO = MI->getOperand(i); + if (MO.isReg() && MO.getReg() == Reg && MO.isImplicit() && + MO.isDef() && !MO.isDead()) + return true; + } + return false; +} + +/// isReadModWriteImplicitDef - True if this is an implicit def for a +/// read/mod/write register, i.e. update partial register. +static bool isReadModWriteImplicitDef(MachineInstr *MI, unsigned Reg) { + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + MachineOperand& MO = MI->getOperand(i); + if (MO.isReg() && MO.getReg() == Reg && MO.isImplicit() && + !MO.isDef() && MO.isKill()) + return true; + } + return false; +} + +// precedes - Helper function to determine with MachineInstr A +// precedes MachineInstr B within the same MBB. +static bool precedes(MachineBasicBlock::iterator A, + MachineBasicBlock::iterator B) { + if (A == B) + return false; + + MachineBasicBlock::iterator I = A->getParent()->begin(); + while (I != A->getParent()->end()) { + if (I == A) + return true; + else if (I == B) + return false; + + ++I; + } + + return false; +} + +/// ComputeLocalLiveness - Computes liveness of registers within a basic +/// block, setting the killed/dead flags as appropriate. +void RALocal::ComputeLocalLiveness(MachineBasicBlock& MBB) { + MachineRegisterInfo& MRI = MBB.getParent()->getRegInfo(); + // Keep track of the most recently seen previous use or def of each reg, + // so that we can update them with dead/kill markers. + DenseMap > LastUseDef; + for (MachineBasicBlock::iterator I = MBB.begin(), E = MBB.end(); + I != E; ++I) { + for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i) { + MachineOperand& MO = I->getOperand(i); + // Uses don't trigger any flags, but we need to save + // them for later. Also, we have to process these + // _before_ processing the defs, since an instr + // uses regs before it defs them. + if (MO.isReg() && MO.getReg() && MO.isUse()) { + LastUseDef[MO.getReg()] = std::make_pair(I, i); + + + if (TargetRegisterInfo::isVirtualRegister(MO.getReg())) continue; + + const unsigned* Aliases = TRI->getAliasSet(MO.getReg()); + if (Aliases) { + while (*Aliases) { + DenseMap >::iterator + alias = LastUseDef.find(*Aliases); + + if (alias != LastUseDef.end() && alias->second.first != I) + LastUseDef[*Aliases] = std::make_pair(I, i); + + ++Aliases; + } + } + } + } + + for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i) { + MachineOperand& MO = I->getOperand(i); + // Defs others than 2-addr redefs _do_ trigger flag changes: + // - A def followed by a def is dead + // - A use followed by a def is a kill + if (MO.isReg() && MO.getReg() && MO.isDef()) { + DenseMap >::iterator + last = LastUseDef.find(MO.getReg()); + if (last != LastUseDef.end()) { + // Check if this is a two address instruction. If so, then + // the def does not kill the use. + if (last->second.first == I && + I->isRegTiedToUseOperand(i)) + continue; + + MachineOperand& lastUD = + last->second.first->getOperand(last->second.second); + if (lastUD.isDef()) + lastUD.setIsDead(true); + else + lastUD.setIsKill(true); + } + + LastUseDef[MO.getReg()] = std::make_pair(I, i); + } + } + } + + // Live-out (of the function) registers contain return values of the function, + // so we need to make sure they are alive at return time. + if (!MBB.empty() && MBB.back().getDesc().isReturn()) { + MachineInstr* Ret = &MBB.back(); + for (MachineRegisterInfo::liveout_iterator + I = MF->getRegInfo().liveout_begin(), + E = MF->getRegInfo().liveout_end(); I != E; ++I) + if (!Ret->readsRegister(*I)) { + Ret->addOperand(MachineOperand::CreateReg(*I, false, true)); + LastUseDef[*I] = std::make_pair(Ret, Ret->getNumOperands()-1); + } + } + + // Finally, loop over the final use/def of each reg + // in the block and determine if it is dead. + for (DenseMap >::iterator + I = LastUseDef.begin(), E = LastUseDef.end(); I != E; ++I) { + MachineInstr* MI = I->second.first; + unsigned idx = I->second.second; + MachineOperand& MO = MI->getOperand(idx); + + bool isPhysReg = TargetRegisterInfo::isPhysicalRegister(MO.getReg()); + + // A crude approximation of "live-out" calculation + bool usedOutsideBlock = isPhysReg ? false : + UsedInMultipleBlocks.test(MO.getReg() - + TargetRegisterInfo::FirstVirtualRegister); + if (!isPhysReg && !usedOutsideBlock) + for (MachineRegisterInfo::reg_iterator UI = MRI.reg_begin(MO.getReg()), + UE = MRI.reg_end(); UI != UE; ++UI) + // Two cases: + // - used in another block + // - used in the same block before it is defined (loop) + if (UI->getParent() != &MBB || + (MO.isDef() && UI.getOperand().isUse() && precedes(&*UI, MI))) { + UsedInMultipleBlocks.set(MO.getReg() - + TargetRegisterInfo::FirstVirtualRegister); + usedOutsideBlock = true; + break; + } + + // Physical registers and those that are not live-out of the block + // are killed/dead at their last use/def within this block. + if (isPhysReg || !usedOutsideBlock) { + if (MO.isUse()) { + // Don't mark uses that are tied to defs as kills. + if (!MI->isRegTiedToDefOperand(idx)) + MO.setIsKill(true); + } else + MO.setIsDead(true); + } + } +} + +void RALocal::AllocateBasicBlock(MachineBasicBlock &MBB) { + // loop over each instruction + MachineBasicBlock::iterator MII = MBB.begin(); + + DEBUG({ + const BasicBlock *LBB = MBB.getBasicBlock(); + if (LBB) + errs() << "\nStarting RegAlloc of BB: " << LBB->getName(); + }); + + // Add live-in registers as active. + for (MachineBasicBlock::livein_iterator I = MBB.livein_begin(), + E = MBB.livein_end(); I != E; ++I) { + unsigned Reg = *I; + MF->getRegInfo().setPhysRegUsed(Reg); + PhysRegsUsed[Reg] = 0; // It is free and reserved now + AddToPhysRegsUseOrder(Reg); + for (const unsigned *SubRegs = TRI->getSubRegisters(Reg); + *SubRegs; ++SubRegs) { + if (PhysRegsUsed[*SubRegs] != -2) { + AddToPhysRegsUseOrder(*SubRegs); + PhysRegsUsed[*SubRegs] = 0; // It is free and reserved now + MF->getRegInfo().setPhysRegUsed(*SubRegs); + } + } + } + + ComputeLocalLiveness(MBB); + + // Otherwise, sequentially allocate each instruction in the MBB. + while (MII != MBB.end()) { + MachineInstr *MI = MII++; + const TargetInstrDesc &TID = MI->getDesc(); + DEBUG({ + errs() << "\nStarting RegAlloc of: " << *MI; + errs() << " Regs have values: "; + for (unsigned i = 0; i != TRI->getNumRegs(); ++i) + if (PhysRegsUsed[i] != -1 && PhysRegsUsed[i] != -2) + errs() << "[" << TRI->getName(i) + << ",%reg" << PhysRegsUsed[i] << "] "; + errs() << '\n'; + }); + + // Loop over the implicit uses, making sure that they are at the head of the + // use order list, so they don't get reallocated. + if (TID.ImplicitUses) { + for (const unsigned *ImplicitUses = TID.ImplicitUses; + *ImplicitUses; ++ImplicitUses) + MarkPhysRegRecentlyUsed(*ImplicitUses); + } + + SmallVector Kills; + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + MachineOperand& MO = MI->getOperand(i); + if (MO.isReg() && MO.isKill()) { + if (!MO.isImplicit()) + Kills.push_back(MO.getReg()); + else if (!isReadModWriteImplicitKill(MI, MO.getReg())) + // These are extra physical register kills when a sub-register + // is defined (def of a sub-register is a read/mod/write of the + // larger registers). Ignore. + Kills.push_back(MO.getReg()); + } + } + + // If any physical regs are earlyclobber, spill any value they might + // have in them, then mark them unallocatable. + // If any virtual regs are earlyclobber, allocate them now (before + // freeing inputs that are killed). + if (MI->getOpcode()==TargetInstrInfo::INLINEASM) { + for (unsigned i = 0; i != MI->getNumOperands(); ++i) { + MachineOperand& MO = MI->getOperand(i); + if (MO.isReg() && MO.isDef() && MO.isEarlyClobber() && + MO.getReg()) { + if (TargetRegisterInfo::isVirtualRegister(MO.getReg())) { + unsigned DestVirtReg = MO.getReg(); + unsigned DestPhysReg; + + // If DestVirtReg already has a value, use it. + if (!(DestPhysReg = getVirt2PhysRegMapSlot(DestVirtReg))) + DestPhysReg = getReg(MBB, MI, DestVirtReg); + MF->getRegInfo().setPhysRegUsed(DestPhysReg); + markVirtRegModified(DestVirtReg); + getVirtRegLastUse(DestVirtReg) = + std::make_pair((MachineInstr*)0, 0); + DEBUG(errs() << " Assigning " << TRI->getName(DestPhysReg) + << " to %reg" << DestVirtReg << "\n"); + MO.setReg(DestPhysReg); // Assign the earlyclobber register + } else { + unsigned Reg = MO.getReg(); + if (PhysRegsUsed[Reg] == -2) continue; // Something like ESP. + // These are extra physical register defs when a sub-register + // is defined (def of a sub-register is a read/mod/write of the + // larger registers). Ignore. + if (isReadModWriteImplicitDef(MI, MO.getReg())) continue; + + MF->getRegInfo().setPhysRegUsed(Reg); + spillPhysReg(MBB, MI, Reg, true); // Spill any existing value in reg + PhysRegsUsed[Reg] = 0; // It is free and reserved now + AddToPhysRegsUseOrder(Reg); + + for (const unsigned *SubRegs = TRI->getSubRegisters(Reg); + *SubRegs; ++SubRegs) { + if (PhysRegsUsed[*SubRegs] != -2) { + MF->getRegInfo().setPhysRegUsed(*SubRegs); + PhysRegsUsed[*SubRegs] = 0; // It is free and reserved now + AddToPhysRegsUseOrder(*SubRegs); + } + } + } + } + } + } + + // Get the used operands into registers. This has the potential to spill + // incoming values if we are out of registers. Note that we completely + // ignore physical register uses here. We assume that if an explicit + // physical register is referenced by the instruction, that it is guaranteed + // to be live-in, or the input is badly hosed. + // + SmallSet ReloadedRegs; + for (unsigned i = 0; i != MI->getNumOperands(); ++i) { + MachineOperand& MO = MI->getOperand(i); + // here we are looking for only used operands (never def&use) + if (MO.isReg() && !MO.isDef() && MO.getReg() && !MO.isImplicit() && + TargetRegisterInfo::isVirtualRegister(MO.getReg())) + MI = reloadVirtReg(MBB, MI, i, ReloadedRegs); + } + + // If this instruction is the last user of this register, kill the + // value, freeing the register being used, so it doesn't need to be + // spilled to memory. + // + for (unsigned i = 0, e = Kills.size(); i != e; ++i) { + unsigned VirtReg = Kills[i]; + unsigned PhysReg = VirtReg; + if (TargetRegisterInfo::isVirtualRegister(VirtReg)) { + // If the virtual register was never materialized into a register, it + // might not be in the map, but it won't hurt to zero it out anyway. + unsigned &PhysRegSlot = getVirt2PhysRegMapSlot(VirtReg); + PhysReg = PhysRegSlot; + PhysRegSlot = 0; + } else if (PhysRegsUsed[PhysReg] == -2) { + // Unallocatable register dead, ignore. + continue; + } else { + assert((!PhysRegsUsed[PhysReg] || PhysRegsUsed[PhysReg] == -1) && + "Silently clearing a virtual register?"); + } + + if (PhysReg) { + DEBUG(errs() << " Last use of " << TRI->getName(PhysReg) + << "[%reg" << VirtReg <<"], removing it from live set\n"); + removePhysReg(PhysReg); + for (const unsigned *SubRegs = TRI->getSubRegisters(PhysReg); + *SubRegs; ++SubRegs) { + if (PhysRegsUsed[*SubRegs] != -2) { + DEBUG(errs() << " Last use of " + << TRI->getName(*SubRegs) << "[%reg" << VirtReg + <<"], removing it from live set\n"); + removePhysReg(*SubRegs); + } + } + } + } + + // Loop over all of the operands of the instruction, spilling registers that + // are defined, and marking explicit destinations in the PhysRegsUsed map. + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + MachineOperand& MO = MI->getOperand(i); + if (MO.isReg() && MO.isDef() && !MO.isImplicit() && MO.getReg() && + !MO.isEarlyClobber() && + TargetRegisterInfo::isPhysicalRegister(MO.getReg())) { + unsigned Reg = MO.getReg(); + if (PhysRegsUsed[Reg] == -2) continue; // Something like ESP. + // These are extra physical register defs when a sub-register + // is defined (def of a sub-register is a read/mod/write of the + // larger registers). Ignore. + if (isReadModWriteImplicitDef(MI, MO.getReg())) continue; + + MF->getRegInfo().setPhysRegUsed(Reg); + spillPhysReg(MBB, MI, Reg, true); // Spill any existing value in reg + PhysRegsUsed[Reg] = 0; // It is free and reserved now + AddToPhysRegsUseOrder(Reg); + + for (const unsigned *SubRegs = TRI->getSubRegisters(Reg); + *SubRegs; ++SubRegs) { + if (PhysRegsUsed[*SubRegs] != -2) { + MF->getRegInfo().setPhysRegUsed(*SubRegs); + PhysRegsUsed[*SubRegs] = 0; // It is free and reserved now + AddToPhysRegsUseOrder(*SubRegs); + } + } + } + } + + // Loop over the implicit defs, spilling them as well. + if (TID.ImplicitDefs) { + for (const unsigned *ImplicitDefs = TID.ImplicitDefs; + *ImplicitDefs; ++ImplicitDefs) { + unsigned Reg = *ImplicitDefs; + if (PhysRegsUsed[Reg] != -2) { + spillPhysReg(MBB, MI, Reg, true); + AddToPhysRegsUseOrder(Reg); + PhysRegsUsed[Reg] = 0; // It is free and reserved now + } + MF->getRegInfo().setPhysRegUsed(Reg); + for (const unsigned *SubRegs = TRI->getSubRegisters(Reg); + *SubRegs; ++SubRegs) { + if (PhysRegsUsed[*SubRegs] != -2) { + AddToPhysRegsUseOrder(*SubRegs); + PhysRegsUsed[*SubRegs] = 0; // It is free and reserved now + MF->getRegInfo().setPhysRegUsed(*SubRegs); + } + } + } + } + + SmallVector DeadDefs; + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + MachineOperand& MO = MI->getOperand(i); + if (MO.isReg() && MO.isDead()) + DeadDefs.push_back(MO.getReg()); + } + + // Okay, we have allocated all of the source operands and spilled any values + // that would be destroyed by defs of this instruction. Loop over the + // explicit defs and assign them to a register, spilling incoming values if + // we need to scavenge a register. + // + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + MachineOperand& MO = MI->getOperand(i); + if (MO.isReg() && MO.isDef() && MO.getReg() && + !MO.isEarlyClobber() && + TargetRegisterInfo::isVirtualRegister(MO.getReg())) { + unsigned DestVirtReg = MO.getReg(); + unsigned DestPhysReg; + + // If DestVirtReg already has a value, use it. + if (!(DestPhysReg = getVirt2PhysRegMapSlot(DestVirtReg))) + DestPhysReg = getReg(MBB, MI, DestVirtReg); + MF->getRegInfo().setPhysRegUsed(DestPhysReg); + markVirtRegModified(DestVirtReg); + getVirtRegLastUse(DestVirtReg) = std::make_pair((MachineInstr*)0, 0); + DEBUG(errs() << " Assigning " << TRI->getName(DestPhysReg) + << " to %reg" << DestVirtReg << "\n"); + MO.setReg(DestPhysReg); // Assign the output register + } + } + + // If this instruction defines any registers that are immediately dead, + // kill them now. + // + for (unsigned i = 0, e = DeadDefs.size(); i != e; ++i) { + unsigned VirtReg = DeadDefs[i]; + unsigned PhysReg = VirtReg; + if (TargetRegisterInfo::isVirtualRegister(VirtReg)) { + unsigned &PhysRegSlot = getVirt2PhysRegMapSlot(VirtReg); + PhysReg = PhysRegSlot; + assert(PhysReg != 0); + PhysRegSlot = 0; + } else if (PhysRegsUsed[PhysReg] == -2) { + // Unallocatable register dead, ignore. + continue; + } + + if (PhysReg) { + DEBUG(errs() << " Register " << TRI->getName(PhysReg) + << " [%reg" << VirtReg + << "] is never used, removing it from live set\n"); + removePhysReg(PhysReg); + for (const unsigned *AliasSet = TRI->getAliasSet(PhysReg); + *AliasSet; ++AliasSet) { + if (PhysRegsUsed[*AliasSet] != -2) { + DEBUG(errs() << " Register " << TRI->getName(*AliasSet) + << " [%reg" << *AliasSet + << "] is never used, removing it from live set\n"); + removePhysReg(*AliasSet); + } + } + } + } + + // Finally, if this is a noop copy instruction, zap it. (Except that if + // the copy is dead, it must be kept to avoid messing up liveness info for + // the register scavenger. See pr4100.) + unsigned SrcReg, DstReg, SrcSubReg, DstSubReg; + if (TII->isMoveInstr(*MI, SrcReg, DstReg, SrcSubReg, DstSubReg) && + SrcReg == DstReg && DeadDefs.empty()) + MBB.erase(MI); + } + + MachineBasicBlock::iterator MI = MBB.getFirstTerminator(); + + // Spill all physical registers holding virtual registers now. + for (unsigned i = 0, e = TRI->getNumRegs(); i != e; ++i) + if (PhysRegsUsed[i] != -1 && PhysRegsUsed[i] != -2) { + if (unsigned VirtReg = PhysRegsUsed[i]) + spillVirtReg(MBB, MI, VirtReg, i); + else + removePhysReg(i); + } + +#if 0 + // This checking code is very expensive. + bool AllOk = true; + for (unsigned i = TargetRegisterInfo::FirstVirtualRegister, + e = MF->getRegInfo().getLastVirtReg(); i <= e; ++i) + if (unsigned PR = Virt2PhysRegMap[i]) { + cerr << "Register still mapped: " << i << " -> " << PR << "\n"; + AllOk = false; + } + assert(AllOk && "Virtual registers still in phys regs?"); +#endif + + // Clear any physical register which appear live at the end of the basic + // block, but which do not hold any virtual registers. e.g., the stack + // pointer. + PhysRegsUseOrder.clear(); +} + +/// runOnMachineFunction - Register allocate the whole function +/// +bool RALocal::runOnMachineFunction(MachineFunction &Fn) { + DEBUG(errs() << "Machine Function\n"); + MF = &Fn; + TM = &Fn.getTarget(); + TRI = TM->getRegisterInfo(); + TII = TM->getInstrInfo(); + + PhysRegsUsed.assign(TRI->getNumRegs(), -1); + + // At various places we want to efficiently check to see whether a register + // is allocatable. To handle this, we mark all unallocatable registers as + // being pinned down, permanently. + { + BitVector Allocable = TRI->getAllocatableSet(Fn); + for (unsigned i = 0, e = Allocable.size(); i != e; ++i) + if (!Allocable[i]) + PhysRegsUsed[i] = -2; // Mark the reg unallocable. + } + + // initialize the virtual->physical register map to have a 'null' + // mapping for all virtual registers + unsigned LastVirtReg = MF->getRegInfo().getLastVirtReg(); + StackSlotForVirtReg.grow(LastVirtReg); + Virt2PhysRegMap.grow(LastVirtReg); + Virt2LastUseMap.grow(LastVirtReg); + VirtRegModified.resize(LastVirtReg+1-TargetRegisterInfo::FirstVirtualRegister); + UsedInMultipleBlocks.resize(LastVirtReg+1-TargetRegisterInfo::FirstVirtualRegister); + + // Loop over all of the basic blocks, eliminating virtual register references + for (MachineFunction::iterator MBB = Fn.begin(), MBBe = Fn.end(); + MBB != MBBe; ++MBB) + AllocateBasicBlock(*MBB); + + StackSlotForVirtReg.clear(); + PhysRegsUsed.clear(); + VirtRegModified.clear(); + UsedInMultipleBlocks.clear(); + Virt2PhysRegMap.clear(); + Virt2LastUseMap.clear(); + return true; +} + +FunctionPass *llvm::createLocalRegisterAllocator() { + return new RALocal(); +} diff --git a/libclamav/c++/llvm/lib/CodeGen/RegAllocPBQP.cpp b/libclamav/c++/llvm/lib/CodeGen/RegAllocPBQP.cpp new file mode 100644 index 000000000..c677d341b --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/RegAllocPBQP.cpp @@ -0,0 +1,912 @@ +//===------ RegAllocPBQP.cpp ---- PBQP Register Allocator -------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains a Partitioned Boolean Quadratic Programming (PBQP) based +// register allocator for LLVM. This allocator works by constructing a PBQP +// problem representing the register allocation problem under consideration, +// solving this using a PBQP solver, and mapping the solution back to a +// register assignment. If any variables are selected for spilling then spill +// code is inserted and the process repeated. +// +// The PBQP solver (pbqp.c) provided for this allocator uses a heuristic tuned +// for register allocation. For more information on PBQP for register +// allocation, see the following papers: +// +// (1) Hames, L. and Scholz, B. 2006. Nearly optimal register allocation with +// PBQP. In Proceedings of the 7th Joint Modular Languages Conference +// (JMLC'06). LNCS, vol. 4228. Springer, New York, NY, USA. 346-361. +// +// (2) Scholz, B., Eckstein, E. 2002. Register allocation for irregular +// architectures. In Proceedings of the Joint Conference on Languages, +// Compilers and Tools for Embedded Systems (LCTES'02), ACM Press, New York, +// NY, USA, 139-148. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "regalloc" + +#include "PBQP/HeuristicSolver.h" +#include "PBQP/SimpleGraph.h" +#include "PBQP/Heuristics/Briggs.h" +#include "VirtRegMap.h" +#include "VirtRegRewriter.h" +#include "llvm/CodeGen/LiveIntervalAnalysis.h" +#include "llvm/CodeGen/LiveStackAnalysis.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineLoopInfo.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/RegAllocRegistry.h" +#include "llvm/CodeGen/RegisterCoalescer.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetMachine.h" +#include +#include +#include +#include +#include + +using namespace llvm; + +static RegisterRegAlloc +registerPBQPRepAlloc("pbqp", "PBQP register allocator.", + llvm::createPBQPRegisterAllocator); + +static cl::opt +pbqpCoalescing("pbqp-coalescing", + cl::desc("Attempt coalescing during PBQP register allocation."), + cl::init(false), cl::Hidden); + +namespace { + + /// + /// PBQP based allocators solve the register allocation problem by mapping + /// register allocation problems to Partitioned Boolean Quadratic + /// Programming problems. + class PBQPRegAlloc : public MachineFunctionPass { + public: + + static char ID; + + /// Construct a PBQP register allocator. + PBQPRegAlloc() : MachineFunctionPass(&ID) {} + + /// Return the pass name. + virtual const char* getPassName() const { + return "PBQP Register Allocator"; + } + + /// PBQP analysis usage. + virtual void getAnalysisUsage(AnalysisUsage &au) const { + au.addRequired(); + au.addPreserved(); + au.addRequired(); + //au.addRequiredID(SplitCriticalEdgesID); + au.addRequired(); + au.addRequired(); + au.addPreserved(); + au.addRequired(); + au.addPreserved(); + au.addRequired(); + MachineFunctionPass::getAnalysisUsage(au); + } + + /// Perform register allocation + virtual bool runOnMachineFunction(MachineFunction &MF); + + private: + typedef std::map LI2NodeMap; + typedef std::vector Node2LIMap; + typedef std::vector AllowedSet; + typedef std::vector AllowedSetMap; + typedef std::set RegSet; + typedef std::pair RegPair; + typedef std::map CoalesceMap; + + typedef std::set LiveIntervalSet; + + MachineFunction *mf; + const TargetMachine *tm; + const TargetRegisterInfo *tri; + const TargetInstrInfo *tii; + const MachineLoopInfo *loopInfo; + MachineRegisterInfo *mri; + + LiveIntervals *lis; + LiveStacks *lss; + VirtRegMap *vrm; + + LI2NodeMap li2Node; + Node2LIMap node2LI; + AllowedSetMap allowedSets; + LiveIntervalSet vregIntervalsToAlloc, + emptyVRegIntervals; + + + /// Builds a PBQP cost vector. + template + PBQP::Vector buildCostVector(unsigned vReg, + const RegContainer &allowed, + const CoalesceMap &cealesces, + PBQP::PBQPNum spillCost) const; + + /// \brief Builds a PBQP interference matrix. + /// + /// @return Either a pointer to a non-zero PBQP matrix representing the + /// allocation option costs, or a null pointer for a zero matrix. + /// + /// Expects allowed sets for two interfering LiveIntervals. These allowed + /// sets should contain only allocable registers from the LiveInterval's + /// register class, with any interfering pre-colored registers removed. + template + PBQP::Matrix* buildInterferenceMatrix(const RegContainer &allowed1, + const RegContainer &allowed2) const; + + /// + /// Expects allowed sets for two potentially coalescable LiveIntervals, + /// and an estimated benefit due to coalescing. The allowed sets should + /// contain only allocable registers from the LiveInterval's register + /// classes, with any interfering pre-colored registers removed. + template + PBQP::Matrix* buildCoalescingMatrix(const RegContainer &allowed1, + const RegContainer &allowed2, + PBQP::PBQPNum cBenefit) const; + + /// \brief Finds coalescing opportunities and returns them as a map. + /// + /// Any entries in the map are guaranteed coalescable, even if their + /// corresponding live intervals overlap. + CoalesceMap findCoalesces(); + + /// \brief Finds the initial set of vreg intervals to allocate. + void findVRegIntervalsToAlloc(); + + /// \brief Constructs a PBQP problem representation of the register + /// allocation problem for this function. + /// + /// @return a PBQP solver object for the register allocation problem. + PBQP::SimpleGraph constructPBQPProblem(); + + /// \brief Adds a stack interval if the given live interval has been + /// spilled. Used to support stack slot coloring. + void addStackInterval(const LiveInterval *spilled,MachineRegisterInfo* mri); + + /// \brief Given a solved PBQP problem maps this solution back to a register + /// assignment. + bool mapPBQPToRegAlloc(const PBQP::Solution &solution); + + /// \brief Postprocessing before final spilling. Sets basic block "live in" + /// variables. + void finalizeAlloc() const; + + }; + + char PBQPRegAlloc::ID = 0; +} + + +template +PBQP::Vector PBQPRegAlloc::buildCostVector(unsigned vReg, + const RegContainer &allowed, + const CoalesceMap &coalesces, + PBQP::PBQPNum spillCost) const { + + typedef typename RegContainer::const_iterator AllowedItr; + + // Allocate vector. Additional element (0th) used for spill option + PBQP::Vector v(allowed.size() + 1, 0); + + v[0] = spillCost; + + // Iterate over the allowed registers inserting coalesce benefits if there + // are any. + unsigned ai = 0; + for (AllowedItr itr = allowed.begin(), end = allowed.end(); + itr != end; ++itr, ++ai) { + + unsigned pReg = *itr; + + CoalesceMap::const_iterator cmItr = + coalesces.find(RegPair(vReg, pReg)); + + // No coalesce - on to the next preg. + if (cmItr == coalesces.end()) + continue; + + // We have a coalesce - insert the benefit. + v[ai + 1] = -cmItr->second; + } + + return v; +} + +template +PBQP::Matrix* PBQPRegAlloc::buildInterferenceMatrix( + const RegContainer &allowed1, const RegContainer &allowed2) const { + + typedef typename RegContainer::const_iterator RegContainerIterator; + + // Construct a PBQP matrix representing the cost of allocation options. The + // rows and columns correspond to the allocation options for the two live + // intervals. Elements will be infinite where corresponding registers alias, + // since we cannot allocate aliasing registers to interfering live intervals. + // All other elements (non-aliasing combinations) will have zero cost. Note + // that the spill option (element 0,0) has zero cost, since we can allocate + // both intervals to memory safely (the cost for each individual allocation + // to memory is accounted for by the cost vectors for each live interval). + PBQP::Matrix *m = + new PBQP::Matrix(allowed1.size() + 1, allowed2.size() + 1, 0); + + // Assume this is a zero matrix until proven otherwise. Zero matrices occur + // between interfering live ranges with non-overlapping register sets (e.g. + // non-overlapping reg classes, or disjoint sets of allowed regs within the + // same class). The term "overlapping" is used advisedly: sets which do not + // intersect, but contain registers which alias, will have non-zero matrices. + // We optimize zero matrices away to improve solver speed. + bool isZeroMatrix = true; + + + // Row index. Starts at 1, since the 0th row is for the spill option, which + // is always zero. + unsigned ri = 1; + + // Iterate over allowed sets, insert infinities where required. + for (RegContainerIterator a1Itr = allowed1.begin(), a1End = allowed1.end(); + a1Itr != a1End; ++a1Itr) { + + // Column index, starts at 1 as for row index. + unsigned ci = 1; + unsigned reg1 = *a1Itr; + + for (RegContainerIterator a2Itr = allowed2.begin(), a2End = allowed2.end(); + a2Itr != a2End; ++a2Itr) { + + unsigned reg2 = *a2Itr; + + // If the row/column regs are identical or alias insert an infinity. + if (tri->regsOverlap(reg1, reg2)) { + (*m)[ri][ci] = std::numeric_limits::infinity(); + isZeroMatrix = false; + } + + ++ci; + } + + ++ri; + } + + // If this turns out to be a zero matrix... + if (isZeroMatrix) { + // free it and return null. + delete m; + return 0; + } + + // ...otherwise return the cost matrix. + return m; +} + +template +PBQP::Matrix* PBQPRegAlloc::buildCoalescingMatrix( + const RegContainer &allowed1, const RegContainer &allowed2, + PBQP::PBQPNum cBenefit) const { + + typedef typename RegContainer::const_iterator RegContainerIterator; + + // Construct a PBQP Matrix representing the benefits of coalescing. As with + // interference matrices the rows and columns represent allowed registers + // for the LiveIntervals which are (potentially) to be coalesced. The amount + // -cBenefit will be placed in any element representing the same register + // for both intervals. + PBQP::Matrix *m = + new PBQP::Matrix(allowed1.size() + 1, allowed2.size() + 1, 0); + + // Reset costs to zero. + m->reset(0); + + // Assume the matrix is zero till proven otherwise. Zero matrices will be + // optimized away as in the interference case. + bool isZeroMatrix = true; + + // Row index. Starts at 1, since the 0th row is for the spill option, which + // is always zero. + unsigned ri = 1; + + // Iterate over the allowed sets, insert coalescing benefits where + // appropriate. + for (RegContainerIterator a1Itr = allowed1.begin(), a1End = allowed1.end(); + a1Itr != a1End; ++a1Itr) { + + // Column index, starts at 1 as for row index. + unsigned ci = 1; + unsigned reg1 = *a1Itr; + + for (RegContainerIterator a2Itr = allowed2.begin(), a2End = allowed2.end(); + a2Itr != a2End; ++a2Itr) { + + // If the row and column represent the same register insert a beneficial + // cost to preference this allocation - it would allow us to eliminate a + // move instruction. + if (reg1 == *a2Itr) { + (*m)[ri][ci] = -cBenefit; + isZeroMatrix = false; + } + + ++ci; + } + + ++ri; + } + + // If this turns out to be a zero matrix... + if (isZeroMatrix) { + // ...free it and return null. + delete m; + return 0; + } + + return m; +} + +PBQPRegAlloc::CoalesceMap PBQPRegAlloc::findCoalesces() { + + typedef MachineFunction::const_iterator MFIterator; + typedef MachineBasicBlock::const_iterator MBBIterator; + typedef LiveInterval::const_vni_iterator VNIIterator; + + CoalesceMap coalescesFound; + + // To find coalesces we need to iterate over the function looking for + // copy instructions. + for (MFIterator bbItr = mf->begin(), bbEnd = mf->end(); + bbItr != bbEnd; ++bbItr) { + + const MachineBasicBlock *mbb = &*bbItr; + + for (MBBIterator iItr = mbb->begin(), iEnd = mbb->end(); + iItr != iEnd; ++iItr) { + + const MachineInstr *instr = &*iItr; + unsigned srcReg, dstReg, srcSubReg, dstSubReg; + + // If this isn't a copy then continue to the next instruction. + if (!tii->isMoveInstr(*instr, srcReg, dstReg, srcSubReg, dstSubReg)) + continue; + + // If the registers are already the same our job is nice and easy. + if (dstReg == srcReg) + continue; + + bool srcRegIsPhysical = TargetRegisterInfo::isPhysicalRegister(srcReg), + dstRegIsPhysical = TargetRegisterInfo::isPhysicalRegister(dstReg); + + // If both registers are physical then we can't coalesce. + if (srcRegIsPhysical && dstRegIsPhysical) + continue; + + // If it's a copy that includes a virtual register but the source and + // destination classes differ then we can't coalesce, so continue with + // the next instruction. + const TargetRegisterClass *srcRegClass = srcRegIsPhysical ? + tri->getPhysicalRegisterRegClass(srcReg) : mri->getRegClass(srcReg); + + const TargetRegisterClass *dstRegClass = dstRegIsPhysical ? + tri->getPhysicalRegisterRegClass(dstReg) : mri->getRegClass(dstReg); + + if (srcRegClass != dstRegClass) + continue; + + // We also need any physical regs to be allocable, coalescing with + // a non-allocable register is invalid. + if (srcRegIsPhysical) { + if (std::find(srcRegClass->allocation_order_begin(*mf), + srcRegClass->allocation_order_end(*mf), srcReg) == + srcRegClass->allocation_order_end(*mf)) + continue; + } + + if (dstRegIsPhysical) { + if (std::find(dstRegClass->allocation_order_begin(*mf), + dstRegClass->allocation_order_end(*mf), dstReg) == + dstRegClass->allocation_order_end(*mf)) + continue; + } + + // If we've made it here we have a copy with compatible register classes. + // We can probably coalesce, but we need to consider overlap. + const LiveInterval *srcLI = &lis->getInterval(srcReg), + *dstLI = &lis->getInterval(dstReg); + + if (srcLI->overlaps(*dstLI)) { + // Even in the case of an overlap we might still be able to coalesce, + // but we need to make sure that no definition of either range occurs + // while the other range is live. + + // Otherwise start by assuming we're ok. + bool badDef = false; + + // Test all defs of the source range. + for (VNIIterator + vniItr = srcLI->vni_begin(), vniEnd = srcLI->vni_end(); + vniItr != vniEnd; ++vniItr) { + + // If we find a def that kills the coalescing opportunity then + // record it and break from the loop. + if (dstLI->liveAt((*vniItr)->def)) { + badDef = true; + break; + } + } + + // If we have a bad def give up, continue to the next instruction. + if (badDef) + continue; + + // Otherwise test definitions of the destination range. + for (VNIIterator + vniItr = dstLI->vni_begin(), vniEnd = dstLI->vni_end(); + vniItr != vniEnd; ++vniItr) { + + // We want to make sure we skip the copy instruction itself. + if ((*vniItr)->getCopy() == instr) + continue; + + if (srcLI->liveAt((*vniItr)->def)) { + badDef = true; + break; + } + } + + // As before a bad def we give up and continue to the next instr. + if (badDef) + continue; + } + + // If we make it to here then either the ranges didn't overlap, or they + // did, but none of their definitions would prevent us from coalescing. + // We're good to go with the coalesce. + + float cBenefit = powf(10.0f, loopInfo->getLoopDepth(mbb)) / 5.0; + + coalescesFound[RegPair(srcReg, dstReg)] = cBenefit; + coalescesFound[RegPair(dstReg, srcReg)] = cBenefit; + } + + } + + return coalescesFound; +} + +void PBQPRegAlloc::findVRegIntervalsToAlloc() { + + // Iterate over all live ranges. + for (LiveIntervals::iterator itr = lis->begin(), end = lis->end(); + itr != end; ++itr) { + + // Ignore physical ones. + if (TargetRegisterInfo::isPhysicalRegister(itr->first)) + continue; + + LiveInterval *li = itr->second; + + // If this live interval is non-empty we will use pbqp to allocate it. + // Empty intervals we allocate in a simple post-processing stage in + // finalizeAlloc. + if (!li->empty()) { + vregIntervalsToAlloc.insert(li); + } + else { + emptyVRegIntervals.insert(li); + } + } +} + +PBQP::SimpleGraph PBQPRegAlloc::constructPBQPProblem() { + + typedef std::vector LIVector; + typedef std::vector RegVector; + typedef std::vector NodeVector; + + // This will store the physical intervals for easy reference. + LIVector physIntervals; + + // Start by clearing the old node <-> live interval mappings & allowed sets + li2Node.clear(); + node2LI.clear(); + allowedSets.clear(); + + // Populate physIntervals, update preg use: + for (LiveIntervals::iterator itr = lis->begin(), end = lis->end(); + itr != end; ++itr) { + + if (TargetRegisterInfo::isPhysicalRegister(itr->first)) { + physIntervals.push_back(itr->second); + mri->setPhysRegUsed(itr->second->reg); + } + } + + // Iterate over vreg intervals, construct live interval <-> node number + // mappings. + for (LiveIntervalSet::const_iterator + itr = vregIntervalsToAlloc.begin(), end = vregIntervalsToAlloc.end(); + itr != end; ++itr) { + const LiveInterval *li = *itr; + + li2Node[li] = node2LI.size(); + node2LI.push_back(li); + } + + // Get the set of potential coalesces. + CoalesceMap coalesces; + + if (pbqpCoalescing) { + coalesces = findCoalesces(); + } + + // Construct a PBQP solver for this problem + PBQP::SimpleGraph problem; + NodeVector problemNodes(vregIntervalsToAlloc.size()); + + // Resize allowedSets container appropriately. + allowedSets.resize(vregIntervalsToAlloc.size()); + + // Iterate over virtual register intervals to compute allowed sets... + for (unsigned node = 0; node < node2LI.size(); ++node) { + + // Grab pointers to the interval and its register class. + const LiveInterval *li = node2LI[node]; + const TargetRegisterClass *liRC = mri->getRegClass(li->reg); + + // Start by assuming all allocable registers in the class are allowed... + RegVector liAllowed(liRC->allocation_order_begin(*mf), + liRC->allocation_order_end(*mf)); + + // Eliminate the physical registers which overlap with this range, along + // with all their aliases. + for (LIVector::iterator pItr = physIntervals.begin(), + pEnd = physIntervals.end(); pItr != pEnd; ++pItr) { + + if (!li->overlaps(**pItr)) + continue; + + unsigned pReg = (*pItr)->reg; + + // If we get here then the live intervals overlap, but we're still ok + // if they're coalescable. + if (coalesces.find(RegPair(li->reg, pReg)) != coalesces.end()) + continue; + + // If we get here then we have a genuine exclusion. + + // Remove the overlapping reg... + RegVector::iterator eraseItr = + std::find(liAllowed.begin(), liAllowed.end(), pReg); + + if (eraseItr != liAllowed.end()) + liAllowed.erase(eraseItr); + + const unsigned *aliasItr = tri->getAliasSet(pReg); + + if (aliasItr != 0) { + // ...and its aliases. + for (; *aliasItr != 0; ++aliasItr) { + RegVector::iterator eraseItr = + std::find(liAllowed.begin(), liAllowed.end(), *aliasItr); + + if (eraseItr != liAllowed.end()) { + liAllowed.erase(eraseItr); + } + } + } + } + + // Copy the allowed set into a member vector for use when constructing cost + // vectors & matrices, and mapping PBQP solutions back to assignments. + allowedSets[node] = AllowedSet(liAllowed.begin(), liAllowed.end()); + + // Set the spill cost to the interval weight, or epsilon if the + // interval weight is zero + PBQP::PBQPNum spillCost = (li->weight != 0.0) ? + li->weight : std::numeric_limits::min(); + + // Build a cost vector for this interval. + problemNodes[node] = + problem.addNode( + buildCostVector(li->reg, allowedSets[node], coalesces, spillCost)); + + } + + + // Now add the cost matrices... + for (unsigned node1 = 0; node1 < node2LI.size(); ++node1) { + const LiveInterval *li = node2LI[node1]; + + // Test for live range overlaps and insert interference matrices. + for (unsigned node2 = node1 + 1; node2 < node2LI.size(); ++node2) { + const LiveInterval *li2 = node2LI[node2]; + + CoalesceMap::const_iterator cmItr = + coalesces.find(RegPair(li->reg, li2->reg)); + + PBQP::Matrix *m = 0; + + if (cmItr != coalesces.end()) { + m = buildCoalescingMatrix(allowedSets[node1], allowedSets[node2], + cmItr->second); + } + else if (li->overlaps(*li2)) { + m = buildInterferenceMatrix(allowedSets[node1], allowedSets[node2]); + } + + if (m != 0) { + problem.addEdge(problemNodes[node1], + problemNodes[node2], + *m); + + delete m; + } + } + } + + problem.assignNodeIDs(); + + assert(problem.getNumNodes() == allowedSets.size()); + for (unsigned i = 0; i < allowedSets.size(); ++i) { + assert(problem.getNodeItr(i) == problemNodes[i]); + } +/* + std::cerr << "Allocating for " << problem.getNumNodes() << " nodes, " + << problem.getNumEdges() << " edges.\n"; + + problem.printDot(std::cerr); +*/ + // We're done, PBQP problem constructed - return it. + return problem; +} + +void PBQPRegAlloc::addStackInterval(const LiveInterval *spilled, + MachineRegisterInfo* mri) { + int stackSlot = vrm->getStackSlot(spilled->reg); + + if (stackSlot == VirtRegMap::NO_STACK_SLOT) + return; + + const TargetRegisterClass *RC = mri->getRegClass(spilled->reg); + LiveInterval &stackInterval = lss->getOrCreateInterval(stackSlot, RC); + + VNInfo *vni; + if (stackInterval.getNumValNums() != 0) + vni = stackInterval.getValNumInfo(0); + else + vni = stackInterval.getNextValue( + SlotIndex(), 0, false, lss->getVNInfoAllocator()); + + LiveInterval &rhsInterval = lis->getInterval(spilled->reg); + stackInterval.MergeRangesInAsValue(rhsInterval, vni); +} + +bool PBQPRegAlloc::mapPBQPToRegAlloc(const PBQP::Solution &solution) { + + // Assert that this is a valid solution to the regalloc problem. + assert(solution.getCost() != std::numeric_limits::infinity() && + "Invalid (infinite cost) solution for PBQP problem."); + + // Set to true if we have any spills + bool anotherRoundNeeded = false; + + // Clear the existing allocation. + vrm->clearAllVirt(); + + // Iterate over the nodes mapping the PBQP solution to a register assignment. + for (unsigned node = 0; node < node2LI.size(); ++node) { + unsigned virtReg = node2LI[node]->reg, + allocSelection = solution.getSelection(node); + + + // If the PBQP solution is non-zero it's a physical register... + if (allocSelection != 0) { + // Get the physical reg, subtracting 1 to account for the spill option. + unsigned physReg = allowedSets[node][allocSelection - 1]; + + DEBUG(errs() << "VREG " << virtReg << " -> " + << tri->getName(physReg) << "\n"); + + assert(physReg != 0); + + // Add to the virt reg map and update the used phys regs. + vrm->assignVirt2Phys(virtReg, physReg); + } + // ...Otherwise it's a spill. + else { + + // Make sure we ignore this virtual reg on the next round + // of allocation + vregIntervalsToAlloc.erase(&lis->getInterval(virtReg)); + + // Insert spill ranges for this live range + const LiveInterval *spillInterval = node2LI[node]; + double oldSpillWeight = spillInterval->weight; + SmallVector spillIs; + std::vector newSpills = + lis->addIntervalsForSpills(*spillInterval, spillIs, loopInfo, *vrm); + addStackInterval(spillInterval, mri); + + (void) oldSpillWeight; + DEBUG(errs() << "VREG " << virtReg << " -> SPILLED (Cost: " + << oldSpillWeight << ", New vregs: "); + + // Copy any newly inserted live intervals into the list of regs to + // allocate. + for (std::vector::const_iterator + itr = newSpills.begin(), end = newSpills.end(); + itr != end; ++itr) { + + assert(!(*itr)->empty() && "Empty spill range."); + + DEBUG(errs() << (*itr)->reg << " "); + + vregIntervalsToAlloc.insert(*itr); + } + + DEBUG(errs() << ")\n"); + + // We need another round if spill intervals were added. + anotherRoundNeeded |= !newSpills.empty(); + } + } + + return !anotherRoundNeeded; +} + +void PBQPRegAlloc::finalizeAlloc() const { + typedef LiveIntervals::iterator LIIterator; + typedef LiveInterval::Ranges::const_iterator LRIterator; + + // First allocate registers for the empty intervals. + for (LiveIntervalSet::const_iterator + itr = emptyVRegIntervals.begin(), end = emptyVRegIntervals.end(); + itr != end; ++itr) { + LiveInterval *li = *itr; + + unsigned physReg = vrm->getRegAllocPref(li->reg); + + if (physReg == 0) { + const TargetRegisterClass *liRC = mri->getRegClass(li->reg); + physReg = *liRC->allocation_order_begin(*mf); + } + + vrm->assignVirt2Phys(li->reg, physReg); + } + + // Finally iterate over the basic blocks to compute and set the live-in sets. + SmallVector liveInMBBs; + MachineBasicBlock *entryMBB = &*mf->begin(); + + for (LIIterator liItr = lis->begin(), liEnd = lis->end(); + liItr != liEnd; ++liItr) { + + const LiveInterval *li = liItr->second; + unsigned reg = 0; + + // Get the physical register for this interval + if (TargetRegisterInfo::isPhysicalRegister(li->reg)) { + reg = li->reg; + } + else if (vrm->isAssignedReg(li->reg)) { + reg = vrm->getPhys(li->reg); + } + else { + // Ranges which are assigned a stack slot only are ignored. + continue; + } + + if (reg == 0) { + // Filter out zero regs - they're for intervals that were spilled. + continue; + } + + // Iterate over the ranges of the current interval... + for (LRIterator lrItr = li->begin(), lrEnd = li->end(); + lrItr != lrEnd; ++lrItr) { + + // Find the set of basic blocks which this range is live into... + if (lis->findLiveInMBBs(lrItr->start, lrItr->end, liveInMBBs)) { + // And add the physreg for this interval to their live-in sets. + for (unsigned i = 0; i < liveInMBBs.size(); ++i) { + if (liveInMBBs[i] != entryMBB) { + if (!liveInMBBs[i]->isLiveIn(reg)) { + liveInMBBs[i]->addLiveIn(reg); + } + } + } + liveInMBBs.clear(); + } + } + } + +} + +bool PBQPRegAlloc::runOnMachineFunction(MachineFunction &MF) { + + mf = &MF; + tm = &mf->getTarget(); + tri = tm->getRegisterInfo(); + tii = tm->getInstrInfo(); + mri = &mf->getRegInfo(); + + lis = &getAnalysis(); + lss = &getAnalysis(); + loopInfo = &getAnalysis(); + + vrm = &getAnalysis(); + + DEBUG(errs() << "PBQP2 Register Allocating for " << mf->getFunction()->getName() << "\n"); + + // Allocator main loop: + // + // * Map current regalloc problem to a PBQP problem + // * Solve the PBQP problem + // * Map the solution back to a register allocation + // * Spill if necessary + // + // This process is continued till no more spills are generated. + + // Find the vreg intervals in need of allocation. + findVRegIntervalsToAlloc(); + + // If there aren't any then we're done here. + if (vregIntervalsToAlloc.empty() && emptyVRegIntervals.empty()) + return true; + + // If there are non-empty intervals allocate them using pbqp. + if (!vregIntervalsToAlloc.empty()) { + + bool pbqpAllocComplete = false; + unsigned round = 0; + + while (!pbqpAllocComplete) { + DEBUG(errs() << " PBQP Regalloc round " << round << ":\n"); + + PBQP::SimpleGraph problem = constructPBQPProblem(); + PBQP::HeuristicSolver solver; + problem.assignNodeIDs(); + PBQP::Solution solution = solver.solve(problem); + + pbqpAllocComplete = mapPBQPToRegAlloc(solution); + + ++round; + } + } + + // Finalise allocation, allocate empty ranges. + finalizeAlloc(); + + vregIntervalsToAlloc.clear(); + emptyVRegIntervals.clear(); + li2Node.clear(); + node2LI.clear(); + allowedSets.clear(); + + DEBUG(errs() << "Post alloc VirtRegMap:\n" << *vrm << "\n"); + + // Run rewriter + std::auto_ptr rewriter(createVirtRegRewriter()); + + rewriter->runOnMachineFunction(*mf, *vrm, lis); + + return true; +} + +FunctionPass* llvm::createPBQPRegisterAllocator() { + return new PBQPRegAlloc(); +} + + +#undef DEBUG_TYPE diff --git a/libclamav/c++/llvm/lib/CodeGen/RegisterCoalescer.cpp b/libclamav/c++/llvm/lib/CodeGen/RegisterCoalescer.cpp new file mode 100644 index 000000000..1131e3db4 --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/RegisterCoalescer.cpp @@ -0,0 +1,41 @@ +//===- RegisterCoalescer.cpp - Generic Register Coalescing Interface -------==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the generic RegisterCoalescer interface which +// is used as the common interface used by all clients and +// implementations of register coalescing. +// +//===----------------------------------------------------------------------===// + +#include "llvm/CodeGen/RegisterCoalescer.h" +#include "llvm/CodeGen/LiveIntervalAnalysis.h" +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Pass.h" + +using namespace llvm; + +// Register the RegisterCoalescer interface, providing a nice name to refer to. +static RegisterAnalysisGroup Z("Register Coalescer"); +char RegisterCoalescer::ID = 0; + +// RegisterCoalescer destructor: DO NOT move this to the header file +// for RegisterCoalescer or else clients of the RegisterCoalescer +// class may not depend on the RegisterCoalescer.o file in the current +// .a file, causing alias analysis support to not be included in the +// tool correctly! +// +RegisterCoalescer::~RegisterCoalescer() {} + +// Because of the way .a files work, we must force the SimpleRC +// implementation to be pulled in if the RegisterCoalescer classes are +// pulled in. Otherwise we run the risk of RegisterCoalescer being +// used, but the default implementation not being linked into the tool +// that uses it. +DEFINING_FILE_FOR(RegisterCoalescer) diff --git a/libclamav/c++/llvm/lib/CodeGen/RegisterScavenging.cpp b/libclamav/c++/llvm/lib/CodeGen/RegisterScavenging.cpp new file mode 100644 index 000000000..94680ed29 --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/RegisterScavenging.cpp @@ -0,0 +1,360 @@ +//===-- RegisterScavenging.cpp - Machine register scavenging --------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the machine register scavenger. It can provide +// information, such as unused registers, at any point in a machine basic block. +// It also provides a mechanism to make registers available by evicting them to +// spill slots. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "reg-scavenging" +#include "llvm/CodeGen/RegisterScavenging.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineBasicBlock.h" +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/STLExtras.h" +using namespace llvm; + +/// setUsed - Set the register and its sub-registers as being used. +void RegScavenger::setUsed(unsigned Reg) { + RegsAvailable.reset(Reg); + + for (const unsigned *SubRegs = TRI->getSubRegisters(Reg); + unsigned SubReg = *SubRegs; ++SubRegs) + RegsAvailable.reset(SubReg); +} + +bool RegScavenger::isAliasUsed(unsigned Reg) const { + if (isUsed(Reg)) + return true; + for (const unsigned *R = TRI->getAliasSet(Reg); *R; ++R) + if (isUsed(*R)) + return true; + return false; +} + +void RegScavenger::initRegState() { + ScavengedReg = 0; + ScavengedRC = NULL; + ScavengeRestore = NULL; + + // All registers started out unused. + RegsAvailable.set(); + + // Reserved registers are always used. + RegsAvailable ^= ReservedRegs; + + if (!MBB) + return; + + // Live-in registers are in use. + for (MachineBasicBlock::const_livein_iterator I = MBB->livein_begin(), + E = MBB->livein_end(); I != E; ++I) + setUsed(*I); + + // Pristine CSRs are also unavailable. + BitVector PR = MBB->getParent()->getFrameInfo()->getPristineRegs(MBB); + for (int I = PR.find_first(); I>0; I = PR.find_next(I)) + setUsed(I); +} + +void RegScavenger::enterBasicBlock(MachineBasicBlock *mbb) { + MachineFunction &MF = *mbb->getParent(); + const TargetMachine &TM = MF.getTarget(); + TII = TM.getInstrInfo(); + TRI = TM.getRegisterInfo(); + MRI = &MF.getRegInfo(); + + assert((NumPhysRegs == 0 || NumPhysRegs == TRI->getNumRegs()) && + "Target changed?"); + + // Self-initialize. + if (!MBB) { + NumPhysRegs = TRI->getNumRegs(); + RegsAvailable.resize(NumPhysRegs); + + // Create reserved registers bitvector. + ReservedRegs = TRI->getReservedRegs(MF); + + // Create callee-saved registers bitvector. + CalleeSavedRegs.resize(NumPhysRegs); + const unsigned *CSRegs = TRI->getCalleeSavedRegs(); + if (CSRegs != NULL) + for (unsigned i = 0; CSRegs[i]; ++i) + CalleeSavedRegs.set(CSRegs[i]); + } + + MBB = mbb; + initRegState(); + + Tracking = false; +} + +void RegScavenger::addRegWithSubRegs(BitVector &BV, unsigned Reg) { + BV.set(Reg); + for (const unsigned *R = TRI->getSubRegisters(Reg); *R; R++) + BV.set(*R); +} + +void RegScavenger::addRegWithAliases(BitVector &BV, unsigned Reg) { + BV.set(Reg); + for (const unsigned *R = TRI->getAliasSet(Reg); *R; R++) + BV.set(*R); +} + +void RegScavenger::forward() { + // Move ptr forward. + if (!Tracking) { + MBBI = MBB->begin(); + Tracking = true; + } else { + assert(MBBI != MBB->end() && "Already at the end of the basic block!"); + MBBI = next(MBBI); + } + + MachineInstr *MI = MBBI; + + if (MI == ScavengeRestore) { + ScavengedReg = 0; + ScavengedRC = NULL; + ScavengeRestore = NULL; + } + + // Find out which registers are early clobbered, killed, defined, and marked + // def-dead in this instruction. + BitVector EarlyClobberRegs(NumPhysRegs); + BitVector KillRegs(NumPhysRegs); + BitVector DefRegs(NumPhysRegs); + BitVector DeadRegs(NumPhysRegs); + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + const MachineOperand &MO = MI->getOperand(i); + if (!MO.isReg() || MO.isUndef()) + continue; + unsigned Reg = MO.getReg(); + if (!Reg || isReserved(Reg)) + continue; + + if (MO.isUse()) { + // Two-address operands implicitly kill. + if (MO.isKill() || MI->isRegTiedToDefOperand(i)) + addRegWithSubRegs(KillRegs, Reg); + } else { + assert(MO.isDef()); + if (MO.isDead()) + addRegWithSubRegs(DeadRegs, Reg); + else + addRegWithSubRegs(DefRegs, Reg); + if (MO.isEarlyClobber()) + addRegWithAliases(EarlyClobberRegs, Reg); + } + } + + // Verify uses and defs. + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + const MachineOperand &MO = MI->getOperand(i); + if (!MO.isReg() || MO.isUndef()) + continue; + unsigned Reg = MO.getReg(); + if (!Reg || isReserved(Reg)) + continue; + if (MO.isUse()) { + if (!isUsed(Reg)) { + // Check if it's partial live: e.g. + // D0 = insert_subreg D0, S0 + // ... D0 + // The problem is the insert_subreg could be eliminated. The use of + // D0 is using a partially undef value. This is not *incorrect* since + // S1 is can be freely clobbered. + // Ideally we would like a way to model this, but leaving the + // insert_subreg around causes both correctness and performance issues. + bool SubUsed = false; + for (const unsigned *SubRegs = TRI->getSubRegisters(Reg); + unsigned SubReg = *SubRegs; ++SubRegs) + if (isUsed(SubReg)) { + SubUsed = true; + break; + } + assert(SubUsed && "Using an undefined register!"); + } + assert((!EarlyClobberRegs.test(Reg) || MI->isRegTiedToDefOperand(i)) && + "Using an early clobbered register!"); + } else { + assert(MO.isDef()); +#if 0 + // FIXME: Enable this once we've figured out how to correctly transfer + // implicit kills during codegen passes like the coalescer. + assert((KillRegs.test(Reg) || isUnused(Reg) || + isLiveInButUnusedBefore(Reg, MI, MBB, TRI, MRI)) && + "Re-defining a live register!"); +#endif + } + } + + // Commit the changes. + setUnused(KillRegs); + setUnused(DeadRegs); + setUsed(DefRegs); +} + +void RegScavenger::getRegsUsed(BitVector &used, bool includeReserved) { + if (includeReserved) + used = ~RegsAvailable; + else + used = ~RegsAvailable & ~ReservedRegs; +} + +/// CreateRegClassMask - Set the bits that represent the registers in the +/// TargetRegisterClass. +static void CreateRegClassMask(const TargetRegisterClass *RC, BitVector &Mask) { + for (TargetRegisterClass::iterator I = RC->begin(), E = RC->end(); I != E; + ++I) + Mask.set(*I); +} + +unsigned RegScavenger::FindUnusedReg(const TargetRegisterClass *RC) const { + for (TargetRegisterClass::iterator I = RC->begin(), E = RC->end(); + I != E; ++I) + if (!isAliasUsed(*I)) + return *I; + return 0; +} + +/// findSurvivorReg - Return the candidate register that is unused for the +/// longest after MBBI. UseMI is set to the instruction where the search +/// stopped. +/// +/// No more than InstrLimit instructions are inspected. +/// +unsigned RegScavenger::findSurvivorReg(MachineBasicBlock::iterator StartMI, + BitVector &Candidates, + unsigned InstrLimit, + MachineBasicBlock::iterator &UseMI) { + int Survivor = Candidates.find_first(); + assert(Survivor > 0 && "No candidates for scavenging"); + + MachineBasicBlock::iterator ME = MBB->getFirstTerminator(); + assert(StartMI != ME && "MI already at terminator"); + MachineBasicBlock::iterator RestorePointMI = StartMI; + MachineBasicBlock::iterator MI = StartMI; + + bool inVirtLiveRange = false; + for (++MI; InstrLimit > 0 && MI != ME; ++MI, --InstrLimit) { + bool isVirtKillInsn = false; + bool isVirtDefInsn = false; + // Remove any candidates touched by instruction. + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + const MachineOperand &MO = MI->getOperand(i); + if (!MO.isReg() || MO.isUndef() || !MO.getReg()) + continue; + if (TargetRegisterInfo::isVirtualRegister(MO.getReg())) { + if (MO.isDef()) + isVirtDefInsn = true; + else if (MO.isKill()) + isVirtKillInsn = true; + continue; + } + Candidates.reset(MO.getReg()); + for (const unsigned *R = TRI->getAliasSet(MO.getReg()); *R; R++) + Candidates.reset(*R); + } + // If we're not in a virtual reg's live range, this is a valid + // restore point. + if (!inVirtLiveRange) RestorePointMI = MI; + + // Update whether we're in the live range of a virtual register + if (isVirtKillInsn) inVirtLiveRange = false; + if (isVirtDefInsn) inVirtLiveRange = true; + + // Was our survivor untouched by this instruction? + if (Candidates.test(Survivor)) + continue; + + // All candidates gone? + if (Candidates.none()) + break; + + Survivor = Candidates.find_first(); + } + // If we ran off the end, that's where we want to restore. + if (MI == ME) RestorePointMI = ME; + assert (RestorePointMI != StartMI && + "No available scavenger restore location!"); + + // We ran out of candidates, so stop the search. + UseMI = RestorePointMI; + return Survivor; +} + +unsigned RegScavenger::scavengeRegister(const TargetRegisterClass *RC, + MachineBasicBlock::iterator I, + int SPAdj) { + // Mask off the registers which are not in the TargetRegisterClass. + BitVector Candidates(NumPhysRegs, false); + CreateRegClassMask(RC, Candidates); + // Do not include reserved registers. + Candidates ^= ReservedRegs & Candidates; + + // Exclude all the registers being used by the instruction. + for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i) { + MachineOperand &MO = I->getOperand(i); + if (MO.isReg() && MO.getReg() != 0 && + !TargetRegisterInfo::isVirtualRegister(MO.getReg())) + Candidates.reset(MO.getReg()); + } + + // Find the register whose use is furthest away. + MachineBasicBlock::iterator UseMI; + unsigned SReg = findSurvivorReg(I, Candidates, 25, UseMI); + + // If we found an unused register there is no reason to spill it. We have + // probably found a callee-saved register that has been saved in the + // prologue, but happens to be unused at this point. + if (!isAliasUsed(SReg)) + return SReg; + + assert(ScavengedReg == 0 && + "Scavenger slot is live, unable to scavenge another register!"); + + // Avoid infinite regress + ScavengedReg = SReg; + + // If the target knows how to save/restore the register, let it do so; + // otherwise, use the emergency stack spill slot. + if (!TRI->saveScavengerRegister(*MBB, I, UseMI, RC, SReg)) { + // Spill the scavenged register before I. + assert(ScavengingFrameIndex >= 0 && + "Cannot scavenge register without an emergency spill slot!"); + TII->storeRegToStackSlot(*MBB, I, SReg, true, ScavengingFrameIndex, RC); + MachineBasicBlock::iterator II = prior(I); + TRI->eliminateFrameIndex(II, SPAdj, NULL, this); + + // Restore the scavenged register before its use (or first terminator). + TII->loadRegFromStackSlot(*MBB, UseMI, SReg, ScavengingFrameIndex, RC); + II = prior(UseMI); + TRI->eliminateFrameIndex(II, SPAdj, NULL, this); + } + + ScavengeRestore = prior(UseMI); + + // Doing this here leads to infinite regress. + // ScavengedReg = SReg; + ScavengedRC = RC; + + return SReg; +} diff --git a/libclamav/c++/llvm/lib/CodeGen/ScheduleDAG.cpp b/libclamav/c++/llvm/lib/CodeGen/ScheduleDAG.cpp new file mode 100644 index 000000000..71693d21c --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/ScheduleDAG.cpp @@ -0,0 +1,589 @@ +//===---- ScheduleDAG.cpp - Implement the ScheduleDAG class ---------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This implements the ScheduleDAG class, which is a base class used by +// scheduling implementation classes. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "pre-RA-sched" +#include "llvm/CodeGen/ScheduleDAG.h" +#include "llvm/CodeGen/ScheduleHazardRecognizer.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" +#include +using namespace llvm; + +ScheduleDAG::ScheduleDAG(MachineFunction &mf) + : TM(mf.getTarget()), + TII(TM.getInstrInfo()), + TRI(TM.getRegisterInfo()), + TLI(TM.getTargetLowering()), + MF(mf), MRI(mf.getRegInfo()), + ConstPool(MF.getConstantPool()), + EntrySU(), ExitSU() { +} + +ScheduleDAG::~ScheduleDAG() {} + +/// dump - dump the schedule. +void ScheduleDAG::dumpSchedule() const { + for (unsigned i = 0, e = Sequence.size(); i != e; i++) { + if (SUnit *SU = Sequence[i]) + SU->dump(this); + else + errs() << "**** NOOP ****\n"; + } +} + + +/// Run - perform scheduling. +/// +void ScheduleDAG::Run(MachineBasicBlock *bb, + MachineBasicBlock::iterator insertPos) { + BB = bb; + InsertPos = insertPos; + + SUnits.clear(); + Sequence.clear(); + EntrySU = SUnit(); + ExitSU = SUnit(); + + Schedule(); + + DEBUG({ + errs() << "*** Final schedule ***\n"; + dumpSchedule(); + errs() << '\n'; + }); +} + +/// addPred - This adds the specified edge as a pred of the current node if +/// not already. It also adds the current node as a successor of the +/// specified node. +void SUnit::addPred(const SDep &D) { + // If this node already has this depenence, don't add a redundant one. + for (SmallVector::const_iterator I = Preds.begin(), E = Preds.end(); + I != E; ++I) + if (*I == D) + return; + // Now add a corresponding succ to N. + SDep P = D; + P.setSUnit(this); + SUnit *N = D.getSUnit(); + // Update the bookkeeping. + if (D.getKind() == SDep::Data) { + assert(NumPreds < UINT_MAX && "NumPreds will overflow!"); + assert(N->NumSuccs < UINT_MAX && "NumSuccs will overflow!"); + ++NumPreds; + ++N->NumSuccs; + } + if (!N->isScheduled) { + assert(NumPredsLeft < UINT_MAX && "NumPredsLeft will overflow!"); + ++NumPredsLeft; + } + if (!isScheduled) { + assert(N->NumSuccsLeft < UINT_MAX && "NumSuccsLeft will overflow!"); + ++N->NumSuccsLeft; + } + Preds.push_back(D); + N->Succs.push_back(P); + if (P.getLatency() != 0) { + this->setDepthDirty(); + N->setHeightDirty(); + } +} + +/// removePred - This removes the specified edge as a pred of the current +/// node if it exists. It also removes the current node as a successor of +/// the specified node. +void SUnit::removePred(const SDep &D) { + // Find the matching predecessor. + for (SmallVector::iterator I = Preds.begin(), E = Preds.end(); + I != E; ++I) + if (*I == D) { + bool FoundSucc = false; + // Find the corresponding successor in N. + SDep P = D; + P.setSUnit(this); + SUnit *N = D.getSUnit(); + for (SmallVector::iterator II = N->Succs.begin(), + EE = N->Succs.end(); II != EE; ++II) + if (*II == P) { + FoundSucc = true; + N->Succs.erase(II); + break; + } + assert(FoundSucc && "Mismatching preds / succs lists!"); + Preds.erase(I); + // Update the bookkeeping. + if (P.getKind() == SDep::Data) { + assert(NumPreds > 0 && "NumPreds will underflow!"); + assert(N->NumSuccs > 0 && "NumSuccs will underflow!"); + --NumPreds; + --N->NumSuccs; + } + if (!N->isScheduled) { + assert(NumPredsLeft > 0 && "NumPredsLeft will underflow!"); + --NumPredsLeft; + } + if (!isScheduled) { + assert(N->NumSuccsLeft > 0 && "NumSuccsLeft will underflow!"); + --N->NumSuccsLeft; + } + if (P.getLatency() != 0) { + this->setDepthDirty(); + N->setHeightDirty(); + } + return; + } +} + +void SUnit::setDepthDirty() { + if (!isDepthCurrent) return; + SmallVector WorkList; + WorkList.push_back(this); + do { + SUnit *SU = WorkList.pop_back_val(); + SU->isDepthCurrent = false; + for (SUnit::const_succ_iterator I = SU->Succs.begin(), + E = SU->Succs.end(); I != E; ++I) { + SUnit *SuccSU = I->getSUnit(); + if (SuccSU->isDepthCurrent) + WorkList.push_back(SuccSU); + } + } while (!WorkList.empty()); +} + +void SUnit::setHeightDirty() { + if (!isHeightCurrent) return; + SmallVector WorkList; + WorkList.push_back(this); + do { + SUnit *SU = WorkList.pop_back_val(); + SU->isHeightCurrent = false; + for (SUnit::const_pred_iterator I = SU->Preds.begin(), + E = SU->Preds.end(); I != E; ++I) { + SUnit *PredSU = I->getSUnit(); + if (PredSU->isHeightCurrent) + WorkList.push_back(PredSU); + } + } while (!WorkList.empty()); +} + +/// setDepthToAtLeast - Update this node's successors to reflect the +/// fact that this node's depth just increased. +/// +void SUnit::setDepthToAtLeast(unsigned NewDepth) { + if (NewDepth <= getDepth()) + return; + setDepthDirty(); + Depth = NewDepth; + isDepthCurrent = true; +} + +/// setHeightToAtLeast - Update this node's predecessors to reflect the +/// fact that this node's height just increased. +/// +void SUnit::setHeightToAtLeast(unsigned NewHeight) { + if (NewHeight <= getHeight()) + return; + setHeightDirty(); + Height = NewHeight; + isHeightCurrent = true; +} + +/// ComputeDepth - Calculate the maximal path from the node to the exit. +/// +void SUnit::ComputeDepth() { + SmallVector WorkList; + WorkList.push_back(this); + do { + SUnit *Cur = WorkList.back(); + + bool Done = true; + unsigned MaxPredDepth = 0; + for (SUnit::const_pred_iterator I = Cur->Preds.begin(), + E = Cur->Preds.end(); I != E; ++I) { + SUnit *PredSU = I->getSUnit(); + if (PredSU->isDepthCurrent) + MaxPredDepth = std::max(MaxPredDepth, + PredSU->Depth + I->getLatency()); + else { + Done = false; + WorkList.push_back(PredSU); + } + } + + if (Done) { + WorkList.pop_back(); + if (MaxPredDepth != Cur->Depth) { + Cur->setDepthDirty(); + Cur->Depth = MaxPredDepth; + } + Cur->isDepthCurrent = true; + } + } while (!WorkList.empty()); +} + +/// ComputeHeight - Calculate the maximal path from the node to the entry. +/// +void SUnit::ComputeHeight() { + SmallVector WorkList; + WorkList.push_back(this); + do { + SUnit *Cur = WorkList.back(); + + bool Done = true; + unsigned MaxSuccHeight = 0; + for (SUnit::const_succ_iterator I = Cur->Succs.begin(), + E = Cur->Succs.end(); I != E; ++I) { + SUnit *SuccSU = I->getSUnit(); + if (SuccSU->isHeightCurrent) + MaxSuccHeight = std::max(MaxSuccHeight, + SuccSU->Height + I->getLatency()); + else { + Done = false; + WorkList.push_back(SuccSU); + } + } + + if (Done) { + WorkList.pop_back(); + if (MaxSuccHeight != Cur->Height) { + Cur->setHeightDirty(); + Cur->Height = MaxSuccHeight; + } + Cur->isHeightCurrent = true; + } + } while (!WorkList.empty()); +} + +/// SUnit - Scheduling unit. It's an wrapper around either a single SDNode or +/// a group of nodes flagged together. +void SUnit::dump(const ScheduleDAG *G) const { + errs() << "SU(" << NodeNum << "): "; + G->dumpNode(this); +} + +void SUnit::dumpAll(const ScheduleDAG *G) const { + dump(G); + + errs() << " # preds left : " << NumPredsLeft << "\n"; + errs() << " # succs left : " << NumSuccsLeft << "\n"; + errs() << " Latency : " << Latency << "\n"; + errs() << " Depth : " << Depth << "\n"; + errs() << " Height : " << Height << "\n"; + + if (Preds.size() != 0) { + errs() << " Predecessors:\n"; + for (SUnit::const_succ_iterator I = Preds.begin(), E = Preds.end(); + I != E; ++I) { + errs() << " "; + switch (I->getKind()) { + case SDep::Data: errs() << "val "; break; + case SDep::Anti: errs() << "anti"; break; + case SDep::Output: errs() << "out "; break; + case SDep::Order: errs() << "ch "; break; + } + errs() << "#"; + errs() << I->getSUnit() << " - SU(" << I->getSUnit()->NodeNum << ")"; + if (I->isArtificial()) + errs() << " *"; + errs() << ": Latency=" << I->getLatency(); + errs() << "\n"; + } + } + if (Succs.size() != 0) { + errs() << " Successors:\n"; + for (SUnit::const_succ_iterator I = Succs.begin(), E = Succs.end(); + I != E; ++I) { + errs() << " "; + switch (I->getKind()) { + case SDep::Data: errs() << "val "; break; + case SDep::Anti: errs() << "anti"; break; + case SDep::Output: errs() << "out "; break; + case SDep::Order: errs() << "ch "; break; + } + errs() << "#"; + errs() << I->getSUnit() << " - SU(" << I->getSUnit()->NodeNum << ")"; + if (I->isArtificial()) + errs() << " *"; + errs() << ": Latency=" << I->getLatency(); + errs() << "\n"; + } + } + errs() << "\n"; +} + +#ifndef NDEBUG +/// VerifySchedule - Verify that all SUnits were scheduled and that +/// their state is consistent. +/// +void ScheduleDAG::VerifySchedule(bool isBottomUp) { + bool AnyNotSched = false; + unsigned DeadNodes = 0; + unsigned Noops = 0; + for (unsigned i = 0, e = SUnits.size(); i != e; ++i) { + if (!SUnits[i].isScheduled) { + if (SUnits[i].NumPreds == 0 && SUnits[i].NumSuccs == 0) { + ++DeadNodes; + continue; + } + if (!AnyNotSched) + errs() << "*** Scheduling failed! ***\n"; + SUnits[i].dump(this); + errs() << "has not been scheduled!\n"; + AnyNotSched = true; + } + if (SUnits[i].isScheduled && + (isBottomUp ? SUnits[i].getHeight() : SUnits[i].getDepth()) > + unsigned(INT_MAX)) { + if (!AnyNotSched) + errs() << "*** Scheduling failed! ***\n"; + SUnits[i].dump(this); + errs() << "has an unexpected " + << (isBottomUp ? "Height" : "Depth") << " value!\n"; + AnyNotSched = true; + } + if (isBottomUp) { + if (SUnits[i].NumSuccsLeft != 0) { + if (!AnyNotSched) + errs() << "*** Scheduling failed! ***\n"; + SUnits[i].dump(this); + errs() << "has successors left!\n"; + AnyNotSched = true; + } + } else { + if (SUnits[i].NumPredsLeft != 0) { + if (!AnyNotSched) + errs() << "*** Scheduling failed! ***\n"; + SUnits[i].dump(this); + errs() << "has predecessors left!\n"; + AnyNotSched = true; + } + } + } + for (unsigned i = 0, e = Sequence.size(); i != e; ++i) + if (!Sequence[i]) + ++Noops; + assert(!AnyNotSched); + assert(Sequence.size() + DeadNodes - Noops == SUnits.size() && + "The number of nodes scheduled doesn't match the expected number!"); +} +#endif + +/// InitDAGTopologicalSorting - create the initial topological +/// ordering from the DAG to be scheduled. +/// +/// The idea of the algorithm is taken from +/// "Online algorithms for managing the topological order of +/// a directed acyclic graph" by David J. Pearce and Paul H.J. Kelly +/// This is the MNR algorithm, which was first introduced by +/// A. Marchetti-Spaccamela, U. Nanni and H. Rohnert in +/// "Maintaining a topological order under edge insertions". +/// +/// Short description of the algorithm: +/// +/// Topological ordering, ord, of a DAG maps each node to a topological +/// index so that for all edges X->Y it is the case that ord(X) < ord(Y). +/// +/// This means that if there is a path from the node X to the node Z, +/// then ord(X) < ord(Z). +/// +/// This property can be used to check for reachability of nodes: +/// if Z is reachable from X, then an insertion of the edge Z->X would +/// create a cycle. +/// +/// The algorithm first computes a topological ordering for the DAG by +/// initializing the Index2Node and Node2Index arrays and then tries to keep +/// the ordering up-to-date after edge insertions by reordering the DAG. +/// +/// On insertion of the edge X->Y, the algorithm first marks by calling DFS +/// the nodes reachable from Y, and then shifts them using Shift to lie +/// immediately after X in Index2Node. +void ScheduleDAGTopologicalSort::InitDAGTopologicalSorting() { + unsigned DAGSize = SUnits.size(); + std::vector WorkList; + WorkList.reserve(DAGSize); + + Index2Node.resize(DAGSize); + Node2Index.resize(DAGSize); + + // Initialize the data structures. + for (unsigned i = 0, e = DAGSize; i != e; ++i) { + SUnit *SU = &SUnits[i]; + int NodeNum = SU->NodeNum; + unsigned Degree = SU->Succs.size(); + // Temporarily use the Node2Index array as scratch space for degree counts. + Node2Index[NodeNum] = Degree; + + // Is it a node without dependencies? + if (Degree == 0) { + assert(SU->Succs.empty() && "SUnit should have no successors"); + // Collect leaf nodes. + WorkList.push_back(SU); + } + } + + int Id = DAGSize; + while (!WorkList.empty()) { + SUnit *SU = WorkList.back(); + WorkList.pop_back(); + Allocate(SU->NodeNum, --Id); + for (SUnit::const_pred_iterator I = SU->Preds.begin(), E = SU->Preds.end(); + I != E; ++I) { + SUnit *SU = I->getSUnit(); + if (!--Node2Index[SU->NodeNum]) + // If all dependencies of the node are processed already, + // then the node can be computed now. + WorkList.push_back(SU); + } + } + + Visited.resize(DAGSize); + +#ifndef NDEBUG + // Check correctness of the ordering + for (unsigned i = 0, e = DAGSize; i != e; ++i) { + SUnit *SU = &SUnits[i]; + for (SUnit::const_pred_iterator I = SU->Preds.begin(), E = SU->Preds.end(); + I != E; ++I) { + assert(Node2Index[SU->NodeNum] > Node2Index[I->getSUnit()->NodeNum] && + "Wrong topological sorting"); + } + } +#endif +} + +/// AddPred - Updates the topological ordering to accomodate an edge +/// to be added from SUnit X to SUnit Y. +void ScheduleDAGTopologicalSort::AddPred(SUnit *Y, SUnit *X) { + int UpperBound, LowerBound; + LowerBound = Node2Index[Y->NodeNum]; + UpperBound = Node2Index[X->NodeNum]; + bool HasLoop = false; + // Is Ord(X) < Ord(Y) ? + if (LowerBound < UpperBound) { + // Update the topological order. + Visited.reset(); + DFS(Y, UpperBound, HasLoop); + assert(!HasLoop && "Inserted edge creates a loop!"); + // Recompute topological indexes. + Shift(Visited, LowerBound, UpperBound); + } +} + +/// RemovePred - Updates the topological ordering to accomodate an +/// an edge to be removed from the specified node N from the predecessors +/// of the current node M. +void ScheduleDAGTopologicalSort::RemovePred(SUnit *M, SUnit *N) { + // InitDAGTopologicalSorting(); +} + +/// DFS - Make a DFS traversal to mark all nodes reachable from SU and mark +/// all nodes affected by the edge insertion. These nodes will later get new +/// topological indexes by means of the Shift method. +void ScheduleDAGTopologicalSort::DFS(const SUnit *SU, int UpperBound, + bool& HasLoop) { + std::vector WorkList; + WorkList.reserve(SUnits.size()); + + WorkList.push_back(SU); + do { + SU = WorkList.back(); + WorkList.pop_back(); + Visited.set(SU->NodeNum); + for (int I = SU->Succs.size()-1; I >= 0; --I) { + int s = SU->Succs[I].getSUnit()->NodeNum; + if (Node2Index[s] == UpperBound) { + HasLoop = true; + return; + } + // Visit successors if not already and in affected region. + if (!Visited.test(s) && Node2Index[s] < UpperBound) { + WorkList.push_back(SU->Succs[I].getSUnit()); + } + } + } while (!WorkList.empty()); +} + +/// Shift - Renumber the nodes so that the topological ordering is +/// preserved. +void ScheduleDAGTopologicalSort::Shift(BitVector& Visited, int LowerBound, + int UpperBound) { + std::vector L; + int shift = 0; + int i; + + for (i = LowerBound; i <= UpperBound; ++i) { + // w is node at topological index i. + int w = Index2Node[i]; + if (Visited.test(w)) { + // Unmark. + Visited.reset(w); + L.push_back(w); + shift = shift + 1; + } else { + Allocate(w, i - shift); + } + } + + for (unsigned j = 0; j < L.size(); ++j) { + Allocate(L[j], i - shift); + i = i + 1; + } +} + + +/// WillCreateCycle - Returns true if adding an edge from SU to TargetSU will +/// create a cycle. +bool ScheduleDAGTopologicalSort::WillCreateCycle(SUnit *SU, SUnit *TargetSU) { + if (IsReachable(TargetSU, SU)) + return true; + for (SUnit::pred_iterator I = SU->Preds.begin(), E = SU->Preds.end(); + I != E; ++I) + if (I->isAssignedRegDep() && + IsReachable(TargetSU, I->getSUnit())) + return true; + return false; +} + +/// IsReachable - Checks if SU is reachable from TargetSU. +bool ScheduleDAGTopologicalSort::IsReachable(const SUnit *SU, + const SUnit *TargetSU) { + // If insertion of the edge SU->TargetSU would create a cycle + // then there is a path from TargetSU to SU. + int UpperBound, LowerBound; + LowerBound = Node2Index[TargetSU->NodeNum]; + UpperBound = Node2Index[SU->NodeNum]; + bool HasLoop = false; + // Is Ord(TargetSU) < Ord(SU) ? + if (LowerBound < UpperBound) { + Visited.reset(); + // There may be a path from TargetSU to SU. Check for it. + DFS(TargetSU, UpperBound, HasLoop); + } + return HasLoop; +} + +/// Allocate - assign the topological index to the node n. +void ScheduleDAGTopologicalSort::Allocate(int n, int index) { + Node2Index[n] = index; + Index2Node[index] = n; +} + +ScheduleDAGTopologicalSort::ScheduleDAGTopologicalSort( + std::vector &sunits) + : SUnits(sunits) {} + +ScheduleHazardRecognizer::~ScheduleHazardRecognizer() {} diff --git a/libclamav/c++/llvm/lib/CodeGen/ScheduleDAGEmit.cpp b/libclamav/c++/llvm/lib/CodeGen/ScheduleDAGEmit.cpp new file mode 100644 index 000000000..8e034203f --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/ScheduleDAGEmit.cpp @@ -0,0 +1,71 @@ +//===---- ScheduleDAGEmit.cpp - Emit routines for the ScheduleDAG class ---===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This implements the Emit routines for the ScheduleDAG class, which creates +// MachineInstrs according to the computed schedule. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "pre-RA-sched" +#include "llvm/CodeGen/ScheduleDAG.h" +#include "llvm/CodeGen/MachineConstantPool.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetLowering.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/MathExtras.h" +using namespace llvm; + +void ScheduleDAG::EmitNoop() { + TII->insertNoop(*BB, InsertPos); +} + +void ScheduleDAG::EmitPhysRegCopy(SUnit *SU, + DenseMap &VRBaseMap) { + for (SUnit::const_pred_iterator I = SU->Preds.begin(), E = SU->Preds.end(); + I != E; ++I) { + if (I->isCtrl()) continue; // ignore chain preds + if (I->getSUnit()->CopyDstRC) { + // Copy to physical register. + DenseMap::iterator VRI = VRBaseMap.find(I->getSUnit()); + assert(VRI != VRBaseMap.end() && "Node emitted out of order - late"); + // Find the destination physical register. + unsigned Reg = 0; + for (SUnit::const_succ_iterator II = SU->Succs.begin(), + EE = SU->Succs.end(); II != EE; ++II) { + if (II->getReg()) { + Reg = II->getReg(); + break; + } + } + bool Success = TII->copyRegToReg(*BB, InsertPos, Reg, VRI->second, + SU->CopyDstRC, SU->CopySrcRC); + (void)Success; + assert(Success && "copyRegToReg failed!"); + } else { + // Copy from physical register. + assert(I->getReg() && "Unknown physical register!"); + unsigned VRBase = MRI.createVirtualRegister(SU->CopyDstRC); + bool isNew = VRBaseMap.insert(std::make_pair(SU, VRBase)).second; + isNew = isNew; // Silence compiler warning. + assert(isNew && "Node emitted out of order - early"); + bool Success = TII->copyRegToReg(*BB, InsertPos, VRBase, I->getReg(), + SU->CopyDstRC, SU->CopySrcRC); + (void)Success; + assert(Success && "copyRegToReg failed!"); + } + break; + } +} diff --git a/libclamav/c++/llvm/lib/CodeGen/ScheduleDAGInstrs.cpp b/libclamav/c++/llvm/lib/CodeGen/ScheduleDAGInstrs.cpp new file mode 100644 index 000000000..56dd53345 --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/ScheduleDAGInstrs.cpp @@ -0,0 +1,576 @@ +//===---- ScheduleDAGInstrs.cpp - MachineInstr Rescheduling ---------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This implements the ScheduleDAGInstrs class, which implements re-scheduling +// of MachineInstrs. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "sched-instrs" +#include "ScheduleDAGInstrs.h" +#include "llvm/Operator.h" +#include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineMemOperand.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/PseudoSourceValue.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Target/TargetSubtarget.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/ADT/SmallSet.h" +using namespace llvm; + +ScheduleDAGInstrs::ScheduleDAGInstrs(MachineFunction &mf, + const MachineLoopInfo &mli, + const MachineDominatorTree &mdt) + : ScheduleDAG(mf), MLI(mli), MDT(mdt), LoopRegs(MLI, MDT) { + MFI = mf.getFrameInfo(); +} + +/// Run - perform scheduling. +/// +void ScheduleDAGInstrs::Run(MachineBasicBlock *bb, + MachineBasicBlock::iterator begin, + MachineBasicBlock::iterator end, + unsigned endcount) { + BB = bb; + Begin = begin; + InsertPosIndex = endcount; + + ScheduleDAG::Run(bb, end); +} + +/// getUnderlyingObjectFromInt - This is the function that does the work of +/// looking through basic ptrtoint+arithmetic+inttoptr sequences. +static const Value *getUnderlyingObjectFromInt(const Value *V) { + do { + if (const Operator *U = dyn_cast(V)) { + // If we find a ptrtoint, we can transfer control back to the + // regular getUnderlyingObjectFromInt. + if (U->getOpcode() == Instruction::PtrToInt) + return U->getOperand(0); + // If we find an add of a constant or a multiplied value, it's + // likely that the other operand will lead us to the base + // object. We don't have to worry about the case where the + // object address is somehow being computed by the multiply, + // because our callers only care when the result is an + // identifibale object. + if (U->getOpcode() != Instruction::Add || + (!isa(U->getOperand(1)) && + Operator::getOpcode(U->getOperand(1)) != Instruction::Mul)) + return V; + V = U->getOperand(0); + } else { + return V; + } + assert(isa(V->getType()) && "Unexpected operand type!"); + } while (1); +} + +/// getUnderlyingObject - This is a wrapper around Value::getUnderlyingObject +/// and adds support for basic ptrtoint+arithmetic+inttoptr sequences. +static const Value *getUnderlyingObject(const Value *V) { + // First just call Value::getUnderlyingObject to let it do what it does. + do { + V = V->getUnderlyingObject(); + // If it found an inttoptr, use special code to continue climing. + if (Operator::getOpcode(V) != Instruction::IntToPtr) + break; + const Value *O = getUnderlyingObjectFromInt(cast(V)->getOperand(0)); + // If that succeeded in finding a pointer, continue the search. + if (!isa(O->getType())) + break; + V = O; + } while (1); + return V; +} + +/// getUnderlyingObjectForInstr - If this machine instr has memory reference +/// information and it can be tracked to a normal reference to a known +/// object, return the Value for that object. Otherwise return null. +static const Value *getUnderlyingObjectForInstr(const MachineInstr *MI, + const MachineFrameInfo *MFI, + bool &MayAlias) { + MayAlias = true; + if (!MI->hasOneMemOperand() || + !(*MI->memoperands_begin())->getValue() || + (*MI->memoperands_begin())->isVolatile()) + return 0; + + const Value *V = (*MI->memoperands_begin())->getValue(); + if (!V) + return 0; + + V = getUnderlyingObject(V); + if (const PseudoSourceValue *PSV = dyn_cast(V)) { + // For now, ignore PseudoSourceValues which may alias LLVM IR values + // because the code that uses this function has no way to cope with + // such aliases. + if (PSV->isAliased(MFI)) + return 0; + + MayAlias = PSV->mayAlias(MFI); + return V; + } + + if (isIdentifiedObject(V)) + return V; + + return 0; +} + +void ScheduleDAGInstrs::StartBlock(MachineBasicBlock *BB) { + if (MachineLoop *ML = MLI.getLoopFor(BB)) + if (BB == ML->getLoopLatch()) { + MachineBasicBlock *Header = ML->getHeader(); + for (MachineBasicBlock::livein_iterator I = Header->livein_begin(), + E = Header->livein_end(); I != E; ++I) + LoopLiveInRegs.insert(*I); + LoopRegs.VisitLoop(ML); + } +} + +void ScheduleDAGInstrs::BuildSchedGraph(AliasAnalysis *AA) { + // We'll be allocating one SUnit for each instruction, plus one for + // the region exit node. + SUnits.reserve(BB->size()); + + // We build scheduling units by walking a block's instruction list from bottom + // to top. + + // Remember where a generic side-effecting instruction is as we procede. + SUnit *BarrierChain = 0, *AliasChain = 0; + + // Memory references to specific known memory locations are tracked + // so that they can be given more precise dependencies. We track + // separately the known memory locations that may alias and those + // that are known not to alias + std::map AliasMemDefs, NonAliasMemDefs; + std::map > AliasMemUses, NonAliasMemUses; + + // Check to see if the scheduler cares about latencies. + bool UnitLatencies = ForceUnitLatencies(); + + // Ask the target if address-backscheduling is desirable, and if so how much. + const TargetSubtarget &ST = TM.getSubtarget(); + unsigned SpecialAddressLatency = ST.getSpecialAddressLatency(); + + // Walk the list of instructions, from bottom moving up. + for (MachineBasicBlock::iterator MII = InsertPos, MIE = Begin; + MII != MIE; --MII) { + MachineInstr *MI = prior(MII); + const TargetInstrDesc &TID = MI->getDesc(); + assert(!TID.isTerminator() && !MI->isLabel() && + "Cannot schedule terminators or labels!"); + // Create the SUnit for this MI. + SUnit *SU = NewSUnit(MI); + + // Assign the Latency field of SU using target-provided information. + if (UnitLatencies) + SU->Latency = 1; + else + ComputeLatency(SU); + + // Add register-based dependencies (data, anti, and output). + for (unsigned j = 0, n = MI->getNumOperands(); j != n; ++j) { + const MachineOperand &MO = MI->getOperand(j); + if (!MO.isReg()) continue; + unsigned Reg = MO.getReg(); + if (Reg == 0) continue; + + assert(TRI->isPhysicalRegister(Reg) && "Virtual register encountered!"); + std::vector &UseList = Uses[Reg]; + std::vector &DefList = Defs[Reg]; + // Optionally add output and anti dependencies. For anti + // dependencies we use a latency of 0 because for a multi-issue + // target we want to allow the defining instruction to issue + // in the same cycle as the using instruction. + // TODO: Using a latency of 1 here for output dependencies assumes + // there's no cost for reusing registers. + SDep::Kind Kind = MO.isUse() ? SDep::Anti : SDep::Output; + unsigned AOLatency = (Kind == SDep::Anti) ? 0 : 1; + for (unsigned i = 0, e = DefList.size(); i != e; ++i) { + SUnit *DefSU = DefList[i]; + if (DefSU != SU && + (Kind != SDep::Output || !MO.isDead() || + !DefSU->getInstr()->registerDefIsDead(Reg))) + DefSU->addPred(SDep(SU, Kind, AOLatency, /*Reg=*/Reg)); + } + for (const unsigned *Alias = TRI->getAliasSet(Reg); *Alias; ++Alias) { + std::vector &DefList = Defs[*Alias]; + for (unsigned i = 0, e = DefList.size(); i != e; ++i) { + SUnit *DefSU = DefList[i]; + if (DefSU != SU && + (Kind != SDep::Output || !MO.isDead() || + !DefSU->getInstr()->registerDefIsDead(*Alias))) + DefSU->addPred(SDep(SU, Kind, AOLatency, /*Reg=*/ *Alias)); + } + } + + if (MO.isDef()) { + // Add any data dependencies. + unsigned DataLatency = SU->Latency; + for (unsigned i = 0, e = UseList.size(); i != e; ++i) { + SUnit *UseSU = UseList[i]; + if (UseSU != SU) { + unsigned LDataLatency = DataLatency; + // Optionally add in a special extra latency for nodes that + // feed addresses. + // TODO: Do this for register aliases too. + // TODO: Perhaps we should get rid of + // SpecialAddressLatency and just move this into + // adjustSchedDependency for the targets that care about + // it. + if (SpecialAddressLatency != 0 && !UnitLatencies) { + MachineInstr *UseMI = UseSU->getInstr(); + const TargetInstrDesc &UseTID = UseMI->getDesc(); + int RegUseIndex = UseMI->findRegisterUseOperandIdx(Reg); + assert(RegUseIndex >= 0 && "UseMI doesn's use register!"); + if ((UseTID.mayLoad() || UseTID.mayStore()) && + (unsigned)RegUseIndex < UseTID.getNumOperands() && + UseTID.OpInfo[RegUseIndex].isLookupPtrRegClass()) + LDataLatency += SpecialAddressLatency; + } + // Adjust the dependence latency using operand def/use + // information (if any), and then allow the target to + // perform its own adjustments. + const SDep& dep = SDep(SU, SDep::Data, LDataLatency, Reg); + if (!UnitLatencies) { + ComputeOperandLatency(SU, UseSU, (SDep &)dep); + ST.adjustSchedDependency(SU, UseSU, (SDep &)dep); + } + UseSU->addPred(dep); + } + } + for (const unsigned *Alias = TRI->getAliasSet(Reg); *Alias; ++Alias) { + std::vector &UseList = Uses[*Alias]; + for (unsigned i = 0, e = UseList.size(); i != e; ++i) { + SUnit *UseSU = UseList[i]; + if (UseSU != SU) { + const SDep& dep = SDep(SU, SDep::Data, DataLatency, *Alias); + if (!UnitLatencies) { + ComputeOperandLatency(SU, UseSU, (SDep &)dep); + ST.adjustSchedDependency(SU, UseSU, (SDep &)dep); + } + UseSU->addPred(dep); + } + } + } + + // If a def is going to wrap back around to the top of the loop, + // backschedule it. + if (!UnitLatencies && DefList.empty()) { + LoopDependencies::LoopDeps::iterator I = LoopRegs.Deps.find(Reg); + if (I != LoopRegs.Deps.end()) { + const MachineOperand *UseMO = I->second.first; + unsigned Count = I->second.second; + const MachineInstr *UseMI = UseMO->getParent(); + unsigned UseMOIdx = UseMO - &UseMI->getOperand(0); + const TargetInstrDesc &UseTID = UseMI->getDesc(); + // TODO: If we knew the total depth of the region here, we could + // handle the case where the whole loop is inside the region but + // is large enough that the isScheduleHigh trick isn't needed. + if (UseMOIdx < UseTID.getNumOperands()) { + // Currently, we only support scheduling regions consisting of + // single basic blocks. Check to see if the instruction is in + // the same region by checking to see if it has the same parent. + if (UseMI->getParent() != MI->getParent()) { + unsigned Latency = SU->Latency; + if (UseTID.OpInfo[UseMOIdx].isLookupPtrRegClass()) + Latency += SpecialAddressLatency; + // This is a wild guess as to the portion of the latency which + // will be overlapped by work done outside the current + // scheduling region. + Latency -= std::min(Latency, Count); + // Add the artifical edge. + ExitSU.addPred(SDep(SU, SDep::Order, Latency, + /*Reg=*/0, /*isNormalMemory=*/false, + /*isMustAlias=*/false, + /*isArtificial=*/true)); + } else if (SpecialAddressLatency > 0 && + UseTID.OpInfo[UseMOIdx].isLookupPtrRegClass()) { + // The entire loop body is within the current scheduling region + // and the latency of this operation is assumed to be greater + // than the latency of the loop. + // TODO: Recursively mark data-edge predecessors as + // isScheduleHigh too. + SU->isScheduleHigh = true; + } + } + LoopRegs.Deps.erase(I); + } + } + + UseList.clear(); + if (!MO.isDead()) + DefList.clear(); + DefList.push_back(SU); + } else { + UseList.push_back(SU); + } + } + + // Add chain dependencies. + // Chain dependencies used to enforce memory order should have + // latency of 0 (except for true dependency of Store followed by + // aliased Load... we estimate that with a single cycle of latency + // assuming the hardware will bypass) + // Note that isStoreToStackSlot and isLoadFromStackSLot are not usable + // after stack slots are lowered to actual addresses. + // TODO: Use an AliasAnalysis and do real alias-analysis queries, and + // produce more precise dependence information. +#define STORE_LOAD_LATENCY 1 + unsigned TrueMemOrderLatency = 0; + if (TID.isCall() || TID.hasUnmodeledSideEffects() || + (MI->hasVolatileMemoryRef() && + (!TID.mayLoad() || !MI->isInvariantLoad(AA)))) { + // Be conservative with these and add dependencies on all memory + // references, even those that are known to not alias. + for (std::map::iterator I = + NonAliasMemDefs.begin(), E = NonAliasMemDefs.end(); I != E; ++I) { + I->second->addPred(SDep(SU, SDep::Order, /*Latency=*/0)); + } + for (std::map >::iterator I = + NonAliasMemUses.begin(), E = NonAliasMemUses.end(); I != E; ++I) { + for (unsigned i = 0, e = I->second.size(); i != e; ++i) + I->second[i]->addPred(SDep(SU, SDep::Order, TrueMemOrderLatency)); + } + NonAliasMemDefs.clear(); + NonAliasMemUses.clear(); + // Add SU to the barrier chain. + if (BarrierChain) + BarrierChain->addPred(SDep(SU, SDep::Order, /*Latency=*/0)); + BarrierChain = SU; + + // fall-through + new_alias_chain: + // Chain all possibly aliasing memory references though SU. + if (AliasChain) + AliasChain->addPred(SDep(SU, SDep::Order, /*Latency=*/0)); + AliasChain = SU; + for (unsigned k = 0, m = PendingLoads.size(); k != m; ++k) + PendingLoads[k]->addPred(SDep(SU, SDep::Order, TrueMemOrderLatency)); + for (std::map::iterator I = AliasMemDefs.begin(), + E = AliasMemDefs.end(); I != E; ++I) { + I->second->addPred(SDep(SU, SDep::Order, /*Latency=*/0)); + } + for (std::map >::iterator I = + AliasMemUses.begin(), E = AliasMemUses.end(); I != E; ++I) { + for (unsigned i = 0, e = I->second.size(); i != e; ++i) + I->second[i]->addPred(SDep(SU, SDep::Order, TrueMemOrderLatency)); + } + PendingLoads.clear(); + AliasMemDefs.clear(); + AliasMemUses.clear(); + } else if (TID.mayStore()) { + bool MayAlias = true; + TrueMemOrderLatency = STORE_LOAD_LATENCY; + if (const Value *V = getUnderlyingObjectForInstr(MI, MFI, MayAlias)) { + // A store to a specific PseudoSourceValue. Add precise dependencies. + // Record the def in MemDefs, first adding a dep if there is + // an existing def. + std::map::iterator I = + ((MayAlias) ? AliasMemDefs.find(V) : NonAliasMemDefs.find(V)); + std::map::iterator IE = + ((MayAlias) ? AliasMemDefs.end() : NonAliasMemDefs.end()); + if (I != IE) { + I->second->addPred(SDep(SU, SDep::Order, /*Latency=*/0, /*Reg=*/0, + /*isNormalMemory=*/true)); + I->second = SU; + } else { + if (MayAlias) + AliasMemDefs[V] = SU; + else + NonAliasMemDefs[V] = SU; + } + // Handle the uses in MemUses, if there are any. + std::map >::iterator J = + ((MayAlias) ? AliasMemUses.find(V) : NonAliasMemUses.find(V)); + std::map >::iterator JE = + ((MayAlias) ? AliasMemUses.end() : NonAliasMemUses.end()); + if (J != JE) { + for (unsigned i = 0, e = J->second.size(); i != e; ++i) + J->second[i]->addPred(SDep(SU, SDep::Order, TrueMemOrderLatency, + /*Reg=*/0, /*isNormalMemory=*/true)); + J->second.clear(); + } + if (MayAlias) { + // Add dependencies from all the PendingLoads, i.e. loads + // with no underlying object. + for (unsigned k = 0, m = PendingLoads.size(); k != m; ++k) + PendingLoads[k]->addPred(SDep(SU, SDep::Order, TrueMemOrderLatency)); + // Add dependence on alias chain, if needed. + if (AliasChain) + AliasChain->addPred(SDep(SU, SDep::Order, /*Latency=*/0)); + } + // Add dependence on barrier chain, if needed. + if (BarrierChain) + BarrierChain->addPred(SDep(SU, SDep::Order, /*Latency=*/0)); + } else { + // Treat all other stores conservatively. + goto new_alias_chain; + } + } else if (TID.mayLoad()) { + bool MayAlias = true; + TrueMemOrderLatency = 0; + if (MI->isInvariantLoad(AA)) { + // Invariant load, no chain dependencies needed! + } else { + if (const Value *V = + getUnderlyingObjectForInstr(MI, MFI, MayAlias)) { + // A load from a specific PseudoSourceValue. Add precise dependencies. + std::map::iterator I = + ((MayAlias) ? AliasMemDefs.find(V) : NonAliasMemDefs.find(V)); + std::map::iterator IE = + ((MayAlias) ? AliasMemDefs.end() : NonAliasMemDefs.end()); + if (I != IE) + I->second->addPred(SDep(SU, SDep::Order, /*Latency=*/0, /*Reg=*/0, + /*isNormalMemory=*/true)); + if (MayAlias) + AliasMemUses[V].push_back(SU); + else + NonAliasMemUses[V].push_back(SU); + } else { + // A load with no underlying object. Depend on all + // potentially aliasing stores. + for (std::map::iterator I = + AliasMemDefs.begin(), E = AliasMemDefs.end(); I != E; ++I) + I->second->addPred(SDep(SU, SDep::Order, /*Latency=*/0)); + + PendingLoads.push_back(SU); + MayAlias = true; + } + + // Add dependencies on alias and barrier chains, if needed. + if (MayAlias && AliasChain) + AliasChain->addPred(SDep(SU, SDep::Order, /*Latency=*/0)); + if (BarrierChain) + BarrierChain->addPred(SDep(SU, SDep::Order, /*Latency=*/0)); + } + } + } + + for (int i = 0, e = TRI->getNumRegs(); i != e; ++i) { + Defs[i].clear(); + Uses[i].clear(); + } + PendingLoads.clear(); +} + +void ScheduleDAGInstrs::FinishBlock() { + // Nothing to do. +} + +void ScheduleDAGInstrs::ComputeLatency(SUnit *SU) { + const InstrItineraryData &InstrItins = TM.getInstrItineraryData(); + + // Compute the latency for the node. + SU->Latency = + InstrItins.getStageLatency(SU->getInstr()->getDesc().getSchedClass()); + + // Simplistic target-independent heuristic: assume that loads take + // extra time. + if (InstrItins.isEmpty()) + if (SU->getInstr()->getDesc().mayLoad()) + SU->Latency += 2; +} + +void ScheduleDAGInstrs::ComputeOperandLatency(SUnit *Def, SUnit *Use, + SDep& dep) const { + const InstrItineraryData &InstrItins = TM.getInstrItineraryData(); + if (InstrItins.isEmpty()) + return; + + // For a data dependency with a known register... + if ((dep.getKind() != SDep::Data) || (dep.getReg() == 0)) + return; + + const unsigned Reg = dep.getReg(); + + // ... find the definition of the register in the defining + // instruction + MachineInstr *DefMI = Def->getInstr(); + int DefIdx = DefMI->findRegisterDefOperandIdx(Reg); + if (DefIdx != -1) { + int DefCycle = InstrItins.getOperandCycle(DefMI->getDesc().getSchedClass(), DefIdx); + if (DefCycle >= 0) { + MachineInstr *UseMI = Use->getInstr(); + const unsigned UseClass = UseMI->getDesc().getSchedClass(); + + // For all uses of the register, calculate the maxmimum latency + int Latency = -1; + for (unsigned i = 0, e = UseMI->getNumOperands(); i != e; ++i) { + const MachineOperand &MO = UseMI->getOperand(i); + if (!MO.isReg() || !MO.isUse()) + continue; + unsigned MOReg = MO.getReg(); + if (MOReg != Reg) + continue; + + int UseCycle = InstrItins.getOperandCycle(UseClass, i); + if (UseCycle >= 0) + Latency = std::max(Latency, DefCycle - UseCycle + 1); + } + + // If we found a latency, then replace the existing dependence latency. + if (Latency >= 0) + dep.setLatency(Latency); + } + } +} + +void ScheduleDAGInstrs::dumpNode(const SUnit *SU) const { + SU->getInstr()->dump(); +} + +std::string ScheduleDAGInstrs::getGraphNodeLabel(const SUnit *SU) const { + std::string s; + raw_string_ostream oss(s); + if (SU == &EntrySU) + oss << ""; + else if (SU == &ExitSU) + oss << ""; + else + SU->getInstr()->print(oss); + return oss.str(); +} + +// EmitSchedule - Emit the machine code in scheduled order. +MachineBasicBlock *ScheduleDAGInstrs:: +EmitSchedule(DenseMap *EM) { + // For MachineInstr-based scheduling, we're rescheduling the instructions in + // the block, so start by removing them from the block. + while (Begin != InsertPos) { + MachineBasicBlock::iterator I = Begin; + ++Begin; + BB->remove(I); + } + + // Then re-insert them according to the given schedule. + for (unsigned i = 0, e = Sequence.size(); i != e; i++) { + SUnit *SU = Sequence[i]; + if (!SU) { + // Null SUnit* is a noop. + EmitNoop(); + continue; + } + + BB->insert(InsertPos, SU->getInstr()); + } + + // Update the Begin iterator, as the first instruction in the block + // may have been scheduled later. + if (!Sequence.empty()) + Begin = Sequence[0]->getInstr(); + + return BB; +} diff --git a/libclamav/c++/llvm/lib/CodeGen/ScheduleDAGInstrs.h b/libclamav/c++/llvm/lib/CodeGen/ScheduleDAGInstrs.h new file mode 100644 index 000000000..366c3a859 --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/ScheduleDAGInstrs.h @@ -0,0 +1,192 @@ +//==- ScheduleDAGInstrs.h - MachineInstr Scheduling --------------*- 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 the ScheduleDAGInstrs class, which implements +// scheduling for a MachineInstr-based dependency graph. +// +//===----------------------------------------------------------------------===// + +#ifndef SCHEDULEDAGINSTRS_H +#define SCHEDULEDAGINSTRS_H + +#include "llvm/CodeGen/MachineDominators.h" +#include "llvm/CodeGen/MachineLoopInfo.h" +#include "llvm/CodeGen/ScheduleDAG.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallSet.h" +#include + +namespace llvm { + class MachineLoopInfo; + class MachineDominatorTree; + + /// LoopDependencies - This class analyzes loop-oriented register + /// dependencies, which are used to guide scheduling decisions. + /// For example, loop induction variable increments should be + /// scheduled as soon as possible after the variable's last use. + /// + class VISIBILITY_HIDDEN LoopDependencies { + const MachineLoopInfo &MLI; + const MachineDominatorTree &MDT; + + public: + typedef std::map > + LoopDeps; + LoopDeps Deps; + + LoopDependencies(const MachineLoopInfo &mli, + const MachineDominatorTree &mdt) : + MLI(mli), MDT(mdt) {} + + /// VisitLoop - Clear out any previous state and analyze the given loop. + /// + void VisitLoop(const MachineLoop *Loop) { + Deps.clear(); + MachineBasicBlock *Header = Loop->getHeader(); + SmallSet LoopLiveIns; + for (MachineBasicBlock::livein_iterator LI = Header->livein_begin(), + LE = Header->livein_end(); LI != LE; ++LI) + LoopLiveIns.insert(*LI); + + const MachineDomTreeNode *Node = MDT.getNode(Header); + const MachineBasicBlock *MBB = Node->getBlock(); + assert(Loop->contains(MBB) && + "Loop does not contain header!"); + VisitRegion(Node, MBB, Loop, LoopLiveIns); + } + + private: + void VisitRegion(const MachineDomTreeNode *Node, + const MachineBasicBlock *MBB, + const MachineLoop *Loop, + const SmallSet &LoopLiveIns) { + unsigned Count = 0; + for (MachineBasicBlock::const_iterator I = MBB->begin(), E = MBB->end(); + I != E; ++I, ++Count) { + const MachineInstr *MI = I; + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + const MachineOperand &MO = MI->getOperand(i); + if (!MO.isReg() || !MO.isUse()) + continue; + unsigned MOReg = MO.getReg(); + if (LoopLiveIns.count(MOReg)) + Deps.insert(std::make_pair(MOReg, std::make_pair(&MO, Count))); + } + } + + const std::vector &Children = Node->getChildren(); + for (std::vector::const_iterator I = + Children.begin(), E = Children.end(); I != E; ++I) { + const MachineDomTreeNode *ChildNode = *I; + MachineBasicBlock *ChildBlock = ChildNode->getBlock(); + if (Loop->contains(ChildBlock)) + VisitRegion(ChildNode, ChildBlock, Loop, LoopLiveIns); + } + } + }; + + /// ScheduleDAGInstrs - A ScheduleDAG subclass for scheduling lists of + /// MachineInstrs. + class VISIBILITY_HIDDEN ScheduleDAGInstrs : public ScheduleDAG { + const MachineLoopInfo &MLI; + const MachineDominatorTree &MDT; + const MachineFrameInfo *MFI; + + /// Defs, Uses - Remember where defs and uses of each physical register + /// are as we iterate upward through the instructions. This is allocated + /// here instead of inside BuildSchedGraph to avoid the need for it to be + /// initialized and destructed for each block. + std::vector Defs[TargetRegisterInfo::FirstVirtualRegister]; + std::vector Uses[TargetRegisterInfo::FirstVirtualRegister]; + + /// PendingLoads - Remember where unknown loads are after the most recent + /// unknown store, as we iterate. As with Defs and Uses, this is here + /// to minimize construction/destruction. + std::vector PendingLoads; + + /// LoopRegs - Track which registers are used for loop-carried dependencies. + /// + LoopDependencies LoopRegs; + + /// LoopLiveInRegs - Track which regs are live into a loop, to help guide + /// back-edge-aware scheduling. + /// + SmallSet LoopLiveInRegs; + + public: + MachineBasicBlock::iterator Begin; // The beginning of the range to + // be scheduled. The range extends + // to InsertPos. + unsigned InsertPosIndex; // The index in BB of InsertPos. + + explicit ScheduleDAGInstrs(MachineFunction &mf, + const MachineLoopInfo &mli, + const MachineDominatorTree &mdt); + + virtual ~ScheduleDAGInstrs() {} + + /// NewSUnit - Creates a new SUnit and return a ptr to it. + /// + SUnit *NewSUnit(MachineInstr *MI) { +#ifndef NDEBUG + const SUnit *Addr = SUnits.empty() ? 0 : &SUnits[0]; +#endif + SUnits.push_back(SUnit(MI, (unsigned)SUnits.size())); + assert((Addr == 0 || Addr == &SUnits[0]) && + "SUnits std::vector reallocated on the fly!"); + SUnits.back().OrigNode = &SUnits.back(); + return &SUnits.back(); + } + + /// Run - perform scheduling. + /// + void Run(MachineBasicBlock *bb, + MachineBasicBlock::iterator begin, + MachineBasicBlock::iterator end, + unsigned endindex); + + /// BuildSchedGraph - Build SUnits from the MachineBasicBlock that we are + /// input. + virtual void BuildSchedGraph(AliasAnalysis *AA); + + /// ComputeLatency - Compute node latency. + /// + virtual void ComputeLatency(SUnit *SU); + + /// ComputeOperandLatency - Override dependence edge latency using + /// operand use/def information + /// + virtual void ComputeOperandLatency(SUnit *Def, SUnit *Use, + SDep& dep) const; + + virtual MachineBasicBlock* + EmitSchedule(DenseMap*); + + /// StartBlock - Prepare to perform scheduling in the given block. + /// + virtual void StartBlock(MachineBasicBlock *BB); + + /// Schedule - Order nodes according to selected style, filling + /// in the Sequence member. + /// + virtual void Schedule() = 0; + + /// FinishBlock - Clean up after scheduling in the given block. + /// + virtual void FinishBlock(); + + virtual void dumpNode(const SUnit *SU) const; + + virtual std::string getGraphNodeLabel(const SUnit *SU) const; + }; +} + +#endif diff --git a/libclamav/c++/llvm/lib/CodeGen/ScheduleDAGPrinter.cpp b/libclamav/c++/llvm/lib/CodeGen/ScheduleDAGPrinter.cpp new file mode 100644 index 000000000..4851d496b --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/ScheduleDAGPrinter.cpp @@ -0,0 +1,98 @@ +//===-- ScheduleDAGPrinter.cpp - Implement ScheduleDAG::viewGraph() -------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This implements the ScheduleDAG::viewGraph method. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Constants.h" +#include "llvm/Function.h" +#include "llvm/Assembly/Writer.h" +#include "llvm/CodeGen/ScheduleDAG.h" +#include "llvm/CodeGen/MachineConstantPool.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/GraphWriter.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/ADT/DenseSet.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/Config/config.h" +#include +using namespace llvm; + +namespace llvm { + template<> + struct DOTGraphTraits : public DefaultDOTGraphTraits { + static std::string getGraphName(const ScheduleDAG *G) { + return G->MF.getFunction()->getName(); + } + + static bool renderGraphFromBottomUp() { + return true; + } + + static bool hasNodeAddressLabel(const SUnit *Node, + const ScheduleDAG *Graph) { + return true; + } + + /// If you want to override the dot attributes printed for a particular + /// edge, override this method. + static std::string getEdgeAttributes(const SUnit *Node, + SUnitIterator EI) { + if (EI.isArtificialDep()) + return "color=cyan,style=dashed"; + if (EI.isCtrlDep()) + return "color=blue,style=dashed"; + return ""; + } + + + static std::string getNodeLabel(const SUnit *Node, + const ScheduleDAG *Graph, + bool ShortNames); + static std::string getNodeAttributes(const SUnit *N, + const ScheduleDAG *Graph) { + return "shape=Mrecord"; + } + + static void addCustomGraphFeatures(ScheduleDAG *G, + GraphWriter &GW) { + return G->addCustomGraphFeatures(GW); + } + }; +} + +std::string DOTGraphTraits::getNodeLabel(const SUnit *SU, + const ScheduleDAG *G, + bool ShortNames) { + return G->getGraphNodeLabel(SU); +} + +/// viewGraph - Pop up a ghostview window with the reachable parts of the DAG +/// rendered using 'dot'. +/// +void ScheduleDAG::viewGraph() { +// This code is only for debugging! +#ifndef NDEBUG + if (BB->getBasicBlock()) + ViewGraph(this, "dag." + MF.getFunction()->getNameStr(), false, + "Scheduling-Units Graph for " + MF.getFunction()->getNameStr() + + ":" + BB->getBasicBlock()->getNameStr()); + else + ViewGraph(this, "dag." + MF.getFunction()->getNameStr(), false, + "Scheduling-Units Graph for " + MF.getFunction()->getNameStr()); +#else + errs() << "ScheduleDAG::viewGraph is only available in debug builds on " + << "systems with Graphviz or gv!\n"; +#endif // NDEBUG +} diff --git a/libclamav/c++/llvm/lib/CodeGen/SelectionDAG/CMakeLists.txt b/libclamav/c++/llvm/lib/CodeGen/SelectionDAG/CMakeLists.txt new file mode 100644 index 000000000..80c7d7c9e --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/SelectionDAG/CMakeLists.txt @@ -0,0 +1,25 @@ +add_llvm_library(LLVMSelectionDAG + CallingConvLower.cpp + DAGCombiner.cpp + FastISel.cpp + FunctionLoweringInfo.cpp + InstrEmitter.cpp + LegalizeDAG.cpp + LegalizeFloatTypes.cpp + LegalizeIntegerTypes.cpp + LegalizeTypes.cpp + LegalizeTypesGeneric.cpp + LegalizeVectorOps.cpp + LegalizeVectorTypes.cpp + ScheduleDAGFast.cpp + ScheduleDAGList.cpp + ScheduleDAGRRList.cpp + ScheduleDAGSDNodes.cpp + SelectionDAG.cpp + SelectionDAGBuilder.cpp + SelectionDAGISel.cpp + SelectionDAGPrinter.cpp + TargetLowering.cpp + ) + +target_link_libraries (LLVMSelectionDAG LLVMAnalysis LLVMAsmPrinter LLVMCodeGen) diff --git a/libclamav/c++/llvm/lib/CodeGen/SelectionDAG/CallingConvLower.cpp b/libclamav/c++/llvm/lib/CodeGen/SelectionDAG/CallingConvLower.cpp new file mode 100644 index 000000000..38839c441 --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/SelectionDAG/CallingConvLower.cpp @@ -0,0 +1,178 @@ +//===-- CallingConvLower.cpp - Calling Conventions ------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the CCState class, used for lowering and implementing +// calling conventions. +// +//===----------------------------------------------------------------------===// + +#include "llvm/CodeGen/CallingConvLower.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetMachine.h" +using namespace llvm; + +CCState::CCState(CallingConv::ID CC, bool isVarArg, const TargetMachine &tm, + SmallVector &locs, LLVMContext &C) + : CallingConv(CC), IsVarArg(isVarArg), TM(tm), + TRI(*TM.getRegisterInfo()), Locs(locs), Context(C) { + // No stack is used. + StackOffset = 0; + + UsedRegs.resize((TRI.getNumRegs()+31)/32); +} + +// HandleByVal - Allocate a stack slot large enough to pass an argument by +// value. The size and alignment information of the argument is encoded in its +// parameter attribute. +void CCState::HandleByVal(unsigned ValNo, EVT ValVT, + EVT LocVT, CCValAssign::LocInfo LocInfo, + int MinSize, int MinAlign, + ISD::ArgFlagsTy ArgFlags) { + unsigned Align = ArgFlags.getByValAlign(); + unsigned Size = ArgFlags.getByValSize(); + if (MinSize > (int)Size) + Size = MinSize; + if (MinAlign > (int)Align) + Align = MinAlign; + unsigned Offset = AllocateStack(Size, Align); + + addLoc(CCValAssign::getMem(ValNo, ValVT, Offset, LocVT, LocInfo)); +} + +/// MarkAllocated - Mark a register and all of its aliases as allocated. +void CCState::MarkAllocated(unsigned Reg) { + UsedRegs[Reg/32] |= 1 << (Reg&31); + + if (const unsigned *RegAliases = TRI.getAliasSet(Reg)) + for (; (Reg = *RegAliases); ++RegAliases) + UsedRegs[Reg/32] |= 1 << (Reg&31); +} + +/// AnalyzeFormalArguments - Analyze an array of argument values, +/// incorporating info about the formals into this state. +void +CCState::AnalyzeFormalArguments(const SmallVectorImpl &Ins, + CCAssignFn Fn) { + unsigned NumArgs = Ins.size(); + + for (unsigned i = 0; i != NumArgs; ++i) { + EVT ArgVT = Ins[i].VT; + ISD::ArgFlagsTy ArgFlags = Ins[i].Flags; + if (Fn(i, ArgVT, ArgVT, CCValAssign::Full, ArgFlags, *this)) { +#ifndef NDEBUG + errs() << "Formal argument #" << i << " has unhandled type " + << ArgVT.getEVTString(); +#endif + llvm_unreachable(0); + } + } +} + +/// CheckReturn - Analyze the return values of a function, returning true if +/// the return can be performed without sret-demotion, and false otherwise. +bool CCState::CheckReturn(const SmallVectorImpl &OutTys, + const SmallVectorImpl &ArgsFlags, + CCAssignFn Fn) { + // Determine which register each value should be copied into. + for (unsigned i = 0, e = OutTys.size(); i != e; ++i) { + EVT VT = OutTys[i]; + ISD::ArgFlagsTy ArgFlags = ArgsFlags[i]; + if (Fn(i, VT, VT, CCValAssign::Full, ArgFlags, *this)) + return false; + } + return true; +} + +/// AnalyzeReturn - Analyze the returned values of a return, +/// incorporating info about the result values into this state. +void CCState::AnalyzeReturn(const SmallVectorImpl &Outs, + CCAssignFn Fn) { + // Determine which register each value should be copied into. + for (unsigned i = 0, e = Outs.size(); i != e; ++i) { + EVT VT = Outs[i].Val.getValueType(); + ISD::ArgFlagsTy ArgFlags = Outs[i].Flags; + if (Fn(i, VT, VT, CCValAssign::Full, ArgFlags, *this)) { +#ifndef NDEBUG + errs() << "Return operand #" << i << " has unhandled type " + << VT.getEVTString(); +#endif + llvm_unreachable(0); + } + } +} + + +/// AnalyzeCallOperands - Analyze the outgoing arguments to a call, +/// incorporating info about the passed values into this state. +void CCState::AnalyzeCallOperands(const SmallVectorImpl &Outs, + CCAssignFn Fn) { + unsigned NumOps = Outs.size(); + for (unsigned i = 0; i != NumOps; ++i) { + EVT ArgVT = Outs[i].Val.getValueType(); + ISD::ArgFlagsTy ArgFlags = Outs[i].Flags; + if (Fn(i, ArgVT, ArgVT, CCValAssign::Full, ArgFlags, *this)) { +#ifndef NDEBUG + errs() << "Call operand #" << i << " has unhandled type " + << ArgVT.getEVTString(); +#endif + llvm_unreachable(0); + } + } +} + +/// AnalyzeCallOperands - Same as above except it takes vectors of types +/// and argument flags. +void CCState::AnalyzeCallOperands(SmallVectorImpl &ArgVTs, + SmallVectorImpl &Flags, + CCAssignFn Fn) { + unsigned NumOps = ArgVTs.size(); + for (unsigned i = 0; i != NumOps; ++i) { + EVT ArgVT = ArgVTs[i]; + ISD::ArgFlagsTy ArgFlags = Flags[i]; + if (Fn(i, ArgVT, ArgVT, CCValAssign::Full, ArgFlags, *this)) { +#ifndef NDEBUG + errs() << "Call operand #" << i << " has unhandled type " + << ArgVT.getEVTString(); +#endif + llvm_unreachable(0); + } + } +} + +/// AnalyzeCallResult - Analyze the return values of a call, +/// incorporating info about the passed values into this state. +void CCState::AnalyzeCallResult(const SmallVectorImpl &Ins, + CCAssignFn Fn) { + for (unsigned i = 0, e = Ins.size(); i != e; ++i) { + EVT VT = Ins[i].VT; + ISD::ArgFlagsTy Flags = Ins[i].Flags; + if (Fn(i, VT, VT, CCValAssign::Full, Flags, *this)) { +#ifndef NDEBUG + errs() << "Call result #" << i << " has unhandled type " + << VT.getEVTString(); +#endif + llvm_unreachable(0); + } + } +} + +/// AnalyzeCallResult - Same as above except it's specialized for calls which +/// produce a single value. +void CCState::AnalyzeCallResult(EVT VT, CCAssignFn Fn) { + if (Fn(0, VT, VT, CCValAssign::Full, ISD::ArgFlagsTy(), *this)) { +#ifndef NDEBUG + errs() << "Call result has unhandled type " + << VT.getEVTString(); +#endif + llvm_unreachable(0); + } +} diff --git a/libclamav/c++/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/libclamav/c++/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp new file mode 100644 index 000000000..06ffdd638 --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -0,0 +1,6337 @@ +//===-- DAGCombiner.cpp - Implement a DAG node combiner -------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This pass combines dag nodes to form fewer, simpler DAG nodes. It can be run +// both before and after the DAG is legalized. +// +// This pass is not a substitute for the LLVM IR instcombine pass. This pass is +// primarily intended to handle simplification opportunities that are implicit +// in the LLVM IR and exposed by the various codegen lowering phases. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "dagcombine" +#include "llvm/CodeGen/SelectionDAG.h" +#include "llvm/DerivedTypes.h" +#include "llvm/LLVMContext.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/PseudoSourceValue.h" +#include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetFrameInfo.h" +#include "llvm/Target/TargetLowering.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetOptions.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/Support/raw_ostream.h" +#include +using namespace llvm; + +STATISTIC(NodesCombined , "Number of dag nodes combined"); +STATISTIC(PreIndexedNodes , "Number of pre-indexed nodes created"); +STATISTIC(PostIndexedNodes, "Number of post-indexed nodes created"); +STATISTIC(OpsNarrowed , "Number of load/op/store narrowed"); + +namespace { + static cl::opt + CombinerAA("combiner-alias-analysis", cl::Hidden, + cl::desc("Turn on alias analysis during testing")); + + static cl::opt + CombinerGlobalAA("combiner-global-alias-analysis", cl::Hidden, + cl::desc("Include global information in alias analysis")); + +//------------------------------ DAGCombiner ---------------------------------// + + class DAGCombiner { + SelectionDAG &DAG; + const TargetLowering &TLI; + CombineLevel Level; + CodeGenOpt::Level OptLevel; + bool LegalOperations; + bool LegalTypes; + + // Worklist of all of the nodes that need to be simplified. + std::vector WorkList; + + // AA - Used for DAG load/store alias analysis. + AliasAnalysis &AA; + + /// AddUsersToWorkList - When an instruction is simplified, add all users of + /// the instruction to the work lists because they might get more simplified + /// now. + /// + void AddUsersToWorkList(SDNode *N) { + for (SDNode::use_iterator UI = N->use_begin(), UE = N->use_end(); + UI != UE; ++UI) + AddToWorkList(*UI); + } + + /// visit - call the node-specific routine that knows how to fold each + /// particular type of node. + SDValue visit(SDNode *N); + + public: + /// AddToWorkList - Add to the work list making sure it's instance is at the + /// the back (next to be processed.) + void AddToWorkList(SDNode *N) { + removeFromWorkList(N); + WorkList.push_back(N); + } + + /// removeFromWorkList - remove all instances of N from the worklist. + /// + void removeFromWorkList(SDNode *N) { + WorkList.erase(std::remove(WorkList.begin(), WorkList.end(), N), + WorkList.end()); + } + + SDValue CombineTo(SDNode *N, const SDValue *To, unsigned NumTo, + bool AddTo = true); + + SDValue CombineTo(SDNode *N, SDValue Res, bool AddTo = true) { + return CombineTo(N, &Res, 1, AddTo); + } + + SDValue CombineTo(SDNode *N, SDValue Res0, SDValue Res1, + bool AddTo = true) { + SDValue To[] = { Res0, Res1 }; + return CombineTo(N, To, 2, AddTo); + } + + void CommitTargetLoweringOpt(const TargetLowering::TargetLoweringOpt &TLO); + + private: + + /// SimplifyDemandedBits - Check the specified integer node value to see if + /// it can be simplified or if things it uses can be simplified by bit + /// propagation. If so, return true. + bool SimplifyDemandedBits(SDValue Op) { + APInt Demanded = APInt::getAllOnesValue(Op.getValueSizeInBits()); + return SimplifyDemandedBits(Op, Demanded); + } + + bool SimplifyDemandedBits(SDValue Op, const APInt &Demanded); + + bool CombineToPreIndexedLoadStore(SDNode *N); + bool CombineToPostIndexedLoadStore(SDNode *N); + + + /// combine - call the node-specific routine that knows how to fold each + /// particular type of node. If that doesn't do anything, try the + /// target-specific DAG combines. + SDValue combine(SDNode *N); + + // Visitation implementation - Implement dag node combining for different + // node types. The semantics are as follows: + // Return Value: + // SDValue.getNode() == 0 - No change was made + // SDValue.getNode() == N - N was replaced, is dead and has been handled. + // otherwise - N should be replaced by the returned Operand. + // + SDValue visitTokenFactor(SDNode *N); + SDValue visitMERGE_VALUES(SDNode *N); + SDValue visitADD(SDNode *N); + SDValue visitSUB(SDNode *N); + SDValue visitADDC(SDNode *N); + SDValue visitADDE(SDNode *N); + SDValue visitMUL(SDNode *N); + SDValue visitSDIV(SDNode *N); + SDValue visitUDIV(SDNode *N); + SDValue visitSREM(SDNode *N); + SDValue visitUREM(SDNode *N); + SDValue visitMULHU(SDNode *N); + SDValue visitMULHS(SDNode *N); + SDValue visitSMUL_LOHI(SDNode *N); + SDValue visitUMUL_LOHI(SDNode *N); + SDValue visitSDIVREM(SDNode *N); + SDValue visitUDIVREM(SDNode *N); + SDValue visitAND(SDNode *N); + SDValue visitOR(SDNode *N); + SDValue visitXOR(SDNode *N); + SDValue SimplifyVBinOp(SDNode *N); + SDValue visitSHL(SDNode *N); + SDValue visitSRA(SDNode *N); + SDValue visitSRL(SDNode *N); + SDValue visitCTLZ(SDNode *N); + SDValue visitCTTZ(SDNode *N); + SDValue visitCTPOP(SDNode *N); + SDValue visitSELECT(SDNode *N); + SDValue visitSELECT_CC(SDNode *N); + SDValue visitSETCC(SDNode *N); + SDValue visitSIGN_EXTEND(SDNode *N); + SDValue visitZERO_EXTEND(SDNode *N); + SDValue visitANY_EXTEND(SDNode *N); + SDValue visitSIGN_EXTEND_INREG(SDNode *N); + SDValue visitTRUNCATE(SDNode *N); + SDValue visitBIT_CONVERT(SDNode *N); + SDValue visitBUILD_PAIR(SDNode *N); + SDValue visitFADD(SDNode *N); + SDValue visitFSUB(SDNode *N); + SDValue visitFMUL(SDNode *N); + SDValue visitFDIV(SDNode *N); + SDValue visitFREM(SDNode *N); + SDValue visitFCOPYSIGN(SDNode *N); + SDValue visitSINT_TO_FP(SDNode *N); + SDValue visitUINT_TO_FP(SDNode *N); + SDValue visitFP_TO_SINT(SDNode *N); + SDValue visitFP_TO_UINT(SDNode *N); + SDValue visitFP_ROUND(SDNode *N); + SDValue visitFP_ROUND_INREG(SDNode *N); + SDValue visitFP_EXTEND(SDNode *N); + SDValue visitFNEG(SDNode *N); + SDValue visitFABS(SDNode *N); + SDValue visitBRCOND(SDNode *N); + SDValue visitBR_CC(SDNode *N); + SDValue visitLOAD(SDNode *N); + SDValue visitSTORE(SDNode *N); + SDValue visitINSERT_VECTOR_ELT(SDNode *N); + SDValue visitEXTRACT_VECTOR_ELT(SDNode *N); + SDValue visitBUILD_VECTOR(SDNode *N); + SDValue visitCONCAT_VECTORS(SDNode *N); + SDValue visitVECTOR_SHUFFLE(SDNode *N); + + SDValue XformToShuffleWithZero(SDNode *N); + SDValue ReassociateOps(unsigned Opc, DebugLoc DL, SDValue LHS, SDValue RHS); + + SDValue visitShiftByConstant(SDNode *N, unsigned Amt); + + bool SimplifySelectOps(SDNode *SELECT, SDValue LHS, SDValue RHS); + SDValue SimplifyBinOpWithSameOpcodeHands(SDNode *N); + SDValue SimplifySelect(DebugLoc DL, SDValue N0, SDValue N1, SDValue N2); + SDValue SimplifySelectCC(DebugLoc DL, SDValue N0, SDValue N1, SDValue N2, + SDValue N3, ISD::CondCode CC, + bool NotExtCompare = false); + SDValue SimplifySetCC(EVT VT, SDValue N0, SDValue N1, ISD::CondCode Cond, + DebugLoc DL, bool foldBooleans = true); + SDValue SimplifyNodeWithTwoResults(SDNode *N, unsigned LoOp, + unsigned HiOp); + SDValue CombineConsecutiveLoads(SDNode *N, EVT VT); + SDValue ConstantFoldBIT_CONVERTofBUILD_VECTOR(SDNode *, EVT); + SDValue BuildSDIV(SDNode *N); + SDValue BuildUDIV(SDNode *N); + SDNode *MatchRotate(SDValue LHS, SDValue RHS, DebugLoc DL); + SDValue ReduceLoadWidth(SDNode *N); + SDValue ReduceLoadOpStoreWidth(SDNode *N); + + SDValue GetDemandedBits(SDValue V, const APInt &Mask); + + /// GatherAllAliases - Walk up chain skipping non-aliasing memory nodes, + /// looking for aliasing nodes and adding them to the Aliases vector. + void GatherAllAliases(SDNode *N, SDValue OriginalChain, + SmallVector &Aliases); + + /// isAlias - Return true if there is any possibility that the two addresses + /// overlap. + bool isAlias(SDValue Ptr1, int64_t Size1, + const Value *SrcValue1, int SrcValueOffset1, + unsigned SrcValueAlign1, + SDValue Ptr2, int64_t Size2, + const Value *SrcValue2, int SrcValueOffset2, + unsigned SrcValueAlign2) const; + + /// FindAliasInfo - Extracts the relevant alias information from the memory + /// node. Returns true if the operand was a load. + bool FindAliasInfo(SDNode *N, + SDValue &Ptr, int64_t &Size, + const Value *&SrcValue, int &SrcValueOffset, + unsigned &SrcValueAlignment) const; + + /// FindBetterChain - Walk up chain skipping non-aliasing memory nodes, + /// looking for a better chain (aliasing node.) + SDValue FindBetterChain(SDNode *N, SDValue Chain); + + /// getShiftAmountTy - Returns a type large enough to hold any valid + /// shift amount - before type legalization these can be huge. + EVT getShiftAmountTy() { + return LegalTypes ? TLI.getShiftAmountTy() : TLI.getPointerTy(); + } + +public: + DAGCombiner(SelectionDAG &D, AliasAnalysis &A, CodeGenOpt::Level OL) + : DAG(D), + TLI(D.getTargetLoweringInfo()), + Level(Unrestricted), + OptLevel(OL), + LegalOperations(false), + LegalTypes(false), + AA(A) {} + + /// Run - runs the dag combiner on all nodes in the work list + void Run(CombineLevel AtLevel); + }; +} + + +namespace { +/// WorkListRemover - This class is a DAGUpdateListener that removes any deleted +/// nodes from the worklist. +class WorkListRemover : public SelectionDAG::DAGUpdateListener { + DAGCombiner &DC; +public: + explicit WorkListRemover(DAGCombiner &dc) : DC(dc) {} + + virtual void NodeDeleted(SDNode *N, SDNode *E) { + DC.removeFromWorkList(N); + } + + virtual void NodeUpdated(SDNode *N) { + // Ignore updates. + } +}; +} + +//===----------------------------------------------------------------------===// +// TargetLowering::DAGCombinerInfo implementation +//===----------------------------------------------------------------------===// + +void TargetLowering::DAGCombinerInfo::AddToWorklist(SDNode *N) { + ((DAGCombiner*)DC)->AddToWorkList(N); +} + +SDValue TargetLowering::DAGCombinerInfo:: +CombineTo(SDNode *N, const std::vector &To, bool AddTo) { + return ((DAGCombiner*)DC)->CombineTo(N, &To[0], To.size(), AddTo); +} + +SDValue TargetLowering::DAGCombinerInfo:: +CombineTo(SDNode *N, SDValue Res, bool AddTo) { + return ((DAGCombiner*)DC)->CombineTo(N, Res, AddTo); +} + + +SDValue TargetLowering::DAGCombinerInfo:: +CombineTo(SDNode *N, SDValue Res0, SDValue Res1, bool AddTo) { + return ((DAGCombiner*)DC)->CombineTo(N, Res0, Res1, AddTo); +} + +void TargetLowering::DAGCombinerInfo:: +CommitTargetLoweringOpt(const TargetLowering::TargetLoweringOpt &TLO) { + return ((DAGCombiner*)DC)->CommitTargetLoweringOpt(TLO); +} + +//===----------------------------------------------------------------------===// +// Helper Functions +//===----------------------------------------------------------------------===// + +/// isNegatibleForFree - Return 1 if we can compute the negated form of the +/// specified expression for the same cost as the expression itself, or 2 if we +/// can compute the negated form more cheaply than the expression itself. +static char isNegatibleForFree(SDValue Op, bool LegalOperations, + unsigned Depth = 0) { + // No compile time optimizations on this type. + if (Op.getValueType() == MVT::ppcf128) + return 0; + + // fneg is removable even if it has multiple uses. + if (Op.getOpcode() == ISD::FNEG) return 2; + + // Don't allow anything with multiple uses. + if (!Op.hasOneUse()) return 0; + + // Don't recurse exponentially. + if (Depth > 6) return 0; + + switch (Op.getOpcode()) { + default: return false; + case ISD::ConstantFP: + // Don't invert constant FP values after legalize. The negated constant + // isn't necessarily legal. + return LegalOperations ? 0 : 1; + case ISD::FADD: + // FIXME: determine better conditions for this xform. + if (!UnsafeFPMath) return 0; + + // fold (fsub (fadd A, B)) -> (fsub (fneg A), B) + if (char V = isNegatibleForFree(Op.getOperand(0), LegalOperations, Depth+1)) + return V; + // fold (fneg (fadd A, B)) -> (fsub (fneg B), A) + return isNegatibleForFree(Op.getOperand(1), LegalOperations, Depth+1); + case ISD::FSUB: + // We can't turn -(A-B) into B-A when we honor signed zeros. + if (!UnsafeFPMath) return 0; + + // fold (fneg (fsub A, B)) -> (fsub B, A) + return 1; + + case ISD::FMUL: + case ISD::FDIV: + if (HonorSignDependentRoundingFPMath()) return 0; + + // fold (fneg (fmul X, Y)) -> (fmul (fneg X), Y) or (fmul X, (fneg Y)) + if (char V = isNegatibleForFree(Op.getOperand(0), LegalOperations, Depth+1)) + return V; + + return isNegatibleForFree(Op.getOperand(1), LegalOperations, Depth+1); + + case ISD::FP_EXTEND: + case ISD::FP_ROUND: + case ISD::FSIN: + return isNegatibleForFree(Op.getOperand(0), LegalOperations, Depth+1); + } +} + +/// GetNegatedExpression - If isNegatibleForFree returns true, this function +/// returns the newly negated expression. +static SDValue GetNegatedExpression(SDValue Op, SelectionDAG &DAG, + bool LegalOperations, unsigned Depth = 0) { + // fneg is removable even if it has multiple uses. + if (Op.getOpcode() == ISD::FNEG) return Op.getOperand(0); + + // Don't allow anything with multiple uses. + assert(Op.hasOneUse() && "Unknown reuse!"); + + assert(Depth <= 6 && "GetNegatedExpression doesn't match isNegatibleForFree"); + switch (Op.getOpcode()) { + default: llvm_unreachable("Unknown code"); + case ISD::ConstantFP: { + APFloat V = cast(Op)->getValueAPF(); + V.changeSign(); + return DAG.getConstantFP(V, Op.getValueType()); + } + case ISD::FADD: + // FIXME: determine better conditions for this xform. + assert(UnsafeFPMath); + + // fold (fneg (fadd A, B)) -> (fsub (fneg A), B) + if (isNegatibleForFree(Op.getOperand(0), LegalOperations, Depth+1)) + return DAG.getNode(ISD::FSUB, Op.getDebugLoc(), Op.getValueType(), + GetNegatedExpression(Op.getOperand(0), DAG, + LegalOperations, Depth+1), + Op.getOperand(1)); + // fold (fneg (fadd A, B)) -> (fsub (fneg B), A) + return DAG.getNode(ISD::FSUB, Op.getDebugLoc(), Op.getValueType(), + GetNegatedExpression(Op.getOperand(1), DAG, + LegalOperations, Depth+1), + Op.getOperand(0)); + case ISD::FSUB: + // We can't turn -(A-B) into B-A when we honor signed zeros. + assert(UnsafeFPMath); + + // fold (fneg (fsub 0, B)) -> B + if (ConstantFPSDNode *N0CFP = dyn_cast(Op.getOperand(0))) + if (N0CFP->getValueAPF().isZero()) + return Op.getOperand(1); + + // fold (fneg (fsub A, B)) -> (fsub B, A) + return DAG.getNode(ISD::FSUB, Op.getDebugLoc(), Op.getValueType(), + Op.getOperand(1), Op.getOperand(0)); + + case ISD::FMUL: + case ISD::FDIV: + assert(!HonorSignDependentRoundingFPMath()); + + // fold (fneg (fmul X, Y)) -> (fmul (fneg X), Y) + if (isNegatibleForFree(Op.getOperand(0), LegalOperations, Depth+1)) + return DAG.getNode(Op.getOpcode(), Op.getDebugLoc(), Op.getValueType(), + GetNegatedExpression(Op.getOperand(0), DAG, + LegalOperations, Depth+1), + Op.getOperand(1)); + + // fold (fneg (fmul X, Y)) -> (fmul X, (fneg Y)) + return DAG.getNode(Op.getOpcode(), Op.getDebugLoc(), Op.getValueType(), + Op.getOperand(0), + GetNegatedExpression(Op.getOperand(1), DAG, + LegalOperations, Depth+1)); + + case ISD::FP_EXTEND: + case ISD::FSIN: + return DAG.getNode(Op.getOpcode(), Op.getDebugLoc(), Op.getValueType(), + GetNegatedExpression(Op.getOperand(0), DAG, + LegalOperations, Depth+1)); + case ISD::FP_ROUND: + return DAG.getNode(ISD::FP_ROUND, Op.getDebugLoc(), Op.getValueType(), + GetNegatedExpression(Op.getOperand(0), DAG, + LegalOperations, Depth+1), + Op.getOperand(1)); + } +} + + +// isSetCCEquivalent - Return true if this node is a setcc, or is a select_cc +// that selects between the values 1 and 0, making it equivalent to a setcc. +// Also, set the incoming LHS, RHS, and CC references to the appropriate +// nodes based on the type of node we are checking. This simplifies life a +// bit for the callers. +static bool isSetCCEquivalent(SDValue N, SDValue &LHS, SDValue &RHS, + SDValue &CC) { + if (N.getOpcode() == ISD::SETCC) { + LHS = N.getOperand(0); + RHS = N.getOperand(1); + CC = N.getOperand(2); + return true; + } + if (N.getOpcode() == ISD::SELECT_CC && + N.getOperand(2).getOpcode() == ISD::Constant && + N.getOperand(3).getOpcode() == ISD::Constant && + cast(N.getOperand(2))->getAPIntValue() == 1 && + cast(N.getOperand(3))->isNullValue()) { + LHS = N.getOperand(0); + RHS = N.getOperand(1); + CC = N.getOperand(4); + return true; + } + return false; +} + +// isOneUseSetCC - Return true if this is a SetCC-equivalent operation with only +// one use. If this is true, it allows the users to invert the operation for +// free when it is profitable to do so. +static bool isOneUseSetCC(SDValue N) { + SDValue N0, N1, N2; + if (isSetCCEquivalent(N, N0, N1, N2) && N.getNode()->hasOneUse()) + return true; + return false; +} + +SDValue DAGCombiner::ReassociateOps(unsigned Opc, DebugLoc DL, + SDValue N0, SDValue N1) { + EVT VT = N0.getValueType(); + if (N0.getOpcode() == Opc && isa(N0.getOperand(1))) { + if (isa(N1)) { + // reassoc. (op (op x, c1), c2) -> (op x, (op c1, c2)) + SDValue OpNode = + DAG.FoldConstantArithmetic(Opc, VT, + cast(N0.getOperand(1)), + cast(N1)); + return DAG.getNode(Opc, DL, VT, N0.getOperand(0), OpNode); + } else if (N0.hasOneUse()) { + // reassoc. (op (op x, c1), y) -> (op (op x, y), c1) iff x+c1 has one use + SDValue OpNode = DAG.getNode(Opc, N0.getDebugLoc(), VT, + N0.getOperand(0), N1); + AddToWorkList(OpNode.getNode()); + return DAG.getNode(Opc, DL, VT, OpNode, N0.getOperand(1)); + } + } + + if (N1.getOpcode() == Opc && isa(N1.getOperand(1))) { + if (isa(N0)) { + // reassoc. (op c2, (op x, c1)) -> (op x, (op c1, c2)) + SDValue OpNode = + DAG.FoldConstantArithmetic(Opc, VT, + cast(N1.getOperand(1)), + cast(N0)); + return DAG.getNode(Opc, DL, VT, N1.getOperand(0), OpNode); + } else if (N1.hasOneUse()) { + // reassoc. (op y, (op x, c1)) -> (op (op x, y), c1) iff x+c1 has one use + SDValue OpNode = DAG.getNode(Opc, N0.getDebugLoc(), VT, + N1.getOperand(0), N0); + AddToWorkList(OpNode.getNode()); + return DAG.getNode(Opc, DL, VT, OpNode, N1.getOperand(1)); + } + } + + return SDValue(); +} + +SDValue DAGCombiner::CombineTo(SDNode *N, const SDValue *To, unsigned NumTo, + bool AddTo) { + assert(N->getNumValues() == NumTo && "Broken CombineTo call!"); + ++NodesCombined; + DEBUG(errs() << "\nReplacing.1 "; + N->dump(&DAG); + errs() << "\nWith: "; + To[0].getNode()->dump(&DAG); + errs() << " and " << NumTo-1 << " other values\n"; + for (unsigned i = 0, e = NumTo; i != e; ++i) + assert(N->getValueType(i) == To[i].getValueType() && + "Cannot combine value to value of different type!")); + WorkListRemover DeadNodes(*this); + DAG.ReplaceAllUsesWith(N, To, &DeadNodes); + + if (AddTo) { + // Push the new nodes and any users onto the worklist + for (unsigned i = 0, e = NumTo; i != e; ++i) { + if (To[i].getNode()) { + AddToWorkList(To[i].getNode()); + AddUsersToWorkList(To[i].getNode()); + } + } + } + + // Finally, if the node is now dead, remove it from the graph. The node + // may not be dead if the replacement process recursively simplified to + // something else needing this node. + if (N->use_empty()) { + // Nodes can be reintroduced into the worklist. Make sure we do not + // process a node that has been replaced. + removeFromWorkList(N); + + // Finally, since the node is now dead, remove it from the graph. + DAG.DeleteNode(N); + } + return SDValue(N, 0); +} + +void +DAGCombiner::CommitTargetLoweringOpt(const TargetLowering::TargetLoweringOpt & + TLO) { + // Replace all uses. If any nodes become isomorphic to other nodes and + // are deleted, make sure to remove them from our worklist. + WorkListRemover DeadNodes(*this); + DAG.ReplaceAllUsesOfValueWith(TLO.Old, TLO.New, &DeadNodes); + + // Push the new node and any (possibly new) users onto the worklist. + AddToWorkList(TLO.New.getNode()); + AddUsersToWorkList(TLO.New.getNode()); + + // Finally, if the node is now dead, remove it from the graph. The node + // may not be dead if the replacement process recursively simplified to + // something else needing this node. + if (TLO.Old.getNode()->use_empty()) { + removeFromWorkList(TLO.Old.getNode()); + + // If the operands of this node are only used by the node, they will now + // be dead. Make sure to visit them first to delete dead nodes early. + for (unsigned i = 0, e = TLO.Old.getNode()->getNumOperands(); i != e; ++i) + if (TLO.Old.getNode()->getOperand(i).getNode()->hasOneUse()) + AddToWorkList(TLO.Old.getNode()->getOperand(i).getNode()); + + DAG.DeleteNode(TLO.Old.getNode()); + } +} + +/// SimplifyDemandedBits - Check the specified integer node value to see if +/// it can be simplified or if things it uses can be simplified by bit +/// propagation. If so, return true. +bool DAGCombiner::SimplifyDemandedBits(SDValue Op, const APInt &Demanded) { + TargetLowering::TargetLoweringOpt TLO(DAG); + APInt KnownZero, KnownOne; + if (!TLI.SimplifyDemandedBits(Op, Demanded, KnownZero, KnownOne, TLO)) + return false; + + // Revisit the node. + AddToWorkList(Op.getNode()); + + // Replace the old value with the new one. + ++NodesCombined; + DEBUG(errs() << "\nReplacing.2 "; + TLO.Old.getNode()->dump(&DAG); + errs() << "\nWith: "; + TLO.New.getNode()->dump(&DAG); + errs() << '\n'); + + CommitTargetLoweringOpt(TLO); + return true; +} + +//===----------------------------------------------------------------------===// +// Main DAG Combiner implementation +//===----------------------------------------------------------------------===// + +void DAGCombiner::Run(CombineLevel AtLevel) { + // set the instance variables, so that the various visit routines may use it. + Level = AtLevel; + LegalOperations = Level >= NoIllegalOperations; + LegalTypes = Level >= NoIllegalTypes; + + // Add all the dag nodes to the worklist. + WorkList.reserve(DAG.allnodes_size()); + for (SelectionDAG::allnodes_iterator I = DAG.allnodes_begin(), + E = DAG.allnodes_end(); I != E; ++I) + WorkList.push_back(I); + + // Create a dummy node (which is not added to allnodes), that adds a reference + // to the root node, preventing it from being deleted, and tracking any + // changes of the root. + HandleSDNode Dummy(DAG.getRoot()); + + // The root of the dag may dangle to deleted nodes until the dag combiner is + // done. Set it to null to avoid confusion. + DAG.setRoot(SDValue()); + + // while the worklist isn't empty, inspect the node on the end of it and + // try and combine it. + while (!WorkList.empty()) { + SDNode *N = WorkList.back(); + WorkList.pop_back(); + + // If N has no uses, it is dead. Make sure to revisit all N's operands once + // N is deleted from the DAG, since they too may now be dead or may have a + // reduced number of uses, allowing other xforms. + if (N->use_empty() && N != &Dummy) { + for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) + AddToWorkList(N->getOperand(i).getNode()); + + DAG.DeleteNode(N); + continue; + } + + SDValue RV = combine(N); + + if (RV.getNode() == 0) + continue; + + ++NodesCombined; + + // If we get back the same node we passed in, rather than a new node or + // zero, we know that the node must have defined multiple values and + // CombineTo was used. Since CombineTo takes care of the worklist + // mechanics for us, we have no work to do in this case. + if (RV.getNode() == N) + continue; + + assert(N->getOpcode() != ISD::DELETED_NODE && + RV.getNode()->getOpcode() != ISD::DELETED_NODE && + "Node was deleted but visit returned new node!"); + + DEBUG(errs() << "\nReplacing.3 "; + N->dump(&DAG); + errs() << "\nWith: "; + RV.getNode()->dump(&DAG); + errs() << '\n'); + WorkListRemover DeadNodes(*this); + if (N->getNumValues() == RV.getNode()->getNumValues()) + DAG.ReplaceAllUsesWith(N, RV.getNode(), &DeadNodes); + else { + assert(N->getValueType(0) == RV.getValueType() && + N->getNumValues() == 1 && "Type mismatch"); + SDValue OpV = RV; + DAG.ReplaceAllUsesWith(N, &OpV, &DeadNodes); + } + + // Push the new node and any users onto the worklist + AddToWorkList(RV.getNode()); + AddUsersToWorkList(RV.getNode()); + + // Add any uses of the old node to the worklist in case this node is the + // last one that uses them. They may become dead after this node is + // deleted. + for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) + AddToWorkList(N->getOperand(i).getNode()); + + // Finally, if the node is now dead, remove it from the graph. The node + // may not be dead if the replacement process recursively simplified to + // something else needing this node. + if (N->use_empty()) { + // Nodes can be reintroduced into the worklist. Make sure we do not + // process a node that has been replaced. + removeFromWorkList(N); + + // Finally, since the node is now dead, remove it from the graph. + DAG.DeleteNode(N); + } + } + + // If the root changed (e.g. it was a dead load, update the root). + DAG.setRoot(Dummy.getValue()); +} + +SDValue DAGCombiner::visit(SDNode *N) { + switch(N->getOpcode()) { + default: break; + case ISD::TokenFactor: return visitTokenFactor(N); + case ISD::MERGE_VALUES: return visitMERGE_VALUES(N); + case ISD::ADD: return visitADD(N); + case ISD::SUB: return visitSUB(N); + case ISD::ADDC: return visitADDC(N); + case ISD::ADDE: return visitADDE(N); + case ISD::MUL: return visitMUL(N); + case ISD::SDIV: return visitSDIV(N); + case ISD::UDIV: return visitUDIV(N); + case ISD::SREM: return visitSREM(N); + case ISD::UREM: return visitUREM(N); + case ISD::MULHU: return visitMULHU(N); + case ISD::MULHS: return visitMULHS(N); + case ISD::SMUL_LOHI: return visitSMUL_LOHI(N); + case ISD::UMUL_LOHI: return visitUMUL_LOHI(N); + case ISD::SDIVREM: return visitSDIVREM(N); + case ISD::UDIVREM: return visitUDIVREM(N); + case ISD::AND: return visitAND(N); + case ISD::OR: return visitOR(N); + case ISD::XOR: return visitXOR(N); + case ISD::SHL: return visitSHL(N); + case ISD::SRA: return visitSRA(N); + case ISD::SRL: return visitSRL(N); + case ISD::CTLZ: return visitCTLZ(N); + case ISD::CTTZ: return visitCTTZ(N); + case ISD::CTPOP: return visitCTPOP(N); + case ISD::SELECT: return visitSELECT(N); + case ISD::SELECT_CC: return visitSELECT_CC(N); + case ISD::SETCC: return visitSETCC(N); + case ISD::SIGN_EXTEND: return visitSIGN_EXTEND(N); + case ISD::ZERO_EXTEND: return visitZERO_EXTEND(N); + case ISD::ANY_EXTEND: return visitANY_EXTEND(N); + case ISD::SIGN_EXTEND_INREG: return visitSIGN_EXTEND_INREG(N); + case ISD::TRUNCATE: return visitTRUNCATE(N); + case ISD::BIT_CONVERT: return visitBIT_CONVERT(N); + case ISD::BUILD_PAIR: return visitBUILD_PAIR(N); + case ISD::FADD: return visitFADD(N); + case ISD::FSUB: return visitFSUB(N); + case ISD::FMUL: return visitFMUL(N); + case ISD::FDIV: return visitFDIV(N); + case ISD::FREM: return visitFREM(N); + case ISD::FCOPYSIGN: return visitFCOPYSIGN(N); + case ISD::SINT_TO_FP: return visitSINT_TO_FP(N); + case ISD::UINT_TO_FP: return visitUINT_TO_FP(N); + case ISD::FP_TO_SINT: return visitFP_TO_SINT(N); + case ISD::FP_TO_UINT: return visitFP_TO_UINT(N); + case ISD::FP_ROUND: return visitFP_ROUND(N); + case ISD::FP_ROUND_INREG: return visitFP_ROUND_INREG(N); + case ISD::FP_EXTEND: return visitFP_EXTEND(N); + case ISD::FNEG: return visitFNEG(N); + case ISD::FABS: return visitFABS(N); + case ISD::BRCOND: return visitBRCOND(N); + case ISD::BR_CC: return visitBR_CC(N); + case ISD::LOAD: return visitLOAD(N); + case ISD::STORE: return visitSTORE(N); + case ISD::INSERT_VECTOR_ELT: return visitINSERT_VECTOR_ELT(N); + case ISD::EXTRACT_VECTOR_ELT: return visitEXTRACT_VECTOR_ELT(N); + case ISD::BUILD_VECTOR: return visitBUILD_VECTOR(N); + case ISD::CONCAT_VECTORS: return visitCONCAT_VECTORS(N); + case ISD::VECTOR_SHUFFLE: return visitVECTOR_SHUFFLE(N); + } + return SDValue(); +} + +SDValue DAGCombiner::combine(SDNode *N) { + SDValue RV = visit(N); + + // If nothing happened, try a target-specific DAG combine. + if (RV.getNode() == 0) { + assert(N->getOpcode() != ISD::DELETED_NODE && + "Node was deleted but visit returned NULL!"); + + if (N->getOpcode() >= ISD::BUILTIN_OP_END || + TLI.hasTargetDAGCombine((ISD::NodeType)N->getOpcode())) { + + // Expose the DAG combiner to the target combiner impls. + TargetLowering::DAGCombinerInfo + DagCombineInfo(DAG, !LegalTypes, !LegalOperations, false, this); + + RV = TLI.PerformDAGCombine(N, DagCombineInfo); + } + } + + // If N is a commutative binary node, try commuting it to enable more + // sdisel CSE. + if (RV.getNode() == 0 && + SelectionDAG::isCommutativeBinOp(N->getOpcode()) && + N->getNumValues() == 1) { + SDValue N0 = N->getOperand(0); + SDValue N1 = N->getOperand(1); + + // Constant operands are canonicalized to RHS. + if (isa(N0) || !isa(N1)) { + SDValue Ops[] = { N1, N0 }; + SDNode *CSENode = DAG.getNodeIfExists(N->getOpcode(), N->getVTList(), + Ops, 2); + if (CSENode) + return SDValue(CSENode, 0); + } + } + + return RV; +} + +/// getInputChainForNode - Given a node, return its input chain if it has one, +/// otherwise return a null sd operand. +static SDValue getInputChainForNode(SDNode *N) { + if (unsigned NumOps = N->getNumOperands()) { + if (N->getOperand(0).getValueType() == MVT::Other) + return N->getOperand(0); + else if (N->getOperand(NumOps-1).getValueType() == MVT::Other) + return N->getOperand(NumOps-1); + for (unsigned i = 1; i < NumOps-1; ++i) + if (N->getOperand(i).getValueType() == MVT::Other) + return N->getOperand(i); + } + return SDValue(); +} + +SDValue DAGCombiner::visitTokenFactor(SDNode *N) { + // If N has two operands, where one has an input chain equal to the other, + // the 'other' chain is redundant. + if (N->getNumOperands() == 2) { + if (getInputChainForNode(N->getOperand(0).getNode()) == N->getOperand(1)) + return N->getOperand(0); + if (getInputChainForNode(N->getOperand(1).getNode()) == N->getOperand(0)) + return N->getOperand(1); + } + + SmallVector TFs; // List of token factors to visit. + SmallVector Ops; // Ops for replacing token factor. + SmallPtrSet SeenOps; + bool Changed = false; // If we should replace this token factor. + + // Start out with this token factor. + TFs.push_back(N); + + // Iterate through token factors. The TFs grows when new token factors are + // encountered. + for (unsigned i = 0; i < TFs.size(); ++i) { + SDNode *TF = TFs[i]; + + // Check each of the operands. + for (unsigned i = 0, ie = TF->getNumOperands(); i != ie; ++i) { + SDValue Op = TF->getOperand(i); + + switch (Op.getOpcode()) { + case ISD::EntryToken: + // Entry tokens don't need to be added to the list. They are + // rededundant. + Changed = true; + break; + + case ISD::TokenFactor: + if (Op.hasOneUse() && + std::find(TFs.begin(), TFs.end(), Op.getNode()) == TFs.end()) { + // Queue up for processing. + TFs.push_back(Op.getNode()); + // Clean up in case the token factor is removed. + AddToWorkList(Op.getNode()); + Changed = true; + break; + } + // Fall thru + + default: + // Only add if it isn't already in the list. + if (SeenOps.insert(Op.getNode())) + Ops.push_back(Op); + else + Changed = true; + break; + } + } + } + + SDValue Result; + + // If we've change things around then replace token factor. + if (Changed) { + if (Ops.empty()) { + // The entry token is the only possible outcome. + Result = DAG.getEntryNode(); + } else { + // New and improved token factor. + Result = DAG.getNode(ISD::TokenFactor, N->getDebugLoc(), + MVT::Other, &Ops[0], Ops.size()); + } + + // Don't add users to work list. + return CombineTo(N, Result, false); + } + + return Result; +} + +/// MERGE_VALUES can always be eliminated. +SDValue DAGCombiner::visitMERGE_VALUES(SDNode *N) { + WorkListRemover DeadNodes(*this); + // Replacing results may cause a different MERGE_VALUES to suddenly + // be CSE'd with N, and carry its uses with it. Iterate until no + // uses remain, to ensure that the node can be safely deleted. + do { + for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) + DAG.ReplaceAllUsesOfValueWith(SDValue(N, i), N->getOperand(i), + &DeadNodes); + } while (!N->use_empty()); + removeFromWorkList(N); + DAG.DeleteNode(N); + return SDValue(N, 0); // Return N so it doesn't get rechecked! +} + +static +SDValue combineShlAddConstant(DebugLoc DL, SDValue N0, SDValue N1, + SelectionDAG &DAG) { + EVT VT = N0.getValueType(); + SDValue N00 = N0.getOperand(0); + SDValue N01 = N0.getOperand(1); + ConstantSDNode *N01C = dyn_cast(N01); + + if (N01C && N00.getOpcode() == ISD::ADD && N00.getNode()->hasOneUse() && + isa(N00.getOperand(1))) { + // fold (add (shl (add x, c1), c2), ) -> (add (add (shl x, c2), c1<getOperand(0); + SDValue N1 = N->getOperand(1); + ConstantSDNode *N0C = dyn_cast(N0); + ConstantSDNode *N1C = dyn_cast(N1); + EVT VT = N0.getValueType(); + + // fold vector ops + if (VT.isVector()) { + SDValue FoldedVOp = SimplifyVBinOp(N); + if (FoldedVOp.getNode()) return FoldedVOp; + } + + // fold (add x, undef) -> undef + if (N0.getOpcode() == ISD::UNDEF) + return N0; + if (N1.getOpcode() == ISD::UNDEF) + return N1; + // fold (add c1, c2) -> c1+c2 + if (N0C && N1C) + return DAG.FoldConstantArithmetic(ISD::ADD, VT, N0C, N1C); + // canonicalize constant to RHS + if (N0C && !N1C) + return DAG.getNode(ISD::ADD, N->getDebugLoc(), VT, N1, N0); + // fold (add x, 0) -> x + if (N1C && N1C->isNullValue()) + return N0; + // fold (add Sym, c) -> Sym+c + if (GlobalAddressSDNode *GA = dyn_cast(N0)) + if (!LegalOperations && TLI.isOffsetFoldingLegal(GA) && N1C && + GA->getOpcode() == ISD::GlobalAddress) + return DAG.getGlobalAddress(GA->getGlobal(), VT, + GA->getOffset() + + (uint64_t)N1C->getSExtValue()); + // fold ((c1-A)+c2) -> (c1+c2)-A + if (N1C && N0.getOpcode() == ISD::SUB) + if (ConstantSDNode *N0C = dyn_cast(N0.getOperand(0))) + return DAG.getNode(ISD::SUB, N->getDebugLoc(), VT, + DAG.getConstant(N1C->getAPIntValue()+ + N0C->getAPIntValue(), VT), + N0.getOperand(1)); + // reassociate add + SDValue RADD = ReassociateOps(ISD::ADD, N->getDebugLoc(), N0, N1); + if (RADD.getNode() != 0) + return RADD; + // fold ((0-A) + B) -> B-A + if (N0.getOpcode() == ISD::SUB && isa(N0.getOperand(0)) && + cast(N0.getOperand(0))->isNullValue()) + return DAG.getNode(ISD::SUB, N->getDebugLoc(), VT, N1, N0.getOperand(1)); + // fold (A + (0-B)) -> A-B + if (N1.getOpcode() == ISD::SUB && isa(N1.getOperand(0)) && + cast(N1.getOperand(0))->isNullValue()) + return DAG.getNode(ISD::SUB, N->getDebugLoc(), VT, N0, N1.getOperand(1)); + // fold (A+(B-A)) -> B + if (N1.getOpcode() == ISD::SUB && N0 == N1.getOperand(1)) + return N1.getOperand(0); + // fold ((B-A)+A) -> B + if (N0.getOpcode() == ISD::SUB && N1 == N0.getOperand(1)) + return N0.getOperand(0); + // fold (A+(B-(A+C))) to (B-C) + if (N1.getOpcode() == ISD::SUB && N1.getOperand(1).getOpcode() == ISD::ADD && + N0 == N1.getOperand(1).getOperand(0)) + return DAG.getNode(ISD::SUB, N->getDebugLoc(), VT, N1.getOperand(0), + N1.getOperand(1).getOperand(1)); + // fold (A+(B-(C+A))) to (B-C) + if (N1.getOpcode() == ISD::SUB && N1.getOperand(1).getOpcode() == ISD::ADD && + N0 == N1.getOperand(1).getOperand(1)) + return DAG.getNode(ISD::SUB, N->getDebugLoc(), VT, N1.getOperand(0), + N1.getOperand(1).getOperand(0)); + // fold (A+((B-A)+or-C)) to (B+or-C) + if ((N1.getOpcode() == ISD::SUB || N1.getOpcode() == ISD::ADD) && + N1.getOperand(0).getOpcode() == ISD::SUB && + N0 == N1.getOperand(0).getOperand(1)) + return DAG.getNode(N1.getOpcode(), N->getDebugLoc(), VT, + N1.getOperand(0).getOperand(0), N1.getOperand(1)); + + // fold (A-B)+(C-D) to (A+C)-(B+D) when A or C is constant + if (N0.getOpcode() == ISD::SUB && N1.getOpcode() == ISD::SUB) { + SDValue N00 = N0.getOperand(0); + SDValue N01 = N0.getOperand(1); + SDValue N10 = N1.getOperand(0); + SDValue N11 = N1.getOperand(1); + + if (isa(N00) || isa(N10)) + return DAG.getNode(ISD::SUB, N->getDebugLoc(), VT, + DAG.getNode(ISD::ADD, N0.getDebugLoc(), VT, N00, N10), + DAG.getNode(ISD::ADD, N1.getDebugLoc(), VT, N01, N11)); + } + + if (!VT.isVector() && SimplifyDemandedBits(SDValue(N, 0))) + return SDValue(N, 0); + + // fold (a+b) -> (a|b) iff a and b share no bits. + if (VT.isInteger() && !VT.isVector()) { + APInt LHSZero, LHSOne; + APInt RHSZero, RHSOne; + APInt Mask = APInt::getAllOnesValue(VT.getSizeInBits()); + DAG.ComputeMaskedBits(N0, Mask, LHSZero, LHSOne); + + if (LHSZero.getBoolValue()) { + DAG.ComputeMaskedBits(N1, Mask, RHSZero, RHSOne); + + // If all possibly-set bits on the LHS are clear on the RHS, return an OR. + // If all possibly-set bits on the RHS are clear on the LHS, return an OR. + if ((RHSZero & (~LHSZero & Mask)) == (~LHSZero & Mask) || + (LHSZero & (~RHSZero & Mask)) == (~RHSZero & Mask)) + return DAG.getNode(ISD::OR, N->getDebugLoc(), VT, N0, N1); + } + } + + // fold (add (shl (add x, c1), c2), ) -> (add (add (shl x, c2), c1<hasOneUse()) { + SDValue Result = combineShlAddConstant(N->getDebugLoc(), N0, N1, DAG); + if (Result.getNode()) return Result; + } + if (N1.getOpcode() == ISD::SHL && N1.getNode()->hasOneUse()) { + SDValue Result = combineShlAddConstant(N->getDebugLoc(), N1, N0, DAG); + if (Result.getNode()) return Result; + } + + return SDValue(); +} + +SDValue DAGCombiner::visitADDC(SDNode *N) { + SDValue N0 = N->getOperand(0); + SDValue N1 = N->getOperand(1); + ConstantSDNode *N0C = dyn_cast(N0); + ConstantSDNode *N1C = dyn_cast(N1); + EVT VT = N0.getValueType(); + + // If the flag result is dead, turn this into an ADD. + if (N->hasNUsesOfValue(0, 1)) + return CombineTo(N, DAG.getNode(ISD::ADD, N->getDebugLoc(), VT, N1, N0), + DAG.getNode(ISD::CARRY_FALSE, + N->getDebugLoc(), MVT::Flag)); + + // canonicalize constant to RHS. + if (N0C && !N1C) + return DAG.getNode(ISD::ADDC, N->getDebugLoc(), N->getVTList(), N1, N0); + + // fold (addc x, 0) -> x + no carry out + if (N1C && N1C->isNullValue()) + return CombineTo(N, N0, DAG.getNode(ISD::CARRY_FALSE, + N->getDebugLoc(), MVT::Flag)); + + // fold (addc a, b) -> (or a, b), CARRY_FALSE iff a and b share no bits. + APInt LHSZero, LHSOne; + APInt RHSZero, RHSOne; + APInt Mask = APInt::getAllOnesValue(VT.getSizeInBits()); + DAG.ComputeMaskedBits(N0, Mask, LHSZero, LHSOne); + + if (LHSZero.getBoolValue()) { + DAG.ComputeMaskedBits(N1, Mask, RHSZero, RHSOne); + + // If all possibly-set bits on the LHS are clear on the RHS, return an OR. + // If all possibly-set bits on the RHS are clear on the LHS, return an OR. + if ((RHSZero & (~LHSZero & Mask)) == (~LHSZero & Mask) || + (LHSZero & (~RHSZero & Mask)) == (~RHSZero & Mask)) + return CombineTo(N, DAG.getNode(ISD::OR, N->getDebugLoc(), VT, N0, N1), + DAG.getNode(ISD::CARRY_FALSE, + N->getDebugLoc(), MVT::Flag)); + } + + return SDValue(); +} + +SDValue DAGCombiner::visitADDE(SDNode *N) { + SDValue N0 = N->getOperand(0); + SDValue N1 = N->getOperand(1); + SDValue CarryIn = N->getOperand(2); + ConstantSDNode *N0C = dyn_cast(N0); + ConstantSDNode *N1C = dyn_cast(N1); + + // canonicalize constant to RHS + if (N0C && !N1C) + return DAG.getNode(ISD::ADDE, N->getDebugLoc(), N->getVTList(), + N1, N0, CarryIn); + + // fold (adde x, y, false) -> (addc x, y) + if (CarryIn.getOpcode() == ISD::CARRY_FALSE) + return DAG.getNode(ISD::ADDC, N->getDebugLoc(), N->getVTList(), N1, N0); + + return SDValue(); +} + +SDValue DAGCombiner::visitSUB(SDNode *N) { + SDValue N0 = N->getOperand(0); + SDValue N1 = N->getOperand(1); + ConstantSDNode *N0C = dyn_cast(N0.getNode()); + ConstantSDNode *N1C = dyn_cast(N1.getNode()); + EVT VT = N0.getValueType(); + + // fold vector ops + if (VT.isVector()) { + SDValue FoldedVOp = SimplifyVBinOp(N); + if (FoldedVOp.getNode()) return FoldedVOp; + } + + // fold (sub x, x) -> 0 + if (N0 == N1) + return DAG.getConstant(0, N->getValueType(0)); + // fold (sub c1, c2) -> c1-c2 + if (N0C && N1C) + return DAG.FoldConstantArithmetic(ISD::SUB, VT, N0C, N1C); + // fold (sub x, c) -> (add x, -c) + if (N1C) + return DAG.getNode(ISD::ADD, N->getDebugLoc(), VT, N0, + DAG.getConstant(-N1C->getAPIntValue(), VT)); + // fold (A+B)-A -> B + if (N0.getOpcode() == ISD::ADD && N0.getOperand(0) == N1) + return N0.getOperand(1); + // fold (A+B)-B -> A + if (N0.getOpcode() == ISD::ADD && N0.getOperand(1) == N1) + return N0.getOperand(0); + // fold ((A+(B+or-C))-B) -> A+or-C + if (N0.getOpcode() == ISD::ADD && + (N0.getOperand(1).getOpcode() == ISD::SUB || + N0.getOperand(1).getOpcode() == ISD::ADD) && + N0.getOperand(1).getOperand(0) == N1) + return DAG.getNode(N0.getOperand(1).getOpcode(), N->getDebugLoc(), VT, + N0.getOperand(0), N0.getOperand(1).getOperand(1)); + // fold ((A+(C+B))-B) -> A+C + if (N0.getOpcode() == ISD::ADD && + N0.getOperand(1).getOpcode() == ISD::ADD && + N0.getOperand(1).getOperand(1) == N1) + return DAG.getNode(ISD::ADD, N->getDebugLoc(), VT, + N0.getOperand(0), N0.getOperand(1).getOperand(0)); + // fold ((A-(B-C))-C) -> A-B + if (N0.getOpcode() == ISD::SUB && + N0.getOperand(1).getOpcode() == ISD::SUB && + N0.getOperand(1).getOperand(1) == N1) + return DAG.getNode(ISD::SUB, N->getDebugLoc(), VT, + N0.getOperand(0), N0.getOperand(1).getOperand(0)); + + // If either operand of a sub is undef, the result is undef + if (N0.getOpcode() == ISD::UNDEF) + return N0; + if (N1.getOpcode() == ISD::UNDEF) + return N1; + + // If the relocation model supports it, consider symbol offsets. + if (GlobalAddressSDNode *GA = dyn_cast(N0)) + if (!LegalOperations && TLI.isOffsetFoldingLegal(GA)) { + // fold (sub Sym, c) -> Sym-c + if (N1C && GA->getOpcode() == ISD::GlobalAddress) + return DAG.getGlobalAddress(GA->getGlobal(), VT, + GA->getOffset() - + (uint64_t)N1C->getSExtValue()); + // fold (sub Sym+c1, Sym+c2) -> c1-c2 + if (GlobalAddressSDNode *GB = dyn_cast(N1)) + if (GA->getGlobal() == GB->getGlobal()) + return DAG.getConstant((uint64_t)GA->getOffset() - GB->getOffset(), + VT); + } + + return SDValue(); +} + +SDValue DAGCombiner::visitMUL(SDNode *N) { + SDValue N0 = N->getOperand(0); + SDValue N1 = N->getOperand(1); + ConstantSDNode *N0C = dyn_cast(N0); + ConstantSDNode *N1C = dyn_cast(N1); + EVT VT = N0.getValueType(); + + // fold vector ops + if (VT.isVector()) { + SDValue FoldedVOp = SimplifyVBinOp(N); + if (FoldedVOp.getNode()) return FoldedVOp; + } + + // fold (mul x, undef) -> 0 + if (N0.getOpcode() == ISD::UNDEF || N1.getOpcode() == ISD::UNDEF) + return DAG.getConstant(0, VT); + // fold (mul c1, c2) -> c1*c2 + if (N0C && N1C) + return DAG.FoldConstantArithmetic(ISD::MUL, VT, N0C, N1C); + // canonicalize constant to RHS + if (N0C && !N1C) + return DAG.getNode(ISD::MUL, N->getDebugLoc(), VT, N1, N0); + // fold (mul x, 0) -> 0 + if (N1C && N1C->isNullValue()) + return N1; + // fold (mul x, -1) -> 0-x + if (N1C && N1C->isAllOnesValue()) + return DAG.getNode(ISD::SUB, N->getDebugLoc(), VT, + DAG.getConstant(0, VT), N0); + // fold (mul x, (1 << c)) -> x << c + if (N1C && N1C->getAPIntValue().isPowerOf2()) + return DAG.getNode(ISD::SHL, N->getDebugLoc(), VT, N0, + DAG.getConstant(N1C->getAPIntValue().logBase2(), + getShiftAmountTy())); + // fold (mul x, -(1 << c)) -> -(x << c) or (-x) << c + if (N1C && (-N1C->getAPIntValue()).isPowerOf2()) { + unsigned Log2Val = (-N1C->getAPIntValue()).logBase2(); + // FIXME: If the input is something that is easily negated (e.g. a + // single-use add), we should put the negate there. + return DAG.getNode(ISD::SUB, N->getDebugLoc(), VT, + DAG.getConstant(0, VT), + DAG.getNode(ISD::SHL, N->getDebugLoc(), VT, N0, + DAG.getConstant(Log2Val, getShiftAmountTy()))); + } + // (mul (shl X, c1), c2) -> (mul X, c2 << c1) + if (N1C && N0.getOpcode() == ISD::SHL && + isa(N0.getOperand(1))) { + SDValue C3 = DAG.getNode(ISD::SHL, N->getDebugLoc(), VT, + N1, N0.getOperand(1)); + AddToWorkList(C3.getNode()); + return DAG.getNode(ISD::MUL, N->getDebugLoc(), VT, + N0.getOperand(0), C3); + } + + // Change (mul (shl X, C), Y) -> (shl (mul X, Y), C) when the shift has one + // use. + { + SDValue Sh(0,0), Y(0,0); + // Check for both (mul (shl X, C), Y) and (mul Y, (shl X, C)). + if (N0.getOpcode() == ISD::SHL && isa(N0.getOperand(1)) && + N0.getNode()->hasOneUse()) { + Sh = N0; Y = N1; + } else if (N1.getOpcode() == ISD::SHL && + isa(N1.getOperand(1)) && + N1.getNode()->hasOneUse()) { + Sh = N1; Y = N0; + } + + if (Sh.getNode()) { + SDValue Mul = DAG.getNode(ISD::MUL, N->getDebugLoc(), VT, + Sh.getOperand(0), Y); + return DAG.getNode(ISD::SHL, N->getDebugLoc(), VT, + Mul, Sh.getOperand(1)); + } + } + + // fold (mul (add x, c1), c2) -> (add (mul x, c2), c1*c2) + if (N1C && N0.getOpcode() == ISD::ADD && N0.getNode()->hasOneUse() && + isa(N0.getOperand(1))) + return DAG.getNode(ISD::ADD, N->getDebugLoc(), VT, + DAG.getNode(ISD::MUL, N0.getDebugLoc(), VT, + N0.getOperand(0), N1), + DAG.getNode(ISD::MUL, N1.getDebugLoc(), VT, + N0.getOperand(1), N1)); + + // reassociate mul + SDValue RMUL = ReassociateOps(ISD::MUL, N->getDebugLoc(), N0, N1); + if (RMUL.getNode() != 0) + return RMUL; + + return SDValue(); +} + +SDValue DAGCombiner::visitSDIV(SDNode *N) { + SDValue N0 = N->getOperand(0); + SDValue N1 = N->getOperand(1); + ConstantSDNode *N0C = dyn_cast(N0.getNode()); + ConstantSDNode *N1C = dyn_cast(N1.getNode()); + EVT VT = N->getValueType(0); + + // fold vector ops + if (VT.isVector()) { + SDValue FoldedVOp = SimplifyVBinOp(N); + if (FoldedVOp.getNode()) return FoldedVOp; + } + + // fold (sdiv c1, c2) -> c1/c2 + if (N0C && N1C && !N1C->isNullValue()) + return DAG.FoldConstantArithmetic(ISD::SDIV, VT, N0C, N1C); + // fold (sdiv X, 1) -> X + if (N1C && N1C->getSExtValue() == 1LL) + return N0; + // fold (sdiv X, -1) -> 0-X + if (N1C && N1C->isAllOnesValue()) + return DAG.getNode(ISD::SUB, N->getDebugLoc(), VT, + DAG.getConstant(0, VT), N0); + // If we know the sign bits of both operands are zero, strength reduce to a + // udiv instead. Handles (X&15) /s 4 -> X&15 >> 2 + if (!VT.isVector()) { + if (DAG.SignBitIsZero(N1) && DAG.SignBitIsZero(N0)) + return DAG.getNode(ISD::UDIV, N->getDebugLoc(), N1.getValueType(), + N0, N1); + } + // fold (sdiv X, pow2) -> simple ops after legalize + if (N1C && !N1C->isNullValue() && !TLI.isIntDivCheap() && + (isPowerOf2_64(N1C->getSExtValue()) || + isPowerOf2_64(-N1C->getSExtValue()))) { + // If dividing by powers of two is cheap, then don't perform the following + // fold. + if (TLI.isPow2DivCheap()) + return SDValue(); + + int64_t pow2 = N1C->getSExtValue(); + int64_t abs2 = pow2 > 0 ? pow2 : -pow2; + unsigned lg2 = Log2_64(abs2); + + // Splat the sign bit into the register + SDValue SGN = DAG.getNode(ISD::SRA, N->getDebugLoc(), VT, N0, + DAG.getConstant(VT.getSizeInBits()-1, + getShiftAmountTy())); + AddToWorkList(SGN.getNode()); + + // Add (N0 < 0) ? abs2 - 1 : 0; + SDValue SRL = DAG.getNode(ISD::SRL, N->getDebugLoc(), VT, SGN, + DAG.getConstant(VT.getSizeInBits() - lg2, + getShiftAmountTy())); + SDValue ADD = DAG.getNode(ISD::ADD, N->getDebugLoc(), VT, N0, SRL); + AddToWorkList(SRL.getNode()); + AddToWorkList(ADD.getNode()); // Divide by pow2 + SDValue SRA = DAG.getNode(ISD::SRA, N->getDebugLoc(), VT, ADD, + DAG.getConstant(lg2, getShiftAmountTy())); + + // If we're dividing by a positive value, we're done. Otherwise, we must + // negate the result. + if (pow2 > 0) + return SRA; + + AddToWorkList(SRA.getNode()); + return DAG.getNode(ISD::SUB, N->getDebugLoc(), VT, + DAG.getConstant(0, VT), SRA); + } + + // if integer divide is expensive and we satisfy the requirements, emit an + // alternate sequence. + if (N1C && (N1C->getSExtValue() < -1 || N1C->getSExtValue() > 1) && + !TLI.isIntDivCheap()) { + SDValue Op = BuildSDIV(N); + if (Op.getNode()) return Op; + } + + // undef / X -> 0 + if (N0.getOpcode() == ISD::UNDEF) + return DAG.getConstant(0, VT); + // X / undef -> undef + if (N1.getOpcode() == ISD::UNDEF) + return N1; + + return SDValue(); +} + +SDValue DAGCombiner::visitUDIV(SDNode *N) { + SDValue N0 = N->getOperand(0); + SDValue N1 = N->getOperand(1); + ConstantSDNode *N0C = dyn_cast(N0.getNode()); + ConstantSDNode *N1C = dyn_cast(N1.getNode()); + EVT VT = N->getValueType(0); + + // fold vector ops + if (VT.isVector()) { + SDValue FoldedVOp = SimplifyVBinOp(N); + if (FoldedVOp.getNode()) return FoldedVOp; + } + + // fold (udiv c1, c2) -> c1/c2 + if (N0C && N1C && !N1C->isNullValue()) + return DAG.FoldConstantArithmetic(ISD::UDIV, VT, N0C, N1C); + // fold (udiv x, (1 << c)) -> x >>u c + if (N1C && N1C->getAPIntValue().isPowerOf2()) + return DAG.getNode(ISD::SRL, N->getDebugLoc(), VT, N0, + DAG.getConstant(N1C->getAPIntValue().logBase2(), + getShiftAmountTy())); + // fold (udiv x, (shl c, y)) -> x >>u (log2(c)+y) iff c is power of 2 + if (N1.getOpcode() == ISD::SHL) { + if (ConstantSDNode *SHC = dyn_cast(N1.getOperand(0))) { + if (SHC->getAPIntValue().isPowerOf2()) { + EVT ADDVT = N1.getOperand(1).getValueType(); + SDValue Add = DAG.getNode(ISD::ADD, N->getDebugLoc(), ADDVT, + N1.getOperand(1), + DAG.getConstant(SHC->getAPIntValue() + .logBase2(), + ADDVT)); + AddToWorkList(Add.getNode()); + return DAG.getNode(ISD::SRL, N->getDebugLoc(), VT, N0, Add); + } + } + } + // fold (udiv x, c) -> alternate + if (N1C && !N1C->isNullValue() && !TLI.isIntDivCheap()) { + SDValue Op = BuildUDIV(N); + if (Op.getNode()) return Op; + } + + // undef / X -> 0 + if (N0.getOpcode() == ISD::UNDEF) + return DAG.getConstant(0, VT); + // X / undef -> undef + if (N1.getOpcode() == ISD::UNDEF) + return N1; + + return SDValue(); +} + +SDValue DAGCombiner::visitSREM(SDNode *N) { + SDValue N0 = N->getOperand(0); + SDValue N1 = N->getOperand(1); + ConstantSDNode *N0C = dyn_cast(N0); + ConstantSDNode *N1C = dyn_cast(N1); + EVT VT = N->getValueType(0); + + // fold (srem c1, c2) -> c1%c2 + if (N0C && N1C && !N1C->isNullValue()) + return DAG.FoldConstantArithmetic(ISD::SREM, VT, N0C, N1C); + // If we know the sign bits of both operands are zero, strength reduce to a + // urem instead. Handles (X & 0x0FFFFFFF) %s 16 -> X&15 + if (!VT.isVector()) { + if (DAG.SignBitIsZero(N1) && DAG.SignBitIsZero(N0)) + return DAG.getNode(ISD::UREM, N->getDebugLoc(), VT, N0, N1); + } + + // If X/C can be simplified by the division-by-constant logic, lower + // X%C to the equivalent of X-X/C*C. + if (N1C && !N1C->isNullValue()) { + SDValue Div = DAG.getNode(ISD::SDIV, N->getDebugLoc(), VT, N0, N1); + AddToWorkList(Div.getNode()); + SDValue OptimizedDiv = combine(Div.getNode()); + if (OptimizedDiv.getNode() && OptimizedDiv.getNode() != Div.getNode()) { + SDValue Mul = DAG.getNode(ISD::MUL, N->getDebugLoc(), VT, + OptimizedDiv, N1); + SDValue Sub = DAG.getNode(ISD::SUB, N->getDebugLoc(), VT, N0, Mul); + AddToWorkList(Mul.getNode()); + return Sub; + } + } + + // undef % X -> 0 + if (N0.getOpcode() == ISD::UNDEF) + return DAG.getConstant(0, VT); + // X % undef -> undef + if (N1.getOpcode() == ISD::UNDEF) + return N1; + + return SDValue(); +} + +SDValue DAGCombiner::visitUREM(SDNode *N) { + SDValue N0 = N->getOperand(0); + SDValue N1 = N->getOperand(1); + ConstantSDNode *N0C = dyn_cast(N0); + ConstantSDNode *N1C = dyn_cast(N1); + EVT VT = N->getValueType(0); + + // fold (urem c1, c2) -> c1%c2 + if (N0C && N1C && !N1C->isNullValue()) + return DAG.FoldConstantArithmetic(ISD::UREM, VT, N0C, N1C); + // fold (urem x, pow2) -> (and x, pow2-1) + if (N1C && !N1C->isNullValue() && N1C->getAPIntValue().isPowerOf2()) + return DAG.getNode(ISD::AND, N->getDebugLoc(), VT, N0, + DAG.getConstant(N1C->getAPIntValue()-1,VT)); + // fold (urem x, (shl pow2, y)) -> (and x, (add (shl pow2, y), -1)) + if (N1.getOpcode() == ISD::SHL) { + if (ConstantSDNode *SHC = dyn_cast(N1.getOperand(0))) { + if (SHC->getAPIntValue().isPowerOf2()) { + SDValue Add = + DAG.getNode(ISD::ADD, N->getDebugLoc(), VT, N1, + DAG.getConstant(APInt::getAllOnesValue(VT.getSizeInBits()), + VT)); + AddToWorkList(Add.getNode()); + return DAG.getNode(ISD::AND, N->getDebugLoc(), VT, N0, Add); + } + } + } + + // If X/C can be simplified by the division-by-constant logic, lower + // X%C to the equivalent of X-X/C*C. + if (N1C && !N1C->isNullValue()) { + SDValue Div = DAG.getNode(ISD::UDIV, N->getDebugLoc(), VT, N0, N1); + AddToWorkList(Div.getNode()); + SDValue OptimizedDiv = combine(Div.getNode()); + if (OptimizedDiv.getNode() && OptimizedDiv.getNode() != Div.getNode()) { + SDValue Mul = DAG.getNode(ISD::MUL, N->getDebugLoc(), VT, + OptimizedDiv, N1); + SDValue Sub = DAG.getNode(ISD::SUB, N->getDebugLoc(), VT, N0, Mul); + AddToWorkList(Mul.getNode()); + return Sub; + } + } + + // undef % X -> 0 + if (N0.getOpcode() == ISD::UNDEF) + return DAG.getConstant(0, VT); + // X % undef -> undef + if (N1.getOpcode() == ISD::UNDEF) + return N1; + + return SDValue(); +} + +SDValue DAGCombiner::visitMULHS(SDNode *N) { + SDValue N0 = N->getOperand(0); + SDValue N1 = N->getOperand(1); + ConstantSDNode *N1C = dyn_cast(N1); + EVT VT = N->getValueType(0); + + // fold (mulhs x, 0) -> 0 + if (N1C && N1C->isNullValue()) + return N1; + // fold (mulhs x, 1) -> (sra x, size(x)-1) + if (N1C && N1C->getAPIntValue() == 1) + return DAG.getNode(ISD::SRA, N->getDebugLoc(), N0.getValueType(), N0, + DAG.getConstant(N0.getValueType().getSizeInBits() - 1, + getShiftAmountTy())); + // fold (mulhs x, undef) -> 0 + if (N0.getOpcode() == ISD::UNDEF || N1.getOpcode() == ISD::UNDEF) + return DAG.getConstant(0, VT); + + return SDValue(); +} + +SDValue DAGCombiner::visitMULHU(SDNode *N) { + SDValue N0 = N->getOperand(0); + SDValue N1 = N->getOperand(1); + ConstantSDNode *N1C = dyn_cast(N1); + EVT VT = N->getValueType(0); + + // fold (mulhu x, 0) -> 0 + if (N1C && N1C->isNullValue()) + return N1; + // fold (mulhu x, 1) -> 0 + if (N1C && N1C->getAPIntValue() == 1) + return DAG.getConstant(0, N0.getValueType()); + // fold (mulhu x, undef) -> 0 + if (N0.getOpcode() == ISD::UNDEF || N1.getOpcode() == ISD::UNDEF) + return DAG.getConstant(0, VT); + + return SDValue(); +} + +/// SimplifyNodeWithTwoResults - Perform optimizations common to nodes that +/// compute two values. LoOp and HiOp give the opcodes for the two computations +/// that are being performed. Return true if a simplification was made. +/// +SDValue DAGCombiner::SimplifyNodeWithTwoResults(SDNode *N, unsigned LoOp, + unsigned HiOp) { + // If the high half is not needed, just compute the low half. + bool HiExists = N->hasAnyUseOfValue(1); + if (!HiExists && + (!LegalOperations || + TLI.isOperationLegal(LoOp, N->getValueType(0)))) { + SDValue Res = DAG.getNode(LoOp, N->getDebugLoc(), N->getValueType(0), + N->op_begin(), N->getNumOperands()); + return CombineTo(N, Res, Res); + } + + // If the low half is not needed, just compute the high half. + bool LoExists = N->hasAnyUseOfValue(0); + if (!LoExists && + (!LegalOperations || + TLI.isOperationLegal(HiOp, N->getValueType(1)))) { + SDValue Res = DAG.getNode(HiOp, N->getDebugLoc(), N->getValueType(1), + N->op_begin(), N->getNumOperands()); + return CombineTo(N, Res, Res); + } + + // If both halves are used, return as it is. + if (LoExists && HiExists) + return SDValue(); + + // If the two computed results can be simplified separately, separate them. + if (LoExists) { + SDValue Lo = DAG.getNode(LoOp, N->getDebugLoc(), N->getValueType(0), + N->op_begin(), N->getNumOperands()); + AddToWorkList(Lo.getNode()); + SDValue LoOpt = combine(Lo.getNode()); + if (LoOpt.getNode() && LoOpt.getNode() != Lo.getNode() && + (!LegalOperations || + TLI.isOperationLegal(LoOpt.getOpcode(), LoOpt.getValueType()))) + return CombineTo(N, LoOpt, LoOpt); + } + + if (HiExists) { + SDValue Hi = DAG.getNode(HiOp, N->getDebugLoc(), N->getValueType(1), + N->op_begin(), N->getNumOperands()); + AddToWorkList(Hi.getNode()); + SDValue HiOpt = combine(Hi.getNode()); + if (HiOpt.getNode() && HiOpt != Hi && + (!LegalOperations || + TLI.isOperationLegal(HiOpt.getOpcode(), HiOpt.getValueType()))) + return CombineTo(N, HiOpt, HiOpt); + } + + return SDValue(); +} + +SDValue DAGCombiner::visitSMUL_LOHI(SDNode *N) { + SDValue Res = SimplifyNodeWithTwoResults(N, ISD::MUL, ISD::MULHS); + if (Res.getNode()) return Res; + + return SDValue(); +} + +SDValue DAGCombiner::visitUMUL_LOHI(SDNode *N) { + SDValue Res = SimplifyNodeWithTwoResults(N, ISD::MUL, ISD::MULHU); + if (Res.getNode()) return Res; + + return SDValue(); +} + +SDValue DAGCombiner::visitSDIVREM(SDNode *N) { + SDValue Res = SimplifyNodeWithTwoResults(N, ISD::SDIV, ISD::SREM); + if (Res.getNode()) return Res; + + return SDValue(); +} + +SDValue DAGCombiner::visitUDIVREM(SDNode *N) { + SDValue Res = SimplifyNodeWithTwoResults(N, ISD::UDIV, ISD::UREM); + if (Res.getNode()) return Res; + + return SDValue(); +} + +/// SimplifyBinOpWithSameOpcodeHands - If this is a binary operator with +/// two operands of the same opcode, try to simplify it. +SDValue DAGCombiner::SimplifyBinOpWithSameOpcodeHands(SDNode *N) { + SDValue N0 = N->getOperand(0), N1 = N->getOperand(1); + EVT VT = N0.getValueType(); + assert(N0.getOpcode() == N1.getOpcode() && "Bad input!"); + + // For each of OP in AND/OR/XOR: + // fold (OP (zext x), (zext y)) -> (zext (OP x, y)) + // fold (OP (sext x), (sext y)) -> (sext (OP x, y)) + // fold (OP (aext x), (aext y)) -> (aext (OP x, y)) + // fold (OP (trunc x), (trunc y)) -> (trunc (OP x, y)) (if trunc isn't free) + if ((N0.getOpcode() == ISD::ZERO_EXTEND || N0.getOpcode() == ISD::ANY_EXTEND|| + N0.getOpcode() == ISD::SIGN_EXTEND || + (N0.getOpcode() == ISD::TRUNCATE && + !TLI.isTruncateFree(N0.getOperand(0).getValueType(), VT))) && + N0.getOperand(0).getValueType() == N1.getOperand(0).getValueType() && + (!LegalOperations || + TLI.isOperationLegal(N->getOpcode(), N0.getOperand(0).getValueType()))) { + SDValue ORNode = DAG.getNode(N->getOpcode(), N0.getDebugLoc(), + N0.getOperand(0).getValueType(), + N0.getOperand(0), N1.getOperand(0)); + AddToWorkList(ORNode.getNode()); + return DAG.getNode(N0.getOpcode(), N->getDebugLoc(), VT, ORNode); + } + + // For each of OP in SHL/SRL/SRA/AND... + // fold (and (OP x, z), (OP y, z)) -> (OP (and x, y), z) + // fold (or (OP x, z), (OP y, z)) -> (OP (or x, y), z) + // fold (xor (OP x, z), (OP y, z)) -> (OP (xor x, y), z) + if ((N0.getOpcode() == ISD::SHL || N0.getOpcode() == ISD::SRL || + N0.getOpcode() == ISD::SRA || N0.getOpcode() == ISD::AND) && + N0.getOperand(1) == N1.getOperand(1)) { + SDValue ORNode = DAG.getNode(N->getOpcode(), N0.getDebugLoc(), + N0.getOperand(0).getValueType(), + N0.getOperand(0), N1.getOperand(0)); + AddToWorkList(ORNode.getNode()); + return DAG.getNode(N0.getOpcode(), N->getDebugLoc(), VT, + ORNode, N0.getOperand(1)); + } + + return SDValue(); +} + +SDValue DAGCombiner::visitAND(SDNode *N) { + SDValue N0 = N->getOperand(0); + SDValue N1 = N->getOperand(1); + SDValue LL, LR, RL, RR, CC0, CC1; + ConstantSDNode *N0C = dyn_cast(N0); + ConstantSDNode *N1C = dyn_cast(N1); + EVT VT = N1.getValueType(); + unsigned BitWidth = VT.getSizeInBits(); + + // fold vector ops + if (VT.isVector()) { + SDValue FoldedVOp = SimplifyVBinOp(N); + if (FoldedVOp.getNode()) return FoldedVOp; + } + + // fold (and x, undef) -> 0 + if (N0.getOpcode() == ISD::UNDEF || N1.getOpcode() == ISD::UNDEF) + return DAG.getConstant(0, VT); + // fold (and c1, c2) -> c1&c2 + if (N0C && N1C) + return DAG.FoldConstantArithmetic(ISD::AND, VT, N0C, N1C); + // canonicalize constant to RHS + if (N0C && !N1C) + return DAG.getNode(ISD::AND, N->getDebugLoc(), VT, N1, N0); + // fold (and x, -1) -> x + if (N1C && N1C->isAllOnesValue()) + return N0; + // if (and x, c) is known to be zero, return 0 + if (N1C && DAG.MaskedValueIsZero(SDValue(N, 0), + APInt::getAllOnesValue(BitWidth))) + return DAG.getConstant(0, VT); + // reassociate and + SDValue RAND = ReassociateOps(ISD::AND, N->getDebugLoc(), N0, N1); + if (RAND.getNode() != 0) + return RAND; + // fold (and (or x, 0xFFFF), 0xFF) -> 0xFF + if (N1C && N0.getOpcode() == ISD::OR) + if (ConstantSDNode *ORI = dyn_cast(N0.getOperand(1))) + if ((ORI->getAPIntValue() & N1C->getAPIntValue()) == N1C->getAPIntValue()) + return N1; + // fold (and (any_ext V), c) -> (zero_ext V) if 'and' only clears top bits. + if (N1C && N0.getOpcode() == ISD::ANY_EXTEND) { + SDValue N0Op0 = N0.getOperand(0); + APInt Mask = ~N1C->getAPIntValue(); + Mask.trunc(N0Op0.getValueSizeInBits()); + if (DAG.MaskedValueIsZero(N0Op0, Mask)) { + SDValue Zext = DAG.getNode(ISD::ZERO_EXTEND, N->getDebugLoc(), + N0.getValueType(), N0Op0); + + // Replace uses of the AND with uses of the Zero extend node. + CombineTo(N, Zext); + + // We actually want to replace all uses of the any_extend with the + // zero_extend, to avoid duplicating things. This will later cause this + // AND to be folded. + CombineTo(N0.getNode(), Zext); + return SDValue(N, 0); // Return N so it doesn't get rechecked! + } + } + // fold (and (setcc x), (setcc y)) -> (setcc (and x, y)) + if (isSetCCEquivalent(N0, LL, LR, CC0) && isSetCCEquivalent(N1, RL, RR, CC1)){ + ISD::CondCode Op0 = cast(CC0)->get(); + ISD::CondCode Op1 = cast(CC1)->get(); + + if (LR == RR && isa(LR) && Op0 == Op1 && + LL.getValueType().isInteger()) { + // fold (and (seteq X, 0), (seteq Y, 0)) -> (seteq (or X, Y), 0) + if (cast(LR)->isNullValue() && Op1 == ISD::SETEQ) { + SDValue ORNode = DAG.getNode(ISD::OR, N0.getDebugLoc(), + LR.getValueType(), LL, RL); + AddToWorkList(ORNode.getNode()); + return DAG.getSetCC(N->getDebugLoc(), VT, ORNode, LR, Op1); + } + // fold (and (seteq X, -1), (seteq Y, -1)) -> (seteq (and X, Y), -1) + if (cast(LR)->isAllOnesValue() && Op1 == ISD::SETEQ) { + SDValue ANDNode = DAG.getNode(ISD::AND, N0.getDebugLoc(), + LR.getValueType(), LL, RL); + AddToWorkList(ANDNode.getNode()); + return DAG.getSetCC(N->getDebugLoc(), VT, ANDNode, LR, Op1); + } + // fold (and (setgt X, -1), (setgt Y, -1)) -> (setgt (or X, Y), -1) + if (cast(LR)->isAllOnesValue() && Op1 == ISD::SETGT) { + SDValue ORNode = DAG.getNode(ISD::OR, N0.getDebugLoc(), + LR.getValueType(), LL, RL); + AddToWorkList(ORNode.getNode()); + return DAG.getSetCC(N->getDebugLoc(), VT, ORNode, LR, Op1); + } + } + // canonicalize equivalent to ll == rl + if (LL == RR && LR == RL) { + Op1 = ISD::getSetCCSwappedOperands(Op1); + std::swap(RL, RR); + } + if (LL == RL && LR == RR) { + bool isInteger = LL.getValueType().isInteger(); + ISD::CondCode Result = ISD::getSetCCAndOperation(Op0, Op1, isInteger); + if (Result != ISD::SETCC_INVALID && + (!LegalOperations || TLI.isCondCodeLegal(Result, LL.getValueType()))) + return DAG.getSetCC(N->getDebugLoc(), N0.getValueType(), + LL, LR, Result); + } + } + + // Simplify: (and (op x...), (op y...)) -> (op (and x, y)) + if (N0.getOpcode() == N1.getOpcode()) { + SDValue Tmp = SimplifyBinOpWithSameOpcodeHands(N); + if (Tmp.getNode()) return Tmp; + } + + // fold (and (sign_extend_inreg x, i16 to i32), 1) -> (and x, 1) + // fold (and (sra)) -> (and (srl)) when possible. + if (!VT.isVector() && + SimplifyDemandedBits(SDValue(N, 0))) + return SDValue(N, 0); + // fold (zext_inreg (extload x)) -> (zextload x) + if (ISD::isEXTLoad(N0.getNode()) && ISD::isUNINDEXEDLoad(N0.getNode())) { + LoadSDNode *LN0 = cast(N0); + EVT MemVT = LN0->getMemoryVT(); + // If we zero all the possible extended bits, then we can turn this into + // a zextload if we are running before legalize or the operation is legal. + unsigned BitWidth = N1.getValueSizeInBits(); + if (DAG.MaskedValueIsZero(N1, APInt::getHighBitsSet(BitWidth, + BitWidth - MemVT.getSizeInBits())) && + ((!LegalOperations && !LN0->isVolatile()) || + TLI.isLoadExtLegal(ISD::ZEXTLOAD, MemVT))) { + SDValue ExtLoad = DAG.getExtLoad(ISD::ZEXTLOAD, N0.getDebugLoc(), VT, + LN0->getChain(), LN0->getBasePtr(), + LN0->getSrcValue(), + LN0->getSrcValueOffset(), MemVT, + LN0->isVolatile(), LN0->getAlignment()); + AddToWorkList(N); + CombineTo(N0.getNode(), ExtLoad, ExtLoad.getValue(1)); + return SDValue(N, 0); // Return N so it doesn't get rechecked! + } + } + // fold (zext_inreg (sextload x)) -> (zextload x) iff load has one use + if (ISD::isSEXTLoad(N0.getNode()) && ISD::isUNINDEXEDLoad(N0.getNode()) && + N0.hasOneUse()) { + LoadSDNode *LN0 = cast(N0); + EVT MemVT = LN0->getMemoryVT(); + // If we zero all the possible extended bits, then we can turn this into + // a zextload if we are running before legalize or the operation is legal. + unsigned BitWidth = N1.getValueSizeInBits(); + if (DAG.MaskedValueIsZero(N1, APInt::getHighBitsSet(BitWidth, + BitWidth - MemVT.getSizeInBits())) && + ((!LegalOperations && !LN0->isVolatile()) || + TLI.isLoadExtLegal(ISD::ZEXTLOAD, MemVT))) { + SDValue ExtLoad = DAG.getExtLoad(ISD::ZEXTLOAD, N0.getDebugLoc(), VT, + LN0->getChain(), + LN0->getBasePtr(), LN0->getSrcValue(), + LN0->getSrcValueOffset(), MemVT, + LN0->isVolatile(), LN0->getAlignment()); + AddToWorkList(N); + CombineTo(N0.getNode(), ExtLoad, ExtLoad.getValue(1)); + return SDValue(N, 0); // Return N so it doesn't get rechecked! + } + } + + // fold (and (load x), 255) -> (zextload x, i8) + // fold (and (extload x, i16), 255) -> (zextload x, i8) + if (N1C && N0.getOpcode() == ISD::LOAD) { + LoadSDNode *LN0 = cast(N0); + if (LN0->getExtensionType() != ISD::SEXTLOAD && + LN0->isUnindexed() && N0.hasOneUse() && + // Do not change the width of a volatile load. + !LN0->isVolatile()) { + EVT ExtVT = MVT::Other; + uint32_t ActiveBits = N1C->getAPIntValue().getActiveBits(); + if (ActiveBits > 0 && APIntOps::isMask(ActiveBits, N1C->getAPIntValue())) + ExtVT = EVT::getIntegerVT(*DAG.getContext(), ActiveBits); + + EVT LoadedVT = LN0->getMemoryVT(); + + // Do not generate loads of non-round integer types since these can + // be expensive (and would be wrong if the type is not byte sized). + if (ExtVT != MVT::Other && LoadedVT.bitsGT(ExtVT) && ExtVT.isRound() && + (!LegalOperations || TLI.isLoadExtLegal(ISD::ZEXTLOAD, ExtVT))) { + EVT PtrType = N0.getOperand(1).getValueType(); + + // For big endian targets, we need to add an offset to the pointer to + // load the correct bytes. For little endian systems, we merely need to + // read fewer bytes from the same pointer. + unsigned LVTStoreBytes = LoadedVT.getStoreSize(); + unsigned EVTStoreBytes = ExtVT.getStoreSize(); + unsigned PtrOff = LVTStoreBytes - EVTStoreBytes; + unsigned Alignment = LN0->getAlignment(); + SDValue NewPtr = LN0->getBasePtr(); + + if (TLI.isBigEndian()) { + NewPtr = DAG.getNode(ISD::ADD, LN0->getDebugLoc(), PtrType, + NewPtr, DAG.getConstant(PtrOff, PtrType)); + Alignment = MinAlign(Alignment, PtrOff); + } + + AddToWorkList(NewPtr.getNode()); + SDValue Load = + DAG.getExtLoad(ISD::ZEXTLOAD, LN0->getDebugLoc(), VT, LN0->getChain(), + NewPtr, LN0->getSrcValue(), LN0->getSrcValueOffset(), + ExtVT, LN0->isVolatile(), Alignment); + AddToWorkList(N); + CombineTo(N0.getNode(), Load, Load.getValue(1)); + return SDValue(N, 0); // Return N so it doesn't get rechecked! + } + } + } + + return SDValue(); +} + +SDValue DAGCombiner::visitOR(SDNode *N) { + SDValue N0 = N->getOperand(0); + SDValue N1 = N->getOperand(1); + SDValue LL, LR, RL, RR, CC0, CC1; + ConstantSDNode *N0C = dyn_cast(N0); + ConstantSDNode *N1C = dyn_cast(N1); + EVT VT = N1.getValueType(); + + // fold vector ops + if (VT.isVector()) { + SDValue FoldedVOp = SimplifyVBinOp(N); + if (FoldedVOp.getNode()) return FoldedVOp; + } + + // fold (or x, undef) -> -1 + if (N0.getOpcode() == ISD::UNDEF || N1.getOpcode() == ISD::UNDEF) + return DAG.getConstant(APInt::getAllOnesValue(VT.getSizeInBits()), VT); + // fold (or c1, c2) -> c1|c2 + if (N0C && N1C) + return DAG.FoldConstantArithmetic(ISD::OR, VT, N0C, N1C); + // canonicalize constant to RHS + if (N0C && !N1C) + return DAG.getNode(ISD::OR, N->getDebugLoc(), VT, N1, N0); + // fold (or x, 0) -> x + if (N1C && N1C->isNullValue()) + return N0; + // fold (or x, -1) -> -1 + if (N1C && N1C->isAllOnesValue()) + return N1; + // fold (or x, c) -> c iff (x & ~c) == 0 + if (N1C && DAG.MaskedValueIsZero(N0, ~N1C->getAPIntValue())) + return N1; + // reassociate or + SDValue ROR = ReassociateOps(ISD::OR, N->getDebugLoc(), N0, N1); + if (ROR.getNode() != 0) + return ROR; + // Canonicalize (or (and X, c1), c2) -> (and (or X, c2), c1|c2) + if (N1C && N0.getOpcode() == ISD::AND && N0.getNode()->hasOneUse() && + isa(N0.getOperand(1))) { + ConstantSDNode *C1 = cast(N0.getOperand(1)); + return DAG.getNode(ISD::AND, N->getDebugLoc(), VT, + DAG.getNode(ISD::OR, N0.getDebugLoc(), VT, + N0.getOperand(0), N1), + DAG.FoldConstantArithmetic(ISD::OR, VT, N1C, C1)); + } + // fold (or (setcc x), (setcc y)) -> (setcc (or x, y)) + if (isSetCCEquivalent(N0, LL, LR, CC0) && isSetCCEquivalent(N1, RL, RR, CC1)){ + ISD::CondCode Op0 = cast(CC0)->get(); + ISD::CondCode Op1 = cast(CC1)->get(); + + if (LR == RR && isa(LR) && Op0 == Op1 && + LL.getValueType().isInteger()) { + // fold (or (setne X, 0), (setne Y, 0)) -> (setne (or X, Y), 0) + // fold (or (setlt X, 0), (setlt Y, 0)) -> (setne (or X, Y), 0) + if (cast(LR)->isNullValue() && + (Op1 == ISD::SETNE || Op1 == ISD::SETLT)) { + SDValue ORNode = DAG.getNode(ISD::OR, LR.getDebugLoc(), + LR.getValueType(), LL, RL); + AddToWorkList(ORNode.getNode()); + return DAG.getSetCC(N->getDebugLoc(), VT, ORNode, LR, Op1); + } + // fold (or (setne X, -1), (setne Y, -1)) -> (setne (and X, Y), -1) + // fold (or (setgt X, -1), (setgt Y -1)) -> (setgt (and X, Y), -1) + if (cast(LR)->isAllOnesValue() && + (Op1 == ISD::SETNE || Op1 == ISD::SETGT)) { + SDValue ANDNode = DAG.getNode(ISD::AND, LR.getDebugLoc(), + LR.getValueType(), LL, RL); + AddToWorkList(ANDNode.getNode()); + return DAG.getSetCC(N->getDebugLoc(), VT, ANDNode, LR, Op1); + } + } + // canonicalize equivalent to ll == rl + if (LL == RR && LR == RL) { + Op1 = ISD::getSetCCSwappedOperands(Op1); + std::swap(RL, RR); + } + if (LL == RL && LR == RR) { + bool isInteger = LL.getValueType().isInteger(); + ISD::CondCode Result = ISD::getSetCCOrOperation(Op0, Op1, isInteger); + if (Result != ISD::SETCC_INVALID && + (!LegalOperations || TLI.isCondCodeLegal(Result, LL.getValueType()))) + return DAG.getSetCC(N->getDebugLoc(), N0.getValueType(), + LL, LR, Result); + } + } + + // Simplify: (or (op x...), (op y...)) -> (op (or x, y)) + if (N0.getOpcode() == N1.getOpcode()) { + SDValue Tmp = SimplifyBinOpWithSameOpcodeHands(N); + if (Tmp.getNode()) return Tmp; + } + + // (or (and X, C1), (and Y, C2)) -> (and (or X, Y), C3) if possible. + if (N0.getOpcode() == ISD::AND && + N1.getOpcode() == ISD::AND && + N0.getOperand(1).getOpcode() == ISD::Constant && + N1.getOperand(1).getOpcode() == ISD::Constant && + // Don't increase # computations. + (N0.getNode()->hasOneUse() || N1.getNode()->hasOneUse())) { + // We can only do this xform if we know that bits from X that are set in C2 + // but not in C1 are already zero. Likewise for Y. + const APInt &LHSMask = + cast(N0.getOperand(1))->getAPIntValue(); + const APInt &RHSMask = + cast(N1.getOperand(1))->getAPIntValue(); + + if (DAG.MaskedValueIsZero(N0.getOperand(0), RHSMask&~LHSMask) && + DAG.MaskedValueIsZero(N1.getOperand(0), LHSMask&~RHSMask)) { + SDValue X = DAG.getNode(ISD::OR, N0.getDebugLoc(), VT, + N0.getOperand(0), N1.getOperand(0)); + return DAG.getNode(ISD::AND, N->getDebugLoc(), VT, X, + DAG.getConstant(LHSMask | RHSMask, VT)); + } + } + + // See if this is some rotate idiom. + if (SDNode *Rot = MatchRotate(N0, N1, N->getDebugLoc())) + return SDValue(Rot, 0); + + return SDValue(); +} + +/// MatchRotateHalf - Match "(X shl/srl V1) & V2" where V2 may not be present. +static bool MatchRotateHalf(SDValue Op, SDValue &Shift, SDValue &Mask) { + if (Op.getOpcode() == ISD::AND) { + if (isa(Op.getOperand(1))) { + Mask = Op.getOperand(1); + Op = Op.getOperand(0); + } else { + return false; + } + } + + if (Op.getOpcode() == ISD::SRL || Op.getOpcode() == ISD::SHL) { + Shift = Op; + return true; + } + + return false; +} + +// MatchRotate - Handle an 'or' of two operands. If this is one of the many +// idioms for rotate, and if the target supports rotation instructions, generate +// a rot[lr]. +SDNode *DAGCombiner::MatchRotate(SDValue LHS, SDValue RHS, DebugLoc DL) { + // Must be a legal type. Expanded 'n promoted things won't work with rotates. + EVT VT = LHS.getValueType(); + if (!TLI.isTypeLegal(VT)) return 0; + + // The target must have at least one rotate flavor. + bool HasROTL = TLI.isOperationLegalOrCustom(ISD::ROTL, VT); + bool HasROTR = TLI.isOperationLegalOrCustom(ISD::ROTR, VT); + if (!HasROTL && !HasROTR) return 0; + + // Match "(X shl/srl V1) & V2" where V2 may not be present. + SDValue LHSShift; // The shift. + SDValue LHSMask; // AND value if any. + if (!MatchRotateHalf(LHS, LHSShift, LHSMask)) + return 0; // Not part of a rotate. + + SDValue RHSShift; // The shift. + SDValue RHSMask; // AND value if any. + if (!MatchRotateHalf(RHS, RHSShift, RHSMask)) + return 0; // Not part of a rotate. + + if (LHSShift.getOperand(0) != RHSShift.getOperand(0)) + return 0; // Not shifting the same value. + + if (LHSShift.getOpcode() == RHSShift.getOpcode()) + return 0; // Shifts must disagree. + + // Canonicalize shl to left side in a shl/srl pair. + if (RHSShift.getOpcode() == ISD::SHL) { + std::swap(LHS, RHS); + std::swap(LHSShift, RHSShift); + std::swap(LHSMask , RHSMask ); + } + + unsigned OpSizeInBits = VT.getSizeInBits(); + SDValue LHSShiftArg = LHSShift.getOperand(0); + SDValue LHSShiftAmt = LHSShift.getOperand(1); + SDValue RHSShiftAmt = RHSShift.getOperand(1); + + // fold (or (shl x, C1), (srl x, C2)) -> (rotl x, C1) + // fold (or (shl x, C1), (srl x, C2)) -> (rotr x, C2) + if (LHSShiftAmt.getOpcode() == ISD::Constant && + RHSShiftAmt.getOpcode() == ISD::Constant) { + uint64_t LShVal = cast(LHSShiftAmt)->getZExtValue(); + uint64_t RShVal = cast(RHSShiftAmt)->getZExtValue(); + if ((LShVal + RShVal) != OpSizeInBits) + return 0; + + SDValue Rot; + if (HasROTL) + Rot = DAG.getNode(ISD::ROTL, DL, VT, LHSShiftArg, LHSShiftAmt); + else + Rot = DAG.getNode(ISD::ROTR, DL, VT, LHSShiftArg, RHSShiftAmt); + + // If there is an AND of either shifted operand, apply it to the result. + if (LHSMask.getNode() || RHSMask.getNode()) { + APInt Mask = APInt::getAllOnesValue(OpSizeInBits); + + if (LHSMask.getNode()) { + APInt RHSBits = APInt::getLowBitsSet(OpSizeInBits, LShVal); + Mask &= cast(LHSMask)->getAPIntValue() | RHSBits; + } + if (RHSMask.getNode()) { + APInt LHSBits = APInt::getHighBitsSet(OpSizeInBits, RShVal); + Mask &= cast(RHSMask)->getAPIntValue() | LHSBits; + } + + Rot = DAG.getNode(ISD::AND, DL, VT, Rot, DAG.getConstant(Mask, VT)); + } + + return Rot.getNode(); + } + + // If there is a mask here, and we have a variable shift, we can't be sure + // that we're masking out the right stuff. + if (LHSMask.getNode() || RHSMask.getNode()) + return 0; + + // fold (or (shl x, y), (srl x, (sub 32, y))) -> (rotl x, y) + // fold (or (shl x, y), (srl x, (sub 32, y))) -> (rotr x, (sub 32, y)) + if (RHSShiftAmt.getOpcode() == ISD::SUB && + LHSShiftAmt == RHSShiftAmt.getOperand(1)) { + if (ConstantSDNode *SUBC = + dyn_cast(RHSShiftAmt.getOperand(0))) { + if (SUBC->getAPIntValue() == OpSizeInBits) { + if (HasROTL) + return DAG.getNode(ISD::ROTL, DL, VT, + LHSShiftArg, LHSShiftAmt).getNode(); + else + return DAG.getNode(ISD::ROTR, DL, VT, + LHSShiftArg, RHSShiftAmt).getNode(); + } + } + } + + // fold (or (shl x, (sub 32, y)), (srl x, r)) -> (rotr x, y) + // fold (or (shl x, (sub 32, y)), (srl x, r)) -> (rotl x, (sub 32, y)) + if (LHSShiftAmt.getOpcode() == ISD::SUB && + RHSShiftAmt == LHSShiftAmt.getOperand(1)) { + if (ConstantSDNode *SUBC = + dyn_cast(LHSShiftAmt.getOperand(0))) { + if (SUBC->getAPIntValue() == OpSizeInBits) { + if (HasROTR) + return DAG.getNode(ISD::ROTR, DL, VT, + LHSShiftArg, RHSShiftAmt).getNode(); + else + return DAG.getNode(ISD::ROTL, DL, VT, + LHSShiftArg, LHSShiftAmt).getNode(); + } + } + } + + // Look for sign/zext/any-extended or truncate cases: + if ((LHSShiftAmt.getOpcode() == ISD::SIGN_EXTEND + || LHSShiftAmt.getOpcode() == ISD::ZERO_EXTEND + || LHSShiftAmt.getOpcode() == ISD::ANY_EXTEND + || LHSShiftAmt.getOpcode() == ISD::TRUNCATE) && + (RHSShiftAmt.getOpcode() == ISD::SIGN_EXTEND + || RHSShiftAmt.getOpcode() == ISD::ZERO_EXTEND + || RHSShiftAmt.getOpcode() == ISD::ANY_EXTEND + || RHSShiftAmt.getOpcode() == ISD::TRUNCATE)) { + SDValue LExtOp0 = LHSShiftAmt.getOperand(0); + SDValue RExtOp0 = RHSShiftAmt.getOperand(0); + if (RExtOp0.getOpcode() == ISD::SUB && + RExtOp0.getOperand(1) == LExtOp0) { + // fold (or (shl x, (*ext y)), (srl x, (*ext (sub 32, y)))) -> + // (rotl x, y) + // fold (or (shl x, (*ext y)), (srl x, (*ext (sub 32, y)))) -> + // (rotr x, (sub 32, y)) + if (ConstantSDNode *SUBC = + dyn_cast(RExtOp0.getOperand(0))) { + if (SUBC->getAPIntValue() == OpSizeInBits) { + return DAG.getNode(HasROTL ? ISD::ROTL : ISD::ROTR, DL, VT, + LHSShiftArg, + HasROTL ? LHSShiftAmt : RHSShiftAmt).getNode(); + } + } + } else if (LExtOp0.getOpcode() == ISD::SUB && + RExtOp0 == LExtOp0.getOperand(1)) { + // fold (or (shl x, (*ext (sub 32, y))), (srl x, (*ext y))) -> + // (rotr x, y) + // fold (or (shl x, (*ext (sub 32, y))), (srl x, (*ext y))) -> + // (rotl x, (sub 32, y)) + if (ConstantSDNode *SUBC = + dyn_cast(LExtOp0.getOperand(0))) { + if (SUBC->getAPIntValue() == OpSizeInBits) { + return DAG.getNode(HasROTR ? ISD::ROTR : ISD::ROTL, DL, VT, + LHSShiftArg, + HasROTR ? RHSShiftAmt : LHSShiftAmt).getNode(); + } + } + } + } + + return 0; +} + +SDValue DAGCombiner::visitXOR(SDNode *N) { + SDValue N0 = N->getOperand(0); + SDValue N1 = N->getOperand(1); + SDValue LHS, RHS, CC; + ConstantSDNode *N0C = dyn_cast(N0); + ConstantSDNode *N1C = dyn_cast(N1); + EVT VT = N0.getValueType(); + + // fold vector ops + if (VT.isVector()) { + SDValue FoldedVOp = SimplifyVBinOp(N); + if (FoldedVOp.getNode()) return FoldedVOp; + } + + // fold (xor undef, undef) -> 0. This is a common idiom (misuse). + if (N0.getOpcode() == ISD::UNDEF && N1.getOpcode() == ISD::UNDEF) + return DAG.getConstant(0, VT); + // fold (xor x, undef) -> undef + if (N0.getOpcode() == ISD::UNDEF) + return N0; + if (N1.getOpcode() == ISD::UNDEF) + return N1; + // fold (xor c1, c2) -> c1^c2 + if (N0C && N1C) + return DAG.FoldConstantArithmetic(ISD::XOR, VT, N0C, N1C); + // canonicalize constant to RHS + if (N0C && !N1C) + return DAG.getNode(ISD::XOR, N->getDebugLoc(), VT, N1, N0); + // fold (xor x, 0) -> x + if (N1C && N1C->isNullValue()) + return N0; + // reassociate xor + SDValue RXOR = ReassociateOps(ISD::XOR, N->getDebugLoc(), N0, N1); + if (RXOR.getNode() != 0) + return RXOR; + + // fold !(x cc y) -> (x !cc y) + if (N1C && N1C->getAPIntValue() == 1 && isSetCCEquivalent(N0, LHS, RHS, CC)) { + bool isInt = LHS.getValueType().isInteger(); + ISD::CondCode NotCC = ISD::getSetCCInverse(cast(CC)->get(), + isInt); + + if (!LegalOperations || TLI.isCondCodeLegal(NotCC, LHS.getValueType())) { + switch (N0.getOpcode()) { + default: + llvm_unreachable("Unhandled SetCC Equivalent!"); + case ISD::SETCC: + return DAG.getSetCC(N->getDebugLoc(), VT, LHS, RHS, NotCC); + case ISD::SELECT_CC: + return DAG.getSelectCC(N->getDebugLoc(), LHS, RHS, N0.getOperand(2), + N0.getOperand(3), NotCC); + } + } + } + + // fold (not (zext (setcc x, y))) -> (zext (not (setcc x, y))) + if (N1C && N1C->getAPIntValue() == 1 && N0.getOpcode() == ISD::ZERO_EXTEND && + N0.getNode()->hasOneUse() && + isSetCCEquivalent(N0.getOperand(0), LHS, RHS, CC)){ + SDValue V = N0.getOperand(0); + V = DAG.getNode(ISD::XOR, N0.getDebugLoc(), V.getValueType(), V, + DAG.getConstant(1, V.getValueType())); + AddToWorkList(V.getNode()); + return DAG.getNode(ISD::ZERO_EXTEND, N->getDebugLoc(), VT, V); + } + + // fold (not (or x, y)) -> (and (not x), (not y)) iff x or y are setcc + if (N1C && N1C->getAPIntValue() == 1 && VT == MVT::i1 && + (N0.getOpcode() == ISD::OR || N0.getOpcode() == ISD::AND)) { + SDValue LHS = N0.getOperand(0), RHS = N0.getOperand(1); + if (isOneUseSetCC(RHS) || isOneUseSetCC(LHS)) { + unsigned NewOpcode = N0.getOpcode() == ISD::AND ? ISD::OR : ISD::AND; + LHS = DAG.getNode(ISD::XOR, LHS.getDebugLoc(), VT, LHS, N1); // LHS = ~LHS + RHS = DAG.getNode(ISD::XOR, RHS.getDebugLoc(), VT, RHS, N1); // RHS = ~RHS + AddToWorkList(LHS.getNode()); AddToWorkList(RHS.getNode()); + return DAG.getNode(NewOpcode, N->getDebugLoc(), VT, LHS, RHS); + } + } + // fold (not (or x, y)) -> (and (not x), (not y)) iff x or y are constants + if (N1C && N1C->isAllOnesValue() && + (N0.getOpcode() == ISD::OR || N0.getOpcode() == ISD::AND)) { + SDValue LHS = N0.getOperand(0), RHS = N0.getOperand(1); + if (isa(RHS) || isa(LHS)) { + unsigned NewOpcode = N0.getOpcode() == ISD::AND ? ISD::OR : ISD::AND; + LHS = DAG.getNode(ISD::XOR, LHS.getDebugLoc(), VT, LHS, N1); // LHS = ~LHS + RHS = DAG.getNode(ISD::XOR, RHS.getDebugLoc(), VT, RHS, N1); // RHS = ~RHS + AddToWorkList(LHS.getNode()); AddToWorkList(RHS.getNode()); + return DAG.getNode(NewOpcode, N->getDebugLoc(), VT, LHS, RHS); + } + } + // fold (xor (xor x, c1), c2) -> (xor x, (xor c1, c2)) + if (N1C && N0.getOpcode() == ISD::XOR) { + ConstantSDNode *N00C = dyn_cast(N0.getOperand(0)); + ConstantSDNode *N01C = dyn_cast(N0.getOperand(1)); + if (N00C) + return DAG.getNode(ISD::XOR, N->getDebugLoc(), VT, N0.getOperand(1), + DAG.getConstant(N1C->getAPIntValue() ^ + N00C->getAPIntValue(), VT)); + if (N01C) + return DAG.getNode(ISD::XOR, N->getDebugLoc(), VT, N0.getOperand(0), + DAG.getConstant(N1C->getAPIntValue() ^ + N01C->getAPIntValue(), VT)); + } + // fold (xor x, x) -> 0 + if (N0 == N1) { + if (!VT.isVector()) { + return DAG.getConstant(0, VT); + } else if (!LegalOperations || TLI.isOperationLegal(ISD::BUILD_VECTOR, VT)){ + // Produce a vector of zeros. + SDValue El = DAG.getConstant(0, VT.getVectorElementType()); + std::vector Ops(VT.getVectorNumElements(), El); + return DAG.getNode(ISD::BUILD_VECTOR, N->getDebugLoc(), VT, + &Ops[0], Ops.size()); + } + } + + // Simplify: xor (op x...), (op y...) -> (op (xor x, y)) + if (N0.getOpcode() == N1.getOpcode()) { + SDValue Tmp = SimplifyBinOpWithSameOpcodeHands(N); + if (Tmp.getNode()) return Tmp; + } + + // Simplify the expression using non-local knowledge. + if (!VT.isVector() && + SimplifyDemandedBits(SDValue(N, 0))) + return SDValue(N, 0); + + return SDValue(); +} + +/// visitShiftByConstant - Handle transforms common to the three shifts, when +/// the shift amount is a constant. +SDValue DAGCombiner::visitShiftByConstant(SDNode *N, unsigned Amt) { + SDNode *LHS = N->getOperand(0).getNode(); + if (!LHS->hasOneUse()) return SDValue(); + + // We want to pull some binops through shifts, so that we have (and (shift)) + // instead of (shift (and)), likewise for add, or, xor, etc. This sort of + // thing happens with address calculations, so it's important to canonicalize + // it. + bool HighBitSet = false; // Can we transform this if the high bit is set? + + switch (LHS->getOpcode()) { + default: return SDValue(); + case ISD::OR: + case ISD::XOR: + HighBitSet = false; // We can only transform sra if the high bit is clear. + break; + case ISD::AND: + HighBitSet = true; // We can only transform sra if the high bit is set. + break; + case ISD::ADD: + if (N->getOpcode() != ISD::SHL) + return SDValue(); // only shl(add) not sr[al](add). + HighBitSet = false; // We can only transform sra if the high bit is clear. + break; + } + + // We require the RHS of the binop to be a constant as well. + ConstantSDNode *BinOpCst = dyn_cast(LHS->getOperand(1)); + if (!BinOpCst) return SDValue(); + + // FIXME: disable this unless the input to the binop is a shift by a constant. + // If it is not a shift, it pessimizes some common cases like: + // + // void foo(int *X, int i) { X[i & 1235] = 1; } + // int bar(int *X, int i) { return X[i & 255]; } + SDNode *BinOpLHSVal = LHS->getOperand(0).getNode(); + if ((BinOpLHSVal->getOpcode() != ISD::SHL && + BinOpLHSVal->getOpcode() != ISD::SRA && + BinOpLHSVal->getOpcode() != ISD::SRL) || + !isa(BinOpLHSVal->getOperand(1))) + return SDValue(); + + EVT VT = N->getValueType(0); + + // If this is a signed shift right, and the high bit is modified by the + // logical operation, do not perform the transformation. The highBitSet + // boolean indicates the value of the high bit of the constant which would + // cause it to be modified for this operation. + if (N->getOpcode() == ISD::SRA) { + bool BinOpRHSSignSet = BinOpCst->getAPIntValue().isNegative(); + if (BinOpRHSSignSet != HighBitSet) + return SDValue(); + } + + // Fold the constants, shifting the binop RHS by the shift amount. + SDValue NewRHS = DAG.getNode(N->getOpcode(), LHS->getOperand(1).getDebugLoc(), + N->getValueType(0), + LHS->getOperand(1), N->getOperand(1)); + + // Create the new shift. + SDValue NewShift = DAG.getNode(N->getOpcode(), LHS->getOperand(0).getDebugLoc(), + VT, LHS->getOperand(0), N->getOperand(1)); + + // Create the new binop. + return DAG.getNode(LHS->getOpcode(), N->getDebugLoc(), VT, NewShift, NewRHS); +} + +SDValue DAGCombiner::visitSHL(SDNode *N) { + SDValue N0 = N->getOperand(0); + SDValue N1 = N->getOperand(1); + ConstantSDNode *N0C = dyn_cast(N0); + ConstantSDNode *N1C = dyn_cast(N1); + EVT VT = N0.getValueType(); + unsigned OpSizeInBits = VT.getSizeInBits(); + + // fold (shl c1, c2) -> c1< 0 + if (N0C && N0C->isNullValue()) + return N0; + // fold (shl x, c >= size(x)) -> undef + if (N1C && N1C->getZExtValue() >= OpSizeInBits) + return DAG.getUNDEF(VT); + // fold (shl x, 0) -> x + if (N1C && N1C->isNullValue()) + return N0; + // if (shl x, c) is known to be zero, return 0 + if (DAG.MaskedValueIsZero(SDValue(N, 0), + APInt::getAllOnesValue(VT.getSizeInBits()))) + return DAG.getConstant(0, VT); + // fold (shl x, (trunc (and y, c))) -> (shl x, (and (trunc y), (trunc c))). + if (N1.getOpcode() == ISD::TRUNCATE && + N1.getOperand(0).getOpcode() == ISD::AND && + N1.hasOneUse() && N1.getOperand(0).hasOneUse()) { + SDValue N101 = N1.getOperand(0).getOperand(1); + if (ConstantSDNode *N101C = dyn_cast(N101)) { + EVT TruncVT = N1.getValueType(); + SDValue N100 = N1.getOperand(0).getOperand(0); + APInt TruncC = N101C->getAPIntValue(); + TruncC.trunc(TruncVT.getSizeInBits()); + return DAG.getNode(ISD::SHL, N->getDebugLoc(), VT, N0, + DAG.getNode(ISD::AND, N->getDebugLoc(), TruncVT, + DAG.getNode(ISD::TRUNCATE, + N->getDebugLoc(), + TruncVT, N100), + DAG.getConstant(TruncC, TruncVT))); + } + } + + if (N1C && SimplifyDemandedBits(SDValue(N, 0))) + return SDValue(N, 0); + + // fold (shl (shl x, c1), c2) -> 0 or (shl x, (add c1, c2)) + if (N1C && N0.getOpcode() == ISD::SHL && + N0.getOperand(1).getOpcode() == ISD::Constant) { + uint64_t c1 = cast(N0.getOperand(1))->getZExtValue(); + uint64_t c2 = N1C->getZExtValue(); + if (c1 + c2 > OpSizeInBits) + return DAG.getConstant(0, VT); + return DAG.getNode(ISD::SHL, N->getDebugLoc(), VT, N0.getOperand(0), + DAG.getConstant(c1 + c2, N1.getValueType())); + } + // fold (shl (srl x, c1), c2) -> (shl (and x, (shl -1, c1)), (sub c2, c1)) or + // (srl (and x, (shl -1, c1)), (sub c1, c2)) + if (N1C && N0.getOpcode() == ISD::SRL && + N0.getOperand(1).getOpcode() == ISD::Constant) { + uint64_t c1 = cast(N0.getOperand(1))->getZExtValue(); + if (c1 < VT.getSizeInBits()) { + uint64_t c2 = N1C->getZExtValue(); + SDValue HiBitsMask = + DAG.getConstant(APInt::getHighBitsSet(VT.getSizeInBits(), + VT.getSizeInBits() - c1), + VT); + SDValue Mask = DAG.getNode(ISD::AND, N0.getDebugLoc(), VT, + N0.getOperand(0), + HiBitsMask); + if (c2 > c1) + return DAG.getNode(ISD::SHL, N->getDebugLoc(), VT, Mask, + DAG.getConstant(c2-c1, N1.getValueType())); + else + return DAG.getNode(ISD::SRL, N->getDebugLoc(), VT, Mask, + DAG.getConstant(c1-c2, N1.getValueType())); + } + } + // fold (shl (sra x, c1), c1) -> (and x, (shl -1, c1)) + if (N1C && N0.getOpcode() == ISD::SRA && N1 == N0.getOperand(1)) { + SDValue HiBitsMask = + DAG.getConstant(APInt::getHighBitsSet(VT.getSizeInBits(), + VT.getSizeInBits() - + N1C->getZExtValue()), + VT); + return DAG.getNode(ISD::AND, N->getDebugLoc(), VT, N0.getOperand(0), + HiBitsMask); + } + + return N1C ? visitShiftByConstant(N, N1C->getZExtValue()) : SDValue(); +} + +SDValue DAGCombiner::visitSRA(SDNode *N) { + SDValue N0 = N->getOperand(0); + SDValue N1 = N->getOperand(1); + ConstantSDNode *N0C = dyn_cast(N0); + ConstantSDNode *N1C = dyn_cast(N1); + EVT VT = N0.getValueType(); + + // fold (sra c1, c2) -> (sra c1, c2) + if (N0C && N1C) + return DAG.FoldConstantArithmetic(ISD::SRA, VT, N0C, N1C); + // fold (sra 0, x) -> 0 + if (N0C && N0C->isNullValue()) + return N0; + // fold (sra -1, x) -> -1 + if (N0C && N0C->isAllOnesValue()) + return N0; + // fold (sra x, (setge c, size(x))) -> undef + if (N1C && N1C->getZExtValue() >= VT.getSizeInBits()) + return DAG.getUNDEF(VT); + // fold (sra x, 0) -> x + if (N1C && N1C->isNullValue()) + return N0; + // fold (sra (shl x, c1), c1) -> sext_inreg for some c1 and target supports + // sext_inreg. + if (N1C && N0.getOpcode() == ISD::SHL && N1 == N0.getOperand(1)) { + unsigned LowBits = VT.getSizeInBits() - (unsigned)N1C->getZExtValue(); + EVT EVT = EVT::getIntegerVT(*DAG.getContext(), LowBits); + if ((!LegalOperations || TLI.isOperationLegal(ISD::SIGN_EXTEND_INREG, EVT))) + return DAG.getNode(ISD::SIGN_EXTEND_INREG, N->getDebugLoc(), VT, + N0.getOperand(0), DAG.getValueType(EVT)); + } + + // fold (sra (sra x, c1), c2) -> (sra x, (add c1, c2)) + if (N1C && N0.getOpcode() == ISD::SRA) { + if (ConstantSDNode *C1 = dyn_cast(N0.getOperand(1))) { + unsigned Sum = N1C->getZExtValue() + C1->getZExtValue(); + if (Sum >= VT.getSizeInBits()) Sum = VT.getSizeInBits()-1; + return DAG.getNode(ISD::SRA, N->getDebugLoc(), VT, N0.getOperand(0), + DAG.getConstant(Sum, N1C->getValueType(0))); + } + } + + // fold (sra (shl X, m), (sub result_size, n)) + // -> (sign_extend (trunc (shl X, (sub (sub result_size, n), m)))) for + // result_size - n != m. + // If truncate is free for the target sext(shl) is likely to result in better + // code. + if (N0.getOpcode() == ISD::SHL) { + // Get the two constanst of the shifts, CN0 = m, CN = n. + const ConstantSDNode *N01C = dyn_cast(N0.getOperand(1)); + if (N01C && N1C) { + // Determine what the truncate's result bitsize and type would be. + unsigned VTValSize = VT.getSizeInBits(); + EVT TruncVT = + EVT::getIntegerVT(*DAG.getContext(), VTValSize - N1C->getZExtValue()); + // Determine the residual right-shift amount. + signed ShiftAmt = N1C->getZExtValue() - N01C->getZExtValue(); + + // If the shift is not a no-op (in which case this should be just a sign + // extend already), the truncated to type is legal, sign_extend is legal + // on that type, and the the truncate to that type is both legal and free, + // perform the transform. + if ((ShiftAmt > 0) && + TLI.isOperationLegalOrCustom(ISD::SIGN_EXTEND, TruncVT) && + TLI.isOperationLegalOrCustom(ISD::TRUNCATE, VT) && + TLI.isTruncateFree(VT, TruncVT)) { + + SDValue Amt = DAG.getConstant(ShiftAmt, getShiftAmountTy()); + SDValue Shift = DAG.getNode(ISD::SRL, N0.getDebugLoc(), VT, + N0.getOperand(0), Amt); + SDValue Trunc = DAG.getNode(ISD::TRUNCATE, N0.getDebugLoc(), TruncVT, + Shift); + return DAG.getNode(ISD::SIGN_EXTEND, N->getDebugLoc(), + N->getValueType(0), Trunc); + } + } + } + + // fold (sra x, (trunc (and y, c))) -> (sra x, (and (trunc y), (trunc c))). + if (N1.getOpcode() == ISD::TRUNCATE && + N1.getOperand(0).getOpcode() == ISD::AND && + N1.hasOneUse() && N1.getOperand(0).hasOneUse()) { + SDValue N101 = N1.getOperand(0).getOperand(1); + if (ConstantSDNode *N101C = dyn_cast(N101)) { + EVT TruncVT = N1.getValueType(); + SDValue N100 = N1.getOperand(0).getOperand(0); + APInt TruncC = N101C->getAPIntValue(); + TruncC.trunc(TruncVT.getSizeInBits()); + return DAG.getNode(ISD::SRA, N->getDebugLoc(), VT, N0, + DAG.getNode(ISD::AND, N->getDebugLoc(), + TruncVT, + DAG.getNode(ISD::TRUNCATE, + N->getDebugLoc(), + TruncVT, N100), + DAG.getConstant(TruncC, TruncVT))); + } + } + + // Simplify, based on bits shifted out of the LHS. + if (N1C && SimplifyDemandedBits(SDValue(N, 0))) + return SDValue(N, 0); + + + // If the sign bit is known to be zero, switch this to a SRL. + if (DAG.SignBitIsZero(N0)) + return DAG.getNode(ISD::SRL, N->getDebugLoc(), VT, N0, N1); + + return N1C ? visitShiftByConstant(N, N1C->getZExtValue()) : SDValue(); +} + +SDValue DAGCombiner::visitSRL(SDNode *N) { + SDValue N0 = N->getOperand(0); + SDValue N1 = N->getOperand(1); + ConstantSDNode *N0C = dyn_cast(N0); + ConstantSDNode *N1C = dyn_cast(N1); + EVT VT = N0.getValueType(); + unsigned OpSizeInBits = VT.getSizeInBits(); + + // fold (srl c1, c2) -> c1 >>u c2 + if (N0C && N1C) + return DAG.FoldConstantArithmetic(ISD::SRL, VT, N0C, N1C); + // fold (srl 0, x) -> 0 + if (N0C && N0C->isNullValue()) + return N0; + // fold (srl x, c >= size(x)) -> undef + if (N1C && N1C->getZExtValue() >= OpSizeInBits) + return DAG.getUNDEF(VT); + // fold (srl x, 0) -> x + if (N1C && N1C->isNullValue()) + return N0; + // if (srl x, c) is known to be zero, return 0 + if (N1C && DAG.MaskedValueIsZero(SDValue(N, 0), + APInt::getAllOnesValue(OpSizeInBits))) + return DAG.getConstant(0, VT); + + // fold (srl (srl x, c1), c2) -> 0 or (srl x, (add c1, c2)) + if (N1C && N0.getOpcode() == ISD::SRL && + N0.getOperand(1).getOpcode() == ISD::Constant) { + uint64_t c1 = cast(N0.getOperand(1))->getZExtValue(); + uint64_t c2 = N1C->getZExtValue(); + if (c1 + c2 > OpSizeInBits) + return DAG.getConstant(0, VT); + return DAG.getNode(ISD::SRL, N->getDebugLoc(), VT, N0.getOperand(0), + DAG.getConstant(c1 + c2, N1.getValueType())); + } + + // fold (srl (anyextend x), c) -> (anyextend (srl x, c)) + if (N1C && N0.getOpcode() == ISD::ANY_EXTEND) { + // Shifting in all undef bits? + EVT SmallVT = N0.getOperand(0).getValueType(); + if (N1C->getZExtValue() >= SmallVT.getSizeInBits()) + return DAG.getUNDEF(VT); + + SDValue SmallShift = DAG.getNode(ISD::SRL, N0.getDebugLoc(), SmallVT, + N0.getOperand(0), N1); + AddToWorkList(SmallShift.getNode()); + return DAG.getNode(ISD::ANY_EXTEND, N->getDebugLoc(), VT, SmallShift); + } + + // fold (srl (sra X, Y), 31) -> (srl X, 31). This srl only looks at the sign + // bit, which is unmodified by sra. + if (N1C && N1C->getZExtValue() + 1 == VT.getSizeInBits()) { + if (N0.getOpcode() == ISD::SRA) + return DAG.getNode(ISD::SRL, N->getDebugLoc(), VT, N0.getOperand(0), N1); + } + + // fold (srl (ctlz x), "5") -> x iff x has one bit set (the low bit). + if (N1C && N0.getOpcode() == ISD::CTLZ && + N1C->getAPIntValue() == Log2_32(VT.getSizeInBits())) { + APInt KnownZero, KnownOne; + APInt Mask = APInt::getAllOnesValue(VT.getSizeInBits()); + DAG.ComputeMaskedBits(N0.getOperand(0), Mask, KnownZero, KnownOne); + + // If any of the input bits are KnownOne, then the input couldn't be all + // zeros, thus the result of the srl will always be zero. + if (KnownOne.getBoolValue()) return DAG.getConstant(0, VT); + + // If all of the bits input the to ctlz node are known to be zero, then + // the result of the ctlz is "32" and the result of the shift is one. + APInt UnknownBits = ~KnownZero & Mask; + if (UnknownBits == 0) return DAG.getConstant(1, VT); + + // Otherwise, check to see if there is exactly one bit input to the ctlz. + if ((UnknownBits & (UnknownBits - 1)) == 0) { + // Okay, we know that only that the single bit specified by UnknownBits + // could be set on input to the CTLZ node. If this bit is set, the SRL + // will return 0, if it is clear, it returns 1. Change the CTLZ/SRL pair + // to an SRL/XOR pair, which is likely to simplify more. + unsigned ShAmt = UnknownBits.countTrailingZeros(); + SDValue Op = N0.getOperand(0); + + if (ShAmt) { + Op = DAG.getNode(ISD::SRL, N0.getDebugLoc(), VT, Op, + DAG.getConstant(ShAmt, getShiftAmountTy())); + AddToWorkList(Op.getNode()); + } + + return DAG.getNode(ISD::XOR, N->getDebugLoc(), VT, + Op, DAG.getConstant(1, VT)); + } + } + + // fold (srl x, (trunc (and y, c))) -> (srl x, (and (trunc y), (trunc c))). + if (N1.getOpcode() == ISD::TRUNCATE && + N1.getOperand(0).getOpcode() == ISD::AND && + N1.hasOneUse() && N1.getOperand(0).hasOneUse()) { + SDValue N101 = N1.getOperand(0).getOperand(1); + if (ConstantSDNode *N101C = dyn_cast(N101)) { + EVT TruncVT = N1.getValueType(); + SDValue N100 = N1.getOperand(0).getOperand(0); + APInt TruncC = N101C->getAPIntValue(); + TruncC.trunc(TruncVT.getSizeInBits()); + return DAG.getNode(ISD::SRL, N->getDebugLoc(), VT, N0, + DAG.getNode(ISD::AND, N->getDebugLoc(), + TruncVT, + DAG.getNode(ISD::TRUNCATE, + N->getDebugLoc(), + TruncVT, N100), + DAG.getConstant(TruncC, TruncVT))); + } + } + + // fold operands of srl based on knowledge that the low bits are not + // demanded. + if (N1C && SimplifyDemandedBits(SDValue(N, 0))) + return SDValue(N, 0); + + return N1C ? visitShiftByConstant(N, N1C->getZExtValue()) : SDValue(); +} + +SDValue DAGCombiner::visitCTLZ(SDNode *N) { + SDValue N0 = N->getOperand(0); + EVT VT = N->getValueType(0); + + // fold (ctlz c1) -> c2 + if (isa(N0)) + return DAG.getNode(ISD::CTLZ, N->getDebugLoc(), VT, N0); + return SDValue(); +} + +SDValue DAGCombiner::visitCTTZ(SDNode *N) { + SDValue N0 = N->getOperand(0); + EVT VT = N->getValueType(0); + + // fold (cttz c1) -> c2 + if (isa(N0)) + return DAG.getNode(ISD::CTTZ, N->getDebugLoc(), VT, N0); + return SDValue(); +} + +SDValue DAGCombiner::visitCTPOP(SDNode *N) { + SDValue N0 = N->getOperand(0); + EVT VT = N->getValueType(0); + + // fold (ctpop c1) -> c2 + if (isa(N0)) + return DAG.getNode(ISD::CTPOP, N->getDebugLoc(), VT, N0); + return SDValue(); +} + +SDValue DAGCombiner::visitSELECT(SDNode *N) { + SDValue N0 = N->getOperand(0); + SDValue N1 = N->getOperand(1); + SDValue N2 = N->getOperand(2); + ConstantSDNode *N0C = dyn_cast(N0); + ConstantSDNode *N1C = dyn_cast(N1); + ConstantSDNode *N2C = dyn_cast(N2); + EVT VT = N->getValueType(0); + EVT VT0 = N0.getValueType(); + + // fold (select C, X, X) -> X + if (N1 == N2) + return N1; + // fold (select true, X, Y) -> X + if (N0C && !N0C->isNullValue()) + return N1; + // fold (select false, X, Y) -> Y + if (N0C && N0C->isNullValue()) + return N2; + // fold (select C, 1, X) -> (or C, X) + if (VT == MVT::i1 && N1C && N1C->getAPIntValue() == 1) + return DAG.getNode(ISD::OR, N->getDebugLoc(), VT, N0, N2); + // fold (select C, 0, 1) -> (xor C, 1) + if (VT.isInteger() && + (VT0 == MVT::i1 || + (VT0.isInteger() && + TLI.getBooleanContents() == TargetLowering::ZeroOrOneBooleanContent)) && + N1C && N2C && N1C->isNullValue() && N2C->getAPIntValue() == 1) { + SDValue XORNode; + if (VT == VT0) + return DAG.getNode(ISD::XOR, N->getDebugLoc(), VT0, + N0, DAG.getConstant(1, VT0)); + XORNode = DAG.getNode(ISD::XOR, N0.getDebugLoc(), VT0, + N0, DAG.getConstant(1, VT0)); + AddToWorkList(XORNode.getNode()); + if (VT.bitsGT(VT0)) + return DAG.getNode(ISD::ZERO_EXTEND, N->getDebugLoc(), VT, XORNode); + return DAG.getNode(ISD::TRUNCATE, N->getDebugLoc(), VT, XORNode); + } + // fold (select C, 0, X) -> (and (not C), X) + if (VT == VT0 && VT == MVT::i1 && N1C && N1C->isNullValue()) { + SDValue NOTNode = DAG.getNOT(N0.getDebugLoc(), N0, VT); + AddToWorkList(NOTNode.getNode()); + return DAG.getNode(ISD::AND, N->getDebugLoc(), VT, NOTNode, N2); + } + // fold (select C, X, 1) -> (or (not C), X) + if (VT == VT0 && VT == MVT::i1 && N2C && N2C->getAPIntValue() == 1) { + SDValue NOTNode = DAG.getNOT(N0.getDebugLoc(), N0, VT); + AddToWorkList(NOTNode.getNode()); + return DAG.getNode(ISD::OR, N->getDebugLoc(), VT, NOTNode, N1); + } + // fold (select C, X, 0) -> (and C, X) + if (VT == MVT::i1 && N2C && N2C->isNullValue()) + return DAG.getNode(ISD::AND, N->getDebugLoc(), VT, N0, N1); + // fold (select X, X, Y) -> (or X, Y) + // fold (select X, 1, Y) -> (or X, Y) + if (VT == MVT::i1 && (N0 == N1 || (N1C && N1C->getAPIntValue() == 1))) + return DAG.getNode(ISD::OR, N->getDebugLoc(), VT, N0, N2); + // fold (select X, Y, X) -> (and X, Y) + // fold (select X, Y, 0) -> (and X, Y) + if (VT == MVT::i1 && (N0 == N2 || (N2C && N2C->getAPIntValue() == 0))) + return DAG.getNode(ISD::AND, N->getDebugLoc(), VT, N0, N1); + + // If we can fold this based on the true/false value, do so. + if (SimplifySelectOps(N, N1, N2)) + return SDValue(N, 0); // Don't revisit N. + + // fold selects based on a setcc into other things, such as min/max/abs + if (N0.getOpcode() == ISD::SETCC) { + // FIXME: + // Check against MVT::Other for SELECT_CC, which is a workaround for targets + // having to say they don't support SELECT_CC on every type the DAG knows + // about, since there is no way to mark an opcode illegal at all value types + if (TLI.isOperationLegalOrCustom(ISD::SELECT_CC, MVT::Other) && + TLI.isOperationLegalOrCustom(ISD::SELECT_CC, VT)) + return DAG.getNode(ISD::SELECT_CC, N->getDebugLoc(), VT, + N0.getOperand(0), N0.getOperand(1), + N1, N2, N0.getOperand(2)); + return SimplifySelect(N->getDebugLoc(), N0, N1, N2); + } + + return SDValue(); +} + +SDValue DAGCombiner::visitSELECT_CC(SDNode *N) { + SDValue N0 = N->getOperand(0); + SDValue N1 = N->getOperand(1); + SDValue N2 = N->getOperand(2); + SDValue N3 = N->getOperand(3); + SDValue N4 = N->getOperand(4); + ISD::CondCode CC = cast(N4)->get(); + + // fold select_cc lhs, rhs, x, x, cc -> x + if (N2 == N3) + return N2; + + // Determine if the condition we're dealing with is constant + SDValue SCC = SimplifySetCC(TLI.getSetCCResultType(N0.getValueType()), + N0, N1, CC, N->getDebugLoc(), false); + if (SCC.getNode()) AddToWorkList(SCC.getNode()); + + if (ConstantSDNode *SCCC = dyn_cast_or_null(SCC.getNode())) { + if (!SCCC->isNullValue()) + return N2; // cond always true -> true val + else + return N3; // cond always false -> false val + } + + // Fold to a simpler select_cc + if (SCC.getNode() && SCC.getOpcode() == ISD::SETCC) + return DAG.getNode(ISD::SELECT_CC, N->getDebugLoc(), N2.getValueType(), + SCC.getOperand(0), SCC.getOperand(1), N2, N3, + SCC.getOperand(2)); + + // If we can fold this based on the true/false value, do so. + if (SimplifySelectOps(N, N2, N3)) + return SDValue(N, 0); // Don't revisit N. + + // fold select_cc into other things, such as min/max/abs + return SimplifySelectCC(N->getDebugLoc(), N0, N1, N2, N3, CC); +} + +SDValue DAGCombiner::visitSETCC(SDNode *N) { + return SimplifySetCC(N->getValueType(0), N->getOperand(0), N->getOperand(1), + cast(N->getOperand(2))->get(), + N->getDebugLoc()); +} + +// ExtendUsesToFormExtLoad - Trying to extend uses of a load to enable this: +// "fold ({s|z|a}ext (load x)) -> ({s|z|a}ext (truncate ({s|z|a}extload x)))" +// transformation. Returns true if extension are possible and the above +// mentioned transformation is profitable. +static bool ExtendUsesToFormExtLoad(SDNode *N, SDValue N0, + unsigned ExtOpc, + SmallVector &ExtendNodes, + const TargetLowering &TLI) { + bool HasCopyToRegUses = false; + bool isTruncFree = TLI.isTruncateFree(N->getValueType(0), N0.getValueType()); + for (SDNode::use_iterator UI = N0.getNode()->use_begin(), + UE = N0.getNode()->use_end(); + UI != UE; ++UI) { + SDNode *User = *UI; + if (User == N) + continue; + if (UI.getUse().getResNo() != N0.getResNo()) + continue; + // FIXME: Only extend SETCC N, N and SETCC N, c for now. + if (ExtOpc != ISD::ANY_EXTEND && User->getOpcode() == ISD::SETCC) { + ISD::CondCode CC = cast(User->getOperand(2))->get(); + if (ExtOpc == ISD::ZERO_EXTEND && ISD::isSignedIntSetCC(CC)) + // Sign bits will be lost after a zext. + return false; + bool Add = false; + for (unsigned i = 0; i != 2; ++i) { + SDValue UseOp = User->getOperand(i); + if (UseOp == N0) + continue; + if (!isa(UseOp)) + return false; + Add = true; + } + if (Add) + ExtendNodes.push_back(User); + continue; + } + // If truncates aren't free and there are users we can't + // extend, it isn't worthwhile. + if (!isTruncFree) + return false; + // Remember if this value is live-out. + if (User->getOpcode() == ISD::CopyToReg) + HasCopyToRegUses = true; + } + + if (HasCopyToRegUses) { + bool BothLiveOut = false; + for (SDNode::use_iterator UI = N->use_begin(), UE = N->use_end(); + UI != UE; ++UI) { + SDUse &Use = UI.getUse(); + if (Use.getResNo() == 0 && Use.getUser()->getOpcode() == ISD::CopyToReg) { + BothLiveOut = true; + break; + } + } + if (BothLiveOut) + // Both unextended and extended values are live out. There had better be + // good a reason for the transformation. + return ExtendNodes.size(); + } + return true; +} + +SDValue DAGCombiner::visitSIGN_EXTEND(SDNode *N) { + SDValue N0 = N->getOperand(0); + EVT VT = N->getValueType(0); + + // fold (sext c1) -> c1 + if (isa(N0)) + return DAG.getNode(ISD::SIGN_EXTEND, N->getDebugLoc(), VT, N0); + + // fold (sext (sext x)) -> (sext x) + // fold (sext (aext x)) -> (sext x) + if (N0.getOpcode() == ISD::SIGN_EXTEND || N0.getOpcode() == ISD::ANY_EXTEND) + return DAG.getNode(ISD::SIGN_EXTEND, N->getDebugLoc(), VT, + N0.getOperand(0)); + + if (N0.getOpcode() == ISD::TRUNCATE) { + // fold (sext (truncate (load x))) -> (sext (smaller load x)) + // fold (sext (truncate (srl (load x), c))) -> (sext (smaller load (x+c/n))) + SDValue NarrowLoad = ReduceLoadWidth(N0.getNode()); + if (NarrowLoad.getNode()) { + if (NarrowLoad.getNode() != N0.getNode()) + CombineTo(N0.getNode(), NarrowLoad); + return SDValue(N, 0); // Return N so it doesn't get rechecked! + } + + // See if the value being truncated is already sign extended. If so, just + // eliminate the trunc/sext pair. + SDValue Op = N0.getOperand(0); + unsigned OpBits = Op.getValueType().getSizeInBits(); + unsigned MidBits = N0.getValueType().getSizeInBits(); + unsigned DestBits = VT.getSizeInBits(); + unsigned NumSignBits = DAG.ComputeNumSignBits(Op); + + if (OpBits == DestBits) { + // Op is i32, Mid is i8, and Dest is i32. If Op has more than 24 sign + // bits, it is already ready. + if (NumSignBits > DestBits-MidBits) + return Op; + } else if (OpBits < DestBits) { + // Op is i32, Mid is i8, and Dest is i64. If Op has more than 24 sign + // bits, just sext from i32. + if (NumSignBits > OpBits-MidBits) + return DAG.getNode(ISD::SIGN_EXTEND, N->getDebugLoc(), VT, Op); + } else { + // Op is i64, Mid is i8, and Dest is i32. If Op has more than 56 sign + // bits, just truncate to i32. + if (NumSignBits > OpBits-MidBits) + return DAG.getNode(ISD::TRUNCATE, N->getDebugLoc(), VT, Op); + } + + // fold (sext (truncate x)) -> (sextinreg x). + if (!LegalOperations || TLI.isOperationLegal(ISD::SIGN_EXTEND_INREG, + N0.getValueType())) { + if (Op.getValueType().bitsLT(VT)) + Op = DAG.getNode(ISD::ANY_EXTEND, N0.getDebugLoc(), VT, Op); + else if (Op.getValueType().bitsGT(VT)) + Op = DAG.getNode(ISD::TRUNCATE, N0.getDebugLoc(), VT, Op); + return DAG.getNode(ISD::SIGN_EXTEND_INREG, N->getDebugLoc(), VT, Op, + DAG.getValueType(N0.getValueType())); + } + } + + // fold (sext (load x)) -> (sext (truncate (sextload x))) + if (ISD::isNON_EXTLoad(N0.getNode()) && + ((!LegalOperations && !cast(N0)->isVolatile()) || + TLI.isLoadExtLegal(ISD::SEXTLOAD, N0.getValueType()))) { + bool DoXform = true; + SmallVector SetCCs; + if (!N0.hasOneUse()) + DoXform = ExtendUsesToFormExtLoad(N, N0, ISD::SIGN_EXTEND, SetCCs, TLI); + if (DoXform) { + LoadSDNode *LN0 = cast(N0); + SDValue ExtLoad = DAG.getExtLoad(ISD::SEXTLOAD, N->getDebugLoc(), VT, + LN0->getChain(), + LN0->getBasePtr(), LN0->getSrcValue(), + LN0->getSrcValueOffset(), + N0.getValueType(), + LN0->isVolatile(), LN0->getAlignment()); + CombineTo(N, ExtLoad); + SDValue Trunc = DAG.getNode(ISD::TRUNCATE, N0.getDebugLoc(), + N0.getValueType(), ExtLoad); + CombineTo(N0.getNode(), Trunc, ExtLoad.getValue(1)); + + // Extend SetCC uses if necessary. + for (unsigned i = 0, e = SetCCs.size(); i != e; ++i) { + SDNode *SetCC = SetCCs[i]; + SmallVector Ops; + + for (unsigned j = 0; j != 2; ++j) { + SDValue SOp = SetCC->getOperand(j); + if (SOp == Trunc) + Ops.push_back(ExtLoad); + else + Ops.push_back(DAG.getNode(ISD::SIGN_EXTEND, + N->getDebugLoc(), VT, SOp)); + } + + Ops.push_back(SetCC->getOperand(2)); + CombineTo(SetCC, DAG.getNode(ISD::SETCC, N->getDebugLoc(), + SetCC->getValueType(0), + &Ops[0], Ops.size())); + } + + return SDValue(N, 0); // Return N so it doesn't get rechecked! + } + } + + // fold (sext (sextload x)) -> (sext (truncate (sextload x))) + // fold (sext ( extload x)) -> (sext (truncate (sextload x))) + if ((ISD::isSEXTLoad(N0.getNode()) || ISD::isEXTLoad(N0.getNode())) && + ISD::isUNINDEXEDLoad(N0.getNode()) && N0.hasOneUse()) { + LoadSDNode *LN0 = cast(N0); + EVT MemVT = LN0->getMemoryVT(); + if ((!LegalOperations && !LN0->isVolatile()) || + TLI.isLoadExtLegal(ISD::SEXTLOAD, MemVT)) { + SDValue ExtLoad = DAG.getExtLoad(ISD::SEXTLOAD, N->getDebugLoc(), VT, + LN0->getChain(), + LN0->getBasePtr(), LN0->getSrcValue(), + LN0->getSrcValueOffset(), MemVT, + LN0->isVolatile(), LN0->getAlignment()); + CombineTo(N, ExtLoad); + CombineTo(N0.getNode(), + DAG.getNode(ISD::TRUNCATE, N0.getDebugLoc(), + N0.getValueType(), ExtLoad), + ExtLoad.getValue(1)); + return SDValue(N, 0); // Return N so it doesn't get rechecked! + } + } + + if (N0.getOpcode() == ISD::SETCC) { + // sext(setcc) -> sext_in_reg(vsetcc) for vectors. + if (VT.isVector() && + // We know that the # elements of the results is the same as the + // # elements of the compare (and the # elements of the compare result + // for that matter). Check to see that they are the same size. If so, + // we know that the element size of the sext'd result matches the + // element size of the compare operands. + VT.getSizeInBits() == N0.getOperand(0).getValueType().getSizeInBits() && + + // Only do this before legalize for now. + !LegalOperations) { + return DAG.getVSetCC(N->getDebugLoc(), VT, N0.getOperand(0), + N0.getOperand(1), + cast(N0.getOperand(2))->get()); + } + + // sext(setcc x, y, cc) -> (select_cc x, y, -1, 0, cc) + SDValue NegOne = + DAG.getConstant(APInt::getAllOnesValue(VT.getSizeInBits()), VT); + SDValue SCC = + SimplifySelectCC(N->getDebugLoc(), N0.getOperand(0), N0.getOperand(1), + NegOne, DAG.getConstant(0, VT), + cast(N0.getOperand(2))->get(), true); + if (SCC.getNode()) return SCC; + } + + + + // fold (sext x) -> (zext x) if the sign bit is known zero. + if ((!LegalOperations || TLI.isOperationLegal(ISD::ZERO_EXTEND, VT)) && + DAG.SignBitIsZero(N0)) + return DAG.getNode(ISD::ZERO_EXTEND, N->getDebugLoc(), VT, N0); + + return SDValue(); +} + +SDValue DAGCombiner::visitZERO_EXTEND(SDNode *N) { + SDValue N0 = N->getOperand(0); + EVT VT = N->getValueType(0); + + // fold (zext c1) -> c1 + if (isa(N0)) + return DAG.getNode(ISD::ZERO_EXTEND, N->getDebugLoc(), VT, N0); + // fold (zext (zext x)) -> (zext x) + // fold (zext (aext x)) -> (zext x) + if (N0.getOpcode() == ISD::ZERO_EXTEND || N0.getOpcode() == ISD::ANY_EXTEND) + return DAG.getNode(ISD::ZERO_EXTEND, N->getDebugLoc(), VT, + N0.getOperand(0)); + + // fold (zext (truncate (load x))) -> (zext (smaller load x)) + // fold (zext (truncate (srl (load x), c))) -> (zext (small load (x+c/n))) + if (N0.getOpcode() == ISD::TRUNCATE) { + SDValue NarrowLoad = ReduceLoadWidth(N0.getNode()); + if (NarrowLoad.getNode()) { + if (NarrowLoad.getNode() != N0.getNode()) + CombineTo(N0.getNode(), NarrowLoad); + return DAG.getNode(ISD::ZERO_EXTEND, N->getDebugLoc(), VT, NarrowLoad); + } + } + + // fold (zext (truncate x)) -> (and x, mask) + if (N0.getOpcode() == ISD::TRUNCATE && + (!LegalOperations || TLI.isOperationLegal(ISD::AND, VT))) { + SDValue Op = N0.getOperand(0); + if (Op.getValueType().bitsLT(VT)) { + Op = DAG.getNode(ISD::ANY_EXTEND, N->getDebugLoc(), VT, Op); + } else if (Op.getValueType().bitsGT(VT)) { + Op = DAG.getNode(ISD::TRUNCATE, N->getDebugLoc(), VT, Op); + } + return DAG.getZeroExtendInReg(Op, N->getDebugLoc(), N0.getValueType()); + } + + // Fold (zext (and (trunc x), cst)) -> (and x, cst), + // if either of the casts is not free. + if (N0.getOpcode() == ISD::AND && + N0.getOperand(0).getOpcode() == ISD::TRUNCATE && + N0.getOperand(1).getOpcode() == ISD::Constant && + (!TLI.isTruncateFree(N0.getOperand(0).getOperand(0).getValueType(), + N0.getValueType()) || + !TLI.isZExtFree(N0.getValueType(), VT))) { + SDValue X = N0.getOperand(0).getOperand(0); + if (X.getValueType().bitsLT(VT)) { + X = DAG.getNode(ISD::ANY_EXTEND, X.getDebugLoc(), VT, X); + } else if (X.getValueType().bitsGT(VT)) { + X = DAG.getNode(ISD::TRUNCATE, X.getDebugLoc(), VT, X); + } + APInt Mask = cast(N0.getOperand(1))->getAPIntValue(); + Mask.zext(VT.getSizeInBits()); + return DAG.getNode(ISD::AND, N->getDebugLoc(), VT, + X, DAG.getConstant(Mask, VT)); + } + + // fold (zext (load x)) -> (zext (truncate (zextload x))) + if (ISD::isNON_EXTLoad(N0.getNode()) && + ((!LegalOperations && !cast(N0)->isVolatile()) || + TLI.isLoadExtLegal(ISD::ZEXTLOAD, N0.getValueType()))) { + bool DoXform = true; + SmallVector SetCCs; + if (!N0.hasOneUse()) + DoXform = ExtendUsesToFormExtLoad(N, N0, ISD::ZERO_EXTEND, SetCCs, TLI); + if (DoXform) { + LoadSDNode *LN0 = cast(N0); + SDValue ExtLoad = DAG.getExtLoad(ISD::ZEXTLOAD, N->getDebugLoc(), VT, + LN0->getChain(), + LN0->getBasePtr(), LN0->getSrcValue(), + LN0->getSrcValueOffset(), + N0.getValueType(), + LN0->isVolatile(), LN0->getAlignment()); + CombineTo(N, ExtLoad); + SDValue Trunc = DAG.getNode(ISD::TRUNCATE, N0.getDebugLoc(), + N0.getValueType(), ExtLoad); + CombineTo(N0.getNode(), Trunc, ExtLoad.getValue(1)); + + // Extend SetCC uses if necessary. + for (unsigned i = 0, e = SetCCs.size(); i != e; ++i) { + SDNode *SetCC = SetCCs[i]; + SmallVector Ops; + + for (unsigned j = 0; j != 2; ++j) { + SDValue SOp = SetCC->getOperand(j); + if (SOp == Trunc) + Ops.push_back(ExtLoad); + else + Ops.push_back(DAG.getNode(ISD::ZERO_EXTEND, + N->getDebugLoc(), VT, SOp)); + } + + Ops.push_back(SetCC->getOperand(2)); + CombineTo(SetCC, DAG.getNode(ISD::SETCC, N->getDebugLoc(), + SetCC->getValueType(0), + &Ops[0], Ops.size())); + } + + return SDValue(N, 0); // Return N so it doesn't get rechecked! + } + } + + // fold (zext (zextload x)) -> (zext (truncate (zextload x))) + // fold (zext ( extload x)) -> (zext (truncate (zextload x))) + if ((ISD::isZEXTLoad(N0.getNode()) || ISD::isEXTLoad(N0.getNode())) && + ISD::isUNINDEXEDLoad(N0.getNode()) && N0.hasOneUse()) { + LoadSDNode *LN0 = cast(N0); + EVT MemVT = LN0->getMemoryVT(); + if ((!LegalOperations && !LN0->isVolatile()) || + TLI.isLoadExtLegal(ISD::ZEXTLOAD, MemVT)) { + SDValue ExtLoad = DAG.getExtLoad(ISD::ZEXTLOAD, N->getDebugLoc(), VT, + LN0->getChain(), + LN0->getBasePtr(), LN0->getSrcValue(), + LN0->getSrcValueOffset(), MemVT, + LN0->isVolatile(), LN0->getAlignment()); + CombineTo(N, ExtLoad); + CombineTo(N0.getNode(), + DAG.getNode(ISD::TRUNCATE, N0.getDebugLoc(), N0.getValueType(), + ExtLoad), + ExtLoad.getValue(1)); + return SDValue(N, 0); // Return N so it doesn't get rechecked! + } + } + + // zext(setcc x,y,cc) -> select_cc x, y, 1, 0, cc + if (N0.getOpcode() == ISD::SETCC) { + SDValue SCC = + SimplifySelectCC(N->getDebugLoc(), N0.getOperand(0), N0.getOperand(1), + DAG.getConstant(1, VT), DAG.getConstant(0, VT), + cast(N0.getOperand(2))->get(), true); + if (SCC.getNode()) return SCC; + } + + return SDValue(); +} + +SDValue DAGCombiner::visitANY_EXTEND(SDNode *N) { + SDValue N0 = N->getOperand(0); + EVT VT = N->getValueType(0); + + // fold (aext c1) -> c1 + if (isa(N0)) + return DAG.getNode(ISD::ANY_EXTEND, N->getDebugLoc(), VT, N0); + // fold (aext (aext x)) -> (aext x) + // fold (aext (zext x)) -> (zext x) + // fold (aext (sext x)) -> (sext x) + if (N0.getOpcode() == ISD::ANY_EXTEND || + N0.getOpcode() == ISD::ZERO_EXTEND || + N0.getOpcode() == ISD::SIGN_EXTEND) + return DAG.getNode(N0.getOpcode(), N->getDebugLoc(), VT, N0.getOperand(0)); + + // fold (aext (truncate (load x))) -> (aext (smaller load x)) + // fold (aext (truncate (srl (load x), c))) -> (aext (small load (x+c/n))) + if (N0.getOpcode() == ISD::TRUNCATE) { + SDValue NarrowLoad = ReduceLoadWidth(N0.getNode()); + if (NarrowLoad.getNode()) { + if (NarrowLoad.getNode() != N0.getNode()) + CombineTo(N0.getNode(), NarrowLoad); + return DAG.getNode(ISD::ANY_EXTEND, N->getDebugLoc(), VT, NarrowLoad); + } + } + + // fold (aext (truncate x)) + if (N0.getOpcode() == ISD::TRUNCATE) { + SDValue TruncOp = N0.getOperand(0); + if (TruncOp.getValueType() == VT) + return TruncOp; // x iff x size == zext size. + if (TruncOp.getValueType().bitsGT(VT)) + return DAG.getNode(ISD::TRUNCATE, N->getDebugLoc(), VT, TruncOp); + return DAG.getNode(ISD::ANY_EXTEND, N->getDebugLoc(), VT, TruncOp); + } + + // Fold (aext (and (trunc x), cst)) -> (and x, cst) + // if the trunc is not free. + if (N0.getOpcode() == ISD::AND && + N0.getOperand(0).getOpcode() == ISD::TRUNCATE && + N0.getOperand(1).getOpcode() == ISD::Constant && + !TLI.isTruncateFree(N0.getOperand(0).getOperand(0).getValueType(), + N0.getValueType())) { + SDValue X = N0.getOperand(0).getOperand(0); + if (X.getValueType().bitsLT(VT)) { + X = DAG.getNode(ISD::ANY_EXTEND, N->getDebugLoc(), VT, X); + } else if (X.getValueType().bitsGT(VT)) { + X = DAG.getNode(ISD::TRUNCATE, N->getDebugLoc(), VT, X); + } + APInt Mask = cast(N0.getOperand(1))->getAPIntValue(); + Mask.zext(VT.getSizeInBits()); + return DAG.getNode(ISD::AND, N->getDebugLoc(), VT, + X, DAG.getConstant(Mask, VT)); + } + + // fold (aext (load x)) -> (aext (truncate (extload x))) + if (ISD::isNON_EXTLoad(N0.getNode()) && + ((!LegalOperations && !cast(N0)->isVolatile()) || + TLI.isLoadExtLegal(ISD::EXTLOAD, N0.getValueType()))) { + bool DoXform = true; + SmallVector SetCCs; + if (!N0.hasOneUse()) + DoXform = ExtendUsesToFormExtLoad(N, N0, ISD::ANY_EXTEND, SetCCs, TLI); + if (DoXform) { + LoadSDNode *LN0 = cast(N0); + SDValue ExtLoad = DAG.getExtLoad(ISD::EXTLOAD, N->getDebugLoc(), VT, + LN0->getChain(), + LN0->getBasePtr(), LN0->getSrcValue(), + LN0->getSrcValueOffset(), + N0.getValueType(), + LN0->isVolatile(), LN0->getAlignment()); + CombineTo(N, ExtLoad); + SDValue Trunc = DAG.getNode(ISD::TRUNCATE, N0.getDebugLoc(), + N0.getValueType(), ExtLoad); + CombineTo(N0.getNode(), Trunc, ExtLoad.getValue(1)); + + // Extend SetCC uses if necessary. + for (unsigned i = 0, e = SetCCs.size(); i != e; ++i) { + SDNode *SetCC = SetCCs[i]; + SmallVector Ops; + + for (unsigned j = 0; j != 2; ++j) { + SDValue SOp = SetCC->getOperand(j); + if (SOp == Trunc) + Ops.push_back(ExtLoad); + else + Ops.push_back(DAG.getNode(ISD::ANY_EXTEND, + N->getDebugLoc(), VT, SOp)); + } + + Ops.push_back(SetCC->getOperand(2)); + CombineTo(SetCC, DAG.getNode(ISD::SETCC, N->getDebugLoc(), + SetCC->getValueType(0), + &Ops[0], Ops.size())); + } + + return SDValue(N, 0); // Return N so it doesn't get rechecked! + } + } + + // fold (aext (zextload x)) -> (aext (truncate (zextload x))) + // fold (aext (sextload x)) -> (aext (truncate (sextload x))) + // fold (aext ( extload x)) -> (aext (truncate (extload x))) + if (N0.getOpcode() == ISD::LOAD && + !ISD::isNON_EXTLoad(N0.getNode()) && ISD::isUNINDEXEDLoad(N0.getNode()) && + N0.hasOneUse()) { + LoadSDNode *LN0 = cast(N0); + EVT MemVT = LN0->getMemoryVT(); + SDValue ExtLoad = DAG.getExtLoad(LN0->getExtensionType(), N->getDebugLoc(), + VT, LN0->getChain(), LN0->getBasePtr(), + LN0->getSrcValue(), + LN0->getSrcValueOffset(), MemVT, + LN0->isVolatile(), LN0->getAlignment()); + CombineTo(N, ExtLoad); + CombineTo(N0.getNode(), + DAG.getNode(ISD::TRUNCATE, N0.getDebugLoc(), + N0.getValueType(), ExtLoad), + ExtLoad.getValue(1)); + return SDValue(N, 0); // Return N so it doesn't get rechecked! + } + + // aext(setcc x,y,cc) -> select_cc x, y, 1, 0, cc + if (N0.getOpcode() == ISD::SETCC) { + SDValue SCC = + SimplifySelectCC(N->getDebugLoc(), N0.getOperand(0), N0.getOperand(1), + DAG.getConstant(1, VT), DAG.getConstant(0, VT), + cast(N0.getOperand(2))->get(), true); + if (SCC.getNode()) + return SCC; + } + + return SDValue(); +} + +/// GetDemandedBits - See if the specified operand can be simplified with the +/// knowledge that only the bits specified by Mask are used. If so, return the +/// simpler operand, otherwise return a null SDValue. +SDValue DAGCombiner::GetDemandedBits(SDValue V, const APInt &Mask) { + switch (V.getOpcode()) { + default: break; + case ISD::OR: + case ISD::XOR: + // If the LHS or RHS don't contribute bits to the or, drop them. + if (DAG.MaskedValueIsZero(V.getOperand(0), Mask)) + return V.getOperand(1); + if (DAG.MaskedValueIsZero(V.getOperand(1), Mask)) + return V.getOperand(0); + break; + case ISD::SRL: + // Only look at single-use SRLs. + if (!V.getNode()->hasOneUse()) + break; + if (ConstantSDNode *RHSC = dyn_cast(V.getOperand(1))) { + // See if we can recursively simplify the LHS. + unsigned Amt = RHSC->getZExtValue(); + + // Watch out for shift count overflow though. + if (Amt >= Mask.getBitWidth()) break; + APInt NewMask = Mask << Amt; + SDValue SimplifyLHS = GetDemandedBits(V.getOperand(0), NewMask); + if (SimplifyLHS.getNode()) + return DAG.getNode(ISD::SRL, V.getDebugLoc(), V.getValueType(), + SimplifyLHS, V.getOperand(1)); + } + } + return SDValue(); +} + +/// ReduceLoadWidth - If the result of a wider load is shifted to right of N +/// bits and then truncated to a narrower type and where N is a multiple +/// of number of bits of the narrower type, transform it to a narrower load +/// from address + N / num of bits of new type. If the result is to be +/// extended, also fold the extension to form a extending load. +SDValue DAGCombiner::ReduceLoadWidth(SDNode *N) { + unsigned Opc = N->getOpcode(); + ISD::LoadExtType ExtType = ISD::NON_EXTLOAD; + SDValue N0 = N->getOperand(0); + EVT VT = N->getValueType(0); + EVT ExtVT = VT; + + // This transformation isn't valid for vector loads. + if (VT.isVector()) + return SDValue(); + + // Special case: SIGN_EXTEND_INREG is basically truncating to EVT then + // extended to VT. + if (Opc == ISD::SIGN_EXTEND_INREG) { + ExtType = ISD::SEXTLOAD; + ExtVT = cast(N->getOperand(1))->getVT(); + if (LegalOperations && !TLI.isLoadExtLegal(ISD::SEXTLOAD, ExtVT)) + return SDValue(); + } + + unsigned EVTBits = ExtVT.getSizeInBits(); + unsigned ShAmt = 0; + if (N0.getOpcode() == ISD::SRL && N0.hasOneUse() && ExtVT.isRound()) { + if (ConstantSDNode *N01 = dyn_cast(N0.getOperand(1))) { + ShAmt = N01->getZExtValue(); + // Is the shift amount a multiple of size of VT? + if ((ShAmt & (EVTBits-1)) == 0) { + N0 = N0.getOperand(0); + // Is the load width a multiple of size of VT? + if ((N0.getValueType().getSizeInBits() & (EVTBits-1)) != 0) + return SDValue(); + } + } + } + + // Do not generate loads of non-round integer types since these can + // be expensive (and would be wrong if the type is not byte sized). + if (isa(N0) && N0.hasOneUse() && ExtVT.isRound() && + cast(N0)->getMemoryVT().getSizeInBits() > EVTBits && + // Do not change the width of a volatile load. + !cast(N0)->isVolatile()) { + LoadSDNode *LN0 = cast(N0); + EVT PtrType = N0.getOperand(1).getValueType(); + + // For big endian targets, we need to adjust the offset to the pointer to + // load the correct bytes. + if (TLI.isBigEndian()) { + unsigned LVTStoreBits = LN0->getMemoryVT().getStoreSizeInBits(); + unsigned EVTStoreBits = ExtVT.getStoreSizeInBits(); + ShAmt = LVTStoreBits - EVTStoreBits - ShAmt; + } + + uint64_t PtrOff = ShAmt / 8; + unsigned NewAlign = MinAlign(LN0->getAlignment(), PtrOff); + SDValue NewPtr = DAG.getNode(ISD::ADD, LN0->getDebugLoc(), + PtrType, LN0->getBasePtr(), + DAG.getConstant(PtrOff, PtrType)); + AddToWorkList(NewPtr.getNode()); + + SDValue Load = (ExtType == ISD::NON_EXTLOAD) + ? DAG.getLoad(VT, N0.getDebugLoc(), LN0->getChain(), NewPtr, + LN0->getSrcValue(), LN0->getSrcValueOffset() + PtrOff, + LN0->isVolatile(), NewAlign) + : DAG.getExtLoad(ExtType, N0.getDebugLoc(), VT, LN0->getChain(), NewPtr, + LN0->getSrcValue(), LN0->getSrcValueOffset() + PtrOff, + ExtVT, LN0->isVolatile(), NewAlign); + + // Replace the old load's chain with the new load's chain. + WorkListRemover DeadNodes(*this); + DAG.ReplaceAllUsesOfValueWith(N0.getValue(1), Load.getValue(1), + &DeadNodes); + + // Return the new loaded value. + return Load; + } + + return SDValue(); +} + +SDValue DAGCombiner::visitSIGN_EXTEND_INREG(SDNode *N) { + SDValue N0 = N->getOperand(0); + SDValue N1 = N->getOperand(1); + EVT VT = N->getValueType(0); + EVT EVT = cast(N1)->getVT(); + unsigned VTBits = VT.getSizeInBits(); + unsigned EVTBits = EVT.getSizeInBits(); + + // fold (sext_in_reg c1) -> c1 + if (isa(N0) || N0.getOpcode() == ISD::UNDEF) + return DAG.getNode(ISD::SIGN_EXTEND_INREG, N->getDebugLoc(), VT, N0, N1); + + // If the input is already sign extended, just drop the extension. + if (DAG.ComputeNumSignBits(N0) >= VT.getSizeInBits()-EVTBits+1) + return N0; + + // fold (sext_in_reg (sext_in_reg x, VT2), VT1) -> (sext_in_reg x, minVT) pt2 + if (N0.getOpcode() == ISD::SIGN_EXTEND_INREG && + EVT.bitsLT(cast(N0.getOperand(1))->getVT())) { + return DAG.getNode(ISD::SIGN_EXTEND_INREG, N->getDebugLoc(), VT, + N0.getOperand(0), N1); + } + + // fold (sext_in_reg (sext x)) -> (sext x) + // fold (sext_in_reg (aext x)) -> (sext x) + // if x is small enough. + if (N0.getOpcode() == ISD::SIGN_EXTEND || N0.getOpcode() == ISD::ANY_EXTEND) { + SDValue N00 = N0.getOperand(0); + if (N00.getValueType().getSizeInBits() < EVTBits) + return DAG.getNode(ISD::SIGN_EXTEND, N->getDebugLoc(), VT, N00, N1); + } + + // fold (sext_in_reg x) -> (zext_in_reg x) if the sign bit is known zero. + if (DAG.MaskedValueIsZero(N0, APInt::getBitsSet(VTBits, EVTBits-1, EVTBits))) + return DAG.getZeroExtendInReg(N0, N->getDebugLoc(), EVT); + + // fold operands of sext_in_reg based on knowledge that the top bits are not + // demanded. + if (SimplifyDemandedBits(SDValue(N, 0))) + return SDValue(N, 0); + + // fold (sext_in_reg (load x)) -> (smaller sextload x) + // fold (sext_in_reg (srl (load x), c)) -> (smaller sextload (x+c/evtbits)) + SDValue NarrowLoad = ReduceLoadWidth(N); + if (NarrowLoad.getNode()) + return NarrowLoad; + + // fold (sext_in_reg (srl X, 24), i8) -> (sra X, 24) + // fold (sext_in_reg (srl X, 23), i8) -> (sra X, 23) iff possible. + // We already fold "(sext_in_reg (srl X, 25), i8) -> srl X, 25" above. + if (N0.getOpcode() == ISD::SRL) { + if (ConstantSDNode *ShAmt = dyn_cast(N0.getOperand(1))) + if (ShAmt->getZExtValue()+EVTBits <= VT.getSizeInBits()) { + // We can turn this into an SRA iff the input to the SRL is already sign + // extended enough. + unsigned InSignBits = DAG.ComputeNumSignBits(N0.getOperand(0)); + if (VT.getSizeInBits()-(ShAmt->getZExtValue()+EVTBits) < InSignBits) + return DAG.getNode(ISD::SRA, N->getDebugLoc(), VT, + N0.getOperand(0), N0.getOperand(1)); + } + } + + // fold (sext_inreg (extload x)) -> (sextload x) + if (ISD::isEXTLoad(N0.getNode()) && + ISD::isUNINDEXEDLoad(N0.getNode()) && + EVT == cast(N0)->getMemoryVT() && + ((!LegalOperations && !cast(N0)->isVolatile()) || + TLI.isLoadExtLegal(ISD::SEXTLOAD, EVT))) { + LoadSDNode *LN0 = cast(N0); + SDValue ExtLoad = DAG.getExtLoad(ISD::SEXTLOAD, N->getDebugLoc(), VT, + LN0->getChain(), + LN0->getBasePtr(), LN0->getSrcValue(), + LN0->getSrcValueOffset(), EVT, + LN0->isVolatile(), LN0->getAlignment()); + CombineTo(N, ExtLoad); + CombineTo(N0.getNode(), ExtLoad, ExtLoad.getValue(1)); + return SDValue(N, 0); // Return N so it doesn't get rechecked! + } + // fold (sext_inreg (zextload x)) -> (sextload x) iff load has one use + if (ISD::isZEXTLoad(N0.getNode()) && ISD::isUNINDEXEDLoad(N0.getNode()) && + N0.hasOneUse() && + EVT == cast(N0)->getMemoryVT() && + ((!LegalOperations && !cast(N0)->isVolatile()) || + TLI.isLoadExtLegal(ISD::SEXTLOAD, EVT))) { + LoadSDNode *LN0 = cast(N0); + SDValue ExtLoad = DAG.getExtLoad(ISD::SEXTLOAD, N->getDebugLoc(), VT, + LN0->getChain(), + LN0->getBasePtr(), LN0->getSrcValue(), + LN0->getSrcValueOffset(), EVT, + LN0->isVolatile(), LN0->getAlignment()); + CombineTo(N, ExtLoad); + CombineTo(N0.getNode(), ExtLoad, ExtLoad.getValue(1)); + return SDValue(N, 0); // Return N so it doesn't get rechecked! + } + return SDValue(); +} + +SDValue DAGCombiner::visitTRUNCATE(SDNode *N) { + SDValue N0 = N->getOperand(0); + EVT VT = N->getValueType(0); + + // noop truncate + if (N0.getValueType() == N->getValueType(0)) + return N0; + // fold (truncate c1) -> c1 + if (isa(N0)) + return DAG.getNode(ISD::TRUNCATE, N->getDebugLoc(), VT, N0); + // fold (truncate (truncate x)) -> (truncate x) + if (N0.getOpcode() == ISD::TRUNCATE) + return DAG.getNode(ISD::TRUNCATE, N->getDebugLoc(), VT, N0.getOperand(0)); + // fold (truncate (ext x)) -> (ext x) or (truncate x) or x + if (N0.getOpcode() == ISD::ZERO_EXTEND || N0.getOpcode() == ISD::SIGN_EXTEND|| + N0.getOpcode() == ISD::ANY_EXTEND) { + if (N0.getOperand(0).getValueType().bitsLT(VT)) + // if the source is smaller than the dest, we still need an extend + return DAG.getNode(N0.getOpcode(), N->getDebugLoc(), VT, + N0.getOperand(0)); + else if (N0.getOperand(0).getValueType().bitsGT(VT)) + // if the source is larger than the dest, than we just need the truncate + return DAG.getNode(ISD::TRUNCATE, N->getDebugLoc(), VT, N0.getOperand(0)); + else + // if the source and dest are the same type, we can drop both the extend + // and the truncate + return N0.getOperand(0); + } + + // See if we can simplify the input to this truncate through knowledge that + // only the low bits are being used. For example "trunc (or (shl x, 8), y)" + // -> trunc y + SDValue Shorter = + GetDemandedBits(N0, APInt::getLowBitsSet(N0.getValueSizeInBits(), + VT.getSizeInBits())); + if (Shorter.getNode()) + return DAG.getNode(ISD::TRUNCATE, N->getDebugLoc(), VT, Shorter); + + // fold (truncate (load x)) -> (smaller load x) + // fold (truncate (srl (load x), c)) -> (smaller load (x+c/evtbits)) + return ReduceLoadWidth(N); +} + +static SDNode *getBuildPairElt(SDNode *N, unsigned i) { + SDValue Elt = N->getOperand(i); + if (Elt.getOpcode() != ISD::MERGE_VALUES) + return Elt.getNode(); + return Elt.getOperand(Elt.getResNo()).getNode(); +} + +/// CombineConsecutiveLoads - build_pair (load, load) -> load +/// if load locations are consecutive. +SDValue DAGCombiner::CombineConsecutiveLoads(SDNode *N, EVT VT) { + assert(N->getOpcode() == ISD::BUILD_PAIR); + + LoadSDNode *LD1 = dyn_cast(getBuildPairElt(N, 0)); + LoadSDNode *LD2 = dyn_cast(getBuildPairElt(N, 1)); + if (!LD1 || !LD2 || !ISD::isNON_EXTLoad(LD1) || !LD1->hasOneUse()) + return SDValue(); + EVT LD1VT = LD1->getValueType(0); + const MachineFrameInfo *MFI = DAG.getMachineFunction().getFrameInfo(); + + if (ISD::isNON_EXTLoad(LD2) && + LD2->hasOneUse() && + // If both are volatile this would reduce the number of volatile loads. + // If one is volatile it might be ok, but play conservative and bail out. + !LD1->isVolatile() && + !LD2->isVolatile() && + TLI.isConsecutiveLoad(LD2, LD1, LD1VT.getSizeInBits()/8, 1, MFI)) { + unsigned Align = LD1->getAlignment(); + unsigned NewAlign = TLI.getTargetData()-> + getABITypeAlignment(VT.getTypeForEVT(*DAG.getContext())); + + if (NewAlign <= Align && + (!LegalOperations || TLI.isOperationLegal(ISD::LOAD, VT))) + return DAG.getLoad(VT, N->getDebugLoc(), LD1->getChain(), + LD1->getBasePtr(), LD1->getSrcValue(), + LD1->getSrcValueOffset(), false, Align); + } + + return SDValue(); +} + +SDValue DAGCombiner::visitBIT_CONVERT(SDNode *N) { + SDValue N0 = N->getOperand(0); + EVT VT = N->getValueType(0); + + // If the input is a BUILD_VECTOR with all constant elements, fold this now. + // Only do this before legalize, since afterward the target may be depending + // on the bitconvert. + // First check to see if this is all constant. + if (!LegalTypes && + N0.getOpcode() == ISD::BUILD_VECTOR && N0.getNode()->hasOneUse() && + VT.isVector()) { + bool isSimple = true; + for (unsigned i = 0, e = N0.getNumOperands(); i != e; ++i) + if (N0.getOperand(i).getOpcode() != ISD::UNDEF && + N0.getOperand(i).getOpcode() != ISD::Constant && + N0.getOperand(i).getOpcode() != ISD::ConstantFP) { + isSimple = false; + break; + } + + EVT DestEltVT = N->getValueType(0).getVectorElementType(); + assert(!DestEltVT.isVector() && + "Element type of vector ValueType must not be vector!"); + if (isSimple) + return ConstantFoldBIT_CONVERTofBUILD_VECTOR(N0.getNode(), DestEltVT); + } + + // If the input is a constant, let getNode fold it. + if (isa(N0) || isa(N0)) { + SDValue Res = DAG.getNode(ISD::BIT_CONVERT, N->getDebugLoc(), VT, N0); + if (Res.getNode() != N) { + if (!LegalOperations || + TLI.isOperationLegal(Res.getNode()->getOpcode(), VT)) + return Res; + + // Folding it resulted in an illegal node, and it's too late to + // do that. Clean up the old node and forego the transformation. + // Ideally this won't happen very often, because instcombine + // and the earlier dagcombine runs (where illegal nodes are + // permitted) should have folded most of them already. + DAG.DeleteNode(Res.getNode()); + } + } + + // (conv (conv x, t1), t2) -> (conv x, t2) + if (N0.getOpcode() == ISD::BIT_CONVERT) + return DAG.getNode(ISD::BIT_CONVERT, N->getDebugLoc(), VT, + N0.getOperand(0)); + + // fold (conv (load x)) -> (load (conv*)x) + // If the resultant load doesn't need a higher alignment than the original! + if (ISD::isNormalLoad(N0.getNode()) && N0.hasOneUse() && + // Do not change the width of a volatile load. + !cast(N0)->isVolatile() && + (!LegalOperations || TLI.isOperationLegal(ISD::LOAD, VT))) { + LoadSDNode *LN0 = cast(N0); + unsigned Align = TLI.getTargetData()-> + getABITypeAlignment(VT.getTypeForEVT(*DAG.getContext())); + unsigned OrigAlign = LN0->getAlignment(); + + if (Align <= OrigAlign) { + SDValue Load = DAG.getLoad(VT, N->getDebugLoc(), LN0->getChain(), + LN0->getBasePtr(), + LN0->getSrcValue(), LN0->getSrcValueOffset(), + LN0->isVolatile(), OrigAlign); + AddToWorkList(N); + CombineTo(N0.getNode(), + DAG.getNode(ISD::BIT_CONVERT, N0.getDebugLoc(), + N0.getValueType(), Load), + Load.getValue(1)); + return Load; + } + } + + // fold (bitconvert (fneg x)) -> (xor (bitconvert x), signbit) + // fold (bitconvert (fabs x)) -> (and (bitconvert x), (not signbit)) + // This often reduces constant pool loads. + if ((N0.getOpcode() == ISD::FNEG || N0.getOpcode() == ISD::FABS) && + N0.getNode()->hasOneUse() && VT.isInteger() && !VT.isVector()) { + SDValue NewConv = DAG.getNode(ISD::BIT_CONVERT, N0.getDebugLoc(), VT, + N0.getOperand(0)); + AddToWorkList(NewConv.getNode()); + + APInt SignBit = APInt::getSignBit(VT.getSizeInBits()); + if (N0.getOpcode() == ISD::FNEG) + return DAG.getNode(ISD::XOR, N->getDebugLoc(), VT, + NewConv, DAG.getConstant(SignBit, VT)); + assert(N0.getOpcode() == ISD::FABS); + return DAG.getNode(ISD::AND, N->getDebugLoc(), VT, + NewConv, DAG.getConstant(~SignBit, VT)); + } + + // fold (bitconvert (fcopysign cst, x)) -> + // (or (and (bitconvert x), sign), (and cst, (not sign))) + // Note that we don't handle (copysign x, cst) because this can always be + // folded to an fneg or fabs. + if (N0.getOpcode() == ISD::FCOPYSIGN && N0.getNode()->hasOneUse() && + isa(N0.getOperand(0)) && + VT.isInteger() && !VT.isVector()) { + unsigned OrigXWidth = N0.getOperand(1).getValueType().getSizeInBits(); + EVT IntXVT = EVT::getIntegerVT(*DAG.getContext(), OrigXWidth); + if (TLI.isTypeLegal(IntXVT) || !LegalTypes) { + SDValue X = DAG.getNode(ISD::BIT_CONVERT, N0.getDebugLoc(), + IntXVT, N0.getOperand(1)); + AddToWorkList(X.getNode()); + + // If X has a different width than the result/lhs, sext it or truncate it. + unsigned VTWidth = VT.getSizeInBits(); + if (OrigXWidth < VTWidth) { + X = DAG.getNode(ISD::SIGN_EXTEND, N->getDebugLoc(), VT, X); + AddToWorkList(X.getNode()); + } else if (OrigXWidth > VTWidth) { + // To get the sign bit in the right place, we have to shift it right + // before truncating. + X = DAG.getNode(ISD::SRL, X.getDebugLoc(), + X.getValueType(), X, + DAG.getConstant(OrigXWidth-VTWidth, X.getValueType())); + AddToWorkList(X.getNode()); + X = DAG.getNode(ISD::TRUNCATE, X.getDebugLoc(), VT, X); + AddToWorkList(X.getNode()); + } + + APInt SignBit = APInt::getSignBit(VT.getSizeInBits()); + X = DAG.getNode(ISD::AND, X.getDebugLoc(), VT, + X, DAG.getConstant(SignBit, VT)); + AddToWorkList(X.getNode()); + + SDValue Cst = DAG.getNode(ISD::BIT_CONVERT, N0.getDebugLoc(), + VT, N0.getOperand(0)); + Cst = DAG.getNode(ISD::AND, Cst.getDebugLoc(), VT, + Cst, DAG.getConstant(~SignBit, VT)); + AddToWorkList(Cst.getNode()); + + return DAG.getNode(ISD::OR, N->getDebugLoc(), VT, X, Cst); + } + } + + // bitconvert(build_pair(ld, ld)) -> ld iff load locations are consecutive. + if (N0.getOpcode() == ISD::BUILD_PAIR) { + SDValue CombineLD = CombineConsecutiveLoads(N0.getNode(), VT); + if (CombineLD.getNode()) + return CombineLD; + } + + return SDValue(); +} + +SDValue DAGCombiner::visitBUILD_PAIR(SDNode *N) { + EVT VT = N->getValueType(0); + return CombineConsecutiveLoads(N, VT); +} + +/// ConstantFoldBIT_CONVERTofBUILD_VECTOR - We know that BV is a build_vector +/// node with Constant, ConstantFP or Undef operands. DstEltVT indicates the +/// destination element value type. +SDValue DAGCombiner:: +ConstantFoldBIT_CONVERTofBUILD_VECTOR(SDNode *BV, EVT DstEltVT) { + EVT SrcEltVT = BV->getValueType(0).getVectorElementType(); + + // If this is already the right type, we're done. + if (SrcEltVT == DstEltVT) return SDValue(BV, 0); + + unsigned SrcBitSize = SrcEltVT.getSizeInBits(); + unsigned DstBitSize = DstEltVT.getSizeInBits(); + + // If this is a conversion of N elements of one type to N elements of another + // type, convert each element. This handles FP<->INT cases. + if (SrcBitSize == DstBitSize) { + SmallVector Ops; + for (unsigned i = 0, e = BV->getNumOperands(); i != e; ++i) { + SDValue Op = BV->getOperand(i); + // If the vector element type is not legal, the BUILD_VECTOR operands + // are promoted and implicitly truncated. Make that explicit here. + if (Op.getValueType() != SrcEltVT) + Op = DAG.getNode(ISD::TRUNCATE, BV->getDebugLoc(), SrcEltVT, Op); + Ops.push_back(DAG.getNode(ISD::BIT_CONVERT, BV->getDebugLoc(), + DstEltVT, Op)); + AddToWorkList(Ops.back().getNode()); + } + EVT VT = EVT::getVectorVT(*DAG.getContext(), DstEltVT, + BV->getValueType(0).getVectorNumElements()); + return DAG.getNode(ISD::BUILD_VECTOR, BV->getDebugLoc(), VT, + &Ops[0], Ops.size()); + } + + // Otherwise, we're growing or shrinking the elements. To avoid having to + // handle annoying details of growing/shrinking FP values, we convert them to + // int first. + if (SrcEltVT.isFloatingPoint()) { + // Convert the input float vector to a int vector where the elements are the + // same sizes. + assert((SrcEltVT == MVT::f32 || SrcEltVT == MVT::f64) && "Unknown FP VT!"); + EVT IntVT = EVT::getIntegerVT(*DAG.getContext(), SrcEltVT.getSizeInBits()); + BV = ConstantFoldBIT_CONVERTofBUILD_VECTOR(BV, IntVT).getNode(); + SrcEltVT = IntVT; + } + + // Now we know the input is an integer vector. If the output is a FP type, + // convert to integer first, then to FP of the right size. + if (DstEltVT.isFloatingPoint()) { + assert((DstEltVT == MVT::f32 || DstEltVT == MVT::f64) && "Unknown FP VT!"); + EVT TmpVT = EVT::getIntegerVT(*DAG.getContext(), DstEltVT.getSizeInBits()); + SDNode *Tmp = ConstantFoldBIT_CONVERTofBUILD_VECTOR(BV, TmpVT).getNode(); + + // Next, convert to FP elements of the same size. + return ConstantFoldBIT_CONVERTofBUILD_VECTOR(Tmp, DstEltVT); + } + + // Okay, we know the src/dst types are both integers of differing types. + // Handling growing first. + assert(SrcEltVT.isInteger() && DstEltVT.isInteger()); + if (SrcBitSize < DstBitSize) { + unsigned NumInputsPerOutput = DstBitSize/SrcBitSize; + + SmallVector Ops; + for (unsigned i = 0, e = BV->getNumOperands(); i != e; + i += NumInputsPerOutput) { + bool isLE = TLI.isLittleEndian(); + APInt NewBits = APInt(DstBitSize, 0); + bool EltIsUndef = true; + for (unsigned j = 0; j != NumInputsPerOutput; ++j) { + // Shift the previously computed bits over. + NewBits <<= SrcBitSize; + SDValue Op = BV->getOperand(i+ (isLE ? (NumInputsPerOutput-j-1) : j)); + if (Op.getOpcode() == ISD::UNDEF) continue; + EltIsUndef = false; + + NewBits |= (APInt(cast(Op)->getAPIntValue()). + zextOrTrunc(SrcBitSize).zext(DstBitSize)); + } + + if (EltIsUndef) + Ops.push_back(DAG.getUNDEF(DstEltVT)); + else + Ops.push_back(DAG.getConstant(NewBits, DstEltVT)); + } + + EVT VT = EVT::getVectorVT(*DAG.getContext(), DstEltVT, Ops.size()); + return DAG.getNode(ISD::BUILD_VECTOR, BV->getDebugLoc(), VT, + &Ops[0], Ops.size()); + } + + // Finally, this must be the case where we are shrinking elements: each input + // turns into multiple outputs. + bool isS2V = ISD::isScalarToVector(BV); + unsigned NumOutputsPerInput = SrcBitSize/DstBitSize; + EVT VT = EVT::getVectorVT(*DAG.getContext(), DstEltVT, + NumOutputsPerInput*BV->getNumOperands()); + SmallVector Ops; + + for (unsigned i = 0, e = BV->getNumOperands(); i != e; ++i) { + if (BV->getOperand(i).getOpcode() == ISD::UNDEF) { + for (unsigned j = 0; j != NumOutputsPerInput; ++j) + Ops.push_back(DAG.getUNDEF(DstEltVT)); + continue; + } + + APInt OpVal = APInt(cast(BV->getOperand(i))-> + getAPIntValue()).zextOrTrunc(SrcBitSize); + + for (unsigned j = 0; j != NumOutputsPerInput; ++j) { + APInt ThisVal = APInt(OpVal).trunc(DstBitSize); + Ops.push_back(DAG.getConstant(ThisVal, DstEltVT)); + if (isS2V && i == 0 && j == 0 && APInt(ThisVal).zext(SrcBitSize) == OpVal) + // Simply turn this into a SCALAR_TO_VECTOR of the new type. + return DAG.getNode(ISD::SCALAR_TO_VECTOR, BV->getDebugLoc(), VT, + Ops[0]); + OpVal = OpVal.lshr(DstBitSize); + } + + // For big endian targets, swap the order of the pieces of each element. + if (TLI.isBigEndian()) + std::reverse(Ops.end()-NumOutputsPerInput, Ops.end()); + } + + return DAG.getNode(ISD::BUILD_VECTOR, BV->getDebugLoc(), VT, + &Ops[0], Ops.size()); +} + +SDValue DAGCombiner::visitFADD(SDNode *N) { + SDValue N0 = N->getOperand(0); + SDValue N1 = N->getOperand(1); + ConstantFPSDNode *N0CFP = dyn_cast(N0); + ConstantFPSDNode *N1CFP = dyn_cast(N1); + EVT VT = N->getValueType(0); + + // fold vector ops + if (VT.isVector()) { + SDValue FoldedVOp = SimplifyVBinOp(N); + if (FoldedVOp.getNode()) return FoldedVOp; + } + + // fold (fadd c1, c2) -> (fadd c1, c2) + if (N0CFP && N1CFP && VT != MVT::ppcf128) + return DAG.getNode(ISD::FADD, N->getDebugLoc(), VT, N0, N1); + // canonicalize constant to RHS + if (N0CFP && !N1CFP) + return DAG.getNode(ISD::FADD, N->getDebugLoc(), VT, N1, N0); + // fold (fadd A, 0) -> A + if (UnsafeFPMath && N1CFP && N1CFP->getValueAPF().isZero()) + return N0; + // fold (fadd A, (fneg B)) -> (fsub A, B) + if (isNegatibleForFree(N1, LegalOperations) == 2) + return DAG.getNode(ISD::FSUB, N->getDebugLoc(), VT, N0, + GetNegatedExpression(N1, DAG, LegalOperations)); + // fold (fadd (fneg A), B) -> (fsub B, A) + if (isNegatibleForFree(N0, LegalOperations) == 2) + return DAG.getNode(ISD::FSUB, N->getDebugLoc(), VT, N1, + GetNegatedExpression(N0, DAG, LegalOperations)); + + // If allowed, fold (fadd (fadd x, c1), c2) -> (fadd x, (fadd c1, c2)) + if (UnsafeFPMath && N1CFP && N0.getOpcode() == ISD::FADD && + N0.getNode()->hasOneUse() && isa(N0.getOperand(1))) + return DAG.getNode(ISD::FADD, N->getDebugLoc(), VT, N0.getOperand(0), + DAG.getNode(ISD::FADD, N->getDebugLoc(), VT, + N0.getOperand(1), N1)); + + return SDValue(); +} + +SDValue DAGCombiner::visitFSUB(SDNode *N) { + SDValue N0 = N->getOperand(0); + SDValue N1 = N->getOperand(1); + ConstantFPSDNode *N0CFP = dyn_cast(N0); + ConstantFPSDNode *N1CFP = dyn_cast(N1); + EVT VT = N->getValueType(0); + + // fold vector ops + if (VT.isVector()) { + SDValue FoldedVOp = SimplifyVBinOp(N); + if (FoldedVOp.getNode()) return FoldedVOp; + } + + // fold (fsub c1, c2) -> c1-c2 + if (N0CFP && N1CFP && VT != MVT::ppcf128) + return DAG.getNode(ISD::FSUB, N->getDebugLoc(), VT, N0, N1); + // fold (fsub A, 0) -> A + if (UnsafeFPMath && N1CFP && N1CFP->getValueAPF().isZero()) + return N0; + // fold (fsub 0, B) -> -B + if (UnsafeFPMath && N0CFP && N0CFP->getValueAPF().isZero()) { + if (isNegatibleForFree(N1, LegalOperations)) + return GetNegatedExpression(N1, DAG, LegalOperations); + if (!LegalOperations || TLI.isOperationLegal(ISD::FNEG, VT)) + return DAG.getNode(ISD::FNEG, N->getDebugLoc(), VT, N1); + } + // fold (fsub A, (fneg B)) -> (fadd A, B) + if (isNegatibleForFree(N1, LegalOperations)) + return DAG.getNode(ISD::FADD, N->getDebugLoc(), VT, N0, + GetNegatedExpression(N1, DAG, LegalOperations)); + + return SDValue(); +} + +SDValue DAGCombiner::visitFMUL(SDNode *N) { + SDValue N0 = N->getOperand(0); + SDValue N1 = N->getOperand(1); + ConstantFPSDNode *N0CFP = dyn_cast(N0); + ConstantFPSDNode *N1CFP = dyn_cast(N1); + EVT VT = N->getValueType(0); + + // fold vector ops + if (VT.isVector()) { + SDValue FoldedVOp = SimplifyVBinOp(N); + if (FoldedVOp.getNode()) return FoldedVOp; + } + + // fold (fmul c1, c2) -> c1*c2 + if (N0CFP && N1CFP && VT != MVT::ppcf128) + return DAG.getNode(ISD::FMUL, N->getDebugLoc(), VT, N0, N1); + // canonicalize constant to RHS + if (N0CFP && !N1CFP) + return DAG.getNode(ISD::FMUL, N->getDebugLoc(), VT, N1, N0); + // fold (fmul A, 0) -> 0 + if (UnsafeFPMath && N1CFP && N1CFP->getValueAPF().isZero()) + return N1; + // fold (fmul A, 0) -> 0, vector edition. + if (UnsafeFPMath && ISD::isBuildVectorAllZeros(N1.getNode())) + return N1; + // fold (fmul X, 2.0) -> (fadd X, X) + if (N1CFP && N1CFP->isExactlyValue(+2.0)) + return DAG.getNode(ISD::FADD, N->getDebugLoc(), VT, N0, N0); + // fold (fmul X, -1.0) -> (fneg X) + if (N1CFP && N1CFP->isExactlyValue(-1.0)) + if (!LegalOperations || TLI.isOperationLegal(ISD::FNEG, VT)) + return DAG.getNode(ISD::FNEG, N->getDebugLoc(), VT, N0); + + // fold (fmul (fneg X), (fneg Y)) -> (fmul X, Y) + if (char LHSNeg = isNegatibleForFree(N0, LegalOperations)) { + if (char RHSNeg = isNegatibleForFree(N1, LegalOperations)) { + // Both can be negated for free, check to see if at least one is cheaper + // negated. + if (LHSNeg == 2 || RHSNeg == 2) + return DAG.getNode(ISD::FMUL, N->getDebugLoc(), VT, + GetNegatedExpression(N0, DAG, LegalOperations), + GetNegatedExpression(N1, DAG, LegalOperations)); + } + } + + // If allowed, fold (fmul (fmul x, c1), c2) -> (fmul x, (fmul c1, c2)) + if (UnsafeFPMath && N1CFP && N0.getOpcode() == ISD::FMUL && + N0.getNode()->hasOneUse() && isa(N0.getOperand(1))) + return DAG.getNode(ISD::FMUL, N->getDebugLoc(), VT, N0.getOperand(0), + DAG.getNode(ISD::FMUL, N->getDebugLoc(), VT, + N0.getOperand(1), N1)); + + return SDValue(); +} + +SDValue DAGCombiner::visitFDIV(SDNode *N) { + SDValue N0 = N->getOperand(0); + SDValue N1 = N->getOperand(1); + ConstantFPSDNode *N0CFP = dyn_cast(N0); + ConstantFPSDNode *N1CFP = dyn_cast(N1); + EVT VT = N->getValueType(0); + + // fold vector ops + if (VT.isVector()) { + SDValue FoldedVOp = SimplifyVBinOp(N); + if (FoldedVOp.getNode()) return FoldedVOp; + } + + // fold (fdiv c1, c2) -> c1/c2 + if (N0CFP && N1CFP && VT != MVT::ppcf128) + return DAG.getNode(ISD::FDIV, N->getDebugLoc(), VT, N0, N1); + + + // (fdiv (fneg X), (fneg Y)) -> (fdiv X, Y) + if (char LHSNeg = isNegatibleForFree(N0, LegalOperations)) { + if (char RHSNeg = isNegatibleForFree(N1, LegalOperations)) { + // Both can be negated for free, check to see if at least one is cheaper + // negated. + if (LHSNeg == 2 || RHSNeg == 2) + return DAG.getNode(ISD::FDIV, N->getDebugLoc(), VT, + GetNegatedExpression(N0, DAG, LegalOperations), + GetNegatedExpression(N1, DAG, LegalOperations)); + } + } + + return SDValue(); +} + +SDValue DAGCombiner::visitFREM(SDNode *N) { + SDValue N0 = N->getOperand(0); + SDValue N1 = N->getOperand(1); + ConstantFPSDNode *N0CFP = dyn_cast(N0); + ConstantFPSDNode *N1CFP = dyn_cast(N1); + EVT VT = N->getValueType(0); + + // fold (frem c1, c2) -> fmod(c1,c2) + if (N0CFP && N1CFP && VT != MVT::ppcf128) + return DAG.getNode(ISD::FREM, N->getDebugLoc(), VT, N0, N1); + + return SDValue(); +} + +SDValue DAGCombiner::visitFCOPYSIGN(SDNode *N) { + SDValue N0 = N->getOperand(0); + SDValue N1 = N->getOperand(1); + ConstantFPSDNode *N0CFP = dyn_cast(N0); + ConstantFPSDNode *N1CFP = dyn_cast(N1); + EVT VT = N->getValueType(0); + + if (N0CFP && N1CFP && VT != MVT::ppcf128) // Constant fold + return DAG.getNode(ISD::FCOPYSIGN, N->getDebugLoc(), VT, N0, N1); + + if (N1CFP) { + const APFloat& V = N1CFP->getValueAPF(); + // copysign(x, c1) -> fabs(x) iff ispos(c1) + // copysign(x, c1) -> fneg(fabs(x)) iff isneg(c1) + if (!V.isNegative()) { + if (!LegalOperations || TLI.isOperationLegal(ISD::FABS, VT)) + return DAG.getNode(ISD::FABS, N->getDebugLoc(), VT, N0); + } else { + if (!LegalOperations || TLI.isOperationLegal(ISD::FNEG, VT)) + return DAG.getNode(ISD::FNEG, N->getDebugLoc(), VT, + DAG.getNode(ISD::FABS, N0.getDebugLoc(), VT, N0)); + } + } + + // copysign(fabs(x), y) -> copysign(x, y) + // copysign(fneg(x), y) -> copysign(x, y) + // copysign(copysign(x,z), y) -> copysign(x, y) + if (N0.getOpcode() == ISD::FABS || N0.getOpcode() == ISD::FNEG || + N0.getOpcode() == ISD::FCOPYSIGN) + return DAG.getNode(ISD::FCOPYSIGN, N->getDebugLoc(), VT, + N0.getOperand(0), N1); + + // copysign(x, abs(y)) -> abs(x) + if (N1.getOpcode() == ISD::FABS) + return DAG.getNode(ISD::FABS, N->getDebugLoc(), VT, N0); + + // copysign(x, copysign(y,z)) -> copysign(x, z) + if (N1.getOpcode() == ISD::FCOPYSIGN) + return DAG.getNode(ISD::FCOPYSIGN, N->getDebugLoc(), VT, + N0, N1.getOperand(1)); + + // copysign(x, fp_extend(y)) -> copysign(x, y) + // copysign(x, fp_round(y)) -> copysign(x, y) + if (N1.getOpcode() == ISD::FP_EXTEND || N1.getOpcode() == ISD::FP_ROUND) + return DAG.getNode(ISD::FCOPYSIGN, N->getDebugLoc(), VT, + N0, N1.getOperand(0)); + + return SDValue(); +} + +SDValue DAGCombiner::visitSINT_TO_FP(SDNode *N) { + SDValue N0 = N->getOperand(0); + ConstantSDNode *N0C = dyn_cast(N0); + EVT VT = N->getValueType(0); + EVT OpVT = N0.getValueType(); + + // fold (sint_to_fp c1) -> c1fp + if (N0C && OpVT != MVT::ppcf128) + return DAG.getNode(ISD::SINT_TO_FP, N->getDebugLoc(), VT, N0); + + // If the input is a legal type, and SINT_TO_FP is not legal on this target, + // but UINT_TO_FP is legal on this target, try to convert. + if (!TLI.isOperationLegalOrCustom(ISD::SINT_TO_FP, OpVT) && + TLI.isOperationLegalOrCustom(ISD::UINT_TO_FP, OpVT)) { + // If the sign bit is known to be zero, we can change this to UINT_TO_FP. + if (DAG.SignBitIsZero(N0)) + return DAG.getNode(ISD::UINT_TO_FP, N->getDebugLoc(), VT, N0); + } + + return SDValue(); +} + +SDValue DAGCombiner::visitUINT_TO_FP(SDNode *N) { + SDValue N0 = N->getOperand(0); + ConstantSDNode *N0C = dyn_cast(N0); + EVT VT = N->getValueType(0); + EVT OpVT = N0.getValueType(); + + // fold (uint_to_fp c1) -> c1fp + if (N0C && OpVT != MVT::ppcf128) + return DAG.getNode(ISD::UINT_TO_FP, N->getDebugLoc(), VT, N0); + + // If the input is a legal type, and UINT_TO_FP is not legal on this target, + // but SINT_TO_FP is legal on this target, try to convert. + if (!TLI.isOperationLegalOrCustom(ISD::UINT_TO_FP, OpVT) && + TLI.isOperationLegalOrCustom(ISD::SINT_TO_FP, OpVT)) { + // If the sign bit is known to be zero, we can change this to SINT_TO_FP. + if (DAG.SignBitIsZero(N0)) + return DAG.getNode(ISD::SINT_TO_FP, N->getDebugLoc(), VT, N0); + } + + return SDValue(); +} + +SDValue DAGCombiner::visitFP_TO_SINT(SDNode *N) { + SDValue N0 = N->getOperand(0); + ConstantFPSDNode *N0CFP = dyn_cast(N0); + EVT VT = N->getValueType(0); + + // fold (fp_to_sint c1fp) -> c1 + if (N0CFP) + return DAG.getNode(ISD::FP_TO_SINT, N->getDebugLoc(), VT, N0); + + return SDValue(); +} + +SDValue DAGCombiner::visitFP_TO_UINT(SDNode *N) { + SDValue N0 = N->getOperand(0); + ConstantFPSDNode *N0CFP = dyn_cast(N0); + EVT VT = N->getValueType(0); + + // fold (fp_to_uint c1fp) -> c1 + if (N0CFP && VT != MVT::ppcf128) + return DAG.getNode(ISD::FP_TO_UINT, N->getDebugLoc(), VT, N0); + + return SDValue(); +} + +SDValue DAGCombiner::visitFP_ROUND(SDNode *N) { + SDValue N0 = N->getOperand(0); + SDValue N1 = N->getOperand(1); + ConstantFPSDNode *N0CFP = dyn_cast(N0); + EVT VT = N->getValueType(0); + + // fold (fp_round c1fp) -> c1fp + if (N0CFP && N0.getValueType() != MVT::ppcf128) + return DAG.getNode(ISD::FP_ROUND, N->getDebugLoc(), VT, N0, N1); + + // fold (fp_round (fp_extend x)) -> x + if (N0.getOpcode() == ISD::FP_EXTEND && VT == N0.getOperand(0).getValueType()) + return N0.getOperand(0); + + // fold (fp_round (fp_round x)) -> (fp_round x) + if (N0.getOpcode() == ISD::FP_ROUND) { + // This is a value preserving truncation if both round's are. + bool IsTrunc = N->getConstantOperandVal(1) == 1 && + N0.getNode()->getConstantOperandVal(1) == 1; + return DAG.getNode(ISD::FP_ROUND, N->getDebugLoc(), VT, N0.getOperand(0), + DAG.getIntPtrConstant(IsTrunc)); + } + + // fold (fp_round (copysign X, Y)) -> (copysign (fp_round X), Y) + if (N0.getOpcode() == ISD::FCOPYSIGN && N0.getNode()->hasOneUse()) { + SDValue Tmp = DAG.getNode(ISD::FP_ROUND, N0.getDebugLoc(), VT, + N0.getOperand(0), N1); + AddToWorkList(Tmp.getNode()); + return DAG.getNode(ISD::FCOPYSIGN, N->getDebugLoc(), VT, + Tmp, N0.getOperand(1)); + } + + return SDValue(); +} + +SDValue DAGCombiner::visitFP_ROUND_INREG(SDNode *N) { + SDValue N0 = N->getOperand(0); + EVT VT = N->getValueType(0); + EVT EVT = cast(N->getOperand(1))->getVT(); + ConstantFPSDNode *N0CFP = dyn_cast(N0); + + // fold (fp_round_inreg c1fp) -> c1fp + if (N0CFP && (TLI.isTypeLegal(EVT) || !LegalTypes)) { + SDValue Round = DAG.getConstantFP(*N0CFP->getConstantFPValue(), EVT); + return DAG.getNode(ISD::FP_EXTEND, N->getDebugLoc(), VT, Round); + } + + return SDValue(); +} + +SDValue DAGCombiner::visitFP_EXTEND(SDNode *N) { + SDValue N0 = N->getOperand(0); + ConstantFPSDNode *N0CFP = dyn_cast(N0); + EVT VT = N->getValueType(0); + + // If this is fp_round(fpextend), don't fold it, allow ourselves to be folded. + if (N->hasOneUse() && + N->use_begin()->getOpcode() == ISD::FP_ROUND) + return SDValue(); + + // fold (fp_extend c1fp) -> c1fp + if (N0CFP && VT != MVT::ppcf128) + return DAG.getNode(ISD::FP_EXTEND, N->getDebugLoc(), VT, N0); + + // Turn fp_extend(fp_round(X, 1)) -> x since the fp_round doesn't affect the + // value of X. + if (N0.getOpcode() == ISD::FP_ROUND + && N0.getNode()->getConstantOperandVal(1) == 1) { + SDValue In = N0.getOperand(0); + if (In.getValueType() == VT) return In; + if (VT.bitsLT(In.getValueType())) + return DAG.getNode(ISD::FP_ROUND, N->getDebugLoc(), VT, + In, N0.getOperand(1)); + return DAG.getNode(ISD::FP_EXTEND, N->getDebugLoc(), VT, In); + } + + // fold (fpext (load x)) -> (fpext (fptrunc (extload x))) + if (ISD::isNON_EXTLoad(N0.getNode()) && N0.hasOneUse() && + ((!LegalOperations && !cast(N0)->isVolatile()) || + TLI.isLoadExtLegal(ISD::EXTLOAD, N0.getValueType()))) { + LoadSDNode *LN0 = cast(N0); + SDValue ExtLoad = DAG.getExtLoad(ISD::EXTLOAD, N->getDebugLoc(), VT, + LN0->getChain(), + LN0->getBasePtr(), LN0->getSrcValue(), + LN0->getSrcValueOffset(), + N0.getValueType(), + LN0->isVolatile(), LN0->getAlignment()); + CombineTo(N, ExtLoad); + CombineTo(N0.getNode(), + DAG.getNode(ISD::FP_ROUND, N0.getDebugLoc(), + N0.getValueType(), ExtLoad, DAG.getIntPtrConstant(1)), + ExtLoad.getValue(1)); + return SDValue(N, 0); // Return N so it doesn't get rechecked! + } + + return SDValue(); +} + +SDValue DAGCombiner::visitFNEG(SDNode *N) { + SDValue N0 = N->getOperand(0); + EVT VT = N->getValueType(0); + + if (isNegatibleForFree(N0, LegalOperations)) + return GetNegatedExpression(N0, DAG, LegalOperations); + + // Transform fneg(bitconvert(x)) -> bitconvert(x^sign) to avoid loading + // constant pool values. + if (N0.getOpcode() == ISD::BIT_CONVERT && + !VT.isVector() && + N0.getNode()->hasOneUse() && + N0.getOperand(0).getValueType().isInteger()) { + SDValue Int = N0.getOperand(0); + EVT IntVT = Int.getValueType(); + if (IntVT.isInteger() && !IntVT.isVector()) { + Int = DAG.getNode(ISD::XOR, N0.getDebugLoc(), IntVT, Int, + DAG.getConstant(APInt::getSignBit(IntVT.getSizeInBits()), IntVT)); + AddToWorkList(Int.getNode()); + return DAG.getNode(ISD::BIT_CONVERT, N->getDebugLoc(), + VT, Int); + } + } + + return SDValue(); +} + +SDValue DAGCombiner::visitFABS(SDNode *N) { + SDValue N0 = N->getOperand(0); + ConstantFPSDNode *N0CFP = dyn_cast(N0); + EVT VT = N->getValueType(0); + + // fold (fabs c1) -> fabs(c1) + if (N0CFP && VT != MVT::ppcf128) + return DAG.getNode(ISD::FABS, N->getDebugLoc(), VT, N0); + // fold (fabs (fabs x)) -> (fabs x) + if (N0.getOpcode() == ISD::FABS) + return N->getOperand(0); + // fold (fabs (fneg x)) -> (fabs x) + // fold (fabs (fcopysign x, y)) -> (fabs x) + if (N0.getOpcode() == ISD::FNEG || N0.getOpcode() == ISD::FCOPYSIGN) + return DAG.getNode(ISD::FABS, N->getDebugLoc(), VT, N0.getOperand(0)); + + // Transform fabs(bitconvert(x)) -> bitconvert(x&~sign) to avoid loading + // constant pool values. + if (N0.getOpcode() == ISD::BIT_CONVERT && N0.getNode()->hasOneUse() && + N0.getOperand(0).getValueType().isInteger() && + !N0.getOperand(0).getValueType().isVector()) { + SDValue Int = N0.getOperand(0); + EVT IntVT = Int.getValueType(); + if (IntVT.isInteger() && !IntVT.isVector()) { + Int = DAG.getNode(ISD::AND, N0.getDebugLoc(), IntVT, Int, + DAG.getConstant(~APInt::getSignBit(IntVT.getSizeInBits()), IntVT)); + AddToWorkList(Int.getNode()); + return DAG.getNode(ISD::BIT_CONVERT, N->getDebugLoc(), + N->getValueType(0), Int); + } + } + + return SDValue(); +} + +SDValue DAGCombiner::visitBRCOND(SDNode *N) { + SDValue Chain = N->getOperand(0); + SDValue N1 = N->getOperand(1); + SDValue N2 = N->getOperand(2); + + // If N is a constant we could fold this into a fallthrough or unconditional + // branch. However that doesn't happen very often in normal code, because + // Instcombine/SimplifyCFG should have handled the available opportunities. + // If we did this folding here, it would be necessary to update the + // MachineBasicBlock CFG, which is awkward. + + // fold a brcond with a setcc condition into a BR_CC node if BR_CC is legal + // on the target. + if (N1.getOpcode() == ISD::SETCC && + TLI.isOperationLegalOrCustom(ISD::BR_CC, MVT::Other)) { + return DAG.getNode(ISD::BR_CC, N->getDebugLoc(), MVT::Other, + Chain, N1.getOperand(2), + N1.getOperand(0), N1.getOperand(1), N2); + } + + if (N1.hasOneUse() && N1.getOpcode() == ISD::SRL) { + // Match this pattern so that we can generate simpler code: + // + // %a = ... + // %b = and i32 %a, 2 + // %c = srl i32 %b, 1 + // brcond i32 %c ... + // + // into + // + // %a = ... + // %b = and %a, 2 + // %c = setcc eq %b, 0 + // brcond %c ... + // + // This applies only when the AND constant value has one bit set and the + // SRL constant is equal to the log2 of the AND constant. The back-end is + // smart enough to convert the result into a TEST/JMP sequence. + SDValue Op0 = N1.getOperand(0); + SDValue Op1 = N1.getOperand(1); + + if (Op0.getOpcode() == ISD::AND && + Op0.hasOneUse() && + Op1.getOpcode() == ISD::Constant) { + SDValue AndOp1 = Op0.getOperand(1); + + if (AndOp1.getOpcode() == ISD::Constant) { + const APInt &AndConst = cast(AndOp1)->getAPIntValue(); + + if (AndConst.isPowerOf2() && + cast(Op1)->getAPIntValue()==AndConst.logBase2()) { + SDValue SetCC = + DAG.getSetCC(N->getDebugLoc(), + TLI.getSetCCResultType(Op0.getValueType()), + Op0, DAG.getConstant(0, Op0.getValueType()), + ISD::SETNE); + + // Replace the uses of SRL with SETCC + DAG.ReplaceAllUsesOfValueWith(N1, SetCC); + removeFromWorkList(N1.getNode()); + DAG.DeleteNode(N1.getNode()); + return DAG.getNode(ISD::BRCOND, N->getDebugLoc(), + MVT::Other, Chain, SetCC, N2); + } + } + } + } + + return SDValue(); +} + +// Operand List for BR_CC: Chain, CondCC, CondLHS, CondRHS, DestBB. +// +SDValue DAGCombiner::visitBR_CC(SDNode *N) { + CondCodeSDNode *CC = cast(N->getOperand(1)); + SDValue CondLHS = N->getOperand(2), CondRHS = N->getOperand(3); + + // If N is a constant we could fold this into a fallthrough or unconditional + // branch. However that doesn't happen very often in normal code, because + // Instcombine/SimplifyCFG should have handled the available opportunities. + // If we did this folding here, it would be necessary to update the + // MachineBasicBlock CFG, which is awkward. + + // Use SimplifySetCC to simplify SETCC's. + SDValue Simp = SimplifySetCC(TLI.getSetCCResultType(CondLHS.getValueType()), + CondLHS, CondRHS, CC->get(), N->getDebugLoc(), + false); + if (Simp.getNode()) AddToWorkList(Simp.getNode()); + + // fold to a simpler setcc + if (Simp.getNode() && Simp.getOpcode() == ISD::SETCC) + return DAG.getNode(ISD::BR_CC, N->getDebugLoc(), MVT::Other, + N->getOperand(0), Simp.getOperand(2), + Simp.getOperand(0), Simp.getOperand(1), + N->getOperand(4)); + + return SDValue(); +} + +/// CombineToPreIndexedLoadStore - Try turning a load / store into a +/// pre-indexed load / store when the base pointer is an add or subtract +/// and it has other uses besides the load / store. After the +/// transformation, the new indexed load / store has effectively folded +/// the add / subtract in and all of its other uses are redirected to the +/// new load / store. +bool DAGCombiner::CombineToPreIndexedLoadStore(SDNode *N) { + if (!LegalOperations) + return false; + + bool isLoad = true; + SDValue Ptr; + EVT VT; + if (LoadSDNode *LD = dyn_cast(N)) { + if (LD->isIndexed()) + return false; + VT = LD->getMemoryVT(); + if (!TLI.isIndexedLoadLegal(ISD::PRE_INC, VT) && + !TLI.isIndexedLoadLegal(ISD::PRE_DEC, VT)) + return false; + Ptr = LD->getBasePtr(); + } else if (StoreSDNode *ST = dyn_cast(N)) { + if (ST->isIndexed()) + return false; + VT = ST->getMemoryVT(); + if (!TLI.isIndexedStoreLegal(ISD::PRE_INC, VT) && + !TLI.isIndexedStoreLegal(ISD::PRE_DEC, VT)) + return false; + Ptr = ST->getBasePtr(); + isLoad = false; + } else { + return false; + } + + // If the pointer is not an add/sub, or if it doesn't have multiple uses, bail + // out. There is no reason to make this a preinc/predec. + if ((Ptr.getOpcode() != ISD::ADD && Ptr.getOpcode() != ISD::SUB) || + Ptr.getNode()->hasOneUse()) + return false; + + // Ask the target to do addressing mode selection. + SDValue BasePtr; + SDValue Offset; + ISD::MemIndexedMode AM = ISD::UNINDEXED; + if (!TLI.getPreIndexedAddressParts(N, BasePtr, Offset, AM, DAG)) + return false; + // Don't create a indexed load / store with zero offset. + if (isa(Offset) && + cast(Offset)->isNullValue()) + return false; + + // Try turning it into a pre-indexed load / store except when: + // 1) The new base ptr is a frame index. + // 2) If N is a store and the new base ptr is either the same as or is a + // predecessor of the value being stored. + // 3) Another use of old base ptr is a predecessor of N. If ptr is folded + // that would create a cycle. + // 4) All uses are load / store ops that use it as old base ptr. + + // Check #1. Preinc'ing a frame index would require copying the stack pointer + // (plus the implicit offset) to a register to preinc anyway. + if (isa(BasePtr) || isa(BasePtr)) + return false; + + // Check #2. + if (!isLoad) { + SDValue Val = cast(N)->getValue(); + if (Val == BasePtr || BasePtr.getNode()->isPredecessorOf(Val.getNode())) + return false; + } + + // Now check for #3 and #4. + bool RealUse = false; + for (SDNode::use_iterator I = Ptr.getNode()->use_begin(), + E = Ptr.getNode()->use_end(); I != E; ++I) { + SDNode *Use = *I; + if (Use == N) + continue; + if (Use->isPredecessorOf(N)) + return false; + + if (!((Use->getOpcode() == ISD::LOAD && + cast(Use)->getBasePtr() == Ptr) || + (Use->getOpcode() == ISD::STORE && + cast(Use)->getBasePtr() == Ptr))) + RealUse = true; + } + + if (!RealUse) + return false; + + SDValue Result; + if (isLoad) + Result = DAG.getIndexedLoad(SDValue(N,0), N->getDebugLoc(), + BasePtr, Offset, AM); + else + Result = DAG.getIndexedStore(SDValue(N,0), N->getDebugLoc(), + BasePtr, Offset, AM); + ++PreIndexedNodes; + ++NodesCombined; + DEBUG(errs() << "\nReplacing.4 "; + N->dump(&DAG); + errs() << "\nWith: "; + Result.getNode()->dump(&DAG); + errs() << '\n'); + WorkListRemover DeadNodes(*this); + if (isLoad) { + DAG.ReplaceAllUsesOfValueWith(SDValue(N, 0), Result.getValue(0), + &DeadNodes); + DAG.ReplaceAllUsesOfValueWith(SDValue(N, 1), Result.getValue(2), + &DeadNodes); + } else { + DAG.ReplaceAllUsesOfValueWith(SDValue(N, 0), Result.getValue(1), + &DeadNodes); + } + + // Finally, since the node is now dead, remove it from the graph. + DAG.DeleteNode(N); + + // Replace the uses of Ptr with uses of the updated base value. + DAG.ReplaceAllUsesOfValueWith(Ptr, Result.getValue(isLoad ? 1 : 0), + &DeadNodes); + removeFromWorkList(Ptr.getNode()); + DAG.DeleteNode(Ptr.getNode()); + + return true; +} + +/// CombineToPostIndexedLoadStore - Try to combine a load / store with a +/// add / sub of the base pointer node into a post-indexed load / store. +/// The transformation folded the add / subtract into the new indexed +/// load / store effectively and all of its uses are redirected to the +/// new load / store. +bool DAGCombiner::CombineToPostIndexedLoadStore(SDNode *N) { + if (!LegalOperations) + return false; + + bool isLoad = true; + SDValue Ptr; + EVT VT; + if (LoadSDNode *LD = dyn_cast(N)) { + if (LD->isIndexed()) + return false; + VT = LD->getMemoryVT(); + if (!TLI.isIndexedLoadLegal(ISD::POST_INC, VT) && + !TLI.isIndexedLoadLegal(ISD::POST_DEC, VT)) + return false; + Ptr = LD->getBasePtr(); + } else if (StoreSDNode *ST = dyn_cast(N)) { + if (ST->isIndexed()) + return false; + VT = ST->getMemoryVT(); + if (!TLI.isIndexedStoreLegal(ISD::POST_INC, VT) && + !TLI.isIndexedStoreLegal(ISD::POST_DEC, VT)) + return false; + Ptr = ST->getBasePtr(); + isLoad = false; + } else { + return false; + } + + if (Ptr.getNode()->hasOneUse()) + return false; + + for (SDNode::use_iterator I = Ptr.getNode()->use_begin(), + E = Ptr.getNode()->use_end(); I != E; ++I) { + SDNode *Op = *I; + if (Op == N || + (Op->getOpcode() != ISD::ADD && Op->getOpcode() != ISD::SUB)) + continue; + + SDValue BasePtr; + SDValue Offset; + ISD::MemIndexedMode AM = ISD::UNINDEXED; + if (TLI.getPostIndexedAddressParts(N, Op, BasePtr, Offset, AM, DAG)) { + if (Ptr == Offset && Op->getOpcode() == ISD::ADD) + std::swap(BasePtr, Offset); + if (Ptr != BasePtr) + continue; + // Don't create a indexed load / store with zero offset. + if (isa(Offset) && + cast(Offset)->isNullValue()) + continue; + + // Try turning it into a post-indexed load / store except when + // 1) All uses are load / store ops that use it as base ptr. + // 2) Op must be independent of N, i.e. Op is neither a predecessor + // nor a successor of N. Otherwise, if Op is folded that would + // create a cycle. + + if (isa(BasePtr) || isa(BasePtr)) + continue; + + // Check for #1. + bool TryNext = false; + for (SDNode::use_iterator II = BasePtr.getNode()->use_begin(), + EE = BasePtr.getNode()->use_end(); II != EE; ++II) { + SDNode *Use = *II; + if (Use == Ptr.getNode()) + continue; + + // If all the uses are load / store addresses, then don't do the + // transformation. + if (Use->getOpcode() == ISD::ADD || Use->getOpcode() == ISD::SUB){ + bool RealUse = false; + for (SDNode::use_iterator III = Use->use_begin(), + EEE = Use->use_end(); III != EEE; ++III) { + SDNode *UseUse = *III; + if (!((UseUse->getOpcode() == ISD::LOAD && + cast(UseUse)->getBasePtr().getNode() == Use) || + (UseUse->getOpcode() == ISD::STORE && + cast(UseUse)->getBasePtr().getNode() == Use))) + RealUse = true; + } + + if (!RealUse) { + TryNext = true; + break; + } + } + } + + if (TryNext) + continue; + + // Check for #2 + if (!Op->isPredecessorOf(N) && !N->isPredecessorOf(Op)) { + SDValue Result = isLoad + ? DAG.getIndexedLoad(SDValue(N,0), N->getDebugLoc(), + BasePtr, Offset, AM) + : DAG.getIndexedStore(SDValue(N,0), N->getDebugLoc(), + BasePtr, Offset, AM); + ++PostIndexedNodes; + ++NodesCombined; + DEBUG(errs() << "\nReplacing.5 "; + N->dump(&DAG); + errs() << "\nWith: "; + Result.getNode()->dump(&DAG); + errs() << '\n'); + WorkListRemover DeadNodes(*this); + if (isLoad) { + DAG.ReplaceAllUsesOfValueWith(SDValue(N, 0), Result.getValue(0), + &DeadNodes); + DAG.ReplaceAllUsesOfValueWith(SDValue(N, 1), Result.getValue(2), + &DeadNodes); + } else { + DAG.ReplaceAllUsesOfValueWith(SDValue(N, 0), Result.getValue(1), + &DeadNodes); + } + + // Finally, since the node is now dead, remove it from the graph. + DAG.DeleteNode(N); + + // Replace the uses of Use with uses of the updated base value. + DAG.ReplaceAllUsesOfValueWith(SDValue(Op, 0), + Result.getValue(isLoad ? 1 : 0), + &DeadNodes); + removeFromWorkList(Op); + DAG.DeleteNode(Op); + return true; + } + } + } + + return false; +} + +/// InferAlignment - If we can infer some alignment information from this +/// pointer, return it. +static unsigned InferAlignment(SDValue Ptr, SelectionDAG &DAG) { + // If this is a direct reference to a stack slot, use information about the + // stack slot's alignment. + int FrameIdx = 1 << 31; + int64_t FrameOffset = 0; + if (FrameIndexSDNode *FI = dyn_cast(Ptr)) { + FrameIdx = FI->getIndex(); + } else if (Ptr.getOpcode() == ISD::ADD && + isa(Ptr.getOperand(1)) && + isa(Ptr.getOperand(0))) { + FrameIdx = cast(Ptr.getOperand(0))->getIndex(); + FrameOffset = Ptr.getConstantOperandVal(1); + } + + if (FrameIdx != (1 << 31)) { + // FIXME: Handle FI+CST. + const MachineFrameInfo &MFI = *DAG.getMachineFunction().getFrameInfo(); + if (MFI.isFixedObjectIndex(FrameIdx)) { + int64_t ObjectOffset = MFI.getObjectOffset(FrameIdx) + FrameOffset; + + // The alignment of the frame index can be determined from its offset from + // the incoming frame position. If the frame object is at offset 32 and + // the stack is guaranteed to be 16-byte aligned, then we know that the + // object is 16-byte aligned. + unsigned StackAlign = DAG.getTarget().getFrameInfo()->getStackAlignment(); + unsigned Align = MinAlign(ObjectOffset, StackAlign); + + // Finally, the frame object itself may have a known alignment. Factor + // the alignment + offset into a new alignment. For example, if we know + // the FI is 8 byte aligned, but the pointer is 4 off, we really have a + // 4-byte alignment of the resultant pointer. Likewise align 4 + 4-byte + // offset = 4-byte alignment, align 4 + 1-byte offset = align 1, etc. + unsigned FIInfoAlign = MinAlign(MFI.getObjectAlignment(FrameIdx), + FrameOffset); + return std::max(Align, FIInfoAlign); + } + } + + return 0; +} + +SDValue DAGCombiner::visitLOAD(SDNode *N) { + LoadSDNode *LD = cast(N); + SDValue Chain = LD->getChain(); + SDValue Ptr = LD->getBasePtr(); + + // Try to infer better alignment information than the load already has. + if (OptLevel != CodeGenOpt::None && LD->isUnindexed()) { + if (unsigned Align = InferAlignment(Ptr, DAG)) { + if (Align > LD->getAlignment()) + return DAG.getExtLoad(LD->getExtensionType(), N->getDebugLoc(), + LD->getValueType(0), + Chain, Ptr, LD->getSrcValue(), + LD->getSrcValueOffset(), LD->getMemoryVT(), + LD->isVolatile(), Align); + } + } + + // If load is not volatile and there are no uses of the loaded value (and + // the updated indexed value in case of indexed loads), change uses of the + // chain value into uses of the chain input (i.e. delete the dead load). + if (!LD->isVolatile()) { + if (N->getValueType(1) == MVT::Other) { + // Unindexed loads. + if (N->hasNUsesOfValue(0, 0)) { + // It's not safe to use the two value CombineTo variant here. e.g. + // v1, chain2 = load chain1, loc + // v2, chain3 = load chain2, loc + // v3 = add v2, c + // Now we replace use of chain2 with chain1. This makes the second load + // isomorphic to the one we are deleting, and thus makes this load live. + DEBUG(errs() << "\nReplacing.6 "; + N->dump(&DAG); + errs() << "\nWith chain: "; + Chain.getNode()->dump(&DAG); + errs() << "\n"); + WorkListRemover DeadNodes(*this); + DAG.ReplaceAllUsesOfValueWith(SDValue(N, 1), Chain, &DeadNodes); + + if (N->use_empty()) { + removeFromWorkList(N); + DAG.DeleteNode(N); + } + + return SDValue(N, 0); // Return N so it doesn't get rechecked! + } + } else { + // Indexed loads. + assert(N->getValueType(2) == MVT::Other && "Malformed indexed loads?"); + if (N->hasNUsesOfValue(0, 0) && N->hasNUsesOfValue(0, 1)) { + SDValue Undef = DAG.getUNDEF(N->getValueType(0)); + DEBUG(errs() << "\nReplacing.6 "; + N->dump(&DAG); + errs() << "\nWith: "; + Undef.getNode()->dump(&DAG); + errs() << " and 2 other values\n"); + WorkListRemover DeadNodes(*this); + DAG.ReplaceAllUsesOfValueWith(SDValue(N, 0), Undef, &DeadNodes); + DAG.ReplaceAllUsesOfValueWith(SDValue(N, 1), + DAG.getUNDEF(N->getValueType(1)), + &DeadNodes); + DAG.ReplaceAllUsesOfValueWith(SDValue(N, 2), Chain, &DeadNodes); + removeFromWorkList(N); + DAG.DeleteNode(N); + return SDValue(N, 0); // Return N so it doesn't get rechecked! + } + } + } + + // If this load is directly stored, replace the load value with the stored + // value. + // TODO: Handle store large -> read small portion. + // TODO: Handle TRUNCSTORE/LOADEXT + if (LD->getExtensionType() == ISD::NON_EXTLOAD && + !LD->isVolatile()) { + if (ISD::isNON_TRUNCStore(Chain.getNode())) { + StoreSDNode *PrevST = cast(Chain); + if (PrevST->getBasePtr() == Ptr && + PrevST->getValue().getValueType() == N->getValueType(0)) + return CombineTo(N, Chain.getOperand(1), Chain); + } + } + + if (CombinerAA) { + // Walk up chain skipping non-aliasing memory nodes. + SDValue BetterChain = FindBetterChain(N, Chain); + + // If there is a better chain. + if (Chain != BetterChain) { + SDValue ReplLoad; + + // Replace the chain to void dependency. + if (LD->getExtensionType() == ISD::NON_EXTLOAD) { + ReplLoad = DAG.getLoad(N->getValueType(0), LD->getDebugLoc(), + BetterChain, Ptr, + LD->getSrcValue(), LD->getSrcValueOffset(), + LD->isVolatile(), LD->getAlignment()); + } else { + ReplLoad = DAG.getExtLoad(LD->getExtensionType(), LD->getDebugLoc(), + LD->getValueType(0), + BetterChain, Ptr, LD->getSrcValue(), + LD->getSrcValueOffset(), + LD->getMemoryVT(), + LD->isVolatile(), + LD->getAlignment()); + } + + // Create token factor to keep old chain connected. + SDValue Token = DAG.getNode(ISD::TokenFactor, N->getDebugLoc(), + MVT::Other, Chain, ReplLoad.getValue(1)); + + // Make sure the new and old chains are cleaned up. + AddToWorkList(Token.getNode()); + + // Replace uses with load result and token factor. Don't add users + // to work list. + return CombineTo(N, ReplLoad.getValue(0), Token, false); + } + } + + // Try transforming N to an indexed load. + if (CombineToPreIndexedLoadStore(N) || CombineToPostIndexedLoadStore(N)) + return SDValue(N, 0); + + return SDValue(); +} + + +/// ReduceLoadOpStoreWidth - Look for sequence of load / op / store where op is +/// one of 'or', 'xor', and 'and' of immediates. If 'op' is only touching some +/// of the loaded bits, try narrowing the load and store if it would end up +/// being a win for performance or code size. +SDValue DAGCombiner::ReduceLoadOpStoreWidth(SDNode *N) { + StoreSDNode *ST = cast(N); + if (ST->isVolatile()) + return SDValue(); + + SDValue Chain = ST->getChain(); + SDValue Value = ST->getValue(); + SDValue Ptr = ST->getBasePtr(); + EVT VT = Value.getValueType(); + + if (ST->isTruncatingStore() || VT.isVector() || !Value.hasOneUse()) + return SDValue(); + + unsigned Opc = Value.getOpcode(); + if ((Opc != ISD::OR && Opc != ISD::XOR && Opc != ISD::AND) || + Value.getOperand(1).getOpcode() != ISD::Constant) + return SDValue(); + + SDValue N0 = Value.getOperand(0); + if (ISD::isNormalLoad(N0.getNode()) && N0.hasOneUse()) { + LoadSDNode *LD = cast(N0); + if (LD->getBasePtr() != Ptr) + return SDValue(); + + // Find the type to narrow it the load / op / store to. + SDValue N1 = Value.getOperand(1); + unsigned BitWidth = N1.getValueSizeInBits(); + APInt Imm = cast(N1)->getAPIntValue(); + if (Opc == ISD::AND) + Imm ^= APInt::getAllOnesValue(BitWidth); + if (Imm == 0 || Imm.isAllOnesValue()) + return SDValue(); + unsigned ShAmt = Imm.countTrailingZeros(); + unsigned MSB = BitWidth - Imm.countLeadingZeros() - 1; + unsigned NewBW = NextPowerOf2(MSB - ShAmt); + EVT NewVT = EVT::getIntegerVT(*DAG.getContext(), NewBW); + while (NewBW < BitWidth && + !(TLI.isOperationLegalOrCustom(Opc, NewVT) && + TLI.isNarrowingProfitable(VT, NewVT))) { + NewBW = NextPowerOf2(NewBW); + NewVT = EVT::getIntegerVT(*DAG.getContext(), NewBW); + } + if (NewBW >= BitWidth) + return SDValue(); + + // If the lsb changed does not start at the type bitwidth boundary, + // start at the previous one. + if (ShAmt % NewBW) + ShAmt = (((ShAmt + NewBW - 1) / NewBW) * NewBW) - NewBW; + APInt Mask = APInt::getBitsSet(BitWidth, ShAmt, ShAmt + NewBW); + if ((Imm & Mask) == Imm) { + APInt NewImm = (Imm & Mask).lshr(ShAmt).trunc(NewBW); + if (Opc == ISD::AND) + NewImm ^= APInt::getAllOnesValue(NewBW); + uint64_t PtrOff = ShAmt / 8; + // For big endian targets, we need to adjust the offset to the pointer to + // load the correct bytes. + if (TLI.isBigEndian()) + PtrOff = (BitWidth + 7 - NewBW) / 8 - PtrOff; + + unsigned NewAlign = MinAlign(LD->getAlignment(), PtrOff); + if (NewAlign < + TLI.getTargetData()->getABITypeAlignment(NewVT.getTypeForEVT(*DAG.getContext()))) + return SDValue(); + + SDValue NewPtr = DAG.getNode(ISD::ADD, LD->getDebugLoc(), + Ptr.getValueType(), Ptr, + DAG.getConstant(PtrOff, Ptr.getValueType())); + SDValue NewLD = DAG.getLoad(NewVT, N0.getDebugLoc(), + LD->getChain(), NewPtr, + LD->getSrcValue(), LD->getSrcValueOffset(), + LD->isVolatile(), NewAlign); + SDValue NewVal = DAG.getNode(Opc, Value.getDebugLoc(), NewVT, NewLD, + DAG.getConstant(NewImm, NewVT)); + SDValue NewST = DAG.getStore(Chain, N->getDebugLoc(), + NewVal, NewPtr, + ST->getSrcValue(), ST->getSrcValueOffset(), + false, NewAlign); + + AddToWorkList(NewPtr.getNode()); + AddToWorkList(NewLD.getNode()); + AddToWorkList(NewVal.getNode()); + WorkListRemover DeadNodes(*this); + DAG.ReplaceAllUsesOfValueWith(N0.getValue(1), NewLD.getValue(1), + &DeadNodes); + ++OpsNarrowed; + return NewST; + } + } + + return SDValue(); +} + +SDValue DAGCombiner::visitSTORE(SDNode *N) { + StoreSDNode *ST = cast(N); + SDValue Chain = ST->getChain(); + SDValue Value = ST->getValue(); + SDValue Ptr = ST->getBasePtr(); + + // Try to infer better alignment information than the store already has. + if (OptLevel != CodeGenOpt::None && ST->isUnindexed()) { + if (unsigned Align = InferAlignment(Ptr, DAG)) { + if (Align > ST->getAlignment()) + return DAG.getTruncStore(Chain, N->getDebugLoc(), Value, + Ptr, ST->getSrcValue(), + ST->getSrcValueOffset(), ST->getMemoryVT(), + ST->isVolatile(), Align); + } + } + + // If this is a store of a bit convert, store the input value if the + // resultant store does not need a higher alignment than the original. + if (Value.getOpcode() == ISD::BIT_CONVERT && !ST->isTruncatingStore() && + ST->isUnindexed()) { + unsigned OrigAlign = ST->getAlignment(); + EVT SVT = Value.getOperand(0).getValueType(); + unsigned Align = TLI.getTargetData()-> + getABITypeAlignment(SVT.getTypeForEVT(*DAG.getContext())); + if (Align <= OrigAlign && + ((!LegalOperations && !ST->isVolatile()) || + TLI.isOperationLegalOrCustom(ISD::STORE, SVT))) + return DAG.getStore(Chain, N->getDebugLoc(), Value.getOperand(0), + Ptr, ST->getSrcValue(), + ST->getSrcValueOffset(), ST->isVolatile(), OrigAlign); + } + + // Turn 'store float 1.0, Ptr' -> 'store int 0x12345678, Ptr' + if (ConstantFPSDNode *CFP = dyn_cast(Value)) { + // NOTE: If the original store is volatile, this transform must not increase + // the number of stores. For example, on x86-32 an f64 can be stored in one + // processor operation but an i64 (which is not legal) requires two. So the + // transform should not be done in this case. + if (Value.getOpcode() != ISD::TargetConstantFP) { + SDValue Tmp; + switch (CFP->getValueType(0).getSimpleVT().SimpleTy) { + default: llvm_unreachable("Unknown FP type"); + case MVT::f80: // We don't do this for these yet. + case MVT::f128: + case MVT::ppcf128: + break; + case MVT::f32: + if (((TLI.isTypeLegal(MVT::i32) || !LegalTypes) && !LegalOperations && + !ST->isVolatile()) || + TLI.isOperationLegalOrCustom(ISD::STORE, MVT::i32)) { + Tmp = DAG.getConstant((uint32_t)CFP->getValueAPF(). + bitcastToAPInt().getZExtValue(), MVT::i32); + return DAG.getStore(Chain, N->getDebugLoc(), Tmp, + Ptr, ST->getSrcValue(), + ST->getSrcValueOffset(), ST->isVolatile(), + ST->getAlignment()); + } + break; + case MVT::f64: + if (((TLI.isTypeLegal(MVT::i64) || !LegalTypes) && !LegalOperations && + !ST->isVolatile()) || + TLI.isOperationLegalOrCustom(ISD::STORE, MVT::i64)) { + Tmp = DAG.getConstant(CFP->getValueAPF().bitcastToAPInt(). + getZExtValue(), MVT::i64); + return DAG.getStore(Chain, N->getDebugLoc(), Tmp, + Ptr, ST->getSrcValue(), + ST->getSrcValueOffset(), ST->isVolatile(), + ST->getAlignment()); + } else if (!ST->isVolatile() && + TLI.isOperationLegalOrCustom(ISD::STORE, MVT::i32)) { + // Many FP stores are not made apparent until after legalize, e.g. for + // argument passing. Since this is so common, custom legalize the + // 64-bit integer store into two 32-bit stores. + uint64_t Val = CFP->getValueAPF().bitcastToAPInt().getZExtValue(); + SDValue Lo = DAG.getConstant(Val & 0xFFFFFFFF, MVT::i32); + SDValue Hi = DAG.getConstant(Val >> 32, MVT::i32); + if (TLI.isBigEndian()) std::swap(Lo, Hi); + + int SVOffset = ST->getSrcValueOffset(); + unsigned Alignment = ST->getAlignment(); + bool isVolatile = ST->isVolatile(); + + SDValue St0 = DAG.getStore(Chain, ST->getDebugLoc(), Lo, + Ptr, ST->getSrcValue(), + ST->getSrcValueOffset(), + isVolatile, ST->getAlignment()); + Ptr = DAG.getNode(ISD::ADD, N->getDebugLoc(), Ptr.getValueType(), Ptr, + DAG.getConstant(4, Ptr.getValueType())); + SVOffset += 4; + Alignment = MinAlign(Alignment, 4U); + SDValue St1 = DAG.getStore(Chain, ST->getDebugLoc(), Hi, + Ptr, ST->getSrcValue(), + SVOffset, isVolatile, Alignment); + return DAG.getNode(ISD::TokenFactor, N->getDebugLoc(), MVT::Other, + St0, St1); + } + + break; + } + } + } + + if (CombinerAA) { + // Walk up chain skipping non-aliasing memory nodes. + SDValue BetterChain = FindBetterChain(N, Chain); + + // If there is a better chain. + if (Chain != BetterChain) { + SDValue ReplStore; + + // Replace the chain to avoid dependency. + if (ST->isTruncatingStore()) { + ReplStore = DAG.getTruncStore(BetterChain, N->getDebugLoc(), Value, Ptr, + ST->getSrcValue(),ST->getSrcValueOffset(), + ST->getMemoryVT(), + ST->isVolatile(), ST->getAlignment()); + } else { + ReplStore = DAG.getStore(BetterChain, N->getDebugLoc(), Value, Ptr, + ST->getSrcValue(), ST->getSrcValueOffset(), + ST->isVolatile(), ST->getAlignment()); + } + + // Create token to keep both nodes around. + SDValue Token = DAG.getNode(ISD::TokenFactor, N->getDebugLoc(), + MVT::Other, Chain, ReplStore); + + // Make sure the new and old chains are cleaned up. + AddToWorkList(Token.getNode()); + + // Don't add users to work list. + return CombineTo(N, Token, false); + } + } + + // Try transforming N to an indexed store. + if (CombineToPreIndexedLoadStore(N) || CombineToPostIndexedLoadStore(N)) + return SDValue(N, 0); + + // FIXME: is there such a thing as a truncating indexed store? + if (ST->isTruncatingStore() && ST->isUnindexed() && + Value.getValueType().isInteger()) { + // See if we can simplify the input to this truncstore with knowledge that + // only the low bits are being used. For example: + // "truncstore (or (shl x, 8), y), i8" -> "truncstore y, i8" + SDValue Shorter = + GetDemandedBits(Value, + APInt::getLowBitsSet(Value.getValueSizeInBits(), + ST->getMemoryVT().getSizeInBits())); + AddToWorkList(Value.getNode()); + if (Shorter.getNode()) + return DAG.getTruncStore(Chain, N->getDebugLoc(), Shorter, + Ptr, ST->getSrcValue(), + ST->getSrcValueOffset(), ST->getMemoryVT(), + ST->isVolatile(), ST->getAlignment()); + + // Otherwise, see if we can simplify the operation with + // SimplifyDemandedBits, which only works if the value has a single use. + if (SimplifyDemandedBits(Value, + APInt::getLowBitsSet( + Value.getValueSizeInBits(), + ST->getMemoryVT().getSizeInBits()))) + return SDValue(N, 0); + } + + // If this is a load followed by a store to the same location, then the store + // is dead/noop. + if (LoadSDNode *Ld = dyn_cast(Value)) { + if (Ld->getBasePtr() == Ptr && ST->getMemoryVT() == Ld->getMemoryVT() && + ST->isUnindexed() && !ST->isVolatile() && + // There can't be any side effects between the load and store, such as + // a call or store. + Chain.reachesChainWithoutSideEffects(SDValue(Ld, 1))) { + // The store is dead, remove it. + return Chain; + } + } + + // If this is an FP_ROUND or TRUNC followed by a store, fold this into a + // truncating store. We can do this even if this is already a truncstore. + if ((Value.getOpcode() == ISD::FP_ROUND || Value.getOpcode() == ISD::TRUNCATE) + && Value.getNode()->hasOneUse() && ST->isUnindexed() && + TLI.isTruncStoreLegal(Value.getOperand(0).getValueType(), + ST->getMemoryVT())) { + return DAG.getTruncStore(Chain, N->getDebugLoc(), Value.getOperand(0), + Ptr, ST->getSrcValue(), + ST->getSrcValueOffset(), ST->getMemoryVT(), + ST->isVolatile(), ST->getAlignment()); + } + + return ReduceLoadOpStoreWidth(N); +} + +SDValue DAGCombiner::visitINSERT_VECTOR_ELT(SDNode *N) { + SDValue InVec = N->getOperand(0); + SDValue InVal = N->getOperand(1); + SDValue EltNo = N->getOperand(2); + + // If the invec is a BUILD_VECTOR and if EltNo is a constant, build a new + // vector with the inserted element. + if (InVec.getOpcode() == ISD::BUILD_VECTOR && isa(EltNo)) { + unsigned Elt = cast(EltNo)->getZExtValue(); + SmallVector Ops(InVec.getNode()->op_begin(), + InVec.getNode()->op_end()); + if (Elt < Ops.size()) + Ops[Elt] = InVal; + return DAG.getNode(ISD::BUILD_VECTOR, N->getDebugLoc(), + InVec.getValueType(), &Ops[0], Ops.size()); + } + // If the invec is an UNDEF and if EltNo is a constant, create a new + // BUILD_VECTOR with undef elements and the inserted element. + if (!LegalOperations && InVec.getOpcode() == ISD::UNDEF && + isa(EltNo)) { + EVT VT = InVec.getValueType(); + EVT EltVT = VT.getVectorElementType(); + unsigned NElts = VT.getVectorNumElements(); + SmallVector Ops(NElts, DAG.getUNDEF(EltVT)); + + unsigned Elt = cast(EltNo)->getZExtValue(); + if (Elt < Ops.size()) + Ops[Elt] = InVal; + return DAG.getNode(ISD::BUILD_VECTOR, N->getDebugLoc(), + InVec.getValueType(), &Ops[0], Ops.size()); + } + return SDValue(); +} + +SDValue DAGCombiner::visitEXTRACT_VECTOR_ELT(SDNode *N) { + // (vextract (scalar_to_vector val, 0) -> val + SDValue InVec = N->getOperand(0); + + if (InVec.getOpcode() == ISD::SCALAR_TO_VECTOR) { + // If the operand is wider than the vector element type then it is implicitly + // truncated. Make that explicit here. + EVT EltVT = InVec.getValueType().getVectorElementType(); + SDValue InOp = InVec.getOperand(0); + if (InOp.getValueType() != EltVT) + return DAG.getNode(ISD::TRUNCATE, InVec.getDebugLoc(), EltVT, InOp); + return InOp; + } + + // Perform only after legalization to ensure build_vector / vector_shuffle + // optimizations have already been done. + if (!LegalOperations) return SDValue(); + + // (vextract (v4f32 load $addr), c) -> (f32 load $addr+c*size) + // (vextract (v4f32 s2v (f32 load $addr)), c) -> (f32 load $addr+c*size) + // (vextract (v4f32 shuffle (load $addr), <1,u,u,u>), 0) -> (f32 load $addr) + SDValue EltNo = N->getOperand(1); + + if (isa(EltNo)) { + unsigned Elt = cast(EltNo)->getZExtValue(); + bool NewLoad = false; + bool BCNumEltsChanged = false; + EVT VT = InVec.getValueType(); + EVT ExtVT = VT.getVectorElementType(); + EVT LVT = ExtVT; + + if (InVec.getOpcode() == ISD::BIT_CONVERT) { + EVT BCVT = InVec.getOperand(0).getValueType(); + if (!BCVT.isVector() || ExtVT.bitsGT(BCVT.getVectorElementType())) + return SDValue(); + if (VT.getVectorNumElements() != BCVT.getVectorNumElements()) + BCNumEltsChanged = true; + InVec = InVec.getOperand(0); + ExtVT = BCVT.getVectorElementType(); + NewLoad = true; + } + + LoadSDNode *LN0 = NULL; + const ShuffleVectorSDNode *SVN = NULL; + if (ISD::isNormalLoad(InVec.getNode())) { + LN0 = cast(InVec); + } else if (InVec.getOpcode() == ISD::SCALAR_TO_VECTOR && + InVec.getOperand(0).getValueType() == ExtVT && + ISD::isNormalLoad(InVec.getOperand(0).getNode())) { + LN0 = cast(InVec.getOperand(0)); + } else if ((SVN = dyn_cast(InVec))) { + // (vextract (vector_shuffle (load $addr), v2, <1, u, u, u>), 1) + // => + // (load $addr+1*size) + + // If the bit convert changed the number of elements, it is unsafe + // to examine the mask. + if (BCNumEltsChanged) + return SDValue(); + + // Select the input vector, guarding against out of range extract vector. + unsigned NumElems = VT.getVectorNumElements(); + int Idx = (Elt > NumElems) ? -1 : SVN->getMaskElt(Elt); + InVec = (Idx < (int)NumElems) ? InVec.getOperand(0) : InVec.getOperand(1); + + if (InVec.getOpcode() == ISD::BIT_CONVERT) + InVec = InVec.getOperand(0); + if (ISD::isNormalLoad(InVec.getNode())) { + LN0 = cast(InVec); + Elt = (Idx < (int)NumElems) ? Idx : Idx - NumElems; + } + } + + if (!LN0 || !LN0->hasOneUse() || LN0->isVolatile()) + return SDValue(); + + unsigned Align = LN0->getAlignment(); + if (NewLoad) { + // Check the resultant load doesn't need a higher alignment than the + // original load. + unsigned NewAlign = + TLI.getTargetData()->getABITypeAlignment(LVT.getTypeForEVT(*DAG.getContext())); + + if (NewAlign > Align || !TLI.isOperationLegalOrCustom(ISD::LOAD, LVT)) + return SDValue(); + + Align = NewAlign; + } + + SDValue NewPtr = LN0->getBasePtr(); + if (Elt) { + unsigned PtrOff = LVT.getSizeInBits() * Elt / 8; + EVT PtrType = NewPtr.getValueType(); + if (TLI.isBigEndian()) + PtrOff = VT.getSizeInBits() / 8 - PtrOff; + NewPtr = DAG.getNode(ISD::ADD, N->getDebugLoc(), PtrType, NewPtr, + DAG.getConstant(PtrOff, PtrType)); + } + + return DAG.getLoad(LVT, N->getDebugLoc(), LN0->getChain(), NewPtr, + LN0->getSrcValue(), LN0->getSrcValueOffset(), + LN0->isVolatile(), Align); + } + + return SDValue(); +} + +SDValue DAGCombiner::visitBUILD_VECTOR(SDNode *N) { + unsigned NumInScalars = N->getNumOperands(); + EVT VT = N->getValueType(0); + + // Check to see if this is a BUILD_VECTOR of a bunch of EXTRACT_VECTOR_ELT + // operations. If so, and if the EXTRACT_VECTOR_ELT vector inputs come from + // at most two distinct vectors, turn this into a shuffle node. + SDValue VecIn1, VecIn2; + for (unsigned i = 0; i != NumInScalars; ++i) { + // Ignore undef inputs. + if (N->getOperand(i).getOpcode() == ISD::UNDEF) continue; + + // If this input is something other than a EXTRACT_VECTOR_ELT with a + // constant index, bail out. + if (N->getOperand(i).getOpcode() != ISD::EXTRACT_VECTOR_ELT || + !isa(N->getOperand(i).getOperand(1))) { + VecIn1 = VecIn2 = SDValue(0, 0); + break; + } + + // If the input vector type disagrees with the result of the build_vector, + // we can't make a shuffle. + SDValue ExtractedFromVec = N->getOperand(i).getOperand(0); + if (ExtractedFromVec.getValueType() != VT) { + VecIn1 = VecIn2 = SDValue(0, 0); + break; + } + + // Otherwise, remember this. We allow up to two distinct input vectors. + if (ExtractedFromVec == VecIn1 || ExtractedFromVec == VecIn2) + continue; + + if (VecIn1.getNode() == 0) { + VecIn1 = ExtractedFromVec; + } else if (VecIn2.getNode() == 0) { + VecIn2 = ExtractedFromVec; + } else { + // Too many inputs. + VecIn1 = VecIn2 = SDValue(0, 0); + break; + } + } + + // If everything is good, we can make a shuffle operation. + if (VecIn1.getNode()) { + SmallVector Mask; + for (unsigned i = 0; i != NumInScalars; ++i) { + if (N->getOperand(i).getOpcode() == ISD::UNDEF) { + Mask.push_back(-1); + continue; + } + + // If extracting from the first vector, just use the index directly. + SDValue Extract = N->getOperand(i); + SDValue ExtVal = Extract.getOperand(1); + if (Extract.getOperand(0) == VecIn1) { + unsigned ExtIndex = cast(ExtVal)->getZExtValue(); + if (ExtIndex > VT.getVectorNumElements()) + return SDValue(); + + Mask.push_back(ExtIndex); + continue; + } + + // Otherwise, use InIdx + VecSize + unsigned Idx = cast(ExtVal)->getZExtValue(); + Mask.push_back(Idx+NumInScalars); + } + + // Add count and size info. + if (!TLI.isTypeLegal(VT) && LegalTypes) + return SDValue(); + + // Return the new VECTOR_SHUFFLE node. + SDValue Ops[2]; + Ops[0] = VecIn1; + Ops[1] = VecIn2.getNode() ? VecIn2 : DAG.getUNDEF(VT); + return DAG.getVectorShuffle(VT, N->getDebugLoc(), Ops[0], Ops[1], &Mask[0]); + } + + return SDValue(); +} + +SDValue DAGCombiner::visitCONCAT_VECTORS(SDNode *N) { + // TODO: Check to see if this is a CONCAT_VECTORS of a bunch of + // EXTRACT_SUBVECTOR operations. If so, and if the EXTRACT_SUBVECTOR vector + // inputs come from at most two distinct vectors, turn this into a shuffle + // node. + + // If we only have one input vector, we don't need to do any concatenation. + if (N->getNumOperands() == 1) + return N->getOperand(0); + + return SDValue(); +} + +SDValue DAGCombiner::visitVECTOR_SHUFFLE(SDNode *N) { + return SDValue(); + + EVT VT = N->getValueType(0); + unsigned NumElts = VT.getVectorNumElements(); + + SDValue N0 = N->getOperand(0); + + assert(N0.getValueType().getVectorNumElements() == NumElts && + "Vector shuffle must be normalized in DAG"); + + // FIXME: implement canonicalizations from DAG.getVectorShuffle() + + // If it is a splat, check if the argument vector is a build_vector with + // all scalar elements the same. + if (cast(N)->isSplat()) { + SDNode *V = N0.getNode(); + + + // If this is a bit convert that changes the element type of the vector but + // not the number of vector elements, look through it. Be careful not to + // look though conversions that change things like v4f32 to v2f64. + if (V->getOpcode() == ISD::BIT_CONVERT) { + SDValue ConvInput = V->getOperand(0); + if (ConvInput.getValueType().isVector() && + ConvInput.getValueType().getVectorNumElements() == NumElts) + V = ConvInput.getNode(); + } + + if (V->getOpcode() == ISD::BUILD_VECTOR) { + unsigned NumElems = V->getNumOperands(); + unsigned BaseIdx = cast(N)->getSplatIndex(); + if (NumElems > BaseIdx) { + SDValue Base; + bool AllSame = true; + for (unsigned i = 0; i != NumElems; ++i) { + if (V->getOperand(i).getOpcode() != ISD::UNDEF) { + Base = V->getOperand(i); + break; + } + } + // Splat of , return + if (!Base.getNode()) + return N0; + for (unsigned i = 0; i != NumElems; ++i) { + if (V->getOperand(i) != Base) { + AllSame = false; + break; + } + } + // Splat of , return + if (AllSame) + return N0; + } + } + } + return SDValue(); +} + +/// XformToShuffleWithZero - Returns a vector_shuffle if it able to transform +/// an AND to a vector_shuffle with the destination vector and a zero vector. +/// e.g. AND V, <0xffffffff, 0, 0xffffffff, 0>. ==> +/// vector_shuffle V, Zero, <0, 4, 2, 4> +SDValue DAGCombiner::XformToShuffleWithZero(SDNode *N) { + EVT VT = N->getValueType(0); + DebugLoc dl = N->getDebugLoc(); + SDValue LHS = N->getOperand(0); + SDValue RHS = N->getOperand(1); + if (N->getOpcode() == ISD::AND) { + if (RHS.getOpcode() == ISD::BIT_CONVERT) + RHS = RHS.getOperand(0); + if (RHS.getOpcode() == ISD::BUILD_VECTOR) { + SmallVector Indices; + unsigned NumElts = RHS.getNumOperands(); + for (unsigned i = 0; i != NumElts; ++i) { + SDValue Elt = RHS.getOperand(i); + if (!isa(Elt)) + return SDValue(); + else if (cast(Elt)->isAllOnesValue()) + Indices.push_back(i); + else if (cast(Elt)->isNullValue()) + Indices.push_back(NumElts); + else + return SDValue(); + } + + // Let's see if the target supports this vector_shuffle. + EVT RVT = RHS.getValueType(); + if (!TLI.isVectorClearMaskLegal(Indices, RVT)) + return SDValue(); + + // Return the new VECTOR_SHUFFLE node. + EVT EltVT = RVT.getVectorElementType(); + SmallVector ZeroOps(RVT.getVectorNumElements(), + DAG.getConstant(0, EltVT)); + SDValue Zero = DAG.getNode(ISD::BUILD_VECTOR, N->getDebugLoc(), + RVT, &ZeroOps[0], ZeroOps.size()); + LHS = DAG.getNode(ISD::BIT_CONVERT, dl, RVT, LHS); + SDValue Shuf = DAG.getVectorShuffle(RVT, dl, LHS, Zero, &Indices[0]); + return DAG.getNode(ISD::BIT_CONVERT, dl, VT, Shuf); + } + } + + return SDValue(); +} + +/// SimplifyVBinOp - Visit a binary vector operation, like ADD. +SDValue DAGCombiner::SimplifyVBinOp(SDNode *N) { + // After legalize, the target may be depending on adds and other + // binary ops to provide legal ways to construct constants or other + // things. Simplifying them may result in a loss of legality. + if (LegalOperations) return SDValue(); + + EVT VT = N->getValueType(0); + assert(VT.isVector() && "SimplifyVBinOp only works on vectors!"); + + EVT EltType = VT.getVectorElementType(); + SDValue LHS = N->getOperand(0); + SDValue RHS = N->getOperand(1); + SDValue Shuffle = XformToShuffleWithZero(N); + if (Shuffle.getNode()) return Shuffle; + + // If the LHS and RHS are BUILD_VECTOR nodes, see if we can constant fold + // this operation. + if (LHS.getOpcode() == ISD::BUILD_VECTOR && + RHS.getOpcode() == ISD::BUILD_VECTOR) { + SmallVector Ops; + for (unsigned i = 0, e = LHS.getNumOperands(); i != e; ++i) { + SDValue LHSOp = LHS.getOperand(i); + SDValue RHSOp = RHS.getOperand(i); + // If these two elements can't be folded, bail out. + if ((LHSOp.getOpcode() != ISD::UNDEF && + LHSOp.getOpcode() != ISD::Constant && + LHSOp.getOpcode() != ISD::ConstantFP) || + (RHSOp.getOpcode() != ISD::UNDEF && + RHSOp.getOpcode() != ISD::Constant && + RHSOp.getOpcode() != ISD::ConstantFP)) + break; + + // Can't fold divide by zero. + if (N->getOpcode() == ISD::SDIV || N->getOpcode() == ISD::UDIV || + N->getOpcode() == ISD::FDIV) { + if ((RHSOp.getOpcode() == ISD::Constant && + cast(RHSOp.getNode())->isNullValue()) || + (RHSOp.getOpcode() == ISD::ConstantFP && + cast(RHSOp.getNode())->getValueAPF().isZero())) + break; + } + + Ops.push_back(DAG.getNode(N->getOpcode(), LHS.getDebugLoc(), + EltType, LHSOp, RHSOp)); + AddToWorkList(Ops.back().getNode()); + assert((Ops.back().getOpcode() == ISD::UNDEF || + Ops.back().getOpcode() == ISD::Constant || + Ops.back().getOpcode() == ISD::ConstantFP) && + "Scalar binop didn't fold!"); + } + + if (Ops.size() == LHS.getNumOperands()) { + EVT VT = LHS.getValueType(); + return DAG.getNode(ISD::BUILD_VECTOR, N->getDebugLoc(), VT, + &Ops[0], Ops.size()); + } + } + + return SDValue(); +} + +SDValue DAGCombiner::SimplifySelect(DebugLoc DL, SDValue N0, + SDValue N1, SDValue N2){ + assert(N0.getOpcode() ==ISD::SETCC && "First argument must be a SetCC node!"); + + SDValue SCC = SimplifySelectCC(DL, N0.getOperand(0), N0.getOperand(1), N1, N2, + cast(N0.getOperand(2))->get()); + + // If we got a simplified select_cc node back from SimplifySelectCC, then + // break it down into a new SETCC node, and a new SELECT node, and then return + // the SELECT node, since we were called with a SELECT node. + if (SCC.getNode()) { + // Check to see if we got a select_cc back (to turn into setcc/select). + // Otherwise, just return whatever node we got back, like fabs. + if (SCC.getOpcode() == ISD::SELECT_CC) { + SDValue SETCC = DAG.getNode(ISD::SETCC, N0.getDebugLoc(), + N0.getValueType(), + SCC.getOperand(0), SCC.getOperand(1), + SCC.getOperand(4)); + AddToWorkList(SETCC.getNode()); + return DAG.getNode(ISD::SELECT, SCC.getDebugLoc(), SCC.getValueType(), + SCC.getOperand(2), SCC.getOperand(3), SETCC); + } + + return SCC; + } + return SDValue(); +} + +/// SimplifySelectOps - Given a SELECT or a SELECT_CC node, where LHS and RHS +/// are the two values being selected between, see if we can simplify the +/// select. Callers of this should assume that TheSelect is deleted if this +/// returns true. As such, they should return the appropriate thing (e.g. the +/// node) back to the top-level of the DAG combiner loop to avoid it being +/// looked at. +bool DAGCombiner::SimplifySelectOps(SDNode *TheSelect, SDValue LHS, + SDValue RHS) { + + // If this is a select from two identical things, try to pull the operation + // through the select. + if (LHS.getOpcode() == RHS.getOpcode() && LHS.hasOneUse() && RHS.hasOneUse()){ + // If this is a load and the token chain is identical, replace the select + // of two loads with a load through a select of the address to load from. + // This triggers in things like "select bool X, 10.0, 123.0" after the FP + // constants have been dropped into the constant pool. + if (LHS.getOpcode() == ISD::LOAD && + // Do not let this transformation reduce the number of volatile loads. + !cast(LHS)->isVolatile() && + !cast(RHS)->isVolatile() && + // Token chains must be identical. + LHS.getOperand(0) == RHS.getOperand(0)) { + LoadSDNode *LLD = cast(LHS); + LoadSDNode *RLD = cast(RHS); + + // If this is an EXTLOAD, the VT's must match. + if (LLD->getMemoryVT() == RLD->getMemoryVT()) { + // FIXME: this discards src value information. This is + // over-conservative. It would be beneficial to be able to remember + // both potential memory locations. + SDValue Addr; + if (TheSelect->getOpcode() == ISD::SELECT) { + // Check that the condition doesn't reach either load. If so, folding + // this will induce a cycle into the DAG. + if ((!LLD->hasAnyUseOfValue(1) || + !LLD->isPredecessorOf(TheSelect->getOperand(0).getNode())) && + (!RLD->hasAnyUseOfValue(1) || + !RLD->isPredecessorOf(TheSelect->getOperand(0).getNode()))) { + Addr = DAG.getNode(ISD::SELECT, TheSelect->getDebugLoc(), + LLD->getBasePtr().getValueType(), + TheSelect->getOperand(0), LLD->getBasePtr(), + RLD->getBasePtr()); + } + } else { + // Check that the condition doesn't reach either load. If so, folding + // this will induce a cycle into the DAG. + if ((!LLD->hasAnyUseOfValue(1) || + (!LLD->isPredecessorOf(TheSelect->getOperand(0).getNode()) && + !LLD->isPredecessorOf(TheSelect->getOperand(1).getNode()))) && + (!RLD->hasAnyUseOfValue(1) || + (!RLD->isPredecessorOf(TheSelect->getOperand(0).getNode()) && + !RLD->isPredecessorOf(TheSelect->getOperand(1).getNode())))) { + Addr = DAG.getNode(ISD::SELECT_CC, TheSelect->getDebugLoc(), + LLD->getBasePtr().getValueType(), + TheSelect->getOperand(0), + TheSelect->getOperand(1), + LLD->getBasePtr(), RLD->getBasePtr(), + TheSelect->getOperand(4)); + } + } + + if (Addr.getNode()) { + SDValue Load; + if (LLD->getExtensionType() == ISD::NON_EXTLOAD) { + Load = DAG.getLoad(TheSelect->getValueType(0), + TheSelect->getDebugLoc(), + LLD->getChain(), + Addr, 0, 0, + LLD->isVolatile(), + LLD->getAlignment()); + } else { + Load = DAG.getExtLoad(LLD->getExtensionType(), + TheSelect->getDebugLoc(), + TheSelect->getValueType(0), + LLD->getChain(), Addr, 0, 0, + LLD->getMemoryVT(), + LLD->isVolatile(), + LLD->getAlignment()); + } + + // Users of the select now use the result of the load. + CombineTo(TheSelect, Load); + + // Users of the old loads now use the new load's chain. We know the + // old-load value is dead now. + CombineTo(LHS.getNode(), Load.getValue(0), Load.getValue(1)); + CombineTo(RHS.getNode(), Load.getValue(0), Load.getValue(1)); + return true; + } + } + } + } + + return false; +} + +/// SimplifySelectCC - Simplify an expression of the form (N0 cond N1) ? N2 : N3 +/// where 'cond' is the comparison specified by CC. +SDValue DAGCombiner::SimplifySelectCC(DebugLoc DL, SDValue N0, SDValue N1, + SDValue N2, SDValue N3, + ISD::CondCode CC, bool NotExtCompare) { + // (x ? y : y) -> y. + if (N2 == N3) return N2; + + EVT VT = N2.getValueType(); + ConstantSDNode *N1C = dyn_cast(N1.getNode()); + ConstantSDNode *N2C = dyn_cast(N2.getNode()); + ConstantSDNode *N3C = dyn_cast(N3.getNode()); + + // Determine if the condition we're dealing with is constant + SDValue SCC = SimplifySetCC(TLI.getSetCCResultType(N0.getValueType()), + N0, N1, CC, DL, false); + if (SCC.getNode()) AddToWorkList(SCC.getNode()); + ConstantSDNode *SCCC = dyn_cast_or_null(SCC.getNode()); + + // fold select_cc true, x, y -> x + if (SCCC && !SCCC->isNullValue()) + return N2; + // fold select_cc false, x, y -> y + if (SCCC && SCCC->isNullValue()) + return N3; + + // Check to see if we can simplify the select into an fabs node + if (ConstantFPSDNode *CFP = dyn_cast(N1)) { + // Allow either -0.0 or 0.0 + if (CFP->getValueAPF().isZero()) { + // select (setg[te] X, +/-0.0), X, fneg(X) -> fabs + if ((CC == ISD::SETGE || CC == ISD::SETGT) && + N0 == N2 && N3.getOpcode() == ISD::FNEG && + N2 == N3.getOperand(0)) + return DAG.getNode(ISD::FABS, DL, VT, N0); + + // select (setl[te] X, +/-0.0), fneg(X), X -> fabs + if ((CC == ISD::SETLT || CC == ISD::SETLE) && + N0 == N3 && N2.getOpcode() == ISD::FNEG && + N2.getOperand(0) == N3) + return DAG.getNode(ISD::FABS, DL, VT, N3); + } + } + + // Turn "(a cond b) ? 1.0f : 2.0f" into "load (tmp + ((a cond b) ? 0 : 4)" + // where "tmp" is a constant pool entry containing an array with 1.0 and 2.0 + // in it. This is a win when the constant is not otherwise available because + // it replaces two constant pool loads with one. We only do this if the FP + // type is known to be legal, because if it isn't, then we are before legalize + // types an we want the other legalization to happen first (e.g. to avoid + // messing with soft float) and if the ConstantFP is not legal, because if + // it is legal, we may not need to store the FP constant in a constant pool. + if (ConstantFPSDNode *TV = dyn_cast(N2)) + if (ConstantFPSDNode *FV = dyn_cast(N3)) { + if (TLI.isTypeLegal(N2.getValueType()) && + (TLI.getOperationAction(ISD::ConstantFP, N2.getValueType()) != + TargetLowering::Legal) && + // If both constants have multiple uses, then we won't need to do an + // extra load, they are likely around in registers for other users. + (TV->hasOneUse() || FV->hasOneUse())) { + Constant *Elts[] = { + const_cast(FV->getConstantFPValue()), + const_cast(TV->getConstantFPValue()) + }; + const Type *FPTy = Elts[0]->getType(); + const TargetData &TD = *TLI.getTargetData(); + + // Create a ConstantArray of the two constants. + Constant *CA = ConstantArray::get(ArrayType::get(FPTy, 2), Elts, 2); + SDValue CPIdx = DAG.getConstantPool(CA, TLI.getPointerTy(), + TD.getPrefTypeAlignment(FPTy)); + unsigned Alignment = cast(CPIdx)->getAlignment(); + + // Get the offsets to the 0 and 1 element of the array so that we can + // select between them. + SDValue Zero = DAG.getIntPtrConstant(0); + unsigned EltSize = (unsigned)TD.getTypeAllocSize(Elts[0]->getType()); + SDValue One = DAG.getIntPtrConstant(EltSize); + + SDValue Cond = DAG.getSetCC(DL, + TLI.getSetCCResultType(N0.getValueType()), + N0, N1, CC); + SDValue CstOffset = DAG.getNode(ISD::SELECT, DL, Zero.getValueType(), + Cond, One, Zero); + CPIdx = DAG.getNode(ISD::ADD, DL, TLI.getPointerTy(), CPIdx, + CstOffset); + return DAG.getLoad(TV->getValueType(0), DL, DAG.getEntryNode(), CPIdx, + PseudoSourceValue::getConstantPool(), 0, false, + Alignment); + + } + } + + // Check to see if we can perform the "gzip trick", transforming + // (select_cc setlt X, 0, A, 0) -> (and (sra X, (sub size(X), 1), A) + if (N1C && N3C && N3C->isNullValue() && CC == ISD::SETLT && + N0.getValueType().isInteger() && + N2.getValueType().isInteger() && + (N1C->isNullValue() || // (a < 0) ? b : 0 + (N1C->getAPIntValue() == 1 && N0 == N2))) { // (a < 1) ? a : 0 + EVT XType = N0.getValueType(); + EVT AType = N2.getValueType(); + if (XType.bitsGE(AType)) { + // and (sra X, size(X)-1, A) -> "and (srl X, C2), A" iff A is a + // single-bit constant. + if (N2C && ((N2C->getAPIntValue() & (N2C->getAPIntValue()-1)) == 0)) { + unsigned ShCtV = N2C->getAPIntValue().logBase2(); + ShCtV = XType.getSizeInBits()-ShCtV-1; + SDValue ShCt = DAG.getConstant(ShCtV, getShiftAmountTy()); + SDValue Shift = DAG.getNode(ISD::SRL, N0.getDebugLoc(), + XType, N0, ShCt); + AddToWorkList(Shift.getNode()); + + if (XType.bitsGT(AType)) { + Shift = DAG.getNode(ISD::TRUNCATE, DL, AType, Shift); + AddToWorkList(Shift.getNode()); + } + + return DAG.getNode(ISD::AND, DL, AType, Shift, N2); + } + + SDValue Shift = DAG.getNode(ISD::SRA, N0.getDebugLoc(), + XType, N0, + DAG.getConstant(XType.getSizeInBits()-1, + getShiftAmountTy())); + AddToWorkList(Shift.getNode()); + + if (XType.bitsGT(AType)) { + Shift = DAG.getNode(ISD::TRUNCATE, DL, AType, Shift); + AddToWorkList(Shift.getNode()); + } + + return DAG.getNode(ISD::AND, DL, AType, Shift, N2); + } + } + + // fold select C, 16, 0 -> shl C, 4 + if (N2C && N3C && N3C->isNullValue() && N2C->getAPIntValue().isPowerOf2() && + TLI.getBooleanContents() == TargetLowering::ZeroOrOneBooleanContent) { + + // If the caller doesn't want us to simplify this into a zext of a compare, + // don't do it. + if (NotExtCompare && N2C->getAPIntValue() == 1) + return SDValue(); + + // Get a SetCC of the condition + // FIXME: Should probably make sure that setcc is legal if we ever have a + // target where it isn't. + SDValue Temp, SCC; + // cast from setcc result type to select result type + if (LegalTypes) { + SCC = DAG.getSetCC(DL, TLI.getSetCCResultType(N0.getValueType()), + N0, N1, CC); + if (N2.getValueType().bitsLT(SCC.getValueType())) + Temp = DAG.getZeroExtendInReg(SCC, N2.getDebugLoc(), N2.getValueType()); + else + Temp = DAG.getNode(ISD::ZERO_EXTEND, N2.getDebugLoc(), + N2.getValueType(), SCC); + } else { + SCC = DAG.getSetCC(N0.getDebugLoc(), MVT::i1, N0, N1, CC); + Temp = DAG.getNode(ISD::ZERO_EXTEND, N2.getDebugLoc(), + N2.getValueType(), SCC); + } + + AddToWorkList(SCC.getNode()); + AddToWorkList(Temp.getNode()); + + if (N2C->getAPIntValue() == 1) + return Temp; + + // shl setcc result by log2 n2c + return DAG.getNode(ISD::SHL, DL, N2.getValueType(), Temp, + DAG.getConstant(N2C->getAPIntValue().logBase2(), + getShiftAmountTy())); + } + + // Check to see if this is the equivalent of setcc + // FIXME: Turn all of these into setcc if setcc if setcc is legal + // otherwise, go ahead with the folds. + if (0 && N3C && N3C->isNullValue() && N2C && (N2C->getAPIntValue() == 1ULL)) { + EVT XType = N0.getValueType(); + if (!LegalOperations || + TLI.isOperationLegal(ISD::SETCC, TLI.getSetCCResultType(XType))) { + SDValue Res = DAG.getSetCC(DL, TLI.getSetCCResultType(XType), N0, N1, CC); + if (Res.getValueType() != VT) + Res = DAG.getNode(ISD::ZERO_EXTEND, DL, VT, Res); + return Res; + } + + // fold (seteq X, 0) -> (srl (ctlz X, log2(size(X)))) + if (N1C && N1C->isNullValue() && CC == ISD::SETEQ && + (!LegalOperations || + TLI.isOperationLegal(ISD::CTLZ, XType))) { + SDValue Ctlz = DAG.getNode(ISD::CTLZ, N0.getDebugLoc(), XType, N0); + return DAG.getNode(ISD::SRL, DL, XType, Ctlz, + DAG.getConstant(Log2_32(XType.getSizeInBits()), + getShiftAmountTy())); + } + // fold (setgt X, 0) -> (srl (and (-X, ~X), size(X)-1)) + if (N1C && N1C->isNullValue() && CC == ISD::SETGT) { + SDValue NegN0 = DAG.getNode(ISD::SUB, N0.getDebugLoc(), + XType, DAG.getConstant(0, XType), N0); + SDValue NotN0 = DAG.getNOT(N0.getDebugLoc(), N0, XType); + return DAG.getNode(ISD::SRL, DL, XType, + DAG.getNode(ISD::AND, DL, XType, NegN0, NotN0), + DAG.getConstant(XType.getSizeInBits()-1, + getShiftAmountTy())); + } + // fold (setgt X, -1) -> (xor (srl (X, size(X)-1), 1)) + if (N1C && N1C->isAllOnesValue() && CC == ISD::SETGT) { + SDValue Sign = DAG.getNode(ISD::SRL, N0.getDebugLoc(), XType, N0, + DAG.getConstant(XType.getSizeInBits()-1, + getShiftAmountTy())); + return DAG.getNode(ISD::XOR, DL, XType, Sign, DAG.getConstant(1, XType)); + } + } + + // Check to see if this is an integer abs. select_cc setl[te] X, 0, -X, X -> + // Y = sra (X, size(X)-1); xor (add (X, Y), Y) + if (N1C && N1C->isNullValue() && (CC == ISD::SETLT || CC == ISD::SETLE) && + N0 == N3 && N2.getOpcode() == ISD::SUB && N0 == N2.getOperand(1) && + N2.getOperand(0) == N1 && N0.getValueType().isInteger()) { + EVT XType = N0.getValueType(); + SDValue Shift = DAG.getNode(ISD::SRA, N0.getDebugLoc(), XType, N0, + DAG.getConstant(XType.getSizeInBits()-1, + getShiftAmountTy())); + SDValue Add = DAG.getNode(ISD::ADD, N0.getDebugLoc(), XType, + N0, Shift); + AddToWorkList(Shift.getNode()); + AddToWorkList(Add.getNode()); + return DAG.getNode(ISD::XOR, DL, XType, Add, Shift); + } + // Check to see if this is an integer abs. select_cc setgt X, -1, X, -X -> + // Y = sra (X, size(X)-1); xor (add (X, Y), Y) + if (N1C && N1C->isAllOnesValue() && CC == ISD::SETGT && + N0 == N2 && N3.getOpcode() == ISD::SUB && N0 == N3.getOperand(1)) { + if (ConstantSDNode *SubC = dyn_cast(N3.getOperand(0))) { + EVT XType = N0.getValueType(); + if (SubC->isNullValue() && XType.isInteger()) { + SDValue Shift = DAG.getNode(ISD::SRA, N0.getDebugLoc(), XType, + N0, + DAG.getConstant(XType.getSizeInBits()-1, + getShiftAmountTy())); + SDValue Add = DAG.getNode(ISD::ADD, N0.getDebugLoc(), + XType, N0, Shift); + AddToWorkList(Shift.getNode()); + AddToWorkList(Add.getNode()); + return DAG.getNode(ISD::XOR, DL, XType, Add, Shift); + } + } + } + + return SDValue(); +} + +/// SimplifySetCC - This is a stub for TargetLowering::SimplifySetCC. +SDValue DAGCombiner::SimplifySetCC(EVT VT, SDValue N0, + SDValue N1, ISD::CondCode Cond, + DebugLoc DL, bool foldBooleans) { + TargetLowering::DAGCombinerInfo + DagCombineInfo(DAG, !LegalTypes, !LegalOperations, false, this); + return TLI.SimplifySetCC(VT, N0, N1, Cond, foldBooleans, DagCombineInfo, DL); +} + +/// BuildSDIVSequence - Given an ISD::SDIV node expressing a divide by constant, +/// return a DAG expression to select that will generate the same value by +/// multiplying by a magic number. See: +/// +SDValue DAGCombiner::BuildSDIV(SDNode *N) { + std::vector Built; + SDValue S = TLI.BuildSDIV(N, DAG, &Built); + + for (std::vector::iterator ii = Built.begin(), ee = Built.end(); + ii != ee; ++ii) + AddToWorkList(*ii); + return S; +} + +/// BuildUDIVSequence - Given an ISD::UDIV node expressing a divide by constant, +/// return a DAG expression to select that will generate the same value by +/// multiplying by a magic number. See: +/// +SDValue DAGCombiner::BuildUDIV(SDNode *N) { + std::vector Built; + SDValue S = TLI.BuildUDIV(N, DAG, &Built); + + for (std::vector::iterator ii = Built.begin(), ee = Built.end(); + ii != ee; ++ii) + AddToWorkList(*ii); + return S; +} + +/// FindBaseOffset - Return true if base is a frame index, which is known not +// to alias with anything but itself. Provides base object and offset as results. +static bool FindBaseOffset(SDValue Ptr, SDValue &Base, int64_t &Offset, + GlobalValue *&GV, void *&CV) { + // Assume it is a primitive operation. + Base = Ptr; Offset = 0; GV = 0; CV = 0; + + // If it's an adding a simple constant then integrate the offset. + if (Base.getOpcode() == ISD::ADD) { + if (ConstantSDNode *C = dyn_cast(Base.getOperand(1))) { + Base = Base.getOperand(0); + Offset += C->getZExtValue(); + } + } + + // Return the underlying GlobalValue, and update the Offset. Return false + // for GlobalAddressSDNode since the same GlobalAddress may be represented + // by multiple nodes with different offsets. + if (GlobalAddressSDNode *G = dyn_cast(Base)) { + GV = G->getGlobal(); + Offset += G->getOffset(); + return false; + } + + // Return the underlying Constant value, and update the Offset. Return false + // for ConstantSDNodes since the same constant pool entry may be represented + // by multiple nodes with different offsets. + if (ConstantPoolSDNode *C = dyn_cast(Base)) { + CV = C->isMachineConstantPoolEntry() ? (void *)C->getMachineCPVal() + : (void *)C->getConstVal(); + Offset += C->getOffset(); + return false; + } + // If it's any of the following then it can't alias with anything but itself. + return isa(Base); +} + +/// isAlias - Return true if there is any possibility that the two addresses +/// overlap. +bool DAGCombiner::isAlias(SDValue Ptr1, int64_t Size1, + const Value *SrcValue1, int SrcValueOffset1, + unsigned SrcValueAlign1, + SDValue Ptr2, int64_t Size2, + const Value *SrcValue2, int SrcValueOffset2, + unsigned SrcValueAlign2) const { + // If they are the same then they must be aliases. + if (Ptr1 == Ptr2) return true; + + // Gather base node and offset information. + SDValue Base1, Base2; + int64_t Offset1, Offset2; + GlobalValue *GV1, *GV2; + void *CV1, *CV2; + bool isFrameIndex1 = FindBaseOffset(Ptr1, Base1, Offset1, GV1, CV1); + bool isFrameIndex2 = FindBaseOffset(Ptr2, Base2, Offset2, GV2, CV2); + + // If they have a same base address then check to see if they overlap. + if (Base1 == Base2 || (GV1 && (GV1 == GV2)) || (CV1 && (CV1 == CV2))) + return !((Offset1 + Size1) <= Offset2 || (Offset2 + Size2) <= Offset1); + + // If we know what the bases are, and they aren't identical, then we know they + // cannot alias. + if ((isFrameIndex1 || CV1 || GV1) && (isFrameIndex2 || CV2 || GV2)) + return false; + + // If we know required SrcValue1 and SrcValue2 have relatively large alignment + // compared to the size and offset of the access, we may be able to prove they + // do not alias. This check is conservative for now to catch cases created by + // splitting vector types. + if ((SrcValueAlign1 == SrcValueAlign2) && + (SrcValueOffset1 != SrcValueOffset2) && + (Size1 == Size2) && (SrcValueAlign1 > Size1)) { + int64_t OffAlign1 = SrcValueOffset1 % SrcValueAlign1; + int64_t OffAlign2 = SrcValueOffset2 % SrcValueAlign1; + + // There is no overlap between these relatively aligned accesses of similar + // size, return no alias. + if ((OffAlign1 + Size1) <= OffAlign2 || (OffAlign2 + Size2) <= OffAlign1) + return false; + } + + if (CombinerGlobalAA) { + // Use alias analysis information. + int64_t MinOffset = std::min(SrcValueOffset1, SrcValueOffset2); + int64_t Overlap1 = Size1 + SrcValueOffset1 - MinOffset; + int64_t Overlap2 = Size2 + SrcValueOffset2 - MinOffset; + AliasAnalysis::AliasResult AAResult = + AA.alias(SrcValue1, Overlap1, SrcValue2, Overlap2); + if (AAResult == AliasAnalysis::NoAlias) + return false; + } + + // Otherwise we have to assume they alias. + return true; +} + +/// FindAliasInfo - Extracts the relevant alias information from the memory +/// node. Returns true if the operand was a load. +bool DAGCombiner::FindAliasInfo(SDNode *N, + SDValue &Ptr, int64_t &Size, + const Value *&SrcValue, + int &SrcValueOffset, + unsigned &SrcValueAlign) const { + if (LoadSDNode *LD = dyn_cast(N)) { + Ptr = LD->getBasePtr(); + Size = LD->getMemoryVT().getSizeInBits() >> 3; + SrcValue = LD->getSrcValue(); + SrcValueOffset = LD->getSrcValueOffset(); + SrcValueAlign = LD->getOriginalAlignment(); + return true; + } else if (StoreSDNode *ST = dyn_cast(N)) { + Ptr = ST->getBasePtr(); + Size = ST->getMemoryVT().getSizeInBits() >> 3; + SrcValue = ST->getSrcValue(); + SrcValueOffset = ST->getSrcValueOffset(); + SrcValueAlign = ST->getOriginalAlignment(); + } else { + llvm_unreachable("FindAliasInfo expected a memory operand"); + } + + return false; +} + +/// GatherAllAliases - Walk up chain skipping non-aliasing memory nodes, +/// looking for aliasing nodes and adding them to the Aliases vector. +void DAGCombiner::GatherAllAliases(SDNode *N, SDValue OriginalChain, + SmallVector &Aliases) { + SmallVector Chains; // List of chains to visit. + SmallPtrSet Visited; // Visited node set. + + // Get alias information for node. + SDValue Ptr; + int64_t Size; + const Value *SrcValue; + int SrcValueOffset; + unsigned SrcValueAlign; + bool IsLoad = FindAliasInfo(N, Ptr, Size, SrcValue, SrcValueOffset, + SrcValueAlign); + + // Starting off. + Chains.push_back(OriginalChain); + unsigned Depth = 0; + + // Look at each chain and determine if it is an alias. If so, add it to the + // aliases list. If not, then continue up the chain looking for the next + // candidate. + while (!Chains.empty()) { + SDValue Chain = Chains.back(); + Chains.pop_back(); + + // For TokenFactor nodes, look at each operand and only continue up the + // chain until we find two aliases. If we've seen two aliases, assume we'll + // find more and revert to original chain since the xform is unlikely to be + // profitable. + // + // FIXME: The depth check could be made to return the last non-aliasing + // chain we found before we hit a tokenfactor rather than the original + // chain. + if (Depth > 6 || Aliases.size() == 2) { + Aliases.clear(); + Aliases.push_back(OriginalChain); + break; + } + + // Don't bother if we've been before. + if (!Visited.insert(Chain.getNode())) + continue; + + switch (Chain.getOpcode()) { + case ISD::EntryToken: + // Entry token is ideal chain operand, but handled in FindBetterChain. + break; + + case ISD::LOAD: + case ISD::STORE: { + // Get alias information for Chain. + SDValue OpPtr; + int64_t OpSize; + const Value *OpSrcValue; + int OpSrcValueOffset; + unsigned OpSrcValueAlign; + bool IsOpLoad = FindAliasInfo(Chain.getNode(), OpPtr, OpSize, + OpSrcValue, OpSrcValueOffset, + OpSrcValueAlign); + + // If chain is alias then stop here. + if (!(IsLoad && IsOpLoad) && + isAlias(Ptr, Size, SrcValue, SrcValueOffset, SrcValueAlign, + OpPtr, OpSize, OpSrcValue, OpSrcValueOffset, + OpSrcValueAlign)) { + Aliases.push_back(Chain); + } else { + // Look further up the chain. + Chains.push_back(Chain.getOperand(0)); + ++Depth; + } + break; + } + + case ISD::TokenFactor: + // We have to check each of the operands of the token factor for "small" + // token factors, so we queue them up. Adding the operands to the queue + // (stack) in reverse order maintains the original order and increases the + // likelihood that getNode will find a matching token factor (CSE.) + if (Chain.getNumOperands() > 16) { + Aliases.push_back(Chain); + break; + } + for (unsigned n = Chain.getNumOperands(); n;) + Chains.push_back(Chain.getOperand(--n)); + ++Depth; + break; + + default: + // For all other instructions we will just have to take what we can get. + Aliases.push_back(Chain); + break; + } + } +} + +/// FindBetterChain - Walk up chain skipping non-aliasing memory nodes, looking +/// for a better chain (aliasing node.) +SDValue DAGCombiner::FindBetterChain(SDNode *N, SDValue OldChain) { + SmallVector Aliases; // Ops for replacing token factor. + + // Accumulate all the aliases to this node. + GatherAllAliases(N, OldChain, Aliases); + + if (Aliases.size() == 0) { + // If no operands then chain to entry token. + return DAG.getEntryNode(); + } else if (Aliases.size() == 1) { + // If a single operand then chain to it. We don't need to revisit it. + return Aliases[0]; + } + + // Construct a custom tailored token factor. + return DAG.getNode(ISD::TokenFactor, N->getDebugLoc(), MVT::Other, + &Aliases[0], Aliases.size()); +} + +// SelectionDAG::Combine - This is the entry point for the file. +// +void SelectionDAG::Combine(CombineLevel Level, AliasAnalysis &AA, + CodeGenOpt::Level OptLevel) { + /// run - This is the main entry point to this class. + /// + DAGCombiner(*this, AA, OptLevel).Run(Level); +} diff --git a/libclamav/c++/llvm/lib/CodeGen/SelectionDAG/FastISel.cpp b/libclamav/c++/llvm/lib/CodeGen/SelectionDAG/FastISel.cpp new file mode 100644 index 000000000..5eb9ca1eb --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/SelectionDAG/FastISel.cpp @@ -0,0 +1,994 @@ +///===-- FastISel.cpp - Implementation of the FastISel class --------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the implementation of the FastISel class. +// +// "Fast" instruction selection is designed to emit very poor code quickly. +// Also, it is not designed to be able to do much lowering, so most illegal +// types (e.g. i64 on 32-bit targets) and operations are not supported. It is +// also not intended to be able to do much optimization, except in a few cases +// where doing optimizations reduces overall compile time. For example, folding +// constants into immediate fields is often done, because it's cheap and it +// reduces the number of instructions later phases have to examine. +// +// "Fast" instruction selection is able to fail gracefully and transfer +// control to the SelectionDAG selector for operations that it doesn't +// support. In many cases, this allows us to avoid duplicating a lot of +// the complicated lowering logic that SelectionDAG currently has. +// +// The intended use for "fast" instruction selection is "-O0" mode +// compilation, where the quality of the generated code is irrelevant when +// weighed against the speed at which the code can be generated. Also, +// at -O0, the LLVM optimizers are not running, and this makes the +// compile time of codegen a much higher portion of the overall compile +// time. Despite its limitations, "fast" instruction selection is able to +// handle enough code on its own to provide noticeable overall speedups +// in -O0 compiles. +// +// Basic operations are supported in a target-independent way, by reading +// the same instruction descriptions that the SelectionDAG selector reads, +// and identifying simple arithmetic operations that can be directly selected +// from simple operators. More complicated operations currently require +// target-specific code. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Function.h" +#include "llvm/GlobalVariable.h" +#include "llvm/Instructions.h" +#include "llvm/IntrinsicInst.h" +#include "llvm/LLVMContext.h" +#include "llvm/CodeGen/FastISel.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/DwarfWriter.h" +#include "llvm/Analysis/DebugInfo.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetLowering.h" +#include "llvm/Target/TargetMachine.h" +#include "SelectionDAGBuilder.h" +#include "FunctionLoweringInfo.h" +using namespace llvm; + +unsigned FastISel::getRegForValue(Value *V) { + EVT RealVT = TLI.getValueType(V->getType(), /*AllowUnknown=*/true); + // Don't handle non-simple values in FastISel. + if (!RealVT.isSimple()) + return 0; + + // Ignore illegal types. We must do this before looking up the value + // in ValueMap because Arguments are given virtual registers regardless + // of whether FastISel can handle them. + MVT VT = RealVT.getSimpleVT(); + if (!TLI.isTypeLegal(VT)) { + // Promote MVT::i1 to a legal type though, because it's common and easy. + if (VT == MVT::i1) + VT = TLI.getTypeToTransformTo(V->getContext(), VT).getSimpleVT(); + else + return 0; + } + + // Look up the value to see if we already have a register for it. We + // cache values defined by Instructions across blocks, and other values + // only locally. This is because Instructions already have the SSA + // def-dominatess-use requirement enforced. + if (ValueMap.count(V)) + return ValueMap[V]; + unsigned Reg = LocalValueMap[V]; + if (Reg != 0) + return Reg; + + if (ConstantInt *CI = dyn_cast(V)) { + if (CI->getValue().getActiveBits() <= 64) + Reg = FastEmit_i(VT, VT, ISD::Constant, CI->getZExtValue()); + } else if (isa(V)) { + Reg = TargetMaterializeAlloca(cast(V)); + } else if (isa(V)) { + // Translate this as an integer zero so that it can be + // local-CSE'd with actual integer zeros. + Reg = + getRegForValue(Constant::getNullValue(TD.getIntPtrType(V->getContext()))); + } else if (ConstantFP *CF = dyn_cast(V)) { + Reg = FastEmit_f(VT, VT, ISD::ConstantFP, CF); + + if (!Reg) { + const APFloat &Flt = CF->getValueAPF(); + EVT IntVT = TLI.getPointerTy(); + + uint64_t x[2]; + uint32_t IntBitWidth = IntVT.getSizeInBits(); + bool isExact; + (void) Flt.convertToInteger(x, IntBitWidth, /*isSigned=*/true, + APFloat::rmTowardZero, &isExact); + if (isExact) { + APInt IntVal(IntBitWidth, 2, x); + + unsigned IntegerReg = + getRegForValue(ConstantInt::get(V->getContext(), IntVal)); + if (IntegerReg != 0) + Reg = FastEmit_r(IntVT.getSimpleVT(), VT, ISD::SINT_TO_FP, IntegerReg); + } + } + } else if (ConstantExpr *CE = dyn_cast(V)) { + if (!SelectOperator(CE, CE->getOpcode())) return 0; + Reg = LocalValueMap[CE]; + } else if (isa(V)) { + Reg = createResultReg(TLI.getRegClassFor(VT)); + BuildMI(MBB, DL, TII.get(TargetInstrInfo::IMPLICIT_DEF), Reg); + } + + // If target-independent code couldn't handle the value, give target-specific + // code a try. + if (!Reg && isa(V)) + Reg = TargetMaterializeConstant(cast(V)); + + // Don't cache constant materializations in the general ValueMap. + // To do so would require tracking what uses they dominate. + if (Reg != 0) + LocalValueMap[V] = Reg; + return Reg; +} + +unsigned FastISel::lookUpRegForValue(Value *V) { + // Look up the value to see if we already have a register for it. We + // cache values defined by Instructions across blocks, and other values + // only locally. This is because Instructions already have the SSA + // def-dominatess-use requirement enforced. + if (ValueMap.count(V)) + return ValueMap[V]; + return LocalValueMap[V]; +} + +/// UpdateValueMap - Update the value map to include the new mapping for this +/// instruction, or insert an extra copy to get the result in a previous +/// determined register. +/// NOTE: This is only necessary because we might select a block that uses +/// a value before we select the block that defines the value. It might be +/// possible to fix this by selecting blocks in reverse postorder. +unsigned FastISel::UpdateValueMap(Value* I, unsigned Reg) { + if (!isa(I)) { + LocalValueMap[I] = Reg; + return Reg; + } + + unsigned &AssignedReg = ValueMap[I]; + if (AssignedReg == 0) + AssignedReg = Reg; + else if (Reg != AssignedReg) { + const TargetRegisterClass *RegClass = MRI.getRegClass(Reg); + TII.copyRegToReg(*MBB, MBB->end(), AssignedReg, + Reg, RegClass, RegClass); + } + return AssignedReg; +} + +unsigned FastISel::getRegForGEPIndex(Value *Idx) { + unsigned IdxN = getRegForValue(Idx); + if (IdxN == 0) + // Unhandled operand. Halt "fast" selection and bail. + return 0; + + // If the index is smaller or larger than intptr_t, truncate or extend it. + MVT PtrVT = TLI.getPointerTy(); + EVT IdxVT = EVT::getEVT(Idx->getType(), /*HandleUnknown=*/false); + if (IdxVT.bitsLT(PtrVT)) + IdxN = FastEmit_r(IdxVT.getSimpleVT(), PtrVT, ISD::SIGN_EXTEND, IdxN); + else if (IdxVT.bitsGT(PtrVT)) + IdxN = FastEmit_r(IdxVT.getSimpleVT(), PtrVT, ISD::TRUNCATE, IdxN); + return IdxN; +} + +/// SelectBinaryOp - Select and emit code for a binary operator instruction, +/// which has an opcode which directly corresponds to the given ISD opcode. +/// +bool FastISel::SelectBinaryOp(User *I, ISD::NodeType ISDOpcode) { + EVT VT = EVT::getEVT(I->getType(), /*HandleUnknown=*/true); + if (VT == MVT::Other || !VT.isSimple()) + // Unhandled type. Halt "fast" selection and bail. + return false; + + // We only handle legal types. For example, on x86-32 the instruction + // selector contains all of the 64-bit instructions from x86-64, + // under the assumption that i64 won't be used if the target doesn't + // support it. + if (!TLI.isTypeLegal(VT)) { + // MVT::i1 is special. Allow AND, OR, or XOR because they + // don't require additional zeroing, which makes them easy. + if (VT == MVT::i1 && + (ISDOpcode == ISD::AND || ISDOpcode == ISD::OR || + ISDOpcode == ISD::XOR)) + VT = TLI.getTypeToTransformTo(I->getContext(), VT); + else + return false; + } + + unsigned Op0 = getRegForValue(I->getOperand(0)); + if (Op0 == 0) + // Unhandled operand. Halt "fast" selection and bail. + return false; + + // Check if the second operand is a constant and handle it appropriately. + if (ConstantInt *CI = dyn_cast(I->getOperand(1))) { + unsigned ResultReg = FastEmit_ri(VT.getSimpleVT(), VT.getSimpleVT(), + ISDOpcode, Op0, CI->getZExtValue()); + if (ResultReg != 0) { + // We successfully emitted code for the given LLVM Instruction. + UpdateValueMap(I, ResultReg); + return true; + } + } + + // Check if the second operand is a constant float. + if (ConstantFP *CF = dyn_cast(I->getOperand(1))) { + unsigned ResultReg = FastEmit_rf(VT.getSimpleVT(), VT.getSimpleVT(), + ISDOpcode, Op0, CF); + if (ResultReg != 0) { + // We successfully emitted code for the given LLVM Instruction. + UpdateValueMap(I, ResultReg); + return true; + } + } + + unsigned Op1 = getRegForValue(I->getOperand(1)); + if (Op1 == 0) + // Unhandled operand. Halt "fast" selection and bail. + return false; + + // Now we have both operands in registers. Emit the instruction. + unsigned ResultReg = FastEmit_rr(VT.getSimpleVT(), VT.getSimpleVT(), + ISDOpcode, Op0, Op1); + if (ResultReg == 0) + // Target-specific code wasn't able to find a machine opcode for + // the given ISD opcode and type. Halt "fast" selection and bail. + return false; + + // We successfully emitted code for the given LLVM Instruction. + UpdateValueMap(I, ResultReg); + return true; +} + +bool FastISel::SelectGetElementPtr(User *I) { + unsigned N = getRegForValue(I->getOperand(0)); + if (N == 0) + // Unhandled operand. Halt "fast" selection and bail. + return false; + + const Type *Ty = I->getOperand(0)->getType(); + MVT VT = TLI.getPointerTy(); + for (GetElementPtrInst::op_iterator OI = I->op_begin()+1, E = I->op_end(); + OI != E; ++OI) { + Value *Idx = *OI; + if (const StructType *StTy = dyn_cast(Ty)) { + unsigned Field = cast(Idx)->getZExtValue(); + if (Field) { + // N = N + Offset + uint64_t Offs = TD.getStructLayout(StTy)->getElementOffset(Field); + // FIXME: This can be optimized by combining the add with a + // subsequent one. + N = FastEmit_ri_(VT, ISD::ADD, N, Offs, VT); + if (N == 0) + // Unhandled operand. Halt "fast" selection and bail. + return false; + } + Ty = StTy->getElementType(Field); + } else { + Ty = cast(Ty)->getElementType(); + + // If this is a constant subscript, handle it quickly. + if (ConstantInt *CI = dyn_cast(Idx)) { + if (CI->getZExtValue() == 0) continue; + uint64_t Offs = + TD.getTypeAllocSize(Ty)*cast(CI)->getSExtValue(); + N = FastEmit_ri_(VT, ISD::ADD, N, Offs, VT); + if (N == 0) + // Unhandled operand. Halt "fast" selection and bail. + return false; + continue; + } + + // N = N + Idx * ElementSize; + uint64_t ElementSize = TD.getTypeAllocSize(Ty); + unsigned IdxN = getRegForGEPIndex(Idx); + if (IdxN == 0) + // Unhandled operand. Halt "fast" selection and bail. + return false; + + if (ElementSize != 1) { + IdxN = FastEmit_ri_(VT, ISD::MUL, IdxN, ElementSize, VT); + if (IdxN == 0) + // Unhandled operand. Halt "fast" selection and bail. + return false; + } + N = FastEmit_rr(VT, VT, ISD::ADD, N, IdxN); + if (N == 0) + // Unhandled operand. Halt "fast" selection and bail. + return false; + } + } + + // We successfully emitted code for the given LLVM Instruction. + UpdateValueMap(I, N); + return true; +} + +bool FastISel::SelectCall(User *I) { + Function *F = cast(I)->getCalledFunction(); + if (!F) return false; + + unsigned IID = F->getIntrinsicID(); + switch (IID) { + default: break; + case Intrinsic::dbg_stoppoint: + case Intrinsic::dbg_region_start: + case Intrinsic::dbg_region_end: + case Intrinsic::dbg_func_start: + // FIXME - Remove this instructions once the dust settles. + return true; + case Intrinsic::dbg_declare: { + DbgDeclareInst *DI = cast(I); + if (!isValidDebugInfoIntrinsic(*DI, CodeGenOpt::None) || !DW + || !DW->ShouldEmitDwarfDebug()) + return true; + + Value *Address = DI->getAddress(); + if (BitCastInst *BCI = dyn_cast(Address)) + Address = BCI->getOperand(0); + AllocaInst *AI = dyn_cast(Address); + // Don't handle byval struct arguments or VLAs, for example. + if (!AI) break; + DenseMap::iterator SI = + StaticAllocaMap.find(AI); + if (SI == StaticAllocaMap.end()) break; // VLAs. + int FI = SI->second; + if (MMI) { + MetadataContext &TheMetadata = + DI->getParent()->getContext().getMetadata(); + unsigned MDDbgKind = TheMetadata.getMDKind("dbg"); + MDNode *Dbg = TheMetadata.getMD(MDDbgKind, DI); + MMI->setVariableDbgInfo(DI->getVariable(), FI, Dbg); + } + return true; + } + case Intrinsic::eh_exception: { + EVT VT = TLI.getValueType(I->getType()); + switch (TLI.getOperationAction(ISD::EXCEPTIONADDR, VT)) { + default: break; + case TargetLowering::Expand: { + assert(MBB->isLandingPad() && "Call to eh.exception not in landing pad!"); + unsigned Reg = TLI.getExceptionAddressRegister(); + const TargetRegisterClass *RC = TLI.getRegClassFor(VT); + unsigned ResultReg = createResultReg(RC); + bool InsertedCopy = TII.copyRegToReg(*MBB, MBB->end(), ResultReg, + Reg, RC, RC); + assert(InsertedCopy && "Can't copy address registers!"); + InsertedCopy = InsertedCopy; + UpdateValueMap(I, ResultReg); + return true; + } + } + break; + } + case Intrinsic::eh_selector: { + EVT VT = TLI.getValueType(I->getType()); + switch (TLI.getOperationAction(ISD::EHSELECTION, VT)) { + default: break; + case TargetLowering::Expand: { + if (MMI) { + if (MBB->isLandingPad()) + AddCatchInfo(*cast(I), MMI, MBB); + else { +#ifndef NDEBUG + CatchInfoLost.insert(cast(I)); +#endif + // FIXME: Mark exception selector register as live in. Hack for PR1508. + unsigned Reg = TLI.getExceptionSelectorRegister(); + if (Reg) MBB->addLiveIn(Reg); + } + + unsigned Reg = TLI.getExceptionSelectorRegister(); + EVT SrcVT = TLI.getPointerTy(); + const TargetRegisterClass *RC = TLI.getRegClassFor(SrcVT); + unsigned ResultReg = createResultReg(RC); + bool InsertedCopy = TII.copyRegToReg(*MBB, MBB->end(), ResultReg, Reg, + RC, RC); + assert(InsertedCopy && "Can't copy address registers!"); + InsertedCopy = InsertedCopy; + + // Cast the register to the type of the selector. + if (SrcVT.bitsGT(MVT::i32)) + ResultReg = FastEmit_r(SrcVT.getSimpleVT(), MVT::i32, ISD::TRUNCATE, + ResultReg); + else if (SrcVT.bitsLT(MVT::i32)) + ResultReg = FastEmit_r(SrcVT.getSimpleVT(), MVT::i32, + ISD::SIGN_EXTEND, ResultReg); + if (ResultReg == 0) + // Unhandled operand. Halt "fast" selection and bail. + return false; + + UpdateValueMap(I, ResultReg); + } else { + unsigned ResultReg = + getRegForValue(Constant::getNullValue(I->getType())); + UpdateValueMap(I, ResultReg); + } + return true; + } + } + break; + } + } + return false; +} + +bool FastISel::SelectCast(User *I, ISD::NodeType Opcode) { + EVT SrcVT = TLI.getValueType(I->getOperand(0)->getType()); + EVT DstVT = TLI.getValueType(I->getType()); + + if (SrcVT == MVT::Other || !SrcVT.isSimple() || + DstVT == MVT::Other || !DstVT.isSimple()) + // Unhandled type. Halt "fast" selection and bail. + return false; + + // Check if the destination type is legal. Or as a special case, + // it may be i1 if we're doing a truncate because that's + // easy and somewhat common. + if (!TLI.isTypeLegal(DstVT)) + if (DstVT != MVT::i1 || Opcode != ISD::TRUNCATE) + // Unhandled type. Halt "fast" selection and bail. + return false; + + // Check if the source operand is legal. Or as a special case, + // it may be i1 if we're doing zero-extension because that's + // easy and somewhat common. + if (!TLI.isTypeLegal(SrcVT)) + if (SrcVT != MVT::i1 || Opcode != ISD::ZERO_EXTEND) + // Unhandled type. Halt "fast" selection and bail. + return false; + + unsigned InputReg = getRegForValue(I->getOperand(0)); + if (!InputReg) + // Unhandled operand. Halt "fast" selection and bail. + return false; + + // If the operand is i1, arrange for the high bits in the register to be zero. + if (SrcVT == MVT::i1) { + SrcVT = TLI.getTypeToTransformTo(I->getContext(), SrcVT); + InputReg = FastEmitZExtFromI1(SrcVT.getSimpleVT(), InputReg); + if (!InputReg) + return false; + } + // If the result is i1, truncate to the target's type for i1 first. + if (DstVT == MVT::i1) + DstVT = TLI.getTypeToTransformTo(I->getContext(), DstVT); + + unsigned ResultReg = FastEmit_r(SrcVT.getSimpleVT(), + DstVT.getSimpleVT(), + Opcode, + InputReg); + if (!ResultReg) + return false; + + UpdateValueMap(I, ResultReg); + return true; +} + +bool FastISel::SelectBitCast(User *I) { + // If the bitcast doesn't change the type, just use the operand value. + if (I->getType() == I->getOperand(0)->getType()) { + unsigned Reg = getRegForValue(I->getOperand(0)); + if (Reg == 0) + return false; + UpdateValueMap(I, Reg); + return true; + } + + // Bitcasts of other values become reg-reg copies or BIT_CONVERT operators. + EVT SrcVT = TLI.getValueType(I->getOperand(0)->getType()); + EVT DstVT = TLI.getValueType(I->getType()); + + if (SrcVT == MVT::Other || !SrcVT.isSimple() || + DstVT == MVT::Other || !DstVT.isSimple() || + !TLI.isTypeLegal(SrcVT) || !TLI.isTypeLegal(DstVT)) + // Unhandled type. Halt "fast" selection and bail. + return false; + + unsigned Op0 = getRegForValue(I->getOperand(0)); + if (Op0 == 0) + // Unhandled operand. Halt "fast" selection and bail. + return false; + + // First, try to perform the bitcast by inserting a reg-reg copy. + unsigned ResultReg = 0; + if (SrcVT.getSimpleVT() == DstVT.getSimpleVT()) { + TargetRegisterClass* SrcClass = TLI.getRegClassFor(SrcVT); + TargetRegisterClass* DstClass = TLI.getRegClassFor(DstVT); + ResultReg = createResultReg(DstClass); + + bool InsertedCopy = TII.copyRegToReg(*MBB, MBB->end(), ResultReg, + Op0, DstClass, SrcClass); + if (!InsertedCopy) + ResultReg = 0; + } + + // If the reg-reg copy failed, select a BIT_CONVERT opcode. + if (!ResultReg) + ResultReg = FastEmit_r(SrcVT.getSimpleVT(), DstVT.getSimpleVT(), + ISD::BIT_CONVERT, Op0); + + if (!ResultReg) + return false; + + UpdateValueMap(I, ResultReg); + return true; +} + +bool +FastISel::SelectInstruction(Instruction *I) { + return SelectOperator(I, I->getOpcode()); +} + +/// FastEmitBranch - Emit an unconditional branch to the given block, +/// unless it is the immediate (fall-through) successor, and update +/// the CFG. +void +FastISel::FastEmitBranch(MachineBasicBlock *MSucc) { + MachineFunction::iterator NextMBB = + next(MachineFunction::iterator(MBB)); + + if (MBB->isLayoutSuccessor(MSucc)) { + // The unconditional fall-through case, which needs no instructions. + } else { + // The unconditional branch case. + TII.InsertBranch(*MBB, MSucc, NULL, SmallVector()); + } + MBB->addSuccessor(MSucc); +} + +/// SelectFNeg - Emit an FNeg operation. +/// +bool +FastISel::SelectFNeg(User *I) { + unsigned OpReg = getRegForValue(BinaryOperator::getFNegArgument(I)); + if (OpReg == 0) return false; + + // If the target has ISD::FNEG, use it. + EVT VT = TLI.getValueType(I->getType()); + unsigned ResultReg = FastEmit_r(VT.getSimpleVT(), VT.getSimpleVT(), + ISD::FNEG, OpReg); + if (ResultReg != 0) { + UpdateValueMap(I, ResultReg); + return true; + } + + // Bitcast the value to integer, twiddle the sign bit with xor, + // and then bitcast it back to floating-point. + if (VT.getSizeInBits() > 64) return false; + EVT IntVT = EVT::getIntegerVT(I->getContext(), VT.getSizeInBits()); + if (!TLI.isTypeLegal(IntVT)) + return false; + + unsigned IntReg = FastEmit_r(VT.getSimpleVT(), IntVT.getSimpleVT(), + ISD::BIT_CONVERT, OpReg); + if (IntReg == 0) + return false; + + unsigned IntResultReg = FastEmit_ri_(IntVT.getSimpleVT(), ISD::XOR, IntReg, + UINT64_C(1) << (VT.getSizeInBits()-1), + IntVT.getSimpleVT()); + if (IntResultReg == 0) + return false; + + ResultReg = FastEmit_r(IntVT.getSimpleVT(), VT.getSimpleVT(), + ISD::BIT_CONVERT, IntResultReg); + if (ResultReg == 0) + return false; + + UpdateValueMap(I, ResultReg); + return true; +} + +bool +FastISel::SelectOperator(User *I, unsigned Opcode) { + switch (Opcode) { + case Instruction::Add: + return SelectBinaryOp(I, ISD::ADD); + case Instruction::FAdd: + return SelectBinaryOp(I, ISD::FADD); + case Instruction::Sub: + return SelectBinaryOp(I, ISD::SUB); + case Instruction::FSub: + // FNeg is currently represented in LLVM IR as a special case of FSub. + if (BinaryOperator::isFNeg(I)) + return SelectFNeg(I); + return SelectBinaryOp(I, ISD::FSUB); + case Instruction::Mul: + return SelectBinaryOp(I, ISD::MUL); + case Instruction::FMul: + return SelectBinaryOp(I, ISD::FMUL); + case Instruction::SDiv: + return SelectBinaryOp(I, ISD::SDIV); + case Instruction::UDiv: + return SelectBinaryOp(I, ISD::UDIV); + case Instruction::FDiv: + return SelectBinaryOp(I, ISD::FDIV); + case Instruction::SRem: + return SelectBinaryOp(I, ISD::SREM); + case Instruction::URem: + return SelectBinaryOp(I, ISD::UREM); + case Instruction::FRem: + return SelectBinaryOp(I, ISD::FREM); + case Instruction::Shl: + return SelectBinaryOp(I, ISD::SHL); + case Instruction::LShr: + return SelectBinaryOp(I, ISD::SRL); + case Instruction::AShr: + return SelectBinaryOp(I, ISD::SRA); + case Instruction::And: + return SelectBinaryOp(I, ISD::AND); + case Instruction::Or: + return SelectBinaryOp(I, ISD::OR); + case Instruction::Xor: + return SelectBinaryOp(I, ISD::XOR); + + case Instruction::GetElementPtr: + return SelectGetElementPtr(I); + + case Instruction::Br: { + BranchInst *BI = cast(I); + + if (BI->isUnconditional()) { + BasicBlock *LLVMSucc = BI->getSuccessor(0); + MachineBasicBlock *MSucc = MBBMap[LLVMSucc]; + FastEmitBranch(MSucc); + return true; + } + + // Conditional branches are not handed yet. + // Halt "fast" selection and bail. + return false; + } + + case Instruction::Unreachable: + // Nothing to emit. + return true; + + case Instruction::PHI: + // PHI nodes are already emitted. + return true; + + case Instruction::Alloca: + // FunctionLowering has the static-sized case covered. + if (StaticAllocaMap.count(cast(I))) + return true; + + // Dynamic-sized alloca is not handled yet. + return false; + + case Instruction::Call: + return SelectCall(I); + + case Instruction::BitCast: + return SelectBitCast(I); + + case Instruction::FPToSI: + return SelectCast(I, ISD::FP_TO_SINT); + case Instruction::ZExt: + return SelectCast(I, ISD::ZERO_EXTEND); + case Instruction::SExt: + return SelectCast(I, ISD::SIGN_EXTEND); + case Instruction::Trunc: + return SelectCast(I, ISD::TRUNCATE); + case Instruction::SIToFP: + return SelectCast(I, ISD::SINT_TO_FP); + + case Instruction::IntToPtr: // Deliberate fall-through. + case Instruction::PtrToInt: { + EVT SrcVT = TLI.getValueType(I->getOperand(0)->getType()); + EVT DstVT = TLI.getValueType(I->getType()); + if (DstVT.bitsGT(SrcVT)) + return SelectCast(I, ISD::ZERO_EXTEND); + if (DstVT.bitsLT(SrcVT)) + return SelectCast(I, ISD::TRUNCATE); + unsigned Reg = getRegForValue(I->getOperand(0)); + if (Reg == 0) return false; + UpdateValueMap(I, Reg); + return true; + } + + default: + // Unhandled instruction. Halt "fast" selection and bail. + return false; + } +} + +FastISel::FastISel(MachineFunction &mf, + MachineModuleInfo *mmi, + DwarfWriter *dw, + DenseMap &vm, + DenseMap &bm, + DenseMap &am +#ifndef NDEBUG + , SmallSet &cil +#endif + ) + : MBB(0), + ValueMap(vm), + MBBMap(bm), + StaticAllocaMap(am), +#ifndef NDEBUG + CatchInfoLost(cil), +#endif + MF(mf), + MMI(mmi), + DW(dw), + MRI(MF.getRegInfo()), + MFI(*MF.getFrameInfo()), + MCP(*MF.getConstantPool()), + TM(MF.getTarget()), + TD(*TM.getTargetData()), + TII(*TM.getInstrInfo()), + TLI(*TM.getTargetLowering()) { +} + +FastISel::~FastISel() {} + +unsigned FastISel::FastEmit_(MVT, MVT, + ISD::NodeType) { + return 0; +} + +unsigned FastISel::FastEmit_r(MVT, MVT, + ISD::NodeType, unsigned /*Op0*/) { + return 0; +} + +unsigned FastISel::FastEmit_rr(MVT, MVT, + ISD::NodeType, unsigned /*Op0*/, + unsigned /*Op0*/) { + return 0; +} + +unsigned FastISel::FastEmit_i(MVT, MVT, ISD::NodeType, uint64_t /*Imm*/) { + return 0; +} + +unsigned FastISel::FastEmit_f(MVT, MVT, + ISD::NodeType, ConstantFP * /*FPImm*/) { + return 0; +} + +unsigned FastISel::FastEmit_ri(MVT, MVT, + ISD::NodeType, unsigned /*Op0*/, + uint64_t /*Imm*/) { + return 0; +} + +unsigned FastISel::FastEmit_rf(MVT, MVT, + ISD::NodeType, unsigned /*Op0*/, + ConstantFP * /*FPImm*/) { + return 0; +} + +unsigned FastISel::FastEmit_rri(MVT, MVT, + ISD::NodeType, + unsigned /*Op0*/, unsigned /*Op1*/, + uint64_t /*Imm*/) { + return 0; +} + +/// FastEmit_ri_ - This method is a wrapper of FastEmit_ri. It first tries +/// to emit an instruction with an immediate operand using FastEmit_ri. +/// If that fails, it materializes the immediate into a register and try +/// FastEmit_rr instead. +unsigned FastISel::FastEmit_ri_(MVT VT, ISD::NodeType Opcode, + unsigned Op0, uint64_t Imm, + MVT ImmType) { + // First check if immediate type is legal. If not, we can't use the ri form. + unsigned ResultReg = FastEmit_ri(VT, VT, Opcode, Op0, Imm); + if (ResultReg != 0) + return ResultReg; + unsigned MaterialReg = FastEmit_i(ImmType, ImmType, ISD::Constant, Imm); + if (MaterialReg == 0) + return 0; + return FastEmit_rr(VT, VT, Opcode, Op0, MaterialReg); +} + +/// FastEmit_rf_ - This method is a wrapper of FastEmit_ri. It first tries +/// to emit an instruction with a floating-point immediate operand using +/// FastEmit_rf. If that fails, it materializes the immediate into a register +/// and try FastEmit_rr instead. +unsigned FastISel::FastEmit_rf_(MVT VT, ISD::NodeType Opcode, + unsigned Op0, ConstantFP *FPImm, + MVT ImmType) { + // First check if immediate type is legal. If not, we can't use the rf form. + unsigned ResultReg = FastEmit_rf(VT, VT, Opcode, Op0, FPImm); + if (ResultReg != 0) + return ResultReg; + + // Materialize the constant in a register. + unsigned MaterialReg = FastEmit_f(ImmType, ImmType, ISD::ConstantFP, FPImm); + if (MaterialReg == 0) { + // If the target doesn't have a way to directly enter a floating-point + // value into a register, use an alternate approach. + // TODO: The current approach only supports floating-point constants + // that can be constructed by conversion from integer values. This should + // be replaced by code that creates a load from a constant-pool entry, + // which will require some target-specific work. + const APFloat &Flt = FPImm->getValueAPF(); + EVT IntVT = TLI.getPointerTy(); + + uint64_t x[2]; + uint32_t IntBitWidth = IntVT.getSizeInBits(); + bool isExact; + (void) Flt.convertToInteger(x, IntBitWidth, /*isSigned=*/true, + APFloat::rmTowardZero, &isExact); + if (!isExact) + return 0; + APInt IntVal(IntBitWidth, 2, x); + + unsigned IntegerReg = FastEmit_i(IntVT.getSimpleVT(), IntVT.getSimpleVT(), + ISD::Constant, IntVal.getZExtValue()); + if (IntegerReg == 0) + return 0; + MaterialReg = FastEmit_r(IntVT.getSimpleVT(), VT, + ISD::SINT_TO_FP, IntegerReg); + if (MaterialReg == 0) + return 0; + } + return FastEmit_rr(VT, VT, Opcode, Op0, MaterialReg); +} + +unsigned FastISel::createResultReg(const TargetRegisterClass* RC) { + return MRI.createVirtualRegister(RC); +} + +unsigned FastISel::FastEmitInst_(unsigned MachineInstOpcode, + const TargetRegisterClass* RC) { + unsigned ResultReg = createResultReg(RC); + const TargetInstrDesc &II = TII.get(MachineInstOpcode); + + BuildMI(MBB, DL, II, ResultReg); + return ResultReg; +} + +unsigned FastISel::FastEmitInst_r(unsigned MachineInstOpcode, + const TargetRegisterClass *RC, + unsigned Op0) { + unsigned ResultReg = createResultReg(RC); + const TargetInstrDesc &II = TII.get(MachineInstOpcode); + + if (II.getNumDefs() >= 1) + BuildMI(MBB, DL, II, ResultReg).addReg(Op0); + else { + BuildMI(MBB, DL, II).addReg(Op0); + bool InsertedCopy = TII.copyRegToReg(*MBB, MBB->end(), ResultReg, + II.ImplicitDefs[0], RC, RC); + if (!InsertedCopy) + ResultReg = 0; + } + + return ResultReg; +} + +unsigned FastISel::FastEmitInst_rr(unsigned MachineInstOpcode, + const TargetRegisterClass *RC, + unsigned Op0, unsigned Op1) { + unsigned ResultReg = createResultReg(RC); + const TargetInstrDesc &II = TII.get(MachineInstOpcode); + + if (II.getNumDefs() >= 1) + BuildMI(MBB, DL, II, ResultReg).addReg(Op0).addReg(Op1); + else { + BuildMI(MBB, DL, II).addReg(Op0).addReg(Op1); + bool InsertedCopy = TII.copyRegToReg(*MBB, MBB->end(), ResultReg, + II.ImplicitDefs[0], RC, RC); + if (!InsertedCopy) + ResultReg = 0; + } + return ResultReg; +} + +unsigned FastISel::FastEmitInst_ri(unsigned MachineInstOpcode, + const TargetRegisterClass *RC, + unsigned Op0, uint64_t Imm) { + unsigned ResultReg = createResultReg(RC); + const TargetInstrDesc &II = TII.get(MachineInstOpcode); + + if (II.getNumDefs() >= 1) + BuildMI(MBB, DL, II, ResultReg).addReg(Op0).addImm(Imm); + else { + BuildMI(MBB, DL, II).addReg(Op0).addImm(Imm); + bool InsertedCopy = TII.copyRegToReg(*MBB, MBB->end(), ResultReg, + II.ImplicitDefs[0], RC, RC); + if (!InsertedCopy) + ResultReg = 0; + } + return ResultReg; +} + +unsigned FastISel::FastEmitInst_rf(unsigned MachineInstOpcode, + const TargetRegisterClass *RC, + unsigned Op0, ConstantFP *FPImm) { + unsigned ResultReg = createResultReg(RC); + const TargetInstrDesc &II = TII.get(MachineInstOpcode); + + if (II.getNumDefs() >= 1) + BuildMI(MBB, DL, II, ResultReg).addReg(Op0).addFPImm(FPImm); + else { + BuildMI(MBB, DL, II).addReg(Op0).addFPImm(FPImm); + bool InsertedCopy = TII.copyRegToReg(*MBB, MBB->end(), ResultReg, + II.ImplicitDefs[0], RC, RC); + if (!InsertedCopy) + ResultReg = 0; + } + return ResultReg; +} + +unsigned FastISel::FastEmitInst_rri(unsigned MachineInstOpcode, + const TargetRegisterClass *RC, + unsigned Op0, unsigned Op1, uint64_t Imm) { + unsigned ResultReg = createResultReg(RC); + const TargetInstrDesc &II = TII.get(MachineInstOpcode); + + if (II.getNumDefs() >= 1) + BuildMI(MBB, DL, II, ResultReg).addReg(Op0).addReg(Op1).addImm(Imm); + else { + BuildMI(MBB, DL, II).addReg(Op0).addReg(Op1).addImm(Imm); + bool InsertedCopy = TII.copyRegToReg(*MBB, MBB->end(), ResultReg, + II.ImplicitDefs[0], RC, RC); + if (!InsertedCopy) + ResultReg = 0; + } + return ResultReg; +} + +unsigned FastISel::FastEmitInst_i(unsigned MachineInstOpcode, + const TargetRegisterClass *RC, + uint64_t Imm) { + unsigned ResultReg = createResultReg(RC); + const TargetInstrDesc &II = TII.get(MachineInstOpcode); + + if (II.getNumDefs() >= 1) + BuildMI(MBB, DL, II, ResultReg).addImm(Imm); + else { + BuildMI(MBB, DL, II).addImm(Imm); + bool InsertedCopy = TII.copyRegToReg(*MBB, MBB->end(), ResultReg, + II.ImplicitDefs[0], RC, RC); + if (!InsertedCopy) + ResultReg = 0; + } + return ResultReg; +} + +unsigned FastISel::FastEmitInst_extractsubreg(MVT RetVT, + unsigned Op0, uint32_t Idx) { + const TargetRegisterClass* RC = MRI.getRegClass(Op0); + + unsigned ResultReg = createResultReg(TLI.getRegClassFor(RetVT)); + const TargetInstrDesc &II = TII.get(TargetInstrInfo::EXTRACT_SUBREG); + + if (II.getNumDefs() >= 1) + BuildMI(MBB, DL, II, ResultReg).addReg(Op0).addImm(Idx); + else { + BuildMI(MBB, DL, II).addReg(Op0).addImm(Idx); + bool InsertedCopy = TII.copyRegToReg(*MBB, MBB->end(), ResultReg, + II.ImplicitDefs[0], RC, RC); + if (!InsertedCopy) + ResultReg = 0; + } + return ResultReg; +} + +/// FastEmitZExtFromI1 - Emit MachineInstrs to compute the value of Op +/// with all but the least significant bit set to zero. +unsigned FastISel::FastEmitZExtFromI1(MVT VT, unsigned Op) { + return FastEmit_ri(VT, VT, ISD::AND, Op, 1); +} diff --git a/libclamav/c++/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp b/libclamav/c++/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp new file mode 100644 index 000000000..e3b25c2a8 --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp @@ -0,0 +1,355 @@ +//===-- FunctionLoweringInfo.cpp ------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This implements routines for translating functions from LLVM IR into +// Machine IR. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "function-lowering-info" +#include "FunctionLoweringInfo.h" +#include "llvm/CallingConv.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Function.h" +#include "llvm/Instructions.h" +#include "llvm/IntrinsicInst.h" +#include "llvm/LLVMContext.h" +#include "llvm/Module.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/Analysis/DebugInfo.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetFrameInfo.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetIntrinsicInfo.h" +#include "llvm/Target/TargetLowering.h" +#include "llvm/Target/TargetOptions.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/Support/raw_ostream.h" +#include +using namespace llvm; + +/// ComputeLinearIndex - Given an LLVM IR aggregate type and a sequence +/// of insertvalue or extractvalue indices that identify a member, return +/// the linearized index of the start of the member. +/// +unsigned llvm::ComputeLinearIndex(const TargetLowering &TLI, const Type *Ty, + const unsigned *Indices, + const unsigned *IndicesEnd, + unsigned CurIndex) { + // Base case: We're done. + if (Indices && Indices == IndicesEnd) + return CurIndex; + + // Given a struct type, recursively traverse the elements. + if (const StructType *STy = dyn_cast(Ty)) { + for (StructType::element_iterator EB = STy->element_begin(), + EI = EB, + EE = STy->element_end(); + EI != EE; ++EI) { + if (Indices && *Indices == unsigned(EI - EB)) + return ComputeLinearIndex(TLI, *EI, Indices+1, IndicesEnd, CurIndex); + CurIndex = ComputeLinearIndex(TLI, *EI, 0, 0, CurIndex); + } + return CurIndex; + } + // Given an array type, recursively traverse the elements. + else if (const ArrayType *ATy = dyn_cast(Ty)) { + const Type *EltTy = ATy->getElementType(); + for (unsigned i = 0, e = ATy->getNumElements(); i != e; ++i) { + if (Indices && *Indices == i) + return ComputeLinearIndex(TLI, EltTy, Indices+1, IndicesEnd, CurIndex); + CurIndex = ComputeLinearIndex(TLI, EltTy, 0, 0, CurIndex); + } + return CurIndex; + } + // We haven't found the type we're looking for, so keep searching. + return CurIndex + 1; +} + +/// ComputeValueVTs - Given an LLVM IR type, compute a sequence of +/// EVTs that represent all the individual underlying +/// non-aggregate types that comprise it. +/// +/// 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. +/// +void llvm::ComputeValueVTs(const TargetLowering &TLI, const Type *Ty, + SmallVectorImpl &ValueVTs, + SmallVectorImpl *Offsets, + uint64_t StartingOffset) { + // Given a struct type, recursively traverse the elements. + if (const StructType *STy = dyn_cast(Ty)) { + const StructLayout *SL = TLI.getTargetData()->getStructLayout(STy); + for (StructType::element_iterator EB = STy->element_begin(), + EI = EB, + EE = STy->element_end(); + EI != EE; ++EI) + ComputeValueVTs(TLI, *EI, ValueVTs, Offsets, + StartingOffset + SL->getElementOffset(EI - EB)); + return; + } + // Given an array type, recursively traverse the elements. + if (const ArrayType *ATy = dyn_cast(Ty)) { + const Type *EltTy = ATy->getElementType(); + uint64_t EltSize = TLI.getTargetData()->getTypeAllocSize(EltTy); + for (unsigned i = 0, e = ATy->getNumElements(); i != e; ++i) + ComputeValueVTs(TLI, EltTy, ValueVTs, Offsets, + StartingOffset + i * EltSize); + return; + } + // Interpret void as zero return values. + if (Ty == Type::getVoidTy(Ty->getContext())) + return; + // Base case: we can get an EVT for this LLVM IR type. + ValueVTs.push_back(TLI.getValueType(Ty)); + if (Offsets) + Offsets->push_back(StartingOffset); +} + +/// isUsedOutsideOfDefiningBlock - Return true if this instruction is used by +/// PHI nodes or outside of the basic block that defines it, or used by a +/// switch or atomic instruction, which may expand to multiple basic blocks. +static bool isUsedOutsideOfDefiningBlock(Instruction *I) { + if (isa(I)) return true; + BasicBlock *BB = I->getParent(); + for (Value::use_iterator UI = I->use_begin(), E = I->use_end(); UI != E; ++UI) + if (cast(*UI)->getParent() != BB || isa(*UI)) + return true; + return false; +} + +/// isOnlyUsedInEntryBlock - If the specified argument is only used in the +/// entry block, return true. This includes arguments used by switches, since +/// the switch may expand into multiple basic blocks. +static bool isOnlyUsedInEntryBlock(Argument *A, bool EnableFastISel) { + // With FastISel active, we may be splitting blocks, so force creation + // of virtual registers for all non-dead arguments. + // Don't force virtual registers for byval arguments though, because + // fast-isel can't handle those in all cases. + if (EnableFastISel && !A->hasByValAttr()) + return A->use_empty(); + + BasicBlock *Entry = A->getParent()->begin(); + for (Value::use_iterator UI = A->use_begin(), E = A->use_end(); UI != E; ++UI) + if (cast(*UI)->getParent() != Entry || isa(*UI)) + return false; // Use not in entry block. + return true; +} + +FunctionLoweringInfo::FunctionLoweringInfo(TargetLowering &tli) + : TLI(tli) { +} + +void FunctionLoweringInfo::set(Function &fn, MachineFunction &mf, + bool EnableFastISel) { + Fn = &fn; + MF = &mf; + RegInfo = &MF->getRegInfo(); + + // Create a vreg for each argument register that is not dead and is used + // outside of the entry block for the function. + for (Function::arg_iterator AI = Fn->arg_begin(), E = Fn->arg_end(); + AI != E; ++AI) + if (!isOnlyUsedInEntryBlock(AI, EnableFastISel)) + InitializeRegForValue(AI); + + // Initialize the mapping of values to registers. This is only set up for + // instruction values that are used outside of the block that defines + // them. + Function::iterator BB = Fn->begin(), EB = Fn->end(); + for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ++I) + if (AllocaInst *AI = dyn_cast(I)) + if (ConstantInt *CUI = dyn_cast(AI->getArraySize())) { + const Type *Ty = AI->getAllocatedType(); + uint64_t TySize = TLI.getTargetData()->getTypeAllocSize(Ty); + unsigned Align = + std::max((unsigned)TLI.getTargetData()->getPrefTypeAlignment(Ty), + AI->getAlignment()); + + TySize *= CUI->getZExtValue(); // Get total allocated size. + if (TySize == 0) TySize = 1; // Don't create zero-sized stack objects. + StaticAllocaMap[AI] = + MF->getFrameInfo()->CreateStackObject(TySize, Align, false); + } + + for (; BB != EB; ++BB) + for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ++I) + if (!I->use_empty() && isUsedOutsideOfDefiningBlock(I)) + if (!isa(I) || + !StaticAllocaMap.count(cast(I))) + InitializeRegForValue(I); + + // Create an initial MachineBasicBlock for each LLVM BasicBlock in F. This + // also creates the initial PHI MachineInstrs, though none of the input + // operands are populated. + for (BB = Fn->begin(), EB = Fn->end(); BB != EB; ++BB) { + MachineBasicBlock *MBB = mf.CreateMachineBasicBlock(BB); + MBBMap[BB] = MBB; + MF->push_back(MBB); + + // Transfer the address-taken flag. This is necessary because there could + // be multiple MachineBasicBlocks corresponding to one BasicBlock, and only + // the first one should be marked. + if (BB->hasAddressTaken()) + MBB->setHasAddressTaken(); + + // Create Machine PHI nodes for LLVM PHI nodes, lowering them as + // appropriate. + PHINode *PN; + DebugLoc DL; + for (BasicBlock::iterator + I = BB->begin(), E = BB->end(); I != E; ++I) { + + PN = dyn_cast(I); + if (!PN || PN->use_empty()) continue; + + unsigned PHIReg = ValueMap[PN]; + assert(PHIReg && "PHI node does not have an assigned virtual register!"); + + SmallVector ValueVTs; + ComputeValueVTs(TLI, PN->getType(), ValueVTs); + for (unsigned vti = 0, vte = ValueVTs.size(); vti != vte; ++vti) { + EVT VT = ValueVTs[vti]; + unsigned NumRegisters = TLI.getNumRegisters(Fn->getContext(), VT); + const TargetInstrInfo *TII = MF->getTarget().getInstrInfo(); + for (unsigned i = 0; i != NumRegisters; ++i) + BuildMI(MBB, DL, TII->get(TargetInstrInfo::PHI), PHIReg + i); + PHIReg += NumRegisters; + } + } + } +} + +/// clear - Clear out all the function-specific state. This returns this +/// FunctionLoweringInfo to an empty state, ready to be used for a +/// different function. +void FunctionLoweringInfo::clear() { + MBBMap.clear(); + ValueMap.clear(); + StaticAllocaMap.clear(); +#ifndef NDEBUG + CatchInfoLost.clear(); + CatchInfoFound.clear(); +#endif + LiveOutRegInfo.clear(); +} + +unsigned FunctionLoweringInfo::MakeReg(EVT VT) { + return RegInfo->createVirtualRegister(TLI.getRegClassFor(VT)); +} + +/// CreateRegForValue - Allocate the appropriate number of virtual registers of +/// the correctly promoted or expanded types. Assign these registers +/// consecutive vreg numbers and return the first assigned number. +/// +/// In the case that the given value has struct or array type, this function +/// will assign registers for each member or element. +/// +unsigned FunctionLoweringInfo::CreateRegForValue(const Value *V) { + SmallVector ValueVTs; + ComputeValueVTs(TLI, V->getType(), ValueVTs); + + unsigned FirstReg = 0; + for (unsigned Value = 0, e = ValueVTs.size(); Value != e; ++Value) { + EVT ValueVT = ValueVTs[Value]; + EVT RegisterVT = TLI.getRegisterType(V->getContext(), ValueVT); + + unsigned NumRegs = TLI.getNumRegisters(V->getContext(), ValueVT); + for (unsigned i = 0; i != NumRegs; ++i) { + unsigned R = MakeReg(RegisterVT); + if (!FirstReg) FirstReg = R; + } + } + return FirstReg; +} + +/// ExtractTypeInfo - Returns the type info, possibly bitcast, encoded in V. +GlobalVariable *llvm::ExtractTypeInfo(Value *V) { + V = V->stripPointerCasts(); + GlobalVariable *GV = dyn_cast(V); + assert ((GV || isa(V)) && + "TypeInfo must be a global variable or NULL"); + return GV; +} + +/// AddCatchInfo - Extract the personality and type infos from an eh.selector +/// call, and add them to the specified machine basic block. +void llvm::AddCatchInfo(CallInst &I, MachineModuleInfo *MMI, + MachineBasicBlock *MBB) { + // Inform the MachineModuleInfo of the personality for this landing pad. + ConstantExpr *CE = cast(I.getOperand(2)); + assert(CE->getOpcode() == Instruction::BitCast && + isa(CE->getOperand(0)) && + "Personality should be a function"); + MMI->addPersonality(MBB, cast(CE->getOperand(0))); + + // Gather all the type infos for this landing pad and pass them along to + // MachineModuleInfo. + std::vector TyInfo; + unsigned N = I.getNumOperands(); + + for (unsigned i = N - 1; i > 2; --i) { + if (ConstantInt *CI = dyn_cast(I.getOperand(i))) { + unsigned FilterLength = CI->getZExtValue(); + unsigned FirstCatch = i + FilterLength + !FilterLength; + assert (FirstCatch <= N && "Invalid filter length"); + + if (FirstCatch < N) { + TyInfo.reserve(N - FirstCatch); + for (unsigned j = FirstCatch; j < N; ++j) + TyInfo.push_back(ExtractTypeInfo(I.getOperand(j))); + MMI->addCatchTypeInfo(MBB, TyInfo); + TyInfo.clear(); + } + + if (!FilterLength) { + // Cleanup. + MMI->addCleanup(MBB); + } else { + // Filter. + TyInfo.reserve(FilterLength - 1); + for (unsigned j = i + 1; j < FirstCatch; ++j) + TyInfo.push_back(ExtractTypeInfo(I.getOperand(j))); + MMI->addFilterTypeInfo(MBB, TyInfo); + TyInfo.clear(); + } + + N = i; + } + } + + if (N > 3) { + TyInfo.reserve(N - 3); + for (unsigned j = 3; j < N; ++j) + TyInfo.push_back(ExtractTypeInfo(I.getOperand(j))); + MMI->addCatchTypeInfo(MBB, TyInfo); + } +} + +void llvm::CopyCatchInfo(BasicBlock *SrcBB, BasicBlock *DestBB, + MachineModuleInfo *MMI, FunctionLoweringInfo &FLI) { + for (BasicBlock::iterator I = SrcBB->begin(), E = --SrcBB->end(); I != E; ++I) + if (EHSelectorInst *EHSel = dyn_cast(I)) { + // Apply the catch info to DestBB. + AddCatchInfo(*EHSel, MMI, FLI.MBBMap[DestBB]); +#ifndef NDEBUG + if (!FLI.MBBMap[SrcBB]->isLandingPad()) + FLI.CatchInfoFound.insert(EHSel); +#endif + } +} diff --git a/libclamav/c++/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.h b/libclamav/c++/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.h new file mode 100644 index 000000000..d851e6429 --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.h @@ -0,0 +1,151 @@ +//===-- FunctionLoweringInfo.h - Lower functions from LLVM IR to CodeGen --===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This implements routines for translating functions from LLVM IR into +// Machine IR. +// +//===----------------------------------------------------------------------===// + +#ifndef FUNCTIONLOWERINGINFO_H +#define FUNCTIONLOWERINGINFO_H + +#include "llvm/ADT/APInt.h" +#include "llvm/ADT/DenseMap.h" +#ifndef NDEBUG +#include "llvm/ADT/SmallSet.h" +#endif +#include "llvm/CodeGen/ValueTypes.h" +#include + +namespace llvm { + +class AllocaInst; +class BasicBlock; +class CallInst; +class Function; +class GlobalVariable; +class Instruction; +class MachineBasicBlock; +class MachineFunction; +class MachineModuleInfo; +class MachineRegisterInfo; +class TargetLowering; +class Value; + +//===--------------------------------------------------------------------===// +/// FunctionLoweringInfo - This contains information that is global to a +/// function that is used when lowering a region of the function. +/// +class FunctionLoweringInfo { +public: + TargetLowering &TLI; + Function *Fn; + MachineFunction *MF; + MachineRegisterInfo *RegInfo; + + /// CanLowerReturn - true iff the function's return value can be lowered to + /// registers. + bool CanLowerReturn; + + /// DemoteRegister - if CanLowerReturn is false, DemoteRegister is a vreg + /// allocated to hold a pointer to the hidden sret parameter. + unsigned DemoteRegister; + + explicit FunctionLoweringInfo(TargetLowering &TLI); + + /// set - Initialize this FunctionLoweringInfo with the given Function + /// and its associated MachineFunction. + /// + void set(Function &Fn, MachineFunction &MF, bool EnableFastISel); + + /// MBBMap - A mapping from LLVM basic blocks to their machine code entry. + DenseMap MBBMap; + + /// ValueMap - Since we emit code for the function a basic block at a time, + /// we must remember which virtual registers hold the values for + /// cross-basic-block values. + DenseMap ValueMap; + + /// StaticAllocaMap - Keep track of frame indices for fixed sized allocas in + /// the entry block. This allows the allocas to be efficiently referenced + /// anywhere in the function. + DenseMap StaticAllocaMap; + +#ifndef NDEBUG + SmallSet CatchInfoLost; + SmallSet CatchInfoFound; +#endif + + unsigned MakeReg(EVT VT); + + /// isExportedInst - Return true if the specified value is an instruction + /// exported from its block. + bool isExportedInst(const Value *V) { + return ValueMap.count(V); + } + + unsigned CreateRegForValue(const Value *V); + + unsigned InitializeRegForValue(const Value *V) { + unsigned &R = ValueMap[V]; + assert(R == 0 && "Already initialized this value register!"); + return R = CreateRegForValue(V); + } + + struct LiveOutInfo { + unsigned NumSignBits; + APInt KnownOne, KnownZero; + LiveOutInfo() : NumSignBits(0), KnownOne(1, 0), KnownZero(1, 0) {} + }; + + /// LiveOutRegInfo - Information about live out vregs, indexed by their + /// register number offset by 'FirstVirtualRegister'. + std::vector LiveOutRegInfo; + + /// clear - Clear out all the function-specific state. This returns this + /// FunctionLoweringInfo to an empty state, ready to be used for a + /// different function. + void clear(); +}; + +/// ComputeLinearIndex - Given an LLVM IR aggregate type and a sequence +/// of insertvalue or extractvalue indices that identify a member, return +/// the linearized index of the start of the member. +/// +unsigned ComputeLinearIndex(const TargetLowering &TLI, const Type *Ty, + const unsigned *Indices, + const unsigned *IndicesEnd, + unsigned CurIndex = 0); + +/// ComputeValueVTs - Given an LLVM IR type, compute a sequence of +/// EVTs that represent all the individual underlying +/// non-aggregate types that comprise it. +/// +/// 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. +/// +void ComputeValueVTs(const TargetLowering &TLI, const Type *Ty, + SmallVectorImpl &ValueVTs, + SmallVectorImpl *Offsets = 0, + uint64_t StartingOffset = 0); + +/// ExtractTypeInfo - Returns the type info, possibly bitcast, encoded in V. +GlobalVariable *ExtractTypeInfo(Value *V); + +/// AddCatchInfo - Extract the personality and type infos from an eh.selector +/// call, and add them to the specified machine basic block. +void AddCatchInfo(CallInst &I, MachineModuleInfo *MMI, MachineBasicBlock *MBB); + +/// CopyCatchInfo - Copy catch information from DestBB to SrcBB. +void CopyCatchInfo(BasicBlock *SrcBB, BasicBlock *DestBB, + MachineModuleInfo *MMI, FunctionLoweringInfo &FLI); + +} // end namespace llvm + +#endif diff --git a/libclamav/c++/llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp b/libclamav/c++/llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp new file mode 100644 index 000000000..669d414ce --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp @@ -0,0 +1,702 @@ +//==--- InstrEmitter.cpp - Emit MachineInstrs for the SelectionDAG class ---==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This implements the Emit routines for the SelectionDAG class, which creates +// MachineInstrs based on the decisions of the SelectionDAG instruction +// selection. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "instr-emitter" +#include "InstrEmitter.h" +#include "llvm/CodeGen/MachineConstantPool.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetLowering.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/MathExtras.h" +using namespace llvm; + +/// CountResults - The results of target nodes have register or immediate +/// operands first, then an optional chain, and optional flag operands (which do +/// not go into the resulting MachineInstr). +unsigned InstrEmitter::CountResults(SDNode *Node) { + unsigned N = Node->getNumValues(); + while (N && Node->getValueType(N - 1) == MVT::Flag) + --N; + if (N && Node->getValueType(N - 1) == MVT::Other) + --N; // Skip over chain result. + return N; +} + +/// CountOperands - The inputs to target nodes have any actual inputs first, +/// followed by an optional chain operand, then an optional flag operand. +/// Compute the number of actual operands that will go into the resulting +/// MachineInstr. +unsigned InstrEmitter::CountOperands(SDNode *Node) { + unsigned N = Node->getNumOperands(); + while (N && Node->getOperand(N - 1).getValueType() == MVT::Flag) + --N; + if (N && Node->getOperand(N - 1).getValueType() == MVT::Other) + --N; // Ignore chain if it exists. + return N; +} + +/// EmitCopyFromReg - Generate machine code for an CopyFromReg node or an +/// implicit physical register output. +void InstrEmitter:: +EmitCopyFromReg(SDNode *Node, unsigned ResNo, bool IsClone, bool IsCloned, + unsigned SrcReg, DenseMap &VRBaseMap) { + unsigned VRBase = 0; + if (TargetRegisterInfo::isVirtualRegister(SrcReg)) { + // Just use the input register directly! + SDValue Op(Node, ResNo); + if (IsClone) + VRBaseMap.erase(Op); + bool isNew = VRBaseMap.insert(std::make_pair(Op, SrcReg)).second; + isNew = isNew; // Silence compiler warning. + assert(isNew && "Node emitted out of order - early"); + return; + } + + // If the node is only used by a CopyToReg and the dest reg is a vreg, use + // the CopyToReg'd destination register instead of creating a new vreg. + bool MatchReg = true; + const TargetRegisterClass *UseRC = NULL; + if (!IsClone && !IsCloned) + for (SDNode::use_iterator UI = Node->use_begin(), E = Node->use_end(); + UI != E; ++UI) { + SDNode *User = *UI; + bool Match = true; + if (User->getOpcode() == ISD::CopyToReg && + User->getOperand(2).getNode() == Node && + User->getOperand(2).getResNo() == ResNo) { + unsigned DestReg = cast(User->getOperand(1))->getReg(); + if (TargetRegisterInfo::isVirtualRegister(DestReg)) { + VRBase = DestReg; + Match = false; + } else if (DestReg != SrcReg) + Match = false; + } else { + for (unsigned i = 0, e = User->getNumOperands(); i != e; ++i) { + SDValue Op = User->getOperand(i); + if (Op.getNode() != Node || Op.getResNo() != ResNo) + continue; + EVT VT = Node->getValueType(Op.getResNo()); + if (VT == MVT::Other || VT == MVT::Flag) + continue; + Match = false; + if (User->isMachineOpcode()) { + const TargetInstrDesc &II = TII->get(User->getMachineOpcode()); + const TargetRegisterClass *RC = 0; + if (i+II.getNumDefs() < II.getNumOperands()) + RC = II.OpInfo[i+II.getNumDefs()].getRegClass(TRI); + if (!UseRC) + UseRC = RC; + else if (RC) { + const TargetRegisterClass *ComRC = getCommonSubClass(UseRC, RC); + // If multiple uses expect disjoint register classes, we emit + // copies in AddRegisterOperand. + if (ComRC) + UseRC = ComRC; + } + } + } + } + MatchReg &= Match; + if (VRBase) + break; + } + + EVT VT = Node->getValueType(ResNo); + const TargetRegisterClass *SrcRC = 0, *DstRC = 0; + SrcRC = TRI->getPhysicalRegisterRegClass(SrcReg, VT); + + // Figure out the register class to create for the destreg. + if (VRBase) { + DstRC = MRI->getRegClass(VRBase); + } else if (UseRC) { + assert(UseRC->hasType(VT) && "Incompatible phys register def and uses!"); + DstRC = UseRC; + } else { + DstRC = TLI->getRegClassFor(VT); + } + + // If all uses are reading from the src physical register and copying the + // register is either impossible or very expensive, then don't create a copy. + if (MatchReg && SrcRC->getCopyCost() < 0) { + VRBase = SrcReg; + } else { + // Create the reg, emit the copy. + VRBase = MRI->createVirtualRegister(DstRC); + bool Emitted = TII->copyRegToReg(*MBB, InsertPos, VRBase, SrcReg, + DstRC, SrcRC); + + assert(Emitted && "Unable to issue a copy instruction!\n"); + (void) Emitted; + } + + SDValue Op(Node, ResNo); + if (IsClone) + VRBaseMap.erase(Op); + bool isNew = VRBaseMap.insert(std::make_pair(Op, VRBase)).second; + isNew = isNew; // Silence compiler warning. + assert(isNew && "Node emitted out of order - early"); +} + +/// getDstOfCopyToRegUse - If the only use of the specified result number of +/// node is a CopyToReg, return its destination register. Return 0 otherwise. +unsigned InstrEmitter::getDstOfOnlyCopyToRegUse(SDNode *Node, + unsigned ResNo) const { + if (!Node->hasOneUse()) + return 0; + + SDNode *User = *Node->use_begin(); + if (User->getOpcode() == ISD::CopyToReg && + User->getOperand(2).getNode() == Node && + User->getOperand(2).getResNo() == ResNo) { + unsigned Reg = cast(User->getOperand(1))->getReg(); + if (TargetRegisterInfo::isVirtualRegister(Reg)) + return Reg; + } + return 0; +} + +void InstrEmitter::CreateVirtualRegisters(SDNode *Node, MachineInstr *MI, + const TargetInstrDesc &II, + bool IsClone, bool IsCloned, + DenseMap &VRBaseMap) { + assert(Node->getMachineOpcode() != TargetInstrInfo::IMPLICIT_DEF && + "IMPLICIT_DEF should have been handled as a special case elsewhere!"); + + for (unsigned i = 0; i < II.getNumDefs(); ++i) { + // If the specific node value is only used by a CopyToReg and the dest reg + // is a vreg in the same register class, use the CopyToReg'd destination + // register instead of creating a new vreg. + unsigned VRBase = 0; + const TargetRegisterClass *RC = II.OpInfo[i].getRegClass(TRI); + if (II.OpInfo[i].isOptionalDef()) { + // Optional def must be a physical register. + unsigned NumResults = CountResults(Node); + VRBase = cast(Node->getOperand(i-NumResults))->getReg(); + assert(TargetRegisterInfo::isPhysicalRegister(VRBase)); + MI->addOperand(MachineOperand::CreateReg(VRBase, true)); + } + + if (!VRBase && !IsClone && !IsCloned) + for (SDNode::use_iterator UI = Node->use_begin(), E = Node->use_end(); + UI != E; ++UI) { + SDNode *User = *UI; + if (User->getOpcode() == ISD::CopyToReg && + User->getOperand(2).getNode() == Node && + User->getOperand(2).getResNo() == i) { + unsigned Reg = cast(User->getOperand(1))->getReg(); + if (TargetRegisterInfo::isVirtualRegister(Reg)) { + const TargetRegisterClass *RegRC = MRI->getRegClass(Reg); + if (RegRC == RC) { + VRBase = Reg; + MI->addOperand(MachineOperand::CreateReg(Reg, true)); + break; + } + } + } + } + + // Create the result registers for this node and add the result regs to + // the machine instruction. + if (VRBase == 0) { + assert(RC && "Isn't a register operand!"); + VRBase = MRI->createVirtualRegister(RC); + MI->addOperand(MachineOperand::CreateReg(VRBase, true)); + } + + SDValue Op(Node, i); + if (IsClone) + VRBaseMap.erase(Op); + bool isNew = VRBaseMap.insert(std::make_pair(Op, VRBase)).second; + isNew = isNew; // Silence compiler warning. + assert(isNew && "Node emitted out of order - early"); + } +} + +/// getVR - Return the virtual register corresponding to the specified result +/// of the specified node. +unsigned InstrEmitter::getVR(SDValue Op, + DenseMap &VRBaseMap) { + if (Op.isMachineOpcode() && + Op.getMachineOpcode() == TargetInstrInfo::IMPLICIT_DEF) { + // Add an IMPLICIT_DEF instruction before every use. + unsigned VReg = getDstOfOnlyCopyToRegUse(Op.getNode(), Op.getResNo()); + // IMPLICIT_DEF can produce any type of result so its TargetInstrDesc + // does not include operand register class info. + if (!VReg) { + const TargetRegisterClass *RC = TLI->getRegClassFor(Op.getValueType()); + VReg = MRI->createVirtualRegister(RC); + } + BuildMI(MBB, Op.getDebugLoc(), + TII->get(TargetInstrInfo::IMPLICIT_DEF), VReg); + return VReg; + } + + DenseMap::iterator I = VRBaseMap.find(Op); + assert(I != VRBaseMap.end() && "Node emitted out of order - late"); + return I->second; +} + + +/// AddRegisterOperand - Add the specified register as an operand to the +/// specified machine instr. Insert register copies if the register is +/// not in the required register class. +void +InstrEmitter::AddRegisterOperand(MachineInstr *MI, SDValue Op, + unsigned IIOpNum, + const TargetInstrDesc *II, + DenseMap &VRBaseMap) { + assert(Op.getValueType() != MVT::Other && + Op.getValueType() != MVT::Flag && + "Chain and flag operands should occur at end of operand list!"); + // Get/emit the operand. + unsigned VReg = getVR(Op, VRBaseMap); + assert(TargetRegisterInfo::isVirtualRegister(VReg) && "Not a vreg?"); + + const TargetInstrDesc &TID = MI->getDesc(); + bool isOptDef = IIOpNum < TID.getNumOperands() && + TID.OpInfo[IIOpNum].isOptionalDef(); + + // If the instruction requires a register in a different class, create + // a new virtual register and copy the value into it. + if (II) { + const TargetRegisterClass *SrcRC = MRI->getRegClass(VReg); + const TargetRegisterClass *DstRC = 0; + if (IIOpNum < II->getNumOperands()) + DstRC = II->OpInfo[IIOpNum].getRegClass(TRI); + assert((DstRC || (TID.isVariadic() && IIOpNum >= TID.getNumOperands())) && + "Don't have operand info for this instruction!"); + if (DstRC && SrcRC != DstRC && !SrcRC->hasSuperClass(DstRC)) { + unsigned NewVReg = MRI->createVirtualRegister(DstRC); + bool Emitted = TII->copyRegToReg(*MBB, InsertPos, NewVReg, VReg, + DstRC, SrcRC); + assert(Emitted && "Unable to issue a copy instruction!\n"); + (void) Emitted; + VReg = NewVReg; + } + } + + MI->addOperand(MachineOperand::CreateReg(VReg, isOptDef)); +} + +/// AddOperand - Add the specified operand to the specified machine instr. II +/// specifies the instruction information for the node, and IIOpNum is the +/// operand number (in the II) that we are adding. IIOpNum and II are used for +/// assertions only. +void InstrEmitter::AddOperand(MachineInstr *MI, SDValue Op, + unsigned IIOpNum, + const TargetInstrDesc *II, + DenseMap &VRBaseMap) { + if (Op.isMachineOpcode()) { + AddRegisterOperand(MI, Op, IIOpNum, II, VRBaseMap); + } else if (ConstantSDNode *C = dyn_cast(Op)) { + MI->addOperand(MachineOperand::CreateImm(C->getSExtValue())); + } else if (ConstantFPSDNode *F = dyn_cast(Op)) { + const ConstantFP *CFP = F->getConstantFPValue(); + MI->addOperand(MachineOperand::CreateFPImm(CFP)); + } else if (RegisterSDNode *R = dyn_cast(Op)) { + MI->addOperand(MachineOperand::CreateReg(R->getReg(), false)); + } else if (GlobalAddressSDNode *TGA = dyn_cast(Op)) { + MI->addOperand(MachineOperand::CreateGA(TGA->getGlobal(), TGA->getOffset(), + TGA->getTargetFlags())); + } else if (BasicBlockSDNode *BBNode = dyn_cast(Op)) { + MI->addOperand(MachineOperand::CreateMBB(BBNode->getBasicBlock())); + } else if (FrameIndexSDNode *FI = dyn_cast(Op)) { + MI->addOperand(MachineOperand::CreateFI(FI->getIndex())); + } else if (JumpTableSDNode *JT = dyn_cast(Op)) { + MI->addOperand(MachineOperand::CreateJTI(JT->getIndex(), + JT->getTargetFlags())); + } else if (ConstantPoolSDNode *CP = dyn_cast(Op)) { + int Offset = CP->getOffset(); + unsigned Align = CP->getAlignment(); + const Type *Type = CP->getType(); + // MachineConstantPool wants an explicit alignment. + if (Align == 0) { + Align = TM->getTargetData()->getPrefTypeAlignment(Type); + if (Align == 0) { + // Alignment of vector types. FIXME! + Align = TM->getTargetData()->getTypeAllocSize(Type); + } + } + + unsigned Idx; + MachineConstantPool *MCP = MF->getConstantPool(); + if (CP->isMachineConstantPoolEntry()) + Idx = MCP->getConstantPoolIndex(CP->getMachineCPVal(), Align); + else + Idx = MCP->getConstantPoolIndex(CP->getConstVal(), Align); + MI->addOperand(MachineOperand::CreateCPI(Idx, Offset, + CP->getTargetFlags())); + } else if (ExternalSymbolSDNode *ES = dyn_cast(Op)) { + MI->addOperand(MachineOperand::CreateES(ES->getSymbol(), + ES->getTargetFlags())); + } else if (BlockAddressSDNode *BA = dyn_cast(Op)) { + MI->addOperand(MachineOperand::CreateBA(BA->getBlockAddress(), + BA->getTargetFlags())); + } else { + assert(Op.getValueType() != MVT::Other && + Op.getValueType() != MVT::Flag && + "Chain and flag operands should occur at end of operand list!"); + AddRegisterOperand(MI, Op, IIOpNum, II, VRBaseMap); + } +} + +/// getSuperRegisterRegClass - Returns the register class of a superreg A whose +/// "SubIdx"'th sub-register class is the specified register class and whose +/// type matches the specified type. +static const TargetRegisterClass* +getSuperRegisterRegClass(const TargetRegisterClass *TRC, + unsigned SubIdx, EVT VT) { + // Pick the register class of the superegister for this type + for (TargetRegisterInfo::regclass_iterator I = TRC->superregclasses_begin(), + E = TRC->superregclasses_end(); I != E; ++I) + if ((*I)->hasType(VT) && (*I)->getSubRegisterRegClass(SubIdx) == TRC) + return *I; + assert(false && "Couldn't find the register class"); + return 0; +} + +/// EmitSubregNode - Generate machine code for subreg nodes. +/// +void InstrEmitter::EmitSubregNode(SDNode *Node, + DenseMap &VRBaseMap){ + unsigned VRBase = 0; + unsigned Opc = Node->getMachineOpcode(); + + // If the node is only used by a CopyToReg and the dest reg is a vreg, use + // the CopyToReg'd destination register instead of creating a new vreg. + for (SDNode::use_iterator UI = Node->use_begin(), E = Node->use_end(); + UI != E; ++UI) { + SDNode *User = *UI; + if (User->getOpcode() == ISD::CopyToReg && + User->getOperand(2).getNode() == Node) { + unsigned DestReg = cast(User->getOperand(1))->getReg(); + if (TargetRegisterInfo::isVirtualRegister(DestReg)) { + VRBase = DestReg; + break; + } + } + } + + if (Opc == TargetInstrInfo::EXTRACT_SUBREG) { + unsigned SubIdx = cast(Node->getOperand(1))->getZExtValue(); + + // Create the extract_subreg machine instruction. + MachineInstr *MI = BuildMI(*MF, Node->getDebugLoc(), + TII->get(TargetInstrInfo::EXTRACT_SUBREG)); + + // Figure out the register class to create for the destreg. + unsigned VReg = getVR(Node->getOperand(0), VRBaseMap); + const TargetRegisterClass *TRC = MRI->getRegClass(VReg); + const TargetRegisterClass *SRC = TRC->getSubRegisterRegClass(SubIdx); + assert(SRC && "Invalid subregister index in EXTRACT_SUBREG"); + + // Figure out the register class to create for the destreg. + // Note that if we're going to directly use an existing register, + // it must be precisely the required class, and not a subclass + // thereof. + if (VRBase == 0 || SRC != MRI->getRegClass(VRBase)) { + // Create the reg + assert(SRC && "Couldn't find source register class"); + VRBase = MRI->createVirtualRegister(SRC); + } + + // Add def, source, and subreg index + MI->addOperand(MachineOperand::CreateReg(VRBase, true)); + AddOperand(MI, Node->getOperand(0), 0, 0, VRBaseMap); + MI->addOperand(MachineOperand::CreateImm(SubIdx)); + MBB->insert(InsertPos, MI); + } else if (Opc == TargetInstrInfo::INSERT_SUBREG || + Opc == TargetInstrInfo::SUBREG_TO_REG) { + SDValue N0 = Node->getOperand(0); + SDValue N1 = Node->getOperand(1); + SDValue N2 = Node->getOperand(2); + unsigned SubReg = getVR(N1, VRBaseMap); + unsigned SubIdx = cast(N2)->getZExtValue(); + const TargetRegisterClass *TRC = MRI->getRegClass(SubReg); + const TargetRegisterClass *SRC = + getSuperRegisterRegClass(TRC, SubIdx, + Node->getValueType(0)); + + // Figure out the register class to create for the destreg. + // Note that if we're going to directly use an existing register, + // it must be precisely the required class, and not a subclass + // thereof. + if (VRBase == 0 || SRC != MRI->getRegClass(VRBase)) { + // Create the reg + assert(SRC && "Couldn't find source register class"); + VRBase = MRI->createVirtualRegister(SRC); + } + + // Create the insert_subreg or subreg_to_reg machine instruction. + MachineInstr *MI = BuildMI(*MF, Node->getDebugLoc(), TII->get(Opc)); + MI->addOperand(MachineOperand::CreateReg(VRBase, true)); + + // If creating a subreg_to_reg, then the first input operand + // is an implicit value immediate, otherwise it's a register + if (Opc == TargetInstrInfo::SUBREG_TO_REG) { + const ConstantSDNode *SD = cast(N0); + MI->addOperand(MachineOperand::CreateImm(SD->getZExtValue())); + } else + AddOperand(MI, N0, 0, 0, VRBaseMap); + // Add the subregster being inserted + AddOperand(MI, N1, 0, 0, VRBaseMap); + MI->addOperand(MachineOperand::CreateImm(SubIdx)); + MBB->insert(InsertPos, MI); + } else + llvm_unreachable("Node is not insert_subreg, extract_subreg, or subreg_to_reg"); + + SDValue Op(Node, 0); + bool isNew = VRBaseMap.insert(std::make_pair(Op, VRBase)).second; + isNew = isNew; // Silence compiler warning. + assert(isNew && "Node emitted out of order - early"); +} + +/// EmitCopyToRegClassNode - Generate machine code for COPY_TO_REGCLASS nodes. +/// COPY_TO_REGCLASS is just a normal copy, except that the destination +/// register is constrained to be in a particular register class. +/// +void +InstrEmitter::EmitCopyToRegClassNode(SDNode *Node, + DenseMap &VRBaseMap) { + unsigned VReg = getVR(Node->getOperand(0), VRBaseMap); + const TargetRegisterClass *SrcRC = MRI->getRegClass(VReg); + + unsigned DstRCIdx = cast(Node->getOperand(1))->getZExtValue(); + const TargetRegisterClass *DstRC = TRI->getRegClass(DstRCIdx); + + // Create the new VReg in the destination class and emit a copy. + unsigned NewVReg = MRI->createVirtualRegister(DstRC); + bool Emitted = TII->copyRegToReg(*MBB, InsertPos, NewVReg, VReg, + DstRC, SrcRC); + assert(Emitted && + "Unable to issue a copy instruction for a COPY_TO_REGCLASS node!\n"); + (void) Emitted; + + SDValue Op(Node, 0); + bool isNew = VRBaseMap.insert(std::make_pair(Op, NewVReg)).second; + isNew = isNew; // Silence compiler warning. + assert(isNew && "Node emitted out of order - early"); +} + +/// EmitNode - Generate machine code for a node and needed dependencies. +/// +void InstrEmitter::EmitNode(SDNode *Node, bool IsClone, bool IsCloned, + DenseMap &VRBaseMap, + DenseMap *EM) { + // If machine instruction + if (Node->isMachineOpcode()) { + unsigned Opc = Node->getMachineOpcode(); + + // Handle subreg insert/extract specially + if (Opc == TargetInstrInfo::EXTRACT_SUBREG || + Opc == TargetInstrInfo::INSERT_SUBREG || + Opc == TargetInstrInfo::SUBREG_TO_REG) { + EmitSubregNode(Node, VRBaseMap); + return; + } + + // Handle COPY_TO_REGCLASS specially. + if (Opc == TargetInstrInfo::COPY_TO_REGCLASS) { + EmitCopyToRegClassNode(Node, VRBaseMap); + return; + } + + if (Opc == TargetInstrInfo::IMPLICIT_DEF) + // We want a unique VR for each IMPLICIT_DEF use. + return; + + const TargetInstrDesc &II = TII->get(Opc); + unsigned NumResults = CountResults(Node); + unsigned NodeOperands = CountOperands(Node); + bool HasPhysRegOuts = (NumResults > II.getNumDefs()) && + II.getImplicitDefs() != 0; +#ifndef NDEBUG + unsigned NumMIOperands = NodeOperands + NumResults; + assert((II.getNumOperands() == NumMIOperands || + HasPhysRegOuts || II.isVariadic()) && + "#operands for dag node doesn't match .td file!"); +#endif + + // Create the new machine instruction. + MachineInstr *MI = BuildMI(*MF, Node->getDebugLoc(), II); + + // Add result register values for things that are defined by this + // instruction. + if (NumResults) + CreateVirtualRegisters(Node, MI, II, IsClone, IsCloned, VRBaseMap); + + // Emit all of the actual operands of this instruction, adding them to the + // instruction as appropriate. + bool HasOptPRefs = II.getNumDefs() > NumResults; + assert((!HasOptPRefs || !HasPhysRegOuts) && + "Unable to cope with optional defs and phys regs defs!"); + unsigned NumSkip = HasOptPRefs ? II.getNumDefs() - NumResults : 0; + for (unsigned i = NumSkip; i != NodeOperands; ++i) + AddOperand(MI, Node->getOperand(i), i-NumSkip+II.getNumDefs(), &II, + VRBaseMap); + + // Transfer all of the memory reference descriptions of this instruction. + MI->setMemRefs(cast(Node)->memoperands_begin(), + cast(Node)->memoperands_end()); + + if (II.usesCustomInsertionHook()) { + // Insert this instruction into the basic block using a target + // specific inserter which may returns a new basic block. + MBB = TLI->EmitInstrWithCustomInserter(MI, MBB, EM); + InsertPos = MBB->end(); + } else { + MBB->insert(InsertPos, MI); + } + + // Additional results must be an physical register def. + if (HasPhysRegOuts) { + for (unsigned i = II.getNumDefs(); i < NumResults; ++i) { + unsigned Reg = II.getImplicitDefs()[i - II.getNumDefs()]; + if (Node->hasAnyUseOfValue(i)) + EmitCopyFromReg(Node, i, IsClone, IsCloned, Reg, VRBaseMap); + // If there are no uses, mark the register as dead now, so that + // MachineLICM/Sink can see that it's dead. Don't do this if the + // node has a Flag value, for the benefit of targets still using + // Flag for values in physregs. + else if (Node->getValueType(Node->getNumValues()-1) != MVT::Flag) + MI->addRegisterDead(Reg, TRI); + } + } + return; + } + + switch (Node->getOpcode()) { + default: +#ifndef NDEBUG + Node->dump(); +#endif + llvm_unreachable("This target-independent node should have been selected!"); + break; + case ISD::EntryToken: + llvm_unreachable("EntryToken should have been excluded from the schedule!"); + break; + case ISD::MERGE_VALUES: + case ISD::TokenFactor: // fall thru + break; + case ISD::CopyToReg: { + unsigned SrcReg; + SDValue SrcVal = Node->getOperand(2); + if (RegisterSDNode *R = dyn_cast(SrcVal)) + SrcReg = R->getReg(); + else + SrcReg = getVR(SrcVal, VRBaseMap); + + unsigned DestReg = cast(Node->getOperand(1))->getReg(); + if (SrcReg == DestReg) // Coalesced away the copy? Ignore. + break; + + const TargetRegisterClass *SrcTRC = 0, *DstTRC = 0; + // Get the register classes of the src/dst. + if (TargetRegisterInfo::isVirtualRegister(SrcReg)) + SrcTRC = MRI->getRegClass(SrcReg); + else + SrcTRC = TRI->getPhysicalRegisterRegClass(SrcReg,SrcVal.getValueType()); + + if (TargetRegisterInfo::isVirtualRegister(DestReg)) + DstTRC = MRI->getRegClass(DestReg); + else + DstTRC = TRI->getPhysicalRegisterRegClass(DestReg, + Node->getOperand(1).getValueType()); + + bool Emitted = TII->copyRegToReg(*MBB, InsertPos, DestReg, SrcReg, + DstTRC, SrcTRC); + assert(Emitted && "Unable to issue a copy instruction!\n"); + (void) Emitted; + break; + } + case ISD::CopyFromReg: { + unsigned SrcReg = cast(Node->getOperand(1))->getReg(); + EmitCopyFromReg(Node, 0, IsClone, IsCloned, SrcReg, VRBaseMap); + break; + } + case ISD::INLINEASM: { + unsigned NumOps = Node->getNumOperands(); + if (Node->getOperand(NumOps-1).getValueType() == MVT::Flag) + --NumOps; // Ignore the flag operand. + + // Create the inline asm machine instruction. + MachineInstr *MI = BuildMI(*MF, Node->getDebugLoc(), + TII->get(TargetInstrInfo::INLINEASM)); + + // Add the asm string as an external symbol operand. + const char *AsmStr = + cast(Node->getOperand(1))->getSymbol(); + MI->addOperand(MachineOperand::CreateES(AsmStr)); + + // Add all of the operand registers to the instruction. + for (unsigned i = 2; i != NumOps;) { + unsigned Flags = + cast(Node->getOperand(i))->getZExtValue(); + unsigned NumVals = InlineAsm::getNumOperandRegisters(Flags); + + MI->addOperand(MachineOperand::CreateImm(Flags)); + ++i; // Skip the ID value. + + switch (Flags & 7) { + default: llvm_unreachable("Bad flags!"); + case 2: // Def of register. + for (; NumVals; --NumVals, ++i) { + unsigned Reg = cast(Node->getOperand(i))->getReg(); + MI->addOperand(MachineOperand::CreateReg(Reg, true)); + } + break; + case 6: // Def of earlyclobber register. + for (; NumVals; --NumVals, ++i) { + unsigned Reg = cast(Node->getOperand(i))->getReg(); + MI->addOperand(MachineOperand::CreateReg(Reg, true, false, false, + false, false, true)); + } + break; + case 1: // Use of register. + case 3: // Immediate. + case 4: // Addressing mode. + // The addressing mode has been selected, just add all of the + // operands to the machine instruction. + for (; NumVals; --NumVals, ++i) + AddOperand(MI, Node->getOperand(i), 0, 0, VRBaseMap); + break; + } + } + MBB->insert(InsertPos, MI); + break; + } + } +} + +/// InstrEmitter - Construct an InstrEmitter and set it to start inserting +/// at the given position in the given block. +InstrEmitter::InstrEmitter(MachineBasicBlock *mbb, + MachineBasicBlock::iterator insertpos) + : MF(mbb->getParent()), + MRI(&MF->getRegInfo()), + TM(&MF->getTarget()), + TII(TM->getInstrInfo()), + TRI(TM->getRegisterInfo()), + TLI(TM->getTargetLowering()), + MBB(mbb), InsertPos(insertpos) { +} diff --git a/libclamav/c++/llvm/lib/CodeGen/SelectionDAG/InstrEmitter.h b/libclamav/c++/llvm/lib/CodeGen/SelectionDAG/InstrEmitter.h new file mode 100644 index 000000000..91817e4d3 --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/SelectionDAG/InstrEmitter.h @@ -0,0 +1,119 @@ +//===---- InstrEmitter.h - Emit MachineInstrs for the SelectionDAG class ---==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This declares the Emit routines for the SelectionDAG class, which creates +// MachineInstrs based on the decisions of the SelectionDAG instruction +// selection. +// +//===----------------------------------------------------------------------===// + +#ifndef INSTREMITTER_H +#define INSTREMITTER_H + +#include "llvm/CodeGen/SelectionDAG.h" +#include "llvm/CodeGen/MachineBasicBlock.h" +#include "llvm/ADT/DenseMap.h" + +namespace llvm { + +class TargetInstrDesc; + +class InstrEmitter { + MachineFunction *MF; + MachineRegisterInfo *MRI; + const TargetMachine *TM; + const TargetInstrInfo *TII; + const TargetRegisterInfo *TRI; + const TargetLowering *TLI; + + MachineBasicBlock *MBB; + MachineBasicBlock::iterator InsertPos; + + /// EmitCopyFromReg - Generate machine code for an CopyFromReg node or an + /// implicit physical register output. + void EmitCopyFromReg(SDNode *Node, unsigned ResNo, + bool IsClone, bool IsCloned, + unsigned SrcReg, + DenseMap &VRBaseMap); + + /// getDstOfCopyToRegUse - If the only use of the specified result number of + /// node is a CopyToReg, return its destination register. Return 0 otherwise. + unsigned getDstOfOnlyCopyToRegUse(SDNode *Node, + unsigned ResNo) const; + + void CreateVirtualRegisters(SDNode *Node, MachineInstr *MI, + const TargetInstrDesc &II, + bool IsClone, bool IsCloned, + DenseMap &VRBaseMap); + + /// getVR - Return the virtual register corresponding to the specified result + /// of the specified node. + unsigned getVR(SDValue Op, + DenseMap &VRBaseMap); + + /// AddRegisterOperand - Add the specified register as an operand to the + /// specified machine instr. Insert register copies if the register is + /// not in the required register class. + void AddRegisterOperand(MachineInstr *MI, SDValue Op, + unsigned IIOpNum, + const TargetInstrDesc *II, + DenseMap &VRBaseMap); + + /// AddOperand - Add the specified operand to the specified machine instr. II + /// specifies the instruction information for the node, and IIOpNum is the + /// operand number (in the II) that we are adding. IIOpNum and II are used for + /// assertions only. + void AddOperand(MachineInstr *MI, SDValue Op, + unsigned IIOpNum, + const TargetInstrDesc *II, + DenseMap &VRBaseMap); + + /// EmitSubregNode - Generate machine code for subreg nodes. + /// + void EmitSubregNode(SDNode *Node, DenseMap &VRBaseMap); + + /// EmitCopyToRegClassNode - Generate machine code for COPY_TO_REGCLASS nodes. + /// COPY_TO_REGCLASS is just a normal copy, except that the destination + /// register is constrained to be in a particular register class. + /// + void EmitCopyToRegClassNode(SDNode *Node, + DenseMap &VRBaseMap); + +public: + /// CountResults - The results of target nodes have register or immediate + /// operands first, then an optional chain, and optional flag operands + /// (which do not go into the machine instrs.) + static unsigned CountResults(SDNode *Node); + + /// CountOperands - The inputs to target nodes have any actual inputs first, + /// followed by an optional chain operand, then flag operands. Compute + /// the number of actual operands that will go into the resulting + /// MachineInstr. + static unsigned CountOperands(SDNode *Node); + + /// EmitNode - Generate machine code for a node and needed dependencies. + /// + void EmitNode(SDNode *Node, bool IsClone, bool IsCloned, + DenseMap &VRBaseMap, + DenseMap *EM); + + /// getBlock - Return the current basic block. + MachineBasicBlock *getBlock() { return MBB; } + + /// getInsertPos - Return the current insertion position. + MachineBasicBlock::iterator getInsertPos() { return InsertPos; } + + /// InstrEmitter - Construct an InstrEmitter and set it to start inserting + /// at the given position in the given block. + InstrEmitter(MachineBasicBlock *mbb, MachineBasicBlock::iterator insertpos); +}; + +} + +#endif diff --git a/libclamav/c++/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/libclamav/c++/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp new file mode 100644 index 000000000..273dbf0d5 --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp @@ -0,0 +1,3068 @@ +//===-- LegalizeDAG.cpp - Implement SelectionDAG::Legalize ----------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the SelectionDAG::Legalize method. +// +//===----------------------------------------------------------------------===// + +#include "llvm/CodeGen/SelectionDAG.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineJumpTableInfo.h" +#include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/CodeGen/DwarfWriter.h" +#include "llvm/Analysis/DebugInfo.h" +#include "llvm/CodeGen/PseudoSourceValue.h" +#include "llvm/Target/TargetFrameInfo.h" +#include "llvm/Target/TargetLowering.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetOptions.h" +#include "llvm/Target/TargetSubtarget.h" +#include "llvm/CallingConv.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Function.h" +#include "llvm/GlobalVariable.h" +#include "llvm/LLVMContext.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/SmallPtrSet.h" +#include +using namespace llvm; + +//===----------------------------------------------------------------------===// +/// SelectionDAGLegalize - This takes an arbitrary SelectionDAG as input and +/// hacks on it until the target machine can handle it. This involves +/// eliminating value sizes the machine cannot handle (promoting small sizes to +/// large sizes or splitting up large values into small values) as well as +/// eliminating operations the machine cannot handle. +/// +/// This code also does a small amount of optimization and recognition of idioms +/// as part of its processing. For example, if a target does not support a +/// 'setcc' instruction efficiently, but does support 'brcc' instruction, this +/// will attempt merge setcc and brc instructions into brcc's. +/// +namespace { +class SelectionDAGLegalize { + TargetLowering &TLI; + SelectionDAG &DAG; + CodeGenOpt::Level OptLevel; + + // Libcall insertion helpers. + + /// LastCALLSEQ_END - This keeps track of the CALLSEQ_END node that has been + /// legalized. We use this to ensure that calls are properly serialized + /// against each other, including inserted libcalls. + SDValue LastCALLSEQ_END; + + /// IsLegalizingCall - This member is used *only* for purposes of providing + /// helpful assertions that a libcall isn't created while another call is + /// being legalized (which could lead to non-serialized call sequences). + bool IsLegalizingCall; + + enum LegalizeAction { + Legal, // The target natively supports this operation. + Promote, // This operation should be executed in a larger type. + Expand // Try to expand this to other ops, otherwise use a libcall. + }; + + /// ValueTypeActions - This is a bitvector that contains two bits for each + /// value type, where the two bits correspond to the LegalizeAction enum. + /// This can be queried with "getTypeAction(VT)". + TargetLowering::ValueTypeActionImpl ValueTypeActions; + + /// LegalizedNodes - For nodes that are of legal width, and that have more + /// than one use, this map indicates what regularized operand to use. This + /// allows us to avoid legalizing the same thing more than once. + DenseMap LegalizedNodes; + + void AddLegalizedOperand(SDValue From, SDValue To) { + LegalizedNodes.insert(std::make_pair(From, To)); + // If someone requests legalization of the new node, return itself. + if (From != To) + LegalizedNodes.insert(std::make_pair(To, To)); + } + +public: + SelectionDAGLegalize(SelectionDAG &DAG, CodeGenOpt::Level ol); + + /// getTypeAction - Return how we should legalize values of this type, either + /// it is already legal or we need to expand it into multiple registers of + /// smaller integer type, or we need to promote it to a larger type. + LegalizeAction getTypeAction(EVT VT) const { + return + (LegalizeAction)ValueTypeActions.getTypeAction(*DAG.getContext(), VT); + } + + /// isTypeLegal - Return true if this type is legal on this target. + /// + bool isTypeLegal(EVT VT) const { + return getTypeAction(VT) == Legal; + } + + void LegalizeDAG(); + +private: + /// LegalizeOp - We know that the specified value has a legal type. + /// Recursively ensure that the operands have legal types, then return the + /// result. + SDValue LegalizeOp(SDValue O); + + SDValue OptimizeFloatStore(StoreSDNode *ST); + + /// PerformInsertVectorEltInMemory - Some target cannot handle a variable + /// insertion index for the INSERT_VECTOR_ELT instruction. In this case, it + /// is necessary to spill the vector being inserted into to memory, perform + /// the insert there, and then read the result back. + SDValue PerformInsertVectorEltInMemory(SDValue Vec, SDValue Val, + SDValue Idx, DebugLoc dl); + SDValue ExpandINSERT_VECTOR_ELT(SDValue Vec, SDValue Val, + SDValue Idx, DebugLoc dl); + + /// ShuffleWithNarrowerEltType - Return a vector shuffle operation which + /// performs the same shuffe in terms of order or result bytes, but on a type + /// whose vector element type is narrower than the original shuffle type. + /// e.g. <0, 1, 0, 1> -> v8i16 <0, 1, 2, 3, 0, 1, 2, 3> + SDValue ShuffleWithNarrowerEltType(EVT NVT, EVT VT, DebugLoc dl, + SDValue N1, SDValue N2, + SmallVectorImpl &Mask) const; + + bool LegalizeAllNodesNotLeadingTo(SDNode *N, SDNode *Dest, + SmallPtrSet &NodesLeadingTo); + + void LegalizeSetCCCondCode(EVT VT, SDValue &LHS, SDValue &RHS, SDValue &CC, + DebugLoc dl); + + SDValue ExpandLibCall(RTLIB::Libcall LC, SDNode *Node, bool isSigned); + SDValue ExpandFPLibCall(SDNode *Node, RTLIB::Libcall Call_F32, + RTLIB::Libcall Call_F64, RTLIB::Libcall Call_F80, + RTLIB::Libcall Call_PPCF128); + SDValue ExpandIntLibCall(SDNode *Node, bool isSigned, + RTLIB::Libcall Call_I8, + RTLIB::Libcall Call_I16, + RTLIB::Libcall Call_I32, + RTLIB::Libcall Call_I64, + RTLIB::Libcall Call_I128); + + SDValue EmitStackConvert(SDValue SrcOp, EVT SlotVT, EVT DestVT, DebugLoc dl); + SDValue ExpandBUILD_VECTOR(SDNode *Node); + SDValue ExpandSCALAR_TO_VECTOR(SDNode *Node); + void ExpandDYNAMIC_STACKALLOC(SDNode *Node, + SmallVectorImpl &Results); + SDValue ExpandFCOPYSIGN(SDNode *Node); + SDValue ExpandLegalINT_TO_FP(bool isSigned, SDValue LegalOp, EVT DestVT, + DebugLoc dl); + SDValue PromoteLegalINT_TO_FP(SDValue LegalOp, EVT DestVT, bool isSigned, + DebugLoc dl); + SDValue PromoteLegalFP_TO_INT(SDValue LegalOp, EVT DestVT, bool isSigned, + DebugLoc dl); + + SDValue ExpandBSWAP(SDValue Op, DebugLoc dl); + SDValue ExpandBitCount(unsigned Opc, SDValue Op, DebugLoc dl); + + SDValue ExpandExtractFromVectorThroughStack(SDValue Op); + SDValue ExpandVectorBuildThroughStack(SDNode* Node); + + void ExpandNode(SDNode *Node, SmallVectorImpl &Results); + void PromoteNode(SDNode *Node, SmallVectorImpl &Results); +}; +} + +/// ShuffleWithNarrowerEltType - Return a vector shuffle operation which +/// performs the same shuffe in terms of order or result bytes, but on a type +/// whose vector element type is narrower than the original shuffle type. +/// e.g. <0, 1, 0, 1> -> v8i16 <0, 1, 2, 3, 0, 1, 2, 3> +SDValue +SelectionDAGLegalize::ShuffleWithNarrowerEltType(EVT NVT, EVT VT, DebugLoc dl, + SDValue N1, SDValue N2, + SmallVectorImpl &Mask) const { + EVT EltVT = NVT.getVectorElementType(); + unsigned NumMaskElts = VT.getVectorNumElements(); + unsigned NumDestElts = NVT.getVectorNumElements(); + unsigned NumEltsGrowth = NumDestElts / NumMaskElts; + + assert(NumEltsGrowth && "Cannot promote to vector type with fewer elts!"); + + if (NumEltsGrowth == 1) + return DAG.getVectorShuffle(NVT, dl, N1, N2, &Mask[0]); + + SmallVector NewMask; + for (unsigned i = 0; i != NumMaskElts; ++i) { + int Idx = Mask[i]; + for (unsigned j = 0; j != NumEltsGrowth; ++j) { + if (Idx < 0) + NewMask.push_back(-1); + else + NewMask.push_back(Idx * NumEltsGrowth + j); + } + } + assert(NewMask.size() == NumDestElts && "Non-integer NumEltsGrowth?"); + assert(TLI.isShuffleMaskLegal(NewMask, NVT) && "Shuffle not legal?"); + return DAG.getVectorShuffle(NVT, dl, N1, N2, &NewMask[0]); +} + +SelectionDAGLegalize::SelectionDAGLegalize(SelectionDAG &dag, + CodeGenOpt::Level ol) + : TLI(dag.getTargetLoweringInfo()), DAG(dag), OptLevel(ol), + ValueTypeActions(TLI.getValueTypeActions()) { + assert(MVT::LAST_VALUETYPE <= MVT::MAX_ALLOWED_VALUETYPE && + "Too many value types for ValueTypeActions to hold!"); +} + +void SelectionDAGLegalize::LegalizeDAG() { + LastCALLSEQ_END = DAG.getEntryNode(); + IsLegalizingCall = false; + + // The legalize process is inherently a bottom-up recursive process (users + // legalize their uses before themselves). Given infinite stack space, we + // could just start legalizing on the root and traverse the whole graph. In + // practice however, this causes us to run out of stack space on large basic + // blocks. To avoid this problem, compute an ordering of the nodes where each + // node is only legalized after all of its operands are legalized. + DAG.AssignTopologicalOrder(); + for (SelectionDAG::allnodes_iterator I = DAG.allnodes_begin(), + E = prior(DAG.allnodes_end()); I != next(E); ++I) + LegalizeOp(SDValue(I, 0)); + + // Finally, it's possible the root changed. Get the new root. + SDValue OldRoot = DAG.getRoot(); + assert(LegalizedNodes.count(OldRoot) && "Root didn't get legalized?"); + DAG.setRoot(LegalizedNodes[OldRoot]); + + LegalizedNodes.clear(); + + // Remove dead nodes now. + DAG.RemoveDeadNodes(); +} + + +/// FindCallEndFromCallStart - Given a chained node that is part of a call +/// sequence, find the CALLSEQ_END node that terminates the call sequence. +static SDNode *FindCallEndFromCallStart(SDNode *Node) { + if (Node->getOpcode() == ISD::CALLSEQ_END) + return Node; + if (Node->use_empty()) + return 0; // No CallSeqEnd + + // The chain is usually at the end. + SDValue TheChain(Node, Node->getNumValues()-1); + if (TheChain.getValueType() != MVT::Other) { + // Sometimes it's at the beginning. + TheChain = SDValue(Node, 0); + if (TheChain.getValueType() != MVT::Other) { + // Otherwise, hunt for it. + for (unsigned i = 1, e = Node->getNumValues(); i != e; ++i) + if (Node->getValueType(i) == MVT::Other) { + TheChain = SDValue(Node, i); + break; + } + + // Otherwise, we walked into a node without a chain. + if (TheChain.getValueType() != MVT::Other) + return 0; + } + } + + for (SDNode::use_iterator UI = Node->use_begin(), + E = Node->use_end(); UI != E; ++UI) { + + // Make sure to only follow users of our token chain. + SDNode *User = *UI; + for (unsigned i = 0, e = User->getNumOperands(); i != e; ++i) + if (User->getOperand(i) == TheChain) + if (SDNode *Result = FindCallEndFromCallStart(User)) + return Result; + } + return 0; +} + +/// FindCallStartFromCallEnd - Given a chained node that is part of a call +/// sequence, find the CALLSEQ_START node that initiates the call sequence. +static SDNode *FindCallStartFromCallEnd(SDNode *Node) { + assert(Node && "Didn't find callseq_start for a call??"); + if (Node->getOpcode() == ISD::CALLSEQ_START) return Node; + + assert(Node->getOperand(0).getValueType() == MVT::Other && + "Node doesn't have a token chain argument!"); + return FindCallStartFromCallEnd(Node->getOperand(0).getNode()); +} + +/// LegalizeAllNodesNotLeadingTo - Recursively walk the uses of N, looking to +/// see if any uses can reach Dest. If no dest operands can get to dest, +/// legalize them, legalize ourself, and return false, otherwise, return true. +/// +/// Keep track of the nodes we fine that actually do lead to Dest in +/// NodesLeadingTo. This avoids retraversing them exponential number of times. +/// +bool SelectionDAGLegalize::LegalizeAllNodesNotLeadingTo(SDNode *N, SDNode *Dest, + SmallPtrSet &NodesLeadingTo) { + if (N == Dest) return true; // N certainly leads to Dest :) + + // If we've already processed this node and it does lead to Dest, there is no + // need to reprocess it. + if (NodesLeadingTo.count(N)) return true; + + // If the first result of this node has been already legalized, then it cannot + // reach N. + if (LegalizedNodes.count(SDValue(N, 0))) return false; + + // Okay, this node has not already been legalized. Check and legalize all + // operands. If none lead to Dest, then we can legalize this node. + bool OperandsLeadToDest = false; + for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) + OperandsLeadToDest |= // If an operand leads to Dest, so do we. + LegalizeAllNodesNotLeadingTo(N->getOperand(i).getNode(), Dest, NodesLeadingTo); + + if (OperandsLeadToDest) { + NodesLeadingTo.insert(N); + return true; + } + + // Okay, this node looks safe, legalize it and return false. + LegalizeOp(SDValue(N, 0)); + return false; +} + +/// ExpandConstantFP - Expands the ConstantFP node to an integer constant or +/// a load from the constant pool. +static SDValue ExpandConstantFP(ConstantFPSDNode *CFP, bool UseCP, + SelectionDAG &DAG, const TargetLowering &TLI) { + bool Extend = false; + DebugLoc dl = CFP->getDebugLoc(); + + // If a FP immediate is precise when represented as a float and if the + // target can do an extending load from float to double, we put it into + // the constant pool as a float, even if it's is statically typed as a + // double. This shrinks FP constants and canonicalizes them for targets where + // an FP extending load is the same cost as a normal load (such as on the x87 + // fp stack or PPC FP unit). + EVT VT = CFP->getValueType(0); + ConstantFP *LLVMC = const_cast(CFP->getConstantFPValue()); + if (!UseCP) { + assert((VT == MVT::f64 || VT == MVT::f32) && "Invalid type expansion"); + return DAG.getConstant(LLVMC->getValueAPF().bitcastToAPInt(), + (VT == MVT::f64) ? MVT::i64 : MVT::i32); + } + + EVT OrigVT = VT; + EVT SVT = VT; + while (SVT != MVT::f32) { + SVT = (MVT::SimpleValueType)(SVT.getSimpleVT().SimpleTy - 1); + if (CFP->isValueValidForType(SVT, CFP->getValueAPF()) && + // Only do this if the target has a native EXTLOAD instruction from + // smaller type. + TLI.isLoadExtLegal(ISD::EXTLOAD, SVT) && + TLI.ShouldShrinkFPConstant(OrigVT)) { + const Type *SType = SVT.getTypeForEVT(*DAG.getContext()); + LLVMC = cast(ConstantExpr::getFPTrunc(LLVMC, SType)); + VT = SVT; + Extend = true; + } + } + + SDValue CPIdx = DAG.getConstantPool(LLVMC, TLI.getPointerTy()); + unsigned Alignment = cast(CPIdx)->getAlignment(); + if (Extend) + return DAG.getExtLoad(ISD::EXTLOAD, dl, + OrigVT, DAG.getEntryNode(), + CPIdx, PseudoSourceValue::getConstantPool(), + 0, VT, false, Alignment); + return DAG.getLoad(OrigVT, dl, DAG.getEntryNode(), CPIdx, + PseudoSourceValue::getConstantPool(), 0, false, Alignment); +} + +/// ExpandUnalignedStore - Expands an unaligned store to 2 half-size stores. +static +SDValue ExpandUnalignedStore(StoreSDNode *ST, SelectionDAG &DAG, + const TargetLowering &TLI) { + SDValue Chain = ST->getChain(); + SDValue Ptr = ST->getBasePtr(); + SDValue Val = ST->getValue(); + EVT VT = Val.getValueType(); + int Alignment = ST->getAlignment(); + int SVOffset = ST->getSrcValueOffset(); + DebugLoc dl = ST->getDebugLoc(); + if (ST->getMemoryVT().isFloatingPoint() || + ST->getMemoryVT().isVector()) { + EVT intVT = EVT::getIntegerVT(*DAG.getContext(), VT.getSizeInBits()); + if (TLI.isTypeLegal(intVT)) { + // Expand to a bitconvert of the value to the integer type of the + // same size, then a (misaligned) int store. + // FIXME: Does not handle truncating floating point stores! + SDValue Result = DAG.getNode(ISD::BIT_CONVERT, dl, intVT, Val); + return DAG.getStore(Chain, dl, Result, Ptr, ST->getSrcValue(), + SVOffset, ST->isVolatile(), Alignment); + } else { + // Do a (aligned) store to a stack slot, then copy from the stack slot + // to the final destination using (unaligned) integer loads and stores. + EVT StoredVT = ST->getMemoryVT(); + EVT RegVT = + TLI.getRegisterType(*DAG.getContext(), EVT::getIntegerVT(*DAG.getContext(), StoredVT.getSizeInBits())); + unsigned StoredBytes = StoredVT.getSizeInBits() / 8; + unsigned RegBytes = RegVT.getSizeInBits() / 8; + unsigned NumRegs = (StoredBytes + RegBytes - 1) / RegBytes; + + // Make sure the stack slot is also aligned for the register type. + SDValue StackPtr = DAG.CreateStackTemporary(StoredVT, RegVT); + + // Perform the original store, only redirected to the stack slot. + SDValue Store = DAG.getTruncStore(Chain, dl, + Val, StackPtr, NULL, 0, StoredVT); + SDValue Increment = DAG.getConstant(RegBytes, TLI.getPointerTy()); + SmallVector Stores; + unsigned Offset = 0; + + // Do all but one copies using the full register width. + for (unsigned i = 1; i < NumRegs; i++) { + // Load one integer register's worth from the stack slot. + SDValue Load = DAG.getLoad(RegVT, dl, Store, StackPtr, NULL, 0); + // Store it to the final location. Remember the store. + Stores.push_back(DAG.getStore(Load.getValue(1), dl, Load, Ptr, + ST->getSrcValue(), SVOffset + Offset, + ST->isVolatile(), + MinAlign(ST->getAlignment(), Offset))); + // Increment the pointers. + Offset += RegBytes; + StackPtr = DAG.getNode(ISD::ADD, dl, StackPtr.getValueType(), StackPtr, + Increment); + Ptr = DAG.getNode(ISD::ADD, dl, Ptr.getValueType(), Ptr, Increment); + } + + // The last store may be partial. Do a truncating store. On big-endian + // machines this requires an extending load from the stack slot to ensure + // that the bits are in the right place. + EVT MemVT = EVT::getIntegerVT(*DAG.getContext(), 8 * (StoredBytes - Offset)); + + // Load from the stack slot. + SDValue Load = DAG.getExtLoad(ISD::EXTLOAD, dl, RegVT, Store, StackPtr, + NULL, 0, MemVT); + + Stores.push_back(DAG.getTruncStore(Load.getValue(1), dl, Load, Ptr, + ST->getSrcValue(), SVOffset + Offset, + MemVT, ST->isVolatile(), + MinAlign(ST->getAlignment(), Offset))); + // The order of the stores doesn't matter - say it with a TokenFactor. + return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, &Stores[0], + Stores.size()); + } + } + assert(ST->getMemoryVT().isInteger() && + !ST->getMemoryVT().isVector() && + "Unaligned store of unknown type."); + // Get the half-size VT + EVT NewStoredVT = + (MVT::SimpleValueType)(ST->getMemoryVT().getSimpleVT().SimpleTy - 1); + int NumBits = NewStoredVT.getSizeInBits(); + int IncrementSize = NumBits / 8; + + // Divide the stored value in two parts. + SDValue ShiftAmount = DAG.getConstant(NumBits, TLI.getShiftAmountTy()); + SDValue Lo = Val; + SDValue Hi = DAG.getNode(ISD::SRL, dl, VT, Val, ShiftAmount); + + // Store the two parts + SDValue Store1, Store2; + Store1 = DAG.getTruncStore(Chain, dl, TLI.isLittleEndian()?Lo:Hi, Ptr, + ST->getSrcValue(), SVOffset, NewStoredVT, + ST->isVolatile(), Alignment); + Ptr = DAG.getNode(ISD::ADD, dl, Ptr.getValueType(), Ptr, + DAG.getConstant(IncrementSize, TLI.getPointerTy())); + Alignment = MinAlign(Alignment, IncrementSize); + Store2 = DAG.getTruncStore(Chain, dl, TLI.isLittleEndian()?Hi:Lo, Ptr, + ST->getSrcValue(), SVOffset + IncrementSize, + NewStoredVT, ST->isVolatile(), Alignment); + + return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Store1, Store2); +} + +/// ExpandUnalignedLoad - Expands an unaligned load to 2 half-size loads. +static +SDValue ExpandUnalignedLoad(LoadSDNode *LD, SelectionDAG &DAG, + const TargetLowering &TLI) { + int SVOffset = LD->getSrcValueOffset(); + SDValue Chain = LD->getChain(); + SDValue Ptr = LD->getBasePtr(); + EVT VT = LD->getValueType(0); + EVT LoadedVT = LD->getMemoryVT(); + DebugLoc dl = LD->getDebugLoc(); + if (VT.isFloatingPoint() || VT.isVector()) { + EVT intVT = EVT::getIntegerVT(*DAG.getContext(), LoadedVT.getSizeInBits()); + if (TLI.isTypeLegal(intVT)) { + // Expand to a (misaligned) integer load of the same size, + // then bitconvert to floating point or vector. + SDValue newLoad = DAG.getLoad(intVT, dl, Chain, Ptr, LD->getSrcValue(), + SVOffset, LD->isVolatile(), + LD->getAlignment()); + SDValue Result = DAG.getNode(ISD::BIT_CONVERT, dl, LoadedVT, newLoad); + if (VT.isFloatingPoint() && LoadedVT != VT) + Result = DAG.getNode(ISD::FP_EXTEND, dl, VT, Result); + + SDValue Ops[] = { Result, Chain }; + return DAG.getMergeValues(Ops, 2, dl); + } else { + // Copy the value to a (aligned) stack slot using (unaligned) integer + // loads and stores, then do a (aligned) load from the stack slot. + EVT RegVT = TLI.getRegisterType(*DAG.getContext(), intVT); + unsigned LoadedBytes = LoadedVT.getSizeInBits() / 8; + unsigned RegBytes = RegVT.getSizeInBits() / 8; + unsigned NumRegs = (LoadedBytes + RegBytes - 1) / RegBytes; + + // Make sure the stack slot is also aligned for the register type. + SDValue StackBase = DAG.CreateStackTemporary(LoadedVT, RegVT); + + SDValue Increment = DAG.getConstant(RegBytes, TLI.getPointerTy()); + SmallVector Stores; + SDValue StackPtr = StackBase; + unsigned Offset = 0; + + // Do all but one copies using the full register width. + for (unsigned i = 1; i < NumRegs; i++) { + // Load one integer register's worth from the original location. + SDValue Load = DAG.getLoad(RegVT, dl, Chain, Ptr, LD->getSrcValue(), + SVOffset + Offset, LD->isVolatile(), + MinAlign(LD->getAlignment(), Offset)); + // Follow the load with a store to the stack slot. Remember the store. + Stores.push_back(DAG.getStore(Load.getValue(1), dl, Load, StackPtr, + NULL, 0)); + // Increment the pointers. + Offset += RegBytes; + Ptr = DAG.getNode(ISD::ADD, dl, Ptr.getValueType(), Ptr, Increment); + StackPtr = DAG.getNode(ISD::ADD, dl, StackPtr.getValueType(), StackPtr, + Increment); + } + + // The last copy may be partial. Do an extending load. + EVT MemVT = EVT::getIntegerVT(*DAG.getContext(), 8 * (LoadedBytes - Offset)); + SDValue Load = DAG.getExtLoad(ISD::EXTLOAD, dl, RegVT, Chain, Ptr, + LD->getSrcValue(), SVOffset + Offset, + MemVT, LD->isVolatile(), + MinAlign(LD->getAlignment(), Offset)); + // Follow the load with a store to the stack slot. Remember the store. + // On big-endian machines this requires a truncating store to ensure + // that the bits end up in the right place. + Stores.push_back(DAG.getTruncStore(Load.getValue(1), dl, Load, StackPtr, + NULL, 0, MemVT)); + + // The order of the stores doesn't matter - say it with a TokenFactor. + SDValue TF = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, &Stores[0], + Stores.size()); + + // Finally, perform the original load only redirected to the stack slot. + Load = DAG.getExtLoad(LD->getExtensionType(), dl, VT, TF, StackBase, + NULL, 0, LoadedVT); + + // Callers expect a MERGE_VALUES node. + SDValue Ops[] = { Load, TF }; + return DAG.getMergeValues(Ops, 2, dl); + } + } + assert(LoadedVT.isInteger() && !LoadedVT.isVector() && + "Unaligned load of unsupported type."); + + // Compute the new VT that is half the size of the old one. This is an + // integer MVT. + unsigned NumBits = LoadedVT.getSizeInBits(); + EVT NewLoadedVT; + NewLoadedVT = EVT::getIntegerVT(*DAG.getContext(), NumBits/2); + NumBits >>= 1; + + unsigned Alignment = LD->getAlignment(); + unsigned IncrementSize = NumBits / 8; + ISD::LoadExtType HiExtType = LD->getExtensionType(); + + // If the original load is NON_EXTLOAD, the hi part load must be ZEXTLOAD. + if (HiExtType == ISD::NON_EXTLOAD) + HiExtType = ISD::ZEXTLOAD; + + // Load the value in two parts + SDValue Lo, Hi; + if (TLI.isLittleEndian()) { + Lo = DAG.getExtLoad(ISD::ZEXTLOAD, dl, VT, Chain, Ptr, LD->getSrcValue(), + SVOffset, NewLoadedVT, LD->isVolatile(), Alignment); + Ptr = DAG.getNode(ISD::ADD, dl, Ptr.getValueType(), Ptr, + DAG.getConstant(IncrementSize, TLI.getPointerTy())); + Hi = DAG.getExtLoad(HiExtType, dl, VT, Chain, Ptr, LD->getSrcValue(), + SVOffset + IncrementSize, NewLoadedVT, LD->isVolatile(), + MinAlign(Alignment, IncrementSize)); + } else { + Hi = DAG.getExtLoad(HiExtType, dl, VT, Chain, Ptr, LD->getSrcValue(), + SVOffset, NewLoadedVT, LD->isVolatile(), Alignment); + Ptr = DAG.getNode(ISD::ADD, dl, Ptr.getValueType(), Ptr, + DAG.getConstant(IncrementSize, TLI.getPointerTy())); + Lo = DAG.getExtLoad(ISD::ZEXTLOAD, dl, VT, Chain, Ptr, LD->getSrcValue(), + SVOffset + IncrementSize, NewLoadedVT, LD->isVolatile(), + MinAlign(Alignment, IncrementSize)); + } + + // aggregate the two parts + SDValue ShiftAmount = DAG.getConstant(NumBits, TLI.getShiftAmountTy()); + SDValue Result = DAG.getNode(ISD::SHL, dl, VT, Hi, ShiftAmount); + Result = DAG.getNode(ISD::OR, dl, VT, Result, Lo); + + SDValue TF = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Lo.getValue(1), + Hi.getValue(1)); + + SDValue Ops[] = { Result, TF }; + return DAG.getMergeValues(Ops, 2, dl); +} + +/// PerformInsertVectorEltInMemory - Some target cannot handle a variable +/// insertion index for the INSERT_VECTOR_ELT instruction. In this case, it +/// is necessary to spill the vector being inserted into to memory, perform +/// the insert there, and then read the result back. +SDValue SelectionDAGLegalize:: +PerformInsertVectorEltInMemory(SDValue Vec, SDValue Val, SDValue Idx, + DebugLoc dl) { + SDValue Tmp1 = Vec; + SDValue Tmp2 = Val; + SDValue Tmp3 = Idx; + + // If the target doesn't support this, we have to spill the input vector + // to a temporary stack slot, update the element, then reload it. This is + // badness. We could also load the value into a vector register (either + // with a "move to register" or "extload into register" instruction, then + // permute it into place, if the idx is a constant and if the idx is + // supported by the target. + EVT VT = Tmp1.getValueType(); + EVT EltVT = VT.getVectorElementType(); + EVT IdxVT = Tmp3.getValueType(); + EVT PtrVT = TLI.getPointerTy(); + SDValue StackPtr = DAG.CreateStackTemporary(VT); + + int SPFI = cast(StackPtr.getNode())->getIndex(); + + // Store the vector. + SDValue Ch = DAG.getStore(DAG.getEntryNode(), dl, Tmp1, StackPtr, + PseudoSourceValue::getFixedStack(SPFI), 0); + + // Truncate or zero extend offset to target pointer type. + unsigned CastOpc = IdxVT.bitsGT(PtrVT) ? ISD::TRUNCATE : ISD::ZERO_EXTEND; + Tmp3 = DAG.getNode(CastOpc, dl, PtrVT, Tmp3); + // Add the offset to the index. + unsigned EltSize = EltVT.getSizeInBits()/8; + Tmp3 = DAG.getNode(ISD::MUL, dl, IdxVT, Tmp3,DAG.getConstant(EltSize, IdxVT)); + SDValue StackPtr2 = DAG.getNode(ISD::ADD, dl, IdxVT, Tmp3, StackPtr); + // Store the scalar value. + Ch = DAG.getTruncStore(Ch, dl, Tmp2, StackPtr2, + PseudoSourceValue::getFixedStack(SPFI), 0, EltVT); + // Load the updated vector. + return DAG.getLoad(VT, dl, Ch, StackPtr, + PseudoSourceValue::getFixedStack(SPFI), 0); +} + + +SDValue SelectionDAGLegalize:: +ExpandINSERT_VECTOR_ELT(SDValue Vec, SDValue Val, SDValue Idx, DebugLoc dl) { + if (ConstantSDNode *InsertPos = dyn_cast(Idx)) { + // SCALAR_TO_VECTOR requires that the type of the value being inserted + // match the element type of the vector being created, except for + // integers in which case the inserted value can be over width. + EVT EltVT = Vec.getValueType().getVectorElementType(); + if (Val.getValueType() == EltVT || + (EltVT.isInteger() && Val.getValueType().bitsGE(EltVT))) { + SDValue ScVec = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, + Vec.getValueType(), Val); + + unsigned NumElts = Vec.getValueType().getVectorNumElements(); + // We generate a shuffle of InVec and ScVec, so the shuffle mask + // should be 0,1,2,3,4,5... with the appropriate element replaced with + // elt 0 of the RHS. + SmallVector ShufOps; + for (unsigned i = 0; i != NumElts; ++i) + ShufOps.push_back(i != InsertPos->getZExtValue() ? i : NumElts); + + return DAG.getVectorShuffle(Vec.getValueType(), dl, Vec, ScVec, + &ShufOps[0]); + } + } + return PerformInsertVectorEltInMemory(Vec, Val, Idx, dl); +} + +SDValue SelectionDAGLegalize::OptimizeFloatStore(StoreSDNode* ST) { + // Turn 'store float 1.0, Ptr' -> 'store int 0x12345678, Ptr' + // FIXME: We shouldn't do this for TargetConstantFP's. + // FIXME: move this to the DAG Combiner! Note that we can't regress due + // to phase ordering between legalized code and the dag combiner. This + // probably means that we need to integrate dag combiner and legalizer + // together. + // We generally can't do this one for long doubles. + SDValue Tmp1 = ST->getChain(); + SDValue Tmp2 = ST->getBasePtr(); + SDValue Tmp3; + int SVOffset = ST->getSrcValueOffset(); + unsigned Alignment = ST->getAlignment(); + bool isVolatile = ST->isVolatile(); + DebugLoc dl = ST->getDebugLoc(); + if (ConstantFPSDNode *CFP = dyn_cast(ST->getValue())) { + if (CFP->getValueType(0) == MVT::f32 && + getTypeAction(MVT::i32) == Legal) { + Tmp3 = DAG.getConstant(CFP->getValueAPF(). + bitcastToAPInt().zextOrTrunc(32), + MVT::i32); + return DAG.getStore(Tmp1, dl, Tmp3, Tmp2, ST->getSrcValue(), + SVOffset, isVolatile, Alignment); + } else if (CFP->getValueType(0) == MVT::f64) { + // If this target supports 64-bit registers, do a single 64-bit store. + if (getTypeAction(MVT::i64) == Legal) { + Tmp3 = DAG.getConstant(CFP->getValueAPF().bitcastToAPInt(). + zextOrTrunc(64), MVT::i64); + return DAG.getStore(Tmp1, dl, Tmp3, Tmp2, ST->getSrcValue(), + SVOffset, isVolatile, Alignment); + } else if (getTypeAction(MVT::i32) == Legal && !ST->isVolatile()) { + // Otherwise, if the target supports 32-bit registers, use 2 32-bit + // stores. If the target supports neither 32- nor 64-bits, this + // xform is certainly not worth it. + const APInt &IntVal =CFP->getValueAPF().bitcastToAPInt(); + SDValue Lo = DAG.getConstant(APInt(IntVal).trunc(32), MVT::i32); + SDValue Hi = DAG.getConstant(IntVal.lshr(32).trunc(32), MVT::i32); + if (TLI.isBigEndian()) std::swap(Lo, Hi); + + Lo = DAG.getStore(Tmp1, dl, Lo, Tmp2, ST->getSrcValue(), + SVOffset, isVolatile, Alignment); + Tmp2 = DAG.getNode(ISD::ADD, dl, Tmp2.getValueType(), Tmp2, + DAG.getIntPtrConstant(4)); + Hi = DAG.getStore(Tmp1, dl, Hi, Tmp2, ST->getSrcValue(), SVOffset+4, + isVolatile, MinAlign(Alignment, 4U)); + + return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Lo, Hi); + } + } + } + return SDValue(); +} + +/// LegalizeOp - We know that the specified value has a legal type, and +/// that its operands are legal. Now ensure that the operation itself +/// is legal, recursively ensuring that the operands' operations remain +/// legal. +SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { + if (Op.getOpcode() == ISD::TargetConstant) // Allow illegal target nodes. + return Op; + + SDNode *Node = Op.getNode(); + DebugLoc dl = Node->getDebugLoc(); + + for (unsigned i = 0, e = Node->getNumValues(); i != e; ++i) + assert(getTypeAction(Node->getValueType(i)) == Legal && + "Unexpected illegal type!"); + + for (unsigned i = 0, e = Node->getNumOperands(); i != e; ++i) + assert((isTypeLegal(Node->getOperand(i).getValueType()) || + Node->getOperand(i).getOpcode() == ISD::TargetConstant) && + "Unexpected illegal type!"); + + // Note that LegalizeOp may be reentered even from single-use nodes, which + // means that we always must cache transformed nodes. + DenseMap::iterator I = LegalizedNodes.find(Op); + if (I != LegalizedNodes.end()) return I->second; + + SDValue Tmp1, Tmp2, Tmp3, Tmp4; + SDValue Result = Op; + bool isCustom = false; + + // Figure out the correct action; the way to query this varies by opcode + TargetLowering::LegalizeAction Action; + bool SimpleFinishLegalizing = true; + switch (Node->getOpcode()) { + case ISD::INTRINSIC_W_CHAIN: + case ISD::INTRINSIC_WO_CHAIN: + case ISD::INTRINSIC_VOID: + case ISD::VAARG: + case ISD::STACKSAVE: + Action = TLI.getOperationAction(Node->getOpcode(), MVT::Other); + break; + case ISD::SINT_TO_FP: + case ISD::UINT_TO_FP: + case ISD::EXTRACT_VECTOR_ELT: + Action = TLI.getOperationAction(Node->getOpcode(), + Node->getOperand(0).getValueType()); + break; + case ISD::FP_ROUND_INREG: + case ISD::SIGN_EXTEND_INREG: { + EVT InnerType = cast(Node->getOperand(1))->getVT(); + Action = TLI.getOperationAction(Node->getOpcode(), InnerType); + break; + } + case ISD::SELECT_CC: + case ISD::SETCC: + case ISD::BR_CC: { + unsigned CCOperand = Node->getOpcode() == ISD::SELECT_CC ? 4 : + Node->getOpcode() == ISD::SETCC ? 2 : 1; + unsigned CompareOperand = Node->getOpcode() == ISD::BR_CC ? 2 : 0; + EVT OpVT = Node->getOperand(CompareOperand).getValueType(); + ISD::CondCode CCCode = + cast(Node->getOperand(CCOperand))->get(); + Action = TLI.getCondCodeAction(CCCode, OpVT); + if (Action == TargetLowering::Legal) { + if (Node->getOpcode() == ISD::SELECT_CC) + Action = TLI.getOperationAction(Node->getOpcode(), + Node->getValueType(0)); + else + Action = TLI.getOperationAction(Node->getOpcode(), OpVT); + } + break; + } + case ISD::LOAD: + case ISD::STORE: + // FIXME: Model these properly. LOAD and STORE are complicated, and + // STORE expects the unlegalized operand in some cases. + SimpleFinishLegalizing = false; + break; + case ISD::CALLSEQ_START: + case ISD::CALLSEQ_END: + // FIXME: This shouldn't be necessary. These nodes have special properties + // dealing with the recursive nature of legalization. Removing this + // special case should be done as part of making LegalizeDAG non-recursive. + SimpleFinishLegalizing = false; + break; + case ISD::EXTRACT_ELEMENT: + case ISD::FLT_ROUNDS_: + case ISD::SADDO: + case ISD::SSUBO: + case ISD::UADDO: + case ISD::USUBO: + case ISD::SMULO: + case ISD::UMULO: + case ISD::FPOWI: + case ISD::MERGE_VALUES: + case ISD::EH_RETURN: + case ISD::FRAME_TO_ARGS_OFFSET: + // These operations lie about being legal: when they claim to be legal, + // they should actually be expanded. + Action = TLI.getOperationAction(Node->getOpcode(), Node->getValueType(0)); + if (Action == TargetLowering::Legal) + Action = TargetLowering::Expand; + break; + case ISD::TRAMPOLINE: + case ISD::FRAMEADDR: + case ISD::RETURNADDR: + // These operations lie about being legal: when they claim to be legal, + // they should actually be custom-lowered. + Action = TLI.getOperationAction(Node->getOpcode(), Node->getValueType(0)); + if (Action == TargetLowering::Legal) + Action = TargetLowering::Custom; + break; + case ISD::BUILD_VECTOR: + // A weird case: legalization for BUILD_VECTOR never legalizes the + // operands! + // FIXME: This really sucks... changing it isn't semantically incorrect, + // but it massively pessimizes the code for floating-point BUILD_VECTORs + // because ConstantFP operands get legalized into constant pool loads + // before the BUILD_VECTOR code can see them. It doesn't usually bite, + // though, because BUILD_VECTORS usually get lowered into other nodes + // which get legalized properly. + SimpleFinishLegalizing = false; + break; + default: + if (Node->getOpcode() >= ISD::BUILTIN_OP_END) { + Action = TargetLowering::Legal; + } else { + Action = TLI.getOperationAction(Node->getOpcode(), Node->getValueType(0)); + } + break; + } + + if (SimpleFinishLegalizing) { + SmallVector Ops, ResultVals; + for (unsigned i = 0, e = Node->getNumOperands(); i != e; ++i) + Ops.push_back(LegalizeOp(Node->getOperand(i))); + switch (Node->getOpcode()) { + default: break; + case ISD::BR: + case ISD::BRIND: + case ISD::BR_JT: + case ISD::BR_CC: + case ISD::BRCOND: + // Branches tweak the chain to include LastCALLSEQ_END + Ops[0] = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Ops[0], + LastCALLSEQ_END); + Ops[0] = LegalizeOp(Ops[0]); + LastCALLSEQ_END = DAG.getEntryNode(); + break; + case ISD::SHL: + case ISD::SRL: + case ISD::SRA: + case ISD::ROTL: + case ISD::ROTR: + // Legalizing shifts/rotates requires adjusting the shift amount + // to the appropriate width. + if (!Ops[1].getValueType().isVector()) + Ops[1] = LegalizeOp(DAG.getShiftAmountOperand(Ops[1])); + break; + case ISD::SRL_PARTS: + case ISD::SRA_PARTS: + case ISD::SHL_PARTS: + // Legalizing shifts/rotates requires adjusting the shift amount + // to the appropriate width. + if (!Ops[2].getValueType().isVector()) + Ops[2] = LegalizeOp(DAG.getShiftAmountOperand(Ops[2])); + break; + } + + Result = DAG.UpdateNodeOperands(Result.getValue(0), Ops.data(), + Ops.size()); + switch (Action) { + case TargetLowering::Legal: + for (unsigned i = 0, e = Node->getNumValues(); i != e; ++i) + ResultVals.push_back(Result.getValue(i)); + break; + case TargetLowering::Custom: + // FIXME: The handling for custom lowering with multiple results is + // a complete mess. + Tmp1 = TLI.LowerOperation(Result, DAG); + if (Tmp1.getNode()) { + for (unsigned i = 0, e = Node->getNumValues(); i != e; ++i) { + if (e == 1) + ResultVals.push_back(Tmp1); + else + ResultVals.push_back(Tmp1.getValue(i)); + } + break; + } + + // FALL THROUGH + case TargetLowering::Expand: + ExpandNode(Result.getNode(), ResultVals); + break; + case TargetLowering::Promote: + PromoteNode(Result.getNode(), ResultVals); + break; + } + if (!ResultVals.empty()) { + for (unsigned i = 0, e = ResultVals.size(); i != e; ++i) { + if (ResultVals[i] != SDValue(Node, i)) + ResultVals[i] = LegalizeOp(ResultVals[i]); + AddLegalizedOperand(SDValue(Node, i), ResultVals[i]); + } + return ResultVals[Op.getResNo()]; + } + } + + switch (Node->getOpcode()) { + default: +#ifndef NDEBUG + errs() << "NODE: "; + Node->dump(&DAG); + errs() << "\n"; +#endif + llvm_unreachable("Do not know how to legalize this operator!"); + + case ISD::BUILD_VECTOR: + switch (TLI.getOperationAction(ISD::BUILD_VECTOR, Node->getValueType(0))) { + default: llvm_unreachable("This action is not supported yet!"); + case TargetLowering::Custom: + Tmp3 = TLI.LowerOperation(Result, DAG); + if (Tmp3.getNode()) { + Result = Tmp3; + break; + } + // FALLTHROUGH + case TargetLowering::Expand: + Result = ExpandBUILD_VECTOR(Result.getNode()); + break; + } + break; + case ISD::CALLSEQ_START: { + SDNode *CallEnd = FindCallEndFromCallStart(Node); + + // Recursively Legalize all of the inputs of the call end that do not lead + // to this call start. This ensures that any libcalls that need be inserted + // are inserted *before* the CALLSEQ_START. + {SmallPtrSet NodesLeadingTo; + for (unsigned i = 0, e = CallEnd->getNumOperands(); i != e; ++i) + LegalizeAllNodesNotLeadingTo(CallEnd->getOperand(i).getNode(), Node, + NodesLeadingTo); + } + + // Now that we legalized all of the inputs (which may have inserted + // libcalls) create the new CALLSEQ_START node. + Tmp1 = LegalizeOp(Node->getOperand(0)); // Legalize the chain. + + // Merge in the last call, to ensure that this call start after the last + // call ended. + if (LastCALLSEQ_END.getOpcode() != ISD::EntryToken) { + Tmp1 = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, + Tmp1, LastCALLSEQ_END); + Tmp1 = LegalizeOp(Tmp1); + } + + // Do not try to legalize the target-specific arguments (#1+). + if (Tmp1 != Node->getOperand(0)) { + SmallVector Ops(Node->op_begin(), Node->op_end()); + Ops[0] = Tmp1; + Result = DAG.UpdateNodeOperands(Result, &Ops[0], Ops.size()); + } + + // Remember that the CALLSEQ_START is legalized. + AddLegalizedOperand(Op.getValue(0), Result); + if (Node->getNumValues() == 2) // If this has a flag result, remember it. + AddLegalizedOperand(Op.getValue(1), Result.getValue(1)); + + // Now that the callseq_start and all of the non-call nodes above this call + // sequence have been legalized, legalize the call itself. During this + // process, no libcalls can/will be inserted, guaranteeing that no calls + // can overlap. + assert(!IsLegalizingCall && "Inconsistent sequentialization of calls!"); + // Note that we are selecting this call! + LastCALLSEQ_END = SDValue(CallEnd, 0); + IsLegalizingCall = true; + + // Legalize the call, starting from the CALLSEQ_END. + LegalizeOp(LastCALLSEQ_END); + assert(!IsLegalizingCall && "CALLSEQ_END should have cleared this!"); + return Result; + } + case ISD::CALLSEQ_END: + // If the CALLSEQ_START node hasn't been legalized first, legalize it. This + // will cause this node to be legalized as well as handling libcalls right. + if (LastCALLSEQ_END.getNode() != Node) { + LegalizeOp(SDValue(FindCallStartFromCallEnd(Node), 0)); + DenseMap::iterator I = LegalizedNodes.find(Op); + assert(I != LegalizedNodes.end() && + "Legalizing the call start should have legalized this node!"); + return I->second; + } + + // Otherwise, the call start has been legalized and everything is going + // according to plan. Just legalize ourselves normally here. + Tmp1 = LegalizeOp(Node->getOperand(0)); // Legalize the chain. + // Do not try to legalize the target-specific arguments (#1+), except for + // an optional flag input. + if (Node->getOperand(Node->getNumOperands()-1).getValueType() != MVT::Flag){ + if (Tmp1 != Node->getOperand(0)) { + SmallVector Ops(Node->op_begin(), Node->op_end()); + Ops[0] = Tmp1; + Result = DAG.UpdateNodeOperands(Result, &Ops[0], Ops.size()); + } + } else { + Tmp2 = LegalizeOp(Node->getOperand(Node->getNumOperands()-1)); + if (Tmp1 != Node->getOperand(0) || + Tmp2 != Node->getOperand(Node->getNumOperands()-1)) { + SmallVector Ops(Node->op_begin(), Node->op_end()); + Ops[0] = Tmp1; + Ops.back() = Tmp2; + Result = DAG.UpdateNodeOperands(Result, &Ops[0], Ops.size()); + } + } + assert(IsLegalizingCall && "Call sequence imbalance between start/end?"); + // This finishes up call legalization. + IsLegalizingCall = false; + + // If the CALLSEQ_END node has a flag, remember that we legalized it. + AddLegalizedOperand(SDValue(Node, 0), Result.getValue(0)); + if (Node->getNumValues() == 2) + AddLegalizedOperand(SDValue(Node, 1), Result.getValue(1)); + return Result.getValue(Op.getResNo()); + case ISD::LOAD: { + LoadSDNode *LD = cast(Node); + Tmp1 = LegalizeOp(LD->getChain()); // Legalize the chain. + Tmp2 = LegalizeOp(LD->getBasePtr()); // Legalize the base pointer. + + ISD::LoadExtType ExtType = LD->getExtensionType(); + if (ExtType == ISD::NON_EXTLOAD) { + EVT VT = Node->getValueType(0); + Result = DAG.UpdateNodeOperands(Result, Tmp1, Tmp2, LD->getOffset()); + Tmp3 = Result.getValue(0); + Tmp4 = Result.getValue(1); + + switch (TLI.getOperationAction(Node->getOpcode(), VT)) { + default: llvm_unreachable("This action is not supported yet!"); + case TargetLowering::Legal: + // If this is an unaligned load and the target doesn't support it, + // expand it. + if (!TLI.allowsUnalignedMemoryAccesses(LD->getMemoryVT())) { + const Type *Ty = LD->getMemoryVT().getTypeForEVT(*DAG.getContext()); + unsigned ABIAlignment = TLI.getTargetData()->getABITypeAlignment(Ty); + if (LD->getAlignment() < ABIAlignment){ + Result = ExpandUnalignedLoad(cast(Result.getNode()), + DAG, TLI); + Tmp3 = Result.getOperand(0); + Tmp4 = Result.getOperand(1); + Tmp3 = LegalizeOp(Tmp3); + Tmp4 = LegalizeOp(Tmp4); + } + } + break; + case TargetLowering::Custom: + Tmp1 = TLI.LowerOperation(Tmp3, DAG); + if (Tmp1.getNode()) { + Tmp3 = LegalizeOp(Tmp1); + Tmp4 = LegalizeOp(Tmp1.getValue(1)); + } + break; + case TargetLowering::Promote: { + // Only promote a load of vector type to another. + assert(VT.isVector() && "Cannot promote this load!"); + // Change base type to a different vector type. + EVT NVT = TLI.getTypeToPromoteTo(Node->getOpcode(), VT); + + Tmp1 = DAG.getLoad(NVT, dl, Tmp1, Tmp2, LD->getSrcValue(), + LD->getSrcValueOffset(), + LD->isVolatile(), LD->getAlignment()); + Tmp3 = LegalizeOp(DAG.getNode(ISD::BIT_CONVERT, dl, VT, Tmp1)); + Tmp4 = LegalizeOp(Tmp1.getValue(1)); + break; + } + } + // Since loads produce two values, make sure to remember that we + // legalized both of them. + AddLegalizedOperand(SDValue(Node, 0), Tmp3); + AddLegalizedOperand(SDValue(Node, 1), Tmp4); + return Op.getResNo() ? Tmp4 : Tmp3; + } else { + EVT SrcVT = LD->getMemoryVT(); + unsigned SrcWidth = SrcVT.getSizeInBits(); + int SVOffset = LD->getSrcValueOffset(); + unsigned Alignment = LD->getAlignment(); + bool isVolatile = LD->isVolatile(); + + if (SrcWidth != SrcVT.getStoreSizeInBits() && + // Some targets pretend to have an i1 loading operation, and actually + // load an i8. This trick is correct for ZEXTLOAD because the top 7 + // bits are guaranteed to be zero; it helps the optimizers understand + // that these bits are zero. It is also useful for EXTLOAD, since it + // tells the optimizers that those bits are undefined. It would be + // nice to have an effective generic way of getting these benefits... + // Until such a way is found, don't insist on promoting i1 here. + (SrcVT != MVT::i1 || + TLI.getLoadExtAction(ExtType, MVT::i1) == TargetLowering::Promote)) { + // Promote to a byte-sized load if not loading an integral number of + // bytes. For example, promote EXTLOAD:i20 -> EXTLOAD:i24. + unsigned NewWidth = SrcVT.getStoreSizeInBits(); + EVT NVT = EVT::getIntegerVT(*DAG.getContext(), NewWidth); + SDValue Ch; + + // The extra bits are guaranteed to be zero, since we stored them that + // way. A zext load from NVT thus automatically gives zext from SrcVT. + + ISD::LoadExtType NewExtType = + ExtType == ISD::ZEXTLOAD ? ISD::ZEXTLOAD : ISD::EXTLOAD; + + Result = DAG.getExtLoad(NewExtType, dl, Node->getValueType(0), + Tmp1, Tmp2, LD->getSrcValue(), SVOffset, + NVT, isVolatile, Alignment); + + Ch = Result.getValue(1); // The chain. + + if (ExtType == ISD::SEXTLOAD) + // Having the top bits zero doesn't help when sign extending. + Result = DAG.getNode(ISD::SIGN_EXTEND_INREG, dl, + Result.getValueType(), + Result, DAG.getValueType(SrcVT)); + else if (ExtType == ISD::ZEXTLOAD || NVT == Result.getValueType()) + // All the top bits are guaranteed to be zero - inform the optimizers. + Result = DAG.getNode(ISD::AssertZext, dl, + Result.getValueType(), Result, + DAG.getValueType(SrcVT)); + + Tmp1 = LegalizeOp(Result); + Tmp2 = LegalizeOp(Ch); + } else if (SrcWidth & (SrcWidth - 1)) { + // If not loading a power-of-2 number of bits, expand as two loads. + assert(SrcVT.isExtended() && !SrcVT.isVector() && + "Unsupported extload!"); + unsigned RoundWidth = 1 << Log2_32(SrcWidth); + assert(RoundWidth < SrcWidth); + unsigned ExtraWidth = SrcWidth - RoundWidth; + assert(ExtraWidth < RoundWidth); + assert(!(RoundWidth % 8) && !(ExtraWidth % 8) && + "Load size not an integral number of bytes!"); + EVT RoundVT = EVT::getIntegerVT(*DAG.getContext(), RoundWidth); + EVT ExtraVT = EVT::getIntegerVT(*DAG.getContext(), ExtraWidth); + SDValue Lo, Hi, Ch; + unsigned IncrementSize; + + if (TLI.isLittleEndian()) { + // EXTLOAD:i24 -> ZEXTLOAD:i16 | (shl EXTLOAD@+2:i8, 16) + // Load the bottom RoundWidth bits. + Lo = DAG.getExtLoad(ISD::ZEXTLOAD, dl, + Node->getValueType(0), Tmp1, Tmp2, + LD->getSrcValue(), SVOffset, RoundVT, isVolatile, + Alignment); + + // Load the remaining ExtraWidth bits. + IncrementSize = RoundWidth / 8; + Tmp2 = DAG.getNode(ISD::ADD, dl, Tmp2.getValueType(), Tmp2, + DAG.getIntPtrConstant(IncrementSize)); + Hi = DAG.getExtLoad(ExtType, dl, Node->getValueType(0), Tmp1, Tmp2, + LD->getSrcValue(), SVOffset + IncrementSize, + ExtraVT, isVolatile, + MinAlign(Alignment, IncrementSize)); + + // Build a factor node to remember that this load is independent of the + // other one. + Ch = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Lo.getValue(1), + Hi.getValue(1)); + + // Move the top bits to the right place. + Hi = DAG.getNode(ISD::SHL, dl, Hi.getValueType(), Hi, + DAG.getConstant(RoundWidth, TLI.getShiftAmountTy())); + + // Join the hi and lo parts. + Result = DAG.getNode(ISD::OR, dl, Node->getValueType(0), Lo, Hi); + } else { + // Big endian - avoid unaligned loads. + // EXTLOAD:i24 -> (shl EXTLOAD:i16, 8) | ZEXTLOAD@+2:i8 + // Load the top RoundWidth bits. + Hi = DAG.getExtLoad(ExtType, dl, Node->getValueType(0), Tmp1, Tmp2, + LD->getSrcValue(), SVOffset, RoundVT, isVolatile, + Alignment); + + // Load the remaining ExtraWidth bits. + IncrementSize = RoundWidth / 8; + Tmp2 = DAG.getNode(ISD::ADD, dl, Tmp2.getValueType(), Tmp2, + DAG.getIntPtrConstant(IncrementSize)); + Lo = DAG.getExtLoad(ISD::ZEXTLOAD, dl, + Node->getValueType(0), Tmp1, Tmp2, + LD->getSrcValue(), SVOffset + IncrementSize, + ExtraVT, isVolatile, + MinAlign(Alignment, IncrementSize)); + + // Build a factor node to remember that this load is independent of the + // other one. + Ch = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Lo.getValue(1), + Hi.getValue(1)); + + // Move the top bits to the right place. + Hi = DAG.getNode(ISD::SHL, dl, Hi.getValueType(), Hi, + DAG.getConstant(ExtraWidth, TLI.getShiftAmountTy())); + + // Join the hi and lo parts. + Result = DAG.getNode(ISD::OR, dl, Node->getValueType(0), Lo, Hi); + } + + Tmp1 = LegalizeOp(Result); + Tmp2 = LegalizeOp(Ch); + } else { + switch (TLI.getLoadExtAction(ExtType, SrcVT)) { + default: llvm_unreachable("This action is not supported yet!"); + case TargetLowering::Custom: + isCustom = true; + // FALLTHROUGH + case TargetLowering::Legal: + Result = DAG.UpdateNodeOperands(Result, Tmp1, Tmp2, LD->getOffset()); + Tmp1 = Result.getValue(0); + Tmp2 = Result.getValue(1); + + if (isCustom) { + Tmp3 = TLI.LowerOperation(Result, DAG); + if (Tmp3.getNode()) { + Tmp1 = LegalizeOp(Tmp3); + Tmp2 = LegalizeOp(Tmp3.getValue(1)); + } + } else { + // If this is an unaligned load and the target doesn't support it, + // expand it. + if (!TLI.allowsUnalignedMemoryAccesses(LD->getMemoryVT())) { + const Type *Ty = LD->getMemoryVT().getTypeForEVT(*DAG.getContext()); + unsigned ABIAlignment = TLI.getTargetData()->getABITypeAlignment(Ty); + if (LD->getAlignment() < ABIAlignment){ + Result = ExpandUnalignedLoad(cast(Result.getNode()), + DAG, TLI); + Tmp1 = Result.getOperand(0); + Tmp2 = Result.getOperand(1); + Tmp1 = LegalizeOp(Tmp1); + Tmp2 = LegalizeOp(Tmp2); + } + } + } + break; + case TargetLowering::Expand: + // f64 = EXTLOAD f32 should expand to LOAD, FP_EXTEND + // f128 = EXTLOAD {f32,f64} too + if ((SrcVT == MVT::f32 && (Node->getValueType(0) == MVT::f64 || + Node->getValueType(0) == MVT::f128)) || + (SrcVT == MVT::f64 && Node->getValueType(0) == MVT::f128)) { + SDValue Load = DAG.getLoad(SrcVT, dl, Tmp1, Tmp2, LD->getSrcValue(), + LD->getSrcValueOffset(), + LD->isVolatile(), LD->getAlignment()); + Result = DAG.getNode(ISD::FP_EXTEND, dl, + Node->getValueType(0), Load); + Tmp1 = LegalizeOp(Result); // Relegalize new nodes. + Tmp2 = LegalizeOp(Load.getValue(1)); + break; + } + assert(ExtType != ISD::EXTLOAD &&"EXTLOAD should always be supported!"); + // Turn the unsupported load into an EXTLOAD followed by an explicit + // zero/sign extend inreg. + Result = DAG.getExtLoad(ISD::EXTLOAD, dl, Node->getValueType(0), + Tmp1, Tmp2, LD->getSrcValue(), + LD->getSrcValueOffset(), SrcVT, + LD->isVolatile(), LD->getAlignment()); + SDValue ValRes; + if (ExtType == ISD::SEXTLOAD) + ValRes = DAG.getNode(ISD::SIGN_EXTEND_INREG, dl, + Result.getValueType(), + Result, DAG.getValueType(SrcVT)); + else + ValRes = DAG.getZeroExtendInReg(Result, dl, SrcVT); + Tmp1 = LegalizeOp(ValRes); // Relegalize new nodes. + Tmp2 = LegalizeOp(Result.getValue(1)); // Relegalize new nodes. + break; + } + } + + // Since loads produce two values, make sure to remember that we legalized + // both of them. + AddLegalizedOperand(SDValue(Node, 0), Tmp1); + AddLegalizedOperand(SDValue(Node, 1), Tmp2); + return Op.getResNo() ? Tmp2 : Tmp1; + } + } + case ISD::STORE: { + StoreSDNode *ST = cast(Node); + Tmp1 = LegalizeOp(ST->getChain()); // Legalize the chain. + Tmp2 = LegalizeOp(ST->getBasePtr()); // Legalize the pointer. + int SVOffset = ST->getSrcValueOffset(); + unsigned Alignment = ST->getAlignment(); + bool isVolatile = ST->isVolatile(); + + if (!ST->isTruncatingStore()) { + if (SDNode *OptStore = OptimizeFloatStore(ST).getNode()) { + Result = SDValue(OptStore, 0); + break; + } + + { + Tmp3 = LegalizeOp(ST->getValue()); + Result = DAG.UpdateNodeOperands(Result, Tmp1, Tmp3, Tmp2, + ST->getOffset()); + + EVT VT = Tmp3.getValueType(); + switch (TLI.getOperationAction(ISD::STORE, VT)) { + default: llvm_unreachable("This action is not supported yet!"); + case TargetLowering::Legal: + // If this is an unaligned store and the target doesn't support it, + // expand it. + if (!TLI.allowsUnalignedMemoryAccesses(ST->getMemoryVT())) { + const Type *Ty = ST->getMemoryVT().getTypeForEVT(*DAG.getContext()); + unsigned ABIAlignment = TLI.getTargetData()->getABITypeAlignment(Ty); + if (ST->getAlignment() < ABIAlignment) + Result = ExpandUnalignedStore(cast(Result.getNode()), + DAG, TLI); + } + break; + case TargetLowering::Custom: + Tmp1 = TLI.LowerOperation(Result, DAG); + if (Tmp1.getNode()) Result = Tmp1; + break; + case TargetLowering::Promote: + assert(VT.isVector() && "Unknown legal promote case!"); + Tmp3 = DAG.getNode(ISD::BIT_CONVERT, dl, + TLI.getTypeToPromoteTo(ISD::STORE, VT), Tmp3); + Result = DAG.getStore(Tmp1, dl, Tmp3, Tmp2, + ST->getSrcValue(), SVOffset, isVolatile, + Alignment); + break; + } + break; + } + } else { + Tmp3 = LegalizeOp(ST->getValue()); + + EVT StVT = ST->getMemoryVT(); + unsigned StWidth = StVT.getSizeInBits(); + + if (StWidth != StVT.getStoreSizeInBits()) { + // Promote to a byte-sized store with upper bits zero if not + // storing an integral number of bytes. For example, promote + // TRUNCSTORE:i1 X -> TRUNCSTORE:i8 (and X, 1) + EVT NVT = EVT::getIntegerVT(*DAG.getContext(), StVT.getStoreSizeInBits()); + Tmp3 = DAG.getZeroExtendInReg(Tmp3, dl, StVT); + Result = DAG.getTruncStore(Tmp1, dl, Tmp3, Tmp2, ST->getSrcValue(), + SVOffset, NVT, isVolatile, Alignment); + } else if (StWidth & (StWidth - 1)) { + // If not storing a power-of-2 number of bits, expand as two stores. + assert(StVT.isExtended() && !StVT.isVector() && + "Unsupported truncstore!"); + unsigned RoundWidth = 1 << Log2_32(StWidth); + assert(RoundWidth < StWidth); + unsigned ExtraWidth = StWidth - RoundWidth; + assert(ExtraWidth < RoundWidth); + assert(!(RoundWidth % 8) && !(ExtraWidth % 8) && + "Store size not an integral number of bytes!"); + EVT RoundVT = EVT::getIntegerVT(*DAG.getContext(), RoundWidth); + EVT ExtraVT = EVT::getIntegerVT(*DAG.getContext(), ExtraWidth); + SDValue Lo, Hi; + unsigned IncrementSize; + + if (TLI.isLittleEndian()) { + // TRUNCSTORE:i24 X -> TRUNCSTORE:i16 X, TRUNCSTORE@+2:i8 (srl X, 16) + // Store the bottom RoundWidth bits. + Lo = DAG.getTruncStore(Tmp1, dl, Tmp3, Tmp2, ST->getSrcValue(), + SVOffset, RoundVT, + isVolatile, Alignment); + + // Store the remaining ExtraWidth bits. + IncrementSize = RoundWidth / 8; + Tmp2 = DAG.getNode(ISD::ADD, dl, Tmp2.getValueType(), Tmp2, + DAG.getIntPtrConstant(IncrementSize)); + Hi = DAG.getNode(ISD::SRL, dl, Tmp3.getValueType(), Tmp3, + DAG.getConstant(RoundWidth, TLI.getShiftAmountTy())); + Hi = DAG.getTruncStore(Tmp1, dl, Hi, Tmp2, ST->getSrcValue(), + SVOffset + IncrementSize, ExtraVT, isVolatile, + MinAlign(Alignment, IncrementSize)); + } else { + // Big endian - avoid unaligned stores. + // TRUNCSTORE:i24 X -> TRUNCSTORE:i16 (srl X, 8), TRUNCSTORE@+2:i8 X + // Store the top RoundWidth bits. + Hi = DAG.getNode(ISD::SRL, dl, Tmp3.getValueType(), Tmp3, + DAG.getConstant(ExtraWidth, TLI.getShiftAmountTy())); + Hi = DAG.getTruncStore(Tmp1, dl, Hi, Tmp2, ST->getSrcValue(), + SVOffset, RoundVT, isVolatile, Alignment); + + // Store the remaining ExtraWidth bits. + IncrementSize = RoundWidth / 8; + Tmp2 = DAG.getNode(ISD::ADD, dl, Tmp2.getValueType(), Tmp2, + DAG.getIntPtrConstant(IncrementSize)); + Lo = DAG.getTruncStore(Tmp1, dl, Tmp3, Tmp2, ST->getSrcValue(), + SVOffset + IncrementSize, ExtraVT, isVolatile, + MinAlign(Alignment, IncrementSize)); + } + + // The order of the stores doesn't matter. + Result = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Lo, Hi); + } else { + if (Tmp1 != ST->getChain() || Tmp3 != ST->getValue() || + Tmp2 != ST->getBasePtr()) + Result = DAG.UpdateNodeOperands(Result, Tmp1, Tmp3, Tmp2, + ST->getOffset()); + + switch (TLI.getTruncStoreAction(ST->getValue().getValueType(), StVT)) { + default: llvm_unreachable("This action is not supported yet!"); + case TargetLowering::Legal: + // If this is an unaligned store and the target doesn't support it, + // expand it. + if (!TLI.allowsUnalignedMemoryAccesses(ST->getMemoryVT())) { + const Type *Ty = ST->getMemoryVT().getTypeForEVT(*DAG.getContext()); + unsigned ABIAlignment = TLI.getTargetData()->getABITypeAlignment(Ty); + if (ST->getAlignment() < ABIAlignment) + Result = ExpandUnalignedStore(cast(Result.getNode()), + DAG, TLI); + } + break; + case TargetLowering::Custom: + Result = TLI.LowerOperation(Result, DAG); + break; + case Expand: + // TRUNCSTORE:i16 i32 -> STORE i16 + assert(isTypeLegal(StVT) && "Do not know how to expand this store!"); + Tmp3 = DAG.getNode(ISD::TRUNCATE, dl, StVT, Tmp3); + Result = DAG.getStore(Tmp1, dl, Tmp3, Tmp2, ST->getSrcValue(), + SVOffset, isVolatile, Alignment); + break; + } + } + } + break; + } + } + assert(Result.getValueType() == Op.getValueType() && + "Bad legalization!"); + + // Make sure that the generated code is itself legal. + if (Result != Op) + Result = LegalizeOp(Result); + + // Note that LegalizeOp may be reentered even from single-use nodes, which + // means that we always must cache transformed nodes. + AddLegalizedOperand(Op, Result); + return Result; +} + +SDValue SelectionDAGLegalize::ExpandExtractFromVectorThroughStack(SDValue Op) { + SDValue Vec = Op.getOperand(0); + SDValue Idx = Op.getOperand(1); + DebugLoc dl = Op.getDebugLoc(); + // Store the value to a temporary stack slot, then LOAD the returned part. + SDValue StackPtr = DAG.CreateStackTemporary(Vec.getValueType()); + SDValue Ch = DAG.getStore(DAG.getEntryNode(), dl, Vec, StackPtr, NULL, 0); + + // Add the offset to the index. + unsigned EltSize = + Vec.getValueType().getVectorElementType().getSizeInBits()/8; + Idx = DAG.getNode(ISD::MUL, dl, Idx.getValueType(), Idx, + DAG.getConstant(EltSize, Idx.getValueType())); + + if (Idx.getValueType().bitsGT(TLI.getPointerTy())) + Idx = DAG.getNode(ISD::TRUNCATE, dl, TLI.getPointerTy(), Idx); + else + Idx = DAG.getNode(ISD::ZERO_EXTEND, dl, TLI.getPointerTy(), Idx); + + StackPtr = DAG.getNode(ISD::ADD, dl, Idx.getValueType(), Idx, StackPtr); + + if (Op.getValueType().isVector()) + return DAG.getLoad(Op.getValueType(), dl, Ch, StackPtr, NULL, 0); + else + return DAG.getExtLoad(ISD::EXTLOAD, dl, Op.getValueType(), Ch, StackPtr, + NULL, 0, Vec.getValueType().getVectorElementType()); +} + +SDValue SelectionDAGLegalize::ExpandVectorBuildThroughStack(SDNode* Node) { + // We can't handle this case efficiently. Allocate a sufficiently + // aligned object on the stack, store each element into it, then load + // the result as a vector. + // Create the stack frame object. + EVT VT = Node->getValueType(0); + EVT OpVT = Node->getOperand(0).getValueType(); + EVT EltVT = VT.getVectorElementType(); + DebugLoc dl = Node->getDebugLoc(); + SDValue FIPtr = DAG.CreateStackTemporary(VT); + int FI = cast(FIPtr.getNode())->getIndex(); + const Value *SV = PseudoSourceValue::getFixedStack(FI); + + // Emit a store of each element to the stack slot. + SmallVector Stores; + unsigned TypeByteSize = EltVT.getSizeInBits() / 8; + // Store (in the right endianness) the elements to memory. + for (unsigned i = 0, e = Node->getNumOperands(); i != e; ++i) { + // Ignore undef elements. + if (Node->getOperand(i).getOpcode() == ISD::UNDEF) continue; + + unsigned Offset = TypeByteSize*i; + + SDValue Idx = DAG.getConstant(Offset, FIPtr.getValueType()); + Idx = DAG.getNode(ISD::ADD, dl, FIPtr.getValueType(), FIPtr, Idx); + + // If EltVT smaller than OpVT, only store the bits necessary. + if (EltVT.bitsLT(OpVT)) + Stores.push_back(DAG.getTruncStore(DAG.getEntryNode(), dl, + Node->getOperand(i), Idx, SV, Offset, EltVT)); + else + Stores.push_back(DAG.getStore(DAG.getEntryNode(), dl, + Node->getOperand(i), Idx, SV, Offset)); + } + + SDValue StoreChain; + if (!Stores.empty()) // Not all undef elements? + StoreChain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, + &Stores[0], Stores.size()); + else + StoreChain = DAG.getEntryNode(); + + // Result is a load from the stack slot. + return DAG.getLoad(VT, dl, StoreChain, FIPtr, SV, 0); +} + +SDValue SelectionDAGLegalize::ExpandFCOPYSIGN(SDNode* Node) { + DebugLoc dl = Node->getDebugLoc(); + SDValue Tmp1 = Node->getOperand(0); + SDValue Tmp2 = Node->getOperand(1); + assert((Tmp2.getValueType() == MVT::f32 || + Tmp2.getValueType() == MVT::f64) && + "Ugly special-cased code!"); + // Get the sign bit of the RHS. + SDValue SignBit; + EVT IVT = Tmp2.getValueType() == MVT::f64 ? MVT::i64 : MVT::i32; + if (isTypeLegal(IVT)) { + SignBit = DAG.getNode(ISD::BIT_CONVERT, dl, IVT, Tmp2); + } else { + assert(isTypeLegal(TLI.getPointerTy()) && + (TLI.getPointerTy() == MVT::i32 || + TLI.getPointerTy() == MVT::i64) && + "Legal type for load?!"); + SDValue StackPtr = DAG.CreateStackTemporary(Tmp2.getValueType()); + SDValue StorePtr = StackPtr, LoadPtr = StackPtr; + SDValue Ch = + DAG.getStore(DAG.getEntryNode(), dl, Tmp2, StorePtr, NULL, 0); + if (Tmp2.getValueType() == MVT::f64 && TLI.isLittleEndian()) + LoadPtr = DAG.getNode(ISD::ADD, dl, StackPtr.getValueType(), + LoadPtr, DAG.getIntPtrConstant(4)); + SignBit = DAG.getExtLoad(ISD::SEXTLOAD, dl, TLI.getPointerTy(), + Ch, LoadPtr, NULL, 0, MVT::i32); + } + SignBit = + DAG.getSetCC(dl, TLI.getSetCCResultType(SignBit.getValueType()), + SignBit, DAG.getConstant(0, SignBit.getValueType()), + ISD::SETLT); + // Get the absolute value of the result. + SDValue AbsVal = DAG.getNode(ISD::FABS, dl, Tmp1.getValueType(), Tmp1); + // Select between the nabs and abs value based on the sign bit of + // the input. + return DAG.getNode(ISD::SELECT, dl, AbsVal.getValueType(), SignBit, + DAG.getNode(ISD::FNEG, dl, AbsVal.getValueType(), AbsVal), + AbsVal); +} + +void SelectionDAGLegalize::ExpandDYNAMIC_STACKALLOC(SDNode* Node, + SmallVectorImpl &Results) { + unsigned SPReg = TLI.getStackPointerRegisterToSaveRestore(); + assert(SPReg && "Target cannot require DYNAMIC_STACKALLOC expansion and" + " not tell us which reg is the stack pointer!"); + DebugLoc dl = Node->getDebugLoc(); + EVT VT = Node->getValueType(0); + SDValue Tmp1 = SDValue(Node, 0); + SDValue Tmp2 = SDValue(Node, 1); + SDValue Tmp3 = Node->getOperand(2); + SDValue Chain = Tmp1.getOperand(0); + + // Chain the dynamic stack allocation so that it doesn't modify the stack + // pointer when other instructions are using the stack. + Chain = DAG.getCALLSEQ_START(Chain, DAG.getIntPtrConstant(0, true)); + + SDValue Size = Tmp2.getOperand(1); + SDValue SP = DAG.getCopyFromReg(Chain, dl, SPReg, VT); + Chain = SP.getValue(1); + unsigned Align = cast(Tmp3)->getZExtValue(); + unsigned StackAlign = + TLI.getTargetMachine().getFrameInfo()->getStackAlignment(); + if (Align > StackAlign) + SP = DAG.getNode(ISD::AND, dl, VT, SP, + DAG.getConstant(-(uint64_t)Align, VT)); + Tmp1 = DAG.getNode(ISD::SUB, dl, VT, SP, Size); // Value + Chain = DAG.getCopyToReg(Chain, dl, SPReg, Tmp1); // Output chain + + Tmp2 = DAG.getCALLSEQ_END(Chain, DAG.getIntPtrConstant(0, true), + DAG.getIntPtrConstant(0, true), SDValue()); + + Results.push_back(Tmp1); + Results.push_back(Tmp2); +} + +/// LegalizeSetCCCondCode - Legalize a SETCC with given LHS and RHS and +/// condition code CC on the current target. This routine expands SETCC with +/// illegal condition code into AND / OR of multiple SETCC values. +void SelectionDAGLegalize::LegalizeSetCCCondCode(EVT VT, + SDValue &LHS, SDValue &RHS, + SDValue &CC, + DebugLoc dl) { + EVT OpVT = LHS.getValueType(); + ISD::CondCode CCCode = cast(CC)->get(); + switch (TLI.getCondCodeAction(CCCode, OpVT)) { + default: llvm_unreachable("Unknown condition code action!"); + case TargetLowering::Legal: + // Nothing to do. + break; + case TargetLowering::Expand: { + ISD::CondCode CC1 = ISD::SETCC_INVALID, CC2 = ISD::SETCC_INVALID; + unsigned Opc = 0; + switch (CCCode) { + default: llvm_unreachable("Don't know how to expand this condition!"); + case ISD::SETOEQ: CC1 = ISD::SETEQ; CC2 = ISD::SETO; Opc = ISD::AND; break; + case ISD::SETOGT: CC1 = ISD::SETGT; CC2 = ISD::SETO; Opc = ISD::AND; break; + case ISD::SETOGE: CC1 = ISD::SETGE; CC2 = ISD::SETO; Opc = ISD::AND; break; + case ISD::SETOLT: CC1 = ISD::SETLT; CC2 = ISD::SETO; Opc = ISD::AND; break; + case ISD::SETOLE: CC1 = ISD::SETLE; CC2 = ISD::SETO; Opc = ISD::AND; break; + case ISD::SETONE: CC1 = ISD::SETNE; CC2 = ISD::SETO; Opc = ISD::AND; break; + case ISD::SETUEQ: CC1 = ISD::SETEQ; CC2 = ISD::SETUO; Opc = ISD::OR; break; + case ISD::SETUGT: CC1 = ISD::SETGT; CC2 = ISD::SETUO; Opc = ISD::OR; break; + case ISD::SETUGE: CC1 = ISD::SETGE; CC2 = ISD::SETUO; Opc = ISD::OR; break; + case ISD::SETULT: CC1 = ISD::SETLT; CC2 = ISD::SETUO; Opc = ISD::OR; break; + case ISD::SETULE: CC1 = ISD::SETLE; CC2 = ISD::SETUO; Opc = ISD::OR; break; + case ISD::SETUNE: CC1 = ISD::SETNE; CC2 = ISD::SETUO; Opc = ISD::OR; break; + // FIXME: Implement more expansions. + } + + SDValue SetCC1 = DAG.getSetCC(dl, VT, LHS, RHS, CC1); + SDValue SetCC2 = DAG.getSetCC(dl, VT, LHS, RHS, CC2); + LHS = DAG.getNode(Opc, dl, VT, SetCC1, SetCC2); + RHS = SDValue(); + CC = SDValue(); + break; + } + } +} + +/// EmitStackConvert - Emit a store/load combination to the stack. This stores +/// SrcOp to a stack slot of type SlotVT, truncating it if needed. It then does +/// a load from the stack slot to DestVT, extending it if needed. +/// The resultant code need not be legal. +SDValue SelectionDAGLegalize::EmitStackConvert(SDValue SrcOp, + EVT SlotVT, + EVT DestVT, + DebugLoc dl) { + // Create the stack frame object. + unsigned SrcAlign = + TLI.getTargetData()->getPrefTypeAlignment(SrcOp.getValueType(). + getTypeForEVT(*DAG.getContext())); + SDValue FIPtr = DAG.CreateStackTemporary(SlotVT, SrcAlign); + + FrameIndexSDNode *StackPtrFI = cast(FIPtr); + int SPFI = StackPtrFI->getIndex(); + const Value *SV = PseudoSourceValue::getFixedStack(SPFI); + + unsigned SrcSize = SrcOp.getValueType().getSizeInBits(); + unsigned SlotSize = SlotVT.getSizeInBits(); + unsigned DestSize = DestVT.getSizeInBits(); + unsigned DestAlign = + TLI.getTargetData()->getPrefTypeAlignment(DestVT.getTypeForEVT(*DAG.getContext())); + + // Emit a store to the stack slot. Use a truncstore if the input value is + // later than DestVT. + SDValue Store; + + if (SrcSize > SlotSize) + Store = DAG.getTruncStore(DAG.getEntryNode(), dl, SrcOp, FIPtr, + SV, 0, SlotVT, false, SrcAlign); + else { + assert(SrcSize == SlotSize && "Invalid store"); + Store = DAG.getStore(DAG.getEntryNode(), dl, SrcOp, FIPtr, + SV, 0, false, SrcAlign); + } + + // Result is a load from the stack slot. + if (SlotSize == DestSize) + return DAG.getLoad(DestVT, dl, Store, FIPtr, SV, 0, false, DestAlign); + + assert(SlotSize < DestSize && "Unknown extension!"); + return DAG.getExtLoad(ISD::EXTLOAD, dl, DestVT, Store, FIPtr, SV, 0, SlotVT, + false, DestAlign); +} + +SDValue SelectionDAGLegalize::ExpandSCALAR_TO_VECTOR(SDNode *Node) { + DebugLoc dl = Node->getDebugLoc(); + // Create a vector sized/aligned stack slot, store the value to element #0, + // then load the whole vector back out. + SDValue StackPtr = DAG.CreateStackTemporary(Node->getValueType(0)); + + FrameIndexSDNode *StackPtrFI = cast(StackPtr); + int SPFI = StackPtrFI->getIndex(); + + SDValue Ch = DAG.getTruncStore(DAG.getEntryNode(), dl, Node->getOperand(0), + StackPtr, + PseudoSourceValue::getFixedStack(SPFI), 0, + Node->getValueType(0).getVectorElementType()); + return DAG.getLoad(Node->getValueType(0), dl, Ch, StackPtr, + PseudoSourceValue::getFixedStack(SPFI), 0); +} + + +/// ExpandBUILD_VECTOR - Expand a BUILD_VECTOR node on targets that don't +/// support the operation, but do support the resultant vector type. +SDValue SelectionDAGLegalize::ExpandBUILD_VECTOR(SDNode *Node) { + unsigned NumElems = Node->getNumOperands(); + SDValue Value1, Value2; + DebugLoc dl = Node->getDebugLoc(); + EVT VT = Node->getValueType(0); + EVT OpVT = Node->getOperand(0).getValueType(); + EVT EltVT = VT.getVectorElementType(); + + // If the only non-undef value is the low element, turn this into a + // SCALAR_TO_VECTOR node. If this is { X, X, X, X }, determine X. + bool isOnlyLowElement = true; + bool MoreThanTwoValues = false; + bool isConstant = true; + for (unsigned i = 0; i < NumElems; ++i) { + SDValue V = Node->getOperand(i); + if (V.getOpcode() == ISD::UNDEF) + continue; + if (i > 0) + isOnlyLowElement = false; + if (!isa(V) && !isa(V)) + isConstant = false; + + if (!Value1.getNode()) { + Value1 = V; + } else if (!Value2.getNode()) { + if (V != Value1) + Value2 = V; + } else if (V != Value1 && V != Value2) { + MoreThanTwoValues = true; + } + } + + if (!Value1.getNode()) + return DAG.getUNDEF(VT); + + if (isOnlyLowElement) + return DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, VT, Node->getOperand(0)); + + // If all elements are constants, create a load from the constant pool. + if (isConstant) { + std::vector CV; + for (unsigned i = 0, e = NumElems; i != e; ++i) { + if (ConstantFPSDNode *V = + dyn_cast(Node->getOperand(i))) { + CV.push_back(const_cast(V->getConstantFPValue())); + } else if (ConstantSDNode *V = + dyn_cast(Node->getOperand(i))) { + if (OpVT==EltVT) + CV.push_back(const_cast(V->getConstantIntValue())); + else { + // If OpVT and EltVT don't match, EltVT is not legal and the + // element values have been promoted/truncated earlier. Undo this; + // we don't want a v16i8 to become a v16i32 for example. + const ConstantInt *CI = V->getConstantIntValue(); + CV.push_back(ConstantInt::get(EltVT.getTypeForEVT(*DAG.getContext()), + CI->getZExtValue())); + } + } else { + assert(Node->getOperand(i).getOpcode() == ISD::UNDEF); + const Type *OpNTy = EltVT.getTypeForEVT(*DAG.getContext()); + CV.push_back(UndefValue::get(OpNTy)); + } + } + Constant *CP = ConstantVector::get(CV); + SDValue CPIdx = DAG.getConstantPool(CP, TLI.getPointerTy()); + unsigned Alignment = cast(CPIdx)->getAlignment(); + return DAG.getLoad(VT, dl, DAG.getEntryNode(), CPIdx, + PseudoSourceValue::getConstantPool(), 0, + false, Alignment); + } + + if (!MoreThanTwoValues) { + SmallVector ShuffleVec(NumElems, -1); + for (unsigned i = 0; i < NumElems; ++i) { + SDValue V = Node->getOperand(i); + if (V.getOpcode() == ISD::UNDEF) + continue; + ShuffleVec[i] = V == Value1 ? 0 : NumElems; + } + if (TLI.isShuffleMaskLegal(ShuffleVec, Node->getValueType(0))) { + // Get the splatted value into the low element of a vector register. + SDValue Vec1 = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, VT, Value1); + SDValue Vec2; + if (Value2.getNode()) + Vec2 = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, VT, Value2); + else + Vec2 = DAG.getUNDEF(VT); + + // Return shuffle(LowValVec, undef, <0,0,0,0>) + return DAG.getVectorShuffle(VT, dl, Vec1, Vec2, ShuffleVec.data()); + } + } + + // Otherwise, we can't handle this case efficiently. + return ExpandVectorBuildThroughStack(Node); +} + +// ExpandLibCall - Expand a node into a call to a libcall. If the result value +// does not fit into a register, return the lo part and set the hi part to the +// by-reg argument. If it does fit into a single register, return the result +// and leave the Hi part unset. +SDValue SelectionDAGLegalize::ExpandLibCall(RTLIB::Libcall LC, SDNode *Node, + bool isSigned) { + assert(!IsLegalizingCall && "Cannot overlap legalization of calls!"); + // The input chain to this libcall is the entry node of the function. + // Legalizing the call will automatically add the previous call to the + // dependence. + SDValue InChain = DAG.getEntryNode(); + + TargetLowering::ArgListTy Args; + TargetLowering::ArgListEntry Entry; + for (unsigned i = 0, e = Node->getNumOperands(); i != e; ++i) { + EVT ArgVT = Node->getOperand(i).getValueType(); + const Type *ArgTy = ArgVT.getTypeForEVT(*DAG.getContext()); + Entry.Node = Node->getOperand(i); Entry.Ty = ArgTy; + Entry.isSExt = isSigned; + Entry.isZExt = !isSigned; + Args.push_back(Entry); + } + SDValue Callee = DAG.getExternalSymbol(TLI.getLibcallName(LC), + TLI.getPointerTy()); + + // Splice the libcall in wherever FindInputOutputChains tells us to. + const Type *RetTy = Node->getValueType(0).getTypeForEVT(*DAG.getContext()); + std::pair CallInfo = + TLI.LowerCallTo(InChain, RetTy, isSigned, !isSigned, false, false, + 0, TLI.getLibcallCallingConv(LC), false, + /*isReturnValueUsed=*/true, + Callee, Args, DAG, + Node->getDebugLoc()); + + // Legalize the call sequence, starting with the chain. This will advance + // the LastCALLSEQ_END to the legalized version of the CALLSEQ_END node that + // was added by LowerCallTo (guaranteeing proper serialization of calls). + LegalizeOp(CallInfo.second); + return CallInfo.first; +} + +SDValue SelectionDAGLegalize::ExpandFPLibCall(SDNode* Node, + RTLIB::Libcall Call_F32, + RTLIB::Libcall Call_F64, + RTLIB::Libcall Call_F80, + RTLIB::Libcall Call_PPCF128) { + RTLIB::Libcall LC; + switch (Node->getValueType(0).getSimpleVT().SimpleTy) { + default: llvm_unreachable("Unexpected request for libcall!"); + case MVT::f32: LC = Call_F32; break; + case MVT::f64: LC = Call_F64; break; + case MVT::f80: LC = Call_F80; break; + case MVT::ppcf128: LC = Call_PPCF128; break; + } + return ExpandLibCall(LC, Node, false); +} + +SDValue SelectionDAGLegalize::ExpandIntLibCall(SDNode* Node, bool isSigned, + RTLIB::Libcall Call_I8, + RTLIB::Libcall Call_I16, + RTLIB::Libcall Call_I32, + RTLIB::Libcall Call_I64, + RTLIB::Libcall Call_I128) { + RTLIB::Libcall LC; + switch (Node->getValueType(0).getSimpleVT().SimpleTy) { + default: llvm_unreachable("Unexpected request for libcall!"); + case MVT::i8: LC = Call_I8; break; + case MVT::i16: LC = Call_I16; break; + case MVT::i32: LC = Call_I32; break; + case MVT::i64: LC = Call_I64; break; + case MVT::i128: LC = Call_I128; break; + } + return ExpandLibCall(LC, Node, isSigned); +} + +/// ExpandLegalINT_TO_FP - This function is responsible for legalizing a +/// INT_TO_FP operation of the specified operand when the target requests that +/// we expand it. At this point, we know that the result and operand types are +/// legal for the target. +SDValue SelectionDAGLegalize::ExpandLegalINT_TO_FP(bool isSigned, + SDValue Op0, + EVT DestVT, + DebugLoc dl) { + if (Op0.getValueType() == MVT::i32) { + // simple 32-bit [signed|unsigned] integer to float/double expansion + + // Get the stack frame index of a 8 byte buffer. + SDValue StackSlot = DAG.CreateStackTemporary(MVT::f64); + + // word offset constant for Hi/Lo address computation + SDValue WordOff = DAG.getConstant(sizeof(int), TLI.getPointerTy()); + // set up Hi and Lo (into buffer) address based on endian + SDValue Hi = StackSlot; + SDValue Lo = DAG.getNode(ISD::ADD, dl, + TLI.getPointerTy(), StackSlot, WordOff); + if (TLI.isLittleEndian()) + std::swap(Hi, Lo); + + // if signed map to unsigned space + SDValue Op0Mapped; + if (isSigned) { + // constant used to invert sign bit (signed to unsigned mapping) + SDValue SignBit = DAG.getConstant(0x80000000u, MVT::i32); + Op0Mapped = DAG.getNode(ISD::XOR, dl, MVT::i32, Op0, SignBit); + } else { + Op0Mapped = Op0; + } + // store the lo of the constructed double - based on integer input + SDValue Store1 = DAG.getStore(DAG.getEntryNode(), dl, + Op0Mapped, Lo, NULL, 0); + // initial hi portion of constructed double + SDValue InitialHi = DAG.getConstant(0x43300000u, MVT::i32); + // store the hi of the constructed double - biased exponent + SDValue Store2=DAG.getStore(Store1, dl, InitialHi, Hi, NULL, 0); + // load the constructed double + SDValue Load = DAG.getLoad(MVT::f64, dl, Store2, StackSlot, NULL, 0); + // FP constant to bias correct the final result + SDValue Bias = DAG.getConstantFP(isSigned ? + BitsToDouble(0x4330000080000000ULL) : + BitsToDouble(0x4330000000000000ULL), + MVT::f64); + // subtract the bias + SDValue Sub = DAG.getNode(ISD::FSUB, dl, MVT::f64, Load, Bias); + // final result + SDValue Result; + // handle final rounding + if (DestVT == MVT::f64) { + // do nothing + Result = Sub; + } else if (DestVT.bitsLT(MVT::f64)) { + Result = DAG.getNode(ISD::FP_ROUND, dl, DestVT, Sub, + DAG.getIntPtrConstant(0)); + } else if (DestVT.bitsGT(MVT::f64)) { + Result = DAG.getNode(ISD::FP_EXTEND, dl, DestVT, Sub); + } + return Result; + } + assert(!isSigned && "Legalize cannot Expand SINT_TO_FP for i64 yet"); + SDValue Tmp1 = DAG.getNode(ISD::SINT_TO_FP, dl, DestVT, Op0); + + SDValue SignSet = DAG.getSetCC(dl, TLI.getSetCCResultType(Op0.getValueType()), + Op0, DAG.getConstant(0, Op0.getValueType()), + ISD::SETLT); + SDValue Zero = DAG.getIntPtrConstant(0), Four = DAG.getIntPtrConstant(4); + SDValue CstOffset = DAG.getNode(ISD::SELECT, dl, Zero.getValueType(), + SignSet, Four, Zero); + + // If the sign bit of the integer is set, the large number will be treated + // as a negative number. To counteract this, the dynamic code adds an + // offset depending on the data type. + uint64_t FF; + switch (Op0.getValueType().getSimpleVT().SimpleTy) { + default: llvm_unreachable("Unsupported integer type!"); + case MVT::i8 : FF = 0x43800000ULL; break; // 2^8 (as a float) + case MVT::i16: FF = 0x47800000ULL; break; // 2^16 (as a float) + case MVT::i32: FF = 0x4F800000ULL; break; // 2^32 (as a float) + case MVT::i64: FF = 0x5F800000ULL; break; // 2^64 (as a float) + } + if (TLI.isLittleEndian()) FF <<= 32; + Constant *FudgeFactor = ConstantInt::get( + Type::getInt64Ty(*DAG.getContext()), FF); + + SDValue CPIdx = DAG.getConstantPool(FudgeFactor, TLI.getPointerTy()); + unsigned Alignment = cast(CPIdx)->getAlignment(); + CPIdx = DAG.getNode(ISD::ADD, dl, TLI.getPointerTy(), CPIdx, CstOffset); + Alignment = std::min(Alignment, 4u); + SDValue FudgeInReg; + if (DestVT == MVT::f32) + FudgeInReg = DAG.getLoad(MVT::f32, dl, DAG.getEntryNode(), CPIdx, + PseudoSourceValue::getConstantPool(), 0, + false, Alignment); + else { + FudgeInReg = + LegalizeOp(DAG.getExtLoad(ISD::EXTLOAD, dl, DestVT, + DAG.getEntryNode(), CPIdx, + PseudoSourceValue::getConstantPool(), 0, + MVT::f32, false, Alignment)); + } + + return DAG.getNode(ISD::FADD, dl, DestVT, Tmp1, FudgeInReg); +} + +/// PromoteLegalINT_TO_FP - This function is responsible for legalizing a +/// *INT_TO_FP operation of the specified operand when the target requests that +/// we promote it. At this point, we know that the result and operand types are +/// legal for the target, and that there is a legal UINT_TO_FP or SINT_TO_FP +/// operation that takes a larger input. +SDValue SelectionDAGLegalize::PromoteLegalINT_TO_FP(SDValue LegalOp, + EVT DestVT, + bool isSigned, + DebugLoc dl) { + // First step, figure out the appropriate *INT_TO_FP operation to use. + EVT NewInTy = LegalOp.getValueType(); + + unsigned OpToUse = 0; + + // Scan for the appropriate larger type to use. + while (1) { + NewInTy = (MVT::SimpleValueType)(NewInTy.getSimpleVT().SimpleTy+1); + assert(NewInTy.isInteger() && "Ran out of possibilities!"); + + // If the target supports SINT_TO_FP of this type, use it. + if (TLI.isOperationLegalOrCustom(ISD::SINT_TO_FP, NewInTy)) { + OpToUse = ISD::SINT_TO_FP; + break; + } + if (isSigned) continue; + + // If the target supports UINT_TO_FP of this type, use it. + if (TLI.isOperationLegalOrCustom(ISD::UINT_TO_FP, NewInTy)) { + OpToUse = ISD::UINT_TO_FP; + break; + } + + // Otherwise, try a larger type. + } + + // Okay, we found the operation and type to use. Zero extend our input to the + // desired type then run the operation on it. + return DAG.getNode(OpToUse, dl, DestVT, + DAG.getNode(isSigned ? ISD::SIGN_EXTEND : ISD::ZERO_EXTEND, + dl, NewInTy, LegalOp)); +} + +/// PromoteLegalFP_TO_INT - This function is responsible for legalizing a +/// FP_TO_*INT operation of the specified operand when the target requests that +/// we promote it. At this point, we know that the result and operand types are +/// legal for the target, and that there is a legal FP_TO_UINT or FP_TO_SINT +/// operation that returns a larger result. +SDValue SelectionDAGLegalize::PromoteLegalFP_TO_INT(SDValue LegalOp, + EVT DestVT, + bool isSigned, + DebugLoc dl) { + // First step, figure out the appropriate FP_TO*INT operation to use. + EVT NewOutTy = DestVT; + + unsigned OpToUse = 0; + + // Scan for the appropriate larger type to use. + while (1) { + NewOutTy = (MVT::SimpleValueType)(NewOutTy.getSimpleVT().SimpleTy+1); + assert(NewOutTy.isInteger() && "Ran out of possibilities!"); + + if (TLI.isOperationLegalOrCustom(ISD::FP_TO_SINT, NewOutTy)) { + OpToUse = ISD::FP_TO_SINT; + break; + } + + if (TLI.isOperationLegalOrCustom(ISD::FP_TO_UINT, NewOutTy)) { + OpToUse = ISD::FP_TO_UINT; + break; + } + + // Otherwise, try a larger type. + } + + + // Okay, we found the operation and type to use. + SDValue Operation = DAG.getNode(OpToUse, dl, NewOutTy, LegalOp); + + // Truncate the result of the extended FP_TO_*INT operation to the desired + // size. + return DAG.getNode(ISD::TRUNCATE, dl, DestVT, Operation); +} + +/// ExpandBSWAP - Open code the operations for BSWAP of the specified operation. +/// +SDValue SelectionDAGLegalize::ExpandBSWAP(SDValue Op, DebugLoc dl) { + EVT VT = Op.getValueType(); + EVT SHVT = TLI.getShiftAmountTy(); + SDValue Tmp1, Tmp2, Tmp3, Tmp4, Tmp5, Tmp6, Tmp7, Tmp8; + switch (VT.getSimpleVT().SimpleTy) { + default: llvm_unreachable("Unhandled Expand type in BSWAP!"); + case MVT::i16: + Tmp2 = DAG.getNode(ISD::SHL, dl, VT, Op, DAG.getConstant(8, SHVT)); + Tmp1 = DAG.getNode(ISD::SRL, dl, VT, Op, DAG.getConstant(8, SHVT)); + return DAG.getNode(ISD::OR, dl, VT, Tmp1, Tmp2); + case MVT::i32: + Tmp4 = DAG.getNode(ISD::SHL, dl, VT, Op, DAG.getConstant(24, SHVT)); + Tmp3 = DAG.getNode(ISD::SHL, dl, VT, Op, DAG.getConstant(8, SHVT)); + Tmp2 = DAG.getNode(ISD::SRL, dl, VT, Op, DAG.getConstant(8, SHVT)); + Tmp1 = DAG.getNode(ISD::SRL, dl, VT, Op, DAG.getConstant(24, SHVT)); + Tmp3 = DAG.getNode(ISD::AND, dl, VT, Tmp3, DAG.getConstant(0xFF0000, VT)); + Tmp2 = DAG.getNode(ISD::AND, dl, VT, Tmp2, DAG.getConstant(0xFF00, VT)); + Tmp4 = DAG.getNode(ISD::OR, dl, VT, Tmp4, Tmp3); + Tmp2 = DAG.getNode(ISD::OR, dl, VT, Tmp2, Tmp1); + return DAG.getNode(ISD::OR, dl, VT, Tmp4, Tmp2); + case MVT::i64: + Tmp8 = DAG.getNode(ISD::SHL, dl, VT, Op, DAG.getConstant(56, SHVT)); + Tmp7 = DAG.getNode(ISD::SHL, dl, VT, Op, DAG.getConstant(40, SHVT)); + Tmp6 = DAG.getNode(ISD::SHL, dl, VT, Op, DAG.getConstant(24, SHVT)); + Tmp5 = DAG.getNode(ISD::SHL, dl, VT, Op, DAG.getConstant(8, SHVT)); + Tmp4 = DAG.getNode(ISD::SRL, dl, VT, Op, DAG.getConstant(8, SHVT)); + Tmp3 = DAG.getNode(ISD::SRL, dl, VT, Op, DAG.getConstant(24, SHVT)); + Tmp2 = DAG.getNode(ISD::SRL, dl, VT, Op, DAG.getConstant(40, SHVT)); + Tmp1 = DAG.getNode(ISD::SRL, dl, VT, Op, DAG.getConstant(56, SHVT)); + Tmp7 = DAG.getNode(ISD::AND, dl, VT, Tmp7, DAG.getConstant(255ULL<<48, VT)); + Tmp6 = DAG.getNode(ISD::AND, dl, VT, Tmp6, DAG.getConstant(255ULL<<40, VT)); + Tmp5 = DAG.getNode(ISD::AND, dl, VT, Tmp5, DAG.getConstant(255ULL<<32, VT)); + Tmp4 = DAG.getNode(ISD::AND, dl, VT, Tmp4, DAG.getConstant(255ULL<<24, VT)); + Tmp3 = DAG.getNode(ISD::AND, dl, VT, Tmp3, DAG.getConstant(255ULL<<16, VT)); + Tmp2 = DAG.getNode(ISD::AND, dl, VT, Tmp2, DAG.getConstant(255ULL<<8 , VT)); + Tmp8 = DAG.getNode(ISD::OR, dl, VT, Tmp8, Tmp7); + Tmp6 = DAG.getNode(ISD::OR, dl, VT, Tmp6, Tmp5); + Tmp4 = DAG.getNode(ISD::OR, dl, VT, Tmp4, Tmp3); + Tmp2 = DAG.getNode(ISD::OR, dl, VT, Tmp2, Tmp1); + Tmp8 = DAG.getNode(ISD::OR, dl, VT, Tmp8, Tmp6); + Tmp4 = DAG.getNode(ISD::OR, dl, VT, Tmp4, Tmp2); + return DAG.getNode(ISD::OR, dl, VT, Tmp8, Tmp4); + } +} + +/// ExpandBitCount - Expand the specified bitcount instruction into operations. +/// +SDValue SelectionDAGLegalize::ExpandBitCount(unsigned Opc, SDValue Op, + DebugLoc dl) { + switch (Opc) { + default: llvm_unreachable("Cannot expand this yet!"); + case ISD::CTPOP: { + static const uint64_t mask[6] = { + 0x5555555555555555ULL, 0x3333333333333333ULL, + 0x0F0F0F0F0F0F0F0FULL, 0x00FF00FF00FF00FFULL, + 0x0000FFFF0000FFFFULL, 0x00000000FFFFFFFFULL + }; + EVT VT = Op.getValueType(); + EVT ShVT = TLI.getShiftAmountTy(); + unsigned len = VT.getSizeInBits(); + for (unsigned i = 0; (1U << i) <= (len / 2); ++i) { + //x = (x & mask[i][len/8]) + (x >> (1 << i) & mask[i][len/8]) + unsigned EltSize = VT.isVector() ? + VT.getVectorElementType().getSizeInBits() : len; + SDValue Tmp2 = DAG.getConstant(APInt(EltSize, mask[i]), VT); + SDValue Tmp3 = DAG.getConstant(1ULL << i, ShVT); + Op = DAG.getNode(ISD::ADD, dl, VT, + DAG.getNode(ISD::AND, dl, VT, Op, Tmp2), + DAG.getNode(ISD::AND, dl, VT, + DAG.getNode(ISD::SRL, dl, VT, Op, Tmp3), + Tmp2)); + } + return Op; + } + case ISD::CTLZ: { + // for now, we do this: + // x = x | (x >> 1); + // x = x | (x >> 2); + // ... + // x = x | (x >>16); + // x = x | (x >>32); // for 64-bit input + // return popcount(~x); + // + // but see also: http://www.hackersdelight.org/HDcode/nlz.cc + EVT VT = Op.getValueType(); + EVT ShVT = TLI.getShiftAmountTy(); + unsigned len = VT.getSizeInBits(); + for (unsigned i = 0; (1U << i) <= (len / 2); ++i) { + SDValue Tmp3 = DAG.getConstant(1ULL << i, ShVT); + Op = DAG.getNode(ISD::OR, dl, VT, Op, + DAG.getNode(ISD::SRL, dl, VT, Op, Tmp3)); + } + Op = DAG.getNOT(dl, Op, VT); + return DAG.getNode(ISD::CTPOP, dl, VT, Op); + } + case ISD::CTTZ: { + // for now, we use: { return popcount(~x & (x - 1)); } + // unless the target has ctlz but not ctpop, in which case we use: + // { return 32 - nlz(~x & (x-1)); } + // see also http://www.hackersdelight.org/HDcode/ntz.cc + EVT VT = Op.getValueType(); + SDValue Tmp3 = DAG.getNode(ISD::AND, dl, VT, + DAG.getNOT(dl, Op, VT), + DAG.getNode(ISD::SUB, dl, VT, Op, + DAG.getConstant(1, VT))); + // If ISD::CTLZ is legal and CTPOP isn't, then do that instead. + if (!TLI.isOperationLegalOrCustom(ISD::CTPOP, VT) && + TLI.isOperationLegalOrCustom(ISD::CTLZ, VT)) + return DAG.getNode(ISD::SUB, dl, VT, + DAG.getConstant(VT.getSizeInBits(), VT), + DAG.getNode(ISD::CTLZ, dl, VT, Tmp3)); + return DAG.getNode(ISD::CTPOP, dl, VT, Tmp3); + } + } +} + +void SelectionDAGLegalize::ExpandNode(SDNode *Node, + SmallVectorImpl &Results) { + DebugLoc dl = Node->getDebugLoc(); + SDValue Tmp1, Tmp2, Tmp3, Tmp4; + switch (Node->getOpcode()) { + case ISD::CTPOP: + case ISD::CTLZ: + case ISD::CTTZ: + Tmp1 = ExpandBitCount(Node->getOpcode(), Node->getOperand(0), dl); + Results.push_back(Tmp1); + break; + case ISD::BSWAP: + Results.push_back(ExpandBSWAP(Node->getOperand(0), dl)); + break; + case ISD::FRAMEADDR: + case ISD::RETURNADDR: + case ISD::FRAME_TO_ARGS_OFFSET: + Results.push_back(DAG.getConstant(0, Node->getValueType(0))); + break; + case ISD::FLT_ROUNDS_: + Results.push_back(DAG.getConstant(1, Node->getValueType(0))); + break; + case ISD::EH_RETURN: + case ISD::EH_LABEL: + case ISD::PREFETCH: + case ISD::MEMBARRIER: + case ISD::VAEND: + Results.push_back(Node->getOperand(0)); + break; + case ISD::DYNAMIC_STACKALLOC: + ExpandDYNAMIC_STACKALLOC(Node, Results); + break; + case ISD::MERGE_VALUES: + for (unsigned i = 0; i < Node->getNumValues(); i++) + Results.push_back(Node->getOperand(i)); + break; + case ISD::UNDEF: { + EVT VT = Node->getValueType(0); + if (VT.isInteger()) + Results.push_back(DAG.getConstant(0, VT)); + else if (VT.isFloatingPoint()) + Results.push_back(DAG.getConstantFP(0, VT)); + else + llvm_unreachable("Unknown value type!"); + break; + } + case ISD::TRAP: { + // If this operation is not supported, lower it to 'abort()' call + TargetLowering::ArgListTy Args; + std::pair CallResult = + TLI.LowerCallTo(Node->getOperand(0), Type::getVoidTy(*DAG.getContext()), + false, false, false, false, 0, CallingConv::C, false, + /*isReturnValueUsed=*/true, + DAG.getExternalSymbol("abort", TLI.getPointerTy()), + Args, DAG, dl); + Results.push_back(CallResult.second); + break; + } + case ISD::FP_ROUND: + case ISD::BIT_CONVERT: + Tmp1 = EmitStackConvert(Node->getOperand(0), Node->getValueType(0), + Node->getValueType(0), dl); + Results.push_back(Tmp1); + break; + case ISD::FP_EXTEND: + Tmp1 = EmitStackConvert(Node->getOperand(0), + Node->getOperand(0).getValueType(), + Node->getValueType(0), dl); + Results.push_back(Tmp1); + break; + case ISD::SIGN_EXTEND_INREG: { + // NOTE: we could fall back on load/store here too for targets without + // SAR. However, it is doubtful that any exist. + EVT ExtraVT = cast(Node->getOperand(1))->getVT(); + unsigned BitsDiff = Node->getValueType(0).getSizeInBits() - + ExtraVT.getSizeInBits(); + SDValue ShiftCst = DAG.getConstant(BitsDiff, TLI.getShiftAmountTy()); + Tmp1 = DAG.getNode(ISD::SHL, dl, Node->getValueType(0), + Node->getOperand(0), ShiftCst); + Tmp1 = DAG.getNode(ISD::SRA, dl, Node->getValueType(0), Tmp1, ShiftCst); + Results.push_back(Tmp1); + break; + } + case ISD::FP_ROUND_INREG: { + // The only way we can lower this is to turn it into a TRUNCSTORE, + // EXTLOAD pair, targetting a temporary location (a stack slot). + + // NOTE: there is a choice here between constantly creating new stack + // slots and always reusing the same one. We currently always create + // new ones, as reuse may inhibit scheduling. + EVT ExtraVT = cast(Node->getOperand(1))->getVT(); + Tmp1 = EmitStackConvert(Node->getOperand(0), ExtraVT, + Node->getValueType(0), dl); + Results.push_back(Tmp1); + break; + } + case ISD::SINT_TO_FP: + case ISD::UINT_TO_FP: + Tmp1 = ExpandLegalINT_TO_FP(Node->getOpcode() == ISD::SINT_TO_FP, + Node->getOperand(0), Node->getValueType(0), dl); + Results.push_back(Tmp1); + break; + case ISD::FP_TO_UINT: { + SDValue True, False; + EVT VT = Node->getOperand(0).getValueType(); + EVT NVT = Node->getValueType(0); + const uint64_t zero[] = {0, 0}; + APFloat apf = APFloat(APInt(VT.getSizeInBits(), 2, zero)); + APInt x = APInt::getSignBit(NVT.getSizeInBits()); + (void)apf.convertFromAPInt(x, false, APFloat::rmNearestTiesToEven); + Tmp1 = DAG.getConstantFP(apf, VT); + Tmp2 = DAG.getSetCC(dl, TLI.getSetCCResultType(VT), + Node->getOperand(0), + Tmp1, ISD::SETLT); + True = DAG.getNode(ISD::FP_TO_SINT, dl, NVT, Node->getOperand(0)); + False = DAG.getNode(ISD::FP_TO_SINT, dl, NVT, + DAG.getNode(ISD::FSUB, dl, VT, + Node->getOperand(0), Tmp1)); + False = DAG.getNode(ISD::XOR, dl, NVT, False, + DAG.getConstant(x, NVT)); + Tmp1 = DAG.getNode(ISD::SELECT, dl, NVT, Tmp2, True, False); + Results.push_back(Tmp1); + break; + } + case ISD::VAARG: { + const Value *V = cast(Node->getOperand(2))->getValue(); + EVT VT = Node->getValueType(0); + Tmp1 = Node->getOperand(0); + Tmp2 = Node->getOperand(1); + SDValue VAList = DAG.getLoad(TLI.getPointerTy(), dl, Tmp1, Tmp2, V, 0); + // Increment the pointer, VAList, to the next vaarg + Tmp3 = DAG.getNode(ISD::ADD, dl, TLI.getPointerTy(), VAList, + DAG.getConstant(TLI.getTargetData()-> + getTypeAllocSize(VT.getTypeForEVT(*DAG.getContext())), + TLI.getPointerTy())); + // Store the incremented VAList to the legalized pointer + Tmp3 = DAG.getStore(VAList.getValue(1), dl, Tmp3, Tmp2, V, 0); + // Load the actual argument out of the pointer VAList + Results.push_back(DAG.getLoad(VT, dl, Tmp3, VAList, NULL, 0)); + Results.push_back(Results[0].getValue(1)); + break; + } + case ISD::VACOPY: { + // This defaults to loading a pointer from the input and storing it to the + // output, returning the chain. + const Value *VD = cast(Node->getOperand(3))->getValue(); + const Value *VS = cast(Node->getOperand(4))->getValue(); + Tmp1 = DAG.getLoad(TLI.getPointerTy(), dl, Node->getOperand(0), + Node->getOperand(2), VS, 0); + Tmp1 = DAG.getStore(Tmp1.getValue(1), dl, Tmp1, Node->getOperand(1), VD, 0); + Results.push_back(Tmp1); + break; + } + case ISD::EXTRACT_VECTOR_ELT: + if (Node->getOperand(0).getValueType().getVectorNumElements() == 1) + // This must be an access of the only element. Return it. + Tmp1 = DAG.getNode(ISD::BIT_CONVERT, dl, Node->getValueType(0), + Node->getOperand(0)); + else + Tmp1 = ExpandExtractFromVectorThroughStack(SDValue(Node, 0)); + Results.push_back(Tmp1); + break; + case ISD::EXTRACT_SUBVECTOR: + Results.push_back(ExpandExtractFromVectorThroughStack(SDValue(Node, 0))); + break; + case ISD::CONCAT_VECTORS: { + Results.push_back(ExpandVectorBuildThroughStack(Node)); + break; + } + case ISD::SCALAR_TO_VECTOR: + Results.push_back(ExpandSCALAR_TO_VECTOR(Node)); + break; + case ISD::INSERT_VECTOR_ELT: + Results.push_back(ExpandINSERT_VECTOR_ELT(Node->getOperand(0), + Node->getOperand(1), + Node->getOperand(2), dl)); + break; + case ISD::VECTOR_SHUFFLE: { + SmallVector Mask; + cast(Node)->getMask(Mask); + + EVT VT = Node->getValueType(0); + EVT EltVT = VT.getVectorElementType(); + unsigned NumElems = VT.getVectorNumElements(); + SmallVector Ops; + for (unsigned i = 0; i != NumElems; ++i) { + if (Mask[i] < 0) { + Ops.push_back(DAG.getUNDEF(EltVT)); + continue; + } + unsigned Idx = Mask[i]; + if (Idx < NumElems) + Ops.push_back(DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, EltVT, + Node->getOperand(0), + DAG.getIntPtrConstant(Idx))); + else + Ops.push_back(DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, EltVT, + Node->getOperand(1), + DAG.getIntPtrConstant(Idx - NumElems))); + } + Tmp1 = DAG.getNode(ISD::BUILD_VECTOR, dl, VT, &Ops[0], Ops.size()); + Results.push_back(Tmp1); + break; + } + case ISD::EXTRACT_ELEMENT: { + EVT OpTy = Node->getOperand(0).getValueType(); + if (cast(Node->getOperand(1))->getZExtValue()) { + // 1 -> Hi + Tmp1 = DAG.getNode(ISD::SRL, dl, OpTy, Node->getOperand(0), + DAG.getConstant(OpTy.getSizeInBits()/2, + TLI.getShiftAmountTy())); + Tmp1 = DAG.getNode(ISD::TRUNCATE, dl, Node->getValueType(0), Tmp1); + } else { + // 0 -> Lo + Tmp1 = DAG.getNode(ISD::TRUNCATE, dl, Node->getValueType(0), + Node->getOperand(0)); + } + Results.push_back(Tmp1); + break; + } + case ISD::STACKSAVE: + // Expand to CopyFromReg if the target set + // StackPointerRegisterToSaveRestore. + if (unsigned SP = TLI.getStackPointerRegisterToSaveRestore()) { + Results.push_back(DAG.getCopyFromReg(Node->getOperand(0), dl, SP, + Node->getValueType(0))); + Results.push_back(Results[0].getValue(1)); + } else { + Results.push_back(DAG.getUNDEF(Node->getValueType(0))); + Results.push_back(Node->getOperand(0)); + } + break; + case ISD::STACKRESTORE: + // Expand to CopyToReg if the target set + // StackPointerRegisterToSaveRestore. + if (unsigned SP = TLI.getStackPointerRegisterToSaveRestore()) { + Results.push_back(DAG.getCopyToReg(Node->getOperand(0), dl, SP, + Node->getOperand(1))); + } else { + Results.push_back(Node->getOperand(0)); + } + break; + case ISD::FCOPYSIGN: + Results.push_back(ExpandFCOPYSIGN(Node)); + break; + case ISD::FNEG: + // Expand Y = FNEG(X) -> Y = SUB -0.0, X + Tmp1 = DAG.getConstantFP(-0.0, Node->getValueType(0)); + Tmp1 = DAG.getNode(ISD::FSUB, dl, Node->getValueType(0), Tmp1, + Node->getOperand(0)); + Results.push_back(Tmp1); + break; + case ISD::FABS: { + // Expand Y = FABS(X) -> Y = (X >u 0.0) ? X : fneg(X). + EVT VT = Node->getValueType(0); + Tmp1 = Node->getOperand(0); + Tmp2 = DAG.getConstantFP(0.0, VT); + Tmp2 = DAG.getSetCC(dl, TLI.getSetCCResultType(Tmp1.getValueType()), + Tmp1, Tmp2, ISD::SETUGT); + Tmp3 = DAG.getNode(ISD::FNEG, dl, VT, Tmp1); + Tmp1 = DAG.getNode(ISD::SELECT, dl, VT, Tmp2, Tmp1, Tmp3); + Results.push_back(Tmp1); + break; + } + case ISD::FSQRT: + Results.push_back(ExpandFPLibCall(Node, RTLIB::SQRT_F32, RTLIB::SQRT_F64, + RTLIB::SQRT_F80, RTLIB::SQRT_PPCF128)); + break; + case ISD::FSIN: + Results.push_back(ExpandFPLibCall(Node, RTLIB::SIN_F32, RTLIB::SIN_F64, + RTLIB::SIN_F80, RTLIB::SIN_PPCF128)); + break; + case ISD::FCOS: + Results.push_back(ExpandFPLibCall(Node, RTLIB::COS_F32, RTLIB::COS_F64, + RTLIB::COS_F80, RTLIB::COS_PPCF128)); + break; + case ISD::FLOG: + Results.push_back(ExpandFPLibCall(Node, RTLIB::LOG_F32, RTLIB::LOG_F64, + RTLIB::LOG_F80, RTLIB::LOG_PPCF128)); + break; + case ISD::FLOG2: + Results.push_back(ExpandFPLibCall(Node, RTLIB::LOG2_F32, RTLIB::LOG2_F64, + RTLIB::LOG2_F80, RTLIB::LOG2_PPCF128)); + break; + case ISD::FLOG10: + Results.push_back(ExpandFPLibCall(Node, RTLIB::LOG10_F32, RTLIB::LOG10_F64, + RTLIB::LOG10_F80, RTLIB::LOG10_PPCF128)); + break; + case ISD::FEXP: + Results.push_back(ExpandFPLibCall(Node, RTLIB::EXP_F32, RTLIB::EXP_F64, + RTLIB::EXP_F80, RTLIB::EXP_PPCF128)); + break; + case ISD::FEXP2: + Results.push_back(ExpandFPLibCall(Node, RTLIB::EXP2_F32, RTLIB::EXP2_F64, + RTLIB::EXP2_F80, RTLIB::EXP2_PPCF128)); + break; + case ISD::FTRUNC: + Results.push_back(ExpandFPLibCall(Node, RTLIB::TRUNC_F32, RTLIB::TRUNC_F64, + RTLIB::TRUNC_F80, RTLIB::TRUNC_PPCF128)); + break; + case ISD::FFLOOR: + Results.push_back(ExpandFPLibCall(Node, RTLIB::FLOOR_F32, RTLIB::FLOOR_F64, + RTLIB::FLOOR_F80, RTLIB::FLOOR_PPCF128)); + break; + case ISD::FCEIL: + Results.push_back(ExpandFPLibCall(Node, RTLIB::CEIL_F32, RTLIB::CEIL_F64, + RTLIB::CEIL_F80, RTLIB::CEIL_PPCF128)); + break; + case ISD::FRINT: + Results.push_back(ExpandFPLibCall(Node, RTLIB::RINT_F32, RTLIB::RINT_F64, + RTLIB::RINT_F80, RTLIB::RINT_PPCF128)); + break; + case ISD::FNEARBYINT: + Results.push_back(ExpandFPLibCall(Node, RTLIB::NEARBYINT_F32, + RTLIB::NEARBYINT_F64, + RTLIB::NEARBYINT_F80, + RTLIB::NEARBYINT_PPCF128)); + break; + case ISD::FPOWI: + Results.push_back(ExpandFPLibCall(Node, RTLIB::POWI_F32, RTLIB::POWI_F64, + RTLIB::POWI_F80, RTLIB::POWI_PPCF128)); + break; + case ISD::FPOW: + Results.push_back(ExpandFPLibCall(Node, RTLIB::POW_F32, RTLIB::POW_F64, + RTLIB::POW_F80, RTLIB::POW_PPCF128)); + break; + case ISD::FDIV: + Results.push_back(ExpandFPLibCall(Node, RTLIB::DIV_F32, RTLIB::DIV_F64, + RTLIB::DIV_F80, RTLIB::DIV_PPCF128)); + break; + case ISD::FREM: + Results.push_back(ExpandFPLibCall(Node, RTLIB::REM_F32, RTLIB::REM_F64, + RTLIB::REM_F80, RTLIB::REM_PPCF128)); + break; + case ISD::ConstantFP: { + ConstantFPSDNode *CFP = cast(Node); + // Check to see if this FP immediate is already legal. + // If this is a legal constant, turn it into a TargetConstantFP node. + if (TLI.isFPImmLegal(CFP->getValueAPF(), Node->getValueType(0))) + Results.push_back(SDValue(Node, 0)); + else + Results.push_back(ExpandConstantFP(CFP, true, DAG, TLI)); + break; + } + case ISD::EHSELECTION: { + unsigned Reg = TLI.getExceptionSelectorRegister(); + assert(Reg && "Can't expand to unknown register!"); + Results.push_back(DAG.getCopyFromReg(Node->getOperand(1), dl, Reg, + Node->getValueType(0))); + Results.push_back(Results[0].getValue(1)); + break; + } + case ISD::EXCEPTIONADDR: { + unsigned Reg = TLI.getExceptionAddressRegister(); + assert(Reg && "Can't expand to unknown register!"); + Results.push_back(DAG.getCopyFromReg(Node->getOperand(0), dl, Reg, + Node->getValueType(0))); + Results.push_back(Results[0].getValue(1)); + break; + } + case ISD::SUB: { + EVT VT = Node->getValueType(0); + assert(TLI.isOperationLegalOrCustom(ISD::ADD, VT) && + TLI.isOperationLegalOrCustom(ISD::XOR, VT) && + "Don't know how to expand this subtraction!"); + Tmp1 = DAG.getNode(ISD::XOR, dl, VT, Node->getOperand(1), + DAG.getConstant(APInt::getAllOnesValue(VT.getSizeInBits()), VT)); + Tmp1 = DAG.getNode(ISD::ADD, dl, VT, Tmp2, DAG.getConstant(1, VT)); + Results.push_back(DAG.getNode(ISD::ADD, dl, VT, Node->getOperand(0), Tmp1)); + break; + } + case ISD::UREM: + case ISD::SREM: { + EVT VT = Node->getValueType(0); + SDVTList VTs = DAG.getVTList(VT, VT); + bool isSigned = Node->getOpcode() == ISD::SREM; + unsigned DivOpc = isSigned ? ISD::SDIV : ISD::UDIV; + unsigned DivRemOpc = isSigned ? ISD::SDIVREM : ISD::UDIVREM; + Tmp2 = Node->getOperand(0); + Tmp3 = Node->getOperand(1); + if (TLI.isOperationLegalOrCustom(DivRemOpc, VT)) { + Tmp1 = DAG.getNode(DivRemOpc, dl, VTs, Tmp2, Tmp3).getValue(1); + } else if (TLI.isOperationLegalOrCustom(DivOpc, VT)) { + // X % Y -> X-X/Y*Y + Tmp1 = DAG.getNode(DivOpc, dl, VT, Tmp2, Tmp3); + Tmp1 = DAG.getNode(ISD::MUL, dl, VT, Tmp1, Tmp3); + Tmp1 = DAG.getNode(ISD::SUB, dl, VT, Tmp2, Tmp1); + } else if (isSigned) { + Tmp1 = ExpandIntLibCall(Node, true, + RTLIB::SREM_I8, + RTLIB::SREM_I16, RTLIB::SREM_I32, + RTLIB::SREM_I64, RTLIB::SREM_I128); + } else { + Tmp1 = ExpandIntLibCall(Node, false, + RTLIB::UREM_I8, + RTLIB::UREM_I16, RTLIB::UREM_I32, + RTLIB::UREM_I64, RTLIB::UREM_I128); + } + Results.push_back(Tmp1); + break; + } + case ISD::UDIV: + case ISD::SDIV: { + bool isSigned = Node->getOpcode() == ISD::SDIV; + unsigned DivRemOpc = isSigned ? ISD::SDIVREM : ISD::UDIVREM; + EVT VT = Node->getValueType(0); + SDVTList VTs = DAG.getVTList(VT, VT); + if (TLI.isOperationLegalOrCustom(DivRemOpc, VT)) + Tmp1 = DAG.getNode(DivRemOpc, dl, VTs, Node->getOperand(0), + Node->getOperand(1)); + else if (isSigned) + Tmp1 = ExpandIntLibCall(Node, true, + RTLIB::SDIV_I8, + RTLIB::SDIV_I16, RTLIB::SDIV_I32, + RTLIB::SDIV_I64, RTLIB::SDIV_I128); + else + Tmp1 = ExpandIntLibCall(Node, false, + RTLIB::UDIV_I8, + RTLIB::UDIV_I16, RTLIB::UDIV_I32, + RTLIB::UDIV_I64, RTLIB::UDIV_I128); + Results.push_back(Tmp1); + break; + } + case ISD::MULHU: + case ISD::MULHS: { + unsigned ExpandOpcode = Node->getOpcode() == ISD::MULHU ? ISD::UMUL_LOHI : + ISD::SMUL_LOHI; + EVT VT = Node->getValueType(0); + SDVTList VTs = DAG.getVTList(VT, VT); + assert(TLI.isOperationLegalOrCustom(ExpandOpcode, VT) && + "If this wasn't legal, it shouldn't have been created!"); + Tmp1 = DAG.getNode(ExpandOpcode, dl, VTs, Node->getOperand(0), + Node->getOperand(1)); + Results.push_back(Tmp1.getValue(1)); + break; + } + case ISD::MUL: { + EVT VT = Node->getValueType(0); + SDVTList VTs = DAG.getVTList(VT, VT); + // See if multiply or divide can be lowered using two-result operations. + // We just need the low half of the multiply; try both the signed + // and unsigned forms. If the target supports both SMUL_LOHI and + // UMUL_LOHI, form a preference by checking which forms of plain + // MULH it supports. + bool HasSMUL_LOHI = TLI.isOperationLegalOrCustom(ISD::SMUL_LOHI, VT); + bool HasUMUL_LOHI = TLI.isOperationLegalOrCustom(ISD::UMUL_LOHI, VT); + bool HasMULHS = TLI.isOperationLegalOrCustom(ISD::MULHS, VT); + bool HasMULHU = TLI.isOperationLegalOrCustom(ISD::MULHU, VT); + unsigned OpToUse = 0; + if (HasSMUL_LOHI && !HasMULHS) { + OpToUse = ISD::SMUL_LOHI; + } else if (HasUMUL_LOHI && !HasMULHU) { + OpToUse = ISD::UMUL_LOHI; + } else if (HasSMUL_LOHI) { + OpToUse = ISD::SMUL_LOHI; + } else if (HasUMUL_LOHI) { + OpToUse = ISD::UMUL_LOHI; + } + if (OpToUse) { + Results.push_back(DAG.getNode(OpToUse, dl, VTs, Node->getOperand(0), + Node->getOperand(1))); + break; + } + Tmp1 = ExpandIntLibCall(Node, false, + RTLIB::MUL_I8, + RTLIB::MUL_I16, RTLIB::MUL_I32, + RTLIB::MUL_I64, RTLIB::MUL_I128); + Results.push_back(Tmp1); + break; + } + case ISD::SADDO: + case ISD::SSUBO: { + SDValue LHS = Node->getOperand(0); + SDValue RHS = Node->getOperand(1); + SDValue Sum = DAG.getNode(Node->getOpcode() == ISD::SADDO ? + ISD::ADD : ISD::SUB, dl, LHS.getValueType(), + LHS, RHS); + Results.push_back(Sum); + EVT OType = Node->getValueType(1); + + SDValue Zero = DAG.getConstant(0, LHS.getValueType()); + + // LHSSign -> LHS >= 0 + // RHSSign -> RHS >= 0 + // SumSign -> Sum >= 0 + // + // Add: + // Overflow -> (LHSSign == RHSSign) && (LHSSign != SumSign) + // Sub: + // Overflow -> (LHSSign != RHSSign) && (LHSSign != SumSign) + // + SDValue LHSSign = DAG.getSetCC(dl, OType, LHS, Zero, ISD::SETGE); + SDValue RHSSign = DAG.getSetCC(dl, OType, RHS, Zero, ISD::SETGE); + SDValue SignsMatch = DAG.getSetCC(dl, OType, LHSSign, RHSSign, + Node->getOpcode() == ISD::SADDO ? + ISD::SETEQ : ISD::SETNE); + + SDValue SumSign = DAG.getSetCC(dl, OType, Sum, Zero, ISD::SETGE); + SDValue SumSignNE = DAG.getSetCC(dl, OType, LHSSign, SumSign, ISD::SETNE); + + SDValue Cmp = DAG.getNode(ISD::AND, dl, OType, SignsMatch, SumSignNE); + Results.push_back(Cmp); + break; + } + case ISD::UADDO: + case ISD::USUBO: { + SDValue LHS = Node->getOperand(0); + SDValue RHS = Node->getOperand(1); + SDValue Sum = DAG.getNode(Node->getOpcode() == ISD::UADDO ? + ISD::ADD : ISD::SUB, dl, LHS.getValueType(), + LHS, RHS); + Results.push_back(Sum); + Results.push_back(DAG.getSetCC(dl, Node->getValueType(1), Sum, LHS, + Node->getOpcode () == ISD::UADDO ? + ISD::SETULT : ISD::SETUGT)); + break; + } + case ISD::UMULO: + case ISD::SMULO: { + EVT VT = Node->getValueType(0); + SDValue LHS = Node->getOperand(0); + SDValue RHS = Node->getOperand(1); + SDValue BottomHalf; + SDValue TopHalf; + static unsigned Ops[2][3] = + { { ISD::MULHU, ISD::UMUL_LOHI, ISD::ZERO_EXTEND }, + { ISD::MULHS, ISD::SMUL_LOHI, ISD::SIGN_EXTEND }}; + bool isSigned = Node->getOpcode() == ISD::SMULO; + if (TLI.isOperationLegalOrCustom(Ops[isSigned][0], VT)) { + BottomHalf = DAG.getNode(ISD::MUL, dl, VT, LHS, RHS); + TopHalf = DAG.getNode(Ops[isSigned][0], dl, VT, LHS, RHS); + } else if (TLI.isOperationLegalOrCustom(Ops[isSigned][1], VT)) { + BottomHalf = DAG.getNode(Ops[isSigned][1], dl, DAG.getVTList(VT, VT), LHS, + RHS); + TopHalf = BottomHalf.getValue(1); + } else if (TLI.isTypeLegal(EVT::getIntegerVT(*DAG.getContext(), VT.getSizeInBits() * 2))) { + EVT WideVT = EVT::getIntegerVT(*DAG.getContext(), VT.getSizeInBits() * 2); + LHS = DAG.getNode(Ops[isSigned][2], dl, WideVT, LHS); + RHS = DAG.getNode(Ops[isSigned][2], dl, WideVT, RHS); + Tmp1 = DAG.getNode(ISD::MUL, dl, WideVT, LHS, RHS); + BottomHalf = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, VT, Tmp1, + DAG.getIntPtrConstant(0)); + TopHalf = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, VT, Tmp1, + DAG.getIntPtrConstant(1)); + } else { + // FIXME: We should be able to fall back to a libcall with an illegal + // type in some cases cases. + // Also, we can fall back to a division in some cases, but that's a big + // performance hit in the general case. + llvm_unreachable("Don't know how to expand this operation yet!"); + } + if (isSigned) { + Tmp1 = DAG.getConstant(VT.getSizeInBits() - 1, TLI.getShiftAmountTy()); + Tmp1 = DAG.getNode(ISD::SRA, dl, VT, BottomHalf, Tmp1); + TopHalf = DAG.getSetCC(dl, TLI.getSetCCResultType(VT), TopHalf, Tmp1, + ISD::SETNE); + } else { + TopHalf = DAG.getSetCC(dl, TLI.getSetCCResultType(VT), TopHalf, + DAG.getConstant(0, VT), ISD::SETNE); + } + Results.push_back(BottomHalf); + Results.push_back(TopHalf); + break; + } + case ISD::BUILD_PAIR: { + EVT PairTy = Node->getValueType(0); + Tmp1 = DAG.getNode(ISD::ZERO_EXTEND, dl, PairTy, Node->getOperand(0)); + Tmp2 = DAG.getNode(ISD::ANY_EXTEND, dl, PairTy, Node->getOperand(1)); + Tmp2 = DAG.getNode(ISD::SHL, dl, PairTy, Tmp2, + DAG.getConstant(PairTy.getSizeInBits()/2, + TLI.getShiftAmountTy())); + Results.push_back(DAG.getNode(ISD::OR, dl, PairTy, Tmp1, Tmp2)); + break; + } + case ISD::SELECT: + Tmp1 = Node->getOperand(0); + Tmp2 = Node->getOperand(1); + Tmp3 = Node->getOperand(2); + if (Tmp1.getOpcode() == ISD::SETCC) { + Tmp1 = DAG.getSelectCC(dl, Tmp1.getOperand(0), Tmp1.getOperand(1), + Tmp2, Tmp3, + cast(Tmp1.getOperand(2))->get()); + } else { + Tmp1 = DAG.getSelectCC(dl, Tmp1, + DAG.getConstant(0, Tmp1.getValueType()), + Tmp2, Tmp3, ISD::SETNE); + } + Results.push_back(Tmp1); + break; + case ISD::BR_JT: { + SDValue Chain = Node->getOperand(0); + SDValue Table = Node->getOperand(1); + SDValue Index = Node->getOperand(2); + + EVT PTy = TLI.getPointerTy(); + MachineFunction &MF = DAG.getMachineFunction(); + unsigned EntrySize = MF.getJumpTableInfo()->getEntrySize(); + Index= DAG.getNode(ISD::MUL, dl, PTy, + Index, DAG.getConstant(EntrySize, PTy)); + SDValue Addr = DAG.getNode(ISD::ADD, dl, PTy, Index, Table); + + EVT MemVT = EVT::getIntegerVT(*DAG.getContext(), EntrySize * 8); + SDValue LD = DAG.getExtLoad(ISD::SEXTLOAD, dl, PTy, Chain, Addr, + PseudoSourceValue::getJumpTable(), 0, MemVT); + Addr = LD; + if (TLI.getTargetMachine().getRelocationModel() == Reloc::PIC_) { + // For PIC, the sequence is: + // BRIND(load(Jumptable + index) + RelocBase) + // RelocBase can be JumpTable, GOT or some sort of global base. + Addr = DAG.getNode(ISD::ADD, dl, PTy, Addr, + TLI.getPICJumpTableRelocBase(Table, DAG)); + } + Tmp1 = DAG.getNode(ISD::BRIND, dl, MVT::Other, LD.getValue(1), Addr); + Results.push_back(Tmp1); + break; + } + case ISD::BRCOND: + // Expand brcond's setcc into its constituent parts and create a BR_CC + // Node. + Tmp1 = Node->getOperand(0); + Tmp2 = Node->getOperand(1); + if (Tmp2.getOpcode() == ISD::SETCC) { + Tmp1 = DAG.getNode(ISD::BR_CC, dl, MVT::Other, + Tmp1, Tmp2.getOperand(2), + Tmp2.getOperand(0), Tmp2.getOperand(1), + Node->getOperand(2)); + } else { + Tmp1 = DAG.getNode(ISD::BR_CC, dl, MVT::Other, Tmp1, + DAG.getCondCode(ISD::SETNE), Tmp2, + DAG.getConstant(0, Tmp2.getValueType()), + Node->getOperand(2)); + } + Results.push_back(Tmp1); + break; + case ISD::SETCC: { + Tmp1 = Node->getOperand(0); + Tmp2 = Node->getOperand(1); + Tmp3 = Node->getOperand(2); + LegalizeSetCCCondCode(Node->getValueType(0), Tmp1, Tmp2, Tmp3, dl); + + // If we expanded the SETCC into an AND/OR, return the new node + if (Tmp2.getNode() == 0) { + Results.push_back(Tmp1); + break; + } + + // Otherwise, SETCC for the given comparison type must be completely + // illegal; expand it into a SELECT_CC. + EVT VT = Node->getValueType(0); + Tmp1 = DAG.getNode(ISD::SELECT_CC, dl, VT, Tmp1, Tmp2, + DAG.getConstant(1, VT), DAG.getConstant(0, VT), Tmp3); + Results.push_back(Tmp1); + break; + } + case ISD::SELECT_CC: { + Tmp1 = Node->getOperand(0); // LHS + Tmp2 = Node->getOperand(1); // RHS + Tmp3 = Node->getOperand(2); // True + Tmp4 = Node->getOperand(3); // False + SDValue CC = Node->getOperand(4); + + LegalizeSetCCCondCode(TLI.getSetCCResultType(Tmp1.getValueType()), + Tmp1, Tmp2, CC, dl); + + assert(!Tmp2.getNode() && "Can't legalize SELECT_CC with legal condition!"); + Tmp2 = DAG.getConstant(0, Tmp1.getValueType()); + CC = DAG.getCondCode(ISD::SETNE); + Tmp1 = DAG.getNode(ISD::SELECT_CC, dl, Node->getValueType(0), Tmp1, Tmp2, + Tmp3, Tmp4, CC); + Results.push_back(Tmp1); + break; + } + case ISD::BR_CC: { + Tmp1 = Node->getOperand(0); // Chain + Tmp2 = Node->getOperand(2); // LHS + Tmp3 = Node->getOperand(3); // RHS + Tmp4 = Node->getOperand(1); // CC + + LegalizeSetCCCondCode(TLI.getSetCCResultType(Tmp2.getValueType()), + Tmp2, Tmp3, Tmp4, dl); + LastCALLSEQ_END = DAG.getEntryNode(); + + assert(!Tmp3.getNode() && "Can't legalize BR_CC with legal condition!"); + Tmp3 = DAG.getConstant(0, Tmp2.getValueType()); + Tmp4 = DAG.getCondCode(ISD::SETNE); + Tmp1 = DAG.getNode(ISD::BR_CC, dl, Node->getValueType(0), Tmp1, Tmp4, Tmp2, + Tmp3, Node->getOperand(4)); + Results.push_back(Tmp1); + break; + } + case ISD::GLOBAL_OFFSET_TABLE: + case ISD::GlobalAddress: + case ISD::GlobalTLSAddress: + case ISD::ExternalSymbol: + case ISD::ConstantPool: + case ISD::JumpTable: + case ISD::INTRINSIC_W_CHAIN: + case ISD::INTRINSIC_WO_CHAIN: + case ISD::INTRINSIC_VOID: + // FIXME: Custom lowering for these operations shouldn't return null! + for (unsigned i = 0, e = Node->getNumValues(); i != e; ++i) + Results.push_back(SDValue(Node, i)); + break; + } +} +void SelectionDAGLegalize::PromoteNode(SDNode *Node, + SmallVectorImpl &Results) { + EVT OVT = Node->getValueType(0); + if (Node->getOpcode() == ISD::UINT_TO_FP || + Node->getOpcode() == ISD::SINT_TO_FP || + Node->getOpcode() == ISD::SETCC) { + OVT = Node->getOperand(0).getValueType(); + } + EVT NVT = TLI.getTypeToPromoteTo(Node->getOpcode(), OVT); + DebugLoc dl = Node->getDebugLoc(); + SDValue Tmp1, Tmp2, Tmp3; + switch (Node->getOpcode()) { + case ISD::CTTZ: + case ISD::CTLZ: + case ISD::CTPOP: + // Zero extend the argument. + Tmp1 = DAG.getNode(ISD::ZERO_EXTEND, dl, NVT, Node->getOperand(0)); + // Perform the larger operation. + Tmp1 = DAG.getNode(Node->getOpcode(), dl, NVT, Tmp1); + if (Node->getOpcode() == ISD::CTTZ) { + //if Tmp1 == sizeinbits(NVT) then Tmp1 = sizeinbits(Old VT) + Tmp2 = DAG.getSetCC(dl, TLI.getSetCCResultType(NVT), + Tmp1, DAG.getConstant(NVT.getSizeInBits(), NVT), + ISD::SETEQ); + Tmp1 = DAG.getNode(ISD::SELECT, dl, NVT, Tmp2, + DAG.getConstant(OVT.getSizeInBits(), NVT), Tmp1); + } else if (Node->getOpcode() == ISD::CTLZ) { + // Tmp1 = Tmp1 - (sizeinbits(NVT) - sizeinbits(Old VT)) + Tmp1 = DAG.getNode(ISD::SUB, dl, NVT, Tmp1, + DAG.getConstant(NVT.getSizeInBits() - + OVT.getSizeInBits(), NVT)); + } + Results.push_back(DAG.getNode(ISD::TRUNCATE, dl, OVT, Tmp1)); + break; + case ISD::BSWAP: { + unsigned DiffBits = NVT.getSizeInBits() - OVT.getSizeInBits(); + Tmp1 = DAG.getNode(ISD::ZERO_EXTEND, dl, NVT, Tmp1); + Tmp1 = DAG.getNode(ISD::BSWAP, dl, NVT, Tmp1); + Tmp1 = DAG.getNode(ISD::SRL, dl, NVT, Tmp1, + DAG.getConstant(DiffBits, TLI.getShiftAmountTy())); + Results.push_back(Tmp1); + break; + } + case ISD::FP_TO_UINT: + case ISD::FP_TO_SINT: + Tmp1 = PromoteLegalFP_TO_INT(Node->getOperand(0), Node->getValueType(0), + Node->getOpcode() == ISD::FP_TO_SINT, dl); + Results.push_back(Tmp1); + break; + case ISD::UINT_TO_FP: + case ISD::SINT_TO_FP: + Tmp1 = PromoteLegalINT_TO_FP(Node->getOperand(0), Node->getValueType(0), + Node->getOpcode() == ISD::SINT_TO_FP, dl); + Results.push_back(Tmp1); + break; + case ISD::AND: + case ISD::OR: + case ISD::XOR: { + unsigned ExtOp, TruncOp; + if (OVT.isVector()) { + ExtOp = ISD::BIT_CONVERT; + TruncOp = ISD::BIT_CONVERT; + } else if (OVT.isInteger()) { + ExtOp = ISD::ANY_EXTEND; + TruncOp = ISD::TRUNCATE; + } else { + llvm_report_error("Cannot promote logic operation"); + } + // Promote each of the values to the new type. + Tmp1 = DAG.getNode(ExtOp, dl, NVT, Node->getOperand(0)); + Tmp2 = DAG.getNode(ExtOp, dl, NVT, Node->getOperand(1)); + // Perform the larger operation, then convert back + Tmp1 = DAG.getNode(Node->getOpcode(), dl, NVT, Tmp1, Tmp2); + Results.push_back(DAG.getNode(TruncOp, dl, OVT, Tmp1)); + break; + } + case ISD::SELECT: { + unsigned ExtOp, TruncOp; + if (Node->getValueType(0).isVector()) { + ExtOp = ISD::BIT_CONVERT; + TruncOp = ISD::BIT_CONVERT; + } else if (Node->getValueType(0).isInteger()) { + ExtOp = ISD::ANY_EXTEND; + TruncOp = ISD::TRUNCATE; + } else { + ExtOp = ISD::FP_EXTEND; + TruncOp = ISD::FP_ROUND; + } + Tmp1 = Node->getOperand(0); + // Promote each of the values to the new type. + Tmp2 = DAG.getNode(ExtOp, dl, NVT, Node->getOperand(1)); + Tmp3 = DAG.getNode(ExtOp, dl, NVT, Node->getOperand(2)); + // Perform the larger operation, then round down. + Tmp1 = DAG.getNode(ISD::SELECT, dl, NVT, Tmp1, Tmp2, Tmp3); + if (TruncOp != ISD::FP_ROUND) + Tmp1 = DAG.getNode(TruncOp, dl, Node->getValueType(0), Tmp1); + else + Tmp1 = DAG.getNode(TruncOp, dl, Node->getValueType(0), Tmp1, + DAG.getIntPtrConstant(0)); + Results.push_back(Tmp1); + break; + } + case ISD::VECTOR_SHUFFLE: { + SmallVector Mask; + cast(Node)->getMask(Mask); + + // Cast the two input vectors. + Tmp1 = DAG.getNode(ISD::BIT_CONVERT, dl, NVT, Node->getOperand(0)); + Tmp2 = DAG.getNode(ISD::BIT_CONVERT, dl, NVT, Node->getOperand(1)); + + // Convert the shuffle mask to the right # elements. + Tmp1 = ShuffleWithNarrowerEltType(NVT, OVT, dl, Tmp1, Tmp2, Mask); + Tmp1 = DAG.getNode(ISD::BIT_CONVERT, dl, OVT, Tmp1); + Results.push_back(Tmp1); + break; + } + case ISD::SETCC: { + unsigned ExtOp = ISD::FP_EXTEND; + if (NVT.isInteger()) { + ISD::CondCode CCCode = + cast(Node->getOperand(2))->get(); + ExtOp = isSignedIntSetCC(CCCode) ? ISD::SIGN_EXTEND : ISD::ZERO_EXTEND; + } + Tmp1 = DAG.getNode(ExtOp, dl, NVT, Node->getOperand(0)); + Tmp2 = DAG.getNode(ExtOp, dl, NVT, Node->getOperand(1)); + Results.push_back(DAG.getNode(ISD::SETCC, dl, Node->getValueType(0), + Tmp1, Tmp2, Node->getOperand(2))); + break; + } + } +} + +// SelectionDAG::Legalize - This is the entry point for the file. +// +void SelectionDAG::Legalize(bool TypesNeedLegalizing, + CodeGenOpt::Level OptLevel) { + /// run - This is the main entry point to this class. + /// + SelectionDAGLegalize(*this, OptLevel).LegalizeDAG(); +} + diff --git a/libclamav/c++/llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp b/libclamav/c++/llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp new file mode 100644 index 000000000..84e39b480 --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp @@ -0,0 +1,1386 @@ +//===-------- LegalizeFloatTypes.cpp - Legalization of float types --------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements float type expansion and softening for LegalizeTypes. +// Softening is the act of turning a computation in an illegal floating point +// type into a computation in an integer type of the same size; also known as +// "soft float". For example, turning f32 arithmetic into operations using i32. +// The resulting integer value is the same as what you would get by performing +// the floating point operation and bitcasting the result to the integer type. +// Expansion is the act of changing a computation in an illegal type to be a +// computation in two identical registers of a smaller type. For example, +// implementing ppcf128 arithmetic in two f64 registers. +// +//===----------------------------------------------------------------------===// + +#include "LegalizeTypes.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +/// GetFPLibCall - Return the right libcall for the given floating point type. +static RTLIB::Libcall GetFPLibCall(EVT VT, + RTLIB::Libcall Call_F32, + RTLIB::Libcall Call_F64, + RTLIB::Libcall Call_F80, + RTLIB::Libcall Call_PPCF128) { + return + VT == MVT::f32 ? Call_F32 : + VT == MVT::f64 ? Call_F64 : + VT == MVT::f80 ? Call_F80 : + VT == MVT::ppcf128 ? Call_PPCF128 : + RTLIB::UNKNOWN_LIBCALL; +} + +//===----------------------------------------------------------------------===// +// Result Float to Integer Conversion. +//===----------------------------------------------------------------------===// + +void DAGTypeLegalizer::SoftenFloatResult(SDNode *N, unsigned ResNo) { + DEBUG(errs() << "Soften float result " << ResNo << ": "; N->dump(&DAG); + errs() << "\n"); + SDValue R = SDValue(); + + switch (N->getOpcode()) { + default: +#ifndef NDEBUG + errs() << "SoftenFloatResult #" << ResNo << ": "; + N->dump(&DAG); errs() << "\n"; +#endif + llvm_unreachable("Do not know how to soften the result of this operator!"); + + case ISD::BIT_CONVERT: R = SoftenFloatRes_BIT_CONVERT(N); break; + case ISD::BUILD_PAIR: R = SoftenFloatRes_BUILD_PAIR(N); break; + case ISD::ConstantFP: + R = SoftenFloatRes_ConstantFP(cast(N)); + break; + case ISD::EXTRACT_VECTOR_ELT: + R = SoftenFloatRes_EXTRACT_VECTOR_ELT(N); break; + case ISD::FABS: R = SoftenFloatRes_FABS(N); break; + case ISD::FADD: R = SoftenFloatRes_FADD(N); break; + case ISD::FCEIL: R = SoftenFloatRes_FCEIL(N); break; + case ISD::FCOPYSIGN: R = SoftenFloatRes_FCOPYSIGN(N); break; + case ISD::FCOS: R = SoftenFloatRes_FCOS(N); break; + case ISD::FDIV: R = SoftenFloatRes_FDIV(N); break; + case ISD::FEXP: R = SoftenFloatRes_FEXP(N); break; + case ISD::FEXP2: R = SoftenFloatRes_FEXP2(N); break; + case ISD::FFLOOR: R = SoftenFloatRes_FFLOOR(N); break; + case ISD::FLOG: R = SoftenFloatRes_FLOG(N); break; + case ISD::FLOG2: R = SoftenFloatRes_FLOG2(N); break; + case ISD::FLOG10: R = SoftenFloatRes_FLOG10(N); break; + case ISD::FMUL: R = SoftenFloatRes_FMUL(N); break; + case ISD::FNEARBYINT: R = SoftenFloatRes_FNEARBYINT(N); break; + case ISD::FNEG: R = SoftenFloatRes_FNEG(N); break; + case ISD::FP_EXTEND: R = SoftenFloatRes_FP_EXTEND(N); break; + case ISD::FP_ROUND: R = SoftenFloatRes_FP_ROUND(N); break; + case ISD::FPOW: R = SoftenFloatRes_FPOW(N); break; + case ISD::FPOWI: R = SoftenFloatRes_FPOWI(N); break; + case ISD::FREM: R = SoftenFloatRes_FREM(N); break; + case ISD::FRINT: R = SoftenFloatRes_FRINT(N); break; + case ISD::FSIN: R = SoftenFloatRes_FSIN(N); break; + case ISD::FSQRT: R = SoftenFloatRes_FSQRT(N); break; + case ISD::FSUB: R = SoftenFloatRes_FSUB(N); break; + case ISD::FTRUNC: R = SoftenFloatRes_FTRUNC(N); break; + case ISD::LOAD: R = SoftenFloatRes_LOAD(N); break; + case ISD::SELECT: R = SoftenFloatRes_SELECT(N); break; + case ISD::SELECT_CC: R = SoftenFloatRes_SELECT_CC(N); break; + case ISD::SINT_TO_FP: + case ISD::UINT_TO_FP: R = SoftenFloatRes_XINT_TO_FP(N); break; + case ISD::UNDEF: R = SoftenFloatRes_UNDEF(N); break; + case ISD::VAARG: R = SoftenFloatRes_VAARG(N); break; + } + + // If R is null, the sub-method took care of registering the result. + if (R.getNode()) + SetSoftenedFloat(SDValue(N, ResNo), R); +} + +SDValue DAGTypeLegalizer::SoftenFloatRes_BIT_CONVERT(SDNode *N) { + return BitConvertToInteger(N->getOperand(0)); +} + +SDValue DAGTypeLegalizer::SoftenFloatRes_BUILD_PAIR(SDNode *N) { + // Convert the inputs to integers, and build a new pair out of them. + return DAG.getNode(ISD::BUILD_PAIR, N->getDebugLoc(), + TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)), + BitConvertToInteger(N->getOperand(0)), + BitConvertToInteger(N->getOperand(1))); +} + +SDValue DAGTypeLegalizer::SoftenFloatRes_ConstantFP(ConstantFPSDNode *N) { + return DAG.getConstant(N->getValueAPF().bitcastToAPInt(), + TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0))); +} + +SDValue DAGTypeLegalizer::SoftenFloatRes_EXTRACT_VECTOR_ELT(SDNode *N) { + SDValue NewOp = BitConvertVectorToIntegerVector(N->getOperand(0)); + return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, N->getDebugLoc(), + NewOp.getValueType().getVectorElementType(), + NewOp, N->getOperand(1)); +} + +SDValue DAGTypeLegalizer::SoftenFloatRes_FABS(SDNode *N) { + EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); + unsigned Size = NVT.getSizeInBits(); + + // Mask = ~(1 << (Size-1)) + SDValue Mask = DAG.getConstant(APInt::getAllOnesValue(Size).clear(Size-1), + NVT); + SDValue Op = GetSoftenedFloat(N->getOperand(0)); + return DAG.getNode(ISD::AND, N->getDebugLoc(), NVT, Op, Mask); +} + +SDValue DAGTypeLegalizer::SoftenFloatRes_FADD(SDNode *N) { + EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); + SDValue Ops[2] = { GetSoftenedFloat(N->getOperand(0)), + GetSoftenedFloat(N->getOperand(1)) }; + return MakeLibCall(GetFPLibCall(N->getValueType(0), + RTLIB::ADD_F32, + RTLIB::ADD_F64, + RTLIB::ADD_F80, + RTLIB::ADD_PPCF128), + NVT, Ops, 2, false, N->getDebugLoc()); +} + +SDValue DAGTypeLegalizer::SoftenFloatRes_FCEIL(SDNode *N) { + EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); + SDValue Op = GetSoftenedFloat(N->getOperand(0)); + return MakeLibCall(GetFPLibCall(N->getValueType(0), + RTLIB::CEIL_F32, + RTLIB::CEIL_F64, + RTLIB::CEIL_F80, + RTLIB::CEIL_PPCF128), + NVT, &Op, 1, false, N->getDebugLoc()); +} + +SDValue DAGTypeLegalizer::SoftenFloatRes_FCOPYSIGN(SDNode *N) { + SDValue LHS = GetSoftenedFloat(N->getOperand(0)); + SDValue RHS = BitConvertToInteger(N->getOperand(1)); + DebugLoc dl = N->getDebugLoc(); + + EVT LVT = LHS.getValueType(); + EVT RVT = RHS.getValueType(); + + unsigned LSize = LVT.getSizeInBits(); + unsigned RSize = RVT.getSizeInBits(); + + // First get the sign bit of second operand. + SDValue SignBit = DAG.getNode(ISD::SHL, dl, RVT, DAG.getConstant(1, RVT), + DAG.getConstant(RSize - 1, + TLI.getShiftAmountTy())); + SignBit = DAG.getNode(ISD::AND, dl, RVT, RHS, SignBit); + + // Shift right or sign-extend it if the two operands have different types. + int SizeDiff = RVT.getSizeInBits() - LVT.getSizeInBits(); + if (SizeDiff > 0) { + SignBit = DAG.getNode(ISD::SRL, dl, RVT, SignBit, + DAG.getConstant(SizeDiff, TLI.getShiftAmountTy())); + SignBit = DAG.getNode(ISD::TRUNCATE, dl, LVT, SignBit); + } else if (SizeDiff < 0) { + SignBit = DAG.getNode(ISD::ANY_EXTEND, dl, LVT, SignBit); + SignBit = DAG.getNode(ISD::SHL, dl, LVT, SignBit, + DAG.getConstant(-SizeDiff, TLI.getShiftAmountTy())); + } + + // Clear the sign bit of the first operand. + SDValue Mask = DAG.getNode(ISD::SHL, dl, LVT, DAG.getConstant(1, LVT), + DAG.getConstant(LSize - 1, + TLI.getShiftAmountTy())); + Mask = DAG.getNode(ISD::SUB, dl, LVT, Mask, DAG.getConstant(1, LVT)); + LHS = DAG.getNode(ISD::AND, dl, LVT, LHS, Mask); + + // Or the value with the sign bit. + return DAG.getNode(ISD::OR, dl, LVT, LHS, SignBit); +} + +SDValue DAGTypeLegalizer::SoftenFloatRes_FCOS(SDNode *N) { + EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); + SDValue Op = GetSoftenedFloat(N->getOperand(0)); + return MakeLibCall(GetFPLibCall(N->getValueType(0), + RTLIB::COS_F32, + RTLIB::COS_F64, + RTLIB::COS_F80, + RTLIB::COS_PPCF128), + NVT, &Op, 1, false, N->getDebugLoc()); +} + +SDValue DAGTypeLegalizer::SoftenFloatRes_FDIV(SDNode *N) { + EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); + SDValue Ops[2] = { GetSoftenedFloat(N->getOperand(0)), + GetSoftenedFloat(N->getOperand(1)) }; + return MakeLibCall(GetFPLibCall(N->getValueType(0), + RTLIB::DIV_F32, + RTLIB::DIV_F64, + RTLIB::DIV_F80, + RTLIB::DIV_PPCF128), + NVT, Ops, 2, false, N->getDebugLoc()); +} + +SDValue DAGTypeLegalizer::SoftenFloatRes_FEXP(SDNode *N) { + EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); + SDValue Op = GetSoftenedFloat(N->getOperand(0)); + return MakeLibCall(GetFPLibCall(N->getValueType(0), + RTLIB::EXP_F32, + RTLIB::EXP_F64, + RTLIB::EXP_F80, + RTLIB::EXP_PPCF128), + NVT, &Op, 1, false, N->getDebugLoc()); +} + +SDValue DAGTypeLegalizer::SoftenFloatRes_FEXP2(SDNode *N) { + EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); + SDValue Op = GetSoftenedFloat(N->getOperand(0)); + return MakeLibCall(GetFPLibCall(N->getValueType(0), + RTLIB::EXP2_F32, + RTLIB::EXP2_F64, + RTLIB::EXP2_F80, + RTLIB::EXP2_PPCF128), + NVT, &Op, 1, false, N->getDebugLoc()); +} + +SDValue DAGTypeLegalizer::SoftenFloatRes_FFLOOR(SDNode *N) { + EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); + SDValue Op = GetSoftenedFloat(N->getOperand(0)); + return MakeLibCall(GetFPLibCall(N->getValueType(0), + RTLIB::FLOOR_F32, + RTLIB::FLOOR_F64, + RTLIB::FLOOR_F80, + RTLIB::FLOOR_PPCF128), + NVT, &Op, 1, false, N->getDebugLoc()); +} + +SDValue DAGTypeLegalizer::SoftenFloatRes_FLOG(SDNode *N) { + EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); + SDValue Op = GetSoftenedFloat(N->getOperand(0)); + return MakeLibCall(GetFPLibCall(N->getValueType(0), + RTLIB::LOG_F32, + RTLIB::LOG_F64, + RTLIB::LOG_F80, + RTLIB::LOG_PPCF128), + NVT, &Op, 1, false, N->getDebugLoc()); +} + +SDValue DAGTypeLegalizer::SoftenFloatRes_FLOG2(SDNode *N) { + EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); + SDValue Op = GetSoftenedFloat(N->getOperand(0)); + return MakeLibCall(GetFPLibCall(N->getValueType(0), + RTLIB::LOG2_F32, + RTLIB::LOG2_F64, + RTLIB::LOG2_F80, + RTLIB::LOG2_PPCF128), + NVT, &Op, 1, false, N->getDebugLoc()); +} + +SDValue DAGTypeLegalizer::SoftenFloatRes_FLOG10(SDNode *N) { + EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); + SDValue Op = GetSoftenedFloat(N->getOperand(0)); + return MakeLibCall(GetFPLibCall(N->getValueType(0), + RTLIB::LOG10_F32, + RTLIB::LOG10_F64, + RTLIB::LOG10_F80, + RTLIB::LOG10_PPCF128), + NVT, &Op, 1, false, N->getDebugLoc()); +} + +SDValue DAGTypeLegalizer::SoftenFloatRes_FMUL(SDNode *N) { + EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); + SDValue Ops[2] = { GetSoftenedFloat(N->getOperand(0)), + GetSoftenedFloat(N->getOperand(1)) }; + return MakeLibCall(GetFPLibCall(N->getValueType(0), + RTLIB::MUL_F32, + RTLIB::MUL_F64, + RTLIB::MUL_F80, + RTLIB::MUL_PPCF128), + NVT, Ops, 2, false, N->getDebugLoc()); +} + +SDValue DAGTypeLegalizer::SoftenFloatRes_FNEARBYINT(SDNode *N) { + EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); + SDValue Op = GetSoftenedFloat(N->getOperand(0)); + return MakeLibCall(GetFPLibCall(N->getValueType(0), + RTLIB::NEARBYINT_F32, + RTLIB::NEARBYINT_F64, + RTLIB::NEARBYINT_F80, + RTLIB::NEARBYINT_PPCF128), + NVT, &Op, 1, false, N->getDebugLoc()); +} + +SDValue DAGTypeLegalizer::SoftenFloatRes_FNEG(SDNode *N) { + EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); + // Expand Y = FNEG(X) -> Y = SUB -0.0, X + SDValue Ops[2] = { DAG.getConstantFP(-0.0, N->getValueType(0)), + GetSoftenedFloat(N->getOperand(0)) }; + return MakeLibCall(GetFPLibCall(N->getValueType(0), + RTLIB::SUB_F32, + RTLIB::SUB_F64, + RTLIB::SUB_F80, + RTLIB::SUB_PPCF128), + NVT, Ops, 2, false, N->getDebugLoc()); +} + +SDValue DAGTypeLegalizer::SoftenFloatRes_FP_EXTEND(SDNode *N) { + EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); + SDValue Op = N->getOperand(0); + RTLIB::Libcall LC = RTLIB::getFPEXT(Op.getValueType(), N->getValueType(0)); + assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unsupported FP_EXTEND!"); + return MakeLibCall(LC, NVT, &Op, 1, false, N->getDebugLoc()); +} + +SDValue DAGTypeLegalizer::SoftenFloatRes_FP_ROUND(SDNode *N) { + EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); + SDValue Op = N->getOperand(0); + RTLIB::Libcall LC = RTLIB::getFPROUND(Op.getValueType(), N->getValueType(0)); + assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unsupported FP_ROUND!"); + return MakeLibCall(LC, NVT, &Op, 1, false, N->getDebugLoc()); +} + +SDValue DAGTypeLegalizer::SoftenFloatRes_FPOW(SDNode *N) { + EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); + SDValue Ops[2] = { GetSoftenedFloat(N->getOperand(0)), + GetSoftenedFloat(N->getOperand(1)) }; + return MakeLibCall(GetFPLibCall(N->getValueType(0), + RTLIB::POW_F32, + RTLIB::POW_F64, + RTLIB::POW_F80, + RTLIB::POW_PPCF128), + NVT, Ops, 2, false, N->getDebugLoc()); +} + +SDValue DAGTypeLegalizer::SoftenFloatRes_FPOWI(SDNode *N) { + assert(N->getOperand(1).getValueType() == MVT::i32 && + "Unsupported power type!"); + EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); + SDValue Ops[2] = { GetSoftenedFloat(N->getOperand(0)), N->getOperand(1) }; + return MakeLibCall(GetFPLibCall(N->getValueType(0), + RTLIB::POWI_F32, + RTLIB::POWI_F64, + RTLIB::POWI_F80, + RTLIB::POWI_PPCF128), + NVT, Ops, 2, false, N->getDebugLoc()); +} + +SDValue DAGTypeLegalizer::SoftenFloatRes_FREM(SDNode *N) { + EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); + SDValue Ops[2] = { GetSoftenedFloat(N->getOperand(0)), + GetSoftenedFloat(N->getOperand(1)) }; + return MakeLibCall(GetFPLibCall(N->getValueType(0), + RTLIB::REM_F32, + RTLIB::REM_F64, + RTLIB::REM_F80, + RTLIB::REM_PPCF128), + NVT, Ops, 2, false, N->getDebugLoc()); +} + +SDValue DAGTypeLegalizer::SoftenFloatRes_FRINT(SDNode *N) { + EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); + SDValue Op = GetSoftenedFloat(N->getOperand(0)); + return MakeLibCall(GetFPLibCall(N->getValueType(0), + RTLIB::RINT_F32, + RTLIB::RINT_F64, + RTLIB::RINT_F80, + RTLIB::RINT_PPCF128), + NVT, &Op, 1, false, N->getDebugLoc()); +} + +SDValue DAGTypeLegalizer::SoftenFloatRes_FSIN(SDNode *N) { + EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); + SDValue Op = GetSoftenedFloat(N->getOperand(0)); + return MakeLibCall(GetFPLibCall(N->getValueType(0), + RTLIB::SIN_F32, + RTLIB::SIN_F64, + RTLIB::SIN_F80, + RTLIB::SIN_PPCF128), + NVT, &Op, 1, false, N->getDebugLoc()); +} + +SDValue DAGTypeLegalizer::SoftenFloatRes_FSQRT(SDNode *N) { + EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); + SDValue Op = GetSoftenedFloat(N->getOperand(0)); + return MakeLibCall(GetFPLibCall(N->getValueType(0), + RTLIB::SQRT_F32, + RTLIB::SQRT_F64, + RTLIB::SQRT_F80, + RTLIB::SQRT_PPCF128), + NVT, &Op, 1, false, N->getDebugLoc()); +} + +SDValue DAGTypeLegalizer::SoftenFloatRes_FSUB(SDNode *N) { + EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); + SDValue Ops[2] = { GetSoftenedFloat(N->getOperand(0)), + GetSoftenedFloat(N->getOperand(1)) }; + return MakeLibCall(GetFPLibCall(N->getValueType(0), + RTLIB::SUB_F32, + RTLIB::SUB_F64, + RTLIB::SUB_F80, + RTLIB::SUB_PPCF128), + NVT, Ops, 2, false, N->getDebugLoc()); +} + +SDValue DAGTypeLegalizer::SoftenFloatRes_FTRUNC(SDNode *N) { + EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); + SDValue Op = GetSoftenedFloat(N->getOperand(0)); + return MakeLibCall(GetFPLibCall(N->getValueType(0), + RTLIB::TRUNC_F32, + RTLIB::TRUNC_F64, + RTLIB::TRUNC_F80, + RTLIB::TRUNC_PPCF128), + NVT, &Op, 1, false, N->getDebugLoc()); +} + +SDValue DAGTypeLegalizer::SoftenFloatRes_LOAD(SDNode *N) { + LoadSDNode *L = cast(N); + EVT VT = N->getValueType(0); + EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT); + DebugLoc dl = N->getDebugLoc(); + + SDValue NewL; + if (L->getExtensionType() == ISD::NON_EXTLOAD) { + NewL = DAG.getLoad(L->getAddressingMode(), dl, L->getExtensionType(), + NVT, L->getChain(), L->getBasePtr(), L->getOffset(), + L->getSrcValue(), L->getSrcValueOffset(), NVT, + L->isVolatile(), L->getAlignment()); + // Legalized the chain result - switch anything that used the old chain to + // use the new one. + ReplaceValueWith(SDValue(N, 1), NewL.getValue(1)); + return NewL; + } + + // Do a non-extending load followed by FP_EXTEND. + NewL = DAG.getLoad(L->getAddressingMode(), dl, ISD::NON_EXTLOAD, + L->getMemoryVT(), L->getChain(), + L->getBasePtr(), L->getOffset(), + L->getSrcValue(), L->getSrcValueOffset(), + L->getMemoryVT(), + L->isVolatile(), L->getAlignment()); + // Legalized the chain result - switch anything that used the old chain to + // use the new one. + ReplaceValueWith(SDValue(N, 1), NewL.getValue(1)); + return BitConvertToInteger(DAG.getNode(ISD::FP_EXTEND, dl, VT, NewL)); +} + +SDValue DAGTypeLegalizer::SoftenFloatRes_SELECT(SDNode *N) { + SDValue LHS = GetSoftenedFloat(N->getOperand(1)); + SDValue RHS = GetSoftenedFloat(N->getOperand(2)); + return DAG.getNode(ISD::SELECT, N->getDebugLoc(), + LHS.getValueType(), N->getOperand(0),LHS,RHS); +} + +SDValue DAGTypeLegalizer::SoftenFloatRes_SELECT_CC(SDNode *N) { + SDValue LHS = GetSoftenedFloat(N->getOperand(2)); + SDValue RHS = GetSoftenedFloat(N->getOperand(3)); + return DAG.getNode(ISD::SELECT_CC, N->getDebugLoc(), + LHS.getValueType(), N->getOperand(0), + N->getOperand(1), LHS, RHS, N->getOperand(4)); +} + +SDValue DAGTypeLegalizer::SoftenFloatRes_UNDEF(SDNode *N) { + return DAG.getUNDEF(TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0))); +} + +SDValue DAGTypeLegalizer::SoftenFloatRes_VAARG(SDNode *N) { + SDValue Chain = N->getOperand(0); // Get the chain. + SDValue Ptr = N->getOperand(1); // Get the pointer. + EVT VT = N->getValueType(0); + EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT); + DebugLoc dl = N->getDebugLoc(); + + SDValue NewVAARG; + NewVAARG = DAG.getVAArg(NVT, dl, Chain, Ptr, N->getOperand(2)); + + // Legalized the chain result - switch anything that used the old chain to + // use the new one. + ReplaceValueWith(SDValue(N, 1), NewVAARG.getValue(1)); + return NewVAARG; +} + +SDValue DAGTypeLegalizer::SoftenFloatRes_XINT_TO_FP(SDNode *N) { + bool Signed = N->getOpcode() == ISD::SINT_TO_FP; + EVT SVT = N->getOperand(0).getValueType(); + EVT RVT = N->getValueType(0); + EVT NVT = EVT(); + DebugLoc dl = N->getDebugLoc(); + + // If the input is not legal, eg: i1 -> fp, then it needs to be promoted to + // a larger type, eg: i8 -> fp. Even if it is legal, no libcall may exactly + // match. Look for an appropriate libcall. + RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL; + for (unsigned t = MVT::FIRST_INTEGER_VALUETYPE; + t <= MVT::LAST_INTEGER_VALUETYPE && LC == RTLIB::UNKNOWN_LIBCALL; ++t) { + NVT = (MVT::SimpleValueType)t; + // The source needs to big enough to hold the operand. + if (NVT.bitsGE(SVT)) + LC = Signed ? RTLIB::getSINTTOFP(NVT, RVT):RTLIB::getUINTTOFP (NVT, RVT); + } + assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unsupported XINT_TO_FP!"); + + // Sign/zero extend the argument if the libcall takes a larger type. + SDValue Op = DAG.getNode(Signed ? ISD::SIGN_EXTEND : ISD::ZERO_EXTEND, dl, + NVT, N->getOperand(0)); + return MakeLibCall(LC, TLI.getTypeToTransformTo(*DAG.getContext(), RVT), &Op, 1, false, dl); +} + + +//===----------------------------------------------------------------------===// +// Operand Float to Integer Conversion.. +//===----------------------------------------------------------------------===// + +bool DAGTypeLegalizer::SoftenFloatOperand(SDNode *N, unsigned OpNo) { + DEBUG(errs() << "Soften float operand " << OpNo << ": "; N->dump(&DAG); + errs() << "\n"); + SDValue Res = SDValue(); + + switch (N->getOpcode()) { + default: +#ifndef NDEBUG + errs() << "SoftenFloatOperand Op #" << OpNo << ": "; + N->dump(&DAG); errs() << "\n"; +#endif + llvm_unreachable("Do not know how to soften this operator's operand!"); + + case ISD::BIT_CONVERT: Res = SoftenFloatOp_BIT_CONVERT(N); break; + case ISD::BR_CC: Res = SoftenFloatOp_BR_CC(N); break; + case ISD::FP_ROUND: Res = SoftenFloatOp_FP_ROUND(N); break; + case ISD::FP_TO_SINT: Res = SoftenFloatOp_FP_TO_SINT(N); break; + case ISD::FP_TO_UINT: Res = SoftenFloatOp_FP_TO_UINT(N); break; + case ISD::SELECT_CC: Res = SoftenFloatOp_SELECT_CC(N); break; + case ISD::SETCC: Res = SoftenFloatOp_SETCC(N); break; + case ISD::STORE: Res = SoftenFloatOp_STORE(N, OpNo); break; + } + + // If the result is null, the sub-method took care of registering results etc. + if (!Res.getNode()) return false; + + // If the result is N, the sub-method updated N in place. Tell the legalizer + // core about this. + if (Res.getNode() == N) + return true; + + assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 1 && + "Invalid operand expansion"); + + ReplaceValueWith(SDValue(N, 0), Res); + return false; +} + +/// SoftenSetCCOperands - Soften the operands of a comparison. This code is +/// shared among BR_CC, SELECT_CC, and SETCC handlers. +void DAGTypeLegalizer::SoftenSetCCOperands(SDValue &NewLHS, SDValue &NewRHS, + ISD::CondCode &CCCode, DebugLoc dl) { + SDValue LHSInt = GetSoftenedFloat(NewLHS); + SDValue RHSInt = GetSoftenedFloat(NewRHS); + EVT VT = NewLHS.getValueType(); + + assert((VT == MVT::f32 || VT == MVT::f64) && "Unsupported setcc type!"); + + // Expand into one or more soft-fp libcall(s). + RTLIB::Libcall LC1 = RTLIB::UNKNOWN_LIBCALL, LC2 = RTLIB::UNKNOWN_LIBCALL; + switch (CCCode) { + case ISD::SETEQ: + case ISD::SETOEQ: + LC1 = (VT == MVT::f32) ? RTLIB::OEQ_F32 : RTLIB::OEQ_F64; + break; + case ISD::SETNE: + case ISD::SETUNE: + LC1 = (VT == MVT::f32) ? RTLIB::UNE_F32 : RTLIB::UNE_F64; + break; + case ISD::SETGE: + case ISD::SETOGE: + LC1 = (VT == MVT::f32) ? RTLIB::OGE_F32 : RTLIB::OGE_F64; + break; + case ISD::SETLT: + case ISD::SETOLT: + LC1 = (VT == MVT::f32) ? RTLIB::OLT_F32 : RTLIB::OLT_F64; + break; + case ISD::SETLE: + case ISD::SETOLE: + LC1 = (VT == MVT::f32) ? RTLIB::OLE_F32 : RTLIB::OLE_F64; + break; + case ISD::SETGT: + case ISD::SETOGT: + LC1 = (VT == MVT::f32) ? RTLIB::OGT_F32 : RTLIB::OGT_F64; + break; + case ISD::SETUO: + LC1 = (VT == MVT::f32) ? RTLIB::UO_F32 : RTLIB::UO_F64; + break; + case ISD::SETO: + LC1 = (VT == MVT::f32) ? RTLIB::O_F32 : RTLIB::O_F64; + break; + default: + LC1 = (VT == MVT::f32) ? RTLIB::UO_F32 : RTLIB::UO_F64; + switch (CCCode) { + case ISD::SETONE: + // SETONE = SETOLT | SETOGT + LC1 = (VT == MVT::f32) ? RTLIB::OLT_F32 : RTLIB::OLT_F64; + // Fallthrough + case ISD::SETUGT: + LC2 = (VT == MVT::f32) ? RTLIB::OGT_F32 : RTLIB::OGT_F64; + break; + case ISD::SETUGE: + LC2 = (VT == MVT::f32) ? RTLIB::OGE_F32 : RTLIB::OGE_F64; + break; + case ISD::SETULT: + LC2 = (VT == MVT::f32) ? RTLIB::OLT_F32 : RTLIB::OLT_F64; + break; + case ISD::SETULE: + LC2 = (VT == MVT::f32) ? RTLIB::OLE_F32 : RTLIB::OLE_F64; + break; + case ISD::SETUEQ: + LC2 = (VT == MVT::f32) ? RTLIB::OEQ_F32 : RTLIB::OEQ_F64; + break; + default: assert(false && "Do not know how to soften this setcc!"); + } + } + + EVT RetVT = MVT::i32; // FIXME: is this the correct return type? + SDValue Ops[2] = { LHSInt, RHSInt }; + NewLHS = MakeLibCall(LC1, RetVT, Ops, 2, false/*sign irrelevant*/, dl); + NewRHS = DAG.getConstant(0, RetVT); + CCCode = TLI.getCmpLibcallCC(LC1); + if (LC2 != RTLIB::UNKNOWN_LIBCALL) { + SDValue Tmp = DAG.getNode(ISD::SETCC, dl, TLI.getSetCCResultType(RetVT), + NewLHS, NewRHS, DAG.getCondCode(CCCode)); + NewLHS = MakeLibCall(LC2, RetVT, Ops, 2, false/*sign irrelevant*/, dl); + NewLHS = DAG.getNode(ISD::SETCC, dl, TLI.getSetCCResultType(RetVT), NewLHS, + NewRHS, DAG.getCondCode(TLI.getCmpLibcallCC(LC2))); + NewLHS = DAG.getNode(ISD::OR, dl, Tmp.getValueType(), Tmp, NewLHS); + NewRHS = SDValue(); + } +} + +SDValue DAGTypeLegalizer::SoftenFloatOp_BIT_CONVERT(SDNode *N) { + return DAG.getNode(ISD::BIT_CONVERT, N->getDebugLoc(), N->getValueType(0), + GetSoftenedFloat(N->getOperand(0))); +} + +SDValue DAGTypeLegalizer::SoftenFloatOp_FP_ROUND(SDNode *N) { + EVT SVT = N->getOperand(0).getValueType(); + EVT RVT = N->getValueType(0); + + RTLIB::Libcall LC = RTLIB::getFPROUND(SVT, RVT); + assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unsupported FP_ROUND libcall"); + + SDValue Op = GetSoftenedFloat(N->getOperand(0)); + return MakeLibCall(LC, RVT, &Op, 1, false, N->getDebugLoc()); +} + +SDValue DAGTypeLegalizer::SoftenFloatOp_BR_CC(SDNode *N) { + SDValue NewLHS = N->getOperand(2), NewRHS = N->getOperand(3); + ISD::CondCode CCCode = cast(N->getOperand(1))->get(); + SoftenSetCCOperands(NewLHS, NewRHS, CCCode, N->getDebugLoc()); + + // If SoftenSetCCOperands returned a scalar, we need to compare the result + // against zero to select between true and false values. + if (NewRHS.getNode() == 0) { + NewRHS = DAG.getConstant(0, NewLHS.getValueType()); + CCCode = ISD::SETNE; + } + + // Update N to have the operands specified. + return DAG.UpdateNodeOperands(SDValue(N, 0), N->getOperand(0), + DAG.getCondCode(CCCode), NewLHS, NewRHS, + N->getOperand(4)); +} + +SDValue DAGTypeLegalizer::SoftenFloatOp_FP_TO_SINT(SDNode *N) { + EVT RVT = N->getValueType(0); + RTLIB::Libcall LC = RTLIB::getFPTOSINT(N->getOperand(0).getValueType(), RVT); + assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unsupported FP_TO_SINT!"); + SDValue Op = GetSoftenedFloat(N->getOperand(0)); + return MakeLibCall(LC, RVT, &Op, 1, false, N->getDebugLoc()); +} + +SDValue DAGTypeLegalizer::SoftenFloatOp_FP_TO_UINT(SDNode *N) { + EVT RVT = N->getValueType(0); + RTLIB::Libcall LC = RTLIB::getFPTOUINT(N->getOperand(0).getValueType(), RVT); + assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unsupported FP_TO_UINT!"); + SDValue Op = GetSoftenedFloat(N->getOperand(0)); + return MakeLibCall(LC, RVT, &Op, 1, false, N->getDebugLoc()); +} + +SDValue DAGTypeLegalizer::SoftenFloatOp_SELECT_CC(SDNode *N) { + SDValue NewLHS = N->getOperand(0), NewRHS = N->getOperand(1); + ISD::CondCode CCCode = cast(N->getOperand(4))->get(); + SoftenSetCCOperands(NewLHS, NewRHS, CCCode, N->getDebugLoc()); + + // If SoftenSetCCOperands returned a scalar, we need to compare the result + // against zero to select between true and false values. + if (NewRHS.getNode() == 0) { + NewRHS = DAG.getConstant(0, NewLHS.getValueType()); + CCCode = ISD::SETNE; + } + + // Update N to have the operands specified. + return DAG.UpdateNodeOperands(SDValue(N, 0), NewLHS, NewRHS, + N->getOperand(2), N->getOperand(3), + DAG.getCondCode(CCCode)); +} + +SDValue DAGTypeLegalizer::SoftenFloatOp_SETCC(SDNode *N) { + SDValue NewLHS = N->getOperand(0), NewRHS = N->getOperand(1); + ISD::CondCode CCCode = cast(N->getOperand(2))->get(); + SoftenSetCCOperands(NewLHS, NewRHS, CCCode, N->getDebugLoc()); + + // If SoftenSetCCOperands returned a scalar, use it. + if (NewRHS.getNode() == 0) { + assert(NewLHS.getValueType() == N->getValueType(0) && + "Unexpected setcc expansion!"); + return NewLHS; + } + + // Otherwise, update N to have the operands specified. + return DAG.UpdateNodeOperands(SDValue(N, 0), NewLHS, NewRHS, + DAG.getCondCode(CCCode)); +} + +SDValue DAGTypeLegalizer::SoftenFloatOp_STORE(SDNode *N, unsigned OpNo) { + assert(ISD::isUNINDEXEDStore(N) && "Indexed store during type legalization!"); + assert(OpNo == 1 && "Can only soften the stored value!"); + StoreSDNode *ST = cast(N); + SDValue Val = ST->getValue(); + DebugLoc dl = N->getDebugLoc(); + + if (ST->isTruncatingStore()) + // Do an FP_ROUND followed by a non-truncating store. + Val = BitConvertToInteger(DAG.getNode(ISD::FP_ROUND, dl, ST->getMemoryVT(), + Val, DAG.getIntPtrConstant(0))); + else + Val = GetSoftenedFloat(Val); + + return DAG.getStore(ST->getChain(), dl, Val, ST->getBasePtr(), + ST->getSrcValue(), ST->getSrcValueOffset(), + ST->isVolatile(), ST->getAlignment()); +} + + +//===----------------------------------------------------------------------===// +// Float Result Expansion +//===----------------------------------------------------------------------===// + +/// ExpandFloatResult - This method is called when the specified result of the +/// specified node is found to need expansion. At this point, the node may also +/// have invalid operands or may have other results that need promotion, we just +/// know that (at least) one result needs expansion. +void DAGTypeLegalizer::ExpandFloatResult(SDNode *N, unsigned ResNo) { + DEBUG(errs() << "Expand float result: "; N->dump(&DAG); errs() << "\n"); + SDValue Lo, Hi; + Lo = Hi = SDValue(); + + // See if the target wants to custom expand this node. + if (CustomLowerNode(N, N->getValueType(ResNo), true)) + return; + + switch (N->getOpcode()) { + default: +#ifndef NDEBUG + errs() << "ExpandFloatResult #" << ResNo << ": "; + N->dump(&DAG); errs() << "\n"; +#endif + llvm_unreachable("Do not know how to expand the result of this operator!"); + + case ISD::MERGE_VALUES: SplitRes_MERGE_VALUES(N, Lo, Hi); break; + case ISD::UNDEF: SplitRes_UNDEF(N, Lo, Hi); break; + case ISD::SELECT: SplitRes_SELECT(N, Lo, Hi); break; + case ISD::SELECT_CC: SplitRes_SELECT_CC(N, Lo, Hi); break; + + case ISD::BIT_CONVERT: ExpandRes_BIT_CONVERT(N, Lo, Hi); break; + case ISD::BUILD_PAIR: ExpandRes_BUILD_PAIR(N, Lo, Hi); break; + case ISD::EXTRACT_ELEMENT: ExpandRes_EXTRACT_ELEMENT(N, Lo, Hi); break; + case ISD::EXTRACT_VECTOR_ELT: ExpandRes_EXTRACT_VECTOR_ELT(N, Lo, Hi); break; + case ISD::VAARG: ExpandRes_VAARG(N, Lo, Hi); break; + + case ISD::ConstantFP: ExpandFloatRes_ConstantFP(N, Lo, Hi); break; + case ISD::FABS: ExpandFloatRes_FABS(N, Lo, Hi); break; + case ISD::FADD: ExpandFloatRes_FADD(N, Lo, Hi); break; + case ISD::FCEIL: ExpandFloatRes_FCEIL(N, Lo, Hi); break; + case ISD::FCOS: ExpandFloatRes_FCOS(N, Lo, Hi); break; + case ISD::FDIV: ExpandFloatRes_FDIV(N, Lo, Hi); break; + case ISD::FEXP: ExpandFloatRes_FEXP(N, Lo, Hi); break; + case ISD::FEXP2: ExpandFloatRes_FEXP2(N, Lo, Hi); break; + case ISD::FFLOOR: ExpandFloatRes_FFLOOR(N, Lo, Hi); break; + case ISD::FLOG: ExpandFloatRes_FLOG(N, Lo, Hi); break; + case ISD::FLOG2: ExpandFloatRes_FLOG2(N, Lo, Hi); break; + case ISD::FLOG10: ExpandFloatRes_FLOG10(N, Lo, Hi); break; + case ISD::FMUL: ExpandFloatRes_FMUL(N, Lo, Hi); break; + case ISD::FNEARBYINT: ExpandFloatRes_FNEARBYINT(N, Lo, Hi); break; + case ISD::FNEG: ExpandFloatRes_FNEG(N, Lo, Hi); break; + case ISD::FP_EXTEND: ExpandFloatRes_FP_EXTEND(N, Lo, Hi); break; + case ISD::FPOW: ExpandFloatRes_FPOW(N, Lo, Hi); break; + case ISD::FPOWI: ExpandFloatRes_FPOWI(N, Lo, Hi); break; + case ISD::FRINT: ExpandFloatRes_FRINT(N, Lo, Hi); break; + case ISD::FSIN: ExpandFloatRes_FSIN(N, Lo, Hi); break; + case ISD::FSQRT: ExpandFloatRes_FSQRT(N, Lo, Hi); break; + case ISD::FSUB: ExpandFloatRes_FSUB(N, Lo, Hi); break; + case ISD::FTRUNC: ExpandFloatRes_FTRUNC(N, Lo, Hi); break; + case ISD::LOAD: ExpandFloatRes_LOAD(N, Lo, Hi); break; + case ISD::SINT_TO_FP: + case ISD::UINT_TO_FP: ExpandFloatRes_XINT_TO_FP(N, Lo, Hi); break; + } + + // If Lo/Hi is null, the sub-method took care of registering results etc. + if (Lo.getNode()) + SetExpandedFloat(SDValue(N, ResNo), Lo, Hi); +} + +void DAGTypeLegalizer::ExpandFloatRes_ConstantFP(SDNode *N, SDValue &Lo, + SDValue &Hi) { + EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); + assert(NVT.getSizeInBits() == integerPartWidth && + "Do not know how to expand this float constant!"); + APInt C = cast(N)->getValueAPF().bitcastToAPInt(); + Lo = DAG.getConstantFP(APFloat(APInt(integerPartWidth, 1, + &C.getRawData()[1])), NVT); + Hi = DAG.getConstantFP(APFloat(APInt(integerPartWidth, 1, + &C.getRawData()[0])), NVT); +} + +void DAGTypeLegalizer::ExpandFloatRes_FABS(SDNode *N, SDValue &Lo, + SDValue &Hi) { + assert(N->getValueType(0) == MVT::ppcf128 && + "Logic only correct for ppcf128!"); + DebugLoc dl = N->getDebugLoc(); + SDValue Tmp; + GetExpandedFloat(N->getOperand(0), Lo, Tmp); + Hi = DAG.getNode(ISD::FABS, dl, Tmp.getValueType(), Tmp); + // Lo = Hi==fabs(Hi) ? Lo : -Lo; + Lo = DAG.getNode(ISD::SELECT_CC, dl, Lo.getValueType(), Tmp, Hi, Lo, + DAG.getNode(ISD::FNEG, dl, Lo.getValueType(), Lo), + DAG.getCondCode(ISD::SETEQ)); +} + +void DAGTypeLegalizer::ExpandFloatRes_FADD(SDNode *N, SDValue &Lo, + SDValue &Hi) { + SDValue Call = LibCallify(GetFPLibCall(N->getValueType(0), + RTLIB::ADD_F32, RTLIB::ADD_F64, + RTLIB::ADD_F80, RTLIB::ADD_PPCF128), + N, false); + GetPairElements(Call, Lo, Hi); +} + +void DAGTypeLegalizer::ExpandFloatRes_FCEIL(SDNode *N, + SDValue &Lo, SDValue &Hi) { + SDValue Call = LibCallify(GetFPLibCall(N->getValueType(0), + RTLIB::CEIL_F32, RTLIB::CEIL_F64, + RTLIB::CEIL_F80, RTLIB::CEIL_PPCF128), + N, false); + GetPairElements(Call, Lo, Hi); +} + +void DAGTypeLegalizer::ExpandFloatRes_FCOS(SDNode *N, + SDValue &Lo, SDValue &Hi) { + SDValue Call = LibCallify(GetFPLibCall(N->getValueType(0), + RTLIB::COS_F32, RTLIB::COS_F64, + RTLIB::COS_F80, RTLIB::COS_PPCF128), + N, false); + GetPairElements(Call, Lo, Hi); +} + +void DAGTypeLegalizer::ExpandFloatRes_FDIV(SDNode *N, SDValue &Lo, + SDValue &Hi) { + SDValue Ops[2] = { N->getOperand(0), N->getOperand(1) }; + SDValue Call = MakeLibCall(GetFPLibCall(N->getValueType(0), + RTLIB::DIV_F32, + RTLIB::DIV_F64, + RTLIB::DIV_F80, + RTLIB::DIV_PPCF128), + N->getValueType(0), Ops, 2, false, + N->getDebugLoc()); + GetPairElements(Call, Lo, Hi); +} + +void DAGTypeLegalizer::ExpandFloatRes_FEXP(SDNode *N, + SDValue &Lo, SDValue &Hi) { + SDValue Call = LibCallify(GetFPLibCall(N->getValueType(0), + RTLIB::EXP_F32, RTLIB::EXP_F64, + RTLIB::EXP_F80, RTLIB::EXP_PPCF128), + N, false); + GetPairElements(Call, Lo, Hi); +} + +void DAGTypeLegalizer::ExpandFloatRes_FEXP2(SDNode *N, + SDValue &Lo, SDValue &Hi) { + SDValue Call = LibCallify(GetFPLibCall(N->getValueType(0), + RTLIB::EXP2_F32, RTLIB::EXP2_F64, + RTLIB::EXP2_F80, RTLIB::EXP2_PPCF128), + N, false); + GetPairElements(Call, Lo, Hi); +} + +void DAGTypeLegalizer::ExpandFloatRes_FFLOOR(SDNode *N, + SDValue &Lo, SDValue &Hi) { + SDValue Call = LibCallify(GetFPLibCall(N->getValueType(0), + RTLIB::FLOOR_F32,RTLIB::FLOOR_F64, + RTLIB::FLOOR_F80,RTLIB::FLOOR_PPCF128), + N, false); + GetPairElements(Call, Lo, Hi); +} + +void DAGTypeLegalizer::ExpandFloatRes_FLOG(SDNode *N, + SDValue &Lo, SDValue &Hi) { + SDValue Call = LibCallify(GetFPLibCall(N->getValueType(0), + RTLIB::LOG_F32, RTLIB::LOG_F64, + RTLIB::LOG_F80, RTLIB::LOG_PPCF128), + N, false); + GetPairElements(Call, Lo, Hi); +} + +void DAGTypeLegalizer::ExpandFloatRes_FLOG2(SDNode *N, + SDValue &Lo, SDValue &Hi) { + SDValue Call = LibCallify(GetFPLibCall(N->getValueType(0), + RTLIB::LOG2_F32, RTLIB::LOG2_F64, + RTLIB::LOG2_F80, RTLIB::LOG2_PPCF128), + N, false); + GetPairElements(Call, Lo, Hi); +} + +void DAGTypeLegalizer::ExpandFloatRes_FLOG10(SDNode *N, + SDValue &Lo, SDValue &Hi) { + SDValue Call = LibCallify(GetFPLibCall(N->getValueType(0), + RTLIB::LOG10_F32,RTLIB::LOG10_F64, + RTLIB::LOG10_F80,RTLIB::LOG10_PPCF128), + N, false); + GetPairElements(Call, Lo, Hi); +} + +void DAGTypeLegalizer::ExpandFloatRes_FMUL(SDNode *N, SDValue &Lo, + SDValue &Hi) { + SDValue Ops[2] = { N->getOperand(0), N->getOperand(1) }; + SDValue Call = MakeLibCall(GetFPLibCall(N->getValueType(0), + RTLIB::MUL_F32, + RTLIB::MUL_F64, + RTLIB::MUL_F80, + RTLIB::MUL_PPCF128), + N->getValueType(0), Ops, 2, false, + N->getDebugLoc()); + GetPairElements(Call, Lo, Hi); +} + +void DAGTypeLegalizer::ExpandFloatRes_FNEARBYINT(SDNode *N, + SDValue &Lo, SDValue &Hi) { + SDValue Call = LibCallify(GetFPLibCall(N->getValueType(0), + RTLIB::NEARBYINT_F32, + RTLIB::NEARBYINT_F64, + RTLIB::NEARBYINT_F80, + RTLIB::NEARBYINT_PPCF128), + N, false); + GetPairElements(Call, Lo, Hi); +} + +void DAGTypeLegalizer::ExpandFloatRes_FNEG(SDNode *N, SDValue &Lo, + SDValue &Hi) { + DebugLoc dl = N->getDebugLoc(); + GetExpandedFloat(N->getOperand(0), Lo, Hi); + Lo = DAG.getNode(ISD::FNEG, dl, Lo.getValueType(), Lo); + Hi = DAG.getNode(ISD::FNEG, dl, Hi.getValueType(), Hi); +} + +void DAGTypeLegalizer::ExpandFloatRes_FP_EXTEND(SDNode *N, SDValue &Lo, + SDValue &Hi) { + EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); + Hi = DAG.getNode(ISD::FP_EXTEND, N->getDebugLoc(), NVT, N->getOperand(0)); + Lo = DAG.getConstantFP(APFloat(APInt(NVT.getSizeInBits(), 0)), NVT); +} + +void DAGTypeLegalizer::ExpandFloatRes_FPOW(SDNode *N, + SDValue &Lo, SDValue &Hi) { + SDValue Call = LibCallify(GetFPLibCall(N->getValueType(0), + RTLIB::POW_F32, RTLIB::POW_F64, + RTLIB::POW_F80, RTLIB::POW_PPCF128), + N, false); + GetPairElements(Call, Lo, Hi); +} + +void DAGTypeLegalizer::ExpandFloatRes_FPOWI(SDNode *N, + SDValue &Lo, SDValue &Hi) { + SDValue Call = LibCallify(GetFPLibCall(N->getValueType(0), + RTLIB::POWI_F32, RTLIB::POWI_F64, + RTLIB::POWI_F80, RTLIB::POWI_PPCF128), + N, false); + GetPairElements(Call, Lo, Hi); +} + +void DAGTypeLegalizer::ExpandFloatRes_FRINT(SDNode *N, + SDValue &Lo, SDValue &Hi) { + SDValue Call = LibCallify(GetFPLibCall(N->getValueType(0), + RTLIB::RINT_F32, RTLIB::RINT_F64, + RTLIB::RINT_F80, RTLIB::RINT_PPCF128), + N, false); + GetPairElements(Call, Lo, Hi); +} + +void DAGTypeLegalizer::ExpandFloatRes_FSIN(SDNode *N, + SDValue &Lo, SDValue &Hi) { + SDValue Call = LibCallify(GetFPLibCall(N->getValueType(0), + RTLIB::SIN_F32, RTLIB::SIN_F64, + RTLIB::SIN_F80, RTLIB::SIN_PPCF128), + N, false); + GetPairElements(Call, Lo, Hi); +} + +void DAGTypeLegalizer::ExpandFloatRes_FSQRT(SDNode *N, + SDValue &Lo, SDValue &Hi) { + SDValue Call = LibCallify(GetFPLibCall(N->getValueType(0), + RTLIB::SQRT_F32, RTLIB::SQRT_F64, + RTLIB::SQRT_F80, RTLIB::SQRT_PPCF128), + N, false); + GetPairElements(Call, Lo, Hi); +} + +void DAGTypeLegalizer::ExpandFloatRes_FSUB(SDNode *N, SDValue &Lo, + SDValue &Hi) { + SDValue Ops[2] = { N->getOperand(0), N->getOperand(1) }; + SDValue Call = MakeLibCall(GetFPLibCall(N->getValueType(0), + RTLIB::SUB_F32, + RTLIB::SUB_F64, + RTLIB::SUB_F80, + RTLIB::SUB_PPCF128), + N->getValueType(0), Ops, 2, false, + N->getDebugLoc()); + GetPairElements(Call, Lo, Hi); +} + +void DAGTypeLegalizer::ExpandFloatRes_FTRUNC(SDNode *N, + SDValue &Lo, SDValue &Hi) { + SDValue Call = LibCallify(GetFPLibCall(N->getValueType(0), + RTLIB::TRUNC_F32, RTLIB::TRUNC_F64, + RTLIB::TRUNC_F80, RTLIB::TRUNC_PPCF128), + N, false); + GetPairElements(Call, Lo, Hi); +} + +void DAGTypeLegalizer::ExpandFloatRes_LOAD(SDNode *N, SDValue &Lo, + SDValue &Hi) { + if (ISD::isNormalLoad(N)) { + ExpandRes_NormalLoad(N, Lo, Hi); + return; + } + + assert(ISD::isUNINDEXEDLoad(N) && "Indexed load during type legalization!"); + LoadSDNode *LD = cast(N); + SDValue Chain = LD->getChain(); + SDValue Ptr = LD->getBasePtr(); + DebugLoc dl = N->getDebugLoc(); + + EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), LD->getValueType(0)); + assert(NVT.isByteSized() && "Expanded type not byte sized!"); + assert(LD->getMemoryVT().bitsLE(NVT) && "Float type not round?"); + + Hi = DAG.getExtLoad(LD->getExtensionType(), dl, NVT, Chain, Ptr, + LD->getSrcValue(), LD->getSrcValueOffset(), + LD->getMemoryVT(), + LD->isVolatile(), LD->getAlignment()); + + // Remember the chain. + Chain = Hi.getValue(1); + + // The low part is zero. + Lo = DAG.getConstantFP(APFloat(APInt(NVT.getSizeInBits(), 0)), NVT); + + // Modified the chain - switch anything that used the old chain to use the + // new one. + ReplaceValueWith(SDValue(LD, 1), Chain); +} + +void DAGTypeLegalizer::ExpandFloatRes_XINT_TO_FP(SDNode *N, SDValue &Lo, + SDValue &Hi) { + assert(N->getValueType(0) == MVT::ppcf128 && "Unsupported XINT_TO_FP!"); + EVT VT = N->getValueType(0); + EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT); + SDValue Src = N->getOperand(0); + EVT SrcVT = Src.getValueType(); + bool isSigned = N->getOpcode() == ISD::SINT_TO_FP; + DebugLoc dl = N->getDebugLoc(); + + // First do an SINT_TO_FP, whether the original was signed or unsigned. + // When promoting partial word types to i32 we must honor the signedness, + // though. + if (SrcVT.bitsLE(MVT::i32)) { + // The integer can be represented exactly in an f64. + Src = DAG.getNode(isSigned ? ISD::SIGN_EXTEND : ISD::ZERO_EXTEND, dl, + MVT::i32, Src); + Lo = DAG.getConstantFP(APFloat(APInt(NVT.getSizeInBits(), 0)), NVT); + Hi = DAG.getNode(ISD::SINT_TO_FP, dl, NVT, Src); + } else { + RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL; + if (SrcVT.bitsLE(MVT::i64)) { + Src = DAG.getNode(isSigned ? ISD::SIGN_EXTEND : ISD::ZERO_EXTEND, dl, + MVT::i64, Src); + LC = RTLIB::SINTTOFP_I64_PPCF128; + } else if (SrcVT.bitsLE(MVT::i128)) { + Src = DAG.getNode(ISD::SIGN_EXTEND, dl, MVT::i128, Src); + LC = RTLIB::SINTTOFP_I128_PPCF128; + } + assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unsupported XINT_TO_FP!"); + + Hi = MakeLibCall(LC, VT, &Src, 1, true, dl); + GetPairElements(Hi, Lo, Hi); + } + + if (isSigned) + return; + + // Unsigned - fix up the SINT_TO_FP value just calculated. + Hi = DAG.getNode(ISD::BUILD_PAIR, dl, VT, Lo, Hi); + SrcVT = Src.getValueType(); + + // x>=0 ? (ppcf128)(iN)x : (ppcf128)(iN)x + 2^N; N=32,64,128. + static const uint64_t TwoE32[] = { 0x41f0000000000000LL, 0 }; + static const uint64_t TwoE64[] = { 0x43f0000000000000LL, 0 }; + static const uint64_t TwoE128[] = { 0x47f0000000000000LL, 0 }; + const uint64_t *Parts = 0; + + switch (SrcVT.getSimpleVT().SimpleTy) { + default: + assert(false && "Unsupported UINT_TO_FP!"); + case MVT::i32: + Parts = TwoE32; + break; + case MVT::i64: + Parts = TwoE64; + break; + case MVT::i128: + Parts = TwoE128; + break; + } + + Lo = DAG.getNode(ISD::FADD, dl, VT, Hi, + DAG.getConstantFP(APFloat(APInt(128, 2, Parts)), + MVT::ppcf128)); + Lo = DAG.getNode(ISD::SELECT_CC, dl, VT, Src, DAG.getConstant(0, SrcVT), + Lo, Hi, DAG.getCondCode(ISD::SETLT)); + GetPairElements(Lo, Lo, Hi); +} + + +//===----------------------------------------------------------------------===// +// Float Operand Expansion +//===----------------------------------------------------------------------===// + +/// ExpandFloatOperand - This method is called when the specified operand of the +/// specified node is found to need expansion. At this point, all of the result +/// types of the node are known to be legal, but other operands of the node may +/// need promotion or expansion as well as the specified one. +bool DAGTypeLegalizer::ExpandFloatOperand(SDNode *N, unsigned OpNo) { + DEBUG(errs() << "Expand float operand: "; N->dump(&DAG); errs() << "\n"); + SDValue Res = SDValue(); + + if (TLI.getOperationAction(N->getOpcode(), N->getOperand(OpNo).getValueType()) + == TargetLowering::Custom) + Res = TLI.LowerOperation(SDValue(N, 0), DAG); + + if (Res.getNode() == 0) { + switch (N->getOpcode()) { + default: + #ifndef NDEBUG + errs() << "ExpandFloatOperand Op #" << OpNo << ": "; + N->dump(&DAG); errs() << "\n"; + #endif + llvm_unreachable("Do not know how to expand this operator's operand!"); + + case ISD::BIT_CONVERT: Res = ExpandOp_BIT_CONVERT(N); break; + case ISD::BUILD_VECTOR: Res = ExpandOp_BUILD_VECTOR(N); break; + case ISD::EXTRACT_ELEMENT: Res = ExpandOp_EXTRACT_ELEMENT(N); break; + + case ISD::BR_CC: Res = ExpandFloatOp_BR_CC(N); break; + case ISD::FP_ROUND: Res = ExpandFloatOp_FP_ROUND(N); break; + case ISD::FP_TO_SINT: Res = ExpandFloatOp_FP_TO_SINT(N); break; + case ISD::FP_TO_UINT: Res = ExpandFloatOp_FP_TO_UINT(N); break; + case ISD::SELECT_CC: Res = ExpandFloatOp_SELECT_CC(N); break; + case ISD::SETCC: Res = ExpandFloatOp_SETCC(N); break; + case ISD::STORE: Res = ExpandFloatOp_STORE(cast(N), + OpNo); break; + } + } + + // If the result is null, the sub-method took care of registering results etc. + if (!Res.getNode()) return false; + + // If the result is N, the sub-method updated N in place. Tell the legalizer + // core about this. + if (Res.getNode() == N) + return true; + + assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 1 && + "Invalid operand expansion"); + + ReplaceValueWith(SDValue(N, 0), Res); + return false; +} + +/// FloatExpandSetCCOperands - Expand the operands of a comparison. This code +/// is shared among BR_CC, SELECT_CC, and SETCC handlers. +void DAGTypeLegalizer::FloatExpandSetCCOperands(SDValue &NewLHS, + SDValue &NewRHS, + ISD::CondCode &CCCode, + DebugLoc dl) { + SDValue LHSLo, LHSHi, RHSLo, RHSHi; + GetExpandedFloat(NewLHS, LHSLo, LHSHi); + GetExpandedFloat(NewRHS, RHSLo, RHSHi); + + EVT VT = NewLHS.getValueType(); + assert(VT == MVT::ppcf128 && "Unsupported setcc type!"); + + // FIXME: This generated code sucks. We want to generate + // FCMPU crN, hi1, hi2 + // BNE crN, L: + // FCMPU crN, lo1, lo2 + // The following can be improved, but not that much. + SDValue Tmp1, Tmp2, Tmp3; + Tmp1 = DAG.getSetCC(dl, TLI.getSetCCResultType(LHSHi.getValueType()), + LHSHi, RHSHi, ISD::SETOEQ); + Tmp2 = DAG.getSetCC(dl, TLI.getSetCCResultType(LHSLo.getValueType()), + LHSLo, RHSLo, CCCode); + Tmp3 = DAG.getNode(ISD::AND, dl, Tmp1.getValueType(), Tmp1, Tmp2); + Tmp1 = DAG.getSetCC(dl, TLI.getSetCCResultType(LHSHi.getValueType()), + LHSHi, RHSHi, ISD::SETUNE); + Tmp2 = DAG.getSetCC(dl, TLI.getSetCCResultType(LHSHi.getValueType()), + LHSHi, RHSHi, CCCode); + Tmp1 = DAG.getNode(ISD::AND, dl, Tmp1.getValueType(), Tmp1, Tmp2); + NewLHS = DAG.getNode(ISD::OR, dl, Tmp1.getValueType(), Tmp1, Tmp3); + NewRHS = SDValue(); // LHS is the result, not a compare. +} + +SDValue DAGTypeLegalizer::ExpandFloatOp_BR_CC(SDNode *N) { + SDValue NewLHS = N->getOperand(2), NewRHS = N->getOperand(3); + ISD::CondCode CCCode = cast(N->getOperand(1))->get(); + FloatExpandSetCCOperands(NewLHS, NewRHS, CCCode, N->getDebugLoc()); + + // If ExpandSetCCOperands returned a scalar, we need to compare the result + // against zero to select between true and false values. + if (NewRHS.getNode() == 0) { + NewRHS = DAG.getConstant(0, NewLHS.getValueType()); + CCCode = ISD::SETNE; + } + + // Update N to have the operands specified. + return DAG.UpdateNodeOperands(SDValue(N, 0), N->getOperand(0), + DAG.getCondCode(CCCode), NewLHS, NewRHS, + N->getOperand(4)); +} + +SDValue DAGTypeLegalizer::ExpandFloatOp_FP_ROUND(SDNode *N) { + assert(N->getOperand(0).getValueType() == MVT::ppcf128 && + "Logic only correct for ppcf128!"); + SDValue Lo, Hi; + GetExpandedFloat(N->getOperand(0), Lo, Hi); + // Round it the rest of the way (e.g. to f32) if needed. + return DAG.getNode(ISD::FP_ROUND, N->getDebugLoc(), + N->getValueType(0), Hi, N->getOperand(1)); +} + +SDValue DAGTypeLegalizer::ExpandFloatOp_FP_TO_SINT(SDNode *N) { + EVT RVT = N->getValueType(0); + DebugLoc dl = N->getDebugLoc(); + + // Expand ppcf128 to i32 by hand for the benefit of llvm-gcc bootstrap on + // PPC (the libcall is not available). FIXME: Do this in a less hacky way. + if (RVT == MVT::i32) { + assert(N->getOperand(0).getValueType() == MVT::ppcf128 && + "Logic only correct for ppcf128!"); + SDValue Res = DAG.getNode(ISD::FP_ROUND_INREG, dl, MVT::ppcf128, + N->getOperand(0), DAG.getValueType(MVT::f64)); + Res = DAG.getNode(ISD::FP_ROUND, dl, MVT::f64, Res, + DAG.getIntPtrConstant(1)); + return DAG.getNode(ISD::FP_TO_SINT, dl, MVT::i32, Res); + } + + RTLIB::Libcall LC = RTLIB::getFPTOSINT(N->getOperand(0).getValueType(), RVT); + assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unsupported FP_TO_SINT!"); + return MakeLibCall(LC, RVT, &N->getOperand(0), 1, false, dl); +} + +SDValue DAGTypeLegalizer::ExpandFloatOp_FP_TO_UINT(SDNode *N) { + EVT RVT = N->getValueType(0); + DebugLoc dl = N->getDebugLoc(); + + // Expand ppcf128 to i32 by hand for the benefit of llvm-gcc bootstrap on + // PPC (the libcall is not available). FIXME: Do this in a less hacky way. + if (RVT == MVT::i32) { + assert(N->getOperand(0).getValueType() == MVT::ppcf128 && + "Logic only correct for ppcf128!"); + const uint64_t TwoE31[] = {0x41e0000000000000LL, 0}; + APFloat APF = APFloat(APInt(128, 2, TwoE31)); + SDValue Tmp = DAG.getConstantFP(APF, MVT::ppcf128); + // X>=2^31 ? (int)(X-2^31)+0x80000000 : (int)X + // FIXME: generated code sucks. + return DAG.getNode(ISD::SELECT_CC, dl, MVT::i32, N->getOperand(0), Tmp, + DAG.getNode(ISD::ADD, dl, MVT::i32, + DAG.getNode(ISD::FP_TO_SINT, dl, MVT::i32, + DAG.getNode(ISD::FSUB, dl, + MVT::ppcf128, + N->getOperand(0), + Tmp)), + DAG.getConstant(0x80000000, MVT::i32)), + DAG.getNode(ISD::FP_TO_SINT, dl, + MVT::i32, N->getOperand(0)), + DAG.getCondCode(ISD::SETGE)); + } + + RTLIB::Libcall LC = RTLIB::getFPTOUINT(N->getOperand(0).getValueType(), RVT); + assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unsupported FP_TO_UINT!"); + return MakeLibCall(LC, N->getValueType(0), &N->getOperand(0), 1, false, dl); +} + +SDValue DAGTypeLegalizer::ExpandFloatOp_SELECT_CC(SDNode *N) { + SDValue NewLHS = N->getOperand(0), NewRHS = N->getOperand(1); + ISD::CondCode CCCode = cast(N->getOperand(4))->get(); + FloatExpandSetCCOperands(NewLHS, NewRHS, CCCode, N->getDebugLoc()); + + // If ExpandSetCCOperands returned a scalar, we need to compare the result + // against zero to select between true and false values. + if (NewRHS.getNode() == 0) { + NewRHS = DAG.getConstant(0, NewLHS.getValueType()); + CCCode = ISD::SETNE; + } + + // Update N to have the operands specified. + return DAG.UpdateNodeOperands(SDValue(N, 0), NewLHS, NewRHS, + N->getOperand(2), N->getOperand(3), + DAG.getCondCode(CCCode)); +} + +SDValue DAGTypeLegalizer::ExpandFloatOp_SETCC(SDNode *N) { + SDValue NewLHS = N->getOperand(0), NewRHS = N->getOperand(1); + ISD::CondCode CCCode = cast(N->getOperand(2))->get(); + FloatExpandSetCCOperands(NewLHS, NewRHS, CCCode, N->getDebugLoc()); + + // If ExpandSetCCOperands returned a scalar, use it. + if (NewRHS.getNode() == 0) { + assert(NewLHS.getValueType() == N->getValueType(0) && + "Unexpected setcc expansion!"); + return NewLHS; + } + + // Otherwise, update N to have the operands specified. + return DAG.UpdateNodeOperands(SDValue(N, 0), NewLHS, NewRHS, + DAG.getCondCode(CCCode)); +} + +SDValue DAGTypeLegalizer::ExpandFloatOp_STORE(SDNode *N, unsigned OpNo) { + if (ISD::isNormalStore(N)) + return ExpandOp_NormalStore(N, OpNo); + + assert(ISD::isUNINDEXEDStore(N) && "Indexed store during type legalization!"); + assert(OpNo == 1 && "Can only expand the stored value so far"); + StoreSDNode *ST = cast(N); + + SDValue Chain = ST->getChain(); + SDValue Ptr = ST->getBasePtr(); + + EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), ST->getValue().getValueType()); + assert(NVT.isByteSized() && "Expanded type not byte sized!"); + assert(ST->getMemoryVT().bitsLE(NVT) && "Float type not round?"); + + SDValue Lo, Hi; + GetExpandedOp(ST->getValue(), Lo, Hi); + + return DAG.getTruncStore(Chain, N->getDebugLoc(), Hi, Ptr, + ST->getSrcValue(), ST->getSrcValueOffset(), + ST->getMemoryVT(), + ST->isVolatile(), ST->getAlignment()); +} diff --git a/libclamav/c++/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp b/libclamav/c++/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp new file mode 100644 index 000000000..8ac8063be --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp @@ -0,0 +1,2337 @@ +//===----- LegalizeIntegerTypes.cpp - Legalization of integer types -------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements integer type expansion and promotion for LegalizeTypes. +// Promotion is the act of changing a computation in an illegal type into a +// computation in a larger type. For example, implementing i8 arithmetic in an +// i32 register (often needed on powerpc). +// Expansion is the act of changing a computation in an illegal type into a +// computation in two identical registers of a smaller type. For example, +// implementing i64 arithmetic in two i32 registers (often needed on 32-bit +// targets). +// +//===----------------------------------------------------------------------===// + +#include "LegalizeTypes.h" +#include "llvm/CodeGen/PseudoSourceValue.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +//===----------------------------------------------------------------------===// +// Integer Result Promotion +//===----------------------------------------------------------------------===// + +/// PromoteIntegerResult - This method is called when a result of a node is +/// found to be in need of promotion to a larger type. At this point, the node +/// may also have invalid operands or may have other results that need +/// expansion, we just know that (at least) one result needs promotion. +void DAGTypeLegalizer::PromoteIntegerResult(SDNode *N, unsigned ResNo) { + DEBUG(errs() << "Promote integer result: "; N->dump(&DAG); errs() << "\n"); + SDValue Res = SDValue(); + + // See if the target wants to custom expand this node. + if (CustomLowerNode(N, N->getValueType(ResNo), true)) + return; + + switch (N->getOpcode()) { + default: +#ifndef NDEBUG + errs() << "PromoteIntegerResult #" << ResNo << ": "; + N->dump(&DAG); errs() << "\n"; +#endif + llvm_unreachable("Do not know how to promote this operator!"); + case ISD::AssertSext: Res = PromoteIntRes_AssertSext(N); break; + case ISD::AssertZext: Res = PromoteIntRes_AssertZext(N); break; + case ISD::BIT_CONVERT: Res = PromoteIntRes_BIT_CONVERT(N); break; + case ISD::BSWAP: Res = PromoteIntRes_BSWAP(N); break; + case ISD::BUILD_PAIR: Res = PromoteIntRes_BUILD_PAIR(N); break; + case ISD::Constant: Res = PromoteIntRes_Constant(N); break; + case ISD::CONVERT_RNDSAT: + Res = PromoteIntRes_CONVERT_RNDSAT(N); break; + case ISD::CTLZ: Res = PromoteIntRes_CTLZ(N); break; + case ISD::CTPOP: Res = PromoteIntRes_CTPOP(N); break; + case ISD::CTTZ: Res = PromoteIntRes_CTTZ(N); break; + case ISD::EXTRACT_VECTOR_ELT: + Res = PromoteIntRes_EXTRACT_VECTOR_ELT(N); break; + case ISD::LOAD: Res = PromoteIntRes_LOAD(cast(N));break; + case ISD::SELECT: Res = PromoteIntRes_SELECT(N); break; + case ISD::SELECT_CC: Res = PromoteIntRes_SELECT_CC(N); break; + case ISD::SETCC: Res = PromoteIntRes_SETCC(N); break; + case ISD::SHL: Res = PromoteIntRes_SHL(N); break; + case ISD::SIGN_EXTEND_INREG: + Res = PromoteIntRes_SIGN_EXTEND_INREG(N); break; + case ISD::SRA: Res = PromoteIntRes_SRA(N); break; + case ISD::SRL: Res = PromoteIntRes_SRL(N); break; + case ISD::TRUNCATE: Res = PromoteIntRes_TRUNCATE(N); break; + case ISD::UNDEF: Res = PromoteIntRes_UNDEF(N); break; + case ISD::VAARG: Res = PromoteIntRes_VAARG(N); break; + + case ISD::SIGN_EXTEND: + case ISD::ZERO_EXTEND: + case ISD::ANY_EXTEND: Res = PromoteIntRes_INT_EXTEND(N); break; + + case ISD::FP_TO_SINT: + case ISD::FP_TO_UINT: Res = PromoteIntRes_FP_TO_XINT(N); break; + + case ISD::AND: + case ISD::OR: + case ISD::XOR: + case ISD::ADD: + case ISD::SUB: + case ISD::MUL: Res = PromoteIntRes_SimpleIntBinOp(N); break; + + case ISD::SDIV: + case ISD::SREM: Res = PromoteIntRes_SDIV(N); break; + + case ISD::UDIV: + case ISD::UREM: Res = PromoteIntRes_UDIV(N); break; + + case ISD::SADDO: + case ISD::SSUBO: Res = PromoteIntRes_SADDSUBO(N, ResNo); break; + case ISD::UADDO: + case ISD::USUBO: Res = PromoteIntRes_UADDSUBO(N, ResNo); break; + case ISD::SMULO: + case ISD::UMULO: Res = PromoteIntRes_XMULO(N, ResNo); break; + + case ISD::ATOMIC_LOAD_ADD: + case ISD::ATOMIC_LOAD_SUB: + case ISD::ATOMIC_LOAD_AND: + case ISD::ATOMIC_LOAD_OR: + case ISD::ATOMIC_LOAD_XOR: + case ISD::ATOMIC_LOAD_NAND: + case ISD::ATOMIC_LOAD_MIN: + case ISD::ATOMIC_LOAD_MAX: + case ISD::ATOMIC_LOAD_UMIN: + case ISD::ATOMIC_LOAD_UMAX: + case ISD::ATOMIC_SWAP: + Res = PromoteIntRes_Atomic1(cast(N)); break; + + case ISD::ATOMIC_CMP_SWAP: + Res = PromoteIntRes_Atomic2(cast(N)); break; + } + + // If the result is null then the sub-method took care of registering it. + if (Res.getNode()) + SetPromotedInteger(SDValue(N, ResNo), Res); +} + +SDValue DAGTypeLegalizer::PromoteIntRes_AssertSext(SDNode *N) { + // Sign-extend the new bits, and continue the assertion. + SDValue Op = SExtPromotedInteger(N->getOperand(0)); + return DAG.getNode(ISD::AssertSext, N->getDebugLoc(), + Op.getValueType(), Op, N->getOperand(1)); +} + +SDValue DAGTypeLegalizer::PromoteIntRes_AssertZext(SDNode *N) { + // Zero the new bits, and continue the assertion. + SDValue Op = ZExtPromotedInteger(N->getOperand(0)); + return DAG.getNode(ISD::AssertZext, N->getDebugLoc(), + Op.getValueType(), Op, N->getOperand(1)); +} + +SDValue DAGTypeLegalizer::PromoteIntRes_Atomic1(AtomicSDNode *N) { + SDValue Op2 = GetPromotedInteger(N->getOperand(2)); + SDValue Res = DAG.getAtomic(N->getOpcode(), N->getDebugLoc(), + N->getMemoryVT(), + N->getChain(), N->getBasePtr(), + Op2, N->getSrcValue(), N->getAlignment()); + // Legalized the chain result - switch anything that used the old chain to + // use the new one. + ReplaceValueWith(SDValue(N, 1), Res.getValue(1)); + return Res; +} + +SDValue DAGTypeLegalizer::PromoteIntRes_Atomic2(AtomicSDNode *N) { + SDValue Op2 = GetPromotedInteger(N->getOperand(2)); + SDValue Op3 = GetPromotedInteger(N->getOperand(3)); + SDValue Res = DAG.getAtomic(N->getOpcode(), N->getDebugLoc(), + N->getMemoryVT(), N->getChain(), N->getBasePtr(), + Op2, Op3, N->getSrcValue(), N->getAlignment()); + // Legalized the chain result - switch anything that used the old chain to + // use the new one. + ReplaceValueWith(SDValue(N, 1), Res.getValue(1)); + return Res; +} + +SDValue DAGTypeLegalizer::PromoteIntRes_BIT_CONVERT(SDNode *N) { + SDValue InOp = N->getOperand(0); + EVT InVT = InOp.getValueType(); + EVT NInVT = TLI.getTypeToTransformTo(*DAG.getContext(), InVT); + EVT OutVT = N->getValueType(0); + EVT NOutVT = TLI.getTypeToTransformTo(*DAG.getContext(), OutVT); + DebugLoc dl = N->getDebugLoc(); + + switch (getTypeAction(InVT)) { + default: + assert(false && "Unknown type action!"); + break; + case Legal: + break; + case PromoteInteger: + if (NOutVT.bitsEq(NInVT)) + // The input promotes to the same size. Convert the promoted value. + return DAG.getNode(ISD::BIT_CONVERT, dl, + NOutVT, GetPromotedInteger(InOp)); + break; + case SoftenFloat: + // Promote the integer operand by hand. + return DAG.getNode(ISD::ANY_EXTEND, dl, NOutVT, GetSoftenedFloat(InOp)); + case ExpandInteger: + case ExpandFloat: + break; + case ScalarizeVector: + // Convert the element to an integer and promote it by hand. + return DAG.getNode(ISD::ANY_EXTEND, dl, NOutVT, + BitConvertToInteger(GetScalarizedVector(InOp))); + case SplitVector: { + // For example, i32 = BIT_CONVERT v2i16 on alpha. Convert the split + // pieces of the input into integers and reassemble in the final type. + SDValue Lo, Hi; + GetSplitVector(N->getOperand(0), Lo, Hi); + Lo = BitConvertToInteger(Lo); + Hi = BitConvertToInteger(Hi); + + if (TLI.isBigEndian()) + std::swap(Lo, Hi); + + InOp = DAG.getNode(ISD::ANY_EXTEND, dl, + EVT::getIntegerVT(*DAG.getContext(), NOutVT.getSizeInBits()), + JoinIntegers(Lo, Hi)); + return DAG.getNode(ISD::BIT_CONVERT, dl, NOutVT, InOp); + } + case WidenVector: + if (OutVT.bitsEq(NInVT)) + // The input is widened to the same size. Convert to the widened value. + return DAG.getNode(ISD::BIT_CONVERT, dl, OutVT, GetWidenedVector(InOp)); + } + + return DAG.getNode(ISD::ANY_EXTEND, dl, NOutVT, + CreateStackStoreLoad(InOp, OutVT)); +} + +SDValue DAGTypeLegalizer::PromoteIntRes_BSWAP(SDNode *N) { + SDValue Op = GetPromotedInteger(N->getOperand(0)); + EVT OVT = N->getValueType(0); + EVT NVT = Op.getValueType(); + DebugLoc dl = N->getDebugLoc(); + + unsigned DiffBits = NVT.getSizeInBits() - OVT.getSizeInBits(); + return DAG.getNode(ISD::SRL, dl, NVT, DAG.getNode(ISD::BSWAP, dl, NVT, Op), + DAG.getConstant(DiffBits, TLI.getPointerTy())); +} + +SDValue DAGTypeLegalizer::PromoteIntRes_BUILD_PAIR(SDNode *N) { + // The pair element type may be legal, or may not promote to the same type as + // the result, for example i14 = BUILD_PAIR (i7, i7). Handle all cases. + return DAG.getNode(ISD::ANY_EXTEND, N->getDebugLoc(), + TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)), + JoinIntegers(N->getOperand(0), N->getOperand(1))); +} + +SDValue DAGTypeLegalizer::PromoteIntRes_Constant(SDNode *N) { + EVT VT = N->getValueType(0); + // FIXME there is no actual debug info here + DebugLoc dl = N->getDebugLoc(); + // Zero extend things like i1, sign extend everything else. It shouldn't + // matter in theory which one we pick, but this tends to give better code? + unsigned Opc = VT.isByteSized() ? ISD::SIGN_EXTEND : ISD::ZERO_EXTEND; + SDValue Result = DAG.getNode(Opc, dl, TLI.getTypeToTransformTo(*DAG.getContext(), VT), + SDValue(N, 0)); + assert(isa(Result) && "Didn't constant fold ext?"); + return Result; +} + +SDValue DAGTypeLegalizer::PromoteIntRes_CONVERT_RNDSAT(SDNode *N) { + ISD::CvtCode CvtCode = cast(N)->getCvtCode(); + assert ((CvtCode == ISD::CVT_SS || CvtCode == ISD::CVT_SU || + CvtCode == ISD::CVT_US || CvtCode == ISD::CVT_UU || + CvtCode == ISD::CVT_SF || CvtCode == ISD::CVT_UF) && + "can only promote integers"); + EVT OutVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); + return DAG.getConvertRndSat(OutVT, N->getDebugLoc(), N->getOperand(0), + N->getOperand(1), N->getOperand(2), + N->getOperand(3), N->getOperand(4), CvtCode); +} + +SDValue DAGTypeLegalizer::PromoteIntRes_CTLZ(SDNode *N) { + // Zero extend to the promoted type and do the count there. + SDValue Op = ZExtPromotedInteger(N->getOperand(0)); + DebugLoc dl = N->getDebugLoc(); + EVT OVT = N->getValueType(0); + EVT NVT = Op.getValueType(); + Op = DAG.getNode(ISD::CTLZ, dl, NVT, Op); + // Subtract off the extra leading bits in the bigger type. + return DAG.getNode(ISD::SUB, dl, NVT, Op, + DAG.getConstant(NVT.getSizeInBits() - + OVT.getSizeInBits(), NVT)); +} + +SDValue DAGTypeLegalizer::PromoteIntRes_CTPOP(SDNode *N) { + // Zero extend to the promoted type and do the count there. + SDValue Op = ZExtPromotedInteger(N->getOperand(0)); + return DAG.getNode(ISD::CTPOP, N->getDebugLoc(), Op.getValueType(), Op); +} + +SDValue DAGTypeLegalizer::PromoteIntRes_CTTZ(SDNode *N) { + SDValue Op = GetPromotedInteger(N->getOperand(0)); + EVT OVT = N->getValueType(0); + EVT NVT = Op.getValueType(); + DebugLoc dl = N->getDebugLoc(); + // The count is the same in the promoted type except if the original + // value was zero. This can be handled by setting the bit just off + // the top of the original type. + APInt TopBit(NVT.getSizeInBits(), 0); + TopBit.set(OVT.getSizeInBits()); + Op = DAG.getNode(ISD::OR, dl, NVT, Op, DAG.getConstant(TopBit, NVT)); + return DAG.getNode(ISD::CTTZ, dl, NVT, Op); +} + +SDValue DAGTypeLegalizer::PromoteIntRes_EXTRACT_VECTOR_ELT(SDNode *N) { + DebugLoc dl = N->getDebugLoc(); + EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); + return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, NVT, N->getOperand(0), + N->getOperand(1)); +} + +SDValue DAGTypeLegalizer::PromoteIntRes_FP_TO_XINT(SDNode *N) { + EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); + unsigned NewOpc = N->getOpcode(); + DebugLoc dl = N->getDebugLoc(); + + // If we're promoting a UINT to a larger size and the larger FP_TO_UINT is + // not Legal, check to see if we can use FP_TO_SINT instead. (If both UINT + // and SINT conversions are Custom, there is no way to tell which is preferable. + // We choose SINT because that's the right thing on PPC.) + if (N->getOpcode() == ISD::FP_TO_UINT && + !TLI.isOperationLegal(ISD::FP_TO_UINT, NVT) && + TLI.isOperationLegalOrCustom(ISD::FP_TO_SINT, NVT)) + NewOpc = ISD::FP_TO_SINT; + + SDValue Res = DAG.getNode(NewOpc, dl, NVT, N->getOperand(0)); + + // Assert that the converted value fits in the original type. If it doesn't + // (eg: because the value being converted is too big), then the result of the + // original operation was undefined anyway, so the assert is still correct. + return DAG.getNode(N->getOpcode() == ISD::FP_TO_UINT ? + ISD::AssertZext : ISD::AssertSext, dl, + NVT, Res, DAG.getValueType(N->getValueType(0))); +} + +SDValue DAGTypeLegalizer::PromoteIntRes_INT_EXTEND(SDNode *N) { + EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); + DebugLoc dl = N->getDebugLoc(); + + if (getTypeAction(N->getOperand(0).getValueType()) == PromoteInteger) { + SDValue Res = GetPromotedInteger(N->getOperand(0)); + assert(Res.getValueType().bitsLE(NVT) && "Extension doesn't make sense!"); + + // If the result and operand types are the same after promotion, simplify + // to an in-register extension. + if (NVT == Res.getValueType()) { + // The high bits are not guaranteed to be anything. Insert an extend. + if (N->getOpcode() == ISD::SIGN_EXTEND) + return DAG.getNode(ISD::SIGN_EXTEND_INREG, dl, NVT, Res, + DAG.getValueType(N->getOperand(0).getValueType())); + if (N->getOpcode() == ISD::ZERO_EXTEND) + return DAG.getZeroExtendInReg(Res, dl, N->getOperand(0).getValueType()); + assert(N->getOpcode() == ISD::ANY_EXTEND && "Unknown integer extension!"); + return Res; + } + } + + // Otherwise, just extend the original operand all the way to the larger type. + return DAG.getNode(N->getOpcode(), dl, NVT, N->getOperand(0)); +} + +SDValue DAGTypeLegalizer::PromoteIntRes_LOAD(LoadSDNode *N) { + assert(ISD::isUNINDEXEDLoad(N) && "Indexed load during type legalization!"); + EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); + ISD::LoadExtType ExtType = + ISD::isNON_EXTLoad(N) ? ISD::EXTLOAD : N->getExtensionType(); + DebugLoc dl = N->getDebugLoc(); + SDValue Res = DAG.getExtLoad(ExtType, dl, NVT, N->getChain(), N->getBasePtr(), + N->getSrcValue(), N->getSrcValueOffset(), + N->getMemoryVT(), N->isVolatile(), + N->getAlignment()); + + // Legalized the chain result - switch anything that used the old chain to + // use the new one. + ReplaceValueWith(SDValue(N, 1), Res.getValue(1)); + return Res; +} + +/// Promote the overflow flag of an overflowing arithmetic node. +SDValue DAGTypeLegalizer::PromoteIntRes_Overflow(SDNode *N) { + // Simply change the return type of the boolean result. + EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(1)); + EVT ValueVTs[] = { N->getValueType(0), NVT }; + SDValue Ops[] = { N->getOperand(0), N->getOperand(1) }; + SDValue Res = DAG.getNode(N->getOpcode(), N->getDebugLoc(), + DAG.getVTList(ValueVTs, 2), Ops, 2); + + // Modified the sum result - switch anything that used the old sum to use + // the new one. + ReplaceValueWith(SDValue(N, 0), Res); + + return SDValue(Res.getNode(), 1); +} + +SDValue DAGTypeLegalizer::PromoteIntRes_SADDSUBO(SDNode *N, unsigned ResNo) { + if (ResNo == 1) + return PromoteIntRes_Overflow(N); + + // The operation overflowed iff the result in the larger type is not the + // sign extension of its truncation to the original type. + SDValue LHS = SExtPromotedInteger(N->getOperand(0)); + SDValue RHS = SExtPromotedInteger(N->getOperand(1)); + EVT OVT = N->getOperand(0).getValueType(); + EVT NVT = LHS.getValueType(); + DebugLoc dl = N->getDebugLoc(); + + // Do the arithmetic in the larger type. + unsigned Opcode = N->getOpcode() == ISD::SADDO ? ISD::ADD : ISD::SUB; + SDValue Res = DAG.getNode(Opcode, dl, NVT, LHS, RHS); + + // Calculate the overflow flag: sign extend the arithmetic result from + // the original type. + SDValue Ofl = DAG.getNode(ISD::SIGN_EXTEND_INREG, dl, NVT, Res, + DAG.getValueType(OVT)); + // Overflowed if and only if this is not equal to Res. + Ofl = DAG.getSetCC(dl, N->getValueType(1), Ofl, Res, ISD::SETNE); + + // Use the calculated overflow everywhere. + ReplaceValueWith(SDValue(N, 1), Ofl); + + return Res; +} + +SDValue DAGTypeLegalizer::PromoteIntRes_SDIV(SDNode *N) { + // Sign extend the input. + SDValue LHS = SExtPromotedInteger(N->getOperand(0)); + SDValue RHS = SExtPromotedInteger(N->getOperand(1)); + return DAG.getNode(N->getOpcode(), N->getDebugLoc(), + LHS.getValueType(), LHS, RHS); +} + +SDValue DAGTypeLegalizer::PromoteIntRes_SELECT(SDNode *N) { + SDValue LHS = GetPromotedInteger(N->getOperand(1)); + SDValue RHS = GetPromotedInteger(N->getOperand(2)); + return DAG.getNode(ISD::SELECT, N->getDebugLoc(), + LHS.getValueType(), N->getOperand(0),LHS,RHS); +} + +SDValue DAGTypeLegalizer::PromoteIntRes_SELECT_CC(SDNode *N) { + SDValue LHS = GetPromotedInteger(N->getOperand(2)); + SDValue RHS = GetPromotedInteger(N->getOperand(3)); + return DAG.getNode(ISD::SELECT_CC, N->getDebugLoc(), + LHS.getValueType(), N->getOperand(0), + N->getOperand(1), LHS, RHS, N->getOperand(4)); +} + +SDValue DAGTypeLegalizer::PromoteIntRes_SETCC(SDNode *N) { + EVT SVT = TLI.getSetCCResultType(N->getOperand(0).getValueType()); + assert(isTypeLegal(SVT) && "Illegal SetCC type!"); + DebugLoc dl = N->getDebugLoc(); + + // Get the SETCC result using the canonical SETCC type. + SDValue SetCC = DAG.getNode(ISD::SETCC, dl, SVT, N->getOperand(0), + N->getOperand(1), N->getOperand(2)); + + // Convert to the expected type. + EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); + assert(NVT.bitsLE(SVT) && "Integer type overpromoted?"); + return DAG.getNode(ISD::TRUNCATE, dl, NVT, SetCC); +} + +SDValue DAGTypeLegalizer::PromoteIntRes_SHL(SDNode *N) { + return DAG.getNode(ISD::SHL, N->getDebugLoc(), + TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)), + GetPromotedInteger(N->getOperand(0)), N->getOperand(1)); +} + +SDValue DAGTypeLegalizer::PromoteIntRes_SIGN_EXTEND_INREG(SDNode *N) { + SDValue Op = GetPromotedInteger(N->getOperand(0)); + return DAG.getNode(ISD::SIGN_EXTEND_INREG, N->getDebugLoc(), + Op.getValueType(), Op, N->getOperand(1)); +} + +SDValue DAGTypeLegalizer::PromoteIntRes_SimpleIntBinOp(SDNode *N) { + // The input may have strange things in the top bits of the registers, but + // these operations don't care. They may have weird bits going out, but + // that too is okay if they are integer operations. + SDValue LHS = GetPromotedInteger(N->getOperand(0)); + SDValue RHS = GetPromotedInteger(N->getOperand(1)); + return DAG.getNode(N->getOpcode(), N->getDebugLoc(), + LHS.getValueType(), LHS, RHS); +} + +SDValue DAGTypeLegalizer::PromoteIntRes_SRA(SDNode *N) { + // The input value must be properly sign extended. + SDValue Res = SExtPromotedInteger(N->getOperand(0)); + return DAG.getNode(ISD::SRA, N->getDebugLoc(), + Res.getValueType(), Res, N->getOperand(1)); +} + +SDValue DAGTypeLegalizer::PromoteIntRes_SRL(SDNode *N) { + // The input value must be properly zero extended. + EVT VT = N->getValueType(0); + EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT); + SDValue Res = ZExtPromotedInteger(N->getOperand(0)); + return DAG.getNode(ISD::SRL, N->getDebugLoc(), NVT, Res, N->getOperand(1)); +} + +SDValue DAGTypeLegalizer::PromoteIntRes_TRUNCATE(SDNode *N) { + EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); + SDValue Res; + + switch (getTypeAction(N->getOperand(0).getValueType())) { + default: llvm_unreachable("Unknown type action!"); + case Legal: + case ExpandInteger: + Res = N->getOperand(0); + break; + case PromoteInteger: + Res = GetPromotedInteger(N->getOperand(0)); + break; + } + + // Truncate to NVT instead of VT + return DAG.getNode(ISD::TRUNCATE, N->getDebugLoc(), NVT, Res); +} + +SDValue DAGTypeLegalizer::PromoteIntRes_UADDSUBO(SDNode *N, unsigned ResNo) { + if (ResNo == 1) + return PromoteIntRes_Overflow(N); + + // The operation overflowed iff the result in the larger type is not the + // zero extension of its truncation to the original type. + SDValue LHS = ZExtPromotedInteger(N->getOperand(0)); + SDValue RHS = ZExtPromotedInteger(N->getOperand(1)); + EVT OVT = N->getOperand(0).getValueType(); + EVT NVT = LHS.getValueType(); + DebugLoc dl = N->getDebugLoc(); + + // Do the arithmetic in the larger type. + unsigned Opcode = N->getOpcode() == ISD::UADDO ? ISD::ADD : ISD::SUB; + SDValue Res = DAG.getNode(Opcode, dl, NVT, LHS, RHS); + + // Calculate the overflow flag: zero extend the arithmetic result from + // the original type. + SDValue Ofl = DAG.getZeroExtendInReg(Res, dl, OVT); + // Overflowed if and only if this is not equal to Res. + Ofl = DAG.getSetCC(dl, N->getValueType(1), Ofl, Res, ISD::SETNE); + + // Use the calculated overflow everywhere. + ReplaceValueWith(SDValue(N, 1), Ofl); + + return Res; +} + +SDValue DAGTypeLegalizer::PromoteIntRes_UDIV(SDNode *N) { + // Zero extend the input. + SDValue LHS = ZExtPromotedInteger(N->getOperand(0)); + SDValue RHS = ZExtPromotedInteger(N->getOperand(1)); + return DAG.getNode(N->getOpcode(), N->getDebugLoc(), + LHS.getValueType(), LHS, RHS); +} + +SDValue DAGTypeLegalizer::PromoteIntRes_UNDEF(SDNode *N) { + return DAG.getUNDEF(TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0))); +} + +SDValue DAGTypeLegalizer::PromoteIntRes_VAARG(SDNode *N) { + SDValue Chain = N->getOperand(0); // Get the chain. + SDValue Ptr = N->getOperand(1); // Get the pointer. + EVT VT = N->getValueType(0); + DebugLoc dl = N->getDebugLoc(); + + EVT RegVT = TLI.getRegisterType(*DAG.getContext(), VT); + unsigned NumRegs = TLI.getNumRegisters(*DAG.getContext(), VT); + // The argument is passed as NumRegs registers of type RegVT. + + SmallVector Parts(NumRegs); + for (unsigned i = 0; i < NumRegs; ++i) { + Parts[i] = DAG.getVAArg(RegVT, dl, Chain, Ptr, N->getOperand(2)); + Chain = Parts[i].getValue(1); + } + + // Handle endianness of the load. + if (TLI.isBigEndian()) + std::reverse(Parts.begin(), Parts.end()); + + // Assemble the parts in the promoted type. + EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); + SDValue Res = DAG.getNode(ISD::ZERO_EXTEND, dl, NVT, Parts[0]); + for (unsigned i = 1; i < NumRegs; ++i) { + SDValue Part = DAG.getNode(ISD::ZERO_EXTEND, dl, NVT, Parts[i]); + // Shift it to the right position and "or" it in. + Part = DAG.getNode(ISD::SHL, dl, NVT, Part, + DAG.getConstant(i * RegVT.getSizeInBits(), + TLI.getPointerTy())); + Res = DAG.getNode(ISD::OR, dl, NVT, Res, Part); + } + + // Modified the chain result - switch anything that used the old chain to + // use the new one. + ReplaceValueWith(SDValue(N, 1), Chain); + + return Res; +} + +SDValue DAGTypeLegalizer::PromoteIntRes_XMULO(SDNode *N, unsigned ResNo) { + assert(ResNo == 1 && "Only boolean result promotion currently supported!"); + return PromoteIntRes_Overflow(N); +} + +//===----------------------------------------------------------------------===// +// Integer Operand Promotion +//===----------------------------------------------------------------------===// + +/// PromoteIntegerOperand - This method is called when the specified operand of +/// the specified node is found to need promotion. At this point, all of the +/// result types of the node are known to be legal, but other operands of the +/// node may need promotion or expansion as well as the specified one. +bool DAGTypeLegalizer::PromoteIntegerOperand(SDNode *N, unsigned OpNo) { + DEBUG(errs() << "Promote integer operand: "; N->dump(&DAG); errs() << "\n"); + SDValue Res = SDValue(); + + if (CustomLowerNode(N, N->getOperand(OpNo).getValueType(), false)) + return false; + + switch (N->getOpcode()) { + default: + #ifndef NDEBUG + errs() << "PromoteIntegerOperand Op #" << OpNo << ": "; + N->dump(&DAG); errs() << "\n"; + #endif + llvm_unreachable("Do not know how to promote this operator's operand!"); + + case ISD::ANY_EXTEND: Res = PromoteIntOp_ANY_EXTEND(N); break; + case ISD::BIT_CONVERT: Res = PromoteIntOp_BIT_CONVERT(N); break; + case ISD::BR_CC: Res = PromoteIntOp_BR_CC(N, OpNo); break; + case ISD::BRCOND: Res = PromoteIntOp_BRCOND(N, OpNo); break; + case ISD::BUILD_PAIR: Res = PromoteIntOp_BUILD_PAIR(N); break; + case ISD::BUILD_VECTOR: Res = PromoteIntOp_BUILD_VECTOR(N); break; + case ISD::CONVERT_RNDSAT: + Res = PromoteIntOp_CONVERT_RNDSAT(N); break; + case ISD::INSERT_VECTOR_ELT: + Res = PromoteIntOp_INSERT_VECTOR_ELT(N, OpNo);break; + case ISD::MEMBARRIER: Res = PromoteIntOp_MEMBARRIER(N); break; + case ISD::SCALAR_TO_VECTOR: + Res = PromoteIntOp_SCALAR_TO_VECTOR(N); break; + case ISD::SELECT: Res = PromoteIntOp_SELECT(N, OpNo); break; + case ISD::SELECT_CC: Res = PromoteIntOp_SELECT_CC(N, OpNo); break; + case ISD::SETCC: Res = PromoteIntOp_SETCC(N, OpNo); break; + case ISD::SIGN_EXTEND: Res = PromoteIntOp_SIGN_EXTEND(N); break; + case ISD::SINT_TO_FP: Res = PromoteIntOp_SINT_TO_FP(N); break; + case ISD::STORE: Res = PromoteIntOp_STORE(cast(N), + OpNo); break; + case ISD::TRUNCATE: Res = PromoteIntOp_TRUNCATE(N); break; + case ISD::UINT_TO_FP: Res = PromoteIntOp_UINT_TO_FP(N); break; + case ISD::ZERO_EXTEND: Res = PromoteIntOp_ZERO_EXTEND(N); break; + + case ISD::SHL: + case ISD::SRA: + case ISD::SRL: + case ISD::ROTL: + case ISD::ROTR: Res = PromoteIntOp_Shift(N); break; + } + + // If the result is null, the sub-method took care of registering results etc. + if (!Res.getNode()) return false; + + // If the result is N, the sub-method updated N in place. Tell the legalizer + // core about this. + if (Res.getNode() == N) + return true; + + assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 1 && + "Invalid operand expansion"); + + ReplaceValueWith(SDValue(N, 0), Res); + return false; +} + +/// PromoteSetCCOperands - Promote the operands of a comparison. This code is +/// shared among BR_CC, SELECT_CC, and SETCC handlers. +void DAGTypeLegalizer::PromoteSetCCOperands(SDValue &NewLHS,SDValue &NewRHS, + ISD::CondCode CCCode) { + // We have to insert explicit sign or zero extends. Note that we could + // insert sign extends for ALL conditions, but zero extend is cheaper on + // many machines (an AND instead of two shifts), so prefer it. + switch (CCCode) { + default: llvm_unreachable("Unknown integer comparison!"); + case ISD::SETEQ: + case ISD::SETNE: + case ISD::SETUGE: + case ISD::SETUGT: + case ISD::SETULE: + case ISD::SETULT: + // ALL of these operations will work if we either sign or zero extend + // the operands (including the unsigned comparisons!). Zero extend is + // usually a simpler/cheaper operation, so prefer it. + NewLHS = ZExtPromotedInteger(NewLHS); + NewRHS = ZExtPromotedInteger(NewRHS); + break; + case ISD::SETGE: + case ISD::SETGT: + case ISD::SETLT: + case ISD::SETLE: + NewLHS = SExtPromotedInteger(NewLHS); + NewRHS = SExtPromotedInteger(NewRHS); + break; + } +} + +SDValue DAGTypeLegalizer::PromoteIntOp_ANY_EXTEND(SDNode *N) { + SDValue Op = GetPromotedInteger(N->getOperand(0)); + return DAG.getNode(ISD::ANY_EXTEND, N->getDebugLoc(), N->getValueType(0), Op); +} + +SDValue DAGTypeLegalizer::PromoteIntOp_BIT_CONVERT(SDNode *N) { + // This should only occur in unusual situations like bitcasting to an + // x86_fp80, so just turn it into a store+load + return CreateStackStoreLoad(N->getOperand(0), N->getValueType(0)); +} + +SDValue DAGTypeLegalizer::PromoteIntOp_BR_CC(SDNode *N, unsigned OpNo) { + assert(OpNo == 2 && "Don't know how to promote this operand!"); + + SDValue LHS = N->getOperand(2); + SDValue RHS = N->getOperand(3); + PromoteSetCCOperands(LHS, RHS, cast(N->getOperand(1))->get()); + + // The chain (Op#0), CC (#1) and basic block destination (Op#4) are always + // legal types. + return DAG.UpdateNodeOperands(SDValue(N, 0), N->getOperand(0), + N->getOperand(1), LHS, RHS, N->getOperand(4)); +} + +SDValue DAGTypeLegalizer::PromoteIntOp_BRCOND(SDNode *N, unsigned OpNo) { + assert(OpNo == 1 && "only know how to promote condition"); + + // Promote all the way up to the canonical SetCC type. + EVT SVT = TLI.getSetCCResultType(MVT::Other); + SDValue Cond = PromoteTargetBoolean(N->getOperand(1), SVT); + + // The chain (Op#0) and basic block destination (Op#2) are always legal types. + return DAG.UpdateNodeOperands(SDValue(N, 0), N->getOperand(0), Cond, + N->getOperand(2)); +} + +SDValue DAGTypeLegalizer::PromoteIntOp_BUILD_PAIR(SDNode *N) { + // Since the result type is legal, the operands must promote to it. + EVT OVT = N->getOperand(0).getValueType(); + SDValue Lo = ZExtPromotedInteger(N->getOperand(0)); + SDValue Hi = GetPromotedInteger(N->getOperand(1)); + assert(Lo.getValueType() == N->getValueType(0) && "Operand over promoted?"); + DebugLoc dl = N->getDebugLoc(); + + Hi = DAG.getNode(ISD::SHL, dl, N->getValueType(0), Hi, + DAG.getConstant(OVT.getSizeInBits(), TLI.getPointerTy())); + return DAG.getNode(ISD::OR, dl, N->getValueType(0), Lo, Hi); +} + +SDValue DAGTypeLegalizer::PromoteIntOp_BUILD_VECTOR(SDNode *N) { + // The vector type is legal but the element type is not. This implies + // that the vector is a power-of-two in length and that the element + // type does not have a strange size (eg: it is not i1). + EVT VecVT = N->getValueType(0); + unsigned NumElts = VecVT.getVectorNumElements(); + assert(!(NumElts & 1) && "Legal vector of one illegal element?"); + + // Promote the inserted value. The type does not need to match the + // vector element type. Check that any extra bits introduced will be + // truncated away. + assert(N->getOperand(0).getValueType().getSizeInBits() >= + N->getValueType(0).getVectorElementType().getSizeInBits() && + "Type of inserted value narrower than vector element type!"); + + SmallVector NewOps; + for (unsigned i = 0; i < NumElts; ++i) + NewOps.push_back(GetPromotedInteger(N->getOperand(i))); + + return DAG.UpdateNodeOperands(SDValue(N, 0), &NewOps[0], NumElts); +} + +SDValue DAGTypeLegalizer::PromoteIntOp_CONVERT_RNDSAT(SDNode *N) { + ISD::CvtCode CvtCode = cast(N)->getCvtCode(); + assert ((CvtCode == ISD::CVT_SS || CvtCode == ISD::CVT_SU || + CvtCode == ISD::CVT_US || CvtCode == ISD::CVT_UU || + CvtCode == ISD::CVT_FS || CvtCode == ISD::CVT_FU) && + "can only promote integer arguments"); + SDValue InOp = GetPromotedInteger(N->getOperand(0)); + return DAG.getConvertRndSat(N->getValueType(0), N->getDebugLoc(), InOp, + N->getOperand(1), N->getOperand(2), + N->getOperand(3), N->getOperand(4), CvtCode); +} + +SDValue DAGTypeLegalizer::PromoteIntOp_INSERT_VECTOR_ELT(SDNode *N, + unsigned OpNo) { + if (OpNo == 1) { + // Promote the inserted value. This is valid because the type does not + // have to match the vector element type. + + // Check that any extra bits introduced will be truncated away. + assert(N->getOperand(1).getValueType().getSizeInBits() >= + N->getValueType(0).getVectorElementType().getSizeInBits() && + "Type of inserted value narrower than vector element type!"); + return DAG.UpdateNodeOperands(SDValue(N, 0), N->getOperand(0), + GetPromotedInteger(N->getOperand(1)), + N->getOperand(2)); + } + + assert(OpNo == 2 && "Different operand and result vector types?"); + + // Promote the index. + SDValue Idx = ZExtPromotedInteger(N->getOperand(2)); + return DAG.UpdateNodeOperands(SDValue(N, 0), N->getOperand(0), + N->getOperand(1), Idx); +} + +SDValue DAGTypeLegalizer::PromoteIntOp_MEMBARRIER(SDNode *N) { + SDValue NewOps[6]; + DebugLoc dl = N->getDebugLoc(); + NewOps[0] = N->getOperand(0); + for (unsigned i = 1; i < array_lengthof(NewOps); ++i) { + SDValue Flag = GetPromotedInteger(N->getOperand(i)); + NewOps[i] = DAG.getZeroExtendInReg(Flag, dl, MVT::i1); + } + return DAG.UpdateNodeOperands(SDValue (N, 0), NewOps, + array_lengthof(NewOps)); +} + +SDValue DAGTypeLegalizer::PromoteIntOp_SCALAR_TO_VECTOR(SDNode *N) { + // Integer SCALAR_TO_VECTOR operands are implicitly truncated, so just promote + // the operand in place. + return DAG.UpdateNodeOperands(SDValue(N, 0), + GetPromotedInteger(N->getOperand(0))); +} + +SDValue DAGTypeLegalizer::PromoteIntOp_SELECT(SDNode *N, unsigned OpNo) { + assert(OpNo == 0 && "Only know how to promote condition"); + + // Promote all the way up to the canonical SetCC type. + EVT SVT = TLI.getSetCCResultType(N->getOperand(1).getValueType()); + SDValue Cond = PromoteTargetBoolean(N->getOperand(0), SVT); + + return DAG.UpdateNodeOperands(SDValue(N, 0), Cond, + N->getOperand(1), N->getOperand(2)); +} + +SDValue DAGTypeLegalizer::PromoteIntOp_SELECT_CC(SDNode *N, unsigned OpNo) { + assert(OpNo == 0 && "Don't know how to promote this operand!"); + + SDValue LHS = N->getOperand(0); + SDValue RHS = N->getOperand(1); + PromoteSetCCOperands(LHS, RHS, cast(N->getOperand(4))->get()); + + // The CC (#4) and the possible return values (#2 and #3) have legal types. + return DAG.UpdateNodeOperands(SDValue(N, 0), LHS, RHS, N->getOperand(2), + N->getOperand(3), N->getOperand(4)); +} + +SDValue DAGTypeLegalizer::PromoteIntOp_SETCC(SDNode *N, unsigned OpNo) { + assert(OpNo == 0 && "Don't know how to promote this operand!"); + + SDValue LHS = N->getOperand(0); + SDValue RHS = N->getOperand(1); + PromoteSetCCOperands(LHS, RHS, cast(N->getOperand(2))->get()); + + // The CC (#2) is always legal. + return DAG.UpdateNodeOperands(SDValue(N, 0), LHS, RHS, N->getOperand(2)); +} + +SDValue DAGTypeLegalizer::PromoteIntOp_Shift(SDNode *N) { + return DAG.UpdateNodeOperands(SDValue(N, 0), N->getOperand(0), + ZExtPromotedInteger(N->getOperand(1))); +} + +SDValue DAGTypeLegalizer::PromoteIntOp_SIGN_EXTEND(SDNode *N) { + SDValue Op = GetPromotedInteger(N->getOperand(0)); + DebugLoc dl = N->getDebugLoc(); + Op = DAG.getNode(ISD::ANY_EXTEND, dl, N->getValueType(0), Op); + return DAG.getNode(ISD::SIGN_EXTEND_INREG, dl, Op.getValueType(), + Op, DAG.getValueType(N->getOperand(0).getValueType())); +} + +SDValue DAGTypeLegalizer::PromoteIntOp_SINT_TO_FP(SDNode *N) { + return DAG.UpdateNodeOperands(SDValue(N, 0), + SExtPromotedInteger(N->getOperand(0))); +} + +SDValue DAGTypeLegalizer::PromoteIntOp_STORE(StoreSDNode *N, unsigned OpNo){ + assert(ISD::isUNINDEXEDStore(N) && "Indexed store during type legalization!"); + SDValue Ch = N->getChain(), Ptr = N->getBasePtr(); + int SVOffset = N->getSrcValueOffset(); + unsigned Alignment = N->getAlignment(); + bool isVolatile = N->isVolatile(); + DebugLoc dl = N->getDebugLoc(); + + SDValue Val = GetPromotedInteger(N->getValue()); // Get promoted value. + + // Truncate the value and store the result. + return DAG.getTruncStore(Ch, dl, Val, Ptr, N->getSrcValue(), + SVOffset, N->getMemoryVT(), + isVolatile, Alignment); +} + +SDValue DAGTypeLegalizer::PromoteIntOp_TRUNCATE(SDNode *N) { + SDValue Op = GetPromotedInteger(N->getOperand(0)); + return DAG.getNode(ISD::TRUNCATE, N->getDebugLoc(), N->getValueType(0), Op); +} + +SDValue DAGTypeLegalizer::PromoteIntOp_UINT_TO_FP(SDNode *N) { + return DAG.UpdateNodeOperands(SDValue(N, 0), + ZExtPromotedInteger(N->getOperand(0))); +} + +SDValue DAGTypeLegalizer::PromoteIntOp_ZERO_EXTEND(SDNode *N) { + DebugLoc dl = N->getDebugLoc(); + SDValue Op = GetPromotedInteger(N->getOperand(0)); + Op = DAG.getNode(ISD::ANY_EXTEND, dl, N->getValueType(0), Op); + return DAG.getZeroExtendInReg(Op, dl, N->getOperand(0).getValueType()); +} + + +//===----------------------------------------------------------------------===// +// Integer Result Expansion +//===----------------------------------------------------------------------===// + +/// ExpandIntegerResult - This method is called when the specified result of the +/// specified node is found to need expansion. At this point, the node may also +/// have invalid operands or may have other results that need promotion, we just +/// know that (at least) one result needs expansion. +void DAGTypeLegalizer::ExpandIntegerResult(SDNode *N, unsigned ResNo) { + DEBUG(errs() << "Expand integer result: "; N->dump(&DAG); errs() << "\n"); + SDValue Lo, Hi; + Lo = Hi = SDValue(); + + // See if the target wants to custom expand this node. + if (CustomLowerNode(N, N->getValueType(ResNo), true)) + return; + + switch (N->getOpcode()) { + default: +#ifndef NDEBUG + errs() << "ExpandIntegerResult #" << ResNo << ": "; + N->dump(&DAG); errs() << "\n"; +#endif + llvm_unreachable("Do not know how to expand the result of this operator!"); + + case ISD::MERGE_VALUES: SplitRes_MERGE_VALUES(N, Lo, Hi); break; + case ISD::SELECT: SplitRes_SELECT(N, Lo, Hi); break; + case ISD::SELECT_CC: SplitRes_SELECT_CC(N, Lo, Hi); break; + case ISD::UNDEF: SplitRes_UNDEF(N, Lo, Hi); break; + + case ISD::BIT_CONVERT: ExpandRes_BIT_CONVERT(N, Lo, Hi); break; + case ISD::BUILD_PAIR: ExpandRes_BUILD_PAIR(N, Lo, Hi); break; + case ISD::EXTRACT_ELEMENT: ExpandRes_EXTRACT_ELEMENT(N, Lo, Hi); break; + case ISD::EXTRACT_VECTOR_ELT: ExpandRes_EXTRACT_VECTOR_ELT(N, Lo, Hi); break; + case ISD::VAARG: ExpandRes_VAARG(N, Lo, Hi); break; + + case ISD::ANY_EXTEND: ExpandIntRes_ANY_EXTEND(N, Lo, Hi); break; + case ISD::AssertSext: ExpandIntRes_AssertSext(N, Lo, Hi); break; + case ISD::AssertZext: ExpandIntRes_AssertZext(N, Lo, Hi); break; + case ISD::BSWAP: ExpandIntRes_BSWAP(N, Lo, Hi); break; + case ISD::Constant: ExpandIntRes_Constant(N, Lo, Hi); break; + case ISD::CTLZ: ExpandIntRes_CTLZ(N, Lo, Hi); break; + case ISD::CTPOP: ExpandIntRes_CTPOP(N, Lo, Hi); break; + case ISD::CTTZ: ExpandIntRes_CTTZ(N, Lo, Hi); break; + case ISD::FP_TO_SINT: ExpandIntRes_FP_TO_SINT(N, Lo, Hi); break; + case ISD::FP_TO_UINT: ExpandIntRes_FP_TO_UINT(N, Lo, Hi); break; + case ISD::LOAD: ExpandIntRes_LOAD(cast(N), Lo, Hi); break; + case ISD::MUL: ExpandIntRes_MUL(N, Lo, Hi); break; + case ISD::SDIV: ExpandIntRes_SDIV(N, Lo, Hi); break; + case ISD::SIGN_EXTEND: ExpandIntRes_SIGN_EXTEND(N, Lo, Hi); break; + case ISD::SIGN_EXTEND_INREG: ExpandIntRes_SIGN_EXTEND_INREG(N, Lo, Hi); break; + case ISD::SREM: ExpandIntRes_SREM(N, Lo, Hi); break; + case ISD::TRUNCATE: ExpandIntRes_TRUNCATE(N, Lo, Hi); break; + case ISD::UDIV: ExpandIntRes_UDIV(N, Lo, Hi); break; + case ISD::UREM: ExpandIntRes_UREM(N, Lo, Hi); break; + case ISD::ZERO_EXTEND: ExpandIntRes_ZERO_EXTEND(N, Lo, Hi); break; + + case ISD::AND: + case ISD::OR: + case ISD::XOR: ExpandIntRes_Logical(N, Lo, Hi); break; + + case ISD::ADD: + case ISD::SUB: ExpandIntRes_ADDSUB(N, Lo, Hi); break; + + case ISD::ADDC: + case ISD::SUBC: ExpandIntRes_ADDSUBC(N, Lo, Hi); break; + + case ISD::ADDE: + case ISD::SUBE: ExpandIntRes_ADDSUBE(N, Lo, Hi); break; + + case ISD::SHL: + case ISD::SRA: + case ISD::SRL: ExpandIntRes_Shift(N, Lo, Hi); break; + } + + // If Lo/Hi is null, the sub-method took care of registering results etc. + if (Lo.getNode()) + SetExpandedInteger(SDValue(N, ResNo), Lo, Hi); +} + +/// ExpandShiftByConstant - N is a shift by a value that needs to be expanded, +/// and the shift amount is a constant 'Amt'. Expand the operation. +void DAGTypeLegalizer::ExpandShiftByConstant(SDNode *N, unsigned Amt, + SDValue &Lo, SDValue &Hi) { + DebugLoc dl = N->getDebugLoc(); + // Expand the incoming operand to be shifted, so that we have its parts + SDValue InL, InH; + GetExpandedInteger(N->getOperand(0), InL, InH); + + EVT NVT = InL.getValueType(); + unsigned VTBits = N->getValueType(0).getSizeInBits(); + unsigned NVTBits = NVT.getSizeInBits(); + EVT ShTy = N->getOperand(1).getValueType(); + + if (N->getOpcode() == ISD::SHL) { + if (Amt > VTBits) { + Lo = Hi = DAG.getConstant(0, NVT); + } else if (Amt > NVTBits) { + Lo = DAG.getConstant(0, NVT); + Hi = DAG.getNode(ISD::SHL, dl, + NVT, InL, DAG.getConstant(Amt-NVTBits,ShTy)); + } else if (Amt == NVTBits) { + Lo = DAG.getConstant(0, NVT); + Hi = InL; + } else if (Amt == 1 && + TLI.isOperationLegalOrCustom(ISD::ADDC, + TLI.getTypeToExpandTo(*DAG.getContext(), NVT))) { + // Emit this X << 1 as X+X. + SDVTList VTList = DAG.getVTList(NVT, MVT::Flag); + SDValue LoOps[2] = { InL, InL }; + Lo = DAG.getNode(ISD::ADDC, dl, VTList, LoOps, 2); + SDValue HiOps[3] = { InH, InH, Lo.getValue(1) }; + Hi = DAG.getNode(ISD::ADDE, dl, VTList, HiOps, 3); + } else { + Lo = DAG.getNode(ISD::SHL, dl, NVT, InL, DAG.getConstant(Amt, ShTy)); + Hi = DAG.getNode(ISD::OR, dl, NVT, + DAG.getNode(ISD::SHL, dl, NVT, InH, + DAG.getConstant(Amt, ShTy)), + DAG.getNode(ISD::SRL, dl, NVT, InL, + DAG.getConstant(NVTBits-Amt, ShTy))); + } + return; + } + + if (N->getOpcode() == ISD::SRL) { + if (Amt > VTBits) { + Lo = DAG.getConstant(0, NVT); + Hi = DAG.getConstant(0, NVT); + } else if (Amt > NVTBits) { + Lo = DAG.getNode(ISD::SRL, dl, + NVT, InH, DAG.getConstant(Amt-NVTBits,ShTy)); + Hi = DAG.getConstant(0, NVT); + } else if (Amt == NVTBits) { + Lo = InH; + Hi = DAG.getConstant(0, NVT); + } else { + Lo = DAG.getNode(ISD::OR, dl, NVT, + DAG.getNode(ISD::SRL, dl, NVT, InL, + DAG.getConstant(Amt, ShTy)), + DAG.getNode(ISD::SHL, dl, NVT, InH, + DAG.getConstant(NVTBits-Amt, ShTy))); + Hi = DAG.getNode(ISD::SRL, dl, NVT, InH, DAG.getConstant(Amt, ShTy)); + } + return; + } + + assert(N->getOpcode() == ISD::SRA && "Unknown shift!"); + if (Amt > VTBits) { + Hi = Lo = DAG.getNode(ISD::SRA, dl, NVT, InH, + DAG.getConstant(NVTBits-1, ShTy)); + } else if (Amt > NVTBits) { + Lo = DAG.getNode(ISD::SRA, dl, NVT, InH, + DAG.getConstant(Amt-NVTBits, ShTy)); + Hi = DAG.getNode(ISD::SRA, dl, NVT, InH, + DAG.getConstant(NVTBits-1, ShTy)); + } else if (Amt == NVTBits) { + Lo = InH; + Hi = DAG.getNode(ISD::SRA, dl, NVT, InH, + DAG.getConstant(NVTBits-1, ShTy)); + } else { + Lo = DAG.getNode(ISD::OR, dl, NVT, + DAG.getNode(ISD::SRL, dl, NVT, InL, + DAG.getConstant(Amt, ShTy)), + DAG.getNode(ISD::SHL, dl, NVT, InH, + DAG.getConstant(NVTBits-Amt, ShTy))); + Hi = DAG.getNode(ISD::SRA, dl, NVT, InH, DAG.getConstant(Amt, ShTy)); + } +} + +/// ExpandShiftWithKnownAmountBit - Try to determine whether we can simplify +/// this shift based on knowledge of the high bit of the shift amount. If we +/// can tell this, we know that it is >= 32 or < 32, without knowing the actual +/// shift amount. +bool DAGTypeLegalizer:: +ExpandShiftWithKnownAmountBit(SDNode *N, SDValue &Lo, SDValue &Hi) { + SDValue Amt = N->getOperand(1); + EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); + EVT ShTy = Amt.getValueType(); + unsigned ShBits = ShTy.getSizeInBits(); + unsigned NVTBits = NVT.getSizeInBits(); + assert(isPowerOf2_32(NVTBits) && + "Expanded integer type size not a power of two!"); + DebugLoc dl = N->getDebugLoc(); + + APInt HighBitMask = APInt::getHighBitsSet(ShBits, ShBits - Log2_32(NVTBits)); + APInt KnownZero, KnownOne; + DAG.ComputeMaskedBits(N->getOperand(1), HighBitMask, KnownZero, KnownOne); + + // If we don't know anything about the high bits, exit. + if (((KnownZero|KnownOne) & HighBitMask) == 0) + return false; + + // Get the incoming operand to be shifted. + SDValue InL, InH; + GetExpandedInteger(N->getOperand(0), InL, InH); + + // If we know that any of the high bits of the shift amount are one, then we + // can do this as a couple of simple shifts. + if (KnownOne.intersects(HighBitMask)) { + // Mask out the high bit, which we know is set. + Amt = DAG.getNode(ISD::AND, dl, ShTy, Amt, + DAG.getConstant(~HighBitMask, ShTy)); + + switch (N->getOpcode()) { + default: llvm_unreachable("Unknown shift"); + case ISD::SHL: + Lo = DAG.getConstant(0, NVT); // Low part is zero. + Hi = DAG.getNode(ISD::SHL, dl, NVT, InL, Amt); // High part from Lo part. + return true; + case ISD::SRL: + Hi = DAG.getConstant(0, NVT); // Hi part is zero. + Lo = DAG.getNode(ISD::SRL, dl, NVT, InH, Amt); // Lo part from Hi part. + return true; + case ISD::SRA: + Hi = DAG.getNode(ISD::SRA, dl, NVT, InH, // Sign extend high part. + DAG.getConstant(NVTBits-1, ShTy)); + Lo = DAG.getNode(ISD::SRA, dl, NVT, InH, Amt); // Lo part from Hi part. + return true; + } + } + +#if 0 + // FIXME: This code is broken for shifts with a zero amount! + // If we know that all of the high bits of the shift amount are zero, then we + // can do this as a couple of simple shifts. + if ((KnownZero & HighBitMask) == HighBitMask) { + // Compute 32-amt. + SDValue Amt2 = DAG.getNode(ISD::SUB, ShTy, + DAG.getConstant(NVTBits, ShTy), + Amt); + unsigned Op1, Op2; + switch (N->getOpcode()) { + default: llvm_unreachable("Unknown shift"); + case ISD::SHL: Op1 = ISD::SHL; Op2 = ISD::SRL; break; + case ISD::SRL: + case ISD::SRA: Op1 = ISD::SRL; Op2 = ISD::SHL; break; + } + + Lo = DAG.getNode(N->getOpcode(), NVT, InL, Amt); + Hi = DAG.getNode(ISD::OR, NVT, + DAG.getNode(Op1, NVT, InH, Amt), + DAG.getNode(Op2, NVT, InL, Amt2)); + return true; + } +#endif + + return false; +} + +/// ExpandShiftWithUnknownAmountBit - Fully general expansion of integer shift +/// of any size. +bool DAGTypeLegalizer:: +ExpandShiftWithUnknownAmountBit(SDNode *N, SDValue &Lo, SDValue &Hi) { + SDValue Amt = N->getOperand(1); + EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); + EVT ShTy = Amt.getValueType(); + unsigned NVTBits = NVT.getSizeInBits(); + assert(isPowerOf2_32(NVTBits) && + "Expanded integer type size not a power of two!"); + DebugLoc dl = N->getDebugLoc(); + + // Get the incoming operand to be shifted. + SDValue InL, InH; + GetExpandedInteger(N->getOperand(0), InL, InH); + + SDValue NVBitsNode = DAG.getConstant(NVTBits, ShTy); + SDValue Amt2 = DAG.getNode(ISD::SUB, dl, ShTy, NVBitsNode, Amt); + SDValue Cmp = DAG.getSetCC(dl, TLI.getSetCCResultType(ShTy), + Amt, NVBitsNode, ISD::SETULT); + + SDValue Lo1, Hi1, Lo2, Hi2; + switch (N->getOpcode()) { + default: llvm_unreachable("Unknown shift"); + case ISD::SHL: + // ShAmt < NVTBits + Lo1 = DAG.getConstant(0, NVT); // Low part is zero. + Hi1 = DAG.getNode(ISD::SHL, dl, NVT, InL, Amt); // High part from Lo part. + + // ShAmt >= NVTBits + Lo2 = DAG.getNode(ISD::SHL, dl, NVT, InL, Amt); + Hi2 = DAG.getNode(ISD::OR, dl, NVT, + DAG.getNode(ISD::SHL, dl, NVT, InH, Amt), + DAG.getNode(ISD::SRL, dl, NVT, InL, Amt2)); + + Lo = DAG.getNode(ISD::SELECT, dl, NVT, Cmp, Lo1, Lo2); + Hi = DAG.getNode(ISD::SELECT, dl, NVT, Cmp, Hi1, Hi2); + return true; + case ISD::SRL: + // ShAmt < NVTBits + Hi1 = DAG.getConstant(0, NVT); // Hi part is zero. + Lo1 = DAG.getNode(ISD::SRL, dl, NVT, InH, Amt); // Lo part from Hi part. + + // ShAmt >= NVTBits + Hi2 = DAG.getNode(ISD::SRL, dl, NVT, InH, Amt); + Lo2 = DAG.getNode(ISD::OR, dl, NVT, + DAG.getNode(ISD::SRL, dl, NVT, InL, Amt), + DAG.getNode(ISD::SHL, dl, NVT, InH, Amt2)); + + Lo = DAG.getNode(ISD::SELECT, dl, NVT, Cmp, Lo1, Lo2); + Hi = DAG.getNode(ISD::SELECT, dl, NVT, Cmp, Hi1, Hi2); + return true; + case ISD::SRA: + // ShAmt < NVTBits + Hi1 = DAG.getNode(ISD::SRA, dl, NVT, InH, // Sign extend high part. + DAG.getConstant(NVTBits-1, ShTy)); + Lo1 = DAG.getNode(ISD::SRA, dl, NVT, InH, Amt); // Lo part from Hi part. + + // ShAmt >= NVTBits + Hi2 = DAG.getNode(ISD::SRA, dl, NVT, InH, Amt); + Lo2 = DAG.getNode(ISD::OR, dl, NVT, + DAG.getNode(ISD::SRL, dl, NVT, InL, Amt), + DAG.getNode(ISD::SHL, dl, NVT, InH, Amt2)); + + Lo = DAG.getNode(ISD::SELECT, dl, NVT, Cmp, Lo1, Lo2); + Hi = DAG.getNode(ISD::SELECT, dl, NVT, Cmp, Hi1, Hi2); + return true; + } + + return false; +} + +void DAGTypeLegalizer::ExpandIntRes_ADDSUB(SDNode *N, + SDValue &Lo, SDValue &Hi) { + DebugLoc dl = N->getDebugLoc(); + // Expand the subcomponents. + SDValue LHSL, LHSH, RHSL, RHSH; + GetExpandedInteger(N->getOperand(0), LHSL, LHSH); + GetExpandedInteger(N->getOperand(1), RHSL, RHSH); + + EVT NVT = LHSL.getValueType(); + SDValue LoOps[2] = { LHSL, RHSL }; + SDValue HiOps[3] = { LHSH, RHSH }; + + // Do not generate ADDC/ADDE or SUBC/SUBE if the target does not support + // them. TODO: Teach operation legalization how to expand unsupported + // ADDC/ADDE/SUBC/SUBE. The problem is that these operations generate + // a carry of type MVT::Flag, but there doesn't seem to be any way to + // generate a value of this type in the expanded code sequence. + bool hasCarry = + TLI.isOperationLegalOrCustom(N->getOpcode() == ISD::ADD ? + ISD::ADDC : ISD::SUBC, + TLI.getTypeToExpandTo(*DAG.getContext(), NVT)); + + if (hasCarry) { + SDVTList VTList = DAG.getVTList(NVT, MVT::Flag); + if (N->getOpcode() == ISD::ADD) { + Lo = DAG.getNode(ISD::ADDC, dl, VTList, LoOps, 2); + HiOps[2] = Lo.getValue(1); + Hi = DAG.getNode(ISD::ADDE, dl, VTList, HiOps, 3); + } else { + Lo = DAG.getNode(ISD::SUBC, dl, VTList, LoOps, 2); + HiOps[2] = Lo.getValue(1); + Hi = DAG.getNode(ISD::SUBE, dl, VTList, HiOps, 3); + } + } else { + if (N->getOpcode() == ISD::ADD) { + Lo = DAG.getNode(ISD::ADD, dl, NVT, LoOps, 2); + Hi = DAG.getNode(ISD::ADD, dl, NVT, HiOps, 2); + SDValue Cmp1 = DAG.getSetCC(dl, TLI.getSetCCResultType(NVT), Lo, LoOps[0], + ISD::SETULT); + SDValue Carry1 = DAG.getNode(ISD::SELECT, dl, NVT, Cmp1, + DAG.getConstant(1, NVT), + DAG.getConstant(0, NVT)); + SDValue Cmp2 = DAG.getSetCC(dl, TLI.getSetCCResultType(NVT), Lo, LoOps[1], + ISD::SETULT); + SDValue Carry2 = DAG.getNode(ISD::SELECT, dl, NVT, Cmp2, + DAG.getConstant(1, NVT), Carry1); + Hi = DAG.getNode(ISD::ADD, dl, NVT, Hi, Carry2); + } else { + Lo = DAG.getNode(ISD::SUB, dl, NVT, LoOps, 2); + Hi = DAG.getNode(ISD::SUB, dl, NVT, HiOps, 2); + SDValue Cmp = + DAG.getSetCC(dl, TLI.getSetCCResultType(LoOps[0].getValueType()), + LoOps[0], LoOps[1], ISD::SETULT); + SDValue Borrow = DAG.getNode(ISD::SELECT, dl, NVT, Cmp, + DAG.getConstant(1, NVT), + DAG.getConstant(0, NVT)); + Hi = DAG.getNode(ISD::SUB, dl, NVT, Hi, Borrow); + } + } +} + +void DAGTypeLegalizer::ExpandIntRes_ADDSUBC(SDNode *N, + SDValue &Lo, SDValue &Hi) { + // Expand the subcomponents. + SDValue LHSL, LHSH, RHSL, RHSH; + DebugLoc dl = N->getDebugLoc(); + GetExpandedInteger(N->getOperand(0), LHSL, LHSH); + GetExpandedInteger(N->getOperand(1), RHSL, RHSH); + SDVTList VTList = DAG.getVTList(LHSL.getValueType(), MVT::Flag); + SDValue LoOps[2] = { LHSL, RHSL }; + SDValue HiOps[3] = { LHSH, RHSH }; + + if (N->getOpcode() == ISD::ADDC) { + Lo = DAG.getNode(ISD::ADDC, dl, VTList, LoOps, 2); + HiOps[2] = Lo.getValue(1); + Hi = DAG.getNode(ISD::ADDE, dl, VTList, HiOps, 3); + } else { + Lo = DAG.getNode(ISD::SUBC, dl, VTList, LoOps, 2); + HiOps[2] = Lo.getValue(1); + Hi = DAG.getNode(ISD::SUBE, dl, VTList, HiOps, 3); + } + + // Legalized the flag result - switch anything that used the old flag to + // use the new one. + ReplaceValueWith(SDValue(N, 1), Hi.getValue(1)); +} + +void DAGTypeLegalizer::ExpandIntRes_ADDSUBE(SDNode *N, + SDValue &Lo, SDValue &Hi) { + // Expand the subcomponents. + SDValue LHSL, LHSH, RHSL, RHSH; + DebugLoc dl = N->getDebugLoc(); + GetExpandedInteger(N->getOperand(0), LHSL, LHSH); + GetExpandedInteger(N->getOperand(1), RHSL, RHSH); + SDVTList VTList = DAG.getVTList(LHSL.getValueType(), MVT::Flag); + SDValue LoOps[3] = { LHSL, RHSL, N->getOperand(2) }; + SDValue HiOps[3] = { LHSH, RHSH }; + + Lo = DAG.getNode(N->getOpcode(), dl, VTList, LoOps, 3); + HiOps[2] = Lo.getValue(1); + Hi = DAG.getNode(N->getOpcode(), dl, VTList, HiOps, 3); + + // Legalized the flag result - switch anything that used the old flag to + // use the new one. + ReplaceValueWith(SDValue(N, 1), Hi.getValue(1)); +} + +void DAGTypeLegalizer::ExpandIntRes_ANY_EXTEND(SDNode *N, + SDValue &Lo, SDValue &Hi) { + EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); + DebugLoc dl = N->getDebugLoc(); + SDValue Op = N->getOperand(0); + if (Op.getValueType().bitsLE(NVT)) { + // The low part is any extension of the input (which degenerates to a copy). + Lo = DAG.getNode(ISD::ANY_EXTEND, dl, NVT, Op); + Hi = DAG.getUNDEF(NVT); // The high part is undefined. + } else { + // For example, extension of an i48 to an i64. The operand type necessarily + // promotes to the result type, so will end up being expanded too. + assert(getTypeAction(Op.getValueType()) == PromoteInteger && + "Only know how to promote this result!"); + SDValue Res = GetPromotedInteger(Op); + assert(Res.getValueType() == N->getValueType(0) && + "Operand over promoted?"); + // Split the promoted operand. This will simplify when it is expanded. + SplitInteger(Res, Lo, Hi); + } +} + +void DAGTypeLegalizer::ExpandIntRes_AssertSext(SDNode *N, + SDValue &Lo, SDValue &Hi) { + DebugLoc dl = N->getDebugLoc(); + GetExpandedInteger(N->getOperand(0), Lo, Hi); + EVT NVT = Lo.getValueType(); + EVT EVT = cast(N->getOperand(1))->getVT(); + unsigned NVTBits = NVT.getSizeInBits(); + unsigned EVTBits = EVT.getSizeInBits(); + + if (NVTBits < EVTBits) { + Hi = DAG.getNode(ISD::AssertSext, dl, NVT, Hi, + DAG.getValueType(EVT::getIntegerVT(*DAG.getContext(), EVTBits - NVTBits))); + } else { + Lo = DAG.getNode(ISD::AssertSext, dl, NVT, Lo, DAG.getValueType(EVT)); + // The high part replicates the sign bit of Lo, make it explicit. + Hi = DAG.getNode(ISD::SRA, dl, NVT, Lo, + DAG.getConstant(NVTBits-1, TLI.getPointerTy())); + } +} + +void DAGTypeLegalizer::ExpandIntRes_AssertZext(SDNode *N, + SDValue &Lo, SDValue &Hi) { + DebugLoc dl = N->getDebugLoc(); + GetExpandedInteger(N->getOperand(0), Lo, Hi); + EVT NVT = Lo.getValueType(); + EVT EVT = cast(N->getOperand(1))->getVT(); + unsigned NVTBits = NVT.getSizeInBits(); + unsigned EVTBits = EVT.getSizeInBits(); + + if (NVTBits < EVTBits) { + Hi = DAG.getNode(ISD::AssertZext, dl, NVT, Hi, + DAG.getValueType(EVT::getIntegerVT(*DAG.getContext(), EVTBits - NVTBits))); + } else { + Lo = DAG.getNode(ISD::AssertZext, dl, NVT, Lo, DAG.getValueType(EVT)); + // The high part must be zero, make it explicit. + Hi = DAG.getConstant(0, NVT); + } +} + +void DAGTypeLegalizer::ExpandIntRes_BSWAP(SDNode *N, + SDValue &Lo, SDValue &Hi) { + DebugLoc dl = N->getDebugLoc(); + GetExpandedInteger(N->getOperand(0), Hi, Lo); // Note swapped operands. + Lo = DAG.getNode(ISD::BSWAP, dl, Lo.getValueType(), Lo); + Hi = DAG.getNode(ISD::BSWAP, dl, Hi.getValueType(), Hi); +} + +void DAGTypeLegalizer::ExpandIntRes_Constant(SDNode *N, + SDValue &Lo, SDValue &Hi) { + EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); + unsigned NBitWidth = NVT.getSizeInBits(); + const APInt &Cst = cast(N)->getAPIntValue(); + Lo = DAG.getConstant(APInt(Cst).trunc(NBitWidth), NVT); + Hi = DAG.getConstant(Cst.lshr(NBitWidth).trunc(NBitWidth), NVT); +} + +void DAGTypeLegalizer::ExpandIntRes_CTLZ(SDNode *N, + SDValue &Lo, SDValue &Hi) { + DebugLoc dl = N->getDebugLoc(); + // ctlz (HiLo) -> Hi != 0 ? ctlz(Hi) : (ctlz(Lo)+32) + GetExpandedInteger(N->getOperand(0), Lo, Hi); + EVT NVT = Lo.getValueType(); + + SDValue HiNotZero = DAG.getSetCC(dl, TLI.getSetCCResultType(NVT), Hi, + DAG.getConstant(0, NVT), ISD::SETNE); + + SDValue LoLZ = DAG.getNode(ISD::CTLZ, dl, NVT, Lo); + SDValue HiLZ = DAG.getNode(ISD::CTLZ, dl, NVT, Hi); + + Lo = DAG.getNode(ISD::SELECT, dl, NVT, HiNotZero, HiLZ, + DAG.getNode(ISD::ADD, dl, NVT, LoLZ, + DAG.getConstant(NVT.getSizeInBits(), NVT))); + Hi = DAG.getConstant(0, NVT); +} + +void DAGTypeLegalizer::ExpandIntRes_CTPOP(SDNode *N, + SDValue &Lo, SDValue &Hi) { + DebugLoc dl = N->getDebugLoc(); + // ctpop(HiLo) -> ctpop(Hi)+ctpop(Lo) + GetExpandedInteger(N->getOperand(0), Lo, Hi); + EVT NVT = Lo.getValueType(); + Lo = DAG.getNode(ISD::ADD, dl, NVT, DAG.getNode(ISD::CTPOP, dl, NVT, Lo), + DAG.getNode(ISD::CTPOP, dl, NVT, Hi)); + Hi = DAG.getConstant(0, NVT); +} + +void DAGTypeLegalizer::ExpandIntRes_CTTZ(SDNode *N, + SDValue &Lo, SDValue &Hi) { + DebugLoc dl = N->getDebugLoc(); + // cttz (HiLo) -> Lo != 0 ? cttz(Lo) : (cttz(Hi)+32) + GetExpandedInteger(N->getOperand(0), Lo, Hi); + EVT NVT = Lo.getValueType(); + + SDValue LoNotZero = DAG.getSetCC(dl, TLI.getSetCCResultType(NVT), Lo, + DAG.getConstant(0, NVT), ISD::SETNE); + + SDValue LoLZ = DAG.getNode(ISD::CTTZ, dl, NVT, Lo); + SDValue HiLZ = DAG.getNode(ISD::CTTZ, dl, NVT, Hi); + + Lo = DAG.getNode(ISD::SELECT, dl, NVT, LoNotZero, LoLZ, + DAG.getNode(ISD::ADD, dl, NVT, HiLZ, + DAG.getConstant(NVT.getSizeInBits(), NVT))); + Hi = DAG.getConstant(0, NVT); +} + +void DAGTypeLegalizer::ExpandIntRes_FP_TO_SINT(SDNode *N, SDValue &Lo, + SDValue &Hi) { + DebugLoc dl = N->getDebugLoc(); + EVT VT = N->getValueType(0); + SDValue Op = N->getOperand(0); + RTLIB::Libcall LC = RTLIB::getFPTOSINT(Op.getValueType(), VT); + assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unexpected fp-to-sint conversion!"); + SplitInteger(MakeLibCall(LC, VT, &Op, 1, true/*irrelevant*/, dl), Lo, Hi); +} + +void DAGTypeLegalizer::ExpandIntRes_FP_TO_UINT(SDNode *N, SDValue &Lo, + SDValue &Hi) { + DebugLoc dl = N->getDebugLoc(); + EVT VT = N->getValueType(0); + SDValue Op = N->getOperand(0); + RTLIB::Libcall LC = RTLIB::getFPTOUINT(Op.getValueType(), VT); + assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unexpected fp-to-uint conversion!"); + SplitInteger(MakeLibCall(LC, VT, &Op, 1, false/*irrelevant*/, dl), Lo, Hi); +} + +void DAGTypeLegalizer::ExpandIntRes_LOAD(LoadSDNode *N, + SDValue &Lo, SDValue &Hi) { + if (ISD::isNormalLoad(N)) { + ExpandRes_NormalLoad(N, Lo, Hi); + return; + } + + assert(ISD::isUNINDEXEDLoad(N) && "Indexed load during type legalization!"); + + EVT VT = N->getValueType(0); + EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT); + SDValue Ch = N->getChain(); + SDValue Ptr = N->getBasePtr(); + ISD::LoadExtType ExtType = N->getExtensionType(); + int SVOffset = N->getSrcValueOffset(); + unsigned Alignment = N->getAlignment(); + bool isVolatile = N->isVolatile(); + DebugLoc dl = N->getDebugLoc(); + + assert(NVT.isByteSized() && "Expanded type not byte sized!"); + + if (N->getMemoryVT().bitsLE(NVT)) { + EVT MemVT = N->getMemoryVT(); + + Lo = DAG.getExtLoad(ExtType, dl, NVT, Ch, Ptr, N->getSrcValue(), SVOffset, + MemVT, isVolatile, Alignment); + + // Remember the chain. + Ch = Lo.getValue(1); + + if (ExtType == ISD::SEXTLOAD) { + // The high part is obtained by SRA'ing all but one of the bits of the + // lo part. + unsigned LoSize = Lo.getValueType().getSizeInBits(); + Hi = DAG.getNode(ISD::SRA, dl, NVT, Lo, + DAG.getConstant(LoSize-1, TLI.getPointerTy())); + } else if (ExtType == ISD::ZEXTLOAD) { + // The high part is just a zero. + Hi = DAG.getConstant(0, NVT); + } else { + assert(ExtType == ISD::EXTLOAD && "Unknown extload!"); + // The high part is undefined. + Hi = DAG.getUNDEF(NVT); + } + } else if (TLI.isLittleEndian()) { + // Little-endian - low bits are at low addresses. + Lo = DAG.getLoad(NVT, dl, Ch, Ptr, N->getSrcValue(), SVOffset, + isVolatile, Alignment); + + unsigned ExcessBits = + N->getMemoryVT().getSizeInBits() - NVT.getSizeInBits(); + EVT NEVT = EVT::getIntegerVT(*DAG.getContext(), ExcessBits); + + // Increment the pointer to the other half. + unsigned IncrementSize = NVT.getSizeInBits()/8; + Ptr = DAG.getNode(ISD::ADD, dl, Ptr.getValueType(), Ptr, + DAG.getIntPtrConstant(IncrementSize)); + Hi = DAG.getExtLoad(ExtType, dl, NVT, Ch, Ptr, N->getSrcValue(), + SVOffset+IncrementSize, NEVT, + isVolatile, MinAlign(Alignment, IncrementSize)); + + // Build a factor node to remember that this load is independent of the + // other one. + Ch = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Lo.getValue(1), + Hi.getValue(1)); + } else { + // Big-endian - high bits are at low addresses. Favor aligned loads at + // the cost of some bit-fiddling. + EVT MemVT = N->getMemoryVT(); + unsigned EBytes = MemVT.getStoreSize(); + unsigned IncrementSize = NVT.getSizeInBits()/8; + unsigned ExcessBits = (EBytes - IncrementSize)*8; + + // Load both the high bits and maybe some of the low bits. + Hi = DAG.getExtLoad(ExtType, dl, NVT, Ch, Ptr, N->getSrcValue(), SVOffset, + EVT::getIntegerVT(*DAG.getContext(), + MemVT.getSizeInBits() - ExcessBits), + isVolatile, Alignment); + + // Increment the pointer to the other half. + Ptr = DAG.getNode(ISD::ADD, dl, Ptr.getValueType(), Ptr, + DAG.getIntPtrConstant(IncrementSize)); + // Load the rest of the low bits. + Lo = DAG.getExtLoad(ISD::ZEXTLOAD, dl, NVT, Ch, Ptr, N->getSrcValue(), + SVOffset+IncrementSize, + EVT::getIntegerVT(*DAG.getContext(), ExcessBits), + isVolatile, MinAlign(Alignment, IncrementSize)); + + // Build a factor node to remember that this load is independent of the + // other one. + Ch = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Lo.getValue(1), + Hi.getValue(1)); + + if (ExcessBits < NVT.getSizeInBits()) { + // Transfer low bits from the bottom of Hi to the top of Lo. + Lo = DAG.getNode(ISD::OR, dl, NVT, Lo, + DAG.getNode(ISD::SHL, dl, NVT, Hi, + DAG.getConstant(ExcessBits, + TLI.getPointerTy()))); + // Move high bits to the right position in Hi. + Hi = DAG.getNode(ExtType == ISD::SEXTLOAD ? ISD::SRA : ISD::SRL, dl, + NVT, Hi, + DAG.getConstant(NVT.getSizeInBits() - ExcessBits, + TLI.getPointerTy())); + } + } + + // Legalized the chain result - switch anything that used the old chain to + // use the new one. + ReplaceValueWith(SDValue(N, 1), Ch); +} + +void DAGTypeLegalizer::ExpandIntRes_Logical(SDNode *N, + SDValue &Lo, SDValue &Hi) { + DebugLoc dl = N->getDebugLoc(); + SDValue LL, LH, RL, RH; + GetExpandedInteger(N->getOperand(0), LL, LH); + GetExpandedInteger(N->getOperand(1), RL, RH); + Lo = DAG.getNode(N->getOpcode(), dl, LL.getValueType(), LL, RL); + Hi = DAG.getNode(N->getOpcode(), dl, LL.getValueType(), LH, RH); +} + +void DAGTypeLegalizer::ExpandIntRes_MUL(SDNode *N, + SDValue &Lo, SDValue &Hi) { + EVT VT = N->getValueType(0); + EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT); + DebugLoc dl = N->getDebugLoc(); + + bool HasMULHS = TLI.isOperationLegalOrCustom(ISD::MULHS, NVT); + bool HasMULHU = TLI.isOperationLegalOrCustom(ISD::MULHU, NVT); + bool HasSMUL_LOHI = TLI.isOperationLegalOrCustom(ISD::SMUL_LOHI, NVT); + bool HasUMUL_LOHI = TLI.isOperationLegalOrCustom(ISD::UMUL_LOHI, NVT); + if (HasMULHU || HasMULHS || HasUMUL_LOHI || HasSMUL_LOHI) { + SDValue LL, LH, RL, RH; + GetExpandedInteger(N->getOperand(0), LL, LH); + GetExpandedInteger(N->getOperand(1), RL, RH); + unsigned OuterBitSize = VT.getSizeInBits(); + unsigned InnerBitSize = NVT.getSizeInBits(); + unsigned LHSSB = DAG.ComputeNumSignBits(N->getOperand(0)); + unsigned RHSSB = DAG.ComputeNumSignBits(N->getOperand(1)); + + APInt HighMask = APInt::getHighBitsSet(OuterBitSize, InnerBitSize); + if (DAG.MaskedValueIsZero(N->getOperand(0), HighMask) && + DAG.MaskedValueIsZero(N->getOperand(1), HighMask)) { + // The inputs are both zero-extended. + if (HasUMUL_LOHI) { + // We can emit a umul_lohi. + Lo = DAG.getNode(ISD::UMUL_LOHI, dl, DAG.getVTList(NVT, NVT), LL, RL); + Hi = SDValue(Lo.getNode(), 1); + return; + } + if (HasMULHU) { + // We can emit a mulhu+mul. + Lo = DAG.getNode(ISD::MUL, dl, NVT, LL, RL); + Hi = DAG.getNode(ISD::MULHU, dl, NVT, LL, RL); + return; + } + } + if (LHSSB > InnerBitSize && RHSSB > InnerBitSize) { + // The input values are both sign-extended. + if (HasSMUL_LOHI) { + // We can emit a smul_lohi. + Lo = DAG.getNode(ISD::SMUL_LOHI, dl, DAG.getVTList(NVT, NVT), LL, RL); + Hi = SDValue(Lo.getNode(), 1); + return; + } + if (HasMULHS) { + // We can emit a mulhs+mul. + Lo = DAG.getNode(ISD::MUL, dl, NVT, LL, RL); + Hi = DAG.getNode(ISD::MULHS, dl, NVT, LL, RL); + return; + } + } + if (HasUMUL_LOHI) { + // Lo,Hi = umul LHS, RHS. + SDValue UMulLOHI = DAG.getNode(ISD::UMUL_LOHI, dl, + DAG.getVTList(NVT, NVT), LL, RL); + Lo = UMulLOHI; + Hi = UMulLOHI.getValue(1); + RH = DAG.getNode(ISD::MUL, dl, NVT, LL, RH); + LH = DAG.getNode(ISD::MUL, dl, NVT, LH, RL); + Hi = DAG.getNode(ISD::ADD, dl, NVT, Hi, RH); + Hi = DAG.getNode(ISD::ADD, dl, NVT, Hi, LH); + return; + } + if (HasMULHU) { + Lo = DAG.getNode(ISD::MUL, dl, NVT, LL, RL); + Hi = DAG.getNode(ISD::MULHU, dl, NVT, LL, RL); + RH = DAG.getNode(ISD::MUL, dl, NVT, LL, RH); + LH = DAG.getNode(ISD::MUL, dl, NVT, LH, RL); + Hi = DAG.getNode(ISD::ADD, dl, NVT, Hi, RH); + Hi = DAG.getNode(ISD::ADD, dl, NVT, Hi, LH); + return; + } + } + + // If nothing else, we can make a libcall. + RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL; + if (VT == MVT::i16) + LC = RTLIB::MUL_I16; + else if (VT == MVT::i32) + LC = RTLIB::MUL_I32; + else if (VT == MVT::i64) + LC = RTLIB::MUL_I64; + else if (VT == MVT::i128) + LC = RTLIB::MUL_I128; + assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unsupported MUL!"); + + SDValue Ops[2] = { N->getOperand(0), N->getOperand(1) }; + SplitInteger(MakeLibCall(LC, VT, Ops, 2, true/*irrelevant*/, dl), Lo, Hi); +} + +void DAGTypeLegalizer::ExpandIntRes_SDIV(SDNode *N, + SDValue &Lo, SDValue &Hi) { + EVT VT = N->getValueType(0); + DebugLoc dl = N->getDebugLoc(); + + RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL; + if (VT == MVT::i16) + LC = RTLIB::SDIV_I16; + else if (VT == MVT::i32) + LC = RTLIB::SDIV_I32; + else if (VT == MVT::i64) + LC = RTLIB::SDIV_I64; + else if (VT == MVT::i128) + LC = RTLIB::SDIV_I128; + assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unsupported SDIV!"); + + SDValue Ops[2] = { N->getOperand(0), N->getOperand(1) }; + SplitInteger(MakeLibCall(LC, VT, Ops, 2, true, dl), Lo, Hi); +} + +void DAGTypeLegalizer::ExpandIntRes_Shift(SDNode *N, + SDValue &Lo, SDValue &Hi) { + EVT VT = N->getValueType(0); + DebugLoc dl = N->getDebugLoc(); + + // If we can emit an efficient shift operation, do so now. Check to see if + // the RHS is a constant. + if (ConstantSDNode *CN = dyn_cast(N->getOperand(1))) + return ExpandShiftByConstant(N, CN->getZExtValue(), Lo, Hi); + + // If we can determine that the high bit of the shift is zero or one, even if + // the low bits are variable, emit this shift in an optimized form. + if (ExpandShiftWithKnownAmountBit(N, Lo, Hi)) + return; + + // If this target supports shift_PARTS, use it. First, map to the _PARTS opc. + unsigned PartsOpc; + if (N->getOpcode() == ISD::SHL) { + PartsOpc = ISD::SHL_PARTS; + } else if (N->getOpcode() == ISD::SRL) { + PartsOpc = ISD::SRL_PARTS; + } else { + assert(N->getOpcode() == ISD::SRA && "Unknown shift!"); + PartsOpc = ISD::SRA_PARTS; + } + + // Next check to see if the target supports this SHL_PARTS operation or if it + // will custom expand it. + EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT); + TargetLowering::LegalizeAction Action = TLI.getOperationAction(PartsOpc, NVT); + if ((Action == TargetLowering::Legal && TLI.isTypeLegal(NVT)) || + Action == TargetLowering::Custom) { + // Expand the subcomponents. + SDValue LHSL, LHSH; + GetExpandedInteger(N->getOperand(0), LHSL, LHSH); + + SDValue Ops[] = { LHSL, LHSH, N->getOperand(1) }; + EVT VT = LHSL.getValueType(); + Lo = DAG.getNode(PartsOpc, dl, DAG.getVTList(VT, VT), Ops, 3); + Hi = Lo.getValue(1); + return; + } + + // Otherwise, emit a libcall. + RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL; + bool isSigned; + if (N->getOpcode() == ISD::SHL) { + isSigned = false; /*sign irrelevant*/ + if (VT == MVT::i16) + LC = RTLIB::SHL_I16; + else if (VT == MVT::i32) + LC = RTLIB::SHL_I32; + else if (VT == MVT::i64) + LC = RTLIB::SHL_I64; + else if (VT == MVT::i128) + LC = RTLIB::SHL_I128; + } else if (N->getOpcode() == ISD::SRL) { + isSigned = false; + if (VT == MVT::i16) + LC = RTLIB::SRL_I16; + else if (VT == MVT::i32) + LC = RTLIB::SRL_I32; + else if (VT == MVT::i64) + LC = RTLIB::SRL_I64; + else if (VT == MVT::i128) + LC = RTLIB::SRL_I128; + } else { + assert(N->getOpcode() == ISD::SRA && "Unknown shift!"); + isSigned = true; + if (VT == MVT::i16) + LC = RTLIB::SRA_I16; + else if (VT == MVT::i32) + LC = RTLIB::SRA_I32; + else if (VT == MVT::i64) + LC = RTLIB::SRA_I64; + else if (VT == MVT::i128) + LC = RTLIB::SRA_I128; + } + + if (LC != RTLIB::UNKNOWN_LIBCALL && TLI.getLibcallName(LC)) { + SDValue Ops[2] = { N->getOperand(0), N->getOperand(1) }; + SplitInteger(MakeLibCall(LC, VT, Ops, 2, isSigned, dl), Lo, Hi); + return; + } + + if (!ExpandShiftWithUnknownAmountBit(N, Lo, Hi)) + llvm_unreachable("Unsupported shift!"); +} + +void DAGTypeLegalizer::ExpandIntRes_SIGN_EXTEND(SDNode *N, + SDValue &Lo, SDValue &Hi) { + EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); + DebugLoc dl = N->getDebugLoc(); + SDValue Op = N->getOperand(0); + if (Op.getValueType().bitsLE(NVT)) { + // The low part is sign extension of the input (degenerates to a copy). + Lo = DAG.getNode(ISD::SIGN_EXTEND, dl, NVT, N->getOperand(0)); + // The high part is obtained by SRA'ing all but one of the bits of low part. + unsigned LoSize = NVT.getSizeInBits(); + Hi = DAG.getNode(ISD::SRA, dl, NVT, Lo, + DAG.getConstant(LoSize-1, TLI.getPointerTy())); + } else { + // For example, extension of an i48 to an i64. The operand type necessarily + // promotes to the result type, so will end up being expanded too. + assert(getTypeAction(Op.getValueType()) == PromoteInteger && + "Only know how to promote this result!"); + SDValue Res = GetPromotedInteger(Op); + assert(Res.getValueType() == N->getValueType(0) && + "Operand over promoted?"); + // Split the promoted operand. This will simplify when it is expanded. + SplitInteger(Res, Lo, Hi); + unsigned ExcessBits = + Op.getValueType().getSizeInBits() - NVT.getSizeInBits(); + Hi = DAG.getNode(ISD::SIGN_EXTEND_INREG, dl, Hi.getValueType(), Hi, + DAG.getValueType(EVT::getIntegerVT(*DAG.getContext(), ExcessBits))); + } +} + +void DAGTypeLegalizer:: +ExpandIntRes_SIGN_EXTEND_INREG(SDNode *N, SDValue &Lo, SDValue &Hi) { + DebugLoc dl = N->getDebugLoc(); + GetExpandedInteger(N->getOperand(0), Lo, Hi); + EVT EVT = cast(N->getOperand(1))->getVT(); + + if (EVT.bitsLE(Lo.getValueType())) { + // sext_inreg the low part if needed. + Lo = DAG.getNode(ISD::SIGN_EXTEND_INREG, dl, Lo.getValueType(), Lo, + N->getOperand(1)); + + // The high part gets the sign extension from the lo-part. This handles + // things like sextinreg V:i64 from i8. + Hi = DAG.getNode(ISD::SRA, dl, Hi.getValueType(), Lo, + DAG.getConstant(Hi.getValueType().getSizeInBits()-1, + TLI.getPointerTy())); + } else { + // For example, extension of an i48 to an i64. Leave the low part alone, + // sext_inreg the high part. + unsigned ExcessBits = + EVT.getSizeInBits() - Lo.getValueType().getSizeInBits(); + Hi = DAG.getNode(ISD::SIGN_EXTEND_INREG, dl, Hi.getValueType(), Hi, + DAG.getValueType(EVT::getIntegerVT(*DAG.getContext(), ExcessBits))); + } +} + +void DAGTypeLegalizer::ExpandIntRes_SREM(SDNode *N, + SDValue &Lo, SDValue &Hi) { + EVT VT = N->getValueType(0); + DebugLoc dl = N->getDebugLoc(); + + RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL; + if (VT == MVT::i16) + LC = RTLIB::SREM_I16; + else if (VT == MVT::i32) + LC = RTLIB::SREM_I32; + else if (VT == MVT::i64) + LC = RTLIB::SREM_I64; + else if (VT == MVT::i128) + LC = RTLIB::SREM_I128; + assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unsupported SREM!"); + + SDValue Ops[2] = { N->getOperand(0), N->getOperand(1) }; + SplitInteger(MakeLibCall(LC, VT, Ops, 2, true, dl), Lo, Hi); +} + +void DAGTypeLegalizer::ExpandIntRes_TRUNCATE(SDNode *N, + SDValue &Lo, SDValue &Hi) { + EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); + DebugLoc dl = N->getDebugLoc(); + Lo = DAG.getNode(ISD::TRUNCATE, dl, NVT, N->getOperand(0)); + Hi = DAG.getNode(ISD::SRL, dl, + N->getOperand(0).getValueType(), N->getOperand(0), + DAG.getConstant(NVT.getSizeInBits(), TLI.getPointerTy())); + Hi = DAG.getNode(ISD::TRUNCATE, dl, NVT, Hi); +} + +void DAGTypeLegalizer::ExpandIntRes_UDIV(SDNode *N, + SDValue &Lo, SDValue &Hi) { + EVT VT = N->getValueType(0); + DebugLoc dl = N->getDebugLoc(); + + RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL; + if (VT == MVT::i16) + LC = RTLIB::UDIV_I16; + else if (VT == MVT::i32) + LC = RTLIB::UDIV_I32; + else if (VT == MVT::i64) + LC = RTLIB::UDIV_I64; + else if (VT == MVT::i128) + LC = RTLIB::UDIV_I128; + assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unsupported UDIV!"); + + SDValue Ops[2] = { N->getOperand(0), N->getOperand(1) }; + SplitInteger(MakeLibCall(LC, VT, Ops, 2, false, dl), Lo, Hi); +} + +void DAGTypeLegalizer::ExpandIntRes_UREM(SDNode *N, + SDValue &Lo, SDValue &Hi) { + EVT VT = N->getValueType(0); + DebugLoc dl = N->getDebugLoc(); + + RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL; + if (VT == MVT::i16) + LC = RTLIB::UREM_I16; + else if (VT == MVT::i32) + LC = RTLIB::UREM_I32; + else if (VT == MVT::i64) + LC = RTLIB::UREM_I64; + else if (VT == MVT::i128) + LC = RTLIB::UREM_I128; + assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unsupported UREM!"); + + SDValue Ops[2] = { N->getOperand(0), N->getOperand(1) }; + SplitInteger(MakeLibCall(LC, VT, Ops, 2, false, dl), Lo, Hi); +} + +void DAGTypeLegalizer::ExpandIntRes_ZERO_EXTEND(SDNode *N, + SDValue &Lo, SDValue &Hi) { + EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); + DebugLoc dl = N->getDebugLoc(); + SDValue Op = N->getOperand(0); + if (Op.getValueType().bitsLE(NVT)) { + // The low part is zero extension of the input (degenerates to a copy). + Lo = DAG.getNode(ISD::ZERO_EXTEND, dl, NVT, N->getOperand(0)); + Hi = DAG.getConstant(0, NVT); // The high part is just a zero. + } else { + // For example, extension of an i48 to an i64. The operand type necessarily + // promotes to the result type, so will end up being expanded too. + assert(getTypeAction(Op.getValueType()) == PromoteInteger && + "Only know how to promote this result!"); + SDValue Res = GetPromotedInteger(Op); + assert(Res.getValueType() == N->getValueType(0) && + "Operand over promoted?"); + // Split the promoted operand. This will simplify when it is expanded. + SplitInteger(Res, Lo, Hi); + unsigned ExcessBits = + Op.getValueType().getSizeInBits() - NVT.getSizeInBits(); + Hi = DAG.getZeroExtendInReg(Hi, dl, EVT::getIntegerVT(*DAG.getContext(), ExcessBits)); + } +} + + +//===----------------------------------------------------------------------===// +// Integer Operand Expansion +//===----------------------------------------------------------------------===// + +/// ExpandIntegerOperand - This method is called when the specified operand of +/// the specified node is found to need expansion. At this point, all of the +/// result types of the node are known to be legal, but other operands of the +/// node may need promotion or expansion as well as the specified one. +bool DAGTypeLegalizer::ExpandIntegerOperand(SDNode *N, unsigned OpNo) { + DEBUG(errs() << "Expand integer operand: "; N->dump(&DAG); errs() << "\n"); + SDValue Res = SDValue(); + + if (CustomLowerNode(N, N->getOperand(OpNo).getValueType(), false)) + return false; + + switch (N->getOpcode()) { + default: + #ifndef NDEBUG + errs() << "ExpandIntegerOperand Op #" << OpNo << ": "; + N->dump(&DAG); errs() << "\n"; + #endif + llvm_unreachable("Do not know how to expand this operator's operand!"); + + case ISD::BIT_CONVERT: Res = ExpandOp_BIT_CONVERT(N); break; + case ISD::BR_CC: Res = ExpandIntOp_BR_CC(N); break; + case ISD::BUILD_VECTOR: Res = ExpandOp_BUILD_VECTOR(N); break; + case ISD::EXTRACT_ELEMENT: Res = ExpandOp_EXTRACT_ELEMENT(N); break; + case ISD::INSERT_VECTOR_ELT: Res = ExpandOp_INSERT_VECTOR_ELT(N); break; + case ISD::SCALAR_TO_VECTOR: Res = ExpandOp_SCALAR_TO_VECTOR(N); break; + case ISD::SELECT_CC: Res = ExpandIntOp_SELECT_CC(N); break; + case ISD::SETCC: Res = ExpandIntOp_SETCC(N); break; + case ISD::SINT_TO_FP: Res = ExpandIntOp_SINT_TO_FP(N); break; + case ISD::STORE: Res = ExpandIntOp_STORE(cast(N), OpNo); break; + case ISD::TRUNCATE: Res = ExpandIntOp_TRUNCATE(N); break; + case ISD::UINT_TO_FP: Res = ExpandIntOp_UINT_TO_FP(N); break; + + case ISD::SHL: + case ISD::SRA: + case ISD::SRL: + case ISD::ROTL: + case ISD::ROTR: Res = ExpandIntOp_Shift(N); break; + } + + // If the result is null, the sub-method took care of registering results etc. + if (!Res.getNode()) return false; + + // If the result is N, the sub-method updated N in place. Tell the legalizer + // core about this. + if (Res.getNode() == N) + return true; + + assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 1 && + "Invalid operand expansion"); + + ReplaceValueWith(SDValue(N, 0), Res); + return false; +} + +/// IntegerExpandSetCCOperands - Expand the operands of a comparison. This code +/// is shared among BR_CC, SELECT_CC, and SETCC handlers. +void DAGTypeLegalizer::IntegerExpandSetCCOperands(SDValue &NewLHS, + SDValue &NewRHS, + ISD::CondCode &CCCode, + DebugLoc dl) { + SDValue LHSLo, LHSHi, RHSLo, RHSHi; + GetExpandedInteger(NewLHS, LHSLo, LHSHi); + GetExpandedInteger(NewRHS, RHSLo, RHSHi); + + EVT VT = NewLHS.getValueType(); + + if (CCCode == ISD::SETEQ || CCCode == ISD::SETNE) { + if (RHSLo == RHSHi) { + if (ConstantSDNode *RHSCST = dyn_cast(RHSLo)) { + if (RHSCST->isAllOnesValue()) { + // Equality comparison to -1. + NewLHS = DAG.getNode(ISD::AND, dl, + LHSLo.getValueType(), LHSLo, LHSHi); + NewRHS = RHSLo; + return; + } + } + } + + NewLHS = DAG.getNode(ISD::XOR, dl, LHSLo.getValueType(), LHSLo, RHSLo); + NewRHS = DAG.getNode(ISD::XOR, dl, LHSLo.getValueType(), LHSHi, RHSHi); + NewLHS = DAG.getNode(ISD::OR, dl, NewLHS.getValueType(), NewLHS, NewRHS); + NewRHS = DAG.getConstant(0, NewLHS.getValueType()); + return; + } + + // If this is a comparison of the sign bit, just look at the top part. + // X > -1, x < 0 + if (ConstantSDNode *CST = dyn_cast(NewRHS)) + if ((CCCode == ISD::SETLT && CST->isNullValue()) || // X < 0 + (CCCode == ISD::SETGT && CST->isAllOnesValue())) { // X > -1 + NewLHS = LHSHi; + NewRHS = RHSHi; + return; + } + + // FIXME: This generated code sucks. + ISD::CondCode LowCC; + switch (CCCode) { + default: llvm_unreachable("Unknown integer setcc!"); + case ISD::SETLT: + case ISD::SETULT: LowCC = ISD::SETULT; break; + case ISD::SETGT: + case ISD::SETUGT: LowCC = ISD::SETUGT; break; + case ISD::SETLE: + case ISD::SETULE: LowCC = ISD::SETULE; break; + case ISD::SETGE: + case ISD::SETUGE: LowCC = ISD::SETUGE; break; + } + + // Tmp1 = lo(op1) < lo(op2) // Always unsigned comparison + // Tmp2 = hi(op1) < hi(op2) // Signedness depends on operands + // dest = hi(op1) == hi(op2) ? Tmp1 : Tmp2; + + // NOTE: on targets without efficient SELECT of bools, we can always use + // this identity: (B1 ? B2 : B3) --> (B1 & B2)|(!B1&B3) + TargetLowering::DAGCombinerInfo DagCombineInfo(DAG, false, true, true, NULL); + SDValue Tmp1, Tmp2; + Tmp1 = TLI.SimplifySetCC(TLI.getSetCCResultType(LHSLo.getValueType()), + LHSLo, RHSLo, LowCC, false, DagCombineInfo, dl); + if (!Tmp1.getNode()) + Tmp1 = DAG.getSetCC(dl, TLI.getSetCCResultType(LHSLo.getValueType()), + LHSLo, RHSLo, LowCC); + Tmp2 = TLI.SimplifySetCC(TLI.getSetCCResultType(LHSHi.getValueType()), + LHSHi, RHSHi, CCCode, false, DagCombineInfo, dl); + if (!Tmp2.getNode()) + Tmp2 = DAG.getNode(ISD::SETCC, dl, + TLI.getSetCCResultType(LHSHi.getValueType()), + LHSHi, RHSHi, DAG.getCondCode(CCCode)); + + ConstantSDNode *Tmp1C = dyn_cast(Tmp1.getNode()); + ConstantSDNode *Tmp2C = dyn_cast(Tmp2.getNode()); + if ((Tmp1C && Tmp1C->isNullValue()) || + (Tmp2C && Tmp2C->isNullValue() && + (CCCode == ISD::SETLE || CCCode == ISD::SETGE || + CCCode == ISD::SETUGE || CCCode == ISD::SETULE)) || + (Tmp2C && Tmp2C->getAPIntValue() == 1 && + (CCCode == ISD::SETLT || CCCode == ISD::SETGT || + CCCode == ISD::SETUGT || CCCode == ISD::SETULT))) { + // low part is known false, returns high part. + // For LE / GE, if high part is known false, ignore the low part. + // For LT / GT, if high part is known true, ignore the low part. + NewLHS = Tmp2; + NewRHS = SDValue(); + return; + } + + NewLHS = TLI.SimplifySetCC(TLI.getSetCCResultType(LHSHi.getValueType()), + LHSHi, RHSHi, ISD::SETEQ, false, + DagCombineInfo, dl); + if (!NewLHS.getNode()) + NewLHS = DAG.getSetCC(dl, TLI.getSetCCResultType(LHSHi.getValueType()), + LHSHi, RHSHi, ISD::SETEQ); + NewLHS = DAG.getNode(ISD::SELECT, dl, Tmp1.getValueType(), + NewLHS, Tmp1, Tmp2); + NewRHS = SDValue(); +} + +SDValue DAGTypeLegalizer::ExpandIntOp_BR_CC(SDNode *N) { + SDValue NewLHS = N->getOperand(2), NewRHS = N->getOperand(3); + ISD::CondCode CCCode = cast(N->getOperand(1))->get(); + IntegerExpandSetCCOperands(NewLHS, NewRHS, CCCode, N->getDebugLoc()); + + // If ExpandSetCCOperands returned a scalar, we need to compare the result + // against zero to select between true and false values. + if (NewRHS.getNode() == 0) { + NewRHS = DAG.getConstant(0, NewLHS.getValueType()); + CCCode = ISD::SETNE; + } + + // Update N to have the operands specified. + return DAG.UpdateNodeOperands(SDValue(N, 0), N->getOperand(0), + DAG.getCondCode(CCCode), NewLHS, NewRHS, + N->getOperand(4)); +} + +SDValue DAGTypeLegalizer::ExpandIntOp_SELECT_CC(SDNode *N) { + SDValue NewLHS = N->getOperand(0), NewRHS = N->getOperand(1); + ISD::CondCode CCCode = cast(N->getOperand(4))->get(); + IntegerExpandSetCCOperands(NewLHS, NewRHS, CCCode, N->getDebugLoc()); + + // If ExpandSetCCOperands returned a scalar, we need to compare the result + // against zero to select between true and false values. + if (NewRHS.getNode() == 0) { + NewRHS = DAG.getConstant(0, NewLHS.getValueType()); + CCCode = ISD::SETNE; + } + + // Update N to have the operands specified. + return DAG.UpdateNodeOperands(SDValue(N, 0), NewLHS, NewRHS, + N->getOperand(2), N->getOperand(3), + DAG.getCondCode(CCCode)); +} + +SDValue DAGTypeLegalizer::ExpandIntOp_SETCC(SDNode *N) { + SDValue NewLHS = N->getOperand(0), NewRHS = N->getOperand(1); + ISD::CondCode CCCode = cast(N->getOperand(2))->get(); + IntegerExpandSetCCOperands(NewLHS, NewRHS, CCCode, N->getDebugLoc()); + + // If ExpandSetCCOperands returned a scalar, use it. + if (NewRHS.getNode() == 0) { + assert(NewLHS.getValueType() == N->getValueType(0) && + "Unexpected setcc expansion!"); + return NewLHS; + } + + // Otherwise, update N to have the operands specified. + return DAG.UpdateNodeOperands(SDValue(N, 0), NewLHS, NewRHS, + DAG.getCondCode(CCCode)); +} + +SDValue DAGTypeLegalizer::ExpandIntOp_Shift(SDNode *N) { + // The value being shifted is legal, but the shift amount is too big. + // It follows that either the result of the shift is undefined, or the + // upper half of the shift amount is zero. Just use the lower half. + SDValue Lo, Hi; + GetExpandedInteger(N->getOperand(1), Lo, Hi); + return DAG.UpdateNodeOperands(SDValue(N, 0), N->getOperand(0), Lo); +} + +SDValue DAGTypeLegalizer::ExpandIntOp_SINT_TO_FP(SDNode *N) { + SDValue Op = N->getOperand(0); + EVT DstVT = N->getValueType(0); + RTLIB::Libcall LC = RTLIB::getSINTTOFP(Op.getValueType(), DstVT); + assert(LC != RTLIB::UNKNOWN_LIBCALL && + "Don't know how to expand this SINT_TO_FP!"); + return MakeLibCall(LC, DstVT, &Op, 1, true, N->getDebugLoc()); +} + +SDValue DAGTypeLegalizer::ExpandIntOp_STORE(StoreSDNode *N, unsigned OpNo) { + if (ISD::isNormalStore(N)) + return ExpandOp_NormalStore(N, OpNo); + + assert(ISD::isUNINDEXEDStore(N) && "Indexed store during type legalization!"); + assert(OpNo == 1 && "Can only expand the stored value so far"); + + EVT VT = N->getOperand(1).getValueType(); + EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT); + SDValue Ch = N->getChain(); + SDValue Ptr = N->getBasePtr(); + int SVOffset = N->getSrcValueOffset(); + unsigned Alignment = N->getAlignment(); + bool isVolatile = N->isVolatile(); + DebugLoc dl = N->getDebugLoc(); + SDValue Lo, Hi; + + assert(NVT.isByteSized() && "Expanded type not byte sized!"); + + if (N->getMemoryVT().bitsLE(NVT)) { + GetExpandedInteger(N->getValue(), Lo, Hi); + return DAG.getTruncStore(Ch, dl, Lo, Ptr, N->getSrcValue(), SVOffset, + N->getMemoryVT(), isVolatile, Alignment); + } else if (TLI.isLittleEndian()) { + // Little-endian - low bits are at low addresses. + GetExpandedInteger(N->getValue(), Lo, Hi); + + Lo = DAG.getStore(Ch, dl, Lo, Ptr, N->getSrcValue(), SVOffset, + isVolatile, Alignment); + + unsigned ExcessBits = + N->getMemoryVT().getSizeInBits() - NVT.getSizeInBits(); + EVT NEVT = EVT::getIntegerVT(*DAG.getContext(), ExcessBits); + + // Increment the pointer to the other half. + unsigned IncrementSize = NVT.getSizeInBits()/8; + Ptr = DAG.getNode(ISD::ADD, dl, Ptr.getValueType(), Ptr, + DAG.getIntPtrConstant(IncrementSize)); + Hi = DAG.getTruncStore(Ch, dl, Hi, Ptr, N->getSrcValue(), + SVOffset+IncrementSize, NEVT, + isVolatile, MinAlign(Alignment, IncrementSize)); + return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Lo, Hi); + } else { + // Big-endian - high bits are at low addresses. Favor aligned stores at + // the cost of some bit-fiddling. + GetExpandedInteger(N->getValue(), Lo, Hi); + + EVT ExtVT = N->getMemoryVT(); + unsigned EBytes = ExtVT.getStoreSize(); + unsigned IncrementSize = NVT.getSizeInBits()/8; + unsigned ExcessBits = (EBytes - IncrementSize)*8; + EVT HiVT = EVT::getIntegerVT(*DAG.getContext(), ExtVT.getSizeInBits() - ExcessBits); + + if (ExcessBits < NVT.getSizeInBits()) { + // Transfer high bits from the top of Lo to the bottom of Hi. + Hi = DAG.getNode(ISD::SHL, dl, NVT, Hi, + DAG.getConstant(NVT.getSizeInBits() - ExcessBits, + TLI.getPointerTy())); + Hi = DAG.getNode(ISD::OR, dl, NVT, Hi, + DAG.getNode(ISD::SRL, dl, NVT, Lo, + DAG.getConstant(ExcessBits, + TLI.getPointerTy()))); + } + + // Store both the high bits and maybe some of the low bits. + Hi = DAG.getTruncStore(Ch, dl, Hi, Ptr, N->getSrcValue(), + SVOffset, HiVT, isVolatile, Alignment); + + // Increment the pointer to the other half. + Ptr = DAG.getNode(ISD::ADD, dl, Ptr.getValueType(), Ptr, + DAG.getIntPtrConstant(IncrementSize)); + // Store the lowest ExcessBits bits in the second half. + Lo = DAG.getTruncStore(Ch, dl, Lo, Ptr, N->getSrcValue(), + SVOffset+IncrementSize, + EVT::getIntegerVT(*DAG.getContext(), ExcessBits), + isVolatile, MinAlign(Alignment, IncrementSize)); + return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Lo, Hi); + } +} + +SDValue DAGTypeLegalizer::ExpandIntOp_TRUNCATE(SDNode *N) { + SDValue InL, InH; + GetExpandedInteger(N->getOperand(0), InL, InH); + // Just truncate the low part of the source. + return DAG.getNode(ISD::TRUNCATE, N->getDebugLoc(), N->getValueType(0), InL); +} + +SDValue DAGTypeLegalizer::ExpandIntOp_UINT_TO_FP(SDNode *N) { + SDValue Op = N->getOperand(0); + EVT SrcVT = Op.getValueType(); + EVT DstVT = N->getValueType(0); + DebugLoc dl = N->getDebugLoc(); + + if (TLI.getOperationAction(ISD::SINT_TO_FP, SrcVT) == TargetLowering::Custom){ + // Do a signed conversion then adjust the result. + SDValue SignedConv = DAG.getNode(ISD::SINT_TO_FP, dl, DstVT, Op); + SignedConv = TLI.LowerOperation(SignedConv, DAG); + + // The result of the signed conversion needs adjusting if the 'sign bit' of + // the incoming integer was set. To handle this, we dynamically test to see + // if it is set, and, if so, add a fudge factor. + + const uint64_t F32TwoE32 = 0x4F800000ULL; + const uint64_t F32TwoE64 = 0x5F800000ULL; + const uint64_t F32TwoE128 = 0x7F800000ULL; + + APInt FF(32, 0); + if (SrcVT == MVT::i32) + FF = APInt(32, F32TwoE32); + else if (SrcVT == MVT::i64) + FF = APInt(32, F32TwoE64); + else if (SrcVT == MVT::i128) + FF = APInt(32, F32TwoE128); + else + assert(false && "Unsupported UINT_TO_FP!"); + + // Check whether the sign bit is set. + SDValue Lo, Hi; + GetExpandedInteger(Op, Lo, Hi); + SDValue SignSet = DAG.getSetCC(dl, + TLI.getSetCCResultType(Hi.getValueType()), + Hi, DAG.getConstant(0, Hi.getValueType()), + ISD::SETLT); + + // Build a 64 bit pair (0, FF) in the constant pool, with FF in the lo bits. + SDValue FudgePtr = DAG.getConstantPool( + ConstantInt::get(*DAG.getContext(), FF.zext(64)), + TLI.getPointerTy()); + + // Get a pointer to FF if the sign bit was set, or to 0 otherwise. + SDValue Zero = DAG.getIntPtrConstant(0); + SDValue Four = DAG.getIntPtrConstant(4); + if (TLI.isBigEndian()) std::swap(Zero, Four); + SDValue Offset = DAG.getNode(ISD::SELECT, dl, Zero.getValueType(), SignSet, + Zero, Four); + unsigned Alignment = cast(FudgePtr)->getAlignment(); + FudgePtr = DAG.getNode(ISD::ADD, dl, TLI.getPointerTy(), FudgePtr, Offset); + Alignment = std::min(Alignment, 4u); + + // Load the value out, extending it from f32 to the destination float type. + // FIXME: Avoid the extend by constructing the right constant pool? + SDValue Fudge = DAG.getExtLoad(ISD::EXTLOAD, dl, DstVT, DAG.getEntryNode(), + FudgePtr, NULL, 0, MVT::f32, + false, Alignment); + return DAG.getNode(ISD::FADD, dl, DstVT, SignedConv, Fudge); + } + + // Otherwise, use a libcall. + RTLIB::Libcall LC = RTLIB::getUINTTOFP(SrcVT, DstVT); + assert(LC != RTLIB::UNKNOWN_LIBCALL && + "Don't know how to expand this UINT_TO_FP!"); + return MakeLibCall(LC, DstVT, &Op, 1, true, dl); +} diff --git a/libclamav/c++/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp b/libclamav/c++/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp new file mode 100644 index 000000000..e2986493d --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp @@ -0,0 +1,1078 @@ +//===-- LegalizeTypes.cpp - Common code for DAG type legalizer ------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the SelectionDAG::LegalizeTypes method. It transforms +// an arbitrary well-formed SelectionDAG to only consist of legal types. This +// is common code shared among the LegalizeTypes*.cpp files. +// +//===----------------------------------------------------------------------===// + +#include "LegalizeTypes.h" +#include "llvm/CallingConv.h" +#include "llvm/Target/TargetData.h" +#include "llvm/ADT/SetVector.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +static cl::opt +EnableExpensiveChecks("enable-legalize-types-checking", cl::Hidden); + +/// PerformExpensiveChecks - Do extensive, expensive, sanity checking. +void DAGTypeLegalizer::PerformExpensiveChecks() { + // If a node is not processed, then none of its values should be mapped by any + // of PromotedIntegers, ExpandedIntegers, ..., ReplacedValues. + + // If a node is processed, then each value with an illegal type must be mapped + // by exactly one of PromotedIntegers, ExpandedIntegers, ..., ReplacedValues. + // Values with a legal type may be mapped by ReplacedValues, but not by any of + // the other maps. + + // Note that these invariants may not hold momentarily when processing a node: + // the node being processed may be put in a map before being marked Processed. + + // Note that it is possible to have nodes marked NewNode in the DAG. This can + // occur in two ways. Firstly, a node may be created during legalization but + // never passed to the legalization core. This is usually due to the implicit + // folding that occurs when using the DAG.getNode operators. Secondly, a new + // node may be passed to the legalization core, but when analyzed may morph + // into a different node, leaving the original node as a NewNode in the DAG. + // A node may morph if one of its operands changes during analysis. Whether + // it actually morphs or not depends on whether, after updating its operands, + // it is equivalent to an existing node: if so, it morphs into that existing + // node (CSE). An operand can change during analysis if the operand is a new + // node that morphs, or it is a processed value that was mapped to some other + // value (as recorded in ReplacedValues) in which case the operand is turned + // into that other value. If a node morphs then the node it morphed into will + // be used instead of it for legalization, however the original node continues + // to live on in the DAG. + // The conclusion is that though there may be nodes marked NewNode in the DAG, + // all uses of such nodes are also marked NewNode: the result is a fungus of + // NewNodes growing on top of the useful nodes, and perhaps using them, but + // not used by them. + + // If a value is mapped by ReplacedValues, then it must have no uses, except + // by nodes marked NewNode (see above). + + // The final node obtained by mapping by ReplacedValues is not marked NewNode. + // Note that ReplacedValues should be applied iteratively. + + // Note that the ReplacedValues map may also map deleted nodes (by iterating + // over the DAG we never dereference deleted nodes). This means that it may + // also map nodes marked NewNode if the deallocated memory was reallocated as + // another node, and that new node was not seen by the LegalizeTypes machinery + // (for example because it was created but not used). In general, we cannot + // distinguish between new nodes and deleted nodes. + SmallVector NewNodes; + for (SelectionDAG::allnodes_iterator I = DAG.allnodes_begin(), + E = DAG.allnodes_end(); I != E; ++I) { + // Remember nodes marked NewNode - they are subject to extra checking below. + if (I->getNodeId() == NewNode) + NewNodes.push_back(I); + + for (unsigned i = 0, e = I->getNumValues(); i != e; ++i) { + SDValue Res(I, i); + bool Failed = false; + + unsigned Mapped = 0; + if (ReplacedValues.find(Res) != ReplacedValues.end()) { + Mapped |= 1; + // Check that remapped values are only used by nodes marked NewNode. + for (SDNode::use_iterator UI = I->use_begin(), UE = I->use_end(); + UI != UE; ++UI) + if (UI.getUse().getResNo() == i) + assert(UI->getNodeId() == NewNode && + "Remapped value has non-trivial use!"); + + // Check that the final result of applying ReplacedValues is not + // marked NewNode. + SDValue NewVal = ReplacedValues[Res]; + DenseMap::iterator I = ReplacedValues.find(NewVal); + while (I != ReplacedValues.end()) { + NewVal = I->second; + I = ReplacedValues.find(NewVal); + } + assert(NewVal.getNode()->getNodeId() != NewNode && + "ReplacedValues maps to a new node!"); + } + if (PromotedIntegers.find(Res) != PromotedIntegers.end()) + Mapped |= 2; + if (SoftenedFloats.find(Res) != SoftenedFloats.end()) + Mapped |= 4; + if (ScalarizedVectors.find(Res) != ScalarizedVectors.end()) + Mapped |= 8; + if (ExpandedIntegers.find(Res) != ExpandedIntegers.end()) + Mapped |= 16; + if (ExpandedFloats.find(Res) != ExpandedFloats.end()) + Mapped |= 32; + if (SplitVectors.find(Res) != SplitVectors.end()) + Mapped |= 64; + if (WidenedVectors.find(Res) != WidenedVectors.end()) + Mapped |= 128; + + if (I->getNodeId() != Processed) { + // Since we allow ReplacedValues to map deleted nodes, it may map nodes + // marked NewNode too, since a deleted node may have been reallocated as + // another node that has not been seen by the LegalizeTypes machinery. + if ((I->getNodeId() == NewNode && Mapped > 1) || + (I->getNodeId() != NewNode && Mapped != 0)) { + errs() << "Unprocessed value in a map!"; + Failed = true; + } + } else if (isTypeLegal(Res.getValueType()) || IgnoreNodeResults(I)) { + if (Mapped > 1) { + errs() << "Value with legal type was transformed!"; + Failed = true; + } + } else { + if (Mapped == 0) { + errs() << "Processed value not in any map!"; + Failed = true; + } else if (Mapped & (Mapped - 1)) { + errs() << "Value in multiple maps!"; + Failed = true; + } + } + + if (Failed) { + if (Mapped & 1) + errs() << " ReplacedValues"; + if (Mapped & 2) + errs() << " PromotedIntegers"; + if (Mapped & 4) + errs() << " SoftenedFloats"; + if (Mapped & 8) + errs() << " ScalarizedVectors"; + if (Mapped & 16) + errs() << " ExpandedIntegers"; + if (Mapped & 32) + errs() << " ExpandedFloats"; + if (Mapped & 64) + errs() << " SplitVectors"; + if (Mapped & 128) + errs() << " WidenedVectors"; + errs() << "\n"; + llvm_unreachable(0); + } + } + } + + // Checked that NewNodes are only used by other NewNodes. + for (unsigned i = 0, e = NewNodes.size(); i != e; ++i) { + SDNode *N = NewNodes[i]; + for (SDNode::use_iterator UI = N->use_begin(), UE = N->use_end(); + UI != UE; ++UI) + assert(UI->getNodeId() == NewNode && "NewNode used by non-NewNode!"); + } +} + +/// run - This is the main entry point for the type legalizer. This does a +/// top-down traversal of the dag, legalizing types as it goes. Returns "true" +/// if it made any changes. +bool DAGTypeLegalizer::run() { + bool Changed = false; + + // Create a dummy node (which is not added to allnodes), that adds a reference + // to the root node, preventing it from being deleted, and tracking any + // changes of the root. + HandleSDNode Dummy(DAG.getRoot()); + Dummy.setNodeId(Unanalyzed); + + // The root of the dag may dangle to deleted nodes until the type legalizer is + // done. Set it to null to avoid confusion. + DAG.setRoot(SDValue()); + + // Walk all nodes in the graph, assigning them a NodeId of 'ReadyToProcess' + // (and remembering them) if they are leaves and assigning 'Unanalyzed' if + // non-leaves. + for (SelectionDAG::allnodes_iterator I = DAG.allnodes_begin(), + E = DAG.allnodes_end(); I != E; ++I) { + if (I->getNumOperands() == 0) { + I->setNodeId(ReadyToProcess); + Worklist.push_back(I); + } else { + I->setNodeId(Unanalyzed); + } + } + + // Now that we have a set of nodes to process, handle them all. + while (!Worklist.empty()) { +#ifndef XDEBUG + if (EnableExpensiveChecks) +#endif + PerformExpensiveChecks(); + + SDNode *N = Worklist.back(); + Worklist.pop_back(); + assert(N->getNodeId() == ReadyToProcess && + "Node should be ready if on worklist!"); + + if (IgnoreNodeResults(N)) + goto ScanOperands; + + // Scan the values produced by the node, checking to see if any result + // types are illegal. + for (unsigned i = 0, NumResults = N->getNumValues(); i < NumResults; ++i) { + EVT ResultVT = N->getValueType(i); + switch (getTypeAction(ResultVT)) { + default: + assert(false && "Unknown action!"); + case Legal: + break; + // The following calls must take care of *all* of the node's results, + // not just the illegal result they were passed (this includes results + // with a legal type). Results can be remapped using ReplaceValueWith, + // or their promoted/expanded/etc values registered in PromotedIntegers, + // ExpandedIntegers etc. + case PromoteInteger: + PromoteIntegerResult(N, i); + Changed = true; + goto NodeDone; + case ExpandInteger: + ExpandIntegerResult(N, i); + Changed = true; + goto NodeDone; + case SoftenFloat: + SoftenFloatResult(N, i); + Changed = true; + goto NodeDone; + case ExpandFloat: + ExpandFloatResult(N, i); + Changed = true; + goto NodeDone; + case ScalarizeVector: + ScalarizeVectorResult(N, i); + Changed = true; + goto NodeDone; + case SplitVector: + SplitVectorResult(N, i); + Changed = true; + goto NodeDone; + case WidenVector: + WidenVectorResult(N, i); + Changed = true; + goto NodeDone; + } + } + +ScanOperands: + // Scan the operand list for the node, handling any nodes with operands that + // are illegal. + { + unsigned NumOperands = N->getNumOperands(); + bool NeedsReanalyzing = false; + unsigned i; + for (i = 0; i != NumOperands; ++i) { + if (IgnoreNodeResults(N->getOperand(i).getNode())) + continue; + + EVT OpVT = N->getOperand(i).getValueType(); + switch (getTypeAction(OpVT)) { + default: + assert(false && "Unknown action!"); + case Legal: + continue; + // The following calls must either replace all of the node's results + // using ReplaceValueWith, and return "false"; or update the node's + // operands in place, and return "true". + case PromoteInteger: + NeedsReanalyzing = PromoteIntegerOperand(N, i); + Changed = true; + break; + case ExpandInteger: + NeedsReanalyzing = ExpandIntegerOperand(N, i); + Changed = true; + break; + case SoftenFloat: + NeedsReanalyzing = SoftenFloatOperand(N, i); + Changed = true; + break; + case ExpandFloat: + NeedsReanalyzing = ExpandFloatOperand(N, i); + Changed = true; + break; + case ScalarizeVector: + NeedsReanalyzing = ScalarizeVectorOperand(N, i); + Changed = true; + break; + case SplitVector: + NeedsReanalyzing = SplitVectorOperand(N, i); + Changed = true; + break; + case WidenVector: + NeedsReanalyzing = WidenVectorOperand(N, i); + Changed = true; + break; + } + break; + } + + // The sub-method updated N in place. Check to see if any operands are new, + // and if so, mark them. If the node needs revisiting, don't add all users + // to the worklist etc. + if (NeedsReanalyzing) { + assert(N->getNodeId() == ReadyToProcess && "Node ID recalculated?"); + N->setNodeId(NewNode); + // Recompute the NodeId and correct processed operands, adding the node to + // the worklist if ready. + SDNode *M = AnalyzeNewNode(N); + if (M == N) + // The node didn't morph - nothing special to do, it will be revisited. + continue; + + // The node morphed - this is equivalent to legalizing by replacing every + // value of N with the corresponding value of M. So do that now. + assert(N->getNumValues() == M->getNumValues() && + "Node morphing changed the number of results!"); + for (unsigned i = 0, e = N->getNumValues(); i != e; ++i) + // Replacing the value takes care of remapping the new value. + ReplaceValueWith(SDValue(N, i), SDValue(M, i)); + assert(N->getNodeId() == NewNode && "Unexpected node state!"); + // The node continues to live on as part of the NewNode fungus that + // grows on top of the useful nodes. Nothing more needs to be done + // with it - move on to the next node. + continue; + } + + if (i == NumOperands) { + DEBUG(errs() << "Legally typed node: "; N->dump(&DAG); errs() << "\n"); + } + } +NodeDone: + + // If we reach here, the node was processed, potentially creating new nodes. + // Mark it as processed and add its users to the worklist as appropriate. + assert(N->getNodeId() == ReadyToProcess && "Node ID recalculated?"); + N->setNodeId(Processed); + + for (SDNode::use_iterator UI = N->use_begin(), E = N->use_end(); + UI != E; ++UI) { + SDNode *User = *UI; + int NodeId = User->getNodeId(); + + // This node has two options: it can either be a new node or its Node ID + // may be a count of the number of operands it has that are not ready. + if (NodeId > 0) { + User->setNodeId(NodeId-1); + + // If this was the last use it was waiting on, add it to the ready list. + if (NodeId-1 == ReadyToProcess) + Worklist.push_back(User); + continue; + } + + // If this is an unreachable new node, then ignore it. If it ever becomes + // reachable by being used by a newly created node then it will be handled + // by AnalyzeNewNode. + if (NodeId == NewNode) + continue; + + // Otherwise, this node is new: this is the first operand of it that + // became ready. Its new NodeId is the number of operands it has minus 1 + // (as this node is now processed). + assert(NodeId == Unanalyzed && "Unknown node ID!"); + User->setNodeId(User->getNumOperands() - 1); + + // If the node only has a single operand, it is now ready. + if (User->getNumOperands() == 1) + Worklist.push_back(User); + } + } + +#ifndef XDEBUG + if (EnableExpensiveChecks) +#endif + PerformExpensiveChecks(); + + // If the root changed (e.g. it was a dead load) update the root. + DAG.setRoot(Dummy.getValue()); + + // Remove dead nodes. This is important to do for cleanliness but also before + // the checking loop below. Implicit folding by the DAG.getNode operators and + // node morphing can cause unreachable nodes to be around with their flags set + // to new. + DAG.RemoveDeadNodes(); + + // In a debug build, scan all the nodes to make sure we found them all. This + // ensures that there are no cycles and that everything got processed. +#ifndef NDEBUG + for (SelectionDAG::allnodes_iterator I = DAG.allnodes_begin(), + E = DAG.allnodes_end(); I != E; ++I) { + bool Failed = false; + + // Check that all result types are legal. + if (!IgnoreNodeResults(I)) + for (unsigned i = 0, NumVals = I->getNumValues(); i < NumVals; ++i) + if (!isTypeLegal(I->getValueType(i))) { + errs() << "Result type " << i << " illegal!\n"; + Failed = true; + } + + // Check that all operand types are legal. + for (unsigned i = 0, NumOps = I->getNumOperands(); i < NumOps; ++i) + if (!IgnoreNodeResults(I->getOperand(i).getNode()) && + !isTypeLegal(I->getOperand(i).getValueType())) { + errs() << "Operand type " << i << " illegal!\n"; + Failed = true; + } + + if (I->getNodeId() != Processed) { + if (I->getNodeId() == NewNode) + errs() << "New node not analyzed?\n"; + else if (I->getNodeId() == Unanalyzed) + errs() << "Unanalyzed node not noticed?\n"; + else if (I->getNodeId() > 0) + errs() << "Operand not processed?\n"; + else if (I->getNodeId() == ReadyToProcess) + errs() << "Not added to worklist?\n"; + Failed = true; + } + + if (Failed) { + I->dump(&DAG); errs() << "\n"; + llvm_unreachable(0); + } + } +#endif + + return Changed; +} + +/// AnalyzeNewNode - The specified node is the root of a subtree of potentially +/// new nodes. Correct any processed operands (this may change the node) and +/// calculate the NodeId. If the node itself changes to a processed node, it +/// is not remapped - the caller needs to take care of this. +/// Returns the potentially changed node. +SDNode *DAGTypeLegalizer::AnalyzeNewNode(SDNode *N) { + // If this was an existing node that is already done, we're done. + if (N->getNodeId() != NewNode && N->getNodeId() != Unanalyzed) + return N; + + // Remove any stale map entries. + ExpungeNode(N); + + // Okay, we know that this node is new. Recursively walk all of its operands + // to see if they are new also. The depth of this walk is bounded by the size + // of the new tree that was constructed (usually 2-3 nodes), so we don't worry + // about revisiting of nodes. + // + // As we walk the operands, keep track of the number of nodes that are + // processed. If non-zero, this will become the new nodeid of this node. + // Operands may morph when they are analyzed. If so, the node will be + // updated after all operands have been analyzed. Since this is rare, + // the code tries to minimize overhead in the non-morphing case. + + SmallVector NewOps; + unsigned NumProcessed = 0; + for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) { + SDValue OrigOp = N->getOperand(i); + SDValue Op = OrigOp; + + AnalyzeNewValue(Op); // Op may morph. + + if (Op.getNode()->getNodeId() == Processed) + ++NumProcessed; + + if (!NewOps.empty()) { + // Some previous operand changed. Add this one to the list. + NewOps.push_back(Op); + } else if (Op != OrigOp) { + // This is the first operand to change - add all operands so far. + NewOps.insert(NewOps.end(), N->op_begin(), N->op_begin() + i); + NewOps.push_back(Op); + } + } + + // Some operands changed - update the node. + if (!NewOps.empty()) { + SDNode *M = DAG.UpdateNodeOperands(SDValue(N, 0), &NewOps[0], + NewOps.size()).getNode(); + if (M != N) { + // The node morphed into a different node. Normally for this to happen + // the original node would have to be marked NewNode. However this can + // in theory momentarily not be the case while ReplaceValueWith is doing + // its stuff. Mark the original node NewNode to help sanity checking. + N->setNodeId(NewNode); + if (M->getNodeId() != NewNode && M->getNodeId() != Unanalyzed) + // It morphed into a previously analyzed node - nothing more to do. + return M; + + // It morphed into a different new node. Do the equivalent of passing + // it to AnalyzeNewNode: expunge it and calculate the NodeId. No need + // to remap the operands, since they are the same as the operands we + // remapped above. + N = M; + ExpungeNode(N); + } + } + + // Calculate the NodeId. + N->setNodeId(N->getNumOperands() - NumProcessed); + if (N->getNodeId() == ReadyToProcess) + Worklist.push_back(N); + + return N; +} + +/// AnalyzeNewValue - Call AnalyzeNewNode, updating the node in Val if needed. +/// If the node changes to a processed node, then remap it. +void DAGTypeLegalizer::AnalyzeNewValue(SDValue &Val) { + Val.setNode(AnalyzeNewNode(Val.getNode())); + if (Val.getNode()->getNodeId() == Processed) + // We were passed a processed node, or it morphed into one - remap it. + RemapValue(Val); +} + +/// ExpungeNode - If N has a bogus mapping in ReplacedValues, eliminate it. +/// This can occur when a node is deleted then reallocated as a new node - +/// the mapping in ReplacedValues applies to the deleted node, not the new +/// one. +/// The only map that can have a deleted node as a source is ReplacedValues. +/// Other maps can have deleted nodes as targets, but since their looked-up +/// values are always immediately remapped using RemapValue, resulting in a +/// not-deleted node, this is harmless as long as ReplacedValues/RemapValue +/// always performs correct mappings. In order to keep the mapping correct, +/// ExpungeNode should be called on any new nodes *before* adding them as +/// either source or target to ReplacedValues (which typically means calling +/// Expunge when a new node is first seen, since it may no longer be marked +/// NewNode by the time it is added to ReplacedValues). +void DAGTypeLegalizer::ExpungeNode(SDNode *N) { + if (N->getNodeId() != NewNode) + return; + + // If N is not remapped by ReplacedValues then there is nothing to do. + unsigned i, e; + for (i = 0, e = N->getNumValues(); i != e; ++i) + if (ReplacedValues.find(SDValue(N, i)) != ReplacedValues.end()) + break; + + if (i == e) + return; + + // Remove N from all maps - this is expensive but rare. + + for (DenseMap::iterator I = PromotedIntegers.begin(), + E = PromotedIntegers.end(); I != E; ++I) { + assert(I->first.getNode() != N); + RemapValue(I->second); + } + + for (DenseMap::iterator I = SoftenedFloats.begin(), + E = SoftenedFloats.end(); I != E; ++I) { + assert(I->first.getNode() != N); + RemapValue(I->second); + } + + for (DenseMap::iterator I = ScalarizedVectors.begin(), + E = ScalarizedVectors.end(); I != E; ++I) { + assert(I->first.getNode() != N); + RemapValue(I->second); + } + + for (DenseMap::iterator I = WidenedVectors.begin(), + E = WidenedVectors.end(); I != E; ++I) { + assert(I->first.getNode() != N); + RemapValue(I->second); + } + + for (DenseMap >::iterator + I = ExpandedIntegers.begin(), E = ExpandedIntegers.end(); I != E; ++I){ + assert(I->first.getNode() != N); + RemapValue(I->second.first); + RemapValue(I->second.second); + } + + for (DenseMap >::iterator + I = ExpandedFloats.begin(), E = ExpandedFloats.end(); I != E; ++I) { + assert(I->first.getNode() != N); + RemapValue(I->second.first); + RemapValue(I->second.second); + } + + for (DenseMap >::iterator + I = SplitVectors.begin(), E = SplitVectors.end(); I != E; ++I) { + assert(I->first.getNode() != N); + RemapValue(I->second.first); + RemapValue(I->second.second); + } + + for (DenseMap::iterator I = ReplacedValues.begin(), + E = ReplacedValues.end(); I != E; ++I) + RemapValue(I->second); + + for (unsigned i = 0, e = N->getNumValues(); i != e; ++i) + ReplacedValues.erase(SDValue(N, i)); +} + +/// RemapValue - If the specified value was already legalized to another value, +/// replace it by that value. +void DAGTypeLegalizer::RemapValue(SDValue &N) { + DenseMap::iterator I = ReplacedValues.find(N); + if (I != ReplacedValues.end()) { + // Use path compression to speed up future lookups if values get multiply + // replaced with other values. + RemapValue(I->second); + N = I->second; + assert(N.getNode()->getNodeId() != NewNode && "Mapped to new node!"); + } +} + +namespace { + /// NodeUpdateListener - This class is a DAGUpdateListener that listens for + /// updates to nodes and recomputes their ready state. + class NodeUpdateListener : public SelectionDAG::DAGUpdateListener { + DAGTypeLegalizer &DTL; + SmallSetVector &NodesToAnalyze; + public: + explicit NodeUpdateListener(DAGTypeLegalizer &dtl, + SmallSetVector &nta) + : DTL(dtl), NodesToAnalyze(nta) {} + + virtual void NodeDeleted(SDNode *N, SDNode *E) { + assert(N->getNodeId() != DAGTypeLegalizer::ReadyToProcess && + N->getNodeId() != DAGTypeLegalizer::Processed && + "Invalid node ID for RAUW deletion!"); + // It is possible, though rare, for the deleted node N to occur as a + // target in a map, so note the replacement N -> E in ReplacedValues. + assert(E && "Node not replaced?"); + DTL.NoteDeletion(N, E); + + // In theory the deleted node could also have been scheduled for analysis. + // So remove it from the set of nodes which will be analyzed. + NodesToAnalyze.remove(N); + + // In general nothing needs to be done for E, since it didn't change but + // only gained new uses. However N -> E was just added to ReplacedValues, + // and the result of a ReplacedValues mapping is not allowed to be marked + // NewNode. So if E is marked NewNode, then it needs to be analyzed. + if (E->getNodeId() == DAGTypeLegalizer::NewNode) + NodesToAnalyze.insert(E); + } + + virtual void NodeUpdated(SDNode *N) { + // Node updates can mean pretty much anything. It is possible that an + // operand was set to something already processed (f.e.) in which case + // this node could become ready. Recompute its flags. + assert(N->getNodeId() != DAGTypeLegalizer::ReadyToProcess && + N->getNodeId() != DAGTypeLegalizer::Processed && + "Invalid node ID for RAUW deletion!"); + N->setNodeId(DAGTypeLegalizer::NewNode); + NodesToAnalyze.insert(N); + } + }; +} + + +/// ReplaceValueWith - The specified value was legalized to the specified other +/// value. Update the DAG and NodeIds replacing any uses of From to use To +/// instead. +void DAGTypeLegalizer::ReplaceValueWith(SDValue From, SDValue To) { + assert(From.getNode() != To.getNode() && "Potential legalization loop!"); + + // If expansion produced new nodes, make sure they are properly marked. + ExpungeNode(From.getNode()); + AnalyzeNewValue(To); // Expunges To. + + // Anything that used the old node should now use the new one. Note that this + // can potentially cause recursive merging. + SmallSetVector NodesToAnalyze; + NodeUpdateListener NUL(*this, NodesToAnalyze); + DAG.ReplaceAllUsesOfValueWith(From, To, &NUL); + + // The old node may still be present in a map like ExpandedIntegers or + // PromotedIntegers. Inform maps about the replacement. + ReplacedValues[From] = To; + + // Process the list of nodes that need to be reanalyzed. + while (!NodesToAnalyze.empty()) { + SDNode *N = NodesToAnalyze.back(); + NodesToAnalyze.pop_back(); + if (N->getNodeId() != DAGTypeLegalizer::NewNode) + // The node was analyzed while reanalyzing an earlier node - it is safe to + // skip. Note that this is not a morphing node - otherwise it would still + // be marked NewNode. + continue; + + // Analyze the node's operands and recalculate the node ID. + SDNode *M = AnalyzeNewNode(N); + if (M != N) { + // The node morphed into a different node. Make everyone use the new node + // instead. + assert(M->getNodeId() != NewNode && "Analysis resulted in NewNode!"); + assert(N->getNumValues() == M->getNumValues() && + "Node morphing changed the number of results!"); + for (unsigned i = 0, e = N->getNumValues(); i != e; ++i) { + SDValue OldVal(N, i); + SDValue NewVal(M, i); + if (M->getNodeId() == Processed) + RemapValue(NewVal); + DAG.ReplaceAllUsesOfValueWith(OldVal, NewVal, &NUL); + } + // The original node continues to exist in the DAG, marked NewNode. + } + } +} + +void DAGTypeLegalizer::SetPromotedInteger(SDValue Op, SDValue Result) { + assert(Result.getValueType() == TLI.getTypeToTransformTo(*DAG.getContext(), Op.getValueType()) && + "Invalid type for promoted integer"); + AnalyzeNewValue(Result); + + SDValue &OpEntry = PromotedIntegers[Op]; + assert(OpEntry.getNode() == 0 && "Node is already promoted!"); + OpEntry = Result; +} + +void DAGTypeLegalizer::SetSoftenedFloat(SDValue Op, SDValue Result) { + assert(Result.getValueType() == TLI.getTypeToTransformTo(*DAG.getContext(), Op.getValueType()) && + "Invalid type for softened float"); + AnalyzeNewValue(Result); + + SDValue &OpEntry = SoftenedFloats[Op]; + assert(OpEntry.getNode() == 0 && "Node is already converted to integer!"); + OpEntry = Result; +} + +void DAGTypeLegalizer::SetScalarizedVector(SDValue Op, SDValue Result) { + assert(Result.getValueType() == Op.getValueType().getVectorElementType() && + "Invalid type for scalarized vector"); + AnalyzeNewValue(Result); + + SDValue &OpEntry = ScalarizedVectors[Op]; + assert(OpEntry.getNode() == 0 && "Node is already scalarized!"); + OpEntry = Result; +} + +void DAGTypeLegalizer::GetExpandedInteger(SDValue Op, SDValue &Lo, + SDValue &Hi) { + std::pair &Entry = ExpandedIntegers[Op]; + RemapValue(Entry.first); + RemapValue(Entry.second); + assert(Entry.first.getNode() && "Operand isn't expanded"); + Lo = Entry.first; + Hi = Entry.second; +} + +void DAGTypeLegalizer::SetExpandedInteger(SDValue Op, SDValue Lo, + SDValue Hi) { + assert(Lo.getValueType() == TLI.getTypeToTransformTo(*DAG.getContext(), Op.getValueType()) && + Hi.getValueType() == Lo.getValueType() && + "Invalid type for expanded integer"); + // Lo/Hi may have been newly allocated, if so, add nodeid's as relevant. + AnalyzeNewValue(Lo); + AnalyzeNewValue(Hi); + + // Remember that this is the result of the node. + std::pair &Entry = ExpandedIntegers[Op]; + assert(Entry.first.getNode() == 0 && "Node already expanded"); + Entry.first = Lo; + Entry.second = Hi; +} + +void DAGTypeLegalizer::GetExpandedFloat(SDValue Op, SDValue &Lo, + SDValue &Hi) { + std::pair &Entry = ExpandedFloats[Op]; + RemapValue(Entry.first); + RemapValue(Entry.second); + assert(Entry.first.getNode() && "Operand isn't expanded"); + Lo = Entry.first; + Hi = Entry.second; +} + +void DAGTypeLegalizer::SetExpandedFloat(SDValue Op, SDValue Lo, + SDValue Hi) { + assert(Lo.getValueType() == TLI.getTypeToTransformTo(*DAG.getContext(), Op.getValueType()) && + Hi.getValueType() == Lo.getValueType() && + "Invalid type for expanded float"); + // Lo/Hi may have been newly allocated, if so, add nodeid's as relevant. + AnalyzeNewValue(Lo); + AnalyzeNewValue(Hi); + + // Remember that this is the result of the node. + std::pair &Entry = ExpandedFloats[Op]; + assert(Entry.first.getNode() == 0 && "Node already expanded"); + Entry.first = Lo; + Entry.second = Hi; +} + +void DAGTypeLegalizer::GetSplitVector(SDValue Op, SDValue &Lo, + SDValue &Hi) { + std::pair &Entry = SplitVectors[Op]; + RemapValue(Entry.first); + RemapValue(Entry.second); + assert(Entry.first.getNode() && "Operand isn't split"); + Lo = Entry.first; + Hi = Entry.second; +} + +void DAGTypeLegalizer::SetSplitVector(SDValue Op, SDValue Lo, + SDValue Hi) { + assert(Lo.getValueType().getVectorElementType() == + Op.getValueType().getVectorElementType() && + 2*Lo.getValueType().getVectorNumElements() == + Op.getValueType().getVectorNumElements() && + Hi.getValueType() == Lo.getValueType() && + "Invalid type for split vector"); + // Lo/Hi may have been newly allocated, if so, add nodeid's as relevant. + AnalyzeNewValue(Lo); + AnalyzeNewValue(Hi); + + // Remember that this is the result of the node. + std::pair &Entry = SplitVectors[Op]; + assert(Entry.first.getNode() == 0 && "Node already split"); + Entry.first = Lo; + Entry.second = Hi; +} + +void DAGTypeLegalizer::SetWidenedVector(SDValue Op, SDValue Result) { + assert(Result.getValueType() == TLI.getTypeToTransformTo(*DAG.getContext(), Op.getValueType()) && + "Invalid type for widened vector"); + AnalyzeNewValue(Result); + + SDValue &OpEntry = WidenedVectors[Op]; + assert(OpEntry.getNode() == 0 && "Node already widened!"); + OpEntry = Result; +} + + +//===----------------------------------------------------------------------===// +// Utilities. +//===----------------------------------------------------------------------===// + +/// BitConvertToInteger - Convert to an integer of the same size. +SDValue DAGTypeLegalizer::BitConvertToInteger(SDValue Op) { + unsigned BitWidth = Op.getValueType().getSizeInBits(); + return DAG.getNode(ISD::BIT_CONVERT, Op.getDebugLoc(), + EVT::getIntegerVT(*DAG.getContext(), BitWidth), Op); +} + +/// BitConvertVectorToIntegerVector - Convert to a vector of integers of the +/// same size. +SDValue DAGTypeLegalizer::BitConvertVectorToIntegerVector(SDValue Op) { + assert(Op.getValueType().isVector() && "Only applies to vectors!"); + unsigned EltWidth = Op.getValueType().getVectorElementType().getSizeInBits(); + EVT EltNVT = EVT::getIntegerVT(*DAG.getContext(), EltWidth); + unsigned NumElts = Op.getValueType().getVectorNumElements(); + return DAG.getNode(ISD::BIT_CONVERT, Op.getDebugLoc(), + EVT::getVectorVT(*DAG.getContext(), EltNVT, NumElts), Op); +} + +SDValue DAGTypeLegalizer::CreateStackStoreLoad(SDValue Op, + EVT DestVT) { + DebugLoc dl = Op.getDebugLoc(); + // Create the stack frame object. Make sure it is aligned for both + // the source and destination types. + SDValue StackPtr = DAG.CreateStackTemporary(Op.getValueType(), DestVT); + // Emit a store to the stack slot. + SDValue Store = DAG.getStore(DAG.getEntryNode(), dl, Op, StackPtr, NULL, 0); + // Result is a load from the stack slot. + return DAG.getLoad(DestVT, dl, Store, StackPtr, NULL, 0); +} + +/// CustomLowerNode - Replace the node's results with custom code provided +/// by the target and return "true", or do nothing and return "false". +/// The last parameter is FALSE if we are dealing with a node with legal +/// result types and illegal operand. The second parameter denotes the type of +/// illegal OperandNo in that case. +/// The last parameter being TRUE means we are dealing with a +/// node with illegal result types. The second parameter denotes the type of +/// illegal ResNo in that case. +bool DAGTypeLegalizer::CustomLowerNode(SDNode *N, EVT VT, bool LegalizeResult) { + // See if the target wants to custom lower this node. + if (TLI.getOperationAction(N->getOpcode(), VT) != TargetLowering::Custom) + return false; + + SmallVector Results; + if (LegalizeResult) + TLI.ReplaceNodeResults(N, Results, DAG); + else + TLI.LowerOperationWrapper(N, Results, DAG); + + if (Results.empty()) + // The target didn't want to custom lower it after all. + return false; + + // Make everything that once used N's values now use those in Results instead. + assert(Results.size() == N->getNumValues() && + "Custom lowering returned the wrong number of results!"); + for (unsigned i = 0, e = Results.size(); i != e; ++i) + ReplaceValueWith(SDValue(N, i), Results[i]); + return true; +} + +/// GetSplitDestVTs - Compute the VTs needed for the low/hi parts of a type +/// which is split into two not necessarily identical pieces. +void DAGTypeLegalizer::GetSplitDestVTs(EVT InVT, EVT &LoVT, EVT &HiVT) { + // Currently all types are split in half. + if (!InVT.isVector()) { + LoVT = HiVT = TLI.getTypeToTransformTo(*DAG.getContext(), InVT); + } else { + unsigned NumElements = InVT.getVectorNumElements(); + assert(!(NumElements & 1) && "Splitting vector, but not in half!"); + LoVT = HiVT = EVT::getVectorVT(*DAG.getContext(), InVT.getVectorElementType(), NumElements/2); + } +} + +/// GetPairElements - Use ISD::EXTRACT_ELEMENT nodes to extract the low and +/// high parts of the given value. +void DAGTypeLegalizer::GetPairElements(SDValue Pair, + SDValue &Lo, SDValue &Hi) { + DebugLoc dl = Pair.getDebugLoc(); + EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), Pair.getValueType()); + Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, NVT, Pair, + DAG.getIntPtrConstant(0)); + Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, NVT, Pair, + DAG.getIntPtrConstant(1)); +} + +SDValue DAGTypeLegalizer::GetVectorElementPointer(SDValue VecPtr, EVT EltVT, + SDValue Index) { + DebugLoc dl = Index.getDebugLoc(); + // Make sure the index type is big enough to compute in. + if (Index.getValueType().bitsGT(TLI.getPointerTy())) + Index = DAG.getNode(ISD::TRUNCATE, dl, TLI.getPointerTy(), Index); + else + Index = DAG.getNode(ISD::ZERO_EXTEND, dl, TLI.getPointerTy(), Index); + + // Calculate the element offset and add it to the pointer. + unsigned EltSize = EltVT.getSizeInBits() / 8; // FIXME: should be ABI size. + + Index = DAG.getNode(ISD::MUL, dl, Index.getValueType(), Index, + DAG.getConstant(EltSize, Index.getValueType())); + return DAG.getNode(ISD::ADD, dl, Index.getValueType(), Index, VecPtr); +} + +/// JoinIntegers - Build an integer with low bits Lo and high bits Hi. +SDValue DAGTypeLegalizer::JoinIntegers(SDValue Lo, SDValue Hi) { + // Arbitrarily use dlHi for result DebugLoc + DebugLoc dlHi = Hi.getDebugLoc(); + DebugLoc dlLo = Lo.getDebugLoc(); + EVT LVT = Lo.getValueType(); + EVT HVT = Hi.getValueType(); + EVT NVT = EVT::getIntegerVT(*DAG.getContext(), LVT.getSizeInBits() + HVT.getSizeInBits()); + + Lo = DAG.getNode(ISD::ZERO_EXTEND, dlLo, NVT, Lo); + Hi = DAG.getNode(ISD::ANY_EXTEND, dlHi, NVT, Hi); + Hi = DAG.getNode(ISD::SHL, dlHi, NVT, Hi, + DAG.getConstant(LVT.getSizeInBits(), TLI.getPointerTy())); + return DAG.getNode(ISD::OR, dlHi, NVT, Lo, Hi); +} + +/// LibCallify - Convert the node into a libcall with the same prototype. +SDValue DAGTypeLegalizer::LibCallify(RTLIB::Libcall LC, SDNode *N, + bool isSigned) { + unsigned NumOps = N->getNumOperands(); + DebugLoc dl = N->getDebugLoc(); + if (NumOps == 0) { + return MakeLibCall(LC, N->getValueType(0), 0, 0, isSigned, dl); + } else if (NumOps == 1) { + SDValue Op = N->getOperand(0); + return MakeLibCall(LC, N->getValueType(0), &Op, 1, isSigned, dl); + } else if (NumOps == 2) { + SDValue Ops[2] = { N->getOperand(0), N->getOperand(1) }; + return MakeLibCall(LC, N->getValueType(0), Ops, 2, isSigned, dl); + } + SmallVector Ops(NumOps); + for (unsigned i = 0; i < NumOps; ++i) + Ops[i] = N->getOperand(i); + + return MakeLibCall(LC, N->getValueType(0), &Ops[0], NumOps, isSigned, dl); +} + +/// MakeLibCall - Generate a libcall taking the given operands as arguments and +/// returning a result of type RetVT. +SDValue DAGTypeLegalizer::MakeLibCall(RTLIB::Libcall LC, EVT RetVT, + const SDValue *Ops, unsigned NumOps, + bool isSigned, DebugLoc dl) { + TargetLowering::ArgListTy Args; + Args.reserve(NumOps); + + TargetLowering::ArgListEntry Entry; + for (unsigned i = 0; i != NumOps; ++i) { + Entry.Node = Ops[i]; + Entry.Ty = Entry.Node.getValueType().getTypeForEVT(*DAG.getContext()); + Entry.isSExt = isSigned; + Entry.isZExt = !isSigned; + Args.push_back(Entry); + } + SDValue Callee = DAG.getExternalSymbol(TLI.getLibcallName(LC), + TLI.getPointerTy()); + + const Type *RetTy = RetVT.getTypeForEVT(*DAG.getContext()); + std::pair CallInfo = + TLI.LowerCallTo(DAG.getEntryNode(), RetTy, isSigned, !isSigned, false, + false, 0, TLI.getLibcallCallingConv(LC), false, + /*isReturnValueUsed=*/true, + Callee, Args, DAG, dl); + return CallInfo.first; +} + +/// PromoteTargetBoolean - Promote the given target boolean to a target boolean +/// of the given type. A target boolean is an integer value, not necessarily of +/// type i1, the bits of which conform to getBooleanContents. +SDValue DAGTypeLegalizer::PromoteTargetBoolean(SDValue Bool, EVT VT) { + DebugLoc dl = Bool.getDebugLoc(); + ISD::NodeType ExtendCode; + switch (TLI.getBooleanContents()) { + default: + assert(false && "Unknown BooleanContent!"); + case TargetLowering::UndefinedBooleanContent: + // Extend to VT by adding rubbish bits. + ExtendCode = ISD::ANY_EXTEND; + break; + case TargetLowering::ZeroOrOneBooleanContent: + // Extend to VT by adding zero bits. + ExtendCode = ISD::ZERO_EXTEND; + break; + case TargetLowering::ZeroOrNegativeOneBooleanContent: { + // Extend to VT by copying the sign bit. + ExtendCode = ISD::SIGN_EXTEND; + break; + } + } + return DAG.getNode(ExtendCode, dl, VT, Bool); +} + +/// SplitInteger - Return the lower LoVT bits of Op in Lo and the upper HiVT +/// bits in Hi. +void DAGTypeLegalizer::SplitInteger(SDValue Op, + EVT LoVT, EVT HiVT, + SDValue &Lo, SDValue &Hi) { + DebugLoc dl = Op.getDebugLoc(); + assert(LoVT.getSizeInBits() + HiVT.getSizeInBits() == + Op.getValueType().getSizeInBits() && "Invalid integer splitting!"); + Lo = DAG.getNode(ISD::TRUNCATE, dl, LoVT, Op); + Hi = DAG.getNode(ISD::SRL, dl, Op.getValueType(), Op, + DAG.getConstant(LoVT.getSizeInBits(), TLI.getPointerTy())); + Hi = DAG.getNode(ISD::TRUNCATE, dl, HiVT, Hi); +} + +/// SplitInteger - Return the lower and upper halves of Op's bits in a value +/// type half the size of Op's. +void DAGTypeLegalizer::SplitInteger(SDValue Op, + SDValue &Lo, SDValue &Hi) { + EVT HalfVT = EVT::getIntegerVT(*DAG.getContext(), Op.getValueType().getSizeInBits()/2); + SplitInteger(Op, HalfVT, HalfVT, Lo, Hi); +} + + +//===----------------------------------------------------------------------===// +// Entry Point +//===----------------------------------------------------------------------===// + +/// LegalizeTypes - This transforms the SelectionDAG into a SelectionDAG that +/// only uses types natively supported by the target. Returns "true" if it made +/// any changes. +/// +/// Note that this is an involved process that may invalidate pointers into +/// the graph. +bool SelectionDAG::LegalizeTypes() { + return DAGTypeLegalizer(*this).run(); +} diff --git a/libclamav/c++/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h b/libclamav/c++/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h new file mode 100644 index 000000000..7b9b010e6 --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h @@ -0,0 +1,737 @@ +//===-- LegalizeTypes.h - Definition of the DAG Type Legalizer class ------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the DAGTypeLegalizer class. This is a private interface +// shared between the code that implements the SelectionDAG::LegalizeTypes +// method. +// +//===----------------------------------------------------------------------===// + +#ifndef SELECTIONDAG_LEGALIZETYPES_H +#define SELECTIONDAG_LEGALIZETYPES_H + +#define DEBUG_TYPE "legalize-types" +#include "llvm/CodeGen/SelectionDAG.h" +#include "llvm/Target/TargetLowering.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/DenseSet.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/Debug.h" + +namespace llvm { + +//===----------------------------------------------------------------------===// +/// DAGTypeLegalizer - This takes an arbitrary SelectionDAG as input and hacks +/// on it until only value types the target machine can handle are left. This +/// involves promoting small sizes to large sizes or splitting up large values +/// into small values. +/// +class VISIBILITY_HIDDEN DAGTypeLegalizer { + TargetLowering &TLI; + SelectionDAG &DAG; +public: + // NodeIdFlags - This pass uses the NodeId on the SDNodes to hold information + // about the state of the node. The enum has all the values. + enum NodeIdFlags { + /// ReadyToProcess - All operands have been processed, so this node is ready + /// to be handled. + ReadyToProcess = 0, + + /// NewNode - This is a new node, not before seen, that was created in the + /// process of legalizing some other node. + NewNode = -1, + + /// Unanalyzed - This node's ID needs to be set to the number of its + /// unprocessed operands. + Unanalyzed = -2, + + /// Processed - This is a node that has already been processed. + Processed = -3 + + // 1+ - This is a node which has this many unprocessed operands. + }; +private: + enum LegalizeAction { + Legal, // The target natively supports this type. + PromoteInteger, // Replace this integer type with a larger one. + ExpandInteger, // Split this integer type into two of half the size. + SoftenFloat, // Convert this float type to a same size integer type. + ExpandFloat, // Split this float type into two of half the size. + ScalarizeVector, // Replace this one-element vector with its element type. + SplitVector, // Split this vector type into two of half the size. + WidenVector // This vector type should be widened into a larger vector. + }; + + /// ValueTypeActions - This is a bitvector that contains two bits for each + /// simple value type, where the two bits correspond to the LegalizeAction + /// enum from TargetLowering. This can be queried with "getTypeAction(VT)". + TargetLowering::ValueTypeActionImpl ValueTypeActions; + + /// getTypeAction - Return how we should legalize values of this type. + LegalizeAction getTypeAction(EVT VT) const { + switch (ValueTypeActions.getTypeAction(*DAG.getContext(), VT)) { + default: + assert(false && "Unknown legalize action!"); + case TargetLowering::Legal: + return Legal; + case TargetLowering::Promote: + // Promote can mean + // 1) For integers, use a larger integer type (e.g. i8 -> i32). + // 2) For vectors, use a wider vector type (e.g. v3i32 -> v4i32). + if (!VT.isVector()) + return PromoteInteger; + else + return WidenVector; + case TargetLowering::Expand: + // Expand can mean + // 1) split scalar in half, 2) convert a float to an integer, + // 3) scalarize a single-element vector, 4) split a vector in two. + if (!VT.isVector()) { + if (VT.isInteger()) + return ExpandInteger; + else if (VT.getSizeInBits() == + TLI.getTypeToTransformTo(*DAG.getContext(), VT).getSizeInBits()) + return SoftenFloat; + else + return ExpandFloat; + } else if (VT.getVectorNumElements() == 1) { + return ScalarizeVector; + } else { + return SplitVector; + } + } + } + + /// isTypeLegal - Return true if this type is legal on this target. + bool isTypeLegal(EVT VT) const { + return (ValueTypeActions.getTypeAction(*DAG.getContext(), VT) == + TargetLowering::Legal); + } + + /// IgnoreNodeResults - Pretend all of this node's results are legal. + bool IgnoreNodeResults(SDNode *N) const { + return N->getOpcode() == ISD::TargetConstant; + } + + /// PromotedIntegers - For integer nodes that are below legal width, this map + /// indicates what promoted value to use. + DenseMap PromotedIntegers; + + /// ExpandedIntegers - For integer nodes that need to be expanded this map + /// indicates which operands are the expanded version of the input. + DenseMap > ExpandedIntegers; + + /// SoftenedFloats - For floating point nodes converted to integers of + /// the same size, this map indicates the converted value to use. + DenseMap SoftenedFloats; + + /// ExpandedFloats - For float nodes that need to be expanded this map + /// indicates which operands are the expanded version of the input. + DenseMap > ExpandedFloats; + + /// ScalarizedVectors - For nodes that are <1 x ty>, this map indicates the + /// scalar value of type 'ty' to use. + DenseMap ScalarizedVectors; + + /// SplitVectors - For nodes that need to be split this map indicates + /// which operands are the expanded version of the input. + DenseMap > SplitVectors; + + /// WidenedVectors - For vector nodes that need to be widened, indicates + /// the widened value to use. + DenseMap WidenedVectors; + + /// ReplacedValues - For values that have been replaced with another, + /// indicates the replacement value to use. + DenseMap ReplacedValues; + + /// Worklist - This defines a worklist of nodes to process. In order to be + /// pushed onto this worklist, all operands of a node must have already been + /// processed. + SmallVector Worklist; + +public: + explicit DAGTypeLegalizer(SelectionDAG &dag) + : TLI(dag.getTargetLoweringInfo()), DAG(dag), + ValueTypeActions(TLI.getValueTypeActions()) { + assert(MVT::LAST_VALUETYPE <= MVT::MAX_ALLOWED_VALUETYPE && + "Too many value types for ValueTypeActions to hold!"); + } + + /// run - This is the main entry point for the type legalizer. This does a + /// top-down traversal of the dag, legalizing types as it goes. Returns + /// "true" if it made any changes. + bool run(); + + void NoteDeletion(SDNode *Old, SDNode *New) { + ExpungeNode(Old); + ExpungeNode(New); + for (unsigned i = 0, e = Old->getNumValues(); i != e; ++i) + ReplacedValues[SDValue(Old, i)] = SDValue(New, i); + } + +private: + SDNode *AnalyzeNewNode(SDNode *N); + void AnalyzeNewValue(SDValue &Val); + void ExpungeNode(SDNode *N); + void PerformExpensiveChecks(); + void RemapValue(SDValue &N); + + // Common routines. + SDValue BitConvertToInteger(SDValue Op); + SDValue BitConvertVectorToIntegerVector(SDValue Op); + SDValue CreateStackStoreLoad(SDValue Op, EVT DestVT); + bool CustomLowerNode(SDNode *N, EVT VT, bool LegalizeResult); + SDValue GetVectorElementPointer(SDValue VecPtr, EVT EltVT, SDValue Index); + SDValue JoinIntegers(SDValue Lo, SDValue Hi); + SDValue LibCallify(RTLIB::Libcall LC, SDNode *N, bool isSigned); + SDValue MakeLibCall(RTLIB::Libcall LC, EVT RetVT, + const SDValue *Ops, unsigned NumOps, bool isSigned, + DebugLoc dl); + SDValue PromoteTargetBoolean(SDValue Bool, EVT VT); + void ReplaceValueWith(SDValue From, SDValue To); + void SplitInteger(SDValue Op, SDValue &Lo, SDValue &Hi); + void SplitInteger(SDValue Op, EVT LoVT, EVT HiVT, + SDValue &Lo, SDValue &Hi); + + //===--------------------------------------------------------------------===// + // Integer Promotion Support: LegalizeIntegerTypes.cpp + //===--------------------------------------------------------------------===// + + /// GetPromotedInteger - Given a processed operand Op which was promoted to a + /// larger integer type, this returns the promoted value. The low bits of the + /// promoted value corresponding to the original type are exactly equal to Op. + /// The extra bits contain rubbish, so the promoted value may need to be zero- + /// or sign-extended from the original type before it is usable (the helpers + /// SExtPromotedInteger and ZExtPromotedInteger can do this for you). + /// For example, if Op is an i16 and was promoted to an i32, then this method + /// returns an i32, the lower 16 bits of which coincide with Op, and the upper + /// 16 bits of which contain rubbish. + SDValue GetPromotedInteger(SDValue Op) { + SDValue &PromotedOp = PromotedIntegers[Op]; + RemapValue(PromotedOp); + assert(PromotedOp.getNode() && "Operand wasn't promoted?"); + return PromotedOp; + } + void SetPromotedInteger(SDValue Op, SDValue Result); + + /// SExtPromotedInteger - Get a promoted operand and sign extend it to the + /// final size. + SDValue SExtPromotedInteger(SDValue Op) { + EVT OldVT = Op.getValueType(); + DebugLoc dl = Op.getDebugLoc(); + Op = GetPromotedInteger(Op); + return DAG.getNode(ISD::SIGN_EXTEND_INREG, dl, Op.getValueType(), Op, + DAG.getValueType(OldVT)); + } + + /// ZExtPromotedInteger - Get a promoted operand and zero extend it to the + /// final size. + SDValue ZExtPromotedInteger(SDValue Op) { + EVT OldVT = Op.getValueType(); + DebugLoc dl = Op.getDebugLoc(); + Op = GetPromotedInteger(Op); + return DAG.getZeroExtendInReg(Op, dl, OldVT); + } + + // Integer Result Promotion. + void PromoteIntegerResult(SDNode *N, unsigned ResNo); + SDValue PromoteIntRes_AssertSext(SDNode *N); + SDValue PromoteIntRes_AssertZext(SDNode *N); + SDValue PromoteIntRes_Atomic1(AtomicSDNode *N); + SDValue PromoteIntRes_Atomic2(AtomicSDNode *N); + SDValue PromoteIntRes_BIT_CONVERT(SDNode *N); + SDValue PromoteIntRes_BSWAP(SDNode *N); + SDValue PromoteIntRes_BUILD_PAIR(SDNode *N); + SDValue PromoteIntRes_Constant(SDNode *N); + SDValue PromoteIntRes_CONVERT_RNDSAT(SDNode *N); + SDValue PromoteIntRes_CTLZ(SDNode *N); + SDValue PromoteIntRes_CTPOP(SDNode *N); + SDValue PromoteIntRes_CTTZ(SDNode *N); + SDValue PromoteIntRes_EXTRACT_VECTOR_ELT(SDNode *N); + SDValue PromoteIntRes_FP_TO_XINT(SDNode *N); + SDValue PromoteIntRes_INT_EXTEND(SDNode *N); + SDValue PromoteIntRes_LOAD(LoadSDNode *N); + SDValue PromoteIntRes_Overflow(SDNode *N); + SDValue PromoteIntRes_SADDSUBO(SDNode *N, unsigned ResNo); + SDValue PromoteIntRes_SDIV(SDNode *N); + SDValue PromoteIntRes_SELECT(SDNode *N); + SDValue PromoteIntRes_SELECT_CC(SDNode *N); + SDValue PromoteIntRes_SETCC(SDNode *N); + SDValue PromoteIntRes_SHL(SDNode *N); + SDValue PromoteIntRes_SimpleIntBinOp(SDNode *N); + SDValue PromoteIntRes_SIGN_EXTEND_INREG(SDNode *N); + SDValue PromoteIntRes_SRA(SDNode *N); + SDValue PromoteIntRes_SRL(SDNode *N); + SDValue PromoteIntRes_TRUNCATE(SDNode *N); + SDValue PromoteIntRes_UADDSUBO(SDNode *N, unsigned ResNo); + SDValue PromoteIntRes_UDIV(SDNode *N); + SDValue PromoteIntRes_UNDEF(SDNode *N); + SDValue PromoteIntRes_VAARG(SDNode *N); + SDValue PromoteIntRes_XMULO(SDNode *N, unsigned ResNo); + + // Integer Operand Promotion. + bool PromoteIntegerOperand(SDNode *N, unsigned OperandNo); + SDValue PromoteIntOp_ANY_EXTEND(SDNode *N); + SDValue PromoteIntOp_BIT_CONVERT(SDNode *N); + SDValue PromoteIntOp_BUILD_PAIR(SDNode *N); + SDValue PromoteIntOp_BR_CC(SDNode *N, unsigned OpNo); + SDValue PromoteIntOp_BRCOND(SDNode *N, unsigned OpNo); + SDValue PromoteIntOp_BUILD_VECTOR(SDNode *N); + SDValue PromoteIntOp_CONVERT_RNDSAT(SDNode *N); + SDValue PromoteIntOp_INSERT_VECTOR_ELT(SDNode *N, unsigned OpNo); + SDValue PromoteIntOp_MEMBARRIER(SDNode *N); + SDValue PromoteIntOp_SCALAR_TO_VECTOR(SDNode *N); + SDValue PromoteIntOp_SELECT(SDNode *N, unsigned OpNo); + SDValue PromoteIntOp_SELECT_CC(SDNode *N, unsigned OpNo); + SDValue PromoteIntOp_SETCC(SDNode *N, unsigned OpNo); + SDValue PromoteIntOp_Shift(SDNode *N); + SDValue PromoteIntOp_SIGN_EXTEND(SDNode *N); + SDValue PromoteIntOp_SINT_TO_FP(SDNode *N); + SDValue PromoteIntOp_STORE(StoreSDNode *N, unsigned OpNo); + SDValue PromoteIntOp_TRUNCATE(SDNode *N); + SDValue PromoteIntOp_UINT_TO_FP(SDNode *N); + SDValue PromoteIntOp_ZERO_EXTEND(SDNode *N); + + void PromoteSetCCOperands(SDValue &LHS,SDValue &RHS, ISD::CondCode Code); + + //===--------------------------------------------------------------------===// + // Integer Expansion Support: LegalizeIntegerTypes.cpp + //===--------------------------------------------------------------------===// + + /// GetExpandedInteger - Given a processed operand Op which was expanded into + /// two integers of half the size, this returns the two halves. The low bits + /// of Op are exactly equal to the bits of Lo; the high bits exactly equal Hi. + /// For example, if Op is an i64 which was expanded into two i32's, then this + /// method returns the two i32's, with Lo being equal to the lower 32 bits of + /// Op, and Hi being equal to the upper 32 bits. + void GetExpandedInteger(SDValue Op, SDValue &Lo, SDValue &Hi); + void SetExpandedInteger(SDValue Op, SDValue Lo, SDValue Hi); + + // Integer Result Expansion. + void ExpandIntegerResult(SDNode *N, unsigned ResNo); + void ExpandIntRes_ANY_EXTEND (SDNode *N, SDValue &Lo, SDValue &Hi); + void ExpandIntRes_AssertSext (SDNode *N, SDValue &Lo, SDValue &Hi); + void ExpandIntRes_AssertZext (SDNode *N, SDValue &Lo, SDValue &Hi); + void ExpandIntRes_Constant (SDNode *N, SDValue &Lo, SDValue &Hi); + void ExpandIntRes_CTLZ (SDNode *N, SDValue &Lo, SDValue &Hi); + void ExpandIntRes_CTPOP (SDNode *N, SDValue &Lo, SDValue &Hi); + void ExpandIntRes_CTTZ (SDNode *N, SDValue &Lo, SDValue &Hi); + void ExpandIntRes_LOAD (LoadSDNode *N, SDValue &Lo, SDValue &Hi); + void ExpandIntRes_SIGN_EXTEND (SDNode *N, SDValue &Lo, SDValue &Hi); + void ExpandIntRes_SIGN_EXTEND_INREG (SDNode *N, SDValue &Lo, SDValue &Hi); + void ExpandIntRes_TRUNCATE (SDNode *N, SDValue &Lo, SDValue &Hi); + void ExpandIntRes_ZERO_EXTEND (SDNode *N, SDValue &Lo, SDValue &Hi); + void ExpandIntRes_FP_TO_SINT (SDNode *N, SDValue &Lo, SDValue &Hi); + void ExpandIntRes_FP_TO_UINT (SDNode *N, SDValue &Lo, SDValue &Hi); + + void ExpandIntRes_Logical (SDNode *N, SDValue &Lo, SDValue &Hi); + void ExpandIntRes_ADDSUB (SDNode *N, SDValue &Lo, SDValue &Hi); + void ExpandIntRes_ADDSUBC (SDNode *N, SDValue &Lo, SDValue &Hi); + void ExpandIntRes_ADDSUBE (SDNode *N, SDValue &Lo, SDValue &Hi); + void ExpandIntRes_BSWAP (SDNode *N, SDValue &Lo, SDValue &Hi); + void ExpandIntRes_MUL (SDNode *N, SDValue &Lo, SDValue &Hi); + void ExpandIntRes_SDIV (SDNode *N, SDValue &Lo, SDValue &Hi); + void ExpandIntRes_SREM (SDNode *N, SDValue &Lo, SDValue &Hi); + void ExpandIntRes_UDIV (SDNode *N, SDValue &Lo, SDValue &Hi); + void ExpandIntRes_UREM (SDNode *N, SDValue &Lo, SDValue &Hi); + void ExpandIntRes_Shift (SDNode *N, SDValue &Lo, SDValue &Hi); + + void ExpandShiftByConstant(SDNode *N, unsigned Amt, + SDValue &Lo, SDValue &Hi); + bool ExpandShiftWithKnownAmountBit(SDNode *N, SDValue &Lo, SDValue &Hi); + bool ExpandShiftWithUnknownAmountBit(SDNode *N, SDValue &Lo, SDValue &Hi); + + // Integer Operand Expansion. + bool ExpandIntegerOperand(SDNode *N, unsigned OperandNo); + SDValue ExpandIntOp_BIT_CONVERT(SDNode *N); + SDValue ExpandIntOp_BR_CC(SDNode *N); + SDValue ExpandIntOp_BUILD_VECTOR(SDNode *N); + SDValue ExpandIntOp_EXTRACT_ELEMENT(SDNode *N); + SDValue ExpandIntOp_SELECT_CC(SDNode *N); + SDValue ExpandIntOp_SETCC(SDNode *N); + SDValue ExpandIntOp_Shift(SDNode *N); + SDValue ExpandIntOp_SINT_TO_FP(SDNode *N); + SDValue ExpandIntOp_STORE(StoreSDNode *N, unsigned OpNo); + SDValue ExpandIntOp_TRUNCATE(SDNode *N); + SDValue ExpandIntOp_UINT_TO_FP(SDNode *N); + + void IntegerExpandSetCCOperands(SDValue &NewLHS, SDValue &NewRHS, + ISD::CondCode &CCCode, DebugLoc dl); + + //===--------------------------------------------------------------------===// + // Float to Integer Conversion Support: LegalizeFloatTypes.cpp + //===--------------------------------------------------------------------===// + + /// GetSoftenedFloat - Given a processed operand Op which was converted to an + /// integer of the same size, this returns the integer. The integer contains + /// exactly the same bits as Op - only the type changed. For example, if Op + /// is an f32 which was softened to an i32, then this method returns an i32, + /// the bits of which coincide with those of Op. + SDValue GetSoftenedFloat(SDValue Op) { + SDValue &SoftenedOp = SoftenedFloats[Op]; + RemapValue(SoftenedOp); + assert(SoftenedOp.getNode() && "Operand wasn't converted to integer?"); + return SoftenedOp; + } + void SetSoftenedFloat(SDValue Op, SDValue Result); + + // Result Float to Integer Conversion. + void SoftenFloatResult(SDNode *N, unsigned OpNo); + SDValue SoftenFloatRes_BIT_CONVERT(SDNode *N); + SDValue SoftenFloatRes_BUILD_PAIR(SDNode *N); + SDValue SoftenFloatRes_ConstantFP(ConstantFPSDNode *N); + SDValue SoftenFloatRes_EXTRACT_VECTOR_ELT(SDNode *N); + SDValue SoftenFloatRes_FABS(SDNode *N); + SDValue SoftenFloatRes_FADD(SDNode *N); + SDValue SoftenFloatRes_FCEIL(SDNode *N); + SDValue SoftenFloatRes_FCOPYSIGN(SDNode *N); + SDValue SoftenFloatRes_FCOS(SDNode *N); + SDValue SoftenFloatRes_FDIV(SDNode *N); + SDValue SoftenFloatRes_FEXP(SDNode *N); + SDValue SoftenFloatRes_FEXP2(SDNode *N); + SDValue SoftenFloatRes_FFLOOR(SDNode *N); + SDValue SoftenFloatRes_FLOG(SDNode *N); + SDValue SoftenFloatRes_FLOG2(SDNode *N); + SDValue SoftenFloatRes_FLOG10(SDNode *N); + SDValue SoftenFloatRes_FMUL(SDNode *N); + SDValue SoftenFloatRes_FNEARBYINT(SDNode *N); + SDValue SoftenFloatRes_FNEG(SDNode *N); + SDValue SoftenFloatRes_FP_EXTEND(SDNode *N); + SDValue SoftenFloatRes_FP_ROUND(SDNode *N); + SDValue SoftenFloatRes_FPOW(SDNode *N); + SDValue SoftenFloatRes_FPOWI(SDNode *N); + SDValue SoftenFloatRes_FREM(SDNode *N); + SDValue SoftenFloatRes_FRINT(SDNode *N); + SDValue SoftenFloatRes_FSIN(SDNode *N); + SDValue SoftenFloatRes_FSQRT(SDNode *N); + SDValue SoftenFloatRes_FSUB(SDNode *N); + SDValue SoftenFloatRes_FTRUNC(SDNode *N); + SDValue SoftenFloatRes_LOAD(SDNode *N); + SDValue SoftenFloatRes_SELECT(SDNode *N); + SDValue SoftenFloatRes_SELECT_CC(SDNode *N); + SDValue SoftenFloatRes_UNDEF(SDNode *N); + SDValue SoftenFloatRes_VAARG(SDNode *N); + SDValue SoftenFloatRes_XINT_TO_FP(SDNode *N); + + // Operand Float to Integer Conversion. + bool SoftenFloatOperand(SDNode *N, unsigned OpNo); + SDValue SoftenFloatOp_BIT_CONVERT(SDNode *N); + SDValue SoftenFloatOp_BR_CC(SDNode *N); + SDValue SoftenFloatOp_FP_ROUND(SDNode *N); + SDValue SoftenFloatOp_FP_TO_SINT(SDNode *N); + SDValue SoftenFloatOp_FP_TO_UINT(SDNode *N); + SDValue SoftenFloatOp_SELECT_CC(SDNode *N); + SDValue SoftenFloatOp_SETCC(SDNode *N); + SDValue SoftenFloatOp_STORE(SDNode *N, unsigned OpNo); + + void SoftenSetCCOperands(SDValue &NewLHS, SDValue &NewRHS, + ISD::CondCode &CCCode, DebugLoc dl); + + //===--------------------------------------------------------------------===// + // Float Expansion Support: LegalizeFloatTypes.cpp + //===--------------------------------------------------------------------===// + + /// GetExpandedFloat - Given a processed operand Op which was expanded into + /// two floating point values of half the size, this returns the two halves. + /// The low bits of Op are exactly equal to the bits of Lo; the high bits + /// exactly equal Hi. For example, if Op is a ppcf128 which was expanded + /// into two f64's, then this method returns the two f64's, with Lo being + /// equal to the lower 64 bits of Op, and Hi to the upper 64 bits. + void GetExpandedFloat(SDValue Op, SDValue &Lo, SDValue &Hi); + void SetExpandedFloat(SDValue Op, SDValue Lo, SDValue Hi); + + // Float Result Expansion. + void ExpandFloatResult(SDNode *N, unsigned ResNo); + void ExpandFloatRes_ConstantFP(SDNode *N, SDValue &Lo, SDValue &Hi); + void ExpandFloatRes_FABS (SDNode *N, SDValue &Lo, SDValue &Hi); + void ExpandFloatRes_FADD (SDNode *N, SDValue &Lo, SDValue &Hi); + void ExpandFloatRes_FCEIL (SDNode *N, SDValue &Lo, SDValue &Hi); + void ExpandFloatRes_FCOS (SDNode *N, SDValue &Lo, SDValue &Hi); + void ExpandFloatRes_FDIV (SDNode *N, SDValue &Lo, SDValue &Hi); + void ExpandFloatRes_FEXP (SDNode *N, SDValue &Lo, SDValue &Hi); + void ExpandFloatRes_FEXP2 (SDNode *N, SDValue &Lo, SDValue &Hi); + void ExpandFloatRes_FFLOOR (SDNode *N, SDValue &Lo, SDValue &Hi); + void ExpandFloatRes_FLOG (SDNode *N, SDValue &Lo, SDValue &Hi); + void ExpandFloatRes_FLOG2 (SDNode *N, SDValue &Lo, SDValue &Hi); + void ExpandFloatRes_FLOG10 (SDNode *N, SDValue &Lo, SDValue &Hi); + void ExpandFloatRes_FMUL (SDNode *N, SDValue &Lo, SDValue &Hi); + void ExpandFloatRes_FNEARBYINT(SDNode *N, SDValue &Lo, SDValue &Hi); + void ExpandFloatRes_FNEG (SDNode *N, SDValue &Lo, SDValue &Hi); + void ExpandFloatRes_FP_EXTEND (SDNode *N, SDValue &Lo, SDValue &Hi); + void ExpandFloatRes_FPOW (SDNode *N, SDValue &Lo, SDValue &Hi); + void ExpandFloatRes_FPOWI (SDNode *N, SDValue &Lo, SDValue &Hi); + void ExpandFloatRes_FRINT (SDNode *N, SDValue &Lo, SDValue &Hi); + void ExpandFloatRes_FSIN (SDNode *N, SDValue &Lo, SDValue &Hi); + void ExpandFloatRes_FSQRT (SDNode *N, SDValue &Lo, SDValue &Hi); + void ExpandFloatRes_FSUB (SDNode *N, SDValue &Lo, SDValue &Hi); + void ExpandFloatRes_FTRUNC (SDNode *N, SDValue &Lo, SDValue &Hi); + void ExpandFloatRes_LOAD (SDNode *N, SDValue &Lo, SDValue &Hi); + void ExpandFloatRes_XINT_TO_FP(SDNode *N, SDValue &Lo, SDValue &Hi); + + // Float Operand Expansion. + bool ExpandFloatOperand(SDNode *N, unsigned OperandNo); + SDValue ExpandFloatOp_BR_CC(SDNode *N); + SDValue ExpandFloatOp_FP_ROUND(SDNode *N); + SDValue ExpandFloatOp_FP_TO_SINT(SDNode *N); + SDValue ExpandFloatOp_FP_TO_UINT(SDNode *N); + SDValue ExpandFloatOp_SELECT_CC(SDNode *N); + SDValue ExpandFloatOp_SETCC(SDNode *N); + SDValue ExpandFloatOp_STORE(SDNode *N, unsigned OpNo); + + void FloatExpandSetCCOperands(SDValue &NewLHS, SDValue &NewRHS, + ISD::CondCode &CCCode, DebugLoc dl); + + //===--------------------------------------------------------------------===// + // Scalarization Support: LegalizeVectorTypes.cpp + //===--------------------------------------------------------------------===// + + /// GetScalarizedVector - Given a processed one-element vector Op which was + /// scalarized to its element type, this returns the element. For example, + /// if Op is a v1i32, Op = < i32 val >, this method returns val, an i32. + SDValue GetScalarizedVector(SDValue Op) { + SDValue &ScalarizedOp = ScalarizedVectors[Op]; + RemapValue(ScalarizedOp); + assert(ScalarizedOp.getNode() && "Operand wasn't scalarized?"); + return ScalarizedOp; + } + void SetScalarizedVector(SDValue Op, SDValue Result); + + // Vector Result Scalarization: <1 x ty> -> ty. + void ScalarizeVectorResult(SDNode *N, unsigned OpNo); + SDValue ScalarizeVecRes_BinOp(SDNode *N); + SDValue ScalarizeVecRes_UnaryOp(SDNode *N); + + SDValue ScalarizeVecRes_BIT_CONVERT(SDNode *N); + SDValue ScalarizeVecRes_CONVERT_RNDSAT(SDNode *N); + SDValue ScalarizeVecRes_EXTRACT_SUBVECTOR(SDNode *N); + SDValue ScalarizeVecRes_FPOWI(SDNode *N); + SDValue ScalarizeVecRes_INSERT_VECTOR_ELT(SDNode *N); + SDValue ScalarizeVecRes_LOAD(LoadSDNode *N); + SDValue ScalarizeVecRes_SCALAR_TO_VECTOR(SDNode *N); + SDValue ScalarizeVecRes_SELECT(SDNode *N); + SDValue ScalarizeVecRes_SELECT_CC(SDNode *N); + SDValue ScalarizeVecRes_SETCC(SDNode *N); + SDValue ScalarizeVecRes_UNDEF(SDNode *N); + SDValue ScalarizeVecRes_VECTOR_SHUFFLE(SDNode *N); + SDValue ScalarizeVecRes_VSETCC(SDNode *N); + + // Vector Operand Scalarization: <1 x ty> -> ty. + bool ScalarizeVectorOperand(SDNode *N, unsigned OpNo); + SDValue ScalarizeVecOp_BIT_CONVERT(SDNode *N); + SDValue ScalarizeVecOp_CONCAT_VECTORS(SDNode *N); + SDValue ScalarizeVecOp_EXTRACT_VECTOR_ELT(SDNode *N); + SDValue ScalarizeVecOp_STORE(StoreSDNode *N, unsigned OpNo); + + //===--------------------------------------------------------------------===// + // Vector Splitting Support: LegalizeVectorTypes.cpp + //===--------------------------------------------------------------------===// + + /// GetSplitVector - Given a processed vector Op which was split into vectors + /// of half the size, this method returns the halves. The first elements of + /// Op coincide with the elements of Lo; the remaining elements of Op coincide + /// with the elements of Hi: Op is what you would get by concatenating Lo and + /// Hi. For example, if Op is a v8i32 that was split into two v4i32's, then + /// this method returns the two v4i32's, with Lo corresponding to the first 4 + /// elements of Op, and Hi to the last 4 elements. + void GetSplitVector(SDValue Op, SDValue &Lo, SDValue &Hi); + void SetSplitVector(SDValue Op, SDValue Lo, SDValue Hi); + + // Vector Result Splitting: <128 x ty> -> 2 x <64 x ty>. + void SplitVectorResult(SDNode *N, unsigned OpNo); + void SplitVecRes_BinOp(SDNode *N, SDValue &Lo, SDValue &Hi); + void SplitVecRes_UnaryOp(SDNode *N, SDValue &Lo, SDValue &Hi); + + void SplitVecRes_BIT_CONVERT(SDNode *N, SDValue &Lo, SDValue &Hi); + void SplitVecRes_BUILD_PAIR(SDNode *N, SDValue &Lo, SDValue &Hi); + void SplitVecRes_BUILD_VECTOR(SDNode *N, SDValue &Lo, SDValue &Hi); + void SplitVecRes_CONCAT_VECTORS(SDNode *N, SDValue &Lo, SDValue &Hi); + void SplitVecRes_CONVERT_RNDSAT(SDNode *N, SDValue &Lo, SDValue &Hi); + void SplitVecRes_EXTRACT_SUBVECTOR(SDNode *N, SDValue &Lo, SDValue &Hi); + void SplitVecRes_FPOWI(SDNode *N, SDValue &Lo, SDValue &Hi); + void SplitVecRes_INSERT_VECTOR_ELT(SDNode *N, SDValue &Lo, SDValue &Hi); + void SplitVecRes_LOAD(LoadSDNode *N, SDValue &Lo, SDValue &Hi); + void SplitVecRes_SCALAR_TO_VECTOR(SDNode *N, SDValue &Lo, SDValue &Hi); + void SplitVecRes_SETCC(SDNode *N, SDValue &Lo, SDValue &Hi); + void SplitVecRes_UNDEF(SDNode *N, SDValue &Lo, SDValue &Hi); + void SplitVecRes_VECTOR_SHUFFLE(ShuffleVectorSDNode *N, SDValue &Lo, + SDValue &Hi); + + // Vector Operand Splitting: <128 x ty> -> 2 x <64 x ty>. + bool SplitVectorOperand(SDNode *N, unsigned OpNo); + SDValue SplitVecOp_UnaryOp(SDNode *N); + + SDValue SplitVecOp_BIT_CONVERT(SDNode *N); + SDValue SplitVecOp_EXTRACT_SUBVECTOR(SDNode *N); + SDValue SplitVecOp_EXTRACT_VECTOR_ELT(SDNode *N); + SDValue SplitVecOp_STORE(StoreSDNode *N, unsigned OpNo); + + //===--------------------------------------------------------------------===// + // Vector Widening Support: LegalizeVectorTypes.cpp + //===--------------------------------------------------------------------===// + + /// GetWidenedVector - Given a processed vector Op which was widened into a + /// larger vector, this method returns the larger vector. The elements of + /// the returned vector consist of the elements of Op followed by elements + /// containing rubbish. For example, if Op is a v2i32 that was widened to a + /// v4i32, then this method returns a v4i32 for which the first two elements + /// are the same as those of Op, while the last two elements contain rubbish. + SDValue GetWidenedVector(SDValue Op) { + SDValue &WidenedOp = WidenedVectors[Op]; + RemapValue(WidenedOp); + assert(WidenedOp.getNode() && "Operand wasn't widened?"); + return WidenedOp; + } + void SetWidenedVector(SDValue Op, SDValue Result); + + // Widen Vector Result Promotion. + void WidenVectorResult(SDNode *N, unsigned ResNo); + SDValue WidenVecRes_BIT_CONVERT(SDNode* N); + SDValue WidenVecRes_BUILD_VECTOR(SDNode* N); + SDValue WidenVecRes_CONCAT_VECTORS(SDNode* N); + SDValue WidenVecRes_CONVERT_RNDSAT(SDNode* N); + SDValue WidenVecRes_EXTRACT_SUBVECTOR(SDNode* N); + SDValue WidenVecRes_INSERT_VECTOR_ELT(SDNode* N); + SDValue WidenVecRes_LOAD(SDNode* N); + SDValue WidenVecRes_SCALAR_TO_VECTOR(SDNode* N); + SDValue WidenVecRes_SELECT(SDNode* N); + SDValue WidenVecRes_SELECT_CC(SDNode* N); + SDValue WidenVecRes_UNDEF(SDNode *N); + SDValue WidenVecRes_VECTOR_SHUFFLE(ShuffleVectorSDNode *N); + SDValue WidenVecRes_VSETCC(SDNode* N); + + SDValue WidenVecRes_Binary(SDNode *N); + SDValue WidenVecRes_Convert(SDNode *N); + SDValue WidenVecRes_Shift(SDNode *N); + SDValue WidenVecRes_Unary(SDNode *N); + + // Widen Vector Operand. + bool WidenVectorOperand(SDNode *N, unsigned ResNo); + SDValue WidenVecOp_BIT_CONVERT(SDNode *N); + SDValue WidenVecOp_CONCAT_VECTORS(SDNode *N); + SDValue WidenVecOp_EXTRACT_VECTOR_ELT(SDNode *N); + SDValue WidenVecOp_EXTRACT_SUBVECTOR(SDNode *N); + SDValue WidenVecOp_STORE(SDNode* N); + + SDValue WidenVecOp_Convert(SDNode *N); + + //===--------------------------------------------------------------------===// + // Vector Widening Utilities Support: LegalizeVectorTypes.cpp + //===--------------------------------------------------------------------===// + + /// Helper genWidenVectorLoads - Helper function to generate a set of + /// loads to load a vector with a resulting wider type. It takes + /// ExtType: Extension type + /// LdChain: list of chains for the load we have generated. + /// Chain: incoming chain for the ld vector. + /// BasePtr: base pointer to load from. + /// SV: memory disambiguation source value. + /// SVOffset: memory disambiugation offset. + /// Alignment: alignment of the memory. + /// isVolatile: volatile load. + /// LdWidth: width of memory that we want to load. + /// ResType: the wider result result type for the resulting vector. + /// dl: DebugLoc to be applied to new nodes + SDValue GenWidenVectorLoads(SmallVector& LdChain, SDValue Chain, + SDValue BasePtr, const Value *SV, + int SVOffset, unsigned Alignment, + bool isVolatile, unsigned LdWidth, + EVT ResType, DebugLoc dl); + + /// Helper genWidenVectorStores - Helper function to generate a set of + /// stores to store a widen vector into non widen memory + /// It takes + /// StChain: list of chains for the stores we have generated + /// Chain: incoming chain for the ld vector + /// BasePtr: base pointer to load from + /// SV: memory disambiguation source value + /// SVOffset: memory disambiugation offset + /// Alignment: alignment of the memory + /// isVolatile: volatile lod + /// ValOp: value to store + /// StWidth: width of memory that we want to store + /// dl: DebugLoc to be applied to new nodes + void GenWidenVectorStores(SmallVector& StChain, SDValue Chain, + SDValue BasePtr, const Value *SV, + int SVOffset, unsigned Alignment, + bool isVolatile, SDValue ValOp, + unsigned StWidth, DebugLoc dl); + + /// Modifies a vector input (widen or narrows) to a vector of NVT. The + /// input vector must have the same element type as NVT. + SDValue ModifyToType(SDValue InOp, EVT WidenVT); + + + //===--------------------------------------------------------------------===// + // Generic Splitting: LegalizeTypesGeneric.cpp + //===--------------------------------------------------------------------===// + + // Legalization methods which only use that the illegal type is split into two + // not necessarily identical types. As such they can be used for splitting + // vectors and expanding integers and floats. + + void GetSplitOp(SDValue Op, SDValue &Lo, SDValue &Hi) { + if (Op.getValueType().isVector()) + GetSplitVector(Op, Lo, Hi); + else if (Op.getValueType().isInteger()) + GetExpandedInteger(Op, Lo, Hi); + else + GetExpandedFloat(Op, Lo, Hi); + } + + /// GetSplitDestVTs - Compute the VTs needed for the low/hi parts of a type + /// which is split (or expanded) into two not necessarily identical pieces. + void GetSplitDestVTs(EVT InVT, EVT &LoVT, EVT &HiVT); + + /// GetPairElements - Use ISD::EXTRACT_ELEMENT nodes to extract the low and + /// high parts of the given value. + void GetPairElements(SDValue Pair, SDValue &Lo, SDValue &Hi); + + // Generic Result Splitting. + void SplitRes_MERGE_VALUES(SDNode *N, SDValue &Lo, SDValue &Hi); + void SplitRes_SELECT (SDNode *N, SDValue &Lo, SDValue &Hi); + void SplitRes_SELECT_CC (SDNode *N, SDValue &Lo, SDValue &Hi); + void SplitRes_UNDEF (SDNode *N, SDValue &Lo, SDValue &Hi); + + //===--------------------------------------------------------------------===// + // Generic Expansion: LegalizeTypesGeneric.cpp + //===--------------------------------------------------------------------===// + + // Legalization methods which only use that the illegal type is split into two + // identical types of half the size, and that the Lo/Hi part is stored first + // in memory on little/big-endian machines, followed by the Hi/Lo part. As + // such they can be used for expanding integers and floats. + + void GetExpandedOp(SDValue Op, SDValue &Lo, SDValue &Hi) { + if (Op.getValueType().isInteger()) + GetExpandedInteger(Op, Lo, Hi); + else + GetExpandedFloat(Op, Lo, Hi); + } + + // Generic Result Expansion. + void ExpandRes_BIT_CONVERT (SDNode *N, SDValue &Lo, SDValue &Hi); + void ExpandRes_BUILD_PAIR (SDNode *N, SDValue &Lo, SDValue &Hi); + void ExpandRes_EXTRACT_ELEMENT (SDNode *N, SDValue &Lo, SDValue &Hi); + void ExpandRes_EXTRACT_VECTOR_ELT(SDNode *N, SDValue &Lo, SDValue &Hi); + void ExpandRes_NormalLoad (SDNode *N, SDValue &Lo, SDValue &Hi); + void ExpandRes_VAARG (SDNode *N, SDValue &Lo, SDValue &Hi); + + // Generic Operand Expansion. + SDValue ExpandOp_BIT_CONVERT (SDNode *N); + SDValue ExpandOp_BUILD_VECTOR (SDNode *N); + SDValue ExpandOp_EXTRACT_ELEMENT (SDNode *N); + SDValue ExpandOp_INSERT_VECTOR_ELT(SDNode *N); + SDValue ExpandOp_SCALAR_TO_VECTOR (SDNode *N); + SDValue ExpandOp_NormalStore (SDNode *N, unsigned OpNo); +}; + +} // end namespace llvm. + +#endif diff --git a/libclamav/c++/llvm/lib/CodeGen/SelectionDAG/LegalizeTypesGeneric.cpp b/libclamav/c++/llvm/lib/CodeGen/SelectionDAG/LegalizeTypesGeneric.cpp new file mode 100644 index 000000000..dbd3e39b5 --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/SelectionDAG/LegalizeTypesGeneric.cpp @@ -0,0 +1,471 @@ +//===-------- LegalizeTypesGeneric.cpp - Generic type legalization --------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements generic type expansion and splitting for LegalizeTypes. +// The routines here perform legalization when the details of the type (such as +// whether it is an integer or a float) do not matter. +// Expansion is the act of changing a computation in an illegal type to be a +// computation in two identical registers of a smaller type. The Lo/Hi part +// is required to be stored first in memory on little/big-endian machines. +// Splitting is the act of changing a computation in an illegal type to be a +// computation in two not necessarily identical registers of a smaller type. +// There are no requirements on how the type is represented in memory. +// +//===----------------------------------------------------------------------===// + +#include "LegalizeTypes.h" +#include "llvm/Target/TargetData.h" +#include "llvm/CodeGen/PseudoSourceValue.h" +using namespace llvm; + +//===----------------------------------------------------------------------===// +// Generic Result Expansion. +//===----------------------------------------------------------------------===// + +// These routines assume that the Lo/Hi part is stored first in memory on +// little/big-endian machines, followed by the Hi/Lo part. This means that +// they cannot be used as is on vectors, for which Lo is always stored first. + +void DAGTypeLegalizer::ExpandRes_BIT_CONVERT(SDNode *N, SDValue &Lo, + SDValue &Hi) { + EVT OutVT = N->getValueType(0); + EVT NOutVT = TLI.getTypeToTransformTo(*DAG.getContext(), OutVT); + SDValue InOp = N->getOperand(0); + EVT InVT = InOp.getValueType(); + DebugLoc dl = N->getDebugLoc(); + + // Handle some special cases efficiently. + switch (getTypeAction(InVT)) { + default: + assert(false && "Unknown type action!"); + case Legal: + case PromoteInteger: + break; + case SoftenFloat: + // Convert the integer operand instead. + SplitInteger(GetSoftenedFloat(InOp), Lo, Hi); + Lo = DAG.getNode(ISD::BIT_CONVERT, dl, NOutVT, Lo); + Hi = DAG.getNode(ISD::BIT_CONVERT, dl, NOutVT, Hi); + return; + case ExpandInteger: + case ExpandFloat: + // Convert the expanded pieces of the input. + GetExpandedOp(InOp, Lo, Hi); + Lo = DAG.getNode(ISD::BIT_CONVERT, dl, NOutVT, Lo); + Hi = DAG.getNode(ISD::BIT_CONVERT, dl, NOutVT, Hi); + return; + case SplitVector: + GetSplitVector(InOp, Lo, Hi); + if (TLI.isBigEndian()) + std::swap(Lo, Hi); + Lo = DAG.getNode(ISD::BIT_CONVERT, dl, NOutVT, Lo); + Hi = DAG.getNode(ISD::BIT_CONVERT, dl, NOutVT, Hi); + return; + case ScalarizeVector: + // Convert the element instead. + SplitInteger(BitConvertToInteger(GetScalarizedVector(InOp)), Lo, Hi); + Lo = DAG.getNode(ISD::BIT_CONVERT, dl, NOutVT, Lo); + Hi = DAG.getNode(ISD::BIT_CONVERT, dl, NOutVT, Hi); + return; + case WidenVector: { + assert(!(InVT.getVectorNumElements() & 1) && "Unsupported BIT_CONVERT"); + InOp = GetWidenedVector(InOp); + EVT InNVT = EVT::getVectorVT(*DAG.getContext(), InVT.getVectorElementType(), + InVT.getVectorNumElements()/2); + Lo = DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, InNVT, InOp, + DAG.getIntPtrConstant(0)); + Hi = DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, InNVT, InOp, + DAG.getIntPtrConstant(InNVT.getVectorNumElements())); + if (TLI.isBigEndian()) + std::swap(Lo, Hi); + Lo = DAG.getNode(ISD::BIT_CONVERT, dl, NOutVT, Lo); + Hi = DAG.getNode(ISD::BIT_CONVERT, dl, NOutVT, Hi); + return; + } + } + + if (InVT.isVector() && OutVT.isInteger()) { + // Handle cases like i64 = BIT_CONVERT v1i64 on x86, where the operand + // is legal but the result is not. + EVT NVT = EVT::getVectorVT(*DAG.getContext(), NOutVT, 2); + + if (isTypeLegal(NVT)) { + SDValue CastInOp = DAG.getNode(ISD::BIT_CONVERT, dl, NVT, InOp); + Lo = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, NOutVT, CastInOp, + DAG.getIntPtrConstant(0)); + Hi = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, NOutVT, CastInOp, + DAG.getIntPtrConstant(1)); + + if (TLI.isBigEndian()) + std::swap(Lo, Hi); + + return; + } + } + + // Lower the bit-convert to a store/load from the stack. + assert(NOutVT.isByteSized() && "Expanded type not byte sized!"); + + // Create the stack frame object. Make sure it is aligned for both + // the source and expanded destination types. + unsigned Alignment = + TLI.getTargetData()->getPrefTypeAlignment(NOutVT. + getTypeForEVT(*DAG.getContext())); + SDValue StackPtr = DAG.CreateStackTemporary(InVT, Alignment); + int SPFI = cast(StackPtr.getNode())->getIndex(); + const Value *SV = PseudoSourceValue::getFixedStack(SPFI); + + // Emit a store to the stack slot. + SDValue Store = DAG.getStore(DAG.getEntryNode(), dl, InOp, StackPtr, SV, 0); + + // Load the first half from the stack slot. + Lo = DAG.getLoad(NOutVT, dl, Store, StackPtr, SV, 0); + + // Increment the pointer to the other half. + unsigned IncrementSize = NOutVT.getSizeInBits() / 8; + StackPtr = DAG.getNode(ISD::ADD, dl, StackPtr.getValueType(), StackPtr, + DAG.getIntPtrConstant(IncrementSize)); + + // Load the second half from the stack slot. + Hi = DAG.getLoad(NOutVT, dl, Store, StackPtr, SV, IncrementSize, false, + MinAlign(Alignment, IncrementSize)); + + // Handle endianness of the load. + if (TLI.isBigEndian()) + std::swap(Lo, Hi); +} + +void DAGTypeLegalizer::ExpandRes_BUILD_PAIR(SDNode *N, SDValue &Lo, + SDValue &Hi) { + // Return the operands. + Lo = N->getOperand(0); + Hi = N->getOperand(1); +} + +void DAGTypeLegalizer::ExpandRes_EXTRACT_ELEMENT(SDNode *N, SDValue &Lo, + SDValue &Hi) { + GetExpandedOp(N->getOperand(0), Lo, Hi); + SDValue Part = cast(N->getOperand(1))->getZExtValue() ? + Hi : Lo; + + assert(Part.getValueType() == N->getValueType(0) && + "Type twice as big as expanded type not itself expanded!"); + + GetPairElements(Part, Lo, Hi); +} + +void DAGTypeLegalizer::ExpandRes_EXTRACT_VECTOR_ELT(SDNode *N, SDValue &Lo, + SDValue &Hi) { + SDValue OldVec = N->getOperand(0); + unsigned OldElts = OldVec.getValueType().getVectorNumElements(); + DebugLoc dl = N->getDebugLoc(); + + // Convert to a vector of the expanded element type, for example + // <3 x i64> -> <6 x i32>. + EVT OldVT = N->getValueType(0); + EVT NewVT = TLI.getTypeToTransformTo(*DAG.getContext(), OldVT); + + SDValue NewVec = DAG.getNode(ISD::BIT_CONVERT, dl, + EVT::getVectorVT(*DAG.getContext(), NewVT, 2*OldElts), + OldVec); + + // Extract the elements at 2 * Idx and 2 * Idx + 1 from the new vector. + SDValue Idx = N->getOperand(1); + + // Make sure the type of Idx is big enough to hold the new values. + if (Idx.getValueType().bitsLT(TLI.getPointerTy())) + Idx = DAG.getNode(ISD::ZERO_EXTEND, dl, TLI.getPointerTy(), Idx); + + Idx = DAG.getNode(ISD::ADD, dl, Idx.getValueType(), Idx, Idx); + Lo = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, NewVT, NewVec, Idx); + + Idx = DAG.getNode(ISD::ADD, dl, Idx.getValueType(), Idx, + DAG.getConstant(1, Idx.getValueType())); + Hi = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, NewVT, NewVec, Idx); + + if (TLI.isBigEndian()) + std::swap(Lo, Hi); +} + +void DAGTypeLegalizer::ExpandRes_NormalLoad(SDNode *N, SDValue &Lo, + SDValue &Hi) { + assert(ISD::isNormalLoad(N) && "This routine only for normal loads!"); + DebugLoc dl = N->getDebugLoc(); + + LoadSDNode *LD = cast(N); + EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), LD->getValueType(0)); + SDValue Chain = LD->getChain(); + SDValue Ptr = LD->getBasePtr(); + int SVOffset = LD->getSrcValueOffset(); + unsigned Alignment = LD->getAlignment(); + bool isVolatile = LD->isVolatile(); + + assert(NVT.isByteSized() && "Expanded type not byte sized!"); + + Lo = DAG.getLoad(NVT, dl, Chain, Ptr, LD->getSrcValue(), SVOffset, + isVolatile, Alignment); + + // Increment the pointer to the other half. + unsigned IncrementSize = NVT.getSizeInBits() / 8; + Ptr = DAG.getNode(ISD::ADD, dl, Ptr.getValueType(), Ptr, + DAG.getIntPtrConstant(IncrementSize)); + Hi = DAG.getLoad(NVT, dl, Chain, Ptr, LD->getSrcValue(), + SVOffset+IncrementSize, + isVolatile, MinAlign(Alignment, IncrementSize)); + + // Build a factor node to remember that this load is independent of the + // other one. + Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Lo.getValue(1), + Hi.getValue(1)); + + // Handle endianness of the load. + if (TLI.isBigEndian()) + std::swap(Lo, Hi); + + // Modified the chain - switch anything that used the old chain to use + // the new one. + ReplaceValueWith(SDValue(N, 1), Chain); +} + +void DAGTypeLegalizer::ExpandRes_VAARG(SDNode *N, SDValue &Lo, SDValue &Hi) { + EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); + SDValue Chain = N->getOperand(0); + SDValue Ptr = N->getOperand(1); + DebugLoc dl = N->getDebugLoc(); + + Lo = DAG.getVAArg(NVT, dl, Chain, Ptr, N->getOperand(2)); + Hi = DAG.getVAArg(NVT, dl, Lo.getValue(1), Ptr, N->getOperand(2)); + + // Handle endianness of the load. + if (TLI.isBigEndian()) + std::swap(Lo, Hi); + + // Modified the chain - switch anything that used the old chain to use + // the new one. + ReplaceValueWith(SDValue(N, 1), Hi.getValue(1)); +} + + +//===--------------------------------------------------------------------===// +// Generic Operand Expansion. +//===--------------------------------------------------------------------===// + +SDValue DAGTypeLegalizer::ExpandOp_BIT_CONVERT(SDNode *N) { + DebugLoc dl = N->getDebugLoc(); + if (N->getValueType(0).isVector()) { + // An illegal expanding type is being converted to a legal vector type. + // Make a two element vector out of the expanded parts and convert that + // instead, but only if the new vector type is legal (otherwise there + // is no point, and it might create expansion loops). For example, on + // x86 this turns v1i64 = BIT_CONVERT i64 into v1i64 = BIT_CONVERT v2i32. + EVT OVT = N->getOperand(0).getValueType(); + EVT NVT = EVT::getVectorVT(*DAG.getContext(), TLI.getTypeToTransformTo(*DAG.getContext(), OVT), 2); + + if (isTypeLegal(NVT)) { + SDValue Parts[2]; + GetExpandedOp(N->getOperand(0), Parts[0], Parts[1]); + + if (TLI.isBigEndian()) + std::swap(Parts[0], Parts[1]); + + SDValue Vec = DAG.getNode(ISD::BUILD_VECTOR, dl, NVT, Parts, 2); + return DAG.getNode(ISD::BIT_CONVERT, dl, N->getValueType(0), Vec); + } + } + + // Otherwise, store to a temporary and load out again as the new type. + return CreateStackStoreLoad(N->getOperand(0), N->getValueType(0)); +} + +SDValue DAGTypeLegalizer::ExpandOp_BUILD_VECTOR(SDNode *N) { + // The vector type is legal but the element type needs expansion. + EVT VecVT = N->getValueType(0); + unsigned NumElts = VecVT.getVectorNumElements(); + EVT OldVT = N->getOperand(0).getValueType(); + EVT NewVT = TLI.getTypeToTransformTo(*DAG.getContext(), OldVT); + DebugLoc dl = N->getDebugLoc(); + + assert(OldVT == VecVT.getVectorElementType() && + "BUILD_VECTOR operand type doesn't match vector element type!"); + + // Build a vector of twice the length out of the expanded elements. + // For example <3 x i64> -> <6 x i32>. + std::vector NewElts; + NewElts.reserve(NumElts*2); + + for (unsigned i = 0; i < NumElts; ++i) { + SDValue Lo, Hi; + GetExpandedOp(N->getOperand(i), Lo, Hi); + if (TLI.isBigEndian()) + std::swap(Lo, Hi); + NewElts.push_back(Lo); + NewElts.push_back(Hi); + } + + SDValue NewVec = DAG.getNode(ISD::BUILD_VECTOR, dl, + EVT::getVectorVT(*DAG.getContext(), NewVT, NewElts.size()), + &NewElts[0], NewElts.size()); + + // Convert the new vector to the old vector type. + return DAG.getNode(ISD::BIT_CONVERT, dl, VecVT, NewVec); +} + +SDValue DAGTypeLegalizer::ExpandOp_EXTRACT_ELEMENT(SDNode *N) { + SDValue Lo, Hi; + GetExpandedOp(N->getOperand(0), Lo, Hi); + return cast(N->getOperand(1))->getZExtValue() ? Hi : Lo; +} + +SDValue DAGTypeLegalizer::ExpandOp_INSERT_VECTOR_ELT(SDNode *N) { + // The vector type is legal but the element type needs expansion. + EVT VecVT = N->getValueType(0); + unsigned NumElts = VecVT.getVectorNumElements(); + DebugLoc dl = N->getDebugLoc(); + + SDValue Val = N->getOperand(1); + EVT OldEVT = Val.getValueType(); + EVT NewEVT = TLI.getTypeToTransformTo(*DAG.getContext(), OldEVT); + + assert(OldEVT == VecVT.getVectorElementType() && + "Inserted element type doesn't match vector element type!"); + + // Bitconvert to a vector of twice the length with elements of the expanded + // type, insert the expanded vector elements, and then convert back. + EVT NewVecVT = EVT::getVectorVT(*DAG.getContext(), NewEVT, NumElts*2); + SDValue NewVec = DAG.getNode(ISD::BIT_CONVERT, dl, + NewVecVT, N->getOperand(0)); + + SDValue Lo, Hi; + GetExpandedOp(Val, Lo, Hi); + if (TLI.isBigEndian()) + std::swap(Lo, Hi); + + SDValue Idx = N->getOperand(2); + Idx = DAG.getNode(ISD::ADD, dl, Idx.getValueType(), Idx, Idx); + NewVec = DAG.getNode(ISD::INSERT_VECTOR_ELT, dl, NewVecVT, NewVec, Lo, Idx); + Idx = DAG.getNode(ISD::ADD, dl, + Idx.getValueType(), Idx, DAG.getIntPtrConstant(1)); + NewVec = DAG.getNode(ISD::INSERT_VECTOR_ELT, dl, NewVecVT, NewVec, Hi, Idx); + + // Convert the new vector to the old vector type. + return DAG.getNode(ISD::BIT_CONVERT, dl, VecVT, NewVec); +} + +SDValue DAGTypeLegalizer::ExpandOp_SCALAR_TO_VECTOR(SDNode *N) { + DebugLoc dl = N->getDebugLoc(); + EVT VT = N->getValueType(0); + assert(VT.getVectorElementType() == N->getOperand(0).getValueType() && + "SCALAR_TO_VECTOR operand type doesn't match vector element type!"); + unsigned NumElts = VT.getVectorNumElements(); + SmallVector Ops(NumElts); + Ops[0] = N->getOperand(0); + SDValue UndefVal = DAG.getUNDEF(Ops[0].getValueType()); + for (unsigned i = 1; i < NumElts; ++i) + Ops[i] = UndefVal; + return DAG.getNode(ISD::BUILD_VECTOR, dl, VT, &Ops[0], NumElts); +} + +SDValue DAGTypeLegalizer::ExpandOp_NormalStore(SDNode *N, unsigned OpNo) { + assert(ISD::isNormalStore(N) && "This routine only for normal stores!"); + assert(OpNo == 1 && "Can only expand the stored value so far"); + DebugLoc dl = N->getDebugLoc(); + + StoreSDNode *St = cast(N); + EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), St->getValue().getValueType()); + SDValue Chain = St->getChain(); + SDValue Ptr = St->getBasePtr(); + int SVOffset = St->getSrcValueOffset(); + unsigned Alignment = St->getAlignment(); + bool isVolatile = St->isVolatile(); + + assert(NVT.isByteSized() && "Expanded type not byte sized!"); + unsigned IncrementSize = NVT.getSizeInBits() / 8; + + SDValue Lo, Hi; + GetExpandedOp(St->getValue(), Lo, Hi); + + if (TLI.isBigEndian()) + std::swap(Lo, Hi); + + Lo = DAG.getStore(Chain, dl, Lo, Ptr, St->getSrcValue(), SVOffset, + isVolatile, Alignment); + + Ptr = DAG.getNode(ISD::ADD, dl, Ptr.getValueType(), Ptr, + DAG.getIntPtrConstant(IncrementSize)); + assert(isTypeLegal(Ptr.getValueType()) && "Pointers must be legal!"); + Hi = DAG.getStore(Chain, dl, Hi, Ptr, St->getSrcValue(), + SVOffset + IncrementSize, + isVolatile, MinAlign(Alignment, IncrementSize)); + + return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Lo, Hi); +} + + +//===--------------------------------------------------------------------===// +// Generic Result Splitting. +//===--------------------------------------------------------------------===// + +// Be careful to make no assumptions about which of Lo/Hi is stored first in +// memory (for vectors it is always Lo first followed by Hi in the following +// bytes; for integers and floats it is Lo first if and only if the machine is +// little-endian). + +void DAGTypeLegalizer::SplitRes_MERGE_VALUES(SDNode *N, + SDValue &Lo, SDValue &Hi) { + // A MERGE_VALUES node can produce any number of values. We know that the + // first illegal one needs to be expanded into Lo/Hi. + unsigned i; + + // The string of legal results gets turned into input operands, which have + // the same type. + for (i = 0; isTypeLegal(N->getValueType(i)); ++i) + ReplaceValueWith(SDValue(N, i), SDValue(N->getOperand(i))); + + // The first illegal result must be the one that needs to be expanded. + GetSplitOp(N->getOperand(i), Lo, Hi); + + // Legalize the rest of the results into the input operands whether they are + // legal or not. + unsigned e = N->getNumValues(); + for (++i; i != e; ++i) + ReplaceValueWith(SDValue(N, i), SDValue(N->getOperand(i))); +} + +void DAGTypeLegalizer::SplitRes_SELECT(SDNode *N, SDValue &Lo, + SDValue &Hi) { + SDValue LL, LH, RL, RH; + DebugLoc dl = N->getDebugLoc(); + GetSplitOp(N->getOperand(1), LL, LH); + GetSplitOp(N->getOperand(2), RL, RH); + + SDValue Cond = N->getOperand(0); + Lo = DAG.getNode(ISD::SELECT, dl, LL.getValueType(), Cond, LL, RL); + Hi = DAG.getNode(ISD::SELECT, dl, LH.getValueType(), Cond, LH, RH); +} + +void DAGTypeLegalizer::SplitRes_SELECT_CC(SDNode *N, SDValue &Lo, + SDValue &Hi) { + SDValue LL, LH, RL, RH; + DebugLoc dl = N->getDebugLoc(); + GetSplitOp(N->getOperand(2), LL, LH); + GetSplitOp(N->getOperand(3), RL, RH); + + Lo = DAG.getNode(ISD::SELECT_CC, dl, LL.getValueType(), N->getOperand(0), + N->getOperand(1), LL, RL, N->getOperand(4)); + Hi = DAG.getNode(ISD::SELECT_CC, dl, LH.getValueType(), N->getOperand(0), + N->getOperand(1), LH, RH, N->getOperand(4)); +} + +void DAGTypeLegalizer::SplitRes_UNDEF(SDNode *N, SDValue &Lo, SDValue &Hi) { + EVT LoVT, HiVT; + DebugLoc dl = N->getDebugLoc(); + GetSplitDestVTs(N->getValueType(0), LoVT, HiVT); + Lo = DAG.getUNDEF(LoVT); + Hi = DAG.getUNDEF(HiVT); +} diff --git a/libclamav/c++/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorOps.cpp b/libclamav/c++/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorOps.cpp new file mode 100644 index 000000000..ca194305d --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorOps.cpp @@ -0,0 +1,339 @@ +//===-- LegalizeVectorOps.cpp - Implement SelectionDAG::LegalizeVectors ---===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the SelectionDAG::LegalizeVectors method. +// +// The vector legalizer looks for vector operations which might need to be +// scalarized and legalizes them. This is a separate step from Legalize because +// scalarizing can introduce illegal types. For example, suppose we have an +// ISD::SDIV of type v2i64 on x86-32. The type is legal (for example, addition +// on a v2i64 is legal), but ISD::SDIV isn't legal, so we have to unroll the +// operation, which introduces nodes with the illegal type i64 which must be +// expanded. Similarly, suppose we have an ISD::SRA of type v16i8 on PowerPC; +// the operation must be unrolled, which introduces nodes with the illegal +// type i8 which must be promoted. +// +// This does not legalize vector manipulations like ISD::BUILD_VECTOR, +// or operations that happen to take a vector which are custom-lowered; +// the legalization for such operations never produces nodes +// with illegal types, so it's okay to put off legalizing them until +// SelectionDAG::Legalize runs. +// +//===----------------------------------------------------------------------===// + +#include "llvm/CodeGen/SelectionDAG.h" +#include "llvm/Target/TargetLowering.h" +using namespace llvm; + +namespace { +class VectorLegalizer { + SelectionDAG& DAG; + TargetLowering& TLI; + bool Changed; // Keep track of whether anything changed + + /// LegalizedNodes - For nodes that are of legal width, and that have more + /// than one use, this map indicates what regularized operand to use. This + /// allows us to avoid legalizing the same thing more than once. + DenseMap LegalizedNodes; + + // Adds a node to the translation cache + void AddLegalizedOperand(SDValue From, SDValue To) { + LegalizedNodes.insert(std::make_pair(From, To)); + // If someone requests legalization of the new node, return itself. + if (From != To) + LegalizedNodes.insert(std::make_pair(To, To)); + } + + // Legalizes the given node + SDValue LegalizeOp(SDValue Op); + // Assuming the node is legal, "legalize" the results + SDValue TranslateLegalizeResults(SDValue Op, SDValue Result); + // Implements unrolling a generic vector operation, i.e. turning it into + // scalar operations. + SDValue UnrollVectorOp(SDValue Op); + // Implements unrolling a VSETCC. + SDValue UnrollVSETCC(SDValue Op); + // Implements expansion for FNEG; falls back to UnrollVectorOp if FSUB + // isn't legal. + SDValue ExpandFNEG(SDValue Op); + // Implements vector promotion; this is essentially just bitcasting the + // operands to a different type and bitcasting the result back to the + // original type. + SDValue PromoteVectorOp(SDValue Op); + + public: + bool Run(); + VectorLegalizer(SelectionDAG& dag) : + DAG(dag), TLI(dag.getTargetLoweringInfo()), Changed(false) {} +}; + +bool VectorLegalizer::Run() { + // The legalize process is inherently a bottom-up recursive process (users + // legalize their uses before themselves). Given infinite stack space, we + // could just start legalizing on the root and traverse the whole graph. In + // practice however, this causes us to run out of stack space on large basic + // blocks. To avoid this problem, compute an ordering of the nodes where each + // node is only legalized after all of its operands are legalized. + DAG.AssignTopologicalOrder(); + for (SelectionDAG::allnodes_iterator I = DAG.allnodes_begin(), + E = prior(DAG.allnodes_end()); I != next(E); ++I) + LegalizeOp(SDValue(I, 0)); + + // Finally, it's possible the root changed. Get the new root. + SDValue OldRoot = DAG.getRoot(); + assert(LegalizedNodes.count(OldRoot) && "Root didn't get legalized?"); + DAG.setRoot(LegalizedNodes[OldRoot]); + + LegalizedNodes.clear(); + + // Remove dead nodes now. + DAG.RemoveDeadNodes(); + + return Changed; +} + +SDValue VectorLegalizer::TranslateLegalizeResults(SDValue Op, SDValue Result) { + // Generic legalization: just pass the operand through. + for (unsigned i = 0, e = Op.getNode()->getNumValues(); i != e; ++i) + AddLegalizedOperand(Op.getValue(i), Result.getValue(i)); + return Result.getValue(Op.getResNo()); +} + +SDValue VectorLegalizer::LegalizeOp(SDValue Op) { + // Note that LegalizeOp may be reentered even from single-use nodes, which + // means that we always must cache transformed nodes. + DenseMap::iterator I = LegalizedNodes.find(Op); + if (I != LegalizedNodes.end()) return I->second; + + SDNode* Node = Op.getNode(); + + // Legalize the operands + SmallVector Ops; + for (unsigned i = 0, e = Node->getNumOperands(); i != e; ++i) + Ops.push_back(LegalizeOp(Node->getOperand(i))); + + SDValue Result = + DAG.UpdateNodeOperands(Op.getValue(0), Ops.data(), Ops.size()); + + bool HasVectorValue = false; + for (SDNode::value_iterator J = Node->value_begin(), E = Node->value_end(); + J != E; + ++J) + HasVectorValue |= J->isVector(); + if (!HasVectorValue) + return TranslateLegalizeResults(Op, Result); + + EVT QueryType; + switch (Op.getOpcode()) { + default: + return TranslateLegalizeResults(Op, Result); + case ISD::ADD: + case ISD::SUB: + case ISD::MUL: + case ISD::SDIV: + case ISD::UDIV: + case ISD::SREM: + case ISD::UREM: + case ISD::FADD: + case ISD::FSUB: + case ISD::FMUL: + case ISD::FDIV: + case ISD::FREM: + case ISD::AND: + case ISD::OR: + case ISD::XOR: + case ISD::SHL: + case ISD::SRA: + case ISD::SRL: + case ISD::ROTL: + case ISD::ROTR: + case ISD::CTTZ: + case ISD::CTLZ: + case ISD::CTPOP: + case ISD::SELECT: + case ISD::SELECT_CC: + case ISD::VSETCC: + case ISD::ZERO_EXTEND: + case ISD::ANY_EXTEND: + case ISD::TRUNCATE: + case ISD::SIGN_EXTEND: + case ISD::FP_TO_SINT: + case ISD::FP_TO_UINT: + case ISD::FNEG: + case ISD::FABS: + case ISD::FSQRT: + case ISD::FSIN: + case ISD::FCOS: + case ISD::FPOWI: + case ISD::FPOW: + case ISD::FLOG: + case ISD::FLOG2: + case ISD::FLOG10: + case ISD::FEXP: + case ISD::FEXP2: + case ISD::FCEIL: + case ISD::FTRUNC: + case ISD::FRINT: + case ISD::FNEARBYINT: + case ISD::FFLOOR: + QueryType = Node->getValueType(0); + break; + case ISD::SINT_TO_FP: + case ISD::UINT_TO_FP: + QueryType = Node->getOperand(0).getValueType(); + break; + } + + switch (TLI.getOperationAction(Node->getOpcode(), QueryType)) { + case TargetLowering::Promote: + // "Promote" the operation by bitcasting + Result = PromoteVectorOp(Op); + Changed = true; + break; + case TargetLowering::Legal: break; + case TargetLowering::Custom: { + SDValue Tmp1 = TLI.LowerOperation(Op, DAG); + if (Tmp1.getNode()) { + Result = Tmp1; + break; + } + // FALL THROUGH + } + case TargetLowering::Expand: + if (Node->getOpcode() == ISD::FNEG) + Result = ExpandFNEG(Op); + else if (Node->getOpcode() == ISD::VSETCC) + Result = UnrollVSETCC(Op); + else + Result = UnrollVectorOp(Op); + break; + } + + // Make sure that the generated code is itself legal. + if (Result != Op) { + Result = LegalizeOp(Result); + Changed = true; + } + + // Note that LegalizeOp may be reentered even from single-use nodes, which + // means that we always must cache transformed nodes. + AddLegalizedOperand(Op, Result); + return Result; +} + +SDValue VectorLegalizer::PromoteVectorOp(SDValue Op) { + // Vector "promotion" is basically just bitcasting and doing the operation + // in a different type. For example, x86 promotes ISD::AND on v2i32 to + // v1i64. + EVT VT = Op.getValueType(); + assert(Op.getNode()->getNumValues() == 1 && + "Can't promote a vector with multiple results!"); + EVT NVT = TLI.getTypeToPromoteTo(Op.getOpcode(), VT); + DebugLoc dl = Op.getDebugLoc(); + SmallVector Operands(Op.getNumOperands()); + + for (unsigned j = 0; j != Op.getNumOperands(); ++j) { + if (Op.getOperand(j).getValueType().isVector()) + Operands[j] = DAG.getNode(ISD::BIT_CONVERT, dl, NVT, Op.getOperand(j)); + else + Operands[j] = Op.getOperand(j); + } + + Op = DAG.getNode(Op.getOpcode(), dl, NVT, &Operands[0], Operands.size()); + + return DAG.getNode(ISD::BIT_CONVERT, dl, VT, Op); +} + +SDValue VectorLegalizer::ExpandFNEG(SDValue Op) { + if (TLI.isOperationLegalOrCustom(ISD::FSUB, Op.getValueType())) { + SDValue Zero = DAG.getConstantFP(-0.0, Op.getValueType()); + return DAG.getNode(ISD::FSUB, Op.getDebugLoc(), Op.getValueType(), + Zero, Op.getOperand(0)); + } + return UnrollVectorOp(Op); +} + +SDValue VectorLegalizer::UnrollVSETCC(SDValue Op) { + EVT VT = Op.getValueType(); + unsigned NumElems = VT.getVectorNumElements(); + EVT EltVT = VT.getVectorElementType(); + SDValue LHS = Op.getOperand(0), RHS = Op.getOperand(1), CC = Op.getOperand(2); + EVT TmpEltVT = LHS.getValueType().getVectorElementType(); + DebugLoc dl = Op.getDebugLoc(); + SmallVector Ops(NumElems); + for (unsigned i = 0; i < NumElems; ++i) { + SDValue LHSElem = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, TmpEltVT, LHS, + DAG.getIntPtrConstant(i)); + SDValue RHSElem = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, TmpEltVT, RHS, + DAG.getIntPtrConstant(i)); + Ops[i] = DAG.getNode(ISD::SETCC, dl, TLI.getSetCCResultType(TmpEltVT), + LHSElem, RHSElem, CC); + Ops[i] = DAG.getNode(ISD::SELECT, dl, EltVT, Ops[i], + DAG.getConstant(APInt::getAllOnesValue + (EltVT.getSizeInBits()), EltVT), + DAG.getConstant(0, EltVT)); + } + return DAG.getNode(ISD::BUILD_VECTOR, dl, VT, &Ops[0], NumElems); +} + +/// UnrollVectorOp - We know that the given vector has a legal type, however +/// the operation it performs is not legal, and the target has requested that +/// the operation be expanded. "Unroll" the vector, splitting out the scalars +/// and operating on each element individually. +SDValue VectorLegalizer::UnrollVectorOp(SDValue Op) { + EVT VT = Op.getValueType(); + assert(Op.getNode()->getNumValues() == 1 && + "Can't unroll a vector with multiple results!"); + unsigned NE = VT.getVectorNumElements(); + EVT EltVT = VT.getVectorElementType(); + DebugLoc dl = Op.getDebugLoc(); + + SmallVector Scalars; + SmallVector Operands(Op.getNumOperands()); + for (unsigned i = 0; i != NE; ++i) { + for (unsigned j = 0; j != Op.getNumOperands(); ++j) { + SDValue Operand = Op.getOperand(j); + EVT OperandVT = Operand.getValueType(); + if (OperandVT.isVector()) { + // A vector operand; extract a single element. + EVT OperandEltVT = OperandVT.getVectorElementType(); + Operands[j] = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, + OperandEltVT, + Operand, + DAG.getConstant(i, MVT::i32)); + } else { + // A scalar operand; just use it as is. + Operands[j] = Operand; + } + } + + switch (Op.getOpcode()) { + default: + Scalars.push_back(DAG.getNode(Op.getOpcode(), dl, EltVT, + &Operands[0], Operands.size())); + break; + case ISD::SHL: + case ISD::SRA: + case ISD::SRL: + case ISD::ROTL: + case ISD::ROTR: + Scalars.push_back(DAG.getNode(Op.getOpcode(), dl, EltVT, Operands[0], + DAG.getShiftAmountOperand(Operands[1]))); + break; + } + } + + return DAG.getNode(ISD::BUILD_VECTOR, dl, VT, &Scalars[0], Scalars.size()); +} + +} + +bool SelectionDAG::LegalizeVectors() { + return VectorLegalizer(*this).Run(); +} diff --git a/libclamav/c++/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp b/libclamav/c++/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp new file mode 100644 index 000000000..75e12395d --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp @@ -0,0 +1,2191 @@ +//===------- LegalizeVectorTypes.cpp - Legalization of vector types -------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file performs vector type splitting and scalarization for LegalizeTypes. +// Scalarization is the act of changing a computation in an illegal one-element +// vector type to be a computation in its scalar element type. For example, +// implementing <1 x f32> arithmetic in a scalar f32 register. This is needed +// as a base case when scalarizing vector arithmetic like <4 x f32>, which +// eventually decomposes to scalars if the target doesn't support v4f32 or v2f32 +// types. +// Splitting is the act of changing a computation in an invalid vector type to +// be a computation in two vectors of half the size. For example, implementing +// <128 x f32> operations in terms of two <64 x f32> operations. +// +//===----------------------------------------------------------------------===// + +#include "LegalizeTypes.h" +#include "llvm/CodeGen/PseudoSourceValue.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +//===----------------------------------------------------------------------===// +// Result Vector Scalarization: <1 x ty> -> ty. +//===----------------------------------------------------------------------===// + +void DAGTypeLegalizer::ScalarizeVectorResult(SDNode *N, unsigned ResNo) { + DEBUG(errs() << "Scalarize node result " << ResNo << ": "; + N->dump(&DAG); + errs() << "\n"); + SDValue R = SDValue(); + + switch (N->getOpcode()) { + default: +#ifndef NDEBUG + errs() << "ScalarizeVectorResult #" << ResNo << ": "; + N->dump(&DAG); + errs() << "\n"; +#endif + llvm_unreachable("Do not know how to scalarize the result of this operator!"); + + case ISD::BIT_CONVERT: R = ScalarizeVecRes_BIT_CONVERT(N); break; + case ISD::BUILD_VECTOR: R = N->getOperand(0); break; + case ISD::CONVERT_RNDSAT: R = ScalarizeVecRes_CONVERT_RNDSAT(N); break; + case ISD::EXTRACT_SUBVECTOR: R = ScalarizeVecRes_EXTRACT_SUBVECTOR(N); break; + case ISD::FPOWI: R = ScalarizeVecRes_FPOWI(N); break; + case ISD::INSERT_VECTOR_ELT: R = ScalarizeVecRes_INSERT_VECTOR_ELT(N); break; + case ISD::LOAD: R = ScalarizeVecRes_LOAD(cast(N));break; + case ISD::SCALAR_TO_VECTOR: R = ScalarizeVecRes_SCALAR_TO_VECTOR(N); break; + case ISD::SELECT: R = ScalarizeVecRes_SELECT(N); break; + case ISD::SELECT_CC: R = ScalarizeVecRes_SELECT_CC(N); break; + case ISD::SETCC: R = ScalarizeVecRes_SETCC(N); break; + case ISD::UNDEF: R = ScalarizeVecRes_UNDEF(N); break; + case ISD::VECTOR_SHUFFLE: R = ScalarizeVecRes_VECTOR_SHUFFLE(N); break; + case ISD::VSETCC: R = ScalarizeVecRes_VSETCC(N); break; + + case ISD::CTLZ: + case ISD::CTPOP: + case ISD::CTTZ: + case ISD::FABS: + case ISD::FCOS: + case ISD::FNEG: + case ISD::FP_TO_SINT: + case ISD::FP_TO_UINT: + case ISD::FSIN: + case ISD::FSQRT: + case ISD::FTRUNC: + case ISD::FFLOOR: + case ISD::FCEIL: + case ISD::FRINT: + case ISD::FNEARBYINT: + case ISD::UINT_TO_FP: + case ISD::SINT_TO_FP: + case ISD::TRUNCATE: + case ISD::SIGN_EXTEND: + case ISD::ZERO_EXTEND: + case ISD::ANY_EXTEND: + R = ScalarizeVecRes_UnaryOp(N); + break; + + case ISD::ADD: + case ISD::AND: + case ISD::FADD: + case ISD::FDIV: + case ISD::FMUL: + case ISD::FPOW: + case ISD::FREM: + case ISD::FSUB: + case ISD::MUL: + case ISD::OR: + case ISD::SDIV: + case ISD::SREM: + case ISD::SUB: + case ISD::UDIV: + case ISD::UREM: + case ISD::XOR: + case ISD::SHL: + case ISD::SRA: + case ISD::SRL: + R = ScalarizeVecRes_BinOp(N); + break; + } + + // If R is null, the sub-method took care of registering the result. + if (R.getNode()) + SetScalarizedVector(SDValue(N, ResNo), R); +} + +SDValue DAGTypeLegalizer::ScalarizeVecRes_BinOp(SDNode *N) { + SDValue LHS = GetScalarizedVector(N->getOperand(0)); + SDValue RHS = GetScalarizedVector(N->getOperand(1)); + return DAG.getNode(N->getOpcode(), N->getDebugLoc(), + LHS.getValueType(), LHS, RHS); +} + +SDValue DAGTypeLegalizer::ScalarizeVecRes_BIT_CONVERT(SDNode *N) { + EVT NewVT = N->getValueType(0).getVectorElementType(); + return DAG.getNode(ISD::BIT_CONVERT, N->getDebugLoc(), + NewVT, N->getOperand(0)); +} + +SDValue DAGTypeLegalizer::ScalarizeVecRes_CONVERT_RNDSAT(SDNode *N) { + EVT NewVT = N->getValueType(0).getVectorElementType(); + SDValue Op0 = GetScalarizedVector(N->getOperand(0)); + return DAG.getConvertRndSat(NewVT, N->getDebugLoc(), + Op0, DAG.getValueType(NewVT), + DAG.getValueType(Op0.getValueType()), + N->getOperand(3), + N->getOperand(4), + cast(N)->getCvtCode()); +} + +SDValue DAGTypeLegalizer::ScalarizeVecRes_EXTRACT_SUBVECTOR(SDNode *N) { + return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, N->getDebugLoc(), + N->getValueType(0).getVectorElementType(), + N->getOperand(0), N->getOperand(1)); +} + +SDValue DAGTypeLegalizer::ScalarizeVecRes_FPOWI(SDNode *N) { + SDValue Op = GetScalarizedVector(N->getOperand(0)); + return DAG.getNode(ISD::FPOWI, N->getDebugLoc(), + Op.getValueType(), Op, N->getOperand(1)); +} + +SDValue DAGTypeLegalizer::ScalarizeVecRes_INSERT_VECTOR_ELT(SDNode *N) { + // The value to insert may have a wider type than the vector element type, + // so be sure to truncate it to the element type if necessary. + SDValue Op = N->getOperand(1); + EVT EltVT = N->getValueType(0).getVectorElementType(); + if (Op.getValueType() != EltVT) + // FIXME: Can this happen for floating point types? + Op = DAG.getNode(ISD::TRUNCATE, N->getDebugLoc(), EltVT, Op); + return Op; +} + +SDValue DAGTypeLegalizer::ScalarizeVecRes_LOAD(LoadSDNode *N) { + assert(N->isUnindexed() && "Indexed vector load?"); + + SDValue Result = DAG.getLoad(ISD::UNINDEXED, N->getDebugLoc(), + N->getExtensionType(), + N->getValueType(0).getVectorElementType(), + N->getChain(), N->getBasePtr(), + DAG.getUNDEF(N->getBasePtr().getValueType()), + N->getSrcValue(), N->getSrcValueOffset(), + N->getMemoryVT().getVectorElementType(), + N->isVolatile(), N->getOriginalAlignment()); + + // Legalized the chain result - switch anything that used the old chain to + // use the new one. + ReplaceValueWith(SDValue(N, 1), Result.getValue(1)); + return Result; +} + +SDValue DAGTypeLegalizer::ScalarizeVecRes_UnaryOp(SDNode *N) { + // Get the dest type - it doesn't always match the input type, e.g. int_to_fp. + EVT DestVT = N->getValueType(0).getVectorElementType(); + SDValue Op = GetScalarizedVector(N->getOperand(0)); + return DAG.getNode(N->getOpcode(), N->getDebugLoc(), DestVT, Op); +} + +SDValue DAGTypeLegalizer::ScalarizeVecRes_SCALAR_TO_VECTOR(SDNode *N) { + // If the operand is wider than the vector element type then it is implicitly + // truncated. Make that explicit here. + EVT EltVT = N->getValueType(0).getVectorElementType(); + SDValue InOp = N->getOperand(0); + if (InOp.getValueType() != EltVT) + return DAG.getNode(ISD::TRUNCATE, N->getDebugLoc(), EltVT, InOp); + return InOp; +} + +SDValue DAGTypeLegalizer::ScalarizeVecRes_SELECT(SDNode *N) { + SDValue LHS = GetScalarizedVector(N->getOperand(1)); + return DAG.getNode(ISD::SELECT, N->getDebugLoc(), + LHS.getValueType(), N->getOperand(0), LHS, + GetScalarizedVector(N->getOperand(2))); +} + +SDValue DAGTypeLegalizer::ScalarizeVecRes_SELECT_CC(SDNode *N) { + SDValue LHS = GetScalarizedVector(N->getOperand(2)); + return DAG.getNode(ISD::SELECT_CC, N->getDebugLoc(), LHS.getValueType(), + N->getOperand(0), N->getOperand(1), + LHS, GetScalarizedVector(N->getOperand(3)), + N->getOperand(4)); +} + +SDValue DAGTypeLegalizer::ScalarizeVecRes_SETCC(SDNode *N) { + SDValue LHS = GetScalarizedVector(N->getOperand(0)); + SDValue RHS = GetScalarizedVector(N->getOperand(1)); + DebugLoc DL = N->getDebugLoc(); + + // Turn it into a scalar SETCC. + return DAG.getNode(ISD::SETCC, DL, MVT::i1, LHS, RHS, N->getOperand(2)); +} + +SDValue DAGTypeLegalizer::ScalarizeVecRes_UNDEF(SDNode *N) { + return DAG.getUNDEF(N->getValueType(0).getVectorElementType()); +} + +SDValue DAGTypeLegalizer::ScalarizeVecRes_VECTOR_SHUFFLE(SDNode *N) { + // Figure out if the scalar is the LHS or RHS and return it. + SDValue Arg = N->getOperand(2).getOperand(0); + if (Arg.getOpcode() == ISD::UNDEF) + return DAG.getUNDEF(N->getValueType(0).getVectorElementType()); + unsigned Op = !cast(Arg)->isNullValue(); + return GetScalarizedVector(N->getOperand(Op)); +} + +SDValue DAGTypeLegalizer::ScalarizeVecRes_VSETCC(SDNode *N) { + SDValue LHS = GetScalarizedVector(N->getOperand(0)); + SDValue RHS = GetScalarizedVector(N->getOperand(1)); + EVT NVT = N->getValueType(0).getVectorElementType(); + EVT SVT = TLI.getSetCCResultType(LHS.getValueType()); + DebugLoc DL = N->getDebugLoc(); + + // Turn it into a scalar SETCC. + SDValue Res = DAG.getNode(ISD::SETCC, DL, SVT, LHS, RHS, N->getOperand(2)); + + // VSETCC always returns a sign-extended value, while SETCC may not. The + // SETCC result type may not match the vector element type. Correct these. + if (NVT.bitsLE(SVT)) { + // The SETCC result type is bigger than the vector element type. + // Ensure the SETCC result is sign-extended. + if (TLI.getBooleanContents() != + TargetLowering::ZeroOrNegativeOneBooleanContent) + Res = DAG.getNode(ISD::SIGN_EXTEND_INREG, DL, SVT, Res, + DAG.getValueType(MVT::i1)); + // Truncate to the final type. + return DAG.getNode(ISD::TRUNCATE, DL, NVT, Res); + } + + // The SETCC result type is smaller than the vector element type. + // If the SetCC result is not sign-extended, chop it down to MVT::i1. + if (TLI.getBooleanContents() != + TargetLowering::ZeroOrNegativeOneBooleanContent) + Res = DAG.getNode(ISD::TRUNCATE, DL, MVT::i1, Res); + // Sign extend to the final type. + return DAG.getNode(ISD::SIGN_EXTEND, DL, NVT, Res); +} + + +//===----------------------------------------------------------------------===// +// Operand Vector Scalarization <1 x ty> -> ty. +//===----------------------------------------------------------------------===// + +bool DAGTypeLegalizer::ScalarizeVectorOperand(SDNode *N, unsigned OpNo) { + DEBUG(errs() << "Scalarize node operand " << OpNo << ": "; + N->dump(&DAG); + errs() << "\n"); + SDValue Res = SDValue(); + + if (Res.getNode() == 0) { + switch (N->getOpcode()) { + default: +#ifndef NDEBUG + errs() << "ScalarizeVectorOperand Op #" << OpNo << ": "; + N->dump(&DAG); + errs() << "\n"; +#endif + llvm_unreachable("Do not know how to scalarize this operator's operand!"); + case ISD::BIT_CONVERT: + Res = ScalarizeVecOp_BIT_CONVERT(N); + break; + case ISD::CONCAT_VECTORS: + Res = ScalarizeVecOp_CONCAT_VECTORS(N); + break; + case ISD::EXTRACT_VECTOR_ELT: + Res = ScalarizeVecOp_EXTRACT_VECTOR_ELT(N); + break; + case ISD::STORE: + Res = ScalarizeVecOp_STORE(cast(N), OpNo); + break; + } + } + + // If the result is null, the sub-method took care of registering results etc. + if (!Res.getNode()) return false; + + // If the result is N, the sub-method updated N in place. Tell the legalizer + // core about this. + if (Res.getNode() == N) + return true; + + assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 1 && + "Invalid operand expansion"); + + ReplaceValueWith(SDValue(N, 0), Res); + return false; +} + +/// ScalarizeVecOp_BIT_CONVERT - If the value to convert is a vector that needs +/// to be scalarized, it must be <1 x ty>. Convert the element instead. +SDValue DAGTypeLegalizer::ScalarizeVecOp_BIT_CONVERT(SDNode *N) { + SDValue Elt = GetScalarizedVector(N->getOperand(0)); + return DAG.getNode(ISD::BIT_CONVERT, N->getDebugLoc(), + N->getValueType(0), Elt); +} + +/// ScalarizeVecOp_CONCAT_VECTORS - The vectors to concatenate have length one - +/// use a BUILD_VECTOR instead. +SDValue DAGTypeLegalizer::ScalarizeVecOp_CONCAT_VECTORS(SDNode *N) { + SmallVector Ops(N->getNumOperands()); + for (unsigned i = 0, e = N->getNumOperands(); i < e; ++i) + Ops[i] = GetScalarizedVector(N->getOperand(i)); + return DAG.getNode(ISD::BUILD_VECTOR, N->getDebugLoc(), N->getValueType(0), + &Ops[0], Ops.size()); +} + +/// ScalarizeVecOp_EXTRACT_VECTOR_ELT - If the input is a vector that needs to +/// be scalarized, it must be <1 x ty>, so just return the element, ignoring the +/// index. +SDValue DAGTypeLegalizer::ScalarizeVecOp_EXTRACT_VECTOR_ELT(SDNode *N) { + SDValue Res = GetScalarizedVector(N->getOperand(0)); + if (Res.getValueType() != N->getValueType(0)) + Res = DAG.getNode(ISD::ANY_EXTEND, N->getDebugLoc(), N->getValueType(0), + Res); + return Res; +} + +/// ScalarizeVecOp_STORE - If the value to store is a vector that needs to be +/// scalarized, it must be <1 x ty>. Just store the element. +SDValue DAGTypeLegalizer::ScalarizeVecOp_STORE(StoreSDNode *N, unsigned OpNo){ + assert(N->isUnindexed() && "Indexed store of one-element vector?"); + assert(OpNo == 1 && "Do not know how to scalarize this operand!"); + DebugLoc dl = N->getDebugLoc(); + + if (N->isTruncatingStore()) + return DAG.getTruncStore(N->getChain(), dl, + GetScalarizedVector(N->getOperand(1)), + N->getBasePtr(), + N->getSrcValue(), N->getSrcValueOffset(), + N->getMemoryVT().getVectorElementType(), + N->isVolatile(), N->getAlignment()); + + return DAG.getStore(N->getChain(), dl, GetScalarizedVector(N->getOperand(1)), + N->getBasePtr(), N->getSrcValue(), N->getSrcValueOffset(), + N->isVolatile(), N->getOriginalAlignment()); +} + + +//===----------------------------------------------------------------------===// +// Result Vector Splitting +//===----------------------------------------------------------------------===// + +/// SplitVectorResult - This method is called when the specified result of the +/// specified node is found to need vector splitting. At this point, the node +/// may also have invalid operands or may have other results that need +/// legalization, we just know that (at least) one result needs vector +/// splitting. +void DAGTypeLegalizer::SplitVectorResult(SDNode *N, unsigned ResNo) { + DEBUG(errs() << "Split node result: "; + N->dump(&DAG); + errs() << "\n"); + SDValue Lo, Hi; + + switch (N->getOpcode()) { + default: +#ifndef NDEBUG + errs() << "SplitVectorResult #" << ResNo << ": "; + N->dump(&DAG); + errs() << "\n"; +#endif + llvm_unreachable("Do not know how to split the result of this operator!"); + + case ISD::MERGE_VALUES: SplitRes_MERGE_VALUES(N, Lo, Hi); break; + case ISD::SELECT: SplitRes_SELECT(N, Lo, Hi); break; + case ISD::SELECT_CC: SplitRes_SELECT_CC(N, Lo, Hi); break; + case ISD::UNDEF: SplitRes_UNDEF(N, Lo, Hi); break; + + case ISD::BIT_CONVERT: SplitVecRes_BIT_CONVERT(N, Lo, Hi); break; + case ISD::BUILD_VECTOR: SplitVecRes_BUILD_VECTOR(N, Lo, Hi); break; + case ISD::CONCAT_VECTORS: SplitVecRes_CONCAT_VECTORS(N, Lo, Hi); break; + case ISD::CONVERT_RNDSAT: SplitVecRes_CONVERT_RNDSAT(N, Lo, Hi); break; + case ISD::EXTRACT_SUBVECTOR: SplitVecRes_EXTRACT_SUBVECTOR(N, Lo, Hi); break; + case ISD::FPOWI: SplitVecRes_FPOWI(N, Lo, Hi); break; + case ISD::INSERT_VECTOR_ELT: SplitVecRes_INSERT_VECTOR_ELT(N, Lo, Hi); break; + case ISD::SCALAR_TO_VECTOR: SplitVecRes_SCALAR_TO_VECTOR(N, Lo, Hi); break; + case ISD::LOAD: + SplitVecRes_LOAD(cast(N), Lo, Hi); + break; + case ISD::SETCC: + case ISD::VSETCC: + SplitVecRes_SETCC(N, Lo, Hi); + break; + case ISD::VECTOR_SHUFFLE: + SplitVecRes_VECTOR_SHUFFLE(cast(N), Lo, Hi); + break; + + case ISD::CTTZ: + case ISD::CTLZ: + case ISD::CTPOP: + case ISD::FNEG: + case ISD::FABS: + case ISD::FSQRT: + case ISD::FSIN: + case ISD::FCOS: + case ISD::FTRUNC: + case ISD::FFLOOR: + case ISD::FCEIL: + case ISD::FRINT: + case ISD::FNEARBYINT: + case ISD::FP_TO_SINT: + case ISD::FP_TO_UINT: + case ISD::SINT_TO_FP: + case ISD::UINT_TO_FP: + case ISD::TRUNCATE: + case ISD::SIGN_EXTEND: + case ISD::ZERO_EXTEND: + case ISD::ANY_EXTEND: + SplitVecRes_UnaryOp(N, Lo, Hi); + break; + + case ISD::ADD: + case ISD::SUB: + case ISD::MUL: + case ISD::FADD: + case ISD::FSUB: + case ISD::FMUL: + case ISD::SDIV: + case ISD::UDIV: + case ISD::FDIV: + case ISD::FPOW: + case ISD::AND: + case ISD::OR: + case ISD::XOR: + case ISD::SHL: + case ISD::SRA: + case ISD::SRL: + case ISD::UREM: + case ISD::SREM: + case ISD::FREM: + SplitVecRes_BinOp(N, Lo, Hi); + break; + } + + // If Lo/Hi is null, the sub-method took care of registering results etc. + if (Lo.getNode()) + SetSplitVector(SDValue(N, ResNo), Lo, Hi); +} + +void DAGTypeLegalizer::SplitVecRes_BinOp(SDNode *N, SDValue &Lo, + SDValue &Hi) { + SDValue LHSLo, LHSHi; + GetSplitVector(N->getOperand(0), LHSLo, LHSHi); + SDValue RHSLo, RHSHi; + GetSplitVector(N->getOperand(1), RHSLo, RHSHi); + DebugLoc dl = N->getDebugLoc(); + + Lo = DAG.getNode(N->getOpcode(), dl, LHSLo.getValueType(), LHSLo, RHSLo); + Hi = DAG.getNode(N->getOpcode(), dl, LHSHi.getValueType(), LHSHi, RHSHi); +} + +void DAGTypeLegalizer::SplitVecRes_BIT_CONVERT(SDNode *N, SDValue &Lo, + SDValue &Hi) { + // We know the result is a vector. The input may be either a vector or a + // scalar value. + EVT LoVT, HiVT; + GetSplitDestVTs(N->getValueType(0), LoVT, HiVT); + DebugLoc dl = N->getDebugLoc(); + + SDValue InOp = N->getOperand(0); + EVT InVT = InOp.getValueType(); + + // Handle some special cases efficiently. + switch (getTypeAction(InVT)) { + default: + assert(false && "Unknown type action!"); + case Legal: + case PromoteInteger: + case SoftenFloat: + case ScalarizeVector: + break; + case ExpandInteger: + case ExpandFloat: + // A scalar to vector conversion, where the scalar needs expansion. + // If the vector is being split in two then we can just convert the + // expanded pieces. + if (LoVT == HiVT) { + GetExpandedOp(InOp, Lo, Hi); + if (TLI.isBigEndian()) + std::swap(Lo, Hi); + Lo = DAG.getNode(ISD::BIT_CONVERT, dl, LoVT, Lo); + Hi = DAG.getNode(ISD::BIT_CONVERT, dl, HiVT, Hi); + return; + } + break; + case SplitVector: + // If the input is a vector that needs to be split, convert each split + // piece of the input now. + GetSplitVector(InOp, Lo, Hi); + Lo = DAG.getNode(ISD::BIT_CONVERT, dl, LoVT, Lo); + Hi = DAG.getNode(ISD::BIT_CONVERT, dl, HiVT, Hi); + return; + } + + // In the general case, convert the input to an integer and split it by hand. + EVT LoIntVT = EVT::getIntegerVT(*DAG.getContext(), LoVT.getSizeInBits()); + EVT HiIntVT = EVT::getIntegerVT(*DAG.getContext(), HiVT.getSizeInBits()); + if (TLI.isBigEndian()) + std::swap(LoIntVT, HiIntVT); + + SplitInteger(BitConvertToInteger(InOp), LoIntVT, HiIntVT, Lo, Hi); + + if (TLI.isBigEndian()) + std::swap(Lo, Hi); + Lo = DAG.getNode(ISD::BIT_CONVERT, dl, LoVT, Lo); + Hi = DAG.getNode(ISD::BIT_CONVERT, dl, HiVT, Hi); +} + +void DAGTypeLegalizer::SplitVecRes_BUILD_VECTOR(SDNode *N, SDValue &Lo, + SDValue &Hi) { + EVT LoVT, HiVT; + DebugLoc dl = N->getDebugLoc(); + GetSplitDestVTs(N->getValueType(0), LoVT, HiVT); + unsigned LoNumElts = LoVT.getVectorNumElements(); + SmallVector LoOps(N->op_begin(), N->op_begin()+LoNumElts); + Lo = DAG.getNode(ISD::BUILD_VECTOR, dl, LoVT, &LoOps[0], LoOps.size()); + + SmallVector HiOps(N->op_begin()+LoNumElts, N->op_end()); + Hi = DAG.getNode(ISD::BUILD_VECTOR, dl, HiVT, &HiOps[0], HiOps.size()); +} + +void DAGTypeLegalizer::SplitVecRes_CONCAT_VECTORS(SDNode *N, SDValue &Lo, + SDValue &Hi) { + assert(!(N->getNumOperands() & 1) && "Unsupported CONCAT_VECTORS"); + DebugLoc dl = N->getDebugLoc(); + unsigned NumSubvectors = N->getNumOperands() / 2; + if (NumSubvectors == 1) { + Lo = N->getOperand(0); + Hi = N->getOperand(1); + return; + } + + EVT LoVT, HiVT; + GetSplitDestVTs(N->getValueType(0), LoVT, HiVT); + + SmallVector LoOps(N->op_begin(), N->op_begin()+NumSubvectors); + Lo = DAG.getNode(ISD::CONCAT_VECTORS, dl, LoVT, &LoOps[0], LoOps.size()); + + SmallVector HiOps(N->op_begin()+NumSubvectors, N->op_end()); + Hi = DAG.getNode(ISD::CONCAT_VECTORS, dl, HiVT, &HiOps[0], HiOps.size()); +} + +void DAGTypeLegalizer::SplitVecRes_CONVERT_RNDSAT(SDNode *N, SDValue &Lo, + SDValue &Hi) { + EVT LoVT, HiVT; + DebugLoc dl = N->getDebugLoc(); + GetSplitDestVTs(N->getValueType(0), LoVT, HiVT); + + SDValue DTyOpLo = DAG.getValueType(LoVT); + SDValue DTyOpHi = DAG.getValueType(HiVT); + + SDValue RndOp = N->getOperand(3); + SDValue SatOp = N->getOperand(4); + ISD::CvtCode CvtCode = cast(N)->getCvtCode(); + + // Split the input. + SDValue VLo, VHi; + EVT InVT = N->getOperand(0).getValueType(); + switch (getTypeAction(InVT)) { + default: llvm_unreachable("Unexpected type action!"); + case Legal: { + EVT InNVT = EVT::getVectorVT(*DAG.getContext(), InVT.getVectorElementType(), + LoVT.getVectorNumElements()); + VLo = DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, InNVT, N->getOperand(0), + DAG.getIntPtrConstant(0)); + VHi = DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, InNVT, N->getOperand(0), + DAG.getIntPtrConstant(InNVT.getVectorNumElements())); + break; + } + case SplitVector: + GetSplitVector(N->getOperand(0), VLo, VHi); + break; + case WidenVector: { + // If the result needs to be split and the input needs to be widened, + // the two types must have different lengths. Use the widened result + // and extract from it to do the split. + SDValue InOp = GetWidenedVector(N->getOperand(0)); + EVT InNVT = EVT::getVectorVT(*DAG.getContext(), InVT.getVectorElementType(), + LoVT.getVectorNumElements()); + VLo = DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, InNVT, InOp, + DAG.getIntPtrConstant(0)); + VHi = DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, InNVT, InOp, + DAG.getIntPtrConstant(InNVT.getVectorNumElements())); + break; + } + } + + SDValue STyOpLo = DAG.getValueType(VLo.getValueType()); + SDValue STyOpHi = DAG.getValueType(VHi.getValueType()); + + Lo = DAG.getConvertRndSat(LoVT, dl, VLo, DTyOpLo, STyOpLo, RndOp, SatOp, + CvtCode); + Hi = DAG.getConvertRndSat(HiVT, dl, VHi, DTyOpHi, STyOpHi, RndOp, SatOp, + CvtCode); +} + +void DAGTypeLegalizer::SplitVecRes_EXTRACT_SUBVECTOR(SDNode *N, SDValue &Lo, + SDValue &Hi) { + SDValue Vec = N->getOperand(0); + SDValue Idx = N->getOperand(1); + EVT IdxVT = Idx.getValueType(); + DebugLoc dl = N->getDebugLoc(); + + EVT LoVT, HiVT; + GetSplitDestVTs(N->getValueType(0), LoVT, HiVT); + + Lo = DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, LoVT, Vec, Idx); + Idx = DAG.getNode(ISD::ADD, dl, IdxVT, Idx, + DAG.getConstant(LoVT.getVectorNumElements(), IdxVT)); + Hi = DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, HiVT, Vec, Idx); +} + +void DAGTypeLegalizer::SplitVecRes_FPOWI(SDNode *N, SDValue &Lo, + SDValue &Hi) { + DebugLoc dl = N->getDebugLoc(); + GetSplitVector(N->getOperand(0), Lo, Hi); + Lo = DAG.getNode(ISD::FPOWI, dl, Lo.getValueType(), Lo, N->getOperand(1)); + Hi = DAG.getNode(ISD::FPOWI, dl, Hi.getValueType(), Hi, N->getOperand(1)); +} + +void DAGTypeLegalizer::SplitVecRes_INSERT_VECTOR_ELT(SDNode *N, SDValue &Lo, + SDValue &Hi) { + SDValue Vec = N->getOperand(0); + SDValue Elt = N->getOperand(1); + SDValue Idx = N->getOperand(2); + DebugLoc dl = N->getDebugLoc(); + GetSplitVector(Vec, Lo, Hi); + + if (ConstantSDNode *CIdx = dyn_cast(Idx)) { + unsigned IdxVal = CIdx->getZExtValue(); + unsigned LoNumElts = Lo.getValueType().getVectorNumElements(); + if (IdxVal < LoNumElts) + Lo = DAG.getNode(ISD::INSERT_VECTOR_ELT, dl, + Lo.getValueType(), Lo, Elt, Idx); + else + Hi = DAG.getNode(ISD::INSERT_VECTOR_ELT, dl, Hi.getValueType(), Hi, Elt, + DAG.getIntPtrConstant(IdxVal - LoNumElts)); + return; + } + + // Spill the vector to the stack. + EVT VecVT = Vec.getValueType(); + EVT EltVT = VecVT.getVectorElementType(); + SDValue StackPtr = DAG.CreateStackTemporary(VecVT); + SDValue Store = DAG.getStore(DAG.getEntryNode(), dl, Vec, StackPtr, NULL, 0); + + // Store the new element. This may be larger than the vector element type, + // so use a truncating store. + SDValue EltPtr = GetVectorElementPointer(StackPtr, EltVT, Idx); + unsigned Alignment = + TLI.getTargetData()->getPrefTypeAlignment(VecVT.getTypeForEVT(*DAG.getContext())); + Store = DAG.getTruncStore(Store, dl, Elt, EltPtr, NULL, 0, EltVT); + + // Load the Lo part from the stack slot. + Lo = DAG.getLoad(Lo.getValueType(), dl, Store, StackPtr, NULL, 0); + + // Increment the pointer to the other part. + unsigned IncrementSize = Lo.getValueType().getSizeInBits() / 8; + StackPtr = DAG.getNode(ISD::ADD, dl, StackPtr.getValueType(), StackPtr, + DAG.getIntPtrConstant(IncrementSize)); + + // Load the Hi part from the stack slot. + Hi = DAG.getLoad(Hi.getValueType(), dl, Store, StackPtr, NULL, 0, false, + MinAlign(Alignment, IncrementSize)); +} + +void DAGTypeLegalizer::SplitVecRes_SCALAR_TO_VECTOR(SDNode *N, SDValue &Lo, + SDValue &Hi) { + EVT LoVT, HiVT; + DebugLoc dl = N->getDebugLoc(); + GetSplitDestVTs(N->getValueType(0), LoVT, HiVT); + Lo = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, LoVT, N->getOperand(0)); + Hi = DAG.getUNDEF(HiVT); +} + +void DAGTypeLegalizer::SplitVecRes_LOAD(LoadSDNode *LD, SDValue &Lo, + SDValue &Hi) { + assert(ISD::isUNINDEXEDLoad(LD) && "Indexed load during type legalization!"); + EVT LoVT, HiVT; + DebugLoc dl = LD->getDebugLoc(); + GetSplitDestVTs(LD->getValueType(0), LoVT, HiVT); + + ISD::LoadExtType ExtType = LD->getExtensionType(); + SDValue Ch = LD->getChain(); + SDValue Ptr = LD->getBasePtr(); + SDValue Offset = DAG.getUNDEF(Ptr.getValueType()); + const Value *SV = LD->getSrcValue(); + int SVOffset = LD->getSrcValueOffset(); + EVT MemoryVT = LD->getMemoryVT(); + unsigned Alignment = LD->getOriginalAlignment(); + bool isVolatile = LD->isVolatile(); + + EVT LoMemVT, HiMemVT; + GetSplitDestVTs(MemoryVT, LoMemVT, HiMemVT); + + Lo = DAG.getLoad(ISD::UNINDEXED, dl, ExtType, LoVT, Ch, Ptr, Offset, + SV, SVOffset, LoMemVT, isVolatile, Alignment); + + unsigned IncrementSize = LoMemVT.getSizeInBits()/8; + Ptr = DAG.getNode(ISD::ADD, dl, Ptr.getValueType(), Ptr, + DAG.getIntPtrConstant(IncrementSize)); + SVOffset += IncrementSize; + Hi = DAG.getLoad(ISD::UNINDEXED, dl, ExtType, HiVT, Ch, Ptr, Offset, + SV, SVOffset, HiMemVT, isVolatile, Alignment); + + // Build a factor node to remember that this load is independent of the + // other one. + Ch = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Lo.getValue(1), + Hi.getValue(1)); + + // Legalized the chain result - switch anything that used the old chain to + // use the new one. + ReplaceValueWith(SDValue(LD, 1), Ch); +} + +void DAGTypeLegalizer::SplitVecRes_SETCC(SDNode *N, SDValue &Lo, SDValue &Hi) { + EVT LoVT, HiVT; + DebugLoc DL = N->getDebugLoc(); + GetSplitDestVTs(N->getValueType(0), LoVT, HiVT); + + // Split the input. + EVT InVT = N->getOperand(0).getValueType(); + SDValue LL, LH, RL, RH; + EVT InNVT = EVT::getVectorVT(*DAG.getContext(), InVT.getVectorElementType(), + LoVT.getVectorNumElements()); + LL = DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, InNVT, N->getOperand(0), + DAG.getIntPtrConstant(0)); + LH = DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, InNVT, N->getOperand(0), + DAG.getIntPtrConstant(InNVT.getVectorNumElements())); + + RL = DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, InNVT, N->getOperand(1), + DAG.getIntPtrConstant(0)); + RH = DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, InNVT, N->getOperand(1), + DAG.getIntPtrConstant(InNVT.getVectorNumElements())); + + Lo = DAG.getNode(N->getOpcode(), DL, LoVT, LL, RL, N->getOperand(2)); + Hi = DAG.getNode(N->getOpcode(), DL, HiVT, LH, RH, N->getOperand(2)); +} + +void DAGTypeLegalizer::SplitVecRes_UnaryOp(SDNode *N, SDValue &Lo, + SDValue &Hi) { + // Get the dest types - they may not match the input types, e.g. int_to_fp. + EVT LoVT, HiVT; + DebugLoc dl = N->getDebugLoc(); + GetSplitDestVTs(N->getValueType(0), LoVT, HiVT); + + // Split the input. + EVT InVT = N->getOperand(0).getValueType(); + switch (getTypeAction(InVT)) { + default: llvm_unreachable("Unexpected type action!"); + case Legal: { + EVT InNVT = EVT::getVectorVT(*DAG.getContext(), InVT.getVectorElementType(), + LoVT.getVectorNumElements()); + Lo = DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, InNVT, N->getOperand(0), + DAG.getIntPtrConstant(0)); + Hi = DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, InNVT, N->getOperand(0), + DAG.getIntPtrConstant(InNVT.getVectorNumElements())); + break; + } + case SplitVector: + GetSplitVector(N->getOperand(0), Lo, Hi); + break; + case WidenVector: { + // If the result needs to be split and the input needs to be widened, + // the two types must have different lengths. Use the widened result + // and extract from it to do the split. + SDValue InOp = GetWidenedVector(N->getOperand(0)); + EVT InNVT = EVT::getVectorVT(*DAG.getContext(), InVT.getVectorElementType(), + LoVT.getVectorNumElements()); + Lo = DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, InNVT, InOp, + DAG.getIntPtrConstant(0)); + Hi = DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, InNVT, InOp, + DAG.getIntPtrConstant(InNVT.getVectorNumElements())); + break; + } + } + + Lo = DAG.getNode(N->getOpcode(), dl, LoVT, Lo); + Hi = DAG.getNode(N->getOpcode(), dl, HiVT, Hi); +} + +void DAGTypeLegalizer::SplitVecRes_VECTOR_SHUFFLE(ShuffleVectorSDNode *N, + SDValue &Lo, SDValue &Hi) { + // The low and high parts of the original input give four input vectors. + SDValue Inputs[4]; + DebugLoc dl = N->getDebugLoc(); + GetSplitVector(N->getOperand(0), Inputs[0], Inputs[1]); + GetSplitVector(N->getOperand(1), Inputs[2], Inputs[3]); + EVT NewVT = Inputs[0].getValueType(); + unsigned NewElts = NewVT.getVectorNumElements(); + + // If Lo or Hi uses elements from at most two of the four input vectors, then + // express it as a vector shuffle of those two inputs. Otherwise extract the + // input elements by hand and construct the Lo/Hi output using a BUILD_VECTOR. + SmallVector Ops; + for (unsigned High = 0; High < 2; ++High) { + SDValue &Output = High ? Hi : Lo; + + // Build a shuffle mask for the output, discovering on the fly which + // input vectors to use as shuffle operands (recorded in InputUsed). + // If building a suitable shuffle vector proves too hard, then bail + // out with useBuildVector set. + unsigned InputUsed[2] = { -1U, -1U }; // Not yet discovered. + unsigned FirstMaskIdx = High * NewElts; + bool useBuildVector = false; + for (unsigned MaskOffset = 0; MaskOffset < NewElts; ++MaskOffset) { + // The mask element. This indexes into the input. + int Idx = N->getMaskElt(FirstMaskIdx + MaskOffset); + + // The input vector this mask element indexes into. + unsigned Input = (unsigned)Idx / NewElts; + + if (Input >= array_lengthof(Inputs)) { + // The mask element does not index into any input vector. + Ops.push_back(-1); + continue; + } + + // Turn the index into an offset from the start of the input vector. + Idx -= Input * NewElts; + + // Find or create a shuffle vector operand to hold this input. + unsigned OpNo; + for (OpNo = 0; OpNo < array_lengthof(InputUsed); ++OpNo) { + if (InputUsed[OpNo] == Input) { + // This input vector is already an operand. + break; + } else if (InputUsed[OpNo] == -1U) { + // Create a new operand for this input vector. + InputUsed[OpNo] = Input; + break; + } + } + + if (OpNo >= array_lengthof(InputUsed)) { + // More than two input vectors used! Give up on trying to create a + // shuffle vector. Insert all elements into a BUILD_VECTOR instead. + useBuildVector = true; + break; + } + + // Add the mask index for the new shuffle vector. + Ops.push_back(Idx + OpNo * NewElts); + } + + if (useBuildVector) { + EVT EltVT = NewVT.getVectorElementType(); + SmallVector SVOps; + + // Extract the input elements by hand. + for (unsigned MaskOffset = 0; MaskOffset < NewElts; ++MaskOffset) { + // The mask element. This indexes into the input. + int Idx = N->getMaskElt(FirstMaskIdx + MaskOffset); + + // The input vector this mask element indexes into. + unsigned Input = (unsigned)Idx / NewElts; + + if (Input >= array_lengthof(Inputs)) { + // The mask element is "undef" or indexes off the end of the input. + SVOps.push_back(DAG.getUNDEF(EltVT)); + continue; + } + + // Turn the index into an offset from the start of the input vector. + Idx -= Input * NewElts; + + // Extract the vector element by hand. + SVOps.push_back(DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, EltVT, + Inputs[Input], DAG.getIntPtrConstant(Idx))); + } + + // Construct the Lo/Hi output using a BUILD_VECTOR. + Output = DAG.getNode(ISD::BUILD_VECTOR,dl,NewVT, &SVOps[0], SVOps.size()); + } else if (InputUsed[0] == -1U) { + // No input vectors were used! The result is undefined. + Output = DAG.getUNDEF(NewVT); + } else { + SDValue Op0 = Inputs[InputUsed[0]]; + // If only one input was used, use an undefined vector for the other. + SDValue Op1 = InputUsed[1] == -1U ? + DAG.getUNDEF(NewVT) : Inputs[InputUsed[1]]; + // At least one input vector was used. Create a new shuffle vector. + Output = DAG.getVectorShuffle(NewVT, dl, Op0, Op1, &Ops[0]); + } + + Ops.clear(); + } +} + + +//===----------------------------------------------------------------------===// +// Operand Vector Splitting +//===----------------------------------------------------------------------===// + +/// SplitVectorOperand - This method is called when the specified operand of the +/// specified node is found to need vector splitting. At this point, all of the +/// result types of the node are known to be legal, but other operands of the +/// node may need legalization as well as the specified one. +bool DAGTypeLegalizer::SplitVectorOperand(SDNode *N, unsigned OpNo) { + DEBUG(errs() << "Split node operand: "; + N->dump(&DAG); + errs() << "\n"); + SDValue Res = SDValue(); + + if (Res.getNode() == 0) { + switch (N->getOpcode()) { + default: +#ifndef NDEBUG + errs() << "SplitVectorOperand Op #" << OpNo << ": "; + N->dump(&DAG); + errs() << "\n"; +#endif + llvm_unreachable("Do not know how to split this operator's operand!"); + + case ISD::BIT_CONVERT: Res = SplitVecOp_BIT_CONVERT(N); break; + case ISD::EXTRACT_SUBVECTOR: Res = SplitVecOp_EXTRACT_SUBVECTOR(N); break; + case ISD::EXTRACT_VECTOR_ELT:Res = SplitVecOp_EXTRACT_VECTOR_ELT(N); break; + case ISD::STORE: + Res = SplitVecOp_STORE(cast(N), OpNo); + break; + + case ISD::CTTZ: + case ISD::CTLZ: + case ISD::CTPOP: + case ISD::FP_TO_SINT: + case ISD::FP_TO_UINT: + case ISD::SINT_TO_FP: + case ISD::UINT_TO_FP: + case ISD::TRUNCATE: + case ISD::SIGN_EXTEND: + case ISD::ZERO_EXTEND: + case ISD::ANY_EXTEND: + Res = SplitVecOp_UnaryOp(N); + break; + } + } + + // If the result is null, the sub-method took care of registering results etc. + if (!Res.getNode()) return false; + + // If the result is N, the sub-method updated N in place. Tell the legalizer + // core about this. + if (Res.getNode() == N) + return true; + + assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 1 && + "Invalid operand expansion"); + + ReplaceValueWith(SDValue(N, 0), Res); + return false; +} + +SDValue DAGTypeLegalizer::SplitVecOp_UnaryOp(SDNode *N) { + // The result has a legal vector type, but the input needs splitting. + EVT ResVT = N->getValueType(0); + SDValue Lo, Hi; + DebugLoc dl = N->getDebugLoc(); + GetSplitVector(N->getOperand(0), Lo, Hi); + EVT InVT = Lo.getValueType(); + + EVT OutVT = EVT::getVectorVT(*DAG.getContext(), ResVT.getVectorElementType(), + InVT.getVectorNumElements()); + + Lo = DAG.getNode(N->getOpcode(), dl, OutVT, Lo); + Hi = DAG.getNode(N->getOpcode(), dl, OutVT, Hi); + + return DAG.getNode(ISD::CONCAT_VECTORS, dl, ResVT, Lo, Hi); +} + +SDValue DAGTypeLegalizer::SplitVecOp_BIT_CONVERT(SDNode *N) { + // For example, i64 = BIT_CONVERT v4i16 on alpha. Typically the vector will + // end up being split all the way down to individual components. Convert the + // split pieces into integers and reassemble. + SDValue Lo, Hi; + GetSplitVector(N->getOperand(0), Lo, Hi); + Lo = BitConvertToInteger(Lo); + Hi = BitConvertToInteger(Hi); + + if (TLI.isBigEndian()) + std::swap(Lo, Hi); + + return DAG.getNode(ISD::BIT_CONVERT, N->getDebugLoc(), N->getValueType(0), + JoinIntegers(Lo, Hi)); +} + +SDValue DAGTypeLegalizer::SplitVecOp_EXTRACT_SUBVECTOR(SDNode *N) { + // We know that the extracted result type is legal. For now, assume the index + // is a constant. + EVT SubVT = N->getValueType(0); + SDValue Idx = N->getOperand(1); + DebugLoc dl = N->getDebugLoc(); + SDValue Lo, Hi; + GetSplitVector(N->getOperand(0), Lo, Hi); + + uint64_t LoElts = Lo.getValueType().getVectorNumElements(); + uint64_t IdxVal = cast(Idx)->getZExtValue(); + + if (IdxVal < LoElts) { + assert(IdxVal + SubVT.getVectorNumElements() <= LoElts && + "Extracted subvector crosses vector split!"); + return DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, SubVT, Lo, Idx); + } else { + return DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, SubVT, Hi, + DAG.getConstant(IdxVal - LoElts, Idx.getValueType())); + } +} + +SDValue DAGTypeLegalizer::SplitVecOp_EXTRACT_VECTOR_ELT(SDNode *N) { + SDValue Vec = N->getOperand(0); + SDValue Idx = N->getOperand(1); + EVT VecVT = Vec.getValueType(); + + if (isa(Idx)) { + uint64_t IdxVal = cast(Idx)->getZExtValue(); + assert(IdxVal < VecVT.getVectorNumElements() && "Invalid vector index!"); + + SDValue Lo, Hi; + GetSplitVector(Vec, Lo, Hi); + + uint64_t LoElts = Lo.getValueType().getVectorNumElements(); + + if (IdxVal < LoElts) + return DAG.UpdateNodeOperands(SDValue(N, 0), Lo, Idx); + return DAG.UpdateNodeOperands(SDValue(N, 0), Hi, + DAG.getConstant(IdxVal - LoElts, + Idx.getValueType())); + } + + // Store the vector to the stack. + EVT EltVT = VecVT.getVectorElementType(); + DebugLoc dl = N->getDebugLoc(); + SDValue StackPtr = DAG.CreateStackTemporary(VecVT); + int SPFI = cast(StackPtr.getNode())->getIndex(); + const Value *SV = PseudoSourceValue::getFixedStack(SPFI); + SDValue Store = DAG.getStore(DAG.getEntryNode(), dl, Vec, StackPtr, SV, 0); + + // Load back the required element. + StackPtr = GetVectorElementPointer(StackPtr, EltVT, Idx); + return DAG.getExtLoad(ISD::EXTLOAD, dl, N->getValueType(0), Store, StackPtr, + SV, 0, EltVT); +} + +SDValue DAGTypeLegalizer::SplitVecOp_STORE(StoreSDNode *N, unsigned OpNo) { + assert(N->isUnindexed() && "Indexed store of vector?"); + assert(OpNo == 1 && "Can only split the stored value"); + DebugLoc dl = N->getDebugLoc(); + + bool isTruncating = N->isTruncatingStore(); + SDValue Ch = N->getChain(); + SDValue Ptr = N->getBasePtr(); + int SVOffset = N->getSrcValueOffset(); + EVT MemoryVT = N->getMemoryVT(); + unsigned Alignment = N->getOriginalAlignment(); + bool isVol = N->isVolatile(); + SDValue Lo, Hi; + GetSplitVector(N->getOperand(1), Lo, Hi); + + EVT LoMemVT, HiMemVT; + GetSplitDestVTs(MemoryVT, LoMemVT, HiMemVT); + + unsigned IncrementSize = LoMemVT.getSizeInBits()/8; + + if (isTruncating) + Lo = DAG.getTruncStore(Ch, dl, Lo, Ptr, N->getSrcValue(), SVOffset, + LoMemVT, isVol, Alignment); + else + Lo = DAG.getStore(Ch, dl, Lo, Ptr, N->getSrcValue(), SVOffset, + isVol, Alignment); + + // Increment the pointer to the other half. + Ptr = DAG.getNode(ISD::ADD, dl, Ptr.getValueType(), Ptr, + DAG.getIntPtrConstant(IncrementSize)); + SVOffset += IncrementSize; + + if (isTruncating) + Hi = DAG.getTruncStore(Ch, dl, Hi, Ptr, N->getSrcValue(), SVOffset, + HiMemVT, isVol, Alignment); + else + Hi = DAG.getStore(Ch, dl, Hi, Ptr, N->getSrcValue(), SVOffset, + isVol, Alignment); + + return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Lo, Hi); +} + + +//===----------------------------------------------------------------------===// +// Result Vector Widening +//===----------------------------------------------------------------------===// + +void DAGTypeLegalizer::WidenVectorResult(SDNode *N, unsigned ResNo) { + DEBUG(errs() << "Widen node result " << ResNo << ": "; + N->dump(&DAG); + errs() << "\n"); + SDValue Res = SDValue(); + + switch (N->getOpcode()) { + default: +#ifndef NDEBUG + errs() << "WidenVectorResult #" << ResNo << ": "; + N->dump(&DAG); + errs() << "\n"; +#endif + llvm_unreachable("Do not know how to widen the result of this operator!"); + + case ISD::BIT_CONVERT: Res = WidenVecRes_BIT_CONVERT(N); break; + case ISD::BUILD_VECTOR: Res = WidenVecRes_BUILD_VECTOR(N); break; + case ISD::CONCAT_VECTORS: Res = WidenVecRes_CONCAT_VECTORS(N); break; + case ISD::CONVERT_RNDSAT: Res = WidenVecRes_CONVERT_RNDSAT(N); break; + case ISD::EXTRACT_SUBVECTOR: Res = WidenVecRes_EXTRACT_SUBVECTOR(N); break; + case ISD::INSERT_VECTOR_ELT: Res = WidenVecRes_INSERT_VECTOR_ELT(N); break; + case ISD::LOAD: Res = WidenVecRes_LOAD(N); break; + case ISD::SCALAR_TO_VECTOR: Res = WidenVecRes_SCALAR_TO_VECTOR(N); break; + case ISD::SELECT: Res = WidenVecRes_SELECT(N); break; + case ISD::SELECT_CC: Res = WidenVecRes_SELECT_CC(N); break; + case ISD::UNDEF: Res = WidenVecRes_UNDEF(N); break; + case ISD::VECTOR_SHUFFLE: + Res = WidenVecRes_VECTOR_SHUFFLE(cast(N)); + break; + case ISD::VSETCC: + Res = WidenVecRes_VSETCC(N); + break; + + case ISD::ADD: + case ISD::AND: + case ISD::BSWAP: + case ISD::FADD: + case ISD::FCOPYSIGN: + case ISD::FDIV: + case ISD::FMUL: + case ISD::FPOW: + case ISD::FPOWI: + case ISD::FREM: + case ISD::FSUB: + case ISD::MUL: + case ISD::MULHS: + case ISD::MULHU: + case ISD::OR: + case ISD::SDIV: + case ISD::SREM: + case ISD::UDIV: + case ISD::UREM: + case ISD::SUB: + case ISD::XOR: + Res = WidenVecRes_Binary(N); + break; + + case ISD::SHL: + case ISD::SRA: + case ISD::SRL: + Res = WidenVecRes_Shift(N); + break; + + case ISD::FP_ROUND: + case ISD::FP_TO_SINT: + case ISD::FP_TO_UINT: + case ISD::SINT_TO_FP: + case ISD::UINT_TO_FP: + case ISD::TRUNCATE: + case ISD::SIGN_EXTEND: + case ISD::ZERO_EXTEND: + case ISD::ANY_EXTEND: + Res = WidenVecRes_Convert(N); + break; + + case ISD::CTLZ: + case ISD::CTPOP: + case ISD::CTTZ: + case ISD::FABS: + case ISD::FCOS: + case ISD::FNEG: + case ISD::FSIN: + case ISD::FSQRT: + Res = WidenVecRes_Unary(N); + break; + } + + // If Res is null, the sub-method took care of registering the result. + if (Res.getNode()) + SetWidenedVector(SDValue(N, ResNo), Res); +} + +SDValue DAGTypeLegalizer::WidenVecRes_Binary(SDNode *N) { + // Binary op widening. + EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); + SDValue InOp1 = GetWidenedVector(N->getOperand(0)); + SDValue InOp2 = GetWidenedVector(N->getOperand(1)); + return DAG.getNode(N->getOpcode(), N->getDebugLoc(), WidenVT, InOp1, InOp2); +} + +SDValue DAGTypeLegalizer::WidenVecRes_Convert(SDNode *N) { + SDValue InOp = N->getOperand(0); + DebugLoc dl = N->getDebugLoc(); + + EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); + unsigned WidenNumElts = WidenVT.getVectorNumElements(); + + EVT InVT = InOp.getValueType(); + EVT InEltVT = InVT.getVectorElementType(); + EVT InWidenVT = EVT::getVectorVT(*DAG.getContext(), InEltVT, WidenNumElts); + + unsigned Opcode = N->getOpcode(); + unsigned InVTNumElts = InVT.getVectorNumElements(); + + if (getTypeAction(InVT) == WidenVector) { + InOp = GetWidenedVector(N->getOperand(0)); + InVT = InOp.getValueType(); + InVTNumElts = InVT.getVectorNumElements(); + if (InVTNumElts == WidenNumElts) + return DAG.getNode(Opcode, dl, WidenVT, InOp); + } + + if (TLI.isTypeLegal(InWidenVT)) { + // Because the result and the input are different vector types, widening + // the result could create a legal type but widening the input might make + // it an illegal type that might lead to repeatedly splitting the input + // and then widening it. To avoid this, we widen the input only if + // it results in a legal type. + if (WidenNumElts % InVTNumElts == 0) { + // Widen the input and call convert on the widened input vector. + unsigned NumConcat = WidenNumElts/InVTNumElts; + SmallVector Ops(NumConcat); + Ops[0] = InOp; + SDValue UndefVal = DAG.getUNDEF(InVT); + for (unsigned i = 1; i != NumConcat; ++i) + Ops[i] = UndefVal; + return DAG.getNode(Opcode, dl, WidenVT, + DAG.getNode(ISD::CONCAT_VECTORS, dl, InWidenVT, + &Ops[0], NumConcat)); + } + + if (InVTNumElts % WidenNumElts == 0) { + // Extract the input and convert the shorten input vector. + return DAG.getNode(Opcode, dl, WidenVT, + DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, InWidenVT, + InOp, DAG.getIntPtrConstant(0))); + } + } + + // Otherwise unroll into some nasty scalar code and rebuild the vector. + SmallVector Ops(WidenNumElts); + EVT EltVT = WidenVT.getVectorElementType(); + unsigned MinElts = std::min(InVTNumElts, WidenNumElts); + unsigned i; + for (i=0; i < MinElts; ++i) + Ops[i] = DAG.getNode(Opcode, dl, EltVT, + DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, InEltVT, InOp, + DAG.getIntPtrConstant(i))); + + SDValue UndefVal = DAG.getUNDEF(EltVT); + for (; i < WidenNumElts; ++i) + Ops[i] = UndefVal; + + return DAG.getNode(ISD::BUILD_VECTOR, dl, WidenVT, &Ops[0], WidenNumElts); +} + +SDValue DAGTypeLegalizer::WidenVecRes_Shift(SDNode *N) { + EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); + SDValue InOp = GetWidenedVector(N->getOperand(0)); + SDValue ShOp = N->getOperand(1); + + EVT ShVT = ShOp.getValueType(); + if (getTypeAction(ShVT) == WidenVector) { + ShOp = GetWidenedVector(ShOp); + ShVT = ShOp.getValueType(); + } + EVT ShWidenVT = EVT::getVectorVT(*DAG.getContext(), ShVT.getVectorElementType(), + WidenVT.getVectorNumElements()); + if (ShVT != ShWidenVT) + ShOp = ModifyToType(ShOp, ShWidenVT); + + return DAG.getNode(N->getOpcode(), N->getDebugLoc(), WidenVT, InOp, ShOp); +} + +SDValue DAGTypeLegalizer::WidenVecRes_Unary(SDNode *N) { + // Unary op widening. + EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); + SDValue InOp = GetWidenedVector(N->getOperand(0)); + return DAG.getNode(N->getOpcode(), N->getDebugLoc(), WidenVT, InOp); +} + +SDValue DAGTypeLegalizer::WidenVecRes_BIT_CONVERT(SDNode *N) { + SDValue InOp = N->getOperand(0); + EVT InVT = InOp.getValueType(); + EVT VT = N->getValueType(0); + EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT); + DebugLoc dl = N->getDebugLoc(); + + switch (getTypeAction(InVT)) { + default: + assert(false && "Unknown type action!"); + break; + case Legal: + break; + case PromoteInteger: + // If the InOp is promoted to the same size, convert it. Otherwise, + // fall out of the switch and widen the promoted input. + InOp = GetPromotedInteger(InOp); + InVT = InOp.getValueType(); + if (WidenVT.bitsEq(InVT)) + return DAG.getNode(ISD::BIT_CONVERT, dl, WidenVT, InOp); + break; + case SoftenFloat: + case ExpandInteger: + case ExpandFloat: + case ScalarizeVector: + case SplitVector: + break; + case WidenVector: + // If the InOp is widened to the same size, convert it. Otherwise, fall + // out of the switch and widen the widened input. + InOp = GetWidenedVector(InOp); + InVT = InOp.getValueType(); + if (WidenVT.bitsEq(InVT)) + // The input widens to the same size. Convert to the widen value. + return DAG.getNode(ISD::BIT_CONVERT, dl, WidenVT, InOp); + break; + } + + unsigned WidenSize = WidenVT.getSizeInBits(); + unsigned InSize = InVT.getSizeInBits(); + if (WidenSize % InSize == 0) { + // Determine new input vector type. The new input vector type will use + // the same element type (if its a vector) or use the input type as a + // vector. It is the same size as the type to widen to. + EVT NewInVT; + unsigned NewNumElts = WidenSize / InSize; + if (InVT.isVector()) { + EVT InEltVT = InVT.getVectorElementType(); + NewInVT= EVT::getVectorVT(*DAG.getContext(), InEltVT, WidenSize / InEltVT.getSizeInBits()); + } else { + NewInVT = EVT::getVectorVT(*DAG.getContext(), InVT, NewNumElts); + } + + if (TLI.isTypeLegal(NewInVT)) { + // Because the result and the input are different vector types, widening + // the result could create a legal type but widening the input might make + // it an illegal type that might lead to repeatedly splitting the input + // and then widening it. To avoid this, we widen the input only if + // it results in a legal type. + SmallVector Ops(NewNumElts); + SDValue UndefVal = DAG.getUNDEF(InVT); + Ops[0] = InOp; + for (unsigned i = 1; i < NewNumElts; ++i) + Ops[i] = UndefVal; + + SDValue NewVec; + if (InVT.isVector()) + NewVec = DAG.getNode(ISD::CONCAT_VECTORS, dl, + NewInVT, &Ops[0], NewNumElts); + else + NewVec = DAG.getNode(ISD::BUILD_VECTOR, dl, + NewInVT, &Ops[0], NewNumElts); + return DAG.getNode(ISD::BIT_CONVERT, dl, WidenVT, NewVec); + } + } + + return CreateStackStoreLoad(InOp, WidenVT); +} + +SDValue DAGTypeLegalizer::WidenVecRes_BUILD_VECTOR(SDNode *N) { + DebugLoc dl = N->getDebugLoc(); + // Build a vector with undefined for the new nodes. + EVT VT = N->getValueType(0); + EVT EltVT = VT.getVectorElementType(); + unsigned NumElts = VT.getVectorNumElements(); + + EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT); + unsigned WidenNumElts = WidenVT.getVectorNumElements(); + + SmallVector NewOps(N->op_begin(), N->op_end()); + NewOps.reserve(WidenNumElts); + for (unsigned i = NumElts; i < WidenNumElts; ++i) + NewOps.push_back(DAG.getUNDEF(EltVT)); + + return DAG.getNode(ISD::BUILD_VECTOR, dl, WidenVT, &NewOps[0], NewOps.size()); +} + +SDValue DAGTypeLegalizer::WidenVecRes_CONCAT_VECTORS(SDNode *N) { + EVT InVT = N->getOperand(0).getValueType(); + EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); + DebugLoc dl = N->getDebugLoc(); + unsigned WidenNumElts = WidenVT.getVectorNumElements(); + unsigned NumOperands = N->getNumOperands(); + + bool InputWidened = false; // Indicates we need to widen the input. + if (getTypeAction(InVT) != WidenVector) { + if (WidenVT.getVectorNumElements() % InVT.getVectorNumElements() == 0) { + // Add undef vectors to widen to correct length. + unsigned NumConcat = WidenVT.getVectorNumElements() / + InVT.getVectorNumElements(); + SDValue UndefVal = DAG.getUNDEF(InVT); + SmallVector Ops(NumConcat); + for (unsigned i=0; i < NumOperands; ++i) + Ops[i] = N->getOperand(i); + for (unsigned i = NumOperands; i != NumConcat; ++i) + Ops[i] = UndefVal; + return DAG.getNode(ISD::CONCAT_VECTORS, dl, WidenVT, &Ops[0], NumConcat); + } + } else { + InputWidened = true; + if (WidenVT == TLI.getTypeToTransformTo(*DAG.getContext(), InVT)) { + // The inputs and the result are widen to the same value. + unsigned i; + for (i=1; i < NumOperands; ++i) + if (N->getOperand(i).getOpcode() != ISD::UNDEF) + break; + + if (i > NumOperands) + // Everything but the first operand is an UNDEF so just return the + // widened first operand. + return GetWidenedVector(N->getOperand(0)); + + if (NumOperands == 2) { + // Replace concat of two operands with a shuffle. + SmallVector MaskOps(WidenNumElts); + for (unsigned i=0; i < WidenNumElts/2; ++i) { + MaskOps[i] = i; + MaskOps[i+WidenNumElts/2] = i+WidenNumElts; + } + return DAG.getVectorShuffle(WidenVT, dl, + GetWidenedVector(N->getOperand(0)), + GetWidenedVector(N->getOperand(1)), + &MaskOps[0]); + } + } + } + + // Fall back to use extracts and build vector. + EVT EltVT = WidenVT.getVectorElementType(); + unsigned NumInElts = InVT.getVectorNumElements(); + SmallVector Ops(WidenNumElts); + unsigned Idx = 0; + for (unsigned i=0; i < NumOperands; ++i) { + SDValue InOp = N->getOperand(i); + if (InputWidened) + InOp = GetWidenedVector(InOp); + for (unsigned j=0; j < NumInElts; ++j) + Ops[Idx++] = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, EltVT, InOp, + DAG.getIntPtrConstant(j)); + } + SDValue UndefVal = DAG.getUNDEF(EltVT); + for (; Idx < WidenNumElts; ++Idx) + Ops[Idx] = UndefVal; + return DAG.getNode(ISD::BUILD_VECTOR, dl, WidenVT, &Ops[0], WidenNumElts); +} + +SDValue DAGTypeLegalizer::WidenVecRes_CONVERT_RNDSAT(SDNode *N) { + DebugLoc dl = N->getDebugLoc(); + SDValue InOp = N->getOperand(0); + SDValue RndOp = N->getOperand(3); + SDValue SatOp = N->getOperand(4); + + EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); + unsigned WidenNumElts = WidenVT.getVectorNumElements(); + + EVT InVT = InOp.getValueType(); + EVT InEltVT = InVT.getVectorElementType(); + EVT InWidenVT = EVT::getVectorVT(*DAG.getContext(), InEltVT, WidenNumElts); + + SDValue DTyOp = DAG.getValueType(WidenVT); + SDValue STyOp = DAG.getValueType(InWidenVT); + ISD::CvtCode CvtCode = cast(N)->getCvtCode(); + + unsigned InVTNumElts = InVT.getVectorNumElements(); + if (getTypeAction(InVT) == WidenVector) { + InOp = GetWidenedVector(InOp); + InVT = InOp.getValueType(); + InVTNumElts = InVT.getVectorNumElements(); + if (InVTNumElts == WidenNumElts) + return DAG.getConvertRndSat(WidenVT, dl, InOp, DTyOp, STyOp, RndOp, + SatOp, CvtCode); + } + + if (TLI.isTypeLegal(InWidenVT)) { + // Because the result and the input are different vector types, widening + // the result could create a legal type but widening the input might make + // it an illegal type that might lead to repeatedly splitting the input + // and then widening it. To avoid this, we widen the input only if + // it results in a legal type. + if (WidenNumElts % InVTNumElts == 0) { + // Widen the input and call convert on the widened input vector. + unsigned NumConcat = WidenNumElts/InVTNumElts; + SmallVector Ops(NumConcat); + Ops[0] = InOp; + SDValue UndefVal = DAG.getUNDEF(InVT); + for (unsigned i = 1; i != NumConcat; ++i) { + Ops[i] = UndefVal; + } + InOp = DAG.getNode(ISD::CONCAT_VECTORS, dl, InWidenVT, &Ops[0],NumConcat); + return DAG.getConvertRndSat(WidenVT, dl, InOp, DTyOp, STyOp, RndOp, + SatOp, CvtCode); + } + + if (InVTNumElts % WidenNumElts == 0) { + // Extract the input and convert the shorten input vector. + InOp = DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, InWidenVT, InOp, + DAG.getIntPtrConstant(0)); + return DAG.getConvertRndSat(WidenVT, dl, InOp, DTyOp, STyOp, RndOp, + SatOp, CvtCode); + } + } + + // Otherwise unroll into some nasty scalar code and rebuild the vector. + SmallVector Ops(WidenNumElts); + EVT EltVT = WidenVT.getVectorElementType(); + DTyOp = DAG.getValueType(EltVT); + STyOp = DAG.getValueType(InEltVT); + + unsigned MinElts = std::min(InVTNumElts, WidenNumElts); + unsigned i; + for (i=0; i < MinElts; ++i) { + SDValue ExtVal = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, InEltVT, InOp, + DAG.getIntPtrConstant(i)); + Ops[i] = DAG.getConvertRndSat(WidenVT, dl, ExtVal, DTyOp, STyOp, RndOp, + SatOp, CvtCode); + } + + SDValue UndefVal = DAG.getUNDEF(EltVT); + for (; i < WidenNumElts; ++i) + Ops[i] = UndefVal; + + return DAG.getNode(ISD::BUILD_VECTOR, dl, WidenVT, &Ops[0], WidenNumElts); +} + +SDValue DAGTypeLegalizer::WidenVecRes_EXTRACT_SUBVECTOR(SDNode *N) { + EVT VT = N->getValueType(0); + EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT); + unsigned WidenNumElts = WidenVT.getVectorNumElements(); + SDValue InOp = N->getOperand(0); + SDValue Idx = N->getOperand(1); + DebugLoc dl = N->getDebugLoc(); + + if (getTypeAction(InOp.getValueType()) == WidenVector) + InOp = GetWidenedVector(InOp); + + EVT InVT = InOp.getValueType(); + + ConstantSDNode *CIdx = dyn_cast(Idx); + if (CIdx) { + unsigned IdxVal = CIdx->getZExtValue(); + // Check if we can just return the input vector after widening. + if (IdxVal == 0 && InVT == WidenVT) + return InOp; + + // Check if we can extract from the vector. + unsigned InNumElts = InVT.getVectorNumElements(); + if (IdxVal % WidenNumElts == 0 && IdxVal + WidenNumElts < InNumElts) + return DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, WidenVT, InOp, Idx); + } + + // We could try widening the input to the right length but for now, extract + // the original elements, fill the rest with undefs and build a vector. + SmallVector Ops(WidenNumElts); + EVT EltVT = VT.getVectorElementType(); + EVT IdxVT = Idx.getValueType(); + unsigned NumElts = VT.getVectorNumElements(); + unsigned i; + if (CIdx) { + unsigned IdxVal = CIdx->getZExtValue(); + for (i=0; i < NumElts; ++i) + Ops[i] = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, EltVT, InOp, + DAG.getConstant(IdxVal+i, IdxVT)); + } else { + Ops[0] = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, EltVT, InOp, Idx); + for (i=1; i < NumElts; ++i) { + SDValue NewIdx = DAG.getNode(ISD::ADD, dl, Idx.getValueType(), Idx, + DAG.getConstant(i, IdxVT)); + Ops[i] = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, EltVT, InOp, NewIdx); + } + } + + SDValue UndefVal = DAG.getUNDEF(EltVT); + for (; i < WidenNumElts; ++i) + Ops[i] = UndefVal; + return DAG.getNode(ISD::BUILD_VECTOR, dl, WidenVT, &Ops[0], WidenNumElts); +} + +SDValue DAGTypeLegalizer::WidenVecRes_INSERT_VECTOR_ELT(SDNode *N) { + SDValue InOp = GetWidenedVector(N->getOperand(0)); + return DAG.getNode(ISD::INSERT_VECTOR_ELT, N->getDebugLoc(), + InOp.getValueType(), InOp, + N->getOperand(1), N->getOperand(2)); +} + +SDValue DAGTypeLegalizer::WidenVecRes_LOAD(SDNode *N) { + LoadSDNode *LD = cast(N); + EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), LD->getValueType(0)); + EVT LdVT = LD->getMemoryVT(); + DebugLoc dl = N->getDebugLoc(); + assert(LdVT.isVector() && WidenVT.isVector()); + + // Load information + SDValue Chain = LD->getChain(); + SDValue BasePtr = LD->getBasePtr(); + int SVOffset = LD->getSrcValueOffset(); + unsigned Align = LD->getAlignment(); + bool isVolatile = LD->isVolatile(); + const Value *SV = LD->getSrcValue(); + ISD::LoadExtType ExtType = LD->getExtensionType(); + + SDValue Result; + SmallVector LdChain; // Chain for the series of load + if (ExtType != ISD::NON_EXTLOAD) { + // For extension loads, we can not play the tricks of chopping legal + // vector types and bit cast it to the right type. Instead, we unroll + // the load and build a vector. + EVT EltVT = WidenVT.getVectorElementType(); + EVT LdEltVT = LdVT.getVectorElementType(); + unsigned NumElts = LdVT.getVectorNumElements(); + + // Load each element and widen + unsigned WidenNumElts = WidenVT.getVectorNumElements(); + SmallVector Ops(WidenNumElts); + unsigned Increment = LdEltVT.getSizeInBits() / 8; + Ops[0] = DAG.getExtLoad(ExtType, dl, EltVT, Chain, BasePtr, SV, SVOffset, + LdEltVT, isVolatile, Align); + LdChain.push_back(Ops[0].getValue(1)); + unsigned i = 0, Offset = Increment; + for (i=1; i < NumElts; ++i, Offset += Increment) { + SDValue NewBasePtr = DAG.getNode(ISD::ADD, dl, BasePtr.getValueType(), + BasePtr, DAG.getIntPtrConstant(Offset)); + Ops[i] = DAG.getExtLoad(ExtType, dl, EltVT, Chain, NewBasePtr, SV, + SVOffset + Offset, LdEltVT, isVolatile, Align); + LdChain.push_back(Ops[i].getValue(1)); + } + + // Fill the rest with undefs + SDValue UndefVal = DAG.getUNDEF(EltVT); + for (; i != WidenNumElts; ++i) + Ops[i] = UndefVal; + + Result = DAG.getNode(ISD::BUILD_VECTOR, dl, WidenVT, &Ops[0], Ops.size()); + } else { + assert(LdVT.getVectorElementType() == WidenVT.getVectorElementType()); + unsigned int LdWidth = LdVT.getSizeInBits(); + Result = GenWidenVectorLoads(LdChain, Chain, BasePtr, SV, SVOffset, + Align, isVolatile, LdWidth, WidenVT, dl); + } + + // If we generate a single load, we can use that for the chain. Otherwise, + // build a factor node to remember the multiple loads are independent and + // chain to that. + SDValue NewChain; + if (LdChain.size() == 1) + NewChain = LdChain[0]; + else + NewChain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, &LdChain[0], + LdChain.size()); + + // Modified the chain - switch anything that used the old chain to use + // the new one. + ReplaceValueWith(SDValue(N, 1), NewChain); + + return Result; +} + +SDValue DAGTypeLegalizer::WidenVecRes_SCALAR_TO_VECTOR(SDNode *N) { + EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); + return DAG.getNode(ISD::SCALAR_TO_VECTOR, N->getDebugLoc(), + WidenVT, N->getOperand(0)); +} + +SDValue DAGTypeLegalizer::WidenVecRes_SELECT(SDNode *N) { + EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); + unsigned WidenNumElts = WidenVT.getVectorNumElements(); + + SDValue Cond1 = N->getOperand(0); + EVT CondVT = Cond1.getValueType(); + if (CondVT.isVector()) { + EVT CondEltVT = CondVT.getVectorElementType(); + EVT CondWidenVT = EVT::getVectorVT(*DAG.getContext(), CondEltVT, WidenNumElts); + if (getTypeAction(CondVT) == WidenVector) + Cond1 = GetWidenedVector(Cond1); + + if (Cond1.getValueType() != CondWidenVT) + Cond1 = ModifyToType(Cond1, CondWidenVT); + } + + SDValue InOp1 = GetWidenedVector(N->getOperand(1)); + SDValue InOp2 = GetWidenedVector(N->getOperand(2)); + assert(InOp1.getValueType() == WidenVT && InOp2.getValueType() == WidenVT); + return DAG.getNode(ISD::SELECT, N->getDebugLoc(), + WidenVT, Cond1, InOp1, InOp2); +} + +SDValue DAGTypeLegalizer::WidenVecRes_SELECT_CC(SDNode *N) { + SDValue InOp1 = GetWidenedVector(N->getOperand(2)); + SDValue InOp2 = GetWidenedVector(N->getOperand(3)); + return DAG.getNode(ISD::SELECT_CC, N->getDebugLoc(), + InOp1.getValueType(), N->getOperand(0), + N->getOperand(1), InOp1, InOp2, N->getOperand(4)); +} + +SDValue DAGTypeLegalizer::WidenVecRes_UNDEF(SDNode *N) { + EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); + return DAG.getUNDEF(WidenVT); +} + +SDValue DAGTypeLegalizer::WidenVecRes_VECTOR_SHUFFLE(ShuffleVectorSDNode *N) { + EVT VT = N->getValueType(0); + DebugLoc dl = N->getDebugLoc(); + + EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT); + unsigned NumElts = VT.getVectorNumElements(); + unsigned WidenNumElts = WidenVT.getVectorNumElements(); + + SDValue InOp1 = GetWidenedVector(N->getOperand(0)); + SDValue InOp2 = GetWidenedVector(N->getOperand(1)); + + // Adjust mask based on new input vector length. + SmallVector NewMask; + for (unsigned i = 0; i != NumElts; ++i) { + int Idx = N->getMaskElt(i); + if (Idx < (int)NumElts) + NewMask.push_back(Idx); + else + NewMask.push_back(Idx - NumElts + WidenNumElts); + } + for (unsigned i = NumElts; i != WidenNumElts; ++i) + NewMask.push_back(-1); + return DAG.getVectorShuffle(WidenVT, dl, InOp1, InOp2, &NewMask[0]); +} + +SDValue DAGTypeLegalizer::WidenVecRes_VSETCC(SDNode *N) { + EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); + unsigned WidenNumElts = WidenVT.getVectorNumElements(); + + SDValue InOp1 = N->getOperand(0); + EVT InVT = InOp1.getValueType(); + assert(InVT.isVector() && "can not widen non vector type"); + EVT WidenInVT = EVT::getVectorVT(*DAG.getContext(), InVT.getVectorElementType(), WidenNumElts); + InOp1 = GetWidenedVector(InOp1); + SDValue InOp2 = GetWidenedVector(N->getOperand(1)); + + // Assume that the input and output will be widen appropriately. If not, + // we will have to unroll it at some point. + assert(InOp1.getValueType() == WidenInVT && + InOp2.getValueType() == WidenInVT && + "Input not widened to expected type!"); + return DAG.getNode(ISD::VSETCC, N->getDebugLoc(), + WidenVT, InOp1, InOp2, N->getOperand(2)); +} + + +//===----------------------------------------------------------------------===// +// Widen Vector Operand +//===----------------------------------------------------------------------===// +bool DAGTypeLegalizer::WidenVectorOperand(SDNode *N, unsigned ResNo) { + DEBUG(errs() << "Widen node operand " << ResNo << ": "; + N->dump(&DAG); + errs() << "\n"); + SDValue Res = SDValue(); + + switch (N->getOpcode()) { + default: +#ifndef NDEBUG + errs() << "WidenVectorOperand op #" << ResNo << ": "; + N->dump(&DAG); + errs() << "\n"; +#endif + llvm_unreachable("Do not know how to widen this operator's operand!"); + + case ISD::BIT_CONVERT: Res = WidenVecOp_BIT_CONVERT(N); break; + case ISD::CONCAT_VECTORS: Res = WidenVecOp_CONCAT_VECTORS(N); break; + case ISD::EXTRACT_SUBVECTOR: Res = WidenVecOp_EXTRACT_SUBVECTOR(N); break; + case ISD::EXTRACT_VECTOR_ELT: Res = WidenVecOp_EXTRACT_VECTOR_ELT(N); break; + case ISD::STORE: Res = WidenVecOp_STORE(N); break; + + case ISD::FP_ROUND: + case ISD::FP_TO_SINT: + case ISD::FP_TO_UINT: + case ISD::SINT_TO_FP: + case ISD::UINT_TO_FP: + case ISD::TRUNCATE: + case ISD::SIGN_EXTEND: + case ISD::ZERO_EXTEND: + case ISD::ANY_EXTEND: + Res = WidenVecOp_Convert(N); + break; + } + + // If Res is null, the sub-method took care of registering the result. + if (!Res.getNode()) return false; + + // If the result is N, the sub-method updated N in place. Tell the legalizer + // core about this. + if (Res.getNode() == N) + return true; + + + assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 1 && + "Invalid operand expansion"); + + ReplaceValueWith(SDValue(N, 0), Res); + return false; +} + +SDValue DAGTypeLegalizer::WidenVecOp_Convert(SDNode *N) { + // Since the result is legal and the input is illegal, it is unlikely + // that we can fix the input to a legal type so unroll the convert + // into some scalar code and create a nasty build vector. + EVT VT = N->getValueType(0); + EVT EltVT = VT.getVectorElementType(); + DebugLoc dl = N->getDebugLoc(); + unsigned NumElts = VT.getVectorNumElements(); + SDValue InOp = N->getOperand(0); + if (getTypeAction(InOp.getValueType()) == WidenVector) + InOp = GetWidenedVector(InOp); + EVT InVT = InOp.getValueType(); + EVT InEltVT = InVT.getVectorElementType(); + + unsigned Opcode = N->getOpcode(); + SmallVector Ops(NumElts); + for (unsigned i=0; i < NumElts; ++i) + Ops[i] = DAG.getNode(Opcode, dl, EltVT, + DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, InEltVT, InOp, + DAG.getIntPtrConstant(i))); + + return DAG.getNode(ISD::BUILD_VECTOR, dl, VT, &Ops[0], NumElts); +} + +SDValue DAGTypeLegalizer::WidenVecOp_BIT_CONVERT(SDNode *N) { + EVT VT = N->getValueType(0); + SDValue InOp = GetWidenedVector(N->getOperand(0)); + EVT InWidenVT = InOp.getValueType(); + DebugLoc dl = N->getDebugLoc(); + + // Check if we can convert between two legal vector types and extract. + unsigned InWidenSize = InWidenVT.getSizeInBits(); + unsigned Size = VT.getSizeInBits(); + if (InWidenSize % Size == 0 && !VT.isVector()) { + unsigned NewNumElts = InWidenSize / Size; + EVT NewVT = EVT::getVectorVT(*DAG.getContext(), VT, NewNumElts); + if (TLI.isTypeLegal(NewVT)) { + SDValue BitOp = DAG.getNode(ISD::BIT_CONVERT, dl, NewVT, InOp); + return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, VT, BitOp, + DAG.getIntPtrConstant(0)); + } + } + + return CreateStackStoreLoad(InOp, VT); +} + +SDValue DAGTypeLegalizer::WidenVecOp_CONCAT_VECTORS(SDNode *N) { + // If the input vector is not legal, it is likely that we will not find a + // legal vector of the same size. Replace the concatenate vector with a + // nasty build vector. + EVT VT = N->getValueType(0); + EVT EltVT = VT.getVectorElementType(); + DebugLoc dl = N->getDebugLoc(); + unsigned NumElts = VT.getVectorNumElements(); + SmallVector Ops(NumElts); + + EVT InVT = N->getOperand(0).getValueType(); + unsigned NumInElts = InVT.getVectorNumElements(); + + unsigned Idx = 0; + unsigned NumOperands = N->getNumOperands(); + for (unsigned i=0; i < NumOperands; ++i) { + SDValue InOp = N->getOperand(i); + if (getTypeAction(InOp.getValueType()) == WidenVector) + InOp = GetWidenedVector(InOp); + for (unsigned j=0; j < NumInElts; ++j) + Ops[Idx++] = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, EltVT, InOp, + DAG.getIntPtrConstant(j)); + } + return DAG.getNode(ISD::BUILD_VECTOR, dl, VT, &Ops[0], NumElts); +} + +SDValue DAGTypeLegalizer::WidenVecOp_EXTRACT_SUBVECTOR(SDNode *N) { + SDValue InOp = GetWidenedVector(N->getOperand(0)); + return DAG.getNode(ISD::EXTRACT_SUBVECTOR, N->getDebugLoc(), + N->getValueType(0), InOp, N->getOperand(1)); +} + +SDValue DAGTypeLegalizer::WidenVecOp_EXTRACT_VECTOR_ELT(SDNode *N) { + SDValue InOp = GetWidenedVector(N->getOperand(0)); + return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, N->getDebugLoc(), + N->getValueType(0), InOp, N->getOperand(1)); +} + +SDValue DAGTypeLegalizer::WidenVecOp_STORE(SDNode *N) { + // We have to widen the value but we want only to store the original + // vector type. + StoreSDNode *ST = cast(N); + SDValue Chain = ST->getChain(); + SDValue BasePtr = ST->getBasePtr(); + const Value *SV = ST->getSrcValue(); + int SVOffset = ST->getSrcValueOffset(); + unsigned Align = ST->getAlignment(); + bool isVolatile = ST->isVolatile(); + SDValue ValOp = GetWidenedVector(ST->getValue()); + DebugLoc dl = N->getDebugLoc(); + + EVT StVT = ST->getMemoryVT(); + EVT ValVT = ValOp.getValueType(); + // It must be true that we the widen vector type is bigger than where + // we need to store. + assert(StVT.isVector() && ValOp.getValueType().isVector()); + assert(StVT.bitsLT(ValOp.getValueType())); + + SmallVector StChain; + if (ST->isTruncatingStore()) { + // For truncating stores, we can not play the tricks of chopping legal + // vector types and bit cast it to the right type. Instead, we unroll + // the store. + EVT StEltVT = StVT.getVectorElementType(); + EVT ValEltVT = ValVT.getVectorElementType(); + unsigned Increment = ValEltVT.getSizeInBits() / 8; + unsigned NumElts = StVT.getVectorNumElements(); + SDValue EOp = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, ValEltVT, ValOp, + DAG.getIntPtrConstant(0)); + StChain.push_back(DAG.getTruncStore(Chain, dl, EOp, BasePtr, SV, + SVOffset, StEltVT, + isVolatile, Align)); + unsigned Offset = Increment; + for (unsigned i=1; i < NumElts; ++i, Offset += Increment) { + SDValue NewBasePtr = DAG.getNode(ISD::ADD, dl, BasePtr.getValueType(), + BasePtr, DAG.getIntPtrConstant(Offset)); + SDValue EOp = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, ValEltVT, ValOp, + DAG.getIntPtrConstant(0)); + StChain.push_back(DAG.getTruncStore(Chain, dl, EOp, NewBasePtr, SV, + SVOffset + Offset, StEltVT, + isVolatile, MinAlign(Align, Offset))); + } + } + else { + assert(StVT.getVectorElementType() == ValVT.getVectorElementType()); + // Store value + GenWidenVectorStores(StChain, Chain, BasePtr, SV, SVOffset, + Align, isVolatile, ValOp, StVT.getSizeInBits(), dl); + } + if (StChain.size() == 1) + return StChain[0]; + else + return DAG.getNode(ISD::TokenFactor, dl, + MVT::Other,&StChain[0],StChain.size()); +} + +//===----------------------------------------------------------------------===// +// Vector Widening Utilities +//===----------------------------------------------------------------------===// + + +// Utility function to find a vector type and its associated element +// type from a preferred width and whose vector type must be the same size +// as the VecVT. +// TLI: Target lowering used to determine legal types. +// Width: Preferred width to store. +// VecVT: Vector value type whose size we must match. +// Returns NewVecVT and NewEltVT - the vector type and its associated +// element type. +static void FindAssocWidenVecType(SelectionDAG& DAG, + const TargetLowering &TLI, unsigned Width, + EVT VecVT, + EVT& NewEltVT, EVT& NewVecVT) { + unsigned EltWidth = Width + 1; + if (TLI.isTypeLegal(VecVT)) { + // We start with the preferred with, making it a power of 2 and find a + // legal vector type of that width. If not, we reduce it by another of 2. + // For incoming type is legal, this process will end as a vector of the + // smallest loadable type should always be legal. + do { + assert(EltWidth > 0); + EltWidth = 1 << Log2_32(EltWidth - 1); + NewEltVT = EVT::getIntegerVT(*DAG.getContext(), EltWidth); + unsigned NumElts = VecVT.getSizeInBits() / EltWidth; + NewVecVT = EVT::getVectorVT(*DAG.getContext(), NewEltVT, NumElts); + } while (!TLI.isTypeLegal(NewVecVT) || + VecVT.getSizeInBits() != NewVecVT.getSizeInBits()); + } else { + // The incoming vector type is illegal and is the result of widening + // a vector to a power of 2. In this case, we will use the preferred + // with as long as it is a multiple of the incoming vector length. + // The legalization process will eventually make this into a legal type + // and remove the illegal bit converts (which would turn to stack converts + // if they are allow to exist). + do { + assert(EltWidth > 0); + EltWidth = 1 << Log2_32(EltWidth - 1); + NewEltVT = EVT::getIntegerVT(*DAG.getContext(), EltWidth); + unsigned NumElts = VecVT.getSizeInBits() / EltWidth; + NewVecVT = EVT::getVectorVT(*DAG.getContext(), NewEltVT, NumElts); + } while (!TLI.isTypeLegal(NewEltVT) || + VecVT.getSizeInBits() != NewVecVT.getSizeInBits()); + } +} + +SDValue DAGTypeLegalizer::GenWidenVectorLoads(SmallVector& LdChain, + SDValue Chain, + SDValue BasePtr, + const Value *SV, + int SVOffset, + unsigned Alignment, + bool isVolatile, + unsigned LdWidth, + EVT ResType, + DebugLoc dl) { + // The strategy assumes that we can efficiently load powers of two widths. + // The routines chops the vector into the largest power of 2 load and + // can be inserted into a legal vector and then cast the result into the + // vector type we want. This avoids unnecessary stack converts. + + // TODO: If the Ldwidth is legal, alignment is the same as the LdWidth, and + // the load is nonvolatile, we an use a wider load for the value. + + // Find the vector type that can load from. + EVT NewEltVT, NewVecVT; + unsigned NewEltVTWidth; + FindAssocWidenVecType(DAG, TLI, LdWidth, ResType, NewEltVT, NewVecVT); + NewEltVTWidth = NewEltVT.getSizeInBits(); + + SDValue LdOp = DAG.getLoad(NewEltVT, dl, Chain, BasePtr, SV, SVOffset, + isVolatile, Alignment); + SDValue VecOp = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, NewVecVT, LdOp); + LdChain.push_back(LdOp.getValue(1)); + + // Check if we can load the element with one instruction + if (LdWidth == NewEltVTWidth) { + return DAG.getNode(ISD::BIT_CONVERT, dl, ResType, VecOp); + } + + unsigned Idx = 1; + LdWidth -= NewEltVTWidth; + unsigned Offset = 0; + + while (LdWidth > 0) { + unsigned Increment = NewEltVTWidth / 8; + Offset += Increment; + BasePtr = DAG.getNode(ISD::ADD, dl, BasePtr.getValueType(), BasePtr, + DAG.getIntPtrConstant(Increment)); + + if (LdWidth < NewEltVTWidth) { + // Our current type we are using is too large, use a smaller size by + // using a smaller power of 2 + unsigned oNewEltVTWidth = NewEltVTWidth; + FindAssocWidenVecType(DAG, TLI, LdWidth, ResType, NewEltVT, NewVecVT); + NewEltVTWidth = NewEltVT.getSizeInBits(); + // Readjust position and vector position based on new load type + Idx = Idx * (oNewEltVTWidth/NewEltVTWidth); + VecOp = DAG.getNode(ISD::BIT_CONVERT, dl, NewVecVT, VecOp); + } + + SDValue LdOp = DAG.getLoad(NewEltVT, dl, Chain, BasePtr, SV, + SVOffset+Offset, isVolatile, + MinAlign(Alignment, Offset)); + LdChain.push_back(LdOp.getValue(1)); + VecOp = DAG.getNode(ISD::INSERT_VECTOR_ELT, dl, NewVecVT, VecOp, LdOp, + DAG.getIntPtrConstant(Idx++)); + + LdWidth -= NewEltVTWidth; + } + + return DAG.getNode(ISD::BIT_CONVERT, dl, ResType, VecOp); +} + +void DAGTypeLegalizer::GenWidenVectorStores(SmallVector& StChain, + SDValue Chain, + SDValue BasePtr, + const Value *SV, + int SVOffset, + unsigned Alignment, + bool isVolatile, + SDValue ValOp, + unsigned StWidth, + DebugLoc dl) { + // Breaks the stores into a series of power of 2 width stores. For any + // width, we convert the vector to the vector of element size that we + // want to store. This avoids requiring a stack convert. + + // Find a width of the element type we can store with + EVT WidenVT = ValOp.getValueType(); + EVT NewEltVT, NewVecVT; + + FindAssocWidenVecType(DAG, TLI, StWidth, WidenVT, NewEltVT, NewVecVT); + unsigned NewEltVTWidth = NewEltVT.getSizeInBits(); + + SDValue VecOp = DAG.getNode(ISD::BIT_CONVERT, dl, NewVecVT, ValOp); + SDValue EOp = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, NewEltVT, VecOp, + DAG.getIntPtrConstant(0)); + SDValue StOp = DAG.getStore(Chain, dl, EOp, BasePtr, SV, SVOffset, + isVolatile, Alignment); + StChain.push_back(StOp); + + // Check if we are done + if (StWidth == NewEltVTWidth) { + return; + } + + unsigned Idx = 1; + StWidth -= NewEltVTWidth; + unsigned Offset = 0; + + while (StWidth > 0) { + unsigned Increment = NewEltVTWidth / 8; + Offset += Increment; + BasePtr = DAG.getNode(ISD::ADD, dl, BasePtr.getValueType(), BasePtr, + DAG.getIntPtrConstant(Increment)); + + if (StWidth < NewEltVTWidth) { + // Our current type we are using is too large, use a smaller size by + // using a smaller power of 2 + unsigned oNewEltVTWidth = NewEltVTWidth; + FindAssocWidenVecType(DAG, TLI, StWidth, WidenVT, NewEltVT, NewVecVT); + NewEltVTWidth = NewEltVT.getSizeInBits(); + // Readjust position and vector position based on new load type + Idx = Idx * (oNewEltVTWidth/NewEltVTWidth); + VecOp = DAG.getNode(ISD::BIT_CONVERT, dl, NewVecVT, VecOp); + } + + EOp = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, NewEltVT, VecOp, + DAG.getIntPtrConstant(Idx++)); + StChain.push_back(DAG.getStore(Chain, dl, EOp, BasePtr, SV, + SVOffset + Offset, isVolatile, + MinAlign(Alignment, Offset))); + StWidth -= NewEltVTWidth; + } +} + +/// Modifies a vector input (widen or narrows) to a vector of NVT. The +/// input vector must have the same element type as NVT. +SDValue DAGTypeLegalizer::ModifyToType(SDValue InOp, EVT NVT) { + // Note that InOp might have been widened so it might already have + // the right width or it might need be narrowed. + EVT InVT = InOp.getValueType(); + assert(InVT.getVectorElementType() == NVT.getVectorElementType() && + "input and widen element type must match"); + DebugLoc dl = InOp.getDebugLoc(); + + // Check if InOp already has the right width. + if (InVT == NVT) + return InOp; + + unsigned InNumElts = InVT.getVectorNumElements(); + unsigned WidenNumElts = NVT.getVectorNumElements(); + if (WidenNumElts > InNumElts && WidenNumElts % InNumElts == 0) { + unsigned NumConcat = WidenNumElts / InNumElts; + SmallVector Ops(NumConcat); + SDValue UndefVal = DAG.getUNDEF(InVT); + Ops[0] = InOp; + for (unsigned i = 1; i != NumConcat; ++i) + Ops[i] = UndefVal; + + return DAG.getNode(ISD::CONCAT_VECTORS, dl, NVT, &Ops[0], NumConcat); + } + + if (WidenNumElts < InNumElts && InNumElts % WidenNumElts) + return DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, NVT, InOp, + DAG.getIntPtrConstant(0)); + + // Fall back to extract and build. + SmallVector Ops(WidenNumElts); + EVT EltVT = NVT.getVectorElementType(); + unsigned MinNumElts = std::min(WidenNumElts, InNumElts); + unsigned Idx; + for (Idx = 0; Idx < MinNumElts; ++Idx) + Ops[Idx] = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, EltVT, InOp, + DAG.getIntPtrConstant(Idx)); + + SDValue UndefVal = DAG.getUNDEF(EltVT); + for ( ; Idx < WidenNumElts; ++Idx) + Ops[Idx] = UndefVal; + return DAG.getNode(ISD::BUILD_VECTOR, dl, NVT, &Ops[0], WidenNumElts); +} diff --git a/libclamav/c++/llvm/lib/CodeGen/SelectionDAG/Makefile b/libclamav/c++/llvm/lib/CodeGen/SelectionDAG/Makefile new file mode 100644 index 000000000..73f0b5da8 --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/SelectionDAG/Makefile @@ -0,0 +1,13 @@ +##===- lib/CodeGen/SelectionDAG/Makefile -------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## +LEVEL = ../../.. +LIBRARYNAME = LLVMSelectionDAG +PARALLEL_DIRS = + +include $(LEVEL)/Makefile.common diff --git a/libclamav/c++/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGFast.cpp b/libclamav/c++/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGFast.cpp new file mode 100644 index 000000000..4045a34a8 --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGFast.cpp @@ -0,0 +1,605 @@ +//===----- ScheduleDAGFast.cpp - Fast poor list scheduler -----------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This implements a fast scheduler. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "pre-RA-sched" +#include "ScheduleDAGSDNodes.h" +#include "llvm/CodeGen/SchedulerRegistry.h" +#include "llvm/CodeGen/SelectionDAGISel.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Support/Debug.h" +#include "llvm/ADT/SmallSet.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +STATISTIC(NumUnfolds, "Number of nodes unfolded"); +STATISTIC(NumDups, "Number of duplicated nodes"); +STATISTIC(NumPRCopies, "Number of physical copies"); + +static RegisterScheduler + fastDAGScheduler("fast", "Fast suboptimal list scheduling", + createFastDAGScheduler); + +namespace { + /// FastPriorityQueue - A degenerate priority queue that considers + /// all nodes to have the same priority. + /// + struct FastPriorityQueue { + SmallVector Queue; + + bool empty() const { return Queue.empty(); } + + void push(SUnit *U) { + Queue.push_back(U); + } + + SUnit *pop() { + if (empty()) return NULL; + SUnit *V = Queue.back(); + Queue.pop_back(); + return V; + } + }; + +//===----------------------------------------------------------------------===// +/// ScheduleDAGFast - The actual "fast" list scheduler implementation. +/// +class ScheduleDAGFast : public ScheduleDAGSDNodes { +private: + /// AvailableQueue - The priority queue to use for the available SUnits. + FastPriorityQueue AvailableQueue; + + /// LiveRegDefs - A set of physical registers and their definition + /// that are "live". These nodes must be scheduled before any other nodes that + /// modifies the registers can be scheduled. + unsigned NumLiveRegs; + std::vector LiveRegDefs; + std::vector LiveRegCycles; + +public: + ScheduleDAGFast(MachineFunction &mf) + : ScheduleDAGSDNodes(mf) {} + + void Schedule(); + + /// AddPred - adds a predecessor edge to SUnit SU. + /// This returns true if this is a new predecessor. + void AddPred(SUnit *SU, const SDep &D) { + SU->addPred(D); + } + + /// RemovePred - removes a predecessor edge from SUnit SU. + /// This returns true if an edge was removed. + void RemovePred(SUnit *SU, const SDep &D) { + SU->removePred(D); + } + +private: + void ReleasePred(SUnit *SU, SDep *PredEdge); + void ReleasePredecessors(SUnit *SU, unsigned CurCycle); + void ScheduleNodeBottomUp(SUnit*, unsigned); + SUnit *CopyAndMoveSuccessors(SUnit*); + void InsertCopiesAndMoveSuccs(SUnit*, unsigned, + const TargetRegisterClass*, + const TargetRegisterClass*, + SmallVector&); + bool DelayForLiveRegsBottomUp(SUnit*, SmallVector&); + void ListScheduleBottomUp(); + + /// ForceUnitLatencies - The fast scheduler doesn't care about real latencies. + bool ForceUnitLatencies() const { return true; } +}; +} // end anonymous namespace + + +/// Schedule - Schedule the DAG using list scheduling. +void ScheduleDAGFast::Schedule() { + DEBUG(errs() << "********** List Scheduling **********\n"); + + NumLiveRegs = 0; + LiveRegDefs.resize(TRI->getNumRegs(), NULL); + LiveRegCycles.resize(TRI->getNumRegs(), 0); + + // Build the scheduling graph. + BuildSchedGraph(NULL); + + DEBUG(for (unsigned su = 0, e = SUnits.size(); su != e; ++su) + SUnits[su].dumpAll(this)); + + // Execute the actual scheduling loop. + ListScheduleBottomUp(); +} + +//===----------------------------------------------------------------------===// +// Bottom-Up Scheduling +//===----------------------------------------------------------------------===// + +/// ReleasePred - Decrement the NumSuccsLeft count of a predecessor. Add it to +/// the AvailableQueue if the count reaches zero. Also update its cycle bound. +void ScheduleDAGFast::ReleasePred(SUnit *SU, SDep *PredEdge) { + SUnit *PredSU = PredEdge->getSUnit(); + +#ifndef NDEBUG + if (PredSU->NumSuccsLeft == 0) { + errs() << "*** Scheduling failed! ***\n"; + PredSU->dump(this); + errs() << " has been released too many times!\n"; + llvm_unreachable(0); + } +#endif + --PredSU->NumSuccsLeft; + + // If all the node's successors are scheduled, this node is ready + // to be scheduled. Ignore the special EntrySU node. + if (PredSU->NumSuccsLeft == 0 && PredSU != &EntrySU) { + PredSU->isAvailable = true; + AvailableQueue.push(PredSU); + } +} + +void ScheduleDAGFast::ReleasePredecessors(SUnit *SU, unsigned CurCycle) { + // Bottom up: release predecessors + for (SUnit::pred_iterator I = SU->Preds.begin(), E = SU->Preds.end(); + I != E; ++I) { + ReleasePred(SU, &*I); + if (I->isAssignedRegDep()) { + // This is a physical register dependency and it's impossible or + // expensive to copy the register. Make sure nothing that can + // clobber the register is scheduled between the predecessor and + // this node. + if (!LiveRegDefs[I->getReg()]) { + ++NumLiveRegs; + LiveRegDefs[I->getReg()] = I->getSUnit(); + LiveRegCycles[I->getReg()] = CurCycle; + } + } + } +} + +/// ScheduleNodeBottomUp - Add the node to the schedule. Decrement the pending +/// count of its predecessors. If a predecessor pending count is zero, add it to +/// the Available queue. +void ScheduleDAGFast::ScheduleNodeBottomUp(SUnit *SU, unsigned CurCycle) { + DEBUG(errs() << "*** Scheduling [" << CurCycle << "]: "); + DEBUG(SU->dump(this)); + + assert(CurCycle >= SU->getHeight() && "Node scheduled below its height!"); + SU->setHeightToAtLeast(CurCycle); + Sequence.push_back(SU); + + ReleasePredecessors(SU, CurCycle); + + // Release all the implicit physical register defs that are live. + for (SUnit::succ_iterator I = SU->Succs.begin(), E = SU->Succs.end(); + I != E; ++I) { + if (I->isAssignedRegDep()) { + if (LiveRegCycles[I->getReg()] == I->getSUnit()->getHeight()) { + assert(NumLiveRegs > 0 && "NumLiveRegs is already zero!"); + assert(LiveRegDefs[I->getReg()] == SU && + "Physical register dependency violated?"); + --NumLiveRegs; + LiveRegDefs[I->getReg()] = NULL; + LiveRegCycles[I->getReg()] = 0; + } + } + } + + SU->isScheduled = true; +} + +/// CopyAndMoveSuccessors - Clone the specified node and move its scheduled +/// successors to the newly created node. +SUnit *ScheduleDAGFast::CopyAndMoveSuccessors(SUnit *SU) { + if (SU->getNode()->getFlaggedNode()) + return NULL; + + SDNode *N = SU->getNode(); + if (!N) + return NULL; + + SUnit *NewSU; + bool TryUnfold = false; + for (unsigned i = 0, e = N->getNumValues(); i != e; ++i) { + EVT VT = N->getValueType(i); + if (VT == MVT::Flag) + return NULL; + else if (VT == MVT::Other) + TryUnfold = true; + } + for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) { + const SDValue &Op = N->getOperand(i); + EVT VT = Op.getNode()->getValueType(Op.getResNo()); + if (VT == MVT::Flag) + return NULL; + } + + if (TryUnfold) { + SmallVector NewNodes; + if (!TII->unfoldMemoryOperand(*DAG, N, NewNodes)) + return NULL; + + DEBUG(errs() << "Unfolding SU # " << SU->NodeNum << "\n"); + assert(NewNodes.size() == 2 && "Expected a load folding node!"); + + N = NewNodes[1]; + SDNode *LoadNode = NewNodes[0]; + unsigned NumVals = N->getNumValues(); + unsigned OldNumVals = SU->getNode()->getNumValues(); + for (unsigned i = 0; i != NumVals; ++i) + DAG->ReplaceAllUsesOfValueWith(SDValue(SU->getNode(), i), SDValue(N, i)); + DAG->ReplaceAllUsesOfValueWith(SDValue(SU->getNode(), OldNumVals-1), + SDValue(LoadNode, 1)); + + SUnit *NewSU = NewSUnit(N); + assert(N->getNodeId() == -1 && "Node already inserted!"); + N->setNodeId(NewSU->NodeNum); + + const TargetInstrDesc &TID = TII->get(N->getMachineOpcode()); + for (unsigned i = 0; i != TID.getNumOperands(); ++i) { + if (TID.getOperandConstraint(i, TOI::TIED_TO) != -1) { + NewSU->isTwoAddress = true; + break; + } + } + if (TID.isCommutable()) + NewSU->isCommutable = true; + + // LoadNode may already exist. This can happen when there is another + // load from the same location and producing the same type of value + // but it has different alignment or volatileness. + bool isNewLoad = true; + SUnit *LoadSU; + if (LoadNode->getNodeId() != -1) { + LoadSU = &SUnits[LoadNode->getNodeId()]; + isNewLoad = false; + } else { + LoadSU = NewSUnit(LoadNode); + LoadNode->setNodeId(LoadSU->NodeNum); + } + + SDep ChainPred; + SmallVector ChainSuccs; + SmallVector LoadPreds; + SmallVector NodePreds; + SmallVector NodeSuccs; + for (SUnit::pred_iterator I = SU->Preds.begin(), E = SU->Preds.end(); + I != E; ++I) { + if (I->isCtrl()) + ChainPred = *I; + else if (I->getSUnit()->getNode() && + I->getSUnit()->getNode()->isOperandOf(LoadNode)) + LoadPreds.push_back(*I); + else + NodePreds.push_back(*I); + } + for (SUnit::succ_iterator I = SU->Succs.begin(), E = SU->Succs.end(); + I != E; ++I) { + if (I->isCtrl()) + ChainSuccs.push_back(*I); + else + NodeSuccs.push_back(*I); + } + + if (ChainPred.getSUnit()) { + RemovePred(SU, ChainPred); + if (isNewLoad) + AddPred(LoadSU, ChainPred); + } + for (unsigned i = 0, e = LoadPreds.size(); i != e; ++i) { + const SDep &Pred = LoadPreds[i]; + RemovePred(SU, Pred); + if (isNewLoad) { + AddPred(LoadSU, Pred); + } + } + for (unsigned i = 0, e = NodePreds.size(); i != e; ++i) { + const SDep &Pred = NodePreds[i]; + RemovePred(SU, Pred); + AddPred(NewSU, Pred); + } + for (unsigned i = 0, e = NodeSuccs.size(); i != e; ++i) { + SDep D = NodeSuccs[i]; + SUnit *SuccDep = D.getSUnit(); + D.setSUnit(SU); + RemovePred(SuccDep, D); + D.setSUnit(NewSU); + AddPred(SuccDep, D); + } + for (unsigned i = 0, e = ChainSuccs.size(); i != e; ++i) { + SDep D = ChainSuccs[i]; + SUnit *SuccDep = D.getSUnit(); + D.setSUnit(SU); + RemovePred(SuccDep, D); + if (isNewLoad) { + D.setSUnit(LoadSU); + AddPred(SuccDep, D); + } + } + if (isNewLoad) { + AddPred(NewSU, SDep(LoadSU, SDep::Order, LoadSU->Latency)); + } + + ++NumUnfolds; + + if (NewSU->NumSuccsLeft == 0) { + NewSU->isAvailable = true; + return NewSU; + } + SU = NewSU; + } + + DEBUG(errs() << "Duplicating SU # " << SU->NodeNum << "\n"); + NewSU = Clone(SU); + + // New SUnit has the exact same predecessors. + for (SUnit::pred_iterator I = SU->Preds.begin(), E = SU->Preds.end(); + I != E; ++I) + if (!I->isArtificial()) + AddPred(NewSU, *I); + + // Only copy scheduled successors. Cut them from old node's successor + // list and move them over. + SmallVector, 4> DelDeps; + for (SUnit::succ_iterator I = SU->Succs.begin(), E = SU->Succs.end(); + I != E; ++I) { + if (I->isArtificial()) + continue; + SUnit *SuccSU = I->getSUnit(); + if (SuccSU->isScheduled) { + SDep D = *I; + D.setSUnit(NewSU); + AddPred(SuccSU, D); + D.setSUnit(SU); + DelDeps.push_back(std::make_pair(SuccSU, D)); + } + } + for (unsigned i = 0, e = DelDeps.size(); i != e; ++i) + RemovePred(DelDeps[i].first, DelDeps[i].second); + + ++NumDups; + return NewSU; +} + +/// InsertCopiesAndMoveSuccs - Insert register copies and move all +/// scheduled successors of the given SUnit to the last copy. +void ScheduleDAGFast::InsertCopiesAndMoveSuccs(SUnit *SU, unsigned Reg, + const TargetRegisterClass *DestRC, + const TargetRegisterClass *SrcRC, + SmallVector &Copies) { + SUnit *CopyFromSU = NewSUnit(static_cast(NULL)); + CopyFromSU->CopySrcRC = SrcRC; + CopyFromSU->CopyDstRC = DestRC; + + SUnit *CopyToSU = NewSUnit(static_cast(NULL)); + CopyToSU->CopySrcRC = DestRC; + CopyToSU->CopyDstRC = SrcRC; + + // Only copy scheduled successors. Cut them from old node's successor + // list and move them over. + SmallVector, 4> DelDeps; + for (SUnit::succ_iterator I = SU->Succs.begin(), E = SU->Succs.end(); + I != E; ++I) { + if (I->isArtificial()) + continue; + SUnit *SuccSU = I->getSUnit(); + if (SuccSU->isScheduled) { + SDep D = *I; + D.setSUnit(CopyToSU); + AddPred(SuccSU, D); + DelDeps.push_back(std::make_pair(SuccSU, *I)); + } + } + for (unsigned i = 0, e = DelDeps.size(); i != e; ++i) { + RemovePred(DelDeps[i].first, DelDeps[i].second); + } + + AddPred(CopyFromSU, SDep(SU, SDep::Data, SU->Latency, Reg)); + AddPred(CopyToSU, SDep(CopyFromSU, SDep::Data, CopyFromSU->Latency, 0)); + + Copies.push_back(CopyFromSU); + Copies.push_back(CopyToSU); + + ++NumPRCopies; +} + +/// getPhysicalRegisterVT - Returns the ValueType of the physical register +/// definition of the specified node. +/// FIXME: Move to SelectionDAG? +static EVT getPhysicalRegisterVT(SDNode *N, unsigned Reg, + const TargetInstrInfo *TII) { + const TargetInstrDesc &TID = TII->get(N->getMachineOpcode()); + assert(TID.ImplicitDefs && "Physical reg def must be in implicit def list!"); + unsigned NumRes = TID.getNumDefs(); + for (const unsigned *ImpDef = TID.getImplicitDefs(); *ImpDef; ++ImpDef) { + if (Reg == *ImpDef) + break; + ++NumRes; + } + return N->getValueType(NumRes); +} + +/// DelayForLiveRegsBottomUp - Returns true if it is necessary to delay +/// scheduling of the given node to satisfy live physical register dependencies. +/// If the specific node is the last one that's available to schedule, do +/// whatever is necessary (i.e. backtracking or cloning) to make it possible. +bool ScheduleDAGFast::DelayForLiveRegsBottomUp(SUnit *SU, + SmallVector &LRegs){ + if (NumLiveRegs == 0) + return false; + + SmallSet RegAdded; + // If this node would clobber any "live" register, then it's not ready. + for (SUnit::pred_iterator I = SU->Preds.begin(), E = SU->Preds.end(); + I != E; ++I) { + if (I->isAssignedRegDep()) { + unsigned Reg = I->getReg(); + if (LiveRegDefs[Reg] && LiveRegDefs[Reg] != I->getSUnit()) { + if (RegAdded.insert(Reg)) + LRegs.push_back(Reg); + } + for (const unsigned *Alias = TRI->getAliasSet(Reg); + *Alias; ++Alias) + if (LiveRegDefs[*Alias] && LiveRegDefs[*Alias] != I->getSUnit()) { + if (RegAdded.insert(*Alias)) + LRegs.push_back(*Alias); + } + } + } + + for (SDNode *Node = SU->getNode(); Node; Node = Node->getFlaggedNode()) { + if (!Node->isMachineOpcode()) + continue; + const TargetInstrDesc &TID = TII->get(Node->getMachineOpcode()); + if (!TID.ImplicitDefs) + continue; + for (const unsigned *Reg = TID.ImplicitDefs; *Reg; ++Reg) { + if (LiveRegDefs[*Reg] && LiveRegDefs[*Reg] != SU) { + if (RegAdded.insert(*Reg)) + LRegs.push_back(*Reg); + } + for (const unsigned *Alias = TRI->getAliasSet(*Reg); + *Alias; ++Alias) + if (LiveRegDefs[*Alias] && LiveRegDefs[*Alias] != SU) { + if (RegAdded.insert(*Alias)) + LRegs.push_back(*Alias); + } + } + } + return !LRegs.empty(); +} + + +/// ListScheduleBottomUp - The main loop of list scheduling for bottom-up +/// schedulers. +void ScheduleDAGFast::ListScheduleBottomUp() { + unsigned CurCycle = 0; + + // Release any predecessors of the special Exit node. + ReleasePredecessors(&ExitSU, CurCycle); + + // Add root to Available queue. + if (!SUnits.empty()) { + SUnit *RootSU = &SUnits[DAG->getRoot().getNode()->getNodeId()]; + assert(RootSU->Succs.empty() && "Graph root shouldn't have successors!"); + RootSU->isAvailable = true; + AvailableQueue.push(RootSU); + } + + // While Available queue is not empty, grab the node with the highest + // priority. If it is not ready put it back. Schedule the node. + SmallVector NotReady; + DenseMap > LRegsMap; + Sequence.reserve(SUnits.size()); + while (!AvailableQueue.empty()) { + bool Delayed = false; + LRegsMap.clear(); + SUnit *CurSU = AvailableQueue.pop(); + while (CurSU) { + SmallVector LRegs; + if (!DelayForLiveRegsBottomUp(CurSU, LRegs)) + break; + Delayed = true; + LRegsMap.insert(std::make_pair(CurSU, LRegs)); + + CurSU->isPending = true; // This SU is not in AvailableQueue right now. + NotReady.push_back(CurSU); + CurSU = AvailableQueue.pop(); + } + + // All candidates are delayed due to live physical reg dependencies. + // Try code duplication or inserting cross class copies + // to resolve it. + if (Delayed && !CurSU) { + if (!CurSU) { + // Try duplicating the nodes that produces these + // "expensive to copy" values to break the dependency. In case even + // that doesn't work, insert cross class copies. + SUnit *TrySU = NotReady[0]; + SmallVector &LRegs = LRegsMap[TrySU]; + assert(LRegs.size() == 1 && "Can't handle this yet!"); + unsigned Reg = LRegs[0]; + SUnit *LRDef = LiveRegDefs[Reg]; + EVT VT = getPhysicalRegisterVT(LRDef->getNode(), Reg, TII); + const TargetRegisterClass *RC = + TRI->getPhysicalRegisterRegClass(Reg, VT); + const TargetRegisterClass *DestRC = TRI->getCrossCopyRegClass(RC); + + // If cross copy register class is null, then it must be possible copy + // the value directly. Do not try duplicate the def. + SUnit *NewDef = 0; + if (DestRC) + NewDef = CopyAndMoveSuccessors(LRDef); + else + DestRC = RC; + if (!NewDef) { + // Issue copies, these can be expensive cross register class copies. + SmallVector Copies; + InsertCopiesAndMoveSuccs(LRDef, Reg, DestRC, RC, Copies); + DEBUG(errs() << "Adding an edge from SU # " << TrySU->NodeNum + << " to SU #" << Copies.front()->NodeNum << "\n"); + AddPred(TrySU, SDep(Copies.front(), SDep::Order, /*Latency=*/1, + /*Reg=*/0, /*isNormalMemory=*/false, + /*isMustAlias=*/false, /*isArtificial=*/true)); + NewDef = Copies.back(); + } + + DEBUG(errs() << "Adding an edge from SU # " << NewDef->NodeNum + << " to SU #" << TrySU->NodeNum << "\n"); + LiveRegDefs[Reg] = NewDef; + AddPred(NewDef, SDep(TrySU, SDep::Order, /*Latency=*/1, + /*Reg=*/0, /*isNormalMemory=*/false, + /*isMustAlias=*/false, /*isArtificial=*/true)); + TrySU->isAvailable = false; + CurSU = NewDef; + } + + if (!CurSU) { + llvm_unreachable("Unable to resolve live physical register dependencies!"); + } + } + + // Add the nodes that aren't ready back onto the available list. + for (unsigned i = 0, e = NotReady.size(); i != e; ++i) { + NotReady[i]->isPending = false; + // May no longer be available due to backtracking. + if (NotReady[i]->isAvailable) + AvailableQueue.push(NotReady[i]); + } + NotReady.clear(); + + if (CurSU) + ScheduleNodeBottomUp(CurSU, CurCycle); + ++CurCycle; + } + + // Reverse the order since it is bottom up. + std::reverse(Sequence.begin(), Sequence.end()); + +#ifndef NDEBUG + VerifySchedule(/*isBottomUp=*/true); +#endif +} + +//===----------------------------------------------------------------------===// +// Public Constructor Functions +//===----------------------------------------------------------------------===// + +llvm::ScheduleDAGSDNodes * +llvm::createFastDAGScheduler(SelectionDAGISel *IS, CodeGenOpt::Level) { + return new ScheduleDAGFast(*IS->MF); +} diff --git a/libclamav/c++/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGList.cpp b/libclamav/c++/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGList.cpp new file mode 100644 index 000000000..faf21f7be --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGList.cpp @@ -0,0 +1,269 @@ +//===---- ScheduleDAGList.cpp - Implement a list scheduler for isel DAG ---===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This implements a top-down list scheduler, using standard algorithms. +// The basic approach uses a priority queue of available nodes to schedule. +// One at a time, nodes are taken from the priority queue (thus in priority +// order), checked for legality to schedule, and emitted if legal. +// +// Nodes may not be legal to schedule either due to structural hazards (e.g. +// pipeline or resource constraints) or because an input to the instruction has +// not completed execution. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "pre-RA-sched" +#include "ScheduleDAGSDNodes.h" +#include "llvm/CodeGen/LatencyPriorityQueue.h" +#include "llvm/CodeGen/ScheduleHazardRecognizer.h" +#include "llvm/CodeGen/SchedulerRegistry.h" +#include "llvm/CodeGen/SelectionDAGISel.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/ADT/PriorityQueue.h" +#include "llvm/ADT/Statistic.h" +#include +using namespace llvm; + +STATISTIC(NumNoops , "Number of noops inserted"); +STATISTIC(NumStalls, "Number of pipeline stalls"); + +static RegisterScheduler + tdListDAGScheduler("list-td", "Top-down list scheduler", + createTDListDAGScheduler); + +namespace { +//===----------------------------------------------------------------------===// +/// ScheduleDAGList - The actual list scheduler implementation. This supports +/// top-down scheduling. +/// +class ScheduleDAGList : public ScheduleDAGSDNodes { +private: + /// AvailableQueue - The priority queue to use for the available SUnits. + /// + SchedulingPriorityQueue *AvailableQueue; + + /// PendingQueue - This contains all of the instructions whose operands have + /// been issued, but their results are not ready yet (due to the latency of + /// the operation). Once the operands become available, the instruction is + /// added to the AvailableQueue. + std::vector PendingQueue; + + /// HazardRec - The hazard recognizer to use. + ScheduleHazardRecognizer *HazardRec; + +public: + ScheduleDAGList(MachineFunction &mf, + SchedulingPriorityQueue *availqueue, + ScheduleHazardRecognizer *HR) + : ScheduleDAGSDNodes(mf), + AvailableQueue(availqueue), HazardRec(HR) { + } + + ~ScheduleDAGList() { + delete HazardRec; + delete AvailableQueue; + } + + void Schedule(); + +private: + void ReleaseSucc(SUnit *SU, const SDep &D); + void ReleaseSuccessors(SUnit *SU); + void ScheduleNodeTopDown(SUnit *SU, unsigned CurCycle); + void ListScheduleTopDown(); +}; +} // end anonymous namespace + +/// Schedule - Schedule the DAG using list scheduling. +void ScheduleDAGList::Schedule() { + DEBUG(errs() << "********** List Scheduling **********\n"); + + // Build the scheduling graph. + BuildSchedGraph(NULL); + + AvailableQueue->initNodes(SUnits); + + ListScheduleTopDown(); + + AvailableQueue->releaseState(); +} + +//===----------------------------------------------------------------------===// +// Top-Down Scheduling +//===----------------------------------------------------------------------===// + +/// ReleaseSucc - Decrement the NumPredsLeft count of a successor. Add it to +/// the PendingQueue if the count reaches zero. Also update its cycle bound. +void ScheduleDAGList::ReleaseSucc(SUnit *SU, const SDep &D) { + SUnit *SuccSU = D.getSUnit(); + +#ifndef NDEBUG + if (SuccSU->NumPredsLeft == 0) { + errs() << "*** Scheduling failed! ***\n"; + SuccSU->dump(this); + errs() << " has been released too many times!\n"; + llvm_unreachable(0); + } +#endif + --SuccSU->NumPredsLeft; + + SuccSU->setDepthToAtLeast(SU->getDepth() + D.getLatency()); + + // If all the node's predecessors are scheduled, this node is ready + // to be scheduled. Ignore the special ExitSU node. + if (SuccSU->NumPredsLeft == 0 && SuccSU != &ExitSU) + PendingQueue.push_back(SuccSU); +} + +void ScheduleDAGList::ReleaseSuccessors(SUnit *SU) { + // Top down: release successors. + for (SUnit::succ_iterator I = SU->Succs.begin(), E = SU->Succs.end(); + I != E; ++I) { + assert(!I->isAssignedRegDep() && + "The list-td scheduler doesn't yet support physreg dependencies!"); + + ReleaseSucc(SU, *I); + } +} + +/// ScheduleNodeTopDown - Add the node to the schedule. Decrement the pending +/// count of its successors. If a successor pending count is zero, add it to +/// the Available queue. +void ScheduleDAGList::ScheduleNodeTopDown(SUnit *SU, unsigned CurCycle) { + DEBUG(errs() << "*** Scheduling [" << CurCycle << "]: "); + DEBUG(SU->dump(this)); + + Sequence.push_back(SU); + assert(CurCycle >= SU->getDepth() && "Node scheduled above its depth!"); + SU->setDepthToAtLeast(CurCycle); + + ReleaseSuccessors(SU); + SU->isScheduled = true; + AvailableQueue->ScheduledNode(SU); +} + +/// ListScheduleTopDown - The main loop of list scheduling for top-down +/// schedulers. +void ScheduleDAGList::ListScheduleTopDown() { + unsigned CurCycle = 0; + + // Release any successors of the special Entry node. + ReleaseSuccessors(&EntrySU); + + // All leaves to Available queue. + for (unsigned i = 0, e = SUnits.size(); i != e; ++i) { + // It is available if it has no predecessors. + if (SUnits[i].Preds.empty()) { + AvailableQueue->push(&SUnits[i]); + SUnits[i].isAvailable = true; + } + } + + // While Available queue is not empty, grab the node with the highest + // priority. If it is not ready put it back. Schedule the node. + std::vector NotReady; + Sequence.reserve(SUnits.size()); + while (!AvailableQueue->empty() || !PendingQueue.empty()) { + // Check to see if any of the pending instructions are ready to issue. If + // so, add them to the available queue. + for (unsigned i = 0, e = PendingQueue.size(); i != e; ++i) { + if (PendingQueue[i]->getDepth() == CurCycle) { + AvailableQueue->push(PendingQueue[i]); + PendingQueue[i]->isAvailable = true; + PendingQueue[i] = PendingQueue.back(); + PendingQueue.pop_back(); + --i; --e; + } else { + assert(PendingQueue[i]->getDepth() > CurCycle && "Negative latency?"); + } + } + + // If there are no instructions available, don't try to issue anything, and + // don't advance the hazard recognizer. + if (AvailableQueue->empty()) { + ++CurCycle; + continue; + } + + SUnit *FoundSUnit = 0; + + bool HasNoopHazards = false; + while (!AvailableQueue->empty()) { + SUnit *CurSUnit = AvailableQueue->pop(); + + ScheduleHazardRecognizer::HazardType HT = + HazardRec->getHazardType(CurSUnit); + if (HT == ScheduleHazardRecognizer::NoHazard) { + FoundSUnit = CurSUnit; + break; + } + + // Remember if this is a noop hazard. + HasNoopHazards |= HT == ScheduleHazardRecognizer::NoopHazard; + + NotReady.push_back(CurSUnit); + } + + // Add the nodes that aren't ready back onto the available list. + if (!NotReady.empty()) { + AvailableQueue->push_all(NotReady); + NotReady.clear(); + } + + // If we found a node to schedule, do it now. + if (FoundSUnit) { + ScheduleNodeTopDown(FoundSUnit, CurCycle); + HazardRec->EmitInstruction(FoundSUnit); + + // If this is a pseudo-op node, we don't want to increment the current + // cycle. + if (FoundSUnit->Latency) // Don't increment CurCycle for pseudo-ops! + ++CurCycle; + } else if (!HasNoopHazards) { + // Otherwise, we have a pipeline stall, but no other problem, just advance + // the current cycle and try again. + DEBUG(errs() << "*** Advancing cycle, no work to do\n"); + HazardRec->AdvanceCycle(); + ++NumStalls; + ++CurCycle; + } else { + // Otherwise, we have no instructions to issue and we have instructions + // that will fault if we don't do this right. This is the case for + // processors without pipeline interlocks and other cases. + DEBUG(errs() << "*** Emitting noop\n"); + HazardRec->EmitNoop(); + Sequence.push_back(0); // NULL here means noop + ++NumNoops; + ++CurCycle; + } + } + +#ifndef NDEBUG + VerifySchedule(/*isBottomUp=*/false); +#endif +} + +//===----------------------------------------------------------------------===// +// Public Constructor Functions +//===----------------------------------------------------------------------===// + +/// createTDListDAGScheduler - This creates a top-down list scheduler with a +/// new hazard recognizer. This scheduler takes ownership of the hazard +/// recognizer and deletes it when done. +ScheduleDAGSDNodes * +llvm::createTDListDAGScheduler(SelectionDAGISel *IS, CodeGenOpt::Level) { + return new ScheduleDAGList(*IS->MF, + new LatencyPriorityQueue(), + IS->CreateTargetHazardRecognizer()); +} diff --git a/libclamav/c++/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp b/libclamav/c++/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp new file mode 100644 index 000000000..7e1015aff --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp @@ -0,0 +1,1534 @@ +//===----- ScheduleDAGRRList.cpp - Reg pressure reduction list scheduler --===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This implements bottom-up and top-down register pressure reduction list +// schedulers, using standard algorithms. The basic approach uses a priority +// queue of available nodes to schedule. One at a time, nodes are taken from +// the priority queue (thus in priority order), checked for legality to +// schedule, and emitted if legal. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "pre-RA-sched" +#include "ScheduleDAGSDNodes.h" +#include "llvm/CodeGen/SchedulerRegistry.h" +#include "llvm/CodeGen/SelectionDAGISel.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/ADT/PriorityQueue.h" +#include "llvm/ADT/SmallSet.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/Support/raw_ostream.h" +#include +using namespace llvm; + +STATISTIC(NumBacktracks, "Number of times scheduler backtracked"); +STATISTIC(NumUnfolds, "Number of nodes unfolded"); +STATISTIC(NumDups, "Number of duplicated nodes"); +STATISTIC(NumPRCopies, "Number of physical register copies"); + +static RegisterScheduler + burrListDAGScheduler("list-burr", + "Bottom-up register reduction list scheduling", + createBURRListDAGScheduler); +static RegisterScheduler + tdrListrDAGScheduler("list-tdrr", + "Top-down register reduction list scheduling", + createTDRRListDAGScheduler); + +namespace { +//===----------------------------------------------------------------------===// +/// ScheduleDAGRRList - The actual register reduction list scheduler +/// implementation. This supports both top-down and bottom-up scheduling. +/// +class ScheduleDAGRRList : public ScheduleDAGSDNodes { +private: + /// isBottomUp - This is true if the scheduling problem is bottom-up, false if + /// it is top-down. + bool isBottomUp; + + /// AvailableQueue - The priority queue to use for the available SUnits. + SchedulingPriorityQueue *AvailableQueue; + + /// LiveRegDefs - A set of physical registers and their definition + /// that are "live". These nodes must be scheduled before any other nodes that + /// modifies the registers can be scheduled. + unsigned NumLiveRegs; + std::vector LiveRegDefs; + std::vector LiveRegCycles; + + /// Topo - A topological ordering for SUnits which permits fast IsReachable + /// and similar queries. + ScheduleDAGTopologicalSort Topo; + +public: + ScheduleDAGRRList(MachineFunction &mf, + bool isbottomup, + SchedulingPriorityQueue *availqueue) + : ScheduleDAGSDNodes(mf), isBottomUp(isbottomup), + AvailableQueue(availqueue), Topo(SUnits) { + } + + ~ScheduleDAGRRList() { + delete AvailableQueue; + } + + void Schedule(); + + /// IsReachable - Checks if SU is reachable from TargetSU. + bool IsReachable(const SUnit *SU, const SUnit *TargetSU) { + return Topo.IsReachable(SU, TargetSU); + } + + /// WillCreateCycle - Returns true if adding an edge from SU to TargetSU will + /// create a cycle. + bool WillCreateCycle(SUnit *SU, SUnit *TargetSU) { + return Topo.WillCreateCycle(SU, TargetSU); + } + + /// AddPred - adds a predecessor edge to SUnit SU. + /// This returns true if this is a new predecessor. + /// Updates the topological ordering if required. + void AddPred(SUnit *SU, const SDep &D) { + Topo.AddPred(SU, D.getSUnit()); + SU->addPred(D); + } + + /// RemovePred - removes a predecessor edge from SUnit SU. + /// This returns true if an edge was removed. + /// Updates the topological ordering if required. + void RemovePred(SUnit *SU, const SDep &D) { + Topo.RemovePred(SU, D.getSUnit()); + SU->removePred(D); + } + +private: + void ReleasePred(SUnit *SU, const SDep *PredEdge); + void ReleasePredecessors(SUnit *SU, unsigned CurCycle); + void ReleaseSucc(SUnit *SU, const SDep *SuccEdge); + void ReleaseSuccessors(SUnit *SU); + void CapturePred(SDep *PredEdge); + void ScheduleNodeBottomUp(SUnit*, unsigned); + void ScheduleNodeTopDown(SUnit*, unsigned); + void UnscheduleNodeBottomUp(SUnit*); + void BacktrackBottomUp(SUnit*, unsigned, unsigned&); + SUnit *CopyAndMoveSuccessors(SUnit*); + void InsertCopiesAndMoveSuccs(SUnit*, unsigned, + const TargetRegisterClass*, + const TargetRegisterClass*, + SmallVector&); + bool DelayForLiveRegsBottomUp(SUnit*, SmallVector&); + void ListScheduleTopDown(); + void ListScheduleBottomUp(); + + + /// CreateNewSUnit - Creates a new SUnit and returns a pointer to it. + /// Updates the topological ordering if required. + SUnit *CreateNewSUnit(SDNode *N) { + unsigned NumSUnits = SUnits.size(); + SUnit *NewNode = NewSUnit(N); + // Update the topological ordering. + if (NewNode->NodeNum >= NumSUnits) + Topo.InitDAGTopologicalSorting(); + return NewNode; + } + + /// CreateClone - Creates a new SUnit from an existing one. + /// Updates the topological ordering if required. + SUnit *CreateClone(SUnit *N) { + unsigned NumSUnits = SUnits.size(); + SUnit *NewNode = Clone(N); + // Update the topological ordering. + if (NewNode->NodeNum >= NumSUnits) + Topo.InitDAGTopologicalSorting(); + return NewNode; + } + + /// ForceUnitLatencies - Return true, since register-pressure-reducing + /// scheduling doesn't need actual latency information. + bool ForceUnitLatencies() const { return true; } +}; +} // end anonymous namespace + + +/// Schedule - Schedule the DAG using list scheduling. +void ScheduleDAGRRList::Schedule() { + DEBUG(errs() << "********** List Scheduling **********\n"); + + NumLiveRegs = 0; + LiveRegDefs.resize(TRI->getNumRegs(), NULL); + LiveRegCycles.resize(TRI->getNumRegs(), 0); + + // Build the scheduling graph. + BuildSchedGraph(NULL); + + DEBUG(for (unsigned su = 0, e = SUnits.size(); su != e; ++su) + SUnits[su].dumpAll(this)); + Topo.InitDAGTopologicalSorting(); + + AvailableQueue->initNodes(SUnits); + + // Execute the actual scheduling loop Top-Down or Bottom-Up as appropriate. + if (isBottomUp) + ListScheduleBottomUp(); + else + ListScheduleTopDown(); + + AvailableQueue->releaseState(); +} + +//===----------------------------------------------------------------------===// +// Bottom-Up Scheduling +//===----------------------------------------------------------------------===// + +/// ReleasePred - Decrement the NumSuccsLeft count of a predecessor. Add it to +/// the AvailableQueue if the count reaches zero. Also update its cycle bound. +void ScheduleDAGRRList::ReleasePred(SUnit *SU, const SDep *PredEdge) { + SUnit *PredSU = PredEdge->getSUnit(); + +#ifndef NDEBUG + if (PredSU->NumSuccsLeft == 0) { + errs() << "*** Scheduling failed! ***\n"; + PredSU->dump(this); + errs() << " has been released too many times!\n"; + llvm_unreachable(0); + } +#endif + --PredSU->NumSuccsLeft; + + // If all the node's successors are scheduled, this node is ready + // to be scheduled. Ignore the special EntrySU node. + if (PredSU->NumSuccsLeft == 0 && PredSU != &EntrySU) { + PredSU->isAvailable = true; + AvailableQueue->push(PredSU); + } +} + +void ScheduleDAGRRList::ReleasePredecessors(SUnit *SU, unsigned CurCycle) { + // Bottom up: release predecessors + for (SUnit::pred_iterator I = SU->Preds.begin(), E = SU->Preds.end(); + I != E; ++I) { + ReleasePred(SU, &*I); + if (I->isAssignedRegDep()) { + // This is a physical register dependency and it's impossible or + // expensive to copy the register. Make sure nothing that can + // clobber the register is scheduled between the predecessor and + // this node. + if (!LiveRegDefs[I->getReg()]) { + ++NumLiveRegs; + LiveRegDefs[I->getReg()] = I->getSUnit(); + LiveRegCycles[I->getReg()] = CurCycle; + } + } + } +} + +/// ScheduleNodeBottomUp - Add the node to the schedule. Decrement the pending +/// count of its predecessors. If a predecessor pending count is zero, add it to +/// the Available queue. +void ScheduleDAGRRList::ScheduleNodeBottomUp(SUnit *SU, unsigned CurCycle) { + DEBUG(errs() << "*** Scheduling [" << CurCycle << "]: "); + DEBUG(SU->dump(this)); + + assert(CurCycle >= SU->getHeight() && "Node scheduled below its height!"); + SU->setHeightToAtLeast(CurCycle); + Sequence.push_back(SU); + + ReleasePredecessors(SU, CurCycle); + + // Release all the implicit physical register defs that are live. + for (SUnit::succ_iterator I = SU->Succs.begin(), E = SU->Succs.end(); + I != E; ++I) { + if (I->isAssignedRegDep()) { + if (LiveRegCycles[I->getReg()] == I->getSUnit()->getHeight()) { + assert(NumLiveRegs > 0 && "NumLiveRegs is already zero!"); + assert(LiveRegDefs[I->getReg()] == SU && + "Physical register dependency violated?"); + --NumLiveRegs; + LiveRegDefs[I->getReg()] = NULL; + LiveRegCycles[I->getReg()] = 0; + } + } + } + + SU->isScheduled = true; + AvailableQueue->ScheduledNode(SU); +} + +/// CapturePred - This does the opposite of ReleasePred. Since SU is being +/// unscheduled, incrcease the succ left count of its predecessors. Remove +/// them from AvailableQueue if necessary. +void ScheduleDAGRRList::CapturePred(SDep *PredEdge) { + SUnit *PredSU = PredEdge->getSUnit(); + if (PredSU->isAvailable) { + PredSU->isAvailable = false; + if (!PredSU->isPending) + AvailableQueue->remove(PredSU); + } + + assert(PredSU->NumSuccsLeft < UINT_MAX && "NumSuccsLeft will overflow!"); + ++PredSU->NumSuccsLeft; +} + +/// UnscheduleNodeBottomUp - Remove the node from the schedule, update its and +/// its predecessor states to reflect the change. +void ScheduleDAGRRList::UnscheduleNodeBottomUp(SUnit *SU) { + DEBUG(errs() << "*** Unscheduling [" << SU->getHeight() << "]: "); + DEBUG(SU->dump(this)); + + AvailableQueue->UnscheduledNode(SU); + + for (SUnit::pred_iterator I = SU->Preds.begin(), E = SU->Preds.end(); + I != E; ++I) { + CapturePred(&*I); + if (I->isAssignedRegDep() && SU->getHeight() == LiveRegCycles[I->getReg()]) { + assert(NumLiveRegs > 0 && "NumLiveRegs is already zero!"); + assert(LiveRegDefs[I->getReg()] == I->getSUnit() && + "Physical register dependency violated?"); + --NumLiveRegs; + LiveRegDefs[I->getReg()] = NULL; + LiveRegCycles[I->getReg()] = 0; + } + } + + for (SUnit::succ_iterator I = SU->Succs.begin(), E = SU->Succs.end(); + I != E; ++I) { + if (I->isAssignedRegDep()) { + if (!LiveRegDefs[I->getReg()]) { + LiveRegDefs[I->getReg()] = SU; + ++NumLiveRegs; + } + if (I->getSUnit()->getHeight() < LiveRegCycles[I->getReg()]) + LiveRegCycles[I->getReg()] = I->getSUnit()->getHeight(); + } + } + + SU->setHeightDirty(); + SU->isScheduled = false; + SU->isAvailable = true; + AvailableQueue->push(SU); +} + +/// BacktrackBottomUp - Backtrack scheduling to a previous cycle specified in +/// BTCycle in order to schedule a specific node. +void ScheduleDAGRRList::BacktrackBottomUp(SUnit *SU, unsigned BtCycle, + unsigned &CurCycle) { + SUnit *OldSU = NULL; + while (CurCycle > BtCycle) { + OldSU = Sequence.back(); + Sequence.pop_back(); + if (SU->isSucc(OldSU)) + // Don't try to remove SU from AvailableQueue. + SU->isAvailable = false; + UnscheduleNodeBottomUp(OldSU); + --CurCycle; + } + + assert(!SU->isSucc(OldSU) && "Something is wrong!"); + + ++NumBacktracks; +} + +/// CopyAndMoveSuccessors - Clone the specified node and move its scheduled +/// successors to the newly created node. +SUnit *ScheduleDAGRRList::CopyAndMoveSuccessors(SUnit *SU) { + if (SU->getNode()->getFlaggedNode()) + return NULL; + + SDNode *N = SU->getNode(); + if (!N) + return NULL; + + SUnit *NewSU; + bool TryUnfold = false; + for (unsigned i = 0, e = N->getNumValues(); i != e; ++i) { + EVT VT = N->getValueType(i); + if (VT == MVT::Flag) + return NULL; + else if (VT == MVT::Other) + TryUnfold = true; + } + for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) { + const SDValue &Op = N->getOperand(i); + EVT VT = Op.getNode()->getValueType(Op.getResNo()); + if (VT == MVT::Flag) + return NULL; + } + + if (TryUnfold) { + SmallVector NewNodes; + if (!TII->unfoldMemoryOperand(*DAG, N, NewNodes)) + return NULL; + + DEBUG(errs() << "Unfolding SU # " << SU->NodeNum << "\n"); + assert(NewNodes.size() == 2 && "Expected a load folding node!"); + + N = NewNodes[1]; + SDNode *LoadNode = NewNodes[0]; + unsigned NumVals = N->getNumValues(); + unsigned OldNumVals = SU->getNode()->getNumValues(); + for (unsigned i = 0; i != NumVals; ++i) + DAG->ReplaceAllUsesOfValueWith(SDValue(SU->getNode(), i), SDValue(N, i)); + DAG->ReplaceAllUsesOfValueWith(SDValue(SU->getNode(), OldNumVals-1), + SDValue(LoadNode, 1)); + + // LoadNode may already exist. This can happen when there is another + // load from the same location and producing the same type of value + // but it has different alignment or volatileness. + bool isNewLoad = true; + SUnit *LoadSU; + if (LoadNode->getNodeId() != -1) { + LoadSU = &SUnits[LoadNode->getNodeId()]; + isNewLoad = false; + } else { + LoadSU = CreateNewSUnit(LoadNode); + LoadNode->setNodeId(LoadSU->NodeNum); + ComputeLatency(LoadSU); + } + + SUnit *NewSU = CreateNewSUnit(N); + assert(N->getNodeId() == -1 && "Node already inserted!"); + N->setNodeId(NewSU->NodeNum); + + const TargetInstrDesc &TID = TII->get(N->getMachineOpcode()); + for (unsigned i = 0; i != TID.getNumOperands(); ++i) { + if (TID.getOperandConstraint(i, TOI::TIED_TO) != -1) { + NewSU->isTwoAddress = true; + break; + } + } + if (TID.isCommutable()) + NewSU->isCommutable = true; + ComputeLatency(NewSU); + + // Record all the edges to and from the old SU, by category. + SmallVector ChainPreds; + SmallVector ChainSuccs; + SmallVector LoadPreds; + SmallVector NodePreds; + SmallVector NodeSuccs; + for (SUnit::pred_iterator I = SU->Preds.begin(), E = SU->Preds.end(); + I != E; ++I) { + if (I->isCtrl()) + ChainPreds.push_back(*I); + else if (I->getSUnit()->getNode() && + I->getSUnit()->getNode()->isOperandOf(LoadNode)) + LoadPreds.push_back(*I); + else + NodePreds.push_back(*I); + } + for (SUnit::succ_iterator I = SU->Succs.begin(), E = SU->Succs.end(); + I != E; ++I) { + if (I->isCtrl()) + ChainSuccs.push_back(*I); + else + NodeSuccs.push_back(*I); + } + + // Now assign edges to the newly-created nodes. + for (unsigned i = 0, e = ChainPreds.size(); i != e; ++i) { + const SDep &Pred = ChainPreds[i]; + RemovePred(SU, Pred); + if (isNewLoad) + AddPred(LoadSU, Pred); + } + for (unsigned i = 0, e = LoadPreds.size(); i != e; ++i) { + const SDep &Pred = LoadPreds[i]; + RemovePred(SU, Pred); + if (isNewLoad) + AddPred(LoadSU, Pred); + } + for (unsigned i = 0, e = NodePreds.size(); i != e; ++i) { + const SDep &Pred = NodePreds[i]; + RemovePred(SU, Pred); + AddPred(NewSU, Pred); + } + for (unsigned i = 0, e = NodeSuccs.size(); i != e; ++i) { + SDep D = NodeSuccs[i]; + SUnit *SuccDep = D.getSUnit(); + D.setSUnit(SU); + RemovePred(SuccDep, D); + D.setSUnit(NewSU); + AddPred(SuccDep, D); + } + for (unsigned i = 0, e = ChainSuccs.size(); i != e; ++i) { + SDep D = ChainSuccs[i]; + SUnit *SuccDep = D.getSUnit(); + D.setSUnit(SU); + RemovePred(SuccDep, D); + if (isNewLoad) { + D.setSUnit(LoadSU); + AddPred(SuccDep, D); + } + } + + // Add a data dependency to reflect that NewSU reads the value defined + // by LoadSU. + AddPred(NewSU, SDep(LoadSU, SDep::Data, LoadSU->Latency)); + + if (isNewLoad) + AvailableQueue->addNode(LoadSU); + AvailableQueue->addNode(NewSU); + + ++NumUnfolds; + + if (NewSU->NumSuccsLeft == 0) { + NewSU->isAvailable = true; + return NewSU; + } + SU = NewSU; + } + + DEBUG(errs() << "Duplicating SU # " << SU->NodeNum << "\n"); + NewSU = CreateClone(SU); + + // New SUnit has the exact same predecessors. + for (SUnit::pred_iterator I = SU->Preds.begin(), E = SU->Preds.end(); + I != E; ++I) + if (!I->isArtificial()) + AddPred(NewSU, *I); + + // Only copy scheduled successors. Cut them from old node's successor + // list and move them over. + SmallVector, 4> DelDeps; + for (SUnit::succ_iterator I = SU->Succs.begin(), E = SU->Succs.end(); + I != E; ++I) { + if (I->isArtificial()) + continue; + SUnit *SuccSU = I->getSUnit(); + if (SuccSU->isScheduled) { + SDep D = *I; + D.setSUnit(NewSU); + AddPred(SuccSU, D); + D.setSUnit(SU); + DelDeps.push_back(std::make_pair(SuccSU, D)); + } + } + for (unsigned i = 0, e = DelDeps.size(); i != e; ++i) + RemovePred(DelDeps[i].first, DelDeps[i].second); + + AvailableQueue->updateNode(SU); + AvailableQueue->addNode(NewSU); + + ++NumDups; + return NewSU; +} + +/// InsertCopiesAndMoveSuccs - Insert register copies and move all +/// scheduled successors of the given SUnit to the last copy. +void ScheduleDAGRRList::InsertCopiesAndMoveSuccs(SUnit *SU, unsigned Reg, + const TargetRegisterClass *DestRC, + const TargetRegisterClass *SrcRC, + SmallVector &Copies) { + SUnit *CopyFromSU = CreateNewSUnit(NULL); + CopyFromSU->CopySrcRC = SrcRC; + CopyFromSU->CopyDstRC = DestRC; + + SUnit *CopyToSU = CreateNewSUnit(NULL); + CopyToSU->CopySrcRC = DestRC; + CopyToSU->CopyDstRC = SrcRC; + + // Only copy scheduled successors. Cut them from old node's successor + // list and move them over. + SmallVector, 4> DelDeps; + for (SUnit::succ_iterator I = SU->Succs.begin(), E = SU->Succs.end(); + I != E; ++I) { + if (I->isArtificial()) + continue; + SUnit *SuccSU = I->getSUnit(); + if (SuccSU->isScheduled) { + SDep D = *I; + D.setSUnit(CopyToSU); + AddPred(SuccSU, D); + DelDeps.push_back(std::make_pair(SuccSU, *I)); + } + } + for (unsigned i = 0, e = DelDeps.size(); i != e; ++i) + RemovePred(DelDeps[i].first, DelDeps[i].second); + + AddPred(CopyFromSU, SDep(SU, SDep::Data, SU->Latency, Reg)); + AddPred(CopyToSU, SDep(CopyFromSU, SDep::Data, CopyFromSU->Latency, 0)); + + AvailableQueue->updateNode(SU); + AvailableQueue->addNode(CopyFromSU); + AvailableQueue->addNode(CopyToSU); + Copies.push_back(CopyFromSU); + Copies.push_back(CopyToSU); + + ++NumPRCopies; +} + +/// getPhysicalRegisterVT - Returns the ValueType of the physical register +/// definition of the specified node. +/// FIXME: Move to SelectionDAG? +static EVT getPhysicalRegisterVT(SDNode *N, unsigned Reg, + const TargetInstrInfo *TII) { + const TargetInstrDesc &TID = TII->get(N->getMachineOpcode()); + assert(TID.ImplicitDefs && "Physical reg def must be in implicit def list!"); + unsigned NumRes = TID.getNumDefs(); + for (const unsigned *ImpDef = TID.getImplicitDefs(); *ImpDef; ++ImpDef) { + if (Reg == *ImpDef) + break; + ++NumRes; + } + return N->getValueType(NumRes); +} + +/// CheckForLiveRegDef - Return true and update live register vector if the +/// specified register def of the specified SUnit clobbers any "live" registers. +static bool CheckForLiveRegDef(SUnit *SU, unsigned Reg, + std::vector &LiveRegDefs, + SmallSet &RegAdded, + SmallVector &LRegs, + const TargetRegisterInfo *TRI) { + bool Added = false; + if (LiveRegDefs[Reg] && LiveRegDefs[Reg] != SU) { + if (RegAdded.insert(Reg)) { + LRegs.push_back(Reg); + Added = true; + } + } + for (const unsigned *Alias = TRI->getAliasSet(Reg); *Alias; ++Alias) + if (LiveRegDefs[*Alias] && LiveRegDefs[*Alias] != SU) { + if (RegAdded.insert(*Alias)) { + LRegs.push_back(*Alias); + Added = true; + } + } + return Added; +} + +/// DelayForLiveRegsBottomUp - Returns true if it is necessary to delay +/// scheduling of the given node to satisfy live physical register dependencies. +/// If the specific node is the last one that's available to schedule, do +/// whatever is necessary (i.e. backtracking or cloning) to make it possible. +bool ScheduleDAGRRList::DelayForLiveRegsBottomUp(SUnit *SU, + SmallVector &LRegs){ + if (NumLiveRegs == 0) + return false; + + SmallSet RegAdded; + // If this node would clobber any "live" register, then it's not ready. + for (SUnit::pred_iterator I = SU->Preds.begin(), E = SU->Preds.end(); + I != E; ++I) { + if (I->isAssignedRegDep()) + CheckForLiveRegDef(I->getSUnit(), I->getReg(), LiveRegDefs, + RegAdded, LRegs, TRI); + } + + for (SDNode *Node = SU->getNode(); Node; Node = Node->getFlaggedNode()) { + if (Node->getOpcode() == ISD::INLINEASM) { + // Inline asm can clobber physical defs. + unsigned NumOps = Node->getNumOperands(); + if (Node->getOperand(NumOps-1).getValueType() == MVT::Flag) + --NumOps; // Ignore the flag operand. + + for (unsigned i = 2; i != NumOps;) { + unsigned Flags = + cast(Node->getOperand(i))->getZExtValue(); + unsigned NumVals = (Flags & 0xffff) >> 3; + + ++i; // Skip the ID value. + if ((Flags & 7) == 2 || (Flags & 7) == 6) { + // Check for def of register or earlyclobber register. + for (; NumVals; --NumVals, ++i) { + unsigned Reg = cast(Node->getOperand(i))->getReg(); + if (TargetRegisterInfo::isPhysicalRegister(Reg)) + CheckForLiveRegDef(SU, Reg, LiveRegDefs, RegAdded, LRegs, TRI); + } + } else + i += NumVals; + } + continue; + } + + if (!Node->isMachineOpcode()) + continue; + const TargetInstrDesc &TID = TII->get(Node->getMachineOpcode()); + if (!TID.ImplicitDefs) + continue; + for (const unsigned *Reg = TID.ImplicitDefs; *Reg; ++Reg) + CheckForLiveRegDef(SU, *Reg, LiveRegDefs, RegAdded, LRegs, TRI); + } + return !LRegs.empty(); +} + + +/// ListScheduleBottomUp - The main loop of list scheduling for bottom-up +/// schedulers. +void ScheduleDAGRRList::ListScheduleBottomUp() { + unsigned CurCycle = 0; + + // Release any predecessors of the special Exit node. + ReleasePredecessors(&ExitSU, CurCycle); + + // Add root to Available queue. + if (!SUnits.empty()) { + SUnit *RootSU = &SUnits[DAG->getRoot().getNode()->getNodeId()]; + assert(RootSU->Succs.empty() && "Graph root shouldn't have successors!"); + RootSU->isAvailable = true; + AvailableQueue->push(RootSU); + } + + // While Available queue is not empty, grab the node with the highest + // priority. If it is not ready put it back. Schedule the node. + SmallVector NotReady; + DenseMap > LRegsMap; + Sequence.reserve(SUnits.size()); + while (!AvailableQueue->empty()) { + bool Delayed = false; + LRegsMap.clear(); + SUnit *CurSU = AvailableQueue->pop(); + while (CurSU) { + SmallVector LRegs; + if (!DelayForLiveRegsBottomUp(CurSU, LRegs)) + break; + Delayed = true; + LRegsMap.insert(std::make_pair(CurSU, LRegs)); + + CurSU->isPending = true; // This SU is not in AvailableQueue right now. + NotReady.push_back(CurSU); + CurSU = AvailableQueue->pop(); + } + + // All candidates are delayed due to live physical reg dependencies. + // Try backtracking, code duplication, or inserting cross class copies + // to resolve it. + if (Delayed && !CurSU) { + for (unsigned i = 0, e = NotReady.size(); i != e; ++i) { + SUnit *TrySU = NotReady[i]; + SmallVector &LRegs = LRegsMap[TrySU]; + + // Try unscheduling up to the point where it's safe to schedule + // this node. + unsigned LiveCycle = CurCycle; + for (unsigned j = 0, ee = LRegs.size(); j != ee; ++j) { + unsigned Reg = LRegs[j]; + unsigned LCycle = LiveRegCycles[Reg]; + LiveCycle = std::min(LiveCycle, LCycle); + } + SUnit *OldSU = Sequence[LiveCycle]; + if (!WillCreateCycle(TrySU, OldSU)) { + BacktrackBottomUp(TrySU, LiveCycle, CurCycle); + // Force the current node to be scheduled before the node that + // requires the physical reg dep. + if (OldSU->isAvailable) { + OldSU->isAvailable = false; + AvailableQueue->remove(OldSU); + } + AddPred(TrySU, SDep(OldSU, SDep::Order, /*Latency=*/1, + /*Reg=*/0, /*isNormalMemory=*/false, + /*isMustAlias=*/false, /*isArtificial=*/true)); + // If one or more successors has been unscheduled, then the current + // node is no longer avaialable. Schedule a successor that's now + // available instead. + if (!TrySU->isAvailable) + CurSU = AvailableQueue->pop(); + else { + CurSU = TrySU; + TrySU->isPending = false; + NotReady.erase(NotReady.begin()+i); + } + break; + } + } + + if (!CurSU) { + // Can't backtrack. If it's too expensive to copy the value, then try + // duplicate the nodes that produces these "too expensive to copy" + // values to break the dependency. In case even that doesn't work, + // insert cross class copies. + // If it's not too expensive, i.e. cost != -1, issue copies. + SUnit *TrySU = NotReady[0]; + SmallVector &LRegs = LRegsMap[TrySU]; + assert(LRegs.size() == 1 && "Can't handle this yet!"); + unsigned Reg = LRegs[0]; + SUnit *LRDef = LiveRegDefs[Reg]; + EVT VT = getPhysicalRegisterVT(LRDef->getNode(), Reg, TII); + const TargetRegisterClass *RC = + TRI->getPhysicalRegisterRegClass(Reg, VT); + const TargetRegisterClass *DestRC = TRI->getCrossCopyRegClass(RC); + + // If cross copy register class is null, then it must be possible copy + // the value directly. Do not try duplicate the def. + SUnit *NewDef = 0; + if (DestRC) + NewDef = CopyAndMoveSuccessors(LRDef); + else + DestRC = RC; + if (!NewDef) { + // Issue copies, these can be expensive cross register class copies. + SmallVector Copies; + InsertCopiesAndMoveSuccs(LRDef, Reg, DestRC, RC, Copies); + DEBUG(errs() << "Adding an edge from SU #" << TrySU->NodeNum + << " to SU #" << Copies.front()->NodeNum << "\n"); + AddPred(TrySU, SDep(Copies.front(), SDep::Order, /*Latency=*/1, + /*Reg=*/0, /*isNormalMemory=*/false, + /*isMustAlias=*/false, + /*isArtificial=*/true)); + NewDef = Copies.back(); + } + + DEBUG(errs() << "Adding an edge from SU #" << NewDef->NodeNum + << " to SU #" << TrySU->NodeNum << "\n"); + LiveRegDefs[Reg] = NewDef; + AddPred(NewDef, SDep(TrySU, SDep::Order, /*Latency=*/1, + /*Reg=*/0, /*isNormalMemory=*/false, + /*isMustAlias=*/false, + /*isArtificial=*/true)); + TrySU->isAvailable = false; + CurSU = NewDef; + } + + assert(CurSU && "Unable to resolve live physical register dependencies!"); + } + + // Add the nodes that aren't ready back onto the available list. + for (unsigned i = 0, e = NotReady.size(); i != e; ++i) { + NotReady[i]->isPending = false; + // May no longer be available due to backtracking. + if (NotReady[i]->isAvailable) + AvailableQueue->push(NotReady[i]); + } + NotReady.clear(); + + if (CurSU) + ScheduleNodeBottomUp(CurSU, CurCycle); + ++CurCycle; + } + + // Reverse the order if it is bottom up. + std::reverse(Sequence.begin(), Sequence.end()); + +#ifndef NDEBUG + VerifySchedule(isBottomUp); +#endif +} + +//===----------------------------------------------------------------------===// +// Top-Down Scheduling +//===----------------------------------------------------------------------===// + +/// ReleaseSucc - Decrement the NumPredsLeft count of a successor. Add it to +/// the AvailableQueue if the count reaches zero. Also update its cycle bound. +void ScheduleDAGRRList::ReleaseSucc(SUnit *SU, const SDep *SuccEdge) { + SUnit *SuccSU = SuccEdge->getSUnit(); + +#ifndef NDEBUG + if (SuccSU->NumPredsLeft == 0) { + errs() << "*** Scheduling failed! ***\n"; + SuccSU->dump(this); + errs() << " has been released too many times!\n"; + llvm_unreachable(0); + } +#endif + --SuccSU->NumPredsLeft; + + // If all the node's predecessors are scheduled, this node is ready + // to be scheduled. Ignore the special ExitSU node. + if (SuccSU->NumPredsLeft == 0 && SuccSU != &ExitSU) { + SuccSU->isAvailable = true; + AvailableQueue->push(SuccSU); + } +} + +void ScheduleDAGRRList::ReleaseSuccessors(SUnit *SU) { + // Top down: release successors + for (SUnit::succ_iterator I = SU->Succs.begin(), E = SU->Succs.end(); + I != E; ++I) { + assert(!I->isAssignedRegDep() && + "The list-tdrr scheduler doesn't yet support physreg dependencies!"); + + ReleaseSucc(SU, &*I); + } +} + +/// ScheduleNodeTopDown - Add the node to the schedule. Decrement the pending +/// count of its successors. If a successor pending count is zero, add it to +/// the Available queue. +void ScheduleDAGRRList::ScheduleNodeTopDown(SUnit *SU, unsigned CurCycle) { + DEBUG(errs() << "*** Scheduling [" << CurCycle << "]: "); + DEBUG(SU->dump(this)); + + assert(CurCycle >= SU->getDepth() && "Node scheduled above its depth!"); + SU->setDepthToAtLeast(CurCycle); + Sequence.push_back(SU); + + ReleaseSuccessors(SU); + SU->isScheduled = true; + AvailableQueue->ScheduledNode(SU); +} + +/// ListScheduleTopDown - The main loop of list scheduling for top-down +/// schedulers. +void ScheduleDAGRRList::ListScheduleTopDown() { + unsigned CurCycle = 0; + + // Release any successors of the special Entry node. + ReleaseSuccessors(&EntrySU); + + // All leaves to Available queue. + for (unsigned i = 0, e = SUnits.size(); i != e; ++i) { + // It is available if it has no predecessors. + if (SUnits[i].Preds.empty()) { + AvailableQueue->push(&SUnits[i]); + SUnits[i].isAvailable = true; + } + } + + // While Available queue is not empty, grab the node with the highest + // priority. If it is not ready put it back. Schedule the node. + Sequence.reserve(SUnits.size()); + while (!AvailableQueue->empty()) { + SUnit *CurSU = AvailableQueue->pop(); + + if (CurSU) + ScheduleNodeTopDown(CurSU, CurCycle); + ++CurCycle; + } + +#ifndef NDEBUG + VerifySchedule(isBottomUp); +#endif +} + + +//===----------------------------------------------------------------------===// +// RegReductionPriorityQueue Implementation +//===----------------------------------------------------------------------===// +// +// This is a SchedulingPriorityQueue that schedules using Sethi Ullman numbers +// to reduce register pressure. +// +namespace { + template + class RegReductionPriorityQueue; + + /// Sorting functions for the Available queue. + struct bu_ls_rr_sort : public std::binary_function { + RegReductionPriorityQueue *SPQ; + bu_ls_rr_sort(RegReductionPriorityQueue *spq) : SPQ(spq) {} + bu_ls_rr_sort(const bu_ls_rr_sort &RHS) : SPQ(RHS.SPQ) {} + + bool operator()(const SUnit* left, const SUnit* right) const; + }; + + struct td_ls_rr_sort : public std::binary_function { + RegReductionPriorityQueue *SPQ; + td_ls_rr_sort(RegReductionPriorityQueue *spq) : SPQ(spq) {} + td_ls_rr_sort(const td_ls_rr_sort &RHS) : SPQ(RHS.SPQ) {} + + bool operator()(const SUnit* left, const SUnit* right) const; + }; +} // end anonymous namespace + +/// CalcNodeSethiUllmanNumber - Compute Sethi Ullman number. +/// Smaller number is the higher priority. +static unsigned +CalcNodeSethiUllmanNumber(const SUnit *SU, std::vector &SUNumbers) { + unsigned &SethiUllmanNumber = SUNumbers[SU->NodeNum]; + if (SethiUllmanNumber != 0) + return SethiUllmanNumber; + + unsigned Extra = 0; + for (SUnit::const_pred_iterator I = SU->Preds.begin(), E = SU->Preds.end(); + I != E; ++I) { + if (I->isCtrl()) continue; // ignore chain preds + SUnit *PredSU = I->getSUnit(); + unsigned PredSethiUllman = CalcNodeSethiUllmanNumber(PredSU, SUNumbers); + if (PredSethiUllman > SethiUllmanNumber) { + SethiUllmanNumber = PredSethiUllman; + Extra = 0; + } else if (PredSethiUllman == SethiUllmanNumber) + ++Extra; + } + + SethiUllmanNumber += Extra; + + if (SethiUllmanNumber == 0) + SethiUllmanNumber = 1; + + return SethiUllmanNumber; +} + +namespace { + template + class RegReductionPriorityQueue : public SchedulingPriorityQueue { + PriorityQueue, SF> Queue; + unsigned currentQueueId; + + protected: + // SUnits - The SUnits for the current graph. + std::vector *SUnits; + + const TargetInstrInfo *TII; + const TargetRegisterInfo *TRI; + ScheduleDAGRRList *scheduleDAG; + + // SethiUllmanNumbers - The SethiUllman number for each node. + std::vector SethiUllmanNumbers; + + public: + RegReductionPriorityQueue(const TargetInstrInfo *tii, + const TargetRegisterInfo *tri) : + Queue(SF(this)), currentQueueId(0), + TII(tii), TRI(tri), scheduleDAG(NULL) {} + + void initNodes(std::vector &sunits) { + SUnits = &sunits; + // Add pseudo dependency edges for two-address nodes. + AddPseudoTwoAddrDeps(); + // Reroute edges to nodes with multiple uses. + PrescheduleNodesWithMultipleUses(); + // Calculate node priorities. + CalculateSethiUllmanNumbers(); + } + + void addNode(const SUnit *SU) { + unsigned SUSize = SethiUllmanNumbers.size(); + if (SUnits->size() > SUSize) + SethiUllmanNumbers.resize(SUSize*2, 0); + CalcNodeSethiUllmanNumber(SU, SethiUllmanNumbers); + } + + void updateNode(const SUnit *SU) { + SethiUllmanNumbers[SU->NodeNum] = 0; + CalcNodeSethiUllmanNumber(SU, SethiUllmanNumbers); + } + + void releaseState() { + SUnits = 0; + SethiUllmanNumbers.clear(); + } + + unsigned getNodePriority(const SUnit *SU) const { + assert(SU->NodeNum < SethiUllmanNumbers.size()); + unsigned Opc = SU->getNode() ? SU->getNode()->getOpcode() : 0; + if (Opc == ISD::TokenFactor || Opc == ISD::CopyToReg) + // CopyToReg should be close to its uses to facilitate coalescing and + // avoid spilling. + return 0; + if (Opc == TargetInstrInfo::EXTRACT_SUBREG || + Opc == TargetInstrInfo::SUBREG_TO_REG || + Opc == TargetInstrInfo::INSERT_SUBREG) + // EXTRACT_SUBREG, INSERT_SUBREG, and SUBREG_TO_REG nodes should be + // close to their uses to facilitate coalescing. + return 0; + if (SU->NumSuccs == 0 && SU->NumPreds != 0) + // If SU does not have a register use, i.e. it doesn't produce a value + // that would be consumed (e.g. store), then it terminates a chain of + // computation. Give it a large SethiUllman number so it will be + // scheduled right before its predecessors that it doesn't lengthen + // their live ranges. + return 0xffff; + if (SU->NumPreds == 0 && SU->NumSuccs != 0) + // If SU does not have a register def, schedule it close to its uses + // because it does not lengthen any live ranges. + return 0; + return SethiUllmanNumbers[SU->NodeNum]; + } + + unsigned size() const { return Queue.size(); } + + bool empty() const { return Queue.empty(); } + + void push(SUnit *U) { + assert(!U->NodeQueueId && "Node in the queue already"); + U->NodeQueueId = ++currentQueueId; + Queue.push(U); + } + + void push_all(const std::vector &Nodes) { + for (unsigned i = 0, e = Nodes.size(); i != e; ++i) + push(Nodes[i]); + } + + SUnit *pop() { + if (empty()) return NULL; + SUnit *V = Queue.top(); + Queue.pop(); + V->NodeQueueId = 0; + return V; + } + + void remove(SUnit *SU) { + assert(!Queue.empty() && "Queue is empty!"); + assert(SU->NodeQueueId != 0 && "Not in queue!"); + Queue.erase_one(SU); + SU->NodeQueueId = 0; + } + + void setScheduleDAG(ScheduleDAGRRList *scheduleDag) { + scheduleDAG = scheduleDag; + } + + protected: + bool canClobber(const SUnit *SU, const SUnit *Op); + void AddPseudoTwoAddrDeps(); + void PrescheduleNodesWithMultipleUses(); + void CalculateSethiUllmanNumbers(); + }; + + typedef RegReductionPriorityQueue + BURegReductionPriorityQueue; + + typedef RegReductionPriorityQueue + TDRegReductionPriorityQueue; +} + +/// closestSucc - Returns the scheduled cycle of the successor which is +/// closest to the current cycle. +static unsigned closestSucc(const SUnit *SU) { + unsigned MaxHeight = 0; + for (SUnit::const_succ_iterator I = SU->Succs.begin(), E = SU->Succs.end(); + I != E; ++I) { + if (I->isCtrl()) continue; // ignore chain succs + unsigned Height = I->getSUnit()->getHeight(); + // If there are bunch of CopyToRegs stacked up, they should be considered + // to be at the same position. + if (I->getSUnit()->getNode() && + I->getSUnit()->getNode()->getOpcode() == ISD::CopyToReg) + Height = closestSucc(I->getSUnit())+1; + if (Height > MaxHeight) + MaxHeight = Height; + } + return MaxHeight; +} + +/// calcMaxScratches - Returns an cost estimate of the worse case requirement +/// for scratch registers, i.e. number of data dependencies. +static unsigned calcMaxScratches(const SUnit *SU) { + unsigned Scratches = 0; + for (SUnit::const_pred_iterator I = SU->Preds.begin(), E = SU->Preds.end(); + I != E; ++I) { + if (I->isCtrl()) continue; // ignore chain preds + Scratches++; + } + return Scratches; +} + +// Bottom up +bool bu_ls_rr_sort::operator()(const SUnit *left, const SUnit *right) const { + unsigned LPriority = SPQ->getNodePriority(left); + unsigned RPriority = SPQ->getNodePriority(right); + if (LPriority != RPriority) + return LPriority > RPriority; + + // Try schedule def + use closer when Sethi-Ullman numbers are the same. + // e.g. + // t1 = op t2, c1 + // t3 = op t4, c2 + // + // and the following instructions are both ready. + // t2 = op c3 + // t4 = op c4 + // + // Then schedule t2 = op first. + // i.e. + // t4 = op c4 + // t2 = op c3 + // t1 = op t2, c1 + // t3 = op t4, c2 + // + // This creates more short live intervals. + unsigned LDist = closestSucc(left); + unsigned RDist = closestSucc(right); + if (LDist != RDist) + return LDist < RDist; + + // How many registers becomes live when the node is scheduled. + unsigned LScratch = calcMaxScratches(left); + unsigned RScratch = calcMaxScratches(right); + if (LScratch != RScratch) + return LScratch > RScratch; + + if (left->getHeight() != right->getHeight()) + return left->getHeight() > right->getHeight(); + + if (left->getDepth() != right->getDepth()) + return left->getDepth() < right->getDepth(); + + assert(left->NodeQueueId && right->NodeQueueId && + "NodeQueueId cannot be zero"); + return (left->NodeQueueId > right->NodeQueueId); +} + +template +bool +RegReductionPriorityQueue::canClobber(const SUnit *SU, const SUnit *Op) { + if (SU->isTwoAddress) { + unsigned Opc = SU->getNode()->getMachineOpcode(); + const TargetInstrDesc &TID = TII->get(Opc); + unsigned NumRes = TID.getNumDefs(); + unsigned NumOps = TID.getNumOperands() - NumRes; + for (unsigned i = 0; i != NumOps; ++i) { + if (TID.getOperandConstraint(i+NumRes, TOI::TIED_TO) != -1) { + SDNode *DU = SU->getNode()->getOperand(i).getNode(); + if (DU->getNodeId() != -1 && + Op->OrigNode == &(*SUnits)[DU->getNodeId()]) + return true; + } + } + } + return false; +} + + +/// hasCopyToRegUse - Return true if SU has a value successor that is a +/// CopyToReg node. +static bool hasCopyToRegUse(const SUnit *SU) { + for (SUnit::const_succ_iterator I = SU->Succs.begin(), E = SU->Succs.end(); + I != E; ++I) { + if (I->isCtrl()) continue; + const SUnit *SuccSU = I->getSUnit(); + if (SuccSU->getNode() && SuccSU->getNode()->getOpcode() == ISD::CopyToReg) + return true; + } + return false; +} + +/// canClobberPhysRegDefs - True if SU would clobber one of SuccSU's +/// physical register defs. +static bool canClobberPhysRegDefs(const SUnit *SuccSU, const SUnit *SU, + const TargetInstrInfo *TII, + const TargetRegisterInfo *TRI) { + SDNode *N = SuccSU->getNode(); + unsigned NumDefs = TII->get(N->getMachineOpcode()).getNumDefs(); + const unsigned *ImpDefs = TII->get(N->getMachineOpcode()).getImplicitDefs(); + assert(ImpDefs && "Caller should check hasPhysRegDefs"); + for (const SDNode *SUNode = SU->getNode(); SUNode; + SUNode = SUNode->getFlaggedNode()) { + if (!SUNode->isMachineOpcode()) + continue; + const unsigned *SUImpDefs = + TII->get(SUNode->getMachineOpcode()).getImplicitDefs(); + if (!SUImpDefs) + return false; + for (unsigned i = NumDefs, e = N->getNumValues(); i != e; ++i) { + EVT VT = N->getValueType(i); + if (VT == MVT::Flag || VT == MVT::Other) + continue; + if (!N->hasAnyUseOfValue(i)) + continue; + unsigned Reg = ImpDefs[i - NumDefs]; + for (;*SUImpDefs; ++SUImpDefs) { + unsigned SUReg = *SUImpDefs; + if (TRI->regsOverlap(Reg, SUReg)) + return true; + } + } + } + return false; +} + +/// PrescheduleNodesWithMultipleUses - Nodes with multiple uses +/// are not handled well by the general register pressure reduction +/// heuristics. When presented with code like this: +/// +/// N +/// / | +/// / | +/// U store +/// | +/// ... +/// +/// the heuristics tend to push the store up, but since the +/// operand of the store has another use (U), this would increase +/// the length of that other use (the U->N edge). +/// +/// This function transforms code like the above to route U's +/// dependence through the store when possible, like this: +/// +/// N +/// || +/// || +/// store +/// | +/// U +/// | +/// ... +/// +/// This results in the store being scheduled immediately +/// after N, which shortens the U->N live range, reducing +/// register pressure. +/// +template +void RegReductionPriorityQueue::PrescheduleNodesWithMultipleUses() { + // Visit all the nodes in topological order, working top-down. + for (unsigned i = 0, e = SUnits->size(); i != e; ++i) { + SUnit *SU = &(*SUnits)[i]; + // For now, only look at nodes with no data successors, such as stores. + // These are especially important, due to the heuristics in + // getNodePriority for nodes with no data successors. + if (SU->NumSuccs != 0) + continue; + // For now, only look at nodes with exactly one data predecessor. + if (SU->NumPreds != 1) + continue; + // Avoid prescheduling copies to virtual registers, which don't behave + // like other nodes from the perspective of scheduling heuristics. + if (SDNode *N = SU->getNode()) + if (N->getOpcode() == ISD::CopyToReg && + TargetRegisterInfo::isVirtualRegister + (cast(N->getOperand(1))->getReg())) + continue; + + // Locate the single data predecessor. + SUnit *PredSU = 0; + for (SUnit::const_pred_iterator II = SU->Preds.begin(), + EE = SU->Preds.end(); II != EE; ++II) + if (!II->isCtrl()) { + PredSU = II->getSUnit(); + break; + } + assert(PredSU); + + // Don't rewrite edges that carry physregs, because that requires additional + // support infrastructure. + if (PredSU->hasPhysRegDefs) + continue; + // Short-circuit the case where SU is PredSU's only data successor. + if (PredSU->NumSuccs == 1) + continue; + // Avoid prescheduling to copies from virtual registers, which don't behave + // like other nodes from the perspective of scheduling // heuristics. + if (SDNode *N = SU->getNode()) + if (N->getOpcode() == ISD::CopyFromReg && + TargetRegisterInfo::isVirtualRegister + (cast(N->getOperand(1))->getReg())) + continue; + + // Perform checks on the successors of PredSU. + for (SUnit::const_succ_iterator II = PredSU->Succs.begin(), + EE = PredSU->Succs.end(); II != EE; ++II) { + SUnit *PredSuccSU = II->getSUnit(); + if (PredSuccSU == SU) continue; + // If PredSU has another successor with no data successors, for + // now don't attempt to choose either over the other. + if (PredSuccSU->NumSuccs == 0) + goto outer_loop_continue; + // Don't break physical register dependencies. + if (SU->hasPhysRegClobbers && PredSuccSU->hasPhysRegDefs) + if (canClobberPhysRegDefs(PredSuccSU, SU, TII, TRI)) + goto outer_loop_continue; + // Don't introduce graph cycles. + if (scheduleDAG->IsReachable(SU, PredSuccSU)) + goto outer_loop_continue; + } + + // Ok, the transformation is safe and the heuristics suggest it is + // profitable. Update the graph. + DEBUG(errs() << "Prescheduling SU # " << SU->NodeNum + << " next to PredSU # " << PredSU->NodeNum + << " to guide scheduling in the presence of multiple uses\n"); + for (unsigned i = 0; i != PredSU->Succs.size(); ++i) { + SDep Edge = PredSU->Succs[i]; + assert(!Edge.isAssignedRegDep()); + SUnit *SuccSU = Edge.getSUnit(); + if (SuccSU != SU) { + Edge.setSUnit(PredSU); + scheduleDAG->RemovePred(SuccSU, Edge); + scheduleDAG->AddPred(SU, Edge); + Edge.setSUnit(SU); + scheduleDAG->AddPred(SuccSU, Edge); + --i; + } + } + outer_loop_continue:; + } +} + +/// AddPseudoTwoAddrDeps - If two nodes share an operand and one of them uses +/// it as a def&use operand. Add a pseudo control edge from it to the other +/// node (if it won't create a cycle) so the two-address one will be scheduled +/// first (lower in the schedule). If both nodes are two-address, favor the +/// one that has a CopyToReg use (more likely to be a loop induction update). +/// If both are two-address, but one is commutable while the other is not +/// commutable, favor the one that's not commutable. +template +void RegReductionPriorityQueue::AddPseudoTwoAddrDeps() { + for (unsigned i = 0, e = SUnits->size(); i != e; ++i) { + SUnit *SU = &(*SUnits)[i]; + if (!SU->isTwoAddress) + continue; + + SDNode *Node = SU->getNode(); + if (!Node || !Node->isMachineOpcode() || SU->getNode()->getFlaggedNode()) + continue; + + unsigned Opc = Node->getMachineOpcode(); + const TargetInstrDesc &TID = TII->get(Opc); + unsigned NumRes = TID.getNumDefs(); + unsigned NumOps = TID.getNumOperands() - NumRes; + for (unsigned j = 0; j != NumOps; ++j) { + if (TID.getOperandConstraint(j+NumRes, TOI::TIED_TO) == -1) + continue; + SDNode *DU = SU->getNode()->getOperand(j).getNode(); + if (DU->getNodeId() == -1) + continue; + const SUnit *DUSU = &(*SUnits)[DU->getNodeId()]; + if (!DUSU) continue; + for (SUnit::const_succ_iterator I = DUSU->Succs.begin(), + E = DUSU->Succs.end(); I != E; ++I) { + if (I->isCtrl()) continue; + SUnit *SuccSU = I->getSUnit(); + if (SuccSU == SU) + continue; + // Be conservative. Ignore if nodes aren't at roughly the same + // depth and height. + if (SuccSU->getHeight() < SU->getHeight() && + (SU->getHeight() - SuccSU->getHeight()) > 1) + continue; + // Skip past COPY_TO_REGCLASS nodes, so that the pseudo edge + // constrains whatever is using the copy, instead of the copy + // itself. In the case that the copy is coalesced, this + // preserves the intent of the pseudo two-address heurietics. + while (SuccSU->Succs.size() == 1 && + SuccSU->getNode()->isMachineOpcode() && + SuccSU->getNode()->getMachineOpcode() == + TargetInstrInfo::COPY_TO_REGCLASS) + SuccSU = SuccSU->Succs.front().getSUnit(); + // Don't constrain non-instruction nodes. + if (!SuccSU->getNode() || !SuccSU->getNode()->isMachineOpcode()) + continue; + // Don't constrain nodes with physical register defs if the + // predecessor can clobber them. + if (SuccSU->hasPhysRegDefs && SU->hasPhysRegClobbers) { + if (canClobberPhysRegDefs(SuccSU, SU, TII, TRI)) + continue; + } + // Don't constrain EXTRACT_SUBREG, INSERT_SUBREG, and SUBREG_TO_REG; + // these may be coalesced away. We want them close to their uses. + unsigned SuccOpc = SuccSU->getNode()->getMachineOpcode(); + if (SuccOpc == TargetInstrInfo::EXTRACT_SUBREG || + SuccOpc == TargetInstrInfo::INSERT_SUBREG || + SuccOpc == TargetInstrInfo::SUBREG_TO_REG) + continue; + if ((!canClobber(SuccSU, DUSU) || + (hasCopyToRegUse(SU) && !hasCopyToRegUse(SuccSU)) || + (!SU->isCommutable && SuccSU->isCommutable)) && + !scheduleDAG->IsReachable(SuccSU, SU)) { + DEBUG(errs() << "Adding a pseudo-two-addr edge from SU # " + << SU->NodeNum << " to SU #" << SuccSU->NodeNum << "\n"); + scheduleDAG->AddPred(SU, SDep(SuccSU, SDep::Order, /*Latency=*/0, + /*Reg=*/0, /*isNormalMemory=*/false, + /*isMustAlias=*/false, + /*isArtificial=*/true)); + } + } + } + } +} + +/// CalculateSethiUllmanNumbers - Calculate Sethi-Ullman numbers of all +/// scheduling units. +template +void RegReductionPriorityQueue::CalculateSethiUllmanNumbers() { + SethiUllmanNumbers.assign(SUnits->size(), 0); + + for (unsigned i = 0, e = SUnits->size(); i != e; ++i) + CalcNodeSethiUllmanNumber(&(*SUnits)[i], SethiUllmanNumbers); +} + +/// LimitedSumOfUnscheduledPredsOfSuccs - Compute the sum of the unscheduled +/// predecessors of the successors of the SUnit SU. Stop when the provided +/// limit is exceeded. +static unsigned LimitedSumOfUnscheduledPredsOfSuccs(const SUnit *SU, + unsigned Limit) { + unsigned Sum = 0; + for (SUnit::const_succ_iterator I = SU->Succs.begin(), E = SU->Succs.end(); + I != E; ++I) { + const SUnit *SuccSU = I->getSUnit(); + for (SUnit::const_pred_iterator II = SuccSU->Preds.begin(), + EE = SuccSU->Preds.end(); II != EE; ++II) { + SUnit *PredSU = II->getSUnit(); + if (!PredSU->isScheduled) + if (++Sum > Limit) + return Sum; + } + } + return Sum; +} + + +// Top down +bool td_ls_rr_sort::operator()(const SUnit *left, const SUnit *right) const { + unsigned LPriority = SPQ->getNodePriority(left); + unsigned RPriority = SPQ->getNodePriority(right); + bool LIsTarget = left->getNode() && left->getNode()->isMachineOpcode(); + bool RIsTarget = right->getNode() && right->getNode()->isMachineOpcode(); + bool LIsFloater = LIsTarget && left->NumPreds == 0; + bool RIsFloater = RIsTarget && right->NumPreds == 0; + unsigned LBonus = (LimitedSumOfUnscheduledPredsOfSuccs(left,1) == 1) ? 2 : 0; + unsigned RBonus = (LimitedSumOfUnscheduledPredsOfSuccs(right,1) == 1) ? 2 : 0; + + if (left->NumSuccs == 0 && right->NumSuccs != 0) + return false; + else if (left->NumSuccs != 0 && right->NumSuccs == 0) + return true; + + if (LIsFloater) + LBonus -= 2; + if (RIsFloater) + RBonus -= 2; + if (left->NumSuccs == 1) + LBonus += 2; + if (right->NumSuccs == 1) + RBonus += 2; + + if (LPriority+LBonus != RPriority+RBonus) + return LPriority+LBonus < RPriority+RBonus; + + if (left->getDepth() != right->getDepth()) + return left->getDepth() < right->getDepth(); + + if (left->NumSuccsLeft != right->NumSuccsLeft) + return left->NumSuccsLeft > right->NumSuccsLeft; + + assert(left->NodeQueueId && right->NodeQueueId && + "NodeQueueId cannot be zero"); + return (left->NodeQueueId > right->NodeQueueId); +} + +//===----------------------------------------------------------------------===// +// Public Constructor Functions +//===----------------------------------------------------------------------===// + +llvm::ScheduleDAGSDNodes * +llvm::createBURRListDAGScheduler(SelectionDAGISel *IS, CodeGenOpt::Level) { + const TargetMachine &TM = IS->TM; + const TargetInstrInfo *TII = TM.getInstrInfo(); + const TargetRegisterInfo *TRI = TM.getRegisterInfo(); + + BURegReductionPriorityQueue *PQ = new BURegReductionPriorityQueue(TII, TRI); + + ScheduleDAGRRList *SD = + new ScheduleDAGRRList(*IS->MF, true, PQ); + PQ->setScheduleDAG(SD); + return SD; +} + +llvm::ScheduleDAGSDNodes * +llvm::createTDRRListDAGScheduler(SelectionDAGISel *IS, CodeGenOpt::Level) { + const TargetMachine &TM = IS->TM; + const TargetInstrInfo *TII = TM.getInstrInfo(); + const TargetRegisterInfo *TRI = TM.getRegisterInfo(); + + TDRegReductionPriorityQueue *PQ = new TDRegReductionPriorityQueue(TII, TRI); + + ScheduleDAGRRList *SD = + new ScheduleDAGRRList(*IS->MF, false, PQ); + PQ->setScheduleDAG(SD); + return SD; +} diff --git a/libclamav/c++/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp b/libclamav/c++/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp new file mode 100644 index 000000000..d53de347a --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp @@ -0,0 +1,311 @@ +//===--- ScheduleDAGSDNodes.cpp - Implement the ScheduleDAGSDNodes class --===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This implements the ScheduleDAG class, which is a base class used by +// scheduling implementation classes. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "pre-RA-sched" +#include "ScheduleDAGSDNodes.h" +#include "InstrEmitter.h" +#include "llvm/CodeGen/SelectionDAG.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Target/TargetSubtarget.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +ScheduleDAGSDNodes::ScheduleDAGSDNodes(MachineFunction &mf) + : ScheduleDAG(mf) { +} + +/// Run - perform scheduling. +/// +void ScheduleDAGSDNodes::Run(SelectionDAG *dag, MachineBasicBlock *bb, + MachineBasicBlock::iterator insertPos) { + DAG = dag; + ScheduleDAG::Run(bb, insertPos); +} + +SUnit *ScheduleDAGSDNodes::Clone(SUnit *Old) { + SUnit *SU = NewSUnit(Old->getNode()); + SU->OrigNode = Old->OrigNode; + SU->Latency = Old->Latency; + SU->isTwoAddress = Old->isTwoAddress; + SU->isCommutable = Old->isCommutable; + SU->hasPhysRegDefs = Old->hasPhysRegDefs; + SU->hasPhysRegClobbers = Old->hasPhysRegClobbers; + Old->isCloned = true; + return SU; +} + +/// CheckForPhysRegDependency - Check if the dependency between def and use of +/// a specified operand is a physical register dependency. If so, returns the +/// register and the cost of copying the register. +static void CheckForPhysRegDependency(SDNode *Def, SDNode *User, unsigned Op, + const TargetRegisterInfo *TRI, + const TargetInstrInfo *TII, + unsigned &PhysReg, int &Cost) { + if (Op != 2 || User->getOpcode() != ISD::CopyToReg) + return; + + unsigned Reg = cast(User->getOperand(1))->getReg(); + if (TargetRegisterInfo::isVirtualRegister(Reg)) + return; + + unsigned ResNo = User->getOperand(2).getResNo(); + if (Def->isMachineOpcode()) { + const TargetInstrDesc &II = TII->get(Def->getMachineOpcode()); + if (ResNo >= II.getNumDefs() && + II.ImplicitDefs[ResNo - II.getNumDefs()] == Reg) { + PhysReg = Reg; + const TargetRegisterClass *RC = + TRI->getPhysicalRegisterRegClass(Reg, Def->getValueType(ResNo)); + Cost = RC->getCopyCost(); + } + } +} + +void ScheduleDAGSDNodes::BuildSchedUnits() { + // During scheduling, the NodeId field of SDNode is used to map SDNodes + // to their associated SUnits by holding SUnits table indices. A value + // of -1 means the SDNode does not yet have an associated SUnit. + unsigned NumNodes = 0; + for (SelectionDAG::allnodes_iterator NI = DAG->allnodes_begin(), + E = DAG->allnodes_end(); NI != E; ++NI) { + NI->setNodeId(-1); + ++NumNodes; + } + + // Reserve entries in the vector for each of the SUnits we are creating. This + // ensure that reallocation of the vector won't happen, so SUnit*'s won't get + // invalidated. + // FIXME: Multiply by 2 because we may clone nodes during scheduling. + // This is a temporary workaround. + SUnits.reserve(NumNodes * 2); + + // Check to see if the scheduler cares about latencies. + bool UnitLatencies = ForceUnitLatencies(); + + for (SelectionDAG::allnodes_iterator NI = DAG->allnodes_begin(), + E = DAG->allnodes_end(); NI != E; ++NI) { + if (isPassiveNode(NI)) // Leaf node, e.g. a TargetImmediate. + continue; + + // If this node has already been processed, stop now. + if (NI->getNodeId() != -1) continue; + + SUnit *NodeSUnit = NewSUnit(NI); + + // See if anything is flagged to this node, if so, add them to flagged + // nodes. Nodes can have at most one flag input and one flag output. Flags + // are required to be the last operand and result of a node. + + // Scan up to find flagged preds. + SDNode *N = NI; + while (N->getNumOperands() && + N->getOperand(N->getNumOperands()-1).getValueType() == MVT::Flag) { + N = N->getOperand(N->getNumOperands()-1).getNode(); + assert(N->getNodeId() == -1 && "Node already inserted!"); + N->setNodeId(NodeSUnit->NodeNum); + } + + // Scan down to find any flagged succs. + N = NI; + while (N->getValueType(N->getNumValues()-1) == MVT::Flag) { + SDValue FlagVal(N, N->getNumValues()-1); + + // There are either zero or one users of the Flag result. + bool HasFlagUse = false; + for (SDNode::use_iterator UI = N->use_begin(), E = N->use_end(); + UI != E; ++UI) + if (FlagVal.isOperandOf(*UI)) { + HasFlagUse = true; + assert(N->getNodeId() == -1 && "Node already inserted!"); + N->setNodeId(NodeSUnit->NodeNum); + N = *UI; + break; + } + if (!HasFlagUse) break; + } + + // If there are flag operands involved, N is now the bottom-most node + // of the sequence of nodes that are flagged together. + // Update the SUnit. + NodeSUnit->setNode(N); + assert(N->getNodeId() == -1 && "Node already inserted!"); + N->setNodeId(NodeSUnit->NodeNum); + + // Assign the Latency field of NodeSUnit using target-provided information. + if (UnitLatencies) + NodeSUnit->Latency = 1; + else + ComputeLatency(NodeSUnit); + } +} + +void ScheduleDAGSDNodes::AddSchedEdges() { + const TargetSubtarget &ST = TM.getSubtarget(); + + // Check to see if the scheduler cares about latencies. + bool UnitLatencies = ForceUnitLatencies(); + + // Pass 2: add the preds, succs, etc. + for (unsigned su = 0, e = SUnits.size(); su != e; ++su) { + SUnit *SU = &SUnits[su]; + SDNode *MainNode = SU->getNode(); + + if (MainNode->isMachineOpcode()) { + unsigned Opc = MainNode->getMachineOpcode(); + const TargetInstrDesc &TID = TII->get(Opc); + for (unsigned i = 0; i != TID.getNumOperands(); ++i) { + if (TID.getOperandConstraint(i, TOI::TIED_TO) != -1) { + SU->isTwoAddress = true; + break; + } + } + if (TID.isCommutable()) + SU->isCommutable = true; + } + + // Find all predecessors and successors of the group. + for (SDNode *N = SU->getNode(); N; N = N->getFlaggedNode()) { + if (N->isMachineOpcode() && + TII->get(N->getMachineOpcode()).getImplicitDefs()) { + SU->hasPhysRegClobbers = true; + unsigned NumUsed = InstrEmitter::CountResults(N); + while (NumUsed != 0 && !N->hasAnyUseOfValue(NumUsed - 1)) + --NumUsed; // Skip over unused values at the end. + if (NumUsed > TII->get(N->getMachineOpcode()).getNumDefs()) + SU->hasPhysRegDefs = true; + } + + for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) { + SDNode *OpN = N->getOperand(i).getNode(); + if (isPassiveNode(OpN)) continue; // Not scheduled. + SUnit *OpSU = &SUnits[OpN->getNodeId()]; + assert(OpSU && "Node has no SUnit!"); + if (OpSU == SU) continue; // In the same group. + + EVT OpVT = N->getOperand(i).getValueType(); + assert(OpVT != MVT::Flag && "Flagged nodes should be in same sunit!"); + bool isChain = OpVT == MVT::Other; + + unsigned PhysReg = 0; + int Cost = 1; + // Determine if this is a physical register dependency. + CheckForPhysRegDependency(OpN, N, i, TRI, TII, PhysReg, Cost); + assert((PhysReg == 0 || !isChain) && + "Chain dependence via physreg data?"); + // FIXME: See ScheduleDAGSDNodes::EmitCopyFromReg. For now, scheduler + // emits a copy from the physical register to a virtual register unless + // it requires a cross class copy (cost < 0). That means we are only + // treating "expensive to copy" register dependency as physical register + // dependency. This may change in the future though. + if (Cost >= 0) + PhysReg = 0; + + const SDep& dep = SDep(OpSU, isChain ? SDep::Order : SDep::Data, + OpSU->Latency, PhysReg); + if (!isChain && !UnitLatencies) { + ComputeOperandLatency(OpSU, SU, (SDep &)dep); + ST.adjustSchedDependency(OpSU, SU, (SDep &)dep); + } + + SU->addPred(dep); + } + } + } +} + +/// BuildSchedGraph - Build the SUnit graph from the selection dag that we +/// are input. This SUnit graph is similar to the SelectionDAG, but +/// excludes nodes that aren't interesting to scheduling, and represents +/// flagged together nodes with a single SUnit. +void ScheduleDAGSDNodes::BuildSchedGraph(AliasAnalysis *AA) { + // Populate the SUnits array. + BuildSchedUnits(); + // Compute all the scheduling dependencies between nodes. + AddSchedEdges(); +} + +void ScheduleDAGSDNodes::ComputeLatency(SUnit *SU) { + const InstrItineraryData &InstrItins = TM.getInstrItineraryData(); + + // Compute the latency for the node. We use the sum of the latencies for + // all nodes flagged together into this SUnit. + SU->Latency = 0; + for (SDNode *N = SU->getNode(); N; N = N->getFlaggedNode()) + if (N->isMachineOpcode()) { + SU->Latency += InstrItins. + getStageLatency(TII->get(N->getMachineOpcode()).getSchedClass()); + } +} + +void ScheduleDAGSDNodes::dumpNode(const SUnit *SU) const { + if (!SU->getNode()) { + errs() << "PHYS REG COPY\n"; + return; + } + + SU->getNode()->dump(DAG); + errs() << "\n"; + SmallVector FlaggedNodes; + for (SDNode *N = SU->getNode()->getFlaggedNode(); N; N = N->getFlaggedNode()) + FlaggedNodes.push_back(N); + while (!FlaggedNodes.empty()) { + errs() << " "; + FlaggedNodes.back()->dump(DAG); + errs() << "\n"; + FlaggedNodes.pop_back(); + } +} + +/// EmitSchedule - Emit the machine code in scheduled order. +MachineBasicBlock *ScheduleDAGSDNodes:: +EmitSchedule(DenseMap *EM) { + InstrEmitter Emitter(BB, InsertPos); + DenseMap VRBaseMap; + DenseMap CopyVRBaseMap; + for (unsigned i = 0, e = Sequence.size(); i != e; i++) { + SUnit *SU = Sequence[i]; + if (!SU) { + // Null SUnit* is a noop. + EmitNoop(); + continue; + } + + // For pre-regalloc scheduling, create instructions corresponding to the + // SDNode and any flagged SDNodes and append them to the block. + if (!SU->getNode()) { + // Emit a copy. + EmitPhysRegCopy(SU, CopyVRBaseMap); + continue; + } + + SmallVector FlaggedNodes; + for (SDNode *N = SU->getNode()->getFlaggedNode(); N; + N = N->getFlaggedNode()) + FlaggedNodes.push_back(N); + while (!FlaggedNodes.empty()) { + Emitter.EmitNode(FlaggedNodes.back(), SU->OrigNode != SU, SU->isCloned, + VRBaseMap, EM); + FlaggedNodes.pop_back(); + } + Emitter.EmitNode(SU->getNode(), SU->OrigNode != SU, SU->isCloned, + VRBaseMap, EM); + } + + BB = Emitter.getBlock(); + InsertPos = Emitter.getInsertPos(); + return BB; +} diff --git a/libclamav/c++/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.h b/libclamav/c++/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.h new file mode 100644 index 000000000..ebb31ac47 --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.h @@ -0,0 +1,117 @@ +//===---- ScheduleDAGSDNodes.h - SDNode Scheduling --------------*- 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 the ScheduleDAGSDNodes class, which implements +// scheduling for an SDNode-based dependency graph. +// +//===----------------------------------------------------------------------===// + +#ifndef SCHEDULEDAGSDNODES_H +#define SCHEDULEDAGSDNODES_H + +#include "llvm/CodeGen/ScheduleDAG.h" +#include "llvm/CodeGen/SelectionDAG.h" + +namespace llvm { + /// ScheduleDAGSDNodes - A ScheduleDAG for scheduling SDNode-based DAGs. + /// + /// Edges between SUnits are initially based on edges in the SelectionDAG, + /// and additional edges can be added by the schedulers as heuristics. + /// SDNodes such as Constants, Registers, and a few others that are not + /// interesting to schedulers are not allocated SUnits. + /// + /// SDNodes with MVT::Flag operands are grouped along with the flagged + /// nodes into a single SUnit so that they are scheduled together. + /// + /// SDNode-based scheduling graphs do not use SDep::Anti or SDep::Output + /// edges. Physical register dependence information is not carried in + /// the DAG and must be handled explicitly by schedulers. + /// + class ScheduleDAGSDNodes : public ScheduleDAG { + public: + SelectionDAG *DAG; // DAG of the current basic block + + explicit ScheduleDAGSDNodes(MachineFunction &mf); + + virtual ~ScheduleDAGSDNodes() {} + + /// Run - perform scheduling. + /// + void Run(SelectionDAG *dag, MachineBasicBlock *bb, + MachineBasicBlock::iterator insertPos); + + /// isPassiveNode - Return true if the node is a non-scheduled leaf. + /// + static bool isPassiveNode(SDNode *Node) { + if (isa(Node)) return true; + if (isa(Node)) return true; + if (isa(Node)) return true; + if (isa(Node)) return true; + if (isa(Node)) return true; + if (isa(Node)) return true; + if (isa(Node)) return true; + if (isa(Node)) return true; + if (isa(Node)) return true; + if (isa(Node)) return true; + if (Node->getOpcode() == ISD::EntryToken) return true; + return false; + } + + /// NewSUnit - Creates a new SUnit and return a ptr to it. + /// + SUnit *NewSUnit(SDNode *N) { +#ifndef NDEBUG + const SUnit *Addr = 0; + if (!SUnits.empty()) + Addr = &SUnits[0]; +#endif + SUnits.push_back(SUnit(N, (unsigned)SUnits.size())); + assert((Addr == 0 || Addr == &SUnits[0]) && + "SUnits std::vector reallocated on the fly!"); + SUnits.back().OrigNode = &SUnits.back(); + return &SUnits.back(); + } + + /// Clone - Creates a clone of the specified SUnit. It does not copy the + /// predecessors / successors info nor the temporary scheduling states. + /// + SUnit *Clone(SUnit *N); + + /// BuildSchedGraph - Build the SUnit graph from the selection dag that we + /// are input. This SUnit graph is similar to the SelectionDAG, but + /// excludes nodes that aren't interesting to scheduling, and represents + /// flagged together nodes with a single SUnit. + virtual void BuildSchedGraph(AliasAnalysis *AA); + + /// ComputeLatency - Compute node latency. + /// + virtual void ComputeLatency(SUnit *SU); + + virtual MachineBasicBlock * + EmitSchedule(DenseMap *EM); + + /// Schedule - Order nodes according to selected style, filling + /// in the Sequence member. + /// + virtual void Schedule() = 0; + + virtual void dumpNode(const SUnit *SU) const; + + virtual std::string getGraphNodeLabel(const SUnit *SU) const; + + virtual void getCustomGraphFeatures(GraphWriter &GW) const; + + private: + /// BuildSchedUnits, AddSchedEdges - Helper functions for BuildSchedGraph. + void BuildSchedUnits(); + void AddSchedEdges(); + }; +} + +#endif diff --git a/libclamav/c++/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/libclamav/c++/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp new file mode 100644 index 000000000..8f9995708 --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -0,0 +1,5964 @@ +//===-- SelectionDAG.cpp - Implement the SelectionDAG data structures -----===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This implements the SelectionDAG class. +// +//===----------------------------------------------------------------------===// +#include "llvm/CodeGen/SelectionDAG.h" +#include "llvm/Constants.h" +#include "llvm/Analysis/ValueTracking.h" +#include "llvm/Function.h" +#include "llvm/GlobalAlias.h" +#include "llvm/GlobalVariable.h" +#include "llvm/Intrinsics.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Assembly/Writer.h" +#include "llvm/CallingConv.h" +#include "llvm/CodeGen/MachineBasicBlock.h" +#include "llvm/CodeGen/MachineConstantPool.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/CodeGen/PseudoSourceValue.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetLowering.h" +#include "llvm/Target/TargetOptions.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetIntrinsicInfo.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/ManagedStatic.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/System/Mutex.h" +#include "llvm/ADT/SetVector.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallSet.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringExtras.h" +#include +#include +using namespace llvm; + +/// makeVTList - Return an instance of the SDVTList struct initialized with the +/// specified members. +static SDVTList makeVTList(const EVT *VTs, unsigned NumVTs) { + SDVTList Res = {VTs, NumVTs}; + return Res; +} + +static const fltSemantics *EVTToAPFloatSemantics(EVT VT) { + switch (VT.getSimpleVT().SimpleTy) { + default: llvm_unreachable("Unknown FP format"); + case MVT::f32: return &APFloat::IEEEsingle; + case MVT::f64: return &APFloat::IEEEdouble; + case MVT::f80: return &APFloat::x87DoubleExtended; + case MVT::f128: return &APFloat::IEEEquad; + case MVT::ppcf128: return &APFloat::PPCDoubleDouble; + } +} + +SelectionDAG::DAGUpdateListener::~DAGUpdateListener() {} + +//===----------------------------------------------------------------------===// +// ConstantFPSDNode Class +//===----------------------------------------------------------------------===// + +/// isExactlyValue - We don't rely on operator== working on double values, as +/// it returns true for things that are clearly not equal, like -0.0 and 0.0. +/// As such, this method can be used to do an exact bit-for-bit comparison of +/// two floating point values. +bool ConstantFPSDNode::isExactlyValue(const APFloat& V) const { + return getValueAPF().bitwiseIsEqual(V); +} + +bool ConstantFPSDNode::isValueValidForType(EVT VT, + const APFloat& Val) { + assert(VT.isFloatingPoint() && "Can only convert between FP types"); + + // PPC long double cannot be converted to any other type. + if (VT == MVT::ppcf128 || + &Val.getSemantics() == &APFloat::PPCDoubleDouble) + return false; + + // convert modifies in place, so make a copy. + APFloat Val2 = APFloat(Val); + bool losesInfo; + (void) Val2.convert(*EVTToAPFloatSemantics(VT), APFloat::rmNearestTiesToEven, + &losesInfo); + return !losesInfo; +} + +//===----------------------------------------------------------------------===// +// ISD Namespace +//===----------------------------------------------------------------------===// + +/// isBuildVectorAllOnes - Return true if the specified node is a +/// BUILD_VECTOR where all of the elements are ~0 or undef. +bool ISD::isBuildVectorAllOnes(const SDNode *N) { + // Look through a bit convert. + if (N->getOpcode() == ISD::BIT_CONVERT) + N = N->getOperand(0).getNode(); + + if (N->getOpcode() != ISD::BUILD_VECTOR) return false; + + unsigned i = 0, e = N->getNumOperands(); + + // Skip over all of the undef values. + while (i != e && N->getOperand(i).getOpcode() == ISD::UNDEF) + ++i; + + // Do not accept an all-undef vector. + if (i == e) return false; + + // Do not accept build_vectors that aren't all constants or which have non-~0 + // elements. + SDValue NotZero = N->getOperand(i); + if (isa(NotZero)) { + if (!cast(NotZero)->isAllOnesValue()) + return false; + } else if (isa(NotZero)) { + if (!cast(NotZero)->getValueAPF(). + bitcastToAPInt().isAllOnesValue()) + return false; + } else + return false; + + // Okay, we have at least one ~0 value, check to see if the rest match or are + // undefs. + for (++i; i != e; ++i) + if (N->getOperand(i) != NotZero && + N->getOperand(i).getOpcode() != ISD::UNDEF) + return false; + return true; +} + + +/// isBuildVectorAllZeros - Return true if the specified node is a +/// BUILD_VECTOR where all of the elements are 0 or undef. +bool ISD::isBuildVectorAllZeros(const SDNode *N) { + // Look through a bit convert. + if (N->getOpcode() == ISD::BIT_CONVERT) + N = N->getOperand(0).getNode(); + + if (N->getOpcode() != ISD::BUILD_VECTOR) return false; + + unsigned i = 0, e = N->getNumOperands(); + + // Skip over all of the undef values. + while (i != e && N->getOperand(i).getOpcode() == ISD::UNDEF) + ++i; + + // Do not accept an all-undef vector. + if (i == e) return false; + + // Do not accept build_vectors that aren't all constants or which have non-0 + // elements. + SDValue Zero = N->getOperand(i); + if (isa(Zero)) { + if (!cast(Zero)->isNullValue()) + return false; + } else if (isa(Zero)) { + if (!cast(Zero)->getValueAPF().isPosZero()) + return false; + } else + return false; + + // Okay, we have at least one 0 value, check to see if the rest match or are + // undefs. + for (++i; i != e; ++i) + if (N->getOperand(i) != Zero && + N->getOperand(i).getOpcode() != ISD::UNDEF) + return false; + return true; +} + +/// isScalarToVector - Return true if the specified node is a +/// ISD::SCALAR_TO_VECTOR node or a BUILD_VECTOR node where only the low +/// element is not an undef. +bool ISD::isScalarToVector(const SDNode *N) { + if (N->getOpcode() == ISD::SCALAR_TO_VECTOR) + return true; + + if (N->getOpcode() != ISD::BUILD_VECTOR) + return false; + if (N->getOperand(0).getOpcode() == ISD::UNDEF) + return false; + unsigned NumElems = N->getNumOperands(); + for (unsigned i = 1; i < NumElems; ++i) { + SDValue V = N->getOperand(i); + if (V.getOpcode() != ISD::UNDEF) + return false; + } + return true; +} + +/// getSetCCSwappedOperands - Return the operation corresponding to (Y op X) +/// when given the operation for (X op Y). +ISD::CondCode ISD::getSetCCSwappedOperands(ISD::CondCode Operation) { + // To perform this operation, we just need to swap the L and G bits of the + // operation. + unsigned OldL = (Operation >> 2) & 1; + unsigned OldG = (Operation >> 1) & 1; + return ISD::CondCode((Operation & ~6) | // Keep the N, U, E bits + (OldL << 1) | // New G bit + (OldG << 2)); // New L bit. +} + +/// getSetCCInverse - Return the operation corresponding to !(X op Y), where +/// 'op' is a valid SetCC operation. +ISD::CondCode ISD::getSetCCInverse(ISD::CondCode Op, bool isInteger) { + unsigned Operation = Op; + if (isInteger) + Operation ^= 7; // Flip L, G, E bits, but not U. + else + Operation ^= 15; // Flip all of the condition bits. + + if (Operation > ISD::SETTRUE2) + Operation &= ~8; // Don't let N and U bits get set. + + return ISD::CondCode(Operation); +} + + +/// isSignedOp - For an integer comparison, return 1 if the comparison is a +/// signed operation and 2 if the result is an unsigned comparison. Return zero +/// if the operation does not depend on the sign of the input (setne and seteq). +static int isSignedOp(ISD::CondCode Opcode) { + switch (Opcode) { + default: llvm_unreachable("Illegal integer setcc operation!"); + case ISD::SETEQ: + case ISD::SETNE: return 0; + case ISD::SETLT: + case ISD::SETLE: + case ISD::SETGT: + case ISD::SETGE: return 1; + case ISD::SETULT: + case ISD::SETULE: + case ISD::SETUGT: + case ISD::SETUGE: return 2; + } +} + +/// getSetCCOrOperation - Return the result of a logical OR between different +/// comparisons of identical values: ((X op1 Y) | (X op2 Y)). This function +/// returns SETCC_INVALID if it is not possible to represent the resultant +/// comparison. +ISD::CondCode ISD::getSetCCOrOperation(ISD::CondCode Op1, ISD::CondCode Op2, + bool isInteger) { + if (isInteger && (isSignedOp(Op1) | isSignedOp(Op2)) == 3) + // Cannot fold a signed integer setcc with an unsigned integer setcc. + return ISD::SETCC_INVALID; + + unsigned Op = Op1 | Op2; // Combine all of the condition bits. + + // If the N and U bits get set then the resultant comparison DOES suddenly + // care about orderedness, and is true when ordered. + if (Op > ISD::SETTRUE2) + Op &= ~16; // Clear the U bit if the N bit is set. + + // Canonicalize illegal integer setcc's. + if (isInteger && Op == ISD::SETUNE) // e.g. SETUGT | SETULT + Op = ISD::SETNE; + + return ISD::CondCode(Op); +} + +/// getSetCCAndOperation - Return the result of a logical AND between different +/// comparisons of identical values: ((X op1 Y) & (X op2 Y)). This +/// function returns zero if it is not possible to represent the resultant +/// comparison. +ISD::CondCode ISD::getSetCCAndOperation(ISD::CondCode Op1, ISD::CondCode Op2, + bool isInteger) { + if (isInteger && (isSignedOp(Op1) | isSignedOp(Op2)) == 3) + // Cannot fold a signed setcc with an unsigned setcc. + return ISD::SETCC_INVALID; + + // Combine all of the condition bits. + ISD::CondCode Result = ISD::CondCode(Op1 & Op2); + + // Canonicalize illegal integer setcc's. + if (isInteger) { + switch (Result) { + default: break; + case ISD::SETUO : Result = ISD::SETFALSE; break; // SETUGT & SETULT + case ISD::SETOEQ: // SETEQ & SETU[LG]E + case ISD::SETUEQ: Result = ISD::SETEQ ; break; // SETUGE & SETULE + case ISD::SETOLT: Result = ISD::SETULT ; break; // SETULT & SETNE + case ISD::SETOGT: Result = ISD::SETUGT ; break; // SETUGT & SETNE + } + } + + return Result; +} + +const TargetMachine &SelectionDAG::getTarget() const { + return MF->getTarget(); +} + +//===----------------------------------------------------------------------===// +// SDNode Profile Support +//===----------------------------------------------------------------------===// + +/// AddNodeIDOpcode - Add the node opcode to the NodeID data. +/// +static void AddNodeIDOpcode(FoldingSetNodeID &ID, unsigned OpC) { + ID.AddInteger(OpC); +} + +/// AddNodeIDValueTypes - Value type lists are intern'd so we can represent them +/// solely with their pointer. +static void AddNodeIDValueTypes(FoldingSetNodeID &ID, SDVTList VTList) { + ID.AddPointer(VTList.VTs); +} + +/// AddNodeIDOperands - Various routines for adding operands to the NodeID data. +/// +static void AddNodeIDOperands(FoldingSetNodeID &ID, + const SDValue *Ops, unsigned NumOps) { + for (; NumOps; --NumOps, ++Ops) { + ID.AddPointer(Ops->getNode()); + ID.AddInteger(Ops->getResNo()); + } +} + +/// AddNodeIDOperands - Various routines for adding operands to the NodeID data. +/// +static void AddNodeIDOperands(FoldingSetNodeID &ID, + const SDUse *Ops, unsigned NumOps) { + for (; NumOps; --NumOps, ++Ops) { + ID.AddPointer(Ops->getNode()); + ID.AddInteger(Ops->getResNo()); + } +} + +static void AddNodeIDNode(FoldingSetNodeID &ID, + unsigned short OpC, SDVTList VTList, + const SDValue *OpList, unsigned N) { + AddNodeIDOpcode(ID, OpC); + AddNodeIDValueTypes(ID, VTList); + AddNodeIDOperands(ID, OpList, N); +} + +/// AddNodeIDCustom - If this is an SDNode with special info, add this info to +/// the NodeID data. +static void AddNodeIDCustom(FoldingSetNodeID &ID, const SDNode *N) { + switch (N->getOpcode()) { + case ISD::TargetExternalSymbol: + case ISD::ExternalSymbol: + llvm_unreachable("Should only be used on nodes with operands"); + default: break; // Normal nodes don't need extra info. + case ISD::TargetConstant: + case ISD::Constant: + ID.AddPointer(cast(N)->getConstantIntValue()); + break; + case ISD::TargetConstantFP: + case ISD::ConstantFP: { + ID.AddPointer(cast(N)->getConstantFPValue()); + break; + } + case ISD::TargetGlobalAddress: + case ISD::GlobalAddress: + case ISD::TargetGlobalTLSAddress: + case ISD::GlobalTLSAddress: { + const GlobalAddressSDNode *GA = cast(N); + ID.AddPointer(GA->getGlobal()); + ID.AddInteger(GA->getOffset()); + ID.AddInteger(GA->getTargetFlags()); + break; + } + case ISD::BasicBlock: + ID.AddPointer(cast(N)->getBasicBlock()); + break; + case ISD::Register: + ID.AddInteger(cast(N)->getReg()); + break; + + case ISD::SRCVALUE: + ID.AddPointer(cast(N)->getValue()); + break; + case ISD::FrameIndex: + case ISD::TargetFrameIndex: + ID.AddInteger(cast(N)->getIndex()); + break; + case ISD::JumpTable: + case ISD::TargetJumpTable: + ID.AddInteger(cast(N)->getIndex()); + ID.AddInteger(cast(N)->getTargetFlags()); + break; + case ISD::ConstantPool: + case ISD::TargetConstantPool: { + const ConstantPoolSDNode *CP = cast(N); + ID.AddInteger(CP->getAlignment()); + ID.AddInteger(CP->getOffset()); + if (CP->isMachineConstantPoolEntry()) + CP->getMachineCPVal()->AddSelectionDAGCSEId(ID); + else + ID.AddPointer(CP->getConstVal()); + ID.AddInteger(CP->getTargetFlags()); + break; + } + case ISD::LOAD: { + const LoadSDNode *LD = cast(N); + ID.AddInteger(LD->getMemoryVT().getRawBits()); + ID.AddInteger(LD->getRawSubclassData()); + break; + } + case ISD::STORE: { + const StoreSDNode *ST = cast(N); + ID.AddInteger(ST->getMemoryVT().getRawBits()); + ID.AddInteger(ST->getRawSubclassData()); + break; + } + case ISD::ATOMIC_CMP_SWAP: + case ISD::ATOMIC_SWAP: + case ISD::ATOMIC_LOAD_ADD: + case ISD::ATOMIC_LOAD_SUB: + case ISD::ATOMIC_LOAD_AND: + case ISD::ATOMIC_LOAD_OR: + case ISD::ATOMIC_LOAD_XOR: + case ISD::ATOMIC_LOAD_NAND: + case ISD::ATOMIC_LOAD_MIN: + case ISD::ATOMIC_LOAD_MAX: + case ISD::ATOMIC_LOAD_UMIN: + case ISD::ATOMIC_LOAD_UMAX: { + const AtomicSDNode *AT = cast(N); + ID.AddInteger(AT->getMemoryVT().getRawBits()); + ID.AddInteger(AT->getRawSubclassData()); + break; + } + case ISD::VECTOR_SHUFFLE: { + const ShuffleVectorSDNode *SVN = cast(N); + for (unsigned i = 0, e = N->getValueType(0).getVectorNumElements(); + i != e; ++i) + ID.AddInteger(SVN->getMaskElt(i)); + break; + } + case ISD::TargetBlockAddress: + case ISD::BlockAddress: { + ID.AddPointer(cast(N)->getBlockAddress()); + ID.AddInteger(cast(N)->getTargetFlags()); + break; + } + } // end switch (N->getOpcode()) +} + +/// AddNodeIDNode - Generic routine for adding a nodes info to the NodeID +/// data. +static void AddNodeIDNode(FoldingSetNodeID &ID, const SDNode *N) { + AddNodeIDOpcode(ID, N->getOpcode()); + // Add the return value info. + AddNodeIDValueTypes(ID, N->getVTList()); + // Add the operand info. + AddNodeIDOperands(ID, N->op_begin(), N->getNumOperands()); + + // Handle SDNode leafs with special info. + AddNodeIDCustom(ID, N); +} + +/// encodeMemSDNodeFlags - Generic routine for computing a value for use in +/// the CSE map that carries volatility, indexing mode, and +/// extension/truncation information. +/// +static inline unsigned +encodeMemSDNodeFlags(int ConvType, ISD::MemIndexedMode AM, bool isVolatile) { + assert((ConvType & 3) == ConvType && + "ConvType may not require more than 2 bits!"); + assert((AM & 7) == AM && + "AM may not require more than 3 bits!"); + return ConvType | + (AM << 2) | + (isVolatile << 5); +} + +//===----------------------------------------------------------------------===// +// SelectionDAG Class +//===----------------------------------------------------------------------===// + +/// doNotCSE - Return true if CSE should not be performed for this node. +static bool doNotCSE(SDNode *N) { + if (N->getValueType(0) == MVT::Flag) + return true; // Never CSE anything that produces a flag. + + switch (N->getOpcode()) { + default: break; + case ISD::HANDLENODE: + case ISD::EH_LABEL: + return true; // Never CSE these nodes. + } + + // Check that remaining values produced are not flags. + for (unsigned i = 1, e = N->getNumValues(); i != e; ++i) + if (N->getValueType(i) == MVT::Flag) + return true; // Never CSE anything that produces a flag. + + return false; +} + +/// RemoveDeadNodes - This method deletes all unreachable nodes in the +/// SelectionDAG. +void SelectionDAG::RemoveDeadNodes() { + // Create a dummy node (which is not added to allnodes), that adds a reference + // to the root node, preventing it from being deleted. + HandleSDNode Dummy(getRoot()); + + SmallVector DeadNodes; + + // Add all obviously-dead nodes to the DeadNodes worklist. + for (allnodes_iterator I = allnodes_begin(), E = allnodes_end(); I != E; ++I) + if (I->use_empty()) + DeadNodes.push_back(I); + + RemoveDeadNodes(DeadNodes); + + // If the root changed (e.g. it was a dead load, update the root). + setRoot(Dummy.getValue()); +} + +/// RemoveDeadNodes - This method deletes the unreachable nodes in the +/// given list, and any nodes that become unreachable as a result. +void SelectionDAG::RemoveDeadNodes(SmallVectorImpl &DeadNodes, + DAGUpdateListener *UpdateListener) { + + // Process the worklist, deleting the nodes and adding their uses to the + // worklist. + while (!DeadNodes.empty()) { + SDNode *N = DeadNodes.pop_back_val(); + + if (UpdateListener) + UpdateListener->NodeDeleted(N, 0); + + // Take the node out of the appropriate CSE map. + RemoveNodeFromCSEMaps(N); + + // Next, brutally remove the operand list. This is safe to do, as there are + // no cycles in the graph. + for (SDNode::op_iterator I = N->op_begin(), E = N->op_end(); I != E; ) { + SDUse &Use = *I++; + SDNode *Operand = Use.getNode(); + Use.set(SDValue()); + + // Now that we removed this operand, see if there are no uses of it left. + if (Operand->use_empty()) + DeadNodes.push_back(Operand); + } + + DeallocateNode(N); + } +} + +void SelectionDAG::RemoveDeadNode(SDNode *N, DAGUpdateListener *UpdateListener){ + SmallVector DeadNodes(1, N); + RemoveDeadNodes(DeadNodes, UpdateListener); +} + +void SelectionDAG::DeleteNode(SDNode *N) { + // First take this out of the appropriate CSE map. + RemoveNodeFromCSEMaps(N); + + // Finally, remove uses due to operands of this node, remove from the + // AllNodes list, and delete the node. + DeleteNodeNotInCSEMaps(N); +} + +void SelectionDAG::DeleteNodeNotInCSEMaps(SDNode *N) { + assert(N != AllNodes.begin() && "Cannot delete the entry node!"); + assert(N->use_empty() && "Cannot delete a node that is not dead!"); + + // Drop all of the operands and decrement used node's use counts. + N->DropOperands(); + + DeallocateNode(N); +} + +void SelectionDAG::DeallocateNode(SDNode *N) { + if (N->OperandsNeedDelete) + delete[] N->OperandList; + + // Set the opcode to DELETED_NODE to help catch bugs when node + // memory is reallocated. + N->NodeType = ISD::DELETED_NODE; + + NodeAllocator.Deallocate(AllNodes.remove(N)); +} + +/// RemoveNodeFromCSEMaps - Take the specified node out of the CSE map that +/// correspond to it. This is useful when we're about to delete or repurpose +/// the node. We don't want future request for structurally identical nodes +/// to return N anymore. +bool SelectionDAG::RemoveNodeFromCSEMaps(SDNode *N) { + bool Erased = false; + switch (N->getOpcode()) { + case ISD::EntryToken: + llvm_unreachable("EntryToken should not be in CSEMaps!"); + return false; + case ISD::HANDLENODE: return false; // noop. + case ISD::CONDCODE: + assert(CondCodeNodes[cast(N)->get()] && + "Cond code doesn't exist!"); + Erased = CondCodeNodes[cast(N)->get()] != 0; + CondCodeNodes[cast(N)->get()] = 0; + break; + case ISD::ExternalSymbol: + Erased = ExternalSymbols.erase(cast(N)->getSymbol()); + break; + case ISD::TargetExternalSymbol: { + ExternalSymbolSDNode *ESN = cast(N); + Erased = TargetExternalSymbols.erase( + std::pair(ESN->getSymbol(), + ESN->getTargetFlags())); + break; + } + case ISD::VALUETYPE: { + EVT VT = cast(N)->getVT(); + if (VT.isExtended()) { + Erased = ExtendedValueTypeNodes.erase(VT); + } else { + Erased = ValueTypeNodes[VT.getSimpleVT().SimpleTy] != 0; + ValueTypeNodes[VT.getSimpleVT().SimpleTy] = 0; + } + break; + } + default: + // Remove it from the CSE Map. + Erased = CSEMap.RemoveNode(N); + break; + } +#ifndef NDEBUG + // Verify that the node was actually in one of the CSE maps, unless it has a + // flag result (which cannot be CSE'd) or is one of the special cases that are + // not subject to CSE. + if (!Erased && N->getValueType(N->getNumValues()-1) != MVT::Flag && + !N->isMachineOpcode() && !doNotCSE(N)) { + N->dump(this); + errs() << "\n"; + llvm_unreachable("Node is not in map!"); + } +#endif + return Erased; +} + +/// AddModifiedNodeToCSEMaps - The specified node has been removed from the CSE +/// maps and modified in place. Add it back to the CSE maps, unless an identical +/// node already exists, in which case transfer all its users to the existing +/// node. This transfer can potentially trigger recursive merging. +/// +void +SelectionDAG::AddModifiedNodeToCSEMaps(SDNode *N, + DAGUpdateListener *UpdateListener) { + // For node types that aren't CSE'd, just act as if no identical node + // already exists. + if (!doNotCSE(N)) { + SDNode *Existing = CSEMap.GetOrInsertNode(N); + if (Existing != N) { + // If there was already an existing matching node, use ReplaceAllUsesWith + // to replace the dead one with the existing one. This can cause + // recursive merging of other unrelated nodes down the line. + ReplaceAllUsesWith(N, Existing, UpdateListener); + + // N is now dead. Inform the listener if it exists and delete it. + if (UpdateListener) + UpdateListener->NodeDeleted(N, Existing); + DeleteNodeNotInCSEMaps(N); + return; + } + } + + // If the node doesn't already exist, we updated it. Inform a listener if + // it exists. + if (UpdateListener) + UpdateListener->NodeUpdated(N); +} + +/// FindModifiedNodeSlot - Find a slot for the specified node if its operands +/// were replaced with those specified. If this node is never memoized, +/// return null, otherwise return a pointer to the slot it would take. If a +/// node already exists with these operands, the slot will be non-null. +SDNode *SelectionDAG::FindModifiedNodeSlot(SDNode *N, SDValue Op, + void *&InsertPos) { + if (doNotCSE(N)) + return 0; + + SDValue Ops[] = { Op }; + FoldingSetNodeID ID; + AddNodeIDNode(ID, N->getOpcode(), N->getVTList(), Ops, 1); + AddNodeIDCustom(ID, N); + return CSEMap.FindNodeOrInsertPos(ID, InsertPos); +} + +/// FindModifiedNodeSlot - Find a slot for the specified node if its operands +/// were replaced with those specified. If this node is never memoized, +/// return null, otherwise return a pointer to the slot it would take. If a +/// node already exists with these operands, the slot will be non-null. +SDNode *SelectionDAG::FindModifiedNodeSlot(SDNode *N, + SDValue Op1, SDValue Op2, + void *&InsertPos) { + if (doNotCSE(N)) + return 0; + + SDValue Ops[] = { Op1, Op2 }; + FoldingSetNodeID ID; + AddNodeIDNode(ID, N->getOpcode(), N->getVTList(), Ops, 2); + AddNodeIDCustom(ID, N); + return CSEMap.FindNodeOrInsertPos(ID, InsertPos); +} + + +/// FindModifiedNodeSlot - Find a slot for the specified node if its operands +/// were replaced with those specified. If this node is never memoized, +/// return null, otherwise return a pointer to the slot it would take. If a +/// node already exists with these operands, the slot will be non-null. +SDNode *SelectionDAG::FindModifiedNodeSlot(SDNode *N, + const SDValue *Ops,unsigned NumOps, + void *&InsertPos) { + if (doNotCSE(N)) + return 0; + + FoldingSetNodeID ID; + AddNodeIDNode(ID, N->getOpcode(), N->getVTList(), Ops, NumOps); + AddNodeIDCustom(ID, N); + return CSEMap.FindNodeOrInsertPos(ID, InsertPos); +} + +/// VerifyNode - Sanity check the given node. Aborts if it is invalid. +void SelectionDAG::VerifyNode(SDNode *N) { + switch (N->getOpcode()) { + default: + break; + case ISD::BUILD_PAIR: { + EVT VT = N->getValueType(0); + assert(N->getNumValues() == 1 && "Too many results!"); + assert(!VT.isVector() && (VT.isInteger() || VT.isFloatingPoint()) && + "Wrong return type!"); + assert(N->getNumOperands() == 2 && "Wrong number of operands!"); + assert(N->getOperand(0).getValueType() == N->getOperand(1).getValueType() && + "Mismatched operand types!"); + assert(N->getOperand(0).getValueType().isInteger() == VT.isInteger() && + "Wrong operand type!"); + assert(VT.getSizeInBits() == 2 * N->getOperand(0).getValueSizeInBits() && + "Wrong return type size"); + break; + } + case ISD::BUILD_VECTOR: { + assert(N->getNumValues() == 1 && "Too many results!"); + assert(N->getValueType(0).isVector() && "Wrong return type!"); + assert(N->getNumOperands() == N->getValueType(0).getVectorNumElements() && + "Wrong number of operands!"); + EVT EltVT = N->getValueType(0).getVectorElementType(); + for (SDNode::op_iterator I = N->op_begin(), E = N->op_end(); I != E; ++I) + assert((I->getValueType() == EltVT || + (EltVT.isInteger() && I->getValueType().isInteger() && + EltVT.bitsLE(I->getValueType()))) && + "Wrong operand type!"); + break; + } + } +} + +/// getEVTAlignment - Compute the default alignment value for the +/// given type. +/// +unsigned SelectionDAG::getEVTAlignment(EVT VT) const { + const Type *Ty = VT == MVT::iPTR ? + PointerType::get(Type::getInt8Ty(*getContext()), 0) : + VT.getTypeForEVT(*getContext()); + + return TLI.getTargetData()->getABITypeAlignment(Ty); +} + +// EntryNode could meaningfully have debug info if we can find it... +SelectionDAG::SelectionDAG(TargetLowering &tli, FunctionLoweringInfo &fli) + : TLI(tli), FLI(fli), DW(0), + EntryNode(ISD::EntryToken, DebugLoc::getUnknownLoc(), + getVTList(MVT::Other)), Root(getEntryNode()) { + AllNodes.push_back(&EntryNode); +} + +void SelectionDAG::init(MachineFunction &mf, MachineModuleInfo *mmi, + DwarfWriter *dw) { + MF = &mf; + MMI = mmi; + DW = dw; + Context = &mf.getFunction()->getContext(); +} + +SelectionDAG::~SelectionDAG() { + allnodes_clear(); +} + +void SelectionDAG::allnodes_clear() { + assert(&*AllNodes.begin() == &EntryNode); + AllNodes.remove(AllNodes.begin()); + while (!AllNodes.empty()) + DeallocateNode(AllNodes.begin()); +} + +void SelectionDAG::clear() { + allnodes_clear(); + OperandAllocator.Reset(); + CSEMap.clear(); + + ExtendedValueTypeNodes.clear(); + ExternalSymbols.clear(); + TargetExternalSymbols.clear(); + std::fill(CondCodeNodes.begin(), CondCodeNodes.end(), + static_cast(0)); + std::fill(ValueTypeNodes.begin(), ValueTypeNodes.end(), + static_cast(0)); + + EntryNode.UseList = 0; + AllNodes.push_back(&EntryNode); + Root = getEntryNode(); +} + +SDValue SelectionDAG::getSExtOrTrunc(SDValue Op, DebugLoc DL, EVT VT) { + return VT.bitsGT(Op.getValueType()) ? + getNode(ISD::SIGN_EXTEND, DL, VT, Op) : + getNode(ISD::TRUNCATE, DL, VT, Op); +} + +SDValue SelectionDAG::getZExtOrTrunc(SDValue Op, DebugLoc DL, EVT VT) { + return VT.bitsGT(Op.getValueType()) ? + getNode(ISD::ZERO_EXTEND, DL, VT, Op) : + getNode(ISD::TRUNCATE, DL, VT, Op); +} + +SDValue SelectionDAG::getZeroExtendInReg(SDValue Op, DebugLoc DL, EVT VT) { + if (Op.getValueType() == VT) return Op; + APInt Imm = APInt::getLowBitsSet(Op.getValueSizeInBits(), + VT.getSizeInBits()); + return getNode(ISD::AND, DL, Op.getValueType(), Op, + getConstant(Imm, Op.getValueType())); +} + +/// getNOT - Create a bitwise NOT operation as (XOR Val, -1). +/// +SDValue SelectionDAG::getNOT(DebugLoc DL, SDValue Val, EVT VT) { + EVT EltVT = VT.isVector() ? VT.getVectorElementType() : VT; + SDValue NegOne = + getConstant(APInt::getAllOnesValue(EltVT.getSizeInBits()), VT); + return getNode(ISD::XOR, DL, VT, Val, NegOne); +} + +SDValue SelectionDAG::getConstant(uint64_t Val, EVT VT, bool isT) { + EVT EltVT = VT.isVector() ? VT.getVectorElementType() : VT; + assert((EltVT.getSizeInBits() >= 64 || + (uint64_t)((int64_t)Val >> EltVT.getSizeInBits()) + 1 < 2) && + "getConstant with a uint64_t value that doesn't fit in the type!"); + return getConstant(APInt(EltVT.getSizeInBits(), Val), VT, isT); +} + +SDValue SelectionDAG::getConstant(const APInt &Val, EVT VT, bool isT) { + return getConstant(*ConstantInt::get(*Context, Val), VT, isT); +} + +SDValue SelectionDAG::getConstant(const ConstantInt &Val, EVT VT, bool isT) { + assert(VT.isInteger() && "Cannot create FP integer constant!"); + + EVT EltVT = VT.isVector() ? VT.getVectorElementType() : VT; + assert(Val.getBitWidth() == EltVT.getSizeInBits() && + "APInt size does not match type size!"); + + unsigned Opc = isT ? ISD::TargetConstant : ISD::Constant; + FoldingSetNodeID ID; + AddNodeIDNode(ID, Opc, getVTList(EltVT), 0, 0); + ID.AddPointer(&Val); + void *IP = 0; + SDNode *N = NULL; + if ((N = CSEMap.FindNodeOrInsertPos(ID, IP))) + if (!VT.isVector()) + return SDValue(N, 0); + if (!N) { + N = NodeAllocator.Allocate(); + new (N) ConstantSDNode(isT, &Val, EltVT); + CSEMap.InsertNode(N, IP); + AllNodes.push_back(N); + } + + SDValue Result(N, 0); + if (VT.isVector()) { + SmallVector Ops; + Ops.assign(VT.getVectorNumElements(), Result); + Result = getNode(ISD::BUILD_VECTOR, DebugLoc::getUnknownLoc(), + VT, &Ops[0], Ops.size()); + } + return Result; +} + +SDValue SelectionDAG::getIntPtrConstant(uint64_t Val, bool isTarget) { + return getConstant(Val, TLI.getPointerTy(), isTarget); +} + + +SDValue SelectionDAG::getConstantFP(const APFloat& V, EVT VT, bool isTarget) { + return getConstantFP(*ConstantFP::get(*getContext(), V), VT, isTarget); +} + +SDValue SelectionDAG::getConstantFP(const ConstantFP& V, EVT VT, bool isTarget){ + assert(VT.isFloatingPoint() && "Cannot create integer FP constant!"); + + EVT EltVT = + VT.isVector() ? VT.getVectorElementType() : VT; + + // Do the map lookup using the actual bit pattern for the floating point + // value, so that we don't have problems with 0.0 comparing equal to -0.0, and + // we don't have issues with SNANs. + unsigned Opc = isTarget ? ISD::TargetConstantFP : ISD::ConstantFP; + FoldingSetNodeID ID; + AddNodeIDNode(ID, Opc, getVTList(EltVT), 0, 0); + ID.AddPointer(&V); + void *IP = 0; + SDNode *N = NULL; + if ((N = CSEMap.FindNodeOrInsertPos(ID, IP))) + if (!VT.isVector()) + return SDValue(N, 0); + if (!N) { + N = NodeAllocator.Allocate(); + new (N) ConstantFPSDNode(isTarget, &V, EltVT); + CSEMap.InsertNode(N, IP); + AllNodes.push_back(N); + } + + SDValue Result(N, 0); + if (VT.isVector()) { + SmallVector Ops; + Ops.assign(VT.getVectorNumElements(), Result); + // FIXME DebugLoc info might be appropriate here + Result = getNode(ISD::BUILD_VECTOR, DebugLoc::getUnknownLoc(), + VT, &Ops[0], Ops.size()); + } + return Result; +} + +SDValue SelectionDAG::getConstantFP(double Val, EVT VT, bool isTarget) { + EVT EltVT = + VT.isVector() ? VT.getVectorElementType() : VT; + if (EltVT==MVT::f32) + return getConstantFP(APFloat((float)Val), VT, isTarget); + else + return getConstantFP(APFloat(Val), VT, isTarget); +} + +SDValue SelectionDAG::getGlobalAddress(const GlobalValue *GV, + EVT VT, int64_t Offset, + bool isTargetGA, + unsigned char TargetFlags) { + assert((TargetFlags == 0 || isTargetGA) && + "Cannot set target flags on target-independent globals"); + + // Truncate (with sign-extension) the offset value to the pointer size. + EVT PTy = TLI.getPointerTy(); + unsigned BitWidth = PTy.getSizeInBits(); + if (BitWidth < 64) + Offset = (Offset << (64 - BitWidth) >> (64 - BitWidth)); + + const GlobalVariable *GVar = dyn_cast(GV); + if (!GVar) { + // If GV is an alias then use the aliasee for determining thread-localness. + if (const GlobalAlias *GA = dyn_cast(GV)) + GVar = dyn_cast_or_null(GA->resolveAliasedGlobal(false)); + } + + unsigned Opc; + if (GVar && GVar->isThreadLocal()) + Opc = isTargetGA ? ISD::TargetGlobalTLSAddress : ISD::GlobalTLSAddress; + else + Opc = isTargetGA ? ISD::TargetGlobalAddress : ISD::GlobalAddress; + + FoldingSetNodeID ID; + AddNodeIDNode(ID, Opc, getVTList(VT), 0, 0); + ID.AddPointer(GV); + ID.AddInteger(Offset); + ID.AddInteger(TargetFlags); + void *IP = 0; + if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) + return SDValue(E, 0); + SDNode *N = NodeAllocator.Allocate(); + new (N) GlobalAddressSDNode(Opc, GV, VT, Offset, TargetFlags); + CSEMap.InsertNode(N, IP); + AllNodes.push_back(N); + return SDValue(N, 0); +} + +SDValue SelectionDAG::getFrameIndex(int FI, EVT VT, bool isTarget) { + unsigned Opc = isTarget ? ISD::TargetFrameIndex : ISD::FrameIndex; + FoldingSetNodeID ID; + AddNodeIDNode(ID, Opc, getVTList(VT), 0, 0); + ID.AddInteger(FI); + void *IP = 0; + if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) + return SDValue(E, 0); + SDNode *N = NodeAllocator.Allocate(); + new (N) FrameIndexSDNode(FI, VT, isTarget); + CSEMap.InsertNode(N, IP); + AllNodes.push_back(N); + return SDValue(N, 0); +} + +SDValue SelectionDAG::getJumpTable(int JTI, EVT VT, bool isTarget, + unsigned char TargetFlags) { + assert((TargetFlags == 0 || isTarget) && + "Cannot set target flags on target-independent jump tables"); + unsigned Opc = isTarget ? ISD::TargetJumpTable : ISD::JumpTable; + FoldingSetNodeID ID; + AddNodeIDNode(ID, Opc, getVTList(VT), 0, 0); + ID.AddInteger(JTI); + ID.AddInteger(TargetFlags); + void *IP = 0; + if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) + return SDValue(E, 0); + SDNode *N = NodeAllocator.Allocate(); + new (N) JumpTableSDNode(JTI, VT, isTarget, TargetFlags); + CSEMap.InsertNode(N, IP); + AllNodes.push_back(N); + return SDValue(N, 0); +} + +SDValue SelectionDAG::getConstantPool(Constant *C, EVT VT, + unsigned Alignment, int Offset, + bool isTarget, + unsigned char TargetFlags) { + assert((TargetFlags == 0 || isTarget) && + "Cannot set target flags on target-independent globals"); + if (Alignment == 0) + Alignment = TLI.getTargetData()->getPrefTypeAlignment(C->getType()); + unsigned Opc = isTarget ? ISD::TargetConstantPool : ISD::ConstantPool; + FoldingSetNodeID ID; + AddNodeIDNode(ID, Opc, getVTList(VT), 0, 0); + ID.AddInteger(Alignment); + ID.AddInteger(Offset); + ID.AddPointer(C); + ID.AddInteger(TargetFlags); + void *IP = 0; + if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) + return SDValue(E, 0); + SDNode *N = NodeAllocator.Allocate(); + new (N) ConstantPoolSDNode(isTarget, C, VT, Offset, Alignment, TargetFlags); + CSEMap.InsertNode(N, IP); + AllNodes.push_back(N); + return SDValue(N, 0); +} + + +SDValue SelectionDAG::getConstantPool(MachineConstantPoolValue *C, EVT VT, + unsigned Alignment, int Offset, + bool isTarget, + unsigned char TargetFlags) { + assert((TargetFlags == 0 || isTarget) && + "Cannot set target flags on target-independent globals"); + if (Alignment == 0) + Alignment = TLI.getTargetData()->getPrefTypeAlignment(C->getType()); + unsigned Opc = isTarget ? ISD::TargetConstantPool : ISD::ConstantPool; + FoldingSetNodeID ID; + AddNodeIDNode(ID, Opc, getVTList(VT), 0, 0); + ID.AddInteger(Alignment); + ID.AddInteger(Offset); + C->AddSelectionDAGCSEId(ID); + ID.AddInteger(TargetFlags); + void *IP = 0; + if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) + return SDValue(E, 0); + SDNode *N = NodeAllocator.Allocate(); + new (N) ConstantPoolSDNode(isTarget, C, VT, Offset, Alignment, TargetFlags); + CSEMap.InsertNode(N, IP); + AllNodes.push_back(N); + return SDValue(N, 0); +} + +SDValue SelectionDAG::getBasicBlock(MachineBasicBlock *MBB) { + FoldingSetNodeID ID; + AddNodeIDNode(ID, ISD::BasicBlock, getVTList(MVT::Other), 0, 0); + ID.AddPointer(MBB); + void *IP = 0; + if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) + return SDValue(E, 0); + SDNode *N = NodeAllocator.Allocate(); + new (N) BasicBlockSDNode(MBB); + CSEMap.InsertNode(N, IP); + AllNodes.push_back(N); + return SDValue(N, 0); +} + +SDValue SelectionDAG::getValueType(EVT VT) { + if (VT.isSimple() && (unsigned)VT.getSimpleVT().SimpleTy >= + ValueTypeNodes.size()) + ValueTypeNodes.resize(VT.getSimpleVT().SimpleTy+1); + + SDNode *&N = VT.isExtended() ? + ExtendedValueTypeNodes[VT] : ValueTypeNodes[VT.getSimpleVT().SimpleTy]; + + if (N) return SDValue(N, 0); + N = NodeAllocator.Allocate(); + new (N) VTSDNode(VT); + AllNodes.push_back(N); + return SDValue(N, 0); +} + +SDValue SelectionDAG::getExternalSymbol(const char *Sym, EVT VT) { + SDNode *&N = ExternalSymbols[Sym]; + if (N) return SDValue(N, 0); + N = NodeAllocator.Allocate(); + new (N) ExternalSymbolSDNode(false, Sym, 0, VT); + AllNodes.push_back(N); + return SDValue(N, 0); +} + +SDValue SelectionDAG::getTargetExternalSymbol(const char *Sym, EVT VT, + unsigned char TargetFlags) { + SDNode *&N = + TargetExternalSymbols[std::pair(Sym, + TargetFlags)]; + if (N) return SDValue(N, 0); + N = NodeAllocator.Allocate(); + new (N) ExternalSymbolSDNode(true, Sym, TargetFlags, VT); + AllNodes.push_back(N); + return SDValue(N, 0); +} + +SDValue SelectionDAG::getCondCode(ISD::CondCode Cond) { + if ((unsigned)Cond >= CondCodeNodes.size()) + CondCodeNodes.resize(Cond+1); + + if (CondCodeNodes[Cond] == 0) { + CondCodeSDNode *N = NodeAllocator.Allocate(); + new (N) CondCodeSDNode(Cond); + CondCodeNodes[Cond] = N; + AllNodes.push_back(N); + } + return SDValue(CondCodeNodes[Cond], 0); +} + +// commuteShuffle - swaps the values of N1 and N2, and swaps all indices in +// the shuffle mask M that point at N1 to point at N2, and indices that point +// N2 to point at N1. +static void commuteShuffle(SDValue &N1, SDValue &N2, SmallVectorImpl &M) { + std::swap(N1, N2); + int NElts = M.size(); + for (int i = 0; i != NElts; ++i) { + if (M[i] >= NElts) + M[i] -= NElts; + else if (M[i] >= 0) + M[i] += NElts; + } +} + +SDValue SelectionDAG::getVectorShuffle(EVT VT, DebugLoc dl, SDValue N1, + SDValue N2, const int *Mask) { + assert(N1.getValueType() == N2.getValueType() && "Invalid VECTOR_SHUFFLE"); + assert(VT.isVector() && N1.getValueType().isVector() && + "Vector Shuffle VTs must be a vectors"); + assert(VT.getVectorElementType() == N1.getValueType().getVectorElementType() + && "Vector Shuffle VTs must have same element type"); + + // Canonicalize shuffle undef, undef -> undef + if (N1.getOpcode() == ISD::UNDEF && N2.getOpcode() == ISD::UNDEF) + return getUNDEF(VT); + + // Validate that all indices in Mask are within the range of the elements + // input to the shuffle. + unsigned NElts = VT.getVectorNumElements(); + SmallVector MaskVec; + for (unsigned i = 0; i != NElts; ++i) { + assert(Mask[i] < (int)(NElts * 2) && "Index out of range"); + MaskVec.push_back(Mask[i]); + } + + // Canonicalize shuffle v, v -> v, undef + if (N1 == N2) { + N2 = getUNDEF(VT); + for (unsigned i = 0; i != NElts; ++i) + if (MaskVec[i] >= (int)NElts) MaskVec[i] -= NElts; + } + + // Canonicalize shuffle undef, v -> v, undef. Commute the shuffle mask. + if (N1.getOpcode() == ISD::UNDEF) + commuteShuffle(N1, N2, MaskVec); + + // Canonicalize all index into lhs, -> shuffle lhs, undef + // Canonicalize all index into rhs, -> shuffle rhs, undef + bool AllLHS = true, AllRHS = true; + bool N2Undef = N2.getOpcode() == ISD::UNDEF; + for (unsigned i = 0; i != NElts; ++i) { + if (MaskVec[i] >= (int)NElts) { + if (N2Undef) + MaskVec[i] = -1; + else + AllLHS = false; + } else if (MaskVec[i] >= 0) { + AllRHS = false; + } + } + if (AllLHS && AllRHS) + return getUNDEF(VT); + if (AllLHS && !N2Undef) + N2 = getUNDEF(VT); + if (AllRHS) { + N1 = getUNDEF(VT); + commuteShuffle(N1, N2, MaskVec); + } + + // If Identity shuffle, or all shuffle in to undef, return that node. + bool AllUndef = true; + bool Identity = true; + for (unsigned i = 0; i != NElts; ++i) { + if (MaskVec[i] >= 0 && MaskVec[i] != (int)i) Identity = false; + if (MaskVec[i] >= 0) AllUndef = false; + } + if (Identity && NElts == N1.getValueType().getVectorNumElements()) + return N1; + if (AllUndef) + return getUNDEF(VT); + + FoldingSetNodeID ID; + SDValue Ops[2] = { N1, N2 }; + AddNodeIDNode(ID, ISD::VECTOR_SHUFFLE, getVTList(VT), Ops, 2); + for (unsigned i = 0; i != NElts; ++i) + ID.AddInteger(MaskVec[i]); + + void* IP = 0; + if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) + return SDValue(E, 0); + + // Allocate the mask array for the node out of the BumpPtrAllocator, since + // SDNode doesn't have access to it. This memory will be "leaked" when + // the node is deallocated, but recovered when the NodeAllocator is released. + int *MaskAlloc = OperandAllocator.Allocate(NElts); + memcpy(MaskAlloc, &MaskVec[0], NElts * sizeof(int)); + + ShuffleVectorSDNode *N = NodeAllocator.Allocate(); + new (N) ShuffleVectorSDNode(VT, dl, N1, N2, MaskAlloc); + CSEMap.InsertNode(N, IP); + AllNodes.push_back(N); + return SDValue(N, 0); +} + +SDValue SelectionDAG::getConvertRndSat(EVT VT, DebugLoc dl, + SDValue Val, SDValue DTy, + SDValue STy, SDValue Rnd, SDValue Sat, + ISD::CvtCode Code) { + // If the src and dest types are the same and the conversion is between + // integer types of the same sign or two floats, no conversion is necessary. + if (DTy == STy && + (Code == ISD::CVT_UU || Code == ISD::CVT_SS || Code == ISD::CVT_FF)) + return Val; + + FoldingSetNodeID ID; + SDValue Ops[] = { Val, DTy, STy, Rnd, Sat }; + AddNodeIDNode(ID, ISD::CONVERT_RNDSAT, getVTList(VT), &Ops[0], 5); + void* IP = 0; + if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) + return SDValue(E, 0); + CvtRndSatSDNode *N = NodeAllocator.Allocate(); + new (N) CvtRndSatSDNode(VT, dl, Ops, 5, Code); + CSEMap.InsertNode(N, IP); + AllNodes.push_back(N); + return SDValue(N, 0); +} + +SDValue SelectionDAG::getRegister(unsigned RegNo, EVT VT) { + FoldingSetNodeID ID; + AddNodeIDNode(ID, ISD::Register, getVTList(VT), 0, 0); + ID.AddInteger(RegNo); + void *IP = 0; + if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) + return SDValue(E, 0); + SDNode *N = NodeAllocator.Allocate(); + new (N) RegisterSDNode(RegNo, VT); + CSEMap.InsertNode(N, IP); + AllNodes.push_back(N); + return SDValue(N, 0); +} + +SDValue SelectionDAG::getLabel(unsigned Opcode, DebugLoc dl, + SDValue Root, + unsigned LabelID) { + FoldingSetNodeID ID; + SDValue Ops[] = { Root }; + AddNodeIDNode(ID, Opcode, getVTList(MVT::Other), &Ops[0], 1); + ID.AddInteger(LabelID); + void *IP = 0; + if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) + return SDValue(E, 0); + SDNode *N = NodeAllocator.Allocate(); + new (N) LabelSDNode(Opcode, dl, Root, LabelID); + CSEMap.InsertNode(N, IP); + AllNodes.push_back(N); + return SDValue(N, 0); +} + +SDValue SelectionDAG::getBlockAddress(BlockAddress *BA, EVT VT, + bool isTarget, + unsigned char TargetFlags) { + unsigned Opc = isTarget ? ISD::TargetBlockAddress : ISD::BlockAddress; + + FoldingSetNodeID ID; + AddNodeIDNode(ID, Opc, getVTList(VT), 0, 0); + ID.AddPointer(BA); + ID.AddInteger(TargetFlags); + void *IP = 0; + if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) + return SDValue(E, 0); + SDNode *N = NodeAllocator.Allocate(); + new (N) BlockAddressSDNode(Opc, VT, BA, TargetFlags); + CSEMap.InsertNode(N, IP); + AllNodes.push_back(N); + return SDValue(N, 0); +} + +SDValue SelectionDAG::getSrcValue(const Value *V) { + assert((!V || isa(V->getType())) && + "SrcValue is not a pointer?"); + + FoldingSetNodeID ID; + AddNodeIDNode(ID, ISD::SRCVALUE, getVTList(MVT::Other), 0, 0); + ID.AddPointer(V); + + void *IP = 0; + if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) + return SDValue(E, 0); + + SDNode *N = NodeAllocator.Allocate(); + new (N) SrcValueSDNode(V); + CSEMap.InsertNode(N, IP); + AllNodes.push_back(N); + return SDValue(N, 0); +} + +/// getShiftAmountOperand - Return the specified value casted to +/// the target's desired shift amount type. +SDValue SelectionDAG::getShiftAmountOperand(SDValue Op) { + EVT OpTy = Op.getValueType(); + MVT ShTy = TLI.getShiftAmountTy(); + if (OpTy == ShTy || OpTy.isVector()) return Op; + + ISD::NodeType Opcode = OpTy.bitsGT(ShTy) ? ISD::TRUNCATE : ISD::ZERO_EXTEND; + return getNode(Opcode, Op.getDebugLoc(), ShTy, Op); +} + +/// CreateStackTemporary - Create a stack temporary, suitable for holding the +/// specified value type. +SDValue SelectionDAG::CreateStackTemporary(EVT VT, unsigned minAlign) { + MachineFrameInfo *FrameInfo = getMachineFunction().getFrameInfo(); + unsigned ByteSize = VT.getStoreSize(); + const Type *Ty = VT.getTypeForEVT(*getContext()); + unsigned StackAlign = + std::max((unsigned)TLI.getTargetData()->getPrefTypeAlignment(Ty), minAlign); + + int FrameIdx = FrameInfo->CreateStackObject(ByteSize, StackAlign, false); + return getFrameIndex(FrameIdx, TLI.getPointerTy()); +} + +/// CreateStackTemporary - Create a stack temporary suitable for holding +/// either of the specified value types. +SDValue SelectionDAG::CreateStackTemporary(EVT VT1, EVT VT2) { + unsigned Bytes = std::max(VT1.getStoreSizeInBits(), + VT2.getStoreSizeInBits())/8; + const Type *Ty1 = VT1.getTypeForEVT(*getContext()); + const Type *Ty2 = VT2.getTypeForEVT(*getContext()); + const TargetData *TD = TLI.getTargetData(); + unsigned Align = std::max(TD->getPrefTypeAlignment(Ty1), + TD->getPrefTypeAlignment(Ty2)); + + MachineFrameInfo *FrameInfo = getMachineFunction().getFrameInfo(); + int FrameIdx = FrameInfo->CreateStackObject(Bytes, Align, false); + return getFrameIndex(FrameIdx, TLI.getPointerTy()); +} + +SDValue SelectionDAG::FoldSetCC(EVT VT, SDValue N1, + SDValue N2, ISD::CondCode Cond, DebugLoc dl) { + // These setcc operations always fold. + switch (Cond) { + default: break; + case ISD::SETFALSE: + case ISD::SETFALSE2: return getConstant(0, VT); + case ISD::SETTRUE: + case ISD::SETTRUE2: return getConstant(1, VT); + + case ISD::SETOEQ: + case ISD::SETOGT: + case ISD::SETOGE: + case ISD::SETOLT: + case ISD::SETOLE: + case ISD::SETONE: + case ISD::SETO: + case ISD::SETUO: + case ISD::SETUEQ: + case ISD::SETUNE: + assert(!N1.getValueType().isInteger() && "Illegal setcc for integer!"); + break; + } + + if (ConstantSDNode *N2C = dyn_cast(N2.getNode())) { + const APInt &C2 = N2C->getAPIntValue(); + if (ConstantSDNode *N1C = dyn_cast(N1.getNode())) { + const APInt &C1 = N1C->getAPIntValue(); + + switch (Cond) { + default: llvm_unreachable("Unknown integer setcc!"); + case ISD::SETEQ: return getConstant(C1 == C2, VT); + case ISD::SETNE: return getConstant(C1 != C2, VT); + case ISD::SETULT: return getConstant(C1.ult(C2), VT); + case ISD::SETUGT: return getConstant(C1.ugt(C2), VT); + case ISD::SETULE: return getConstant(C1.ule(C2), VT); + case ISD::SETUGE: return getConstant(C1.uge(C2), VT); + case ISD::SETLT: return getConstant(C1.slt(C2), VT); + case ISD::SETGT: return getConstant(C1.sgt(C2), VT); + case ISD::SETLE: return getConstant(C1.sle(C2), VT); + case ISD::SETGE: return getConstant(C1.sge(C2), VT); + } + } + } + if (ConstantFPSDNode *N1C = dyn_cast(N1.getNode())) { + if (ConstantFPSDNode *N2C = dyn_cast(N2.getNode())) { + // No compile time operations on this type yet. + if (N1C->getValueType(0) == MVT::ppcf128) + return SDValue(); + + APFloat::cmpResult R = N1C->getValueAPF().compare(N2C->getValueAPF()); + switch (Cond) { + default: break; + case ISD::SETEQ: if (R==APFloat::cmpUnordered) + return getUNDEF(VT); + // fall through + case ISD::SETOEQ: return getConstant(R==APFloat::cmpEqual, VT); + case ISD::SETNE: if (R==APFloat::cmpUnordered) + return getUNDEF(VT); + // fall through + case ISD::SETONE: return getConstant(R==APFloat::cmpGreaterThan || + R==APFloat::cmpLessThan, VT); + case ISD::SETLT: if (R==APFloat::cmpUnordered) + return getUNDEF(VT); + // fall through + case ISD::SETOLT: return getConstant(R==APFloat::cmpLessThan, VT); + case ISD::SETGT: if (R==APFloat::cmpUnordered) + return getUNDEF(VT); + // fall through + case ISD::SETOGT: return getConstant(R==APFloat::cmpGreaterThan, VT); + case ISD::SETLE: if (R==APFloat::cmpUnordered) + return getUNDEF(VT); + // fall through + case ISD::SETOLE: return getConstant(R==APFloat::cmpLessThan || + R==APFloat::cmpEqual, VT); + case ISD::SETGE: if (R==APFloat::cmpUnordered) + return getUNDEF(VT); + // fall through + case ISD::SETOGE: return getConstant(R==APFloat::cmpGreaterThan || + R==APFloat::cmpEqual, VT); + case ISD::SETO: return getConstant(R!=APFloat::cmpUnordered, VT); + case ISD::SETUO: return getConstant(R==APFloat::cmpUnordered, VT); + case ISD::SETUEQ: return getConstant(R==APFloat::cmpUnordered || + R==APFloat::cmpEqual, VT); + case ISD::SETUNE: return getConstant(R!=APFloat::cmpEqual, VT); + case ISD::SETULT: return getConstant(R==APFloat::cmpUnordered || + R==APFloat::cmpLessThan, VT); + case ISD::SETUGT: return getConstant(R==APFloat::cmpGreaterThan || + R==APFloat::cmpUnordered, VT); + case ISD::SETULE: return getConstant(R!=APFloat::cmpGreaterThan, VT); + case ISD::SETUGE: return getConstant(R!=APFloat::cmpLessThan, VT); + } + } else { + // Ensure that the constant occurs on the RHS. + return getSetCC(dl, VT, N2, N1, ISD::getSetCCSwappedOperands(Cond)); + } + } + + // Could not fold it. + return SDValue(); +} + +/// SignBitIsZero - Return true if the sign bit of Op is known to be zero. We +/// use this predicate to simplify operations downstream. +bool SelectionDAG::SignBitIsZero(SDValue Op, unsigned Depth) const { + // This predicate is not safe for vector operations. + if (Op.getValueType().isVector()) + return false; + + unsigned BitWidth = Op.getValueSizeInBits(); + return MaskedValueIsZero(Op, APInt::getSignBit(BitWidth), Depth); +} + +/// MaskedValueIsZero - Return true if 'V & Mask' is known to be zero. We use +/// this predicate to simplify operations downstream. Mask is known to be zero +/// for bits that V cannot have. +bool SelectionDAG::MaskedValueIsZero(SDValue Op, const APInt &Mask, + unsigned Depth) const { + APInt KnownZero, KnownOne; + ComputeMaskedBits(Op, Mask, KnownZero, KnownOne, Depth); + assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?"); + return (KnownZero & Mask) == Mask; +} + +/// ComputeMaskedBits - Determine which of the bits specified in Mask are +/// known to be either zero or one and return them in the KnownZero/KnownOne +/// bitsets. This code only analyzes bits in Mask, in order to short-circuit +/// processing. +void SelectionDAG::ComputeMaskedBits(SDValue Op, const APInt &Mask, + APInt &KnownZero, APInt &KnownOne, + unsigned Depth) const { + unsigned BitWidth = Mask.getBitWidth(); + assert(BitWidth == Op.getValueType().getSizeInBits() && + "Mask size mismatches value type size!"); + + KnownZero = KnownOne = APInt(BitWidth, 0); // Don't know anything. + if (Depth == 6 || Mask == 0) + return; // Limit search depth. + + APInt KnownZero2, KnownOne2; + + switch (Op.getOpcode()) { + case ISD::Constant: + // We know all of the bits for a constant! + KnownOne = cast(Op)->getAPIntValue() & Mask; + KnownZero = ~KnownOne & Mask; + return; + case ISD::AND: + // If either the LHS or the RHS are Zero, the result is zero. + ComputeMaskedBits(Op.getOperand(1), Mask, KnownZero, KnownOne, Depth+1); + ComputeMaskedBits(Op.getOperand(0), Mask & ~KnownZero, + KnownZero2, KnownOne2, Depth+1); + assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?"); + assert((KnownZero2 & KnownOne2) == 0 && "Bits known to be one AND zero?"); + + // Output known-1 bits are only known if set in both the LHS & RHS. + KnownOne &= KnownOne2; + // Output known-0 are known to be clear if zero in either the LHS | RHS. + KnownZero |= KnownZero2; + return; + case ISD::OR: + ComputeMaskedBits(Op.getOperand(1), Mask, KnownZero, KnownOne, Depth+1); + ComputeMaskedBits(Op.getOperand(0), Mask & ~KnownOne, + KnownZero2, KnownOne2, Depth+1); + assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?"); + assert((KnownZero2 & KnownOne2) == 0 && "Bits known to be one AND zero?"); + + // Output known-0 bits are only known if clear in both the LHS & RHS. + KnownZero &= KnownZero2; + // Output known-1 are known to be set if set in either the LHS | RHS. + KnownOne |= KnownOne2; + return; + case ISD::XOR: { + ComputeMaskedBits(Op.getOperand(1), Mask, KnownZero, KnownOne, Depth+1); + ComputeMaskedBits(Op.getOperand(0), Mask, KnownZero2, KnownOne2, Depth+1); + assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?"); + assert((KnownZero2 & KnownOne2) == 0 && "Bits known to be one AND zero?"); + + // Output known-0 bits are known if clear or set in both the LHS & RHS. + APInt KnownZeroOut = (KnownZero & KnownZero2) | (KnownOne & KnownOne2); + // Output known-1 are known to be set if set in only one of the LHS, RHS. + KnownOne = (KnownZero & KnownOne2) | (KnownOne & KnownZero2); + KnownZero = KnownZeroOut; + return; + } + case ISD::MUL: { + APInt Mask2 = APInt::getAllOnesValue(BitWidth); + ComputeMaskedBits(Op.getOperand(1), Mask2, KnownZero, KnownOne, Depth+1); + ComputeMaskedBits(Op.getOperand(0), Mask2, KnownZero2, KnownOne2, Depth+1); + assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?"); + assert((KnownZero2 & KnownOne2) == 0 && "Bits known to be one AND zero?"); + + // If low bits are zero in either operand, output low known-0 bits. + // Also compute a conserative estimate for high known-0 bits. + // More trickiness is possible, but this is sufficient for the + // interesting case of alignment computation. + KnownOne.clear(); + unsigned TrailZ = KnownZero.countTrailingOnes() + + KnownZero2.countTrailingOnes(); + unsigned LeadZ = std::max(KnownZero.countLeadingOnes() + + KnownZero2.countLeadingOnes(), + BitWidth) - BitWidth; + + TrailZ = std::min(TrailZ, BitWidth); + LeadZ = std::min(LeadZ, BitWidth); + KnownZero = APInt::getLowBitsSet(BitWidth, TrailZ) | + APInt::getHighBitsSet(BitWidth, LeadZ); + KnownZero &= Mask; + return; + } + case ISD::UDIV: { + // For the purposes of computing leading zeros we can conservatively + // treat a udiv as a logical right shift by the power of 2 known to + // be less than the denominator. + APInt AllOnes = APInt::getAllOnesValue(BitWidth); + ComputeMaskedBits(Op.getOperand(0), + AllOnes, KnownZero2, KnownOne2, Depth+1); + unsigned LeadZ = KnownZero2.countLeadingOnes(); + + KnownOne2.clear(); + KnownZero2.clear(); + ComputeMaskedBits(Op.getOperand(1), + AllOnes, KnownZero2, KnownOne2, Depth+1); + unsigned RHSUnknownLeadingOnes = KnownOne2.countLeadingZeros(); + if (RHSUnknownLeadingOnes != BitWidth) + LeadZ = std::min(BitWidth, + LeadZ + BitWidth - RHSUnknownLeadingOnes - 1); + + KnownZero = APInt::getHighBitsSet(BitWidth, LeadZ) & Mask; + return; + } + case ISD::SELECT: + ComputeMaskedBits(Op.getOperand(2), Mask, KnownZero, KnownOne, Depth+1); + ComputeMaskedBits(Op.getOperand(1), Mask, KnownZero2, KnownOne2, Depth+1); + assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?"); + assert((KnownZero2 & KnownOne2) == 0 && "Bits known to be one AND zero?"); + + // Only known if known in both the LHS and RHS. + KnownOne &= KnownOne2; + KnownZero &= KnownZero2; + return; + case ISD::SELECT_CC: + ComputeMaskedBits(Op.getOperand(3), Mask, KnownZero, KnownOne, Depth+1); + ComputeMaskedBits(Op.getOperand(2), Mask, KnownZero2, KnownOne2, Depth+1); + assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?"); + assert((KnownZero2 & KnownOne2) == 0 && "Bits known to be one AND zero?"); + + // Only known if known in both the LHS and RHS. + KnownOne &= KnownOne2; + KnownZero &= KnownZero2; + return; + case ISD::SADDO: + case ISD::UADDO: + case ISD::SSUBO: + case ISD::USUBO: + case ISD::SMULO: + case ISD::UMULO: + if (Op.getResNo() != 1) + return; + // The boolean result conforms to getBooleanContents. Fall through. + case ISD::SETCC: + // If we know the result of a setcc has the top bits zero, use this info. + if (TLI.getBooleanContents() == TargetLowering::ZeroOrOneBooleanContent && + BitWidth > 1) + KnownZero |= APInt::getHighBitsSet(BitWidth, BitWidth - 1); + return; + case ISD::SHL: + // (shl X, C1) & C2 == 0 iff (X & C2 >>u C1) == 0 + if (ConstantSDNode *SA = dyn_cast(Op.getOperand(1))) { + unsigned ShAmt = SA->getZExtValue(); + + // If the shift count is an invalid immediate, don't do anything. + if (ShAmt >= BitWidth) + return; + + ComputeMaskedBits(Op.getOperand(0), Mask.lshr(ShAmt), + KnownZero, KnownOne, Depth+1); + assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?"); + KnownZero <<= ShAmt; + KnownOne <<= ShAmt; + // low bits known zero. + KnownZero |= APInt::getLowBitsSet(BitWidth, ShAmt); + } + return; + case ISD::SRL: + // (ushr X, C1) & C2 == 0 iff (-1 >> C1) & C2 == 0 + if (ConstantSDNode *SA = dyn_cast(Op.getOperand(1))) { + unsigned ShAmt = SA->getZExtValue(); + + // If the shift count is an invalid immediate, don't do anything. + if (ShAmt >= BitWidth) + return; + + ComputeMaskedBits(Op.getOperand(0), (Mask << ShAmt), + KnownZero, KnownOne, Depth+1); + assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?"); + KnownZero = KnownZero.lshr(ShAmt); + KnownOne = KnownOne.lshr(ShAmt); + + APInt HighBits = APInt::getHighBitsSet(BitWidth, ShAmt) & Mask; + KnownZero |= HighBits; // High bits known zero. + } + return; + case ISD::SRA: + if (ConstantSDNode *SA = dyn_cast(Op.getOperand(1))) { + unsigned ShAmt = SA->getZExtValue(); + + // If the shift count is an invalid immediate, don't do anything. + if (ShAmt >= BitWidth) + return; + + APInt InDemandedMask = (Mask << ShAmt); + // If any of the demanded bits are produced by the sign extension, we also + // demand the input sign bit. + APInt HighBits = APInt::getHighBitsSet(BitWidth, ShAmt) & Mask; + if (HighBits.getBoolValue()) + InDemandedMask |= APInt::getSignBit(BitWidth); + + ComputeMaskedBits(Op.getOperand(0), InDemandedMask, KnownZero, KnownOne, + Depth+1); + assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?"); + KnownZero = KnownZero.lshr(ShAmt); + KnownOne = KnownOne.lshr(ShAmt); + + // Handle the sign bits. + APInt SignBit = APInt::getSignBit(BitWidth); + SignBit = SignBit.lshr(ShAmt); // Adjust to where it is now in the mask. + + if (KnownZero.intersects(SignBit)) { + KnownZero |= HighBits; // New bits are known zero. + } else if (KnownOne.intersects(SignBit)) { + KnownOne |= HighBits; // New bits are known one. + } + } + return; + case ISD::SIGN_EXTEND_INREG: { + EVT EVT = cast(Op.getOperand(1))->getVT(); + unsigned EBits = EVT.getSizeInBits(); + + // Sign extension. Compute the demanded bits in the result that are not + // present in the input. + APInt NewBits = APInt::getHighBitsSet(BitWidth, BitWidth - EBits) & Mask; + + APInt InSignBit = APInt::getSignBit(EBits); + APInt InputDemandedBits = Mask & APInt::getLowBitsSet(BitWidth, EBits); + + // If the sign extended bits are demanded, we know that the sign + // bit is demanded. + InSignBit.zext(BitWidth); + if (NewBits.getBoolValue()) + InputDemandedBits |= InSignBit; + + ComputeMaskedBits(Op.getOperand(0), InputDemandedBits, + KnownZero, KnownOne, Depth+1); + assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?"); + + // If the sign bit of the input is known set or clear, then we know the + // top bits of the result. + if (KnownZero.intersects(InSignBit)) { // Input sign bit known clear + KnownZero |= NewBits; + KnownOne &= ~NewBits; + } else if (KnownOne.intersects(InSignBit)) { // Input sign bit known set + KnownOne |= NewBits; + KnownZero &= ~NewBits; + } else { // Input sign bit unknown + KnownZero &= ~NewBits; + KnownOne &= ~NewBits; + } + return; + } + case ISD::CTTZ: + case ISD::CTLZ: + case ISD::CTPOP: { + unsigned LowBits = Log2_32(BitWidth)+1; + KnownZero = APInt::getHighBitsSet(BitWidth, BitWidth - LowBits); + KnownOne.clear(); + return; + } + case ISD::LOAD: { + if (ISD::isZEXTLoad(Op.getNode())) { + LoadSDNode *LD = cast(Op); + EVT VT = LD->getMemoryVT(); + unsigned MemBits = VT.getSizeInBits(); + KnownZero |= APInt::getHighBitsSet(BitWidth, BitWidth - MemBits) & Mask; + } + return; + } + case ISD::ZERO_EXTEND: { + EVT InVT = Op.getOperand(0).getValueType(); + unsigned InBits = InVT.getSizeInBits(); + APInt NewBits = APInt::getHighBitsSet(BitWidth, BitWidth - InBits) & Mask; + APInt InMask = Mask; + InMask.trunc(InBits); + KnownZero.trunc(InBits); + KnownOne.trunc(InBits); + ComputeMaskedBits(Op.getOperand(0), InMask, KnownZero, KnownOne, Depth+1); + KnownZero.zext(BitWidth); + KnownOne.zext(BitWidth); + KnownZero |= NewBits; + return; + } + case ISD::SIGN_EXTEND: { + EVT InVT = Op.getOperand(0).getValueType(); + unsigned InBits = InVT.getSizeInBits(); + APInt InSignBit = APInt::getSignBit(InBits); + APInt NewBits = APInt::getHighBitsSet(BitWidth, BitWidth - InBits) & Mask; + APInt InMask = Mask; + InMask.trunc(InBits); + + // If any of the sign extended bits are demanded, we know that the sign + // bit is demanded. Temporarily set this bit in the mask for our callee. + if (NewBits.getBoolValue()) + InMask |= InSignBit; + + KnownZero.trunc(InBits); + KnownOne.trunc(InBits); + ComputeMaskedBits(Op.getOperand(0), InMask, KnownZero, KnownOne, Depth+1); + + // Note if the sign bit is known to be zero or one. + bool SignBitKnownZero = KnownZero.isNegative(); + bool SignBitKnownOne = KnownOne.isNegative(); + assert(!(SignBitKnownZero && SignBitKnownOne) && + "Sign bit can't be known to be both zero and one!"); + + // If the sign bit wasn't actually demanded by our caller, we don't + // want it set in the KnownZero and KnownOne result values. Reset the + // mask and reapply it to the result values. + InMask = Mask; + InMask.trunc(InBits); + KnownZero &= InMask; + KnownOne &= InMask; + + KnownZero.zext(BitWidth); + KnownOne.zext(BitWidth); + + // If the sign bit is known zero or one, the top bits match. + if (SignBitKnownZero) + KnownZero |= NewBits; + else if (SignBitKnownOne) + KnownOne |= NewBits; + return; + } + case ISD::ANY_EXTEND: { + EVT InVT = Op.getOperand(0).getValueType(); + unsigned InBits = InVT.getSizeInBits(); + APInt InMask = Mask; + InMask.trunc(InBits); + KnownZero.trunc(InBits); + KnownOne.trunc(InBits); + ComputeMaskedBits(Op.getOperand(0), InMask, KnownZero, KnownOne, Depth+1); + KnownZero.zext(BitWidth); + KnownOne.zext(BitWidth); + return; + } + case ISD::TRUNCATE: { + EVT InVT = Op.getOperand(0).getValueType(); + unsigned InBits = InVT.getSizeInBits(); + APInt InMask = Mask; + InMask.zext(InBits); + KnownZero.zext(InBits); + KnownOne.zext(InBits); + ComputeMaskedBits(Op.getOperand(0), InMask, KnownZero, KnownOne, Depth+1); + assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?"); + KnownZero.trunc(BitWidth); + KnownOne.trunc(BitWidth); + break; + } + case ISD::AssertZext: { + EVT VT = cast(Op.getOperand(1))->getVT(); + APInt InMask = APInt::getLowBitsSet(BitWidth, VT.getSizeInBits()); + ComputeMaskedBits(Op.getOperand(0), Mask & InMask, KnownZero, + KnownOne, Depth+1); + KnownZero |= (~InMask) & Mask; + return; + } + case ISD::FGETSIGN: + // All bits are zero except the low bit. + KnownZero = APInt::getHighBitsSet(BitWidth, BitWidth - 1); + return; + + case ISD::SUB: { + if (ConstantSDNode *CLHS = dyn_cast(Op.getOperand(0))) { + // We know that the top bits of C-X are clear if X contains less bits + // than C (i.e. no wrap-around can happen). For example, 20-X is + // positive if we can prove that X is >= 0 and < 16. + if (CLHS->getAPIntValue().isNonNegative()) { + unsigned NLZ = (CLHS->getAPIntValue()+1).countLeadingZeros(); + // NLZ can't be BitWidth with no sign bit + APInt MaskV = APInt::getHighBitsSet(BitWidth, NLZ+1); + ComputeMaskedBits(Op.getOperand(1), MaskV, KnownZero2, KnownOne2, + Depth+1); + + // If all of the MaskV bits are known to be zero, then we know the + // output top bits are zero, because we now know that the output is + // from [0-C]. + if ((KnownZero2 & MaskV) == MaskV) { + unsigned NLZ2 = CLHS->getAPIntValue().countLeadingZeros(); + // Top bits known zero. + KnownZero = APInt::getHighBitsSet(BitWidth, NLZ2) & Mask; + } + } + } + } + // fall through + case ISD::ADD: { + // Output known-0 bits are known if clear or set in both the low clear bits + // common to both LHS & RHS. For example, 8+(X<<3) is known to have the + // low 3 bits clear. + APInt Mask2 = APInt::getLowBitsSet(BitWidth, Mask.countTrailingOnes()); + ComputeMaskedBits(Op.getOperand(0), Mask2, KnownZero2, KnownOne2, Depth+1); + assert((KnownZero2 & KnownOne2) == 0 && "Bits known to be one AND zero?"); + unsigned KnownZeroOut = KnownZero2.countTrailingOnes(); + + ComputeMaskedBits(Op.getOperand(1), Mask2, KnownZero2, KnownOne2, Depth+1); + assert((KnownZero2 & KnownOne2) == 0 && "Bits known to be one AND zero?"); + KnownZeroOut = std::min(KnownZeroOut, + KnownZero2.countTrailingOnes()); + + KnownZero |= APInt::getLowBitsSet(BitWidth, KnownZeroOut); + return; + } + case ISD::SREM: + if (ConstantSDNode *Rem = dyn_cast(Op.getOperand(1))) { + const APInt &RA = Rem->getAPIntValue(); + if (RA.isPowerOf2() || (-RA).isPowerOf2()) { + APInt LowBits = RA.isStrictlyPositive() ? (RA - 1) : ~RA; + APInt Mask2 = LowBits | APInt::getSignBit(BitWidth); + ComputeMaskedBits(Op.getOperand(0), Mask2,KnownZero2,KnownOne2,Depth+1); + + // If the sign bit of the first operand is zero, the sign bit of + // the result is zero. If the first operand has no one bits below + // the second operand's single 1 bit, its sign will be zero. + if (KnownZero2[BitWidth-1] || ((KnownZero2 & LowBits) == LowBits)) + KnownZero2 |= ~LowBits; + + KnownZero |= KnownZero2 & Mask; + + assert((KnownZero & KnownOne) == 0&&"Bits known to be one AND zero?"); + } + } + return; + case ISD::UREM: { + if (ConstantSDNode *Rem = dyn_cast(Op.getOperand(1))) { + const APInt &RA = Rem->getAPIntValue(); + if (RA.isPowerOf2()) { + APInt LowBits = (RA - 1); + APInt Mask2 = LowBits & Mask; + KnownZero |= ~LowBits & Mask; + ComputeMaskedBits(Op.getOperand(0), Mask2, KnownZero, KnownOne,Depth+1); + assert((KnownZero & KnownOne) == 0&&"Bits known to be one AND zero?"); + break; + } + } + + // Since the result is less than or equal to either operand, any leading + // zero bits in either operand must also exist in the result. + APInt AllOnes = APInt::getAllOnesValue(BitWidth); + ComputeMaskedBits(Op.getOperand(0), AllOnes, KnownZero, KnownOne, + Depth+1); + ComputeMaskedBits(Op.getOperand(1), AllOnes, KnownZero2, KnownOne2, + Depth+1); + + uint32_t Leaders = std::max(KnownZero.countLeadingOnes(), + KnownZero2.countLeadingOnes()); + KnownOne.clear(); + KnownZero = APInt::getHighBitsSet(BitWidth, Leaders) & Mask; + return; + } + default: + // Allow the target to implement this method for its nodes. + if (Op.getOpcode() >= ISD::BUILTIN_OP_END) { + case ISD::INTRINSIC_WO_CHAIN: + case ISD::INTRINSIC_W_CHAIN: + case ISD::INTRINSIC_VOID: + TLI.computeMaskedBitsForTargetNode(Op, Mask, KnownZero, KnownOne, *this, + Depth); + } + return; + } +} + +/// ComputeNumSignBits - Return the number of times the sign bit of the +/// register is replicated into the other bits. We know that at least 1 bit +/// is always equal to the sign bit (itself), but other cases can give us +/// information. For example, immediately after an "SRA X, 2", we know that +/// the top 3 bits are all equal to each other, so we return 3. +unsigned SelectionDAG::ComputeNumSignBits(SDValue Op, unsigned Depth) const{ + EVT VT = Op.getValueType(); + assert(VT.isInteger() && "Invalid VT!"); + unsigned VTBits = VT.getSizeInBits(); + unsigned Tmp, Tmp2; + unsigned FirstAnswer = 1; + + if (Depth == 6) + return 1; // Limit search depth. + + switch (Op.getOpcode()) { + default: break; + case ISD::AssertSext: + Tmp = cast(Op.getOperand(1))->getVT().getSizeInBits(); + return VTBits-Tmp+1; + case ISD::AssertZext: + Tmp = cast(Op.getOperand(1))->getVT().getSizeInBits(); + return VTBits-Tmp; + + case ISD::Constant: { + const APInt &Val = cast(Op)->getAPIntValue(); + // If negative, return # leading ones. + if (Val.isNegative()) + return Val.countLeadingOnes(); + + // Return # leading zeros. + return Val.countLeadingZeros(); + } + + case ISD::SIGN_EXTEND: + Tmp = VTBits-Op.getOperand(0).getValueType().getSizeInBits(); + return ComputeNumSignBits(Op.getOperand(0), Depth+1) + Tmp; + + case ISD::SIGN_EXTEND_INREG: + // Max of the input and what this extends. + Tmp = cast(Op.getOperand(1))->getVT().getSizeInBits(); + Tmp = VTBits-Tmp+1; + + Tmp2 = ComputeNumSignBits(Op.getOperand(0), Depth+1); + return std::max(Tmp, Tmp2); + + case ISD::SRA: + Tmp = ComputeNumSignBits(Op.getOperand(0), Depth+1); + // SRA X, C -> adds C sign bits. + if (ConstantSDNode *C = dyn_cast(Op.getOperand(1))) { + Tmp += C->getZExtValue(); + if (Tmp > VTBits) Tmp = VTBits; + } + return Tmp; + case ISD::SHL: + if (ConstantSDNode *C = dyn_cast(Op.getOperand(1))) { + // shl destroys sign bits. + Tmp = ComputeNumSignBits(Op.getOperand(0), Depth+1); + if (C->getZExtValue() >= VTBits || // Bad shift. + C->getZExtValue() >= Tmp) break; // Shifted all sign bits out. + return Tmp - C->getZExtValue(); + } + break; + case ISD::AND: + case ISD::OR: + case ISD::XOR: // NOT is handled here. + // Logical binary ops preserve the number of sign bits at the worst. + Tmp = ComputeNumSignBits(Op.getOperand(0), Depth+1); + if (Tmp != 1) { + Tmp2 = ComputeNumSignBits(Op.getOperand(1), Depth+1); + FirstAnswer = std::min(Tmp, Tmp2); + // We computed what we know about the sign bits as our first + // answer. Now proceed to the generic code that uses + // ComputeMaskedBits, and pick whichever answer is better. + } + break; + + case ISD::SELECT: + Tmp = ComputeNumSignBits(Op.getOperand(1), Depth+1); + if (Tmp == 1) return 1; // Early out. + Tmp2 = ComputeNumSignBits(Op.getOperand(2), Depth+1); + return std::min(Tmp, Tmp2); + + case ISD::SADDO: + case ISD::UADDO: + case ISD::SSUBO: + case ISD::USUBO: + case ISD::SMULO: + case ISD::UMULO: + if (Op.getResNo() != 1) + break; + // The boolean result conforms to getBooleanContents. Fall through. + case ISD::SETCC: + // If setcc returns 0/-1, all bits are sign bits. + if (TLI.getBooleanContents() == + TargetLowering::ZeroOrNegativeOneBooleanContent) + return VTBits; + break; + case ISD::ROTL: + case ISD::ROTR: + if (ConstantSDNode *C = dyn_cast(Op.getOperand(1))) { + unsigned RotAmt = C->getZExtValue() & (VTBits-1); + + // Handle rotate right by N like a rotate left by 32-N. + if (Op.getOpcode() == ISD::ROTR) + RotAmt = (VTBits-RotAmt) & (VTBits-1); + + // If we aren't rotating out all of the known-in sign bits, return the + // number that are left. This handles rotl(sext(x), 1) for example. + Tmp = ComputeNumSignBits(Op.getOperand(0), Depth+1); + if (Tmp > RotAmt+1) return Tmp-RotAmt; + } + break; + case ISD::ADD: + // Add can have at most one carry bit. Thus we know that the output + // is, at worst, one more bit than the inputs. + Tmp = ComputeNumSignBits(Op.getOperand(0), Depth+1); + if (Tmp == 1) return 1; // Early out. + + // Special case decrementing a value (ADD X, -1): + if (ConstantSDNode *CRHS = dyn_cast(Op.getOperand(1))) + if (CRHS->isAllOnesValue()) { + APInt KnownZero, KnownOne; + APInt Mask = APInt::getAllOnesValue(VTBits); + ComputeMaskedBits(Op.getOperand(0), Mask, KnownZero, KnownOne, Depth+1); + + // If the input is known to be 0 or 1, the output is 0/-1, which is all + // sign bits set. + if ((KnownZero | APInt(VTBits, 1)) == Mask) + return VTBits; + + // If we are subtracting one from a positive number, there is no carry + // out of the result. + if (KnownZero.isNegative()) + return Tmp; + } + + Tmp2 = ComputeNumSignBits(Op.getOperand(1), Depth+1); + if (Tmp2 == 1) return 1; + return std::min(Tmp, Tmp2)-1; + break; + + case ISD::SUB: + Tmp2 = ComputeNumSignBits(Op.getOperand(1), Depth+1); + if (Tmp2 == 1) return 1; + + // Handle NEG. + if (ConstantSDNode *CLHS = dyn_cast(Op.getOperand(0))) + if (CLHS->isNullValue()) { + APInt KnownZero, KnownOne; + APInt Mask = APInt::getAllOnesValue(VTBits); + ComputeMaskedBits(Op.getOperand(1), Mask, KnownZero, KnownOne, Depth+1); + // If the input is known to be 0 or 1, the output is 0/-1, which is all + // sign bits set. + if ((KnownZero | APInt(VTBits, 1)) == Mask) + return VTBits; + + // If the input is known to be positive (the sign bit is known clear), + // the output of the NEG has the same number of sign bits as the input. + if (KnownZero.isNegative()) + return Tmp2; + + // Otherwise, we treat this like a SUB. + } + + // Sub can have at most one carry bit. Thus we know that the output + // is, at worst, one more bit than the inputs. + Tmp = ComputeNumSignBits(Op.getOperand(0), Depth+1); + if (Tmp == 1) return 1; // Early out. + return std::min(Tmp, Tmp2)-1; + break; + case ISD::TRUNCATE: + // FIXME: it's tricky to do anything useful for this, but it is an important + // case for targets like X86. + break; + } + + // Handle LOADX separately here. EXTLOAD case will fallthrough. + if (Op.getOpcode() == ISD::LOAD) { + LoadSDNode *LD = cast(Op); + unsigned ExtType = LD->getExtensionType(); + switch (ExtType) { + default: break; + case ISD::SEXTLOAD: // '17' bits known + Tmp = LD->getMemoryVT().getSizeInBits(); + return VTBits-Tmp+1; + case ISD::ZEXTLOAD: // '16' bits known + Tmp = LD->getMemoryVT().getSizeInBits(); + return VTBits-Tmp; + } + } + + // Allow the target to implement this method for its nodes. + if (Op.getOpcode() >= ISD::BUILTIN_OP_END || + Op.getOpcode() == ISD::INTRINSIC_WO_CHAIN || + Op.getOpcode() == ISD::INTRINSIC_W_CHAIN || + Op.getOpcode() == ISD::INTRINSIC_VOID) { + unsigned NumBits = TLI.ComputeNumSignBitsForTargetNode(Op, Depth); + if (NumBits > 1) FirstAnswer = std::max(FirstAnswer, NumBits); + } + + // Finally, if we can prove that the top bits of the result are 0's or 1's, + // use this information. + APInt KnownZero, KnownOne; + APInt Mask = APInt::getAllOnesValue(VTBits); + ComputeMaskedBits(Op, Mask, KnownZero, KnownOne, Depth); + + if (KnownZero.isNegative()) { // sign bit is 0 + Mask = KnownZero; + } else if (KnownOne.isNegative()) { // sign bit is 1; + Mask = KnownOne; + } else { + // Nothing known. + return FirstAnswer; + } + + // Okay, we know that the sign bit in Mask is set. Use CLZ to determine + // the number of identical bits in the top of the input value. + Mask = ~Mask; + Mask <<= Mask.getBitWidth()-VTBits; + // Return # leading zeros. We use 'min' here in case Val was zero before + // shifting. We don't want to return '64' as for an i32 "0". + return std::max(FirstAnswer, std::min(VTBits, Mask.countLeadingZeros())); +} + +bool SelectionDAG::isKnownNeverNaN(SDValue Op) const { + // If we're told that NaNs won't happen, assume they won't. + if (FiniteOnlyFPMath()) + return true; + + // If the value is a constant, we can obviously see if it is a NaN or not. + if (const ConstantFPSDNode *C = dyn_cast(Op)) + return !C->getValueAPF().isNaN(); + + // TODO: Recognize more cases here. + + return false; +} + +bool SelectionDAG::isVerifiedDebugInfoDesc(SDValue Op) const { + GlobalAddressSDNode *GA = dyn_cast(Op); + if (!GA) return false; + if (GA->getOffset() != 0) return false; + GlobalVariable *GV = dyn_cast(GA->getGlobal()); + if (!GV) return false; + MachineModuleInfo *MMI = getMachineModuleInfo(); + return MMI && MMI->hasDebugInfo(); +} + + +/// getShuffleScalarElt - Returns the scalar element that will make up the ith +/// element of the result of the vector shuffle. +SDValue SelectionDAG::getShuffleScalarElt(const ShuffleVectorSDNode *N, + unsigned i) { + EVT VT = N->getValueType(0); + DebugLoc dl = N->getDebugLoc(); + if (N->getMaskElt(i) < 0) + return getUNDEF(VT.getVectorElementType()); + unsigned Index = N->getMaskElt(i); + unsigned NumElems = VT.getVectorNumElements(); + SDValue V = (Index < NumElems) ? N->getOperand(0) : N->getOperand(1); + Index %= NumElems; + + if (V.getOpcode() == ISD::BIT_CONVERT) { + V = V.getOperand(0); + EVT VVT = V.getValueType(); + if (!VVT.isVector() || VVT.getVectorNumElements() != (unsigned)NumElems) + return SDValue(); + } + if (V.getOpcode() == ISD::SCALAR_TO_VECTOR) + return (Index == 0) ? V.getOperand(0) + : getUNDEF(VT.getVectorElementType()); + if (V.getOpcode() == ISD::BUILD_VECTOR) + return V.getOperand(Index); + if (const ShuffleVectorSDNode *SVN = dyn_cast(V)) + return getShuffleScalarElt(SVN, Index); + return SDValue(); +} + + +/// getNode - Gets or creates the specified node. +/// +SDValue SelectionDAG::getNode(unsigned Opcode, DebugLoc DL, EVT VT) { + FoldingSetNodeID ID; + AddNodeIDNode(ID, Opcode, getVTList(VT), 0, 0); + void *IP = 0; + if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) + return SDValue(E, 0); + SDNode *N = NodeAllocator.Allocate(); + new (N) SDNode(Opcode, DL, getVTList(VT)); + CSEMap.InsertNode(N, IP); + + AllNodes.push_back(N); +#ifndef NDEBUG + VerifyNode(N); +#endif + return SDValue(N, 0); +} + +SDValue SelectionDAG::getNode(unsigned Opcode, DebugLoc DL, + EVT VT, SDValue Operand) { + // Constant fold unary operations with an integer constant operand. + if (ConstantSDNode *C = dyn_cast(Operand.getNode())) { + const APInt &Val = C->getAPIntValue(); + unsigned BitWidth = VT.getSizeInBits(); + switch (Opcode) { + default: break; + case ISD::SIGN_EXTEND: + return getConstant(APInt(Val).sextOrTrunc(BitWidth), VT); + case ISD::ANY_EXTEND: + case ISD::ZERO_EXTEND: + case ISD::TRUNCATE: + return getConstant(APInt(Val).zextOrTrunc(BitWidth), VT); + case ISD::UINT_TO_FP: + case ISD::SINT_TO_FP: { + const uint64_t zero[] = {0, 0}; + // No compile time operations on this type. + if (VT==MVT::ppcf128) + break; + APFloat apf = APFloat(APInt(BitWidth, 2, zero)); + (void)apf.convertFromAPInt(Val, + Opcode==ISD::SINT_TO_FP, + APFloat::rmNearestTiesToEven); + return getConstantFP(apf, VT); + } + case ISD::BIT_CONVERT: + if (VT == MVT::f32 && C->getValueType(0) == MVT::i32) + return getConstantFP(Val.bitsToFloat(), VT); + else if (VT == MVT::f64 && C->getValueType(0) == MVT::i64) + return getConstantFP(Val.bitsToDouble(), VT); + break; + case ISD::BSWAP: + return getConstant(Val.byteSwap(), VT); + case ISD::CTPOP: + return getConstant(Val.countPopulation(), VT); + case ISD::CTLZ: + return getConstant(Val.countLeadingZeros(), VT); + case ISD::CTTZ: + return getConstant(Val.countTrailingZeros(), VT); + } + } + + // Constant fold unary operations with a floating point constant operand. + if (ConstantFPSDNode *C = dyn_cast(Operand.getNode())) { + APFloat V = C->getValueAPF(); // make copy + if (VT != MVT::ppcf128 && Operand.getValueType() != MVT::ppcf128) { + switch (Opcode) { + case ISD::FNEG: + V.changeSign(); + return getConstantFP(V, VT); + case ISD::FABS: + V.clearSign(); + return getConstantFP(V, VT); + case ISD::FP_ROUND: + case ISD::FP_EXTEND: { + bool ignored; + // This can return overflow, underflow, or inexact; we don't care. + // FIXME need to be more flexible about rounding mode. + (void)V.convert(*EVTToAPFloatSemantics(VT), + APFloat::rmNearestTiesToEven, &ignored); + return getConstantFP(V, VT); + } + case ISD::FP_TO_SINT: + case ISD::FP_TO_UINT: { + integerPart x[2]; + bool ignored; + assert(integerPartWidth >= 64); + // FIXME need to be more flexible about rounding mode. + APFloat::opStatus s = V.convertToInteger(x, VT.getSizeInBits(), + Opcode==ISD::FP_TO_SINT, + APFloat::rmTowardZero, &ignored); + if (s==APFloat::opInvalidOp) // inexact is OK, in fact usual + break; + APInt api(VT.getSizeInBits(), 2, x); + return getConstant(api, VT); + } + case ISD::BIT_CONVERT: + if (VT == MVT::i32 && C->getValueType(0) == MVT::f32) + return getConstant((uint32_t)V.bitcastToAPInt().getZExtValue(), VT); + else if (VT == MVT::i64 && C->getValueType(0) == MVT::f64) + return getConstant(V.bitcastToAPInt().getZExtValue(), VT); + break; + } + } + } + + unsigned OpOpcode = Operand.getNode()->getOpcode(); + switch (Opcode) { + case ISD::TokenFactor: + case ISD::MERGE_VALUES: + case ISD::CONCAT_VECTORS: + return Operand; // Factor, merge or concat of one node? No need. + case ISD::FP_ROUND: llvm_unreachable("Invalid method to make FP_ROUND node"); + case ISD::FP_EXTEND: + assert(VT.isFloatingPoint() && + Operand.getValueType().isFloatingPoint() && "Invalid FP cast!"); + if (Operand.getValueType() == VT) return Operand; // noop conversion. + if (Operand.getOpcode() == ISD::UNDEF) + return getUNDEF(VT); + break; + case ISD::SIGN_EXTEND: + assert(VT.isInteger() && Operand.getValueType().isInteger() && + "Invalid SIGN_EXTEND!"); + if (Operand.getValueType() == VT) return Operand; // noop extension + assert(Operand.getValueType().bitsLT(VT) + && "Invalid sext node, dst < src!"); + if (OpOpcode == ISD::SIGN_EXTEND || OpOpcode == ISD::ZERO_EXTEND) + return getNode(OpOpcode, DL, VT, Operand.getNode()->getOperand(0)); + break; + case ISD::ZERO_EXTEND: + assert(VT.isInteger() && Operand.getValueType().isInteger() && + "Invalid ZERO_EXTEND!"); + if (Operand.getValueType() == VT) return Operand; // noop extension + assert(Operand.getValueType().bitsLT(VT) + && "Invalid zext node, dst < src!"); + if (OpOpcode == ISD::ZERO_EXTEND) // (zext (zext x)) -> (zext x) + return getNode(ISD::ZERO_EXTEND, DL, VT, + Operand.getNode()->getOperand(0)); + break; + case ISD::ANY_EXTEND: + assert(VT.isInteger() && Operand.getValueType().isInteger() && + "Invalid ANY_EXTEND!"); + if (Operand.getValueType() == VT) return Operand; // noop extension + assert(Operand.getValueType().bitsLT(VT) + && "Invalid anyext node, dst < src!"); + if (OpOpcode == ISD::ZERO_EXTEND || OpOpcode == ISD::SIGN_EXTEND) + // (ext (zext x)) -> (zext x) and (ext (sext x)) -> (sext x) + return getNode(OpOpcode, DL, VT, Operand.getNode()->getOperand(0)); + break; + case ISD::TRUNCATE: + assert(VT.isInteger() && Operand.getValueType().isInteger() && + "Invalid TRUNCATE!"); + if (Operand.getValueType() == VT) return Operand; // noop truncate + assert(Operand.getValueType().bitsGT(VT) + && "Invalid truncate node, src < dst!"); + if (OpOpcode == ISD::TRUNCATE) + return getNode(ISD::TRUNCATE, DL, VT, Operand.getNode()->getOperand(0)); + else if (OpOpcode == ISD::ZERO_EXTEND || OpOpcode == ISD::SIGN_EXTEND || + OpOpcode == ISD::ANY_EXTEND) { + // If the source is smaller than the dest, we still need an extend. + if (Operand.getNode()->getOperand(0).getValueType().bitsLT(VT)) + return getNode(OpOpcode, DL, VT, Operand.getNode()->getOperand(0)); + else if (Operand.getNode()->getOperand(0).getValueType().bitsGT(VT)) + return getNode(ISD::TRUNCATE, DL, VT, Operand.getNode()->getOperand(0)); + else + return Operand.getNode()->getOperand(0); + } + break; + case ISD::BIT_CONVERT: + // Basic sanity checking. + assert(VT.getSizeInBits() == Operand.getValueType().getSizeInBits() + && "Cannot BIT_CONVERT between types of different sizes!"); + if (VT == Operand.getValueType()) return Operand; // noop conversion. + if (OpOpcode == ISD::BIT_CONVERT) // bitconv(bitconv(x)) -> bitconv(x) + return getNode(ISD::BIT_CONVERT, DL, VT, Operand.getOperand(0)); + if (OpOpcode == ISD::UNDEF) + return getUNDEF(VT); + break; + case ISD::SCALAR_TO_VECTOR: + assert(VT.isVector() && !Operand.getValueType().isVector() && + (VT.getVectorElementType() == Operand.getValueType() || + (VT.getVectorElementType().isInteger() && + Operand.getValueType().isInteger() && + VT.getVectorElementType().bitsLE(Operand.getValueType()))) && + "Illegal SCALAR_TO_VECTOR node!"); + if (OpOpcode == ISD::UNDEF) + return getUNDEF(VT); + // scalar_to_vector(extract_vector_elt V, 0) -> V, top bits are undefined. + if (OpOpcode == ISD::EXTRACT_VECTOR_ELT && + isa(Operand.getOperand(1)) && + Operand.getConstantOperandVal(1) == 0 && + Operand.getOperand(0).getValueType() == VT) + return Operand.getOperand(0); + break; + case ISD::FNEG: + // -(X-Y) -> (Y-X) is unsafe because when X==Y, -0.0 != +0.0 + if (UnsafeFPMath && OpOpcode == ISD::FSUB) + return getNode(ISD::FSUB, DL, VT, Operand.getNode()->getOperand(1), + Operand.getNode()->getOperand(0)); + if (OpOpcode == ISD::FNEG) // --X -> X + return Operand.getNode()->getOperand(0); + break; + case ISD::FABS: + if (OpOpcode == ISD::FNEG) // abs(-X) -> abs(X) + return getNode(ISD::FABS, DL, VT, Operand.getNode()->getOperand(0)); + break; + } + + SDNode *N; + SDVTList VTs = getVTList(VT); + if (VT != MVT::Flag) { // Don't CSE flag producing nodes + FoldingSetNodeID ID; + SDValue Ops[1] = { Operand }; + AddNodeIDNode(ID, Opcode, VTs, Ops, 1); + void *IP = 0; + if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) + return SDValue(E, 0); + N = NodeAllocator.Allocate(); + new (N) UnarySDNode(Opcode, DL, VTs, Operand); + CSEMap.InsertNode(N, IP); + } else { + N = NodeAllocator.Allocate(); + new (N) UnarySDNode(Opcode, DL, VTs, Operand); + } + + AllNodes.push_back(N); +#ifndef NDEBUG + VerifyNode(N); +#endif + return SDValue(N, 0); +} + +SDValue SelectionDAG::FoldConstantArithmetic(unsigned Opcode, + EVT VT, + ConstantSDNode *Cst1, + ConstantSDNode *Cst2) { + const APInt &C1 = Cst1->getAPIntValue(), &C2 = Cst2->getAPIntValue(); + + switch (Opcode) { + case ISD::ADD: return getConstant(C1 + C2, VT); + case ISD::SUB: return getConstant(C1 - C2, VT); + case ISD::MUL: return getConstant(C1 * C2, VT); + case ISD::UDIV: + if (C2.getBoolValue()) return getConstant(C1.udiv(C2), VT); + break; + case ISD::UREM: + if (C2.getBoolValue()) return getConstant(C1.urem(C2), VT); + break; + case ISD::SDIV: + if (C2.getBoolValue()) return getConstant(C1.sdiv(C2), VT); + break; + case ISD::SREM: + if (C2.getBoolValue()) return getConstant(C1.srem(C2), VT); + break; + case ISD::AND: return getConstant(C1 & C2, VT); + case ISD::OR: return getConstant(C1 | C2, VT); + case ISD::XOR: return getConstant(C1 ^ C2, VT); + case ISD::SHL: return getConstant(C1 << C2, VT); + case ISD::SRL: return getConstant(C1.lshr(C2), VT); + case ISD::SRA: return getConstant(C1.ashr(C2), VT); + case ISD::ROTL: return getConstant(C1.rotl(C2), VT); + case ISD::ROTR: return getConstant(C1.rotr(C2), VT); + default: break; + } + + return SDValue(); +} + +SDValue SelectionDAG::getNode(unsigned Opcode, DebugLoc DL, EVT VT, + SDValue N1, SDValue N2) { + ConstantSDNode *N1C = dyn_cast(N1.getNode()); + ConstantSDNode *N2C = dyn_cast(N2.getNode()); + switch (Opcode) { + default: break; + case ISD::TokenFactor: + assert(VT == MVT::Other && N1.getValueType() == MVT::Other && + N2.getValueType() == MVT::Other && "Invalid token factor!"); + // Fold trivial token factors. + if (N1.getOpcode() == ISD::EntryToken) return N2; + if (N2.getOpcode() == ISD::EntryToken) return N1; + if (N1 == N2) return N1; + break; + case ISD::CONCAT_VECTORS: + // A CONCAT_VECTOR with all operands BUILD_VECTOR can be simplified to + // one big BUILD_VECTOR. + if (N1.getOpcode() == ISD::BUILD_VECTOR && + N2.getOpcode() == ISD::BUILD_VECTOR) { + SmallVector Elts(N1.getNode()->op_begin(), N1.getNode()->op_end()); + Elts.insert(Elts.end(), N2.getNode()->op_begin(), N2.getNode()->op_end()); + return getNode(ISD::BUILD_VECTOR, DL, VT, &Elts[0], Elts.size()); + } + break; + case ISD::AND: + assert(VT.isInteger() && N1.getValueType() == N2.getValueType() && + N1.getValueType() == VT && "Binary operator types must match!"); + // (X & 0) -> 0. This commonly occurs when legalizing i64 values, so it's + // worth handling here. + if (N2C && N2C->isNullValue()) + return N2; + if (N2C && N2C->isAllOnesValue()) // X & -1 -> X + return N1; + break; + case ISD::OR: + case ISD::XOR: + case ISD::ADD: + case ISD::SUB: + assert(VT.isInteger() && N1.getValueType() == N2.getValueType() && + N1.getValueType() == VT && "Binary operator types must match!"); + // (X ^|+- 0) -> X. This commonly occurs when legalizing i64 values, so + // it's worth handling here. + if (N2C && N2C->isNullValue()) + return N1; + break; + case ISD::UDIV: + case ISD::UREM: + case ISD::MULHU: + case ISD::MULHS: + case ISD::MUL: + case ISD::SDIV: + case ISD::SREM: + assert(VT.isInteger() && "This operator does not apply to FP types!"); + // fall through + case ISD::FADD: + case ISD::FSUB: + case ISD::FMUL: + case ISD::FDIV: + case ISD::FREM: + if (UnsafeFPMath) { + if (Opcode == ISD::FADD) { + // 0+x --> x + if (ConstantFPSDNode *CFP = dyn_cast(N1)) + if (CFP->getValueAPF().isZero()) + return N2; + // x+0 --> x + if (ConstantFPSDNode *CFP = dyn_cast(N2)) + if (CFP->getValueAPF().isZero()) + return N1; + } else if (Opcode == ISD::FSUB) { + // x-0 --> x + if (ConstantFPSDNode *CFP = dyn_cast(N2)) + if (CFP->getValueAPF().isZero()) + return N1; + } + } + assert(N1.getValueType() == N2.getValueType() && + N1.getValueType() == VT && "Binary operator types must match!"); + break; + case ISD::FCOPYSIGN: // N1 and result must match. N1/N2 need not match. + assert(N1.getValueType() == VT && + N1.getValueType().isFloatingPoint() && + N2.getValueType().isFloatingPoint() && + "Invalid FCOPYSIGN!"); + break; + case ISD::SHL: + case ISD::SRA: + case ISD::SRL: + case ISD::ROTL: + case ISD::ROTR: + assert(VT == N1.getValueType() && + "Shift operators return type must be the same as their first arg"); + assert(VT.isInteger() && N2.getValueType().isInteger() && + "Shifts only work on integers"); + + // Always fold shifts of i1 values so the code generator doesn't need to + // handle them. Since we know the size of the shift has to be less than the + // size of the value, the shift/rotate count is guaranteed to be zero. + if (VT == MVT::i1) + return N1; + break; + case ISD::FP_ROUND_INREG: { + EVT EVT = cast(N2)->getVT(); + assert(VT == N1.getValueType() && "Not an inreg round!"); + assert(VT.isFloatingPoint() && EVT.isFloatingPoint() && + "Cannot FP_ROUND_INREG integer types"); + assert(EVT.bitsLE(VT) && "Not rounding down!"); + if (cast(N2)->getVT() == VT) return N1; // Not actually rounding. + break; + } + case ISD::FP_ROUND: + assert(VT.isFloatingPoint() && + N1.getValueType().isFloatingPoint() && + VT.bitsLE(N1.getValueType()) && + isa(N2) && "Invalid FP_ROUND!"); + if (N1.getValueType() == VT) return N1; // noop conversion. + break; + case ISD::AssertSext: + case ISD::AssertZext: { + EVT EVT = cast(N2)->getVT(); + assert(VT == N1.getValueType() && "Not an inreg extend!"); + assert(VT.isInteger() && EVT.isInteger() && + "Cannot *_EXTEND_INREG FP types"); + assert(EVT.bitsLE(VT) && "Not extending!"); + if (VT == EVT) return N1; // noop assertion. + break; + } + case ISD::SIGN_EXTEND_INREG: { + EVT EVT = cast(N2)->getVT(); + assert(VT == N1.getValueType() && "Not an inreg extend!"); + assert(VT.isInteger() && EVT.isInteger() && + "Cannot *_EXTEND_INREG FP types"); + assert(EVT.bitsLE(VT) && "Not extending!"); + if (EVT == VT) return N1; // Not actually extending + + if (N1C) { + APInt Val = N1C->getAPIntValue(); + unsigned FromBits = cast(N2)->getVT().getSizeInBits(); + Val <<= Val.getBitWidth()-FromBits; + Val = Val.ashr(Val.getBitWidth()-FromBits); + return getConstant(Val, VT); + } + break; + } + case ISD::EXTRACT_VECTOR_ELT: + // EXTRACT_VECTOR_ELT of an UNDEF is an UNDEF. + if (N1.getOpcode() == ISD::UNDEF) + return getUNDEF(VT); + + // EXTRACT_VECTOR_ELT of CONCAT_VECTORS is often formed while lowering is + // expanding copies of large vectors from registers. + if (N2C && + N1.getOpcode() == ISD::CONCAT_VECTORS && + N1.getNumOperands() > 0) { + unsigned Factor = + N1.getOperand(0).getValueType().getVectorNumElements(); + return getNode(ISD::EXTRACT_VECTOR_ELT, DL, VT, + N1.getOperand(N2C->getZExtValue() / Factor), + getConstant(N2C->getZExtValue() % Factor, + N2.getValueType())); + } + + // EXTRACT_VECTOR_ELT of BUILD_VECTOR is often formed while lowering is + // expanding large vector constants. + if (N2C && N1.getOpcode() == ISD::BUILD_VECTOR) { + SDValue Elt = N1.getOperand(N2C->getZExtValue()); + EVT VEltTy = N1.getValueType().getVectorElementType(); + if (Elt.getValueType() != VEltTy) { + // If the vector element type is not legal, the BUILD_VECTOR operands + // are promoted and implicitly truncated. Make that explicit here. + Elt = getNode(ISD::TRUNCATE, DL, VEltTy, Elt); + } + if (VT != VEltTy) { + // If the vector element type is not legal, the EXTRACT_VECTOR_ELT + // result is implicitly extended. + Elt = getNode(ISD::ANY_EXTEND, DL, VT, Elt); + } + return Elt; + } + + // EXTRACT_VECTOR_ELT of INSERT_VECTOR_ELT is often formed when vector + // operations are lowered to scalars. + if (N1.getOpcode() == ISD::INSERT_VECTOR_ELT) { + // If the indices are the same, return the inserted element. + if (N1.getOperand(2) == N2) + return N1.getOperand(1); + // If the indices are known different, extract the element from + // the original vector. + else if (isa(N1.getOperand(2)) && + isa(N2)) + return getNode(ISD::EXTRACT_VECTOR_ELT, DL, VT, N1.getOperand(0), N2); + } + break; + case ISD::EXTRACT_ELEMENT: + assert(N2C && (unsigned)N2C->getZExtValue() < 2 && "Bad EXTRACT_ELEMENT!"); + assert(!N1.getValueType().isVector() && !VT.isVector() && + (N1.getValueType().isInteger() == VT.isInteger()) && + "Wrong types for EXTRACT_ELEMENT!"); + + // EXTRACT_ELEMENT of BUILD_PAIR is often formed while legalize is expanding + // 64-bit integers into 32-bit parts. Instead of building the extract of + // the BUILD_PAIR, only to have legalize rip it apart, just do it now. + if (N1.getOpcode() == ISD::BUILD_PAIR) + return N1.getOperand(N2C->getZExtValue()); + + // EXTRACT_ELEMENT of a constant int is also very common. + if (ConstantSDNode *C = dyn_cast(N1)) { + unsigned ElementSize = VT.getSizeInBits(); + unsigned Shift = ElementSize * N2C->getZExtValue(); + APInt ShiftedVal = C->getAPIntValue().lshr(Shift); + return getConstant(ShiftedVal.trunc(ElementSize), VT); + } + break; + case ISD::EXTRACT_SUBVECTOR: + if (N1.getValueType() == VT) // Trivial extraction. + return N1; + break; + } + + if (N1C) { + if (N2C) { + SDValue SV = FoldConstantArithmetic(Opcode, VT, N1C, N2C); + if (SV.getNode()) return SV; + } else { // Cannonicalize constant to RHS if commutative + if (isCommutativeBinOp(Opcode)) { + std::swap(N1C, N2C); + std::swap(N1, N2); + } + } + } + + // Constant fold FP operations. + ConstantFPSDNode *N1CFP = dyn_cast(N1.getNode()); + ConstantFPSDNode *N2CFP = dyn_cast(N2.getNode()); + if (N1CFP) { + if (!N2CFP && isCommutativeBinOp(Opcode)) { + // Cannonicalize constant to RHS if commutative + std::swap(N1CFP, N2CFP); + std::swap(N1, N2); + } else if (N2CFP && VT != MVT::ppcf128) { + APFloat V1 = N1CFP->getValueAPF(), V2 = N2CFP->getValueAPF(); + APFloat::opStatus s; + switch (Opcode) { + case ISD::FADD: + s = V1.add(V2, APFloat::rmNearestTiesToEven); + if (s != APFloat::opInvalidOp) + return getConstantFP(V1, VT); + break; + case ISD::FSUB: + s = V1.subtract(V2, APFloat::rmNearestTiesToEven); + if (s!=APFloat::opInvalidOp) + return getConstantFP(V1, VT); + break; + case ISD::FMUL: + s = V1.multiply(V2, APFloat::rmNearestTiesToEven); + if (s!=APFloat::opInvalidOp) + return getConstantFP(V1, VT); + break; + case ISD::FDIV: + s = V1.divide(V2, APFloat::rmNearestTiesToEven); + if (s!=APFloat::opInvalidOp && s!=APFloat::opDivByZero) + return getConstantFP(V1, VT); + break; + case ISD::FREM : + s = V1.mod(V2, APFloat::rmNearestTiesToEven); + if (s!=APFloat::opInvalidOp && s!=APFloat::opDivByZero) + return getConstantFP(V1, VT); + break; + case ISD::FCOPYSIGN: + V1.copySign(V2); + return getConstantFP(V1, VT); + default: break; + } + } + } + + // Canonicalize an UNDEF to the RHS, even over a constant. + if (N1.getOpcode() == ISD::UNDEF) { + if (isCommutativeBinOp(Opcode)) { + std::swap(N1, N2); + } else { + switch (Opcode) { + case ISD::FP_ROUND_INREG: + case ISD::SIGN_EXTEND_INREG: + case ISD::SUB: + case ISD::FSUB: + case ISD::FDIV: + case ISD::FREM: + case ISD::SRA: + return N1; // fold op(undef, arg2) -> undef + case ISD::UDIV: + case ISD::SDIV: + case ISD::UREM: + case ISD::SREM: + case ISD::SRL: + case ISD::SHL: + if (!VT.isVector()) + return getConstant(0, VT); // fold op(undef, arg2) -> 0 + // For vectors, we can't easily build an all zero vector, just return + // the LHS. + return N2; + } + } + } + + // Fold a bunch of operators when the RHS is undef. + if (N2.getOpcode() == ISD::UNDEF) { + switch (Opcode) { + case ISD::XOR: + if (N1.getOpcode() == ISD::UNDEF) + // Handle undef ^ undef -> 0 special case. This is a common + // idiom (misuse). + return getConstant(0, VT); + // fallthrough + case ISD::ADD: + case ISD::ADDC: + case ISD::ADDE: + case ISD::SUB: + case ISD::UDIV: + case ISD::SDIV: + case ISD::UREM: + case ISD::SREM: + return N2; // fold op(arg1, undef) -> undef + case ISD::FADD: + case ISD::FSUB: + case ISD::FMUL: + case ISD::FDIV: + case ISD::FREM: + if (UnsafeFPMath) + return N2; + break; + case ISD::MUL: + case ISD::AND: + case ISD::SRL: + case ISD::SHL: + if (!VT.isVector()) + return getConstant(0, VT); // fold op(arg1, undef) -> 0 + // For vectors, we can't easily build an all zero vector, just return + // the LHS. + return N1; + case ISD::OR: + if (!VT.isVector()) + return getConstant(APInt::getAllOnesValue(VT.getSizeInBits()), VT); + // For vectors, we can't easily build an all one vector, just return + // the LHS. + return N1; + case ISD::SRA: + return N1; + } + } + + // Memoize this node if possible. + SDNode *N; + SDVTList VTs = getVTList(VT); + if (VT != MVT::Flag) { + SDValue Ops[] = { N1, N2 }; + FoldingSetNodeID ID; + AddNodeIDNode(ID, Opcode, VTs, Ops, 2); + void *IP = 0; + if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) + return SDValue(E, 0); + N = NodeAllocator.Allocate(); + new (N) BinarySDNode(Opcode, DL, VTs, N1, N2); + CSEMap.InsertNode(N, IP); + } else { + N = NodeAllocator.Allocate(); + new (N) BinarySDNode(Opcode, DL, VTs, N1, N2); + } + + AllNodes.push_back(N); +#ifndef NDEBUG + VerifyNode(N); +#endif + return SDValue(N, 0); +} + +SDValue SelectionDAG::getNode(unsigned Opcode, DebugLoc DL, EVT VT, + SDValue N1, SDValue N2, SDValue N3) { + // Perform various simplifications. + ConstantSDNode *N1C = dyn_cast(N1.getNode()); + ConstantSDNode *N2C = dyn_cast(N2.getNode()); + switch (Opcode) { + case ISD::CONCAT_VECTORS: + // A CONCAT_VECTOR with all operands BUILD_VECTOR can be simplified to + // one big BUILD_VECTOR. + if (N1.getOpcode() == ISD::BUILD_VECTOR && + N2.getOpcode() == ISD::BUILD_VECTOR && + N3.getOpcode() == ISD::BUILD_VECTOR) { + SmallVector Elts(N1.getNode()->op_begin(), N1.getNode()->op_end()); + Elts.insert(Elts.end(), N2.getNode()->op_begin(), N2.getNode()->op_end()); + Elts.insert(Elts.end(), N3.getNode()->op_begin(), N3.getNode()->op_end()); + return getNode(ISD::BUILD_VECTOR, DL, VT, &Elts[0], Elts.size()); + } + break; + case ISD::SETCC: { + // Use FoldSetCC to simplify SETCC's. + SDValue Simp = FoldSetCC(VT, N1, N2, cast(N3)->get(), DL); + if (Simp.getNode()) return Simp; + break; + } + case ISD::SELECT: + if (N1C) { + if (N1C->getZExtValue()) + return N2; // select true, X, Y -> X + else + return N3; // select false, X, Y -> Y + } + + if (N2 == N3) return N2; // select C, X, X -> X + break; + case ISD::BRCOND: + if (N2C) { + if (N2C->getZExtValue()) // Unconditional branch + return getNode(ISD::BR, DL, MVT::Other, N1, N3); + else + return N1; // Never-taken branch + } + break; + case ISD::VECTOR_SHUFFLE: + llvm_unreachable("should use getVectorShuffle constructor!"); + break; + case ISD::BIT_CONVERT: + // Fold bit_convert nodes from a type to themselves. + if (N1.getValueType() == VT) + return N1; + break; + } + + // Memoize node if it doesn't produce a flag. + SDNode *N; + SDVTList VTs = getVTList(VT); + if (VT != MVT::Flag) { + SDValue Ops[] = { N1, N2, N3 }; + FoldingSetNodeID ID; + AddNodeIDNode(ID, Opcode, VTs, Ops, 3); + void *IP = 0; + if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) + return SDValue(E, 0); + N = NodeAllocator.Allocate(); + new (N) TernarySDNode(Opcode, DL, VTs, N1, N2, N3); + CSEMap.InsertNode(N, IP); + } else { + N = NodeAllocator.Allocate(); + new (N) TernarySDNode(Opcode, DL, VTs, N1, N2, N3); + } + AllNodes.push_back(N); +#ifndef NDEBUG + VerifyNode(N); +#endif + return SDValue(N, 0); +} + +SDValue SelectionDAG::getNode(unsigned Opcode, DebugLoc DL, EVT VT, + SDValue N1, SDValue N2, SDValue N3, + SDValue N4) { + SDValue Ops[] = { N1, N2, N3, N4 }; + return getNode(Opcode, DL, VT, Ops, 4); +} + +SDValue SelectionDAG::getNode(unsigned Opcode, DebugLoc DL, EVT VT, + SDValue N1, SDValue N2, SDValue N3, + SDValue N4, SDValue N5) { + SDValue Ops[] = { N1, N2, N3, N4, N5 }; + return getNode(Opcode, DL, VT, Ops, 5); +} + +/// getStackArgumentTokenFactor - Compute a TokenFactor to force all +/// the incoming stack arguments to be loaded from the stack. +SDValue SelectionDAG::getStackArgumentTokenFactor(SDValue Chain) { + SmallVector ArgChains; + + // Include the original chain at the beginning of the list. When this is + // used by target LowerCall hooks, this helps legalize find the + // CALLSEQ_BEGIN node. + ArgChains.push_back(Chain); + + // Add a chain value for each stack argument. + for (SDNode::use_iterator U = getEntryNode().getNode()->use_begin(), + UE = getEntryNode().getNode()->use_end(); U != UE; ++U) + if (LoadSDNode *L = dyn_cast(*U)) + if (FrameIndexSDNode *FI = dyn_cast(L->getBasePtr())) + if (FI->getIndex() < 0) + ArgChains.push_back(SDValue(L, 1)); + + // Build a tokenfactor for all the chains. + return getNode(ISD::TokenFactor, Chain.getDebugLoc(), MVT::Other, + &ArgChains[0], ArgChains.size()); +} + +/// getMemsetValue - Vectorized representation of the memset value +/// operand. +static SDValue getMemsetValue(SDValue Value, EVT VT, SelectionDAG &DAG, + DebugLoc dl) { + unsigned NumBits = VT.isVector() ? + VT.getVectorElementType().getSizeInBits() : VT.getSizeInBits(); + if (ConstantSDNode *C = dyn_cast(Value)) { + APInt Val = APInt(NumBits, C->getZExtValue() & 255); + unsigned Shift = 8; + for (unsigned i = NumBits; i > 8; i >>= 1) { + Val = (Val << Shift) | Val; + Shift <<= 1; + } + if (VT.isInteger()) + return DAG.getConstant(Val, VT); + return DAG.getConstantFP(APFloat(Val), VT); + } + + const TargetLowering &TLI = DAG.getTargetLoweringInfo(); + Value = DAG.getNode(ISD::ZERO_EXTEND, dl, VT, Value); + unsigned Shift = 8; + for (unsigned i = NumBits; i > 8; i >>= 1) { + Value = DAG.getNode(ISD::OR, dl, VT, + DAG.getNode(ISD::SHL, dl, VT, Value, + DAG.getConstant(Shift, + TLI.getShiftAmountTy())), + Value); + Shift <<= 1; + } + + return Value; +} + +/// getMemsetStringVal - Similar to getMemsetValue. Except this is only +/// used when a memcpy is turned into a memset when the source is a constant +/// string ptr. +static SDValue getMemsetStringVal(EVT VT, DebugLoc dl, SelectionDAG &DAG, + const TargetLowering &TLI, + std::string &Str, unsigned Offset) { + // Handle vector with all elements zero. + if (Str.empty()) { + if (VT.isInteger()) + return DAG.getConstant(0, VT); + unsigned NumElts = VT.getVectorNumElements(); + MVT EltVT = (VT.getVectorElementType() == MVT::f32) ? MVT::i32 : MVT::i64; + return DAG.getNode(ISD::BIT_CONVERT, dl, VT, + DAG.getConstant(0, + EVT::getVectorVT(*DAG.getContext(), EltVT, NumElts))); + } + + assert(!VT.isVector() && "Can't handle vector type here!"); + unsigned NumBits = VT.getSizeInBits(); + unsigned MSB = NumBits / 8; + uint64_t Val = 0; + if (TLI.isLittleEndian()) + Offset = Offset + MSB - 1; + for (unsigned i = 0; i != MSB; ++i) { + Val = (Val << 8) | (unsigned char)Str[Offset]; + Offset += TLI.isLittleEndian() ? -1 : 1; + } + return DAG.getConstant(Val, VT); +} + +/// getMemBasePlusOffset - Returns base and offset node for the +/// +static SDValue getMemBasePlusOffset(SDValue Base, unsigned Offset, + SelectionDAG &DAG) { + EVT VT = Base.getValueType(); + return DAG.getNode(ISD::ADD, Base.getDebugLoc(), + VT, Base, DAG.getConstant(Offset, VT)); +} + +/// isMemSrcFromString - Returns true if memcpy source is a string constant. +/// +static bool isMemSrcFromString(SDValue Src, std::string &Str) { + unsigned SrcDelta = 0; + GlobalAddressSDNode *G = NULL; + if (Src.getOpcode() == ISD::GlobalAddress) + G = cast(Src); + else if (Src.getOpcode() == ISD::ADD && + Src.getOperand(0).getOpcode() == ISD::GlobalAddress && + Src.getOperand(1).getOpcode() == ISD::Constant) { + G = cast(Src.getOperand(0)); + SrcDelta = cast(Src.getOperand(1))->getZExtValue(); + } + if (!G) + return false; + + GlobalVariable *GV = dyn_cast(G->getGlobal()); + if (GV && GetConstantStringInfo(GV, Str, SrcDelta, false)) + return true; + + return false; +} + +/// MeetsMaxMemopRequirement - Determines if the number of memory ops required +/// to replace the memset / memcpy is below the threshold. It also returns the +/// types of the sequence of memory ops to perform memset / memcpy. +static +bool MeetsMaxMemopRequirement(std::vector &MemOps, + SDValue Dst, SDValue Src, + unsigned Limit, uint64_t Size, unsigned &Align, + std::string &Str, bool &isSrcStr, + SelectionDAG &DAG, + const TargetLowering &TLI) { + isSrcStr = isMemSrcFromString(Src, Str); + bool isSrcConst = isa(Src); + EVT VT = TLI.getOptimalMemOpType(Size, Align, isSrcConst, isSrcStr, DAG); + bool AllowUnalign = TLI.allowsUnalignedMemoryAccesses(VT); + if (VT != MVT::iAny) { + const Type *Ty = VT.getTypeForEVT(*DAG.getContext()); + unsigned NewAlign = (unsigned) TLI.getTargetData()->getABITypeAlignment(Ty); + // If source is a string constant, this will require an unaligned load. + if (NewAlign > Align && (isSrcConst || AllowUnalign)) { + if (Dst.getOpcode() != ISD::FrameIndex) { + // Can't change destination alignment. It requires a unaligned store. + if (AllowUnalign) + VT = MVT::iAny; + } else { + int FI = cast(Dst)->getIndex(); + MachineFrameInfo *MFI = DAG.getMachineFunction().getFrameInfo(); + if (MFI->isFixedObjectIndex(FI)) { + // Can't change destination alignment. It requires a unaligned store. + if (AllowUnalign) + VT = MVT::iAny; + } else { + // Give the stack frame object a larger alignment if needed. + if (MFI->getObjectAlignment(FI) < NewAlign) + MFI->setObjectAlignment(FI, NewAlign); + Align = NewAlign; + } + } + } + } + + if (VT == MVT::iAny) { + if (TLI.allowsUnalignedMemoryAccesses(MVT::i64)) { + VT = MVT::i64; + } else { + switch (Align & 7) { + case 0: VT = MVT::i64; break; + case 4: VT = MVT::i32; break; + case 2: VT = MVT::i16; break; + default: VT = MVT::i8; break; + } + } + + MVT LVT = MVT::i64; + while (!TLI.isTypeLegal(LVT)) + LVT = (MVT::SimpleValueType)(LVT.SimpleTy - 1); + assert(LVT.isInteger()); + + if (VT.bitsGT(LVT)) + VT = LVT; + } + + unsigned NumMemOps = 0; + while (Size != 0) { + unsigned VTSize = VT.getSizeInBits() / 8; + while (VTSize > Size) { + // For now, only use non-vector load / store's for the left-over pieces. + if (VT.isVector()) { + VT = MVT::i64; + while (!TLI.isTypeLegal(VT)) + VT = (MVT::SimpleValueType)(VT.getSimpleVT().SimpleTy - 1); + VTSize = VT.getSizeInBits() / 8; + } else { + // This can result in a type that is not legal on the target, e.g. + // 1 or 2 bytes on PPC. + VT = (MVT::SimpleValueType)(VT.getSimpleVT().SimpleTy - 1); + VTSize >>= 1; + } + } + + if (++NumMemOps > Limit) + return false; + MemOps.push_back(VT); + Size -= VTSize; + } + + return true; +} + +static SDValue getMemcpyLoadsAndStores(SelectionDAG &DAG, DebugLoc dl, + SDValue Chain, SDValue Dst, + SDValue Src, uint64_t Size, + unsigned Align, bool AlwaysInline, + const Value *DstSV, uint64_t DstSVOff, + const Value *SrcSV, uint64_t SrcSVOff){ + const TargetLowering &TLI = DAG.getTargetLoweringInfo(); + + // Expand memcpy to a series of load and store ops if the size operand falls + // below a certain threshold. + std::vector MemOps; + uint64_t Limit = -1ULL; + if (!AlwaysInline) + Limit = TLI.getMaxStoresPerMemcpy(); + unsigned DstAlign = Align; // Destination alignment can change. + std::string Str; + bool CopyFromStr; + if (!MeetsMaxMemopRequirement(MemOps, Dst, Src, Limit, Size, DstAlign, + Str, CopyFromStr, DAG, TLI)) + return SDValue(); + + + bool isZeroStr = CopyFromStr && Str.empty(); + SmallVector OutChains; + unsigned NumMemOps = MemOps.size(); + uint64_t SrcOff = 0, DstOff = 0; + for (unsigned i = 0; i != NumMemOps; ++i) { + EVT VT = MemOps[i]; + unsigned VTSize = VT.getSizeInBits() / 8; + SDValue Value, Store; + + if (CopyFromStr && (isZeroStr || !VT.isVector())) { + // It's unlikely a store of a vector immediate can be done in a single + // instruction. It would require a load from a constantpool first. + // We also handle store a vector with all zero's. + // FIXME: Handle other cases where store of vector immediate is done in + // a single instruction. + Value = getMemsetStringVal(VT, dl, DAG, TLI, Str, SrcOff); + Store = DAG.getStore(Chain, dl, Value, + getMemBasePlusOffset(Dst, DstOff, DAG), + DstSV, DstSVOff + DstOff, false, DstAlign); + } else { + // The type might not be legal for the target. This should only happen + // if the type is smaller than a legal type, as on PPC, so the right + // thing to do is generate a LoadExt/StoreTrunc pair. These simplify + // to Load/Store if NVT==VT. + // FIXME does the case above also need this? + EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT); + assert(NVT.bitsGE(VT)); + Value = DAG.getExtLoad(ISD::EXTLOAD, dl, NVT, Chain, + getMemBasePlusOffset(Src, SrcOff, DAG), + SrcSV, SrcSVOff + SrcOff, VT, false, Align); + Store = DAG.getTruncStore(Chain, dl, Value, + getMemBasePlusOffset(Dst, DstOff, DAG), + DstSV, DstSVOff + DstOff, VT, false, DstAlign); + } + OutChains.push_back(Store); + SrcOff += VTSize; + DstOff += VTSize; + } + + return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, + &OutChains[0], OutChains.size()); +} + +static SDValue getMemmoveLoadsAndStores(SelectionDAG &DAG, DebugLoc dl, + SDValue Chain, SDValue Dst, + SDValue Src, uint64_t Size, + unsigned Align, bool AlwaysInline, + const Value *DstSV, uint64_t DstSVOff, + const Value *SrcSV, uint64_t SrcSVOff){ + const TargetLowering &TLI = DAG.getTargetLoweringInfo(); + + // Expand memmove to a series of load and store ops if the size operand falls + // below a certain threshold. + std::vector MemOps; + uint64_t Limit = -1ULL; + if (!AlwaysInline) + Limit = TLI.getMaxStoresPerMemmove(); + unsigned DstAlign = Align; // Destination alignment can change. + std::string Str; + bool CopyFromStr; + if (!MeetsMaxMemopRequirement(MemOps, Dst, Src, Limit, Size, DstAlign, + Str, CopyFromStr, DAG, TLI)) + return SDValue(); + + uint64_t SrcOff = 0, DstOff = 0; + + SmallVector LoadValues; + SmallVector LoadChains; + SmallVector OutChains; + unsigned NumMemOps = MemOps.size(); + for (unsigned i = 0; i < NumMemOps; i++) { + EVT VT = MemOps[i]; + unsigned VTSize = VT.getSizeInBits() / 8; + SDValue Value, Store; + + Value = DAG.getLoad(VT, dl, Chain, + getMemBasePlusOffset(Src, SrcOff, DAG), + SrcSV, SrcSVOff + SrcOff, false, Align); + LoadValues.push_back(Value); + LoadChains.push_back(Value.getValue(1)); + SrcOff += VTSize; + } + Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, + &LoadChains[0], LoadChains.size()); + OutChains.clear(); + for (unsigned i = 0; i < NumMemOps; i++) { + EVT VT = MemOps[i]; + unsigned VTSize = VT.getSizeInBits() / 8; + SDValue Value, Store; + + Store = DAG.getStore(Chain, dl, LoadValues[i], + getMemBasePlusOffset(Dst, DstOff, DAG), + DstSV, DstSVOff + DstOff, false, DstAlign); + OutChains.push_back(Store); + DstOff += VTSize; + } + + return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, + &OutChains[0], OutChains.size()); +} + +static SDValue getMemsetStores(SelectionDAG &DAG, DebugLoc dl, + SDValue Chain, SDValue Dst, + SDValue Src, uint64_t Size, + unsigned Align, + const Value *DstSV, uint64_t DstSVOff) { + const TargetLowering &TLI = DAG.getTargetLoweringInfo(); + + // Expand memset to a series of load/store ops if the size operand + // falls below a certain threshold. + std::vector MemOps; + std::string Str; + bool CopyFromStr; + if (!MeetsMaxMemopRequirement(MemOps, Dst, Src, TLI.getMaxStoresPerMemset(), + Size, Align, Str, CopyFromStr, DAG, TLI)) + return SDValue(); + + SmallVector OutChains; + uint64_t DstOff = 0; + + unsigned NumMemOps = MemOps.size(); + for (unsigned i = 0; i < NumMemOps; i++) { + EVT VT = MemOps[i]; + unsigned VTSize = VT.getSizeInBits() / 8; + SDValue Value = getMemsetValue(Src, VT, DAG, dl); + SDValue Store = DAG.getStore(Chain, dl, Value, + getMemBasePlusOffset(Dst, DstOff, DAG), + DstSV, DstSVOff + DstOff); + OutChains.push_back(Store); + DstOff += VTSize; + } + + return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, + &OutChains[0], OutChains.size()); +} + +SDValue SelectionDAG::getMemcpy(SDValue Chain, DebugLoc dl, SDValue Dst, + SDValue Src, SDValue Size, + unsigned Align, bool AlwaysInline, + const Value *DstSV, uint64_t DstSVOff, + const Value *SrcSV, uint64_t SrcSVOff) { + + // Check to see if we should lower the memcpy to loads and stores first. + // For cases within the target-specified limits, this is the best choice. + ConstantSDNode *ConstantSize = dyn_cast(Size); + if (ConstantSize) { + // Memcpy with size zero? Just return the original chain. + if (ConstantSize->isNullValue()) + return Chain; + + SDValue Result = + getMemcpyLoadsAndStores(*this, dl, Chain, Dst, Src, + ConstantSize->getZExtValue(), + Align, false, DstSV, DstSVOff, SrcSV, SrcSVOff); + if (Result.getNode()) + return Result; + } + + // Then check to see if we should lower the memcpy with target-specific + // code. If the target chooses to do this, this is the next best. + SDValue Result = + TLI.EmitTargetCodeForMemcpy(*this, dl, Chain, Dst, Src, Size, Align, + AlwaysInline, + DstSV, DstSVOff, SrcSV, SrcSVOff); + if (Result.getNode()) + return Result; + + // If we really need inline code and the target declined to provide it, + // use a (potentially long) sequence of loads and stores. + if (AlwaysInline) { + assert(ConstantSize && "AlwaysInline requires a constant size!"); + return getMemcpyLoadsAndStores(*this, dl, Chain, Dst, Src, + ConstantSize->getZExtValue(), Align, true, + DstSV, DstSVOff, SrcSV, SrcSVOff); + } + + // Emit a library call. + TargetLowering::ArgListTy Args; + TargetLowering::ArgListEntry Entry; + Entry.Ty = TLI.getTargetData()->getIntPtrType(*getContext()); + Entry.Node = Dst; Args.push_back(Entry); + Entry.Node = Src; Args.push_back(Entry); + Entry.Node = Size; Args.push_back(Entry); + // FIXME: pass in DebugLoc + std::pair CallResult = + TLI.LowerCallTo(Chain, Type::getVoidTy(*getContext()), + false, false, false, false, 0, + TLI.getLibcallCallingConv(RTLIB::MEMCPY), false, + /*isReturnValueUsed=*/false, + getExternalSymbol(TLI.getLibcallName(RTLIB::MEMCPY), + TLI.getPointerTy()), + Args, *this, dl); + return CallResult.second; +} + +SDValue SelectionDAG::getMemmove(SDValue Chain, DebugLoc dl, SDValue Dst, + SDValue Src, SDValue Size, + unsigned Align, + const Value *DstSV, uint64_t DstSVOff, + const Value *SrcSV, uint64_t SrcSVOff) { + + // Check to see if we should lower the memmove to loads and stores first. + // For cases within the target-specified limits, this is the best choice. + ConstantSDNode *ConstantSize = dyn_cast(Size); + if (ConstantSize) { + // Memmove with size zero? Just return the original chain. + if (ConstantSize->isNullValue()) + return Chain; + + SDValue Result = + getMemmoveLoadsAndStores(*this, dl, Chain, Dst, Src, + ConstantSize->getZExtValue(), + Align, false, DstSV, DstSVOff, SrcSV, SrcSVOff); + if (Result.getNode()) + return Result; + } + + // Then check to see if we should lower the memmove with target-specific + // code. If the target chooses to do this, this is the next best. + SDValue Result = + TLI.EmitTargetCodeForMemmove(*this, dl, Chain, Dst, Src, Size, Align, + DstSV, DstSVOff, SrcSV, SrcSVOff); + if (Result.getNode()) + return Result; + + // Emit a library call. + TargetLowering::ArgListTy Args; + TargetLowering::ArgListEntry Entry; + Entry.Ty = TLI.getTargetData()->getIntPtrType(*getContext()); + Entry.Node = Dst; Args.push_back(Entry); + Entry.Node = Src; Args.push_back(Entry); + Entry.Node = Size; Args.push_back(Entry); + // FIXME: pass in DebugLoc + std::pair CallResult = + TLI.LowerCallTo(Chain, Type::getVoidTy(*getContext()), + false, false, false, false, 0, + TLI.getLibcallCallingConv(RTLIB::MEMMOVE), false, + /*isReturnValueUsed=*/false, + getExternalSymbol(TLI.getLibcallName(RTLIB::MEMMOVE), + TLI.getPointerTy()), + Args, *this, dl); + return CallResult.second; +} + +SDValue SelectionDAG::getMemset(SDValue Chain, DebugLoc dl, SDValue Dst, + SDValue Src, SDValue Size, + unsigned Align, + const Value *DstSV, uint64_t DstSVOff) { + + // Check to see if we should lower the memset to stores first. + // For cases within the target-specified limits, this is the best choice. + ConstantSDNode *ConstantSize = dyn_cast(Size); + if (ConstantSize) { + // Memset with size zero? Just return the original chain. + if (ConstantSize->isNullValue()) + return Chain; + + SDValue Result = + getMemsetStores(*this, dl, Chain, Dst, Src, ConstantSize->getZExtValue(), + Align, DstSV, DstSVOff); + if (Result.getNode()) + return Result; + } + + // Then check to see if we should lower the memset with target-specific + // code. If the target chooses to do this, this is the next best. + SDValue Result = + TLI.EmitTargetCodeForMemset(*this, dl, Chain, Dst, Src, Size, Align, + DstSV, DstSVOff); + if (Result.getNode()) + return Result; + + // Emit a library call. + const Type *IntPtrTy = TLI.getTargetData()->getIntPtrType(*getContext()); + TargetLowering::ArgListTy Args; + TargetLowering::ArgListEntry Entry; + Entry.Node = Dst; Entry.Ty = IntPtrTy; + Args.push_back(Entry); + // Extend or truncate the argument to be an i32 value for the call. + if (Src.getValueType().bitsGT(MVT::i32)) + Src = getNode(ISD::TRUNCATE, dl, MVT::i32, Src); + else + Src = getNode(ISD::ZERO_EXTEND, dl, MVT::i32, Src); + Entry.Node = Src; + Entry.Ty = Type::getInt32Ty(*getContext()); + Entry.isSExt = true; + Args.push_back(Entry); + Entry.Node = Size; + Entry.Ty = IntPtrTy; + Entry.isSExt = false; + Args.push_back(Entry); + // FIXME: pass in DebugLoc + std::pair CallResult = + TLI.LowerCallTo(Chain, Type::getVoidTy(*getContext()), + false, false, false, false, 0, + TLI.getLibcallCallingConv(RTLIB::MEMSET), false, + /*isReturnValueUsed=*/false, + getExternalSymbol(TLI.getLibcallName(RTLIB::MEMSET), + TLI.getPointerTy()), + Args, *this, dl); + return CallResult.second; +} + +SDValue SelectionDAG::getAtomic(unsigned Opcode, DebugLoc dl, EVT MemVT, + SDValue Chain, + SDValue Ptr, SDValue Cmp, + SDValue Swp, const Value* PtrVal, + unsigned Alignment) { + if (Alignment == 0) // Ensure that codegen never sees alignment 0 + Alignment = getEVTAlignment(MemVT); + + // Check if the memory reference references a frame index + if (!PtrVal) + if (const FrameIndexSDNode *FI = + dyn_cast(Ptr.getNode())) + PtrVal = PseudoSourceValue::getFixedStack(FI->getIndex()); + + MachineFunction &MF = getMachineFunction(); + unsigned Flags = MachineMemOperand::MOLoad | MachineMemOperand::MOStore; + + // For now, atomics are considered to be volatile always. + Flags |= MachineMemOperand::MOVolatile; + + MachineMemOperand *MMO = + MF.getMachineMemOperand(PtrVal, Flags, 0, + MemVT.getStoreSize(), Alignment); + + return getAtomic(Opcode, dl, MemVT, Chain, Ptr, Cmp, Swp, MMO); +} + +SDValue SelectionDAG::getAtomic(unsigned Opcode, DebugLoc dl, EVT MemVT, + SDValue Chain, + SDValue Ptr, SDValue Cmp, + SDValue Swp, MachineMemOperand *MMO) { + assert(Opcode == ISD::ATOMIC_CMP_SWAP && "Invalid Atomic Op"); + assert(Cmp.getValueType() == Swp.getValueType() && "Invalid Atomic Op Types"); + + EVT VT = Cmp.getValueType(); + + SDVTList VTs = getVTList(VT, MVT::Other); + FoldingSetNodeID ID; + ID.AddInteger(MemVT.getRawBits()); + SDValue Ops[] = {Chain, Ptr, Cmp, Swp}; + AddNodeIDNode(ID, Opcode, VTs, Ops, 4); + void* IP = 0; + if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) { + cast(E)->refineAlignment(MMO); + return SDValue(E, 0); + } + SDNode* N = NodeAllocator.Allocate(); + new (N) AtomicSDNode(Opcode, dl, VTs, MemVT, Chain, Ptr, Cmp, Swp, MMO); + CSEMap.InsertNode(N, IP); + AllNodes.push_back(N); + return SDValue(N, 0); +} + +SDValue SelectionDAG::getAtomic(unsigned Opcode, DebugLoc dl, EVT MemVT, + SDValue Chain, + SDValue Ptr, SDValue Val, + const Value* PtrVal, + unsigned Alignment) { + if (Alignment == 0) // Ensure that codegen never sees alignment 0 + Alignment = getEVTAlignment(MemVT); + + // Check if the memory reference references a frame index + if (!PtrVal) + if (const FrameIndexSDNode *FI = + dyn_cast(Ptr.getNode())) + PtrVal = PseudoSourceValue::getFixedStack(FI->getIndex()); + + MachineFunction &MF = getMachineFunction(); + unsigned Flags = MachineMemOperand::MOLoad | MachineMemOperand::MOStore; + + // For now, atomics are considered to be volatile always. + Flags |= MachineMemOperand::MOVolatile; + + MachineMemOperand *MMO = + MF.getMachineMemOperand(PtrVal, Flags, 0, + MemVT.getStoreSize(), Alignment); + + return getAtomic(Opcode, dl, MemVT, Chain, Ptr, Val, MMO); +} + +SDValue SelectionDAG::getAtomic(unsigned Opcode, DebugLoc dl, EVT MemVT, + SDValue Chain, + SDValue Ptr, SDValue Val, + MachineMemOperand *MMO) { + assert((Opcode == ISD::ATOMIC_LOAD_ADD || + Opcode == ISD::ATOMIC_LOAD_SUB || + Opcode == ISD::ATOMIC_LOAD_AND || + Opcode == ISD::ATOMIC_LOAD_OR || + Opcode == ISD::ATOMIC_LOAD_XOR || + Opcode == ISD::ATOMIC_LOAD_NAND || + Opcode == ISD::ATOMIC_LOAD_MIN || + Opcode == ISD::ATOMIC_LOAD_MAX || + Opcode == ISD::ATOMIC_LOAD_UMIN || + Opcode == ISD::ATOMIC_LOAD_UMAX || + Opcode == ISD::ATOMIC_SWAP) && + "Invalid Atomic Op"); + + EVT VT = Val.getValueType(); + + SDVTList VTs = getVTList(VT, MVT::Other); + FoldingSetNodeID ID; + ID.AddInteger(MemVT.getRawBits()); + SDValue Ops[] = {Chain, Ptr, Val}; + AddNodeIDNode(ID, Opcode, VTs, Ops, 3); + void* IP = 0; + if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) { + cast(E)->refineAlignment(MMO); + return SDValue(E, 0); + } + SDNode* N = NodeAllocator.Allocate(); + new (N) AtomicSDNode(Opcode, dl, VTs, MemVT, Chain, Ptr, Val, MMO); + CSEMap.InsertNode(N, IP); + AllNodes.push_back(N); + return SDValue(N, 0); +} + +/// getMergeValues - Create a MERGE_VALUES node from the given operands. +/// Allowed to return something different (and simpler) if Simplify is true. +SDValue SelectionDAG::getMergeValues(const SDValue *Ops, unsigned NumOps, + DebugLoc dl) { + if (NumOps == 1) + return Ops[0]; + + SmallVector VTs; + VTs.reserve(NumOps); + for (unsigned i = 0; i < NumOps; ++i) + VTs.push_back(Ops[i].getValueType()); + return getNode(ISD::MERGE_VALUES, dl, getVTList(&VTs[0], NumOps), + Ops, NumOps); +} + +SDValue +SelectionDAG::getMemIntrinsicNode(unsigned Opcode, DebugLoc dl, + const EVT *VTs, unsigned NumVTs, + const SDValue *Ops, unsigned NumOps, + EVT MemVT, const Value *srcValue, int SVOff, + unsigned Align, bool Vol, + bool ReadMem, bool WriteMem) { + return getMemIntrinsicNode(Opcode, dl, makeVTList(VTs, NumVTs), Ops, NumOps, + MemVT, srcValue, SVOff, Align, Vol, + ReadMem, WriteMem); +} + +SDValue +SelectionDAG::getMemIntrinsicNode(unsigned Opcode, DebugLoc dl, SDVTList VTList, + const SDValue *Ops, unsigned NumOps, + EVT MemVT, const Value *srcValue, int SVOff, + unsigned Align, bool Vol, + bool ReadMem, bool WriteMem) { + if (Align == 0) // Ensure that codegen never sees alignment 0 + Align = getEVTAlignment(MemVT); + + MachineFunction &MF = getMachineFunction(); + unsigned Flags = 0; + if (WriteMem) + Flags |= MachineMemOperand::MOStore; + if (ReadMem) + Flags |= MachineMemOperand::MOLoad; + if (Vol) + Flags |= MachineMemOperand::MOVolatile; + MachineMemOperand *MMO = + MF.getMachineMemOperand(srcValue, Flags, SVOff, + MemVT.getStoreSize(), Align); + + return getMemIntrinsicNode(Opcode, dl, VTList, Ops, NumOps, MemVT, MMO); +} + +SDValue +SelectionDAG::getMemIntrinsicNode(unsigned Opcode, DebugLoc dl, SDVTList VTList, + const SDValue *Ops, unsigned NumOps, + EVT MemVT, MachineMemOperand *MMO) { + assert((Opcode == ISD::INTRINSIC_VOID || + Opcode == ISD::INTRINSIC_W_CHAIN || + (Opcode <= INT_MAX && + (int)Opcode >= ISD::FIRST_TARGET_MEMORY_OPCODE)) && + "Opcode is not a memory-accessing opcode!"); + + // Memoize the node unless it returns a flag. + MemIntrinsicSDNode *N; + if (VTList.VTs[VTList.NumVTs-1] != MVT::Flag) { + FoldingSetNodeID ID; + AddNodeIDNode(ID, Opcode, VTList, Ops, NumOps); + void *IP = 0; + if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) { + cast(E)->refineAlignment(MMO); + return SDValue(E, 0); + } + + N = NodeAllocator.Allocate(); + new (N) MemIntrinsicSDNode(Opcode, dl, VTList, Ops, NumOps, MemVT, MMO); + CSEMap.InsertNode(N, IP); + } else { + N = NodeAllocator.Allocate(); + new (N) MemIntrinsicSDNode(Opcode, dl, VTList, Ops, NumOps, MemVT, MMO); + } + AllNodes.push_back(N); + return SDValue(N, 0); +} + +SDValue +SelectionDAG::getLoad(ISD::MemIndexedMode AM, DebugLoc dl, + ISD::LoadExtType ExtType, EVT VT, SDValue Chain, + SDValue Ptr, SDValue Offset, + const Value *SV, int SVOffset, EVT MemVT, + bool isVolatile, unsigned Alignment) { + if (Alignment == 0) // Ensure that codegen never sees alignment 0 + Alignment = getEVTAlignment(VT); + + // Check if the memory reference references a frame index + if (!SV) + if (const FrameIndexSDNode *FI = + dyn_cast(Ptr.getNode())) + SV = PseudoSourceValue::getFixedStack(FI->getIndex()); + + MachineFunction &MF = getMachineFunction(); + unsigned Flags = MachineMemOperand::MOLoad; + if (isVolatile) + Flags |= MachineMemOperand::MOVolatile; + MachineMemOperand *MMO = + MF.getMachineMemOperand(SV, Flags, SVOffset, + MemVT.getStoreSize(), Alignment); + return getLoad(AM, dl, ExtType, VT, Chain, Ptr, Offset, MemVT, MMO); +} + +SDValue +SelectionDAG::getLoad(ISD::MemIndexedMode AM, DebugLoc dl, + ISD::LoadExtType ExtType, EVT VT, SDValue Chain, + SDValue Ptr, SDValue Offset, EVT MemVT, + MachineMemOperand *MMO) { + if (VT == MemVT) { + ExtType = ISD::NON_EXTLOAD; + } else if (ExtType == ISD::NON_EXTLOAD) { + assert(VT == MemVT && "Non-extending load from different memory type!"); + } else { + // Extending load. + if (VT.isVector()) + assert(MemVT.getVectorNumElements() == VT.getVectorNumElements() && + "Invalid vector extload!"); + else + assert(MemVT.bitsLT(VT) && + "Should only be an extending load, not truncating!"); + assert((ExtType == ISD::EXTLOAD || VT.isInteger()) && + "Cannot sign/zero extend a FP/Vector load!"); + assert(VT.isInteger() == MemVT.isInteger() && + "Cannot convert from FP to Int or Int -> FP!"); + } + + bool Indexed = AM != ISD::UNINDEXED; + assert((Indexed || Offset.getOpcode() == ISD::UNDEF) && + "Unindexed load with an offset!"); + + SDVTList VTs = Indexed ? + getVTList(VT, Ptr.getValueType(), MVT::Other) : getVTList(VT, MVT::Other); + SDValue Ops[] = { Chain, Ptr, Offset }; + FoldingSetNodeID ID; + AddNodeIDNode(ID, ISD::LOAD, VTs, Ops, 3); + ID.AddInteger(MemVT.getRawBits()); + ID.AddInteger(encodeMemSDNodeFlags(ExtType, AM, MMO->isVolatile())); + void *IP = 0; + if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) { + cast(E)->refineAlignment(MMO); + return SDValue(E, 0); + } + SDNode *N = NodeAllocator.Allocate(); + new (N) LoadSDNode(Ops, dl, VTs, AM, ExtType, MemVT, MMO); + CSEMap.InsertNode(N, IP); + AllNodes.push_back(N); + return SDValue(N, 0); +} + +SDValue SelectionDAG::getLoad(EVT VT, DebugLoc dl, + SDValue Chain, SDValue Ptr, + const Value *SV, int SVOffset, + bool isVolatile, unsigned Alignment) { + SDValue Undef = getUNDEF(Ptr.getValueType()); + return getLoad(ISD::UNINDEXED, dl, ISD::NON_EXTLOAD, VT, Chain, Ptr, Undef, + SV, SVOffset, VT, isVolatile, Alignment); +} + +SDValue SelectionDAG::getExtLoad(ISD::LoadExtType ExtType, DebugLoc dl, EVT VT, + SDValue Chain, SDValue Ptr, + const Value *SV, + int SVOffset, EVT MemVT, + bool isVolatile, unsigned Alignment) { + SDValue Undef = getUNDEF(Ptr.getValueType()); + return getLoad(ISD::UNINDEXED, dl, ExtType, VT, Chain, Ptr, Undef, + SV, SVOffset, MemVT, isVolatile, Alignment); +} + +SDValue +SelectionDAG::getIndexedLoad(SDValue OrigLoad, DebugLoc dl, SDValue Base, + SDValue Offset, ISD::MemIndexedMode AM) { + LoadSDNode *LD = cast(OrigLoad); + assert(LD->getOffset().getOpcode() == ISD::UNDEF && + "Load is already a indexed load!"); + return getLoad(AM, dl, LD->getExtensionType(), OrigLoad.getValueType(), + LD->getChain(), Base, Offset, LD->getSrcValue(), + LD->getSrcValueOffset(), LD->getMemoryVT(), + LD->isVolatile(), LD->getAlignment()); +} + +SDValue SelectionDAG::getStore(SDValue Chain, DebugLoc dl, SDValue Val, + SDValue Ptr, const Value *SV, int SVOffset, + bool isVolatile, unsigned Alignment) { + if (Alignment == 0) // Ensure that codegen never sees alignment 0 + Alignment = getEVTAlignment(Val.getValueType()); + + // Check if the memory reference references a frame index + if (!SV) + if (const FrameIndexSDNode *FI = + dyn_cast(Ptr.getNode())) + SV = PseudoSourceValue::getFixedStack(FI->getIndex()); + + MachineFunction &MF = getMachineFunction(); + unsigned Flags = MachineMemOperand::MOStore; + if (isVolatile) + Flags |= MachineMemOperand::MOVolatile; + MachineMemOperand *MMO = + MF.getMachineMemOperand(SV, Flags, SVOffset, + Val.getValueType().getStoreSize(), Alignment); + + return getStore(Chain, dl, Val, Ptr, MMO); +} + +SDValue SelectionDAG::getStore(SDValue Chain, DebugLoc dl, SDValue Val, + SDValue Ptr, MachineMemOperand *MMO) { + EVT VT = Val.getValueType(); + SDVTList VTs = getVTList(MVT::Other); + SDValue Undef = getUNDEF(Ptr.getValueType()); + SDValue Ops[] = { Chain, Val, Ptr, Undef }; + FoldingSetNodeID ID; + AddNodeIDNode(ID, ISD::STORE, VTs, Ops, 4); + ID.AddInteger(VT.getRawBits()); + ID.AddInteger(encodeMemSDNodeFlags(false, ISD::UNINDEXED, MMO->isVolatile())); + void *IP = 0; + if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) { + cast(E)->refineAlignment(MMO); + return SDValue(E, 0); + } + SDNode *N = NodeAllocator.Allocate(); + new (N) StoreSDNode(Ops, dl, VTs, ISD::UNINDEXED, false, VT, MMO); + CSEMap.InsertNode(N, IP); + AllNodes.push_back(N); + return SDValue(N, 0); +} + +SDValue SelectionDAG::getTruncStore(SDValue Chain, DebugLoc dl, SDValue Val, + SDValue Ptr, const Value *SV, + int SVOffset, EVT SVT, + bool isVolatile, unsigned Alignment) { + if (Alignment == 0) // Ensure that codegen never sees alignment 0 + Alignment = getEVTAlignment(SVT); + + // Check if the memory reference references a frame index + if (!SV) + if (const FrameIndexSDNode *FI = + dyn_cast(Ptr.getNode())) + SV = PseudoSourceValue::getFixedStack(FI->getIndex()); + + MachineFunction &MF = getMachineFunction(); + unsigned Flags = MachineMemOperand::MOStore; + if (isVolatile) + Flags |= MachineMemOperand::MOVolatile; + MachineMemOperand *MMO = + MF.getMachineMemOperand(SV, Flags, SVOffset, SVT.getStoreSize(), Alignment); + + return getTruncStore(Chain, dl, Val, Ptr, SVT, MMO); +} + +SDValue SelectionDAG::getTruncStore(SDValue Chain, DebugLoc dl, SDValue Val, + SDValue Ptr, EVT SVT, + MachineMemOperand *MMO) { + EVT VT = Val.getValueType(); + + if (VT == SVT) + return getStore(Chain, dl, Val, Ptr, MMO); + + assert(VT.bitsGT(SVT) && "Not a truncation?"); + assert(VT.isInteger() == SVT.isInteger() && + "Can't do FP-INT conversion!"); + + + SDVTList VTs = getVTList(MVT::Other); + SDValue Undef = getUNDEF(Ptr.getValueType()); + SDValue Ops[] = { Chain, Val, Ptr, Undef }; + FoldingSetNodeID ID; + AddNodeIDNode(ID, ISD::STORE, VTs, Ops, 4); + ID.AddInteger(SVT.getRawBits()); + ID.AddInteger(encodeMemSDNodeFlags(true, ISD::UNINDEXED, MMO->isVolatile())); + void *IP = 0; + if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) { + cast(E)->refineAlignment(MMO); + return SDValue(E, 0); + } + SDNode *N = NodeAllocator.Allocate(); + new (N) StoreSDNode(Ops, dl, VTs, ISD::UNINDEXED, true, SVT, MMO); + CSEMap.InsertNode(N, IP); + AllNodes.push_back(N); + return SDValue(N, 0); +} + +SDValue +SelectionDAG::getIndexedStore(SDValue OrigStore, DebugLoc dl, SDValue Base, + SDValue Offset, ISD::MemIndexedMode AM) { + StoreSDNode *ST = cast(OrigStore); + assert(ST->getOffset().getOpcode() == ISD::UNDEF && + "Store is already a indexed store!"); + SDVTList VTs = getVTList(Base.getValueType(), MVT::Other); + SDValue Ops[] = { ST->getChain(), ST->getValue(), Base, Offset }; + FoldingSetNodeID ID; + AddNodeIDNode(ID, ISD::STORE, VTs, Ops, 4); + ID.AddInteger(ST->getMemoryVT().getRawBits()); + ID.AddInteger(ST->getRawSubclassData()); + void *IP = 0; + if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) + return SDValue(E, 0); + SDNode *N = NodeAllocator.Allocate(); + new (N) StoreSDNode(Ops, dl, VTs, AM, + ST->isTruncatingStore(), ST->getMemoryVT(), + ST->getMemOperand()); + CSEMap.InsertNode(N, IP); + AllNodes.push_back(N); + return SDValue(N, 0); +} + +SDValue SelectionDAG::getVAArg(EVT VT, DebugLoc dl, + SDValue Chain, SDValue Ptr, + SDValue SV) { + SDValue Ops[] = { Chain, Ptr, SV }; + return getNode(ISD::VAARG, dl, getVTList(VT, MVT::Other), Ops, 3); +} + +SDValue SelectionDAG::getNode(unsigned Opcode, DebugLoc DL, EVT VT, + const SDUse *Ops, unsigned NumOps) { + switch (NumOps) { + case 0: return getNode(Opcode, DL, VT); + case 1: return getNode(Opcode, DL, VT, Ops[0]); + case 2: return getNode(Opcode, DL, VT, Ops[0], Ops[1]); + case 3: return getNode(Opcode, DL, VT, Ops[0], Ops[1], Ops[2]); + default: break; + } + + // Copy from an SDUse array into an SDValue array for use with + // the regular getNode logic. + SmallVector NewOps(Ops, Ops + NumOps); + return getNode(Opcode, DL, VT, &NewOps[0], NumOps); +} + +SDValue SelectionDAG::getNode(unsigned Opcode, DebugLoc DL, EVT VT, + const SDValue *Ops, unsigned NumOps) { + switch (NumOps) { + case 0: return getNode(Opcode, DL, VT); + case 1: return getNode(Opcode, DL, VT, Ops[0]); + case 2: return getNode(Opcode, DL, VT, Ops[0], Ops[1]); + case 3: return getNode(Opcode, DL, VT, Ops[0], Ops[1], Ops[2]); + default: break; + } + + switch (Opcode) { + default: break; + case ISD::SELECT_CC: { + assert(NumOps == 5 && "SELECT_CC takes 5 operands!"); + assert(Ops[0].getValueType() == Ops[1].getValueType() && + "LHS and RHS of condition must have same type!"); + assert(Ops[2].getValueType() == Ops[3].getValueType() && + "True and False arms of SelectCC must have same type!"); + assert(Ops[2].getValueType() == VT && + "select_cc node must be of same type as true and false value!"); + break; + } + case ISD::BR_CC: { + assert(NumOps == 5 && "BR_CC takes 5 operands!"); + assert(Ops[2].getValueType() == Ops[3].getValueType() && + "LHS/RHS of comparison should match types!"); + break; + } + } + + // Memoize nodes. + SDNode *N; + SDVTList VTs = getVTList(VT); + + if (VT != MVT::Flag) { + FoldingSetNodeID ID; + AddNodeIDNode(ID, Opcode, VTs, Ops, NumOps); + void *IP = 0; + + if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) + return SDValue(E, 0); + + N = NodeAllocator.Allocate(); + new (N) SDNode(Opcode, DL, VTs, Ops, NumOps); + CSEMap.InsertNode(N, IP); + } else { + N = NodeAllocator.Allocate(); + new (N) SDNode(Opcode, DL, VTs, Ops, NumOps); + } + + AllNodes.push_back(N); +#ifndef NDEBUG + VerifyNode(N); +#endif + return SDValue(N, 0); +} + +SDValue SelectionDAG::getNode(unsigned Opcode, DebugLoc DL, + const std::vector &ResultTys, + const SDValue *Ops, unsigned NumOps) { + return getNode(Opcode, DL, getVTList(&ResultTys[0], ResultTys.size()), + Ops, NumOps); +} + +SDValue SelectionDAG::getNode(unsigned Opcode, DebugLoc DL, + const EVT *VTs, unsigned NumVTs, + const SDValue *Ops, unsigned NumOps) { + if (NumVTs == 1) + return getNode(Opcode, DL, VTs[0], Ops, NumOps); + return getNode(Opcode, DL, makeVTList(VTs, NumVTs), Ops, NumOps); +} + +SDValue SelectionDAG::getNode(unsigned Opcode, DebugLoc DL, SDVTList VTList, + const SDValue *Ops, unsigned NumOps) { + if (VTList.NumVTs == 1) + return getNode(Opcode, DL, VTList.VTs[0], Ops, NumOps); + +#if 0 + switch (Opcode) { + // FIXME: figure out how to safely handle things like + // int foo(int x) { return 1 << (x & 255); } + // int bar() { return foo(256); } + case ISD::SRA_PARTS: + case ISD::SRL_PARTS: + case ISD::SHL_PARTS: + if (N3.getOpcode() == ISD::SIGN_EXTEND_INREG && + cast(N3.getOperand(1))->getVT() != MVT::i1) + return getNode(Opcode, DL, VT, N1, N2, N3.getOperand(0)); + else if (N3.getOpcode() == ISD::AND) + if (ConstantSDNode *AndRHS = dyn_cast(N3.getOperand(1))) { + // If the and is only masking out bits that cannot effect the shift, + // eliminate the and. + unsigned NumBits = VT.getSizeInBits()*2; + if ((AndRHS->getValue() & (NumBits-1)) == NumBits-1) + return getNode(Opcode, DL, VT, N1, N2, N3.getOperand(0)); + } + break; + } +#endif + + // Memoize the node unless it returns a flag. + SDNode *N; + if (VTList.VTs[VTList.NumVTs-1] != MVT::Flag) { + FoldingSetNodeID ID; + AddNodeIDNode(ID, Opcode, VTList, Ops, NumOps); + void *IP = 0; + if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) + return SDValue(E, 0); + if (NumOps == 1) { + N = NodeAllocator.Allocate(); + new (N) UnarySDNode(Opcode, DL, VTList, Ops[0]); + } else if (NumOps == 2) { + N = NodeAllocator.Allocate(); + new (N) BinarySDNode(Opcode, DL, VTList, Ops[0], Ops[1]); + } else if (NumOps == 3) { + N = NodeAllocator.Allocate(); + new (N) TernarySDNode(Opcode, DL, VTList, Ops[0], Ops[1], Ops[2]); + } else { + N = NodeAllocator.Allocate(); + new (N) SDNode(Opcode, DL, VTList, Ops, NumOps); + } + CSEMap.InsertNode(N, IP); + } else { + if (NumOps == 1) { + N = NodeAllocator.Allocate(); + new (N) UnarySDNode(Opcode, DL, VTList, Ops[0]); + } else if (NumOps == 2) { + N = NodeAllocator.Allocate(); + new (N) BinarySDNode(Opcode, DL, VTList, Ops[0], Ops[1]); + } else if (NumOps == 3) { + N = NodeAllocator.Allocate(); + new (N) TernarySDNode(Opcode, DL, VTList, Ops[0], Ops[1], Ops[2]); + } else { + N = NodeAllocator.Allocate(); + new (N) SDNode(Opcode, DL, VTList, Ops, NumOps); + } + } + AllNodes.push_back(N); +#ifndef NDEBUG + VerifyNode(N); +#endif + return SDValue(N, 0); +} + +SDValue SelectionDAG::getNode(unsigned Opcode, DebugLoc DL, SDVTList VTList) { + return getNode(Opcode, DL, VTList, 0, 0); +} + +SDValue SelectionDAG::getNode(unsigned Opcode, DebugLoc DL, SDVTList VTList, + SDValue N1) { + SDValue Ops[] = { N1 }; + return getNode(Opcode, DL, VTList, Ops, 1); +} + +SDValue SelectionDAG::getNode(unsigned Opcode, DebugLoc DL, SDVTList VTList, + SDValue N1, SDValue N2) { + SDValue Ops[] = { N1, N2 }; + return getNode(Opcode, DL, VTList, Ops, 2); +} + +SDValue SelectionDAG::getNode(unsigned Opcode, DebugLoc DL, SDVTList VTList, + SDValue N1, SDValue N2, SDValue N3) { + SDValue Ops[] = { N1, N2, N3 }; + return getNode(Opcode, DL, VTList, Ops, 3); +} + +SDValue SelectionDAG::getNode(unsigned Opcode, DebugLoc DL, SDVTList VTList, + SDValue N1, SDValue N2, SDValue N3, + SDValue N4) { + SDValue Ops[] = { N1, N2, N3, N4 }; + return getNode(Opcode, DL, VTList, Ops, 4); +} + +SDValue SelectionDAG::getNode(unsigned Opcode, DebugLoc DL, SDVTList VTList, + SDValue N1, SDValue N2, SDValue N3, + SDValue N4, SDValue N5) { + SDValue Ops[] = { N1, N2, N3, N4, N5 }; + return getNode(Opcode, DL, VTList, Ops, 5); +} + +SDVTList SelectionDAG::getVTList(EVT VT) { + return makeVTList(SDNode::getValueTypeList(VT), 1); +} + +SDVTList SelectionDAG::getVTList(EVT VT1, EVT VT2) { + for (std::vector::reverse_iterator I = VTList.rbegin(), + E = VTList.rend(); I != E; ++I) + if (I->NumVTs == 2 && I->VTs[0] == VT1 && I->VTs[1] == VT2) + return *I; + + EVT *Array = Allocator.Allocate(2); + Array[0] = VT1; + Array[1] = VT2; + SDVTList Result = makeVTList(Array, 2); + VTList.push_back(Result); + return Result; +} + +SDVTList SelectionDAG::getVTList(EVT VT1, EVT VT2, EVT VT3) { + for (std::vector::reverse_iterator I = VTList.rbegin(), + E = VTList.rend(); I != E; ++I) + if (I->NumVTs == 3 && I->VTs[0] == VT1 && I->VTs[1] == VT2 && + I->VTs[2] == VT3) + return *I; + + EVT *Array = Allocator.Allocate(3); + Array[0] = VT1; + Array[1] = VT2; + Array[2] = VT3; + SDVTList Result = makeVTList(Array, 3); + VTList.push_back(Result); + return Result; +} + +SDVTList SelectionDAG::getVTList(EVT VT1, EVT VT2, EVT VT3, EVT VT4) { + for (std::vector::reverse_iterator I = VTList.rbegin(), + E = VTList.rend(); I != E; ++I) + if (I->NumVTs == 4 && I->VTs[0] == VT1 && I->VTs[1] == VT2 && + I->VTs[2] == VT3 && I->VTs[3] == VT4) + return *I; + + EVT *Array = Allocator.Allocate(3); + Array[0] = VT1; + Array[1] = VT2; + Array[2] = VT3; + Array[3] = VT4; + SDVTList Result = makeVTList(Array, 4); + VTList.push_back(Result); + return Result; +} + +SDVTList SelectionDAG::getVTList(const EVT *VTs, unsigned NumVTs) { + switch (NumVTs) { + case 0: llvm_unreachable("Cannot have nodes without results!"); + case 1: return getVTList(VTs[0]); + case 2: return getVTList(VTs[0], VTs[1]); + case 3: return getVTList(VTs[0], VTs[1], VTs[2]); + default: break; + } + + for (std::vector::reverse_iterator I = VTList.rbegin(), + E = VTList.rend(); I != E; ++I) { + if (I->NumVTs != NumVTs || VTs[0] != I->VTs[0] || VTs[1] != I->VTs[1]) + continue; + + bool NoMatch = false; + for (unsigned i = 2; i != NumVTs; ++i) + if (VTs[i] != I->VTs[i]) { + NoMatch = true; + break; + } + if (!NoMatch) + return *I; + } + + EVT *Array = Allocator.Allocate(NumVTs); + std::copy(VTs, VTs+NumVTs, Array); + SDVTList Result = makeVTList(Array, NumVTs); + VTList.push_back(Result); + return Result; +} + + +/// UpdateNodeOperands - *Mutate* the specified node in-place to have the +/// specified operands. If the resultant node already exists in the DAG, +/// this does not modify the specified node, instead it returns the node that +/// already exists. If the resultant node does not exist in the DAG, the +/// input node is returned. As a degenerate case, if you specify the same +/// input operands as the node already has, the input node is returned. +SDValue SelectionDAG::UpdateNodeOperands(SDValue InN, SDValue Op) { + SDNode *N = InN.getNode(); + assert(N->getNumOperands() == 1 && "Update with wrong number of operands"); + + // Check to see if there is no change. + if (Op == N->getOperand(0)) return InN; + + // See if the modified node already exists. + void *InsertPos = 0; + if (SDNode *Existing = FindModifiedNodeSlot(N, Op, InsertPos)) + return SDValue(Existing, InN.getResNo()); + + // Nope it doesn't. Remove the node from its current place in the maps. + if (InsertPos) + if (!RemoveNodeFromCSEMaps(N)) + InsertPos = 0; + + // Now we update the operands. + N->OperandList[0].set(Op); + + // If this gets put into a CSE map, add it. + if (InsertPos) CSEMap.InsertNode(N, InsertPos); + return InN; +} + +SDValue SelectionDAG:: +UpdateNodeOperands(SDValue InN, SDValue Op1, SDValue Op2) { + SDNode *N = InN.getNode(); + assert(N->getNumOperands() == 2 && "Update with wrong number of operands"); + + // Check to see if there is no change. + if (Op1 == N->getOperand(0) && Op2 == N->getOperand(1)) + return InN; // No operands changed, just return the input node. + + // See if the modified node already exists. + void *InsertPos = 0; + if (SDNode *Existing = FindModifiedNodeSlot(N, Op1, Op2, InsertPos)) + return SDValue(Existing, InN.getResNo()); + + // Nope it doesn't. Remove the node from its current place in the maps. + if (InsertPos) + if (!RemoveNodeFromCSEMaps(N)) + InsertPos = 0; + + // Now we update the operands. + if (N->OperandList[0] != Op1) + N->OperandList[0].set(Op1); + if (N->OperandList[1] != Op2) + N->OperandList[1].set(Op2); + + // If this gets put into a CSE map, add it. + if (InsertPos) CSEMap.InsertNode(N, InsertPos); + return InN; +} + +SDValue SelectionDAG:: +UpdateNodeOperands(SDValue N, SDValue Op1, SDValue Op2, SDValue Op3) { + SDValue Ops[] = { Op1, Op2, Op3 }; + return UpdateNodeOperands(N, Ops, 3); +} + +SDValue SelectionDAG:: +UpdateNodeOperands(SDValue N, SDValue Op1, SDValue Op2, + SDValue Op3, SDValue Op4) { + SDValue Ops[] = { Op1, Op2, Op3, Op4 }; + return UpdateNodeOperands(N, Ops, 4); +} + +SDValue SelectionDAG:: +UpdateNodeOperands(SDValue N, SDValue Op1, SDValue Op2, + SDValue Op3, SDValue Op4, SDValue Op5) { + SDValue Ops[] = { Op1, Op2, Op3, Op4, Op5 }; + return UpdateNodeOperands(N, Ops, 5); +} + +SDValue SelectionDAG:: +UpdateNodeOperands(SDValue InN, const SDValue *Ops, unsigned NumOps) { + SDNode *N = InN.getNode(); + assert(N->getNumOperands() == NumOps && + "Update with wrong number of operands"); + + // Check to see if there is no change. + bool AnyChange = false; + for (unsigned i = 0; i != NumOps; ++i) { + if (Ops[i] != N->getOperand(i)) { + AnyChange = true; + break; + } + } + + // No operands changed, just return the input node. + if (!AnyChange) return InN; + + // See if the modified node already exists. + void *InsertPos = 0; + if (SDNode *Existing = FindModifiedNodeSlot(N, Ops, NumOps, InsertPos)) + return SDValue(Existing, InN.getResNo()); + + // Nope it doesn't. Remove the node from its current place in the maps. + if (InsertPos) + if (!RemoveNodeFromCSEMaps(N)) + InsertPos = 0; + + // Now we update the operands. + for (unsigned i = 0; i != NumOps; ++i) + if (N->OperandList[i] != Ops[i]) + N->OperandList[i].set(Ops[i]); + + // If this gets put into a CSE map, add it. + if (InsertPos) CSEMap.InsertNode(N, InsertPos); + return InN; +} + +/// DropOperands - Release the operands and set this node to have +/// zero operands. +void SDNode::DropOperands() { + // Unlike the code in MorphNodeTo that does this, we don't need to + // watch for dead nodes here. + for (op_iterator I = op_begin(), E = op_end(); I != E; ) { + SDUse &Use = *I++; + Use.set(SDValue()); + } +} + +/// SelectNodeTo - These are wrappers around MorphNodeTo that accept a +/// machine opcode. +/// +SDNode *SelectionDAG::SelectNodeTo(SDNode *N, unsigned MachineOpc, + EVT VT) { + SDVTList VTs = getVTList(VT); + return SelectNodeTo(N, MachineOpc, VTs, 0, 0); +} + +SDNode *SelectionDAG::SelectNodeTo(SDNode *N, unsigned MachineOpc, + EVT VT, SDValue Op1) { + SDVTList VTs = getVTList(VT); + SDValue Ops[] = { Op1 }; + return SelectNodeTo(N, MachineOpc, VTs, Ops, 1); +} + +SDNode *SelectionDAG::SelectNodeTo(SDNode *N, unsigned MachineOpc, + EVT VT, SDValue Op1, + SDValue Op2) { + SDVTList VTs = getVTList(VT); + SDValue Ops[] = { Op1, Op2 }; + return SelectNodeTo(N, MachineOpc, VTs, Ops, 2); +} + +SDNode *SelectionDAG::SelectNodeTo(SDNode *N, unsigned MachineOpc, + EVT VT, SDValue Op1, + SDValue Op2, SDValue Op3) { + SDVTList VTs = getVTList(VT); + SDValue Ops[] = { Op1, Op2, Op3 }; + return SelectNodeTo(N, MachineOpc, VTs, Ops, 3); +} + +SDNode *SelectionDAG::SelectNodeTo(SDNode *N, unsigned MachineOpc, + EVT VT, const SDValue *Ops, + unsigned NumOps) { + SDVTList VTs = getVTList(VT); + return SelectNodeTo(N, MachineOpc, VTs, Ops, NumOps); +} + +SDNode *SelectionDAG::SelectNodeTo(SDNode *N, unsigned MachineOpc, + EVT VT1, EVT VT2, const SDValue *Ops, + unsigned NumOps) { + SDVTList VTs = getVTList(VT1, VT2); + return SelectNodeTo(N, MachineOpc, VTs, Ops, NumOps); +} + +SDNode *SelectionDAG::SelectNodeTo(SDNode *N, unsigned MachineOpc, + EVT VT1, EVT VT2) { + SDVTList VTs = getVTList(VT1, VT2); + return SelectNodeTo(N, MachineOpc, VTs, (SDValue *)0, 0); +} + +SDNode *SelectionDAG::SelectNodeTo(SDNode *N, unsigned MachineOpc, + EVT VT1, EVT VT2, EVT VT3, + const SDValue *Ops, unsigned NumOps) { + SDVTList VTs = getVTList(VT1, VT2, VT3); + return SelectNodeTo(N, MachineOpc, VTs, Ops, NumOps); +} + +SDNode *SelectionDAG::SelectNodeTo(SDNode *N, unsigned MachineOpc, + EVT VT1, EVT VT2, EVT VT3, EVT VT4, + const SDValue *Ops, unsigned NumOps) { + SDVTList VTs = getVTList(VT1, VT2, VT3, VT4); + return SelectNodeTo(N, MachineOpc, VTs, Ops, NumOps); +} + +SDNode *SelectionDAG::SelectNodeTo(SDNode *N, unsigned MachineOpc, + EVT VT1, EVT VT2, + SDValue Op1) { + SDVTList VTs = getVTList(VT1, VT2); + SDValue Ops[] = { Op1 }; + return SelectNodeTo(N, MachineOpc, VTs, Ops, 1); +} + +SDNode *SelectionDAG::SelectNodeTo(SDNode *N, unsigned MachineOpc, + EVT VT1, EVT VT2, + SDValue Op1, SDValue Op2) { + SDVTList VTs = getVTList(VT1, VT2); + SDValue Ops[] = { Op1, Op2 }; + return SelectNodeTo(N, MachineOpc, VTs, Ops, 2); +} + +SDNode *SelectionDAG::SelectNodeTo(SDNode *N, unsigned MachineOpc, + EVT VT1, EVT VT2, + SDValue Op1, SDValue Op2, + SDValue Op3) { + SDVTList VTs = getVTList(VT1, VT2); + SDValue Ops[] = { Op1, Op2, Op3 }; + return SelectNodeTo(N, MachineOpc, VTs, Ops, 3); +} + +SDNode *SelectionDAG::SelectNodeTo(SDNode *N, unsigned MachineOpc, + EVT VT1, EVT VT2, EVT VT3, + SDValue Op1, SDValue Op2, + SDValue Op3) { + SDVTList VTs = getVTList(VT1, VT2, VT3); + SDValue Ops[] = { Op1, Op2, Op3 }; + return SelectNodeTo(N, MachineOpc, VTs, Ops, 3); +} + +SDNode *SelectionDAG::SelectNodeTo(SDNode *N, unsigned MachineOpc, + SDVTList VTs, const SDValue *Ops, + unsigned NumOps) { + return MorphNodeTo(N, ~MachineOpc, VTs, Ops, NumOps); +} + +SDNode *SelectionDAG::MorphNodeTo(SDNode *N, unsigned Opc, + EVT VT) { + SDVTList VTs = getVTList(VT); + return MorphNodeTo(N, Opc, VTs, 0, 0); +} + +SDNode *SelectionDAG::MorphNodeTo(SDNode *N, unsigned Opc, + EVT VT, SDValue Op1) { + SDVTList VTs = getVTList(VT); + SDValue Ops[] = { Op1 }; + return MorphNodeTo(N, Opc, VTs, Ops, 1); +} + +SDNode *SelectionDAG::MorphNodeTo(SDNode *N, unsigned Opc, + EVT VT, SDValue Op1, + SDValue Op2) { + SDVTList VTs = getVTList(VT); + SDValue Ops[] = { Op1, Op2 }; + return MorphNodeTo(N, Opc, VTs, Ops, 2); +} + +SDNode *SelectionDAG::MorphNodeTo(SDNode *N, unsigned Opc, + EVT VT, SDValue Op1, + SDValue Op2, SDValue Op3) { + SDVTList VTs = getVTList(VT); + SDValue Ops[] = { Op1, Op2, Op3 }; + return MorphNodeTo(N, Opc, VTs, Ops, 3); +} + +SDNode *SelectionDAG::MorphNodeTo(SDNode *N, unsigned Opc, + EVT VT, const SDValue *Ops, + unsigned NumOps) { + SDVTList VTs = getVTList(VT); + return MorphNodeTo(N, Opc, VTs, Ops, NumOps); +} + +SDNode *SelectionDAG::MorphNodeTo(SDNode *N, unsigned Opc, + EVT VT1, EVT VT2, const SDValue *Ops, + unsigned NumOps) { + SDVTList VTs = getVTList(VT1, VT2); + return MorphNodeTo(N, Opc, VTs, Ops, NumOps); +} + +SDNode *SelectionDAG::MorphNodeTo(SDNode *N, unsigned Opc, + EVT VT1, EVT VT2) { + SDVTList VTs = getVTList(VT1, VT2); + return MorphNodeTo(N, Opc, VTs, (SDValue *)0, 0); +} + +SDNode *SelectionDAG::MorphNodeTo(SDNode *N, unsigned Opc, + EVT VT1, EVT VT2, EVT VT3, + const SDValue *Ops, unsigned NumOps) { + SDVTList VTs = getVTList(VT1, VT2, VT3); + return MorphNodeTo(N, Opc, VTs, Ops, NumOps); +} + +SDNode *SelectionDAG::MorphNodeTo(SDNode *N, unsigned Opc, + EVT VT1, EVT VT2, + SDValue Op1) { + SDVTList VTs = getVTList(VT1, VT2); + SDValue Ops[] = { Op1 }; + return MorphNodeTo(N, Opc, VTs, Ops, 1); +} + +SDNode *SelectionDAG::MorphNodeTo(SDNode *N, unsigned Opc, + EVT VT1, EVT VT2, + SDValue Op1, SDValue Op2) { + SDVTList VTs = getVTList(VT1, VT2); + SDValue Ops[] = { Op1, Op2 }; + return MorphNodeTo(N, Opc, VTs, Ops, 2); +} + +SDNode *SelectionDAG::MorphNodeTo(SDNode *N, unsigned Opc, + EVT VT1, EVT VT2, + SDValue Op1, SDValue Op2, + SDValue Op3) { + SDVTList VTs = getVTList(VT1, VT2); + SDValue Ops[] = { Op1, Op2, Op3 }; + return MorphNodeTo(N, Opc, VTs, Ops, 3); +} + +/// MorphNodeTo - These *mutate* the specified node to have the specified +/// return type, opcode, and operands. +/// +/// Note that MorphNodeTo returns the resultant node. If there is already a +/// node of the specified opcode and operands, it returns that node instead of +/// the current one. Note that the DebugLoc need not be the same. +/// +/// Using MorphNodeTo is faster than creating a new node and swapping it in +/// with ReplaceAllUsesWith both because it often avoids allocating a new +/// node, and because it doesn't require CSE recalculation for any of +/// the node's users. +/// +SDNode *SelectionDAG::MorphNodeTo(SDNode *N, unsigned Opc, + SDVTList VTs, const SDValue *Ops, + unsigned NumOps) { + // If an identical node already exists, use it. + void *IP = 0; + if (VTs.VTs[VTs.NumVTs-1] != MVT::Flag) { + FoldingSetNodeID ID; + AddNodeIDNode(ID, Opc, VTs, Ops, NumOps); + if (SDNode *ON = CSEMap.FindNodeOrInsertPos(ID, IP)) + return ON; + } + + if (!RemoveNodeFromCSEMaps(N)) + IP = 0; + + // Start the morphing. + N->NodeType = Opc; + N->ValueList = VTs.VTs; + N->NumValues = VTs.NumVTs; + + // Clear the operands list, updating used nodes to remove this from their + // use list. Keep track of any operands that become dead as a result. + SmallPtrSet DeadNodeSet; + for (SDNode::op_iterator I = N->op_begin(), E = N->op_end(); I != E; ) { + SDUse &Use = *I++; + SDNode *Used = Use.getNode(); + Use.set(SDValue()); + if (Used->use_empty()) + DeadNodeSet.insert(Used); + } + + if (MachineSDNode *MN = dyn_cast(N)) { + // Initialize the memory references information. + MN->setMemRefs(0, 0); + // If NumOps is larger than the # of operands we can have in a + // MachineSDNode, reallocate the operand list. + if (NumOps > MN->NumOperands || !MN->OperandsNeedDelete) { + if (MN->OperandsNeedDelete) + delete[] MN->OperandList; + if (NumOps > array_lengthof(MN->LocalOperands)) + // We're creating a final node that will live unmorphed for the + // remainder of the current SelectionDAG iteration, so we can allocate + // the operands directly out of a pool with no recycling metadata. + MN->InitOperands(OperandAllocator.Allocate(NumOps), + Ops, NumOps); + else + MN->InitOperands(MN->LocalOperands, Ops, NumOps); + MN->OperandsNeedDelete = false; + } else + MN->InitOperands(MN->OperandList, Ops, NumOps); + } else { + // If NumOps is larger than the # of operands we currently have, reallocate + // the operand list. + if (NumOps > N->NumOperands) { + if (N->OperandsNeedDelete) + delete[] N->OperandList; + N->InitOperands(new SDUse[NumOps], Ops, NumOps); + N->OperandsNeedDelete = true; + } else + N->InitOperands(N->OperandList, Ops, NumOps); + } + + // Delete any nodes that are still dead after adding the uses for the + // new operands. + SmallVector DeadNodes; + for (SmallPtrSet::iterator I = DeadNodeSet.begin(), + E = DeadNodeSet.end(); I != E; ++I) + if ((*I)->use_empty()) + DeadNodes.push_back(*I); + RemoveDeadNodes(DeadNodes); + + if (IP) + CSEMap.InsertNode(N, IP); // Memoize the new node. + return N; +} + + +/// getMachineNode - These are used for target selectors to create a new node +/// with specified return type(s), MachineInstr opcode, and operands. +/// +/// Note that getMachineNode returns the resultant node. If there is already a +/// node of the specified opcode and operands, it returns that node instead of +/// the current one. +MachineSDNode * +SelectionDAG::getMachineNode(unsigned Opcode, DebugLoc dl, EVT VT) { + SDVTList VTs = getVTList(VT); + return getMachineNode(Opcode, dl, VTs, 0, 0); +} + +MachineSDNode * +SelectionDAG::getMachineNode(unsigned Opcode, DebugLoc dl, EVT VT, SDValue Op1) { + SDVTList VTs = getVTList(VT); + SDValue Ops[] = { Op1 }; + return getMachineNode(Opcode, dl, VTs, Ops, array_lengthof(Ops)); +} + +MachineSDNode * +SelectionDAG::getMachineNode(unsigned Opcode, DebugLoc dl, EVT VT, + SDValue Op1, SDValue Op2) { + SDVTList VTs = getVTList(VT); + SDValue Ops[] = { Op1, Op2 }; + return getMachineNode(Opcode, dl, VTs, Ops, array_lengthof(Ops)); +} + +MachineSDNode * +SelectionDAG::getMachineNode(unsigned Opcode, DebugLoc dl, EVT VT, + SDValue Op1, SDValue Op2, SDValue Op3) { + SDVTList VTs = getVTList(VT); + SDValue Ops[] = { Op1, Op2, Op3 }; + return getMachineNode(Opcode, dl, VTs, Ops, array_lengthof(Ops)); +} + +MachineSDNode * +SelectionDAG::getMachineNode(unsigned Opcode, DebugLoc dl, EVT VT, + const SDValue *Ops, unsigned NumOps) { + SDVTList VTs = getVTList(VT); + return getMachineNode(Opcode, dl, VTs, Ops, NumOps); +} + +MachineSDNode * +SelectionDAG::getMachineNode(unsigned Opcode, DebugLoc dl, EVT VT1, EVT VT2) { + SDVTList VTs = getVTList(VT1, VT2); + return getMachineNode(Opcode, dl, VTs, 0, 0); +} + +MachineSDNode * +SelectionDAG::getMachineNode(unsigned Opcode, DebugLoc dl, + EVT VT1, EVT VT2, SDValue Op1) { + SDVTList VTs = getVTList(VT1, VT2); + SDValue Ops[] = { Op1 }; + return getMachineNode(Opcode, dl, VTs, Ops, array_lengthof(Ops)); +} + +MachineSDNode * +SelectionDAG::getMachineNode(unsigned Opcode, DebugLoc dl, + EVT VT1, EVT VT2, SDValue Op1, SDValue Op2) { + SDVTList VTs = getVTList(VT1, VT2); + SDValue Ops[] = { Op1, Op2 }; + return getMachineNode(Opcode, dl, VTs, Ops, array_lengthof(Ops)); +} + +MachineSDNode * +SelectionDAG::getMachineNode(unsigned Opcode, DebugLoc dl, + EVT VT1, EVT VT2, SDValue Op1, + SDValue Op2, SDValue Op3) { + SDVTList VTs = getVTList(VT1, VT2); + SDValue Ops[] = { Op1, Op2, Op3 }; + return getMachineNode(Opcode, dl, VTs, Ops, array_lengthof(Ops)); +} + +MachineSDNode * +SelectionDAG::getMachineNode(unsigned Opcode, DebugLoc dl, + EVT VT1, EVT VT2, + const SDValue *Ops, unsigned NumOps) { + SDVTList VTs = getVTList(VT1, VT2); + return getMachineNode(Opcode, dl, VTs, Ops, NumOps); +} + +MachineSDNode * +SelectionDAG::getMachineNode(unsigned Opcode, DebugLoc dl, + EVT VT1, EVT VT2, EVT VT3, + SDValue Op1, SDValue Op2) { + SDVTList VTs = getVTList(VT1, VT2, VT3); + SDValue Ops[] = { Op1, Op2 }; + return getMachineNode(Opcode, dl, VTs, Ops, array_lengthof(Ops)); +} + +MachineSDNode * +SelectionDAG::getMachineNode(unsigned Opcode, DebugLoc dl, + EVT VT1, EVT VT2, EVT VT3, + SDValue Op1, SDValue Op2, SDValue Op3) { + SDVTList VTs = getVTList(VT1, VT2, VT3); + SDValue Ops[] = { Op1, Op2, Op3 }; + return getMachineNode(Opcode, dl, VTs, Ops, array_lengthof(Ops)); +} + +MachineSDNode * +SelectionDAG::getMachineNode(unsigned Opcode, DebugLoc dl, + EVT VT1, EVT VT2, EVT VT3, + const SDValue *Ops, unsigned NumOps) { + SDVTList VTs = getVTList(VT1, VT2, VT3); + return getMachineNode(Opcode, dl, VTs, Ops, NumOps); +} + +MachineSDNode * +SelectionDAG::getMachineNode(unsigned Opcode, DebugLoc dl, EVT VT1, + EVT VT2, EVT VT3, EVT VT4, + const SDValue *Ops, unsigned NumOps) { + SDVTList VTs = getVTList(VT1, VT2, VT3, VT4); + return getMachineNode(Opcode, dl, VTs, Ops, NumOps); +} + +MachineSDNode * +SelectionDAG::getMachineNode(unsigned Opcode, DebugLoc dl, + const std::vector &ResultTys, + const SDValue *Ops, unsigned NumOps) { + SDVTList VTs = getVTList(&ResultTys[0], ResultTys.size()); + return getMachineNode(Opcode, dl, VTs, Ops, NumOps); +} + +MachineSDNode * +SelectionDAG::getMachineNode(unsigned Opcode, DebugLoc DL, SDVTList VTs, + const SDValue *Ops, unsigned NumOps) { + bool DoCSE = VTs.VTs[VTs.NumVTs-1] != MVT::Flag; + MachineSDNode *N; + void *IP; + + if (DoCSE) { + FoldingSetNodeID ID; + AddNodeIDNode(ID, ~Opcode, VTs, Ops, NumOps); + IP = 0; + if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) + return cast(E); + } + + // Allocate a new MachineSDNode. + N = NodeAllocator.Allocate(); + new (N) MachineSDNode(~Opcode, DL, VTs); + + // Initialize the operands list. + if (NumOps > array_lengthof(N->LocalOperands)) + // We're creating a final node that will live unmorphed for the + // remainder of the current SelectionDAG iteration, so we can allocate + // the operands directly out of a pool with no recycling metadata. + N->InitOperands(OperandAllocator.Allocate(NumOps), + Ops, NumOps); + else + N->InitOperands(N->LocalOperands, Ops, NumOps); + N->OperandsNeedDelete = false; + + if (DoCSE) + CSEMap.InsertNode(N, IP); + + AllNodes.push_back(N); +#ifndef NDEBUG + VerifyNode(N); +#endif + return N; +} + +/// getTargetExtractSubreg - A convenience function for creating +/// TargetInstrInfo::EXTRACT_SUBREG nodes. +SDValue +SelectionDAG::getTargetExtractSubreg(int SRIdx, DebugLoc DL, EVT VT, + SDValue Operand) { + SDValue SRIdxVal = getTargetConstant(SRIdx, MVT::i32); + SDNode *Subreg = getMachineNode(TargetInstrInfo::EXTRACT_SUBREG, DL, + VT, Operand, SRIdxVal); + return SDValue(Subreg, 0); +} + +/// getTargetInsertSubreg - A convenience function for creating +/// TargetInstrInfo::INSERT_SUBREG nodes. +SDValue +SelectionDAG::getTargetInsertSubreg(int SRIdx, DebugLoc DL, EVT VT, + SDValue Operand, SDValue Subreg) { + SDValue SRIdxVal = getTargetConstant(SRIdx, MVT::i32); + SDNode *Result = getMachineNode(TargetInstrInfo::INSERT_SUBREG, DL, + VT, Operand, Subreg, SRIdxVal); + return SDValue(Result, 0); +} + +/// getNodeIfExists - Get the specified node if it's already available, or +/// else return NULL. +SDNode *SelectionDAG::getNodeIfExists(unsigned Opcode, SDVTList VTList, + const SDValue *Ops, unsigned NumOps) { + if (VTList.VTs[VTList.NumVTs-1] != MVT::Flag) { + FoldingSetNodeID ID; + AddNodeIDNode(ID, Opcode, VTList, Ops, NumOps); + void *IP = 0; + if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) + return E; + } + return NULL; +} + +/// ReplaceAllUsesWith - Modify anything using 'From' to use 'To' instead. +/// This can cause recursive merging of nodes in the DAG. +/// +/// This version assumes From has a single result value. +/// +void SelectionDAG::ReplaceAllUsesWith(SDValue FromN, SDValue To, + DAGUpdateListener *UpdateListener) { + SDNode *From = FromN.getNode(); + assert(From->getNumValues() == 1 && FromN.getResNo() == 0 && + "Cannot replace with this method!"); + assert(From != To.getNode() && "Cannot replace uses of with self"); + + // Iterate over all the existing uses of From. New uses will be added + // to the beginning of the use list, which we avoid visiting. + // This specifically avoids visiting uses of From that arise while the + // replacement is happening, because any such uses would be the result + // of CSE: If an existing node looks like From after one of its operands + // is replaced by To, we don't want to replace of all its users with To + // too. See PR3018 for more info. + SDNode::use_iterator UI = From->use_begin(), UE = From->use_end(); + while (UI != UE) { + SDNode *User = *UI; + + // This node is about to morph, remove its old self from the CSE maps. + RemoveNodeFromCSEMaps(User); + + // A user can appear in a use list multiple times, and when this + // happens the uses are usually next to each other in the list. + // To help reduce the number of CSE recomputations, process all + // the uses of this user that we can find this way. + do { + SDUse &Use = UI.getUse(); + ++UI; + Use.set(To); + } while (UI != UE && *UI == User); + + // Now that we have modified User, add it back to the CSE maps. If it + // already exists there, recursively merge the results together. + AddModifiedNodeToCSEMaps(User, UpdateListener); + } +} + +/// ReplaceAllUsesWith - Modify anything using 'From' to use 'To' instead. +/// This can cause recursive merging of nodes in the DAG. +/// +/// This version assumes that for each value of From, there is a +/// corresponding value in To in the same position with the same type. +/// +void SelectionDAG::ReplaceAllUsesWith(SDNode *From, SDNode *To, + DAGUpdateListener *UpdateListener) { +#ifndef NDEBUG + for (unsigned i = 0, e = From->getNumValues(); i != e; ++i) + assert((!From->hasAnyUseOfValue(i) || + From->getValueType(i) == To->getValueType(i)) && + "Cannot use this version of ReplaceAllUsesWith!"); +#endif + + // Handle the trivial case. + if (From == To) + return; + + // Iterate over just the existing users of From. See the comments in + // the ReplaceAllUsesWith above. + SDNode::use_iterator UI = From->use_begin(), UE = From->use_end(); + while (UI != UE) { + SDNode *User = *UI; + + // This node is about to morph, remove its old self from the CSE maps. + RemoveNodeFromCSEMaps(User); + + // A user can appear in a use list multiple times, and when this + // happens the uses are usually next to each other in the list. + // To help reduce the number of CSE recomputations, process all + // the uses of this user that we can find this way. + do { + SDUse &Use = UI.getUse(); + ++UI; + Use.setNode(To); + } while (UI != UE && *UI == User); + + // Now that we have modified User, add it back to the CSE maps. If it + // already exists there, recursively merge the results together. + AddModifiedNodeToCSEMaps(User, UpdateListener); + } +} + +/// ReplaceAllUsesWith - Modify anything using 'From' to use 'To' instead. +/// This can cause recursive merging of nodes in the DAG. +/// +/// This version can replace From with any result values. To must match the +/// number and types of values returned by From. +void SelectionDAG::ReplaceAllUsesWith(SDNode *From, + const SDValue *To, + DAGUpdateListener *UpdateListener) { + if (From->getNumValues() == 1) // Handle the simple case efficiently. + return ReplaceAllUsesWith(SDValue(From, 0), To[0], UpdateListener); + + // Iterate over just the existing users of From. See the comments in + // the ReplaceAllUsesWith above. + SDNode::use_iterator UI = From->use_begin(), UE = From->use_end(); + while (UI != UE) { + SDNode *User = *UI; + + // This node is about to morph, remove its old self from the CSE maps. + RemoveNodeFromCSEMaps(User); + + // A user can appear in a use list multiple times, and when this + // happens the uses are usually next to each other in the list. + // To help reduce the number of CSE recomputations, process all + // the uses of this user that we can find this way. + do { + SDUse &Use = UI.getUse(); + const SDValue &ToOp = To[Use.getResNo()]; + ++UI; + Use.set(ToOp); + } while (UI != UE && *UI == User); + + // Now that we have modified User, add it back to the CSE maps. If it + // already exists there, recursively merge the results together. + AddModifiedNodeToCSEMaps(User, UpdateListener); + } +} + +/// ReplaceAllUsesOfValueWith - Replace any uses of From with To, leaving +/// uses of other values produced by From.getNode() alone. The Deleted +/// vector is handled the same way as for ReplaceAllUsesWith. +void SelectionDAG::ReplaceAllUsesOfValueWith(SDValue From, SDValue To, + DAGUpdateListener *UpdateListener){ + // Handle the really simple, really trivial case efficiently. + if (From == To) return; + + // Handle the simple, trivial, case efficiently. + if (From.getNode()->getNumValues() == 1) { + ReplaceAllUsesWith(From, To, UpdateListener); + return; + } + + // Iterate over just the existing users of From. See the comments in + // the ReplaceAllUsesWith above. + SDNode::use_iterator UI = From.getNode()->use_begin(), + UE = From.getNode()->use_end(); + while (UI != UE) { + SDNode *User = *UI; + bool UserRemovedFromCSEMaps = false; + + // A user can appear in a use list multiple times, and when this + // happens the uses are usually next to each other in the list. + // To help reduce the number of CSE recomputations, process all + // the uses of this user that we can find this way. + do { + SDUse &Use = UI.getUse(); + + // Skip uses of different values from the same node. + if (Use.getResNo() != From.getResNo()) { + ++UI; + continue; + } + + // If this node hasn't been modified yet, it's still in the CSE maps, + // so remove its old self from the CSE maps. + if (!UserRemovedFromCSEMaps) { + RemoveNodeFromCSEMaps(User); + UserRemovedFromCSEMaps = true; + } + + ++UI; + Use.set(To); + } while (UI != UE && *UI == User); + + // We are iterating over all uses of the From node, so if a use + // doesn't use the specific value, no changes are made. + if (!UserRemovedFromCSEMaps) + continue; + + // Now that we have modified User, add it back to the CSE maps. If it + // already exists there, recursively merge the results together. + AddModifiedNodeToCSEMaps(User, UpdateListener); + } +} + +namespace { + /// UseMemo - This class is used by SelectionDAG::ReplaceAllUsesOfValuesWith + /// to record information about a use. + struct UseMemo { + SDNode *User; + unsigned Index; + SDUse *Use; + }; + + /// operator< - Sort Memos by User. + bool operator<(const UseMemo &L, const UseMemo &R) { + return (intptr_t)L.User < (intptr_t)R.User; + } +} + +/// ReplaceAllUsesOfValuesWith - Replace any uses of From with To, leaving +/// uses of other values produced by From.getNode() alone. The same value +/// may appear in both the From and To list. The Deleted vector is +/// handled the same way as for ReplaceAllUsesWith. +void SelectionDAG::ReplaceAllUsesOfValuesWith(const SDValue *From, + const SDValue *To, + unsigned Num, + DAGUpdateListener *UpdateListener){ + // Handle the simple, trivial case efficiently. + if (Num == 1) + return ReplaceAllUsesOfValueWith(*From, *To, UpdateListener); + + // Read up all the uses and make records of them. This helps + // processing new uses that are introduced during the + // replacement process. + SmallVector Uses; + for (unsigned i = 0; i != Num; ++i) { + unsigned FromResNo = From[i].getResNo(); + SDNode *FromNode = From[i].getNode(); + for (SDNode::use_iterator UI = FromNode->use_begin(), + E = FromNode->use_end(); UI != E; ++UI) { + SDUse &Use = UI.getUse(); + if (Use.getResNo() == FromResNo) { + UseMemo Memo = { *UI, i, &Use }; + Uses.push_back(Memo); + } + } + } + + // Sort the uses, so that all the uses from a given User are together. + std::sort(Uses.begin(), Uses.end()); + + for (unsigned UseIndex = 0, UseIndexEnd = Uses.size(); + UseIndex != UseIndexEnd; ) { + // We know that this user uses some value of From. If it is the right + // value, update it. + SDNode *User = Uses[UseIndex].User; + + // This node is about to morph, remove its old self from the CSE maps. + RemoveNodeFromCSEMaps(User); + + // The Uses array is sorted, so all the uses for a given User + // are next to each other in the list. + // To help reduce the number of CSE recomputations, process all + // the uses of this user that we can find this way. + do { + unsigned i = Uses[UseIndex].Index; + SDUse &Use = *Uses[UseIndex].Use; + ++UseIndex; + + Use.set(To[i]); + } while (UseIndex != UseIndexEnd && Uses[UseIndex].User == User); + + // Now that we have modified User, add it back to the CSE maps. If it + // already exists there, recursively merge the results together. + AddModifiedNodeToCSEMaps(User, UpdateListener); + } +} + +/// AssignTopologicalOrder - Assign a unique node id for each node in the DAG +/// based on their topological order. It returns the maximum id and a vector +/// of the SDNodes* in assigned order by reference. +unsigned SelectionDAG::AssignTopologicalOrder() { + + unsigned DAGSize = 0; + + // SortedPos tracks the progress of the algorithm. Nodes before it are + // sorted, nodes after it are unsorted. When the algorithm completes + // it is at the end of the list. + allnodes_iterator SortedPos = allnodes_begin(); + + // Visit all the nodes. Move nodes with no operands to the front of + // the list immediately. Annotate nodes that do have operands with their + // operand count. Before we do this, the Node Id fields of the nodes + // may contain arbitrary values. After, the Node Id fields for nodes + // before SortedPos will contain the topological sort index, and the + // Node Id fields for nodes At SortedPos and after will contain the + // count of outstanding operands. + for (allnodes_iterator I = allnodes_begin(),E = allnodes_end(); I != E; ) { + SDNode *N = I++; + unsigned Degree = N->getNumOperands(); + if (Degree == 0) { + // A node with no uses, add it to the result array immediately. + N->setNodeId(DAGSize++); + allnodes_iterator Q = N; + if (Q != SortedPos) + SortedPos = AllNodes.insert(SortedPos, AllNodes.remove(Q)); + ++SortedPos; + } else { + // Temporarily use the Node Id as scratch space for the degree count. + N->setNodeId(Degree); + } + } + + // Visit all the nodes. As we iterate, moves nodes into sorted order, + // such that by the time the end is reached all nodes will be sorted. + for (allnodes_iterator I = allnodes_begin(),E = allnodes_end(); I != E; ++I) { + SDNode *N = I; + for (SDNode::use_iterator UI = N->use_begin(), UE = N->use_end(); + UI != UE; ++UI) { + SDNode *P = *UI; + unsigned Degree = P->getNodeId(); + --Degree; + if (Degree == 0) { + // All of P's operands are sorted, so P may sorted now. + P->setNodeId(DAGSize++); + if (P != SortedPos) + SortedPos = AllNodes.insert(SortedPos, AllNodes.remove(P)); + ++SortedPos; + } else { + // Update P's outstanding operand count. + P->setNodeId(Degree); + } + } + } + + assert(SortedPos == AllNodes.end() && + "Topological sort incomplete!"); + assert(AllNodes.front().getOpcode() == ISD::EntryToken && + "First node in topological sort is not the entry token!"); + assert(AllNodes.front().getNodeId() == 0 && + "First node in topological sort has non-zero id!"); + assert(AllNodes.front().getNumOperands() == 0 && + "First node in topological sort has operands!"); + assert(AllNodes.back().getNodeId() == (int)DAGSize-1 && + "Last node in topologic sort has unexpected id!"); + assert(AllNodes.back().use_empty() && + "Last node in topologic sort has users!"); + assert(DAGSize == allnodes_size() && "Node count mismatch!"); + return DAGSize; +} + + + +//===----------------------------------------------------------------------===// +// SDNode Class +//===----------------------------------------------------------------------===// + +HandleSDNode::~HandleSDNode() { + DropOperands(); +} + +GlobalAddressSDNode::GlobalAddressSDNode(unsigned Opc, const GlobalValue *GA, + EVT VT, int64_t o, unsigned char TF) + : SDNode(Opc, DebugLoc::getUnknownLoc(), getSDVTList(VT)), + Offset(o), TargetFlags(TF) { + TheGlobal = const_cast(GA); +} + +MemSDNode::MemSDNode(unsigned Opc, DebugLoc dl, SDVTList VTs, EVT memvt, + MachineMemOperand *mmo) + : SDNode(Opc, dl, VTs), MemoryVT(memvt), MMO(mmo) { + SubclassData = encodeMemSDNodeFlags(0, ISD::UNINDEXED, MMO->isVolatile()); + assert(isVolatile() == MMO->isVolatile() && "Volatile encoding error!"); + assert(memvt.getStoreSize() == MMO->getSize() && "Size mismatch!"); +} + +MemSDNode::MemSDNode(unsigned Opc, DebugLoc dl, SDVTList VTs, + const SDValue *Ops, unsigned NumOps, EVT memvt, + MachineMemOperand *mmo) + : SDNode(Opc, dl, VTs, Ops, NumOps), + MemoryVT(memvt), MMO(mmo) { + SubclassData = encodeMemSDNodeFlags(0, ISD::UNINDEXED, MMO->isVolatile()); + assert(isVolatile() == MMO->isVolatile() && "Volatile encoding error!"); + assert(memvt.getStoreSize() == MMO->getSize() && "Size mismatch!"); +} + +/// Profile - Gather unique data for the node. +/// +void SDNode::Profile(FoldingSetNodeID &ID) const { + AddNodeIDNode(ID, this); +} + +namespace { + struct EVTArray { + std::vector VTs; + + EVTArray() { + VTs.reserve(MVT::LAST_VALUETYPE); + for (unsigned i = 0; i < MVT::LAST_VALUETYPE; ++i) + VTs.push_back(MVT((MVT::SimpleValueType)i)); + } + }; +} + +static ManagedStatic > EVTs; +static ManagedStatic SimpleVTArray; +static ManagedStatic > VTMutex; + +/// getValueTypeList - Return a pointer to the specified value type. +/// +const EVT *SDNode::getValueTypeList(EVT VT) { + if (VT.isExtended()) { + sys::SmartScopedLock Lock(*VTMutex); + return &(*EVTs->insert(VT).first); + } else { + return &SimpleVTArray->VTs[VT.getSimpleVT().SimpleTy]; + } +} + +/// hasNUsesOfValue - Return true if there are exactly NUSES uses of the +/// indicated value. This method ignores uses of other values defined by this +/// operation. +bool SDNode::hasNUsesOfValue(unsigned NUses, unsigned Value) const { + assert(Value < getNumValues() && "Bad value!"); + + // TODO: Only iterate over uses of a given value of the node + for (SDNode::use_iterator UI = use_begin(), E = use_end(); UI != E; ++UI) { + if (UI.getUse().getResNo() == Value) { + if (NUses == 0) + return false; + --NUses; + } + } + + // Found exactly the right number of uses? + return NUses == 0; +} + + +/// hasAnyUseOfValue - Return true if there are any use of the indicated +/// value. This method ignores uses of other values defined by this operation. +bool SDNode::hasAnyUseOfValue(unsigned Value) const { + assert(Value < getNumValues() && "Bad value!"); + + for (SDNode::use_iterator UI = use_begin(), E = use_end(); UI != E; ++UI) + if (UI.getUse().getResNo() == Value) + return true; + + return false; +} + + +/// isOnlyUserOf - Return true if this node is the only use of N. +/// +bool SDNode::isOnlyUserOf(SDNode *N) const { + bool Seen = false; + for (SDNode::use_iterator I = N->use_begin(), E = N->use_end(); I != E; ++I) { + SDNode *User = *I; + if (User == this) + Seen = true; + else + return false; + } + + return Seen; +} + +/// isOperand - Return true if this node is an operand of N. +/// +bool SDValue::isOperandOf(SDNode *N) const { + for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) + if (*this == N->getOperand(i)) + return true; + return false; +} + +bool SDNode::isOperandOf(SDNode *N) const { + for (unsigned i = 0, e = N->NumOperands; i != e; ++i) + if (this == N->OperandList[i].getNode()) + return true; + return false; +} + +/// reachesChainWithoutSideEffects - Return true if this operand (which must +/// be a chain) reaches the specified operand without crossing any +/// side-effecting instructions. In practice, this looks through token +/// factors and non-volatile loads. In order to remain efficient, this only +/// looks a couple of nodes in, it does not do an exhaustive search. +bool SDValue::reachesChainWithoutSideEffects(SDValue Dest, + unsigned Depth) const { + if (*this == Dest) return true; + + // Don't search too deeply, we just want to be able to see through + // TokenFactor's etc. + if (Depth == 0) return false; + + // If this is a token factor, all inputs to the TF happen in parallel. If any + // of the operands of the TF reach dest, then we can do the xform. + if (getOpcode() == ISD::TokenFactor) { + for (unsigned i = 0, e = getNumOperands(); i != e; ++i) + if (getOperand(i).reachesChainWithoutSideEffects(Dest, Depth-1)) + return true; + return false; + } + + // Loads don't have side effects, look through them. + if (LoadSDNode *Ld = dyn_cast(*this)) { + if (!Ld->isVolatile()) + return Ld->getChain().reachesChainWithoutSideEffects(Dest, Depth-1); + } + return false; +} + +/// isPredecessorOf - Return true if this node is a predecessor of N. This node +/// is either an operand of N or it can be reached by traversing up the operands. +/// NOTE: this is an expensive method. Use it carefully. +bool SDNode::isPredecessorOf(SDNode *N) const { + SmallPtrSet Visited; + SmallVector Worklist; + Worklist.push_back(N); + + do { + N = Worklist.pop_back_val(); + for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) { + SDNode *Op = N->getOperand(i).getNode(); + if (Op == this) + return true; + if (Visited.insert(Op)) + Worklist.push_back(Op); + } + } while (!Worklist.empty()); + + return false; +} + +uint64_t SDNode::getConstantOperandVal(unsigned Num) const { + assert(Num < NumOperands && "Invalid child # of SDNode!"); + return cast(OperandList[Num])->getZExtValue(); +} + +std::string SDNode::getOperationName(const SelectionDAG *G) const { + switch (getOpcode()) { + default: + if (getOpcode() < ISD::BUILTIN_OP_END) + return "<>"; + if (isMachineOpcode()) { + if (G) + if (const TargetInstrInfo *TII = G->getTarget().getInstrInfo()) + if (getMachineOpcode() < TII->getNumOpcodes()) + return TII->get(getMachineOpcode()).getName(); + return "<>"; + } + if (G) { + const TargetLowering &TLI = G->getTargetLoweringInfo(); + const char *Name = TLI.getTargetNodeName(getOpcode()); + if (Name) return Name; + return "<>"; + } + return "<>"; + +#ifndef NDEBUG + case ISD::DELETED_NODE: + return "<>"; +#endif + case ISD::PREFETCH: return "Prefetch"; + case ISD::MEMBARRIER: return "MemBarrier"; + case ISD::ATOMIC_CMP_SWAP: return "AtomicCmpSwap"; + case ISD::ATOMIC_SWAP: return "AtomicSwap"; + case ISD::ATOMIC_LOAD_ADD: return "AtomicLoadAdd"; + case ISD::ATOMIC_LOAD_SUB: return "AtomicLoadSub"; + case ISD::ATOMIC_LOAD_AND: return "AtomicLoadAnd"; + case ISD::ATOMIC_LOAD_OR: return "AtomicLoadOr"; + case ISD::ATOMIC_LOAD_XOR: return "AtomicLoadXor"; + case ISD::ATOMIC_LOAD_NAND: return "AtomicLoadNand"; + case ISD::ATOMIC_LOAD_MIN: return "AtomicLoadMin"; + case ISD::ATOMIC_LOAD_MAX: return "AtomicLoadMax"; + case ISD::ATOMIC_LOAD_UMIN: return "AtomicLoadUMin"; + case ISD::ATOMIC_LOAD_UMAX: return "AtomicLoadUMax"; + case ISD::PCMARKER: return "PCMarker"; + case ISD::READCYCLECOUNTER: return "ReadCycleCounter"; + case ISD::SRCVALUE: return "SrcValue"; + case ISD::EntryToken: return "EntryToken"; + case ISD::TokenFactor: return "TokenFactor"; + case ISD::AssertSext: return "AssertSext"; + case ISD::AssertZext: return "AssertZext"; + + case ISD::BasicBlock: return "BasicBlock"; + case ISD::VALUETYPE: return "ValueType"; + case ISD::Register: return "Register"; + + case ISD::Constant: return "Constant"; + case ISD::ConstantFP: return "ConstantFP"; + case ISD::GlobalAddress: return "GlobalAddress"; + case ISD::GlobalTLSAddress: return "GlobalTLSAddress"; + case ISD::FrameIndex: return "FrameIndex"; + case ISD::JumpTable: return "JumpTable"; + case ISD::GLOBAL_OFFSET_TABLE: return "GLOBAL_OFFSET_TABLE"; + case ISD::RETURNADDR: return "RETURNADDR"; + case ISD::FRAMEADDR: return "FRAMEADDR"; + case ISD::FRAME_TO_ARGS_OFFSET: return "FRAME_TO_ARGS_OFFSET"; + case ISD::EXCEPTIONADDR: return "EXCEPTIONADDR"; + case ISD::LSDAADDR: return "LSDAADDR"; + case ISD::EHSELECTION: return "EHSELECTION"; + case ISD::EH_RETURN: return "EH_RETURN"; + case ISD::ConstantPool: return "ConstantPool"; + case ISD::ExternalSymbol: return "ExternalSymbol"; + case ISD::BlockAddress: return "BlockAddress"; + case ISD::INTRINSIC_WO_CHAIN: + case ISD::INTRINSIC_VOID: + case ISD::INTRINSIC_W_CHAIN: { + unsigned OpNo = getOpcode() == ISD::INTRINSIC_WO_CHAIN ? 0 : 1; + unsigned IID = cast(getOperand(OpNo))->getZExtValue(); + if (IID < Intrinsic::num_intrinsics) + return Intrinsic::getName((Intrinsic::ID)IID); + else if (const TargetIntrinsicInfo *TII = G->getTarget().getIntrinsicInfo()) + return TII->getName(IID); + llvm_unreachable("Invalid intrinsic ID"); + } + + case ISD::BUILD_VECTOR: return "BUILD_VECTOR"; + case ISD::TargetConstant: return "TargetConstant"; + case ISD::TargetConstantFP:return "TargetConstantFP"; + case ISD::TargetGlobalAddress: return "TargetGlobalAddress"; + case ISD::TargetGlobalTLSAddress: return "TargetGlobalTLSAddress"; + case ISD::TargetFrameIndex: return "TargetFrameIndex"; + case ISD::TargetJumpTable: return "TargetJumpTable"; + case ISD::TargetConstantPool: return "TargetConstantPool"; + case ISD::TargetExternalSymbol: return "TargetExternalSymbol"; + case ISD::TargetBlockAddress: return "TargetBlockAddress"; + + case ISD::CopyToReg: return "CopyToReg"; + case ISD::CopyFromReg: return "CopyFromReg"; + case ISD::UNDEF: return "undef"; + case ISD::MERGE_VALUES: return "merge_values"; + case ISD::INLINEASM: return "inlineasm"; + case ISD::EH_LABEL: return "eh_label"; + case ISD::HANDLENODE: return "handlenode"; + + // Unary operators + case ISD::FABS: return "fabs"; + case ISD::FNEG: return "fneg"; + case ISD::FSQRT: return "fsqrt"; + case ISD::FSIN: return "fsin"; + case ISD::FCOS: return "fcos"; + case ISD::FPOWI: return "fpowi"; + case ISD::FPOW: return "fpow"; + case ISD::FTRUNC: return "ftrunc"; + case ISD::FFLOOR: return "ffloor"; + case ISD::FCEIL: return "fceil"; + case ISD::FRINT: return "frint"; + case ISD::FNEARBYINT: return "fnearbyint"; + + // Binary operators + case ISD::ADD: return "add"; + case ISD::SUB: return "sub"; + case ISD::MUL: return "mul"; + case ISD::MULHU: return "mulhu"; + case ISD::MULHS: return "mulhs"; + case ISD::SDIV: return "sdiv"; + case ISD::UDIV: return "udiv"; + case ISD::SREM: return "srem"; + case ISD::UREM: return "urem"; + case ISD::SMUL_LOHI: return "smul_lohi"; + case ISD::UMUL_LOHI: return "umul_lohi"; + case ISD::SDIVREM: return "sdivrem"; + case ISD::UDIVREM: return "udivrem"; + case ISD::AND: return "and"; + case ISD::OR: return "or"; + case ISD::XOR: return "xor"; + case ISD::SHL: return "shl"; + case ISD::SRA: return "sra"; + case ISD::SRL: return "srl"; + case ISD::ROTL: return "rotl"; + case ISD::ROTR: return "rotr"; + case ISD::FADD: return "fadd"; + case ISD::FSUB: return "fsub"; + case ISD::FMUL: return "fmul"; + case ISD::FDIV: return "fdiv"; + case ISD::FREM: return "frem"; + case ISD::FCOPYSIGN: return "fcopysign"; + case ISD::FGETSIGN: return "fgetsign"; + + case ISD::SETCC: return "setcc"; + case ISD::VSETCC: return "vsetcc"; + case ISD::SELECT: return "select"; + case ISD::SELECT_CC: return "select_cc"; + case ISD::INSERT_VECTOR_ELT: return "insert_vector_elt"; + case ISD::EXTRACT_VECTOR_ELT: return "extract_vector_elt"; + case ISD::CONCAT_VECTORS: return "concat_vectors"; + case ISD::EXTRACT_SUBVECTOR: return "extract_subvector"; + case ISD::SCALAR_TO_VECTOR: return "scalar_to_vector"; + case ISD::VECTOR_SHUFFLE: return "vector_shuffle"; + case ISD::CARRY_FALSE: return "carry_false"; + case ISD::ADDC: return "addc"; + case ISD::ADDE: return "adde"; + case ISD::SADDO: return "saddo"; + case ISD::UADDO: return "uaddo"; + case ISD::SSUBO: return "ssubo"; + case ISD::USUBO: return "usubo"; + case ISD::SMULO: return "smulo"; + case ISD::UMULO: return "umulo"; + case ISD::SUBC: return "subc"; + case ISD::SUBE: return "sube"; + case ISD::SHL_PARTS: return "shl_parts"; + case ISD::SRA_PARTS: return "sra_parts"; + case ISD::SRL_PARTS: return "srl_parts"; + + // Conversion operators. + case ISD::SIGN_EXTEND: return "sign_extend"; + case ISD::ZERO_EXTEND: return "zero_extend"; + case ISD::ANY_EXTEND: return "any_extend"; + case ISD::SIGN_EXTEND_INREG: return "sign_extend_inreg"; + case ISD::TRUNCATE: return "truncate"; + case ISD::FP_ROUND: return "fp_round"; + case ISD::FLT_ROUNDS_: return "flt_rounds"; + case ISD::FP_ROUND_INREG: return "fp_round_inreg"; + case ISD::FP_EXTEND: return "fp_extend"; + + case ISD::SINT_TO_FP: return "sint_to_fp"; + case ISD::UINT_TO_FP: return "uint_to_fp"; + case ISD::FP_TO_SINT: return "fp_to_sint"; + case ISD::FP_TO_UINT: return "fp_to_uint"; + case ISD::BIT_CONVERT: return "bit_convert"; + + case ISD::CONVERT_RNDSAT: { + switch (cast(this)->getCvtCode()) { + default: llvm_unreachable("Unknown cvt code!"); + case ISD::CVT_FF: return "cvt_ff"; + case ISD::CVT_FS: return "cvt_fs"; + case ISD::CVT_FU: return "cvt_fu"; + case ISD::CVT_SF: return "cvt_sf"; + case ISD::CVT_UF: return "cvt_uf"; + case ISD::CVT_SS: return "cvt_ss"; + case ISD::CVT_SU: return "cvt_su"; + case ISD::CVT_US: return "cvt_us"; + case ISD::CVT_UU: return "cvt_uu"; + } + } + + // Control flow instructions + case ISD::BR: return "br"; + case ISD::BRIND: return "brind"; + case ISD::BR_JT: return "br_jt"; + case ISD::BRCOND: return "brcond"; + case ISD::BR_CC: return "br_cc"; + case ISD::CALLSEQ_START: return "callseq_start"; + case ISD::CALLSEQ_END: return "callseq_end"; + + // Other operators + case ISD::LOAD: return "load"; + case ISD::STORE: return "store"; + case ISD::VAARG: return "vaarg"; + case ISD::VACOPY: return "vacopy"; + case ISD::VAEND: return "vaend"; + case ISD::VASTART: return "vastart"; + case ISD::DYNAMIC_STACKALLOC: return "dynamic_stackalloc"; + case ISD::EXTRACT_ELEMENT: return "extract_element"; + case ISD::BUILD_PAIR: return "build_pair"; + case ISD::STACKSAVE: return "stacksave"; + case ISD::STACKRESTORE: return "stackrestore"; + case ISD::TRAP: return "trap"; + + // Bit manipulation + case ISD::BSWAP: return "bswap"; + case ISD::CTPOP: return "ctpop"; + case ISD::CTTZ: return "cttz"; + case ISD::CTLZ: return "ctlz"; + + // Trampolines + case ISD::TRAMPOLINE: return "trampoline"; + + case ISD::CONDCODE: + switch (cast(this)->get()) { + default: llvm_unreachable("Unknown setcc condition!"); + case ISD::SETOEQ: return "setoeq"; + case ISD::SETOGT: return "setogt"; + case ISD::SETOGE: return "setoge"; + case ISD::SETOLT: return "setolt"; + case ISD::SETOLE: return "setole"; + case ISD::SETONE: return "setone"; + + case ISD::SETO: return "seto"; + case ISD::SETUO: return "setuo"; + case ISD::SETUEQ: return "setue"; + case ISD::SETUGT: return "setugt"; + case ISD::SETUGE: return "setuge"; + case ISD::SETULT: return "setult"; + case ISD::SETULE: return "setule"; + case ISD::SETUNE: return "setune"; + + case ISD::SETEQ: return "seteq"; + case ISD::SETGT: return "setgt"; + case ISD::SETGE: return "setge"; + case ISD::SETLT: return "setlt"; + case ISD::SETLE: return "setle"; + case ISD::SETNE: return "setne"; + } + } +} + +const char *SDNode::getIndexedModeName(ISD::MemIndexedMode AM) { + switch (AM) { + default: + return ""; + case ISD::PRE_INC: + return ""; + case ISD::PRE_DEC: + return ""; + case ISD::POST_INC: + return ""; + case ISD::POST_DEC: + return ""; + } +} + +std::string ISD::ArgFlagsTy::getArgFlagsString() { + std::string S = "< "; + + if (isZExt()) + S += "zext "; + if (isSExt()) + S += "sext "; + if (isInReg()) + S += "inreg "; + if (isSRet()) + S += "sret "; + if (isByVal()) + S += "byval "; + if (isNest()) + S += "nest "; + if (getByValAlign()) + S += "byval-align:" + utostr(getByValAlign()) + " "; + if (getOrigAlign()) + S += "orig-align:" + utostr(getOrigAlign()) + " "; + if (getByValSize()) + S += "byval-size:" + utostr(getByValSize()) + " "; + return S + ">"; +} + +void SDNode::dump() const { dump(0); } +void SDNode::dump(const SelectionDAG *G) const { + print(errs(), G); +} + +void SDNode::print_types(raw_ostream &OS, const SelectionDAG *G) const { + OS << (void*)this << ": "; + + for (unsigned i = 0, e = getNumValues(); i != e; ++i) { + if (i) OS << ","; + if (getValueType(i) == MVT::Other) + OS << "ch"; + else + OS << getValueType(i).getEVTString(); + } + OS << " = " << getOperationName(G); +} + +void SDNode::print_details(raw_ostream &OS, const SelectionDAG *G) const { + if (const MachineSDNode *MN = dyn_cast(this)) { + if (!MN->memoperands_empty()) { + OS << "<"; + OS << "Mem:"; + for (MachineSDNode::mmo_iterator i = MN->memoperands_begin(), + e = MN->memoperands_end(); i != e; ++i) { + OS << **i; + if (next(i) != e) + OS << " "; + } + OS << ">"; + } + } else if (const ShuffleVectorSDNode *SVN = + dyn_cast(this)) { + OS << "<"; + for (unsigned i = 0, e = ValueList[0].getVectorNumElements(); i != e; ++i) { + int Idx = SVN->getMaskElt(i); + if (i) OS << ","; + if (Idx < 0) + OS << "u"; + else + OS << Idx; + } + OS << ">"; + } else if (const ConstantSDNode *CSDN = dyn_cast(this)) { + OS << '<' << CSDN->getAPIntValue() << '>'; + } else if (const ConstantFPSDNode *CSDN = dyn_cast(this)) { + if (&CSDN->getValueAPF().getSemantics()==&APFloat::IEEEsingle) + OS << '<' << CSDN->getValueAPF().convertToFloat() << '>'; + else if (&CSDN->getValueAPF().getSemantics()==&APFloat::IEEEdouble) + OS << '<' << CSDN->getValueAPF().convertToDouble() << '>'; + else { + OS << "getValueAPF().bitcastToAPInt().dump(); + OS << ")>"; + } + } else if (const GlobalAddressSDNode *GADN = + dyn_cast(this)) { + int64_t offset = GADN->getOffset(); + OS << '<'; + WriteAsOperand(OS, GADN->getGlobal()); + OS << '>'; + if (offset > 0) + OS << " + " << offset; + else + OS << " " << offset; + if (unsigned int TF = GADN->getTargetFlags()) + OS << " [TF=" << TF << ']'; + } else if (const FrameIndexSDNode *FIDN = dyn_cast(this)) { + OS << "<" << FIDN->getIndex() << ">"; + } else if (const JumpTableSDNode *JTDN = dyn_cast(this)) { + OS << "<" << JTDN->getIndex() << ">"; + if (unsigned int TF = JTDN->getTargetFlags()) + OS << " [TF=" << TF << ']'; + } else if (const ConstantPoolSDNode *CP = dyn_cast(this)){ + int offset = CP->getOffset(); + if (CP->isMachineConstantPoolEntry()) + OS << "<" << *CP->getMachineCPVal() << ">"; + else + OS << "<" << *CP->getConstVal() << ">"; + if (offset > 0) + OS << " + " << offset; + else + OS << " " << offset; + if (unsigned int TF = CP->getTargetFlags()) + OS << " [TF=" << TF << ']'; + } else if (const BasicBlockSDNode *BBDN = dyn_cast(this)) { + OS << "<"; + const Value *LBB = (const Value*)BBDN->getBasicBlock()->getBasicBlock(); + if (LBB) + OS << LBB->getName() << " "; + OS << (const void*)BBDN->getBasicBlock() << ">"; + } else if (const RegisterSDNode *R = dyn_cast(this)) { + if (G && R->getReg() && + TargetRegisterInfo::isPhysicalRegister(R->getReg())) { + OS << " %" << G->getTarget().getRegisterInfo()->getName(R->getReg()); + } else { + OS << " %reg" << R->getReg(); + } + } else if (const ExternalSymbolSDNode *ES = + dyn_cast(this)) { + OS << "'" << ES->getSymbol() << "'"; + if (unsigned int TF = ES->getTargetFlags()) + OS << " [TF=" << TF << ']'; + } else if (const SrcValueSDNode *M = dyn_cast(this)) { + if (M->getValue()) + OS << "<" << M->getValue() << ">"; + else + OS << ""; + } else if (const VTSDNode *N = dyn_cast(this)) { + OS << ":" << N->getVT().getEVTString(); + } + else if (const LoadSDNode *LD = dyn_cast(this)) { + OS << "<" << *LD->getMemOperand(); + + bool doExt = true; + switch (LD->getExtensionType()) { + default: doExt = false; break; + case ISD::EXTLOAD: OS << ", anyext"; break; + case ISD::SEXTLOAD: OS << ", sext"; break; + case ISD::ZEXTLOAD: OS << ", zext"; break; + } + if (doExt) + OS << " from " << LD->getMemoryVT().getEVTString(); + + const char *AM = getIndexedModeName(LD->getAddressingMode()); + if (*AM) + OS << ", " << AM; + + OS << ">"; + } else if (const StoreSDNode *ST = dyn_cast(this)) { + OS << "<" << *ST->getMemOperand(); + + if (ST->isTruncatingStore()) + OS << ", trunc to " << ST->getMemoryVT().getEVTString(); + + const char *AM = getIndexedModeName(ST->getAddressingMode()); + if (*AM) + OS << ", " << AM; + + OS << ">"; + } else if (const MemSDNode* M = dyn_cast(this)) { + OS << "<" << *M->getMemOperand() << ">"; + } else if (const BlockAddressSDNode *BA = + dyn_cast(this)) { + OS << "<"; + WriteAsOperand(OS, BA->getBlockAddress()->getFunction(), false); + OS << ", "; + WriteAsOperand(OS, BA->getBlockAddress()->getBasicBlock(), false); + OS << ">"; + if (unsigned int TF = BA->getTargetFlags()) + OS << " [TF=" << TF << ']'; + } +} + +void SDNode::print(raw_ostream &OS, const SelectionDAG *G) const { + print_types(OS, G); + for (unsigned i = 0, e = getNumOperands(); i != e; ++i) { + if (i) OS << ", "; else OS << " "; + OS << (void*)getOperand(i).getNode(); + if (unsigned RN = getOperand(i).getResNo()) + OS << ":" << RN; + } + print_details(OS, G); +} + +static void DumpNodes(const SDNode *N, unsigned indent, const SelectionDAG *G) { + for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) + if (N->getOperand(i).getNode()->hasOneUse()) + DumpNodes(N->getOperand(i).getNode(), indent+2, G); + else + errs() << "\n" << std::string(indent+2, ' ') + << (void*)N->getOperand(i).getNode() << ": "; + + + errs() << "\n"; + errs().indent(indent); + N->dump(G); +} + +void SelectionDAG::dump() const { + errs() << "SelectionDAG has " << AllNodes.size() << " nodes:"; + + for (allnodes_const_iterator I = allnodes_begin(), E = allnodes_end(); + I != E; ++I) { + const SDNode *N = I; + if (!N->hasOneUse() && N != getRoot().getNode()) + DumpNodes(N, 2, this); + } + + if (getRoot().getNode()) DumpNodes(getRoot().getNode(), 2, this); + + errs() << "\n\n"; +} + +void SDNode::printr(raw_ostream &OS, const SelectionDAG *G) const { + print_types(OS, G); + print_details(OS, G); +} + +typedef SmallPtrSet VisitedSDNodeSet; +static void DumpNodesr(raw_ostream &OS, const SDNode *N, unsigned indent, + const SelectionDAG *G, VisitedSDNodeSet &once) { + if (!once.insert(N)) // If we've been here before, return now. + return; + // Dump the current SDNode, but don't end the line yet. + OS << std::string(indent, ' '); + N->printr(OS, G); + // Having printed this SDNode, walk the children: + for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) { + const SDNode *child = N->getOperand(i).getNode(); + if (i) OS << ","; + OS << " "; + if (child->getNumOperands() == 0) { + // This child has no grandchildren; print it inline right here. + child->printr(OS, G); + once.insert(child); + } else { // Just the address. FIXME: also print the child's opcode + OS << (void*)child; + if (unsigned RN = N->getOperand(i).getResNo()) + OS << ":" << RN; + } + } + OS << "\n"; + // Dump children that have grandchildren on their own line(s). + for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) { + const SDNode *child = N->getOperand(i).getNode(); + DumpNodesr(OS, child, indent+2, G, once); + } +} + +void SDNode::dumpr() const { + VisitedSDNodeSet once; + DumpNodesr(errs(), this, 0, 0, once); +} + +void SDNode::dumpr(const SelectionDAG *G) const { + VisitedSDNodeSet once; + DumpNodesr(errs(), this, 0, G, once); +} + + +// getAddressSpace - Return the address space this GlobalAddress belongs to. +unsigned GlobalAddressSDNode::getAddressSpace() const { + return getGlobal()->getType()->getAddressSpace(); +} + + +const Type *ConstantPoolSDNode::getType() const { + if (isMachineConstantPoolEntry()) + return Val.MachineCPVal->getType(); + return Val.ConstVal->getType(); +} + +bool BuildVectorSDNode::isConstantSplat(APInt &SplatValue, + APInt &SplatUndef, + unsigned &SplatBitSize, + bool &HasAnyUndefs, + unsigned MinSplatBits, + bool isBigEndian) { + EVT VT = getValueType(0); + assert(VT.isVector() && "Expected a vector type"); + unsigned sz = VT.getSizeInBits(); + if (MinSplatBits > sz) + return false; + + SplatValue = APInt(sz, 0); + SplatUndef = APInt(sz, 0); + + // Get the bits. Bits with undefined values (when the corresponding element + // of the vector is an ISD::UNDEF value) are set in SplatUndef and cleared + // in SplatValue. If any of the values are not constant, give up and return + // false. + unsigned int nOps = getNumOperands(); + assert(nOps > 0 && "isConstantSplat has 0-size build vector"); + unsigned EltBitSize = VT.getVectorElementType().getSizeInBits(); + + for (unsigned j = 0; j < nOps; ++j) { + unsigned i = isBigEndian ? nOps-1-j : j; + SDValue OpVal = getOperand(i); + unsigned BitPos = j * EltBitSize; + + if (OpVal.getOpcode() == ISD::UNDEF) + SplatUndef |= APInt::getBitsSet(sz, BitPos, BitPos + EltBitSize); + else if (ConstantSDNode *CN = dyn_cast(OpVal)) + SplatValue |= (APInt(CN->getAPIntValue()).zextOrTrunc(EltBitSize). + zextOrTrunc(sz) << BitPos); + else if (ConstantFPSDNode *CN = dyn_cast(OpVal)) + SplatValue |= CN->getValueAPF().bitcastToAPInt().zextOrTrunc(sz) < 8) { + + unsigned HalfSize = sz / 2; + APInt HighValue = APInt(SplatValue).lshr(HalfSize).trunc(HalfSize); + APInt LowValue = APInt(SplatValue).trunc(HalfSize); + APInt HighUndef = APInt(SplatUndef).lshr(HalfSize).trunc(HalfSize); + APInt LowUndef = APInt(SplatUndef).trunc(HalfSize); + + // If the two halves do not match (ignoring undef bits), stop here. + if ((HighValue & ~LowUndef) != (LowValue & ~HighUndef) || + MinSplatBits > HalfSize) + break; + + SplatValue = HighValue | LowValue; + SplatUndef = HighUndef & LowUndef; + + sz = HalfSize; + } + + SplatBitSize = sz; + return true; +} + +bool ShuffleVectorSDNode::isSplatMask(const int *Mask, EVT VT) { + // Find the first non-undef value in the shuffle mask. + unsigned i, e; + for (i = 0, e = VT.getVectorNumElements(); i != e && Mask[i] < 0; ++i) + /* search */; + + assert(i != e && "VECTOR_SHUFFLE node with all undef indices!"); + + // Make sure all remaining elements are either undef or the same as the first + // non-undef value. + for (int Idx = Mask[i]; i != e; ++i) + if (Mask[i] >= 0 && Mask[i] != Idx) + return false; + return true; +} diff --git a/libclamav/c++/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/libclamav/c++/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp new file mode 100644 index 000000000..57d89036a --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -0,0 +1,5821 @@ +//===-- SelectionDAGBuilder.cpp - Selection-DAG building ------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This implements routines for translating from LLVM IR into SelectionDAG IR. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "isel" +#include "SelectionDAGBuilder.h" +#include "FunctionLoweringInfo.h" +#include "llvm/ADT/BitVector.h" +#include "llvm/ADT/SmallSet.h" +#include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/Constants.h" +#include "llvm/CallingConv.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Function.h" +#include "llvm/GlobalVariable.h" +#include "llvm/InlineAsm.h" +#include "llvm/Instructions.h" +#include "llvm/Intrinsics.h" +#include "llvm/IntrinsicInst.h" +#include "llvm/LLVMContext.h" +#include "llvm/Module.h" +#include "llvm/CodeGen/FastISel.h" +#include "llvm/CodeGen/GCStrategy.h" +#include "llvm/CodeGen/GCMetadata.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineJumpTableInfo.h" +#include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/PseudoSourceValue.h" +#include "llvm/CodeGen/SelectionDAG.h" +#include "llvm/CodeGen/DwarfWriter.h" +#include "llvm/Analysis/DebugInfo.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetFrameInfo.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetIntrinsicInfo.h" +#include "llvm/Target/TargetLowering.h" +#include "llvm/Target/TargetOptions.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/Support/raw_ostream.h" +#include +using namespace llvm; + +/// LimitFloatPrecision - Generate low-precision inline sequences for +/// some float libcalls (6, 8 or 12 bits). +static unsigned LimitFloatPrecision; + +static cl::opt +LimitFPPrecision("limit-float-precision", + cl::desc("Generate low-precision inline sequences " + "for some float libcalls"), + cl::location(LimitFloatPrecision), + cl::init(0)); + +namespace { + /// RegsForValue - This struct represents the registers (physical or virtual) + /// that a particular set of values is assigned, and the type information about + /// the value. The most common situation is to represent one value at a time, + /// but struct or array values are handled element-wise as multiple values. + /// The splitting of aggregates is performed recursively, so that we never + /// have aggregate-typed registers. The values at this point do not necessarily + /// have legal types, so each value may require one or more registers of some + /// legal type. + /// + struct RegsForValue { + /// TLI - The TargetLowering object. + /// + const TargetLowering *TLI; + + /// ValueVTs - The value types of the values, which may not be legal, and + /// may need be promoted or synthesized from one or more registers. + /// + SmallVector ValueVTs; + + /// RegVTs - The value types of the registers. This is the same size as + /// ValueVTs and it records, for each value, what the type of the assigned + /// register or registers are. (Individual values are never synthesized + /// from more than one type of register.) + /// + /// With virtual registers, the contents of RegVTs is redundant with TLI's + /// getRegisterType member function, however when with physical registers + /// it is necessary to have a separate record of the types. + /// + SmallVector RegVTs; + + /// Regs - This list holds the registers assigned to the values. + /// Each legal or promoted value requires one register, and each + /// expanded value requires multiple registers. + /// + SmallVector Regs; + + RegsForValue() : TLI(0) {} + + RegsForValue(const TargetLowering &tli, + const SmallVector ®s, + EVT regvt, EVT valuevt) + : TLI(&tli), ValueVTs(1, valuevt), RegVTs(1, regvt), Regs(regs) {} + RegsForValue(const TargetLowering &tli, + const SmallVector ®s, + const SmallVector ®vts, + const SmallVector &valuevts) + : TLI(&tli), ValueVTs(valuevts), RegVTs(regvts), Regs(regs) {} + RegsForValue(LLVMContext &Context, const TargetLowering &tli, + unsigned Reg, const Type *Ty) : TLI(&tli) { + ComputeValueVTs(tli, Ty, ValueVTs); + + for (unsigned Value = 0, e = ValueVTs.size(); Value != e; ++Value) { + EVT ValueVT = ValueVTs[Value]; + unsigned NumRegs = TLI->getNumRegisters(Context, ValueVT); + EVT RegisterVT = TLI->getRegisterType(Context, ValueVT); + for (unsigned i = 0; i != NumRegs; ++i) + Regs.push_back(Reg + i); + RegVTs.push_back(RegisterVT); + Reg += NumRegs; + } + } + + /// append - Add the specified values to this one. + void append(const RegsForValue &RHS) { + TLI = RHS.TLI; + ValueVTs.append(RHS.ValueVTs.begin(), RHS.ValueVTs.end()); + RegVTs.append(RHS.RegVTs.begin(), RHS.RegVTs.end()); + Regs.append(RHS.Regs.begin(), RHS.Regs.end()); + } + + + /// getCopyFromRegs - Emit a series of CopyFromReg nodes that copies from + /// this value and returns the result as a ValueVTs value. This uses + /// Chain/Flag as the input and updates them for the output Chain/Flag. + /// If the Flag pointer is NULL, no flag is used. + SDValue getCopyFromRegs(SelectionDAG &DAG, DebugLoc dl, + SDValue &Chain, SDValue *Flag) const; + + /// getCopyToRegs - Emit a series of CopyToReg nodes that copies the + /// specified value into the registers specified by this object. This uses + /// Chain/Flag as the input and updates them for the output Chain/Flag. + /// If the Flag pointer is NULL, no flag is used. + void getCopyToRegs(SDValue Val, SelectionDAG &DAG, DebugLoc dl, + SDValue &Chain, SDValue *Flag) const; + + /// AddInlineAsmOperands - Add this value to the specified inlineasm node + /// operand list. This adds the code marker, matching input operand index + /// (if applicable), and includes the number of values added into it. + void AddInlineAsmOperands(unsigned Code, + bool HasMatching, unsigned MatchingIdx, + SelectionDAG &DAG, std::vector &Ops) const; + }; +} + +/// getCopyFromParts - Create a value that contains the specified legal parts +/// combined into the value they represent. If the parts combine to a type +/// larger then ValueVT then AssertOp can be used to specify whether the extra +/// bits are known to be zero (ISD::AssertZext) or sign extended from ValueVT +/// (ISD::AssertSext). +static SDValue getCopyFromParts(SelectionDAG &DAG, DebugLoc dl, + const SDValue *Parts, + unsigned NumParts, EVT PartVT, EVT ValueVT, + ISD::NodeType AssertOp = ISD::DELETED_NODE) { + assert(NumParts > 0 && "No parts to assemble!"); + const TargetLowering &TLI = DAG.getTargetLoweringInfo(); + SDValue Val = Parts[0]; + + if (NumParts > 1) { + // Assemble the value from multiple parts. + if (!ValueVT.isVector() && ValueVT.isInteger()) { + unsigned PartBits = PartVT.getSizeInBits(); + unsigned ValueBits = ValueVT.getSizeInBits(); + + // Assemble the power of 2 part. + unsigned RoundParts = NumParts & (NumParts - 1) ? + 1 << Log2_32(NumParts) : NumParts; + unsigned RoundBits = PartBits * RoundParts; + EVT RoundVT = RoundBits == ValueBits ? + ValueVT : EVT::getIntegerVT(*DAG.getContext(), RoundBits); + SDValue Lo, Hi; + + EVT HalfVT = EVT::getIntegerVT(*DAG.getContext(), RoundBits/2); + + if (RoundParts > 2) { + Lo = getCopyFromParts(DAG, dl, Parts, RoundParts/2, PartVT, HalfVT); + Hi = getCopyFromParts(DAG, dl, Parts+RoundParts/2, RoundParts/2, + PartVT, HalfVT); + } else { + Lo = DAG.getNode(ISD::BIT_CONVERT, dl, HalfVT, Parts[0]); + Hi = DAG.getNode(ISD::BIT_CONVERT, dl, HalfVT, Parts[1]); + } + if (TLI.isBigEndian()) + std::swap(Lo, Hi); + Val = DAG.getNode(ISD::BUILD_PAIR, dl, RoundVT, Lo, Hi); + + if (RoundParts < NumParts) { + // Assemble the trailing non-power-of-2 part. + unsigned OddParts = NumParts - RoundParts; + EVT OddVT = EVT::getIntegerVT(*DAG.getContext(), OddParts * PartBits); + Hi = getCopyFromParts(DAG, dl, + Parts+RoundParts, OddParts, PartVT, OddVT); + + // Combine the round and odd parts. + Lo = Val; + if (TLI.isBigEndian()) + std::swap(Lo, Hi); + EVT TotalVT = EVT::getIntegerVT(*DAG.getContext(), NumParts * PartBits); + Hi = DAG.getNode(ISD::ANY_EXTEND, dl, TotalVT, Hi); + Hi = DAG.getNode(ISD::SHL, dl, TotalVT, Hi, + DAG.getConstant(Lo.getValueType().getSizeInBits(), + TLI.getPointerTy())); + Lo = DAG.getNode(ISD::ZERO_EXTEND, dl, TotalVT, Lo); + Val = DAG.getNode(ISD::OR, dl, TotalVT, Lo, Hi); + } + } else if (ValueVT.isVector()) { + // Handle a multi-element vector. + EVT IntermediateVT, RegisterVT; + unsigned NumIntermediates; + unsigned NumRegs = + TLI.getVectorTypeBreakdown(*DAG.getContext(), ValueVT, IntermediateVT, + NumIntermediates, RegisterVT); + assert(NumRegs == NumParts && "Part count doesn't match vector breakdown!"); + NumParts = NumRegs; // Silence a compiler warning. + assert(RegisterVT == PartVT && "Part type doesn't match vector breakdown!"); + assert(RegisterVT == Parts[0].getValueType() && + "Part type doesn't match part!"); + + // Assemble the parts into intermediate operands. + SmallVector Ops(NumIntermediates); + if (NumIntermediates == NumParts) { + // If the register was not expanded, truncate or copy the value, + // as appropriate. + for (unsigned i = 0; i != NumParts; ++i) + Ops[i] = getCopyFromParts(DAG, dl, &Parts[i], 1, + PartVT, IntermediateVT); + } else if (NumParts > 0) { + // If the intermediate type was expanded, build the intermediate operands + // from the parts. + assert(NumParts % NumIntermediates == 0 && + "Must expand into a divisible number of parts!"); + unsigned Factor = NumParts / NumIntermediates; + for (unsigned i = 0; i != NumIntermediates; ++i) + Ops[i] = getCopyFromParts(DAG, dl, &Parts[i * Factor], Factor, + PartVT, IntermediateVT); + } + + // Build a vector with BUILD_VECTOR or CONCAT_VECTORS from the intermediate + // operands. + Val = DAG.getNode(IntermediateVT.isVector() ? + ISD::CONCAT_VECTORS : ISD::BUILD_VECTOR, dl, + ValueVT, &Ops[0], NumIntermediates); + } else if (PartVT.isFloatingPoint()) { + // FP split into multiple FP parts (for ppcf128) + assert(ValueVT == EVT(MVT::ppcf128) && PartVT == EVT(MVT::f64) && + "Unexpected split"); + SDValue Lo, Hi; + Lo = DAG.getNode(ISD::BIT_CONVERT, dl, EVT(MVT::f64), Parts[0]); + Hi = DAG.getNode(ISD::BIT_CONVERT, dl, EVT(MVT::f64), Parts[1]); + if (TLI.isBigEndian()) + std::swap(Lo, Hi); + Val = DAG.getNode(ISD::BUILD_PAIR, dl, ValueVT, Lo, Hi); + } else { + // FP split into integer parts (soft fp) + assert(ValueVT.isFloatingPoint() && PartVT.isInteger() && + !PartVT.isVector() && "Unexpected split"); + EVT IntVT = EVT::getIntegerVT(*DAG.getContext(), ValueVT.getSizeInBits()); + Val = getCopyFromParts(DAG, dl, Parts, NumParts, PartVT, IntVT); + } + } + + // There is now one part, held in Val. Correct it to match ValueVT. + PartVT = Val.getValueType(); + + if (PartVT == ValueVT) + return Val; + + if (PartVT.isVector()) { + assert(ValueVT.isVector() && "Unknown vector conversion!"); + return DAG.getNode(ISD::BIT_CONVERT, dl, ValueVT, Val); + } + + if (ValueVT.isVector()) { + assert(ValueVT.getVectorElementType() == PartVT && + ValueVT.getVectorNumElements() == 1 && + "Only trivial scalar-to-vector conversions should get here!"); + return DAG.getNode(ISD::BUILD_VECTOR, dl, ValueVT, Val); + } + + if (PartVT.isInteger() && + ValueVT.isInteger()) { + if (ValueVT.bitsLT(PartVT)) { + // For a truncate, see if we have any information to + // indicate whether the truncated bits will always be + // zero or sign-extension. + if (AssertOp != ISD::DELETED_NODE) + Val = DAG.getNode(AssertOp, dl, PartVT, Val, + DAG.getValueType(ValueVT)); + return DAG.getNode(ISD::TRUNCATE, dl, ValueVT, Val); + } else { + return DAG.getNode(ISD::ANY_EXTEND, dl, ValueVT, Val); + } + } + + if (PartVT.isFloatingPoint() && ValueVT.isFloatingPoint()) { + if (ValueVT.bitsLT(Val.getValueType())) + // FP_ROUND's are always exact here. + return DAG.getNode(ISD::FP_ROUND, dl, ValueVT, Val, + DAG.getIntPtrConstant(1)); + return DAG.getNode(ISD::FP_EXTEND, dl, ValueVT, Val); + } + + if (PartVT.getSizeInBits() == ValueVT.getSizeInBits()) + return DAG.getNode(ISD::BIT_CONVERT, dl, ValueVT, Val); + + llvm_unreachable("Unknown mismatch!"); + return SDValue(); +} + +/// getCopyToParts - Create a series of nodes that contain the specified value +/// split into legal parts. If the parts contain more bits than Val, then, for +/// integers, ExtendKind can be used to specify how to generate the extra bits. +static void getCopyToParts(SelectionDAG &DAG, DebugLoc dl, SDValue Val, + SDValue *Parts, unsigned NumParts, EVT PartVT, + ISD::NodeType ExtendKind = ISD::ANY_EXTEND) { + const TargetLowering &TLI = DAG.getTargetLoweringInfo(); + EVT PtrVT = TLI.getPointerTy(); + EVT ValueVT = Val.getValueType(); + unsigned PartBits = PartVT.getSizeInBits(); + unsigned OrigNumParts = NumParts; + assert(TLI.isTypeLegal(PartVT) && "Copying to an illegal type!"); + + if (!NumParts) + return; + + if (!ValueVT.isVector()) { + if (PartVT == ValueVT) { + assert(NumParts == 1 && "No-op copy with multiple parts!"); + Parts[0] = Val; + return; + } + + if (NumParts * PartBits > ValueVT.getSizeInBits()) { + // If the parts cover more bits than the value has, promote the value. + if (PartVT.isFloatingPoint() && ValueVT.isFloatingPoint()) { + assert(NumParts == 1 && "Do not know what to promote to!"); + Val = DAG.getNode(ISD::FP_EXTEND, dl, PartVT, Val); + } else if (PartVT.isInteger() && ValueVT.isInteger()) { + ValueVT = EVT::getIntegerVT(*DAG.getContext(), NumParts * PartBits); + Val = DAG.getNode(ExtendKind, dl, ValueVT, Val); + } else { + llvm_unreachable("Unknown mismatch!"); + } + } else if (PartBits == ValueVT.getSizeInBits()) { + // Different types of the same size. + assert(NumParts == 1 && PartVT != ValueVT); + Val = DAG.getNode(ISD::BIT_CONVERT, dl, PartVT, Val); + } else if (NumParts * PartBits < ValueVT.getSizeInBits()) { + // If the parts cover less bits than value has, truncate the value. + if (PartVT.isInteger() && ValueVT.isInteger()) { + ValueVT = EVT::getIntegerVT(*DAG.getContext(), NumParts * PartBits); + Val = DAG.getNode(ISD::TRUNCATE, dl, ValueVT, Val); + } else { + llvm_unreachable("Unknown mismatch!"); + } + } + + // The value may have changed - recompute ValueVT. + ValueVT = Val.getValueType(); + assert(NumParts * PartBits == ValueVT.getSizeInBits() && + "Failed to tile the value with PartVT!"); + + if (NumParts == 1) { + assert(PartVT == ValueVT && "Type conversion failed!"); + Parts[0] = Val; + return; + } + + // Expand the value into multiple parts. + if (NumParts & (NumParts - 1)) { + // The number of parts is not a power of 2. Split off and copy the tail. + assert(PartVT.isInteger() && ValueVT.isInteger() && + "Do not know what to expand to!"); + unsigned RoundParts = 1 << Log2_32(NumParts); + unsigned RoundBits = RoundParts * PartBits; + unsigned OddParts = NumParts - RoundParts; + SDValue OddVal = DAG.getNode(ISD::SRL, dl, ValueVT, Val, + DAG.getConstant(RoundBits, + TLI.getPointerTy())); + getCopyToParts(DAG, dl, OddVal, Parts + RoundParts, OddParts, PartVT); + if (TLI.isBigEndian()) + // The odd parts were reversed by getCopyToParts - unreverse them. + std::reverse(Parts + RoundParts, Parts + NumParts); + NumParts = RoundParts; + ValueVT = EVT::getIntegerVT(*DAG.getContext(), NumParts * PartBits); + Val = DAG.getNode(ISD::TRUNCATE, dl, ValueVT, Val); + } + + // The number of parts is a power of 2. Repeatedly bisect the value using + // EXTRACT_ELEMENT. + Parts[0] = DAG.getNode(ISD::BIT_CONVERT, dl, + EVT::getIntegerVT(*DAG.getContext(), ValueVT.getSizeInBits()), + Val); + for (unsigned StepSize = NumParts; StepSize > 1; StepSize /= 2) { + for (unsigned i = 0; i < NumParts; i += StepSize) { + unsigned ThisBits = StepSize * PartBits / 2; + EVT ThisVT = EVT::getIntegerVT(*DAG.getContext(), ThisBits); + SDValue &Part0 = Parts[i]; + SDValue &Part1 = Parts[i+StepSize/2]; + + Part1 = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, + ThisVT, Part0, + DAG.getConstant(1, PtrVT)); + Part0 = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, + ThisVT, Part0, + DAG.getConstant(0, PtrVT)); + + if (ThisBits == PartBits && ThisVT != PartVT) { + Part0 = DAG.getNode(ISD::BIT_CONVERT, dl, + PartVT, Part0); + Part1 = DAG.getNode(ISD::BIT_CONVERT, dl, + PartVT, Part1); + } + } + } + + if (TLI.isBigEndian()) + std::reverse(Parts, Parts + OrigNumParts); + + return; + } + + // Vector ValueVT. + if (NumParts == 1) { + if (PartVT != ValueVT) { + if (PartVT.isVector()) { + Val = DAG.getNode(ISD::BIT_CONVERT, dl, PartVT, Val); + } else { + assert(ValueVT.getVectorElementType() == PartVT && + ValueVT.getVectorNumElements() == 1 && + "Only trivial vector-to-scalar conversions should get here!"); + Val = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, + PartVT, Val, + DAG.getConstant(0, PtrVT)); + } + } + + Parts[0] = Val; + return; + } + + // Handle a multi-element vector. + EVT IntermediateVT, RegisterVT; + unsigned NumIntermediates; + unsigned NumRegs = TLI.getVectorTypeBreakdown(*DAG.getContext(), ValueVT, + IntermediateVT, NumIntermediates, RegisterVT); + unsigned NumElements = ValueVT.getVectorNumElements(); + + assert(NumRegs == NumParts && "Part count doesn't match vector breakdown!"); + NumParts = NumRegs; // Silence a compiler warning. + assert(RegisterVT == PartVT && "Part type doesn't match vector breakdown!"); + + // Split the vector into intermediate operands. + SmallVector Ops(NumIntermediates); + for (unsigned i = 0; i != NumIntermediates; ++i) + if (IntermediateVT.isVector()) + Ops[i] = DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, + IntermediateVT, Val, + DAG.getConstant(i * (NumElements / NumIntermediates), + PtrVT)); + else + Ops[i] = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, + IntermediateVT, Val, + DAG.getConstant(i, PtrVT)); + + // Split the intermediate operands into legal parts. + if (NumParts == NumIntermediates) { + // If the register was not expanded, promote or copy the value, + // as appropriate. + for (unsigned i = 0; i != NumParts; ++i) + getCopyToParts(DAG, dl, Ops[i], &Parts[i], 1, PartVT); + } else if (NumParts > 0) { + // If the intermediate type was expanded, split each the value into + // legal parts. + assert(NumParts % NumIntermediates == 0 && + "Must expand into a divisible number of parts!"); + unsigned Factor = NumParts / NumIntermediates; + for (unsigned i = 0; i != NumIntermediates; ++i) + getCopyToParts(DAG, dl, Ops[i], &Parts[i * Factor], Factor, PartVT); + } +} + + +void SelectionDAGBuilder::init(GCFunctionInfo *gfi, AliasAnalysis &aa) { + AA = &aa; + GFI = gfi; + TD = DAG.getTarget().getTargetData(); +} + +/// clear - Clear out the curret SelectionDAG and the associated +/// state and prepare this SelectionDAGBuilder object to be used +/// for a new block. This doesn't clear out information about +/// additional blocks that are needed to complete switch lowering +/// or PHI node updating; that information is cleared out as it is +/// consumed. +void SelectionDAGBuilder::clear() { + NodeMap.clear(); + PendingLoads.clear(); + PendingExports.clear(); + EdgeMapping.clear(); + DAG.clear(); + CurDebugLoc = DebugLoc::getUnknownLoc(); + HasTailCall = false; +} + +/// getRoot - Return the current virtual root of the Selection DAG, +/// flushing any PendingLoad items. This must be done before emitting +/// a store or any other node that may need to be ordered after any +/// prior load instructions. +/// +SDValue SelectionDAGBuilder::getRoot() { + if (PendingLoads.empty()) + return DAG.getRoot(); + + if (PendingLoads.size() == 1) { + SDValue Root = PendingLoads[0]; + DAG.setRoot(Root); + PendingLoads.clear(); + return Root; + } + + // Otherwise, we have to make a token factor node. + SDValue Root = DAG.getNode(ISD::TokenFactor, getCurDebugLoc(), MVT::Other, + &PendingLoads[0], PendingLoads.size()); + PendingLoads.clear(); + DAG.setRoot(Root); + return Root; +} + +/// getControlRoot - Similar to getRoot, but instead of flushing all the +/// PendingLoad items, flush all the PendingExports items. It is necessary +/// to do this before emitting a terminator instruction. +/// +SDValue SelectionDAGBuilder::getControlRoot() { + SDValue Root = DAG.getRoot(); + + if (PendingExports.empty()) + return Root; + + // Turn all of the CopyToReg chains into one factored node. + if (Root.getOpcode() != ISD::EntryToken) { + unsigned i = 0, e = PendingExports.size(); + for (; i != e; ++i) { + assert(PendingExports[i].getNode()->getNumOperands() > 1); + if (PendingExports[i].getNode()->getOperand(0) == Root) + break; // Don't add the root if we already indirectly depend on it. + } + + if (i == e) + PendingExports.push_back(Root); + } + + Root = DAG.getNode(ISD::TokenFactor, getCurDebugLoc(), MVT::Other, + &PendingExports[0], + PendingExports.size()); + PendingExports.clear(); + DAG.setRoot(Root); + return Root; +} + +void SelectionDAGBuilder::visit(Instruction &I) { + visit(I.getOpcode(), I); +} + +void SelectionDAGBuilder::visit(unsigned Opcode, User &I) { + // Note: this doesn't use InstVisitor, because it has to work with + // ConstantExpr's in addition to instructions. + switch (Opcode) { + default: llvm_unreachable("Unknown instruction type encountered!"); + // Build the switch statement using the Instruction.def file. +#define HANDLE_INST(NUM, OPCODE, CLASS) \ + case Instruction::OPCODE:return visit##OPCODE((CLASS&)I); +#include "llvm/Instruction.def" + } +} + +SDValue SelectionDAGBuilder::getValue(const Value *V) { + SDValue &N = NodeMap[V]; + if (N.getNode()) return N; + + if (Constant *C = const_cast(dyn_cast(V))) { + EVT VT = TLI.getValueType(V->getType(), true); + + if (ConstantInt *CI = dyn_cast(C)) + return N = DAG.getConstant(*CI, VT); + + if (GlobalValue *GV = dyn_cast(C)) + return N = DAG.getGlobalAddress(GV, VT); + + if (isa(C)) + return N = DAG.getConstant(0, TLI.getPointerTy()); + + if (ConstantFP *CFP = dyn_cast(C)) + return N = DAG.getConstantFP(*CFP, VT); + + if (isa(C) && !V->getType()->isAggregateType()) + return N = DAG.getUNDEF(VT); + + if (ConstantExpr *CE = dyn_cast(C)) { + visit(CE->getOpcode(), *CE); + SDValue N1 = NodeMap[V]; + assert(N1.getNode() && "visit didn't populate the ValueMap!"); + return N1; + } + + if (isa(C) || isa(C)) { + SmallVector Constants; + for (User::const_op_iterator OI = C->op_begin(), OE = C->op_end(); + OI != OE; ++OI) { + SDNode *Val = getValue(*OI).getNode(); + // If the operand is an empty aggregate, there are no values. + if (!Val) continue; + // Add each leaf value from the operand to the Constants list + // to form a flattened list of all the values. + for (unsigned i = 0, e = Val->getNumValues(); i != e; ++i) + Constants.push_back(SDValue(Val, i)); + } + return DAG.getMergeValues(&Constants[0], Constants.size(), + getCurDebugLoc()); + } + + if (isa(C->getType()) || isa(C->getType())) { + assert((isa(C) || isa(C)) && + "Unknown struct or array constant!"); + + SmallVector ValueVTs; + ComputeValueVTs(TLI, C->getType(), ValueVTs); + unsigned NumElts = ValueVTs.size(); + if (NumElts == 0) + return SDValue(); // empty struct + SmallVector Constants(NumElts); + for (unsigned i = 0; i != NumElts; ++i) { + EVT EltVT = ValueVTs[i]; + if (isa(C)) + Constants[i] = DAG.getUNDEF(EltVT); + else if (EltVT.isFloatingPoint()) + Constants[i] = DAG.getConstantFP(0, EltVT); + else + Constants[i] = DAG.getConstant(0, EltVT); + } + return DAG.getMergeValues(&Constants[0], NumElts, getCurDebugLoc()); + } + + if (BlockAddress *BA = dyn_cast(C)) + return DAG.getBlockAddress(BA, VT); + + const VectorType *VecTy = cast(V->getType()); + unsigned NumElements = VecTy->getNumElements(); + + // Now that we know the number and type of the elements, get that number of + // elements into the Ops array based on what kind of constant it is. + SmallVector Ops; + if (ConstantVector *CP = dyn_cast(C)) { + for (unsigned i = 0; i != NumElements; ++i) + Ops.push_back(getValue(CP->getOperand(i))); + } else { + assert(isa(C) && "Unknown vector constant!"); + EVT EltVT = TLI.getValueType(VecTy->getElementType()); + + SDValue Op; + if (EltVT.isFloatingPoint()) + Op = DAG.getConstantFP(0, EltVT); + else + Op = DAG.getConstant(0, EltVT); + Ops.assign(NumElements, Op); + } + + // Create a BUILD_VECTOR node. + return NodeMap[V] = DAG.getNode(ISD::BUILD_VECTOR, getCurDebugLoc(), + VT, &Ops[0], Ops.size()); + } + + // If this is a static alloca, generate it as the frameindex instead of + // computation. + if (const AllocaInst *AI = dyn_cast(V)) { + DenseMap::iterator SI = + FuncInfo.StaticAllocaMap.find(AI); + if (SI != FuncInfo.StaticAllocaMap.end()) + return DAG.getFrameIndex(SI->second, TLI.getPointerTy()); + } + + unsigned InReg = FuncInfo.ValueMap[V]; + assert(InReg && "Value not in map!"); + + RegsForValue RFV(*DAG.getContext(), TLI, InReg, V->getType()); + SDValue Chain = DAG.getEntryNode(); + return RFV.getCopyFromRegs(DAG, getCurDebugLoc(), Chain, NULL); +} + +/// Get the EVTs and ArgFlags collections that represent the return type +/// of the given function. This does not require a DAG or a return value, and +/// is suitable for use before any DAGs for the function are constructed. +static void getReturnInfo(const Type* ReturnType, + Attributes attr, SmallVectorImpl &OutVTs, + SmallVectorImpl &OutFlags, + TargetLowering &TLI, + SmallVectorImpl *Offsets = 0) { + SmallVector ValueVTs; + ComputeValueVTs(TLI, ReturnType, ValueVTs, Offsets); + unsigned NumValues = ValueVTs.size(); + if ( NumValues == 0 ) return; + + for (unsigned j = 0, f = NumValues; j != f; ++j) { + EVT VT = ValueVTs[j]; + ISD::NodeType ExtendKind = ISD::ANY_EXTEND; + + if (attr & Attribute::SExt) + ExtendKind = ISD::SIGN_EXTEND; + else if (attr & Attribute::ZExt) + ExtendKind = ISD::ZERO_EXTEND; + + // FIXME: C calling convention requires the return type to be promoted to + // at least 32-bit. But this is not necessary for non-C calling + // conventions. The frontend should mark functions whose return values + // require promoting with signext or zeroext attributes. + if (ExtendKind != ISD::ANY_EXTEND && VT.isInteger()) { + EVT MinVT = TLI.getRegisterType(ReturnType->getContext(), MVT::i32); + if (VT.bitsLT(MinVT)) + VT = MinVT; + } + + unsigned NumParts = TLI.getNumRegisters(ReturnType->getContext(), VT); + EVT PartVT = TLI.getRegisterType(ReturnType->getContext(), VT); + // 'inreg' on function refers to return value + ISD::ArgFlagsTy Flags = ISD::ArgFlagsTy(); + if (attr & Attribute::InReg) + Flags.setInReg(); + + // Propagate extension type if any + if (attr & Attribute::SExt) + Flags.setSExt(); + else if (attr & Attribute::ZExt) + Flags.setZExt(); + + for (unsigned i = 0; i < NumParts; ++i) { + OutVTs.push_back(PartVT); + OutFlags.push_back(Flags); + } + } +} + +void SelectionDAGBuilder::visitRet(ReturnInst &I) { + SDValue Chain = getControlRoot(); + SmallVector Outs; + FunctionLoweringInfo &FLI = DAG.getFunctionLoweringInfo(); + + if (!FLI.CanLowerReturn) { + unsigned DemoteReg = FLI.DemoteRegister; + const Function *F = I.getParent()->getParent(); + + // Emit a store of the return value through the virtual register. + // Leave Outs empty so that LowerReturn won't try to load return + // registers the usual way. + SmallVector PtrValueVTs; + ComputeValueVTs(TLI, PointerType::getUnqual(F->getReturnType()), + PtrValueVTs); + + SDValue RetPtr = DAG.getRegister(DemoteReg, PtrValueVTs[0]); + SDValue RetOp = getValue(I.getOperand(0)); + + SmallVector ValueVTs; + SmallVector Offsets; + ComputeValueVTs(TLI, I.getOperand(0)->getType(), ValueVTs, &Offsets); + unsigned NumValues = ValueVTs.size(); + + SmallVector Chains(NumValues); + EVT PtrVT = PtrValueVTs[0]; + for (unsigned i = 0; i != NumValues; ++i) + Chains[i] = DAG.getStore(Chain, getCurDebugLoc(), + SDValue(RetOp.getNode(), RetOp.getResNo() + i), + DAG.getNode(ISD::ADD, getCurDebugLoc(), PtrVT, RetPtr, + DAG.getConstant(Offsets[i], PtrVT)), + NULL, Offsets[i], false, 0); + Chain = DAG.getNode(ISD::TokenFactor, getCurDebugLoc(), + MVT::Other, &Chains[0], NumValues); + } + else { + for (unsigned i = 0, e = I.getNumOperands(); i != e; ++i) { + SmallVector ValueVTs; + ComputeValueVTs(TLI, I.getOperand(i)->getType(), ValueVTs); + unsigned NumValues = ValueVTs.size(); + if (NumValues == 0) continue; + + SDValue RetOp = getValue(I.getOperand(i)); + for (unsigned j = 0, f = NumValues; j != f; ++j) { + EVT VT = ValueVTs[j]; + + ISD::NodeType ExtendKind = ISD::ANY_EXTEND; + + const Function *F = I.getParent()->getParent(); + if (F->paramHasAttr(0, Attribute::SExt)) + ExtendKind = ISD::SIGN_EXTEND; + else if (F->paramHasAttr(0, Attribute::ZExt)) + ExtendKind = ISD::ZERO_EXTEND; + + // FIXME: C calling convention requires the return type to be promoted to + // at least 32-bit. But this is not necessary for non-C calling + // conventions. The frontend should mark functions whose return values + // require promoting with signext or zeroext attributes. + if (ExtendKind != ISD::ANY_EXTEND && VT.isInteger()) { + EVT MinVT = TLI.getRegisterType(*DAG.getContext(), MVT::i32); + if (VT.bitsLT(MinVT)) + VT = MinVT; + } + + unsigned NumParts = TLI.getNumRegisters(*DAG.getContext(), VT); + EVT PartVT = TLI.getRegisterType(*DAG.getContext(), VT); + SmallVector Parts(NumParts); + getCopyToParts(DAG, getCurDebugLoc(), + SDValue(RetOp.getNode(), RetOp.getResNo() + j), + &Parts[0], NumParts, PartVT, ExtendKind); + + // 'inreg' on function refers to return value + ISD::ArgFlagsTy Flags = ISD::ArgFlagsTy(); + if (F->paramHasAttr(0, Attribute::InReg)) + Flags.setInReg(); + + // Propagate extension type if any + if (F->paramHasAttr(0, Attribute::SExt)) + Flags.setSExt(); + else if (F->paramHasAttr(0, Attribute::ZExt)) + Flags.setZExt(); + + for (unsigned i = 0; i < NumParts; ++i) + Outs.push_back(ISD::OutputArg(Flags, Parts[i], /*isfixed=*/true)); + } + } + } + + bool isVarArg = DAG.getMachineFunction().getFunction()->isVarArg(); + CallingConv::ID CallConv = + DAG.getMachineFunction().getFunction()->getCallingConv(); + Chain = TLI.LowerReturn(Chain, CallConv, isVarArg, + Outs, getCurDebugLoc(), DAG); + + // Verify that the target's LowerReturn behaved as expected. + assert(Chain.getNode() && Chain.getValueType() == MVT::Other && + "LowerReturn didn't return a valid chain!"); + + // Update the DAG with the new chain value resulting from return lowering. + DAG.setRoot(Chain); +} + +/// CopyToExportRegsIfNeeded - If the given value has virtual registers +/// created for it, emit nodes to copy the value into the virtual +/// registers. +void SelectionDAGBuilder::CopyToExportRegsIfNeeded(Value *V) { + if (!V->use_empty()) { + DenseMap::iterator VMI = FuncInfo.ValueMap.find(V); + if (VMI != FuncInfo.ValueMap.end()) + CopyValueToVirtualRegister(V, VMI->second); + } +} + +/// ExportFromCurrentBlock - If this condition isn't known to be exported from +/// the current basic block, add it to ValueMap now so that we'll get a +/// CopyTo/FromReg. +void SelectionDAGBuilder::ExportFromCurrentBlock(Value *V) { + // No need to export constants. + if (!isa(V) && !isa(V)) return; + + // Already exported? + if (FuncInfo.isExportedInst(V)) return; + + unsigned Reg = FuncInfo.InitializeRegForValue(V); + CopyValueToVirtualRegister(V, Reg); +} + +bool SelectionDAGBuilder::isExportableFromCurrentBlock(Value *V, + const BasicBlock *FromBB) { + // The operands of the setcc have to be in this block. We don't know + // how to export them from some other block. + if (Instruction *VI = dyn_cast(V)) { + // Can export from current BB. + if (VI->getParent() == FromBB) + return true; + + // Is already exported, noop. + return FuncInfo.isExportedInst(V); + } + + // If this is an argument, we can export it if the BB is the entry block or + // if it is already exported. + if (isa(V)) { + if (FromBB == &FromBB->getParent()->getEntryBlock()) + return true; + + // Otherwise, can only export this if it is already exported. + return FuncInfo.isExportedInst(V); + } + + // Otherwise, constants can always be exported. + return true; +} + +static bool InBlock(const Value *V, const BasicBlock *BB) { + if (const Instruction *I = dyn_cast(V)) + return I->getParent() == BB; + return true; +} + +/// getFCmpCondCode - Return the ISD condition code corresponding to +/// the given LLVM IR floating-point condition code. This includes +/// consideration of global floating-point math flags. +/// +static ISD::CondCode getFCmpCondCode(FCmpInst::Predicate Pred) { + ISD::CondCode FPC, FOC; + switch (Pred) { + case FCmpInst::FCMP_FALSE: FOC = FPC = ISD::SETFALSE; break; + case FCmpInst::FCMP_OEQ: FOC = ISD::SETEQ; FPC = ISD::SETOEQ; break; + case FCmpInst::FCMP_OGT: FOC = ISD::SETGT; FPC = ISD::SETOGT; break; + case FCmpInst::FCMP_OGE: FOC = ISD::SETGE; FPC = ISD::SETOGE; break; + case FCmpInst::FCMP_OLT: FOC = ISD::SETLT; FPC = ISD::SETOLT; break; + case FCmpInst::FCMP_OLE: FOC = ISD::SETLE; FPC = ISD::SETOLE; break; + case FCmpInst::FCMP_ONE: FOC = ISD::SETNE; FPC = ISD::SETONE; break; + case FCmpInst::FCMP_ORD: FOC = FPC = ISD::SETO; break; + case FCmpInst::FCMP_UNO: FOC = FPC = ISD::SETUO; break; + case FCmpInst::FCMP_UEQ: FOC = ISD::SETEQ; FPC = ISD::SETUEQ; break; + case FCmpInst::FCMP_UGT: FOC = ISD::SETGT; FPC = ISD::SETUGT; break; + case FCmpInst::FCMP_UGE: FOC = ISD::SETGE; FPC = ISD::SETUGE; break; + case FCmpInst::FCMP_ULT: FOC = ISD::SETLT; FPC = ISD::SETULT; break; + case FCmpInst::FCMP_ULE: FOC = ISD::SETLE; FPC = ISD::SETULE; break; + case FCmpInst::FCMP_UNE: FOC = ISD::SETNE; FPC = ISD::SETUNE; break; + case FCmpInst::FCMP_TRUE: FOC = FPC = ISD::SETTRUE; break; + default: + llvm_unreachable("Invalid FCmp predicate opcode!"); + FOC = FPC = ISD::SETFALSE; + break; + } + if (FiniteOnlyFPMath()) + return FOC; + else + return FPC; +} + +/// getICmpCondCode - Return the ISD condition code corresponding to +/// the given LLVM IR integer condition code. +/// +static ISD::CondCode getICmpCondCode(ICmpInst::Predicate Pred) { + switch (Pred) { + case ICmpInst::ICMP_EQ: return ISD::SETEQ; + case ICmpInst::ICMP_NE: return ISD::SETNE; + case ICmpInst::ICMP_SLE: return ISD::SETLE; + case ICmpInst::ICMP_ULE: return ISD::SETULE; + case ICmpInst::ICMP_SGE: return ISD::SETGE; + case ICmpInst::ICMP_UGE: return ISD::SETUGE; + case ICmpInst::ICMP_SLT: return ISD::SETLT; + case ICmpInst::ICMP_ULT: return ISD::SETULT; + case ICmpInst::ICMP_SGT: return ISD::SETGT; + case ICmpInst::ICMP_UGT: return ISD::SETUGT; + default: + llvm_unreachable("Invalid ICmp predicate opcode!"); + return ISD::SETNE; + } +} + +/// EmitBranchForMergedCondition - Helper method for FindMergedConditions. +/// This function emits a branch and is used at the leaves of an OR or an +/// AND operator tree. +/// +void +SelectionDAGBuilder::EmitBranchForMergedCondition(Value *Cond, + MachineBasicBlock *TBB, + MachineBasicBlock *FBB, + MachineBasicBlock *CurBB) { + const BasicBlock *BB = CurBB->getBasicBlock(); + + // If the leaf of the tree is a comparison, merge the condition into + // the caseblock. + if (CmpInst *BOp = dyn_cast(Cond)) { + // The operands of the cmp have to be in this block. We don't know + // how to export them from some other block. If this is the first block + // of the sequence, no exporting is needed. + if (CurBB == CurMBB || + (isExportableFromCurrentBlock(BOp->getOperand(0), BB) && + isExportableFromCurrentBlock(BOp->getOperand(1), BB))) { + ISD::CondCode Condition; + if (ICmpInst *IC = dyn_cast(Cond)) { + Condition = getICmpCondCode(IC->getPredicate()); + } else if (FCmpInst *FC = dyn_cast(Cond)) { + Condition = getFCmpCondCode(FC->getPredicate()); + } else { + Condition = ISD::SETEQ; // silence warning. + llvm_unreachable("Unknown compare instruction"); + } + + CaseBlock CB(Condition, BOp->getOperand(0), + BOp->getOperand(1), NULL, TBB, FBB, CurBB); + SwitchCases.push_back(CB); + return; + } + } + + // Create a CaseBlock record representing this branch. + CaseBlock CB(ISD::SETEQ, Cond, ConstantInt::getTrue(*DAG.getContext()), + NULL, TBB, FBB, CurBB); + SwitchCases.push_back(CB); +} + +/// FindMergedConditions - If Cond is an expression like +void SelectionDAGBuilder::FindMergedConditions(Value *Cond, + MachineBasicBlock *TBB, + MachineBasicBlock *FBB, + MachineBasicBlock *CurBB, + unsigned Opc) { + // If this node is not part of the or/and tree, emit it as a branch. + Instruction *BOp = dyn_cast(Cond); + if (!BOp || !(isa(BOp) || isa(BOp)) || + (unsigned)BOp->getOpcode() != Opc || !BOp->hasOneUse() || + BOp->getParent() != CurBB->getBasicBlock() || + !InBlock(BOp->getOperand(0), CurBB->getBasicBlock()) || + !InBlock(BOp->getOperand(1), CurBB->getBasicBlock())) { + EmitBranchForMergedCondition(Cond, TBB, FBB, CurBB); + return; + } + + // Create TmpBB after CurBB. + MachineFunction::iterator BBI = CurBB; + MachineFunction &MF = DAG.getMachineFunction(); + MachineBasicBlock *TmpBB = MF.CreateMachineBasicBlock(CurBB->getBasicBlock()); + CurBB->getParent()->insert(++BBI, TmpBB); + + if (Opc == Instruction::Or) { + // Codegen X | Y as: + // jmp_if_X TBB + // jmp TmpBB + // TmpBB: + // jmp_if_Y TBB + // jmp FBB + // + + // Emit the LHS condition. + FindMergedConditions(BOp->getOperand(0), TBB, TmpBB, CurBB, Opc); + + // Emit the RHS condition into TmpBB. + FindMergedConditions(BOp->getOperand(1), TBB, FBB, TmpBB, Opc); + } else { + assert(Opc == Instruction::And && "Unknown merge op!"); + // Codegen X & Y as: + // jmp_if_X TmpBB + // jmp FBB + // TmpBB: + // jmp_if_Y TBB + // jmp FBB + // + // This requires creation of TmpBB after CurBB. + + // Emit the LHS condition. + FindMergedConditions(BOp->getOperand(0), TmpBB, FBB, CurBB, Opc); + + // Emit the RHS condition into TmpBB. + FindMergedConditions(BOp->getOperand(1), TBB, FBB, TmpBB, Opc); + } +} + +/// If the set of cases should be emitted as a series of branches, return true. +/// If we should emit this as a bunch of and/or'd together conditions, return +/// false. +bool +SelectionDAGBuilder::ShouldEmitAsBranches(const std::vector &Cases){ + if (Cases.size() != 2) return true; + + // If this is two comparisons of the same values or'd or and'd together, they + // will get folded into a single comparison, so don't emit two blocks. + if ((Cases[0].CmpLHS == Cases[1].CmpLHS && + Cases[0].CmpRHS == Cases[1].CmpRHS) || + (Cases[0].CmpRHS == Cases[1].CmpLHS && + Cases[0].CmpLHS == Cases[1].CmpRHS)) { + return false; + } + + return true; +} + +void SelectionDAGBuilder::visitBr(BranchInst &I) { + // Update machine-CFG edges. + MachineBasicBlock *Succ0MBB = FuncInfo.MBBMap[I.getSuccessor(0)]; + + // Figure out which block is immediately after the current one. + MachineBasicBlock *NextBlock = 0; + MachineFunction::iterator BBI = CurMBB; + if (++BBI != FuncInfo.MF->end()) + NextBlock = BBI; + + if (I.isUnconditional()) { + // Update machine-CFG edges. + CurMBB->addSuccessor(Succ0MBB); + + // If this is not a fall-through branch, emit the branch. + if (Succ0MBB != NextBlock) + DAG.setRoot(DAG.getNode(ISD::BR, getCurDebugLoc(), + MVT::Other, getControlRoot(), + DAG.getBasicBlock(Succ0MBB))); + return; + } + + // If this condition is one of the special cases we handle, do special stuff + // now. + Value *CondVal = I.getCondition(); + MachineBasicBlock *Succ1MBB = FuncInfo.MBBMap[I.getSuccessor(1)]; + + // If this is a series of conditions that are or'd or and'd together, emit + // this as a sequence of branches instead of setcc's with and/or operations. + // For example, instead of something like: + // cmp A, B + // C = seteq + // cmp D, E + // F = setle + // or C, F + // jnz foo + // Emit: + // cmp A, B + // je foo + // cmp D, E + // jle foo + // + if (BinaryOperator *BOp = dyn_cast(CondVal)) { + if (BOp->hasOneUse() && + (BOp->getOpcode() == Instruction::And || + BOp->getOpcode() == Instruction::Or)) { + FindMergedConditions(BOp, Succ0MBB, Succ1MBB, CurMBB, BOp->getOpcode()); + // If the compares in later blocks need to use values not currently + // exported from this block, export them now. This block should always + // be the first entry. + assert(SwitchCases[0].ThisBB == CurMBB && "Unexpected lowering!"); + + // Allow some cases to be rejected. + if (ShouldEmitAsBranches(SwitchCases)) { + for (unsigned i = 1, e = SwitchCases.size(); i != e; ++i) { + ExportFromCurrentBlock(SwitchCases[i].CmpLHS); + ExportFromCurrentBlock(SwitchCases[i].CmpRHS); + } + + // Emit the branch for this block. + visitSwitchCase(SwitchCases[0]); + SwitchCases.erase(SwitchCases.begin()); + return; + } + + // Okay, we decided not to do this, remove any inserted MBB's and clear + // SwitchCases. + for (unsigned i = 1, e = SwitchCases.size(); i != e; ++i) + FuncInfo.MF->erase(SwitchCases[i].ThisBB); + + SwitchCases.clear(); + } + } + + // Create a CaseBlock record representing this branch. + CaseBlock CB(ISD::SETEQ, CondVal, ConstantInt::getTrue(*DAG.getContext()), + NULL, Succ0MBB, Succ1MBB, CurMBB); + // Use visitSwitchCase to actually insert the fast branch sequence for this + // cond branch. + visitSwitchCase(CB); +} + +/// visitSwitchCase - Emits the necessary code to represent a single node in +/// the binary search tree resulting from lowering a switch instruction. +void SelectionDAGBuilder::visitSwitchCase(CaseBlock &CB) { + SDValue Cond; + SDValue CondLHS = getValue(CB.CmpLHS); + DebugLoc dl = getCurDebugLoc(); + + // Build the setcc now. + if (CB.CmpMHS == NULL) { + // Fold "(X == true)" to X and "(X == false)" to !X to + // handle common cases produced by branch lowering. + if (CB.CmpRHS == ConstantInt::getTrue(*DAG.getContext()) && + CB.CC == ISD::SETEQ) + Cond = CondLHS; + else if (CB.CmpRHS == ConstantInt::getFalse(*DAG.getContext()) && + CB.CC == ISD::SETEQ) { + SDValue True = DAG.getConstant(1, CondLHS.getValueType()); + Cond = DAG.getNode(ISD::XOR, dl, CondLHS.getValueType(), CondLHS, True); + } else + Cond = DAG.getSetCC(dl, MVT::i1, CondLHS, getValue(CB.CmpRHS), CB.CC); + } else { + assert(CB.CC == ISD::SETLE && "Can handle only LE ranges now"); + + const APInt& Low = cast(CB.CmpLHS)->getValue(); + const APInt& High = cast(CB.CmpRHS)->getValue(); + + SDValue CmpOp = getValue(CB.CmpMHS); + EVT VT = CmpOp.getValueType(); + + if (cast(CB.CmpLHS)->isMinValue(true)) { + Cond = DAG.getSetCC(dl, MVT::i1, CmpOp, DAG.getConstant(High, VT), + ISD::SETLE); + } else { + SDValue SUB = DAG.getNode(ISD::SUB, dl, + VT, CmpOp, DAG.getConstant(Low, VT)); + Cond = DAG.getSetCC(dl, MVT::i1, SUB, + DAG.getConstant(High-Low, VT), ISD::SETULE); + } + } + + // Update successor info + CurMBB->addSuccessor(CB.TrueBB); + CurMBB->addSuccessor(CB.FalseBB); + + // Set NextBlock to be the MBB immediately after the current one, if any. + // This is used to avoid emitting unnecessary branches to the next block. + MachineBasicBlock *NextBlock = 0; + MachineFunction::iterator BBI = CurMBB; + if (++BBI != FuncInfo.MF->end()) + NextBlock = BBI; + + // If the lhs block is the next block, invert the condition so that we can + // fall through to the lhs instead of the rhs block. + if (CB.TrueBB == NextBlock) { + std::swap(CB.TrueBB, CB.FalseBB); + SDValue True = DAG.getConstant(1, Cond.getValueType()); + Cond = DAG.getNode(ISD::XOR, dl, Cond.getValueType(), Cond, True); + } + SDValue BrCond = DAG.getNode(ISD::BRCOND, dl, + MVT::Other, getControlRoot(), Cond, + DAG.getBasicBlock(CB.TrueBB)); + + // If the branch was constant folded, fix up the CFG. + if (BrCond.getOpcode() == ISD::BR) { + CurMBB->removeSuccessor(CB.FalseBB); + DAG.setRoot(BrCond); + } else { + // Otherwise, go ahead and insert the false branch. + if (BrCond == getControlRoot()) + CurMBB->removeSuccessor(CB.TrueBB); + + if (CB.FalseBB == NextBlock) + DAG.setRoot(BrCond); + else + DAG.setRoot(DAG.getNode(ISD::BR, dl, MVT::Other, BrCond, + DAG.getBasicBlock(CB.FalseBB))); + } +} + +/// visitJumpTable - Emit JumpTable node in the current MBB +void SelectionDAGBuilder::visitJumpTable(JumpTable &JT) { + // Emit the code for the jump table + assert(JT.Reg != -1U && "Should lower JT Header first!"); + EVT PTy = TLI.getPointerTy(); + SDValue Index = DAG.getCopyFromReg(getControlRoot(), getCurDebugLoc(), + JT.Reg, PTy); + SDValue Table = DAG.getJumpTable(JT.JTI, PTy); + DAG.setRoot(DAG.getNode(ISD::BR_JT, getCurDebugLoc(), + MVT::Other, Index.getValue(1), + Table, Index)); +} + +/// visitJumpTableHeader - This function emits necessary code to produce index +/// in the JumpTable from switch case. +void SelectionDAGBuilder::visitJumpTableHeader(JumpTable &JT, + JumpTableHeader &JTH) { + // Subtract the lowest switch case value from the value being switched on and + // conditional branch to default mbb if the result is greater than the + // difference between smallest and largest cases. + SDValue SwitchOp = getValue(JTH.SValue); + EVT VT = SwitchOp.getValueType(); + SDValue SUB = DAG.getNode(ISD::SUB, getCurDebugLoc(), VT, SwitchOp, + DAG.getConstant(JTH.First, VT)); + + // The SDNode we just created, which holds the value being switched on minus + // the the smallest case value, needs to be copied to a virtual register so it + // can be used as an index into the jump table in a subsequent basic block. + // This value may be smaller or larger than the target's pointer type, and + // therefore require extension or truncating. + SwitchOp = DAG.getZExtOrTrunc(SUB, getCurDebugLoc(), TLI.getPointerTy()); + + unsigned JumpTableReg = FuncInfo.MakeReg(TLI.getPointerTy()); + SDValue CopyTo = DAG.getCopyToReg(getControlRoot(), getCurDebugLoc(), + JumpTableReg, SwitchOp); + JT.Reg = JumpTableReg; + + // Emit the range check for the jump table, and branch to the default block + // for the switch statement if the value being switched on exceeds the largest + // case in the switch. + SDValue CMP = DAG.getSetCC(getCurDebugLoc(), + TLI.getSetCCResultType(SUB.getValueType()), SUB, + DAG.getConstant(JTH.Last-JTH.First,VT), + ISD::SETUGT); + + // Set NextBlock to be the MBB immediately after the current one, if any. + // This is used to avoid emitting unnecessary branches to the next block. + MachineBasicBlock *NextBlock = 0; + MachineFunction::iterator BBI = CurMBB; + if (++BBI != FuncInfo.MF->end()) + NextBlock = BBI; + + SDValue BrCond = DAG.getNode(ISD::BRCOND, getCurDebugLoc(), + MVT::Other, CopyTo, CMP, + DAG.getBasicBlock(JT.Default)); + + if (JT.MBB == NextBlock) + DAG.setRoot(BrCond); + else + DAG.setRoot(DAG.getNode(ISD::BR, getCurDebugLoc(), MVT::Other, BrCond, + DAG.getBasicBlock(JT.MBB))); +} + +/// visitBitTestHeader - This function emits necessary code to produce value +/// suitable for "bit tests" +void SelectionDAGBuilder::visitBitTestHeader(BitTestBlock &B) { + // Subtract the minimum value + SDValue SwitchOp = getValue(B.SValue); + EVT VT = SwitchOp.getValueType(); + SDValue SUB = DAG.getNode(ISD::SUB, getCurDebugLoc(), VT, SwitchOp, + DAG.getConstant(B.First, VT)); + + // Check range + SDValue RangeCmp = DAG.getSetCC(getCurDebugLoc(), + TLI.getSetCCResultType(SUB.getValueType()), + SUB, DAG.getConstant(B.Range, VT), + ISD::SETUGT); + + SDValue ShiftOp = DAG.getZExtOrTrunc(SUB, getCurDebugLoc(), TLI.getPointerTy()); + + B.Reg = FuncInfo.MakeReg(TLI.getPointerTy()); + SDValue CopyTo = DAG.getCopyToReg(getControlRoot(), getCurDebugLoc(), + B.Reg, ShiftOp); + + // Set NextBlock to be the MBB immediately after the current one, if any. + // This is used to avoid emitting unnecessary branches to the next block. + MachineBasicBlock *NextBlock = 0; + MachineFunction::iterator BBI = CurMBB; + if (++BBI != FuncInfo.MF->end()) + NextBlock = BBI; + + MachineBasicBlock* MBB = B.Cases[0].ThisBB; + + CurMBB->addSuccessor(B.Default); + CurMBB->addSuccessor(MBB); + + SDValue BrRange = DAG.getNode(ISD::BRCOND, getCurDebugLoc(), + MVT::Other, CopyTo, RangeCmp, + DAG.getBasicBlock(B.Default)); + + if (MBB == NextBlock) + DAG.setRoot(BrRange); + else + DAG.setRoot(DAG.getNode(ISD::BR, getCurDebugLoc(), MVT::Other, CopyTo, + DAG.getBasicBlock(MBB))); +} + +/// visitBitTestCase - this function produces one "bit test" +void SelectionDAGBuilder::visitBitTestCase(MachineBasicBlock* NextMBB, + unsigned Reg, + BitTestCase &B) { + // Make desired shift + SDValue ShiftOp = DAG.getCopyFromReg(getControlRoot(), getCurDebugLoc(), Reg, + TLI.getPointerTy()); + SDValue SwitchVal = DAG.getNode(ISD::SHL, getCurDebugLoc(), + TLI.getPointerTy(), + DAG.getConstant(1, TLI.getPointerTy()), + ShiftOp); + + // Emit bit tests and jumps + SDValue AndOp = DAG.getNode(ISD::AND, getCurDebugLoc(), + TLI.getPointerTy(), SwitchVal, + DAG.getConstant(B.Mask, TLI.getPointerTy())); + SDValue AndCmp = DAG.getSetCC(getCurDebugLoc(), + TLI.getSetCCResultType(AndOp.getValueType()), + AndOp, DAG.getConstant(0, TLI.getPointerTy()), + ISD::SETNE); + + CurMBB->addSuccessor(B.TargetBB); + CurMBB->addSuccessor(NextMBB); + + SDValue BrAnd = DAG.getNode(ISD::BRCOND, getCurDebugLoc(), + MVT::Other, getControlRoot(), + AndCmp, DAG.getBasicBlock(B.TargetBB)); + + // Set NextBlock to be the MBB immediately after the current one, if any. + // This is used to avoid emitting unnecessary branches to the next block. + MachineBasicBlock *NextBlock = 0; + MachineFunction::iterator BBI = CurMBB; + if (++BBI != FuncInfo.MF->end()) + NextBlock = BBI; + + if (NextMBB == NextBlock) + DAG.setRoot(BrAnd); + else + DAG.setRoot(DAG.getNode(ISD::BR, getCurDebugLoc(), MVT::Other, BrAnd, + DAG.getBasicBlock(NextMBB))); +} + +void SelectionDAGBuilder::visitInvoke(InvokeInst &I) { + // Retrieve successors. + MachineBasicBlock *Return = FuncInfo.MBBMap[I.getSuccessor(0)]; + MachineBasicBlock *LandingPad = FuncInfo.MBBMap[I.getSuccessor(1)]; + + const Value *Callee(I.getCalledValue()); + if (isa(Callee)) + visitInlineAsm(&I); + else + LowerCallTo(&I, getValue(Callee), false, LandingPad); + + // If the value of the invoke is used outside of its defining block, make it + // available as a virtual register. + CopyToExportRegsIfNeeded(&I); + + // Update successor info + CurMBB->addSuccessor(Return); + CurMBB->addSuccessor(LandingPad); + + // Drop into normal successor. + DAG.setRoot(DAG.getNode(ISD::BR, getCurDebugLoc(), + MVT::Other, getControlRoot(), + DAG.getBasicBlock(Return))); +} + +void SelectionDAGBuilder::visitUnwind(UnwindInst &I) { +} + +/// handleSmallSwitchCaseRange - Emit a series of specific tests (suitable for +/// small case ranges). +bool SelectionDAGBuilder::handleSmallSwitchRange(CaseRec& CR, + CaseRecVector& WorkList, + Value* SV, + MachineBasicBlock* Default) { + Case& BackCase = *(CR.Range.second-1); + + // Size is the number of Cases represented by this range. + size_t Size = CR.Range.second - CR.Range.first; + if (Size > 3) + return false; + + // Get the MachineFunction which holds the current MBB. This is used when + // inserting any additional MBBs necessary to represent the switch. + MachineFunction *CurMF = FuncInfo.MF; + + // Figure out which block is immediately after the current one. + MachineBasicBlock *NextBlock = 0; + MachineFunction::iterator BBI = CR.CaseBB; + + if (++BBI != FuncInfo.MF->end()) + NextBlock = BBI; + + // TODO: If any two of the cases has the same destination, and if one value + // is the same as the other, but has one bit unset that the other has set, + // use bit manipulation to do two compares at once. For example: + // "if (X == 6 || X == 4)" -> "if ((X|2) == 6)" + + // Rearrange the case blocks so that the last one falls through if possible. + if (NextBlock && Default != NextBlock && BackCase.BB != NextBlock) { + // The last case block won't fall through into 'NextBlock' if we emit the + // branches in this order. See if rearranging a case value would help. + for (CaseItr I = CR.Range.first, E = CR.Range.second-1; I != E; ++I) { + if (I->BB == NextBlock) { + std::swap(*I, BackCase); + break; + } + } + } + + // Create a CaseBlock record representing a conditional branch to + // the Case's target mbb if the value being switched on SV is equal + // to C. + MachineBasicBlock *CurBlock = CR.CaseBB; + for (CaseItr I = CR.Range.first, E = CR.Range.second; I != E; ++I) { + MachineBasicBlock *FallThrough; + if (I != E-1) { + FallThrough = CurMF->CreateMachineBasicBlock(CurBlock->getBasicBlock()); + CurMF->insert(BBI, FallThrough); + + // Put SV in a virtual register to make it available from the new blocks. + ExportFromCurrentBlock(SV); + } else { + // If the last case doesn't match, go to the default block. + FallThrough = Default; + } + + Value *RHS, *LHS, *MHS; + ISD::CondCode CC; + if (I->High == I->Low) { + // This is just small small case range :) containing exactly 1 case + CC = ISD::SETEQ; + LHS = SV; RHS = I->High; MHS = NULL; + } else { + CC = ISD::SETLE; + LHS = I->Low; MHS = SV; RHS = I->High; + } + CaseBlock CB(CC, LHS, RHS, MHS, I->BB, FallThrough, CurBlock); + + // If emitting the first comparison, just call visitSwitchCase to emit the + // code into the current block. Otherwise, push the CaseBlock onto the + // vector to be later processed by SDISel, and insert the node's MBB + // before the next MBB. + if (CurBlock == CurMBB) + visitSwitchCase(CB); + else + SwitchCases.push_back(CB); + + CurBlock = FallThrough; + } + + return true; +} + +static inline bool areJTsAllowed(const TargetLowering &TLI) { + return !DisableJumpTables && + (TLI.isOperationLegalOrCustom(ISD::BR_JT, MVT::Other) || + TLI.isOperationLegalOrCustom(ISD::BRIND, MVT::Other)); +} + +static APInt ComputeRange(const APInt &First, const APInt &Last) { + APInt LastExt(Last), FirstExt(First); + uint32_t BitWidth = std::max(Last.getBitWidth(), First.getBitWidth()) + 1; + LastExt.sext(BitWidth); FirstExt.sext(BitWidth); + return (LastExt - FirstExt + 1ULL); +} + +/// handleJTSwitchCase - Emit jumptable for current switch case range +bool SelectionDAGBuilder::handleJTSwitchCase(CaseRec& CR, + CaseRecVector& WorkList, + Value* SV, + MachineBasicBlock* Default) { + Case& FrontCase = *CR.Range.first; + Case& BackCase = *(CR.Range.second-1); + + const APInt &First = cast(FrontCase.Low)->getValue(); + const APInt &Last = cast(BackCase.High)->getValue(); + + APInt TSize(First.getBitWidth(), 0); + for (CaseItr I = CR.Range.first, E = CR.Range.second; + I!=E; ++I) + TSize += I->size(); + + if (!areJTsAllowed(TLI) || TSize.ult(APInt(First.getBitWidth(), 4))) + return false; + + APInt Range = ComputeRange(First, Last); + double Density = TSize.roundToDouble() / Range.roundToDouble(); + if (Density < 0.4) + return false; + + DEBUG(errs() << "Lowering jump table\n" + << "First entry: " << First << ". Last entry: " << Last << '\n' + << "Range: " << Range + << "Size: " << TSize << ". Density: " << Density << "\n\n"); + + // Get the MachineFunction which holds the current MBB. This is used when + // inserting any additional MBBs necessary to represent the switch. + MachineFunction *CurMF = FuncInfo.MF; + + // Figure out which block is immediately after the current one. + MachineFunction::iterator BBI = CR.CaseBB; + ++BBI; + + const BasicBlock *LLVMBB = CR.CaseBB->getBasicBlock(); + + // Create a new basic block to hold the code for loading the address + // of the jump table, and jumping to it. Update successor information; + // we will either branch to the default case for the switch, or the jump + // table. + MachineBasicBlock *JumpTableBB = CurMF->CreateMachineBasicBlock(LLVMBB); + CurMF->insert(BBI, JumpTableBB); + CR.CaseBB->addSuccessor(Default); + CR.CaseBB->addSuccessor(JumpTableBB); + + // Build a vector of destination BBs, corresponding to each target + // of the jump table. If the value of the jump table slot corresponds to + // a case statement, push the case's BB onto the vector, otherwise, push + // the default BB. + std::vector DestBBs; + APInt TEI = First; + for (CaseItr I = CR.Range.first, E = CR.Range.second; I != E; ++TEI) { + const APInt& Low = cast(I->Low)->getValue(); + const APInt& High = cast(I->High)->getValue(); + + if (Low.sle(TEI) && TEI.sle(High)) { + DestBBs.push_back(I->BB); + if (TEI==High) + ++I; + } else { + DestBBs.push_back(Default); + } + } + + // Update successor info. Add one edge to each unique successor. + BitVector SuccsHandled(CR.CaseBB->getParent()->getNumBlockIDs()); + for (std::vector::iterator I = DestBBs.begin(), + E = DestBBs.end(); I != E; ++I) { + if (!SuccsHandled[(*I)->getNumber()]) { + SuccsHandled[(*I)->getNumber()] = true; + JumpTableBB->addSuccessor(*I); + } + } + + // Create a jump table index for this jump table, or return an existing + // one. + unsigned JTI = CurMF->getJumpTableInfo()->getJumpTableIndex(DestBBs); + + // Set the jump table information so that we can codegen it as a second + // MachineBasicBlock + JumpTable JT(-1U, JTI, JumpTableBB, Default); + JumpTableHeader JTH(First, Last, SV, CR.CaseBB, (CR.CaseBB == CurMBB)); + if (CR.CaseBB == CurMBB) + visitJumpTableHeader(JT, JTH); + + JTCases.push_back(JumpTableBlock(JTH, JT)); + + return true; +} + +/// handleBTSplitSwitchCase - emit comparison and split binary search tree into +/// 2 subtrees. +bool SelectionDAGBuilder::handleBTSplitSwitchCase(CaseRec& CR, + CaseRecVector& WorkList, + Value* SV, + MachineBasicBlock* Default) { + // Get the MachineFunction which holds the current MBB. This is used when + // inserting any additional MBBs necessary to represent the switch. + MachineFunction *CurMF = FuncInfo.MF; + + // Figure out which block is immediately after the current one. + MachineFunction::iterator BBI = CR.CaseBB; + ++BBI; + + Case& FrontCase = *CR.Range.first; + Case& BackCase = *(CR.Range.second-1); + const BasicBlock *LLVMBB = CR.CaseBB->getBasicBlock(); + + // Size is the number of Cases represented by this range. + unsigned Size = CR.Range.second - CR.Range.first; + + const APInt &First = cast(FrontCase.Low)->getValue(); + const APInt &Last = cast(BackCase.High)->getValue(); + double FMetric = 0; + CaseItr Pivot = CR.Range.first + Size/2; + + // Select optimal pivot, maximizing sum density of LHS and RHS. This will + // (heuristically) allow us to emit JumpTable's later. + APInt TSize(First.getBitWidth(), 0); + for (CaseItr I = CR.Range.first, E = CR.Range.second; + I!=E; ++I) + TSize += I->size(); + + APInt LSize = FrontCase.size(); + APInt RSize = TSize-LSize; + DEBUG(errs() << "Selecting best pivot: \n" + << "First: " << First << ", Last: " << Last <<'\n' + << "LSize: " << LSize << ", RSize: " << RSize << '\n'); + for (CaseItr I = CR.Range.first, J=I+1, E = CR.Range.second; + J!=E; ++I, ++J) { + const APInt &LEnd = cast(I->High)->getValue(); + const APInt &RBegin = cast(J->Low)->getValue(); + APInt Range = ComputeRange(LEnd, RBegin); + assert((Range - 2ULL).isNonNegative() && + "Invalid case distance"); + double LDensity = (double)LSize.roundToDouble() / + (LEnd - First + 1ULL).roundToDouble(); + double RDensity = (double)RSize.roundToDouble() / + (Last - RBegin + 1ULL).roundToDouble(); + double Metric = Range.logBase2()*(LDensity+RDensity); + // Should always split in some non-trivial place + DEBUG(errs() <<"=>Step\n" + << "LEnd: " << LEnd << ", RBegin: " << RBegin << '\n' + << "LDensity: " << LDensity + << ", RDensity: " << RDensity << '\n' + << "Metric: " << Metric << '\n'); + if (FMetric < Metric) { + Pivot = J; + FMetric = Metric; + DEBUG(errs() << "Current metric set to: " << FMetric << '\n'); + } + + LSize += J->size(); + RSize -= J->size(); + } + if (areJTsAllowed(TLI)) { + // If our case is dense we *really* should handle it earlier! + assert((FMetric > 0) && "Should handle dense range earlier!"); + } else { + Pivot = CR.Range.first + Size/2; + } + + CaseRange LHSR(CR.Range.first, Pivot); + CaseRange RHSR(Pivot, CR.Range.second); + Constant *C = Pivot->Low; + MachineBasicBlock *FalseBB = 0, *TrueBB = 0; + + // We know that we branch to the LHS if the Value being switched on is + // less than the Pivot value, C. We use this to optimize our binary + // tree a bit, by recognizing that if SV is greater than or equal to the + // LHS's Case Value, and that Case Value is exactly one less than the + // Pivot's Value, then we can branch directly to the LHS's Target, + // rather than creating a leaf node for it. + if ((LHSR.second - LHSR.first) == 1 && + LHSR.first->High == CR.GE && + cast(C)->getValue() == + (cast(CR.GE)->getValue() + 1LL)) { + TrueBB = LHSR.first->BB; + } else { + TrueBB = CurMF->CreateMachineBasicBlock(LLVMBB); + CurMF->insert(BBI, TrueBB); + WorkList.push_back(CaseRec(TrueBB, C, CR.GE, LHSR)); + + // Put SV in a virtual register to make it available from the new blocks. + ExportFromCurrentBlock(SV); + } + + // Similar to the optimization above, if the Value being switched on is + // known to be less than the Constant CR.LT, and the current Case Value + // is CR.LT - 1, then we can branch directly to the target block for + // the current Case Value, rather than emitting a RHS leaf node for it. + if ((RHSR.second - RHSR.first) == 1 && CR.LT && + cast(RHSR.first->Low)->getValue() == + (cast(CR.LT)->getValue() - 1LL)) { + FalseBB = RHSR.first->BB; + } else { + FalseBB = CurMF->CreateMachineBasicBlock(LLVMBB); + CurMF->insert(BBI, FalseBB); + WorkList.push_back(CaseRec(FalseBB,CR.LT,C,RHSR)); + + // Put SV in a virtual register to make it available from the new blocks. + ExportFromCurrentBlock(SV); + } + + // Create a CaseBlock record representing a conditional branch to + // the LHS node if the value being switched on SV is less than C. + // Otherwise, branch to LHS. + CaseBlock CB(ISD::SETLT, SV, C, NULL, TrueBB, FalseBB, CR.CaseBB); + + if (CR.CaseBB == CurMBB) + visitSwitchCase(CB); + else + SwitchCases.push_back(CB); + + return true; +} + +/// handleBitTestsSwitchCase - if current case range has few destination and +/// range span less, than machine word bitwidth, encode case range into series +/// of masks and emit bit tests with these masks. +bool SelectionDAGBuilder::handleBitTestsSwitchCase(CaseRec& CR, + CaseRecVector& WorkList, + Value* SV, + MachineBasicBlock* Default){ + EVT PTy = TLI.getPointerTy(); + unsigned IntPtrBits = PTy.getSizeInBits(); + + Case& FrontCase = *CR.Range.first; + Case& BackCase = *(CR.Range.second-1); + + // Get the MachineFunction which holds the current MBB. This is used when + // inserting any additional MBBs necessary to represent the switch. + MachineFunction *CurMF = FuncInfo.MF; + + // If target does not have legal shift left, do not emit bit tests at all. + if (!TLI.isOperationLegal(ISD::SHL, TLI.getPointerTy())) + return false; + + size_t numCmps = 0; + for (CaseItr I = CR.Range.first, E = CR.Range.second; + I!=E; ++I) { + // Single case counts one, case range - two. + numCmps += (I->Low == I->High ? 1 : 2); + } + + // Count unique destinations + SmallSet Dests; + for (CaseItr I = CR.Range.first, E = CR.Range.second; I!=E; ++I) { + Dests.insert(I->BB); + if (Dests.size() > 3) + // Don't bother the code below, if there are too much unique destinations + return false; + } + DEBUG(errs() << "Total number of unique destinations: " << Dests.size() << '\n' + << "Total number of comparisons: " << numCmps << '\n'); + + // Compute span of values. + const APInt& minValue = cast(FrontCase.Low)->getValue(); + const APInt& maxValue = cast(BackCase.High)->getValue(); + APInt cmpRange = maxValue - minValue; + + DEBUG(errs() << "Compare range: " << cmpRange << '\n' + << "Low bound: " << minValue << '\n' + << "High bound: " << maxValue << '\n'); + + if (cmpRange.uge(APInt(cmpRange.getBitWidth(), IntPtrBits)) || + (!(Dests.size() == 1 && numCmps >= 3) && + !(Dests.size() == 2 && numCmps >= 5) && + !(Dests.size() >= 3 && numCmps >= 6))) + return false; + + DEBUG(errs() << "Emitting bit tests\n"); + APInt lowBound = APInt::getNullValue(cmpRange.getBitWidth()); + + // Optimize the case where all the case values fit in a + // word without having to subtract minValue. In this case, + // we can optimize away the subtraction. + if (minValue.isNonNegative() && + maxValue.slt(APInt(maxValue.getBitWidth(), IntPtrBits))) { + cmpRange = maxValue; + } else { + lowBound = minValue; + } + + CaseBitsVector CasesBits; + unsigned i, count = 0; + + for (CaseItr I = CR.Range.first, E = CR.Range.second; I!=E; ++I) { + MachineBasicBlock* Dest = I->BB; + for (i = 0; i < count; ++i) + if (Dest == CasesBits[i].BB) + break; + + if (i == count) { + assert((count < 3) && "Too much destinations to test!"); + CasesBits.push_back(CaseBits(0, Dest, 0)); + count++; + } + + const APInt& lowValue = cast(I->Low)->getValue(); + const APInt& highValue = cast(I->High)->getValue(); + + uint64_t lo = (lowValue - lowBound).getZExtValue(); + uint64_t hi = (highValue - lowBound).getZExtValue(); + + for (uint64_t j = lo; j <= hi; j++) { + CasesBits[i].Mask |= 1ULL << j; + CasesBits[i].Bits++; + } + + } + std::sort(CasesBits.begin(), CasesBits.end(), CaseBitsCmp()); + + BitTestInfo BTC; + + // Figure out which block is immediately after the current one. + MachineFunction::iterator BBI = CR.CaseBB; + ++BBI; + + const BasicBlock *LLVMBB = CR.CaseBB->getBasicBlock(); + + DEBUG(errs() << "Cases:\n"); + for (unsigned i = 0, e = CasesBits.size(); i!=e; ++i) { + DEBUG(errs() << "Mask: " << CasesBits[i].Mask + << ", Bits: " << CasesBits[i].Bits + << ", BB: " << CasesBits[i].BB << '\n'); + + MachineBasicBlock *CaseBB = CurMF->CreateMachineBasicBlock(LLVMBB); + CurMF->insert(BBI, CaseBB); + BTC.push_back(BitTestCase(CasesBits[i].Mask, + CaseBB, + CasesBits[i].BB)); + + // Put SV in a virtual register to make it available from the new blocks. + ExportFromCurrentBlock(SV); + } + + BitTestBlock BTB(lowBound, cmpRange, SV, + -1U, (CR.CaseBB == CurMBB), + CR.CaseBB, Default, BTC); + + if (CR.CaseBB == CurMBB) + visitBitTestHeader(BTB); + + BitTestCases.push_back(BTB); + + return true; +} + + +/// Clusterify - Transform simple list of Cases into list of CaseRange's +size_t SelectionDAGBuilder::Clusterify(CaseVector& Cases, + const SwitchInst& SI) { + size_t numCmps = 0; + + // Start with "simple" cases + for (size_t i = 1; i < SI.getNumSuccessors(); ++i) { + MachineBasicBlock *SMBB = FuncInfo.MBBMap[SI.getSuccessor(i)]; + Cases.push_back(Case(SI.getSuccessorValue(i), + SI.getSuccessorValue(i), + SMBB)); + } + std::sort(Cases.begin(), Cases.end(), CaseCmp()); + + // Merge case into clusters + if (Cases.size() >= 2) + // Must recompute end() each iteration because it may be + // invalidated by erase if we hold on to it + for (CaseItr I = Cases.begin(), J = ++(Cases.begin()); J != Cases.end(); ) { + const APInt& nextValue = cast(J->Low)->getValue(); + const APInt& currentValue = cast(I->High)->getValue(); + MachineBasicBlock* nextBB = J->BB; + MachineBasicBlock* currentBB = I->BB; + + // If the two neighboring cases go to the same destination, merge them + // into a single case. + if ((nextValue - currentValue == 1) && (currentBB == nextBB)) { + I->High = J->High; + J = Cases.erase(J); + } else { + I = J++; + } + } + + for (CaseItr I=Cases.begin(), E=Cases.end(); I!=E; ++I, ++numCmps) { + if (I->Low != I->High) + // A range counts double, since it requires two compares. + ++numCmps; + } + + return numCmps; +} + +void SelectionDAGBuilder::visitSwitch(SwitchInst &SI) { + // Figure out which block is immediately after the current one. + MachineBasicBlock *NextBlock = 0; + + MachineBasicBlock *Default = FuncInfo.MBBMap[SI.getDefaultDest()]; + + // If there is only the default destination, branch to it if it is not the + // next basic block. Otherwise, just fall through. + if (SI.getNumOperands() == 2) { + // Update machine-CFG edges. + + // If this is not a fall-through branch, emit the branch. + CurMBB->addSuccessor(Default); + if (Default != NextBlock) + DAG.setRoot(DAG.getNode(ISD::BR, getCurDebugLoc(), + MVT::Other, getControlRoot(), + DAG.getBasicBlock(Default))); + return; + } + + // If there are any non-default case statements, create a vector of Cases + // representing each one, and sort the vector so that we can efficiently + // create a binary search tree from them. + CaseVector Cases; + size_t numCmps = Clusterify(Cases, SI); + DEBUG(errs() << "Clusterify finished. Total clusters: " << Cases.size() + << ". Total compares: " << numCmps << '\n'); + numCmps = 0; + + // Get the Value to be switched on and default basic blocks, which will be + // inserted into CaseBlock records, representing basic blocks in the binary + // search tree. + Value *SV = SI.getOperand(0); + + // Push the initial CaseRec onto the worklist + CaseRecVector WorkList; + WorkList.push_back(CaseRec(CurMBB,0,0,CaseRange(Cases.begin(),Cases.end()))); + + while (!WorkList.empty()) { + // Grab a record representing a case range to process off the worklist + CaseRec CR = WorkList.back(); + WorkList.pop_back(); + + if (handleBitTestsSwitchCase(CR, WorkList, SV, Default)) + continue; + + // If the range has few cases (two or less) emit a series of specific + // tests. + if (handleSmallSwitchRange(CR, WorkList, SV, Default)) + continue; + + // If the switch has more than 5 blocks, and at least 40% dense, and the + // target supports indirect branches, then emit a jump table rather than + // lowering the switch to a binary tree of conditional branches. + if (handleJTSwitchCase(CR, WorkList, SV, Default)) + continue; + + // Emit binary tree. We need to pick a pivot, and push left and right ranges + // onto the worklist. Leafs are handled via handleSmallSwitchRange() call. + handleBTSplitSwitchCase(CR, WorkList, SV, Default); + } +} + +void SelectionDAGBuilder::visitIndirectBr(IndirectBrInst &I) { + // Update machine-CFG edges. + for (unsigned i = 0, e = I.getNumSuccessors(); i != e; ++i) + CurMBB->addSuccessor(FuncInfo.MBBMap[I.getSuccessor(i)]); + + DAG.setRoot(DAG.getNode(ISD::BRIND, getCurDebugLoc(), + MVT::Other, getControlRoot(), + getValue(I.getAddress()))); +} + + +void SelectionDAGBuilder::visitFSub(User &I) { + // -0.0 - X --> fneg + const Type *Ty = I.getType(); + if (isa(Ty)) { + if (ConstantVector *CV = dyn_cast(I.getOperand(0))) { + const VectorType *DestTy = cast(I.getType()); + const Type *ElTy = DestTy->getElementType(); + unsigned VL = DestTy->getNumElements(); + std::vector NZ(VL, ConstantFP::getNegativeZero(ElTy)); + Constant *CNZ = ConstantVector::get(&NZ[0], NZ.size()); + if (CV == CNZ) { + SDValue Op2 = getValue(I.getOperand(1)); + setValue(&I, DAG.getNode(ISD::FNEG, getCurDebugLoc(), + Op2.getValueType(), Op2)); + return; + } + } + } + if (ConstantFP *CFP = dyn_cast(I.getOperand(0))) + if (CFP->isExactlyValue(ConstantFP::getNegativeZero(Ty)->getValueAPF())) { + SDValue Op2 = getValue(I.getOperand(1)); + setValue(&I, DAG.getNode(ISD::FNEG, getCurDebugLoc(), + Op2.getValueType(), Op2)); + return; + } + + visitBinary(I, ISD::FSUB); +} + +void SelectionDAGBuilder::visitBinary(User &I, unsigned OpCode) { + SDValue Op1 = getValue(I.getOperand(0)); + SDValue Op2 = getValue(I.getOperand(1)); + + setValue(&I, DAG.getNode(OpCode, getCurDebugLoc(), + Op1.getValueType(), Op1, Op2)); +} + +void SelectionDAGBuilder::visitShift(User &I, unsigned Opcode) { + SDValue Op1 = getValue(I.getOperand(0)); + SDValue Op2 = getValue(I.getOperand(1)); + if (!isa(I.getType()) && + Op2.getValueType() != TLI.getShiftAmountTy()) { + // If the operand is smaller than the shift count type, promote it. + EVT PTy = TLI.getPointerTy(); + EVT STy = TLI.getShiftAmountTy(); + if (STy.bitsGT(Op2.getValueType())) + Op2 = DAG.getNode(ISD::ANY_EXTEND, getCurDebugLoc(), + TLI.getShiftAmountTy(), Op2); + // If the operand is larger than the shift count type but the shift + // count type has enough bits to represent any shift value, truncate + // it now. This is a common case and it exposes the truncate to + // optimization early. + else if (STy.getSizeInBits() >= + Log2_32_Ceil(Op2.getValueType().getSizeInBits())) + Op2 = DAG.getNode(ISD::TRUNCATE, getCurDebugLoc(), + TLI.getShiftAmountTy(), Op2); + // Otherwise we'll need to temporarily settle for some other + // convenient type; type legalization will make adjustments as + // needed. + else if (PTy.bitsLT(Op2.getValueType())) + Op2 = DAG.getNode(ISD::TRUNCATE, getCurDebugLoc(), + TLI.getPointerTy(), Op2); + else if (PTy.bitsGT(Op2.getValueType())) + Op2 = DAG.getNode(ISD::ANY_EXTEND, getCurDebugLoc(), + TLI.getPointerTy(), Op2); + } + + setValue(&I, DAG.getNode(Opcode, getCurDebugLoc(), + Op1.getValueType(), Op1, Op2)); +} + +void SelectionDAGBuilder::visitICmp(User &I) { + ICmpInst::Predicate predicate = ICmpInst::BAD_ICMP_PREDICATE; + if (ICmpInst *IC = dyn_cast(&I)) + predicate = IC->getPredicate(); + else if (ConstantExpr *IC = dyn_cast(&I)) + predicate = ICmpInst::Predicate(IC->getPredicate()); + SDValue Op1 = getValue(I.getOperand(0)); + SDValue Op2 = getValue(I.getOperand(1)); + ISD::CondCode Opcode = getICmpCondCode(predicate); + + EVT DestVT = TLI.getValueType(I.getType()); + setValue(&I, DAG.getSetCC(getCurDebugLoc(), DestVT, Op1, Op2, Opcode)); +} + +void SelectionDAGBuilder::visitFCmp(User &I) { + FCmpInst::Predicate predicate = FCmpInst::BAD_FCMP_PREDICATE; + if (FCmpInst *FC = dyn_cast(&I)) + predicate = FC->getPredicate(); + else if (ConstantExpr *FC = dyn_cast(&I)) + predicate = FCmpInst::Predicate(FC->getPredicate()); + SDValue Op1 = getValue(I.getOperand(0)); + SDValue Op2 = getValue(I.getOperand(1)); + ISD::CondCode Condition = getFCmpCondCode(predicate); + EVT DestVT = TLI.getValueType(I.getType()); + setValue(&I, DAG.getSetCC(getCurDebugLoc(), DestVT, Op1, Op2, Condition)); +} + +void SelectionDAGBuilder::visitSelect(User &I) { + SmallVector ValueVTs; + ComputeValueVTs(TLI, I.getType(), ValueVTs); + unsigned NumValues = ValueVTs.size(); + if (NumValues != 0) { + SmallVector Values(NumValues); + SDValue Cond = getValue(I.getOperand(0)); + SDValue TrueVal = getValue(I.getOperand(1)); + SDValue FalseVal = getValue(I.getOperand(2)); + + for (unsigned i = 0; i != NumValues; ++i) + Values[i] = DAG.getNode(ISD::SELECT, getCurDebugLoc(), + TrueVal.getValueType(), Cond, + SDValue(TrueVal.getNode(), TrueVal.getResNo() + i), + SDValue(FalseVal.getNode(), FalseVal.getResNo() + i)); + + setValue(&I, DAG.getNode(ISD::MERGE_VALUES, getCurDebugLoc(), + DAG.getVTList(&ValueVTs[0], NumValues), + &Values[0], NumValues)); + } +} + + +void SelectionDAGBuilder::visitTrunc(User &I) { + // TruncInst cannot be a no-op cast because sizeof(src) > sizeof(dest). + SDValue N = getValue(I.getOperand(0)); + EVT DestVT = TLI.getValueType(I.getType()); + setValue(&I, DAG.getNode(ISD::TRUNCATE, getCurDebugLoc(), DestVT, N)); +} + +void SelectionDAGBuilder::visitZExt(User &I) { + // ZExt cannot be a no-op cast because sizeof(src) < sizeof(dest). + // ZExt also can't be a cast to bool for same reason. So, nothing much to do + SDValue N = getValue(I.getOperand(0)); + EVT DestVT = TLI.getValueType(I.getType()); + setValue(&I, DAG.getNode(ISD::ZERO_EXTEND, getCurDebugLoc(), DestVT, N)); +} + +void SelectionDAGBuilder::visitSExt(User &I) { + // SExt cannot be a no-op cast because sizeof(src) < sizeof(dest). + // SExt also can't be a cast to bool for same reason. So, nothing much to do + SDValue N = getValue(I.getOperand(0)); + EVT DestVT = TLI.getValueType(I.getType()); + setValue(&I, DAG.getNode(ISD::SIGN_EXTEND, getCurDebugLoc(), DestVT, N)); +} + +void SelectionDAGBuilder::visitFPTrunc(User &I) { + // FPTrunc is never a no-op cast, no need to check + SDValue N = getValue(I.getOperand(0)); + EVT DestVT = TLI.getValueType(I.getType()); + setValue(&I, DAG.getNode(ISD::FP_ROUND, getCurDebugLoc(), + DestVT, N, DAG.getIntPtrConstant(0))); +} + +void SelectionDAGBuilder::visitFPExt(User &I){ + // FPTrunc is never a no-op cast, no need to check + SDValue N = getValue(I.getOperand(0)); + EVT DestVT = TLI.getValueType(I.getType()); + setValue(&I, DAG.getNode(ISD::FP_EXTEND, getCurDebugLoc(), DestVT, N)); +} + +void SelectionDAGBuilder::visitFPToUI(User &I) { + // FPToUI is never a no-op cast, no need to check + SDValue N = getValue(I.getOperand(0)); + EVT DestVT = TLI.getValueType(I.getType()); + setValue(&I, DAG.getNode(ISD::FP_TO_UINT, getCurDebugLoc(), DestVT, N)); +} + +void SelectionDAGBuilder::visitFPToSI(User &I) { + // FPToSI is never a no-op cast, no need to check + SDValue N = getValue(I.getOperand(0)); + EVT DestVT = TLI.getValueType(I.getType()); + setValue(&I, DAG.getNode(ISD::FP_TO_SINT, getCurDebugLoc(), DestVT, N)); +} + +void SelectionDAGBuilder::visitUIToFP(User &I) { + // UIToFP is never a no-op cast, no need to check + SDValue N = getValue(I.getOperand(0)); + EVT DestVT = TLI.getValueType(I.getType()); + setValue(&I, DAG.getNode(ISD::UINT_TO_FP, getCurDebugLoc(), DestVT, N)); +} + +void SelectionDAGBuilder::visitSIToFP(User &I){ + // SIToFP is never a no-op cast, no need to check + SDValue N = getValue(I.getOperand(0)); + EVT DestVT = TLI.getValueType(I.getType()); + setValue(&I, DAG.getNode(ISD::SINT_TO_FP, getCurDebugLoc(), DestVT, N)); +} + +void SelectionDAGBuilder::visitPtrToInt(User &I) { + // What to do depends on the size of the integer and the size of the pointer. + // We can either truncate, zero extend, or no-op, accordingly. + SDValue N = getValue(I.getOperand(0)); + EVT SrcVT = N.getValueType(); + EVT DestVT = TLI.getValueType(I.getType()); + SDValue Result = DAG.getZExtOrTrunc(N, getCurDebugLoc(), DestVT); + setValue(&I, Result); +} + +void SelectionDAGBuilder::visitIntToPtr(User &I) { + // What to do depends on the size of the integer and the size of the pointer. + // We can either truncate, zero extend, or no-op, accordingly. + SDValue N = getValue(I.getOperand(0)); + EVT SrcVT = N.getValueType(); + EVT DestVT = TLI.getValueType(I.getType()); + setValue(&I, DAG.getZExtOrTrunc(N, getCurDebugLoc(), DestVT)); +} + +void SelectionDAGBuilder::visitBitCast(User &I) { + SDValue N = getValue(I.getOperand(0)); + EVT DestVT = TLI.getValueType(I.getType()); + + // BitCast assures us that source and destination are the same size so this + // is either a BIT_CONVERT or a no-op. + if (DestVT != N.getValueType()) + setValue(&I, DAG.getNode(ISD::BIT_CONVERT, getCurDebugLoc(), + DestVT, N)); // convert types + else + setValue(&I, N); // noop cast. +} + +void SelectionDAGBuilder::visitInsertElement(User &I) { + SDValue InVec = getValue(I.getOperand(0)); + SDValue InVal = getValue(I.getOperand(1)); + SDValue InIdx = DAG.getNode(ISD::ZERO_EXTEND, getCurDebugLoc(), + TLI.getPointerTy(), + getValue(I.getOperand(2))); + + setValue(&I, DAG.getNode(ISD::INSERT_VECTOR_ELT, getCurDebugLoc(), + TLI.getValueType(I.getType()), + InVec, InVal, InIdx)); +} + +void SelectionDAGBuilder::visitExtractElement(User &I) { + SDValue InVec = getValue(I.getOperand(0)); + SDValue InIdx = DAG.getNode(ISD::ZERO_EXTEND, getCurDebugLoc(), + TLI.getPointerTy(), + getValue(I.getOperand(1))); + setValue(&I, DAG.getNode(ISD::EXTRACT_VECTOR_ELT, getCurDebugLoc(), + TLI.getValueType(I.getType()), InVec, InIdx)); +} + + +// Utility for visitShuffleVector - Returns true if the mask is mask starting +// from SIndx and increasing to the element length (undefs are allowed). +static bool SequentialMask(SmallVectorImpl &Mask, unsigned SIndx) { + unsigned MaskNumElts = Mask.size(); + for (unsigned i = 0; i != MaskNumElts; ++i) + if ((Mask[i] >= 0) && (Mask[i] != (int)(i + SIndx))) + return false; + return true; +} + +void SelectionDAGBuilder::visitShuffleVector(User &I) { + SmallVector Mask; + SDValue Src1 = getValue(I.getOperand(0)); + SDValue Src2 = getValue(I.getOperand(1)); + + // Convert the ConstantVector mask operand into an array of ints, with -1 + // representing undef values. + SmallVector MaskElts; + cast(I.getOperand(2))->getVectorElements(*DAG.getContext(), + MaskElts); + unsigned MaskNumElts = MaskElts.size(); + for (unsigned i = 0; i != MaskNumElts; ++i) { + if (isa(MaskElts[i])) + Mask.push_back(-1); + else + Mask.push_back(cast(MaskElts[i])->getSExtValue()); + } + + EVT VT = TLI.getValueType(I.getType()); + EVT SrcVT = Src1.getValueType(); + unsigned SrcNumElts = SrcVT.getVectorNumElements(); + + if (SrcNumElts == MaskNumElts) { + setValue(&I, DAG.getVectorShuffle(VT, getCurDebugLoc(), Src1, Src2, + &Mask[0])); + return; + } + + // Normalize the shuffle vector since mask and vector length don't match. + if (SrcNumElts < MaskNumElts && MaskNumElts % SrcNumElts == 0) { + // Mask is longer than the source vectors and is a multiple of the source + // vectors. We can use concatenate vector to make the mask and vectors + // lengths match. + if (SrcNumElts*2 == MaskNumElts && SequentialMask(Mask, 0)) { + // The shuffle is concatenating two vectors together. + setValue(&I, DAG.getNode(ISD::CONCAT_VECTORS, getCurDebugLoc(), + VT, Src1, Src2)); + return; + } + + // Pad both vectors with undefs to make them the same length as the mask. + unsigned NumConcat = MaskNumElts / SrcNumElts; + bool Src1U = Src1.getOpcode() == ISD::UNDEF; + bool Src2U = Src2.getOpcode() == ISD::UNDEF; + SDValue UndefVal = DAG.getUNDEF(SrcVT); + + SmallVector MOps1(NumConcat, UndefVal); + SmallVector MOps2(NumConcat, UndefVal); + MOps1[0] = Src1; + MOps2[0] = Src2; + + Src1 = Src1U ? DAG.getUNDEF(VT) : DAG.getNode(ISD::CONCAT_VECTORS, + getCurDebugLoc(), VT, + &MOps1[0], NumConcat); + Src2 = Src2U ? DAG.getUNDEF(VT) : DAG.getNode(ISD::CONCAT_VECTORS, + getCurDebugLoc(), VT, + &MOps2[0], NumConcat); + + // Readjust mask for new input vector length. + SmallVector MappedOps; + for (unsigned i = 0; i != MaskNumElts; ++i) { + int Idx = Mask[i]; + if (Idx < (int)SrcNumElts) + MappedOps.push_back(Idx); + else + MappedOps.push_back(Idx + MaskNumElts - SrcNumElts); + } + setValue(&I, DAG.getVectorShuffle(VT, getCurDebugLoc(), Src1, Src2, + &MappedOps[0])); + return; + } + + if (SrcNumElts > MaskNumElts) { + // Analyze the access pattern of the vector to see if we can extract + // two subvectors and do the shuffle. The analysis is done by calculating + // the range of elements the mask access on both vectors. + int MinRange[2] = { SrcNumElts+1, SrcNumElts+1}; + int MaxRange[2] = {-1, -1}; + + for (unsigned i = 0; i != MaskNumElts; ++i) { + int Idx = Mask[i]; + int Input = 0; + if (Idx < 0) + continue; + + if (Idx >= (int)SrcNumElts) { + Input = 1; + Idx -= SrcNumElts; + } + if (Idx > MaxRange[Input]) + MaxRange[Input] = Idx; + if (Idx < MinRange[Input]) + MinRange[Input] = Idx; + } + + // Check if the access is smaller than the vector size and can we find + // a reasonable extract index. + int RangeUse[2] = { 2, 2 }; // 0 = Unused, 1 = Extract, 2 = Can not Extract. + int StartIdx[2]; // StartIdx to extract from + for (int Input=0; Input < 2; ++Input) { + if (MinRange[Input] == (int)(SrcNumElts+1) && MaxRange[Input] == -1) { + RangeUse[Input] = 0; // Unused + StartIdx[Input] = 0; + } else if (MaxRange[Input] - MinRange[Input] < (int)MaskNumElts) { + // Fits within range but we should see if we can find a good + // start index that is a multiple of the mask length. + if (MaxRange[Input] < (int)MaskNumElts) { + RangeUse[Input] = 1; // Extract from beginning of the vector + StartIdx[Input] = 0; + } else { + StartIdx[Input] = (MinRange[Input]/MaskNumElts)*MaskNumElts; + if (MaxRange[Input] - StartIdx[Input] < (int)MaskNumElts && + StartIdx[Input] + MaskNumElts < SrcNumElts) + RangeUse[Input] = 1; // Extract from a multiple of the mask length. + } + } + } + + if (RangeUse[0] == 0 && RangeUse[1] == 0) { + setValue(&I, DAG.getUNDEF(VT)); // Vectors are not used. + return; + } + else if (RangeUse[0] < 2 && RangeUse[1] < 2) { + // Extract appropriate subvector and generate a vector shuffle + for (int Input=0; Input < 2; ++Input) { + SDValue& Src = Input == 0 ? Src1 : Src2; + if (RangeUse[Input] == 0) { + Src = DAG.getUNDEF(VT); + } else { + Src = DAG.getNode(ISD::EXTRACT_SUBVECTOR, getCurDebugLoc(), VT, + Src, DAG.getIntPtrConstant(StartIdx[Input])); + } + } + // Calculate new mask. + SmallVector MappedOps; + for (unsigned i = 0; i != MaskNumElts; ++i) { + int Idx = Mask[i]; + if (Idx < 0) + MappedOps.push_back(Idx); + else if (Idx < (int)SrcNumElts) + MappedOps.push_back(Idx - StartIdx[0]); + else + MappedOps.push_back(Idx - SrcNumElts - StartIdx[1] + MaskNumElts); + } + setValue(&I, DAG.getVectorShuffle(VT, getCurDebugLoc(), Src1, Src2, + &MappedOps[0])); + return; + } + } + + // We can't use either concat vectors or extract subvectors so fall back to + // replacing the shuffle with extract and build vector. + // to insert and build vector. + EVT EltVT = VT.getVectorElementType(); + EVT PtrVT = TLI.getPointerTy(); + SmallVector Ops; + for (unsigned i = 0; i != MaskNumElts; ++i) { + if (Mask[i] < 0) { + Ops.push_back(DAG.getUNDEF(EltVT)); + } else { + int Idx = Mask[i]; + if (Idx < (int)SrcNumElts) + Ops.push_back(DAG.getNode(ISD::EXTRACT_VECTOR_ELT, getCurDebugLoc(), + EltVT, Src1, DAG.getConstant(Idx, PtrVT))); + else + Ops.push_back(DAG.getNode(ISD::EXTRACT_VECTOR_ELT, getCurDebugLoc(), + EltVT, Src2, + DAG.getConstant(Idx - SrcNumElts, PtrVT))); + } + } + setValue(&I, DAG.getNode(ISD::BUILD_VECTOR, getCurDebugLoc(), + VT, &Ops[0], Ops.size())); +} + +void SelectionDAGBuilder::visitInsertValue(InsertValueInst &I) { + const Value *Op0 = I.getOperand(0); + const Value *Op1 = I.getOperand(1); + const Type *AggTy = I.getType(); + const Type *ValTy = Op1->getType(); + bool IntoUndef = isa(Op0); + bool FromUndef = isa(Op1); + + unsigned LinearIndex = ComputeLinearIndex(TLI, AggTy, + I.idx_begin(), I.idx_end()); + + SmallVector AggValueVTs; + ComputeValueVTs(TLI, AggTy, AggValueVTs); + SmallVector ValValueVTs; + ComputeValueVTs(TLI, ValTy, ValValueVTs); + + unsigned NumAggValues = AggValueVTs.size(); + unsigned NumValValues = ValValueVTs.size(); + SmallVector Values(NumAggValues); + + SDValue Agg = getValue(Op0); + SDValue Val = getValue(Op1); + unsigned i = 0; + // Copy the beginning value(s) from the original aggregate. + for (; i != LinearIndex; ++i) + Values[i] = IntoUndef ? DAG.getUNDEF(AggValueVTs[i]) : + SDValue(Agg.getNode(), Agg.getResNo() + i); + // Copy values from the inserted value(s). + for (; i != LinearIndex + NumValValues; ++i) + Values[i] = FromUndef ? DAG.getUNDEF(AggValueVTs[i]) : + SDValue(Val.getNode(), Val.getResNo() + i - LinearIndex); + // Copy remaining value(s) from the original aggregate. + for (; i != NumAggValues; ++i) + Values[i] = IntoUndef ? DAG.getUNDEF(AggValueVTs[i]) : + SDValue(Agg.getNode(), Agg.getResNo() + i); + + setValue(&I, DAG.getNode(ISD::MERGE_VALUES, getCurDebugLoc(), + DAG.getVTList(&AggValueVTs[0], NumAggValues), + &Values[0], NumAggValues)); +} + +void SelectionDAGBuilder::visitExtractValue(ExtractValueInst &I) { + const Value *Op0 = I.getOperand(0); + const Type *AggTy = Op0->getType(); + const Type *ValTy = I.getType(); + bool OutOfUndef = isa(Op0); + + unsigned LinearIndex = ComputeLinearIndex(TLI, AggTy, + I.idx_begin(), I.idx_end()); + + SmallVector ValValueVTs; + ComputeValueVTs(TLI, ValTy, ValValueVTs); + + unsigned NumValValues = ValValueVTs.size(); + SmallVector Values(NumValValues); + + SDValue Agg = getValue(Op0); + // Copy out the selected value(s). + for (unsigned i = LinearIndex; i != LinearIndex + NumValValues; ++i) + Values[i - LinearIndex] = + OutOfUndef ? + DAG.getUNDEF(Agg.getNode()->getValueType(Agg.getResNo() + i)) : + SDValue(Agg.getNode(), Agg.getResNo() + i); + + setValue(&I, DAG.getNode(ISD::MERGE_VALUES, getCurDebugLoc(), + DAG.getVTList(&ValValueVTs[0], NumValValues), + &Values[0], NumValValues)); +} + + +void SelectionDAGBuilder::visitGetElementPtr(User &I) { + SDValue N = getValue(I.getOperand(0)); + const Type *Ty = I.getOperand(0)->getType(); + + for (GetElementPtrInst::op_iterator OI = I.op_begin()+1, E = I.op_end(); + OI != E; ++OI) { + Value *Idx = *OI; + if (const StructType *StTy = dyn_cast(Ty)) { + unsigned Field = cast(Idx)->getZExtValue(); + if (Field) { + // N = N + Offset + uint64_t Offset = TD->getStructLayout(StTy)->getElementOffset(Field); + N = DAG.getNode(ISD::ADD, getCurDebugLoc(), N.getValueType(), N, + DAG.getIntPtrConstant(Offset)); + } + Ty = StTy->getElementType(Field); + } else { + Ty = cast(Ty)->getElementType(); + + // If this is a constant subscript, handle it quickly. + if (ConstantInt *CI = dyn_cast(Idx)) { + if (CI->getZExtValue() == 0) continue; + uint64_t Offs = + TD->getTypeAllocSize(Ty)*cast(CI)->getSExtValue(); + SDValue OffsVal; + EVT PTy = TLI.getPointerTy(); + unsigned PtrBits = PTy.getSizeInBits(); + if (PtrBits < 64) { + OffsVal = DAG.getNode(ISD::TRUNCATE, getCurDebugLoc(), + TLI.getPointerTy(), + DAG.getConstant(Offs, MVT::i64)); + } else + OffsVal = DAG.getIntPtrConstant(Offs); + N = DAG.getNode(ISD::ADD, getCurDebugLoc(), N.getValueType(), N, + OffsVal); + continue; + } + + // N = N + Idx * ElementSize; + APInt ElementSize = APInt(TLI.getPointerTy().getSizeInBits(), + TD->getTypeAllocSize(Ty)); + SDValue IdxN = getValue(Idx); + + // If the index is smaller or larger than intptr_t, truncate or extend + // it. + IdxN = DAG.getSExtOrTrunc(IdxN, getCurDebugLoc(), N.getValueType()); + + // If this is a multiply by a power of two, turn it into a shl + // immediately. This is a very common case. + if (ElementSize != 1) { + if (ElementSize.isPowerOf2()) { + unsigned Amt = ElementSize.logBase2(); + IdxN = DAG.getNode(ISD::SHL, getCurDebugLoc(), + N.getValueType(), IdxN, + DAG.getConstant(Amt, TLI.getPointerTy())); + } else { + SDValue Scale = DAG.getConstant(ElementSize, TLI.getPointerTy()); + IdxN = DAG.getNode(ISD::MUL, getCurDebugLoc(), + N.getValueType(), IdxN, Scale); + } + } + + N = DAG.getNode(ISD::ADD, getCurDebugLoc(), + N.getValueType(), N, IdxN); + } + } + setValue(&I, N); +} + +void SelectionDAGBuilder::visitAlloca(AllocaInst &I) { + // If this is a fixed sized alloca in the entry block of the function, + // allocate it statically on the stack. + if (FuncInfo.StaticAllocaMap.count(&I)) + return; // getValue will auto-populate this. + + const Type *Ty = I.getAllocatedType(); + uint64_t TySize = TLI.getTargetData()->getTypeAllocSize(Ty); + unsigned Align = + std::max((unsigned)TLI.getTargetData()->getPrefTypeAlignment(Ty), + I.getAlignment()); + + SDValue AllocSize = getValue(I.getArraySize()); + + AllocSize = DAG.getNode(ISD::MUL, getCurDebugLoc(), AllocSize.getValueType(), + AllocSize, + DAG.getConstant(TySize, AllocSize.getValueType())); + + + + EVT IntPtr = TLI.getPointerTy(); + AllocSize = DAG.getZExtOrTrunc(AllocSize, getCurDebugLoc(), IntPtr); + + // Handle alignment. If the requested alignment is less than or equal to + // the stack alignment, ignore it. If the size is greater than or equal to + // the stack alignment, we note this in the DYNAMIC_STACKALLOC node. + unsigned StackAlign = + TLI.getTargetMachine().getFrameInfo()->getStackAlignment(); + if (Align <= StackAlign) + Align = 0; + + // Round the size of the allocation up to the stack alignment size + // by add SA-1 to the size. + AllocSize = DAG.getNode(ISD::ADD, getCurDebugLoc(), + AllocSize.getValueType(), AllocSize, + DAG.getIntPtrConstant(StackAlign-1)); + // Mask out the low bits for alignment purposes. + AllocSize = DAG.getNode(ISD::AND, getCurDebugLoc(), + AllocSize.getValueType(), AllocSize, + DAG.getIntPtrConstant(~(uint64_t)(StackAlign-1))); + + SDValue Ops[] = { getRoot(), AllocSize, DAG.getIntPtrConstant(Align) }; + SDVTList VTs = DAG.getVTList(AllocSize.getValueType(), MVT::Other); + SDValue DSA = DAG.getNode(ISD::DYNAMIC_STACKALLOC, getCurDebugLoc(), + VTs, Ops, 3); + setValue(&I, DSA); + DAG.setRoot(DSA.getValue(1)); + + // Inform the Frame Information that we have just allocated a variable-sized + // object. + FuncInfo.MF->getFrameInfo()->CreateVariableSizedObject(); +} + +void SelectionDAGBuilder::visitLoad(LoadInst &I) { + const Value *SV = I.getOperand(0); + SDValue Ptr = getValue(SV); + + const Type *Ty = I.getType(); + bool isVolatile = I.isVolatile(); + unsigned Alignment = I.getAlignment(); + + SmallVector ValueVTs; + SmallVector Offsets; + ComputeValueVTs(TLI, Ty, ValueVTs, &Offsets); + unsigned NumValues = ValueVTs.size(); + if (NumValues == 0) + return; + + SDValue Root; + bool ConstantMemory = false; + if (I.isVolatile()) + // Serialize volatile loads with other side effects. + Root = getRoot(); + else if (AA->pointsToConstantMemory(SV)) { + // Do not serialize (non-volatile) loads of constant memory with anything. + Root = DAG.getEntryNode(); + ConstantMemory = true; + } else { + // Do not serialize non-volatile loads against each other. + Root = DAG.getRoot(); + } + + SmallVector Values(NumValues); + SmallVector Chains(NumValues); + EVT PtrVT = Ptr.getValueType(); + for (unsigned i = 0; i != NumValues; ++i) { + SDValue L = DAG.getLoad(ValueVTs[i], getCurDebugLoc(), Root, + DAG.getNode(ISD::ADD, getCurDebugLoc(), + PtrVT, Ptr, + DAG.getConstant(Offsets[i], PtrVT)), + SV, Offsets[i], isVolatile, Alignment); + Values[i] = L; + Chains[i] = L.getValue(1); + } + + if (!ConstantMemory) { + SDValue Chain = DAG.getNode(ISD::TokenFactor, getCurDebugLoc(), + MVT::Other, + &Chains[0], NumValues); + if (isVolatile) + DAG.setRoot(Chain); + else + PendingLoads.push_back(Chain); + } + + setValue(&I, DAG.getNode(ISD::MERGE_VALUES, getCurDebugLoc(), + DAG.getVTList(&ValueVTs[0], NumValues), + &Values[0], NumValues)); +} + + +void SelectionDAGBuilder::visitStore(StoreInst &I) { + Value *SrcV = I.getOperand(0); + Value *PtrV = I.getOperand(1); + + SmallVector ValueVTs; + SmallVector Offsets; + ComputeValueVTs(TLI, SrcV->getType(), ValueVTs, &Offsets); + unsigned NumValues = ValueVTs.size(); + if (NumValues == 0) + return; + + // Get the lowered operands. Note that we do this after + // checking if NumResults is zero, because with zero results + // the operands won't have values in the map. + SDValue Src = getValue(SrcV); + SDValue Ptr = getValue(PtrV); + + SDValue Root = getRoot(); + SmallVector Chains(NumValues); + EVT PtrVT = Ptr.getValueType(); + bool isVolatile = I.isVolatile(); + unsigned Alignment = I.getAlignment(); + for (unsigned i = 0; i != NumValues; ++i) + Chains[i] = DAG.getStore(Root, getCurDebugLoc(), + SDValue(Src.getNode(), Src.getResNo() + i), + DAG.getNode(ISD::ADD, getCurDebugLoc(), + PtrVT, Ptr, + DAG.getConstant(Offsets[i], PtrVT)), + PtrV, Offsets[i], isVolatile, Alignment); + + DAG.setRoot(DAG.getNode(ISD::TokenFactor, getCurDebugLoc(), + MVT::Other, &Chains[0], NumValues)); +} + +/// visitTargetIntrinsic - Lower a call of a target intrinsic to an INTRINSIC +/// node. +void SelectionDAGBuilder::visitTargetIntrinsic(CallInst &I, + unsigned Intrinsic) { + bool HasChain = !I.doesNotAccessMemory(); + bool OnlyLoad = HasChain && I.onlyReadsMemory(); + + // Build the operand list. + SmallVector Ops; + if (HasChain) { // If this intrinsic has side-effects, chainify it. + if (OnlyLoad) { + // We don't need to serialize loads against other loads. + Ops.push_back(DAG.getRoot()); + } else { + Ops.push_back(getRoot()); + } + } + + // Info is set by getTgtMemInstrinsic + TargetLowering::IntrinsicInfo Info; + bool IsTgtIntrinsic = TLI.getTgtMemIntrinsic(Info, I, Intrinsic); + + // Add the intrinsic ID as an integer operand if it's not a target intrinsic. + if (!IsTgtIntrinsic) + Ops.push_back(DAG.getConstant(Intrinsic, TLI.getPointerTy())); + + // Add all operands of the call to the operand list. + for (unsigned i = 1, e = I.getNumOperands(); i != e; ++i) { + SDValue Op = getValue(I.getOperand(i)); + assert(TLI.isTypeLegal(Op.getValueType()) && + "Intrinsic uses a non-legal type?"); + Ops.push_back(Op); + } + + SmallVector ValueVTs; + ComputeValueVTs(TLI, I.getType(), ValueVTs); +#ifndef NDEBUG + for (unsigned Val = 0, E = ValueVTs.size(); Val != E; ++Val) { + assert(TLI.isTypeLegal(ValueVTs[Val]) && + "Intrinsic uses a non-legal type?"); + } +#endif // NDEBUG + if (HasChain) + ValueVTs.push_back(MVT::Other); + + SDVTList VTs = DAG.getVTList(ValueVTs.data(), ValueVTs.size()); + + // Create the node. + SDValue Result; + if (IsTgtIntrinsic) { + // This is target intrinsic that touches memory + Result = DAG.getMemIntrinsicNode(Info.opc, getCurDebugLoc(), + VTs, &Ops[0], Ops.size(), + Info.memVT, Info.ptrVal, Info.offset, + Info.align, Info.vol, + Info.readMem, Info.writeMem); + } + else if (!HasChain) + Result = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, getCurDebugLoc(), + VTs, &Ops[0], Ops.size()); + else if (I.getType() != Type::getVoidTy(*DAG.getContext())) + Result = DAG.getNode(ISD::INTRINSIC_W_CHAIN, getCurDebugLoc(), + VTs, &Ops[0], Ops.size()); + else + Result = DAG.getNode(ISD::INTRINSIC_VOID, getCurDebugLoc(), + VTs, &Ops[0], Ops.size()); + + if (HasChain) { + SDValue Chain = Result.getValue(Result.getNode()->getNumValues()-1); + if (OnlyLoad) + PendingLoads.push_back(Chain); + else + DAG.setRoot(Chain); + } + if (I.getType() != Type::getVoidTy(*DAG.getContext())) { + if (const VectorType *PTy = dyn_cast(I.getType())) { + EVT VT = TLI.getValueType(PTy); + Result = DAG.getNode(ISD::BIT_CONVERT, getCurDebugLoc(), VT, Result); + } + setValue(&I, Result); + } +} + +/// GetSignificand - Get the significand and build it into a floating-point +/// number with exponent of 1: +/// +/// Op = (Op & 0x007fffff) | 0x3f800000; +/// +/// where Op is the hexidecimal representation of floating point value. +static SDValue +GetSignificand(SelectionDAG &DAG, SDValue Op, DebugLoc dl) { + SDValue t1 = DAG.getNode(ISD::AND, dl, MVT::i32, Op, + DAG.getConstant(0x007fffff, MVT::i32)); + SDValue t2 = DAG.getNode(ISD::OR, dl, MVT::i32, t1, + DAG.getConstant(0x3f800000, MVT::i32)); + return DAG.getNode(ISD::BIT_CONVERT, dl, MVT::f32, t2); +} + +/// GetExponent - Get the exponent: +/// +/// (float)(int)(((Op & 0x7f800000) >> 23) - 127); +/// +/// where Op is the hexidecimal representation of floating point value. +static SDValue +GetExponent(SelectionDAG &DAG, SDValue Op, const TargetLowering &TLI, + DebugLoc dl) { + SDValue t0 = DAG.getNode(ISD::AND, dl, MVT::i32, Op, + DAG.getConstant(0x7f800000, MVT::i32)); + SDValue t1 = DAG.getNode(ISD::SRL, dl, MVT::i32, t0, + DAG.getConstant(23, TLI.getPointerTy())); + SDValue t2 = DAG.getNode(ISD::SUB, dl, MVT::i32, t1, + DAG.getConstant(127, MVT::i32)); + return DAG.getNode(ISD::SINT_TO_FP, dl, MVT::f32, t2); +} + +/// getF32Constant - Get 32-bit floating point constant. +static SDValue +getF32Constant(SelectionDAG &DAG, unsigned Flt) { + return DAG.getConstantFP(APFloat(APInt(32, Flt)), MVT::f32); +} + +/// Inlined utility function to implement binary input atomic intrinsics for +/// visitIntrinsicCall: I is a call instruction +/// Op is the associated NodeType for I +const char * +SelectionDAGBuilder::implVisitBinaryAtomic(CallInst& I, ISD::NodeType Op) { + SDValue Root = getRoot(); + SDValue L = + DAG.getAtomic(Op, getCurDebugLoc(), + getValue(I.getOperand(2)).getValueType().getSimpleVT(), + Root, + getValue(I.getOperand(1)), + getValue(I.getOperand(2)), + I.getOperand(1)); + setValue(&I, L); + DAG.setRoot(L.getValue(1)); + return 0; +} + +// implVisitAluOverflow - Lower arithmetic overflow instrinsics. +const char * +SelectionDAGBuilder::implVisitAluOverflow(CallInst &I, ISD::NodeType Op) { + SDValue Op1 = getValue(I.getOperand(1)); + SDValue Op2 = getValue(I.getOperand(2)); + + SDVTList VTs = DAG.getVTList(Op1.getValueType(), MVT::i1); + SDValue Result = DAG.getNode(Op, getCurDebugLoc(), VTs, Op1, Op2); + + setValue(&I, Result); + return 0; +} + +/// visitExp - Lower an exp intrinsic. Handles the special sequences for +/// limited-precision mode. +void +SelectionDAGBuilder::visitExp(CallInst &I) { + SDValue result; + DebugLoc dl = getCurDebugLoc(); + + if (getValue(I.getOperand(1)).getValueType() == MVT::f32 && + LimitFloatPrecision > 0 && LimitFloatPrecision <= 18) { + SDValue Op = getValue(I.getOperand(1)); + + // Put the exponent in the right bit position for later addition to the + // final result: + // + // #define LOG2OFe 1.4426950f + // IntegerPartOfX = ((int32_t)(X * LOG2OFe)); + SDValue t0 = DAG.getNode(ISD::FMUL, dl, MVT::f32, Op, + getF32Constant(DAG, 0x3fb8aa3b)); + SDValue IntegerPartOfX = DAG.getNode(ISD::FP_TO_SINT, dl, MVT::i32, t0); + + // FractionalPartOfX = (X * LOG2OFe) - (float)IntegerPartOfX; + SDValue t1 = DAG.getNode(ISD::SINT_TO_FP, dl, MVT::f32, IntegerPartOfX); + SDValue X = DAG.getNode(ISD::FSUB, dl, MVT::f32, t0, t1); + + // IntegerPartOfX <<= 23; + IntegerPartOfX = DAG.getNode(ISD::SHL, dl, MVT::i32, IntegerPartOfX, + DAG.getConstant(23, TLI.getPointerTy())); + + if (LimitFloatPrecision <= 6) { + // For floating-point precision of 6: + // + // TwoToFractionalPartOfX = + // 0.997535578f + + // (0.735607626f + 0.252464424f * x) * x; + // + // error 0.0144103317, which is 6 bits + SDValue t2 = DAG.getNode(ISD::FMUL, dl, MVT::f32, X, + getF32Constant(DAG, 0x3e814304)); + SDValue t3 = DAG.getNode(ISD::FADD, dl, MVT::f32, t2, + getF32Constant(DAG, 0x3f3c50c8)); + SDValue t4 = DAG.getNode(ISD::FMUL, dl, MVT::f32, t3, X); + SDValue t5 = DAG.getNode(ISD::FADD, dl, MVT::f32, t4, + getF32Constant(DAG, 0x3f7f5e7e)); + SDValue TwoToFracPartOfX = DAG.getNode(ISD::BIT_CONVERT, dl,MVT::i32, t5); + + // Add the exponent into the result in integer domain. + SDValue t6 = DAG.getNode(ISD::ADD, dl, MVT::i32, + TwoToFracPartOfX, IntegerPartOfX); + + result = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::f32, t6); + } else if (LimitFloatPrecision > 6 && LimitFloatPrecision <= 12) { + // For floating-point precision of 12: + // + // TwoToFractionalPartOfX = + // 0.999892986f + + // (0.696457318f + + // (0.224338339f + 0.792043434e-1f * x) * x) * x; + // + // 0.000107046256 error, which is 13 to 14 bits + SDValue t2 = DAG.getNode(ISD::FMUL, dl, MVT::f32, X, + getF32Constant(DAG, 0x3da235e3)); + SDValue t3 = DAG.getNode(ISD::FADD, dl, MVT::f32, t2, + getF32Constant(DAG, 0x3e65b8f3)); + SDValue t4 = DAG.getNode(ISD::FMUL, dl, MVT::f32, t3, X); + SDValue t5 = DAG.getNode(ISD::FADD, dl, MVT::f32, t4, + getF32Constant(DAG, 0x3f324b07)); + SDValue t6 = DAG.getNode(ISD::FMUL, dl, MVT::f32, t5, X); + SDValue t7 = DAG.getNode(ISD::FADD, dl, MVT::f32, t6, + getF32Constant(DAG, 0x3f7ff8fd)); + SDValue TwoToFracPartOfX = DAG.getNode(ISD::BIT_CONVERT, dl,MVT::i32, t7); + + // Add the exponent into the result in integer domain. + SDValue t8 = DAG.getNode(ISD::ADD, dl, MVT::i32, + TwoToFracPartOfX, IntegerPartOfX); + + result = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::f32, t8); + } else { // LimitFloatPrecision > 12 && LimitFloatPrecision <= 18 + // For floating-point precision of 18: + // + // TwoToFractionalPartOfX = + // 0.999999982f + + // (0.693148872f + + // (0.240227044f + + // (0.554906021e-1f + + // (0.961591928e-2f + + // (0.136028312e-2f + 0.157059148e-3f *x)*x)*x)*x)*x)*x; + // + // error 2.47208000*10^(-7), which is better than 18 bits + SDValue t2 = DAG.getNode(ISD::FMUL, dl, MVT::f32, X, + getF32Constant(DAG, 0x3924b03e)); + SDValue t3 = DAG.getNode(ISD::FADD, dl, MVT::f32, t2, + getF32Constant(DAG, 0x3ab24b87)); + SDValue t4 = DAG.getNode(ISD::FMUL, dl, MVT::f32, t3, X); + SDValue t5 = DAG.getNode(ISD::FADD, dl, MVT::f32, t4, + getF32Constant(DAG, 0x3c1d8c17)); + SDValue t6 = DAG.getNode(ISD::FMUL, dl, MVT::f32, t5, X); + SDValue t7 = DAG.getNode(ISD::FADD, dl, MVT::f32, t6, + getF32Constant(DAG, 0x3d634a1d)); + SDValue t8 = DAG.getNode(ISD::FMUL, dl, MVT::f32, t7, X); + SDValue t9 = DAG.getNode(ISD::FADD, dl, MVT::f32, t8, + getF32Constant(DAG, 0x3e75fe14)); + SDValue t10 = DAG.getNode(ISD::FMUL, dl, MVT::f32, t9, X); + SDValue t11 = DAG.getNode(ISD::FADD, dl, MVT::f32, t10, + getF32Constant(DAG, 0x3f317234)); + SDValue t12 = DAG.getNode(ISD::FMUL, dl, MVT::f32, t11, X); + SDValue t13 = DAG.getNode(ISD::FADD, dl, MVT::f32, t12, + getF32Constant(DAG, 0x3f800000)); + SDValue TwoToFracPartOfX = DAG.getNode(ISD::BIT_CONVERT, dl, + MVT::i32, t13); + + // Add the exponent into the result in integer domain. + SDValue t14 = DAG.getNode(ISD::ADD, dl, MVT::i32, + TwoToFracPartOfX, IntegerPartOfX); + + result = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::f32, t14); + } + } else { + // No special expansion. + result = DAG.getNode(ISD::FEXP, dl, + getValue(I.getOperand(1)).getValueType(), + getValue(I.getOperand(1))); + } + + setValue(&I, result); +} + +/// visitLog - Lower a log intrinsic. Handles the special sequences for +/// limited-precision mode. +void +SelectionDAGBuilder::visitLog(CallInst &I) { + SDValue result; + DebugLoc dl = getCurDebugLoc(); + + if (getValue(I.getOperand(1)).getValueType() == MVT::f32 && + LimitFloatPrecision > 0 && LimitFloatPrecision <= 18) { + SDValue Op = getValue(I.getOperand(1)); + SDValue Op1 = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::i32, Op); + + // Scale the exponent by log(2) [0.69314718f]. + SDValue Exp = GetExponent(DAG, Op1, TLI, dl); + SDValue LogOfExponent = DAG.getNode(ISD::FMUL, dl, MVT::f32, Exp, + getF32Constant(DAG, 0x3f317218)); + + // Get the significand and build it into a floating-point number with + // exponent of 1. + SDValue X = GetSignificand(DAG, Op1, dl); + + if (LimitFloatPrecision <= 6) { + // For floating-point precision of 6: + // + // LogofMantissa = + // -1.1609546f + + // (1.4034025f - 0.23903021f * x) * x; + // + // error 0.0034276066, which is better than 8 bits + SDValue t0 = DAG.getNode(ISD::FMUL, dl, MVT::f32, X, + getF32Constant(DAG, 0xbe74c456)); + SDValue t1 = DAG.getNode(ISD::FADD, dl, MVT::f32, t0, + getF32Constant(DAG, 0x3fb3a2b1)); + SDValue t2 = DAG.getNode(ISD::FMUL, dl, MVT::f32, t1, X); + SDValue LogOfMantissa = DAG.getNode(ISD::FSUB, dl, MVT::f32, t2, + getF32Constant(DAG, 0x3f949a29)); + + result = DAG.getNode(ISD::FADD, dl, + MVT::f32, LogOfExponent, LogOfMantissa); + } else if (LimitFloatPrecision > 6 && LimitFloatPrecision <= 12) { + // For floating-point precision of 12: + // + // LogOfMantissa = + // -1.7417939f + + // (2.8212026f + + // (-1.4699568f + + // (0.44717955f - 0.56570851e-1f * x) * x) * x) * x; + // + // error 0.000061011436, which is 14 bits + SDValue t0 = DAG.getNode(ISD::FMUL, dl, MVT::f32, X, + getF32Constant(DAG, 0xbd67b6d6)); + SDValue t1 = DAG.getNode(ISD::FADD, dl, MVT::f32, t0, + getF32Constant(DAG, 0x3ee4f4b8)); + SDValue t2 = DAG.getNode(ISD::FMUL, dl, MVT::f32, t1, X); + SDValue t3 = DAG.getNode(ISD::FSUB, dl, MVT::f32, t2, + getF32Constant(DAG, 0x3fbc278b)); + SDValue t4 = DAG.getNode(ISD::FMUL, dl, MVT::f32, t3, X); + SDValue t5 = DAG.getNode(ISD::FADD, dl, MVT::f32, t4, + getF32Constant(DAG, 0x40348e95)); + SDValue t6 = DAG.getNode(ISD::FMUL, dl, MVT::f32, t5, X); + SDValue LogOfMantissa = DAG.getNode(ISD::FSUB, dl, MVT::f32, t6, + getF32Constant(DAG, 0x3fdef31a)); + + result = DAG.getNode(ISD::FADD, dl, + MVT::f32, LogOfExponent, LogOfMantissa); + } else { // LimitFloatPrecision > 12 && LimitFloatPrecision <= 18 + // For floating-point precision of 18: + // + // LogOfMantissa = + // -2.1072184f + + // (4.2372794f + + // (-3.7029485f + + // (2.2781945f + + // (-0.87823314f + + // (0.19073739f - 0.17809712e-1f * x) * x) * x) * x) * x)*x; + // + // error 0.0000023660568, which is better than 18 bits + SDValue t0 = DAG.getNode(ISD::FMUL, dl, MVT::f32, X, + getF32Constant(DAG, 0xbc91e5ac)); + SDValue t1 = DAG.getNode(ISD::FADD, dl, MVT::f32, t0, + getF32Constant(DAG, 0x3e4350aa)); + SDValue t2 = DAG.getNode(ISD::FMUL, dl, MVT::f32, t1, X); + SDValue t3 = DAG.getNode(ISD::FSUB, dl, MVT::f32, t2, + getF32Constant(DAG, 0x3f60d3e3)); + SDValue t4 = DAG.getNode(ISD::FMUL, dl, MVT::f32, t3, X); + SDValue t5 = DAG.getNode(ISD::FADD, dl, MVT::f32, t4, + getF32Constant(DAG, 0x4011cdf0)); + SDValue t6 = DAG.getNode(ISD::FMUL, dl, MVT::f32, t5, X); + SDValue t7 = DAG.getNode(ISD::FSUB, dl, MVT::f32, t6, + getF32Constant(DAG, 0x406cfd1c)); + SDValue t8 = DAG.getNode(ISD::FMUL, dl, MVT::f32, t7, X); + SDValue t9 = DAG.getNode(ISD::FADD, dl, MVT::f32, t8, + getF32Constant(DAG, 0x408797cb)); + SDValue t10 = DAG.getNode(ISD::FMUL, dl, MVT::f32, t9, X); + SDValue LogOfMantissa = DAG.getNode(ISD::FSUB, dl, MVT::f32, t10, + getF32Constant(DAG, 0x4006dcab)); + + result = DAG.getNode(ISD::FADD, dl, + MVT::f32, LogOfExponent, LogOfMantissa); + } + } else { + // No special expansion. + result = DAG.getNode(ISD::FLOG, dl, + getValue(I.getOperand(1)).getValueType(), + getValue(I.getOperand(1))); + } + + setValue(&I, result); +} + +/// visitLog2 - Lower a log2 intrinsic. Handles the special sequences for +/// limited-precision mode. +void +SelectionDAGBuilder::visitLog2(CallInst &I) { + SDValue result; + DebugLoc dl = getCurDebugLoc(); + + if (getValue(I.getOperand(1)).getValueType() == MVT::f32 && + LimitFloatPrecision > 0 && LimitFloatPrecision <= 18) { + SDValue Op = getValue(I.getOperand(1)); + SDValue Op1 = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::i32, Op); + + // Get the exponent. + SDValue LogOfExponent = GetExponent(DAG, Op1, TLI, dl); + + // Get the significand and build it into a floating-point number with + // exponent of 1. + SDValue X = GetSignificand(DAG, Op1, dl); + + // Different possible minimax approximations of significand in + // floating-point for various degrees of accuracy over [1,2]. + if (LimitFloatPrecision <= 6) { + // For floating-point precision of 6: + // + // Log2ofMantissa = -1.6749035f + (2.0246817f - .34484768f * x) * x; + // + // error 0.0049451742, which is more than 7 bits + SDValue t0 = DAG.getNode(ISD::FMUL, dl, MVT::f32, X, + getF32Constant(DAG, 0xbeb08fe0)); + SDValue t1 = DAG.getNode(ISD::FADD, dl, MVT::f32, t0, + getF32Constant(DAG, 0x40019463)); + SDValue t2 = DAG.getNode(ISD::FMUL, dl, MVT::f32, t1, X); + SDValue Log2ofMantissa = DAG.getNode(ISD::FSUB, dl, MVT::f32, t2, + getF32Constant(DAG, 0x3fd6633d)); + + result = DAG.getNode(ISD::FADD, dl, + MVT::f32, LogOfExponent, Log2ofMantissa); + } else if (LimitFloatPrecision > 6 && LimitFloatPrecision <= 12) { + // For floating-point precision of 12: + // + // Log2ofMantissa = + // -2.51285454f + + // (4.07009056f + + // (-2.12067489f + + // (.645142248f - 0.816157886e-1f * x) * x) * x) * x; + // + // error 0.0000876136000, which is better than 13 bits + SDValue t0 = DAG.getNode(ISD::FMUL, dl, MVT::f32, X, + getF32Constant(DAG, 0xbda7262e)); + SDValue t1 = DAG.getNode(ISD::FADD, dl, MVT::f32, t0, + getF32Constant(DAG, 0x3f25280b)); + SDValue t2 = DAG.getNode(ISD::FMUL, dl, MVT::f32, t1, X); + SDValue t3 = DAG.getNode(ISD::FSUB, dl, MVT::f32, t2, + getF32Constant(DAG, 0x4007b923)); + SDValue t4 = DAG.getNode(ISD::FMUL, dl, MVT::f32, t3, X); + SDValue t5 = DAG.getNode(ISD::FADD, dl, MVT::f32, t4, + getF32Constant(DAG, 0x40823e2f)); + SDValue t6 = DAG.getNode(ISD::FMUL, dl, MVT::f32, t5, X); + SDValue Log2ofMantissa = DAG.getNode(ISD::FSUB, dl, MVT::f32, t6, + getF32Constant(DAG, 0x4020d29c)); + + result = DAG.getNode(ISD::FADD, dl, + MVT::f32, LogOfExponent, Log2ofMantissa); + } else { // LimitFloatPrecision > 12 && LimitFloatPrecision <= 18 + // For floating-point precision of 18: + // + // Log2ofMantissa = + // -3.0400495f + + // (6.1129976f + + // (-5.3420409f + + // (3.2865683f + + // (-1.2669343f + + // (0.27515199f - + // 0.25691327e-1f * x) * x) * x) * x) * x) * x; + // + // error 0.0000018516, which is better than 18 bits + SDValue t0 = DAG.getNode(ISD::FMUL, dl, MVT::f32, X, + getF32Constant(DAG, 0xbcd2769e)); + SDValue t1 = DAG.getNode(ISD::FADD, dl, MVT::f32, t0, + getF32Constant(DAG, 0x3e8ce0b9)); + SDValue t2 = DAG.getNode(ISD::FMUL, dl, MVT::f32, t1, X); + SDValue t3 = DAG.getNode(ISD::FSUB, dl, MVT::f32, t2, + getF32Constant(DAG, 0x3fa22ae7)); + SDValue t4 = DAG.getNode(ISD::FMUL, dl, MVT::f32, t3, X); + SDValue t5 = DAG.getNode(ISD::FADD, dl, MVT::f32, t4, + getF32Constant(DAG, 0x40525723)); + SDValue t6 = DAG.getNode(ISD::FMUL, dl, MVT::f32, t5, X); + SDValue t7 = DAG.getNode(ISD::FSUB, dl, MVT::f32, t6, + getF32Constant(DAG, 0x40aaf200)); + SDValue t8 = DAG.getNode(ISD::FMUL, dl, MVT::f32, t7, X); + SDValue t9 = DAG.getNode(ISD::FADD, dl, MVT::f32, t8, + getF32Constant(DAG, 0x40c39dad)); + SDValue t10 = DAG.getNode(ISD::FMUL, dl, MVT::f32, t9, X); + SDValue Log2ofMantissa = DAG.getNode(ISD::FSUB, dl, MVT::f32, t10, + getF32Constant(DAG, 0x4042902c)); + + result = DAG.getNode(ISD::FADD, dl, + MVT::f32, LogOfExponent, Log2ofMantissa); + } + } else { + // No special expansion. + result = DAG.getNode(ISD::FLOG2, dl, + getValue(I.getOperand(1)).getValueType(), + getValue(I.getOperand(1))); + } + + setValue(&I, result); +} + +/// visitLog10 - Lower a log10 intrinsic. Handles the special sequences for +/// limited-precision mode. +void +SelectionDAGBuilder::visitLog10(CallInst &I) { + SDValue result; + DebugLoc dl = getCurDebugLoc(); + + if (getValue(I.getOperand(1)).getValueType() == MVT::f32 && + LimitFloatPrecision > 0 && LimitFloatPrecision <= 18) { + SDValue Op = getValue(I.getOperand(1)); + SDValue Op1 = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::i32, Op); + + // Scale the exponent by log10(2) [0.30102999f]. + SDValue Exp = GetExponent(DAG, Op1, TLI, dl); + SDValue LogOfExponent = DAG.getNode(ISD::FMUL, dl, MVT::f32, Exp, + getF32Constant(DAG, 0x3e9a209a)); + + // Get the significand and build it into a floating-point number with + // exponent of 1. + SDValue X = GetSignificand(DAG, Op1, dl); + + if (LimitFloatPrecision <= 6) { + // For floating-point precision of 6: + // + // Log10ofMantissa = + // -0.50419619f + + // (0.60948995f - 0.10380950f * x) * x; + // + // error 0.0014886165, which is 6 bits + SDValue t0 = DAG.getNode(ISD::FMUL, dl, MVT::f32, X, + getF32Constant(DAG, 0xbdd49a13)); + SDValue t1 = DAG.getNode(ISD::FADD, dl, MVT::f32, t0, + getF32Constant(DAG, 0x3f1c0789)); + SDValue t2 = DAG.getNode(ISD::FMUL, dl, MVT::f32, t1, X); + SDValue Log10ofMantissa = DAG.getNode(ISD::FSUB, dl, MVT::f32, t2, + getF32Constant(DAG, 0x3f011300)); + + result = DAG.getNode(ISD::FADD, dl, + MVT::f32, LogOfExponent, Log10ofMantissa); + } else if (LimitFloatPrecision > 6 && LimitFloatPrecision <= 12) { + // For floating-point precision of 12: + // + // Log10ofMantissa = + // -0.64831180f + + // (0.91751397f + + // (-0.31664806f + 0.47637168e-1f * x) * x) * x; + // + // error 0.00019228036, which is better than 12 bits + SDValue t0 = DAG.getNode(ISD::FMUL, dl, MVT::f32, X, + getF32Constant(DAG, 0x3d431f31)); + SDValue t1 = DAG.getNode(ISD::FSUB, dl, MVT::f32, t0, + getF32Constant(DAG, 0x3ea21fb2)); + SDValue t2 = DAG.getNode(ISD::FMUL, dl, MVT::f32, t1, X); + SDValue t3 = DAG.getNode(ISD::FADD, dl, MVT::f32, t2, + getF32Constant(DAG, 0x3f6ae232)); + SDValue t4 = DAG.getNode(ISD::FMUL, dl, MVT::f32, t3, X); + SDValue Log10ofMantissa = DAG.getNode(ISD::FSUB, dl, MVT::f32, t4, + getF32Constant(DAG, 0x3f25f7c3)); + + result = DAG.getNode(ISD::FADD, dl, + MVT::f32, LogOfExponent, Log10ofMantissa); + } else { // LimitFloatPrecision > 12 && LimitFloatPrecision <= 18 + // For floating-point precision of 18: + // + // Log10ofMantissa = + // -0.84299375f + + // (1.5327582f + + // (-1.0688956f + + // (0.49102474f + + // (-0.12539807f + 0.13508273e-1f * x) * x) * x) * x) * x; + // + // error 0.0000037995730, which is better than 18 bits + SDValue t0 = DAG.getNode(ISD::FMUL, dl, MVT::f32, X, + getF32Constant(DAG, 0x3c5d51ce)); + SDValue t1 = DAG.getNode(ISD::FSUB, dl, MVT::f32, t0, + getF32Constant(DAG, 0x3e00685a)); + SDValue t2 = DAG.getNode(ISD::FMUL, dl, MVT::f32, t1, X); + SDValue t3 = DAG.getNode(ISD::FADD, dl, MVT::f32, t2, + getF32Constant(DAG, 0x3efb6798)); + SDValue t4 = DAG.getNode(ISD::FMUL, dl, MVT::f32, t3, X); + SDValue t5 = DAG.getNode(ISD::FSUB, dl, MVT::f32, t4, + getF32Constant(DAG, 0x3f88d192)); + SDValue t6 = DAG.getNode(ISD::FMUL, dl, MVT::f32, t5, X); + SDValue t7 = DAG.getNode(ISD::FADD, dl, MVT::f32, t6, + getF32Constant(DAG, 0x3fc4316c)); + SDValue t8 = DAG.getNode(ISD::FMUL, dl, MVT::f32, t7, X); + SDValue Log10ofMantissa = DAG.getNode(ISD::FSUB, dl, MVT::f32, t8, + getF32Constant(DAG, 0x3f57ce70)); + + result = DAG.getNode(ISD::FADD, dl, + MVT::f32, LogOfExponent, Log10ofMantissa); + } + } else { + // No special expansion. + result = DAG.getNode(ISD::FLOG10, dl, + getValue(I.getOperand(1)).getValueType(), + getValue(I.getOperand(1))); + } + + setValue(&I, result); +} + +/// visitExp2 - Lower an exp2 intrinsic. Handles the special sequences for +/// limited-precision mode. +void +SelectionDAGBuilder::visitExp2(CallInst &I) { + SDValue result; + DebugLoc dl = getCurDebugLoc(); + + if (getValue(I.getOperand(1)).getValueType() == MVT::f32 && + LimitFloatPrecision > 0 && LimitFloatPrecision <= 18) { + SDValue Op = getValue(I.getOperand(1)); + + SDValue IntegerPartOfX = DAG.getNode(ISD::FP_TO_SINT, dl, MVT::i32, Op); + + // FractionalPartOfX = x - (float)IntegerPartOfX; + SDValue t1 = DAG.getNode(ISD::SINT_TO_FP, dl, MVT::f32, IntegerPartOfX); + SDValue X = DAG.getNode(ISD::FSUB, dl, MVT::f32, Op, t1); + + // IntegerPartOfX <<= 23; + IntegerPartOfX = DAG.getNode(ISD::SHL, dl, MVT::i32, IntegerPartOfX, + DAG.getConstant(23, TLI.getPointerTy())); + + if (LimitFloatPrecision <= 6) { + // For floating-point precision of 6: + // + // TwoToFractionalPartOfX = + // 0.997535578f + + // (0.735607626f + 0.252464424f * x) * x; + // + // error 0.0144103317, which is 6 bits + SDValue t2 = DAG.getNode(ISD::FMUL, dl, MVT::f32, X, + getF32Constant(DAG, 0x3e814304)); + SDValue t3 = DAG.getNode(ISD::FADD, dl, MVT::f32, t2, + getF32Constant(DAG, 0x3f3c50c8)); + SDValue t4 = DAG.getNode(ISD::FMUL, dl, MVT::f32, t3, X); + SDValue t5 = DAG.getNode(ISD::FADD, dl, MVT::f32, t4, + getF32Constant(DAG, 0x3f7f5e7e)); + SDValue t6 = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::i32, t5); + SDValue TwoToFractionalPartOfX = + DAG.getNode(ISD::ADD, dl, MVT::i32, t6, IntegerPartOfX); + + result = DAG.getNode(ISD::BIT_CONVERT, dl, + MVT::f32, TwoToFractionalPartOfX); + } else if (LimitFloatPrecision > 6 && LimitFloatPrecision <= 12) { + // For floating-point precision of 12: + // + // TwoToFractionalPartOfX = + // 0.999892986f + + // (0.696457318f + + // (0.224338339f + 0.792043434e-1f * x) * x) * x; + // + // error 0.000107046256, which is 13 to 14 bits + SDValue t2 = DAG.getNode(ISD::FMUL, dl, MVT::f32, X, + getF32Constant(DAG, 0x3da235e3)); + SDValue t3 = DAG.getNode(ISD::FADD, dl, MVT::f32, t2, + getF32Constant(DAG, 0x3e65b8f3)); + SDValue t4 = DAG.getNode(ISD::FMUL, dl, MVT::f32, t3, X); + SDValue t5 = DAG.getNode(ISD::FADD, dl, MVT::f32, t4, + getF32Constant(DAG, 0x3f324b07)); + SDValue t6 = DAG.getNode(ISD::FMUL, dl, MVT::f32, t5, X); + SDValue t7 = DAG.getNode(ISD::FADD, dl, MVT::f32, t6, + getF32Constant(DAG, 0x3f7ff8fd)); + SDValue t8 = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::i32, t7); + SDValue TwoToFractionalPartOfX = + DAG.getNode(ISD::ADD, dl, MVT::i32, t8, IntegerPartOfX); + + result = DAG.getNode(ISD::BIT_CONVERT, dl, + MVT::f32, TwoToFractionalPartOfX); + } else { // LimitFloatPrecision > 12 && LimitFloatPrecision <= 18 + // For floating-point precision of 18: + // + // TwoToFractionalPartOfX = + // 0.999999982f + + // (0.693148872f + + // (0.240227044f + + // (0.554906021e-1f + + // (0.961591928e-2f + + // (0.136028312e-2f + 0.157059148e-3f *x)*x)*x)*x)*x)*x; + // error 2.47208000*10^(-7), which is better than 18 bits + SDValue t2 = DAG.getNode(ISD::FMUL, dl, MVT::f32, X, + getF32Constant(DAG, 0x3924b03e)); + SDValue t3 = DAG.getNode(ISD::FADD, dl, MVT::f32, t2, + getF32Constant(DAG, 0x3ab24b87)); + SDValue t4 = DAG.getNode(ISD::FMUL, dl, MVT::f32, t3, X); + SDValue t5 = DAG.getNode(ISD::FADD, dl, MVT::f32, t4, + getF32Constant(DAG, 0x3c1d8c17)); + SDValue t6 = DAG.getNode(ISD::FMUL, dl, MVT::f32, t5, X); + SDValue t7 = DAG.getNode(ISD::FADD, dl, MVT::f32, t6, + getF32Constant(DAG, 0x3d634a1d)); + SDValue t8 = DAG.getNode(ISD::FMUL, dl, MVT::f32, t7, X); + SDValue t9 = DAG.getNode(ISD::FADD, dl, MVT::f32, t8, + getF32Constant(DAG, 0x3e75fe14)); + SDValue t10 = DAG.getNode(ISD::FMUL, dl, MVT::f32, t9, X); + SDValue t11 = DAG.getNode(ISD::FADD, dl, MVT::f32, t10, + getF32Constant(DAG, 0x3f317234)); + SDValue t12 = DAG.getNode(ISD::FMUL, dl, MVT::f32, t11, X); + SDValue t13 = DAG.getNode(ISD::FADD, dl, MVT::f32, t12, + getF32Constant(DAG, 0x3f800000)); + SDValue t14 = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::i32, t13); + SDValue TwoToFractionalPartOfX = + DAG.getNode(ISD::ADD, dl, MVT::i32, t14, IntegerPartOfX); + + result = DAG.getNode(ISD::BIT_CONVERT, dl, + MVT::f32, TwoToFractionalPartOfX); + } + } else { + // No special expansion. + result = DAG.getNode(ISD::FEXP2, dl, + getValue(I.getOperand(1)).getValueType(), + getValue(I.getOperand(1))); + } + + setValue(&I, result); +} + +/// visitPow - Lower a pow intrinsic. Handles the special sequences for +/// limited-precision mode with x == 10.0f. +void +SelectionDAGBuilder::visitPow(CallInst &I) { + SDValue result; + Value *Val = I.getOperand(1); + DebugLoc dl = getCurDebugLoc(); + bool IsExp10 = false; + + if (getValue(Val).getValueType() == MVT::f32 && + getValue(I.getOperand(2)).getValueType() == MVT::f32 && + LimitFloatPrecision > 0 && LimitFloatPrecision <= 18) { + if (Constant *C = const_cast(dyn_cast(Val))) { + if (ConstantFP *CFP = dyn_cast(C)) { + APFloat Ten(10.0f); + IsExp10 = CFP->getValueAPF().bitwiseIsEqual(Ten); + } + } + } + + if (IsExp10 && LimitFloatPrecision > 0 && LimitFloatPrecision <= 18) { + SDValue Op = getValue(I.getOperand(2)); + + // Put the exponent in the right bit position for later addition to the + // final result: + // + // #define LOG2OF10 3.3219281f + // IntegerPartOfX = (int32_t)(x * LOG2OF10); + SDValue t0 = DAG.getNode(ISD::FMUL, dl, MVT::f32, Op, + getF32Constant(DAG, 0x40549a78)); + SDValue IntegerPartOfX = DAG.getNode(ISD::FP_TO_SINT, dl, MVT::i32, t0); + + // FractionalPartOfX = x - (float)IntegerPartOfX; + SDValue t1 = DAG.getNode(ISD::SINT_TO_FP, dl, MVT::f32, IntegerPartOfX); + SDValue X = DAG.getNode(ISD::FSUB, dl, MVT::f32, t0, t1); + + // IntegerPartOfX <<= 23; + IntegerPartOfX = DAG.getNode(ISD::SHL, dl, MVT::i32, IntegerPartOfX, + DAG.getConstant(23, TLI.getPointerTy())); + + if (LimitFloatPrecision <= 6) { + // For floating-point precision of 6: + // + // twoToFractionalPartOfX = + // 0.997535578f + + // (0.735607626f + 0.252464424f * x) * x; + // + // error 0.0144103317, which is 6 bits + SDValue t2 = DAG.getNode(ISD::FMUL, dl, MVT::f32, X, + getF32Constant(DAG, 0x3e814304)); + SDValue t3 = DAG.getNode(ISD::FADD, dl, MVT::f32, t2, + getF32Constant(DAG, 0x3f3c50c8)); + SDValue t4 = DAG.getNode(ISD::FMUL, dl, MVT::f32, t3, X); + SDValue t5 = DAG.getNode(ISD::FADD, dl, MVT::f32, t4, + getF32Constant(DAG, 0x3f7f5e7e)); + SDValue t6 = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::i32, t5); + SDValue TwoToFractionalPartOfX = + DAG.getNode(ISD::ADD, dl, MVT::i32, t6, IntegerPartOfX); + + result = DAG.getNode(ISD::BIT_CONVERT, dl, + MVT::f32, TwoToFractionalPartOfX); + } else if (LimitFloatPrecision > 6 && LimitFloatPrecision <= 12) { + // For floating-point precision of 12: + // + // TwoToFractionalPartOfX = + // 0.999892986f + + // (0.696457318f + + // (0.224338339f + 0.792043434e-1f * x) * x) * x; + // + // error 0.000107046256, which is 13 to 14 bits + SDValue t2 = DAG.getNode(ISD::FMUL, dl, MVT::f32, X, + getF32Constant(DAG, 0x3da235e3)); + SDValue t3 = DAG.getNode(ISD::FADD, dl, MVT::f32, t2, + getF32Constant(DAG, 0x3e65b8f3)); + SDValue t4 = DAG.getNode(ISD::FMUL, dl, MVT::f32, t3, X); + SDValue t5 = DAG.getNode(ISD::FADD, dl, MVT::f32, t4, + getF32Constant(DAG, 0x3f324b07)); + SDValue t6 = DAG.getNode(ISD::FMUL, dl, MVT::f32, t5, X); + SDValue t7 = DAG.getNode(ISD::FADD, dl, MVT::f32, t6, + getF32Constant(DAG, 0x3f7ff8fd)); + SDValue t8 = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::i32, t7); + SDValue TwoToFractionalPartOfX = + DAG.getNode(ISD::ADD, dl, MVT::i32, t8, IntegerPartOfX); + + result = DAG.getNode(ISD::BIT_CONVERT, dl, + MVT::f32, TwoToFractionalPartOfX); + } else { // LimitFloatPrecision > 12 && LimitFloatPrecision <= 18 + // For floating-point precision of 18: + // + // TwoToFractionalPartOfX = + // 0.999999982f + + // (0.693148872f + + // (0.240227044f + + // (0.554906021e-1f + + // (0.961591928e-2f + + // (0.136028312e-2f + 0.157059148e-3f *x)*x)*x)*x)*x)*x; + // error 2.47208000*10^(-7), which is better than 18 bits + SDValue t2 = DAG.getNode(ISD::FMUL, dl, MVT::f32, X, + getF32Constant(DAG, 0x3924b03e)); + SDValue t3 = DAG.getNode(ISD::FADD, dl, MVT::f32, t2, + getF32Constant(DAG, 0x3ab24b87)); + SDValue t4 = DAG.getNode(ISD::FMUL, dl, MVT::f32, t3, X); + SDValue t5 = DAG.getNode(ISD::FADD, dl, MVT::f32, t4, + getF32Constant(DAG, 0x3c1d8c17)); + SDValue t6 = DAG.getNode(ISD::FMUL, dl, MVT::f32, t5, X); + SDValue t7 = DAG.getNode(ISD::FADD, dl, MVT::f32, t6, + getF32Constant(DAG, 0x3d634a1d)); + SDValue t8 = DAG.getNode(ISD::FMUL, dl, MVT::f32, t7, X); + SDValue t9 = DAG.getNode(ISD::FADD, dl, MVT::f32, t8, + getF32Constant(DAG, 0x3e75fe14)); + SDValue t10 = DAG.getNode(ISD::FMUL, dl, MVT::f32, t9, X); + SDValue t11 = DAG.getNode(ISD::FADD, dl, MVT::f32, t10, + getF32Constant(DAG, 0x3f317234)); + SDValue t12 = DAG.getNode(ISD::FMUL, dl, MVT::f32, t11, X); + SDValue t13 = DAG.getNode(ISD::FADD, dl, MVT::f32, t12, + getF32Constant(DAG, 0x3f800000)); + SDValue t14 = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::i32, t13); + SDValue TwoToFractionalPartOfX = + DAG.getNode(ISD::ADD, dl, MVT::i32, t14, IntegerPartOfX); + + result = DAG.getNode(ISD::BIT_CONVERT, dl, + MVT::f32, TwoToFractionalPartOfX); + } + } else { + // No special expansion. + result = DAG.getNode(ISD::FPOW, dl, + getValue(I.getOperand(1)).getValueType(), + getValue(I.getOperand(1)), + getValue(I.getOperand(2))); + } + + setValue(&I, result); +} + +/// visitIntrinsicCall - Lower the call to the specified intrinsic function. If +/// we want to emit this as a call to a named external function, return the name +/// otherwise lower it and return null. +const char * +SelectionDAGBuilder::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) { + DebugLoc dl = getCurDebugLoc(); + switch (Intrinsic) { + default: + // By default, turn this into a target intrinsic node. + visitTargetIntrinsic(I, Intrinsic); + return 0; + case Intrinsic::vastart: visitVAStart(I); return 0; + case Intrinsic::vaend: visitVAEnd(I); return 0; + case Intrinsic::vacopy: visitVACopy(I); return 0; + case Intrinsic::returnaddress: + setValue(&I, DAG.getNode(ISD::RETURNADDR, dl, TLI.getPointerTy(), + getValue(I.getOperand(1)))); + return 0; + case Intrinsic::frameaddress: + setValue(&I, DAG.getNode(ISD::FRAMEADDR, dl, TLI.getPointerTy(), + getValue(I.getOperand(1)))); + return 0; + case Intrinsic::setjmp: + return "_setjmp"+!TLI.usesUnderscoreSetJmp(); + break; + case Intrinsic::longjmp: + return "_longjmp"+!TLI.usesUnderscoreLongJmp(); + break; + case Intrinsic::memcpy: { + SDValue Op1 = getValue(I.getOperand(1)); + SDValue Op2 = getValue(I.getOperand(2)); + SDValue Op3 = getValue(I.getOperand(3)); + unsigned Align = cast(I.getOperand(4))->getZExtValue(); + DAG.setRoot(DAG.getMemcpy(getRoot(), dl, Op1, Op2, Op3, Align, false, + I.getOperand(1), 0, I.getOperand(2), 0)); + return 0; + } + case Intrinsic::memset: { + SDValue Op1 = getValue(I.getOperand(1)); + SDValue Op2 = getValue(I.getOperand(2)); + SDValue Op3 = getValue(I.getOperand(3)); + unsigned Align = cast(I.getOperand(4))->getZExtValue(); + DAG.setRoot(DAG.getMemset(getRoot(), dl, Op1, Op2, Op3, Align, + I.getOperand(1), 0)); + return 0; + } + case Intrinsic::memmove: { + SDValue Op1 = getValue(I.getOperand(1)); + SDValue Op2 = getValue(I.getOperand(2)); + SDValue Op3 = getValue(I.getOperand(3)); + unsigned Align = cast(I.getOperand(4))->getZExtValue(); + + // If the source and destination are known to not be aliases, we can + // lower memmove as memcpy. + uint64_t Size = -1ULL; + if (ConstantSDNode *C = dyn_cast(Op3)) + Size = C->getZExtValue(); + if (AA->alias(I.getOperand(1), Size, I.getOperand(2), Size) == + AliasAnalysis::NoAlias) { + DAG.setRoot(DAG.getMemcpy(getRoot(), dl, Op1, Op2, Op3, Align, false, + I.getOperand(1), 0, I.getOperand(2), 0)); + return 0; + } + + DAG.setRoot(DAG.getMemmove(getRoot(), dl, Op1, Op2, Op3, Align, + I.getOperand(1), 0, I.getOperand(2), 0)); + return 0; + } + case Intrinsic::dbg_stoppoint: + case Intrinsic::dbg_region_start: + case Intrinsic::dbg_region_end: + case Intrinsic::dbg_func_start: + // FIXME - Remove this instructions once the dust settles. + return 0; + case Intrinsic::dbg_declare: { + if (OptLevel != CodeGenOpt::None) + // FIXME: Variable debug info is not supported here. + return 0; + DwarfWriter *DW = DAG.getDwarfWriter(); + if (!DW) + return 0; + DbgDeclareInst &DI = cast(I); + if (!isValidDebugInfoIntrinsic(DI, CodeGenOpt::None)) + return 0; + + MDNode *Variable = DI.getVariable(); + Value *Address = DI.getAddress(); + if (BitCastInst *BCI = dyn_cast(Address)) + Address = BCI->getOperand(0); + AllocaInst *AI = dyn_cast(Address); + // Don't handle byval struct arguments or VLAs, for example. + if (!AI) + return 0; + DenseMap::iterator SI = + FuncInfo.StaticAllocaMap.find(AI); + if (SI == FuncInfo.StaticAllocaMap.end()) + return 0; // VLAs. + int FI = SI->second; + + MachineModuleInfo *MMI = DAG.getMachineModuleInfo(); + if (MMI) { + MetadataContext &TheMetadata = + DI.getParent()->getContext().getMetadata(); + unsigned MDDbgKind = TheMetadata.getMDKind("dbg"); + MDNode *Dbg = TheMetadata.getMD(MDDbgKind, &DI); + MMI->setVariableDbgInfo(Variable, FI, Dbg); + } + return 0; + } + case Intrinsic::eh_exception: { + // Insert the EXCEPTIONADDR instruction. + assert(CurMBB->isLandingPad() &&"Call to eh.exception not in landing pad!"); + SDVTList VTs = DAG.getVTList(TLI.getPointerTy(), MVT::Other); + SDValue Ops[1]; + Ops[0] = DAG.getRoot(); + SDValue Op = DAG.getNode(ISD::EXCEPTIONADDR, dl, VTs, Ops, 1); + setValue(&I, Op); + DAG.setRoot(Op.getValue(1)); + return 0; + } + + case Intrinsic::eh_selector: { + MachineModuleInfo *MMI = DAG.getMachineModuleInfo(); + + if (CurMBB->isLandingPad()) + AddCatchInfo(I, MMI, CurMBB); + else { +#ifndef NDEBUG + FuncInfo.CatchInfoLost.insert(&I); +#endif + // FIXME: Mark exception selector register as live in. Hack for PR1508. + unsigned Reg = TLI.getExceptionSelectorRegister(); + if (Reg) CurMBB->addLiveIn(Reg); + } + + // Insert the EHSELECTION instruction. + SDVTList VTs = DAG.getVTList(TLI.getPointerTy(), MVT::Other); + SDValue Ops[2]; + Ops[0] = getValue(I.getOperand(1)); + Ops[1] = getRoot(); + SDValue Op = DAG.getNode(ISD::EHSELECTION, dl, VTs, Ops, 2); + + DAG.setRoot(Op.getValue(1)); + + setValue(&I, DAG.getSExtOrTrunc(Op, dl, MVT::i32)); + return 0; + } + + case Intrinsic::eh_typeid_for: { + MachineModuleInfo *MMI = DAG.getMachineModuleInfo(); + + if (MMI) { + // Find the type id for the given typeinfo. + GlobalVariable *GV = ExtractTypeInfo(I.getOperand(1)); + + unsigned TypeID = MMI->getTypeIDFor(GV); + setValue(&I, DAG.getConstant(TypeID, MVT::i32)); + } else { + // Return something different to eh_selector. + setValue(&I, DAG.getConstant(1, MVT::i32)); + } + + return 0; + } + + case Intrinsic::eh_return_i32: + case Intrinsic::eh_return_i64: + if (MachineModuleInfo *MMI = DAG.getMachineModuleInfo()) { + MMI->setCallsEHReturn(true); + DAG.setRoot(DAG.getNode(ISD::EH_RETURN, dl, + MVT::Other, + getControlRoot(), + getValue(I.getOperand(1)), + getValue(I.getOperand(2)))); + } else { + setValue(&I, DAG.getConstant(0, TLI.getPointerTy())); + } + + return 0; + case Intrinsic::eh_unwind_init: + if (MachineModuleInfo *MMI = DAG.getMachineModuleInfo()) { + MMI->setCallsUnwindInit(true); + } + + return 0; + + case Intrinsic::eh_dwarf_cfa: { + EVT VT = getValue(I.getOperand(1)).getValueType(); + SDValue CfaArg = DAG.getSExtOrTrunc(getValue(I.getOperand(1)), dl, + TLI.getPointerTy()); + + SDValue Offset = DAG.getNode(ISD::ADD, dl, + TLI.getPointerTy(), + DAG.getNode(ISD::FRAME_TO_ARGS_OFFSET, dl, + TLI.getPointerTy()), + CfaArg); + setValue(&I, DAG.getNode(ISD::ADD, dl, + TLI.getPointerTy(), + DAG.getNode(ISD::FRAMEADDR, dl, + TLI.getPointerTy(), + DAG.getConstant(0, + TLI.getPointerTy())), + Offset)); + return 0; + } + case Intrinsic::convertff: + case Intrinsic::convertfsi: + case Intrinsic::convertfui: + case Intrinsic::convertsif: + case Intrinsic::convertuif: + case Intrinsic::convertss: + case Intrinsic::convertsu: + case Intrinsic::convertus: + case Intrinsic::convertuu: { + ISD::CvtCode Code = ISD::CVT_INVALID; + switch (Intrinsic) { + case Intrinsic::convertff: Code = ISD::CVT_FF; break; + case Intrinsic::convertfsi: Code = ISD::CVT_FS; break; + case Intrinsic::convertfui: Code = ISD::CVT_FU; break; + case Intrinsic::convertsif: Code = ISD::CVT_SF; break; + case Intrinsic::convertuif: Code = ISD::CVT_UF; break; + case Intrinsic::convertss: Code = ISD::CVT_SS; break; + case Intrinsic::convertsu: Code = ISD::CVT_SU; break; + case Intrinsic::convertus: Code = ISD::CVT_US; break; + case Intrinsic::convertuu: Code = ISD::CVT_UU; break; + } + EVT DestVT = TLI.getValueType(I.getType()); + Value* Op1 = I.getOperand(1); + setValue(&I, DAG.getConvertRndSat(DestVT, getCurDebugLoc(), getValue(Op1), + DAG.getValueType(DestVT), + DAG.getValueType(getValue(Op1).getValueType()), + getValue(I.getOperand(2)), + getValue(I.getOperand(3)), + Code)); + return 0; + } + + case Intrinsic::sqrt: + setValue(&I, DAG.getNode(ISD::FSQRT, dl, + getValue(I.getOperand(1)).getValueType(), + getValue(I.getOperand(1)))); + return 0; + case Intrinsic::powi: + setValue(&I, DAG.getNode(ISD::FPOWI, dl, + getValue(I.getOperand(1)).getValueType(), + getValue(I.getOperand(1)), + getValue(I.getOperand(2)))); + return 0; + case Intrinsic::sin: + setValue(&I, DAG.getNode(ISD::FSIN, dl, + getValue(I.getOperand(1)).getValueType(), + getValue(I.getOperand(1)))); + return 0; + case Intrinsic::cos: + setValue(&I, DAG.getNode(ISD::FCOS, dl, + getValue(I.getOperand(1)).getValueType(), + getValue(I.getOperand(1)))); + return 0; + case Intrinsic::log: + visitLog(I); + return 0; + case Intrinsic::log2: + visitLog2(I); + return 0; + case Intrinsic::log10: + visitLog10(I); + return 0; + case Intrinsic::exp: + visitExp(I); + return 0; + case Intrinsic::exp2: + visitExp2(I); + return 0; + case Intrinsic::pow: + visitPow(I); + return 0; + case Intrinsic::pcmarker: { + SDValue Tmp = getValue(I.getOperand(1)); + DAG.setRoot(DAG.getNode(ISD::PCMARKER, dl, MVT::Other, getRoot(), Tmp)); + return 0; + } + case Intrinsic::readcyclecounter: { + SDValue Op = getRoot(); + SDValue Tmp = DAG.getNode(ISD::READCYCLECOUNTER, dl, + DAG.getVTList(MVT::i64, MVT::Other), + &Op, 1); + setValue(&I, Tmp); + DAG.setRoot(Tmp.getValue(1)); + return 0; + } + case Intrinsic::bswap: + setValue(&I, DAG.getNode(ISD::BSWAP, dl, + getValue(I.getOperand(1)).getValueType(), + getValue(I.getOperand(1)))); + return 0; + case Intrinsic::cttz: { + SDValue Arg = getValue(I.getOperand(1)); + EVT Ty = Arg.getValueType(); + SDValue result = DAG.getNode(ISD::CTTZ, dl, Ty, Arg); + setValue(&I, result); + return 0; + } + case Intrinsic::ctlz: { + SDValue Arg = getValue(I.getOperand(1)); + EVT Ty = Arg.getValueType(); + SDValue result = DAG.getNode(ISD::CTLZ, dl, Ty, Arg); + setValue(&I, result); + return 0; + } + case Intrinsic::ctpop: { + SDValue Arg = getValue(I.getOperand(1)); + EVT Ty = Arg.getValueType(); + SDValue result = DAG.getNode(ISD::CTPOP, dl, Ty, Arg); + setValue(&I, result); + return 0; + } + case Intrinsic::stacksave: { + SDValue Op = getRoot(); + SDValue Tmp = DAG.getNode(ISD::STACKSAVE, dl, + DAG.getVTList(TLI.getPointerTy(), MVT::Other), &Op, 1); + setValue(&I, Tmp); + DAG.setRoot(Tmp.getValue(1)); + return 0; + } + case Intrinsic::stackrestore: { + SDValue Tmp = getValue(I.getOperand(1)); + DAG.setRoot(DAG.getNode(ISD::STACKRESTORE, dl, MVT::Other, getRoot(), Tmp)); + return 0; + } + case Intrinsic::stackprotector: { + // Emit code into the DAG to store the stack guard onto the stack. + MachineFunction &MF = DAG.getMachineFunction(); + MachineFrameInfo *MFI = MF.getFrameInfo(); + EVT PtrTy = TLI.getPointerTy(); + + SDValue Src = getValue(I.getOperand(1)); // The guard's value. + AllocaInst *Slot = cast(I.getOperand(2)); + + int FI = FuncInfo.StaticAllocaMap[Slot]; + MFI->setStackProtectorIndex(FI); + + SDValue FIN = DAG.getFrameIndex(FI, PtrTy); + + // Store the stack protector onto the stack. + SDValue Result = DAG.getStore(getRoot(), getCurDebugLoc(), Src, FIN, + PseudoSourceValue::getFixedStack(FI), + 0, true); + setValue(&I, Result); + DAG.setRoot(Result); + return 0; + } + case Intrinsic::objectsize: { + // If we don't know by now, we're never going to know. + ConstantInt *CI = dyn_cast(I.getOperand(2)); + + assert(CI && "Non-constant type in __builtin_object_size?"); + + SDValue Arg = getValue(I.getOperand(0)); + EVT Ty = Arg.getValueType(); + + if (CI->getZExtValue() < 2) + setValue(&I, DAG.getConstant(-1ULL, Ty)); + else + setValue(&I, DAG.getConstant(0, Ty)); + return 0; + } + case Intrinsic::var_annotation: + // Discard annotate attributes + return 0; + + case Intrinsic::init_trampoline: { + const Function *F = cast(I.getOperand(2)->stripPointerCasts()); + + SDValue Ops[6]; + Ops[0] = getRoot(); + Ops[1] = getValue(I.getOperand(1)); + Ops[2] = getValue(I.getOperand(2)); + Ops[3] = getValue(I.getOperand(3)); + Ops[4] = DAG.getSrcValue(I.getOperand(1)); + Ops[5] = DAG.getSrcValue(F); + + SDValue Tmp = DAG.getNode(ISD::TRAMPOLINE, dl, + DAG.getVTList(TLI.getPointerTy(), MVT::Other), + Ops, 6); + + setValue(&I, Tmp); + DAG.setRoot(Tmp.getValue(1)); + return 0; + } + + case Intrinsic::gcroot: + if (GFI) { + Value *Alloca = I.getOperand(1); + Constant *TypeMap = cast(I.getOperand(2)); + + FrameIndexSDNode *FI = cast(getValue(Alloca).getNode()); + GFI->addStackRoot(FI->getIndex(), TypeMap); + } + return 0; + + case Intrinsic::gcread: + case Intrinsic::gcwrite: + llvm_unreachable("GC failed to lower gcread/gcwrite intrinsics!"); + return 0; + + case Intrinsic::flt_rounds: { + setValue(&I, DAG.getNode(ISD::FLT_ROUNDS_, dl, MVT::i32)); + return 0; + } + + case Intrinsic::trap: { + DAG.setRoot(DAG.getNode(ISD::TRAP, dl,MVT::Other, getRoot())); + return 0; + } + + case Intrinsic::uadd_with_overflow: + return implVisitAluOverflow(I, ISD::UADDO); + case Intrinsic::sadd_with_overflow: + return implVisitAluOverflow(I, ISD::SADDO); + case Intrinsic::usub_with_overflow: + return implVisitAluOverflow(I, ISD::USUBO); + case Intrinsic::ssub_with_overflow: + return implVisitAluOverflow(I, ISD::SSUBO); + case Intrinsic::umul_with_overflow: + return implVisitAluOverflow(I, ISD::UMULO); + case Intrinsic::smul_with_overflow: + return implVisitAluOverflow(I, ISD::SMULO); + + case Intrinsic::prefetch: { + SDValue Ops[4]; + Ops[0] = getRoot(); + Ops[1] = getValue(I.getOperand(1)); + Ops[2] = getValue(I.getOperand(2)); + Ops[3] = getValue(I.getOperand(3)); + DAG.setRoot(DAG.getNode(ISD::PREFETCH, dl, MVT::Other, &Ops[0], 4)); + return 0; + } + + case Intrinsic::memory_barrier: { + SDValue Ops[6]; + Ops[0] = getRoot(); + for (int x = 1; x < 6; ++x) + Ops[x] = getValue(I.getOperand(x)); + + DAG.setRoot(DAG.getNode(ISD::MEMBARRIER, dl, MVT::Other, &Ops[0], 6)); + return 0; + } + case Intrinsic::atomic_cmp_swap: { + SDValue Root = getRoot(); + SDValue L = + DAG.getAtomic(ISD::ATOMIC_CMP_SWAP, getCurDebugLoc(), + getValue(I.getOperand(2)).getValueType().getSimpleVT(), + Root, + getValue(I.getOperand(1)), + getValue(I.getOperand(2)), + getValue(I.getOperand(3)), + I.getOperand(1)); + setValue(&I, L); + DAG.setRoot(L.getValue(1)); + return 0; + } + case Intrinsic::atomic_load_add: + return implVisitBinaryAtomic(I, ISD::ATOMIC_LOAD_ADD); + case Intrinsic::atomic_load_sub: + return implVisitBinaryAtomic(I, ISD::ATOMIC_LOAD_SUB); + case Intrinsic::atomic_load_or: + return implVisitBinaryAtomic(I, ISD::ATOMIC_LOAD_OR); + case Intrinsic::atomic_load_xor: + return implVisitBinaryAtomic(I, ISD::ATOMIC_LOAD_XOR); + case Intrinsic::atomic_load_and: + return implVisitBinaryAtomic(I, ISD::ATOMIC_LOAD_AND); + case Intrinsic::atomic_load_nand: + return implVisitBinaryAtomic(I, ISD::ATOMIC_LOAD_NAND); + case Intrinsic::atomic_load_max: + return implVisitBinaryAtomic(I, ISD::ATOMIC_LOAD_MAX); + case Intrinsic::atomic_load_min: + return implVisitBinaryAtomic(I, ISD::ATOMIC_LOAD_MIN); + case Intrinsic::atomic_load_umin: + return implVisitBinaryAtomic(I, ISD::ATOMIC_LOAD_UMIN); + case Intrinsic::atomic_load_umax: + return implVisitBinaryAtomic(I, ISD::ATOMIC_LOAD_UMAX); + case Intrinsic::atomic_swap: + return implVisitBinaryAtomic(I, ISD::ATOMIC_SWAP); + + case Intrinsic::invariant_start: + case Intrinsic::lifetime_start: + // Discard region information. + setValue(&I, DAG.getUNDEF(TLI.getPointerTy())); + return 0; + case Intrinsic::invariant_end: + case Intrinsic::lifetime_end: + // Discard region information. + return 0; + } +} + +/// Test if the given instruction is in a position to be optimized +/// with a tail-call. This roughly means that it's in a block with +/// a return and there's nothing that needs to be scheduled +/// between it and the return. +/// +/// This function only tests target-independent requirements. +/// For target-dependent requirements, a target should override +/// TargetLowering::IsEligibleForTailCallOptimization. +/// +static bool +isInTailCallPosition(const Instruction *I, Attributes CalleeRetAttr, + const TargetLowering &TLI) { + const BasicBlock *ExitBB = I->getParent(); + const TerminatorInst *Term = ExitBB->getTerminator(); + const ReturnInst *Ret = dyn_cast(Term); + const Function *F = ExitBB->getParent(); + + // The block must end in a return statement or an unreachable. + if (!Ret && !isa(Term)) return false; + + // If I will have a chain, make sure no other instruction that will have a + // chain interposes between I and the return. + if (I->mayHaveSideEffects() || I->mayReadFromMemory() || + !I->isSafeToSpeculativelyExecute()) + for (BasicBlock::const_iterator BBI = prior(prior(ExitBB->end())); ; + --BBI) { + if (&*BBI == I) + break; + if (BBI->mayHaveSideEffects() || BBI->mayReadFromMemory() || + !BBI->isSafeToSpeculativelyExecute()) + return false; + } + + // If the block ends with a void return or unreachable, it doesn't matter + // what the call's return type is. + if (!Ret || Ret->getNumOperands() == 0) return true; + + // If the return value is undef, it doesn't matter what the call's + // return type is. + if (isa(Ret->getOperand(0))) return true; + + // Conservatively require the attributes of the call to match those of + // the return. Ignore noalias because it doesn't affect the call sequence. + unsigned CallerRetAttr = F->getAttributes().getRetAttributes(); + if ((CalleeRetAttr ^ CallerRetAttr) & ~Attribute::NoAlias) + return false; + + // Otherwise, make sure the unmodified return value of I is the return value. + for (const Instruction *U = dyn_cast(Ret->getOperand(0)); ; + U = dyn_cast(U->getOperand(0))) { + if (!U) + return false; + if (!U->hasOneUse()) + return false; + if (U == I) + break; + // Check for a truly no-op truncate. + if (isa(U) && + TLI.isTruncateFree(U->getOperand(0)->getType(), U->getType())) + continue; + // Check for a truly no-op bitcast. + if (isa(U) && + (U->getOperand(0)->getType() == U->getType() || + (isa(U->getOperand(0)->getType()) && + isa(U->getType())))) + continue; + // Otherwise it's not a true no-op. + return false; + } + + return true; +} + +void SelectionDAGBuilder::LowerCallTo(CallSite CS, SDValue Callee, + bool isTailCall, + MachineBasicBlock *LandingPad) { + const PointerType *PT = cast(CS.getCalledValue()->getType()); + const FunctionType *FTy = cast(PT->getElementType()); + const Type *RetTy = FTy->getReturnType(); + MachineModuleInfo *MMI = DAG.getMachineModuleInfo(); + unsigned BeginLabel = 0, EndLabel = 0; + + TargetLowering::ArgListTy Args; + TargetLowering::ArgListEntry Entry; + Args.reserve(CS.arg_size()); + + // Check whether the function can return without sret-demotion. + SmallVector OutVTs; + SmallVector OutsFlags; + SmallVector Offsets; + getReturnInfo(RetTy, CS.getAttributes().getRetAttributes(), + OutVTs, OutsFlags, TLI, &Offsets); + + + bool CanLowerReturn = TLI.CanLowerReturn(CS.getCallingConv(), + FTy->isVarArg(), OutVTs, OutsFlags, DAG); + + SDValue DemoteStackSlot; + + if (!CanLowerReturn) { + uint64_t TySize = TLI.getTargetData()->getTypeAllocSize( + FTy->getReturnType()); + unsigned Align = TLI.getTargetData()->getPrefTypeAlignment( + FTy->getReturnType()); + MachineFunction &MF = DAG.getMachineFunction(); + int SSFI = MF.getFrameInfo()->CreateStackObject(TySize, Align, false); + const Type *StackSlotPtrType = PointerType::getUnqual(FTy->getReturnType()); + + DemoteStackSlot = DAG.getFrameIndex(SSFI, TLI.getPointerTy()); + Entry.Node = DemoteStackSlot; + Entry.Ty = StackSlotPtrType; + Entry.isSExt = false; + Entry.isZExt = false; + Entry.isInReg = false; + Entry.isSRet = true; + Entry.isNest = false; + Entry.isByVal = false; + Entry.Alignment = Align; + Args.push_back(Entry); + RetTy = Type::getVoidTy(FTy->getContext()); + } + + for (CallSite::arg_iterator i = CS.arg_begin(), e = CS.arg_end(); + i != e; ++i) { + SDValue ArgNode = getValue(*i); + Entry.Node = ArgNode; Entry.Ty = (*i)->getType(); + + unsigned attrInd = i - CS.arg_begin() + 1; + Entry.isSExt = CS.paramHasAttr(attrInd, Attribute::SExt); + Entry.isZExt = CS.paramHasAttr(attrInd, Attribute::ZExt); + Entry.isInReg = CS.paramHasAttr(attrInd, Attribute::InReg); + Entry.isSRet = CS.paramHasAttr(attrInd, Attribute::StructRet); + Entry.isNest = CS.paramHasAttr(attrInd, Attribute::Nest); + Entry.isByVal = CS.paramHasAttr(attrInd, Attribute::ByVal); + Entry.Alignment = CS.getParamAlignment(attrInd); + Args.push_back(Entry); + } + + if (LandingPad && MMI) { + // Insert a label before the invoke call to mark the try range. This can be + // used to detect deletion of the invoke via the MachineModuleInfo. + BeginLabel = MMI->NextLabelID(); + + // Both PendingLoads and PendingExports must be flushed here; + // this call might not return. + (void)getRoot(); + DAG.setRoot(DAG.getLabel(ISD::EH_LABEL, getCurDebugLoc(), + getControlRoot(), BeginLabel)); + } + + // Check if target-independent constraints permit a tail call here. + // Target-dependent constraints are checked within TLI.LowerCallTo. + if (isTailCall && + !isInTailCallPosition(CS.getInstruction(), + CS.getAttributes().getRetAttributes(), + TLI)) + isTailCall = false; + + std::pair Result = + TLI.LowerCallTo(getRoot(), RetTy, + CS.paramHasAttr(0, Attribute::SExt), + CS.paramHasAttr(0, Attribute::ZExt), FTy->isVarArg(), + CS.paramHasAttr(0, Attribute::InReg), FTy->getNumParams(), + CS.getCallingConv(), + isTailCall, + !CS.getInstruction()->use_empty(), + Callee, Args, DAG, getCurDebugLoc()); + assert((isTailCall || Result.second.getNode()) && + "Non-null chain expected with non-tail call!"); + assert((Result.second.getNode() || !Result.first.getNode()) && + "Null value expected with tail call!"); + if (Result.first.getNode()) + setValue(CS.getInstruction(), Result.first); + else if (!CanLowerReturn && Result.second.getNode()) { + // The instruction result is the result of loading from the + // hidden sret parameter. + SmallVector PVTs; + const Type *PtrRetTy = PointerType::getUnqual(FTy->getReturnType()); + + ComputeValueVTs(TLI, PtrRetTy, PVTs); + assert(PVTs.size() == 1 && "Pointers should fit in one register"); + EVT PtrVT = PVTs[0]; + unsigned NumValues = OutVTs.size(); + SmallVector Values(NumValues); + SmallVector Chains(NumValues); + + for (unsigned i = 0; i < NumValues; ++i) { + SDValue L = DAG.getLoad(OutVTs[i], getCurDebugLoc(), Result.second, + DAG.getNode(ISD::ADD, getCurDebugLoc(), PtrVT, DemoteStackSlot, + DAG.getConstant(Offsets[i], PtrVT)), + NULL, Offsets[i], false, 1); + Values[i] = L; + Chains[i] = L.getValue(1); + } + SDValue Chain = DAG.getNode(ISD::TokenFactor, getCurDebugLoc(), + MVT::Other, &Chains[0], NumValues); + PendingLoads.push_back(Chain); + + setValue(CS.getInstruction(), DAG.getNode(ISD::MERGE_VALUES, + getCurDebugLoc(), DAG.getVTList(&OutVTs[0], NumValues), + &Values[0], NumValues)); + } + // As a special case, a null chain means that a tail call has + // been emitted and the DAG root is already updated. + if (Result.second.getNode()) + DAG.setRoot(Result.second); + else + HasTailCall = true; + + if (LandingPad && MMI) { + // Insert a label at the end of the invoke call to mark the try range. This + // can be used to detect deletion of the invoke via the MachineModuleInfo. + EndLabel = MMI->NextLabelID(); + DAG.setRoot(DAG.getLabel(ISD::EH_LABEL, getCurDebugLoc(), + getRoot(), EndLabel)); + + // Inform MachineModuleInfo of range. + MMI->addInvoke(LandingPad, BeginLabel, EndLabel); + } +} + + +void SelectionDAGBuilder::visitCall(CallInst &I) { + const char *RenameFn = 0; + if (Function *F = I.getCalledFunction()) { + if (F->isDeclaration()) { + const TargetIntrinsicInfo *II = TLI.getTargetMachine().getIntrinsicInfo(); + if (II) { + if (unsigned IID = II->getIntrinsicID(F)) { + RenameFn = visitIntrinsicCall(I, IID); + if (!RenameFn) + return; + } + } + if (unsigned IID = F->getIntrinsicID()) { + RenameFn = visitIntrinsicCall(I, IID); + if (!RenameFn) + return; + } + } + + // Check for well-known libc/libm calls. If the function is internal, it + // can't be a library call. + if (!F->hasLocalLinkage() && F->hasName()) { + StringRef Name = F->getName(); + if (Name == "copysign" || Name == "copysignf") { + if (I.getNumOperands() == 3 && // Basic sanity checks. + I.getOperand(1)->getType()->isFloatingPoint() && + I.getType() == I.getOperand(1)->getType() && + I.getType() == I.getOperand(2)->getType()) { + SDValue LHS = getValue(I.getOperand(1)); + SDValue RHS = getValue(I.getOperand(2)); + setValue(&I, DAG.getNode(ISD::FCOPYSIGN, getCurDebugLoc(), + LHS.getValueType(), LHS, RHS)); + return; + } + } else if (Name == "fabs" || Name == "fabsf" || Name == "fabsl") { + if (I.getNumOperands() == 2 && // Basic sanity checks. + I.getOperand(1)->getType()->isFloatingPoint() && + I.getType() == I.getOperand(1)->getType()) { + SDValue Tmp = getValue(I.getOperand(1)); + setValue(&I, DAG.getNode(ISD::FABS, getCurDebugLoc(), + Tmp.getValueType(), Tmp)); + return; + } + } else if (Name == "sin" || Name == "sinf" || Name == "sinl") { + if (I.getNumOperands() == 2 && // Basic sanity checks. + I.getOperand(1)->getType()->isFloatingPoint() && + I.getType() == I.getOperand(1)->getType() && + I.onlyReadsMemory()) { + SDValue Tmp = getValue(I.getOperand(1)); + setValue(&I, DAG.getNode(ISD::FSIN, getCurDebugLoc(), + Tmp.getValueType(), Tmp)); + return; + } + } else if (Name == "cos" || Name == "cosf" || Name == "cosl") { + if (I.getNumOperands() == 2 && // Basic sanity checks. + I.getOperand(1)->getType()->isFloatingPoint() && + I.getType() == I.getOperand(1)->getType() && + I.onlyReadsMemory()) { + SDValue Tmp = getValue(I.getOperand(1)); + setValue(&I, DAG.getNode(ISD::FCOS, getCurDebugLoc(), + Tmp.getValueType(), Tmp)); + return; + } + } else if (Name == "sqrt" || Name == "sqrtf" || Name == "sqrtl") { + if (I.getNumOperands() == 2 && // Basic sanity checks. + I.getOperand(1)->getType()->isFloatingPoint() && + I.getType() == I.getOperand(1)->getType() && + I.onlyReadsMemory()) { + SDValue Tmp = getValue(I.getOperand(1)); + setValue(&I, DAG.getNode(ISD::FSQRT, getCurDebugLoc(), + Tmp.getValueType(), Tmp)); + return; + } + } + } + } else if (isa(I.getOperand(0))) { + visitInlineAsm(&I); + return; + } + + SDValue Callee; + if (!RenameFn) + Callee = getValue(I.getOperand(0)); + else + Callee = DAG.getExternalSymbol(RenameFn, TLI.getPointerTy()); + + // Check if we can potentially perform a tail call. More detailed + // checking is be done within LowerCallTo, after more information + // about the call is known. + bool isTailCall = PerformTailCallOpt && I.isTailCall(); + + LowerCallTo(&I, Callee, isTailCall); +} + + +/// getCopyFromRegs - Emit a series of CopyFromReg nodes that copies from +/// this value and returns the result as a ValueVT value. This uses +/// Chain/Flag as the input and updates them for the output Chain/Flag. +/// If the Flag pointer is NULL, no flag is used. +SDValue RegsForValue::getCopyFromRegs(SelectionDAG &DAG, DebugLoc dl, + SDValue &Chain, + SDValue *Flag) const { + // Assemble the legal parts into the final values. + SmallVector Values(ValueVTs.size()); + SmallVector Parts; + for (unsigned Value = 0, Part = 0, e = ValueVTs.size(); Value != e; ++Value) { + // Copy the legal parts from the registers. + EVT ValueVT = ValueVTs[Value]; + unsigned NumRegs = TLI->getNumRegisters(*DAG.getContext(), ValueVT); + EVT RegisterVT = RegVTs[Value]; + + Parts.resize(NumRegs); + for (unsigned i = 0; i != NumRegs; ++i) { + SDValue P; + if (Flag == 0) + P = DAG.getCopyFromReg(Chain, dl, Regs[Part+i], RegisterVT); + else { + P = DAG.getCopyFromReg(Chain, dl, Regs[Part+i], RegisterVT, *Flag); + *Flag = P.getValue(2); + } + Chain = P.getValue(1); + + // If the source register was virtual and if we know something about it, + // add an assert node. + if (TargetRegisterInfo::isVirtualRegister(Regs[Part+i]) && + RegisterVT.isInteger() && !RegisterVT.isVector()) { + unsigned SlotNo = Regs[Part+i]-TargetRegisterInfo::FirstVirtualRegister; + FunctionLoweringInfo &FLI = DAG.getFunctionLoweringInfo(); + if (FLI.LiveOutRegInfo.size() > SlotNo) { + FunctionLoweringInfo::LiveOutInfo &LOI = FLI.LiveOutRegInfo[SlotNo]; + + unsigned RegSize = RegisterVT.getSizeInBits(); + unsigned NumSignBits = LOI.NumSignBits; + unsigned NumZeroBits = LOI.KnownZero.countLeadingOnes(); + + // FIXME: We capture more information than the dag can represent. For + // now, just use the tightest assertzext/assertsext possible. + bool isSExt = true; + EVT FromVT(MVT::Other); + if (NumSignBits == RegSize) + isSExt = true, FromVT = MVT::i1; // ASSERT SEXT 1 + else if (NumZeroBits >= RegSize-1) + isSExt = false, FromVT = MVT::i1; // ASSERT ZEXT 1 + else if (NumSignBits > RegSize-8) + isSExt = true, FromVT = MVT::i8; // ASSERT SEXT 8 + else if (NumZeroBits >= RegSize-8) + isSExt = false, FromVT = MVT::i8; // ASSERT ZEXT 8 + else if (NumSignBits > RegSize-16) + isSExt = true, FromVT = MVT::i16; // ASSERT SEXT 16 + else if (NumZeroBits >= RegSize-16) + isSExt = false, FromVT = MVT::i16; // ASSERT ZEXT 16 + else if (NumSignBits > RegSize-32) + isSExt = true, FromVT = MVT::i32; // ASSERT SEXT 32 + else if (NumZeroBits >= RegSize-32) + isSExt = false, FromVT = MVT::i32; // ASSERT ZEXT 32 + + if (FromVT != MVT::Other) { + P = DAG.getNode(isSExt ? ISD::AssertSext : ISD::AssertZext, dl, + RegisterVT, P, DAG.getValueType(FromVT)); + + } + } + } + + Parts[i] = P; + } + + Values[Value] = getCopyFromParts(DAG, dl, Parts.begin(), + NumRegs, RegisterVT, ValueVT); + Part += NumRegs; + Parts.clear(); + } + + return DAG.getNode(ISD::MERGE_VALUES, dl, + DAG.getVTList(&ValueVTs[0], ValueVTs.size()), + &Values[0], ValueVTs.size()); +} + +/// getCopyToRegs - Emit a series of CopyToReg nodes that copies the +/// specified value into the registers specified by this object. This uses +/// Chain/Flag as the input and updates them for the output Chain/Flag. +/// If the Flag pointer is NULL, no flag is used. +void RegsForValue::getCopyToRegs(SDValue Val, SelectionDAG &DAG, DebugLoc dl, + SDValue &Chain, SDValue *Flag) const { + // Get the list of the values's legal parts. + unsigned NumRegs = Regs.size(); + SmallVector Parts(NumRegs); + for (unsigned Value = 0, Part = 0, e = ValueVTs.size(); Value != e; ++Value) { + EVT ValueVT = ValueVTs[Value]; + unsigned NumParts = TLI->getNumRegisters(*DAG.getContext(), ValueVT); + EVT RegisterVT = RegVTs[Value]; + + getCopyToParts(DAG, dl, Val.getValue(Val.getResNo() + Value), + &Parts[Part], NumParts, RegisterVT); + Part += NumParts; + } + + // Copy the parts into the registers. + SmallVector Chains(NumRegs); + for (unsigned i = 0; i != NumRegs; ++i) { + SDValue Part; + if (Flag == 0) + Part = DAG.getCopyToReg(Chain, dl, Regs[i], Parts[i]); + else { + Part = DAG.getCopyToReg(Chain, dl, Regs[i], Parts[i], *Flag); + *Flag = Part.getValue(1); + } + Chains[i] = Part.getValue(0); + } + + if (NumRegs == 1 || Flag) + // If NumRegs > 1 && Flag is used then the use of the last CopyToReg is + // flagged to it. That is the CopyToReg nodes and the user are considered + // a single scheduling unit. If we create a TokenFactor and return it as + // chain, then the TokenFactor is both a predecessor (operand) of the + // user as well as a successor (the TF operands are flagged to the user). + // c1, f1 = CopyToReg + // c2, f2 = CopyToReg + // c3 = TokenFactor c1, c2 + // ... + // = op c3, ..., f2 + Chain = Chains[NumRegs-1]; + else + Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, &Chains[0], NumRegs); +} + +/// AddInlineAsmOperands - Add this value to the specified inlineasm node +/// operand list. This adds the code marker and includes the number of +/// values added into it. +void RegsForValue::AddInlineAsmOperands(unsigned Code, + bool HasMatching,unsigned MatchingIdx, + SelectionDAG &DAG, + std::vector &Ops) const { + EVT IntPtrTy = DAG.getTargetLoweringInfo().getPointerTy(); + assert(Regs.size() < (1 << 13) && "Too many inline asm outputs!"); + unsigned Flag = Code | (Regs.size() << 3); + if (HasMatching) + Flag |= 0x80000000 | (MatchingIdx << 16); + Ops.push_back(DAG.getTargetConstant(Flag, IntPtrTy)); + for (unsigned Value = 0, Reg = 0, e = ValueVTs.size(); Value != e; ++Value) { + unsigned NumRegs = TLI->getNumRegisters(*DAG.getContext(), ValueVTs[Value]); + EVT RegisterVT = RegVTs[Value]; + for (unsigned i = 0; i != NumRegs; ++i) { + assert(Reg < Regs.size() && "Mismatch in # registers expected"); + Ops.push_back(DAG.getRegister(Regs[Reg++], RegisterVT)); + } + } +} + +/// isAllocatableRegister - If the specified register is safe to allocate, +/// i.e. it isn't a stack pointer or some other special register, return the +/// register class for the register. Otherwise, return null. +static const TargetRegisterClass * +isAllocatableRegister(unsigned Reg, MachineFunction &MF, + const TargetLowering &TLI, + const TargetRegisterInfo *TRI) { + EVT FoundVT = MVT::Other; + const TargetRegisterClass *FoundRC = 0; + for (TargetRegisterInfo::regclass_iterator RCI = TRI->regclass_begin(), + E = TRI->regclass_end(); RCI != E; ++RCI) { + EVT ThisVT = MVT::Other; + + const TargetRegisterClass *RC = *RCI; + // If none of the the value types for this register class are valid, we + // can't use it. For example, 64-bit reg classes on 32-bit targets. + for (TargetRegisterClass::vt_iterator I = RC->vt_begin(), E = RC->vt_end(); + I != E; ++I) { + if (TLI.isTypeLegal(*I)) { + // If we have already found this register in a different register class, + // choose the one with the largest VT specified. For example, on + // PowerPC, we favor f64 register classes over f32. + if (FoundVT == MVT::Other || FoundVT.bitsLT(*I)) { + ThisVT = *I; + break; + } + } + } + + if (ThisVT == MVT::Other) continue; + + // NOTE: This isn't ideal. In particular, this might allocate the + // frame pointer in functions that need it (due to them not being taken + // out of allocation, because a variable sized allocation hasn't been seen + // yet). This is a slight code pessimization, but should still work. + for (TargetRegisterClass::iterator I = RC->allocation_order_begin(MF), + E = RC->allocation_order_end(MF); I != E; ++I) + if (*I == Reg) { + // We found a matching register class. Keep looking at others in case + // we find one with larger registers that this physreg is also in. + FoundRC = RC; + FoundVT = ThisVT; + break; + } + } + return FoundRC; +} + + +namespace llvm { +/// AsmOperandInfo - This contains information for each constraint that we are +/// lowering. +class VISIBILITY_HIDDEN SDISelAsmOperandInfo : + public TargetLowering::AsmOperandInfo { +public: + /// CallOperand - If this is the result output operand or a clobber + /// this is null, otherwise it is the incoming operand to the CallInst. + /// This gets modified as the asm is processed. + SDValue CallOperand; + + /// AssignedRegs - If this is a register or register class operand, this + /// contains the set of register corresponding to the operand. + RegsForValue AssignedRegs; + + explicit SDISelAsmOperandInfo(const InlineAsm::ConstraintInfo &info) + : TargetLowering::AsmOperandInfo(info), CallOperand(0,0) { + } + + /// MarkAllocatedRegs - Once AssignedRegs is set, mark the assigned registers + /// busy in OutputRegs/InputRegs. + void MarkAllocatedRegs(bool isOutReg, bool isInReg, + std::set &OutputRegs, + std::set &InputRegs, + const TargetRegisterInfo &TRI) const { + if (isOutReg) { + for (unsigned i = 0, e = AssignedRegs.Regs.size(); i != e; ++i) + MarkRegAndAliases(AssignedRegs.Regs[i], OutputRegs, TRI); + } + if (isInReg) { + for (unsigned i = 0, e = AssignedRegs.Regs.size(); i != e; ++i) + MarkRegAndAliases(AssignedRegs.Regs[i], InputRegs, TRI); + } + } + + /// getCallOperandValEVT - Return the EVT of the Value* that this operand + /// corresponds to. If there is no Value* for this operand, it returns + /// MVT::Other. + EVT getCallOperandValEVT(LLVMContext &Context, + const TargetLowering &TLI, + const TargetData *TD) const { + if (CallOperandVal == 0) return MVT::Other; + + if (isa(CallOperandVal)) + return TLI.getPointerTy(); + + const llvm::Type *OpTy = CallOperandVal->getType(); + + // If this is an indirect operand, the operand is a pointer to the + // accessed type. + if (isIndirect) + OpTy = cast(OpTy)->getElementType(); + + // If OpTy is not a single value, it may be a struct/union that we + // can tile with integers. + if (!OpTy->isSingleValueType() && OpTy->isSized()) { + unsigned BitSize = TD->getTypeSizeInBits(OpTy); + switch (BitSize) { + default: break; + case 1: + case 8: + case 16: + case 32: + case 64: + case 128: + OpTy = IntegerType::get(Context, BitSize); + break; + } + } + + return TLI.getValueType(OpTy, true); + } + +private: + /// MarkRegAndAliases - Mark the specified register and all aliases in the + /// specified set. + static void MarkRegAndAliases(unsigned Reg, std::set &Regs, + const TargetRegisterInfo &TRI) { + assert(TargetRegisterInfo::isPhysicalRegister(Reg) && "Isn't a physreg"); + Regs.insert(Reg); + if (const unsigned *Aliases = TRI.getAliasSet(Reg)) + for (; *Aliases; ++Aliases) + Regs.insert(*Aliases); + } +}; +} // end llvm namespace. + + +/// GetRegistersForValue - Assign registers (virtual or physical) for the +/// specified operand. We prefer to assign virtual registers, to allow the +/// register allocator handle the assignment process. However, if the asm uses +/// features that we can't model on machineinstrs, we have SDISel do the +/// allocation. This produces generally horrible, but correct, code. +/// +/// OpInfo describes the operand. +/// Input and OutputRegs are the set of already allocated physical registers. +/// +void SelectionDAGBuilder:: +GetRegistersForValue(SDISelAsmOperandInfo &OpInfo, + std::set &OutputRegs, + std::set &InputRegs) { + LLVMContext &Context = FuncInfo.Fn->getContext(); + + // Compute whether this value requires an input register, an output register, + // or both. + bool isOutReg = false; + bool isInReg = false; + switch (OpInfo.Type) { + case InlineAsm::isOutput: + isOutReg = true; + + // If there is an input constraint that matches this, we need to reserve + // the input register so no other inputs allocate to it. + isInReg = OpInfo.hasMatchingInput(); + break; + case InlineAsm::isInput: + isInReg = true; + isOutReg = false; + break; + case InlineAsm::isClobber: + isOutReg = true; + isInReg = true; + break; + } + + + MachineFunction &MF = DAG.getMachineFunction(); + SmallVector Regs; + + // If this is a constraint for a single physreg, or a constraint for a + // register class, find it. + std::pair PhysReg = + TLI.getRegForInlineAsmConstraint(OpInfo.ConstraintCode, + OpInfo.ConstraintVT); + + unsigned NumRegs = 1; + if (OpInfo.ConstraintVT != MVT::Other) { + // If this is a FP input in an integer register (or visa versa) insert a bit + // cast of the input value. More generally, handle any case where the input + // value disagrees with the register class we plan to stick this in. + if (OpInfo.Type == InlineAsm::isInput && + PhysReg.second && !PhysReg.second->hasType(OpInfo.ConstraintVT)) { + // Try to convert to the first EVT that the reg class contains. If the + // types are identical size, use a bitcast to convert (e.g. two differing + // vector types). + EVT RegVT = *PhysReg.second->vt_begin(); + if (RegVT.getSizeInBits() == OpInfo.ConstraintVT.getSizeInBits()) { + OpInfo.CallOperand = DAG.getNode(ISD::BIT_CONVERT, getCurDebugLoc(), + RegVT, OpInfo.CallOperand); + OpInfo.ConstraintVT = RegVT; + } else if (RegVT.isInteger() && OpInfo.ConstraintVT.isFloatingPoint()) { + // If the input is a FP value and we want it in FP registers, do a + // bitcast to the corresponding integer type. This turns an f64 value + // into i64, which can be passed with two i32 values on a 32-bit + // machine. + RegVT = EVT::getIntegerVT(Context, + OpInfo.ConstraintVT.getSizeInBits()); + OpInfo.CallOperand = DAG.getNode(ISD::BIT_CONVERT, getCurDebugLoc(), + RegVT, OpInfo.CallOperand); + OpInfo.ConstraintVT = RegVT; + } + } + + NumRegs = TLI.getNumRegisters(Context, OpInfo.ConstraintVT); + } + + EVT RegVT; + EVT ValueVT = OpInfo.ConstraintVT; + + // If this is a constraint for a specific physical register, like {r17}, + // assign it now. + if (unsigned AssignedReg = PhysReg.first) { + const TargetRegisterClass *RC = PhysReg.second; + if (OpInfo.ConstraintVT == MVT::Other) + ValueVT = *RC->vt_begin(); + + // Get the actual register value type. This is important, because the user + // may have asked for (e.g.) the AX register in i32 type. We need to + // remember that AX is actually i16 to get the right extension. + RegVT = *RC->vt_begin(); + + // This is a explicit reference to a physical register. + Regs.push_back(AssignedReg); + + // If this is an expanded reference, add the rest of the regs to Regs. + if (NumRegs != 1) { + TargetRegisterClass::iterator I = RC->begin(); + for (; *I != AssignedReg; ++I) + assert(I != RC->end() && "Didn't find reg!"); + + // Already added the first reg. + --NumRegs; ++I; + for (; NumRegs; --NumRegs, ++I) { + assert(I != RC->end() && "Ran out of registers to allocate!"); + Regs.push_back(*I); + } + } + OpInfo.AssignedRegs = RegsForValue(TLI, Regs, RegVT, ValueVT); + const TargetRegisterInfo *TRI = DAG.getTarget().getRegisterInfo(); + OpInfo.MarkAllocatedRegs(isOutReg, isInReg, OutputRegs, InputRegs, *TRI); + return; + } + + // Otherwise, if this was a reference to an LLVM register class, create vregs + // for this reference. + if (const TargetRegisterClass *RC = PhysReg.second) { + RegVT = *RC->vt_begin(); + if (OpInfo.ConstraintVT == MVT::Other) + ValueVT = RegVT; + + // Create the appropriate number of virtual registers. + MachineRegisterInfo &RegInfo = MF.getRegInfo(); + for (; NumRegs; --NumRegs) + Regs.push_back(RegInfo.createVirtualRegister(RC)); + + OpInfo.AssignedRegs = RegsForValue(TLI, Regs, RegVT, ValueVT); + return; + } + + // This is a reference to a register class that doesn't directly correspond + // to an LLVM register class. Allocate NumRegs consecutive, available, + // registers from the class. + std::vector RegClassRegs + = TLI.getRegClassForInlineAsmConstraint(OpInfo.ConstraintCode, + OpInfo.ConstraintVT); + + const TargetRegisterInfo *TRI = DAG.getTarget().getRegisterInfo(); + unsigned NumAllocated = 0; + for (unsigned i = 0, e = RegClassRegs.size(); i != e; ++i) { + unsigned Reg = RegClassRegs[i]; + // See if this register is available. + if ((isOutReg && OutputRegs.count(Reg)) || // Already used. + (isInReg && InputRegs.count(Reg))) { // Already used. + // Make sure we find consecutive registers. + NumAllocated = 0; + continue; + } + + // Check to see if this register is allocatable (i.e. don't give out the + // stack pointer). + const TargetRegisterClass *RC = isAllocatableRegister(Reg, MF, TLI, TRI); + if (!RC) { // Couldn't allocate this register. + // Reset NumAllocated to make sure we return consecutive registers. + NumAllocated = 0; + continue; + } + + // Okay, this register is good, we can use it. + ++NumAllocated; + + // If we allocated enough consecutive registers, succeed. + if (NumAllocated == NumRegs) { + unsigned RegStart = (i-NumAllocated)+1; + unsigned RegEnd = i+1; + // Mark all of the allocated registers used. + for (unsigned i = RegStart; i != RegEnd; ++i) + Regs.push_back(RegClassRegs[i]); + + OpInfo.AssignedRegs = RegsForValue(TLI, Regs, *RC->vt_begin(), + OpInfo.ConstraintVT); + OpInfo.MarkAllocatedRegs(isOutReg, isInReg, OutputRegs, InputRegs, *TRI); + return; + } + } + + // Otherwise, we couldn't allocate enough registers for this. +} + +/// hasInlineAsmMemConstraint - Return true if the inline asm instruction being +/// processed uses a memory 'm' constraint. +static bool +hasInlineAsmMemConstraint(std::vector &CInfos, + const TargetLowering &TLI) { + for (unsigned i = 0, e = CInfos.size(); i != e; ++i) { + InlineAsm::ConstraintInfo &CI = CInfos[i]; + for (unsigned j = 0, ee = CI.Codes.size(); j != ee; ++j) { + TargetLowering::ConstraintType CType = TLI.getConstraintType(CI.Codes[j]); + if (CType == TargetLowering::C_Memory) + return true; + } + + // Indirect operand accesses access memory. + if (CI.isIndirect) + return true; + } + + return false; +} + +/// visitInlineAsm - Handle a call to an InlineAsm object. +/// +void SelectionDAGBuilder::visitInlineAsm(CallSite CS) { + InlineAsm *IA = cast(CS.getCalledValue()); + + /// ConstraintOperands - Information about all of the constraints. + std::vector ConstraintOperands; + + std::set OutputRegs, InputRegs; + + // Do a prepass over the constraints, canonicalizing them, and building up the + // ConstraintOperands list. + std::vector + ConstraintInfos = IA->ParseConstraints(); + + bool hasMemory = hasInlineAsmMemConstraint(ConstraintInfos, TLI); + + SDValue Chain, Flag; + + // We won't need to flush pending loads if this asm doesn't touch + // memory and is nonvolatile. + if (hasMemory || IA->hasSideEffects()) + Chain = getRoot(); + else + Chain = DAG.getRoot(); + + unsigned ArgNo = 0; // ArgNo - The argument of the CallInst. + unsigned ResNo = 0; // ResNo - The result number of the next output. + for (unsigned i = 0, e = ConstraintInfos.size(); i != e; ++i) { + ConstraintOperands.push_back(SDISelAsmOperandInfo(ConstraintInfos[i])); + SDISelAsmOperandInfo &OpInfo = ConstraintOperands.back(); + + EVT OpVT = MVT::Other; + + // Compute the value type for each operand. + switch (OpInfo.Type) { + case InlineAsm::isOutput: + // Indirect outputs just consume an argument. + if (OpInfo.isIndirect) { + OpInfo.CallOperandVal = CS.getArgument(ArgNo++); + break; + } + + // The return value of the call is this value. As such, there is no + // corresponding argument. + assert(CS.getType() != Type::getVoidTy(*DAG.getContext()) && + "Bad inline asm!"); + if (const StructType *STy = dyn_cast(CS.getType())) { + OpVT = TLI.getValueType(STy->getElementType(ResNo)); + } else { + assert(ResNo == 0 && "Asm only has one result!"); + OpVT = TLI.getValueType(CS.getType()); + } + ++ResNo; + break; + case InlineAsm::isInput: + OpInfo.CallOperandVal = CS.getArgument(ArgNo++); + break; + case InlineAsm::isClobber: + // Nothing to do. + break; + } + + // If this is an input or an indirect output, process the call argument. + // BasicBlocks are labels, currently appearing only in asm's. + if (OpInfo.CallOperandVal) { + // Strip bitcasts, if any. This mostly comes up for functions. + OpInfo.CallOperandVal = OpInfo.CallOperandVal->stripPointerCasts(); + + if (BasicBlock *BB = dyn_cast(OpInfo.CallOperandVal)) { + OpInfo.CallOperand = DAG.getBasicBlock(FuncInfo.MBBMap[BB]); + } else { + OpInfo.CallOperand = getValue(OpInfo.CallOperandVal); + } + + OpVT = OpInfo.getCallOperandValEVT(*DAG.getContext(), TLI, TD); + } + + OpInfo.ConstraintVT = OpVT; + } + + // Second pass over the constraints: compute which constraint option to use + // and assign registers to constraints that want a specific physreg. + for (unsigned i = 0, e = ConstraintInfos.size(); i != e; ++i) { + SDISelAsmOperandInfo &OpInfo = ConstraintOperands[i]; + + // If this is an output operand with a matching input operand, look up the + // matching input. If their types mismatch, e.g. one is an integer, the + // other is floating point, or their sizes are different, flag it as an + // error. + if (OpInfo.hasMatchingInput()) { + SDISelAsmOperandInfo &Input = ConstraintOperands[OpInfo.MatchingInput]; + if (OpInfo.ConstraintVT != Input.ConstraintVT) { + if ((OpInfo.ConstraintVT.isInteger() != + Input.ConstraintVT.isInteger()) || + (OpInfo.ConstraintVT.getSizeInBits() != + Input.ConstraintVT.getSizeInBits())) { + llvm_report_error("Unsupported asm: input constraint" + " with a matching output constraint of incompatible" + " type!"); + } + Input.ConstraintVT = OpInfo.ConstraintVT; + } + } + + // Compute the constraint code and ConstraintType to use. + TLI.ComputeConstraintToUse(OpInfo, OpInfo.CallOperand, hasMemory, &DAG); + + // If this is a memory input, and if the operand is not indirect, do what we + // need to to provide an address for the memory input. + if (OpInfo.ConstraintType == TargetLowering::C_Memory && + !OpInfo.isIndirect) { + assert(OpInfo.Type == InlineAsm::isInput && + "Can only indirectify direct input operands!"); + + // Memory operands really want the address of the value. If we don't have + // an indirect input, put it in the constpool if we can, otherwise spill + // it to a stack slot. + + // If the operand is a float, integer, or vector constant, spill to a + // constant pool entry to get its address. + Value *OpVal = OpInfo.CallOperandVal; + if (isa(OpVal) || isa(OpVal) || + isa(OpVal)) { + OpInfo.CallOperand = DAG.getConstantPool(cast(OpVal), + TLI.getPointerTy()); + } else { + // Otherwise, create a stack slot and emit a store to it before the + // asm. + const Type *Ty = OpVal->getType(); + uint64_t TySize = TLI.getTargetData()->getTypeAllocSize(Ty); + unsigned Align = TLI.getTargetData()->getPrefTypeAlignment(Ty); + MachineFunction &MF = DAG.getMachineFunction(); + int SSFI = MF.getFrameInfo()->CreateStackObject(TySize, Align, false); + SDValue StackSlot = DAG.getFrameIndex(SSFI, TLI.getPointerTy()); + Chain = DAG.getStore(Chain, getCurDebugLoc(), + OpInfo.CallOperand, StackSlot, NULL, 0); + OpInfo.CallOperand = StackSlot; + } + + // There is no longer a Value* corresponding to this operand. + OpInfo.CallOperandVal = 0; + // It is now an indirect operand. + OpInfo.isIndirect = true; + } + + // If this constraint is for a specific register, allocate it before + // anything else. + if (OpInfo.ConstraintType == TargetLowering::C_Register) + GetRegistersForValue(OpInfo, OutputRegs, InputRegs); + } + ConstraintInfos.clear(); + + + // Second pass - Loop over all of the operands, assigning virtual or physregs + // to register class operands. + for (unsigned i = 0, e = ConstraintOperands.size(); i != e; ++i) { + SDISelAsmOperandInfo &OpInfo = ConstraintOperands[i]; + + // C_Register operands have already been allocated, Other/Memory don't need + // to be. + if (OpInfo.ConstraintType == TargetLowering::C_RegisterClass) + GetRegistersForValue(OpInfo, OutputRegs, InputRegs); + } + + // AsmNodeOperands - The operands for the ISD::INLINEASM node. + std::vector AsmNodeOperands; + AsmNodeOperands.push_back(SDValue()); // reserve space for input chain + AsmNodeOperands.push_back( + DAG.getTargetExternalSymbol(IA->getAsmString().c_str(), MVT::Other)); + + + // Loop over all of the inputs, copying the operand values into the + // appropriate registers and processing the output regs. + RegsForValue RetValRegs; + + // IndirectStoresToEmit - The set of stores to emit after the inline asm node. + std::vector > IndirectStoresToEmit; + + for (unsigned i = 0, e = ConstraintOperands.size(); i != e; ++i) { + SDISelAsmOperandInfo &OpInfo = ConstraintOperands[i]; + + switch (OpInfo.Type) { + case InlineAsm::isOutput: { + if (OpInfo.ConstraintType != TargetLowering::C_RegisterClass && + OpInfo.ConstraintType != TargetLowering::C_Register) { + // Memory output, or 'other' output (e.g. 'X' constraint). + assert(OpInfo.isIndirect && "Memory output must be indirect operand"); + + // Add information to the INLINEASM node to know about this output. + unsigned ResOpType = 4/*MEM*/ | (1<<3); + AsmNodeOperands.push_back(DAG.getTargetConstant(ResOpType, + TLI.getPointerTy())); + AsmNodeOperands.push_back(OpInfo.CallOperand); + break; + } + + // Otherwise, this is a register or register class output. + + // Copy the output from the appropriate register. Find a register that + // we can use. + if (OpInfo.AssignedRegs.Regs.empty()) { + llvm_report_error("Couldn't allocate output reg for" + " constraint '" + OpInfo.ConstraintCode + "'!"); + } + + // If this is an indirect operand, store through the pointer after the + // asm. + if (OpInfo.isIndirect) { + IndirectStoresToEmit.push_back(std::make_pair(OpInfo.AssignedRegs, + OpInfo.CallOperandVal)); + } else { + // This is the result value of the call. + assert(CS.getType() != Type::getVoidTy(*DAG.getContext()) && + "Bad inline asm!"); + // Concatenate this output onto the outputs list. + RetValRegs.append(OpInfo.AssignedRegs); + } + + // Add information to the INLINEASM node to know that this register is + // set. + OpInfo.AssignedRegs.AddInlineAsmOperands(OpInfo.isEarlyClobber ? + 6 /* EARLYCLOBBER REGDEF */ : + 2 /* REGDEF */ , + false, + 0, + DAG, AsmNodeOperands); + break; + } + case InlineAsm::isInput: { + SDValue InOperandVal = OpInfo.CallOperand; + + if (OpInfo.isMatchingInputConstraint()) { // Matching constraint? + // If this is required to match an output register we have already set, + // just use its register. + unsigned OperandNo = OpInfo.getMatchedOperand(); + + // Scan until we find the definition we already emitted of this operand. + // When we find it, create a RegsForValue operand. + unsigned CurOp = 2; // The first operand. + for (; OperandNo; --OperandNo) { + // Advance to the next operand. + unsigned OpFlag = + cast(AsmNodeOperands[CurOp])->getZExtValue(); + assert(((OpFlag & 7) == 2 /*REGDEF*/ || + (OpFlag & 7) == 6 /*EARLYCLOBBER REGDEF*/ || + (OpFlag & 7) == 4 /*MEM*/) && + "Skipped past definitions?"); + CurOp += InlineAsm::getNumOperandRegisters(OpFlag)+1; + } + + unsigned OpFlag = + cast(AsmNodeOperands[CurOp])->getZExtValue(); + if ((OpFlag & 7) == 2 /*REGDEF*/ + || (OpFlag & 7) == 6 /* EARLYCLOBBER REGDEF */) { + // Add (OpFlag&0xffff)>>3 registers to MatchedRegs. + if (OpInfo.isIndirect) { + llvm_report_error("Don't know how to handle tied indirect " + "register inputs yet!"); + } + RegsForValue MatchedRegs; + MatchedRegs.TLI = &TLI; + MatchedRegs.ValueVTs.push_back(InOperandVal.getValueType()); + EVT RegVT = AsmNodeOperands[CurOp+1].getValueType(); + MatchedRegs.RegVTs.push_back(RegVT); + MachineRegisterInfo &RegInfo = DAG.getMachineFunction().getRegInfo(); + for (unsigned i = 0, e = InlineAsm::getNumOperandRegisters(OpFlag); + i != e; ++i) + MatchedRegs.Regs. + push_back(RegInfo.createVirtualRegister(TLI.getRegClassFor(RegVT))); + + // Use the produced MatchedRegs object to + MatchedRegs.getCopyToRegs(InOperandVal, DAG, getCurDebugLoc(), + Chain, &Flag); + MatchedRegs.AddInlineAsmOperands(1 /*REGUSE*/, + true, OpInfo.getMatchedOperand(), + DAG, AsmNodeOperands); + break; + } else { + assert(((OpFlag & 7) == 4) && "Unknown matching constraint!"); + assert((InlineAsm::getNumOperandRegisters(OpFlag)) == 1 && + "Unexpected number of operands"); + // Add information to the INLINEASM node to know about this input. + // See InlineAsm.h isUseOperandTiedToDef. + OpFlag |= 0x80000000 | (OpInfo.getMatchedOperand() << 16); + AsmNodeOperands.push_back(DAG.getTargetConstant(OpFlag, + TLI.getPointerTy())); + AsmNodeOperands.push_back(AsmNodeOperands[CurOp+1]); + break; + } + } + + if (OpInfo.ConstraintType == TargetLowering::C_Other) { + assert(!OpInfo.isIndirect && + "Don't know how to handle indirect other inputs yet!"); + + std::vector Ops; + TLI.LowerAsmOperandForConstraint(InOperandVal, OpInfo.ConstraintCode[0], + hasMemory, Ops, DAG); + if (Ops.empty()) { + llvm_report_error("Invalid operand for inline asm" + " constraint '" + OpInfo.ConstraintCode + "'!"); + } + + // Add information to the INLINEASM node to know about this input. + unsigned ResOpType = 3 /*IMM*/ | (Ops.size() << 3); + AsmNodeOperands.push_back(DAG.getTargetConstant(ResOpType, + TLI.getPointerTy())); + AsmNodeOperands.insert(AsmNodeOperands.end(), Ops.begin(), Ops.end()); + break; + } else if (OpInfo.ConstraintType == TargetLowering::C_Memory) { + assert(OpInfo.isIndirect && "Operand must be indirect to be a mem!"); + assert(InOperandVal.getValueType() == TLI.getPointerTy() && + "Memory operands expect pointer values"); + + // Add information to the INLINEASM node to know about this input. + unsigned ResOpType = 4/*MEM*/ | (1<<3); + AsmNodeOperands.push_back(DAG.getTargetConstant(ResOpType, + TLI.getPointerTy())); + AsmNodeOperands.push_back(InOperandVal); + break; + } + + assert((OpInfo.ConstraintType == TargetLowering::C_RegisterClass || + OpInfo.ConstraintType == TargetLowering::C_Register) && + "Unknown constraint type!"); + assert(!OpInfo.isIndirect && + "Don't know how to handle indirect register inputs yet!"); + + // Copy the input into the appropriate registers. + if (OpInfo.AssignedRegs.Regs.empty()) { + llvm_report_error("Couldn't allocate input reg for" + " constraint '"+ OpInfo.ConstraintCode +"'!"); + } + + OpInfo.AssignedRegs.getCopyToRegs(InOperandVal, DAG, getCurDebugLoc(), + Chain, &Flag); + + OpInfo.AssignedRegs.AddInlineAsmOperands(1/*REGUSE*/, false, 0, + DAG, AsmNodeOperands); + break; + } + case InlineAsm::isClobber: { + // Add the clobbered value to the operand list, so that the register + // allocator is aware that the physreg got clobbered. + if (!OpInfo.AssignedRegs.Regs.empty()) + OpInfo.AssignedRegs.AddInlineAsmOperands(6 /* EARLYCLOBBER REGDEF */, + false, 0, DAG,AsmNodeOperands); + break; + } + } + } + + // Finish up input operands. + AsmNodeOperands[0] = Chain; + if (Flag.getNode()) AsmNodeOperands.push_back(Flag); + + Chain = DAG.getNode(ISD::INLINEASM, getCurDebugLoc(), + DAG.getVTList(MVT::Other, MVT::Flag), + &AsmNodeOperands[0], AsmNodeOperands.size()); + Flag = Chain.getValue(1); + + // If this asm returns a register value, copy the result from that register + // and set it as the value of the call. + if (!RetValRegs.Regs.empty()) { + SDValue Val = RetValRegs.getCopyFromRegs(DAG, getCurDebugLoc(), + Chain, &Flag); + + // FIXME: Why don't we do this for inline asms with MRVs? + if (CS.getType()->isSingleValueType() && CS.getType()->isSized()) { + EVT ResultType = TLI.getValueType(CS.getType()); + + // If any of the results of the inline asm is a vector, it may have the + // wrong width/num elts. This can happen for register classes that can + // contain multiple different value types. The preg or vreg allocated may + // not have the same VT as was expected. Convert it to the right type + // with bit_convert. + if (ResultType != Val.getValueType() && Val.getValueType().isVector()) { + Val = DAG.getNode(ISD::BIT_CONVERT, getCurDebugLoc(), + ResultType, Val); + + } else if (ResultType != Val.getValueType() && + ResultType.isInteger() && Val.getValueType().isInteger()) { + // If a result value was tied to an input value, the computed result may + // have a wider width than the expected result. Extract the relevant + // portion. + Val = DAG.getNode(ISD::TRUNCATE, getCurDebugLoc(), ResultType, Val); + } + + assert(ResultType == Val.getValueType() && "Asm result value mismatch!"); + } + + setValue(CS.getInstruction(), Val); + // Don't need to use this as a chain in this case. + if (!IA->hasSideEffects() && !hasMemory && IndirectStoresToEmit.empty()) + return; + } + + std::vector > StoresToEmit; + + // Process indirect outputs, first output all of the flagged copies out of + // physregs. + for (unsigned i = 0, e = IndirectStoresToEmit.size(); i != e; ++i) { + RegsForValue &OutRegs = IndirectStoresToEmit[i].first; + Value *Ptr = IndirectStoresToEmit[i].second; + SDValue OutVal = OutRegs.getCopyFromRegs(DAG, getCurDebugLoc(), + Chain, &Flag); + StoresToEmit.push_back(std::make_pair(OutVal, Ptr)); + + } + + // Emit the non-flagged stores from the physregs. + SmallVector OutChains; + for (unsigned i = 0, e = StoresToEmit.size(); i != e; ++i) + OutChains.push_back(DAG.getStore(Chain, getCurDebugLoc(), + StoresToEmit[i].first, + getValue(StoresToEmit[i].second), + StoresToEmit[i].second, 0)); + if (!OutChains.empty()) + Chain = DAG.getNode(ISD::TokenFactor, getCurDebugLoc(), MVT::Other, + &OutChains[0], OutChains.size()); + DAG.setRoot(Chain); +} + +void SelectionDAGBuilder::visitVAStart(CallInst &I) { + DAG.setRoot(DAG.getNode(ISD::VASTART, getCurDebugLoc(), + MVT::Other, getRoot(), + getValue(I.getOperand(1)), + DAG.getSrcValue(I.getOperand(1)))); +} + +void SelectionDAGBuilder::visitVAArg(VAArgInst &I) { + SDValue V = DAG.getVAArg(TLI.getValueType(I.getType()), getCurDebugLoc(), + getRoot(), getValue(I.getOperand(0)), + DAG.getSrcValue(I.getOperand(0))); + setValue(&I, V); + DAG.setRoot(V.getValue(1)); +} + +void SelectionDAGBuilder::visitVAEnd(CallInst &I) { + DAG.setRoot(DAG.getNode(ISD::VAEND, getCurDebugLoc(), + MVT::Other, getRoot(), + getValue(I.getOperand(1)), + DAG.getSrcValue(I.getOperand(1)))); +} + +void SelectionDAGBuilder::visitVACopy(CallInst &I) { + DAG.setRoot(DAG.getNode(ISD::VACOPY, getCurDebugLoc(), + MVT::Other, getRoot(), + getValue(I.getOperand(1)), + getValue(I.getOperand(2)), + DAG.getSrcValue(I.getOperand(1)), + DAG.getSrcValue(I.getOperand(2)))); +} + +/// TargetLowering::LowerCallTo - This is the default LowerCallTo +/// implementation, which just calls LowerCall. +/// FIXME: When all targets are +/// migrated to using LowerCall, this hook should be integrated into SDISel. +std::pair +TargetLowering::LowerCallTo(SDValue Chain, const Type *RetTy, + bool RetSExt, bool RetZExt, bool isVarArg, + bool isInreg, unsigned NumFixedArgs, + CallingConv::ID CallConv, bool isTailCall, + bool isReturnValueUsed, + SDValue Callee, + ArgListTy &Args, SelectionDAG &DAG, DebugLoc dl) { + + assert((!isTailCall || PerformTailCallOpt) && + "isTailCall set when tail-call optimizations are disabled!"); + + // Handle all of the outgoing arguments. + SmallVector Outs; + for (unsigned i = 0, e = Args.size(); i != e; ++i) { + SmallVector ValueVTs; + ComputeValueVTs(*this, Args[i].Ty, ValueVTs); + for (unsigned Value = 0, NumValues = ValueVTs.size(); + Value != NumValues; ++Value) { + EVT VT = ValueVTs[Value]; + const Type *ArgTy = VT.getTypeForEVT(RetTy->getContext()); + SDValue Op = SDValue(Args[i].Node.getNode(), + Args[i].Node.getResNo() + Value); + ISD::ArgFlagsTy Flags; + unsigned OriginalAlignment = + getTargetData()->getABITypeAlignment(ArgTy); + + if (Args[i].isZExt) + Flags.setZExt(); + if (Args[i].isSExt) + Flags.setSExt(); + if (Args[i].isInReg) + Flags.setInReg(); + if (Args[i].isSRet) + Flags.setSRet(); + if (Args[i].isByVal) { + Flags.setByVal(); + const PointerType *Ty = cast(Args[i].Ty); + const Type *ElementTy = Ty->getElementType(); + unsigned FrameAlign = getByValTypeAlignment(ElementTy); + unsigned FrameSize = getTargetData()->getTypeAllocSize(ElementTy); + // For ByVal, alignment should come from FE. BE will guess if this + // info is not there but there are cases it cannot get right. + if (Args[i].Alignment) + FrameAlign = Args[i].Alignment; + Flags.setByValAlign(FrameAlign); + Flags.setByValSize(FrameSize); + } + if (Args[i].isNest) + Flags.setNest(); + Flags.setOrigAlign(OriginalAlignment); + + EVT PartVT = getRegisterType(RetTy->getContext(), VT); + unsigned NumParts = getNumRegisters(RetTy->getContext(), VT); + SmallVector Parts(NumParts); + ISD::NodeType ExtendKind = ISD::ANY_EXTEND; + + if (Args[i].isSExt) + ExtendKind = ISD::SIGN_EXTEND; + else if (Args[i].isZExt) + ExtendKind = ISD::ZERO_EXTEND; + + getCopyToParts(DAG, dl, Op, &Parts[0], NumParts, PartVT, ExtendKind); + + for (unsigned j = 0; j != NumParts; ++j) { + // if it isn't first piece, alignment must be 1 + ISD::OutputArg MyFlags(Flags, Parts[j], i < NumFixedArgs); + if (NumParts > 1 && j == 0) + MyFlags.Flags.setSplit(); + else if (j != 0) + MyFlags.Flags.setOrigAlign(1); + + Outs.push_back(MyFlags); + } + } + } + + // Handle the incoming return values from the call. + SmallVector Ins; + SmallVector RetTys; + ComputeValueVTs(*this, RetTy, RetTys); + for (unsigned I = 0, E = RetTys.size(); I != E; ++I) { + EVT VT = RetTys[I]; + EVT RegisterVT = getRegisterType(RetTy->getContext(), VT); + unsigned NumRegs = getNumRegisters(RetTy->getContext(), VT); + for (unsigned i = 0; i != NumRegs; ++i) { + ISD::InputArg MyFlags; + MyFlags.VT = RegisterVT; + MyFlags.Used = isReturnValueUsed; + if (RetSExt) + MyFlags.Flags.setSExt(); + if (RetZExt) + MyFlags.Flags.setZExt(); + if (isInreg) + MyFlags.Flags.setInReg(); + Ins.push_back(MyFlags); + } + } + + // Check if target-dependent constraints permit a tail call here. + // Target-independent constraints should be checked by the caller. + if (isTailCall && + !IsEligibleForTailCallOptimization(Callee, CallConv, isVarArg, Ins, DAG)) + isTailCall = false; + + SmallVector InVals; + Chain = LowerCall(Chain, Callee, CallConv, isVarArg, isTailCall, + Outs, Ins, dl, DAG, InVals); + + // Verify that the target's LowerCall behaved as expected. + assert(Chain.getNode() && Chain.getValueType() == MVT::Other && + "LowerCall didn't return a valid chain!"); + assert((!isTailCall || InVals.empty()) && + "LowerCall emitted a return value for a tail call!"); + assert((isTailCall || InVals.size() == Ins.size()) && + "LowerCall didn't emit the correct number of values!"); + DEBUG(for (unsigned i = 0, e = Ins.size(); i != e; ++i) { + assert(InVals[i].getNode() && + "LowerCall emitted a null value!"); + assert(Ins[i].VT == InVals[i].getValueType() && + "LowerCall emitted a value with the wrong type!"); + }); + + // For a tail call, the return value is merely live-out and there aren't + // any nodes in the DAG representing it. Return a special value to + // indicate that a tail call has been emitted and no more Instructions + // should be processed in the current block. + if (isTailCall) { + DAG.setRoot(Chain); + return std::make_pair(SDValue(), SDValue()); + } + + // Collect the legal value parts into potentially illegal values + // that correspond to the original function's return values. + ISD::NodeType AssertOp = ISD::DELETED_NODE; + if (RetSExt) + AssertOp = ISD::AssertSext; + else if (RetZExt) + AssertOp = ISD::AssertZext; + SmallVector ReturnValues; + unsigned CurReg = 0; + for (unsigned I = 0, E = RetTys.size(); I != E; ++I) { + EVT VT = RetTys[I]; + EVT RegisterVT = getRegisterType(RetTy->getContext(), VT); + unsigned NumRegs = getNumRegisters(RetTy->getContext(), VT); + + SDValue ReturnValue = + getCopyFromParts(DAG, dl, &InVals[CurReg], NumRegs, RegisterVT, VT, + AssertOp); + ReturnValues.push_back(ReturnValue); + CurReg += NumRegs; + } + + // For a function returning void, there is no return value. We can't create + // such a node, so we just return a null return value in that case. In + // that case, nothing will actualy look at the value. + if (ReturnValues.empty()) + return std::make_pair(SDValue(), Chain); + + SDValue Res = DAG.getNode(ISD::MERGE_VALUES, dl, + DAG.getVTList(&RetTys[0], RetTys.size()), + &ReturnValues[0], ReturnValues.size()); + + return std::make_pair(Res, Chain); +} + +void TargetLowering::LowerOperationWrapper(SDNode *N, + SmallVectorImpl &Results, + SelectionDAG &DAG) { + SDValue Res = LowerOperation(SDValue(N, 0), DAG); + if (Res.getNode()) + Results.push_back(Res); +} + +SDValue TargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) { + llvm_unreachable("LowerOperation not implemented for this target!"); + return SDValue(); +} + + +void SelectionDAGBuilder::CopyValueToVirtualRegister(Value *V, unsigned Reg) { + SDValue Op = getValue(V); + assert((Op.getOpcode() != ISD::CopyFromReg || + cast(Op.getOperand(1))->getReg() != Reg) && + "Copy from a reg to the same reg!"); + assert(!TargetRegisterInfo::isPhysicalRegister(Reg) && "Is a physreg"); + + RegsForValue RFV(V->getContext(), TLI, Reg, V->getType()); + SDValue Chain = DAG.getEntryNode(); + RFV.getCopyToRegs(Op, DAG, getCurDebugLoc(), Chain, 0); + PendingExports.push_back(Chain); +} + +#include "llvm/CodeGen/SelectionDAGISel.h" + +void SelectionDAGISel::LowerArguments(BasicBlock *LLVMBB) { + // If this is the entry block, emit arguments. + Function &F = *LLVMBB->getParent(); + SelectionDAG &DAG = SDB->DAG; + SDValue OldRoot = DAG.getRoot(); + DebugLoc dl = SDB->getCurDebugLoc(); + const TargetData *TD = TLI.getTargetData(); + SmallVector Ins; + + // Check whether the function can return without sret-demotion. + SmallVector OutVTs; + SmallVector OutsFlags; + getReturnInfo(F.getReturnType(), F.getAttributes().getRetAttributes(), + OutVTs, OutsFlags, TLI); + FunctionLoweringInfo &FLI = DAG.getFunctionLoweringInfo(); + + FLI.CanLowerReturn = TLI.CanLowerReturn(F.getCallingConv(), F.isVarArg(), + OutVTs, OutsFlags, DAG); + if (!FLI.CanLowerReturn) { + // Put in an sret pointer parameter before all the other parameters. + SmallVector ValueVTs; + ComputeValueVTs(TLI, PointerType::getUnqual(F.getReturnType()), ValueVTs); + + // NOTE: Assuming that a pointer will never break down to more than one VT + // or one register. + ISD::ArgFlagsTy Flags; + Flags.setSRet(); + EVT RegisterVT = TLI.getRegisterType(*CurDAG->getContext(), ValueVTs[0]); + ISD::InputArg RetArg(Flags, RegisterVT, true); + Ins.push_back(RetArg); + } + + // Set up the incoming argument description vector. + unsigned Idx = 1; + for (Function::arg_iterator I = F.arg_begin(), E = F.arg_end(); + I != E; ++I, ++Idx) { + SmallVector ValueVTs; + ComputeValueVTs(TLI, I->getType(), ValueVTs); + bool isArgValueUsed = !I->use_empty(); + for (unsigned Value = 0, NumValues = ValueVTs.size(); + Value != NumValues; ++Value) { + EVT VT = ValueVTs[Value]; + const Type *ArgTy = VT.getTypeForEVT(*DAG.getContext()); + ISD::ArgFlagsTy Flags; + unsigned OriginalAlignment = + TD->getABITypeAlignment(ArgTy); + + if (F.paramHasAttr(Idx, Attribute::ZExt)) + Flags.setZExt(); + if (F.paramHasAttr(Idx, Attribute::SExt)) + Flags.setSExt(); + if (F.paramHasAttr(Idx, Attribute::InReg)) + Flags.setInReg(); + if (F.paramHasAttr(Idx, Attribute::StructRet)) + Flags.setSRet(); + if (F.paramHasAttr(Idx, Attribute::ByVal)) { + Flags.setByVal(); + const PointerType *Ty = cast(I->getType()); + const Type *ElementTy = Ty->getElementType(); + unsigned FrameAlign = TLI.getByValTypeAlignment(ElementTy); + unsigned FrameSize = TD->getTypeAllocSize(ElementTy); + // For ByVal, alignment should be passed from FE. BE will guess if + // this info is not there but there are cases it cannot get right. + if (F.getParamAlignment(Idx)) + FrameAlign = F.getParamAlignment(Idx); + Flags.setByValAlign(FrameAlign); + Flags.setByValSize(FrameSize); + } + if (F.paramHasAttr(Idx, Attribute::Nest)) + Flags.setNest(); + Flags.setOrigAlign(OriginalAlignment); + + EVT RegisterVT = TLI.getRegisterType(*CurDAG->getContext(), VT); + unsigned NumRegs = TLI.getNumRegisters(*CurDAG->getContext(), VT); + for (unsigned i = 0; i != NumRegs; ++i) { + ISD::InputArg MyFlags(Flags, RegisterVT, isArgValueUsed); + if (NumRegs > 1 && i == 0) + MyFlags.Flags.setSplit(); + // if it isn't first piece, alignment must be 1 + else if (i > 0) + MyFlags.Flags.setOrigAlign(1); + Ins.push_back(MyFlags); + } + } + } + + // Call the target to set up the argument values. + SmallVector InVals; + SDValue NewRoot = TLI.LowerFormalArguments(DAG.getRoot(), F.getCallingConv(), + F.isVarArg(), Ins, + dl, DAG, InVals); + + // Verify that the target's LowerFormalArguments behaved as expected. + assert(NewRoot.getNode() && NewRoot.getValueType() == MVT::Other && + "LowerFormalArguments didn't return a valid chain!"); + assert(InVals.size() == Ins.size() && + "LowerFormalArguments didn't emit the correct number of values!"); + DEBUG(for (unsigned i = 0, e = Ins.size(); i != e; ++i) { + assert(InVals[i].getNode() && + "LowerFormalArguments emitted a null value!"); + assert(Ins[i].VT == InVals[i].getValueType() && + "LowerFormalArguments emitted a value with the wrong type!"); + }); + + // Update the DAG with the new chain value resulting from argument lowering. + DAG.setRoot(NewRoot); + + // Set up the argument values. + unsigned i = 0; + Idx = 1; + if (!FLI.CanLowerReturn) { + // Create a virtual register for the sret pointer, and put in a copy + // from the sret argument into it. + SmallVector ValueVTs; + ComputeValueVTs(TLI, PointerType::getUnqual(F.getReturnType()), ValueVTs); + EVT VT = ValueVTs[0]; + EVT RegVT = TLI.getRegisterType(*CurDAG->getContext(), VT); + ISD::NodeType AssertOp = ISD::DELETED_NODE; + SDValue ArgValue = getCopyFromParts(DAG, dl, &InVals[0], 1, RegVT, + VT, AssertOp); + + MachineFunction& MF = SDB->DAG.getMachineFunction(); + MachineRegisterInfo& RegInfo = MF.getRegInfo(); + unsigned SRetReg = RegInfo.createVirtualRegister(TLI.getRegClassFor(RegVT)); + FLI.DemoteRegister = SRetReg; + NewRoot = SDB->DAG.getCopyToReg(NewRoot, SDB->getCurDebugLoc(), SRetReg, ArgValue); + DAG.setRoot(NewRoot); + + // i indexes lowered arguments. Bump it past the hidden sret argument. + // Idx indexes LLVM arguments. Don't touch it. + ++i; + } + for (Function::arg_iterator I = F.arg_begin(), E = F.arg_end(); I != E; + ++I, ++Idx) { + SmallVector ArgValues; + SmallVector ValueVTs; + ComputeValueVTs(TLI, I->getType(), ValueVTs); + unsigned NumValues = ValueVTs.size(); + for (unsigned Value = 0; Value != NumValues; ++Value) { + EVT VT = ValueVTs[Value]; + EVT PartVT = TLI.getRegisterType(*CurDAG->getContext(), VT); + unsigned NumParts = TLI.getNumRegisters(*CurDAG->getContext(), VT); + + if (!I->use_empty()) { + ISD::NodeType AssertOp = ISD::DELETED_NODE; + if (F.paramHasAttr(Idx, Attribute::SExt)) + AssertOp = ISD::AssertSext; + else if (F.paramHasAttr(Idx, Attribute::ZExt)) + AssertOp = ISD::AssertZext; + + ArgValues.push_back(getCopyFromParts(DAG, dl, &InVals[i], NumParts, + PartVT, VT, AssertOp)); + } + i += NumParts; + } + if (!I->use_empty()) { + SDB->setValue(I, DAG.getMergeValues(&ArgValues[0], NumValues, + SDB->getCurDebugLoc())); + // If this argument is live outside of the entry block, insert a copy from + // whereever we got it to the vreg that other BB's will reference it as. + SDB->CopyToExportRegsIfNeeded(I); + } + } + assert(i == InVals.size() && "Argument register count mismatch!"); + + // Finally, if the target has anything special to do, allow it to do so. + // FIXME: this should insert code into the DAG! + EmitFunctionEntryCode(F, SDB->DAG.getMachineFunction()); +} + +/// Handle PHI nodes in successor blocks. Emit code into the SelectionDAG to +/// ensure constants are generated when needed. Remember the virtual registers +/// that need to be added to the Machine PHI nodes as input. We cannot just +/// directly add them, because expansion might result in multiple MBB's for one +/// BB. As such, the start of the BB might correspond to a different MBB than +/// the end. +/// +void +SelectionDAGISel::HandlePHINodesInSuccessorBlocks(BasicBlock *LLVMBB) { + TerminatorInst *TI = LLVMBB->getTerminator(); + + SmallPtrSet SuccsHandled; + + // Check successor nodes' PHI nodes that expect a constant to be available + // from this block. + for (unsigned succ = 0, e = TI->getNumSuccessors(); succ != e; ++succ) { + BasicBlock *SuccBB = TI->getSuccessor(succ); + if (!isa(SuccBB->begin())) continue; + MachineBasicBlock *SuccMBB = FuncInfo->MBBMap[SuccBB]; + + // If this terminator has multiple identical successors (common for + // switches), only handle each succ once. + if (!SuccsHandled.insert(SuccMBB)) continue; + + MachineBasicBlock::iterator MBBI = SuccMBB->begin(); + PHINode *PN; + + // At this point we know that there is a 1-1 correspondence between LLVM PHI + // nodes and Machine PHI nodes, but the incoming operands have not been + // emitted yet. + for (BasicBlock::iterator I = SuccBB->begin(); + (PN = dyn_cast(I)); ++I) { + // Ignore dead phi's. + if (PN->use_empty()) continue; + + unsigned Reg; + Value *PHIOp = PN->getIncomingValueForBlock(LLVMBB); + + if (Constant *C = dyn_cast(PHIOp)) { + unsigned &RegOut = SDB->ConstantsOut[C]; + if (RegOut == 0) { + RegOut = FuncInfo->CreateRegForValue(C); + SDB->CopyValueToVirtualRegister(C, RegOut); + } + Reg = RegOut; + } else { + Reg = FuncInfo->ValueMap[PHIOp]; + if (Reg == 0) { + assert(isa(PHIOp) && + FuncInfo->StaticAllocaMap.count(cast(PHIOp)) && + "Didn't codegen value into a register!??"); + Reg = FuncInfo->CreateRegForValue(PHIOp); + SDB->CopyValueToVirtualRegister(PHIOp, Reg); + } + } + + // Remember that this register needs to added to the machine PHI node as + // the input for this MBB. + SmallVector ValueVTs; + ComputeValueVTs(TLI, PN->getType(), ValueVTs); + for (unsigned vti = 0, vte = ValueVTs.size(); vti != vte; ++vti) { + EVT VT = ValueVTs[vti]; + unsigned NumRegisters = TLI.getNumRegisters(*CurDAG->getContext(), VT); + for (unsigned i = 0, e = NumRegisters; i != e; ++i) + SDB->PHINodesToUpdate.push_back(std::make_pair(MBBI++, Reg+i)); + Reg += NumRegisters; + } + } + } + SDB->ConstantsOut.clear(); +} + +/// This is the Fast-ISel version of HandlePHINodesInSuccessorBlocks. It only +/// supports legal types, and it emits MachineInstrs directly instead of +/// creating SelectionDAG nodes. +/// +bool +SelectionDAGISel::HandlePHINodesInSuccessorBlocksFast(BasicBlock *LLVMBB, + FastISel *F) { + TerminatorInst *TI = LLVMBB->getTerminator(); + + SmallPtrSet SuccsHandled; + unsigned OrigNumPHINodesToUpdate = SDB->PHINodesToUpdate.size(); + + // Check successor nodes' PHI nodes that expect a constant to be available + // from this block. + for (unsigned succ = 0, e = TI->getNumSuccessors(); succ != e; ++succ) { + BasicBlock *SuccBB = TI->getSuccessor(succ); + if (!isa(SuccBB->begin())) continue; + MachineBasicBlock *SuccMBB = FuncInfo->MBBMap[SuccBB]; + + // If this terminator has multiple identical successors (common for + // switches), only handle each succ once. + if (!SuccsHandled.insert(SuccMBB)) continue; + + MachineBasicBlock::iterator MBBI = SuccMBB->begin(); + PHINode *PN; + + // At this point we know that there is a 1-1 correspondence between LLVM PHI + // nodes and Machine PHI nodes, but the incoming operands have not been + // emitted yet. + for (BasicBlock::iterator I = SuccBB->begin(); + (PN = dyn_cast(I)); ++I) { + // Ignore dead phi's. + if (PN->use_empty()) continue; + + // Only handle legal types. Two interesting things to note here. First, + // by bailing out early, we may leave behind some dead instructions, + // since SelectionDAG's HandlePHINodesInSuccessorBlocks will insert its + // own moves. Second, this check is necessary becuase FastISel doesn't + // use CreateRegForValue to create registers, so it always creates + // exactly one register for each non-void instruction. + EVT VT = TLI.getValueType(PN->getType(), /*AllowUnknown=*/true); + if (VT == MVT::Other || !TLI.isTypeLegal(VT)) { + // Promote MVT::i1. + if (VT == MVT::i1) + VT = TLI.getTypeToTransformTo(*CurDAG->getContext(), VT); + else { + SDB->PHINodesToUpdate.resize(OrigNumPHINodesToUpdate); + return false; + } + } + + Value *PHIOp = PN->getIncomingValueForBlock(LLVMBB); + + unsigned Reg = F->getRegForValue(PHIOp); + if (Reg == 0) { + SDB->PHINodesToUpdate.resize(OrigNumPHINodesToUpdate); + return false; + } + SDB->PHINodesToUpdate.push_back(std::make_pair(MBBI++, Reg)); + } + } + + return true; +} diff --git a/libclamav/c++/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h b/libclamav/c++/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h new file mode 100644 index 000000000..244f9b501 --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h @@ -0,0 +1,487 @@ +//===-- SelectionDAGBuilder.h - Selection-DAG building --------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This implements routines for translating from LLVM IR into SelectionDAG IR. +// +//===----------------------------------------------------------------------===// + +#ifndef SELECTIONDAGBUILDER_H +#define SELECTIONDAGBUILDER_H + +#include "llvm/Constants.h" +#include "llvm/CodeGen/SelectionDAG.h" +#include "llvm/ADT/APInt.h" +#include "llvm/ADT/DenseMap.h" +#ifndef NDEBUG +#include "llvm/ADT/SmallSet.h" +#endif +#include "llvm/CodeGen/SelectionDAGNodes.h" +#include "llvm/CodeGen/ValueTypes.h" +#include "llvm/Support/CallSite.h" +#include "llvm/Support/ErrorHandling.h" +#include +#include + +namespace llvm { + +class AliasAnalysis; +class AllocaInst; +class BasicBlock; +class BitCastInst; +class BranchInst; +class CallInst; +class ExtractElementInst; +class ExtractValueInst; +class FCmpInst; +class FPExtInst; +class FPToSIInst; +class FPToUIInst; +class FPTruncInst; +class Function; +class FunctionLoweringInfo; +class GetElementPtrInst; +class GCFunctionInfo; +class ICmpInst; +class IntToPtrInst; +class IndirectBrInst; +class InvokeInst; +class InsertElementInst; +class InsertValueInst; +class Instruction; +class LoadInst; +class MachineBasicBlock; +class MachineFunction; +class MachineInstr; +class MachineRegisterInfo; +class PHINode; +class PtrToIntInst; +class ReturnInst; +class SDISelAsmOperandInfo; +class SExtInst; +class SelectInst; +class ShuffleVectorInst; +class SIToFPInst; +class StoreInst; +class SwitchInst; +class TargetData; +class TargetLowering; +class TruncInst; +class UIToFPInst; +class UnreachableInst; +class UnwindInst; +class VAArgInst; +class ZExtInst; + +//===----------------------------------------------------------------------===// +/// SelectionDAGBuilder - This is the common target-independent lowering +/// implementation that is parameterized by a TargetLowering object. +/// Also, targets can overload any lowering method. +/// +class SelectionDAGBuilder { + MachineBasicBlock *CurMBB; + + /// CurDebugLoc - current file + line number. Changes as we build the DAG. + DebugLoc CurDebugLoc; + + DenseMap NodeMap; + + /// PendingLoads - Loads are not emitted to the program immediately. We bunch + /// them up and then emit token factor nodes when possible. This allows us to + /// get simple disambiguation between loads without worrying about alias + /// analysis. + SmallVector PendingLoads; + + /// PendingExports - CopyToReg nodes that copy values to virtual registers + /// for export to other blocks need to be emitted before any terminator + /// instruction, but they have no other ordering requirements. We bunch them + /// up and the emit a single tokenfactor for them just before terminator + /// instructions. + SmallVector PendingExports; + + /// Case - A struct to record the Value for a switch case, and the + /// case's target basic block. + struct Case { + Constant* Low; + Constant* High; + MachineBasicBlock* BB; + + Case() : Low(0), High(0), BB(0) { } + Case(Constant* low, Constant* high, MachineBasicBlock* bb) : + Low(low), High(high), BB(bb) { } + APInt size() const { + const APInt &rHigh = cast(High)->getValue(); + const APInt &rLow = cast(Low)->getValue(); + return (rHigh - rLow + 1ULL); + } + }; + + struct CaseBits { + uint64_t Mask; + MachineBasicBlock* BB; + unsigned Bits; + + CaseBits(uint64_t mask, MachineBasicBlock* bb, unsigned bits): + Mask(mask), BB(bb), Bits(bits) { } + }; + + typedef std::vector CaseVector; + typedef std::vector CaseBitsVector; + typedef CaseVector::iterator CaseItr; + typedef std::pair CaseRange; + + /// CaseRec - A struct with ctor used in lowering switches to a binary tree + /// of conditional branches. + struct CaseRec { + CaseRec(MachineBasicBlock *bb, Constant *lt, Constant *ge, CaseRange r) : + CaseBB(bb), LT(lt), GE(ge), Range(r) {} + + /// CaseBB - The MBB in which to emit the compare and branch + MachineBasicBlock *CaseBB; + /// LT, GE - If nonzero, we know the current case value must be less-than or + /// greater-than-or-equal-to these Constants. + Constant *LT; + Constant *GE; + /// Range - A pair of iterators representing the range of case values to be + /// processed at this point in the binary search tree. + CaseRange Range; + }; + + typedef std::vector CaseRecVector; + + /// The comparison function for sorting the switch case values in the vector. + /// WARNING: Case ranges should be disjoint! + struct CaseCmp { + bool operator () (const Case& C1, const Case& C2) { + assert(isa(C1.Low) && isa(C2.High)); + const ConstantInt* CI1 = cast(C1.Low); + const ConstantInt* CI2 = cast(C2.High); + return CI1->getValue().slt(CI2->getValue()); + } + }; + + struct CaseBitsCmp { + bool operator () (const CaseBits& C1, const CaseBits& C2) { + return C1.Bits > C2.Bits; + } + }; + + size_t Clusterify(CaseVector& Cases, const SwitchInst &SI); + + /// CaseBlock - This structure is used to communicate between + /// SelectionDAGBuilder and SDISel for the code generation of additional basic + /// blocks needed by multi-case switch statements. + struct CaseBlock { + CaseBlock(ISD::CondCode cc, Value *cmplhs, Value *cmprhs, Value *cmpmiddle, + MachineBasicBlock *truebb, MachineBasicBlock *falsebb, + MachineBasicBlock *me) + : CC(cc), CmpLHS(cmplhs), CmpMHS(cmpmiddle), CmpRHS(cmprhs), + TrueBB(truebb), FalseBB(falsebb), ThisBB(me) {} + // CC - the condition code to use for the case block's setcc node + ISD::CondCode CC; + // CmpLHS/CmpRHS/CmpMHS - The LHS/MHS/RHS of the comparison to emit. + // Emit by default LHS op RHS. MHS is used for range comparisons: + // If MHS is not null: (LHS <= MHS) and (MHS <= RHS). + Value *CmpLHS, *CmpMHS, *CmpRHS; + // TrueBB/FalseBB - the block to branch to if the setcc is true/false. + MachineBasicBlock *TrueBB, *FalseBB; + // ThisBB - the block into which to emit the code for the setcc and branches + MachineBasicBlock *ThisBB; + }; + struct JumpTable { + JumpTable(unsigned R, unsigned J, MachineBasicBlock *M, + MachineBasicBlock *D): Reg(R), JTI(J), MBB(M), Default(D) {} + + /// Reg - the virtual register containing the index of the jump table entry + //. to jump to. + unsigned Reg; + /// JTI - the JumpTableIndex for this jump table in the function. + unsigned JTI; + /// MBB - the MBB into which to emit the code for the indirect jump. + MachineBasicBlock *MBB; + /// Default - the MBB of the default bb, which is a successor of the range + /// check MBB. This is when updating PHI nodes in successors. + MachineBasicBlock *Default; + }; + struct JumpTableHeader { + JumpTableHeader(APInt F, APInt L, Value* SV, MachineBasicBlock* H, + bool E = false): + First(F), Last(L), SValue(SV), HeaderBB(H), Emitted(E) {} + APInt First; + APInt Last; + Value *SValue; + MachineBasicBlock *HeaderBB; + bool Emitted; + }; + typedef std::pair JumpTableBlock; + + struct BitTestCase { + BitTestCase(uint64_t M, MachineBasicBlock* T, MachineBasicBlock* Tr): + Mask(M), ThisBB(T), TargetBB(Tr) { } + uint64_t Mask; + MachineBasicBlock* ThisBB; + MachineBasicBlock* TargetBB; + }; + + typedef SmallVector BitTestInfo; + + struct BitTestBlock { + BitTestBlock(APInt F, APInt R, Value* SV, + unsigned Rg, bool E, + MachineBasicBlock* P, MachineBasicBlock* D, + const BitTestInfo& C): + First(F), Range(R), SValue(SV), Reg(Rg), Emitted(E), + Parent(P), Default(D), Cases(C) { } + APInt First; + APInt Range; + Value *SValue; + unsigned Reg; + bool Emitted; + MachineBasicBlock *Parent; + MachineBasicBlock *Default; + BitTestInfo Cases; + }; + +public: + // TLI - This is information that describes the available target features we + // need for lowering. This indicates when operations are unavailable, + // implemented with a libcall, etc. + TargetLowering &TLI; + SelectionDAG &DAG; + const TargetData *TD; + AliasAnalysis *AA; + + /// SwitchCases - Vector of CaseBlock structures used to communicate + /// SwitchInst code generation information. + std::vector SwitchCases; + /// JTCases - Vector of JumpTable structures used to communicate + /// SwitchInst code generation information. + std::vector JTCases; + /// BitTestCases - Vector of BitTestBlock structures used to communicate + /// SwitchInst code generation information. + std::vector BitTestCases; + + /// PHINodesToUpdate - A list of phi instructions whose operand list will + /// be updated after processing the current basic block. + std::vector > PHINodesToUpdate; + + /// EdgeMapping - If an edge from CurMBB to any MBB is changed (e.g. due to + /// scheduler custom lowering), track the change here. + DenseMap EdgeMapping; + + // Emit PHI-node-operand constants only once even if used by multiple + // PHI nodes. + DenseMap ConstantsOut; + + /// FuncInfo - Information about the function as a whole. + /// + FunctionLoweringInfo &FuncInfo; + + /// OptLevel - What optimization level we're generating code for. + /// + CodeGenOpt::Level OptLevel; + + /// GFI - Garbage collection metadata for the function. + GCFunctionInfo *GFI; + + /// HasTailCall - This is set to true if a call in the current + /// block has been translated as a tail call. In this case, + /// no subsequent DAG nodes should be created. + /// + bool HasTailCall; + + LLVMContext *Context; + + SelectionDAGBuilder(SelectionDAG &dag, TargetLowering &tli, + FunctionLoweringInfo &funcinfo, + CodeGenOpt::Level ol) + : CurDebugLoc(DebugLoc::getUnknownLoc()), + TLI(tli), DAG(dag), FuncInfo(funcinfo), OptLevel(ol), + HasTailCall(false), + Context(dag.getContext()) { + } + + void init(GCFunctionInfo *gfi, AliasAnalysis &aa); + + /// clear - Clear out the curret SelectionDAG and the associated + /// state and prepare this SelectionDAGBuilder object to be used + /// for a new block. This doesn't clear out information about + /// additional blocks that are needed to complete switch lowering + /// or PHI node updating; that information is cleared out as it is + /// consumed. + void clear(); + + /// getRoot - Return the current virtual root of the Selection DAG, + /// flushing any PendingLoad items. This must be done before emitting + /// a store or any other node that may need to be ordered after any + /// prior load instructions. + /// + SDValue getRoot(); + + /// getControlRoot - Similar to getRoot, but instead of flushing all the + /// PendingLoad items, flush all the PendingExports items. It is necessary + /// to do this before emitting a terminator instruction. + /// + SDValue getControlRoot(); + + DebugLoc getCurDebugLoc() const { return CurDebugLoc; } + void setCurDebugLoc(DebugLoc dl) { CurDebugLoc = dl; } + + void CopyValueToVirtualRegister(Value *V, unsigned Reg); + + void visit(Instruction &I); + + void visit(unsigned Opcode, User &I); + + void setCurrentBasicBlock(MachineBasicBlock *MBB) { CurMBB = MBB; } + + SDValue getValue(const Value *V); + + void setValue(const Value *V, SDValue NewN) { + SDValue &N = NodeMap[V]; + assert(N.getNode() == 0 && "Already set a value for this node!"); + N = NewN; + } + + void GetRegistersForValue(SDISelAsmOperandInfo &OpInfo, + std::set &OutputRegs, + std::set &InputRegs); + + void FindMergedConditions(Value *Cond, MachineBasicBlock *TBB, + MachineBasicBlock *FBB, MachineBasicBlock *CurBB, + unsigned Opc); + void EmitBranchForMergedCondition(Value *Cond, MachineBasicBlock *TBB, + MachineBasicBlock *FBB, + MachineBasicBlock *CurBB); + bool ShouldEmitAsBranches(const std::vector &Cases); + bool isExportableFromCurrentBlock(Value *V, const BasicBlock *FromBB); + void CopyToExportRegsIfNeeded(Value *V); + void ExportFromCurrentBlock(Value *V); + void LowerCallTo(CallSite CS, SDValue Callee, bool IsTailCall, + MachineBasicBlock *LandingPad = NULL); + +private: + // Terminator instructions. + void visitRet(ReturnInst &I); + void visitBr(BranchInst &I); + void visitSwitch(SwitchInst &I); + void visitIndirectBr(IndirectBrInst &I); + void visitUnreachable(UnreachableInst &I) { /* noop */ } + + // Helpers for visitSwitch + bool handleSmallSwitchRange(CaseRec& CR, + CaseRecVector& WorkList, + Value* SV, + MachineBasicBlock* Default); + bool handleJTSwitchCase(CaseRec& CR, + CaseRecVector& WorkList, + Value* SV, + MachineBasicBlock* Default); + bool handleBTSplitSwitchCase(CaseRec& CR, + CaseRecVector& WorkList, + Value* SV, + MachineBasicBlock* Default); + bool handleBitTestsSwitchCase(CaseRec& CR, + CaseRecVector& WorkList, + Value* SV, + MachineBasicBlock* Default); +public: + void visitSwitchCase(CaseBlock &CB); + void visitBitTestHeader(BitTestBlock &B); + void visitBitTestCase(MachineBasicBlock* NextMBB, + unsigned Reg, + BitTestCase &B); + void visitJumpTable(JumpTable &JT); + void visitJumpTableHeader(JumpTable &JT, JumpTableHeader &JTH); + +private: + // These all get lowered before this pass. + void visitInvoke(InvokeInst &I); + void visitUnwind(UnwindInst &I); + + void visitBinary(User &I, unsigned OpCode); + void visitShift(User &I, unsigned Opcode); + void visitAdd(User &I) { visitBinary(I, ISD::ADD); } + void visitFAdd(User &I) { visitBinary(I, ISD::FADD); } + void visitSub(User &I) { visitBinary(I, ISD::SUB); } + void visitFSub(User &I); + void visitMul(User &I) { visitBinary(I, ISD::MUL); } + void visitFMul(User &I) { visitBinary(I, ISD::FMUL); } + void visitURem(User &I) { visitBinary(I, ISD::UREM); } + void visitSRem(User &I) { visitBinary(I, ISD::SREM); } + void visitFRem(User &I) { visitBinary(I, ISD::FREM); } + void visitUDiv(User &I) { visitBinary(I, ISD::UDIV); } + void visitSDiv(User &I) { visitBinary(I, ISD::SDIV); } + void visitFDiv(User &I) { visitBinary(I, ISD::FDIV); } + void visitAnd (User &I) { visitBinary(I, ISD::AND); } + void visitOr (User &I) { visitBinary(I, ISD::OR); } + void visitXor (User &I) { visitBinary(I, ISD::XOR); } + void visitShl (User &I) { visitShift(I, ISD::SHL); } + void visitLShr(User &I) { visitShift(I, ISD::SRL); } + void visitAShr(User &I) { visitShift(I, ISD::SRA); } + void visitICmp(User &I); + void visitFCmp(User &I); + // Visit the conversion instructions + void visitTrunc(User &I); + void visitZExt(User &I); + void visitSExt(User &I); + void visitFPTrunc(User &I); + void visitFPExt(User &I); + void visitFPToUI(User &I); + void visitFPToSI(User &I); + void visitUIToFP(User &I); + void visitSIToFP(User &I); + void visitPtrToInt(User &I); + void visitIntToPtr(User &I); + void visitBitCast(User &I); + + void visitExtractElement(User &I); + void visitInsertElement(User &I); + void visitShuffleVector(User &I); + + void visitExtractValue(ExtractValueInst &I); + void visitInsertValue(InsertValueInst &I); + + void visitGetElementPtr(User &I); + void visitSelect(User &I); + + void visitAlloca(AllocaInst &I); + void visitLoad(LoadInst &I); + void visitStore(StoreInst &I); + void visitPHI(PHINode &I) { } // PHI nodes are handled specially. + void visitCall(CallInst &I); + void visitInlineAsm(CallSite CS); + const char *visitIntrinsicCall(CallInst &I, unsigned Intrinsic); + void visitTargetIntrinsic(CallInst &I, unsigned Intrinsic); + + void visitPow(CallInst &I); + void visitExp2(CallInst &I); + void visitExp(CallInst &I); + void visitLog(CallInst &I); + void visitLog2(CallInst &I); + void visitLog10(CallInst &I); + + void visitVAStart(CallInst &I); + void visitVAArg(VAArgInst &I); + void visitVAEnd(CallInst &I); + void visitVACopy(CallInst &I); + + void visitUserOp1(Instruction &I) { + llvm_unreachable("UserOp1 should not exist at instruction selection time!"); + } + void visitUserOp2(Instruction &I) { + llvm_unreachable("UserOp2 should not exist at instruction selection time!"); + } + + const char *implVisitBinaryAtomic(CallInst& I, ISD::NodeType Op); + const char *implVisitAluOverflow(CallInst &I, ISD::NodeType Op); +}; + +} // end namespace llvm + +#endif diff --git a/libclamav/c++/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/libclamav/c++/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp new file mode 100644 index 000000000..c39437f98 --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp @@ -0,0 +1,1351 @@ +//===-- SelectionDAGISel.cpp - Implement the SelectionDAGISel class -------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This implements the SelectionDAGISel class. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "isel" +#include "ScheduleDAGSDNodes.h" +#include "SelectionDAGBuilder.h" +#include "FunctionLoweringInfo.h" +#include "llvm/CodeGen/SelectionDAGISel.h" +#include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/Analysis/DebugInfo.h" +#include "llvm/Constants.h" +#include "llvm/CallingConv.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Function.h" +#include "llvm/GlobalVariable.h" +#include "llvm/InlineAsm.h" +#include "llvm/Instructions.h" +#include "llvm/Intrinsics.h" +#include "llvm/IntrinsicInst.h" +#include "llvm/LLVMContext.h" +#include "llvm/CodeGen/FastISel.h" +#include "llvm/CodeGen/GCStrategy.h" +#include "llvm/CodeGen/GCMetadata.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineFunctionAnalysis.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineJumpTableInfo.h" +#include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/ScheduleHazardRecognizer.h" +#include "llvm/CodeGen/SchedulerRegistry.h" +#include "llvm/CodeGen/SelectionDAG.h" +#include "llvm/CodeGen/DwarfWriter.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetFrameInfo.h" +#include "llvm/Target/TargetIntrinsicInfo.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetLowering.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetOptions.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/Support/Timer.h" +#include "llvm/Support/raw_ostream.h" +#include +using namespace llvm; + +static cl::opt +DisableLegalizeTypes("disable-legalize-types", cl::Hidden); +static cl::opt +EnableFastISelVerbose("fast-isel-verbose", cl::Hidden, + cl::desc("Enable verbose messages in the \"fast\" " + "instruction selector")); +static cl::opt +EnableFastISelAbort("fast-isel-abort", cl::Hidden, + cl::desc("Enable abort calls when \"fast\" instruction fails")); +static cl::opt +SchedLiveInCopies("schedule-livein-copies", cl::Hidden, + cl::desc("Schedule copies of livein registers"), + cl::init(false)); + +#ifndef NDEBUG +static cl::opt +ViewDAGCombine1("view-dag-combine1-dags", cl::Hidden, + cl::desc("Pop up a window to show dags before the first " + "dag combine pass")); +static cl::opt +ViewLegalizeTypesDAGs("view-legalize-types-dags", cl::Hidden, + cl::desc("Pop up a window to show dags before legalize types")); +static cl::opt +ViewLegalizeDAGs("view-legalize-dags", cl::Hidden, + cl::desc("Pop up a window to show dags before legalize")); +static cl::opt +ViewDAGCombine2("view-dag-combine2-dags", cl::Hidden, + cl::desc("Pop up a window to show dags before the second " + "dag combine pass")); +static cl::opt +ViewDAGCombineLT("view-dag-combine-lt-dags", cl::Hidden, + cl::desc("Pop up a window to show dags before the post legalize types" + " dag combine pass")); +static cl::opt +ViewISelDAGs("view-isel-dags", cl::Hidden, + cl::desc("Pop up a window to show isel dags as they are selected")); +static cl::opt +ViewSchedDAGs("view-sched-dags", cl::Hidden, + cl::desc("Pop up a window to show sched dags as they are processed")); +static cl::opt +ViewSUnitDAGs("view-sunit-dags", cl::Hidden, + cl::desc("Pop up a window to show SUnit dags after they are processed")); +#else +static const bool ViewDAGCombine1 = false, + ViewLegalizeTypesDAGs = false, ViewLegalizeDAGs = false, + ViewDAGCombine2 = false, + ViewDAGCombineLT = false, + ViewISelDAGs = false, ViewSchedDAGs = false, + ViewSUnitDAGs = false; +#endif + +//===---------------------------------------------------------------------===// +/// +/// RegisterScheduler class - Track the registration of instruction schedulers. +/// +//===---------------------------------------------------------------------===// +MachinePassRegistry RegisterScheduler::Registry; + +//===---------------------------------------------------------------------===// +/// +/// ISHeuristic command line option for instruction schedulers. +/// +//===---------------------------------------------------------------------===// +static cl::opt > +ISHeuristic("pre-RA-sched", + cl::init(&createDefaultScheduler), + cl::desc("Instruction schedulers available (before register" + " allocation):")); + +static RegisterScheduler +defaultListDAGScheduler("default", "Best scheduler for the target", + createDefaultScheduler); + +namespace llvm { + //===--------------------------------------------------------------------===// + /// createDefaultScheduler - This creates an instruction scheduler appropriate + /// for the target. + ScheduleDAGSDNodes* createDefaultScheduler(SelectionDAGISel *IS, + CodeGenOpt::Level OptLevel) { + const TargetLowering &TLI = IS->getTargetLowering(); + + if (OptLevel == CodeGenOpt::None) + return createFastDAGScheduler(IS, OptLevel); + if (TLI.getSchedulingPreference() == TargetLowering::SchedulingForLatency) + return createTDListDAGScheduler(IS, OptLevel); + assert(TLI.getSchedulingPreference() == + TargetLowering::SchedulingForRegPressure && "Unknown sched type!"); + return createBURRListDAGScheduler(IS, OptLevel); + } +} + +// EmitInstrWithCustomInserter - This method should be implemented by targets +// that mark instructions with the 'usesCustomInserter' flag. These +// instructions are special in various ways, which require special support to +// insert. The specified MachineInstr is created but not inserted into any +// basic blocks, and this method is called to expand it into a sequence of +// instructions, potentially also creating new basic blocks and control flow. +// When new basic blocks are inserted and the edges from MBB to its successors +// are modified, the method should insert pairs of into the +// DenseMap. +MachineBasicBlock *TargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI, + MachineBasicBlock *MBB, + DenseMap *EM) const { +#ifndef NDEBUG + errs() << "If a target marks an instruction with " + "'usesCustomInserter', it must implement " + "TargetLowering::EmitInstrWithCustomInserter!"; +#endif + llvm_unreachable(0); + return 0; +} + +/// EmitLiveInCopy - Emit a copy for a live in physical register. If the +/// physical register has only a single copy use, then coalesced the copy +/// if possible. +static void EmitLiveInCopy(MachineBasicBlock *MBB, + MachineBasicBlock::iterator &InsertPos, + unsigned VirtReg, unsigned PhysReg, + const TargetRegisterClass *RC, + DenseMap &CopyRegMap, + const MachineRegisterInfo &MRI, + const TargetRegisterInfo &TRI, + const TargetInstrInfo &TII) { + unsigned NumUses = 0; + MachineInstr *UseMI = NULL; + for (MachineRegisterInfo::use_iterator UI = MRI.use_begin(VirtReg), + UE = MRI.use_end(); UI != UE; ++UI) { + UseMI = &*UI; + if (++NumUses > 1) + break; + } + + // If the number of uses is not one, or the use is not a move instruction, + // don't coalesce. Also, only coalesce away a virtual register to virtual + // register copy. + bool Coalesced = false; + unsigned SrcReg, DstReg, SrcSubReg, DstSubReg; + if (NumUses == 1 && + TII.isMoveInstr(*UseMI, SrcReg, DstReg, SrcSubReg, DstSubReg) && + TargetRegisterInfo::isVirtualRegister(DstReg)) { + VirtReg = DstReg; + Coalesced = true; + } + + // Now find an ideal location to insert the copy. + MachineBasicBlock::iterator Pos = InsertPos; + while (Pos != MBB->begin()) { + MachineInstr *PrevMI = prior(Pos); + DenseMap::iterator RI = CopyRegMap.find(PrevMI); + // copyRegToReg might emit multiple instructions to do a copy. + unsigned CopyDstReg = (RI == CopyRegMap.end()) ? 0 : RI->second; + if (CopyDstReg && !TRI.regsOverlap(CopyDstReg, PhysReg)) + // This is what the BB looks like right now: + // r1024 = mov r0 + // ... + // r1 = mov r1024 + // + // We want to insert "r1025 = mov r1". Inserting this copy below the + // move to r1024 makes it impossible for that move to be coalesced. + // + // r1025 = mov r1 + // r1024 = mov r0 + // ... + // r1 = mov 1024 + // r2 = mov 1025 + break; // Woot! Found a good location. + --Pos; + } + + bool Emitted = TII.copyRegToReg(*MBB, Pos, VirtReg, PhysReg, RC, RC); + assert(Emitted && "Unable to issue a live-in copy instruction!\n"); + (void) Emitted; + + CopyRegMap.insert(std::make_pair(prior(Pos), VirtReg)); + if (Coalesced) { + if (&*InsertPos == UseMI) ++InsertPos; + MBB->erase(UseMI); + } +} + +/// EmitLiveInCopies - If this is the first basic block in the function, +/// and if it has live ins that need to be copied into vregs, emit the +/// copies into the block. +static void EmitLiveInCopies(MachineBasicBlock *EntryMBB, + const MachineRegisterInfo &MRI, + const TargetRegisterInfo &TRI, + const TargetInstrInfo &TII) { + if (SchedLiveInCopies) { + // Emit the copies at a heuristically-determined location in the block. + DenseMap CopyRegMap; + MachineBasicBlock::iterator InsertPos = EntryMBB->begin(); + for (MachineRegisterInfo::livein_iterator LI = MRI.livein_begin(), + E = MRI.livein_end(); LI != E; ++LI) + if (LI->second) { + const TargetRegisterClass *RC = MRI.getRegClass(LI->second); + EmitLiveInCopy(EntryMBB, InsertPos, LI->second, LI->first, + RC, CopyRegMap, MRI, TRI, TII); + } + } else { + // Emit the copies into the top of the block. + for (MachineRegisterInfo::livein_iterator LI = MRI.livein_begin(), + E = MRI.livein_end(); LI != E; ++LI) + if (LI->second) { + const TargetRegisterClass *RC = MRI.getRegClass(LI->second); + bool Emitted = TII.copyRegToReg(*EntryMBB, EntryMBB->begin(), + LI->second, LI->first, RC, RC); + assert(Emitted && "Unable to issue a live-in copy instruction!\n"); + (void) Emitted; + } + } +} + +//===----------------------------------------------------------------------===// +// SelectionDAGISel code +//===----------------------------------------------------------------------===// + +SelectionDAGISel::SelectionDAGISel(TargetMachine &tm, CodeGenOpt::Level OL) : + MachineFunctionPass(&ID), TM(tm), TLI(*tm.getTargetLowering()), + FuncInfo(new FunctionLoweringInfo(TLI)), + CurDAG(new SelectionDAG(TLI, *FuncInfo)), + SDB(new SelectionDAGBuilder(*CurDAG, TLI, *FuncInfo, OL)), + GFI(), + OptLevel(OL), + DAGSize(0) +{} + +SelectionDAGISel::~SelectionDAGISel() { + delete SDB; + delete CurDAG; + delete FuncInfo; +} + +unsigned SelectionDAGISel::MakeReg(EVT VT) { + return RegInfo->createVirtualRegister(TLI.getRegClassFor(VT)); +} + +void SelectionDAGISel::getAnalysisUsage(AnalysisUsage &AU) const { + AU.addRequired(); + AU.addPreserved(); + AU.addRequired(); + AU.addPreserved(); + AU.addRequired(); + AU.addPreserved(); + MachineFunctionPass::getAnalysisUsage(AU); +} + +bool SelectionDAGISel::runOnMachineFunction(MachineFunction &mf) { + Function &Fn = *mf.getFunction(); + + // Do some sanity-checking on the command-line options. + assert((!EnableFastISelVerbose || EnableFastISel) && + "-fast-isel-verbose requires -fast-isel"); + assert((!EnableFastISelAbort || EnableFastISel) && + "-fast-isel-abort requires -fast-isel"); + + // Get alias analysis for load/store combining. + AA = &getAnalysis(); + + MF = &mf; + const TargetInstrInfo &TII = *TM.getInstrInfo(); + const TargetRegisterInfo &TRI = *TM.getRegisterInfo(); + + if (Fn.hasGC()) + GFI = &getAnalysis().getFunctionInfo(Fn); + else + GFI = 0; + RegInfo = &MF->getRegInfo(); + DEBUG(errs() << "\n\n\n=== " << Fn.getName() << "\n"); + + MachineModuleInfo *MMI = getAnalysisIfAvailable(); + DwarfWriter *DW = getAnalysisIfAvailable(); + CurDAG->init(*MF, MMI, DW); + FuncInfo->set(Fn, *MF, EnableFastISel); + SDB->init(GFI, *AA); + + for (Function::iterator I = Fn.begin(), E = Fn.end(); I != E; ++I) + if (InvokeInst *Invoke = dyn_cast(I->getTerminator())) + // Mark landing pad. + FuncInfo->MBBMap[Invoke->getSuccessor(1)]->setIsLandingPad(); + + SelectAllBasicBlocks(Fn, *MF, MMI, DW, TII); + + // If the first basic block in the function has live ins that need to be + // copied into vregs, emit the copies into the top of the block before + // emitting the code for the block. + EmitLiveInCopies(MF->begin(), *RegInfo, TRI, TII); + + // Add function live-ins to entry block live-in set. + for (MachineRegisterInfo::livein_iterator I = RegInfo->livein_begin(), + E = RegInfo->livein_end(); I != E; ++I) + MF->begin()->addLiveIn(I->first); + +#ifndef NDEBUG + assert(FuncInfo->CatchInfoFound.size() == FuncInfo->CatchInfoLost.size() && + "Not all catch info was assigned to a landing pad!"); +#endif + + FuncInfo->clear(); + + return true; +} + +void SelectionDAGISel::SelectBasicBlock(BasicBlock *LLVMBB, + BasicBlock::iterator Begin, + BasicBlock::iterator End, + bool &HadTailCall) { + SDB->setCurrentBasicBlock(BB); + MetadataContext &TheMetadata = LLVMBB->getParent()->getContext().getMetadata(); + unsigned MDDbgKind = TheMetadata.getMDKind("dbg"); + + // Lower all of the non-terminator instructions. If a call is emitted + // as a tail call, cease emitting nodes for this block. + for (BasicBlock::iterator I = Begin; I != End && !SDB->HasTailCall; ++I) { + if (MDDbgKind) { + // Update DebugLoc if debug information is attached with this + // instruction. + if (!isa(I)) + if (MDNode *Dbg = TheMetadata.getMD(MDDbgKind, I)) { + DILocation DILoc(Dbg); + DebugLoc Loc = ExtractDebugLocation(DILoc, MF->getDebugLocInfo()); + SDB->setCurDebugLoc(Loc); + if (MF->getDefaultDebugLoc().isUnknown()) + MF->setDefaultDebugLoc(Loc); + } + } + if (!isa(I)) + SDB->visit(*I); + } + + if (!SDB->HasTailCall) { + // Ensure that all instructions which are used outside of their defining + // blocks are available as virtual registers. Invoke is handled elsewhere. + for (BasicBlock::iterator I = Begin; I != End; ++I) + if (!isa(I) && !isa(I)) + SDB->CopyToExportRegsIfNeeded(I); + + // Handle PHI nodes in successor blocks. + if (End == LLVMBB->end()) { + HandlePHINodesInSuccessorBlocks(LLVMBB); + + // Lower the terminator after the copies are emitted. + SDB->visit(*LLVMBB->getTerminator()); + } + } + + // Make sure the root of the DAG is up-to-date. + CurDAG->setRoot(SDB->getControlRoot()); + + // Final step, emit the lowered DAG as machine code. + CodeGenAndEmitDAG(); + HadTailCall = SDB->HasTailCall; + SDB->clear(); +} + +void SelectionDAGISel::ComputeLiveOutVRegInfo() { + SmallPtrSet VisitedNodes; + SmallVector Worklist; + + Worklist.push_back(CurDAG->getRoot().getNode()); + + APInt Mask; + APInt KnownZero; + APInt KnownOne; + + while (!Worklist.empty()) { + SDNode *N = Worklist.back(); + Worklist.pop_back(); + + // If we've already seen this node, ignore it. + if (!VisitedNodes.insert(N)) + continue; + + // Otherwise, add all chain operands to the worklist. + for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) + if (N->getOperand(i).getValueType() == MVT::Other) + Worklist.push_back(N->getOperand(i).getNode()); + + // If this is a CopyToReg with a vreg dest, process it. + if (N->getOpcode() != ISD::CopyToReg) + continue; + + unsigned DestReg = cast(N->getOperand(1))->getReg(); + if (!TargetRegisterInfo::isVirtualRegister(DestReg)) + continue; + + // Ignore non-scalar or non-integer values. + SDValue Src = N->getOperand(2); + EVT SrcVT = Src.getValueType(); + if (!SrcVT.isInteger() || SrcVT.isVector()) + continue; + + unsigned NumSignBits = CurDAG->ComputeNumSignBits(Src); + Mask = APInt::getAllOnesValue(SrcVT.getSizeInBits()); + CurDAG->ComputeMaskedBits(Src, Mask, KnownZero, KnownOne); + + // Only install this information if it tells us something. + if (NumSignBits != 1 || KnownZero != 0 || KnownOne != 0) { + DestReg -= TargetRegisterInfo::FirstVirtualRegister; + if (DestReg >= FuncInfo->LiveOutRegInfo.size()) + FuncInfo->LiveOutRegInfo.resize(DestReg+1); + FunctionLoweringInfo::LiveOutInfo &LOI = + FuncInfo->LiveOutRegInfo[DestReg]; + LOI.NumSignBits = NumSignBits; + LOI.KnownOne = KnownOne; + LOI.KnownZero = KnownZero; + } + } +} + +void SelectionDAGISel::CodeGenAndEmitDAG() { + std::string GroupName; + if (TimePassesIsEnabled) + GroupName = "Instruction Selection and Scheduling"; + std::string BlockName; + if (ViewDAGCombine1 || ViewLegalizeTypesDAGs || ViewLegalizeDAGs || + ViewDAGCombine2 || ViewDAGCombineLT || ViewISelDAGs || ViewSchedDAGs || + ViewSUnitDAGs) + BlockName = MF->getFunction()->getNameStr() + ":" + + BB->getBasicBlock()->getNameStr(); + + DEBUG(errs() << "Initial selection DAG:\n"); + DEBUG(CurDAG->dump()); + + if (ViewDAGCombine1) CurDAG->viewGraph("dag-combine1 input for " + BlockName); + + // Run the DAG combiner in pre-legalize mode. + if (TimePassesIsEnabled) { + NamedRegionTimer T("DAG Combining 1", GroupName); + CurDAG->Combine(Unrestricted, *AA, OptLevel); + } else { + CurDAG->Combine(Unrestricted, *AA, OptLevel); + } + + DEBUG(errs() << "Optimized lowered selection DAG:\n"); + DEBUG(CurDAG->dump()); + + // Second step, hack on the DAG until it only uses operations and types that + // the target supports. + if (!DisableLegalizeTypes) { + if (ViewLegalizeTypesDAGs) CurDAG->viewGraph("legalize-types input for " + + BlockName); + + bool Changed; + if (TimePassesIsEnabled) { + NamedRegionTimer T("Type Legalization", GroupName); + Changed = CurDAG->LegalizeTypes(); + } else { + Changed = CurDAG->LegalizeTypes(); + } + + DEBUG(errs() << "Type-legalized selection DAG:\n"); + DEBUG(CurDAG->dump()); + + if (Changed) { + if (ViewDAGCombineLT) + CurDAG->viewGraph("dag-combine-lt input for " + BlockName); + + // Run the DAG combiner in post-type-legalize mode. + if (TimePassesIsEnabled) { + NamedRegionTimer T("DAG Combining after legalize types", GroupName); + CurDAG->Combine(NoIllegalTypes, *AA, OptLevel); + } else { + CurDAG->Combine(NoIllegalTypes, *AA, OptLevel); + } + + DEBUG(errs() << "Optimized type-legalized selection DAG:\n"); + DEBUG(CurDAG->dump()); + } + + if (TimePassesIsEnabled) { + NamedRegionTimer T("Vector Legalization", GroupName); + Changed = CurDAG->LegalizeVectors(); + } else { + Changed = CurDAG->LegalizeVectors(); + } + + if (Changed) { + if (TimePassesIsEnabled) { + NamedRegionTimer T("Type Legalization 2", GroupName); + Changed = CurDAG->LegalizeTypes(); + } else { + Changed = CurDAG->LegalizeTypes(); + } + + if (ViewDAGCombineLT) + CurDAG->viewGraph("dag-combine-lv input for " + BlockName); + + // Run the DAG combiner in post-type-legalize mode. + if (TimePassesIsEnabled) { + NamedRegionTimer T("DAG Combining after legalize vectors", GroupName); + CurDAG->Combine(NoIllegalOperations, *AA, OptLevel); + } else { + CurDAG->Combine(NoIllegalOperations, *AA, OptLevel); + } + + DEBUG(errs() << "Optimized vector-legalized selection DAG:\n"); + DEBUG(CurDAG->dump()); + } + } + + if (ViewLegalizeDAGs) CurDAG->viewGraph("legalize input for " + BlockName); + + if (TimePassesIsEnabled) { + NamedRegionTimer T("DAG Legalization", GroupName); + CurDAG->Legalize(DisableLegalizeTypes, OptLevel); + } else { + CurDAG->Legalize(DisableLegalizeTypes, OptLevel); + } + + DEBUG(errs() << "Legalized selection DAG:\n"); + DEBUG(CurDAG->dump()); + + if (ViewDAGCombine2) CurDAG->viewGraph("dag-combine2 input for " + BlockName); + + // Run the DAG combiner in post-legalize mode. + if (TimePassesIsEnabled) { + NamedRegionTimer T("DAG Combining 2", GroupName); + CurDAG->Combine(NoIllegalOperations, *AA, OptLevel); + } else { + CurDAG->Combine(NoIllegalOperations, *AA, OptLevel); + } + + DEBUG(errs() << "Optimized legalized selection DAG:\n"); + DEBUG(CurDAG->dump()); + + if (ViewISelDAGs) CurDAG->viewGraph("isel input for " + BlockName); + + if (OptLevel != CodeGenOpt::None) + ComputeLiveOutVRegInfo(); + + // Third, instruction select all of the operations to machine code, adding the + // code to the MachineBasicBlock. + if (TimePassesIsEnabled) { + NamedRegionTimer T("Instruction Selection", GroupName); + InstructionSelect(); + } else { + InstructionSelect(); + } + + DEBUG(errs() << "Selected selection DAG:\n"); + DEBUG(CurDAG->dump()); + + if (ViewSchedDAGs) CurDAG->viewGraph("scheduler input for " + BlockName); + + // Schedule machine code. + ScheduleDAGSDNodes *Scheduler = CreateScheduler(); + if (TimePassesIsEnabled) { + NamedRegionTimer T("Instruction Scheduling", GroupName); + Scheduler->Run(CurDAG, BB, BB->end()); + } else { + Scheduler->Run(CurDAG, BB, BB->end()); + } + + if (ViewSUnitDAGs) Scheduler->viewGraph(); + + // Emit machine code to BB. This can change 'BB' to the last block being + // inserted into. + if (TimePassesIsEnabled) { + NamedRegionTimer T("Instruction Creation", GroupName); + BB = Scheduler->EmitSchedule(&SDB->EdgeMapping); + } else { + BB = Scheduler->EmitSchedule(&SDB->EdgeMapping); + } + + // Free the scheduler state. + if (TimePassesIsEnabled) { + NamedRegionTimer T("Instruction Scheduling Cleanup", GroupName); + delete Scheduler; + } else { + delete Scheduler; + } + + DEBUG(errs() << "Selected machine code:\n"); + DEBUG(BB->dump()); +} + +void SelectionDAGISel::SelectAllBasicBlocks(Function &Fn, + MachineFunction &MF, + MachineModuleInfo *MMI, + DwarfWriter *DW, + const TargetInstrInfo &TII) { + // Initialize the Fast-ISel state, if needed. + FastISel *FastIS = 0; + if (EnableFastISel) + FastIS = TLI.createFastISel(MF, MMI, DW, + FuncInfo->ValueMap, + FuncInfo->MBBMap, + FuncInfo->StaticAllocaMap +#ifndef NDEBUG + , FuncInfo->CatchInfoLost +#endif + ); + + MetadataContext &TheMetadata = Fn.getContext().getMetadata(); + unsigned MDDbgKind = TheMetadata.getMDKind("dbg"); + + // Iterate over all basic blocks in the function. + for (Function::iterator I = Fn.begin(), E = Fn.end(); I != E; ++I) { + BasicBlock *LLVMBB = &*I; + BB = FuncInfo->MBBMap[LLVMBB]; + + BasicBlock::iterator const Begin = LLVMBB->begin(); + BasicBlock::iterator const End = LLVMBB->end(); + BasicBlock::iterator BI = Begin; + + // Lower any arguments needed in this block if this is the entry block. + bool SuppressFastISel = false; + if (LLVMBB == &Fn.getEntryBlock()) { + LowerArguments(LLVMBB); + + // If any of the arguments has the byval attribute, forgo + // fast-isel in the entry block. + if (FastIS) { + unsigned j = 1; + for (Function::arg_iterator I = Fn.arg_begin(), E = Fn.arg_end(); + I != E; ++I, ++j) + if (Fn.paramHasAttr(j, Attribute::ByVal)) { + if (EnableFastISelVerbose || EnableFastISelAbort) + errs() << "FastISel skips entry block due to byval argument\n"; + SuppressFastISel = true; + break; + } + } + } + + if (MMI && BB->isLandingPad()) { + // Add a label to mark the beginning of the landing pad. Deletion of the + // landing pad can thus be detected via the MachineModuleInfo. + unsigned LabelID = MMI->addLandingPad(BB); + + const TargetInstrDesc &II = TII.get(TargetInstrInfo::EH_LABEL); + BuildMI(BB, SDB->getCurDebugLoc(), II).addImm(LabelID); + + // Mark exception register as live in. + unsigned Reg = TLI.getExceptionAddressRegister(); + if (Reg) BB->addLiveIn(Reg); + + // Mark exception selector register as live in. + Reg = TLI.getExceptionSelectorRegister(); + if (Reg) BB->addLiveIn(Reg); + + // FIXME: Hack around an exception handling flaw (PR1508): the personality + // function and list of typeids logically belong to the invoke (or, if you + // like, the basic block containing the invoke), and need to be associated + // with it in the dwarf exception handling tables. Currently however the + // information is provided by an intrinsic (eh.selector) that can be moved + // to unexpected places by the optimizers: if the unwind edge is critical, + // then breaking it can result in the intrinsics being in the successor of + // the landing pad, not the landing pad itself. This results in exceptions + // not being caught because no typeids are associated with the invoke. + // This may not be the only way things can go wrong, but it is the only way + // we try to work around for the moment. + BranchInst *Br = dyn_cast(LLVMBB->getTerminator()); + + if (Br && Br->isUnconditional()) { // Critical edge? + BasicBlock::iterator I, E; + for (I = LLVMBB->begin(), E = --LLVMBB->end(); I != E; ++I) + if (isa(I)) + break; + + if (I == E) + // No catch info found - try to extract some from the successor. + CopyCatchInfo(Br->getSuccessor(0), LLVMBB, MMI, *FuncInfo); + } + } + + // Before doing SelectionDAG ISel, see if FastISel has been requested. + if (FastIS && !SuppressFastISel) { + // Emit code for any incoming arguments. This must happen before + // beginning FastISel on the entry block. + if (LLVMBB == &Fn.getEntryBlock()) { + CurDAG->setRoot(SDB->getControlRoot()); + CodeGenAndEmitDAG(); + SDB->clear(); + } + FastIS->startNewBlock(BB); + // Do FastISel on as many instructions as possible. + for (; BI != End; ++BI) { + if (MDDbgKind) { + // Update DebugLoc if debug information is attached with this + // instruction. + if (!isa(BI)) + if (MDNode *Dbg = TheMetadata.getMD(MDDbgKind, BI)) { + DILocation DILoc(Dbg); + DebugLoc Loc = ExtractDebugLocation(DILoc, + MF.getDebugLocInfo()); + FastIS->setCurDebugLoc(Loc); + if (MF.getDefaultDebugLoc().isUnknown()) + MF.setDefaultDebugLoc(Loc); + } + } + + // Just before the terminator instruction, insert instructions to + // feed PHI nodes in successor blocks. + if (isa(BI)) + if (!HandlePHINodesInSuccessorBlocksFast(LLVMBB, FastIS)) { + if (EnableFastISelVerbose || EnableFastISelAbort) { + errs() << "FastISel miss: "; + BI->dump(); + } + assert(!EnableFastISelAbort && + "FastISel didn't handle a PHI in a successor"); + break; + } + + // First try normal tablegen-generated "fast" selection. + if (FastIS->SelectInstruction(BI)) + continue; + + // Next, try calling the target to attempt to handle the instruction. + if (FastIS->TargetSelectInstruction(BI)) + continue; + + // Then handle certain instructions as single-LLVM-Instruction blocks. + if (isa(BI)) { + if (EnableFastISelVerbose || EnableFastISelAbort) { + errs() << "FastISel missed call: "; + BI->dump(); + } + + if (BI->getType() != Type::getVoidTy(*CurDAG->getContext())) { + unsigned &R = FuncInfo->ValueMap[BI]; + if (!R) + R = FuncInfo->CreateRegForValue(BI); + } + + SDB->setCurDebugLoc(FastIS->getCurDebugLoc()); + + bool HadTailCall = false; + SelectBasicBlock(LLVMBB, BI, next(BI), HadTailCall); + + // If the call was emitted as a tail call, we're done with the block. + if (HadTailCall) { + BI = End; + break; + } + + // If the instruction was codegen'd with multiple blocks, + // inform the FastISel object where to resume inserting. + FastIS->setCurrentBlock(BB); + continue; + } + + // Otherwise, give up on FastISel for the rest of the block. + // For now, be a little lenient about non-branch terminators. + if (!isa(BI) || isa(BI)) { + if (EnableFastISelVerbose || EnableFastISelAbort) { + errs() << "FastISel miss: "; + BI->dump(); + } + if (EnableFastISelAbort) + // The "fast" selector couldn't handle something and bailed. + // For the purpose of debugging, just abort. + llvm_unreachable("FastISel didn't select the entire block"); + } + break; + } + } + + // Run SelectionDAG instruction selection on the remainder of the block + // not handled by FastISel. If FastISel is not run, this is the entire + // block. + if (BI != End) { + // If FastISel is run and it has known DebugLoc then use it. + if (FastIS && !FastIS->getCurDebugLoc().isUnknown()) + SDB->setCurDebugLoc(FastIS->getCurDebugLoc()); + bool HadTailCall; + SelectBasicBlock(LLVMBB, BI, End, HadTailCall); + } + + FinishBasicBlock(); + } + + delete FastIS; +} + +void +SelectionDAGISel::FinishBasicBlock() { + + DEBUG(errs() << "Target-post-processed machine code:\n"); + DEBUG(BB->dump()); + + DEBUG(errs() << "Total amount of phi nodes to update: " + << SDB->PHINodesToUpdate.size() << "\n"); + DEBUG(for (unsigned i = 0, e = SDB->PHINodesToUpdate.size(); i != e; ++i) + errs() << "Node " << i << " : (" + << SDB->PHINodesToUpdate[i].first + << ", " << SDB->PHINodesToUpdate[i].second << ")\n"); + + // Next, now that we know what the last MBB the LLVM BB expanded is, update + // PHI nodes in successors. + if (SDB->SwitchCases.empty() && + SDB->JTCases.empty() && + SDB->BitTestCases.empty()) { + for (unsigned i = 0, e = SDB->PHINodesToUpdate.size(); i != e; ++i) { + MachineInstr *PHI = SDB->PHINodesToUpdate[i].first; + assert(PHI->getOpcode() == TargetInstrInfo::PHI && + "This is not a machine PHI node that we are updating!"); + PHI->addOperand(MachineOperand::CreateReg(SDB->PHINodesToUpdate[i].second, + false)); + PHI->addOperand(MachineOperand::CreateMBB(BB)); + } + SDB->PHINodesToUpdate.clear(); + return; + } + + for (unsigned i = 0, e = SDB->BitTestCases.size(); i != e; ++i) { + // Lower header first, if it wasn't already lowered + if (!SDB->BitTestCases[i].Emitted) { + // Set the current basic block to the mbb we wish to insert the code into + BB = SDB->BitTestCases[i].Parent; + SDB->setCurrentBasicBlock(BB); + // Emit the code + SDB->visitBitTestHeader(SDB->BitTestCases[i]); + CurDAG->setRoot(SDB->getRoot()); + CodeGenAndEmitDAG(); + SDB->clear(); + } + + for (unsigned j = 0, ej = SDB->BitTestCases[i].Cases.size(); j != ej; ++j) { + // Set the current basic block to the mbb we wish to insert the code into + BB = SDB->BitTestCases[i].Cases[j].ThisBB; + SDB->setCurrentBasicBlock(BB); + // Emit the code + if (j+1 != ej) + SDB->visitBitTestCase(SDB->BitTestCases[i].Cases[j+1].ThisBB, + SDB->BitTestCases[i].Reg, + SDB->BitTestCases[i].Cases[j]); + else + SDB->visitBitTestCase(SDB->BitTestCases[i].Default, + SDB->BitTestCases[i].Reg, + SDB->BitTestCases[i].Cases[j]); + + + CurDAG->setRoot(SDB->getRoot()); + CodeGenAndEmitDAG(); + SDB->clear(); + } + + // Update PHI Nodes + for (unsigned pi = 0, pe = SDB->PHINodesToUpdate.size(); pi != pe; ++pi) { + MachineInstr *PHI = SDB->PHINodesToUpdate[pi].first; + MachineBasicBlock *PHIBB = PHI->getParent(); + assert(PHI->getOpcode() == TargetInstrInfo::PHI && + "This is not a machine PHI node that we are updating!"); + // This is "default" BB. We have two jumps to it. From "header" BB and + // from last "case" BB. + if (PHIBB == SDB->BitTestCases[i].Default) { + PHI->addOperand(MachineOperand::CreateReg(SDB->PHINodesToUpdate[pi].second, + false)); + PHI->addOperand(MachineOperand::CreateMBB(SDB->BitTestCases[i].Parent)); + PHI->addOperand(MachineOperand::CreateReg(SDB->PHINodesToUpdate[pi].second, + false)); + PHI->addOperand(MachineOperand::CreateMBB(SDB->BitTestCases[i].Cases. + back().ThisBB)); + } + // One of "cases" BB. + for (unsigned j = 0, ej = SDB->BitTestCases[i].Cases.size(); + j != ej; ++j) { + MachineBasicBlock* cBB = SDB->BitTestCases[i].Cases[j].ThisBB; + if (cBB->succ_end() != + std::find(cBB->succ_begin(),cBB->succ_end(), PHIBB)) { + PHI->addOperand(MachineOperand::CreateReg(SDB->PHINodesToUpdate[pi].second, + false)); + PHI->addOperand(MachineOperand::CreateMBB(cBB)); + } + } + } + } + SDB->BitTestCases.clear(); + + // If the JumpTable record is filled in, then we need to emit a jump table. + // Updating the PHI nodes is tricky in this case, since we need to determine + // whether the PHI is a successor of the range check MBB or the jump table MBB + for (unsigned i = 0, e = SDB->JTCases.size(); i != e; ++i) { + // Lower header first, if it wasn't already lowered + if (!SDB->JTCases[i].first.Emitted) { + // Set the current basic block to the mbb we wish to insert the code into + BB = SDB->JTCases[i].first.HeaderBB; + SDB->setCurrentBasicBlock(BB); + // Emit the code + SDB->visitJumpTableHeader(SDB->JTCases[i].second, SDB->JTCases[i].first); + CurDAG->setRoot(SDB->getRoot()); + CodeGenAndEmitDAG(); + SDB->clear(); + } + + // Set the current basic block to the mbb we wish to insert the code into + BB = SDB->JTCases[i].second.MBB; + SDB->setCurrentBasicBlock(BB); + // Emit the code + SDB->visitJumpTable(SDB->JTCases[i].second); + CurDAG->setRoot(SDB->getRoot()); + CodeGenAndEmitDAG(); + SDB->clear(); + + // Update PHI Nodes + for (unsigned pi = 0, pe = SDB->PHINodesToUpdate.size(); pi != pe; ++pi) { + MachineInstr *PHI = SDB->PHINodesToUpdate[pi].first; + MachineBasicBlock *PHIBB = PHI->getParent(); + assert(PHI->getOpcode() == TargetInstrInfo::PHI && + "This is not a machine PHI node that we are updating!"); + // "default" BB. We can go there only from header BB. + if (PHIBB == SDB->JTCases[i].second.Default) { + PHI->addOperand + (MachineOperand::CreateReg(SDB->PHINodesToUpdate[pi].second, false)); + PHI->addOperand + (MachineOperand::CreateMBB(SDB->JTCases[i].first.HeaderBB)); + } + // JT BB. Just iterate over successors here + if (BB->succ_end() != std::find(BB->succ_begin(),BB->succ_end(), PHIBB)) { + PHI->addOperand + (MachineOperand::CreateReg(SDB->PHINodesToUpdate[pi].second, false)); + PHI->addOperand(MachineOperand::CreateMBB(BB)); + } + } + } + SDB->JTCases.clear(); + + // If the switch block involved a branch to one of the actual successors, we + // need to update PHI nodes in that block. + for (unsigned i = 0, e = SDB->PHINodesToUpdate.size(); i != e; ++i) { + MachineInstr *PHI = SDB->PHINodesToUpdate[i].first; + assert(PHI->getOpcode() == TargetInstrInfo::PHI && + "This is not a machine PHI node that we are updating!"); + if (BB->isSuccessor(PHI->getParent())) { + PHI->addOperand(MachineOperand::CreateReg(SDB->PHINodesToUpdate[i].second, + false)); + PHI->addOperand(MachineOperand::CreateMBB(BB)); + } + } + + // If we generated any switch lowering information, build and codegen any + // additional DAGs necessary. + for (unsigned i = 0, e = SDB->SwitchCases.size(); i != e; ++i) { + // Set the current basic block to the mbb we wish to insert the code into + MachineBasicBlock *ThisBB = BB = SDB->SwitchCases[i].ThisBB; + SDB->setCurrentBasicBlock(BB); + + // Emit the code + SDB->visitSwitchCase(SDB->SwitchCases[i]); + CurDAG->setRoot(SDB->getRoot()); + CodeGenAndEmitDAG(); + + // Handle any PHI nodes in successors of this chunk, as if we were coming + // from the original BB before switch expansion. Note that PHI nodes can + // occur multiple times in PHINodesToUpdate. We have to be very careful to + // handle them the right number of times. + while ((BB = SDB->SwitchCases[i].TrueBB)) { // Handle LHS and RHS. + // If new BB's are created during scheduling, the edges may have been + // updated. That is, the edge from ThisBB to BB may have been split and + // BB's predecessor is now another block. + DenseMap::iterator EI = + SDB->EdgeMapping.find(BB); + if (EI != SDB->EdgeMapping.end()) + ThisBB = EI->second; + for (MachineBasicBlock::iterator Phi = BB->begin(); + Phi != BB->end() && Phi->getOpcode() == TargetInstrInfo::PHI; ++Phi){ + // This value for this PHI node is recorded in PHINodesToUpdate, get it. + for (unsigned pn = 0; ; ++pn) { + assert(pn != SDB->PHINodesToUpdate.size() && + "Didn't find PHI entry!"); + if (SDB->PHINodesToUpdate[pn].first == Phi) { + Phi->addOperand(MachineOperand::CreateReg(SDB->PHINodesToUpdate[pn]. + second, false)); + Phi->addOperand(MachineOperand::CreateMBB(ThisBB)); + break; + } + } + } + + // Don't process RHS if same block as LHS. + if (BB == SDB->SwitchCases[i].FalseBB) + SDB->SwitchCases[i].FalseBB = 0; + + // If we haven't handled the RHS, do so now. Otherwise, we're done. + SDB->SwitchCases[i].TrueBB = SDB->SwitchCases[i].FalseBB; + SDB->SwitchCases[i].FalseBB = 0; + } + assert(SDB->SwitchCases[i].TrueBB == 0 && SDB->SwitchCases[i].FalseBB == 0); + SDB->clear(); + } + SDB->SwitchCases.clear(); + + SDB->PHINodesToUpdate.clear(); +} + + +/// Create the scheduler. If a specific scheduler was specified +/// via the SchedulerRegistry, use it, otherwise select the +/// one preferred by the target. +/// +ScheduleDAGSDNodes *SelectionDAGISel::CreateScheduler() { + RegisterScheduler::FunctionPassCtor Ctor = RegisterScheduler::getDefault(); + + if (!Ctor) { + Ctor = ISHeuristic; + RegisterScheduler::setDefault(Ctor); + } + + return Ctor(this, OptLevel); +} + +ScheduleHazardRecognizer *SelectionDAGISel::CreateTargetHazardRecognizer() { + return new ScheduleHazardRecognizer(); +} + +//===----------------------------------------------------------------------===// +// Helper functions used by the generated instruction selector. +//===----------------------------------------------------------------------===// +// Calls to these methods are generated by tblgen. + +/// CheckAndMask - The isel is trying to match something like (and X, 255). If +/// the dag combiner simplified the 255, we still want to match. RHS is the +/// actual value in the DAG on the RHS of an AND, and DesiredMaskS is the value +/// specified in the .td file (e.g. 255). +bool SelectionDAGISel::CheckAndMask(SDValue LHS, ConstantSDNode *RHS, + int64_t DesiredMaskS) const { + const APInt &ActualMask = RHS->getAPIntValue(); + const APInt &DesiredMask = APInt(LHS.getValueSizeInBits(), DesiredMaskS); + + // If the actual mask exactly matches, success! + if (ActualMask == DesiredMask) + return true; + + // If the actual AND mask is allowing unallowed bits, this doesn't match. + if (ActualMask.intersects(~DesiredMask)) + return false; + + // Otherwise, the DAG Combiner may have proven that the value coming in is + // either already zero or is not demanded. Check for known zero input bits. + APInt NeededMask = DesiredMask & ~ActualMask; + if (CurDAG->MaskedValueIsZero(LHS, NeededMask)) + return true; + + // TODO: check to see if missing bits are just not demanded. + + // Otherwise, this pattern doesn't match. + return false; +} + +/// CheckOrMask - The isel is trying to match something like (or X, 255). If +/// the dag combiner simplified the 255, we still want to match. RHS is the +/// actual value in the DAG on the RHS of an OR, and DesiredMaskS is the value +/// specified in the .td file (e.g. 255). +bool SelectionDAGISel::CheckOrMask(SDValue LHS, ConstantSDNode *RHS, + int64_t DesiredMaskS) const { + const APInt &ActualMask = RHS->getAPIntValue(); + const APInt &DesiredMask = APInt(LHS.getValueSizeInBits(), DesiredMaskS); + + // If the actual mask exactly matches, success! + if (ActualMask == DesiredMask) + return true; + + // If the actual AND mask is allowing unallowed bits, this doesn't match. + if (ActualMask.intersects(~DesiredMask)) + return false; + + // Otherwise, the DAG Combiner may have proven that the value coming in is + // either already zero or is not demanded. Check for known zero input bits. + APInt NeededMask = DesiredMask & ~ActualMask; + + APInt KnownZero, KnownOne; + CurDAG->ComputeMaskedBits(LHS, NeededMask, KnownZero, KnownOne); + + // If all the missing bits in the or are already known to be set, match! + if ((NeededMask & KnownOne) == NeededMask) + return true; + + // TODO: check to see if missing bits are just not demanded. + + // Otherwise, this pattern doesn't match. + return false; +} + + +/// SelectInlineAsmMemoryOperands - Calls to this are automatically generated +/// by tblgen. Others should not call it. +void SelectionDAGISel:: +SelectInlineAsmMemoryOperands(std::vector &Ops) { + std::vector InOps; + std::swap(InOps, Ops); + + Ops.push_back(InOps[0]); // input chain. + Ops.push_back(InOps[1]); // input asm string. + + unsigned i = 2, e = InOps.size(); + if (InOps[e-1].getValueType() == MVT::Flag) + --e; // Don't process a flag operand if it is here. + + while (i != e) { + unsigned Flags = cast(InOps[i])->getZExtValue(); + if ((Flags & 7) != 4 /*MEM*/) { + // Just skip over this operand, copying the operands verbatim. + Ops.insert(Ops.end(), InOps.begin()+i, + InOps.begin()+i+InlineAsm::getNumOperandRegisters(Flags) + 1); + i += InlineAsm::getNumOperandRegisters(Flags) + 1; + } else { + assert(InlineAsm::getNumOperandRegisters(Flags) == 1 && + "Memory operand with multiple values?"); + // Otherwise, this is a memory operand. Ask the target to select it. + std::vector SelOps; + if (SelectInlineAsmMemoryOperand(InOps[i+1], 'm', SelOps)) { + llvm_report_error("Could not match memory address. Inline asm" + " failure!"); + } + + // Add this to the output node. + EVT IntPtrTy = TLI.getPointerTy(); + Ops.push_back(CurDAG->getTargetConstant(4/*MEM*/ | (SelOps.size()<< 3), + IntPtrTy)); + Ops.insert(Ops.end(), SelOps.begin(), SelOps.end()); + i += 2; + } + } + + // Add the flag input back if present. + if (e != InOps.size()) + Ops.push_back(InOps.back()); +} + +/// findFlagUse - Return use of EVT::Flag value produced by the specified +/// SDNode. +/// +static SDNode *findFlagUse(SDNode *N) { + unsigned FlagResNo = N->getNumValues()-1; + for (SDNode::use_iterator I = N->use_begin(), E = N->use_end(); I != E; ++I) { + SDUse &Use = I.getUse(); + if (Use.getResNo() == FlagResNo) + return Use.getUser(); + } + return NULL; +} + +/// findNonImmUse - Return true if "Use" is a non-immediate use of "Def". +/// This function recursively traverses up the operand chain, ignoring +/// certain nodes. +static bool findNonImmUse(SDNode *Use, SDNode* Def, SDNode *ImmedUse, + SDNode *Root, + SmallPtrSet &Visited) { + if (Use->getNodeId() < Def->getNodeId() || + !Visited.insert(Use)) + return false; + + for (unsigned i = 0, e = Use->getNumOperands(); i != e; ++i) { + SDNode *N = Use->getOperand(i).getNode(); + if (N == Def) { + if (Use == ImmedUse || Use == Root) + continue; // We are not looking for immediate use. + assert(N != Root); + return true; + } + + // Traverse up the operand chain. + if (findNonImmUse(N, Def, ImmedUse, Root, Visited)) + return true; + } + return false; +} + +/// isNonImmUse - Start searching from Root up the DAG to check is Def can +/// be reached. Return true if that's the case. However, ignore direct uses +/// by ImmedUse (which would be U in the example illustrated in +/// IsLegalAndProfitableToFold) and by Root (which can happen in the store +/// case). +/// FIXME: to be really generic, we should allow direct use by any node +/// that is being folded. But realisticly since we only fold loads which +/// have one non-chain use, we only need to watch out for load/op/store +/// and load/op/cmp case where the root (store / cmp) may reach the load via +/// its chain operand. +static inline bool isNonImmUse(SDNode *Root, SDNode *Def, SDNode *ImmedUse) { + SmallPtrSet Visited; + return findNonImmUse(Root, Def, ImmedUse, Root, Visited); +} + +/// IsLegalAndProfitableToFold - Returns true if the specific operand node N of +/// U can be folded during instruction selection that starts at Root and +/// folding N is profitable. +bool SelectionDAGISel::IsLegalAndProfitableToFold(SDNode *N, SDNode *U, + SDNode *Root) const { + if (OptLevel == CodeGenOpt::None) return false; + + // If Root use can somehow reach N through a path that that doesn't contain + // U then folding N would create a cycle. e.g. In the following + // diagram, Root can reach N through X. If N is folded into into Root, then + // X is both a predecessor and a successor of U. + // + // [N*] // + // ^ ^ // + // / \ // + // [U*] [X]? // + // ^ ^ // + // \ / // + // \ / // + // [Root*] // + // + // * indicates nodes to be folded together. + // + // If Root produces a flag, then it gets (even more) interesting. Since it + // will be "glued" together with its flag use in the scheduler, we need to + // check if it might reach N. + // + // [N*] // + // ^ ^ // + // / \ // + // [U*] [X]? // + // ^ ^ // + // \ \ // + // \ | // + // [Root*] | // + // ^ | // + // f | // + // | / // + // [Y] / // + // ^ / // + // f / // + // | / // + // [FU] // + // + // If FU (flag use) indirectly reaches N (the load), and Root folds N + // (call it Fold), then X is a predecessor of FU and a successor of + // Fold. But since Fold and FU are flagged together, this will create + // a cycle in the scheduling graph. + + EVT VT = Root->getValueType(Root->getNumValues()-1); + while (VT == MVT::Flag) { + SDNode *FU = findFlagUse(Root); + if (FU == NULL) + break; + Root = FU; + VT = Root->getValueType(Root->getNumValues()-1); + } + + return !isNonImmUse(Root, N, U); +} + +SDNode *SelectionDAGISel::Select_INLINEASM(SDValue N) { + std::vector Ops(N.getNode()->op_begin(), N.getNode()->op_end()); + SelectInlineAsmMemoryOperands(Ops); + + std::vector VTs; + VTs.push_back(MVT::Other); + VTs.push_back(MVT::Flag); + SDValue New = CurDAG->getNode(ISD::INLINEASM, N.getDebugLoc(), + VTs, &Ops[0], Ops.size()); + return New.getNode(); +} + +SDNode *SelectionDAGISel::Select_UNDEF(const SDValue &N) { + return CurDAG->SelectNodeTo(N.getNode(), TargetInstrInfo::IMPLICIT_DEF, + N.getValueType()); +} + +SDNode *SelectionDAGISel::Select_DBG_LABEL(const SDValue &N) { + SDValue Chain = N.getOperand(0); + unsigned C = cast(N)->getLabelID(); + SDValue Tmp = CurDAG->getTargetConstant(C, MVT::i32); + return CurDAG->SelectNodeTo(N.getNode(), TargetInstrInfo::DBG_LABEL, + MVT::Other, Tmp, Chain); +} + +SDNode *SelectionDAGISel::Select_EH_LABEL(const SDValue &N) { + SDValue Chain = N.getOperand(0); + unsigned C = cast(N)->getLabelID(); + SDValue Tmp = CurDAG->getTargetConstant(C, MVT::i32); + return CurDAG->SelectNodeTo(N.getNode(), TargetInstrInfo::EH_LABEL, + MVT::Other, Tmp, Chain); +} + +void SelectionDAGISel::CannotYetSelect(SDValue N) { + std::string msg; + raw_string_ostream Msg(msg); + Msg << "Cannot yet select: "; + N.getNode()->print(Msg, CurDAG); + llvm_report_error(Msg.str()); +} + +void SelectionDAGISel::CannotYetSelectIntrinsic(SDValue N) { + errs() << "Cannot yet select: "; + unsigned iid = + cast(N.getOperand(N.getOperand(0).getValueType() == MVT::Other))->getZExtValue(); + if (iid < Intrinsic::num_intrinsics) + llvm_report_error("Cannot yet select: intrinsic %" + Intrinsic::getName((Intrinsic::ID)iid)); + else if (const TargetIntrinsicInfo *tii = TM.getIntrinsicInfo()) + llvm_report_error(Twine("Cannot yet select: target intrinsic %") + + tii->getName(iid)); +} + +char SelectionDAGISel::ID = 0; diff --git a/libclamav/c++/llvm/lib/CodeGen/SelectionDAG/SelectionDAGPrinter.cpp b/libclamav/c++/llvm/lib/CodeGen/SelectionDAG/SelectionDAGPrinter.cpp new file mode 100644 index 000000000..ccc5e3c75 --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/SelectionDAG/SelectionDAGPrinter.cpp @@ -0,0 +1,293 @@ +//===-- SelectionDAGPrinter.cpp - Implement SelectionDAG::viewGraph() -----===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This implements the SelectionDAG::viewGraph method. +// +//===----------------------------------------------------------------------===// + +#include "ScheduleDAGSDNodes.h" +#include "llvm/Constants.h" +#include "llvm/Function.h" +#include "llvm/Assembly/Writer.h" +#include "llvm/CodeGen/SelectionDAG.h" +#include "llvm/CodeGen/MachineConstantPool.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/CodeGen/PseudoSourceValue.h" +#include "llvm/Analysis/DebugInfo.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/GraphWriter.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/ADT/DenseSet.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/Config/config.h" +#include +using namespace llvm; + +namespace llvm { + template<> + struct DOTGraphTraits : public DefaultDOTGraphTraits { + static bool hasEdgeDestLabels() { + return true; + } + + static unsigned numEdgeDestLabels(const void *Node) { + return ((const SDNode *) Node)->getNumValues(); + } + + static std::string getEdgeDestLabel(const void *Node, unsigned i) { + return ((const SDNode *) Node)->getValueType(i).getEVTString(); + } + + /// edgeTargetsEdgeSource - This method returns true if this outgoing edge + /// should actually target another edge source, not a node. If this method is + /// implemented, getEdgeTarget should be implemented. + template + static bool edgeTargetsEdgeSource(const void *Node, EdgeIter I) { + return true; + } + + /// getEdgeTarget - If edgeTargetsEdgeSource returns true, this method is + /// called to determine which outgoing edge of Node is the target of this + /// edge. + template + static EdgeIter getEdgeTarget(const void *Node, EdgeIter I) { + SDNode *TargetNode = *I; + SDNodeIterator NI = SDNodeIterator::begin(TargetNode); + std::advance(NI, I.getNode()->getOperand(I.getOperand()).getResNo()); + return NI; + } + + static std::string getGraphName(const SelectionDAG *G) { + return G->getMachineFunction().getFunction()->getName(); + } + + static bool renderGraphFromBottomUp() { + return true; + } + + static bool hasNodeAddressLabel(const SDNode *Node, + const SelectionDAG *Graph) { + return true; + } + + /// If you want to override the dot attributes printed for a particular + /// edge, override this method. + template + static std::string getEdgeAttributes(const void *Node, EdgeIter EI) { + SDValue Op = EI.getNode()->getOperand(EI.getOperand()); + EVT VT = Op.getValueType(); + if (VT == MVT::Flag) + return "color=red,style=bold"; + else if (VT == MVT::Other) + return "color=blue,style=dashed"; + return ""; + } + + + static std::string getNodeLabel(const SDNode *Node, + const SelectionDAG *Graph, + bool ShortNames); + static std::string getNodeAttributes(const SDNode *N, + const SelectionDAG *Graph) { +#ifndef NDEBUG + const std::string &Attrs = Graph->getGraphAttrs(N); + if (!Attrs.empty()) { + if (Attrs.find("shape=") == std::string::npos) + return std::string("shape=Mrecord,") + Attrs; + else + return Attrs; + } +#endif + return "shape=Mrecord"; + } + + static void addCustomGraphFeatures(SelectionDAG *G, + GraphWriter &GW) { + GW.emitSimpleNode(0, "plaintext=circle", "GraphRoot"); + if (G->getRoot().getNode()) + GW.emitEdge(0, -1, G->getRoot().getNode(), G->getRoot().getResNo(), + "color=blue,style=dashed"); + } + }; +} + +std::string DOTGraphTraits::getNodeLabel(const SDNode *Node, + const SelectionDAG *G, + bool ShortNames) { + std::string Result = Node->getOperationName(G); + { + raw_string_ostream OS(Result); + Node->print_details(OS, G); + } + return Result; +} + + +/// viewGraph - Pop up a ghostview window with the reachable parts of the DAG +/// rendered using 'dot'. +/// +void SelectionDAG::viewGraph(const std::string &Title) { +// This code is only for debugging! +#ifndef NDEBUG + ViewGraph(this, "dag." + getMachineFunction().getFunction()->getNameStr(), + false, Title); +#else + errs() << "SelectionDAG::viewGraph is only available in debug builds on " + << "systems with Graphviz or gv!\n"; +#endif // NDEBUG +} + +// This overload is defined out-of-line here instead of just using a +// default parameter because this is easiest for gdb to call. +void SelectionDAG::viewGraph() { + viewGraph(""); +} + +/// clearGraphAttrs - Clear all previously defined node graph attributes. +/// Intended to be used from a debugging tool (eg. gdb). +void SelectionDAG::clearGraphAttrs() { +#ifndef NDEBUG + NodeGraphAttrs.clear(); +#else + errs() << "SelectionDAG::clearGraphAttrs is only available in debug builds" + << " on systems with Graphviz or gv!\n"; +#endif +} + + +/// setGraphAttrs - Set graph attributes for a node. (eg. "color=red".) +/// +void SelectionDAG::setGraphAttrs(const SDNode *N, const char *Attrs) { +#ifndef NDEBUG + NodeGraphAttrs[N] = Attrs; +#else + errs() << "SelectionDAG::setGraphAttrs is only available in debug builds" + << " on systems with Graphviz or gv!\n"; +#endif +} + + +/// getGraphAttrs - Get graph attributes for a node. (eg. "color=red".) +/// Used from getNodeAttributes. +const std::string SelectionDAG::getGraphAttrs(const SDNode *N) const { +#ifndef NDEBUG + std::map::const_iterator I = + NodeGraphAttrs.find(N); + + if (I != NodeGraphAttrs.end()) + return I->second; + else + return ""; +#else + errs() << "SelectionDAG::getGraphAttrs is only available in debug builds" + << " on systems with Graphviz or gv!\n"; + return std::string(""); +#endif +} + +/// setGraphColor - Convenience for setting node color attribute. +/// +void SelectionDAG::setGraphColor(const SDNode *N, const char *Color) { +#ifndef NDEBUG + NodeGraphAttrs[N] = std::string("color=") + Color; +#else + errs() << "SelectionDAG::setGraphColor is only available in debug builds" + << " on systems with Graphviz or gv!\n"; +#endif +} + +/// setSubgraphColorHelper - Implement setSubgraphColor. Return +/// whether we truncated the search. +/// +bool SelectionDAG::setSubgraphColorHelper(SDNode *N, const char *Color, DenseSet &visited, + int level, bool &printed) { + bool hit_limit = false; + +#ifndef NDEBUG + if (level >= 20) { + if (!printed) { + printed = true; + DEBUG(errs() << "setSubgraphColor hit max level\n"); + } + return true; + } + + unsigned oldSize = visited.size(); + visited.insert(N); + if (visited.size() != oldSize) { + setGraphColor(N, Color); + for(SDNodeIterator i = SDNodeIterator::begin(N), iend = SDNodeIterator::end(N); + i != iend; + ++i) { + hit_limit = setSubgraphColorHelper(*i, Color, visited, level+1, printed) || hit_limit; + } + } +#else + errs() << "SelectionDAG::setSubgraphColor is only available in debug builds" + << " on systems with Graphviz or gv!\n"; +#endif + return hit_limit; +} + +/// setSubgraphColor - Convenience for setting subgraph color attribute. +/// +void SelectionDAG::setSubgraphColor(SDNode *N, const char *Color) { +#ifndef NDEBUG + DenseSet visited; + bool printed = false; + if (setSubgraphColorHelper(N, Color, visited, 0, printed)) { + // Visually mark that we hit the limit + if (strcmp(Color, "red") == 0) { + setSubgraphColorHelper(N, "blue", visited, 0, printed); + } + else if (strcmp(Color, "yellow") == 0) { + setSubgraphColorHelper(N, "green", visited, 0, printed); + } + } + +#else + errs() << "SelectionDAG::setSubgraphColor is only available in debug builds" + << " on systems with Graphviz or gv!\n"; +#endif +} + +std::string ScheduleDAGSDNodes::getGraphNodeLabel(const SUnit *SU) const { + std::string s; + raw_string_ostream O(s); + O << "SU(" << SU->NodeNum << "): "; + if (SU->getNode()) { + SmallVector FlaggedNodes; + for (SDNode *N = SU->getNode(); N; N = N->getFlaggedNode()) + FlaggedNodes.push_back(N); + while (!FlaggedNodes.empty()) { + O << DOTGraphTraits::getNodeLabel(FlaggedNodes.back(), + DAG, false); + FlaggedNodes.pop_back(); + if (!FlaggedNodes.empty()) + O << "\n "; + } + } else { + O << "CROSS RC COPY"; + } + return O.str(); +} + +void ScheduleDAGSDNodes::getCustomGraphFeatures(GraphWriter &GW) const { + if (DAG) { + // Draw a special "GraphRoot" node to indicate the root of the graph. + GW.emitSimpleNode(0, "plaintext=circle", "GraphRoot"); + const SDNode *N = DAG->getRoot().getNode(); + if (N && N->getNodeId() != -1) + GW.emitEdge(0, -1, &SUnits[N->getNodeId()], -1, + "color=blue,style=dashed"); + } +} diff --git a/libclamav/c++/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/libclamav/c++/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp new file mode 100644 index 000000000..68bc2d630 --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp @@ -0,0 +1,2676 @@ +//===-- TargetLowering.cpp - Implement the TargetLowering class -----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This implements the TargetLowering class. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Target/TargetLowering.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetLoweringObjectFile.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Target/TargetSubtarget.h" +#include "llvm/GlobalVariable.h" +#include "llvm/DerivedTypes.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/SelectionDAG.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/MathExtras.h" +using namespace llvm; + +namespace llvm { +TLSModel::Model getTLSModel(const GlobalValue *GV, Reloc::Model reloc) { + bool isLocal = GV->hasLocalLinkage(); + bool isDeclaration = GV->isDeclaration(); + // FIXME: what should we do for protected and internal visibility? + // For variables, is internal different from hidden? + bool isHidden = GV->hasHiddenVisibility(); + + if (reloc == Reloc::PIC_) { + if (isLocal || isHidden) + return TLSModel::LocalDynamic; + else + return TLSModel::GeneralDynamic; + } else { + if (!isDeclaration || isHidden) + return TLSModel::LocalExec; + else + return TLSModel::InitialExec; + } +} +} + +/// InitLibcallNames - Set default libcall names. +/// +static void InitLibcallNames(const char **Names) { + Names[RTLIB::SHL_I16] = "__ashlhi3"; + Names[RTLIB::SHL_I32] = "__ashlsi3"; + Names[RTLIB::SHL_I64] = "__ashldi3"; + Names[RTLIB::SHL_I128] = "__ashlti3"; + Names[RTLIB::SRL_I16] = "__lshrhi3"; + Names[RTLIB::SRL_I32] = "__lshrsi3"; + Names[RTLIB::SRL_I64] = "__lshrdi3"; + Names[RTLIB::SRL_I128] = "__lshrti3"; + Names[RTLIB::SRA_I16] = "__ashrhi3"; + Names[RTLIB::SRA_I32] = "__ashrsi3"; + Names[RTLIB::SRA_I64] = "__ashrdi3"; + Names[RTLIB::SRA_I128] = "__ashrti3"; + Names[RTLIB::MUL_I8] = "__mulqi3"; + Names[RTLIB::MUL_I16] = "__mulhi3"; + Names[RTLIB::MUL_I32] = "__mulsi3"; + Names[RTLIB::MUL_I64] = "__muldi3"; + Names[RTLIB::MUL_I128] = "__multi3"; + Names[RTLIB::SDIV_I8] = "__divqi3"; + Names[RTLIB::SDIV_I16] = "__divhi3"; + Names[RTLIB::SDIV_I32] = "__divsi3"; + Names[RTLIB::SDIV_I64] = "__divdi3"; + Names[RTLIB::SDIV_I128] = "__divti3"; + Names[RTLIB::UDIV_I8] = "__udivqi3"; + Names[RTLIB::UDIV_I16] = "__udivhi3"; + Names[RTLIB::UDIV_I32] = "__udivsi3"; + Names[RTLIB::UDIV_I64] = "__udivdi3"; + Names[RTLIB::UDIV_I128] = "__udivti3"; + Names[RTLIB::SREM_I8] = "__modqi3"; + Names[RTLIB::SREM_I16] = "__modhi3"; + Names[RTLIB::SREM_I32] = "__modsi3"; + Names[RTLIB::SREM_I64] = "__moddi3"; + Names[RTLIB::SREM_I128] = "__modti3"; + Names[RTLIB::UREM_I8] = "__umodqi3"; + Names[RTLIB::UREM_I16] = "__umodhi3"; + Names[RTLIB::UREM_I32] = "__umodsi3"; + Names[RTLIB::UREM_I64] = "__umoddi3"; + Names[RTLIB::UREM_I128] = "__umodti3"; + Names[RTLIB::NEG_I32] = "__negsi2"; + Names[RTLIB::NEG_I64] = "__negdi2"; + Names[RTLIB::ADD_F32] = "__addsf3"; + Names[RTLIB::ADD_F64] = "__adddf3"; + Names[RTLIB::ADD_F80] = "__addxf3"; + Names[RTLIB::ADD_PPCF128] = "__gcc_qadd"; + Names[RTLIB::SUB_F32] = "__subsf3"; + Names[RTLIB::SUB_F64] = "__subdf3"; + Names[RTLIB::SUB_F80] = "__subxf3"; + Names[RTLIB::SUB_PPCF128] = "__gcc_qsub"; + Names[RTLIB::MUL_F32] = "__mulsf3"; + Names[RTLIB::MUL_F64] = "__muldf3"; + Names[RTLIB::MUL_F80] = "__mulxf3"; + Names[RTLIB::MUL_PPCF128] = "__gcc_qmul"; + Names[RTLIB::DIV_F32] = "__divsf3"; + Names[RTLIB::DIV_F64] = "__divdf3"; + Names[RTLIB::DIV_F80] = "__divxf3"; + Names[RTLIB::DIV_PPCF128] = "__gcc_qdiv"; + Names[RTLIB::REM_F32] = "fmodf"; + Names[RTLIB::REM_F64] = "fmod"; + Names[RTLIB::REM_F80] = "fmodl"; + Names[RTLIB::REM_PPCF128] = "fmodl"; + Names[RTLIB::POWI_F32] = "__powisf2"; + Names[RTLIB::POWI_F64] = "__powidf2"; + Names[RTLIB::POWI_F80] = "__powixf2"; + Names[RTLIB::POWI_PPCF128] = "__powitf2"; + Names[RTLIB::SQRT_F32] = "sqrtf"; + Names[RTLIB::SQRT_F64] = "sqrt"; + Names[RTLIB::SQRT_F80] = "sqrtl"; + Names[RTLIB::SQRT_PPCF128] = "sqrtl"; + Names[RTLIB::LOG_F32] = "logf"; + Names[RTLIB::LOG_F64] = "log"; + Names[RTLIB::LOG_F80] = "logl"; + Names[RTLIB::LOG_PPCF128] = "logl"; + Names[RTLIB::LOG2_F32] = "log2f"; + Names[RTLIB::LOG2_F64] = "log2"; + Names[RTLIB::LOG2_F80] = "log2l"; + Names[RTLIB::LOG2_PPCF128] = "log2l"; + Names[RTLIB::LOG10_F32] = "log10f"; + Names[RTLIB::LOG10_F64] = "log10"; + Names[RTLIB::LOG10_F80] = "log10l"; + Names[RTLIB::LOG10_PPCF128] = "log10l"; + Names[RTLIB::EXP_F32] = "expf"; + Names[RTLIB::EXP_F64] = "exp"; + Names[RTLIB::EXP_F80] = "expl"; + Names[RTLIB::EXP_PPCF128] = "expl"; + Names[RTLIB::EXP2_F32] = "exp2f"; + Names[RTLIB::EXP2_F64] = "exp2"; + Names[RTLIB::EXP2_F80] = "exp2l"; + Names[RTLIB::EXP2_PPCF128] = "exp2l"; + Names[RTLIB::SIN_F32] = "sinf"; + Names[RTLIB::SIN_F64] = "sin"; + Names[RTLIB::SIN_F80] = "sinl"; + Names[RTLIB::SIN_PPCF128] = "sinl"; + Names[RTLIB::COS_F32] = "cosf"; + Names[RTLIB::COS_F64] = "cos"; + Names[RTLIB::COS_F80] = "cosl"; + Names[RTLIB::COS_PPCF128] = "cosl"; + Names[RTLIB::POW_F32] = "powf"; + Names[RTLIB::POW_F64] = "pow"; + Names[RTLIB::POW_F80] = "powl"; + Names[RTLIB::POW_PPCF128] = "powl"; + Names[RTLIB::CEIL_F32] = "ceilf"; + Names[RTLIB::CEIL_F64] = "ceil"; + Names[RTLIB::CEIL_F80] = "ceill"; + Names[RTLIB::CEIL_PPCF128] = "ceill"; + Names[RTLIB::TRUNC_F32] = "truncf"; + Names[RTLIB::TRUNC_F64] = "trunc"; + Names[RTLIB::TRUNC_F80] = "truncl"; + Names[RTLIB::TRUNC_PPCF128] = "truncl"; + Names[RTLIB::RINT_F32] = "rintf"; + Names[RTLIB::RINT_F64] = "rint"; + Names[RTLIB::RINT_F80] = "rintl"; + Names[RTLIB::RINT_PPCF128] = "rintl"; + Names[RTLIB::NEARBYINT_F32] = "nearbyintf"; + Names[RTLIB::NEARBYINT_F64] = "nearbyint"; + Names[RTLIB::NEARBYINT_F80] = "nearbyintl"; + Names[RTLIB::NEARBYINT_PPCF128] = "nearbyintl"; + Names[RTLIB::FLOOR_F32] = "floorf"; + Names[RTLIB::FLOOR_F64] = "floor"; + Names[RTLIB::FLOOR_F80] = "floorl"; + Names[RTLIB::FLOOR_PPCF128] = "floorl"; + Names[RTLIB::FPEXT_F32_F64] = "__extendsfdf2"; + Names[RTLIB::FPROUND_F64_F32] = "__truncdfsf2"; + Names[RTLIB::FPROUND_F80_F32] = "__truncxfsf2"; + Names[RTLIB::FPROUND_PPCF128_F32] = "__trunctfsf2"; + Names[RTLIB::FPROUND_F80_F64] = "__truncxfdf2"; + Names[RTLIB::FPROUND_PPCF128_F64] = "__trunctfdf2"; + Names[RTLIB::FPTOSINT_F32_I8] = "__fixsfi8"; + Names[RTLIB::FPTOSINT_F32_I16] = "__fixsfi16"; + Names[RTLIB::FPTOSINT_F32_I32] = "__fixsfsi"; + Names[RTLIB::FPTOSINT_F32_I64] = "__fixsfdi"; + Names[RTLIB::FPTOSINT_F32_I128] = "__fixsfti"; + Names[RTLIB::FPTOSINT_F64_I32] = "__fixdfsi"; + Names[RTLIB::FPTOSINT_F64_I64] = "__fixdfdi"; + Names[RTLIB::FPTOSINT_F64_I128] = "__fixdfti"; + Names[RTLIB::FPTOSINT_F80_I32] = "__fixxfsi"; + Names[RTLIB::FPTOSINT_F80_I64] = "__fixxfdi"; + Names[RTLIB::FPTOSINT_F80_I128] = "__fixxfti"; + Names[RTLIB::FPTOSINT_PPCF128_I32] = "__fixtfsi"; + Names[RTLIB::FPTOSINT_PPCF128_I64] = "__fixtfdi"; + Names[RTLIB::FPTOSINT_PPCF128_I128] = "__fixtfti"; + Names[RTLIB::FPTOUINT_F32_I8] = "__fixunssfi8"; + Names[RTLIB::FPTOUINT_F32_I16] = "__fixunssfi16"; + Names[RTLIB::FPTOUINT_F32_I32] = "__fixunssfsi"; + Names[RTLIB::FPTOUINT_F32_I64] = "__fixunssfdi"; + Names[RTLIB::FPTOUINT_F32_I128] = "__fixunssfti"; + Names[RTLIB::FPTOUINT_F64_I32] = "__fixunsdfsi"; + Names[RTLIB::FPTOUINT_F64_I64] = "__fixunsdfdi"; + Names[RTLIB::FPTOUINT_F64_I128] = "__fixunsdfti"; + Names[RTLIB::FPTOUINT_F80_I32] = "__fixunsxfsi"; + Names[RTLIB::FPTOUINT_F80_I64] = "__fixunsxfdi"; + Names[RTLIB::FPTOUINT_F80_I128] = "__fixunsxfti"; + Names[RTLIB::FPTOUINT_PPCF128_I32] = "__fixunstfsi"; + Names[RTLIB::FPTOUINT_PPCF128_I64] = "__fixunstfdi"; + Names[RTLIB::FPTOUINT_PPCF128_I128] = "__fixunstfti"; + Names[RTLIB::SINTTOFP_I32_F32] = "__floatsisf"; + Names[RTLIB::SINTTOFP_I32_F64] = "__floatsidf"; + Names[RTLIB::SINTTOFP_I32_F80] = "__floatsixf"; + Names[RTLIB::SINTTOFP_I32_PPCF128] = "__floatsitf"; + Names[RTLIB::SINTTOFP_I64_F32] = "__floatdisf"; + Names[RTLIB::SINTTOFP_I64_F64] = "__floatdidf"; + Names[RTLIB::SINTTOFP_I64_F80] = "__floatdixf"; + Names[RTLIB::SINTTOFP_I64_PPCF128] = "__floatditf"; + Names[RTLIB::SINTTOFP_I128_F32] = "__floattisf"; + Names[RTLIB::SINTTOFP_I128_F64] = "__floattidf"; + Names[RTLIB::SINTTOFP_I128_F80] = "__floattixf"; + Names[RTLIB::SINTTOFP_I128_PPCF128] = "__floattitf"; + Names[RTLIB::UINTTOFP_I32_F32] = "__floatunsisf"; + Names[RTLIB::UINTTOFP_I32_F64] = "__floatunsidf"; + Names[RTLIB::UINTTOFP_I32_F80] = "__floatunsixf"; + Names[RTLIB::UINTTOFP_I32_PPCF128] = "__floatunsitf"; + Names[RTLIB::UINTTOFP_I64_F32] = "__floatundisf"; + Names[RTLIB::UINTTOFP_I64_F64] = "__floatundidf"; + Names[RTLIB::UINTTOFP_I64_F80] = "__floatundixf"; + Names[RTLIB::UINTTOFP_I64_PPCF128] = "__floatunditf"; + Names[RTLIB::UINTTOFP_I128_F32] = "__floatuntisf"; + Names[RTLIB::UINTTOFP_I128_F64] = "__floatuntidf"; + Names[RTLIB::UINTTOFP_I128_F80] = "__floatuntixf"; + Names[RTLIB::UINTTOFP_I128_PPCF128] = "__floatuntitf"; + Names[RTLIB::OEQ_F32] = "__eqsf2"; + Names[RTLIB::OEQ_F64] = "__eqdf2"; + Names[RTLIB::UNE_F32] = "__nesf2"; + Names[RTLIB::UNE_F64] = "__nedf2"; + Names[RTLIB::OGE_F32] = "__gesf2"; + Names[RTLIB::OGE_F64] = "__gedf2"; + Names[RTLIB::OLT_F32] = "__ltsf2"; + Names[RTLIB::OLT_F64] = "__ltdf2"; + Names[RTLIB::OLE_F32] = "__lesf2"; + Names[RTLIB::OLE_F64] = "__ledf2"; + Names[RTLIB::OGT_F32] = "__gtsf2"; + Names[RTLIB::OGT_F64] = "__gtdf2"; + Names[RTLIB::UO_F32] = "__unordsf2"; + Names[RTLIB::UO_F64] = "__unorddf2"; + Names[RTLIB::O_F32] = "__unordsf2"; + Names[RTLIB::O_F64] = "__unorddf2"; + Names[RTLIB::MEMCPY] = "memcpy"; + Names[RTLIB::MEMMOVE] = "memmove"; + Names[RTLIB::MEMSET] = "memset"; + Names[RTLIB::UNWIND_RESUME] = "_Unwind_Resume"; +} + +/// InitLibcallCallingConvs - Set default libcall CallingConvs. +/// +static void InitLibcallCallingConvs(CallingConv::ID *CCs) { + for (int i = 0; i < RTLIB::UNKNOWN_LIBCALL; ++i) { + CCs[i] = CallingConv::C; + } +} + +/// getFPEXT - Return the FPEXT_*_* value for the given types, or +/// UNKNOWN_LIBCALL if there is none. +RTLIB::Libcall RTLIB::getFPEXT(EVT OpVT, EVT RetVT) { + if (OpVT == MVT::f32) { + if (RetVT == MVT::f64) + return FPEXT_F32_F64; + } + return UNKNOWN_LIBCALL; +} + +/// getFPROUND - Return the FPROUND_*_* value for the given types, or +/// UNKNOWN_LIBCALL if there is none. +RTLIB::Libcall RTLIB::getFPROUND(EVT OpVT, EVT RetVT) { + if (RetVT == MVT::f32) { + if (OpVT == MVT::f64) + return FPROUND_F64_F32; + if (OpVT == MVT::f80) + return FPROUND_F80_F32; + if (OpVT == MVT::ppcf128) + return FPROUND_PPCF128_F32; + } else if (RetVT == MVT::f64) { + if (OpVT == MVT::f80) + return FPROUND_F80_F64; + if (OpVT == MVT::ppcf128) + return FPROUND_PPCF128_F64; + } + return UNKNOWN_LIBCALL; +} + +/// getFPTOSINT - Return the FPTOSINT_*_* value for the given types, or +/// UNKNOWN_LIBCALL if there is none. +RTLIB::Libcall RTLIB::getFPTOSINT(EVT OpVT, EVT RetVT) { + if (OpVT == MVT::f32) { + if (RetVT == MVT::i8) + return FPTOSINT_F32_I8; + if (RetVT == MVT::i16) + return FPTOSINT_F32_I16; + if (RetVT == MVT::i32) + return FPTOSINT_F32_I32; + if (RetVT == MVT::i64) + return FPTOSINT_F32_I64; + if (RetVT == MVT::i128) + return FPTOSINT_F32_I128; + } else if (OpVT == MVT::f64) { + if (RetVT == MVT::i32) + return FPTOSINT_F64_I32; + if (RetVT == MVT::i64) + return FPTOSINT_F64_I64; + if (RetVT == MVT::i128) + return FPTOSINT_F64_I128; + } else if (OpVT == MVT::f80) { + if (RetVT == MVT::i32) + return FPTOSINT_F80_I32; + if (RetVT == MVT::i64) + return FPTOSINT_F80_I64; + if (RetVT == MVT::i128) + return FPTOSINT_F80_I128; + } else if (OpVT == MVT::ppcf128) { + if (RetVT == MVT::i32) + return FPTOSINT_PPCF128_I32; + if (RetVT == MVT::i64) + return FPTOSINT_PPCF128_I64; + if (RetVT == MVT::i128) + return FPTOSINT_PPCF128_I128; + } + return UNKNOWN_LIBCALL; +} + +/// getFPTOUINT - Return the FPTOUINT_*_* value for the given types, or +/// UNKNOWN_LIBCALL if there is none. +RTLIB::Libcall RTLIB::getFPTOUINT(EVT OpVT, EVT RetVT) { + if (OpVT == MVT::f32) { + if (RetVT == MVT::i8) + return FPTOUINT_F32_I8; + if (RetVT == MVT::i16) + return FPTOUINT_F32_I16; + if (RetVT == MVT::i32) + return FPTOUINT_F32_I32; + if (RetVT == MVT::i64) + return FPTOUINT_F32_I64; + if (RetVT == MVT::i128) + return FPTOUINT_F32_I128; + } else if (OpVT == MVT::f64) { + if (RetVT == MVT::i32) + return FPTOUINT_F64_I32; + if (RetVT == MVT::i64) + return FPTOUINT_F64_I64; + if (RetVT == MVT::i128) + return FPTOUINT_F64_I128; + } else if (OpVT == MVT::f80) { + if (RetVT == MVT::i32) + return FPTOUINT_F80_I32; + if (RetVT == MVT::i64) + return FPTOUINT_F80_I64; + if (RetVT == MVT::i128) + return FPTOUINT_F80_I128; + } else if (OpVT == MVT::ppcf128) { + if (RetVT == MVT::i32) + return FPTOUINT_PPCF128_I32; + if (RetVT == MVT::i64) + return FPTOUINT_PPCF128_I64; + if (RetVT == MVT::i128) + return FPTOUINT_PPCF128_I128; + } + return UNKNOWN_LIBCALL; +} + +/// getSINTTOFP - Return the SINTTOFP_*_* value for the given types, or +/// UNKNOWN_LIBCALL if there is none. +RTLIB::Libcall RTLIB::getSINTTOFP(EVT OpVT, EVT RetVT) { + if (OpVT == MVT::i32) { + if (RetVT == MVT::f32) + return SINTTOFP_I32_F32; + else if (RetVT == MVT::f64) + return SINTTOFP_I32_F64; + else if (RetVT == MVT::f80) + return SINTTOFP_I32_F80; + else if (RetVT == MVT::ppcf128) + return SINTTOFP_I32_PPCF128; + } else if (OpVT == MVT::i64) { + if (RetVT == MVT::f32) + return SINTTOFP_I64_F32; + else if (RetVT == MVT::f64) + return SINTTOFP_I64_F64; + else if (RetVT == MVT::f80) + return SINTTOFP_I64_F80; + else if (RetVT == MVT::ppcf128) + return SINTTOFP_I64_PPCF128; + } else if (OpVT == MVT::i128) { + if (RetVT == MVT::f32) + return SINTTOFP_I128_F32; + else if (RetVT == MVT::f64) + return SINTTOFP_I128_F64; + else if (RetVT == MVT::f80) + return SINTTOFP_I128_F80; + else if (RetVT == MVT::ppcf128) + return SINTTOFP_I128_PPCF128; + } + return UNKNOWN_LIBCALL; +} + +/// getUINTTOFP - Return the UINTTOFP_*_* value for the given types, or +/// UNKNOWN_LIBCALL if there is none. +RTLIB::Libcall RTLIB::getUINTTOFP(EVT OpVT, EVT RetVT) { + if (OpVT == MVT::i32) { + if (RetVT == MVT::f32) + return UINTTOFP_I32_F32; + else if (RetVT == MVT::f64) + return UINTTOFP_I32_F64; + else if (RetVT == MVT::f80) + return UINTTOFP_I32_F80; + else if (RetVT == MVT::ppcf128) + return UINTTOFP_I32_PPCF128; + } else if (OpVT == MVT::i64) { + if (RetVT == MVT::f32) + return UINTTOFP_I64_F32; + else if (RetVT == MVT::f64) + return UINTTOFP_I64_F64; + else if (RetVT == MVT::f80) + return UINTTOFP_I64_F80; + else if (RetVT == MVT::ppcf128) + return UINTTOFP_I64_PPCF128; + } else if (OpVT == MVT::i128) { + if (RetVT == MVT::f32) + return UINTTOFP_I128_F32; + else if (RetVT == MVT::f64) + return UINTTOFP_I128_F64; + else if (RetVT == MVT::f80) + return UINTTOFP_I128_F80; + else if (RetVT == MVT::ppcf128) + return UINTTOFP_I128_PPCF128; + } + return UNKNOWN_LIBCALL; +} + +/// InitCmpLibcallCCs - Set default comparison libcall CC. +/// +static void InitCmpLibcallCCs(ISD::CondCode *CCs) { + memset(CCs, ISD::SETCC_INVALID, sizeof(ISD::CondCode)*RTLIB::UNKNOWN_LIBCALL); + CCs[RTLIB::OEQ_F32] = ISD::SETEQ; + CCs[RTLIB::OEQ_F64] = ISD::SETEQ; + CCs[RTLIB::UNE_F32] = ISD::SETNE; + CCs[RTLIB::UNE_F64] = ISD::SETNE; + CCs[RTLIB::OGE_F32] = ISD::SETGE; + CCs[RTLIB::OGE_F64] = ISD::SETGE; + CCs[RTLIB::OLT_F32] = ISD::SETLT; + CCs[RTLIB::OLT_F64] = ISD::SETLT; + CCs[RTLIB::OLE_F32] = ISD::SETLE; + CCs[RTLIB::OLE_F64] = ISD::SETLE; + CCs[RTLIB::OGT_F32] = ISD::SETGT; + CCs[RTLIB::OGT_F64] = ISD::SETGT; + CCs[RTLIB::UO_F32] = ISD::SETNE; + CCs[RTLIB::UO_F64] = ISD::SETNE; + CCs[RTLIB::O_F32] = ISD::SETEQ; + CCs[RTLIB::O_F64] = ISD::SETEQ; +} + +/// NOTE: The constructor takes ownership of TLOF. +TargetLowering::TargetLowering(TargetMachine &tm,TargetLoweringObjectFile *tlof) + : TM(tm), TD(TM.getTargetData()), TLOF(*tlof) { + // All operations default to being supported. + memset(OpActions, 0, sizeof(OpActions)); + memset(LoadExtActions, 0, sizeof(LoadExtActions)); + memset(TruncStoreActions, 0, sizeof(TruncStoreActions)); + memset(IndexedModeActions, 0, sizeof(IndexedModeActions)); + memset(ConvertActions, 0, sizeof(ConvertActions)); + memset(CondCodeActions, 0, sizeof(CondCodeActions)); + + // Set default actions for various operations. + for (unsigned VT = 0; VT != (unsigned)MVT::LAST_VALUETYPE; ++VT) { + // Default all indexed load / store to expand. + for (unsigned IM = (unsigned)ISD::PRE_INC; + IM != (unsigned)ISD::LAST_INDEXED_MODE; ++IM) { + setIndexedLoadAction(IM, (MVT::SimpleValueType)VT, Expand); + setIndexedStoreAction(IM, (MVT::SimpleValueType)VT, Expand); + } + + // These operations default to expand. + setOperationAction(ISD::FGETSIGN, (MVT::SimpleValueType)VT, Expand); + setOperationAction(ISD::CONCAT_VECTORS, (MVT::SimpleValueType)VT, Expand); + } + + // Most targets ignore the @llvm.prefetch intrinsic. + setOperationAction(ISD::PREFETCH, MVT::Other, Expand); + + // ConstantFP nodes default to expand. Targets can either change this to + // Legal, in which case all fp constants are legal, or use isFPImmLegal() + // to optimize expansions for certain constants. + setOperationAction(ISD::ConstantFP, MVT::f32, Expand); + setOperationAction(ISD::ConstantFP, MVT::f64, Expand); + setOperationAction(ISD::ConstantFP, MVT::f80, Expand); + + // These library functions default to expand. + setOperationAction(ISD::FLOG , MVT::f64, Expand); + setOperationAction(ISD::FLOG2, MVT::f64, Expand); + setOperationAction(ISD::FLOG10,MVT::f64, Expand); + setOperationAction(ISD::FEXP , MVT::f64, Expand); + setOperationAction(ISD::FEXP2, MVT::f64, Expand); + setOperationAction(ISD::FLOG , MVT::f32, Expand); + setOperationAction(ISD::FLOG2, MVT::f32, Expand); + setOperationAction(ISD::FLOG10,MVT::f32, Expand); + setOperationAction(ISD::FEXP , MVT::f32, Expand); + setOperationAction(ISD::FEXP2, MVT::f32, Expand); + + // Default ISD::TRAP to expand (which turns it into abort). + setOperationAction(ISD::TRAP, MVT::Other, Expand); + + IsLittleEndian = TD->isLittleEndian(); + UsesGlobalOffsetTable = false; + ShiftAmountTy = PointerTy = MVT::getIntegerVT(8*TD->getPointerSize()); + memset(RegClassForVT, 0,MVT::LAST_VALUETYPE*sizeof(TargetRegisterClass*)); + memset(TargetDAGCombineArray, 0, array_lengthof(TargetDAGCombineArray)); + maxStoresPerMemset = maxStoresPerMemcpy = maxStoresPerMemmove = 8; + benefitFromCodePlacementOpt = false; + UseUnderscoreSetJmp = false; + UseUnderscoreLongJmp = false; + SelectIsExpensive = false; + IntDivIsCheap = false; + Pow2DivIsCheap = false; + StackPointerRegisterToSaveRestore = 0; + ExceptionPointerRegister = 0; + ExceptionSelectorRegister = 0; + BooleanContents = UndefinedBooleanContent; + SchedPreferenceInfo = SchedulingForLatency; + JumpBufSize = 0; + JumpBufAlignment = 0; + IfCvtBlockSizeLimit = 2; + IfCvtDupBlockSizeLimit = 0; + PrefLoopAlignment = 0; + + InitLibcallNames(LibcallRoutineNames); + InitCmpLibcallCCs(CmpLibcallCCs); + InitLibcallCallingConvs(LibcallCallingConvs); +} + +TargetLowering::~TargetLowering() { + delete &TLOF; +} + +static unsigned getVectorTypeBreakdownMVT(MVT VT, MVT &IntermediateVT, + unsigned &NumIntermediates, + EVT &RegisterVT, + TargetLowering* TLI) { + // Figure out the right, legal destination reg to copy into. + unsigned NumElts = VT.getVectorNumElements(); + MVT EltTy = VT.getVectorElementType(); + + unsigned NumVectorRegs = 1; + + // FIXME: We don't support non-power-of-2-sized vectors for now. Ideally we + // could break down into LHS/RHS like LegalizeDAG does. + if (!isPowerOf2_32(NumElts)) { + NumVectorRegs = NumElts; + NumElts = 1; + } + + // Divide the input until we get to a supported size. This will always + // end with a scalar if the target doesn't support vectors. + while (NumElts > 1 && !TLI->isTypeLegal(MVT::getVectorVT(EltTy, NumElts))) { + NumElts >>= 1; + NumVectorRegs <<= 1; + } + + NumIntermediates = NumVectorRegs; + + MVT NewVT = MVT::getVectorVT(EltTy, NumElts); + if (!TLI->isTypeLegal(NewVT)) + NewVT = EltTy; + IntermediateVT = NewVT; + + EVT DestVT = TLI->getRegisterType(NewVT); + RegisterVT = DestVT; + if (EVT(DestVT).bitsLT(NewVT)) { + // Value is expanded, e.g. i64 -> i16. + return NumVectorRegs*(NewVT.getSizeInBits()/DestVT.getSizeInBits()); + } else { + // Otherwise, promotion or legal types use the same number of registers as + // the vector decimated to the appropriate level. + return NumVectorRegs; + } + + return 1; +} + +/// computeRegisterProperties - Once all of the register classes are added, +/// this allows us to compute derived properties we expose. +void TargetLowering::computeRegisterProperties() { + assert(MVT::LAST_VALUETYPE <= MVT::MAX_ALLOWED_VALUETYPE && + "Too many value types for ValueTypeActions to hold!"); + + // Everything defaults to needing one register. + for (unsigned i = 0; i != MVT::LAST_VALUETYPE; ++i) { + NumRegistersForVT[i] = 1; + RegisterTypeForVT[i] = TransformToType[i] = (MVT::SimpleValueType)i; + } + // ...except isVoid, which doesn't need any registers. + NumRegistersForVT[MVT::isVoid] = 0; + + // Find the largest integer register class. + unsigned LargestIntReg = MVT::LAST_INTEGER_VALUETYPE; + for (; RegClassForVT[LargestIntReg] == 0; --LargestIntReg) + assert(LargestIntReg != MVT::i1 && "No integer registers defined!"); + + // Every integer value type larger than this largest register takes twice as + // many registers to represent as the previous ValueType. + for (unsigned ExpandedReg = LargestIntReg + 1; ; ++ExpandedReg) { + EVT ExpandedVT = (MVT::SimpleValueType)ExpandedReg; + if (!ExpandedVT.isInteger()) + break; + NumRegistersForVT[ExpandedReg] = 2*NumRegistersForVT[ExpandedReg-1]; + RegisterTypeForVT[ExpandedReg] = (MVT::SimpleValueType)LargestIntReg; + TransformToType[ExpandedReg] = (MVT::SimpleValueType)(ExpandedReg - 1); + ValueTypeActions.setTypeAction(ExpandedVT, Expand); + } + + // Inspect all of the ValueType's smaller than the largest integer + // register to see which ones need promotion. + unsigned LegalIntReg = LargestIntReg; + for (unsigned IntReg = LargestIntReg - 1; + IntReg >= (unsigned)MVT::i1; --IntReg) { + EVT IVT = (MVT::SimpleValueType)IntReg; + if (isTypeLegal(IVT)) { + LegalIntReg = IntReg; + } else { + RegisterTypeForVT[IntReg] = TransformToType[IntReg] = + (MVT::SimpleValueType)LegalIntReg; + ValueTypeActions.setTypeAction(IVT, Promote); + } + } + + // ppcf128 type is really two f64's. + if (!isTypeLegal(MVT::ppcf128)) { + NumRegistersForVT[MVT::ppcf128] = 2*NumRegistersForVT[MVT::f64]; + RegisterTypeForVT[MVT::ppcf128] = MVT::f64; + TransformToType[MVT::ppcf128] = MVT::f64; + ValueTypeActions.setTypeAction(MVT::ppcf128, Expand); + } + + // Decide how to handle f64. If the target does not have native f64 support, + // expand it to i64 and we will be generating soft float library calls. + if (!isTypeLegal(MVT::f64)) { + NumRegistersForVT[MVT::f64] = NumRegistersForVT[MVT::i64]; + RegisterTypeForVT[MVT::f64] = RegisterTypeForVT[MVT::i64]; + TransformToType[MVT::f64] = MVT::i64; + ValueTypeActions.setTypeAction(MVT::f64, Expand); + } + + // Decide how to handle f32. If the target does not have native support for + // f32, promote it to f64 if it is legal. Otherwise, expand it to i32. + if (!isTypeLegal(MVT::f32)) { + if (isTypeLegal(MVT::f64)) { + NumRegistersForVT[MVT::f32] = NumRegistersForVT[MVT::f64]; + RegisterTypeForVT[MVT::f32] = RegisterTypeForVT[MVT::f64]; + TransformToType[MVT::f32] = MVT::f64; + ValueTypeActions.setTypeAction(MVT::f32, Promote); + } else { + NumRegistersForVT[MVT::f32] = NumRegistersForVT[MVT::i32]; + RegisterTypeForVT[MVT::f32] = RegisterTypeForVT[MVT::i32]; + TransformToType[MVT::f32] = MVT::i32; + ValueTypeActions.setTypeAction(MVT::f32, Expand); + } + } + + // Loop over all of the vector value types to see which need transformations. + for (unsigned i = MVT::FIRST_VECTOR_VALUETYPE; + i <= (unsigned)MVT::LAST_VECTOR_VALUETYPE; ++i) { + MVT VT = (MVT::SimpleValueType)i; + if (!isTypeLegal(VT)) { + MVT IntermediateVT; + EVT RegisterVT; + unsigned NumIntermediates; + NumRegistersForVT[i] = + getVectorTypeBreakdownMVT(VT, IntermediateVT, NumIntermediates, + RegisterVT, this); + RegisterTypeForVT[i] = RegisterVT; + + // Determine if there is a legal wider type. + bool IsLegalWiderType = false; + EVT EltVT = VT.getVectorElementType(); + unsigned NElts = VT.getVectorNumElements(); + for (unsigned nVT = i+1; nVT <= MVT::LAST_VECTOR_VALUETYPE; ++nVT) { + EVT SVT = (MVT::SimpleValueType)nVT; + if (isTypeLegal(SVT) && SVT.getVectorElementType() == EltVT && + SVT.getVectorNumElements() > NElts) { + TransformToType[i] = SVT; + ValueTypeActions.setTypeAction(VT, Promote); + IsLegalWiderType = true; + break; + } + } + if (!IsLegalWiderType) { + EVT NVT = VT.getPow2VectorType(); + if (NVT == VT) { + // Type is already a power of 2. The default action is to split. + TransformToType[i] = MVT::Other; + ValueTypeActions.setTypeAction(VT, Expand); + } else { + TransformToType[i] = NVT; + ValueTypeActions.setTypeAction(VT, Promote); + } + } + } + } +} + +const char *TargetLowering::getTargetNodeName(unsigned Opcode) const { + return NULL; +} + + +MVT::SimpleValueType TargetLowering::getSetCCResultType(EVT VT) const { + return PointerTy.SimpleTy; +} + +/// getVectorTypeBreakdown - Vector types are broken down into some number of +/// legal first class types. For example, MVT::v8f32 maps to 2 MVT::v4f32 +/// with Altivec or SSE1, or 8 promoted MVT::f64 values with the X86 FP stack. +/// Similarly, MVT::v2i64 turns into 4 MVT::i32 values with both PPC and X86. +/// +/// This method returns the number of registers needed, and the VT for each +/// register. It also returns the VT and quantity of the intermediate values +/// before they are promoted/expanded. +/// +unsigned TargetLowering::getVectorTypeBreakdown(LLVMContext &Context, EVT VT, + EVT &IntermediateVT, + unsigned &NumIntermediates, + EVT &RegisterVT) const { + // Figure out the right, legal destination reg to copy into. + unsigned NumElts = VT.getVectorNumElements(); + EVT EltTy = VT.getVectorElementType(); + + unsigned NumVectorRegs = 1; + + // FIXME: We don't support non-power-of-2-sized vectors for now. Ideally we + // could break down into LHS/RHS like LegalizeDAG does. + if (!isPowerOf2_32(NumElts)) { + NumVectorRegs = NumElts; + NumElts = 1; + } + + // Divide the input until we get to a supported size. This will always + // end with a scalar if the target doesn't support vectors. + while (NumElts > 1 && !isTypeLegal( + EVT::getVectorVT(Context, EltTy, NumElts))) { + NumElts >>= 1; + NumVectorRegs <<= 1; + } + + NumIntermediates = NumVectorRegs; + + EVT NewVT = EVT::getVectorVT(Context, EltTy, NumElts); + if (!isTypeLegal(NewVT)) + NewVT = EltTy; + IntermediateVT = NewVT; + + EVT DestVT = getRegisterType(Context, NewVT); + RegisterVT = DestVT; + if (DestVT.bitsLT(NewVT)) { + // Value is expanded, e.g. i64 -> i16. + return NumVectorRegs*(NewVT.getSizeInBits()/DestVT.getSizeInBits()); + } else { + // Otherwise, promotion or legal types use the same number of registers as + // the vector decimated to the appropriate level. + return NumVectorRegs; + } + + return 1; +} + +/// getWidenVectorType: given a vector type, returns the type to widen to +/// (e.g., v7i8 to v8i8). If the vector type is legal, it returns itself. +/// If there is no vector type that we want to widen to, returns MVT::Other +/// When and where to widen is target dependent based on the cost of +/// scalarizing vs using the wider vector type. +EVT TargetLowering::getWidenVectorType(EVT VT) const { + assert(VT.isVector()); + if (isTypeLegal(VT)) + return VT; + + // Default is not to widen until moved to LegalizeTypes + return MVT::Other; +} + +/// getByValTypeAlignment - Return the desired alignment for ByVal aggregate +/// function arguments in the caller parameter area. This is the actual +/// alignment, not its logarithm. +unsigned TargetLowering::getByValTypeAlignment(const Type *Ty) const { + return TD->getCallFrameTypeAlignment(Ty); +} + +SDValue TargetLowering::getPICJumpTableRelocBase(SDValue Table, + SelectionDAG &DAG) const { + if (usesGlobalOffsetTable()) + return DAG.getGLOBAL_OFFSET_TABLE(getPointerTy()); + return Table; +} + +bool +TargetLowering::isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const { + // Assume that everything is safe in static mode. + if (getTargetMachine().getRelocationModel() == Reloc::Static) + return true; + + // In dynamic-no-pic mode, assume that known defined values are safe. + if (getTargetMachine().getRelocationModel() == Reloc::DynamicNoPIC && + GA && + !GA->getGlobal()->isDeclaration() && + !GA->getGlobal()->isWeakForLinker()) + return true; + + // Otherwise assume nothing is safe. + return false; +} + +//===----------------------------------------------------------------------===// +// Optimization Methods +//===----------------------------------------------------------------------===// + +/// ShrinkDemandedConstant - Check to see if the specified operand of the +/// specified instruction is a constant integer. If so, check to see if there +/// are any bits set in the constant that are not demanded. If so, shrink the +/// constant and return true. +bool TargetLowering::TargetLoweringOpt::ShrinkDemandedConstant(SDValue Op, + const APInt &Demanded) { + DebugLoc dl = Op.getDebugLoc(); + + // FIXME: ISD::SELECT, ISD::SELECT_CC + switch (Op.getOpcode()) { + default: break; + case ISD::XOR: + case ISD::AND: + case ISD::OR: { + ConstantSDNode *C = dyn_cast(Op.getOperand(1)); + if (!C) return false; + + if (Op.getOpcode() == ISD::XOR && + (C->getAPIntValue() | (~Demanded)).isAllOnesValue()) + return false; + + // if we can expand it to have all bits set, do it + if (C->getAPIntValue().intersects(~Demanded)) { + EVT VT = Op.getValueType(); + SDValue New = DAG.getNode(Op.getOpcode(), dl, VT, Op.getOperand(0), + DAG.getConstant(Demanded & + C->getAPIntValue(), + VT)); + return CombineTo(Op, New); + } + + break; + } + } + + return false; +} + +/// ShrinkDemandedOp - Convert x+y to (VT)((SmallVT)x+(SmallVT)y) if the +/// casts are free. This uses isZExtFree and ZERO_EXTEND for the widening +/// cast, but it could be generalized for targets with other types of +/// implicit widening casts. +bool +TargetLowering::TargetLoweringOpt::ShrinkDemandedOp(SDValue Op, + unsigned BitWidth, + const APInt &Demanded, + DebugLoc dl) { + assert(Op.getNumOperands() == 2 && + "ShrinkDemandedOp only supports binary operators!"); + assert(Op.getNode()->getNumValues() == 1 && + "ShrinkDemandedOp only supports nodes with one result!"); + + // Don't do this if the node has another user, which may require the + // full value. + if (!Op.getNode()->hasOneUse()) + return false; + + // Search for the smallest integer type with free casts to and from + // Op's type. For expedience, just check power-of-2 integer types. + const TargetLowering &TLI = DAG.getTargetLoweringInfo(); + unsigned SmallVTBits = BitWidth - Demanded.countLeadingZeros(); + if (!isPowerOf2_32(SmallVTBits)) + SmallVTBits = NextPowerOf2(SmallVTBits); + for (; SmallVTBits < BitWidth; SmallVTBits = NextPowerOf2(SmallVTBits)) { + EVT SmallVT = EVT::getIntegerVT(*DAG.getContext(), SmallVTBits); + if (TLI.isTruncateFree(Op.getValueType(), SmallVT) && + TLI.isZExtFree(SmallVT, Op.getValueType())) { + // We found a type with free casts. + SDValue X = DAG.getNode(Op.getOpcode(), dl, SmallVT, + DAG.getNode(ISD::TRUNCATE, dl, SmallVT, + Op.getNode()->getOperand(0)), + DAG.getNode(ISD::TRUNCATE, dl, SmallVT, + Op.getNode()->getOperand(1))); + SDValue Z = DAG.getNode(ISD::ZERO_EXTEND, dl, Op.getValueType(), X); + return CombineTo(Op, Z); + } + } + return false; +} + +/// SimplifyDemandedBits - Look at Op. At this point, we know that only the +/// DemandedMask bits of the result of Op are ever used downstream. If we can +/// use this information to simplify Op, create a new simplified DAG node and +/// return true, returning the original and new nodes in Old and New. Otherwise, +/// analyze the expression and return a mask of KnownOne and KnownZero bits for +/// the expression (used to simplify the caller). The KnownZero/One bits may +/// only be accurate for those bits in the DemandedMask. +bool TargetLowering::SimplifyDemandedBits(SDValue Op, + const APInt &DemandedMask, + APInt &KnownZero, + APInt &KnownOne, + TargetLoweringOpt &TLO, + unsigned Depth) const { + unsigned BitWidth = DemandedMask.getBitWidth(); + assert(Op.getValueSizeInBits() == BitWidth && + "Mask size mismatches value type size!"); + APInt NewMask = DemandedMask; + DebugLoc dl = Op.getDebugLoc(); + + // Don't know anything. + KnownZero = KnownOne = APInt(BitWidth, 0); + + // Other users may use these bits. + if (!Op.getNode()->hasOneUse()) { + if (Depth != 0) { + // If not at the root, Just compute the KnownZero/KnownOne bits to + // simplify things downstream. + TLO.DAG.ComputeMaskedBits(Op, DemandedMask, KnownZero, KnownOne, Depth); + return false; + } + // If this is the root being simplified, allow it to have multiple uses, + // just set the NewMask to all bits. + NewMask = APInt::getAllOnesValue(BitWidth); + } else if (DemandedMask == 0) { + // Not demanding any bits from Op. + if (Op.getOpcode() != ISD::UNDEF) + return TLO.CombineTo(Op, TLO.DAG.getUNDEF(Op.getValueType())); + return false; + } else if (Depth == 6) { // Limit search depth. + return false; + } + + APInt KnownZero2, KnownOne2, KnownZeroOut, KnownOneOut; + switch (Op.getOpcode()) { + case ISD::Constant: + // We know all of the bits for a constant! + KnownOne = cast(Op)->getAPIntValue() & NewMask; + KnownZero = ~KnownOne & NewMask; + return false; // Don't fall through, will infinitely loop. + case ISD::AND: + // If the RHS is a constant, check to see if the LHS would be zero without + // using the bits from the RHS. Below, we use knowledge about the RHS to + // simplify the LHS, here we're using information from the LHS to simplify + // the RHS. + if (ConstantSDNode *RHSC = dyn_cast(Op.getOperand(1))) { + APInt LHSZero, LHSOne; + TLO.DAG.ComputeMaskedBits(Op.getOperand(0), NewMask, + LHSZero, LHSOne, Depth+1); + // If the LHS already has zeros where RHSC does, this and is dead. + if ((LHSZero & NewMask) == (~RHSC->getAPIntValue() & NewMask)) + return TLO.CombineTo(Op, Op.getOperand(0)); + // If any of the set bits in the RHS are known zero on the LHS, shrink + // the constant. + if (TLO.ShrinkDemandedConstant(Op, ~LHSZero & NewMask)) + return true; + } + + if (SimplifyDemandedBits(Op.getOperand(1), NewMask, KnownZero, + KnownOne, TLO, Depth+1)) + return true; + assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?"); + if (SimplifyDemandedBits(Op.getOperand(0), ~KnownZero & NewMask, + KnownZero2, KnownOne2, TLO, Depth+1)) + return true; + assert((KnownZero2 & KnownOne2) == 0 && "Bits known to be one AND zero?"); + + // If all of the demanded bits are known one on one side, return the other. + // These bits cannot contribute to the result of the 'and'. + if ((NewMask & ~KnownZero2 & KnownOne) == (~KnownZero2 & NewMask)) + return TLO.CombineTo(Op, Op.getOperand(0)); + if ((NewMask & ~KnownZero & KnownOne2) == (~KnownZero & NewMask)) + return TLO.CombineTo(Op, Op.getOperand(1)); + // If all of the demanded bits in the inputs are known zeros, return zero. + if ((NewMask & (KnownZero|KnownZero2)) == NewMask) + return TLO.CombineTo(Op, TLO.DAG.getConstant(0, Op.getValueType())); + // If the RHS is a constant, see if we can simplify it. + if (TLO.ShrinkDemandedConstant(Op, ~KnownZero2 & NewMask)) + return true; + // If the operation can be done in a smaller type, do so. + if (TLO.ShrinkDemandedOp(Op, BitWidth, NewMask, dl)) + return true; + + // Output known-1 bits are only known if set in both the LHS & RHS. + KnownOne &= KnownOne2; + // Output known-0 are known to be clear if zero in either the LHS | RHS. + KnownZero |= KnownZero2; + break; + case ISD::OR: + if (SimplifyDemandedBits(Op.getOperand(1), NewMask, KnownZero, + KnownOne, TLO, Depth+1)) + return true; + assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?"); + if (SimplifyDemandedBits(Op.getOperand(0), ~KnownOne & NewMask, + KnownZero2, KnownOne2, TLO, Depth+1)) + return true; + assert((KnownZero2 & KnownOne2) == 0 && "Bits known to be one AND zero?"); + + // If all of the demanded bits are known zero on one side, return the other. + // These bits cannot contribute to the result of the 'or'. + if ((NewMask & ~KnownOne2 & KnownZero) == (~KnownOne2 & NewMask)) + return TLO.CombineTo(Op, Op.getOperand(0)); + if ((NewMask & ~KnownOne & KnownZero2) == (~KnownOne & NewMask)) + return TLO.CombineTo(Op, Op.getOperand(1)); + // If all of the potentially set bits on one side are known to be set on + // the other side, just use the 'other' side. + if ((NewMask & ~KnownZero & KnownOne2) == (~KnownZero & NewMask)) + return TLO.CombineTo(Op, Op.getOperand(0)); + if ((NewMask & ~KnownZero2 & KnownOne) == (~KnownZero2 & NewMask)) + return TLO.CombineTo(Op, Op.getOperand(1)); + // If the RHS is a constant, see if we can simplify it. + if (TLO.ShrinkDemandedConstant(Op, NewMask)) + return true; + // If the operation can be done in a smaller type, do so. + if (TLO.ShrinkDemandedOp(Op, BitWidth, NewMask, dl)) + return true; + + // Output known-0 bits are only known if clear in both the LHS & RHS. + KnownZero &= KnownZero2; + // Output known-1 are known to be set if set in either the LHS | RHS. + KnownOne |= KnownOne2; + break; + case ISD::XOR: + if (SimplifyDemandedBits(Op.getOperand(1), NewMask, KnownZero, + KnownOne, TLO, Depth+1)) + return true; + assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?"); + if (SimplifyDemandedBits(Op.getOperand(0), NewMask, KnownZero2, + KnownOne2, TLO, Depth+1)) + return true; + assert((KnownZero2 & KnownOne2) == 0 && "Bits known to be one AND zero?"); + + // If all of the demanded bits are known zero on one side, return the other. + // These bits cannot contribute to the result of the 'xor'. + if ((KnownZero & NewMask) == NewMask) + return TLO.CombineTo(Op, Op.getOperand(0)); + if ((KnownZero2 & NewMask) == NewMask) + return TLO.CombineTo(Op, Op.getOperand(1)); + // If the operation can be done in a smaller type, do so. + if (TLO.ShrinkDemandedOp(Op, BitWidth, NewMask, dl)) + return true; + + // If all of the unknown bits are known to be zero on one side or the other + // (but not both) turn this into an *inclusive* or. + // e.g. (A & C1)^(B & C2) -> (A & C1)|(B & C2) iff C1&C2 == 0 + if ((NewMask & ~KnownZero & ~KnownZero2) == 0) + return TLO.CombineTo(Op, TLO.DAG.getNode(ISD::OR, dl, Op.getValueType(), + Op.getOperand(0), + Op.getOperand(1))); + + // Output known-0 bits are known if clear or set in both the LHS & RHS. + KnownZeroOut = (KnownZero & KnownZero2) | (KnownOne & KnownOne2); + // Output known-1 are known to be set if set in only one of the LHS, RHS. + KnownOneOut = (KnownZero & KnownOne2) | (KnownOne & KnownZero2); + + // If all of the demanded bits on one side are known, and all of the set + // bits on that side are also known to be set on the other side, turn this + // into an AND, as we know the bits will be cleared. + // e.g. (X | C1) ^ C2 --> (X | C1) & ~C2 iff (C1&C2) == C2 + if ((NewMask & (KnownZero|KnownOne)) == NewMask) { // all known + if ((KnownOne & KnownOne2) == KnownOne) { + EVT VT = Op.getValueType(); + SDValue ANDC = TLO.DAG.getConstant(~KnownOne & NewMask, VT); + return TLO.CombineTo(Op, TLO.DAG.getNode(ISD::AND, dl, VT, + Op.getOperand(0), ANDC)); + } + } + + // If the RHS is a constant, see if we can simplify it. + // for XOR, we prefer to force bits to 1 if they will make a -1. + // if we can't force bits, try to shrink constant + if (ConstantSDNode *C = dyn_cast(Op.getOperand(1))) { + APInt Expanded = C->getAPIntValue() | (~NewMask); + // if we can expand it to have all bits set, do it + if (Expanded.isAllOnesValue()) { + if (Expanded != C->getAPIntValue()) { + EVT VT = Op.getValueType(); + SDValue New = TLO.DAG.getNode(Op.getOpcode(), dl,VT, Op.getOperand(0), + TLO.DAG.getConstant(Expanded, VT)); + return TLO.CombineTo(Op, New); + } + // if it already has all the bits set, nothing to change + // but don't shrink either! + } else if (TLO.ShrinkDemandedConstant(Op, NewMask)) { + return true; + } + } + + KnownZero = KnownZeroOut; + KnownOne = KnownOneOut; + break; + case ISD::SELECT: + if (SimplifyDemandedBits(Op.getOperand(2), NewMask, KnownZero, + KnownOne, TLO, Depth+1)) + return true; + if (SimplifyDemandedBits(Op.getOperand(1), NewMask, KnownZero2, + KnownOne2, TLO, Depth+1)) + return true; + assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?"); + assert((KnownZero2 & KnownOne2) == 0 && "Bits known to be one AND zero?"); + + // If the operands are constants, see if we can simplify them. + if (TLO.ShrinkDemandedConstant(Op, NewMask)) + return true; + + // Only known if known in both the LHS and RHS. + KnownOne &= KnownOne2; + KnownZero &= KnownZero2; + break; + case ISD::SELECT_CC: + if (SimplifyDemandedBits(Op.getOperand(3), NewMask, KnownZero, + KnownOne, TLO, Depth+1)) + return true; + if (SimplifyDemandedBits(Op.getOperand(2), NewMask, KnownZero2, + KnownOne2, TLO, Depth+1)) + return true; + assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?"); + assert((KnownZero2 & KnownOne2) == 0 && "Bits known to be one AND zero?"); + + // If the operands are constants, see if we can simplify them. + if (TLO.ShrinkDemandedConstant(Op, NewMask)) + return true; + + // Only known if known in both the LHS and RHS. + KnownOne &= KnownOne2; + KnownZero &= KnownZero2; + break; + case ISD::SHL: + if (ConstantSDNode *SA = dyn_cast(Op.getOperand(1))) { + unsigned ShAmt = SA->getZExtValue(); + SDValue InOp = Op.getOperand(0); + + // If the shift count is an invalid immediate, don't do anything. + if (ShAmt >= BitWidth) + break; + + // If this is ((X >>u C1) << ShAmt), see if we can simplify this into a + // single shift. We can do this if the bottom bits (which are shifted + // out) are never demanded. + if (InOp.getOpcode() == ISD::SRL && + isa(InOp.getOperand(1))) { + if (ShAmt && (NewMask & APInt::getLowBitsSet(BitWidth, ShAmt)) == 0) { + unsigned C1= cast(InOp.getOperand(1))->getZExtValue(); + unsigned Opc = ISD::SHL; + int Diff = ShAmt-C1; + if (Diff < 0) { + Diff = -Diff; + Opc = ISD::SRL; + } + + SDValue NewSA = + TLO.DAG.getConstant(Diff, Op.getOperand(1).getValueType()); + EVT VT = Op.getValueType(); + return TLO.CombineTo(Op, TLO.DAG.getNode(Opc, dl, VT, + InOp.getOperand(0), NewSA)); + } + } + + if (SimplifyDemandedBits(Op.getOperand(0), NewMask.lshr(ShAmt), + KnownZero, KnownOne, TLO, Depth+1)) + return true; + KnownZero <<= SA->getZExtValue(); + KnownOne <<= SA->getZExtValue(); + // low bits known zero. + KnownZero |= APInt::getLowBitsSet(BitWidth, SA->getZExtValue()); + } + break; + case ISD::SRL: + if (ConstantSDNode *SA = dyn_cast(Op.getOperand(1))) { + EVT VT = Op.getValueType(); + unsigned ShAmt = SA->getZExtValue(); + unsigned VTSize = VT.getSizeInBits(); + SDValue InOp = Op.getOperand(0); + + // If the shift count is an invalid immediate, don't do anything. + if (ShAmt >= BitWidth) + break; + + // If this is ((X << C1) >>u ShAmt), see if we can simplify this into a + // single shift. We can do this if the top bits (which are shifted out) + // are never demanded. + if (InOp.getOpcode() == ISD::SHL && + isa(InOp.getOperand(1))) { + if (ShAmt && (NewMask & APInt::getHighBitsSet(VTSize, ShAmt)) == 0) { + unsigned C1= cast(InOp.getOperand(1))->getZExtValue(); + unsigned Opc = ISD::SRL; + int Diff = ShAmt-C1; + if (Diff < 0) { + Diff = -Diff; + Opc = ISD::SHL; + } + + SDValue NewSA = + TLO.DAG.getConstant(Diff, Op.getOperand(1).getValueType()); + return TLO.CombineTo(Op, TLO.DAG.getNode(Opc, dl, VT, + InOp.getOperand(0), NewSA)); + } + } + + // Compute the new bits that are at the top now. + if (SimplifyDemandedBits(InOp, (NewMask << ShAmt), + KnownZero, KnownOne, TLO, Depth+1)) + return true; + assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?"); + KnownZero = KnownZero.lshr(ShAmt); + KnownOne = KnownOne.lshr(ShAmt); + + APInt HighBits = APInt::getHighBitsSet(BitWidth, ShAmt); + KnownZero |= HighBits; // High bits known zero. + } + break; + case ISD::SRA: + // If this is an arithmetic shift right and only the low-bit is set, we can + // always convert this into a logical shr, even if the shift amount is + // variable. The low bit of the shift cannot be an input sign bit unless + // the shift amount is >= the size of the datatype, which is undefined. + if (DemandedMask == 1) + return TLO.CombineTo(Op, TLO.DAG.getNode(ISD::SRL, dl, Op.getValueType(), + Op.getOperand(0), Op.getOperand(1))); + + if (ConstantSDNode *SA = dyn_cast(Op.getOperand(1))) { + EVT VT = Op.getValueType(); + unsigned ShAmt = SA->getZExtValue(); + + // If the shift count is an invalid immediate, don't do anything. + if (ShAmt >= BitWidth) + break; + + APInt InDemandedMask = (NewMask << ShAmt); + + // If any of the demanded bits are produced by the sign extension, we also + // demand the input sign bit. + APInt HighBits = APInt::getHighBitsSet(BitWidth, ShAmt); + if (HighBits.intersects(NewMask)) + InDemandedMask |= APInt::getSignBit(VT.getSizeInBits()); + + if (SimplifyDemandedBits(Op.getOperand(0), InDemandedMask, + KnownZero, KnownOne, TLO, Depth+1)) + return true; + assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?"); + KnownZero = KnownZero.lshr(ShAmt); + KnownOne = KnownOne.lshr(ShAmt); + + // Handle the sign bit, adjusted to where it is now in the mask. + APInt SignBit = APInt::getSignBit(BitWidth).lshr(ShAmt); + + // If the input sign bit is known to be zero, or if none of the top bits + // are demanded, turn this into an unsigned shift right. + if (KnownZero.intersects(SignBit) || (HighBits & ~NewMask) == HighBits) { + return TLO.CombineTo(Op, TLO.DAG.getNode(ISD::SRL, dl, VT, + Op.getOperand(0), + Op.getOperand(1))); + } else if (KnownOne.intersects(SignBit)) { // New bits are known one. + KnownOne |= HighBits; + } + } + break; + case ISD::SIGN_EXTEND_INREG: { + EVT EVT = cast(Op.getOperand(1))->getVT(); + + // Sign extension. Compute the demanded bits in the result that are not + // present in the input. + APInt NewBits = APInt::getHighBitsSet(BitWidth, + BitWidth - EVT.getSizeInBits()) & + NewMask; + + // If none of the extended bits are demanded, eliminate the sextinreg. + if (NewBits == 0) + return TLO.CombineTo(Op, Op.getOperand(0)); + + APInt InSignBit = APInt::getSignBit(EVT.getSizeInBits()); + InSignBit.zext(BitWidth); + APInt InputDemandedBits = APInt::getLowBitsSet(BitWidth, + EVT.getSizeInBits()) & + NewMask; + + // Since the sign extended bits are demanded, we know that the sign + // bit is demanded. + InputDemandedBits |= InSignBit; + + if (SimplifyDemandedBits(Op.getOperand(0), InputDemandedBits, + KnownZero, KnownOne, TLO, Depth+1)) + return true; + assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?"); + + // If the sign bit of the input is known set or clear, then we know the + // top bits of the result. + + // If the input sign bit is known zero, convert this into a zero extension. + if (KnownZero.intersects(InSignBit)) + return TLO.CombineTo(Op, + TLO.DAG.getZeroExtendInReg(Op.getOperand(0),dl,EVT)); + + if (KnownOne.intersects(InSignBit)) { // Input sign bit known set + KnownOne |= NewBits; + KnownZero &= ~NewBits; + } else { // Input sign bit unknown + KnownZero &= ~NewBits; + KnownOne &= ~NewBits; + } + break; + } + case ISD::ZERO_EXTEND: { + unsigned OperandBitWidth = Op.getOperand(0).getValueSizeInBits(); + APInt InMask = NewMask; + InMask.trunc(OperandBitWidth); + + // If none of the top bits are demanded, convert this into an any_extend. + APInt NewBits = + APInt::getHighBitsSet(BitWidth, BitWidth - OperandBitWidth) & NewMask; + if (!NewBits.intersects(NewMask)) + return TLO.CombineTo(Op, TLO.DAG.getNode(ISD::ANY_EXTEND, dl, + Op.getValueType(), + Op.getOperand(0))); + + if (SimplifyDemandedBits(Op.getOperand(0), InMask, + KnownZero, KnownOne, TLO, Depth+1)) + return true; + assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?"); + KnownZero.zext(BitWidth); + KnownOne.zext(BitWidth); + KnownZero |= NewBits; + break; + } + case ISD::SIGN_EXTEND: { + EVT InVT = Op.getOperand(0).getValueType(); + unsigned InBits = InVT.getSizeInBits(); + APInt InMask = APInt::getLowBitsSet(BitWidth, InBits); + APInt InSignBit = APInt::getBitsSet(BitWidth, InBits - 1, InBits); + APInt NewBits = ~InMask & NewMask; + + // If none of the top bits are demanded, convert this into an any_extend. + if (NewBits == 0) + return TLO.CombineTo(Op,TLO.DAG.getNode(ISD::ANY_EXTEND, dl, + Op.getValueType(), + Op.getOperand(0))); + + // Since some of the sign extended bits are demanded, we know that the sign + // bit is demanded. + APInt InDemandedBits = InMask & NewMask; + InDemandedBits |= InSignBit; + InDemandedBits.trunc(InBits); + + if (SimplifyDemandedBits(Op.getOperand(0), InDemandedBits, KnownZero, + KnownOne, TLO, Depth+1)) + return true; + KnownZero.zext(BitWidth); + KnownOne.zext(BitWidth); + + // If the sign bit is known zero, convert this to a zero extend. + if (KnownZero.intersects(InSignBit)) + return TLO.CombineTo(Op, TLO.DAG.getNode(ISD::ZERO_EXTEND, dl, + Op.getValueType(), + Op.getOperand(0))); + + // If the sign bit is known one, the top bits match. + if (KnownOne.intersects(InSignBit)) { + KnownOne |= NewBits; + KnownZero &= ~NewBits; + } else { // Otherwise, top bits aren't known. + KnownOne &= ~NewBits; + KnownZero &= ~NewBits; + } + break; + } + case ISD::ANY_EXTEND: { + unsigned OperandBitWidth = Op.getOperand(0).getValueSizeInBits(); + APInt InMask = NewMask; + InMask.trunc(OperandBitWidth); + if (SimplifyDemandedBits(Op.getOperand(0), InMask, + KnownZero, KnownOne, TLO, Depth+1)) + return true; + assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?"); + KnownZero.zext(BitWidth); + KnownOne.zext(BitWidth); + break; + } + case ISD::TRUNCATE: { + // Simplify the input, using demanded bit information, and compute the known + // zero/one bits live out. + APInt TruncMask = NewMask; + TruncMask.zext(Op.getOperand(0).getValueSizeInBits()); + if (SimplifyDemandedBits(Op.getOperand(0), TruncMask, + KnownZero, KnownOne, TLO, Depth+1)) + return true; + KnownZero.trunc(BitWidth); + KnownOne.trunc(BitWidth); + + // If the input is only used by this truncate, see if we can shrink it based + // on the known demanded bits. + if (Op.getOperand(0).getNode()->hasOneUse()) { + SDValue In = Op.getOperand(0); + unsigned InBitWidth = In.getValueSizeInBits(); + switch (In.getOpcode()) { + default: break; + case ISD::SRL: + // Shrink SRL by a constant if none of the high bits shifted in are + // demanded. + if (ConstantSDNode *ShAmt = dyn_cast(In.getOperand(1))){ + APInt HighBits = APInt::getHighBitsSet(InBitWidth, + InBitWidth - BitWidth); + HighBits = HighBits.lshr(ShAmt->getZExtValue()); + HighBits.trunc(BitWidth); + + if (ShAmt->getZExtValue() < BitWidth && !(HighBits & NewMask)) { + // None of the shifted in bits are needed. Add a truncate of the + // shift input, then shift it. + SDValue NewTrunc = TLO.DAG.getNode(ISD::TRUNCATE, dl, + Op.getValueType(), + In.getOperand(0)); + return TLO.CombineTo(Op, TLO.DAG.getNode(ISD::SRL, dl, + Op.getValueType(), + NewTrunc, + In.getOperand(1))); + } + } + break; + } + } + + assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?"); + break; + } + case ISD::AssertZext: { + EVT VT = cast(Op.getOperand(1))->getVT(); + APInt InMask = APInt::getLowBitsSet(BitWidth, + VT.getSizeInBits()); + if (SimplifyDemandedBits(Op.getOperand(0), InMask & NewMask, + KnownZero, KnownOne, TLO, Depth+1)) + return true; + assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?"); + KnownZero |= ~InMask & NewMask; + break; + } + case ISD::BIT_CONVERT: +#if 0 + // If this is an FP->Int bitcast and if the sign bit is the only thing that + // is demanded, turn this into a FGETSIGN. + if (NewMask == EVT::getIntegerVTSignBit(Op.getValueType()) && + MVT::isFloatingPoint(Op.getOperand(0).getValueType()) && + !MVT::isVector(Op.getOperand(0).getValueType())) { + // Only do this xform if FGETSIGN is valid or if before legalize. + if (!TLO.AfterLegalize || + isOperationLegal(ISD::FGETSIGN, Op.getValueType())) { + // Make a FGETSIGN + SHL to move the sign bit into the appropriate + // place. We expect the SHL to be eliminated by other optimizations. + SDValue Sign = TLO.DAG.getNode(ISD::FGETSIGN, Op.getValueType(), + Op.getOperand(0)); + unsigned ShVal = Op.getValueType().getSizeInBits()-1; + SDValue ShAmt = TLO.DAG.getConstant(ShVal, getShiftAmountTy()); + return TLO.CombineTo(Op, TLO.DAG.getNode(ISD::SHL, Op.getValueType(), + Sign, ShAmt)); + } + } +#endif + break; + case ISD::ADD: + case ISD::MUL: + case ISD::SUB: { + // Add, Sub, and Mul don't demand any bits in positions beyond that + // of the highest bit demanded of them. + APInt LoMask = APInt::getLowBitsSet(BitWidth, + BitWidth - NewMask.countLeadingZeros()); + if (SimplifyDemandedBits(Op.getOperand(0), LoMask, KnownZero2, + KnownOne2, TLO, Depth+1)) + return true; + if (SimplifyDemandedBits(Op.getOperand(1), LoMask, KnownZero2, + KnownOne2, TLO, Depth+1)) + return true; + // See if the operation should be performed at a smaller bit width. + if (TLO.ShrinkDemandedOp(Op, BitWidth, NewMask, dl)) + return true; + } + // FALL THROUGH + default: + // Just use ComputeMaskedBits to compute output bits. + TLO.DAG.ComputeMaskedBits(Op, NewMask, KnownZero, KnownOne, Depth); + break; + } + + // If we know the value of all of the demanded bits, return this as a + // constant. + if ((NewMask & (KnownZero|KnownOne)) == NewMask) + return TLO.CombineTo(Op, TLO.DAG.getConstant(KnownOne, Op.getValueType())); + + return false; +} + +/// computeMaskedBitsForTargetNode - Determine which of the bits specified +/// in Mask are known to be either zero or one and return them in the +/// KnownZero/KnownOne bitsets. +void TargetLowering::computeMaskedBitsForTargetNode(const SDValue Op, + const APInt &Mask, + APInt &KnownZero, + APInt &KnownOne, + const SelectionDAG &DAG, + unsigned Depth) const { + assert((Op.getOpcode() >= ISD::BUILTIN_OP_END || + Op.getOpcode() == ISD::INTRINSIC_WO_CHAIN || + Op.getOpcode() == ISD::INTRINSIC_W_CHAIN || + Op.getOpcode() == ISD::INTRINSIC_VOID) && + "Should use MaskedValueIsZero if you don't know whether Op" + " is a target node!"); + KnownZero = KnownOne = APInt(Mask.getBitWidth(), 0); +} + +/// ComputeNumSignBitsForTargetNode - This method can be implemented by +/// targets that want to expose additional information about sign bits to the +/// DAG Combiner. +unsigned TargetLowering::ComputeNumSignBitsForTargetNode(SDValue Op, + unsigned Depth) const { + assert((Op.getOpcode() >= ISD::BUILTIN_OP_END || + Op.getOpcode() == ISD::INTRINSIC_WO_CHAIN || + Op.getOpcode() == ISD::INTRINSIC_W_CHAIN || + Op.getOpcode() == ISD::INTRINSIC_VOID) && + "Should use ComputeNumSignBits if you don't know whether Op" + " is a target node!"); + return 1; +} + +/// ValueHasExactlyOneBitSet - Test if the given value is known to have exactly +/// one bit set. This differs from ComputeMaskedBits in that it doesn't need to +/// determine which bit is set. +/// +static bool ValueHasExactlyOneBitSet(SDValue Val, const SelectionDAG &DAG) { + // A left-shift of a constant one will have exactly one bit set, because + // shifting the bit off the end is undefined. + if (Val.getOpcode() == ISD::SHL) + if (ConstantSDNode *C = + dyn_cast(Val.getNode()->getOperand(0))) + if (C->getAPIntValue() == 1) + return true; + + // Similarly, a right-shift of a constant sign-bit will have exactly + // one bit set. + if (Val.getOpcode() == ISD::SRL) + if (ConstantSDNode *C = + dyn_cast(Val.getNode()->getOperand(0))) + if (C->getAPIntValue().isSignBit()) + return true; + + // More could be done here, though the above checks are enough + // to handle some common cases. + + // Fall back to ComputeMaskedBits to catch other known cases. + EVT OpVT = Val.getValueType(); + unsigned BitWidth = OpVT.getSizeInBits(); + APInt Mask = APInt::getAllOnesValue(BitWidth); + APInt KnownZero, KnownOne; + DAG.ComputeMaskedBits(Val, Mask, KnownZero, KnownOne); + return (KnownZero.countPopulation() == BitWidth - 1) && + (KnownOne.countPopulation() == 1); +} + +/// SimplifySetCC - Try to simplify a setcc built with the specified operands +/// and cc. If it is unable to simplify it, return a null SDValue. +SDValue +TargetLowering::SimplifySetCC(EVT VT, SDValue N0, SDValue N1, + ISD::CondCode Cond, bool foldBooleans, + DAGCombinerInfo &DCI, DebugLoc dl) const { + SelectionDAG &DAG = DCI.DAG; + LLVMContext &Context = *DAG.getContext(); + + // These setcc operations always fold. + switch (Cond) { + default: break; + case ISD::SETFALSE: + case ISD::SETFALSE2: return DAG.getConstant(0, VT); + case ISD::SETTRUE: + case ISD::SETTRUE2: return DAG.getConstant(1, VT); + } + + if (isa(N0.getNode())) { + // Ensure that the constant occurs on the RHS, and fold constant + // comparisons. + return DAG.getSetCC(dl, VT, N1, N0, ISD::getSetCCSwappedOperands(Cond)); + } + + if (ConstantSDNode *N1C = dyn_cast(N1.getNode())) { + const APInt &C1 = N1C->getAPIntValue(); + + // If the LHS is '(srl (ctlz x), 5)', the RHS is 0/1, and this is an + // equality comparison, then we're just comparing whether X itself is + // zero. + if (N0.getOpcode() == ISD::SRL && (C1 == 0 || C1 == 1) && + N0.getOperand(0).getOpcode() == ISD::CTLZ && + N0.getOperand(1).getOpcode() == ISD::Constant) { + unsigned ShAmt = cast(N0.getOperand(1))->getZExtValue(); + if ((Cond == ISD::SETEQ || Cond == ISD::SETNE) && + ShAmt == Log2_32(N0.getValueType().getSizeInBits())) { + if ((C1 == 0) == (Cond == ISD::SETEQ)) { + // (srl (ctlz x), 5) == 0 -> X != 0 + // (srl (ctlz x), 5) != 1 -> X != 0 + Cond = ISD::SETNE; + } else { + // (srl (ctlz x), 5) != 0 -> X == 0 + // (srl (ctlz x), 5) == 1 -> X == 0 + Cond = ISD::SETEQ; + } + SDValue Zero = DAG.getConstant(0, N0.getValueType()); + return DAG.getSetCC(dl, VT, N0.getOperand(0).getOperand(0), + Zero, Cond); + } + } + + // If the LHS is '(and load, const)', the RHS is 0, + // the test is for equality or unsigned, and all 1 bits of the const are + // in the same partial word, see if we can shorten the load. + if (DCI.isBeforeLegalize() && + N0.getOpcode() == ISD::AND && C1 == 0 && + N0.getNode()->hasOneUse() && + isa(N0.getOperand(0)) && + N0.getOperand(0).getNode()->hasOneUse() && + isa(N0.getOperand(1))) { + LoadSDNode *Lod = cast(N0.getOperand(0)); + uint64_t bestMask = 0; + unsigned bestWidth = 0, bestOffset = 0; + if (!Lod->isVolatile() && Lod->isUnindexed() && + // FIXME: This uses getZExtValue() below so it only works on i64 and + // below. + N0.getValueType().getSizeInBits() <= 64) { + unsigned origWidth = N0.getValueType().getSizeInBits(); + // We can narrow (e.g.) 16-bit extending loads on 32-bit target to + // 8 bits, but have to be careful... + if (Lod->getExtensionType() != ISD::NON_EXTLOAD) + origWidth = Lod->getMemoryVT().getSizeInBits(); + uint64_t Mask =cast(N0.getOperand(1))->getZExtValue(); + for (unsigned width = origWidth / 2; width>=8; width /= 2) { + uint64_t newMask = (1ULL << width) - 1; + for (unsigned offset=0; offsetisLittleEndian()) + bestOffset = (origWidth/width - offset - 1) * (width/8); + else + bestOffset = (uint64_t)offset * (width/8); + bestMask = Mask >> (offset * (width/8) * 8); + bestWidth = width; + break; + } + newMask = newMask << width; + } + } + } + if (bestWidth) { + EVT newVT = EVT::getIntegerVT(Context, bestWidth); + if (newVT.isRound()) { + EVT PtrType = Lod->getOperand(1).getValueType(); + SDValue Ptr = Lod->getBasePtr(); + if (bestOffset != 0) + Ptr = DAG.getNode(ISD::ADD, dl, PtrType, Lod->getBasePtr(), + DAG.getConstant(bestOffset, PtrType)); + unsigned NewAlign = MinAlign(Lod->getAlignment(), bestOffset); + SDValue NewLoad = DAG.getLoad(newVT, dl, Lod->getChain(), Ptr, + Lod->getSrcValue(), + Lod->getSrcValueOffset() + bestOffset, + false, NewAlign); + return DAG.getSetCC(dl, VT, + DAG.getNode(ISD::AND, dl, newVT, NewLoad, + DAG.getConstant(bestMask, newVT)), + DAG.getConstant(0LL, newVT), Cond); + } + } + } + + // If the LHS is a ZERO_EXTEND, perform the comparison on the input. + if (N0.getOpcode() == ISD::ZERO_EXTEND) { + unsigned InSize = N0.getOperand(0).getValueType().getSizeInBits(); + + // If the comparison constant has bits in the upper part, the + // zero-extended value could never match. + if (C1.intersects(APInt::getHighBitsSet(C1.getBitWidth(), + C1.getBitWidth() - InSize))) { + switch (Cond) { + case ISD::SETUGT: + case ISD::SETUGE: + case ISD::SETEQ: return DAG.getConstant(0, VT); + case ISD::SETULT: + case ISD::SETULE: + case ISD::SETNE: return DAG.getConstant(1, VT); + case ISD::SETGT: + case ISD::SETGE: + // True if the sign bit of C1 is set. + return DAG.getConstant(C1.isNegative(), VT); + case ISD::SETLT: + case ISD::SETLE: + // True if the sign bit of C1 isn't set. + return DAG.getConstant(C1.isNonNegative(), VT); + default: + break; + } + } + + // Otherwise, we can perform the comparison with the low bits. + switch (Cond) { + case ISD::SETEQ: + case ISD::SETNE: + case ISD::SETUGT: + case ISD::SETUGE: + case ISD::SETULT: + case ISD::SETULE: { + EVT newVT = N0.getOperand(0).getValueType(); + if (DCI.isBeforeLegalizeOps() || + (isOperationLegal(ISD::SETCC, newVT) && + getCondCodeAction(Cond, newVT)==Legal)) + return DAG.getSetCC(dl, VT, N0.getOperand(0), + DAG.getConstant(APInt(C1).trunc(InSize), newVT), + Cond); + break; + } + default: + break; // todo, be more careful with signed comparisons + } + } else if (N0.getOpcode() == ISD::SIGN_EXTEND_INREG && + (Cond == ISD::SETEQ || Cond == ISD::SETNE)) { + EVT ExtSrcTy = cast(N0.getOperand(1))->getVT(); + unsigned ExtSrcTyBits = ExtSrcTy.getSizeInBits(); + EVT ExtDstTy = N0.getValueType(); + unsigned ExtDstTyBits = ExtDstTy.getSizeInBits(); + + // If the extended part has any inconsistent bits, it cannot ever + // compare equal. In other words, they have to be all ones or all + // zeros. + APInt ExtBits = + APInt::getHighBitsSet(ExtDstTyBits, ExtDstTyBits - ExtSrcTyBits); + if ((C1 & ExtBits) != 0 && (C1 & ExtBits) != ExtBits) + return DAG.getConstant(Cond == ISD::SETNE, VT); + + SDValue ZextOp; + EVT Op0Ty = N0.getOperand(0).getValueType(); + if (Op0Ty == ExtSrcTy) { + ZextOp = N0.getOperand(0); + } else { + APInt Imm = APInt::getLowBitsSet(ExtDstTyBits, ExtSrcTyBits); + ZextOp = DAG.getNode(ISD::AND, dl, Op0Ty, N0.getOperand(0), + DAG.getConstant(Imm, Op0Ty)); + } + if (!DCI.isCalledByLegalizer()) + DCI.AddToWorklist(ZextOp.getNode()); + // Otherwise, make this a use of a zext. + return DAG.getSetCC(dl, VT, ZextOp, + DAG.getConstant(C1 & APInt::getLowBitsSet( + ExtDstTyBits, + ExtSrcTyBits), + ExtDstTy), + Cond); + } else if ((N1C->isNullValue() || N1C->getAPIntValue() == 1) && + (Cond == ISD::SETEQ || Cond == ISD::SETNE)) { + + // SETCC (SETCC), [0|1], [EQ|NE] -> SETCC + if (N0.getOpcode() == ISD::SETCC) { + bool TrueWhenTrue = (Cond == ISD::SETEQ) ^ (N1C->getZExtValue() != 1); + if (TrueWhenTrue) + return N0; + + // Invert the condition. + ISD::CondCode CC = cast(N0.getOperand(2))->get(); + CC = ISD::getSetCCInverse(CC, + N0.getOperand(0).getValueType().isInteger()); + return DAG.getSetCC(dl, VT, N0.getOperand(0), N0.getOperand(1), CC); + } + + if ((N0.getOpcode() == ISD::XOR || + (N0.getOpcode() == ISD::AND && + N0.getOperand(0).getOpcode() == ISD::XOR && + N0.getOperand(1) == N0.getOperand(0).getOperand(1))) && + isa(N0.getOperand(1)) && + cast(N0.getOperand(1))->getAPIntValue() == 1) { + // If this is (X^1) == 0/1, swap the RHS and eliminate the xor. We + // can only do this if the top bits are known zero. + unsigned BitWidth = N0.getValueSizeInBits(); + if (DAG.MaskedValueIsZero(N0, + APInt::getHighBitsSet(BitWidth, + BitWidth-1))) { + // Okay, get the un-inverted input value. + SDValue Val; + if (N0.getOpcode() == ISD::XOR) + Val = N0.getOperand(0); + else { + assert(N0.getOpcode() == ISD::AND && + N0.getOperand(0).getOpcode() == ISD::XOR); + // ((X^1)&1)^1 -> X & 1 + Val = DAG.getNode(ISD::AND, dl, N0.getValueType(), + N0.getOperand(0).getOperand(0), + N0.getOperand(1)); + } + return DAG.getSetCC(dl, VT, Val, N1, + Cond == ISD::SETEQ ? ISD::SETNE : ISD::SETEQ); + } + } + } + + APInt MinVal, MaxVal; + unsigned OperandBitSize = N1C->getValueType(0).getSizeInBits(); + if (ISD::isSignedIntSetCC(Cond)) { + MinVal = APInt::getSignedMinValue(OperandBitSize); + MaxVal = APInt::getSignedMaxValue(OperandBitSize); + } else { + MinVal = APInt::getMinValue(OperandBitSize); + MaxVal = APInt::getMaxValue(OperandBitSize); + } + + // Canonicalize GE/LE comparisons to use GT/LT comparisons. + if (Cond == ISD::SETGE || Cond == ISD::SETUGE) { + if (C1 == MinVal) return DAG.getConstant(1, VT); // X >= MIN --> true + // X >= C0 --> X > (C0-1) + return DAG.getSetCC(dl, VT, N0, + DAG.getConstant(C1-1, N1.getValueType()), + (Cond == ISD::SETGE) ? ISD::SETGT : ISD::SETUGT); + } + + if (Cond == ISD::SETLE || Cond == ISD::SETULE) { + if (C1 == MaxVal) return DAG.getConstant(1, VT); // X <= MAX --> true + // X <= C0 --> X < (C0+1) + return DAG.getSetCC(dl, VT, N0, + DAG.getConstant(C1+1, N1.getValueType()), + (Cond == ISD::SETLE) ? ISD::SETLT : ISD::SETULT); + } + + if ((Cond == ISD::SETLT || Cond == ISD::SETULT) && C1 == MinVal) + return DAG.getConstant(0, VT); // X < MIN --> false + if ((Cond == ISD::SETGE || Cond == ISD::SETUGE) && C1 == MinVal) + return DAG.getConstant(1, VT); // X >= MIN --> true + if ((Cond == ISD::SETGT || Cond == ISD::SETUGT) && C1 == MaxVal) + return DAG.getConstant(0, VT); // X > MAX --> false + if ((Cond == ISD::SETLE || Cond == ISD::SETULE) && C1 == MaxVal) + return DAG.getConstant(1, VT); // X <= MAX --> true + + // Canonicalize setgt X, Min --> setne X, Min + if ((Cond == ISD::SETGT || Cond == ISD::SETUGT) && C1 == MinVal) + return DAG.getSetCC(dl, VT, N0, N1, ISD::SETNE); + // Canonicalize setlt X, Max --> setne X, Max + if ((Cond == ISD::SETLT || Cond == ISD::SETULT) && C1 == MaxVal) + return DAG.getSetCC(dl, VT, N0, N1, ISD::SETNE); + + // If we have setult X, 1, turn it into seteq X, 0 + if ((Cond == ISD::SETLT || Cond == ISD::SETULT) && C1 == MinVal+1) + return DAG.getSetCC(dl, VT, N0, + DAG.getConstant(MinVal, N0.getValueType()), + ISD::SETEQ); + // If we have setugt X, Max-1, turn it into seteq X, Max + else if ((Cond == ISD::SETGT || Cond == ISD::SETUGT) && C1 == MaxVal-1) + return DAG.getSetCC(dl, VT, N0, + DAG.getConstant(MaxVal, N0.getValueType()), + ISD::SETEQ); + + // If we have "setcc X, C0", check to see if we can shrink the immediate + // by changing cc. + + // SETUGT X, SINTMAX -> SETLT X, 0 + if (Cond == ISD::SETUGT && + C1 == APInt::getSignedMaxValue(OperandBitSize)) + return DAG.getSetCC(dl, VT, N0, + DAG.getConstant(0, N1.getValueType()), + ISD::SETLT); + + // SETULT X, SINTMIN -> SETGT X, -1 + if (Cond == ISD::SETULT && + C1 == APInt::getSignedMinValue(OperandBitSize)) { + SDValue ConstMinusOne = + DAG.getConstant(APInt::getAllOnesValue(OperandBitSize), + N1.getValueType()); + return DAG.getSetCC(dl, VT, N0, ConstMinusOne, ISD::SETGT); + } + + // Fold bit comparisons when we can. + if ((Cond == ISD::SETEQ || Cond == ISD::SETNE) && + VT == N0.getValueType() && N0.getOpcode() == ISD::AND) + if (ConstantSDNode *AndRHS = + dyn_cast(N0.getOperand(1))) { + EVT ShiftTy = DCI.isBeforeLegalize() ? + getPointerTy() : getShiftAmountTy(); + if (Cond == ISD::SETNE && C1 == 0) {// (X & 8) != 0 --> (X & 8) >> 3 + // Perform the xform if the AND RHS is a single bit. + if (isPowerOf2_64(AndRHS->getZExtValue())) { + return DAG.getNode(ISD::SRL, dl, VT, N0, + DAG.getConstant(Log2_64(AndRHS->getZExtValue()), + ShiftTy)); + } + } else if (Cond == ISD::SETEQ && C1 == AndRHS->getZExtValue()) { + // (X & 8) == 8 --> (X & 8) >> 3 + // Perform the xform if C1 is a single bit. + if (C1.isPowerOf2()) { + return DAG.getNode(ISD::SRL, dl, VT, N0, + DAG.getConstant(C1.logBase2(), ShiftTy)); + } + } + } + } + + if (isa(N0.getNode())) { + // Constant fold or commute setcc. + SDValue O = DAG.FoldSetCC(VT, N0, N1, Cond, dl); + if (O.getNode()) return O; + } else if (ConstantFPSDNode *CFP = dyn_cast(N1.getNode())) { + // If the RHS of an FP comparison is a constant, simplify it away in + // some cases. + if (CFP->getValueAPF().isNaN()) { + // If an operand is known to be a nan, we can fold it. + switch (ISD::getUnorderedFlavor(Cond)) { + default: llvm_unreachable("Unknown flavor!"); + case 0: // Known false. + return DAG.getConstant(0, VT); + case 1: // Known true. + return DAG.getConstant(1, VT); + case 2: // Undefined. + return DAG.getUNDEF(VT); + } + } + + // Otherwise, we know the RHS is not a NaN. Simplify the node to drop the + // constant if knowing that the operand is non-nan is enough. We prefer to + // have SETO(x,x) instead of SETO(x, 0.0) because this avoids having to + // materialize 0.0. + if (Cond == ISD::SETO || Cond == ISD::SETUO) + return DAG.getSetCC(dl, VT, N0, N0, Cond); + + // If the condition is not legal, see if we can find an equivalent one + // which is legal. + if (!isCondCodeLegal(Cond, N0.getValueType())) { + // If the comparison was an awkward floating-point == or != and one of + // the comparison operands is infinity or negative infinity, convert the + // condition to a less-awkward <= or >=. + if (CFP->getValueAPF().isInfinity()) { + if (CFP->getValueAPF().isNegative()) { + if (Cond == ISD::SETOEQ && + isCondCodeLegal(ISD::SETOLE, N0.getValueType())) + return DAG.getSetCC(dl, VT, N0, N1, ISD::SETOLE); + if (Cond == ISD::SETUEQ && + isCondCodeLegal(ISD::SETOLE, N0.getValueType())) + return DAG.getSetCC(dl, VT, N0, N1, ISD::SETULE); + if (Cond == ISD::SETUNE && + isCondCodeLegal(ISD::SETUGT, N0.getValueType())) + return DAG.getSetCC(dl, VT, N0, N1, ISD::SETUGT); + if (Cond == ISD::SETONE && + isCondCodeLegal(ISD::SETUGT, N0.getValueType())) + return DAG.getSetCC(dl, VT, N0, N1, ISD::SETOGT); + } else { + if (Cond == ISD::SETOEQ && + isCondCodeLegal(ISD::SETOGE, N0.getValueType())) + return DAG.getSetCC(dl, VT, N0, N1, ISD::SETOGE); + if (Cond == ISD::SETUEQ && + isCondCodeLegal(ISD::SETOGE, N0.getValueType())) + return DAG.getSetCC(dl, VT, N0, N1, ISD::SETUGE); + if (Cond == ISD::SETUNE && + isCondCodeLegal(ISD::SETULT, N0.getValueType())) + return DAG.getSetCC(dl, VT, N0, N1, ISD::SETULT); + if (Cond == ISD::SETONE && + isCondCodeLegal(ISD::SETULT, N0.getValueType())) + return DAG.getSetCC(dl, VT, N0, N1, ISD::SETOLT); + } + } + } + } + + if (N0 == N1) { + // We can always fold X == X for integer setcc's. + if (N0.getValueType().isInteger()) + return DAG.getConstant(ISD::isTrueWhenEqual(Cond), VT); + unsigned UOF = ISD::getUnorderedFlavor(Cond); + if (UOF == 2) // FP operators that are undefined on NaNs. + return DAG.getConstant(ISD::isTrueWhenEqual(Cond), VT); + if (UOF == unsigned(ISD::isTrueWhenEqual(Cond))) + return DAG.getConstant(UOF, VT); + // Otherwise, we can't fold it. However, we can simplify it to SETUO/SETO + // if it is not already. + ISD::CondCode NewCond = UOF == 0 ? ISD::SETO : ISD::SETUO; + if (NewCond != Cond) + return DAG.getSetCC(dl, VT, N0, N1, NewCond); + } + + if ((Cond == ISD::SETEQ || Cond == ISD::SETNE) && + N0.getValueType().isInteger()) { + if (N0.getOpcode() == ISD::ADD || N0.getOpcode() == ISD::SUB || + N0.getOpcode() == ISD::XOR) { + // Simplify (X+Y) == (X+Z) --> Y == Z + if (N0.getOpcode() == N1.getOpcode()) { + if (N0.getOperand(0) == N1.getOperand(0)) + return DAG.getSetCC(dl, VT, N0.getOperand(1), N1.getOperand(1), Cond); + if (N0.getOperand(1) == N1.getOperand(1)) + return DAG.getSetCC(dl, VT, N0.getOperand(0), N1.getOperand(0), Cond); + if (DAG.isCommutativeBinOp(N0.getOpcode())) { + // If X op Y == Y op X, try other combinations. + if (N0.getOperand(0) == N1.getOperand(1)) + return DAG.getSetCC(dl, VT, N0.getOperand(1), N1.getOperand(0), + Cond); + if (N0.getOperand(1) == N1.getOperand(0)) + return DAG.getSetCC(dl, VT, N0.getOperand(0), N1.getOperand(1), + Cond); + } + } + + if (ConstantSDNode *RHSC = dyn_cast(N1)) { + if (ConstantSDNode *LHSR = dyn_cast(N0.getOperand(1))) { + // Turn (X+C1) == C2 --> X == C2-C1 + if (N0.getOpcode() == ISD::ADD && N0.getNode()->hasOneUse()) { + return DAG.getSetCC(dl, VT, N0.getOperand(0), + DAG.getConstant(RHSC->getAPIntValue()- + LHSR->getAPIntValue(), + N0.getValueType()), Cond); + } + + // Turn (X^C1) == C2 into X == C1^C2 iff X&~C1 = 0. + if (N0.getOpcode() == ISD::XOR) + // If we know that all of the inverted bits are zero, don't bother + // performing the inversion. + if (DAG.MaskedValueIsZero(N0.getOperand(0), ~LHSR->getAPIntValue())) + return + DAG.getSetCC(dl, VT, N0.getOperand(0), + DAG.getConstant(LHSR->getAPIntValue() ^ + RHSC->getAPIntValue(), + N0.getValueType()), + Cond); + } + + // Turn (C1-X) == C2 --> X == C1-C2 + if (ConstantSDNode *SUBC = dyn_cast(N0.getOperand(0))) { + if (N0.getOpcode() == ISD::SUB && N0.getNode()->hasOneUse()) { + return + DAG.getSetCC(dl, VT, N0.getOperand(1), + DAG.getConstant(SUBC->getAPIntValue() - + RHSC->getAPIntValue(), + N0.getValueType()), + Cond); + } + } + } + + // Simplify (X+Z) == X --> Z == 0 + if (N0.getOperand(0) == N1) + return DAG.getSetCC(dl, VT, N0.getOperand(1), + DAG.getConstant(0, N0.getValueType()), Cond); + if (N0.getOperand(1) == N1) { + if (DAG.isCommutativeBinOp(N0.getOpcode())) + return DAG.getSetCC(dl, VT, N0.getOperand(0), + DAG.getConstant(0, N0.getValueType()), Cond); + else if (N0.getNode()->hasOneUse()) { + assert(N0.getOpcode() == ISD::SUB && "Unexpected operation!"); + // (Z-X) == X --> Z == X<<1 + SDValue SH = DAG.getNode(ISD::SHL, dl, N1.getValueType(), + N1, + DAG.getConstant(1, getShiftAmountTy())); + if (!DCI.isCalledByLegalizer()) + DCI.AddToWorklist(SH.getNode()); + return DAG.getSetCC(dl, VT, N0.getOperand(0), SH, Cond); + } + } + } + + if (N1.getOpcode() == ISD::ADD || N1.getOpcode() == ISD::SUB || + N1.getOpcode() == ISD::XOR) { + // Simplify X == (X+Z) --> Z == 0 + if (N1.getOperand(0) == N0) { + return DAG.getSetCC(dl, VT, N1.getOperand(1), + DAG.getConstant(0, N1.getValueType()), Cond); + } else if (N1.getOperand(1) == N0) { + if (DAG.isCommutativeBinOp(N1.getOpcode())) { + return DAG.getSetCC(dl, VT, N1.getOperand(0), + DAG.getConstant(0, N1.getValueType()), Cond); + } else if (N1.getNode()->hasOneUse()) { + assert(N1.getOpcode() == ISD::SUB && "Unexpected operation!"); + // X == (Z-X) --> X<<1 == Z + SDValue SH = DAG.getNode(ISD::SHL, dl, N1.getValueType(), N0, + DAG.getConstant(1, getShiftAmountTy())); + if (!DCI.isCalledByLegalizer()) + DCI.AddToWorklist(SH.getNode()); + return DAG.getSetCC(dl, VT, SH, N1.getOperand(0), Cond); + } + } + } + + // Simplify x&y == y to x&y != 0 if y has exactly one bit set. + // Note that where y is variable and is known to have at most + // one bit set (for example, if it is z&1) we cannot do this; + // the expressions are not equivalent when y==0. + if (N0.getOpcode() == ISD::AND) + if (N0.getOperand(0) == N1 || N0.getOperand(1) == N1) { + if (ValueHasExactlyOneBitSet(N1, DAG)) { + Cond = ISD::getSetCCInverse(Cond, /*isInteger=*/true); + SDValue Zero = DAG.getConstant(0, N1.getValueType()); + return DAG.getSetCC(dl, VT, N0, Zero, Cond); + } + } + if (N1.getOpcode() == ISD::AND) + if (N1.getOperand(0) == N0 || N1.getOperand(1) == N0) { + if (ValueHasExactlyOneBitSet(N0, DAG)) { + Cond = ISD::getSetCCInverse(Cond, /*isInteger=*/true); + SDValue Zero = DAG.getConstant(0, N0.getValueType()); + return DAG.getSetCC(dl, VT, N1, Zero, Cond); + } + } + } + + // Fold away ALL boolean setcc's. + SDValue Temp; + if (N0.getValueType() == MVT::i1 && foldBooleans) { + switch (Cond) { + default: llvm_unreachable("Unknown integer setcc!"); + case ISD::SETEQ: // X == Y -> ~(X^Y) + Temp = DAG.getNode(ISD::XOR, dl, MVT::i1, N0, N1); + N0 = DAG.getNOT(dl, Temp, MVT::i1); + if (!DCI.isCalledByLegalizer()) + DCI.AddToWorklist(Temp.getNode()); + break; + case ISD::SETNE: // X != Y --> (X^Y) + N0 = DAG.getNode(ISD::XOR, dl, MVT::i1, N0, N1); + break; + case ISD::SETGT: // X >s Y --> X == 0 & Y == 1 --> ~X & Y + case ISD::SETULT: // X X == 0 & Y == 1 --> ~X & Y + Temp = DAG.getNOT(dl, N0, MVT::i1); + N0 = DAG.getNode(ISD::AND, dl, MVT::i1, N1, Temp); + if (!DCI.isCalledByLegalizer()) + DCI.AddToWorklist(Temp.getNode()); + break; + case ISD::SETLT: // X X == 1 & Y == 0 --> ~Y & X + case ISD::SETUGT: // X >u Y --> X == 1 & Y == 0 --> ~Y & X + Temp = DAG.getNOT(dl, N1, MVT::i1); + N0 = DAG.getNode(ISD::AND, dl, MVT::i1, N0, Temp); + if (!DCI.isCalledByLegalizer()) + DCI.AddToWorklist(Temp.getNode()); + break; + case ISD::SETULE: // X <=u Y --> X == 0 | Y == 1 --> ~X | Y + case ISD::SETGE: // X >=s Y --> X == 0 | Y == 1 --> ~X | Y + Temp = DAG.getNOT(dl, N0, MVT::i1); + N0 = DAG.getNode(ISD::OR, dl, MVT::i1, N1, Temp); + if (!DCI.isCalledByLegalizer()) + DCI.AddToWorklist(Temp.getNode()); + break; + case ISD::SETUGE: // X >=u Y --> X == 1 | Y == 0 --> ~Y | X + case ISD::SETLE: // X <=s Y --> X == 1 | Y == 0 --> ~Y | X + Temp = DAG.getNOT(dl, N1, MVT::i1); + N0 = DAG.getNode(ISD::OR, dl, MVT::i1, N0, Temp); + break; + } + if (VT != MVT::i1) { + if (!DCI.isCalledByLegalizer()) + DCI.AddToWorklist(N0.getNode()); + // FIXME: If running after legalize, we probably can't do this. + N0 = DAG.getNode(ISD::ZERO_EXTEND, dl, VT, N0); + } + return N0; + } + + // Could not fold it. + return SDValue(); +} + +/// isGAPlusOffset - Returns true (and the GlobalValue and the offset) if the +/// node is a GlobalAddress + offset. +bool TargetLowering::isGAPlusOffset(SDNode *N, GlobalValue* &GA, + int64_t &Offset) const { + if (isa(N)) { + GlobalAddressSDNode *GASD = cast(N); + GA = GASD->getGlobal(); + Offset += GASD->getOffset(); + return true; + } + + if (N->getOpcode() == ISD::ADD) { + SDValue N1 = N->getOperand(0); + SDValue N2 = N->getOperand(1); + if (isGAPlusOffset(N1.getNode(), GA, Offset)) { + ConstantSDNode *V = dyn_cast(N2); + if (V) { + Offset += V->getSExtValue(); + return true; + } + } else if (isGAPlusOffset(N2.getNode(), GA, Offset)) { + ConstantSDNode *V = dyn_cast(N1); + if (V) { + Offset += V->getSExtValue(); + return true; + } + } + } + return false; +} + + +/// isConsecutiveLoad - Return true if LD is loading 'Bytes' bytes from a +/// location that is 'Dist' units away from the location that the 'Base' load +/// is loading from. +bool TargetLowering::isConsecutiveLoad(LoadSDNode *LD, LoadSDNode *Base, + unsigned Bytes, int Dist, + const MachineFrameInfo *MFI) const { + if (LD->getChain() != Base->getChain()) + return false; + EVT VT = LD->getValueType(0); + if (VT.getSizeInBits() / 8 != Bytes) + return false; + + SDValue Loc = LD->getOperand(1); + SDValue BaseLoc = Base->getOperand(1); + if (Loc.getOpcode() == ISD::FrameIndex) { + if (BaseLoc.getOpcode() != ISD::FrameIndex) + return false; + int FI = cast(Loc)->getIndex(); + int BFI = cast(BaseLoc)->getIndex(); + int FS = MFI->getObjectSize(FI); + int BFS = MFI->getObjectSize(BFI); + if (FS != BFS || FS != (int)Bytes) return false; + return MFI->getObjectOffset(FI) == (MFI->getObjectOffset(BFI) + Dist*Bytes); + } + if (Loc.getOpcode() == ISD::ADD && Loc.getOperand(0) == BaseLoc) { + ConstantSDNode *V = dyn_cast(Loc.getOperand(1)); + if (V && (V->getSExtValue() == Dist*Bytes)) + return true; + } + + GlobalValue *GV1 = NULL; + GlobalValue *GV2 = NULL; + int64_t Offset1 = 0; + int64_t Offset2 = 0; + bool isGA1 = isGAPlusOffset(Loc.getNode(), GV1, Offset1); + bool isGA2 = isGAPlusOffset(BaseLoc.getNode(), GV2, Offset2); + if (isGA1 && isGA2 && GV1 == GV2) + return Offset1 == (Offset2 + Dist*Bytes); + return false; +} + + +SDValue TargetLowering:: +PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const { + // Default implementation: no optimization. + return SDValue(); +} + +//===----------------------------------------------------------------------===// +// Inline Assembler Implementation Methods +//===----------------------------------------------------------------------===// + + +TargetLowering::ConstraintType +TargetLowering::getConstraintType(const std::string &Constraint) const { + // FIXME: lots more standard ones to handle. + if (Constraint.size() == 1) { + switch (Constraint[0]) { + default: break; + case 'r': return C_RegisterClass; + case 'm': // memory + case 'o': // offsetable + case 'V': // not offsetable + return C_Memory; + case 'i': // Simple Integer or Relocatable Constant + case 'n': // Simple Integer + case 's': // Relocatable Constant + case 'X': // Allow ANY value. + case 'I': // Target registers. + case 'J': + case 'K': + case 'L': + case 'M': + case 'N': + case 'O': + case 'P': + return C_Other; + } + } + + if (Constraint.size() > 1 && Constraint[0] == '{' && + Constraint[Constraint.size()-1] == '}') + return C_Register; + return C_Unknown; +} + +/// LowerXConstraint - try to replace an X constraint, which matches anything, +/// with another that has more specific requirements based on the type of the +/// corresponding operand. +const char *TargetLowering::LowerXConstraint(EVT ConstraintVT) const{ + if (ConstraintVT.isInteger()) + return "r"; + if (ConstraintVT.isFloatingPoint()) + return "f"; // works for many targets + return 0; +} + +/// LowerAsmOperandForConstraint - Lower the specified operand into the Ops +/// vector. If it is invalid, don't add anything to Ops. +void TargetLowering::LowerAsmOperandForConstraint(SDValue Op, + char ConstraintLetter, + bool hasMemory, + std::vector &Ops, + SelectionDAG &DAG) const { + switch (ConstraintLetter) { + default: break; + case 'X': // Allows any operand; labels (basic block) use this. + if (Op.getOpcode() == ISD::BasicBlock) { + Ops.push_back(Op); + return; + } + // fall through + case 'i': // Simple Integer or Relocatable Constant + case 'n': // Simple Integer + case 's': { // Relocatable Constant + // These operands are interested in values of the form (GV+C), where C may + // be folded in as an offset of GV, or it may be explicitly added. Also, it + // is possible and fine if either GV or C are missing. + ConstantSDNode *C = dyn_cast(Op); + GlobalAddressSDNode *GA = dyn_cast(Op); + + // If we have "(add GV, C)", pull out GV/C + if (Op.getOpcode() == ISD::ADD) { + C = dyn_cast(Op.getOperand(1)); + GA = dyn_cast(Op.getOperand(0)); + if (C == 0 || GA == 0) { + C = dyn_cast(Op.getOperand(0)); + GA = dyn_cast(Op.getOperand(1)); + } + if (C == 0 || GA == 0) + C = 0, GA = 0; + } + + // If we find a valid operand, map to the TargetXXX version so that the + // value itself doesn't get selected. + if (GA) { // Either &GV or &GV+C + if (ConstraintLetter != 'n') { + int64_t Offs = GA->getOffset(); + if (C) Offs += C->getZExtValue(); + Ops.push_back(DAG.getTargetGlobalAddress(GA->getGlobal(), + Op.getValueType(), Offs)); + return; + } + } + if (C) { // just C, no GV. + // Simple constants are not allowed for 's'. + if (ConstraintLetter != 's') { + // gcc prints these as sign extended. Sign extend value to 64 bits + // now; without this it would get ZExt'd later in + // ScheduleDAGSDNodes::EmitNode, which is very generic. + Ops.push_back(DAG.getTargetConstant(C->getAPIntValue().getSExtValue(), + MVT::i64)); + return; + } + } + break; + } + } +} + +std::vector TargetLowering:: +getRegClassForInlineAsmConstraint(const std::string &Constraint, + EVT VT) const { + return std::vector(); +} + + +std::pair TargetLowering:: +getRegForInlineAsmConstraint(const std::string &Constraint, + EVT VT) const { + if (Constraint[0] != '{') + return std::pair(0, 0); + assert(*(Constraint.end()-1) == '}' && "Not a brace enclosed constraint?"); + + // Remove the braces from around the name. + StringRef RegName(Constraint.data()+1, Constraint.size()-2); + + // Figure out which register class contains this reg. + const TargetRegisterInfo *RI = TM.getRegisterInfo(); + for (TargetRegisterInfo::regclass_iterator RCI = RI->regclass_begin(), + E = RI->regclass_end(); RCI != E; ++RCI) { + const TargetRegisterClass *RC = *RCI; + + // If none of the the value types for this register class are valid, we + // can't use it. For example, 64-bit reg classes on 32-bit targets. + bool isLegal = false; + for (TargetRegisterClass::vt_iterator I = RC->vt_begin(), E = RC->vt_end(); + I != E; ++I) { + if (isTypeLegal(*I)) { + isLegal = true; + break; + } + } + + if (!isLegal) continue; + + for (TargetRegisterClass::iterator I = RC->begin(), E = RC->end(); + I != E; ++I) { + if (RegName.equals_lower(RI->getName(*I))) + return std::make_pair(*I, RC); + } + } + + return std::pair(0, 0); +} + +//===----------------------------------------------------------------------===// +// Constraint Selection. + +/// isMatchingInputConstraint - Return true of this is an input operand that is +/// a matching constraint like "4". +bool TargetLowering::AsmOperandInfo::isMatchingInputConstraint() const { + assert(!ConstraintCode.empty() && "No known constraint!"); + return isdigit(ConstraintCode[0]); +} + +/// getMatchedOperand - If this is an input matching constraint, this method +/// returns the output operand it matches. +unsigned TargetLowering::AsmOperandInfo::getMatchedOperand() const { + assert(!ConstraintCode.empty() && "No known constraint!"); + return atoi(ConstraintCode.c_str()); +} + + +/// getConstraintGenerality - Return an integer indicating how general CT +/// is. +static unsigned getConstraintGenerality(TargetLowering::ConstraintType CT) { + switch (CT) { + default: llvm_unreachable("Unknown constraint type!"); + case TargetLowering::C_Other: + case TargetLowering::C_Unknown: + return 0; + case TargetLowering::C_Register: + return 1; + case TargetLowering::C_RegisterClass: + return 2; + case TargetLowering::C_Memory: + return 3; + } +} + +/// ChooseConstraint - If there are multiple different constraints that we +/// could pick for this operand (e.g. "imr") try to pick the 'best' one. +/// This is somewhat tricky: constraints fall into four classes: +/// Other -> immediates and magic values +/// Register -> one specific register +/// RegisterClass -> a group of regs +/// Memory -> memory +/// Ideally, we would pick the most specific constraint possible: if we have +/// something that fits into a register, we would pick it. The problem here +/// is that if we have something that could either be in a register or in +/// memory that use of the register could cause selection of *other* +/// operands to fail: they might only succeed if we pick memory. Because of +/// this the heuristic we use is: +/// +/// 1) If there is an 'other' constraint, and if the operand is valid for +/// that constraint, use it. This makes us take advantage of 'i' +/// constraints when available. +/// 2) Otherwise, pick the most general constraint present. This prefers +/// 'm' over 'r', for example. +/// +static void ChooseConstraint(TargetLowering::AsmOperandInfo &OpInfo, + bool hasMemory, const TargetLowering &TLI, + SDValue Op, SelectionDAG *DAG) { + assert(OpInfo.Codes.size() > 1 && "Doesn't have multiple constraint options"); + unsigned BestIdx = 0; + TargetLowering::ConstraintType BestType = TargetLowering::C_Unknown; + int BestGenerality = -1; + + // Loop over the options, keeping track of the most general one. + for (unsigned i = 0, e = OpInfo.Codes.size(); i != e; ++i) { + TargetLowering::ConstraintType CType = + TLI.getConstraintType(OpInfo.Codes[i]); + + // If this is an 'other' constraint, see if the operand is valid for it. + // For example, on X86 we might have an 'rI' constraint. If the operand + // is an integer in the range [0..31] we want to use I (saving a load + // of a register), otherwise we must use 'r'. + if (CType == TargetLowering::C_Other && Op.getNode()) { + assert(OpInfo.Codes[i].size() == 1 && + "Unhandled multi-letter 'other' constraint"); + std::vector ResultOps; + TLI.LowerAsmOperandForConstraint(Op, OpInfo.Codes[i][0], hasMemory, + ResultOps, *DAG); + if (!ResultOps.empty()) { + BestType = CType; + BestIdx = i; + break; + } + } + + // This constraint letter is more general than the previous one, use it. + int Generality = getConstraintGenerality(CType); + if (Generality > BestGenerality) { + BestType = CType; + BestIdx = i; + BestGenerality = Generality; + } + } + + OpInfo.ConstraintCode = OpInfo.Codes[BestIdx]; + OpInfo.ConstraintType = BestType; +} + +/// ComputeConstraintToUse - Determines the constraint code and constraint +/// type to use for the specific AsmOperandInfo, setting +/// OpInfo.ConstraintCode and OpInfo.ConstraintType. +void TargetLowering::ComputeConstraintToUse(AsmOperandInfo &OpInfo, + SDValue Op, + bool hasMemory, + SelectionDAG *DAG) const { + assert(!OpInfo.Codes.empty() && "Must have at least one constraint"); + + // Single-letter constraints ('r') are very common. + if (OpInfo.Codes.size() == 1) { + OpInfo.ConstraintCode = OpInfo.Codes[0]; + OpInfo.ConstraintType = getConstraintType(OpInfo.ConstraintCode); + } else { + ChooseConstraint(OpInfo, hasMemory, *this, Op, DAG); + } + + // 'X' matches anything. + if (OpInfo.ConstraintCode == "X" && OpInfo.CallOperandVal) { + // Labels and constants are handled elsewhere ('X' is the only thing + // that matches labels). For Functions, the type here is the type of + // the result, which is not what we want to look at; leave them alone. + Value *v = OpInfo.CallOperandVal; + if (isa(v) || isa(v) || isa(v)) { + OpInfo.CallOperandVal = v; + return; + } + + // Otherwise, try to resolve it to something we know about by looking at + // the actual operand type. + if (const char *Repl = LowerXConstraint(OpInfo.ConstraintVT)) { + OpInfo.ConstraintCode = Repl; + OpInfo.ConstraintType = getConstraintType(OpInfo.ConstraintCode); + } + } +} + +//===----------------------------------------------------------------------===// +// Loop Strength Reduction hooks +//===----------------------------------------------------------------------===// + +/// isLegalAddressingMode - Return true if the addressing mode represented +/// by AM is legal for this target, for a load/store of the specified type. +bool TargetLowering::isLegalAddressingMode(const AddrMode &AM, + const Type *Ty) const { + // The default implementation of this implements a conservative RISCy, r+r and + // r+i addr mode. + + // Allows a sign-extended 16-bit immediate field. + if (AM.BaseOffs <= -(1LL << 16) || AM.BaseOffs >= (1LL << 16)-1) + return false; + + // No global is ever allowed as a base. + if (AM.BaseGV) + return false; + + // Only support r+r, + switch (AM.Scale) { + case 0: // "r+i" or just "i", depending on HasBaseReg. + break; + case 1: + if (AM.HasBaseReg && AM.BaseOffs) // "r+r+i" is not allowed. + return false; + // Otherwise we have r+r or r+i. + break; + case 2: + if (AM.HasBaseReg || AM.BaseOffs) // 2*r+r or 2*r+i is not allowed. + return false; + // Allow 2*r as r+r. + break; + } + + return true; +} + +/// BuildSDIVSequence - Given an ISD::SDIV node expressing a divide by constant, +/// return a DAG expression to select that will generate the same value by +/// multiplying by a magic number. See: +/// +SDValue TargetLowering::BuildSDIV(SDNode *N, SelectionDAG &DAG, + std::vector* Created) const { + EVT VT = N->getValueType(0); + DebugLoc dl= N->getDebugLoc(); + + // Check to see if we can do this. + // FIXME: We should be more aggressive here. + if (!isTypeLegal(VT)) + return SDValue(); + + APInt d = cast(N->getOperand(1))->getAPIntValue(); + APInt::ms magics = d.magic(); + + // Multiply the numerator (operand 0) by the magic value + // FIXME: We should support doing a MUL in a wider type + SDValue Q; + if (isOperationLegalOrCustom(ISD::MULHS, VT)) + Q = DAG.getNode(ISD::MULHS, dl, VT, N->getOperand(0), + DAG.getConstant(magics.m, VT)); + else if (isOperationLegalOrCustom(ISD::SMUL_LOHI, VT)) + Q = SDValue(DAG.getNode(ISD::SMUL_LOHI, dl, DAG.getVTList(VT, VT), + N->getOperand(0), + DAG.getConstant(magics.m, VT)).getNode(), 1); + else + return SDValue(); // No mulhs or equvialent + // If d > 0 and m < 0, add the numerator + if (d.isStrictlyPositive() && magics.m.isNegative()) { + Q = DAG.getNode(ISD::ADD, dl, VT, Q, N->getOperand(0)); + if (Created) + Created->push_back(Q.getNode()); + } + // If d < 0 and m > 0, subtract the numerator. + if (d.isNegative() && magics.m.isStrictlyPositive()) { + Q = DAG.getNode(ISD::SUB, dl, VT, Q, N->getOperand(0)); + if (Created) + Created->push_back(Q.getNode()); + } + // Shift right algebraic if shift value is nonzero + if (magics.s > 0) { + Q = DAG.getNode(ISD::SRA, dl, VT, Q, + DAG.getConstant(magics.s, getShiftAmountTy())); + if (Created) + Created->push_back(Q.getNode()); + } + // Extract the sign bit and add it to the quotient + SDValue T = + DAG.getNode(ISD::SRL, dl, VT, Q, DAG.getConstant(VT.getSizeInBits()-1, + getShiftAmountTy())); + if (Created) + Created->push_back(T.getNode()); + return DAG.getNode(ISD::ADD, dl, VT, Q, T); +} + +/// BuildUDIVSequence - Given an ISD::UDIV node expressing a divide by constant, +/// return a DAG expression to select that will generate the same value by +/// multiplying by a magic number. See: +/// +SDValue TargetLowering::BuildUDIV(SDNode *N, SelectionDAG &DAG, + std::vector* Created) const { + EVT VT = N->getValueType(0); + DebugLoc dl = N->getDebugLoc(); + + // Check to see if we can do this. + // FIXME: We should be more aggressive here. + if (!isTypeLegal(VT)) + return SDValue(); + + // FIXME: We should use a narrower constant when the upper + // bits are known to be zero. + ConstantSDNode *N1C = cast(N->getOperand(1)); + APInt::mu magics = N1C->getAPIntValue().magicu(); + + // Multiply the numerator (operand 0) by the magic value + // FIXME: We should support doing a MUL in a wider type + SDValue Q; + if (isOperationLegalOrCustom(ISD::MULHU, VT)) + Q = DAG.getNode(ISD::MULHU, dl, VT, N->getOperand(0), + DAG.getConstant(magics.m, VT)); + else if (isOperationLegalOrCustom(ISD::UMUL_LOHI, VT)) + Q = SDValue(DAG.getNode(ISD::UMUL_LOHI, dl, DAG.getVTList(VT, VT), + N->getOperand(0), + DAG.getConstant(magics.m, VT)).getNode(), 1); + else + return SDValue(); // No mulhu or equvialent + if (Created) + Created->push_back(Q.getNode()); + + if (magics.a == 0) { + assert(magics.s < N1C->getAPIntValue().getBitWidth() && + "We shouldn't generate an undefined shift!"); + return DAG.getNode(ISD::SRL, dl, VT, Q, + DAG.getConstant(magics.s, getShiftAmountTy())); + } else { + SDValue NPQ = DAG.getNode(ISD::SUB, dl, VT, N->getOperand(0), Q); + if (Created) + Created->push_back(NPQ.getNode()); + NPQ = DAG.getNode(ISD::SRL, dl, VT, NPQ, + DAG.getConstant(1, getShiftAmountTy())); + if (Created) + Created->push_back(NPQ.getNode()); + NPQ = DAG.getNode(ISD::ADD, dl, VT, NPQ, Q); + if (Created) + Created->push_back(NPQ.getNode()); + return DAG.getNode(ISD::SRL, dl, VT, NPQ, + DAG.getConstant(magics.s-1, getShiftAmountTy())); + } +} diff --git a/libclamav/c++/llvm/lib/CodeGen/ShadowStackGC.cpp b/libclamav/c++/llvm/lib/CodeGen/ShadowStackGC.cpp new file mode 100644 index 000000000..0e6d4796e --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/ShadowStackGC.cpp @@ -0,0 +1,449 @@ +//===-- ShadowStackGC.cpp - GC support for uncooperative targets ----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements lowering for the llvm.gc* intrinsics for targets that do +// not natively support them (which includes the C backend). Note that the code +// generated is not quite as efficient as algorithms which generate stack maps +// to identify roots. +// +// This pass implements the code transformation described in this paper: +// "Accurate Garbage Collection in an Uncooperative Environment" +// Fergus Henderson, ISMM, 2002 +// +// In runtime/GC/SemiSpace.cpp is a prototype runtime which is compatible with +// ShadowStackGC. +// +// In order to support this particular transformation, all stack roots are +// coallocated in the stack. This allows a fully target-independent stack map +// while introducing only minor runtime overhead. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "shadowstackgc" +#include "llvm/CodeGen/GCs.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/CodeGen/GCStrategy.h" +#include "llvm/IntrinsicInst.h" +#include "llvm/Module.h" +#include "llvm/Support/IRBuilder.h" + +using namespace llvm; + +namespace { + + class ShadowStackGC : public GCStrategy { + /// RootChain - This is the global linked-list that contains the chain of GC + /// roots. + GlobalVariable *Head; + + /// StackEntryTy - Abstract type of a link in the shadow stack. + /// + const StructType *StackEntryTy; + + /// Roots - GC roots in the current function. Each is a pair of the + /// intrinsic call and its corresponding alloca. + std::vector > Roots; + + public: + ShadowStackGC(); + + bool initializeCustomLowering(Module &M); + bool performCustomLowering(Function &F); + + private: + bool IsNullValue(Value *V); + Constant *GetFrameMap(Function &F); + const Type* GetConcreteStackEntryType(Function &F); + void CollectRoots(Function &F); + static GetElementPtrInst *CreateGEP(LLVMContext &Context, + IRBuilder<> &B, Value *BasePtr, + int Idx1, const char *Name); + static GetElementPtrInst *CreateGEP(LLVMContext &Context, + IRBuilder<> &B, Value *BasePtr, + int Idx1, int Idx2, const char *Name); + }; + +} + +static GCRegistry::Add +X("shadow-stack", "Very portable GC for uncooperative code generators"); + +namespace { + /// EscapeEnumerator - This is a little algorithm to find all escape points + /// from a function so that "finally"-style code can be inserted. In addition + /// to finding the existing return and unwind instructions, it also (if + /// necessary) transforms any call instructions into invokes and sends them to + /// a landing pad. + /// + /// It's wrapped up in a state machine using the same transform C# uses for + /// 'yield return' enumerators, This transform allows it to be non-allocating. + class EscapeEnumerator { + Function &F; + const char *CleanupBBName; + + // State. + int State; + Function::iterator StateBB, StateE; + IRBuilder<> Builder; + + public: + EscapeEnumerator(Function &F, const char *N = "cleanup") + : F(F), CleanupBBName(N), State(0), Builder(F.getContext()) {} + + IRBuilder<> *Next() { + switch (State) { + default: + return 0; + + case 0: + StateBB = F.begin(); + StateE = F.end(); + State = 1; + + case 1: + // Find all 'return' and 'unwind' instructions. + while (StateBB != StateE) { + BasicBlock *CurBB = StateBB++; + + // Branches and invokes do not escape, only unwind and return do. + TerminatorInst *TI = CurBB->getTerminator(); + if (!isa(TI) && !isa(TI)) + continue; + + Builder.SetInsertPoint(TI->getParent(), TI); + return &Builder; + } + + State = 2; + + // Find all 'call' instructions. + SmallVector Calls; + for (Function::iterator BB = F.begin(), + E = F.end(); BB != E; ++BB) + for (BasicBlock::iterator II = BB->begin(), + EE = BB->end(); II != EE; ++II) + if (CallInst *CI = dyn_cast(II)) + if (!CI->getCalledFunction() || + !CI->getCalledFunction()->getIntrinsicID()) + Calls.push_back(CI); + + if (Calls.empty()) + return 0; + + // Create a cleanup block. + BasicBlock *CleanupBB = BasicBlock::Create(F.getContext(), + CleanupBBName, &F); + UnwindInst *UI = new UnwindInst(F.getContext(), CleanupBB); + + // Transform the 'call' instructions into 'invoke's branching to the + // cleanup block. Go in reverse order to make prettier BB names. + SmallVector Args; + for (unsigned I = Calls.size(); I != 0; ) { + CallInst *CI = cast(Calls[--I]); + + // Split the basic block containing the function call. + BasicBlock *CallBB = CI->getParent(); + BasicBlock *NewBB = + CallBB->splitBasicBlock(CI, CallBB->getName() + ".cont"); + + // Remove the unconditional branch inserted at the end of CallBB. + CallBB->getInstList().pop_back(); + NewBB->getInstList().remove(CI); + + // Create a new invoke instruction. + Args.clear(); + Args.append(CI->op_begin() + 1, CI->op_end()); + + InvokeInst *II = InvokeInst::Create(CI->getOperand(0), + NewBB, CleanupBB, + Args.begin(), Args.end(), + CI->getName(), CallBB); + II->setCallingConv(CI->getCallingConv()); + II->setAttributes(CI->getAttributes()); + CI->replaceAllUsesWith(II); + delete CI; + } + + Builder.SetInsertPoint(UI->getParent(), UI); + return &Builder; + } + } + }; +} + +// ----------------------------------------------------------------------------- + +void llvm::linkShadowStackGC() { } + +ShadowStackGC::ShadowStackGC() : Head(0), StackEntryTy(0) { + InitRoots = true; + CustomRoots = true; +} + +Constant *ShadowStackGC::GetFrameMap(Function &F) { + // doInitialization creates the abstract type of this value. + const Type *VoidPtr = Type::getInt8PtrTy(F.getContext()); + + // Truncate the ShadowStackDescriptor if some metadata is null. + unsigned NumMeta = 0; + SmallVector Metadata; + for (unsigned I = 0; I != Roots.size(); ++I) { + Constant *C = cast(Roots[I].first->getOperand(2)); + if (!C->isNullValue()) + NumMeta = I + 1; + Metadata.push_back(ConstantExpr::getBitCast(C, VoidPtr)); + } + + Constant *BaseElts[] = { + ConstantInt::get(Type::getInt32Ty(F.getContext()), Roots.size(), false), + ConstantInt::get(Type::getInt32Ty(F.getContext()), NumMeta, false), + }; + + Constant *DescriptorElts[] = { + ConstantStruct::get(F.getContext(), BaseElts, 2, false), + ConstantArray::get(ArrayType::get(VoidPtr, NumMeta), + Metadata.begin(), NumMeta) + }; + + Constant *FrameMap = ConstantStruct::get(F.getContext(), DescriptorElts, 2, + false); + + std::string TypeName("gc_map."); + TypeName += utostr(NumMeta); + F.getParent()->addTypeName(TypeName, FrameMap->getType()); + + // FIXME: Is this actually dangerous as WritingAnLLVMPass.html claims? Seems + // that, short of multithreaded LLVM, it should be safe; all that is + // necessary is that a simple Module::iterator loop not be invalidated. + // Appending to the GlobalVariable list is safe in that sense. + // + // All of the output passes emit globals last. The ExecutionEngine + // explicitly supports adding globals to the module after + // initialization. + // + // Still, if it isn't deemed acceptable, then this transformation needs + // to be a ModulePass (which means it cannot be in the 'llc' pipeline + // (which uses a FunctionPassManager (which segfaults (not asserts) if + // provided a ModulePass))). + Constant *GV = new GlobalVariable(*F.getParent(), FrameMap->getType(), true, + GlobalVariable::InternalLinkage, + FrameMap, "__gc_" + F.getName()); + + Constant *GEPIndices[2] = { + ConstantInt::get(Type::getInt32Ty(F.getContext()), 0), + ConstantInt::get(Type::getInt32Ty(F.getContext()), 0) + }; + return ConstantExpr::getGetElementPtr(GV, GEPIndices, 2); +} + +const Type* ShadowStackGC::GetConcreteStackEntryType(Function &F) { + // doInitialization creates the generic version of this type. + std::vector EltTys; + EltTys.push_back(StackEntryTy); + for (size_t I = 0; I != Roots.size(); I++) + EltTys.push_back(Roots[I].second->getAllocatedType()); + Type *Ty = StructType::get(F.getContext(), EltTys); + + std::string TypeName("gc_stackentry."); + TypeName += F.getName(); + F.getParent()->addTypeName(TypeName, Ty); + + return Ty; +} + +/// doInitialization - If this module uses the GC intrinsics, find them now. If +/// not, exit fast. +bool ShadowStackGC::initializeCustomLowering(Module &M) { + // struct FrameMap { + // int32_t NumRoots; // Number of roots in stack frame. + // int32_t NumMeta; // Number of metadata descriptors. May be < NumRoots. + // void *Meta[]; // May be absent for roots without metadata. + // }; + std::vector EltTys; + // 32 bits is ok up to a 32GB stack frame. :) + EltTys.push_back(Type::getInt32Ty(M.getContext())); + // Specifies length of variable length array. + EltTys.push_back(Type::getInt32Ty(M.getContext())); + StructType *FrameMapTy = StructType::get(M.getContext(), EltTys); + M.addTypeName("gc_map", FrameMapTy); + PointerType *FrameMapPtrTy = PointerType::getUnqual(FrameMapTy); + + // struct StackEntry { + // ShadowStackEntry *Next; // Caller's stack entry. + // FrameMap *Map; // Pointer to constant FrameMap. + // void *Roots[]; // Stack roots (in-place array, so we pretend). + // }; + OpaqueType *RecursiveTy = OpaqueType::get(M.getContext()); + + EltTys.clear(); + EltTys.push_back(PointerType::getUnqual(RecursiveTy)); + EltTys.push_back(FrameMapPtrTy); + PATypeHolder LinkTyH = StructType::get(M.getContext(), EltTys); + + RecursiveTy->refineAbstractTypeTo(LinkTyH.get()); + StackEntryTy = cast(LinkTyH.get()); + const PointerType *StackEntryPtrTy = PointerType::getUnqual(StackEntryTy); + M.addTypeName("gc_stackentry", LinkTyH.get()); // FIXME: Is this safe from + // a FunctionPass? + + // Get the root chain if it already exists. + Head = M.getGlobalVariable("llvm_gc_root_chain"); + if (!Head) { + // If the root chain does not exist, insert a new one with linkonce + // linkage! + Head = new GlobalVariable(M, StackEntryPtrTy, false, + GlobalValue::LinkOnceAnyLinkage, + Constant::getNullValue(StackEntryPtrTy), + "llvm_gc_root_chain"); + } else if (Head->hasExternalLinkage() && Head->isDeclaration()) { + Head->setInitializer(Constant::getNullValue(StackEntryPtrTy)); + Head->setLinkage(GlobalValue::LinkOnceAnyLinkage); + } + + return true; +} + +bool ShadowStackGC::IsNullValue(Value *V) { + if (Constant *C = dyn_cast(V)) + return C->isNullValue(); + return false; +} + +void ShadowStackGC::CollectRoots(Function &F) { + // FIXME: Account for original alignment. Could fragment the root array. + // Approach 1: Null initialize empty slots at runtime. Yuck. + // Approach 2: Emit a map of the array instead of just a count. + + assert(Roots.empty() && "Not cleaned up?"); + + SmallVector,16> MetaRoots; + + for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB) + for (BasicBlock::iterator II = BB->begin(), E = BB->end(); II != E;) + if (IntrinsicInst *CI = dyn_cast(II++)) + if (Function *F = CI->getCalledFunction()) + if (F->getIntrinsicID() == Intrinsic::gcroot) { + std::pair Pair = std::make_pair( + CI, cast(CI->getOperand(1)->stripPointerCasts())); + if (IsNullValue(CI->getOperand(2))) + Roots.push_back(Pair); + else + MetaRoots.push_back(Pair); + } + + // Number roots with metadata (usually empty) at the beginning, so that the + // FrameMap::Meta array can be elided. + Roots.insert(Roots.begin(), MetaRoots.begin(), MetaRoots.end()); +} + +GetElementPtrInst * +ShadowStackGC::CreateGEP(LLVMContext &Context, IRBuilder<> &B, Value *BasePtr, + int Idx, int Idx2, const char *Name) { + Value *Indices[] = { ConstantInt::get(Type::getInt32Ty(Context), 0), + ConstantInt::get(Type::getInt32Ty(Context), Idx), + ConstantInt::get(Type::getInt32Ty(Context), Idx2) }; + Value* Val = B.CreateGEP(BasePtr, Indices, Indices + 3, Name); + + assert(isa(Val) && "Unexpected folded constant"); + + return dyn_cast(Val); +} + +GetElementPtrInst * +ShadowStackGC::CreateGEP(LLVMContext &Context, IRBuilder<> &B, Value *BasePtr, + int Idx, const char *Name) { + Value *Indices[] = { ConstantInt::get(Type::getInt32Ty(Context), 0), + ConstantInt::get(Type::getInt32Ty(Context), Idx) }; + Value *Val = B.CreateGEP(BasePtr, Indices, Indices + 2, Name); + + assert(isa(Val) && "Unexpected folded constant"); + + return dyn_cast(Val); +} + +/// runOnFunction - Insert code to maintain the shadow stack. +bool ShadowStackGC::performCustomLowering(Function &F) { + LLVMContext &Context = F.getContext(); + + // Find calls to llvm.gcroot. + CollectRoots(F); + + // If there are no roots in this function, then there is no need to add a + // stack map entry for it. + if (Roots.empty()) + return false; + + // Build the constant map and figure the type of the shadow stack entry. + Value *FrameMap = GetFrameMap(F); + const Type *ConcreteStackEntryTy = GetConcreteStackEntryType(F); + + // Build the shadow stack entry at the very start of the function. + BasicBlock::iterator IP = F.getEntryBlock().begin(); + IRBuilder<> AtEntry(IP->getParent(), IP); + + Instruction *StackEntry = AtEntry.CreateAlloca(ConcreteStackEntryTy, 0, + "gc_frame"); + + while (isa(IP)) ++IP; + AtEntry.SetInsertPoint(IP->getParent(), IP); + + // Initialize the map pointer and load the current head of the shadow stack. + Instruction *CurrentHead = AtEntry.CreateLoad(Head, "gc_currhead"); + Instruction *EntryMapPtr = CreateGEP(Context, AtEntry, StackEntry, + 0,1,"gc_frame.map"); + AtEntry.CreateStore(FrameMap, EntryMapPtr); + + // After all the allocas... + for (unsigned I = 0, E = Roots.size(); I != E; ++I) { + // For each root, find the corresponding slot in the aggregate... + Value *SlotPtr = CreateGEP(Context, AtEntry, StackEntry, 1 + I, "gc_root"); + + // And use it in lieu of the alloca. + AllocaInst *OriginalAlloca = Roots[I].second; + SlotPtr->takeName(OriginalAlloca); + OriginalAlloca->replaceAllUsesWith(SlotPtr); + } + + // Move past the original stores inserted by GCStrategy::InitRoots. This isn't + // really necessary (the collector would never see the intermediate state at + // runtime), but it's nicer not to push the half-initialized entry onto the + // shadow stack. + while (isa(IP)) ++IP; + AtEntry.SetInsertPoint(IP->getParent(), IP); + + // Push the entry onto the shadow stack. + Instruction *EntryNextPtr = CreateGEP(Context, AtEntry, + StackEntry,0,0,"gc_frame.next"); + Instruction *NewHeadVal = CreateGEP(Context, AtEntry, + StackEntry, 0, "gc_newhead"); + AtEntry.CreateStore(CurrentHead, EntryNextPtr); + AtEntry.CreateStore(NewHeadVal, Head); + + // For each instruction that escapes... + EscapeEnumerator EE(F, "gc_cleanup"); + while (IRBuilder<> *AtExit = EE.Next()) { + // Pop the entry from the shadow stack. Don't reuse CurrentHead from + // AtEntry, since that would make the value live for the entire function. + Instruction *EntryNextPtr2 = CreateGEP(Context, *AtExit, StackEntry, 0, 0, + "gc_frame.next"); + Value *SavedHead = AtExit->CreateLoad(EntryNextPtr2, "gc_savedhead"); + AtExit->CreateStore(SavedHead, Head); + } + + // Delete the original allocas (which are no longer used) and the intrinsic + // calls (which are no longer valid). Doing this last avoids invalidating + // iterators. + for (unsigned I = 0, E = Roots.size(); I != E; ++I) { + Roots[I].first->eraseFromParent(); + Roots[I].second->eraseFromParent(); + } + + Roots.clear(); + return true; +} diff --git a/libclamav/c++/llvm/lib/CodeGen/ShrinkWrapping.cpp b/libclamav/c++/llvm/lib/CodeGen/ShrinkWrapping.cpp new file mode 100644 index 000000000..8070570cb --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/ShrinkWrapping.cpp @@ -0,0 +1,1152 @@ +//===-- ShrinkWrapping.cpp - Reduce spills/restores of callee-saved regs --===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements a shrink wrapping variant of prolog/epilog insertion: +// - Spills and restores of callee-saved registers (CSRs) are placed in the +// machine CFG to tightly surround their uses so that execution paths that +// do not use CSRs do not pay the spill/restore penalty. +// +// - Avoiding placment of spills/restores in loops: if a CSR is used inside a +// loop the spills are placed in the loop preheader, and restores are +// placed in the loop exit nodes (the successors of loop _exiting_ nodes). +// +// - Covering paths without CSR uses: +// If a region in a CFG uses CSRs and has multiple entry and/or exit points, +// the use info for the CSRs inside the region is propagated outward in the +// CFG to ensure validity of the spill/restore placements. This decreases +// the effectiveness of shrink wrapping but does not require edge splitting +// in the machine CFG. +// +// This shrink wrapping implementation uses an iterative analysis to determine +// which basic blocks require spills and restores for CSRs. +// +// This pass uses MachineDominators and MachineLoopInfo. Loop information +// is used to prevent placement of callee-saved register spills/restores +// in the bodies of loops. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "shrink-wrap" + +#include "PrologEpilogInserter.h" +#include "llvm/CodeGen/MachineDominators.h" +#include "llvm/CodeGen/MachineLoopInfo.h" +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/ADT/SparseBitVector.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/PostOrderIterator.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/Debug.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/Statistic.h" +#include + +using namespace llvm; + +STATISTIC(numSRReduced, "Number of CSR spills+restores reduced."); + +// Shrink Wrapping: +static cl::opt +ShrinkWrapping("shrink-wrap", + cl::desc("Shrink wrap callee-saved register spills/restores")); + +// Shrink wrap only the specified function, a debugging aid. +static cl::opt +ShrinkWrapFunc("shrink-wrap-func", cl::Hidden, + cl::desc("Shrink wrap the specified function"), + cl::value_desc("funcname"), + cl::init("")); + +// Debugging level for shrink wrapping. +enum ShrinkWrapDebugLevel { + None, BasicInfo, Iterations, Details +}; + +static cl::opt +ShrinkWrapDebugging("shrink-wrap-dbg", cl::Hidden, + cl::desc("Print shrink wrapping debugging information"), + cl::values( + clEnumVal(None , "disable debug output"), + clEnumVal(BasicInfo , "print basic DF sets"), + clEnumVal(Iterations, "print SR sets for each iteration"), + clEnumVal(Details , "print all DF sets"), + clEnumValEnd)); + + +void PEI::getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesCFG(); + if (ShrinkWrapping || ShrinkWrapFunc != "") { + AU.addRequired(); + AU.addRequired(); + } + AU.addPreserved(); + AU.addPreserved(); + MachineFunctionPass::getAnalysisUsage(AU); +} + +//===----------------------------------------------------------------------===// +// ShrinkWrapping implementation +//===----------------------------------------------------------------------===// + +// Convienences for dealing with machine loops. +MachineBasicBlock* PEI::getTopLevelLoopPreheader(MachineLoop* LP) { + assert(LP && "Machine loop is NULL."); + MachineBasicBlock* PHDR = LP->getLoopPreheader(); + MachineLoop* PLP = LP->getParentLoop(); + while (PLP) { + PHDR = PLP->getLoopPreheader(); + PLP = PLP->getParentLoop(); + } + return PHDR; +} + +MachineLoop* PEI::getTopLevelLoopParent(MachineLoop *LP) { + if (LP == 0) + return 0; + MachineLoop* PLP = LP->getParentLoop(); + while (PLP) { + LP = PLP; + PLP = PLP->getParentLoop(); + } + return LP; +} + +bool PEI::isReturnBlock(MachineBasicBlock* MBB) { + return (MBB && !MBB->empty() && MBB->back().getDesc().isReturn()); +} + +// Initialize shrink wrapping DFA sets, called before iterations. +void PEI::clearAnticAvailSets() { + AnticIn.clear(); + AnticOut.clear(); + AvailIn.clear(); + AvailOut.clear(); +} + +// Clear all sets constructed by shrink wrapping. +void PEI::clearAllSets() { + ReturnBlocks.clear(); + clearAnticAvailSets(); + UsedCSRegs.clear(); + CSRUsed.clear(); + TLLoops.clear(); + CSRSave.clear(); + CSRRestore.clear(); +} + +// Initialize all shrink wrapping data. +void PEI::initShrinkWrappingInfo() { + clearAllSets(); + EntryBlock = 0; +#ifndef NDEBUG + HasFastExitPath = false; +#endif + ShrinkWrapThisFunction = ShrinkWrapping; + // DEBUG: enable or disable shrink wrapping for the current function + // via --shrink-wrap-func=. +#ifndef NDEBUG + if (ShrinkWrapFunc != "") { + std::string MFName = MF->getFunction()->getNameStr(); + ShrinkWrapThisFunction = (MFName == ShrinkWrapFunc); + } +#endif +} + + +/// placeCSRSpillsAndRestores - determine which MBBs of the function +/// need save, restore code for callee-saved registers by doing a DF analysis +/// similar to the one used in code motion (GVNPRE). This produces maps of MBBs +/// to sets of registers (CSRs) for saves and restores. MachineLoopInfo +/// is used to ensure that CSR save/restore code is not placed inside loops. +/// This function computes the maps of MBBs -> CSRs to spill and restore +/// in CSRSave, CSRRestore. +/// +/// If shrink wrapping is not being performed, place all spills in +/// the entry block, all restores in return blocks. In this case, +/// CSRSave has a single mapping, CSRRestore has mappings for each +/// return block. +/// +void PEI::placeCSRSpillsAndRestores(MachineFunction &Fn) { + + DEBUG(MF = &Fn); + + initShrinkWrappingInfo(); + + DEBUG(if (ShrinkWrapThisFunction) { + errs() << "Place CSR spills/restores for " + << MF->getFunction()->getName() << "\n"; + }); + + if (calculateSets(Fn)) + placeSpillsAndRestores(Fn); +} + +/// calcAnticInOut - calculate the anticipated in/out reg sets +/// for the given MBB by looking forward in the MCFG at MBB's +/// successors. +/// +bool PEI::calcAnticInOut(MachineBasicBlock* MBB) { + bool changed = false; + + // AnticOut[MBB] = INTERSECT(AnticIn[S] for S in SUCCESSORS(MBB)) + SmallVector successors; + for (MachineBasicBlock::succ_iterator SI = MBB->succ_begin(), + SE = MBB->succ_end(); SI != SE; ++SI) { + MachineBasicBlock* SUCC = *SI; + if (SUCC != MBB) + successors.push_back(SUCC); + } + + unsigned i = 0, e = successors.size(); + if (i != e) { + CSRegSet prevAnticOut = AnticOut[MBB]; + MachineBasicBlock* SUCC = successors[i]; + + AnticOut[MBB] = AnticIn[SUCC]; + for (++i; i != e; ++i) { + SUCC = successors[i]; + AnticOut[MBB] &= AnticIn[SUCC]; + } + if (prevAnticOut != AnticOut[MBB]) + changed = true; + } + + // AnticIn[MBB] = UNION(CSRUsed[MBB], AnticOut[MBB]); + CSRegSet prevAnticIn = AnticIn[MBB]; + AnticIn[MBB] = CSRUsed[MBB] | AnticOut[MBB]; + if (prevAnticIn |= AnticIn[MBB]) + changed = true; + return changed; +} + +/// calcAvailInOut - calculate the available in/out reg sets +/// for the given MBB by looking backward in the MCFG at MBB's +/// predecessors. +/// +bool PEI::calcAvailInOut(MachineBasicBlock* MBB) { + bool changed = false; + + // AvailIn[MBB] = INTERSECT(AvailOut[P] for P in PREDECESSORS(MBB)) + SmallVector predecessors; + for (MachineBasicBlock::pred_iterator PI = MBB->pred_begin(), + PE = MBB->pred_end(); PI != PE; ++PI) { + MachineBasicBlock* PRED = *PI; + if (PRED != MBB) + predecessors.push_back(PRED); + } + + unsigned i = 0, e = predecessors.size(); + if (i != e) { + CSRegSet prevAvailIn = AvailIn[MBB]; + MachineBasicBlock* PRED = predecessors[i]; + + AvailIn[MBB] = AvailOut[PRED]; + for (++i; i != e; ++i) { + PRED = predecessors[i]; + AvailIn[MBB] &= AvailOut[PRED]; + } + if (prevAvailIn != AvailIn[MBB]) + changed = true; + } + + // AvailOut[MBB] = UNION(CSRUsed[MBB], AvailIn[MBB]); + CSRegSet prevAvailOut = AvailOut[MBB]; + AvailOut[MBB] = CSRUsed[MBB] | AvailIn[MBB]; + if (prevAvailOut |= AvailOut[MBB]) + changed = true; + return changed; +} + +/// calculateAnticAvail - build the sets anticipated and available +/// registers in the MCFG of the current function iteratively, +/// doing a combined forward and backward analysis. +/// +void PEI::calculateAnticAvail(MachineFunction &Fn) { + // Initialize data flow sets. + clearAnticAvailSets(); + + // Calulate Antic{In,Out} and Avail{In,Out} iteratively on the MCFG. + bool changed = true; + unsigned iterations = 0; + while (changed) { + changed = false; + ++iterations; + for (MachineFunction::iterator MBBI = Fn.begin(), MBBE = Fn.end(); + MBBI != MBBE; ++MBBI) { + MachineBasicBlock* MBB = MBBI; + + // Calculate anticipated in, out regs at MBB from + // anticipated at successors of MBB. + changed |= calcAnticInOut(MBB); + + // Calculate available in, out regs at MBB from + // available at predecessors of MBB. + changed |= calcAvailInOut(MBB); + } + } + + DEBUG({ + if (ShrinkWrapDebugging >= Details) { + errs() + << "-----------------------------------------------------------\n" + << " Antic/Avail Sets:\n" + << "-----------------------------------------------------------\n" + << "iterations = " << iterations << "\n" + << "-----------------------------------------------------------\n" + << "MBB | USED | ANTIC_IN | ANTIC_OUT | AVAIL_IN | AVAIL_OUT\n" + << "-----------------------------------------------------------\n"; + + for (MachineFunction::iterator MBBI = Fn.begin(), MBBE = Fn.end(); + MBBI != MBBE; ++MBBI) { + MachineBasicBlock* MBB = MBBI; + dumpSets(MBB); + } + + errs() + << "-----------------------------------------------------------\n"; + } + }); +} + +/// propagateUsesAroundLoop - copy used register info from MBB to all blocks +/// of the loop given by LP and its parent loops. This prevents spills/restores +/// from being placed in the bodies of loops. +/// +void PEI::propagateUsesAroundLoop(MachineBasicBlock* MBB, MachineLoop* LP) { + if (! MBB || !LP) + return; + + std::vector loopBlocks = LP->getBlocks(); + for (unsigned i = 0, e = loopBlocks.size(); i != e; ++i) { + MachineBasicBlock* LBB = loopBlocks[i]; + if (LBB == MBB) + continue; + if (CSRUsed[LBB].contains(CSRUsed[MBB])) + continue; + CSRUsed[LBB] |= CSRUsed[MBB]; + } +} + +/// calculateSets - collect the CSRs used in this function, compute +/// the DF sets that describe the initial minimal regions in the +/// Machine CFG around which CSR spills and restores must be placed. +/// +/// Additionally, this function decides if shrink wrapping should +/// be disabled for the current function, checking the following: +/// 1. the current function has more than 500 MBBs: heuristic limit +/// on function size to reduce compile time impact of the current +/// iterative algorithm. +/// 2. all CSRs are used in the entry block. +/// 3. all CSRs are used in all immediate successors of the entry block. +/// 4. all CSRs are used in a subset of blocks, each of which dominates +/// all return blocks. These blocks, taken as a subgraph of the MCFG, +/// are equivalent to the entry block since all execution paths pass +/// through them. +/// +bool PEI::calculateSets(MachineFunction &Fn) { + // Sets used to compute spill, restore placement sets. + const std::vector CSI = + Fn.getFrameInfo()->getCalleeSavedInfo(); + + // If no CSRs used, we are done. + if (CSI.empty()) { + DEBUG(if (ShrinkWrapThisFunction) + errs() << "DISABLED: " << Fn.getFunction()->getName() + << ": uses no callee-saved registers\n"); + return false; + } + + // Save refs to entry and return blocks. + EntryBlock = Fn.begin(); + for (MachineFunction::iterator MBB = Fn.begin(), E = Fn.end(); + MBB != E; ++MBB) + if (isReturnBlock(MBB)) + ReturnBlocks.push_back(MBB); + + // Determine if this function has fast exit paths. + DEBUG(if (ShrinkWrapThisFunction) + findFastExitPath()); + + // Limit shrink wrapping via the current iterative bit vector + // implementation to functions with <= 500 MBBs. + if (Fn.size() > 500) { + DEBUG(if (ShrinkWrapThisFunction) + errs() << "DISABLED: " << Fn.getFunction()->getName() + << ": too large (" << Fn.size() << " MBBs)\n"); + ShrinkWrapThisFunction = false; + } + + // Return now if not shrink wrapping. + if (! ShrinkWrapThisFunction) + return false; + + // Collect set of used CSRs. + for (unsigned inx = 0, e = CSI.size(); inx != e; ++inx) { + UsedCSRegs.set(inx); + } + + // Walk instructions in all MBBs, create CSRUsed[] sets, choose + // whether or not to shrink wrap this function. + MachineLoopInfo &LI = getAnalysis(); + MachineDominatorTree &DT = getAnalysis(); + const TargetRegisterInfo *TRI = Fn.getTarget().getRegisterInfo(); + + bool allCSRUsesInEntryBlock = true; + for (MachineFunction::iterator MBBI = Fn.begin(), MBBE = Fn.end(); + MBBI != MBBE; ++MBBI) { + MachineBasicBlock* MBB = MBBI; + for (MachineBasicBlock::iterator I = MBB->begin(); I != MBB->end(); ++I) { + for (unsigned inx = 0, e = CSI.size(); inx != e; ++inx) { + unsigned Reg = CSI[inx].getReg(); + // If instruction I reads or modifies Reg, add it to UsedCSRegs, + // CSRUsed map for the current block. + for (unsigned opInx = 0, opEnd = I->getNumOperands(); + opInx != opEnd; ++opInx) { + const MachineOperand &MO = I->getOperand(opInx); + if (! (MO.isReg() && (MO.isUse() || MO.isDef()))) + continue; + unsigned MOReg = MO.getReg(); + if (!MOReg) + continue; + if (MOReg == Reg || + (TargetRegisterInfo::isPhysicalRegister(MOReg) && + TargetRegisterInfo::isPhysicalRegister(Reg) && + TRI->isSubRegister(Reg, MOReg))) { + // CSR Reg is defined/used in block MBB. + CSRUsed[MBB].set(inx); + // Check for uses in EntryBlock. + if (MBB != EntryBlock) + allCSRUsesInEntryBlock = false; + } + } + } + } + + if (CSRUsed[MBB].empty()) + continue; + + // Propagate CSRUsed[MBB] in loops + if (MachineLoop* LP = LI.getLoopFor(MBB)) { + // Add top level loop to work list. + MachineBasicBlock* HDR = getTopLevelLoopPreheader(LP); + MachineLoop* PLP = getTopLevelLoopParent(LP); + + if (! HDR) { + HDR = PLP->getHeader(); + assert(HDR->pred_size() > 0 && "Loop header has no predecessors?"); + MachineBasicBlock::pred_iterator PI = HDR->pred_begin(); + HDR = *PI; + } + TLLoops[HDR] = PLP; + + // Push uses from inside loop to its parent loops, + // or to all other MBBs in its loop. + if (LP->getLoopDepth() > 1) { + for (MachineLoop* PLP = LP->getParentLoop(); PLP; + PLP = PLP->getParentLoop()) { + propagateUsesAroundLoop(MBB, PLP); + } + } else { + propagateUsesAroundLoop(MBB, LP); + } + } + } + + if (allCSRUsesInEntryBlock) { + DEBUG(errs() << "DISABLED: " << Fn.getFunction()->getName() + << ": all CSRs used in EntryBlock\n"); + ShrinkWrapThisFunction = false; + } else { + bool allCSRsUsedInEntryFanout = true; + for (MachineBasicBlock::succ_iterator SI = EntryBlock->succ_begin(), + SE = EntryBlock->succ_end(); SI != SE; ++SI) { + MachineBasicBlock* SUCC = *SI; + if (CSRUsed[SUCC] != UsedCSRegs) + allCSRsUsedInEntryFanout = false; + } + if (allCSRsUsedInEntryFanout) { + DEBUG(errs() << "DISABLED: " << Fn.getFunction()->getName() + << ": all CSRs used in imm successors of EntryBlock\n"); + ShrinkWrapThisFunction = false; + } + } + + if (ShrinkWrapThisFunction) { + // Check if MBB uses CSRs and dominates all exit nodes. + // Such nodes are equiv. to the entry node w.r.t. + // CSR uses: every path through the function must + // pass through this node. If each CSR is used at least + // once by these nodes, shrink wrapping is disabled. + CSRegSet CSRUsedInChokePoints; + for (MachineFunction::iterator MBBI = Fn.begin(), MBBE = Fn.end(); + MBBI != MBBE; ++MBBI) { + MachineBasicBlock* MBB = MBBI; + if (MBB == EntryBlock || CSRUsed[MBB].empty() || MBB->succ_size() < 1) + continue; + bool dominatesExitNodes = true; + for (unsigned ri = 0, re = ReturnBlocks.size(); ri != re; ++ri) + if (! DT.dominates(MBB, ReturnBlocks[ri])) { + dominatesExitNodes = false; + break; + } + if (dominatesExitNodes) { + CSRUsedInChokePoints |= CSRUsed[MBB]; + if (CSRUsedInChokePoints == UsedCSRegs) { + DEBUG(errs() << "DISABLED: " << Fn.getFunction()->getName() + << ": all CSRs used in choke point(s) at " + << getBasicBlockName(MBB) << "\n"); + ShrinkWrapThisFunction = false; + break; + } + } + } + } + + // Return now if we have decided not to apply shrink wrapping + // to the current function. + if (! ShrinkWrapThisFunction) + return false; + + DEBUG({ + errs() << "ENABLED: " << Fn.getFunction()->getName(); + if (HasFastExitPath) + errs() << " (fast exit path)"; + errs() << "\n"; + if (ShrinkWrapDebugging >= BasicInfo) { + errs() << "------------------------------" + << "-----------------------------\n"; + errs() << "UsedCSRegs = " << stringifyCSRegSet(UsedCSRegs) << "\n"; + if (ShrinkWrapDebugging >= Details) { + errs() << "------------------------------" + << "-----------------------------\n"; + dumpAllUsed(); + } + } + }); + + // Build initial DF sets to determine minimal regions in the + // Machine CFG around which CSRs must be spilled and restored. + calculateAnticAvail(Fn); + + return true; +} + +/// addUsesForMEMERegion - add uses of CSRs spilled or restored in +/// multi-entry, multi-exit (MEME) regions so spill and restore +/// placement will not break code that enters or leaves a +/// shrink-wrapped region by inducing spills with no matching +/// restores or restores with no matching spills. A MEME region +/// is a subgraph of the MCFG with multiple entry edges, multiple +/// exit edges, or both. This code propagates use information +/// through the MCFG until all paths requiring spills and restores +/// _outside_ the computed minimal placement regions have been covered. +/// +bool PEI::addUsesForMEMERegion(MachineBasicBlock* MBB, + SmallVector& blks) { + if (MBB->succ_size() < 2 && MBB->pred_size() < 2) { + bool processThisBlock = false; + for (MachineBasicBlock::succ_iterator SI = MBB->succ_begin(), + SE = MBB->succ_end(); SI != SE; ++SI) { + MachineBasicBlock* SUCC = *SI; + if (SUCC->pred_size() > 1) { + processThisBlock = true; + break; + } + } + if (!CSRRestore[MBB].empty() && MBB->succ_size() > 0) { + for (MachineBasicBlock::pred_iterator PI = MBB->pred_begin(), + PE = MBB->pred_end(); PI != PE; ++PI) { + MachineBasicBlock* PRED = *PI; + if (PRED->succ_size() > 1) { + processThisBlock = true; + break; + } + } + } + if (! processThisBlock) + return false; + } + + CSRegSet prop; + if (!CSRSave[MBB].empty()) + prop = CSRSave[MBB]; + else if (!CSRRestore[MBB].empty()) + prop = CSRRestore[MBB]; + else + prop = CSRUsed[MBB]; + if (prop.empty()) + return false; + + // Propagate selected bits to successors, predecessors of MBB. + bool addedUses = false; + for (MachineBasicBlock::succ_iterator SI = MBB->succ_begin(), + SE = MBB->succ_end(); SI != SE; ++SI) { + MachineBasicBlock* SUCC = *SI; + // Self-loop + if (SUCC == MBB) + continue; + if (! CSRUsed[SUCC].contains(prop)) { + CSRUsed[SUCC] |= prop; + addedUses = true; + blks.push_back(SUCC); + DEBUG(if (ShrinkWrapDebugging >= Iterations) + errs() << getBasicBlockName(MBB) + << "(" << stringifyCSRegSet(prop) << ")->" + << "successor " << getBasicBlockName(SUCC) << "\n"); + } + } + for (MachineBasicBlock::pred_iterator PI = MBB->pred_begin(), + PE = MBB->pred_end(); PI != PE; ++PI) { + MachineBasicBlock* PRED = *PI; + // Self-loop + if (PRED == MBB) + continue; + if (! CSRUsed[PRED].contains(prop)) { + CSRUsed[PRED] |= prop; + addedUses = true; + blks.push_back(PRED); + DEBUG(if (ShrinkWrapDebugging >= Iterations) + errs() << getBasicBlockName(MBB) + << "(" << stringifyCSRegSet(prop) << ")->" + << "predecessor " << getBasicBlockName(PRED) << "\n"); + } + } + return addedUses; +} + +/// addUsesForTopLevelLoops - add uses for CSRs used inside top +/// level loops to the exit blocks of those loops. +/// +bool PEI::addUsesForTopLevelLoops(SmallVector& blks) { + bool addedUses = false; + + // Place restores for top level loops where needed. + for (DenseMap::iterator + I = TLLoops.begin(), E = TLLoops.end(); I != E; ++I) { + MachineBasicBlock* MBB = I->first; + MachineLoop* LP = I->second; + MachineBasicBlock* HDR = LP->getHeader(); + SmallVector exitBlocks; + CSRegSet loopSpills; + + loopSpills = CSRSave[MBB]; + if (CSRSave[MBB].empty()) { + loopSpills = CSRUsed[HDR]; + assert(!loopSpills.empty() && "No CSRs used in loop?"); + } else if (CSRRestore[MBB].contains(CSRSave[MBB])) + continue; + + LP->getExitBlocks(exitBlocks); + assert(exitBlocks.size() > 0 && "Loop has no top level exit blocks?"); + for (unsigned i = 0, e = exitBlocks.size(); i != e; ++i) { + MachineBasicBlock* EXB = exitBlocks[i]; + if (! CSRUsed[EXB].contains(loopSpills)) { + CSRUsed[EXB] |= loopSpills; + addedUses = true; + DEBUG(if (ShrinkWrapDebugging >= Iterations) + errs() << "LOOP " << getBasicBlockName(MBB) + << "(" << stringifyCSRegSet(loopSpills) << ")->" + << getBasicBlockName(EXB) << "\n"); + if (EXB->succ_size() > 1 || EXB->pred_size() > 1) + blks.push_back(EXB); + } + } + } + return addedUses; +} + +/// calcSpillPlacements - determine which CSRs should be spilled +/// in MBB using AnticIn sets of MBB's predecessors, keeping track +/// of changes to spilled reg sets. Add MBB to the set of blocks +/// that need to be processed for propagating use info to cover +/// multi-entry/exit regions. +/// +bool PEI::calcSpillPlacements(MachineBasicBlock* MBB, + SmallVector &blks, + CSRegBlockMap &prevSpills) { + bool placedSpills = false; + // Intersect (CSRegs - AnticIn[P]) for P in Predecessors(MBB) + CSRegSet anticInPreds; + SmallVector predecessors; + for (MachineBasicBlock::pred_iterator PI = MBB->pred_begin(), + PE = MBB->pred_end(); PI != PE; ++PI) { + MachineBasicBlock* PRED = *PI; + if (PRED != MBB) + predecessors.push_back(PRED); + } + unsigned i = 0, e = predecessors.size(); + if (i != e) { + MachineBasicBlock* PRED = predecessors[i]; + anticInPreds = UsedCSRegs - AnticIn[PRED]; + for (++i; i != e; ++i) { + PRED = predecessors[i]; + anticInPreds &= (UsedCSRegs - AnticIn[PRED]); + } + } else { + // Handle uses in entry blocks (which have no predecessors). + // This is necessary because the DFA formulation assumes the + // entry and (multiple) exit nodes cannot have CSR uses, which + // is not the case in the real world. + anticInPreds = UsedCSRegs; + } + // Compute spills required at MBB: + CSRSave[MBB] |= (AnticIn[MBB] - AvailIn[MBB]) & anticInPreds; + + if (! CSRSave[MBB].empty()) { + if (MBB == EntryBlock) { + for (unsigned ri = 0, re = ReturnBlocks.size(); ri != re; ++ri) + CSRRestore[ReturnBlocks[ri]] |= CSRSave[MBB]; + } else { + // Reset all regs spilled in MBB that are also spilled in EntryBlock. + if (CSRSave[EntryBlock].intersects(CSRSave[MBB])) { + CSRSave[MBB] = CSRSave[MBB] - CSRSave[EntryBlock]; + } + } + } + placedSpills = (CSRSave[MBB] != prevSpills[MBB]); + prevSpills[MBB] = CSRSave[MBB]; + // Remember this block for adding restores to successor + // blocks for multi-entry region. + if (placedSpills) + blks.push_back(MBB); + + DEBUG(if (! CSRSave[MBB].empty() && ShrinkWrapDebugging >= Iterations) + errs() << "SAVE[" << getBasicBlockName(MBB) << "] = " + << stringifyCSRegSet(CSRSave[MBB]) << "\n"); + + return placedSpills; +} + +/// calcRestorePlacements - determine which CSRs should be restored +/// in MBB using AvailOut sets of MBB's succcessors, keeping track +/// of changes to restored reg sets. Add MBB to the set of blocks +/// that need to be processed for propagating use info to cover +/// multi-entry/exit regions. +/// +bool PEI::calcRestorePlacements(MachineBasicBlock* MBB, + SmallVector &blks, + CSRegBlockMap &prevRestores) { + bool placedRestores = false; + // Intersect (CSRegs - AvailOut[S]) for S in Successors(MBB) + CSRegSet availOutSucc; + SmallVector successors; + for (MachineBasicBlock::succ_iterator SI = MBB->succ_begin(), + SE = MBB->succ_end(); SI != SE; ++SI) { + MachineBasicBlock* SUCC = *SI; + if (SUCC != MBB) + successors.push_back(SUCC); + } + unsigned i = 0, e = successors.size(); + if (i != e) { + MachineBasicBlock* SUCC = successors[i]; + availOutSucc = UsedCSRegs - AvailOut[SUCC]; + for (++i; i != e; ++i) { + SUCC = successors[i]; + availOutSucc &= (UsedCSRegs - AvailOut[SUCC]); + } + } else { + if (! CSRUsed[MBB].empty() || ! AvailOut[MBB].empty()) { + // Handle uses in return blocks (which have no successors). + // This is necessary because the DFA formulation assumes the + // entry and (multiple) exit nodes cannot have CSR uses, which + // is not the case in the real world. + availOutSucc = UsedCSRegs; + } + } + // Compute restores required at MBB: + CSRRestore[MBB] |= (AvailOut[MBB] - AnticOut[MBB]) & availOutSucc; + + // Postprocess restore placements at MBB. + // Remove the CSRs that are restored in the return blocks. + // Lest this be confusing, note that: + // CSRSave[EntryBlock] == CSRRestore[B] for all B in ReturnBlocks. + if (MBB->succ_size() && ! CSRRestore[MBB].empty()) { + if (! CSRSave[EntryBlock].empty()) + CSRRestore[MBB] = CSRRestore[MBB] - CSRSave[EntryBlock]; + } + placedRestores = (CSRRestore[MBB] != prevRestores[MBB]); + prevRestores[MBB] = CSRRestore[MBB]; + // Remember this block for adding saves to predecessor + // blocks for multi-entry region. + if (placedRestores) + blks.push_back(MBB); + + DEBUG(if (! CSRRestore[MBB].empty() && ShrinkWrapDebugging >= Iterations) + errs() << "RESTORE[" << getBasicBlockName(MBB) << "] = " + << stringifyCSRegSet(CSRRestore[MBB]) << "\n"); + + return placedRestores; +} + +/// placeSpillsAndRestores - place spills and restores of CSRs +/// used in MBBs in minimal regions that contain the uses. +/// +void PEI::placeSpillsAndRestores(MachineFunction &Fn) { + CSRegBlockMap prevCSRSave; + CSRegBlockMap prevCSRRestore; + SmallVector cvBlocks, ncvBlocks; + bool changed = true; + unsigned iterations = 0; + + // Iterate computation of spill and restore placements in the MCFG until: + // 1. CSR use info has been fully propagated around the MCFG, and + // 2. computation of CSRSave[], CSRRestore[] reach fixed points. + while (changed) { + changed = false; + ++iterations; + + DEBUG(if (ShrinkWrapDebugging >= Iterations) + errs() << "iter " << iterations + << " --------------------------------------------------\n"); + + // Calculate CSR{Save,Restore} sets using Antic, Avail on the MCFG, + // which determines the placements of spills and restores. + // Keep track of changes to spills, restores in each iteration to + // minimize the total iterations. + bool SRChanged = false; + for (MachineFunction::iterator MBBI = Fn.begin(), MBBE = Fn.end(); + MBBI != MBBE; ++MBBI) { + MachineBasicBlock* MBB = MBBI; + + // Place spills for CSRs in MBB. + SRChanged |= calcSpillPlacements(MBB, cvBlocks, prevCSRSave); + + // Place restores for CSRs in MBB. + SRChanged |= calcRestorePlacements(MBB, cvBlocks, prevCSRRestore); + } + + // Add uses of CSRs used inside loops where needed. + changed |= addUsesForTopLevelLoops(cvBlocks); + + // Add uses for CSRs spilled or restored at branch, join points. + if (changed || SRChanged) { + while (! cvBlocks.empty()) { + MachineBasicBlock* MBB = cvBlocks.pop_back_val(); + changed |= addUsesForMEMERegion(MBB, ncvBlocks); + } + if (! ncvBlocks.empty()) { + cvBlocks = ncvBlocks; + ncvBlocks.clear(); + } + } + + if (changed) { + calculateAnticAvail(Fn); + CSRSave.clear(); + CSRRestore.clear(); + } + } + + // Check for effectiveness: + // SR0 = {r | r in CSRSave[EntryBlock], CSRRestore[RB], RB in ReturnBlocks} + // numSRReduced = |(UsedCSRegs - SR0)|, approx. SR0 by CSRSave[EntryBlock] + // Gives a measure of how many CSR spills have been moved from EntryBlock + // to minimal regions enclosing their uses. + CSRegSet notSpilledInEntryBlock = (UsedCSRegs - CSRSave[EntryBlock]); + unsigned numSRReducedThisFunc = notSpilledInEntryBlock.count(); + numSRReduced += numSRReducedThisFunc; + DEBUG(if (ShrinkWrapDebugging >= BasicInfo) { + errs() << "-----------------------------------------------------------\n"; + errs() << "total iterations = " << iterations << " ( " + << Fn.getFunction()->getName() + << " " << numSRReducedThisFunc + << " " << Fn.size() + << " )\n"; + errs() << "-----------------------------------------------------------\n"; + dumpSRSets(); + errs() << "-----------------------------------------------------------\n"; + if (numSRReducedThisFunc) + verifySpillRestorePlacement(); + }); +} + +// Debugging methods. +#ifndef NDEBUG +/// findFastExitPath - debugging method used to detect functions +/// with at least one path from the entry block to a return block +/// directly or which has a very small number of edges. +/// +void PEI::findFastExitPath() { + if (! EntryBlock) + return; + // Fina a path from EntryBlock to any return block that does not branch: + // Entry + // | ... + // v | + // B1<-----+ + // | + // v + // Return + for (MachineBasicBlock::succ_iterator SI = EntryBlock->succ_begin(), + SE = EntryBlock->succ_end(); SI != SE; ++SI) { + MachineBasicBlock* SUCC = *SI; + + // Assume positive, disprove existence of fast path. + HasFastExitPath = true; + + // Check the immediate successors. + if (isReturnBlock(SUCC)) { + if (ShrinkWrapDebugging >= BasicInfo) + errs() << "Fast exit path: " << getBasicBlockName(EntryBlock) + << "->" << getBasicBlockName(SUCC) << "\n"; + break; + } + // Traverse df from SUCC, look for a branch block. + std::string exitPath = getBasicBlockName(SUCC); + for (df_iterator BI = df_begin(SUCC), + BE = df_end(SUCC); BI != BE; ++BI) { + MachineBasicBlock* SBB = *BI; + // Reject paths with branch nodes. + if (SBB->succ_size() > 1) { + HasFastExitPath = false; + break; + } + exitPath += "->" + getBasicBlockName(SBB); + } + if (HasFastExitPath) { + if (ShrinkWrapDebugging >= BasicInfo) + errs() << "Fast exit path: " << getBasicBlockName(EntryBlock) + << "->" << exitPath << "\n"; + break; + } + } +} + +/// verifySpillRestorePlacement - check the current spill/restore +/// sets for safety. Attempt to find spills without restores or +/// restores without spills. +/// Spills: walk df from each MBB in spill set ensuring that +/// all CSRs spilled at MMBB are restored on all paths +/// from MBB to all exit blocks. +/// Restores: walk idf from each MBB in restore set ensuring that +/// all CSRs restored at MBB are spilled on all paths +/// reaching MBB. +/// +void PEI::verifySpillRestorePlacement() { + unsigned numReturnBlocks = 0; + for (MachineFunction::iterator MBBI = MF->begin(), MBBE = MF->end(); + MBBI != MBBE; ++MBBI) { + MachineBasicBlock* MBB = MBBI; + if (isReturnBlock(MBB) || MBB->succ_size() == 0) + ++numReturnBlocks; + } + for (CSRegBlockMap::iterator BI = CSRSave.begin(), + BE = CSRSave.end(); BI != BE; ++BI) { + MachineBasicBlock* MBB = BI->first; + CSRegSet spilled = BI->second; + CSRegSet restored; + + if (spilled.empty()) + continue; + + DEBUG(errs() << "SAVE[" << getBasicBlockName(MBB) << "] = " + << stringifyCSRegSet(spilled) + << " RESTORE[" << getBasicBlockName(MBB) << "] = " + << stringifyCSRegSet(CSRRestore[MBB]) << "\n"); + + if (CSRRestore[MBB].intersects(spilled)) { + restored |= (CSRRestore[MBB] & spilled); + } + + // Walk depth first from MBB to find restores of all CSRs spilled at MBB: + // we must find restores for all spills w/no intervening spills on all + // paths from MBB to all return blocks. + for (df_iterator BI = df_begin(MBB), + BE = df_end(MBB); BI != BE; ++BI) { + MachineBasicBlock* SBB = *BI; + if (SBB == MBB) + continue; + // Stop when we encounter spills of any CSRs spilled at MBB that + // have not yet been seen to be restored. + if (CSRSave[SBB].intersects(spilled) && + !restored.contains(CSRSave[SBB] & spilled)) + break; + // Collect the CSRs spilled at MBB that are restored + // at this DF successor of MBB. + if (CSRRestore[SBB].intersects(spilled)) + restored |= (CSRRestore[SBB] & spilled); + // If we are at a retun block, check that the restores + // we have seen so far exhaust the spills at MBB, then + // reset the restores. + if (isReturnBlock(SBB) || SBB->succ_size() == 0) { + if (restored != spilled) { + CSRegSet notRestored = (spilled - restored); + DEBUG(errs() << MF->getFunction()->getName() << ": " + << stringifyCSRegSet(notRestored) + << " spilled at " << getBasicBlockName(MBB) + << " are never restored on path to return " + << getBasicBlockName(SBB) << "\n"); + } + restored.clear(); + } + } + } + + // Check restore placements. + for (CSRegBlockMap::iterator BI = CSRRestore.begin(), + BE = CSRRestore.end(); BI != BE; ++BI) { + MachineBasicBlock* MBB = BI->first; + CSRegSet restored = BI->second; + CSRegSet spilled; + + if (restored.empty()) + continue; + + DEBUG(errs() << "SAVE[" << getBasicBlockName(MBB) << "] = " + << stringifyCSRegSet(CSRSave[MBB]) + << " RESTORE[" << getBasicBlockName(MBB) << "] = " + << stringifyCSRegSet(restored) << "\n"); + + if (CSRSave[MBB].intersects(restored)) { + spilled |= (CSRSave[MBB] & restored); + } + // Walk inverse depth first from MBB to find spills of all + // CSRs restored at MBB: + for (idf_iterator BI = idf_begin(MBB), + BE = idf_end(MBB); BI != BE; ++BI) { + MachineBasicBlock* PBB = *BI; + if (PBB == MBB) + continue; + // Stop when we encounter restores of any CSRs restored at MBB that + // have not yet been seen to be spilled. + if (CSRRestore[PBB].intersects(restored) && + !spilled.contains(CSRRestore[PBB] & restored)) + break; + // Collect the CSRs restored at MBB that are spilled + // at this DF predecessor of MBB. + if (CSRSave[PBB].intersects(restored)) + spilled |= (CSRSave[PBB] & restored); + } + if (spilled != restored) { + CSRegSet notSpilled = (restored - spilled); + DEBUG(errs() << MF->getFunction()->getName() << ": " + << stringifyCSRegSet(notSpilled) + << " restored at " << getBasicBlockName(MBB) + << " are never spilled\n"); + } + } +} + +// Debugging print methods. +std::string PEI::getBasicBlockName(const MachineBasicBlock* MBB) { + if (!MBB) + return ""; + + if (MBB->getBasicBlock()) + return MBB->getBasicBlock()->getNameStr(); + + std::ostringstream name; + name << "_MBB_" << MBB->getNumber(); + return name.str(); +} + +std::string PEI::stringifyCSRegSet(const CSRegSet& s) { + const TargetRegisterInfo* TRI = MF->getTarget().getRegisterInfo(); + const std::vector CSI = + MF->getFrameInfo()->getCalleeSavedInfo(); + + std::ostringstream srep; + if (CSI.size() == 0) { + srep << "[]"; + return srep.str(); + } + srep << "["; + CSRegSet::iterator I = s.begin(), E = s.end(); + if (I != E) { + unsigned reg = CSI[*I].getReg(); + srep << TRI->getName(reg); + for (++I; I != E; ++I) { + reg = CSI[*I].getReg(); + srep << ","; + srep << TRI->getName(reg); + } + } + srep << "]"; + return srep.str(); +} + +void PEI::dumpSet(const CSRegSet& s) { + DEBUG(errs() << stringifyCSRegSet(s) << "\n"); +} + +void PEI::dumpUsed(MachineBasicBlock* MBB) { + DEBUG({ + if (MBB) + errs() << "CSRUsed[" << getBasicBlockName(MBB) << "] = " + << stringifyCSRegSet(CSRUsed[MBB]) << "\n"; + }); +} + +void PEI::dumpAllUsed() { + for (MachineFunction::iterator MBBI = MF->begin(), MBBE = MF->end(); + MBBI != MBBE; ++MBBI) { + MachineBasicBlock* MBB = MBBI; + dumpUsed(MBB); + } +} + +void PEI::dumpSets(MachineBasicBlock* MBB) { + DEBUG({ + if (MBB) + errs() << getBasicBlockName(MBB) << " | " + << stringifyCSRegSet(CSRUsed[MBB]) << " | " + << stringifyCSRegSet(AnticIn[MBB]) << " | " + << stringifyCSRegSet(AnticOut[MBB]) << " | " + << stringifyCSRegSet(AvailIn[MBB]) << " | " + << stringifyCSRegSet(AvailOut[MBB]) << "\n"; + }); +} + +void PEI::dumpSets1(MachineBasicBlock* MBB) { + DEBUG({ + if (MBB) + errs() << getBasicBlockName(MBB) << " | " + << stringifyCSRegSet(CSRUsed[MBB]) << " | " + << stringifyCSRegSet(AnticIn[MBB]) << " | " + << stringifyCSRegSet(AnticOut[MBB]) << " | " + << stringifyCSRegSet(AvailIn[MBB]) << " | " + << stringifyCSRegSet(AvailOut[MBB]) << " | " + << stringifyCSRegSet(CSRSave[MBB]) << " | " + << stringifyCSRegSet(CSRRestore[MBB]) << "\n"; + }); +} + +void PEI::dumpAllSets() { + for (MachineFunction::iterator MBBI = MF->begin(), MBBE = MF->end(); + MBBI != MBBE; ++MBBI) { + MachineBasicBlock* MBB = MBBI; + dumpSets1(MBB); + } +} + +void PEI::dumpSRSets() { + DEBUG({ + for (MachineFunction::iterator MBB = MF->begin(), E = MF->end(); + MBB != E; ++MBB) { + if (!CSRSave[MBB].empty()) { + errs() << "SAVE[" << getBasicBlockName(MBB) << "] = " + << stringifyCSRegSet(CSRSave[MBB]); + if (CSRRestore[MBB].empty()) + errs() << '\n'; + } + + if (!CSRRestore[MBB].empty() && !CSRSave[MBB].empty()) + errs() << " " + << "RESTORE[" << getBasicBlockName(MBB) << "] = " + << stringifyCSRegSet(CSRRestore[MBB]) << "\n"; + } + }); +} +#endif diff --git a/libclamav/c++/llvm/lib/CodeGen/SimpleHazardRecognizer.h b/libclamav/c++/llvm/lib/CodeGen/SimpleHazardRecognizer.h new file mode 100644 index 000000000..f69feaf9e --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/SimpleHazardRecognizer.h @@ -0,0 +1,89 @@ +//=- llvm/CodeGen/SimpleHazardRecognizer.h - Scheduling Support -*- 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 the SimpleHazardRecognizer class, which +// implements hazard-avoidance heuristics for scheduling, based on the +// scheduling itineraries specified for the target. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_SIMPLEHAZARDRECOGNIZER_H +#define LLVM_CODEGEN_SIMPLEHAZARDRECOGNIZER_H + +#include "llvm/CodeGen/ScheduleHazardRecognizer.h" +#include "llvm/CodeGen/ScheduleDAG.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetInstrInfo.h" + +namespace llvm { + /// SimpleHazardRecognizer - A *very* simple hazard recognizer. It uses + /// a coarse classification and attempts to avoid that instructions of + /// a given class aren't grouped too densely together. + class SimpleHazardRecognizer : public ScheduleHazardRecognizer { + /// Class - A simple classification for SUnits. + enum Class { + Other, Load, Store + }; + + /// Window - The Class values of the most recently issued + /// instructions. + Class Window[8]; + + /// getClass - Classify the given SUnit. + Class getClass(const SUnit *SU) { + const MachineInstr *MI = SU->getInstr(); + const TargetInstrDesc &TID = MI->getDesc(); + if (TID.mayLoad()) + return Load; + if (TID.mayStore()) + return Store; + return Other; + } + + /// Step - Rotate the existing entries in Window and insert the + /// given class value in position as the most recent. + void Step(Class C) { + std::copy(Window+1, array_endof(Window), Window); + Window[array_lengthof(Window)-1] = C; + } + + public: + SimpleHazardRecognizer() : Window() { + Reset(); + } + + virtual HazardType getHazardType(SUnit *SU) { + Class C = getClass(SU); + if (C == Other) + return NoHazard; + unsigned Score = 0; + for (unsigned i = 0; i != array_lengthof(Window); ++i) + if (Window[i] == C) + Score += i + 1; + if (Score > array_lengthof(Window) * 2) + return Hazard; + return NoHazard; + } + + virtual void Reset() { + for (unsigned i = 0; i != array_lengthof(Window); ++i) + Window[i] = Other; + } + + virtual void EmitInstruction(SUnit *SU) { + Step(getClass(SU)); + } + + virtual void AdvanceCycle() { + Step(Other); + } + }; +} + +#endif diff --git a/libclamav/c++/llvm/lib/CodeGen/SimpleRegisterCoalescing.cpp b/libclamav/c++/llvm/lib/CodeGen/SimpleRegisterCoalescing.cpp new file mode 100644 index 000000000..7847f8ec2 --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/SimpleRegisterCoalescing.cpp @@ -0,0 +1,2840 @@ +//===-- SimpleRegisterCoalescing.cpp - Register Coalescing ----------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements a simple register coalescing pass that attempts to +// aggressively coalesce every register copy that it can. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "regcoalescing" +#include "SimpleRegisterCoalescing.h" +#include "VirtRegMap.h" +#include "llvm/CodeGen/LiveIntervalAnalysis.h" +#include "llvm/Value.h" +#include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/CodeGen/MachineLoopInfo.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/CodeGen/RegisterCoalescer.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetOptions.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/ADT/SmallSet.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/ADT/STLExtras.h" +#include +#include +using namespace llvm; + +STATISTIC(numJoins , "Number of interval joins performed"); +STATISTIC(numCrossRCs , "Number of cross class joins performed"); +STATISTIC(numCommutes , "Number of instruction commuting performed"); +STATISTIC(numExtends , "Number of copies extended"); +STATISTIC(NumReMats , "Number of instructions re-materialized"); +STATISTIC(numPeep , "Number of identity moves eliminated after coalescing"); +STATISTIC(numAborts , "Number of times interval joining aborted"); +STATISTIC(numDeadValNo, "Number of valno def marked dead"); + +char SimpleRegisterCoalescing::ID = 0; +static cl::opt +EnableJoining("join-liveintervals", + cl::desc("Coalesce copies (default=true)"), + cl::init(true)); + +static cl::opt +DisableCrossClassJoin("disable-cross-class-join", + cl::desc("Avoid coalescing cross register class copies"), + cl::init(false), cl::Hidden); + +static cl::opt +PhysJoinTweak("tweak-phys-join-heuristics", + cl::desc("Tweak heuristics for joining phys reg with vr"), + cl::init(false), cl::Hidden); + +static RegisterPass +X("simple-register-coalescing", "Simple Register Coalescing"); + +// Declare that we implement the RegisterCoalescer interface +static RegisterAnalysisGroup V(X); + +const PassInfo *const llvm::SimpleRegisterCoalescingID = &X; + +void SimpleRegisterCoalescing::getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesCFG(); + AU.addRequired(); + AU.addRequired(); + AU.addPreserved(); + AU.addPreserved(); + AU.addRequired(); + AU.addPreserved(); + AU.addPreservedID(MachineDominatorsID); + if (StrongPHIElim) + AU.addPreservedID(StrongPHIEliminationID); + else + AU.addPreservedID(PHIEliminationID); + AU.addPreservedID(TwoAddressInstructionPassID); + MachineFunctionPass::getAnalysisUsage(AU); +} + +/// AdjustCopiesBackFrom - We found a non-trivially-coalescable copy with IntA +/// being the source and IntB being the dest, thus this defines a value number +/// in IntB. If the source value number (in IntA) is defined by a copy from B, +/// see if we can merge these two pieces of B into a single value number, +/// eliminating a copy. For example: +/// +/// A3 = B0 +/// ... +/// B1 = A3 <- this copy +/// +/// In this case, B0 can be extended to where the B1 copy lives, allowing the B1 +/// value number to be replaced with B0 (which simplifies the B liveinterval). +/// +/// This returns true if an interval was modified. +/// +bool SimpleRegisterCoalescing::AdjustCopiesBackFrom(LiveInterval &IntA, + LiveInterval &IntB, + MachineInstr *CopyMI) { + SlotIndex CopyIdx = li_->getInstructionIndex(CopyMI).getDefIndex(); + + // BValNo is a value number in B that is defined by a copy from A. 'B3' in + // the example above. + LiveInterval::iterator BLR = IntB.FindLiveRangeContaining(CopyIdx); + assert(BLR != IntB.end() && "Live range not found!"); + VNInfo *BValNo = BLR->valno; + + // Get the location that B is defined at. Two options: either this value has + // an unknown definition point or it is defined at CopyIdx. If unknown, we + // can't process it. + if (!BValNo->getCopy()) return false; + assert(BValNo->def == CopyIdx && "Copy doesn't define the value?"); + + // AValNo is the value number in A that defines the copy, A3 in the example. + SlotIndex CopyUseIdx = CopyIdx.getUseIndex(); + LiveInterval::iterator ALR = IntA.FindLiveRangeContaining(CopyUseIdx); + assert(ALR != IntA.end() && "Live range not found!"); + VNInfo *AValNo = ALR->valno; + // If it's re-defined by an early clobber somewhere in the live range, then + // it's not safe to eliminate the copy. FIXME: This is a temporary workaround. + // See PR3149: + // 172 %ECX = MOV32rr %reg1039 + // 180 INLINEASM , 10, %EAX, 14, %ECX, 9, %EAX, + // 36, , 1, %reg0, 0, 9, %ECX, 36, , 1, %reg0, 0 + // 188 %EAX = MOV32rr %EAX + // 196 %ECX = MOV32rr %ECX + // 204 %ECX = MOV32rr %ECX + // 212 %EAX = MOV32rr %EAX + // 220 %EAX = MOV32rr %EAX + // 228 %reg1039 = MOV32rr %ECX + // The early clobber operand ties ECX input to the ECX def. + // + // The live interval of ECX is represented as this: + // %reg20,inf = [46,47:1)[174,230:0) 0@174-(230) 1@46-(47) + // The coalescer has no idea there was a def in the middle of [174,230]. + if (AValNo->hasRedefByEC()) + return false; + + // If AValNo is defined as a copy from IntB, we can potentially process this. + // Get the instruction that defines this value number. + unsigned SrcReg = li_->getVNInfoSourceReg(AValNo); + if (!SrcReg) return false; // Not defined by a copy. + + // If the value number is not defined by a copy instruction, ignore it. + + // If the source register comes from an interval other than IntB, we can't + // handle this. + if (SrcReg != IntB.reg) return false; + + // Get the LiveRange in IntB that this value number starts with. + LiveInterval::iterator ValLR = + IntB.FindLiveRangeContaining(AValNo->def.getPrevSlot()); + assert(ValLR != IntB.end() && "Live range not found!"); + + // Make sure that the end of the live range is inside the same block as + // CopyMI. + MachineInstr *ValLREndInst = + li_->getInstructionFromIndex(ValLR->end.getPrevSlot()); + if (!ValLREndInst || + ValLREndInst->getParent() != CopyMI->getParent()) return false; + + // Okay, we now know that ValLR ends in the same block that the CopyMI + // live-range starts. If there are no intervening live ranges between them in + // IntB, we can merge them. + if (ValLR+1 != BLR) return false; + + // If a live interval is a physical register, conservatively check if any + // of its sub-registers is overlapping the live interval of the virtual + // register. If so, do not coalesce. + if (TargetRegisterInfo::isPhysicalRegister(IntB.reg) && + *tri_->getSubRegisters(IntB.reg)) { + for (const unsigned* SR = tri_->getSubRegisters(IntB.reg); *SR; ++SR) + if (li_->hasInterval(*SR) && IntA.overlaps(li_->getInterval(*SR))) { + DEBUG({ + errs() << "Interfere with sub-register "; + li_->getInterval(*SR).print(errs(), tri_); + }); + return false; + } + } + + DEBUG({ + errs() << "\nExtending: "; + IntB.print(errs(), tri_); + }); + + SlotIndex FillerStart = ValLR->end, FillerEnd = BLR->start; + // We are about to delete CopyMI, so need to remove it as the 'instruction + // that defines this value #'. Update the the valnum with the new defining + // instruction #. + BValNo->def = FillerStart; + BValNo->setCopy(0); + + // Okay, we can merge them. We need to insert a new liverange: + // [ValLR.end, BLR.begin) of either value number, then we merge the + // two value numbers. + IntB.addRange(LiveRange(FillerStart, FillerEnd, BValNo)); + + // If the IntB live range is assigned to a physical register, and if that + // physreg has sub-registers, update their live intervals as well. + if (TargetRegisterInfo::isPhysicalRegister(IntB.reg)) { + for (const unsigned *SR = tri_->getSubRegisters(IntB.reg); *SR; ++SR) { + LiveInterval &SRLI = li_->getInterval(*SR); + SRLI.addRange(LiveRange(FillerStart, FillerEnd, + SRLI.getNextValue(FillerStart, 0, true, + li_->getVNInfoAllocator()))); + } + } + + // Okay, merge "B1" into the same value number as "B0". + if (BValNo != ValLR->valno) { + IntB.addKills(ValLR->valno, BValNo->kills); + IntB.MergeValueNumberInto(BValNo, ValLR->valno); + } + DEBUG({ + errs() << " result = "; + IntB.print(errs(), tri_); + errs() << "\n"; + }); + + // If the source instruction was killing the source register before the + // merge, unset the isKill marker given the live range has been extended. + int UIdx = ValLREndInst->findRegisterUseOperandIdx(IntB.reg, true); + if (UIdx != -1) { + ValLREndInst->getOperand(UIdx).setIsKill(false); + ValLR->valno->removeKill(FillerStart); + } + + // If the copy instruction was killing the destination register before the + // merge, find the last use and trim the live range. That will also add the + // isKill marker. + if (CopyMI->killsRegister(IntA.reg)) + TrimLiveIntervalToLastUse(CopyUseIdx, CopyMI->getParent(), IntA, ALR); + + ++numExtends; + return true; +} + +/// HasOtherReachingDefs - Return true if there are definitions of IntB +/// other than BValNo val# that can reach uses of AValno val# of IntA. +bool SimpleRegisterCoalescing::HasOtherReachingDefs(LiveInterval &IntA, + LiveInterval &IntB, + VNInfo *AValNo, + VNInfo *BValNo) { + for (LiveInterval::iterator AI = IntA.begin(), AE = IntA.end(); + AI != AE; ++AI) { + if (AI->valno != AValNo) continue; + LiveInterval::Ranges::iterator BI = + std::upper_bound(IntB.ranges.begin(), IntB.ranges.end(), AI->start); + if (BI != IntB.ranges.begin()) + --BI; + for (; BI != IntB.ranges.end() && AI->end >= BI->start; ++BI) { + if (BI->valno == BValNo) + continue; + if (BI->start <= AI->start && BI->end > AI->start) + return true; + if (BI->start > AI->start && BI->start < AI->end) + return true; + } + } + return false; +} + +static void +TransferImplicitOps(MachineInstr *MI, MachineInstr *NewMI) { + for (unsigned i = MI->getDesc().getNumOperands(), e = MI->getNumOperands(); + i != e; ++i) { + MachineOperand &MO = MI->getOperand(i); + if (MO.isReg() && MO.isImplicit()) + NewMI->addOperand(MO); + } +} + +/// RemoveCopyByCommutingDef - We found a non-trivially-coalescable copy with IntA +/// being the source and IntB being the dest, thus this defines a value number +/// in IntB. If the source value number (in IntA) is defined by a commutable +/// instruction and its other operand is coalesced to the copy dest register, +/// see if we can transform the copy into a noop by commuting the definition. For +/// example, +/// +/// A3 = op A2 B0 +/// ... +/// B1 = A3 <- this copy +/// ... +/// = op A3 <- more uses +/// +/// ==> +/// +/// B2 = op B0 A2 +/// ... +/// B1 = B2 <- now an identify copy +/// ... +/// = op B2 <- more uses +/// +/// This returns true if an interval was modified. +/// +bool SimpleRegisterCoalescing::RemoveCopyByCommutingDef(LiveInterval &IntA, + LiveInterval &IntB, + MachineInstr *CopyMI) { + SlotIndex CopyIdx = + li_->getInstructionIndex(CopyMI).getDefIndex(); + + // FIXME: For now, only eliminate the copy by commuting its def when the + // source register is a virtual register. We want to guard against cases + // where the copy is a back edge copy and commuting the def lengthen the + // live interval of the source register to the entire loop. + if (TargetRegisterInfo::isPhysicalRegister(IntA.reg)) + return false; + + // BValNo is a value number in B that is defined by a copy from A. 'B3' in + // the example above. + LiveInterval::iterator BLR = IntB.FindLiveRangeContaining(CopyIdx); + assert(BLR != IntB.end() && "Live range not found!"); + VNInfo *BValNo = BLR->valno; + + // Get the location that B is defined at. Two options: either this value has + // an unknown definition point or it is defined at CopyIdx. If unknown, we + // can't process it. + if (!BValNo->getCopy()) return false; + assert(BValNo->def == CopyIdx && "Copy doesn't define the value?"); + + // AValNo is the value number in A that defines the copy, A3 in the example. + LiveInterval::iterator ALR = + IntA.FindLiveRangeContaining(CopyIdx.getUseIndex()); // + + assert(ALR != IntA.end() && "Live range not found!"); + VNInfo *AValNo = ALR->valno; + // If other defs can reach uses of this def, then it's not safe to perform + // the optimization. FIXME: Do isPHIDef and isDefAccurate both need to be + // tested? + if (AValNo->isPHIDef() || !AValNo->isDefAccurate() || + AValNo->isUnused() || AValNo->hasPHIKill()) + return false; + MachineInstr *DefMI = li_->getInstructionFromIndex(AValNo->def); + const TargetInstrDesc &TID = DefMI->getDesc(); + if (!TID.isCommutable()) + return false; + // If DefMI is a two-address instruction then commuting it will change the + // destination register. + int DefIdx = DefMI->findRegisterDefOperandIdx(IntA.reg); + assert(DefIdx != -1); + unsigned UseOpIdx; + if (!DefMI->isRegTiedToUseOperand(DefIdx, &UseOpIdx)) + return false; + unsigned Op1, Op2, NewDstIdx; + if (!tii_->findCommutedOpIndices(DefMI, Op1, Op2)) + return false; + if (Op1 == UseOpIdx) + NewDstIdx = Op2; + else if (Op2 == UseOpIdx) + NewDstIdx = Op1; + else + return false; + + MachineOperand &NewDstMO = DefMI->getOperand(NewDstIdx); + unsigned NewReg = NewDstMO.getReg(); + if (NewReg != IntB.reg || !NewDstMO.isKill()) + return false; + + // Make sure there are no other definitions of IntB that would reach the + // uses which the new definition can reach. + if (HasOtherReachingDefs(IntA, IntB, AValNo, BValNo)) + return false; + + // If some of the uses of IntA.reg is already coalesced away, return false. + // It's not possible to determine whether it's safe to perform the coalescing. + for (MachineRegisterInfo::use_iterator UI = mri_->use_begin(IntA.reg), + UE = mri_->use_end(); UI != UE; ++UI) { + MachineInstr *UseMI = &*UI; + SlotIndex UseIdx = li_->getInstructionIndex(UseMI); + LiveInterval::iterator ULR = IntA.FindLiveRangeContaining(UseIdx); + if (ULR == IntA.end()) + continue; + if (ULR->valno == AValNo && JoinedCopies.count(UseMI)) + return false; + } + + // At this point we have decided that it is legal to do this + // transformation. Start by commuting the instruction. + MachineBasicBlock *MBB = DefMI->getParent(); + MachineInstr *NewMI = tii_->commuteInstruction(DefMI); + if (!NewMI) + return false; + if (NewMI != DefMI) { + li_->ReplaceMachineInstrInMaps(DefMI, NewMI); + MBB->insert(DefMI, NewMI); + MBB->erase(DefMI); + } + unsigned OpIdx = NewMI->findRegisterUseOperandIdx(IntA.reg, false); + NewMI->getOperand(OpIdx).setIsKill(); + + bool BHasPHIKill = BValNo->hasPHIKill(); + SmallVector BDeadValNos; + VNInfo::KillSet BKills; + std::map BExtend; + + // If ALR and BLR overlaps and end of BLR extends beyond end of ALR, e.g. + // A = or A, B + // ... + // B = A + // ... + // C = A + // ... + // = B + // + // then do not add kills of A to the newly created B interval. + bool Extended = BLR->end > ALR->end && ALR->end != ALR->start; + if (Extended) + BExtend[ALR->end] = BLR->end; + + // Update uses of IntA of the specific Val# with IntB. + bool BHasSubRegs = false; + if (TargetRegisterInfo::isPhysicalRegister(IntB.reg)) + BHasSubRegs = *tri_->getSubRegisters(IntB.reg); + for (MachineRegisterInfo::use_iterator UI = mri_->use_begin(IntA.reg), + UE = mri_->use_end(); UI != UE;) { + MachineOperand &UseMO = UI.getOperand(); + MachineInstr *UseMI = &*UI; + ++UI; + if (JoinedCopies.count(UseMI)) + continue; + SlotIndex UseIdx = li_->getInstructionIndex(UseMI).getUseIndex(); + LiveInterval::iterator ULR = IntA.FindLiveRangeContaining(UseIdx); + if (ULR == IntA.end() || ULR->valno != AValNo) + continue; + UseMO.setReg(NewReg); + if (UseMI == CopyMI) + continue; + if (UseMO.isKill()) { + if (Extended) + UseMO.setIsKill(false); + else + BKills.push_back(UseIdx.getDefIndex()); + } + unsigned SrcReg, DstReg, SrcSubIdx, DstSubIdx; + if (!tii_->isMoveInstr(*UseMI, SrcReg, DstReg, SrcSubIdx, DstSubIdx)) + continue; + if (DstReg == IntB.reg) { + // This copy will become a noop. If it's defining a new val#, + // remove that val# as well. However this live range is being + // extended to the end of the existing live range defined by the copy. + SlotIndex DefIdx = UseIdx.getDefIndex(); + const LiveRange *DLR = IntB.getLiveRangeContaining(DefIdx); + BHasPHIKill |= DLR->valno->hasPHIKill(); + assert(DLR->valno->def == DefIdx); + BDeadValNos.push_back(DLR->valno); + BExtend[DLR->start] = DLR->end; + JoinedCopies.insert(UseMI); + // If this is a kill but it's going to be removed, the last use + // of the same val# is the new kill. + if (UseMO.isKill()) + BKills.pop_back(); + } + } + + // We need to insert a new liverange: [ALR.start, LastUse). It may be we can + // simply extend BLR if CopyMI doesn't end the range. + DEBUG({ + errs() << "\nExtending: "; + IntB.print(errs(), tri_); + }); + + // Remove val#'s defined by copies that will be coalesced away. + for (unsigned i = 0, e = BDeadValNos.size(); i != e; ++i) { + VNInfo *DeadVNI = BDeadValNos[i]; + if (BHasSubRegs) { + for (const unsigned *SR = tri_->getSubRegisters(IntB.reg); *SR; ++SR) { + LiveInterval &SRLI = li_->getInterval(*SR); + const LiveRange *SRLR = SRLI.getLiveRangeContaining(DeadVNI->def); + SRLI.removeValNo(SRLR->valno); + } + } + IntB.removeValNo(BDeadValNos[i]); + } + + // Extend BValNo by merging in IntA live ranges of AValNo. Val# definition + // is updated. Kills are also updated. + VNInfo *ValNo = BValNo; + ValNo->def = AValNo->def; + ValNo->setCopy(0); + for (unsigned j = 0, ee = ValNo->kills.size(); j != ee; ++j) { + if (ValNo->kills[j] != BLR->end) + BKills.push_back(ValNo->kills[j]); + } + ValNo->kills.clear(); + for (LiveInterval::iterator AI = IntA.begin(), AE = IntA.end(); + AI != AE; ++AI) { + if (AI->valno != AValNo) continue; + SlotIndex End = AI->end; + std::map::iterator + EI = BExtend.find(End); + if (EI != BExtend.end()) + End = EI->second; + IntB.addRange(LiveRange(AI->start, End, ValNo)); + + // If the IntB live range is assigned to a physical register, and if that + // physreg has sub-registers, update their live intervals as well. + if (BHasSubRegs) { + for (const unsigned *SR = tri_->getSubRegisters(IntB.reg); *SR; ++SR) { + LiveInterval &SRLI = li_->getInterval(*SR); + SRLI.MergeInClobberRange(*li_, AI->start, End, li_->getVNInfoAllocator()); + } + } + } + IntB.addKills(ValNo, BKills); + ValNo->setHasPHIKill(BHasPHIKill); + + DEBUG({ + errs() << " result = "; + IntB.print(errs(), tri_); + errs() << '\n'; + errs() << "\nShortening: "; + IntA.print(errs(), tri_); + }); + + IntA.removeValNo(AValNo); + + DEBUG({ + errs() << " result = "; + IntA.print(errs(), tri_); + errs() << '\n'; + }); + + ++numCommutes; + return true; +} + +/// isSameOrFallThroughBB - Return true if MBB == SuccMBB or MBB simply +/// fallthoughs to SuccMBB. +static bool isSameOrFallThroughBB(MachineBasicBlock *MBB, + MachineBasicBlock *SuccMBB, + const TargetInstrInfo *tii_) { + if (MBB == SuccMBB) + return true; + MachineBasicBlock *TBB = 0, *FBB = 0; + SmallVector Cond; + return !tii_->AnalyzeBranch(*MBB, TBB, FBB, Cond) && !TBB && !FBB && + MBB->isSuccessor(SuccMBB); +} + +/// removeRange - Wrapper for LiveInterval::removeRange. This removes a range +/// from a physical register live interval as well as from the live intervals +/// of its sub-registers. +static void removeRange(LiveInterval &li, + SlotIndex Start, SlotIndex End, + LiveIntervals *li_, const TargetRegisterInfo *tri_) { + li.removeRange(Start, End, true); + if (TargetRegisterInfo::isPhysicalRegister(li.reg)) { + for (const unsigned* SR = tri_->getSubRegisters(li.reg); *SR; ++SR) { + if (!li_->hasInterval(*SR)) + continue; + LiveInterval &sli = li_->getInterval(*SR); + SlotIndex RemoveStart = Start; + SlotIndex RemoveEnd = Start; + + while (RemoveEnd != End) { + LiveInterval::iterator LR = sli.FindLiveRangeContaining(RemoveStart); + if (LR == sli.end()) + break; + RemoveEnd = (LR->end < End) ? LR->end : End; + sli.removeRange(RemoveStart, RemoveEnd, true); + RemoveStart = RemoveEnd; + } + } + } +} + +/// TrimLiveIntervalToLastUse - If there is a last use in the same basic block +/// as the copy instruction, trim the live interval to the last use and return +/// true. +bool +SimpleRegisterCoalescing::TrimLiveIntervalToLastUse(SlotIndex CopyIdx, + MachineBasicBlock *CopyMBB, + LiveInterval &li, + const LiveRange *LR) { + SlotIndex MBBStart = li_->getMBBStartIdx(CopyMBB); + SlotIndex LastUseIdx; + MachineOperand *LastUse = + lastRegisterUse(LR->start, CopyIdx.getPrevSlot(), li.reg, LastUseIdx); + if (LastUse) { + MachineInstr *LastUseMI = LastUse->getParent(); + if (!isSameOrFallThroughBB(LastUseMI->getParent(), CopyMBB, tii_)) { + // r1024 = op + // ... + // BB1: + // = r1024 + // + // BB2: + // r1025 = r1024 + if (MBBStart < LR->end) + removeRange(li, MBBStart, LR->end, li_, tri_); + return true; + } + + // There are uses before the copy, just shorten the live range to the end + // of last use. + LastUse->setIsKill(); + removeRange(li, LastUseIdx.getDefIndex(), LR->end, li_, tri_); + LR->valno->addKill(LastUseIdx.getDefIndex()); + unsigned SrcReg, DstReg, SrcSubIdx, DstSubIdx; + if (tii_->isMoveInstr(*LastUseMI, SrcReg, DstReg, SrcSubIdx, DstSubIdx) && + DstReg == li.reg) { + // Last use is itself an identity code. + int DeadIdx = LastUseMI->findRegisterDefOperandIdx(li.reg, false, tri_); + LastUseMI->getOperand(DeadIdx).setIsDead(); + } + return true; + } + + // Is it livein? + if (LR->start <= MBBStart && LR->end > MBBStart) { + if (LR->start == li_->getZeroIndex()) { + assert(TargetRegisterInfo::isPhysicalRegister(li.reg)); + // Live-in to the function but dead. Remove it from entry live-in set. + mf_->begin()->removeLiveIn(li.reg); + } + // FIXME: Shorten intervals in BBs that reaches this BB. + } + + return false; +} + +/// ReMaterializeTrivialDef - If the source of a copy is defined by a trivial +/// computation, replace the copy by rematerialize the definition. +bool SimpleRegisterCoalescing::ReMaterializeTrivialDef(LiveInterval &SrcInt, + unsigned DstReg, + unsigned DstSubIdx, + MachineInstr *CopyMI) { + SlotIndex CopyIdx = li_->getInstructionIndex(CopyMI).getUseIndex(); + LiveInterval::iterator SrcLR = SrcInt.FindLiveRangeContaining(CopyIdx); + assert(SrcLR != SrcInt.end() && "Live range not found!"); + VNInfo *ValNo = SrcLR->valno; + // If other defs can reach uses of this def, then it's not safe to perform + // the optimization. FIXME: Do isPHIDef and isDefAccurate both need to be + // tested? + if (ValNo->isPHIDef() || !ValNo->isDefAccurate() || + ValNo->isUnused() || ValNo->hasPHIKill()) + return false; + MachineInstr *DefMI = li_->getInstructionFromIndex(ValNo->def); + const TargetInstrDesc &TID = DefMI->getDesc(); + if (!TID.isAsCheapAsAMove()) + return false; + if (!tii_->isTriviallyReMaterializable(DefMI, AA)) + return false; + bool SawStore = false; + if (!DefMI->isSafeToMove(tii_, SawStore, AA)) + return false; + if (TID.getNumDefs() != 1) + return false; + if (DefMI->getOpcode() != TargetInstrInfo::IMPLICIT_DEF) { + // Make sure the copy destination register class fits the instruction + // definition register class. The mismatch can happen as a result of earlier + // extract_subreg, insert_subreg, subreg_to_reg coalescing. + const TargetRegisterClass *RC = TID.OpInfo[0].getRegClass(tri_); + if (TargetRegisterInfo::isVirtualRegister(DstReg)) { + if (mri_->getRegClass(DstReg) != RC) + return false; + } else if (!RC->contains(DstReg)) + return false; + } + + // If destination register has a sub-register index on it, make sure it mtches + // the instruction register class. + if (DstSubIdx) { + const TargetInstrDesc &TID = DefMI->getDesc(); + if (TID.getNumDefs() != 1) + return false; + const TargetRegisterClass *DstRC = mri_->getRegClass(DstReg); + const TargetRegisterClass *DstSubRC = + DstRC->getSubRegisterRegClass(DstSubIdx); + const TargetRegisterClass *DefRC = TID.OpInfo[0].getRegClass(tri_); + if (DefRC == DstRC) + DstSubIdx = 0; + else if (DefRC != DstSubRC) + return false; + } + + SlotIndex DefIdx = CopyIdx.getDefIndex(); + const LiveRange *DLR= li_->getInterval(DstReg).getLiveRangeContaining(DefIdx); + DLR->valno->setCopy(0); + // Don't forget to update sub-register intervals. + if (TargetRegisterInfo::isPhysicalRegister(DstReg)) { + for (const unsigned* SR = tri_->getSubRegisters(DstReg); *SR; ++SR) { + if (!li_->hasInterval(*SR)) + continue; + DLR = li_->getInterval(*SR).getLiveRangeContaining(DefIdx); + if (DLR && DLR->valno->getCopy() == CopyMI) + DLR->valno->setCopy(0); + } + } + + // If copy kills the source register, find the last use and propagate + // kill. + bool checkForDeadDef = false; + MachineBasicBlock *MBB = CopyMI->getParent(); + if (CopyMI->killsRegister(SrcInt.reg)) + if (!TrimLiveIntervalToLastUse(CopyIdx, MBB, SrcInt, SrcLR)) { + checkForDeadDef = true; + } + + MachineBasicBlock::iterator MII = next(MachineBasicBlock::iterator(CopyMI)); + tii_->reMaterialize(*MBB, MII, DstReg, DstSubIdx, DefMI, tri_); + MachineInstr *NewMI = prior(MII); + + if (checkForDeadDef) { + // PR4090 fix: Trim interval failed because there was no use of the + // source interval in this MBB. If the def is in this MBB too then we + // should mark it dead: + if (DefMI->getParent() == MBB) { + DefMI->addRegisterDead(SrcInt.reg, tri_); + SrcLR->end = SrcLR->start.getNextSlot(); + } + } + + // CopyMI may have implicit operands, transfer them over to the newly + // rematerialized instruction. And update implicit def interval valnos. + for (unsigned i = CopyMI->getDesc().getNumOperands(), + e = CopyMI->getNumOperands(); i != e; ++i) { + MachineOperand &MO = CopyMI->getOperand(i); + if (MO.isReg() && MO.isImplicit()) + NewMI->addOperand(MO); + if (MO.isDef() && li_->hasInterval(MO.getReg())) { + unsigned Reg = MO.getReg(); + DLR = li_->getInterval(Reg).getLiveRangeContaining(DefIdx); + if (DLR && DLR->valno->getCopy() == CopyMI) + DLR->valno->setCopy(0); + } + } + + TransferImplicitOps(CopyMI, NewMI); + li_->ReplaceMachineInstrInMaps(CopyMI, NewMI); + CopyMI->eraseFromParent(); + ReMatCopies.insert(CopyMI); + ReMatDefs.insert(DefMI); + ++NumReMats; + return true; +} + +/// UpdateRegDefsUses - Replace all defs and uses of SrcReg to DstReg and +/// update the subregister number if it is not zero. If DstReg is a +/// physical register and the existing subregister number of the def / use +/// being updated is not zero, make sure to set it to the correct physical +/// subregister. +void +SimpleRegisterCoalescing::UpdateRegDefsUses(unsigned SrcReg, unsigned DstReg, + unsigned SubIdx) { + bool DstIsPhys = TargetRegisterInfo::isPhysicalRegister(DstReg); + if (DstIsPhys && SubIdx) { + // Figure out the real physical register we are updating with. + DstReg = tri_->getSubReg(DstReg, SubIdx); + SubIdx = 0; + } + + for (MachineRegisterInfo::reg_iterator I = mri_->reg_begin(SrcReg), + E = mri_->reg_end(); I != E; ) { + MachineOperand &O = I.getOperand(); + MachineInstr *UseMI = &*I; + ++I; + unsigned OldSubIdx = O.getSubReg(); + if (DstIsPhys) { + unsigned UseDstReg = DstReg; + if (OldSubIdx) + UseDstReg = tri_->getSubReg(DstReg, OldSubIdx); + + unsigned CopySrcReg, CopyDstReg, CopySrcSubIdx, CopyDstSubIdx; + if (tii_->isMoveInstr(*UseMI, CopySrcReg, CopyDstReg, + CopySrcSubIdx, CopyDstSubIdx) && + CopySrcReg != CopyDstReg && + CopySrcReg == SrcReg && CopyDstReg != UseDstReg) { + // If the use is a copy and it won't be coalesced away, and its source + // is defined by a trivial computation, try to rematerialize it instead. + if (ReMaterializeTrivialDef(li_->getInterval(SrcReg), CopyDstReg, + CopyDstSubIdx, UseMI)) + continue; + } + + O.setReg(UseDstReg); + O.setSubReg(0); + continue; + } + + // Sub-register indexes goes from small to large. e.g. + // RAX: 1 -> AL, 2 -> AX, 3 -> EAX + // EAX: 1 -> AL, 2 -> AX + // So RAX's sub-register 2 is AX, RAX's sub-regsiter 3 is EAX, whose + // sub-register 2 is also AX. + if (SubIdx && OldSubIdx && SubIdx != OldSubIdx) + assert(OldSubIdx < SubIdx && "Conflicting sub-register index!"); + else if (SubIdx) + O.setSubReg(SubIdx); + // Remove would-be duplicated kill marker. + if (O.isKill() && UseMI->killsRegister(DstReg)) + O.setIsKill(false); + O.setReg(DstReg); + + // After updating the operand, check if the machine instruction has + // become a copy. If so, update its val# information. + if (JoinedCopies.count(UseMI)) + continue; + + const TargetInstrDesc &TID = UseMI->getDesc(); + unsigned CopySrcReg, CopyDstReg, CopySrcSubIdx, CopyDstSubIdx; + if (TID.getNumDefs() == 1 && TID.getNumOperands() > 2 && + tii_->isMoveInstr(*UseMI, CopySrcReg, CopyDstReg, + CopySrcSubIdx, CopyDstSubIdx) && + CopySrcReg != CopyDstReg && + (TargetRegisterInfo::isVirtualRegister(CopyDstReg) || + allocatableRegs_[CopyDstReg])) { + LiveInterval &LI = li_->getInterval(CopyDstReg); + SlotIndex DefIdx = + li_->getInstructionIndex(UseMI).getDefIndex(); + if (const LiveRange *DLR = LI.getLiveRangeContaining(DefIdx)) { + if (DLR->valno->def == DefIdx) + DLR->valno->setCopy(UseMI); + } + } + } +} + +/// RemoveUnnecessaryKills - Remove kill markers that are no longer accurate +/// due to live range lengthening as the result of coalescing. +void SimpleRegisterCoalescing::RemoveUnnecessaryKills(unsigned Reg, + LiveInterval &LI) { + for (MachineRegisterInfo::use_iterator UI = mri_->use_begin(Reg), + UE = mri_->use_end(); UI != UE; ++UI) { + MachineOperand &UseMO = UI.getOperand(); + if (!UseMO.isKill()) + continue; + MachineInstr *UseMI = UseMO.getParent(); + SlotIndex UseIdx = + li_->getInstructionIndex(UseMI).getUseIndex(); + const LiveRange *LR = LI.getLiveRangeContaining(UseIdx); + if (!LR || + (!LR->valno->isKill(UseIdx.getDefIndex()) && + LR->valno->def != UseIdx.getDefIndex())) { + // Interesting problem. After coalescing reg1027's def and kill are both + // at the same point: %reg1027,0.000000e+00 = [56,814:0) 0@70-(814) + // + // bb5: + // 60 %reg1027 = t2MOVr %reg1027, 14, %reg0, %reg0 + // 68 %reg1027 = t2LDRi12 %reg1027, 8, 14, %reg0 + // 76 t2CMPzri %reg1038, 0, 14, %reg0, %CPSR + // 84 %reg1027 = t2MOVr %reg1027, 14, %reg0, %reg0 + // 96 t2Bcc mbb, 1, %CPSR + // + // Do not remove the kill marker on t2LDRi12. + UseMO.setIsKill(false); + } + } +} + +/// removeIntervalIfEmpty - Check if the live interval of a physical register +/// is empty, if so remove it and also remove the empty intervals of its +/// sub-registers. Return true if live interval is removed. +static bool removeIntervalIfEmpty(LiveInterval &li, LiveIntervals *li_, + const TargetRegisterInfo *tri_) { + if (li.empty()) { + if (TargetRegisterInfo::isPhysicalRegister(li.reg)) + for (const unsigned* SR = tri_->getSubRegisters(li.reg); *SR; ++SR) { + if (!li_->hasInterval(*SR)) + continue; + LiveInterval &sli = li_->getInterval(*SR); + if (sli.empty()) + li_->removeInterval(*SR); + } + li_->removeInterval(li.reg); + return true; + } + return false; +} + +/// ShortenDeadCopyLiveRange - Shorten a live range defined by a dead copy. +/// Return true if live interval is removed. +bool SimpleRegisterCoalescing::ShortenDeadCopyLiveRange(LiveInterval &li, + MachineInstr *CopyMI) { + SlotIndex CopyIdx = li_->getInstructionIndex(CopyMI); + LiveInterval::iterator MLR = + li.FindLiveRangeContaining(CopyIdx.getDefIndex()); + if (MLR == li.end()) + return false; // Already removed by ShortenDeadCopySrcLiveRange. + SlotIndex RemoveStart = MLR->start; + SlotIndex RemoveEnd = MLR->end; + SlotIndex DefIdx = CopyIdx.getDefIndex(); + // Remove the liverange that's defined by this. + if (RemoveStart == DefIdx && RemoveEnd == DefIdx.getStoreIndex()) { + removeRange(li, RemoveStart, RemoveEnd, li_, tri_); + return removeIntervalIfEmpty(li, li_, tri_); + } + return false; +} + +/// RemoveDeadDef - If a def of a live interval is now determined dead, remove +/// the val# it defines. If the live interval becomes empty, remove it as well. +bool SimpleRegisterCoalescing::RemoveDeadDef(LiveInterval &li, + MachineInstr *DefMI) { + SlotIndex DefIdx = li_->getInstructionIndex(DefMI).getDefIndex(); + LiveInterval::iterator MLR = li.FindLiveRangeContaining(DefIdx); + if (DefIdx != MLR->valno->def) + return false; + li.removeValNo(MLR->valno); + return removeIntervalIfEmpty(li, li_, tri_); +} + +/// PropagateDeadness - Propagate the dead marker to the instruction which +/// defines the val#. +static void PropagateDeadness(LiveInterval &li, MachineInstr *CopyMI, + SlotIndex &LRStart, LiveIntervals *li_, + const TargetRegisterInfo* tri_) { + MachineInstr *DefMI = + li_->getInstructionFromIndex(LRStart.getDefIndex()); + if (DefMI && DefMI != CopyMI) { + int DeadIdx = DefMI->findRegisterDefOperandIdx(li.reg, false); + if (DeadIdx != -1) + DefMI->getOperand(DeadIdx).setIsDead(); + else + DefMI->addOperand(MachineOperand::CreateReg(li.reg, + /*def*/true, /*implicit*/true, /*kill*/false, /*dead*/true)); + LRStart = LRStart.getNextSlot(); + } +} + +/// ShortenDeadCopySrcLiveRange - Shorten a live range as it's artificially +/// extended by a dead copy. Mark the last use (if any) of the val# as kill as +/// ends the live range there. If there isn't another use, then this live range +/// is dead. Return true if live interval is removed. +bool +SimpleRegisterCoalescing::ShortenDeadCopySrcLiveRange(LiveInterval &li, + MachineInstr *CopyMI) { + SlotIndex CopyIdx = li_->getInstructionIndex(CopyMI); + if (CopyIdx == SlotIndex()) { + // FIXME: special case: function live in. It can be a general case if the + // first instruction index starts at > 0 value. + assert(TargetRegisterInfo::isPhysicalRegister(li.reg)); + // Live-in to the function but dead. Remove it from entry live-in set. + if (mf_->begin()->isLiveIn(li.reg)) + mf_->begin()->removeLiveIn(li.reg); + const LiveRange *LR = li.getLiveRangeContaining(CopyIdx); + removeRange(li, LR->start, LR->end, li_, tri_); + return removeIntervalIfEmpty(li, li_, tri_); + } + + LiveInterval::iterator LR = + li.FindLiveRangeContaining(CopyIdx.getPrevIndex().getStoreIndex()); + if (LR == li.end()) + // Livein but defined by a phi. + return false; + + SlotIndex RemoveStart = LR->start; + SlotIndex RemoveEnd = CopyIdx.getStoreIndex(); + if (LR->end > RemoveEnd) + // More uses past this copy? Nothing to do. + return false; + + // If there is a last use in the same bb, we can't remove the live range. + // Shorten the live interval and return. + MachineBasicBlock *CopyMBB = CopyMI->getParent(); + if (TrimLiveIntervalToLastUse(CopyIdx, CopyMBB, li, LR)) + return false; + + // There are other kills of the val#. Nothing to do. + if (!li.isOnlyLROfValNo(LR)) + return false; + + MachineBasicBlock *StartMBB = li_->getMBBFromIndex(RemoveStart); + if (!isSameOrFallThroughBB(StartMBB, CopyMBB, tii_)) + // If the live range starts in another mbb and the copy mbb is not a fall + // through mbb, then we can only cut the range from the beginning of the + // copy mbb. + RemoveStart = li_->getMBBStartIdx(CopyMBB).getNextIndex().getBaseIndex(); + + if (LR->valno->def == RemoveStart) { + // If the def MI defines the val# and this copy is the only kill of the + // val#, then propagate the dead marker. + PropagateDeadness(li, CopyMI, RemoveStart, li_, tri_); + ++numDeadValNo; + + if (LR->valno->isKill(RemoveEnd)) + LR->valno->removeKill(RemoveEnd); + } + + removeRange(li, RemoveStart, RemoveEnd, li_, tri_); + return removeIntervalIfEmpty(li, li_, tri_); +} + +/// CanCoalesceWithImpDef - Returns true if the specified copy instruction +/// from an implicit def to another register can be coalesced away. +bool SimpleRegisterCoalescing::CanCoalesceWithImpDef(MachineInstr *CopyMI, + LiveInterval &li, + LiveInterval &ImpLi) const{ + if (!CopyMI->killsRegister(ImpLi.reg)) + return false; + // Make sure this is the only use. + for (MachineRegisterInfo::use_iterator UI = mri_->use_begin(ImpLi.reg), + UE = mri_->use_end(); UI != UE;) { + MachineInstr *UseMI = &*UI; + ++UI; + if (CopyMI == UseMI || JoinedCopies.count(UseMI)) + continue; + return false; + } + return true; +} + + +/// isWinToJoinVRWithSrcPhysReg - Return true if it's worth while to join a +/// a virtual destination register with physical source register. +bool +SimpleRegisterCoalescing::isWinToJoinVRWithSrcPhysReg(MachineInstr *CopyMI, + MachineBasicBlock *CopyMBB, + LiveInterval &DstInt, + LiveInterval &SrcInt) { + // If the virtual register live interval is long but it has low use desity, + // do not join them, instead mark the physical register as its allocation + // preference. + const TargetRegisterClass *RC = mri_->getRegClass(DstInt.reg); + unsigned Threshold = allocatableRCRegs_[RC].count() * 2; + unsigned Length = li_->getApproximateInstructionCount(DstInt); + if (Length > Threshold && + (((float)std::distance(mri_->use_begin(DstInt.reg), + mri_->use_end()) / Length) < (1.0 / Threshold))) + return false; + + // If the virtual register live interval extends into a loop, turn down + // aggressiveness. + SlotIndex CopyIdx = + li_->getInstructionIndex(CopyMI).getDefIndex(); + const MachineLoop *L = loopInfo->getLoopFor(CopyMBB); + if (!L) { + // Let's see if the virtual register live interval extends into the loop. + LiveInterval::iterator DLR = DstInt.FindLiveRangeContaining(CopyIdx); + assert(DLR != DstInt.end() && "Live range not found!"); + DLR = DstInt.FindLiveRangeContaining(DLR->end.getNextSlot()); + if (DLR != DstInt.end()) { + CopyMBB = li_->getMBBFromIndex(DLR->start); + L = loopInfo->getLoopFor(CopyMBB); + } + } + + if (!L || Length <= Threshold) + return true; + + SlotIndex UseIdx = CopyIdx.getUseIndex(); + LiveInterval::iterator SLR = SrcInt.FindLiveRangeContaining(UseIdx); + MachineBasicBlock *SMBB = li_->getMBBFromIndex(SLR->start); + if (loopInfo->getLoopFor(SMBB) != L) { + if (!loopInfo->isLoopHeader(CopyMBB)) + return false; + // If vr's live interval extends pass the loop header, do not join. + for (MachineBasicBlock::succ_iterator SI = CopyMBB->succ_begin(), + SE = CopyMBB->succ_end(); SI != SE; ++SI) { + MachineBasicBlock *SuccMBB = *SI; + if (SuccMBB == CopyMBB) + continue; + if (DstInt.overlaps(li_->getMBBStartIdx(SuccMBB), + li_->getMBBEndIdx(SuccMBB).getNextIndex().getBaseIndex())) + return false; + } + } + return true; +} + +/// isWinToJoinVRWithDstPhysReg - Return true if it's worth while to join a +/// copy from a virtual source register to a physical destination register. +bool +SimpleRegisterCoalescing::isWinToJoinVRWithDstPhysReg(MachineInstr *CopyMI, + MachineBasicBlock *CopyMBB, + LiveInterval &DstInt, + LiveInterval &SrcInt) { + // If the virtual register live interval is long but it has low use desity, + // do not join them, instead mark the physical register as its allocation + // preference. + const TargetRegisterClass *RC = mri_->getRegClass(SrcInt.reg); + unsigned Threshold = allocatableRCRegs_[RC].count() * 2; + unsigned Length = li_->getApproximateInstructionCount(SrcInt); + if (Length > Threshold && + (((float)std::distance(mri_->use_begin(SrcInt.reg), + mri_->use_end()) / Length) < (1.0 / Threshold))) + return false; + + if (SrcInt.empty()) + // Must be implicit_def. + return false; + + // If the virtual register live interval is defined or cross a loop, turn + // down aggressiveness. + SlotIndex CopyIdx = + li_->getInstructionIndex(CopyMI).getDefIndex(); + SlotIndex UseIdx = CopyIdx.getUseIndex(); + LiveInterval::iterator SLR = SrcInt.FindLiveRangeContaining(UseIdx); + assert(SLR != SrcInt.end() && "Live range not found!"); + SLR = SrcInt.FindLiveRangeContaining(SLR->start.getPrevSlot()); + if (SLR == SrcInt.end()) + return true; + MachineBasicBlock *SMBB = li_->getMBBFromIndex(SLR->start); + const MachineLoop *L = loopInfo->getLoopFor(SMBB); + + if (!L || Length <= Threshold) + return true; + + if (loopInfo->getLoopFor(CopyMBB) != L) { + if (SMBB != L->getLoopLatch()) + return false; + // If vr's live interval is extended from before the loop latch, do not + // join. + for (MachineBasicBlock::pred_iterator PI = SMBB->pred_begin(), + PE = SMBB->pred_end(); PI != PE; ++PI) { + MachineBasicBlock *PredMBB = *PI; + if (PredMBB == SMBB) + continue; + if (SrcInt.overlaps(li_->getMBBStartIdx(PredMBB), + li_->getMBBEndIdx(PredMBB).getNextIndex().getBaseIndex())) + return false; + } + } + return true; +} + +/// isWinToJoinCrossClass - Return true if it's profitable to coalesce +/// two virtual registers from different register classes. +bool +SimpleRegisterCoalescing::isWinToJoinCrossClass(unsigned LargeReg, + unsigned SmallReg, + unsigned Threshold) { + // Then make sure the intervals are *short*. + LiveInterval &LargeInt = li_->getInterval(LargeReg); + LiveInterval &SmallInt = li_->getInterval(SmallReg); + unsigned LargeSize = li_->getApproximateInstructionCount(LargeInt); + unsigned SmallSize = li_->getApproximateInstructionCount(SmallInt); + if (SmallSize > Threshold || LargeSize > Threshold) + if ((float)std::distance(mri_->use_begin(SmallReg), + mri_->use_end()) / SmallSize < + (float)std::distance(mri_->use_begin(LargeReg), + mri_->use_end()) / LargeSize) + return false; + return true; +} + +/// HasIncompatibleSubRegDefUse - If we are trying to coalesce a virtual +/// register with a physical register, check if any of the virtual register +/// operand is a sub-register use or def. If so, make sure it won't result +/// in an illegal extract_subreg or insert_subreg instruction. e.g. +/// vr1024 = extract_subreg vr1025, 1 +/// ... +/// vr1024 = mov8rr AH +/// If vr1024 is coalesced with AH, the extract_subreg is now illegal since +/// AH does not have a super-reg whose sub-register 1 is AH. +bool +SimpleRegisterCoalescing::HasIncompatibleSubRegDefUse(MachineInstr *CopyMI, + unsigned VirtReg, + unsigned PhysReg) { + for (MachineRegisterInfo::reg_iterator I = mri_->reg_begin(VirtReg), + E = mri_->reg_end(); I != E; ++I) { + MachineOperand &O = I.getOperand(); + MachineInstr *MI = &*I; + if (MI == CopyMI || JoinedCopies.count(MI)) + continue; + unsigned SubIdx = O.getSubReg(); + if (SubIdx && !tri_->getSubReg(PhysReg, SubIdx)) + return true; + if (MI->getOpcode() == TargetInstrInfo::EXTRACT_SUBREG) { + SubIdx = MI->getOperand(2).getImm(); + if (O.isUse() && !tri_->getSubReg(PhysReg, SubIdx)) + return true; + if (O.isDef()) { + unsigned SrcReg = MI->getOperand(1).getReg(); + const TargetRegisterClass *RC = + TargetRegisterInfo::isPhysicalRegister(SrcReg) + ? tri_->getPhysicalRegisterRegClass(SrcReg) + : mri_->getRegClass(SrcReg); + if (!tri_->getMatchingSuperReg(PhysReg, SubIdx, RC)) + return true; + } + } + if (MI->getOpcode() == TargetInstrInfo::INSERT_SUBREG || + MI->getOpcode() == TargetInstrInfo::SUBREG_TO_REG) { + SubIdx = MI->getOperand(3).getImm(); + if (VirtReg == MI->getOperand(0).getReg()) { + if (!tri_->getSubReg(PhysReg, SubIdx)) + return true; + } else { + unsigned DstReg = MI->getOperand(0).getReg(); + const TargetRegisterClass *RC = + TargetRegisterInfo::isPhysicalRegister(DstReg) + ? tri_->getPhysicalRegisterRegClass(DstReg) + : mri_->getRegClass(DstReg); + if (!tri_->getMatchingSuperReg(PhysReg, SubIdx, RC)) + return true; + } + } + } + return false; +} + + +/// CanJoinExtractSubRegToPhysReg - Return true if it's possible to coalesce +/// an extract_subreg where dst is a physical register, e.g. +/// cl = EXTRACT_SUBREG reg1024, 1 +bool +SimpleRegisterCoalescing::CanJoinExtractSubRegToPhysReg(unsigned DstReg, + unsigned SrcReg, unsigned SubIdx, + unsigned &RealDstReg) { + const TargetRegisterClass *RC = mri_->getRegClass(SrcReg); + RealDstReg = tri_->getMatchingSuperReg(DstReg, SubIdx, RC); + assert(RealDstReg && "Invalid extract_subreg instruction!"); + + // For this type of EXTRACT_SUBREG, conservatively + // check if the live interval of the source register interfere with the + // actual super physical register we are trying to coalesce with. + LiveInterval &RHS = li_->getInterval(SrcReg); + if (li_->hasInterval(RealDstReg) && + RHS.overlaps(li_->getInterval(RealDstReg))) { + DEBUG({ + errs() << "Interfere with register "; + li_->getInterval(RealDstReg).print(errs(), tri_); + }); + return false; // Not coalescable + } + for (const unsigned* SR = tri_->getSubRegisters(RealDstReg); *SR; ++SR) + if (li_->hasInterval(*SR) && RHS.overlaps(li_->getInterval(*SR))) { + DEBUG({ + errs() << "Interfere with sub-register "; + li_->getInterval(*SR).print(errs(), tri_); + }); + return false; // Not coalescable + } + return true; +} + +/// CanJoinInsertSubRegToPhysReg - Return true if it's possible to coalesce +/// an insert_subreg where src is a physical register, e.g. +/// reg1024 = INSERT_SUBREG reg1024, c1, 0 +bool +SimpleRegisterCoalescing::CanJoinInsertSubRegToPhysReg(unsigned DstReg, + unsigned SrcReg, unsigned SubIdx, + unsigned &RealSrcReg) { + const TargetRegisterClass *RC = mri_->getRegClass(DstReg); + RealSrcReg = tri_->getMatchingSuperReg(SrcReg, SubIdx, RC); + assert(RealSrcReg && "Invalid extract_subreg instruction!"); + + LiveInterval &RHS = li_->getInterval(DstReg); + if (li_->hasInterval(RealSrcReg) && + RHS.overlaps(li_->getInterval(RealSrcReg))) { + DEBUG({ + errs() << "Interfere with register "; + li_->getInterval(RealSrcReg).print(errs(), tri_); + }); + return false; // Not coalescable + } + for (const unsigned* SR = tri_->getSubRegisters(RealSrcReg); *SR; ++SR) + if (li_->hasInterval(*SR) && RHS.overlaps(li_->getInterval(*SR))) { + DEBUG({ + errs() << "Interfere with sub-register "; + li_->getInterval(*SR).print(errs(), tri_); + }); + return false; // Not coalescable + } + return true; +} + +/// getRegAllocPreference - Return register allocation preference register. +/// +static unsigned getRegAllocPreference(unsigned Reg, MachineFunction &MF, + MachineRegisterInfo *MRI, + const TargetRegisterInfo *TRI) { + if (TargetRegisterInfo::isPhysicalRegister(Reg)) + return 0; + std::pair Hint = MRI->getRegAllocationHint(Reg); + return TRI->ResolveRegAllocHint(Hint.first, Hint.second, MF); +} + +/// JoinCopy - Attempt to join intervals corresponding to SrcReg/DstReg, +/// which are the src/dst of the copy instruction CopyMI. This returns true +/// if the copy was successfully coalesced away. If it is not currently +/// possible to coalesce this interval, but it may be possible if other +/// things get coalesced, then it returns true by reference in 'Again'. +bool SimpleRegisterCoalescing::JoinCopy(CopyRec &TheCopy, bool &Again) { + MachineInstr *CopyMI = TheCopy.MI; + + Again = false; + if (JoinedCopies.count(CopyMI) || ReMatCopies.count(CopyMI)) + return false; // Already done. + + DEBUG(errs() << li_->getInstructionIndex(CopyMI) << '\t' << *CopyMI); + + unsigned SrcReg, DstReg, SrcSubIdx = 0, DstSubIdx = 0; + bool isExtSubReg = CopyMI->getOpcode() == TargetInstrInfo::EXTRACT_SUBREG; + bool isInsSubReg = CopyMI->getOpcode() == TargetInstrInfo::INSERT_SUBREG; + bool isSubRegToReg = CopyMI->getOpcode() == TargetInstrInfo::SUBREG_TO_REG; + unsigned SubIdx = 0; + if (isExtSubReg) { + DstReg = CopyMI->getOperand(0).getReg(); + DstSubIdx = CopyMI->getOperand(0).getSubReg(); + SrcReg = CopyMI->getOperand(1).getReg(); + SrcSubIdx = CopyMI->getOperand(2).getImm(); + } else if (isInsSubReg || isSubRegToReg) { + DstReg = CopyMI->getOperand(0).getReg(); + DstSubIdx = CopyMI->getOperand(3).getImm(); + SrcReg = CopyMI->getOperand(2).getReg(); + SrcSubIdx = CopyMI->getOperand(2).getSubReg(); + if (SrcSubIdx && SrcSubIdx != DstSubIdx) { + // r1025 = INSERT_SUBREG r1025, r1024<2>, 2 Then r1024 has already been + // coalesced to a larger register so the subreg indices cancel out. + DEBUG(errs() << "\tSource of insert_subreg or subreg_to_reg is already " + "coalesced to another register.\n"); + return false; // Not coalescable. + } + } else if (!tii_->isMoveInstr(*CopyMI, SrcReg, DstReg, SrcSubIdx, DstSubIdx)){ + llvm_unreachable("Unrecognized copy instruction!"); + } + + // If they are already joined we continue. + if (SrcReg == DstReg) { + DEBUG(errs() << "\tCopy already coalesced.\n"); + return false; // Not coalescable. + } + + bool SrcIsPhys = TargetRegisterInfo::isPhysicalRegister(SrcReg); + bool DstIsPhys = TargetRegisterInfo::isPhysicalRegister(DstReg); + + // If they are both physical registers, we cannot join them. + if (SrcIsPhys && DstIsPhys) { + DEBUG(errs() << "\tCan not coalesce physregs.\n"); + return false; // Not coalescable. + } + + // We only join virtual registers with allocatable physical registers. + if (SrcIsPhys && !allocatableRegs_[SrcReg]) { + DEBUG(errs() << "\tSrc reg is unallocatable physreg.\n"); + return false; // Not coalescable. + } + if (DstIsPhys && !allocatableRegs_[DstReg]) { + DEBUG(errs() << "\tDst reg is unallocatable physreg.\n"); + return false; // Not coalescable. + } + + // Check that a physical source register is compatible with dst regclass + if (SrcIsPhys) { + unsigned SrcSubReg = SrcSubIdx ? + tri_->getSubReg(SrcReg, SrcSubIdx) : SrcReg; + const TargetRegisterClass *DstRC = mri_->getRegClass(DstReg); + const TargetRegisterClass *DstSubRC = DstRC; + if (DstSubIdx) + DstSubRC = DstRC->getSubRegisterRegClass(DstSubIdx); + assert(DstSubRC && "Illegal subregister index"); + if (!DstSubRC->contains(SrcSubReg)) { + DEBUG(errs() << "\tIncompatible destination regclass: " + << tri_->getName(SrcSubReg) << " not in " + << DstSubRC->getName() << ".\n"); + return false; // Not coalescable. + } + } + + // Check that a physical dst register is compatible with source regclass + if (DstIsPhys) { + unsigned DstSubReg = DstSubIdx ? + tri_->getSubReg(DstReg, DstSubIdx) : DstReg; + const TargetRegisterClass *SrcRC = mri_->getRegClass(SrcReg); + const TargetRegisterClass *SrcSubRC = SrcRC; + if (SrcSubIdx) + SrcSubRC = SrcRC->getSubRegisterRegClass(SrcSubIdx); + assert(SrcSubRC && "Illegal subregister index"); + if (!SrcSubRC->contains(DstSubReg)) { + DEBUG(errs() << "\tIncompatible source regclass: " + << tri_->getName(DstSubReg) << " not in " + << SrcSubRC->getName() << ".\n"); + (void)DstSubReg; + return false; // Not coalescable. + } + } + + // Should be non-null only when coalescing to a sub-register class. + bool CrossRC = false; + const TargetRegisterClass *SrcRC= SrcIsPhys ? 0 : mri_->getRegClass(SrcReg); + const TargetRegisterClass *DstRC= DstIsPhys ? 0 : mri_->getRegClass(DstReg); + const TargetRegisterClass *NewRC = NULL; + MachineBasicBlock *CopyMBB = CopyMI->getParent(); + unsigned RealDstReg = 0; + unsigned RealSrcReg = 0; + if (isExtSubReg || isInsSubReg || isSubRegToReg) { + SubIdx = CopyMI->getOperand(isExtSubReg ? 2 : 3).getImm(); + if (SrcIsPhys && isExtSubReg) { + // r1024 = EXTRACT_SUBREG EAX, 0 then r1024 is really going to be + // coalesced with AX. + unsigned DstSubIdx = CopyMI->getOperand(0).getSubReg(); + if (DstSubIdx) { + // r1024<2> = EXTRACT_SUBREG EAX, 2. Then r1024 has already been + // coalesced to a larger register so the subreg indices cancel out. + if (DstSubIdx != SubIdx) { + DEBUG(errs() << "\t Sub-register indices mismatch.\n"); + return false; // Not coalescable. + } + } else + SrcReg = tri_->getSubReg(SrcReg, SubIdx); + SubIdx = 0; + } else if (DstIsPhys && (isInsSubReg || isSubRegToReg)) { + // EAX = INSERT_SUBREG EAX, r1024, 0 + unsigned SrcSubIdx = CopyMI->getOperand(2).getSubReg(); + if (SrcSubIdx) { + // EAX = INSERT_SUBREG EAX, r1024<2>, 2 Then r1024 has already been + // coalesced to a larger register so the subreg indices cancel out. + if (SrcSubIdx != SubIdx) { + DEBUG(errs() << "\t Sub-register indices mismatch.\n"); + return false; // Not coalescable. + } + } else + DstReg = tri_->getSubReg(DstReg, SubIdx); + SubIdx = 0; + } else if ((DstIsPhys && isExtSubReg) || + (SrcIsPhys && (isInsSubReg || isSubRegToReg))) { + if (!isSubRegToReg && CopyMI->getOperand(1).getSubReg()) { + DEBUG(errs() << "\tSrc of extract_subreg already coalesced with reg" + << " of a super-class.\n"); + return false; // Not coalescable. + } + + if (isExtSubReg) { + if (!CanJoinExtractSubRegToPhysReg(DstReg, SrcReg, SubIdx, RealDstReg)) + return false; // Not coalescable + } else { + if (!CanJoinInsertSubRegToPhysReg(DstReg, SrcReg, SubIdx, RealSrcReg)) + return false; // Not coalescable + } + SubIdx = 0; + } else { + unsigned OldSubIdx = isExtSubReg ? CopyMI->getOperand(0).getSubReg() + : CopyMI->getOperand(2).getSubReg(); + if (OldSubIdx) { + if (OldSubIdx == SubIdx && !differingRegisterClasses(SrcReg, DstReg)) + // r1024<2> = EXTRACT_SUBREG r1025, 2. Then r1024 has already been + // coalesced to a larger register so the subreg indices cancel out. + // Also check if the other larger register is of the same register + // class as the would be resulting register. + SubIdx = 0; + else { + DEBUG(errs() << "\t Sub-register indices mismatch.\n"); + return false; // Not coalescable. + } + } + if (SubIdx) { + if (!DstIsPhys && !SrcIsPhys) { + if (isInsSubReg || isSubRegToReg) { + NewRC = tri_->getMatchingSuperRegClass(DstRC, SrcRC, SubIdx); + } else // extract_subreg { + NewRC = tri_->getMatchingSuperRegClass(SrcRC, DstRC, SubIdx); + } + if (!NewRC) { + DEBUG(errs() << "\t Conflicting sub-register indices.\n"); + return false; // Not coalescable + } + + unsigned LargeReg = isExtSubReg ? SrcReg : DstReg; + unsigned SmallReg = isExtSubReg ? DstReg : SrcReg; + unsigned Limit= allocatableRCRegs_[mri_->getRegClass(SmallReg)].count(); + if (!isWinToJoinCrossClass(LargeReg, SmallReg, Limit)) { + Again = true; // May be possible to coalesce later. + return false; + } + } + } + } else if (differingRegisterClasses(SrcReg, DstReg)) { + if (DisableCrossClassJoin) + return false; + CrossRC = true; + + // FIXME: What if the result of a EXTRACT_SUBREG is then coalesced + // with another? If it's the resulting destination register, then + // the subidx must be propagated to uses (but only those defined + // by the EXTRACT_SUBREG). If it's being coalesced into another + // register, it should be safe because register is assumed to have + // the register class of the super-register. + + // Process moves where one of the registers have a sub-register index. + MachineOperand *DstMO = CopyMI->findRegisterDefOperand(DstReg); + MachineOperand *SrcMO = CopyMI->findRegisterUseOperand(SrcReg); + SubIdx = DstMO->getSubReg(); + if (SubIdx) { + if (SrcMO->getSubReg()) + // FIXME: can we handle this? + return false; + // This is not an insert_subreg but it looks like one. + // e.g. %reg1024:4 = MOV32rr %EAX + isInsSubReg = true; + if (SrcIsPhys) { + if (!CanJoinInsertSubRegToPhysReg(DstReg, SrcReg, SubIdx, RealSrcReg)) + return false; // Not coalescable + SubIdx = 0; + } + } else { + SubIdx = SrcMO->getSubReg(); + if (SubIdx) { + // This is not a extract_subreg but it looks like one. + // e.g. %cl = MOV16rr %reg1024:1 + isExtSubReg = true; + if (DstIsPhys) { + if (!CanJoinExtractSubRegToPhysReg(DstReg, SrcReg, SubIdx,RealDstReg)) + return false; // Not coalescable + SubIdx = 0; + } + } + } + + unsigned LargeReg = SrcReg; + unsigned SmallReg = DstReg; + + // Now determine the register class of the joined register. + if (isExtSubReg) { + if (SubIdx && DstRC && DstRC->isASubClass()) { + // This is a move to a sub-register class. However, the source is a + // sub-register of a larger register class. We don't know what should + // the register class be. FIXME. + Again = true; + return false; + } + if (!DstIsPhys && !SrcIsPhys) + NewRC = SrcRC; + } else if (!SrcIsPhys && !DstIsPhys) { + NewRC = getCommonSubClass(SrcRC, DstRC); + if (!NewRC) { + DEBUG(errs() << "\tDisjoint regclasses: " + << SrcRC->getName() << ", " + << DstRC->getName() << ".\n"); + return false; // Not coalescable. + } + if (DstRC->getSize() > SrcRC->getSize()) + std::swap(LargeReg, SmallReg); + } + + // If we are joining two virtual registers and the resulting register + // class is more restrictive (fewer register, smaller size). Check if it's + // worth doing the merge. + if (!SrcIsPhys && !DstIsPhys && + (isExtSubReg || DstRC->isASubClass()) && + !isWinToJoinCrossClass(LargeReg, SmallReg, + allocatableRCRegs_[NewRC].count())) { + DEBUG(errs() << "\tSrc/Dest are different register classes.\n"); + // Allow the coalescer to try again in case either side gets coalesced to + // a physical register that's compatible with the other side. e.g. + // r1024 = MOV32to32_ r1025 + // But later r1024 is assigned EAX then r1025 may be coalesced with EAX. + Again = true; // May be possible to coalesce later. + return false; + } + } + + // Will it create illegal extract_subreg / insert_subreg? + if (SrcIsPhys && HasIncompatibleSubRegDefUse(CopyMI, DstReg, SrcReg)) + return false; + if (DstIsPhys && HasIncompatibleSubRegDefUse(CopyMI, SrcReg, DstReg)) + return false; + + LiveInterval &SrcInt = li_->getInterval(SrcReg); + LiveInterval &DstInt = li_->getInterval(DstReg); + assert(SrcInt.reg == SrcReg && DstInt.reg == DstReg && + "Register mapping is horribly broken!"); + + DEBUG({ + errs() << "\t\tInspecting "; SrcInt.print(errs(), tri_); + errs() << " and "; DstInt.print(errs(), tri_); + errs() << ": "; + }); + + // Save a copy of the virtual register live interval. We'll manually + // merge this into the "real" physical register live interval this is + // coalesced with. + LiveInterval *SavedLI = 0; + if (RealDstReg) + SavedLI = li_->dupInterval(&SrcInt); + else if (RealSrcReg) + SavedLI = li_->dupInterval(&DstInt); + + // Check if it is necessary to propagate "isDead" property. + if (!isExtSubReg && !isInsSubReg && !isSubRegToReg) { + MachineOperand *mopd = CopyMI->findRegisterDefOperand(DstReg, false); + bool isDead = mopd->isDead(); + + // We need to be careful about coalescing a source physical register with a + // virtual register. Once the coalescing is done, it cannot be broken and + // these are not spillable! If the destination interval uses are far away, + // think twice about coalescing them! + if (!isDead && (SrcIsPhys || DstIsPhys)) { + // If the copy is in a loop, take care not to coalesce aggressively if the + // src is coming in from outside the loop (or the dst is out of the loop). + // If it's not in a loop, then determine whether to join them base purely + // by the length of the interval. + if (PhysJoinTweak) { + if (SrcIsPhys) { + if (!isWinToJoinVRWithSrcPhysReg(CopyMI, CopyMBB, DstInt, SrcInt)) { + mri_->setRegAllocationHint(DstInt.reg, 0, SrcReg); + ++numAborts; + DEBUG(errs() << "\tMay tie down a physical register, abort!\n"); + Again = true; // May be possible to coalesce later. + return false; + } + } else { + if (!isWinToJoinVRWithDstPhysReg(CopyMI, CopyMBB, DstInt, SrcInt)) { + mri_->setRegAllocationHint(SrcInt.reg, 0, DstReg); + ++numAborts; + DEBUG(errs() << "\tMay tie down a physical register, abort!\n"); + Again = true; // May be possible to coalesce later. + return false; + } + } + } else { + // If the virtual register live interval is long but it has low use desity, + // do not join them, instead mark the physical register as its allocation + // preference. + LiveInterval &JoinVInt = SrcIsPhys ? DstInt : SrcInt; + unsigned JoinVReg = SrcIsPhys ? DstReg : SrcReg; + unsigned JoinPReg = SrcIsPhys ? SrcReg : DstReg; + const TargetRegisterClass *RC = mri_->getRegClass(JoinVReg); + unsigned Threshold = allocatableRCRegs_[RC].count() * 2; + unsigned Length = li_->getApproximateInstructionCount(JoinVInt); + float Ratio = 1.0 / Threshold; + if (Length > Threshold && + (((float)std::distance(mri_->use_begin(JoinVReg), + mri_->use_end()) / Length) < Ratio)) { + mri_->setRegAllocationHint(JoinVInt.reg, 0, JoinPReg); + ++numAborts; + DEBUG(errs() << "\tMay tie down a physical register, abort!\n"); + Again = true; // May be possible to coalesce later. + return false; + } + } + } + } + + // Okay, attempt to join these two intervals. On failure, this returns false. + // Otherwise, if one of the intervals being joined is a physreg, this method + // always canonicalizes DstInt to be it. The output "SrcInt" will not have + // been modified, so we can use this information below to update aliases. + bool Swapped = false; + // If SrcInt is implicitly defined, it's safe to coalesce. + bool isEmpty = SrcInt.empty(); + if (isEmpty && !CanCoalesceWithImpDef(CopyMI, DstInt, SrcInt)) { + // Only coalesce an empty interval (defined by implicit_def) with + // another interval which has a valno defined by the CopyMI and the CopyMI + // is a kill of the implicit def. + DEBUG(errs() << "Not profitable!\n"); + return false; + } + + if (!isEmpty && !JoinIntervals(DstInt, SrcInt, Swapped)) { + // Coalescing failed. + + // If definition of source is defined by trivial computation, try + // rematerializing it. + if (!isExtSubReg && !isInsSubReg && !isSubRegToReg && + ReMaterializeTrivialDef(SrcInt, DstReg, DstSubIdx, CopyMI)) + return true; + + // If we can eliminate the copy without merging the live ranges, do so now. + if (!isExtSubReg && !isInsSubReg && !isSubRegToReg && + (AdjustCopiesBackFrom(SrcInt, DstInt, CopyMI) || + RemoveCopyByCommutingDef(SrcInt, DstInt, CopyMI))) { + JoinedCopies.insert(CopyMI); + return true; + } + + // Otherwise, we are unable to join the intervals. + DEBUG(errs() << "Interference!\n"); + Again = true; // May be possible to coalesce later. + return false; + } + + LiveInterval *ResSrcInt = &SrcInt; + LiveInterval *ResDstInt = &DstInt; + if (Swapped) { + std::swap(SrcReg, DstReg); + std::swap(ResSrcInt, ResDstInt); + } + assert(TargetRegisterInfo::isVirtualRegister(SrcReg) && + "LiveInterval::join didn't work right!"); + + // If we're about to merge live ranges into a physical register live interval, + // we have to update any aliased register's live ranges to indicate that they + // have clobbered values for this range. + if (TargetRegisterInfo::isPhysicalRegister(DstReg)) { + // If this is a extract_subreg where dst is a physical register, e.g. + // cl = EXTRACT_SUBREG reg1024, 1 + // then create and update the actual physical register allocated to RHS. + if (RealDstReg || RealSrcReg) { + LiveInterval &RealInt = + li_->getOrCreateInterval(RealDstReg ? RealDstReg : RealSrcReg); + for (LiveInterval::const_vni_iterator I = SavedLI->vni_begin(), + E = SavedLI->vni_end(); I != E; ++I) { + const VNInfo *ValNo = *I; + VNInfo *NewValNo = RealInt.getNextValue(ValNo->def, ValNo->getCopy(), + false, // updated at * + li_->getVNInfoAllocator()); + NewValNo->setFlags(ValNo->getFlags()); // * updated here. + RealInt.addKills(NewValNo, ValNo->kills); + RealInt.MergeValueInAsValue(*SavedLI, ValNo, NewValNo); + } + RealInt.weight += SavedLI->weight; + DstReg = RealDstReg ? RealDstReg : RealSrcReg; + } + + // Update the liveintervals of sub-registers. + for (const unsigned *AS = tri_->getSubRegisters(DstReg); *AS; ++AS) + li_->getOrCreateInterval(*AS).MergeInClobberRanges(*li_, *ResSrcInt, + li_->getVNInfoAllocator()); + } + + // If this is a EXTRACT_SUBREG, make sure the result of coalescing is the + // larger super-register. + if ((isExtSubReg || isInsSubReg || isSubRegToReg) && + !SrcIsPhys && !DstIsPhys) { + if ((isExtSubReg && !Swapped) || + ((isInsSubReg || isSubRegToReg) && Swapped)) { + ResSrcInt->Copy(*ResDstInt, mri_, li_->getVNInfoAllocator()); + std::swap(SrcReg, DstReg); + std::swap(ResSrcInt, ResDstInt); + } + } + + // Coalescing to a virtual register that is of a sub-register class of the + // other. Make sure the resulting register is set to the right register class. + if (CrossRC) + ++numCrossRCs; + + // This may happen even if it's cross-rc coalescing. e.g. + // %reg1026 = SUBREG_TO_REG 0, %reg1037, 4 + // reg1026 -> GR64, reg1037 -> GR32_ABCD. The resulting register will have to + // be allocate a register from GR64_ABCD. + if (NewRC) + mri_->setRegClass(DstReg, NewRC); + + // Remember to delete the copy instruction. + JoinedCopies.insert(CopyMI); + + // Some live range has been lengthened due to colaescing, eliminate the + // unnecessary kills. + RemoveUnnecessaryKills(SrcReg, *ResDstInt); + if (TargetRegisterInfo::isVirtualRegister(DstReg)) + RemoveUnnecessaryKills(DstReg, *ResDstInt); + + UpdateRegDefsUses(SrcReg, DstReg, SubIdx); + + // SrcReg is guarateed to be the register whose live interval that is + // being merged. + li_->removeInterval(SrcReg); + + // Update regalloc hint. + tri_->UpdateRegAllocHint(SrcReg, DstReg, *mf_); + + // Manually deleted the live interval copy. + if (SavedLI) { + SavedLI->clear(); + delete SavedLI; + } + + // If resulting interval has a preference that no longer fits because of subreg + // coalescing, just clear the preference. + unsigned Preference = getRegAllocPreference(ResDstInt->reg, *mf_, mri_, tri_); + if (Preference && (isExtSubReg || isInsSubReg || isSubRegToReg) && + TargetRegisterInfo::isVirtualRegister(ResDstInt->reg)) { + const TargetRegisterClass *RC = mri_->getRegClass(ResDstInt->reg); + if (!RC->contains(Preference)) + mri_->setRegAllocationHint(ResDstInt->reg, 0, 0); + } + + DEBUG({ + errs() << "\n\t\tJoined. Result = "; + ResDstInt->print(errs(), tri_); + errs() << "\n"; + }); + + ++numJoins; + return true; +} + +/// ComputeUltimateVN - Assuming we are going to join two live intervals, +/// compute what the resultant value numbers for each value in the input two +/// ranges will be. This is complicated by copies between the two which can +/// and will commonly cause multiple value numbers to be merged into one. +/// +/// VN is the value number that we're trying to resolve. InstDefiningValue +/// keeps track of the new InstDefiningValue assignment for the result +/// LiveInterval. ThisFromOther/OtherFromThis are sets that keep track of +/// whether a value in this or other is a copy from the opposite set. +/// ThisValNoAssignments/OtherValNoAssignments keep track of value #'s that have +/// already been assigned. +/// +/// ThisFromOther[x] - If x is defined as a copy from the other interval, this +/// contains the value number the copy is from. +/// +static unsigned ComputeUltimateVN(VNInfo *VNI, + SmallVector &NewVNInfo, + DenseMap &ThisFromOther, + DenseMap &OtherFromThis, + SmallVector &ThisValNoAssignments, + SmallVector &OtherValNoAssignments) { + unsigned VN = VNI->id; + + // If the VN has already been computed, just return it. + if (ThisValNoAssignments[VN] >= 0) + return ThisValNoAssignments[VN]; +// assert(ThisValNoAssignments[VN] != -2 && "Cyclic case?"); + + // If this val is not a copy from the other val, then it must be a new value + // number in the destination. + DenseMap::iterator I = ThisFromOther.find(VNI); + if (I == ThisFromOther.end()) { + NewVNInfo.push_back(VNI); + return ThisValNoAssignments[VN] = NewVNInfo.size()-1; + } + VNInfo *OtherValNo = I->second; + + // Otherwise, this *is* a copy from the RHS. If the other side has already + // been computed, return it. + if (OtherValNoAssignments[OtherValNo->id] >= 0) + return ThisValNoAssignments[VN] = OtherValNoAssignments[OtherValNo->id]; + + // Mark this value number as currently being computed, then ask what the + // ultimate value # of the other value is. + ThisValNoAssignments[VN] = -2; + unsigned UltimateVN = + ComputeUltimateVN(OtherValNo, NewVNInfo, OtherFromThis, ThisFromOther, + OtherValNoAssignments, ThisValNoAssignments); + return ThisValNoAssignments[VN] = UltimateVN; +} + +static bool InVector(VNInfo *Val, const SmallVector &V) { + return std::find(V.begin(), V.end(), Val) != V.end(); +} + +static bool isValNoDefMove(const MachineInstr *MI, unsigned DR, unsigned SR, + const TargetInstrInfo *TII, + const TargetRegisterInfo *TRI) { + unsigned SrcReg, DstReg, SrcSubIdx, DstSubIdx; + if (TII->isMoveInstr(*MI, SrcReg, DstReg, SrcSubIdx, DstSubIdx)) + ; + else if (MI->getOpcode() == TargetInstrInfo::EXTRACT_SUBREG) { + DstReg = MI->getOperand(0).getReg(); + SrcReg = MI->getOperand(1).getReg(); + } else if (MI->getOpcode() == TargetInstrInfo::SUBREG_TO_REG || + MI->getOpcode() == TargetInstrInfo::INSERT_SUBREG) { + DstReg = MI->getOperand(0).getReg(); + SrcReg = MI->getOperand(2).getReg(); + } else + return false; + return (SrcReg == SR || TRI->isSuperRegister(SR, SrcReg)) && + (DstReg == DR || TRI->isSuperRegister(DR, DstReg)); +} + +/// RangeIsDefinedByCopyFromReg - Return true if the specified live range of +/// the specified live interval is defined by a copy from the specified +/// register. +bool SimpleRegisterCoalescing::RangeIsDefinedByCopyFromReg(LiveInterval &li, + LiveRange *LR, + unsigned Reg) { + unsigned SrcReg = li_->getVNInfoSourceReg(LR->valno); + if (SrcReg == Reg) + return true; + // FIXME: Do isPHIDef and isDefAccurate both need to be tested? + if ((LR->valno->isPHIDef() || !LR->valno->isDefAccurate()) && + TargetRegisterInfo::isPhysicalRegister(li.reg) && + *tri_->getSuperRegisters(li.reg)) { + // It's a sub-register live interval, we may not have precise information. + // Re-compute it. + MachineInstr *DefMI = li_->getInstructionFromIndex(LR->start); + if (DefMI && isValNoDefMove(DefMI, li.reg, Reg, tii_, tri_)) { + // Cache computed info. + LR->valno->def = LR->start; + LR->valno->setCopy(DefMI); + return true; + } + } + return false; +} + + +/// ValueLiveAt - Return true if the LiveRange pointed to by the given +/// iterator, or any subsequent range with the same value number, +/// is live at the given point. +bool SimpleRegisterCoalescing::ValueLiveAt(LiveInterval::iterator LRItr, + LiveInterval::iterator LREnd, + SlotIndex defPoint) const { + for (const VNInfo *valno = LRItr->valno; + (LRItr != LREnd) && (LRItr->valno == valno); ++LRItr) { + if (LRItr->contains(defPoint)) + return true; + } + + return false; +} + + +/// SimpleJoin - Attempt to joint the specified interval into this one. The +/// caller of this method must guarantee that the RHS only contains a single +/// value number and that the RHS is not defined by a copy from this +/// interval. This returns false if the intervals are not joinable, or it +/// joins them and returns true. +bool SimpleRegisterCoalescing::SimpleJoin(LiveInterval &LHS, LiveInterval &RHS){ + assert(RHS.containsOneValue()); + + // Some number (potentially more than one) value numbers in the current + // interval may be defined as copies from the RHS. Scan the overlapping + // portions of the LHS and RHS, keeping track of this and looking for + // overlapping live ranges that are NOT defined as copies. If these exist, we + // cannot coalesce. + + LiveInterval::iterator LHSIt = LHS.begin(), LHSEnd = LHS.end(); + LiveInterval::iterator RHSIt = RHS.begin(), RHSEnd = RHS.end(); + + if (LHSIt->start < RHSIt->start) { + LHSIt = std::upper_bound(LHSIt, LHSEnd, RHSIt->start); + if (LHSIt != LHS.begin()) --LHSIt; + } else if (RHSIt->start < LHSIt->start) { + RHSIt = std::upper_bound(RHSIt, RHSEnd, LHSIt->start); + if (RHSIt != RHS.begin()) --RHSIt; + } + + SmallVector EliminatedLHSVals; + + while (1) { + // Determine if these live intervals overlap. + bool Overlaps = false; + if (LHSIt->start <= RHSIt->start) + Overlaps = LHSIt->end > RHSIt->start; + else + Overlaps = RHSIt->end > LHSIt->start; + + // If the live intervals overlap, there are two interesting cases: if the + // LHS interval is defined by a copy from the RHS, it's ok and we record + // that the LHS value # is the same as the RHS. If it's not, then we cannot + // coalesce these live ranges and we bail out. + if (Overlaps) { + // If we haven't already recorded that this value # is safe, check it. + if (!InVector(LHSIt->valno, EliminatedLHSVals)) { + // Copy from the RHS? + if (!RangeIsDefinedByCopyFromReg(LHS, LHSIt, RHS.reg)) + return false; // Nope, bail out. + + if (ValueLiveAt(LHSIt, LHS.end(), RHSIt->valno->def)) + // Here is an interesting situation: + // BB1: + // vr1025 = copy vr1024 + // .. + // BB2: + // vr1024 = op + // = vr1025 + // Even though vr1025 is copied from vr1024, it's not safe to + // coalesce them since the live range of vr1025 intersects the + // def of vr1024. This happens because vr1025 is assigned the + // value of the previous iteration of vr1024. + return false; + EliminatedLHSVals.push_back(LHSIt->valno); + } + + // We know this entire LHS live range is okay, so skip it now. + if (++LHSIt == LHSEnd) break; + continue; + } + + if (LHSIt->end < RHSIt->end) { + if (++LHSIt == LHSEnd) break; + } else { + // One interesting case to check here. It's possible that we have + // something like "X3 = Y" which defines a new value number in the LHS, + // and is the last use of this liverange of the RHS. In this case, we + // want to notice this copy (so that it gets coalesced away) even though + // the live ranges don't actually overlap. + if (LHSIt->start == RHSIt->end) { + if (InVector(LHSIt->valno, EliminatedLHSVals)) { + // We already know that this value number is going to be merged in + // if coalescing succeeds. Just skip the liverange. + if (++LHSIt == LHSEnd) break; + } else { + // Otherwise, if this is a copy from the RHS, mark it as being merged + // in. + if (RangeIsDefinedByCopyFromReg(LHS, LHSIt, RHS.reg)) { + if (ValueLiveAt(LHSIt, LHS.end(), RHSIt->valno->def)) + // Here is an interesting situation: + // BB1: + // vr1025 = copy vr1024 + // .. + // BB2: + // vr1024 = op + // = vr1025 + // Even though vr1025 is copied from vr1024, it's not safe to + // coalesced them since live range of vr1025 intersects the + // def of vr1024. This happens because vr1025 is assigned the + // value of the previous iteration of vr1024. + return false; + EliminatedLHSVals.push_back(LHSIt->valno); + + // We know this entire LHS live range is okay, so skip it now. + if (++LHSIt == LHSEnd) break; + } + } + } + + if (++RHSIt == RHSEnd) break; + } + } + + // If we got here, we know that the coalescing will be successful and that + // the value numbers in EliminatedLHSVals will all be merged together. Since + // the most common case is that EliminatedLHSVals has a single number, we + // optimize for it: if there is more than one value, we merge them all into + // the lowest numbered one, then handle the interval as if we were merging + // with one value number. + VNInfo *LHSValNo = NULL; + if (EliminatedLHSVals.size() > 1) { + // Loop through all the equal value numbers merging them into the smallest + // one. + VNInfo *Smallest = EliminatedLHSVals[0]; + for (unsigned i = 1, e = EliminatedLHSVals.size(); i != e; ++i) { + if (EliminatedLHSVals[i]->id < Smallest->id) { + // Merge the current notion of the smallest into the smaller one. + LHS.MergeValueNumberInto(Smallest, EliminatedLHSVals[i]); + Smallest = EliminatedLHSVals[i]; + } else { + // Merge into the smallest. + LHS.MergeValueNumberInto(EliminatedLHSVals[i], Smallest); + } + } + LHSValNo = Smallest; + } else if (EliminatedLHSVals.empty()) { + if (TargetRegisterInfo::isPhysicalRegister(LHS.reg) && + *tri_->getSuperRegisters(LHS.reg)) + // Imprecise sub-register information. Can't handle it. + return false; + llvm_unreachable("No copies from the RHS?"); + } else { + LHSValNo = EliminatedLHSVals[0]; + } + + // Okay, now that there is a single LHS value number that we're merging the + // RHS into, update the value number info for the LHS to indicate that the + // value number is defined where the RHS value number was. + const VNInfo *VNI = RHS.getValNumInfo(0); + LHSValNo->def = VNI->def; + LHSValNo->setCopy(VNI->getCopy()); + + // Okay, the final step is to loop over the RHS live intervals, adding them to + // the LHS. + if (VNI->hasPHIKill()) + LHSValNo->setHasPHIKill(true); + LHS.addKills(LHSValNo, VNI->kills); + LHS.MergeRangesInAsValue(RHS, LHSValNo); + + LHS.ComputeJoinedWeight(RHS); + + // Update regalloc hint if both are virtual registers. + if (TargetRegisterInfo::isVirtualRegister(LHS.reg) && + TargetRegisterInfo::isVirtualRegister(RHS.reg)) { + std::pair RHSPref = mri_->getRegAllocationHint(RHS.reg); + std::pair LHSPref = mri_->getRegAllocationHint(LHS.reg); + if (RHSPref != LHSPref) + mri_->setRegAllocationHint(LHS.reg, RHSPref.first, RHSPref.second); + } + + // Update the liveintervals of sub-registers. + if (TargetRegisterInfo::isPhysicalRegister(LHS.reg)) + for (const unsigned *AS = tri_->getSubRegisters(LHS.reg); *AS; ++AS) + li_->getOrCreateInterval(*AS).MergeInClobberRanges(*li_, LHS, + li_->getVNInfoAllocator()); + + return true; +} + +/// JoinIntervals - Attempt to join these two intervals. On failure, this +/// returns false. Otherwise, if one of the intervals being joined is a +/// physreg, this method always canonicalizes LHS to be it. The output +/// "RHS" will not have been modified, so we can use this information +/// below to update aliases. +bool +SimpleRegisterCoalescing::JoinIntervals(LiveInterval &LHS, LiveInterval &RHS, + bool &Swapped) { + // Compute the final value assignment, assuming that the live ranges can be + // coalesced. + SmallVector LHSValNoAssignments; + SmallVector RHSValNoAssignments; + DenseMap LHSValsDefinedFromRHS; + DenseMap RHSValsDefinedFromLHS; + SmallVector NewVNInfo; + + // If a live interval is a physical register, conservatively check if any + // of its sub-registers is overlapping the live interval of the virtual + // register. If so, do not coalesce. + if (TargetRegisterInfo::isPhysicalRegister(LHS.reg) && + *tri_->getSubRegisters(LHS.reg)) { + // If it's coalescing a virtual register to a physical register, estimate + // its live interval length. This is the *cost* of scanning an entire live + // interval. If the cost is low, we'll do an exhaustive check instead. + + // If this is something like this: + // BB1: + // v1024 = op + // ... + // BB2: + // ... + // RAX = v1024 + // + // That is, the live interval of v1024 crosses a bb. Then we can't rely on + // less conservative check. It's possible a sub-register is defined before + // v1024 (or live in) and live out of BB1. + if (RHS.containsOneValue() && + li_->intervalIsInOneMBB(RHS) && + li_->getApproximateInstructionCount(RHS) <= 10) { + // Perform a more exhaustive check for some common cases. + if (li_->conflictsWithPhysRegRef(RHS, LHS.reg, true, JoinedCopies)) + return false; + } else { + for (const unsigned* SR = tri_->getSubRegisters(LHS.reg); *SR; ++SR) + if (li_->hasInterval(*SR) && RHS.overlaps(li_->getInterval(*SR))) { + DEBUG({ + errs() << "Interfere with sub-register "; + li_->getInterval(*SR).print(errs(), tri_); + }); + return false; + } + } + } else if (TargetRegisterInfo::isPhysicalRegister(RHS.reg) && + *tri_->getSubRegisters(RHS.reg)) { + if (LHS.containsOneValue() && + li_->getApproximateInstructionCount(LHS) <= 10) { + // Perform a more exhaustive check for some common cases. + if (li_->conflictsWithPhysRegRef(LHS, RHS.reg, false, JoinedCopies)) + return false; + } else { + for (const unsigned* SR = tri_->getSubRegisters(RHS.reg); *SR; ++SR) + if (li_->hasInterval(*SR) && LHS.overlaps(li_->getInterval(*SR))) { + DEBUG({ + errs() << "Interfere with sub-register "; + li_->getInterval(*SR).print(errs(), tri_); + }); + return false; + } + } + } + + // Compute ultimate value numbers for the LHS and RHS values. + if (RHS.containsOneValue()) { + // Copies from a liveinterval with a single value are simple to handle and + // very common, handle the special case here. This is important, because + // often RHS is small and LHS is large (e.g. a physreg). + + // Find out if the RHS is defined as a copy from some value in the LHS. + int RHSVal0DefinedFromLHS = -1; + int RHSValID = -1; + VNInfo *RHSValNoInfo = NULL; + VNInfo *RHSValNoInfo0 = RHS.getValNumInfo(0); + unsigned RHSSrcReg = li_->getVNInfoSourceReg(RHSValNoInfo0); + if (RHSSrcReg == 0 || RHSSrcReg != LHS.reg) { + // If RHS is not defined as a copy from the LHS, we can use simpler and + // faster checks to see if the live ranges are coalescable. This joiner + // can't swap the LHS/RHS intervals though. + if (!TargetRegisterInfo::isPhysicalRegister(RHS.reg)) { + return SimpleJoin(LHS, RHS); + } else { + RHSValNoInfo = RHSValNoInfo0; + } + } else { + // It was defined as a copy from the LHS, find out what value # it is. + RHSValNoInfo = + LHS.getLiveRangeContaining(RHSValNoInfo0->def.getPrevSlot())->valno; + RHSValID = RHSValNoInfo->id; + RHSVal0DefinedFromLHS = RHSValID; + } + + LHSValNoAssignments.resize(LHS.getNumValNums(), -1); + RHSValNoAssignments.resize(RHS.getNumValNums(), -1); + NewVNInfo.resize(LHS.getNumValNums(), NULL); + + // Okay, *all* of the values in LHS that are defined as a copy from RHS + // should now get updated. + for (LiveInterval::vni_iterator i = LHS.vni_begin(), e = LHS.vni_end(); + i != e; ++i) { + VNInfo *VNI = *i; + unsigned VN = VNI->id; + if (unsigned LHSSrcReg = li_->getVNInfoSourceReg(VNI)) { + if (LHSSrcReg != RHS.reg) { + // If this is not a copy from the RHS, its value number will be + // unmodified by the coalescing. + NewVNInfo[VN] = VNI; + LHSValNoAssignments[VN] = VN; + } else if (RHSValID == -1) { + // Otherwise, it is a copy from the RHS, and we don't already have a + // value# for it. Keep the current value number, but remember it. + LHSValNoAssignments[VN] = RHSValID = VN; + NewVNInfo[VN] = RHSValNoInfo; + LHSValsDefinedFromRHS[VNI] = RHSValNoInfo0; + } else { + // Otherwise, use the specified value #. + LHSValNoAssignments[VN] = RHSValID; + if (VN == (unsigned)RHSValID) { // Else this val# is dead. + NewVNInfo[VN] = RHSValNoInfo; + LHSValsDefinedFromRHS[VNI] = RHSValNoInfo0; + } + } + } else { + NewVNInfo[VN] = VNI; + LHSValNoAssignments[VN] = VN; + } + } + + assert(RHSValID != -1 && "Didn't find value #?"); + RHSValNoAssignments[0] = RHSValID; + if (RHSVal0DefinedFromLHS != -1) { + // This path doesn't go through ComputeUltimateVN so just set + // it to anything. + RHSValsDefinedFromLHS[RHSValNoInfo0] = (VNInfo*)1; + } + } else { + // Loop over the value numbers of the LHS, seeing if any are defined from + // the RHS. + for (LiveInterval::vni_iterator i = LHS.vni_begin(), e = LHS.vni_end(); + i != e; ++i) { + VNInfo *VNI = *i; + if (VNI->isUnused() || VNI->getCopy() == 0) // Src not defined by a copy? + continue; + + // DstReg is known to be a register in the LHS interval. If the src is + // from the RHS interval, we can use its value #. + if (li_->getVNInfoSourceReg(VNI) != RHS.reg) + continue; + + // Figure out the value # from the RHS. + LHSValsDefinedFromRHS[VNI]= + RHS.getLiveRangeContaining(VNI->def.getPrevSlot())->valno; + } + + // Loop over the value numbers of the RHS, seeing if any are defined from + // the LHS. + for (LiveInterval::vni_iterator i = RHS.vni_begin(), e = RHS.vni_end(); + i != e; ++i) { + VNInfo *VNI = *i; + if (VNI->isUnused() || VNI->getCopy() == 0) // Src not defined by a copy? + continue; + + // DstReg is known to be a register in the RHS interval. If the src is + // from the LHS interval, we can use its value #. + if (li_->getVNInfoSourceReg(VNI) != LHS.reg) + continue; + + // Figure out the value # from the LHS. + RHSValsDefinedFromLHS[VNI]= + LHS.getLiveRangeContaining(VNI->def.getPrevSlot())->valno; + } + + LHSValNoAssignments.resize(LHS.getNumValNums(), -1); + RHSValNoAssignments.resize(RHS.getNumValNums(), -1); + NewVNInfo.reserve(LHS.getNumValNums() + RHS.getNumValNums()); + + for (LiveInterval::vni_iterator i = LHS.vni_begin(), e = LHS.vni_end(); + i != e; ++i) { + VNInfo *VNI = *i; + unsigned VN = VNI->id; + if (LHSValNoAssignments[VN] >= 0 || VNI->isUnused()) + continue; + ComputeUltimateVN(VNI, NewVNInfo, + LHSValsDefinedFromRHS, RHSValsDefinedFromLHS, + LHSValNoAssignments, RHSValNoAssignments); + } + for (LiveInterval::vni_iterator i = RHS.vni_begin(), e = RHS.vni_end(); + i != e; ++i) { + VNInfo *VNI = *i; + unsigned VN = VNI->id; + if (RHSValNoAssignments[VN] >= 0 || VNI->isUnused()) + continue; + // If this value number isn't a copy from the LHS, it's a new number. + if (RHSValsDefinedFromLHS.find(VNI) == RHSValsDefinedFromLHS.end()) { + NewVNInfo.push_back(VNI); + RHSValNoAssignments[VN] = NewVNInfo.size()-1; + continue; + } + + ComputeUltimateVN(VNI, NewVNInfo, + RHSValsDefinedFromLHS, LHSValsDefinedFromRHS, + RHSValNoAssignments, LHSValNoAssignments); + } + } + + // Armed with the mappings of LHS/RHS values to ultimate values, walk the + // interval lists to see if these intervals are coalescable. + LiveInterval::const_iterator I = LHS.begin(); + LiveInterval::const_iterator IE = LHS.end(); + LiveInterval::const_iterator J = RHS.begin(); + LiveInterval::const_iterator JE = RHS.end(); + + // Skip ahead until the first place of potential sharing. + if (I->start < J->start) { + I = std::upper_bound(I, IE, J->start); + if (I != LHS.begin()) --I; + } else if (J->start < I->start) { + J = std::upper_bound(J, JE, I->start); + if (J != RHS.begin()) --J; + } + + while (1) { + // Determine if these two live ranges overlap. + bool Overlaps; + if (I->start < J->start) { + Overlaps = I->end > J->start; + } else { + Overlaps = J->end > I->start; + } + + // If so, check value # info to determine if they are really different. + if (Overlaps) { + // If the live range overlap will map to the same value number in the + // result liverange, we can still coalesce them. If not, we can't. + if (LHSValNoAssignments[I->valno->id] != + RHSValNoAssignments[J->valno->id]) + return false; + } + + if (I->end < J->end) { + ++I; + if (I == IE) break; + } else { + ++J; + if (J == JE) break; + } + } + + // Update kill info. Some live ranges are extended due to copy coalescing. + for (DenseMap::iterator I = LHSValsDefinedFromRHS.begin(), + E = LHSValsDefinedFromRHS.end(); I != E; ++I) { + VNInfo *VNI = I->first; + unsigned LHSValID = LHSValNoAssignments[VNI->id]; + NewVNInfo[LHSValID]->removeKill(VNI->def); + if (VNI->hasPHIKill()) + NewVNInfo[LHSValID]->setHasPHIKill(true); + RHS.addKills(NewVNInfo[LHSValID], VNI->kills); + } + + // Update kill info. Some live ranges are extended due to copy coalescing. + for (DenseMap::iterator I = RHSValsDefinedFromLHS.begin(), + E = RHSValsDefinedFromLHS.end(); I != E; ++I) { + VNInfo *VNI = I->first; + unsigned RHSValID = RHSValNoAssignments[VNI->id]; + NewVNInfo[RHSValID]->removeKill(VNI->def); + if (VNI->hasPHIKill()) + NewVNInfo[RHSValID]->setHasPHIKill(true); + LHS.addKills(NewVNInfo[RHSValID], VNI->kills); + } + + // If we get here, we know that we can coalesce the live ranges. Ask the + // intervals to coalesce themselves now. + if ((RHS.ranges.size() > LHS.ranges.size() && + TargetRegisterInfo::isVirtualRegister(LHS.reg)) || + TargetRegisterInfo::isPhysicalRegister(RHS.reg)) { + RHS.join(LHS, &RHSValNoAssignments[0], &LHSValNoAssignments[0], NewVNInfo, + mri_); + Swapped = true; + } else { + LHS.join(RHS, &LHSValNoAssignments[0], &RHSValNoAssignments[0], NewVNInfo, + mri_); + Swapped = false; + } + return true; +} + +namespace { + // DepthMBBCompare - Comparison predicate that sort first based on the loop + // depth of the basic block (the unsigned), and then on the MBB number. + struct DepthMBBCompare { + typedef std::pair DepthMBBPair; + bool operator()(const DepthMBBPair &LHS, const DepthMBBPair &RHS) const { + if (LHS.first > RHS.first) return true; // Deeper loops first + return LHS.first == RHS.first && + LHS.second->getNumber() < RHS.second->getNumber(); + } + }; +} + +void SimpleRegisterCoalescing::CopyCoalesceInMBB(MachineBasicBlock *MBB, + std::vector &TryAgain) { + DEBUG(errs() << MBB->getName() << ":\n"); + + std::vector VirtCopies; + std::vector PhysCopies; + std::vector ImpDefCopies; + for (MachineBasicBlock::iterator MII = MBB->begin(), E = MBB->end(); + MII != E;) { + MachineInstr *Inst = MII++; + + // If this isn't a copy nor a extract_subreg, we can't join intervals. + unsigned SrcReg, DstReg, SrcSubIdx, DstSubIdx; + if (Inst->getOpcode() == TargetInstrInfo::EXTRACT_SUBREG) { + DstReg = Inst->getOperand(0).getReg(); + SrcReg = Inst->getOperand(1).getReg(); + } else if (Inst->getOpcode() == TargetInstrInfo::INSERT_SUBREG || + Inst->getOpcode() == TargetInstrInfo::SUBREG_TO_REG) { + DstReg = Inst->getOperand(0).getReg(); + SrcReg = Inst->getOperand(2).getReg(); + } else if (!tii_->isMoveInstr(*Inst, SrcReg, DstReg, SrcSubIdx, DstSubIdx)) + continue; + + bool SrcIsPhys = TargetRegisterInfo::isPhysicalRegister(SrcReg); + bool DstIsPhys = TargetRegisterInfo::isPhysicalRegister(DstReg); + if (li_->hasInterval(SrcReg) && li_->getInterval(SrcReg).empty()) + ImpDefCopies.push_back(CopyRec(Inst, 0)); + else if (SrcIsPhys || DstIsPhys) + PhysCopies.push_back(CopyRec(Inst, 0)); + else + VirtCopies.push_back(CopyRec(Inst, 0)); + } + + // Try coalescing implicit copies first, followed by copies to / from + // physical registers, then finally copies from virtual registers to + // virtual registers. + for (unsigned i = 0, e = ImpDefCopies.size(); i != e; ++i) { + CopyRec &TheCopy = ImpDefCopies[i]; + bool Again = false; + if (!JoinCopy(TheCopy, Again)) + if (Again) + TryAgain.push_back(TheCopy); + } + for (unsigned i = 0, e = PhysCopies.size(); i != e; ++i) { + CopyRec &TheCopy = PhysCopies[i]; + bool Again = false; + if (!JoinCopy(TheCopy, Again)) + if (Again) + TryAgain.push_back(TheCopy); + } + for (unsigned i = 0, e = VirtCopies.size(); i != e; ++i) { + CopyRec &TheCopy = VirtCopies[i]; + bool Again = false; + if (!JoinCopy(TheCopy, Again)) + if (Again) + TryAgain.push_back(TheCopy); + } +} + +void SimpleRegisterCoalescing::joinIntervals() { + DEBUG(errs() << "********** JOINING INTERVALS ***********\n"); + + std::vector TryAgainList; + if (loopInfo->empty()) { + // If there are no loops in the function, join intervals in function order. + for (MachineFunction::iterator I = mf_->begin(), E = mf_->end(); + I != E; ++I) + CopyCoalesceInMBB(I, TryAgainList); + } else { + // Otherwise, join intervals in inner loops before other intervals. + // Unfortunately we can't just iterate over loop hierarchy here because + // there may be more MBB's than BB's. Collect MBB's for sorting. + + // Join intervals in the function prolog first. We want to join physical + // registers with virtual registers before the intervals got too long. + std::vector > MBBs; + for (MachineFunction::iterator I = mf_->begin(), E = mf_->end();I != E;++I){ + MachineBasicBlock *MBB = I; + MBBs.push_back(std::make_pair(loopInfo->getLoopDepth(MBB), I)); + } + + // Sort by loop depth. + std::sort(MBBs.begin(), MBBs.end(), DepthMBBCompare()); + + // Finally, join intervals in loop nest order. + for (unsigned i = 0, e = MBBs.size(); i != e; ++i) + CopyCoalesceInMBB(MBBs[i].second, TryAgainList); + } + + // Joining intervals can allow other intervals to be joined. Iteratively join + // until we make no progress. + bool ProgressMade = true; + while (ProgressMade) { + ProgressMade = false; + + for (unsigned i = 0, e = TryAgainList.size(); i != e; ++i) { + CopyRec &TheCopy = TryAgainList[i]; + if (!TheCopy.MI) + continue; + + bool Again = false; + bool Success = JoinCopy(TheCopy, Again); + if (Success || !Again) { + TheCopy.MI = 0; // Mark this one as done. + ProgressMade = true; + } + } + } +} + +/// Return true if the two specified registers belong to different register +/// classes. The registers may be either phys or virt regs. +bool +SimpleRegisterCoalescing::differingRegisterClasses(unsigned RegA, + unsigned RegB) const { + // Get the register classes for the first reg. + if (TargetRegisterInfo::isPhysicalRegister(RegA)) { + assert(TargetRegisterInfo::isVirtualRegister(RegB) && + "Shouldn't consider two physregs!"); + return !mri_->getRegClass(RegB)->contains(RegA); + } + + // Compare against the regclass for the second reg. + const TargetRegisterClass *RegClassA = mri_->getRegClass(RegA); + if (TargetRegisterInfo::isVirtualRegister(RegB)) { + const TargetRegisterClass *RegClassB = mri_->getRegClass(RegB); + return RegClassA != RegClassB; + } + return !RegClassA->contains(RegB); +} + +/// lastRegisterUse - Returns the last use of the specific register between +/// cycles Start and End or NULL if there are no uses. +MachineOperand * +SimpleRegisterCoalescing::lastRegisterUse(SlotIndex Start, + SlotIndex End, + unsigned Reg, + SlotIndex &UseIdx) const{ + UseIdx = SlotIndex(); + if (TargetRegisterInfo::isVirtualRegister(Reg)) { + MachineOperand *LastUse = NULL; + for (MachineRegisterInfo::use_iterator I = mri_->use_begin(Reg), + E = mri_->use_end(); I != E; ++I) { + MachineOperand &Use = I.getOperand(); + MachineInstr *UseMI = Use.getParent(); + unsigned SrcReg, DstReg, SrcSubIdx, DstSubIdx; + if (tii_->isMoveInstr(*UseMI, SrcReg, DstReg, SrcSubIdx, DstSubIdx) && + SrcReg == DstReg) + // Ignore identity copies. + continue; + SlotIndex Idx = li_->getInstructionIndex(UseMI); + // FIXME: Should this be Idx != UseIdx? SlotIndex() will return something + // that compares higher than any other interval. + if (Idx >= Start && Idx < End && Idx >= UseIdx) { + LastUse = &Use; + UseIdx = Idx.getUseIndex(); + } + } + return LastUse; + } + + SlotIndex s = Start; + SlotIndex e = End.getPrevSlot().getBaseIndex(); + while (e >= s) { + // Skip deleted instructions + MachineInstr *MI = li_->getInstructionFromIndex(e); + while (e != SlotIndex() && e.getPrevIndex() >= s && !MI) { + e = e.getPrevIndex(); + MI = li_->getInstructionFromIndex(e); + } + if (e < s || MI == NULL) + return NULL; + + // Ignore identity copies. + unsigned SrcReg, DstReg, SrcSubIdx, DstSubIdx; + if (!(tii_->isMoveInstr(*MI, SrcReg, DstReg, SrcSubIdx, DstSubIdx) && + SrcReg == DstReg)) + for (unsigned i = 0, NumOps = MI->getNumOperands(); i != NumOps; ++i) { + MachineOperand &Use = MI->getOperand(i); + if (Use.isReg() && Use.isUse() && Use.getReg() && + tri_->regsOverlap(Use.getReg(), Reg)) { + UseIdx = e.getUseIndex(); + return &Use; + } + } + + e = e.getPrevIndex(); + } + + return NULL; +} + + +void SimpleRegisterCoalescing::printRegName(unsigned reg) const { + if (TargetRegisterInfo::isPhysicalRegister(reg)) + errs() << tri_->getName(reg); + else + errs() << "%reg" << reg; +} + +void SimpleRegisterCoalescing::releaseMemory() { + JoinedCopies.clear(); + ReMatCopies.clear(); + ReMatDefs.clear(); +} + +/// Returns true if the given live interval is zero length. +static bool isZeroLengthInterval(LiveInterval *li, LiveIntervals *li_) { + for (LiveInterval::Ranges::const_iterator + i = li->ranges.begin(), e = li->ranges.end(); i != e; ++i) + if (i->end.getPrevIndex() > i->start) + return false; + return true; +} + + +void SimpleRegisterCoalescing::CalculateSpillWeights() { + SmallSet Processed; + for (MachineFunction::iterator mbbi = mf_->begin(), mbbe = mf_->end(); + mbbi != mbbe; ++mbbi) { + MachineBasicBlock* MBB = mbbi; + SlotIndex MBBEnd = li_->getMBBEndIdx(MBB); + MachineLoop* loop = loopInfo->getLoopFor(MBB); + unsigned loopDepth = loop ? loop->getLoopDepth() : 0; + bool isExiting = loop ? loop->isLoopExiting(MBB) : false; + + for (MachineBasicBlock::const_iterator mii = MBB->begin(), mie = MBB->end(); + mii != mie; ++mii) { + const MachineInstr *MI = mii; + if (tii_->isIdentityCopy(*MI)) + continue; + + if (MI->getOpcode() == TargetInstrInfo::IMPLICIT_DEF) + continue; + + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + const MachineOperand &mopi = MI->getOperand(i); + if (!mopi.isReg() || mopi.getReg() == 0) + continue; + unsigned Reg = mopi.getReg(); + if (!TargetRegisterInfo::isVirtualRegister(mopi.getReg())) + continue; + // Multiple uses of reg by the same instruction. It should not + // contribute to spill weight again. + if (!Processed.insert(Reg)) + continue; + + bool HasDef = mopi.isDef(); + bool HasUse = !HasDef; + for (unsigned j = i+1; j != e; ++j) { + const MachineOperand &mopj = MI->getOperand(j); + if (!mopj.isReg() || mopj.getReg() != Reg) + continue; + HasDef |= mopj.isDef(); + HasUse |= mopj.isUse(); + if (HasDef && HasUse) + break; + } + + LiveInterval &RegInt = li_->getInterval(Reg); + float Weight = li_->getSpillWeight(HasDef, HasUse, loopDepth); + if (HasDef && isExiting) { + // Looks like this is a loop count variable update. + SlotIndex DefIdx = li_->getInstructionIndex(MI).getDefIndex(); + const LiveRange *DLR = + li_->getInterval(Reg).getLiveRangeContaining(DefIdx); + if (DLR->end > MBBEnd) + Weight *= 3.0F; + } + RegInt.weight += Weight; + } + Processed.clear(); + } + } + + for (LiveIntervals::iterator I = li_->begin(), E = li_->end(); I != E; ++I) { + LiveInterval &LI = *I->second; + if (TargetRegisterInfo::isVirtualRegister(LI.reg)) { + // If the live interval length is essentially zero, i.e. in every live + // range the use follows def immediately, it doesn't make sense to spill + // it and hope it will be easier to allocate for this li. + if (isZeroLengthInterval(&LI, li_)) { + LI.weight = HUGE_VALF; + continue; + } + + bool isLoad = false; + SmallVector SpillIs; + if (li_->isReMaterializable(LI, SpillIs, isLoad)) { + // If all of the definitions of the interval are re-materializable, + // it is a preferred candidate for spilling. If non of the defs are + // loads, then it's potentially very cheap to re-materialize. + // FIXME: this gets much more complicated once we support non-trivial + // re-materialization. + if (isLoad) + LI.weight *= 0.9F; + else + LI.weight *= 0.5F; + } + + // Slightly prefer live interval that has been assigned a preferred reg. + std::pair Hint = mri_->getRegAllocationHint(LI.reg); + if (Hint.first || Hint.second) + LI.weight *= 1.01F; + + // Divide the weight of the interval by its size. This encourages + // spilling of intervals that are large and have few uses, and + // discourages spilling of small intervals with many uses. + LI.weight /= li_->getApproximateInstructionCount(LI) * InstrSlots::NUM; + } + } +} + + +bool SimpleRegisterCoalescing::runOnMachineFunction(MachineFunction &fn) { + mf_ = &fn; + mri_ = &fn.getRegInfo(); + tm_ = &fn.getTarget(); + tri_ = tm_->getRegisterInfo(); + tii_ = tm_->getInstrInfo(); + li_ = &getAnalysis(); + AA = &getAnalysis(); + loopInfo = &getAnalysis(); + + DEBUG(errs() << "********** SIMPLE REGISTER COALESCING **********\n" + << "********** Function: " + << ((Value*)mf_->getFunction())->getName() << '\n'); + + allocatableRegs_ = tri_->getAllocatableSet(fn); + for (TargetRegisterInfo::regclass_iterator I = tri_->regclass_begin(), + E = tri_->regclass_end(); I != E; ++I) + allocatableRCRegs_.insert(std::make_pair(*I, + tri_->getAllocatableSet(fn, *I))); + + // Join (coalesce) intervals if requested. + if (EnableJoining) { + joinIntervals(); + DEBUG({ + errs() << "********** INTERVALS POST JOINING **********\n"; + for (LiveIntervals::iterator I = li_->begin(), E = li_->end(); I != E; ++I){ + I->second->print(errs(), tri_); + errs() << "\n"; + } + }); + } + + // Perform a final pass over the instructions and compute spill weights + // and remove identity moves. + SmallVector DeadDefs; + for (MachineFunction::iterator mbbi = mf_->begin(), mbbe = mf_->end(); + mbbi != mbbe; ++mbbi) { + MachineBasicBlock* mbb = mbbi; + for (MachineBasicBlock::iterator mii = mbb->begin(), mie = mbb->end(); + mii != mie; ) { + MachineInstr *MI = mii; + unsigned SrcReg, DstReg, SrcSubIdx, DstSubIdx; + if (JoinedCopies.count(MI)) { + // Delete all coalesced copies. + bool DoDelete = true; + if (!tii_->isMoveInstr(*MI, SrcReg, DstReg, SrcSubIdx, DstSubIdx)) { + assert((MI->getOpcode() == TargetInstrInfo::EXTRACT_SUBREG || + MI->getOpcode() == TargetInstrInfo::INSERT_SUBREG || + MI->getOpcode() == TargetInstrInfo::SUBREG_TO_REG) && + "Unrecognized copy instruction"); + DstReg = MI->getOperand(0).getReg(); + if (TargetRegisterInfo::isPhysicalRegister(DstReg)) + // Do not delete extract_subreg, insert_subreg of physical + // registers unless the definition is dead. e.g. + // %DO = INSERT_SUBREG %D0, %S0, 1 + // or else the scavenger may complain. LowerSubregs will + // delete them later. + DoDelete = false; + } + if (MI->registerDefIsDead(DstReg)) { + LiveInterval &li = li_->getInterval(DstReg); + if (!ShortenDeadCopySrcLiveRange(li, MI)) + ShortenDeadCopyLiveRange(li, MI); + DoDelete = true; + } + if (!DoDelete) + mii = next(mii); + else { + li_->RemoveMachineInstrFromMaps(MI); + mii = mbbi->erase(mii); + ++numPeep; + } + continue; + } + + // Now check if this is a remat'ed def instruction which is now dead. + if (ReMatDefs.count(MI)) { + bool isDead = true; + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + const MachineOperand &MO = MI->getOperand(i); + if (!MO.isReg()) + continue; + unsigned Reg = MO.getReg(); + if (!Reg) + continue; + if (TargetRegisterInfo::isVirtualRegister(Reg)) + DeadDefs.push_back(Reg); + if (MO.isDead()) + continue; + if (TargetRegisterInfo::isPhysicalRegister(Reg) || + !mri_->use_empty(Reg)) { + isDead = false; + break; + } + } + if (isDead) { + while (!DeadDefs.empty()) { + unsigned DeadDef = DeadDefs.back(); + DeadDefs.pop_back(); + RemoveDeadDef(li_->getInterval(DeadDef), MI); + } + li_->RemoveMachineInstrFromMaps(mii); + mii = mbbi->erase(mii); + continue; + } else + DeadDefs.clear(); + } + + // If the move will be an identity move delete it + bool isMove= tii_->isMoveInstr(*MI, SrcReg, DstReg, SrcSubIdx, DstSubIdx); + if (isMove && SrcReg == DstReg) { + if (li_->hasInterval(SrcReg)) { + LiveInterval &RegInt = li_->getInterval(SrcReg); + // If def of this move instruction is dead, remove its live range + // from the dstination register's live interval. + if (MI->registerDefIsDead(DstReg)) { + if (!ShortenDeadCopySrcLiveRange(RegInt, MI)) + ShortenDeadCopyLiveRange(RegInt, MI); + } + } + li_->RemoveMachineInstrFromMaps(MI); + mii = mbbi->erase(mii); + ++numPeep; + } else { + ++mii; + } + } + } + + CalculateSpillWeights(); + + DEBUG(dump()); + return true; +} + +/// print - Implement the dump method. +void SimpleRegisterCoalescing::print(raw_ostream &O, const Module* m) const { + li_->print(O, m); +} + +RegisterCoalescer* llvm::createSimpleRegisterCoalescer() { + return new SimpleRegisterCoalescing(); +} + +// Make sure that anything that uses RegisterCoalescer pulls in this file... +DEFINING_FILE_FOR(SimpleRegisterCoalescing) diff --git a/libclamav/c++/llvm/lib/CodeGen/SimpleRegisterCoalescing.h b/libclamav/c++/llvm/lib/CodeGen/SimpleRegisterCoalescing.h new file mode 100644 index 000000000..78f8a9a56 --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/SimpleRegisterCoalescing.h @@ -0,0 +1,256 @@ +//===-- SimpleRegisterCoalescing.h - Register Coalescing --------*- 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 a simple register copy coalescing phase. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_SIMPLE_REGISTER_COALESCING_H +#define LLVM_CODEGEN_SIMPLE_REGISTER_COALESCING_H + +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/LiveIntervalAnalysis.h" +#include "llvm/CodeGen/RegisterCoalescer.h" +#include "llvm/ADT/BitVector.h" + +namespace llvm { + class SimpleRegisterCoalescing; + class LiveVariables; + class TargetRegisterInfo; + class TargetInstrInfo; + class VirtRegMap; + class MachineLoopInfo; + + /// CopyRec - Representation for copy instructions in coalescer queue. + /// + struct CopyRec { + MachineInstr *MI; + unsigned LoopDepth; + CopyRec(MachineInstr *mi, unsigned depth) + : MI(mi), LoopDepth(depth) {}; + }; + + class SimpleRegisterCoalescing : public MachineFunctionPass, + public RegisterCoalescer { + MachineFunction* mf_; + MachineRegisterInfo* mri_; + const TargetMachine* tm_; + const TargetRegisterInfo* tri_; + const TargetInstrInfo* tii_; + LiveIntervals *li_; + const MachineLoopInfo* loopInfo; + AliasAnalysis *AA; + + BitVector allocatableRegs_; + DenseMap allocatableRCRegs_; + + /// JoinedCopies - Keep track of copies eliminated due to coalescing. + /// + SmallPtrSet JoinedCopies; + + /// ReMatCopies - Keep track of copies eliminated due to remat. + /// + SmallPtrSet ReMatCopies; + + /// ReMatDefs - Keep track of definition instructions which have + /// been remat'ed. + SmallPtrSet ReMatDefs; + + public: + static char ID; // Pass identifcation, replacement for typeid + SimpleRegisterCoalescing() : MachineFunctionPass(&ID) {} + + struct InstrSlots { + enum { + LOAD = 0, + USE = 1, + DEF = 2, + STORE = 3, + NUM = 4 + }; + }; + + virtual void getAnalysisUsage(AnalysisUsage &AU) const; + virtual void releaseMemory(); + + /// runOnMachineFunction - pass entry point + virtual bool runOnMachineFunction(MachineFunction&); + + bool coalesceFunction(MachineFunction &mf, RegallocQuery &) { + // This runs as an independent pass, so don't do anything. + return false; + }; + + /// print - Implement the dump method. + virtual void print(raw_ostream &O, const Module* = 0) const; + + private: + /// joinIntervals - join compatible live intervals + void joinIntervals(); + + /// CopyCoalesceInMBB - Coalesce copies in the specified MBB, putting + /// copies that cannot yet be coalesced into the "TryAgain" list. + void CopyCoalesceInMBB(MachineBasicBlock *MBB, + std::vector &TryAgain); + + /// JoinCopy - Attempt to join intervals corresponding to SrcReg/DstReg, + /// which are the src/dst of the copy instruction CopyMI. This returns true + /// if the copy was successfully coalesced away. If it is not currently + /// possible to coalesce this interval, but it may be possible if other + /// things get coalesced, then it returns true by reference in 'Again'. + bool JoinCopy(CopyRec &TheCopy, bool &Again); + + /// JoinIntervals - Attempt to join these two intervals. On failure, this + /// returns false. Otherwise, if one of the intervals being joined is a + /// physreg, this method always canonicalizes DestInt to be it. The output + /// "SrcInt" will not have been modified, so we can use this information + /// below to update aliases. + bool JoinIntervals(LiveInterval &LHS, LiveInterval &RHS, bool &Swapped); + + /// SimpleJoin - Attempt to join the specified interval into this one. The + /// caller of this method must guarantee that the RHS only contains a single + /// value number and that the RHS is not defined by a copy from this + /// interval. This returns false if the intervals are not joinable, or it + /// joins them and returns true. + bool SimpleJoin(LiveInterval &LHS, LiveInterval &RHS); + + /// Return true if the two specified registers belong to different register + /// classes. The registers may be either phys or virt regs. + bool differingRegisterClasses(unsigned RegA, unsigned RegB) const; + + /// AdjustCopiesBackFrom - We found a non-trivially-coalescable copy. If + /// the source value number is defined by a copy from the destination reg + /// see if we can merge these two destination reg valno# into a single + /// value number, eliminating a copy. + bool AdjustCopiesBackFrom(LiveInterval &IntA, LiveInterval &IntB, + MachineInstr *CopyMI); + + /// HasOtherReachingDefs - Return true if there are definitions of IntB + /// other than BValNo val# that can reach uses of AValno val# of IntA. + bool HasOtherReachingDefs(LiveInterval &IntA, LiveInterval &IntB, + VNInfo *AValNo, VNInfo *BValNo); + + /// RemoveCopyByCommutingDef - We found a non-trivially-coalescable copy. + /// If the source value number is defined by a commutable instruction and + /// its other operand is coalesced to the copy dest register, see if we + /// can transform the copy into a noop by commuting the definition. + bool RemoveCopyByCommutingDef(LiveInterval &IntA, LiveInterval &IntB, + MachineInstr *CopyMI); + + /// TrimLiveIntervalToLastUse - If there is a last use in the same basic + /// block as the copy instruction, trim the ive interval to the last use + /// and return true. + bool TrimLiveIntervalToLastUse(SlotIndex CopyIdx, + MachineBasicBlock *CopyMBB, + LiveInterval &li, const LiveRange *LR); + + /// ReMaterializeTrivialDef - If the source of a copy is defined by a trivial + /// computation, replace the copy by rematerialize the definition. + bool ReMaterializeTrivialDef(LiveInterval &SrcInt, unsigned DstReg, + unsigned DstSubIdx, MachineInstr *CopyMI); + + /// CanCoalesceWithImpDef - Returns true if the specified copy instruction + /// from an implicit def to another register can be coalesced away. + bool CanCoalesceWithImpDef(MachineInstr *CopyMI, + LiveInterval &li, LiveInterval &ImpLi) const; + + /// TurnCopiesFromValNoToImpDefs - The specified value# is defined by an + /// implicit_def and it is being removed. Turn all copies from this value# + /// into implicit_defs. + void TurnCopiesFromValNoToImpDefs(LiveInterval &li, VNInfo *VNI); + + /// isWinToJoinVRWithSrcPhysReg - Return true if it's worth while to join a + /// a virtual destination register with physical source register. + bool isWinToJoinVRWithSrcPhysReg(MachineInstr *CopyMI, + MachineBasicBlock *CopyMBB, + LiveInterval &DstInt, LiveInterval &SrcInt); + + /// isWinToJoinVRWithDstPhysReg - Return true if it's worth while to join a + /// copy from a virtual source register to a physical destination register. + bool isWinToJoinVRWithDstPhysReg(MachineInstr *CopyMI, + MachineBasicBlock *CopyMBB, + LiveInterval &DstInt, LiveInterval &SrcInt); + + /// isWinToJoinCrossClass - Return true if it's profitable to coalesce + /// two virtual registers from different register classes. + bool isWinToJoinCrossClass(unsigned LargeReg, unsigned SmallReg, + unsigned Threshold); + + /// HasIncompatibleSubRegDefUse - If we are trying to coalesce a virtual + /// register with a physical register, check if any of the virtual register + /// operand is a sub-register use or def. If so, make sure it won't result + /// in an illegal extract_subreg or insert_subreg instruction. + bool HasIncompatibleSubRegDefUse(MachineInstr *CopyMI, + unsigned VirtReg, unsigned PhysReg); + + /// CanJoinExtractSubRegToPhysReg - Return true if it's possible to coalesce + /// an extract_subreg where dst is a physical register, e.g. + /// cl = EXTRACT_SUBREG reg1024, 1 + bool CanJoinExtractSubRegToPhysReg(unsigned DstReg, unsigned SrcReg, + unsigned SubIdx, unsigned &RealDstReg); + + /// CanJoinInsertSubRegToPhysReg - Return true if it's possible to coalesce + /// an insert_subreg where src is a physical register, e.g. + /// reg1024 = INSERT_SUBREG reg1024, c1, 0 + bool CanJoinInsertSubRegToPhysReg(unsigned DstReg, unsigned SrcReg, + unsigned SubIdx, unsigned &RealDstReg); + + /// ValueLiveAt - Return true if the LiveRange pointed to by the given + /// iterator, or any subsequent range with the same value number, + /// is live at the given point. + bool ValueLiveAt(LiveInterval::iterator LRItr, LiveInterval::iterator LREnd, + SlotIndex defPoint) const; + + /// RangeIsDefinedByCopyFromReg - Return true if the specified live range of + /// the specified live interval is defined by a copy from the specified + /// register. + bool RangeIsDefinedByCopyFromReg(LiveInterval &li, LiveRange *LR, + unsigned Reg); + + /// UpdateRegDefsUses - Replace all defs and uses of SrcReg to DstReg and + /// update the subregister number if it is not zero. If DstReg is a + /// physical register and the existing subregister number of the def / use + /// being updated is not zero, make sure to set it to the correct physical + /// subregister. + void UpdateRegDefsUses(unsigned SrcReg, unsigned DstReg, unsigned SubIdx); + + /// RemoveUnnecessaryKills - Remove kill markers that are no longer accurate + /// due to live range lengthening as the result of coalescing. + void RemoveUnnecessaryKills(unsigned Reg, LiveInterval &LI); + + /// ShortenDeadCopyLiveRange - Shorten a live range defined by a dead copy. + /// Return true if live interval is removed. + bool ShortenDeadCopyLiveRange(LiveInterval &li, MachineInstr *CopyMI); + + /// ShortenDeadCopyLiveRange - Shorten a live range as it's artificially + /// extended by a dead copy. Mark the last use (if any) of the val# as kill + /// as ends the live range there. If there isn't another use, then this + /// live range is dead. Return true if live interval is removed. + bool ShortenDeadCopySrcLiveRange(LiveInterval &li, MachineInstr *CopyMI); + + /// RemoveDeadDef - If a def of a live interval is now determined dead, + /// remove the val# it defines. If the live interval becomes empty, remove + /// it as well. + bool RemoveDeadDef(LiveInterval &li, MachineInstr *DefMI); + + /// lastRegisterUse - Returns the last use of the specific register between + /// cycles Start and End or NULL if there are no uses. + MachineOperand *lastRegisterUse(SlotIndex Start, SlotIndex End, + unsigned Reg, SlotIndex &LastUseIdx) const; + + /// CalculateSpillWeights - Compute spill weights for all virtual register + /// live intervals. + void CalculateSpillWeights(); + + void printRegName(unsigned reg) const; + }; + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/lib/CodeGen/SjLjEHPrepare.cpp b/libclamav/c++/llvm/lib/CodeGen/SjLjEHPrepare.cpp new file mode 100644 index 000000000..6de03e1aa --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/SjLjEHPrepare.cpp @@ -0,0 +1,519 @@ +//===- SjLjEHPass.cpp - Eliminate Invoke & Unwind instructions -----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This transformation is designed for use by code generators which use SjLj +// based exception handling. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "sjljehprepare" +#include "llvm/Transforms/Scalar.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Instructions.h" +#include "llvm/Intrinsics.h" +#include "llvm/LLVMContext.h" +#include "llvm/Module.h" +#include "llvm/Pass.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/Transforms/Utils/BasicBlockUtils.h" +#include "llvm/Transforms/Utils/Local.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Target/TargetLowering.h" +using namespace llvm; + +STATISTIC(NumInvokes, "Number of invokes replaced"); +STATISTIC(NumUnwinds, "Number of unwinds replaced"); +STATISTIC(NumSpilled, "Number of registers live across unwind edges"); + +namespace { + class SjLjEHPass : public FunctionPass { + + const TargetLowering *TLI; + + const Type *FunctionContextTy; + Constant *RegisterFn; + Constant *UnregisterFn; + Constant *ResumeFn; + Constant *BuiltinSetjmpFn; + Constant *FrameAddrFn; + Constant *LSDAAddrFn; + Value *PersonalityFn; + Constant *SelectorFn; + Constant *ExceptionFn; + + Value *CallSite; + public: + static char ID; // Pass identification, replacement for typeid + explicit SjLjEHPass(const TargetLowering *tli = NULL) + : FunctionPass(&ID), TLI(tli) { } + bool doInitialization(Module &M); + bool runOnFunction(Function &F); + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { } + const char *getPassName() const { + return "SJLJ Exception Handling preparation"; + } + + private: + void markInvokeCallSite(InvokeInst *II, unsigned InvokeNo, + Value *CallSite, + SwitchInst *CatchSwitch); + void splitLiveRangesLiveAcrossInvokes(SmallVector &Invokes); + bool insertSjLjEHSupport(Function &F); + }; +} // end anonymous namespace + +char SjLjEHPass::ID = 0; + +// Public Interface To the SjLjEHPass pass. +FunctionPass *llvm::createSjLjEHPass(const TargetLowering *TLI) { + return new SjLjEHPass(TLI); +} +// doInitialization - Set up decalarations and types needed to process +// exceptions. +bool SjLjEHPass::doInitialization(Module &M) { + // Build the function context structure. + // builtin_setjmp uses a five word jbuf + const Type *VoidPtrTy = + Type::getInt8PtrTy(M.getContext()); + const Type *Int32Ty = Type::getInt32Ty(M.getContext()); + FunctionContextTy = + StructType::get(M.getContext(), + VoidPtrTy, // __prev + Int32Ty, // call_site + ArrayType::get(Int32Ty, 4), // __data + VoidPtrTy, // __personality + VoidPtrTy, // __lsda + ArrayType::get(VoidPtrTy, 5), // __jbuf + NULL); + RegisterFn = M.getOrInsertFunction("_Unwind_SjLj_Register", + Type::getVoidTy(M.getContext()), + PointerType::getUnqual(FunctionContextTy), + (Type *)0); + UnregisterFn = + M.getOrInsertFunction("_Unwind_SjLj_Unregister", + Type::getVoidTy(M.getContext()), + PointerType::getUnqual(FunctionContextTy), + (Type *)0); + ResumeFn = + M.getOrInsertFunction("_Unwind_SjLj_Resume", + Type::getVoidTy(M.getContext()), + VoidPtrTy, + (Type *)0); + FrameAddrFn = Intrinsic::getDeclaration(&M, Intrinsic::frameaddress); + BuiltinSetjmpFn = Intrinsic::getDeclaration(&M, Intrinsic::eh_sjlj_setjmp); + LSDAAddrFn = Intrinsic::getDeclaration(&M, Intrinsic::eh_sjlj_lsda); + SelectorFn = Intrinsic::getDeclaration(&M, Intrinsic::eh_selector); + ExceptionFn = Intrinsic::getDeclaration(&M, Intrinsic::eh_exception); + PersonalityFn = 0; + + return true; +} + +/// markInvokeCallSite - Insert code to mark the call_site for this invoke +void SjLjEHPass::markInvokeCallSite(InvokeInst *II, unsigned InvokeNo, + Value *CallSite, + SwitchInst *CatchSwitch) { + ConstantInt *CallSiteNoC= ConstantInt::get(Type::getInt32Ty(II->getContext()), + InvokeNo); + // The runtime comes back to the dispatcher with the call_site - 1 in + // the context. Odd, but there it is. + ConstantInt *SwitchValC = ConstantInt::get(Type::getInt32Ty(II->getContext()), + InvokeNo - 1); + + // If the unwind edge has phi nodes, split the edge. + if (isa(II->getUnwindDest()->begin())) { + SplitCriticalEdge(II, 1, this); + + // If there are any phi nodes left, they must have a single predecessor. + while (PHINode *PN = dyn_cast(II->getUnwindDest()->begin())) { + PN->replaceAllUsesWith(PN->getIncomingValue(0)); + PN->eraseFromParent(); + } + } + + // Insert a store of the invoke num before the invoke and store zero into the + // location afterward. + new StoreInst(CallSiteNoC, CallSite, true, II); // volatile + + // Add a switch case to our unwind block. + CatchSwitch->addCase(SwitchValC, II->getUnwindDest()); + // We still want this to look like an invoke so we emit the LSDA properly + // FIXME: ??? Or will this cause strangeness with mis-matched IDs like + // when it was in the front end? +} + +/// MarkBlocksLiveIn - Insert BB and all of its predescessors into LiveBBs until +/// we reach blocks we've already seen. +static void MarkBlocksLiveIn(BasicBlock *BB, std::set &LiveBBs) { + if (!LiveBBs.insert(BB).second) return; // already been here. + + for (pred_iterator PI = pred_begin(BB), E = pred_end(BB); PI != E; ++PI) + MarkBlocksLiveIn(*PI, LiveBBs); +} + +/// splitLiveRangesAcrossInvokes - Each value that is live across an unwind edge +/// we spill into a stack location, guaranteeing that there is nothing live +/// across the unwind edge. This process also splits all critical edges +/// coming out of invoke's. +void SjLjEHPass:: +splitLiveRangesLiveAcrossInvokes(SmallVector &Invokes) { + // First step, split all critical edges from invoke instructions. + for (unsigned i = 0, e = Invokes.size(); i != e; ++i) { + InvokeInst *II = Invokes[i]; + SplitCriticalEdge(II, 0, this); + SplitCriticalEdge(II, 1, this); + assert(!isa(II->getNormalDest()) && + !isa(II->getUnwindDest()) && + "critical edge splitting left single entry phi nodes?"); + } + + Function *F = Invokes.back()->getParent()->getParent(); + + // To avoid having to handle incoming arguments specially, we lower each arg + // to a copy instruction in the entry block. This ensures that the argument + // value itself cannot be live across the entry block. + BasicBlock::iterator AfterAllocaInsertPt = F->begin()->begin(); + while (isa(AfterAllocaInsertPt) && + isa(cast(AfterAllocaInsertPt)->getArraySize())) + ++AfterAllocaInsertPt; + for (Function::arg_iterator AI = F->arg_begin(), E = F->arg_end(); + AI != E; ++AI) { + // This is always a no-op cast because we're casting AI to AI->getType() so + // src and destination types are identical. BitCast is the only possibility. + CastInst *NC = new BitCastInst( + AI, AI->getType(), AI->getName()+".tmp", AfterAllocaInsertPt); + AI->replaceAllUsesWith(NC); + // Normally its is forbidden to replace a CastInst's operand because it + // could cause the opcode to reflect an illegal conversion. However, we're + // replacing it here with the same value it was constructed with to simply + // make NC its user. + NC->setOperand(0, AI); + } + + // Finally, scan the code looking for instructions with bad live ranges. + for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) + for (BasicBlock::iterator II = BB->begin(), E = BB->end(); II != E; ++II) { + // Ignore obvious cases we don't have to handle. In particular, most + // instructions either have no uses or only have a single use inside the + // current block. Ignore them quickly. + Instruction *Inst = II; + if (Inst->use_empty()) continue; + if (Inst->hasOneUse() && + cast(Inst->use_back())->getParent() == BB && + !isa(Inst->use_back())) continue; + + // If this is an alloca in the entry block, it's not a real register + // value. + if (AllocaInst *AI = dyn_cast(Inst)) + if (isa(AI->getArraySize()) && BB == F->begin()) + continue; + + // Avoid iterator invalidation by copying users to a temporary vector. + SmallVector Users; + for (Value::use_iterator UI = Inst->use_begin(), E = Inst->use_end(); + UI != E; ++UI) { + Instruction *User = cast(*UI); + if (User->getParent() != BB || isa(User)) + Users.push_back(User); + } + + // Find all of the blocks that this value is live in. + std::set LiveBBs; + LiveBBs.insert(Inst->getParent()); + while (!Users.empty()) { + Instruction *U = Users.back(); + Users.pop_back(); + + if (!isa(U)) { + MarkBlocksLiveIn(U->getParent(), LiveBBs); + } else { + // Uses for a PHI node occur in their predecessor block. + PHINode *PN = cast(U); + for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) + if (PN->getIncomingValue(i) == Inst) + MarkBlocksLiveIn(PN->getIncomingBlock(i), LiveBBs); + } + } + + // Now that we know all of the blocks that this thing is live in, see if + // it includes any of the unwind locations. + bool NeedsSpill = false; + for (unsigned i = 0, e = Invokes.size(); i != e; ++i) { + BasicBlock *UnwindBlock = Invokes[i]->getUnwindDest(); + if (UnwindBlock != BB && LiveBBs.count(UnwindBlock)) { + NeedsSpill = true; + } + } + + // If we decided we need a spill, do it. + if (NeedsSpill) { + ++NumSpilled; + DemoteRegToStack(*Inst, true); + } + } +} + +bool SjLjEHPass::insertSjLjEHSupport(Function &F) { + SmallVector Returns; + SmallVector Unwinds; + SmallVector Invokes; + + // Look through the terminators of the basic blocks to find invokes, returns + // and unwinds + for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB) + if (ReturnInst *RI = dyn_cast(BB->getTerminator())) { + // Remember all return instructions in case we insert an invoke into this + // function. + Returns.push_back(RI); + } else if (InvokeInst *II = dyn_cast(BB->getTerminator())) { + Invokes.push_back(II); + } else if (UnwindInst *UI = dyn_cast(BB->getTerminator())) { + Unwinds.push_back(UI); + } + // If we don't have any invokes or unwinds, there's nothing to do. + if (Unwinds.empty() && Invokes.empty()) return false; + + // Find the eh.selector.* and eh.exception calls. We'll use the first + // eh.selector to determine the right personality function to use. For + // SJLJ, we always use the same personality for the whole function, + // not on a per-selector basis. + // FIXME: That's a bit ugly. Better way? + SmallVector EH_Selectors; + SmallVector EH_Exceptions; + for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB) { + for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ++I) { + if (CallInst *CI = dyn_cast(I)) { + if (CI->getCalledFunction() == SelectorFn) { + if (!PersonalityFn) PersonalityFn = CI->getOperand(2); + EH_Selectors.push_back(CI); + } else if (CI->getCalledFunction() == ExceptionFn) { + EH_Exceptions.push_back(CI); + } + } + } + } + // If we don't have any eh.selector calls, we can't determine the personality + // function. Without a personality function, we can't process exceptions. + if (!PersonalityFn) return false; + + NumInvokes += Invokes.size(); + NumUnwinds += Unwinds.size(); + + if (!Invokes.empty()) { + // We have invokes, so we need to add register/unregister calls to get + // this function onto the global unwind stack. + // + // First thing we need to do is scan the whole function for values that are + // live across unwind edges. Each value that is live across an unwind edge + // we spill into a stack location, guaranteeing that there is nothing live + // across the unwind edge. This process also splits all critical edges + // coming out of invoke's. + splitLiveRangesLiveAcrossInvokes(Invokes); + + BasicBlock *EntryBB = F.begin(); + // Create an alloca for the incoming jump buffer ptr and the new jump buffer + // that needs to be restored on all exits from the function. This is an + // alloca because the value needs to be added to the global context list. + unsigned Align = 4; // FIXME: Should be a TLI check? + AllocaInst *FunctionContext = + new AllocaInst(FunctionContextTy, 0, Align, + "fcn_context", F.begin()->begin()); + + Value *Idxs[2]; + const Type *Int32Ty = Type::getInt32Ty(F.getContext()); + Value *Zero = ConstantInt::get(Int32Ty, 0); + // We need to also keep around a reference to the call_site field + Idxs[0] = Zero; + Idxs[1] = ConstantInt::get(Int32Ty, 1); + CallSite = GetElementPtrInst::Create(FunctionContext, Idxs, Idxs+2, + "call_site", + EntryBB->getTerminator()); + + // The exception selector comes back in context->data[1] + Idxs[1] = ConstantInt::get(Int32Ty, 2); + Value *FCData = GetElementPtrInst::Create(FunctionContext, Idxs, Idxs+2, + "fc_data", + EntryBB->getTerminator()); + Idxs[1] = ConstantInt::get(Int32Ty, 1); + Value *SelectorAddr = GetElementPtrInst::Create(FCData, Idxs, Idxs+2, + "exc_selector_gep", + EntryBB->getTerminator()); + // The exception value comes back in context->data[0] + Idxs[1] = Zero; + Value *ExceptionAddr = GetElementPtrInst::Create(FCData, Idxs, Idxs+2, + "exception_gep", + EntryBB->getTerminator()); + + // The result of the eh.selector call will be replaced with a + // a reference to the selector value returned in the function + // context. We leave the selector itself so the EH analysis later + // can use it. + for (int i = 0, e = EH_Selectors.size(); i < e; ++i) { + CallInst *I = EH_Selectors[i]; + Value *SelectorVal = new LoadInst(SelectorAddr, "select_val", true, I); + I->replaceAllUsesWith(SelectorVal); + } + // eh.exception calls are replaced with references to the proper + // location in the context. Unlike eh.selector, the eh.exception + // calls are removed entirely. + for (int i = 0, e = EH_Exceptions.size(); i < e; ++i) { + CallInst *I = EH_Exceptions[i]; + // Possible for there to be duplicates, so check to make sure + // the instruction hasn't already been removed. + if (!I->getParent()) continue; + Value *Val = new LoadInst(ExceptionAddr, "exception", true, I); + const Type *Ty = Type::getInt8PtrTy(F.getContext()); + Val = CastInst::Create(Instruction::IntToPtr, Val, Ty, "", I); + + I->replaceAllUsesWith(Val); + I->eraseFromParent(); + } + + + + + // The entry block changes to have the eh.sjlj.setjmp, with a conditional + // branch to a dispatch block for non-zero returns. If we return normally, + // we're not handling an exception and just register the function context + // and continue. + + // Create the dispatch block. The dispatch block is basically a big switch + // statement that goes to all of the invoke landing pads. + BasicBlock *DispatchBlock = + BasicBlock::Create(F.getContext(), "eh.sjlj.setjmp.catch", &F); + + // Insert a load in the Catch block, and a switch on its value. By default, + // we go to a block that just does an unwind (which is the correct action + // for a standard call). + BasicBlock *UnwindBlock = BasicBlock::Create(F.getContext(), "unwindbb", &F); + Unwinds.push_back(new UnwindInst(F.getContext(), UnwindBlock)); + + Value *DispatchLoad = new LoadInst(CallSite, "invoke.num", true, + DispatchBlock); + SwitchInst *DispatchSwitch = + SwitchInst::Create(DispatchLoad, UnwindBlock, Invokes.size(), DispatchBlock); + // Split the entry block to insert the conditional branch for the setjmp. + BasicBlock *ContBlock = EntryBB->splitBasicBlock(EntryBB->getTerminator(), + "eh.sjlj.setjmp.cont"); + + // Populate the Function Context + // 1. LSDA address + // 2. Personality function address + // 3. jmpbuf (save FP and call eh.sjlj.setjmp) + + // LSDA address + Idxs[0] = Zero; + Idxs[1] = ConstantInt::get(Int32Ty, 4); + Value *LSDAFieldPtr = + GetElementPtrInst::Create(FunctionContext, Idxs, Idxs+2, + "lsda_gep", + EntryBB->getTerminator()); + Value *LSDA = CallInst::Create(LSDAAddrFn, "lsda_addr", + EntryBB->getTerminator()); + new StoreInst(LSDA, LSDAFieldPtr, true, EntryBB->getTerminator()); + + Idxs[1] = ConstantInt::get(Int32Ty, 3); + Value *PersonalityFieldPtr = + GetElementPtrInst::Create(FunctionContext, Idxs, Idxs+2, + "lsda_gep", + EntryBB->getTerminator()); + new StoreInst(PersonalityFn, PersonalityFieldPtr, true, + EntryBB->getTerminator()); + + // Save the frame pointer. + Idxs[1] = ConstantInt::get(Int32Ty, 5); + Value *FieldPtr + = GetElementPtrInst::Create(FunctionContext, Idxs, Idxs+2, + "jbuf_gep", + EntryBB->getTerminator()); + Idxs[1] = ConstantInt::get(Int32Ty, 0); + Value *ElemPtr = + GetElementPtrInst::Create(FieldPtr, Idxs, Idxs+2, "jbuf_fp_gep", + EntryBB->getTerminator()); + + Value *Val = CallInst::Create(FrameAddrFn, + ConstantInt::get(Int32Ty, 0), + "fp", + EntryBB->getTerminator()); + new StoreInst(Val, ElemPtr, true, EntryBB->getTerminator()); + // Call the setjmp instrinsic. It fills in the rest of the jmpbuf + Value *SetjmpArg = + CastInst::Create(Instruction::BitCast, FieldPtr, + Type::getInt8PtrTy(F.getContext()), "", + EntryBB->getTerminator()); + Value *DispatchVal = CallInst::Create(BuiltinSetjmpFn, SetjmpArg, + "dispatch", + EntryBB->getTerminator()); + // check the return value of the setjmp. non-zero goes to dispatcher + Value *IsNormal = new ICmpInst(EntryBB->getTerminator(), + ICmpInst::ICMP_EQ, DispatchVal, Zero, + "notunwind"); + // Nuke the uncond branch. + EntryBB->getTerminator()->eraseFromParent(); + + // Put in a new condbranch in its place. + BranchInst::Create(ContBlock, DispatchBlock, IsNormal, EntryBB); + + // Register the function context and make sure it's known to not throw + CallInst *Register = + CallInst::Create(RegisterFn, FunctionContext, "", + ContBlock->getTerminator()); + Register->setDoesNotThrow(); + + // At this point, we are all set up, update the invoke instructions + // to mark their call_site values, and fill in the dispatch switch + // accordingly. + for (unsigned i = 0, e = Invokes.size(); i != e; ++i) + markInvokeCallSite(Invokes[i], i+1, CallSite, DispatchSwitch); + + // The front end has likely added calls to _Unwind_Resume. We need + // to find those calls and mark the call_site as -1 immediately prior. + // resume is a noreturn function, so any block that has a call to it + // should end in an 'unreachable' instruction with the call immediately + // prior. That's how we'll search. + // ??? There's got to be a better way. this is fugly. + for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB) + if ((dyn_cast(BB->getTerminator()))) { + BasicBlock::iterator I = BB->getTerminator(); + // Check the previous instruction and see if it's a resume call + if (I == BB->begin()) continue; + if (CallInst *CI = dyn_cast(--I)) { + if (CI->getCalledFunction() == ResumeFn) { + Value *NegativeOne = Constant::getAllOnesValue(Int32Ty); + new StoreInst(NegativeOne, CallSite, true, I); // volatile + } + } + } + + // Replace all unwinds with a branch to the unwind handler. + // ??? Should this ever happen with sjlj exceptions? + for (unsigned i = 0, e = Unwinds.size(); i != e; ++i) { + BranchInst::Create(UnwindBlock, Unwinds[i]); + Unwinds[i]->eraseFromParent(); + } + + // Finally, for any returns from this function, if this function contains an + // invoke, add a call to unregister the function context. + for (unsigned i = 0, e = Returns.size(); i != e; ++i) + CallInst::Create(UnregisterFn, FunctionContext, "", Returns[i]); + } + + return true; +} + +bool SjLjEHPass::runOnFunction(Function &F) { + bool Res = insertSjLjEHSupport(F); + return Res; +} diff --git a/libclamav/c++/llvm/lib/CodeGen/SlotIndexes.cpp b/libclamav/c++/llvm/lib/CodeGen/SlotIndexes.cpp new file mode 100644 index 000000000..f85384bc5 --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/SlotIndexes.cpp @@ -0,0 +1,222 @@ +//===-- SlotIndexes.cpp - Slot Indexes Pass ------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "slotindexes" + +#include "llvm/CodeGen/SlotIndexes.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/ManagedStatic.h" + +using namespace llvm; + + +// Yep - these are thread safe. See the header for details. +namespace { + + + class EmptyIndexListEntry : public IndexListEntry { + public: + EmptyIndexListEntry() : IndexListEntry(EMPTY_KEY) {} + }; + + class TombstoneIndexListEntry : public IndexListEntry { + public: + TombstoneIndexListEntry() : IndexListEntry(TOMBSTONE_KEY) {} + }; + + // The following statics are thread safe. They're read only, and you + // can't step from them to any other list entries. + ManagedStatic IndexListEntryEmptyKey; + ManagedStatic IndexListEntryTombstoneKey; +} + +char SlotIndexes::ID = 0; +static RegisterPass X("slotindexes", "Slot index numbering"); + +IndexListEntry* IndexListEntry::getEmptyKeyEntry() { + return &*IndexListEntryEmptyKey; +} + +IndexListEntry* IndexListEntry::getTombstoneKeyEntry() { + return &*IndexListEntryTombstoneKey; +} + + +void SlotIndexes::getAnalysisUsage(AnalysisUsage &au) const { + au.setPreservesAll(); + MachineFunctionPass::getAnalysisUsage(au); +} + +void SlotIndexes::releaseMemory() { + mi2iMap.clear(); + mbb2IdxMap.clear(); + idx2MBBMap.clear(); + terminatorGaps.clear(); + clearList(); +} + +bool SlotIndexes::runOnMachineFunction(MachineFunction &fn) { + + // Compute numbering as follows: + // Grab an iterator to the start of the index list. + // Iterate over all MBBs, and within each MBB all MIs, keeping the MI + // iterator in lock-step (though skipping it over indexes which have + // null pointers in the instruction field). + // At each iteration assert that the instruction pointed to in the index + // is the same one pointed to by the MI iterator. This + + // FIXME: This can be simplified. The mi2iMap_, Idx2MBBMap, etc. should + // only need to be set up once after the first numbering is computed. + + mf = &fn; + initList(); + + // Check that the list contains only the sentinal. + assert(indexListHead->getNext() == 0 && + "Index list non-empty at initial numbering?"); + assert(idx2MBBMap.empty() && + "Index -> MBB mapping non-empty at initial numbering?"); + assert(mbb2IdxMap.empty() && + "MBB -> Index mapping non-empty at initial numbering?"); + assert(mi2iMap.empty() && + "MachineInstr -> Index mapping non-empty at initial numbering?"); + + functionSize = 0; + unsigned index = 0; + + // Iterate over the the function. + for (MachineFunction::iterator mbbItr = mf->begin(), mbbEnd = mf->end(); + mbbItr != mbbEnd; ++mbbItr) { + MachineBasicBlock *mbb = &*mbbItr; + + // Insert an index for the MBB start. + push_back(createEntry(0, index)); + SlotIndex blockStartIndex(back(), SlotIndex::LOAD); + + index += SlotIndex::NUM; + + for (MachineBasicBlock::iterator miItr = mbb->begin(), miEnd = mbb->end(); + miItr != miEnd; ++miItr) { + MachineInstr *mi = &*miItr; + + if (miItr == mbb->getFirstTerminator()) { + push_back(createEntry(0, index)); + terminatorGaps.insert( + std::make_pair(mbb, SlotIndex(back(), SlotIndex::PHI_BIT))); + index += SlotIndex::NUM; + } + + // Insert a store index for the instr. + push_back(createEntry(mi, index)); + + // Save this base index in the maps. + mi2iMap.insert( + std::make_pair(mi, SlotIndex(back(), SlotIndex::LOAD))); + + ++functionSize; + + unsigned Slots = mi->getDesc().getNumDefs(); + if (Slots == 0) + Slots = 1; + + index += (Slots + 1) * SlotIndex::NUM; + } + + if (mbb->getFirstTerminator() == mbb->end()) { + push_back(createEntry(0, index)); + terminatorGaps.insert( + std::make_pair(mbb, SlotIndex(back(), SlotIndex::PHI_BIT))); + index += SlotIndex::NUM; + } + + SlotIndex blockEndIndex(back(), SlotIndex::STORE); + mbb2IdxMap.insert( + std::make_pair(mbb, std::make_pair(blockStartIndex, blockEndIndex))); + + idx2MBBMap.push_back(IdxMBBPair(blockStartIndex, mbb)); + } + + // One blank instruction at the end. + push_back(createEntry(0, index)); + + // Sort the Idx2MBBMap + std::sort(idx2MBBMap.begin(), idx2MBBMap.end(), Idx2MBBCompare()); + + DEBUG(dump()); + + // And we're done! + return false; +} + +void SlotIndexes::renumberIndexes() { + + // Renumber updates the index of every element of the index list. + // If all instrs in the function have been allocated an index (which has been + // placed in the index list in the order of instruction iteration) then the + // resulting numbering will match what would have been generated by the + // pass during the initial numbering of the function if the new instructions + // had been present. + + functionSize = 0; + unsigned index = 0; + + for (IndexListEntry *curEntry = front(); curEntry != getTail(); + curEntry = curEntry->getNext()) { + + curEntry->setIndex(index); + + if (curEntry->getInstr() == 0) { + // MBB start entry or terminator gap. Just step index by 1. + index += SlotIndex::NUM; + } + else { + ++functionSize; + unsigned Slots = curEntry->getInstr()->getDesc().getNumDefs(); + if (Slots == 0) + Slots = 1; + + index += (Slots + 1) * SlotIndex::NUM; + } + } +} + +void SlotIndexes::dump() const { + for (const IndexListEntry *itr = front(); itr != getTail(); + itr = itr->getNext()) { + errs() << itr->getIndex() << " "; + + if (itr->getInstr() != 0) { + errs() << *itr->getInstr(); + } else { + errs() << "\n"; + } + } + + for (MBB2IdxMap::const_iterator itr = mbb2IdxMap.begin(); + itr != mbb2IdxMap.end(); ++itr) { + errs() << "MBB " << itr->first->getNumber() << " (" << itr->first << ") - [" + << itr->second.first << ", " << itr->second.second << "]\n"; + } +} + +// Print a SlotIndex to a raw_ostream. +void SlotIndex::print(raw_ostream &os) const { + os << getIndex(); + if (isPHI()) + os << "*"; +} + +// Dump a SlotIndex to stderr. +void SlotIndex::dump() const { + print(errs()); + errs() << "\n"; +} + diff --git a/libclamav/c++/llvm/lib/CodeGen/Spiller.cpp b/libclamav/c++/llvm/lib/CodeGen/Spiller.cpp new file mode 100644 index 000000000..237d0b5f4 --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/Spiller.cpp @@ -0,0 +1,209 @@ +//===-- llvm/CodeGen/Spiller.cpp - Spiller -------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "spiller" + +#include "Spiller.h" +#include "VirtRegMap.h" +#include "llvm/CodeGen/LiveIntervalAnalysis.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" + +using namespace llvm; + +namespace { + enum SpillerName { trivial, standard }; +} + +static cl::opt +spillerOpt("spiller", + cl::desc("Spiller to use: (default: standard)"), + cl::Prefix, + cl::values(clEnumVal(trivial, "trivial spiller"), + clEnumVal(standard, "default spiller"), + clEnumValEnd), + cl::init(standard)); + +Spiller::~Spiller() {} + +namespace { + +/// Utility class for spillers. +class SpillerBase : public Spiller { +protected: + + MachineFunction *mf; + LiveIntervals *lis; + MachineFrameInfo *mfi; + MachineRegisterInfo *mri; + const TargetInstrInfo *tii; + VirtRegMap *vrm; + + /// Construct a spiller base. + SpillerBase(MachineFunction *mf, LiveIntervals *lis, VirtRegMap *vrm) + : mf(mf), lis(lis), vrm(vrm) + { + mfi = mf->getFrameInfo(); + mri = &mf->getRegInfo(); + tii = mf->getTarget().getInstrInfo(); + } + + /// Add spill ranges for every use/def of the live interval, inserting loads + /// immediately before each use, and stores after each def. No folding or + /// remat is attempted. + std::vector trivialSpillEverywhere(LiveInterval *li) { + DEBUG(errs() << "Spilling everywhere " << *li << "\n"); + + assert(li->weight != HUGE_VALF && + "Attempting to spill already spilled value."); + + assert(!li->isStackSlot() && + "Trying to spill a stack slot."); + + DEBUG(errs() << "Trivial spill everywhere of reg" << li->reg << "\n"); + + std::vector added; + + const TargetRegisterClass *trc = mri->getRegClass(li->reg); + unsigned ss = vrm->assignVirt2StackSlot(li->reg); + + // Iterate over reg uses/defs. + for (MachineRegisterInfo::reg_iterator + regItr = mri->reg_begin(li->reg); regItr != mri->reg_end();) { + + // Grab the use/def instr. + MachineInstr *mi = &*regItr; + + DEBUG(errs() << " Processing " << *mi); + + // Step regItr to the next use/def instr. + do { + ++regItr; + } while (regItr != mri->reg_end() && (&*regItr == mi)); + + // Collect uses & defs for this instr. + SmallVector indices; + bool hasUse = false; + bool hasDef = false; + for (unsigned i = 0; i != mi->getNumOperands(); ++i) { + MachineOperand &op = mi->getOperand(i); + if (!op.isReg() || op.getReg() != li->reg) + continue; + hasUse |= mi->getOperand(i).isUse(); + hasDef |= mi->getOperand(i).isDef(); + indices.push_back(i); + } + + // Create a new vreg & interval for this instr. + unsigned newVReg = mri->createVirtualRegister(trc); + vrm->grow(); + vrm->assignVirt2StackSlot(newVReg, ss); + LiveInterval *newLI = &lis->getOrCreateInterval(newVReg); + newLI->weight = HUGE_VALF; + + // Update the reg operands & kill flags. + for (unsigned i = 0; i < indices.size(); ++i) { + unsigned mopIdx = indices[i]; + MachineOperand &mop = mi->getOperand(mopIdx); + mop.setReg(newVReg); + if (mop.isUse() && !mi->isRegTiedToDefOperand(mopIdx)) { + mop.setIsKill(true); + } + } + assert(hasUse || hasDef); + + // Insert reload if necessary. + MachineBasicBlock::iterator miItr(mi); + if (hasUse) { + tii->loadRegFromStackSlot(*mi->getParent(), miItr, newVReg, ss, trc); + MachineInstr *loadInstr(prior(miItr)); + SlotIndex loadIndex = + lis->InsertMachineInstrInMaps(loadInstr).getDefIndex(); + SlotIndex endIndex = loadIndex.getNextIndex(); + VNInfo *loadVNI = + newLI->getNextValue(loadIndex, 0, true, lis->getVNInfoAllocator()); + loadVNI->addKill(endIndex); + newLI->addRange(LiveRange(loadIndex, endIndex, loadVNI)); + } + + // Insert store if necessary. + if (hasDef) { + tii->storeRegToStackSlot(*mi->getParent(), next(miItr), newVReg, true, + ss, trc); + MachineInstr *storeInstr(next(miItr)); + SlotIndex storeIndex = + lis->InsertMachineInstrInMaps(storeInstr).getDefIndex(); + SlotIndex beginIndex = storeIndex.getPrevIndex(); + VNInfo *storeVNI = + newLI->getNextValue(beginIndex, 0, true, lis->getVNInfoAllocator()); + storeVNI->addKill(storeIndex); + newLI->addRange(LiveRange(beginIndex, storeIndex, storeVNI)); + } + + added.push_back(newLI); + } + + return added; + } + +}; + + +/// Spills any live range using the spill-everywhere method with no attempt at +/// folding. +class TrivialSpiller : public SpillerBase { +public: + + TrivialSpiller(MachineFunction *mf, LiveIntervals *lis, VirtRegMap *vrm) + : SpillerBase(mf, lis, vrm) {} + + std::vector spill(LiveInterval *li, + SmallVectorImpl &spillIs) { + // Ignore spillIs - we don't use it. + return trivialSpillEverywhere(li); + } + +}; + +/// Falls back on LiveIntervals::addIntervalsForSpills. +class StandardSpiller : public Spiller { +private: + LiveIntervals *lis; + const MachineLoopInfo *loopInfo; + VirtRegMap *vrm; +public: + StandardSpiller(MachineFunction *mf, LiveIntervals *lis, + const MachineLoopInfo *loopInfo, VirtRegMap *vrm) + : lis(lis), loopInfo(loopInfo), vrm(vrm) {} + + /// Falls back on LiveIntervals::addIntervalsForSpills. + std::vector spill(LiveInterval *li, + SmallVectorImpl &spillIs) { + return lis->addIntervalsForSpills(*li, spillIs, loopInfo, *vrm); + } + +}; + +} + +llvm::Spiller* llvm::createSpiller(MachineFunction *mf, LiveIntervals *lis, + const MachineLoopInfo *loopInfo, + VirtRegMap *vrm) { + switch (spillerOpt) { + case trivial: return new TrivialSpiller(mf, lis, vrm); break; + case standard: return new StandardSpiller(mf, lis, loopInfo, vrm); break; + default: llvm_unreachable("Unreachable!"); break; + } +} diff --git a/libclamav/c++/llvm/lib/CodeGen/Spiller.h b/libclamav/c++/llvm/lib/CodeGen/Spiller.h new file mode 100644 index 000000000..c6bd9857d --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/Spiller.h @@ -0,0 +1,47 @@ +//===-- llvm/CodeGen/Spiller.h - Spiller -*- C++ -*------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_SPILLER_H +#define LLVM_CODEGEN_SPILLER_H + +#include "llvm/ADT/SmallVector.h" +#include + +namespace llvm { + + class LiveInterval; + class LiveIntervals; + class LiveStacks; + class MachineFunction; + class MachineInstr; + class MachineLoopInfo; + class VirtRegMap; + class VNInfo; + + /// Spiller interface. + /// + /// Implementations are utility classes which insert spill or remat code on + /// demand. + class Spiller { + public: + virtual ~Spiller() = 0; + + /// Spill the given live range. The method used will depend on the Spiller + /// implementation selected. + virtual std::vector spill(LiveInterval *li, + SmallVectorImpl &spillIs) = 0; + + }; + + /// Create and return a spiller object, as specified on the command line. + Spiller* createSpiller(MachineFunction *mf, LiveIntervals *li, + const MachineLoopInfo *loopInfo, VirtRegMap *vrm); +} + +#endif diff --git a/libclamav/c++/llvm/lib/CodeGen/StackProtector.cpp b/libclamav/c++/llvm/lib/CodeGen/StackProtector.cpp new file mode 100644 index 000000000..e8ee82213 --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/StackProtector.cpp @@ -0,0 +1,232 @@ +//===-- StackProtector.cpp - Stack Protector Insertion --------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This pass inserts stack protectors into functions which need them. A variable +// with a random value in it is stored onto the stack before the local variables +// are allocated. Upon exiting the block, the stored value is checked. If it's +// changed, then there was some sort of violation and the program aborts. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "stack-protector" +#include "llvm/CodeGen/Passes.h" +#include "llvm/Attributes.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Function.h" +#include "llvm/Instructions.h" +#include "llvm/Intrinsics.h" +#include "llvm/Module.h" +#include "llvm/Pass.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetLowering.h" +using namespace llvm; + +// SSPBufferSize - The lower bound for a buffer to be considered for stack +// smashing protection. +static cl::opt +SSPBufferSize("stack-protector-buffer-size", cl::init(8), + cl::desc("Lower bound for a buffer to be considered for " + "stack protection")); + +namespace { + class StackProtector : public FunctionPass { + /// TLI - Keep a pointer of a TargetLowering to consult for determining + /// target type sizes. + const TargetLowering *TLI; + + Function *F; + Module *M; + + /// InsertStackProtectors - Insert code into the prologue and epilogue of + /// the function. + /// + /// - The prologue code loads and stores the stack guard onto the stack. + /// - The epilogue checks the value stored in the prologue against the + /// original value. It calls __stack_chk_fail if they differ. + bool InsertStackProtectors(); + + /// CreateFailBB - Create a basic block to jump to when the stack protector + /// check fails. + BasicBlock *CreateFailBB(); + + /// RequiresStackProtector - Check whether or not this function needs a + /// stack protector based upon the stack protector level. + bool RequiresStackProtector() const; + public: + static char ID; // Pass identification, replacement for typeid. + StackProtector() : FunctionPass(&ID), TLI(0) {} + StackProtector(const TargetLowering *tli) + : FunctionPass(&ID), TLI(tli) {} + + virtual bool runOnFunction(Function &Fn); + }; +} // end anonymous namespace + +char StackProtector::ID = 0; +static RegisterPass +X("stack-protector", "Insert stack protectors"); + +FunctionPass *llvm::createStackProtectorPass(const TargetLowering *tli) { + return new StackProtector(tli); +} + +bool StackProtector::runOnFunction(Function &Fn) { + F = &Fn; + M = F->getParent(); + + if (!RequiresStackProtector()) return false; + + return InsertStackProtectors(); +} + +/// RequiresStackProtector - Check whether or not this function needs a stack +/// protector based upon the stack protector level. The heuristic we use is to +/// add a guard variable to functions that call alloca, and functions with +/// buffers larger than SSPBufferSize bytes. +bool StackProtector::RequiresStackProtector() const { + if (F->hasFnAttr(Attribute::StackProtectReq)) + return true; + + if (!F->hasFnAttr(Attribute::StackProtect)) + return false; + + const TargetData *TD = TLI->getTargetData(); + + for (Function::iterator I = F->begin(), E = F->end(); I != E; ++I) { + BasicBlock *BB = I; + + for (BasicBlock::iterator + II = BB->begin(), IE = BB->end(); II != IE; ++II) + if (AllocaInst *AI = dyn_cast(II)) { + if (AI->isArrayAllocation()) + // This is a call to alloca with a variable size. Emit stack + // protectors. + return true; + + if (const ArrayType *AT = dyn_cast(AI->getAllocatedType())) { + // We apparently only care about character arrays. + if (AT->getElementType() != Type::getInt8Ty(AT->getContext())) + continue; + + // If an array has more than SSPBufferSize bytes of allocated space, + // then we emit stack protectors. + if (SSPBufferSize <= TD->getTypeAllocSize(AT)) + return true; + } + } + } + + return false; +} + +/// InsertStackProtectors - Insert code into the prologue and epilogue of the +/// function. +/// +/// - The prologue code loads and stores the stack guard onto the stack. +/// - The epilogue checks the value stored in the prologue against the original +/// value. It calls __stack_chk_fail if they differ. +bool StackProtector::InsertStackProtectors() { + BasicBlock *FailBB = 0; // The basic block to jump to if check fails. + AllocaInst *AI = 0; // Place on stack that stores the stack guard. + Constant *StackGuardVar = 0; // The stack guard variable. + + for (Function::iterator I = F->begin(), E = F->end(); I != E; ) { + BasicBlock *BB = I++; + + ReturnInst *RI = dyn_cast(BB->getTerminator()); + if (!RI) continue; + + if (!FailBB) { + // Insert code into the entry block that stores the __stack_chk_guard + // variable onto the stack: + // + // entry: + // StackGuardSlot = alloca i8* + // StackGuard = load __stack_chk_guard + // call void @llvm.stackprotect.create(StackGuard, StackGuardSlot) + // + PointerType *PtrTy = PointerType::getUnqual( + Type::getInt8Ty(RI->getContext())); + StackGuardVar = M->getOrInsertGlobal("__stack_chk_guard", PtrTy); + + BasicBlock &Entry = F->getEntryBlock(); + Instruction *InsPt = &Entry.front(); + + AI = new AllocaInst(PtrTy, "StackGuardSlot", InsPt); + LoadInst *LI = new LoadInst(StackGuardVar, "StackGuard", false, InsPt); + + Value *Args[] = { LI, AI }; + CallInst:: + Create(Intrinsic::getDeclaration(M, Intrinsic::stackprotector), + &Args[0], array_endof(Args), "", InsPt); + + // Create the basic block to jump to when the guard check fails. + FailBB = CreateFailBB(); + } + + // For each block with a return instruction, convert this: + // + // return: + // ... + // ret ... + // + // into this: + // + // return: + // ... + // %1 = load __stack_chk_guard + // %2 = load StackGuardSlot + // %3 = cmp i1 %1, %2 + // br i1 %3, label %SP_return, label %CallStackCheckFailBlk + // + // SP_return: + // ret ... + // + // CallStackCheckFailBlk: + // call void @__stack_chk_fail() + // unreachable + + // Split the basic block before the return instruction. + BasicBlock *NewBB = BB->splitBasicBlock(RI, "SP_return"); + + // Remove default branch instruction to the new BB. + BB->getTerminator()->eraseFromParent(); + + // Move the newly created basic block to the point right after the old basic + // block so that it's in the "fall through" position. + NewBB->moveAfter(BB); + + // Generate the stack protector instructions in the old basic block. + LoadInst *LI1 = new LoadInst(StackGuardVar, "", false, BB); + LoadInst *LI2 = new LoadInst(AI, "", true, BB); + ICmpInst *Cmp = new ICmpInst(*BB, CmpInst::ICMP_EQ, LI1, LI2, ""); + BranchInst::Create(NewBB, FailBB, Cmp, BB); + } + + // Return if we didn't modify any basic blocks. I.e., there are no return + // statements in the function. + if (!FailBB) return false; + + return true; +} + +/// CreateFailBB - Create a basic block to jump to when the stack protector +/// check fails. +BasicBlock *StackProtector::CreateFailBB() { + BasicBlock *FailBB = BasicBlock::Create(F->getContext(), + "CallStackCheckFailBlk", F); + Constant *StackChkFail = + M->getOrInsertFunction("__stack_chk_fail", + Type::getVoidTy(F->getContext()), NULL); + CallInst::Create(StackChkFail, "", FailBB); + new UnreachableInst(F->getContext(), FailBB); + return FailBB; +} diff --git a/libclamav/c++/llvm/lib/CodeGen/StackSlotColoring.cpp b/libclamav/c++/llvm/lib/CodeGen/StackSlotColoring.cpp new file mode 100644 index 000000000..c299192b2 --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/StackSlotColoring.cpp @@ -0,0 +1,745 @@ +//===-- StackSlotColoring.cpp - Stack slot coloring pass. -----------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the stack slot coloring pass. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "stackcoloring" +#include "VirtRegMap.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/CodeGen/LiveIntervalAnalysis.h" +#include "llvm/CodeGen/LiveStackAnalysis.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineLoopInfo.h" +#include "llvm/CodeGen/MachineMemOperand.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/PseudoSourceValue.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/ADT/BitVector.h" +#include "llvm/ADT/SmallSet.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/Statistic.h" +#include +using namespace llvm; + +static cl::opt +DisableSharing("no-stack-slot-sharing", + cl::init(false), cl::Hidden, + cl::desc("Suppress slot sharing during stack coloring")); + +static cl::opt +ColorWithRegsOpt("color-ss-with-regs", + cl::init(false), cl::Hidden, + cl::desc("Color stack slots with free registers")); + + +static cl::opt DCELimit("ssc-dce-limit", cl::init(-1), cl::Hidden); + +STATISTIC(NumEliminated, "Number of stack slots eliminated due to coloring"); +STATISTIC(NumRegRepl, "Number of stack slot refs replaced with reg refs"); +STATISTIC(NumLoadElim, "Number of loads eliminated"); +STATISTIC(NumStoreElim, "Number of stores eliminated"); +STATISTIC(NumDead, "Number of trivially dead stack accesses eliminated"); + +namespace { + class StackSlotColoring : public MachineFunctionPass { + bool ColorWithRegs; + LiveStacks* LS; + VirtRegMap* VRM; + MachineFrameInfo *MFI; + MachineRegisterInfo *MRI; + const TargetInstrInfo *TII; + const TargetRegisterInfo *TRI; + const MachineLoopInfo *loopInfo; + + // SSIntervals - Spill slot intervals. + std::vector SSIntervals; + + // SSRefs - Keep a list of frame index references for each spill slot. + SmallVector, 16> SSRefs; + + // OrigAlignments - Alignments of stack objects before coloring. + SmallVector OrigAlignments; + + // OrigSizes - Sizess of stack objects before coloring. + SmallVector OrigSizes; + + // AllColors - If index is set, it's a spill slot, i.e. color. + // FIXME: This assumes PEI locate spill slot with smaller indices + // closest to stack pointer / frame pointer. Therefore, smaller + // index == better color. + BitVector AllColors; + + // NextColor - Next "color" that's not yet used. + int NextColor; + + // UsedColors - "Colors" that have been assigned. + BitVector UsedColors; + + // Assignments - Color to intervals mapping. + SmallVector, 16> Assignments; + + public: + static char ID; // Pass identification + StackSlotColoring() : + MachineFunctionPass(&ID), ColorWithRegs(false), NextColor(-1) {} + StackSlotColoring(bool RegColor) : + MachineFunctionPass(&ID), ColorWithRegs(RegColor), NextColor(-1) {} + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesCFG(); + AU.addRequired(); + AU.addPreserved(); + AU.addRequired(); + AU.addRequired(); + AU.addPreserved(); + AU.addRequired(); + AU.addPreserved(); + AU.addPreservedID(MachineDominatorsID); + MachineFunctionPass::getAnalysisUsage(AU); + } + + virtual bool runOnMachineFunction(MachineFunction &MF); + virtual const char* getPassName() const { + return "Stack Slot Coloring"; + } + + private: + void InitializeSlots(); + void ScanForSpillSlotRefs(MachineFunction &MF); + bool OverlapWithAssignments(LiveInterval *li, int Color) const; + int ColorSlot(LiveInterval *li); + bool ColorSlots(MachineFunction &MF); + bool ColorSlotsWithFreeRegs(SmallVector &SlotMapping, + SmallVector, 16> &RevMap, + BitVector &SlotIsReg); + void RewriteInstruction(MachineInstr *MI, int OldFI, int NewFI, + MachineFunction &MF); + bool PropagateBackward(MachineBasicBlock::iterator MII, + MachineBasicBlock *MBB, + unsigned OldReg, unsigned NewReg); + bool PropagateForward(MachineBasicBlock::iterator MII, + MachineBasicBlock *MBB, + unsigned OldReg, unsigned NewReg); + void UnfoldAndRewriteInstruction(MachineInstr *MI, int OldFI, + unsigned Reg, const TargetRegisterClass *RC, + SmallSet &Defs, + MachineFunction &MF); + bool AllMemRefsCanBeUnfolded(int SS); + bool RemoveDeadStores(MachineBasicBlock* MBB); + }; +} // end anonymous namespace + +char StackSlotColoring::ID = 0; + +static RegisterPass +X("stack-slot-coloring", "Stack Slot Coloring"); + +FunctionPass *llvm::createStackSlotColoringPass(bool RegColor) { + return new StackSlotColoring(RegColor); +} + +namespace { + // IntervalSorter - Comparison predicate that sort live intervals by + // their weight. + struct IntervalSorter { + bool operator()(LiveInterval* LHS, LiveInterval* RHS) const { + return LHS->weight > RHS->weight; + } + }; +} + +/// ScanForSpillSlotRefs - Scan all the machine instructions for spill slot +/// references and update spill slot weights. +void StackSlotColoring::ScanForSpillSlotRefs(MachineFunction &MF) { + SSRefs.resize(MFI->getObjectIndexEnd()); + + // FIXME: Need the equivalent of MachineRegisterInfo for frameindex operands. + for (MachineFunction::iterator MBBI = MF.begin(), E = MF.end(); + MBBI != E; ++MBBI) { + MachineBasicBlock *MBB = &*MBBI; + unsigned loopDepth = loopInfo->getLoopDepth(MBB); + for (MachineBasicBlock::iterator MII = MBB->begin(), EE = MBB->end(); + MII != EE; ++MII) { + MachineInstr *MI = &*MII; + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + MachineOperand &MO = MI->getOperand(i); + if (!MO.isFI()) + continue; + int FI = MO.getIndex(); + if (FI < 0) + continue; + if (!LS->hasInterval(FI)) + continue; + LiveInterval &li = LS->getInterval(FI); + li.weight += LiveIntervals::getSpillWeight(false, true, loopDepth); + SSRefs[FI].push_back(MI); + } + } + } +} + +/// InitializeSlots - Process all spill stack slot liveintervals and add them +/// to a sorted (by weight) list. +void StackSlotColoring::InitializeSlots() { + int LastFI = MFI->getObjectIndexEnd(); + OrigAlignments.resize(LastFI); + OrigSizes.resize(LastFI); + AllColors.resize(LastFI); + UsedColors.resize(LastFI); + Assignments.resize(LastFI); + + // Gather all spill slots into a list. + DEBUG(errs() << "Spill slot intervals:\n"); + for (LiveStacks::iterator i = LS->begin(), e = LS->end(); i != e; ++i) { + LiveInterval &li = i->second; + DEBUG(li.dump()); + int FI = li.getStackSlotIndex(); + if (MFI->isDeadObjectIndex(FI)) + continue; + SSIntervals.push_back(&li); + OrigAlignments[FI] = MFI->getObjectAlignment(FI); + OrigSizes[FI] = MFI->getObjectSize(FI); + AllColors.set(FI); + } + DEBUG(errs() << '\n'); + + // Sort them by weight. + std::stable_sort(SSIntervals.begin(), SSIntervals.end(), IntervalSorter()); + + // Get first "color". + NextColor = AllColors.find_first(); +} + +/// OverlapWithAssignments - Return true if LiveInterval overlaps with any +/// LiveIntervals that have already been assigned to the specified color. +bool +StackSlotColoring::OverlapWithAssignments(LiveInterval *li, int Color) const { + const SmallVector &OtherLIs = Assignments[Color]; + for (unsigned i = 0, e = OtherLIs.size(); i != e; ++i) { + LiveInterval *OtherLI = OtherLIs[i]; + if (OtherLI->overlaps(*li)) + return true; + } + return false; +} + +/// ColorSlotsWithFreeRegs - If there are any free registers available, try +/// replacing spill slots references with registers instead. +bool +StackSlotColoring::ColorSlotsWithFreeRegs(SmallVector &SlotMapping, + SmallVector, 16> &RevMap, + BitVector &SlotIsReg) { + if (!(ColorWithRegs || ColorWithRegsOpt) || !VRM->HasUnusedRegisters()) + return false; + + bool Changed = false; + DEBUG(errs() << "Assigning unused registers to spill slots:\n"); + for (unsigned i = 0, e = SSIntervals.size(); i != e; ++i) { + LiveInterval *li = SSIntervals[i]; + int SS = li->getStackSlotIndex(); + if (!UsedColors[SS] || li->weight < 20) + // If the weight is < 20, i.e. two references in a loop with depth 1, + // don't bother with it. + continue; + + // These slots allow to share the same registers. + bool AllColored = true; + SmallVector ColoredRegs; + for (unsigned j = 0, ee = RevMap[SS].size(); j != ee; ++j) { + int RSS = RevMap[SS][j]; + const TargetRegisterClass *RC = LS->getIntervalRegClass(RSS); + // If it's not colored to another stack slot, try coloring it + // to a "free" register. + if (!RC) { + AllColored = false; + continue; + } + unsigned Reg = VRM->getFirstUnusedRegister(RC); + if (!Reg) { + AllColored = false; + continue; + } + if (!AllMemRefsCanBeUnfolded(RSS)) { + AllColored = false; + continue; + } else { + DEBUG(errs() << "Assigning fi#" << RSS << " to " + << TRI->getName(Reg) << '\n'); + ColoredRegs.push_back(Reg); + SlotMapping[RSS] = Reg; + SlotIsReg.set(RSS); + Changed = true; + } + } + + // Register and its sub-registers are no longer free. + while (!ColoredRegs.empty()) { + unsigned Reg = ColoredRegs.back(); + ColoredRegs.pop_back(); + VRM->setRegisterUsed(Reg); + // If reg is a callee-saved register, it will have to be spilled in + // the prologue. + MRI->setPhysRegUsed(Reg); + for (const unsigned *AS = TRI->getAliasSet(Reg); *AS; ++AS) { + VRM->setRegisterUsed(*AS); + MRI->setPhysRegUsed(*AS); + } + } + // This spill slot is dead after the rewrites + if (AllColored) { + MFI->RemoveStackObject(SS); + ++NumEliminated; + } + } + DEBUG(errs() << '\n'); + + return Changed; +} + +/// ColorSlot - Assign a "color" (stack slot) to the specified stack slot. +/// +int StackSlotColoring::ColorSlot(LiveInterval *li) { + int Color = -1; + bool Share = false; + if (!DisableSharing) { + // Check if it's possible to reuse any of the used colors. + Color = UsedColors.find_first(); + while (Color != -1) { + if (!OverlapWithAssignments(li, Color)) { + Share = true; + ++NumEliminated; + break; + } + Color = UsedColors.find_next(Color); + } + } + + // Assign it to the first available color (assumed to be the best) if it's + // not possible to share a used color with other objects. + if (!Share) { + assert(NextColor != -1 && "No more spill slots?"); + Color = NextColor; + UsedColors.set(Color); + NextColor = AllColors.find_next(NextColor); + } + + // Record the assignment. + Assignments[Color].push_back(li); + int FI = li->getStackSlotIndex(); + DEBUG(errs() << "Assigning fi#" << FI << " to fi#" << Color << "\n"); + + // Change size and alignment of the allocated slot. If there are multiple + // objects sharing the same slot, then make sure the size and alignment + // are large enough for all. + unsigned Align = OrigAlignments[FI]; + if (!Share || Align > MFI->getObjectAlignment(Color)) + MFI->setObjectAlignment(Color, Align); + int64_t Size = OrigSizes[FI]; + if (!Share || Size > MFI->getObjectSize(Color)) + MFI->setObjectSize(Color, Size); + return Color; +} + +/// Colorslots - Color all spill stack slots and rewrite all frameindex machine +/// operands in the function. +bool StackSlotColoring::ColorSlots(MachineFunction &MF) { + unsigned NumObjs = MFI->getObjectIndexEnd(); + SmallVector SlotMapping(NumObjs, -1); + SmallVector SlotWeights(NumObjs, 0.0); + SmallVector, 16> RevMap(NumObjs); + BitVector SlotIsReg(NumObjs); + BitVector UsedColors(NumObjs); + + DEBUG(errs() << "Color spill slot intervals:\n"); + bool Changed = false; + for (unsigned i = 0, e = SSIntervals.size(); i != e; ++i) { + LiveInterval *li = SSIntervals[i]; + int SS = li->getStackSlotIndex(); + int NewSS = ColorSlot(li); + assert(NewSS >= 0 && "Stack coloring failed?"); + SlotMapping[SS] = NewSS; + RevMap[NewSS].push_back(SS); + SlotWeights[NewSS] += li->weight; + UsedColors.set(NewSS); + Changed |= (SS != NewSS); + } + + DEBUG(errs() << "\nSpill slots after coloring:\n"); + for (unsigned i = 0, e = SSIntervals.size(); i != e; ++i) { + LiveInterval *li = SSIntervals[i]; + int SS = li->getStackSlotIndex(); + li->weight = SlotWeights[SS]; + } + // Sort them by new weight. + std::stable_sort(SSIntervals.begin(), SSIntervals.end(), IntervalSorter()); + +#ifndef NDEBUG + for (unsigned i = 0, e = SSIntervals.size(); i != e; ++i) + DEBUG(SSIntervals[i]->dump()); + DEBUG(errs() << '\n'); +#endif + + // Can we "color" a stack slot with a unused register? + Changed |= ColorSlotsWithFreeRegs(SlotMapping, RevMap, SlotIsReg); + + if (!Changed) + return false; + + // Rewrite all MO_FrameIndex operands. + SmallVector, 4> NewDefs(MF.getNumBlockIDs()); + for (unsigned SS = 0, SE = SSRefs.size(); SS != SE; ++SS) { + bool isReg = SlotIsReg[SS]; + int NewFI = SlotMapping[SS]; + if (NewFI == -1 || (NewFI == (int)SS && !isReg)) + continue; + + const TargetRegisterClass *RC = LS->getIntervalRegClass(SS); + SmallVector &RefMIs = SSRefs[SS]; + for (unsigned i = 0, e = RefMIs.size(); i != e; ++i) + if (!isReg) + RewriteInstruction(RefMIs[i], SS, NewFI, MF); + else { + // Rewrite to use a register instead. + unsigned MBBId = RefMIs[i]->getParent()->getNumber(); + SmallSet &Defs = NewDefs[MBBId]; + UnfoldAndRewriteInstruction(RefMIs[i], SS, NewFI, RC, Defs, MF); + } + } + + // Delete unused stack slots. + while (NextColor != -1) { + DEBUG(errs() << "Removing unused stack object fi#" << NextColor << "\n"); + MFI->RemoveStackObject(NextColor); + NextColor = AllColors.find_next(NextColor); + } + + return true; +} + +/// AllMemRefsCanBeUnfolded - Return true if all references of the specified +/// spill slot index can be unfolded. +bool StackSlotColoring::AllMemRefsCanBeUnfolded(int SS) { + SmallVector &RefMIs = SSRefs[SS]; + for (unsigned i = 0, e = RefMIs.size(); i != e; ++i) { + MachineInstr *MI = RefMIs[i]; + if (TII->isLoadFromStackSlot(MI, SS) || + TII->isStoreToStackSlot(MI, SS)) + // Restore and spill will become copies. + return true; + if (!TII->getOpcodeAfterMemoryUnfold(MI->getOpcode(), false, false)) + return false; + for (unsigned j = 0, ee = MI->getNumOperands(); j != ee; ++j) { + MachineOperand &MO = MI->getOperand(j); + if (MO.isFI() && MO.getIndex() != SS) + // If it uses another frameindex, we can, currently* unfold it. + return false; + } + } + return true; +} + +/// RewriteInstruction - Rewrite specified instruction by replacing references +/// to old frame index with new one. +void StackSlotColoring::RewriteInstruction(MachineInstr *MI, int OldFI, + int NewFI, MachineFunction &MF) { + // Update the operands. + for (unsigned i = 0, ee = MI->getNumOperands(); i != ee; ++i) { + MachineOperand &MO = MI->getOperand(i); + if (!MO.isFI()) + continue; + int FI = MO.getIndex(); + if (FI != OldFI) + continue; + MO.setIndex(NewFI); + } + + // Update the memory references. This changes the MachineMemOperands + // directly. They may be in use by multiple instructions, however all + // instructions using OldFI are being rewritten to use NewFI. + const Value *OldSV = PseudoSourceValue::getFixedStack(OldFI); + const Value *NewSV = PseudoSourceValue::getFixedStack(NewFI); + for (MachineInstr::mmo_iterator I = MI->memoperands_begin(), + E = MI->memoperands_end(); I != E; ++I) + if ((*I)->getValue() == OldSV) + (*I)->setValue(NewSV); +} + +/// PropagateBackward - Traverse backward and look for the definition of +/// OldReg. If it can successfully update all of the references with NewReg, +/// do so and return true. +bool StackSlotColoring::PropagateBackward(MachineBasicBlock::iterator MII, + MachineBasicBlock *MBB, + unsigned OldReg, unsigned NewReg) { + if (MII == MBB->begin()) + return false; + + SmallVector Uses; + SmallVector Refs; + while (--MII != MBB->begin()) { + bool FoundDef = false; // Not counting 2address def. + + Uses.clear(); + const TargetInstrDesc &TID = MII->getDesc(); + for (unsigned i = 0, e = MII->getNumOperands(); i != e; ++i) { + MachineOperand &MO = MII->getOperand(i); + if (!MO.isReg()) + continue; + unsigned Reg = MO.getReg(); + if (Reg == 0) + continue; + if (Reg == OldReg) { + if (MO.isImplicit()) + return false; + + // Abort the use is actually a sub-register def. We don't have enough + // information to figure out if it is really legal. + if (MO.getSubReg() || + TID.getOpcode() == TargetInstrInfo::EXTRACT_SUBREG || + TID.getOpcode() == TargetInstrInfo::INSERT_SUBREG || + TID.getOpcode() == TargetInstrInfo::SUBREG_TO_REG) + return false; + + const TargetRegisterClass *RC = TID.OpInfo[i].getRegClass(TRI); + if (RC && !RC->contains(NewReg)) + return false; + + if (MO.isUse()) { + Uses.push_back(&MO); + } else { + Refs.push_back(&MO); + if (!MII->isRegTiedToUseOperand(i)) + FoundDef = true; + } + } else if (TRI->regsOverlap(Reg, NewReg)) { + return false; + } else if (TRI->regsOverlap(Reg, OldReg)) { + if (!MO.isUse() || !MO.isKill()) + return false; + } + } + + if (FoundDef) { + // Found non-two-address def. Stop here. + for (unsigned i = 0, e = Refs.size(); i != e; ++i) + Refs[i]->setReg(NewReg); + return true; + } + + // Two-address uses must be updated as well. + for (unsigned i = 0, e = Uses.size(); i != e; ++i) + Refs.push_back(Uses[i]); + } + return false; +} + +/// PropagateForward - Traverse forward and look for the kill of OldReg. If +/// it can successfully update all of the uses with NewReg, do so and +/// return true. +bool StackSlotColoring::PropagateForward(MachineBasicBlock::iterator MII, + MachineBasicBlock *MBB, + unsigned OldReg, unsigned NewReg) { + if (MII == MBB->end()) + return false; + + SmallVector Uses; + while (++MII != MBB->end()) { + bool FoundKill = false; + const TargetInstrDesc &TID = MII->getDesc(); + for (unsigned i = 0, e = MII->getNumOperands(); i != e; ++i) { + MachineOperand &MO = MII->getOperand(i); + if (!MO.isReg()) + continue; + unsigned Reg = MO.getReg(); + if (Reg == 0) + continue; + if (Reg == OldReg) { + if (MO.isDef() || MO.isImplicit()) + return false; + + // Abort the use is actually a sub-register use. We don't have enough + // information to figure out if it is really legal. + if (MO.getSubReg() || + TID.getOpcode() == TargetInstrInfo::EXTRACT_SUBREG) + return false; + + const TargetRegisterClass *RC = TID.OpInfo[i].getRegClass(TRI); + if (RC && !RC->contains(NewReg)) + return false; + if (MO.isKill()) + FoundKill = true; + + Uses.push_back(&MO); + } else if (TRI->regsOverlap(Reg, NewReg) || + TRI->regsOverlap(Reg, OldReg)) + return false; + } + if (FoundKill) { + for (unsigned i = 0, e = Uses.size(); i != e; ++i) + Uses[i]->setReg(NewReg); + return true; + } + } + return false; +} + +/// UnfoldAndRewriteInstruction - Rewrite specified instruction by unfolding +/// folded memory references and replacing those references with register +/// references instead. +void +StackSlotColoring::UnfoldAndRewriteInstruction(MachineInstr *MI, int OldFI, + unsigned Reg, + const TargetRegisterClass *RC, + SmallSet &Defs, + MachineFunction &MF) { + MachineBasicBlock *MBB = MI->getParent(); + if (unsigned DstReg = TII->isLoadFromStackSlot(MI, OldFI)) { + if (PropagateForward(MI, MBB, DstReg, Reg)) { + DEBUG(errs() << "Eliminated load: "); + DEBUG(MI->dump()); + ++NumLoadElim; + } else { + TII->copyRegToReg(*MBB, MI, DstReg, Reg, RC, RC); + ++NumRegRepl; + } + + if (!Defs.count(Reg)) { + // If this is the first use of Reg in this MBB and it wasn't previously + // defined in MBB, add it to livein. + MBB->addLiveIn(Reg); + Defs.insert(Reg); + } + } else if (unsigned SrcReg = TII->isStoreToStackSlot(MI, OldFI)) { + if (MI->killsRegister(SrcReg) && PropagateBackward(MI, MBB, SrcReg, Reg)) { + DEBUG(errs() << "Eliminated store: "); + DEBUG(MI->dump()); + ++NumStoreElim; + } else { + TII->copyRegToReg(*MBB, MI, Reg, SrcReg, RC, RC); + ++NumRegRepl; + } + + // Remember reg has been defined in MBB. + Defs.insert(Reg); + } else { + SmallVector NewMIs; + bool Success = TII->unfoldMemoryOperand(MF, MI, Reg, false, false, NewMIs); + Success = Success; // Silence compiler warning. + assert(Success && "Failed to unfold!"); + MachineInstr *NewMI = NewMIs[0]; + MBB->insert(MI, NewMI); + ++NumRegRepl; + + if (NewMI->readsRegister(Reg)) { + if (!Defs.count(Reg)) + // If this is the first use of Reg in this MBB and it wasn't previously + // defined in MBB, add it to livein. + MBB->addLiveIn(Reg); + Defs.insert(Reg); + } + } + MBB->erase(MI); +} + +/// RemoveDeadStores - Scan through a basic block and look for loads followed +/// by stores. If they're both using the same stack slot, then the store is +/// definitely dead. This could obviously be much more aggressive (consider +/// pairs with instructions between them), but such extensions might have a +/// considerable compile time impact. +bool StackSlotColoring::RemoveDeadStores(MachineBasicBlock* MBB) { + // FIXME: This could be much more aggressive, but we need to investigate + // the compile time impact of doing so. + bool changed = false; + + SmallVector toErase; + + for (MachineBasicBlock::iterator I = MBB->begin(), E = MBB->end(); + I != E; ++I) { + if (DCELimit != -1 && (int)NumDead >= DCELimit) + break; + + MachineBasicBlock::iterator NextMI = next(I); + if (NextMI == MBB->end()) continue; + + int FirstSS, SecondSS; + unsigned LoadReg = 0; + unsigned StoreReg = 0; + if (!(LoadReg = TII->isLoadFromStackSlot(I, FirstSS))) continue; + if (!(StoreReg = TII->isStoreToStackSlot(NextMI, SecondSS))) continue; + if (FirstSS != SecondSS || LoadReg != StoreReg || FirstSS == -1) continue; + + ++NumDead; + changed = true; + + if (NextMI->findRegisterUseOperandIdx(LoadReg, true, 0) != -1) { + ++NumDead; + toErase.push_back(I); + } + + toErase.push_back(NextMI); + ++I; + } + + for (SmallVector::iterator I = toErase.begin(), + E = toErase.end(); I != E; ++I) + (*I)->eraseFromParent(); + + return changed; +} + + +bool StackSlotColoring::runOnMachineFunction(MachineFunction &MF) { + DEBUG(errs() << "********** Stack Slot Coloring **********\n"); + + MFI = MF.getFrameInfo(); + MRI = &MF.getRegInfo(); + TII = MF.getTarget().getInstrInfo(); + TRI = MF.getTarget().getRegisterInfo(); + LS = &getAnalysis(); + VRM = &getAnalysis(); + loopInfo = &getAnalysis(); + + bool Changed = false; + + unsigned NumSlots = LS->getNumIntervals(); + if (NumSlots < 2) { + if (NumSlots == 0 || !VRM->HasUnusedRegisters()) + // Nothing to do! + return false; + } + + // Gather spill slot references + ScanForSpillSlotRefs(MF); + InitializeSlots(); + Changed = ColorSlots(MF); + + NextColor = -1; + SSIntervals.clear(); + for (unsigned i = 0, e = SSRefs.size(); i != e; ++i) + SSRefs[i].clear(); + SSRefs.clear(); + OrigAlignments.clear(); + OrigSizes.clear(); + AllColors.clear(); + UsedColors.clear(); + for (unsigned i = 0, e = Assignments.size(); i != e; ++i) + Assignments[i].clear(); + Assignments.clear(); + + if (Changed) { + for (MachineFunction::iterator I = MF.begin(), E = MF.end(); I != E; ++I) + Changed |= RemoveDeadStores(I); + } + + return Changed; +} diff --git a/libclamav/c++/llvm/lib/CodeGen/StrongPHIElimination.cpp b/libclamav/c++/llvm/lib/CodeGen/StrongPHIElimination.cpp new file mode 100644 index 000000000..3c139068e --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/StrongPHIElimination.cpp @@ -0,0 +1,1051 @@ +//===- StrongPhiElimination.cpp - Eliminate PHI nodes by inserting copies -===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This pass eliminates machine instruction PHI nodes by inserting copy +// instructions, using an intelligent copy-folding technique based on +// dominator information. This is technique is derived from: +// +// Budimlic, et al. Fast copy coalescing and live-range identification. +// In Proceedings of the ACM SIGPLAN 2002 Conference on Programming Language +// Design and Implementation (Berlin, Germany, June 17 - 19, 2002). +// PLDI '02. ACM, New York, NY, 25-32. +// DOI= http://doi.acm.org/10.1145/512529.512534 +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "strongphielim" +#include "llvm/CodeGen/Passes.h" +#include "llvm/CodeGen/LiveIntervalAnalysis.h" +#include "llvm/CodeGen/MachineDominators.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/CodeGen/MachineLoopInfo.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/RegisterCoalescer.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/ADT/DepthFirstIterator.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/Support/Debug.h" +using namespace llvm; + +namespace { + struct StrongPHIElimination : public MachineFunctionPass { + static char ID; // Pass identification, replacement for typeid + StrongPHIElimination() : MachineFunctionPass(&ID) {} + + // Waiting stores, for each MBB, the set of copies that need to + // be inserted into that MBB + DenseMap > Waiting; + + // Stacks holds the renaming stack for each register + std::map > Stacks; + + // Registers in UsedByAnother are PHI nodes that are themselves + // used as operands to another another PHI node + std::set UsedByAnother; + + // RenameSets are the is a map from a PHI-defined register + // to the input registers to be coalesced along with the + // predecessor block for those input registers. + std::map > RenameSets; + + // PhiValueNumber holds the ID numbers of the VNs for each phi that we're + // eliminating, indexed by the register defined by that phi. + std::map PhiValueNumber; + + // Store the DFS-in number of each block + DenseMap preorder; + + // Store the DFS-out number of each block + DenseMap maxpreorder; + + bool runOnMachineFunction(MachineFunction &Fn); + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesCFG(); + AU.addRequired(); + AU.addRequired(); + AU.addPreserved(); + AU.addRequired(); + + // TODO: Actually make this true. + AU.addPreserved(); + AU.addPreserved(); + MachineFunctionPass::getAnalysisUsage(AU); + } + + virtual void releaseMemory() { + preorder.clear(); + maxpreorder.clear(); + + Waiting.clear(); + Stacks.clear(); + UsedByAnother.clear(); + RenameSets.clear(); + } + + private: + + /// DomForestNode - Represents a node in the "dominator forest". This is + /// a forest in which the nodes represent registers and the edges + /// represent a dominance relation in the block defining those registers. + struct DomForestNode { + private: + // Store references to our children + std::vector children; + // The register we represent + unsigned reg; + + // Add another node as our child + void addChild(DomForestNode* DFN) { children.push_back(DFN); } + + public: + typedef std::vector::iterator iterator; + + // Create a DomForestNode by providing the register it represents, and + // the node to be its parent. The virtual root node has register 0 + // and a null parent. + DomForestNode(unsigned r, DomForestNode* parent) : reg(r) { + if (parent) + parent->addChild(this); + } + + ~DomForestNode() { + for (iterator I = begin(), E = end(); I != E; ++I) + delete *I; + } + + /// getReg - Return the regiser that this node represents + inline unsigned getReg() { return reg; } + + // Provide iterator access to our children + inline DomForestNode::iterator begin() { return children.begin(); } + inline DomForestNode::iterator end() { return children.end(); } + }; + + void computeDFS(MachineFunction& MF); + void processBlock(MachineBasicBlock* MBB); + + std::vector computeDomForest( + std::map& instrs, + MachineRegisterInfo& MRI); + void processPHIUnion(MachineInstr* Inst, + std::map& PHIUnion, + std::vector& DF, + std::vector >& locals); + void ScheduleCopies(MachineBasicBlock* MBB, std::set& pushed); + void InsertCopies(MachineDomTreeNode* MBB, + SmallPtrSet& v); + bool mergeLiveIntervals(unsigned primary, unsigned secondary); + }; +} + +char StrongPHIElimination::ID = 0; +static RegisterPass +X("strong-phi-node-elimination", + "Eliminate PHI nodes for register allocation, intelligently"); + +const PassInfo *const llvm::StrongPHIEliminationID = &X; + +/// computeDFS - Computes the DFS-in and DFS-out numbers of the dominator tree +/// of the given MachineFunction. These numbers are then used in other parts +/// of the PHI elimination process. +void StrongPHIElimination::computeDFS(MachineFunction& MF) { + SmallPtrSet frontier; + SmallPtrSet visited; + + unsigned time = 0; + + MachineDominatorTree& DT = getAnalysis(); + + MachineDomTreeNode* node = DT.getRootNode(); + + std::vector worklist; + worklist.push_back(node); + + while (!worklist.empty()) { + MachineDomTreeNode* currNode = worklist.back(); + + if (!frontier.count(currNode)) { + frontier.insert(currNode); + ++time; + preorder.insert(std::make_pair(currNode->getBlock(), time)); + } + + bool inserted = false; + for (MachineDomTreeNode::iterator I = currNode->begin(), E = currNode->end(); + I != E; ++I) + if (!frontier.count(*I) && !visited.count(*I)) { + worklist.push_back(*I); + inserted = true; + break; + } + + if (!inserted) { + frontier.erase(currNode); + visited.insert(currNode); + maxpreorder.insert(std::make_pair(currNode->getBlock(), time)); + + worklist.pop_back(); + } + } +} + +namespace { + +/// PreorderSorter - a helper class that is used to sort registers +/// according to the preorder number of their defining blocks +class PreorderSorter { +private: + DenseMap& preorder; + MachineRegisterInfo& MRI; + +public: + PreorderSorter(DenseMap& p, + MachineRegisterInfo& M) : preorder(p), MRI(M) { } + + bool operator()(unsigned A, unsigned B) { + if (A == B) + return false; + + MachineBasicBlock* ABlock = MRI.getVRegDef(A)->getParent(); + MachineBasicBlock* BBlock = MRI.getVRegDef(B)->getParent(); + + if (preorder[ABlock] < preorder[BBlock]) + return true; + else if (preorder[ABlock] > preorder[BBlock]) + return false; + + return false; + } +}; + +} + +/// computeDomForest - compute the subforest of the DomTree corresponding +/// to the defining blocks of the registers in question +std::vector +StrongPHIElimination::computeDomForest( + std::map& regs, + MachineRegisterInfo& MRI) { + // Begin by creating a virtual root node, since the actual results + // may well be a forest. Assume this node has maximum DFS-out number. + DomForestNode* VirtualRoot = new DomForestNode(0, 0); + maxpreorder.insert(std::make_pair((MachineBasicBlock*)0, ~0UL)); + + // Populate a worklist with the registers + std::vector worklist; + worklist.reserve(regs.size()); + for (std::map::iterator I = regs.begin(), + E = regs.end(); I != E; ++I) + worklist.push_back(I->first); + + // Sort the registers by the DFS-in number of their defining block + PreorderSorter PS(preorder, MRI); + std::sort(worklist.begin(), worklist.end(), PS); + + // Create a "current parent" stack, and put the virtual root on top of it + DomForestNode* CurrentParent = VirtualRoot; + std::vector stack; + stack.push_back(VirtualRoot); + + // Iterate over all the registers in the previously computed order + for (std::vector::iterator I = worklist.begin(), E = worklist.end(); + I != E; ++I) { + unsigned pre = preorder[MRI.getVRegDef(*I)->getParent()]; + MachineBasicBlock* parentBlock = CurrentParent->getReg() ? + MRI.getVRegDef(CurrentParent->getReg())->getParent() : + 0; + + // If the DFS-in number of the register is greater than the DFS-out number + // of the current parent, repeatedly pop the parent stack until it isn't. + while (pre > maxpreorder[parentBlock]) { + stack.pop_back(); + CurrentParent = stack.back(); + + parentBlock = CurrentParent->getReg() ? + MRI.getVRegDef(CurrentParent->getReg())->getParent() : + 0; + } + + // Now that we've found the appropriate parent, create a DomForestNode for + // this register and attach it to the forest + DomForestNode* child = new DomForestNode(*I, CurrentParent); + + // Push this new node on the "current parent" stack + stack.push_back(child); + CurrentParent = child; + } + + // Return a vector containing the children of the virtual root node + std::vector ret; + ret.insert(ret.end(), VirtualRoot->begin(), VirtualRoot->end()); + return ret; +} + +/// isLiveIn - helper method that determines, from a regno, if a register +/// is live into a block +static bool isLiveIn(unsigned r, MachineBasicBlock* MBB, + LiveIntervals& LI) { + LiveInterval& I = LI.getOrCreateInterval(r); + SlotIndex idx = LI.getMBBStartIdx(MBB); + return I.liveAt(idx); +} + +/// isLiveOut - help method that determines, from a regno, if a register is +/// live out of a block. +static bool isLiveOut(unsigned r, MachineBasicBlock* MBB, + LiveIntervals& LI) { + for (MachineBasicBlock::succ_iterator PI = MBB->succ_begin(), + E = MBB->succ_end(); PI != E; ++PI) + if (isLiveIn(r, *PI, LI)) + return true; + + return false; +} + +/// interferes - checks for local interferences by scanning a block. The only +/// trick parameter is 'mode' which tells it the relationship of the two +/// registers. 0 - defined in the same block, 1 - first properly dominates +/// second, 2 - second properly dominates first +static bool interferes(unsigned a, unsigned b, MachineBasicBlock* scan, + LiveIntervals& LV, unsigned mode) { + MachineInstr* def = 0; + MachineInstr* kill = 0; + + // The code is still in SSA form at this point, so there is only one + // definition per VReg. Thus we can safely use MRI->getVRegDef(). + const MachineRegisterInfo* MRI = &scan->getParent()->getRegInfo(); + + bool interference = false; + + // Wallk the block, checking for interferences + for (MachineBasicBlock::iterator MBI = scan->begin(), MBE = scan->end(); + MBI != MBE; ++MBI) { + MachineInstr* curr = MBI; + + // Same defining block... + if (mode == 0) { + if (curr == MRI->getVRegDef(a)) { + // If we find our first definition, save it + if (!def) { + def = curr; + // If there's already an unkilled definition, then + // this is an interference + } else if (!kill) { + interference = true; + break; + // If there's a definition followed by a KillInst, then + // they can't interfere + } else { + interference = false; + break; + } + // Symmetric with the above + } else if (curr == MRI->getVRegDef(b)) { + if (!def) { + def = curr; + } else if (!kill) { + interference = true; + break; + } else { + interference = false; + break; + } + // Store KillInsts if they match up with the definition + } else if (curr->killsRegister(a)) { + if (def == MRI->getVRegDef(a)) { + kill = curr; + } else if (curr->killsRegister(b)) { + if (def == MRI->getVRegDef(b)) { + kill = curr; + } + } + } + // First properly dominates second... + } else if (mode == 1) { + if (curr == MRI->getVRegDef(b)) { + // Definition of second without kill of first is an interference + if (!kill) { + interference = true; + break; + // Definition after a kill is a non-interference + } else { + interference = false; + break; + } + // Save KillInsts of First + } else if (curr->killsRegister(a)) { + kill = curr; + } + // Symmetric with the above + } else if (mode == 2) { + if (curr == MRI->getVRegDef(a)) { + if (!kill) { + interference = true; + break; + } else { + interference = false; + break; + } + } else if (curr->killsRegister(b)) { + kill = curr; + } + } + } + + return interference; +} + +/// processBlock - Determine how to break up PHIs in the current block. Each +/// PHI is broken up by some combination of renaming its operands and inserting +/// copies. This method is responsible for determining which operands receive +/// which treatment. +void StrongPHIElimination::processBlock(MachineBasicBlock* MBB) { + LiveIntervals& LI = getAnalysis(); + MachineRegisterInfo& MRI = MBB->getParent()->getRegInfo(); + + // Holds names that have been added to a set in any PHI within this block + // before the current one. + std::set ProcessedNames; + + // Iterate over all the PHI nodes in this block + MachineBasicBlock::iterator P = MBB->begin(); + while (P != MBB->end() && P->getOpcode() == TargetInstrInfo::PHI) { + unsigned DestReg = P->getOperand(0).getReg(); + + // Don't both doing PHI elimination for dead PHI's. + if (P->registerDefIsDead(DestReg)) { + ++P; + continue; + } + + LiveInterval& PI = LI.getOrCreateInterval(DestReg); + SlotIndex pIdx = LI.getInstructionIndex(P).getDefIndex(); + VNInfo* PVN = PI.getLiveRangeContaining(pIdx)->valno; + PhiValueNumber.insert(std::make_pair(DestReg, PVN->id)); + + // PHIUnion is the set of incoming registers to the PHI node that + // are going to be renames rather than having copies inserted. This set + // is refinded over the course of this function. UnionedBlocks is the set + // of corresponding MBBs. + std::map PHIUnion; + SmallPtrSet UnionedBlocks; + + // Iterate over the operands of the PHI node + for (int i = P->getNumOperands() - 1; i >= 2; i-=2) { + unsigned SrcReg = P->getOperand(i-1).getReg(); + + // Don't need to try to coalesce a register with itself. + if (SrcReg == DestReg) { + ProcessedNames.insert(SrcReg); + continue; + } + + // We don't need to insert copies for implicit_defs. + MachineInstr* DefMI = MRI.getVRegDef(SrcReg); + if (DefMI->getOpcode() == TargetInstrInfo::IMPLICIT_DEF) + ProcessedNames.insert(SrcReg); + + // Check for trivial interferences via liveness information, allowing us + // to avoid extra work later. Any registers that interfere cannot both + // be in the renaming set, so choose one and add copies for it instead. + // The conditions are: + // 1) if the operand is live into the PHI node's block OR + // 2) if the PHI node is live out of the operand's defining block OR + // 3) if the operand is itself a PHI node and the original PHI is + // live into the operand's defining block OR + // 4) if the operand is already being renamed for another PHI node + // in this block OR + // 5) if any two operands are defined in the same block, insert copies + // for one of them + if (isLiveIn(SrcReg, P->getParent(), LI) || + isLiveOut(P->getOperand(0).getReg(), + MRI.getVRegDef(SrcReg)->getParent(), LI) || + ( MRI.getVRegDef(SrcReg)->getOpcode() == TargetInstrInfo::PHI && + isLiveIn(P->getOperand(0).getReg(), + MRI.getVRegDef(SrcReg)->getParent(), LI) ) || + ProcessedNames.count(SrcReg) || + UnionedBlocks.count(MRI.getVRegDef(SrcReg)->getParent())) { + + // Add a copy for the selected register + MachineBasicBlock* From = P->getOperand(i).getMBB(); + Waiting[From].insert(std::make_pair(SrcReg, DestReg)); + UsedByAnother.insert(SrcReg); + } else { + // Otherwise, add it to the renaming set + PHIUnion.insert(std::make_pair(SrcReg,P->getOperand(i).getMBB())); + UnionedBlocks.insert(MRI.getVRegDef(SrcReg)->getParent()); + } + } + + // Compute the dominator forest for the renaming set. This is a forest + // where the nodes are the registers and the edges represent dominance + // relations between the defining blocks of the registers + std::vector DF = + computeDomForest(PHIUnion, MRI); + + // Walk DomForest to resolve interferences at an inter-block level. This + // will remove registers from the renaming set (and insert copies for them) + // if interferences are found. + std::vector > localInterferences; + processPHIUnion(P, PHIUnion, DF, localInterferences); + + // If one of the inputs is defined in the same block as the current PHI + // then we need to check for a local interference between that input and + // the PHI. + for (std::map::iterator I = PHIUnion.begin(), + E = PHIUnion.end(); I != E; ++I) + if (MRI.getVRegDef(I->first)->getParent() == P->getParent()) + localInterferences.push_back(std::make_pair(I->first, + P->getOperand(0).getReg())); + + // The dominator forest walk may have returned some register pairs whose + // interference cannot be determined from dominator analysis. We now + // examine these pairs for local interferences. + for (std::vector >::iterator I = + localInterferences.begin(), E = localInterferences.end(); I != E; ++I) { + std::pair p = *I; + + MachineDominatorTree& MDT = getAnalysis(); + + // Determine the block we need to scan and the relationship between + // the two registers + MachineBasicBlock* scan = 0; + unsigned mode = 0; + if (MRI.getVRegDef(p.first)->getParent() == + MRI.getVRegDef(p.second)->getParent()) { + scan = MRI.getVRegDef(p.first)->getParent(); + mode = 0; // Same block + } else if (MDT.dominates(MRI.getVRegDef(p.first)->getParent(), + MRI.getVRegDef(p.second)->getParent())) { + scan = MRI.getVRegDef(p.second)->getParent(); + mode = 1; // First dominates second + } else { + scan = MRI.getVRegDef(p.first)->getParent(); + mode = 2; // Second dominates first + } + + // If there's an interference, we need to insert copies + if (interferes(p.first, p.second, scan, LI, mode)) { + // Insert copies for First + for (int i = P->getNumOperands() - 1; i >= 2; i-=2) { + if (P->getOperand(i-1).getReg() == p.first) { + unsigned SrcReg = p.first; + MachineBasicBlock* From = P->getOperand(i).getMBB(); + + Waiting[From].insert(std::make_pair(SrcReg, + P->getOperand(0).getReg())); + UsedByAnother.insert(SrcReg); + + PHIUnion.erase(SrcReg); + } + } + } + } + + // Add the renaming set for this PHI node to our overall renaming information + for (std::map::iterator QI = PHIUnion.begin(), + QE = PHIUnion.end(); QI != QE; ++QI) { + DEBUG(errs() << "Adding Renaming: " << QI->first << " -> " + << P->getOperand(0).getReg() << "\n"); + } + + RenameSets.insert(std::make_pair(P->getOperand(0).getReg(), PHIUnion)); + + // Remember which registers are already renamed, so that we don't try to + // rename them for another PHI node in this block + for (std::map::iterator I = PHIUnion.begin(), + E = PHIUnion.end(); I != E; ++I) + ProcessedNames.insert(I->first); + + ++P; + } +} + +/// processPHIUnion - Take a set of candidate registers to be coalesced when +/// decomposing the PHI instruction. Use the DominanceForest to remove the ones +/// that are known to interfere, and flag others that need to be checked for +/// local interferences. +void StrongPHIElimination::processPHIUnion(MachineInstr* Inst, + std::map& PHIUnion, + std::vector& DF, + std::vector >& locals) { + + std::vector worklist(DF.begin(), DF.end()); + SmallPtrSet visited; + + // Code is still in SSA form, so we can use MRI::getVRegDef() + MachineRegisterInfo& MRI = Inst->getParent()->getParent()->getRegInfo(); + + LiveIntervals& LI = getAnalysis(); + unsigned DestReg = Inst->getOperand(0).getReg(); + + // DF walk on the DomForest + while (!worklist.empty()) { + DomForestNode* DFNode = worklist.back(); + + visited.insert(DFNode); + + bool inserted = false; + for (DomForestNode::iterator CI = DFNode->begin(), CE = DFNode->end(); + CI != CE; ++CI) { + DomForestNode* child = *CI; + + // If the current node is live-out of the defining block of one of its + // children, insert a copy for it. NOTE: The paper actually calls for + // a more elaborate heuristic for determining whether to insert copies + // for the child or the parent. In the interest of simplicity, we're + // just always choosing the parent. + if (isLiveOut(DFNode->getReg(), + MRI.getVRegDef(child->getReg())->getParent(), LI)) { + // Insert copies for parent + for (int i = Inst->getNumOperands() - 1; i >= 2; i-=2) { + if (Inst->getOperand(i-1).getReg() == DFNode->getReg()) { + unsigned SrcReg = DFNode->getReg(); + MachineBasicBlock* From = Inst->getOperand(i).getMBB(); + + Waiting[From].insert(std::make_pair(SrcReg, DestReg)); + UsedByAnother.insert(SrcReg); + + PHIUnion.erase(SrcReg); + } + } + + // If a node is live-in to the defining block of one of its children, but + // not live-out, then we need to scan that block for local interferences. + } else if (isLiveIn(DFNode->getReg(), + MRI.getVRegDef(child->getReg())->getParent(), LI) || + MRI.getVRegDef(DFNode->getReg())->getParent() == + MRI.getVRegDef(child->getReg())->getParent()) { + // Add (p, c) to possible local interferences + locals.push_back(std::make_pair(DFNode->getReg(), child->getReg())); + } + + if (!visited.count(child)) { + worklist.push_back(child); + inserted = true; + } + } + + if (!inserted) worklist.pop_back(); + } +} + +/// ScheduleCopies - Insert copies into predecessor blocks, scheduling +/// them properly so as to avoid the 'lost copy' and the 'virtual swap' +/// problems. +/// +/// Based on "Practical Improvements to the Construction and Destruction +/// of Static Single Assignment Form" by Briggs, et al. +void StrongPHIElimination::ScheduleCopies(MachineBasicBlock* MBB, + std::set& pushed) { + // FIXME: This function needs to update LiveIntervals + std::multimap& copy_set= Waiting[MBB]; + + std::multimap worklist; + std::map map; + + // Setup worklist of initial copies + for (std::multimap::iterator I = copy_set.begin(), + E = copy_set.end(); I != E; ) { + map.insert(std::make_pair(I->first, I->first)); + map.insert(std::make_pair(I->second, I->second)); + + if (!UsedByAnother.count(I->second)) { + worklist.insert(*I); + + // Avoid iterator invalidation + std::multimap::iterator OI = I; + ++I; + copy_set.erase(OI); + } else { + ++I; + } + } + + LiveIntervals& LI = getAnalysis(); + MachineFunction* MF = MBB->getParent(); + MachineRegisterInfo& MRI = MF->getRegInfo(); + const TargetInstrInfo *TII = MF->getTarget().getInstrInfo(); + + SmallVector, 4> InsertedPHIDests; + + // Iterate over the worklist, inserting copies + while (!worklist.empty() || !copy_set.empty()) { + while (!worklist.empty()) { + std::multimap::iterator WI = worklist.begin(); + std::pair curr = *WI; + worklist.erase(WI); + + const TargetRegisterClass *RC = MF->getRegInfo().getRegClass(curr.first); + + if (isLiveOut(curr.second, MBB, LI)) { + // Create a temporary + unsigned t = MF->getRegInfo().createVirtualRegister(RC); + + // Insert copy from curr.second to a temporary at + // the Phi defining curr.second + MachineBasicBlock::iterator PI = MRI.getVRegDef(curr.second); + TII->copyRegToReg(*PI->getParent(), PI, t, + curr.second, RC, RC); + + DEBUG(errs() << "Inserted copy from " << curr.second << " to " << t + << "\n"); + + // Push temporary on Stacks + Stacks[curr.second].push_back(t); + + // Insert curr.second in pushed + pushed.insert(curr.second); + + // Create a live interval for this temporary + InsertedPHIDests.push_back(std::make_pair(t, --PI)); + } + + // Insert copy from map[curr.first] to curr.second + TII->copyRegToReg(*MBB, MBB->getFirstTerminator(), curr.second, + map[curr.first], RC, RC); + map[curr.first] = curr.second; + DEBUG(errs() << "Inserted copy from " << curr.first << " to " + << curr.second << "\n"); + + // Push this copy onto InsertedPHICopies so we can + // update LiveIntervals with it. + MachineBasicBlock::iterator MI = MBB->getFirstTerminator(); + InsertedPHIDests.push_back(std::make_pair(curr.second, --MI)); + + // If curr.first is a destination in copy_set... + for (std::multimap::iterator I = copy_set.begin(), + E = copy_set.end(); I != E; ) + if (curr.first == I->second) { + std::pair temp = *I; + worklist.insert(temp); + + // Avoid iterator invalidation + std::multimap::iterator OI = I; + ++I; + copy_set.erase(OI); + + break; + } else { + ++I; + } + } + + if (!copy_set.empty()) { + std::multimap::iterator CI = copy_set.begin(); + std::pair curr = *CI; + worklist.insert(curr); + copy_set.erase(CI); + + LiveInterval& I = LI.getInterval(curr.second); + MachineBasicBlock::iterator term = MBB->getFirstTerminator(); + SlotIndex endIdx = SlotIndex(); + if (term != MBB->end()) + endIdx = LI.getInstructionIndex(term); + else + endIdx = LI.getMBBEndIdx(MBB); + + if (I.liveAt(endIdx)) { + const TargetRegisterClass *RC = + MF->getRegInfo().getRegClass(curr.first); + + // Insert a copy from dest to a new temporary t at the end of b + unsigned t = MF->getRegInfo().createVirtualRegister(RC); + TII->copyRegToReg(*MBB, MBB->getFirstTerminator(), t, + curr.second, RC, RC); + map[curr.second] = t; + + MachineBasicBlock::iterator TI = MBB->getFirstTerminator(); + InsertedPHIDests.push_back(std::make_pair(t, --TI)); + } + } + } + + // Renumber the instructions so that we can perform the index computations + // needed to create new live intervals. + LI.renumber(); + + // For copies that we inserted at the ends of predecessors, we construct + // live intervals. This is pretty easy, since we know that the destination + // register cannot have be in live at that point previously. We just have + // to make sure that, for registers that serve as inputs to more than one + // PHI, we don't create multiple overlapping live intervals. + std::set RegHandled; + for (SmallVector, 4>::iterator I = + InsertedPHIDests.begin(), E = InsertedPHIDests.end(); I != E; ++I) { + if (RegHandled.insert(I->first).second) { + LiveInterval& Int = LI.getOrCreateInterval(I->first); + SlotIndex instrIdx = LI.getInstructionIndex(I->second); + if (Int.liveAt(instrIdx.getDefIndex())) + Int.removeRange(instrIdx.getDefIndex(), + LI.getMBBEndIdx(I->second->getParent()).getNextSlot(), + true); + + LiveRange R = LI.addLiveRangeToEndOfBlock(I->first, I->second); + R.valno->setCopy(I->second); + R.valno->def = LI.getInstructionIndex(I->second).getDefIndex(); + } + } +} + +/// InsertCopies - insert copies into MBB and all of its successors +void StrongPHIElimination::InsertCopies(MachineDomTreeNode* MDTN, + SmallPtrSet& visited) { + MachineBasicBlock* MBB = MDTN->getBlock(); + visited.insert(MBB); + + std::set pushed; + + LiveIntervals& LI = getAnalysis(); + // Rewrite register uses from Stacks + for (MachineBasicBlock::iterator I = MBB->begin(), E = MBB->end(); + I != E; ++I) { + if (I->getOpcode() == TargetInstrInfo::PHI) + continue; + + for (unsigned i = 0; i < I->getNumOperands(); ++i) + if (I->getOperand(i).isReg() && + Stacks[I->getOperand(i).getReg()].size()) { + // Remove the live range for the old vreg. + LiveInterval& OldInt = LI.getInterval(I->getOperand(i).getReg()); + LiveInterval::iterator OldLR = + OldInt.FindLiveRangeContaining(LI.getInstructionIndex(I).getUseIndex()); + if (OldLR != OldInt.end()) + OldInt.removeRange(*OldLR, true); + + // Change the register + I->getOperand(i).setReg(Stacks[I->getOperand(i).getReg()].back()); + + // Add a live range for the new vreg + LiveInterval& Int = LI.getInterval(I->getOperand(i).getReg()); + VNInfo* FirstVN = *Int.vni_begin(); + FirstVN->setHasPHIKill(false); + if (I->getOperand(i).isKill()) + FirstVN->addKill(LI.getInstructionIndex(I).getUseIndex()); + + LiveRange LR (LI.getMBBStartIdx(I->getParent()), + LI.getInstructionIndex(I).getUseIndex().getNextSlot(), + FirstVN); + + Int.addRange(LR); + } + } + + // Schedule the copies for this block + ScheduleCopies(MBB, pushed); + + // Recur down the dominator tree. + for (MachineDomTreeNode::iterator I = MDTN->begin(), + E = MDTN->end(); I != E; ++I) + if (!visited.count((*I)->getBlock())) + InsertCopies(*I, visited); + + // As we exit this block, pop the names we pushed while processing it + for (std::set::iterator I = pushed.begin(), + E = pushed.end(); I != E; ++I) + Stacks[*I].pop_back(); +} + +bool StrongPHIElimination::mergeLiveIntervals(unsigned primary, + unsigned secondary) { + + LiveIntervals& LI = getAnalysis(); + LiveInterval& LHS = LI.getOrCreateInterval(primary); + LiveInterval& RHS = LI.getOrCreateInterval(secondary); + + LI.renumber(); + + DenseMap VNMap; + for (LiveInterval::iterator I = RHS.begin(), E = RHS.end(); I != E; ++I) { + LiveRange R = *I; + + SlotIndex Start = R.start; + SlotIndex End = R.end; + if (LHS.getLiveRangeContaining(Start)) + return false; + + if (LHS.getLiveRangeContaining(End)) + return false; + + LiveInterval::iterator RI = std::upper_bound(LHS.begin(), LHS.end(), R); + if (RI != LHS.end() && RI->start < End) + return false; + } + + for (LiveInterval::iterator I = RHS.begin(), E = RHS.end(); I != E; ++I) { + LiveRange R = *I; + VNInfo* OldVN = R.valno; + VNInfo*& NewVN = VNMap[OldVN]; + if (!NewVN) { + NewVN = LHS.createValueCopy(OldVN, LI.getVNInfoAllocator()); + } + + LiveRange LR (R.start, R.end, NewVN); + LHS.addRange(LR); + } + + LI.removeInterval(RHS.reg); + + return true; +} + +bool StrongPHIElimination::runOnMachineFunction(MachineFunction &Fn) { + LiveIntervals& LI = getAnalysis(); + + // Compute DFS numbers of each block + computeDFS(Fn); + + // Determine which phi node operands need copies + for (MachineFunction::iterator I = Fn.begin(), E = Fn.end(); I != E; ++I) + if (!I->empty() && + I->begin()->getOpcode() == TargetInstrInfo::PHI) + processBlock(I); + + // Break interferences where two different phis want to coalesce + // in the same register. + std::set seen; + typedef std::map > + RenameSetType; + for (RenameSetType::iterator I = RenameSets.begin(), E = RenameSets.end(); + I != E; ++I) { + for (std::map::iterator + OI = I->second.begin(), OE = I->second.end(); OI != OE; ) { + if (!seen.count(OI->first)) { + seen.insert(OI->first); + ++OI; + } else { + Waiting[OI->second].insert(std::make_pair(OI->first, I->first)); + unsigned reg = OI->first; + ++OI; + I->second.erase(reg); + DEBUG(errs() << "Removing Renaming: " << reg << " -> " << I->first + << "\n"); + } + } + } + + // Insert copies + // FIXME: This process should probably preserve LiveIntervals + SmallPtrSet visited; + MachineDominatorTree& MDT = getAnalysis(); + InsertCopies(MDT.getRootNode(), visited); + + // Perform renaming + for (RenameSetType::iterator I = RenameSets.begin(), E = RenameSets.end(); + I != E; ++I) + while (I->second.size()) { + std::map::iterator SI = I->second.begin(); + + DEBUG(errs() << "Renaming: " << SI->first << " -> " << I->first << "\n"); + + if (SI->first != I->first) { + if (mergeLiveIntervals(I->first, SI->first)) { + Fn.getRegInfo().replaceRegWith(SI->first, I->first); + + if (RenameSets.count(SI->first)) { + I->second.insert(RenameSets[SI->first].begin(), + RenameSets[SI->first].end()); + RenameSets.erase(SI->first); + } + } else { + // Insert a last-minute copy if a conflict was detected. + const TargetInstrInfo *TII = Fn.getTarget().getInstrInfo(); + const TargetRegisterClass *RC = Fn.getRegInfo().getRegClass(I->first); + TII->copyRegToReg(*SI->second, SI->second->getFirstTerminator(), + I->first, SI->first, RC, RC); + + LI.renumber(); + + LiveInterval& Int = LI.getOrCreateInterval(I->first); + SlotIndex instrIdx = + LI.getInstructionIndex(--SI->second->getFirstTerminator()); + if (Int.liveAt(instrIdx.getDefIndex())) + Int.removeRange(instrIdx.getDefIndex(), + LI.getMBBEndIdx(SI->second).getNextSlot(), true); + + LiveRange R = LI.addLiveRangeToEndOfBlock(I->first, + --SI->second->getFirstTerminator()); + R.valno->setCopy(--SI->second->getFirstTerminator()); + R.valno->def = instrIdx.getDefIndex(); + + DEBUG(errs() << "Renaming failed: " << SI->first << " -> " + << I->first << "\n"); + } + } + + LiveInterval& Int = LI.getOrCreateInterval(I->first); + const LiveRange* LR = + Int.getLiveRangeContaining(LI.getMBBEndIdx(SI->second)); + LR->valno->setHasPHIKill(true); + + I->second.erase(SI->first); + } + + // Remove PHIs + std::vector phis; + for (MachineFunction::iterator I = Fn.begin(), E = Fn.end(); I != E; ++I) { + for (MachineBasicBlock::iterator BI = I->begin(), BE = I->end(); + BI != BE; ++BI) + if (BI->getOpcode() == TargetInstrInfo::PHI) + phis.push_back(BI); + } + + for (std::vector::iterator I = phis.begin(), E = phis.end(); + I != E; ) { + MachineInstr* PInstr = *(I++); + + // If this is a dead PHI node, then remove it from LiveIntervals. + unsigned DestReg = PInstr->getOperand(0).getReg(); + LiveInterval& PI = LI.getInterval(DestReg); + if (PInstr->registerDefIsDead(DestReg)) { + if (PI.containsOneValue()) { + LI.removeInterval(DestReg); + } else { + SlotIndex idx = LI.getInstructionIndex(PInstr).getDefIndex(); + PI.removeRange(*PI.getLiveRangeContaining(idx), true); + } + } else { + // Trim live intervals of input registers. They are no longer live into + // this block if they died after the PHI. If they lived after it, don't + // trim them because they might have other legitimate uses. + for (unsigned i = 1; i < PInstr->getNumOperands(); i += 2) { + unsigned reg = PInstr->getOperand(i).getReg(); + + MachineBasicBlock* MBB = PInstr->getOperand(i+1).getMBB(); + LiveInterval& InputI = LI.getInterval(reg); + if (MBB != PInstr->getParent() && + InputI.liveAt(LI.getMBBStartIdx(PInstr->getParent())) && + InputI.expiredAt(LI.getInstructionIndex(PInstr).getNextIndex())) + InputI.removeRange(LI.getMBBStartIdx(PInstr->getParent()), + LI.getInstructionIndex(PInstr), + true); + } + + // If the PHI is not dead, then the valno defined by the PHI + // now has an unknown def. + SlotIndex idx = LI.getInstructionIndex(PInstr).getDefIndex(); + const LiveRange* PLR = PI.getLiveRangeContaining(idx); + PLR->valno->setIsPHIDef(true); + LiveRange R (LI.getMBBStartIdx(PInstr->getParent()), + PLR->start, PLR->valno); + PI.addRange(R); + } + + LI.RemoveMachineInstrFromMaps(PInstr); + PInstr->eraseFromParent(); + } + + LI.renumber(); + + return true; +} diff --git a/libclamav/c++/llvm/lib/CodeGen/TailDuplication.cpp b/libclamav/c++/llvm/lib/CodeGen/TailDuplication.cpp new file mode 100644 index 000000000..12610b027 --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/TailDuplication.cpp @@ -0,0 +1,250 @@ +//===-- TailDuplication.cpp - Duplicate blocks into predecessors' tails ---===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This pass duplicates basic blocks ending in unconditional branches into +// the tails of their predecessors. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "tailduplication" +#include "llvm/Function.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/ADT/SmallSet.h" +#include "llvm/ADT/SetVector.h" +#include "llvm/ADT/Statistic.h" +using namespace llvm; + +STATISTIC(NumTailDups , "Number of tail duplicated blocks"); +STATISTIC(NumInstrDups , "Additional instructions due to tail duplication"); +STATISTIC(NumDeadBlocks, "Number of dead blocks removed"); + +// Heuristic for tail duplication. +static cl::opt +TailDuplicateSize("tail-dup-size", + cl::desc("Maximum instructions to consider tail duplicating"), + cl::init(2), cl::Hidden); + +namespace { + /// TailDuplicatePass - Perform tail duplication. + class TailDuplicatePass : public MachineFunctionPass { + const TargetInstrInfo *TII; + MachineModuleInfo *MMI; + + public: + static char ID; + explicit TailDuplicatePass() : MachineFunctionPass(&ID) {} + + virtual bool runOnMachineFunction(MachineFunction &MF); + virtual const char *getPassName() const { return "Tail Duplication"; } + + private: + bool TailDuplicateBlocks(MachineFunction &MF); + bool TailDuplicate(MachineBasicBlock *TailBB, MachineFunction &MF); + void RemoveDeadBlock(MachineBasicBlock *MBB); + }; + + char TailDuplicatePass::ID = 0; +} + +FunctionPass *llvm::createTailDuplicatePass() { + return new TailDuplicatePass(); +} + +bool TailDuplicatePass::runOnMachineFunction(MachineFunction &MF) { + TII = MF.getTarget().getInstrInfo(); + MMI = getAnalysisIfAvailable(); + + bool MadeChange = false; + bool MadeChangeThisIteration = true; + while (MadeChangeThisIteration) { + MadeChangeThisIteration = false; + MadeChangeThisIteration |= TailDuplicateBlocks(MF); + MadeChange |= MadeChangeThisIteration; + } + + return MadeChange; +} + +/// TailDuplicateBlocks - Look for small blocks that are unconditionally +/// branched to and do not fall through. Tail-duplicate their instructions +/// into their predecessors to eliminate (dynamic) branches. +bool TailDuplicatePass::TailDuplicateBlocks(MachineFunction &MF) { + bool MadeChange = false; + + for (MachineFunction::iterator I = ++MF.begin(), E = MF.end(); I != E; ) { + MachineBasicBlock *MBB = I++; + + // Only duplicate blocks that end with unconditional branches. + if (MBB->canFallThrough()) + continue; + + MadeChange |= TailDuplicate(MBB, MF); + + // If it is dead, remove it. + if (MBB->pred_empty()) { + NumInstrDups -= MBB->size(); + RemoveDeadBlock(MBB); + MadeChange = true; + ++NumDeadBlocks; + } + } + return MadeChange; +} + +/// TailDuplicate - If it is profitable, duplicate TailBB's contents in each +/// of its predecessors. +bool TailDuplicatePass::TailDuplicate(MachineBasicBlock *TailBB, + MachineFunction &MF) { + // Don't try to tail-duplicate single-block loops. + if (TailBB->isSuccessor(TailBB)) + return false; + + // Set the limit on the number of instructions to duplicate, with a default + // of one less than the tail-merge threshold. When optimizing for size, + // duplicate only one, because one branch instruction can be eliminated to + // compensate for the duplication. + unsigned MaxDuplicateCount; + if (MF.getFunction()->hasFnAttr(Attribute::OptimizeForSize)) + MaxDuplicateCount = 1; + else if (TII->isProfitableToDuplicateIndirectBranch() && + !TailBB->empty() && TailBB->back().getDesc().isIndirectBranch()) + // If the target has hardware branch prediction that can handle indirect + // branches, duplicating them can often make them predictable when there + // are common paths through the code. The limit needs to be high enough + // to allow undoing the effects of tail merging. + MaxDuplicateCount = 20; + else + MaxDuplicateCount = TailDuplicateSize; + + // Check the instructions in the block to determine whether tail-duplication + // is invalid or unlikely to be profitable. + unsigned i = 0; + bool HasCall = false; + for (MachineBasicBlock::iterator I = TailBB->begin(); + I != TailBB->end(); ++I, ++i) { + // Non-duplicable things shouldn't be tail-duplicated. + if (I->getDesc().isNotDuplicable()) return false; + // Don't duplicate more than the threshold. + if (i == MaxDuplicateCount) return false; + // Remember if we saw a call. + if (I->getDesc().isCall()) HasCall = true; + } + // Heuristically, don't tail-duplicate calls if it would expand code size, + // as it's less likely to be worth the extra cost. + if (i > 1 && HasCall) + return false; + + // Iterate through all the unique predecessors and tail-duplicate this + // block into them, if possible. Copying the list ahead of time also + // avoids trouble with the predecessor list reallocating. + bool Changed = false; + SmallSetVector Preds(TailBB->pred_begin(), + TailBB->pred_end()); + for (SmallSetVector::iterator PI = Preds.begin(), + PE = Preds.end(); PI != PE; ++PI) { + MachineBasicBlock *PredBB = *PI; + + assert(TailBB != PredBB && + "Single-block loop should have been rejected earlier!"); + if (PredBB->succ_size() > 1) continue; + + MachineBasicBlock *PredTBB, *PredFBB; + SmallVector PredCond; + if (TII->AnalyzeBranch(*PredBB, PredTBB, PredFBB, PredCond, true)) + continue; + if (!PredCond.empty()) + continue; + // EH edges are ignored by AnalyzeBranch. + if (PredBB->succ_size() != 1) + continue; + // Don't duplicate into a fall-through predecessor (at least for now). + if (PredBB->isLayoutSuccessor(TailBB) && PredBB->canFallThrough()) + continue; + + DEBUG(errs() << "\nTail-duplicating into PredBB: " << *PredBB + << "From Succ: " << *TailBB); + + // Remove PredBB's unconditional branch. + TII->RemoveBranch(*PredBB); + // Clone the contents of TailBB into PredBB. + for (MachineBasicBlock::iterator I = TailBB->begin(), E = TailBB->end(); + I != E; ++I) { + MachineInstr *NewMI = MF.CloneMachineInstr(I); + PredBB->insert(PredBB->end(), NewMI); + } + NumInstrDups += TailBB->size() - 1; // subtract one for removed branch + + // Update the CFG. + PredBB->removeSuccessor(PredBB->succ_begin()); + assert(PredBB->succ_empty() && + "TailDuplicate called on block with multiple successors!"); + for (MachineBasicBlock::succ_iterator I = TailBB->succ_begin(), + E = TailBB->succ_end(); I != E; ++I) + PredBB->addSuccessor(*I); + + Changed = true; + ++NumTailDups; + } + + // If TailBB was duplicated into all its predecessors except for the prior + // block, which falls through unconditionally, move the contents of this + // block into the prior block. + MachineBasicBlock &PrevBB = *prior(MachineFunction::iterator(TailBB)); + MachineBasicBlock *PriorTBB = 0, *PriorFBB = 0; + SmallVector PriorCond; + bool PriorUnAnalyzable = + TII->AnalyzeBranch(PrevBB, PriorTBB, PriorFBB, PriorCond, true); + // This has to check PrevBB->succ_size() because EH edges are ignored by + // AnalyzeBranch. + if (!PriorUnAnalyzable && PriorCond.empty() && !PriorTBB && + TailBB->pred_size() == 1 && PrevBB.succ_size() == 1 && + !TailBB->hasAddressTaken()) { + DEBUG(errs() << "\nMerging into block: " << PrevBB + << "From MBB: " << *TailBB); + PrevBB.splice(PrevBB.end(), TailBB, TailBB->begin(), TailBB->end()); + PrevBB.removeSuccessor(PrevBB.succ_begin());; + assert(PrevBB.succ_empty()); + PrevBB.transferSuccessors(TailBB); + Changed = true; + } + + return Changed; +} + +/// RemoveDeadBlock - Remove the specified dead machine basic block from the +/// function, updating the CFG. +void TailDuplicatePass::RemoveDeadBlock(MachineBasicBlock *MBB) { + assert(MBB->pred_empty() && "MBB must be dead!"); + DEBUG(errs() << "\nRemoving MBB: " << *MBB); + + // Remove all successors. + while (!MBB->succ_empty()) + MBB->removeSuccessor(MBB->succ_end()-1); + + // If there are any labels in the basic block, unregister them from + // MachineModuleInfo. + if (MMI && !MBB->empty()) { + for (MachineBasicBlock::iterator I = MBB->begin(), E = MBB->end(); + I != E; ++I) { + if (I->isLabel()) + // The label ID # is always operand #0, an immediate. + MMI->InvalidateLabel(I->getOperand(0).getImm()); + } + } + + // Remove the block. + MBB->eraseFromParent(); +} + diff --git a/libclamav/c++/llvm/lib/CodeGen/TargetInstrInfoImpl.cpp b/libclamav/c++/llvm/lib/CodeGen/TargetInstrInfoImpl.cpp new file mode 100644 index 000000000..102e2a34a --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/TargetInstrInfoImpl.cpp @@ -0,0 +1,345 @@ +//===-- TargetInstrInfoImpl.cpp - Target Instruction Information ----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the TargetInstrInfoImpl class, it just provides default +// implementations of various methods. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineMemOperand.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/PseudoSourceValue.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +// commuteInstruction - The default implementation of this method just exchanges +// the two operands returned by findCommutedOpIndices. +MachineInstr *TargetInstrInfoImpl::commuteInstruction(MachineInstr *MI, + bool NewMI) const { + const TargetInstrDesc &TID = MI->getDesc(); + bool HasDef = TID.getNumDefs(); + if (HasDef && !MI->getOperand(0).isReg()) + // No idea how to commute this instruction. Target should implement its own. + return 0; + unsigned Idx1, Idx2; + if (!findCommutedOpIndices(MI, Idx1, Idx2)) { + std::string msg; + raw_string_ostream Msg(msg); + Msg << "Don't know how to commute: " << *MI; + llvm_report_error(Msg.str()); + } + + assert(MI->getOperand(Idx1).isReg() && MI->getOperand(Idx2).isReg() && + "This only knows how to commute register operands so far"); + unsigned Reg1 = MI->getOperand(Idx1).getReg(); + unsigned Reg2 = MI->getOperand(Idx2).getReg(); + bool Reg1IsKill = MI->getOperand(Idx1).isKill(); + bool Reg2IsKill = MI->getOperand(Idx2).isKill(); + bool ChangeReg0 = false; + if (HasDef && MI->getOperand(0).getReg() == Reg1) { + // Must be two address instruction! + assert(MI->getDesc().getOperandConstraint(0, TOI::TIED_TO) && + "Expecting a two-address instruction!"); + Reg2IsKill = false; + ChangeReg0 = true; + } + + if (NewMI) { + // Create a new instruction. + unsigned Reg0 = HasDef + ? (ChangeReg0 ? Reg2 : MI->getOperand(0).getReg()) : 0; + bool Reg0IsDead = HasDef ? MI->getOperand(0).isDead() : false; + MachineFunction &MF = *MI->getParent()->getParent(); + if (HasDef) + return BuildMI(MF, MI->getDebugLoc(), MI->getDesc()) + .addReg(Reg0, RegState::Define | getDeadRegState(Reg0IsDead)) + .addReg(Reg2, getKillRegState(Reg2IsKill)) + .addReg(Reg1, getKillRegState(Reg2IsKill)); + else + return BuildMI(MF, MI->getDebugLoc(), MI->getDesc()) + .addReg(Reg2, getKillRegState(Reg2IsKill)) + .addReg(Reg1, getKillRegState(Reg2IsKill)); + } + + if (ChangeReg0) + MI->getOperand(0).setReg(Reg2); + MI->getOperand(Idx2).setReg(Reg1); + MI->getOperand(Idx1).setReg(Reg2); + MI->getOperand(Idx2).setIsKill(Reg1IsKill); + MI->getOperand(Idx1).setIsKill(Reg2IsKill); + return MI; +} + +/// findCommutedOpIndices - If specified MI is commutable, return the two +/// operand indices that would swap value. Return true if the instruction +/// is not in a form which this routine understands. +bool TargetInstrInfoImpl::findCommutedOpIndices(MachineInstr *MI, + unsigned &SrcOpIdx1, + unsigned &SrcOpIdx2) const { + const TargetInstrDesc &TID = MI->getDesc(); + if (!TID.isCommutable()) + return false; + // This assumes v0 = op v1, v2 and commuting would swap v1 and v2. If this + // is not true, then the target must implement this. + SrcOpIdx1 = TID.getNumDefs(); + SrcOpIdx2 = SrcOpIdx1 + 1; + if (!MI->getOperand(SrcOpIdx1).isReg() || + !MI->getOperand(SrcOpIdx2).isReg()) + // No idea. + return false; + return true; +} + + +bool TargetInstrInfoImpl::PredicateInstruction(MachineInstr *MI, + const SmallVectorImpl &Pred) const { + bool MadeChange = false; + const TargetInstrDesc &TID = MI->getDesc(); + if (!TID.isPredicable()) + return false; + + for (unsigned j = 0, i = 0, e = MI->getNumOperands(); i != e; ++i) { + if (TID.OpInfo[i].isPredicate()) { + MachineOperand &MO = MI->getOperand(i); + if (MO.isReg()) { + MO.setReg(Pred[j].getReg()); + MadeChange = true; + } else if (MO.isImm()) { + MO.setImm(Pred[j].getImm()); + MadeChange = true; + } else if (MO.isMBB()) { + MO.setMBB(Pred[j].getMBB()); + MadeChange = true; + } + ++j; + } + } + return MadeChange; +} + +void TargetInstrInfoImpl::reMaterialize(MachineBasicBlock &MBB, + MachineBasicBlock::iterator I, + unsigned DestReg, + unsigned SubIdx, + const MachineInstr *Orig, + const TargetRegisterInfo *TRI) const { + MachineInstr *MI = MBB.getParent()->CloneMachineInstr(Orig); + MachineOperand &MO = MI->getOperand(0); + if (TargetRegisterInfo::isVirtualRegister(DestReg)) { + MO.setReg(DestReg); + MO.setSubReg(SubIdx); + } else if (SubIdx) { + MO.setReg(TRI->getSubReg(DestReg, SubIdx)); + } else { + MO.setReg(DestReg); + } + MBB.insert(I, MI); +} + +bool +TargetInstrInfoImpl::isIdentical(const MachineInstr *MI, + const MachineInstr *Other, + const MachineRegisterInfo *MRI) const { + if (MI->getOpcode() != Other->getOpcode() || + MI->getNumOperands() != Other->getNumOperands()) + return false; + + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + const MachineOperand &MO = MI->getOperand(i); + const MachineOperand &OMO = Other->getOperand(i); + if (MO.isReg() && MO.isDef()) { + assert(OMO.isReg() && OMO.isDef()); + unsigned Reg = MO.getReg(); + if (TargetRegisterInfo::isPhysicalRegister(Reg)) { + if (Reg != OMO.getReg()) + return false; + } else if (MRI->getRegClass(MO.getReg()) != + MRI->getRegClass(OMO.getReg())) + return false; + + continue; + } + + if (!MO.isIdenticalTo(OMO)) + return false; + } + + return true; +} + +unsigned +TargetInstrInfoImpl::GetFunctionSizeInBytes(const MachineFunction &MF) const { + unsigned FnSize = 0; + for (MachineFunction::const_iterator MBBI = MF.begin(), E = MF.end(); + MBBI != E; ++MBBI) { + const MachineBasicBlock &MBB = *MBBI; + for (MachineBasicBlock::const_iterator I = MBB.begin(),E = MBB.end(); + I != E; ++I) + FnSize += GetInstSizeInBytes(I); + } + return FnSize; +} + +/// foldMemoryOperand - Attempt to fold a load or store of the specified stack +/// slot into the specified machine instruction for the specified operand(s). +/// If this is possible, a new instruction is returned with the specified +/// operand folded, otherwise NULL is returned. The client is responsible for +/// removing the old instruction and adding the new one in the instruction +/// stream. +MachineInstr* +TargetInstrInfo::foldMemoryOperand(MachineFunction &MF, + MachineInstr* MI, + const SmallVectorImpl &Ops, + int FrameIndex) const { + unsigned Flags = 0; + for (unsigned i = 0, e = Ops.size(); i != e; ++i) + if (MI->getOperand(Ops[i]).isDef()) + Flags |= MachineMemOperand::MOStore; + else + Flags |= MachineMemOperand::MOLoad; + + // Ask the target to do the actual folding. + MachineInstr *NewMI = foldMemoryOperandImpl(MF, MI, Ops, FrameIndex); + if (!NewMI) return 0; + + assert((!(Flags & MachineMemOperand::MOStore) || + NewMI->getDesc().mayStore()) && + "Folded a def to a non-store!"); + assert((!(Flags & MachineMemOperand::MOLoad) || + NewMI->getDesc().mayLoad()) && + "Folded a use to a non-load!"); + const MachineFrameInfo &MFI = *MF.getFrameInfo(); + assert(MFI.getObjectOffset(FrameIndex) != -1); + MachineMemOperand *MMO = + MF.getMachineMemOperand(PseudoSourceValue::getFixedStack(FrameIndex), + Flags, /*Offset=*/0, + MFI.getObjectSize(FrameIndex), + MFI.getObjectAlignment(FrameIndex)); + NewMI->addMemOperand(MF, MMO); + + return NewMI; +} + +/// foldMemoryOperand - Same as the previous version except it allows folding +/// of any load and store from / to any address, not just from a specific +/// stack slot. +MachineInstr* +TargetInstrInfo::foldMemoryOperand(MachineFunction &MF, + MachineInstr* MI, + const SmallVectorImpl &Ops, + MachineInstr* LoadMI) const { + assert(LoadMI->getDesc().canFoldAsLoad() && "LoadMI isn't foldable!"); +#ifndef NDEBUG + for (unsigned i = 0, e = Ops.size(); i != e; ++i) + assert(MI->getOperand(Ops[i]).isUse() && "Folding load into def!"); +#endif + + // Ask the target to do the actual folding. + MachineInstr *NewMI = foldMemoryOperandImpl(MF, MI, Ops, LoadMI); + if (!NewMI) return 0; + + // Copy the memoperands from the load to the folded instruction. + NewMI->setMemRefs(LoadMI->memoperands_begin(), + LoadMI->memoperands_end()); + + return NewMI; +} + +bool +TargetInstrInfo::isReallyTriviallyReMaterializableGeneric(const MachineInstr * + MI, + AliasAnalysis * + AA) const { + const MachineFunction &MF = *MI->getParent()->getParent(); + const MachineRegisterInfo &MRI = MF.getRegInfo(); + const TargetMachine &TM = MF.getTarget(); + const TargetInstrInfo &TII = *TM.getInstrInfo(); + const TargetRegisterInfo &TRI = *TM.getRegisterInfo(); + + // A load from a fixed stack slot can be rematerialized. This may be + // redundant with subsequent checks, but it's target-independent, + // simple, and a common case. + int FrameIdx = 0; + if (TII.isLoadFromStackSlot(MI, FrameIdx) && + MF.getFrameInfo()->isImmutableObjectIndex(FrameIdx)) + return true; + + const TargetInstrDesc &TID = MI->getDesc(); + + // Avoid instructions obviously unsafe for remat. + if (TID.hasUnmodeledSideEffects() || TID.isNotDuplicable() || + TID.mayStore()) + return false; + + // Avoid instructions which load from potentially varying memory. + if (TID.mayLoad() && !MI->isInvariantLoad(AA)) + return false; + + // If any of the registers accessed are non-constant, conservatively assume + // the instruction is not rematerializable. + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + const MachineOperand &MO = MI->getOperand(i); + if (!MO.isReg()) continue; + unsigned Reg = MO.getReg(); + if (Reg == 0) + continue; + + // Check for a well-behaved physical register. + if (TargetRegisterInfo::isPhysicalRegister(Reg)) { + if (MO.isUse()) { + // If the physreg has no defs anywhere, it's just an ambient register + // and we can freely move its uses. Alternatively, if it's allocatable, + // it could get allocated to something with a def during allocation. + if (!MRI.def_empty(Reg)) + return false; + BitVector AllocatableRegs = TRI.getAllocatableSet(MF, 0); + if (AllocatableRegs.test(Reg)) + return false; + // Check for a def among the register's aliases too. + for (const unsigned *Alias = TRI.getAliasSet(Reg); *Alias; ++Alias) { + unsigned AliasReg = *Alias; + if (!MRI.def_empty(AliasReg)) + return false; + if (AllocatableRegs.test(AliasReg)) + return false; + } + } else { + // A physreg def. We can't remat it. + return false; + } + continue; + } + + // Only allow one virtual-register def, and that in the first operand. + if (MO.isDef() != (i == 0)) + return false; + + // For the def, it should be the only def of that register. + if (MO.isDef() && (next(MRI.def_begin(Reg)) != MRI.def_end() || + MRI.isLiveIn(Reg))) + return false; + + // Don't allow any virtual-register uses. Rematting an instruction with + // virtual register uses would length the live ranges of the uses, which + // is not necessarily a good idea, certainly not "trivial". + if (MO.isUse()) + return false; + } + + // Everything checked out. + return true; +} diff --git a/libclamav/c++/llvm/lib/CodeGen/TwoAddressInstructionPass.cpp b/libclamav/c++/llvm/lib/CodeGen/TwoAddressInstructionPass.cpp new file mode 100644 index 000000000..5fa690bc4 --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/TwoAddressInstructionPass.cpp @@ -0,0 +1,1109 @@ +//===-- TwoAddressInstructionPass.cpp - Two-Address instruction pass ------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the TwoAddress instruction pass which is used +// by most register allocators. Two-Address instructions are rewritten +// from: +// +// A = B op C +// +// to: +// +// A = B +// A op= C +// +// Note that if a register allocator chooses to use this pass, that it +// has to be capable of handling the non-SSA nature of these rewritten +// virtual registers. +// +// It is also worth noting that the duplicate operand of the two +// address instruction is removed. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "twoaddrinstr" +#include "llvm/CodeGen/Passes.h" +#include "llvm/Function.h" +#include "llvm/CodeGen/LiveVariables.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetOptions.h" +#include "llvm/Support/Debug.h" +#include "llvm/ADT/BitVector.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallSet.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/ADT/STLExtras.h" +using namespace llvm; + +STATISTIC(NumTwoAddressInstrs, "Number of two-address instructions"); +STATISTIC(NumCommuted , "Number of instructions commuted to coalesce"); +STATISTIC(NumAggrCommuted , "Number of instructions aggressively commuted"); +STATISTIC(NumConvertedTo3Addr, "Number of instructions promoted to 3-address"); +STATISTIC(Num3AddrSunk, "Number of 3-address instructions sunk"); +STATISTIC(NumReMats, "Number of instructions re-materialized"); +STATISTIC(NumDeletes, "Number of dead instructions deleted"); + +namespace { + class TwoAddressInstructionPass : public MachineFunctionPass { + const TargetInstrInfo *TII; + const TargetRegisterInfo *TRI; + MachineRegisterInfo *MRI; + LiveVariables *LV; + AliasAnalysis *AA; + + // DistanceMap - Keep track the distance of a MI from the start of the + // current basic block. + DenseMap DistanceMap; + + // SrcRegMap - A map from virtual registers to physical registers which + // are likely targets to be coalesced to due to copies from physical + // registers to virtual registers. e.g. v1024 = move r0. + DenseMap SrcRegMap; + + // DstRegMap - A map from virtual registers to physical registers which + // are likely targets to be coalesced to due to copies to physical + // registers from virtual registers. e.g. r1 = move v1024. + DenseMap DstRegMap; + + bool Sink3AddrInstruction(MachineBasicBlock *MBB, MachineInstr *MI, + unsigned Reg, + MachineBasicBlock::iterator OldPos); + + bool isProfitableToReMat(unsigned Reg, const TargetRegisterClass *RC, + MachineInstr *MI, MachineInstr *DefMI, + MachineBasicBlock *MBB, unsigned Loc); + + bool NoUseAfterLastDef(unsigned Reg, MachineBasicBlock *MBB, unsigned Dist, + unsigned &LastDef); + + MachineInstr *FindLastUseInMBB(unsigned Reg, MachineBasicBlock *MBB, + unsigned Dist); + + bool isProfitableToCommute(unsigned regB, unsigned regC, + MachineInstr *MI, MachineBasicBlock *MBB, + unsigned Dist); + + bool CommuteInstruction(MachineBasicBlock::iterator &mi, + MachineFunction::iterator &mbbi, + unsigned RegB, unsigned RegC, unsigned Dist); + + bool isProfitableToConv3Addr(unsigned RegA); + + bool ConvertInstTo3Addr(MachineBasicBlock::iterator &mi, + MachineBasicBlock::iterator &nmi, + MachineFunction::iterator &mbbi, + unsigned RegB, unsigned Dist); + + typedef std::pair, MachineInstr*> NewKill; + bool canUpdateDeletedKills(SmallVector &Kills, + SmallVector &NewKills, + MachineBasicBlock *MBB, unsigned Dist); + bool DeleteUnusedInstr(MachineBasicBlock::iterator &mi, + MachineBasicBlock::iterator &nmi, + MachineFunction::iterator &mbbi, unsigned Dist); + + bool TryInstructionTransform(MachineBasicBlock::iterator &mi, + MachineBasicBlock::iterator &nmi, + MachineFunction::iterator &mbbi, + unsigned SrcIdx, unsigned DstIdx, + unsigned Dist); + + void ProcessCopy(MachineInstr *MI, MachineBasicBlock *MBB, + SmallPtrSet &Processed); + + public: + static char ID; // Pass identification, replacement for typeid + TwoAddressInstructionPass() : MachineFunctionPass(&ID) {} + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesCFG(); + AU.addRequired(); + AU.addPreserved(); + AU.addPreservedID(MachineLoopInfoID); + AU.addPreservedID(MachineDominatorsID); + if (StrongPHIElim) + AU.addPreservedID(StrongPHIEliminationID); + else + AU.addPreservedID(PHIEliminationID); + MachineFunctionPass::getAnalysisUsage(AU); + } + + /// runOnMachineFunction - Pass entry point. + bool runOnMachineFunction(MachineFunction&); + }; +} + +char TwoAddressInstructionPass::ID = 0; +static RegisterPass +X("twoaddressinstruction", "Two-Address instruction pass"); + +const PassInfo *const llvm::TwoAddressInstructionPassID = &X; + +/// Sink3AddrInstruction - A two-address instruction has been converted to a +/// three-address instruction to avoid clobbering a register. Try to sink it +/// past the instruction that would kill the above mentioned register to reduce +/// register pressure. +bool TwoAddressInstructionPass::Sink3AddrInstruction(MachineBasicBlock *MBB, + MachineInstr *MI, unsigned SavedReg, + MachineBasicBlock::iterator OldPos) { + // Check if it's safe to move this instruction. + bool SeenStore = true; // Be conservative. + if (!MI->isSafeToMove(TII, SeenStore, AA)) + return false; + + unsigned DefReg = 0; + SmallSet UseRegs; + + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + const MachineOperand &MO = MI->getOperand(i); + if (!MO.isReg()) + continue; + unsigned MOReg = MO.getReg(); + if (!MOReg) + continue; + if (MO.isUse() && MOReg != SavedReg) + UseRegs.insert(MO.getReg()); + if (!MO.isDef()) + continue; + if (MO.isImplicit()) + // Don't try to move it if it implicitly defines a register. + return false; + if (DefReg) + // For now, don't move any instructions that define multiple registers. + return false; + DefReg = MO.getReg(); + } + + // Find the instruction that kills SavedReg. + MachineInstr *KillMI = NULL; + for (MachineRegisterInfo::use_iterator UI = MRI->use_begin(SavedReg), + UE = MRI->use_end(); UI != UE; ++UI) { + MachineOperand &UseMO = UI.getOperand(); + if (!UseMO.isKill()) + continue; + KillMI = UseMO.getParent(); + break; + } + + if (!KillMI || KillMI->getParent() != MBB || KillMI == MI) + return false; + + // If any of the definitions are used by another instruction between the + // position and the kill use, then it's not safe to sink it. + // + // FIXME: This can be sped up if there is an easy way to query whether an + // instruction is before or after another instruction. Then we can use + // MachineRegisterInfo def / use instead. + MachineOperand *KillMO = NULL; + MachineBasicBlock::iterator KillPos = KillMI; + ++KillPos; + + unsigned NumVisited = 0; + for (MachineBasicBlock::iterator I = next(OldPos); I != KillPos; ++I) { + MachineInstr *OtherMI = I; + if (NumVisited > 30) // FIXME: Arbitrary limit to reduce compile time cost. + return false; + ++NumVisited; + for (unsigned i = 0, e = OtherMI->getNumOperands(); i != e; ++i) { + MachineOperand &MO = OtherMI->getOperand(i); + if (!MO.isReg()) + continue; + unsigned MOReg = MO.getReg(); + if (!MOReg) + continue; + if (DefReg == MOReg) + return false; + + if (MO.isKill()) { + if (OtherMI == KillMI && MOReg == SavedReg) + // Save the operand that kills the register. We want to unset the kill + // marker if we can sink MI past it. + KillMO = &MO; + else if (UseRegs.count(MOReg)) + // One of the uses is killed before the destination. + return false; + } + } + } + + // Update kill and LV information. + KillMO->setIsKill(false); + KillMO = MI->findRegisterUseOperand(SavedReg, false, TRI); + KillMO->setIsKill(true); + + if (LV) + LV->replaceKillInstruction(SavedReg, KillMI, MI); + + // Move instruction to its destination. + MBB->remove(MI); + MBB->insert(KillPos, MI); + + ++Num3AddrSunk; + return true; +} + +/// isTwoAddrUse - Return true if the specified MI is using the specified +/// register as a two-address operand. +static bool isTwoAddrUse(MachineInstr *UseMI, unsigned Reg) { + const TargetInstrDesc &TID = UseMI->getDesc(); + for (unsigned i = 0, e = TID.getNumOperands(); i != e; ++i) { + MachineOperand &MO = UseMI->getOperand(i); + if (MO.isReg() && MO.getReg() == Reg && + (MO.isDef() || UseMI->isRegTiedToDefOperand(i))) + // Earlier use is a two-address one. + return true; + } + return false; +} + +/// isProfitableToReMat - Return true if the heuristics determines it is likely +/// to be profitable to re-materialize the definition of Reg rather than copy +/// the register. +bool +TwoAddressInstructionPass::isProfitableToReMat(unsigned Reg, + const TargetRegisterClass *RC, + MachineInstr *MI, MachineInstr *DefMI, + MachineBasicBlock *MBB, unsigned Loc) { + bool OtherUse = false; + for (MachineRegisterInfo::use_iterator UI = MRI->use_begin(Reg), + UE = MRI->use_end(); UI != UE; ++UI) { + MachineOperand &UseMO = UI.getOperand(); + MachineInstr *UseMI = UseMO.getParent(); + MachineBasicBlock *UseMBB = UseMI->getParent(); + if (UseMBB == MBB) { + DenseMap::iterator DI = DistanceMap.find(UseMI); + if (DI != DistanceMap.end() && DI->second == Loc) + continue; // Current use. + OtherUse = true; + // There is at least one other use in the MBB that will clobber the + // register. + if (isTwoAddrUse(UseMI, Reg)) + return true; + } + } + + // If other uses in MBB are not two-address uses, then don't remat. + if (OtherUse) + return false; + + // No other uses in the same block, remat if it's defined in the same + // block so it does not unnecessarily extend the live range. + return MBB == DefMI->getParent(); +} + +/// NoUseAfterLastDef - Return true if there are no intervening uses between the +/// last instruction in the MBB that defines the specified register and the +/// two-address instruction which is being processed. It also returns the last +/// def location by reference +bool TwoAddressInstructionPass::NoUseAfterLastDef(unsigned Reg, + MachineBasicBlock *MBB, unsigned Dist, + unsigned &LastDef) { + LastDef = 0; + unsigned LastUse = Dist; + for (MachineRegisterInfo::reg_iterator I = MRI->reg_begin(Reg), + E = MRI->reg_end(); I != E; ++I) { + MachineOperand &MO = I.getOperand(); + MachineInstr *MI = MO.getParent(); + if (MI->getParent() != MBB) + continue; + DenseMap::iterator DI = DistanceMap.find(MI); + if (DI == DistanceMap.end()) + continue; + if (MO.isUse() && DI->second < LastUse) + LastUse = DI->second; + if (MO.isDef() && DI->second > LastDef) + LastDef = DI->second; + } + + return !(LastUse > LastDef && LastUse < Dist); +} + +MachineInstr *TwoAddressInstructionPass::FindLastUseInMBB(unsigned Reg, + MachineBasicBlock *MBB, + unsigned Dist) { + unsigned LastUseDist = 0; + MachineInstr *LastUse = 0; + for (MachineRegisterInfo::reg_iterator I = MRI->reg_begin(Reg), + E = MRI->reg_end(); I != E; ++I) { + MachineOperand &MO = I.getOperand(); + MachineInstr *MI = MO.getParent(); + if (MI->getParent() != MBB) + continue; + DenseMap::iterator DI = DistanceMap.find(MI); + if (DI == DistanceMap.end()) + continue; + if (DI->second >= Dist) + continue; + + if (MO.isUse() && DI->second > LastUseDist) { + LastUse = DI->first; + LastUseDist = DI->second; + } + } + return LastUse; +} + +/// isCopyToReg - Return true if the specified MI is a copy instruction or +/// a extract_subreg instruction. It also returns the source and destination +/// registers and whether they are physical registers by reference. +static bool isCopyToReg(MachineInstr &MI, const TargetInstrInfo *TII, + unsigned &SrcReg, unsigned &DstReg, + bool &IsSrcPhys, bool &IsDstPhys) { + SrcReg = 0; + DstReg = 0; + unsigned SrcSubIdx, DstSubIdx; + if (!TII->isMoveInstr(MI, SrcReg, DstReg, SrcSubIdx, DstSubIdx)) { + if (MI.getOpcode() == TargetInstrInfo::EXTRACT_SUBREG) { + DstReg = MI.getOperand(0).getReg(); + SrcReg = MI.getOperand(1).getReg(); + } else if (MI.getOpcode() == TargetInstrInfo::INSERT_SUBREG) { + DstReg = MI.getOperand(0).getReg(); + SrcReg = MI.getOperand(2).getReg(); + } else if (MI.getOpcode() == TargetInstrInfo::SUBREG_TO_REG) { + DstReg = MI.getOperand(0).getReg(); + SrcReg = MI.getOperand(2).getReg(); + } + } + + if (DstReg) { + IsSrcPhys = TargetRegisterInfo::isPhysicalRegister(SrcReg); + IsDstPhys = TargetRegisterInfo::isPhysicalRegister(DstReg); + return true; + } + return false; +} + +/// isKilled - Test if the given register value, which is used by the given +/// instruction, is killed by the given instruction. This looks through +/// coalescable copies to see if the original value is potentially not killed. +/// +/// For example, in this code: +/// +/// %reg1034 = copy %reg1024 +/// %reg1035 = copy %reg1025 +/// %reg1036 = add %reg1034, %reg1035 +/// +/// %reg1034 is not considered to be killed, since it is copied from a +/// register which is not killed. Treating it as not killed lets the +/// normal heuristics commute the (two-address) add, which lets +/// coalescing eliminate the extra copy. +/// +static bool isKilled(MachineInstr &MI, unsigned Reg, + const MachineRegisterInfo *MRI, + const TargetInstrInfo *TII) { + MachineInstr *DefMI = &MI; + for (;;) { + if (!DefMI->killsRegister(Reg)) + return false; + if (TargetRegisterInfo::isPhysicalRegister(Reg)) + return true; + MachineRegisterInfo::def_iterator Begin = MRI->def_begin(Reg); + // If there are multiple defs, we can't do a simple analysis, so just + // go with what the kill flag says. + if (next(Begin) != MRI->def_end()) + return true; + DefMI = &*Begin; + bool IsSrcPhys, IsDstPhys; + unsigned SrcReg, DstReg; + // If the def is something other than a copy, then it isn't going to + // be coalesced, so follow the kill flag. + if (!isCopyToReg(*DefMI, TII, SrcReg, DstReg, IsSrcPhys, IsDstPhys)) + return true; + Reg = SrcReg; + } +} + +/// isTwoAddrUse - Return true if the specified MI uses the specified register +/// as a two-address use. If so, return the destination register by reference. +static bool isTwoAddrUse(MachineInstr &MI, unsigned Reg, unsigned &DstReg) { + const TargetInstrDesc &TID = MI.getDesc(); + unsigned NumOps = (MI.getOpcode() == TargetInstrInfo::INLINEASM) + ? MI.getNumOperands() : TID.getNumOperands(); + for (unsigned i = 0; i != NumOps; ++i) { + const MachineOperand &MO = MI.getOperand(i); + if (!MO.isReg() || !MO.isUse() || MO.getReg() != Reg) + continue; + unsigned ti; + if (MI.isRegTiedToDefOperand(i, &ti)) { + DstReg = MI.getOperand(ti).getReg(); + return true; + } + } + return false; +} + +/// findOnlyInterestingUse - Given a register, if has a single in-basic block +/// use, return the use instruction if it's a copy or a two-address use. +static +MachineInstr *findOnlyInterestingUse(unsigned Reg, MachineBasicBlock *MBB, + MachineRegisterInfo *MRI, + const TargetInstrInfo *TII, + bool &IsCopy, + unsigned &DstReg, bool &IsDstPhys) { + MachineRegisterInfo::use_iterator UI = MRI->use_begin(Reg); + if (UI == MRI->use_end()) + return 0; + MachineInstr &UseMI = *UI; + if (++UI != MRI->use_end()) + // More than one use. + return 0; + if (UseMI.getParent() != MBB) + return 0; + unsigned SrcReg; + bool IsSrcPhys; + if (isCopyToReg(UseMI, TII, SrcReg, DstReg, IsSrcPhys, IsDstPhys)) { + IsCopy = true; + return &UseMI; + } + IsDstPhys = false; + if (isTwoAddrUse(UseMI, Reg, DstReg)) { + IsDstPhys = TargetRegisterInfo::isPhysicalRegister(DstReg); + return &UseMI; + } + return 0; +} + +/// getMappedReg - Return the physical register the specified virtual register +/// might be mapped to. +static unsigned +getMappedReg(unsigned Reg, DenseMap &RegMap) { + while (TargetRegisterInfo::isVirtualRegister(Reg)) { + DenseMap::iterator SI = RegMap.find(Reg); + if (SI == RegMap.end()) + return 0; + Reg = SI->second; + } + if (TargetRegisterInfo::isPhysicalRegister(Reg)) + return Reg; + return 0; +} + +/// regsAreCompatible - Return true if the two registers are equal or aliased. +/// +static bool +regsAreCompatible(unsigned RegA, unsigned RegB, const TargetRegisterInfo *TRI) { + if (RegA == RegB) + return true; + if (!RegA || !RegB) + return false; + return TRI->regsOverlap(RegA, RegB); +} + + +/// isProfitableToReMat - Return true if it's potentially profitable to commute +/// the two-address instruction that's being processed. +bool +TwoAddressInstructionPass::isProfitableToCommute(unsigned regB, unsigned regC, + MachineInstr *MI, MachineBasicBlock *MBB, + unsigned Dist) { + // Determine if it's profitable to commute this two address instruction. In + // general, we want no uses between this instruction and the definition of + // the two-address register. + // e.g. + // %reg1028 = EXTRACT_SUBREG %reg1027, 1 + // %reg1029 = MOV8rr %reg1028 + // %reg1029 = SHR8ri %reg1029, 7, %EFLAGS + // insert => %reg1030 = MOV8rr %reg1028 + // %reg1030 = ADD8rr %reg1028, %reg1029, %EFLAGS + // In this case, it might not be possible to coalesce the second MOV8rr + // instruction if the first one is coalesced. So it would be profitable to + // commute it: + // %reg1028 = EXTRACT_SUBREG %reg1027, 1 + // %reg1029 = MOV8rr %reg1028 + // %reg1029 = SHR8ri %reg1029, 7, %EFLAGS + // insert => %reg1030 = MOV8rr %reg1029 + // %reg1030 = ADD8rr %reg1029, %reg1028, %EFLAGS + + if (!MI->killsRegister(regC)) + return false; + + // Ok, we have something like: + // %reg1030 = ADD8rr %reg1028, %reg1029, %EFLAGS + // let's see if it's worth commuting it. + + // Look for situations like this: + // %reg1024 = MOV r1 + // %reg1025 = MOV r0 + // %reg1026 = ADD %reg1024, %reg1025 + // r0 = MOV %reg1026 + // Commute the ADD to hopefully eliminate an otherwise unavoidable copy. + unsigned FromRegB = getMappedReg(regB, SrcRegMap); + unsigned FromRegC = getMappedReg(regC, SrcRegMap); + unsigned ToRegB = getMappedReg(regB, DstRegMap); + unsigned ToRegC = getMappedReg(regC, DstRegMap); + if (!regsAreCompatible(FromRegB, ToRegB, TRI) && + (regsAreCompatible(FromRegB, ToRegC, TRI) || + regsAreCompatible(FromRegC, ToRegB, TRI))) + return true; + + // If there is a use of regC between its last def (could be livein) and this + // instruction, then bail. + unsigned LastDefC = 0; + if (!NoUseAfterLastDef(regC, MBB, Dist, LastDefC)) + return false; + + // If there is a use of regB between its last def (could be livein) and this + // instruction, then go ahead and make this transformation. + unsigned LastDefB = 0; + if (!NoUseAfterLastDef(regB, MBB, Dist, LastDefB)) + return true; + + // Since there are no intervening uses for both registers, then commute + // if the def of regC is closer. Its live interval is shorter. + return LastDefB && LastDefC && LastDefC > LastDefB; +} + +/// CommuteInstruction - Commute a two-address instruction and update the basic +/// block, distance map, and live variables if needed. Return true if it is +/// successful. +bool +TwoAddressInstructionPass::CommuteInstruction(MachineBasicBlock::iterator &mi, + MachineFunction::iterator &mbbi, + unsigned RegB, unsigned RegC, unsigned Dist) { + MachineInstr *MI = mi; + DEBUG(errs() << "2addr: COMMUTING : " << *MI); + MachineInstr *NewMI = TII->commuteInstruction(MI); + + if (NewMI == 0) { + DEBUG(errs() << "2addr: COMMUTING FAILED!\n"); + return false; + } + + DEBUG(errs() << "2addr: COMMUTED TO: " << *NewMI); + // If the instruction changed to commute it, update livevar. + if (NewMI != MI) { + if (LV) + // Update live variables + LV->replaceKillInstruction(RegC, MI, NewMI); + + mbbi->insert(mi, NewMI); // Insert the new inst + mbbi->erase(mi); // Nuke the old inst. + mi = NewMI; + DistanceMap.insert(std::make_pair(NewMI, Dist)); + } + + // Update source register map. + unsigned FromRegC = getMappedReg(RegC, SrcRegMap); + if (FromRegC) { + unsigned RegA = MI->getOperand(0).getReg(); + SrcRegMap[RegA] = FromRegC; + } + + return true; +} + +/// isProfitableToConv3Addr - Return true if it is profitable to convert the +/// given 2-address instruction to a 3-address one. +bool +TwoAddressInstructionPass::isProfitableToConv3Addr(unsigned RegA) { + // Look for situations like this: + // %reg1024 = MOV r1 + // %reg1025 = MOV r0 + // %reg1026 = ADD %reg1024, %reg1025 + // r2 = MOV %reg1026 + // Turn ADD into a 3-address instruction to avoid a copy. + unsigned FromRegA = getMappedReg(RegA, SrcRegMap); + unsigned ToRegA = getMappedReg(RegA, DstRegMap); + return (FromRegA && ToRegA && !regsAreCompatible(FromRegA, ToRegA, TRI)); +} + +/// ConvertInstTo3Addr - Convert the specified two-address instruction into a +/// three address one. Return true if this transformation was successful. +bool +TwoAddressInstructionPass::ConvertInstTo3Addr(MachineBasicBlock::iterator &mi, + MachineBasicBlock::iterator &nmi, + MachineFunction::iterator &mbbi, + unsigned RegB, unsigned Dist) { + MachineInstr *NewMI = TII->convertToThreeAddress(mbbi, mi, LV); + if (NewMI) { + DEBUG(errs() << "2addr: CONVERTING 2-ADDR: " << *mi); + DEBUG(errs() << "2addr: TO 3-ADDR: " << *NewMI); + bool Sunk = false; + + if (NewMI->findRegisterUseOperand(RegB, false, TRI)) + // FIXME: Temporary workaround. If the new instruction doesn't + // uses RegB, convertToThreeAddress must have created more + // then one instruction. + Sunk = Sink3AddrInstruction(mbbi, NewMI, RegB, mi); + + mbbi->erase(mi); // Nuke the old inst. + + if (!Sunk) { + DistanceMap.insert(std::make_pair(NewMI, Dist)); + mi = NewMI; + nmi = next(mi); + } + return true; + } + + return false; +} + +/// ProcessCopy - If the specified instruction is not yet processed, process it +/// if it's a copy. For a copy instruction, we find the physical registers the +/// source and destination registers might be mapped to. These are kept in +/// point-to maps used to determine future optimizations. e.g. +/// v1024 = mov r0 +/// v1025 = mov r1 +/// v1026 = add v1024, v1025 +/// r1 = mov r1026 +/// If 'add' is a two-address instruction, v1024, v1026 are both potentially +/// coalesced to r0 (from the input side). v1025 is mapped to r1. v1026 is +/// potentially joined with r1 on the output side. It's worthwhile to commute +/// 'add' to eliminate a copy. +void TwoAddressInstructionPass::ProcessCopy(MachineInstr *MI, + MachineBasicBlock *MBB, + SmallPtrSet &Processed) { + if (Processed.count(MI)) + return; + + bool IsSrcPhys, IsDstPhys; + unsigned SrcReg, DstReg; + if (!isCopyToReg(*MI, TII, SrcReg, DstReg, IsSrcPhys, IsDstPhys)) + return; + + if (IsDstPhys && !IsSrcPhys) + DstRegMap.insert(std::make_pair(SrcReg, DstReg)); + else if (!IsDstPhys && IsSrcPhys) { + bool isNew = SrcRegMap.insert(std::make_pair(DstReg, SrcReg)).second; + if (!isNew) + assert(SrcRegMap[DstReg] == SrcReg && + "Can't map to two src physical registers!"); + + SmallVector VirtRegPairs; + bool IsCopy = false; + unsigned NewReg = 0; + while (MachineInstr *UseMI = findOnlyInterestingUse(DstReg, MBB, MRI,TII, + IsCopy, NewReg, IsDstPhys)) { + if (IsCopy) { + if (!Processed.insert(UseMI)) + break; + } + + DenseMap::iterator DI = DistanceMap.find(UseMI); + if (DI != DistanceMap.end()) + // Earlier in the same MBB.Reached via a back edge. + break; + + if (IsDstPhys) { + VirtRegPairs.push_back(NewReg); + break; + } + bool isNew = SrcRegMap.insert(std::make_pair(NewReg, DstReg)).second; + if (!isNew) + assert(SrcRegMap[NewReg] == DstReg && + "Can't map to two src physical registers!"); + VirtRegPairs.push_back(NewReg); + DstReg = NewReg; + } + + if (!VirtRegPairs.empty()) { + unsigned ToReg = VirtRegPairs.back(); + VirtRegPairs.pop_back(); + while (!VirtRegPairs.empty()) { + unsigned FromReg = VirtRegPairs.back(); + VirtRegPairs.pop_back(); + bool isNew = DstRegMap.insert(std::make_pair(FromReg, ToReg)).second; + if (!isNew) + assert(DstRegMap[FromReg] == ToReg && + "Can't map to two dst physical registers!"); + ToReg = FromReg; + } + } + } + + Processed.insert(MI); +} + +/// isSafeToDelete - If the specified instruction does not produce any side +/// effects and all of its defs are dead, then it's safe to delete. +static bool isSafeToDelete(MachineInstr *MI, + const TargetInstrInfo *TII, + SmallVector &Kills) { + const TargetInstrDesc &TID = MI->getDesc(); + if (TID.mayStore() || TID.isCall()) + return false; + if (TID.isTerminator() || TID.hasUnmodeledSideEffects()) + return false; + + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + MachineOperand &MO = MI->getOperand(i); + if (!MO.isReg()) + continue; + if (MO.isDef() && !MO.isDead()) + return false; + if (MO.isUse() && MO.isKill()) + Kills.push_back(MO.getReg()); + } + return true; +} + +/// canUpdateDeletedKills - Check if all the registers listed in Kills are +/// killed by instructions in MBB preceding the current instruction at +/// position Dist. If so, return true and record information about the +/// preceding kills in NewKills. +bool TwoAddressInstructionPass:: +canUpdateDeletedKills(SmallVector &Kills, + SmallVector &NewKills, + MachineBasicBlock *MBB, unsigned Dist) { + while (!Kills.empty()) { + unsigned Kill = Kills.back(); + Kills.pop_back(); + if (TargetRegisterInfo::isPhysicalRegister(Kill)) + return false; + + MachineInstr *LastKill = FindLastUseInMBB(Kill, MBB, Dist); + if (!LastKill) + return false; + + bool isModRef = LastKill->modifiesRegister(Kill); + NewKills.push_back(std::make_pair(std::make_pair(Kill, isModRef), + LastKill)); + } + return true; +} + +/// DeleteUnusedInstr - If an instruction with a tied register operand can +/// be safely deleted, just delete it. +bool +TwoAddressInstructionPass::DeleteUnusedInstr(MachineBasicBlock::iterator &mi, + MachineBasicBlock::iterator &nmi, + MachineFunction::iterator &mbbi, + unsigned Dist) { + // Check if the instruction has no side effects and if all its defs are dead. + SmallVector Kills; + if (!isSafeToDelete(mi, TII, Kills)) + return false; + + // If this instruction kills some virtual registers, we need to + // update the kill information. If it's not possible to do so, + // then bail out. + SmallVector NewKills; + if (!canUpdateDeletedKills(Kills, NewKills, &*mbbi, Dist)) + return false; + + if (LV) { + while (!NewKills.empty()) { + MachineInstr *NewKill = NewKills.back().second; + unsigned Kill = NewKills.back().first.first; + bool isDead = NewKills.back().first.second; + NewKills.pop_back(); + if (LV->removeVirtualRegisterKilled(Kill, mi)) { + if (isDead) + LV->addVirtualRegisterDead(Kill, NewKill); + else + LV->addVirtualRegisterKilled(Kill, NewKill); + } + } + } + + mbbi->erase(mi); // Nuke the old inst. + mi = nmi; + return true; +} + +/// TryInstructionTransform - For the case where an instruction has a single +/// pair of tied register operands, attempt some transformations that may +/// either eliminate the tied operands or improve the opportunities for +/// coalescing away the register copy. Returns true if the tied operands +/// are eliminated altogether. +bool TwoAddressInstructionPass:: +TryInstructionTransform(MachineBasicBlock::iterator &mi, + MachineBasicBlock::iterator &nmi, + MachineFunction::iterator &mbbi, + unsigned SrcIdx, unsigned DstIdx, unsigned Dist) { + const TargetInstrDesc &TID = mi->getDesc(); + unsigned regA = mi->getOperand(DstIdx).getReg(); + unsigned regB = mi->getOperand(SrcIdx).getReg(); + + assert(TargetRegisterInfo::isVirtualRegister(regB) && + "cannot make instruction into two-address form"); + + // If regA is dead and the instruction can be deleted, just delete + // it so it doesn't clobber regB. + bool regBKilled = isKilled(*mi, regB, MRI, TII); + if (!regBKilled && mi->getOperand(DstIdx).isDead() && + DeleteUnusedInstr(mi, nmi, mbbi, Dist)) { + ++NumDeletes; + return true; // Done with this instruction. + } + + // Check if it is profitable to commute the operands. + unsigned SrcOp1, SrcOp2; + unsigned regC = 0; + unsigned regCIdx = ~0U; + bool TryCommute = false; + bool AggressiveCommute = false; + if (TID.isCommutable() && mi->getNumOperands() >= 3 && + TII->findCommutedOpIndices(mi, SrcOp1, SrcOp2)) { + if (SrcIdx == SrcOp1) + regCIdx = SrcOp2; + else if (SrcIdx == SrcOp2) + regCIdx = SrcOp1; + + if (regCIdx != ~0U) { + regC = mi->getOperand(regCIdx).getReg(); + if (!regBKilled && isKilled(*mi, regC, MRI, TII)) + // If C dies but B does not, swap the B and C operands. + // This makes the live ranges of A and C joinable. + TryCommute = true; + else if (isProfitableToCommute(regB, regC, mi, mbbi, Dist)) { + TryCommute = true; + AggressiveCommute = true; + } + } + } + + // If it's profitable to commute, try to do so. + if (TryCommute && CommuteInstruction(mi, mbbi, regB, regC, Dist)) { + ++NumCommuted; + if (AggressiveCommute) + ++NumAggrCommuted; + return false; + } + + if (TID.isConvertibleTo3Addr()) { + // This instruction is potentially convertible to a true + // three-address instruction. Check if it is profitable. + if (!regBKilled || isProfitableToConv3Addr(regA)) { + // Try to convert it. + if (ConvertInstTo3Addr(mi, nmi, mbbi, regB, Dist)) { + ++NumConvertedTo3Addr; + return true; // Done with this instruction. + } + } + } + return false; +} + +/// runOnMachineFunction - Reduce two-address instructions to two operands. +/// +bool TwoAddressInstructionPass::runOnMachineFunction(MachineFunction &MF) { + DEBUG(errs() << "Machine Function\n"); + const TargetMachine &TM = MF.getTarget(); + MRI = &MF.getRegInfo(); + TII = TM.getInstrInfo(); + TRI = TM.getRegisterInfo(); + LV = getAnalysisIfAvailable(); + AA = &getAnalysis(); + + bool MadeChange = false; + + DEBUG(errs() << "********** REWRITING TWO-ADDR INSTRS **********\n"); + DEBUG(errs() << "********** Function: " + << MF.getFunction()->getName() << '\n'); + + // ReMatRegs - Keep track of the registers whose def's are remat'ed. + BitVector ReMatRegs; + ReMatRegs.resize(MRI->getLastVirtReg()+1); + + typedef DenseMap, 4> > + TiedOperandMap; + TiedOperandMap TiedOperands(4); + + SmallPtrSet Processed; + for (MachineFunction::iterator mbbi = MF.begin(), mbbe = MF.end(); + mbbi != mbbe; ++mbbi) { + unsigned Dist = 0; + DistanceMap.clear(); + SrcRegMap.clear(); + DstRegMap.clear(); + Processed.clear(); + for (MachineBasicBlock::iterator mi = mbbi->begin(), me = mbbi->end(); + mi != me; ) { + MachineBasicBlock::iterator nmi = next(mi); + const TargetInstrDesc &TID = mi->getDesc(); + bool FirstTied = true; + + DistanceMap.insert(std::make_pair(mi, ++Dist)); + + ProcessCopy(&*mi, &*mbbi, Processed); + + // First scan through all the tied register uses in this instruction + // and record a list of pairs of tied operands for each register. + unsigned NumOps = (mi->getOpcode() == TargetInstrInfo::INLINEASM) + ? mi->getNumOperands() : TID.getNumOperands(); + for (unsigned SrcIdx = 0; SrcIdx < NumOps; ++SrcIdx) { + unsigned DstIdx = 0; + if (!mi->isRegTiedToDefOperand(SrcIdx, &DstIdx)) + continue; + + if (FirstTied) { + FirstTied = false; + ++NumTwoAddressInstrs; + DEBUG(errs() << '\t' << *mi); + } + + assert(mi->getOperand(SrcIdx).isReg() && + mi->getOperand(SrcIdx).getReg() && + mi->getOperand(SrcIdx).isUse() && + "two address instruction invalid"); + + unsigned regB = mi->getOperand(SrcIdx).getReg(); + TiedOperandMap::iterator OI = TiedOperands.find(regB); + if (OI == TiedOperands.end()) { + SmallVector, 4> TiedPair; + OI = TiedOperands.insert(std::make_pair(regB, TiedPair)).first; + } + OI->second.push_back(std::make_pair(SrcIdx, DstIdx)); + } + + // Now iterate over the information collected above. + for (TiedOperandMap::iterator OI = TiedOperands.begin(), + OE = TiedOperands.end(); OI != OE; ++OI) { + SmallVector, 4> &TiedPairs = OI->second; + + // If the instruction has a single pair of tied operands, try some + // transformations that may either eliminate the tied operands or + // improve the opportunities for coalescing away the register copy. + if (TiedOperands.size() == 1 && TiedPairs.size() == 1) { + unsigned SrcIdx = TiedPairs[0].first; + unsigned DstIdx = TiedPairs[0].second; + + // If the registers are already equal, nothing needs to be done. + if (mi->getOperand(SrcIdx).getReg() == + mi->getOperand(DstIdx).getReg()) + break; // Done with this instruction. + + if (TryInstructionTransform(mi, nmi, mbbi, SrcIdx, DstIdx, Dist)) + break; // The tied operands have been eliminated. + } + + bool RemovedKillFlag = false; + bool AllUsesCopied = true; + unsigned LastCopiedReg = 0; + unsigned regB = OI->first; + for (unsigned tpi = 0, tpe = TiedPairs.size(); tpi != tpe; ++tpi) { + unsigned SrcIdx = TiedPairs[tpi].first; + unsigned DstIdx = TiedPairs[tpi].second; + unsigned regA = mi->getOperand(DstIdx).getReg(); + // Grab regB from the instruction because it may have changed if the + // instruction was commuted. + regB = mi->getOperand(SrcIdx).getReg(); + + if (regA == regB) { + // The register is tied to multiple destinations (or else we would + // not have continued this far), but this use of the register + // already matches the tied destination. Leave it. + AllUsesCopied = false; + continue; + } + LastCopiedReg = regA; + + assert(TargetRegisterInfo::isVirtualRegister(regB) && + "cannot make instruction into two-address form"); + +#ifndef NDEBUG + // First, verify that we don't have a use of "a" in the instruction + // (a = b + a for example) because our transformation will not + // work. This should never occur because we are in SSA form. + for (unsigned i = 0; i != mi->getNumOperands(); ++i) + assert(i == DstIdx || + !mi->getOperand(i).isReg() || + mi->getOperand(i).getReg() != regA); +#endif + + // Emit a copy or rematerialize the definition. + const TargetRegisterClass *rc = MRI->getRegClass(regB); + MachineInstr *DefMI = MRI->getVRegDef(regB); + // If it's safe and profitable, remat the definition instead of + // copying it. + if (DefMI && + DefMI->getDesc().isAsCheapAsAMove() && + DefMI->isSafeToReMat(TII, regB, AA) && + isProfitableToReMat(regB, rc, mi, DefMI, mbbi, Dist)){ + DEBUG(errs() << "2addr: REMATTING : " << *DefMI << "\n"); + unsigned regASubIdx = mi->getOperand(DstIdx).getSubReg(); + TII->reMaterialize(*mbbi, mi, regA, regASubIdx, DefMI, TRI); + ReMatRegs.set(regB); + ++NumReMats; + } else { + bool Emitted = TII->copyRegToReg(*mbbi, mi, regA, regB, rc, rc); + (void)Emitted; + assert(Emitted && "Unable to issue a copy instruction!\n"); + } + + MachineBasicBlock::iterator prevMI = prior(mi); + // Update DistanceMap. + DistanceMap.insert(std::make_pair(prevMI, Dist)); + DistanceMap[mi] = ++Dist; + + DEBUG(errs() << "\t\tprepend:\t" << *prevMI); + + MachineOperand &MO = mi->getOperand(SrcIdx); + assert(MO.isReg() && MO.getReg() == regB && MO.isUse() && + "inconsistent operand info for 2-reg pass"); + if (MO.isKill()) { + MO.setIsKill(false); + RemovedKillFlag = true; + } + MO.setReg(regA); + } + + if (AllUsesCopied) { + // Replace other (un-tied) uses of regB with LastCopiedReg. + for (unsigned i = 0, e = mi->getNumOperands(); i != e; ++i) { + MachineOperand &MO = mi->getOperand(i); + if (MO.isReg() && MO.getReg() == regB && MO.isUse()) { + if (MO.isKill()) { + MO.setIsKill(false); + RemovedKillFlag = true; + } + MO.setReg(LastCopiedReg); + } + } + + // Update live variables for regB. + if (RemovedKillFlag && LV && LV->getVarInfo(regB).removeKill(mi)) + LV->addVirtualRegisterKilled(regB, prior(mi)); + + } else if (RemovedKillFlag) { + // Some tied uses of regB matched their destination registers, so + // regB is still used in this instruction, but a kill flag was + // removed from a different tied use of regB, so now we need to add + // a kill flag to one of the remaining uses of regB. + for (unsigned i = 0, e = mi->getNumOperands(); i != e; ++i) { + MachineOperand &MO = mi->getOperand(i); + if (MO.isReg() && MO.getReg() == regB && MO.isUse()) { + MO.setIsKill(true); + break; + } + } + } + + MadeChange = true; + + DEBUG(errs() << "\t\trewrite to:\t" << *mi); + } + + // Clear TiedOperands here instead of at the top of the loop + // since most instructions do not have tied operands. + TiedOperands.clear(); + mi = nmi; + } + } + + // Some remat'ed instructions are dead. + int VReg = ReMatRegs.find_first(); + while (VReg != -1) { + if (MRI->use_empty(VReg)) { + MachineInstr *DefMI = MRI->getVRegDef(VReg); + DefMI->eraseFromParent(); + } + VReg = ReMatRegs.find_next(VReg); + } + + return MadeChange; +} diff --git a/libclamav/c++/llvm/lib/CodeGen/UnreachableBlockElim.cpp b/libclamav/c++/llvm/lib/CodeGen/UnreachableBlockElim.cpp new file mode 100644 index 000000000..6ab5db2ed --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/UnreachableBlockElim.cpp @@ -0,0 +1,220 @@ +//===-- UnreachableBlockElim.cpp - Remove unreachable blocks for codegen --===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This pass is an extremely simple version of the SimplifyCFG pass. Its sole +// job is to delete LLVM basic blocks that are not reachable from the entry +// node. To do this, it performs a simple depth first traversal of the CFG, +// then deletes any unvisited nodes. +// +// Note that this pass is really a hack. In particular, the instruction +// selectors for various targets should just not generate code for unreachable +// blocks. Until LLVM has a more systematic way of defining instruction +// selectors, however, we cannot really expect them to handle additional +// complexity. +// +//===----------------------------------------------------------------------===// + +#include "llvm/CodeGen/Passes.h" +#include "llvm/Constant.h" +#include "llvm/Instructions.h" +#include "llvm/Function.h" +#include "llvm/Pass.h" +#include "llvm/Type.h" +#include "llvm/Analysis/ProfileInfo.h" +#include "llvm/CodeGen/MachineDominators.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/CodeGen/MachineLoopInfo.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/Support/CFG.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/ADT/DepthFirstIterator.h" +#include "llvm/ADT/SmallPtrSet.h" +using namespace llvm; + +namespace { + class UnreachableBlockElim : public FunctionPass { + virtual bool runOnFunction(Function &F); + public: + static char ID; // Pass identification, replacement for typeid + UnreachableBlockElim() : FunctionPass(&ID) {} + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.addPreserved(); + } + }; +} +char UnreachableBlockElim::ID = 0; +static RegisterPass +X("unreachableblockelim", "Remove unreachable blocks from the CFG"); + +FunctionPass *llvm::createUnreachableBlockEliminationPass() { + return new UnreachableBlockElim(); +} + +bool UnreachableBlockElim::runOnFunction(Function &F) { + SmallPtrSet Reachable; + + // Mark all reachable blocks. + for (df_ext_iterator > I = + df_ext_begin(&F, Reachable), E = df_ext_end(&F, Reachable); I != E; ++I) + /* Mark all reachable blocks */; + + // Loop over all dead blocks, remembering them and deleting all instructions + // in them. + std::vector DeadBlocks; + for (Function::iterator I = F.begin(), E = F.end(); I != E; ++I) + if (!Reachable.count(I)) { + BasicBlock *BB = I; + DeadBlocks.push_back(BB); + while (PHINode *PN = dyn_cast(BB->begin())) { + PN->replaceAllUsesWith(Constant::getNullValue(PN->getType())); + BB->getInstList().pop_front(); + } + for (succ_iterator SI = succ_begin(BB), E = succ_end(BB); SI != E; ++SI) + (*SI)->removePredecessor(BB); + BB->dropAllReferences(); + } + + // Actually remove the blocks now. + ProfileInfo *PI = getAnalysisIfAvailable(); + for (unsigned i = 0, e = DeadBlocks.size(); i != e; ++i) { + if (PI) PI->removeBlock(DeadBlocks[i]); + DeadBlocks[i]->eraseFromParent(); + } + + return DeadBlocks.size(); +} + + +namespace { + class UnreachableMachineBlockElim : public MachineFunctionPass { + virtual bool runOnMachineFunction(MachineFunction &F); + virtual void getAnalysisUsage(AnalysisUsage &AU) const; + MachineModuleInfo *MMI; + public: + static char ID; // Pass identification, replacement for typeid + UnreachableMachineBlockElim() : MachineFunctionPass(&ID) {} + }; +} +char UnreachableMachineBlockElim::ID = 0; + +static RegisterPass +Y("unreachable-mbb-elimination", + "Remove unreachable machine basic blocks"); + +const PassInfo *const llvm::UnreachableMachineBlockElimID = &Y; + +void UnreachableMachineBlockElim::getAnalysisUsage(AnalysisUsage &AU) const { + AU.addPreserved(); + AU.addPreserved(); + MachineFunctionPass::getAnalysisUsage(AU); +} + +bool UnreachableMachineBlockElim::runOnMachineFunction(MachineFunction &F) { + SmallPtrSet Reachable; + + MMI = getAnalysisIfAvailable(); + MachineDominatorTree *MDT = getAnalysisIfAvailable(); + MachineLoopInfo *MLI = getAnalysisIfAvailable(); + + // Mark all reachable blocks. + for (df_ext_iterator > + I = df_ext_begin(&F, Reachable), E = df_ext_end(&F, Reachable); + I != E; ++I) + /* Mark all reachable blocks */; + + // Loop over all dead blocks, remembering them and deleting all instructions + // in them. + std::vector DeadBlocks; + for (MachineFunction::iterator I = F.begin(), E = F.end(); I != E; ++I) { + MachineBasicBlock *BB = I; + + // Test for deadness. + if (!Reachable.count(BB)) { + DeadBlocks.push_back(BB); + + // Update dominator and loop info. + if (MLI) MLI->removeBlock(BB); + if (MDT && MDT->getNode(BB)) MDT->eraseNode(BB); + + while (BB->succ_begin() != BB->succ_end()) { + MachineBasicBlock* succ = *BB->succ_begin(); + + MachineBasicBlock::iterator start = succ->begin(); + while (start != succ->end() && + start->getOpcode() == TargetInstrInfo::PHI) { + for (unsigned i = start->getNumOperands() - 1; i >= 2; i-=2) + if (start->getOperand(i).isMBB() && + start->getOperand(i).getMBB() == BB) { + start->RemoveOperand(i); + start->RemoveOperand(i-1); + } + + start++; + } + + BB->removeSuccessor(BB->succ_begin()); + } + } + } + + // Actually remove the blocks now. + for (unsigned i = 0, e = DeadBlocks.size(); i != e; ++i) { + MachineBasicBlock *MBB = DeadBlocks[i]; + // If there are any labels in the basic block, unregister them from + // MachineModuleInfo. + if (MMI && !MBB->empty()) { + for (MachineBasicBlock::iterator I = MBB->begin(), + E = MBB->end(); I != E; ++I) { + if (I->isLabel()) + // The label ID # is always operand #0, an immediate. + MMI->InvalidateLabel(I->getOperand(0).getImm()); + } + } + MBB->eraseFromParent(); + } + + // Cleanup PHI nodes. + for (MachineFunction::iterator I = F.begin(), E = F.end(); I != E; ++I) { + MachineBasicBlock *BB = I; + // Prune unneeded PHI entries. + SmallPtrSet preds(BB->pred_begin(), + BB->pred_end()); + MachineBasicBlock::iterator phi = BB->begin(); + while (phi != BB->end() && + phi->getOpcode() == TargetInstrInfo::PHI) { + for (unsigned i = phi->getNumOperands() - 1; i >= 2; i-=2) + if (!preds.count(phi->getOperand(i).getMBB())) { + phi->RemoveOperand(i); + phi->RemoveOperand(i-1); + } + + if (phi->getNumOperands() == 3) { + unsigned Input = phi->getOperand(1).getReg(); + unsigned Output = phi->getOperand(0).getReg(); + + MachineInstr* temp = phi; + ++phi; + temp->eraseFromParent(); + + if (Input != Output) + F.getRegInfo().replaceRegWith(Output, Input); + + continue; + } + + ++phi; + } + } + + F.RenumberBlocks(); + + return DeadBlocks.size(); +} diff --git a/libclamav/c++/llvm/lib/CodeGen/VirtRegMap.cpp b/libclamav/c++/llvm/lib/CodeGen/VirtRegMap.cpp new file mode 100644 index 000000000..c8c5d8615 --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/VirtRegMap.cpp @@ -0,0 +1,282 @@ +//===-- llvm/CodeGen/VirtRegMap.cpp - Virtual Register Map ----------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the VirtRegMap class. +// +// It also contains implementations of the the Spiller interface, which, given a +// virtual register map and a machine function, eliminates all virtual +// references by replacing them with physical register references - adding spill +// code as necessary. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "virtregmap" +#include "VirtRegMap.h" +#include "llvm/Function.h" +#include "llvm/CodeGen/LiveIntervalAnalysis.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/ADT/BitVector.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/DepthFirstIterator.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallSet.h" +#include +using namespace llvm; + +STATISTIC(NumSpills , "Number of register spills"); + +//===----------------------------------------------------------------------===// +// VirtRegMap implementation +//===----------------------------------------------------------------------===// + +char VirtRegMap::ID = 0; + +static RegisterPass +X("virtregmap", "Virtual Register Map"); + +bool VirtRegMap::runOnMachineFunction(MachineFunction &mf) { + MRI = &mf.getRegInfo(); + TII = mf.getTarget().getInstrInfo(); + TRI = mf.getTarget().getRegisterInfo(); + MF = &mf; + + ReMatId = MAX_STACK_SLOT+1; + LowSpillSlot = HighSpillSlot = NO_STACK_SLOT; + + Virt2PhysMap.clear(); + Virt2StackSlotMap.clear(); + Virt2ReMatIdMap.clear(); + Virt2SplitMap.clear(); + Virt2SplitKillMap.clear(); + ReMatMap.clear(); + ImplicitDefed.clear(); + SpillSlotToUsesMap.clear(); + MI2VirtMap.clear(); + SpillPt2VirtMap.clear(); + RestorePt2VirtMap.clear(); + EmergencySpillMap.clear(); + EmergencySpillSlots.clear(); + + SpillSlotToUsesMap.resize(8); + ImplicitDefed.resize(MF->getRegInfo().getLastVirtReg()+1- + TargetRegisterInfo::FirstVirtualRegister); + + allocatableRCRegs.clear(); + for (TargetRegisterInfo::regclass_iterator I = TRI->regclass_begin(), + E = TRI->regclass_end(); I != E; ++I) + allocatableRCRegs.insert(std::make_pair(*I, + TRI->getAllocatableSet(mf, *I))); + + grow(); + + return false; +} + +void VirtRegMap::grow() { + unsigned LastVirtReg = MF->getRegInfo().getLastVirtReg(); + Virt2PhysMap.grow(LastVirtReg); + Virt2StackSlotMap.grow(LastVirtReg); + Virt2ReMatIdMap.grow(LastVirtReg); + Virt2SplitMap.grow(LastVirtReg); + Virt2SplitKillMap.grow(LastVirtReg); + ReMatMap.grow(LastVirtReg); + ImplicitDefed.resize(LastVirtReg-TargetRegisterInfo::FirstVirtualRegister+1); +} + +unsigned VirtRegMap::getRegAllocPref(unsigned virtReg) { + std::pair Hint = MRI->getRegAllocationHint(virtReg); + unsigned physReg = Hint.second; + if (physReg && + TargetRegisterInfo::isVirtualRegister(physReg) && hasPhys(physReg)) + physReg = getPhys(physReg); + if (Hint.first == 0) + return (physReg && TargetRegisterInfo::isPhysicalRegister(physReg)) + ? physReg : 0; + return TRI->ResolveRegAllocHint(Hint.first, physReg, *MF); +} + +int VirtRegMap::assignVirt2StackSlot(unsigned virtReg) { + assert(TargetRegisterInfo::isVirtualRegister(virtReg)); + assert(Virt2StackSlotMap[virtReg] == NO_STACK_SLOT && + "attempt to assign stack slot to already spilled register"); + const TargetRegisterClass* RC = MF->getRegInfo().getRegClass(virtReg); + int SS = MF->getFrameInfo()->CreateSpillStackObject(RC->getSize(), + RC->getAlignment()); + if (LowSpillSlot == NO_STACK_SLOT) + LowSpillSlot = SS; + if (HighSpillSlot == NO_STACK_SLOT || SS > HighSpillSlot) + HighSpillSlot = SS; + unsigned Idx = SS-LowSpillSlot; + while (Idx >= SpillSlotToUsesMap.size()) + SpillSlotToUsesMap.resize(SpillSlotToUsesMap.size()*2); + Virt2StackSlotMap[virtReg] = SS; + ++NumSpills; + return SS; +} + +void VirtRegMap::assignVirt2StackSlot(unsigned virtReg, int SS) { + assert(TargetRegisterInfo::isVirtualRegister(virtReg)); + assert(Virt2StackSlotMap[virtReg] == NO_STACK_SLOT && + "attempt to assign stack slot to already spilled register"); + assert((SS >= 0 || + (SS >= MF->getFrameInfo()->getObjectIndexBegin())) && + "illegal fixed frame index"); + Virt2StackSlotMap[virtReg] = SS; +} + +int VirtRegMap::assignVirtReMatId(unsigned virtReg) { + assert(TargetRegisterInfo::isVirtualRegister(virtReg)); + assert(Virt2ReMatIdMap[virtReg] == NO_STACK_SLOT && + "attempt to assign re-mat id to already spilled register"); + Virt2ReMatIdMap[virtReg] = ReMatId; + return ReMatId++; +} + +void VirtRegMap::assignVirtReMatId(unsigned virtReg, int id) { + assert(TargetRegisterInfo::isVirtualRegister(virtReg)); + assert(Virt2ReMatIdMap[virtReg] == NO_STACK_SLOT && + "attempt to assign re-mat id to already spilled register"); + Virt2ReMatIdMap[virtReg] = id; +} + +int VirtRegMap::getEmergencySpillSlot(const TargetRegisterClass *RC) { + std::map::iterator I = + EmergencySpillSlots.find(RC); + if (I != EmergencySpillSlots.end()) + return I->second; + int SS = MF->getFrameInfo()->CreateSpillStackObject(RC->getSize(), + RC->getAlignment()); + if (LowSpillSlot == NO_STACK_SLOT) + LowSpillSlot = SS; + if (HighSpillSlot == NO_STACK_SLOT || SS > HighSpillSlot) + HighSpillSlot = SS; + EmergencySpillSlots[RC] = SS; + return SS; +} + +void VirtRegMap::addSpillSlotUse(int FI, MachineInstr *MI) { + if (!MF->getFrameInfo()->isFixedObjectIndex(FI)) { + // If FI < LowSpillSlot, this stack reference was produced by + // instruction selection and is not a spill + if (FI >= LowSpillSlot) { + assert(FI >= 0 && "Spill slot index should not be negative!"); + assert((unsigned)FI-LowSpillSlot < SpillSlotToUsesMap.size() + && "Invalid spill slot"); + SpillSlotToUsesMap[FI-LowSpillSlot].insert(MI); + } + } +} + +void VirtRegMap::virtFolded(unsigned VirtReg, MachineInstr *OldMI, + MachineInstr *NewMI, ModRef MRInfo) { + // Move previous memory references folded to new instruction. + MI2VirtMapTy::iterator IP = MI2VirtMap.lower_bound(NewMI); + for (MI2VirtMapTy::iterator I = MI2VirtMap.lower_bound(OldMI), + E = MI2VirtMap.end(); I != E && I->first == OldMI; ) { + MI2VirtMap.insert(IP, std::make_pair(NewMI, I->second)); + MI2VirtMap.erase(I++); + } + + // add new memory reference + MI2VirtMap.insert(IP, std::make_pair(NewMI, std::make_pair(VirtReg, MRInfo))); +} + +void VirtRegMap::virtFolded(unsigned VirtReg, MachineInstr *MI, ModRef MRInfo) { + MI2VirtMapTy::iterator IP = MI2VirtMap.lower_bound(MI); + MI2VirtMap.insert(IP, std::make_pair(MI, std::make_pair(VirtReg, MRInfo))); +} + +void VirtRegMap::RemoveMachineInstrFromMaps(MachineInstr *MI) { + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + MachineOperand &MO = MI->getOperand(i); + if (!MO.isFI()) + continue; + int FI = MO.getIndex(); + if (MF->getFrameInfo()->isFixedObjectIndex(FI)) + continue; + // This stack reference was produced by instruction selection and + // is not a spill + if (FI < LowSpillSlot) + continue; + assert((unsigned)FI-LowSpillSlot < SpillSlotToUsesMap.size() + && "Invalid spill slot"); + SpillSlotToUsesMap[FI-LowSpillSlot].erase(MI); + } + MI2VirtMap.erase(MI); + SpillPt2VirtMap.erase(MI); + RestorePt2VirtMap.erase(MI); + EmergencySpillMap.erase(MI); +} + +/// FindUnusedRegisters - Gather a list of allocatable registers that +/// have not been allocated to any virtual register. +bool VirtRegMap::FindUnusedRegisters(LiveIntervals* LIs) { + unsigned NumRegs = TRI->getNumRegs(); + UnusedRegs.reset(); + UnusedRegs.resize(NumRegs); + + BitVector Used(NumRegs); + for (unsigned i = TargetRegisterInfo::FirstVirtualRegister, + e = MF->getRegInfo().getLastVirtReg(); i <= e; ++i) + if (Virt2PhysMap[i] != (unsigned)VirtRegMap::NO_PHYS_REG) + Used.set(Virt2PhysMap[i]); + + BitVector Allocatable = TRI->getAllocatableSet(*MF); + bool AnyUnused = false; + for (unsigned Reg = 1; Reg < NumRegs; ++Reg) { + if (Allocatable[Reg] && !Used[Reg] && !LIs->hasInterval(Reg)) { + bool ReallyUnused = true; + for (const unsigned *AS = TRI->getAliasSet(Reg); *AS; ++AS) { + if (Used[*AS] || LIs->hasInterval(*AS)) { + ReallyUnused = false; + break; + } + } + if (ReallyUnused) { + AnyUnused = true; + UnusedRegs.set(Reg); + } + } + } + + return AnyUnused; +} + +void VirtRegMap::print(raw_ostream &OS, const Module* M) const { + const TargetRegisterInfo* TRI = MF->getTarget().getRegisterInfo(); + + OS << "********** REGISTER MAP **********\n"; + for (unsigned i = TargetRegisterInfo::FirstVirtualRegister, + e = MF->getRegInfo().getLastVirtReg(); i <= e; ++i) { + if (Virt2PhysMap[i] != (unsigned)VirtRegMap::NO_PHYS_REG) + OS << "[reg" << i << " -> " << TRI->getName(Virt2PhysMap[i]) + << "]\n"; + } + + for (unsigned i = TargetRegisterInfo::FirstVirtualRegister, + e = MF->getRegInfo().getLastVirtReg(); i <= e; ++i) + if (Virt2StackSlotMap[i] != VirtRegMap::NO_STACK_SLOT) + OS << "[reg" << i << " -> fi#" << Virt2StackSlotMap[i] << "]\n"; + OS << '\n'; +} + +void VirtRegMap::dump() const { + print(errs()); +} diff --git a/libclamav/c++/llvm/lib/CodeGen/VirtRegMap.h b/libclamav/c++/llvm/lib/CodeGen/VirtRegMap.h new file mode 100644 index 000000000..a5599f68b --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/VirtRegMap.h @@ -0,0 +1,495 @@ +//===-- llvm/CodeGen/VirtRegMap.h - Virtual Register Map -*- 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 a virtual register map. This maps virtual registers to +// physical registers and virtual registers to stack slots. It is created and +// updated by a register allocator and then used by a machine code rewriter that +// adds spill code and rewrites virtual into physical register references. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_VIRTREGMAP_H +#define LLVM_CODEGEN_VIRTREGMAP_H + +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/LiveInterval.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/ADT/BitVector.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/IndexedMap.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallVector.h" +#include + +namespace llvm { + class LiveIntervals; + class MachineInstr; + class MachineFunction; + class MachineRegisterInfo; + class TargetInstrInfo; + class TargetRegisterInfo; + class raw_ostream; + + class VirtRegMap : public MachineFunctionPass { + public: + enum { + NO_PHYS_REG = 0, + NO_STACK_SLOT = (1L << 30)-1, + MAX_STACK_SLOT = (1L << 18)-1 + }; + + enum ModRef { isRef = 1, isMod = 2, isModRef = 3 }; + typedef std::multimap > MI2VirtMapTy; + + private: + MachineRegisterInfo *MRI; + const TargetInstrInfo *TII; + const TargetRegisterInfo *TRI; + MachineFunction *MF; + + DenseMap allocatableRCRegs; + + /// Virt2PhysMap - This is a virtual to physical register + /// mapping. Each virtual register is required to have an entry in + /// it; even spilled virtual registers (the register mapped to a + /// spilled register is the temporary used to load it from the + /// stack). + IndexedMap Virt2PhysMap; + + /// Virt2StackSlotMap - This is virtual register to stack slot + /// mapping. Each spilled virtual register has an entry in it + /// which corresponds to the stack slot this register is spilled + /// at. + IndexedMap Virt2StackSlotMap; + + /// Virt2ReMatIdMap - This is virtual register to rematerialization id + /// mapping. Each spilled virtual register that should be remat'd has an + /// entry in it which corresponds to the remat id. + IndexedMap Virt2ReMatIdMap; + + /// Virt2SplitMap - This is virtual register to splitted virtual register + /// mapping. + IndexedMap Virt2SplitMap; + + /// Virt2SplitKillMap - This is splitted virtual register to its last use + /// (kill) index mapping. + IndexedMap Virt2SplitKillMap; + + /// ReMatMap - This is virtual register to re-materialized instruction + /// mapping. Each virtual register whose definition is going to be + /// re-materialized has an entry in it. + IndexedMap ReMatMap; + + /// MI2VirtMap - This is MachineInstr to virtual register + /// mapping. In the case of memory spill code being folded into + /// instructions, we need to know which virtual register was + /// read/written by this instruction. + MI2VirtMapTy MI2VirtMap; + + /// SpillPt2VirtMap - This records the virtual registers which should + /// be spilled right after the MachineInstr due to live interval + /// splitting. + std::map > > + SpillPt2VirtMap; + + /// RestorePt2VirtMap - This records the virtual registers which should + /// be restored right before the MachineInstr due to live interval + /// splitting. + std::map > RestorePt2VirtMap; + + /// EmergencySpillMap - This records the physical registers that should + /// be spilled / restored around the MachineInstr since the register + /// allocator has run out of registers. + std::map > EmergencySpillMap; + + /// EmergencySpillSlots - This records emergency spill slots used to + /// spill physical registers when the register allocator runs out of + /// registers. Ideally only one stack slot is used per function per + /// register class. + std::map EmergencySpillSlots; + + /// ReMatId - Instead of assigning a stack slot to a to be rematerialized + /// virtual register, an unique id is being assigned. This keeps track of + /// the highest id used so far. Note, this starts at (1<<18) to avoid + /// conflicts with stack slot numbers. + int ReMatId; + + /// LowSpillSlot, HighSpillSlot - Lowest and highest spill slot indexes. + int LowSpillSlot, HighSpillSlot; + + /// SpillSlotToUsesMap - Records uses for each register spill slot. + SmallVector, 8> SpillSlotToUsesMap; + + /// ImplicitDefed - One bit for each virtual register. If set it indicates + /// the register is implicitly defined. + BitVector ImplicitDefed; + + /// UnusedRegs - A list of physical registers that have not been used. + BitVector UnusedRegs; + + VirtRegMap(const VirtRegMap&); // DO NOT IMPLEMENT + void operator=(const VirtRegMap&); // DO NOT IMPLEMENT + + public: + static char ID; + VirtRegMap() : MachineFunctionPass(&ID), Virt2PhysMap(NO_PHYS_REG), + Virt2StackSlotMap(NO_STACK_SLOT), + Virt2ReMatIdMap(NO_STACK_SLOT), Virt2SplitMap(0), + Virt2SplitKillMap(SlotIndex()), ReMatMap(NULL), + ReMatId(MAX_STACK_SLOT+1), + LowSpillSlot(NO_STACK_SLOT), HighSpillSlot(NO_STACK_SLOT) { } + virtual bool runOnMachineFunction(MachineFunction &MF); + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + MachineFunctionPass::getAnalysisUsage(AU); + } + + void grow(); + + /// @brief returns true if the specified virtual register is + /// mapped to a physical register + bool hasPhys(unsigned virtReg) const { + return getPhys(virtReg) != NO_PHYS_REG; + } + + /// @brief returns the physical register mapped to the specified + /// virtual register + unsigned getPhys(unsigned virtReg) const { + assert(TargetRegisterInfo::isVirtualRegister(virtReg)); + return Virt2PhysMap[virtReg]; + } + + /// @brief creates a mapping for the specified virtual register to + /// the specified physical register + void assignVirt2Phys(unsigned virtReg, unsigned physReg) { + assert(TargetRegisterInfo::isVirtualRegister(virtReg) && + TargetRegisterInfo::isPhysicalRegister(physReg)); + assert(Virt2PhysMap[virtReg] == NO_PHYS_REG && + "attempt to assign physical register to already mapped " + "virtual register"); + Virt2PhysMap[virtReg] = physReg; + } + + /// @brief clears the specified virtual register's, physical + /// register mapping + void clearVirt(unsigned virtReg) { + assert(TargetRegisterInfo::isVirtualRegister(virtReg)); + assert(Virt2PhysMap[virtReg] != NO_PHYS_REG && + "attempt to clear a not assigned virtual register"); + Virt2PhysMap[virtReg] = NO_PHYS_REG; + } + + /// @brief clears all virtual to physical register mappings + void clearAllVirt() { + Virt2PhysMap.clear(); + grow(); + } + + /// @brief returns the register allocation preference. + unsigned getRegAllocPref(unsigned virtReg); + + /// @brief records virtReg is a split live interval from SReg. + void setIsSplitFromReg(unsigned virtReg, unsigned SReg) { + Virt2SplitMap[virtReg] = SReg; + } + + /// @brief returns the live interval virtReg is split from. + unsigned getPreSplitReg(unsigned virtReg) { + return Virt2SplitMap[virtReg]; + } + + /// @brief returns true if the specified virtual register is not + /// mapped to a stack slot or rematerialized. + bool isAssignedReg(unsigned virtReg) const { + if (getStackSlot(virtReg) == NO_STACK_SLOT && + getReMatId(virtReg) == NO_STACK_SLOT) + return true; + // Split register can be assigned a physical register as well as a + // stack slot or remat id. + return (Virt2SplitMap[virtReg] && Virt2PhysMap[virtReg] != NO_PHYS_REG); + } + + /// @brief returns the stack slot mapped to the specified virtual + /// register + int getStackSlot(unsigned virtReg) const { + assert(TargetRegisterInfo::isVirtualRegister(virtReg)); + return Virt2StackSlotMap[virtReg]; + } + + /// @brief returns the rematerialization id mapped to the specified virtual + /// register + int getReMatId(unsigned virtReg) const { + assert(TargetRegisterInfo::isVirtualRegister(virtReg)); + return Virt2ReMatIdMap[virtReg]; + } + + /// @brief create a mapping for the specifed virtual register to + /// the next available stack slot + int assignVirt2StackSlot(unsigned virtReg); + /// @brief create a mapping for the specified virtual register to + /// the specified stack slot + void assignVirt2StackSlot(unsigned virtReg, int frameIndex); + + /// @brief assign an unique re-materialization id to the specified + /// virtual register. + int assignVirtReMatId(unsigned virtReg); + /// @brief assign an unique re-materialization id to the specified + /// virtual register. + void assignVirtReMatId(unsigned virtReg, int id); + + /// @brief returns true if the specified virtual register is being + /// re-materialized. + bool isReMaterialized(unsigned virtReg) const { + return ReMatMap[virtReg] != NULL; + } + + /// @brief returns the original machine instruction being re-issued + /// to re-materialize the specified virtual register. + MachineInstr *getReMaterializedMI(unsigned virtReg) const { + return ReMatMap[virtReg]; + } + + /// @brief records the specified virtual register will be + /// re-materialized and the original instruction which will be re-issed + /// for this purpose. If parameter all is true, then all uses of the + /// registers are rematerialized and it's safe to delete the definition. + void setVirtIsReMaterialized(unsigned virtReg, MachineInstr *def) { + ReMatMap[virtReg] = def; + } + + /// @brief record the last use (kill) of a split virtual register. + void addKillPoint(unsigned virtReg, SlotIndex index) { + Virt2SplitKillMap[virtReg] = index; + } + + SlotIndex getKillPoint(unsigned virtReg) const { + return Virt2SplitKillMap[virtReg]; + } + + /// @brief remove the last use (kill) of a split virtual register. + void removeKillPoint(unsigned virtReg) { + Virt2SplitKillMap[virtReg] = SlotIndex(); + } + + /// @brief returns true if the specified MachineInstr is a spill point. + bool isSpillPt(MachineInstr *Pt) const { + return SpillPt2VirtMap.find(Pt) != SpillPt2VirtMap.end(); + } + + /// @brief returns the virtual registers that should be spilled due to + /// splitting right after the specified MachineInstr. + std::vector > &getSpillPtSpills(MachineInstr *Pt) { + return SpillPt2VirtMap[Pt]; + } + + /// @brief records the specified MachineInstr as a spill point for virtReg. + void addSpillPoint(unsigned virtReg, bool isKill, MachineInstr *Pt) { + std::map > >::iterator + I = SpillPt2VirtMap.find(Pt); + if (I != SpillPt2VirtMap.end()) + I->second.push_back(std::make_pair(virtReg, isKill)); + else { + std::vector > Virts; + Virts.push_back(std::make_pair(virtReg, isKill)); + SpillPt2VirtMap.insert(std::make_pair(Pt, Virts)); + } + } + + /// @brief - transfer spill point information from one instruction to + /// another. + void transferSpillPts(MachineInstr *Old, MachineInstr *New) { + std::map > >::iterator + I = SpillPt2VirtMap.find(Old); + if (I == SpillPt2VirtMap.end()) + return; + while (!I->second.empty()) { + unsigned virtReg = I->second.back().first; + bool isKill = I->second.back().second; + I->second.pop_back(); + addSpillPoint(virtReg, isKill, New); + } + SpillPt2VirtMap.erase(I); + } + + /// @brief returns true if the specified MachineInstr is a restore point. + bool isRestorePt(MachineInstr *Pt) const { + return RestorePt2VirtMap.find(Pt) != RestorePt2VirtMap.end(); + } + + /// @brief returns the virtual registers that should be restoreed due to + /// splitting right after the specified MachineInstr. + std::vector &getRestorePtRestores(MachineInstr *Pt) { + return RestorePt2VirtMap[Pt]; + } + + /// @brief records the specified MachineInstr as a restore point for virtReg. + void addRestorePoint(unsigned virtReg, MachineInstr *Pt) { + std::map >::iterator I = + RestorePt2VirtMap.find(Pt); + if (I != RestorePt2VirtMap.end()) + I->second.push_back(virtReg); + else { + std::vector Virts; + Virts.push_back(virtReg); + RestorePt2VirtMap.insert(std::make_pair(Pt, Virts)); + } + } + + /// @brief - transfer restore point information from one instruction to + /// another. + void transferRestorePts(MachineInstr *Old, MachineInstr *New) { + std::map >::iterator I = + RestorePt2VirtMap.find(Old); + if (I == RestorePt2VirtMap.end()) + return; + while (!I->second.empty()) { + unsigned virtReg = I->second.back(); + I->second.pop_back(); + addRestorePoint(virtReg, New); + } + RestorePt2VirtMap.erase(I); + } + + /// @brief records that the specified physical register must be spilled + /// around the specified machine instr. + void addEmergencySpill(unsigned PhysReg, MachineInstr *MI) { + if (EmergencySpillMap.find(MI) != EmergencySpillMap.end()) + EmergencySpillMap[MI].push_back(PhysReg); + else { + std::vector PhysRegs; + PhysRegs.push_back(PhysReg); + EmergencySpillMap.insert(std::make_pair(MI, PhysRegs)); + } + } + + /// @brief returns true if one or more physical registers must be spilled + /// around the specified instruction. + bool hasEmergencySpills(MachineInstr *MI) const { + return EmergencySpillMap.find(MI) != EmergencySpillMap.end(); + } + + /// @brief returns the physical registers to be spilled and restored around + /// the instruction. + std::vector &getEmergencySpills(MachineInstr *MI) { + return EmergencySpillMap[MI]; + } + + /// @brief - transfer emergency spill information from one instruction to + /// another. + void transferEmergencySpills(MachineInstr *Old, MachineInstr *New) { + std::map >::iterator I = + EmergencySpillMap.find(Old); + if (I == EmergencySpillMap.end()) + return; + while (!I->second.empty()) { + unsigned virtReg = I->second.back(); + I->second.pop_back(); + addEmergencySpill(virtReg, New); + } + EmergencySpillMap.erase(I); + } + + /// @brief return or get a emergency spill slot for the register class. + int getEmergencySpillSlot(const TargetRegisterClass *RC); + + /// @brief Return lowest spill slot index. + int getLowSpillSlot() const { + return LowSpillSlot; + } + + /// @brief Return highest spill slot index. + int getHighSpillSlot() const { + return HighSpillSlot; + } + + /// @brief Records a spill slot use. + void addSpillSlotUse(int FrameIndex, MachineInstr *MI); + + /// @brief Returns true if spill slot has been used. + bool isSpillSlotUsed(int FrameIndex) const { + assert(FrameIndex >= 0 && "Spill slot index should not be negative!"); + return !SpillSlotToUsesMap[FrameIndex-LowSpillSlot].empty(); + } + + /// @brief Mark the specified register as being implicitly defined. + void setIsImplicitlyDefined(unsigned VirtReg) { + ImplicitDefed.set(VirtReg-TargetRegisterInfo::FirstVirtualRegister); + } + + /// @brief Returns true if the virtual register is implicitly defined. + bool isImplicitlyDefined(unsigned VirtReg) const { + return ImplicitDefed[VirtReg-TargetRegisterInfo::FirstVirtualRegister]; + } + + /// @brief Updates information about the specified virtual register's value + /// folded into newMI machine instruction. + void virtFolded(unsigned VirtReg, MachineInstr *OldMI, MachineInstr *NewMI, + ModRef MRInfo); + + /// @brief Updates information about the specified virtual register's value + /// folded into the specified machine instruction. + void virtFolded(unsigned VirtReg, MachineInstr *MI, ModRef MRInfo); + + /// @brief returns the virtual registers' values folded in memory + /// operands of this instruction + std::pair + getFoldedVirts(MachineInstr* MI) const { + return MI2VirtMap.equal_range(MI); + } + + /// RemoveMachineInstrFromMaps - MI is being erased, remove it from the + /// the folded instruction map and spill point map. + void RemoveMachineInstrFromMaps(MachineInstr *MI); + + /// FindUnusedRegisters - Gather a list of allocatable registers that + /// have not been allocated to any virtual register. + bool FindUnusedRegisters(LiveIntervals* LIs); + + /// HasUnusedRegisters - Return true if there are any allocatable registers + /// that have not been allocated to any virtual register. + bool HasUnusedRegisters() const { + return !UnusedRegs.none(); + } + + /// setRegisterUsed - Remember the physical register is now used. + void setRegisterUsed(unsigned Reg) { + UnusedRegs.reset(Reg); + } + + /// isRegisterUnused - Return true if the physical register has not been + /// used. + bool isRegisterUnused(unsigned Reg) const { + return UnusedRegs[Reg]; + } + + /// getFirstUnusedRegister - Return the first physical register that has not + /// been used. + unsigned getFirstUnusedRegister(const TargetRegisterClass *RC) { + int Reg = UnusedRegs.find_first(); + while (Reg != -1) { + if (allocatableRCRegs[RC][Reg]) + return (unsigned)Reg; + Reg = UnusedRegs.find_next(Reg); + } + return 0; + } + + void print(raw_ostream &OS, const Module* M = 0) const; + void dump() const; + }; + + inline raw_ostream &operator<<(raw_ostream &OS, const VirtRegMap &VRM) { + VRM.print(OS); + return OS; + } +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/lib/CodeGen/VirtRegRewriter.cpp b/libclamav/c++/llvm/lib/CodeGen/VirtRegRewriter.cpp new file mode 100644 index 000000000..10c806677 --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/VirtRegRewriter.cpp @@ -0,0 +1,2434 @@ +//===-- llvm/CodeGen/Rewriter.cpp - Rewriter -----------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "virtregrewriter" +#include "VirtRegRewriter.h" +#include "llvm/Function.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetLowering.h" +#include "llvm/ADT/DepthFirstIterator.h" +#include "llvm/ADT/Statistic.h" +#include +using namespace llvm; + +STATISTIC(NumDSE , "Number of dead stores elided"); +STATISTIC(NumDSS , "Number of dead spill slots removed"); +STATISTIC(NumCommutes, "Number of instructions commuted"); +STATISTIC(NumDRM , "Number of re-materializable defs elided"); +STATISTIC(NumStores , "Number of stores added"); +STATISTIC(NumPSpills , "Number of physical register spills"); +STATISTIC(NumOmitted , "Number of reloads omited"); +STATISTIC(NumAvoided , "Number of reloads deemed unnecessary"); +STATISTIC(NumCopified, "Number of available reloads turned into copies"); +STATISTIC(NumReMats , "Number of re-materialization"); +STATISTIC(NumLoads , "Number of loads added"); +STATISTIC(NumReused , "Number of values reused"); +STATISTIC(NumDCE , "Number of copies elided"); +STATISTIC(NumSUnfold , "Number of stores unfolded"); +STATISTIC(NumModRefUnfold, "Number of modref unfolded"); + +namespace { + enum RewriterName { local, trivial }; +} + +static cl::opt +RewriterOpt("rewriter", + cl::desc("Rewriter to use: (default: local)"), + cl::Prefix, + cl::values(clEnumVal(local, "local rewriter"), + clEnumVal(trivial, "trivial rewriter"), + clEnumValEnd), + cl::init(local)); + +static cl::opt +ScheduleSpills("schedule-spills", + cl::desc("Schedule spill code"), + cl::init(false)); + +VirtRegRewriter::~VirtRegRewriter() {} + +namespace { + +/// This class is intended for use with the new spilling framework only. It +/// rewrites vreg def/uses to use the assigned preg, but does not insert any +/// spill code. +struct TrivialRewriter : public VirtRegRewriter { + + bool runOnMachineFunction(MachineFunction &MF, VirtRegMap &VRM, + LiveIntervals* LIs) { + DEBUG(errs() << "********** REWRITE MACHINE CODE **********\n"); + DEBUG(errs() << "********** Function: " + << MF.getFunction()->getName() << '\n'); + DEBUG(errs() << "**** Machine Instrs" + << "(NOTE! Does not include spills and reloads!) ****\n"); + DEBUG(MF.dump()); + + MachineRegisterInfo *mri = &MF.getRegInfo(); + const TargetRegisterInfo *tri = MF.getTarget().getRegisterInfo(); + + bool changed = false; + + for (LiveIntervals::iterator liItr = LIs->begin(), liEnd = LIs->end(); + liItr != liEnd; ++liItr) { + + const LiveInterval *li = liItr->second; + unsigned reg = li->reg; + + if (TargetRegisterInfo::isPhysicalRegister(reg)) { + if (!li->empty()) + mri->setPhysRegUsed(reg); + } + else { + if (!VRM.hasPhys(reg)) + continue; + unsigned pReg = VRM.getPhys(reg); + mri->setPhysRegUsed(pReg); + for (MachineRegisterInfo::reg_iterator regItr = mri->reg_begin(reg), + regEnd = mri->reg_end(); regItr != regEnd;) { + MachineOperand &mop = regItr.getOperand(); + assert(mop.isReg() && mop.getReg() == reg && "reg_iterator broken?"); + ++regItr; + unsigned subRegIdx = mop.getSubReg(); + unsigned pRegOp = subRegIdx ? tri->getSubReg(pReg, subRegIdx) : pReg; + mop.setReg(pRegOp); + mop.setSubReg(0); + changed = true; + } + } + } + + DEBUG(errs() << "**** Post Machine Instrs ****\n"); + DEBUG(MF.dump()); + + return changed; + } + +}; + +} + +// ************************************************************************ // + +namespace { + +/// AvailableSpills - As the local rewriter is scanning and rewriting an MBB +/// from top down, keep track of which spill slots or remat are available in +/// each register. +/// +/// Note that not all physregs are created equal here. In particular, some +/// physregs are reloads that we are allowed to clobber or ignore at any time. +/// Other physregs are values that the register allocated program is using +/// that we cannot CHANGE, but we can read if we like. We keep track of this +/// on a per-stack-slot / remat id basis as the low bit in the value of the +/// SpillSlotsAvailable entries. The predicate 'canClobberPhysReg()' checks +/// this bit and addAvailable sets it if. +class AvailableSpills { + const TargetRegisterInfo *TRI; + const TargetInstrInfo *TII; + + // SpillSlotsOrReMatsAvailable - This map keeps track of all of the spilled + // or remat'ed virtual register values that are still available, due to + // being loaded or stored to, but not invalidated yet. + std::map SpillSlotsOrReMatsAvailable; + + // PhysRegsAvailable - This is the inverse of SpillSlotsOrReMatsAvailable, + // indicating which stack slot values are currently held by a physreg. This + // is used to invalidate entries in SpillSlotsOrReMatsAvailable when a + // physreg is modified. + std::multimap PhysRegsAvailable; + + void disallowClobberPhysRegOnly(unsigned PhysReg); + + void ClobberPhysRegOnly(unsigned PhysReg); +public: + AvailableSpills(const TargetRegisterInfo *tri, const TargetInstrInfo *tii) + : TRI(tri), TII(tii) { + } + + /// clear - Reset the state. + void clear() { + SpillSlotsOrReMatsAvailable.clear(); + PhysRegsAvailable.clear(); + } + + const TargetRegisterInfo *getRegInfo() const { return TRI; } + + /// getSpillSlotOrReMatPhysReg - If the specified stack slot or remat is + /// available in a physical register, return that PhysReg, otherwise + /// return 0. + unsigned getSpillSlotOrReMatPhysReg(int Slot) const { + std::map::const_iterator I = + SpillSlotsOrReMatsAvailable.find(Slot); + if (I != SpillSlotsOrReMatsAvailable.end()) { + return I->second >> 1; // Remove the CanClobber bit. + } + return 0; + } + + /// addAvailable - Mark that the specified stack slot / remat is available + /// in the specified physreg. If CanClobber is true, the physreg can be + /// modified at any time without changing the semantics of the program. + void addAvailable(int SlotOrReMat, unsigned Reg, bool CanClobber = true) { + // If this stack slot is thought to be available in some other physreg, + // remove its record. + ModifyStackSlotOrReMat(SlotOrReMat); + + PhysRegsAvailable.insert(std::make_pair(Reg, SlotOrReMat)); + SpillSlotsOrReMatsAvailable[SlotOrReMat]= (Reg << 1) | + (unsigned)CanClobber; + + if (SlotOrReMat > VirtRegMap::MAX_STACK_SLOT) + DEBUG(errs() << "Remembering RM#" + << SlotOrReMat-VirtRegMap::MAX_STACK_SLOT-1); + else + DEBUG(errs() << "Remembering SS#" << SlotOrReMat); + DEBUG(errs() << " in physreg " << TRI->getName(Reg) << "\n"); + } + + /// canClobberPhysRegForSS - Return true if the spiller is allowed to change + /// the value of the specified stackslot register if it desires. The + /// specified stack slot must be available in a physreg for this query to + /// make sense. + bool canClobberPhysRegForSS(int SlotOrReMat) const { + assert(SpillSlotsOrReMatsAvailable.count(SlotOrReMat) && + "Value not available!"); + return SpillSlotsOrReMatsAvailable.find(SlotOrReMat)->second & 1; + } + + /// canClobberPhysReg - Return true if the spiller is allowed to clobber the + /// physical register where values for some stack slot(s) might be + /// available. + bool canClobberPhysReg(unsigned PhysReg) const { + std::multimap::const_iterator I = + PhysRegsAvailable.lower_bound(PhysReg); + while (I != PhysRegsAvailable.end() && I->first == PhysReg) { + int SlotOrReMat = I->second; + I++; + if (!canClobberPhysRegForSS(SlotOrReMat)) + return false; + } + return true; + } + + /// disallowClobberPhysReg - Unset the CanClobber bit of the specified + /// stackslot register. The register is still available but is no longer + /// allowed to be modifed. + void disallowClobberPhysReg(unsigned PhysReg); + + /// ClobberPhysReg - This is called when the specified physreg changes + /// value. We use this to invalidate any info about stuff that lives in + /// it and any of its aliases. + void ClobberPhysReg(unsigned PhysReg); + + /// ModifyStackSlotOrReMat - This method is called when the value in a stack + /// slot changes. This removes information about which register the + /// previous value for this slot lives in (as the previous value is dead + /// now). + void ModifyStackSlotOrReMat(int SlotOrReMat); + + /// AddAvailableRegsToLiveIn - Availability information is being kept coming + /// into the specified MBB. Add available physical registers as potential + /// live-in's. If they are reused in the MBB, they will be added to the + /// live-in set to make register scavenger and post-allocation scheduler. + void AddAvailableRegsToLiveIn(MachineBasicBlock &MBB, BitVector &RegKills, + std::vector &KillOps); +}; + +} + +// ************************************************************************ // + +// Given a location where a reload of a spilled register or a remat of +// a constant is to be inserted, attempt to find a safe location to +// insert the load at an earlier point in the basic-block, to hide +// latency of the load and to avoid address-generation interlock +// issues. +static MachineBasicBlock::iterator +ComputeReloadLoc(MachineBasicBlock::iterator const InsertLoc, + MachineBasicBlock::iterator const Begin, + unsigned PhysReg, + const TargetRegisterInfo *TRI, + bool DoReMat, + int SSorRMId, + const TargetInstrInfo *TII, + const MachineFunction &MF) +{ + if (!ScheduleSpills) + return InsertLoc; + + // Spill backscheduling is of primary interest to addresses, so + // don't do anything if the register isn't in the register class + // used for pointers. + + const TargetLowering *TL = MF.getTarget().getTargetLowering(); + + if (!TL->isTypeLegal(TL->getPointerTy())) + // Believe it or not, this is true on PIC16. + return InsertLoc; + + const TargetRegisterClass *ptrRegClass = + TL->getRegClassFor(TL->getPointerTy()); + if (!ptrRegClass->contains(PhysReg)) + return InsertLoc; + + // Scan upwards through the preceding instructions. If an instruction doesn't + // reference the stack slot or the register we're loading, we can + // backschedule the reload up past it. + MachineBasicBlock::iterator NewInsertLoc = InsertLoc; + while (NewInsertLoc != Begin) { + MachineBasicBlock::iterator Prev = prior(NewInsertLoc); + for (unsigned i = 0; i < Prev->getNumOperands(); ++i) { + MachineOperand &Op = Prev->getOperand(i); + if (!DoReMat && Op.isFI() && Op.getIndex() == SSorRMId) + goto stop; + } + if (Prev->findRegisterUseOperandIdx(PhysReg) != -1 || + Prev->findRegisterDefOperand(PhysReg)) + goto stop; + for (const unsigned *Alias = TRI->getAliasSet(PhysReg); *Alias; ++Alias) + if (Prev->findRegisterUseOperandIdx(*Alias) != -1 || + Prev->findRegisterDefOperand(*Alias)) + goto stop; + NewInsertLoc = Prev; + } +stop:; + + // If we made it to the beginning of the block, turn around and move back + // down just past any existing reloads. They're likely to be reloads/remats + // for instructions earlier than what our current reload/remat is for, so + // they should be scheduled earlier. + if (NewInsertLoc == Begin) { + int FrameIdx; + while (InsertLoc != NewInsertLoc && + (TII->isLoadFromStackSlot(NewInsertLoc, FrameIdx) || + TII->isTriviallyReMaterializable(NewInsertLoc))) + ++NewInsertLoc; + } + + return NewInsertLoc; +} + +namespace { + +// ReusedOp - For each reused operand, we keep track of a bit of information, +// in case we need to rollback upon processing a new operand. See comments +// below. +struct ReusedOp { + // The MachineInstr operand that reused an available value. + unsigned Operand; + + // StackSlotOrReMat - The spill slot or remat id of the value being reused. + unsigned StackSlotOrReMat; + + // PhysRegReused - The physical register the value was available in. + unsigned PhysRegReused; + + // AssignedPhysReg - The physreg that was assigned for use by the reload. + unsigned AssignedPhysReg; + + // VirtReg - The virtual register itself. + unsigned VirtReg; + + ReusedOp(unsigned o, unsigned ss, unsigned prr, unsigned apr, + unsigned vreg) + : Operand(o), StackSlotOrReMat(ss), PhysRegReused(prr), + AssignedPhysReg(apr), VirtReg(vreg) {} +}; + +/// ReuseInfo - This maintains a collection of ReuseOp's for each operand that +/// is reused instead of reloaded. +class ReuseInfo { + MachineInstr &MI; + std::vector Reuses; + BitVector PhysRegsClobbered; +public: + ReuseInfo(MachineInstr &mi, const TargetRegisterInfo *tri) : MI(mi) { + PhysRegsClobbered.resize(tri->getNumRegs()); + } + + bool hasReuses() const { + return !Reuses.empty(); + } + + /// addReuse - If we choose to reuse a virtual register that is already + /// available instead of reloading it, remember that we did so. + void addReuse(unsigned OpNo, unsigned StackSlotOrReMat, + unsigned PhysRegReused, unsigned AssignedPhysReg, + unsigned VirtReg) { + // If the reload is to the assigned register anyway, no undo will be + // required. + if (PhysRegReused == AssignedPhysReg) return; + + // Otherwise, remember this. + Reuses.push_back(ReusedOp(OpNo, StackSlotOrReMat, PhysRegReused, + AssignedPhysReg, VirtReg)); + } + + void markClobbered(unsigned PhysReg) { + PhysRegsClobbered.set(PhysReg); + } + + bool isClobbered(unsigned PhysReg) const { + return PhysRegsClobbered.test(PhysReg); + } + + /// GetRegForReload - We are about to emit a reload into PhysReg. If there + /// is some other operand that is using the specified register, either pick + /// a new register to use, or evict the previous reload and use this reg. + unsigned GetRegForReload(const TargetRegisterClass *RC, unsigned PhysReg, + MachineFunction &MF, MachineInstr *MI, + AvailableSpills &Spills, + std::vector &MaybeDeadStores, + SmallSet &Rejected, + BitVector &RegKills, + std::vector &KillOps, + VirtRegMap &VRM); + + /// GetRegForReload - Helper for the above GetRegForReload(). Add a + /// 'Rejected' set to remember which registers have been considered and + /// rejected for the reload. This avoids infinite looping in case like + /// this: + /// t1 := op t2, t3 + /// t2 <- assigned r0 for use by the reload but ended up reuse r1 + /// t3 <- assigned r1 for use by the reload but ended up reuse r0 + /// t1 <- desires r1 + /// sees r1 is taken by t2, tries t2's reload register r0 + /// sees r0 is taken by t3, tries t3's reload register r1 + /// sees r1 is taken by t2, tries t2's reload register r0 ... + unsigned GetRegForReload(unsigned VirtReg, unsigned PhysReg, MachineInstr *MI, + AvailableSpills &Spills, + std::vector &MaybeDeadStores, + BitVector &RegKills, + std::vector &KillOps, + VirtRegMap &VRM) { + SmallSet Rejected; + MachineFunction &MF = *MI->getParent()->getParent(); + const TargetRegisterClass* RC = MF.getRegInfo().getRegClass(VirtReg); + return GetRegForReload(RC, PhysReg, MF, MI, Spills, MaybeDeadStores, + Rejected, RegKills, KillOps, VRM); + } +}; + +} + +// ****************** // +// Utility Functions // +// ****************** // + +/// findSinglePredSuccessor - Return via reference a vector of machine basic +/// blocks each of which is a successor of the specified BB and has no other +/// predecessor. +static void findSinglePredSuccessor(MachineBasicBlock *MBB, + SmallVectorImpl &Succs) { + for (MachineBasicBlock::succ_iterator SI = MBB->succ_begin(), + SE = MBB->succ_end(); SI != SE; ++SI) { + MachineBasicBlock *SuccMBB = *SI; + if (SuccMBB->pred_size() == 1) + Succs.push_back(SuccMBB); + } +} + +/// InvalidateKill - Invalidate register kill information for a specific +/// register. This also unsets the kills marker on the last kill operand. +static void InvalidateKill(unsigned Reg, + const TargetRegisterInfo* TRI, + BitVector &RegKills, + std::vector &KillOps) { + if (RegKills[Reg]) { + KillOps[Reg]->setIsKill(false); + // KillOps[Reg] might be a def of a super-register. + unsigned KReg = KillOps[Reg]->getReg(); + KillOps[KReg] = NULL; + RegKills.reset(KReg); + for (const unsigned *SR = TRI->getSubRegisters(KReg); *SR; ++SR) { + if (RegKills[*SR]) { + KillOps[*SR]->setIsKill(false); + KillOps[*SR] = NULL; + RegKills.reset(*SR); + } + } + } +} + +/// InvalidateKills - MI is going to be deleted. If any of its operands are +/// marked kill, then invalidate the information. +static void InvalidateKills(MachineInstr &MI, + const TargetRegisterInfo* TRI, + BitVector &RegKills, + std::vector &KillOps, + SmallVector *KillRegs = NULL) { + for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) { + MachineOperand &MO = MI.getOperand(i); + if (!MO.isReg() || !MO.isUse() || !MO.isKill() || MO.isUndef()) + continue; + unsigned Reg = MO.getReg(); + if (TargetRegisterInfo::isVirtualRegister(Reg)) + continue; + if (KillRegs) + KillRegs->push_back(Reg); + assert(Reg < KillOps.size()); + if (KillOps[Reg] == &MO) { + KillOps[Reg] = NULL; + RegKills.reset(Reg); + for (const unsigned *SR = TRI->getSubRegisters(Reg); *SR; ++SR) { + if (RegKills[*SR]) { + KillOps[*SR] = NULL; + RegKills.reset(*SR); + } + } + } + } +} + +/// InvalidateRegDef - If the def operand of the specified def MI is now dead +/// (since its spill instruction is removed), mark it isDead. Also checks if +/// the def MI has other definition operands that are not dead. Returns it by +/// reference. +static bool InvalidateRegDef(MachineBasicBlock::iterator I, + MachineInstr &NewDef, unsigned Reg, + bool &HasLiveDef, + const TargetRegisterInfo *TRI) { + // Due to remat, it's possible this reg isn't being reused. That is, + // the def of this reg (by prev MI) is now dead. + MachineInstr *DefMI = I; + MachineOperand *DefOp = NULL; + for (unsigned i = 0, e = DefMI->getNumOperands(); i != e; ++i) { + MachineOperand &MO = DefMI->getOperand(i); + if (!MO.isReg() || !MO.isDef() || !MO.isKill() || MO.isUndef()) + continue; + if (MO.getReg() == Reg) + DefOp = &MO; + else if (!MO.isDead()) + HasLiveDef = true; + } + if (!DefOp) + return false; + + bool FoundUse = false, Done = false; + MachineBasicBlock::iterator E = &NewDef; + ++I; ++E; + for (; !Done && I != E; ++I) { + MachineInstr *NMI = I; + for (unsigned j = 0, ee = NMI->getNumOperands(); j != ee; ++j) { + MachineOperand &MO = NMI->getOperand(j); + if (!MO.isReg() || MO.getReg() == 0 || + (MO.getReg() != Reg && !TRI->isSubRegister(Reg, MO.getReg()))) + continue; + if (MO.isUse()) + FoundUse = true; + Done = true; // Stop after scanning all the operands of this MI. + } + } + if (!FoundUse) { + // Def is dead! + DefOp->setIsDead(); + return true; + } + return false; +} + +/// UpdateKills - Track and update kill info. If a MI reads a register that is +/// marked kill, then it must be due to register reuse. Transfer the kill info +/// over. +static void UpdateKills(MachineInstr &MI, const TargetRegisterInfo* TRI, + BitVector &RegKills, + std::vector &KillOps) { + for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) { + MachineOperand &MO = MI.getOperand(i); + if (!MO.isReg() || !MO.isUse() || MO.isUndef()) + continue; + unsigned Reg = MO.getReg(); + if (Reg == 0) + continue; + + if (RegKills[Reg] && KillOps[Reg]->getParent() != &MI) { + // That can't be right. Register is killed but not re-defined and it's + // being reused. Let's fix that. + KillOps[Reg]->setIsKill(false); + // KillOps[Reg] might be a def of a super-register. + unsigned KReg = KillOps[Reg]->getReg(); + KillOps[KReg] = NULL; + RegKills.reset(KReg); + + // Must be a def of a super-register. Its other sub-regsters are no + // longer killed as well. + for (const unsigned *SR = TRI->getSubRegisters(KReg); *SR; ++SR) { + KillOps[*SR] = NULL; + RegKills.reset(*SR); + } + } else { + // Check for subreg kills as well. + // d4 = + // store d4, fi#0 + // ... + // = s8 + // ... + // = d4 + for (const unsigned *SR = TRI->getSubRegisters(Reg); *SR; ++SR) { + unsigned SReg = *SR; + if (RegKills[SReg] && KillOps[SReg]->getParent() != &MI) { + KillOps[SReg]->setIsKill(false); + unsigned KReg = KillOps[SReg]->getReg(); + KillOps[KReg] = NULL; + RegKills.reset(KReg); + + for (const unsigned *SSR = TRI->getSubRegisters(KReg); *SSR; ++SSR) { + KillOps[*SSR] = NULL; + RegKills.reset(*SSR); + } + } + } + } + + if (MO.isKill()) { + RegKills.set(Reg); + KillOps[Reg] = &MO; + for (const unsigned *SR = TRI->getSubRegisters(Reg); *SR; ++SR) { + RegKills.set(*SR); + KillOps[*SR] = &MO; + } + } + } + + for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) { + const MachineOperand &MO = MI.getOperand(i); + if (!MO.isReg() || !MO.getReg() || !MO.isDef()) + continue; + unsigned Reg = MO.getReg(); + RegKills.reset(Reg); + KillOps[Reg] = NULL; + // It also defines (or partially define) aliases. + for (const unsigned *SR = TRI->getSubRegisters(Reg); *SR; ++SR) { + RegKills.reset(*SR); + KillOps[*SR] = NULL; + } + for (const unsigned *SR = TRI->getSuperRegisters(Reg); *SR; ++SR) { + RegKills.reset(*SR); + KillOps[*SR] = NULL; + } + } +} + +/// ReMaterialize - Re-materialize definition for Reg targetting DestReg. +/// +static void ReMaterialize(MachineBasicBlock &MBB, + MachineBasicBlock::iterator &MII, + unsigned DestReg, unsigned Reg, + const TargetInstrInfo *TII, + const TargetRegisterInfo *TRI, + VirtRegMap &VRM) { + MachineInstr *ReMatDefMI = VRM.getReMaterializedMI(Reg); +#ifndef NDEBUG + const TargetInstrDesc &TID = ReMatDefMI->getDesc(); + assert(TID.getNumDefs() == 1 && + "Don't know how to remat instructions that define > 1 values!"); +#endif + TII->reMaterialize(MBB, MII, DestReg, + ReMatDefMI->getOperand(0).getSubReg(), ReMatDefMI, TRI); + MachineInstr *NewMI = prior(MII); + for (unsigned i = 0, e = NewMI->getNumOperands(); i != e; ++i) { + MachineOperand &MO = NewMI->getOperand(i); + if (!MO.isReg() || MO.getReg() == 0) + continue; + unsigned VirtReg = MO.getReg(); + if (TargetRegisterInfo::isPhysicalRegister(VirtReg)) + continue; + assert(MO.isUse()); + unsigned SubIdx = MO.getSubReg(); + unsigned Phys = VRM.getPhys(VirtReg); + assert(Phys && "Virtual register is not assigned a register?"); + unsigned RReg = SubIdx ? TRI->getSubReg(Phys, SubIdx) : Phys; + MO.setReg(RReg); + MO.setSubReg(0); + } + ++NumReMats; +} + +/// findSuperReg - Find the SubReg's super-register of given register class +/// where its SubIdx sub-register is SubReg. +static unsigned findSuperReg(const TargetRegisterClass *RC, unsigned SubReg, + unsigned SubIdx, const TargetRegisterInfo *TRI) { + for (TargetRegisterClass::iterator I = RC->begin(), E = RC->end(); + I != E; ++I) { + unsigned Reg = *I; + if (TRI->getSubReg(Reg, SubIdx) == SubReg) + return Reg; + } + return 0; +} + +// ******************************** // +// Available Spills Implementation // +// ******************************** // + +/// disallowClobberPhysRegOnly - Unset the CanClobber bit of the specified +/// stackslot register. The register is still available but is no longer +/// allowed to be modifed. +void AvailableSpills::disallowClobberPhysRegOnly(unsigned PhysReg) { + std::multimap::iterator I = + PhysRegsAvailable.lower_bound(PhysReg); + while (I != PhysRegsAvailable.end() && I->first == PhysReg) { + int SlotOrReMat = I->second; + I++; + assert((SpillSlotsOrReMatsAvailable[SlotOrReMat] >> 1) == PhysReg && + "Bidirectional map mismatch!"); + SpillSlotsOrReMatsAvailable[SlotOrReMat] &= ~1; + DEBUG(errs() << "PhysReg " << TRI->getName(PhysReg) + << " copied, it is available for use but can no longer be modified\n"); + } +} + +/// disallowClobberPhysReg - Unset the CanClobber bit of the specified +/// stackslot register and its aliases. The register and its aliases may +/// still available but is no longer allowed to be modifed. +void AvailableSpills::disallowClobberPhysReg(unsigned PhysReg) { + for (const unsigned *AS = TRI->getAliasSet(PhysReg); *AS; ++AS) + disallowClobberPhysRegOnly(*AS); + disallowClobberPhysRegOnly(PhysReg); +} + +/// ClobberPhysRegOnly - This is called when the specified physreg changes +/// value. We use this to invalidate any info about stuff we thing lives in it. +void AvailableSpills::ClobberPhysRegOnly(unsigned PhysReg) { + std::multimap::iterator I = + PhysRegsAvailable.lower_bound(PhysReg); + while (I != PhysRegsAvailable.end() && I->first == PhysReg) { + int SlotOrReMat = I->second; + PhysRegsAvailable.erase(I++); + assert((SpillSlotsOrReMatsAvailable[SlotOrReMat] >> 1) == PhysReg && + "Bidirectional map mismatch!"); + SpillSlotsOrReMatsAvailable.erase(SlotOrReMat); + DEBUG(errs() << "PhysReg " << TRI->getName(PhysReg) + << " clobbered, invalidating "); + if (SlotOrReMat > VirtRegMap::MAX_STACK_SLOT) + DEBUG(errs() << "RM#" << SlotOrReMat-VirtRegMap::MAX_STACK_SLOT-1 <<"\n"); + else + DEBUG(errs() << "SS#" << SlotOrReMat << "\n"); + } +} + +/// ClobberPhysReg - This is called when the specified physreg changes +/// value. We use this to invalidate any info about stuff we thing lives in +/// it and any of its aliases. +void AvailableSpills::ClobberPhysReg(unsigned PhysReg) { + for (const unsigned *AS = TRI->getAliasSet(PhysReg); *AS; ++AS) + ClobberPhysRegOnly(*AS); + ClobberPhysRegOnly(PhysReg); +} + +/// AddAvailableRegsToLiveIn - Availability information is being kept coming +/// into the specified MBB. Add available physical registers as potential +/// live-in's. If they are reused in the MBB, they will be added to the +/// live-in set to make register scavenger and post-allocation scheduler. +void AvailableSpills::AddAvailableRegsToLiveIn(MachineBasicBlock &MBB, + BitVector &RegKills, + std::vector &KillOps) { + std::set NotAvailable; + for (std::multimap::iterator + I = PhysRegsAvailable.begin(), E = PhysRegsAvailable.end(); + I != E; ++I) { + unsigned Reg = I->first; + const TargetRegisterClass* RC = TRI->getPhysicalRegisterRegClass(Reg); + // FIXME: A temporary workaround. We can't reuse available value if it's + // not safe to move the def of the virtual register's class. e.g. + // X86::RFP* register classes. Do not add it as a live-in. + if (!TII->isSafeToMoveRegClassDefs(RC)) + // This is no longer available. + NotAvailable.insert(Reg); + else { + MBB.addLiveIn(Reg); + InvalidateKill(Reg, TRI, RegKills, KillOps); + } + + // Skip over the same register. + std::multimap::iterator NI = next(I); + while (NI != E && NI->first == Reg) { + ++I; + ++NI; + } + } + + for (std::set::iterator I = NotAvailable.begin(), + E = NotAvailable.end(); I != E; ++I) { + ClobberPhysReg(*I); + for (const unsigned *SubRegs = TRI->getSubRegisters(*I); + *SubRegs; ++SubRegs) + ClobberPhysReg(*SubRegs); + } +} + +/// ModifyStackSlotOrReMat - This method is called when the value in a stack +/// slot changes. This removes information about which register the previous +/// value for this slot lives in (as the previous value is dead now). +void AvailableSpills::ModifyStackSlotOrReMat(int SlotOrReMat) { + std::map::iterator It = + SpillSlotsOrReMatsAvailable.find(SlotOrReMat); + if (It == SpillSlotsOrReMatsAvailable.end()) return; + unsigned Reg = It->second >> 1; + SpillSlotsOrReMatsAvailable.erase(It); + + // This register may hold the value of multiple stack slots, only remove this + // stack slot from the set of values the register contains. + std::multimap::iterator I = PhysRegsAvailable.lower_bound(Reg); + for (; ; ++I) { + assert(I != PhysRegsAvailable.end() && I->first == Reg && + "Map inverse broken!"); + if (I->second == SlotOrReMat) break; + } + PhysRegsAvailable.erase(I); +} + +// ************************** // +// Reuse Info Implementation // +// ************************** // + +/// GetRegForReload - We are about to emit a reload into PhysReg. If there +/// is some other operand that is using the specified register, either pick +/// a new register to use, or evict the previous reload and use this reg. +unsigned ReuseInfo::GetRegForReload(const TargetRegisterClass *RC, + unsigned PhysReg, + MachineFunction &MF, + MachineInstr *MI, AvailableSpills &Spills, + std::vector &MaybeDeadStores, + SmallSet &Rejected, + BitVector &RegKills, + std::vector &KillOps, + VirtRegMap &VRM) { + const TargetInstrInfo* TII = MF.getTarget().getInstrInfo(); + const TargetRegisterInfo *TRI = Spills.getRegInfo(); + + if (Reuses.empty()) return PhysReg; // This is most often empty. + + for (unsigned ro = 0, e = Reuses.size(); ro != e; ++ro) { + ReusedOp &Op = Reuses[ro]; + // If we find some other reuse that was supposed to use this register + // exactly for its reload, we can change this reload to use ITS reload + // register. That is, unless its reload register has already been + // considered and subsequently rejected because it has also been reused + // by another operand. + if (Op.PhysRegReused == PhysReg && + Rejected.count(Op.AssignedPhysReg) == 0 && + RC->contains(Op.AssignedPhysReg)) { + // Yup, use the reload register that we didn't use before. + unsigned NewReg = Op.AssignedPhysReg; + Rejected.insert(PhysReg); + return GetRegForReload(RC, NewReg, MF, MI, Spills, MaybeDeadStores, Rejected, + RegKills, KillOps, VRM); + } else { + // Otherwise, we might also have a problem if a previously reused + // value aliases the new register. If so, codegen the previous reload + // and use this one. + unsigned PRRU = Op.PhysRegReused; + if (TRI->regsOverlap(PRRU, PhysReg)) { + // Okay, we found out that an alias of a reused register + // was used. This isn't good because it means we have + // to undo a previous reuse. + MachineBasicBlock *MBB = MI->getParent(); + const TargetRegisterClass *AliasRC = + MBB->getParent()->getRegInfo().getRegClass(Op.VirtReg); + + // Copy Op out of the vector and remove it, we're going to insert an + // explicit load for it. + ReusedOp NewOp = Op; + Reuses.erase(Reuses.begin()+ro); + + // MI may be using only a sub-register of PhysRegUsed. + unsigned RealPhysRegUsed = MI->getOperand(NewOp.Operand).getReg(); + unsigned SubIdx = 0; + assert(TargetRegisterInfo::isPhysicalRegister(RealPhysRegUsed) && + "A reuse cannot be a virtual register"); + if (PRRU != RealPhysRegUsed) { + // What was the sub-register index? + SubIdx = TRI->getSubRegIndex(PRRU, RealPhysRegUsed); + assert(SubIdx && + "Operand physreg is not a sub-register of PhysRegUsed"); + } + + // Ok, we're going to try to reload the assigned physreg into the + // slot that we were supposed to in the first place. However, that + // register could hold a reuse. Check to see if it conflicts or + // would prefer us to use a different register. + unsigned NewPhysReg = GetRegForReload(RC, NewOp.AssignedPhysReg, + MF, MI, Spills, MaybeDeadStores, + Rejected, RegKills, KillOps, VRM); + + bool DoReMat = NewOp.StackSlotOrReMat > VirtRegMap::MAX_STACK_SLOT; + int SSorRMId = DoReMat + ? VRM.getReMatId(NewOp.VirtReg) : NewOp.StackSlotOrReMat; + + // Back-schedule reloads and remats. + MachineBasicBlock::iterator InsertLoc = + ComputeReloadLoc(MI, MBB->begin(), PhysReg, TRI, + DoReMat, SSorRMId, TII, MF); + + if (DoReMat) { + ReMaterialize(*MBB, InsertLoc, NewPhysReg, NewOp.VirtReg, TII, + TRI, VRM); + } else { + TII->loadRegFromStackSlot(*MBB, InsertLoc, NewPhysReg, + NewOp.StackSlotOrReMat, AliasRC); + MachineInstr *LoadMI = prior(InsertLoc); + VRM.addSpillSlotUse(NewOp.StackSlotOrReMat, LoadMI); + // Any stores to this stack slot are not dead anymore. + MaybeDeadStores[NewOp.StackSlotOrReMat] = NULL; + ++NumLoads; + } + Spills.ClobberPhysReg(NewPhysReg); + Spills.ClobberPhysReg(NewOp.PhysRegReused); + + unsigned RReg = SubIdx ? TRI->getSubReg(NewPhysReg, SubIdx) :NewPhysReg; + MI->getOperand(NewOp.Operand).setReg(RReg); + MI->getOperand(NewOp.Operand).setSubReg(0); + + Spills.addAvailable(NewOp.StackSlotOrReMat, NewPhysReg); + UpdateKills(*prior(InsertLoc), TRI, RegKills, KillOps); + DEBUG(errs() << '\t' << *prior(InsertLoc)); + + DEBUG(errs() << "Reuse undone!\n"); + --NumReused; + + // Finally, PhysReg is now available, go ahead and use it. + return PhysReg; + } + } + } + return PhysReg; +} + +// ************************************************************************ // + +/// FoldsStackSlotModRef - Return true if the specified MI folds the specified +/// stack slot mod/ref. It also checks if it's possible to unfold the +/// instruction by having it define a specified physical register instead. +static bool FoldsStackSlotModRef(MachineInstr &MI, int SS, unsigned PhysReg, + const TargetInstrInfo *TII, + const TargetRegisterInfo *TRI, + VirtRegMap &VRM) { + if (VRM.hasEmergencySpills(&MI) || VRM.isSpillPt(&MI)) + return false; + + bool Found = false; + VirtRegMap::MI2VirtMapTy::const_iterator I, End; + for (tie(I, End) = VRM.getFoldedVirts(&MI); I != End; ++I) { + unsigned VirtReg = I->second.first; + VirtRegMap::ModRef MR = I->second.second; + if (MR & VirtRegMap::isModRef) + if (VRM.getStackSlot(VirtReg) == SS) { + Found= TII->getOpcodeAfterMemoryUnfold(MI.getOpcode(), true, true) != 0; + break; + } + } + if (!Found) + return false; + + // Does the instruction uses a register that overlaps the scratch register? + for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) { + MachineOperand &MO = MI.getOperand(i); + if (!MO.isReg() || MO.getReg() == 0) + continue; + unsigned Reg = MO.getReg(); + if (TargetRegisterInfo::isVirtualRegister(Reg)) { + if (!VRM.hasPhys(Reg)) + continue; + Reg = VRM.getPhys(Reg); + } + if (TRI->regsOverlap(PhysReg, Reg)) + return false; + } + return true; +} + +/// FindFreeRegister - Find a free register of a given register class by looking +/// at (at most) the last two machine instructions. +static unsigned FindFreeRegister(MachineBasicBlock::iterator MII, + MachineBasicBlock &MBB, + const TargetRegisterClass *RC, + const TargetRegisterInfo *TRI, + BitVector &AllocatableRegs) { + BitVector Defs(TRI->getNumRegs()); + BitVector Uses(TRI->getNumRegs()); + SmallVector LocalUses; + SmallVector Kills; + + // Take a look at 2 instructions at most. + for (unsigned Count = 0; Count < 2; ++Count) { + if (MII == MBB.begin()) + break; + MachineInstr *PrevMI = prior(MII); + for (unsigned i = 0, e = PrevMI->getNumOperands(); i != e; ++i) { + MachineOperand &MO = PrevMI->getOperand(i); + if (!MO.isReg() || MO.getReg() == 0) + continue; + unsigned Reg = MO.getReg(); + if (MO.isDef()) { + Defs.set(Reg); + for (const unsigned *AS = TRI->getAliasSet(Reg); *AS; ++AS) + Defs.set(*AS); + } else { + LocalUses.push_back(Reg); + if (MO.isKill() && AllocatableRegs[Reg]) + Kills.push_back(Reg); + } + } + + for (unsigned i = 0, e = Kills.size(); i != e; ++i) { + unsigned Kill = Kills[i]; + if (!Defs[Kill] && !Uses[Kill] && + TRI->getPhysicalRegisterRegClass(Kill) == RC) + return Kill; + } + for (unsigned i = 0, e = LocalUses.size(); i != e; ++i) { + unsigned Reg = LocalUses[i]; + Uses.set(Reg); + for (const unsigned *AS = TRI->getAliasSet(Reg); *AS; ++AS) + Uses.set(*AS); + } + + MII = PrevMI; + } + + return 0; +} + +static +void AssignPhysToVirtReg(MachineInstr *MI, unsigned VirtReg, unsigned PhysReg) { + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + MachineOperand &MO = MI->getOperand(i); + if (MO.isReg() && MO.getReg() == VirtReg) + MO.setReg(PhysReg); + } +} + +namespace { + struct RefSorter { + bool operator()(const std::pair &A, + const std::pair &B) { + return A.second < B.second; + } + }; +} + +// ***************************** // +// Local Spiller Implementation // +// ***************************** // + +namespace { + +class LocalRewriter : public VirtRegRewriter { + MachineRegisterInfo *RegInfo; + const TargetRegisterInfo *TRI; + const TargetInstrInfo *TII; + BitVector AllocatableRegs; + DenseMap DistanceMap; +public: + + bool runOnMachineFunction(MachineFunction &MF, VirtRegMap &VRM, + LiveIntervals* LIs) { + RegInfo = &MF.getRegInfo(); + TRI = MF.getTarget().getRegisterInfo(); + TII = MF.getTarget().getInstrInfo(); + AllocatableRegs = TRI->getAllocatableSet(MF); + DEBUG(errs() << "\n**** Local spiller rewriting function '" + << MF.getFunction()->getName() << "':\n"); + DEBUG(errs() << "**** Machine Instrs (NOTE! Does not include spills and" + " reloads!) ****\n"); + DEBUG(MF.dump()); + + // Spills - Keep track of which spilled values are available in physregs + // so that we can choose to reuse the physregs instead of emitting + // reloads. This is usually refreshed per basic block. + AvailableSpills Spills(TRI, TII); + + // Keep track of kill information. + BitVector RegKills(TRI->getNumRegs()); + std::vector KillOps; + KillOps.resize(TRI->getNumRegs(), NULL); + + // SingleEntrySuccs - Successor blocks which have a single predecessor. + SmallVector SinglePredSuccs; + SmallPtrSet EarlyVisited; + + // Traverse the basic blocks depth first. + MachineBasicBlock *Entry = MF.begin(); + SmallPtrSet Visited; + for (df_ext_iterator > + DFI = df_ext_begin(Entry, Visited), E = df_ext_end(Entry, Visited); + DFI != E; ++DFI) { + MachineBasicBlock *MBB = *DFI; + if (!EarlyVisited.count(MBB)) + RewriteMBB(*MBB, VRM, LIs, Spills, RegKills, KillOps); + + // If this MBB is the only predecessor of a successor. Keep the + // availability information and visit it next. + do { + // Keep visiting single predecessor successor as long as possible. + SinglePredSuccs.clear(); + findSinglePredSuccessor(MBB, SinglePredSuccs); + if (SinglePredSuccs.empty()) + MBB = 0; + else { + // FIXME: More than one successors, each of which has MBB has + // the only predecessor. + MBB = SinglePredSuccs[0]; + if (!Visited.count(MBB) && EarlyVisited.insert(MBB)) { + Spills.AddAvailableRegsToLiveIn(*MBB, RegKills, KillOps); + RewriteMBB(*MBB, VRM, LIs, Spills, RegKills, KillOps); + } + } + } while (MBB); + + // Clear the availability info. + Spills.clear(); + } + + DEBUG(errs() << "**** Post Machine Instrs ****\n"); + DEBUG(MF.dump()); + + // Mark unused spill slots. + MachineFrameInfo *MFI = MF.getFrameInfo(); + int SS = VRM.getLowSpillSlot(); + if (SS != VirtRegMap::NO_STACK_SLOT) + for (int e = VRM.getHighSpillSlot(); SS <= e; ++SS) + if (!VRM.isSpillSlotUsed(SS)) { + MFI->RemoveStackObject(SS); + ++NumDSS; + } + + return true; + } + +private: + + /// OptimizeByUnfold2 - Unfold a series of load / store folding instructions if + /// a scratch register is available. + /// xorq %r12, %r13 + /// addq %rax, -184(%rbp) + /// addq %r13, -184(%rbp) + /// ==> + /// xorq %r12, %r13 + /// movq -184(%rbp), %r12 + /// addq %rax, %r12 + /// addq %r13, %r12 + /// movq %r12, -184(%rbp) + bool OptimizeByUnfold2(unsigned VirtReg, int SS, + MachineBasicBlock &MBB, + MachineBasicBlock::iterator &MII, + std::vector &MaybeDeadStores, + AvailableSpills &Spills, + BitVector &RegKills, + std::vector &KillOps, + VirtRegMap &VRM) { + + MachineBasicBlock::iterator NextMII = next(MII); + if (NextMII == MBB.end()) + return false; + + if (TII->getOpcodeAfterMemoryUnfold(MII->getOpcode(), true, true) == 0) + return false; + + // Now let's see if the last couple of instructions happens to have freed up + // a register. + const TargetRegisterClass* RC = RegInfo->getRegClass(VirtReg); + unsigned PhysReg = FindFreeRegister(MII, MBB, RC, TRI, AllocatableRegs); + if (!PhysReg) + return false; + + MachineFunction &MF = *MBB.getParent(); + TRI = MF.getTarget().getRegisterInfo(); + MachineInstr &MI = *MII; + if (!FoldsStackSlotModRef(MI, SS, PhysReg, TII, TRI, VRM)) + return false; + + // If the next instruction also folds the same SS modref and can be unfoled, + // then it's worthwhile to issue a load from SS into the free register and + // then unfold these instructions. + if (!FoldsStackSlotModRef(*NextMII, SS, PhysReg, TII, TRI, VRM)) + return false; + + // Back-schedule reloads and remats. + ComputeReloadLoc(MII, MBB.begin(), PhysReg, TRI, false, SS, TII, MF); + + // Load from SS to the spare physical register. + TII->loadRegFromStackSlot(MBB, MII, PhysReg, SS, RC); + // This invalidates Phys. + Spills.ClobberPhysReg(PhysReg); + // Remember it's available. + Spills.addAvailable(SS, PhysReg); + MaybeDeadStores[SS] = NULL; + + // Unfold current MI. + SmallVector NewMIs; + if (!TII->unfoldMemoryOperand(MF, &MI, VirtReg, false, false, NewMIs)) + llvm_unreachable("Unable unfold the load / store folding instruction!"); + assert(NewMIs.size() == 1); + AssignPhysToVirtReg(NewMIs[0], VirtReg, PhysReg); + VRM.transferRestorePts(&MI, NewMIs[0]); + MII = MBB.insert(MII, NewMIs[0]); + InvalidateKills(MI, TRI, RegKills, KillOps); + VRM.RemoveMachineInstrFromMaps(&MI); + MBB.erase(&MI); + ++NumModRefUnfold; + + // Unfold next instructions that fold the same SS. + do { + MachineInstr &NextMI = *NextMII; + NextMII = next(NextMII); + NewMIs.clear(); + if (!TII->unfoldMemoryOperand(MF, &NextMI, VirtReg, false, false, NewMIs)) + llvm_unreachable("Unable unfold the load / store folding instruction!"); + assert(NewMIs.size() == 1); + AssignPhysToVirtReg(NewMIs[0], VirtReg, PhysReg); + VRM.transferRestorePts(&NextMI, NewMIs[0]); + MBB.insert(NextMII, NewMIs[0]); + InvalidateKills(NextMI, TRI, RegKills, KillOps); + VRM.RemoveMachineInstrFromMaps(&NextMI); + MBB.erase(&NextMI); + ++NumModRefUnfold; + if (NextMII == MBB.end()) + break; + } while (FoldsStackSlotModRef(*NextMII, SS, PhysReg, TII, TRI, VRM)); + + // Store the value back into SS. + TII->storeRegToStackSlot(MBB, NextMII, PhysReg, true, SS, RC); + MachineInstr *StoreMI = prior(NextMII); + VRM.addSpillSlotUse(SS, StoreMI); + VRM.virtFolded(VirtReg, StoreMI, VirtRegMap::isMod); + + return true; + } + + /// OptimizeByUnfold - Turn a store folding instruction into a load folding + /// instruction. e.g. + /// xorl %edi, %eax + /// movl %eax, -32(%ebp) + /// movl -36(%ebp), %eax + /// orl %eax, -32(%ebp) + /// ==> + /// xorl %edi, %eax + /// orl -36(%ebp), %eax + /// mov %eax, -32(%ebp) + /// This enables unfolding optimization for a subsequent instruction which will + /// also eliminate the newly introduced store instruction. + bool OptimizeByUnfold(MachineBasicBlock &MBB, + MachineBasicBlock::iterator &MII, + std::vector &MaybeDeadStores, + AvailableSpills &Spills, + BitVector &RegKills, + std::vector &KillOps, + VirtRegMap &VRM) { + MachineFunction &MF = *MBB.getParent(); + MachineInstr &MI = *MII; + unsigned UnfoldedOpc = 0; + unsigned UnfoldPR = 0; + unsigned UnfoldVR = 0; + int FoldedSS = VirtRegMap::NO_STACK_SLOT; + VirtRegMap::MI2VirtMapTy::const_iterator I, End; + for (tie(I, End) = VRM.getFoldedVirts(&MI); I != End; ) { + // Only transform a MI that folds a single register. + if (UnfoldedOpc) + return false; + UnfoldVR = I->second.first; + VirtRegMap::ModRef MR = I->second.second; + // MI2VirtMap be can updated which invalidate the iterator. + // Increment the iterator first. + ++I; + if (VRM.isAssignedReg(UnfoldVR)) + continue; + // If this reference is not a use, any previous store is now dead. + // Otherwise, the store to this stack slot is not dead anymore. + FoldedSS = VRM.getStackSlot(UnfoldVR); + MachineInstr* DeadStore = MaybeDeadStores[FoldedSS]; + if (DeadStore && (MR & VirtRegMap::isModRef)) { + unsigned PhysReg = Spills.getSpillSlotOrReMatPhysReg(FoldedSS); + if (!PhysReg || !DeadStore->readsRegister(PhysReg)) + continue; + UnfoldPR = PhysReg; + UnfoldedOpc = TII->getOpcodeAfterMemoryUnfold(MI.getOpcode(), + false, true); + } + } + + if (!UnfoldedOpc) { + if (!UnfoldVR) + return false; + + // Look for other unfolding opportunities. + return OptimizeByUnfold2(UnfoldVR, FoldedSS, MBB, MII, + MaybeDeadStores, Spills, RegKills, KillOps, VRM); + } + + for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) { + MachineOperand &MO = MI.getOperand(i); + if (!MO.isReg() || MO.getReg() == 0 || !MO.isUse()) + continue; + unsigned VirtReg = MO.getReg(); + if (TargetRegisterInfo::isPhysicalRegister(VirtReg) || MO.getSubReg()) + continue; + if (VRM.isAssignedReg(VirtReg)) { + unsigned PhysReg = VRM.getPhys(VirtReg); + if (PhysReg && TRI->regsOverlap(PhysReg, UnfoldPR)) + return false; + } else if (VRM.isReMaterialized(VirtReg)) + continue; + int SS = VRM.getStackSlot(VirtReg); + unsigned PhysReg = Spills.getSpillSlotOrReMatPhysReg(SS); + if (PhysReg) { + if (TRI->regsOverlap(PhysReg, UnfoldPR)) + return false; + continue; + } + if (VRM.hasPhys(VirtReg)) { + PhysReg = VRM.getPhys(VirtReg); + if (!TRI->regsOverlap(PhysReg, UnfoldPR)) + continue; + } + + // Ok, we'll need to reload the value into a register which makes + // it impossible to perform the store unfolding optimization later. + // Let's see if it is possible to fold the load if the store is + // unfolded. This allows us to perform the store unfolding + // optimization. + SmallVector NewMIs; + if (TII->unfoldMemoryOperand(MF, &MI, UnfoldVR, false, false, NewMIs)) { + assert(NewMIs.size() == 1); + MachineInstr *NewMI = NewMIs.back(); + NewMIs.clear(); + int Idx = NewMI->findRegisterUseOperandIdx(VirtReg, false); + assert(Idx != -1); + SmallVector Ops; + Ops.push_back(Idx); + MachineInstr *FoldedMI = TII->foldMemoryOperand(MF, NewMI, Ops, SS); + if (FoldedMI) { + VRM.addSpillSlotUse(SS, FoldedMI); + if (!VRM.hasPhys(UnfoldVR)) + VRM.assignVirt2Phys(UnfoldVR, UnfoldPR); + VRM.virtFolded(VirtReg, FoldedMI, VirtRegMap::isRef); + MII = MBB.insert(MII, FoldedMI); + InvalidateKills(MI, TRI, RegKills, KillOps); + VRM.RemoveMachineInstrFromMaps(&MI); + MBB.erase(&MI); + MF.DeleteMachineInstr(NewMI); + return true; + } + MF.DeleteMachineInstr(NewMI); + } + } + + return false; + } + + /// CommuteChangesDestination - We are looking for r0 = op r1, r2 and + /// where SrcReg is r1 and it is tied to r0. Return true if after + /// commuting this instruction it will be r0 = op r2, r1. + static bool CommuteChangesDestination(MachineInstr *DefMI, + const TargetInstrDesc &TID, + unsigned SrcReg, + const TargetInstrInfo *TII, + unsigned &DstIdx) { + if (TID.getNumDefs() != 1 && TID.getNumOperands() != 3) + return false; + if (!DefMI->getOperand(1).isReg() || + DefMI->getOperand(1).getReg() != SrcReg) + return false; + unsigned DefIdx; + if (!DefMI->isRegTiedToDefOperand(1, &DefIdx) || DefIdx != 0) + return false; + unsigned SrcIdx1, SrcIdx2; + if (!TII->findCommutedOpIndices(DefMI, SrcIdx1, SrcIdx2)) + return false; + if (SrcIdx1 == 1 && SrcIdx2 == 2) { + DstIdx = 2; + return true; + } + return false; + } + + /// CommuteToFoldReload - + /// Look for + /// r1 = load fi#1 + /// r1 = op r1, r2 + /// store r1, fi#1 + /// + /// If op is commutable and r2 is killed, then we can xform these to + /// r2 = op r2, fi#1 + /// store r2, fi#1 + bool CommuteToFoldReload(MachineBasicBlock &MBB, + MachineBasicBlock::iterator &MII, + unsigned VirtReg, unsigned SrcReg, int SS, + AvailableSpills &Spills, + BitVector &RegKills, + std::vector &KillOps, + const TargetRegisterInfo *TRI, + VirtRegMap &VRM) { + if (MII == MBB.begin() || !MII->killsRegister(SrcReg)) + return false; + + MachineFunction &MF = *MBB.getParent(); + MachineInstr &MI = *MII; + MachineBasicBlock::iterator DefMII = prior(MII); + MachineInstr *DefMI = DefMII; + const TargetInstrDesc &TID = DefMI->getDesc(); + unsigned NewDstIdx; + if (DefMII != MBB.begin() && + TID.isCommutable() && + CommuteChangesDestination(DefMI, TID, SrcReg, TII, NewDstIdx)) { + MachineOperand &NewDstMO = DefMI->getOperand(NewDstIdx); + unsigned NewReg = NewDstMO.getReg(); + if (!NewDstMO.isKill() || TRI->regsOverlap(NewReg, SrcReg)) + return false; + MachineInstr *ReloadMI = prior(DefMII); + int FrameIdx; + unsigned DestReg = TII->isLoadFromStackSlot(ReloadMI, FrameIdx); + if (DestReg != SrcReg || FrameIdx != SS) + return false; + int UseIdx = DefMI->findRegisterUseOperandIdx(DestReg, false); + if (UseIdx == -1) + return false; + unsigned DefIdx; + if (!MI.isRegTiedToDefOperand(UseIdx, &DefIdx)) + return false; + assert(DefMI->getOperand(DefIdx).isReg() && + DefMI->getOperand(DefIdx).getReg() == SrcReg); + + // Now commute def instruction. + MachineInstr *CommutedMI = TII->commuteInstruction(DefMI, true); + if (!CommutedMI) + return false; + SmallVector Ops; + Ops.push_back(NewDstIdx); + MachineInstr *FoldedMI = TII->foldMemoryOperand(MF, CommutedMI, Ops, SS); + // Not needed since foldMemoryOperand returns new MI. + MF.DeleteMachineInstr(CommutedMI); + if (!FoldedMI) + return false; + + VRM.addSpillSlotUse(SS, FoldedMI); + VRM.virtFolded(VirtReg, FoldedMI, VirtRegMap::isRef); + // Insert new def MI and spill MI. + const TargetRegisterClass* RC = RegInfo->getRegClass(VirtReg); + TII->storeRegToStackSlot(MBB, &MI, NewReg, true, SS, RC); + MII = prior(MII); + MachineInstr *StoreMI = MII; + VRM.addSpillSlotUse(SS, StoreMI); + VRM.virtFolded(VirtReg, StoreMI, VirtRegMap::isMod); + MII = MBB.insert(MII, FoldedMI); // Update MII to backtrack. + + // Delete all 3 old instructions. + InvalidateKills(*ReloadMI, TRI, RegKills, KillOps); + VRM.RemoveMachineInstrFromMaps(ReloadMI); + MBB.erase(ReloadMI); + InvalidateKills(*DefMI, TRI, RegKills, KillOps); + VRM.RemoveMachineInstrFromMaps(DefMI); + MBB.erase(DefMI); + InvalidateKills(MI, TRI, RegKills, KillOps); + VRM.RemoveMachineInstrFromMaps(&MI); + MBB.erase(&MI); + + // If NewReg was previously holding value of some SS, it's now clobbered. + // This has to be done now because it's a physical register. When this + // instruction is re-visited, it's ignored. + Spills.ClobberPhysReg(NewReg); + + ++NumCommutes; + return true; + } + + return false; + } + + /// SpillRegToStackSlot - Spill a register to a specified stack slot. Check if + /// the last store to the same slot is now dead. If so, remove the last store. + void SpillRegToStackSlot(MachineBasicBlock &MBB, + MachineBasicBlock::iterator &MII, + int Idx, unsigned PhysReg, int StackSlot, + const TargetRegisterClass *RC, + bool isAvailable, MachineInstr *&LastStore, + AvailableSpills &Spills, + SmallSet &ReMatDefs, + BitVector &RegKills, + std::vector &KillOps, + VirtRegMap &VRM) { + + MachineBasicBlock::iterator oldNextMII = next(MII); + TII->storeRegToStackSlot(MBB, next(MII), PhysReg, true, StackSlot, RC); + MachineInstr *StoreMI = prior(oldNextMII); + VRM.addSpillSlotUse(StackSlot, StoreMI); + DEBUG(errs() << "Store:\t" << *StoreMI); + + // If there is a dead store to this stack slot, nuke it now. + if (LastStore) { + DEBUG(errs() << "Removed dead store:\t" << *LastStore); + ++NumDSE; + SmallVector KillRegs; + InvalidateKills(*LastStore, TRI, RegKills, KillOps, &KillRegs); + MachineBasicBlock::iterator PrevMII = LastStore; + bool CheckDef = PrevMII != MBB.begin(); + if (CheckDef) + --PrevMII; + VRM.RemoveMachineInstrFromMaps(LastStore); + MBB.erase(LastStore); + if (CheckDef) { + // Look at defs of killed registers on the store. Mark the defs + // as dead since the store has been deleted and they aren't + // being reused. + for (unsigned j = 0, ee = KillRegs.size(); j != ee; ++j) { + bool HasOtherDef = false; + if (InvalidateRegDef(PrevMII, *MII, KillRegs[j], HasOtherDef, TRI)) { + MachineInstr *DeadDef = PrevMII; + if (ReMatDefs.count(DeadDef) && !HasOtherDef) { + // FIXME: This assumes a remat def does not have side effects. + VRM.RemoveMachineInstrFromMaps(DeadDef); + MBB.erase(DeadDef); + ++NumDRM; + } + } + } + } + } + + // Allow for multi-instruction spill sequences, as on PPC Altivec. Presume + // the last of multiple instructions is the actual store. + LastStore = prior(oldNextMII); + + // If the stack slot value was previously available in some other + // register, change it now. Otherwise, make the register available, + // in PhysReg. + Spills.ModifyStackSlotOrReMat(StackSlot); + Spills.ClobberPhysReg(PhysReg); + Spills.addAvailable(StackSlot, PhysReg, isAvailable); + ++NumStores; + } + + /// isSafeToDelete - Return true if this instruction doesn't produce any side + /// effect and all of its defs are dead. + static bool isSafeToDelete(MachineInstr &MI) { + const TargetInstrDesc &TID = MI.getDesc(); + if (TID.mayLoad() || TID.mayStore() || TID.isCall() || TID.isTerminator() || + TID.isCall() || TID.isBarrier() || TID.isReturn() || + TID.hasUnmodeledSideEffects()) + return false; + for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) { + MachineOperand &MO = MI.getOperand(i); + if (!MO.isReg() || !MO.getReg()) + continue; + if (MO.isDef() && !MO.isDead()) + return false; + if (MO.isUse() && MO.isKill()) + // FIXME: We can't remove kill markers or else the scavenger will assert. + // An alternative is to add a ADD pseudo instruction to replace kill + // markers. + return false; + } + return true; + } + + /// TransferDeadness - A identity copy definition is dead and it's being + /// removed. Find the last def or use and mark it as dead / kill. + void TransferDeadness(MachineBasicBlock *MBB, unsigned CurDist, + unsigned Reg, BitVector &RegKills, + std::vector &KillOps, + VirtRegMap &VRM) { + SmallPtrSet Seens; + SmallVector,8> Refs; + for (MachineRegisterInfo::reg_iterator RI = RegInfo->reg_begin(Reg), + RE = RegInfo->reg_end(); RI != RE; ++RI) { + MachineInstr *UDMI = &*RI; + if (UDMI->getParent() != MBB) + continue; + DenseMap::iterator DI = DistanceMap.find(UDMI); + if (DI == DistanceMap.end() || DI->second > CurDist) + continue; + if (Seens.insert(UDMI)) + Refs.push_back(std::make_pair(UDMI, DI->second)); + } + + if (Refs.empty()) + return; + std::sort(Refs.begin(), Refs.end(), RefSorter()); + + while (!Refs.empty()) { + MachineInstr *LastUDMI = Refs.back().first; + Refs.pop_back(); + + MachineOperand *LastUD = NULL; + for (unsigned i = 0, e = LastUDMI->getNumOperands(); i != e; ++i) { + MachineOperand &MO = LastUDMI->getOperand(i); + if (!MO.isReg() || MO.getReg() != Reg) + continue; + if (!LastUD || (LastUD->isUse() && MO.isDef())) + LastUD = &MO; + if (LastUDMI->isRegTiedToDefOperand(i)) + break; + } + if (LastUD->isDef()) { + // If the instruction has no side effect, delete it and propagate + // backward further. Otherwise, mark is dead and we are done. + if (!isSafeToDelete(*LastUDMI)) { + LastUD->setIsDead(); + break; + } + VRM.RemoveMachineInstrFromMaps(LastUDMI); + MBB->erase(LastUDMI); + } else { + LastUD->setIsKill(); + RegKills.set(Reg); + KillOps[Reg] = LastUD; + break; + } + } + } + + /// rewriteMBB - Keep track of which spills are available even after the + /// register allocator is done with them. If possible, avid reloading vregs. + void RewriteMBB(MachineBasicBlock &MBB, VirtRegMap &VRM, + LiveIntervals *LIs, + AvailableSpills &Spills, BitVector &RegKills, + std::vector &KillOps) { + + DEBUG(errs() << "\n**** Local spiller rewriting MBB '" + << MBB.getName() << "':\n"); + + MachineFunction &MF = *MBB.getParent(); + + // MaybeDeadStores - When we need to write a value back into a stack slot, + // keep track of the inserted store. If the stack slot value is never read + // (because the value was used from some available register, for example), and + // subsequently stored to, the original store is dead. This map keeps track + // of inserted stores that are not used. If we see a subsequent store to the + // same stack slot, the original store is deleted. + std::vector MaybeDeadStores; + MaybeDeadStores.resize(MF.getFrameInfo()->getObjectIndexEnd(), NULL); + + // ReMatDefs - These are rematerializable def MIs which are not deleted. + SmallSet ReMatDefs; + + // Clear kill info. + SmallSet KilledMIRegs; + RegKills.reset(); + KillOps.clear(); + KillOps.resize(TRI->getNumRegs(), NULL); + + unsigned Dist = 0; + DistanceMap.clear(); + for (MachineBasicBlock::iterator MII = MBB.begin(), E = MBB.end(); + MII != E; ) { + MachineBasicBlock::iterator NextMII = next(MII); + + VirtRegMap::MI2VirtMapTy::const_iterator I, End; + bool Erased = false; + bool BackTracked = false; + if (OptimizeByUnfold(MBB, MII, + MaybeDeadStores, Spills, RegKills, KillOps, VRM)) + NextMII = next(MII); + + MachineInstr &MI = *MII; + + if (VRM.hasEmergencySpills(&MI)) { + // Spill physical register(s) in the rare case the allocator has run out + // of registers to allocate. + SmallSet UsedSS; + std::vector &EmSpills = VRM.getEmergencySpills(&MI); + for (unsigned i = 0, e = EmSpills.size(); i != e; ++i) { + unsigned PhysReg = EmSpills[i]; + const TargetRegisterClass *RC = + TRI->getPhysicalRegisterRegClass(PhysReg); + assert(RC && "Unable to determine register class!"); + int SS = VRM.getEmergencySpillSlot(RC); + if (UsedSS.count(SS)) + llvm_unreachable("Need to spill more than one physical registers!"); + UsedSS.insert(SS); + TII->storeRegToStackSlot(MBB, MII, PhysReg, true, SS, RC); + MachineInstr *StoreMI = prior(MII); + VRM.addSpillSlotUse(SS, StoreMI); + + // Back-schedule reloads and remats. + MachineBasicBlock::iterator InsertLoc = + ComputeReloadLoc(next(MII), MBB.begin(), PhysReg, TRI, false, + SS, TII, MF); + + TII->loadRegFromStackSlot(MBB, InsertLoc, PhysReg, SS, RC); + + MachineInstr *LoadMI = prior(InsertLoc); + VRM.addSpillSlotUse(SS, LoadMI); + ++NumPSpills; + DistanceMap.insert(std::make_pair(LoadMI, Dist++)); + } + NextMII = next(MII); + } + + // Insert restores here if asked to. + if (VRM.isRestorePt(&MI)) { + std::vector &RestoreRegs = VRM.getRestorePtRestores(&MI); + for (unsigned i = 0, e = RestoreRegs.size(); i != e; ++i) { + unsigned VirtReg = RestoreRegs[e-i-1]; // Reverse order. + if (!VRM.getPreSplitReg(VirtReg)) + continue; // Split interval spilled again. + unsigned Phys = VRM.getPhys(VirtReg); + RegInfo->setPhysRegUsed(Phys); + + // Check if the value being restored if available. If so, it must be + // from a predecessor BB that fallthrough into this BB. We do not + // expect: + // BB1: + // r1 = load fi#1 + // ... + // = r1 + // ... # r1 not clobbered + // ... + // = load fi#1 + bool DoReMat = VRM.isReMaterialized(VirtReg); + int SSorRMId = DoReMat + ? VRM.getReMatId(VirtReg) : VRM.getStackSlot(VirtReg); + const TargetRegisterClass* RC = RegInfo->getRegClass(VirtReg); + unsigned InReg = Spills.getSpillSlotOrReMatPhysReg(SSorRMId); + if (InReg == Phys) { + // If the value is already available in the expected register, save + // a reload / remat. + if (SSorRMId) + DEBUG(errs() << "Reusing RM#" + << SSorRMId-VirtRegMap::MAX_STACK_SLOT-1); + else + DEBUG(errs() << "Reusing SS#" << SSorRMId); + DEBUG(errs() << " from physreg " + << TRI->getName(InReg) << " for vreg" + << VirtReg <<" instead of reloading into physreg " + << TRI->getName(Phys) << '\n'); + ++NumOmitted; + continue; + } else if (InReg && InReg != Phys) { + if (SSorRMId) + DEBUG(errs() << "Reusing RM#" + << SSorRMId-VirtRegMap::MAX_STACK_SLOT-1); + else + DEBUG(errs() << "Reusing SS#" << SSorRMId); + DEBUG(errs() << " from physreg " + << TRI->getName(InReg) << " for vreg" + << VirtReg <<" by copying it into physreg " + << TRI->getName(Phys) << '\n'); + + // If the reloaded / remat value is available in another register, + // copy it to the desired register. + + // Back-schedule reloads and remats. + MachineBasicBlock::iterator InsertLoc = + ComputeReloadLoc(MII, MBB.begin(), Phys, TRI, DoReMat, + SSorRMId, TII, MF); + + TII->copyRegToReg(MBB, InsertLoc, Phys, InReg, RC, RC); + + // This invalidates Phys. + Spills.ClobberPhysReg(Phys); + // Remember it's available. + Spills.addAvailable(SSorRMId, Phys); + + // Mark is killed. + MachineInstr *CopyMI = prior(InsertLoc); + CopyMI->setAsmPrinterFlag(AsmPrinter::ReloadReuse); + MachineOperand *KillOpnd = CopyMI->findRegisterUseOperand(InReg); + KillOpnd->setIsKill(); + UpdateKills(*CopyMI, TRI, RegKills, KillOps); + + DEBUG(errs() << '\t' << *CopyMI); + ++NumCopified; + continue; + } + + // Back-schedule reloads and remats. + MachineBasicBlock::iterator InsertLoc = + ComputeReloadLoc(MII, MBB.begin(), Phys, TRI, DoReMat, + SSorRMId, TII, MF); + + if (VRM.isReMaterialized(VirtReg)) { + ReMaterialize(MBB, InsertLoc, Phys, VirtReg, TII, TRI, VRM); + } else { + const TargetRegisterClass* RC = RegInfo->getRegClass(VirtReg); + TII->loadRegFromStackSlot(MBB, InsertLoc, Phys, SSorRMId, RC); + MachineInstr *LoadMI = prior(InsertLoc); + VRM.addSpillSlotUse(SSorRMId, LoadMI); + ++NumLoads; + DistanceMap.insert(std::make_pair(LoadMI, Dist++)); + } + + // This invalidates Phys. + Spills.ClobberPhysReg(Phys); + // Remember it's available. + Spills.addAvailable(SSorRMId, Phys); + + UpdateKills(*prior(InsertLoc), TRI, RegKills, KillOps); + DEBUG(errs() << '\t' << *prior(MII)); + } + } + + // Insert spills here if asked to. + if (VRM.isSpillPt(&MI)) { + std::vector > &SpillRegs = + VRM.getSpillPtSpills(&MI); + for (unsigned i = 0, e = SpillRegs.size(); i != e; ++i) { + unsigned VirtReg = SpillRegs[i].first; + bool isKill = SpillRegs[i].second; + if (!VRM.getPreSplitReg(VirtReg)) + continue; // Split interval spilled again. + const TargetRegisterClass *RC = RegInfo->getRegClass(VirtReg); + unsigned Phys = VRM.getPhys(VirtReg); + int StackSlot = VRM.getStackSlot(VirtReg); + MachineBasicBlock::iterator oldNextMII = next(MII); + TII->storeRegToStackSlot(MBB, next(MII), Phys, isKill, StackSlot, RC); + MachineInstr *StoreMI = prior(oldNextMII); + VRM.addSpillSlotUse(StackSlot, StoreMI); + DEBUG(errs() << "Store:\t" << *StoreMI); + VRM.virtFolded(VirtReg, StoreMI, VirtRegMap::isMod); + } + NextMII = next(MII); + } + + /// ReusedOperands - Keep track of operand reuse in case we need to undo + /// reuse. + ReuseInfo ReusedOperands(MI, TRI); + SmallVector VirtUseOps; + for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) { + MachineOperand &MO = MI.getOperand(i); + if (!MO.isReg() || MO.getReg() == 0) + continue; // Ignore non-register operands. + + unsigned VirtReg = MO.getReg(); + if (TargetRegisterInfo::isPhysicalRegister(VirtReg)) { + // Ignore physregs for spilling, but remember that it is used by this + // function. + RegInfo->setPhysRegUsed(VirtReg); + continue; + } + + // We want to process implicit virtual register uses first. + if (MO.isImplicit()) + // If the virtual register is implicitly defined, emit a implicit_def + // before so scavenger knows it's "defined". + // FIXME: This is a horrible hack done the by register allocator to + // remat a definition with virtual register operand. + VirtUseOps.insert(VirtUseOps.begin(), i); + else + VirtUseOps.push_back(i); + } + + // Process all of the spilled uses and all non spilled reg references. + SmallVector PotentialDeadStoreSlots; + KilledMIRegs.clear(); + for (unsigned j = 0, e = VirtUseOps.size(); j != e; ++j) { + unsigned i = VirtUseOps[j]; + MachineOperand &MO = MI.getOperand(i); + unsigned VirtReg = MO.getReg(); + assert(TargetRegisterInfo::isVirtualRegister(VirtReg) && + "Not a virtual register?"); + + unsigned SubIdx = MO.getSubReg(); + if (VRM.isAssignedReg(VirtReg)) { + // This virtual register was assigned a physreg! + unsigned Phys = VRM.getPhys(VirtReg); + RegInfo->setPhysRegUsed(Phys); + if (MO.isDef()) + ReusedOperands.markClobbered(Phys); + unsigned RReg = SubIdx ? TRI->getSubReg(Phys, SubIdx) : Phys; + MI.getOperand(i).setReg(RReg); + MI.getOperand(i).setSubReg(0); + if (VRM.isImplicitlyDefined(VirtReg)) + // FIXME: Is this needed? + BuildMI(MBB, &MI, MI.getDebugLoc(), + TII->get(TargetInstrInfo::IMPLICIT_DEF), RReg); + continue; + } + + // This virtual register is now known to be a spilled value. + if (!MO.isUse()) + continue; // Handle defs in the loop below (handle use&def here though) + + bool AvoidReload = MO.isUndef(); + // Check if it is defined by an implicit def. It should not be spilled. + // Note, this is for correctness reason. e.g. + // 8 %reg1024 = IMPLICIT_DEF + // 12 %reg1024 = INSERT_SUBREG %reg1024, %reg1025, 2 + // The live range [12, 14) are not part of the r1024 live interval since + // it's defined by an implicit def. It will not conflicts with live + // interval of r1025. Now suppose both registers are spilled, you can + // easily see a situation where both registers are reloaded before + // the INSERT_SUBREG and both target registers that would overlap. + bool DoReMat = VRM.isReMaterialized(VirtReg); + int SSorRMId = DoReMat + ? VRM.getReMatId(VirtReg) : VRM.getStackSlot(VirtReg); + int ReuseSlot = SSorRMId; + + // Check to see if this stack slot is available. + unsigned PhysReg = Spills.getSpillSlotOrReMatPhysReg(SSorRMId); + + // If this is a sub-register use, make sure the reuse register is in the + // right register class. For example, for x86 not all of the 32-bit + // registers have accessible sub-registers. + // Similarly so for EXTRACT_SUBREG. Consider this: + // EDI = op + // MOV32_mr fi#1, EDI + // ... + // = EXTRACT_SUBREG fi#1 + // fi#1 is available in EDI, but it cannot be reused because it's not in + // the right register file. + if (PhysReg && !AvoidReload && + (SubIdx || MI.getOpcode() == TargetInstrInfo::EXTRACT_SUBREG)) { + const TargetRegisterClass* RC = RegInfo->getRegClass(VirtReg); + if (!RC->contains(PhysReg)) + PhysReg = 0; + } + + if (PhysReg && !AvoidReload) { + // This spilled operand might be part of a two-address operand. If this + // is the case, then changing it will necessarily require changing the + // def part of the instruction as well. However, in some cases, we + // aren't allowed to modify the reused register. If none of these cases + // apply, reuse it. + bool CanReuse = true; + bool isTied = MI.isRegTiedToDefOperand(i); + if (isTied) { + // Okay, we have a two address operand. We can reuse this physreg as + // long as we are allowed to clobber the value and there isn't an + // earlier def that has already clobbered the physreg. + CanReuse = !ReusedOperands.isClobbered(PhysReg) && + Spills.canClobberPhysReg(PhysReg); + } + + if (CanReuse) { + // If this stack slot value is already available, reuse it! + if (ReuseSlot > VirtRegMap::MAX_STACK_SLOT) + DEBUG(errs() << "Reusing RM#" + << ReuseSlot-VirtRegMap::MAX_STACK_SLOT-1); + else + DEBUG(errs() << "Reusing SS#" << ReuseSlot); + DEBUG(errs() << " from physreg " + << TRI->getName(PhysReg) << " for vreg" + << VirtReg <<" instead of reloading into physreg " + << TRI->getName(VRM.getPhys(VirtReg)) << '\n'); + unsigned RReg = SubIdx ? TRI->getSubReg(PhysReg, SubIdx) : PhysReg; + MI.getOperand(i).setReg(RReg); + MI.getOperand(i).setSubReg(0); + + // The only technical detail we have is that we don't know that + // PhysReg won't be clobbered by a reloaded stack slot that occurs + // later in the instruction. In particular, consider 'op V1, V2'. + // If V1 is available in physreg R0, we would choose to reuse it + // here, instead of reloading it into the register the allocator + // indicated (say R1). However, V2 might have to be reloaded + // later, and it might indicate that it needs to live in R0. When + // this occurs, we need to have information available that + // indicates it is safe to use R1 for the reload instead of R0. + // + // To further complicate matters, we might conflict with an alias, + // or R0 and R1 might not be compatible with each other. In this + // case, we actually insert a reload for V1 in R1, ensuring that + // we can get at R0 or its alias. + ReusedOperands.addReuse(i, ReuseSlot, PhysReg, + VRM.getPhys(VirtReg), VirtReg); + if (isTied) + // Only mark it clobbered if this is a use&def operand. + ReusedOperands.markClobbered(PhysReg); + ++NumReused; + + if (MI.getOperand(i).isKill() && + ReuseSlot <= VirtRegMap::MAX_STACK_SLOT) { + + // The store of this spilled value is potentially dead, but we + // won't know for certain until we've confirmed that the re-use + // above is valid, which means waiting until the other operands + // are processed. For now we just track the spill slot, we'll + // remove it after the other operands are processed if valid. + + PotentialDeadStoreSlots.push_back(ReuseSlot); + } + + // Mark is isKill if it's there no other uses of the same virtual + // register and it's not a two-address operand. IsKill will be + // unset if reg is reused. + if (!isTied && KilledMIRegs.count(VirtReg) == 0) { + MI.getOperand(i).setIsKill(); + KilledMIRegs.insert(VirtReg); + } + + continue; + } // CanReuse + + // Otherwise we have a situation where we have a two-address instruction + // whose mod/ref operand needs to be reloaded. This reload is already + // available in some register "PhysReg", but if we used PhysReg as the + // operand to our 2-addr instruction, the instruction would modify + // PhysReg. This isn't cool if something later uses PhysReg and expects + // to get its initial value. + // + // To avoid this problem, and to avoid doing a load right after a store, + // we emit a copy from PhysReg into the designated register for this + // operand. + unsigned DesignatedReg = VRM.getPhys(VirtReg); + assert(DesignatedReg && "Must map virtreg to physreg!"); + + // Note that, if we reused a register for a previous operand, the + // register we want to reload into might not actually be + // available. If this occurs, use the register indicated by the + // reuser. + if (ReusedOperands.hasReuses()) + DesignatedReg = ReusedOperands.GetRegForReload(VirtReg, + DesignatedReg, &MI, + Spills, MaybeDeadStores, RegKills, KillOps, VRM); + + // If the mapped designated register is actually the physreg we have + // incoming, we don't need to inserted a dead copy. + if (DesignatedReg == PhysReg) { + // If this stack slot value is already available, reuse it! + if (ReuseSlot > VirtRegMap::MAX_STACK_SLOT) + DEBUG(errs() << "Reusing RM#" + << ReuseSlot-VirtRegMap::MAX_STACK_SLOT-1); + else + DEBUG(errs() << "Reusing SS#" << ReuseSlot); + DEBUG(errs() << " from physreg " << TRI->getName(PhysReg) + << " for vreg" << VirtReg + << " instead of reloading into same physreg.\n"); + unsigned RReg = SubIdx ? TRI->getSubReg(PhysReg, SubIdx) : PhysReg; + MI.getOperand(i).setReg(RReg); + MI.getOperand(i).setSubReg(0); + ReusedOperands.markClobbered(RReg); + ++NumReused; + continue; + } + + const TargetRegisterClass* RC = RegInfo->getRegClass(VirtReg); + RegInfo->setPhysRegUsed(DesignatedReg); + ReusedOperands.markClobbered(DesignatedReg); + + // Back-schedule reloads and remats. + MachineBasicBlock::iterator InsertLoc = + ComputeReloadLoc(&MI, MBB.begin(), PhysReg, TRI, DoReMat, + SSorRMId, TII, MF); + + TII->copyRegToReg(MBB, InsertLoc, DesignatedReg, PhysReg, RC, RC); + + MachineInstr *CopyMI = prior(InsertLoc); + CopyMI->setAsmPrinterFlag(AsmPrinter::ReloadReuse); + UpdateKills(*CopyMI, TRI, RegKills, KillOps); + + // This invalidates DesignatedReg. + Spills.ClobberPhysReg(DesignatedReg); + + Spills.addAvailable(ReuseSlot, DesignatedReg); + unsigned RReg = + SubIdx ? TRI->getSubReg(DesignatedReg, SubIdx) : DesignatedReg; + MI.getOperand(i).setReg(RReg); + MI.getOperand(i).setSubReg(0); + DEBUG(errs() << '\t' << *prior(MII)); + ++NumReused; + continue; + } // if (PhysReg) + + // Otherwise, reload it and remember that we have it. + PhysReg = VRM.getPhys(VirtReg); + assert(PhysReg && "Must map virtreg to physreg!"); + + // Note that, if we reused a register for a previous operand, the + // register we want to reload into might not actually be + // available. If this occurs, use the register indicated by the + // reuser. + if (ReusedOperands.hasReuses()) + PhysReg = ReusedOperands.GetRegForReload(VirtReg, PhysReg, &MI, + Spills, MaybeDeadStores, RegKills, KillOps, VRM); + + RegInfo->setPhysRegUsed(PhysReg); + ReusedOperands.markClobbered(PhysReg); + if (AvoidReload) + ++NumAvoided; + else { + // Back-schedule reloads and remats. + MachineBasicBlock::iterator InsertLoc = + ComputeReloadLoc(MII, MBB.begin(), PhysReg, TRI, DoReMat, + SSorRMId, TII, MF); + + if (DoReMat) { + ReMaterialize(MBB, InsertLoc, PhysReg, VirtReg, TII, TRI, VRM); + } else { + const TargetRegisterClass* RC = RegInfo->getRegClass(VirtReg); + TII->loadRegFromStackSlot(MBB, InsertLoc, PhysReg, SSorRMId, RC); + MachineInstr *LoadMI = prior(InsertLoc); + VRM.addSpillSlotUse(SSorRMId, LoadMI); + ++NumLoads; + DistanceMap.insert(std::make_pair(LoadMI, Dist++)); + } + // This invalidates PhysReg. + Spills.ClobberPhysReg(PhysReg); + + // Any stores to this stack slot are not dead anymore. + if (!DoReMat) + MaybeDeadStores[SSorRMId] = NULL; + Spills.addAvailable(SSorRMId, PhysReg); + // Assumes this is the last use. IsKill will be unset if reg is reused + // unless it's a two-address operand. + if (!MI.isRegTiedToDefOperand(i) && + KilledMIRegs.count(VirtReg) == 0) { + MI.getOperand(i).setIsKill(); + KilledMIRegs.insert(VirtReg); + } + + UpdateKills(*prior(InsertLoc), TRI, RegKills, KillOps); + DEBUG(errs() << '\t' << *prior(InsertLoc)); + } + unsigned RReg = SubIdx ? TRI->getSubReg(PhysReg, SubIdx) : PhysReg; + MI.getOperand(i).setReg(RReg); + MI.getOperand(i).setSubReg(0); + } + + // Ok - now we can remove stores that have been confirmed dead. + for (unsigned j = 0, e = PotentialDeadStoreSlots.size(); j != e; ++j) { + // This was the last use and the spilled value is still available + // for reuse. That means the spill was unnecessary! + int PDSSlot = PotentialDeadStoreSlots[j]; + MachineInstr* DeadStore = MaybeDeadStores[PDSSlot]; + if (DeadStore) { + DEBUG(errs() << "Removed dead store:\t" << *DeadStore); + InvalidateKills(*DeadStore, TRI, RegKills, KillOps); + VRM.RemoveMachineInstrFromMaps(DeadStore); + MBB.erase(DeadStore); + MaybeDeadStores[PDSSlot] = NULL; + ++NumDSE; + } + } + + + DEBUG(errs() << '\t' << MI); + + + // If we have folded references to memory operands, make sure we clear all + // physical registers that may contain the value of the spilled virtual + // register + SmallSet FoldedSS; + for (tie(I, End) = VRM.getFoldedVirts(&MI); I != End; ) { + unsigned VirtReg = I->second.first; + VirtRegMap::ModRef MR = I->second.second; + DEBUG(errs() << "Folded vreg: " << VirtReg << " MR: " << MR); + + // MI2VirtMap be can updated which invalidate the iterator. + // Increment the iterator first. + ++I; + int SS = VRM.getStackSlot(VirtReg); + if (SS == VirtRegMap::NO_STACK_SLOT) + continue; + FoldedSS.insert(SS); + DEBUG(errs() << " - StackSlot: " << SS << "\n"); + + // If this folded instruction is just a use, check to see if it's a + // straight load from the virt reg slot. + if ((MR & VirtRegMap::isRef) && !(MR & VirtRegMap::isMod)) { + int FrameIdx; + unsigned DestReg = TII->isLoadFromStackSlot(&MI, FrameIdx); + if (DestReg && FrameIdx == SS) { + // If this spill slot is available, turn it into a copy (or nothing) + // instead of leaving it as a load! + if (unsigned InReg = Spills.getSpillSlotOrReMatPhysReg(SS)) { + DEBUG(errs() << "Promoted Load To Copy: " << MI); + if (DestReg != InReg) { + const TargetRegisterClass *RC = RegInfo->getRegClass(VirtReg); + TII->copyRegToReg(MBB, &MI, DestReg, InReg, RC, RC); + MachineOperand *DefMO = MI.findRegisterDefOperand(DestReg); + unsigned SubIdx = DefMO->getSubReg(); + // Revisit the copy so we make sure to notice the effects of the + // operation on the destreg (either needing to RA it if it's + // virtual or needing to clobber any values if it's physical). + NextMII = &MI; + --NextMII; // backtrack to the copy. + NextMII->setAsmPrinterFlag(AsmPrinter::ReloadReuse); + // Propagate the sub-register index over. + if (SubIdx) { + DefMO = NextMII->findRegisterDefOperand(DestReg); + DefMO->setSubReg(SubIdx); + } + + // Mark is killed. + MachineOperand *KillOpnd = NextMII->findRegisterUseOperand(InReg); + KillOpnd->setIsKill(); + + BackTracked = true; + } else { + DEBUG(errs() << "Removing now-noop copy: " << MI); + // Unset last kill since it's being reused. + InvalidateKill(InReg, TRI, RegKills, KillOps); + Spills.disallowClobberPhysReg(InReg); + } + + InvalidateKills(MI, TRI, RegKills, KillOps); + VRM.RemoveMachineInstrFromMaps(&MI); + MBB.erase(&MI); + Erased = true; + goto ProcessNextInst; + } + } else { + unsigned PhysReg = Spills.getSpillSlotOrReMatPhysReg(SS); + SmallVector NewMIs; + if (PhysReg && + TII->unfoldMemoryOperand(MF, &MI, PhysReg, false, false, NewMIs)) { + MBB.insert(MII, NewMIs[0]); + InvalidateKills(MI, TRI, RegKills, KillOps); + VRM.RemoveMachineInstrFromMaps(&MI); + MBB.erase(&MI); + Erased = true; + --NextMII; // backtrack to the unfolded instruction. + BackTracked = true; + goto ProcessNextInst; + } + } + } + + // If this reference is not a use, any previous store is now dead. + // Otherwise, the store to this stack slot is not dead anymore. + MachineInstr* DeadStore = MaybeDeadStores[SS]; + if (DeadStore) { + bool isDead = !(MR & VirtRegMap::isRef); + MachineInstr *NewStore = NULL; + if (MR & VirtRegMap::isModRef) { + unsigned PhysReg = Spills.getSpillSlotOrReMatPhysReg(SS); + SmallVector NewMIs; + // We can reuse this physreg as long as we are allowed to clobber + // the value and there isn't an earlier def that has already clobbered + // the physreg. + if (PhysReg && + !ReusedOperands.isClobbered(PhysReg) && + Spills.canClobberPhysReg(PhysReg) && + !TII->isStoreToStackSlot(&MI, SS)) { // Not profitable! + MachineOperand *KillOpnd = + DeadStore->findRegisterUseOperand(PhysReg, true); + // Note, if the store is storing a sub-register, it's possible the + // super-register is needed below. + if (KillOpnd && !KillOpnd->getSubReg() && + TII->unfoldMemoryOperand(MF, &MI, PhysReg, false, true,NewMIs)){ + MBB.insert(MII, NewMIs[0]); + NewStore = NewMIs[1]; + MBB.insert(MII, NewStore); + VRM.addSpillSlotUse(SS, NewStore); + InvalidateKills(MI, TRI, RegKills, KillOps); + VRM.RemoveMachineInstrFromMaps(&MI); + MBB.erase(&MI); + Erased = true; + --NextMII; + --NextMII; // backtrack to the unfolded instruction. + BackTracked = true; + isDead = true; + ++NumSUnfold; + } + } + } + + if (isDead) { // Previous store is dead. + // If we get here, the store is dead, nuke it now. + DEBUG(errs() << "Removed dead store:\t" << *DeadStore); + InvalidateKills(*DeadStore, TRI, RegKills, KillOps); + VRM.RemoveMachineInstrFromMaps(DeadStore); + MBB.erase(DeadStore); + if (!NewStore) + ++NumDSE; + } + + MaybeDeadStores[SS] = NULL; + if (NewStore) { + // Treat this store as a spill merged into a copy. That makes the + // stack slot value available. + VRM.virtFolded(VirtReg, NewStore, VirtRegMap::isMod); + goto ProcessNextInst; + } + } + + // If the spill slot value is available, and this is a new definition of + // the value, the value is not available anymore. + if (MR & VirtRegMap::isMod) { + // Notice that the value in this stack slot has been modified. + Spills.ModifyStackSlotOrReMat(SS); + + // If this is *just* a mod of the value, check to see if this is just a + // store to the spill slot (i.e. the spill got merged into the copy). If + // so, realize that the vreg is available now, and add the store to the + // MaybeDeadStore info. + int StackSlot; + if (!(MR & VirtRegMap::isRef)) { + if (unsigned SrcReg = TII->isStoreToStackSlot(&MI, StackSlot)) { + assert(TargetRegisterInfo::isPhysicalRegister(SrcReg) && + "Src hasn't been allocated yet?"); + + if (CommuteToFoldReload(MBB, MII, VirtReg, SrcReg, StackSlot, + Spills, RegKills, KillOps, TRI, VRM)) { + NextMII = next(MII); + BackTracked = true; + goto ProcessNextInst; + } + + // Okay, this is certainly a store of SrcReg to [StackSlot]. Mark + // this as a potentially dead store in case there is a subsequent + // store into the stack slot without a read from it. + MaybeDeadStores[StackSlot] = &MI; + + // If the stack slot value was previously available in some other + // register, change it now. Otherwise, make the register + // available in PhysReg. + Spills.addAvailable(StackSlot, SrcReg, MI.killsRegister(SrcReg)); + } + } + } + } + + // Process all of the spilled defs. + for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) { + MachineOperand &MO = MI.getOperand(i); + if (!(MO.isReg() && MO.getReg() && MO.isDef())) + continue; + + unsigned VirtReg = MO.getReg(); + if (!TargetRegisterInfo::isVirtualRegister(VirtReg)) { + // Check to see if this is a noop copy. If so, eliminate the + // instruction before considering the dest reg to be changed. + // Also check if it's copying from an "undef", if so, we can't + // eliminate this or else the undef marker is lost and it will + // confuses the scavenger. This is extremely rare. + unsigned Src, Dst, SrcSR, DstSR; + if (TII->isMoveInstr(MI, Src, Dst, SrcSR, DstSR) && Src == Dst && + !MI.findRegisterUseOperand(Src)->isUndef()) { + ++NumDCE; + DEBUG(errs() << "Removing now-noop copy: " << MI); + SmallVector KillRegs; + InvalidateKills(MI, TRI, RegKills, KillOps, &KillRegs); + if (MO.isDead() && !KillRegs.empty()) { + // Source register or an implicit super/sub-register use is killed. + assert(KillRegs[0] == Dst || + TRI->isSubRegister(KillRegs[0], Dst) || + TRI->isSuperRegister(KillRegs[0], Dst)); + // Last def is now dead. + TransferDeadness(&MBB, Dist, Src, RegKills, KillOps, VRM); + } + VRM.RemoveMachineInstrFromMaps(&MI); + MBB.erase(&MI); + Erased = true; + Spills.disallowClobberPhysReg(VirtReg); + goto ProcessNextInst; + } + + // If it's not a no-op copy, it clobbers the value in the destreg. + Spills.ClobberPhysReg(VirtReg); + ReusedOperands.markClobbered(VirtReg); + + // Check to see if this instruction is a load from a stack slot into + // a register. If so, this provides the stack slot value in the reg. + int FrameIdx; + if (unsigned DestReg = TII->isLoadFromStackSlot(&MI, FrameIdx)) { + assert(DestReg == VirtReg && "Unknown load situation!"); + + // If it is a folded reference, then it's not safe to clobber. + bool Folded = FoldedSS.count(FrameIdx); + // Otherwise, if it wasn't available, remember that it is now! + Spills.addAvailable(FrameIdx, DestReg, !Folded); + goto ProcessNextInst; + } + + continue; + } + + unsigned SubIdx = MO.getSubReg(); + bool DoReMat = VRM.isReMaterialized(VirtReg); + if (DoReMat) + ReMatDefs.insert(&MI); + + // The only vregs left are stack slot definitions. + int StackSlot = VRM.getStackSlot(VirtReg); + const TargetRegisterClass *RC = RegInfo->getRegClass(VirtReg); + + // If this def is part of a two-address operand, make sure to execute + // the store from the correct physical register. + unsigned PhysReg; + unsigned TiedOp; + if (MI.isRegTiedToUseOperand(i, &TiedOp)) { + PhysReg = MI.getOperand(TiedOp).getReg(); + if (SubIdx) { + unsigned SuperReg = findSuperReg(RC, PhysReg, SubIdx, TRI); + assert(SuperReg && TRI->getSubReg(SuperReg, SubIdx) == PhysReg && + "Can't find corresponding super-register!"); + PhysReg = SuperReg; + } + } else { + PhysReg = VRM.getPhys(VirtReg); + if (ReusedOperands.isClobbered(PhysReg)) { + // Another def has taken the assigned physreg. It must have been a + // use&def which got it due to reuse. Undo the reuse! + PhysReg = ReusedOperands.GetRegForReload(VirtReg, PhysReg, &MI, + Spills, MaybeDeadStores, RegKills, KillOps, VRM); + } + } + + assert(PhysReg && "VR not assigned a physical register?"); + RegInfo->setPhysRegUsed(PhysReg); + unsigned RReg = SubIdx ? TRI->getSubReg(PhysReg, SubIdx) : PhysReg; + ReusedOperands.markClobbered(RReg); + MI.getOperand(i).setReg(RReg); + MI.getOperand(i).setSubReg(0); + + if (!MO.isDead()) { + MachineInstr *&LastStore = MaybeDeadStores[StackSlot]; + SpillRegToStackSlot(MBB, MII, -1, PhysReg, StackSlot, RC, true, + LastStore, Spills, ReMatDefs, RegKills, KillOps, VRM); + NextMII = next(MII); + + // Check to see if this is a noop copy. If so, eliminate the + // instruction before considering the dest reg to be changed. + { + unsigned Src, Dst, SrcSR, DstSR; + if (TII->isMoveInstr(MI, Src, Dst, SrcSR, DstSR) && Src == Dst) { + ++NumDCE; + DEBUG(errs() << "Removing now-noop copy: " << MI); + InvalidateKills(MI, TRI, RegKills, KillOps); + VRM.RemoveMachineInstrFromMaps(&MI); + MBB.erase(&MI); + Erased = true; + UpdateKills(*LastStore, TRI, RegKills, KillOps); + goto ProcessNextInst; + } + } + } + } + ProcessNextInst: + // Delete dead instructions without side effects. + if (!Erased && !BackTracked && isSafeToDelete(MI)) { + InvalidateKills(MI, TRI, RegKills, KillOps); + VRM.RemoveMachineInstrFromMaps(&MI); + MBB.erase(&MI); + Erased = true; + } + if (!Erased) + DistanceMap.insert(std::make_pair(&MI, Dist++)); + if (!Erased && !BackTracked) { + for (MachineBasicBlock::iterator II = &MI; II != NextMII; ++II) + UpdateKills(*II, TRI, RegKills, KillOps); + } + MII = NextMII; + } + + } + +}; + +} + +llvm::VirtRegRewriter* llvm::createVirtRegRewriter() { + switch (RewriterOpt) { + default: llvm_unreachable("Unreachable!"); + case local: + return new LocalRewriter(); + case trivial: + return new TrivialRewriter(); + } +} diff --git a/libclamav/c++/llvm/lib/CodeGen/VirtRegRewriter.h b/libclamav/c++/llvm/lib/CodeGen/VirtRegRewriter.h new file mode 100644 index 000000000..44f9df659 --- /dev/null +++ b/libclamav/c++/llvm/lib/CodeGen/VirtRegRewriter.h @@ -0,0 +1,33 @@ +//===-- llvm/CodeGen/VirtRegRewriter.h - VirtRegRewriter -*- C++ -*--------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_VIRTREGREWRITER_H +#define LLVM_CODEGEN_VIRTREGREWRITER_H + +#include "llvm/CodeGen/LiveIntervalAnalysis.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "VirtRegMap.h" + +namespace llvm { + + /// VirtRegRewriter interface: Implementations of this interface assign + /// spilled virtual registers to stack slots, rewriting the code. + struct VirtRegRewriter { + virtual ~VirtRegRewriter(); + virtual bool runOnMachineFunction(MachineFunction &MF, VirtRegMap &VRM, + LiveIntervals* LIs) = 0; + }; + + /// createVirtRegRewriter - Create an return a rewriter object, as specified + /// on the command line. + VirtRegRewriter* createVirtRegRewriter(); + +} + +#endif diff --git a/libclamav/c++/llvm/lib/ExecutionEngine/CMakeLists.txt b/libclamav/c++/llvm/lib/ExecutionEngine/CMakeLists.txt new file mode 100644 index 000000000..0e118ccd9 --- /dev/null +++ b/libclamav/c++/llvm/lib/ExecutionEngine/CMakeLists.txt @@ -0,0 +1,4 @@ +add_llvm_library(LLVMExecutionEngine + ExecutionEngine.cpp + ExecutionEngineBindings.cpp + ) diff --git a/libclamav/c++/llvm/lib/ExecutionEngine/ExecutionEngine.cpp b/libclamav/c++/llvm/lib/ExecutionEngine/ExecutionEngine.cpp new file mode 100644 index 000000000..cb307483f --- /dev/null +++ b/libclamav/c++/llvm/lib/ExecutionEngine/ExecutionEngine.cpp @@ -0,0 +1,1095 @@ +//===-- ExecutionEngine.cpp - Common Implementation shared by EEs ---------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the common interface used by the various execution engine +// subclasses. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "jit" +#include "llvm/ExecutionEngine/ExecutionEngine.h" + +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Module.h" +#include "llvm/ModuleProvider.h" +#include "llvm/ExecutionEngine/GenericValue.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/MutexGuard.h" +#include "llvm/Support/ValueHandle.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/System/DynamicLibrary.h" +#include "llvm/System/Host.h" +#include "llvm/Target/TargetData.h" +#include +#include +using namespace llvm; + +STATISTIC(NumInitBytes, "Number of bytes of global vars initialized"); +STATISTIC(NumGlobals , "Number of global vars initialized"); + +ExecutionEngine *(*ExecutionEngine::JITCtor)(ModuleProvider *MP, + std::string *ErrorStr, + JITMemoryManager *JMM, + CodeGenOpt::Level OptLevel, + bool GVsWithCode, + CodeModel::Model CMM) = 0; +ExecutionEngine *(*ExecutionEngine::InterpCtor)(ModuleProvider *MP, + std::string *ErrorStr) = 0; +ExecutionEngine::EERegisterFn ExecutionEngine::ExceptionTableRegister = 0; + + +ExecutionEngine::ExecutionEngine(ModuleProvider *P) + : EEState(*this), + LazyFunctionCreator(0) { + CompilingLazily = false; + GVCompilationDisabled = false; + SymbolSearchingDisabled = false; + Modules.push_back(P); + assert(P && "ModuleProvider is null?"); +} + +ExecutionEngine::~ExecutionEngine() { + clearAllGlobalMappings(); + for (unsigned i = 0, e = Modules.size(); i != e; ++i) + delete Modules[i]; +} + +char* ExecutionEngine::getMemoryForGV(const GlobalVariable* GV) { + const Type *ElTy = GV->getType()->getElementType(); + size_t GVSize = (size_t)getTargetData()->getTypeAllocSize(ElTy); + return new char[GVSize]; +} + +/// removeModuleProvider - Remove a ModuleProvider from the list of modules. +/// Relases the Module from the ModuleProvider, materializing it in the +/// process, and returns the materialized Module. +Module* ExecutionEngine::removeModuleProvider(ModuleProvider *P, + std::string *ErrInfo) { + for(SmallVector::iterator I = Modules.begin(), + E = Modules.end(); I != E; ++I) { + ModuleProvider *MP = *I; + if (MP == P) { + Modules.erase(I); + clearGlobalMappingsFromModule(MP->getModule()); + return MP->releaseModule(ErrInfo); + } + } + return NULL; +} + +/// deleteModuleProvider - Remove a ModuleProvider from the list of modules, +/// and deletes the ModuleProvider and owned Module. Avoids materializing +/// the underlying module. +void ExecutionEngine::deleteModuleProvider(ModuleProvider *P, + std::string *ErrInfo) { + for(SmallVector::iterator I = Modules.begin(), + E = Modules.end(); I != E; ++I) { + ModuleProvider *MP = *I; + if (MP == P) { + Modules.erase(I); + clearGlobalMappingsFromModule(MP->getModule()); + delete MP; + return; + } + } +} + +/// FindFunctionNamed - Search all of the active modules to find the one that +/// defines FnName. This is very slow operation and shouldn't be used for +/// general code. +Function *ExecutionEngine::FindFunctionNamed(const char *FnName) { + for (unsigned i = 0, e = Modules.size(); i != e; ++i) { + if (Function *F = Modules[i]->getModule()->getFunction(FnName)) + return F; + } + return 0; +} + + +void *ExecutionEngineState::RemoveMapping( + const MutexGuard &, const GlobalValue *ToUnmap) { + GlobalAddressMapTy::iterator I = GlobalAddressMap.find(ToUnmap); + void *OldVal; + if (I == GlobalAddressMap.end()) + OldVal = 0; + else { + OldVal = I->second; + GlobalAddressMap.erase(I); + } + + GlobalAddressReverseMap.erase(OldVal); + return OldVal; +} + +/// addGlobalMapping - Tell the execution engine that the specified global is +/// at the specified location. This is used internally as functions are JIT'd +/// and as global variables are laid out in memory. It can and should also be +/// used by clients of the EE that want to have an LLVM global overlay +/// existing data in memory. +void ExecutionEngine::addGlobalMapping(const GlobalValue *GV, void *Addr) { + MutexGuard locked(lock); + + DEBUG(errs() << "JIT: Map \'" << GV->getName() + << "\' to [" << Addr << "]\n";); + void *&CurVal = EEState.getGlobalAddressMap(locked)[GV]; + assert((CurVal == 0 || Addr == 0) && "GlobalMapping already established!"); + CurVal = Addr; + + // If we are using the reverse mapping, add it too + if (!EEState.getGlobalAddressReverseMap(locked).empty()) { + AssertingVH &V = + EEState.getGlobalAddressReverseMap(locked)[Addr]; + assert((V == 0 || GV == 0) && "GlobalMapping already established!"); + V = GV; + } +} + +/// clearAllGlobalMappings - Clear all global mappings and start over again +/// use in dynamic compilation scenarios when you want to move globals +void ExecutionEngine::clearAllGlobalMappings() { + MutexGuard locked(lock); + + EEState.getGlobalAddressMap(locked).clear(); + EEState.getGlobalAddressReverseMap(locked).clear(); +} + +/// clearGlobalMappingsFromModule - Clear all global mappings that came from a +/// particular module, because it has been removed from the JIT. +void ExecutionEngine::clearGlobalMappingsFromModule(Module *M) { + MutexGuard locked(lock); + + for (Module::iterator FI = M->begin(), FE = M->end(); FI != FE; ++FI) { + EEState.RemoveMapping(locked, FI); + } + for (Module::global_iterator GI = M->global_begin(), GE = M->global_end(); + GI != GE; ++GI) { + EEState.RemoveMapping(locked, GI); + } +} + +/// updateGlobalMapping - Replace an existing mapping for GV with a new +/// address. This updates both maps as required. If "Addr" is null, the +/// entry for the global is removed from the mappings. +void *ExecutionEngine::updateGlobalMapping(const GlobalValue *GV, void *Addr) { + MutexGuard locked(lock); + + ExecutionEngineState::GlobalAddressMapTy &Map = + EEState.getGlobalAddressMap(locked); + + // Deleting from the mapping? + if (Addr == 0) { + return EEState.RemoveMapping(locked, GV); + } + + void *&CurVal = Map[GV]; + void *OldVal = CurVal; + + if (CurVal && !EEState.getGlobalAddressReverseMap(locked).empty()) + EEState.getGlobalAddressReverseMap(locked).erase(CurVal); + CurVal = Addr; + + // If we are using the reverse mapping, add it too + if (!EEState.getGlobalAddressReverseMap(locked).empty()) { + AssertingVH &V = + EEState.getGlobalAddressReverseMap(locked)[Addr]; + assert((V == 0 || GV == 0) && "GlobalMapping already established!"); + V = GV; + } + return OldVal; +} + +/// getPointerToGlobalIfAvailable - This returns the address of the specified +/// global value if it is has already been codegen'd, otherwise it returns null. +/// +void *ExecutionEngine::getPointerToGlobalIfAvailable(const GlobalValue *GV) { + MutexGuard locked(lock); + + ExecutionEngineState::GlobalAddressMapTy::iterator I = + EEState.getGlobalAddressMap(locked).find(GV); + return I != EEState.getGlobalAddressMap(locked).end() ? I->second : 0; +} + +/// getGlobalValueAtAddress - Return the LLVM global value object that starts +/// at the specified address. +/// +const GlobalValue *ExecutionEngine::getGlobalValueAtAddress(void *Addr) { + MutexGuard locked(lock); + + // If we haven't computed the reverse mapping yet, do so first. + if (EEState.getGlobalAddressReverseMap(locked).empty()) { + for (ExecutionEngineState::GlobalAddressMapTy::iterator + I = EEState.getGlobalAddressMap(locked).begin(), + E = EEState.getGlobalAddressMap(locked).end(); I != E; ++I) + EEState.getGlobalAddressReverseMap(locked).insert(std::make_pair(I->second, + I->first)); + } + + std::map >::iterator I = + EEState.getGlobalAddressReverseMap(locked).find(Addr); + return I != EEState.getGlobalAddressReverseMap(locked).end() ? I->second : 0; +} + +// CreateArgv - Turn a vector of strings into a nice argv style array of +// pointers to null terminated strings. +// +static void *CreateArgv(LLVMContext &C, ExecutionEngine *EE, + const std::vector &InputArgv) { + unsigned PtrSize = EE->getTargetData()->getPointerSize(); + char *Result = new char[(InputArgv.size()+1)*PtrSize]; + + DEBUG(errs() << "JIT: ARGV = " << (void*)Result << "\n"); + const Type *SBytePtr = Type::getInt8PtrTy(C); + + for (unsigned i = 0; i != InputArgv.size(); ++i) { + unsigned Size = InputArgv[i].size()+1; + char *Dest = new char[Size]; + DEBUG(errs() << "JIT: ARGV[" << i << "] = " << (void*)Dest << "\n"); + + std::copy(InputArgv[i].begin(), InputArgv[i].end(), Dest); + Dest[Size-1] = 0; + + // Endian safe: Result[i] = (PointerTy)Dest; + EE->StoreValueToMemory(PTOGV(Dest), (GenericValue*)(Result+i*PtrSize), + SBytePtr); + } + + // Null terminate it + EE->StoreValueToMemory(PTOGV(0), + (GenericValue*)(Result+InputArgv.size()*PtrSize), + SBytePtr); + return Result; +} + + +/// runStaticConstructorsDestructors - This method is used to execute all of +/// the static constructors or destructors for a module, depending on the +/// value of isDtors. +void ExecutionEngine::runStaticConstructorsDestructors(Module *module, + bool isDtors) { + const char *Name = isDtors ? "llvm.global_dtors" : "llvm.global_ctors"; + + // Execute global ctors/dtors for each module in the program. + + GlobalVariable *GV = module->getNamedGlobal(Name); + + // If this global has internal linkage, or if it has a use, then it must be + // an old-style (llvmgcc3) static ctor with __main linked in and in use. If + // this is the case, don't execute any of the global ctors, __main will do + // it. + if (!GV || GV->isDeclaration() || GV->hasLocalLinkage()) return; + + // Should be an array of '{ int, void ()* }' structs. The first value is + // the init priority, which we ignore. + ConstantArray *InitList = dyn_cast(GV->getInitializer()); + if (!InitList) return; + for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i) + if (ConstantStruct *CS = + dyn_cast(InitList->getOperand(i))) { + if (CS->getNumOperands() != 2) return; // Not array of 2-element structs. + + Constant *FP = CS->getOperand(1); + if (FP->isNullValue()) + break; // Found a null terminator, exit. + + if (ConstantExpr *CE = dyn_cast(FP)) + if (CE->isCast()) + FP = CE->getOperand(0); + if (Function *F = dyn_cast(FP)) { + // Execute the ctor/dtor function! + runFunction(F, std::vector()); + } + } +} + +/// runStaticConstructorsDestructors - This method is used to execute all of +/// the static constructors or destructors for a program, depending on the +/// value of isDtors. +void ExecutionEngine::runStaticConstructorsDestructors(bool isDtors) { + // Execute global ctors/dtors for each module in the program. + for (unsigned m = 0, e = Modules.size(); m != e; ++m) + runStaticConstructorsDestructors(Modules[m]->getModule(), isDtors); +} + +#ifndef NDEBUG +/// isTargetNullPtr - Return whether the target pointer stored at Loc is null. +static bool isTargetNullPtr(ExecutionEngine *EE, void *Loc) { + unsigned PtrSize = EE->getTargetData()->getPointerSize(); + for (unsigned i = 0; i < PtrSize; ++i) + if (*(i + (uint8_t*)Loc)) + return false; + return true; +} +#endif + +/// runFunctionAsMain - This is a helper function which wraps runFunction to +/// handle the common task of starting up main with the specified argc, argv, +/// and envp parameters. +int ExecutionEngine::runFunctionAsMain(Function *Fn, + const std::vector &argv, + const char * const * envp) { + std::vector GVArgs; + GenericValue GVArgc; + GVArgc.IntVal = APInt(32, argv.size()); + + // Check main() type + unsigned NumArgs = Fn->getFunctionType()->getNumParams(); + const FunctionType *FTy = Fn->getFunctionType(); + const Type* PPInt8Ty = + PointerType::getUnqual(PointerType::getUnqual( + Type::getInt8Ty(Fn->getContext()))); + switch (NumArgs) { + case 3: + if (FTy->getParamType(2) != PPInt8Ty) { + llvm_report_error("Invalid type for third argument of main() supplied"); + } + // FALLS THROUGH + case 2: + if (FTy->getParamType(1) != PPInt8Ty) { + llvm_report_error("Invalid type for second argument of main() supplied"); + } + // FALLS THROUGH + case 1: + if (FTy->getParamType(0) != Type::getInt32Ty(Fn->getContext())) { + llvm_report_error("Invalid type for first argument of main() supplied"); + } + // FALLS THROUGH + case 0: + if (!isa(FTy->getReturnType()) && + FTy->getReturnType() != Type::getVoidTy(FTy->getContext())) { + llvm_report_error("Invalid return type of main() supplied"); + } + break; + default: + llvm_report_error("Invalid number of arguments of main() supplied"); + } + + if (NumArgs) { + GVArgs.push_back(GVArgc); // Arg #0 = argc. + if (NumArgs > 1) { + // Arg #1 = argv. + GVArgs.push_back(PTOGV(CreateArgv(Fn->getContext(), this, argv))); + assert(!isTargetNullPtr(this, GVTOP(GVArgs[1])) && + "argv[0] was null after CreateArgv"); + if (NumArgs > 2) { + std::vector EnvVars; + for (unsigned i = 0; envp[i]; ++i) + EnvVars.push_back(envp[i]); + // Arg #2 = envp. + GVArgs.push_back(PTOGV(CreateArgv(Fn->getContext(), this, EnvVars))); + } + } + } + return runFunction(Fn, GVArgs).IntVal.getZExtValue(); +} + +/// If possible, create a JIT, unless the caller specifically requests an +/// Interpreter or there's an error. If even an Interpreter cannot be created, +/// NULL is returned. +/// +ExecutionEngine *ExecutionEngine::create(ModuleProvider *MP, + bool ForceInterpreter, + std::string *ErrorStr, + CodeGenOpt::Level OptLevel, + bool GVsWithCode) { + return EngineBuilder(MP) + .setEngineKind(ForceInterpreter + ? EngineKind::Interpreter + : EngineKind::JIT) + .setErrorStr(ErrorStr) + .setOptLevel(OptLevel) + .setAllocateGVsWithCode(GVsWithCode) + .create(); +} + +ExecutionEngine *ExecutionEngine::create(Module *M) { + return EngineBuilder(M).create(); +} + +/// EngineBuilder - Overloaded constructor that automatically creates an +/// ExistingModuleProvider for an existing module. +EngineBuilder::EngineBuilder(Module *m) : MP(new ExistingModuleProvider(m)) { + InitEngine(); +} + +ExecutionEngine *EngineBuilder::create() { + // Make sure we can resolve symbols in the program as well. The zero arg + // to the function tells DynamicLibrary to load the program, not a library. + if (sys::DynamicLibrary::LoadLibraryPermanently(0, ErrorStr)) + return 0; + + // If the user specified a memory manager but didn't specify which engine to + // create, we assume they only want the JIT, and we fail if they only want + // the interpreter. + if (JMM) { + if (WhichEngine & EngineKind::JIT) + WhichEngine = EngineKind::JIT; + else { + if (ErrorStr) + *ErrorStr = "Cannot create an interpreter with a memory manager."; + return 0; + } + } + + // Unless the interpreter was explicitly selected or the JIT is not linked, + // try making a JIT. + if (WhichEngine & EngineKind::JIT) { + if (ExecutionEngine::JITCtor) { + ExecutionEngine *EE = + ExecutionEngine::JITCtor(MP, ErrorStr, JMM, OptLevel, + AllocateGVsWithCode, CMModel); + if (EE) return EE; + } + } + + // If we can't make a JIT and we didn't request one specifically, try making + // an interpreter instead. + if (WhichEngine & EngineKind::Interpreter) { + if (ExecutionEngine::InterpCtor) + return ExecutionEngine::InterpCtor(MP, ErrorStr); + if (ErrorStr) + *ErrorStr = "Interpreter has not been linked in."; + return 0; + } + + if ((WhichEngine & EngineKind::JIT) && ExecutionEngine::JITCtor == 0) { + if (ErrorStr) + *ErrorStr = "JIT has not been linked in."; + } + return 0; +} + +/// getPointerToGlobal - This returns the address of the specified global +/// value. This may involve code generation if it's a function. +/// +void *ExecutionEngine::getPointerToGlobal(const GlobalValue *GV) { + if (Function *F = const_cast(dyn_cast(GV))) + return getPointerToFunction(F); + + MutexGuard locked(lock); + void *p = EEState.getGlobalAddressMap(locked)[GV]; + if (p) + return p; + + // Global variable might have been added since interpreter started. + if (GlobalVariable *GVar = + const_cast(dyn_cast(GV))) + EmitGlobalVariable(GVar); + else + llvm_unreachable("Global hasn't had an address allocated yet!"); + return EEState.getGlobalAddressMap(locked)[GV]; +} + +/// This function converts a Constant* into a GenericValue. The interesting +/// part is if C is a ConstantExpr. +/// @brief Get a GenericValue for a Constant* +GenericValue ExecutionEngine::getConstantValue(const Constant *C) { + // If its undefined, return the garbage. + if (isa(C)) + return GenericValue(); + + // If the value is a ConstantExpr + if (const ConstantExpr *CE = dyn_cast(C)) { + Constant *Op0 = CE->getOperand(0); + switch (CE->getOpcode()) { + case Instruction::GetElementPtr: { + // Compute the index + GenericValue Result = getConstantValue(Op0); + SmallVector Indices(CE->op_begin()+1, CE->op_end()); + uint64_t Offset = + TD->getIndexedOffset(Op0->getType(), &Indices[0], Indices.size()); + + char* tmp = (char*) Result.PointerVal; + Result = PTOGV(tmp + Offset); + return Result; + } + case Instruction::Trunc: { + GenericValue GV = getConstantValue(Op0); + uint32_t BitWidth = cast(CE->getType())->getBitWidth(); + GV.IntVal = GV.IntVal.trunc(BitWidth); + return GV; + } + case Instruction::ZExt: { + GenericValue GV = getConstantValue(Op0); + uint32_t BitWidth = cast(CE->getType())->getBitWidth(); + GV.IntVal = GV.IntVal.zext(BitWidth); + return GV; + } + case Instruction::SExt: { + GenericValue GV = getConstantValue(Op0); + uint32_t BitWidth = cast(CE->getType())->getBitWidth(); + GV.IntVal = GV.IntVal.sext(BitWidth); + return GV; + } + case Instruction::FPTrunc: { + // FIXME long double + GenericValue GV = getConstantValue(Op0); + GV.FloatVal = float(GV.DoubleVal); + return GV; + } + case Instruction::FPExt:{ + // FIXME long double + GenericValue GV = getConstantValue(Op0); + GV.DoubleVal = double(GV.FloatVal); + return GV; + } + case Instruction::UIToFP: { + GenericValue GV = getConstantValue(Op0); + if (CE->getType()->isFloatTy()) + GV.FloatVal = float(GV.IntVal.roundToDouble()); + else if (CE->getType()->isDoubleTy()) + GV.DoubleVal = GV.IntVal.roundToDouble(); + else if (CE->getType()->isX86_FP80Ty()) { + const uint64_t zero[] = {0, 0}; + APFloat apf = APFloat(APInt(80, 2, zero)); + (void)apf.convertFromAPInt(GV.IntVal, + false, + APFloat::rmNearestTiesToEven); + GV.IntVal = apf.bitcastToAPInt(); + } + return GV; + } + case Instruction::SIToFP: { + GenericValue GV = getConstantValue(Op0); + if (CE->getType()->isFloatTy()) + GV.FloatVal = float(GV.IntVal.signedRoundToDouble()); + else if (CE->getType()->isDoubleTy()) + GV.DoubleVal = GV.IntVal.signedRoundToDouble(); + else if (CE->getType()->isX86_FP80Ty()) { + const uint64_t zero[] = { 0, 0}; + APFloat apf = APFloat(APInt(80, 2, zero)); + (void)apf.convertFromAPInt(GV.IntVal, + true, + APFloat::rmNearestTiesToEven); + GV.IntVal = apf.bitcastToAPInt(); + } + return GV; + } + case Instruction::FPToUI: // double->APInt conversion handles sign + case Instruction::FPToSI: { + GenericValue GV = getConstantValue(Op0); + uint32_t BitWidth = cast(CE->getType())->getBitWidth(); + if (Op0->getType()->isFloatTy()) + GV.IntVal = APIntOps::RoundFloatToAPInt(GV.FloatVal, BitWidth); + else if (Op0->getType()->isDoubleTy()) + GV.IntVal = APIntOps::RoundDoubleToAPInt(GV.DoubleVal, BitWidth); + else if (Op0->getType()->isX86_FP80Ty()) { + APFloat apf = APFloat(GV.IntVal); + uint64_t v; + bool ignored; + (void)apf.convertToInteger(&v, BitWidth, + CE->getOpcode()==Instruction::FPToSI, + APFloat::rmTowardZero, &ignored); + GV.IntVal = v; // endian? + } + return GV; + } + case Instruction::PtrToInt: { + GenericValue GV = getConstantValue(Op0); + uint32_t PtrWidth = TD->getPointerSizeInBits(); + GV.IntVal = APInt(PtrWidth, uintptr_t(GV.PointerVal)); + return GV; + } + case Instruction::IntToPtr: { + GenericValue GV = getConstantValue(Op0); + uint32_t PtrWidth = TD->getPointerSizeInBits(); + if (PtrWidth != GV.IntVal.getBitWidth()) + GV.IntVal = GV.IntVal.zextOrTrunc(PtrWidth); + assert(GV.IntVal.getBitWidth() <= 64 && "Bad pointer width"); + GV.PointerVal = PointerTy(uintptr_t(GV.IntVal.getZExtValue())); + return GV; + } + case Instruction::BitCast: { + GenericValue GV = getConstantValue(Op0); + const Type* DestTy = CE->getType(); + switch (Op0->getType()->getTypeID()) { + default: llvm_unreachable("Invalid bitcast operand"); + case Type::IntegerTyID: + assert(DestTy->isFloatingPoint() && "invalid bitcast"); + if (DestTy->isFloatTy()) + GV.FloatVal = GV.IntVal.bitsToFloat(); + else if (DestTy->isDoubleTy()) + GV.DoubleVal = GV.IntVal.bitsToDouble(); + break; + case Type::FloatTyID: + assert(DestTy == Type::getInt32Ty(DestTy->getContext()) && + "Invalid bitcast"); + GV.IntVal.floatToBits(GV.FloatVal); + break; + case Type::DoubleTyID: + assert(DestTy == Type::getInt64Ty(DestTy->getContext()) && + "Invalid bitcast"); + GV.IntVal.doubleToBits(GV.DoubleVal); + break; + case Type::PointerTyID: + assert(isa(DestTy) && "Invalid bitcast"); + break; // getConstantValue(Op0) above already converted it + } + return GV; + } + case Instruction::Add: + case Instruction::FAdd: + case Instruction::Sub: + case Instruction::FSub: + case Instruction::Mul: + case Instruction::FMul: + case Instruction::UDiv: + case Instruction::SDiv: + case Instruction::URem: + case Instruction::SRem: + case Instruction::And: + case Instruction::Or: + case Instruction::Xor: { + GenericValue LHS = getConstantValue(Op0); + GenericValue RHS = getConstantValue(CE->getOperand(1)); + GenericValue GV; + switch (CE->getOperand(0)->getType()->getTypeID()) { + default: llvm_unreachable("Bad add type!"); + case Type::IntegerTyID: + switch (CE->getOpcode()) { + default: llvm_unreachable("Invalid integer opcode"); + case Instruction::Add: GV.IntVal = LHS.IntVal + RHS.IntVal; break; + case Instruction::Sub: GV.IntVal = LHS.IntVal - RHS.IntVal; break; + case Instruction::Mul: GV.IntVal = LHS.IntVal * RHS.IntVal; break; + case Instruction::UDiv:GV.IntVal = LHS.IntVal.udiv(RHS.IntVal); break; + case Instruction::SDiv:GV.IntVal = LHS.IntVal.sdiv(RHS.IntVal); break; + case Instruction::URem:GV.IntVal = LHS.IntVal.urem(RHS.IntVal); break; + case Instruction::SRem:GV.IntVal = LHS.IntVal.srem(RHS.IntVal); break; + case Instruction::And: GV.IntVal = LHS.IntVal & RHS.IntVal; break; + case Instruction::Or: GV.IntVal = LHS.IntVal | RHS.IntVal; break; + case Instruction::Xor: GV.IntVal = LHS.IntVal ^ RHS.IntVal; break; + } + break; + case Type::FloatTyID: + switch (CE->getOpcode()) { + default: llvm_unreachable("Invalid float opcode"); + case Instruction::FAdd: + GV.FloatVal = LHS.FloatVal + RHS.FloatVal; break; + case Instruction::FSub: + GV.FloatVal = LHS.FloatVal - RHS.FloatVal; break; + case Instruction::FMul: + GV.FloatVal = LHS.FloatVal * RHS.FloatVal; break; + case Instruction::FDiv: + GV.FloatVal = LHS.FloatVal / RHS.FloatVal; break; + case Instruction::FRem: + GV.FloatVal = ::fmodf(LHS.FloatVal,RHS.FloatVal); break; + } + break; + case Type::DoubleTyID: + switch (CE->getOpcode()) { + default: llvm_unreachable("Invalid double opcode"); + case Instruction::FAdd: + GV.DoubleVal = LHS.DoubleVal + RHS.DoubleVal; break; + case Instruction::FSub: + GV.DoubleVal = LHS.DoubleVal - RHS.DoubleVal; break; + case Instruction::FMul: + GV.DoubleVal = LHS.DoubleVal * RHS.DoubleVal; break; + case Instruction::FDiv: + GV.DoubleVal = LHS.DoubleVal / RHS.DoubleVal; break; + case Instruction::FRem: + GV.DoubleVal = ::fmod(LHS.DoubleVal,RHS.DoubleVal); break; + } + break; + case Type::X86_FP80TyID: + case Type::PPC_FP128TyID: + case Type::FP128TyID: { + APFloat apfLHS = APFloat(LHS.IntVal); + switch (CE->getOpcode()) { + default: llvm_unreachable("Invalid long double opcode");llvm_unreachable(0); + case Instruction::FAdd: + apfLHS.add(APFloat(RHS.IntVal), APFloat::rmNearestTiesToEven); + GV.IntVal = apfLHS.bitcastToAPInt(); + break; + case Instruction::FSub: + apfLHS.subtract(APFloat(RHS.IntVal), APFloat::rmNearestTiesToEven); + GV.IntVal = apfLHS.bitcastToAPInt(); + break; + case Instruction::FMul: + apfLHS.multiply(APFloat(RHS.IntVal), APFloat::rmNearestTiesToEven); + GV.IntVal = apfLHS.bitcastToAPInt(); + break; + case Instruction::FDiv: + apfLHS.divide(APFloat(RHS.IntVal), APFloat::rmNearestTiesToEven); + GV.IntVal = apfLHS.bitcastToAPInt(); + break; + case Instruction::FRem: + apfLHS.mod(APFloat(RHS.IntVal), APFloat::rmNearestTiesToEven); + GV.IntVal = apfLHS.bitcastToAPInt(); + break; + } + } + break; + } + return GV; + } + default: + break; + } + std::string msg; + raw_string_ostream Msg(msg); + Msg << "ConstantExpr not handled: " << *CE; + llvm_report_error(Msg.str()); + } + + GenericValue Result; + switch (C->getType()->getTypeID()) { + case Type::FloatTyID: + Result.FloatVal = cast(C)->getValueAPF().convertToFloat(); + break; + case Type::DoubleTyID: + Result.DoubleVal = cast(C)->getValueAPF().convertToDouble(); + break; + case Type::X86_FP80TyID: + case Type::FP128TyID: + case Type::PPC_FP128TyID: + Result.IntVal = cast (C)->getValueAPF().bitcastToAPInt(); + break; + case Type::IntegerTyID: + Result.IntVal = cast(C)->getValue(); + break; + case Type::PointerTyID: + if (isa(C)) + Result.PointerVal = 0; + else if (const Function *F = dyn_cast(C)) + Result = PTOGV(getPointerToFunctionOrStub(const_cast(F))); + else if (const GlobalVariable *GV = dyn_cast(C)) + Result = PTOGV(getOrEmitGlobalVariable(const_cast(GV))); + else if (const BlockAddress *BA = dyn_cast(C)) + Result = PTOGV(getPointerToBasicBlock(const_cast( + BA->getBasicBlock()))); + else + llvm_unreachable("Unknown constant pointer type!"); + break; + default: + std::string msg; + raw_string_ostream Msg(msg); + Msg << "ERROR: Constant unimplemented for type: " << *C->getType(); + llvm_report_error(Msg.str()); + } + return Result; +} + +/// StoreIntToMemory - Fills the StoreBytes bytes of memory starting from Dst +/// with the integer held in IntVal. +static void StoreIntToMemory(const APInt &IntVal, uint8_t *Dst, + unsigned StoreBytes) { + assert((IntVal.getBitWidth()+7)/8 >= StoreBytes && "Integer too small!"); + uint8_t *Src = (uint8_t *)IntVal.getRawData(); + + if (sys::isLittleEndianHost()) + // Little-endian host - the source is ordered from LSB to MSB. Order the + // destination from LSB to MSB: Do a straight copy. + memcpy(Dst, Src, StoreBytes); + else { + // Big-endian host - the source is an array of 64 bit words ordered from + // LSW to MSW. Each word is ordered from MSB to LSB. Order the destination + // from MSB to LSB: Reverse the word order, but not the bytes in a word. + while (StoreBytes > sizeof(uint64_t)) { + StoreBytes -= sizeof(uint64_t); + // May not be aligned so use memcpy. + memcpy(Dst + StoreBytes, Src, sizeof(uint64_t)); + Src += sizeof(uint64_t); + } + + memcpy(Dst, Src + sizeof(uint64_t) - StoreBytes, StoreBytes); + } +} + +/// StoreValueToMemory - Stores the data in Val of type Ty at address Ptr. Ptr +/// is the address of the memory at which to store Val, cast to GenericValue *. +/// It is not a pointer to a GenericValue containing the address at which to +/// store Val. +void ExecutionEngine::StoreValueToMemory(const GenericValue &Val, + GenericValue *Ptr, const Type *Ty) { + const unsigned StoreBytes = getTargetData()->getTypeStoreSize(Ty); + + switch (Ty->getTypeID()) { + case Type::IntegerTyID: + StoreIntToMemory(Val.IntVal, (uint8_t*)Ptr, StoreBytes); + break; + case Type::FloatTyID: + *((float*)Ptr) = Val.FloatVal; + break; + case Type::DoubleTyID: + *((double*)Ptr) = Val.DoubleVal; + break; + case Type::X86_FP80TyID: + memcpy(Ptr, Val.IntVal.getRawData(), 10); + break; + case Type::PointerTyID: + // Ensure 64 bit target pointers are fully initialized on 32 bit hosts. + if (StoreBytes != sizeof(PointerTy)) + memset(Ptr, 0, StoreBytes); + + *((PointerTy*)Ptr) = Val.PointerVal; + break; + default: + errs() << "Cannot store value of type " << *Ty << "!\n"; + } + + if (sys::isLittleEndianHost() != getTargetData()->isLittleEndian()) + // Host and target are different endian - reverse the stored bytes. + std::reverse((uint8_t*)Ptr, StoreBytes + (uint8_t*)Ptr); +} + +/// LoadIntFromMemory - Loads the integer stored in the LoadBytes bytes starting +/// from Src into IntVal, which is assumed to be wide enough and to hold zero. +static void LoadIntFromMemory(APInt &IntVal, uint8_t *Src, unsigned LoadBytes) { + assert((IntVal.getBitWidth()+7)/8 >= LoadBytes && "Integer too small!"); + uint8_t *Dst = (uint8_t *)IntVal.getRawData(); + + if (sys::isLittleEndianHost()) + // Little-endian host - the destination must be ordered from LSB to MSB. + // The source is ordered from LSB to MSB: Do a straight copy. + memcpy(Dst, Src, LoadBytes); + else { + // Big-endian - the destination is an array of 64 bit words ordered from + // LSW to MSW. Each word must be ordered from MSB to LSB. The source is + // ordered from MSB to LSB: Reverse the word order, but not the bytes in + // a word. + while (LoadBytes > sizeof(uint64_t)) { + LoadBytes -= sizeof(uint64_t); + // May not be aligned so use memcpy. + memcpy(Dst, Src + LoadBytes, sizeof(uint64_t)); + Dst += sizeof(uint64_t); + } + + memcpy(Dst + sizeof(uint64_t) - LoadBytes, Src, LoadBytes); + } +} + +/// FIXME: document +/// +void ExecutionEngine::LoadValueFromMemory(GenericValue &Result, + GenericValue *Ptr, + const Type *Ty) { + const unsigned LoadBytes = getTargetData()->getTypeStoreSize(Ty); + + switch (Ty->getTypeID()) { + case Type::IntegerTyID: + // An APInt with all words initially zero. + Result.IntVal = APInt(cast(Ty)->getBitWidth(), 0); + LoadIntFromMemory(Result.IntVal, (uint8_t*)Ptr, LoadBytes); + break; + case Type::FloatTyID: + Result.FloatVal = *((float*)Ptr); + break; + case Type::DoubleTyID: + Result.DoubleVal = *((double*)Ptr); + break; + case Type::PointerTyID: + Result.PointerVal = *((PointerTy*)Ptr); + break; + case Type::X86_FP80TyID: { + // This is endian dependent, but it will only work on x86 anyway. + // FIXME: Will not trap if loading a signaling NaN. + uint64_t y[2]; + memcpy(y, Ptr, 10); + Result.IntVal = APInt(80, 2, y); + break; + } + default: + std::string msg; + raw_string_ostream Msg(msg); + Msg << "Cannot load value of type " << *Ty << "!"; + llvm_report_error(Msg.str()); + } +} + +// InitializeMemory - Recursive function to apply a Constant value into the +// specified memory location... +// +void ExecutionEngine::InitializeMemory(const Constant *Init, void *Addr) { + DEBUG(errs() << "JIT: Initializing " << Addr << " "); + DEBUG(Init->dump()); + if (isa(Init)) { + return; + } else if (const ConstantVector *CP = dyn_cast(Init)) { + unsigned ElementSize = + getTargetData()->getTypeAllocSize(CP->getType()->getElementType()); + for (unsigned i = 0, e = CP->getNumOperands(); i != e; ++i) + InitializeMemory(CP->getOperand(i), (char*)Addr+i*ElementSize); + return; + } else if (isa(Init)) { + memset(Addr, 0, (size_t)getTargetData()->getTypeAllocSize(Init->getType())); + return; + } else if (const ConstantArray *CPA = dyn_cast(Init)) { + unsigned ElementSize = + getTargetData()->getTypeAllocSize(CPA->getType()->getElementType()); + for (unsigned i = 0, e = CPA->getNumOperands(); i != e; ++i) + InitializeMemory(CPA->getOperand(i), (char*)Addr+i*ElementSize); + return; + } else if (const ConstantStruct *CPS = dyn_cast(Init)) { + const StructLayout *SL = + getTargetData()->getStructLayout(cast(CPS->getType())); + for (unsigned i = 0, e = CPS->getNumOperands(); i != e; ++i) + InitializeMemory(CPS->getOperand(i), (char*)Addr+SL->getElementOffset(i)); + return; + } else if (Init->getType()->isFirstClassType()) { + GenericValue Val = getConstantValue(Init); + StoreValueToMemory(Val, (GenericValue*)Addr, Init->getType()); + return; + } + + errs() << "Bad Type: " << *Init->getType() << "\n"; + llvm_unreachable("Unknown constant type to initialize memory with!"); +} + +/// EmitGlobals - Emit all of the global variables to memory, storing their +/// addresses into GlobalAddress. This must make sure to copy the contents of +/// their initializers into the memory. +/// +void ExecutionEngine::emitGlobals() { + + // Loop over all of the global variables in the program, allocating the memory + // to hold them. If there is more than one module, do a prepass over globals + // to figure out how the different modules should link together. + // + std::map, + const GlobalValue*> LinkedGlobalsMap; + + if (Modules.size() != 1) { + for (unsigned m = 0, e = Modules.size(); m != e; ++m) { + Module &M = *Modules[m]->getModule(); + for (Module::const_global_iterator I = M.global_begin(), + E = M.global_end(); I != E; ++I) { + const GlobalValue *GV = I; + if (GV->hasLocalLinkage() || GV->isDeclaration() || + GV->hasAppendingLinkage() || !GV->hasName()) + continue;// Ignore external globals and globals with internal linkage. + + const GlobalValue *&GVEntry = + LinkedGlobalsMap[std::make_pair(GV->getName(), GV->getType())]; + + // If this is the first time we've seen this global, it is the canonical + // version. + if (!GVEntry) { + GVEntry = GV; + continue; + } + + // If the existing global is strong, never replace it. + if (GVEntry->hasExternalLinkage() || + GVEntry->hasDLLImportLinkage() || + GVEntry->hasDLLExportLinkage()) + continue; + + // Otherwise, we know it's linkonce/weak, replace it if this is a strong + // symbol. FIXME is this right for common? + if (GV->hasExternalLinkage() || GVEntry->hasExternalWeakLinkage()) + GVEntry = GV; + } + } + } + + std::vector NonCanonicalGlobals; + for (unsigned m = 0, e = Modules.size(); m != e; ++m) { + Module &M = *Modules[m]->getModule(); + for (Module::const_global_iterator I = M.global_begin(), E = M.global_end(); + I != E; ++I) { + // In the multi-module case, see what this global maps to. + if (!LinkedGlobalsMap.empty()) { + if (const GlobalValue *GVEntry = + LinkedGlobalsMap[std::make_pair(I->getName(), I->getType())]) { + // If something else is the canonical global, ignore this one. + if (GVEntry != &*I) { + NonCanonicalGlobals.push_back(I); + continue; + } + } + } + + if (!I->isDeclaration()) { + addGlobalMapping(I, getMemoryForGV(I)); + } else { + // External variable reference. Try to use the dynamic loader to + // get a pointer to it. + if (void *SymAddr = + sys::DynamicLibrary::SearchForAddressOfSymbol(I->getName())) + addGlobalMapping(I, SymAddr); + else { + llvm_report_error("Could not resolve external global address: " + +I->getName()); + } + } + } + + // If there are multiple modules, map the non-canonical globals to their + // canonical location. + if (!NonCanonicalGlobals.empty()) { + for (unsigned i = 0, e = NonCanonicalGlobals.size(); i != e; ++i) { + const GlobalValue *GV = NonCanonicalGlobals[i]; + const GlobalValue *CGV = + LinkedGlobalsMap[std::make_pair(GV->getName(), GV->getType())]; + void *Ptr = getPointerToGlobalIfAvailable(CGV); + assert(Ptr && "Canonical global wasn't codegen'd!"); + addGlobalMapping(GV, Ptr); + } + } + + // Now that all of the globals are set up in memory, loop through them all + // and initialize their contents. + for (Module::const_global_iterator I = M.global_begin(), E = M.global_end(); + I != E; ++I) { + if (!I->isDeclaration()) { + if (!LinkedGlobalsMap.empty()) { + if (const GlobalValue *GVEntry = + LinkedGlobalsMap[std::make_pair(I->getName(), I->getType())]) + if (GVEntry != &*I) // Not the canonical variable. + continue; + } + EmitGlobalVariable(I); + } + } + } +} + +// EmitGlobalVariable - This method emits the specified global variable to the +// address specified in GlobalAddresses, or allocates new memory if it's not +// already in the map. +void ExecutionEngine::EmitGlobalVariable(const GlobalVariable *GV) { + void *GA = getPointerToGlobalIfAvailable(GV); + + if (GA == 0) { + // If it's not already specified, allocate memory for the global. + GA = getMemoryForGV(GV); + addGlobalMapping(GV, GA); + } + + // Don't initialize if it's thread local, let the client do it. + if (!GV->isThreadLocal()) + InitializeMemory(GV->getInitializer(), GA); + + const Type *ElTy = GV->getType()->getElementType(); + size_t GVSize = (size_t)getTargetData()->getTypeAllocSize(ElTy); + NumInitBytes += (unsigned)GVSize; + ++NumGlobals; +} + +ExecutionEngineState::ExecutionEngineState(ExecutionEngine &EE) + : EE(EE), GlobalAddressMap(this) { +} + +sys::Mutex *ExecutionEngineState::AddressMapConfig::getMutex( + ExecutionEngineState *EES) { + return &EES->EE.lock; +} +void ExecutionEngineState::AddressMapConfig::onDelete( + ExecutionEngineState *EES, const GlobalValue *Old) { + void *OldVal = EES->GlobalAddressMap.lookup(Old); + EES->GlobalAddressReverseMap.erase(OldVal); +} + +void ExecutionEngineState::AddressMapConfig::onRAUW( + ExecutionEngineState *, const GlobalValue *, const GlobalValue *) { + assert(false && "The ExecutionEngine doesn't know how to handle a" + " RAUW on a value it has a global mapping for."); +} diff --git a/libclamav/c++/llvm/lib/ExecutionEngine/ExecutionEngineBindings.cpp b/libclamav/c++/llvm/lib/ExecutionEngine/ExecutionEngineBindings.cpp new file mode 100644 index 000000000..5901cd757 --- /dev/null +++ b/libclamav/c++/llvm/lib/ExecutionEngine/ExecutionEngineBindings.cpp @@ -0,0 +1,213 @@ +//===-- ExecutionEngineBindings.cpp - C bindings for EEs ------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the C bindings for the ExecutionEngine library. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "jit" +#include "llvm-c/ExecutionEngine.h" +#include "llvm/ExecutionEngine/GenericValue.h" +#include "llvm/ExecutionEngine/ExecutionEngine.h" +#include "llvm/Support/ErrorHandling.h" +#include + +using namespace llvm; + +/*===-- Operations on generic values --------------------------------------===*/ + +LLVMGenericValueRef LLVMCreateGenericValueOfInt(LLVMTypeRef Ty, + unsigned long long N, + int IsSigned) { + GenericValue *GenVal = new GenericValue(); + GenVal->IntVal = APInt(unwrap(Ty)->getBitWidth(), N, IsSigned); + return wrap(GenVal); +} + +LLVMGenericValueRef LLVMCreateGenericValueOfPointer(void *P) { + GenericValue *GenVal = new GenericValue(); + GenVal->PointerVal = P; + return wrap(GenVal); +} + +LLVMGenericValueRef LLVMCreateGenericValueOfFloat(LLVMTypeRef TyRef, double N) { + GenericValue *GenVal = new GenericValue(); + switch (unwrap(TyRef)->getTypeID()) { + case Type::FloatTyID: + GenVal->FloatVal = N; + break; + case Type::DoubleTyID: + GenVal->DoubleVal = N; + break; + default: + llvm_unreachable("LLVMGenericValueToFloat supports only float and double."); + } + return wrap(GenVal); +} + +unsigned LLVMGenericValueIntWidth(LLVMGenericValueRef GenValRef) { + return unwrap(GenValRef)->IntVal.getBitWidth(); +} + +unsigned long long LLVMGenericValueToInt(LLVMGenericValueRef GenValRef, + int IsSigned) { + GenericValue *GenVal = unwrap(GenValRef); + if (IsSigned) + return GenVal->IntVal.getSExtValue(); + else + return GenVal->IntVal.getZExtValue(); +} + +void *LLVMGenericValueToPointer(LLVMGenericValueRef GenVal) { + return unwrap(GenVal)->PointerVal; +} + +double LLVMGenericValueToFloat(LLVMTypeRef TyRef, LLVMGenericValueRef GenVal) { + switch (unwrap(TyRef)->getTypeID()) { + case Type::FloatTyID: + return unwrap(GenVal)->FloatVal; + case Type::DoubleTyID: + return unwrap(GenVal)->DoubleVal; + default: + llvm_unreachable("LLVMGenericValueToFloat supports only float and double."); + break; + } + return 0; // Not reached +} + +void LLVMDisposeGenericValue(LLVMGenericValueRef GenVal) { + delete unwrap(GenVal); +} + +/*===-- Operations on execution engines -----------------------------------===*/ + +int LLVMCreateExecutionEngine(LLVMExecutionEngineRef *OutEE, + LLVMModuleProviderRef MP, + char **OutError) { + std::string Error; + EngineBuilder builder(unwrap(MP)); + builder.setEngineKind(EngineKind::Either) + .setErrorStr(&Error); + if (ExecutionEngine *EE = builder.create()){ + *OutEE = wrap(EE); + return 0; + } + *OutError = strdup(Error.c_str()); + return 1; +} + +int LLVMCreateInterpreter(LLVMExecutionEngineRef *OutInterp, + LLVMModuleProviderRef MP, + char **OutError) { + std::string Error; + EngineBuilder builder(unwrap(MP)); + builder.setEngineKind(EngineKind::Interpreter) + .setErrorStr(&Error); + if (ExecutionEngine *Interp = builder.create()) { + *OutInterp = wrap(Interp); + return 0; + } + *OutError = strdup(Error.c_str()); + return 1; +} + +int LLVMCreateJITCompiler(LLVMExecutionEngineRef *OutJIT, + LLVMModuleProviderRef MP, + unsigned OptLevel, + char **OutError) { + std::string Error; + EngineBuilder builder(unwrap(MP)); + builder.setEngineKind(EngineKind::JIT) + .setErrorStr(&Error) + .setOptLevel((CodeGenOpt::Level)OptLevel); + if (ExecutionEngine *JIT = builder.create()) { + *OutJIT = wrap(JIT); + return 0; + } + *OutError = strdup(Error.c_str()); + return 1; +} + +void LLVMDisposeExecutionEngine(LLVMExecutionEngineRef EE) { + delete unwrap(EE); +} + +void LLVMRunStaticConstructors(LLVMExecutionEngineRef EE) { + unwrap(EE)->runStaticConstructorsDestructors(false); +} + +void LLVMRunStaticDestructors(LLVMExecutionEngineRef EE) { + unwrap(EE)->runStaticConstructorsDestructors(true); +} + +int LLVMRunFunctionAsMain(LLVMExecutionEngineRef EE, LLVMValueRef F, + unsigned ArgC, const char * const *ArgV, + const char * const *EnvP) { + std::vector ArgVec; + for (unsigned I = 0; I != ArgC; ++I) + ArgVec.push_back(ArgV[I]); + + return unwrap(EE)->runFunctionAsMain(unwrap(F), ArgVec, EnvP); +} + +LLVMGenericValueRef LLVMRunFunction(LLVMExecutionEngineRef EE, LLVMValueRef F, + unsigned NumArgs, + LLVMGenericValueRef *Args) { + std::vector ArgVec; + ArgVec.reserve(NumArgs); + for (unsigned I = 0; I != NumArgs; ++I) + ArgVec.push_back(*unwrap(Args[I])); + + GenericValue *Result = new GenericValue(); + *Result = unwrap(EE)->runFunction(unwrap(F), ArgVec); + return wrap(Result); +} + +void LLVMFreeMachineCodeForFunction(LLVMExecutionEngineRef EE, LLVMValueRef F) { + unwrap(EE)->freeMachineCodeForFunction(unwrap(F)); +} + +void LLVMAddModuleProvider(LLVMExecutionEngineRef EE, LLVMModuleProviderRef MP){ + unwrap(EE)->addModuleProvider(unwrap(MP)); +} + +int LLVMRemoveModuleProvider(LLVMExecutionEngineRef EE, + LLVMModuleProviderRef MP, + LLVMModuleRef *OutMod, char **OutError) { + std::string Error; + if (Module *Gone = unwrap(EE)->removeModuleProvider(unwrap(MP), &Error)) { + *OutMod = wrap(Gone); + return 0; + } + if (OutError) + *OutError = strdup(Error.c_str()); + return 1; +} + +int LLVMFindFunction(LLVMExecutionEngineRef EE, const char *Name, + LLVMValueRef *OutFn) { + if (Function *F = unwrap(EE)->FindFunctionNamed(Name)) { + *OutFn = wrap(F); + return 0; + } + return 1; +} + +LLVMTargetDataRef LLVMGetExecutionEngineTargetData(LLVMExecutionEngineRef EE) { + return wrap(unwrap(EE)->getTargetData()); +} + +void LLVMAddGlobalMapping(LLVMExecutionEngineRef EE, LLVMValueRef Global, + void* Addr) { + unwrap(EE)->addGlobalMapping(unwrap(Global), Addr); +} + +void *LLVMGetPointerToGlobal(LLVMExecutionEngineRef EE, LLVMValueRef Global) { + return unwrap(EE)->getPointerToGlobal(unwrap(Global)); +} diff --git a/libclamav/c++/llvm/lib/ExecutionEngine/Interpreter/CMakeLists.txt b/libclamav/c++/llvm/lib/ExecutionEngine/Interpreter/CMakeLists.txt new file mode 100644 index 000000000..dff97fa26 --- /dev/null +++ b/libclamav/c++/llvm/lib/ExecutionEngine/Interpreter/CMakeLists.txt @@ -0,0 +1,5 @@ +add_llvm_library(LLVMInterpreter + Execution.cpp + ExternalFunctions.cpp + Interpreter.cpp + ) diff --git a/libclamav/c++/llvm/lib/ExecutionEngine/Interpreter/Execution.cpp b/libclamav/c++/llvm/lib/ExecutionEngine/Interpreter/Execution.cpp new file mode 100644 index 000000000..b59cfd162 --- /dev/null +++ b/libclamav/c++/llvm/lib/ExecutionEngine/Interpreter/Execution.cpp @@ -0,0 +1,1352 @@ +//===-- Execution.cpp - Implement code to simulate the program ------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the actual instruction interpreter. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "interpreter" +#include "Interpreter.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Instructions.h" +#include "llvm/CodeGen/IntrinsicLowering.h" +#include "llvm/Support/GetElementPtrTypeIterator.h" +#include "llvm/ADT/APInt.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/MathExtras.h" +#include +#include +using namespace llvm; + +STATISTIC(NumDynamicInsts, "Number of dynamic instructions executed"); + +static cl::opt PrintVolatile("interpreter-print-volatile", cl::Hidden, + cl::desc("make the interpreter print every volatile load and store")); + +//===----------------------------------------------------------------------===// +// Various Helper Functions +//===----------------------------------------------------------------------===// + +static void SetValue(Value *V, GenericValue Val, ExecutionContext &SF) { + SF.Values[V] = Val; +} + +//===----------------------------------------------------------------------===// +// Binary Instruction Implementations +//===----------------------------------------------------------------------===// + +#define IMPLEMENT_BINARY_OPERATOR(OP, TY) \ + case Type::TY##TyID: \ + Dest.TY##Val = Src1.TY##Val OP Src2.TY##Val; \ + break + +static void executeFAddInst(GenericValue &Dest, GenericValue Src1, + GenericValue Src2, const Type *Ty) { + switch (Ty->getTypeID()) { + IMPLEMENT_BINARY_OPERATOR(+, Float); + IMPLEMENT_BINARY_OPERATOR(+, Double); + default: + errs() << "Unhandled type for FAdd instruction: " << *Ty << "\n"; + llvm_unreachable(0); + } +} + +static void executeFSubInst(GenericValue &Dest, GenericValue Src1, + GenericValue Src2, const Type *Ty) { + switch (Ty->getTypeID()) { + IMPLEMENT_BINARY_OPERATOR(-, Float); + IMPLEMENT_BINARY_OPERATOR(-, Double); + default: + errs() << "Unhandled type for FSub instruction: " << *Ty << "\n"; + llvm_unreachable(0); + } +} + +static void executeFMulInst(GenericValue &Dest, GenericValue Src1, + GenericValue Src2, const Type *Ty) { + switch (Ty->getTypeID()) { + IMPLEMENT_BINARY_OPERATOR(*, Float); + IMPLEMENT_BINARY_OPERATOR(*, Double); + default: + errs() << "Unhandled type for FMul instruction: " << *Ty << "\n"; + llvm_unreachable(0); + } +} + +static void executeFDivInst(GenericValue &Dest, GenericValue Src1, + GenericValue Src2, const Type *Ty) { + switch (Ty->getTypeID()) { + IMPLEMENT_BINARY_OPERATOR(/, Float); + IMPLEMENT_BINARY_OPERATOR(/, Double); + default: + errs() << "Unhandled type for FDiv instruction: " << *Ty << "\n"; + llvm_unreachable(0); + } +} + +static void executeFRemInst(GenericValue &Dest, GenericValue Src1, + GenericValue Src2, const Type *Ty) { + switch (Ty->getTypeID()) { + case Type::FloatTyID: + Dest.FloatVal = fmod(Src1.FloatVal, Src2.FloatVal); + break; + case Type::DoubleTyID: + Dest.DoubleVal = fmod(Src1.DoubleVal, Src2.DoubleVal); + break; + default: + errs() << "Unhandled type for Rem instruction: " << *Ty << "\n"; + llvm_unreachable(0); + } +} + +#define IMPLEMENT_INTEGER_ICMP(OP, TY) \ + case Type::IntegerTyID: \ + Dest.IntVal = APInt(1,Src1.IntVal.OP(Src2.IntVal)); \ + break; + +// Handle pointers specially because they must be compared with only as much +// width as the host has. We _do not_ want to be comparing 64 bit values when +// running on a 32-bit target, otherwise the upper 32 bits might mess up +// comparisons if they contain garbage. +#define IMPLEMENT_POINTER_ICMP(OP) \ + case Type::PointerTyID: \ + Dest.IntVal = APInt(1,(void*)(intptr_t)Src1.PointerVal OP \ + (void*)(intptr_t)Src2.PointerVal); \ + break; + +static GenericValue executeICMP_EQ(GenericValue Src1, GenericValue Src2, + const Type *Ty) { + GenericValue Dest; + switch (Ty->getTypeID()) { + IMPLEMENT_INTEGER_ICMP(eq,Ty); + IMPLEMENT_POINTER_ICMP(==); + default: + errs() << "Unhandled type for ICMP_EQ predicate: " << *Ty << "\n"; + llvm_unreachable(0); + } + return Dest; +} + +static GenericValue executeICMP_NE(GenericValue Src1, GenericValue Src2, + const Type *Ty) { + GenericValue Dest; + switch (Ty->getTypeID()) { + IMPLEMENT_INTEGER_ICMP(ne,Ty); + IMPLEMENT_POINTER_ICMP(!=); + default: + errs() << "Unhandled type for ICMP_NE predicate: " << *Ty << "\n"; + llvm_unreachable(0); + } + return Dest; +} + +static GenericValue executeICMP_ULT(GenericValue Src1, GenericValue Src2, + const Type *Ty) { + GenericValue Dest; + switch (Ty->getTypeID()) { + IMPLEMENT_INTEGER_ICMP(ult,Ty); + IMPLEMENT_POINTER_ICMP(<); + default: + errs() << "Unhandled type for ICMP_ULT predicate: " << *Ty << "\n"; + llvm_unreachable(0); + } + return Dest; +} + +static GenericValue executeICMP_SLT(GenericValue Src1, GenericValue Src2, + const Type *Ty) { + GenericValue Dest; + switch (Ty->getTypeID()) { + IMPLEMENT_INTEGER_ICMP(slt,Ty); + IMPLEMENT_POINTER_ICMP(<); + default: + errs() << "Unhandled type for ICMP_SLT predicate: " << *Ty << "\n"; + llvm_unreachable(0); + } + return Dest; +} + +static GenericValue executeICMP_UGT(GenericValue Src1, GenericValue Src2, + const Type *Ty) { + GenericValue Dest; + switch (Ty->getTypeID()) { + IMPLEMENT_INTEGER_ICMP(ugt,Ty); + IMPLEMENT_POINTER_ICMP(>); + default: + errs() << "Unhandled type for ICMP_UGT predicate: " << *Ty << "\n"; + llvm_unreachable(0); + } + return Dest; +} + +static GenericValue executeICMP_SGT(GenericValue Src1, GenericValue Src2, + const Type *Ty) { + GenericValue Dest; + switch (Ty->getTypeID()) { + IMPLEMENT_INTEGER_ICMP(sgt,Ty); + IMPLEMENT_POINTER_ICMP(>); + default: + errs() << "Unhandled type for ICMP_SGT predicate: " << *Ty << "\n"; + llvm_unreachable(0); + } + return Dest; +} + +static GenericValue executeICMP_ULE(GenericValue Src1, GenericValue Src2, + const Type *Ty) { + GenericValue Dest; + switch (Ty->getTypeID()) { + IMPLEMENT_INTEGER_ICMP(ule,Ty); + IMPLEMENT_POINTER_ICMP(<=); + default: + errs() << "Unhandled type for ICMP_ULE predicate: " << *Ty << "\n"; + llvm_unreachable(0); + } + return Dest; +} + +static GenericValue executeICMP_SLE(GenericValue Src1, GenericValue Src2, + const Type *Ty) { + GenericValue Dest; + switch (Ty->getTypeID()) { + IMPLEMENT_INTEGER_ICMP(sle,Ty); + IMPLEMENT_POINTER_ICMP(<=); + default: + errs() << "Unhandled type for ICMP_SLE predicate: " << *Ty << "\n"; + llvm_unreachable(0); + } + return Dest; +} + +static GenericValue executeICMP_UGE(GenericValue Src1, GenericValue Src2, + const Type *Ty) { + GenericValue Dest; + switch (Ty->getTypeID()) { + IMPLEMENT_INTEGER_ICMP(uge,Ty); + IMPLEMENT_POINTER_ICMP(>=); + default: + errs() << "Unhandled type for ICMP_UGE predicate: " << *Ty << "\n"; + llvm_unreachable(0); + } + return Dest; +} + +static GenericValue executeICMP_SGE(GenericValue Src1, GenericValue Src2, + const Type *Ty) { + GenericValue Dest; + switch (Ty->getTypeID()) { + IMPLEMENT_INTEGER_ICMP(sge,Ty); + IMPLEMENT_POINTER_ICMP(>=); + default: + errs() << "Unhandled type for ICMP_SGE predicate: " << *Ty << "\n"; + llvm_unreachable(0); + } + return Dest; +} + +void Interpreter::visitICmpInst(ICmpInst &I) { + ExecutionContext &SF = ECStack.back(); + const Type *Ty = I.getOperand(0)->getType(); + GenericValue Src1 = getOperandValue(I.getOperand(0), SF); + GenericValue Src2 = getOperandValue(I.getOperand(1), SF); + GenericValue R; // Result + + switch (I.getPredicate()) { + case ICmpInst::ICMP_EQ: R = executeICMP_EQ(Src1, Src2, Ty); break; + case ICmpInst::ICMP_NE: R = executeICMP_NE(Src1, Src2, Ty); break; + case ICmpInst::ICMP_ULT: R = executeICMP_ULT(Src1, Src2, Ty); break; + case ICmpInst::ICMP_SLT: R = executeICMP_SLT(Src1, Src2, Ty); break; + case ICmpInst::ICMP_UGT: R = executeICMP_UGT(Src1, Src2, Ty); break; + case ICmpInst::ICMP_SGT: R = executeICMP_SGT(Src1, Src2, Ty); break; + case ICmpInst::ICMP_ULE: R = executeICMP_ULE(Src1, Src2, Ty); break; + case ICmpInst::ICMP_SLE: R = executeICMP_SLE(Src1, Src2, Ty); break; + case ICmpInst::ICMP_UGE: R = executeICMP_UGE(Src1, Src2, Ty); break; + case ICmpInst::ICMP_SGE: R = executeICMP_SGE(Src1, Src2, Ty); break; + default: + errs() << "Don't know how to handle this ICmp predicate!\n-->" << I; + llvm_unreachable(0); + } + + SetValue(&I, R, SF); +} + +#define IMPLEMENT_FCMP(OP, TY) \ + case Type::TY##TyID: \ + Dest.IntVal = APInt(1,Src1.TY##Val OP Src2.TY##Val); \ + break + +static GenericValue executeFCMP_OEQ(GenericValue Src1, GenericValue Src2, + const Type *Ty) { + GenericValue Dest; + switch (Ty->getTypeID()) { + IMPLEMENT_FCMP(==, Float); + IMPLEMENT_FCMP(==, Double); + default: + errs() << "Unhandled type for FCmp EQ instruction: " << *Ty << "\n"; + llvm_unreachable(0); + } + return Dest; +} + +static GenericValue executeFCMP_ONE(GenericValue Src1, GenericValue Src2, + const Type *Ty) { + GenericValue Dest; + switch (Ty->getTypeID()) { + IMPLEMENT_FCMP(!=, Float); + IMPLEMENT_FCMP(!=, Double); + + default: + errs() << "Unhandled type for FCmp NE instruction: " << *Ty << "\n"; + llvm_unreachable(0); + } + return Dest; +} + +static GenericValue executeFCMP_OLE(GenericValue Src1, GenericValue Src2, + const Type *Ty) { + GenericValue Dest; + switch (Ty->getTypeID()) { + IMPLEMENT_FCMP(<=, Float); + IMPLEMENT_FCMP(<=, Double); + default: + errs() << "Unhandled type for FCmp LE instruction: " << *Ty << "\n"; + llvm_unreachable(0); + } + return Dest; +} + +static GenericValue executeFCMP_OGE(GenericValue Src1, GenericValue Src2, + const Type *Ty) { + GenericValue Dest; + switch (Ty->getTypeID()) { + IMPLEMENT_FCMP(>=, Float); + IMPLEMENT_FCMP(>=, Double); + default: + errs() << "Unhandled type for FCmp GE instruction: " << *Ty << "\n"; + llvm_unreachable(0); + } + return Dest; +} + +static GenericValue executeFCMP_OLT(GenericValue Src1, GenericValue Src2, + const Type *Ty) { + GenericValue Dest; + switch (Ty->getTypeID()) { + IMPLEMENT_FCMP(<, Float); + IMPLEMENT_FCMP(<, Double); + default: + errs() << "Unhandled type for FCmp LT instruction: " << *Ty << "\n"; + llvm_unreachable(0); + } + return Dest; +} + +static GenericValue executeFCMP_OGT(GenericValue Src1, GenericValue Src2, + const Type *Ty) { + GenericValue Dest; + switch (Ty->getTypeID()) { + IMPLEMENT_FCMP(>, Float); + IMPLEMENT_FCMP(>, Double); + default: + errs() << "Unhandled type for FCmp GT instruction: " << *Ty << "\n"; + llvm_unreachable(0); + } + return Dest; +} + +#define IMPLEMENT_UNORDERED(TY, X,Y) \ + if (TY->isFloatTy()) { \ + if (X.FloatVal != X.FloatVal || Y.FloatVal != Y.FloatVal) { \ + Dest.IntVal = APInt(1,true); \ + return Dest; \ + } \ + } else if (X.DoubleVal != X.DoubleVal || Y.DoubleVal != Y.DoubleVal) { \ + Dest.IntVal = APInt(1,true); \ + return Dest; \ + } + + +static GenericValue executeFCMP_UEQ(GenericValue Src1, GenericValue Src2, + const Type *Ty) { + GenericValue Dest; + IMPLEMENT_UNORDERED(Ty, Src1, Src2) + return executeFCMP_OEQ(Src1, Src2, Ty); +} + +static GenericValue executeFCMP_UNE(GenericValue Src1, GenericValue Src2, + const Type *Ty) { + GenericValue Dest; + IMPLEMENT_UNORDERED(Ty, Src1, Src2) + return executeFCMP_ONE(Src1, Src2, Ty); +} + +static GenericValue executeFCMP_ULE(GenericValue Src1, GenericValue Src2, + const Type *Ty) { + GenericValue Dest; + IMPLEMENT_UNORDERED(Ty, Src1, Src2) + return executeFCMP_OLE(Src1, Src2, Ty); +} + +static GenericValue executeFCMP_UGE(GenericValue Src1, GenericValue Src2, + const Type *Ty) { + GenericValue Dest; + IMPLEMENT_UNORDERED(Ty, Src1, Src2) + return executeFCMP_OGE(Src1, Src2, Ty); +} + +static GenericValue executeFCMP_ULT(GenericValue Src1, GenericValue Src2, + const Type *Ty) { + GenericValue Dest; + IMPLEMENT_UNORDERED(Ty, Src1, Src2) + return executeFCMP_OLT(Src1, Src2, Ty); +} + +static GenericValue executeFCMP_UGT(GenericValue Src1, GenericValue Src2, + const Type *Ty) { + GenericValue Dest; + IMPLEMENT_UNORDERED(Ty, Src1, Src2) + return executeFCMP_OGT(Src1, Src2, Ty); +} + +static GenericValue executeFCMP_ORD(GenericValue Src1, GenericValue Src2, + const Type *Ty) { + GenericValue Dest; + if (Ty->isFloatTy()) + Dest.IntVal = APInt(1,(Src1.FloatVal == Src1.FloatVal && + Src2.FloatVal == Src2.FloatVal)); + else + Dest.IntVal = APInt(1,(Src1.DoubleVal == Src1.DoubleVal && + Src2.DoubleVal == Src2.DoubleVal)); + return Dest; +} + +static GenericValue executeFCMP_UNO(GenericValue Src1, GenericValue Src2, + const Type *Ty) { + GenericValue Dest; + if (Ty->isFloatTy()) + Dest.IntVal = APInt(1,(Src1.FloatVal != Src1.FloatVal || + Src2.FloatVal != Src2.FloatVal)); + else + Dest.IntVal = APInt(1,(Src1.DoubleVal != Src1.DoubleVal || + Src2.DoubleVal != Src2.DoubleVal)); + return Dest; +} + +void Interpreter::visitFCmpInst(FCmpInst &I) { + ExecutionContext &SF = ECStack.back(); + const Type *Ty = I.getOperand(0)->getType(); + GenericValue Src1 = getOperandValue(I.getOperand(0), SF); + GenericValue Src2 = getOperandValue(I.getOperand(1), SF); + GenericValue R; // Result + + switch (I.getPredicate()) { + case FCmpInst::FCMP_FALSE: R.IntVal = APInt(1,false); break; + case FCmpInst::FCMP_TRUE: R.IntVal = APInt(1,true); break; + case FCmpInst::FCMP_ORD: R = executeFCMP_ORD(Src1, Src2, Ty); break; + case FCmpInst::FCMP_UNO: R = executeFCMP_UNO(Src1, Src2, Ty); break; + case FCmpInst::FCMP_UEQ: R = executeFCMP_UEQ(Src1, Src2, Ty); break; + case FCmpInst::FCMP_OEQ: R = executeFCMP_OEQ(Src1, Src2, Ty); break; + case FCmpInst::FCMP_UNE: R = executeFCMP_UNE(Src1, Src2, Ty); break; + case FCmpInst::FCMP_ONE: R = executeFCMP_ONE(Src1, Src2, Ty); break; + case FCmpInst::FCMP_ULT: R = executeFCMP_ULT(Src1, Src2, Ty); break; + case FCmpInst::FCMP_OLT: R = executeFCMP_OLT(Src1, Src2, Ty); break; + case FCmpInst::FCMP_UGT: R = executeFCMP_UGT(Src1, Src2, Ty); break; + case FCmpInst::FCMP_OGT: R = executeFCMP_OGT(Src1, Src2, Ty); break; + case FCmpInst::FCMP_ULE: R = executeFCMP_ULE(Src1, Src2, Ty); break; + case FCmpInst::FCMP_OLE: R = executeFCMP_OLE(Src1, Src2, Ty); break; + case FCmpInst::FCMP_UGE: R = executeFCMP_UGE(Src1, Src2, Ty); break; + case FCmpInst::FCMP_OGE: R = executeFCMP_OGE(Src1, Src2, Ty); break; + default: + errs() << "Don't know how to handle this FCmp predicate!\n-->" << I; + llvm_unreachable(0); + } + + SetValue(&I, R, SF); +} + +static GenericValue executeCmpInst(unsigned predicate, GenericValue Src1, + GenericValue Src2, const Type *Ty) { + GenericValue Result; + switch (predicate) { + case ICmpInst::ICMP_EQ: return executeICMP_EQ(Src1, Src2, Ty); + case ICmpInst::ICMP_NE: return executeICMP_NE(Src1, Src2, Ty); + case ICmpInst::ICMP_UGT: return executeICMP_UGT(Src1, Src2, Ty); + case ICmpInst::ICMP_SGT: return executeICMP_SGT(Src1, Src2, Ty); + case ICmpInst::ICMP_ULT: return executeICMP_ULT(Src1, Src2, Ty); + case ICmpInst::ICMP_SLT: return executeICMP_SLT(Src1, Src2, Ty); + case ICmpInst::ICMP_UGE: return executeICMP_UGE(Src1, Src2, Ty); + case ICmpInst::ICMP_SGE: return executeICMP_SGE(Src1, Src2, Ty); + case ICmpInst::ICMP_ULE: return executeICMP_ULE(Src1, Src2, Ty); + case ICmpInst::ICMP_SLE: return executeICMP_SLE(Src1, Src2, Ty); + case FCmpInst::FCMP_ORD: return executeFCMP_ORD(Src1, Src2, Ty); + case FCmpInst::FCMP_UNO: return executeFCMP_UNO(Src1, Src2, Ty); + case FCmpInst::FCMP_OEQ: return executeFCMP_OEQ(Src1, Src2, Ty); + case FCmpInst::FCMP_UEQ: return executeFCMP_UEQ(Src1, Src2, Ty); + case FCmpInst::FCMP_ONE: return executeFCMP_ONE(Src1, Src2, Ty); + case FCmpInst::FCMP_UNE: return executeFCMP_UNE(Src1, Src2, Ty); + case FCmpInst::FCMP_OLT: return executeFCMP_OLT(Src1, Src2, Ty); + case FCmpInst::FCMP_ULT: return executeFCMP_ULT(Src1, Src2, Ty); + case FCmpInst::FCMP_OGT: return executeFCMP_OGT(Src1, Src2, Ty); + case FCmpInst::FCMP_UGT: return executeFCMP_UGT(Src1, Src2, Ty); + case FCmpInst::FCMP_OLE: return executeFCMP_OLE(Src1, Src2, Ty); + case FCmpInst::FCMP_ULE: return executeFCMP_ULE(Src1, Src2, Ty); + case FCmpInst::FCMP_OGE: return executeFCMP_OGE(Src1, Src2, Ty); + case FCmpInst::FCMP_UGE: return executeFCMP_UGE(Src1, Src2, Ty); + case FCmpInst::FCMP_FALSE: { + GenericValue Result; + Result.IntVal = APInt(1, false); + return Result; + } + case FCmpInst::FCMP_TRUE: { + GenericValue Result; + Result.IntVal = APInt(1, true); + return Result; + } + default: + errs() << "Unhandled Cmp predicate\n"; + llvm_unreachable(0); + } +} + +void Interpreter::visitBinaryOperator(BinaryOperator &I) { + ExecutionContext &SF = ECStack.back(); + const Type *Ty = I.getOperand(0)->getType(); + GenericValue Src1 = getOperandValue(I.getOperand(0), SF); + GenericValue Src2 = getOperandValue(I.getOperand(1), SF); + GenericValue R; // Result + + switch (I.getOpcode()) { + case Instruction::Add: R.IntVal = Src1.IntVal + Src2.IntVal; break; + case Instruction::Sub: R.IntVal = Src1.IntVal - Src2.IntVal; break; + case Instruction::Mul: R.IntVal = Src1.IntVal * Src2.IntVal; break; + case Instruction::FAdd: executeFAddInst(R, Src1, Src2, Ty); break; + case Instruction::FSub: executeFSubInst(R, Src1, Src2, Ty); break; + case Instruction::FMul: executeFMulInst(R, Src1, Src2, Ty); break; + case Instruction::FDiv: executeFDivInst(R, Src1, Src2, Ty); break; + case Instruction::FRem: executeFRemInst(R, Src1, Src2, Ty); break; + case Instruction::UDiv: R.IntVal = Src1.IntVal.udiv(Src2.IntVal); break; + case Instruction::SDiv: R.IntVal = Src1.IntVal.sdiv(Src2.IntVal); break; + case Instruction::URem: R.IntVal = Src1.IntVal.urem(Src2.IntVal); break; + case Instruction::SRem: R.IntVal = Src1.IntVal.srem(Src2.IntVal); break; + case Instruction::And: R.IntVal = Src1.IntVal & Src2.IntVal; break; + case Instruction::Or: R.IntVal = Src1.IntVal | Src2.IntVal; break; + case Instruction::Xor: R.IntVal = Src1.IntVal ^ Src2.IntVal; break; + default: + errs() << "Don't know how to handle this binary operator!\n-->" << I; + llvm_unreachable(0); + } + + SetValue(&I, R, SF); +} + +static GenericValue executeSelectInst(GenericValue Src1, GenericValue Src2, + GenericValue Src3) { + return Src1.IntVal == 0 ? Src3 : Src2; +} + +void Interpreter::visitSelectInst(SelectInst &I) { + ExecutionContext &SF = ECStack.back(); + GenericValue Src1 = getOperandValue(I.getOperand(0), SF); + GenericValue Src2 = getOperandValue(I.getOperand(1), SF); + GenericValue Src3 = getOperandValue(I.getOperand(2), SF); + GenericValue R = executeSelectInst(Src1, Src2, Src3); + SetValue(&I, R, SF); +} + + +//===----------------------------------------------------------------------===// +// Terminator Instruction Implementations +//===----------------------------------------------------------------------===// + +void Interpreter::exitCalled(GenericValue GV) { + // runAtExitHandlers() assumes there are no stack frames, but + // if exit() was called, then it had a stack frame. Blow away + // the stack before interpreting atexit handlers. + ECStack.clear(); + runAtExitHandlers(); + exit(GV.IntVal.zextOrTrunc(32).getZExtValue()); +} + +/// Pop the last stack frame off of ECStack and then copy the result +/// back into the result variable if we are not returning void. The +/// result variable may be the ExitValue, or the Value of the calling +/// CallInst if there was a previous stack frame. This method may +/// invalidate any ECStack iterators you have. This method also takes +/// care of switching to the normal destination BB, if we are returning +/// from an invoke. +/// +void Interpreter::popStackAndReturnValueToCaller(const Type *RetTy, + GenericValue Result) { + // Pop the current stack frame. + ECStack.pop_back(); + + if (ECStack.empty()) { // Finished main. Put result into exit code... + if (RetTy && RetTy->isInteger()) { // Nonvoid return type? + ExitValue = Result; // Capture the exit value of the program + } else { + memset(&ExitValue.Untyped, 0, sizeof(ExitValue.Untyped)); + } + } else { + // If we have a previous stack frame, and we have a previous call, + // fill in the return value... + ExecutionContext &CallingSF = ECStack.back(); + if (Instruction *I = CallingSF.Caller.getInstruction()) { + // Save result... + if (CallingSF.Caller.getType() != Type::getVoidTy(RetTy->getContext())) + SetValue(I, Result, CallingSF); + if (InvokeInst *II = dyn_cast (I)) + SwitchToNewBasicBlock (II->getNormalDest (), CallingSF); + CallingSF.Caller = CallSite(); // We returned from the call... + } + } +} + +void Interpreter::visitReturnInst(ReturnInst &I) { + ExecutionContext &SF = ECStack.back(); + const Type *RetTy = Type::getVoidTy(I.getContext()); + GenericValue Result; + + // Save away the return value... (if we are not 'ret void') + if (I.getNumOperands()) { + RetTy = I.getReturnValue()->getType(); + Result = getOperandValue(I.getReturnValue(), SF); + } + + popStackAndReturnValueToCaller(RetTy, Result); +} + +void Interpreter::visitUnwindInst(UnwindInst &I) { + // Unwind stack + Instruction *Inst; + do { + ECStack.pop_back(); + if (ECStack.empty()) + llvm_report_error("Empty stack during unwind!"); + Inst = ECStack.back().Caller.getInstruction(); + } while (!(Inst && isa(Inst))); + + // Return from invoke + ExecutionContext &InvokingSF = ECStack.back(); + InvokingSF.Caller = CallSite(); + + // Go to exceptional destination BB of invoke instruction + SwitchToNewBasicBlock(cast(Inst)->getUnwindDest(), InvokingSF); +} + +void Interpreter::visitUnreachableInst(UnreachableInst &I) { + llvm_report_error("Program executed an 'unreachable' instruction!"); +} + +void Interpreter::visitBranchInst(BranchInst &I) { + ExecutionContext &SF = ECStack.back(); + BasicBlock *Dest; + + Dest = I.getSuccessor(0); // Uncond branches have a fixed dest... + if (!I.isUnconditional()) { + Value *Cond = I.getCondition(); + if (getOperandValue(Cond, SF).IntVal == 0) // If false cond... + Dest = I.getSuccessor(1); + } + SwitchToNewBasicBlock(Dest, SF); +} + +void Interpreter::visitSwitchInst(SwitchInst &I) { + ExecutionContext &SF = ECStack.back(); + GenericValue CondVal = getOperandValue(I.getOperand(0), SF); + const Type *ElTy = I.getOperand(0)->getType(); + + // Check to see if any of the cases match... + BasicBlock *Dest = 0; + for (unsigned i = 2, e = I.getNumOperands(); i != e; i += 2) + if (executeICMP_EQ(CondVal, getOperandValue(I.getOperand(i), SF), ElTy) + .IntVal != 0) { + Dest = cast(I.getOperand(i+1)); + break; + } + + if (!Dest) Dest = I.getDefaultDest(); // No cases matched: use default + SwitchToNewBasicBlock(Dest, SF); +} + +void Interpreter::visitIndirectBrInst(IndirectBrInst &I) { + ExecutionContext &SF = ECStack.back(); + void *Dest = GVTOP(getOperandValue(I.getAddress(), SF)); + SwitchToNewBasicBlock((BasicBlock*)Dest, SF); +} + + +// SwitchToNewBasicBlock - This method is used to jump to a new basic block. +// This function handles the actual updating of block and instruction iterators +// as well as execution of all of the PHI nodes in the destination block. +// +// This method does this because all of the PHI nodes must be executed +// atomically, reading their inputs before any of the results are updated. Not +// doing this can cause problems if the PHI nodes depend on other PHI nodes for +// their inputs. If the input PHI node is updated before it is read, incorrect +// results can happen. Thus we use a two phase approach. +// +void Interpreter::SwitchToNewBasicBlock(BasicBlock *Dest, ExecutionContext &SF){ + BasicBlock *PrevBB = SF.CurBB; // Remember where we came from... + SF.CurBB = Dest; // Update CurBB to branch destination + SF.CurInst = SF.CurBB->begin(); // Update new instruction ptr... + + if (!isa(SF.CurInst)) return; // Nothing fancy to do + + // Loop over all of the PHI nodes in the current block, reading their inputs. + std::vector ResultValues; + + for (; PHINode *PN = dyn_cast(SF.CurInst); ++SF.CurInst) { + // Search for the value corresponding to this previous bb... + int i = PN->getBasicBlockIndex(PrevBB); + assert(i != -1 && "PHINode doesn't contain entry for predecessor??"); + Value *IncomingValue = PN->getIncomingValue(i); + + // Save the incoming value for this PHI node... + ResultValues.push_back(getOperandValue(IncomingValue, SF)); + } + + // Now loop over all of the PHI nodes setting their values... + SF.CurInst = SF.CurBB->begin(); + for (unsigned i = 0; isa(SF.CurInst); ++SF.CurInst, ++i) { + PHINode *PN = cast(SF.CurInst); + SetValue(PN, ResultValues[i], SF); + } +} + +//===----------------------------------------------------------------------===// +// Memory Instruction Implementations +//===----------------------------------------------------------------------===// + +void Interpreter::visitAllocaInst(AllocaInst &I) { + ExecutionContext &SF = ECStack.back(); + + const Type *Ty = I.getType()->getElementType(); // Type to be allocated + + // Get the number of elements being allocated by the array... + unsigned NumElements = + getOperandValue(I.getOperand(0), SF).IntVal.getZExtValue(); + + unsigned TypeSize = (size_t)TD.getTypeAllocSize(Ty); + + // Avoid malloc-ing zero bytes, use max()... + unsigned MemToAlloc = std::max(1U, NumElements * TypeSize); + + // Allocate enough memory to hold the type... + void *Memory = malloc(MemToAlloc); + + DEBUG(errs() << "Allocated Type: " << *Ty << " (" << TypeSize << " bytes) x " + << NumElements << " (Total: " << MemToAlloc << ") at " + << uintptr_t(Memory) << '\n'); + + GenericValue Result = PTOGV(Memory); + assert(Result.PointerVal != 0 && "Null pointer returned by malloc!"); + SetValue(&I, Result, SF); + + if (I.getOpcode() == Instruction::Alloca) + ECStack.back().Allocas.add(Memory); +} + +// getElementOffset - The workhorse for getelementptr. +// +GenericValue Interpreter::executeGEPOperation(Value *Ptr, gep_type_iterator I, + gep_type_iterator E, + ExecutionContext &SF) { + assert(isa(Ptr->getType()) && + "Cannot getElementOffset of a nonpointer type!"); + + uint64_t Total = 0; + + for (; I != E; ++I) { + if (const StructType *STy = dyn_cast(*I)) { + const StructLayout *SLO = TD.getStructLayout(STy); + + const ConstantInt *CPU = cast(I.getOperand()); + unsigned Index = unsigned(CPU->getZExtValue()); + + Total += SLO->getElementOffset(Index); + } else { + const SequentialType *ST = cast(*I); + // Get the index number for the array... which must be long type... + GenericValue IdxGV = getOperandValue(I.getOperand(), SF); + + int64_t Idx; + unsigned BitWidth = + cast(I.getOperand()->getType())->getBitWidth(); + if (BitWidth == 32) + Idx = (int64_t)(int32_t)IdxGV.IntVal.getZExtValue(); + else { + assert(BitWidth == 64 && "Invalid index type for getelementptr"); + Idx = (int64_t)IdxGV.IntVal.getZExtValue(); + } + Total += TD.getTypeAllocSize(ST->getElementType())*Idx; + } + } + + GenericValue Result; + Result.PointerVal = ((char*)getOperandValue(Ptr, SF).PointerVal) + Total; + DEBUG(errs() << "GEP Index " << Total << " bytes.\n"); + return Result; +} + +void Interpreter::visitGetElementPtrInst(GetElementPtrInst &I) { + ExecutionContext &SF = ECStack.back(); + SetValue(&I, executeGEPOperation(I.getPointerOperand(), + gep_type_begin(I), gep_type_end(I), SF), SF); +} + +void Interpreter::visitLoadInst(LoadInst &I) { + ExecutionContext &SF = ECStack.back(); + GenericValue SRC = getOperandValue(I.getPointerOperand(), SF); + GenericValue *Ptr = (GenericValue*)GVTOP(SRC); + GenericValue Result; + LoadValueFromMemory(Result, Ptr, I.getType()); + SetValue(&I, Result, SF); + if (I.isVolatile() && PrintVolatile) + errs() << "Volatile load " << I; +} + +void Interpreter::visitStoreInst(StoreInst &I) { + ExecutionContext &SF = ECStack.back(); + GenericValue Val = getOperandValue(I.getOperand(0), SF); + GenericValue SRC = getOperandValue(I.getPointerOperand(), SF); + StoreValueToMemory(Val, (GenericValue *)GVTOP(SRC), + I.getOperand(0)->getType()); + if (I.isVolatile() && PrintVolatile) + errs() << "Volatile store: " << I; +} + +//===----------------------------------------------------------------------===// +// Miscellaneous Instruction Implementations +//===----------------------------------------------------------------------===// + +void Interpreter::visitCallSite(CallSite CS) { + ExecutionContext &SF = ECStack.back(); + + // Check to see if this is an intrinsic function call... + Function *F = CS.getCalledFunction(); + if (F && F->isDeclaration()) + switch (F->getIntrinsicID()) { + case Intrinsic::not_intrinsic: + break; + case Intrinsic::vastart: { // va_start + GenericValue ArgIndex; + ArgIndex.UIntPairVal.first = ECStack.size() - 1; + ArgIndex.UIntPairVal.second = 0; + SetValue(CS.getInstruction(), ArgIndex, SF); + return; + } + case Intrinsic::vaend: // va_end is a noop for the interpreter + return; + case Intrinsic::vacopy: // va_copy: dest = src + SetValue(CS.getInstruction(), getOperandValue(*CS.arg_begin(), SF), SF); + return; + default: + // If it is an unknown intrinsic function, use the intrinsic lowering + // class to transform it into hopefully tasty LLVM code. + // + BasicBlock::iterator me(CS.getInstruction()); + BasicBlock *Parent = CS.getInstruction()->getParent(); + bool atBegin(Parent->begin() == me); + if (!atBegin) + --me; + IL->LowerIntrinsicCall(cast(CS.getInstruction())); + + // Restore the CurInst pointer to the first instruction newly inserted, if + // any. + if (atBegin) { + SF.CurInst = Parent->begin(); + } else { + SF.CurInst = me; + ++SF.CurInst; + } + return; + } + + + SF.Caller = CS; + std::vector ArgVals; + const unsigned NumArgs = SF.Caller.arg_size(); + ArgVals.reserve(NumArgs); + uint16_t pNum = 1; + for (CallSite::arg_iterator i = SF.Caller.arg_begin(), + e = SF.Caller.arg_end(); i != e; ++i, ++pNum) { + Value *V = *i; + ArgVals.push_back(getOperandValue(V, SF)); + } + + // To handle indirect calls, we must get the pointer value from the argument + // and treat it as a function pointer. + GenericValue SRC = getOperandValue(SF.Caller.getCalledValue(), SF); + callFunction((Function*)GVTOP(SRC), ArgVals); +} + +void Interpreter::visitShl(BinaryOperator &I) { + ExecutionContext &SF = ECStack.back(); + GenericValue Src1 = getOperandValue(I.getOperand(0), SF); + GenericValue Src2 = getOperandValue(I.getOperand(1), SF); + GenericValue Dest; + if (Src2.IntVal.getZExtValue() < Src1.IntVal.getBitWidth()) + Dest.IntVal = Src1.IntVal.shl(Src2.IntVal.getZExtValue()); + else + Dest.IntVal = Src1.IntVal; + + SetValue(&I, Dest, SF); +} + +void Interpreter::visitLShr(BinaryOperator &I) { + ExecutionContext &SF = ECStack.back(); + GenericValue Src1 = getOperandValue(I.getOperand(0), SF); + GenericValue Src2 = getOperandValue(I.getOperand(1), SF); + GenericValue Dest; + if (Src2.IntVal.getZExtValue() < Src1.IntVal.getBitWidth()) + Dest.IntVal = Src1.IntVal.lshr(Src2.IntVal.getZExtValue()); + else + Dest.IntVal = Src1.IntVal; + + SetValue(&I, Dest, SF); +} + +void Interpreter::visitAShr(BinaryOperator &I) { + ExecutionContext &SF = ECStack.back(); + GenericValue Src1 = getOperandValue(I.getOperand(0), SF); + GenericValue Src2 = getOperandValue(I.getOperand(1), SF); + GenericValue Dest; + if (Src2.IntVal.getZExtValue() < Src1.IntVal.getBitWidth()) + Dest.IntVal = Src1.IntVal.ashr(Src2.IntVal.getZExtValue()); + else + Dest.IntVal = Src1.IntVal; + + SetValue(&I, Dest, SF); +} + +GenericValue Interpreter::executeTruncInst(Value *SrcVal, const Type *DstTy, + ExecutionContext &SF) { + GenericValue Dest, Src = getOperandValue(SrcVal, SF); + const IntegerType *DITy = cast(DstTy); + unsigned DBitWidth = DITy->getBitWidth(); + Dest.IntVal = Src.IntVal.trunc(DBitWidth); + return Dest; +} + +GenericValue Interpreter::executeSExtInst(Value *SrcVal, const Type *DstTy, + ExecutionContext &SF) { + GenericValue Dest, Src = getOperandValue(SrcVal, SF); + const IntegerType *DITy = cast(DstTy); + unsigned DBitWidth = DITy->getBitWidth(); + Dest.IntVal = Src.IntVal.sext(DBitWidth); + return Dest; +} + +GenericValue Interpreter::executeZExtInst(Value *SrcVal, const Type *DstTy, + ExecutionContext &SF) { + GenericValue Dest, Src = getOperandValue(SrcVal, SF); + const IntegerType *DITy = cast(DstTy); + unsigned DBitWidth = DITy->getBitWidth(); + Dest.IntVal = Src.IntVal.zext(DBitWidth); + return Dest; +} + +GenericValue Interpreter::executeFPTruncInst(Value *SrcVal, const Type *DstTy, + ExecutionContext &SF) { + GenericValue Dest, Src = getOperandValue(SrcVal, SF); + assert(SrcVal->getType()->isDoubleTy() && DstTy->isFloatTy() && + "Invalid FPTrunc instruction"); + Dest.FloatVal = (float) Src.DoubleVal; + return Dest; +} + +GenericValue Interpreter::executeFPExtInst(Value *SrcVal, const Type *DstTy, + ExecutionContext &SF) { + GenericValue Dest, Src = getOperandValue(SrcVal, SF); + assert(SrcVal->getType()->isFloatTy() && DstTy->isDoubleTy() && + "Invalid FPTrunc instruction"); + Dest.DoubleVal = (double) Src.FloatVal; + return Dest; +} + +GenericValue Interpreter::executeFPToUIInst(Value *SrcVal, const Type *DstTy, + ExecutionContext &SF) { + const Type *SrcTy = SrcVal->getType(); + uint32_t DBitWidth = cast(DstTy)->getBitWidth(); + GenericValue Dest, Src = getOperandValue(SrcVal, SF); + assert(SrcTy->isFloatingPoint() && "Invalid FPToUI instruction"); + + if (SrcTy->getTypeID() == Type::FloatTyID) + Dest.IntVal = APIntOps::RoundFloatToAPInt(Src.FloatVal, DBitWidth); + else + Dest.IntVal = APIntOps::RoundDoubleToAPInt(Src.DoubleVal, DBitWidth); + return Dest; +} + +GenericValue Interpreter::executeFPToSIInst(Value *SrcVal, const Type *DstTy, + ExecutionContext &SF) { + const Type *SrcTy = SrcVal->getType(); + uint32_t DBitWidth = cast(DstTy)->getBitWidth(); + GenericValue Dest, Src = getOperandValue(SrcVal, SF); + assert(SrcTy->isFloatingPoint() && "Invalid FPToSI instruction"); + + if (SrcTy->getTypeID() == Type::FloatTyID) + Dest.IntVal = APIntOps::RoundFloatToAPInt(Src.FloatVal, DBitWidth); + else + Dest.IntVal = APIntOps::RoundDoubleToAPInt(Src.DoubleVal, DBitWidth); + return Dest; +} + +GenericValue Interpreter::executeUIToFPInst(Value *SrcVal, const Type *DstTy, + ExecutionContext &SF) { + GenericValue Dest, Src = getOperandValue(SrcVal, SF); + assert(DstTy->isFloatingPoint() && "Invalid UIToFP instruction"); + + if (DstTy->getTypeID() == Type::FloatTyID) + Dest.FloatVal = APIntOps::RoundAPIntToFloat(Src.IntVal); + else + Dest.DoubleVal = APIntOps::RoundAPIntToDouble(Src.IntVal); + return Dest; +} + +GenericValue Interpreter::executeSIToFPInst(Value *SrcVal, const Type *DstTy, + ExecutionContext &SF) { + GenericValue Dest, Src = getOperandValue(SrcVal, SF); + assert(DstTy->isFloatingPoint() && "Invalid SIToFP instruction"); + + if (DstTy->getTypeID() == Type::FloatTyID) + Dest.FloatVal = APIntOps::RoundSignedAPIntToFloat(Src.IntVal); + else + Dest.DoubleVal = APIntOps::RoundSignedAPIntToDouble(Src.IntVal); + return Dest; + +} + +GenericValue Interpreter::executePtrToIntInst(Value *SrcVal, const Type *DstTy, + ExecutionContext &SF) { + uint32_t DBitWidth = cast(DstTy)->getBitWidth(); + GenericValue Dest, Src = getOperandValue(SrcVal, SF); + assert(isa(SrcVal->getType()) && "Invalid PtrToInt instruction"); + + Dest.IntVal = APInt(DBitWidth, (intptr_t) Src.PointerVal); + return Dest; +} + +GenericValue Interpreter::executeIntToPtrInst(Value *SrcVal, const Type *DstTy, + ExecutionContext &SF) { + GenericValue Dest, Src = getOperandValue(SrcVal, SF); + assert(isa(DstTy) && "Invalid PtrToInt instruction"); + + uint32_t PtrSize = TD.getPointerSizeInBits(); + if (PtrSize != Src.IntVal.getBitWidth()) + Src.IntVal = Src.IntVal.zextOrTrunc(PtrSize); + + Dest.PointerVal = PointerTy(intptr_t(Src.IntVal.getZExtValue())); + return Dest; +} + +GenericValue Interpreter::executeBitCastInst(Value *SrcVal, const Type *DstTy, + ExecutionContext &SF) { + + const Type *SrcTy = SrcVal->getType(); + GenericValue Dest, Src = getOperandValue(SrcVal, SF); + if (isa(DstTy)) { + assert(isa(SrcTy) && "Invalid BitCast"); + Dest.PointerVal = Src.PointerVal; + } else if (DstTy->isInteger()) { + if (SrcTy->isFloatTy()) { + Dest.IntVal.zext(sizeof(Src.FloatVal) * CHAR_BIT); + Dest.IntVal.floatToBits(Src.FloatVal); + } else if (SrcTy->isDoubleTy()) { + Dest.IntVal.zext(sizeof(Src.DoubleVal) * CHAR_BIT); + Dest.IntVal.doubleToBits(Src.DoubleVal); + } else if (SrcTy->isInteger()) { + Dest.IntVal = Src.IntVal; + } else + llvm_unreachable("Invalid BitCast"); + } else if (DstTy->isFloatTy()) { + if (SrcTy->isInteger()) + Dest.FloatVal = Src.IntVal.bitsToFloat(); + else + Dest.FloatVal = Src.FloatVal; + } else if (DstTy->isDoubleTy()) { + if (SrcTy->isInteger()) + Dest.DoubleVal = Src.IntVal.bitsToDouble(); + else + Dest.DoubleVal = Src.DoubleVal; + } else + llvm_unreachable("Invalid Bitcast"); + + return Dest; +} + +void Interpreter::visitTruncInst(TruncInst &I) { + ExecutionContext &SF = ECStack.back(); + SetValue(&I, executeTruncInst(I.getOperand(0), I.getType(), SF), SF); +} + +void Interpreter::visitSExtInst(SExtInst &I) { + ExecutionContext &SF = ECStack.back(); + SetValue(&I, executeSExtInst(I.getOperand(0), I.getType(), SF), SF); +} + +void Interpreter::visitZExtInst(ZExtInst &I) { + ExecutionContext &SF = ECStack.back(); + SetValue(&I, executeZExtInst(I.getOperand(0), I.getType(), SF), SF); +} + +void Interpreter::visitFPTruncInst(FPTruncInst &I) { + ExecutionContext &SF = ECStack.back(); + SetValue(&I, executeFPTruncInst(I.getOperand(0), I.getType(), SF), SF); +} + +void Interpreter::visitFPExtInst(FPExtInst &I) { + ExecutionContext &SF = ECStack.back(); + SetValue(&I, executeFPExtInst(I.getOperand(0), I.getType(), SF), SF); +} + +void Interpreter::visitUIToFPInst(UIToFPInst &I) { + ExecutionContext &SF = ECStack.back(); + SetValue(&I, executeUIToFPInst(I.getOperand(0), I.getType(), SF), SF); +} + +void Interpreter::visitSIToFPInst(SIToFPInst &I) { + ExecutionContext &SF = ECStack.back(); + SetValue(&I, executeSIToFPInst(I.getOperand(0), I.getType(), SF), SF); +} + +void Interpreter::visitFPToUIInst(FPToUIInst &I) { + ExecutionContext &SF = ECStack.back(); + SetValue(&I, executeFPToUIInst(I.getOperand(0), I.getType(), SF), SF); +} + +void Interpreter::visitFPToSIInst(FPToSIInst &I) { + ExecutionContext &SF = ECStack.back(); + SetValue(&I, executeFPToSIInst(I.getOperand(0), I.getType(), SF), SF); +} + +void Interpreter::visitPtrToIntInst(PtrToIntInst &I) { + ExecutionContext &SF = ECStack.back(); + SetValue(&I, executePtrToIntInst(I.getOperand(0), I.getType(), SF), SF); +} + +void Interpreter::visitIntToPtrInst(IntToPtrInst &I) { + ExecutionContext &SF = ECStack.back(); + SetValue(&I, executeIntToPtrInst(I.getOperand(0), I.getType(), SF), SF); +} + +void Interpreter::visitBitCastInst(BitCastInst &I) { + ExecutionContext &SF = ECStack.back(); + SetValue(&I, executeBitCastInst(I.getOperand(0), I.getType(), SF), SF); +} + +#define IMPLEMENT_VAARG(TY) \ + case Type::TY##TyID: Dest.TY##Val = Src.TY##Val; break + +void Interpreter::visitVAArgInst(VAArgInst &I) { + ExecutionContext &SF = ECStack.back(); + + // Get the incoming valist parameter. LLI treats the valist as a + // (ec-stack-depth var-arg-index) pair. + GenericValue VAList = getOperandValue(I.getOperand(0), SF); + GenericValue Dest; + GenericValue Src = ECStack[VAList.UIntPairVal.first] + .VarArgs[VAList.UIntPairVal.second]; + const Type *Ty = I.getType(); + switch (Ty->getTypeID()) { + case Type::IntegerTyID: Dest.IntVal = Src.IntVal; + IMPLEMENT_VAARG(Pointer); + IMPLEMENT_VAARG(Float); + IMPLEMENT_VAARG(Double); + default: + errs() << "Unhandled dest type for vaarg instruction: " << *Ty << "\n"; + llvm_unreachable(0); + } + + // Set the Value of this Instruction. + SetValue(&I, Dest, SF); + + // Move the pointer to the next vararg. + ++VAList.UIntPairVal.second; +} + +GenericValue Interpreter::getConstantExprValue (ConstantExpr *CE, + ExecutionContext &SF) { + switch (CE->getOpcode()) { + case Instruction::Trunc: + return executeTruncInst(CE->getOperand(0), CE->getType(), SF); + case Instruction::ZExt: + return executeZExtInst(CE->getOperand(0), CE->getType(), SF); + case Instruction::SExt: + return executeSExtInst(CE->getOperand(0), CE->getType(), SF); + case Instruction::FPTrunc: + return executeFPTruncInst(CE->getOperand(0), CE->getType(), SF); + case Instruction::FPExt: + return executeFPExtInst(CE->getOperand(0), CE->getType(), SF); + case Instruction::UIToFP: + return executeUIToFPInst(CE->getOperand(0), CE->getType(), SF); + case Instruction::SIToFP: + return executeSIToFPInst(CE->getOperand(0), CE->getType(), SF); + case Instruction::FPToUI: + return executeFPToUIInst(CE->getOperand(0), CE->getType(), SF); + case Instruction::FPToSI: + return executeFPToSIInst(CE->getOperand(0), CE->getType(), SF); + case Instruction::PtrToInt: + return executePtrToIntInst(CE->getOperand(0), CE->getType(), SF); + case Instruction::IntToPtr: + return executeIntToPtrInst(CE->getOperand(0), CE->getType(), SF); + case Instruction::BitCast: + return executeBitCastInst(CE->getOperand(0), CE->getType(), SF); + case Instruction::GetElementPtr: + return executeGEPOperation(CE->getOperand(0), gep_type_begin(CE), + gep_type_end(CE), SF); + case Instruction::FCmp: + case Instruction::ICmp: + return executeCmpInst(CE->getPredicate(), + getOperandValue(CE->getOperand(0), SF), + getOperandValue(CE->getOperand(1), SF), + CE->getOperand(0)->getType()); + case Instruction::Select: + return executeSelectInst(getOperandValue(CE->getOperand(0), SF), + getOperandValue(CE->getOperand(1), SF), + getOperandValue(CE->getOperand(2), SF)); + default : + break; + } + + // The cases below here require a GenericValue parameter for the result + // so we initialize one, compute it and then return it. + GenericValue Op0 = getOperandValue(CE->getOperand(0), SF); + GenericValue Op1 = getOperandValue(CE->getOperand(1), SF); + GenericValue Dest; + const Type * Ty = CE->getOperand(0)->getType(); + switch (CE->getOpcode()) { + case Instruction::Add: Dest.IntVal = Op0.IntVal + Op1.IntVal; break; + case Instruction::Sub: Dest.IntVal = Op0.IntVal - Op1.IntVal; break; + case Instruction::Mul: Dest.IntVal = Op0.IntVal * Op1.IntVal; break; + case Instruction::FAdd: executeFAddInst(Dest, Op0, Op1, Ty); break; + case Instruction::FSub: executeFSubInst(Dest, Op0, Op1, Ty); break; + case Instruction::FMul: executeFMulInst(Dest, Op0, Op1, Ty); break; + case Instruction::FDiv: executeFDivInst(Dest, Op0, Op1, Ty); break; + case Instruction::FRem: executeFRemInst(Dest, Op0, Op1, Ty); break; + case Instruction::SDiv: Dest.IntVal = Op0.IntVal.sdiv(Op1.IntVal); break; + case Instruction::UDiv: Dest.IntVal = Op0.IntVal.udiv(Op1.IntVal); break; + case Instruction::URem: Dest.IntVal = Op0.IntVal.urem(Op1.IntVal); break; + case Instruction::SRem: Dest.IntVal = Op0.IntVal.srem(Op1.IntVal); break; + case Instruction::And: Dest.IntVal = Op0.IntVal & Op1.IntVal; break; + case Instruction::Or: Dest.IntVal = Op0.IntVal | Op1.IntVal; break; + case Instruction::Xor: Dest.IntVal = Op0.IntVal ^ Op1.IntVal; break; + case Instruction::Shl: + Dest.IntVal = Op0.IntVal.shl(Op1.IntVal.getZExtValue()); + break; + case Instruction::LShr: + Dest.IntVal = Op0.IntVal.lshr(Op1.IntVal.getZExtValue()); + break; + case Instruction::AShr: + Dest.IntVal = Op0.IntVal.ashr(Op1.IntVal.getZExtValue()); + break; + default: + errs() << "Unhandled ConstantExpr: " << *CE << "\n"; + llvm_unreachable(0); + return GenericValue(); + } + return Dest; +} + +GenericValue Interpreter::getOperandValue(Value *V, ExecutionContext &SF) { + if (ConstantExpr *CE = dyn_cast(V)) { + return getConstantExprValue(CE, SF); + } else if (Constant *CPV = dyn_cast(V)) { + return getConstantValue(CPV); + } else if (GlobalValue *GV = dyn_cast(V)) { + return PTOGV(getPointerToGlobal(GV)); + } else { + return SF.Values[V]; + } +} + +//===----------------------------------------------------------------------===// +// Dispatch and Execution Code +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// callFunction - Execute the specified function... +// +void Interpreter::callFunction(Function *F, + const std::vector &ArgVals) { + assert((ECStack.empty() || ECStack.back().Caller.getInstruction() == 0 || + ECStack.back().Caller.arg_size() == ArgVals.size()) && + "Incorrect number of arguments passed into function call!"); + // Make a new stack frame... and fill it in. + ECStack.push_back(ExecutionContext()); + ExecutionContext &StackFrame = ECStack.back(); + StackFrame.CurFunction = F; + + // Special handling for external functions. + if (F->isDeclaration()) { + GenericValue Result = callExternalFunction (F, ArgVals); + // Simulate a 'ret' instruction of the appropriate type. + popStackAndReturnValueToCaller (F->getReturnType (), Result); + return; + } + + // Get pointers to first LLVM BB & Instruction in function. + StackFrame.CurBB = F->begin(); + StackFrame.CurInst = StackFrame.CurBB->begin(); + + // Run through the function arguments and initialize their values... + assert((ArgVals.size() == F->arg_size() || + (ArgVals.size() > F->arg_size() && F->getFunctionType()->isVarArg()))&& + "Invalid number of values passed to function invocation!"); + + // Handle non-varargs arguments... + unsigned i = 0; + for (Function::arg_iterator AI = F->arg_begin(), E = F->arg_end(); + AI != E; ++AI, ++i) + SetValue(AI, ArgVals[i], StackFrame); + + // Handle varargs arguments... + StackFrame.VarArgs.assign(ArgVals.begin()+i, ArgVals.end()); +} + + +void Interpreter::run() { + while (!ECStack.empty()) { + // Interpret a single instruction & increment the "PC". + ExecutionContext &SF = ECStack.back(); // Current stack frame + Instruction &I = *SF.CurInst++; // Increment before execute + + // Track the number of dynamic instructions executed. + ++NumDynamicInsts; + + DEBUG(errs() << "About to interpret: " << I); + visit(I); // Dispatch to one of the visit* methods... +#if 0 + // This is not safe, as visiting the instruction could lower it and free I. +DEBUG( + if (!isa(I) && !isa(I) && + I.getType() != Type::VoidTy) { + errs() << " --> "; + const GenericValue &Val = SF.Values[&I]; + switch (I.getType()->getTypeID()) { + default: llvm_unreachable("Invalid GenericValue Type"); + case Type::VoidTyID: errs() << "void"; break; + case Type::FloatTyID: errs() << "float " << Val.FloatVal; break; + case Type::DoubleTyID: errs() << "double " << Val.DoubleVal; break; + case Type::PointerTyID: errs() << "void* " << intptr_t(Val.PointerVal); + break; + case Type::IntegerTyID: + errs() << "i" << Val.IntVal.getBitWidth() << " " + << Val.IntVal.toStringUnsigned(10) + << " (0x" << Val.IntVal.toStringUnsigned(16) << ")\n"; + break; + } + }); +#endif + } +} diff --git a/libclamav/c++/llvm/lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp b/libclamav/c++/llvm/lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp new file mode 100644 index 000000000..c02d84f1a --- /dev/null +++ b/libclamav/c++/llvm/lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp @@ -0,0 +1,489 @@ +//===-- ExternalFunctions.cpp - Implement External Functions --------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains both code to deal with invoking "external" functions, but +// also contains code that implements "exported" external functions. +// +// There are currently two mechanisms for handling external functions in the +// Interpreter. The first is to implement lle_* wrapper functions that are +// specific to well-known library functions which manually translate the +// arguments from GenericValues and make the call. If such a wrapper does +// not exist, and libffi is available, then the Interpreter will attempt to +// invoke the function using libffi, after finding its address. +// +//===----------------------------------------------------------------------===// + +#include "Interpreter.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Module.h" +#include "llvm/Config/config.h" // Detect libffi +#include "llvm/Support/ErrorHandling.h" +#include "llvm/System/DynamicLibrary.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Support/ManagedStatic.h" +#include "llvm/System/Mutex.h" +#include +#include +#include +#include +#include + +#ifdef HAVE_FFI_CALL +#ifdef HAVE_FFI_H +#include +#define USE_LIBFFI +#elif HAVE_FFI_FFI_H +#include +#define USE_LIBFFI +#endif +#endif + +using namespace llvm; + +static ManagedStatic FunctionsLock; + +typedef GenericValue (*ExFunc)(const FunctionType *, + const std::vector &); +static ManagedStatic > ExportedFunctions; +static std::map FuncNames; + +#ifdef USE_LIBFFI +typedef void (*RawFunc)(); +static ManagedStatic > RawFunctions; +#endif + +static Interpreter *TheInterpreter; + +static char getTypeID(const Type *Ty) { + switch (Ty->getTypeID()) { + case Type::VoidTyID: return 'V'; + case Type::IntegerTyID: + switch (cast(Ty)->getBitWidth()) { + case 1: return 'o'; + case 8: return 'B'; + case 16: return 'S'; + case 32: return 'I'; + case 64: return 'L'; + default: return 'N'; + } + case Type::FloatTyID: return 'F'; + case Type::DoubleTyID: return 'D'; + case Type::PointerTyID: return 'P'; + case Type::FunctionTyID:return 'M'; + case Type::StructTyID: return 'T'; + case Type::ArrayTyID: return 'A'; + case Type::OpaqueTyID: return 'O'; + default: return 'U'; + } +} + +// Try to find address of external function given a Function object. +// Please note, that interpreter doesn't know how to assemble a +// real call in general case (this is JIT job), that's why it assumes, +// that all external functions has the same (and pretty "general") signature. +// The typical example of such functions are "lle_X_" ones. +static ExFunc lookupFunction(const Function *F) { + // Function not found, look it up... start by figuring out what the + // composite function name should be. + std::string ExtName = "lle_"; + const FunctionType *FT = F->getFunctionType(); + for (unsigned i = 0, e = FT->getNumContainedTypes(); i != e; ++i) + ExtName += getTypeID(FT->getContainedType(i)); + ExtName + "_" + F->getNameStr(); + + sys::ScopedLock Writer(*FunctionsLock); + ExFunc FnPtr = FuncNames[ExtName]; + if (FnPtr == 0) + FnPtr = FuncNames["lle_X_" + F->getNameStr()]; + if (FnPtr == 0) // Try calling a generic function... if it exists... + FnPtr = (ExFunc)(intptr_t) + sys::DynamicLibrary::SearchForAddressOfSymbol("lle_X_"+F->getNameStr()); + if (FnPtr != 0) + ExportedFunctions->insert(std::make_pair(F, FnPtr)); // Cache for later + return FnPtr; +} + +#ifdef USE_LIBFFI +static ffi_type *ffiTypeFor(const Type *Ty) { + switch (Ty->getTypeID()) { + case Type::VoidTyID: return &ffi_type_void; + case Type::IntegerTyID: + switch (cast(Ty)->getBitWidth()) { + case 8: return &ffi_type_sint8; + case 16: return &ffi_type_sint16; + case 32: return &ffi_type_sint32; + case 64: return &ffi_type_sint64; + } + case Type::FloatTyID: return &ffi_type_float; + case Type::DoubleTyID: return &ffi_type_double; + case Type::PointerTyID: return &ffi_type_pointer; + default: break; + } + // TODO: Support other types such as StructTyID, ArrayTyID, OpaqueTyID, etc. + llvm_report_error("Type could not be mapped for use with libffi."); + return NULL; +} + +static void *ffiValueFor(const Type *Ty, const GenericValue &AV, + void *ArgDataPtr) { + switch (Ty->getTypeID()) { + case Type::IntegerTyID: + switch (cast(Ty)->getBitWidth()) { + case 8: { + int8_t *I8Ptr = (int8_t *) ArgDataPtr; + *I8Ptr = (int8_t) AV.IntVal.getZExtValue(); + return ArgDataPtr; + } + case 16: { + int16_t *I16Ptr = (int16_t *) ArgDataPtr; + *I16Ptr = (int16_t) AV.IntVal.getZExtValue(); + return ArgDataPtr; + } + case 32: { + int32_t *I32Ptr = (int32_t *) ArgDataPtr; + *I32Ptr = (int32_t) AV.IntVal.getZExtValue(); + return ArgDataPtr; + } + case 64: { + int64_t *I64Ptr = (int64_t *) ArgDataPtr; + *I64Ptr = (int64_t) AV.IntVal.getZExtValue(); + return ArgDataPtr; + } + } + case Type::FloatTyID: { + float *FloatPtr = (float *) ArgDataPtr; + *FloatPtr = AV.FloatVal; + return ArgDataPtr; + } + case Type::DoubleTyID: { + double *DoublePtr = (double *) ArgDataPtr; + *DoublePtr = AV.DoubleVal; + return ArgDataPtr; + } + case Type::PointerTyID: { + void **PtrPtr = (void **) ArgDataPtr; + *PtrPtr = GVTOP(AV); + return ArgDataPtr; + } + default: break; + } + // TODO: Support other types such as StructTyID, ArrayTyID, OpaqueTyID, etc. + llvm_report_error("Type value could not be mapped for use with libffi."); + return NULL; +} + +static bool ffiInvoke(RawFunc Fn, Function *F, + const std::vector &ArgVals, + const TargetData *TD, GenericValue &Result) { + ffi_cif cif; + const FunctionType *FTy = F->getFunctionType(); + const unsigned NumArgs = F->arg_size(); + + // TODO: We don't have type information about the remaining arguments, because + // this information is never passed into ExecutionEngine::runFunction(). + if (ArgVals.size() > NumArgs && F->isVarArg()) { + llvm_report_error("Calling external var arg function '" + F->getName() + + "' is not supported by the Interpreter."); + } + + unsigned ArgBytes = 0; + + std::vector args(NumArgs); + for (Function::const_arg_iterator A = F->arg_begin(), E = F->arg_end(); + A != E; ++A) { + const unsigned ArgNo = A->getArgNo(); + const Type *ArgTy = FTy->getParamType(ArgNo); + args[ArgNo] = ffiTypeFor(ArgTy); + ArgBytes += TD->getTypeStoreSize(ArgTy); + } + + SmallVector ArgData; + ArgData.resize(ArgBytes); + uint8_t *ArgDataPtr = ArgData.data(); + SmallVector values(NumArgs); + for (Function::const_arg_iterator A = F->arg_begin(), E = F->arg_end(); + A != E; ++A) { + const unsigned ArgNo = A->getArgNo(); + const Type *ArgTy = FTy->getParamType(ArgNo); + values[ArgNo] = ffiValueFor(ArgTy, ArgVals[ArgNo], ArgDataPtr); + ArgDataPtr += TD->getTypeStoreSize(ArgTy); + } + + const Type *RetTy = FTy->getReturnType(); + ffi_type *rtype = ffiTypeFor(RetTy); + + if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, NumArgs, rtype, &args[0]) == FFI_OK) { + SmallVector ret; + if (RetTy->getTypeID() != Type::VoidTyID) + ret.resize(TD->getTypeStoreSize(RetTy)); + ffi_call(&cif, Fn, ret.data(), values.data()); + switch (RetTy->getTypeID()) { + case Type::IntegerTyID: + switch (cast(RetTy)->getBitWidth()) { + case 8: Result.IntVal = APInt(8 , *(int8_t *) ret.data()); break; + case 16: Result.IntVal = APInt(16, *(int16_t*) ret.data()); break; + case 32: Result.IntVal = APInt(32, *(int32_t*) ret.data()); break; + case 64: Result.IntVal = APInt(64, *(int64_t*) ret.data()); break; + } + break; + case Type::FloatTyID: Result.FloatVal = *(float *) ret.data(); break; + case Type::DoubleTyID: Result.DoubleVal = *(double*) ret.data(); break; + case Type::PointerTyID: Result.PointerVal = *(void **) ret.data(); break; + default: break; + } + return true; + } + + return false; +} +#endif // USE_LIBFFI + +GenericValue Interpreter::callExternalFunction(Function *F, + const std::vector &ArgVals) { + TheInterpreter = this; + + FunctionsLock->acquire(); + + // Do a lookup to see if the function is in our cache... this should just be a + // deferred annotation! + std::map::iterator FI = ExportedFunctions->find(F); + if (ExFunc Fn = (FI == ExportedFunctions->end()) ? lookupFunction(F) + : FI->second) { + FunctionsLock->release(); + return Fn(F->getFunctionType(), ArgVals); + } + +#ifdef USE_LIBFFI + std::map::iterator RF = RawFunctions->find(F); + RawFunc RawFn; + if (RF == RawFunctions->end()) { + RawFn = (RawFunc)(intptr_t) + sys::DynamicLibrary::SearchForAddressOfSymbol(F->getName()); + if (RawFn != 0) + RawFunctions->insert(std::make_pair(F, RawFn)); // Cache for later + } else { + RawFn = RF->second; + } + + FunctionsLock->release(); + + GenericValue Result; + if (RawFn != 0 && ffiInvoke(RawFn, F, ArgVals, getTargetData(), Result)) + return Result; +#endif // USE_LIBFFI + + if (F->getName() == "__main") + errs() << "Tried to execute an unknown external function: " + << F->getType()->getDescription() << " __main\n"; + else + llvm_report_error("Tried to execute an unknown external function: " + + F->getType()->getDescription() + " " +F->getName()); +#ifndef USE_LIBFFI + errs() << "Recompiling LLVM with --enable-libffi might help.\n"; +#endif + return GenericValue(); +} + + +//===----------------------------------------------------------------------===// +// Functions "exported" to the running application... +// + +// Visual Studio warns about returning GenericValue in extern "C" linkage +#ifdef _MSC_VER + #pragma warning(disable : 4190) +#endif + +extern "C" { // Don't add C++ manglings to llvm mangling :) + +// void atexit(Function*) +GenericValue lle_X_atexit(const FunctionType *FT, + const std::vector &Args) { + assert(Args.size() == 1); + TheInterpreter->addAtExitHandler((Function*)GVTOP(Args[0])); + GenericValue GV; + GV.IntVal = 0; + return GV; +} + +// void exit(int) +GenericValue lle_X_exit(const FunctionType *FT, + const std::vector &Args) { + TheInterpreter->exitCalled(Args[0]); + return GenericValue(); +} + +// void abort(void) +GenericValue lle_X_abort(const FunctionType *FT, + const std::vector &Args) { + //FIXME: should we report or raise here? + //llvm_report_error("Interpreted program raised SIGABRT"); + raise (SIGABRT); + return GenericValue(); +} + +// int sprintf(char *, const char *, ...) - a very rough implementation to make +// output useful. +GenericValue lle_X_sprintf(const FunctionType *FT, + const std::vector &Args) { + char *OutputBuffer = (char *)GVTOP(Args[0]); + const char *FmtStr = (const char *)GVTOP(Args[1]); + unsigned ArgNo = 2; + + // printf should return # chars printed. This is completely incorrect, but + // close enough for now. + GenericValue GV; + GV.IntVal = APInt(32, strlen(FmtStr)); + while (1) { + switch (*FmtStr) { + case 0: return GV; // Null terminator... + default: // Normal nonspecial character + sprintf(OutputBuffer++, "%c", *FmtStr++); + break; + case '\\': { // Handle escape codes + sprintf(OutputBuffer, "%c%c", *FmtStr, *(FmtStr+1)); + FmtStr += 2; OutputBuffer += 2; + break; + } + case '%': { // Handle format specifiers + char FmtBuf[100] = "", Buffer[1000] = ""; + char *FB = FmtBuf; + *FB++ = *FmtStr++; + char Last = *FB++ = *FmtStr++; + unsigned HowLong = 0; + while (Last != 'c' && Last != 'd' && Last != 'i' && Last != 'u' && + Last != 'o' && Last != 'x' && Last != 'X' && Last != 'e' && + Last != 'E' && Last != 'g' && Last != 'G' && Last != 'f' && + Last != 'p' && Last != 's' && Last != '%') { + if (Last == 'l' || Last == 'L') HowLong++; // Keep track of l's + Last = *FB++ = *FmtStr++; + } + *FB = 0; + + switch (Last) { + case '%': + strcpy(Buffer, "%"); break; + case 'c': + sprintf(Buffer, FmtBuf, uint32_t(Args[ArgNo++].IntVal.getZExtValue())); + break; + case 'd': case 'i': + case 'u': case 'o': + case 'x': case 'X': + if (HowLong >= 1) { + if (HowLong == 1 && + TheInterpreter->getTargetData()->getPointerSizeInBits() == 64 && + sizeof(long) < sizeof(int64_t)) { + // Make sure we use %lld with a 64 bit argument because we might be + // compiling LLI on a 32 bit compiler. + unsigned Size = strlen(FmtBuf); + FmtBuf[Size] = FmtBuf[Size-1]; + FmtBuf[Size+1] = 0; + FmtBuf[Size-1] = 'l'; + } + sprintf(Buffer, FmtBuf, Args[ArgNo++].IntVal.getZExtValue()); + } else + sprintf(Buffer, FmtBuf,uint32_t(Args[ArgNo++].IntVal.getZExtValue())); + break; + case 'e': case 'E': case 'g': case 'G': case 'f': + sprintf(Buffer, FmtBuf, Args[ArgNo++].DoubleVal); break; + case 'p': + sprintf(Buffer, FmtBuf, (void*)GVTOP(Args[ArgNo++])); break; + case 's': + sprintf(Buffer, FmtBuf, (char*)GVTOP(Args[ArgNo++])); break; + default: + errs() << ""; + ArgNo++; break; + } + strcpy(OutputBuffer, Buffer); + OutputBuffer += strlen(Buffer); + } + break; + } + } + return GV; +} + +// int printf(const char *, ...) - a very rough implementation to make output +// useful. +GenericValue lle_X_printf(const FunctionType *FT, + const std::vector &Args) { + char Buffer[10000]; + std::vector NewArgs; + NewArgs.push_back(PTOGV((void*)&Buffer[0])); + NewArgs.insert(NewArgs.end(), Args.begin(), Args.end()); + GenericValue GV = lle_X_sprintf(FT, NewArgs); + outs() << Buffer; + return GV; +} + +// int sscanf(const char *format, ...); +GenericValue lle_X_sscanf(const FunctionType *FT, + const std::vector &args) { + assert(args.size() < 10 && "Only handle up to 10 args to sscanf right now!"); + + char *Args[10]; + for (unsigned i = 0; i < args.size(); ++i) + Args[i] = (char*)GVTOP(args[i]); + + GenericValue GV; + GV.IntVal = APInt(32, sscanf(Args[0], Args[1], Args[2], Args[3], Args[4], + Args[5], Args[6], Args[7], Args[8], Args[9])); + return GV; +} + +// int scanf(const char *format, ...); +GenericValue lle_X_scanf(const FunctionType *FT, + const std::vector &args) { + assert(args.size() < 10 && "Only handle up to 10 args to scanf right now!"); + + char *Args[10]; + for (unsigned i = 0; i < args.size(); ++i) + Args[i] = (char*)GVTOP(args[i]); + + GenericValue GV; + GV.IntVal = APInt(32, scanf( Args[0], Args[1], Args[2], Args[3], Args[4], + Args[5], Args[6], Args[7], Args[8], Args[9])); + return GV; +} + +// int fprintf(FILE *, const char *, ...) - a very rough implementation to make +// output useful. +GenericValue lle_X_fprintf(const FunctionType *FT, + const std::vector &Args) { + assert(Args.size() >= 2); + char Buffer[10000]; + std::vector NewArgs; + NewArgs.push_back(PTOGV(Buffer)); + NewArgs.insert(NewArgs.end(), Args.begin()+1, Args.end()); + GenericValue GV = lle_X_sprintf(FT, NewArgs); + + fputs(Buffer, (FILE *) GVTOP(Args[0])); + return GV; +} + +} // End extern "C" + +// Done with externals; turn the warning back on +#ifdef _MSC_VER + #pragma warning(default: 4190) +#endif + + +void Interpreter::initializeExternalFunctions() { + sys::ScopedLock Writer(*FunctionsLock); + FuncNames["lle_X_atexit"] = lle_X_atexit; + FuncNames["lle_X_exit"] = lle_X_exit; + FuncNames["lle_X_abort"] = lle_X_abort; + + FuncNames["lle_X_printf"] = lle_X_printf; + FuncNames["lle_X_sprintf"] = lle_X_sprintf; + FuncNames["lle_X_sscanf"] = lle_X_sscanf; + FuncNames["lle_X_scanf"] = lle_X_scanf; + FuncNames["lle_X_fprintf"] = lle_X_fprintf; +} diff --git a/libclamav/c++/llvm/lib/ExecutionEngine/Interpreter/Interpreter.cpp b/libclamav/c++/llvm/lib/ExecutionEngine/Interpreter/Interpreter.cpp new file mode 100644 index 000000000..9be6a9265 --- /dev/null +++ b/libclamav/c++/llvm/lib/ExecutionEngine/Interpreter/Interpreter.cpp @@ -0,0 +1,99 @@ +//===- Interpreter.cpp - Top-Level LLVM Interpreter Implementation --------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the top-level functionality for the LLVM interpreter. +// This interpreter is designed to be a very simple, portable, inefficient +// interpreter. +// +//===----------------------------------------------------------------------===// + +#include "Interpreter.h" +#include "llvm/CodeGen/IntrinsicLowering.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Module.h" +#include "llvm/ModuleProvider.h" +#include +using namespace llvm; + +namespace { + +static struct RegisterInterp { + RegisterInterp() { Interpreter::Register(); } +} InterpRegistrator; + +} + +extern "C" void LLVMLinkInInterpreter() { } + +/// create - Create a new interpreter object. This can never fail. +/// +ExecutionEngine *Interpreter::create(ModuleProvider *MP, std::string* ErrStr) { + // Tell this ModuleProvide to materialize and release the module + if (!MP->materializeModule(ErrStr)) + // We got an error, just return 0 + return 0; + + return new Interpreter(MP); +} + +//===----------------------------------------------------------------------===// +// Interpreter ctor - Initialize stuff +// +Interpreter::Interpreter(ModuleProvider *M) + : ExecutionEngine(M), TD(M->getModule()) { + + memset(&ExitValue.Untyped, 0, sizeof(ExitValue.Untyped)); + setTargetData(&TD); + // Initialize the "backend" + initializeExecutionEngine(); + initializeExternalFunctions(); + emitGlobals(); + + IL = new IntrinsicLowering(TD); +} + +Interpreter::~Interpreter() { + delete IL; +} + +void Interpreter::runAtExitHandlers () { + while (!AtExitHandlers.empty()) { + callFunction(AtExitHandlers.back(), std::vector()); + AtExitHandlers.pop_back(); + run(); + } +} + +/// run - Start execution with the specified function and arguments. +/// +GenericValue +Interpreter::runFunction(Function *F, + const std::vector &ArgValues) { + assert (F && "Function *F was null at entry to run()"); + + // Try extra hard not to pass extra args to a function that isn't + // expecting them. C programmers frequently bend the rules and + // declare main() with fewer parameters than it actually gets + // passed, and the interpreter barfs if you pass a function more + // parameters than it is declared to take. This does not attempt to + // take into account gratuitous differences in declared types, + // though. + std::vector ActualArgs; + const unsigned ArgCount = F->getFunctionType()->getNumParams(); + for (unsigned i = 0; i < ArgCount; ++i) + ActualArgs.push_back(ArgValues[i]); + + // Set up the function call. + callFunction(F, ActualArgs); + + // Start executing the function. + run(); + + return ExitValue; +} diff --git a/libclamav/c++/llvm/lib/ExecutionEngine/Interpreter/Interpreter.h b/libclamav/c++/llvm/lib/ExecutionEngine/Interpreter/Interpreter.h new file mode 100644 index 000000000..038830cc0 --- /dev/null +++ b/libclamav/c++/llvm/lib/ExecutionEngine/Interpreter/Interpreter.h @@ -0,0 +1,244 @@ +//===-- Interpreter.h ------------------------------------------*- C++ -*--===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This header file defines the interpreter structure +// +//===----------------------------------------------------------------------===// + +#ifndef LLI_INTERPRETER_H +#define LLI_INTERPRETER_H + +#include "llvm/Function.h" +#include "llvm/ExecutionEngine/ExecutionEngine.h" +#include "llvm/ExecutionEngine/GenericValue.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Support/CallSite.h" +#include "llvm/System/DataTypes.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/InstVisitor.h" +#include "llvm/Support/raw_ostream.h" +namespace llvm { + +class IntrinsicLowering; +struct FunctionInfo; +template class generic_gep_type_iterator; +class ConstantExpr; +typedef generic_gep_type_iterator gep_type_iterator; + + +// AllocaHolder - Object to track all of the blocks of memory allocated by +// alloca. When the function returns, this object is popped off the execution +// stack, which causes the dtor to be run, which frees all the alloca'd memory. +// +class AllocaHolder { + friend class AllocaHolderHandle; + std::vector Allocations; + unsigned RefCnt; +public: + AllocaHolder() : RefCnt(0) {} + void add(void *mem) { Allocations.push_back(mem); } + ~AllocaHolder() { + for (unsigned i = 0; i < Allocations.size(); ++i) + free(Allocations[i]); + } +}; + +// AllocaHolderHandle gives AllocaHolder value semantics so we can stick it into +// a vector... +// +class AllocaHolderHandle { + AllocaHolder *H; +public: + AllocaHolderHandle() : H(new AllocaHolder()) { H->RefCnt++; } + AllocaHolderHandle(const AllocaHolderHandle &AH) : H(AH.H) { H->RefCnt++; } + ~AllocaHolderHandle() { if (--H->RefCnt == 0) delete H; } + + void add(void *mem) { H->add(mem); } +}; + +typedef std::vector ValuePlaneTy; + +// ExecutionContext struct - This struct represents one stack frame currently +// executing. +// +struct ExecutionContext { + Function *CurFunction;// The currently executing function + BasicBlock *CurBB; // The currently executing BB + BasicBlock::iterator CurInst; // The next instruction to execute + std::map Values; // LLVM values used in this invocation + std::vector VarArgs; // Values passed through an ellipsis + CallSite Caller; // Holds the call that called subframes. + // NULL if main func or debugger invoked fn + AllocaHolderHandle Allocas; // Track memory allocated by alloca +}; + +// Interpreter - This class represents the entirety of the interpreter. +// +class Interpreter : public ExecutionEngine, public InstVisitor { + GenericValue ExitValue; // The return value of the called function + TargetData TD; + IntrinsicLowering *IL; + + // The runtime stack of executing code. The top of the stack is the current + // function record. + std::vector ECStack; + + // AtExitHandlers - List of functions to call when the program exits, + // registered with the atexit() library function. + std::vector AtExitHandlers; + +public: + explicit Interpreter(ModuleProvider *M); + ~Interpreter(); + + /// runAtExitHandlers - Run any functions registered by the program's calls to + /// atexit(3), which we intercept and store in AtExitHandlers. + /// + void runAtExitHandlers(); + + static void Register() { + InterpCtor = create; + } + + /// create - Create an interpreter ExecutionEngine. This can never fail. + /// + static ExecutionEngine *create(ModuleProvider *M, std::string *ErrorStr = 0); + + /// run - Start execution with the specified function and arguments. + /// + virtual GenericValue runFunction(Function *F, + const std::vector &ArgValues); + + /// recompileAndRelinkFunction - For the interpreter, functions are always + /// up-to-date. + /// + virtual void *recompileAndRelinkFunction(Function *F) { + return getPointerToFunction(F); + } + + /// freeMachineCodeForFunction - The interpreter does not generate any code. + /// + void freeMachineCodeForFunction(Function *F) { } + + // Methods used to execute code: + // Place a call on the stack + void callFunction(Function *F, const std::vector &ArgVals); + void run(); // Execute instructions until nothing left to do + + // Opcode Implementations + void visitReturnInst(ReturnInst &I); + void visitBranchInst(BranchInst &I); + void visitSwitchInst(SwitchInst &I); + void visitIndirectBrInst(IndirectBrInst &I); + + void visitBinaryOperator(BinaryOperator &I); + void visitICmpInst(ICmpInst &I); + void visitFCmpInst(FCmpInst &I); + void visitAllocaInst(AllocaInst &I); + void visitLoadInst(LoadInst &I); + void visitStoreInst(StoreInst &I); + void visitGetElementPtrInst(GetElementPtrInst &I); + void visitPHINode(PHINode &PN) { + llvm_unreachable("PHI nodes already handled!"); + } + void visitTruncInst(TruncInst &I); + void visitZExtInst(ZExtInst &I); + void visitSExtInst(SExtInst &I); + void visitFPTruncInst(FPTruncInst &I); + void visitFPExtInst(FPExtInst &I); + void visitUIToFPInst(UIToFPInst &I); + void visitSIToFPInst(SIToFPInst &I); + void visitFPToUIInst(FPToUIInst &I); + void visitFPToSIInst(FPToSIInst &I); + void visitPtrToIntInst(PtrToIntInst &I); + void visitIntToPtrInst(IntToPtrInst &I); + void visitBitCastInst(BitCastInst &I); + void visitSelectInst(SelectInst &I); + + + void visitCallSite(CallSite CS); + void visitCallInst(CallInst &I) { visitCallSite (CallSite (&I)); } + void visitInvokeInst(InvokeInst &I) { visitCallSite (CallSite (&I)); } + void visitUnwindInst(UnwindInst &I); + void visitUnreachableInst(UnreachableInst &I); + + void visitShl(BinaryOperator &I); + void visitLShr(BinaryOperator &I); + void visitAShr(BinaryOperator &I); + + void visitVAArgInst(VAArgInst &I); + void visitInstruction(Instruction &I) { + errs() << I; + llvm_unreachable("Instruction not interpretable yet!"); + } + + GenericValue callExternalFunction(Function *F, + const std::vector &ArgVals); + void exitCalled(GenericValue GV); + + void addAtExitHandler(Function *F) { + AtExitHandlers.push_back(F); + } + + GenericValue *getFirstVarArg () { + return &(ECStack.back ().VarArgs[0]); + } + + //FIXME: private: +public: + GenericValue executeGEPOperation(Value *Ptr, gep_type_iterator I, + gep_type_iterator E, ExecutionContext &SF); + +private: // Helper functions + // SwitchToNewBasicBlock - Start execution in a new basic block and run any + // PHI nodes in the top of the block. This is used for intraprocedural + // control flow. + // + void SwitchToNewBasicBlock(BasicBlock *Dest, ExecutionContext &SF); + + void *getPointerToFunction(Function *F) { return (void*)F; } + void *getPointerToBasicBlock(BasicBlock *BB) { return (void*)BB; } + + void initializeExecutionEngine() { } + void initializeExternalFunctions(); + GenericValue getConstantExprValue(ConstantExpr *CE, ExecutionContext &SF); + GenericValue getOperandValue(Value *V, ExecutionContext &SF); + GenericValue executeTruncInst(Value *SrcVal, const Type *DstTy, + ExecutionContext &SF); + GenericValue executeSExtInst(Value *SrcVal, const Type *DstTy, + ExecutionContext &SF); + GenericValue executeZExtInst(Value *SrcVal, const Type *DstTy, + ExecutionContext &SF); + GenericValue executeFPTruncInst(Value *SrcVal, const Type *DstTy, + ExecutionContext &SF); + GenericValue executeFPExtInst(Value *SrcVal, const Type *DstTy, + ExecutionContext &SF); + GenericValue executeFPToUIInst(Value *SrcVal, const Type *DstTy, + ExecutionContext &SF); + GenericValue executeFPToSIInst(Value *SrcVal, const Type *DstTy, + ExecutionContext &SF); + GenericValue executeUIToFPInst(Value *SrcVal, const Type *DstTy, + ExecutionContext &SF); + GenericValue executeSIToFPInst(Value *SrcVal, const Type *DstTy, + ExecutionContext &SF); + GenericValue executePtrToIntInst(Value *SrcVal, const Type *DstTy, + ExecutionContext &SF); + GenericValue executeIntToPtrInst(Value *SrcVal, const Type *DstTy, + ExecutionContext &SF); + GenericValue executeBitCastInst(Value *SrcVal, const Type *DstTy, + ExecutionContext &SF); + GenericValue executeCastOperation(Instruction::CastOps opcode, Value *SrcVal, + const Type *Ty, ExecutionContext &SF); + void popStackAndReturnValueToCaller(const Type *RetTy, GenericValue Result); + +}; + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/lib/ExecutionEngine/Interpreter/Makefile b/libclamav/c++/llvm/lib/ExecutionEngine/Interpreter/Makefile new file mode 100644 index 000000000..5f937c3ad --- /dev/null +++ b/libclamav/c++/llvm/lib/ExecutionEngine/Interpreter/Makefile @@ -0,0 +1,12 @@ +##===- lib/ExecutionEngine/Interpreter/Makefile ------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## +LEVEL = ../../.. +LIBRARYNAME = LLVMInterpreter + +include $(LEVEL)/Makefile.common diff --git a/libclamav/c++/llvm/lib/ExecutionEngine/JIT/CMakeLists.txt b/libclamav/c++/llvm/lib/ExecutionEngine/JIT/CMakeLists.txt new file mode 100644 index 000000000..42020d69a --- /dev/null +++ b/libclamav/c++/llvm/lib/ExecutionEngine/JIT/CMakeLists.txt @@ -0,0 +1,13 @@ +# TODO: Support other architectures. See Makefile. +add_definitions(-DENABLE_X86_JIT) + +add_llvm_library(LLVMJIT + Intercept.cpp + JIT.cpp + JITDebugRegisterer.cpp + JITDwarfEmitter.cpp + JITEmitter.cpp + JITMemoryManager.cpp + OProfileJITEventListener.cpp + TargetSelect.cpp + ) diff --git a/libclamav/c++/llvm/lib/ExecutionEngine/JIT/Intercept.cpp b/libclamav/c++/llvm/lib/ExecutionEngine/JIT/Intercept.cpp new file mode 100644 index 000000000..c00b60a27 --- /dev/null +++ b/libclamav/c++/llvm/lib/ExecutionEngine/JIT/Intercept.cpp @@ -0,0 +1,149 @@ +//===-- Intercept.cpp - System function interception routines -------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// If a function call occurs to an external function, the JIT is designed to use +// the dynamic loader interface to find a function to call. This is useful for +// calling system calls and library functions that are not available in LLVM. +// Some system calls, however, need to be handled specially. For this reason, +// we intercept some of them here and use our own stubs to handle them. +// +//===----------------------------------------------------------------------===// + +#include "JIT.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/System/DynamicLibrary.h" +#include "llvm/Config/config.h" +using namespace llvm; + +// AtExitHandlers - List of functions to call when the program exits, +// registered with the atexit() library function. +static std::vector AtExitHandlers; + +/// runAtExitHandlers - Run any functions registered by the program's +/// calls to atexit(3), which we intercept and store in +/// AtExitHandlers. +/// +static void runAtExitHandlers() { + while (!AtExitHandlers.empty()) { + void (*Fn)() = AtExitHandlers.back(); + AtExitHandlers.pop_back(); + Fn(); + } +} + +//===----------------------------------------------------------------------===// +// Function stubs that are invoked instead of certain library calls +//===----------------------------------------------------------------------===// + +// Force the following functions to be linked in to anything that uses the +// JIT. This is a hack designed to work around the all-too-clever Glibc +// strategy of making these functions work differently when inlined vs. when +// not inlined, and hiding their real definitions in a separate archive file +// that the dynamic linker can't see. For more info, search for +// 'libc_nonshared.a' on Google, or read http://llvm.org/PR274. +#if defined(__linux__) +#if defined(HAVE_SYS_STAT_H) +#include +#endif +#include +/* stat functions are redirecting to __xstat with a version number. On x86-64 + * linking with libc_nonshared.a and -Wl,--export-dynamic doesn't make 'stat' + * available as an exported symbol, so we have to add it explicitly. + */ +namespace { +class StatSymbols { +public: + StatSymbols() { + sys::DynamicLibrary::AddSymbol("stat", (void*)(intptr_t)stat); + sys::DynamicLibrary::AddSymbol("fstat", (void*)(intptr_t)fstat); + sys::DynamicLibrary::AddSymbol("lstat", (void*)(intptr_t)lstat); + sys::DynamicLibrary::AddSymbol("stat64", (void*)(intptr_t)stat64); + sys::DynamicLibrary::AddSymbol("\x1stat64", (void*)(intptr_t)stat64); + sys::DynamicLibrary::AddSymbol("\x1open64", (void*)(intptr_t)open64); + sys::DynamicLibrary::AddSymbol("\x1lseek64", (void*)(intptr_t)lseek64); + sys::DynamicLibrary::AddSymbol("fstat64", (void*)(intptr_t)fstat64); + sys::DynamicLibrary::AddSymbol("lstat64", (void*)(intptr_t)lstat64); + sys::DynamicLibrary::AddSymbol("atexit", (void*)(intptr_t)atexit); + sys::DynamicLibrary::AddSymbol("mknod", (void*)(intptr_t)mknod); + } +}; +} +static StatSymbols initStatSymbols; +#endif // __linux__ + +// jit_exit - Used to intercept the "exit" library call. +static void jit_exit(int Status) { + runAtExitHandlers(); // Run atexit handlers... + exit(Status); +} + +// jit_atexit - Used to intercept the "atexit" library call. +static int jit_atexit(void (*Fn)()) { + AtExitHandlers.push_back(Fn); // Take note of atexit handler... + return 0; // Always successful +} + +//===----------------------------------------------------------------------===// +// +/// getPointerToNamedFunction - This method returns the address of the specified +/// function by using the dynamic loader interface. As such it is only useful +/// for resolving library symbols, not code generated symbols. +/// +void *JIT::getPointerToNamedFunction(const std::string &Name, + bool AbortOnFailure) { + if (!isSymbolSearchingDisabled()) { + // Check to see if this is one of the functions we want to intercept. Note, + // we cast to intptr_t here to silence a -pedantic warning that complains + // about casting a function pointer to a normal pointer. + if (Name == "exit") return (void*)(intptr_t)&jit_exit; + if (Name == "atexit") return (void*)(intptr_t)&jit_atexit; + + const char *NameStr = Name.c_str(); + // If this is an asm specifier, skip the sentinal. + if (NameStr[0] == 1) ++NameStr; + + // If it's an external function, look it up in the process image... + void *Ptr = sys::DynamicLibrary::SearchForAddressOfSymbol(NameStr); + if (Ptr) return Ptr; + + // If it wasn't found and if it starts with an underscore ('_') character, + // and has an asm specifier, try again without the underscore. + if (Name[0] == 1 && NameStr[0] == '_') { + Ptr = sys::DynamicLibrary::SearchForAddressOfSymbol(NameStr+1); + if (Ptr) return Ptr; + } + + // Darwin/PPC adds $LDBLStub suffixes to various symbols like printf. These + // are references to hidden visibility symbols that dlsym cannot resolve. + // If we have one of these, strip off $LDBLStub and try again. +#if defined(__APPLE__) && defined(__ppc__) + if (Name.size() > 9 && Name[Name.size()-9] == '$' && + memcmp(&Name[Name.size()-8], "LDBLStub", 8) == 0) { + // First try turning $LDBLStub into $LDBL128. If that fails, strip it off. + // This mirrors logic in libSystemStubs.a. + std::string Prefix = std::string(Name.begin(), Name.end()-9); + if (void *Ptr = getPointerToNamedFunction(Prefix+"$LDBL128", false)) + return Ptr; + if (void *Ptr = getPointerToNamedFunction(Prefix, false)) + return Ptr; + } +#endif + } + + /// If a LazyFunctionCreator is installed, use it to get/create the function. + if (LazyFunctionCreator) + if (void *RP = LazyFunctionCreator(Name)) + return RP; + + if (AbortOnFailure) { + llvm_report_error("Program used external function '"+Name+ + "' which could not be resolved!"); + } + return 0; +} diff --git a/libclamav/c++/llvm/lib/ExecutionEngine/JIT/JIT.cpp b/libclamav/c++/llvm/lib/ExecutionEngine/JIT/JIT.cpp new file mode 100644 index 000000000..6d781c7e2 --- /dev/null +++ b/libclamav/c++/llvm/lib/ExecutionEngine/JIT/JIT.cpp @@ -0,0 +1,778 @@ +//===-- JIT.cpp - LLVM Just in Time Compiler ------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This tool implements a just-in-time compiler for LLVM, allowing direct +// execution of LLVM bitcode in an efficient manner. +// +//===----------------------------------------------------------------------===// + +#include "JIT.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Function.h" +#include "llvm/GlobalVariable.h" +#include "llvm/Instructions.h" +#include "llvm/ModuleProvider.h" +#include "llvm/CodeGen/JITCodeEmitter.h" +#include "llvm/CodeGen/MachineCodeInfo.h" +#include "llvm/ExecutionEngine/GenericValue.h" +#include "llvm/ExecutionEngine/JITEventListener.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetJITInfo.h" +#include "llvm/Support/Dwarf.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/MutexGuard.h" +#include "llvm/System/DynamicLibrary.h" +#include "llvm/Config/config.h" + +using namespace llvm; + +#ifdef __APPLE__ +// Apple gcc defaults to -fuse-cxa-atexit (i.e. calls __cxa_atexit instead +// of atexit). It passes the address of linker generated symbol __dso_handle +// to the function. +// This configuration change happened at version 5330. +# include +# if defined(MAC_OS_X_VERSION_10_4) && \ + ((MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_4) || \ + (MAC_OS_X_VERSION_MIN_REQUIRED == MAC_OS_X_VERSION_10_4 && \ + __APPLE_CC__ >= 5330)) +# ifndef HAVE___DSO_HANDLE +# define HAVE___DSO_HANDLE 1 +# endif +# endif +#endif + +#if HAVE___DSO_HANDLE +extern void *__dso_handle __attribute__ ((__visibility__ ("hidden"))); +#endif + +namespace { + +static struct RegisterJIT { + RegisterJIT() { JIT::Register(); } +} JITRegistrator; + +} + +extern "C" void LLVMLinkInJIT() { +} + + +#if defined(__GNUC__) && !defined(__ARM__EABI__) + +// libgcc defines the __register_frame function to dynamically register new +// dwarf frames for exception handling. This functionality is not portable +// across compilers and is only provided by GCC. We use the __register_frame +// function here so that code generated by the JIT cooperates with the unwinding +// runtime of libgcc. When JITting with exception handling enable, LLVM +// generates dwarf frames and registers it to libgcc with __register_frame. +// +// The __register_frame function works with Linux. +// +// Unfortunately, this functionality seems to be in libgcc after the unwinding +// library of libgcc for darwin was written. The code for darwin overwrites the +// value updated by __register_frame with a value fetched with "keymgr". +// "keymgr" is an obsolete functionality, which should be rewritten some day. +// In the meantime, since "keymgr" is on all libgccs shipped with apple-gcc, we +// need a workaround in LLVM which uses the "keymgr" to dynamically modify the +// values of an opaque key, used by libgcc to find dwarf tables. + +extern "C" void __register_frame(void*); + +#if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED <= 1050 +# define USE_KEYMGR 1 +#else +# define USE_KEYMGR 0 +#endif + +#if USE_KEYMGR + +namespace { + +// LibgccObject - This is the structure defined in libgcc. There is no #include +// provided for this structure, so we also define it here. libgcc calls it +// "struct object". The structure is undocumented in libgcc. +struct LibgccObject { + void *unused1; + void *unused2; + void *unused3; + + /// frame - Pointer to the exception table. + void *frame; + + /// encoding - The encoding of the object? + union { + struct { + unsigned long sorted : 1; + unsigned long from_array : 1; + unsigned long mixed_encoding : 1; + unsigned long encoding : 8; + unsigned long count : 21; + } b; + size_t i; + } encoding; + + /// fde_end - libgcc defines this field only if some macro is defined. We + /// include this field even if it may not there, to make libgcc happy. + char *fde_end; + + /// next - At least we know it's a chained list! + struct LibgccObject *next; +}; + +// "kemgr" stuff. Apparently, all frame tables are stored there. +extern "C" void _keymgr_set_and_unlock_processwide_ptr(int, void *); +extern "C" void *_keymgr_get_and_lock_processwide_ptr(int); +#define KEYMGR_GCC3_DW2_OBJ_LIST 302 /* Dwarf2 object list */ + +/// LibgccObjectInfo - libgcc defines this struct as km_object_info. It +/// probably contains all dwarf tables that are loaded. +struct LibgccObjectInfo { + + /// seenObjects - LibgccObjects already parsed by the unwinding runtime. + /// + struct LibgccObject* seenObjects; + + /// unseenObjects - LibgccObjects not parsed yet by the unwinding runtime. + /// + struct LibgccObject* unseenObjects; + + unsigned unused[2]; +}; + +/// darwin_register_frame - Since __register_frame does not work with darwin's +/// libgcc,we provide our own function, which "tricks" libgcc by modifying the +/// "Dwarf2 object list" key. +void DarwinRegisterFrame(void* FrameBegin) { + // Get the key. + LibgccObjectInfo* LOI = (struct LibgccObjectInfo*) + _keymgr_get_and_lock_processwide_ptr(KEYMGR_GCC3_DW2_OBJ_LIST); + assert(LOI && "This should be preallocated by the runtime"); + + // Allocate a new LibgccObject to represent this frame. Deallocation of this + // object may be impossible: since darwin code in libgcc was written after + // the ability to dynamically register frames, things may crash if we + // deallocate it. + struct LibgccObject* ob = (struct LibgccObject*) + malloc(sizeof(struct LibgccObject)); + + // Do like libgcc for the values of the field. + ob->unused1 = (void *)-1; + ob->unused2 = 0; + ob->unused3 = 0; + ob->frame = FrameBegin; + ob->encoding.i = 0; + ob->encoding.b.encoding = llvm::dwarf::DW_EH_PE_omit; + + // Put the info on both places, as libgcc uses the first or the the second + // field. Note that we rely on having two pointers here. If fde_end was a + // char, things would get complicated. + ob->fde_end = (char*)LOI->unseenObjects; + ob->next = LOI->unseenObjects; + + // Update the key's unseenObjects list. + LOI->unseenObjects = ob; + + // Finally update the "key". Apparently, libgcc requires it. + _keymgr_set_and_unlock_processwide_ptr(KEYMGR_GCC3_DW2_OBJ_LIST, + LOI); + +} + +} +#endif // __APPLE__ +#endif // __GNUC__ + +/// createJIT - This is the factory method for creating a JIT for the current +/// machine, it does not fall back to the interpreter. This takes ownership +/// of the module provider. +ExecutionEngine *ExecutionEngine::createJIT(ModuleProvider *MP, + std::string *ErrorStr, + JITMemoryManager *JMM, + CodeGenOpt::Level OptLevel, + bool GVsWithCode, + CodeModel::Model CMM) { + return JIT::createJIT(MP, ErrorStr, JMM, OptLevel, GVsWithCode, CMM); +} + +ExecutionEngine *JIT::createJIT(ModuleProvider *MP, + std::string *ErrorStr, + JITMemoryManager *JMM, + CodeGenOpt::Level OptLevel, + bool GVsWithCode, + CodeModel::Model CMM) { + // Make sure we can resolve symbols in the program as well. The zero arg + // to the function tells DynamicLibrary to load the program, not a library. + if (sys::DynamicLibrary::LoadLibraryPermanently(0, ErrorStr)) + return 0; + + // Pick a target either via -march or by guessing the native arch. + TargetMachine *TM = JIT::selectTarget(MP, ErrorStr); + if (!TM || (ErrorStr && ErrorStr->length() > 0)) return 0; + TM->setCodeModel(CMM); + + // If the target supports JIT code generation, create a the JIT. + if (TargetJITInfo *TJ = TM->getJITInfo()) { + return new JIT(MP, *TM, *TJ, JMM, OptLevel, GVsWithCode); + } else { + if (ErrorStr) + *ErrorStr = "target does not support JIT code generation"; + return 0; + } +} + +JIT::JIT(ModuleProvider *MP, TargetMachine &tm, TargetJITInfo &tji, + JITMemoryManager *JMM, CodeGenOpt::Level OptLevel, bool GVsWithCode) + : ExecutionEngine(MP), TM(tm), TJI(tji), AllocateGVsWithCode(GVsWithCode) { + setTargetData(TM.getTargetData()); + + jitstate = new JITState(MP); + + // Initialize JCE + JCE = createEmitter(*this, JMM, TM); + + // Add target data + MutexGuard locked(lock); + FunctionPassManager &PM = jitstate->getPM(locked); + PM.add(new TargetData(*TM.getTargetData())); + + // Turn the machine code intermediate representation into bytes in memory that + // may be executed. + if (TM.addPassesToEmitMachineCode(PM, *JCE, OptLevel)) { + llvm_report_error("Target does not support machine code emission!"); + } + + // Register routine for informing unwinding runtime about new EH frames +#if defined(__GNUC__) && !defined(__ARM_EABI__) +#if USE_KEYMGR + struct LibgccObjectInfo* LOI = (struct LibgccObjectInfo*) + _keymgr_get_and_lock_processwide_ptr(KEYMGR_GCC3_DW2_OBJ_LIST); + + // The key is created on demand, and libgcc creates it the first time an + // exception occurs. Since we need the key to register frames, we create + // it now. + if (!LOI) + LOI = (LibgccObjectInfo*)calloc(sizeof(struct LibgccObjectInfo), 1); + _keymgr_set_and_unlock_processwide_ptr(KEYMGR_GCC3_DW2_OBJ_LIST, LOI); + InstallExceptionTableRegister(DarwinRegisterFrame); +#else + InstallExceptionTableRegister(__register_frame); +#endif // __APPLE__ +#endif // __GNUC__ + + // Initialize passes. + PM.doInitialization(); +} + +JIT::~JIT() { + delete jitstate; + delete JCE; + delete &TM; +} + +/// addModuleProvider - Add a new ModuleProvider to the JIT. If we previously +/// removed the last ModuleProvider, we need re-initialize jitstate with a valid +/// ModuleProvider. +void JIT::addModuleProvider(ModuleProvider *MP) { + MutexGuard locked(lock); + + if (Modules.empty()) { + assert(!jitstate && "jitstate should be NULL if Modules vector is empty!"); + + jitstate = new JITState(MP); + + FunctionPassManager &PM = jitstate->getPM(locked); + PM.add(new TargetData(*TM.getTargetData())); + + // Turn the machine code intermediate representation into bytes in memory + // that may be executed. + if (TM.addPassesToEmitMachineCode(PM, *JCE, CodeGenOpt::Default)) { + llvm_report_error("Target does not support machine code emission!"); + } + + // Initialize passes. + PM.doInitialization(); + } + + ExecutionEngine::addModuleProvider(MP); +} + +/// removeModuleProvider - If we are removing the last ModuleProvider, +/// invalidate the jitstate since the PassManager it contains references a +/// released ModuleProvider. +Module *JIT::removeModuleProvider(ModuleProvider *MP, std::string *E) { + Module *result = ExecutionEngine::removeModuleProvider(MP, E); + + MutexGuard locked(lock); + + if (jitstate->getMP() == MP) { + delete jitstate; + jitstate = 0; + } + + if (!jitstate && !Modules.empty()) { + jitstate = new JITState(Modules[0]); + + FunctionPassManager &PM = jitstate->getPM(locked); + PM.add(new TargetData(*TM.getTargetData())); + + // Turn the machine code intermediate representation into bytes in memory + // that may be executed. + if (TM.addPassesToEmitMachineCode(PM, *JCE, CodeGenOpt::Default)) { + llvm_report_error("Target does not support machine code emission!"); + } + + // Initialize passes. + PM.doInitialization(); + } + return result; +} + +/// deleteModuleProvider - Remove a ModuleProvider from the list of modules, +/// and deletes the ModuleProvider and owned Module. Avoids materializing +/// the underlying module. +void JIT::deleteModuleProvider(ModuleProvider *MP, std::string *E) { + ExecutionEngine::deleteModuleProvider(MP, E); + + MutexGuard locked(lock); + + if (jitstate->getMP() == MP) { + delete jitstate; + jitstate = 0; + } + + if (!jitstate && !Modules.empty()) { + jitstate = new JITState(Modules[0]); + + FunctionPassManager &PM = jitstate->getPM(locked); + PM.add(new TargetData(*TM.getTargetData())); + + // Turn the machine code intermediate representation into bytes in memory + // that may be executed. + if (TM.addPassesToEmitMachineCode(PM, *JCE, CodeGenOpt::Default)) { + llvm_report_error("Target does not support machine code emission!"); + } + + // Initialize passes. + PM.doInitialization(); + } +} + +/// run - Start execution with the specified function and arguments. +/// +GenericValue JIT::runFunction(Function *F, + const std::vector &ArgValues) { + assert(F && "Function *F was null at entry to run()"); + + void *FPtr = getPointerToFunction(F); + assert(FPtr && "Pointer to fn's code was null after getPointerToFunction"); + const FunctionType *FTy = F->getFunctionType(); + const Type *RetTy = FTy->getReturnType(); + + assert((FTy->getNumParams() == ArgValues.size() || + (FTy->isVarArg() && FTy->getNumParams() <= ArgValues.size())) && + "Wrong number of arguments passed into function!"); + assert(FTy->getNumParams() == ArgValues.size() && + "This doesn't support passing arguments through varargs (yet)!"); + + // Handle some common cases first. These cases correspond to common `main' + // prototypes. + if (RetTy == Type::getInt32Ty(F->getContext()) || + RetTy == Type::getVoidTy(F->getContext())) { + switch (ArgValues.size()) { + case 3: + if (FTy->getParamType(0) == Type::getInt32Ty(F->getContext()) && + isa(FTy->getParamType(1)) && + isa(FTy->getParamType(2))) { + int (*PF)(int, char **, const char **) = + (int(*)(int, char **, const char **))(intptr_t)FPtr; + + // Call the function. + GenericValue rv; + rv.IntVal = APInt(32, PF(ArgValues[0].IntVal.getZExtValue(), + (char **)GVTOP(ArgValues[1]), + (const char **)GVTOP(ArgValues[2]))); + return rv; + } + break; + case 2: + if (FTy->getParamType(0) == Type::getInt32Ty(F->getContext()) && + isa(FTy->getParamType(1))) { + int (*PF)(int, char **) = (int(*)(int, char **))(intptr_t)FPtr; + + // Call the function. + GenericValue rv; + rv.IntVal = APInt(32, PF(ArgValues[0].IntVal.getZExtValue(), + (char **)GVTOP(ArgValues[1]))); + return rv; + } + break; + case 1: + if (FTy->getNumParams() == 1 && + FTy->getParamType(0) == Type::getInt32Ty(F->getContext())) { + GenericValue rv; + int (*PF)(int) = (int(*)(int))(intptr_t)FPtr; + rv.IntVal = APInt(32, PF(ArgValues[0].IntVal.getZExtValue())); + return rv; + } + break; + } + } + + // Handle cases where no arguments are passed first. + if (ArgValues.empty()) { + GenericValue rv; + switch (RetTy->getTypeID()) { + default: llvm_unreachable("Unknown return type for function call!"); + case Type::IntegerTyID: { + unsigned BitWidth = cast(RetTy)->getBitWidth(); + if (BitWidth == 1) + rv.IntVal = APInt(BitWidth, ((bool(*)())(intptr_t)FPtr)()); + else if (BitWidth <= 8) + rv.IntVal = APInt(BitWidth, ((char(*)())(intptr_t)FPtr)()); + else if (BitWidth <= 16) + rv.IntVal = APInt(BitWidth, ((short(*)())(intptr_t)FPtr)()); + else if (BitWidth <= 32) + rv.IntVal = APInt(BitWidth, ((int(*)())(intptr_t)FPtr)()); + else if (BitWidth <= 64) + rv.IntVal = APInt(BitWidth, ((int64_t(*)())(intptr_t)FPtr)()); + else + llvm_unreachable("Integer types > 64 bits not supported"); + return rv; + } + case Type::VoidTyID: + rv.IntVal = APInt(32, ((int(*)())(intptr_t)FPtr)()); + return rv; + case Type::FloatTyID: + rv.FloatVal = ((float(*)())(intptr_t)FPtr)(); + return rv; + case Type::DoubleTyID: + rv.DoubleVal = ((double(*)())(intptr_t)FPtr)(); + return rv; + case Type::X86_FP80TyID: + case Type::FP128TyID: + case Type::PPC_FP128TyID: + llvm_unreachable("long double not supported yet"); + return rv; + case Type::PointerTyID: + return PTOGV(((void*(*)())(intptr_t)FPtr)()); + } + } + + // Okay, this is not one of our quick and easy cases. Because we don't have a + // full FFI, we have to codegen a nullary stub function that just calls the + // function we are interested in, passing in constants for all of the + // arguments. Make this function and return. + + // First, create the function. + FunctionType *STy=FunctionType::get(RetTy, false); + Function *Stub = Function::Create(STy, Function::InternalLinkage, "", + F->getParent()); + + // Insert a basic block. + BasicBlock *StubBB = BasicBlock::Create(F->getContext(), "", Stub); + + // Convert all of the GenericValue arguments over to constants. Note that we + // currently don't support varargs. + SmallVector Args; + for (unsigned i = 0, e = ArgValues.size(); i != e; ++i) { + Constant *C = 0; + const Type *ArgTy = FTy->getParamType(i); + const GenericValue &AV = ArgValues[i]; + switch (ArgTy->getTypeID()) { + default: llvm_unreachable("Unknown argument type for function call!"); + case Type::IntegerTyID: + C = ConstantInt::get(F->getContext(), AV.IntVal); + break; + case Type::FloatTyID: + C = ConstantFP::get(F->getContext(), APFloat(AV.FloatVal)); + break; + case Type::DoubleTyID: + C = ConstantFP::get(F->getContext(), APFloat(AV.DoubleVal)); + break; + case Type::PPC_FP128TyID: + case Type::X86_FP80TyID: + case Type::FP128TyID: + C = ConstantFP::get(F->getContext(), APFloat(AV.IntVal)); + break; + case Type::PointerTyID: + void *ArgPtr = GVTOP(AV); + if (sizeof(void*) == 4) + C = ConstantInt::get(Type::getInt32Ty(F->getContext()), + (int)(intptr_t)ArgPtr); + else + C = ConstantInt::get(Type::getInt64Ty(F->getContext()), + (intptr_t)ArgPtr); + // Cast the integer to pointer + C = ConstantExpr::getIntToPtr(C, ArgTy); + break; + } + Args.push_back(C); + } + + CallInst *TheCall = CallInst::Create(F, Args.begin(), Args.end(), + "", StubBB); + TheCall->setCallingConv(F->getCallingConv()); + TheCall->setTailCall(); + if (TheCall->getType() != Type::getVoidTy(F->getContext())) + // Return result of the call. + ReturnInst::Create(F->getContext(), TheCall, StubBB); + else + ReturnInst::Create(F->getContext(), StubBB); // Just return void. + + // Finally, return the value returned by our nullary stub function. + return runFunction(Stub, std::vector()); +} + +void JIT::RegisterJITEventListener(JITEventListener *L) { + if (L == NULL) + return; + MutexGuard locked(lock); + EventListeners.push_back(L); +} +void JIT::UnregisterJITEventListener(JITEventListener *L) { + if (L == NULL) + return; + MutexGuard locked(lock); + std::vector::reverse_iterator I= + std::find(EventListeners.rbegin(), EventListeners.rend(), L); + if (I != EventListeners.rend()) { + std::swap(*I, EventListeners.back()); + EventListeners.pop_back(); + } +} +void JIT::NotifyFunctionEmitted( + const Function &F, + void *Code, size_t Size, + const JITEvent_EmittedFunctionDetails &Details) { + MutexGuard locked(lock); + for (unsigned I = 0, S = EventListeners.size(); I < S; ++I) { + EventListeners[I]->NotifyFunctionEmitted(F, Code, Size, Details); + } +} + +void JIT::NotifyFreeingMachineCode(void *OldPtr) { + MutexGuard locked(lock); + for (unsigned I = 0, S = EventListeners.size(); I < S; ++I) { + EventListeners[I]->NotifyFreeingMachineCode(OldPtr); + } +} + +/// runJITOnFunction - Run the FunctionPassManager full of +/// just-in-time compilation passes on F, hopefully filling in +/// GlobalAddress[F] with the address of F's machine code. +/// +void JIT::runJITOnFunction(Function *F, MachineCodeInfo *MCI) { + MutexGuard locked(lock); + + class MCIListener : public JITEventListener { + MachineCodeInfo *const MCI; + public: + MCIListener(MachineCodeInfo *mci) : MCI(mci) {} + virtual void NotifyFunctionEmitted(const Function &, + void *Code, size_t Size, + const EmittedFunctionDetails &) { + MCI->setAddress(Code); + MCI->setSize(Size); + } + }; + MCIListener MCIL(MCI); + RegisterJITEventListener(&MCIL); + + runJITOnFunctionUnlocked(F, locked); + + UnregisterJITEventListener(&MCIL); +} + +void JIT::runJITOnFunctionUnlocked(Function *F, const MutexGuard &locked) { + static bool isAlreadyCodeGenerating = false; + assert(!isAlreadyCodeGenerating && "Error: Recursive compilation detected!"); + + // JIT the function + isAlreadyCodeGenerating = true; + jitstate->getPM(locked).run(*F); + isAlreadyCodeGenerating = false; + + // If the function referred to another function that had not yet been + // read from bitcode, and we are jitting non-lazily, emit it now. + while (!jitstate->getPendingFunctions(locked).empty()) { + Function *PF = jitstate->getPendingFunctions(locked).back(); + jitstate->getPendingFunctions(locked).pop_back(); + + // JIT the function + isAlreadyCodeGenerating = true; + jitstate->getPM(locked).run(*PF); + isAlreadyCodeGenerating = false; + + // Now that the function has been jitted, ask the JITEmitter to rewrite + // the stub with real address of the function. + updateFunctionStub(PF); + } +} + +/// getPointerToFunction - This method is used to get the address of the +/// specified function, compiling it if neccesary. +/// +void *JIT::getPointerToFunction(Function *F) { + + if (void *Addr = getPointerToGlobalIfAvailable(F)) + return Addr; // Check if function already code gen'd + + MutexGuard locked(lock); + + // Now that this thread owns the lock, check if another thread has already + // code gen'd the function. + if (void *Addr = getPointerToGlobalIfAvailable(F)) + return Addr; + + // Make sure we read in the function if it exists in this Module. + if (F->hasNotBeenReadFromBitcode()) { + // Determine the module provider this function is provided by. + Module *M = F->getParent(); + ModuleProvider *MP = 0; + for (unsigned i = 0, e = Modules.size(); i != e; ++i) { + if (Modules[i]->getModule() == M) { + MP = Modules[i]; + break; + } + } + assert(MP && "Function isn't in a module we know about!"); + + std::string ErrorMsg; + if (MP->materializeFunction(F, &ErrorMsg)) { + llvm_report_error("Error reading function '" + F->getName()+ + "' from bitcode file: " + ErrorMsg); + } + + // Now retry to get the address. + if (void *Addr = getPointerToGlobalIfAvailable(F)) + return Addr; + } + + if (F->isDeclaration() || F->hasAvailableExternallyLinkage()) { + bool AbortOnFailure = !F->hasExternalWeakLinkage(); + void *Addr = getPointerToNamedFunction(F->getName(), AbortOnFailure); + addGlobalMapping(F, Addr); + return Addr; + } + + runJITOnFunctionUnlocked(F, locked); + + void *Addr = getPointerToGlobalIfAvailable(F); + assert(Addr && "Code generation didn't add function to GlobalAddress table!"); + return Addr; +} + +/// getOrEmitGlobalVariable - Return the address of the specified global +/// variable, possibly emitting it to memory if needed. This is used by the +/// Emitter. +void *JIT::getOrEmitGlobalVariable(const GlobalVariable *GV) { + MutexGuard locked(lock); + + void *Ptr = getPointerToGlobalIfAvailable(GV); + if (Ptr) return Ptr; + + // If the global is external, just remember the address. + if (GV->isDeclaration()) { +#if HAVE___DSO_HANDLE + if (GV->getName() == "__dso_handle") + return (void*)&__dso_handle; +#endif + Ptr = sys::DynamicLibrary::SearchForAddressOfSymbol(GV->getName()); + if (Ptr == 0) { + llvm_report_error("Could not resolve external global address: " + +GV->getName()); + } + addGlobalMapping(GV, Ptr); + } else { + // If the global hasn't been emitted to memory yet, allocate space and + // emit it into memory. + Ptr = getMemoryForGV(GV); + addGlobalMapping(GV, Ptr); + EmitGlobalVariable(GV); // Initialize the variable. + } + return Ptr; +} + +/// recompileAndRelinkFunction - This method is used to force a function +/// which has already been compiled, to be compiled again, possibly +/// after it has been modified. Then the entry to the old copy is overwritten +/// with a branch to the new copy. If there was no old copy, this acts +/// just like JIT::getPointerToFunction(). +/// +void *JIT::recompileAndRelinkFunction(Function *F) { + void *OldAddr = getPointerToGlobalIfAvailable(F); + + // If it's not already compiled there is no reason to patch it up. + if (OldAddr == 0) { return getPointerToFunction(F); } + + // Delete the old function mapping. + addGlobalMapping(F, 0); + + // Recodegen the function + runJITOnFunction(F); + + // Update state, forward the old function to the new function. + void *Addr = getPointerToGlobalIfAvailable(F); + assert(Addr && "Code generation didn't add function to GlobalAddress table!"); + TJI.replaceMachineCodeForFunction(OldAddr, Addr); + return Addr; +} + +/// getMemoryForGV - This method abstracts memory allocation of global +/// variable so that the JIT can allocate thread local variables depending +/// on the target. +/// +char* JIT::getMemoryForGV(const GlobalVariable* GV) { + char *Ptr; + + // GlobalVariable's which are not "constant" will cause trouble in a server + // situation. It's returned in the same block of memory as code which may + // not be writable. + if (isGVCompilationDisabled() && !GV->isConstant()) { + llvm_report_error("Compilation of non-internal GlobalValue is disabled!"); + } + + // Some applications require globals and code to live together, so they may + // be allocated into the same buffer, but in general globals are allocated + // through the memory manager which puts them near the code but not in the + // same buffer. + const Type *GlobalType = GV->getType()->getElementType(); + size_t S = getTargetData()->getTypeAllocSize(GlobalType); + size_t A = getTargetData()->getPreferredAlignment(GV); + if (GV->isThreadLocal()) { + MutexGuard locked(lock); + Ptr = TJI.allocateThreadLocalMemory(S); + } else if (TJI.allocateSeparateGVMemory()) { + if (A <= 8) { + Ptr = (char*)malloc(S); + } else { + // Allocate S+A bytes of memory, then use an aligned pointer within that + // space. + Ptr = (char*)malloc(S+A); + unsigned MisAligned = ((intptr_t)Ptr & (A-1)); + Ptr = Ptr + (MisAligned ? (A-MisAligned) : 0); + } + } else if (AllocateGVsWithCode) { + Ptr = (char*)JCE->allocateSpace(S, A); + } else { + Ptr = (char*)JCE->allocateGlobal(S, A); + } + return Ptr; +} + +void JIT::addPendingFunction(Function *F) { + MutexGuard locked(lock); + jitstate->getPendingFunctions(locked).push_back(F); +} + + +JITEventListener::~JITEventListener() {} diff --git a/libclamav/c++/llvm/lib/ExecutionEngine/JIT/JIT.h b/libclamav/c++/llvm/lib/ExecutionEngine/JIT/JIT.h new file mode 100644 index 000000000..f165bd665 --- /dev/null +++ b/libclamav/c++/llvm/lib/ExecutionEngine/JIT/JIT.h @@ -0,0 +1,211 @@ +//===-- JIT.h - Class definition for the JIT --------------------*- 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 the top-level JIT data structure. +// +//===----------------------------------------------------------------------===// + +#ifndef JIT_H +#define JIT_H + +#include "llvm/ExecutionEngine/ExecutionEngine.h" +#include "llvm/PassManager.h" +#include "llvm/Support/ValueHandle.h" + +namespace llvm { + +class Function; +struct JITEvent_EmittedFunctionDetails; +class MachineCodeEmitter; +class MachineCodeInfo; +class TargetJITInfo; +class TargetMachine; + +class JITState { +private: + FunctionPassManager PM; // Passes to compile a function + ModuleProvider *MP; // ModuleProvider used to create the PM + + /// PendingFunctions - Functions which have not been code generated yet, but + /// were called from a function being code generated. + std::vector > PendingFunctions; + +public: + explicit JITState(ModuleProvider *MP) : PM(MP), MP(MP) {} + + FunctionPassManager &getPM(const MutexGuard &L) { + return PM; + } + + ModuleProvider *getMP() const { return MP; } + std::vector > &getPendingFunctions(const MutexGuard &L){ + return PendingFunctions; + } +}; + + +class JIT : public ExecutionEngine { + TargetMachine &TM; // The current target we are compiling to + TargetJITInfo &TJI; // The JITInfo for the target we are compiling to + JITCodeEmitter *JCE; // JCE object + std::vector EventListeners; + + /// AllocateGVsWithCode - Some applications require that global variables and + /// code be allocated into the same region of memory, in which case this flag + /// should be set to true. Doing so breaks freeMachineCodeForFunction. + bool AllocateGVsWithCode; + + JITState *jitstate; + + JIT(ModuleProvider *MP, TargetMachine &tm, TargetJITInfo &tji, + JITMemoryManager *JMM, CodeGenOpt::Level OptLevel, + bool AllocateGVsWithCode); +public: + ~JIT(); + + static void Register() { + JITCtor = create; + } + + /// getJITInfo - Return the target JIT information structure. + /// + TargetJITInfo &getJITInfo() const { return TJI; } + + /// create - Create an return a new JIT compiler if there is one available + /// for the current target. Otherwise, return null. + /// + static ExecutionEngine *create(ModuleProvider *MP, + std::string *Err, + JITMemoryManager *JMM, + CodeGenOpt::Level OptLevel = + CodeGenOpt::Default, + bool GVsWithCode = true, + CodeModel::Model CMM = CodeModel::Default) { + return ExecutionEngine::createJIT(MP, Err, JMM, OptLevel, GVsWithCode, + CMM); + } + + virtual void addModuleProvider(ModuleProvider *MP); + + /// removeModuleProvider - Remove a ModuleProvider from the list of modules. + /// Relases the Module from the ModuleProvider, materializing it in the + /// process, and returns the materialized Module. + virtual Module *removeModuleProvider(ModuleProvider *MP, + std::string *ErrInfo = 0); + + /// deleteModuleProvider - Remove a ModuleProvider from the list of modules, + /// and deletes the ModuleProvider and owned Module. Avoids materializing + /// the underlying module. + virtual void deleteModuleProvider(ModuleProvider *P,std::string *ErrInfo = 0); + + /// runFunction - Start execution with the specified function and arguments. + /// + virtual GenericValue runFunction(Function *F, + const std::vector &ArgValues); + + /// getPointerToNamedFunction - This method returns the address of the + /// specified function by using the dlsym function call. As such it is only + /// useful for resolving library symbols, not code generated symbols. + /// + /// If AbortOnFailure is false and no function with the given name is + /// found, this function silently returns a null pointer. Otherwise, + /// it prints a message to stderr and aborts. + /// + void *getPointerToNamedFunction(const std::string &Name, + bool AbortOnFailure = true); + + // CompilationCallback - Invoked the first time that a call site is found, + // which causes lazy compilation of the target function. + // + static void CompilationCallback(); + + /// getPointerToFunction - This returns the address of the specified function, + /// compiling it if necessary. + /// + void *getPointerToFunction(Function *F); + + void *getPointerToBasicBlock(BasicBlock *BB) { + assert(0 && "JIT does not support address-of-label yet!"); + return 0; + } + + /// getOrEmitGlobalVariable - Return the address of the specified global + /// variable, possibly emitting it to memory if needed. This is used by the + /// Emitter. + void *getOrEmitGlobalVariable(const GlobalVariable *GV); + + /// getPointerToFunctionOrStub - If the specified function has been + /// code-gen'd, return a pointer to the function. If not, compile it, or use + /// a stub to implement lazy compilation if available. + /// + void *getPointerToFunctionOrStub(Function *F); + + /// recompileAndRelinkFunction - This method is used to force a function + /// which has already been compiled, to be compiled again, possibly + /// after it has been modified. Then the entry to the old copy is overwritten + /// with a branch to the new copy. If there was no old copy, this acts + /// just like JIT::getPointerToFunction(). + /// + void *recompileAndRelinkFunction(Function *F); + + /// freeMachineCodeForFunction - deallocate memory used to code-generate this + /// Function. + /// + void freeMachineCodeForFunction(Function *F); + + /// addPendingFunction - while jitting non-lazily, a called but non-codegen'd + /// function was encountered. Add it to a pending list to be processed after + /// the current function. + /// + void addPendingFunction(Function *F); + + /// getCodeEmitter - Return the code emitter this JIT is emitting into. + /// + JITCodeEmitter *getCodeEmitter() const { return JCE; } + + /// selectTarget - Pick a target either via -march or by guessing the native + /// arch. Add any CPU features specified via -mcpu or -mattr. + static TargetMachine *selectTarget(ModuleProvider *MP, std::string *Err); + + static ExecutionEngine *createJIT(ModuleProvider *MP, + std::string *ErrorStr, + JITMemoryManager *JMM, + CodeGenOpt::Level OptLevel, + bool GVsWithCode, + CodeModel::Model CMM); + + // Run the JIT on F and return information about the generated code + void runJITOnFunction(Function *F, MachineCodeInfo *MCI = 0); + + virtual void RegisterJITEventListener(JITEventListener *L); + virtual void UnregisterJITEventListener(JITEventListener *L); + /// These functions correspond to the methods on JITEventListener. They + /// iterate over the registered listeners and call the corresponding method on + /// each. + void NotifyFunctionEmitted( + const Function &F, void *Code, size_t Size, + const JITEvent_EmittedFunctionDetails &Details); + void NotifyFreeingMachineCode(void *OldPtr); + +private: + static JITCodeEmitter *createEmitter(JIT &J, JITMemoryManager *JMM, + TargetMachine &tm); + void runJITOnFunctionUnlocked(Function *F, const MutexGuard &locked); + void updateFunctionStub(Function *F); + +protected: + + /// getMemoryforGV - Allocate memory for a global variable. + virtual char* getMemoryForGV(const GlobalVariable* GV); + +}; + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/lib/ExecutionEngine/JIT/JITDebugRegisterer.cpp b/libclamav/c++/llvm/lib/ExecutionEngine/JIT/JITDebugRegisterer.cpp new file mode 100644 index 000000000..565509cd1 --- /dev/null +++ b/libclamav/c++/llvm/lib/ExecutionEngine/JIT/JITDebugRegisterer.cpp @@ -0,0 +1,209 @@ +//===-- JITDebugRegisterer.cpp - Register debug symbols for JIT -----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines a JITDebugRegisterer object that is used by the JIT to +// register debug info with debuggers like GDB. +// +//===----------------------------------------------------------------------===// + +#include "JITDebugRegisterer.h" +#include "../../CodeGen/ELF.h" +#include "../../CodeGen/ELFWriter.h" +#include "llvm/LLVMContext.h" +#include "llvm/Function.h" +#include "llvm/Module.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetOptions.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/OwningPtr.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/MutexGuard.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/System/Mutex.h" +#include +#include + +namespace llvm { + +// This must be kept in sync with gdb/gdb/jit.h . +extern "C" { + + // Debuggers puts a breakpoint in this function. + DISABLE_INLINE void __jit_debug_register_code() { } + + // We put information about the JITed function in this global, which the + // debugger reads. Make sure to specify the version statically, because the + // debugger checks the version before we can set it during runtime. + struct jit_descriptor __jit_debug_descriptor = { 1, 0, 0, 0 }; + +} + +namespace { + + /// JITDebugLock - Used to serialize all code registration events, since they + /// modify global variables. + sys::Mutex JITDebugLock; + +} + +JITDebugRegisterer::JITDebugRegisterer(TargetMachine &tm) : TM(tm), FnMap() { } + +JITDebugRegisterer::~JITDebugRegisterer() { + // Free all ELF memory. + for (RegisteredFunctionsMap::iterator I = FnMap.begin(), E = FnMap.end(); + I != E; ++I) { + // Call the private method that doesn't update the map so our iterator + // doesn't break. + UnregisterFunctionInternal(I); + } + FnMap.clear(); +} + +std::string JITDebugRegisterer::MakeELF(const Function *F, DebugInfo &I) { + // Stack allocate an empty module with an empty LLVMContext for the ELFWriter + // API. We don't use the real module because then the ELFWriter would write + // out unnecessary GlobalValues during finalization. + LLVMContext Context; + Module M("", Context); + + // Make a buffer for the ELF in memory. + std::string Buffer; + raw_string_ostream O(Buffer); + ELFWriter EW(O, TM); + EW.doInitialization(M); + + // Copy the binary into the .text section. This isn't necessary, but it's + // useful to be able to disassemble the ELF by hand. + ELFSection &Text = EW.getTextSection((Function *)F); + Text.Addr = (uint64_t)I.FnStart; + // TODO: We could eliminate this copy if we somehow used a pointer/size pair + // instead of a vector. + Text.getData().assign(I.FnStart, I.FnEnd); + + // Copy the exception handling call frame information into the .eh_frame + // section. This allows GDB to get a good stack trace, particularly on + // linux x86_64. Mark this as a PROGBITS section that needs to be loaded + // into memory at runtime. + ELFSection &EH = EW.getSection(".eh_frame", ELFSection::SHT_PROGBITS, + ELFSection::SHF_ALLOC); + // Pointers in the DWARF EH info are all relative to the EH frame start, + // which is stored here. + EH.Addr = (uint64_t)I.EhStart; + // TODO: We could eliminate this copy if we somehow used a pointer/size pair + // instead of a vector. + EH.getData().assign(I.EhStart, I.EhEnd); + + // Add this single function to the symbol table, so the debugger prints the + // name instead of '???'. We give the symbol default global visibility. + ELFSym *FnSym = ELFSym::getGV(F, + ELFSym::STB_GLOBAL, + ELFSym::STT_FUNC, + ELFSym::STV_DEFAULT); + FnSym->SectionIdx = Text.SectionIdx; + FnSym->Size = I.FnEnd - I.FnStart; + FnSym->Value = 0; // Offset from start of section. + EW.SymbolList.push_back(FnSym); + + EW.doFinalization(M); + O.flush(); + + // When trying to debug why GDB isn't getting the debug info right, it's + // awfully helpful to write the object file to disk so that it can be + // inspected with readelf and objdump. + if (JITEmitDebugInfoToDisk) { + std::string Filename; + raw_string_ostream O2(Filename); + O2 << "/tmp/llvm_function_" << I.FnStart << "_" << F->getNameStr() << ".o"; + O2.flush(); + std::string Errors; + raw_fd_ostream O3(Filename.c_str(), Errors); + O3 << Buffer; + O3.close(); + } + + return Buffer; +} + +void JITDebugRegisterer::RegisterFunction(const Function *F, DebugInfo &I) { + // TODO: Support non-ELF platforms. + if (!TM.getELFWriterInfo()) + return; + + std::string Buffer = MakeELF(F, I); + + jit_code_entry *JITCodeEntry = new jit_code_entry(); + JITCodeEntry->symfile_addr = Buffer.c_str(); + JITCodeEntry->symfile_size = Buffer.size(); + + // Add a mapping from F to the entry and buffer, so we can delete this + // info later. + FnMap[F] = std::make_pair(Buffer, JITCodeEntry); + + // Acquire the lock and do the registration. + { + MutexGuard locked(JITDebugLock); + __jit_debug_descriptor.action_flag = JIT_REGISTER_FN; + + // Insert this entry at the head of the list. + JITCodeEntry->prev_entry = NULL; + jit_code_entry *NextEntry = __jit_debug_descriptor.first_entry; + JITCodeEntry->next_entry = NextEntry; + if (NextEntry != NULL) { + NextEntry->prev_entry = JITCodeEntry; + } + __jit_debug_descriptor.first_entry = JITCodeEntry; + __jit_debug_descriptor.relevant_entry = JITCodeEntry; + __jit_debug_register_code(); + } +} + +void JITDebugRegisterer::UnregisterFunctionInternal( + RegisteredFunctionsMap::iterator I) { + jit_code_entry *JITCodeEntry = I->second.second; + + // Acquire the lock and do the unregistration. + { + MutexGuard locked(JITDebugLock); + __jit_debug_descriptor.action_flag = JIT_UNREGISTER_FN; + + // Remove the jit_code_entry from the linked list. + jit_code_entry *PrevEntry = JITCodeEntry->prev_entry; + jit_code_entry *NextEntry = JITCodeEntry->next_entry; + if (NextEntry) { + NextEntry->prev_entry = PrevEntry; + } + if (PrevEntry) { + PrevEntry->next_entry = NextEntry; + } else { + assert(__jit_debug_descriptor.first_entry == JITCodeEntry); + __jit_debug_descriptor.first_entry = NextEntry; + } + + // Tell GDB which entry we removed, and unregister the code. + __jit_debug_descriptor.relevant_entry = JITCodeEntry; + __jit_debug_register_code(); + } + + // Free the ELF file in memory. + std::string &Buffer = I->second.first; + Buffer.clear(); +} + +void JITDebugRegisterer::UnregisterFunction(const Function *F) { + // TODO: Support non-ELF platforms. + if (!TM.getELFWriterInfo()) + return; + + RegisteredFunctionsMap::iterator I = FnMap.find(F); + if (I == FnMap.end()) return; + UnregisterFunctionInternal(I); + FnMap.erase(I); +} + +} // end namespace llvm diff --git a/libclamav/c++/llvm/lib/ExecutionEngine/JIT/JITDebugRegisterer.h b/libclamav/c++/llvm/lib/ExecutionEngine/JIT/JITDebugRegisterer.h new file mode 100644 index 000000000..7e53d7847 --- /dev/null +++ b/libclamav/c++/llvm/lib/ExecutionEngine/JIT/JITDebugRegisterer.h @@ -0,0 +1,116 @@ +//===-- JITDebugRegisterer.h - Register debug symbols for JIT -------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines a JITDebugRegisterer object that is used by the JIT to +// register debug info with debuggers like GDB. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_EXECUTION_ENGINE_JIT_DEBUGREGISTERER_H +#define LLVM_EXECUTION_ENGINE_JIT_DEBUGREGISTERER_H + +#include "llvm/ADT/DenseMap.h" +#include "llvm/System/DataTypes.h" +#include + +// This must be kept in sync with gdb/gdb/jit.h . +extern "C" { + + typedef enum { + JIT_NOACTION = 0, + JIT_REGISTER_FN, + JIT_UNREGISTER_FN + } jit_actions_t; + + struct jit_code_entry { + struct jit_code_entry *next_entry; + struct jit_code_entry *prev_entry; + const char *symfile_addr; + uint64_t symfile_size; + }; + + struct jit_descriptor { + uint32_t version; + // This should be jit_actions_t, but we want to be specific about the + // bit-width. + uint32_t action_flag; + struct jit_code_entry *relevant_entry; + struct jit_code_entry *first_entry; + }; + +} + +namespace llvm { + +class ELFSection; +class Function; +class TargetMachine; + + +/// This class encapsulates information we want to send to the debugger. +/// +struct DebugInfo { + uint8_t *FnStart; + uint8_t *FnEnd; + uint8_t *EhStart; + uint8_t *EhEnd; + + DebugInfo() : FnStart(0), FnEnd(0), EhStart(0), EhEnd(0) {} +}; + +typedef DenseMap< const Function*, std::pair > + RegisteredFunctionsMap; + +/// This class registers debug info for JITed code with an attached debugger. +/// Without proper debug info, GDB can't do things like source level debugging +/// or even produce a proper stack trace on linux-x86_64. To use this class, +/// whenever a function is JITed, create a DebugInfo struct and pass it to the +/// RegisterFunction method. The method will then do whatever is necessary to +/// inform the debugger about the JITed function. +class JITDebugRegisterer { + + TargetMachine &TM; + + /// FnMap - A map of functions that have been registered to the associated + /// temporary files. Used for cleanup. + RegisteredFunctionsMap FnMap; + + /// MakeELF - Builds the ELF file in memory and returns a std::string that + /// contains the ELF. + std::string MakeELF(const Function *F, DebugInfo &I); + +public: + JITDebugRegisterer(TargetMachine &tm); + + /// ~JITDebugRegisterer - Unregisters all code and frees symbol files. + /// + ~JITDebugRegisterer(); + + /// RegisterFunction - Register debug info for the given function with an + /// attached debugger. Clients must call UnregisterFunction on all + /// registered functions before deleting them to free the associated symbol + /// file and unregister it from the debugger. + void RegisterFunction(const Function *F, DebugInfo &I); + + /// UnregisterFunction - Unregister the debug info for the given function + /// from the debugger and free associated memory. + void UnregisterFunction(const Function *F); + +private: + /// UnregisterFunctionInternal - Unregister the debug info for the given + /// function from the debugger and delete any temporary files. The private + /// version of this method does not remove the function from FnMap so that it + /// can be called while iterating over FnMap. + void UnregisterFunctionInternal(RegisteredFunctionsMap::iterator I); + +}; + +} // end namespace llvm + +#endif // LLVM_EXECUTION_ENGINE_JIT_DEBUGREGISTERER_H diff --git a/libclamav/c++/llvm/lib/ExecutionEngine/JIT/JITDwarfEmitter.cpp b/libclamav/c++/llvm/lib/ExecutionEngine/JIT/JITDwarfEmitter.cpp new file mode 100644 index 000000000..f2b28ad32 --- /dev/null +++ b/libclamav/c++/llvm/lib/ExecutionEngine/JIT/JITDwarfEmitter.cpp @@ -0,0 +1,1050 @@ +//===----- JITDwarfEmitter.cpp - Write dwarf tables into memory -----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines a JITDwarfEmitter object that is used by the JIT to +// write dwarf tables to memory. +// +//===----------------------------------------------------------------------===// + +#include "JIT.h" +#include "JITDwarfEmitter.h" +#include "llvm/Function.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/CodeGen/JITCodeEmitter.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineLocation.h" +#include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/ExecutionEngine/JITMemoryManager.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetFrameInfo.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetRegisterInfo.h" +using namespace llvm; + +JITDwarfEmitter::JITDwarfEmitter(JIT& theJit) : MMI(0), Jit(theJit) {} + + +unsigned char* JITDwarfEmitter::EmitDwarfTable(MachineFunction& F, + JITCodeEmitter& jce, + unsigned char* StartFunction, + unsigned char* EndFunction, + unsigned char* &EHFramePtr) { + assert(MMI && "MachineModuleInfo not registered!"); + + const TargetMachine& TM = F.getTarget(); + TD = TM.getTargetData(); + stackGrowthDirection = TM.getFrameInfo()->getStackGrowthDirection(); + RI = TM.getRegisterInfo(); + JCE = &jce; + + unsigned char* ExceptionTable = EmitExceptionTable(&F, StartFunction, + EndFunction); + + unsigned char* Result = 0; + + const std::vector Personalities = MMI->getPersonalities(); + EHFramePtr = EmitCommonEHFrame(Personalities[MMI->getPersonalityIndex()]); + + Result = EmitEHFrame(Personalities[MMI->getPersonalityIndex()], EHFramePtr, + StartFunction, EndFunction, ExceptionTable); + + return Result; +} + + +void +JITDwarfEmitter::EmitFrameMoves(intptr_t BaseLabelPtr, + const std::vector &Moves) const { + unsigned PointerSize = TD->getPointerSize(); + int stackGrowth = stackGrowthDirection == TargetFrameInfo::StackGrowsUp ? + PointerSize : -PointerSize; + bool IsLocal = false; + unsigned BaseLabelID = 0; + + for (unsigned i = 0, N = Moves.size(); i < N; ++i) { + const MachineMove &Move = Moves[i]; + unsigned LabelID = Move.getLabelID(); + + if (LabelID) { + LabelID = MMI->MappedLabel(LabelID); + + // Throw out move if the label is invalid. + if (!LabelID) continue; + } + + intptr_t LabelPtr = 0; + if (LabelID) LabelPtr = JCE->getLabelAddress(LabelID); + + const MachineLocation &Dst = Move.getDestination(); + const MachineLocation &Src = Move.getSource(); + + // Advance row if new location. + if (BaseLabelPtr && LabelID && (BaseLabelID != LabelID || !IsLocal)) { + JCE->emitByte(dwarf::DW_CFA_advance_loc4); + JCE->emitInt32(LabelPtr - BaseLabelPtr); + + BaseLabelID = LabelID; + BaseLabelPtr = LabelPtr; + IsLocal = true; + } + + // If advancing cfa. + if (Dst.isReg() && Dst.getReg() == MachineLocation::VirtualFP) { + if (!Src.isReg()) { + if (Src.getReg() == MachineLocation::VirtualFP) { + JCE->emitByte(dwarf::DW_CFA_def_cfa_offset); + } else { + JCE->emitByte(dwarf::DW_CFA_def_cfa); + JCE->emitULEB128Bytes(RI->getDwarfRegNum(Src.getReg(), true)); + } + + JCE->emitULEB128Bytes(-Src.getOffset()); + } else { + llvm_unreachable("Machine move not supported yet."); + } + } else if (Src.isReg() && + Src.getReg() == MachineLocation::VirtualFP) { + if (Dst.isReg()) { + JCE->emitByte(dwarf::DW_CFA_def_cfa_register); + JCE->emitULEB128Bytes(RI->getDwarfRegNum(Dst.getReg(), true)); + } else { + llvm_unreachable("Machine move not supported yet."); + } + } else { + unsigned Reg = RI->getDwarfRegNum(Src.getReg(), true); + int Offset = Dst.getOffset() / stackGrowth; + + if (Offset < 0) { + JCE->emitByte(dwarf::DW_CFA_offset_extended_sf); + JCE->emitULEB128Bytes(Reg); + JCE->emitSLEB128Bytes(Offset); + } else if (Reg < 64) { + JCE->emitByte(dwarf::DW_CFA_offset + Reg); + JCE->emitULEB128Bytes(Offset); + } else { + JCE->emitByte(dwarf::DW_CFA_offset_extended); + JCE->emitULEB128Bytes(Reg); + JCE->emitULEB128Bytes(Offset); + } + } + } +} + +/// SharedTypeIds - How many leading type ids two landing pads have in common. +static unsigned SharedTypeIds(const LandingPadInfo *L, + const LandingPadInfo *R) { + const std::vector &LIds = L->TypeIds, &RIds = R->TypeIds; + unsigned LSize = LIds.size(), RSize = RIds.size(); + unsigned MinSize = LSize < RSize ? LSize : RSize; + unsigned Count = 0; + + for (; Count != MinSize; ++Count) + if (LIds[Count] != RIds[Count]) + return Count; + + return Count; +} + + +/// PadLT - Order landing pads lexicographically by type id. +static bool PadLT(const LandingPadInfo *L, const LandingPadInfo *R) { + const std::vector &LIds = L->TypeIds, &RIds = R->TypeIds; + unsigned LSize = LIds.size(), RSize = RIds.size(); + unsigned MinSize = LSize < RSize ? LSize : RSize; + + for (unsigned i = 0; i != MinSize; ++i) + if (LIds[i] != RIds[i]) + return LIds[i] < RIds[i]; + + return LSize < RSize; +} + +namespace { + +struct KeyInfo { + static inline unsigned getEmptyKey() { return -1U; } + static inline unsigned getTombstoneKey() { return -2U; } + static unsigned getHashValue(const unsigned &Key) { return Key; } + static bool isEqual(unsigned LHS, unsigned RHS) { return LHS == RHS; } + static bool isPod() { return true; } +}; + +/// ActionEntry - Structure describing an entry in the actions table. +struct ActionEntry { + int ValueForTypeID; // The value to write - may not be equal to the type id. + int NextAction; + struct ActionEntry *Previous; +}; + +/// PadRange - Structure holding a try-range and the associated landing pad. +struct PadRange { + // The index of the landing pad. + unsigned PadIndex; + // The index of the begin and end labels in the landing pad's label lists. + unsigned RangeIndex; +}; + +typedef DenseMap RangeMapType; + +/// CallSiteEntry - Structure describing an entry in the call-site table. +struct CallSiteEntry { + unsigned BeginLabel; // zero indicates the start of the function. + unsigned EndLabel; // zero indicates the end of the function. + unsigned PadLabel; // zero indicates that there is no landing pad. + unsigned Action; +}; + +} + +unsigned char* JITDwarfEmitter::EmitExceptionTable(MachineFunction* MF, + unsigned char* StartFunction, + unsigned char* EndFunction) const { + assert(MMI && "MachineModuleInfo not registered!"); + + // Map all labels and get rid of any dead landing pads. + MMI->TidyLandingPads(); + + const std::vector &TypeInfos = MMI->getTypeInfos(); + const std::vector &FilterIds = MMI->getFilterIds(); + const std::vector &PadInfos = MMI->getLandingPads(); + if (PadInfos.empty()) return 0; + + // Sort the landing pads in order of their type ids. This is used to fold + // duplicate actions. + SmallVector LandingPads; + LandingPads.reserve(PadInfos.size()); + for (unsigned i = 0, N = PadInfos.size(); i != N; ++i) + LandingPads.push_back(&PadInfos[i]); + std::sort(LandingPads.begin(), LandingPads.end(), PadLT); + + // Negative type ids index into FilterIds, positive type ids index into + // TypeInfos. The value written for a positive type id is just the type + // id itself. For a negative type id, however, the value written is the + // (negative) byte offset of the corresponding FilterIds entry. The byte + // offset is usually equal to the type id, because the FilterIds entries + // are written using a variable width encoding which outputs one byte per + // entry as long as the value written is not too large, but can differ. + // This kind of complication does not occur for positive type ids because + // type infos are output using a fixed width encoding. + // FilterOffsets[i] holds the byte offset corresponding to FilterIds[i]. + SmallVector FilterOffsets; + FilterOffsets.reserve(FilterIds.size()); + int Offset = -1; + for(std::vector::const_iterator I = FilterIds.begin(), + E = FilterIds.end(); I != E; ++I) { + FilterOffsets.push_back(Offset); + Offset -= MCAsmInfo::getULEB128Size(*I); + } + + // Compute the actions table and gather the first action index for each + // landing pad site. + SmallVector Actions; + SmallVector FirstActions; + FirstActions.reserve(LandingPads.size()); + + int FirstAction = 0; + unsigned SizeActions = 0; + for (unsigned i = 0, N = LandingPads.size(); i != N; ++i) { + const LandingPadInfo *LP = LandingPads[i]; + const std::vector &TypeIds = LP->TypeIds; + const unsigned NumShared = i ? SharedTypeIds(LP, LandingPads[i-1]) : 0; + unsigned SizeSiteActions = 0; + + if (NumShared < TypeIds.size()) { + unsigned SizeAction = 0; + ActionEntry *PrevAction = 0; + + if (NumShared) { + const unsigned SizePrevIds = LandingPads[i-1]->TypeIds.size(); + assert(Actions.size()); + PrevAction = &Actions.back(); + SizeAction = MCAsmInfo::getSLEB128Size(PrevAction->NextAction) + + MCAsmInfo::getSLEB128Size(PrevAction->ValueForTypeID); + for (unsigned j = NumShared; j != SizePrevIds; ++j) { + SizeAction -= MCAsmInfo::getSLEB128Size(PrevAction->ValueForTypeID); + SizeAction += -PrevAction->NextAction; + PrevAction = PrevAction->Previous; + } + } + + // Compute the actions. + for (unsigned I = NumShared, M = TypeIds.size(); I != M; ++I) { + int TypeID = TypeIds[I]; + assert(-1-TypeID < (int)FilterOffsets.size() && "Unknown filter id!"); + int ValueForTypeID = TypeID < 0 ? FilterOffsets[-1 - TypeID] : TypeID; + unsigned SizeTypeID = MCAsmInfo::getSLEB128Size(ValueForTypeID); + + int NextAction = SizeAction ? -(SizeAction + SizeTypeID) : 0; + SizeAction = SizeTypeID + MCAsmInfo::getSLEB128Size(NextAction); + SizeSiteActions += SizeAction; + + ActionEntry Action = {ValueForTypeID, NextAction, PrevAction}; + Actions.push_back(Action); + + PrevAction = &Actions.back(); + } + + // Record the first action of the landing pad site. + FirstAction = SizeActions + SizeSiteActions - SizeAction + 1; + } // else identical - re-use previous FirstAction + + FirstActions.push_back(FirstAction); + + // Compute this sites contribution to size. + SizeActions += SizeSiteActions; + } + + // Compute the call-site table. Entries must be ordered by address. + SmallVector CallSites; + + RangeMapType PadMap; + for (unsigned i = 0, N = LandingPads.size(); i != N; ++i) { + const LandingPadInfo *LandingPad = LandingPads[i]; + for (unsigned j=0, E = LandingPad->BeginLabels.size(); j != E; ++j) { + unsigned BeginLabel = LandingPad->BeginLabels[j]; + assert(!PadMap.count(BeginLabel) && "Duplicate landing pad labels!"); + PadRange P = { i, j }; + PadMap[BeginLabel] = P; + } + } + + bool MayThrow = false; + unsigned LastLabel = 0; + for (MachineFunction::const_iterator I = MF->begin(), E = MF->end(); + I != E; ++I) { + for (MachineBasicBlock::const_iterator MI = I->begin(), E = I->end(); + MI != E; ++MI) { + if (!MI->isLabel()) { + MayThrow |= MI->getDesc().isCall(); + continue; + } + + unsigned BeginLabel = MI->getOperand(0).getImm(); + assert(BeginLabel && "Invalid label!"); + + if (BeginLabel == LastLabel) + MayThrow = false; + + RangeMapType::iterator L = PadMap.find(BeginLabel); + + if (L == PadMap.end()) + continue; + + PadRange P = L->second; + const LandingPadInfo *LandingPad = LandingPads[P.PadIndex]; + + assert(BeginLabel == LandingPad->BeginLabels[P.RangeIndex] && + "Inconsistent landing pad map!"); + + // If some instruction between the previous try-range and this one may + // throw, create a call-site entry with no landing pad for the region + // between the try-ranges. + if (MayThrow) { + CallSiteEntry Site = {LastLabel, BeginLabel, 0, 0}; + CallSites.push_back(Site); + } + + LastLabel = LandingPad->EndLabels[P.RangeIndex]; + CallSiteEntry Site = {BeginLabel, LastLabel, + LandingPad->LandingPadLabel, FirstActions[P.PadIndex]}; + + assert(Site.BeginLabel && Site.EndLabel && Site.PadLabel && + "Invalid landing pad!"); + + // Try to merge with the previous call-site. + if (CallSites.size()) { + CallSiteEntry &Prev = CallSites.back(); + if (Site.PadLabel == Prev.PadLabel && Site.Action == Prev.Action) { + // Extend the range of the previous entry. + Prev.EndLabel = Site.EndLabel; + continue; + } + } + + // Otherwise, create a new call-site. + CallSites.push_back(Site); + } + } + // If some instruction between the previous try-range and the end of the + // function may throw, create a call-site entry with no landing pad for the + // region following the try-range. + if (MayThrow) { + CallSiteEntry Site = {LastLabel, 0, 0, 0}; + CallSites.push_back(Site); + } + + // Final tallies. + unsigned SizeSites = CallSites.size() * (sizeof(int32_t) + // Site start. + sizeof(int32_t) + // Site length. + sizeof(int32_t)); // Landing pad. + for (unsigned i = 0, e = CallSites.size(); i < e; ++i) + SizeSites += MCAsmInfo::getULEB128Size(CallSites[i].Action); + + unsigned SizeTypes = TypeInfos.size() * TD->getPointerSize(); + + unsigned TypeOffset = sizeof(int8_t) + // Call site format + // Call-site table length + MCAsmInfo::getULEB128Size(SizeSites) + + SizeSites + SizeActions + SizeTypes; + + // Begin the exception table. + JCE->emitAlignmentWithFill(4, 0); + // Asm->EOL("Padding"); + + unsigned char* DwarfExceptionTable = (unsigned char*)JCE->getCurrentPCValue(); + + // Emit the header. + JCE->emitByte(dwarf::DW_EH_PE_omit); + // Asm->EOL("LPStart format (DW_EH_PE_omit)"); + JCE->emitByte(dwarf::DW_EH_PE_absptr); + // Asm->EOL("TType format (DW_EH_PE_absptr)"); + JCE->emitULEB128Bytes(TypeOffset); + // Asm->EOL("TType base offset"); + JCE->emitByte(dwarf::DW_EH_PE_udata4); + // Asm->EOL("Call site format (DW_EH_PE_udata4)"); + JCE->emitULEB128Bytes(SizeSites); + // Asm->EOL("Call-site table length"); + + // Emit the landing pad site information. + for (unsigned i = 0; i < CallSites.size(); ++i) { + CallSiteEntry &S = CallSites[i]; + intptr_t BeginLabelPtr = 0; + intptr_t EndLabelPtr = 0; + + if (!S.BeginLabel) { + BeginLabelPtr = (intptr_t)StartFunction; + JCE->emitInt32(0); + } else { + BeginLabelPtr = JCE->getLabelAddress(S.BeginLabel); + JCE->emitInt32(BeginLabelPtr - (intptr_t)StartFunction); + } + + // Asm->EOL("Region start"); + + if (!S.EndLabel) { + EndLabelPtr = (intptr_t)EndFunction; + JCE->emitInt32((intptr_t)EndFunction - BeginLabelPtr); + } else { + EndLabelPtr = JCE->getLabelAddress(S.EndLabel); + JCE->emitInt32(EndLabelPtr - BeginLabelPtr); + } + //Asm->EOL("Region length"); + + if (!S.PadLabel) { + JCE->emitInt32(0); + } else { + unsigned PadLabelPtr = JCE->getLabelAddress(S.PadLabel); + JCE->emitInt32(PadLabelPtr - (intptr_t)StartFunction); + } + // Asm->EOL("Landing pad"); + + JCE->emitULEB128Bytes(S.Action); + // Asm->EOL("Action"); + } + + // Emit the actions. + for (unsigned I = 0, N = Actions.size(); I != N; ++I) { + ActionEntry &Action = Actions[I]; + + JCE->emitSLEB128Bytes(Action.ValueForTypeID); + //Asm->EOL("TypeInfo index"); + JCE->emitSLEB128Bytes(Action.NextAction); + //Asm->EOL("Next action"); + } + + // Emit the type ids. + for (unsigned M = TypeInfos.size(); M; --M) { + GlobalVariable *GV = TypeInfos[M - 1]; + + if (GV) { + if (TD->getPointerSize() == sizeof(int32_t)) + JCE->emitInt32((intptr_t)Jit.getOrEmitGlobalVariable(GV)); + else + JCE->emitInt64((intptr_t)Jit.getOrEmitGlobalVariable(GV)); + } else { + if (TD->getPointerSize() == sizeof(int32_t)) + JCE->emitInt32(0); + else + JCE->emitInt64(0); + } + // Asm->EOL("TypeInfo"); + } + + // Emit the filter typeids. + for (unsigned j = 0, M = FilterIds.size(); j < M; ++j) { + unsigned TypeID = FilterIds[j]; + JCE->emitULEB128Bytes(TypeID); + //Asm->EOL("Filter TypeInfo index"); + } + + JCE->emitAlignmentWithFill(4, 0); + + return DwarfExceptionTable; +} + +unsigned char* +JITDwarfEmitter::EmitCommonEHFrame(const Function* Personality) const { + unsigned PointerSize = TD->getPointerSize(); + int stackGrowth = stackGrowthDirection == TargetFrameInfo::StackGrowsUp ? + PointerSize : -PointerSize; + + unsigned char* StartCommonPtr = (unsigned char*)JCE->getCurrentPCValue(); + // EH Common Frame header + JCE->allocateSpace(4, 0); + unsigned char* FrameCommonBeginPtr = (unsigned char*)JCE->getCurrentPCValue(); + JCE->emitInt32((int)0); + JCE->emitByte(dwarf::DW_CIE_VERSION); + JCE->emitString(Personality ? "zPLR" : "zR"); + JCE->emitULEB128Bytes(1); + JCE->emitSLEB128Bytes(stackGrowth); + JCE->emitByte(RI->getDwarfRegNum(RI->getRARegister(), true)); + + if (Personality) { + // Augmentation Size: 3 small ULEBs of one byte each, and the personality + // function which size is PointerSize. + JCE->emitULEB128Bytes(3 + PointerSize); + + // We set the encoding of the personality as direct encoding because we use + // the function pointer. The encoding is not relative because the current + // PC value may be bigger than the personality function pointer. + if (PointerSize == 4) { + JCE->emitByte(dwarf::DW_EH_PE_sdata4); + JCE->emitInt32(((intptr_t)Jit.getPointerToGlobal(Personality))); + } else { + JCE->emitByte(dwarf::DW_EH_PE_sdata8); + JCE->emitInt64(((intptr_t)Jit.getPointerToGlobal(Personality))); + } + + JCE->emitULEB128Bytes(dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4); + JCE->emitULEB128Bytes(dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4); + } else { + JCE->emitULEB128Bytes(1); + JCE->emitULEB128Bytes(dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4); + } + + std::vector Moves; + RI->getInitialFrameState(Moves); + EmitFrameMoves(0, Moves); + + JCE->emitAlignmentWithFill(PointerSize, dwarf::DW_CFA_nop); + + JCE->emitInt32At((uintptr_t*)StartCommonPtr, + (uintptr_t)((unsigned char*)JCE->getCurrentPCValue() - + FrameCommonBeginPtr)); + + return StartCommonPtr; +} + + +unsigned char* +JITDwarfEmitter::EmitEHFrame(const Function* Personality, + unsigned char* StartCommonPtr, + unsigned char* StartFunction, + unsigned char* EndFunction, + unsigned char* ExceptionTable) const { + unsigned PointerSize = TD->getPointerSize(); + + // EH frame header. + unsigned char* StartEHPtr = (unsigned char*)JCE->getCurrentPCValue(); + JCE->allocateSpace(4, 0); + unsigned char* FrameBeginPtr = (unsigned char*)JCE->getCurrentPCValue(); + // FDE CIE Offset + JCE->emitInt32(FrameBeginPtr - StartCommonPtr); + JCE->emitInt32(StartFunction - (unsigned char*)JCE->getCurrentPCValue()); + JCE->emitInt32(EndFunction - StartFunction); + + // If there is a personality and landing pads then point to the language + // specific data area in the exception table. + if (Personality) { + JCE->emitULEB128Bytes(PointerSize == 4 ? 4 : 8); + + if (PointerSize == 4) { + if (!MMI->getLandingPads().empty()) + JCE->emitInt32(ExceptionTable-(unsigned char*)JCE->getCurrentPCValue()); + else + JCE->emitInt32((int)0); + } else { + if (!MMI->getLandingPads().empty()) + JCE->emitInt64(ExceptionTable-(unsigned char*)JCE->getCurrentPCValue()); + else + JCE->emitInt64((int)0); + } + } else { + JCE->emitULEB128Bytes(0); + } + + // Indicate locations of function specific callee saved registers in + // frame. + EmitFrameMoves((intptr_t)StartFunction, MMI->getFrameMoves()); + + JCE->emitAlignmentWithFill(PointerSize, dwarf::DW_CFA_nop); + + // Indicate the size of the table + JCE->emitInt32At((uintptr_t*)StartEHPtr, + (uintptr_t)((unsigned char*)JCE->getCurrentPCValue() - + StartEHPtr)); + + // Double zeroes for the unwind runtime + if (PointerSize == 8) { + JCE->emitInt64(0); + JCE->emitInt64(0); + } else { + JCE->emitInt32(0); + JCE->emitInt32(0); + } + + return StartEHPtr; +} + +unsigned JITDwarfEmitter::GetDwarfTableSizeInBytes(MachineFunction& F, + JITCodeEmitter& jce, + unsigned char* StartFunction, + unsigned char* EndFunction) { + const TargetMachine& TM = F.getTarget(); + TD = TM.getTargetData(); + stackGrowthDirection = TM.getFrameInfo()->getStackGrowthDirection(); + RI = TM.getRegisterInfo(); + JCE = &jce; + unsigned FinalSize = 0; + + FinalSize += GetExceptionTableSizeInBytes(&F); + + const std::vector Personalities = MMI->getPersonalities(); + FinalSize += + GetCommonEHFrameSizeInBytes(Personalities[MMI->getPersonalityIndex()]); + + FinalSize += GetEHFrameSizeInBytes(Personalities[MMI->getPersonalityIndex()], + StartFunction); + + return FinalSize; +} + +/// RoundUpToAlign - Add the specified alignment to FinalSize and returns +/// the new value. +static unsigned RoundUpToAlign(unsigned FinalSize, unsigned Alignment) { + if (Alignment == 0) Alignment = 1; + // Since we do not know where the buffer will be allocated, be pessimistic. + return FinalSize + Alignment; +} + +unsigned +JITDwarfEmitter::GetEHFrameSizeInBytes(const Function* Personality, + unsigned char* StartFunction) const { + unsigned PointerSize = TD->getPointerSize(); + unsigned FinalSize = 0; + // EH frame header. + FinalSize += PointerSize; + // FDE CIE Offset + FinalSize += 3 * PointerSize; + // If there is a personality and landing pads then point to the language + // specific data area in the exception table. + if (Personality) { + FinalSize += MCAsmInfo::getULEB128Size(4); + FinalSize += PointerSize; + } else { + FinalSize += MCAsmInfo::getULEB128Size(0); + } + + // Indicate locations of function specific callee saved registers in + // frame. + FinalSize += GetFrameMovesSizeInBytes((intptr_t)StartFunction, + MMI->getFrameMoves()); + + FinalSize = RoundUpToAlign(FinalSize, 4); + + // Double zeroes for the unwind runtime + FinalSize += 2 * PointerSize; + + return FinalSize; +} + +unsigned JITDwarfEmitter::GetCommonEHFrameSizeInBytes(const Function* Personality) + const { + + unsigned PointerSize = TD->getPointerSize(); + int stackGrowth = stackGrowthDirection == TargetFrameInfo::StackGrowsUp ? + PointerSize : -PointerSize; + unsigned FinalSize = 0; + // EH Common Frame header + FinalSize += PointerSize; + FinalSize += 4; + FinalSize += 1; + FinalSize += Personality ? 5 : 3; // "zPLR" or "zR" + FinalSize += MCAsmInfo::getULEB128Size(1); + FinalSize += MCAsmInfo::getSLEB128Size(stackGrowth); + FinalSize += 1; + + if (Personality) { + FinalSize += MCAsmInfo::getULEB128Size(7); + + // Encoding + FinalSize+= 1; + //Personality + FinalSize += PointerSize; + + FinalSize += MCAsmInfo::getULEB128Size(dwarf::DW_EH_PE_pcrel); + FinalSize += MCAsmInfo::getULEB128Size(dwarf::DW_EH_PE_pcrel); + + } else { + FinalSize += MCAsmInfo::getULEB128Size(1); + FinalSize += MCAsmInfo::getULEB128Size(dwarf::DW_EH_PE_pcrel); + } + + std::vector Moves; + RI->getInitialFrameState(Moves); + FinalSize += GetFrameMovesSizeInBytes(0, Moves); + FinalSize = RoundUpToAlign(FinalSize, 4); + return FinalSize; +} + +unsigned +JITDwarfEmitter::GetFrameMovesSizeInBytes(intptr_t BaseLabelPtr, + const std::vector &Moves) const { + unsigned PointerSize = TD->getPointerSize(); + int stackGrowth = stackGrowthDirection == TargetFrameInfo::StackGrowsUp ? + PointerSize : -PointerSize; + bool IsLocal = BaseLabelPtr; + unsigned FinalSize = 0; + + for (unsigned i = 0, N = Moves.size(); i < N; ++i) { + const MachineMove &Move = Moves[i]; + unsigned LabelID = Move.getLabelID(); + + if (LabelID) { + LabelID = MMI->MappedLabel(LabelID); + + // Throw out move if the label is invalid. + if (!LabelID) continue; + } + + intptr_t LabelPtr = 0; + if (LabelID) LabelPtr = JCE->getLabelAddress(LabelID); + + const MachineLocation &Dst = Move.getDestination(); + const MachineLocation &Src = Move.getSource(); + + // Advance row if new location. + if (BaseLabelPtr && LabelID && (BaseLabelPtr != LabelPtr || !IsLocal)) { + FinalSize++; + FinalSize += PointerSize; + BaseLabelPtr = LabelPtr; + IsLocal = true; + } + + // If advancing cfa. + if (Dst.isReg() && Dst.getReg() == MachineLocation::VirtualFP) { + if (!Src.isReg()) { + if (Src.getReg() == MachineLocation::VirtualFP) { + ++FinalSize; + } else { + ++FinalSize; + unsigned RegNum = RI->getDwarfRegNum(Src.getReg(), true); + FinalSize += MCAsmInfo::getULEB128Size(RegNum); + } + + int Offset = -Src.getOffset(); + + FinalSize += MCAsmInfo::getULEB128Size(Offset); + } else { + llvm_unreachable("Machine move no supported yet."); + } + } else if (Src.isReg() && + Src.getReg() == MachineLocation::VirtualFP) { + if (Dst.isReg()) { + ++FinalSize; + unsigned RegNum = RI->getDwarfRegNum(Dst.getReg(), true); + FinalSize += MCAsmInfo::getULEB128Size(RegNum); + } else { + llvm_unreachable("Machine move no supported yet."); + } + } else { + unsigned Reg = RI->getDwarfRegNum(Src.getReg(), true); + int Offset = Dst.getOffset() / stackGrowth; + + if (Offset < 0) { + ++FinalSize; + FinalSize += MCAsmInfo::getULEB128Size(Reg); + FinalSize += MCAsmInfo::getSLEB128Size(Offset); + } else if (Reg < 64) { + ++FinalSize; + FinalSize += MCAsmInfo::getULEB128Size(Offset); + } else { + ++FinalSize; + FinalSize += MCAsmInfo::getULEB128Size(Reg); + FinalSize += MCAsmInfo::getULEB128Size(Offset); + } + } + } + return FinalSize; +} + +unsigned +JITDwarfEmitter::GetExceptionTableSizeInBytes(MachineFunction* MF) const { + unsigned FinalSize = 0; + + // Map all labels and get rid of any dead landing pads. + MMI->TidyLandingPads(); + + const std::vector &TypeInfos = MMI->getTypeInfos(); + const std::vector &FilterIds = MMI->getFilterIds(); + const std::vector &PadInfos = MMI->getLandingPads(); + if (PadInfos.empty()) return 0; + + // Sort the landing pads in order of their type ids. This is used to fold + // duplicate actions. + SmallVector LandingPads; + LandingPads.reserve(PadInfos.size()); + for (unsigned i = 0, N = PadInfos.size(); i != N; ++i) + LandingPads.push_back(&PadInfos[i]); + std::sort(LandingPads.begin(), LandingPads.end(), PadLT); + + // Negative type ids index into FilterIds, positive type ids index into + // TypeInfos. The value written for a positive type id is just the type + // id itself. For a negative type id, however, the value written is the + // (negative) byte offset of the corresponding FilterIds entry. The byte + // offset is usually equal to the type id, because the FilterIds entries + // are written using a variable width encoding which outputs one byte per + // entry as long as the value written is not too large, but can differ. + // This kind of complication does not occur for positive type ids because + // type infos are output using a fixed width encoding. + // FilterOffsets[i] holds the byte offset corresponding to FilterIds[i]. + SmallVector FilterOffsets; + FilterOffsets.reserve(FilterIds.size()); + int Offset = -1; + for(std::vector::const_iterator I = FilterIds.begin(), + E = FilterIds.end(); I != E; ++I) { + FilterOffsets.push_back(Offset); + Offset -= MCAsmInfo::getULEB128Size(*I); + } + + // Compute the actions table and gather the first action index for each + // landing pad site. + SmallVector Actions; + SmallVector FirstActions; + FirstActions.reserve(LandingPads.size()); + + int FirstAction = 0; + unsigned SizeActions = 0; + for (unsigned i = 0, N = LandingPads.size(); i != N; ++i) { + const LandingPadInfo *LP = LandingPads[i]; + const std::vector &TypeIds = LP->TypeIds; + const unsigned NumShared = i ? SharedTypeIds(LP, LandingPads[i-1]) : 0; + unsigned SizeSiteActions = 0; + + if (NumShared < TypeIds.size()) { + unsigned SizeAction = 0; + ActionEntry *PrevAction = 0; + + if (NumShared) { + const unsigned SizePrevIds = LandingPads[i-1]->TypeIds.size(); + assert(Actions.size()); + PrevAction = &Actions.back(); + SizeAction = MCAsmInfo::getSLEB128Size(PrevAction->NextAction) + + MCAsmInfo::getSLEB128Size(PrevAction->ValueForTypeID); + for (unsigned j = NumShared; j != SizePrevIds; ++j) { + SizeAction -= MCAsmInfo::getSLEB128Size(PrevAction->ValueForTypeID); + SizeAction += -PrevAction->NextAction; + PrevAction = PrevAction->Previous; + } + } + + // Compute the actions. + for (unsigned I = NumShared, M = TypeIds.size(); I != M; ++I) { + int TypeID = TypeIds[I]; + assert(-1-TypeID < (int)FilterOffsets.size() && "Unknown filter id!"); + int ValueForTypeID = TypeID < 0 ? FilterOffsets[-1 - TypeID] : TypeID; + unsigned SizeTypeID = MCAsmInfo::getSLEB128Size(ValueForTypeID); + + int NextAction = SizeAction ? -(SizeAction + SizeTypeID) : 0; + SizeAction = SizeTypeID + MCAsmInfo::getSLEB128Size(NextAction); + SizeSiteActions += SizeAction; + + ActionEntry Action = {ValueForTypeID, NextAction, PrevAction}; + Actions.push_back(Action); + + PrevAction = &Actions.back(); + } + + // Record the first action of the landing pad site. + FirstAction = SizeActions + SizeSiteActions - SizeAction + 1; + } // else identical - re-use previous FirstAction + + FirstActions.push_back(FirstAction); + + // Compute this sites contribution to size. + SizeActions += SizeSiteActions; + } + + // Compute the call-site table. Entries must be ordered by address. + SmallVector CallSites; + + RangeMapType PadMap; + for (unsigned i = 0, N = LandingPads.size(); i != N; ++i) { + const LandingPadInfo *LandingPad = LandingPads[i]; + for (unsigned j=0, E = LandingPad->BeginLabels.size(); j != E; ++j) { + unsigned BeginLabel = LandingPad->BeginLabels[j]; + assert(!PadMap.count(BeginLabel) && "Duplicate landing pad labels!"); + PadRange P = { i, j }; + PadMap[BeginLabel] = P; + } + } + + bool MayThrow = false; + unsigned LastLabel = 0; + for (MachineFunction::const_iterator I = MF->begin(), E = MF->end(); + I != E; ++I) { + for (MachineBasicBlock::const_iterator MI = I->begin(), E = I->end(); + MI != E; ++MI) { + if (!MI->isLabel()) { + MayThrow |= MI->getDesc().isCall(); + continue; + } + + unsigned BeginLabel = MI->getOperand(0).getImm(); + assert(BeginLabel && "Invalid label!"); + + if (BeginLabel == LastLabel) + MayThrow = false; + + RangeMapType::iterator L = PadMap.find(BeginLabel); + + if (L == PadMap.end()) + continue; + + PadRange P = L->second; + const LandingPadInfo *LandingPad = LandingPads[P.PadIndex]; + + assert(BeginLabel == LandingPad->BeginLabels[P.RangeIndex] && + "Inconsistent landing pad map!"); + + // If some instruction between the previous try-range and this one may + // throw, create a call-site entry with no landing pad for the region + // between the try-ranges. + if (MayThrow) { + CallSiteEntry Site = {LastLabel, BeginLabel, 0, 0}; + CallSites.push_back(Site); + } + + LastLabel = LandingPad->EndLabels[P.RangeIndex]; + CallSiteEntry Site = {BeginLabel, LastLabel, + LandingPad->LandingPadLabel, FirstActions[P.PadIndex]}; + + assert(Site.BeginLabel && Site.EndLabel && Site.PadLabel && + "Invalid landing pad!"); + + // Try to merge with the previous call-site. + if (CallSites.size()) { + CallSiteEntry &Prev = CallSites.back(); + if (Site.PadLabel == Prev.PadLabel && Site.Action == Prev.Action) { + // Extend the range of the previous entry. + Prev.EndLabel = Site.EndLabel; + continue; + } + } + + // Otherwise, create a new call-site. + CallSites.push_back(Site); + } + } + // If some instruction between the previous try-range and the end of the + // function may throw, create a call-site entry with no landing pad for the + // region following the try-range. + if (MayThrow) { + CallSiteEntry Site = {LastLabel, 0, 0, 0}; + CallSites.push_back(Site); + } + + // Final tallies. + unsigned SizeSites = CallSites.size() * (sizeof(int32_t) + // Site start. + sizeof(int32_t) + // Site length. + sizeof(int32_t)); // Landing pad. + for (unsigned i = 0, e = CallSites.size(); i < e; ++i) + SizeSites += MCAsmInfo::getULEB128Size(CallSites[i].Action); + + unsigned SizeTypes = TypeInfos.size() * TD->getPointerSize(); + + unsigned TypeOffset = sizeof(int8_t) + // Call site format + // Call-site table length + MCAsmInfo::getULEB128Size(SizeSites) + + SizeSites + SizeActions + SizeTypes; + + unsigned TotalSize = sizeof(int8_t) + // LPStart format + sizeof(int8_t) + // TType format + MCAsmInfo::getULEB128Size(TypeOffset) + // TType base offset + TypeOffset; + + unsigned SizeAlign = (4 - TotalSize) & 3; + + // Begin the exception table. + FinalSize = RoundUpToAlign(FinalSize, 4); + for (unsigned i = 0; i != SizeAlign; ++i) { + ++FinalSize; + } + + unsigned PointerSize = TD->getPointerSize(); + + // Emit the header. + ++FinalSize; + // Asm->EOL("LPStart format (DW_EH_PE_omit)"); + ++FinalSize; + // Asm->EOL("TType format (DW_EH_PE_absptr)"); + ++FinalSize; + // Asm->EOL("TType base offset"); + ++FinalSize; + // Asm->EOL("Call site format (DW_EH_PE_udata4)"); + ++FinalSize; + // Asm->EOL("Call-site table length"); + + // Emit the landing pad site information. + for (unsigned i = 0; i < CallSites.size(); ++i) { + CallSiteEntry &S = CallSites[i]; + + // Asm->EOL("Region start"); + FinalSize += PointerSize; + + //Asm->EOL("Region length"); + FinalSize += PointerSize; + + // Asm->EOL("Landing pad"); + FinalSize += PointerSize; + + FinalSize += MCAsmInfo::getULEB128Size(S.Action); + // Asm->EOL("Action"); + } + + // Emit the actions. + for (unsigned I = 0, N = Actions.size(); I != N; ++I) { + ActionEntry &Action = Actions[I]; + + //Asm->EOL("TypeInfo index"); + FinalSize += MCAsmInfo::getSLEB128Size(Action.ValueForTypeID); + //Asm->EOL("Next action"); + FinalSize += MCAsmInfo::getSLEB128Size(Action.NextAction); + } + + // Emit the type ids. + for (unsigned M = TypeInfos.size(); M; --M) { + // Asm->EOL("TypeInfo"); + FinalSize += PointerSize; + } + + // Emit the filter typeids. + for (unsigned j = 0, M = FilterIds.size(); j < M; ++j) { + unsigned TypeID = FilterIds[j]; + FinalSize += MCAsmInfo::getULEB128Size(TypeID); + //Asm->EOL("Filter TypeInfo index"); + } + + FinalSize = RoundUpToAlign(FinalSize, 4); + + return FinalSize; +} diff --git a/libclamav/c++/llvm/lib/ExecutionEngine/JIT/JITDwarfEmitter.h b/libclamav/c++/llvm/lib/ExecutionEngine/JIT/JITDwarfEmitter.h new file mode 100644 index 000000000..e627550d6 --- /dev/null +++ b/libclamav/c++/llvm/lib/ExecutionEngine/JIT/JITDwarfEmitter.h @@ -0,0 +1,87 @@ +//===------ JITDwarfEmitter.h - Write dwarf tables into memory ------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines a JITDwarfEmitter object that is used by the JIT to +// write dwarf tables to memory. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_EXECUTION_ENGINE_JIT_DWARFEMITTER_H +#define LLVM_EXECUTION_ENGINE_JIT_DWARFEMITTER_H + +namespace llvm { + +class Function; +class JITCodeEmitter; +class MachineFunction; +class MachineModuleInfo; +class MachineMove; +class TargetData; +class TargetMachine; +class TargetRegisterInfo; + +class JITDwarfEmitter { + const TargetData* TD; + JITCodeEmitter* JCE; + const TargetRegisterInfo* RI; + MachineModuleInfo* MMI; + JIT& Jit; + bool stackGrowthDirection; + + unsigned char* EmitExceptionTable(MachineFunction* MF, + unsigned char* StartFunction, + unsigned char* EndFunction) const; + + void EmitFrameMoves(intptr_t BaseLabelPtr, + const std::vector &Moves) const; + + unsigned char* EmitCommonEHFrame(const Function* Personality) const; + + unsigned char* EmitEHFrame(const Function* Personality, + unsigned char* StartBufferPtr, + unsigned char* StartFunction, + unsigned char* EndFunction, + unsigned char* ExceptionTable) const; + + unsigned GetExceptionTableSizeInBytes(MachineFunction* MF) const; + + unsigned + GetFrameMovesSizeInBytes(intptr_t BaseLabelPtr, + const std::vector &Moves) const; + + unsigned GetCommonEHFrameSizeInBytes(const Function* Personality) const; + + unsigned GetEHFrameSizeInBytes(const Function* Personality, + unsigned char* StartFunction) const; + +public: + + JITDwarfEmitter(JIT& jit); + + unsigned char* EmitDwarfTable(MachineFunction& F, + JITCodeEmitter& JCE, + unsigned char* StartFunction, + unsigned char* EndFunction, + unsigned char* &EHFramePtr); + + + unsigned GetDwarfTableSizeInBytes(MachineFunction& F, + JITCodeEmitter& JCE, + unsigned char* StartFunction, + unsigned char* EndFunction); + + void setModuleInfo(MachineModuleInfo* Info) { + MMI = Info; + } +}; + + +} // end namespace llvm + +#endif // LLVM_EXECUTION_ENGINE_JIT_DWARFEMITTER_H diff --git a/libclamav/c++/llvm/lib/ExecutionEngine/JIT/JITEmitter.cpp b/libclamav/c++/llvm/lib/ExecutionEngine/JIT/JITEmitter.cpp new file mode 100644 index 000000000..bbac762b4 --- /dev/null +++ b/libclamav/c++/llvm/lib/ExecutionEngine/JIT/JITEmitter.cpp @@ -0,0 +1,1566 @@ +//===-- JITEmitter.cpp - Write machine code to executable memory ----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines a MachineCodeEmitter object that is used by the JIT to +// write machine code to memory and remember where relocatable values are. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "jit" +#include "JIT.h" +#include "JITDebugRegisterer.h" +#include "JITDwarfEmitter.h" +#include "llvm/ADT/OwningPtr.h" +#include "llvm/Constants.h" +#include "llvm/Module.h" +#include "llvm/DerivedTypes.h" +#include "llvm/CodeGen/JITCodeEmitter.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineConstantPool.h" +#include "llvm/CodeGen/MachineJumpTableInfo.h" +#include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/CodeGen/MachineRelocation.h" +#include "llvm/ExecutionEngine/GenericValue.h" +#include "llvm/ExecutionEngine/JITEventListener.h" +#include "llvm/ExecutionEngine/JITMemoryManager.h" +#include "llvm/CodeGen/MachineCodeInfo.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetJITInfo.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetOptions.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/MutexGuard.h" +#include "llvm/Support/ValueHandle.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/System/Disassembler.h" +#include "llvm/System/Memory.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/ADT/ValueMap.h" +#include +#ifndef NDEBUG +#include +#endif +using namespace llvm; + +STATISTIC(NumBytes, "Number of bytes of machine code compiled"); +STATISTIC(NumRelos, "Number of relocations applied"); +STATISTIC(NumRetries, "Number of retries with more memory"); +static JIT *TheJIT = 0; + + +//===----------------------------------------------------------------------===// +// JIT lazy compilation code. +// +namespace { + class JITEmitter; + class JITResolverState; + + template + struct NoRAUWValueMapConfig : public ValueMapConfig { + typedef JITResolverState *ExtraData; + static void onRAUW(JITResolverState *, Value *Old, Value *New) { + assert(false && "The JIT doesn't know how to handle a" + " RAUW on a value it has emitted."); + } + }; + + struct CallSiteValueMapConfig : public NoRAUWValueMapConfig { + typedef JITResolverState *ExtraData; + static void onDelete(JITResolverState *JRS, Function *F); + }; + + class JITResolverState { + public: + typedef ValueMap > + FunctionToLazyStubMapTy; + typedef std::map > CallSiteToFunctionMapTy; + typedef ValueMap, + CallSiteValueMapConfig> FunctionToCallSitesMapTy; + typedef std::map, void*> GlobalToIndirectSymMapTy; + private: + /// FunctionToLazyStubMap - Keep track of the lazy stub created for a + /// particular function so that we can reuse them if necessary. + FunctionToLazyStubMapTy FunctionToLazyStubMap; + + /// CallSiteToFunctionMap - Keep track of the function that each lazy call + /// site corresponds to, and vice versa. + CallSiteToFunctionMapTy CallSiteToFunctionMap; + FunctionToCallSitesMapTy FunctionToCallSitesMap; + + /// GlobalToIndirectSymMap - Keep track of the indirect symbol created for a + /// particular GlobalVariable so that we can reuse them if necessary. + GlobalToIndirectSymMapTy GlobalToIndirectSymMap; + + public: + JITResolverState() : FunctionToLazyStubMap(this), + FunctionToCallSitesMap(this) {} + + FunctionToLazyStubMapTy& getFunctionToLazyStubMap( + const MutexGuard& locked) { + assert(locked.holds(TheJIT->lock)); + return FunctionToLazyStubMap; + } + + GlobalToIndirectSymMapTy& getGlobalToIndirectSymMap(const MutexGuard& locked) { + assert(locked.holds(TheJIT->lock)); + return GlobalToIndirectSymMap; + } + + pair LookupFunctionFromCallSite( + const MutexGuard &locked, void *CallSite) const { + assert(locked.holds(TheJIT->lock)); + + // The address given to us for the stub may not be exactly right, it might be + // a little bit after the stub. As such, use upper_bound to find it. + CallSiteToFunctionMapTy::const_iterator I = + CallSiteToFunctionMap.upper_bound(CallSite); + assert(I != CallSiteToFunctionMap.begin() && + "This is not a known call site!"); + --I; + return *I; + } + + void AddCallSite(const MutexGuard &locked, void *CallSite, Function *F) { + assert(locked.holds(TheJIT->lock)); + + bool Inserted = CallSiteToFunctionMap.insert( + std::make_pair(CallSite, F)).second; + (void)Inserted; + assert(Inserted && "Pair was already in CallSiteToFunctionMap"); + FunctionToCallSitesMap[F].insert(CallSite); + } + + // Returns the Function of the stub if a stub was erased, or NULL if there + // was no stub. This function uses the call-site->function map to find a + // relevant function, but asserts that only stubs and not other call sites + // will be passed in. + Function *EraseStub(const MutexGuard &locked, void *Stub) { + CallSiteToFunctionMapTy::iterator C2F_I = + CallSiteToFunctionMap.find(Stub); + if (C2F_I == CallSiteToFunctionMap.end()) { + // Not a stub. + return NULL; + } + + Function *const F = C2F_I->second; +#ifndef NDEBUG + void *RealStub = FunctionToLazyStubMap.lookup(F); + assert(RealStub == Stub && + "Call-site that wasn't a stub pass in to EraseStub"); +#endif + FunctionToLazyStubMap.erase(F); + CallSiteToFunctionMap.erase(C2F_I); + + // Remove the stub from the function->call-sites map, and remove the whole + // entry from the map if that was the last call site. + FunctionToCallSitesMapTy::iterator F2C_I = FunctionToCallSitesMap.find(F); + assert(F2C_I != FunctionToCallSitesMap.end() && + "FunctionToCallSitesMap broken"); + bool Erased = F2C_I->second.erase(Stub); + (void)Erased; + assert(Erased && "FunctionToCallSitesMap broken"); + if (F2C_I->second.empty()) + FunctionToCallSitesMap.erase(F2C_I); + + return F; + } + + void EraseAllCallSites(const MutexGuard &locked, Function *F) { + assert(locked.holds(TheJIT->lock)); + EraseAllCallSitesPrelocked(F); + } + void EraseAllCallSitesPrelocked(Function *F) { + FunctionToCallSitesMapTy::iterator F2C = FunctionToCallSitesMap.find(F); + if (F2C == FunctionToCallSitesMap.end()) + return; + for (SmallPtrSet::const_iterator I = F2C->second.begin(), + E = F2C->second.end(); I != E; ++I) { + bool Erased = CallSiteToFunctionMap.erase(*I); + (void)Erased; + assert(Erased && "Missing call site->function mapping"); + } + FunctionToCallSitesMap.erase(F2C); + } + }; + + /// JITResolver - Keep track of, and resolve, call sites for functions that + /// have not yet been compiled. + class JITResolver { + typedef JITResolverState::FunctionToLazyStubMapTy FunctionToLazyStubMapTy; + typedef JITResolverState::CallSiteToFunctionMapTy CallSiteToFunctionMapTy; + typedef JITResolverState::GlobalToIndirectSymMapTy GlobalToIndirectSymMapTy; + + /// LazyResolverFn - The target lazy resolver function that we actually + /// rewrite instructions to use. + TargetJITInfo::LazyResolverFn LazyResolverFn; + + JITResolverState state; + + /// ExternalFnToStubMap - This is the equivalent of FunctionToLazyStubMap + /// for external functions. TODO: Of course, external functions don't need + /// a lazy stub. It's actually here to make it more likely that far calls + /// succeed, but no single stub can guarantee that. I'll remove this in a + /// subsequent checkin when I actually fix far calls. + std::map ExternalFnToStubMap; + + /// revGOTMap - map addresses to indexes in the GOT + std::map revGOTMap; + unsigned nextGOTIndex; + + JITEmitter &JE; + + static JITResolver *TheJITResolver; + public: + explicit JITResolver(JIT &jit, JITEmitter &je) : nextGOTIndex(0), JE(je) { + TheJIT = &jit; + + LazyResolverFn = jit.getJITInfo().getLazyResolverFunction(JITCompilerFn); + assert(TheJITResolver == 0 && "Multiple JIT resolvers?"); + TheJITResolver = this; + } + + ~JITResolver() { + TheJITResolver = 0; + } + + /// getLazyFunctionStubIfAvailable - This returns a pointer to a function's + /// lazy-compilation stub if it has already been created. + void *getLazyFunctionStubIfAvailable(Function *F); + + /// getLazyFunctionStub - This returns a pointer to a function's + /// lazy-compilation stub, creating one on demand as needed. + void *getLazyFunctionStub(Function *F); + + /// getExternalFunctionStub - Return a stub for the function at the + /// specified address, created lazily on demand. + void *getExternalFunctionStub(void *FnAddr); + + /// getGlobalValueIndirectSym - Return an indirect symbol containing the + /// specified GV address. + void *getGlobalValueIndirectSym(GlobalValue *V, void *GVAddress); + + void getRelocatableGVs(SmallVectorImpl &GVs, + SmallVectorImpl &Ptrs); + + GlobalValue *invalidateStub(void *Stub); + + /// getGOTIndexForAddress - Return a new or existing index in the GOT for + /// an address. This function only manages slots, it does not manage the + /// contents of the slots or the memory associated with the GOT. + unsigned getGOTIndexForAddr(void *addr); + + /// JITCompilerFn - This function is called to resolve a stub to a compiled + /// address. If the LLVM Function corresponding to the stub has not yet + /// been compiled, this function compiles it first. + static void *JITCompilerFn(void *Stub); + }; + + /// JITEmitter - The JIT implementation of the MachineCodeEmitter, which is + /// used to output functions to memory for execution. + class JITEmitter : public JITCodeEmitter { + JITMemoryManager *MemMgr; + + // When reattempting to JIT a function after running out of space, we store + // the estimated size of the function we're trying to JIT here, so we can + // ask the memory manager for at least this much space. When we + // successfully emit the function, we reset this back to zero. + uintptr_t SizeEstimate; + + /// Relocations - These are the relocations that the function needs, as + /// emitted. + std::vector Relocations; + + /// MBBLocations - This vector is a mapping from MBB ID's to their address. + /// It is filled in by the StartMachineBasicBlock callback and queried by + /// the getMachineBasicBlockAddress callback. + std::vector MBBLocations; + + /// ConstantPool - The constant pool for the current function. + /// + MachineConstantPool *ConstantPool; + + /// ConstantPoolBase - A pointer to the first entry in the constant pool. + /// + void *ConstantPoolBase; + + /// ConstPoolAddresses - Addresses of individual constant pool entries. + /// + SmallVector ConstPoolAddresses; + + /// JumpTable - The jump tables for the current function. + /// + MachineJumpTableInfo *JumpTable; + + /// JumpTableBase - A pointer to the first entry in the jump table. + /// + void *JumpTableBase; + + /// Resolver - This contains info about the currently resolved functions. + JITResolver Resolver; + + /// DE - The dwarf emitter for the jit. + OwningPtr DE; + + /// DR - The debug registerer for the jit. + OwningPtr DR; + + /// LabelLocations - This vector is a mapping from Label ID's to their + /// address. + std::vector LabelLocations; + + /// MMI - Machine module info for exception informations + MachineModuleInfo* MMI; + + // GVSet - a set to keep track of which globals have been seen + SmallPtrSet GVSet; + + // CurFn - The llvm function being emitted. Only valid during + // finishFunction(). + const Function *CurFn; + + /// Information about emitted code, which is passed to the + /// JITEventListeners. This is reset in startFunction and used in + /// finishFunction. + JITEvent_EmittedFunctionDetails EmissionDetails; + + struct EmittedCode { + void *FunctionBody; // Beginning of the function's allocation. + void *Code; // The address the function's code actually starts at. + void *ExceptionTable; + EmittedCode() : FunctionBody(0), Code(0), ExceptionTable(0) {} + }; + struct EmittedFunctionConfig : public ValueMapConfig { + typedef JITEmitter *ExtraData; + static void onDelete(JITEmitter *, const Function*); + static void onRAUW(JITEmitter *, const Function*, const Function*); + }; + ValueMap EmittedFunctions; + + // CurFnStubUses - For a given Function, a vector of stubs that it + // references. This facilitates the JIT detecting that a stub is no + // longer used, so that it may be deallocated. + DenseMap, SmallVector > CurFnStubUses; + + // StubFnRefs - For a given pointer to a stub, a set of Functions which + // reference the stub. When the count of a stub's references drops to zero, + // the stub is unused. + DenseMap > StubFnRefs; + + DebugLocTuple PrevDLT; + + public: + JITEmitter(JIT &jit, JITMemoryManager *JMM, TargetMachine &TM) + : SizeEstimate(0), Resolver(jit, *this), MMI(0), CurFn(0), + EmittedFunctions(this) { + MemMgr = JMM ? JMM : JITMemoryManager::CreateDefaultMemManager(); + if (jit.getJITInfo().needsGOT()) { + MemMgr->AllocateGOT(); + DEBUG(errs() << "JIT is managing a GOT\n"); + } + + if (DwarfExceptionHandling || JITEmitDebugInfo) { + DE.reset(new JITDwarfEmitter(jit)); + } + if (JITEmitDebugInfo) { + DR.reset(new JITDebugRegisterer(TM)); + } + } + ~JITEmitter() { + delete MemMgr; + } + + /// classof - Methods for support type inquiry through isa, cast, and + /// dyn_cast: + /// + static inline bool classof(const JITEmitter*) { return true; } + static inline bool classof(const MachineCodeEmitter*) { return true; } + + JITResolver &getJITResolver() { return Resolver; } + + virtual void startFunction(MachineFunction &F); + virtual bool finishFunction(MachineFunction &F); + + void emitConstantPool(MachineConstantPool *MCP); + void initJumpTableInfo(MachineJumpTableInfo *MJTI); + void emitJumpTableInfo(MachineJumpTableInfo *MJTI); + + virtual void startGVStub(BufferState &BS, const GlobalValue* GV, + unsigned StubSize, unsigned Alignment = 1); + virtual void startGVStub(BufferState &BS, void *Buffer, + unsigned StubSize); + virtual void* finishGVStub(BufferState &BS); + + /// allocateSpace - Reserves space in the current block if any, or + /// allocate a new one of the given size. + virtual void *allocateSpace(uintptr_t Size, unsigned Alignment); + + /// allocateGlobal - Allocate memory for a global. Unlike allocateSpace, + /// this method does not allocate memory in the current output buffer, + /// because a global may live longer than the current function. + virtual void *allocateGlobal(uintptr_t Size, unsigned Alignment); + + virtual void addRelocation(const MachineRelocation &MR) { + Relocations.push_back(MR); + } + + virtual void StartMachineBasicBlock(MachineBasicBlock *MBB) { + if (MBBLocations.size() <= (unsigned)MBB->getNumber()) + MBBLocations.resize((MBB->getNumber()+1)*2); + MBBLocations[MBB->getNumber()] = getCurrentPCValue(); + DEBUG(errs() << "JIT: Emitting BB" << MBB->getNumber() << " at [" + << (void*) getCurrentPCValue() << "]\n"); + } + + virtual uintptr_t getConstantPoolEntryAddress(unsigned Entry) const; + virtual uintptr_t getJumpTableEntryAddress(unsigned Entry) const; + + virtual uintptr_t getMachineBasicBlockAddress(MachineBasicBlock *MBB) const { + assert(MBBLocations.size() > (unsigned)MBB->getNumber() && + MBBLocations[MBB->getNumber()] && "MBB not emitted!"); + return MBBLocations[MBB->getNumber()]; + } + + /// retryWithMoreMemory - Log a retry and deallocate all memory for the + /// given function. Increase the minimum allocation size so that we get + /// more memory next time. + void retryWithMoreMemory(MachineFunction &F); + + /// deallocateMemForFunction - Deallocate all memory for the specified + /// function body. + void deallocateMemForFunction(const Function *F); + + /// AddStubToCurrentFunction - Mark the current function being JIT'd as + /// using the stub at the specified address. Allows + /// deallocateMemForFunction to also remove stubs no longer referenced. + void AddStubToCurrentFunction(void *Stub); + + virtual void processDebugLoc(DebugLoc DL, bool BeforePrintingInsn); + + virtual void emitLabel(uint64_t LabelID) { + if (LabelLocations.size() <= LabelID) + LabelLocations.resize((LabelID+1)*2); + LabelLocations[LabelID] = getCurrentPCValue(); + } + + virtual uintptr_t getLabelAddress(uint64_t LabelID) const { + assert(LabelLocations.size() > (unsigned)LabelID && + LabelLocations[LabelID] && "Label not emitted!"); + return LabelLocations[LabelID]; + } + + virtual void setModuleInfo(MachineModuleInfo* Info) { + MMI = Info; + if (DE.get()) DE->setModuleInfo(Info); + } + + void setMemoryExecutable() { + MemMgr->setMemoryExecutable(); + } + + JITMemoryManager *getMemMgr() const { return MemMgr; } + + private: + void *getPointerToGlobal(GlobalValue *GV, void *Reference, + bool MayNeedFarStub); + void *getPointerToGVIndirectSym(GlobalValue *V, void *Reference); + unsigned addSizeOfGlobal(const GlobalVariable *GV, unsigned Size); + unsigned addSizeOfGlobalsInConstantVal(const Constant *C, unsigned Size); + unsigned addSizeOfGlobalsInInitializer(const Constant *Init, unsigned Size); + unsigned GetSizeOfGlobalsInBytes(MachineFunction &MF); + }; +} + +JITResolver *JITResolver::TheJITResolver = 0; + +void CallSiteValueMapConfig::onDelete(JITResolverState *JRS, Function *F) { + JRS->EraseAllCallSitesPrelocked(F); +} + +/// getLazyFunctionStubIfAvailable - This returns a pointer to a function stub +/// if it has already been created. +void *JITResolver::getLazyFunctionStubIfAvailable(Function *F) { + MutexGuard locked(TheJIT->lock); + + // If we already have a stub for this function, recycle it. + return state.getFunctionToLazyStubMap(locked).lookup(F); +} + +/// getFunctionStub - This returns a pointer to a function stub, creating +/// one on demand as needed. +void *JITResolver::getLazyFunctionStub(Function *F) { + MutexGuard locked(TheJIT->lock); + + // If we already have a lazy stub for this function, recycle it. + void *&Stub = state.getFunctionToLazyStubMap(locked)[F]; + if (Stub) return Stub; + + // Call the lazy resolver function if we are JIT'ing lazily. Otherwise we + // must resolve the symbol now. + void *Actual = TheJIT->isCompilingLazily() + ? (void *)(intptr_t)LazyResolverFn : (void *)0; + + // If this is an external declaration, attempt to resolve the address now + // to place in the stub. + if (F->isDeclaration() && !F->hasNotBeenReadFromBitcode()) { + Actual = TheJIT->getPointerToFunction(F); + + // If we resolved the symbol to a null address (eg. a weak external) + // don't emit a stub. Return a null pointer to the application. + if (!Actual) return 0; + } + + MachineCodeEmitter::BufferState BS; + TargetJITInfo::StubLayout SL = TheJIT->getJITInfo().getStubLayout(); + JE.startGVStub(BS, F, SL.Size, SL.Alignment); + // Codegen a new stub, calling the lazy resolver or the actual address of the + // external function, if it was resolved. + Stub = TheJIT->getJITInfo().emitFunctionStub(F, Actual, JE); + JE.finishGVStub(BS); + + if (Actual != (void*)(intptr_t)LazyResolverFn) { + // If we are getting the stub for an external function, we really want the + // address of the stub in the GlobalAddressMap for the JIT, not the address + // of the external function. + TheJIT->updateGlobalMapping(F, Stub); + } + + DEBUG(errs() << "JIT: Lazy stub emitted at [" << Stub << "] for function '" + << F->getName() << "'\n"); + + // Finally, keep track of the stub-to-Function mapping so that the + // JITCompilerFn knows which function to compile! + state.AddCallSite(locked, Stub, F); + + // If we are JIT'ing non-lazily but need to call a function that does not + // exist yet, add it to the JIT's work list so that we can fill in the stub + // address later. + if (!Actual && !TheJIT->isCompilingLazily()) + if (!F->isDeclaration() || F->hasNotBeenReadFromBitcode()) + TheJIT->addPendingFunction(F); + + return Stub; +} + +/// getGlobalValueIndirectSym - Return a lazy pointer containing the specified +/// GV address. +void *JITResolver::getGlobalValueIndirectSym(GlobalValue *GV, void *GVAddress) { + MutexGuard locked(TheJIT->lock); + + // If we already have a stub for this global variable, recycle it. + void *&IndirectSym = state.getGlobalToIndirectSymMap(locked)[GV]; + if (IndirectSym) return IndirectSym; + + // Otherwise, codegen a new indirect symbol. + IndirectSym = TheJIT->getJITInfo().emitGlobalValueIndirectSym(GV, GVAddress, + JE); + + DEBUG(errs() << "JIT: Indirect symbol emitted at [" << IndirectSym + << "] for GV '" << GV->getName() << "'\n"); + + return IndirectSym; +} + +/// getExternalFunctionStub - Return a stub for the function at the +/// specified address, created lazily on demand. +void *JITResolver::getExternalFunctionStub(void *FnAddr) { + // If we already have a stub for this function, recycle it. + void *&Stub = ExternalFnToStubMap[FnAddr]; + if (Stub) return Stub; + + MachineCodeEmitter::BufferState BS; + TargetJITInfo::StubLayout SL = TheJIT->getJITInfo().getStubLayout(); + JE.startGVStub(BS, 0, SL.Size, SL.Alignment); + Stub = TheJIT->getJITInfo().emitFunctionStub(0, FnAddr, JE); + JE.finishGVStub(BS); + + DEBUG(errs() << "JIT: Stub emitted at [" << Stub + << "] for external function at '" << FnAddr << "'\n"); + return Stub; +} + +unsigned JITResolver::getGOTIndexForAddr(void* addr) { + unsigned idx = revGOTMap[addr]; + if (!idx) { + idx = ++nextGOTIndex; + revGOTMap[addr] = idx; + DEBUG(errs() << "JIT: Adding GOT entry " << idx << " for addr [" + << addr << "]\n"); + } + return idx; +} + +void JITResolver::getRelocatableGVs(SmallVectorImpl &GVs, + SmallVectorImpl &Ptrs) { + MutexGuard locked(TheJIT->lock); + + const FunctionToLazyStubMapTy &FM = state.getFunctionToLazyStubMap(locked); + GlobalToIndirectSymMapTy &GM = state.getGlobalToIndirectSymMap(locked); + + for (FunctionToLazyStubMapTy::const_iterator i = FM.begin(), e = FM.end(); + i != e; ++i){ + Function *F = i->first; + if (F->isDeclaration() && F->hasExternalLinkage()) { + GVs.push_back(i->first); + Ptrs.push_back(i->second); + } + } + for (GlobalToIndirectSymMapTy::iterator i = GM.begin(), e = GM.end(); + i != e; ++i) { + GVs.push_back(i->first); + Ptrs.push_back(i->second); + } +} + +GlobalValue *JITResolver::invalidateStub(void *Stub) { + MutexGuard locked(TheJIT->lock); + + GlobalToIndirectSymMapTy &GM = state.getGlobalToIndirectSymMap(locked); + + // Look up the cheap way first, to see if it's a function stub we are + // invalidating. If so, remove it from both the forward and reverse maps. + if (Function *F = state.EraseStub(locked, Stub)) { + return F; + } + + // Otherwise, it might be an indirect symbol stub. Find it and remove it. + for (GlobalToIndirectSymMapTy::iterator i = GM.begin(), e = GM.end(); + i != e; ++i) { + if (i->second != Stub) + continue; + GlobalValue *GV = i->first; + GM.erase(i); + return GV; + } + + // Lastly, check to see if it's in the ExternalFnToStubMap. + for (std::map::iterator i = ExternalFnToStubMap.begin(), + e = ExternalFnToStubMap.end(); i != e; ++i) { + if (i->second != Stub) + continue; + ExternalFnToStubMap.erase(i); + break; + } + + return 0; +} + +/// JITCompilerFn - This function is called when a lazy compilation stub has +/// been entered. It looks up which function this stub corresponds to, compiles +/// it if necessary, then returns the resultant function pointer. +void *JITResolver::JITCompilerFn(void *Stub) { + JITResolver &JR = *TheJITResolver; + + Function* F = 0; + void* ActualPtr = 0; + + { + // Only lock for getting the Function. The call getPointerToFunction made + // in this function might trigger function materializing, which requires + // JIT lock to be unlocked. + MutexGuard locked(TheJIT->lock); + + // The address given to us for the stub may not be exactly right, it might + // be a little bit after the stub. As such, use upper_bound to find it. + pair I = + JR.state.LookupFunctionFromCallSite(locked, Stub); + F = I.second; + ActualPtr = I.first; + } + + // If we have already code generated the function, just return the address. + void *Result = TheJIT->getPointerToGlobalIfAvailable(F); + + if (!Result) { + // Otherwise we don't have it, do lazy compilation now. + + // If lazy compilation is disabled, emit a useful error message and abort. + if (!TheJIT->isCompilingLazily()) { + llvm_report_error("LLVM JIT requested to do lazy compilation of function '" + + F->getName() + "' when lazy compiles are disabled!"); + } + + DEBUG(errs() << "JIT: Lazily resolving function '" << F->getName() + << "' In stub ptr = " << Stub << " actual ptr = " + << ActualPtr << "\n"); + + Result = TheJIT->getPointerToFunction(F); + } + + // Reacquire the lock to update the GOT map. + MutexGuard locked(TheJIT->lock); + + // We might like to remove the call site from the CallSiteToFunction map, but + // we can't do that! Multiple threads could be stuck, waiting to acquire the + // lock above. As soon as the 1st function finishes compiling the function, + // the next one will be released, and needs to be able to find the function it + // needs to call. + + // FIXME: We could rewrite all references to this stub if we knew them. + + // What we will do is set the compiled function address to map to the + // same GOT entry as the stub so that later clients may update the GOT + // if they see it still using the stub address. + // Note: this is done so the Resolver doesn't have to manage GOT memory + // Do this without allocating map space if the target isn't using a GOT + if(JR.revGOTMap.find(Stub) != JR.revGOTMap.end()) + JR.revGOTMap[Result] = JR.revGOTMap[Stub]; + + return Result; +} + +//===----------------------------------------------------------------------===// +// JITEmitter code. +// +void *JITEmitter::getPointerToGlobal(GlobalValue *V, void *Reference, + bool MayNeedFarStub) { + if (GlobalVariable *GV = dyn_cast(V)) + return TheJIT->getOrEmitGlobalVariable(GV); + + if (GlobalAlias *GA = dyn_cast(V)) + return TheJIT->getPointerToGlobal(GA->resolveAliasedGlobal(false)); + + // If we have already compiled the function, return a pointer to its body. + Function *F = cast(V); + + void *FnStub = Resolver.getLazyFunctionStubIfAvailable(F); + if (FnStub) { + // Return the function stub if it's already created. We do this first so + // that we're returning the same address for the function as any previous + // call. TODO: Yes, this is wrong. The lazy stub isn't guaranteed to be + // close enough to call. + AddStubToCurrentFunction(FnStub); + return FnStub; + } + + // If we know the target can handle arbitrary-distance calls, try to + // return a direct pointer. + if (!MayNeedFarStub) { + // If we have code, go ahead and return that. + void *ResultPtr = TheJIT->getPointerToGlobalIfAvailable(F); + if (ResultPtr) return ResultPtr; + + // If this is an external function pointer, we can force the JIT to + // 'compile' it, which really just adds it to the map. + if (F->isDeclaration() && !F->hasNotBeenReadFromBitcode()) + return TheJIT->getPointerToFunction(F); + } + + // Otherwise, we may need a to emit a stub, and, conservatively, we + // always do so. + void *StubAddr = Resolver.getLazyFunctionStub(F); + + // Add the stub to the current function's list of referenced stubs, so we can + // deallocate them if the current function is ever freed. It's possible to + // return null from getLazyFunctionStub in the case of a weak extern that + // fails to resolve. + if (StubAddr) + AddStubToCurrentFunction(StubAddr); + + return StubAddr; +} + +void *JITEmitter::getPointerToGVIndirectSym(GlobalValue *V, void *Reference) { + // Make sure GV is emitted first, and create a stub containing the fully + // resolved address. + void *GVAddress = getPointerToGlobal(V, Reference, false); + void *StubAddr = Resolver.getGlobalValueIndirectSym(V, GVAddress); + + // Add the stub to the current function's list of referenced stubs, so we can + // deallocate them if the current function is ever freed. + AddStubToCurrentFunction(StubAddr); + + return StubAddr; +} + +void JITEmitter::AddStubToCurrentFunction(void *StubAddr) { + assert(CurFn && "Stub added to current function, but current function is 0!"); + + SmallVectorImpl &StubsUsed = CurFnStubUses[CurFn]; + StubsUsed.push_back(StubAddr); + + SmallPtrSet &FnRefs = StubFnRefs[StubAddr]; + FnRefs.insert(CurFn); +} + +void JITEmitter::processDebugLoc(DebugLoc DL, bool BeforePrintingInsn) { + if (!DL.isUnknown()) { + DebugLocTuple CurDLT = EmissionDetails.MF->getDebugLocTuple(DL); + + if (BeforePrintingInsn) { + if (CurDLT.Scope != 0 && PrevDLT != CurDLT) { + JITEvent_EmittedFunctionDetails::LineStart NextLine; + NextLine.Address = getCurrentPCValue(); + NextLine.Loc = DL; + EmissionDetails.LineStarts.push_back(NextLine); + } + + PrevDLT = CurDLT; + } + } +} + +static unsigned GetConstantPoolSizeInBytes(MachineConstantPool *MCP, + const TargetData *TD) { + const std::vector &Constants = MCP->getConstants(); + if (Constants.empty()) return 0; + + unsigned Size = 0; + for (unsigned i = 0, e = Constants.size(); i != e; ++i) { + MachineConstantPoolEntry CPE = Constants[i]; + unsigned AlignMask = CPE.getAlignment() - 1; + Size = (Size + AlignMask) & ~AlignMask; + const Type *Ty = CPE.getType(); + Size += TD->getTypeAllocSize(Ty); + } + return Size; +} + +static unsigned GetJumpTableSizeInBytes(MachineJumpTableInfo *MJTI) { + const std::vector &JT = MJTI->getJumpTables(); + if (JT.empty()) return 0; + + unsigned NumEntries = 0; + for (unsigned i = 0, e = JT.size(); i != e; ++i) + NumEntries += JT[i].MBBs.size(); + + unsigned EntrySize = MJTI->getEntrySize(); + + return NumEntries * EntrySize; +} + +static uintptr_t RoundUpToAlign(uintptr_t Size, unsigned Alignment) { + if (Alignment == 0) Alignment = 1; + // Since we do not know where the buffer will be allocated, be pessimistic. + return Size + Alignment; +} + +/// addSizeOfGlobal - add the size of the global (plus any alignment padding) +/// into the running total Size. + +unsigned JITEmitter::addSizeOfGlobal(const GlobalVariable *GV, unsigned Size) { + const Type *ElTy = GV->getType()->getElementType(); + size_t GVSize = (size_t)TheJIT->getTargetData()->getTypeAllocSize(ElTy); + size_t GVAlign = + (size_t)TheJIT->getTargetData()->getPreferredAlignment(GV); + DEBUG(errs() << "JIT: Adding in size " << GVSize << " alignment " << GVAlign); + DEBUG(GV->dump()); + // Assume code section ends with worst possible alignment, so first + // variable needs maximal padding. + if (Size==0) + Size = 1; + Size = ((Size+GVAlign-1)/GVAlign)*GVAlign; + Size += GVSize; + return Size; +} + +/// addSizeOfGlobalsInConstantVal - find any globals that we haven't seen yet +/// but are referenced from the constant; put them in GVSet and add their +/// size into the running total Size. + +unsigned JITEmitter::addSizeOfGlobalsInConstantVal(const Constant *C, + unsigned Size) { + // If its undefined, return the garbage. + if (isa(C)) + return Size; + + // If the value is a ConstantExpr + if (const ConstantExpr *CE = dyn_cast(C)) { + Constant *Op0 = CE->getOperand(0); + switch (CE->getOpcode()) { + case Instruction::GetElementPtr: + case Instruction::Trunc: + case Instruction::ZExt: + case Instruction::SExt: + case Instruction::FPTrunc: + case Instruction::FPExt: + case Instruction::UIToFP: + case Instruction::SIToFP: + case Instruction::FPToUI: + case Instruction::FPToSI: + case Instruction::PtrToInt: + case Instruction::IntToPtr: + case Instruction::BitCast: { + Size = addSizeOfGlobalsInConstantVal(Op0, Size); + break; + } + case Instruction::Add: + case Instruction::FAdd: + case Instruction::Sub: + case Instruction::FSub: + case Instruction::Mul: + case Instruction::FMul: + case Instruction::UDiv: + case Instruction::SDiv: + case Instruction::URem: + case Instruction::SRem: + case Instruction::And: + case Instruction::Or: + case Instruction::Xor: { + Size = addSizeOfGlobalsInConstantVal(Op0, Size); + Size = addSizeOfGlobalsInConstantVal(CE->getOperand(1), Size); + break; + } + default: { + std::string msg; + raw_string_ostream Msg(msg); + Msg << "ConstantExpr not handled: " << *CE; + llvm_report_error(Msg.str()); + } + } + } + + if (C->getType()->getTypeID() == Type::PointerTyID) + if (const GlobalVariable* GV = dyn_cast(C)) + if (GVSet.insert(GV)) + Size = addSizeOfGlobal(GV, Size); + + return Size; +} + +/// addSizeOfGLobalsInInitializer - handle any globals that we haven't seen yet +/// but are referenced from the given initializer. + +unsigned JITEmitter::addSizeOfGlobalsInInitializer(const Constant *Init, + unsigned Size) { + if (!isa(Init) && + !isa(Init) && + !isa(Init) && + !isa(Init) && + !isa(Init) && + Init->getType()->isFirstClassType()) + Size = addSizeOfGlobalsInConstantVal(Init, Size); + return Size; +} + +/// GetSizeOfGlobalsInBytes - walk the code for the function, looking for +/// globals; then walk the initializers of those globals looking for more. +/// If their size has not been considered yet, add it into the running total +/// Size. + +unsigned JITEmitter::GetSizeOfGlobalsInBytes(MachineFunction &MF) { + unsigned Size = 0; + GVSet.clear(); + + for (MachineFunction::iterator MBB = MF.begin(), E = MF.end(); + MBB != E; ++MBB) { + for (MachineBasicBlock::const_iterator I = MBB->begin(), E = MBB->end(); + I != E; ++I) { + const TargetInstrDesc &Desc = I->getDesc(); + const MachineInstr &MI = *I; + unsigned NumOps = Desc.getNumOperands(); + for (unsigned CurOp = 0; CurOp < NumOps; CurOp++) { + const MachineOperand &MO = MI.getOperand(CurOp); + if (MO.isGlobal()) { + GlobalValue* V = MO.getGlobal(); + const GlobalVariable *GV = dyn_cast(V); + if (!GV) + continue; + // If seen in previous function, it will have an entry here. + if (TheJIT->getPointerToGlobalIfAvailable(GV)) + continue; + // If seen earlier in this function, it will have an entry here. + // FIXME: it should be possible to combine these tables, by + // assuming the addresses of the new globals in this module + // start at 0 (or something) and adjusting them after codegen + // complete. Another possibility is to grab a marker bit in GV. + if (GVSet.insert(GV)) + // A variable as yet unseen. Add in its size. + Size = addSizeOfGlobal(GV, Size); + } + } + } + } + DEBUG(errs() << "JIT: About to look through initializers\n"); + // Look for more globals that are referenced only from initializers. + // GVSet.end is computed each time because the set can grow as we go. + for (SmallPtrSet::iterator I = GVSet.begin(); + I != GVSet.end(); I++) { + const GlobalVariable* GV = *I; + if (GV->hasInitializer()) + Size = addSizeOfGlobalsInInitializer(GV->getInitializer(), Size); + } + + return Size; +} + +void JITEmitter::startFunction(MachineFunction &F) { + DEBUG(errs() << "JIT: Starting CodeGen of Function " + << F.getFunction()->getName() << "\n"); + + uintptr_t ActualSize = 0; + // Set the memory writable, if it's not already + MemMgr->setMemoryWritable(); + if (MemMgr->NeedsExactSize()) { + DEBUG(errs() << "JIT: ExactSize\n"); + const TargetInstrInfo* TII = F.getTarget().getInstrInfo(); + MachineJumpTableInfo *MJTI = F.getJumpTableInfo(); + MachineConstantPool *MCP = F.getConstantPool(); + + // Ensure the constant pool/jump table info is at least 4-byte aligned. + ActualSize = RoundUpToAlign(ActualSize, 16); + + // Add the alignment of the constant pool + ActualSize = RoundUpToAlign(ActualSize, MCP->getConstantPoolAlignment()); + + // Add the constant pool size + ActualSize += GetConstantPoolSizeInBytes(MCP, TheJIT->getTargetData()); + + // Add the aligment of the jump table info + ActualSize = RoundUpToAlign(ActualSize, MJTI->getAlignment()); + + // Add the jump table size + ActualSize += GetJumpTableSizeInBytes(MJTI); + + // Add the alignment for the function + ActualSize = RoundUpToAlign(ActualSize, + std::max(F.getFunction()->getAlignment(), 8U)); + + // Add the function size + ActualSize += TII->GetFunctionSizeInBytes(F); + + DEBUG(errs() << "JIT: ActualSize before globals " << ActualSize << "\n"); + // Add the size of the globals that will be allocated after this function. + // These are all the ones referenced from this function that were not + // previously allocated. + ActualSize += GetSizeOfGlobalsInBytes(F); + DEBUG(errs() << "JIT: ActualSize after globals " << ActualSize << "\n"); + } else if (SizeEstimate > 0) { + // SizeEstimate will be non-zero on reallocation attempts. + ActualSize = SizeEstimate; + } + + BufferBegin = CurBufferPtr = MemMgr->startFunctionBody(F.getFunction(), + ActualSize); + BufferEnd = BufferBegin+ActualSize; + EmittedFunctions[F.getFunction()].FunctionBody = BufferBegin; + + // Ensure the constant pool/jump table info is at least 4-byte aligned. + emitAlignment(16); + + emitConstantPool(F.getConstantPool()); + initJumpTableInfo(F.getJumpTableInfo()); + + // About to start emitting the machine code for the function. + emitAlignment(std::max(F.getFunction()->getAlignment(), 8U)); + TheJIT->updateGlobalMapping(F.getFunction(), CurBufferPtr); + EmittedFunctions[F.getFunction()].Code = CurBufferPtr; + + MBBLocations.clear(); + + EmissionDetails.MF = &F; + EmissionDetails.LineStarts.clear(); +} + +bool JITEmitter::finishFunction(MachineFunction &F) { + if (CurBufferPtr == BufferEnd) { + // We must call endFunctionBody before retrying, because + // deallocateMemForFunction requires it. + MemMgr->endFunctionBody(F.getFunction(), BufferBegin, CurBufferPtr); + retryWithMoreMemory(F); + return true; + } + + emitJumpTableInfo(F.getJumpTableInfo()); + + // FnStart is the start of the text, not the start of the constant pool and + // other per-function data. + uint8_t *FnStart = + (uint8_t *)TheJIT->getPointerToGlobalIfAvailable(F.getFunction()); + + // FnEnd is the end of the function's machine code. + uint8_t *FnEnd = CurBufferPtr; + + if (!Relocations.empty()) { + CurFn = F.getFunction(); + NumRelos += Relocations.size(); + + // Resolve the relocations to concrete pointers. + for (unsigned i = 0, e = Relocations.size(); i != e; ++i) { + MachineRelocation &MR = Relocations[i]; + void *ResultPtr = 0; + if (!MR.letTargetResolve()) { + if (MR.isExternalSymbol()) { + ResultPtr = TheJIT->getPointerToNamedFunction(MR.getExternalSymbol(), + false); + DEBUG(errs() << "JIT: Map \'" << MR.getExternalSymbol() << "\' to [" + << ResultPtr << "]\n"); + + // If the target REALLY wants a stub for this function, emit it now. + if (MR.mayNeedFarStub()) { + ResultPtr = Resolver.getExternalFunctionStub(ResultPtr); + } + } else if (MR.isGlobalValue()) { + ResultPtr = getPointerToGlobal(MR.getGlobalValue(), + BufferBegin+MR.getMachineCodeOffset(), + MR.mayNeedFarStub()); + } else if (MR.isIndirectSymbol()) { + ResultPtr = getPointerToGVIndirectSym( + MR.getGlobalValue(), BufferBegin+MR.getMachineCodeOffset()); + } else if (MR.isBasicBlock()) { + ResultPtr = (void*)getMachineBasicBlockAddress(MR.getBasicBlock()); + } else if (MR.isConstantPoolIndex()) { + ResultPtr = (void*)getConstantPoolEntryAddress(MR.getConstantPoolIndex()); + } else { + assert(MR.isJumpTableIndex()); + ResultPtr=(void*)getJumpTableEntryAddress(MR.getJumpTableIndex()); + } + + MR.setResultPointer(ResultPtr); + } + + // if we are managing the GOT and the relocation wants an index, + // give it one + if (MR.isGOTRelative() && MemMgr->isManagingGOT()) { + unsigned idx = Resolver.getGOTIndexForAddr(ResultPtr); + MR.setGOTIndex(idx); + if (((void**)MemMgr->getGOTBase())[idx] != ResultPtr) { + DEBUG(errs() << "JIT: GOT was out of date for " << ResultPtr + << " pointing at " << ((void**)MemMgr->getGOTBase())[idx] + << "\n"); + ((void**)MemMgr->getGOTBase())[idx] = ResultPtr; + } + } + } + + CurFn = 0; + TheJIT->getJITInfo().relocate(BufferBegin, &Relocations[0], + Relocations.size(), MemMgr->getGOTBase()); + } + + // Update the GOT entry for F to point to the new code. + if (MemMgr->isManagingGOT()) { + unsigned idx = Resolver.getGOTIndexForAddr((void*)BufferBegin); + if (((void**)MemMgr->getGOTBase())[idx] != (void*)BufferBegin) { + DEBUG(errs() << "JIT: GOT was out of date for " << (void*)BufferBegin + << " pointing at " << ((void**)MemMgr->getGOTBase())[idx] + << "\n"); + ((void**)MemMgr->getGOTBase())[idx] = (void*)BufferBegin; + } + } + + // CurBufferPtr may have moved beyond FnEnd, due to memory allocation for + // global variables that were referenced in the relocations. + MemMgr->endFunctionBody(F.getFunction(), BufferBegin, CurBufferPtr); + + if (CurBufferPtr == BufferEnd) { + retryWithMoreMemory(F); + return true; + } else { + // Now that we've succeeded in emitting the function, reset the + // SizeEstimate back down to zero. + SizeEstimate = 0; + } + + BufferBegin = CurBufferPtr = 0; + NumBytes += FnEnd-FnStart; + + // Invalidate the icache if necessary. + sys::Memory::InvalidateInstructionCache(FnStart, FnEnd-FnStart); + + TheJIT->NotifyFunctionEmitted(*F.getFunction(), FnStart, FnEnd-FnStart, + EmissionDetails); + + DEBUG(errs() << "JIT: Finished CodeGen of [" << (void*)FnStart + << "] Function: " << F.getFunction()->getName() + << ": " << (FnEnd-FnStart) << " bytes of text, " + << Relocations.size() << " relocations\n"); + + Relocations.clear(); + ConstPoolAddresses.clear(); + + // Mark code region readable and executable if it's not so already. + MemMgr->setMemoryExecutable(); + + DEBUG( + if (sys::hasDisassembler()) { + errs() << "JIT: Disassembled code:\n"; + errs() << sys::disassembleBuffer(FnStart, FnEnd-FnStart, + (uintptr_t)FnStart); + } else { + errs() << "JIT: Binary code:\n"; + uint8_t* q = FnStart; + for (int i = 0; q < FnEnd; q += 4, ++i) { + if (i == 4) + i = 0; + if (i == 0) + errs() << "JIT: " << (long)(q - FnStart) << ": "; + bool Done = false; + for (int j = 3; j >= 0; --j) { + if (q + j >= FnEnd) + Done = true; + else + errs() << (unsigned short)q[j]; + } + if (Done) + break; + errs() << ' '; + if (i == 3) + errs() << '\n'; + } + errs()<< '\n'; + } + ); + + if (DwarfExceptionHandling || JITEmitDebugInfo) { + uintptr_t ActualSize = 0; + BufferState BS; + SaveStateTo(BS); + + if (MemMgr->NeedsExactSize()) { + ActualSize = DE->GetDwarfTableSizeInBytes(F, *this, FnStart, FnEnd); + } + + BufferBegin = CurBufferPtr = MemMgr->startExceptionTable(F.getFunction(), + ActualSize); + BufferEnd = BufferBegin+ActualSize; + EmittedFunctions[F.getFunction()].ExceptionTable = BufferBegin; + uint8_t *EhStart; + uint8_t *FrameRegister = DE->EmitDwarfTable(F, *this, FnStart, FnEnd, + EhStart); + MemMgr->endExceptionTable(F.getFunction(), BufferBegin, CurBufferPtr, + FrameRegister); + uint8_t *EhEnd = CurBufferPtr; + RestoreStateFrom(BS); + + if (DwarfExceptionHandling) { + TheJIT->RegisterTable(FrameRegister); + } + + if (JITEmitDebugInfo) { + DebugInfo I; + I.FnStart = FnStart; + I.FnEnd = FnEnd; + I.EhStart = EhStart; + I.EhEnd = EhEnd; + DR->RegisterFunction(F.getFunction(), I); + } + } + + if (MMI) + MMI->EndFunction(); + + return false; +} + +void JITEmitter::retryWithMoreMemory(MachineFunction &F) { + DEBUG(errs() << "JIT: Ran out of space for native code. Reattempting.\n"); + Relocations.clear(); // Clear the old relocations or we'll reapply them. + ConstPoolAddresses.clear(); + ++NumRetries; + deallocateMemForFunction(F.getFunction()); + // Try again with at least twice as much free space. + SizeEstimate = (uintptr_t)(2 * (BufferEnd - BufferBegin)); +} + +/// deallocateMemForFunction - Deallocate all memory for the specified +/// function body. Also drop any references the function has to stubs. +/// May be called while the Function is being destroyed inside ~Value(). +void JITEmitter::deallocateMemForFunction(const Function *F) { + ValueMap::iterator + Emitted = EmittedFunctions.find(F); + if (Emitted != EmittedFunctions.end()) { + MemMgr->deallocateFunctionBody(Emitted->second.FunctionBody); + MemMgr->deallocateExceptionTable(Emitted->second.ExceptionTable); + TheJIT->NotifyFreeingMachineCode(Emitted->second.Code); + + EmittedFunctions.erase(Emitted); + } + + // TODO: Do we need to unregister exception handling information from libgcc + // here? + + if (JITEmitDebugInfo) { + DR->UnregisterFunction(F); + } + + // If the function did not reference any stubs, return. + if (CurFnStubUses.find(F) == CurFnStubUses.end()) + return; + + // For each referenced stub, erase the reference to this function, and then + // erase the list of referenced stubs. + SmallVectorImpl &StubList = CurFnStubUses[F]; + for (unsigned i = 0, e = StubList.size(); i != e; ++i) { + void *Stub = StubList[i]; + + // If we already invalidated this stub for this function, continue. + if (StubFnRefs.count(Stub) == 0) + continue; + + SmallPtrSet &FnRefs = StubFnRefs[Stub]; + FnRefs.erase(F); + + // If this function was the last reference to the stub, invalidate the stub + // in the JITResolver. Were there a memory manager deallocateStub routine, + // we could call that at this point too. + if (FnRefs.empty()) { + DEBUG(errs() << "\nJIT: Invalidated Stub at [" << Stub << "]\n"); + StubFnRefs.erase(Stub); + + // Invalidate the stub. If it is a GV stub, update the JIT's global + // mapping for that GV to zero. + GlobalValue *GV = Resolver.invalidateStub(Stub); + if (GV) { + TheJIT->updateGlobalMapping(GV, 0); + } + } + } + CurFnStubUses.erase(F); +} + + +void* JITEmitter::allocateSpace(uintptr_t Size, unsigned Alignment) { + if (BufferBegin) + return JITCodeEmitter::allocateSpace(Size, Alignment); + + // create a new memory block if there is no active one. + // care must be taken so that BufferBegin is invalidated when a + // block is trimmed + BufferBegin = CurBufferPtr = MemMgr->allocateSpace(Size, Alignment); + BufferEnd = BufferBegin+Size; + return CurBufferPtr; +} + +void* JITEmitter::allocateGlobal(uintptr_t Size, unsigned Alignment) { + // Delegate this call through the memory manager. + return MemMgr->allocateGlobal(Size, Alignment); +} + +void JITEmitter::emitConstantPool(MachineConstantPool *MCP) { + if (TheJIT->getJITInfo().hasCustomConstantPool()) + return; + + const std::vector &Constants = MCP->getConstants(); + if (Constants.empty()) return; + + unsigned Size = GetConstantPoolSizeInBytes(MCP, TheJIT->getTargetData()); + unsigned Align = MCP->getConstantPoolAlignment(); + ConstantPoolBase = allocateSpace(Size, Align); + ConstantPool = MCP; + + if (ConstantPoolBase == 0) return; // Buffer overflow. + + DEBUG(errs() << "JIT: Emitted constant pool at [" << ConstantPoolBase + << "] (size: " << Size << ", alignment: " << Align << ")\n"); + + // Initialize the memory for all of the constant pool entries. + unsigned Offset = 0; + for (unsigned i = 0, e = Constants.size(); i != e; ++i) { + MachineConstantPoolEntry CPE = Constants[i]; + unsigned AlignMask = CPE.getAlignment() - 1; + Offset = (Offset + AlignMask) & ~AlignMask; + + uintptr_t CAddr = (uintptr_t)ConstantPoolBase + Offset; + ConstPoolAddresses.push_back(CAddr); + if (CPE.isMachineConstantPoolEntry()) { + // FIXME: add support to lower machine constant pool values into bytes! + llvm_report_error("Initialize memory with machine specific constant pool" + "entry has not been implemented!"); + } + TheJIT->InitializeMemory(CPE.Val.ConstVal, (void*)CAddr); + DEBUG(errs() << "JIT: CP" << i << " at [0x"; + errs().write_hex(CAddr) << "]\n"); + + const Type *Ty = CPE.Val.ConstVal->getType(); + Offset += TheJIT->getTargetData()->getTypeAllocSize(Ty); + } +} + +void JITEmitter::initJumpTableInfo(MachineJumpTableInfo *MJTI) { + if (TheJIT->getJITInfo().hasCustomJumpTables()) + return; + + const std::vector &JT = MJTI->getJumpTables(); + if (JT.empty()) return; + + unsigned NumEntries = 0; + for (unsigned i = 0, e = JT.size(); i != e; ++i) + NumEntries += JT[i].MBBs.size(); + + unsigned EntrySize = MJTI->getEntrySize(); + + // Just allocate space for all the jump tables now. We will fix up the actual + // MBB entries in the tables after we emit the code for each block, since then + // we will know the final locations of the MBBs in memory. + JumpTable = MJTI; + JumpTableBase = allocateSpace(NumEntries * EntrySize, MJTI->getAlignment()); +} + +void JITEmitter::emitJumpTableInfo(MachineJumpTableInfo *MJTI) { + if (TheJIT->getJITInfo().hasCustomJumpTables()) + return; + + const std::vector &JT = MJTI->getJumpTables(); + if (JT.empty() || JumpTableBase == 0) return; + + if (TargetMachine::getRelocationModel() == Reloc::PIC_) { + assert(MJTI->getEntrySize() == 4 && "Cross JIT'ing?"); + // For each jump table, place the offset from the beginning of the table + // to the target address. + int *SlotPtr = (int*)JumpTableBase; + + for (unsigned i = 0, e = JT.size(); i != e; ++i) { + const std::vector &MBBs = JT[i].MBBs; + // Store the offset of the basic block for this jump table slot in the + // memory we allocated for the jump table in 'initJumpTableInfo' + uintptr_t Base = (uintptr_t)SlotPtr; + for (unsigned mi = 0, me = MBBs.size(); mi != me; ++mi) { + uintptr_t MBBAddr = getMachineBasicBlockAddress(MBBs[mi]); + *SlotPtr++ = TheJIT->getJITInfo().getPICJumpTableEntry(MBBAddr, Base); + } + } + } else { + assert(MJTI->getEntrySize() == sizeof(void*) && "Cross JIT'ing?"); + + // For each jump table, map each target in the jump table to the address of + // an emitted MachineBasicBlock. + intptr_t *SlotPtr = (intptr_t*)JumpTableBase; + + for (unsigned i = 0, e = JT.size(); i != e; ++i) { + const std::vector &MBBs = JT[i].MBBs; + // Store the address of the basic block for this jump table slot in the + // memory we allocated for the jump table in 'initJumpTableInfo' + for (unsigned mi = 0, me = MBBs.size(); mi != me; ++mi) + *SlotPtr++ = getMachineBasicBlockAddress(MBBs[mi]); + } + } +} + +void JITEmitter::startGVStub(BufferState &BS, const GlobalValue* GV, + unsigned StubSize, unsigned Alignment) { + SaveStateTo(BS); + + BufferBegin = CurBufferPtr = MemMgr->allocateStub(GV, StubSize, Alignment); + BufferEnd = BufferBegin+StubSize+1; +} + +void JITEmitter::startGVStub(BufferState &BS, void *Buffer, unsigned StubSize) { + SaveStateTo(BS); + + BufferBegin = CurBufferPtr = (uint8_t *)Buffer; + BufferEnd = BufferBegin+StubSize+1; +} + +void *JITEmitter::finishGVStub(BufferState &BS) { + assert(CurBufferPtr != BufferEnd && "Stub overflowed allocated space."); + NumBytes += getCurrentPCOffset(); + void *Result = BufferBegin; + RestoreStateFrom(BS); + return Result; +} + +// getConstantPoolEntryAddress - Return the address of the 'ConstantNum' entry +// in the constant pool that was last emitted with the 'emitConstantPool' +// method. +// +uintptr_t JITEmitter::getConstantPoolEntryAddress(unsigned ConstantNum) const { + assert(ConstantNum < ConstantPool->getConstants().size() && + "Invalid ConstantPoolIndex!"); + return ConstPoolAddresses[ConstantNum]; +} + +// getJumpTableEntryAddress - Return the address of the JumpTable with index +// 'Index' in the jumpp table that was last initialized with 'initJumpTableInfo' +// +uintptr_t JITEmitter::getJumpTableEntryAddress(unsigned Index) const { + const std::vector &JT = JumpTable->getJumpTables(); + assert(Index < JT.size() && "Invalid jump table index!"); + + unsigned Offset = 0; + unsigned EntrySize = JumpTable->getEntrySize(); + + for (unsigned i = 0; i < Index; ++i) + Offset += JT[i].MBBs.size(); + + Offset *= EntrySize; + + return (uintptr_t)((char *)JumpTableBase + Offset); +} + +void JITEmitter::EmittedFunctionConfig::onDelete( + JITEmitter *Emitter, const Function *F) { + Emitter->deallocateMemForFunction(F); +} +void JITEmitter::EmittedFunctionConfig::onRAUW( + JITEmitter *, const Function*, const Function*) { + llvm_unreachable("The JIT doesn't know how to handle a" + " RAUW on a value it has emitted."); +} + + +//===----------------------------------------------------------------------===// +// Public interface to this file +//===----------------------------------------------------------------------===// + +JITCodeEmitter *JIT::createEmitter(JIT &jit, JITMemoryManager *JMM, + TargetMachine &tm) { + return new JITEmitter(jit, JMM, tm); +} + +// getPointerToNamedFunction - This function is used as a global wrapper to +// JIT::getPointerToNamedFunction for the purpose of resolving symbols when +// bugpoint is debugging the JIT. In that scenario, we are loading an .so and +// need to resolve function(s) that are being mis-codegenerated, so we need to +// resolve their addresses at runtime, and this is the way to do it. +extern "C" { + void *getPointerToNamedFunction(const char *Name) { + if (Function *F = TheJIT->FindFunctionNamed(Name)) + return TheJIT->getPointerToFunction(F); + return TheJIT->getPointerToNamedFunction(Name); + } +} + +// getPointerToFunctionOrStub - If the specified function has been +// code-gen'd, return a pointer to the function. If not, compile it, or use +// a stub to implement lazy compilation if available. +// +void *JIT::getPointerToFunctionOrStub(Function *F) { + // If we have already code generated the function, just return the address. + if (void *Addr = getPointerToGlobalIfAvailable(F)) + return Addr; + + // Get a stub if the target supports it. + assert(isa(JCE) && "Unexpected MCE?"); + JITEmitter *JE = cast(getCodeEmitter()); + return JE->getJITResolver().getLazyFunctionStub(F); +} + +void JIT::updateFunctionStub(Function *F) { + // Get the empty stub we generated earlier. + assert(isa(JCE) && "Unexpected MCE?"); + JITEmitter *JE = cast(getCodeEmitter()); + void *Stub = JE->getJITResolver().getLazyFunctionStub(F); + void *Addr = getPointerToGlobalIfAvailable(F); + + // Tell the target jit info to rewrite the stub at the specified address, + // rather than creating a new one. + MachineCodeEmitter::BufferState BS; + TargetJITInfo::StubLayout layout = getJITInfo().getStubLayout(); + JE->startGVStub(BS, Stub, layout.Size); + getJITInfo().emitFunctionStub(F, Addr, *getCodeEmitter()); + JE->finishGVStub(BS); +} + +/// freeMachineCodeForFunction - release machine code memory for given Function. +/// +void JIT::freeMachineCodeForFunction(Function *F) { + // Delete translation for this from the ExecutionEngine, so it will get + // retranslated next time it is used. + updateGlobalMapping(F, 0); + + // Free the actual memory for the function body and related stuff. + assert(isa(JCE) && "Unexpected MCE?"); + cast(JCE)->deallocateMemForFunction(F); +} diff --git a/libclamav/c++/llvm/lib/ExecutionEngine/JIT/JITMemoryManager.cpp b/libclamav/c++/llvm/lib/ExecutionEngine/JIT/JITMemoryManager.cpp new file mode 100644 index 000000000..80cb999a9 --- /dev/null +++ b/libclamav/c++/llvm/lib/ExecutionEngine/JIT/JITMemoryManager.cpp @@ -0,0 +1,729 @@ +//===-- JITMemoryManager.cpp - Memory Allocator for JIT'd code ------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the DefaultJITMemoryManager class. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "jit" +#include "llvm/ExecutionEngine/JITMemoryManager.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/GlobalValue.h" +#include "llvm/Support/Allocator.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/System/Memory.h" +#include +#include +#include +#include +#include +#include +#include +using namespace llvm; + +STATISTIC(NumSlabs, "Number of slabs of memory allocated by the JIT"); + +JITMemoryManager::~JITMemoryManager() {} + +//===----------------------------------------------------------------------===// +// Memory Block Implementation. +//===----------------------------------------------------------------------===// + +namespace { + /// MemoryRangeHeader - For a range of memory, this is the header that we put + /// on the block of memory. It is carefully crafted to be one word of memory. + /// Allocated blocks have just this header, free'd blocks have FreeRangeHeader + /// which starts with this. + struct FreeRangeHeader; + struct MemoryRangeHeader { + /// ThisAllocated - This is true if this block is currently allocated. If + /// not, this can be converted to a FreeRangeHeader. + unsigned ThisAllocated : 1; + + /// PrevAllocated - Keep track of whether the block immediately before us is + /// allocated. If not, the word immediately before this header is the size + /// of the previous block. + unsigned PrevAllocated : 1; + + /// BlockSize - This is the size in bytes of this memory block, + /// including this header. + uintptr_t BlockSize : (sizeof(intptr_t)*CHAR_BIT - 2); + + + /// getBlockAfter - Return the memory block immediately after this one. + /// + MemoryRangeHeader &getBlockAfter() const { + return *(MemoryRangeHeader*)((char*)this+BlockSize); + } + + /// getFreeBlockBefore - If the block before this one is free, return it, + /// otherwise return null. + FreeRangeHeader *getFreeBlockBefore() const { + if (PrevAllocated) return 0; + intptr_t PrevSize = ((intptr_t *)this)[-1]; + return (FreeRangeHeader*)((char*)this-PrevSize); + } + + /// FreeBlock - Turn an allocated block into a free block, adjusting + /// bits in the object headers, and adding an end of region memory block. + FreeRangeHeader *FreeBlock(FreeRangeHeader *FreeList); + + /// TrimAllocationToSize - If this allocated block is significantly larger + /// than NewSize, split it into two pieces (where the former is NewSize + /// bytes, including the header), and add the new block to the free list. + FreeRangeHeader *TrimAllocationToSize(FreeRangeHeader *FreeList, + uint64_t NewSize); + }; + + /// FreeRangeHeader - For a memory block that isn't already allocated, this + /// keeps track of the current block and has a pointer to the next free block. + /// Free blocks are kept on a circularly linked list. + struct FreeRangeHeader : public MemoryRangeHeader { + FreeRangeHeader *Prev; + FreeRangeHeader *Next; + + /// getMinBlockSize - Get the minimum size for a memory block. Blocks + /// smaller than this size cannot be created. + static unsigned getMinBlockSize() { + return sizeof(FreeRangeHeader)+sizeof(intptr_t); + } + + /// SetEndOfBlockSizeMarker - The word at the end of every free block is + /// known to be the size of the free block. Set it for this block. + void SetEndOfBlockSizeMarker() { + void *EndOfBlock = (char*)this + BlockSize; + ((intptr_t *)EndOfBlock)[-1] = BlockSize; + } + + FreeRangeHeader *RemoveFromFreeList() { + assert(Next->Prev == this && Prev->Next == this && "Freelist broken!"); + Next->Prev = Prev; + return Prev->Next = Next; + } + + void AddToFreeList(FreeRangeHeader *FreeList) { + Next = FreeList; + Prev = FreeList->Prev; + Prev->Next = this; + Next->Prev = this; + } + + /// GrowBlock - The block after this block just got deallocated. Merge it + /// into the current block. + void GrowBlock(uintptr_t NewSize); + + /// AllocateBlock - Mark this entire block allocated, updating freelists + /// etc. This returns a pointer to the circular free-list. + FreeRangeHeader *AllocateBlock(); + }; +} + + +/// AllocateBlock - Mark this entire block allocated, updating freelists +/// etc. This returns a pointer to the circular free-list. +FreeRangeHeader *FreeRangeHeader::AllocateBlock() { + assert(!ThisAllocated && !getBlockAfter().PrevAllocated && + "Cannot allocate an allocated block!"); + // Mark this block allocated. + ThisAllocated = 1; + getBlockAfter().PrevAllocated = 1; + + // Remove it from the free list. + return RemoveFromFreeList(); +} + +/// FreeBlock - Turn an allocated block into a free block, adjusting +/// bits in the object headers, and adding an end of region memory block. +/// If possible, coalesce this block with neighboring blocks. Return the +/// FreeRangeHeader to allocate from. +FreeRangeHeader *MemoryRangeHeader::FreeBlock(FreeRangeHeader *FreeList) { + MemoryRangeHeader *FollowingBlock = &getBlockAfter(); + assert(ThisAllocated && "This block is already free!"); + assert(FollowingBlock->PrevAllocated && "Flags out of sync!"); + + FreeRangeHeader *FreeListToReturn = FreeList; + + // If the block after this one is free, merge it into this block. + if (!FollowingBlock->ThisAllocated) { + FreeRangeHeader &FollowingFreeBlock = *(FreeRangeHeader *)FollowingBlock; + // "FreeList" always needs to be a valid free block. If we're about to + // coalesce with it, update our notion of what the free list is. + if (&FollowingFreeBlock == FreeList) { + FreeList = FollowingFreeBlock.Next; + FreeListToReturn = 0; + assert(&FollowingFreeBlock != FreeList && "No tombstone block?"); + } + FollowingFreeBlock.RemoveFromFreeList(); + + // Include the following block into this one. + BlockSize += FollowingFreeBlock.BlockSize; + FollowingBlock = &FollowingFreeBlock.getBlockAfter(); + + // Tell the block after the block we are coalescing that this block is + // allocated. + FollowingBlock->PrevAllocated = 1; + } + + assert(FollowingBlock->ThisAllocated && "Missed coalescing?"); + + if (FreeRangeHeader *PrevFreeBlock = getFreeBlockBefore()) { + PrevFreeBlock->GrowBlock(PrevFreeBlock->BlockSize + BlockSize); + return FreeListToReturn ? FreeListToReturn : PrevFreeBlock; + } + + // Otherwise, mark this block free. + FreeRangeHeader &FreeBlock = *(FreeRangeHeader*)this; + FollowingBlock->PrevAllocated = 0; + FreeBlock.ThisAllocated = 0; + + // Link this into the linked list of free blocks. + FreeBlock.AddToFreeList(FreeList); + + // Add a marker at the end of the block, indicating the size of this free + // block. + FreeBlock.SetEndOfBlockSizeMarker(); + return FreeListToReturn ? FreeListToReturn : &FreeBlock; +} + +/// GrowBlock - The block after this block just got deallocated. Merge it +/// into the current block. +void FreeRangeHeader::GrowBlock(uintptr_t NewSize) { + assert(NewSize > BlockSize && "Not growing block?"); + BlockSize = NewSize; + SetEndOfBlockSizeMarker(); + getBlockAfter().PrevAllocated = 0; +} + +/// TrimAllocationToSize - If this allocated block is significantly larger +/// than NewSize, split it into two pieces (where the former is NewSize +/// bytes, including the header), and add the new block to the free list. +FreeRangeHeader *MemoryRangeHeader:: +TrimAllocationToSize(FreeRangeHeader *FreeList, uint64_t NewSize) { + assert(ThisAllocated && getBlockAfter().PrevAllocated && + "Cannot deallocate part of an allocated block!"); + + // Don't allow blocks to be trimmed below minimum required size + NewSize = std::max(FreeRangeHeader::getMinBlockSize(), NewSize); + + // Round up size for alignment of header. + unsigned HeaderAlign = __alignof(FreeRangeHeader); + NewSize = (NewSize+ (HeaderAlign-1)) & ~(HeaderAlign-1); + + // Size is now the size of the block we will remove from the start of the + // current block. + assert(NewSize <= BlockSize && + "Allocating more space from this block than exists!"); + + // If splitting this block will cause the remainder to be too small, do not + // split the block. + if (BlockSize <= NewSize+FreeRangeHeader::getMinBlockSize()) + return FreeList; + + // Otherwise, we splice the required number of bytes out of this block, form + // a new block immediately after it, then mark this block allocated. + MemoryRangeHeader &FormerNextBlock = getBlockAfter(); + + // Change the size of this block. + BlockSize = NewSize; + + // Get the new block we just sliced out and turn it into a free block. + FreeRangeHeader &NewNextBlock = (FreeRangeHeader &)getBlockAfter(); + NewNextBlock.BlockSize = (char*)&FormerNextBlock - (char*)&NewNextBlock; + NewNextBlock.ThisAllocated = 0; + NewNextBlock.PrevAllocated = 1; + NewNextBlock.SetEndOfBlockSizeMarker(); + FormerNextBlock.PrevAllocated = 0; + NewNextBlock.AddToFreeList(FreeList); + return &NewNextBlock; +} + +//===----------------------------------------------------------------------===// +// Memory Block Implementation. +//===----------------------------------------------------------------------===// + +namespace { + + class DefaultJITMemoryManager; + + class JITSlabAllocator : public SlabAllocator { + DefaultJITMemoryManager &JMM; + public: + JITSlabAllocator(DefaultJITMemoryManager &jmm) : JMM(jmm) { } + virtual ~JITSlabAllocator() { } + virtual MemSlab *Allocate(size_t Size); + virtual void Deallocate(MemSlab *Slab); + }; + + /// DefaultJITMemoryManager - Manage memory for the JIT code generation. + /// This splits a large block of MAP_NORESERVE'd memory into two + /// sections, one for function stubs, one for the functions themselves. We + /// have to do this because we may need to emit a function stub while in the + /// middle of emitting a function, and we don't know how large the function we + /// are emitting is. + class DefaultJITMemoryManager : public JITMemoryManager { + + // Whether to poison freed memory. + bool PoisonMemory; + + /// LastSlab - This points to the last slab allocated and is used as the + /// NearBlock parameter to AllocateRWX so that we can attempt to lay out all + /// stubs, data, and code contiguously in memory. In general, however, this + /// is not possible because the NearBlock parameter is ignored on Windows + /// platforms and even on Unix it works on a best-effort pasis. + sys::MemoryBlock LastSlab; + + // Memory slabs allocated by the JIT. We refer to them as slabs so we don't + // confuse them with the blocks of memory described above. + std::vector CodeSlabs; + JITSlabAllocator BumpSlabAllocator; + BumpPtrAllocator StubAllocator; + BumpPtrAllocator DataAllocator; + + // Circular list of free blocks. + FreeRangeHeader *FreeMemoryList; + + // When emitting code into a memory block, this is the block. + MemoryRangeHeader *CurBlock; + + uint8_t *GOTBase; // Target Specific reserved memory + public: + DefaultJITMemoryManager(); + ~DefaultJITMemoryManager(); + + /// allocateNewSlab - Allocates a new MemoryBlock and remembers it as the + /// last slab it allocated, so that subsequent allocations follow it. + sys::MemoryBlock allocateNewSlab(size_t size); + + /// DefaultCodeSlabSize - When we have to go map more memory, we allocate at + /// least this much unless more is requested. + static const size_t DefaultCodeSlabSize; + + /// DefaultSlabSize - Allocate data into slabs of this size unless we get + /// an allocation above SizeThreshold. + static const size_t DefaultSlabSize; + + /// DefaultSizeThreshold - For any allocation larger than this threshold, we + /// should allocate a separate slab. + static const size_t DefaultSizeThreshold; + + void AllocateGOT(); + + // Testing methods. + virtual bool CheckInvariants(std::string &ErrorStr); + size_t GetDefaultCodeSlabSize() { return DefaultCodeSlabSize; } + size_t GetDefaultDataSlabSize() { return DefaultSlabSize; } + size_t GetDefaultStubSlabSize() { return DefaultSlabSize; } + unsigned GetNumCodeSlabs() { return CodeSlabs.size(); } + unsigned GetNumDataSlabs() { return DataAllocator.GetNumSlabs(); } + unsigned GetNumStubSlabs() { return StubAllocator.GetNumSlabs(); } + + /// startFunctionBody - When a function starts, allocate a block of free + /// executable memory, returning a pointer to it and its actual size. + uint8_t *startFunctionBody(const Function *F, uintptr_t &ActualSize) { + + FreeRangeHeader* candidateBlock = FreeMemoryList; + FreeRangeHeader* head = FreeMemoryList; + FreeRangeHeader* iter = head->Next; + + uintptr_t largest = candidateBlock->BlockSize; + + // Search for the largest free block + while (iter != head) { + if (iter->BlockSize > largest) { + largest = iter->BlockSize; + candidateBlock = iter; + } + iter = iter->Next; + } + + largest = largest - sizeof(MemoryRangeHeader); + + // If this block isn't big enough for the allocation desired, allocate + // another block of memory and add it to the free list. + if (largest < ActualSize || + largest <= FreeRangeHeader::getMinBlockSize()) { + DEBUG(errs() << "JIT: Allocating another slab of memory for function."); + candidateBlock = allocateNewCodeSlab((size_t)ActualSize); + } + + // Select this candidate block for allocation + CurBlock = candidateBlock; + + // Allocate the entire memory block. + FreeMemoryList = candidateBlock->AllocateBlock(); + ActualSize = CurBlock->BlockSize - sizeof(MemoryRangeHeader); + return (uint8_t *)(CurBlock + 1); + } + + /// allocateNewCodeSlab - Helper method to allocate a new slab of code + /// memory from the OS and add it to the free list. Returns the new + /// FreeRangeHeader at the base of the slab. + FreeRangeHeader *allocateNewCodeSlab(size_t MinSize) { + // If the user needs at least MinSize free memory, then we account for + // two MemoryRangeHeaders: the one in the user's block, and the one at the + // end of the slab. + size_t PaddedMin = MinSize + 2 * sizeof(MemoryRangeHeader); + size_t SlabSize = std::max(DefaultCodeSlabSize, PaddedMin); + sys::MemoryBlock B = allocateNewSlab(SlabSize); + CodeSlabs.push_back(B); + char *MemBase = (char*)(B.base()); + + // Put a tiny allocated block at the end of the memory chunk, so when + // FreeBlock calls getBlockAfter it doesn't fall off the end. + MemoryRangeHeader *EndBlock = + (MemoryRangeHeader*)(MemBase + B.size()) - 1; + EndBlock->ThisAllocated = 1; + EndBlock->PrevAllocated = 0; + EndBlock->BlockSize = sizeof(MemoryRangeHeader); + + // Start out with a vast new block of free memory. + FreeRangeHeader *NewBlock = (FreeRangeHeader*)MemBase; + NewBlock->ThisAllocated = 0; + // Make sure getFreeBlockBefore doesn't look into unmapped memory. + NewBlock->PrevAllocated = 1; + NewBlock->BlockSize = (uintptr_t)EndBlock - (uintptr_t)NewBlock; + NewBlock->SetEndOfBlockSizeMarker(); + NewBlock->AddToFreeList(FreeMemoryList); + + assert(NewBlock->BlockSize - sizeof(MemoryRangeHeader) >= MinSize && + "The block was too small!"); + return NewBlock; + } + + /// endFunctionBody - The function F is now allocated, and takes the memory + /// in the range [FunctionStart,FunctionEnd). + void endFunctionBody(const Function *F, uint8_t *FunctionStart, + uint8_t *FunctionEnd) { + assert(FunctionEnd > FunctionStart); + assert(FunctionStart == (uint8_t *)(CurBlock+1) && + "Mismatched function start/end!"); + + uintptr_t BlockSize = FunctionEnd - (uint8_t *)CurBlock; + + // Release the memory at the end of this block that isn't needed. + FreeMemoryList =CurBlock->TrimAllocationToSize(FreeMemoryList, BlockSize); + } + + /// allocateSpace - Allocate a memory block of the given size. This method + /// cannot be called between calls to startFunctionBody and endFunctionBody. + uint8_t *allocateSpace(intptr_t Size, unsigned Alignment) { + CurBlock = FreeMemoryList; + FreeMemoryList = FreeMemoryList->AllocateBlock(); + + uint8_t *result = (uint8_t *)(CurBlock + 1); + + if (Alignment == 0) Alignment = 1; + result = (uint8_t*)(((intptr_t)result+Alignment-1) & + ~(intptr_t)(Alignment-1)); + + uintptr_t BlockSize = result + Size - (uint8_t *)CurBlock; + FreeMemoryList =CurBlock->TrimAllocationToSize(FreeMemoryList, BlockSize); + + return result; + } + + /// allocateStub - Allocate memory for a function stub. + uint8_t *allocateStub(const GlobalValue* F, unsigned StubSize, + unsigned Alignment) { + return (uint8_t*)StubAllocator.Allocate(StubSize, Alignment); + } + + /// allocateGlobal - Allocate memory for a global. + uint8_t *allocateGlobal(uintptr_t Size, unsigned Alignment) { + return (uint8_t*)DataAllocator.Allocate(Size, Alignment); + } + + /// startExceptionTable - Use startFunctionBody to allocate memory for the + /// function's exception table. + uint8_t* startExceptionTable(const Function* F, uintptr_t &ActualSize) { + return startFunctionBody(F, ActualSize); + } + + /// endExceptionTable - The exception table of F is now allocated, + /// and takes the memory in the range [TableStart,TableEnd). + void endExceptionTable(const Function *F, uint8_t *TableStart, + uint8_t *TableEnd, uint8_t* FrameRegister) { + assert(TableEnd > TableStart); + assert(TableStart == (uint8_t *)(CurBlock+1) && + "Mismatched table start/end!"); + + uintptr_t BlockSize = TableEnd - (uint8_t *)CurBlock; + + // Release the memory at the end of this block that isn't needed. + FreeMemoryList =CurBlock->TrimAllocationToSize(FreeMemoryList, BlockSize); + } + + uint8_t *getGOTBase() const { + return GOTBase; + } + + void deallocateBlock(void *Block) { + // Find the block that is allocated for this function. + MemoryRangeHeader *MemRange = static_cast(Block) - 1; + assert(MemRange->ThisAllocated && "Block isn't allocated!"); + + // Fill the buffer with garbage! + if (PoisonMemory) { + memset(MemRange+1, 0xCD, MemRange->BlockSize-sizeof(*MemRange)); + } + + // Free the memory. + FreeMemoryList = MemRange->FreeBlock(FreeMemoryList); + } + + /// deallocateFunctionBody - Deallocate all memory for the specified + /// function body. + void deallocateFunctionBody(void *Body) { + if (Body) deallocateBlock(Body); + } + + /// deallocateExceptionTable - Deallocate memory for the specified + /// exception table. + void deallocateExceptionTable(void *ET) { + if (ET) deallocateBlock(ET); + } + + /// setMemoryWritable - When code generation is in progress, + /// the code pages may need permissions changed. + void setMemoryWritable() + { + for (unsigned i = 0, e = CodeSlabs.size(); i != e; ++i) + sys::Memory::setWritable(CodeSlabs[i]); + } + /// setMemoryExecutable - When code generation is done and we're ready to + /// start execution, the code pages may need permissions changed. + void setMemoryExecutable() + { + for (unsigned i = 0, e = CodeSlabs.size(); i != e; ++i) + sys::Memory::setExecutable(CodeSlabs[i]); + } + + /// setPoisonMemory - Controls whether we write garbage over freed memory. + /// + void setPoisonMemory(bool poison) { + PoisonMemory = poison; + } + }; +} + +MemSlab *JITSlabAllocator::Allocate(size_t Size) { + sys::MemoryBlock B = JMM.allocateNewSlab(Size); + MemSlab *Slab = (MemSlab*)B.base(); + Slab->Size = B.size(); + Slab->NextPtr = 0; + return Slab; +} + +void JITSlabAllocator::Deallocate(MemSlab *Slab) { + sys::MemoryBlock B(Slab, Slab->Size); + sys::Memory::ReleaseRWX(B); +} + +DefaultJITMemoryManager::DefaultJITMemoryManager() + : +#ifdef NDEBUG + PoisonMemory(false), +#else + PoisonMemory(true), +#endif + LastSlab(0, 0), + BumpSlabAllocator(*this), + StubAllocator(DefaultSlabSize, DefaultSizeThreshold, BumpSlabAllocator), + DataAllocator(DefaultSlabSize, DefaultSizeThreshold, BumpSlabAllocator) { + + // Allocate space for code. + sys::MemoryBlock MemBlock = allocateNewSlab(DefaultCodeSlabSize); + CodeSlabs.push_back(MemBlock); + uint8_t *MemBase = (uint8_t*)MemBlock.base(); + + // We set up the memory chunk with 4 mem regions, like this: + // [ START + // [ Free #0 ] -> Large space to allocate functions from. + // [ Allocated #1 ] -> Tiny space to separate regions. + // [ Free #2 ] -> Tiny space so there is always at least 1 free block. + // [ Allocated #3 ] -> Tiny space to prevent looking past end of block. + // END ] + // + // The last three blocks are never deallocated or touched. + + // Add MemoryRangeHeader to the end of the memory region, indicating that + // the space after the block of memory is allocated. This is block #3. + MemoryRangeHeader *Mem3 = (MemoryRangeHeader*)(MemBase+MemBlock.size())-1; + Mem3->ThisAllocated = 1; + Mem3->PrevAllocated = 0; + Mem3->BlockSize = sizeof(MemoryRangeHeader); + + /// Add a tiny free region so that the free list always has one entry. + FreeRangeHeader *Mem2 = + (FreeRangeHeader *)(((char*)Mem3)-FreeRangeHeader::getMinBlockSize()); + Mem2->ThisAllocated = 0; + Mem2->PrevAllocated = 1; + Mem2->BlockSize = FreeRangeHeader::getMinBlockSize(); + Mem2->SetEndOfBlockSizeMarker(); + Mem2->Prev = Mem2; // Mem2 *is* the free list for now. + Mem2->Next = Mem2; + + /// Add a tiny allocated region so that Mem2 is never coalesced away. + MemoryRangeHeader *Mem1 = (MemoryRangeHeader*)Mem2-1; + Mem1->ThisAllocated = 1; + Mem1->PrevAllocated = 0; + Mem1->BlockSize = sizeof(MemoryRangeHeader); + + // Add a FreeRangeHeader to the start of the function body region, indicating + // that the space is free. Mark the previous block allocated so we never look + // at it. + FreeRangeHeader *Mem0 = (FreeRangeHeader*)MemBase; + Mem0->ThisAllocated = 0; + Mem0->PrevAllocated = 1; + Mem0->BlockSize = (char*)Mem1-(char*)Mem0; + Mem0->SetEndOfBlockSizeMarker(); + Mem0->AddToFreeList(Mem2); + + // Start out with the freelist pointing to Mem0. + FreeMemoryList = Mem0; + + GOTBase = NULL; +} + +void DefaultJITMemoryManager::AllocateGOT() { + assert(GOTBase == 0 && "Cannot allocate the got multiple times"); + GOTBase = new uint8_t[sizeof(void*) * 8192]; + HasGOT = true; +} + +DefaultJITMemoryManager::~DefaultJITMemoryManager() { + for (unsigned i = 0, e = CodeSlabs.size(); i != e; ++i) + sys::Memory::ReleaseRWX(CodeSlabs[i]); + + delete[] GOTBase; +} + +sys::MemoryBlock DefaultJITMemoryManager::allocateNewSlab(size_t size) { + // Allocate a new block close to the last one. + std::string ErrMsg; + sys::MemoryBlock *LastSlabPtr = LastSlab.base() ? &LastSlab : 0; + sys::MemoryBlock B = sys::Memory::AllocateRWX(size, LastSlabPtr, &ErrMsg); + if (B.base() == 0) { + llvm_report_error("Allocation failed when allocating new memory in the" + " JIT\n" + ErrMsg); + } + LastSlab = B; + ++NumSlabs; + // Initialize the slab to garbage when debugging. + if (PoisonMemory) { + memset(B.base(), 0xCD, B.size()); + } + return B; +} + +/// CheckInvariants - For testing only. Return "" if all internal invariants +/// are preserved, and a helpful error message otherwise. For free and +/// allocated blocks, make sure that adding BlockSize gives a valid block. +/// For free blocks, make sure they're in the free list and that their end of +/// block size marker is correct. This function should return an error before +/// accessing bad memory. This function is defined here instead of in +/// JITMemoryManagerTest.cpp so that we don't have to expose all of the +/// implementation details of DefaultJITMemoryManager. +bool DefaultJITMemoryManager::CheckInvariants(std::string &ErrorStr) { + raw_string_ostream Err(ErrorStr); + + // Construct a the set of FreeRangeHeader pointers so we can query it + // efficiently. + llvm::SmallPtrSet FreeHdrSet; + FreeRangeHeader* FreeHead = FreeMemoryList; + FreeRangeHeader* FreeRange = FreeHead; + + do { + // Check that the free range pointer is in the blocks we've allocated. + bool Found = false; + for (std::vector::iterator I = CodeSlabs.begin(), + E = CodeSlabs.end(); I != E && !Found; ++I) { + char *Start = (char*)I->base(); + char *End = Start + I->size(); + Found = (Start <= (char*)FreeRange && (char*)FreeRange < End); + } + if (!Found) { + Err << "Corrupt free list; points to " << FreeRange; + return false; + } + + if (FreeRange->Next->Prev != FreeRange) { + Err << "Next and Prev pointers do not match."; + return false; + } + + // Otherwise, add it to the set. + FreeHdrSet.insert(FreeRange); + FreeRange = FreeRange->Next; + } while (FreeRange != FreeHead); + + // Go over each block, and look at each MemoryRangeHeader. + for (std::vector::iterator I = CodeSlabs.begin(), + E = CodeSlabs.end(); I != E; ++I) { + char *Start = (char*)I->base(); + char *End = Start + I->size(); + + // Check each memory range. + for (MemoryRangeHeader *Hdr = (MemoryRangeHeader*)Start, *LastHdr = NULL; + Start <= (char*)Hdr && (char*)Hdr < End; + Hdr = &Hdr->getBlockAfter()) { + if (Hdr->ThisAllocated == 0) { + // Check that this range is in the free list. + if (!FreeHdrSet.count(Hdr)) { + Err << "Found free header at " << Hdr << " that is not in free list."; + return false; + } + + // Now make sure the size marker at the end of the block is correct. + uintptr_t *Marker = ((uintptr_t*)&Hdr->getBlockAfter()) - 1; + if (!(Start <= (char*)Marker && (char*)Marker < End)) { + Err << "Block size in header points out of current MemoryBlock."; + return false; + } + if (Hdr->BlockSize != *Marker) { + Err << "End of block size marker (" << *Marker << ") " + << "and BlockSize (" << Hdr->BlockSize << ") don't match."; + return false; + } + } + + if (LastHdr && LastHdr->ThisAllocated != Hdr->PrevAllocated) { + Err << "Hdr->PrevAllocated (" << Hdr->PrevAllocated << ") != " + << "LastHdr->ThisAllocated (" << LastHdr->ThisAllocated << ")"; + return false; + } else if (!LastHdr && !Hdr->PrevAllocated) { + Err << "The first header should have PrevAllocated true."; + return false; + } + + // Remember the last header. + LastHdr = Hdr; + } + } + + // All invariants are preserved. + return true; +} + +JITMemoryManager *JITMemoryManager::CreateDefaultMemManager() { + return new DefaultJITMemoryManager(); +} + +// Allocate memory for code in 512K slabs. +const size_t DefaultJITMemoryManager::DefaultCodeSlabSize = 512 * 1024; + +// Allocate globals and stubs in slabs of 64K. (probably 16 pages) +const size_t DefaultJITMemoryManager::DefaultSlabSize = 64 * 1024; + +// Waste at most 16K at the end of each bump slab. (probably 4 pages) +const size_t DefaultJITMemoryManager::DefaultSizeThreshold = 16 * 1024; diff --git a/libclamav/c++/llvm/lib/ExecutionEngine/JIT/Makefile b/libclamav/c++/llvm/lib/ExecutionEngine/JIT/Makefile new file mode 100644 index 000000000..e2c9c61e8 --- /dev/null +++ b/libclamav/c++/llvm/lib/ExecutionEngine/JIT/Makefile @@ -0,0 +1,37 @@ +##===- lib/ExecutionEngine/JIT/Makefile --------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## +LEVEL = ../../.. +LIBRARYNAME = LLVMJIT + +# Get the $(ARCH) setting +include $(LEVEL)/Makefile.config + +# Enable the X86 JIT if compiling on X86 +ifeq ($(ARCH), x86) + ENABLE_X86_JIT = 1 +endif + +# This flag can also be used on the command line to force inclusion +# of the X86 JIT on non-X86 hosts +ifdef ENABLE_X86_JIT + CPPFLAGS += -DENABLE_X86_JIT +endif + +# Enable the Sparc JIT if compiling on Sparc +ifeq ($(ARCH), Sparc) + ENABLE_SPARC_JIT = 1 +endif + +# This flag can also be used on the command line to force inclusion +# of the Sparc JIT on non-Sparc hosts +ifdef ENABLE_SPARC_JIT + CPPFLAGS += -DENABLE_SPARC_JIT +endif + +include $(LEVEL)/Makefile.common diff --git a/libclamav/c++/llvm/lib/ExecutionEngine/JIT/OProfileJITEventListener.cpp b/libclamav/c++/llvm/lib/ExecutionEngine/JIT/OProfileJITEventListener.cpp new file mode 100644 index 000000000..b45c71f4f --- /dev/null +++ b/libclamav/c++/llvm/lib/ExecutionEngine/JIT/OProfileJITEventListener.cpp @@ -0,0 +1,178 @@ +//===-- OProfileJITEventListener.cpp - Tell OProfile about JITted code ----===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines a JITEventListener object that calls into OProfile to tell +// it about JITted functions. For now, we only record function names and sizes, +// but eventually we'll also record line number information. +// +// See http://oprofile.sourceforge.net/doc/devel/jit-interface.html for the +// definition of the interface we're using. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "oprofile-jit-event-listener" +#include "llvm/Function.h" +#include "llvm/Analysis/DebugInfo.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/ExecutionEngine/JITEventListener.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/System/Errno.h" +#include "llvm/Config/config.h" +#include +using namespace llvm; + +#if USE_OPROFILE + +#include + +namespace { + +class OProfileJITEventListener : public JITEventListener { + op_agent_t Agent; +public: + OProfileJITEventListener(); + ~OProfileJITEventListener(); + + virtual void NotifyFunctionEmitted(const Function &F, + void *FnStart, size_t FnSize, + const EmittedFunctionDetails &Details); + virtual void NotifyFreeingMachineCode(void *OldPtr); +}; + +OProfileJITEventListener::OProfileJITEventListener() + : Agent(op_open_agent()) { + if (Agent == NULL) { + const std::string err_str = sys::StrError(); + DEBUG(errs() << "Failed to connect to OProfile agent: " << err_str << "\n"); + } else { + DEBUG(errs() << "Connected to OProfile agent.\n"); + } +} + +OProfileJITEventListener::~OProfileJITEventListener() { + if (Agent != NULL) { + if (op_close_agent(Agent) == -1) { + const std::string err_str = sys::StrError(); + DEBUG(errs() << "Failed to disconnect from OProfile agent: " + << err_str << "\n"); + } else { + DEBUG(errs() << "Disconnected from OProfile agent.\n"); + } + } +} + +class FilenameCache { + // Holds the filename of each Scope, so that we can pass the + // pointer into oprofile. These char*s are freed in the destructor. + DenseMap Filenames; + + public: + const char *getFilename(MDNode *Scope) { + char *&Filename = Filenames[Scope]; + if (Filename == NULL) { + DIScope S(Scope); + Filename = strdup(S.getFilename()); + } + return Filename; + } + ~FilenameCache() { + for (DenseMap::iterator + I = Filenames.begin(), E = Filenames.end(); I != E; ++I) { + free(I->second); + } + } +}; + +static debug_line_info LineStartToOProfileFormat( + const MachineFunction &MF, FilenameCache &Filenames, + uintptr_t Address, DebugLoc Loc) { + debug_line_info Result; + Result.vma = Address; + const DebugLocTuple &tuple = MF.getDebugLocTuple(Loc); + Result.lineno = tuple.Line; + Result.filename = Filenames.getFilename(tuple.Scope); + DEBUG(errs() << "Mapping " << reinterpret_cast(Result.vma) << " to " + << Result.filename << ":" << Result.lineno << "\n"); + return Result; +} + +// Adds the just-emitted function to the symbol table. +void OProfileJITEventListener::NotifyFunctionEmitted( + const Function &F, void *FnStart, size_t FnSize, + const EmittedFunctionDetails &Details) { + assert(F.hasName() && FnStart != 0 && "Bad symbol to add"); + if (op_write_native_code(Agent, F.getName().data(), + reinterpret_cast(FnStart), + FnStart, FnSize) == -1) { + DEBUG(errs() << "Failed to tell OProfile about native function " + << F.getName() << " at [" + << FnStart << "-" << ((char*)FnStart + FnSize) << "]\n"); + return; + } + + // Now we convert the line number information from the address/DebugLoc format + // in Details to the address/filename/lineno format that OProfile expects. + // OProfile 0.9.4 (and maybe later versions) has a bug that causes it to + // ignore line numbers for addresses above 4G. + FilenameCache Filenames; + std::vector LineInfo; + LineInfo.reserve(1 + Details.LineStarts.size()); + if (!Details.MF->getDefaultDebugLoc().isUnknown()) { + LineInfo.push_back(LineStartToOProfileFormat( + *Details.MF, Filenames, + reinterpret_cast(FnStart), + Details.MF->getDefaultDebugLoc())); + } + for (std::vector::const_iterator + I = Details.LineStarts.begin(), E = Details.LineStarts.end(); + I != E; ++I) { + LineInfo.push_back(LineStartToOProfileFormat( + *Details.MF, Filenames, I->Address, I->Loc)); + } + if (!LineInfo.empty()) { + if (op_write_debug_line_info(Agent, FnStart, + LineInfo.size(), &*LineInfo.begin()) == -1) { + DEBUG(errs() + << "Failed to tell OProfile about line numbers for native function " + << F.getName() << " at [" + << FnStart << "-" << ((char*)FnStart + FnSize) << "]\n"); + } + } +} + +// Removes the being-deleted function from the symbol table. +void OProfileJITEventListener::NotifyFreeingMachineCode(void *FnStart) { + assert(FnStart && "Invalid function pointer"); + if (op_unload_native_code(Agent, reinterpret_cast(FnStart)) == -1) { + DEBUG(errs() + << "Failed to tell OProfile about unload of native function at " + << FnStart << "\n"); + } +} + +} // anonymous namespace. + +namespace llvm { +JITEventListener *createOProfileJITEventListener() { + return new OProfileJITEventListener; +} +} + +#else // USE_OPROFILE + +namespace llvm { +// By defining this to return NULL, we can let clients call it unconditionally, +// even if they haven't configured with the OProfile libraries. +JITEventListener *createOProfileJITEventListener() { + return NULL; +} +} // namespace llvm + +#endif // USE_OPROFILE diff --git a/libclamav/c++/llvm/lib/ExecutionEngine/JIT/TargetSelect.cpp b/libclamav/c++/llvm/lib/ExecutionEngine/JIT/TargetSelect.cpp new file mode 100644 index 000000000..8bed33bb7 --- /dev/null +++ b/libclamav/c++/llvm/lib/ExecutionEngine/JIT/TargetSelect.cpp @@ -0,0 +1,106 @@ +//===-- TargetSelect.cpp - Target Chooser Code ----------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This just asks the TargetRegistry for the appropriate JIT to use, and allows +// the user to specify a specific one on the commandline with -march=x. Clients +// should initialize targets prior to calling createJIT. +// +//===----------------------------------------------------------------------===// + +#include "JIT.h" +#include "llvm/Module.h" +#include "llvm/ModuleProvider.h" +#include "llvm/ADT/Triple.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/System/Host.h" +#include "llvm/Target/SubtargetFeature.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetRegistry.h" +using namespace llvm; + +static cl::opt +MArch("march", + cl::desc("Architecture to generate assembly for (see --version)")); + +static cl::opt +MCPU("mcpu", + cl::desc("Target a specific cpu type (-mcpu=help for details)"), + cl::value_desc("cpu-name"), + cl::init("")); + +static cl::list +MAttrs("mattr", + cl::CommaSeparated, + cl::desc("Target specific attributes (-mattr=help for details)"), + cl::value_desc("a1,+a2,-a3,...")); + +/// selectTarget - Pick a target either via -march or by guessing the native +/// arch. Add any CPU features specified via -mcpu or -mattr. +TargetMachine *JIT::selectTarget(ModuleProvider *MP, std::string *ErrorStr) { + Module &Mod = *MP->getModule(); + + Triple TheTriple(Mod.getTargetTriple()); + if (TheTriple.getTriple().empty()) + TheTriple.setTriple(sys::getHostTriple()); + + // Adjust the triple to match what the user requested. + const Target *TheTarget = 0; + if (!MArch.empty()) { + for (TargetRegistry::iterator it = TargetRegistry::begin(), + ie = TargetRegistry::end(); it != ie; ++it) { + if (MArch == it->getName()) { + TheTarget = &*it; + break; + } + } + + if (!TheTarget) { + *ErrorStr = "No available targets are compatible with this -march, " + "see -version for the available targets.\n"; + return 0; + } + + // Adjust the triple to match (if known), otherwise stick with the + // module/host triple. + Triple::ArchType Type = Triple::getArchTypeForLLVMName(MArch); + if (Type != Triple::UnknownArch) + TheTriple.setArch(Type); + } else { + std::string Error; + TheTarget = TargetRegistry::lookupTarget(TheTriple.getTriple(), Error); + if (TheTarget == 0) { + if (ErrorStr) + *ErrorStr = Error; + return 0; + } + } + + if (!TheTarget->hasJIT()) { + errs() << "WARNING: This target JIT is not designed for the host you are" + << " running. If bad things happen, please choose a different " + << "-march switch.\n"; + } + + // Package up features to be passed to target/subtarget + std::string FeaturesStr; + if (!MCPU.empty() || !MAttrs.empty()) { + SubtargetFeatures Features; + Features.setCPU(MCPU); + for (unsigned i = 0; i != MAttrs.size(); ++i) + Features.AddFeature(MAttrs[i]); + FeaturesStr = Features.getString(); + } + + // Allocate a target... + TargetMachine *Target = + TheTarget->createTargetMachine(TheTriple.getTriple(), FeaturesStr); + assert(Target && "Could not allocate target machine!"); + return Target; +} diff --git a/libclamav/c++/llvm/lib/ExecutionEngine/Makefile b/libclamav/c++/llvm/lib/ExecutionEngine/Makefile new file mode 100644 index 000000000..e0e050e89 --- /dev/null +++ b/libclamav/c++/llvm/lib/ExecutionEngine/Makefile @@ -0,0 +1,13 @@ +##===- lib/ExecutionEngine/Makefile ------------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## +LEVEL = ../.. +LIBRARYNAME = LLVMExecutionEngine +PARALLEL_DIRS = Interpreter JIT + +include $(LEVEL)/Makefile.common diff --git a/libclamav/c++/llvm/lib/MC/CMakeLists.txt b/libclamav/c++/llvm/lib/MC/CMakeLists.txt new file mode 100644 index 000000000..8a1a05863 --- /dev/null +++ b/libclamav/c++/llvm/lib/MC/CMakeLists.txt @@ -0,0 +1,24 @@ +add_llvm_library(LLVMMC + MCAsmInfo.cpp + MCAsmInfoCOFF.cpp + MCAsmInfoDarwin.cpp + MCAsmLexer.cpp + MCAsmParser.cpp + MCAsmStreamer.cpp + MCAssembler.cpp + MCCodeEmitter.cpp + MCContext.cpp + MCDisassembler.cpp + MCExpr.cpp + MCInst.cpp + MCInstPrinter.cpp + MCMachOStreamer.cpp + MCNullStreamer.cpp + MCSection.cpp + MCSectionELF.cpp + MCSectionMachO.cpp + MCStreamer.cpp + MCSymbol.cpp + MCValue.cpp + TargetAsmParser.cpp + ) diff --git a/libclamav/c++/llvm/lib/MC/MCAsmInfo.cpp b/libclamav/c++/llvm/lib/MC/MCAsmInfo.cpp new file mode 100644 index 000000000..3e5c97d7a --- /dev/null +++ b/libclamav/c++/llvm/lib/MC/MCAsmInfo.cpp @@ -0,0 +1,107 @@ +//===-- MCAsmInfo.cpp - Asm Info -------------------------------------------==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines target asm properties related what form asm statements +// should take. +// +//===----------------------------------------------------------------------===// + +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/System/DataTypes.h" +#include +#include +using namespace llvm; + +MCAsmInfo::MCAsmInfo() { + ZeroFillDirective = 0; + NonexecutableStackDirective = 0; + NeedsSet = false; + MaxInstLength = 4; + PCSymbol = "$"; + SeparatorChar = ';'; + CommentColumn = 60; + CommentString = "#"; + GlobalPrefix = ""; + PrivateGlobalPrefix = "."; + LinkerPrivateGlobalPrefix = ""; + InlineAsmStart = "APP"; + InlineAsmEnd = "NO_APP"; + AssemblerDialect = 0; + AllowQuotesInName = false; + AllowNameToStartWithDigit = false; + ZeroDirective = "\t.zero\t"; + ZeroDirectiveSuffix = 0; + AsciiDirective = "\t.ascii\t"; + AscizDirective = "\t.asciz\t"; + Data8bitsDirective = "\t.byte\t"; + Data16bitsDirective = "\t.short\t"; + Data32bitsDirective = "\t.long\t"; + Data64bitsDirective = "\t.quad\t"; + SunStyleELFSectionSwitchSyntax = false; + UsesELFSectionDirectiveForBSS = false; + AlignDirective = "\t.align\t"; + AlignmentIsInBytes = true; + TextAlignFillValue = 0; + JumpTableDirective = 0; + PICJumpTableDirective = 0; + GlobalDirective = "\t.globl\t"; + SetDirective = 0; + LCOMMDirective = 0; + COMMDirective = "\t.comm\t"; + COMMDirectiveTakesAlignment = true; + HasDotTypeDotSizeDirective = true; + HasSingleParameterDotFile = true; + UsedDirective = 0; + WeakRefDirective = 0; + WeakDefDirective = 0; + // FIXME: These are ELFish - move to ELFMAI. + HiddenDirective = "\t.hidden\t"; + ProtectedDirective = "\t.protected\t"; + AbsoluteDebugSectionOffsets = false; + AbsoluteEHSectionOffsets = false; + HasLEB128 = false; + HasDotLocAndDotFile = false; + SupportsDebugInformation = false; + ExceptionsType = ExceptionHandling::None; + DwarfRequiresFrameSection = true; + DwarfUsesInlineInfoSection = false; + Is_EHSymbolPrivate = true; + GlobalEHDirective = 0; + SupportsWeakOmittedEHFrame = true; + DwarfSectionOffsetDirective = 0; + + AsmTransCBE = 0; +} + +MCAsmInfo::~MCAsmInfo() { +} + + +unsigned MCAsmInfo::getULEB128Size(unsigned Value) { + unsigned Size = 0; + do { + Value >>= 7; + Size += sizeof(int8_t); + } while (Value); + return Size; +} + +unsigned MCAsmInfo::getSLEB128Size(int Value) { + unsigned Size = 0; + int Sign = Value >> (8 * sizeof(Value) - 1); + bool IsMore; + + do { + unsigned Byte = Value & 0x7f; + Value >>= 7; + IsMore = Value != Sign || ((Byte ^ Sign) & 0x40) != 0; + Size += sizeof(int8_t); + } while (IsMore); + return Size; +} diff --git a/libclamav/c++/llvm/lib/MC/MCAsmInfoCOFF.cpp b/libclamav/c++/llvm/lib/MC/MCAsmInfoCOFF.cpp new file mode 100644 index 000000000..23b0dd779 --- /dev/null +++ b/libclamav/c++/llvm/lib/MC/MCAsmInfoCOFF.cpp @@ -0,0 +1,37 @@ +//===-- MCAsmInfoCOFF.cpp - COFF asm properties -----------------*- 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 target asm properties related what form asm statements +// should take in general on COFF-based targets +// +//===----------------------------------------------------------------------===// + +#include "llvm/MC/MCAsmInfoCOFF.h" +#include "llvm/ADT/SmallVector.h" +using namespace llvm; + +MCAsmInfoCOFF::MCAsmInfoCOFF() { + GlobalPrefix = "_"; + LCOMMDirective = "\t.lcomm\t"; + COMMDirectiveTakesAlignment = false; + HasDotTypeDotSizeDirective = false; + HasSingleParameterDotFile = false; + HiddenDirective = NULL; + PrivateGlobalPrefix = "L"; // Prefix for private global symbols + WeakRefDirective = "\t.weak\t"; + SetDirective = "\t.set\t"; + + // Set up DWARF directives + HasLEB128 = true; // Target asm supports leb128 directives (little-endian) + AbsoluteDebugSectionOffsets = true; + AbsoluteEHSectionOffsets = false; + SupportsDebugInformation = true; + DwarfSectionOffsetDirective = "\t.secrel32\t"; +} + diff --git a/libclamav/c++/llvm/lib/MC/MCAsmInfoDarwin.cpp b/libclamav/c++/llvm/lib/MC/MCAsmInfoDarwin.cpp new file mode 100644 index 000000000..d99120d4d --- /dev/null +++ b/libclamav/c++/llvm/lib/MC/MCAsmInfoDarwin.cpp @@ -0,0 +1,52 @@ +//===-- MCAsmInfoDarwin.cpp - Darwin asm properties -------------*- 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 target asm properties related what form asm statements +// should take in general on Darwin-based targets +// +//===----------------------------------------------------------------------===// + +#include "llvm/MC/MCAsmInfoDarwin.h" +using namespace llvm; + +MCAsmInfoDarwin::MCAsmInfoDarwin() { + // Common settings for all Darwin targets. + // Syntax: + GlobalPrefix = "_"; + PrivateGlobalPrefix = "L"; + LinkerPrivateGlobalPrefix = "l"; + NeedsSet = true; + AllowQuotesInName = true; + HasSingleParameterDotFile = false; + + AlignmentIsInBytes = false; + InlineAsmStart = " InlineAsm Start"; + InlineAsmEnd = " InlineAsm End"; + + // Directives: + WeakDefDirective = "\t.weak_definition "; + WeakRefDirective = "\t.weak_reference "; + HiddenDirective = "\t.private_extern "; + LCOMMDirective = "\t.lcomm\t"; + ZeroDirective = "\t.space\t"; // ".space N" emits N zeros. + ZeroFillDirective = "\t.zerofill\t"; // Uses .zerofill + SetDirective = "\t.set"; + ProtectedDirective = "\t.globl\t"; + HasDotTypeDotSizeDirective = false; + UsedDirective = "\t.no_dead_strip\t"; + + // _foo.eh symbols are currently always exported so that the linker knows + // about them. This is not necessary on 10.6 and later, but it + // doesn't hurt anything. + // FIXME: I need to get this from Triple. + Is_EHSymbolPrivate = false; + GlobalEHDirective = "\t.globl\t"; + SupportsWeakOmittedEHFrame = false; +} + diff --git a/libclamav/c++/llvm/lib/MC/MCAsmLexer.cpp b/libclamav/c++/llvm/lib/MC/MCAsmLexer.cpp new file mode 100644 index 000000000..1e34ed6f7 --- /dev/null +++ b/libclamav/c++/llvm/lib/MC/MCAsmLexer.cpp @@ -0,0 +1,23 @@ +//===-- MCAsmLexer.cpp - Abstract Asm Lexer Interface ---------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/MC/MCAsmLexer.h" +#include "llvm/Support/SourceMgr.h" + +using namespace llvm; + +MCAsmLexer::MCAsmLexer() : CurTok(AsmToken::Error, StringRef()) { +} + +MCAsmLexer::~MCAsmLexer() { +} + +SMLoc AsmToken::getLoc() const { + return SMLoc::getFromPointer(Str.data()); +} diff --git a/libclamav/c++/llvm/lib/MC/MCAsmParser.cpp b/libclamav/c++/llvm/lib/MC/MCAsmParser.cpp new file mode 100644 index 000000000..2287e8965 --- /dev/null +++ b/libclamav/c++/llvm/lib/MC/MCAsmParser.cpp @@ -0,0 +1,18 @@ +//===-- MCAsmParser.cpp - Abstract Asm Parser Interface -------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/MC/MCAsmParser.h" + +using namespace llvm; + +MCAsmParser::MCAsmParser() { +} + +MCAsmParser::~MCAsmParser() { +} diff --git a/libclamav/c++/llvm/lib/MC/MCAsmStreamer.cpp b/libclamav/c++/llvm/lib/MC/MCAsmStreamer.cpp new file mode 100644 index 000000000..b6ebb1abb --- /dev/null +++ b/libclamav/c++/llvm/lib/MC/MCAsmStreamer.cpp @@ -0,0 +1,310 @@ +//===- lib/MC/MCAsmStreamer.cpp - Text Assembly Output --------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/MC/MCStreamer.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCCodeEmitter.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCInst.h" +#include "llvm/MC/MCInstPrinter.h" +#include "llvm/MC/MCSectionMachO.h" +#include "llvm/MC/MCSymbol.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/Support/Format.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +namespace { + +class MCAsmStreamer : public MCStreamer { + raw_ostream &OS; + const MCAsmInfo &MAI; + MCInstPrinter *InstPrinter; + MCCodeEmitter *Emitter; +public: + MCAsmStreamer(MCContext &Context, raw_ostream &_OS, const MCAsmInfo &tai, + MCInstPrinter *_Printer, MCCodeEmitter *_Emitter) + : MCStreamer(Context), OS(_OS), MAI(tai), InstPrinter(_Printer), + Emitter(_Emitter) {} + ~MCAsmStreamer() {} + + /// @name MCStreamer Interface + /// @{ + + virtual void SwitchSection(const MCSection *Section); + + virtual void EmitLabel(MCSymbol *Symbol); + + virtual void EmitAssemblerFlag(AssemblerFlag Flag); + + virtual void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value); + + virtual void EmitSymbolAttribute(MCSymbol *Symbol, SymbolAttr Attribute); + + virtual void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue); + + virtual void EmitCommonSymbol(MCSymbol *Symbol, unsigned Size, + unsigned ByteAlignment); + + virtual void EmitZerofill(const MCSection *Section, MCSymbol *Symbol = 0, + unsigned Size = 0, unsigned ByteAlignment = 0); + + virtual void EmitBytes(StringRef Data); + + virtual void EmitValue(const MCExpr *Value, unsigned Size); + + virtual void EmitValueToAlignment(unsigned ByteAlignment, int64_t Value = 0, + unsigned ValueSize = 1, + unsigned MaxBytesToEmit = 0); + + virtual void EmitValueToOffset(const MCExpr *Offset, + unsigned char Value = 0); + + virtual void EmitInstruction(const MCInst &Inst); + + virtual void Finish(); + + /// @} +}; + +} // end anonymous namespace. + +static inline int64_t truncateToSize(int64_t Value, unsigned Bytes) { + assert(Bytes && "Invalid size!"); + return Value & ((uint64_t) (int64_t) -1 >> (64 - Bytes * 8)); +} + +static inline const MCExpr *truncateToSize(const MCExpr *Value, + unsigned Bytes) { + // FIXME: Do we really need this routine? + return Value; +} + +void MCAsmStreamer::SwitchSection(const MCSection *Section) { + assert(Section && "Cannot switch to a null section!"); + if (Section != CurSection) { + CurSection = Section; + Section->PrintSwitchToSection(MAI, OS); + } +} + +void MCAsmStreamer::EmitLabel(MCSymbol *Symbol) { + assert(Symbol->isUndefined() && "Cannot define a symbol twice!"); + assert(CurSection && "Cannot emit before setting section!"); + + Symbol->print(OS, &MAI); + OS << ":\n"; + Symbol->setSection(*CurSection); +} + +void MCAsmStreamer::EmitAssemblerFlag(AssemblerFlag Flag) { + switch (Flag) { + default: assert(0 && "Invalid flag!"); + case SubsectionsViaSymbols: OS << ".subsections_via_symbols"; break; + } + OS << '\n'; +} + +void MCAsmStreamer::EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) { + // Only absolute symbols can be redefined. + assert((Symbol->isUndefined() || Symbol->isAbsolute()) && + "Cannot define a symbol twice!"); + + Symbol->print(OS, &MAI); + OS << " = "; + Value->print(OS, &MAI); + OS << '\n'; + + // FIXME: Lift context changes into super class. + // FIXME: Set associated section. + Symbol->setValue(Value); +} + +void MCAsmStreamer::EmitSymbolAttribute(MCSymbol *Symbol, + SymbolAttr Attribute) { + switch (Attribute) { + case Global: OS << ".globl"; break; + case Hidden: OS << ".hidden"; break; + case IndirectSymbol: OS << ".indirect_symbol"; break; + case Internal: OS << ".internal"; break; + case LazyReference: OS << ".lazy_reference"; break; + case NoDeadStrip: OS << ".no_dead_strip"; break; + case PrivateExtern: OS << ".private_extern"; break; + case Protected: OS << ".protected"; break; + case Reference: OS << ".reference"; break; + case Weak: OS << ".weak"; break; + case WeakDefinition: OS << ".weak_definition"; break; + case WeakReference: OS << ".weak_reference"; break; + } + + OS << ' '; + Symbol->print(OS, &MAI); + OS << '\n'; +} + +void MCAsmStreamer::EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) { + OS << ".desc" << ' '; + Symbol->print(OS, &MAI); + OS << ',' << DescValue << '\n'; +} + +void MCAsmStreamer::EmitCommonSymbol(MCSymbol *Symbol, unsigned Size, + unsigned ByteAlignment) { + OS << ".comm "; + Symbol->print(OS, &MAI); + OS << ',' << Size; + if (ByteAlignment != 0) + OS << ',' << Log2_32(ByteAlignment); + OS << '\n'; +} + +void MCAsmStreamer::EmitZerofill(const MCSection *Section, MCSymbol *Symbol, + unsigned Size, unsigned ByteAlignment) { + // Note: a .zerofill directive does not switch sections. + OS << ".zerofill "; + + // This is a mach-o specific directive. + const MCSectionMachO *MOSection = ((const MCSectionMachO*)Section); + OS << MOSection->getSegmentName() << "," << MOSection->getSectionName(); + + if (Symbol != NULL) { + OS << ','; + Symbol->print(OS, &MAI); + OS << ',' << Size; + if (ByteAlignment != 0) + OS << ',' << Log2_32(ByteAlignment); + } + OS << '\n'; +} + +void MCAsmStreamer::EmitBytes(StringRef Data) { + assert(CurSection && "Cannot emit contents before setting section!"); + for (unsigned i = 0, e = Data.size(); i != e; ++i) + OS << ".byte " << (unsigned) (unsigned char) Data[i] << '\n'; +} + +void MCAsmStreamer::EmitValue(const MCExpr *Value, unsigned Size) { + assert(CurSection && "Cannot emit contents before setting section!"); + // Need target hooks to know how to print this. + switch (Size) { + default: + llvm_unreachable("Invalid size for machine code value!"); + case 1: OS << ".byte"; break; + case 2: OS << ".short"; break; + case 4: OS << ".long"; break; + case 8: OS << ".quad"; break; + } + + OS << ' '; + truncateToSize(Value, Size)->print(OS, &MAI); + OS << '\n'; +} + +void MCAsmStreamer::EmitValueToAlignment(unsigned ByteAlignment, int64_t Value, + unsigned ValueSize, + unsigned MaxBytesToEmit) { + // Some assemblers don't support non-power of two alignments, so we always + // emit alignments as a power of two if possible. + if (isPowerOf2_32(ByteAlignment)) { + switch (ValueSize) { + default: llvm_unreachable("Invalid size for machine code value!"); + case 1: OS << MAI.getAlignDirective(); break; + // FIXME: use MAI for this! + case 2: OS << ".p2alignw "; break; + case 4: OS << ".p2alignl "; break; + case 8: llvm_unreachable("Unsupported alignment size!"); + } + + if (MAI.getAlignmentIsInBytes()) + OS << ByteAlignment; + else + OS << Log2_32(ByteAlignment); + + if (Value || MaxBytesToEmit) { + OS << ", 0x"; + OS.write_hex(truncateToSize(Value, ValueSize)); + + if (MaxBytesToEmit) + OS << ", " << MaxBytesToEmit; + } + OS << '\n'; + return; + } + + // Non-power of two alignment. This is not widely supported by assemblers. + // FIXME: Parameterize this based on MAI. + switch (ValueSize) { + default: llvm_unreachable("Invalid size for machine code value!"); + case 1: OS << ".balign"; break; + case 2: OS << ".balignw"; break; + case 4: OS << ".balignl"; break; + case 8: llvm_unreachable("Unsupported alignment size!"); + } + + OS << ' ' << ByteAlignment; + OS << ", " << truncateToSize(Value, ValueSize); + if (MaxBytesToEmit) + OS << ", " << MaxBytesToEmit; + OS << '\n'; +} + +void MCAsmStreamer::EmitValueToOffset(const MCExpr *Offset, + unsigned char Value) { + // FIXME: Verify that Offset is associated with the current section. + OS << ".org "; + Offset->print(OS, &MAI); + OS << ", " << (unsigned) Value << '\n'; +} + +void MCAsmStreamer::EmitInstruction(const MCInst &Inst) { + assert(CurSection && "Cannot emit contents before setting section!"); + + // If we have an AsmPrinter, use that to print. + if (InstPrinter) { + InstPrinter->printInst(&Inst); + OS << '\n'; + + // Show the encoding if we have a code emitter. + if (Emitter) { + SmallString<256> Code; + raw_svector_ostream VecOS(Code); + Emitter->EncodeInstruction(Inst, VecOS); + VecOS.flush(); + + OS.indent(20); + OS << " # encoding: ["; + for (unsigned i = 0, e = Code.size(); i != e; ++i) { + if (i) + OS << ','; + OS << format("%#04x", uint8_t(Code[i])); + } + OS << "]\n"; + } + + return; + } + + // Otherwise fall back to a structural printing for now. Eventually we should + // always have access to the target specific printer. + Inst.print(OS, &MAI); + OS << '\n'; +} + +void MCAsmStreamer::Finish() { + OS.flush(); +} + +MCStreamer *llvm::createAsmStreamer(MCContext &Context, raw_ostream &OS, + const MCAsmInfo &MAI, MCInstPrinter *IP, + MCCodeEmitter *CE) { + return new MCAsmStreamer(Context, OS, MAI, IP, CE); +} diff --git a/libclamav/c++/llvm/lib/MC/MCAssembler.cpp b/libclamav/c++/llvm/lib/MC/MCAssembler.cpp new file mode 100644 index 000000000..1f5b6f140 --- /dev/null +++ b/libclamav/c++/llvm/lib/MC/MCAssembler.cpp @@ -0,0 +1,1210 @@ +//===- lib/MC/MCAssembler.cpp - Assembler Backend Implementation ----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "assembler" +#include "llvm/MC/MCAssembler.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCSectionMachO.h" +#include "llvm/MC/MCSymbol.h" +#include "llvm/MC/MCValue.h" +#include "llvm/Target/TargetMachOWriterInfo.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/Twine.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +#include +using namespace llvm; + +class MachObjectWriter; + +STATISTIC(EmittedFragments, "Number of emitted assembler fragments"); + +// FIXME FIXME FIXME: There are number of places in this file where we convert +// what is a 64-bit assembler value used for computation into a value in the +// object file, which may truncate it. We should detect that truncation where +// invalid and report errors back. + +static void WriteFileData(raw_ostream &OS, const MCSectionData &SD, + MachObjectWriter &MOW); + +/// isVirtualSection - Check if this is a section which does not actually exist +/// in the object file. +static bool isVirtualSection(const MCSection &Section) { + // FIXME: Lame. + const MCSectionMachO &SMO = static_cast(Section); + unsigned Type = SMO.getTypeAndAttributes() & MCSectionMachO::SECTION_TYPE; + return (Type == MCSectionMachO::S_ZEROFILL); +} + +class MachObjectWriter { + // See . + enum { + Header_Magic32 = 0xFEEDFACE, + Header_Magic64 = 0xFEEDFACF + }; + + static const unsigned Header32Size = 28; + static const unsigned Header64Size = 32; + static const unsigned SegmentLoadCommand32Size = 56; + static const unsigned Section32Size = 68; + static const unsigned SymtabLoadCommandSize = 24; + static const unsigned DysymtabLoadCommandSize = 80; + static const unsigned Nlist32Size = 12; + static const unsigned RelocationInfoSize = 8; + + enum HeaderFileType { + HFT_Object = 0x1 + }; + + enum HeaderFlags { + HF_SubsectionsViaSymbols = 0x2000 + }; + + enum LoadCommandType { + LCT_Segment = 0x1, + LCT_Symtab = 0x2, + LCT_Dysymtab = 0xb + }; + + // See . + enum SymbolTypeType { + STT_Undefined = 0x00, + STT_Absolute = 0x02, + STT_Section = 0x0e + }; + + enum SymbolTypeFlags { + // If any of these bits are set, then the entry is a stab entry number (see + // . Otherwise the other masks apply. + STF_StabsEntryMask = 0xe0, + + STF_TypeMask = 0x0e, + STF_External = 0x01, + STF_PrivateExtern = 0x10 + }; + + /// IndirectSymbolFlags - Flags for encoding special values in the indirect + /// symbol entry. + enum IndirectSymbolFlags { + ISF_Local = 0x80000000, + ISF_Absolute = 0x40000000 + }; + + /// RelocationFlags - Special flags for addresses. + enum RelocationFlags { + RF_Scattered = 0x80000000 + }; + + enum RelocationInfoType { + RIT_Vanilla = 0, + RIT_Pair = 1, + RIT_Difference = 2, + RIT_PreboundLazyPointer = 3, + RIT_LocalDifference = 4 + }; + + /// MachSymbolData - Helper struct for containing some precomputed information + /// on symbols. + struct MachSymbolData { + MCSymbolData *SymbolData; + uint64_t StringIndex; + uint8_t SectionIndex; + + // Support lexicographic sorting. + bool operator<(const MachSymbolData &RHS) const { + const std::string &Name = SymbolData->getSymbol().getName(); + return Name < RHS.SymbolData->getSymbol().getName(); + } + }; + + raw_ostream &OS; + bool IsLSB; + +public: + MachObjectWriter(raw_ostream &_OS, bool _IsLSB = true) + : OS(_OS), IsLSB(_IsLSB) { + } + + /// @name Helper Methods + /// @{ + + void Write8(uint8_t Value) { + OS << char(Value); + } + + void Write16(uint16_t Value) { + if (IsLSB) { + Write8(uint8_t(Value >> 0)); + Write8(uint8_t(Value >> 8)); + } else { + Write8(uint8_t(Value >> 8)); + Write8(uint8_t(Value >> 0)); + } + } + + void Write32(uint32_t Value) { + if (IsLSB) { + Write16(uint16_t(Value >> 0)); + Write16(uint16_t(Value >> 16)); + } else { + Write16(uint16_t(Value >> 16)); + Write16(uint16_t(Value >> 0)); + } + } + + void Write64(uint64_t Value) { + if (IsLSB) { + Write32(uint32_t(Value >> 0)); + Write32(uint32_t(Value >> 32)); + } else { + Write32(uint32_t(Value >> 32)); + Write32(uint32_t(Value >> 0)); + } + } + + void WriteZeros(unsigned N) { + const char Zeros[16] = { 0 }; + + for (unsigned i = 0, e = N / 16; i != e; ++i) + OS << StringRef(Zeros, 16); + + OS << StringRef(Zeros, N % 16); + } + + void WriteString(StringRef Str, unsigned ZeroFillSize = 0) { + OS << Str; + if (ZeroFillSize) + WriteZeros(ZeroFillSize - Str.size()); + } + + /// @} + + void WriteHeader32(unsigned NumLoadCommands, unsigned LoadCommandsSize, + bool SubsectionsViaSymbols) { + uint32_t Flags = 0; + + if (SubsectionsViaSymbols) + Flags |= HF_SubsectionsViaSymbols; + + // struct mach_header (28 bytes) + + uint64_t Start = OS.tell(); + (void) Start; + + Write32(Header_Magic32); + + // FIXME: Support cputype. + Write32(TargetMachOWriterInfo::HDR_CPU_TYPE_I386); + // FIXME: Support cpusubtype. + Write32(TargetMachOWriterInfo::HDR_CPU_SUBTYPE_I386_ALL); + Write32(HFT_Object); + Write32(NumLoadCommands); // Object files have a single load command, the + // segment. + Write32(LoadCommandsSize); + Write32(Flags); + + assert(OS.tell() - Start == Header32Size); + } + + /// WriteSegmentLoadCommand32 - Write a 32-bit segment load command. + /// + /// \arg NumSections - The number of sections in this segment. + /// \arg SectionDataSize - The total size of the sections. + void WriteSegmentLoadCommand32(unsigned NumSections, + uint64_t VMSize, + uint64_t SectionDataStartOffset, + uint64_t SectionDataSize) { + // struct segment_command (56 bytes) + + uint64_t Start = OS.tell(); + (void) Start; + + Write32(LCT_Segment); + Write32(SegmentLoadCommand32Size + NumSections * Section32Size); + + WriteString("", 16); + Write32(0); // vmaddr + Write32(VMSize); // vmsize + Write32(SectionDataStartOffset); // file offset + Write32(SectionDataSize); // file size + Write32(0x7); // maxprot + Write32(0x7); // initprot + Write32(NumSections); + Write32(0); // flags + + assert(OS.tell() - Start == SegmentLoadCommand32Size); + } + + void WriteSection32(const MCSectionData &SD, uint64_t FileOffset, + uint64_t RelocationsStart, unsigned NumRelocations) { + // The offset is unused for virtual sections. + if (isVirtualSection(SD.getSection())) { + assert(SD.getFileSize() == 0 && "Invalid file size!"); + FileOffset = 0; + } + + // struct section (68 bytes) + + uint64_t Start = OS.tell(); + (void) Start; + + // FIXME: cast<> support! + const MCSectionMachO &Section = + static_cast(SD.getSection()); + WriteString(Section.getSectionName(), 16); + WriteString(Section.getSegmentName(), 16); + Write32(SD.getAddress()); // address + Write32(SD.getSize()); // size + Write32(FileOffset); + + assert(isPowerOf2_32(SD.getAlignment()) && "Invalid alignment!"); + Write32(Log2_32(SD.getAlignment())); + Write32(NumRelocations ? RelocationsStart : 0); + Write32(NumRelocations); + Write32(Section.getTypeAndAttributes()); + Write32(0); // reserved1 + Write32(Section.getStubSize()); // reserved2 + + assert(OS.tell() - Start == Section32Size); + } + + void WriteSymtabLoadCommand(uint32_t SymbolOffset, uint32_t NumSymbols, + uint32_t StringTableOffset, + uint32_t StringTableSize) { + // struct symtab_command (24 bytes) + + uint64_t Start = OS.tell(); + (void) Start; + + Write32(LCT_Symtab); + Write32(SymtabLoadCommandSize); + Write32(SymbolOffset); + Write32(NumSymbols); + Write32(StringTableOffset); + Write32(StringTableSize); + + assert(OS.tell() - Start == SymtabLoadCommandSize); + } + + void WriteDysymtabLoadCommand(uint32_t FirstLocalSymbol, + uint32_t NumLocalSymbols, + uint32_t FirstExternalSymbol, + uint32_t NumExternalSymbols, + uint32_t FirstUndefinedSymbol, + uint32_t NumUndefinedSymbols, + uint32_t IndirectSymbolOffset, + uint32_t NumIndirectSymbols) { + // struct dysymtab_command (80 bytes) + + uint64_t Start = OS.tell(); + (void) Start; + + Write32(LCT_Dysymtab); + Write32(DysymtabLoadCommandSize); + Write32(FirstLocalSymbol); + Write32(NumLocalSymbols); + Write32(FirstExternalSymbol); + Write32(NumExternalSymbols); + Write32(FirstUndefinedSymbol); + Write32(NumUndefinedSymbols); + Write32(0); // tocoff + Write32(0); // ntoc + Write32(0); // modtaboff + Write32(0); // nmodtab + Write32(0); // extrefsymoff + Write32(0); // nextrefsyms + Write32(IndirectSymbolOffset); + Write32(NumIndirectSymbols); + Write32(0); // extreloff + Write32(0); // nextrel + Write32(0); // locreloff + Write32(0); // nlocrel + + assert(OS.tell() - Start == DysymtabLoadCommandSize); + } + + void WriteNlist32(MachSymbolData &MSD) { + MCSymbolData &Data = *MSD.SymbolData; + const MCSymbol &Symbol = Data.getSymbol(); + uint8_t Type = 0; + uint16_t Flags = Data.getFlags(); + uint32_t Address = 0; + + // Set the N_TYPE bits. See . + // + // FIXME: Are the prebound or indirect fields possible here? + if (Symbol.isUndefined()) + Type = STT_Undefined; + else if (Symbol.isAbsolute()) + Type = STT_Absolute; + else + Type = STT_Section; + + // FIXME: Set STAB bits. + + if (Data.isPrivateExtern()) + Type |= STF_PrivateExtern; + + // Set external bit. + if (Data.isExternal() || Symbol.isUndefined()) + Type |= STF_External; + + // Compute the symbol address. + if (Symbol.isDefined()) { + if (Symbol.isAbsolute()) { + llvm_unreachable("FIXME: Not yet implemented!"); + } else { + Address = Data.getFragment()->getAddress() + Data.getOffset(); + } + } else if (Data.isCommon()) { + // Common symbols are encoded with the size in the address + // field, and their alignment in the flags. + Address = Data.getCommonSize(); + + // Common alignment is packed into the 'desc' bits. + if (unsigned Align = Data.getCommonAlignment()) { + unsigned Log2Size = Log2_32(Align); + assert((1U << Log2Size) == Align && "Invalid 'common' alignment!"); + if (Log2Size > 15) + llvm_report_error("invalid 'common' alignment '" + + Twine(Align) + "'"); + // FIXME: Keep this mask with the SymbolFlags enumeration. + Flags = (Flags & 0xF0FF) | (Log2Size << 8); + } + } + + // struct nlist (12 bytes) + + Write32(MSD.StringIndex); + Write8(Type); + Write8(MSD.SectionIndex); + + // The Mach-O streamer uses the lowest 16-bits of the flags for the 'desc' + // value. + Write16(Flags); + Write32(Address); + } + + struct MachRelocationEntry { + uint32_t Word0; + uint32_t Word1; + }; + void ComputeScatteredRelocationInfo(MCAssembler &Asm, + MCSectionData::Fixup &Fixup, + const MCValue &Target, + DenseMap &SymbolMap, + std::vector &Relocs) { + uint32_t Address = Fixup.Fragment->getOffset() + Fixup.Offset; + unsigned IsPCRel = 0; + unsigned Type = RIT_Vanilla; + + // See . + const MCSymbol *A = Target.getSymA(); + MCSymbolData *SD = SymbolMap.lookup(A); + uint32_t Value = SD->getFragment()->getAddress() + SD->getOffset(); + uint32_t Value2 = 0; + + if (const MCSymbol *B = Target.getSymB()) { + Type = RIT_LocalDifference; + + MCSymbolData *SD = SymbolMap.lookup(B); + Value2 = SD->getFragment()->getAddress() + SD->getOffset(); + } + + unsigned Log2Size = Log2_32(Fixup.Size); + assert((1U << Log2Size) == Fixup.Size && "Invalid fixup size!"); + + // The value which goes in the fixup is current value of the expression. + Fixup.FixedValue = Value - Value2 + Target.getConstant(); + + MachRelocationEntry MRE; + MRE.Word0 = ((Address << 0) | + (Type << 24) | + (Log2Size << 28) | + (IsPCRel << 30) | + RF_Scattered); + MRE.Word1 = Value; + Relocs.push_back(MRE); + + if (Type == RIT_LocalDifference) { + Type = RIT_Pair; + + MachRelocationEntry MRE; + MRE.Word0 = ((0 << 0) | + (Type << 24) | + (Log2Size << 28) | + (0 << 30) | + RF_Scattered); + MRE.Word1 = Value2; + Relocs.push_back(MRE); + } + } + + void ComputeRelocationInfo(MCAssembler &Asm, + MCSectionData::Fixup &Fixup, + DenseMap &SymbolMap, + std::vector &Relocs) { + MCValue Target; + if (!Fixup.Value->EvaluateAsRelocatable(Target)) + llvm_report_error("expected relocatable expression"); + + // If this is a difference or a local symbol plus an offset, then we need a + // scattered relocation entry. + if (Target.getSymB() || + (Target.getSymA() && !Target.getSymA()->isUndefined() && + Target.getConstant())) + return ComputeScatteredRelocationInfo(Asm, Fixup, Target, + SymbolMap, Relocs); + + // See . + uint32_t Address = Fixup.Fragment->getOffset() + Fixup.Offset; + uint32_t Value = 0; + unsigned Index = 0; + unsigned IsPCRel = 0; + unsigned IsExtern = 0; + unsigned Type = 0; + + if (Target.isAbsolute()) { // constant + // SymbolNum of 0 indicates the absolute section. + Type = RIT_Vanilla; + Value = 0; + llvm_unreachable("FIXME: Not yet implemented!"); + } else { + const MCSymbol *Symbol = Target.getSymA(); + MCSymbolData *SD = SymbolMap.lookup(Symbol); + + if (Symbol->isUndefined()) { + IsExtern = 1; + Index = SD->getIndex(); + Value = 0; + } else { + // The index is the section ordinal. + // + // FIXME: O(N) + Index = 1; + for (MCAssembler::iterator it = Asm.begin(), + ie = Asm.end(); it != ie; ++it, ++Index) + if (&*it == SD->getFragment()->getParent()) + break; + Value = SD->getFragment()->getAddress() + SD->getOffset(); + } + + Type = RIT_Vanilla; + } + + // The value which goes in the fixup is current value of the expression. + Fixup.FixedValue = Value + Target.getConstant(); + + unsigned Log2Size = Log2_32(Fixup.Size); + assert((1U << Log2Size) == Fixup.Size && "Invalid fixup size!"); + + // struct relocation_info (8 bytes) + MachRelocationEntry MRE; + MRE.Word0 = Address; + MRE.Word1 = ((Index << 0) | + (IsPCRel << 24) | + (Log2Size << 25) | + (IsExtern << 27) | + (Type << 28)); + Relocs.push_back(MRE); + } + + void BindIndirectSymbols(MCAssembler &Asm, + DenseMap &SymbolMap) { + // This is the point where 'as' creates actual symbols for indirect symbols + // (in the following two passes). It would be easier for us to do this + // sooner when we see the attribute, but that makes getting the order in the + // symbol table much more complicated than it is worth. + // + // FIXME: Revisit this when the dust settles. + + // Bind non lazy symbol pointers first. + for (MCAssembler::indirect_symbol_iterator it = Asm.indirect_symbol_begin(), + ie = Asm.indirect_symbol_end(); it != ie; ++it) { + // FIXME: cast<> support! + const MCSectionMachO &Section = + static_cast(it->SectionData->getSection()); + + unsigned Type = + Section.getTypeAndAttributes() & MCSectionMachO::SECTION_TYPE; + if (Type != MCSectionMachO::S_NON_LAZY_SYMBOL_POINTERS) + continue; + + MCSymbolData *&Entry = SymbolMap[it->Symbol]; + if (!Entry) + Entry = new MCSymbolData(*it->Symbol, 0, 0, &Asm); + } + + // Then lazy symbol pointers and symbol stubs. + for (MCAssembler::indirect_symbol_iterator it = Asm.indirect_symbol_begin(), + ie = Asm.indirect_symbol_end(); it != ie; ++it) { + // FIXME: cast<> support! + const MCSectionMachO &Section = + static_cast(it->SectionData->getSection()); + + unsigned Type = + Section.getTypeAndAttributes() & MCSectionMachO::SECTION_TYPE; + if (Type != MCSectionMachO::S_LAZY_SYMBOL_POINTERS && + Type != MCSectionMachO::S_SYMBOL_STUBS) + continue; + + MCSymbolData *&Entry = SymbolMap[it->Symbol]; + if (!Entry) { + Entry = new MCSymbolData(*it->Symbol, 0, 0, &Asm); + + // Set the symbol type to undefined lazy, but only on construction. + // + // FIXME: Do not hardcode. + Entry->setFlags(Entry->getFlags() | 0x0001); + } + } + } + + /// ComputeSymbolTable - Compute the symbol table data + /// + /// \param StringTable [out] - The string table data. + /// \param StringIndexMap [out] - Map from symbol names to offsets in the + /// string table. + void ComputeSymbolTable(MCAssembler &Asm, SmallString<256> &StringTable, + std::vector &LocalSymbolData, + std::vector &ExternalSymbolData, + std::vector &UndefinedSymbolData) { + // Build section lookup table. + DenseMap SectionIndexMap; + unsigned Index = 1; + for (MCAssembler::iterator it = Asm.begin(), + ie = Asm.end(); it != ie; ++it, ++Index) + SectionIndexMap[&it->getSection()] = Index; + assert(Index <= 256 && "Too many sections!"); + + // Index 0 is always the empty string. + StringMap StringIndexMap; + StringTable += '\x00'; + + // Build the symbol arrays and the string table, but only for non-local + // symbols. + // + // The particular order that we collect the symbols and create the string + // table, then sort the symbols is chosen to match 'as'. Even though it + // doesn't matter for correctness, this is important for letting us diff .o + // files. + for (MCAssembler::symbol_iterator it = Asm.symbol_begin(), + ie = Asm.symbol_end(); it != ie; ++it) { + const MCSymbol &Symbol = it->getSymbol(); + + // Ignore assembler temporaries. + if (it->getSymbol().isTemporary()) + continue; + + if (!it->isExternal() && !Symbol.isUndefined()) + continue; + + uint64_t &Entry = StringIndexMap[Symbol.getName()]; + if (!Entry) { + Entry = StringTable.size(); + StringTable += Symbol.getName(); + StringTable += '\x00'; + } + + MachSymbolData MSD; + MSD.SymbolData = it; + MSD.StringIndex = Entry; + + if (Symbol.isUndefined()) { + MSD.SectionIndex = 0; + UndefinedSymbolData.push_back(MSD); + } else if (Symbol.isAbsolute()) { + MSD.SectionIndex = 0; + ExternalSymbolData.push_back(MSD); + } else { + MSD.SectionIndex = SectionIndexMap.lookup(&Symbol.getSection()); + assert(MSD.SectionIndex && "Invalid section index!"); + ExternalSymbolData.push_back(MSD); + } + } + + // Now add the data for local symbols. + for (MCAssembler::symbol_iterator it = Asm.symbol_begin(), + ie = Asm.symbol_end(); it != ie; ++it) { + const MCSymbol &Symbol = it->getSymbol(); + + // Ignore assembler temporaries. + if (it->getSymbol().isTemporary()) + continue; + + if (it->isExternal() || Symbol.isUndefined()) + continue; + + uint64_t &Entry = StringIndexMap[Symbol.getName()]; + if (!Entry) { + Entry = StringTable.size(); + StringTable += Symbol.getName(); + StringTable += '\x00'; + } + + MachSymbolData MSD; + MSD.SymbolData = it; + MSD.StringIndex = Entry; + + if (Symbol.isAbsolute()) { + MSD.SectionIndex = 0; + LocalSymbolData.push_back(MSD); + } else { + MSD.SectionIndex = SectionIndexMap.lookup(&Symbol.getSection()); + assert(MSD.SectionIndex && "Invalid section index!"); + LocalSymbolData.push_back(MSD); + } + } + + // External and undefined symbols are required to be in lexicographic order. + std::sort(ExternalSymbolData.begin(), ExternalSymbolData.end()); + std::sort(UndefinedSymbolData.begin(), UndefinedSymbolData.end()); + + // Set the symbol indices. + Index = 0; + for (unsigned i = 0, e = LocalSymbolData.size(); i != e; ++i) + LocalSymbolData[i].SymbolData->setIndex(Index++); + for (unsigned i = 0, e = ExternalSymbolData.size(); i != e; ++i) + ExternalSymbolData[i].SymbolData->setIndex(Index++); + for (unsigned i = 0, e = UndefinedSymbolData.size(); i != e; ++i) + UndefinedSymbolData[i].SymbolData->setIndex(Index++); + + // The string table is padded to a multiple of 4. + // + // FIXME: Check to see if this varies per arch. + while (StringTable.size() % 4) + StringTable += '\x00'; + } + + void WriteObject(MCAssembler &Asm) { + unsigned NumSections = Asm.size(); + + // Compute the symbol -> symbol data map. + // + // FIXME: This should not be here. + DenseMap SymbolMap; + for (MCAssembler::symbol_iterator it = Asm.symbol_begin(), + ie = Asm.symbol_end(); it != ie; ++it) + SymbolMap[&it->getSymbol()] = it; + + // Create symbol data for any indirect symbols. + BindIndirectSymbols(Asm, SymbolMap); + + // Compute symbol table information. + SmallString<256> StringTable; + std::vector LocalSymbolData; + std::vector ExternalSymbolData; + std::vector UndefinedSymbolData; + unsigned NumSymbols = Asm.symbol_size(); + + // No symbol table command is written if there are no symbols. + if (NumSymbols) + ComputeSymbolTable(Asm, StringTable, LocalSymbolData, ExternalSymbolData, + UndefinedSymbolData); + + // The section data starts after the header, the segment load command (and + // section headers) and the symbol table. + unsigned NumLoadCommands = 1; + uint64_t LoadCommandsSize = + SegmentLoadCommand32Size + NumSections * Section32Size; + + // Add the symbol table load command sizes, if used. + if (NumSymbols) { + NumLoadCommands += 2; + LoadCommandsSize += SymtabLoadCommandSize + DysymtabLoadCommandSize; + } + + // Compute the total size of the section data, as well as its file size and + // vm size. + uint64_t SectionDataStart = Header32Size + LoadCommandsSize; + uint64_t SectionDataSize = 0; + uint64_t SectionDataFileSize = 0; + uint64_t VMSize = 0; + for (MCAssembler::iterator it = Asm.begin(), + ie = Asm.end(); it != ie; ++it) { + MCSectionData &SD = *it; + + VMSize = std::max(VMSize, SD.getAddress() + SD.getSize()); + + if (isVirtualSection(SD.getSection())) + continue; + + SectionDataSize = std::max(SectionDataSize, + SD.getAddress() + SD.getSize()); + SectionDataFileSize = std::max(SectionDataFileSize, + SD.getAddress() + SD.getFileSize()); + } + + // The section data is passed to 4 bytes. + // + // FIXME: Is this machine dependent? + unsigned SectionDataPadding = OffsetToAlignment(SectionDataFileSize, 4); + SectionDataFileSize += SectionDataPadding; + + // Write the prolog, starting with the header and load command... + WriteHeader32(NumLoadCommands, LoadCommandsSize, + Asm.getSubsectionsViaSymbols()); + WriteSegmentLoadCommand32(NumSections, VMSize, + SectionDataStart, SectionDataSize); + + // ... and then the section headers. + // + // We also compute the section relocations while we do this. Note that + // compute relocation info will also update the fixup to have the correct + // value; this will be overwrite the appropriate data in the fragment when + // it is written. + std::vector RelocInfos; + uint64_t RelocTableEnd = SectionDataStart + SectionDataFileSize; + for (MCAssembler::iterator it = Asm.begin(), ie = Asm.end(); it != ie; + ++it) { + MCSectionData &SD = *it; + + // The assembler writes relocations in the reverse order they were seen. + // + // FIXME: It is probably more complicated than this. + unsigned NumRelocsStart = RelocInfos.size(); + for (unsigned i = 0, e = SD.fixup_size(); i != e; ++i) + ComputeRelocationInfo(Asm, SD.getFixups()[e - i - 1], SymbolMap, + RelocInfos); + + unsigned NumRelocs = RelocInfos.size() - NumRelocsStart; + uint64_t SectionStart = SectionDataStart + SD.getAddress(); + WriteSection32(SD, SectionStart, RelocTableEnd, NumRelocs); + RelocTableEnd += NumRelocs * RelocationInfoSize; + } + + // Write the symbol table load command, if used. + if (NumSymbols) { + unsigned FirstLocalSymbol = 0; + unsigned NumLocalSymbols = LocalSymbolData.size(); + unsigned FirstExternalSymbol = FirstLocalSymbol + NumLocalSymbols; + unsigned NumExternalSymbols = ExternalSymbolData.size(); + unsigned FirstUndefinedSymbol = FirstExternalSymbol + NumExternalSymbols; + unsigned NumUndefinedSymbols = UndefinedSymbolData.size(); + unsigned NumIndirectSymbols = Asm.indirect_symbol_size(); + unsigned NumSymTabSymbols = + NumLocalSymbols + NumExternalSymbols + NumUndefinedSymbols; + uint64_t IndirectSymbolSize = NumIndirectSymbols * 4; + uint64_t IndirectSymbolOffset = 0; + + // If used, the indirect symbols are written after the section data. + if (NumIndirectSymbols) + IndirectSymbolOffset = RelocTableEnd; + + // The symbol table is written after the indirect symbol data. + uint64_t SymbolTableOffset = RelocTableEnd + IndirectSymbolSize; + + // The string table is written after symbol table. + uint64_t StringTableOffset = + SymbolTableOffset + NumSymTabSymbols * Nlist32Size; + WriteSymtabLoadCommand(SymbolTableOffset, NumSymTabSymbols, + StringTableOffset, StringTable.size()); + + WriteDysymtabLoadCommand(FirstLocalSymbol, NumLocalSymbols, + FirstExternalSymbol, NumExternalSymbols, + FirstUndefinedSymbol, NumUndefinedSymbols, + IndirectSymbolOffset, NumIndirectSymbols); + } + + // Write the actual section data. + for (MCAssembler::iterator it = Asm.begin(), ie = Asm.end(); it != ie; ++it) + WriteFileData(OS, *it, *this); + + // Write the extra padding. + WriteZeros(SectionDataPadding); + + // Write the relocation entries. + for (unsigned i = 0, e = RelocInfos.size(); i != e; ++i) { + Write32(RelocInfos[i].Word0); + Write32(RelocInfos[i].Word1); + } + + // Write the symbol table data, if used. + if (NumSymbols) { + // Write the indirect symbol entries. + for (MCAssembler::indirect_symbol_iterator + it = Asm.indirect_symbol_begin(), + ie = Asm.indirect_symbol_end(); it != ie; ++it) { + // Indirect symbols in the non lazy symbol pointer section have some + // special handling. + const MCSectionMachO &Section = + static_cast(it->SectionData->getSection()); + unsigned Type = + Section.getTypeAndAttributes() & MCSectionMachO::SECTION_TYPE; + if (Type == MCSectionMachO::S_NON_LAZY_SYMBOL_POINTERS) { + // If this symbol is defined and internal, mark it as such. + if (it->Symbol->isDefined() && + !SymbolMap.lookup(it->Symbol)->isExternal()) { + uint32_t Flags = ISF_Local; + if (it->Symbol->isAbsolute()) + Flags |= ISF_Absolute; + Write32(Flags); + continue; + } + } + + Write32(SymbolMap[it->Symbol]->getIndex()); + } + + // FIXME: Check that offsets match computed ones. + + // Write the symbol table entries. + for (unsigned i = 0, e = LocalSymbolData.size(); i != e; ++i) + WriteNlist32(LocalSymbolData[i]); + for (unsigned i = 0, e = ExternalSymbolData.size(); i != e; ++i) + WriteNlist32(ExternalSymbolData[i]); + for (unsigned i = 0, e = UndefinedSymbolData.size(); i != e; ++i) + WriteNlist32(UndefinedSymbolData[i]); + + // Write the string table. + OS << StringTable.str(); + } + } +}; + +/* *** */ + +MCFragment::MCFragment() : Kind(FragmentType(~0)) { +} + +MCFragment::MCFragment(FragmentType _Kind, MCSectionData *_Parent) + : Kind(_Kind), + Parent(_Parent), + FileSize(~UINT64_C(0)) +{ + if (Parent) + Parent->getFragmentList().push_back(this); +} + +MCFragment::~MCFragment() { +} + +uint64_t MCFragment::getAddress() const { + assert(getParent() && "Missing Section!"); + return getParent()->getAddress() + Offset; +} + +/* *** */ + +MCSectionData::MCSectionData() : Section(0) {} + +MCSectionData::MCSectionData(const MCSection &_Section, MCAssembler *A) + : Section(&_Section), + Alignment(1), + Address(~UINT64_C(0)), + Size(~UINT64_C(0)), + FileSize(~UINT64_C(0)), + LastFixupLookup(~0) +{ + if (A) + A->getSectionList().push_back(this); +} + +const MCSectionData::Fixup * +MCSectionData::LookupFixup(const MCFragment *Fragment, uint64_t Offset) const { + // Use a one level cache to turn the common case of accessing the fixups in + // order into O(1) instead of O(N). + unsigned i = LastFixupLookup, Count = Fixups.size(), End = Fixups.size(); + if (i >= End) + i = 0; + while (Count--) { + const Fixup &F = Fixups[i]; + if (F.Fragment == Fragment && F.Offset == Offset) { + LastFixupLookup = i; + return &F; + } + + ++i; + if (i == End) + i = 0; + } + + return 0; +} + +/* *** */ + +MCSymbolData::MCSymbolData() : Symbol(0) {} + +MCSymbolData::MCSymbolData(const MCSymbol &_Symbol, MCFragment *_Fragment, + uint64_t _Offset, MCAssembler *A) + : Symbol(&_Symbol), Fragment(_Fragment), Offset(_Offset), + IsExternal(false), IsPrivateExtern(false), + CommonSize(0), CommonAlign(0), Flags(0), Index(0) +{ + if (A) + A->getSymbolList().push_back(this); +} + +/* *** */ + +MCAssembler::MCAssembler(MCContext &_Context, raw_ostream &_OS) + : Context(_Context), OS(_OS), SubsectionsViaSymbols(false) +{ +} + +MCAssembler::~MCAssembler() { +} + +void MCAssembler::LayoutSection(MCSectionData &SD) { + uint64_t Address = SD.getAddress(); + + for (MCSectionData::iterator it = SD.begin(), ie = SD.end(); it != ie; ++it) { + MCFragment &F = *it; + + F.setOffset(Address - SD.getAddress()); + + // Evaluate fragment size. + switch (F.getKind()) { + case MCFragment::FT_Align: { + MCAlignFragment &AF = cast(F); + + uint64_t Size = OffsetToAlignment(Address, AF.getAlignment()); + if (Size > AF.getMaxBytesToEmit()) + AF.setFileSize(0); + else + AF.setFileSize(Size); + break; + } + + case MCFragment::FT_Data: + F.setFileSize(F.getMaxFileSize()); + break; + + case MCFragment::FT_Fill: { + MCFillFragment &FF = cast(F); + + F.setFileSize(F.getMaxFileSize()); + + MCValue Target; + if (!FF.getValue().EvaluateAsRelocatable(Target)) + llvm_report_error("expected relocatable expression"); + + // If the fill value is constant, thats it. + if (Target.isAbsolute()) + break; + + // Otherwise, add fixups for the values. + for (uint64_t i = 0, e = FF.getCount(); i != e; ++i) { + MCSectionData::Fixup Fix(F, i * FF.getValueSize(), + FF.getValue(),FF.getValueSize()); + SD.getFixups().push_back(Fix); + } + break; + } + + case MCFragment::FT_Org: { + MCOrgFragment &OF = cast(F); + + MCValue Target; + if (!OF.getOffset().EvaluateAsRelocatable(Target)) + llvm_report_error("expected relocatable expression"); + + if (!Target.isAbsolute()) + llvm_unreachable("FIXME: Not yet implemented!"); + uint64_t OrgOffset = Target.getConstant(); + uint64_t Offset = Address - SD.getAddress(); + + // FIXME: We need a way to communicate this error. + if (OrgOffset < Offset) + llvm_report_error("invalid .org offset '" + Twine(OrgOffset) + + "' (at offset '" + Twine(Offset) + "'"); + + F.setFileSize(OrgOffset - Offset); + break; + } + + case MCFragment::FT_ZeroFill: { + MCZeroFillFragment &ZFF = cast(F); + + // Align the fragment offset; it is safe to adjust the offset freely since + // this is only in virtual sections. + uint64_t Aligned = RoundUpToAlignment(Address, ZFF.getAlignment()); + F.setOffset(Aligned - SD.getAddress()); + + // FIXME: This is misnamed. + F.setFileSize(ZFF.getSize()); + break; + } + } + + Address += F.getFileSize(); + } + + // Set the section sizes. + SD.setSize(Address - SD.getAddress()); + if (isVirtualSection(SD.getSection())) + SD.setFileSize(0); + else + SD.setFileSize(Address - SD.getAddress()); +} + +/// WriteFileData - Write the \arg F data to the output file. +static void WriteFileData(raw_ostream &OS, const MCFragment &F, + MachObjectWriter &MOW) { + uint64_t Start = OS.tell(); + (void) Start; + + ++EmittedFragments; + + // FIXME: Embed in fragments instead? + switch (F.getKind()) { + case MCFragment::FT_Align: { + MCAlignFragment &AF = cast(F); + uint64_t Count = AF.getFileSize() / AF.getValueSize(); + + // FIXME: This error shouldn't actually occur (the front end should emit + // multiple .align directives to enforce the semantics it wants), but is + // severe enough that we want to report it. How to handle this? + if (Count * AF.getValueSize() != AF.getFileSize()) + llvm_report_error("undefined .align directive, value size '" + + Twine(AF.getValueSize()) + + "' is not a divisor of padding size '" + + Twine(AF.getFileSize()) + "'"); + + for (uint64_t i = 0; i != Count; ++i) { + switch (AF.getValueSize()) { + default: + assert(0 && "Invalid size!"); + case 1: MOW.Write8 (uint8_t (AF.getValue())); break; + case 2: MOW.Write16(uint16_t(AF.getValue())); break; + case 4: MOW.Write32(uint32_t(AF.getValue())); break; + case 8: MOW.Write64(uint64_t(AF.getValue())); break; + } + } + break; + } + + case MCFragment::FT_Data: + OS << cast(F).getContents().str(); + break; + + case MCFragment::FT_Fill: { + MCFillFragment &FF = cast(F); + + int64_t Value = 0; + + MCValue Target; + if (!FF.getValue().EvaluateAsRelocatable(Target)) + llvm_report_error("expected relocatable expression"); + + if (Target.isAbsolute()) + Value = Target.getConstant(); + for (uint64_t i = 0, e = FF.getCount(); i != e; ++i) { + if (!Target.isAbsolute()) { + // Find the fixup. + // + // FIXME: Find a better way to write in the fixes. + const MCSectionData::Fixup *Fixup = + F.getParent()->LookupFixup(&F, i * FF.getValueSize()); + assert(Fixup && "Missing fixup for fill value!"); + Value = Fixup->FixedValue; + } + + switch (FF.getValueSize()) { + default: + assert(0 && "Invalid size!"); + case 1: MOW.Write8 (uint8_t (Value)); break; + case 2: MOW.Write16(uint16_t(Value)); break; + case 4: MOW.Write32(uint32_t(Value)); break; + case 8: MOW.Write64(uint64_t(Value)); break; + } + } + break; + } + + case MCFragment::FT_Org: { + MCOrgFragment &OF = cast(F); + + for (uint64_t i = 0, e = OF.getFileSize(); i != e; ++i) + MOW.Write8(uint8_t(OF.getValue())); + + break; + } + + case MCFragment::FT_ZeroFill: { + assert(0 && "Invalid zero fill fragment in concrete section!"); + break; + } + } + + assert(OS.tell() - Start == F.getFileSize()); +} + +/// WriteFileData - Write the \arg SD data to the output file. +static void WriteFileData(raw_ostream &OS, const MCSectionData &SD, + MachObjectWriter &MOW) { + // Ignore virtual sections. + if (isVirtualSection(SD.getSection())) { + assert(SD.getFileSize() == 0); + return; + } + + uint64_t Start = OS.tell(); + (void) Start; + + for (MCSectionData::const_iterator it = SD.begin(), + ie = SD.end(); it != ie; ++it) + WriteFileData(OS, *it, MOW); + + // Add section padding. + assert(SD.getFileSize() >= SD.getSize() && "Invalid section sizes!"); + MOW.WriteZeros(SD.getFileSize() - SD.getSize()); + + assert(OS.tell() - Start == SD.getFileSize()); +} + +void MCAssembler::Finish() { + // Layout the concrete sections and fragments. + uint64_t Address = 0; + MCSectionData *Prev = 0; + for (iterator it = begin(), ie = end(); it != ie; ++it) { + MCSectionData &SD = *it; + + // Skip virtual sections. + if (isVirtualSection(SD.getSection())) + continue; + + // Align this section if necessary by adding padding bytes to the previous + // section. + if (uint64_t Pad = OffsetToAlignment(Address, it->getAlignment())) { + assert(Prev && "Missing prev section!"); + Prev->setFileSize(Prev->getFileSize() + Pad); + Address += Pad; + } + + // Layout the section fragments and its size. + SD.setAddress(Address); + LayoutSection(SD); + Address += SD.getFileSize(); + + Prev = &SD; + } + + // Layout the virtual sections. + for (iterator it = begin(), ie = end(); it != ie; ++it) { + MCSectionData &SD = *it; + + if (!isVirtualSection(SD.getSection())) + continue; + + SD.setAddress(Address); + LayoutSection(SD); + Address += SD.getSize(); + } + + // Write the object file. + MachObjectWriter MOW(OS); + MOW.WriteObject(*this); + + OS.flush(); +} diff --git a/libclamav/c++/llvm/lib/MC/MCCodeEmitter.cpp b/libclamav/c++/llvm/lib/MC/MCCodeEmitter.cpp new file mode 100644 index 000000000..c122763b2 --- /dev/null +++ b/libclamav/c++/llvm/lib/MC/MCCodeEmitter.cpp @@ -0,0 +1,18 @@ +//===-- MCCodeEmitter.cpp - Instruction Encoding --------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/MC/MCCodeEmitter.h" + +using namespace llvm; + +MCCodeEmitter::MCCodeEmitter() { +} + +MCCodeEmitter::~MCCodeEmitter() { +} diff --git a/libclamav/c++/llvm/lib/MC/MCContext.cpp b/libclamav/c++/llvm/lib/MC/MCContext.cpp new file mode 100644 index 000000000..45d2c0253 --- /dev/null +++ b/libclamav/c++/llvm/lib/MC/MCContext.cpp @@ -0,0 +1,62 @@ +//===- lib/MC/MCContext.cpp - Machine Code Context ------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCSection.h" +#include "llvm/MC/MCSymbol.h" +#include "llvm/MC/MCValue.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/Twine.h" +using namespace llvm; + +MCContext::MCContext() { +} + +MCContext::~MCContext() { + // NOTE: The sections are all allocated out of a bump pointer allocator, + // we don't need to free them here. +} + +MCSymbol *MCContext::CreateSymbol(StringRef Name) { + assert(Name[0] != '\0' && "Normal symbols cannot be unnamed!"); + + // Create and bind the symbol, and ensure that names are unique. + MCSymbol *&Entry = Symbols[Name]; + assert(!Entry && "Duplicate symbol definition!"); + return Entry = new (*this) MCSymbol(Name, false); +} + +MCSymbol *MCContext::GetOrCreateSymbol(StringRef Name) { + MCSymbol *&Entry = Symbols[Name]; + if (Entry) return Entry; + + return Entry = new (*this) MCSymbol(Name, false); +} + +MCSymbol *MCContext::GetOrCreateSymbol(const Twine &Name) { + SmallString<128> NameSV; + Name.toVector(NameSV); + return GetOrCreateSymbol(NameSV.str()); +} + + +MCSymbol *MCContext::CreateTemporarySymbol(StringRef Name) { + // If unnamed, just create a symbol. + if (Name.empty()) + new (*this) MCSymbol("", true); + + // Otherwise create as usual. + MCSymbol *&Entry = Symbols[Name]; + assert(!Entry && "Duplicate symbol definition!"); + return Entry = new (*this) MCSymbol(Name, true); +} + +MCSymbol *MCContext::LookupSymbol(StringRef Name) const { + return Symbols.lookup(Name); +} diff --git a/libclamav/c++/llvm/lib/MC/MCDisassembler.cpp b/libclamav/c++/llvm/lib/MC/MCDisassembler.cpp new file mode 100644 index 000000000..080969064 --- /dev/null +++ b/libclamav/c++/llvm/lib/MC/MCDisassembler.cpp @@ -0,0 +1,14 @@ +//===-- lib/MC/MCDisassembler.cpp - Disassembler interface ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/MC/MCDisassembler.h" +using namespace llvm; + +MCDisassembler::~MCDisassembler() { +} diff --git a/libclamav/c++/llvm/lib/MC/MCExpr.cpp b/libclamav/c++/llvm/lib/MC/MCExpr.cpp new file mode 100644 index 000000000..a5a2256f4 --- /dev/null +++ b/libclamav/c++/llvm/lib/MC/MCExpr.cpp @@ -0,0 +1,287 @@ +//===- MCExpr.cpp - Assembly Level Expression Implementation --------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCSymbol.h" +#include "llvm/MC/MCValue.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +void MCExpr::print(raw_ostream &OS, const MCAsmInfo *MAI) const { + switch (getKind()) { + case MCExpr::Constant: + OS << cast(*this).getValue(); + return; + + case MCExpr::SymbolRef: { + const MCSymbol &Sym = cast(*this).getSymbol(); + + // Parenthesize names that start with $ so that they don't look like + // absolute names. + if (Sym.getName()[0] == '$') { + OS << '('; + Sym.print(OS, MAI); + OS << ')'; + } else { + Sym.print(OS, MAI); + } + return; + } + + case MCExpr::Unary: { + const MCUnaryExpr &UE = cast(*this); + switch (UE.getOpcode()) { + default: assert(0 && "Invalid opcode!"); + case MCUnaryExpr::LNot: OS << '!'; break; + case MCUnaryExpr::Minus: OS << '-'; break; + case MCUnaryExpr::Not: OS << '~'; break; + case MCUnaryExpr::Plus: OS << '+'; break; + } + UE.getSubExpr()->print(OS, MAI); + return; + } + + case MCExpr::Binary: { + const MCBinaryExpr &BE = cast(*this); + + // Only print parens around the LHS if it is non-trivial. + if (isa(BE.getLHS()) || isa(BE.getLHS())) { + BE.getLHS()->print(OS, MAI); + } else { + OS << '('; + BE.getLHS()->print(OS, MAI); + OS << ')'; + } + + switch (BE.getOpcode()) { + default: assert(0 && "Invalid opcode!"); + case MCBinaryExpr::Add: + // Print "X-42" instead of "X+-42". + if (const MCConstantExpr *RHSC = dyn_cast(BE.getRHS())) { + if (RHSC->getValue() < 0) { + OS << RHSC->getValue(); + return; + } + } + + OS << '+'; + break; + case MCBinaryExpr::And: OS << '&'; break; + case MCBinaryExpr::Div: OS << '/'; break; + case MCBinaryExpr::EQ: OS << "=="; break; + case MCBinaryExpr::GT: OS << '>'; break; + case MCBinaryExpr::GTE: OS << ">="; break; + case MCBinaryExpr::LAnd: OS << "&&"; break; + case MCBinaryExpr::LOr: OS << "||"; break; + case MCBinaryExpr::LT: OS << '<'; break; + case MCBinaryExpr::LTE: OS << "<="; break; + case MCBinaryExpr::Mod: OS << '%'; break; + case MCBinaryExpr::Mul: OS << '*'; break; + case MCBinaryExpr::NE: OS << "!="; break; + case MCBinaryExpr::Or: OS << '|'; break; + case MCBinaryExpr::Shl: OS << "<<"; break; + case MCBinaryExpr::Shr: OS << ">>"; break; + case MCBinaryExpr::Sub: OS << '-'; break; + case MCBinaryExpr::Xor: OS << '^'; break; + } + + // Only print parens around the LHS if it is non-trivial. + if (isa(BE.getRHS()) || isa(BE.getRHS())) { + BE.getRHS()->print(OS, MAI); + } else { + OS << '('; + BE.getRHS()->print(OS, MAI); + OS << ')'; + } + return; + } + } + + assert(0 && "Invalid expression kind!"); +} + +void MCExpr::dump() const { + print(errs(), 0); + errs() << '\n'; +} + +/* *** */ + +const MCBinaryExpr *MCBinaryExpr::Create(Opcode Opc, const MCExpr *LHS, + const MCExpr *RHS, MCContext &Ctx) { + return new (Ctx) MCBinaryExpr(Opc, LHS, RHS); +} + +const MCUnaryExpr *MCUnaryExpr::Create(Opcode Opc, const MCExpr *Expr, + MCContext &Ctx) { + return new (Ctx) MCUnaryExpr(Opc, Expr); +} + +const MCConstantExpr *MCConstantExpr::Create(int64_t Value, MCContext &Ctx) { + return new (Ctx) MCConstantExpr(Value); +} + +const MCSymbolRefExpr *MCSymbolRefExpr::Create(const MCSymbol *Sym, + MCContext &Ctx) { + return new (Ctx) MCSymbolRefExpr(Sym); +} + +const MCSymbolRefExpr *MCSymbolRefExpr::Create(StringRef Name, MCContext &Ctx) { + return Create(Ctx.GetOrCreateSymbol(Name), Ctx); +} + + +/* *** */ + +bool MCExpr::EvaluateAsAbsolute(int64_t &Res) const { + MCValue Value; + + if (!EvaluateAsRelocatable(Value) || !Value.isAbsolute()) + return false; + + Res = Value.getConstant(); + return true; +} + +static bool EvaluateSymbolicAdd(const MCValue &LHS, const MCSymbol *RHS_A, + const MCSymbol *RHS_B, int64_t RHS_Cst, + MCValue &Res) { + // We can't add or subtract two symbols. + if ((LHS.getSymA() && RHS_A) || + (LHS.getSymB() && RHS_B)) + return false; + + const MCSymbol *A = LHS.getSymA() ? LHS.getSymA() : RHS_A; + const MCSymbol *B = LHS.getSymB() ? LHS.getSymB() : RHS_B; + if (B) { + // If we have a negated symbol, then we must have also have a non-negated + // symbol in order to encode the expression. We can do this check later to + // permit expressions which eventually fold to a representable form -- such + // as (a + (0 - b)) -- if necessary. + if (!A) + return false; + } + Res = MCValue::get(A, B, LHS.getConstant() + RHS_Cst); + return true; +} + +bool MCExpr::EvaluateAsRelocatable(MCValue &Res) const { + switch (getKind()) { + case Constant: + Res = MCValue::get(cast(this)->getValue()); + return true; + + case SymbolRef: { + const MCSymbol &Sym = cast(this)->getSymbol(); + + // Evaluate recursively if this is a variable. + if (Sym.isVariable()) + return Sym.getValue()->EvaluateAsRelocatable(Res); + + Res = MCValue::get(&Sym, 0, 0); + return true; + } + + case Unary: { + const MCUnaryExpr *AUE = cast(this); + MCValue Value; + + if (!AUE->getSubExpr()->EvaluateAsRelocatable(Value)) + return false; + + switch (AUE->getOpcode()) { + case MCUnaryExpr::LNot: + if (!Value.isAbsolute()) + return false; + Res = MCValue::get(!Value.getConstant()); + break; + case MCUnaryExpr::Minus: + /// -(a - b + const) ==> (b - a - const) + if (Value.getSymA() && !Value.getSymB()) + return false; + Res = MCValue::get(Value.getSymB(), Value.getSymA(), + -Value.getConstant()); + break; + case MCUnaryExpr::Not: + if (!Value.isAbsolute()) + return false; + Res = MCValue::get(~Value.getConstant()); + break; + case MCUnaryExpr::Plus: + Res = Value; + break; + } + + return true; + } + + case Binary: { + const MCBinaryExpr *ABE = cast(this); + MCValue LHSValue, RHSValue; + + if (!ABE->getLHS()->EvaluateAsRelocatable(LHSValue) || + !ABE->getRHS()->EvaluateAsRelocatable(RHSValue)) + return false; + + // We only support a few operations on non-constant expressions, handle + // those first. + if (!LHSValue.isAbsolute() || !RHSValue.isAbsolute()) { + switch (ABE->getOpcode()) { + default: + return false; + case MCBinaryExpr::Sub: + // Negate RHS and add. + return EvaluateSymbolicAdd(LHSValue, + RHSValue.getSymB(), RHSValue.getSymA(), + -RHSValue.getConstant(), + Res); + + case MCBinaryExpr::Add: + return EvaluateSymbolicAdd(LHSValue, + RHSValue.getSymA(), RHSValue.getSymB(), + RHSValue.getConstant(), + Res); + } + } + + // FIXME: We need target hooks for the evaluation. It may be limited in + // width, and gas defines the result of comparisons differently from Apple + // as (the result is sign extended). + int64_t LHS = LHSValue.getConstant(), RHS = RHSValue.getConstant(); + int64_t Result = 0; + switch (ABE->getOpcode()) { + case MCBinaryExpr::Add: Result = LHS + RHS; break; + case MCBinaryExpr::And: Result = LHS & RHS; break; + case MCBinaryExpr::Div: Result = LHS / RHS; break; + case MCBinaryExpr::EQ: Result = LHS == RHS; break; + case MCBinaryExpr::GT: Result = LHS > RHS; break; + case MCBinaryExpr::GTE: Result = LHS >= RHS; break; + case MCBinaryExpr::LAnd: Result = LHS && RHS; break; + case MCBinaryExpr::LOr: Result = LHS || RHS; break; + case MCBinaryExpr::LT: Result = LHS < RHS; break; + case MCBinaryExpr::LTE: Result = LHS <= RHS; break; + case MCBinaryExpr::Mod: Result = LHS % RHS; break; + case MCBinaryExpr::Mul: Result = LHS * RHS; break; + case MCBinaryExpr::NE: Result = LHS != RHS; break; + case MCBinaryExpr::Or: Result = LHS | RHS; break; + case MCBinaryExpr::Shl: Result = LHS << RHS; break; + case MCBinaryExpr::Shr: Result = LHS >> RHS; break; + case MCBinaryExpr::Sub: Result = LHS - RHS; break; + case MCBinaryExpr::Xor: Result = LHS ^ RHS; break; + } + + Res = MCValue::get(Result); + return true; + } + } + + assert(0 && "Invalid assembly expression kind!"); + return false; +} diff --git a/libclamav/c++/llvm/lib/MC/MCInst.cpp b/libclamav/c++/llvm/lib/MC/MCInst.cpp new file mode 100644 index 000000000..d05031870 --- /dev/null +++ b/libclamav/c++/llvm/lib/MC/MCInst.cpp @@ -0,0 +1,50 @@ +//===- lib/MC/MCInst.cpp - MCInst implementation --------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/MC/MCInst.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/Support/raw_ostream.h" + +using namespace llvm; + +void MCOperand::print(raw_ostream &OS, const MCAsmInfo *MAI) const { + OS << "print(OS, MAI); + OS << ")"; + } else + OS << "UNDEFINED"; + OS << ">"; +} + +void MCOperand::dump() const { + print(errs(), 0); + errs() << "\n"; +} + +void MCInst::print(raw_ostream &OS, const MCAsmInfo *MAI) const { + OS << ""; +} + +void MCInst::dump() const { + print(errs(), 0); + errs() << "\n"; +} diff --git a/libclamav/c++/llvm/lib/MC/MCInstPrinter.cpp b/libclamav/c++/llvm/lib/MC/MCInstPrinter.cpp new file mode 100644 index 000000000..e90c03c0c --- /dev/null +++ b/libclamav/c++/llvm/lib/MC/MCInstPrinter.cpp @@ -0,0 +1,14 @@ +//===-- MCInstPrinter.cpp - Convert an MCInst to target assembly syntax ---===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/MC/MCInstPrinter.h" +using namespace llvm; + +MCInstPrinter::~MCInstPrinter() { +} diff --git a/libclamav/c++/llvm/lib/MC/MCMachOStreamer.cpp b/libclamav/c++/llvm/lib/MC/MCMachOStreamer.cpp new file mode 100644 index 000000000..828b92a74 --- /dev/null +++ b/libclamav/c++/llvm/lib/MC/MCMachOStreamer.cpp @@ -0,0 +1,370 @@ +//===- lib/MC/MCMachOStreamer.cpp - Mach-O Object Output ------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/MC/MCStreamer.h" + +#include "llvm/MC/MCAssembler.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCCodeEmitter.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCInst.h" +#include "llvm/MC/MCSection.h" +#include "llvm/MC/MCSymbol.h" +#include "llvm/MC/MCValue.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +namespace { + +class MCMachOStreamer : public MCStreamer { + /// SymbolFlags - We store the value for the 'desc' symbol field in the lowest + /// 16 bits of the implementation defined flags. + enum SymbolFlags { // See . + SF_DescFlagsMask = 0xFFFF, + + // Reference type flags. + SF_ReferenceTypeMask = 0x0007, + SF_ReferenceTypeUndefinedNonLazy = 0x0000, + SF_ReferenceTypeUndefinedLazy = 0x0001, + SF_ReferenceTypeDefined = 0x0002, + SF_ReferenceTypePrivateDefined = 0x0003, + SF_ReferenceTypePrivateUndefinedNonLazy = 0x0004, + SF_ReferenceTypePrivateUndefinedLazy = 0x0005, + + // Other 'desc' flags. + SF_NoDeadStrip = 0x0020, + SF_WeakReference = 0x0040, + SF_WeakDefinition = 0x0080 + }; + +private: + MCAssembler Assembler; + + MCCodeEmitter *Emitter; + + MCSectionData *CurSectionData; + + DenseMap SectionMap; + + DenseMap SymbolMap; + +private: + MCFragment *getCurrentFragment() const { + assert(CurSectionData && "No current section!"); + + if (!CurSectionData->empty()) + return &CurSectionData->getFragmentList().back(); + + return 0; + } + + MCSectionData &getSectionData(const MCSection &Section) { + MCSectionData *&Entry = SectionMap[&Section]; + + if (!Entry) + Entry = new MCSectionData(Section, &Assembler); + + return *Entry; + } + + MCSymbolData &getSymbolData(const MCSymbol &Symbol) { + MCSymbolData *&Entry = SymbolMap[&Symbol]; + + if (!Entry) + Entry = new MCSymbolData(Symbol, 0, 0, &Assembler); + + return *Entry; + } + +public: + MCMachOStreamer(MCContext &Context, raw_ostream &_OS, MCCodeEmitter *_Emitter) + : MCStreamer(Context), Assembler(Context, _OS), Emitter(_Emitter), + CurSectionData(0) {} + ~MCMachOStreamer() {} + + const MCExpr *AddValueSymbols(const MCExpr *Value) { + switch (Value->getKind()) { + case MCExpr::Constant: + break; + + case MCExpr::Binary: { + const MCBinaryExpr *BE = cast(Value); + AddValueSymbols(BE->getLHS()); + AddValueSymbols(BE->getRHS()); + break; + } + + case MCExpr::SymbolRef: + getSymbolData(cast(Value)->getSymbol()); + break; + + case MCExpr::Unary: + AddValueSymbols(cast(Value)->getSubExpr()); + break; + } + + return Value; + } + + /// @name MCStreamer Interface + /// @{ + + virtual void SwitchSection(const MCSection *Section); + + virtual void EmitLabel(MCSymbol *Symbol); + + virtual void EmitAssemblerFlag(AssemblerFlag Flag); + + virtual void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value); + + virtual void EmitSymbolAttribute(MCSymbol *Symbol, SymbolAttr Attribute); + + virtual void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue); + + virtual void EmitCommonSymbol(MCSymbol *Symbol, unsigned Size, + unsigned ByteAlignment); + + virtual void EmitZerofill(const MCSection *Section, MCSymbol *Symbol = 0, + unsigned Size = 0, unsigned ByteAlignment = 0); + + virtual void EmitBytes(StringRef Data); + + virtual void EmitValue(const MCExpr *Value, unsigned Size); + + virtual void EmitValueToAlignment(unsigned ByteAlignment, int64_t Value = 0, + unsigned ValueSize = 1, + unsigned MaxBytesToEmit = 0); + + virtual void EmitValueToOffset(const MCExpr *Offset, + unsigned char Value = 0); + + virtual void EmitInstruction(const MCInst &Inst); + + virtual void Finish(); + + /// @} +}; + +} // end anonymous namespace. + +void MCMachOStreamer::SwitchSection(const MCSection *Section) { + assert(Section && "Cannot switch to a null section!"); + + // If already in this section, then this is a noop. + if (Section == CurSection) return; + + CurSection = Section; + CurSectionData = &getSectionData(*Section); +} + +void MCMachOStreamer::EmitLabel(MCSymbol *Symbol) { + assert(Symbol->isUndefined() && "Cannot define a symbol twice!"); + + // FIXME: We should also use offsets into Fill fragments. + MCDataFragment *F = dyn_cast_or_null(getCurrentFragment()); + if (!F) + F = new MCDataFragment(CurSectionData); + + MCSymbolData &SD = getSymbolData(*Symbol); + assert(!SD.getFragment() && "Unexpected fragment on symbol data!"); + SD.setFragment(F); + SD.setOffset(F->getContents().size()); + + // This causes the reference type and weak reference flags to be cleared. + SD.setFlags(SD.getFlags() & ~(SF_WeakReference | SF_ReferenceTypeMask)); + + Symbol->setSection(*CurSection); +} + +void MCMachOStreamer::EmitAssemblerFlag(AssemblerFlag Flag) { + switch (Flag) { + case SubsectionsViaSymbols: + Assembler.setSubsectionsViaSymbols(true); + return; + } + + assert(0 && "invalid assembler flag!"); +} + +void MCMachOStreamer::EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) { + // Only absolute symbols can be redefined. + assert((Symbol->isUndefined() || Symbol->isAbsolute()) && + "Cannot define a symbol twice!"); + + // FIXME: Lift context changes into super class. + // FIXME: Set associated section. + Symbol->setValue(Value); +} + +void MCMachOStreamer::EmitSymbolAttribute(MCSymbol *Symbol, + SymbolAttr Attribute) { + // Indirect symbols are handled differently, to match how 'as' handles + // them. This makes writing matching .o files easier. + if (Attribute == MCStreamer::IndirectSymbol) { + // Note that we intentionally cannot use the symbol data here; this is + // important for matching the string table that 'as' generates. + IndirectSymbolData ISD; + ISD.Symbol = Symbol; + ISD.SectionData = CurSectionData; + Assembler.getIndirectSymbols().push_back(ISD); + return; + } + + // Adding a symbol attribute always introduces the symbol, note that an + // important side effect of calling getSymbolData here is to register the + // symbol with the assembler. + MCSymbolData &SD = getSymbolData(*Symbol); + + // The implementation of symbol attributes is designed to match 'as', but it + // leaves much to desired. It doesn't really make sense to arbitrarily add and + // remove flags, but 'as' allows this (in particular, see .desc). + // + // In the future it might be worth trying to make these operations more well + // defined. + switch (Attribute) { + case MCStreamer::IndirectSymbol: + case MCStreamer::Hidden: + case MCStreamer::Internal: + case MCStreamer::Protected: + case MCStreamer::Weak: + assert(0 && "Invalid symbol attribute for Mach-O!"); + break; + + case MCStreamer::Global: + SD.setExternal(true); + break; + + case MCStreamer::LazyReference: + // FIXME: This requires -dynamic. + SD.setFlags(SD.getFlags() | SF_NoDeadStrip); + if (Symbol->isUndefined()) + SD.setFlags(SD.getFlags() | SF_ReferenceTypeUndefinedLazy); + break; + + // Since .reference sets the no dead strip bit, it is equivalent to + // .no_dead_strip in practice. + case MCStreamer::Reference: + case MCStreamer::NoDeadStrip: + SD.setFlags(SD.getFlags() | SF_NoDeadStrip); + break; + + case MCStreamer::PrivateExtern: + SD.setExternal(true); + SD.setPrivateExtern(true); + break; + + case MCStreamer::WeakReference: + // FIXME: This requires -dynamic. + if (Symbol->isUndefined()) + SD.setFlags(SD.getFlags() | SF_WeakReference); + break; + + case MCStreamer::WeakDefinition: + // FIXME: 'as' enforces that this is defined and global. The manual claims + // it has to be in a coalesced section, but this isn't enforced. + SD.setFlags(SD.getFlags() | SF_WeakDefinition); + break; + } +} + +void MCMachOStreamer::EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) { + // Encode the 'desc' value into the lowest implementation defined bits. + assert(DescValue == (DescValue & SF_DescFlagsMask) && + "Invalid .desc value!"); + getSymbolData(*Symbol).setFlags(DescValue & SF_DescFlagsMask); +} + +void MCMachOStreamer::EmitCommonSymbol(MCSymbol *Symbol, unsigned Size, + unsigned ByteAlignment) { + // FIXME: Darwin 'as' does appear to allow redef of a .comm by itself. + assert(Symbol->isUndefined() && "Cannot define a symbol twice!"); + + MCSymbolData &SD = getSymbolData(*Symbol); + SD.setExternal(true); + SD.setCommon(Size, ByteAlignment); +} + +void MCMachOStreamer::EmitZerofill(const MCSection *Section, MCSymbol *Symbol, + unsigned Size, unsigned ByteAlignment) { + MCSectionData &SectData = getSectionData(*Section); + + // The symbol may not be present, which only creates the section. + if (!Symbol) + return; + + // FIXME: Assert that this section has the zerofill type. + + assert(Symbol->isUndefined() && "Cannot define a symbol twice!"); + + MCSymbolData &SD = getSymbolData(*Symbol); + + MCFragment *F = new MCZeroFillFragment(Size, ByteAlignment, &SectData); + SD.setFragment(F); + + Symbol->setSection(*Section); + + // Update the maximum alignment on the zero fill section if necessary. + if (ByteAlignment > SectData.getAlignment()) + SectData.setAlignment(ByteAlignment); +} + +void MCMachOStreamer::EmitBytes(StringRef Data) { + MCDataFragment *DF = dyn_cast_or_null(getCurrentFragment()); + if (!DF) + DF = new MCDataFragment(CurSectionData); + DF->getContents().append(Data.begin(), Data.end()); +} + +void MCMachOStreamer::EmitValue(const MCExpr *Value, unsigned Size) { + new MCFillFragment(*AddValueSymbols(Value), Size, 1, CurSectionData); +} + +void MCMachOStreamer::EmitValueToAlignment(unsigned ByteAlignment, + int64_t Value, unsigned ValueSize, + unsigned MaxBytesToEmit) { + if (MaxBytesToEmit == 0) + MaxBytesToEmit = ByteAlignment; + new MCAlignFragment(ByteAlignment, Value, ValueSize, MaxBytesToEmit, + CurSectionData); + + // Update the maximum alignment on the current section if necessary. + if (ByteAlignment > CurSectionData->getAlignment()) + CurSectionData->setAlignment(ByteAlignment); +} + +void MCMachOStreamer::EmitValueToOffset(const MCExpr *Offset, + unsigned char Value) { + new MCOrgFragment(*Offset, Value, CurSectionData); +} + +void MCMachOStreamer::EmitInstruction(const MCInst &Inst) { + // Scan for values. + for (unsigned i = 0; i != Inst.getNumOperands(); ++i) + if (Inst.getOperand(i).isExpr()) + AddValueSymbols(Inst.getOperand(i).getExpr()); + + if (!Emitter) + llvm_unreachable("no code emitter available!"); + + // FIXME: Relocations! + SmallString<256> Code; + raw_svector_ostream VecOS(Code); + Emitter->EncodeInstruction(Inst, VecOS); + EmitBytes(VecOS.str()); +} + +void MCMachOStreamer::Finish() { + Assembler.Finish(); +} + +MCStreamer *llvm::createMachOStreamer(MCContext &Context, raw_ostream &OS, + MCCodeEmitter *CE) { + return new MCMachOStreamer(Context, OS, CE); +} diff --git a/libclamav/c++/llvm/lib/MC/MCNullStreamer.cpp b/libclamav/c++/llvm/lib/MC/MCNullStreamer.cpp new file mode 100644 index 000000000..ddc4e69d2 --- /dev/null +++ b/libclamav/c++/llvm/lib/MC/MCNullStreamer.cpp @@ -0,0 +1,70 @@ +//===- lib/MC/MCNullStreamer.cpp - Dummy Streamer Implementation ----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/MC/MCStreamer.h" + +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCInst.h" +#include "llvm/MC/MCSectionMachO.h" +#include "llvm/MC/MCSymbol.h" + +using namespace llvm; + +namespace { + + class MCNullStreamer : public MCStreamer { + public: + MCNullStreamer(MCContext &Context) : MCStreamer(Context) {} + + /// @name MCStreamer Interface + /// @{ + + virtual void SwitchSection(const MCSection *Section) { + CurSection = Section; + } + + virtual void EmitLabel(MCSymbol *Symbol) {} + + virtual void EmitAssemblerFlag(AssemblerFlag Flag) {} + + virtual void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) {} + + virtual void EmitSymbolAttribute(MCSymbol *Symbol, SymbolAttr Attribute) {} + + virtual void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) {} + + virtual void EmitCommonSymbol(MCSymbol *Symbol, unsigned Size, + unsigned ByteAlignment) {} + + virtual void EmitZerofill(const MCSection *Section, MCSymbol *Symbol = 0, + unsigned Size = 0, unsigned ByteAlignment = 0) {} + + virtual void EmitBytes(StringRef Data) {} + + virtual void EmitValue(const MCExpr *Value, unsigned Size) {} + + virtual void EmitValueToAlignment(unsigned ByteAlignment, int64_t Value = 0, + unsigned ValueSize = 1, + unsigned MaxBytesToEmit = 0) {} + + virtual void EmitValueToOffset(const MCExpr *Offset, + unsigned char Value = 0) {} + + virtual void EmitInstruction(const MCInst &Inst) {} + + virtual void Finish() {} + + /// @} + }; + +} + +MCStreamer *llvm::createNullStreamer(MCContext &Context) { + return new MCNullStreamer(Context); +} diff --git a/libclamav/c++/llvm/lib/MC/MCSection.cpp b/libclamav/c++/llvm/lib/MC/MCSection.cpp new file mode 100644 index 000000000..24c89efef --- /dev/null +++ b/libclamav/c++/llvm/lib/MC/MCSection.cpp @@ -0,0 +1,45 @@ +//===- lib/MC/MCSection.cpp - Machine Code Section Representation ---------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/MC/MCSection.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +//===----------------------------------------------------------------------===// +// MCSection +//===----------------------------------------------------------------------===// + +MCSection::~MCSection() { +} + +//===----------------------------------------------------------------------===// +// MCSectionCOFF +//===----------------------------------------------------------------------===// + +MCSectionCOFF *MCSectionCOFF:: +Create(StringRef Name, bool IsDirective, SectionKind K, MCContext &Ctx) { + return new (Ctx) MCSectionCOFF(Name, IsDirective, K); +} + +void MCSectionCOFF::PrintSwitchToSection(const MCAsmInfo &MAI, + raw_ostream &OS) const { + + if (isDirective()) { + OS << getName() << '\n'; + return; + } + OS << "\t.section\t" << getName() << ",\""; + if (getKind().isText()) + OS << 'x'; + if (getKind().isWriteable()) + OS << 'w'; + OS << "\"\n"; +} diff --git a/libclamav/c++/llvm/lib/MC/MCSectionELF.cpp b/libclamav/c++/llvm/lib/MC/MCSectionELF.cpp new file mode 100644 index 000000000..c6812ed99 --- /dev/null +++ b/libclamav/c++/llvm/lib/MC/MCSectionELF.cpp @@ -0,0 +1,138 @@ +//===- lib/MC/MCSectionELF.cpp - ELF Code Section Representation ----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/MC/MCSectionELF.h" +#include "llvm/MC/MCContext.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/MC/MCAsmInfo.h" + +using namespace llvm; + +MCSectionELF *MCSectionELF:: +Create(StringRef Section, unsigned Type, unsigned Flags, + SectionKind K, bool isExplicit, MCContext &Ctx) { + return new (Ctx) MCSectionELF(Section, Type, Flags, K, isExplicit); +} + +// ShouldOmitSectionDirective - Decides whether a '.section' directive +// should be printed before the section name +bool MCSectionELF::ShouldOmitSectionDirective(const char *Name, + const MCAsmInfo &MAI) const { + + // FIXME: Does .section .bss/.data/.text work everywhere?? + if (strcmp(Name, ".text") == 0 || + strcmp(Name, ".data") == 0 || + (strcmp(Name, ".bss") == 0 && + !MAI.usesELFSectionDirectiveForBSS())) + return true; + + return false; +} + +// ShouldPrintSectionType - Only prints the section type if supported +bool MCSectionELF::ShouldPrintSectionType(unsigned Ty) const { + + if (IsExplicit && !(Ty == SHT_NOBITS || Ty == SHT_PROGBITS)) + return false; + + return true; +} + +void MCSectionELF::PrintSwitchToSection(const MCAsmInfo &MAI, + raw_ostream &OS) const { + + if (ShouldOmitSectionDirective(SectionName.c_str(), MAI)) { + OS << '\t' << getSectionName() << '\n'; + return; + } + + OS << "\t.section\t" << getSectionName(); + + // Handle the weird solaris syntax if desired. + if (MAI.usesSunStyleELFSectionSwitchSyntax() && + !(Flags & MCSectionELF::SHF_MERGE)) { + if (Flags & MCSectionELF::SHF_ALLOC) + OS << ",#alloc"; + if (Flags & MCSectionELF::SHF_EXECINSTR) + OS << ",#execinstr"; + if (Flags & MCSectionELF::SHF_WRITE) + OS << ",#write"; + if (Flags & MCSectionELF::SHF_TLS) + OS << ",#tls"; + } else { + OS << ",\""; + if (Flags & MCSectionELF::SHF_ALLOC) + OS << 'a'; + if (Flags & MCSectionELF::SHF_EXECINSTR) + OS << 'x'; + if (Flags & MCSectionELF::SHF_WRITE) + OS << 'w'; + if (Flags & MCSectionELF::SHF_MERGE) + OS << 'M'; + if (Flags & MCSectionELF::SHF_STRINGS) + OS << 'S'; + if (Flags & MCSectionELF::SHF_TLS) + OS << 'T'; + + // If there are target-specific flags, print them. + if (Flags & ~MCSectionELF::TARGET_INDEP_SHF) + PrintTargetSpecificSectionFlags(MAI, OS); + + OS << '"'; + + if (ShouldPrintSectionType(Type)) { + OS << ','; + + // If comment string is '@', e.g. as on ARM - use '%' instead + if (MAI.getCommentString()[0] == '@') + OS << '%'; + else + OS << '@'; + + if (Type == MCSectionELF::SHT_INIT_ARRAY) + OS << "init_array"; + else if (Type == MCSectionELF::SHT_FINI_ARRAY) + OS << "fini_array"; + else if (Type == MCSectionELF::SHT_PREINIT_ARRAY) + OS << "preinit_array"; + else if (Type == MCSectionELF::SHT_NOBITS) + OS << "nobits"; + else if (Type == MCSectionELF::SHT_PROGBITS) + OS << "progbits"; + + if (getKind().isMergeable1ByteCString()) { + OS << ",1"; + } else if (getKind().isMergeable2ByteCString()) { + OS << ",2"; + } else if (getKind().isMergeable4ByteCString() || + getKind().isMergeableConst4()) { + OS << ",4"; + } else if (getKind().isMergeableConst8()) { + OS << ",8"; + } else if (getKind().isMergeableConst16()) { + OS << ",16"; + } + } + } + + OS << '\n'; +} + +// HasCommonSymbols - True if this section holds common symbols, this is +// indicated on the ELF object file by a symbol with SHN_COMMON section +// header index. +bool MCSectionELF::HasCommonSymbols() const { + + if (strncmp(SectionName.c_str(), ".gnu.linkonce.", 14) == 0) + return true; + + return false; +} + + diff --git a/libclamav/c++/llvm/lib/MC/MCSectionMachO.cpp b/libclamav/c++/llvm/lib/MC/MCSectionMachO.cpp new file mode 100644 index 000000000..6cc67a222 --- /dev/null +++ b/libclamav/c++/llvm/lib/MC/MCSectionMachO.cpp @@ -0,0 +1,271 @@ +//===- lib/MC/MCSectionMachO.cpp - MachO Code Section Representation ------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/MC/MCSectionMachO.h" +#include "llvm/MC/MCContext.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +/// SectionTypeDescriptors - These are strings that describe the various section +/// types. This *must* be kept in order with and stay synchronized with the +/// section type list. +static const struct { + const char *AssemblerName, *EnumName; +} SectionTypeDescriptors[MCSectionMachO::LAST_KNOWN_SECTION_TYPE+1] = { + { "regular", "S_REGULAR" }, // 0x00 + { 0, "S_ZEROFILL" }, // 0x01 + { "cstring_literals", "S_CSTRING_LITERALS" }, // 0x02 + { "4byte_literals", "S_4BYTE_LITERALS" }, // 0x03 + { "8byte_literals", "S_8BYTE_LITERALS" }, // 0x04 + { "literal_pointers", "S_LITERAL_POINTERS" }, // 0x05 + { "non_lazy_symbol_pointers", "S_NON_LAZY_SYMBOL_POINTERS" }, // 0x06 + { "lazy_symbol_pointers", "S_LAZY_SYMBOL_POINTERS" }, // 0x07 + { "symbol_stubs", "S_SYMBOL_STUBS" }, // 0x08 + { "mod_init_funcs", "S_MOD_INIT_FUNC_POINTERS" }, // 0x09 + { "mod_term_funcs", "S_MOD_TERM_FUNC_POINTERS" }, // 0x0A + { "coalesced", "S_COALESCED" }, // 0x0B + { 0, /*FIXME??*/ "S_GB_ZEROFILL" }, // 0x0C + { "interposing", "S_INTERPOSING" }, // 0x0D + { "16byte_literals", "S_16BYTE_LITERALS" }, // 0x0E + { 0, /*FIXME??*/ "S_DTRACE_DOF" }, // 0x0F + { 0, /*FIXME??*/ "S_LAZY_DYLIB_SYMBOL_POINTERS" } // 0x10 +}; + + +/// SectionAttrDescriptors - This is an array of descriptors for section +/// attributes. Unlike the SectionTypeDescriptors, this is not directly indexed +/// by attribute, instead it is searched. The last entry has an AttrFlagEnd +/// AttrFlag value. +static const struct { + unsigned AttrFlag; + const char *AssemblerName, *EnumName; +} SectionAttrDescriptors[] = { +#define ENTRY(ASMNAME, ENUM) \ + { MCSectionMachO::ENUM, ASMNAME, #ENUM }, +ENTRY("pure_instructions", S_ATTR_PURE_INSTRUCTIONS) +ENTRY("no_toc", S_ATTR_NO_TOC) +ENTRY("strip_static_syms", S_ATTR_STRIP_STATIC_SYMS) +ENTRY("no_dead_strip", S_ATTR_NO_DEAD_STRIP) +ENTRY("live_support", S_ATTR_LIVE_SUPPORT) +ENTRY("self_modifying_code", S_ATTR_SELF_MODIFYING_CODE) +ENTRY("debug", S_ATTR_DEBUG) +ENTRY(0 /*FIXME*/, S_ATTR_SOME_INSTRUCTIONS) +ENTRY(0 /*FIXME*/, S_ATTR_EXT_RELOC) +ENTRY(0 /*FIXME*/, S_ATTR_LOC_RELOC) +#undef ENTRY + { 0, "none", 0 }, // used if section has no attributes but has a stub size +#define AttrFlagEnd 0xffffffff // non legal value, multiple attribute bits set + { AttrFlagEnd, 0, 0 } +}; + + +MCSectionMachO *MCSectionMachO:: +Create(StringRef Segment, StringRef Section, + unsigned TypeAndAttributes, unsigned Reserved2, + SectionKind K, MCContext &Ctx) { + // S_SYMBOL_STUBS must be set for Reserved2 to be non-zero. + return new (Ctx) MCSectionMachO(Segment, Section, TypeAndAttributes, + Reserved2, K); +} + +void MCSectionMachO::PrintSwitchToSection(const MCAsmInfo &MAI, + raw_ostream &OS) const { + OS << "\t.section\t" << getSegmentName() << ',' << getSectionName(); + + // Get the section type and attributes. + unsigned TAA = getTypeAndAttributes(); + if (TAA == 0) { + OS << '\n'; + return; + } + + OS << ','; + + unsigned SectionType = TAA & MCSectionMachO::SECTION_TYPE; + assert(SectionType <= MCSectionMachO::LAST_KNOWN_SECTION_TYPE && + "Invalid SectionType specified!"); + + if (SectionTypeDescriptors[SectionType].AssemblerName) + OS << SectionTypeDescriptors[SectionType].AssemblerName; + else + OS << "<<" << SectionTypeDescriptors[SectionType].EnumName << ">>"; + + // If we don't have any attributes, we're done. + unsigned SectionAttrs = TAA & MCSectionMachO::SECTION_ATTRIBUTES; + if (SectionAttrs == 0) { + // If we have a S_SYMBOL_STUBS size specified, print it along with 'none' as + // the attribute specifier. + if (Reserved2 != 0) + OS << ",none," << Reserved2; + OS << '\n'; + return; + } + + // Check each attribute to see if we have it. + char Separator = ','; + for (unsigned i = 0; SectionAttrDescriptors[i].AttrFlag; ++i) { + // Check to see if we have this attribute. + if ((SectionAttrDescriptors[i].AttrFlag & SectionAttrs) == 0) + continue; + + // Yep, clear it and print it. + SectionAttrs &= ~SectionAttrDescriptors[i].AttrFlag; + + OS << Separator; + if (SectionAttrDescriptors[i].AssemblerName) + OS << SectionAttrDescriptors[i].AssemblerName; + else + OS << "<<" << SectionAttrDescriptors[i].EnumName << ">>"; + Separator = '+'; + } + + assert(SectionAttrs == 0 && "Unknown section attributes!"); + + // If we have a S_SYMBOL_STUBS size specified, print it. + if (Reserved2 != 0) + OS << ',' << Reserved2; + OS << '\n'; +} + +/// StripSpaces - This removes leading and trailing spaces from the StringRef. +static void StripSpaces(StringRef &Str) { + while (!Str.empty() && isspace(Str[0])) + Str = Str.substr(1); + while (!Str.empty() && isspace(Str.back())) + Str = Str.substr(0, Str.size()-1); +} + +/// ParseSectionSpecifier - Parse the section specifier indicated by "Spec". +/// This is a string that can appear after a .section directive in a mach-o +/// flavored .s file. If successful, this fills in the specified Out +/// parameters and returns an empty string. When an invalid section +/// specifier is present, this returns a string indicating the problem. +std::string MCSectionMachO::ParseSectionSpecifier(StringRef Spec, // In. + StringRef &Segment, // Out. + StringRef &Section, // Out. + unsigned &TAA, // Out. + unsigned &StubSize) { // Out. + // Find the first comma. + std::pair Comma = Spec.split(','); + + // If there is no comma, we fail. + if (Comma.second.empty()) + return "mach-o section specifier requires a segment and section " + "separated by a comma"; + + // Capture segment, remove leading and trailing whitespace. + Segment = Comma.first; + StripSpaces(Segment); + + // Verify that the segment is present and not too long. + if (Segment.empty() || Segment.size() > 16) + return "mach-o section specifier requires a segment whose length is " + "between 1 and 16 characters"; + + // Split the section name off from any attributes if present. + Comma = Comma.second.split(','); + + // Capture section, remove leading and trailing whitespace. + Section = Comma.first; + StripSpaces(Section); + + // Verify that the section is present and not too long. + if (Section.empty() || Section.size() > 16) + return "mach-o section specifier requires a section whose length is " + "between 1 and 16 characters"; + + // If there is no comma after the section, we're done. + TAA = 0; + StubSize = 0; + if (Comma.second.empty()) + return ""; + + // Otherwise, we need to parse the section type and attributes. + Comma = Comma.second.split(','); + + // Get the section type. + StringRef SectionType = Comma.first; + StripSpaces(SectionType); + + // Figure out which section type it is. + unsigned TypeID; + for (TypeID = 0; TypeID !=MCSectionMachO::LAST_KNOWN_SECTION_TYPE+1; ++TypeID) + if (SectionTypeDescriptors[TypeID].AssemblerName && + SectionType == SectionTypeDescriptors[TypeID].AssemblerName) + break; + + // If we didn't find the section type, reject it. + if (TypeID > MCSectionMachO::LAST_KNOWN_SECTION_TYPE) + return "mach-o section specifier uses an unknown section type"; + + // Remember the TypeID. + TAA = TypeID; + + // If we have no comma after the section type, there are no attributes. + if (Comma.second.empty()) { + // S_SYMBOL_STUBS always require a symbol stub size specifier. + if (TAA == MCSectionMachO::S_SYMBOL_STUBS) + return "mach-o section specifier of type 'symbol_stubs' requires a size " + "specifier"; + return ""; + } + + // Otherwise, we do have some attributes. Split off the size specifier if + // present. + Comma = Comma.second.split(','); + StringRef Attrs = Comma.first; + + // The attribute list is a '+' separated list of attributes. + std::pair Plus = Attrs.split('+'); + + while (1) { + StringRef Attr = Plus.first; + StripSpaces(Attr); + + // Look up the attribute. + for (unsigned i = 0; ; ++i) { + if (SectionAttrDescriptors[i].AttrFlag == AttrFlagEnd) + return "mach-o section specifier has invalid attribute"; + + if (SectionAttrDescriptors[i].AssemblerName && + Attr == SectionAttrDescriptors[i].AssemblerName) { + TAA |= SectionAttrDescriptors[i].AttrFlag; + break; + } + } + + if (Plus.second.empty()) break; + Plus = Plus.second.split('+'); + }; + + // Okay, we've parsed the section attributes, see if we have a stub size spec. + if (Comma.second.empty()) { + // S_SYMBOL_STUBS always require a symbol stub size specifier. + if (TAA == MCSectionMachO::S_SYMBOL_STUBS) + return "mach-o section specifier of type 'symbol_stubs' requires a size " + "specifier"; + return ""; + } + + // If we have a stub size spec, we must have a sectiontype of S_SYMBOL_STUBS. + if ((TAA & MCSectionMachO::SECTION_TYPE) != MCSectionMachO::S_SYMBOL_STUBS) + return "mach-o section specifier cannot have a stub size specified because " + "it does not have type 'symbol_stubs'"; + + // Okay, if we do, it must be a number. + StringRef StubSizeStr = Comma.second; + StripSpaces(StubSizeStr); + + // Convert the stub size from a string to an integer. + if (StubSizeStr.getAsInteger(0, StubSize)) + return "mach-o section specifier has a malformed stub size"; + + return ""; +} + diff --git a/libclamav/c++/llvm/lib/MC/MCStreamer.cpp b/libclamav/c++/llvm/lib/MC/MCStreamer.cpp new file mode 100644 index 000000000..8a6dcdae7 --- /dev/null +++ b/libclamav/c++/llvm/lib/MC/MCStreamer.cpp @@ -0,0 +1,18 @@ +//===- lib/MC/MCStreamer.cpp - Streaming Machine Code Output --------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/MC/MCStreamer.h" + +using namespace llvm; + +MCStreamer::MCStreamer(MCContext &_Context) : Context(_Context), CurSection(0) { +} + +MCStreamer::~MCStreamer() { +} diff --git a/libclamav/c++/llvm/lib/MC/MCSymbol.cpp b/libclamav/c++/llvm/lib/MC/MCSymbol.cpp new file mode 100644 index 000000000..b145d07f4 --- /dev/null +++ b/libclamav/c++/llvm/lib/MC/MCSymbol.cpp @@ -0,0 +1,110 @@ +//===- lib/MC/MCSymbol.cpp - MCSymbol implementation ----------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/MC/MCSymbol.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +// Sentinel value for the absolute pseudo section. +const MCSection *MCSymbol::AbsolutePseudoSection = + reinterpret_cast(1); + +static bool isAcceptableChar(char C) { + if ((C < 'a' || C > 'z') && + (C < 'A' || C > 'Z') && + (C < '0' || C > '9') && + C != '_' && C != '$' && C != '.' && C != '@') + return false; + return true; +} + +static char HexDigit(int V) { + return V < 10 ? V+'0' : V+'A'-10; +} + +static void MangleLetter(raw_ostream &OS, unsigned char C) { + OS << '_' << HexDigit(C >> 4) << HexDigit(C & 15) << '_'; +} + +/// NameNeedsEscaping - Return true if the identifier \arg Str needs quotes +/// for this assembler. +static bool NameNeedsEscaping(StringRef Str, const MCAsmInfo &MAI) { + assert(!Str.empty() && "Cannot create an empty MCSymbol"); + + // If the first character is a number and the target does not allow this, we + // need quotes. + if (!MAI.doesAllowNameToStartWithDigit() && Str[0] >= '0' && Str[0] <= '9') + return true; + + // If any of the characters in the string is an unacceptable character, force + // quotes. + for (unsigned i = 0, e = Str.size(); i != e; ++i) + if (!isAcceptableChar(Str[i])) + return true; + return false; +} + +static void PrintMangledName(raw_ostream &OS, StringRef Str, + const MCAsmInfo &MAI) { + // The first character is not allowed to be a number unless the target + // explicitly allows it. + if (!MAI.doesAllowNameToStartWithDigit() && Str[0] >= '0' && Str[0] <= '9') { + MangleLetter(OS, Str[0]); + Str = Str.substr(1); + } + + for (unsigned i = 0, e = Str.size(); i != e; ++i) { + if (!isAcceptableChar(Str[i])) + MangleLetter(OS, Str[i]); + else + OS << Str[i]; + } +} + +/// PrintMangledQuotedName - On systems that support quoted symbols, we still +/// have to escape some (obscure) characters like " and \n which would break the +/// assembler's lexing. +static void PrintMangledQuotedName(raw_ostream &OS, StringRef Str) { + OS << '"'; + + for (unsigned i = 0, e = Str.size(); i != e; ++i) { + if (Str[i] == '"') + OS << "_QQ_"; + else if (Str[i] == '\n') + OS << "_NL_"; + else + OS << Str[i]; + } + OS << '"'; +} + + +void MCSymbol::print(raw_ostream &OS, const MCAsmInfo *MAI) const { + if (MAI == 0 || !NameNeedsEscaping(getName(), *MAI)) { + OS << getName(); + return; + } + + // On systems that do not allow quoted names, print with mangling. + if (!MAI->doesAllowQuotesInName()) + return PrintMangledName(OS, getName(), *MAI); + + // If the string contains a double quote or newline, we still have to mangle + // it. + if (getName().find('"') != std::string::npos || + getName().find('\n') != std::string::npos) + return PrintMangledQuotedName(OS, getName()); + + OS << '"' << getName() << '"'; +} + +void MCSymbol::dump() const { + print(errs(), 0); +} diff --git a/libclamav/c++/llvm/lib/MC/MCValue.cpp b/libclamav/c++/llvm/lib/MC/MCValue.cpp new file mode 100644 index 000000000..69bd10c8e --- /dev/null +++ b/libclamav/c++/llvm/lib/MC/MCValue.cpp @@ -0,0 +1,34 @@ +//===- lib/MC/MCValue.cpp - MCValue implementation ------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/MC/MCValue.h" +#include "llvm/Support/raw_ostream.h" + +using namespace llvm; + +void MCValue::print(raw_ostream &OS, const MCAsmInfo *MAI) const { + if (isAbsolute()) { + OS << getConstant(); + return; + } + + getSymA()->print(OS, MAI); + + if (getSymB()) { + OS << " - "; + getSymB()->print(OS, MAI); + } + + if (getConstant()) + OS << " + " << getConstant(); +} + +void MCValue::dump() const { + print(errs(), 0); +} diff --git a/libclamav/c++/llvm/lib/MC/Makefile b/libclamav/c++/llvm/lib/MC/Makefile new file mode 100644 index 000000000..314a5b1af --- /dev/null +++ b/libclamav/c++/llvm/lib/MC/Makefile @@ -0,0 +1,15 @@ +##===- lib/MC/Makefile -------------------------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LEVEL = ../.. +LIBRARYNAME = LLVMMC +BUILD_ARCHIVE := 1 + +include $(LEVEL)/Makefile.common + diff --git a/libclamav/c++/llvm/lib/MC/TargetAsmParser.cpp b/libclamav/c++/llvm/lib/MC/TargetAsmParser.cpp new file mode 100644 index 000000000..05760c96c --- /dev/null +++ b/libclamav/c++/llvm/lib/MC/TargetAsmParser.cpp @@ -0,0 +1,19 @@ +//===-- TargetAsmParser.cpp - Target Assembly Parser -----------------------==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Target/TargetAsmParser.h" +using namespace llvm; + +TargetAsmParser::TargetAsmParser(const Target &T) + : TheTarget(T) +{ +} + +TargetAsmParser::~TargetAsmParser() { +} diff --git a/libclamav/c++/llvm/lib/Makefile b/libclamav/c++/llvm/lib/Makefile new file mode 100644 index 000000000..3807f31c7 --- /dev/null +++ b/libclamav/c++/llvm/lib/Makefile @@ -0,0 +1,17 @@ +##===- lib/Makefile ----------------------------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## +LEVEL = .. + +include $(LEVEL)/Makefile.config + +PARALLEL_DIRS := VMCore AsmParser Bitcode Archive Analysis Transforms CodeGen \ + Target ExecutionEngine Linker MC CompilerDriver + +include $(LEVEL)/Makefile.common + diff --git a/libclamav/c++/llvm/lib/Support/APFloat.cpp b/libclamav/c++/llvm/lib/Support/APFloat.cpp new file mode 100644 index 000000000..b9b323c42 --- /dev/null +++ b/libclamav/c++/llvm/lib/Support/APFloat.cpp @@ -0,0 +1,3157 @@ +//===-- APFloat.cpp - Implement APFloat class -----------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements a class to represent arbitrary precision floating +// point values and provide a variety of arithmetic operations on them. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/APFloat.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/FoldingSet.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/MathExtras.h" +#include + +using namespace llvm; + +#define convolve(lhs, rhs) ((lhs) * 4 + (rhs)) + +/* Assumed in hexadecimal significand parsing, and conversion to + hexadecimal strings. */ +#define COMPILE_TIME_ASSERT(cond) extern int CTAssert[(cond) ? 1 : -1] +COMPILE_TIME_ASSERT(integerPartWidth % 4 == 0); + +namespace llvm { + + /* Represents floating point arithmetic semantics. */ + struct fltSemantics { + /* The largest E such that 2^E is representable; this matches the + definition of IEEE 754. */ + exponent_t maxExponent; + + /* The smallest E such that 2^E is a normalized number; this + matches the definition of IEEE 754. */ + exponent_t minExponent; + + /* Number of bits in the significand. This includes the integer + bit. */ + unsigned int precision; + + /* True if arithmetic is supported. */ + unsigned int arithmeticOK; + }; + + const fltSemantics APFloat::IEEEhalf = { 15, -14, 11, true }; + const fltSemantics APFloat::IEEEsingle = { 127, -126, 24, true }; + const fltSemantics APFloat::IEEEdouble = { 1023, -1022, 53, true }; + const fltSemantics APFloat::IEEEquad = { 16383, -16382, 113, true }; + const fltSemantics APFloat::x87DoubleExtended = { 16383, -16382, 64, true }; + const fltSemantics APFloat::Bogus = { 0, 0, 0, true }; + + // The PowerPC format consists of two doubles. It does not map cleanly + // onto the usual format above. For now only storage of constants of + // this type is supported, no arithmetic. + const fltSemantics APFloat::PPCDoubleDouble = { 1023, -1022, 106, false }; + + /* A tight upper bound on number of parts required to hold the value + pow(5, power) is + + power * 815 / (351 * integerPartWidth) + 1 + + However, whilst the result may require only this many parts, + because we are multiplying two values to get it, the + multiplication may require an extra part with the excess part + being zero (consider the trivial case of 1 * 1, tcFullMultiply + requires two parts to hold the single-part result). So we add an + extra one to guarantee enough space whilst multiplying. */ + const unsigned int maxExponent = 16383; + const unsigned int maxPrecision = 113; + const unsigned int maxPowerOfFiveExponent = maxExponent + maxPrecision - 1; + const unsigned int maxPowerOfFiveParts = 2 + ((maxPowerOfFiveExponent * 815) + / (351 * integerPartWidth)); +} + +/* A bunch of private, handy routines. */ + +static inline unsigned int +partCountForBits(unsigned int bits) +{ + return ((bits) + integerPartWidth - 1) / integerPartWidth; +} + +/* Returns 0U-9U. Return values >= 10U are not digits. */ +static inline unsigned int +decDigitValue(unsigned int c) +{ + return c - '0'; +} + +static unsigned int +hexDigitValue(unsigned int c) +{ + unsigned int r; + + r = c - '0'; + if(r <= 9) + return r; + + r = c - 'A'; + if(r <= 5) + return r + 10; + + r = c - 'a'; + if(r <= 5) + return r + 10; + + return -1U; +} + +static inline void +assertArithmeticOK(const llvm::fltSemantics &semantics) { + assert(semantics.arithmeticOK + && "Compile-time arithmetic does not support these semantics"); +} + +/* Return the value of a decimal exponent of the form + [+-]ddddddd. + + If the exponent overflows, returns a large exponent with the + appropriate sign. */ +static int +readExponent(StringRef::iterator begin, StringRef::iterator end) +{ + bool isNegative; + unsigned int absExponent; + const unsigned int overlargeExponent = 24000; /* FIXME. */ + StringRef::iterator p = begin; + + assert(p != end && "Exponent has no digits"); + + isNegative = (*p == '-'); + if (*p == '-' || *p == '+') { + p++; + assert(p != end && "Exponent has no digits"); + } + + absExponent = decDigitValue(*p++); + assert(absExponent < 10U && "Invalid character in exponent"); + + for (; p != end; ++p) { + unsigned int value; + + value = decDigitValue(*p); + assert(value < 10U && "Invalid character in exponent"); + + value += absExponent * 10; + if (absExponent >= overlargeExponent) { + absExponent = overlargeExponent; + break; + } + absExponent = value; + } + + assert(p == end && "Invalid exponent in exponent"); + + if (isNegative) + return -(int) absExponent; + else + return (int) absExponent; +} + +/* This is ugly and needs cleaning up, but I don't immediately see + how whilst remaining safe. */ +static int +totalExponent(StringRef::iterator p, StringRef::iterator end, + int exponentAdjustment) +{ + int unsignedExponent; + bool negative, overflow; + int exponent; + + assert(p != end && "Exponent has no digits"); + + negative = *p == '-'; + if(*p == '-' || *p == '+') { + p++; + assert(p != end && "Exponent has no digits"); + } + + unsignedExponent = 0; + overflow = false; + for(; p != end; ++p) { + unsigned int value; + + value = decDigitValue(*p); + assert(value < 10U && "Invalid character in exponent"); + + unsignedExponent = unsignedExponent * 10 + value; + if(unsignedExponent > 65535) + overflow = true; + } + + if(exponentAdjustment > 65535 || exponentAdjustment < -65536) + overflow = true; + + if(!overflow) { + exponent = unsignedExponent; + if(negative) + exponent = -exponent; + exponent += exponentAdjustment; + if(exponent > 65535 || exponent < -65536) + overflow = true; + } + + if(overflow) + exponent = negative ? -65536: 65535; + + return exponent; +} + +static StringRef::iterator +skipLeadingZeroesAndAnyDot(StringRef::iterator begin, StringRef::iterator end, + StringRef::iterator *dot) +{ + StringRef::iterator p = begin; + *dot = end; + while(*p == '0' && p != end) + p++; + + if(*p == '.') { + *dot = p++; + + assert(end - begin != 1 && "Significand has no digits"); + + while(*p == '0' && p != end) + p++; + } + + return p; +} + +/* Given a normal decimal floating point number of the form + + dddd.dddd[eE][+-]ddd + + where the decimal point and exponent are optional, fill out the + structure D. Exponent is appropriate if the significand is + treated as an integer, and normalizedExponent if the significand + is taken to have the decimal point after a single leading + non-zero digit. + + If the value is zero, V->firstSigDigit points to a non-digit, and + the return exponent is zero. +*/ +struct decimalInfo { + const char *firstSigDigit; + const char *lastSigDigit; + int exponent; + int normalizedExponent; +}; + +static void +interpretDecimal(StringRef::iterator begin, StringRef::iterator end, + decimalInfo *D) +{ + StringRef::iterator dot = end; + StringRef::iterator p = skipLeadingZeroesAndAnyDot (begin, end, &dot); + + D->firstSigDigit = p; + D->exponent = 0; + D->normalizedExponent = 0; + + for (; p != end; ++p) { + if (*p == '.') { + assert(dot == end && "String contains multiple dots"); + dot = p++; + if (p == end) + break; + } + if (decDigitValue(*p) >= 10U) + break; + } + + if (p != end) { + assert((*p == 'e' || *p == 'E') && "Invalid character in significand"); + assert(p != begin && "Significand has no digits"); + assert((dot == end || p - begin != 1) && "Significand has no digits"); + + /* p points to the first non-digit in the string */ + D->exponent = readExponent(p + 1, end); + + /* Implied decimal point? */ + if (dot == end) + dot = p; + } + + /* If number is all zeroes accept any exponent. */ + if (p != D->firstSigDigit) { + /* Drop insignificant trailing zeroes. */ + if (p != begin) { + do + do + p--; + while (p != begin && *p == '0'); + while (p != begin && *p == '.'); + } + + /* Adjust the exponents for any decimal point. */ + D->exponent += static_cast((dot - p) - (dot > p)); + D->normalizedExponent = (D->exponent + + static_cast((p - D->firstSigDigit) + - (dot > D->firstSigDigit && dot < p))); + } + + D->lastSigDigit = p; +} + +/* Return the trailing fraction of a hexadecimal number. + DIGITVALUE is the first hex digit of the fraction, P points to + the next digit. */ +static lostFraction +trailingHexadecimalFraction(StringRef::iterator p, StringRef::iterator end, + unsigned int digitValue) +{ + unsigned int hexDigit; + + /* If the first trailing digit isn't 0 or 8 we can work out the + fraction immediately. */ + if(digitValue > 8) + return lfMoreThanHalf; + else if(digitValue < 8 && digitValue > 0) + return lfLessThanHalf; + + /* Otherwise we need to find the first non-zero digit. */ + while(*p == '0') + p++; + + assert(p != end && "Invalid trailing hexadecimal fraction!"); + + hexDigit = hexDigitValue(*p); + + /* If we ran off the end it is exactly zero or one-half, otherwise + a little more. */ + if(hexDigit == -1U) + return digitValue == 0 ? lfExactlyZero: lfExactlyHalf; + else + return digitValue == 0 ? lfLessThanHalf: lfMoreThanHalf; +} + +/* Return the fraction lost were a bignum truncated losing the least + significant BITS bits. */ +static lostFraction +lostFractionThroughTruncation(const integerPart *parts, + unsigned int partCount, + unsigned int bits) +{ + unsigned int lsb; + + lsb = APInt::tcLSB(parts, partCount); + + /* Note this is guaranteed true if bits == 0, or LSB == -1U. */ + if(bits <= lsb) + return lfExactlyZero; + if(bits == lsb + 1) + return lfExactlyHalf; + if(bits <= partCount * integerPartWidth + && APInt::tcExtractBit(parts, bits - 1)) + return lfMoreThanHalf; + + return lfLessThanHalf; +} + +/* Shift DST right BITS bits noting lost fraction. */ +static lostFraction +shiftRight(integerPart *dst, unsigned int parts, unsigned int bits) +{ + lostFraction lost_fraction; + + lost_fraction = lostFractionThroughTruncation(dst, parts, bits); + + APInt::tcShiftRight(dst, parts, bits); + + return lost_fraction; +} + +/* Combine the effect of two lost fractions. */ +static lostFraction +combineLostFractions(lostFraction moreSignificant, + lostFraction lessSignificant) +{ + if(lessSignificant != lfExactlyZero) { + if(moreSignificant == lfExactlyZero) + moreSignificant = lfLessThanHalf; + else if(moreSignificant == lfExactlyHalf) + moreSignificant = lfMoreThanHalf; + } + + return moreSignificant; +} + +/* The error from the true value, in half-ulps, on multiplying two + floating point numbers, which differ from the value they + approximate by at most HUE1 and HUE2 half-ulps, is strictly less + than the returned value. + + See "How to Read Floating Point Numbers Accurately" by William D + Clinger. */ +static unsigned int +HUerrBound(bool inexactMultiply, unsigned int HUerr1, unsigned int HUerr2) +{ + assert(HUerr1 < 2 || HUerr2 < 2 || (HUerr1 + HUerr2 < 8)); + + if (HUerr1 + HUerr2 == 0) + return inexactMultiply * 2; /* <= inexactMultiply half-ulps. */ + else + return inexactMultiply + 2 * (HUerr1 + HUerr2); +} + +/* The number of ulps from the boundary (zero, or half if ISNEAREST) + when the least significant BITS are truncated. BITS cannot be + zero. */ +static integerPart +ulpsFromBoundary(const integerPart *parts, unsigned int bits, bool isNearest) +{ + unsigned int count, partBits; + integerPart part, boundary; + + assert(bits != 0); + + bits--; + count = bits / integerPartWidth; + partBits = bits % integerPartWidth + 1; + + part = parts[count] & (~(integerPart) 0 >> (integerPartWidth - partBits)); + + if (isNearest) + boundary = (integerPart) 1 << (partBits - 1); + else + boundary = 0; + + if (count == 0) { + if (part - boundary <= boundary - part) + return part - boundary; + else + return boundary - part; + } + + if (part == boundary) { + while (--count) + if (parts[count]) + return ~(integerPart) 0; /* A lot. */ + + return parts[0]; + } else if (part == boundary - 1) { + while (--count) + if (~parts[count]) + return ~(integerPart) 0; /* A lot. */ + + return -parts[0]; + } + + return ~(integerPart) 0; /* A lot. */ +} + +/* Place pow(5, power) in DST, and return the number of parts used. + DST must be at least one part larger than size of the answer. */ +static unsigned int +powerOf5(integerPart *dst, unsigned int power) +{ + static const integerPart firstEightPowers[] = { 1, 5, 25, 125, 625, 3125, + 15625, 78125 }; + integerPart pow5s[maxPowerOfFiveParts * 2 + 5]; + pow5s[0] = 78125 * 5; + + unsigned int partsCount[16] = { 1 }; + integerPart scratch[maxPowerOfFiveParts], *p1, *p2, *pow5; + unsigned int result; + assert(power <= maxExponent); + + p1 = dst; + p2 = scratch; + + *p1 = firstEightPowers[power & 7]; + power >>= 3; + + result = 1; + pow5 = pow5s; + + for (unsigned int n = 0; power; power >>= 1, n++) { + unsigned int pc; + + pc = partsCount[n]; + + /* Calculate pow(5,pow(2,n+3)) if we haven't yet. */ + if (pc == 0) { + pc = partsCount[n - 1]; + APInt::tcFullMultiply(pow5, pow5 - pc, pow5 - pc, pc, pc); + pc *= 2; + if (pow5[pc - 1] == 0) + pc--; + partsCount[n] = pc; + } + + if (power & 1) { + integerPart *tmp; + + APInt::tcFullMultiply(p2, p1, pow5, result, pc); + result += pc; + if (p2[result - 1] == 0) + result--; + + /* Now result is in p1 with partsCount parts and p2 is scratch + space. */ + tmp = p1, p1 = p2, p2 = tmp; + } + + pow5 += pc; + } + + if (p1 != dst) + APInt::tcAssign(dst, p1, result); + + return result; +} + +/* Zero at the end to avoid modular arithmetic when adding one; used + when rounding up during hexadecimal output. */ +static const char hexDigitsLower[] = "0123456789abcdef0"; +static const char hexDigitsUpper[] = "0123456789ABCDEF0"; +static const char infinityL[] = "infinity"; +static const char infinityU[] = "INFINITY"; +static const char NaNL[] = "nan"; +static const char NaNU[] = "NAN"; + +/* Write out an integerPart in hexadecimal, starting with the most + significant nibble. Write out exactly COUNT hexdigits, return + COUNT. */ +static unsigned int +partAsHex (char *dst, integerPart part, unsigned int count, + const char *hexDigitChars) +{ + unsigned int result = count; + + assert(count != 0 && count <= integerPartWidth / 4); + + part >>= (integerPartWidth - 4 * count); + while (count--) { + dst[count] = hexDigitChars[part & 0xf]; + part >>= 4; + } + + return result; +} + +/* Write out an unsigned decimal integer. */ +static char * +writeUnsignedDecimal (char *dst, unsigned int n) +{ + char buff[40], *p; + + p = buff; + do + *p++ = '0' + n % 10; + while (n /= 10); + + do + *dst++ = *--p; + while (p != buff); + + return dst; +} + +/* Write out a signed decimal integer. */ +static char * +writeSignedDecimal (char *dst, int value) +{ + if (value < 0) { + *dst++ = '-'; + dst = writeUnsignedDecimal(dst, -(unsigned) value); + } else + dst = writeUnsignedDecimal(dst, value); + + return dst; +} + +/* Constructors. */ +void +APFloat::initialize(const fltSemantics *ourSemantics) +{ + unsigned int count; + + semantics = ourSemantics; + count = partCount(); + if(count > 1) + significand.parts = new integerPart[count]; +} + +void +APFloat::freeSignificand() +{ + if(partCount() > 1) + delete [] significand.parts; +} + +void +APFloat::assign(const APFloat &rhs) +{ + assert(semantics == rhs.semantics); + + sign = rhs.sign; + category = rhs.category; + exponent = rhs.exponent; + sign2 = rhs.sign2; + exponent2 = rhs.exponent2; + if(category == fcNormal || category == fcNaN) + copySignificand(rhs); +} + +void +APFloat::copySignificand(const APFloat &rhs) +{ + assert(category == fcNormal || category == fcNaN); + assert(rhs.partCount() >= partCount()); + + APInt::tcAssign(significandParts(), rhs.significandParts(), + partCount()); +} + +/* Make this number a NaN, with an arbitrary but deterministic value + for the significand. If double or longer, this is a signalling NaN, + which may not be ideal. If float, this is QNaN(0). */ +void +APFloat::makeNaN(unsigned type) +{ + category = fcNaN; + // FIXME: Add double and long double support for QNaN(0). + if (semantics->precision == 24 && semantics->maxExponent == 127) { + type |= 0x7fc00000U; + type &= ~0x80000000U; + } else + type = ~0U; + APInt::tcSet(significandParts(), type, partCount()); +} + +APFloat & +APFloat::operator=(const APFloat &rhs) +{ + if(this != &rhs) { + if(semantics != rhs.semantics) { + freeSignificand(); + initialize(rhs.semantics); + } + assign(rhs); + } + + return *this; +} + +bool +APFloat::bitwiseIsEqual(const APFloat &rhs) const { + if (this == &rhs) + return true; + if (semantics != rhs.semantics || + category != rhs.category || + sign != rhs.sign) + return false; + if (semantics==(const llvm::fltSemantics*)&PPCDoubleDouble && + sign2 != rhs.sign2) + return false; + if (category==fcZero || category==fcInfinity) + return true; + else if (category==fcNormal && exponent!=rhs.exponent) + return false; + else if (semantics==(const llvm::fltSemantics*)&PPCDoubleDouble && + exponent2!=rhs.exponent2) + return false; + else { + int i= partCount(); + const integerPart* p=significandParts(); + const integerPart* q=rhs.significandParts(); + for (; i>0; i--, p++, q++) { + if (*p != *q) + return false; + } + return true; + } +} + +APFloat::APFloat(const fltSemantics &ourSemantics, integerPart value) +{ + assertArithmeticOK(ourSemantics); + initialize(&ourSemantics); + sign = 0; + zeroSignificand(); + exponent = ourSemantics.precision - 1; + significandParts()[0] = value; + normalize(rmNearestTiesToEven, lfExactlyZero); +} + +APFloat::APFloat(const fltSemantics &ourSemantics) { + assertArithmeticOK(ourSemantics); + initialize(&ourSemantics); + category = fcZero; + sign = false; +} + + +APFloat::APFloat(const fltSemantics &ourSemantics, + fltCategory ourCategory, bool negative, unsigned type) +{ + assertArithmeticOK(ourSemantics); + initialize(&ourSemantics); + category = ourCategory; + sign = negative; + if (category == fcNormal) + category = fcZero; + else if (ourCategory == fcNaN) + makeNaN(type); +} + +APFloat::APFloat(const fltSemantics &ourSemantics, const StringRef& text) +{ + assertArithmeticOK(ourSemantics); + initialize(&ourSemantics); + convertFromString(text, rmNearestTiesToEven); +} + +APFloat::APFloat(const APFloat &rhs) +{ + initialize(rhs.semantics); + assign(rhs); +} + +APFloat::~APFloat() +{ + freeSignificand(); +} + +// Profile - This method 'profiles' an APFloat for use with FoldingSet. +void APFloat::Profile(FoldingSetNodeID& ID) const { + ID.Add(bitcastToAPInt()); +} + +unsigned int +APFloat::partCount() const +{ + return partCountForBits(semantics->precision + 1); +} + +unsigned int +APFloat::semanticsPrecision(const fltSemantics &semantics) +{ + return semantics.precision; +} + +const integerPart * +APFloat::significandParts() const +{ + return const_cast(this)->significandParts(); +} + +integerPart * +APFloat::significandParts() +{ + assert(category == fcNormal || category == fcNaN); + + if (partCount() > 1) + return significand.parts; + else + return &significand.part; +} + +void +APFloat::zeroSignificand() +{ + category = fcNormal; + APInt::tcSet(significandParts(), 0, partCount()); +} + +/* Increment an fcNormal floating point number's significand. */ +void +APFloat::incrementSignificand() +{ + integerPart carry; + + carry = APInt::tcIncrement(significandParts(), partCount()); + + /* Our callers should never cause us to overflow. */ + assert(carry == 0); +} + +/* Add the significand of the RHS. Returns the carry flag. */ +integerPart +APFloat::addSignificand(const APFloat &rhs) +{ + integerPart *parts; + + parts = significandParts(); + + assert(semantics == rhs.semantics); + assert(exponent == rhs.exponent); + + return APInt::tcAdd(parts, rhs.significandParts(), 0, partCount()); +} + +/* Subtract the significand of the RHS with a borrow flag. Returns + the borrow flag. */ +integerPart +APFloat::subtractSignificand(const APFloat &rhs, integerPart borrow) +{ + integerPart *parts; + + parts = significandParts(); + + assert(semantics == rhs.semantics); + assert(exponent == rhs.exponent); + + return APInt::tcSubtract(parts, rhs.significandParts(), borrow, + partCount()); +} + +/* Multiply the significand of the RHS. If ADDEND is non-NULL, add it + on to the full-precision result of the multiplication. Returns the + lost fraction. */ +lostFraction +APFloat::multiplySignificand(const APFloat &rhs, const APFloat *addend) +{ + unsigned int omsb; // One, not zero, based MSB. + unsigned int partsCount, newPartsCount, precision; + integerPart *lhsSignificand; + integerPart scratch[4]; + integerPart *fullSignificand; + lostFraction lost_fraction; + bool ignored; + + assert(semantics == rhs.semantics); + + precision = semantics->precision; + newPartsCount = partCountForBits(precision * 2); + + if(newPartsCount > 4) + fullSignificand = new integerPart[newPartsCount]; + else + fullSignificand = scratch; + + lhsSignificand = significandParts(); + partsCount = partCount(); + + APInt::tcFullMultiply(fullSignificand, lhsSignificand, + rhs.significandParts(), partsCount, partsCount); + + lost_fraction = lfExactlyZero; + omsb = APInt::tcMSB(fullSignificand, newPartsCount) + 1; + exponent += rhs.exponent; + + if(addend) { + Significand savedSignificand = significand; + const fltSemantics *savedSemantics = semantics; + fltSemantics extendedSemantics; + opStatus status; + unsigned int extendedPrecision; + + /* Normalize our MSB. */ + extendedPrecision = precision + precision - 1; + if(omsb != extendedPrecision) + { + APInt::tcShiftLeft(fullSignificand, newPartsCount, + extendedPrecision - omsb); + exponent -= extendedPrecision - omsb; + } + + /* Create new semantics. */ + extendedSemantics = *semantics; + extendedSemantics.precision = extendedPrecision; + + if(newPartsCount == 1) + significand.part = fullSignificand[0]; + else + significand.parts = fullSignificand; + semantics = &extendedSemantics; + + APFloat extendedAddend(*addend); + status = extendedAddend.convert(extendedSemantics, rmTowardZero, &ignored); + assert(status == opOK); + lost_fraction = addOrSubtractSignificand(extendedAddend, false); + + /* Restore our state. */ + if(newPartsCount == 1) + fullSignificand[0] = significand.part; + significand = savedSignificand; + semantics = savedSemantics; + + omsb = APInt::tcMSB(fullSignificand, newPartsCount) + 1; + } + + exponent -= (precision - 1); + + if(omsb > precision) { + unsigned int bits, significantParts; + lostFraction lf; + + bits = omsb - precision; + significantParts = partCountForBits(omsb); + lf = shiftRight(fullSignificand, significantParts, bits); + lost_fraction = combineLostFractions(lf, lost_fraction); + exponent += bits; + } + + APInt::tcAssign(lhsSignificand, fullSignificand, partsCount); + + if(newPartsCount > 4) + delete [] fullSignificand; + + return lost_fraction; +} + +/* Multiply the significands of LHS and RHS to DST. */ +lostFraction +APFloat::divideSignificand(const APFloat &rhs) +{ + unsigned int bit, i, partsCount; + const integerPart *rhsSignificand; + integerPart *lhsSignificand, *dividend, *divisor; + integerPart scratch[4]; + lostFraction lost_fraction; + + assert(semantics == rhs.semantics); + + lhsSignificand = significandParts(); + rhsSignificand = rhs.significandParts(); + partsCount = partCount(); + + if(partsCount > 2) + dividend = new integerPart[partsCount * 2]; + else + dividend = scratch; + + divisor = dividend + partsCount; + + /* Copy the dividend and divisor as they will be modified in-place. */ + for(i = 0; i < partsCount; i++) { + dividend[i] = lhsSignificand[i]; + divisor[i] = rhsSignificand[i]; + lhsSignificand[i] = 0; + } + + exponent -= rhs.exponent; + + unsigned int precision = semantics->precision; + + /* Normalize the divisor. */ + bit = precision - APInt::tcMSB(divisor, partsCount) - 1; + if(bit) { + exponent += bit; + APInt::tcShiftLeft(divisor, partsCount, bit); + } + + /* Normalize the dividend. */ + bit = precision - APInt::tcMSB(dividend, partsCount) - 1; + if(bit) { + exponent -= bit; + APInt::tcShiftLeft(dividend, partsCount, bit); + } + + /* Ensure the dividend >= divisor initially for the loop below. + Incidentally, this means that the division loop below is + guaranteed to set the integer bit to one. */ + if(APInt::tcCompare(dividend, divisor, partsCount) < 0) { + exponent--; + APInt::tcShiftLeft(dividend, partsCount, 1); + assert(APInt::tcCompare(dividend, divisor, partsCount) >= 0); + } + + /* Long division. */ + for(bit = precision; bit; bit -= 1) { + if(APInt::tcCompare(dividend, divisor, partsCount) >= 0) { + APInt::tcSubtract(dividend, divisor, 0, partsCount); + APInt::tcSetBit(lhsSignificand, bit - 1); + } + + APInt::tcShiftLeft(dividend, partsCount, 1); + } + + /* Figure out the lost fraction. */ + int cmp = APInt::tcCompare(dividend, divisor, partsCount); + + if(cmp > 0) + lost_fraction = lfMoreThanHalf; + else if(cmp == 0) + lost_fraction = lfExactlyHalf; + else if(APInt::tcIsZero(dividend, partsCount)) + lost_fraction = lfExactlyZero; + else + lost_fraction = lfLessThanHalf; + + if(partsCount > 2) + delete [] dividend; + + return lost_fraction; +} + +unsigned int +APFloat::significandMSB() const +{ + return APInt::tcMSB(significandParts(), partCount()); +} + +unsigned int +APFloat::significandLSB() const +{ + return APInt::tcLSB(significandParts(), partCount()); +} + +/* Note that a zero result is NOT normalized to fcZero. */ +lostFraction +APFloat::shiftSignificandRight(unsigned int bits) +{ + /* Our exponent should not overflow. */ + assert((exponent_t) (exponent + bits) >= exponent); + + exponent += bits; + + return shiftRight(significandParts(), partCount(), bits); +} + +/* Shift the significand left BITS bits, subtract BITS from its exponent. */ +void +APFloat::shiftSignificandLeft(unsigned int bits) +{ + assert(bits < semantics->precision); + + if(bits) { + unsigned int partsCount = partCount(); + + APInt::tcShiftLeft(significandParts(), partsCount, bits); + exponent -= bits; + + assert(!APInt::tcIsZero(significandParts(), partsCount)); + } +} + +APFloat::cmpResult +APFloat::compareAbsoluteValue(const APFloat &rhs) const +{ + int compare; + + assert(semantics == rhs.semantics); + assert(category == fcNormal); + assert(rhs.category == fcNormal); + + compare = exponent - rhs.exponent; + + /* If exponents are equal, do an unsigned bignum comparison of the + significands. */ + if(compare == 0) + compare = APInt::tcCompare(significandParts(), rhs.significandParts(), + partCount()); + + if(compare > 0) + return cmpGreaterThan; + else if(compare < 0) + return cmpLessThan; + else + return cmpEqual; +} + +/* Handle overflow. Sign is preserved. We either become infinity or + the largest finite number. */ +APFloat::opStatus +APFloat::handleOverflow(roundingMode rounding_mode) +{ + /* Infinity? */ + if(rounding_mode == rmNearestTiesToEven + || rounding_mode == rmNearestTiesToAway + || (rounding_mode == rmTowardPositive && !sign) + || (rounding_mode == rmTowardNegative && sign)) + { + category = fcInfinity; + return (opStatus) (opOverflow | opInexact); + } + + /* Otherwise we become the largest finite number. */ + category = fcNormal; + exponent = semantics->maxExponent; + APInt::tcSetLeastSignificantBits(significandParts(), partCount(), + semantics->precision); + + return opInexact; +} + +/* Returns TRUE if, when truncating the current number, with BIT the + new LSB, with the given lost fraction and rounding mode, the result + would need to be rounded away from zero (i.e., by increasing the + signficand). This routine must work for fcZero of both signs, and + fcNormal numbers. */ +bool +APFloat::roundAwayFromZero(roundingMode rounding_mode, + lostFraction lost_fraction, + unsigned int bit) const +{ + /* NaNs and infinities should not have lost fractions. */ + assert(category == fcNormal || category == fcZero); + + /* Current callers never pass this so we don't handle it. */ + assert(lost_fraction != lfExactlyZero); + + switch (rounding_mode) { + default: + llvm_unreachable(0); + + case rmNearestTiesToAway: + return lost_fraction == lfExactlyHalf || lost_fraction == lfMoreThanHalf; + + case rmNearestTiesToEven: + if(lost_fraction == lfMoreThanHalf) + return true; + + /* Our zeroes don't have a significand to test. */ + if(lost_fraction == lfExactlyHalf && category != fcZero) + return APInt::tcExtractBit(significandParts(), bit); + + return false; + + case rmTowardZero: + return false; + + case rmTowardPositive: + return sign == false; + + case rmTowardNegative: + return sign == true; + } +} + +APFloat::opStatus +APFloat::normalize(roundingMode rounding_mode, + lostFraction lost_fraction) +{ + unsigned int omsb; /* One, not zero, based MSB. */ + int exponentChange; + + if(category != fcNormal) + return opOK; + + /* Before rounding normalize the exponent of fcNormal numbers. */ + omsb = significandMSB() + 1; + + if(omsb) { + /* OMSB is numbered from 1. We want to place it in the integer + bit numbered PRECISON if possible, with a compensating change in + the exponent. */ + exponentChange = omsb - semantics->precision; + + /* If the resulting exponent is too high, overflow according to + the rounding mode. */ + if(exponent + exponentChange > semantics->maxExponent) + return handleOverflow(rounding_mode); + + /* Subnormal numbers have exponent minExponent, and their MSB + is forced based on that. */ + if(exponent + exponentChange < semantics->minExponent) + exponentChange = semantics->minExponent - exponent; + + /* Shifting left is easy as we don't lose precision. */ + if(exponentChange < 0) { + assert(lost_fraction == lfExactlyZero); + + shiftSignificandLeft(-exponentChange); + + return opOK; + } + + if(exponentChange > 0) { + lostFraction lf; + + /* Shift right and capture any new lost fraction. */ + lf = shiftSignificandRight(exponentChange); + + lost_fraction = combineLostFractions(lf, lost_fraction); + + /* Keep OMSB up-to-date. */ + if(omsb > (unsigned) exponentChange) + omsb -= exponentChange; + else + omsb = 0; + } + } + + /* Now round the number according to rounding_mode given the lost + fraction. */ + + /* As specified in IEEE 754, since we do not trap we do not report + underflow for exact results. */ + if(lost_fraction == lfExactlyZero) { + /* Canonicalize zeroes. */ + if(omsb == 0) + category = fcZero; + + return opOK; + } + + /* Increment the significand if we're rounding away from zero. */ + if(roundAwayFromZero(rounding_mode, lost_fraction, 0)) { + if(omsb == 0) + exponent = semantics->minExponent; + + incrementSignificand(); + omsb = significandMSB() + 1; + + /* Did the significand increment overflow? */ + if(omsb == (unsigned) semantics->precision + 1) { + /* Renormalize by incrementing the exponent and shifting our + significand right one. However if we already have the + maximum exponent we overflow to infinity. */ + if(exponent == semantics->maxExponent) { + category = fcInfinity; + + return (opStatus) (opOverflow | opInexact); + } + + shiftSignificandRight(1); + + return opInexact; + } + } + + /* The normal case - we were and are not denormal, and any + significand increment above didn't overflow. */ + if(omsb == semantics->precision) + return opInexact; + + /* We have a non-zero denormal. */ + assert(omsb < semantics->precision); + + /* Canonicalize zeroes. */ + if(omsb == 0) + category = fcZero; + + /* The fcZero case is a denormal that underflowed to zero. */ + return (opStatus) (opUnderflow | opInexact); +} + +APFloat::opStatus +APFloat::addOrSubtractSpecials(const APFloat &rhs, bool subtract) +{ + switch (convolve(category, rhs.category)) { + default: + llvm_unreachable(0); + + case convolve(fcNaN, fcZero): + case convolve(fcNaN, fcNormal): + case convolve(fcNaN, fcInfinity): + case convolve(fcNaN, fcNaN): + case convolve(fcNormal, fcZero): + case convolve(fcInfinity, fcNormal): + case convolve(fcInfinity, fcZero): + return opOK; + + case convolve(fcZero, fcNaN): + case convolve(fcNormal, fcNaN): + case convolve(fcInfinity, fcNaN): + category = fcNaN; + copySignificand(rhs); + return opOK; + + case convolve(fcNormal, fcInfinity): + case convolve(fcZero, fcInfinity): + category = fcInfinity; + sign = rhs.sign ^ subtract; + return opOK; + + case convolve(fcZero, fcNormal): + assign(rhs); + sign = rhs.sign ^ subtract; + return opOK; + + case convolve(fcZero, fcZero): + /* Sign depends on rounding mode; handled by caller. */ + return opOK; + + case convolve(fcInfinity, fcInfinity): + /* Differently signed infinities can only be validly + subtracted. */ + if(((sign ^ rhs.sign)!=0) != subtract) { + makeNaN(); + return opInvalidOp; + } + + return opOK; + + case convolve(fcNormal, fcNormal): + return opDivByZero; + } +} + +/* Add or subtract two normal numbers. */ +lostFraction +APFloat::addOrSubtractSignificand(const APFloat &rhs, bool subtract) +{ + integerPart carry; + lostFraction lost_fraction; + int bits; + + /* Determine if the operation on the absolute values is effectively + an addition or subtraction. */ + subtract ^= (sign ^ rhs.sign) ? true : false; + + /* Are we bigger exponent-wise than the RHS? */ + bits = exponent - rhs.exponent; + + /* Subtraction is more subtle than one might naively expect. */ + if(subtract) { + APFloat temp_rhs(rhs); + bool reverse; + + if (bits == 0) { + reverse = compareAbsoluteValue(temp_rhs) == cmpLessThan; + lost_fraction = lfExactlyZero; + } else if (bits > 0) { + lost_fraction = temp_rhs.shiftSignificandRight(bits - 1); + shiftSignificandLeft(1); + reverse = false; + } else { + lost_fraction = shiftSignificandRight(-bits - 1); + temp_rhs.shiftSignificandLeft(1); + reverse = true; + } + + if (reverse) { + carry = temp_rhs.subtractSignificand + (*this, lost_fraction != lfExactlyZero); + copySignificand(temp_rhs); + sign = !sign; + } else { + carry = subtractSignificand + (temp_rhs, lost_fraction != lfExactlyZero); + } + + /* Invert the lost fraction - it was on the RHS and + subtracted. */ + if(lost_fraction == lfLessThanHalf) + lost_fraction = lfMoreThanHalf; + else if(lost_fraction == lfMoreThanHalf) + lost_fraction = lfLessThanHalf; + + /* The code above is intended to ensure that no borrow is + necessary. */ + assert(!carry); + } else { + if(bits > 0) { + APFloat temp_rhs(rhs); + + lost_fraction = temp_rhs.shiftSignificandRight(bits); + carry = addSignificand(temp_rhs); + } else { + lost_fraction = shiftSignificandRight(-bits); + carry = addSignificand(rhs); + } + + /* We have a guard bit; generating a carry cannot happen. */ + assert(!carry); + } + + return lost_fraction; +} + +APFloat::opStatus +APFloat::multiplySpecials(const APFloat &rhs) +{ + switch (convolve(category, rhs.category)) { + default: + llvm_unreachable(0); + + case convolve(fcNaN, fcZero): + case convolve(fcNaN, fcNormal): + case convolve(fcNaN, fcInfinity): + case convolve(fcNaN, fcNaN): + return opOK; + + case convolve(fcZero, fcNaN): + case convolve(fcNormal, fcNaN): + case convolve(fcInfinity, fcNaN): + category = fcNaN; + copySignificand(rhs); + return opOK; + + case convolve(fcNormal, fcInfinity): + case convolve(fcInfinity, fcNormal): + case convolve(fcInfinity, fcInfinity): + category = fcInfinity; + return opOK; + + case convolve(fcZero, fcNormal): + case convolve(fcNormal, fcZero): + case convolve(fcZero, fcZero): + category = fcZero; + return opOK; + + case convolve(fcZero, fcInfinity): + case convolve(fcInfinity, fcZero): + makeNaN(); + return opInvalidOp; + + case convolve(fcNormal, fcNormal): + return opOK; + } +} + +APFloat::opStatus +APFloat::divideSpecials(const APFloat &rhs) +{ + switch (convolve(category, rhs.category)) { + default: + llvm_unreachable(0); + + case convolve(fcNaN, fcZero): + case convolve(fcNaN, fcNormal): + case convolve(fcNaN, fcInfinity): + case convolve(fcNaN, fcNaN): + case convolve(fcInfinity, fcZero): + case convolve(fcInfinity, fcNormal): + case convolve(fcZero, fcInfinity): + case convolve(fcZero, fcNormal): + return opOK; + + case convolve(fcZero, fcNaN): + case convolve(fcNormal, fcNaN): + case convolve(fcInfinity, fcNaN): + category = fcNaN; + copySignificand(rhs); + return opOK; + + case convolve(fcNormal, fcInfinity): + category = fcZero; + return opOK; + + case convolve(fcNormal, fcZero): + category = fcInfinity; + return opDivByZero; + + case convolve(fcInfinity, fcInfinity): + case convolve(fcZero, fcZero): + makeNaN(); + return opInvalidOp; + + case convolve(fcNormal, fcNormal): + return opOK; + } +} + +APFloat::opStatus +APFloat::modSpecials(const APFloat &rhs) +{ + switch (convolve(category, rhs.category)) { + default: + llvm_unreachable(0); + + case convolve(fcNaN, fcZero): + case convolve(fcNaN, fcNormal): + case convolve(fcNaN, fcInfinity): + case convolve(fcNaN, fcNaN): + case convolve(fcZero, fcInfinity): + case convolve(fcZero, fcNormal): + case convolve(fcNormal, fcInfinity): + return opOK; + + case convolve(fcZero, fcNaN): + case convolve(fcNormal, fcNaN): + case convolve(fcInfinity, fcNaN): + category = fcNaN; + copySignificand(rhs); + return opOK; + + case convolve(fcNormal, fcZero): + case convolve(fcInfinity, fcZero): + case convolve(fcInfinity, fcNormal): + case convolve(fcInfinity, fcInfinity): + case convolve(fcZero, fcZero): + makeNaN(); + return opInvalidOp; + + case convolve(fcNormal, fcNormal): + return opOK; + } +} + +/* Change sign. */ +void +APFloat::changeSign() +{ + /* Look mummy, this one's easy. */ + sign = !sign; +} + +void +APFloat::clearSign() +{ + /* So is this one. */ + sign = 0; +} + +void +APFloat::copySign(const APFloat &rhs) +{ + /* And this one. */ + sign = rhs.sign; +} + +/* Normalized addition or subtraction. */ +APFloat::opStatus +APFloat::addOrSubtract(const APFloat &rhs, roundingMode rounding_mode, + bool subtract) +{ + opStatus fs; + + assertArithmeticOK(*semantics); + + fs = addOrSubtractSpecials(rhs, subtract); + + /* This return code means it was not a simple case. */ + if(fs == opDivByZero) { + lostFraction lost_fraction; + + lost_fraction = addOrSubtractSignificand(rhs, subtract); + fs = normalize(rounding_mode, lost_fraction); + + /* Can only be zero if we lost no fraction. */ + assert(category != fcZero || lost_fraction == lfExactlyZero); + } + + /* If two numbers add (exactly) to zero, IEEE 754 decrees it is a + positive zero unless rounding to minus infinity, except that + adding two like-signed zeroes gives that zero. */ + if(category == fcZero) { + if(rhs.category != fcZero || (sign == rhs.sign) == subtract) + sign = (rounding_mode == rmTowardNegative); + } + + return fs; +} + +/* Normalized addition. */ +APFloat::opStatus +APFloat::add(const APFloat &rhs, roundingMode rounding_mode) +{ + return addOrSubtract(rhs, rounding_mode, false); +} + +/* Normalized subtraction. */ +APFloat::opStatus +APFloat::subtract(const APFloat &rhs, roundingMode rounding_mode) +{ + return addOrSubtract(rhs, rounding_mode, true); +} + +/* Normalized multiply. */ +APFloat::opStatus +APFloat::multiply(const APFloat &rhs, roundingMode rounding_mode) +{ + opStatus fs; + + assertArithmeticOK(*semantics); + sign ^= rhs.sign; + fs = multiplySpecials(rhs); + + if(category == fcNormal) { + lostFraction lost_fraction = multiplySignificand(rhs, 0); + fs = normalize(rounding_mode, lost_fraction); + if(lost_fraction != lfExactlyZero) + fs = (opStatus) (fs | opInexact); + } + + return fs; +} + +/* Normalized divide. */ +APFloat::opStatus +APFloat::divide(const APFloat &rhs, roundingMode rounding_mode) +{ + opStatus fs; + + assertArithmeticOK(*semantics); + sign ^= rhs.sign; + fs = divideSpecials(rhs); + + if(category == fcNormal) { + lostFraction lost_fraction = divideSignificand(rhs); + fs = normalize(rounding_mode, lost_fraction); + if(lost_fraction != lfExactlyZero) + fs = (opStatus) (fs | opInexact); + } + + return fs; +} + +/* Normalized remainder. This is not currently correct in all cases. */ +APFloat::opStatus +APFloat::remainder(const APFloat &rhs) +{ + opStatus fs; + APFloat V = *this; + unsigned int origSign = sign; + + assertArithmeticOK(*semantics); + fs = V.divide(rhs, rmNearestTiesToEven); + if (fs == opDivByZero) + return fs; + + int parts = partCount(); + integerPart *x = new integerPart[parts]; + bool ignored; + fs = V.convertToInteger(x, parts * integerPartWidth, true, + rmNearestTiesToEven, &ignored); + if (fs==opInvalidOp) + return fs; + + fs = V.convertFromZeroExtendedInteger(x, parts * integerPartWidth, true, + rmNearestTiesToEven); + assert(fs==opOK); // should always work + + fs = V.multiply(rhs, rmNearestTiesToEven); + assert(fs==opOK || fs==opInexact); // should not overflow or underflow + + fs = subtract(V, rmNearestTiesToEven); + assert(fs==opOK || fs==opInexact); // likewise + + if (isZero()) + sign = origSign; // IEEE754 requires this + delete[] x; + return fs; +} + +/* Normalized llvm frem (C fmod). + This is not currently correct in all cases. */ +APFloat::opStatus +APFloat::mod(const APFloat &rhs, roundingMode rounding_mode) +{ + opStatus fs; + assertArithmeticOK(*semantics); + fs = modSpecials(rhs); + + if (category == fcNormal && rhs.category == fcNormal) { + APFloat V = *this; + unsigned int origSign = sign; + + fs = V.divide(rhs, rmNearestTiesToEven); + if (fs == opDivByZero) + return fs; + + int parts = partCount(); + integerPart *x = new integerPart[parts]; + bool ignored; + fs = V.convertToInteger(x, parts * integerPartWidth, true, + rmTowardZero, &ignored); + if (fs==opInvalidOp) + return fs; + + fs = V.convertFromZeroExtendedInteger(x, parts * integerPartWidth, true, + rmNearestTiesToEven); + assert(fs==opOK); // should always work + + fs = V.multiply(rhs, rounding_mode); + assert(fs==opOK || fs==opInexact); // should not overflow or underflow + + fs = subtract(V, rounding_mode); + assert(fs==opOK || fs==opInexact); // likewise + + if (isZero()) + sign = origSign; // IEEE754 requires this + delete[] x; + } + return fs; +} + +/* Normalized fused-multiply-add. */ +APFloat::opStatus +APFloat::fusedMultiplyAdd(const APFloat &multiplicand, + const APFloat &addend, + roundingMode rounding_mode) +{ + opStatus fs; + + assertArithmeticOK(*semantics); + + /* Post-multiplication sign, before addition. */ + sign ^= multiplicand.sign; + + /* If and only if all arguments are normal do we need to do an + extended-precision calculation. */ + if(category == fcNormal + && multiplicand.category == fcNormal + && addend.category == fcNormal) { + lostFraction lost_fraction; + + lost_fraction = multiplySignificand(multiplicand, &addend); + fs = normalize(rounding_mode, lost_fraction); + if(lost_fraction != lfExactlyZero) + fs = (opStatus) (fs | opInexact); + + /* If two numbers add (exactly) to zero, IEEE 754 decrees it is a + positive zero unless rounding to minus infinity, except that + adding two like-signed zeroes gives that zero. */ + if(category == fcZero && sign != addend.sign) + sign = (rounding_mode == rmTowardNegative); + } else { + fs = multiplySpecials(multiplicand); + + /* FS can only be opOK or opInvalidOp. There is no more work + to do in the latter case. The IEEE-754R standard says it is + implementation-defined in this case whether, if ADDEND is a + quiet NaN, we raise invalid op; this implementation does so. + + If we need to do the addition we can do so with normal + precision. */ + if(fs == opOK) + fs = addOrSubtract(addend, rounding_mode, false); + } + + return fs; +} + +/* Comparison requires normalized numbers. */ +APFloat::cmpResult +APFloat::compare(const APFloat &rhs) const +{ + cmpResult result; + + assertArithmeticOK(*semantics); + assert(semantics == rhs.semantics); + + switch (convolve(category, rhs.category)) { + default: + llvm_unreachable(0); + + case convolve(fcNaN, fcZero): + case convolve(fcNaN, fcNormal): + case convolve(fcNaN, fcInfinity): + case convolve(fcNaN, fcNaN): + case convolve(fcZero, fcNaN): + case convolve(fcNormal, fcNaN): + case convolve(fcInfinity, fcNaN): + return cmpUnordered; + + case convolve(fcInfinity, fcNormal): + case convolve(fcInfinity, fcZero): + case convolve(fcNormal, fcZero): + if(sign) + return cmpLessThan; + else + return cmpGreaterThan; + + case convolve(fcNormal, fcInfinity): + case convolve(fcZero, fcInfinity): + case convolve(fcZero, fcNormal): + if(rhs.sign) + return cmpGreaterThan; + else + return cmpLessThan; + + case convolve(fcInfinity, fcInfinity): + if(sign == rhs.sign) + return cmpEqual; + else if(sign) + return cmpLessThan; + else + return cmpGreaterThan; + + case convolve(fcZero, fcZero): + return cmpEqual; + + case convolve(fcNormal, fcNormal): + break; + } + + /* Two normal numbers. Do they have the same sign? */ + if(sign != rhs.sign) { + if(sign) + result = cmpLessThan; + else + result = cmpGreaterThan; + } else { + /* Compare absolute values; invert result if negative. */ + result = compareAbsoluteValue(rhs); + + if(sign) { + if(result == cmpLessThan) + result = cmpGreaterThan; + else if(result == cmpGreaterThan) + result = cmpLessThan; + } + } + + return result; +} + +/// APFloat::convert - convert a value of one floating point type to another. +/// The return value corresponds to the IEEE754 exceptions. *losesInfo +/// records whether the transformation lost information, i.e. whether +/// converting the result back to the original type will produce the +/// original value (this is almost the same as return value==fsOK, but there +/// are edge cases where this is not so). + +APFloat::opStatus +APFloat::convert(const fltSemantics &toSemantics, + roundingMode rounding_mode, bool *losesInfo) +{ + lostFraction lostFraction; + unsigned int newPartCount, oldPartCount; + opStatus fs; + + assertArithmeticOK(*semantics); + assertArithmeticOK(toSemantics); + lostFraction = lfExactlyZero; + newPartCount = partCountForBits(toSemantics.precision + 1); + oldPartCount = partCount(); + + /* Handle storage complications. If our new form is wider, + re-allocate our bit pattern into wider storage. If it is + narrower, we ignore the excess parts, but if narrowing to a + single part we need to free the old storage. + Be careful not to reference significandParts for zeroes + and infinities, since it aborts. */ + if (newPartCount > oldPartCount) { + integerPart *newParts; + newParts = new integerPart[newPartCount]; + APInt::tcSet(newParts, 0, newPartCount); + if (category==fcNormal || category==fcNaN) + APInt::tcAssign(newParts, significandParts(), oldPartCount); + freeSignificand(); + significand.parts = newParts; + } else if (newPartCount < oldPartCount) { + /* Capture any lost fraction through truncation of parts so we get + correct rounding whilst normalizing. */ + if (category==fcNormal) + lostFraction = lostFractionThroughTruncation + (significandParts(), oldPartCount, toSemantics.precision); + if (newPartCount == 1) { + integerPart newPart = 0; + if (category==fcNormal || category==fcNaN) + newPart = significandParts()[0]; + freeSignificand(); + significand.part = newPart; + } + } + + if(category == fcNormal) { + /* Re-interpret our bit-pattern. */ + exponent += toSemantics.precision - semantics->precision; + semantics = &toSemantics; + fs = normalize(rounding_mode, lostFraction); + *losesInfo = (fs != opOK); + } else if (category == fcNaN) { + int shift = toSemantics.precision - semantics->precision; + // Do this now so significandParts gets the right answer + const fltSemantics *oldSemantics = semantics; + semantics = &toSemantics; + *losesInfo = false; + // No normalization here, just truncate + if (shift>0) + APInt::tcShiftLeft(significandParts(), newPartCount, shift); + else if (shift < 0) { + unsigned ushift = -shift; + // Figure out if we are losing information. This happens + // if are shifting out something other than 0s, or if the x87 long + // double input did not have its integer bit set (pseudo-NaN), or if the + // x87 long double input did not have its QNan bit set (because the x87 + // hardware sets this bit when converting a lower-precision NaN to + // x87 long double). + if (APInt::tcLSB(significandParts(), newPartCount) < ushift) + *losesInfo = true; + if (oldSemantics == &APFloat::x87DoubleExtended && + (!(*significandParts() & 0x8000000000000000ULL) || + !(*significandParts() & 0x4000000000000000ULL))) + *losesInfo = true; + APInt::tcShiftRight(significandParts(), newPartCount, ushift); + } + // gcc forces the Quiet bit on, which means (float)(double)(float_sNan) + // does not give you back the same bits. This is dubious, and we + // don't currently do it. You're really supposed to get + // an invalid operation signal at runtime, but nobody does that. + fs = opOK; + } else { + semantics = &toSemantics; + fs = opOK; + *losesInfo = false; + } + + return fs; +} + +/* Convert a floating point number to an integer according to the + rounding mode. If the rounded integer value is out of range this + returns an invalid operation exception and the contents of the + destination parts are unspecified. If the rounded value is in + range but the floating point number is not the exact integer, the C + standard doesn't require an inexact exception to be raised. IEEE + 854 does require it so we do that. + + Note that for conversions to integer type the C standard requires + round-to-zero to always be used. */ +APFloat::opStatus +APFloat::convertToSignExtendedInteger(integerPart *parts, unsigned int width, + bool isSigned, + roundingMode rounding_mode, + bool *isExact) const +{ + lostFraction lost_fraction; + const integerPart *src; + unsigned int dstPartsCount, truncatedBits; + + assertArithmeticOK(*semantics); + + *isExact = false; + + /* Handle the three special cases first. */ + if(category == fcInfinity || category == fcNaN) + return opInvalidOp; + + dstPartsCount = partCountForBits(width); + + if(category == fcZero) { + APInt::tcSet(parts, 0, dstPartsCount); + // Negative zero can't be represented as an int. + *isExact = !sign; + return opOK; + } + + src = significandParts(); + + /* Step 1: place our absolute value, with any fraction truncated, in + the destination. */ + if (exponent < 0) { + /* Our absolute value is less than one; truncate everything. */ + APInt::tcSet(parts, 0, dstPartsCount); + /* For exponent -1 the integer bit represents .5, look at that. + For smaller exponents leftmost truncated bit is 0. */ + truncatedBits = semantics->precision -1U - exponent; + } else { + /* We want the most significant (exponent + 1) bits; the rest are + truncated. */ + unsigned int bits = exponent + 1U; + + /* Hopelessly large in magnitude? */ + if (bits > width) + return opInvalidOp; + + if (bits < semantics->precision) { + /* We truncate (semantics->precision - bits) bits. */ + truncatedBits = semantics->precision - bits; + APInt::tcExtract(parts, dstPartsCount, src, bits, truncatedBits); + } else { + /* We want at least as many bits as are available. */ + APInt::tcExtract(parts, dstPartsCount, src, semantics->precision, 0); + APInt::tcShiftLeft(parts, dstPartsCount, bits - semantics->precision); + truncatedBits = 0; + } + } + + /* Step 2: work out any lost fraction, and increment the absolute + value if we would round away from zero. */ + if (truncatedBits) { + lost_fraction = lostFractionThroughTruncation(src, partCount(), + truncatedBits); + if (lost_fraction != lfExactlyZero + && roundAwayFromZero(rounding_mode, lost_fraction, truncatedBits)) { + if (APInt::tcIncrement(parts, dstPartsCount)) + return opInvalidOp; /* Overflow. */ + } + } else { + lost_fraction = lfExactlyZero; + } + + /* Step 3: check if we fit in the destination. */ + unsigned int omsb = APInt::tcMSB(parts, dstPartsCount) + 1; + + if (sign) { + if (!isSigned) { + /* Negative numbers cannot be represented as unsigned. */ + if (omsb != 0) + return opInvalidOp; + } else { + /* It takes omsb bits to represent the unsigned integer value. + We lose a bit for the sign, but care is needed as the + maximally negative integer is a special case. */ + if (omsb == width && APInt::tcLSB(parts, dstPartsCount) + 1 != omsb) + return opInvalidOp; + + /* This case can happen because of rounding. */ + if (omsb > width) + return opInvalidOp; + } + + APInt::tcNegate (parts, dstPartsCount); + } else { + if (omsb >= width + !isSigned) + return opInvalidOp; + } + + if (lost_fraction == lfExactlyZero) { + *isExact = true; + return opOK; + } else + return opInexact; +} + +/* Same as convertToSignExtendedInteger, except we provide + deterministic values in case of an invalid operation exception, + namely zero for NaNs and the minimal or maximal value respectively + for underflow or overflow. + The *isExact output tells whether the result is exact, in the sense + that converting it back to the original floating point type produces + the original value. This is almost equivalent to result==opOK, + except for negative zeroes. +*/ +APFloat::opStatus +APFloat::convertToInteger(integerPart *parts, unsigned int width, + bool isSigned, + roundingMode rounding_mode, bool *isExact) const +{ + opStatus fs; + + fs = convertToSignExtendedInteger(parts, width, isSigned, rounding_mode, + isExact); + + if (fs == opInvalidOp) { + unsigned int bits, dstPartsCount; + + dstPartsCount = partCountForBits(width); + + if (category == fcNaN) + bits = 0; + else if (sign) + bits = isSigned; + else + bits = width - isSigned; + + APInt::tcSetLeastSignificantBits(parts, dstPartsCount, bits); + if (sign && isSigned) + APInt::tcShiftLeft(parts, dstPartsCount, width - 1); + } + + return fs; +} + +/* Convert an unsigned integer SRC to a floating point number, + rounding according to ROUNDING_MODE. The sign of the floating + point number is not modified. */ +APFloat::opStatus +APFloat::convertFromUnsignedParts(const integerPart *src, + unsigned int srcCount, + roundingMode rounding_mode) +{ + unsigned int omsb, precision, dstCount; + integerPart *dst; + lostFraction lost_fraction; + + assertArithmeticOK(*semantics); + category = fcNormal; + omsb = APInt::tcMSB(src, srcCount) + 1; + dst = significandParts(); + dstCount = partCount(); + precision = semantics->precision; + + /* We want the most significant PRECISON bits of SRC. There may not + be that many; extract what we can. */ + if (precision <= omsb) { + exponent = omsb - 1; + lost_fraction = lostFractionThroughTruncation(src, srcCount, + omsb - precision); + APInt::tcExtract(dst, dstCount, src, precision, omsb - precision); + } else { + exponent = precision - 1; + lost_fraction = lfExactlyZero; + APInt::tcExtract(dst, dstCount, src, omsb, 0); + } + + return normalize(rounding_mode, lost_fraction); +} + +APFloat::opStatus +APFloat::convertFromAPInt(const APInt &Val, + bool isSigned, + roundingMode rounding_mode) +{ + unsigned int partCount = Val.getNumWords(); + APInt api = Val; + + sign = false; + if (isSigned && api.isNegative()) { + sign = true; + api = -api; + } + + return convertFromUnsignedParts(api.getRawData(), partCount, rounding_mode); +} + +/* Convert a two's complement integer SRC to a floating point number, + rounding according to ROUNDING_MODE. ISSIGNED is true if the + integer is signed, in which case it must be sign-extended. */ +APFloat::opStatus +APFloat::convertFromSignExtendedInteger(const integerPart *src, + unsigned int srcCount, + bool isSigned, + roundingMode rounding_mode) +{ + opStatus status; + + assertArithmeticOK(*semantics); + if (isSigned + && APInt::tcExtractBit(src, srcCount * integerPartWidth - 1)) { + integerPart *copy; + + /* If we're signed and negative negate a copy. */ + sign = true; + copy = new integerPart[srcCount]; + APInt::tcAssign(copy, src, srcCount); + APInt::tcNegate(copy, srcCount); + status = convertFromUnsignedParts(copy, srcCount, rounding_mode); + delete [] copy; + } else { + sign = false; + status = convertFromUnsignedParts(src, srcCount, rounding_mode); + } + + return status; +} + +/* FIXME: should this just take a const APInt reference? */ +APFloat::opStatus +APFloat::convertFromZeroExtendedInteger(const integerPart *parts, + unsigned int width, bool isSigned, + roundingMode rounding_mode) +{ + unsigned int partCount = partCountForBits(width); + APInt api = APInt(width, partCount, parts); + + sign = false; + if(isSigned && APInt::tcExtractBit(parts, width - 1)) { + sign = true; + api = -api; + } + + return convertFromUnsignedParts(api.getRawData(), partCount, rounding_mode); +} + +APFloat::opStatus +APFloat::convertFromHexadecimalString(const StringRef &s, + roundingMode rounding_mode) +{ + lostFraction lost_fraction = lfExactlyZero; + integerPart *significand; + unsigned int bitPos, partsCount; + StringRef::iterator dot, firstSignificantDigit; + + zeroSignificand(); + exponent = 0; + category = fcNormal; + + significand = significandParts(); + partsCount = partCount(); + bitPos = partsCount * integerPartWidth; + + /* Skip leading zeroes and any (hexa)decimal point. */ + StringRef::iterator begin = s.begin(); + StringRef::iterator end = s.end(); + StringRef::iterator p = skipLeadingZeroesAndAnyDot(begin, end, &dot); + firstSignificantDigit = p; + + for(; p != end;) { + integerPart hex_value; + + if(*p == '.') { + assert(dot == end && "String contains multiple dots"); + dot = p++; + if (p == end) { + break; + } + } + + hex_value = hexDigitValue(*p); + if(hex_value == -1U) { + break; + } + + p++; + + if (p == end) { + break; + } else { + /* Store the number whilst 4-bit nibbles remain. */ + if(bitPos) { + bitPos -= 4; + hex_value <<= bitPos % integerPartWidth; + significand[bitPos / integerPartWidth] |= hex_value; + } else { + lost_fraction = trailingHexadecimalFraction(p, end, hex_value); + while(p != end && hexDigitValue(*p) != -1U) + p++; + break; + } + } + } + + /* Hex floats require an exponent but not a hexadecimal point. */ + assert(p != end && "Hex strings require an exponent"); + assert((*p == 'p' || *p == 'P') && "Invalid character in significand"); + assert(p != begin && "Significand has no digits"); + assert((dot == end || p - begin != 1) && "Significand has no digits"); + + /* Ignore the exponent if we are zero. */ + if(p != firstSignificantDigit) { + int expAdjustment; + + /* Implicit hexadecimal point? */ + if (dot == end) + dot = p; + + /* Calculate the exponent adjustment implicit in the number of + significant digits. */ + expAdjustment = static_cast(dot - firstSignificantDigit); + if(expAdjustment < 0) + expAdjustment++; + expAdjustment = expAdjustment * 4 - 1; + + /* Adjust for writing the significand starting at the most + significant nibble. */ + expAdjustment += semantics->precision; + expAdjustment -= partsCount * integerPartWidth; + + /* Adjust for the given exponent. */ + exponent = totalExponent(p + 1, end, expAdjustment); + } + + return normalize(rounding_mode, lost_fraction); +} + +APFloat::opStatus +APFloat::roundSignificandWithExponent(const integerPart *decSigParts, + unsigned sigPartCount, int exp, + roundingMode rounding_mode) +{ + unsigned int parts, pow5PartCount; + fltSemantics calcSemantics = { 32767, -32767, 0, true }; + integerPart pow5Parts[maxPowerOfFiveParts]; + bool isNearest; + + isNearest = (rounding_mode == rmNearestTiesToEven + || rounding_mode == rmNearestTiesToAway); + + parts = partCountForBits(semantics->precision + 11); + + /* Calculate pow(5, abs(exp)). */ + pow5PartCount = powerOf5(pow5Parts, exp >= 0 ? exp: -exp); + + for (;; parts *= 2) { + opStatus sigStatus, powStatus; + unsigned int excessPrecision, truncatedBits; + + calcSemantics.precision = parts * integerPartWidth - 1; + excessPrecision = calcSemantics.precision - semantics->precision; + truncatedBits = excessPrecision; + + APFloat decSig(calcSemantics, fcZero, sign); + APFloat pow5(calcSemantics, fcZero, false); + + sigStatus = decSig.convertFromUnsignedParts(decSigParts, sigPartCount, + rmNearestTiesToEven); + powStatus = pow5.convertFromUnsignedParts(pow5Parts, pow5PartCount, + rmNearestTiesToEven); + /* Add exp, as 10^n = 5^n * 2^n. */ + decSig.exponent += exp; + + lostFraction calcLostFraction; + integerPart HUerr, HUdistance; + unsigned int powHUerr; + + if (exp >= 0) { + /* multiplySignificand leaves the precision-th bit set to 1. */ + calcLostFraction = decSig.multiplySignificand(pow5, NULL); + powHUerr = powStatus != opOK; + } else { + calcLostFraction = decSig.divideSignificand(pow5); + /* Denormal numbers have less precision. */ + if (decSig.exponent < semantics->minExponent) { + excessPrecision += (semantics->minExponent - decSig.exponent); + truncatedBits = excessPrecision; + if (excessPrecision > calcSemantics.precision) + excessPrecision = calcSemantics.precision; + } + /* Extra half-ulp lost in reciprocal of exponent. */ + powHUerr = (powStatus == opOK && calcLostFraction == lfExactlyZero) ? 0:2; + } + + /* Both multiplySignificand and divideSignificand return the + result with the integer bit set. */ + assert(APInt::tcExtractBit + (decSig.significandParts(), calcSemantics.precision - 1) == 1); + + HUerr = HUerrBound(calcLostFraction != lfExactlyZero, sigStatus != opOK, + powHUerr); + HUdistance = 2 * ulpsFromBoundary(decSig.significandParts(), + excessPrecision, isNearest); + + /* Are we guaranteed to round correctly if we truncate? */ + if (HUdistance >= HUerr) { + APInt::tcExtract(significandParts(), partCount(), decSig.significandParts(), + calcSemantics.precision - excessPrecision, + excessPrecision); + /* Take the exponent of decSig. If we tcExtract-ed less bits + above we must adjust our exponent to compensate for the + implicit right shift. */ + exponent = (decSig.exponent + semantics->precision + - (calcSemantics.precision - excessPrecision)); + calcLostFraction = lostFractionThroughTruncation(decSig.significandParts(), + decSig.partCount(), + truncatedBits); + return normalize(rounding_mode, calcLostFraction); + } + } +} + +APFloat::opStatus +APFloat::convertFromDecimalString(const StringRef &str, roundingMode rounding_mode) +{ + decimalInfo D; + opStatus fs; + + /* Scan the text. */ + StringRef::iterator p = str.begin(); + interpretDecimal(p, str.end(), &D); + + /* Handle the quick cases. First the case of no significant digits, + i.e. zero, and then exponents that are obviously too large or too + small. Writing L for log 10 / log 2, a number d.ddddd*10^exp + definitely overflows if + + (exp - 1) * L >= maxExponent + + and definitely underflows to zero where + + (exp + 1) * L <= minExponent - precision + + With integer arithmetic the tightest bounds for L are + + 93/28 < L < 196/59 [ numerator <= 256 ] + 42039/12655 < L < 28738/8651 [ numerator <= 65536 ] + */ + + if (decDigitValue(*D.firstSigDigit) >= 10U) { + category = fcZero; + fs = opOK; + } else if ((D.normalizedExponent + 1) * 28738 + <= 8651 * (semantics->minExponent - (int) semantics->precision)) { + /* Underflow to zero and round. */ + zeroSignificand(); + fs = normalize(rounding_mode, lfLessThanHalf); + } else if ((D.normalizedExponent - 1) * 42039 + >= 12655 * semantics->maxExponent) { + /* Overflow and round. */ + fs = handleOverflow(rounding_mode); + } else { + integerPart *decSignificand; + unsigned int partCount; + + /* A tight upper bound on number of bits required to hold an + N-digit decimal integer is N * 196 / 59. Allocate enough space + to hold the full significand, and an extra part required by + tcMultiplyPart. */ + partCount = static_cast(D.lastSigDigit - D.firstSigDigit) + 1; + partCount = partCountForBits(1 + 196 * partCount / 59); + decSignificand = new integerPart[partCount + 1]; + partCount = 0; + + /* Convert to binary efficiently - we do almost all multiplication + in an integerPart. When this would overflow do we do a single + bignum multiplication, and then revert again to multiplication + in an integerPart. */ + do { + integerPart decValue, val, multiplier; + + val = 0; + multiplier = 1; + + do { + if (*p == '.') { + p++; + if (p == str.end()) { + break; + } + } + decValue = decDigitValue(*p++); + assert(decValue < 10U && "Invalid character in significand"); + multiplier *= 10; + val = val * 10 + decValue; + /* The maximum number that can be multiplied by ten with any + digit added without overflowing an integerPart. */ + } while (p <= D.lastSigDigit && multiplier <= (~ (integerPart) 0 - 9) / 10); + + /* Multiply out the current part. */ + APInt::tcMultiplyPart(decSignificand, decSignificand, multiplier, val, + partCount, partCount + 1, false); + + /* If we used another part (likely but not guaranteed), increase + the count. */ + if (decSignificand[partCount]) + partCount++; + } while (p <= D.lastSigDigit); + + category = fcNormal; + fs = roundSignificandWithExponent(decSignificand, partCount, + D.exponent, rounding_mode); + + delete [] decSignificand; + } + + return fs; +} + +APFloat::opStatus +APFloat::convertFromString(const StringRef &str, roundingMode rounding_mode) +{ + assertArithmeticOK(*semantics); + assert(!str.empty() && "Invalid string length"); + + /* Handle a leading minus sign. */ + StringRef::iterator p = str.begin(); + size_t slen = str.size(); + sign = *p == '-' ? 1 : 0; + if(*p == '-' || *p == '+') { + p++; + slen--; + assert(slen && "String has no digits"); + } + + if(slen >= 2 && p[0] == '0' && (p[1] == 'x' || p[1] == 'X')) { + assert(slen - 2 && "Invalid string"); + return convertFromHexadecimalString(StringRef(p + 2, slen - 2), + rounding_mode); + } + + return convertFromDecimalString(StringRef(p, slen), rounding_mode); +} + +/* Write out a hexadecimal representation of the floating point value + to DST, which must be of sufficient size, in the C99 form + [-]0xh.hhhhp[+-]d. Return the number of characters written, + excluding the terminating NUL. + + If UPPERCASE, the output is in upper case, otherwise in lower case. + + HEXDIGITS digits appear altogether, rounding the value if + necessary. If HEXDIGITS is 0, the minimal precision to display the + number precisely is used instead. If nothing would appear after + the decimal point it is suppressed. + + The decimal exponent is always printed and has at least one digit. + Zero values display an exponent of zero. Infinities and NaNs + appear as "infinity" or "nan" respectively. + + The above rules are as specified by C99. There is ambiguity about + what the leading hexadecimal digit should be. This implementation + uses whatever is necessary so that the exponent is displayed as + stored. This implies the exponent will fall within the IEEE format + range, and the leading hexadecimal digit will be 0 (for denormals), + 1 (normal numbers) or 2 (normal numbers rounded-away-from-zero with + any other digits zero). +*/ +unsigned int +APFloat::convertToHexString(char *dst, unsigned int hexDigits, + bool upperCase, roundingMode rounding_mode) const +{ + char *p; + + assertArithmeticOK(*semantics); + + p = dst; + if (sign) + *dst++ = '-'; + + switch (category) { + case fcInfinity: + memcpy (dst, upperCase ? infinityU: infinityL, sizeof infinityU - 1); + dst += sizeof infinityL - 1; + break; + + case fcNaN: + memcpy (dst, upperCase ? NaNU: NaNL, sizeof NaNU - 1); + dst += sizeof NaNU - 1; + break; + + case fcZero: + *dst++ = '0'; + *dst++ = upperCase ? 'X': 'x'; + *dst++ = '0'; + if (hexDigits > 1) { + *dst++ = '.'; + memset (dst, '0', hexDigits - 1); + dst += hexDigits - 1; + } + *dst++ = upperCase ? 'P': 'p'; + *dst++ = '0'; + break; + + case fcNormal: + dst = convertNormalToHexString (dst, hexDigits, upperCase, rounding_mode); + break; + } + + *dst = 0; + + return static_cast(dst - p); +} + +/* Does the hard work of outputting the correctly rounded hexadecimal + form of a normal floating point number with the specified number of + hexadecimal digits. If HEXDIGITS is zero the minimum number of + digits necessary to print the value precisely is output. */ +char * +APFloat::convertNormalToHexString(char *dst, unsigned int hexDigits, + bool upperCase, + roundingMode rounding_mode) const +{ + unsigned int count, valueBits, shift, partsCount, outputDigits; + const char *hexDigitChars; + const integerPart *significand; + char *p; + bool roundUp; + + *dst++ = '0'; + *dst++ = upperCase ? 'X': 'x'; + + roundUp = false; + hexDigitChars = upperCase ? hexDigitsUpper: hexDigitsLower; + + significand = significandParts(); + partsCount = partCount(); + + /* +3 because the first digit only uses the single integer bit, so + we have 3 virtual zero most-significant-bits. */ + valueBits = semantics->precision + 3; + shift = integerPartWidth - valueBits % integerPartWidth; + + /* The natural number of digits required ignoring trailing + insignificant zeroes. */ + outputDigits = (valueBits - significandLSB () + 3) / 4; + + /* hexDigits of zero means use the required number for the + precision. Otherwise, see if we are truncating. If we are, + find out if we need to round away from zero. */ + if (hexDigits) { + if (hexDigits < outputDigits) { + /* We are dropping non-zero bits, so need to check how to round. + "bits" is the number of dropped bits. */ + unsigned int bits; + lostFraction fraction; + + bits = valueBits - hexDigits * 4; + fraction = lostFractionThroughTruncation (significand, partsCount, bits); + roundUp = roundAwayFromZero(rounding_mode, fraction, bits); + } + outputDigits = hexDigits; + } + + /* Write the digits consecutively, and start writing in the location + of the hexadecimal point. We move the most significant digit + left and add the hexadecimal point later. */ + p = ++dst; + + count = (valueBits + integerPartWidth - 1) / integerPartWidth; + + while (outputDigits && count) { + integerPart part; + + /* Put the most significant integerPartWidth bits in "part". */ + if (--count == partsCount) + part = 0; /* An imaginary higher zero part. */ + else + part = significand[count] << shift; + + if (count && shift) + part |= significand[count - 1] >> (integerPartWidth - shift); + + /* Convert as much of "part" to hexdigits as we can. */ + unsigned int curDigits = integerPartWidth / 4; + + if (curDigits > outputDigits) + curDigits = outputDigits; + dst += partAsHex (dst, part, curDigits, hexDigitChars); + outputDigits -= curDigits; + } + + if (roundUp) { + char *q = dst; + + /* Note that hexDigitChars has a trailing '0'. */ + do { + q--; + *q = hexDigitChars[hexDigitValue (*q) + 1]; + } while (*q == '0'); + assert(q >= p); + } else { + /* Add trailing zeroes. */ + memset (dst, '0', outputDigits); + dst += outputDigits; + } + + /* Move the most significant digit to before the point, and if there + is something after the decimal point add it. This must come + after rounding above. */ + p[-1] = p[0]; + if (dst -1 == p) + dst--; + else + p[0] = '.'; + + /* Finally output the exponent. */ + *dst++ = upperCase ? 'P': 'p'; + + return writeSignedDecimal (dst, exponent); +} + +// For good performance it is desirable for different APFloats +// to produce different integers. +uint32_t +APFloat::getHashValue() const +{ + if (category==fcZero) return sign<<8 | semantics->precision ; + else if (category==fcInfinity) return sign<<9 | semantics->precision; + else if (category==fcNaN) return 1<<10 | semantics->precision; + else { + uint32_t hash = sign<<11 | semantics->precision | exponent<<12; + const integerPart* p = significandParts(); + for (int i=partCount(); i>0; i--, p++) + hash ^= ((uint32_t)*p) ^ (uint32_t)((*p)>>32); + return hash; + } +} + +// Conversion from APFloat to/from host float/double. It may eventually be +// possible to eliminate these and have everybody deal with APFloats, but that +// will take a while. This approach will not easily extend to long double. +// Current implementation requires integerPartWidth==64, which is correct at +// the moment but could be made more general. + +// Denormals have exponent minExponent in APFloat, but minExponent-1 in +// the actual IEEE respresentations. We compensate for that here. + +APInt +APFloat::convertF80LongDoubleAPFloatToAPInt() const +{ + assert(semantics == (const llvm::fltSemantics*)&x87DoubleExtended); + assert(partCount()==2); + + uint64_t myexponent, mysignificand; + + if (category==fcNormal) { + myexponent = exponent+16383; //bias + mysignificand = significandParts()[0]; + if (myexponent==1 && !(mysignificand & 0x8000000000000000ULL)) + myexponent = 0; // denormal + } else if (category==fcZero) { + myexponent = 0; + mysignificand = 0; + } else if (category==fcInfinity) { + myexponent = 0x7fff; + mysignificand = 0x8000000000000000ULL; + } else { + assert(category == fcNaN && "Unknown category"); + myexponent = 0x7fff; + mysignificand = significandParts()[0]; + } + + uint64_t words[2]; + words[0] = mysignificand; + words[1] = ((uint64_t)(sign & 1) << 15) | + (myexponent & 0x7fffLL); + return APInt(80, 2, words); +} + +APInt +APFloat::convertPPCDoubleDoubleAPFloatToAPInt() const +{ + assert(semantics == (const llvm::fltSemantics*)&PPCDoubleDouble); + assert(partCount()==2); + + uint64_t myexponent, mysignificand, myexponent2, mysignificand2; + + if (category==fcNormal) { + myexponent = exponent + 1023; //bias + myexponent2 = exponent2 + 1023; + mysignificand = significandParts()[0]; + mysignificand2 = significandParts()[1]; + if (myexponent==1 && !(mysignificand & 0x10000000000000LL)) + myexponent = 0; // denormal + if (myexponent2==1 && !(mysignificand2 & 0x10000000000000LL)) + myexponent2 = 0; // denormal + } else if (category==fcZero) { + myexponent = 0; + mysignificand = 0; + myexponent2 = 0; + mysignificand2 = 0; + } else if (category==fcInfinity) { + myexponent = 0x7ff; + myexponent2 = 0; + mysignificand = 0; + mysignificand2 = 0; + } else { + assert(category == fcNaN && "Unknown category"); + myexponent = 0x7ff; + mysignificand = significandParts()[0]; + myexponent2 = exponent2; + mysignificand2 = significandParts()[1]; + } + + uint64_t words[2]; + words[0] = ((uint64_t)(sign & 1) << 63) | + ((myexponent & 0x7ff) << 52) | + (mysignificand & 0xfffffffffffffLL); + words[1] = ((uint64_t)(sign2 & 1) << 63) | + ((myexponent2 & 0x7ff) << 52) | + (mysignificand2 & 0xfffffffffffffLL); + return APInt(128, 2, words); +} + +APInt +APFloat::convertQuadrupleAPFloatToAPInt() const +{ + assert(semantics == (const llvm::fltSemantics*)&IEEEquad); + assert(partCount()==2); + + uint64_t myexponent, mysignificand, mysignificand2; + + if (category==fcNormal) { + myexponent = exponent+16383; //bias + mysignificand = significandParts()[0]; + mysignificand2 = significandParts()[1]; + if (myexponent==1 && !(mysignificand2 & 0x1000000000000LL)) + myexponent = 0; // denormal + } else if (category==fcZero) { + myexponent = 0; + mysignificand = mysignificand2 = 0; + } else if (category==fcInfinity) { + myexponent = 0x7fff; + mysignificand = mysignificand2 = 0; + } else { + assert(category == fcNaN && "Unknown category!"); + myexponent = 0x7fff; + mysignificand = significandParts()[0]; + mysignificand2 = significandParts()[1]; + } + + uint64_t words[2]; + words[0] = mysignificand; + words[1] = ((uint64_t)(sign & 1) << 63) | + ((myexponent & 0x7fff) << 48) | + (mysignificand2 & 0xffffffffffffLL); + + return APInt(128, 2, words); +} + +APInt +APFloat::convertDoubleAPFloatToAPInt() const +{ + assert(semantics == (const llvm::fltSemantics*)&IEEEdouble); + assert(partCount()==1); + + uint64_t myexponent, mysignificand; + + if (category==fcNormal) { + myexponent = exponent+1023; //bias + mysignificand = *significandParts(); + if (myexponent==1 && !(mysignificand & 0x10000000000000LL)) + myexponent = 0; // denormal + } else if (category==fcZero) { + myexponent = 0; + mysignificand = 0; + } else if (category==fcInfinity) { + myexponent = 0x7ff; + mysignificand = 0; + } else { + assert(category == fcNaN && "Unknown category!"); + myexponent = 0x7ff; + mysignificand = *significandParts(); + } + + return APInt(64, ((((uint64_t)(sign & 1) << 63) | + ((myexponent & 0x7ff) << 52) | + (mysignificand & 0xfffffffffffffLL)))); +} + +APInt +APFloat::convertFloatAPFloatToAPInt() const +{ + assert(semantics == (const llvm::fltSemantics*)&IEEEsingle); + assert(partCount()==1); + + uint32_t myexponent, mysignificand; + + if (category==fcNormal) { + myexponent = exponent+127; //bias + mysignificand = (uint32_t)*significandParts(); + if (myexponent == 1 && !(mysignificand & 0x800000)) + myexponent = 0; // denormal + } else if (category==fcZero) { + myexponent = 0; + mysignificand = 0; + } else if (category==fcInfinity) { + myexponent = 0xff; + mysignificand = 0; + } else { + assert(category == fcNaN && "Unknown category!"); + myexponent = 0xff; + mysignificand = (uint32_t)*significandParts(); + } + + return APInt(32, (((sign&1) << 31) | ((myexponent&0xff) << 23) | + (mysignificand & 0x7fffff))); +} + +APInt +APFloat::convertHalfAPFloatToAPInt() const +{ + assert(semantics == (const llvm::fltSemantics*)&IEEEhalf); + assert(partCount()==1); + + uint32_t myexponent, mysignificand; + + if (category==fcNormal) { + myexponent = exponent+15; //bias + mysignificand = (uint32_t)*significandParts(); + if (myexponent == 1 && !(mysignificand & 0x400)) + myexponent = 0; // denormal + } else if (category==fcZero) { + myexponent = 0; + mysignificand = 0; + } else if (category==fcInfinity) { + myexponent = 0x1f; + mysignificand = 0; + } else { + assert(category == fcNaN && "Unknown category!"); + myexponent = 0x1f; + mysignificand = (uint32_t)*significandParts(); + } + + return APInt(16, (((sign&1) << 15) | ((myexponent&0x1f) << 10) | + (mysignificand & 0x3ff))); +} + +// This function creates an APInt that is just a bit map of the floating +// point constant as it would appear in memory. It is not a conversion, +// and treating the result as a normal integer is unlikely to be useful. + +APInt +APFloat::bitcastToAPInt() const +{ + if (semantics == (const llvm::fltSemantics*)&IEEEhalf) + return convertHalfAPFloatToAPInt(); + + if (semantics == (const llvm::fltSemantics*)&IEEEsingle) + return convertFloatAPFloatToAPInt(); + + if (semantics == (const llvm::fltSemantics*)&IEEEdouble) + return convertDoubleAPFloatToAPInt(); + + if (semantics == (const llvm::fltSemantics*)&IEEEquad) + return convertQuadrupleAPFloatToAPInt(); + + if (semantics == (const llvm::fltSemantics*)&PPCDoubleDouble) + return convertPPCDoubleDoubleAPFloatToAPInt(); + + assert(semantics == (const llvm::fltSemantics*)&x87DoubleExtended && + "unknown format!"); + return convertF80LongDoubleAPFloatToAPInt(); +} + +float +APFloat::convertToFloat() const +{ + assert(semantics == (const llvm::fltSemantics*)&IEEEsingle && + "Float semantics are not IEEEsingle"); + APInt api = bitcastToAPInt(); + return api.bitsToFloat(); +} + +double +APFloat::convertToDouble() const +{ + assert(semantics == (const llvm::fltSemantics*)&IEEEdouble && + "Float semantics are not IEEEdouble"); + APInt api = bitcastToAPInt(); + return api.bitsToDouble(); +} + +/// Integer bit is explicit in this format. Intel hardware (387 and later) +/// does not support these bit patterns: +/// exponent = all 1's, integer bit 0, significand 0 ("pseudoinfinity") +/// exponent = all 1's, integer bit 0, significand nonzero ("pseudoNaN") +/// exponent = 0, integer bit 1 ("pseudodenormal") +/// exponent!=0 nor all 1's, integer bit 0 ("unnormal") +/// At the moment, the first two are treated as NaNs, the second two as Normal. +void +APFloat::initFromF80LongDoubleAPInt(const APInt &api) +{ + assert(api.getBitWidth()==80); + uint64_t i1 = api.getRawData()[0]; + uint64_t i2 = api.getRawData()[1]; + uint64_t myexponent = (i2 & 0x7fff); + uint64_t mysignificand = i1; + + initialize(&APFloat::x87DoubleExtended); + assert(partCount()==2); + + sign = static_cast(i2>>15); + if (myexponent==0 && mysignificand==0) { + // exponent, significand meaningless + category = fcZero; + } else if (myexponent==0x7fff && mysignificand==0x8000000000000000ULL) { + // exponent, significand meaningless + category = fcInfinity; + } else if (myexponent==0x7fff && mysignificand!=0x8000000000000000ULL) { + // exponent meaningless + category = fcNaN; + significandParts()[0] = mysignificand; + significandParts()[1] = 0; + } else { + category = fcNormal; + exponent = myexponent - 16383; + significandParts()[0] = mysignificand; + significandParts()[1] = 0; + if (myexponent==0) // denormal + exponent = -16382; + } +} + +void +APFloat::initFromPPCDoubleDoubleAPInt(const APInt &api) +{ + assert(api.getBitWidth()==128); + uint64_t i1 = api.getRawData()[0]; + uint64_t i2 = api.getRawData()[1]; + uint64_t myexponent = (i1 >> 52) & 0x7ff; + uint64_t mysignificand = i1 & 0xfffffffffffffLL; + uint64_t myexponent2 = (i2 >> 52) & 0x7ff; + uint64_t mysignificand2 = i2 & 0xfffffffffffffLL; + + initialize(&APFloat::PPCDoubleDouble); + assert(partCount()==2); + + sign = static_cast(i1>>63); + sign2 = static_cast(i2>>63); + if (myexponent==0 && mysignificand==0) { + // exponent, significand meaningless + // exponent2 and significand2 are required to be 0; we don't check + category = fcZero; + } else if (myexponent==0x7ff && mysignificand==0) { + // exponent, significand meaningless + // exponent2 and significand2 are required to be 0; we don't check + category = fcInfinity; + } else if (myexponent==0x7ff && mysignificand!=0) { + // exponent meaningless. So is the whole second word, but keep it + // for determinism. + category = fcNaN; + exponent2 = myexponent2; + significandParts()[0] = mysignificand; + significandParts()[1] = mysignificand2; + } else { + category = fcNormal; + // Note there is no category2; the second word is treated as if it is + // fcNormal, although it might be something else considered by itself. + exponent = myexponent - 1023; + exponent2 = myexponent2 - 1023; + significandParts()[0] = mysignificand; + significandParts()[1] = mysignificand2; + if (myexponent==0) // denormal + exponent = -1022; + else + significandParts()[0] |= 0x10000000000000LL; // integer bit + if (myexponent2==0) + exponent2 = -1022; + else + significandParts()[1] |= 0x10000000000000LL; // integer bit + } +} + +void +APFloat::initFromQuadrupleAPInt(const APInt &api) +{ + assert(api.getBitWidth()==128); + uint64_t i1 = api.getRawData()[0]; + uint64_t i2 = api.getRawData()[1]; + uint64_t myexponent = (i2 >> 48) & 0x7fff; + uint64_t mysignificand = i1; + uint64_t mysignificand2 = i2 & 0xffffffffffffLL; + + initialize(&APFloat::IEEEquad); + assert(partCount()==2); + + sign = static_cast(i2>>63); + if (myexponent==0 && + (mysignificand==0 && mysignificand2==0)) { + // exponent, significand meaningless + category = fcZero; + } else if (myexponent==0x7fff && + (mysignificand==0 && mysignificand2==0)) { + // exponent, significand meaningless + category = fcInfinity; + } else if (myexponent==0x7fff && + (mysignificand!=0 || mysignificand2 !=0)) { + // exponent meaningless + category = fcNaN; + significandParts()[0] = mysignificand; + significandParts()[1] = mysignificand2; + } else { + category = fcNormal; + exponent = myexponent - 16383; + significandParts()[0] = mysignificand; + significandParts()[1] = mysignificand2; + if (myexponent==0) // denormal + exponent = -16382; + else + significandParts()[1] |= 0x1000000000000LL; // integer bit + } +} + +void +APFloat::initFromDoubleAPInt(const APInt &api) +{ + assert(api.getBitWidth()==64); + uint64_t i = *api.getRawData(); + uint64_t myexponent = (i >> 52) & 0x7ff; + uint64_t mysignificand = i & 0xfffffffffffffLL; + + initialize(&APFloat::IEEEdouble); + assert(partCount()==1); + + sign = static_cast(i>>63); + if (myexponent==0 && mysignificand==0) { + // exponent, significand meaningless + category = fcZero; + } else if (myexponent==0x7ff && mysignificand==0) { + // exponent, significand meaningless + category = fcInfinity; + } else if (myexponent==0x7ff && mysignificand!=0) { + // exponent meaningless + category = fcNaN; + *significandParts() = mysignificand; + } else { + category = fcNormal; + exponent = myexponent - 1023; + *significandParts() = mysignificand; + if (myexponent==0) // denormal + exponent = -1022; + else + *significandParts() |= 0x10000000000000LL; // integer bit + } +} + +void +APFloat::initFromFloatAPInt(const APInt & api) +{ + assert(api.getBitWidth()==32); + uint32_t i = (uint32_t)*api.getRawData(); + uint32_t myexponent = (i >> 23) & 0xff; + uint32_t mysignificand = i & 0x7fffff; + + initialize(&APFloat::IEEEsingle); + assert(partCount()==1); + + sign = i >> 31; + if (myexponent==0 && mysignificand==0) { + // exponent, significand meaningless + category = fcZero; + } else if (myexponent==0xff && mysignificand==0) { + // exponent, significand meaningless + category = fcInfinity; + } else if (myexponent==0xff && mysignificand!=0) { + // sign, exponent, significand meaningless + category = fcNaN; + *significandParts() = mysignificand; + } else { + category = fcNormal; + exponent = myexponent - 127; //bias + *significandParts() = mysignificand; + if (myexponent==0) // denormal + exponent = -126; + else + *significandParts() |= 0x800000; // integer bit + } +} + +void +APFloat::initFromHalfAPInt(const APInt & api) +{ + assert(api.getBitWidth()==16); + uint32_t i = (uint32_t)*api.getRawData(); + uint32_t myexponent = (i >> 10) & 0x1f; + uint32_t mysignificand = i & 0x3ff; + + initialize(&APFloat::IEEEhalf); + assert(partCount()==1); + + sign = i >> 15; + if (myexponent==0 && mysignificand==0) { + // exponent, significand meaningless + category = fcZero; + } else if (myexponent==0x1f && mysignificand==0) { + // exponent, significand meaningless + category = fcInfinity; + } else if (myexponent==0x1f && mysignificand!=0) { + // sign, exponent, significand meaningless + category = fcNaN; + *significandParts() = mysignificand; + } else { + category = fcNormal; + exponent = myexponent - 15; //bias + *significandParts() = mysignificand; + if (myexponent==0) // denormal + exponent = -14; + else + *significandParts() |= 0x400; // integer bit + } +} + +/// Treat api as containing the bits of a floating point number. Currently +/// we infer the floating point type from the size of the APInt. The +/// isIEEE argument distinguishes between PPC128 and IEEE128 (not meaningful +/// when the size is anything else). +void +APFloat::initFromAPInt(const APInt& api, bool isIEEE) +{ + if (api.getBitWidth() == 16) + return initFromHalfAPInt(api); + else if (api.getBitWidth() == 32) + return initFromFloatAPInt(api); + else if (api.getBitWidth()==64) + return initFromDoubleAPInt(api); + else if (api.getBitWidth()==80) + return initFromF80LongDoubleAPInt(api); + else if (api.getBitWidth()==128) + return (isIEEE ? + initFromQuadrupleAPInt(api) : initFromPPCDoubleDoubleAPInt(api)); + else + llvm_unreachable(0); +} + +APFloat::APFloat(const APInt& api, bool isIEEE) +{ + initFromAPInt(api, isIEEE); +} + +APFloat::APFloat(float f) +{ + APInt api = APInt(32, 0); + initFromAPInt(api.floatToBits(f)); +} + +APFloat::APFloat(double d) +{ + APInt api = APInt(64, 0); + initFromAPInt(api.doubleToBits(d)); +} diff --git a/libclamav/c++/llvm/lib/Support/APInt.cpp b/libclamav/c++/llvm/lib/Support/APInt.cpp new file mode 100644 index 000000000..56d47736e --- /dev/null +++ b/libclamav/c++/llvm/lib/Support/APInt.cpp @@ -0,0 +1,2839 @@ +//===-- APInt.cpp - Implement APInt class ---------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements a class to represent arbitrary precision integer +// constant values and provide a variety of arithmetic operations on them. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "apint" +#include "llvm/ADT/APInt.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/FoldingSet.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/Support/raw_ostream.h" +#include +#include +#include +#include +using namespace llvm; + +/// A utility function for allocating memory, checking for allocation failures, +/// and ensuring the contents are zeroed. +inline static uint64_t* getClearedMemory(unsigned numWords) { + uint64_t * result = new uint64_t[numWords]; + assert(result && "APInt memory allocation fails!"); + memset(result, 0, numWords * sizeof(uint64_t)); + return result; +} + +/// A utility function for allocating memory and checking for allocation +/// failure. The content is not zeroed. +inline static uint64_t* getMemory(unsigned numWords) { + uint64_t * result = new uint64_t[numWords]; + assert(result && "APInt memory allocation fails!"); + return result; +} + +/// A utility function that converts a character to a digit. +inline static unsigned getDigit(char cdigit, uint8_t radix) { + unsigned r; + + if (radix == 16) { + r = cdigit - '0'; + if (r <= 9) + return r; + + r = cdigit - 'A'; + if (r <= 5) + return r + 10; + + r = cdigit - 'a'; + if (r <= 5) + return r + 10; + } + + r = cdigit - '0'; + if (r < radix) + return r; + + return -1U; +} + + +void APInt::initSlowCase(unsigned numBits, uint64_t val, bool isSigned) { + pVal = getClearedMemory(getNumWords()); + pVal[0] = val; + if (isSigned && int64_t(val) < 0) + for (unsigned i = 1; i < getNumWords(); ++i) + pVal[i] = -1ULL; +} + +void APInt::initSlowCase(const APInt& that) { + pVal = getMemory(getNumWords()); + memcpy(pVal, that.pVal, getNumWords() * APINT_WORD_SIZE); +} + + +APInt::APInt(unsigned numBits, unsigned numWords, const uint64_t bigVal[]) + : BitWidth(numBits), VAL(0) { + assert(BitWidth && "Bitwidth too small"); + assert(bigVal && "Null pointer detected!"); + if (isSingleWord()) + VAL = bigVal[0]; + else { + // Get memory, cleared to 0 + pVal = getClearedMemory(getNumWords()); + // Calculate the number of words to copy + unsigned words = std::min(numWords, getNumWords()); + // Copy the words from bigVal to pVal + memcpy(pVal, bigVal, words * APINT_WORD_SIZE); + } + // Make sure unused high bits are cleared + clearUnusedBits(); +} + +APInt::APInt(unsigned numbits, const StringRef& Str, uint8_t radix) + : BitWidth(numbits), VAL(0) { + assert(BitWidth && "Bitwidth too small"); + fromString(numbits, Str, radix); +} + +APInt& APInt::AssignSlowCase(const APInt& RHS) { + // Don't do anything for X = X + if (this == &RHS) + return *this; + + if (BitWidth == RHS.getBitWidth()) { + // assume same bit-width single-word case is already handled + assert(!isSingleWord()); + memcpy(pVal, RHS.pVal, getNumWords() * APINT_WORD_SIZE); + return *this; + } + + if (isSingleWord()) { + // assume case where both are single words is already handled + assert(!RHS.isSingleWord()); + VAL = 0; + pVal = getMemory(RHS.getNumWords()); + memcpy(pVal, RHS.pVal, RHS.getNumWords() * APINT_WORD_SIZE); + } else if (getNumWords() == RHS.getNumWords()) + memcpy(pVal, RHS.pVal, RHS.getNumWords() * APINT_WORD_SIZE); + else if (RHS.isSingleWord()) { + delete [] pVal; + VAL = RHS.VAL; + } else { + delete [] pVal; + pVal = getMemory(RHS.getNumWords()); + memcpy(pVal, RHS.pVal, RHS.getNumWords() * APINT_WORD_SIZE); + } + BitWidth = RHS.BitWidth; + return clearUnusedBits(); +} + +APInt& APInt::operator=(uint64_t RHS) { + if (isSingleWord()) + VAL = RHS; + else { + pVal[0] = RHS; + memset(pVal+1, 0, (getNumWords() - 1) * APINT_WORD_SIZE); + } + return clearUnusedBits(); +} + +/// Profile - This method 'profiles' an APInt for use with FoldingSet. +void APInt::Profile(FoldingSetNodeID& ID) const { + ID.AddInteger(BitWidth); + + if (isSingleWord()) { + ID.AddInteger(VAL); + return; + } + + unsigned NumWords = getNumWords(); + for (unsigned i = 0; i < NumWords; ++i) + ID.AddInteger(pVal[i]); +} + +/// add_1 - This function adds a single "digit" integer, y, to the multiple +/// "digit" integer array, x[]. x[] is modified to reflect the addition and +/// 1 is returned if there is a carry out, otherwise 0 is returned. +/// @returns the carry of the addition. +static bool add_1(uint64_t dest[], uint64_t x[], unsigned len, uint64_t y) { + for (unsigned i = 0; i < len; ++i) { + dest[i] = y + x[i]; + if (dest[i] < y) + y = 1; // Carry one to next digit. + else { + y = 0; // No need to carry so exit early + break; + } + } + return y; +} + +/// @brief Prefix increment operator. Increments the APInt by one. +APInt& APInt::operator++() { + if (isSingleWord()) + ++VAL; + else + add_1(pVal, pVal, getNumWords(), 1); + return clearUnusedBits(); +} + +/// sub_1 - This function subtracts a single "digit" (64-bit word), y, from +/// the multi-digit integer array, x[], propagating the borrowed 1 value until +/// no further borrowing is neeeded or it runs out of "digits" in x. The result +/// is 1 if "borrowing" exhausted the digits in x, or 0 if x was not exhausted. +/// In other words, if y > x then this function returns 1, otherwise 0. +/// @returns the borrow out of the subtraction +static bool sub_1(uint64_t x[], unsigned len, uint64_t y) { + for (unsigned i = 0; i < len; ++i) { + uint64_t X = x[i]; + x[i] -= y; + if (y > X) + y = 1; // We have to "borrow 1" from next "digit" + else { + y = 0; // No need to borrow + break; // Remaining digits are unchanged so exit early + } + } + return bool(y); +} + +/// @brief Prefix decrement operator. Decrements the APInt by one. +APInt& APInt::operator--() { + if (isSingleWord()) + --VAL; + else + sub_1(pVal, getNumWords(), 1); + return clearUnusedBits(); +} + +/// add - This function adds the integer array x to the integer array Y and +/// places the result in dest. +/// @returns the carry out from the addition +/// @brief General addition of 64-bit integer arrays +static bool add(uint64_t *dest, const uint64_t *x, const uint64_t *y, + unsigned len) { + bool carry = false; + for (unsigned i = 0; i< len; ++i) { + uint64_t limit = std::min(x[i],y[i]); // must come first in case dest == x + dest[i] = x[i] + y[i] + carry; + carry = dest[i] < limit || (carry && dest[i] == limit); + } + return carry; +} + +/// Adds the RHS APint to this APInt. +/// @returns this, after addition of RHS. +/// @brief Addition assignment operator. +APInt& APInt::operator+=(const APInt& RHS) { + assert(BitWidth == RHS.BitWidth && "Bit widths must be the same"); + if (isSingleWord()) + VAL += RHS.VAL; + else { + add(pVal, pVal, RHS.pVal, getNumWords()); + } + return clearUnusedBits(); +} + +/// Subtracts the integer array y from the integer array x +/// @returns returns the borrow out. +/// @brief Generalized subtraction of 64-bit integer arrays. +static bool sub(uint64_t *dest, const uint64_t *x, const uint64_t *y, + unsigned len) { + bool borrow = false; + for (unsigned i = 0; i < len; ++i) { + uint64_t x_tmp = borrow ? x[i] - 1 : x[i]; + borrow = y[i] > x_tmp || (borrow && x[i] == 0); + dest[i] = x_tmp - y[i]; + } + return borrow; +} + +/// Subtracts the RHS APInt from this APInt +/// @returns this, after subtraction +/// @brief Subtraction assignment operator. +APInt& APInt::operator-=(const APInt& RHS) { + assert(BitWidth == RHS.BitWidth && "Bit widths must be the same"); + if (isSingleWord()) + VAL -= RHS.VAL; + else + sub(pVal, pVal, RHS.pVal, getNumWords()); + return clearUnusedBits(); +} + +/// Multiplies an integer array, x by a a uint64_t integer and places the result +/// into dest. +/// @returns the carry out of the multiplication. +/// @brief Multiply a multi-digit APInt by a single digit (64-bit) integer. +static uint64_t mul_1(uint64_t dest[], uint64_t x[], unsigned len, uint64_t y) { + // Split y into high 32-bit part (hy) and low 32-bit part (ly) + uint64_t ly = y & 0xffffffffULL, hy = y >> 32; + uint64_t carry = 0; + + // For each digit of x. + for (unsigned i = 0; i < len; ++i) { + // Split x into high and low words + uint64_t lx = x[i] & 0xffffffffULL; + uint64_t hx = x[i] >> 32; + // hasCarry - A flag to indicate if there is a carry to the next digit. + // hasCarry == 0, no carry + // hasCarry == 1, has carry + // hasCarry == 2, no carry and the calculation result == 0. + uint8_t hasCarry = 0; + dest[i] = carry + lx * ly; + // Determine if the add above introduces carry. + hasCarry = (dest[i] < carry) ? 1 : 0; + carry = hx * ly + (dest[i] >> 32) + (hasCarry ? (1ULL << 32) : 0); + // The upper limit of carry can be (2^32 - 1)(2^32 - 1) + + // (2^32 - 1) + 2^32 = 2^64. + hasCarry = (!carry && hasCarry) ? 1 : (!carry ? 2 : 0); + + carry += (lx * hy) & 0xffffffffULL; + dest[i] = (carry << 32) | (dest[i] & 0xffffffffULL); + carry = (((!carry && hasCarry != 2) || hasCarry == 1) ? (1ULL << 32) : 0) + + (carry >> 32) + ((lx * hy) >> 32) + hx * hy; + } + return carry; +} + +/// Multiplies integer array x by integer array y and stores the result into +/// the integer array dest. Note that dest's size must be >= xlen + ylen. +/// @brief Generalized multiplicate of integer arrays. +static void mul(uint64_t dest[], uint64_t x[], unsigned xlen, uint64_t y[], + unsigned ylen) { + dest[xlen] = mul_1(dest, x, xlen, y[0]); + for (unsigned i = 1; i < ylen; ++i) { + uint64_t ly = y[i] & 0xffffffffULL, hy = y[i] >> 32; + uint64_t carry = 0, lx = 0, hx = 0; + for (unsigned j = 0; j < xlen; ++j) { + lx = x[j] & 0xffffffffULL; + hx = x[j] >> 32; + // hasCarry - A flag to indicate if has carry. + // hasCarry == 0, no carry + // hasCarry == 1, has carry + // hasCarry == 2, no carry and the calculation result == 0. + uint8_t hasCarry = 0; + uint64_t resul = carry + lx * ly; + hasCarry = (resul < carry) ? 1 : 0; + carry = (hasCarry ? (1ULL << 32) : 0) + hx * ly + (resul >> 32); + hasCarry = (!carry && hasCarry) ? 1 : (!carry ? 2 : 0); + + carry += (lx * hy) & 0xffffffffULL; + resul = (carry << 32) | (resul & 0xffffffffULL); + dest[i+j] += resul; + carry = (((!carry && hasCarry != 2) || hasCarry == 1) ? (1ULL << 32) : 0)+ + (carry >> 32) + (dest[i+j] < resul ? 1 : 0) + + ((lx * hy) >> 32) + hx * hy; + } + dest[i+xlen] = carry; + } +} + +APInt& APInt::operator*=(const APInt& RHS) { + assert(BitWidth == RHS.BitWidth && "Bit widths must be the same"); + if (isSingleWord()) { + VAL *= RHS.VAL; + clearUnusedBits(); + return *this; + } + + // Get some bit facts about LHS and check for zero + unsigned lhsBits = getActiveBits(); + unsigned lhsWords = !lhsBits ? 0 : whichWord(lhsBits - 1) + 1; + if (!lhsWords) + // 0 * X ===> 0 + return *this; + + // Get some bit facts about RHS and check for zero + unsigned rhsBits = RHS.getActiveBits(); + unsigned rhsWords = !rhsBits ? 0 : whichWord(rhsBits - 1) + 1; + if (!rhsWords) { + // X * 0 ===> 0 + clear(); + return *this; + } + + // Allocate space for the result + unsigned destWords = rhsWords + lhsWords; + uint64_t *dest = getMemory(destWords); + + // Perform the long multiply + mul(dest, pVal, lhsWords, RHS.pVal, rhsWords); + + // Copy result back into *this + clear(); + unsigned wordsToCopy = destWords >= getNumWords() ? getNumWords() : destWords; + memcpy(pVal, dest, wordsToCopy * APINT_WORD_SIZE); + + // delete dest array and return + delete[] dest; + return *this; +} + +APInt& APInt::operator&=(const APInt& RHS) { + assert(BitWidth == RHS.BitWidth && "Bit widths must be the same"); + if (isSingleWord()) { + VAL &= RHS.VAL; + return *this; + } + unsigned numWords = getNumWords(); + for (unsigned i = 0; i < numWords; ++i) + pVal[i] &= RHS.pVal[i]; + return *this; +} + +APInt& APInt::operator|=(const APInt& RHS) { + assert(BitWidth == RHS.BitWidth && "Bit widths must be the same"); + if (isSingleWord()) { + VAL |= RHS.VAL; + return *this; + } + unsigned numWords = getNumWords(); + for (unsigned i = 0; i < numWords; ++i) + pVal[i] |= RHS.pVal[i]; + return *this; +} + +APInt& APInt::operator^=(const APInt& RHS) { + assert(BitWidth == RHS.BitWidth && "Bit widths must be the same"); + if (isSingleWord()) { + VAL ^= RHS.VAL; + this->clearUnusedBits(); + return *this; + } + unsigned numWords = getNumWords(); + for (unsigned i = 0; i < numWords; ++i) + pVal[i] ^= RHS.pVal[i]; + return clearUnusedBits(); +} + +APInt APInt::AndSlowCase(const APInt& RHS) const { + unsigned numWords = getNumWords(); + uint64_t* val = getMemory(numWords); + for (unsigned i = 0; i < numWords; ++i) + val[i] = pVal[i] & RHS.pVal[i]; + return APInt(val, getBitWidth()); +} + +APInt APInt::OrSlowCase(const APInt& RHS) const { + unsigned numWords = getNumWords(); + uint64_t *val = getMemory(numWords); + for (unsigned i = 0; i < numWords; ++i) + val[i] = pVal[i] | RHS.pVal[i]; + return APInt(val, getBitWidth()); +} + +APInt APInt::XorSlowCase(const APInt& RHS) const { + unsigned numWords = getNumWords(); + uint64_t *val = getMemory(numWords); + for (unsigned i = 0; i < numWords; ++i) + val[i] = pVal[i] ^ RHS.pVal[i]; + + // 0^0==1 so clear the high bits in case they got set. + return APInt(val, getBitWidth()).clearUnusedBits(); +} + +bool APInt::operator !() const { + if (isSingleWord()) + return !VAL; + + for (unsigned i = 0; i < getNumWords(); ++i) + if (pVal[i]) + return false; + return true; +} + +APInt APInt::operator*(const APInt& RHS) const { + assert(BitWidth == RHS.BitWidth && "Bit widths must be the same"); + if (isSingleWord()) + return APInt(BitWidth, VAL * RHS.VAL); + APInt Result(*this); + Result *= RHS; + return Result.clearUnusedBits(); +} + +APInt APInt::operator+(const APInt& RHS) const { + assert(BitWidth == RHS.BitWidth && "Bit widths must be the same"); + if (isSingleWord()) + return APInt(BitWidth, VAL + RHS.VAL); + APInt Result(BitWidth, 0); + add(Result.pVal, this->pVal, RHS.pVal, getNumWords()); + return Result.clearUnusedBits(); +} + +APInt APInt::operator-(const APInt& RHS) const { + assert(BitWidth == RHS.BitWidth && "Bit widths must be the same"); + if (isSingleWord()) + return APInt(BitWidth, VAL - RHS.VAL); + APInt Result(BitWidth, 0); + sub(Result.pVal, this->pVal, RHS.pVal, getNumWords()); + return Result.clearUnusedBits(); +} + +bool APInt::operator[](unsigned bitPosition) const { + return (maskBit(bitPosition) & + (isSingleWord() ? VAL : pVal[whichWord(bitPosition)])) != 0; +} + +bool APInt::EqualSlowCase(const APInt& RHS) const { + // Get some facts about the number of bits used in the two operands. + unsigned n1 = getActiveBits(); + unsigned n2 = RHS.getActiveBits(); + + // If the number of bits isn't the same, they aren't equal + if (n1 != n2) + return false; + + // If the number of bits fits in a word, we only need to compare the low word. + if (n1 <= APINT_BITS_PER_WORD) + return pVal[0] == RHS.pVal[0]; + + // Otherwise, compare everything + for (int i = whichWord(n1 - 1); i >= 0; --i) + if (pVal[i] != RHS.pVal[i]) + return false; + return true; +} + +bool APInt::EqualSlowCase(uint64_t Val) const { + unsigned n = getActiveBits(); + if (n <= APINT_BITS_PER_WORD) + return pVal[0] == Val; + else + return false; +} + +bool APInt::ult(const APInt& RHS) const { + assert(BitWidth == RHS.BitWidth && "Bit widths must be same for comparison"); + if (isSingleWord()) + return VAL < RHS.VAL; + + // Get active bit length of both operands + unsigned n1 = getActiveBits(); + unsigned n2 = RHS.getActiveBits(); + + // If magnitude of LHS is less than RHS, return true. + if (n1 < n2) + return true; + + // If magnitude of RHS is greather than LHS, return false. + if (n2 < n1) + return false; + + // If they bot fit in a word, just compare the low order word + if (n1 <= APINT_BITS_PER_WORD && n2 <= APINT_BITS_PER_WORD) + return pVal[0] < RHS.pVal[0]; + + // Otherwise, compare all words + unsigned topWord = whichWord(std::max(n1,n2)-1); + for (int i = topWord; i >= 0; --i) { + if (pVal[i] > RHS.pVal[i]) + return false; + if (pVal[i] < RHS.pVal[i]) + return true; + } + return false; +} + +bool APInt::slt(const APInt& RHS) const { + assert(BitWidth == RHS.BitWidth && "Bit widths must be same for comparison"); + if (isSingleWord()) { + int64_t lhsSext = (int64_t(VAL) << (64-BitWidth)) >> (64-BitWidth); + int64_t rhsSext = (int64_t(RHS.VAL) << (64-BitWidth)) >> (64-BitWidth); + return lhsSext < rhsSext; + } + + APInt lhs(*this); + APInt rhs(RHS); + bool lhsNeg = isNegative(); + bool rhsNeg = rhs.isNegative(); + if (lhsNeg) { + // Sign bit is set so perform two's complement to make it positive + lhs.flip(); + lhs++; + } + if (rhsNeg) { + // Sign bit is set so perform two's complement to make it positive + rhs.flip(); + rhs++; + } + + // Now we have unsigned values to compare so do the comparison if necessary + // based on the negativeness of the values. + if (lhsNeg) + if (rhsNeg) + return lhs.ugt(rhs); + else + return true; + else if (rhsNeg) + return false; + else + return lhs.ult(rhs); +} + +APInt& APInt::set(unsigned bitPosition) { + if (isSingleWord()) + VAL |= maskBit(bitPosition); + else + pVal[whichWord(bitPosition)] |= maskBit(bitPosition); + return *this; +} + +/// Set the given bit to 0 whose position is given as "bitPosition". +/// @brief Set a given bit to 0. +APInt& APInt::clear(unsigned bitPosition) { + if (isSingleWord()) + VAL &= ~maskBit(bitPosition); + else + pVal[whichWord(bitPosition)] &= ~maskBit(bitPosition); + return *this; +} + +/// @brief Toggle every bit to its opposite value. + +/// Toggle a given bit to its opposite value whose position is given +/// as "bitPosition". +/// @brief Toggles a given bit to its opposite value. +APInt& APInt::flip(unsigned bitPosition) { + assert(bitPosition < BitWidth && "Out of the bit-width range!"); + if ((*this)[bitPosition]) clear(bitPosition); + else set(bitPosition); + return *this; +} + +unsigned APInt::getBitsNeeded(const StringRef& str, uint8_t radix) { + assert(!str.empty() && "Invalid string length"); + assert((radix == 10 || radix == 8 || radix == 16 || radix == 2) && + "Radix should be 2, 8, 10, or 16!"); + + size_t slen = str.size(); + + // Each computation below needs to know if it's negative. + StringRef::iterator p = str.begin(); + unsigned isNegative = *p == '-'; + if (*p == '-' || *p == '+') { + p++; + slen--; + assert(slen && "String is only a sign, needs a value."); + } + + // For radixes of power-of-two values, the bits required is accurately and + // easily computed + if (radix == 2) + return slen + isNegative; + if (radix == 8) + return slen * 3 + isNegative; + if (radix == 16) + return slen * 4 + isNegative; + + // This is grossly inefficient but accurate. We could probably do something + // with a computation of roughly slen*64/20 and then adjust by the value of + // the first few digits. But, I'm not sure how accurate that could be. + + // Compute a sufficient number of bits that is always large enough but might + // be too large. This avoids the assertion in the constructor. This + // calculation doesn't work appropriately for the numbers 0-9, so just use 4 + // bits in that case. + unsigned sufficient = slen == 1 ? 4 : slen * 64/18; + + // Convert to the actual binary value. + APInt tmp(sufficient, StringRef(p, slen), radix); + + // Compute how many bits are required. If the log is infinite, assume we need + // just bit. + unsigned log = tmp.logBase2(); + if (log == (unsigned)-1) { + return isNegative + 1; + } else { + return isNegative + log + 1; + } +} + +// From http://www.burtleburtle.net, byBob Jenkins. +// When targeting x86, both GCC and LLVM seem to recognize this as a +// rotate instruction. +#define rot(x,k) (((x)<<(k)) | ((x)>>(32-(k)))) + +// From http://www.burtleburtle.net, by Bob Jenkins. +#define mix(a,b,c) \ + { \ + a -= c; a ^= rot(c, 4); c += b; \ + b -= a; b ^= rot(a, 6); a += c; \ + c -= b; c ^= rot(b, 8); b += a; \ + a -= c; a ^= rot(c,16); c += b; \ + b -= a; b ^= rot(a,19); a += c; \ + c -= b; c ^= rot(b, 4); b += a; \ + } + +// From http://www.burtleburtle.net, by Bob Jenkins. +#define final(a,b,c) \ + { \ + c ^= b; c -= rot(b,14); \ + a ^= c; a -= rot(c,11); \ + b ^= a; b -= rot(a,25); \ + c ^= b; c -= rot(b,16); \ + a ^= c; a -= rot(c,4); \ + b ^= a; b -= rot(a,14); \ + c ^= b; c -= rot(b,24); \ + } + +// hashword() was adapted from http://www.burtleburtle.net, by Bob +// Jenkins. k is a pointer to an array of uint32_t values; length is +// the length of the key, in 32-bit chunks. This version only handles +// keys that are a multiple of 32 bits in size. +static inline uint32_t hashword(const uint64_t *k64, size_t length) +{ + const uint32_t *k = reinterpret_cast(k64); + uint32_t a,b,c; + + /* Set up the internal state */ + a = b = c = 0xdeadbeef + (((uint32_t)length)<<2); + + /*------------------------------------------------- handle most of the key */ + while (length > 3) + { + a += k[0]; + b += k[1]; + c += k[2]; + mix(a,b,c); + length -= 3; + k += 3; + } + + /*------------------------------------------- handle the last 3 uint32_t's */ + switch (length) { /* all the case statements fall through */ + case 3 : c+=k[2]; + case 2 : b+=k[1]; + case 1 : a+=k[0]; + final(a,b,c); + case 0: /* case 0: nothing left to add */ + break; + } + /*------------------------------------------------------ report the result */ + return c; +} + +// hashword8() was adapted from http://www.burtleburtle.net, by Bob +// Jenkins. This computes a 32-bit hash from one 64-bit word. When +// targeting x86 (32 or 64 bit), both LLVM and GCC compile this +// function into about 35 instructions when inlined. +static inline uint32_t hashword8(const uint64_t k64) +{ + uint32_t a,b,c; + a = b = c = 0xdeadbeef + 4; + b += k64 >> 32; + a += k64 & 0xffffffff; + final(a,b,c); + return c; +} +#undef final +#undef mix +#undef rot + +uint64_t APInt::getHashValue() const { + uint64_t hash; + if (isSingleWord()) + hash = hashword8(VAL); + else + hash = hashword(pVal, getNumWords()*2); + return hash; +} + +/// HiBits - This function returns the high "numBits" bits of this APInt. +APInt APInt::getHiBits(unsigned numBits) const { + return APIntOps::lshr(*this, BitWidth - numBits); +} + +/// LoBits - This function returns the low "numBits" bits of this APInt. +APInt APInt::getLoBits(unsigned numBits) const { + return APIntOps::lshr(APIntOps::shl(*this, BitWidth - numBits), + BitWidth - numBits); +} + +bool APInt::isPowerOf2() const { + return (!!*this) && !(*this & (*this - APInt(BitWidth,1))); +} + +unsigned APInt::countLeadingZerosSlowCase() const { + unsigned Count = 0; + for (unsigned i = getNumWords(); i > 0u; --i) { + if (pVal[i-1] == 0) + Count += APINT_BITS_PER_WORD; + else { + Count += CountLeadingZeros_64(pVal[i-1]); + break; + } + } + unsigned remainder = BitWidth % APINT_BITS_PER_WORD; + if (remainder) + Count -= APINT_BITS_PER_WORD - remainder; + return std::min(Count, BitWidth); +} + +static unsigned countLeadingOnes_64(uint64_t V, unsigned skip) { + unsigned Count = 0; + if (skip) + V <<= skip; + while (V && (V & (1ULL << 63))) { + Count++; + V <<= 1; + } + return Count; +} + +unsigned APInt::countLeadingOnes() const { + if (isSingleWord()) + return countLeadingOnes_64(VAL, APINT_BITS_PER_WORD - BitWidth); + + unsigned highWordBits = BitWidth % APINT_BITS_PER_WORD; + unsigned shift; + if (!highWordBits) { + highWordBits = APINT_BITS_PER_WORD; + shift = 0; + } else { + shift = APINT_BITS_PER_WORD - highWordBits; + } + int i = getNumWords() - 1; + unsigned Count = countLeadingOnes_64(pVal[i], shift); + if (Count == highWordBits) { + for (i--; i >= 0; --i) { + if (pVal[i] == -1ULL) + Count += APINT_BITS_PER_WORD; + else { + Count += countLeadingOnes_64(pVal[i], 0); + break; + } + } + } + return Count; +} + +unsigned APInt::countTrailingZeros() const { + if (isSingleWord()) + return std::min(unsigned(CountTrailingZeros_64(VAL)), BitWidth); + unsigned Count = 0; + unsigned i = 0; + for (; i < getNumWords() && pVal[i] == 0; ++i) + Count += APINT_BITS_PER_WORD; + if (i < getNumWords()) + Count += CountTrailingZeros_64(pVal[i]); + return std::min(Count, BitWidth); +} + +unsigned APInt::countTrailingOnesSlowCase() const { + unsigned Count = 0; + unsigned i = 0; + for (; i < getNumWords() && pVal[i] == -1ULL; ++i) + Count += APINT_BITS_PER_WORD; + if (i < getNumWords()) + Count += CountTrailingOnes_64(pVal[i]); + return std::min(Count, BitWidth); +} + +unsigned APInt::countPopulationSlowCase() const { + unsigned Count = 0; + for (unsigned i = 0; i < getNumWords(); ++i) + Count += CountPopulation_64(pVal[i]); + return Count; +} + +APInt APInt::byteSwap() const { + assert(BitWidth >= 16 && BitWidth % 16 == 0 && "Cannot byteswap!"); + if (BitWidth == 16) + return APInt(BitWidth, ByteSwap_16(uint16_t(VAL))); + else if (BitWidth == 32) + return APInt(BitWidth, ByteSwap_32(unsigned(VAL))); + else if (BitWidth == 48) { + unsigned Tmp1 = unsigned(VAL >> 16); + Tmp1 = ByteSwap_32(Tmp1); + uint16_t Tmp2 = uint16_t(VAL); + Tmp2 = ByteSwap_16(Tmp2); + return APInt(BitWidth, (uint64_t(Tmp2) << 32) | Tmp1); + } else if (BitWidth == 64) + return APInt(BitWidth, ByteSwap_64(VAL)); + else { + APInt Result(BitWidth, 0); + char *pByte = (char*)Result.pVal; + for (unsigned i = 0; i < BitWidth / APINT_WORD_SIZE / 2; ++i) { + char Tmp = pByte[i]; + pByte[i] = pByte[BitWidth / APINT_WORD_SIZE - 1 - i]; + pByte[BitWidth / APINT_WORD_SIZE - i - 1] = Tmp; + } + return Result; + } +} + +APInt llvm::APIntOps::GreatestCommonDivisor(const APInt& API1, + const APInt& API2) { + APInt A = API1, B = API2; + while (!!B) { + APInt T = B; + B = APIntOps::urem(A, B); + A = T; + } + return A; +} + +APInt llvm::APIntOps::RoundDoubleToAPInt(double Double, unsigned width) { + union { + double D; + uint64_t I; + } T; + T.D = Double; + + // Get the sign bit from the highest order bit + bool isNeg = T.I >> 63; + + // Get the 11-bit exponent and adjust for the 1023 bit bias + int64_t exp = ((T.I >> 52) & 0x7ff) - 1023; + + // If the exponent is negative, the value is < 0 so just return 0. + if (exp < 0) + return APInt(width, 0u); + + // Extract the mantissa by clearing the top 12 bits (sign + exponent). + uint64_t mantissa = (T.I & (~0ULL >> 12)) | 1ULL << 52; + + // If the exponent doesn't shift all bits out of the mantissa + if (exp < 52) + return isNeg ? -APInt(width, mantissa >> (52 - exp)) : + APInt(width, mantissa >> (52 - exp)); + + // If the client didn't provide enough bits for us to shift the mantissa into + // then the result is undefined, just return 0 + if (width <= exp - 52) + return APInt(width, 0); + + // Otherwise, we have to shift the mantissa bits up to the right location + APInt Tmp(width, mantissa); + Tmp = Tmp.shl((unsigned)exp - 52); + return isNeg ? -Tmp : Tmp; +} + +/// RoundToDouble - This function converts this APInt to a double. +/// The layout for double is as following (IEEE Standard 754): +/// -------------------------------------- +/// | Sign Exponent Fraction Bias | +/// |-------------------------------------- | +/// | 1[63] 11[62-52] 52[51-00] 1023 | +/// -------------------------------------- +double APInt::roundToDouble(bool isSigned) const { + + // Handle the simple case where the value is contained in one uint64_t. + // It is wrong to optimize getWord(0) to VAL; there might be more than one word. + if (isSingleWord() || getActiveBits() <= APINT_BITS_PER_WORD) { + if (isSigned) { + int64_t sext = (int64_t(getWord(0)) << (64-BitWidth)) >> (64-BitWidth); + return double(sext); + } else + return double(getWord(0)); + } + + // Determine if the value is negative. + bool isNeg = isSigned ? (*this)[BitWidth-1] : false; + + // Construct the absolute value if we're negative. + APInt Tmp(isNeg ? -(*this) : (*this)); + + // Figure out how many bits we're using. + unsigned n = Tmp.getActiveBits(); + + // The exponent (without bias normalization) is just the number of bits + // we are using. Note that the sign bit is gone since we constructed the + // absolute value. + uint64_t exp = n; + + // Return infinity for exponent overflow + if (exp > 1023) { + if (!isSigned || !isNeg) + return std::numeric_limits::infinity(); + else + return -std::numeric_limits::infinity(); + } + exp += 1023; // Increment for 1023 bias + + // Number of bits in mantissa is 52. To obtain the mantissa value, we must + // extract the high 52 bits from the correct words in pVal. + uint64_t mantissa; + unsigned hiWord = whichWord(n-1); + if (hiWord == 0) { + mantissa = Tmp.pVal[0]; + if (n > 52) + mantissa >>= n - 52; // shift down, we want the top 52 bits. + } else { + assert(hiWord > 0 && "huh?"); + uint64_t hibits = Tmp.pVal[hiWord] << (52 - n % APINT_BITS_PER_WORD); + uint64_t lobits = Tmp.pVal[hiWord-1] >> (11 + n % APINT_BITS_PER_WORD); + mantissa = hibits | lobits; + } + + // The leading bit of mantissa is implicit, so get rid of it. + uint64_t sign = isNeg ? (1ULL << (APINT_BITS_PER_WORD - 1)) : 0; + union { + double D; + uint64_t I; + } T; + T.I = sign | (exp << 52) | mantissa; + return T.D; +} + +// Truncate to new width. +APInt &APInt::trunc(unsigned width) { + assert(width < BitWidth && "Invalid APInt Truncate request"); + assert(width && "Can't truncate to 0 bits"); + unsigned wordsBefore = getNumWords(); + BitWidth = width; + unsigned wordsAfter = getNumWords(); + if (wordsBefore != wordsAfter) { + if (wordsAfter == 1) { + uint64_t *tmp = pVal; + VAL = pVal[0]; + delete [] tmp; + } else { + uint64_t *newVal = getClearedMemory(wordsAfter); + for (unsigned i = 0; i < wordsAfter; ++i) + newVal[i] = pVal[i]; + delete [] pVal; + pVal = newVal; + } + } + return clearUnusedBits(); +} + +// Sign extend to a new width. +APInt &APInt::sext(unsigned width) { + assert(width > BitWidth && "Invalid APInt SignExtend request"); + // If the sign bit isn't set, this is the same as zext. + if (!isNegative()) { + zext(width); + return *this; + } + + // The sign bit is set. First, get some facts + unsigned wordsBefore = getNumWords(); + unsigned wordBits = BitWidth % APINT_BITS_PER_WORD; + BitWidth = width; + unsigned wordsAfter = getNumWords(); + + // Mask the high order word appropriately + if (wordsBefore == wordsAfter) { + unsigned newWordBits = width % APINT_BITS_PER_WORD; + // The extension is contained to the wordsBefore-1th word. + uint64_t mask = ~0ULL; + if (newWordBits) + mask >>= APINT_BITS_PER_WORD - newWordBits; + mask <<= wordBits; + if (wordsBefore == 1) + VAL |= mask; + else + pVal[wordsBefore-1] |= mask; + return clearUnusedBits(); + } + + uint64_t mask = wordBits == 0 ? 0 : ~0ULL << wordBits; + uint64_t *newVal = getMemory(wordsAfter); + if (wordsBefore == 1) + newVal[0] = VAL | mask; + else { + for (unsigned i = 0; i < wordsBefore; ++i) + newVal[i] = pVal[i]; + newVal[wordsBefore-1] |= mask; + } + for (unsigned i = wordsBefore; i < wordsAfter; i++) + newVal[i] = -1ULL; + if (wordsBefore != 1) + delete [] pVal; + pVal = newVal; + return clearUnusedBits(); +} + +// Zero extend to a new width. +APInt &APInt::zext(unsigned width) { + assert(width > BitWidth && "Invalid APInt ZeroExtend request"); + unsigned wordsBefore = getNumWords(); + BitWidth = width; + unsigned wordsAfter = getNumWords(); + if (wordsBefore != wordsAfter) { + uint64_t *newVal = getClearedMemory(wordsAfter); + if (wordsBefore == 1) + newVal[0] = VAL; + else + for (unsigned i = 0; i < wordsBefore; ++i) + newVal[i] = pVal[i]; + if (wordsBefore != 1) + delete [] pVal; + pVal = newVal; + } + return *this; +} + +APInt &APInt::zextOrTrunc(unsigned width) { + if (BitWidth < width) + return zext(width); + if (BitWidth > width) + return trunc(width); + return *this; +} + +APInt &APInt::sextOrTrunc(unsigned width) { + if (BitWidth < width) + return sext(width); + if (BitWidth > width) + return trunc(width); + return *this; +} + +/// Arithmetic right-shift this APInt by shiftAmt. +/// @brief Arithmetic right-shift function. +APInt APInt::ashr(const APInt &shiftAmt) const { + return ashr((unsigned)shiftAmt.getLimitedValue(BitWidth)); +} + +/// Arithmetic right-shift this APInt by shiftAmt. +/// @brief Arithmetic right-shift function. +APInt APInt::ashr(unsigned shiftAmt) const { + assert(shiftAmt <= BitWidth && "Invalid shift amount"); + // Handle a degenerate case + if (shiftAmt == 0) + return *this; + + // Handle single word shifts with built-in ashr + if (isSingleWord()) { + if (shiftAmt == BitWidth) + return APInt(BitWidth, 0); // undefined + else { + unsigned SignBit = APINT_BITS_PER_WORD - BitWidth; + return APInt(BitWidth, + (((int64_t(VAL) << SignBit) >> SignBit) >> shiftAmt)); + } + } + + // If all the bits were shifted out, the result is, technically, undefined. + // We return -1 if it was negative, 0 otherwise. We check this early to avoid + // issues in the algorithm below. + if (shiftAmt == BitWidth) { + if (isNegative()) + return APInt(BitWidth, -1ULL, true); + else + return APInt(BitWidth, 0); + } + + // Create some space for the result. + uint64_t * val = new uint64_t[getNumWords()]; + + // Compute some values needed by the following shift algorithms + unsigned wordShift = shiftAmt % APINT_BITS_PER_WORD; // bits to shift per word + unsigned offset = shiftAmt / APINT_BITS_PER_WORD; // word offset for shift + unsigned breakWord = getNumWords() - 1 - offset; // last word affected + unsigned bitsInWord = whichBit(BitWidth); // how many bits in last word? + if (bitsInWord == 0) + bitsInWord = APINT_BITS_PER_WORD; + + // If we are shifting whole words, just move whole words + if (wordShift == 0) { + // Move the words containing significant bits + for (unsigned i = 0; i <= breakWord; ++i) + val[i] = pVal[i+offset]; // move whole word + + // Adjust the top significant word for sign bit fill, if negative + if (isNegative()) + if (bitsInWord < APINT_BITS_PER_WORD) + val[breakWord] |= ~0ULL << bitsInWord; // set high bits + } else { + // Shift the low order words + for (unsigned i = 0; i < breakWord; ++i) { + // This combines the shifted corresponding word with the low bits from + // the next word (shifted into this word's high bits). + val[i] = (pVal[i+offset] >> wordShift) | + (pVal[i+offset+1] << (APINT_BITS_PER_WORD - wordShift)); + } + + // Shift the break word. In this case there are no bits from the next word + // to include in this word. + val[breakWord] = pVal[breakWord+offset] >> wordShift; + + // Deal with sign extenstion in the break word, and possibly the word before + // it. + if (isNegative()) { + if (wordShift > bitsInWord) { + if (breakWord > 0) + val[breakWord-1] |= + ~0ULL << (APINT_BITS_PER_WORD - (wordShift - bitsInWord)); + val[breakWord] |= ~0ULL; + } else + val[breakWord] |= (~0ULL << (bitsInWord - wordShift)); + } + } + + // Remaining words are 0 or -1, just assign them. + uint64_t fillValue = (isNegative() ? -1ULL : 0); + for (unsigned i = breakWord+1; i < getNumWords(); ++i) + val[i] = fillValue; + return APInt(val, BitWidth).clearUnusedBits(); +} + +/// Logical right-shift this APInt by shiftAmt. +/// @brief Logical right-shift function. +APInt APInt::lshr(const APInt &shiftAmt) const { + return lshr((unsigned)shiftAmt.getLimitedValue(BitWidth)); +} + +/// Logical right-shift this APInt by shiftAmt. +/// @brief Logical right-shift function. +APInt APInt::lshr(unsigned shiftAmt) const { + if (isSingleWord()) { + if (shiftAmt == BitWidth) + return APInt(BitWidth, 0); + else + return APInt(BitWidth, this->VAL >> shiftAmt); + } + + // If all the bits were shifted out, the result is 0. This avoids issues + // with shifting by the size of the integer type, which produces undefined + // results. We define these "undefined results" to always be 0. + if (shiftAmt == BitWidth) + return APInt(BitWidth, 0); + + // If none of the bits are shifted out, the result is *this. This avoids + // issues with shifting by the size of the integer type, which produces + // undefined results in the code below. This is also an optimization. + if (shiftAmt == 0) + return *this; + + // Create some space for the result. + uint64_t * val = new uint64_t[getNumWords()]; + + // If we are shifting less than a word, compute the shift with a simple carry + if (shiftAmt < APINT_BITS_PER_WORD) { + uint64_t carry = 0; + for (int i = getNumWords()-1; i >= 0; --i) { + val[i] = (pVal[i] >> shiftAmt) | carry; + carry = pVal[i] << (APINT_BITS_PER_WORD - shiftAmt); + } + return APInt(val, BitWidth).clearUnusedBits(); + } + + // Compute some values needed by the remaining shift algorithms + unsigned wordShift = shiftAmt % APINT_BITS_PER_WORD; + unsigned offset = shiftAmt / APINT_BITS_PER_WORD; + + // If we are shifting whole words, just move whole words + if (wordShift == 0) { + for (unsigned i = 0; i < getNumWords() - offset; ++i) + val[i] = pVal[i+offset]; + for (unsigned i = getNumWords()-offset; i < getNumWords(); i++) + val[i] = 0; + return APInt(val,BitWidth).clearUnusedBits(); + } + + // Shift the low order words + unsigned breakWord = getNumWords() - offset -1; + for (unsigned i = 0; i < breakWord; ++i) + val[i] = (pVal[i+offset] >> wordShift) | + (pVal[i+offset+1] << (APINT_BITS_PER_WORD - wordShift)); + // Shift the break word. + val[breakWord] = pVal[breakWord+offset] >> wordShift; + + // Remaining words are 0 + for (unsigned i = breakWord+1; i < getNumWords(); ++i) + val[i] = 0; + return APInt(val, BitWidth).clearUnusedBits(); +} + +/// Left-shift this APInt by shiftAmt. +/// @brief Left-shift function. +APInt APInt::shl(const APInt &shiftAmt) const { + // It's undefined behavior in C to shift by BitWidth or greater. + return shl((unsigned)shiftAmt.getLimitedValue(BitWidth)); +} + +APInt APInt::shlSlowCase(unsigned shiftAmt) const { + // If all the bits were shifted out, the result is 0. This avoids issues + // with shifting by the size of the integer type, which produces undefined + // results. We define these "undefined results" to always be 0. + if (shiftAmt == BitWidth) + return APInt(BitWidth, 0); + + // If none of the bits are shifted out, the result is *this. This avoids a + // lshr by the words size in the loop below which can produce incorrect + // results. It also avoids the expensive computation below for a common case. + if (shiftAmt == 0) + return *this; + + // Create some space for the result. + uint64_t * val = new uint64_t[getNumWords()]; + + // If we are shifting less than a word, do it the easy way + if (shiftAmt < APINT_BITS_PER_WORD) { + uint64_t carry = 0; + for (unsigned i = 0; i < getNumWords(); i++) { + val[i] = pVal[i] << shiftAmt | carry; + carry = pVal[i] >> (APINT_BITS_PER_WORD - shiftAmt); + } + return APInt(val, BitWidth).clearUnusedBits(); + } + + // Compute some values needed by the remaining shift algorithms + unsigned wordShift = shiftAmt % APINT_BITS_PER_WORD; + unsigned offset = shiftAmt / APINT_BITS_PER_WORD; + + // If we are shifting whole words, just move whole words + if (wordShift == 0) { + for (unsigned i = 0; i < offset; i++) + val[i] = 0; + for (unsigned i = offset; i < getNumWords(); i++) + val[i] = pVal[i-offset]; + return APInt(val,BitWidth).clearUnusedBits(); + } + + // Copy whole words from this to Result. + unsigned i = getNumWords() - 1; + for (; i > offset; --i) + val[i] = pVal[i-offset] << wordShift | + pVal[i-offset-1] >> (APINT_BITS_PER_WORD - wordShift); + val[offset] = pVal[0] << wordShift; + for (i = 0; i < offset; ++i) + val[i] = 0; + return APInt(val, BitWidth).clearUnusedBits(); +} + +APInt APInt::rotl(const APInt &rotateAmt) const { + return rotl((unsigned)rotateAmt.getLimitedValue(BitWidth)); +} + +APInt APInt::rotl(unsigned rotateAmt) const { + if (rotateAmt == 0) + return *this; + // Don't get too fancy, just use existing shift/or facilities + APInt hi(*this); + APInt lo(*this); + hi.shl(rotateAmt); + lo.lshr(BitWidth - rotateAmt); + return hi | lo; +} + +APInt APInt::rotr(const APInt &rotateAmt) const { + return rotr((unsigned)rotateAmt.getLimitedValue(BitWidth)); +} + +APInt APInt::rotr(unsigned rotateAmt) const { + if (rotateAmt == 0) + return *this; + // Don't get too fancy, just use existing shift/or facilities + APInt hi(*this); + APInt lo(*this); + lo.lshr(rotateAmt); + hi.shl(BitWidth - rotateAmt); + return hi | lo; +} + +// Square Root - this method computes and returns the square root of "this". +// Three mechanisms are used for computation. For small values (<= 5 bits), +// a table lookup is done. This gets some performance for common cases. For +// values using less than 52 bits, the value is converted to double and then +// the libc sqrt function is called. The result is rounded and then converted +// back to a uint64_t which is then used to construct the result. Finally, +// the Babylonian method for computing square roots is used. +APInt APInt::sqrt() const { + + // Determine the magnitude of the value. + unsigned magnitude = getActiveBits(); + + // Use a fast table for some small values. This also gets rid of some + // rounding errors in libc sqrt for small values. + if (magnitude <= 5) { + static const uint8_t results[32] = { + /* 0 */ 0, + /* 1- 2 */ 1, 1, + /* 3- 6 */ 2, 2, 2, 2, + /* 7-12 */ 3, 3, 3, 3, 3, 3, + /* 13-20 */ 4, 4, 4, 4, 4, 4, 4, 4, + /* 21-30 */ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + /* 31 */ 6 + }; + return APInt(BitWidth, results[ (isSingleWord() ? VAL : pVal[0]) ]); + } + + // If the magnitude of the value fits in less than 52 bits (the precision of + // an IEEE double precision floating point value), then we can use the + // libc sqrt function which will probably use a hardware sqrt computation. + // This should be faster than the algorithm below. + if (magnitude < 52) { +#ifdef _MSC_VER + // Amazingly, VC++ doesn't have round(). + return APInt(BitWidth, + uint64_t(::sqrt(double(isSingleWord()?VAL:pVal[0]))) + 0.5); +#else + return APInt(BitWidth, + uint64_t(::round(::sqrt(double(isSingleWord()?VAL:pVal[0]))))); +#endif + } + + // Okay, all the short cuts are exhausted. We must compute it. The following + // is a classical Babylonian method for computing the square root. This code + // was adapted to APINt from a wikipedia article on such computations. + // See http://www.wikipedia.org/ and go to the page named + // Calculate_an_integer_square_root. + unsigned nbits = BitWidth, i = 4; + APInt testy(BitWidth, 16); + APInt x_old(BitWidth, 1); + APInt x_new(BitWidth, 0); + APInt two(BitWidth, 2); + + // Select a good starting value using binary logarithms. + for (;; i += 2, testy = testy.shl(2)) + if (i >= nbits || this->ule(testy)) { + x_old = x_old.shl(i / 2); + break; + } + + // Use the Babylonian method to arrive at the integer square root: + for (;;) { + x_new = (this->udiv(x_old) + x_old).udiv(two); + if (x_old.ule(x_new)) + break; + x_old = x_new; + } + + // Make sure we return the closest approximation + // NOTE: The rounding calculation below is correct. It will produce an + // off-by-one discrepancy with results from pari/gp. That discrepancy has been + // determined to be a rounding issue with pari/gp as it begins to use a + // floating point representation after 192 bits. There are no discrepancies + // between this algorithm and pari/gp for bit widths < 192 bits. + APInt square(x_old * x_old); + APInt nextSquare((x_old + 1) * (x_old +1)); + if (this->ult(square)) + return x_old; + else if (this->ule(nextSquare)) { + APInt midpoint((nextSquare - square).udiv(two)); + APInt offset(*this - square); + if (offset.ult(midpoint)) + return x_old; + else + return x_old + 1; + } else + llvm_unreachable("Error in APInt::sqrt computation"); + return x_old + 1; +} + +/// Computes the multiplicative inverse of this APInt for a given modulo. The +/// iterative extended Euclidean algorithm is used to solve for this value, +/// however we simplify it to speed up calculating only the inverse, and take +/// advantage of div+rem calculations. We also use some tricks to avoid copying +/// (potentially large) APInts around. +APInt APInt::multiplicativeInverse(const APInt& modulo) const { + assert(ult(modulo) && "This APInt must be smaller than the modulo"); + + // Using the properties listed at the following web page (accessed 06/21/08): + // http://www.numbertheory.org/php/euclid.html + // (especially the properties numbered 3, 4 and 9) it can be proved that + // BitWidth bits suffice for all the computations in the algorithm implemented + // below. More precisely, this number of bits suffice if the multiplicative + // inverse exists, but may not suffice for the general extended Euclidean + // algorithm. + + APInt r[2] = { modulo, *this }; + APInt t[2] = { APInt(BitWidth, 0), APInt(BitWidth, 1) }; + APInt q(BitWidth, 0); + + unsigned i; + for (i = 0; r[i^1] != 0; i ^= 1) { + // An overview of the math without the confusing bit-flipping: + // q = r[i-2] / r[i-1] + // r[i] = r[i-2] % r[i-1] + // t[i] = t[i-2] - t[i-1] * q + udivrem(r[i], r[i^1], q, r[i]); + t[i] -= t[i^1] * q; + } + + // If this APInt and the modulo are not coprime, there is no multiplicative + // inverse, so return 0. We check this by looking at the next-to-last + // remainder, which is the gcd(*this,modulo) as calculated by the Euclidean + // algorithm. + if (r[i] != 1) + return APInt(BitWidth, 0); + + // The next-to-last t is the multiplicative inverse. However, we are + // interested in a positive inverse. Calcuate a positive one from a negative + // one if necessary. A simple addition of the modulo suffices because + // abs(t[i]) is known to be less than *this/2 (see the link above). + return t[i].isNegative() ? t[i] + modulo : t[i]; +} + +/// Calculate the magic numbers required to implement a signed integer division +/// by a constant as a sequence of multiplies, adds and shifts. Requires that +/// the divisor not be 0, 1, or -1. Taken from "Hacker's Delight", Henry S. +/// Warren, Jr., chapter 10. +APInt::ms APInt::magic() const { + const APInt& d = *this; + unsigned p; + APInt ad, anc, delta, q1, r1, q2, r2, t; + APInt signedMin = APInt::getSignedMinValue(d.getBitWidth()); + struct ms mag; + + ad = d.abs(); + t = signedMin + (d.lshr(d.getBitWidth() - 1)); + anc = t - 1 - t.urem(ad); // absolute value of nc + p = d.getBitWidth() - 1; // initialize p + q1 = signedMin.udiv(anc); // initialize q1 = 2p/abs(nc) + r1 = signedMin - q1*anc; // initialize r1 = rem(2p,abs(nc)) + q2 = signedMin.udiv(ad); // initialize q2 = 2p/abs(d) + r2 = signedMin - q2*ad; // initialize r2 = rem(2p,abs(d)) + do { + p = p + 1; + q1 = q1<<1; // update q1 = 2p/abs(nc) + r1 = r1<<1; // update r1 = rem(2p/abs(nc)) + if (r1.uge(anc)) { // must be unsigned comparison + q1 = q1 + 1; + r1 = r1 - anc; + } + q2 = q2<<1; // update q2 = 2p/abs(d) + r2 = r2<<1; // update r2 = rem(2p/abs(d)) + if (r2.uge(ad)) { // must be unsigned comparison + q2 = q2 + 1; + r2 = r2 - ad; + } + delta = ad - r2; + } while (q1.ule(delta) || (q1 == delta && r1 == 0)); + + mag.m = q2 + 1; + if (d.isNegative()) mag.m = -mag.m; // resulting magic number + mag.s = p - d.getBitWidth(); // resulting shift + return mag; +} + +/// Calculate the magic numbers required to implement an unsigned integer +/// division by a constant as a sequence of multiplies, adds and shifts. +/// Requires that the divisor not be 0. Taken from "Hacker's Delight", Henry +/// S. Warren, Jr., chapter 10. +APInt::mu APInt::magicu() const { + const APInt& d = *this; + unsigned p; + APInt nc, delta, q1, r1, q2, r2; + struct mu magu; + magu.a = 0; // initialize "add" indicator + APInt allOnes = APInt::getAllOnesValue(d.getBitWidth()); + APInt signedMin = APInt::getSignedMinValue(d.getBitWidth()); + APInt signedMax = APInt::getSignedMaxValue(d.getBitWidth()); + + nc = allOnes - (-d).urem(d); + p = d.getBitWidth() - 1; // initialize p + q1 = signedMin.udiv(nc); // initialize q1 = 2p/nc + r1 = signedMin - q1*nc; // initialize r1 = rem(2p,nc) + q2 = signedMax.udiv(d); // initialize q2 = (2p-1)/d + r2 = signedMax - q2*d; // initialize r2 = rem((2p-1),d) + do { + p = p + 1; + if (r1.uge(nc - r1)) { + q1 = q1 + q1 + 1; // update q1 + r1 = r1 + r1 - nc; // update r1 + } + else { + q1 = q1+q1; // update q1 + r1 = r1+r1; // update r1 + } + if ((r2 + 1).uge(d - r2)) { + if (q2.uge(signedMax)) magu.a = 1; + q2 = q2+q2 + 1; // update q2 + r2 = r2+r2 + 1 - d; // update r2 + } + else { + if (q2.uge(signedMin)) magu.a = 1; + q2 = q2+q2; // update q2 + r2 = r2+r2 + 1; // update r2 + } + delta = d - 1 - r2; + } while (p < d.getBitWidth()*2 && + (q1.ult(delta) || (q1 == delta && r1 == 0))); + magu.m = q2 + 1; // resulting magic number + magu.s = p - d.getBitWidth(); // resulting shift + return magu; +} + +/// Implementation of Knuth's Algorithm D (Division of nonnegative integers) +/// from "Art of Computer Programming, Volume 2", section 4.3.1, p. 272. The +/// variables here have the same names as in the algorithm. Comments explain +/// the algorithm and any deviation from it. +static void KnuthDiv(unsigned *u, unsigned *v, unsigned *q, unsigned* r, + unsigned m, unsigned n) { + assert(u && "Must provide dividend"); + assert(v && "Must provide divisor"); + assert(q && "Must provide quotient"); + assert(u != v && u != q && v != q && "Must us different memory"); + assert(n>1 && "n must be > 1"); + + // Knuth uses the value b as the base of the number system. In our case b + // is 2^31 so we just set it to -1u. + uint64_t b = uint64_t(1) << 32; + +#if 0 + DEBUG(errs() << "KnuthDiv: m=" << m << " n=" << n << '\n'); + DEBUG(errs() << "KnuthDiv: original:"); + DEBUG(for (int i = m+n; i >=0; i--) errs() << " " << u[i]); + DEBUG(errs() << " by"); + DEBUG(for (int i = n; i >0; i--) errs() << " " << v[i-1]); + DEBUG(errs() << '\n'); +#endif + // D1. [Normalize.] Set d = b / (v[n-1] + 1) and multiply all the digits of + // u and v by d. Note that we have taken Knuth's advice here to use a power + // of 2 value for d such that d * v[n-1] >= b/2 (b is the base). A power of + // 2 allows us to shift instead of multiply and it is easy to determine the + // shift amount from the leading zeros. We are basically normalizing the u + // and v so that its high bits are shifted to the top of v's range without + // overflow. Note that this can require an extra word in u so that u must + // be of length m+n+1. + unsigned shift = CountLeadingZeros_32(v[n-1]); + unsigned v_carry = 0; + unsigned u_carry = 0; + if (shift) { + for (unsigned i = 0; i < m+n; ++i) { + unsigned u_tmp = u[i] >> (32 - shift); + u[i] = (u[i] << shift) | u_carry; + u_carry = u_tmp; + } + for (unsigned i = 0; i < n; ++i) { + unsigned v_tmp = v[i] >> (32 - shift); + v[i] = (v[i] << shift) | v_carry; + v_carry = v_tmp; + } + } + u[m+n] = u_carry; +#if 0 + DEBUG(errs() << "KnuthDiv: normal:"); + DEBUG(for (int i = m+n; i >=0; i--) errs() << " " << u[i]); + DEBUG(errs() << " by"); + DEBUG(for (int i = n; i >0; i--) errs() << " " << v[i-1]); + DEBUG(errs() << '\n'); +#endif + + // D2. [Initialize j.] Set j to m. This is the loop counter over the places. + int j = m; + do { + DEBUG(errs() << "KnuthDiv: quotient digit #" << j << '\n'); + // D3. [Calculate q'.]. + // Set qp = (u[j+n]*b + u[j+n-1]) / v[n-1]. (qp=qprime=q') + // Set rp = (u[j+n]*b + u[j+n-1]) % v[n-1]. (rp=rprime=r') + // Now test if qp == b or qp*v[n-2] > b*rp + u[j+n-2]; if so, decrease + // qp by 1, inrease rp by v[n-1], and repeat this test if rp < b. The test + // on v[n-2] determines at high speed most of the cases in which the trial + // value qp is one too large, and it eliminates all cases where qp is two + // too large. + uint64_t dividend = ((uint64_t(u[j+n]) << 32) + u[j+n-1]); + DEBUG(errs() << "KnuthDiv: dividend == " << dividend << '\n'); + uint64_t qp = dividend / v[n-1]; + uint64_t rp = dividend % v[n-1]; + if (qp == b || qp*v[n-2] > b*rp + u[j+n-2]) { + qp--; + rp += v[n-1]; + if (rp < b && (qp == b || qp*v[n-2] > b*rp + u[j+n-2])) + qp--; + } + DEBUG(errs() << "KnuthDiv: qp == " << qp << ", rp == " << rp << '\n'); + + // D4. [Multiply and subtract.] Replace (u[j+n]u[j+n-1]...u[j]) with + // (u[j+n]u[j+n-1]..u[j]) - qp * (v[n-1]...v[1]v[0]). This computation + // consists of a simple multiplication by a one-place number, combined with + // a subtraction. + bool isNeg = false; + for (unsigned i = 0; i < n; ++i) { + uint64_t u_tmp = uint64_t(u[j+i]) | (uint64_t(u[j+i+1]) << 32); + uint64_t subtrahend = uint64_t(qp) * uint64_t(v[i]); + bool borrow = subtrahend > u_tmp; + DEBUG(errs() << "KnuthDiv: u_tmp == " << u_tmp + << ", subtrahend == " << subtrahend + << ", borrow = " << borrow << '\n'); + + uint64_t result = u_tmp - subtrahend; + unsigned k = j + i; + u[k++] = (unsigned)(result & (b-1)); // subtract low word + u[k++] = (unsigned)(result >> 32); // subtract high word + while (borrow && k <= m+n) { // deal with borrow to the left + borrow = u[k] == 0; + u[k]--; + k++; + } + isNeg |= borrow; + DEBUG(errs() << "KnuthDiv: u[j+i] == " << u[j+i] << ", u[j+i+1] == " << + u[j+i+1] << '\n'); + } + DEBUG(errs() << "KnuthDiv: after subtraction:"); + DEBUG(for (int i = m+n; i >=0; i--) errs() << " " << u[i]); + DEBUG(errs() << '\n'); + // The digits (u[j+n]...u[j]) should be kept positive; if the result of + // this step is actually negative, (u[j+n]...u[j]) should be left as the + // true value plus b**(n+1), namely as the b's complement of + // the true value, and a "borrow" to the left should be remembered. + // + if (isNeg) { + bool carry = true; // true because b's complement is "complement + 1" + for (unsigned i = 0; i <= m+n; ++i) { + u[i] = ~u[i] + carry; // b's complement + carry = carry && u[i] == 0; + } + } + DEBUG(errs() << "KnuthDiv: after complement:"); + DEBUG(for (int i = m+n; i >=0; i--) errs() << " " << u[i]); + DEBUG(errs() << '\n'); + + // D5. [Test remainder.] Set q[j] = qp. If the result of step D4 was + // negative, go to step D6; otherwise go on to step D7. + q[j] = (unsigned)qp; + if (isNeg) { + // D6. [Add back]. The probability that this step is necessary is very + // small, on the order of only 2/b. Make sure that test data accounts for + // this possibility. Decrease q[j] by 1 + q[j]--; + // and add (0v[n-1]...v[1]v[0]) to (u[j+n]u[j+n-1]...u[j+1]u[j]). + // A carry will occur to the left of u[j+n], and it should be ignored + // since it cancels with the borrow that occurred in D4. + bool carry = false; + for (unsigned i = 0; i < n; i++) { + unsigned limit = std::min(u[j+i],v[i]); + u[j+i] += v[i] + carry; + carry = u[j+i] < limit || (carry && u[j+i] == limit); + } + u[j+n] += carry; + } + DEBUG(errs() << "KnuthDiv: after correction:"); + DEBUG(for (int i = m+n; i >=0; i--) errs() <<" " << u[i]); + DEBUG(errs() << "\nKnuthDiv: digit result = " << q[j] << '\n'); + + // D7. [Loop on j.] Decrease j by one. Now if j >= 0, go back to D3. + } while (--j >= 0); + + DEBUG(errs() << "KnuthDiv: quotient:"); + DEBUG(for (int i = m; i >=0; i--) errs() <<" " << q[i]); + DEBUG(errs() << '\n'); + + // D8. [Unnormalize]. Now q[...] is the desired quotient, and the desired + // remainder may be obtained by dividing u[...] by d. If r is non-null we + // compute the remainder (urem uses this). + if (r) { + // The value d is expressed by the "shift" value above since we avoided + // multiplication by d by using a shift left. So, all we have to do is + // shift right here. In order to mak + if (shift) { + unsigned carry = 0; + DEBUG(errs() << "KnuthDiv: remainder:"); + for (int i = n-1; i >= 0; i--) { + r[i] = (u[i] >> shift) | carry; + carry = u[i] << (32 - shift); + DEBUG(errs() << " " << r[i]); + } + } else { + for (int i = n-1; i >= 0; i--) { + r[i] = u[i]; + DEBUG(errs() << " " << r[i]); + } + } + DEBUG(errs() << '\n'); + } +#if 0 + DEBUG(errs() << '\n'); +#endif +} + +void APInt::divide(const APInt LHS, unsigned lhsWords, + const APInt &RHS, unsigned rhsWords, + APInt *Quotient, APInt *Remainder) +{ + assert(lhsWords >= rhsWords && "Fractional result"); + + // First, compose the values into an array of 32-bit words instead of + // 64-bit words. This is a necessity of both the "short division" algorithm + // and the the Knuth "classical algorithm" which requires there to be native + // operations for +, -, and * on an m bit value with an m*2 bit result. We + // can't use 64-bit operands here because we don't have native results of + // 128-bits. Furthermore, casting the 64-bit values to 32-bit values won't + // work on large-endian machines. + uint64_t mask = ~0ull >> (sizeof(unsigned)*CHAR_BIT); + unsigned n = rhsWords * 2; + unsigned m = (lhsWords * 2) - n; + + // Allocate space for the temporary values we need either on the stack, if + // it will fit, or on the heap if it won't. + unsigned SPACE[128]; + unsigned *U = 0; + unsigned *V = 0; + unsigned *Q = 0; + unsigned *R = 0; + if ((Remainder?4:3)*n+2*m+1 <= 128) { + U = &SPACE[0]; + V = &SPACE[m+n+1]; + Q = &SPACE[(m+n+1) + n]; + if (Remainder) + R = &SPACE[(m+n+1) + n + (m+n)]; + } else { + U = new unsigned[m + n + 1]; + V = new unsigned[n]; + Q = new unsigned[m+n]; + if (Remainder) + R = new unsigned[n]; + } + + // Initialize the dividend + memset(U, 0, (m+n+1)*sizeof(unsigned)); + for (unsigned i = 0; i < lhsWords; ++i) { + uint64_t tmp = (LHS.getNumWords() == 1 ? LHS.VAL : LHS.pVal[i]); + U[i * 2] = (unsigned)(tmp & mask); + U[i * 2 + 1] = (unsigned)(tmp >> (sizeof(unsigned)*CHAR_BIT)); + } + U[m+n] = 0; // this extra word is for "spill" in the Knuth algorithm. + + // Initialize the divisor + memset(V, 0, (n)*sizeof(unsigned)); + for (unsigned i = 0; i < rhsWords; ++i) { + uint64_t tmp = (RHS.getNumWords() == 1 ? RHS.VAL : RHS.pVal[i]); + V[i * 2] = (unsigned)(tmp & mask); + V[i * 2 + 1] = (unsigned)(tmp >> (sizeof(unsigned)*CHAR_BIT)); + } + + // initialize the quotient and remainder + memset(Q, 0, (m+n) * sizeof(unsigned)); + if (Remainder) + memset(R, 0, n * sizeof(unsigned)); + + // Now, adjust m and n for the Knuth division. n is the number of words in + // the divisor. m is the number of words by which the dividend exceeds the + // divisor (i.e. m+n is the length of the dividend). These sizes must not + // contain any zero words or the Knuth algorithm fails. + for (unsigned i = n; i > 0 && V[i-1] == 0; i--) { + n--; + m++; + } + for (unsigned i = m+n; i > 0 && U[i-1] == 0; i--) + m--; + + // If we're left with only a single word for the divisor, Knuth doesn't work + // so we implement the short division algorithm here. This is much simpler + // and faster because we are certain that we can divide a 64-bit quantity + // by a 32-bit quantity at hardware speed and short division is simply a + // series of such operations. This is just like doing short division but we + // are using base 2^32 instead of base 10. + assert(n != 0 && "Divide by zero?"); + if (n == 1) { + unsigned divisor = V[0]; + unsigned remainder = 0; + for (int i = m+n-1; i >= 0; i--) { + uint64_t partial_dividend = uint64_t(remainder) << 32 | U[i]; + if (partial_dividend == 0) { + Q[i] = 0; + remainder = 0; + } else if (partial_dividend < divisor) { + Q[i] = 0; + remainder = (unsigned)partial_dividend; + } else if (partial_dividend == divisor) { + Q[i] = 1; + remainder = 0; + } else { + Q[i] = (unsigned)(partial_dividend / divisor); + remainder = (unsigned)(partial_dividend - (Q[i] * divisor)); + } + } + if (R) + R[0] = remainder; + } else { + // Now we're ready to invoke the Knuth classical divide algorithm. In this + // case n > 1. + KnuthDiv(U, V, Q, R, m, n); + } + + // If the caller wants the quotient + if (Quotient) { + // Set up the Quotient value's memory. + if (Quotient->BitWidth != LHS.BitWidth) { + if (Quotient->isSingleWord()) + Quotient->VAL = 0; + else + delete [] Quotient->pVal; + Quotient->BitWidth = LHS.BitWidth; + if (!Quotient->isSingleWord()) + Quotient->pVal = getClearedMemory(Quotient->getNumWords()); + } else + Quotient->clear(); + + // The quotient is in Q. Reconstitute the quotient into Quotient's low + // order words. + if (lhsWords == 1) { + uint64_t tmp = + uint64_t(Q[0]) | (uint64_t(Q[1]) << (APINT_BITS_PER_WORD / 2)); + if (Quotient->isSingleWord()) + Quotient->VAL = tmp; + else + Quotient->pVal[0] = tmp; + } else { + assert(!Quotient->isSingleWord() && "Quotient APInt not large enough"); + for (unsigned i = 0; i < lhsWords; ++i) + Quotient->pVal[i] = + uint64_t(Q[i*2]) | (uint64_t(Q[i*2+1]) << (APINT_BITS_PER_WORD / 2)); + } + } + + // If the caller wants the remainder + if (Remainder) { + // Set up the Remainder value's memory. + if (Remainder->BitWidth != RHS.BitWidth) { + if (Remainder->isSingleWord()) + Remainder->VAL = 0; + else + delete [] Remainder->pVal; + Remainder->BitWidth = RHS.BitWidth; + if (!Remainder->isSingleWord()) + Remainder->pVal = getClearedMemory(Remainder->getNumWords()); + } else + Remainder->clear(); + + // The remainder is in R. Reconstitute the remainder into Remainder's low + // order words. + if (rhsWords == 1) { + uint64_t tmp = + uint64_t(R[0]) | (uint64_t(R[1]) << (APINT_BITS_PER_WORD / 2)); + if (Remainder->isSingleWord()) + Remainder->VAL = tmp; + else + Remainder->pVal[0] = tmp; + } else { + assert(!Remainder->isSingleWord() && "Remainder APInt not large enough"); + for (unsigned i = 0; i < rhsWords; ++i) + Remainder->pVal[i] = + uint64_t(R[i*2]) | (uint64_t(R[i*2+1]) << (APINT_BITS_PER_WORD / 2)); + } + } + + // Clean up the memory we allocated. + if (U != &SPACE[0]) { + delete [] U; + delete [] V; + delete [] Q; + delete [] R; + } +} + +APInt APInt::udiv(const APInt& RHS) const { + assert(BitWidth == RHS.BitWidth && "Bit widths must be the same"); + + // First, deal with the easy case + if (isSingleWord()) { + assert(RHS.VAL != 0 && "Divide by zero?"); + return APInt(BitWidth, VAL / RHS.VAL); + } + + // Get some facts about the LHS and RHS number of bits and words + unsigned rhsBits = RHS.getActiveBits(); + unsigned rhsWords = !rhsBits ? 0 : (APInt::whichWord(rhsBits - 1) + 1); + assert(rhsWords && "Divided by zero???"); + unsigned lhsBits = this->getActiveBits(); + unsigned lhsWords = !lhsBits ? 0 : (APInt::whichWord(lhsBits - 1) + 1); + + // Deal with some degenerate cases + if (!lhsWords) + // 0 / X ===> 0 + return APInt(BitWidth, 0); + else if (lhsWords < rhsWords || this->ult(RHS)) { + // X / Y ===> 0, iff X < Y + return APInt(BitWidth, 0); + } else if (*this == RHS) { + // X / X ===> 1 + return APInt(BitWidth, 1); + } else if (lhsWords == 1 && rhsWords == 1) { + // All high words are zero, just use native divide + return APInt(BitWidth, this->pVal[0] / RHS.pVal[0]); + } + + // We have to compute it the hard way. Invoke the Knuth divide algorithm. + APInt Quotient(1,0); // to hold result. + divide(*this, lhsWords, RHS, rhsWords, &Quotient, 0); + return Quotient; +} + +APInt APInt::urem(const APInt& RHS) const { + assert(BitWidth == RHS.BitWidth && "Bit widths must be the same"); + if (isSingleWord()) { + assert(RHS.VAL != 0 && "Remainder by zero?"); + return APInt(BitWidth, VAL % RHS.VAL); + } + + // Get some facts about the LHS + unsigned lhsBits = getActiveBits(); + unsigned lhsWords = !lhsBits ? 0 : (whichWord(lhsBits - 1) + 1); + + // Get some facts about the RHS + unsigned rhsBits = RHS.getActiveBits(); + unsigned rhsWords = !rhsBits ? 0 : (APInt::whichWord(rhsBits - 1) + 1); + assert(rhsWords && "Performing remainder operation by zero ???"); + + // Check the degenerate cases + if (lhsWords == 0) { + // 0 % Y ===> 0 + return APInt(BitWidth, 0); + } else if (lhsWords < rhsWords || this->ult(RHS)) { + // X % Y ===> X, iff X < Y + return *this; + } else if (*this == RHS) { + // X % X == 0; + return APInt(BitWidth, 0); + } else if (lhsWords == 1) { + // All high words are zero, just use native remainder + return APInt(BitWidth, pVal[0] % RHS.pVal[0]); + } + + // We have to compute it the hard way. Invoke the Knuth divide algorithm. + APInt Remainder(1,0); + divide(*this, lhsWords, RHS, rhsWords, 0, &Remainder); + return Remainder; +} + +void APInt::udivrem(const APInt &LHS, const APInt &RHS, + APInt &Quotient, APInt &Remainder) { + // Get some size facts about the dividend and divisor + unsigned lhsBits = LHS.getActiveBits(); + unsigned lhsWords = !lhsBits ? 0 : (APInt::whichWord(lhsBits - 1) + 1); + unsigned rhsBits = RHS.getActiveBits(); + unsigned rhsWords = !rhsBits ? 0 : (APInt::whichWord(rhsBits - 1) + 1); + + // Check the degenerate cases + if (lhsWords == 0) { + Quotient = 0; // 0 / Y ===> 0 + Remainder = 0; // 0 % Y ===> 0 + return; + } + + if (lhsWords < rhsWords || LHS.ult(RHS)) { + Quotient = 0; // X / Y ===> 0, iff X < Y + Remainder = LHS; // X % Y ===> X, iff X < Y + return; + } + + if (LHS == RHS) { + Quotient = 1; // X / X ===> 1 + Remainder = 0; // X % X ===> 0; + return; + } + + if (lhsWords == 1 && rhsWords == 1) { + // There is only one word to consider so use the native versions. + uint64_t lhsValue = LHS.isSingleWord() ? LHS.VAL : LHS.pVal[0]; + uint64_t rhsValue = RHS.isSingleWord() ? RHS.VAL : RHS.pVal[0]; + Quotient = APInt(LHS.getBitWidth(), lhsValue / rhsValue); + Remainder = APInt(LHS.getBitWidth(), lhsValue % rhsValue); + return; + } + + // Okay, lets do it the long way + divide(LHS, lhsWords, RHS, rhsWords, &Quotient, &Remainder); +} + +void APInt::fromString(unsigned numbits, const StringRef& str, uint8_t radix) { + // Check our assumptions here + assert(!str.empty() && "Invalid string length"); + assert((radix == 10 || radix == 8 || radix == 16 || radix == 2) && + "Radix should be 2, 8, 10, or 16!"); + + StringRef::iterator p = str.begin(); + size_t slen = str.size(); + bool isNeg = *p == '-'; + if (*p == '-' || *p == '+') { + p++; + slen--; + assert(slen && "String is only a sign, needs a value."); + } + assert((slen <= numbits || radix != 2) && "Insufficient bit width"); + assert(((slen-1)*3 <= numbits || radix != 8) && "Insufficient bit width"); + assert(((slen-1)*4 <= numbits || radix != 16) && "Insufficient bit width"); + assert((((slen-1)*64)/22 <= numbits || radix != 10) + && "Insufficient bit width"); + + // Allocate memory + if (!isSingleWord()) + pVal = getClearedMemory(getNumWords()); + + // Figure out if we can shift instead of multiply + unsigned shift = (radix == 16 ? 4 : radix == 8 ? 3 : radix == 2 ? 1 : 0); + + // Set up an APInt for the digit to add outside the loop so we don't + // constantly construct/destruct it. + APInt apdigit(getBitWidth(), 0); + APInt apradix(getBitWidth(), radix); + + // Enter digit traversal loop + for (StringRef::iterator e = str.end(); p != e; ++p) { + unsigned digit = getDigit(*p, radix); + assert(digit < radix && "Invalid character in digit string"); + + // Shift or multiply the value by the radix + if (slen > 1) { + if (shift) + *this <<= shift; + else + *this *= apradix; + } + + // Add in the digit we just interpreted + if (apdigit.isSingleWord()) + apdigit.VAL = digit; + else + apdigit.pVal[0] = digit; + *this += apdigit; + } + // If its negative, put it in two's complement form + if (isNeg) { + (*this)--; + this->flip(); + } +} + +void APInt::toString(SmallVectorImpl &Str, unsigned Radix, + bool Signed) const { + assert((Radix == 10 || Radix == 8 || Radix == 16 || Radix == 2) && + "Radix should be 2, 8, 10, or 16!"); + + // First, check for a zero value and just short circuit the logic below. + if (*this == 0) { + Str.push_back('0'); + return; + } + + static const char Digits[] = "0123456789ABCDEF"; + + if (isSingleWord()) { + char Buffer[65]; + char *BufPtr = Buffer+65; + + uint64_t N; + if (Signed) { + int64_t I = getSExtValue(); + if (I < 0) { + Str.push_back('-'); + I = -I; + } + N = I; + } else { + N = getZExtValue(); + } + + while (N) { + *--BufPtr = Digits[N % Radix]; + N /= Radix; + } + Str.append(BufPtr, Buffer+65); + return; + } + + APInt Tmp(*this); + + if (Signed && isNegative()) { + // They want to print the signed version and it is a negative value + // Flip the bits and add one to turn it into the equivalent positive + // value and put a '-' in the result. + Tmp.flip(); + Tmp++; + Str.push_back('-'); + } + + // We insert the digits backward, then reverse them to get the right order. + unsigned StartDig = Str.size(); + + // For the 2, 8 and 16 bit cases, we can just shift instead of divide + // because the number of bits per digit (1, 3 and 4 respectively) divides + // equaly. We just shift until the value is zero. + if (Radix != 10) { + // Just shift tmp right for each digit width until it becomes zero + unsigned ShiftAmt = (Radix == 16 ? 4 : (Radix == 8 ? 3 : 1)); + unsigned MaskAmt = Radix - 1; + + while (Tmp != 0) { + unsigned Digit = unsigned(Tmp.getRawData()[0]) & MaskAmt; + Str.push_back(Digits[Digit]); + Tmp = Tmp.lshr(ShiftAmt); + } + } else { + APInt divisor(4, 10); + while (Tmp != 0) { + APInt APdigit(1, 0); + APInt tmp2(Tmp.getBitWidth(), 0); + divide(Tmp, Tmp.getNumWords(), divisor, divisor.getNumWords(), &tmp2, + &APdigit); + unsigned Digit = (unsigned)APdigit.getZExtValue(); + assert(Digit < Radix && "divide failed"); + Str.push_back(Digits[Digit]); + Tmp = tmp2; + } + } + + // Reverse the digits before returning. + std::reverse(Str.begin()+StartDig, Str.end()); +} + +/// toString - This returns the APInt as a std::string. Note that this is an +/// inefficient method. It is better to pass in a SmallVector/SmallString +/// to the methods above. +std::string APInt::toString(unsigned Radix = 10, bool Signed = true) const { + SmallString<40> S; + toString(S, Radix, Signed); + return S.str(); +} + + +void APInt::dump() const { + SmallString<40> S, U; + this->toStringUnsigned(U); + this->toStringSigned(S); + errs() << "APInt(" << BitWidth << "b, " + << U.str() << "u " << S.str() << "s)"; +} + +void APInt::print(raw_ostream &OS, bool isSigned) const { + SmallString<40> S; + this->toString(S, 10, isSigned); + OS << S.str(); +} + +// This implements a variety of operations on a representation of +// arbitrary precision, two's-complement, bignum integer values. + +// Assumed by lowHalf, highHalf, partMSB and partLSB. A fairly safe +// and unrestricting assumption. +#define COMPILE_TIME_ASSERT(cond) extern int CTAssert[(cond) ? 1 : -1] +COMPILE_TIME_ASSERT(integerPartWidth % 2 == 0); + +/* Some handy functions local to this file. */ +namespace { + + /* Returns the integer part with the least significant BITS set. + BITS cannot be zero. */ + static inline integerPart + lowBitMask(unsigned int bits) + { + assert (bits != 0 && bits <= integerPartWidth); + + return ~(integerPart) 0 >> (integerPartWidth - bits); + } + + /* Returns the value of the lower half of PART. */ + static inline integerPart + lowHalf(integerPart part) + { + return part & lowBitMask(integerPartWidth / 2); + } + + /* Returns the value of the upper half of PART. */ + static inline integerPart + highHalf(integerPart part) + { + return part >> (integerPartWidth / 2); + } + + /* Returns the bit number of the most significant set bit of a part. + If the input number has no bits set -1U is returned. */ + static unsigned int + partMSB(integerPart value) + { + unsigned int n, msb; + + if (value == 0) + return -1U; + + n = integerPartWidth / 2; + + msb = 0; + do { + if (value >> n) { + value >>= n; + msb += n; + } + + n >>= 1; + } while (n); + + return msb; + } + + /* Returns the bit number of the least significant set bit of a + part. If the input number has no bits set -1U is returned. */ + static unsigned int + partLSB(integerPart value) + { + unsigned int n, lsb; + + if (value == 0) + return -1U; + + lsb = integerPartWidth - 1; + n = integerPartWidth / 2; + + do { + if (value << n) { + value <<= n; + lsb -= n; + } + + n >>= 1; + } while (n); + + return lsb; + } +} + +/* Sets the least significant part of a bignum to the input value, and + zeroes out higher parts. */ +void +APInt::tcSet(integerPart *dst, integerPart part, unsigned int parts) +{ + unsigned int i; + + assert (parts > 0); + + dst[0] = part; + for(i = 1; i < parts; i++) + dst[i] = 0; +} + +/* Assign one bignum to another. */ +void +APInt::tcAssign(integerPart *dst, const integerPart *src, unsigned int parts) +{ + unsigned int i; + + for(i = 0; i < parts; i++) + dst[i] = src[i]; +} + +/* Returns true if a bignum is zero, false otherwise. */ +bool +APInt::tcIsZero(const integerPart *src, unsigned int parts) +{ + unsigned int i; + + for(i = 0; i < parts; i++) + if (src[i]) + return false; + + return true; +} + +/* Extract the given bit of a bignum; returns 0 or 1. */ +int +APInt::tcExtractBit(const integerPart *parts, unsigned int bit) +{ + return(parts[bit / integerPartWidth] + & ((integerPart) 1 << bit % integerPartWidth)) != 0; +} + +/* Set the given bit of a bignum. */ +void +APInt::tcSetBit(integerPart *parts, unsigned int bit) +{ + parts[bit / integerPartWidth] |= (integerPart) 1 << (bit % integerPartWidth); +} + +/* Returns the bit number of the least significant set bit of a + number. If the input number has no bits set -1U is returned. */ +unsigned int +APInt::tcLSB(const integerPart *parts, unsigned int n) +{ + unsigned int i, lsb; + + for(i = 0; i < n; i++) { + if (parts[i] != 0) { + lsb = partLSB(parts[i]); + + return lsb + i * integerPartWidth; + } + } + + return -1U; +} + +/* Returns the bit number of the most significant set bit of a number. + If the input number has no bits set -1U is returned. */ +unsigned int +APInt::tcMSB(const integerPart *parts, unsigned int n) +{ + unsigned int msb; + + do { + --n; + + if (parts[n] != 0) { + msb = partMSB(parts[n]); + + return msb + n * integerPartWidth; + } + } while (n); + + return -1U; +} + +/* Copy the bit vector of width srcBITS from SRC, starting at bit + srcLSB, to DST, of dstCOUNT parts, such that the bit srcLSB becomes + the least significant bit of DST. All high bits above srcBITS in + DST are zero-filled. */ +void +APInt::tcExtract(integerPart *dst, unsigned int dstCount,const integerPart *src, + unsigned int srcBits, unsigned int srcLSB) +{ + unsigned int firstSrcPart, dstParts, shift, n; + + dstParts = (srcBits + integerPartWidth - 1) / integerPartWidth; + assert (dstParts <= dstCount); + + firstSrcPart = srcLSB / integerPartWidth; + tcAssign (dst, src + firstSrcPart, dstParts); + + shift = srcLSB % integerPartWidth; + tcShiftRight (dst, dstParts, shift); + + /* We now have (dstParts * integerPartWidth - shift) bits from SRC + in DST. If this is less that srcBits, append the rest, else + clear the high bits. */ + n = dstParts * integerPartWidth - shift; + if (n < srcBits) { + integerPart mask = lowBitMask (srcBits - n); + dst[dstParts - 1] |= ((src[firstSrcPart + dstParts] & mask) + << n % integerPartWidth); + } else if (n > srcBits) { + if (srcBits % integerPartWidth) + dst[dstParts - 1] &= lowBitMask (srcBits % integerPartWidth); + } + + /* Clear high parts. */ + while (dstParts < dstCount) + dst[dstParts++] = 0; +} + +/* DST += RHS + C where C is zero or one. Returns the carry flag. */ +integerPart +APInt::tcAdd(integerPart *dst, const integerPart *rhs, + integerPart c, unsigned int parts) +{ + unsigned int i; + + assert(c <= 1); + + for(i = 0; i < parts; i++) { + integerPart l; + + l = dst[i]; + if (c) { + dst[i] += rhs[i] + 1; + c = (dst[i] <= l); + } else { + dst[i] += rhs[i]; + c = (dst[i] < l); + } + } + + return c; +} + +/* DST -= RHS + C where C is zero or one. Returns the carry flag. */ +integerPart +APInt::tcSubtract(integerPart *dst, const integerPart *rhs, + integerPart c, unsigned int parts) +{ + unsigned int i; + + assert(c <= 1); + + for(i = 0; i < parts; i++) { + integerPart l; + + l = dst[i]; + if (c) { + dst[i] -= rhs[i] + 1; + c = (dst[i] >= l); + } else { + dst[i] -= rhs[i]; + c = (dst[i] > l); + } + } + + return c; +} + +/* Negate a bignum in-place. */ +void +APInt::tcNegate(integerPart *dst, unsigned int parts) +{ + tcComplement(dst, parts); + tcIncrement(dst, parts); +} + +/* DST += SRC * MULTIPLIER + CARRY if add is true + DST = SRC * MULTIPLIER + CARRY if add is false + + Requires 0 <= DSTPARTS <= SRCPARTS + 1. If DST overlaps SRC + they must start at the same point, i.e. DST == SRC. + + If DSTPARTS == SRCPARTS + 1 no overflow occurs and zero is + returned. Otherwise DST is filled with the least significant + DSTPARTS parts of the result, and if all of the omitted higher + parts were zero return zero, otherwise overflow occurred and + return one. */ +int +APInt::tcMultiplyPart(integerPart *dst, const integerPart *src, + integerPart multiplier, integerPart carry, + unsigned int srcParts, unsigned int dstParts, + bool add) +{ + unsigned int i, n; + + /* Otherwise our writes of DST kill our later reads of SRC. */ + assert(dst <= src || dst >= src + srcParts); + assert(dstParts <= srcParts + 1); + + /* N loops; minimum of dstParts and srcParts. */ + n = dstParts < srcParts ? dstParts: srcParts; + + for(i = 0; i < n; i++) { + integerPart low, mid, high, srcPart; + + /* [ LOW, HIGH ] = MULTIPLIER * SRC[i] + DST[i] + CARRY. + + This cannot overflow, because + + (n - 1) * (n - 1) + 2 (n - 1) = (n - 1) * (n + 1) + + which is less than n^2. */ + + srcPart = src[i]; + + if (multiplier == 0 || srcPart == 0) { + low = carry; + high = 0; + } else { + low = lowHalf(srcPart) * lowHalf(multiplier); + high = highHalf(srcPart) * highHalf(multiplier); + + mid = lowHalf(srcPart) * highHalf(multiplier); + high += highHalf(mid); + mid <<= integerPartWidth / 2; + if (low + mid < low) + high++; + low += mid; + + mid = highHalf(srcPart) * lowHalf(multiplier); + high += highHalf(mid); + mid <<= integerPartWidth / 2; + if (low + mid < low) + high++; + low += mid; + + /* Now add carry. */ + if (low + carry < low) + high++; + low += carry; + } + + if (add) { + /* And now DST[i], and store the new low part there. */ + if (low + dst[i] < low) + high++; + dst[i] += low; + } else + dst[i] = low; + + carry = high; + } + + if (i < dstParts) { + /* Full multiplication, there is no overflow. */ + assert(i + 1 == dstParts); + dst[i] = carry; + return 0; + } else { + /* We overflowed if there is carry. */ + if (carry) + return 1; + + /* We would overflow if any significant unwritten parts would be + non-zero. This is true if any remaining src parts are non-zero + and the multiplier is non-zero. */ + if (multiplier) + for(; i < srcParts; i++) + if (src[i]) + return 1; + + /* We fitted in the narrow destination. */ + return 0; + } +} + +/* DST = LHS * RHS, where DST has the same width as the operands and + is filled with the least significant parts of the result. Returns + one if overflow occurred, otherwise zero. DST must be disjoint + from both operands. */ +int +APInt::tcMultiply(integerPart *dst, const integerPart *lhs, + const integerPart *rhs, unsigned int parts) +{ + unsigned int i; + int overflow; + + assert(dst != lhs && dst != rhs); + + overflow = 0; + tcSet(dst, 0, parts); + + for(i = 0; i < parts; i++) + overflow |= tcMultiplyPart(&dst[i], lhs, rhs[i], 0, parts, + parts - i, true); + + return overflow; +} + +/* DST = LHS * RHS, where DST has width the sum of the widths of the + operands. No overflow occurs. DST must be disjoint from both + operands. Returns the number of parts required to hold the + result. */ +unsigned int +APInt::tcFullMultiply(integerPart *dst, const integerPart *lhs, + const integerPart *rhs, unsigned int lhsParts, + unsigned int rhsParts) +{ + /* Put the narrower number on the LHS for less loops below. */ + if (lhsParts > rhsParts) { + return tcFullMultiply (dst, rhs, lhs, rhsParts, lhsParts); + } else { + unsigned int n; + + assert(dst != lhs && dst != rhs); + + tcSet(dst, 0, rhsParts); + + for(n = 0; n < lhsParts; n++) + tcMultiplyPart(&dst[n], rhs, lhs[n], 0, rhsParts, rhsParts + 1, true); + + n = lhsParts + rhsParts; + + return n - (dst[n - 1] == 0); + } +} + +/* If RHS is zero LHS and REMAINDER are left unchanged, return one. + Otherwise set LHS to LHS / RHS with the fractional part discarded, + set REMAINDER to the remainder, return zero. i.e. + + OLD_LHS = RHS * LHS + REMAINDER + + SCRATCH is a bignum of the same size as the operands and result for + use by the routine; its contents need not be initialized and are + destroyed. LHS, REMAINDER and SCRATCH must be distinct. +*/ +int +APInt::tcDivide(integerPart *lhs, const integerPart *rhs, + integerPart *remainder, integerPart *srhs, + unsigned int parts) +{ + unsigned int n, shiftCount; + integerPart mask; + + assert(lhs != remainder && lhs != srhs && remainder != srhs); + + shiftCount = tcMSB(rhs, parts) + 1; + if (shiftCount == 0) + return true; + + shiftCount = parts * integerPartWidth - shiftCount; + n = shiftCount / integerPartWidth; + mask = (integerPart) 1 << (shiftCount % integerPartWidth); + + tcAssign(srhs, rhs, parts); + tcShiftLeft(srhs, parts, shiftCount); + tcAssign(remainder, lhs, parts); + tcSet(lhs, 0, parts); + + /* Loop, subtracting SRHS if REMAINDER is greater and adding that to + the total. */ + for(;;) { + int compare; + + compare = tcCompare(remainder, srhs, parts); + if (compare >= 0) { + tcSubtract(remainder, srhs, 0, parts); + lhs[n] |= mask; + } + + if (shiftCount == 0) + break; + shiftCount--; + tcShiftRight(srhs, parts, 1); + if ((mask >>= 1) == 0) + mask = (integerPart) 1 << (integerPartWidth - 1), n--; + } + + return false; +} + +/* Shift a bignum left COUNT bits in-place. Shifted in bits are zero. + There are no restrictions on COUNT. */ +void +APInt::tcShiftLeft(integerPart *dst, unsigned int parts, unsigned int count) +{ + if (count) { + unsigned int jump, shift; + + /* Jump is the inter-part jump; shift is is intra-part shift. */ + jump = count / integerPartWidth; + shift = count % integerPartWidth; + + while (parts > jump) { + integerPart part; + + parts--; + + /* dst[i] comes from the two parts src[i - jump] and, if we have + an intra-part shift, src[i - jump - 1]. */ + part = dst[parts - jump]; + if (shift) { + part <<= shift; + if (parts >= jump + 1) + part |= dst[parts - jump - 1] >> (integerPartWidth - shift); + } + + dst[parts] = part; + } + + while (parts > 0) + dst[--parts] = 0; + } +} + +/* Shift a bignum right COUNT bits in-place. Shifted in bits are + zero. There are no restrictions on COUNT. */ +void +APInt::tcShiftRight(integerPart *dst, unsigned int parts, unsigned int count) +{ + if (count) { + unsigned int i, jump, shift; + + /* Jump is the inter-part jump; shift is is intra-part shift. */ + jump = count / integerPartWidth; + shift = count % integerPartWidth; + + /* Perform the shift. This leaves the most significant COUNT bits + of the result at zero. */ + for(i = 0; i < parts; i++) { + integerPart part; + + if (i + jump >= parts) { + part = 0; + } else { + part = dst[i + jump]; + if (shift) { + part >>= shift; + if (i + jump + 1 < parts) + part |= dst[i + jump + 1] << (integerPartWidth - shift); + } + } + + dst[i] = part; + } + } +} + +/* Bitwise and of two bignums. */ +void +APInt::tcAnd(integerPart *dst, const integerPart *rhs, unsigned int parts) +{ + unsigned int i; + + for(i = 0; i < parts; i++) + dst[i] &= rhs[i]; +} + +/* Bitwise inclusive or of two bignums. */ +void +APInt::tcOr(integerPart *dst, const integerPart *rhs, unsigned int parts) +{ + unsigned int i; + + for(i = 0; i < parts; i++) + dst[i] |= rhs[i]; +} + +/* Bitwise exclusive or of two bignums. */ +void +APInt::tcXor(integerPart *dst, const integerPart *rhs, unsigned int parts) +{ + unsigned int i; + + for(i = 0; i < parts; i++) + dst[i] ^= rhs[i]; +} + +/* Complement a bignum in-place. */ +void +APInt::tcComplement(integerPart *dst, unsigned int parts) +{ + unsigned int i; + + for(i = 0; i < parts; i++) + dst[i] = ~dst[i]; +} + +/* Comparison (unsigned) of two bignums. */ +int +APInt::tcCompare(const integerPart *lhs, const integerPart *rhs, + unsigned int parts) +{ + while (parts) { + parts--; + if (lhs[parts] == rhs[parts]) + continue; + + if (lhs[parts] > rhs[parts]) + return 1; + else + return -1; + } + + return 0; +} + +/* Increment a bignum in-place, return the carry flag. */ +integerPart +APInt::tcIncrement(integerPart *dst, unsigned int parts) +{ + unsigned int i; + + for(i = 0; i < parts; i++) + if (++dst[i] != 0) + break; + + return i == parts; +} + +/* Set the least significant BITS bits of a bignum, clear the + rest. */ +void +APInt::tcSetLeastSignificantBits(integerPart *dst, unsigned int parts, + unsigned int bits) +{ + unsigned int i; + + i = 0; + while (bits > integerPartWidth) { + dst[i++] = ~(integerPart) 0; + bits -= integerPartWidth; + } + + if (bits) + dst[i++] = ~(integerPart) 0 >> (integerPartWidth - bits); + + while (i < parts) + dst[i++] = 0; +} diff --git a/libclamav/c++/llvm/lib/Support/APSInt.cpp b/libclamav/c++/llvm/lib/Support/APSInt.cpp new file mode 100644 index 000000000..73acafa69 --- /dev/null +++ b/libclamav/c++/llvm/lib/Support/APSInt.cpp @@ -0,0 +1,23 @@ +//===-- llvm/ADT/APSInt.cpp - Arbitrary Precision Signed Int ---*- 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 the APSInt class, which is a simple class that +// represents an arbitrary sized integer that knows its signedness. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/APSInt.h" +#include "llvm/ADT/FoldingSet.h" + +using namespace llvm; + +void APSInt::Profile(FoldingSetNodeID& ID) const { + ID.AddInteger((unsigned) (IsUnsigned ? 1 : 0)); + APInt::Profile(ID); +} diff --git a/libclamav/c++/llvm/lib/Support/Allocator.cpp b/libclamav/c++/llvm/lib/Support/Allocator.cpp new file mode 100644 index 000000000..31b45c8d4 --- /dev/null +++ b/libclamav/c++/llvm/lib/Support/Allocator.cpp @@ -0,0 +1,171 @@ +//===--- Allocator.cpp - Simple memory allocation abstraction -------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the BumpPtrAllocator interface. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/Allocator.h" +#include "llvm/System/DataTypes.h" +#include "llvm/Support/Recycler.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/System/Memory.h" +#include + +namespace llvm { + +BumpPtrAllocator::BumpPtrAllocator(size_t size, size_t threshold, + SlabAllocator &allocator) + : SlabSize(size), SizeThreshold(threshold), Allocator(allocator), + CurSlab(0), BytesAllocated(0) { + StartNewSlab(); +} + +BumpPtrAllocator::~BumpPtrAllocator() { + DeallocateSlabs(CurSlab); +} + +/// AlignPtr - Align Ptr to Alignment bytes, rounding up. Alignment should +/// be a power of two. This method rounds up, so AlignPtr(7, 4) == 8 and +/// AlignPtr(8, 4) == 8. +char *BumpPtrAllocator::AlignPtr(char *Ptr, size_t Alignment) { + assert(Alignment && (Alignment & (Alignment - 1)) == 0 && + "Alignment is not a power of two!"); + + // Do the alignment. + return (char*)(((uintptr_t)Ptr + Alignment - 1) & + ~(uintptr_t)(Alignment - 1)); +} + +/// StartNewSlab - Allocate a new slab and move the bump pointers over into +/// the new slab. Modifies CurPtr and End. +void BumpPtrAllocator::StartNewSlab() { + MemSlab *NewSlab = Allocator.Allocate(SlabSize); + NewSlab->NextPtr = CurSlab; + CurSlab = NewSlab; + CurPtr = (char*)(CurSlab + 1); + End = ((char*)CurSlab) + CurSlab->Size; +} + +/// DeallocateSlabs - Deallocate all memory slabs after and including this +/// one. +void BumpPtrAllocator::DeallocateSlabs(MemSlab *Slab) { + while (Slab) { + MemSlab *NextSlab = Slab->NextPtr; +#ifndef NDEBUG + // Poison the memory so stale pointers crash sooner. Note we must + // preserve the Size and NextPtr fields at the beginning. + sys::Memory::setRangeWritable(Slab + 1, Slab->Size - sizeof(MemSlab)); + memset(Slab + 1, 0xCD, Slab->Size - sizeof(MemSlab)); +#endif + Allocator.Deallocate(Slab); + Slab = NextSlab; + } +} + +/// Reset - Deallocate all but the current slab and reset the current pointer +/// to the beginning of it, freeing all memory allocated so far. +void BumpPtrAllocator::Reset() { + DeallocateSlabs(CurSlab->NextPtr); + CurSlab->NextPtr = 0; + CurPtr = (char*)(CurSlab + 1); + End = ((char*)CurSlab) + CurSlab->Size; +} + +/// Allocate - Allocate space at the specified alignment. +/// +void *BumpPtrAllocator::Allocate(size_t Size, size_t Alignment) { + // Keep track of how many bytes we've allocated. + BytesAllocated += Size; + + // 0-byte alignment means 1-byte alignment. + if (Alignment == 0) Alignment = 1; + + // Allocate the aligned space, going forwards from CurPtr. + char *Ptr = AlignPtr(CurPtr, Alignment); + + // Check if we can hold it. + if (Ptr + Size <= End) { + CurPtr = Ptr + Size; + return Ptr; + } + + // If Size is really big, allocate a separate slab for it. + size_t PaddedSize = Size + sizeof(MemSlab) + Alignment - 1; + if (PaddedSize > SizeThreshold) { + MemSlab *NewSlab = Allocator.Allocate(PaddedSize); + + // Put the new slab after the current slab, since we are not allocating + // into it. + NewSlab->NextPtr = CurSlab->NextPtr; + CurSlab->NextPtr = NewSlab; + + Ptr = AlignPtr((char*)(NewSlab + 1), Alignment); + assert((uintptr_t)Ptr + Size <= (uintptr_t)NewSlab + NewSlab->Size); + return Ptr; + } + + // Otherwise, start a new slab and try again. + StartNewSlab(); + Ptr = AlignPtr(CurPtr, Alignment); + CurPtr = Ptr + Size; + assert(CurPtr <= End && "Unable to allocate memory!"); + return Ptr; +} + +unsigned BumpPtrAllocator::GetNumSlabs() const { + unsigned NumSlabs = 0; + for (MemSlab *Slab = CurSlab; Slab != 0; Slab = Slab->NextPtr) { + ++NumSlabs; + } + return NumSlabs; +} + +void BumpPtrAllocator::PrintStats() const { + unsigned NumSlabs = 0; + size_t TotalMemory = 0; + for (MemSlab *Slab = CurSlab; Slab != 0; Slab = Slab->NextPtr) { + TotalMemory += Slab->Size; + ++NumSlabs; + } + + errs() << "\nNumber of memory regions: " << NumSlabs << '\n' + << "Bytes used: " << BytesAllocated << '\n' + << "Bytes allocated: " << TotalMemory << '\n' + << "Bytes wasted: " << (TotalMemory - BytesAllocated) + << " (includes alignment, etc)\n"; +} + +MallocSlabAllocator BumpPtrAllocator::DefaultSlabAllocator = + MallocSlabAllocator(); + +SlabAllocator::~SlabAllocator() { } + +MallocSlabAllocator::~MallocSlabAllocator() { } + +MemSlab *MallocSlabAllocator::Allocate(size_t Size) { + MemSlab *Slab = (MemSlab*)Allocator.Allocate(Size, 0); + Slab->Size = Size; + Slab->NextPtr = 0; + return Slab; +} + +void MallocSlabAllocator::Deallocate(MemSlab *Slab) { + Allocator.Deallocate(Slab); +} + +void PrintRecyclerStats(size_t Size, + size_t Align, + size_t FreeListSize) { + errs() << "Recycler element size: " << Size << '\n' + << "Recycler element alignment: " << Align << '\n' + << "Number of elements free for recycling: " << FreeListSize << '\n'; +} + +} diff --git a/libclamav/c++/llvm/lib/Support/CMakeLists.txt b/libclamav/c++/llvm/lib/Support/CMakeLists.txt new file mode 100644 index 000000000..cd355ffe3 --- /dev/null +++ b/libclamav/c++/llvm/lib/Support/CMakeLists.txt @@ -0,0 +1,45 @@ +add_llvm_library(LLVMSupport + APFloat.cpp + APInt.cpp + APSInt.cpp + Allocator.cpp + CommandLine.cpp + ConstantRange.cpp + Debug.cpp + Dwarf.cpp + ErrorHandling.cpp + FileUtilities.cpp + FoldingSet.cpp + FormattedStream.cpp + GraphWriter.cpp + IsInf.cpp + IsNAN.cpp + ManagedStatic.cpp + MemoryBuffer.cpp + MemoryObject.cpp + PluginLoader.cpp + PrettyStackTrace.cpp + Regex.cpp + SlowOperationInformer.cpp + SmallPtrSet.cpp + SourceMgr.cpp + Statistic.cpp + StringExtras.cpp + StringMap.cpp + StringPool.cpp + StringRef.cpp + SystemUtils.cpp + TargetRegistry.cpp + Timer.cpp + Triple.cpp + Twine.cpp + raw_os_ostream.cpp + raw_ostream.cpp + regcomp.c + regerror.c + regexec.c + regfree.c + regstrlcpy.c + ) + +target_link_libraries (LLVMSupport LLVMSystem) diff --git a/libclamav/c++/llvm/lib/Support/COPYRIGHT.regex b/libclamav/c++/llvm/lib/Support/COPYRIGHT.regex new file mode 100644 index 000000000..a6392fd37 --- /dev/null +++ b/libclamav/c++/llvm/lib/Support/COPYRIGHT.regex @@ -0,0 +1,54 @@ +$OpenBSD: COPYRIGHT,v 1.3 2003/06/02 20:18:36 millert Exp $ + +Copyright 1992, 1993, 1994 Henry Spencer. All rights reserved. +This software is not subject to any license of the American Telephone +and Telegraph Company or of the Regents of the University of California. + +Permission is granted to anyone to use this software for any purpose on +any computer system, and to alter it and redistribute it, subject +to the following restrictions: + +1. The author is not responsible for the consequences of use of this + software, no matter how awful, even if they arise from flaws in it. + +2. The origin of this software must not be misrepresented, either by + explicit claim or by omission. Since few users ever read sources, + credits must appear in the documentation. + +3. Altered versions must be plainly marked as such, and must not be + misrepresented as being the original software. Since few users + ever read sources, credits must appear in the documentation. + +4. This notice may not be removed or altered. + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +/*- + * Copyright (c) 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)COPYRIGHT 8.1 (Berkeley) 3/16/94 + */ diff --git a/libclamav/c++/llvm/lib/Support/CommandLine.cpp b/libclamav/c++/llvm/lib/Support/CommandLine.cpp new file mode 100644 index 000000000..9cf9c894d --- /dev/null +++ b/libclamav/c++/llvm/lib/Support/CommandLine.cpp @@ -0,0 +1,1235 @@ +//===-- CommandLine.cpp - Command line parser implementation --------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This class implements a command line argument processor that is useful when +// creating a tool. It provides a simple, minimalistic interface that is easily +// extensible and supports nonlocal (library) command line options. +// +// Note that rather than trying to figure out what this code does, you could try +// reading the library documentation located in docs/CommandLine.html +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/ManagedStatic.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Target/TargetRegistry.h" +#include "llvm/System/Host.h" +#include "llvm/System/Path.h" +#include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/Twine.h" +#include "llvm/Config/config.h" +#include +#include +using namespace llvm; +using namespace cl; + +//===----------------------------------------------------------------------===// +// Template instantiations and anchors. +// +namespace llvm { namespace cl { +TEMPLATE_INSTANTIATION(class basic_parser); +TEMPLATE_INSTANTIATION(class basic_parser); +TEMPLATE_INSTANTIATION(class basic_parser); +TEMPLATE_INSTANTIATION(class basic_parser); +TEMPLATE_INSTANTIATION(class basic_parser); +TEMPLATE_INSTANTIATION(class basic_parser); +TEMPLATE_INSTANTIATION(class basic_parser); +TEMPLATE_INSTANTIATION(class basic_parser); + +TEMPLATE_INSTANTIATION(class opt); +TEMPLATE_INSTANTIATION(class opt); +TEMPLATE_INSTANTIATION(class opt); +TEMPLATE_INSTANTIATION(class opt); +TEMPLATE_INSTANTIATION(class opt); +} } // end namespace llvm::cl + +void Option::anchor() {} +void basic_parser_impl::anchor() {} +void parser::anchor() {} +void parser::anchor() {} +void parser::anchor() {} +void parser::anchor() {} +void parser::anchor() {} +void parser::anchor() {} +void parser::anchor() {} +void parser::anchor() {} + +//===----------------------------------------------------------------------===// + +// Globals for name and overview of program. Program name is not a string to +// avoid static ctor/dtor issues. +static char ProgramName[80] = ""; +static const char *ProgramOverview = 0; + +// This collects additional help to be printed. +static ManagedStatic > MoreHelp; + +extrahelp::extrahelp(const char *Help) + : morehelp(Help) { + MoreHelp->push_back(Help); +} + +static bool OptionListChanged = false; + +// MarkOptionsChanged - Internal helper function. +void cl::MarkOptionsChanged() { + OptionListChanged = true; +} + +/// RegisteredOptionList - This is the list of the command line options that +/// have statically constructed themselves. +static Option *RegisteredOptionList = 0; + +void Option::addArgument() { + assert(NextRegistered == 0 && "argument multiply registered!"); + + NextRegistered = RegisteredOptionList; + RegisteredOptionList = this; + MarkOptionsChanged(); +} + + +//===----------------------------------------------------------------------===// +// Basic, shared command line option processing machinery. +// + +/// GetOptionInfo - Scan the list of registered options, turning them into data +/// structures that are easier to handle. +static void GetOptionInfo(SmallVectorImpl &PositionalOpts, + SmallVectorImpl &SinkOpts, + StringMap &OptionsMap) { + SmallVector OptionNames; + Option *CAOpt = 0; // The ConsumeAfter option if it exists. + for (Option *O = RegisteredOptionList; O; O = O->getNextRegisteredOption()) { + // If this option wants to handle multiple option names, get the full set. + // This handles enum options like "-O1 -O2" etc. + O->getExtraOptionNames(OptionNames); + if (O->ArgStr[0]) + OptionNames.push_back(O->ArgStr); + + // Handle named options. + for (size_t i = 0, e = OptionNames.size(); i != e; ++i) { + // Add argument to the argument map! + if (OptionsMap.GetOrCreateValue(OptionNames[i], O).second != O) { + errs() << ProgramName << ": CommandLine Error: Argument '" + << OptionNames[i] << "' defined more than once!\n"; + } + } + + OptionNames.clear(); + + // Remember information about positional options. + if (O->getFormattingFlag() == cl::Positional) + PositionalOpts.push_back(O); + else if (O->getMiscFlags() & cl::Sink) // Remember sink options + SinkOpts.push_back(O); + else if (O->getNumOccurrencesFlag() == cl::ConsumeAfter) { + if (CAOpt) + O->error("Cannot specify more than one option with cl::ConsumeAfter!"); + CAOpt = O; + } + } + + if (CAOpt) + PositionalOpts.push_back(CAOpt); + + // Make sure that they are in order of registration not backwards. + std::reverse(PositionalOpts.begin(), PositionalOpts.end()); +} + + +/// LookupOption - Lookup the option specified by the specified option on the +/// command line. If there is a value specified (after an equal sign) return +/// that as well. This assumes that leading dashes have already been stripped. +static Option *LookupOption(StringRef &Arg, StringRef &Value, + const StringMap &OptionsMap) { + // Reject all dashes. + if (Arg.empty()) return 0; + + size_t EqualPos = Arg.find('='); + + // If we have an equals sign, remember the value. + if (EqualPos == StringRef::npos) { + // Look up the option. + StringMap::const_iterator I = OptionsMap.find(Arg); + return I != OptionsMap.end() ? I->second : 0; + } + + // If the argument before the = is a valid option name, we match. If not, + // return Arg unmolested. + StringMap::const_iterator I = + OptionsMap.find(Arg.substr(0, EqualPos)); + if (I == OptionsMap.end()) return 0; + + Value = Arg.substr(EqualPos+1); + Arg = Arg.substr(0, EqualPos); + return I->second; +} + +/// CommaSeparateAndAddOccurence - A wrapper around Handler->addOccurence() that +/// does special handling of cl::CommaSeparated options. +static bool CommaSeparateAndAddOccurence(Option *Handler, unsigned pos, + StringRef ArgName, + StringRef Value, bool MultiArg = false) +{ + // Check to see if this option accepts a comma separated list of values. If + // it does, we have to split up the value into multiple values. + if (Handler->getMiscFlags() & CommaSeparated) { + StringRef Val(Value); + StringRef::size_type Pos = Val.find(','); + + while (Pos != StringRef::npos) { + // Process the portion before the comma. + if (Handler->addOccurrence(pos, ArgName, Val.substr(0, Pos), MultiArg)) + return true; + // Erase the portion before the comma, AND the comma. + Val = Val.substr(Pos+1); + Value.substr(Pos+1); // Increment the original value pointer as well. + // Check for another comma. + Pos = Val.find(','); + } + + Value = Val; + } + + if (Handler->addOccurrence(pos, ArgName, Value, MultiArg)) + return true; + + return false; +} + +/// ProvideOption - For Value, this differentiates between an empty value ("") +/// and a null value (StringRef()). The later is accepted for arguments that +/// don't allow a value (-foo) the former is rejected (-foo=). +static inline bool ProvideOption(Option *Handler, StringRef ArgName, + StringRef Value, int argc, char **argv, + int &i) { + // Is this a multi-argument option? + unsigned NumAdditionalVals = Handler->getNumAdditionalVals(); + + // Enforce value requirements + switch (Handler->getValueExpectedFlag()) { + case ValueRequired: + if (Value.data() == 0) { // No value specified? + if (i+1 >= argc) + return Handler->error("requires a value!"); + // Steal the next argument, like for '-o filename' + Value = argv[++i]; + } + break; + case ValueDisallowed: + if (NumAdditionalVals > 0) + return Handler->error("multi-valued option specified" + " with ValueDisallowed modifier!"); + + if (Value.data()) + return Handler->error("does not allow a value! '" + + Twine(Value) + "' specified."); + break; + case ValueOptional: + break; + + default: + errs() << ProgramName + << ": Bad ValueMask flag! CommandLine usage error:" + << Handler->getValueExpectedFlag() << "\n"; + llvm_unreachable(0); + } + + // If this isn't a multi-arg option, just run the handler. + if (NumAdditionalVals == 0) + return CommaSeparateAndAddOccurence(Handler, i, ArgName, Value); + + // If it is, run the handle several times. + bool MultiArg = false; + + if (Value.data()) { + if (CommaSeparateAndAddOccurence(Handler, i, ArgName, Value, MultiArg)) + return true; + --NumAdditionalVals; + MultiArg = true; + } + + while (NumAdditionalVals > 0) { + if (i+1 >= argc) + return Handler->error("not enough values!"); + Value = argv[++i]; + + if (CommaSeparateAndAddOccurence(Handler, i, ArgName, Value, MultiArg)) + return true; + MultiArg = true; + --NumAdditionalVals; + } + return false; +} + +static bool ProvidePositionalOption(Option *Handler, StringRef Arg, int i) { + int Dummy = i; + return ProvideOption(Handler, Handler->ArgStr, Arg, 0, 0, Dummy); +} + + +// Option predicates... +static inline bool isGrouping(const Option *O) { + return O->getFormattingFlag() == cl::Grouping; +} +static inline bool isPrefixedOrGrouping(const Option *O) { + return isGrouping(O) || O->getFormattingFlag() == cl::Prefix; +} + +// getOptionPred - Check to see if there are any options that satisfy the +// specified predicate with names that are the prefixes in Name. This is +// checked by progressively stripping characters off of the name, checking to +// see if there options that satisfy the predicate. If we find one, return it, +// otherwise return null. +// +static Option *getOptionPred(StringRef Name, size_t &Length, + bool (*Pred)(const Option*), + const StringMap &OptionsMap) { + + StringMap::const_iterator OMI = OptionsMap.find(Name); + + // Loop while we haven't found an option and Name still has at least two + // characters in it (so that the next iteration will not be the empty + // string. + while (OMI == OptionsMap.end() && Name.size() > 1) { + Name = Name.substr(0, Name.size()-1); // Chop off the last character. + OMI = OptionsMap.find(Name); + } + + if (OMI != OptionsMap.end() && Pred(OMI->second)) { + Length = Name.size(); + return OMI->second; // Found one! + } + return 0; // No option found! +} + +/// HandlePrefixedOrGroupedOption - The specified argument string (which started +/// with at least one '-') does not fully match an available option. Check to +/// see if this is a prefix or grouped option. If so, split arg into output an +/// Arg/Value pair and return the Option to parse it with. +static Option *HandlePrefixedOrGroupedOption(StringRef &Arg, StringRef &Value, + bool &ErrorParsing, + const StringMap &OptionsMap) { + if (Arg.size() == 1) return 0; + + // Do the lookup! + size_t Length = 0; + Option *PGOpt = getOptionPred(Arg, Length, isPrefixedOrGrouping, OptionsMap); + if (PGOpt == 0) return 0; + + // If the option is a prefixed option, then the value is simply the + // rest of the name... so fall through to later processing, by + // setting up the argument name flags and value fields. + if (PGOpt->getFormattingFlag() == cl::Prefix) { + Value = Arg.substr(Length); + Arg = Arg.substr(0, Length); + assert(OptionsMap.count(Arg) && OptionsMap.find(Arg)->second == PGOpt); + return PGOpt; + } + + // This must be a grouped option... handle them now. Grouping options can't + // have values. + assert(isGrouping(PGOpt) && "Broken getOptionPred!"); + + do { + // Move current arg name out of Arg into OneArgName. + StringRef OneArgName = Arg.substr(0, Length); + Arg = Arg.substr(Length); + + // Because ValueRequired is an invalid flag for grouped arguments, + // we don't need to pass argc/argv in. + assert(PGOpt->getValueExpectedFlag() != cl::ValueRequired && + "Option can not be cl::Grouping AND cl::ValueRequired!"); + int Dummy; + ErrorParsing |= ProvideOption(PGOpt, OneArgName, + StringRef(), 0, 0, Dummy); + + // Get the next grouping option. + PGOpt = getOptionPred(Arg, Length, isGrouping, OptionsMap); + } while (PGOpt && Length != Arg.size()); + + // Return the last option with Arg cut down to just the last one. + return PGOpt; +} + + + +static bool RequiresValue(const Option *O) { + return O->getNumOccurrencesFlag() == cl::Required || + O->getNumOccurrencesFlag() == cl::OneOrMore; +} + +static bool EatsUnboundedNumberOfValues(const Option *O) { + return O->getNumOccurrencesFlag() == cl::ZeroOrMore || + O->getNumOccurrencesFlag() == cl::OneOrMore; +} + +/// ParseCStringVector - Break INPUT up wherever one or more +/// whitespace characters are found, and store the resulting tokens in +/// OUTPUT. The tokens stored in OUTPUT are dynamically allocated +/// using strdup(), so it is the caller's responsibility to free() +/// them later. +/// +static void ParseCStringVector(std::vector &OutputVector, + const char *Input) { + // Characters which will be treated as token separators: + StringRef Delims = " \v\f\t\r\n"; + + StringRef WorkStr(Input); + while (!WorkStr.empty()) { + // If the first character is a delimiter, strip them off. + if (Delims.find(WorkStr[0]) != StringRef::npos) { + size_t Pos = WorkStr.find_first_not_of(Delims); + if (Pos == StringRef::npos) Pos = WorkStr.size(); + WorkStr = WorkStr.substr(Pos); + continue; + } + + // Find position of first delimiter. + size_t Pos = WorkStr.find_first_of(Delims); + if (Pos == StringRef::npos) Pos = WorkStr.size(); + + // Everything from 0 to Pos is the next word to copy. + char *NewStr = (char*)malloc(Pos+1); + memcpy(NewStr, WorkStr.data(), Pos); + NewStr[Pos] = 0; + OutputVector.push_back(NewStr); + + WorkStr = WorkStr.substr(Pos); + } +} + +/// ParseEnvironmentOptions - An alternative entry point to the +/// CommandLine library, which allows you to read the program's name +/// from the caller (as PROGNAME) and its command-line arguments from +/// an environment variable (whose name is given in ENVVAR). +/// +void cl::ParseEnvironmentOptions(const char *progName, const char *envVar, + const char *Overview, bool ReadResponseFiles) { + // Check args. + assert(progName && "Program name not specified"); + assert(envVar && "Environment variable name missing"); + + // Get the environment variable they want us to parse options out of. + const char *envValue = getenv(envVar); + if (!envValue) + return; + + // Get program's "name", which we wouldn't know without the caller + // telling us. + std::vector newArgv; + newArgv.push_back(strdup(progName)); + + // Parse the value of the environment variable into a "command line" + // and hand it off to ParseCommandLineOptions(). + ParseCStringVector(newArgv, envValue); + int newArgc = static_cast(newArgv.size()); + ParseCommandLineOptions(newArgc, &newArgv[0], Overview, ReadResponseFiles); + + // Free all the strdup()ed strings. + for (std::vector::iterator i = newArgv.begin(), e = newArgv.end(); + i != e; ++i) + free(*i); +} + + +/// ExpandResponseFiles - Copy the contents of argv into newArgv, +/// substituting the contents of the response files for the arguments +/// of type @file. +static void ExpandResponseFiles(unsigned argc, char** argv, + std::vector& newArgv) { + for (unsigned i = 1; i != argc; ++i) { + char *arg = argv[i]; + + if (arg[0] == '@') { + sys::PathWithStatus respFile(++arg); + + // Check that the response file is not empty (mmap'ing empty + // files can be problematic). + const sys::FileStatus *FileStat = respFile.getFileStatus(); + if (FileStat && FileStat->getSize() != 0) { + + // Mmap the response file into memory. + OwningPtr + respFilePtr(MemoryBuffer::getFile(respFile.c_str())); + + // If we could open the file, parse its contents, otherwise + // pass the @file option verbatim. + + // TODO: we should also support recursive loading of response files, + // since this is how gcc behaves. (From their man page: "The file may + // itself contain additional @file options; any such options will be + // processed recursively.") + + if (respFilePtr != 0) { + ParseCStringVector(newArgv, respFilePtr->getBufferStart()); + continue; + } + } + } + newArgv.push_back(strdup(arg)); + } +} + +void cl::ParseCommandLineOptions(int argc, char **argv, + const char *Overview, bool ReadResponseFiles) { + // Process all registered options. + SmallVector PositionalOpts; + SmallVector SinkOpts; + StringMap Opts; + GetOptionInfo(PositionalOpts, SinkOpts, Opts); + + assert((!Opts.empty() || !PositionalOpts.empty()) && + "No options specified!"); + + // Expand response files. + std::vector newArgv; + if (ReadResponseFiles) { + newArgv.push_back(strdup(argv[0])); + ExpandResponseFiles(argc, argv, newArgv); + argv = &newArgv[0]; + argc = static_cast(newArgv.size()); + } + + // Copy the program name into ProgName, making sure not to overflow it. + std::string ProgName = sys::Path(argv[0]).getLast(); + if (ProgName.size() > 79) ProgName.resize(79); + strcpy(ProgramName, ProgName.c_str()); + + ProgramOverview = Overview; + bool ErrorParsing = false; + + // Check out the positional arguments to collect information about them. + unsigned NumPositionalRequired = 0; + + // Determine whether or not there are an unlimited number of positionals + bool HasUnlimitedPositionals = false; + + Option *ConsumeAfterOpt = 0; + if (!PositionalOpts.empty()) { + if (PositionalOpts[0]->getNumOccurrencesFlag() == cl::ConsumeAfter) { + assert(PositionalOpts.size() > 1 && + "Cannot specify cl::ConsumeAfter without a positional argument!"); + ConsumeAfterOpt = PositionalOpts[0]; + } + + // Calculate how many positional values are _required_. + bool UnboundedFound = false; + for (size_t i = ConsumeAfterOpt != 0, e = PositionalOpts.size(); + i != e; ++i) { + Option *Opt = PositionalOpts[i]; + if (RequiresValue(Opt)) + ++NumPositionalRequired; + else if (ConsumeAfterOpt) { + // ConsumeAfter cannot be combined with "optional" positional options + // unless there is only one positional argument... + if (PositionalOpts.size() > 2) + ErrorParsing |= + Opt->error("error - this positional option will never be matched, " + "because it does not Require a value, and a " + "cl::ConsumeAfter option is active!"); + } else if (UnboundedFound && !Opt->ArgStr[0]) { + // This option does not "require" a value... Make sure this option is + // not specified after an option that eats all extra arguments, or this + // one will never get any! + // + ErrorParsing |= Opt->error("error - option can never match, because " + "another positional argument will match an " + "unbounded number of values, and this option" + " does not require a value!"); + } + UnboundedFound |= EatsUnboundedNumberOfValues(Opt); + } + HasUnlimitedPositionals = UnboundedFound || ConsumeAfterOpt; + } + + // PositionalVals - A vector of "positional" arguments we accumulate into + // the process at the end. + // + SmallVector, 4> PositionalVals; + + // If the program has named positional arguments, and the name has been run + // across, keep track of which positional argument was named. Otherwise put + // the positional args into the PositionalVals list... + Option *ActivePositionalArg = 0; + + // Loop over all of the arguments... processing them. + bool DashDashFound = false; // Have we read '--'? + for (int i = 1; i < argc; ++i) { + Option *Handler = 0; + StringRef Value; + StringRef ArgName = ""; + + // If the option list changed, this means that some command line + // option has just been registered or deregistered. This can occur in + // response to things like -load, etc. If this happens, rescan the options. + if (OptionListChanged) { + PositionalOpts.clear(); + SinkOpts.clear(); + Opts.clear(); + GetOptionInfo(PositionalOpts, SinkOpts, Opts); + OptionListChanged = false; + } + + // Check to see if this is a positional argument. This argument is + // considered to be positional if it doesn't start with '-', if it is "-" + // itself, or if we have seen "--" already. + // + if (argv[i][0] != '-' || argv[i][1] == 0 || DashDashFound) { + // Positional argument! + if (ActivePositionalArg) { + ProvidePositionalOption(ActivePositionalArg, argv[i], i); + continue; // We are done! + } + + if (!PositionalOpts.empty()) { + PositionalVals.push_back(std::make_pair(argv[i],i)); + + // All of the positional arguments have been fulfulled, give the rest to + // the consume after option... if it's specified... + // + if (PositionalVals.size() >= NumPositionalRequired && + ConsumeAfterOpt != 0) { + for (++i; i < argc; ++i) + PositionalVals.push_back(std::make_pair(argv[i],i)); + break; // Handle outside of the argument processing loop... + } + + // Delay processing positional arguments until the end... + continue; + } + } else if (argv[i][0] == '-' && argv[i][1] == '-' && argv[i][2] == 0 && + !DashDashFound) { + DashDashFound = true; // This is the mythical "--"? + continue; // Don't try to process it as an argument itself. + } else if (ActivePositionalArg && + (ActivePositionalArg->getMiscFlags() & PositionalEatsArgs)) { + // If there is a positional argument eating options, check to see if this + // option is another positional argument. If so, treat it as an argument, + // otherwise feed it to the eating positional. + ArgName = argv[i]+1; + // Eat leading dashes. + while (!ArgName.empty() && ArgName[0] == '-') + ArgName = ArgName.substr(1); + + Handler = LookupOption(ArgName, Value, Opts); + if (!Handler || Handler->getFormattingFlag() != cl::Positional) { + ProvidePositionalOption(ActivePositionalArg, argv[i], i); + continue; // We are done! + } + + } else { // We start with a '-', must be an argument. + ArgName = argv[i]+1; + // Eat leading dashes. + while (!ArgName.empty() && ArgName[0] == '-') + ArgName = ArgName.substr(1); + + Handler = LookupOption(ArgName, Value, Opts); + + // Check to see if this "option" is really a prefixed or grouped argument. + if (Handler == 0) + Handler = HandlePrefixedOrGroupedOption(ArgName, Value, + ErrorParsing, Opts); + } + + if (Handler == 0) { + if (SinkOpts.empty()) { + errs() << ProgramName << ": Unknown command line argument '" + << argv[i] << "'. Try: '" << argv[0] << " --help'\n"; + ErrorParsing = true; + } else { + for (SmallVectorImpl::iterator I = SinkOpts.begin(), + E = SinkOpts.end(); I != E ; ++I) + (*I)->addOccurrence(i, "", argv[i]); + } + continue; + } + + // If this is a named positional argument, just remember that it is the + // active one... + if (Handler->getFormattingFlag() == cl::Positional) + ActivePositionalArg = Handler; + else + ErrorParsing |= ProvideOption(Handler, ArgName, Value, argc, argv, i); + } + + // Check and handle positional arguments now... + if (NumPositionalRequired > PositionalVals.size()) { + errs() << ProgramName + << ": Not enough positional command line arguments specified!\n" + << "Must specify at least " << NumPositionalRequired + << " positional arguments: See: " << argv[0] << " --help\n"; + + ErrorParsing = true; + } else if (!HasUnlimitedPositionals + && PositionalVals.size() > PositionalOpts.size()) { + errs() << ProgramName + << ": Too many positional arguments specified!\n" + << "Can specify at most " << PositionalOpts.size() + << " positional arguments: See: " << argv[0] << " --help\n"; + ErrorParsing = true; + + } else if (ConsumeAfterOpt == 0) { + // Positional args have already been handled if ConsumeAfter is specified. + unsigned ValNo = 0, NumVals = static_cast(PositionalVals.size()); + for (size_t i = 0, e = PositionalOpts.size(); i != e; ++i) { + if (RequiresValue(PositionalOpts[i])) { + ProvidePositionalOption(PositionalOpts[i], PositionalVals[ValNo].first, + PositionalVals[ValNo].second); + ValNo++; + --NumPositionalRequired; // We fulfilled our duty... + } + + // If we _can_ give this option more arguments, do so now, as long as we + // do not give it values that others need. 'Done' controls whether the + // option even _WANTS_ any more. + // + bool Done = PositionalOpts[i]->getNumOccurrencesFlag() == cl::Required; + while (NumVals-ValNo > NumPositionalRequired && !Done) { + switch (PositionalOpts[i]->getNumOccurrencesFlag()) { + case cl::Optional: + Done = true; // Optional arguments want _at most_ one value + // FALL THROUGH + case cl::ZeroOrMore: // Zero or more will take all they can get... + case cl::OneOrMore: // One or more will take all they can get... + ProvidePositionalOption(PositionalOpts[i], + PositionalVals[ValNo].first, + PositionalVals[ValNo].second); + ValNo++; + break; + default: + llvm_unreachable("Internal error, unexpected NumOccurrences flag in " + "positional argument processing!"); + } + } + } + } else { + assert(ConsumeAfterOpt && NumPositionalRequired <= PositionalVals.size()); + unsigned ValNo = 0; + for (size_t j = 1, e = PositionalOpts.size(); j != e; ++j) + if (RequiresValue(PositionalOpts[j])) { + ErrorParsing |= ProvidePositionalOption(PositionalOpts[j], + PositionalVals[ValNo].first, + PositionalVals[ValNo].second); + ValNo++; + } + + // Handle the case where there is just one positional option, and it's + // optional. In this case, we want to give JUST THE FIRST option to the + // positional option and keep the rest for the consume after. The above + // loop would have assigned no values to positional options in this case. + // + if (PositionalOpts.size() == 2 && ValNo == 0 && !PositionalVals.empty()) { + ErrorParsing |= ProvidePositionalOption(PositionalOpts[1], + PositionalVals[ValNo].first, + PositionalVals[ValNo].second); + ValNo++; + } + + // Handle over all of the rest of the arguments to the + // cl::ConsumeAfter command line option... + for (; ValNo != PositionalVals.size(); ++ValNo) + ErrorParsing |= ProvidePositionalOption(ConsumeAfterOpt, + PositionalVals[ValNo].first, + PositionalVals[ValNo].second); + } + + // Loop over args and make sure all required args are specified! + for (StringMap::iterator I = Opts.begin(), + E = Opts.end(); I != E; ++I) { + switch (I->second->getNumOccurrencesFlag()) { + case Required: + case OneOrMore: + if (I->second->getNumOccurrences() == 0) { + I->second->error("must be specified at least once!"); + ErrorParsing = true; + } + // Fall through + default: + break; + } + } + + // Free all of the memory allocated to the map. Command line options may only + // be processed once! + Opts.clear(); + PositionalOpts.clear(); + MoreHelp->clear(); + + // Free the memory allocated by ExpandResponseFiles. + if (ReadResponseFiles) { + // Free all the strdup()ed strings. + for (std::vector::iterator i = newArgv.begin(), e = newArgv.end(); + i != e; ++i) + free(*i); + } + + DEBUG(errs() << "\nArgs: "; + for (int i = 0; i < argc; ++i) + errs() << argv[i] << ' '; + ); + + // If we had an error processing our arguments, don't let the program execute + if (ErrorParsing) exit(1); +} + +//===----------------------------------------------------------------------===// +// Option Base class implementation +// + +bool Option::error(const Twine &Message, StringRef ArgName) { + if (ArgName.data() == 0) ArgName = ArgStr; + if (ArgName.empty()) + errs() << HelpStr; // Be nice for positional arguments + else + errs() << ProgramName << ": for the -" << ArgName; + + errs() << " option: " << Message << "\n"; + return true; +} + +bool Option::addOccurrence(unsigned pos, StringRef ArgName, + StringRef Value, bool MultiArg) { + if (!MultiArg) + NumOccurrences++; // Increment the number of times we have been seen + + switch (getNumOccurrencesFlag()) { + case Optional: + if (NumOccurrences > 1) + return error("may only occur zero or one times!", ArgName); + break; + case Required: + if (NumOccurrences > 1) + return error("must occur exactly one time!", ArgName); + // Fall through + case OneOrMore: + case ZeroOrMore: + case ConsumeAfter: break; + default: return error("bad num occurrences flag value!"); + } + + return handleOccurrence(pos, ArgName, Value); +} + + +// getValueStr - Get the value description string, using "DefaultMsg" if nothing +// has been specified yet. +// +static const char *getValueStr(const Option &O, const char *DefaultMsg) { + if (O.ValueStr[0] == 0) return DefaultMsg; + return O.ValueStr; +} + +//===----------------------------------------------------------------------===// +// cl::alias class implementation +// + +// Return the width of the option tag for printing... +size_t alias::getOptionWidth() const { + return std::strlen(ArgStr)+6; +} + +// Print out the option for the alias. +void alias::printOptionInfo(size_t GlobalWidth) const { + size_t L = std::strlen(ArgStr); + errs() << " -" << ArgStr; + errs().indent(GlobalWidth-L-6) << " - " << HelpStr << "\n"; +} + + + +//===----------------------------------------------------------------------===// +// Parser Implementation code... +// + +// basic_parser implementation +// + +// Return the width of the option tag for printing... +size_t basic_parser_impl::getOptionWidth(const Option &O) const { + size_t Len = std::strlen(O.ArgStr); + if (const char *ValName = getValueName()) + Len += std::strlen(getValueStr(O, ValName))+3; + + return Len + 6; +} + +// printOptionInfo - Print out information about this option. The +// to-be-maintained width is specified. +// +void basic_parser_impl::printOptionInfo(const Option &O, + size_t GlobalWidth) const { + outs() << " -" << O.ArgStr; + + if (const char *ValName = getValueName()) + outs() << "=<" << getValueStr(O, ValName) << '>'; + + outs().indent(GlobalWidth-getOptionWidth(O)) << " - " << O.HelpStr << '\n'; +} + + + + +// parser implementation +// +bool parser::parse(Option &O, StringRef ArgName, + StringRef Arg, bool &Value) { + if (Arg == "" || Arg == "true" || Arg == "TRUE" || Arg == "True" || + Arg == "1") { + Value = true; + return false; + } + + if (Arg == "false" || Arg == "FALSE" || Arg == "False" || Arg == "0") { + Value = false; + return false; + } + return O.error("'" + Arg + + "' is invalid value for boolean argument! Try 0 or 1"); +} + +// parser implementation +// +bool parser::parse(Option &O, StringRef ArgName, + StringRef Arg, boolOrDefault &Value) { + if (Arg == "" || Arg == "true" || Arg == "TRUE" || Arg == "True" || + Arg == "1") { + Value = BOU_TRUE; + return false; + } + if (Arg == "false" || Arg == "FALSE" || Arg == "False" || Arg == "0") { + Value = BOU_FALSE; + return false; + } + + return O.error("'" + Arg + + "' is invalid value for boolean argument! Try 0 or 1"); +} + +// parser implementation +// +bool parser::parse(Option &O, StringRef ArgName, + StringRef Arg, int &Value) { + if (Arg.getAsInteger(0, Value)) + return O.error("'" + Arg + "' value invalid for integer argument!"); + return false; +} + +// parser implementation +// +bool parser::parse(Option &O, StringRef ArgName, + StringRef Arg, unsigned &Value) { + + if (Arg.getAsInteger(0, Value)) + return O.error("'" + Arg + "' value invalid for uint argument!"); + return false; +} + +// parser/parser implementation +// +static bool parseDouble(Option &O, StringRef Arg, double &Value) { + SmallString<32> TmpStr(Arg.begin(), Arg.end()); + const char *ArgStart = TmpStr.c_str(); + char *End; + Value = strtod(ArgStart, &End); + if (*End != 0) + return O.error("'" + Arg + "' value invalid for floating point argument!"); + return false; +} + +bool parser::parse(Option &O, StringRef ArgName, + StringRef Arg, double &Val) { + return parseDouble(O, Arg, Val); +} + +bool parser::parse(Option &O, StringRef ArgName, + StringRef Arg, float &Val) { + double dVal; + if (parseDouble(O, Arg, dVal)) + return true; + Val = (float)dVal; + return false; +} + + + +// generic_parser_base implementation +// + +// findOption - Return the option number corresponding to the specified +// argument string. If the option is not found, getNumOptions() is returned. +// +unsigned generic_parser_base::findOption(const char *Name) { + unsigned e = getNumOptions(); + + for (unsigned i = 0; i != e; ++i) { + if (strcmp(getOption(i), Name) == 0) + return i; + } + return e; +} + + +// Return the width of the option tag for printing... +size_t generic_parser_base::getOptionWidth(const Option &O) const { + if (O.hasArgStr()) { + size_t Size = std::strlen(O.ArgStr)+6; + for (unsigned i = 0, e = getNumOptions(); i != e; ++i) + Size = std::max(Size, std::strlen(getOption(i))+8); + return Size; + } else { + size_t BaseSize = 0; + for (unsigned i = 0, e = getNumOptions(); i != e; ++i) + BaseSize = std::max(BaseSize, std::strlen(getOption(i))+8); + return BaseSize; + } +} + +// printOptionInfo - Print out information about this option. The +// to-be-maintained width is specified. +// +void generic_parser_base::printOptionInfo(const Option &O, + size_t GlobalWidth) const { + if (O.hasArgStr()) { + size_t L = std::strlen(O.ArgStr); + outs() << " -" << O.ArgStr; + outs().indent(GlobalWidth-L-6) << " - " << O.HelpStr << '\n'; + + for (unsigned i = 0, e = getNumOptions(); i != e; ++i) { + size_t NumSpaces = GlobalWidth-strlen(getOption(i))-8; + outs() << " =" << getOption(i); + outs().indent(NumSpaces) << " - " << getDescription(i) << '\n'; + } + } else { + if (O.HelpStr[0]) + outs() << " " << O.HelpStr << '\n'; + for (unsigned i = 0, e = getNumOptions(); i != e; ++i) { + size_t L = std::strlen(getOption(i)); + outs() << " -" << getOption(i); + outs().indent(GlobalWidth-L-8) << " - " << getDescription(i) << '\n'; + } + } +} + + +//===----------------------------------------------------------------------===// +// --help and --help-hidden option implementation +// + +static int OptNameCompare(const void *LHS, const void *RHS) { + typedef std::pair pair_ty; + + return strcmp(((pair_ty*)LHS)->first, ((pair_ty*)RHS)->first); +} + +namespace { + +class HelpPrinter { + size_t MaxArgLen; + const Option *EmptyArg; + const bool ShowHidden; + +public: + explicit HelpPrinter(bool showHidden) : ShowHidden(showHidden) { + EmptyArg = 0; + } + + void operator=(bool Value) { + if (Value == false) return; + + // Get all the options. + SmallVector PositionalOpts; + SmallVector SinkOpts; + StringMap OptMap; + GetOptionInfo(PositionalOpts, SinkOpts, OptMap); + + // Copy Options into a vector so we can sort them as we like. + SmallVector, 128> Opts; + SmallPtrSet OptionSet; // Duplicate option detection. + + for (StringMap::iterator I = OptMap.begin(), E = OptMap.end(); + I != E; ++I) { + // Ignore really-hidden options. + if (I->second->getOptionHiddenFlag() == ReallyHidden) + continue; + + // Unless showhidden is set, ignore hidden flags. + if (I->second->getOptionHiddenFlag() == Hidden && !ShowHidden) + continue; + + // If we've already seen this option, don't add it to the list again. + if (!OptionSet.insert(I->second)) + continue; + + Opts.push_back(std::pair(I->getKey().data(), + I->second)); + } + + // Sort the options list alphabetically. + qsort(Opts.data(), Opts.size(), sizeof(Opts[0]), OptNameCompare); + + if (ProgramOverview) + outs() << "OVERVIEW: " << ProgramOverview << "\n"; + + outs() << "USAGE: " << ProgramName << " [options]"; + + // Print out the positional options. + Option *CAOpt = 0; // The cl::ConsumeAfter option, if it exists... + if (!PositionalOpts.empty() && + PositionalOpts[0]->getNumOccurrencesFlag() == ConsumeAfter) + CAOpt = PositionalOpts[0]; + + for (size_t i = CAOpt != 0, e = PositionalOpts.size(); i != e; ++i) { + if (PositionalOpts[i]->ArgStr[0]) + outs() << " --" << PositionalOpts[i]->ArgStr; + outs() << " " << PositionalOpts[i]->HelpStr; + } + + // Print the consume after option info if it exists... + if (CAOpt) outs() << " " << CAOpt->HelpStr; + + outs() << "\n\n"; + + // Compute the maximum argument length... + MaxArgLen = 0; + for (size_t i = 0, e = Opts.size(); i != e; ++i) + MaxArgLen = std::max(MaxArgLen, Opts[i].second->getOptionWidth()); + + outs() << "OPTIONS:\n"; + for (size_t i = 0, e = Opts.size(); i != e; ++i) + Opts[i].second->printOptionInfo(MaxArgLen); + + // Print any extra help the user has declared. + for (std::vector::iterator I = MoreHelp->begin(), + E = MoreHelp->end(); I != E; ++I) + outs() << *I; + MoreHelp->clear(); + + // Halt the program since help information was printed + exit(1); + } +}; +} // End anonymous namespace + +// Define the two HelpPrinter instances that are used to print out help, or +// help-hidden... +// +static HelpPrinter NormalPrinter(false); +static HelpPrinter HiddenPrinter(true); + +static cl::opt > +HOp("help", cl::desc("Display available options (--help-hidden for more)"), + cl::location(NormalPrinter), cl::ValueDisallowed); + +static cl::opt > +HHOp("help-hidden", cl::desc("Display all available options"), + cl::location(HiddenPrinter), cl::Hidden, cl::ValueDisallowed); + +static void (*OverrideVersionPrinter)() = 0; + +static int TargetArraySortFn(const void *LHS, const void *RHS) { + typedef std::pair pair_ty; + return strcmp(((const pair_ty*)LHS)->first, ((const pair_ty*)RHS)->first); +} + +namespace { +class VersionPrinter { +public: + void print() { + raw_ostream &OS = outs(); + OS << "Low Level Virtual Machine (http://llvm.org/):\n" + << " " << PACKAGE_NAME << " version " << PACKAGE_VERSION; +#ifdef LLVM_VERSION_INFO + OS << LLVM_VERSION_INFO; +#endif + OS << "\n "; +#ifndef __OPTIMIZE__ + OS << "DEBUG build"; +#else + OS << "Optimized build"; +#endif +#ifndef NDEBUG + OS << " with assertions"; +#endif + std::string CPU = sys::getHostCPUName(); + if (CPU == "generic") CPU = "(unknown)"; + OS << ".\n" + << " Built " << __DATE__ << " (" << __TIME__ << ").\n" + << " Host: " << sys::getHostTriple() << '\n' + << " Host CPU: " << CPU << '\n' + << '\n' + << " Registered Targets:\n"; + + std::vector > Targets; + size_t Width = 0; + for (TargetRegistry::iterator it = TargetRegistry::begin(), + ie = TargetRegistry::end(); it != ie; ++it) { + Targets.push_back(std::make_pair(it->getName(), &*it)); + Width = std::max(Width, strlen(Targets.back().first)); + } + if (!Targets.empty()) + qsort(&Targets[0], Targets.size(), sizeof(Targets[0]), + TargetArraySortFn); + + for (unsigned i = 0, e = Targets.size(); i != e; ++i) { + OS << " " << Targets[i].first; + OS.indent(Width - strlen(Targets[i].first)) << " - " + << Targets[i].second->getShortDescription() << '\n'; + } + if (Targets.empty()) + OS << " (none)\n"; + } + void operator=(bool OptionWasSpecified) { + if (!OptionWasSpecified) return; + + if (OverrideVersionPrinter == 0) { + print(); + exit(1); + } + (*OverrideVersionPrinter)(); + exit(1); + } +}; +} // End anonymous namespace + + +// Define the --version option that prints out the LLVM version for the tool +static VersionPrinter VersionPrinterInstance; + +static cl::opt > +VersOp("version", cl::desc("Display the version of this program"), + cl::location(VersionPrinterInstance), cl::ValueDisallowed); + +// Utility function for printing the help message. +void cl::PrintHelpMessage() { + // This looks weird, but it actually prints the help message. The + // NormalPrinter variable is a HelpPrinter and the help gets printed when + // its operator= is invoked. That's because the "normal" usages of the + // help printer is to be assigned true/false depending on whether the + // --help option was given or not. Since we're circumventing that we have + // to make it look like --help was given, so we assign true. + NormalPrinter = true; +} + +/// Utility function for printing version number. +void cl::PrintVersionMessage() { + VersionPrinterInstance.print(); +} + +void cl::SetVersionPrinter(void (*func)()) { + OverrideVersionPrinter = func; +} diff --git a/libclamav/c++/llvm/lib/Support/ConstantRange.cpp b/libclamav/c++/llvm/lib/Support/ConstantRange.cpp new file mode 100644 index 000000000..e427f820c --- /dev/null +++ b/libclamav/c++/llvm/lib/Support/ConstantRange.cpp @@ -0,0 +1,661 @@ +//===-- ConstantRange.cpp - ConstantRange implementation ------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Represent a range of possible values that may occur when the program is run +// for an integral value. This keeps track of a lower and upper bound for the +// constant, which MAY wrap around the end of the numeric range. To do this, it +// keeps track of a [lower, upper) bound, which specifies an interval just like +// STL iterators. When used with boolean values, the following are important +// ranges (other integral ranges use min/max values for special range values): +// +// [F, F) = {} = Empty set +// [T, F) = {T} +// [F, T) = {F} +// [T, T) = {F, T} = Full set +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/ConstantRange.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Instructions.h" +using namespace llvm; + +/// Initialize a full (the default) or empty set for the specified type. +/// +ConstantRange::ConstantRange(uint32_t BitWidth, bool Full) { + if (Full) + Lower = Upper = APInt::getMaxValue(BitWidth); + else + Lower = Upper = APInt::getMinValue(BitWidth); +} + +/// Initialize a range to hold the single specified value. +/// +ConstantRange::ConstantRange(const APInt & V) : Lower(V), Upper(V + 1) {} + +ConstantRange::ConstantRange(const APInt &L, const APInt &U) : + Lower(L), Upper(U) { + assert(L.getBitWidth() == U.getBitWidth() && + "ConstantRange with unequal bit widths"); + assert((L != U || (L.isMaxValue() || L.isMinValue())) && + "Lower == Upper, but they aren't min or max value!"); +} + +ConstantRange ConstantRange::makeICmpRegion(unsigned Pred, + const ConstantRange &CR) { + uint32_t W = CR.getBitWidth(); + switch (Pred) { + default: assert(!"Invalid ICmp predicate to makeICmpRegion()"); + case ICmpInst::ICMP_EQ: + return CR; + case ICmpInst::ICMP_NE: + if (CR.isSingleElement()) + return ConstantRange(CR.getUpper(), CR.getLower()); + return ConstantRange(W); + case ICmpInst::ICMP_ULT: + return ConstantRange(APInt::getMinValue(W), CR.getUnsignedMax()); + case ICmpInst::ICMP_SLT: + return ConstantRange(APInt::getSignedMinValue(W), CR.getSignedMax()); + case ICmpInst::ICMP_ULE: { + APInt UMax(CR.getUnsignedMax()); + if (UMax.isMaxValue()) + return ConstantRange(W); + return ConstantRange(APInt::getMinValue(W), UMax + 1); + } + case ICmpInst::ICMP_SLE: { + APInt SMax(CR.getSignedMax()); + if (SMax.isMaxSignedValue() || (SMax+1).isMaxSignedValue()) + return ConstantRange(W); + return ConstantRange(APInt::getSignedMinValue(W), SMax + 1); + } + case ICmpInst::ICMP_UGT: + return ConstantRange(CR.getUnsignedMin() + 1, APInt::getNullValue(W)); + case ICmpInst::ICMP_SGT: + return ConstantRange(CR.getSignedMin() + 1, + APInt::getSignedMinValue(W)); + case ICmpInst::ICMP_UGE: { + APInt UMin(CR.getUnsignedMin()); + if (UMin.isMinValue()) + return ConstantRange(W); + return ConstantRange(UMin, APInt::getNullValue(W)); + } + case ICmpInst::ICMP_SGE: { + APInt SMin(CR.getSignedMin()); + if (SMin.isMinSignedValue()) + return ConstantRange(W); + return ConstantRange(SMin, APInt::getSignedMinValue(W)); + } + } +} + +/// isFullSet - Return true if this set contains all of the elements possible +/// for this data-type +bool ConstantRange::isFullSet() const { + return Lower == Upper && Lower.isMaxValue(); +} + +/// isEmptySet - Return true if this set contains no members. +/// +bool ConstantRange::isEmptySet() const { + return Lower == Upper && Lower.isMinValue(); +} + +/// isWrappedSet - Return true if this set wraps around the top of the range, +/// for example: [100, 8) +/// +bool ConstantRange::isWrappedSet() const { + return Lower.ugt(Upper); +} + +/// getSetSize - Return the number of elements in this set. +/// +APInt ConstantRange::getSetSize() const { + if (isEmptySet()) + return APInt(getBitWidth(), 0); + if (getBitWidth() == 1) { + if (Lower != Upper) // One of T or F in the set... + return APInt(2, 1); + return APInt(2, 2); // Must be full set... + } + + // Simply subtract the bounds... + return Upper - Lower; +} + +/// getUnsignedMax - Return the largest unsigned value contained in the +/// ConstantRange. +/// +APInt ConstantRange::getUnsignedMax() const { + if (isFullSet() || isWrappedSet()) + return APInt::getMaxValue(getBitWidth()); + else + return getUpper() - 1; +} + +/// getUnsignedMin - Return the smallest unsigned value contained in the +/// ConstantRange. +/// +APInt ConstantRange::getUnsignedMin() const { + if (isFullSet() || (isWrappedSet() && getUpper() != 0)) + return APInt::getMinValue(getBitWidth()); + else + return getLower(); +} + +/// getSignedMax - Return the largest signed value contained in the +/// ConstantRange. +/// +APInt ConstantRange::getSignedMax() const { + APInt SignedMax(APInt::getSignedMaxValue(getBitWidth())); + if (!isWrappedSet()) { + if (getLower().sle(getUpper() - 1)) + return getUpper() - 1; + else + return SignedMax; + } else { + if (getLower().isNegative() == getUpper().isNegative()) + return SignedMax; + else + return getUpper() - 1; + } +} + +/// getSignedMin - Return the smallest signed value contained in the +/// ConstantRange. +/// +APInt ConstantRange::getSignedMin() const { + APInt SignedMin(APInt::getSignedMinValue(getBitWidth())); + if (!isWrappedSet()) { + if (getLower().sle(getUpper() - 1)) + return getLower(); + else + return SignedMin; + } else { + if ((getUpper() - 1).slt(getLower())) { + if (getUpper() != SignedMin) + return SignedMin; + else + return getLower(); + } else { + return getLower(); + } + } +} + +/// contains - Return true if the specified value is in the set. +/// +bool ConstantRange::contains(const APInt &V) const { + if (Lower == Upper) + return isFullSet(); + + if (!isWrappedSet()) + return Lower.ule(V) && V.ult(Upper); + else + return Lower.ule(V) || V.ult(Upper); +} + +/// contains - Return true if the argument is a subset of this range. +/// Two equal set contain each other. The empty set is considered to be +/// contained by all other sets. +/// +bool ConstantRange::contains(const ConstantRange &Other) const { + if (isFullSet()) return true; + if (Other.isFullSet()) return false; + if (Other.isEmptySet()) return true; + if (isEmptySet()) return false; + + if (!isWrappedSet()) { + if (Other.isWrappedSet()) + return false; + + return Lower.ule(Other.getLower()) && Other.getUpper().ule(Upper); + } + + if (!Other.isWrappedSet()) + return Other.getUpper().ule(Upper) || + Lower.ule(Other.getLower()); + + return Other.getUpper().ule(Upper) && Lower.ule(Other.getLower()); +} + +/// subtract - Subtract the specified constant from the endpoints of this +/// constant range. +ConstantRange ConstantRange::subtract(const APInt &Val) const { + assert(Val.getBitWidth() == getBitWidth() && "Wrong bit width"); + // If the set is empty or full, don't modify the endpoints. + if (Lower == Upper) + return *this; + return ConstantRange(Lower - Val, Upper - Val); +} + + +// intersect1Wrapped - This helper function is used to intersect two ranges when +// it is known that LHS is wrapped and RHS isn't. +// +ConstantRange +ConstantRange::intersect1Wrapped(const ConstantRange &LHS, + const ConstantRange &RHS) { + assert(LHS.isWrappedSet() && !RHS.isWrappedSet()); + + // Check to see if we overlap on the Left side of RHS... + // + if (RHS.Lower.ult(LHS.Upper)) { + // We do overlap on the left side of RHS, see if we overlap on the right of + // RHS... + if (RHS.Upper.ugt(LHS.Lower)) { + // Ok, the result overlaps on both the left and right sides. See if the + // resultant interval will be smaller if we wrap or not... + // + if (LHS.getSetSize().ult(RHS.getSetSize())) + return LHS; + else + return RHS; + + } else { + // No overlap on the right, just on the left. + return ConstantRange(RHS.Lower, LHS.Upper); + } + } else { + // We don't overlap on the left side of RHS, see if we overlap on the right + // of RHS... + if (RHS.Upper.ugt(LHS.Lower)) { + // Simple overlap... + return ConstantRange(LHS.Lower, RHS.Upper); + } else { + // No overlap... + return ConstantRange(LHS.getBitWidth(), false); + } + } +} + +/// intersectWith - Return the range that results from the intersection of this +/// range with another range. The resultant range is guaranteed to include all +/// elements contained in both input ranges, and to have the smallest possible +/// set size that does so. Because there may be two intersections with the +/// same set size, A.intersectWith(B) might not be equal to B.intersectWith(A). +ConstantRange ConstantRange::intersectWith(const ConstantRange &CR) const { + assert(getBitWidth() == CR.getBitWidth() && + "ConstantRange types don't agree!"); + + // Handle common cases. + if ( isEmptySet() || CR.isFullSet()) return *this; + if (CR.isEmptySet() || isFullSet()) return CR; + + if (!isWrappedSet() && CR.isWrappedSet()) + return CR.intersectWith(*this); + + if (!isWrappedSet() && !CR.isWrappedSet()) { + if (Lower.ult(CR.Lower)) { + if (Upper.ule(CR.Lower)) + return ConstantRange(getBitWidth(), false); + + if (Upper.ult(CR.Upper)) + return ConstantRange(CR.Lower, Upper); + + return CR; + } else { + if (Upper.ult(CR.Upper)) + return *this; + + if (Lower.ult(CR.Upper)) + return ConstantRange(Lower, CR.Upper); + + return ConstantRange(getBitWidth(), false); + } + } + + if (isWrappedSet() && !CR.isWrappedSet()) { + if (CR.Lower.ult(Upper)) { + if (CR.Upper.ult(Upper)) + return CR; + + if (CR.Upper.ult(Lower)) + return ConstantRange(CR.Lower, Upper); + + if (getSetSize().ult(CR.getSetSize())) + return *this; + else + return CR; + } else if (CR.Lower.ult(Lower)) { + if (CR.Upper.ule(Lower)) + return ConstantRange(getBitWidth(), false); + + return ConstantRange(Lower, CR.Upper); + } + return CR; + } + + if (CR.Upper.ult(Upper)) { + if (CR.Lower.ult(Upper)) { + if (getSetSize().ult(CR.getSetSize())) + return *this; + else + return CR; + } + + if (CR.Lower.ult(Lower)) + return ConstantRange(Lower, CR.Upper); + + return CR; + } else if (CR.Upper.ult(Lower)) { + if (CR.Lower.ult(Lower)) + return *this; + + return ConstantRange(CR.Lower, Upper); + } + if (getSetSize().ult(CR.getSetSize())) + return *this; + else + return CR; +} + + +/// unionWith - Return the range that results from the union of this range with +/// another range. The resultant range is guaranteed to include the elements of +/// both sets, but may contain more. For example, [3, 9) union [12,15) is +/// [3, 15), which includes 9, 10, and 11, which were not included in either +/// set before. +/// +ConstantRange ConstantRange::unionWith(const ConstantRange &CR) const { + assert(getBitWidth() == CR.getBitWidth() && + "ConstantRange types don't agree!"); + + if ( isFullSet() || CR.isEmptySet()) return *this; + if (CR.isFullSet() || isEmptySet()) return CR; + + if (!isWrappedSet() && CR.isWrappedSet()) return CR.unionWith(*this); + + if (!isWrappedSet() && !CR.isWrappedSet()) { + if (CR.Upper.ult(Lower) || Upper.ult(CR.Lower)) { + // If the two ranges are disjoint, find the smaller gap and bridge it. + APInt d1 = CR.Lower - Upper, d2 = Lower - CR.Upper; + if (d1.ult(d2)) + return ConstantRange(Lower, CR.Upper); + else + return ConstantRange(CR.Lower, Upper); + } + + APInt L = Lower, U = Upper; + if (CR.Lower.ult(L)) + L = CR.Lower; + if ((CR.Upper - 1).ugt(U - 1)) + U = CR.Upper; + + if (L == 0 && U == 0) + return ConstantRange(getBitWidth()); + + return ConstantRange(L, U); + } + + if (!CR.isWrappedSet()) { + // ------U L----- and ------U L----- : this + // L--U L--U : CR + if (CR.Upper.ule(Upper) || CR.Lower.uge(Lower)) + return *this; + + // ------U L----- : this + // L---------U : CR + if (CR.Lower.ule(Upper) && Lower.ule(CR.Upper)) + return ConstantRange(getBitWidth()); + + // ----U L---- : this + // L---U : CR + // + if (Upper.ule(CR.Lower) && CR.Upper.ule(Lower)) { + APInt d1 = CR.Lower - Upper, d2 = Lower - CR.Upper; + if (d1.ult(d2)) + return ConstantRange(Lower, CR.Upper); + else + return ConstantRange(CR.Lower, Upper); + } + + // ----U L----- : this + // L----U : CR + if (Upper.ult(CR.Lower) && Lower.ult(CR.Upper)) + return ConstantRange(CR.Lower, Upper); + + // ------U L---- : this + // L-----U : CR + if (CR.Lower.ult(Upper) && CR.Upper.ult(Lower)) + return ConstantRange(Lower, CR.Upper); + } + + assert(isWrappedSet() && CR.isWrappedSet() && + "ConstantRange::unionWith missed wrapped union unwrapped case"); + + // ------U L---- and ------U L---- : this + // -U L----------- and ------------U L : CR + if (CR.Lower.ule(Upper) || Lower.ule(CR.Upper)) + return ConstantRange(getBitWidth()); + + APInt L = Lower, U = Upper; + if (CR.Upper.ugt(U)) + U = CR.Upper; + if (CR.Lower.ult(L)) + L = CR.Lower; + + return ConstantRange(L, U); +} + +/// zeroExtend - Return a new range in the specified integer type, which must +/// be strictly larger than the current type. The returned range will +/// correspond to the possible range of values as if the source range had been +/// zero extended. +ConstantRange ConstantRange::zeroExtend(uint32_t DstTySize) const { + unsigned SrcTySize = getBitWidth(); + assert(SrcTySize < DstTySize && "Not a value extension"); + if (isFullSet()) + // Change a source full set into [0, 1 << 8*numbytes) + return ConstantRange(APInt(DstTySize,0), APInt(DstTySize,1).shl(SrcTySize)); + + APInt L = Lower; L.zext(DstTySize); + APInt U = Upper; U.zext(DstTySize); + return ConstantRange(L, U); +} + +/// signExtend - Return a new range in the specified integer type, which must +/// be strictly larger than the current type. The returned range will +/// correspond to the possible range of values as if the source range had been +/// sign extended. +ConstantRange ConstantRange::signExtend(uint32_t DstTySize) const { + unsigned SrcTySize = getBitWidth(); + assert(SrcTySize < DstTySize && "Not a value extension"); + if (isFullSet()) { + return ConstantRange(APInt::getHighBitsSet(DstTySize,DstTySize-SrcTySize+1), + APInt::getLowBitsSet(DstTySize, SrcTySize-1) + 1); + } + + APInt L = Lower; L.sext(DstTySize); + APInt U = Upper; U.sext(DstTySize); + return ConstantRange(L, U); +} + +/// truncate - Return a new range in the specified integer type, which must be +/// strictly smaller than the current type. The returned range will +/// correspond to the possible range of values as if the source range had been +/// truncated to the specified type. +ConstantRange ConstantRange::truncate(uint32_t DstTySize) const { + unsigned SrcTySize = getBitWidth(); + assert(SrcTySize > DstTySize && "Not a value truncation"); + APInt Size(APInt::getLowBitsSet(SrcTySize, DstTySize)); + if (isFullSet() || getSetSize().ugt(Size)) + return ConstantRange(DstTySize); + + APInt L = Lower; L.trunc(DstTySize); + APInt U = Upper; U.trunc(DstTySize); + return ConstantRange(L, U); +} + +/// zextOrTrunc - make this range have the bit width given by \p DstTySize. The +/// value is zero extended, truncated, or left alone to make it that width. +ConstantRange ConstantRange::zextOrTrunc(uint32_t DstTySize) const { + unsigned SrcTySize = getBitWidth(); + if (SrcTySize > DstTySize) + return truncate(DstTySize); + else if (SrcTySize < DstTySize) + return zeroExtend(DstTySize); + else + return *this; +} + +/// sextOrTrunc - make this range have the bit width given by \p DstTySize. The +/// value is sign extended, truncated, or left alone to make it that width. +ConstantRange ConstantRange::sextOrTrunc(uint32_t DstTySize) const { + unsigned SrcTySize = getBitWidth(); + if (SrcTySize > DstTySize) + return truncate(DstTySize); + else if (SrcTySize < DstTySize) + return signExtend(DstTySize); + else + return *this; +} + +ConstantRange +ConstantRange::add(const ConstantRange &Other) const { + if (isEmptySet() || Other.isEmptySet()) + return ConstantRange(getBitWidth(), /*isFullSet=*/false); + if (isFullSet() || Other.isFullSet()) + return ConstantRange(getBitWidth(), /*isFullSet=*/true); + + APInt Spread_X = getSetSize(), Spread_Y = Other.getSetSize(); + APInt NewLower = getLower() + Other.getLower(); + APInt NewUpper = getUpper() + Other.getUpper() - 1; + if (NewLower == NewUpper) + return ConstantRange(getBitWidth(), /*isFullSet=*/true); + + ConstantRange X = ConstantRange(NewLower, NewUpper); + if (X.getSetSize().ult(Spread_X) || X.getSetSize().ult(Spread_Y)) + // We've wrapped, therefore, full set. + return ConstantRange(getBitWidth(), /*isFullSet=*/true); + + return X; +} + +ConstantRange +ConstantRange::multiply(const ConstantRange &Other) const { + if (isEmptySet() || Other.isEmptySet()) + return ConstantRange(getBitWidth(), /*isFullSet=*/false); + if (isFullSet() || Other.isFullSet()) + return ConstantRange(getBitWidth(), /*isFullSet=*/true); + + APInt this_min = getUnsignedMin().zext(getBitWidth() * 2); + APInt this_max = getUnsignedMax().zext(getBitWidth() * 2); + APInt Other_min = Other.getUnsignedMin().zext(getBitWidth() * 2); + APInt Other_max = Other.getUnsignedMax().zext(getBitWidth() * 2); + + ConstantRange Result_zext = ConstantRange(this_min * Other_min, + this_max * Other_max + 1); + return Result_zext.truncate(getBitWidth()); +} + +ConstantRange +ConstantRange::smax(const ConstantRange &Other) const { + // X smax Y is: range(smax(X_smin, Y_smin), + // smax(X_smax, Y_smax)) + if (isEmptySet() || Other.isEmptySet()) + return ConstantRange(getBitWidth(), /*isFullSet=*/false); + APInt NewL = APIntOps::smax(getSignedMin(), Other.getSignedMin()); + APInt NewU = APIntOps::smax(getSignedMax(), Other.getSignedMax()) + 1; + if (NewU == NewL) + return ConstantRange(getBitWidth(), /*isFullSet=*/true); + return ConstantRange(NewL, NewU); +} + +ConstantRange +ConstantRange::umax(const ConstantRange &Other) const { + // X umax Y is: range(umax(X_umin, Y_umin), + // umax(X_umax, Y_umax)) + if (isEmptySet() || Other.isEmptySet()) + return ConstantRange(getBitWidth(), /*isFullSet=*/false); + APInt NewL = APIntOps::umax(getUnsignedMin(), Other.getUnsignedMin()); + APInt NewU = APIntOps::umax(getUnsignedMax(), Other.getUnsignedMax()) + 1; + if (NewU == NewL) + return ConstantRange(getBitWidth(), /*isFullSet=*/true); + return ConstantRange(NewL, NewU); +} + +ConstantRange +ConstantRange::udiv(const ConstantRange &RHS) const { + if (isEmptySet() || RHS.isEmptySet() || RHS.getUnsignedMax() == 0) + return ConstantRange(getBitWidth(), /*isFullSet=*/false); + if (RHS.isFullSet()) + return ConstantRange(getBitWidth(), /*isFullSet=*/true); + + APInt Lower = getUnsignedMin().udiv(RHS.getUnsignedMax()); + + APInt RHS_umin = RHS.getUnsignedMin(); + if (RHS_umin == 0) { + // We want the lowest value in RHS excluding zero. Usually that would be 1 + // except for a range in the form of [X, 1) in which case it would be X. + if (RHS.getUpper() == 1) + RHS_umin = RHS.getLower(); + else + RHS_umin = APInt(getBitWidth(), 1); + } + + APInt Upper = getUnsignedMax().udiv(RHS_umin) + 1; + + // If the LHS is Full and the RHS is a wrapped interval containing 1 then + // this could occur. + if (Lower == Upper) + return ConstantRange(getBitWidth(), /*isFullSet=*/true); + + return ConstantRange(Lower, Upper); +} + +ConstantRange +ConstantRange::shl(const ConstantRange &Amount) const { + if (isEmptySet()) + return *this; + + APInt min = getUnsignedMin() << Amount.getUnsignedMin(); + APInt max = getUnsignedMax() << Amount.getUnsignedMax(); + + // there's no overflow! + APInt Zeros(getBitWidth(), getUnsignedMax().countLeadingZeros()); + if (Zeros.uge(Amount.getUnsignedMax())) + return ConstantRange(min, max); + + // FIXME: implement the other tricky cases + return ConstantRange(getBitWidth()); +} + +ConstantRange +ConstantRange::ashr(const ConstantRange &Amount) const { + if (isEmptySet()) + return *this; + + APInt min = getUnsignedMax().ashr(Amount.getUnsignedMin()); + APInt max = getUnsignedMin().ashr(Amount.getUnsignedMax()); + return ConstantRange(min, max); +} + +ConstantRange +ConstantRange::lshr(const ConstantRange &Amount) const { + if (isEmptySet()) + return *this; + + APInt min = getUnsignedMax().lshr(Amount.getUnsignedMin()); + APInt max = getUnsignedMin().lshr(Amount.getUnsignedMax()); + return ConstantRange(min, max); +} + +/// print - Print out the bounds to a stream... +/// +void ConstantRange::print(raw_ostream &OS) const { + OS << "[" << Lower << "," << Upper << ")"; +} + +/// dump - Allow printing from a debugger easily... +/// +void ConstantRange::dump() const { + print(errs()); +} + + diff --git a/libclamav/c++/llvm/lib/Support/Debug.cpp b/libclamav/c++/llvm/lib/Support/Debug.cpp new file mode 100644 index 000000000..50abe0164 --- /dev/null +++ b/libclamav/c++/llvm/lib/Support/Debug.cpp @@ -0,0 +1,74 @@ +//===-- Debug.cpp - An easy way to add debug output to your code ----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements a handle way of adding debugging information to your +// code, without it being enabled all of the time, and without having to add +// command line options to enable it. +// +// In particular, just wrap your code with the DEBUG() macro, and it will be +// enabled automatically if you specify '-debug' on the command-line. +// Alternatively, you can also use the SET_DEBUG_TYPE("foo") macro to specify +// that your debug code belongs to class "foo". Then, on the command line, you +// can specify '-debug-only=foo' to enable JUST the debug information for the +// foo class. +// +// When compiling in release mode, the -debug-* options and all code in DEBUG() +// statements disappears, so it does not effect the runtime of the code. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +using namespace llvm; + +// All Debug.h functionality is a no-op in NDEBUG mode. +#ifndef NDEBUG +bool llvm::DebugFlag; // DebugFlag - Exported boolean set by the -debug option + +// -debug - Command line option to enable the DEBUG statements in the passes. +// This flag may only be enabled in debug builds. +static cl::opt +Debug("debug", cl::desc("Enable debug output"), cl::Hidden, + cl::location(DebugFlag)); + +static std::string CurrentDebugType; +static struct DebugOnlyOpt { + void operator=(const std::string &Val) const { + DebugFlag |= !Val.empty(); + CurrentDebugType = Val; + } +} DebugOnlyOptLoc; + +static cl::opt > +DebugOnly("debug-only", cl::desc("Enable a specific type of debug output"), + cl::Hidden, cl::value_desc("debug string"), + cl::location(DebugOnlyOptLoc), cl::ValueRequired); + +// isCurrentDebugType - Return true if the specified string is the debug type +// specified on the command line, or if none was specified on the command line +// with the -debug-only=X option. +// +bool llvm::isCurrentDebugType(const char *DebugType) { + return CurrentDebugType.empty() || DebugType == CurrentDebugType; +} + +/// SetCurrentDebugType - Set the current debug type, as if the -debug-only=X +/// option were specified. Note that DebugFlag also needs to be set to true for +/// debug output to be produced. +/// +void llvm::SetCurrentDebugType(const char *Type) { + CurrentDebugType = Type; +} + +#else +// Avoid "has no symbols" warning. +namespace llvm { +int Debug_dummy = 0; +} +#endif diff --git a/libclamav/c++/llvm/lib/Support/Dwarf.cpp b/libclamav/c++/llvm/lib/Support/Dwarf.cpp new file mode 100644 index 000000000..8b688cae2 --- /dev/null +++ b/libclamav/c++/llvm/lib/Support/Dwarf.cpp @@ -0,0 +1,590 @@ +//===-- llvm/Support/Dwarf.cpp - Dwarf Framework ----------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains support for generic dwarf information. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/Dwarf.h" +#include "llvm/Support/ErrorHandling.h" + +#include + +namespace llvm { + +namespace dwarf { + +/// TagString - Return the string for the specified tag. +/// +const char *TagString(unsigned Tag) { + switch (Tag) { + case DW_TAG_array_type: return "DW_TAG_array_type"; + case DW_TAG_class_type: return "DW_TAG_class_type"; + case DW_TAG_entry_point: return "DW_TAG_entry_point"; + case DW_TAG_enumeration_type: return "DW_TAG_enumeration_type"; + case DW_TAG_formal_parameter: return "DW_TAG_formal_parameter"; + case DW_TAG_imported_declaration: return "DW_TAG_imported_declaration"; + case DW_TAG_label: return "DW_TAG_label"; + case DW_TAG_lexical_block: return "DW_TAG_lexical_block"; + case DW_TAG_member: return "DW_TAG_member"; + case DW_TAG_pointer_type: return "DW_TAG_pointer_type"; + case DW_TAG_reference_type: return "DW_TAG_reference_type"; + case DW_TAG_compile_unit: return "DW_TAG_compile_unit"; + case DW_TAG_string_type: return "DW_TAG_string_type"; + case DW_TAG_structure_type: return "DW_TAG_structure_type"; + case DW_TAG_subroutine_type: return "DW_TAG_subroutine_type"; + case DW_TAG_typedef: return "DW_TAG_typedef"; + case DW_TAG_union_type: return "DW_TAG_union_type"; + case DW_TAG_unspecified_parameters: return "DW_TAG_unspecified_parameters"; + case DW_TAG_variant: return "DW_TAG_variant"; + case DW_TAG_common_block: return "DW_TAG_common_block"; + case DW_TAG_common_inclusion: return "DW_TAG_common_inclusion"; + case DW_TAG_inheritance: return "DW_TAG_inheritance"; + case DW_TAG_inlined_subroutine: return "DW_TAG_inlined_subroutine"; + case DW_TAG_module: return "DW_TAG_module"; + case DW_TAG_ptr_to_member_type: return "DW_TAG_ptr_to_member_type"; + case DW_TAG_set_type: return "DW_TAG_set_type"; + case DW_TAG_subrange_type: return "DW_TAG_subrange_type"; + case DW_TAG_with_stmt: return "DW_TAG_with_stmt"; + case DW_TAG_access_declaration: return "DW_TAG_access_declaration"; + case DW_TAG_base_type: return "DW_TAG_base_type"; + case DW_TAG_catch_block: return "DW_TAG_catch_block"; + case DW_TAG_const_type: return "DW_TAG_const_type"; + case DW_TAG_constant: return "DW_TAG_constant"; + case DW_TAG_enumerator: return "DW_TAG_enumerator"; + case DW_TAG_file_type: return "DW_TAG_file_type"; + case DW_TAG_friend: return "DW_TAG_friend"; + case DW_TAG_namelist: return "DW_TAG_namelist"; + case DW_TAG_namelist_item: return "DW_TAG_namelist_item"; + case DW_TAG_packed_type: return "DW_TAG_packed_type"; + case DW_TAG_subprogram: return "DW_TAG_subprogram"; + case DW_TAG_template_type_parameter: return "DW_TAG_template_type_parameter"; + case DW_TAG_template_value_parameter: return "DW_TAG_template_value_parameter"; + case DW_TAG_thrown_type: return "DW_TAG_thrown_type"; + case DW_TAG_try_block: return "DW_TAG_try_block"; + case DW_TAG_variant_part: return "DW_TAG_variant_part"; + case DW_TAG_variable: return "DW_TAG_variable"; + case DW_TAG_volatile_type: return "DW_TAG_volatile_type"; + case DW_TAG_dwarf_procedure: return "DW_TAG_dwarf_procedure"; + case DW_TAG_restrict_type: return "DW_TAG_restrict_type"; + case DW_TAG_interface_type: return "DW_TAG_interface_type"; + case DW_TAG_namespace: return "DW_TAG_namespace"; + case DW_TAG_imported_module: return "DW_TAG_imported_module"; + case DW_TAG_unspecified_type: return "DW_TAG_unspecified_type"; + case DW_TAG_partial_unit: return "DW_TAG_partial_unit"; + case DW_TAG_imported_unit: return "DW_TAG_imported_unit"; + case DW_TAG_condition: return "DW_TAG_condition"; + case DW_TAG_shared_type: return "DW_TAG_shared_type"; + case DW_TAG_lo_user: return "DW_TAG_lo_user"; + case DW_TAG_hi_user: return "DW_TAG_hi_user"; + } + llvm_unreachable("Unknown Dwarf Tag"); + return ""; +} + +/// ChildrenString - Return the string for the specified children flag. +/// +const char *ChildrenString(unsigned Children) { + switch (Children) { + case DW_CHILDREN_no: return "CHILDREN_no"; + case DW_CHILDREN_yes: return "CHILDREN_yes"; + } + llvm_unreachable("Unknown Dwarf ChildrenFlag"); + return ""; +} + +/// AttributeString - Return the string for the specified attribute. +/// +const char *AttributeString(unsigned Attribute) { + switch (Attribute) { + case DW_AT_sibling: return "DW_AT_sibling"; + case DW_AT_location: return "DW_AT_location"; + case DW_AT_name: return "DW_AT_name"; + case DW_AT_ordering: return "DW_AT_ordering"; + case DW_AT_byte_size: return "DW_AT_byte_size"; + case DW_AT_bit_offset: return "DW_AT_bit_offset"; + case DW_AT_bit_size: return "DW_AT_bit_size"; + case DW_AT_stmt_list: return "DW_AT_stmt_list"; + case DW_AT_low_pc: return "DW_AT_low_pc"; + case DW_AT_high_pc: return "DW_AT_high_pc"; + case DW_AT_language: return "DW_AT_language"; + case DW_AT_discr: return "DW_AT_discr"; + case DW_AT_discr_value: return "DW_AT_discr_value"; + case DW_AT_visibility: return "DW_AT_visibility"; + case DW_AT_import: return "DW_AT_import"; + case DW_AT_string_length: return "DW_AT_string_length"; + case DW_AT_common_reference: return "DW_AT_common_reference"; + case DW_AT_comp_dir: return "DW_AT_comp_dir"; + case DW_AT_const_value: return "DW_AT_const_value"; + case DW_AT_containing_type: return "DW_AT_containing_type"; + case DW_AT_default_value: return "DW_AT_default_value"; + case DW_AT_inline: return "DW_AT_inline"; + case DW_AT_is_optional: return "DW_AT_is_optional"; + case DW_AT_lower_bound: return "DW_AT_lower_bound"; + case DW_AT_producer: return "DW_AT_producer"; + case DW_AT_prototyped: return "DW_AT_prototyped"; + case DW_AT_return_addr: return "DW_AT_return_addr"; + case DW_AT_start_scope: return "DW_AT_start_scope"; + case DW_AT_bit_stride: return "DW_AT_bit_stride"; + case DW_AT_upper_bound: return "DW_AT_upper_bound"; + case DW_AT_abstract_origin: return "DW_AT_abstract_origin"; + case DW_AT_accessibility: return "DW_AT_accessibility"; + case DW_AT_address_class: return "DW_AT_address_class"; + case DW_AT_artificial: return "DW_AT_artificial"; + case DW_AT_base_types: return "DW_AT_base_types"; + case DW_AT_calling_convention: return "DW_AT_calling_convention"; + case DW_AT_count: return "DW_AT_count"; + case DW_AT_data_member_location: return "DW_AT_data_member_location"; + case DW_AT_decl_column: return "DW_AT_decl_column"; + case DW_AT_decl_file: return "DW_AT_decl_file"; + case DW_AT_decl_line: return "DW_AT_decl_line"; + case DW_AT_declaration: return "DW_AT_declaration"; + case DW_AT_discr_list: return "DW_AT_discr_list"; + case DW_AT_encoding: return "DW_AT_encoding"; + case DW_AT_external: return "DW_AT_external"; + case DW_AT_frame_base: return "DW_AT_frame_base"; + case DW_AT_friend: return "DW_AT_friend"; + case DW_AT_identifier_case: return "DW_AT_identifier_case"; + case DW_AT_macro_info: return "DW_AT_macro_info"; + case DW_AT_namelist_item: return "DW_AT_namelist_item"; + case DW_AT_priority: return "DW_AT_priority"; + case DW_AT_segment: return "DW_AT_segment"; + case DW_AT_specification: return "DW_AT_specification"; + case DW_AT_static_link: return "DW_AT_static_link"; + case DW_AT_type: return "DW_AT_type"; + case DW_AT_use_location: return "DW_AT_use_location"; + case DW_AT_variable_parameter: return "DW_AT_variable_parameter"; + case DW_AT_virtuality: return "DW_AT_virtuality"; + case DW_AT_vtable_elem_location: return "DW_AT_vtable_elem_location"; + case DW_AT_allocated: return "DW_AT_allocated"; + case DW_AT_associated: return "DW_AT_associated"; + case DW_AT_data_location: return "DW_AT_data_location"; + case DW_AT_byte_stride: return "DW_AT_byte_stride"; + case DW_AT_entry_pc: return "DW_AT_entry_pc"; + case DW_AT_use_UTF8: return "DW_AT_use_UTF8"; + case DW_AT_extension: return "DW_AT_extension"; + case DW_AT_ranges: return "DW_AT_ranges"; + case DW_AT_trampoline: return "DW_AT_trampoline"; + case DW_AT_call_column: return "DW_AT_call_column"; + case DW_AT_call_file: return "DW_AT_call_file"; + case DW_AT_call_line: return "DW_AT_call_line"; + case DW_AT_description: return "DW_AT_description"; + case DW_AT_binary_scale: return "DW_AT_binary_scale"; + case DW_AT_decimal_scale: return "DW_AT_decimal_scale"; + case DW_AT_small: return "DW_AT_small"; + case DW_AT_decimal_sign: return "DW_AT_decimal_sign"; + case DW_AT_digit_count: return "DW_AT_digit_count"; + case DW_AT_picture_string: return "DW_AT_picture_string"; + case DW_AT_mutable: return "DW_AT_mutable"; + case DW_AT_threads_scaled: return "DW_AT_threads_scaled"; + case DW_AT_explicit: return "DW_AT_explicit"; + case DW_AT_object_pointer: return "DW_AT_object_pointer"; + case DW_AT_endianity: return "DW_AT_endianity"; + case DW_AT_elemental: return "DW_AT_elemental"; + case DW_AT_pure: return "DW_AT_pure"; + case DW_AT_recursive: return "DW_AT_recursive"; + case DW_AT_MIPS_linkage_name: return "DW_AT_MIPS_linkage_name"; + case DW_AT_sf_names: return "DW_AT_sf_names"; + case DW_AT_src_info: return "DW_AT_src_info"; + case DW_AT_mac_info: return "DW_AT_mac_info"; + case DW_AT_src_coords: return "DW_AT_src_coords"; + case DW_AT_body_begin: return "DW_AT_body_begin"; + case DW_AT_body_end: return "DW_AT_body_end"; + case DW_AT_GNU_vector: return "DW_AT_GNU_vector"; + case DW_AT_lo_user: return "DW_AT_lo_user"; + case DW_AT_hi_user: return "DW_AT_hi_user"; + case DW_AT_APPLE_optimized: return "DW_AT_APPLE_optimized"; + case DW_AT_APPLE_flags: return "DW_AT_APPLE_flags"; + case DW_AT_APPLE_isa: return "DW_AT_APPLE_isa"; + case DW_AT_APPLE_block: return "DW_AT_APPLE_block"; + case DW_AT_APPLE_major_runtime_vers: return "DW_AT_APPLE_major_runtime_vers"; + case DW_AT_APPLE_runtime_class: return "DW_AT_APPLE_runtime_class"; + } + llvm_unreachable("Unknown Dwarf Attribute"); + return ""; +} + +/// FormEncodingString - Return the string for the specified form encoding. +/// +const char *FormEncodingString(unsigned Encoding) { + switch (Encoding) { + case DW_FORM_addr: return "FORM_addr"; + case DW_FORM_block2: return "FORM_block2"; + case DW_FORM_block4: return "FORM_block4"; + case DW_FORM_data2: return "FORM_data2"; + case DW_FORM_data4: return "FORM_data4"; + case DW_FORM_data8: return "FORM_data8"; + case DW_FORM_string: return "FORM_string"; + case DW_FORM_block: return "FORM_block"; + case DW_FORM_block1: return "FORM_block1"; + case DW_FORM_data1: return "FORM_data1"; + case DW_FORM_flag: return "FORM_flag"; + case DW_FORM_sdata: return "FORM_sdata"; + case DW_FORM_strp: return "FORM_strp"; + case DW_FORM_udata: return "FORM_udata"; + case DW_FORM_ref_addr: return "FORM_ref_addr"; + case DW_FORM_ref1: return "FORM_ref1"; + case DW_FORM_ref2: return "FORM_ref2"; + case DW_FORM_ref4: return "FORM_ref4"; + case DW_FORM_ref8: return "FORM_ref8"; + case DW_FORM_ref_udata: return "FORM_ref_udata"; + case DW_FORM_indirect: return "FORM_indirect"; + } + llvm_unreachable("Unknown Dwarf Form Encoding"); + return ""; +} + +/// OperationEncodingString - Return the string for the specified operation +/// encoding. +const char *OperationEncodingString(unsigned Encoding) { + switch (Encoding) { + case DW_OP_addr: return "OP_addr"; + case DW_OP_deref: return "OP_deref"; + case DW_OP_const1u: return "OP_const1u"; + case DW_OP_const1s: return "OP_const1s"; + case DW_OP_const2u: return "OP_const2u"; + case DW_OP_const2s: return "OP_const2s"; + case DW_OP_const4u: return "OP_const4u"; + case DW_OP_const4s: return "OP_const4s"; + case DW_OP_const8u: return "OP_const8u"; + case DW_OP_const8s: return "OP_const8s"; + case DW_OP_constu: return "OP_constu"; + case DW_OP_consts: return "OP_consts"; + case DW_OP_dup: return "OP_dup"; + case DW_OP_drop: return "OP_drop"; + case DW_OP_over: return "OP_over"; + case DW_OP_pick: return "OP_pick"; + case DW_OP_swap: return "OP_swap"; + case DW_OP_rot: return "OP_rot"; + case DW_OP_xderef: return "OP_xderef"; + case DW_OP_abs: return "OP_abs"; + case DW_OP_and: return "OP_and"; + case DW_OP_div: return "OP_div"; + case DW_OP_minus: return "OP_minus"; + case DW_OP_mod: return "OP_mod"; + case DW_OP_mul: return "OP_mul"; + case DW_OP_neg: return "OP_neg"; + case DW_OP_not: return "OP_not"; + case DW_OP_or: return "OP_or"; + case DW_OP_plus: return "OP_plus"; + case DW_OP_plus_uconst: return "OP_plus_uconst"; + case DW_OP_shl: return "OP_shl"; + case DW_OP_shr: return "OP_shr"; + case DW_OP_shra: return "OP_shra"; + case DW_OP_xor: return "OP_xor"; + case DW_OP_skip: return "OP_skip"; + case DW_OP_bra: return "OP_bra"; + case DW_OP_eq: return "OP_eq"; + case DW_OP_ge: return "OP_ge"; + case DW_OP_gt: return "OP_gt"; + case DW_OP_le: return "OP_le"; + case DW_OP_lt: return "OP_lt"; + case DW_OP_ne: return "OP_ne"; + case DW_OP_lit0: return "OP_lit0"; + case DW_OP_lit1: return "OP_lit1"; + case DW_OP_lit31: return "OP_lit31"; + case DW_OP_reg0: return "OP_reg0"; + case DW_OP_reg1: return "OP_reg1"; + case DW_OP_reg31: return "OP_reg31"; + case DW_OP_breg0: return "OP_breg0"; + case DW_OP_breg1: return "OP_breg1"; + case DW_OP_breg31: return "OP_breg31"; + case DW_OP_regx: return "OP_regx"; + case DW_OP_fbreg: return "OP_fbreg"; + case DW_OP_bregx: return "OP_bregx"; + case DW_OP_piece: return "OP_piece"; + case DW_OP_deref_size: return "OP_deref_size"; + case DW_OP_xderef_size: return "OP_xderef_size"; + case DW_OP_nop: return "OP_nop"; + case DW_OP_push_object_address: return "OP_push_object_address"; + case DW_OP_call2: return "OP_call2"; + case DW_OP_call4: return "OP_call4"; + case DW_OP_call_ref: return "OP_call_ref"; + case DW_OP_form_tls_address: return "OP_form_tls_address"; + case DW_OP_call_frame_cfa: return "OP_call_frame_cfa"; + case DW_OP_lo_user: return "OP_lo_user"; + case DW_OP_hi_user: return "OP_hi_user"; + } + llvm_unreachable("Unknown Dwarf Operation Encoding"); + return ""; +} + +/// AttributeEncodingString - Return the string for the specified attribute +/// encoding. +const char *AttributeEncodingString(unsigned Encoding) { + switch (Encoding) { + case DW_ATE_address: return "ATE_address"; + case DW_ATE_boolean: return "ATE_boolean"; + case DW_ATE_complex_float: return "ATE_complex_float"; + case DW_ATE_float: return "ATE_float"; + case DW_ATE_signed: return "ATE_signed"; + case DW_ATE_signed_char: return "ATE_signed_char"; + case DW_ATE_unsigned: return "ATE_unsigned"; + case DW_ATE_unsigned_char: return "ATE_unsigned_char"; + case DW_ATE_imaginary_float: return "ATE_imaginary_float"; + case DW_ATE_packed_decimal: return "ATE_packed_decimal"; + case DW_ATE_numeric_string: return "ATE_numeric_string"; + case DW_ATE_edited: return "ATE_edited"; + case DW_ATE_signed_fixed: return "ATE_signed_fixed"; + case DW_ATE_unsigned_fixed: return "ATE_unsigned_fixed"; + case DW_ATE_decimal_float: return "ATE_decimal_float"; + case DW_ATE_lo_user: return "ATE_lo_user"; + case DW_ATE_hi_user: return "ATE_hi_user"; + } + llvm_unreachable("Unknown Dwarf Attribute Encoding"); + return ""; +} + +/// DecimalSignString - Return the string for the specified decimal sign +/// attribute. +const char *DecimalSignString(unsigned Sign) { + switch (Sign) { + case DW_DS_unsigned: return "DS_unsigned"; + case DW_DS_leading_overpunch: return "DS_leading_overpunch"; + case DW_DS_trailing_overpunch: return "DS_trailing_overpunch"; + case DW_DS_leading_separate: return "DS_leading_separate"; + case DW_DS_trailing_separate: return "DS_trailing_separate"; + } + llvm_unreachable("Unknown Dwarf Decimal Sign Attribute"); + return ""; +} + +/// EndianityString - Return the string for the specified endianity. +/// +const char *EndianityString(unsigned Endian) { + switch (Endian) { + case DW_END_default: return "END_default"; + case DW_END_big: return "END_big"; + case DW_END_little: return "END_little"; + case DW_END_lo_user: return "END_lo_user"; + case DW_END_hi_user: return "END_hi_user"; + } + llvm_unreachable("Unknown Dwarf Endianity"); + return ""; +} + +/// AccessibilityString - Return the string for the specified accessibility. +/// +const char *AccessibilityString(unsigned Access) { + switch (Access) { + // Accessibility codes + case DW_ACCESS_public: return "ACCESS_public"; + case DW_ACCESS_protected: return "ACCESS_protected"; + case DW_ACCESS_private: return "ACCESS_private"; + } + llvm_unreachable("Unknown Dwarf Accessibility"); + return ""; +} + +/// VisibilityString - Return the string for the specified visibility. +/// +const char *VisibilityString(unsigned Visibility) { + switch (Visibility) { + case DW_VIS_local: return "VIS_local"; + case DW_VIS_exported: return "VIS_exported"; + case DW_VIS_qualified: return "VIS_qualified"; + } + llvm_unreachable("Unknown Dwarf Visibility"); + return ""; +} + +/// VirtualityString - Return the string for the specified virtuality. +/// +const char *VirtualityString(unsigned Virtuality) { + switch (Virtuality) { + case DW_VIRTUALITY_none: return "VIRTUALITY_none"; + case DW_VIRTUALITY_virtual: return "VIRTUALITY_virtual"; + case DW_VIRTUALITY_pure_virtual: return "VIRTUALITY_pure_virtual"; + } + llvm_unreachable("Unknown Dwarf Virtuality"); + return ""; +} + +/// LanguageString - Return the string for the specified language. +/// +const char *LanguageString(unsigned Language) { + switch (Language) { + case DW_LANG_C89: return "LANG_C89"; + case DW_LANG_C: return "LANG_C"; + case DW_LANG_Ada83: return "LANG_Ada83"; + case DW_LANG_C_plus_plus: return "LANG_C_plus_plus"; + case DW_LANG_Cobol74: return "LANG_Cobol74"; + case DW_LANG_Cobol85: return "LANG_Cobol85"; + case DW_LANG_Fortran77: return "LANG_Fortran77"; + case DW_LANG_Fortran90: return "LANG_Fortran90"; + case DW_LANG_Pascal83: return "LANG_Pascal83"; + case DW_LANG_Modula2: return "LANG_Modula2"; + case DW_LANG_Java: return "LANG_Java"; + case DW_LANG_C99: return "LANG_C99"; + case DW_LANG_Ada95: return "LANG_Ada95"; + case DW_LANG_Fortran95: return "LANG_Fortran95"; + case DW_LANG_PLI: return "LANG_PLI"; + case DW_LANG_ObjC: return "LANG_ObjC"; + case DW_LANG_ObjC_plus_plus: return "LANG_ObjC_plus_plus"; + case DW_LANG_UPC: return "LANG_UPC"; + case DW_LANG_D: return "LANG_D"; + case DW_LANG_lo_user: return "LANG_lo_user"; + case DW_LANG_hi_user: return "LANG_hi_user"; + } + llvm_unreachable("Unknown Dwarf Language"); + return ""; +} + +/// CaseString - Return the string for the specified identifier case. +/// +const char *CaseString(unsigned Case) { + switch (Case) { + case DW_ID_case_sensitive: return "ID_case_sensitive"; + case DW_ID_up_case: return "ID_up_case"; + case DW_ID_down_case: return "ID_down_case"; + case DW_ID_case_insensitive: return "ID_case_insensitive"; + } + llvm_unreachable("Unknown Dwarf Identifier Case"); + return ""; +} + +/// ConventionString - Return the string for the specified calling convention. +/// +const char *ConventionString(unsigned Convention) { + switch (Convention) { + case DW_CC_normal: return "CC_normal"; + case DW_CC_program: return "CC_program"; + case DW_CC_nocall: return "CC_nocall"; + case DW_CC_lo_user: return "CC_lo_user"; + case DW_CC_hi_user: return "CC_hi_user"; + } + llvm_unreachable("Unknown Dwarf Calling Convention"); + return ""; +} + +/// InlineCodeString - Return the string for the specified inline code. +/// +const char *InlineCodeString(unsigned Code) { + switch (Code) { + case DW_INL_not_inlined: return "INL_not_inlined"; + case DW_INL_inlined: return "INL_inlined"; + case DW_INL_declared_not_inlined: return "INL_declared_not_inlined"; + case DW_INL_declared_inlined: return "INL_declared_inlined"; + } + llvm_unreachable("Unknown Dwarf Inline Code"); + return ""; +} + +/// ArrayOrderString - Return the string for the specified array order. +/// +const char *ArrayOrderString(unsigned Order) { + switch (Order) { + case DW_ORD_row_major: return "ORD_row_major"; + case DW_ORD_col_major: return "ORD_col_major"; + } + llvm_unreachable("Unknown Dwarf Array Order"); + return ""; +} + +/// DiscriminantString - Return the string for the specified discriminant +/// descriptor. +const char *DiscriminantString(unsigned Discriminant) { + switch (Discriminant) { + case DW_DSC_label: return "DSC_label"; + case DW_DSC_range: return "DSC_range"; + } + llvm_unreachable("Unknown Dwarf Discriminant Descriptor"); + return ""; +} + +/// LNStandardString - Return the string for the specified line number standard. +/// +const char *LNStandardString(unsigned Standard) { + switch (Standard) { + case DW_LNS_copy: return "LNS_copy"; + case DW_LNS_advance_pc: return "LNS_advance_pc"; + case DW_LNS_advance_line: return "LNS_advance_line"; + case DW_LNS_set_file: return "LNS_set_file"; + case DW_LNS_set_column: return "LNS_set_column"; + case DW_LNS_negate_stmt: return "LNS_negate_stmt"; + case DW_LNS_set_basic_block: return "LNS_set_basic_block"; + case DW_LNS_const_add_pc: return "LNS_const_add_pc"; + case DW_LNS_fixed_advance_pc: return "LNS_fixed_advance_pc"; + case DW_LNS_set_prologue_end: return "LNS_set_prologue_end"; + case DW_LNS_set_epilogue_begin: return "LNS_set_epilogue_begin"; + case DW_LNS_set_isa: return "LNS_set_isa"; + } + llvm_unreachable("Unknown Dwarf Line Number Standard"); + return ""; +} + +/// LNExtendedString - Return the string for the specified line number extended +/// opcode encodings. +const char *LNExtendedString(unsigned Encoding) { + switch (Encoding) { + // Line Number Extended Opcode Encodings + case DW_LNE_end_sequence: return "LNE_end_sequence"; + case DW_LNE_set_address: return "LNE_set_address"; + case DW_LNE_define_file: return "LNE_define_file"; + case DW_LNE_lo_user: return "LNE_lo_user"; + case DW_LNE_hi_user: return "LNE_hi_user"; + } + llvm_unreachable("Unknown Dwarf Line Number Extended Opcode Encoding"); + return ""; +} + +/// MacinfoString - Return the string for the specified macinfo type encodings. +/// +const char *MacinfoString(unsigned Encoding) { + switch (Encoding) { + // Macinfo Type Encodings + case DW_MACINFO_define: return "MACINFO_define"; + case DW_MACINFO_undef: return "MACINFO_undef"; + case DW_MACINFO_start_file: return "MACINFO_start_file"; + case DW_MACINFO_end_file: return "MACINFO_end_file"; + case DW_MACINFO_vendor_ext: return "MACINFO_vendor_ext"; + } + llvm_unreachable("Unknown Dwarf Macinfo Type Encodings"); + return ""; +} + +/// CallFrameString - Return the string for the specified call frame instruction +/// encodings. +const char *CallFrameString(unsigned Encoding) { + switch (Encoding) { + case DW_CFA_advance_loc: return "CFA_advance_loc"; + case DW_CFA_offset: return "CFA_offset"; + case DW_CFA_restore: return "CFA_restore"; + case DW_CFA_set_loc: return "CFA_set_loc"; + case DW_CFA_advance_loc1: return "CFA_advance_loc1"; + case DW_CFA_advance_loc2: return "CFA_advance_loc2"; + case DW_CFA_advance_loc4: return "CFA_advance_loc4"; + case DW_CFA_offset_extended: return "CFA_offset_extended"; + case DW_CFA_restore_extended: return "CFA_restore_extended"; + case DW_CFA_undefined: return "CFA_undefined"; + case DW_CFA_same_value: return "CFA_same_value"; + case DW_CFA_register: return "CFA_register"; + case DW_CFA_remember_state: return "CFA_remember_state"; + case DW_CFA_restore_state: return "CFA_restore_state"; + case DW_CFA_def_cfa: return "CFA_def_cfa"; + case DW_CFA_def_cfa_register: return "CFA_def_cfa_register"; + case DW_CFA_def_cfa_offset: return "CFA_def_cfa_offset"; + case DW_CFA_def_cfa_expression: return "CFA_def_cfa_expression"; + case DW_CFA_expression: return "CFA_expression"; + case DW_CFA_offset_extended_sf: return "CFA_offset_extended_sf"; + case DW_CFA_def_cfa_sf: return "CFA_def_cfa_sf"; + case DW_CFA_def_cfa_offset_sf: return "CFA_def_cfa_offset_sf"; + case DW_CFA_val_offset: return "CFA_val_offset"; + case DW_CFA_val_offset_sf: return "CFA_val_offset_sf"; + case DW_CFA_val_expression: return "CFA_val_expression"; + case DW_CFA_lo_user: return "CFA_lo_user"; + case DW_CFA_hi_user: return "CFA_hi_user"; + } + llvm_unreachable("Unknown Dwarf Call Frame Instruction Encodings"); + return ""; +} + +} // End of namespace dwarf. + +} // End of namespace llvm. diff --git a/libclamav/c++/llvm/lib/Support/ErrorHandling.cpp b/libclamav/c++/llvm/lib/Support/ErrorHandling.cpp new file mode 100644 index 000000000..dff4f030f --- /dev/null +++ b/libclamav/c++/llvm/lib/Support/ErrorHandling.cpp @@ -0,0 +1,73 @@ +//===- lib/Support/ErrorHandling.cpp - Callbacks for errors -----*- 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 an API for error handling, it supersedes cerr+abort(), and +// cerr+exit() style error handling. +// Callbacks can be registered for these errors through this API. +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/Twine.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/System/Threading.h" +#include +#include + +using namespace llvm; +using namespace std; + +static llvm_error_handler_t ErrorHandler = 0; +static void *ErrorHandlerUserData = 0; + +namespace llvm { +void llvm_install_error_handler(llvm_error_handler_t handler, + void *user_data) { + assert(!llvm_is_multithreaded() && + "Cannot register error handlers after starting multithreaded mode!\n"); + assert(!ErrorHandler && "Error handler already registered!\n"); + ErrorHandler = handler; + ErrorHandlerUserData = user_data; +} + +void llvm_remove_error_handler() { + ErrorHandler = 0; +} + +void llvm_report_error(const char *reason) { + llvm_report_error(Twine(reason)); +} + +void llvm_report_error(const std::string &reason) { + llvm_report_error(Twine(reason)); +} + +void llvm_report_error(const Twine &reason) { + if (!ErrorHandler) { + errs() << "LLVM ERROR: " << reason << "\n"; + } else { + ErrorHandler(ErrorHandlerUserData, reason.str()); + } + exit(1); +} + +void llvm_unreachable_internal(const char *msg, const char *file, + unsigned line) { + // This code intentionally doesn't call the ErrorHandler callback, because + // llvm_unreachable is intended to be used to indicate "impossible" + // situations, and not legitimate runtime errors. + if (msg) + errs() << msg << "\n"; + errs() << "UNREACHABLE executed"; + if (file) + errs() << " at " << file << ":" << line; + errs() << "!\n"; + abort(); +} +} + diff --git a/libclamav/c++/llvm/lib/Support/FileUtilities.cpp b/libclamav/c++/llvm/lib/Support/FileUtilities.cpp new file mode 100644 index 000000000..21080b643 --- /dev/null +++ b/libclamav/c++/llvm/lib/Support/FileUtilities.cpp @@ -0,0 +1,263 @@ +//===- Support/FileUtilities.cpp - File System Utilities ------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements a family of utility functions which are useful for doing +// various things with files. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/FileUtilities.h" +#include "llvm/System/Path.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringExtras.h" +#include +#include +#include +using namespace llvm; + +static bool isSignedChar(char C) { + return (C == '+' || C == '-'); +} + +static bool isExponentChar(char C) { + switch (C) { + case 'D': // Strange exponential notation. + case 'd': // Strange exponential notation. + case 'e': + case 'E': return true; + default: return false; + } +} + +static bool isNumberChar(char C) { + switch (C) { + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + case '.': return true; + default: return isSignedChar(C) || isExponentChar(C); + } +} + +static const char *BackupNumber(const char *Pos, const char *FirstChar) { + // If we didn't stop in the middle of a number, don't backup. + if (!isNumberChar(*Pos)) return Pos; + + // Otherwise, return to the start of the number. + while (Pos > FirstChar && isNumberChar(Pos[-1])) { + --Pos; + if (Pos > FirstChar && isSignedChar(Pos[0]) && !isExponentChar(Pos[-1])) + break; + } + return Pos; +} + +/// EndOfNumber - Return the first character that is not part of the specified +/// number. This assumes that the buffer is null terminated, so it won't fall +/// off the end. +static const char *EndOfNumber(const char *Pos) { + while (isNumberChar(*Pos)) + ++Pos; + return Pos; +} + +/// CompareNumbers - compare two numbers, returning true if they are different. +static bool CompareNumbers(const char *&F1P, const char *&F2P, + const char *F1End, const char *F2End, + double AbsTolerance, double RelTolerance, + std::string *ErrorMsg) { + const char *F1NumEnd, *F2NumEnd; + double V1 = 0.0, V2 = 0.0; + + // If one of the positions is at a space and the other isn't, chomp up 'til + // the end of the space. + while (isspace(*F1P) && F1P != F1End) + ++F1P; + while (isspace(*F2P) && F2P != F2End) + ++F2P; + + // If we stop on numbers, compare their difference. + if (!isNumberChar(*F1P) || !isNumberChar(*F2P)) { + // The diff failed. + F1NumEnd = F1P; + F2NumEnd = F2P; + } else { + // Note that some ugliness is built into this to permit support for numbers + // that use "D" or "d" as their exponential marker, e.g. "1.234D45". This + // occurs in 200.sixtrack in spec2k. + V1 = strtod(F1P, const_cast(&F1NumEnd)); + V2 = strtod(F2P, const_cast(&F2NumEnd)); + + if (*F1NumEnd == 'D' || *F1NumEnd == 'd') { + // Copy string into tmp buffer to replace the 'D' with an 'e'. + SmallString<200> StrTmp(F1P, EndOfNumber(F1NumEnd)+1); + // Strange exponential notation! + StrTmp[static_cast(F1NumEnd-F1P)] = 'e'; + + V1 = strtod(&StrTmp[0], const_cast(&F1NumEnd)); + F1NumEnd = F1P + (F1NumEnd-&StrTmp[0]); + } + + if (*F2NumEnd == 'D' || *F2NumEnd == 'd') { + // Copy string into tmp buffer to replace the 'D' with an 'e'. + SmallString<200> StrTmp(F2P, EndOfNumber(F2NumEnd)+1); + // Strange exponential notation! + StrTmp[static_cast(F2NumEnd-F2P)] = 'e'; + + V2 = strtod(&StrTmp[0], const_cast(&F2NumEnd)); + F2NumEnd = F2P + (F2NumEnd-&StrTmp[0]); + } + } + + if (F1NumEnd == F1P || F2NumEnd == F2P) { + if (ErrorMsg) { + *ErrorMsg = "FP Comparison failed, not a numeric difference between '"; + *ErrorMsg += F1P[0]; + *ErrorMsg += "' and '"; + *ErrorMsg += F2P[0]; + *ErrorMsg += "'"; + } + return true; + } + + // Check to see if these are inside the absolute tolerance + if (AbsTolerance < std::abs(V1-V2)) { + // Nope, check the relative tolerance... + double Diff; + if (V2) + Diff = std::abs(V1/V2 - 1.0); + else if (V1) + Diff = std::abs(V2/V1 - 1.0); + else + Diff = 0; // Both zero. + if (Diff > RelTolerance) { + if (ErrorMsg) { + *ErrorMsg = "Compared: " + ftostr(V1) + " and " + ftostr(V2) + "\n"; + *ErrorMsg += "abs. diff = " + ftostr(std::abs(V1-V2)) + + " rel.diff = " + ftostr(Diff) + "\n"; + *ErrorMsg += "Out of tolerance: rel/abs: " + ftostr(RelTolerance) + + "/" + ftostr(AbsTolerance); + } + return true; + } + } + + // Otherwise, advance our read pointers to the end of the numbers. + F1P = F1NumEnd; F2P = F2NumEnd; + return false; +} + +/// DiffFilesWithTolerance - Compare the two files specified, returning 0 if the +/// files match, 1 if they are different, and 2 if there is a file error. This +/// function differs from DiffFiles in that you can specify an absolete and +/// relative FP error that is allowed to exist. If you specify a string to fill +/// in for the error option, it will set the string to an error message if an +/// error occurs, allowing the caller to distinguish between a failed diff and a +/// file system error. +/// +int llvm::DiffFilesWithTolerance(const sys::PathWithStatus &FileA, + const sys::PathWithStatus &FileB, + double AbsTol, double RelTol, + std::string *Error) { + const sys::FileStatus *FileAStat = FileA.getFileStatus(false, Error); + if (!FileAStat) + return 2; + const sys::FileStatus *FileBStat = FileB.getFileStatus(false, Error); + if (!FileBStat) + return 2; + + // Check for zero length files because some systems croak when you try to + // mmap an empty file. + size_t A_size = FileAStat->getSize(); + size_t B_size = FileBStat->getSize(); + + // If they are both zero sized then they're the same + if (A_size == 0 && B_size == 0) + return 0; + + // If only one of them is zero sized then they can't be the same + if ((A_size == 0 || B_size == 0)) { + if (Error) + *Error = "Files differ: one is zero-sized, the other isn't"; + return 1; + } + + // Now its safe to mmap the files into memory becasue both files + // have a non-zero size. + OwningPtr F1(MemoryBuffer::getFile(FileA.c_str(), Error)); + OwningPtr F2(MemoryBuffer::getFile(FileB.c_str(), Error)); + if (F1 == 0 || F2 == 0) + return 2; + + // Okay, now that we opened the files, scan them for the first difference. + const char *File1Start = F1->getBufferStart(); + const char *File2Start = F2->getBufferStart(); + const char *File1End = F1->getBufferEnd(); + const char *File2End = F2->getBufferEnd(); + const char *F1P = File1Start; + const char *F2P = File2Start; + + if (A_size == B_size) { + // Are the buffers identical? Common case: Handle this efficiently. + if (std::memcmp(File1Start, File2Start, A_size) == 0) + return 0; + + if (AbsTol == 0 && RelTol == 0) { + if (Error) + *Error = "Files differ without tolerance allowance"; + return 1; // Files different! + } + } + + bool CompareFailed = false; + while (1) { + // Scan for the end of file or next difference. + while (F1P < File1End && F2P < File2End && *F1P == *F2P) + ++F1P, ++F2P; + + if (F1P >= File1End || F2P >= File2End) break; + + // Okay, we must have found a difference. Backup to the start of the + // current number each stream is at so that we can compare from the + // beginning. + F1P = BackupNumber(F1P, File1Start); + F2P = BackupNumber(F2P, File2Start); + + // Now that we are at the start of the numbers, compare them, exiting if + // they don't match. + if (CompareNumbers(F1P, F2P, File1End, File2End, AbsTol, RelTol, Error)) { + CompareFailed = true; + break; + } + } + + // Okay, we reached the end of file. If both files are at the end, we + // succeeded. + bool F1AtEnd = F1P >= File1End; + bool F2AtEnd = F2P >= File2End; + if (!CompareFailed && (!F1AtEnd || !F2AtEnd)) { + // Else, we might have run off the end due to a number: backup and retry. + if (F1AtEnd && isNumberChar(F1P[-1])) --F1P; + if (F2AtEnd && isNumberChar(F2P[-1])) --F2P; + F1P = BackupNumber(F1P, File1Start); + F2P = BackupNumber(F2P, File2Start); + + // Now that we are at the start of the numbers, compare them, exiting if + // they don't match. + if (CompareNumbers(F1P, F2P, File1End, File2End, AbsTol, RelTol, Error)) + CompareFailed = true; + + // If we found the end, we succeeded. + if (F1P < File1End || F2P < File2End) + CompareFailed = true; + } + + return CompareFailed; +} diff --git a/libclamav/c++/llvm/lib/Support/FoldingSet.cpp b/libclamav/c++/llvm/lib/Support/FoldingSet.cpp new file mode 100644 index 000000000..954dc77df --- /dev/null +++ b/libclamav/c++/llvm/lib/Support/FoldingSet.cpp @@ -0,0 +1,371 @@ +//===-- Support/FoldingSet.cpp - Uniquing Hash Set --------------*- 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 a hash set that can be used to remove duplication of +// nodes in a graph. This code was originally created by Chris Lattner for use +// with SelectionDAGCSEMap, but was isolated to provide use across the llvm code +// set. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/FoldingSet.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/MathExtras.h" +#include +#include +using namespace llvm; + +//===----------------------------------------------------------------------===// +// FoldingSetNodeID Implementation + +/// Add* - Add various data types to Bit data. +/// +void FoldingSetNodeID::AddPointer(const void *Ptr) { + // Note: this adds pointers to the hash using sizes and endianness that + // depend on the host. It doesn't matter however, because hashing on + // pointer values in inherently unstable. Nothing should depend on the + // ordering of nodes in the folding set. + intptr_t PtrI = (intptr_t)Ptr; + Bits.push_back(unsigned(PtrI)); + if (sizeof(intptr_t) > sizeof(unsigned)) + Bits.push_back(unsigned(uint64_t(PtrI) >> 32)); +} +void FoldingSetNodeID::AddInteger(signed I) { + Bits.push_back(I); +} +void FoldingSetNodeID::AddInteger(unsigned I) { + Bits.push_back(I); +} +void FoldingSetNodeID::AddInteger(long I) { + AddInteger((unsigned long)I); +} +void FoldingSetNodeID::AddInteger(unsigned long I) { + if (sizeof(long) == sizeof(int)) + AddInteger(unsigned(I)); + else if (sizeof(long) == sizeof(long long)) { + AddInteger((unsigned long long)I); + } else { + llvm_unreachable("unexpected sizeof(long)"); + } +} +void FoldingSetNodeID::AddInteger(long long I) { + AddInteger((unsigned long long)I); +} +void FoldingSetNodeID::AddInteger(unsigned long long I) { + AddInteger(unsigned(I)); + if ((uint64_t)(int)I != I) + Bits.push_back(unsigned(I >> 32)); +} + +void FoldingSetNodeID::AddString(StringRef String) { + unsigned Size = String.size(); + Bits.push_back(Size); + if (!Size) return; + + unsigned Units = Size / 4; + unsigned Pos = 0; + const unsigned *Base = (const unsigned*) String.data(); + + // If the string is aligned do a bulk transfer. + if (!((intptr_t)Base & 3)) { + Bits.append(Base, Base + Units); + Pos = (Units + 1) * 4; + } else { + // Otherwise do it the hard way. + for (Pos += 4; Pos <= Size; Pos += 4) { + unsigned V = ((unsigned char)String[Pos - 4] << 24) | + ((unsigned char)String[Pos - 3] << 16) | + ((unsigned char)String[Pos - 2] << 8) | + (unsigned char)String[Pos - 1]; + Bits.push_back(V); + } + } + + // With the leftover bits. + unsigned V = 0; + // Pos will have overshot size by 4 - #bytes left over. + switch (Pos - Size) { + case 1: V = (V << 8) | (unsigned char)String[Size - 3]; // Fall thru. + case 2: V = (V << 8) | (unsigned char)String[Size - 2]; // Fall thru. + case 3: V = (V << 8) | (unsigned char)String[Size - 1]; break; + default: return; // Nothing left. + } + + Bits.push_back(V); +} + +/// ComputeHash - Compute a strong hash value for this FoldingSetNodeID, used to +/// lookup the node in the FoldingSetImpl. +unsigned FoldingSetNodeID::ComputeHash() const { + // This is adapted from SuperFastHash by Paul Hsieh. + unsigned Hash = static_cast(Bits.size()); + for (const unsigned *BP = &Bits[0], *E = BP+Bits.size(); BP != E; ++BP) { + unsigned Data = *BP; + Hash += Data & 0xFFFF; + unsigned Tmp = ((Data >> 16) << 11) ^ Hash; + Hash = (Hash << 16) ^ Tmp; + Hash += Hash >> 11; + } + + // Force "avalanching" of final 127 bits. + Hash ^= Hash << 3; + Hash += Hash >> 5; + Hash ^= Hash << 4; + Hash += Hash >> 17; + Hash ^= Hash << 25; + Hash += Hash >> 6; + return Hash; +} + +/// operator== - Used to compare two nodes to each other. +/// +bool FoldingSetNodeID::operator==(const FoldingSetNodeID &RHS)const{ + if (Bits.size() != RHS.Bits.size()) return false; + return memcmp(&Bits[0], &RHS.Bits[0], Bits.size()*sizeof(Bits[0])) == 0; +} + + +//===----------------------------------------------------------------------===// +/// Helper functions for FoldingSetImpl. + +/// GetNextPtr - In order to save space, each bucket is a +/// singly-linked-list. In order to make deletion more efficient, we make +/// the list circular, so we can delete a node without computing its hash. +/// The problem with this is that the start of the hash buckets are not +/// Nodes. If NextInBucketPtr is a bucket pointer, this method returns null: +/// use GetBucketPtr when this happens. +static FoldingSetImpl::Node *GetNextPtr(void *NextInBucketPtr) { + // The low bit is set if this is the pointer back to the bucket. + if (reinterpret_cast(NextInBucketPtr) & 1) + return 0; + + return static_cast(NextInBucketPtr); +} + + +/// testing. +static void **GetBucketPtr(void *NextInBucketPtr) { + intptr_t Ptr = reinterpret_cast(NextInBucketPtr); + assert((Ptr & 1) && "Not a bucket pointer"); + return reinterpret_cast(Ptr & ~intptr_t(1)); +} + +/// GetBucketFor - Hash the specified node ID and return the hash bucket for +/// the specified ID. +static void **GetBucketFor(const FoldingSetNodeID &ID, + void **Buckets, unsigned NumBuckets) { + // NumBuckets is always a power of 2. + unsigned BucketNum = ID.ComputeHash() & (NumBuckets-1); + return Buckets + BucketNum; +} + +//===----------------------------------------------------------------------===// +// FoldingSetImpl Implementation + +FoldingSetImpl::FoldingSetImpl(unsigned Log2InitSize) { + assert(5 < Log2InitSize && Log2InitSize < 32 && + "Initial hash table size out of range"); + NumBuckets = 1 << Log2InitSize; + Buckets = new void*[NumBuckets+1]; + clear(); +} +FoldingSetImpl::~FoldingSetImpl() { + delete [] Buckets; +} +void FoldingSetImpl::clear() { + // Set all but the last bucket to null pointers. + memset(Buckets, 0, NumBuckets*sizeof(void*)); + + // Set the very last bucket to be a non-null "pointer". + Buckets[NumBuckets] = reinterpret_cast(-1); + + // Reset the node count to zero. + NumNodes = 0; +} + +/// GrowHashTable - Double the size of the hash table and rehash everything. +/// +void FoldingSetImpl::GrowHashTable() { + void **OldBuckets = Buckets; + unsigned OldNumBuckets = NumBuckets; + NumBuckets <<= 1; + + // Clear out new buckets. + Buckets = new void*[NumBuckets+1]; + clear(); + + // Walk the old buckets, rehashing nodes into their new place. + FoldingSetNodeID ID; + for (unsigned i = 0; i != OldNumBuckets; ++i) { + void *Probe = OldBuckets[i]; + if (!Probe) continue; + while (Node *NodeInBucket = GetNextPtr(Probe)) { + // Figure out the next link, remove NodeInBucket from the old link. + Probe = NodeInBucket->getNextInBucket(); + NodeInBucket->SetNextInBucket(0); + + // Insert the node into the new bucket, after recomputing the hash. + GetNodeProfile(ID, NodeInBucket); + InsertNode(NodeInBucket, GetBucketFor(ID, Buckets, NumBuckets)); + ID.clear(); + } + } + + delete[] OldBuckets; +} + +/// FindNodeOrInsertPos - Look up the node specified by ID. If it exists, +/// return it. If not, return the insertion token that will make insertion +/// faster. +FoldingSetImpl::Node +*FoldingSetImpl::FindNodeOrInsertPos(const FoldingSetNodeID &ID, + void *&InsertPos) { + + void **Bucket = GetBucketFor(ID, Buckets, NumBuckets); + void *Probe = *Bucket; + + InsertPos = 0; + + FoldingSetNodeID OtherID; + while (Node *NodeInBucket = GetNextPtr(Probe)) { + GetNodeProfile(OtherID, NodeInBucket); + if (OtherID == ID) + return NodeInBucket; + + Probe = NodeInBucket->getNextInBucket(); + OtherID.clear(); + } + + // Didn't find the node, return null with the bucket as the InsertPos. + InsertPos = Bucket; + return 0; +} + +/// InsertNode - Insert the specified node into the folding set, knowing that it +/// is not already in the map. InsertPos must be obtained from +/// FindNodeOrInsertPos. +void FoldingSetImpl::InsertNode(Node *N, void *InsertPos) { + assert(N->getNextInBucket() == 0); + // Do we need to grow the hashtable? + if (NumNodes+1 > NumBuckets*2) { + GrowHashTable(); + FoldingSetNodeID ID; + GetNodeProfile(ID, N); + InsertPos = GetBucketFor(ID, Buckets, NumBuckets); + } + + ++NumNodes; + + /// The insert position is actually a bucket pointer. + void **Bucket = static_cast(InsertPos); + + void *Next = *Bucket; + + // If this is the first insertion into this bucket, its next pointer will be + // null. Pretend as if it pointed to itself, setting the low bit to indicate + // that it is a pointer to the bucket. + if (Next == 0) + Next = reinterpret_cast(reinterpret_cast(Bucket)|1); + + // Set the node's next pointer, and make the bucket point to the node. + N->SetNextInBucket(Next); + *Bucket = N; +} + +/// RemoveNode - Remove a node from the folding set, returning true if one was +/// removed or false if the node was not in the folding set. +bool FoldingSetImpl::RemoveNode(Node *N) { + // Because each bucket is a circular list, we don't need to compute N's hash + // to remove it. + void *Ptr = N->getNextInBucket(); + if (Ptr == 0) return false; // Not in folding set. + + --NumNodes; + N->SetNextInBucket(0); + + // Remember what N originally pointed to, either a bucket or another node. + void *NodeNextPtr = Ptr; + + // Chase around the list until we find the node (or bucket) which points to N. + while (true) { + if (Node *NodeInBucket = GetNextPtr(Ptr)) { + // Advance pointer. + Ptr = NodeInBucket->getNextInBucket(); + + // We found a node that points to N, change it to point to N's next node, + // removing N from the list. + if (Ptr == N) { + NodeInBucket->SetNextInBucket(NodeNextPtr); + return true; + } + } else { + void **Bucket = GetBucketPtr(Ptr); + Ptr = *Bucket; + + // If we found that the bucket points to N, update the bucket to point to + // whatever is next. + if (Ptr == N) { + *Bucket = NodeNextPtr; + return true; + } + } + } +} + +/// GetOrInsertNode - If there is an existing simple Node exactly +/// equal to the specified node, return it. Otherwise, insert 'N' and it +/// instead. +FoldingSetImpl::Node *FoldingSetImpl::GetOrInsertNode(FoldingSetImpl::Node *N) { + FoldingSetNodeID ID; + GetNodeProfile(ID, N); + void *IP; + if (Node *E = FindNodeOrInsertPos(ID, IP)) + return E; + InsertNode(N, IP); + return N; +} + +//===----------------------------------------------------------------------===// +// FoldingSetIteratorImpl Implementation + +FoldingSetIteratorImpl::FoldingSetIteratorImpl(void **Bucket) { + // Skip to the first non-null non-self-cycle bucket. + while (*Bucket != reinterpret_cast(-1) && + (*Bucket == 0 || GetNextPtr(*Bucket) == 0)) + ++Bucket; + + NodePtr = static_cast(*Bucket); +} + +void FoldingSetIteratorImpl::advance() { + // If there is another link within this bucket, go to it. + void *Probe = NodePtr->getNextInBucket(); + + if (FoldingSetNode *NextNodeInBucket = GetNextPtr(Probe)) + NodePtr = NextNodeInBucket; + else { + // Otherwise, this is the last link in this bucket. + void **Bucket = GetBucketPtr(Probe); + + // Skip to the next non-null non-self-cycle bucket. + do { + ++Bucket; + } while (*Bucket != reinterpret_cast(-1) && + (*Bucket == 0 || GetNextPtr(*Bucket) == 0)); + + NodePtr = static_cast(*Bucket); + } +} + +//===----------------------------------------------------------------------===// +// FoldingSetBucketIteratorImpl Implementation + +FoldingSetBucketIteratorImpl::FoldingSetBucketIteratorImpl(void **Bucket) { + Ptr = (*Bucket == 0 || GetNextPtr(*Bucket) == 0) ? (void*) Bucket : *Bucket; +} diff --git a/libclamav/c++/llvm/lib/Support/FormattedStream.cpp b/libclamav/c++/llvm/lib/Support/FormattedStream.cpp new file mode 100644 index 000000000..70f2cfa6a --- /dev/null +++ b/libclamav/c++/llvm/lib/Support/FormattedStream.cpp @@ -0,0 +1,93 @@ +//===-- llvm/Support/FormattedStream.cpp - Formatted streams ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the implementation of formatted_raw_ostream. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/FormattedStream.h" + +using namespace llvm; + +/// CountColumns - Examine the given char sequence and figure out which +/// column we end up in after output. +/// +static unsigned CountColumns(unsigned Column, const char *Ptr, size_t Size) { + // Keep track of the current column by scanning the string for + // special characters + + for (const char *End = Ptr + Size; Ptr != End; ++Ptr) { + ++Column; + if (*Ptr == '\n' || *Ptr == '\r') + Column = 0; + else if (*Ptr == '\t') + // Assumes tab stop = 8 characters. + Column += (8 - (Column & 0x7)) & 0x7; + } + + return Column; +} + +/// ComputeColumn - Examine the current output and figure out which +/// column we end up in after output. +void formatted_raw_ostream::ComputeColumn(const char *Ptr, size_t Size) { + // If our previous scan pointer is inside the buffer, assume we already + // scanned those bytes. This depends on raw_ostream to not change our buffer + // in unexpected ways. + if (Ptr <= Scanned && Scanned <= Ptr + Size) { + // Scan all characters added since our last scan to determine the new + // column. + ColumnScanned = CountColumns(ColumnScanned, Scanned, + Size - (Scanned - Ptr)); + } else + ColumnScanned = CountColumns(ColumnScanned, Ptr, Size); + + // Update the scanning pointer. + Scanned = Ptr + Size; +} + +/// PadToColumn - Align the output to some column number. +/// +/// \param NewCol - The column to move to. +/// \param MinPad - The minimum space to give after the most recent +/// I/O, even if the current column + minpad > newcol. +/// +void formatted_raw_ostream::PadToColumn(unsigned NewCol) { + // Figure out what's in the buffer and add it to the column count. + ComputeColumn(getBufferStart(), GetNumBytesInBuffer()); + + // Output spaces until we reach the desired column. + indent(std::max(int(NewCol - ColumnScanned), 1)); +} + +void formatted_raw_ostream::write_impl(const char *Ptr, size_t Size) { + // Figure out what's in the buffer and add it to the column count. + ComputeColumn(Ptr, Size); + + // Write the data to the underlying stream (which is unbuffered, so + // the data will be immediately written out). + TheStream->write(Ptr, Size); + + // Reset the scanning pointer. + Scanned = 0; +} + +/// fouts() - This returns a reference to a formatted_raw_ostream for +/// standard output. Use it like: fouts() << "foo" << "bar"; +formatted_raw_ostream &llvm::fouts() { + static formatted_raw_ostream S(outs()); + return S; +} + +/// ferrs() - This returns a reference to a formatted_raw_ostream for +/// standard error. Use it like: ferrs() << "foo" << "bar"; +formatted_raw_ostream &llvm::ferrs() { + static formatted_raw_ostream S(errs()); + return S; +} diff --git a/libclamav/c++/llvm/lib/Support/GraphWriter.cpp b/libclamav/c++/llvm/lib/Support/GraphWriter.cpp new file mode 100644 index 000000000..c8bca6ef8 --- /dev/null +++ b/libclamav/c++/llvm/lib/Support/GraphWriter.cpp @@ -0,0 +1,175 @@ +//===-- GraphWriter.cpp - Implements GraphWriter support routines ---------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements misc. GraphWriter support routines. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/GraphWriter.h" +#include "llvm/System/Path.h" +#include "llvm/System/Program.h" +#include "llvm/Config/config.h" +using namespace llvm; + +std::string llvm::DOT::EscapeString(const std::string &Label) { + std::string Str(Label); + for (unsigned i = 0; i != Str.length(); ++i) + switch (Str[i]) { + case '\n': + Str.insert(Str.begin()+i, '\\'); // Escape character... + ++i; + Str[i] = 'n'; + break; + case '\t': + Str.insert(Str.begin()+i, ' '); // Convert to two spaces + ++i; + Str[i] = ' '; + break; + case '\\': + if (i+1 != Str.length()) + switch (Str[i+1]) { + case 'l': continue; // don't disturb \l + case '|': case '{': case '}': + Str.erase(Str.begin()+i); continue; + default: break; + } + case '{': case '}': + case '<': case '>': + case '|': case '"': + Str.insert(Str.begin()+i, '\\'); // Escape character... + ++i; // don't infinite loop + break; + } + return Str; +} + + + +void llvm::DisplayGraph(const sys::Path &Filename, bool wait, + GraphProgram::Name program) { + std::string ErrMsg; +#if HAVE_GRAPHVIZ + sys::Path Graphviz(LLVM_PATH_GRAPHVIZ); + + std::vector args; + args.push_back(Graphviz.c_str()); + args.push_back(Filename.c_str()); + args.push_back(0); + + errs() << "Running 'Graphviz' program... "; + if (sys::Program::ExecuteAndWait(Graphviz, &args[0],0,0,0,0,&ErrMsg)) + errs() << "Error viewing graph " << Filename.str() << ": " << ErrMsg + << "\n"; + else + Filename.eraseFromDisk(); + +#elif (HAVE_GV && (HAVE_DOT || HAVE_FDP || HAVE_NEATO || \ + HAVE_TWOPI || HAVE_CIRCO)) + sys::Path PSFilename = Filename; + PSFilename.appendSuffix("ps"); + + sys::Path prog; + + // Set default grapher +#if HAVE_CIRCO + prog = sys::Path(LLVM_PATH_CIRCO); +#endif +#if HAVE_TWOPI + prog = sys::Path(LLVM_PATH_TWOPI); +#endif +#if HAVE_NEATO + prog = sys::Path(LLVM_PATH_NEATO); +#endif +#if HAVE_FDP + prog = sys::Path(LLVM_PATH_FDP); +#endif +#if HAVE_DOT + prog = sys::Path(LLVM_PATH_DOT); +#endif + + // Find which program the user wants +#if HAVE_DOT + if (program == GraphProgram::DOT) + prog = sys::Path(LLVM_PATH_DOT); +#endif +#if (HAVE_FDP) + if (program == GraphProgram::FDP) + prog = sys::Path(LLVM_PATH_FDP); +#endif +#if (HAVE_NEATO) + if (program == GraphProgram::NEATO) + prog = sys::Path(LLVM_PATH_NEATO); +#endif +#if (HAVE_TWOPI) + if (program == GraphProgram::TWOPI) + prog = sys::Path(LLVM_PATH_TWOPI); +#endif +#if (HAVE_CIRCO) + if (program == GraphProgram::CIRCO) + prog = sys::Path(LLVM_PATH_CIRCO); +#endif + + std::vector args; + args.push_back(prog.c_str()); + args.push_back("-Tps"); + args.push_back("-Nfontname=Courier"); + args.push_back("-Gsize=7.5,10"); + args.push_back(Filename.c_str()); + args.push_back("-o"); + args.push_back(PSFilename.c_str()); + args.push_back(0); + + errs() << "Running '" << prog.str() << "' program... "; + + if (sys::Program::ExecuteAndWait(prog, &args[0], 0, 0, 0, 0, &ErrMsg)) { + errs() << "Error viewing graph " << Filename.str() << ": '" + << ErrMsg << "\n"; + } else { + errs() << " done. \n"; + + sys::Path gv(LLVM_PATH_GV); + args.clear(); + args.push_back(gv.c_str()); + args.push_back(PSFilename.c_str()); + args.push_back("-spartan"); + args.push_back(0); + + ErrMsg.clear(); + if (wait) { + if (sys::Program::ExecuteAndWait(gv, &args[0],0,0,0,0,&ErrMsg)) + errs() << "Error viewing graph: " << ErrMsg << "\n"; + Filename.eraseFromDisk(); + PSFilename.eraseFromDisk(); + } + else { + sys::Program::ExecuteNoWait(gv, &args[0],0,0,0,&ErrMsg); + errs() << "Remember to erase graph files: " << Filename.str() << " " + << PSFilename.str() << "\n"; + } + } +#elif HAVE_DOTTY + sys::Path dotty(LLVM_PATH_DOTTY); + + std::vector args; + args.push_back(dotty.c_str()); + args.push_back(Filename.c_str()); + args.push_back(0); + + errs() << "Running 'dotty' program... "; + if (sys::Program::ExecuteAndWait(dotty, &args[0],0,0,0,0,&ErrMsg)) { + errs() << "Error viewing graph " << Filename.str() << ": " + << ErrMsg << "\n"; + } else { +#ifdef __MINGW32__ // Dotty spawns another app and doesn't wait until it returns + return; +#endif + Filename.eraseFromDisk(); + } +#endif +} diff --git a/libclamav/c++/llvm/lib/Support/IsInf.cpp b/libclamav/c++/llvm/lib/Support/IsInf.cpp new file mode 100644 index 000000000..d6da0c99e --- /dev/null +++ b/libclamav/c++/llvm/lib/Support/IsInf.cpp @@ -0,0 +1,49 @@ +//===-- IsInf.cpp - Platform-independent wrapper around C99 isinf() -------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Platform-independent wrapper around C99 isinf() +// +//===----------------------------------------------------------------------===// + +#include "llvm/Config/config.h" + +#if HAVE_ISINF_IN_MATH_H +# include +#elif HAVE_ISINF_IN_CMATH +# include +#elif HAVE_STD_ISINF_IN_CMATH +# include +using std::isinf; +#elif HAVE_FINITE_IN_IEEEFP_H +// A handy workaround I found at http://www.unixguide.net/sun/faq ... +// apparently this has been a problem with Solaris for years. +# include +static int isinf(double x) { return !finite(x) && x==x; } +#elif defined(_MSC_VER) +#include +#define isinf(X) (!_finite(X)) +#elif defined(_AIX) && defined(__GNUC__) +// GCC's fixincludes seems to be removing the isinf() declaration from the +// system header /usr/include/math.h +# include +static int isinf(double x) { return !finite(x) && x==x; } +#elif defined(__hpux) +// HP-UX is "special" +#include +static int isinf(double x) { return ((x) == INFINITY) || ((x) == -INFINITY); } +#else +# error "Don't know how to get isinf()" +#endif + +namespace llvm { + +int IsInf(float f) { return isinf(f); } +int IsInf(double d) { return isinf(d); } + +} // end namespace llvm; diff --git a/libclamav/c++/llvm/lib/Support/IsNAN.cpp b/libclamav/c++/llvm/lib/Support/IsNAN.cpp new file mode 100644 index 000000000..bdfdfbf31 --- /dev/null +++ b/libclamav/c++/llvm/lib/Support/IsNAN.cpp @@ -0,0 +1,33 @@ +//===-- IsNAN.cpp ---------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Platform-independent wrapper around C99 isnan(). +// +//===----------------------------------------------------------------------===// + +#include "llvm/Config/config.h" + +#if HAVE_ISNAN_IN_MATH_H +# include +#elif HAVE_ISNAN_IN_CMATH +# include +#elif HAVE_STD_ISNAN_IN_CMATH +# include +using std::isnan; +#elif defined(_MSC_VER) +#include +#define isnan _isnan +#else +# error "Don't know how to get isnan()" +#endif + +namespace llvm { + int IsNAN(float f) { return isnan(f); } + int IsNAN(double d) { return isnan(d); } +} // end namespace llvm; diff --git a/libclamav/c++/llvm/lib/Support/Makefile b/libclamav/c++/llvm/lib/Support/Makefile new file mode 100644 index 000000000..48c21f4fd --- /dev/null +++ b/libclamav/c++/llvm/lib/Support/Makefile @@ -0,0 +1,17 @@ +##===- lib/Support/Makefile --------------------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LEVEL = ../.. +LIBRARYNAME = LLVMSupport +BUILD_ARCHIVE = 1 + +## FIXME: This only requires RTTI because tblgen uses it. Fix that. +REQUIRES_RTTI = 1 + +include $(LEVEL)/Makefile.common diff --git a/libclamav/c++/llvm/lib/Support/ManagedStatic.cpp b/libclamav/c++/llvm/lib/Support/ManagedStatic.cpp new file mode 100644 index 000000000..4e655a0f9 --- /dev/null +++ b/libclamav/c++/llvm/lib/Support/ManagedStatic.cpp @@ -0,0 +1,75 @@ +//===-- ManagedStatic.cpp - Static Global wrapper -------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the ManagedStatic class and llvm_shutdown(). +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/ManagedStatic.h" +#include "llvm/Config/config.h" +#include "llvm/System/Atomic.h" +#include +using namespace llvm; + +static const ManagedStaticBase *StaticList = 0; + +void ManagedStaticBase::RegisterManagedStatic(void *(*Creator)(), + void (*Deleter)(void*)) const { + if (llvm_is_multithreaded()) { + llvm_acquire_global_lock(); + + if (Ptr == 0) { + void* tmp = Creator ? Creator() : 0; + + sys::MemoryFence(); + Ptr = tmp; + DeleterFn = Deleter; + + // Add to list of managed statics. + Next = StaticList; + StaticList = this; + } + + llvm_release_global_lock(); + } else { + assert(Ptr == 0 && DeleterFn == 0 && Next == 0 && + "Partially initialized ManagedStatic!?"); + Ptr = Creator ? Creator() : 0; + DeleterFn = Deleter; + + // Add to list of managed statics. + Next = StaticList; + StaticList = this; + } +} + +void ManagedStaticBase::destroy() const { + assert(DeleterFn && "ManagedStatic not initialized correctly!"); + assert(StaticList == this && + "Not destroyed in reverse order of construction?"); + // Unlink from list. + StaticList = Next; + Next = 0; + + // Destroy memory. + DeleterFn(Ptr); + + // Cleanup. + Ptr = 0; + DeleterFn = 0; +} + +/// llvm_shutdown - Deallocate and destroy all ManagedStatic variables. +void llvm::llvm_shutdown() { + while (StaticList) + StaticList->destroy(); + + if (llvm_is_multithreaded()) llvm_stop_multithreaded(); +} + diff --git a/libclamav/c++/llvm/lib/Support/MemoryBuffer.cpp b/libclamav/c++/llvm/lib/Support/MemoryBuffer.cpp new file mode 100644 index 000000000..b04864a1a --- /dev/null +++ b/libclamav/c++/llvm/lib/Support/MemoryBuffer.cpp @@ -0,0 +1,277 @@ +//===--- MemoryBuffer.cpp - Memory Buffer implementation ------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the MemoryBuffer interface. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/System/Path.h" +#include "llvm/System/Process.h" +#include "llvm/System/Program.h" +#include +#include +#include +#include +#include +#include +#if !defined(_MSC_VER) && !defined(__MINGW32__) +#include +#include +#else +#include +#endif +#include +using namespace llvm; + +//===----------------------------------------------------------------------===// +// MemoryBuffer implementation itself. +//===----------------------------------------------------------------------===// + +MemoryBuffer::~MemoryBuffer() { + if (MustDeleteBuffer) + free((void*)BufferStart); +} + +/// initCopyOf - Initialize this source buffer with a copy of the specified +/// memory range. We make the copy so that we can null terminate it +/// successfully. +void MemoryBuffer::initCopyOf(const char *BufStart, const char *BufEnd) { + size_t Size = BufEnd-BufStart; + BufferStart = (char *)malloc((Size+1) * sizeof(char)); + BufferEnd = BufferStart+Size; + memcpy(const_cast(BufferStart), BufStart, Size); + *const_cast(BufferEnd) = 0; // Null terminate buffer. + MustDeleteBuffer = true; +} + +/// init - Initialize this MemoryBuffer as a reference to externally allocated +/// memory, memory that we know is already null terminated. +void MemoryBuffer::init(const char *BufStart, const char *BufEnd) { + assert(BufEnd[0] == 0 && "Buffer is not null terminated!"); + BufferStart = BufStart; + BufferEnd = BufEnd; + MustDeleteBuffer = false; +} + +//===----------------------------------------------------------------------===// +// MemoryBufferMem implementation. +//===----------------------------------------------------------------------===// + +namespace { +class MemoryBufferMem : public MemoryBuffer { + std::string FileID; +public: + MemoryBufferMem(const char *Start, const char *End, StringRef FID, + bool Copy = false) + : FileID(FID) { + if (!Copy) + init(Start, End); + else + initCopyOf(Start, End); + } + + virtual const char *getBufferIdentifier() const { + return FileID.c_str(); + } +}; +} + +/// getMemBuffer - Open the specified memory range as a MemoryBuffer. Note +/// that EndPtr[0] must be a null byte and be accessible! +MemoryBuffer *MemoryBuffer::getMemBuffer(const char *StartPtr, + const char *EndPtr, + const char *BufferName) { + return new MemoryBufferMem(StartPtr, EndPtr, BufferName); +} + +/// getMemBufferCopy - Open the specified memory range as a MemoryBuffer, +/// copying the contents and taking ownership of it. This has no requirements +/// on EndPtr[0]. +MemoryBuffer *MemoryBuffer::getMemBufferCopy(const char *StartPtr, + const char *EndPtr, + const char *BufferName) { + return new MemoryBufferMem(StartPtr, EndPtr, BufferName, true); +} + +/// getNewUninitMemBuffer - Allocate a new MemoryBuffer of the specified size +/// that is completely initialized to zeros. Note that the caller should +/// initialize the memory allocated by this method. The memory is owned by +/// the MemoryBuffer object. +MemoryBuffer *MemoryBuffer::getNewUninitMemBuffer(size_t Size, + StringRef BufferName) { + char *Buf = (char *)malloc((Size+1) * sizeof(char)); + if (!Buf) return 0; + Buf[Size] = 0; + MemoryBufferMem *SB = new MemoryBufferMem(Buf, Buf+Size, BufferName); + // The memory for this buffer is owned by the MemoryBuffer. + SB->MustDeleteBuffer = true; + return SB; +} + +/// getNewMemBuffer - Allocate a new MemoryBuffer of the specified size that +/// is completely initialized to zeros. Note that the caller should +/// initialize the memory allocated by this method. The memory is owned by +/// the MemoryBuffer object. +MemoryBuffer *MemoryBuffer::getNewMemBuffer(size_t Size, + const char *BufferName) { + MemoryBuffer *SB = getNewUninitMemBuffer(Size, BufferName); + if (!SB) return 0; + memset(const_cast(SB->getBufferStart()), 0, Size+1); + return SB; +} + + +/// getFileOrSTDIN - Open the specified file as a MemoryBuffer, or open stdin +/// if the Filename is "-". If an error occurs, this returns null and fills +/// in *ErrStr with a reason. If stdin is empty, this API (unlike getSTDIN) +/// returns an empty buffer. +MemoryBuffer *MemoryBuffer::getFileOrSTDIN(StringRef Filename, + std::string *ErrStr, + int64_t FileSize) { + if (Filename == "-") + return getSTDIN(); + return getFile(Filename, ErrStr, FileSize); +} + +//===----------------------------------------------------------------------===// +// MemoryBuffer::getFile implementation. +//===----------------------------------------------------------------------===// + +namespace { +/// MemoryBufferMMapFile - This represents a file that was mapped in with the +/// sys::Path::MapInFilePages method. When destroyed, it calls the +/// sys::Path::UnMapFilePages method. +class MemoryBufferMMapFile : public MemoryBuffer { + std::string Filename; +public: + MemoryBufferMMapFile(StringRef filename, const char *Pages, uint64_t Size) + : Filename(filename) { + init(Pages, Pages+Size); + } + + virtual const char *getBufferIdentifier() const { + return Filename.c_str(); + } + + ~MemoryBufferMMapFile() { + sys::Path::UnMapFilePages(getBufferStart(), getBufferSize()); + } +}; +} + +MemoryBuffer *MemoryBuffer::getFile(StringRef Filename, std::string *ErrStr, + int64_t FileSize) { + int OpenFlags = 0; +#ifdef O_BINARY + OpenFlags |= O_BINARY; // Open input file in binary mode on win32. +#endif + int FD = ::open(Filename.str().c_str(), O_RDONLY|OpenFlags); + if (FD == -1) { + if (ErrStr) *ErrStr = "could not open file"; + return 0; + } + + // If we don't know the file size, use fstat to find out. fstat on an open + // file descriptor is cheaper than stat on a random path. + if (FileSize == -1) { + struct stat FileInfo; + // TODO: This should use fstat64 when available. + if (fstat(FD, &FileInfo) == -1) { + if (ErrStr) *ErrStr = "could not get file length"; + ::close(FD); + return 0; + } + FileSize = FileInfo.st_size; + } + + + // If the file is large, try to use mmap to read it in. We don't use mmap + // for small files, because this can severely fragment our address space. Also + // don't try to map files that are exactly a multiple of the system page size, + // as the file would not have the required null terminator. + // + // FIXME: Can we just mmap an extra page in the latter case? + if (FileSize >= 4096*4 && + (FileSize & (sys::Process::GetPageSize()-1)) != 0) { + if (const char *Pages = sys::Path::MapInFilePages(FD, FileSize)) { + // Close the file descriptor, now that the whole file is in memory. + ::close(FD); + return new MemoryBufferMMapFile(Filename, Pages, FileSize); + } + } + + MemoryBuffer *Buf = MemoryBuffer::getNewUninitMemBuffer(FileSize, Filename); + if (!Buf) { + // Failed to create a buffer. + if (ErrStr) *ErrStr = "could not allocate buffer"; + ::close(FD); + return 0; + } + + OwningPtr SB(Buf); + char *BufPtr = const_cast(SB->getBufferStart()); + + size_t BytesLeft = FileSize; + while (BytesLeft) { + ssize_t NumRead = ::read(FD, BufPtr, BytesLeft); + if (NumRead > 0) { + BytesLeft -= NumRead; + BufPtr += NumRead; + } else if (NumRead == -1 && errno == EINTR) { + // try again + } else { + // error reading. + close(FD); + if (ErrStr) *ErrStr = "error reading file data"; + return 0; + } + } + close(FD); + + return SB.take(); +} + +//===----------------------------------------------------------------------===// +// MemoryBuffer::getSTDIN implementation. +//===----------------------------------------------------------------------===// + +namespace { +class STDINBufferFile : public MemoryBuffer { +public: + virtual const char *getBufferIdentifier() const { + return ""; + } +}; +} + +MemoryBuffer *MemoryBuffer::getSTDIN() { + char Buffer[4096*4]; + + std::vector FileData; + + // Read in all of the data from stdin, we cannot mmap stdin. + // + // FIXME: That isn't necessarily true, we should try to mmap stdin and + // fallback if it fails. + sys::Program::ChangeStdinToBinary(); + size_t ReadBytes; + do { + ReadBytes = fread(Buffer, sizeof(char), sizeof(Buffer), stdin); + FileData.insert(FileData.end(), Buffer, Buffer+ReadBytes); + } while (ReadBytes == sizeof(Buffer)); + + FileData.push_back(0); // &FileData[Size] is invalid. So is &*FileData.end(). + size_t Size = FileData.size(); + MemoryBuffer *B = new STDINBufferFile(); + B->initCopyOf(&FileData[0], &FileData[Size-1]); + return B; +} diff --git a/libclamav/c++/llvm/lib/Support/MemoryObject.cpp b/libclamav/c++/llvm/lib/Support/MemoryObject.cpp new file mode 100644 index 000000000..91e3ecd23 --- /dev/null +++ b/libclamav/c++/llvm/lib/Support/MemoryObject.cpp @@ -0,0 +1,34 @@ +//===- MemoryObject.cpp - Abstract memory interface -----------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/MemoryObject.h" +using namespace llvm; + +MemoryObject::~MemoryObject() { +} + +int MemoryObject::readBytes(uint64_t address, + uint64_t size, + uint8_t* buf, + uint64_t* copied) const { + uint64_t current = address; + uint64_t limit = getBase() + getExtent(); + + while (current - address < size && current < limit) { + if (readByte(current, &buf[(current - address)])) + return -1; + + current++; + } + + if (copied) + *copied = current - address; + + return 0; +} diff --git a/libclamav/c++/llvm/lib/Support/PluginLoader.cpp b/libclamav/c++/llvm/lib/Support/PluginLoader.cpp new file mode 100644 index 000000000..36caecffe --- /dev/null +++ b/libclamav/c++/llvm/lib/Support/PluginLoader.cpp @@ -0,0 +1,47 @@ +//===-- PluginLoader.cpp - Implement -load command line option ------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the -load command line option handler. +// +//===----------------------------------------------------------------------===// + +#define DONT_GET_PLUGIN_LOADER_OPTION +#include "llvm/Support/ManagedStatic.h" +#include "llvm/Support/PluginLoader.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/System/DynamicLibrary.h" +#include "llvm/System/Mutex.h" +#include +using namespace llvm; + +static ManagedStatic > Plugins; +static ManagedStatic > PluginsLock; + +void PluginLoader::operator=(const std::string &Filename) { + sys::SmartScopedLock Lock(*PluginsLock); + std::string Error; + if (sys::DynamicLibrary::LoadLibraryPermanently(Filename.c_str(), &Error)) { + errs() << "Error opening '" << Filename << "': " << Error + << "\n -load request ignored.\n"; + } else { + Plugins->push_back(Filename); + } +} + +unsigned PluginLoader::getNumPlugins() { + sys::SmartScopedLock Lock(*PluginsLock); + return Plugins.isConstructed() ? Plugins->size() : 0; +} + +std::string &PluginLoader::getPlugin(unsigned num) { + sys::SmartScopedLock Lock(*PluginsLock); + assert(Plugins.isConstructed() && num < Plugins->size() && + "Asking for an out of bounds plugin"); + return (*Plugins)[num]; +} diff --git a/libclamav/c++/llvm/lib/Support/PrettyStackTrace.cpp b/libclamav/c++/llvm/lib/Support/PrettyStackTrace.cpp new file mode 100644 index 000000000..68b41a7f0 --- /dev/null +++ b/libclamav/c++/llvm/lib/Support/PrettyStackTrace.cpp @@ -0,0 +1,114 @@ +//===- PrettyStackTrace.cpp - Pretty Crash Handling -----------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines some helpful functions for dealing with the possibility of +// Unix signals occuring while your program is running. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/PrettyStackTrace.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/System/Signals.h" +#include "llvm/System/ThreadLocal.h" +#include "llvm/ADT/SmallString.h" +using namespace llvm; + +namespace llvm { + bool DisablePrettyStackTrace = false; +} + +// FIXME: This should be thread local when llvm supports threads. +static sys::ThreadLocal PrettyStackTraceHead; + +static unsigned PrintStack(const PrettyStackTraceEntry *Entry, raw_ostream &OS){ + unsigned NextID = 0; + if (Entry->getNextEntry()) + NextID = PrintStack(Entry->getNextEntry(), OS); + OS << NextID << ".\t"; + Entry->print(OS); + + return NextID+1; +} + +/// PrintCurStackTrace - Print the current stack trace to the specified stream. +static void PrintCurStackTrace(raw_ostream &OS) { + // Don't print an empty trace. + if (PrettyStackTraceHead.get() == 0) return; + + // If there are pretty stack frames registered, walk and emit them. + OS << "Stack dump:\n"; + + PrintStack(PrettyStackTraceHead.get(), OS); + OS.flush(); +} + +// Integrate with crash reporter. +#ifdef __APPLE__ +extern "C" const char *__crashreporter_info__; +const char *__crashreporter_info__ = 0; +#endif + + +/// CrashHandler - This callback is run if a fatal signal is delivered to the +/// process, it prints the pretty stack trace. +static void CrashHandler(void *Cookie) { +#ifndef __APPLE__ + // On non-apple systems, just emit the crash stack trace to stderr. + PrintCurStackTrace(errs()); +#else + // Otherwise, emit to a smallvector of chars, send *that* to stderr, but also + // put it into __crashreporter_info__. + SmallString<2048> TmpStr; + { + raw_svector_ostream Stream(TmpStr); + PrintCurStackTrace(Stream); + } + + if (!TmpStr.empty()) { + __crashreporter_info__ = strdup(std::string(TmpStr.str()).c_str()); + errs() << TmpStr.str(); + } + +#endif +} + +static bool RegisterCrashPrinter() { + if (!DisablePrettyStackTrace) + sys::AddSignalHandler(CrashHandler, 0); + return false; +} + +PrettyStackTraceEntry::PrettyStackTraceEntry() { + // The first time this is called, we register the crash printer. + static bool HandlerRegistered = RegisterCrashPrinter(); + HandlerRegistered = HandlerRegistered; + + // Link ourselves. + NextEntry = PrettyStackTraceHead.get(); + PrettyStackTraceHead.set(this); +} + +PrettyStackTraceEntry::~PrettyStackTraceEntry() { + assert(PrettyStackTraceHead.get() == this && + "Pretty stack trace entry destruction is out of order"); + PrettyStackTraceHead.set(getNextEntry()); +} + +void PrettyStackTraceString::print(raw_ostream &OS) const { + OS << Str << "\n"; +} + +void PrettyStackTraceProgram::print(raw_ostream &OS) const { + OS << "Program arguments: "; + // Print the argument list. + for (unsigned i = 0, e = ArgC; i != e; ++i) + OS << ArgV[i] << ' '; + OS << '\n'; +} + diff --git a/libclamav/c++/llvm/lib/Support/Regex.cpp b/libclamav/c++/llvm/lib/Support/Regex.cpp new file mode 100644 index 000000000..618ca0524 --- /dev/null +++ b/libclamav/c++/llvm/lib/Support/Regex.cpp @@ -0,0 +1,92 @@ +//===-- Regex.cpp - Regular Expression matcher implementation -------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements a POSIX regular expression matcher. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/Regex.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/ADT/SmallVector.h" +#include "regex_impl.h" +#include +using namespace llvm; + +Regex::Regex(const StringRef ®ex, unsigned Flags) { + unsigned flags = 0; + preg = new llvm_regex(); + preg->re_endp = regex.end(); + if (Flags & IgnoreCase) + flags |= REG_ICASE; + if (Flags & Newline) + flags |= REG_NEWLINE; + error = llvm_regcomp(preg, regex.data(), flags|REG_EXTENDED|REG_PEND); +} + +Regex::~Regex() { + llvm_regfree(preg); + delete preg; +} + +bool Regex::isValid(std::string &Error) { + if (!error) + return true; + + size_t len = llvm_regerror(error, preg, NULL, 0); + + Error.resize(len); + llvm_regerror(error, preg, &Error[0], len); + return false; +} + +/// getNumMatches - In a valid regex, return the number of parenthesized +/// matches it contains. +unsigned Regex::getNumMatches() const { + return preg->re_nsub; +} + +bool Regex::match(const StringRef &String, SmallVectorImpl *Matches){ + unsigned nmatch = Matches ? preg->re_nsub+1 : 0; + + // pmatch needs to have at least one element. + SmallVector pm; + pm.resize(nmatch > 0 ? nmatch : 1); + pm[0].rm_so = 0; + pm[0].rm_eo = String.size(); + + int rc = llvm_regexec(preg, String.data(), nmatch, pm.data(), REG_STARTEND); + + if (rc == REG_NOMATCH) + return false; + if (rc != 0) { + // regexec can fail due to invalid pattern or running out of memory. + error = rc; + return false; + } + + // There was a match. + + if (Matches) { // match position requested + Matches->clear(); + + for (unsigned i = 0; i != nmatch; ++i) { + if (pm[i].rm_so == -1) { + // this group didn't match + Matches->push_back(StringRef()); + continue; + } + assert(pm[i].rm_eo > pm[i].rm_so); + Matches->push_back(StringRef(String.data()+pm[i].rm_so, + pm[i].rm_eo-pm[i].rm_so)); + } + } + + return true; +} diff --git a/libclamav/c++/llvm/lib/Support/SlowOperationInformer.cpp b/libclamav/c++/llvm/lib/Support/SlowOperationInformer.cpp new file mode 100644 index 000000000..b4e9430e5 --- /dev/null +++ b/libclamav/c++/llvm/lib/Support/SlowOperationInformer.cpp @@ -0,0 +1,67 @@ +//===-- SlowOperationInformer.cpp - Keep the user informed ----------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the SlowOperationInformer class for the LLVM debugger. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/SlowOperationInformer.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/System/Alarm.h" +#include +#include +using namespace llvm; + +SlowOperationInformer::SlowOperationInformer(const std::string &Name) + : OperationName(Name), LastPrintAmount(0) { + sys::SetupAlarm(1); +} + +SlowOperationInformer::~SlowOperationInformer() { + sys::TerminateAlarm(); + if (LastPrintAmount) { + // If we have printed something, make _sure_ we print the 100% amount, and + // also print a newline. + outs() << std::string(LastPrintAmount, '\b') << "Progress " + << OperationName << ": 100% \n"; + } +} + +/// progress - Clients should periodically call this method when they are in +/// an exception-safe state. The Amount variable should indicate how far +/// along the operation is, given in 1/10ths of a percent (in other words, +/// Amount should range from 0 to 1000). +bool SlowOperationInformer::progress(unsigned Amount) { + int status = sys::AlarmStatus(); + if (status == -1) { + outs() << "\n"; + LastPrintAmount = 0; + return true; + } + + // If we haven't spent enough time in this operation to warrant displaying the + // progress bar, don't do so yet. + if (status == 0) + return false; + + // Delete whatever we printed last time. + std::string ToPrint = std::string(LastPrintAmount, '\b'); + + std::ostringstream OS; + OS << "Progress " << OperationName << ": " << Amount/10; + if (unsigned Rem = Amount % 10) + OS << "." << Rem << "%"; + else + OS << "% "; + + LastPrintAmount = OS.str().size(); + outs() << ToPrint+OS.str(); + outs().flush(); + return false; +} diff --git a/libclamav/c++/llvm/lib/Support/SmallPtrSet.cpp b/libclamav/c++/llvm/lib/Support/SmallPtrSet.cpp new file mode 100644 index 000000000..68938fa5a --- /dev/null +++ b/libclamav/c++/llvm/lib/Support/SmallPtrSet.cpp @@ -0,0 +1,223 @@ +//===- llvm/ADT/SmallPtrSet.cpp - 'Normally small' pointer set ------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the SmallPtrSet class. See SmallPtrSet.h for an +// overview of the algorithm. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/Support/MathExtras.h" +#include + +using namespace llvm; + +void SmallPtrSetImpl::shrink_and_clear() { + assert(!isSmall() && "Can't shrink a small set!"); + free(CurArray); + + // Reduce the number of buckets. + CurArraySize = NumElements > 16 ? 1 << (Log2_32_Ceil(NumElements) + 1) : 32; + NumElements = NumTombstones = 0; + + // Install the new array. Clear all the buckets to empty. + CurArray = (const void**)malloc(sizeof(void*) * (CurArraySize+1)); + assert(CurArray && "Failed to allocate memory?"); + memset(CurArray, -1, CurArraySize*sizeof(void*)); + + // The end pointer, always valid, is set to a valid element to help the + // iterator. + CurArray[CurArraySize] = 0; +} + +bool SmallPtrSetImpl::insert_imp(const void * Ptr) { + if (isSmall()) { + // Check to see if it is already in the set. + for (const void **APtr = SmallArray, **E = SmallArray+NumElements; + APtr != E; ++APtr) + if (*APtr == Ptr) + return false; + + // Nope, there isn't. If we stay small, just 'pushback' now. + if (NumElements < CurArraySize-1) { + SmallArray[NumElements++] = Ptr; + return true; + } + // Otherwise, hit the big set case, which will call grow. + } + + // If more than 3/4 of the array is full, grow. + if (NumElements*4 >= CurArraySize*3 || + CurArraySize-(NumElements+NumTombstones) < CurArraySize/8) + Grow(); + + // Okay, we know we have space. Find a hash bucket. + const void **Bucket = const_cast(FindBucketFor(Ptr)); + if (*Bucket == Ptr) return false; // Already inserted, good. + + // Otherwise, insert it! + if (*Bucket == getTombstoneMarker()) + --NumTombstones; + *Bucket = Ptr; + ++NumElements; // Track density. + return true; +} + +bool SmallPtrSetImpl::erase_imp(const void * Ptr) { + if (isSmall()) { + // Check to see if it is in the set. + for (const void **APtr = SmallArray, **E = SmallArray+NumElements; + APtr != E; ++APtr) + if (*APtr == Ptr) { + // If it is in the set, replace this element. + *APtr = E[-1]; + E[-1] = getEmptyMarker(); + --NumElements; + return true; + } + + return false; + } + + // Okay, we know we have space. Find a hash bucket. + void **Bucket = const_cast(FindBucketFor(Ptr)); + if (*Bucket != Ptr) return false; // Not in the set? + + // Set this as a tombstone. + *Bucket = getTombstoneMarker(); + --NumElements; + ++NumTombstones; + return true; +} + +const void * const *SmallPtrSetImpl::FindBucketFor(const void *Ptr) const { + unsigned Bucket = Hash(Ptr); + unsigned ArraySize = CurArraySize; + unsigned ProbeAmt = 1; + const void *const *Array = CurArray; + const void *const *Tombstone = 0; + while (1) { + // Found Ptr's bucket? + if (Array[Bucket] == Ptr) + return Array+Bucket; + + // If we found an empty bucket, the pointer doesn't exist in the set. + // Return a tombstone if we've seen one so far, or the empty bucket if + // not. + if (Array[Bucket] == getEmptyMarker()) + return Tombstone ? Tombstone : Array+Bucket; + + // If this is a tombstone, remember it. If Ptr ends up not in the set, we + // prefer to return it than something that would require more probing. + if (Array[Bucket] == getTombstoneMarker() && !Tombstone) + Tombstone = Array+Bucket; // Remember the first tombstone found. + + // It's a hash collision or a tombstone. Reprobe. + Bucket = (Bucket + ProbeAmt++) & (ArraySize-1); + } +} + +/// Grow - Allocate a larger backing store for the buckets and move it over. +/// +void SmallPtrSetImpl::Grow() { + // Allocate at twice as many buckets, but at least 128. + unsigned OldSize = CurArraySize; + unsigned NewSize = OldSize < 64 ? 128 : OldSize*2; + + const void **OldBuckets = CurArray; + bool WasSmall = isSmall(); + + // Install the new array. Clear all the buckets to empty. + CurArray = (const void**)malloc(sizeof(void*) * (NewSize+1)); + assert(CurArray && "Failed to allocate memory?"); + CurArraySize = NewSize; + memset(CurArray, -1, NewSize*sizeof(void*)); + + // The end pointer, always valid, is set to a valid element to help the + // iterator. + CurArray[NewSize] = 0; + + // Copy over all the elements. + if (WasSmall) { + // Small sets store their elements in order. + for (const void **BucketPtr = OldBuckets, **E = OldBuckets+NumElements; + BucketPtr != E; ++BucketPtr) { + const void *Elt = *BucketPtr; + *const_cast(FindBucketFor(Elt)) = const_cast(Elt); + } + } else { + // Copy over all valid entries. + for (const void **BucketPtr = OldBuckets, **E = OldBuckets+OldSize; + BucketPtr != E; ++BucketPtr) { + // Copy over the element if it is valid. + const void *Elt = *BucketPtr; + if (Elt != getTombstoneMarker() && Elt != getEmptyMarker()) + *const_cast(FindBucketFor(Elt)) = const_cast(Elt); + } + + free(OldBuckets); + NumTombstones = 0; + } +} + +SmallPtrSetImpl::SmallPtrSetImpl(const SmallPtrSetImpl& that) { + // If we're becoming small, prepare to insert into our stack space + if (that.isSmall()) { + CurArray = &SmallArray[0]; + // Otherwise, allocate new heap space (unless we were the same size) + } else { + CurArray = (const void**)malloc(sizeof(void*) * (that.CurArraySize+1)); + assert(CurArray && "Failed to allocate memory?"); + } + + // Copy over the new array size + CurArraySize = that.CurArraySize; + + // Copy over the contents from the other set + memcpy(CurArray, that.CurArray, sizeof(void*)*(CurArraySize+1)); + + NumElements = that.NumElements; + NumTombstones = that.NumTombstones; +} + +/// CopyFrom - implement operator= from a smallptrset that has the same pointer +/// type, but may have a different small size. +void SmallPtrSetImpl::CopyFrom(const SmallPtrSetImpl &RHS) { + if (isSmall() && RHS.isSmall()) + assert(CurArraySize == RHS.CurArraySize && + "Cannot assign sets with different small sizes"); + + // If we're becoming small, prepare to insert into our stack space + if (RHS.isSmall()) { + if (!isSmall()) + free(CurArray); + CurArray = &SmallArray[0]; + // Otherwise, allocate new heap space (unless we were the same size) + } else if (CurArraySize != RHS.CurArraySize) { + if (isSmall()) + CurArray = (const void**)malloc(sizeof(void*) * (RHS.CurArraySize+1)); + else + CurArray = (const void**)realloc(CurArray, sizeof(void*)*(RHS.CurArraySize+1)); + assert(CurArray && "Failed to allocate memory?"); + } + + // Copy over the new array size + CurArraySize = RHS.CurArraySize; + + // Copy over the contents from the other set + memcpy(CurArray, RHS.CurArray, sizeof(void*)*(CurArraySize+1)); + + NumElements = RHS.NumElements; + NumTombstones = RHS.NumTombstones; +} + +SmallPtrSetImpl::~SmallPtrSetImpl() { + if (!isSmall()) + free(CurArray); +} diff --git a/libclamav/c++/llvm/lib/Support/SourceMgr.cpp b/libclamav/c++/llvm/lib/Support/SourceMgr.cpp new file mode 100644 index 000000000..7dd42f4df --- /dev/null +++ b/libclamav/c++/llvm/lib/Support/SourceMgr.cpp @@ -0,0 +1,218 @@ +//===- SourceMgr.cpp - Manager for Simple Source Buffers & Diagnostics ----===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the SourceMgr class. This class is used as a simple +// substrate for diagnostics, #include handling, and other low level things for +// simple parsers. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/SourceMgr.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +namespace { + struct LineNoCacheTy { + int LastQueryBufferID; + const char *LastQuery; + unsigned LineNoOfQuery; + }; +} + +static LineNoCacheTy *getCache(void *Ptr) { + return (LineNoCacheTy*)Ptr; +} + + +SourceMgr::~SourceMgr() { + // Delete the line # cache if allocated. + if (LineNoCacheTy *Cache = getCache(LineNoCache)) + delete Cache; + + while (!Buffers.empty()) { + delete Buffers.back().Buffer; + Buffers.pop_back(); + } +} + +/// AddIncludeFile - Search for a file with the specified name in the current +/// directory or in one of the IncludeDirs. If no file is found, this returns +/// ~0, otherwise it returns the buffer ID of the stacked file. +unsigned SourceMgr::AddIncludeFile(const std::string &Filename, + SMLoc IncludeLoc) { + + MemoryBuffer *NewBuf = MemoryBuffer::getFile(Filename.c_str()); + + // If the file didn't exist directly, see if it's in an include path. + for (unsigned i = 0, e = IncludeDirectories.size(); i != e && !NewBuf; ++i) { + std::string IncFile = IncludeDirectories[i] + "/" + Filename; + NewBuf = MemoryBuffer::getFile(IncFile.c_str()); + } + + if (NewBuf == 0) return ~0U; + + return AddNewSourceBuffer(NewBuf, IncludeLoc); +} + + +/// FindBufferContainingLoc - Return the ID of the buffer containing the +/// specified location, returning -1 if not found. +int SourceMgr::FindBufferContainingLoc(SMLoc Loc) const { + for (unsigned i = 0, e = Buffers.size(); i != e; ++i) + if (Loc.getPointer() >= Buffers[i].Buffer->getBufferStart() && + // Use <= here so that a pointer to the null at the end of the buffer + // is included as part of the buffer. + Loc.getPointer() <= Buffers[i].Buffer->getBufferEnd()) + return i; + return -1; +} + +/// FindLineNumber - Find the line number for the specified location in the +/// specified file. This is not a fast method. +unsigned SourceMgr::FindLineNumber(SMLoc Loc, int BufferID) const { + if (BufferID == -1) BufferID = FindBufferContainingLoc(Loc); + assert(BufferID != -1 && "Invalid Location!"); + + MemoryBuffer *Buff = getBufferInfo(BufferID).Buffer; + + // Count the number of \n's between the start of the file and the specified + // location. + unsigned LineNo = 1; + + const char *Ptr = Buff->getBufferStart(); + + // If we have a line number cache, and if the query is to a later point in the + // same file, start searching from the last query location. This optimizes + // for the case when multiple diagnostics come out of one file in order. + if (LineNoCacheTy *Cache = getCache(LineNoCache)) + if (Cache->LastQueryBufferID == BufferID && + Cache->LastQuery <= Loc.getPointer()) { + Ptr = Cache->LastQuery; + LineNo = Cache->LineNoOfQuery; + } + + // Scan for the location being queried, keeping track of the number of lines + // we see. + for (; SMLoc::getFromPointer(Ptr) != Loc; ++Ptr) + if (*Ptr == '\n') ++LineNo; + + + // Allocate the line number cache if it doesn't exist. + if (LineNoCache == 0) + LineNoCache = new LineNoCacheTy(); + + // Update the line # cache. + LineNoCacheTy &Cache = *getCache(LineNoCache); + Cache.LastQueryBufferID = BufferID; + Cache.LastQuery = Ptr; + Cache.LineNoOfQuery = LineNo; + return LineNo; +} + +void SourceMgr::PrintIncludeStack(SMLoc IncludeLoc, raw_ostream &OS) const { + if (IncludeLoc == SMLoc()) return; // Top of stack. + + int CurBuf = FindBufferContainingLoc(IncludeLoc); + assert(CurBuf != -1 && "Invalid or unspecified location!"); + + PrintIncludeStack(getBufferInfo(CurBuf).IncludeLoc, OS); + + OS << "Included from " + << getBufferInfo(CurBuf).Buffer->getBufferIdentifier() + << ":" << FindLineNumber(IncludeLoc, CurBuf) << ":\n"; +} + + +/// GetMessage - Return an SMDiagnostic at the specified location with the +/// specified string. +/// +/// @param Type - If non-null, the kind of message (e.g., "error") which is +/// prefixed to the message. +SMDiagnostic SourceMgr::GetMessage(SMLoc Loc, const std::string &Msg, + const char *Type, bool ShowLine) const { + + // First thing to do: find the current buffer containing the specified + // location. + int CurBuf = FindBufferContainingLoc(Loc); + assert(CurBuf != -1 && "Invalid or unspecified location!"); + + MemoryBuffer *CurMB = getBufferInfo(CurBuf).Buffer; + + // Scan backward to find the start of the line. + const char *LineStart = Loc.getPointer(); + while (LineStart != CurMB->getBufferStart() && + LineStart[-1] != '\n' && LineStart[-1] != '\r') + --LineStart; + + std::string LineStr; + if (ShowLine) { + // Get the end of the line. + const char *LineEnd = Loc.getPointer(); + while (LineEnd != CurMB->getBufferEnd() && + LineEnd[0] != '\n' && LineEnd[0] != '\r') + ++LineEnd; + LineStr = std::string(LineStart, LineEnd); + } + + std::string PrintedMsg; + if (Type) { + PrintedMsg = Type; + PrintedMsg += ": "; + } + PrintedMsg += Msg; + + return SMDiagnostic(CurMB->getBufferIdentifier(), FindLineNumber(Loc, CurBuf), + Loc.getPointer()-LineStart, PrintedMsg, + LineStr, ShowLine); +} + +void SourceMgr::PrintMessage(SMLoc Loc, const std::string &Msg, + const char *Type, bool ShowLine) const { + raw_ostream &OS = errs(); + + int CurBuf = FindBufferContainingLoc(Loc); + assert(CurBuf != -1 && "Invalid or unspecified location!"); + PrintIncludeStack(getBufferInfo(CurBuf).IncludeLoc, OS); + + GetMessage(Loc, Msg, Type, ShowLine).Print(0, OS); +} + +//===----------------------------------------------------------------------===// +// SMDiagnostic Implementation +//===----------------------------------------------------------------------===// + +void SMDiagnostic::Print(const char *ProgName, raw_ostream &S) { + if (ProgName && ProgName[0]) + S << ProgName << ": "; + + if (Filename == "-") + S << ""; + else + S << Filename; + + if (LineNo != -1) { + S << ':' << LineNo; + if (ColumnNo != -1) + S << ':' << (ColumnNo+1); + } + + S << ": " << Message << '\n'; + + if (LineNo != -1 && ColumnNo != -1 && ShowLine) { + S << LineContents << '\n'; + + // Print out spaces/tabs before the caret. + for (unsigned i = 0; i != unsigned(ColumnNo); ++i) + S << (LineContents[i] == '\t' ? '\t' : ' '); + S << "^\n"; + } +} + + diff --git a/libclamav/c++/llvm/lib/Support/Statistic.cpp b/libclamav/c++/llvm/lib/Support/Statistic.cpp new file mode 100644 index 000000000..14f94bc28 --- /dev/null +++ b/libclamav/c++/llvm/lib/Support/Statistic.cpp @@ -0,0 +1,132 @@ +//===-- Statistic.cpp - Easy way to expose stats information --------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the 'Statistic' class, which is designed to be an easy +// way to expose various success metrics from passes. These statistics are +// printed at the end of a run, when the -stats command line option is enabled +// on the command line. +// +// This is useful for reporting information like the number of instructions +// simplified, optimized or removed by various transformations, like this: +// +// static Statistic NumInstEliminated("GCSE", "Number of instructions killed"); +// +// Later, in the code: ++NumInstEliminated; +// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/Statistic.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/ManagedStatic.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/System/Mutex.h" +#include "llvm/ADT/StringExtras.h" +#include +#include +using namespace llvm; + +// GetLibSupportInfoOutputFile - Return a file stream to print our output on. +namespace llvm { extern raw_ostream *GetLibSupportInfoOutputFile(); } + +/// -stats - Command line option to cause transformations to emit stats about +/// what they did. +/// +static cl::opt +Enabled("stats", cl::desc("Enable statistics output from program")); + + +namespace { +/// StatisticInfo - This class is used in a ManagedStatic so that it is created +/// on demand (when the first statistic is bumped) and destroyed only when +/// llvm_shutdown is called. We print statistics from the destructor. +class StatisticInfo { + std::vector Stats; +public: + ~StatisticInfo(); + + void addStatistic(const Statistic *S) { + Stats.push_back(S); + } +}; +} + +static ManagedStatic StatInfo; +static ManagedStatic > StatLock; + +/// RegisterStatistic - The first time a statistic is bumped, this method is +/// called. +void Statistic::RegisterStatistic() { + // If stats are enabled, inform StatInfo that this statistic should be + // printed. + sys::SmartScopedLock Writer(*StatLock); + if (!Initialized) { + if (Enabled) + StatInfo->addStatistic(this); + + sys::MemoryFence(); + // Remember we have been registered. + Initialized = true; + } +} + +namespace { + +struct NameCompare { + bool operator()(const Statistic *LHS, const Statistic *RHS) const { + int Cmp = std::strcmp(LHS->getName(), RHS->getName()); + if (Cmp != 0) return Cmp < 0; + + // Secondary key is the description. + return std::strcmp(LHS->getDesc(), RHS->getDesc()) < 0; + } +}; + +} + +// Print information when destroyed, iff command line option is specified. +StatisticInfo::~StatisticInfo() { + // Statistics not enabled? + if (Stats.empty()) return; + + // Get the stream to write to. + raw_ostream &OutStream = *GetLibSupportInfoOutputFile(); + + // Figure out how long the biggest Value and Name fields are. + unsigned MaxNameLen = 0, MaxValLen = 0; + for (size_t i = 0, e = Stats.size(); i != e; ++i) { + MaxValLen = std::max(MaxValLen, + (unsigned)utostr(Stats[i]->getValue()).size()); + MaxNameLen = std::max(MaxNameLen, + (unsigned)std::strlen(Stats[i]->getName())); + } + + // Sort the fields by name. + std::stable_sort(Stats.begin(), Stats.end(), NameCompare()); + + // Print out the statistics header... + OutStream << "===" << std::string(73, '-') << "===\n" + << " ... Statistics Collected ...\n" + << "===" << std::string(73, '-') << "===\n\n"; + + // Print all of the statistics. + for (size_t i = 0, e = Stats.size(); i != e; ++i) { + std::string CountStr = utostr(Stats[i]->getValue()); + OutStream << std::string(MaxValLen-CountStr.size(), ' ') + << CountStr << " " << Stats[i]->getName() + << std::string(MaxNameLen-std::strlen(Stats[i]->getName()), ' ') + << " - " << Stats[i]->getDesc() << "\n"; + + } + + OutStream << '\n'; // Flush the output stream... + OutStream.flush(); + + if (&OutStream != &outs() && &OutStream != &errs()) + delete &OutStream; // Close the file. +} diff --git a/libclamav/c++/llvm/lib/Support/StringExtras.cpp b/libclamav/c++/llvm/lib/Support/StringExtras.cpp new file mode 100644 index 000000000..1b233ab20 --- /dev/null +++ b/libclamav/c++/llvm/lib/Support/StringExtras.cpp @@ -0,0 +1,80 @@ +//===-- StringExtras.cpp - Implement the StringExtras header --------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the StringExtras.h header +// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/SmallVector.h" +#include +using namespace llvm; + +/// getToken - This function extracts one token from source, ignoring any +/// leading characters that appear in the Delimiters string, and ending the +/// token at any of the characters that appear in the Delimiters string. If +/// there are no tokens in the source string, an empty string is returned. +/// The Source source string is updated in place to remove the returned string +/// and any delimiter prefix from it. +std::string llvm::getToken(std::string &Source, const char *Delimiters) { + size_t NumDelimiters = std::strlen(Delimiters); + + // Figure out where the token starts. + std::string::size_type Start = + Source.find_first_not_of(Delimiters, 0, NumDelimiters); + if (Start == std::string::npos) Start = Source.size(); + + // Find the next occurance of the delimiter. + std::string::size_type End = + Source.find_first_of(Delimiters, Start, NumDelimiters); + if (End == std::string::npos) End = Source.size(); + + // Create the return token. + std::string Result = std::string(Source.begin()+Start, Source.begin()+End); + + // Erase the token that we read in. + Source.erase(Source.begin(), Source.begin()+End); + + return Result; +} + +/// SplitString - Split up the specified string according to the specified +/// delimiters, appending the result fragments to the output list. +void llvm::SplitString(const std::string &Source, + std::vector &OutFragments, + const char *Delimiters) { + std::string S = Source; + + std::string S2 = getToken(S, Delimiters); + while (!S2.empty()) { + OutFragments.push_back(S2); + S2 = getToken(S, Delimiters); + } +} + +void llvm::StringRef::split(SmallVectorImpl &A, + StringRef Separators, int MaxSplit, + bool KeepEmpty) const { + StringRef rest = *this; + + // rest.data() is used to distinguish cases like "a," that splits into + // "a" + "" and "a" that splits into "a" + 0. + for (int splits = 0; + rest.data() != NULL && (MaxSplit < 0 || splits < MaxSplit); + ++splits) { + std::pair p = rest.split(Separators); + + if (p.first.size() != 0 || KeepEmpty) + A.push_back(p.first); + rest = p.second; + } + // If we have a tail left, add it. + if (rest.data() != NULL && (rest.size() != 0 || KeepEmpty)) + A.push_back(rest); +} diff --git a/libclamav/c++/llvm/lib/Support/StringMap.cpp b/libclamav/c++/llvm/lib/Support/StringMap.cpp new file mode 100644 index 000000000..6f2827789 --- /dev/null +++ b/libclamav/c++/llvm/lib/Support/StringMap.cpp @@ -0,0 +1,215 @@ +//===--- StringMap.cpp - String Hash table map implementation -------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the StringMap class. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringExtras.h" +#include +using namespace llvm; + +StringMapImpl::StringMapImpl(unsigned InitSize, unsigned itemSize) { + ItemSize = itemSize; + + // If a size is specified, initialize the table with that many buckets. + if (InitSize) { + init(InitSize); + return; + } + + // Otherwise, initialize it with zero buckets to avoid the allocation. + TheTable = 0; + NumBuckets = 0; + NumItems = 0; + NumTombstones = 0; +} + +void StringMapImpl::init(unsigned InitSize) { + assert((InitSize & (InitSize-1)) == 0 && + "Init Size must be a power of 2 or zero!"); + NumBuckets = InitSize ? InitSize : 16; + NumItems = 0; + NumTombstones = 0; + + TheTable = (ItemBucket*)calloc(NumBuckets+1, sizeof(ItemBucket)); + + // Allocate one extra bucket, set it to look filled so the iterators stop at + // end. + TheTable[NumBuckets].Item = (StringMapEntryBase*)2; +} + + +/// LookupBucketFor - Look up the bucket that the specified string should end +/// up in. If it already exists as a key in the map, the Item pointer for the +/// specified bucket will be non-null. Otherwise, it will be null. In either +/// case, the FullHashValue field of the bucket will be set to the hash value +/// of the string. +unsigned StringMapImpl::LookupBucketFor(StringRef Name) { + unsigned HTSize = NumBuckets; + if (HTSize == 0) { // Hash table unallocated so far? + init(16); + HTSize = NumBuckets; + } + unsigned FullHashValue = HashString(Name); + unsigned BucketNo = FullHashValue & (HTSize-1); + + unsigned ProbeAmt = 1; + int FirstTombstone = -1; + while (1) { + ItemBucket &Bucket = TheTable[BucketNo]; + StringMapEntryBase *BucketItem = Bucket.Item; + // If we found an empty bucket, this key isn't in the table yet, return it. + if (BucketItem == 0) { + // If we found a tombstone, we want to reuse the tombstone instead of an + // empty bucket. This reduces probing. + if (FirstTombstone != -1) { + TheTable[FirstTombstone].FullHashValue = FullHashValue; + return FirstTombstone; + } + + Bucket.FullHashValue = FullHashValue; + return BucketNo; + } + + if (BucketItem == getTombstoneVal()) { + // Skip over tombstones. However, remember the first one we see. + if (FirstTombstone == -1) FirstTombstone = BucketNo; + } else if (Bucket.FullHashValue == FullHashValue) { + // If the full hash value matches, check deeply for a match. The common + // case here is that we are only looking at the buckets (for item info + // being non-null and for the full hash value) not at the items. This + // is important for cache locality. + + // Do the comparison like this because Name isn't necessarily + // null-terminated! + char *ItemStr = (char*)BucketItem+ItemSize; + if (Name == StringRef(ItemStr, BucketItem->getKeyLength())) { + // We found a match! + return BucketNo; + } + } + + // Okay, we didn't find the item. Probe to the next bucket. + BucketNo = (BucketNo+ProbeAmt) & (HTSize-1); + + // Use quadratic probing, it has fewer clumping artifacts than linear + // probing and has good cache behavior in the common case. + ++ProbeAmt; + } +} + + +/// FindKey - Look up the bucket that contains the specified key. If it exists +/// in the map, return the bucket number of the key. Otherwise return -1. +/// This does not modify the map. +int StringMapImpl::FindKey(StringRef Key) const { + unsigned HTSize = NumBuckets; + if (HTSize == 0) return -1; // Really empty table? + unsigned FullHashValue = HashString(Key); + unsigned BucketNo = FullHashValue & (HTSize-1); + + unsigned ProbeAmt = 1; + while (1) { + ItemBucket &Bucket = TheTable[BucketNo]; + StringMapEntryBase *BucketItem = Bucket.Item; + // If we found an empty bucket, this key isn't in the table yet, return. + if (BucketItem == 0) + return -1; + + if (BucketItem == getTombstoneVal()) { + // Ignore tombstones. + } else if (Bucket.FullHashValue == FullHashValue) { + // If the full hash value matches, check deeply for a match. The common + // case here is that we are only looking at the buckets (for item info + // being non-null and for the full hash value) not at the items. This + // is important for cache locality. + + // Do the comparison like this because NameStart isn't necessarily + // null-terminated! + char *ItemStr = (char*)BucketItem+ItemSize; + if (Key == StringRef(ItemStr, BucketItem->getKeyLength())) { + // We found a match! + return BucketNo; + } + } + + // Okay, we didn't find the item. Probe to the next bucket. + BucketNo = (BucketNo+ProbeAmt) & (HTSize-1); + + // Use quadratic probing, it has fewer clumping artifacts than linear + // probing and has good cache behavior in the common case. + ++ProbeAmt; + } +} + +/// RemoveKey - Remove the specified StringMapEntry from the table, but do not +/// delete it. This aborts if the value isn't in the table. +void StringMapImpl::RemoveKey(StringMapEntryBase *V) { + const char *VStr = (char*)V + ItemSize; + StringMapEntryBase *V2 = RemoveKey(StringRef(VStr, V->getKeyLength())); + V2 = V2; + assert(V == V2 && "Didn't find key?"); +} + +/// RemoveKey - Remove the StringMapEntry for the specified key from the +/// table, returning it. If the key is not in the table, this returns null. +StringMapEntryBase *StringMapImpl::RemoveKey(StringRef Key) { + int Bucket = FindKey(Key); + if (Bucket == -1) return 0; + + StringMapEntryBase *Result = TheTable[Bucket].Item; + TheTable[Bucket].Item = getTombstoneVal(); + --NumItems; + ++NumTombstones; + return Result; +} + + + +/// RehashTable - Grow the table, redistributing values into the buckets with +/// the appropriate mod-of-hashtable-size. +void StringMapImpl::RehashTable() { + unsigned NewSize = NumBuckets*2; + // Allocate one extra bucket which will always be non-empty. This allows the + // iterators to stop at end. + ItemBucket *NewTableArray =(ItemBucket*)calloc(NewSize+1, sizeof(ItemBucket)); + NewTableArray[NewSize].Item = (StringMapEntryBase*)2; + + // Rehash all the items into their new buckets. Luckily :) we already have + // the hash values available, so we don't have to rehash any strings. + for (ItemBucket *IB = TheTable, *E = TheTable+NumBuckets; IB != E; ++IB) { + if (IB->Item && IB->Item != getTombstoneVal()) { + // Fast case, bucket available. + unsigned FullHash = IB->FullHashValue; + unsigned NewBucket = FullHash & (NewSize-1); + if (NewTableArray[NewBucket].Item == 0) { + NewTableArray[FullHash & (NewSize-1)].Item = IB->Item; + NewTableArray[FullHash & (NewSize-1)].FullHashValue = FullHash; + continue; + } + + // Otherwise probe for a spot. + unsigned ProbeSize = 1; + do { + NewBucket = (NewBucket + ProbeSize++) & (NewSize-1); + } while (NewTableArray[NewBucket].Item); + + // Finally found a slot. Fill it in. + NewTableArray[NewBucket].Item = IB->Item; + NewTableArray[NewBucket].FullHashValue = FullHash; + } + } + + free(TheTable); + + TheTable = NewTableArray; + NumBuckets = NewSize; +} diff --git a/libclamav/c++/llvm/lib/Support/StringPool.cpp b/libclamav/c++/llvm/lib/Support/StringPool.cpp new file mode 100644 index 000000000..1ee917f11 --- /dev/null +++ b/libclamav/c++/llvm/lib/Support/StringPool.cpp @@ -0,0 +1,35 @@ +//===-- StringPool.cpp - Interned string pool -----------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the StringPool class. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/StringPool.h" +#include "llvm/ADT/StringRef.h" + +using namespace llvm; + +StringPool::StringPool() {} + +StringPool::~StringPool() { + assert(InternTable.empty() && "PooledStringPtr leaked!"); +} + +PooledStringPtr StringPool::intern(const StringRef &Key) { + table_t::iterator I = InternTable.find(Key); + if (I != InternTable.end()) + return PooledStringPtr(&*I); + + entry_t *S = entry_t::Create(Key.begin(), Key.end()); + S->getValue().Pool = this; + InternTable.insert(S); + + return PooledStringPtr(S); +} diff --git a/libclamav/c++/llvm/lib/Support/StringRef.cpp b/libclamav/c++/llvm/lib/Support/StringRef.cpp new file mode 100644 index 000000000..2d023e489 --- /dev/null +++ b/libclamav/c++/llvm/lib/Support/StringRef.cpp @@ -0,0 +1,223 @@ +//===-- StringRef.cpp - Lightweight String References ---------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/StringRef.h" +using namespace llvm; + +// MSVC emits references to this into the translation units which reference it. +#ifndef _MSC_VER +const size_t StringRef::npos; +#endif + +static char ascii_tolower(char x) { + if (x >= 'A' && x <= 'Z') + return x - 'A' + 'a'; + return x; +} + +/// compare_lower - Compare strings, ignoring case. +int StringRef::compare_lower(StringRef RHS) const { + for (size_t I = 0, E = min(Length, RHS.Length); I != E; ++I) { + char LHC = ascii_tolower(Data[I]); + char RHC = ascii_tolower(RHS.Data[I]); + if (LHC != RHC) + return LHC < RHC ? -1 : 1; + } + + if (Length == RHS.Length) + return 0; + return Length < RHS.Length ? -1 : 1; +} + +//===----------------------------------------------------------------------===// +// String Searching +//===----------------------------------------------------------------------===// + + +/// find - Search for the first string \arg Str in the string. +/// +/// \return - The index of the first occurence of \arg Str, or npos if not +/// found. +size_t StringRef::find(StringRef Str, size_t From) const { + size_t N = Str.size(); + if (N > Length) + return npos; + for (size_t e = Length - N + 1, i = min(From, e); i != e; ++i) + if (substr(i, N).equals(Str)) + return i; + return npos; +} + +/// rfind - Search for the last string \arg Str in the string. +/// +/// \return - The index of the last occurence of \arg Str, or npos if not +/// found. +size_t StringRef::rfind(StringRef Str) const { + size_t N = Str.size(); + if (N > Length) + return npos; + for (size_t i = Length - N + 1, e = 0; i != e;) { + --i; + if (substr(i, N).equals(Str)) + return i; + } + return npos; +} + +/// find_first_of - Find the first character in the string that is in \arg +/// Chars, or npos if not found. +/// +/// Note: O(size() * Chars.size()) +StringRef::size_type StringRef::find_first_of(StringRef Chars, + size_t From) const { + for (size_type i = min(From, Length), e = Length; i != e; ++i) + if (Chars.find(Data[i]) != npos) + return i; + return npos; +} + +/// find_first_not_of - Find the first character in the string that is not +/// \arg C or npos if not found. +StringRef::size_type StringRef::find_first_not_of(char C, size_t From) const { + for (size_type i = min(From, Length), e = Length; i != e; ++i) + if (Data[i] != C) + return i; + return npos; +} + +/// find_first_not_of - Find the first character in the string that is not +/// in the string \arg Chars, or npos if not found. +/// +/// Note: O(size() * Chars.size()) +StringRef::size_type StringRef::find_first_not_of(StringRef Chars, + size_t From) const { + for (size_type i = min(From, Length), e = Length; i != e; ++i) + if (Chars.find(Data[i]) == npos) + return i; + return npos; +} + + +//===----------------------------------------------------------------------===// +// Helpful Algorithms +//===----------------------------------------------------------------------===// + +/// count - Return the number of non-overlapped occurrences of \arg Str in +/// the string. +size_t StringRef::count(StringRef Str) const { + size_t Count = 0; + size_t N = Str.size(); + if (N > Length) + return 0; + for (size_t i = 0, e = Length - N + 1; i != e; ++i) + if (substr(i, N).equals(Str)) + ++Count; + return Count; +} + +/// GetAsUnsignedInteger - Workhorse method that converts a integer character +/// sequence of radix up to 36 to an unsigned long long value. +static bool GetAsUnsignedInteger(StringRef Str, unsigned Radix, + unsigned long long &Result) { + // Autosense radix if not specified. + if (Radix == 0) { + if (Str.startswith("0x")) { + Str = Str.substr(2); + Radix = 16; + } else if (Str.startswith("0b")) { + Str = Str.substr(2); + Radix = 2; + } else if (Str.startswith("0")) + Radix = 8; + else + Radix = 10; + } + + // Empty strings (after the radix autosense) are invalid. + if (Str.empty()) return true; + + // Parse all the bytes of the string given this radix. Watch for overflow. + Result = 0; + while (!Str.empty()) { + unsigned CharVal; + if (Str[0] >= '0' && Str[0] <= '9') + CharVal = Str[0]-'0'; + else if (Str[0] >= 'a' && Str[0] <= 'z') + CharVal = Str[0]-'a'+10; + else if (Str[0] >= 'A' && Str[0] <= 'Z') + CharVal = Str[0]-'A'+10; + else + return true; + + // If the parsed value is larger than the integer radix, the string is + // invalid. + if (CharVal >= Radix) + return true; + + // Add in this character. + unsigned long long PrevResult = Result; + Result = Result*Radix+CharVal; + + // Check for overflow. + if (Result < PrevResult) + return true; + + Str = Str.substr(1); + } + + return false; +} + +bool StringRef::getAsInteger(unsigned Radix, unsigned long long &Result) const { + return GetAsUnsignedInteger(*this, Radix, Result); +} + + +bool StringRef::getAsInteger(unsigned Radix, long long &Result) const { + unsigned long long ULLVal; + + // Handle positive strings first. + if (empty() || front() != '-') { + if (GetAsUnsignedInteger(*this, Radix, ULLVal) || + // Check for value so large it overflows a signed value. + (long long)ULLVal < 0) + return true; + Result = ULLVal; + return false; + } + + // Get the positive part of the value. + if (GetAsUnsignedInteger(substr(1), Radix, ULLVal) || + // Reject values so large they'd overflow as negative signed, but allow + // "-0". This negates the unsigned so that the negative isn't undefined + // on signed overflow. + (long long)-ULLVal > 0) + return true; + + Result = -ULLVal; + return false; +} + +bool StringRef::getAsInteger(unsigned Radix, int &Result) const { + long long Val; + if (getAsInteger(Radix, Val) || + (int)Val != Val) + return true; + Result = Val; + return false; +} + +bool StringRef::getAsInteger(unsigned Radix, unsigned &Result) const { + unsigned long long Val; + if (getAsInteger(Radix, Val) || + (unsigned)Val != Val) + return true; + Result = Val; + return false; +} diff --git a/libclamav/c++/llvm/lib/Support/SystemUtils.cpp b/libclamav/c++/llvm/lib/Support/SystemUtils.cpp new file mode 100644 index 000000000..299032f18 --- /dev/null +++ b/libclamav/c++/llvm/lib/Support/SystemUtils.cpp @@ -0,0 +1,55 @@ +//===- SystemUtils.cpp - Utilities for low-level system tasks -------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains functions used to do a variety of low-level, often +// system-specific, tasks. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/SystemUtils.h" +#include "llvm/System/Process.h" +#include "llvm/System/Program.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +bool llvm::CheckBitcodeOutputToConsole(raw_ostream &stream_to_check, + bool print_warning) { + if (stream_to_check.is_displayed()) { + if (print_warning) { + errs() << "WARNING: You're attempting to print out a bitcode file.\n" + << "This is inadvisable as it may cause display problems. If\n" + << "you REALLY want to taste LLVM bitcode first-hand, you\n" + << "can force output with the `-f' option.\n\n"; + } + return true; + } + return false; +} + +/// FindExecutable - Find a named executable, giving the argv[0] of program +/// being executed. This allows us to find another LLVM tool if it is built in +/// the same directory. If the executable cannot be found, return an +/// empty string. +/// @brief Find a named executable. +#undef FindExecutable // needed on windows :( +sys::Path llvm::FindExecutable(const std::string &ExeName, + const char *Argv0, void *MainAddr) { + // Check the directory that the calling program is in. We can do + // this if ProgramPath contains at least one / character, indicating that it + // is a relative path to the executable itself. + sys::Path Result = sys::Path::GetMainExecutable(Argv0, MainAddr); + Result.eraseComponent(); + if (!Result.isEmpty()) { + Result.appendComponent(ExeName); + if (Result.canExecute()) + return Result; + } + + return sys::Path(); +} diff --git a/libclamav/c++/llvm/lib/Support/TargetRegistry.cpp b/libclamav/c++/llvm/lib/Support/TargetRegistry.cpp new file mode 100644 index 000000000..5896447f5 --- /dev/null +++ b/libclamav/c++/llvm/lib/Support/TargetRegistry.cpp @@ -0,0 +1,92 @@ +//===--- TargetRegistry.cpp - Target registration -------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Target/TargetRegistry.h" +#include "llvm/System/Host.h" +#include +using namespace llvm; + +// Clients are responsible for avoid race conditions in registration. +static Target *FirstTarget = 0; + +TargetRegistry::iterator TargetRegistry::begin() { + return iterator(FirstTarget); +} + +const Target *TargetRegistry::lookupTarget(const std::string &TT, + std::string &Error) { + // Provide special warning when no targets are initialized. + if (begin() == end()) { + Error = "Unable to find target for this triple (no targets are registered)"; + return 0; + } + const Target *Best = 0, *EquallyBest = 0; + unsigned BestQuality = 0; + for (iterator it = begin(), ie = end(); it != ie; ++it) { + if (unsigned Qual = it->TripleMatchQualityFn(TT)) { + if (!Best || Qual > BestQuality) { + Best = &*it; + EquallyBest = 0; + BestQuality = Qual; + } else if (Qual == BestQuality) + EquallyBest = &*it; + } + } + + if (!Best) { + Error = "No available targets are compatible with this triple, " + "see -version for the available targets."; + return 0; + } + + // Otherwise, take the best target, but make sure we don't have two equally + // good best targets. + if (EquallyBest) { + Error = std::string("Cannot choose between targets \"") + + Best->Name + "\" and \"" + EquallyBest->Name + "\""; + return 0; + } + + return Best; +} + +void TargetRegistry::RegisterTarget(Target &T, + const char *Name, + const char *ShortDesc, + Target::TripleMatchQualityFnTy TQualityFn, + bool HasJIT) { + assert(Name && ShortDesc && TQualityFn && + "Missing required target information!"); + + // Check if this target has already been initialized, we allow this as a + // convenience to some clients. + if (T.Name) + return; + + // Add to the list of targets. + T.Next = FirstTarget; + FirstTarget = &T; + + T.Name = Name; + T.ShortDesc = ShortDesc; + T.TripleMatchQualityFn = TQualityFn; + T.HasJIT = HasJIT; +} + +const Target *TargetRegistry::getClosestTargetForJIT(std::string &Error) { + const Target *TheTarget = lookupTarget(sys::getHostTriple(), Error); + + if (TheTarget && !TheTarget->hasJIT()) { + Error = "No JIT compatible target available for this host"; + return 0; + } + + return TheTarget; +} + diff --git a/libclamav/c++/llvm/lib/Support/Timer.cpp b/libclamav/c++/llvm/lib/Support/Timer.cpp new file mode 100644 index 000000000..7d32ee66c --- /dev/null +++ b/libclamav/c++/llvm/lib/Support/Timer.cpp @@ -0,0 +1,390 @@ +//===-- Timer.cpp - Interval Timing Support -------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Interval Timing implementation. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/Timer.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/ManagedStatic.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/Format.h" +#include "llvm/System/Process.h" +#include +#include +#include +using namespace llvm; + +// GetLibSupportInfoOutputFile - Return a file stream to print our output on. +namespace llvm { extern raw_ostream *GetLibSupportInfoOutputFile(); } + +// getLibSupportInfoOutputFilename - This ugly hack is brought to you courtesy +// of constructor/destructor ordering being unspecified by C++. Basically the +// problem is that a Statistic object gets destroyed, which ends up calling +// 'GetLibSupportInfoOutputFile()' (below), which calls this function. +// LibSupportInfoOutputFilename used to be a global variable, but sometimes it +// would get destroyed before the Statistic, causing havoc to ensue. We "fix" +// this by creating the string the first time it is needed and never destroying +// it. +static ManagedStatic LibSupportInfoOutputFilename; +static std::string &getLibSupportInfoOutputFilename() { + return *LibSupportInfoOutputFilename; +} + +static ManagedStatic > TimerLock; + +namespace { + static cl::opt + TrackSpace("track-memory", cl::desc("Enable -time-passes memory " + "tracking (this may be slow)"), + cl::Hidden); + + static cl::opt + InfoOutputFilename("info-output-file", cl::value_desc("filename"), + cl::desc("File to append -stats and -timer output to"), + cl::Hidden, cl::location(getLibSupportInfoOutputFilename())); +} + +static TimerGroup *DefaultTimerGroup = 0; +static TimerGroup *getDefaultTimerGroup() { + TimerGroup* tmp = DefaultTimerGroup; + sys::MemoryFence(); + if (!tmp) { + llvm_acquire_global_lock(); + tmp = DefaultTimerGroup; + if (!tmp) { + tmp = new TimerGroup("Miscellaneous Ungrouped Timers"); + sys::MemoryFence(); + DefaultTimerGroup = tmp; + } + llvm_release_global_lock(); + } + + return tmp; +} + +Timer::Timer(const std::string &N) + : Elapsed(0), UserTime(0), SystemTime(0), MemUsed(0), PeakMem(0), Name(N), + Started(false), TG(getDefaultTimerGroup()) { + TG->addTimer(); +} + +Timer::Timer(const std::string &N, TimerGroup &tg) + : Elapsed(0), UserTime(0), SystemTime(0), MemUsed(0), PeakMem(0), Name(N), + Started(false), TG(&tg) { + TG->addTimer(); +} + +Timer::Timer(const Timer &T) { + TG = T.TG; + if (TG) TG->addTimer(); + operator=(T); +} + + +// Copy ctor, initialize with no TG member. +Timer::Timer(bool, const Timer &T) { + TG = T.TG; // Avoid assertion in operator= + operator=(T); // Copy contents + TG = 0; +} + + +Timer::~Timer() { + if (TG) { + if (Started) { + Started = false; + TG->addTimerToPrint(*this); + } + TG->removeTimer(); + } +} + +static inline size_t getMemUsage() { + if (TrackSpace) + return sys::Process::GetMallocUsage(); + return 0; +} + +struct TimeRecord { + double Elapsed, UserTime, SystemTime; + ssize_t MemUsed; +}; + +static TimeRecord getTimeRecord(bool Start) { + TimeRecord Result; + + sys::TimeValue now(0,0); + sys::TimeValue user(0,0); + sys::TimeValue sys(0,0); + + ssize_t MemUsed = 0; + if (Start) { + MemUsed = getMemUsage(); + sys::Process::GetTimeUsage(now,user,sys); + } else { + sys::Process::GetTimeUsage(now,user,sys); + MemUsed = getMemUsage(); + } + + Result.Elapsed = now.seconds() + now.microseconds() / 1000000.0; + Result.UserTime = user.seconds() + user.microseconds() / 1000000.0; + Result.SystemTime = sys.seconds() + sys.microseconds() / 1000000.0; + Result.MemUsed = MemUsed; + + return Result; +} + +static ManagedStatic > ActiveTimers; + +void Timer::startTimer() { + sys::SmartScopedLock L(*TimerLock); + Started = true; + ActiveTimers->push_back(this); + TimeRecord TR = getTimeRecord(true); + Elapsed -= TR.Elapsed; + UserTime -= TR.UserTime; + SystemTime -= TR.SystemTime; + MemUsed -= TR.MemUsed; + PeakMemBase = TR.MemUsed; +} + +void Timer::stopTimer() { + sys::SmartScopedLock L(*TimerLock); + TimeRecord TR = getTimeRecord(false); + Elapsed += TR.Elapsed; + UserTime += TR.UserTime; + SystemTime += TR.SystemTime; + MemUsed += TR.MemUsed; + + if (ActiveTimers->back() == this) { + ActiveTimers->pop_back(); + } else { + std::vector::iterator I = + std::find(ActiveTimers->begin(), ActiveTimers->end(), this); + assert(I != ActiveTimers->end() && "stop but no startTimer?"); + ActiveTimers->erase(I); + } +} + +void Timer::sum(const Timer &T) { + Elapsed += T.Elapsed; + UserTime += T.UserTime; + SystemTime += T.SystemTime; + MemUsed += T.MemUsed; + PeakMem += T.PeakMem; +} + +/// addPeakMemoryMeasurement - This method should be called whenever memory +/// usage needs to be checked. It adds a peak memory measurement to the +/// currently active timers, which will be printed when the timer group prints +/// +void Timer::addPeakMemoryMeasurement() { + sys::SmartScopedLock L(*TimerLock); + size_t MemUsed = getMemUsage(); + + for (std::vector::iterator I = ActiveTimers->begin(), + E = ActiveTimers->end(); I != E; ++I) + (*I)->PeakMem = std::max((*I)->PeakMem, MemUsed-(*I)->PeakMemBase); +} + +//===----------------------------------------------------------------------===// +// NamedRegionTimer Implementation +//===----------------------------------------------------------------------===// + +namespace { + +typedef std::map Name2Timer; +typedef std::map > Name2Pair; + +} + +static ManagedStatic NamedTimers; + +static ManagedStatic NamedGroupedTimers; + +static Timer &getNamedRegionTimer(const std::string &Name) { + sys::SmartScopedLock L(*TimerLock); + Name2Timer::iterator I = NamedTimers->find(Name); + if (I != NamedTimers->end()) + return I->second; + + return NamedTimers->insert(I, std::make_pair(Name, Timer(Name)))->second; +} + +static Timer &getNamedRegionTimer(const std::string &Name, + const std::string &GroupName) { + sys::SmartScopedLock L(*TimerLock); + + Name2Pair::iterator I = NamedGroupedTimers->find(GroupName); + if (I == NamedGroupedTimers->end()) { + TimerGroup TG(GroupName); + std::pair Pair(TG, Name2Timer()); + I = NamedGroupedTimers->insert(I, std::make_pair(GroupName, Pair)); + } + + Name2Timer::iterator J = I->second.second.find(Name); + if (J == I->second.second.end()) + J = I->second.second.insert(J, + std::make_pair(Name, + Timer(Name, + I->second.first))); + + return J->second; +} + +NamedRegionTimer::NamedRegionTimer(const std::string &Name) + : TimeRegion(getNamedRegionTimer(Name)) {} + +NamedRegionTimer::NamedRegionTimer(const std::string &Name, + const std::string &GroupName) + : TimeRegion(getNamedRegionTimer(Name, GroupName)) {} + +//===----------------------------------------------------------------------===// +// TimerGroup Implementation +//===----------------------------------------------------------------------===// + + +static void printVal(double Val, double Total, raw_ostream &OS) { + if (Total < 1e-7) // Avoid dividing by zero... + OS << " ----- "; + else { + OS << " " << format("%7.4f", Val) << " ("; + OS << format("%5.1f", Val*100/Total) << "%)"; + } +} + +void Timer::print(const Timer &Total, raw_ostream &OS) { + sys::SmartScopedLock L(*TimerLock); + if (Total.UserTime) + printVal(UserTime, Total.UserTime, OS); + if (Total.SystemTime) + printVal(SystemTime, Total.SystemTime, OS); + if (Total.getProcessTime()) + printVal(getProcessTime(), Total.getProcessTime(), OS); + printVal(Elapsed, Total.Elapsed, OS); + + OS << " "; + + if (Total.MemUsed) { + OS << format("%9lld", (long long)MemUsed) << " "; + } + if (Total.PeakMem) { + if (PeakMem) { + OS << format("%9lld", (long long)PeakMem) << " "; + } else + OS << " "; + } + OS << Name << "\n"; + + Started = false; // Once printed, don't print again +} + +// GetLibSupportInfoOutputFile - Return a file stream to print our output on... +raw_ostream * +llvm::GetLibSupportInfoOutputFile() { + std::string &LibSupportInfoOutputFilename = getLibSupportInfoOutputFilename(); + if (LibSupportInfoOutputFilename.empty()) + return &errs(); + if (LibSupportInfoOutputFilename == "-") + return &outs(); + + + std::string Error; + raw_ostream *Result = new raw_fd_ostream(LibSupportInfoOutputFilename.c_str(), + Error, raw_fd_ostream::F_Append); + if (Error.empty()) + return Result; + + errs() << "Error opening info-output-file '" + << LibSupportInfoOutputFilename << " for appending!\n"; + delete Result; + return &errs(); +} + + +void TimerGroup::removeTimer() { + sys::SmartScopedLock L(*TimerLock); + if (--NumTimers == 0 && !TimersToPrint.empty()) { // Print timing report... + // Sort the timers in descending order by amount of time taken... + std::sort(TimersToPrint.begin(), TimersToPrint.end(), + std::greater()); + + // Figure out how many spaces to indent TimerGroup name... + unsigned Padding = (80-Name.length())/2; + if (Padding > 80) Padding = 0; // Don't allow "negative" numbers + + raw_ostream *OutStream = GetLibSupportInfoOutputFile(); + + ++NumTimers; + { // Scope to contain Total timer... don't allow total timer to drop us to + // zero timers... + Timer Total("TOTAL"); + + for (unsigned i = 0, e = TimersToPrint.size(); i != e; ++i) + Total.sum(TimersToPrint[i]); + + // Print out timing header... + *OutStream << "===" << std::string(73, '-') << "===\n" + << std::string(Padding, ' ') << Name << "\n" + << "===" << std::string(73, '-') + << "===\n"; + + // If this is not an collection of ungrouped times, print the total time. + // Ungrouped timers don't really make sense to add up. We still print the + // TOTAL line to make the percentages make sense. + if (this != DefaultTimerGroup) { + *OutStream << " Total Execution Time: "; + + *OutStream << format("%5.4f", Total.getProcessTime()) << " seconds ("; + *OutStream << format("%5.4f", Total.getWallTime()) << " wall clock)\n"; + } + *OutStream << "\n"; + + if (Total.UserTime) + *OutStream << " ---User Time---"; + if (Total.SystemTime) + *OutStream << " --System Time--"; + if (Total.getProcessTime()) + *OutStream << " --User+System--"; + *OutStream << " ---Wall Time---"; + if (Total.getMemUsed()) + *OutStream << " ---Mem---"; + if (Total.getPeakMem()) + *OutStream << " -PeakMem-"; + *OutStream << " --- Name ---\n"; + + // Loop through all of the timing data, printing it out... + for (unsigned i = 0, e = TimersToPrint.size(); i != e; ++i) + TimersToPrint[i].print(Total, *OutStream); + + Total.print(Total, *OutStream); + *OutStream << '\n'; + OutStream->flush(); + } + --NumTimers; + + TimersToPrint.clear(); + + if (OutStream != &errs() && OutStream != &outs()) + delete OutStream; // Close the file... + } +} + +void TimerGroup::addTimer() { + sys::SmartScopedLock L(*TimerLock); + ++NumTimers; +} + +void TimerGroup::addTimerToPrint(const Timer &T) { + sys::SmartScopedLock L(*TimerLock); + TimersToPrint.push_back(Timer(true, T)); +} + diff --git a/libclamav/c++/llvm/lib/Support/Triple.cpp b/libclamav/c++/llvm/lib/Support/Triple.cpp new file mode 100644 index 000000000..2fec094d7 --- /dev/null +++ b/libclamav/c++/llvm/lib/Support/Triple.cpp @@ -0,0 +1,459 @@ +//===--- Triple.cpp - Target triple helper class --------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/Triple.h" + +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/Twine.h" +#include +#include +using namespace llvm; + +// + +const char *Triple::getArchTypeName(ArchType Kind) { + switch (Kind) { + case InvalidArch: return ""; + case UnknownArch: return "unknown"; + + case alpha: return "alpha"; + case arm: return "arm"; + case bfin: return "bfin"; + case cellspu: return "cellspu"; + case mips: return "mips"; + case mipsel: return "mipsel"; + case msp430: return "msp430"; + case pic16: return "pic16"; + case ppc64: return "powerpc64"; + case ppc: return "powerpc"; + case sparc: return "sparc"; + case systemz: return "s390x"; + case tce: return "tce"; + case thumb: return "thumb"; + case x86: return "i386"; + case x86_64: return "x86_64"; + case xcore: return "xcore"; + } + + return ""; +} + +const char *Triple::getArchTypePrefix(ArchType Kind) { + switch (Kind) { + default: + return 0; + + case alpha: return "alpha"; + + case arm: + case thumb: return "arm"; + + case bfin: return "bfin"; + + case cellspu: return "spu"; + + case ppc64: + case ppc: return "ppc"; + + case sparc: return "sparc"; + + case x86: + case x86_64: return "x86"; + case xcore: return "xcore"; + } +} + +const char *Triple::getVendorTypeName(VendorType Kind) { + switch (Kind) { + case UnknownVendor: return "unknown"; + + case Apple: return "apple"; + case PC: return "pc"; + } + + return ""; +} + +const char *Triple::getOSTypeName(OSType Kind) { + switch (Kind) { + case UnknownOS: return "unknown"; + + case AuroraUX: return "auroraux"; + case Cygwin: return "cygwin"; + case Darwin: return "darwin"; + case DragonFly: return "dragonfly"; + case FreeBSD: return "freebsd"; + case Linux: return "linux"; + case Lv2: return "lv2"; + case MinGW32: return "mingw32"; + case MinGW64: return "mingw64"; + case NetBSD: return "netbsd"; + case OpenBSD: return "openbsd"; + case Psp: return "psp"; + case Solaris: return "solaris"; + case Win32: return "win32"; + case Haiku: return "haiku"; + } + + return ""; +} + +Triple::ArchType Triple::getArchTypeForLLVMName(StringRef Name) { + if (Name == "alpha") + return alpha; + if (Name == "arm") + return arm; + if (Name == "bfin") + return bfin; + if (Name == "cellspu") + return cellspu; + if (Name == "mips") + return mips; + if (Name == "mipsel") + return mipsel; + if (Name == "msp430") + return msp430; + if (Name == "pic16") + return pic16; + if (Name == "ppc64") + return ppc64; + if (Name == "ppc") + return ppc; + if (Name == "sparc") + return sparc; + if (Name == "systemz") + return systemz; + if (Name == "tce") + return tce; + if (Name == "thumb") + return thumb; + if (Name == "x86") + return x86; + if (Name == "x86-64") + return x86_64; + if (Name == "xcore") + return xcore; + + return UnknownArch; +} + +Triple::ArchType Triple::getArchTypeForDarwinArchName(StringRef Str) { + // See arch(3) and llvm-gcc's driver-driver.c. We don't implement support for + // archs which Darwin doesn't use. + + // The matching this routine does is fairly pointless, since it is neither the + // complete architecture list, nor a reasonable subset. The problem is that + // historically the driver driver accepts this and also ties its -march= + // handling to the architecture name, so we need to be careful before removing + // support for it. + + // This code must be kept in sync with Clang's Darwin specific argument + // translation. + + if (Str == "ppc" || Str == "ppc601" || Str == "ppc603" || Str == "ppc604" || + Str == "ppc604e" || Str == "ppc750" || Str == "ppc7400" || + Str == "ppc7450" || Str == "ppc970") + return Triple::ppc; + + if (Str == "ppc64") + return Triple::ppc64; + + if (Str == "i386" || Str == "i486" || Str == "i486SX" || Str == "pentium" || + Str == "i586" || Str == "pentpro" || Str == "i686" || Str == "pentIIm3" || + Str == "pentIIm5" || Str == "pentium4") + return Triple::x86; + + if (Str == "x86_64") + return Triple::x86_64; + + // This is derived from the driver driver. + if (Str == "arm" || Str == "armv4t" || Str == "armv5" || Str == "xscale" || + Str == "armv6" || Str == "armv7") + return Triple::arm; + + return Triple::UnknownArch; +} + +// Returns architecture name that is unsderstood by the target assembler. +const char *Triple::getArchNameForAssembler() { + if (getOS() != Triple::Darwin && getVendor() != Triple::Apple) + return NULL; + + StringRef Str = getArchName(); + if (Str == "i386") + return "i386"; + if (Str == "x86_64") + return "x86_64"; + if (Str == "powerpc") + return "ppc"; + if (Str == "powerpc64") + return "ppc64"; + if (Str == "arm") + return "arm"; + if (Str == "armv4t" || Str == "thumbv4t") + return "armv4t"; + if (Str == "armv5" || Str == "armv5e" || Str == "thumbv5" || Str == "thumbv5e") + return "armv5"; + if (Str == "armv6" || Str == "thumbv6") + return "armv6"; + if (Str == "armv7" || Str == "thumbv7") + return "armv7"; + return NULL; +} + +// + +void Triple::Parse() const { + assert(!isInitialized() && "Invalid parse call."); + + StringRef ArchName = getArchName(); + StringRef VendorName = getVendorName(); + StringRef OSName = getOSName(); + + if (ArchName.size() == 4 && ArchName[0] == 'i' && + ArchName[2] == '8' && ArchName[3] == '6' && + ArchName[1] - '3' < 6) // i[3-9]86 + Arch = x86; + else if (ArchName == "amd64" || ArchName == "x86_64") + Arch = x86_64; + else if (ArchName == "bfin") + Arch = bfin; + else if (ArchName == "pic16") + Arch = pic16; + else if (ArchName == "powerpc") + Arch = ppc; + else if ((ArchName == "powerpc64") || (ArchName == "ppu")) + Arch = ppc64; + else if (ArchName == "arm" || + ArchName.startswith("armv") || + ArchName == "xscale") + Arch = arm; + else if (ArchName == "thumb" || + ArchName.startswith("thumbv")) + Arch = thumb; + else if (ArchName.startswith("alpha")) + Arch = alpha; + else if (ArchName == "spu" || ArchName == "cellspu") + Arch = cellspu; + else if (ArchName == "msp430") + Arch = msp430; + else if (ArchName == "mips" || ArchName == "mipsallegrex") + Arch = mips; + else if (ArchName == "mipsel" || ArchName == "mipsallegrexel" || + ArchName == "psp") + Arch = mipsel; + else if (ArchName == "sparc") + Arch = sparc; + else if (ArchName == "s390x") + Arch = systemz; + else if (ArchName == "tce") + Arch = tce; + else if (ArchName == "xcore") + Arch = xcore; + else + Arch = UnknownArch; + + + // Handle some exceptional cases where the OS / environment components are + // stuck into the vendor field. + if (StringRef(getTriple()).count('-') == 1) { + StringRef VendorName = getVendorName(); + + if (VendorName.startswith("mingw32")) { // 'i386-mingw32', etc. + Vendor = PC; + OS = MinGW32; + return; + } + + // arm-elf is another example, but we don't currently parse anything about + // the environment. + } + + if (VendorName == "apple") + Vendor = Apple; + else if (VendorName == "pc") + Vendor = PC; + else + Vendor = UnknownVendor; + + if (OSName.startswith("auroraux")) + OS = AuroraUX; + else if (OSName.startswith("cygwin")) + OS = Cygwin; + else if (OSName.startswith("darwin")) + OS = Darwin; + else if (OSName.startswith("dragonfly")) + OS = DragonFly; + else if (OSName.startswith("freebsd")) + OS = FreeBSD; + else if (OSName.startswith("linux")) + OS = Linux; + else if (OSName.startswith("lv2")) + OS = Lv2; + else if (OSName.startswith("mingw32")) + OS = MinGW32; + else if (OSName.startswith("mingw64")) + OS = MinGW64; + else if (OSName.startswith("netbsd")) + OS = NetBSD; + else if (OSName.startswith("openbsd")) + OS = OpenBSD; + else if (OSName.startswith("psp")) + OS = Psp; + else if (OSName.startswith("solaris")) + OS = Solaris; + else if (OSName.startswith("win32")) + OS = Win32; + else if (OSName.startswith("haiku")) + OS = Haiku; + else + OS = UnknownOS; + + assert(isInitialized() && "Failed to initialize!"); +} + +StringRef Triple::getArchName() const { + return StringRef(Data).split('-').first; // Isolate first component +} + +StringRef Triple::getVendorName() const { + StringRef Tmp = StringRef(Data).split('-').second; // Strip first component + return Tmp.split('-').first; // Isolate second component +} + +StringRef Triple::getOSName() const { + StringRef Tmp = StringRef(Data).split('-').second; // Strip first component + Tmp = Tmp.split('-').second; // Strip second component + return Tmp.split('-').first; // Isolate third component +} + +StringRef Triple::getEnvironmentName() const { + StringRef Tmp = StringRef(Data).split('-').second; // Strip first component + Tmp = Tmp.split('-').second; // Strip second component + return Tmp.split('-').second; // Strip third component +} + +StringRef Triple::getOSAndEnvironmentName() const { + StringRef Tmp = StringRef(Data).split('-').second; // Strip first component + return Tmp.split('-').second; // Strip second component +} + +static unsigned EatNumber(StringRef &Str) { + assert(!Str.empty() && Str[0] >= '0' && Str[0] <= '9' && "Not a number"); + unsigned Result = Str[0]-'0'; + + // Eat the digit. + Str = Str.substr(1); + + // Handle "darwin11". + if (Result == 1 && !Str.empty() && Str[0] >= '0' && Str[0] <= '9') { + Result = Result*10 + (Str[0] - '0'); + // Eat the digit. + Str = Str.substr(1); + } + + return Result; +} + +/// getDarwinNumber - Parse the 'darwin number' out of the specific target +/// triple. For example, if we have darwin8.5 return 8,5,0. If any entry is +/// not defined, return 0's. This requires that the triple have an OSType of +/// darwin before it is called. +void Triple::getDarwinNumber(unsigned &Maj, unsigned &Min, + unsigned &Revision) const { + assert(getOS() == Darwin && "Not a darwin target triple!"); + StringRef OSName = getOSName(); + assert(OSName.startswith("darwin") && "Unknown darwin target triple!"); + + // Strip off "darwin". + OSName = OSName.substr(6); + + Maj = Min = Revision = 0; + + if (OSName.empty() || OSName[0] < '0' || OSName[0] > '9') + return; + + // The major version is the first digit. + Maj = EatNumber(OSName); + if (OSName.empty()) return; + + // Handle minor version: 10.4.9 -> darwin8.9. + if (OSName[0] != '.') + return; + + // Eat the '.'. + OSName = OSName.substr(1); + + if (OSName.empty() || OSName[0] < '0' || OSName[0] > '9') + return; + + Min = EatNumber(OSName); + if (OSName.empty()) return; + + // Handle revision darwin8.9.1 + if (OSName[0] != '.') + return; + + // Eat the '.'. + OSName = OSName.substr(1); + + if (OSName.empty() || OSName[0] < '0' || OSName[0] > '9') + return; + + Revision = EatNumber(OSName); +} + +void Triple::setTriple(const Twine &Str) { + Data = Str.str(); + Arch = InvalidArch; +} + +void Triple::setArch(ArchType Kind) { + setArchName(getArchTypeName(Kind)); +} + +void Triple::setVendor(VendorType Kind) { + setVendorName(getVendorTypeName(Kind)); +} + +void Triple::setOS(OSType Kind) { + setOSName(getOSTypeName(Kind)); +} + +void Triple::setArchName(StringRef Str) { + // Work around a miscompilation bug for Twines in gcc 4.0.3. + SmallString<64> Triple; + Triple += Str; + Triple += "-"; + Triple += getVendorName(); + Triple += "-"; + Triple += getOSAndEnvironmentName(); + setTriple(Triple.str()); +} + +void Triple::setVendorName(StringRef Str) { + setTriple(getArchName() + "-" + Str + "-" + getOSAndEnvironmentName()); +} + +void Triple::setOSName(StringRef Str) { + if (hasEnvironment()) + setTriple(getArchName() + "-" + getVendorName() + "-" + Str + + "-" + getEnvironmentName()); + else + setTriple(getArchName() + "-" + getVendorName() + "-" + Str); +} + +void Triple::setEnvironmentName(StringRef Str) { + setTriple(getArchName() + "-" + getVendorName() + "-" + getOSName() + + "-" + Str); +} + +void Triple::setOSAndEnvironmentName(StringRef Str) { + setTriple(getArchName() + "-" + getVendorName() + "-" + Str); +} diff --git a/libclamav/c++/llvm/lib/Support/Twine.cpp b/libclamav/c++/llvm/lib/Support/Twine.cpp new file mode 100644 index 000000000..292c0c2b9 --- /dev/null +++ b/libclamav/c++/llvm/lib/Support/Twine.cpp @@ -0,0 +1,133 @@ +//===-- Twine.cpp - Fast Temporary String Concatenation -------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/Twine.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +std::string Twine::str() const { + SmallString<256> Vec; + toVector(Vec); + return std::string(Vec.begin(), Vec.end()); +} + +void Twine::toVector(SmallVectorImpl &Out) const { + raw_svector_ostream OS(Out); + print(OS); +} + +void Twine::printOneChild(raw_ostream &OS, const void *Ptr, + NodeKind Kind) const { + switch (Kind) { + case Twine::NullKind: break; + case Twine::EmptyKind: break; + case Twine::TwineKind: + static_cast(Ptr)->print(OS); + break; + case Twine::CStringKind: + OS << static_cast(Ptr); + break; + case Twine::StdStringKind: + OS << *static_cast(Ptr); + break; + case Twine::StringRefKind: + OS << *static_cast(Ptr); + break; + case Twine::DecUIKind: + OS << *static_cast(Ptr); + break; + case Twine::DecIKind: + OS << *static_cast(Ptr); + break; + case Twine::DecULKind: + OS << *static_cast(Ptr); + break; + case Twine::DecLKind: + OS << *static_cast(Ptr); + break; + case Twine::DecULLKind: + OS << *static_cast(Ptr); + break; + case Twine::DecLLKind: + OS << *static_cast(Ptr); + break; + case Twine::UHexKind: + OS.write_hex(*static_cast(Ptr)); + break; + } +} + +void Twine::printOneChildRepr(raw_ostream &OS, const void *Ptr, + NodeKind Kind) const { + switch (Kind) { + case Twine::NullKind: + OS << "null"; break; + case Twine::EmptyKind: + OS << "empty"; break; + case Twine::TwineKind: + OS << "rope:"; + static_cast(Ptr)->printRepr(OS); + break; + case Twine::CStringKind: + OS << "cstring:\"" + << static_cast(Ptr) << "\""; + break; + case Twine::StdStringKind: + OS << "std::string:\"" + << static_cast(Ptr) << "\""; + break; + case Twine::StringRefKind: + OS << "stringref:\"" + << static_cast(Ptr) << "\""; + break; + case Twine::DecUIKind: + OS << "decUI:\"" << *static_cast(Ptr) << "\""; + break; + case Twine::DecIKind: + OS << "decI:\"" << *static_cast(Ptr) << "\""; + break; + case Twine::DecULKind: + OS << "decUL:\"" << *static_cast(Ptr) << "\""; + break; + case Twine::DecLKind: + OS << "decL:\"" << *static_cast(Ptr) << "\""; + break; + case Twine::DecULLKind: + OS << "decULL:\"" << *static_cast(Ptr) << "\""; + break; + case Twine::DecLLKind: + OS << "decLL:\"" << *static_cast(Ptr) << "\""; + break; + case Twine::UHexKind: + OS << "uhex:\"" << static_cast(Ptr) << "\""; + break; + } +} + +void Twine::print(raw_ostream &OS) const { + printOneChild(OS, LHS, getLHSKind()); + printOneChild(OS, RHS, getRHSKind()); +} + +void Twine::printRepr(raw_ostream &OS) const { + OS << "(Twine "; + printOneChildRepr(OS, LHS, getLHSKind()); + OS << " "; + printOneChildRepr(OS, RHS, getRHSKind()); + OS << ")"; +} + +void Twine::dump() const { + print(llvm::errs()); +} + +void Twine::dumpRepr() const { + printRepr(llvm::errs()); +} diff --git a/libclamav/c++/llvm/lib/Support/raw_os_ostream.cpp b/libclamav/c++/llvm/lib/Support/raw_os_ostream.cpp new file mode 100644 index 000000000..3374dd7a6 --- /dev/null +++ b/libclamav/c++/llvm/lib/Support/raw_os_ostream.cpp @@ -0,0 +1,30 @@ +//===--- raw_os_ostream.cpp - Implement the raw_os_ostream class ----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This implements support adapting raw_ostream to std::ostream. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/raw_os_ostream.h" +#include +using namespace llvm; + +//===----------------------------------------------------------------------===// +// raw_os_ostream +//===----------------------------------------------------------------------===// + +raw_os_ostream::~raw_os_ostream() { + flush(); +} + +void raw_os_ostream::write_impl(const char *Ptr, size_t Size) { + OS.write(Ptr, Size); +} + +uint64_t raw_os_ostream::current_pos() { return OS.tellp(); } diff --git a/libclamav/c++/llvm/lib/Support/raw_ostream.cpp b/libclamav/c++/llvm/lib/Support/raw_ostream.cpp new file mode 100644 index 000000000..31451ccfd --- /dev/null +++ b/libclamav/c++/llvm/lib/Support/raw_ostream.cpp @@ -0,0 +1,607 @@ +//===--- raw_ostream.cpp - Implement the raw_ostream classes --------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This implements support for bulk buffered stream output. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/Format.h" +#include "llvm/System/Program.h" +#include "llvm/System/Process.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/Config/config.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/StringExtras.h" +#include +#include + +#if defined(HAVE_UNISTD_H) +# include +#endif +#if defined(HAVE_FCNTL_H) +# include +#endif + +#if defined(_MSC_VER) +#include +#include +#ifndef STDIN_FILENO +# define STDIN_FILENO 0 +#endif +#ifndef STDOUT_FILENO +# define STDOUT_FILENO 1 +#endif +#ifndef STDERR_FILENO +# define STDERR_FILENO 2 +#endif +#endif + +using namespace llvm; + +raw_ostream::~raw_ostream() { + // raw_ostream's subclasses should take care to flush the buffer + // in their destructors. + assert(OutBufCur == OutBufStart && + "raw_ostream destructor called with non-empty buffer!"); + + if (BufferMode == InternalBuffer) + delete [] OutBufStart; + + // If there are any pending errors, report them now. Clients wishing + // to avoid llvm_report_error calls should check for errors with + // has_error() and clear the error flag with clear_error() before + // destructing raw_ostream objects which may have errors. + if (Error) + llvm_report_error("IO failure on output stream."); +} + +// An out of line virtual method to provide a home for the class vtable. +void raw_ostream::handle() {} + +size_t raw_ostream::preferred_buffer_size() { + // BUFSIZ is intended to be a reasonable default. + return BUFSIZ; +} + +void raw_ostream::SetBuffered() { + // Ask the subclass to determine an appropriate buffer size. + if (size_t Size = preferred_buffer_size()) + SetBufferSize(Size); + else + // It may return 0, meaning this stream should be unbuffered. + SetUnbuffered(); +} + +void raw_ostream::SetBufferAndMode(char *BufferStart, size_t Size, + BufferKind Mode) { + assert(((Mode == Unbuffered && BufferStart == 0 && Size == 0) || + (Mode != Unbuffered && BufferStart && Size)) && + "stream must be unbuffered or have at least one byte"); + // Make sure the current buffer is free of content (we can't flush here; the + // child buffer management logic will be in write_impl). + assert(GetNumBytesInBuffer() == 0 && "Current buffer is non-empty!"); + + if (BufferMode == InternalBuffer) + delete [] OutBufStart; + OutBufStart = BufferStart; + OutBufEnd = OutBufStart+Size; + OutBufCur = OutBufStart; + BufferMode = Mode; + + assert(OutBufStart <= OutBufEnd && "Invalid size!"); +} + +raw_ostream &raw_ostream::operator<<(unsigned long N) { + // Zero is a special case. + if (N == 0) + return *this << '0'; + + char NumberBuffer[20]; + char *EndPtr = NumberBuffer+sizeof(NumberBuffer); + char *CurPtr = EndPtr; + + while (N) { + *--CurPtr = '0' + char(N % 10); + N /= 10; + } + return write(CurPtr, EndPtr-CurPtr); +} + +raw_ostream &raw_ostream::operator<<(long N) { + if (N < 0) { + *this << '-'; + N = -N; + } + + return this->operator<<(static_cast(N)); +} + +raw_ostream &raw_ostream::operator<<(unsigned long long N) { + // Output using 32-bit div/mod when possible. + if (N == static_cast(N)) + return this->operator<<(static_cast(N)); + + char NumberBuffer[20]; + char *EndPtr = NumberBuffer+sizeof(NumberBuffer); + char *CurPtr = EndPtr; + + while (N) { + *--CurPtr = '0' + char(N % 10); + N /= 10; + } + return write(CurPtr, EndPtr-CurPtr); +} + +raw_ostream &raw_ostream::operator<<(long long N) { + if (N < 0) { + *this << '-'; + N = -N; + } + + return this->operator<<(static_cast(N)); +} + +raw_ostream &raw_ostream::write_hex(unsigned long long N) { + // Zero is a special case. + if (N == 0) + return *this << '0'; + + char NumberBuffer[20]; + char *EndPtr = NumberBuffer+sizeof(NumberBuffer); + char *CurPtr = EndPtr; + + while (N) { + uintptr_t x = N % 16; + *--CurPtr = (x < 10 ? '0' + x : 'a' + x - 10); + N /= 16; + } + + return write(CurPtr, EndPtr-CurPtr); +} + +raw_ostream &raw_ostream::write_escaped(StringRef Str) { + for (unsigned i = 0, e = Str.size(); i != e; ++i) { + unsigned char c = Str[i]; + + switch (c) { + case '\\': + *this << '\\' << '\\'; + break; + case '\t': + *this << '\\' << 't'; + break; + case '\n': + *this << '\\' << 'n'; + break; + case '"': + *this << '\\' << '"'; + break; + default: + if (std::isprint(c)) { + *this << c; + break; + } + + // Always expand to a 3-character octal escape. + *this << '\\'; + *this << char('0' + ((c >> 6) & 7)); + *this << char('0' + ((c >> 3) & 7)); + *this << char('0' + ((c >> 0) & 7)); + } + } + + return *this; +} + +raw_ostream &raw_ostream::operator<<(const void *P) { + *this << '0' << 'x'; + + return write_hex((uintptr_t) P); +} + +raw_ostream &raw_ostream::operator<<(double N) { + this->operator<<(ftostr(N)); + return *this; +} + + + +void raw_ostream::flush_nonempty() { + assert(OutBufCur > OutBufStart && "Invalid call to flush_nonempty."); + size_t Length = OutBufCur - OutBufStart; + OutBufCur = OutBufStart; + write_impl(OutBufStart, Length); +} + +raw_ostream &raw_ostream::write(unsigned char C) { + // Group exceptional cases into a single branch. + if (BUILTIN_EXPECT(OutBufCur >= OutBufEnd, false)) { + if (BUILTIN_EXPECT(!OutBufStart, false)) { + if (BufferMode == Unbuffered) { + write_impl(reinterpret_cast(&C), 1); + return *this; + } + // Set up a buffer and start over. + SetBuffered(); + return write(C); + } + + flush_nonempty(); + } + + *OutBufCur++ = C; + return *this; +} + +raw_ostream &raw_ostream::write(const char *Ptr, size_t Size) { + // Group exceptional cases into a single branch. + if (BUILTIN_EXPECT(OutBufCur+Size > OutBufEnd, false)) { + if (BUILTIN_EXPECT(!OutBufStart, false)) { + if (BufferMode == Unbuffered) { + write_impl(Ptr, Size); + return *this; + } + // Set up a buffer and start over. + SetBuffered(); + return write(Ptr, Size); + } + + // Write out the data in buffer-sized blocks until the remainder + // fits within the buffer. + do { + size_t NumBytes = OutBufEnd - OutBufCur; + copy_to_buffer(Ptr, NumBytes); + flush_nonempty(); + Ptr += NumBytes; + Size -= NumBytes; + } while (OutBufCur+Size > OutBufEnd); + } + + copy_to_buffer(Ptr, Size); + + return *this; +} + +void raw_ostream::copy_to_buffer(const char *Ptr, size_t Size) { + assert(Size <= size_t(OutBufEnd - OutBufCur) && "Buffer overrun!"); + + // Handle short strings specially, memcpy isn't very good at very short + // strings. + switch (Size) { + case 4: OutBufCur[3] = Ptr[3]; // FALL THROUGH + case 3: OutBufCur[2] = Ptr[2]; // FALL THROUGH + case 2: OutBufCur[1] = Ptr[1]; // FALL THROUGH + case 1: OutBufCur[0] = Ptr[0]; // FALL THROUGH + case 0: break; + default: + memcpy(OutBufCur, Ptr, Size); + break; + } + + OutBufCur += Size; +} + +// Formatted output. +raw_ostream &raw_ostream::operator<<(const format_object_base &Fmt) { + // If we have more than a few bytes left in our output buffer, try + // formatting directly onto its end. + size_t NextBufferSize = 127; + size_t BufferBytesLeft = OutBufEnd - OutBufCur; + if (BufferBytesLeft > 3) { + size_t BytesUsed = Fmt.print(OutBufCur, BufferBytesLeft); + + // Common case is that we have plenty of space. + if (BytesUsed <= BufferBytesLeft) { + OutBufCur += BytesUsed; + return *this; + } + + // Otherwise, we overflowed and the return value tells us the size to try + // again with. + NextBufferSize = BytesUsed; + } + + // If we got here, we didn't have enough space in the output buffer for the + // string. Try printing into a SmallVector that is resized to have enough + // space. Iterate until we win. + SmallVector V; + + while (1) { + V.resize(NextBufferSize); + + // Try formatting into the SmallVector. + size_t BytesUsed = Fmt.print(V.data(), NextBufferSize); + + // If BytesUsed fit into the vector, we win. + if (BytesUsed <= NextBufferSize) + return write(V.data(), BytesUsed); + + // Otherwise, try again with a new size. + assert(BytesUsed > NextBufferSize && "Didn't grow buffer!?"); + NextBufferSize = BytesUsed; + } +} + +/// indent - Insert 'NumSpaces' spaces. +raw_ostream &raw_ostream::indent(unsigned NumSpaces) { + static const char Spaces[] = " " + " " + " "; + + // Usually the indentation is small, handle it with a fastpath. + if (NumSpaces < array_lengthof(Spaces)) + return write(Spaces, NumSpaces); + + while (NumSpaces) { + unsigned NumToWrite = std::min(NumSpaces, + (unsigned)array_lengthof(Spaces)-1); + write(Spaces, NumToWrite); + NumSpaces -= NumToWrite; + } + return *this; +} + + +//===----------------------------------------------------------------------===// +// Formatted Output +//===----------------------------------------------------------------------===// + +// Out of line virtual method. +void format_object_base::home() { +} + +//===----------------------------------------------------------------------===// +// raw_fd_ostream +//===----------------------------------------------------------------------===// + +/// raw_fd_ostream - Open the specified file for writing. If an error +/// occurs, information about the error is put into ErrorInfo, and the +/// stream should be immediately destroyed; the string will be empty +/// if no error occurred. +raw_fd_ostream::raw_fd_ostream(const char *Filename, std::string &ErrorInfo, + unsigned Flags) : pos(0) { + // Verify that we don't have both "append" and "excl". + assert((!(Flags & F_Excl) || !(Flags & F_Append)) && + "Cannot specify both 'excl' and 'append' file creation flags!"); + + ErrorInfo.clear(); + + // Handle "-" as stdout. + if (Filename[0] == '-' && Filename[1] == 0) { + FD = STDOUT_FILENO; + // If user requested binary then put stdout into binary mode if + // possible. + if (Flags & F_Binary) + sys::Program::ChangeStdoutToBinary(); + ShouldClose = false; + return; + } + + int OpenFlags = O_WRONLY|O_CREAT; +#ifdef O_BINARY + if (Flags & F_Binary) + OpenFlags |= O_BINARY; +#endif + + if (Flags & F_Append) + OpenFlags |= O_APPEND; + else + OpenFlags |= O_TRUNC; + if (Flags & F_Excl) + OpenFlags |= O_EXCL; + + FD = open(Filename, OpenFlags, 0664); + if (FD < 0) { + ErrorInfo = "Error opening output file '" + std::string(Filename) + "'"; + ShouldClose = false; + } else { + ShouldClose = true; + } +} + +raw_fd_ostream::~raw_fd_ostream() { + if (FD < 0) return; + flush(); + if (ShouldClose) + if (::close(FD) != 0) + error_detected(); +} + + +void raw_fd_ostream::write_impl(const char *Ptr, size_t Size) { + assert (FD >= 0 && "File already closed."); + pos += Size; + if (::write(FD, Ptr, Size) != (ssize_t) Size) + error_detected(); +} + +void raw_fd_ostream::close() { + assert (ShouldClose); + ShouldClose = false; + flush(); + if (::close(FD) != 0) + error_detected(); + FD = -1; +} + +uint64_t raw_fd_ostream::seek(uint64_t off) { + flush(); + pos = ::lseek(FD, off, SEEK_SET); + if (pos != off) + error_detected(); + return pos; +} + +size_t raw_fd_ostream::preferred_buffer_size() { +#if !defined(_MSC_VER) && !defined(__MINGW32__) // Windows has no st_blksize. + assert(FD >= 0 && "File not yet open!"); + struct stat statbuf; + if (fstat(FD, &statbuf) == 0) { + // If this is a terminal, don't use buffering. Line buffering + // would be a more traditional thing to do, but it's not worth + // the complexity. + if (S_ISCHR(statbuf.st_mode) && isatty(FD)) + return 0; + // Return the preferred block size. + return statbuf.st_blksize; + } + error_detected(); +#endif + return raw_ostream::preferred_buffer_size(); +} + +raw_ostream &raw_fd_ostream::changeColor(enum Colors colors, bool bold, + bool bg) { + if (sys::Process::ColorNeedsFlush()) + flush(); + const char *colorcode = + (colors == SAVEDCOLOR) ? sys::Process::OutputBold(bg) + : sys::Process::OutputColor(colors, bold, bg); + if (colorcode) { + size_t len = strlen(colorcode); + write(colorcode, len); + // don't account colors towards output characters + pos -= len; + } + return *this; +} + +raw_ostream &raw_fd_ostream::resetColor() { + if (sys::Process::ColorNeedsFlush()) + flush(); + const char *colorcode = sys::Process::ResetColor(); + if (colorcode) { + size_t len = strlen(colorcode); + write(colorcode, len); + // don't account colors towards output characters + pos -= len; + } + return *this; +} + +bool raw_fd_ostream::is_displayed() const { + return sys::Process::FileDescriptorIsDisplayed(FD); +} + +//===----------------------------------------------------------------------===// +// raw_stdout/err_ostream +//===----------------------------------------------------------------------===// + +// Set buffer settings to model stdout and stderr behavior. +// Set standard error to be unbuffered by default. +raw_stdout_ostream::raw_stdout_ostream():raw_fd_ostream(STDOUT_FILENO, false) {} +raw_stderr_ostream::raw_stderr_ostream():raw_fd_ostream(STDERR_FILENO, false, + true) {} + +// An out of line virtual method to provide a home for the class vtable. +void raw_stdout_ostream::handle() {} +void raw_stderr_ostream::handle() {} + +/// outs() - This returns a reference to a raw_ostream for standard output. +/// Use it like: outs() << "foo" << "bar"; +raw_ostream &llvm::outs() { + static raw_stdout_ostream S; + return S; +} + +/// errs() - This returns a reference to a raw_ostream for standard error. +/// Use it like: errs() << "foo" << "bar"; +raw_ostream &llvm::errs() { + static raw_stderr_ostream S; + return S; +} + +/// nulls() - This returns a reference to a raw_ostream which discards output. +raw_ostream &llvm::nulls() { + static raw_null_ostream S; + return S; +} + + +//===----------------------------------------------------------------------===// +// raw_string_ostream +//===----------------------------------------------------------------------===// + +raw_string_ostream::~raw_string_ostream() { + flush(); +} + +void raw_string_ostream::write_impl(const char *Ptr, size_t Size) { + OS.append(Ptr, Size); +} + +//===----------------------------------------------------------------------===// +// raw_svector_ostream +//===----------------------------------------------------------------------===// + +// The raw_svector_ostream implementation uses the SmallVector itself as the +// buffer for the raw_ostream. We guarantee that the raw_ostream buffer is +// always pointing past the end of the vector, but within the vector +// capacity. This allows raw_ostream to write directly into the correct place, +// and we only need to set the vector size when the data is flushed. + +raw_svector_ostream::raw_svector_ostream(SmallVectorImpl &O) : OS(O) { + // Set up the initial external buffer. We make sure that the buffer has at + // least 128 bytes free; raw_ostream itself only requires 64, but we want to + // make sure that we don't grow the buffer unnecessarily on destruction (when + // the data is flushed). See the FIXME below. + OS.reserve(OS.size() + 128); + SetBuffer(OS.end(), OS.capacity() - OS.size()); +} + +raw_svector_ostream::~raw_svector_ostream() { + // FIXME: Prevent resizing during this flush(). + flush(); +} + +void raw_svector_ostream::write_impl(const char *Ptr, size_t Size) { + assert(Ptr == OS.end() && OS.size() + Size <= OS.capacity() && + "Invalid write_impl() call!"); + + // We don't need to copy the bytes, just commit the bytes to the + // SmallVector. + OS.set_size(OS.size() + Size); + + // Grow the vector if necessary. + if (OS.capacity() - OS.size() < 64) + OS.reserve(OS.capacity() * 2); + + // Update the buffer position. + SetBuffer(OS.end(), OS.capacity() - OS.size()); +} + +uint64_t raw_svector_ostream::current_pos() { return OS.size(); } + +StringRef raw_svector_ostream::str() { + flush(); + return StringRef(OS.begin(), OS.size()); +} + +//===----------------------------------------------------------------------===// +// raw_null_ostream +//===----------------------------------------------------------------------===// + +raw_null_ostream::~raw_null_ostream() { +#ifndef NDEBUG + // ~raw_ostream asserts that the buffer is empty. This isn't necessary + // with raw_null_ostream, but it's better to have raw_null_ostream follow + // the rules than to change the rules just for raw_null_ostream. + flush(); +#endif +} + +void raw_null_ostream::write_impl(const char *Ptr, size_t Size) { +} + +uint64_t raw_null_ostream::current_pos() { + return 0; +} diff --git a/libclamav/c++/llvm/lib/Support/regcclass.h b/libclamav/c++/llvm/lib/Support/regcclass.h new file mode 100644 index 000000000..2cea3e4e5 --- /dev/null +++ b/libclamav/c++/llvm/lib/Support/regcclass.h @@ -0,0 +1,70 @@ +/*- + * This code is derived from OpenBSD's libc/regex, original license follows: + * + * This code is derived from OpenBSD's libc/regex, original license follows: + * + * Copyright (c) 1992, 1993, 1994 Henry Spencer. + * Copyright (c) 1992, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Henry Spencer. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)cclass.h 8.3 (Berkeley) 3/20/94 + */ + +/* character-class table */ +static struct cclass { + const char *name; + const char *chars; + const char *multis; +} cclasses[] = { + { "alnum", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\ +0123456789", ""} , + { "alpha", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", + ""} , + { "blank", " \t", ""} , + { "cntrl", "\007\b\t\n\v\f\r\1\2\3\4\5\6\16\17\20\21\22\23\24\ +\25\26\27\30\31\32\33\34\35\36\37\177", ""} , + { "digit", "0123456789", ""} , + { "graph", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\ +0123456789!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~", + ""} , + { "lower", "abcdefghijklmnopqrstuvwxyz", + ""} , + { "print", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\ +0123456789!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~ ", + ""} , + { "punct", "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~", + ""} , + { "space", "\t\n\v\f\r ", ""} , + { "upper", "ABCDEFGHIJKLMNOPQRSTUVWXYZ", + ""} , + { "xdigit", "0123456789ABCDEFabcdef", + ""} , + { NULL, 0, "" } +}; diff --git a/libclamav/c++/llvm/lib/Support/regcname.h b/libclamav/c++/llvm/lib/Support/regcname.h new file mode 100644 index 000000000..3c0bb248f --- /dev/null +++ b/libclamav/c++/llvm/lib/Support/regcname.h @@ -0,0 +1,139 @@ +/*- + * This code is derived from OpenBSD's libc/regex, original license follows: + * + * Copyright (c) 1992, 1993, 1994 Henry Spencer. + * Copyright (c) 1992, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Henry Spencer. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)cname.h 8.3 (Berkeley) 3/20/94 + */ + +/* character-name table */ +static struct cname { + const char *name; + char code; +} cnames[] = { + { "NUL", '\0' }, + { "SOH", '\001' }, + { "STX", '\002' }, + { "ETX", '\003' }, + { "EOT", '\004' }, + { "ENQ", '\005' }, + { "ACK", '\006' }, + { "BEL", '\007' }, + { "alert", '\007' }, + { "BS", '\010' }, + { "backspace", '\b' }, + { "HT", '\011' }, + { "tab", '\t' }, + { "LF", '\012' }, + { "newline", '\n' }, + { "VT", '\013' }, + { "vertical-tab", '\v' }, + { "FF", '\014' }, + { "form-feed", '\f' }, + { "CR", '\015' }, + { "carriage-return", '\r' }, + { "SO", '\016' }, + { "SI", '\017' }, + { "DLE", '\020' }, + { "DC1", '\021' }, + { "DC2", '\022' }, + { "DC3", '\023' }, + { "DC4", '\024' }, + { "NAK", '\025' }, + { "SYN", '\026' }, + { "ETB", '\027' }, + { "CAN", '\030' }, + { "EM", '\031' }, + { "SUB", '\032' }, + { "ESC", '\033' }, + { "IS4", '\034' }, + { "FS", '\034' }, + { "IS3", '\035' }, + { "GS", '\035' }, + { "IS2", '\036' }, + { "RS", '\036' }, + { "IS1", '\037' }, + { "US", '\037' }, + { "space", ' ' }, + { "exclamation-mark", '!' }, + { "quotation-mark", '"' }, + { "number-sign", '#' }, + { "dollar-sign", '$' }, + { "percent-sign", '%' }, + { "ampersand", '&' }, + { "apostrophe", '\'' }, + { "left-parenthesis", '(' }, + { "right-parenthesis", ')' }, + { "asterisk", '*' }, + { "plus-sign", '+' }, + { "comma", ',' }, + { "hyphen", '-' }, + { "hyphen-minus", '-' }, + { "period", '.' }, + { "full-stop", '.' }, + { "slash", '/' }, + { "solidus", '/' }, + { "zero", '0' }, + { "one", '1' }, + { "two", '2' }, + { "three", '3' }, + { "four", '4' }, + { "five", '5' }, + { "six", '6' }, + { "seven", '7' }, + { "eight", '8' }, + { "nine", '9' }, + { "colon", ':' }, + { "semicolon", ';' }, + { "less-than-sign", '<' }, + { "equals-sign", '=' }, + { "greater-than-sign", '>' }, + { "question-mark", '?' }, + { "commercial-at", '@' }, + { "left-square-bracket", '[' }, + { "backslash", '\\' }, + { "reverse-solidus", '\\' }, + { "right-square-bracket", ']' }, + { "circumflex", '^' }, + { "circumflex-accent", '^' }, + { "underscore", '_' }, + { "low-line", '_' }, + { "grave-accent", '`' }, + { "left-brace", '{' }, + { "left-curly-bracket", '{' }, + { "vertical-line", '|' }, + { "right-brace", '}' }, + { "right-curly-bracket", '}' }, + { "tilde", '~' }, + { "DEL", '\177' }, + { NULL, 0 } +}; diff --git a/libclamav/c++/llvm/lib/Support/regcomp.c b/libclamav/c++/llvm/lib/Support/regcomp.c new file mode 100644 index 000000000..cd018d5dc --- /dev/null +++ b/libclamav/c++/llvm/lib/Support/regcomp.c @@ -0,0 +1,1525 @@ +/*- + * This code is derived from OpenBSD's libc/regex, original license follows: + * + * Copyright (c) 1992, 1993, 1994 Henry Spencer. + * Copyright (c) 1992, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Henry Spencer. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)regcomp.c 8.5 (Berkeley) 3/20/94 + */ + +#include +#include +#include +#include +#include +#include +#include "regex_impl.h" + +#include "regutils.h" +#include "regex2.h" + +#include "regcclass.h" +#include "regcname.h" + +/* + * parse structure, passed up and down to avoid global variables and + * other clumsinesses + */ +struct parse { + char *next; /* next character in RE */ + char *end; /* end of string (-> NUL normally) */ + int error; /* has an error been seen? */ + sop *strip; /* malloced strip */ + sopno ssize; /* malloced strip size (allocated) */ + sopno slen; /* malloced strip length (used) */ + int ncsalloc; /* number of csets allocated */ + struct re_guts *g; +# define NPAREN 10 /* we need to remember () 1-9 for back refs */ + sopno pbegin[NPAREN]; /* -> ( ([0] unused) */ + sopno pend[NPAREN]; /* -> ) ([0] unused) */ +}; + +static void p_ere(struct parse *, int); +static void p_ere_exp(struct parse *); +static void p_str(struct parse *); +static void p_bre(struct parse *, int, int); +static int p_simp_re(struct parse *, int); +static int p_count(struct parse *); +static void p_bracket(struct parse *); +static void p_b_term(struct parse *, cset *); +static void p_b_cclass(struct parse *, cset *); +static void p_b_eclass(struct parse *, cset *); +static char p_b_symbol(struct parse *); +static char p_b_coll_elem(struct parse *, int); +static char othercase(int); +static void bothcases(struct parse *, int); +static void ordinary(struct parse *, int); +static void nonnewline(struct parse *); +static void repeat(struct parse *, sopno, int, int); +static int seterr(struct parse *, int); +static cset *allocset(struct parse *); +static void freeset(struct parse *, cset *); +static int freezeset(struct parse *, cset *); +static int firstch(struct parse *, cset *); +static int nch(struct parse *, cset *); +static void mcadd(struct parse *, cset *, const char *); +static void mcinvert(struct parse *, cset *); +static void mccase(struct parse *, cset *); +static int isinsets(struct re_guts *, int); +static int samesets(struct re_guts *, int, int); +static void categorize(struct parse *, struct re_guts *); +static sopno dupl(struct parse *, sopno, sopno); +static void doemit(struct parse *, sop, size_t); +static void doinsert(struct parse *, sop, size_t, sopno); +static void dofwd(struct parse *, sopno, sop); +static void enlarge(struct parse *, sopno); +static void stripsnug(struct parse *, struct re_guts *); +static void findmust(struct parse *, struct re_guts *); +static sopno pluscount(struct parse *, struct re_guts *); + +static char nuls[10]; /* place to point scanner in event of error */ + +/* + * macros for use with parse structure + * BEWARE: these know that the parse structure is named `p' !!! + */ +#define PEEK() (*p->next) +#define PEEK2() (*(p->next+1)) +#define MORE() (p->next < p->end) +#define MORE2() (p->next+1 < p->end) +#define SEE(c) (MORE() && PEEK() == (c)) +#define SEETWO(a, b) (MORE() && MORE2() && PEEK() == (a) && PEEK2() == (b)) +#define EAT(c) ((SEE(c)) ? (NEXT(), 1) : 0) +#define EATTWO(a, b) ((SEETWO(a, b)) ? (NEXT2(), 1) : 0) +#define NEXT() (p->next++) +#define NEXT2() (p->next += 2) +#define NEXTn(n) (p->next += (n)) +#define GETNEXT() (*p->next++) +#define SETERROR(e) seterr(p, (e)) +#define REQUIRE(co, e) (void)((co) || SETERROR(e)) +#define MUSTSEE(c, e) (REQUIRE(MORE() && PEEK() == (c), e)) +#define MUSTEAT(c, e) (REQUIRE(MORE() && GETNEXT() == (c), e)) +#define MUSTNOTSEE(c, e) (REQUIRE(!MORE() || PEEK() != (c), e)) +#define EMIT(op, sopnd) doemit(p, (sop)(op), (size_t)(sopnd)) +#define INSERT(op, pos) doinsert(p, (sop)(op), HERE()-(pos)+1, pos) +#define AHEAD(pos) dofwd(p, pos, HERE()-(pos)) +#define ASTERN(sop, pos) EMIT(sop, HERE()-pos) +#define HERE() (p->slen) +#define THERE() (p->slen - 1) +#define THERETHERE() (p->slen - 2) +#define DROP(n) (p->slen -= (n)) + +#ifdef _POSIX2_RE_DUP_MAX +#define DUPMAX _POSIX2_RE_DUP_MAX +#else +#define DUPMAX 255 +#endif +#define INFINITY (DUPMAX + 1) + +#ifndef NDEBUG +static int never = 0; /* for use in asserts; shuts lint up */ +#else +#define never 0 /* some s have bugs too */ +#endif + +/* + - llvm_regcomp - interface for parser and compilation + */ +int /* 0 success, otherwise REG_something */ +llvm_regcomp(llvm_regex_t *preg, const char *pattern, int cflags) +{ + struct parse pa; + struct re_guts *g; + struct parse *p = &pa; + int i; + size_t len; +#ifdef REDEBUG +# define GOODFLAGS(f) (f) +#else +# define GOODFLAGS(f) ((f)&~REG_DUMP) +#endif + + cflags = GOODFLAGS(cflags); + if ((cflags®_EXTENDED) && (cflags®_NOSPEC)) + return(REG_INVARG); + + if (cflags®_PEND) { + if (preg->re_endp < pattern) + return(REG_INVARG); + len = preg->re_endp - pattern; + } else + len = strlen((const char *)pattern); + + /* do the mallocs early so failure handling is easy */ + g = (struct re_guts *)malloc(sizeof(struct re_guts) + + (NC-1)*sizeof(cat_t)); + if (g == NULL) + return(REG_ESPACE); + p->ssize = len/(size_t)2*(size_t)3 + (size_t)1; /* ugh */ + p->strip = (sop *)calloc(p->ssize, sizeof(sop)); + p->slen = 0; + if (p->strip == NULL) { + free((char *)g); + return(REG_ESPACE); + } + + /* set things up */ + p->g = g; + p->next = (char *)pattern; /* convenience; we do not modify it */ + p->end = p->next + len; + p->error = 0; + p->ncsalloc = 0; + for (i = 0; i < NPAREN; i++) { + p->pbegin[i] = 0; + p->pend[i] = 0; + } + g->csetsize = NC; + g->sets = NULL; + g->setbits = NULL; + g->ncsets = 0; + g->cflags = cflags; + g->iflags = 0; + g->nbol = 0; + g->neol = 0; + g->must = NULL; + g->mlen = 0; + g->nsub = 0; + g->ncategories = 1; /* category 0 is "everything else" */ + g->categories = &g->catspace[-(CHAR_MIN)]; + (void) memset((char *)g->catspace, 0, NC*sizeof(cat_t)); + g->backrefs = 0; + + /* do it */ + EMIT(OEND, 0); + g->firststate = THERE(); + if (cflags®_EXTENDED) + p_ere(p, OUT); + else if (cflags®_NOSPEC) + p_str(p); + else + p_bre(p, OUT, OUT); + EMIT(OEND, 0); + g->laststate = THERE(); + + /* tidy up loose ends and fill things in */ + categorize(p, g); + stripsnug(p, g); + findmust(p, g); + g->nplus = pluscount(p, g); + g->magic = MAGIC2; + preg->re_nsub = g->nsub; + preg->re_g = g; + preg->re_magic = MAGIC1; +#ifndef REDEBUG + /* not debugging, so can't rely on the assert() in llvm_regexec() */ + if (g->iflags®EX_BAD) + SETERROR(REG_ASSERT); +#endif + + /* win or lose, we're done */ + if (p->error != 0) /* lose */ + llvm_regfree(preg); + return(p->error); +} + +/* + - p_ere - ERE parser top level, concatenation and alternation + */ +static void +p_ere(struct parse *p, int stop) /* character this ERE should end at */ +{ + char c; + sopno prevback = 0; + sopno prevfwd = 0; + sopno conc; + int first = 1; /* is this the first alternative? */ + + for (;;) { + /* do a bunch of concatenated expressions */ + conc = HERE(); + while (MORE() && (c = PEEK()) != '|' && c != stop) + p_ere_exp(p); + REQUIRE(HERE() != conc, REG_EMPTY); /* require nonempty */ + + if (!EAT('|')) + break; /* NOTE BREAK OUT */ + + if (first) { + INSERT(OCH_, conc); /* offset is wrong */ + prevfwd = conc; + prevback = conc; + first = 0; + } + ASTERN(OOR1, prevback); + prevback = THERE(); + AHEAD(prevfwd); /* fix previous offset */ + prevfwd = HERE(); + EMIT(OOR2, 0); /* offset is very wrong */ + } + + if (!first) { /* tail-end fixups */ + AHEAD(prevfwd); + ASTERN(O_CH, prevback); + } + + assert(!MORE() || SEE(stop)); +} + +/* + - p_ere_exp - parse one subERE, an atom possibly followed by a repetition op + */ +static void +p_ere_exp(struct parse *p) +{ + char c; + sopno pos; + int count; + int count2; + sopno subno; + int wascaret = 0; + + assert(MORE()); /* caller should have ensured this */ + c = GETNEXT(); + + pos = HERE(); + switch (c) { + case '(': + REQUIRE(MORE(), REG_EPAREN); + p->g->nsub++; + subno = p->g->nsub; + if (subno < NPAREN) + p->pbegin[subno] = HERE(); + EMIT(OLPAREN, subno); + if (!SEE(')')) + p_ere(p, ')'); + if (subno < NPAREN) { + p->pend[subno] = HERE(); + assert(p->pend[subno] != 0); + } + EMIT(ORPAREN, subno); + MUSTEAT(')', REG_EPAREN); + break; +#ifndef POSIX_MISTAKE + case ')': /* happens only if no current unmatched ( */ + /* + * You may ask, why the ifndef? Because I didn't notice + * this until slightly too late for 1003.2, and none of the + * other 1003.2 regular-expression reviewers noticed it at + * all. So an unmatched ) is legal POSIX, at least until + * we can get it fixed. + */ + SETERROR(REG_EPAREN); + break; +#endif + case '^': + EMIT(OBOL, 0); + p->g->iflags |= USEBOL; + p->g->nbol++; + wascaret = 1; + break; + case '$': + EMIT(OEOL, 0); + p->g->iflags |= USEEOL; + p->g->neol++; + break; + case '|': + SETERROR(REG_EMPTY); + break; + case '*': + case '+': + case '?': + SETERROR(REG_BADRPT); + break; + case '.': + if (p->g->cflags®_NEWLINE) + nonnewline(p); + else + EMIT(OANY, 0); + break; + case '[': + p_bracket(p); + break; + case '\\': + REQUIRE(MORE(), REG_EESCAPE); + c = GETNEXT(); + ordinary(p, c); + break; + case '{': /* okay as ordinary except if digit follows */ + REQUIRE(!MORE() || !isdigit((uch)PEEK()), REG_BADRPT); + /* FALLTHROUGH */ + default: + ordinary(p, c); + break; + } + + if (!MORE()) + return; + c = PEEK(); + /* we call { a repetition if followed by a digit */ + if (!( c == '*' || c == '+' || c == '?' || + (c == '{' && MORE2() && isdigit((uch)PEEK2())) )) + return; /* no repetition, we're done */ + NEXT(); + + REQUIRE(!wascaret, REG_BADRPT); + switch (c) { + case '*': /* implemented as +? */ + /* this case does not require the (y|) trick, noKLUDGE */ + INSERT(OPLUS_, pos); + ASTERN(O_PLUS, pos); + INSERT(OQUEST_, pos); + ASTERN(O_QUEST, pos); + break; + case '+': + INSERT(OPLUS_, pos); + ASTERN(O_PLUS, pos); + break; + case '?': + /* KLUDGE: emit y? as (y|) until subtle bug gets fixed */ + INSERT(OCH_, pos); /* offset slightly wrong */ + ASTERN(OOR1, pos); /* this one's right */ + AHEAD(pos); /* fix the OCH_ */ + EMIT(OOR2, 0); /* offset very wrong... */ + AHEAD(THERE()); /* ...so fix it */ + ASTERN(O_CH, THERETHERE()); + break; + case '{': + count = p_count(p); + if (EAT(',')) { + if (isdigit((uch)PEEK())) { + count2 = p_count(p); + REQUIRE(count <= count2, REG_BADBR); + } else /* single number with comma */ + count2 = INFINITY; + } else /* just a single number */ + count2 = count; + repeat(p, pos, count, count2); + if (!EAT('}')) { /* error heuristics */ + while (MORE() && PEEK() != '}') + NEXT(); + REQUIRE(MORE(), REG_EBRACE); + SETERROR(REG_BADBR); + } + break; + } + + if (!MORE()) + return; + c = PEEK(); + if (!( c == '*' || c == '+' || c == '?' || + (c == '{' && MORE2() && isdigit((uch)PEEK2())) ) ) + return; + SETERROR(REG_BADRPT); +} + +/* + - p_str - string (no metacharacters) "parser" + */ +static void +p_str(struct parse *p) +{ + REQUIRE(MORE(), REG_EMPTY); + while (MORE()) + ordinary(p, GETNEXT()); +} + +/* + - p_bre - BRE parser top level, anchoring and concatenation + * Giving end1 as OUT essentially eliminates the end1/end2 check. + * + * This implementation is a bit of a kludge, in that a trailing $ is first + * taken as an ordinary character and then revised to be an anchor. The + * only undesirable side effect is that '$' gets included as a character + * category in such cases. This is fairly harmless; not worth fixing. + * The amount of lookahead needed to avoid this kludge is excessive. + */ +static void +p_bre(struct parse *p, + int end1, /* first terminating character */ + int end2) /* second terminating character */ +{ + sopno start = HERE(); + int first = 1; /* first subexpression? */ + int wasdollar = 0; + + if (EAT('^')) { + EMIT(OBOL, 0); + p->g->iflags |= USEBOL; + p->g->nbol++; + } + while (MORE() && !SEETWO(end1, end2)) { + wasdollar = p_simp_re(p, first); + first = 0; + } + if (wasdollar) { /* oops, that was a trailing anchor */ + DROP(1); + EMIT(OEOL, 0); + p->g->iflags |= USEEOL; + p->g->neol++; + } + + REQUIRE(HERE() != start, REG_EMPTY); /* require nonempty */ +} + +/* + - p_simp_re - parse a simple RE, an atom possibly followed by a repetition + */ +static int /* was the simple RE an unbackslashed $? */ +p_simp_re(struct parse *p, + int starordinary) /* is a leading * an ordinary character? */ +{ + int c; + int count; + int count2; + sopno pos; + int i; + sopno subno; +# define BACKSL (1<g->cflags®_NEWLINE) + nonnewline(p); + else + EMIT(OANY, 0); + break; + case '[': + p_bracket(p); + break; + case BACKSL|'{': + SETERROR(REG_BADRPT); + break; + case BACKSL|'(': + p->g->nsub++; + subno = p->g->nsub; + if (subno < NPAREN) + p->pbegin[subno] = HERE(); + EMIT(OLPAREN, subno); + /* the MORE here is an error heuristic */ + if (MORE() && !SEETWO('\\', ')')) + p_bre(p, '\\', ')'); + if (subno < NPAREN) { + p->pend[subno] = HERE(); + assert(p->pend[subno] != 0); + } + EMIT(ORPAREN, subno); + REQUIRE(EATTWO('\\', ')'), REG_EPAREN); + break; + case BACKSL|')': /* should not get here -- must be user */ + case BACKSL|'}': + SETERROR(REG_EPAREN); + break; + case BACKSL|'1': + case BACKSL|'2': + case BACKSL|'3': + case BACKSL|'4': + case BACKSL|'5': + case BACKSL|'6': + case BACKSL|'7': + case BACKSL|'8': + case BACKSL|'9': + i = (c&~BACKSL) - '0'; + assert(i < NPAREN); + if (p->pend[i] != 0) { + assert(i <= p->g->nsub); + EMIT(OBACK_, i); + assert(p->pbegin[i] != 0); + assert(OP(p->strip[p->pbegin[i]]) == OLPAREN); + assert(OP(p->strip[p->pend[i]]) == ORPAREN); + (void) dupl(p, p->pbegin[i]+1, p->pend[i]); + EMIT(O_BACK, i); + } else + SETERROR(REG_ESUBREG); + p->g->backrefs = 1; + break; + case '*': + REQUIRE(starordinary, REG_BADRPT); + /* FALLTHROUGH */ + default: + ordinary(p, (char)c); + break; + } + + if (EAT('*')) { /* implemented as +? */ + /* this case does not require the (y|) trick, noKLUDGE */ + INSERT(OPLUS_, pos); + ASTERN(O_PLUS, pos); + INSERT(OQUEST_, pos); + ASTERN(O_QUEST, pos); + } else if (EATTWO('\\', '{')) { + count = p_count(p); + if (EAT(',')) { + if (MORE() && isdigit((uch)PEEK())) { + count2 = p_count(p); + REQUIRE(count <= count2, REG_BADBR); + } else /* single number with comma */ + count2 = INFINITY; + } else /* just a single number */ + count2 = count; + repeat(p, pos, count, count2); + if (!EATTWO('\\', '}')) { /* error heuristics */ + while (MORE() && !SEETWO('\\', '}')) + NEXT(); + REQUIRE(MORE(), REG_EBRACE); + SETERROR(REG_BADBR); + } + } else if (c == '$') /* $ (but not \$) ends it */ + return(1); + + return(0); +} + +/* + - p_count - parse a repetition count + */ +static int /* the value */ +p_count(struct parse *p) +{ + int count = 0; + int ndigits = 0; + + while (MORE() && isdigit((uch)PEEK()) && count <= DUPMAX) { + count = count*10 + (GETNEXT() - '0'); + ndigits++; + } + + REQUIRE(ndigits > 0 && count <= DUPMAX, REG_BADBR); + return(count); +} + +/* + - p_bracket - parse a bracketed character list + * + * Note a significant property of this code: if the allocset() did SETERROR, + * no set operations are done. + */ +static void +p_bracket(struct parse *p) +{ + cset *cs; + int invert = 0; + + /* Dept of Truly Sickening Special-Case Kludges */ + if (p->next + 5 < p->end && strncmp(p->next, "[:<:]]", 6) == 0) { + EMIT(OBOW, 0); + NEXTn(6); + return; + } + if (p->next + 5 < p->end && strncmp(p->next, "[:>:]]", 6) == 0) { + EMIT(OEOW, 0); + NEXTn(6); + return; + } + + if ((cs = allocset(p)) == NULL) { + /* allocset did set error status in p */ + return; + } + + if (EAT('^')) + invert++; /* make note to invert set at end */ + if (EAT(']')) + CHadd(cs, ']'); + else if (EAT('-')) + CHadd(cs, '-'); + while (MORE() && PEEK() != ']' && !SEETWO('-', ']')) + p_b_term(p, cs); + if (EAT('-')) + CHadd(cs, '-'); + MUSTEAT(']', REG_EBRACK); + + if (p->error != 0) { /* don't mess things up further */ + freeset(p, cs); + return; + } + + if (p->g->cflags®_ICASE) { + int i; + int ci; + + for (i = p->g->csetsize - 1; i >= 0; i--) + if (CHIN(cs, i) && isalpha(i)) { + ci = othercase(i); + if (ci != i) + CHadd(cs, ci); + } + if (cs->multis != NULL) + mccase(p, cs); + } + if (invert) { + int i; + + for (i = p->g->csetsize - 1; i >= 0; i--) + if (CHIN(cs, i)) + CHsub(cs, i); + else + CHadd(cs, i); + if (p->g->cflags®_NEWLINE) + CHsub(cs, '\n'); + if (cs->multis != NULL) + mcinvert(p, cs); + } + + assert(cs->multis == NULL); /* xxx */ + + if (nch(p, cs) == 1) { /* optimize singleton sets */ + ordinary(p, firstch(p, cs)); + freeset(p, cs); + } else + EMIT(OANYOF, freezeset(p, cs)); +} + +/* + - p_b_term - parse one term of a bracketed character list + */ +static void +p_b_term(struct parse *p, cset *cs) +{ + char c; + char start, finish; + int i; + + /* classify what we've got */ + switch ((MORE()) ? PEEK() : '\0') { + case '[': + c = (MORE2()) ? PEEK2() : '\0'; + break; + case '-': + SETERROR(REG_ERANGE); + return; /* NOTE RETURN */ + break; + default: + c = '\0'; + break; + } + + switch (c) { + case ':': /* character class */ + NEXT2(); + REQUIRE(MORE(), REG_EBRACK); + c = PEEK(); + REQUIRE(c != '-' && c != ']', REG_ECTYPE); + p_b_cclass(p, cs); + REQUIRE(MORE(), REG_EBRACK); + REQUIRE(EATTWO(':', ']'), REG_ECTYPE); + break; + case '=': /* equivalence class */ + NEXT2(); + REQUIRE(MORE(), REG_EBRACK); + c = PEEK(); + REQUIRE(c != '-' && c != ']', REG_ECOLLATE); + p_b_eclass(p, cs); + REQUIRE(MORE(), REG_EBRACK); + REQUIRE(EATTWO('=', ']'), REG_ECOLLATE); + break; + default: /* symbol, ordinary character, or range */ +/* xxx revision needed for multichar stuff */ + start = p_b_symbol(p); + if (SEE('-') && MORE2() && PEEK2() != ']') { + /* range */ + NEXT(); + if (EAT('-')) + finish = '-'; + else + finish = p_b_symbol(p); + } else + finish = start; +/* xxx what about signed chars here... */ + REQUIRE(start <= finish, REG_ERANGE); + for (i = start; i <= finish; i++) + CHadd(cs, i); + break; + } +} + +/* + - p_b_cclass - parse a character-class name and deal with it + */ +static void +p_b_cclass(struct parse *p, cset *cs) +{ + char *sp = p->next; + struct cclass *cp; + size_t len; + const char *u; + char c; + + while (MORE() && isalpha(PEEK())) + NEXT(); + len = p->next - sp; + for (cp = cclasses; cp->name != NULL; cp++) + if (strncmp(cp->name, sp, len) == 0 && cp->name[len] == '\0') + break; + if (cp->name == NULL) { + /* oops, didn't find it */ + SETERROR(REG_ECTYPE); + return; + } + + u = cp->chars; + while ((c = *u++) != '\0') + CHadd(cs, c); + for (u = cp->multis; *u != '\0'; u += strlen(u) + 1) + MCadd(p, cs, u); +} + +/* + - p_b_eclass - parse an equivalence-class name and deal with it + * + * This implementation is incomplete. xxx + */ +static void +p_b_eclass(struct parse *p, cset *cs) +{ + char c; + + c = p_b_coll_elem(p, '='); + CHadd(cs, c); +} + +/* + - p_b_symbol - parse a character or [..]ed multicharacter collating symbol + */ +static char /* value of symbol */ +p_b_symbol(struct parse *p) +{ + char value; + + REQUIRE(MORE(), REG_EBRACK); + if (!EATTWO('[', '.')) + return(GETNEXT()); + + /* collating symbol */ + value = p_b_coll_elem(p, '.'); + REQUIRE(EATTWO('.', ']'), REG_ECOLLATE); + return(value); +} + +/* + - p_b_coll_elem - parse a collating-element name and look it up + */ +static char /* value of collating element */ +p_b_coll_elem(struct parse *p, + int endc) /* name ended by endc,']' */ +{ + char *sp = p->next; + struct cname *cp; + int len; + + while (MORE() && !SEETWO(endc, ']')) + NEXT(); + if (!MORE()) { + SETERROR(REG_EBRACK); + return(0); + } + len = p->next - sp; + for (cp = cnames; cp->name != NULL; cp++) + if (strncmp(cp->name, sp, len) == 0 && cp->name[len] == '\0') + return(cp->code); /* known name */ + if (len == 1) + return(*sp); /* single character */ + SETERROR(REG_ECOLLATE); /* neither */ + return(0); +} + +/* + - othercase - return the case counterpart of an alphabetic + */ +static char /* if no counterpart, return ch */ +othercase(int ch) +{ + ch = (uch)ch; + assert(isalpha(ch)); + if (isupper(ch)) + return ((uch)tolower(ch)); + else if (islower(ch)) + return ((uch)toupper(ch)); + else /* peculiar, but could happen */ + return(ch); +} + +/* + - bothcases - emit a dualcase version of a two-case character + * + * Boy, is this implementation ever a kludge... + */ +static void +bothcases(struct parse *p, int ch) +{ + char *oldnext = p->next; + char *oldend = p->end; + char bracket[3]; + + ch = (uch)ch; + assert(othercase(ch) != ch); /* p_bracket() would recurse */ + p->next = bracket; + p->end = bracket+2; + bracket[0] = ch; + bracket[1] = ']'; + bracket[2] = '\0'; + p_bracket(p); + assert(p->next == bracket+2); + p->next = oldnext; + p->end = oldend; +} + +/* + - ordinary - emit an ordinary character + */ +static void +ordinary(struct parse *p, int ch) +{ + cat_t *cap = p->g->categories; + + if ((p->g->cflags®_ICASE) && isalpha((uch)ch) && othercase(ch) != ch) + bothcases(p, ch); + else { + EMIT(OCHAR, (uch)ch); + if (cap[ch] == 0) + cap[ch] = p->g->ncategories++; + } +} + +/* + - nonnewline - emit REG_NEWLINE version of OANY + * + * Boy, is this implementation ever a kludge... + */ +static void +nonnewline(struct parse *p) +{ + char *oldnext = p->next; + char *oldend = p->end; + char bracket[4]; + + p->next = bracket; + p->end = bracket+3; + bracket[0] = '^'; + bracket[1] = '\n'; + bracket[2] = ']'; + bracket[3] = '\0'; + p_bracket(p); + assert(p->next == bracket+3); + p->next = oldnext; + p->end = oldend; +} + +/* + - repeat - generate code for a bounded repetition, recursively if needed + */ +static void +repeat(struct parse *p, + sopno start, /* operand from here to end of strip */ + int from, /* repeated from this number */ + int to) /* to this number of times (maybe INFINITY) */ +{ + sopno finish = HERE(); +# define N 2 +# define INF 3 +# define REP(f, t) ((f)*8 + (t)) +# define MAP(n) (((n) <= 1) ? (n) : ((n) == INFINITY) ? INF : N) + sopno copy; + + if (p->error != 0) /* head off possible runaway recursion */ + return; + + assert(from <= to); + + switch (REP(MAP(from), MAP(to))) { + case REP(0, 0): /* must be user doing this */ + DROP(finish-start); /* drop the operand */ + break; + case REP(0, 1): /* as x{1,1}? */ + case REP(0, N): /* as x{1,n}? */ + case REP(0, INF): /* as x{1,}? */ + /* KLUDGE: emit y? as (y|) until subtle bug gets fixed */ + INSERT(OCH_, start); /* offset is wrong... */ + repeat(p, start+1, 1, to); + ASTERN(OOR1, start); + AHEAD(start); /* ... fix it */ + EMIT(OOR2, 0); + AHEAD(THERE()); + ASTERN(O_CH, THERETHERE()); + break; + case REP(1, 1): /* trivial case */ + /* done */ + break; + case REP(1, N): /* as x?x{1,n-1} */ + /* KLUDGE: emit y? as (y|) until subtle bug gets fixed */ + INSERT(OCH_, start); + ASTERN(OOR1, start); + AHEAD(start); + EMIT(OOR2, 0); /* offset very wrong... */ + AHEAD(THERE()); /* ...so fix it */ + ASTERN(O_CH, THERETHERE()); + copy = dupl(p, start+1, finish+1); + assert(copy == finish+4); + repeat(p, copy, 1, to-1); + break; + case REP(1, INF): /* as x+ */ + INSERT(OPLUS_, start); + ASTERN(O_PLUS, start); + break; + case REP(N, N): /* as xx{m-1,n-1} */ + copy = dupl(p, start, finish); + repeat(p, copy, from-1, to-1); + break; + case REP(N, INF): /* as xx{n-1,INF} */ + copy = dupl(p, start, finish); + repeat(p, copy, from-1, to); + break; + default: /* "can't happen" */ + SETERROR(REG_ASSERT); /* just in case */ + break; + } +} + +/* + - seterr - set an error condition + */ +static int /* useless but makes type checking happy */ +seterr(struct parse *p, int e) +{ + if (p->error == 0) /* keep earliest error condition */ + p->error = e; + p->next = nuls; /* try to bring things to a halt */ + p->end = nuls; + return(0); /* make the return value well-defined */ +} + +/* + - allocset - allocate a set of characters for [] + */ +static cset * +allocset(struct parse *p) +{ + int no = p->g->ncsets++; + size_t nc; + size_t nbytes; + cset *cs; + size_t css = (size_t)p->g->csetsize; + int i; + + if (no >= p->ncsalloc) { /* need another column of space */ + void *ptr; + + p->ncsalloc += CHAR_BIT; + nc = p->ncsalloc; + assert(nc % CHAR_BIT == 0); + nbytes = nc / CHAR_BIT * css; + + ptr = (cset *)realloc((char *)p->g->sets, nc * sizeof(cset)); + if (ptr == NULL) + goto nomem; + p->g->sets = ptr; + + ptr = (uch *)realloc((char *)p->g->setbits, nbytes); + if (ptr == NULL) + goto nomem; + p->g->setbits = ptr; + + for (i = 0; i < no; i++) + p->g->sets[i].ptr = p->g->setbits + css*(i/CHAR_BIT); + + (void) memset((char *)p->g->setbits + (nbytes - css), 0, css); + } + /* XXX should not happen */ + if (p->g->sets == NULL || p->g->setbits == NULL) + goto nomem; + + cs = &p->g->sets[no]; + cs->ptr = p->g->setbits + css*((no)/CHAR_BIT); + cs->mask = 1 << ((no) % CHAR_BIT); + cs->hash = 0; + cs->smultis = 0; + cs->multis = NULL; + + return(cs); +nomem: + free(p->g->sets); + p->g->sets = NULL; + free(p->g->setbits); + p->g->setbits = NULL; + + SETERROR(REG_ESPACE); + /* caller's responsibility not to do set ops */ + return(NULL); +} + +/* + - freeset - free a now-unused set + */ +static void +freeset(struct parse *p, cset *cs) +{ + size_t i; + cset *top = &p->g->sets[p->g->ncsets]; + size_t css = (size_t)p->g->csetsize; + + for (i = 0; i < css; i++) + CHsub(cs, i); + if (cs == top-1) /* recover only the easy case */ + p->g->ncsets--; +} + +/* + - freezeset - final processing on a set of characters + * + * The main task here is merging identical sets. This is usually a waste + * of time (although the hash code minimizes the overhead), but can win + * big if REG_ICASE is being used. REG_ICASE, by the way, is why the hash + * is done using addition rather than xor -- all ASCII [aA] sets xor to + * the same value! + */ +static int /* set number */ +freezeset(struct parse *p, cset *cs) +{ + uch h = cs->hash; + size_t i; + cset *top = &p->g->sets[p->g->ncsets]; + cset *cs2; + size_t css = (size_t)p->g->csetsize; + + /* look for an earlier one which is the same */ + for (cs2 = &p->g->sets[0]; cs2 < top; cs2++) + if (cs2->hash == h && cs2 != cs) { + /* maybe */ + for (i = 0; i < css; i++) + if (!!CHIN(cs2, i) != !!CHIN(cs, i)) + break; /* no */ + if (i == css) + break; /* yes */ + } + + if (cs2 < top) { /* found one */ + freeset(p, cs); + cs = cs2; + } + + return((int)(cs - p->g->sets)); +} + +/* + - firstch - return first character in a set (which must have at least one) + */ +static int /* character; there is no "none" value */ +firstch(struct parse *p, cset *cs) +{ + size_t i; + size_t css = (size_t)p->g->csetsize; + + for (i = 0; i < css; i++) + if (CHIN(cs, i)) + return((char)i); + assert(never); + return(0); /* arbitrary */ +} + +/* + - nch - number of characters in a set + */ +static int +nch(struct parse *p, cset *cs) +{ + size_t i; + size_t css = (size_t)p->g->csetsize; + int n = 0; + + for (i = 0; i < css; i++) + if (CHIN(cs, i)) + n++; + return(n); +} + +/* + - mcadd - add a collating element to a cset + */ +static void +mcadd( struct parse *p, cset *cs, const char *cp) +{ + size_t oldend = cs->smultis; + void *np; + + cs->smultis += strlen(cp) + 1; + np = realloc(cs->multis, cs->smultis); + if (np == NULL) { + if (cs->multis) + free(cs->multis); + cs->multis = NULL; + SETERROR(REG_ESPACE); + return; + } + cs->multis = np; + + llvm_strlcpy(cs->multis + oldend - 1, cp, cs->smultis - oldend + 1); +} + +/* + - mcinvert - invert the list of collating elements in a cset + * + * This would have to know the set of possibilities. Implementation + * is deferred. + */ +/* ARGSUSED */ +static void +mcinvert(struct parse *p, cset *cs) +{ + assert(cs->multis == NULL); /* xxx */ +} + +/* + - mccase - add case counterparts of the list of collating elements in a cset + * + * This would have to know the set of possibilities. Implementation + * is deferred. + */ +/* ARGSUSED */ +static void +mccase(struct parse *p, cset *cs) +{ + assert(cs->multis == NULL); /* xxx */ +} + +/* + - isinsets - is this character in any sets? + */ +static int /* predicate */ +isinsets(struct re_guts *g, int c) +{ + uch *col; + int i; + int ncols = (g->ncsets+(CHAR_BIT-1)) / CHAR_BIT; + unsigned uc = (uch)c; + + for (i = 0, col = g->setbits; i < ncols; i++, col += g->csetsize) + if (col[uc] != 0) + return(1); + return(0); +} + +/* + - samesets - are these two characters in exactly the same sets? + */ +static int /* predicate */ +samesets(struct re_guts *g, int c1, int c2) +{ + uch *col; + int i; + int ncols = (g->ncsets+(CHAR_BIT-1)) / CHAR_BIT; + unsigned uc1 = (uch)c1; + unsigned uc2 = (uch)c2; + + for (i = 0, col = g->setbits; i < ncols; i++, col += g->csetsize) + if (col[uc1] != col[uc2]) + return(0); + return(1); +} + +/* + - categorize - sort out character categories + */ +static void +categorize(struct parse *p, struct re_guts *g) +{ + cat_t *cats = g->categories; + int c; + int c2; + cat_t cat; + + /* avoid making error situations worse */ + if (p->error != 0) + return; + + for (c = CHAR_MIN; c <= CHAR_MAX; c++) + if (cats[c] == 0 && isinsets(g, c)) { + cat = g->ncategories++; + cats[c] = cat; + for (c2 = c+1; c2 <= CHAR_MAX; c2++) + if (cats[c2] == 0 && samesets(g, c, c2)) + cats[c2] = cat; + } +} + +/* + - dupl - emit a duplicate of a bunch of sops + */ +static sopno /* start of duplicate */ +dupl(struct parse *p, + sopno start, /* from here */ + sopno finish) /* to this less one */ +{ + sopno ret = HERE(); + sopno len = finish - start; + + assert(finish >= start); + if (len == 0) + return(ret); + enlarge(p, p->ssize + len); /* this many unexpected additions */ + assert(p->ssize >= p->slen + len); + (void) memmove((char *)(p->strip + p->slen), + (char *)(p->strip + start), (size_t)len*sizeof(sop)); + p->slen += len; + return(ret); +} + +/* + - doemit - emit a strip operator + * + * It might seem better to implement this as a macro with a function as + * hard-case backup, but it's just too big and messy unless there are + * some changes to the data structures. Maybe later. + */ +static void +doemit(struct parse *p, sop op, size_t opnd) +{ + /* avoid making error situations worse */ + if (p->error != 0) + return; + + /* deal with oversize operands ("can't happen", more or less) */ + assert(opnd < 1<slen >= p->ssize) + enlarge(p, (p->ssize+1) / 2 * 3); /* +50% */ + assert(p->slen < p->ssize); + + /* finally, it's all reduced to the easy case */ + p->strip[p->slen++] = SOP(op, opnd); +} + +/* + - doinsert - insert a sop into the strip + */ +static void +doinsert(struct parse *p, sop op, size_t opnd, sopno pos) +{ + sopno sn; + sop s; + int i; + + /* avoid making error situations worse */ + if (p->error != 0) + return; + + sn = HERE(); + EMIT(op, opnd); /* do checks, ensure space */ + assert(HERE() == sn+1); + s = p->strip[sn]; + + /* adjust paren pointers */ + assert(pos > 0); + for (i = 1; i < NPAREN; i++) { + if (p->pbegin[i] >= pos) { + p->pbegin[i]++; + } + if (p->pend[i] >= pos) { + p->pend[i]++; + } + } + + memmove((char *)&p->strip[pos+1], (char *)&p->strip[pos], + (HERE()-pos-1)*sizeof(sop)); + p->strip[pos] = s; +} + +/* + - dofwd - complete a forward reference + */ +static void +dofwd(struct parse *p, sopno pos, sop value) +{ + /* avoid making error situations worse */ + if (p->error != 0) + return; + + assert(value < 1<strip[pos] = OP(p->strip[pos]) | value; +} + +/* + - enlarge - enlarge the strip + */ +static void +enlarge(struct parse *p, sopno size) +{ + sop *sp; + + if (p->ssize >= size) + return; + + sp = (sop *)realloc(p->strip, size*sizeof(sop)); + if (sp == NULL) { + SETERROR(REG_ESPACE); + return; + } + p->strip = sp; + p->ssize = size; +} + +/* + - stripsnug - compact the strip + */ +static void +stripsnug(struct parse *p, struct re_guts *g) +{ + g->nstates = p->slen; + g->strip = (sop *)realloc((char *)p->strip, p->slen * sizeof(sop)); + if (g->strip == NULL) { + SETERROR(REG_ESPACE); + g->strip = p->strip; + } +} + +/* + - findmust - fill in must and mlen with longest mandatory literal string + * + * This algorithm could do fancy things like analyzing the operands of | + * for common subsequences. Someday. This code is simple and finds most + * of the interesting cases. + * + * Note that must and mlen got initialized during setup. + */ +static void +findmust(struct parse *p, struct re_guts *g) +{ + sop *scan; + sop *start = 0; /* start initialized in the default case, after that */ + sop *newstart = 0; /* newstart was initialized in the OCHAR case */ + sopno newlen; + sop s; + char *cp; + sopno i; + + /* avoid making error situations worse */ + if (p->error != 0) + return; + + /* find the longest OCHAR sequence in strip */ + newlen = 0; + scan = g->strip + 1; + do { + s = *scan++; + switch (OP(s)) { + case OCHAR: /* sequence member */ + if (newlen == 0) /* new sequence */ + newstart = scan - 1; + newlen++; + break; + case OPLUS_: /* things that don't break one */ + case OLPAREN: + case ORPAREN: + break; + case OQUEST_: /* things that must be skipped */ + case OCH_: + scan--; + do { + scan += OPND(s); + s = *scan; + /* assert() interferes w debug printouts */ + if (OP(s) != O_QUEST && OP(s) != O_CH && + OP(s) != OOR2) { + g->iflags |= REGEX_BAD; + return; + } + } while (OP(s) != O_QUEST && OP(s) != O_CH); + /* fallthrough */ + default: /* things that break a sequence */ + if (newlen > g->mlen) { /* ends one */ + start = newstart; + g->mlen = newlen; + } + newlen = 0; + break; + } + } while (OP(s) != OEND); + + if (g->mlen == 0) /* there isn't one */ + return; + + /* turn it into a character string */ + g->must = malloc((size_t)g->mlen + 1); + if (g->must == NULL) { /* argh; just forget it */ + g->mlen = 0; + return; + } + cp = g->must; + scan = start; + for (i = g->mlen; i > 0; i--) { + while (OP(s = *scan++) != OCHAR) + continue; + assert(cp < g->must + g->mlen); + *cp++ = (char)OPND(s); + } + assert(cp == g->must + g->mlen); + *cp++ = '\0'; /* just on general principles */ +} + +/* + - pluscount - count + nesting + */ +static sopno /* nesting depth */ +pluscount(struct parse *p, struct re_guts *g) +{ + sop *scan; + sop s; + sopno plusnest = 0; + sopno maxnest = 0; + + if (p->error != 0) + return(0); /* there may not be an OEND */ + + scan = g->strip + 1; + do { + s = *scan++; + switch (OP(s)) { + case OPLUS_: + plusnest++; + break; + case O_PLUS: + if (plusnest > maxnest) + maxnest = plusnest; + plusnest--; + break; + } + } while (OP(s) != OEND); + if (plusnest != 0) + g->iflags |= REGEX_BAD; + return(maxnest); +} diff --git a/libclamav/c++/llvm/lib/Support/regengine.inc b/libclamav/c++/llvm/lib/Support/regengine.inc new file mode 100644 index 000000000..0f27cfd4b --- /dev/null +++ b/libclamav/c++/llvm/lib/Support/regengine.inc @@ -0,0 +1,1027 @@ +/*- + * This code is derived from OpenBSD's libc/regex, original license follows: + * + * Copyright (c) 1992, 1993, 1994 Henry Spencer. + * Copyright (c) 1992, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Henry Spencer. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)engine.c 8.5 (Berkeley) 3/20/94 + */ + +/* + * The matching engine and friends. This file is #included by regexec.c + * after suitable #defines of a variety of macros used herein, so that + * different state representations can be used without duplicating masses + * of code. + */ + +#ifdef SNAMES +#define matcher smatcher +#define fast sfast +#define slow sslow +#define dissect sdissect +#define backref sbackref +#define step sstep +#define print sprint +#define at sat +#define match smat +#define nope snope +#endif +#ifdef LNAMES +#define matcher lmatcher +#define fast lfast +#define slow lslow +#define dissect ldissect +#define backref lbackref +#define step lstep +#define print lprint +#define at lat +#define match lmat +#define nope lnope +#endif + +/* another structure passed up and down to avoid zillions of parameters */ +struct match { + struct re_guts *g; + int eflags; + llvm_regmatch_t *pmatch; /* [nsub+1] (0 element unused) */ + char *offp; /* offsets work from here */ + char *beginp; /* start of string -- virtual NUL precedes */ + char *endp; /* end of string -- virtual NUL here */ + char *coldp; /* can be no match starting before here */ + char **lastpos; /* [nplus+1] */ + STATEVARS; + states st; /* current states */ + states fresh; /* states for a fresh start */ + states tmp; /* temporary */ + states empty; /* empty set of states */ +}; + +static int matcher(struct re_guts *, char *, size_t, llvm_regmatch_t[], int); +static char *dissect(struct match *, char *, char *, sopno, sopno); +static char *backref(struct match *, char *, char *, sopno, sopno, sopno, int); +static char *fast(struct match *, char *, char *, sopno, sopno); +static char *slow(struct match *, char *, char *, sopno, sopno); +static states step(struct re_guts *, sopno, sopno, states, int, states); +#define MAX_RECURSION 100 +#define BOL (OUT+1) +#define EOL (BOL+1) +#define BOLEOL (BOL+2) +#define NOTHING (BOL+3) +#define BOW (BOL+4) +#define EOW (BOL+5) +#define CODEMAX (BOL+5) /* highest code used */ +#define NONCHAR(c) ((c) > CHAR_MAX) +#define NNONCHAR (CODEMAX-CHAR_MAX) +#ifdef REDEBUG +static void print(struct match *, char *, states, int, FILE *); +#endif +#ifdef REDEBUG +static void at(struct match *, char *, char *, char *, sopno, sopno); +#endif +#ifdef REDEBUG +static char *pchar(int); +#endif + +#ifdef REDEBUG +#define SP(t, s, c) print(m, t, s, c, stdout) +#define AT(t, p1, p2, s1, s2) at(m, t, p1, p2, s1, s2) +#define NOTE(str) { if (m->eflags®_TRACE) (void)printf("=%s\n", (str)); } +static int nope = 0; +#else +#define SP(t, s, c) /* nothing */ +#define AT(t, p1, p2, s1, s2) /* nothing */ +#define NOTE(s) /* nothing */ +#endif + +/* + - matcher - the actual matching engine + */ +static int /* 0 success, REG_NOMATCH failure */ +matcher(struct re_guts *g, char *string, size_t nmatch, llvm_regmatch_t pmatch[], + int eflags) +{ + char *endp; + size_t i; + struct match mv; + struct match *m = &mv; + char *dp; + const sopno gf = g->firststate+1; /* +1 for OEND */ + const sopno gl = g->laststate; + char *start; + char *stop; + + /* simplify the situation where possible */ + if (g->cflags®_NOSUB) + nmatch = 0; + if (eflags®_STARTEND) { + start = string + pmatch[0].rm_so; + stop = string + pmatch[0].rm_eo; + } else { + start = string; + stop = start + strlen(start); + } + if (stop < start) + return(REG_INVARG); + + /* prescreening; this does wonders for this rather slow code */ + if (g->must != NULL) { + for (dp = start; dp < stop; dp++) + if (*dp == g->must[0] && stop - dp >= g->mlen && + memcmp(dp, g->must, (size_t)g->mlen) == 0) + break; + if (dp == stop) /* we didn't find g->must */ + return(REG_NOMATCH); + } + + /* match struct setup */ + m->g = g; + m->eflags = eflags; + m->pmatch = NULL; + m->lastpos = NULL; + m->offp = string; + m->beginp = start; + m->endp = stop; + STATESETUP(m, 4); + SETUP(m->st); + SETUP(m->fresh); + SETUP(m->tmp); + SETUP(m->empty); + CLEAR(m->empty); + + /* this loop does only one repetition except for backrefs */ + for (;;) { + endp = fast(m, start, stop, gf, gl); + if (endp == NULL) { /* a miss */ + free(m->pmatch); + free(m->lastpos); + STATETEARDOWN(m); + return(REG_NOMATCH); + } + if (nmatch == 0 && !g->backrefs) + break; /* no further info needed */ + + /* where? */ + assert(m->coldp != NULL); + for (;;) { + NOTE("finding start"); + endp = slow(m, m->coldp, stop, gf, gl); + if (endp != NULL) + break; + assert(m->coldp < m->endp); + m->coldp++; + } + if (nmatch == 1 && !g->backrefs) + break; /* no further info needed */ + + /* oh my, he wants the subexpressions... */ + if (m->pmatch == NULL) + m->pmatch = (llvm_regmatch_t *)malloc((m->g->nsub + 1) * + sizeof(llvm_regmatch_t)); + if (m->pmatch == NULL) { + STATETEARDOWN(m); + return(REG_ESPACE); + } + for (i = 1; i <= m->g->nsub; i++) + m->pmatch[i].rm_so = m->pmatch[i].rm_eo = -1; + if (!g->backrefs && !(m->eflags®_BACKR)) { + NOTE("dissecting"); + dp = dissect(m, m->coldp, endp, gf, gl); + } else { + if (g->nplus > 0 && m->lastpos == NULL) + m->lastpos = (char **)malloc((g->nplus+1) * + sizeof(char *)); + if (g->nplus > 0 && m->lastpos == NULL) { + free(m->pmatch); + STATETEARDOWN(m); + return(REG_ESPACE); + } + NOTE("backref dissect"); + dp = backref(m, m->coldp, endp, gf, gl, (sopno)0, 0); + } + if (dp != NULL) + break; + + /* uh-oh... we couldn't find a subexpression-level match */ + assert(g->backrefs); /* must be back references doing it */ + assert(g->nplus == 0 || m->lastpos != NULL); + for (;;) { + if (dp != NULL || endp <= m->coldp) + break; /* defeat */ + NOTE("backoff"); + endp = slow(m, m->coldp, endp-1, gf, gl); + if (endp == NULL) + break; /* defeat */ + /* try it on a shorter possibility */ +#ifndef NDEBUG + for (i = 1; i <= m->g->nsub; i++) { + assert(m->pmatch[i].rm_so == -1); + assert(m->pmatch[i].rm_eo == -1); + } +#endif + NOTE("backoff dissect"); + dp = backref(m, m->coldp, endp, gf, gl, (sopno)0, 0); + } + assert(dp == NULL || dp == endp); + if (dp != NULL) /* found a shorter one */ + break; + + /* despite initial appearances, there is no match here */ + NOTE("false alarm"); + if (m->coldp == stop) + break; + start = m->coldp + 1; /* recycle starting later */ + } + + /* fill in the details if requested */ + if (nmatch > 0) { + pmatch[0].rm_so = m->coldp - m->offp; + pmatch[0].rm_eo = endp - m->offp; + } + if (nmatch > 1) { + assert(m->pmatch != NULL); + for (i = 1; i < nmatch; i++) + if (i <= m->g->nsub) + pmatch[i] = m->pmatch[i]; + else { + pmatch[i].rm_so = -1; + pmatch[i].rm_eo = -1; + } + } + + if (m->pmatch != NULL) + free((char *)m->pmatch); + if (m->lastpos != NULL) + free((char *)m->lastpos); + STATETEARDOWN(m); + return(0); +} + +/* + - dissect - figure out what matched what, no back references + */ +static char * /* == stop (success) always */ +dissect(struct match *m, char *start, char *stop, sopno startst, sopno stopst) +{ + int i; + sopno ss; /* start sop of current subRE */ + sopno es; /* end sop of current subRE */ + char *sp; /* start of string matched by it */ + char *stp; /* string matched by it cannot pass here */ + char *rest; /* start of rest of string */ + char *tail; /* string unmatched by rest of RE */ + sopno ssub; /* start sop of subsubRE */ + sopno esub; /* end sop of subsubRE */ + char *ssp; /* start of string matched by subsubRE */ + char *sep; /* end of string matched by subsubRE */ + char *oldssp; /* previous ssp */ + + AT("diss", start, stop, startst, stopst); + sp = start; + for (ss = startst; ss < stopst; ss = es) { + /* identify end of subRE */ + es = ss; + switch (OP(m->g->strip[es])) { + case OPLUS_: + case OQUEST_: + es += OPND(m->g->strip[es]); + break; + case OCH_: + while (OP(m->g->strip[es]) != O_CH) + es += OPND(m->g->strip[es]); + break; + } + es++; + + /* figure out what it matched */ + switch (OP(m->g->strip[ss])) { + case OEND: + assert(nope); + break; + case OCHAR: + sp++; + break; + case OBOL: + case OEOL: + case OBOW: + case OEOW: + break; + case OANY: + case OANYOF: + sp++; + break; + case OBACK_: + case O_BACK: + assert(nope); + break; + /* cases where length of match is hard to find */ + case OQUEST_: + stp = stop; + for (;;) { + /* how long could this one be? */ + rest = slow(m, sp, stp, ss, es); + assert(rest != NULL); /* it did match */ + /* could the rest match the rest? */ + tail = slow(m, rest, stop, es, stopst); + if (tail == stop) + break; /* yes! */ + /* no -- try a shorter match for this one */ + stp = rest - 1; + assert(stp >= sp); /* it did work */ + } + ssub = ss + 1; + esub = es - 1; + /* did innards match? */ + if (slow(m, sp, rest, ssub, esub) != NULL) { + char *dp = dissect(m, sp, rest, ssub, esub); + (void)dp; /* avoid warning if assertions off */ + assert(dp == rest); + } else /* no */ + assert(sp == rest); + sp = rest; + break; + case OPLUS_: + stp = stop; + for (;;) { + /* how long could this one be? */ + rest = slow(m, sp, stp, ss, es); + assert(rest != NULL); /* it did match */ + /* could the rest match the rest? */ + tail = slow(m, rest, stop, es, stopst); + if (tail == stop) + break; /* yes! */ + /* no -- try a shorter match for this one */ + stp = rest - 1; + assert(stp >= sp); /* it did work */ + } + ssub = ss + 1; + esub = es - 1; + ssp = sp; + oldssp = ssp; + for (;;) { /* find last match of innards */ + sep = slow(m, ssp, rest, ssub, esub); + if (sep == NULL || sep == ssp) + break; /* failed or matched null */ + oldssp = ssp; /* on to next try */ + ssp = sep; + } + if (sep == NULL) { + /* last successful match */ + sep = ssp; + ssp = oldssp; + } + assert(sep == rest); /* must exhaust substring */ + assert(slow(m, ssp, sep, ssub, esub) == rest); + { + char *dp = dissect(m, ssp, sep, ssub, esub); + (void)dp; /* avoid warning if assertions off */ + assert(dp == sep); + } + sp = rest; + break; + case OCH_: + stp = stop; + for (;;) { + /* how long could this one be? */ + rest = slow(m, sp, stp, ss, es); + assert(rest != NULL); /* it did match */ + /* could the rest match the rest? */ + tail = slow(m, rest, stop, es, stopst); + if (tail == stop) + break; /* yes! */ + /* no -- try a shorter match for this one */ + stp = rest - 1; + assert(stp >= sp); /* it did work */ + } + ssub = ss + 1; + esub = ss + OPND(m->g->strip[ss]) - 1; + assert(OP(m->g->strip[esub]) == OOR1); + for (;;) { /* find first matching branch */ + if (slow(m, sp, rest, ssub, esub) == rest) + break; /* it matched all of it */ + /* that one missed, try next one */ + assert(OP(m->g->strip[esub]) == OOR1); + esub++; + assert(OP(m->g->strip[esub]) == OOR2); + ssub = esub + 1; + esub += OPND(m->g->strip[esub]); + if (OP(m->g->strip[esub]) == OOR2) + esub--; + else + assert(OP(m->g->strip[esub]) == O_CH); + } + { + char *dp = dissect(m, sp, rest, ssub, esub); + (void)dp; /* avoid warning if assertions off */ + assert(dp == rest); + } + sp = rest; + break; + case O_PLUS: + case O_QUEST: + case OOR1: + case OOR2: + case O_CH: + assert(nope); + break; + case OLPAREN: + i = OPND(m->g->strip[ss]); + assert(0 < i && i <= m->g->nsub); + m->pmatch[i].rm_so = sp - m->offp; + break; + case ORPAREN: + i = OPND(m->g->strip[ss]); + assert(0 < i && i <= m->g->nsub); + m->pmatch[i].rm_eo = sp - m->offp; + break; + default: /* uh oh */ + assert(nope); + break; + } + } + + assert(sp == stop); + return(sp); +} + +/* + - backref - figure out what matched what, figuring in back references + */ +static char * /* == stop (success) or NULL (failure) */ +backref(struct match *m, char *start, char *stop, sopno startst, sopno stopst, + sopno lev, int rec) /* PLUS nesting level */ +{ + int i; + sopno ss; /* start sop of current subRE */ + char *sp; /* start of string matched by it */ + sopno ssub; /* start sop of subsubRE */ + sopno esub; /* end sop of subsubRE */ + char *ssp; /* start of string matched by subsubRE */ + char *dp; + size_t len; + int hard; + sop s; + llvm_regoff_t offsave; + cset *cs; + + AT("back", start, stop, startst, stopst); + sp = start; + + /* get as far as we can with easy stuff */ + hard = 0; + for (ss = startst; !hard && ss < stopst; ss++) + switch (OP(s = m->g->strip[ss])) { + case OCHAR: + if (sp == stop || *sp++ != (char)OPND(s)) + return(NULL); + break; + case OANY: + if (sp == stop) + return(NULL); + sp++; + break; + case OANYOF: + cs = &m->g->sets[OPND(s)]; + if (sp == stop || !CHIN(cs, *sp++)) + return(NULL); + break; + case OBOL: + if ( (sp == m->beginp && !(m->eflags®_NOTBOL)) || + (sp < m->endp && *(sp-1) == '\n' && + (m->g->cflags®_NEWLINE)) ) + { /* yes */ } + else + return(NULL); + break; + case OEOL: + if ( (sp == m->endp && !(m->eflags®_NOTEOL)) || + (sp < m->endp && *sp == '\n' && + (m->g->cflags®_NEWLINE)) ) + { /* yes */ } + else + return(NULL); + break; + case OBOW: + if (( (sp == m->beginp && !(m->eflags®_NOTBOL)) || + (sp < m->endp && *(sp-1) == '\n' && + (m->g->cflags®_NEWLINE)) || + (sp > m->beginp && + !ISWORD(*(sp-1))) ) && + (sp < m->endp && ISWORD(*sp)) ) + { /* yes */ } + else + return(NULL); + break; + case OEOW: + if (( (sp == m->endp && !(m->eflags®_NOTEOL)) || + (sp < m->endp && *sp == '\n' && + (m->g->cflags®_NEWLINE)) || + (sp < m->endp && !ISWORD(*sp)) ) && + (sp > m->beginp && ISWORD(*(sp-1))) ) + { /* yes */ } + else + return(NULL); + break; + case O_QUEST: + break; + case OOR1: /* matches null but needs to skip */ + ss++; + s = m->g->strip[ss]; + do { + assert(OP(s) == OOR2); + ss += OPND(s); + } while (OP(s = m->g->strip[ss]) != O_CH); + /* note that the ss++ gets us past the O_CH */ + break; + default: /* have to make a choice */ + hard = 1; + break; + } + if (!hard) { /* that was it! */ + if (sp != stop) + return(NULL); + return(sp); + } + ss--; /* adjust for the for's final increment */ + + /* the hard stuff */ + AT("hard", sp, stop, ss, stopst); + s = m->g->strip[ss]; + switch (OP(s)) { + case OBACK_: /* the vilest depths */ + i = OPND(s); + assert(0 < i && i <= m->g->nsub); + if (m->pmatch[i].rm_eo == -1) + return(NULL); + assert(m->pmatch[i].rm_so != -1); + len = m->pmatch[i].rm_eo - m->pmatch[i].rm_so; + if (len == 0 && rec++ > MAX_RECURSION) + return(NULL); + assert(stop - m->beginp >= len); + if (sp > stop - len) + return(NULL); /* not enough left to match */ + ssp = m->offp + m->pmatch[i].rm_so; + if (memcmp(sp, ssp, len) != 0) + return(NULL); + while (m->g->strip[ss] != SOP(O_BACK, i)) + ss++; + return(backref(m, sp+len, stop, ss+1, stopst, lev, rec)); + break; + case OQUEST_: /* to null or not */ + dp = backref(m, sp, stop, ss+1, stopst, lev, rec); + if (dp != NULL) + return(dp); /* not */ + return(backref(m, sp, stop, ss+OPND(s)+1, stopst, lev, rec)); + break; + case OPLUS_: + assert(m->lastpos != NULL); + assert(lev+1 <= m->g->nplus); + m->lastpos[lev+1] = sp; + return(backref(m, sp, stop, ss+1, stopst, lev+1, rec)); + break; + case O_PLUS: + if (sp == m->lastpos[lev]) /* last pass matched null */ + return(backref(m, sp, stop, ss+1, stopst, lev-1, rec)); + /* try another pass */ + m->lastpos[lev] = sp; + dp = backref(m, sp, stop, ss-OPND(s)+1, stopst, lev, rec); + if (dp == NULL) + return(backref(m, sp, stop, ss+1, stopst, lev-1, rec)); + else + return(dp); + break; + case OCH_: /* find the right one, if any */ + ssub = ss + 1; + esub = ss + OPND(s) - 1; + assert(OP(m->g->strip[esub]) == OOR1); + for (;;) { /* find first matching branch */ + dp = backref(m, sp, stop, ssub, esub, lev, rec); + if (dp != NULL) + return(dp); + /* that one missed, try next one */ + if (OP(m->g->strip[esub]) == O_CH) + return(NULL); /* there is none */ + esub++; + assert(OP(m->g->strip[esub]) == OOR2); + ssub = esub + 1; + esub += OPND(m->g->strip[esub]); + if (OP(m->g->strip[esub]) == OOR2) + esub--; + else + assert(OP(m->g->strip[esub]) == O_CH); + } + break; + case OLPAREN: /* must undo assignment if rest fails */ + i = OPND(s); + assert(0 < i && i <= m->g->nsub); + offsave = m->pmatch[i].rm_so; + m->pmatch[i].rm_so = sp - m->offp; + dp = backref(m, sp, stop, ss+1, stopst, lev, rec); + if (dp != NULL) + return(dp); + m->pmatch[i].rm_so = offsave; + return(NULL); + break; + case ORPAREN: /* must undo assignment if rest fails */ + i = OPND(s); + assert(0 < i && i <= m->g->nsub); + offsave = m->pmatch[i].rm_eo; + m->pmatch[i].rm_eo = sp - m->offp; + dp = backref(m, sp, stop, ss+1, stopst, lev, rec); + if (dp != NULL) + return(dp); + m->pmatch[i].rm_eo = offsave; + return(NULL); + break; + default: /* uh oh */ + assert(nope); + break; + } + + /* "can't happen" */ + assert(nope); + /* NOTREACHED */ + return NULL; +} + +/* + - fast - step through the string at top speed + */ +static char * /* where tentative match ended, or NULL */ +fast(struct match *m, char *start, char *stop, sopno startst, sopno stopst) +{ + states st = m->st; + states fresh = m->fresh; + states tmp = m->tmp; + char *p = start; + int c = (start == m->beginp) ? OUT : *(start-1); + int lastc; /* previous c */ + int flagch; + int i; + char *coldp; /* last p after which no match was underway */ + + CLEAR(st); + SET1(st, startst); + st = step(m->g, startst, stopst, st, NOTHING, st); + ASSIGN(fresh, st); + SP("start", st, *p); + coldp = NULL; + for (;;) { + /* next character */ + lastc = c; + c = (p == m->endp) ? OUT : *p; + if (EQ(st, fresh)) + coldp = p; + + /* is there an EOL and/or BOL between lastc and c? */ + flagch = '\0'; + i = 0; + if ( (lastc == '\n' && m->g->cflags®_NEWLINE) || + (lastc == OUT && !(m->eflags®_NOTBOL)) ) { + flagch = BOL; + i = m->g->nbol; + } + if ( (c == '\n' && m->g->cflags®_NEWLINE) || + (c == OUT && !(m->eflags®_NOTEOL)) ) { + flagch = (flagch == BOL) ? BOLEOL : EOL; + i += m->g->neol; + } + if (i != 0) { + for (; i > 0; i--) + st = step(m->g, startst, stopst, st, flagch, st); + SP("boleol", st, c); + } + + /* how about a word boundary? */ + if ( (flagch == BOL || (lastc != OUT && !ISWORD(lastc))) && + (c != OUT && ISWORD(c)) ) { + flagch = BOW; + } + if ( (lastc != OUT && ISWORD(lastc)) && + (flagch == EOL || (c != OUT && !ISWORD(c))) ) { + flagch = EOW; + } + if (flagch == BOW || flagch == EOW) { + st = step(m->g, startst, stopst, st, flagch, st); + SP("boweow", st, c); + } + + /* are we done? */ + if (ISSET(st, stopst) || p == stop) + break; /* NOTE BREAK OUT */ + + /* no, we must deal with this character */ + ASSIGN(tmp, st); + ASSIGN(st, fresh); + assert(c != OUT); + st = step(m->g, startst, stopst, tmp, c, st); + SP("aft", st, c); + assert(EQ(step(m->g, startst, stopst, st, NOTHING, st), st)); + p++; + } + + assert(coldp != NULL); + m->coldp = coldp; + if (ISSET(st, stopst)) + return(p+1); + else + return(NULL); +} + +/* + - slow - step through the string more deliberately + */ +static char * /* where it ended */ +slow(struct match *m, char *start, char *stop, sopno startst, sopno stopst) +{ + states st = m->st; + states empty = m->empty; + states tmp = m->tmp; + char *p = start; + int c = (start == m->beginp) ? OUT : *(start-1); + int lastc; /* previous c */ + int flagch; + int i; + char *matchp; /* last p at which a match ended */ + + AT("slow", start, stop, startst, stopst); + CLEAR(st); + SET1(st, startst); + SP("sstart", st, *p); + st = step(m->g, startst, stopst, st, NOTHING, st); + matchp = NULL; + for (;;) { + /* next character */ + lastc = c; + c = (p == m->endp) ? OUT : *p; + + /* is there an EOL and/or BOL between lastc and c? */ + flagch = '\0'; + i = 0; + if ( (lastc == '\n' && m->g->cflags®_NEWLINE) || + (lastc == OUT && !(m->eflags®_NOTBOL)) ) { + flagch = BOL; + i = m->g->nbol; + } + if ( (c == '\n' && m->g->cflags®_NEWLINE) || + (c == OUT && !(m->eflags®_NOTEOL)) ) { + flagch = (flagch == BOL) ? BOLEOL : EOL; + i += m->g->neol; + } + if (i != 0) { + for (; i > 0; i--) + st = step(m->g, startst, stopst, st, flagch, st); + SP("sboleol", st, c); + } + + /* how about a word boundary? */ + if ( (flagch == BOL || (lastc != OUT && !ISWORD(lastc))) && + (c != OUT && ISWORD(c)) ) { + flagch = BOW; + } + if ( (lastc != OUT && ISWORD(lastc)) && + (flagch == EOL || (c != OUT && !ISWORD(c))) ) { + flagch = EOW; + } + if (flagch == BOW || flagch == EOW) { + st = step(m->g, startst, stopst, st, flagch, st); + SP("sboweow", st, c); + } + + /* are we done? */ + if (ISSET(st, stopst)) + matchp = p; + if (EQ(st, empty) || p == stop) + break; /* NOTE BREAK OUT */ + + /* no, we must deal with this character */ + ASSIGN(tmp, st); + ASSIGN(st, empty); + assert(c != OUT); + st = step(m->g, startst, stopst, tmp, c, st); + SP("saft", st, c); + assert(EQ(step(m->g, startst, stopst, st, NOTHING, st), st)); + p++; + } + + return(matchp); +} + + +/* + - step - map set of states reachable before char to set reachable after + */ +static states +step(struct re_guts *g, + sopno start, /* start state within strip */ + sopno stop, /* state after stop state within strip */ + states bef, /* states reachable before */ + int ch, /* character or NONCHAR code */ + states aft) /* states already known reachable after */ +{ + cset *cs; + sop s; + sopno pc; + onestate here; /* note, macros know this name */ + sopno look; + int i; + + for (pc = start, INIT(here, pc); pc != stop; pc++, INC(here)) { + s = g->strip[pc]; + switch (OP(s)) { + case OEND: + assert(pc == stop-1); + break; + case OCHAR: + /* only characters can match */ + assert(!NONCHAR(ch) || ch != (char)OPND(s)); + if (ch == (char)OPND(s)) + FWD(aft, bef, 1); + break; + case OBOL: + if (ch == BOL || ch == BOLEOL) + FWD(aft, bef, 1); + break; + case OEOL: + if (ch == EOL || ch == BOLEOL) + FWD(aft, bef, 1); + break; + case OBOW: + if (ch == BOW) + FWD(aft, bef, 1); + break; + case OEOW: + if (ch == EOW) + FWD(aft, bef, 1); + break; + case OANY: + if (!NONCHAR(ch)) + FWD(aft, bef, 1); + break; + case OANYOF: + cs = &g->sets[OPND(s)]; + if (!NONCHAR(ch) && CHIN(cs, ch)) + FWD(aft, bef, 1); + break; + case OBACK_: /* ignored here */ + case O_BACK: + FWD(aft, aft, 1); + break; + case OPLUS_: /* forward, this is just an empty */ + FWD(aft, aft, 1); + break; + case O_PLUS: /* both forward and back */ + FWD(aft, aft, 1); + i = ISSETBACK(aft, OPND(s)); + BACK(aft, aft, OPND(s)); + if (!i && ISSETBACK(aft, OPND(s))) { + /* oho, must reconsider loop body */ + pc -= OPND(s) + 1; + INIT(here, pc); + } + break; + case OQUEST_: /* two branches, both forward */ + FWD(aft, aft, 1); + FWD(aft, aft, OPND(s)); + break; + case O_QUEST: /* just an empty */ + FWD(aft, aft, 1); + break; + case OLPAREN: /* not significant here */ + case ORPAREN: + FWD(aft, aft, 1); + break; + case OCH_: /* mark the first two branches */ + FWD(aft, aft, 1); + assert(OP(g->strip[pc+OPND(s)]) == OOR2); + FWD(aft, aft, OPND(s)); + break; + case OOR1: /* done a branch, find the O_CH */ + if (ISSTATEIN(aft, here)) { + for (look = 1; + OP(s = g->strip[pc+look]) != O_CH; + look += OPND(s)) + assert(OP(s) == OOR2); + FWD(aft, aft, look); + } + break; + case OOR2: /* propagate OCH_'s marking */ + FWD(aft, aft, 1); + if (OP(g->strip[pc+OPND(s)]) != O_CH) { + assert(OP(g->strip[pc+OPND(s)]) == OOR2); + FWD(aft, aft, OPND(s)); + } + break; + case O_CH: /* just empty */ + FWD(aft, aft, 1); + break; + default: /* ooooops... */ + assert(nope); + break; + } + } + + return(aft); +} + +#ifdef REDEBUG +/* + - print - print a set of states + */ +static void +print(struct match *m, char *caption, states st, int ch, FILE *d) +{ + struct re_guts *g = m->g; + int i; + int first = 1; + + if (!(m->eflags®_TRACE)) + return; + + (void)fprintf(d, "%s", caption); + if (ch != '\0') + (void)fprintf(d, " %s", pchar(ch)); + for (i = 0; i < g->nstates; i++) + if (ISSET(st, i)) { + (void)fprintf(d, "%s%d", (first) ? "\t" : ", ", i); + first = 0; + } + (void)fprintf(d, "\n"); +} + +/* + - at - print current situation + */ +static void +at(struct match *m, char *title, char *start, char *stop, sopno startst, + sopno stopst) +{ + if (!(m->eflags®_TRACE)) + return; + + (void)printf("%s %s-", title, pchar(*start)); + (void)printf("%s ", pchar(*stop)); + (void)printf("%ld-%ld\n", (long)startst, (long)stopst); +} + +#ifndef PCHARDONE +#define PCHARDONE /* never again */ +/* + - pchar - make a character printable + * + * Is this identical to regchar() over in debug.c? Well, yes. But a + * duplicate here avoids having a debugging-capable regexec.o tied to + * a matching debug.o, and this is convenient. It all disappears in + * the non-debug compilation anyway, so it doesn't matter much. + */ +static char * /* -> representation */ +pchar(int ch) +{ + static char pbuf[10]; + + if (isprint(ch) || ch == ' ') + (void)snprintf(pbuf, sizeof pbuf, "%c", ch); + else + (void)snprintf(pbuf, sizeof pbuf, "\\%o", ch); + return(pbuf); +} +#endif +#endif + +#undef matcher +#undef fast +#undef slow +#undef dissect +#undef backref +#undef step +#undef print +#undef at +#undef match +#undef nope diff --git a/libclamav/c++/llvm/lib/Support/regerror.c b/libclamav/c++/llvm/lib/Support/regerror.c new file mode 100644 index 000000000..1d67c9a2b --- /dev/null +++ b/libclamav/c++/llvm/lib/Support/regerror.c @@ -0,0 +1,135 @@ +/*- + * This code is derived from OpenBSD's libc/regex, original license follows: + * + * Copyright (c) 1992, 1993, 1994 Henry Spencer. + * Copyright (c) 1992, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Henry Spencer. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)regerror.c 8.4 (Berkeley) 3/20/94 + */ + +#include +#include +#include +#include +#include +#include +#include "regex_impl.h" + +#include "regutils.h" + +#ifdef _MSC_VER +#define snprintf _snprintf +#endif + +static const char *regatoi(const llvm_regex_t *, char *, int); + +static struct rerr { + int code; + const char *name; + const char *explain; +} rerrs[] = { + { REG_NOMATCH, "REG_NOMATCH", "llvm_regexec() failed to match" }, + { REG_BADPAT, "REG_BADPAT", "invalid regular expression" }, + { REG_ECOLLATE, "REG_ECOLLATE", "invalid collating element" }, + { REG_ECTYPE, "REG_ECTYPE", "invalid character class" }, + { REG_EESCAPE, "REG_EESCAPE", "trailing backslash (\\)" }, + { REG_ESUBREG, "REG_ESUBREG", "invalid backreference number" }, + { REG_EBRACK, "REG_EBRACK", "brackets ([ ]) not balanced" }, + { REG_EPAREN, "REG_EPAREN", "parentheses not balanced" }, + { REG_EBRACE, "REG_EBRACE", "braces not balanced" }, + { REG_BADBR, "REG_BADBR", "invalid repetition count(s)" }, + { REG_ERANGE, "REG_ERANGE", "invalid character range" }, + { REG_ESPACE, "REG_ESPACE", "out of memory" }, + { REG_BADRPT, "REG_BADRPT", "repetition-operator operand invalid" }, + { REG_EMPTY, "REG_EMPTY", "empty (sub)expression" }, + { REG_ASSERT, "REG_ASSERT", "\"can't happen\" -- you found a bug" }, + { REG_INVARG, "REG_INVARG", "invalid argument to regex routine" }, + { 0, "", "*** unknown regexp error code ***" } +}; + +/* + - llvm_regerror - the interface to error numbers + = extern size_t llvm_regerror(int, const llvm_regex_t *, char *, size_t); + */ +/* ARGSUSED */ +size_t +llvm_regerror(int errcode, const llvm_regex_t *preg, char *errbuf, size_t errbuf_size) +{ + struct rerr *r; + size_t len; + int target = errcode &~ REG_ITOA; + const char *s; + char convbuf[50]; + + if (errcode == REG_ATOI) + s = regatoi(preg, convbuf, sizeof convbuf); + else { + for (r = rerrs; r->code != 0; r++) + if (r->code == target) + break; + + if (errcode®_ITOA) { + if (r->code != 0) { + assert(strlen(r->name) < sizeof(convbuf)); + (void) llvm_strlcpy(convbuf, r->name, sizeof convbuf); + } else + (void)snprintf(convbuf, sizeof convbuf, + "REG_0x%x", target); + s = convbuf; + } else + s = r->explain; + } + + len = strlen(s) + 1; + if (errbuf_size > 0) { + llvm_strlcpy(errbuf, s, errbuf_size); + } + + return(len); +} + +/* + - regatoi - internal routine to implement REG_ATOI + */ +static const char * +regatoi(const llvm_regex_t *preg, char *localbuf, int localbufsize) +{ + struct rerr *r; + + for (r = rerrs; r->code != 0; r++) + if (strcmp(r->name, preg->re_endp) == 0) + break; + if (r->code == 0) + return("0"); + + (void)snprintf(localbuf, localbufsize, "%d", r->code); + return(localbuf); +} diff --git a/libclamav/c++/llvm/lib/Support/regex2.h b/libclamav/c++/llvm/lib/Support/regex2.h new file mode 100644 index 000000000..21659c344 --- /dev/null +++ b/libclamav/c++/llvm/lib/Support/regex2.h @@ -0,0 +1,157 @@ +/*- + * This code is derived from OpenBSD's libc/regex, original license follows: + * + * Copyright (c) 1992, 1993, 1994 Henry Spencer. + * Copyright (c) 1992, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Henry Spencer. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)regex2.h 8.4 (Berkeley) 3/20/94 + */ + +/* + * internals of regex_t + */ +#define MAGIC1 ((('r'^0200)<<8) | 'e') + +/* + * The internal representation is a *strip*, a sequence of + * operators ending with an endmarker. (Some terminology etc. is a + * historical relic of earlier versions which used multiple strips.) + * Certain oddities in the representation are there to permit running + * the machinery backwards; in particular, any deviation from sequential + * flow must be marked at both its source and its destination. Some + * fine points: + * + * - OPLUS_ and O_PLUS are *inside* the loop they create. + * - OQUEST_ and O_QUEST are *outside* the bypass they create. + * - OCH_ and O_CH are *outside* the multi-way branch they create, while + * OOR1 and OOR2 are respectively the end and the beginning of one of + * the branches. Note that there is an implicit OOR2 following OCH_ + * and an implicit OOR1 preceding O_CH. + * + * In state representations, an operator's bit is on to signify a state + * immediately *preceding* "execution" of that operator. + */ +typedef unsigned long sop; /* strip operator */ +typedef long sopno; +#define OPRMASK 0xf8000000LU +#define OPDMASK 0x07ffffffLU +#define OPSHIFT ((unsigned)27) +#define OP(n) ((n)&OPRMASK) +#define OPND(n) ((n)&OPDMASK) +#define SOP(op, opnd) ((op)|(opnd)) +/* operators meaning operand */ +/* (back, fwd are offsets) */ +#define OEND (1LU< uch [csetsize] */ + uch mask; /* bit within array */ + uch hash; /* hash code */ + size_t smultis; + char *multis; /* -> char[smulti] ab\0cd\0ef\0\0 */ +} cset; +/* note that CHadd and CHsub are unsafe, and CHIN doesn't yield 0/1 */ +#define CHadd(cs, c) ((cs)->ptr[(uch)(c)] |= (cs)->mask, (cs)->hash += (c)) +#define CHsub(cs, c) ((cs)->ptr[(uch)(c)] &= ~(cs)->mask, (cs)->hash -= (c)) +#define CHIN(cs, c) ((cs)->ptr[(uch)(c)] & (cs)->mask) +#define MCadd(p, cs, cp) mcadd(p, cs, cp) /* llvm_regcomp() internal fns */ +#define MCsub(p, cs, cp) mcsub(p, cs, cp) +#define MCin(p, cs, cp) mcin(p, cs, cp) + +/* stuff for character categories */ +typedef unsigned char cat_t; + +/* + * main compiled-expression structure + */ +struct re_guts { + int magic; +# define MAGIC2 ((('R'^0200)<<8)|'E') + sop *strip; /* malloced area for strip */ + int csetsize; /* number of bits in a cset vector */ + int ncsets; /* number of csets in use */ + cset *sets; /* -> cset [ncsets] */ + uch *setbits; /* -> uch[csetsize][ncsets/CHAR_BIT] */ + int cflags; /* copy of llvm_regcomp() cflags argument */ + sopno nstates; /* = number of sops */ + sopno firststate; /* the initial OEND (normally 0) */ + sopno laststate; /* the final OEND */ + int iflags; /* internal flags */ +# define USEBOL 01 /* used ^ */ +# define USEEOL 02 /* used $ */ +# define REGEX_BAD 04 /* something wrong */ + int nbol; /* number of ^ used */ + int neol; /* number of $ used */ + int ncategories; /* how many character categories */ + cat_t *categories; /* ->catspace[-CHAR_MIN] */ + char *must; /* match must contain this string */ + int mlen; /* length of must */ + size_t nsub; /* copy of re_nsub */ + int backrefs; /* does it use back references? */ + sopno nplus; /* how deep does it nest +s? */ + /* catspace must be last */ + cat_t catspace[1]; /* actually [NC] */ +}; + +/* misc utilities */ +#define OUT (CHAR_MAX+1) /* a non-character value */ +#define ISWORD(c) (isalnum(c&0xff) || (c) == '_') diff --git a/libclamav/c++/llvm/lib/Support/regex_impl.h b/libclamav/c++/llvm/lib/Support/regex_impl.h new file mode 100644 index 000000000..f8296c9ff --- /dev/null +++ b/libclamav/c++/llvm/lib/Support/regex_impl.h @@ -0,0 +1,108 @@ +/*- + * This code is derived from OpenBSD's libc/regex, original license follows: + * + * Copyright (c) 1992 Henry Spencer. + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Henry Spencer of the University of Toronto. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)regex.h 8.1 (Berkeley) 6/2/93 + */ + +#ifndef _REGEX_H_ +#define _REGEX_H_ + +#include +typedef off_t llvm_regoff_t; +typedef struct { + llvm_regoff_t rm_so; /* start of match */ + llvm_regoff_t rm_eo; /* end of match */ +} llvm_regmatch_t; + +typedef struct llvm_regex { + int re_magic; + size_t re_nsub; /* number of parenthesized subexpressions */ + const char *re_endp; /* end pointer for REG_PEND */ + struct re_guts *re_g; /* none of your business :-) */ +} llvm_regex_t; + +/* llvm_regcomp() flags */ +#define REG_BASIC 0000 +#define REG_EXTENDED 0001 +#define REG_ICASE 0002 +#define REG_NOSUB 0004 +#define REG_NEWLINE 0010 +#define REG_NOSPEC 0020 +#define REG_PEND 0040 +#define REG_DUMP 0200 + +/* llvm_regerror() flags */ +#define REG_NOMATCH 1 +#define REG_BADPAT 2 +#define REG_ECOLLATE 3 +#define REG_ECTYPE 4 +#define REG_EESCAPE 5 +#define REG_ESUBREG 6 +#define REG_EBRACK 7 +#define REG_EPAREN 8 +#define REG_EBRACE 9 +#define REG_BADBR 10 +#define REG_ERANGE 11 +#define REG_ESPACE 12 +#define REG_BADRPT 13 +#define REG_EMPTY 14 +#define REG_ASSERT 15 +#define REG_INVARG 16 +#define REG_ATOI 255 /* convert name to number (!) */ +#define REG_ITOA 0400 /* convert number to name (!) */ + +/* llvm_regexec() flags */ +#define REG_NOTBOL 00001 +#define REG_NOTEOL 00002 +#define REG_STARTEND 00004 +#define REG_TRACE 00400 /* tracing of execution */ +#define REG_LARGE 01000 /* force large representation */ +#define REG_BACKR 02000 /* force use of backref code */ + +#ifdef __cplusplus +extern "C" { +#endif + +int llvm_regcomp(llvm_regex_t *, const char *, int); +size_t llvm_regerror(int, const llvm_regex_t *, char *, size_t); +int llvm_regexec(const llvm_regex_t *, const char *, size_t, + llvm_regmatch_t [], int); +void llvm_regfree(llvm_regex_t *); +size_t llvm_strlcpy(char *dst, const char *src, size_t siz); + +#ifdef __cplusplus +} +#endif + +#endif /* !_REGEX_H_ */ diff --git a/libclamav/c++/llvm/lib/Support/regexec.c b/libclamav/c++/llvm/lib/Support/regexec.c new file mode 100644 index 000000000..7d70f6e16 --- /dev/null +++ b/libclamav/c++/llvm/lib/Support/regexec.c @@ -0,0 +1,161 @@ +/*- + * This code is derived from OpenBSD's libc/regex, original license follows: + * + * Copyright (c) 1992, 1993, 1994 Henry Spencer. + * Copyright (c) 1992, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Henry Spencer. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)regexec.c 8.3 (Berkeley) 3/20/94 + */ + +/* + * the outer shell of llvm_regexec() + * + * This file includes engine.inc *twice*, after muchos fiddling with the + * macros that code uses. This lets the same code operate on two different + * representations for state sets. + */ +#include +#include +#include +#include +#include +#include +#include "regex_impl.h" + +#include "regutils.h" +#include "regex2.h" + +/* macros for manipulating states, small version */ +#define states long +#define states1 states /* for later use in llvm_regexec() decision */ +#define CLEAR(v) ((v) = 0) +#define SET0(v, n) ((v) &= ~((unsigned long)1 << (n))) +#define SET1(v, n) ((v) |= (unsigned long)1 << (n)) +#define ISSET(v, n) (((v) & ((unsigned long)1 << (n))) != 0) +#define ASSIGN(d, s) ((d) = (s)) +#define EQ(a, b) ((a) == (b)) +#define STATEVARS long dummy /* dummy version */ +#define STATESETUP(m, n) /* nothing */ +#define STATETEARDOWN(m) /* nothing */ +#define SETUP(v) ((v) = 0) +#define onestate long +#define INIT(o, n) ((o) = (unsigned long)1 << (n)) +#define INC(o) ((o) <<= 1) +#define ISSTATEIN(v, o) (((v) & (o)) != 0) +/* some abbreviations; note that some of these know variable names! */ +/* do "if I'm here, I can also be there" etc without branches */ +#define FWD(dst, src, n) ((dst) |= ((unsigned long)(src)&(here)) << (n)) +#define BACK(dst, src, n) ((dst) |= ((unsigned long)(src)&(here)) >> (n)) +#define ISSETBACK(v, n) (((v) & ((unsigned long)here >> (n))) != 0) +/* function names */ +#define SNAMES /* engine.inc looks after details */ + +#include "regengine.inc" + +/* now undo things */ +#undef states +#undef CLEAR +#undef SET0 +#undef SET1 +#undef ISSET +#undef ASSIGN +#undef EQ +#undef STATEVARS +#undef STATESETUP +#undef STATETEARDOWN +#undef SETUP +#undef onestate +#undef INIT +#undef INC +#undef ISSTATEIN +#undef FWD +#undef BACK +#undef ISSETBACK +#undef SNAMES + +/* macros for manipulating states, large version */ +#define states char * +#define CLEAR(v) memset(v, 0, m->g->nstates) +#define SET0(v, n) ((v)[n] = 0) +#define SET1(v, n) ((v)[n] = 1) +#define ISSET(v, n) ((v)[n]) +#define ASSIGN(d, s) memmove(d, s, m->g->nstates) +#define EQ(a, b) (memcmp(a, b, m->g->nstates) == 0) +#define STATEVARS long vn; char *space +#define STATESETUP(m, nv) { (m)->space = malloc((nv)*(m)->g->nstates); \ + if ((m)->space == NULL) return(REG_ESPACE); \ + (m)->vn = 0; } +#define STATETEARDOWN(m) { free((m)->space); } +#define SETUP(v) ((v) = &m->space[m->vn++ * m->g->nstates]) +#define onestate long +#define INIT(o, n) ((o) = (n)) +#define INC(o) ((o)++) +#define ISSTATEIN(v, o) ((v)[o]) +/* some abbreviations; note that some of these know variable names! */ +/* do "if I'm here, I can also be there" etc without branches */ +#define FWD(dst, src, n) ((dst)[here+(n)] |= (src)[here]) +#define BACK(dst, src, n) ((dst)[here-(n)] |= (src)[here]) +#define ISSETBACK(v, n) ((v)[here - (n)]) +/* function names */ +#define LNAMES /* flag */ + +#include "regengine.inc" + +/* + - llvm_regexec - interface for matching + * + * We put this here so we can exploit knowledge of the state representation + * when choosing which matcher to call. Also, by this point the matchers + * have been prototyped. + */ +int /* 0 success, REG_NOMATCH failure */ +llvm_regexec(const llvm_regex_t *preg, const char *string, size_t nmatch, + llvm_regmatch_t pmatch[], int eflags) +{ + struct re_guts *g = preg->re_g; +#ifdef REDEBUG +# define GOODFLAGS(f) (f) +#else +# define GOODFLAGS(f) ((f)&(REG_NOTBOL|REG_NOTEOL|REG_STARTEND)) +#endif + + if (preg->re_magic != MAGIC1 || g->magic != MAGIC2) + return(REG_BADPAT); + assert(!(g->iflags®EX_BAD)); + if (g->iflags®EX_BAD) /* backstop for no-debug case */ + return(REG_BADPAT); + eflags = GOODFLAGS(eflags); + + if (g->nstates <= (long)(CHAR_BIT*sizeof(states1)) && !(eflags®_LARGE)) + return(smatcher(g, (char *)string, nmatch, pmatch, eflags)); + else + return(lmatcher(g, (char *)string, nmatch, pmatch, eflags)); +} diff --git a/libclamav/c++/llvm/lib/Support/regfree.c b/libclamav/c++/llvm/lib/Support/regfree.c new file mode 100644 index 000000000..dc2b4af90 --- /dev/null +++ b/libclamav/c++/llvm/lib/Support/regfree.c @@ -0,0 +1,72 @@ +/*- + * This code is derived from OpenBSD's libc/regex, original license follows: + * + * Copyright (c) 1992, 1993, 1994 Henry Spencer. + * Copyright (c) 1992, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Henry Spencer. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)regfree.c 8.3 (Berkeley) 3/20/94 + */ + +#include +#include +#include +#include "regex_impl.h" + +#include "regutils.h" +#include "regex2.h" + +/* + - llvm_regfree - free everything + */ +void +llvm_regfree(llvm_regex_t *preg) +{ + struct re_guts *g; + + if (preg->re_magic != MAGIC1) /* oops */ + return; /* nice to complain, but hard */ + + g = preg->re_g; + if (g == NULL || g->magic != MAGIC2) /* oops again */ + return; + preg->re_magic = 0; /* mark it invalid */ + g->magic = 0; /* mark it invalid */ + + if (g->strip != NULL) + free((char *)g->strip); + if (g->sets != NULL) + free((char *)g->sets); + if (g->setbits != NULL) + free((char *)g->setbits); + if (g->must != NULL) + free(g->must); + free((char *)g); +} diff --git a/libclamav/c++/llvm/lib/Support/regstrlcpy.c b/libclamav/c++/llvm/lib/Support/regstrlcpy.c new file mode 100644 index 000000000..8b68afdf7 --- /dev/null +++ b/libclamav/c++/llvm/lib/Support/regstrlcpy.c @@ -0,0 +1,52 @@ +/* + * This code is derived from OpenBSD's libc, original license follows: + * + * Copyright (c) 1998 Todd C. Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include + +#include "regex_impl.h" +/* + * Copy src to string dst of size siz. At most siz-1 characters + * will be copied. Always NUL terminates (unless siz == 0). + * Returns strlen(src); if retval >= siz, truncation occurred. + */ +size_t +llvm_strlcpy(char *dst, const char *src, size_t siz) +{ + char *d = dst; + const char *s = src; + size_t n = siz; + + /* Copy as many bytes as will fit */ + if (n != 0) { + while (--n != 0) { + if ((*d++ = *s++) == '\0') + break; + } + } + + /* Not enough room in dst, add NUL and traverse rest of src */ + if (n == 0) { + if (siz != 0) + *d = '\0'; /* NUL-terminate dst */ + while (*s++) + ; + } + + return(s - src - 1); /* count does not include NUL */ +} diff --git a/libclamav/c++/llvm/lib/Support/regutils.h b/libclamav/c++/llvm/lib/Support/regutils.h new file mode 100644 index 000000000..d0ee100a3 --- /dev/null +++ b/libclamav/c++/llvm/lib/Support/regutils.h @@ -0,0 +1,53 @@ +/*- + * This code is derived from OpenBSD's libc/regex, original license follows: + * + * Copyright (c) 1992, 1993, 1994 Henry Spencer. + * Copyright (c) 1992, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Henry Spencer. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)utils.h 8.3 (Berkeley) 3/20/94 + */ + +/* utility definitions */ +#define NC (CHAR_MAX - CHAR_MIN + 1) +typedef unsigned char uch; + +/* switch off assertions (if not already off) if no REDEBUG */ +#ifndef REDEBUG +#ifndef NDEBUG +#define NDEBUG /* no assertions please */ +#endif +#endif +#include + +/* for old systems with bcopy() but no memmove() */ +#ifdef USEBCOPY +#define memmove(d, s, c) bcopy(s, d, c) +#endif diff --git a/libclamav/c++/llvm/lib/System/Alarm.cpp b/libclamav/c++/llvm/lib/System/Alarm.cpp new file mode 100644 index 000000000..0014ca716 --- /dev/null +++ b/libclamav/c++/llvm/lib/System/Alarm.cpp @@ -0,0 +1,33 @@ +//===- Alarm.cpp - Alarm Generation Support ---------------------*- 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 the Alarm functionality +// +//===----------------------------------------------------------------------===// + +#include "llvm/System/Alarm.h" +#include "llvm/Config/config.h" + +namespace llvm { +using namespace sys; + +//===----------------------------------------------------------------------===// +//=== WARNING: Implementation here must contain only TRULY operating system +//=== independent code. +//===----------------------------------------------------------------------===// + +} + +// Include the platform-specific parts of this class. +#ifdef LLVM_ON_UNIX +#include "Unix/Alarm.inc" +#endif +#ifdef LLVM_ON_WIN32 +#include "Win32/Alarm.inc" +#endif diff --git a/libclamav/c++/llvm/lib/System/Atomic.cpp b/libclamav/c++/llvm/lib/System/Atomic.cpp new file mode 100644 index 000000000..f9b55a186 --- /dev/null +++ b/libclamav/c++/llvm/lib/System/Atomic.cpp @@ -0,0 +1,112 @@ +//===-- Atomic.cpp - Atomic Operations --------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This header file implements atomic operations. +// +//===----------------------------------------------------------------------===// + +#include "llvm/System/Atomic.h" +#include "llvm/Config/config.h" + +using namespace llvm; + +#if defined(_MSC_VER) +#include +#undef MemoryFence +#endif + +void sys::MemoryFence() { +#if LLVM_MULTITHREADED==0 + return; +#else +# if defined(__GNUC__) + __sync_synchronize(); +# elif defined(_MSC_VER) + MemoryBarrier(); +# else +# error No memory fence implementation for your platform! +# endif +#endif +} + +sys::cas_flag sys::CompareAndSwap(volatile sys::cas_flag* ptr, + sys::cas_flag new_value, + sys::cas_flag old_value) { +#if LLVM_MULTITHREADED==0 + sys::cas_flag result = *ptr; + if (result == old_value) + *ptr = new_value; + return result; +#elif defined(__GNUC__) + return __sync_val_compare_and_swap(ptr, old_value, new_value); +#elif defined(_MSC_VER) + return InterlockedCompareExchange(ptr, new_value, old_value); +#else +# error No compare-and-swap implementation for your platform! +#endif +} + +sys::cas_flag sys::AtomicIncrement(volatile sys::cas_flag* ptr) { +#if LLVM_MULTITHREADED==0 + ++(*ptr); + return *ptr; +#elif defined(__GNUC__) + return __sync_add_and_fetch(ptr, 1); +#elif defined(_MSC_VER) + return InterlockedIncrement(ptr); +#else +# error No atomic increment implementation for your platform! +#endif +} + +sys::cas_flag sys::AtomicDecrement(volatile sys::cas_flag* ptr) { +#if LLVM_MULTITHREADED==0 + --(*ptr); + return *ptr; +#elif defined(__GNUC__) + return __sync_sub_and_fetch(ptr, 1); +#elif defined(_MSC_VER) + return InterlockedDecrement(ptr); +#else +# error No atomic decrement implementation for your platform! +#endif +} + +sys::cas_flag sys::AtomicAdd(volatile sys::cas_flag* ptr, sys::cas_flag val) { +#if LLVM_MULTITHREADED==0 + *ptr += val; + return *ptr; +#elif defined(__GNUC__) + return __sync_add_and_fetch(ptr, val); +#elif defined(_MSC_VER) + return InterlockedAdd(ptr, val); +#else +# error No atomic add implementation for your platform! +#endif +} + +sys::cas_flag sys::AtomicMul(volatile sys::cas_flag* ptr, sys::cas_flag val) { + sys::cas_flag original, result; + do { + original = *ptr; + result = original * val; + } while (sys::CompareAndSwap(ptr, result, original) != original); + + return result; +} + +sys::cas_flag sys::AtomicDiv(volatile sys::cas_flag* ptr, sys::cas_flag val) { + sys::cas_flag original, result; + do { + original = *ptr; + result = original / val; + } while (sys::CompareAndSwap(ptr, result, original) != original); + + return result; +} diff --git a/libclamav/c++/llvm/lib/System/CMakeLists.txt b/libclamav/c++/llvm/lib/System/CMakeLists.txt new file mode 100644 index 000000000..a56a1f78b --- /dev/null +++ b/libclamav/c++/llvm/lib/System/CMakeLists.txt @@ -0,0 +1,46 @@ +add_llvm_library(LLVMSystem + Alarm.cpp + Atomic.cpp + Disassembler.cpp + DynamicLibrary.cpp + Errno.cpp + Host.cpp + IncludeFile.cpp + Memory.cpp + Mutex.cpp + Path.cpp + Process.cpp + Program.cpp + RWMutex.cpp + Signals.cpp + ThreadLocal.cpp + Threading.cpp + TimeValue.cpp + Unix/Alarm.inc + Unix/Host.inc + Unix/Memory.inc + Unix/Mutex.inc + Unix/Path.inc + Unix/Process.inc + Unix/Program.inc + Unix/RWMutex.inc + Unix/Signals.inc + Unix/ThreadLocal.inc + Unix/TimeValue.inc + Win32/Alarm.inc + Win32/DynamicLibrary.inc + Win32/Host.inc + Win32/Memory.inc + Win32/Mutex.inc + Win32/Path.inc + Win32/Process.inc + Win32/Program.inc + Win32/RWMutex.inc + Win32/Signals.inc + Win32/ThreadLocal.inc + Win32/TimeValue.inc + ) + +if( BUILD_SHARED_LIBS AND NOT WIN32 ) + target_link_libraries(LLVMSystem ${CMAKE_DL_LIBS}) +endif() diff --git a/libclamav/c++/llvm/lib/System/Disassembler.cpp b/libclamav/c++/llvm/lib/System/Disassembler.cpp new file mode 100644 index 000000000..bad427a58 --- /dev/null +++ b/libclamav/c++/llvm/lib/System/Disassembler.cpp @@ -0,0 +1,79 @@ +//===- lib/System/Disassembler.cpp ------------------------------*- 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 the necessary glue to call external disassembler +// libraries. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Config/config.h" +#include "llvm/System/Disassembler.h" + +#include +#include +#include +#include + +#if USE_UDIS86 +#include +#endif + +using namespace llvm; + +bool llvm::sys::hasDisassembler() +{ +#if defined (__i386__) || defined (__amd64__) || defined (__x86_64__) + // We have option to enable udis86 library. +# if USE_UDIS86 + return true; +#else + return false; +#endif +#else + return false; +#endif +} + +std::string llvm::sys::disassembleBuffer(uint8_t* start, size_t length, + uint64_t pc) { + std::stringstream res; + +#if defined (__i386__) || defined (__amd64__) || defined (__x86_64__) + unsigned bits; +# if defined(__i386__) + bits = 32; +# else + bits = 64; +# endif + +# if USE_UDIS86 + ud_t ud_obj; + + ud_init(&ud_obj); + ud_set_input_buffer(&ud_obj, start, length); + ud_set_mode(&ud_obj, bits); + ud_set_pc(&ud_obj, pc); + ud_set_syntax(&ud_obj, UD_SYN_ATT); + + res << std::setbase(16) + << std::setw(bits/4); + + while (ud_disassemble(&ud_obj)) { + res << ud_insn_off(&ud_obj) << ":\t" << ud_insn_asm(&ud_obj) << "\n"; + } +# else + res << "No disassembler available. See configure help for options.\n"; +# endif + +#else + res << "No disassembler available. See configure help for options.\n"; +#endif + + return res.str(); +} diff --git a/libclamav/c++/llvm/lib/System/DynamicLibrary.cpp b/libclamav/c++/llvm/lib/System/DynamicLibrary.cpp new file mode 100644 index 000000000..7eb9f5f3e --- /dev/null +++ b/libclamav/c++/llvm/lib/System/DynamicLibrary.cpp @@ -0,0 +1,165 @@ +//===-- DynamicLibrary.cpp - Runtime link/load libraries --------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This header file implements the operating system DynamicLibrary concept. +// +// FIXME: This file leaks the ExplicitSymbols and OpenedHandles vector, and is +// not thread safe! +// +//===----------------------------------------------------------------------===// + +#include "llvm/System/DynamicLibrary.h" +#include "llvm/Config/config.h" +#include +#include +#include +#include + +// Collection of symbol name/value pairs to be searched prior to any libraries. +static std::map *ExplicitSymbols = 0; + +static struct ExplicitSymbolsDeleter { + ~ExplicitSymbolsDeleter() { + if (ExplicitSymbols) + delete ExplicitSymbols; + } +} Dummy; + +void llvm::sys::DynamicLibrary::AddSymbol(const char* symbolName, + void *symbolValue) { + if (ExplicitSymbols == 0) + ExplicitSymbols = new std::map(); + (*ExplicitSymbols)[symbolName] = symbolValue; +} + +#ifdef LLVM_ON_WIN32 + +#include "Win32/DynamicLibrary.inc" + +#else + +#include +using namespace llvm; +using namespace llvm::sys; + +//===----------------------------------------------------------------------===// +//=== WARNING: Implementation here must contain only TRULY operating system +//=== independent code. +//===----------------------------------------------------------------------===// + +static std::vector *OpenedHandles = 0; + + +bool DynamicLibrary::LoadLibraryPermanently(const char *Filename, + std::string *ErrMsg) { + void *H = dlopen(Filename, RTLD_LAZY|RTLD_GLOBAL); + if (H == 0) { + if (ErrMsg) *ErrMsg = dlerror(); + return true; + } + if (OpenedHandles == 0) + OpenedHandles = new std::vector(); + OpenedHandles->push_back(H); + return false; +} + +void* DynamicLibrary::SearchForAddressOfSymbol(const char* symbolName) { + // First check symbols added via AddSymbol(). + if (ExplicitSymbols) { + std::map::iterator I = + ExplicitSymbols->find(symbolName); + std::map::iterator E = ExplicitSymbols->end(); + + if (I != E) + return I->second; + } + + // Now search the libraries. + if (OpenedHandles) { + for (std::vector::iterator I = OpenedHandles->begin(), + E = OpenedHandles->end(); I != E; ++I) { + //lt_ptr ptr = lt_dlsym(*I, symbolName); + void *ptr = dlsym(*I, symbolName); + if (ptr) { + return ptr; + } + } + } + +#define EXPLICIT_SYMBOL(SYM) \ + extern void *SYM; if (!strcmp(symbolName, #SYM)) return &SYM + + // If this is darwin, it has some funky issues, try to solve them here. Some + // important symbols are marked 'private external' which doesn't allow + // SearchForAddressOfSymbol to find them. As such, we special case them here, + // there is only a small handful of them. + +#ifdef __APPLE__ + { + EXPLICIT_SYMBOL(__ashldi3); + EXPLICIT_SYMBOL(__ashrdi3); + EXPLICIT_SYMBOL(__cmpdi2); + EXPLICIT_SYMBOL(__divdi3); + EXPLICIT_SYMBOL(__eprintf); + EXPLICIT_SYMBOL(__fixdfdi); + EXPLICIT_SYMBOL(__fixsfdi); + EXPLICIT_SYMBOL(__fixunsdfdi); + EXPLICIT_SYMBOL(__fixunssfdi); + EXPLICIT_SYMBOL(__floatdidf); + EXPLICIT_SYMBOL(__floatdisf); + EXPLICIT_SYMBOL(__lshrdi3); + EXPLICIT_SYMBOL(__moddi3); + EXPLICIT_SYMBOL(__udivdi3); + EXPLICIT_SYMBOL(__umoddi3); + } +#endif + +#ifdef __CYGWIN__ + { + EXPLICIT_SYMBOL(_alloca); + EXPLICIT_SYMBOL(__main); + } +#endif + +#undef EXPLICIT_SYMBOL + +// This macro returns the address of a well-known, explicit symbol +#define EXPLICIT_SYMBOL(SYM) \ + if (!strcmp(symbolName, #SYM)) return &SYM + +// On linux we have a weird situation. The stderr/out/in symbols are both +// macros and global variables because of standards requirements. So, we +// boldly use the EXPLICIT_SYMBOL macro without checking for a #define first. +#if defined(__linux__) + { + EXPLICIT_SYMBOL(stderr); + EXPLICIT_SYMBOL(stdout); + EXPLICIT_SYMBOL(stdin); + } +#else + // For everything else, we want to check to make sure the symbol isn't defined + // as a macro before using EXPLICIT_SYMBOL. + { +#ifndef stdin + EXPLICIT_SYMBOL(stdin); +#endif +#ifndef stdout + EXPLICIT_SYMBOL(stdout); +#endif +#ifndef stderr + EXPLICIT_SYMBOL(stderr); +#endif + } +#endif +#undef EXPLICIT_SYMBOL + + return 0; +} + +#endif // LLVM_ON_WIN32 diff --git a/libclamav/c++/llvm/lib/System/Errno.cpp b/libclamav/c++/llvm/lib/System/Errno.cpp new file mode 100644 index 000000000..68f66f6e4 --- /dev/null +++ b/libclamav/c++/llvm/lib/System/Errno.cpp @@ -0,0 +1,74 @@ +//===- Errno.cpp - errno support --------------------------------*- 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 the errno wrappers. +// +//===----------------------------------------------------------------------===// + +#include "llvm/System/Errno.h" +#include "llvm/Config/config.h" // Get autoconf configuration settings + +#if HAVE_STRING_H +#include + +#if HAVE_ERRNO_H +#include +#endif + +//===----------------------------------------------------------------------===// +//=== WARNING: Implementation here must contain only TRULY operating system +//=== independent code. +//===----------------------------------------------------------------------===// + +namespace llvm { +namespace sys { + +#if HAVE_ERRNO_H +std::string StrError() { + return StrError(errno); +} +#endif // HAVE_ERRNO_H + +std::string StrError(int errnum) { + const int MaxErrStrLen = 2000; + char buffer[MaxErrStrLen]; + buffer[0] = '\0'; + char* str = buffer; +#ifdef HAVE_STRERROR_R + // strerror_r is thread-safe. + if (errnum) +# if defined(__GLIBC__) && defined(_GNU_SOURCE) + // glibc defines its own incompatible version of strerror_r + // which may not use the buffer supplied. + str = strerror_r(errnum,buffer,MaxErrStrLen-1); +# else + strerror_r(errnum,buffer,MaxErrStrLen-1); +# endif +#elif defined(HAVE_STRERROR_S) // Windows. + if (errnum) + strerror_s(buffer, errnum); +#elif defined(HAVE_STRERROR) + // Copy the thread un-safe result of strerror into + // the buffer as fast as possible to minimize impact + // of collision of strerror in multiple threads. + if (errnum) + strncpy(buffer,strerror(errnum),MaxErrStrLen-1); + buffer[MaxErrStrLen-1] = '\0'; +#else + // Strange that this system doesn't even have strerror + // but, oh well, just use a generic message + sprintf(buffer, "Error #%d", errnum); +#endif + return str; +} + +} // namespace sys +} // namespace llvm + +#endif // HAVE_STRING_H diff --git a/libclamav/c++/llvm/lib/System/Host.cpp b/libclamav/c++/llvm/lib/System/Host.cpp new file mode 100644 index 000000000..e11269834 --- /dev/null +++ b/libclamav/c++/llvm/lib/System/Host.cpp @@ -0,0 +1,301 @@ +//===-- Host.cpp - Implement OS Host Concept --------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This header file implements the operating system Host concept. +// +//===----------------------------------------------------------------------===// + +#include "llvm/System/Host.h" +#include "llvm/Config/config.h" +#include + +// Include the platform-specific parts of this class. +#ifdef LLVM_ON_UNIX +#include "Unix/Host.inc" +#endif +#ifdef LLVM_ON_WIN32 +#include "Win32/Host.inc" +#endif +#ifdef _MSC_VER +#include +#endif + +//===----------------------------------------------------------------------===// +// +// Implementations of the CPU detection routines +// +//===----------------------------------------------------------------------===// + +using namespace llvm; + +#if defined(i386) || defined(__i386__) || defined(__x86__) || defined(_M_IX86)\ + || defined(__x86_64__) || defined(_M_AMD64) || defined (_M_X64) + +/// GetX86CpuIDAndInfo - Execute the specified cpuid and return the 4 values in the +/// specified arguments. If we can't run cpuid on the host, return true. +static bool GetX86CpuIDAndInfo(unsigned value, unsigned *rEAX, + unsigned *rEBX, unsigned *rECX, unsigned *rEDX) { +#if defined(__x86_64__) || defined(_M_AMD64) || defined (_M_X64) + #if defined(__GNUC__) + // gcc doesn't know cpuid would clobber ebx/rbx. Preseve it manually. + asm ("movq\t%%rbx, %%rsi\n\t" + "cpuid\n\t" + "xchgq\t%%rbx, %%rsi\n\t" + : "=a" (*rEAX), + "=S" (*rEBX), + "=c" (*rECX), + "=d" (*rEDX) + : "a" (value)); + return false; + #elif defined(_MSC_VER) + int registers[4]; + __cpuid(registers, value); + *rEAX = registers[0]; + *rEBX = registers[1]; + *rECX = registers[2]; + *rEDX = registers[3]; + return false; + #endif +#elif defined(i386) || defined(__i386__) || defined(__x86__) || defined(_M_IX86) + #if defined(__GNUC__) + asm ("movl\t%%ebx, %%esi\n\t" + "cpuid\n\t" + "xchgl\t%%ebx, %%esi\n\t" + : "=a" (*rEAX), + "=S" (*rEBX), + "=c" (*rECX), + "=d" (*rEDX) + : "a" (value)); + return false; + #elif defined(_MSC_VER) + __asm { + mov eax,value + cpuid + mov esi,rEAX + mov dword ptr [esi],eax + mov esi,rEBX + mov dword ptr [esi],ebx + mov esi,rECX + mov dword ptr [esi],ecx + mov esi,rEDX + mov dword ptr [esi],edx + } + return false; + #endif +#endif + return true; +} + +static void DetectX86FamilyModel(unsigned EAX, unsigned &Family, unsigned &Model) { + Family = (EAX >> 8) & 0xf; // Bits 8 - 11 + Model = (EAX >> 4) & 0xf; // Bits 4 - 7 + if (Family == 6 || Family == 0xf) { + if (Family == 0xf) + // Examine extended family ID if family ID is F. + Family += (EAX >> 20) & 0xff; // Bits 20 - 27 + // Examine extended model ID if family ID is 6 or F. + Model += ((EAX >> 16) & 0xf) << 4; // Bits 16 - 19 + } +} +#endif + + +std::string sys::getHostCPUName() { +#if defined(__x86_64__) || defined(__i386__) + unsigned EAX = 0, EBX = 0, ECX = 0, EDX = 0; + if (GetX86CpuIDAndInfo(0x1, &EAX, &EBX, &ECX, &EDX)) + return "generic"; + unsigned Family = 0; + unsigned Model = 0; + DetectX86FamilyModel(EAX, Family, Model); + + GetX86CpuIDAndInfo(0x80000001, &EAX, &EBX, &ECX, &EDX); + bool Em64T = (EDX >> 29) & 0x1; + bool HasSSE3 = (ECX & 0x1); + + union { + unsigned u[3]; + char c[12]; + } text; + + GetX86CpuIDAndInfo(0, &EAX, text.u+0, text.u+2, text.u+1); + if (memcmp(text.c, "GenuineIntel", 12) == 0) { + switch (Family) { + case 3: + return "i386"; + case 4: + switch (Model) { + case 0: // Intel486TM DX processors + case 1: // Intel486TM DX processors + case 2: // Intel486 SX processors + case 3: // Intel487TM processors, IntelDX2 OverDrive® processors, + // IntelDX2TM processors + case 4: // Intel486 SL processor + case 5: // IntelSX2TM processors + case 7: // Write-Back Enhanced IntelDX2 processors + case 8: // IntelDX4 OverDrive processors, IntelDX4TM processors + default: return "i486"; + } + case 5: + switch (Model) { + case 1: // Pentium OverDrive processor for Pentium processor (60, 66), + // Pentium® processors (60, 66) + case 2: // Pentium OverDrive processor for Pentium processor (75, 90, + // 100, 120, 133), Pentium processors (75, 90, 100, 120, 133, + // 150, 166, 200) + case 3: // Pentium OverDrive processors for Intel486 processor-based + // systems + return "pentium"; + + case 4: // Pentium OverDrive processor with MMXTM technology for Pentium + // processor (75, 90, 100, 120, 133), Pentium processor with + // MMXTM technology (166, 200) + return "pentium-mmx"; + + default: return "pentium"; + } + case 6: + switch (Model) { + case 1: // Pentium Pro processor + return "pentiumpro"; + + case 3: // Intel Pentium II OverDrive processor, Pentium II processor, + // model 03 + case 5: // Pentium II processor, model 05, Pentium II Xeon processor, + // model 05, and Intel® Celeron® processor, model 05 + case 6: // Celeron processor, model 06 + return "pentium2"; + + case 7: // Pentium III processor, model 07, and Pentium III Xeon + // processor, model 07 + case 8: // Pentium III processor, model 08, Pentium III Xeon processor, + // model 08, and Celeron processor, model 08 + case 10: // Pentium III Xeon processor, model 0Ah + case 11: // Pentium III processor, model 0Bh + return "pentium3"; + + case 9: // Intel Pentium M processor, Intel Celeron M processor model 09. + case 13: // Intel Pentium M processor, Intel Celeron M processor, model + // 0Dh. All processors are manufactured using the 90 nm process. + return "pentium-m"; + + case 14: // Intel CoreTM Duo processor, Intel CoreTM Solo processor, model + // 0Eh. All processors are manufactured using the 65 nm process. + return "yonah"; + + case 15: // Intel CoreTM2 Duo processor, Intel CoreTM2 Duo mobile + // processor, Intel CoreTM2 Quad processor, Intel CoreTM2 Quad + // mobile processor, Intel CoreTM2 Extreme processor, Intel + // Pentium Dual-Core processor, Intel Xeon processor, model + // 0Fh. All processors are manufactured using the 65 nm process. + case 22: // Intel Celeron processor model 16h. All processors are + // manufactured using the 65 nm process + return "core2"; + + case 21: // Intel EP80579 Integrated Processor and Intel EP80579 + // Integrated Processor with Intel QuickAssist Technology + return "i686"; // FIXME: ??? + + case 23: // Intel CoreTM2 Extreme processor, Intel Xeon processor, model + // 17h. All processors are manufactured using the 45 nm process. + // + // 45nm: Penryn , Wolfdale, Yorkfield (XE) + return "penryn"; + + case 26: // Intel Core i7 processor and Intel Xeon processor. All + // processors are manufactured using the 45 nm process. + case 29: // Intel Xeon processor MP. All processors are manufactured using + // the 45 nm process. + return "corei7"; + + case 28: // Intel Atom processor. All processors are manufactured using + // the 45 nm process + return "atom"; + + default: return "i686"; + } + case 15: { + switch (Model) { + case 0: // Pentium 4 processor, Intel Xeon processor. All processors are + // model 00h and manufactured using the 0.18 micron process. + case 1: // Pentium 4 processor, Intel Xeon processor, Intel Xeon + // processor MP, and Intel Celeron processor. All processors are + // model 01h and manufactured using the 0.18 micron process. + case 2: // Pentium 4 processor, Mobile Intel Pentium 4 processor – M, + // Intel Xeon processor, Intel Xeon processor MP, Intel Celeron + // processor, and Mobile Intel Celeron processor. All processors + // are model 02h and manufactured using the 0.13 micron process. + return (Em64T) ? "x86-64" : "pentium4"; + + case 3: // Pentium 4 processor, Intel Xeon processor, Intel Celeron D + // processor. All processors are model 03h and manufactured using + // the 90 nm process. + case 4: // Pentium 4 processor, Pentium 4 processor Extreme Edition, + // Pentium D processor, Intel Xeon processor, Intel Xeon + // processor MP, Intel Celeron D processor. All processors are + // model 04h and manufactured using the 90 nm process. + case 6: // Pentium 4 processor, Pentium D processor, Pentium processor + // Extreme Edition, Intel Xeon processor, Intel Xeon processor + // MP, Intel Celeron D processor. All processors are model 06h + // and manufactured using the 65 nm process. + return (Em64T) ? "nocona" : "prescott"; + + default: + return (Em64T) ? "x86-64" : "pentium4"; + } + } + + default: + return "generic"; + } + } else if (memcmp(text.c, "AuthenticAMD", 12) == 0) { + // FIXME: this poorly matches the generated SubtargetFeatureKV table. There + // appears to be no way to generate the wide variety of AMD-specific targets + // from the information returned from CPUID. + switch (Family) { + case 4: + return "i486"; + case 5: + switch (Model) { + case 6: + case 7: return "k6"; + case 8: return "k6-2"; + case 9: + case 13: return "k6-3"; + default: return "pentium"; + } + case 6: + switch (Model) { + case 4: return "athlon-tbird"; + case 6: + case 7: + case 8: return "athlon-mp"; + case 10: return "athlon-xp"; + default: return "athlon"; + } + case 15: + if (HasSSE3) { + return "k8-sse3"; + } else { + switch (Model) { + case 1: return "opteron"; + case 5: return "athlon-fx"; // also opteron + default: return "athlon64"; + } + } + case 16: + return "amdfam10"; + default: + return "generic"; + } + } +#endif + + return "generic"; +} diff --git a/libclamav/c++/llvm/lib/System/IncludeFile.cpp b/libclamav/c++/llvm/lib/System/IncludeFile.cpp new file mode 100644 index 000000000..8258d4032 --- /dev/null +++ b/libclamav/c++/llvm/lib/System/IncludeFile.cpp @@ -0,0 +1,20 @@ +//===- lib/System/IncludeFile.cpp - Ensure Linking Of Implementation -----===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the IncludeFile constructor. +// +//===----------------------------------------------------------------------===// + +#include "llvm/System/IncludeFile.h" + +using namespace llvm; + +// This constructor is used to ensure linking of other modules. See the +// llvm/System/IncludeFile.h header for details. +IncludeFile::IncludeFile(const void*) {} diff --git a/libclamav/c++/llvm/lib/System/Makefile b/libclamav/c++/llvm/lib/System/Makefile new file mode 100644 index 000000000..d4fd60eee --- /dev/null +++ b/libclamav/c++/llvm/lib/System/Makefile @@ -0,0 +1,25 @@ +##===- lib/System/Makefile ---------------------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LEVEL = ../.. +LIBRARYNAME = LLVMSystem +BUILD_ARCHIVE = 1 + +include $(LEVEL)/Makefile.config + +ifeq ($(HOST_OS),MingW) + REQUIRES_EH := 1 +endif + +EXTRA_DIST = Unix Win32 README.txt + +include $(LEVEL)/Makefile.common + +CompileCommonOpts := $(filter-out -pedantic,$(CompileCommonOpts)) +CompileCommonOpts := $(filter-out -Wno-long-long,$(CompileCommonOpts)) diff --git a/libclamav/c++/llvm/lib/System/Memory.cpp b/libclamav/c++/llvm/lib/System/Memory.cpp new file mode 100644 index 000000000..e2d838dce --- /dev/null +++ b/libclamav/c++/llvm/lib/System/Memory.cpp @@ -0,0 +1,71 @@ +//===- Memory.cpp - Memory Handling Support ---------------------*- 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 some helpful functions for allocating memory and dealing +// with memory mapped files +// +//===----------------------------------------------------------------------===// + +#include "llvm/System/Memory.h" +#include "llvm/Config/config.h" + +namespace llvm { +using namespace sys; +} + +// Include the platform-specific parts of this class. +#ifdef LLVM_ON_UNIX +#include "Unix/Memory.inc" +#endif +#ifdef LLVM_ON_WIN32 +#include "Win32/Memory.inc" +#endif + +extern "C" void sys_icache_invalidate(const void *Addr, size_t len); + +/// InvalidateInstructionCache - Before the JIT can run a block of code +/// that has been emitted it must invalidate the instruction cache on some +/// platforms. +void llvm::sys::Memory::InvalidateInstructionCache(const void *Addr, + size_t Len) { + +// icache invalidation for PPC and ARM. +#if defined(__APPLE__) + +# if (defined(__POWERPC__) || defined (__ppc__) || \ + defined(_POWER) || defined(_ARCH_PPC)) || defined(__arm__) + sys_icache_invalidate(Addr, Len); +# endif + +#else + +# if (defined(__POWERPC__) || defined (__ppc__) || \ + defined(_POWER) || defined(_ARCH_PPC)) && defined(__GNUC__) + const size_t LineSize = 32; + + const intptr_t Mask = ~(LineSize - 1); + const intptr_t StartLine = ((intptr_t) Addr) & Mask; + const intptr_t EndLine = ((intptr_t) Addr + Len + LineSize - 1) & Mask; + + for (intptr_t Line = StartLine; Line < EndLine; Line += LineSize) + asm volatile("dcbf 0, %0" : : "r"(Line)); + asm volatile("sync"); + + for (intptr_t Line = StartLine; Line < EndLine; Line += LineSize) + asm volatile("icbi 0, %0" : : "r"(Line)); + asm volatile("isync"); +# elif defined(__arm__) && defined(__GNUC__) + // FIXME: Can we safely always call this for __GNUC__ everywhere? + char *Start = (char*) Addr; + char *End = Start + Len; + __clear_cache(Start, End); +# endif + +#endif // end apple +} diff --git a/libclamav/c++/llvm/lib/System/Mutex.cpp b/libclamav/c++/llvm/lib/System/Mutex.cpp new file mode 100644 index 000000000..8ccd6e52c --- /dev/null +++ b/libclamav/c++/llvm/lib/System/Mutex.cpp @@ -0,0 +1,157 @@ +//===- Mutex.cpp - Mutual Exclusion Lock ------------------------*- 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 the llvm::sys::Mutex class. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Config/config.h" +#include "llvm/System/Mutex.h" + +//===----------------------------------------------------------------------===// +//=== WARNING: Implementation here must contain only TRULY operating system +//=== independent code. +//===----------------------------------------------------------------------===// + +#if !defined(ENABLE_THREADS) || ENABLE_THREADS == 0 +// Define all methods as no-ops if threading is explicitly disabled +namespace llvm { +using namespace sys; +MutexImpl::MutexImpl( bool recursive) { } +MutexImpl::~MutexImpl() { } +bool MutexImpl::acquire() { return true; } +bool MutexImpl::release() { return true; } +bool MutexImpl::tryacquire() { return true; } +} +#else + +#if defined(HAVE_PTHREAD_H) && defined(HAVE_PTHREAD_MUTEX_LOCK) + +#include +#include +#include + +namespace llvm { +using namespace sys; + + +// This variable is useful for situations where the pthread library has been +// compiled with weak linkage for its interface symbols. This allows the +// threading support to be turned off by simply not linking against -lpthread. +// In that situation, the value of pthread_mutex_init will be 0 and +// consequently pthread_enabled will be false. In such situations, all the +// pthread operations become no-ops and the functions all return false. If +// pthread_mutex_init does have an address, then mutex support is enabled. +// Note: all LLVM tools will link against -lpthread if its available since it +// is configured into the LIBS variable. +// Note: this line of code generates a warning if pthread_mutex_init is not +// declared with weak linkage. It's safe to ignore the warning. +static const bool pthread_enabled = true; + +// Construct a Mutex using pthread calls +MutexImpl::MutexImpl( bool recursive) + : data_(0) +{ + if (pthread_enabled) + { + // Declare the pthread_mutex data structures + pthread_mutex_t* mutex = + static_cast(malloc(sizeof(pthread_mutex_t))); + pthread_mutexattr_t attr; + + // Initialize the mutex attributes + int errorcode = pthread_mutexattr_init(&attr); + assert(errorcode == 0); + + // Initialize the mutex as a recursive mutex, if requested, or normal + // otherwise. + int kind = ( recursive ? PTHREAD_MUTEX_RECURSIVE : PTHREAD_MUTEX_NORMAL ); + errorcode = pthread_mutexattr_settype(&attr, kind); + assert(errorcode == 0); + +#if !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__NetBSD__) && !defined(__DragonFly__) + // Make it a process local mutex + errorcode = pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_PRIVATE); +#endif + + // Initialize the mutex + errorcode = pthread_mutex_init(mutex, &attr); + assert(errorcode == 0); + + // Destroy the attributes + errorcode = pthread_mutexattr_destroy(&attr); + assert(errorcode == 0); + + // Assign the data member + data_ = mutex; + } +} + +// Destruct a Mutex +MutexImpl::~MutexImpl() +{ + if (pthread_enabled) + { + pthread_mutex_t* mutex = static_cast(data_); + assert(mutex != 0); + pthread_mutex_destroy(mutex); + free(mutex); + } +} + +bool +MutexImpl::acquire() +{ + if (pthread_enabled) + { + pthread_mutex_t* mutex = static_cast(data_); + assert(mutex != 0); + + int errorcode = pthread_mutex_lock(mutex); + return errorcode == 0; + } else return false; +} + +bool +MutexImpl::release() +{ + if (pthread_enabled) + { + pthread_mutex_t* mutex = static_cast(data_); + assert(mutex != 0); + + int errorcode = pthread_mutex_unlock(mutex); + return errorcode == 0; + } else return false; +} + +bool +MutexImpl::tryacquire() +{ + if (pthread_enabled) + { + pthread_mutex_t* mutex = static_cast(data_); + assert(mutex != 0); + + int errorcode = pthread_mutex_trylock(mutex); + return errorcode == 0; + } else return false; +} + +} + +#elif defined(LLVM_ON_UNIX) +#include "Unix/Mutex.inc" +#elif defined( LLVM_ON_WIN32) +#include "Win32/Mutex.inc" +#else +#warning Neither LLVM_ON_UNIX nor LLVM_ON_WIN32 was set in System/Mutex.cpp +#endif +#endif + diff --git a/libclamav/c++/llvm/lib/System/Path.cpp b/libclamav/c++/llvm/lib/System/Path.cpp new file mode 100644 index 000000000..8e1fa538b --- /dev/null +++ b/libclamav/c++/llvm/lib/System/Path.cpp @@ -0,0 +1,266 @@ +//===-- Path.cpp - Implement OS Path Concept --------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This header file implements the operating system Path concept. +// +//===----------------------------------------------------------------------===// + +#include "llvm/System/Path.h" +#include "llvm/Config/config.h" +#include +#include +#include +using namespace llvm; +using namespace sys; + +//===----------------------------------------------------------------------===// +//=== WARNING: Implementation here must contain only TRULY operating system +//=== independent code. +//===----------------------------------------------------------------------===// + +bool Path::operator==(const Path &that) const { + return path == that.path; +} + +bool Path::operator<(const Path& that) const { + return path < that.path; +} + +Path +Path::GetLLVMConfigDir() { + Path result; +#ifdef LLVM_ETCDIR + if (result.set(LLVM_ETCDIR)) + return result; +#endif + return GetLLVMDefaultConfigDir(); +} + +LLVMFileType +sys::IdentifyFileType(const char *magic, unsigned length) { + assert(magic && "Invalid magic number string"); + assert(length >=4 && "Invalid magic number length"); + switch ((unsigned char)magic[0]) { + case 0xDE: // 0x0B17C0DE = BC wraper + if (magic[1] == (char)0xC0 && magic[2] == (char)0x17 && + magic[3] == (char)0x0B) + return Bitcode_FileType; + break; + case 'B': + if (magic[1] == 'C' && magic[2] == (char)0xC0 && magic[3] == (char)0xDE) + return Bitcode_FileType; + break; + case '!': + if (length >= 8) + if (memcmp(magic,"!\n",8) == 0) + return Archive_FileType; + break; + + case '\177': + if (magic[1] == 'E' && magic[2] == 'L' && magic[3] == 'F') { + if (length >= 18 && magic[17] == 0) + switch (magic[16]) { + default: break; + case 1: return ELF_Relocatable_FileType; + case 2: return ELF_Executable_FileType; + case 3: return ELF_SharedObject_FileType; + case 4: return ELF_Core_FileType; + } + } + break; + + case 0xCA: + if (magic[1] == char(0xFE) && magic[2] == char(0xBA) && + magic[3] == char(0xBE)) { + // This is complicated by an overlap with Java class files. + // See the Mach-O section in /usr/share/file/magic for details. + if (length >= 8 && magic[7] < 43) + // FIXME: Universal Binary of any type. + return Mach_O_DynamicallyLinkedSharedLib_FileType; + } + break; + + case 0xFE: + case 0xCE: { + uint16_t type = 0; + if (magic[0] == char(0xFE) && magic[1] == char(0xED) && + magic[2] == char(0xFA) && magic[3] == char(0xCE)) { + /* Native endian */ + if (length >= 16) type = magic[14] << 8 | magic[15]; + } else if (magic[0] == char(0xCE) && magic[1] == char(0xFA) && + magic[2] == char(0xED) && magic[3] == char(0xFE)) { + /* Reverse endian */ + if (length >= 14) type = magic[13] << 8 | magic[12]; + } + switch (type) { + default: break; + case 1: return Mach_O_Object_FileType; + case 2: return Mach_O_Executable_FileType; + case 3: return Mach_O_FixedVirtualMemorySharedLib_FileType; + case 4: return Mach_O_Core_FileType; + case 5: return Mach_O_PreloadExectuable_FileType; + case 6: return Mach_O_DynamicallyLinkedSharedLib_FileType; + case 7: return Mach_O_DynamicLinker_FileType; + case 8: return Mach_O_Bundle_FileType; + case 9: return Mach_O_DynamicallyLinkedSharedLibStub_FileType; + case 10: break; // FIXME: MH_DSYM companion file with only debug. + } + break; + } + case 0xF0: // PowerPC Windows + case 0x83: // Alpha 32-bit + case 0x84: // Alpha 64-bit + case 0x66: // MPS R4000 Windows + case 0x50: // mc68K + case 0x4c: // 80386 Windows + if (magic[1] == 0x01) + return COFF_FileType; + + case 0x90: // PA-RISC Windows + case 0x68: // mc68K Windows + if (magic[1] == 0x02) + return COFF_FileType; + break; + + default: + break; + } + return Unknown_FileType; +} + +bool +Path::isArchive() const { + if (canRead()) + return hasMagicNumber("!\012"); + return false; +} + +bool +Path::isDynamicLibrary() const { + if (canRead()) { + std::string Magic; + if (getMagicNumber(Magic, 64)) + switch (IdentifyFileType(Magic.c_str(), + static_cast(Magic.length()))) { + default: return false; + case Mach_O_FixedVirtualMemorySharedLib_FileType: + case Mach_O_DynamicallyLinkedSharedLib_FileType: + case Mach_O_DynamicallyLinkedSharedLibStub_FileType: + case ELF_SharedObject_FileType: + case COFF_FileType: return true; + } + } + return false; +} + +Path +Path::FindLibrary(std::string& name) { + std::vector LibPaths; + GetSystemLibraryPaths(LibPaths); + for (unsigned i = 0; i < LibPaths.size(); ++i) { + sys::Path FullPath(LibPaths[i]); + FullPath.appendComponent("lib" + name + LTDL_SHLIB_EXT); + if (FullPath.isDynamicLibrary()) + return FullPath; + FullPath.eraseSuffix(); + FullPath.appendSuffix("a"); + if (FullPath.isArchive()) + return FullPath; + } + return sys::Path(); +} + +std::string Path::GetDLLSuffix() { + return LTDL_SHLIB_EXT; +} + +bool +Path::isBitcodeFile() const { + std::string actualMagic; + if (!getMagicNumber(actualMagic, 4)) + return false; + LLVMFileType FT = + IdentifyFileType(actualMagic.c_str(), + static_cast(actualMagic.length())); + return FT == Bitcode_FileType; +} + +bool Path::hasMagicNumber(const std::string &Magic) const { + std::string actualMagic; + if (getMagicNumber(actualMagic, static_cast(Magic.size()))) + return Magic == actualMagic; + return false; +} + +static void getPathList(const char*path, std::vector& Paths) { + const char* at = path; + const char* delim = strchr(at, PathSeparator); + Path tmpPath; + while (delim != 0) { + std::string tmp(at, size_t(delim-at)); + if (tmpPath.set(tmp)) + if (tmpPath.canRead()) + Paths.push_back(tmpPath); + at = delim + 1; + delim = strchr(at, PathSeparator); + } + + if (*at != 0) + if (tmpPath.set(std::string(at))) + if (tmpPath.canRead()) + Paths.push_back(tmpPath); +} + +static std::string getDirnameCharSep(const std::string& path, char Sep) { + + if (path.empty()) + return "."; + + // If the path is all slashes, return a single slash. + // Otherwise, remove all trailing slashes. + + signed pos = static_cast(path.size()) - 1; + + while (pos >= 0 && path[pos] == Sep) + --pos; + + if (pos < 0) + return path[0] == Sep ? std::string(1, Sep) : std::string("."); + + // Any slashes left? + signed i = 0; + + while (i < pos && path[i] != Sep) + ++i; + + if (i == pos) // No slashes? Return "." + return "."; + + // There is at least one slash left. Remove all trailing non-slashes. + while (pos >= 0 && path[pos] != Sep) + --pos; + + // Remove any trailing slashes. + while (pos >= 0 && path[pos] == Sep) + --pos; + + if (pos < 0) + return path[0] == Sep ? std::string(1, Sep) : std::string("."); + + return path.substr(0, pos+1); +} + +// Include the truly platform-specific parts of this class. +#if defined(LLVM_ON_UNIX) +#include "Unix/Path.inc" +#endif +#if defined(LLVM_ON_WIN32) +#include "Win32/Path.inc" +#endif + diff --git a/libclamav/c++/llvm/lib/System/Process.cpp b/libclamav/c++/llvm/lib/System/Process.cpp new file mode 100644 index 000000000..e93b2af4c --- /dev/null +++ b/libclamav/c++/llvm/lib/System/Process.cpp @@ -0,0 +1,33 @@ +//===-- Process.cpp - Implement OS Process Concept --------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This header file implements the operating system Process concept. +// +//===----------------------------------------------------------------------===// + +#include "llvm/System/Process.h" +#include "llvm/Config/config.h" + +namespace llvm { +using namespace sys; + +//===----------------------------------------------------------------------===// +//=== WARNING: Implementation here must contain only TRULY operating system +//=== independent code. +//===----------------------------------------------------------------------===// + +} + +// Include the platform-specific parts of this class. +#ifdef LLVM_ON_UNIX +#include "Unix/Process.inc" +#endif +#ifdef LLVM_ON_WIN32 +#include "Win32/Process.inc" +#endif diff --git a/libclamav/c++/llvm/lib/System/Program.cpp b/libclamav/c++/llvm/lib/System/Program.cpp new file mode 100644 index 000000000..a3049d46f --- /dev/null +++ b/libclamav/c++/llvm/lib/System/Program.cpp @@ -0,0 +1,60 @@ +//===-- Program.cpp - Implement OS Program Concept --------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This header file implements the operating system Program concept. +// +//===----------------------------------------------------------------------===// + +#include "llvm/System/Program.h" +#include "llvm/Config/config.h" + +namespace llvm { +using namespace sys; + +//===----------------------------------------------------------------------===// +//=== WARNING: Implementation here must contain only TRULY operating system +//=== independent code. +//===----------------------------------------------------------------------===// + +int +Program::ExecuteAndWait(const Path& path, + const char** args, + const char** envp, + const Path** redirects, + unsigned secondsToWait, + unsigned memoryLimit, + std::string* ErrMsg) { + Program prg; + if (prg.Execute(path, args, envp, redirects, memoryLimit, ErrMsg)) + return prg.Wait(secondsToWait, ErrMsg); + else + return -1; +} + +void +Program::ExecuteNoWait(const Path& path, + const char** args, + const char** envp, + const Path** redirects, + unsigned memoryLimit, + std::string* ErrMsg) { + Program prg; + prg.Execute(path, args, envp, redirects, memoryLimit, ErrMsg); +} + + +} + +// Include the platform-specific parts of this class. +#ifdef LLVM_ON_UNIX +#include "Unix/Program.inc" +#endif +#ifdef LLVM_ON_WIN32 +#include "Win32/Program.inc" +#endif diff --git a/libclamav/c++/llvm/lib/System/README.txt b/libclamav/c++/llvm/lib/System/README.txt new file mode 100644 index 000000000..eacb20094 --- /dev/null +++ b/libclamav/c++/llvm/lib/System/README.txt @@ -0,0 +1,43 @@ +Design Of lib/System +==================== + +The software in this directory is designed to completely shield LLVM from any +and all operating system specific functionality. It is not intended to be a +complete operating system wrapper (such as ACE), but only to provide the +functionality necessary to support LLVM. + +The software located here, of necessity, has very specific and stringent design +rules. Violation of these rules means that cracks in the shield could form and +the primary goal of the library is defeated. By consistently using this library, +LLVM becomes more easily ported to new platforms since the only thing requiring +porting is this library. + +Complete documentation for the library can be found in the file: + llvm/docs/SystemLibrary.html +or at this URL: + http://llvm.org/docs/SystemLibrary.html + +While we recommend that you read the more detailed documentation, for the +impatient, here's a high level summary of the library's requirements. + + 1. No system header files are to be exposed through the interface. + 2. Std C++ and Std C header files are okay to be exposed through the interface. + 3. No exposed system-specific functions. + 4. No exposed system-specific data. + 5. Data in lib/System classes must use only simple C++ intrinsic types. + 6. Errors are handled by returning "true" and setting an optional std::string + 7. Library must not throw any exceptions, period. + 8. Interface functions must not have throw() specifications. + 9. No duplicate function impementations are permitted within an operating + system class. + +To accomplish these requirements, the library has numerous design criteria that +must be satisfied. Here's a high level summary of the library's design criteria: + + 1. No unused functionality (only what LLVM needs) + 2. High-Level Interfaces + 3. Use Opaque Classes + 4. Common Implementations + 5. Multiple Implementations + 6. Minimize Memory Allocation + 7. No Virtual Methods diff --git a/libclamav/c++/llvm/lib/System/RWMutex.cpp b/libclamav/c++/llvm/lib/System/RWMutex.cpp new file mode 100644 index 000000000..5faf220eb --- /dev/null +++ b/libclamav/c++/llvm/lib/System/RWMutex.cpp @@ -0,0 +1,171 @@ +//===- RWMutex.cpp - Reader/Writer Mutual Exclusion Lock --------*- 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 the llvm::sys::RWMutex class. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Config/config.h" +#include "llvm/System/RWMutex.h" +#include + +//===----------------------------------------------------------------------===// +//=== WARNING: Implementation here must contain only TRULY operating system +//=== independent code. +//===----------------------------------------------------------------------===// + +#if !defined(ENABLE_THREADS) || ENABLE_THREADS == 0 +// Define all methods as no-ops if threading is explicitly disabled +namespace llvm { +using namespace sys; +RWMutexImpl::RWMutexImpl() { } +RWMutexImpl::~RWMutexImpl() { } +bool RWMutexImpl::reader_acquire() { return true; } +bool RWMutexImpl::reader_release() { return true; } +bool RWMutexImpl::writer_acquire() { return true; } +bool RWMutexImpl::writer_release() { return true; } +} +#else + +#if defined(HAVE_PTHREAD_H) && defined(HAVE_PTHREAD_RWLOCK_INIT) + +#include +#include +#include + +namespace llvm { +using namespace sys; + + +// This variable is useful for situations where the pthread library has been +// compiled with weak linkage for its interface symbols. This allows the +// threading support to be turned off by simply not linking against -lpthread. +// In that situation, the value of pthread_mutex_init will be 0 and +// consequently pthread_enabled will be false. In such situations, all the +// pthread operations become no-ops and the functions all return false. If +// pthread_rwlock_init does have an address, then rwlock support is enabled. +// Note: all LLVM tools will link against -lpthread if its available since it +// is configured into the LIBS variable. +// Note: this line of code generates a warning if pthread_rwlock_init is not +// declared with weak linkage. It's safe to ignore the warning. +static const bool pthread_enabled = true; + +// Construct a RWMutex using pthread calls +RWMutexImpl::RWMutexImpl() + : data_(0) +{ + if (pthread_enabled) + { + // Declare the pthread_rwlock data structures + pthread_rwlock_t* rwlock = + static_cast(malloc(sizeof(pthread_rwlock_t))); + +#ifdef __APPLE__ + // Workaround a bug/mis-feature in Darwin's pthread_rwlock_init. + bzero(rwlock, sizeof(pthread_rwlock_t)); +#endif + + pthread_rwlockattr_t attr; + + // Initialize the rwlock attributes + int errorcode = pthread_rwlockattr_init(&attr); + assert(errorcode == 0); + +#if !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__NetBSD__) && !defined(__DragonFly__) + // Make it a process local rwlock + errorcode = pthread_rwlockattr_setpshared(&attr, PTHREAD_PROCESS_PRIVATE); +#endif + + // Initialize the rwlock + errorcode = pthread_rwlock_init(rwlock, &attr); + assert(errorcode == 0); + + // Destroy the attributes + errorcode = pthread_rwlockattr_destroy(&attr); + assert(errorcode == 0); + + // Assign the data member + data_ = rwlock; + } +} + +// Destruct a RWMutex +RWMutexImpl::~RWMutexImpl() +{ + if (pthread_enabled) + { + pthread_rwlock_t* rwlock = static_cast(data_); + assert(rwlock != 0); + pthread_rwlock_destroy(rwlock); + free(rwlock); + } +} + +bool +RWMutexImpl::reader_acquire() +{ + if (pthread_enabled) + { + pthread_rwlock_t* rwlock = static_cast(data_); + assert(rwlock != 0); + + int errorcode = pthread_rwlock_rdlock(rwlock); + return errorcode == 0; + } else return false; +} + +bool +RWMutexImpl::reader_release() +{ + if (pthread_enabled) + { + pthread_rwlock_t* rwlock = static_cast(data_); + assert(rwlock != 0); + + int errorcode = pthread_rwlock_unlock(rwlock); + return errorcode == 0; + } else return false; +} + +bool +RWMutexImpl::writer_acquire() +{ + if (pthread_enabled) + { + pthread_rwlock_t* rwlock = static_cast(data_); + assert(rwlock != 0); + + int errorcode = pthread_rwlock_wrlock(rwlock); + return errorcode == 0; + } else return false; +} + +bool +RWMutexImpl::writer_release() +{ + if (pthread_enabled) + { + pthread_rwlock_t* rwlock = static_cast(data_); + assert(rwlock != 0); + + int errorcode = pthread_rwlock_unlock(rwlock); + return errorcode == 0; + } else return false; +} + +} + +#elif defined(LLVM_ON_UNIX) +#include "Unix/RWMutex.inc" +#elif defined( LLVM_ON_WIN32) +#include "Win32/RWMutex.inc" +#else +#warning Neither LLVM_ON_UNIX nor LLVM_ON_WIN32 was set in System/Mutex.cpp +#endif +#endif diff --git a/libclamav/c++/llvm/lib/System/Signals.cpp b/libclamav/c++/llvm/lib/System/Signals.cpp new file mode 100644 index 000000000..d345b0a9a --- /dev/null +++ b/libclamav/c++/llvm/lib/System/Signals.cpp @@ -0,0 +1,34 @@ +//===- Signals.cpp - Signal Handling support --------------------*- 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 some helpful functions for dealing with the possibility of +// Unix signals occuring while your program is running. +// +//===----------------------------------------------------------------------===// + +#include "llvm/System/Signals.h" +#include "llvm/Config/config.h" + +namespace llvm { +using namespace sys; + +//===----------------------------------------------------------------------===// +//=== WARNING: Implementation here must contain only TRULY operating system +//=== independent code. +//===----------------------------------------------------------------------===// + +} + +// Include the platform-specific parts of this class. +#ifdef LLVM_ON_UNIX +#include "Unix/Signals.inc" +#endif +#ifdef LLVM_ON_WIN32 +#include "Win32/Signals.inc" +#endif diff --git a/libclamav/c++/llvm/lib/System/ThreadLocal.cpp b/libclamav/c++/llvm/lib/System/ThreadLocal.cpp new file mode 100644 index 000000000..e7054b528 --- /dev/null +++ b/libclamav/c++/llvm/lib/System/ThreadLocal.cpp @@ -0,0 +1,80 @@ +//===- ThreadLocal.cpp - Thread Local Data ----------------------*- 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 the llvm::sys::ThreadLocal class. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Config/config.h" +#include "llvm/System/ThreadLocal.h" + +//===----------------------------------------------------------------------===// +//=== WARNING: Implementation here must contain only TRULY operating system +//=== independent code. +//===----------------------------------------------------------------------===// + +#if !defined(ENABLE_THREADS) || ENABLE_THREADS == 0 +// Define all methods as no-ops if threading is explicitly disabled +namespace llvm { +using namespace sys; +ThreadLocalImpl::ThreadLocalImpl() { } +ThreadLocalImpl::~ThreadLocalImpl() { } +void ThreadLocalImpl::setInstance(const void* d) { data = const_cast(d);} +const void* ThreadLocalImpl::getInstance() { return data; } +} +#else + +#if defined(HAVE_PTHREAD_H) && defined(HAVE_PTHREAD_GETSPECIFIC) + +#include +#include +#include + +namespace llvm { +using namespace sys; + +ThreadLocalImpl::ThreadLocalImpl() : data(0) { + pthread_key_t* key = new pthread_key_t; + int errorcode = pthread_key_create(key, NULL); + assert(errorcode == 0); + (void) errorcode; + data = (void*)key; +} + +ThreadLocalImpl::~ThreadLocalImpl() { + pthread_key_t* key = static_cast(data); + int errorcode = pthread_key_delete(*key); + assert(errorcode == 0); + (void) errorcode; + delete key; +} + +void ThreadLocalImpl::setInstance(const void* d) { + pthread_key_t* key = static_cast(data); + int errorcode = pthread_setspecific(*key, d); + assert(errorcode == 0); + (void) errorcode; +} + +const void* ThreadLocalImpl::getInstance() { + pthread_key_t* key = static_cast(data); + return pthread_getspecific(*key); +} + +} + +#elif defined(LLVM_ON_UNIX) +#include "Unix/ThreadLocal.inc" +#elif defined( LLVM_ON_WIN32) +#include "Win32/ThreadLocal.inc" +#else +#warning Neither LLVM_ON_UNIX nor LLVM_ON_WIN32 was set in System/ThreadLocal.cpp +#endif +#endif + diff --git a/libclamav/c++/llvm/lib/System/Threading.cpp b/libclamav/c++/llvm/lib/System/Threading.cpp new file mode 100644 index 000000000..466c46802 --- /dev/null +++ b/libclamav/c++/llvm/lib/System/Threading.cpp @@ -0,0 +1,64 @@ +//===-- llvm/System/Threading.cpp- Control multithreading mode --*- 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 llvm_start_multithreaded() and friends. +// +//===----------------------------------------------------------------------===// + +#include "llvm/System/Threading.h" +#include "llvm/System/Atomic.h" +#include "llvm/System/Mutex.h" +#include "llvm/Config/config.h" +#include + +using namespace llvm; + +static bool multithreaded_mode = false; + +static sys::Mutex* global_lock = 0; + +bool llvm::llvm_start_multithreaded() { +#ifdef LLVM_MULTITHREADED + assert(!multithreaded_mode && "Already multithreaded!"); + multithreaded_mode = true; + global_lock = new sys::Mutex(true); + + // We fence here to ensure that all initialization is complete BEFORE we + // return from llvm_start_multithreaded(). + sys::MemoryFence(); + return true; +#else + return false; +#endif +} + +void llvm::llvm_stop_multithreaded() { +#ifdef LLVM_MULTITHREADED + assert(multithreaded_mode && "Not currently multithreaded!"); + + // We fence here to insure that all threaded operations are complete BEFORE we + // return from llvm_stop_multithreaded(). + sys::MemoryFence(); + + multithreaded_mode = false; + delete global_lock; +#endif +} + +bool llvm::llvm_is_multithreaded() { + return multithreaded_mode; +} + +void llvm::llvm_acquire_global_lock() { + if (multithreaded_mode) global_lock->acquire(); +} + +void llvm::llvm_release_global_lock() { + if (multithreaded_mode) global_lock->release(); +} diff --git a/libclamav/c++/llvm/lib/System/TimeValue.cpp b/libclamav/c++/llvm/lib/System/TimeValue.cpp new file mode 100644 index 000000000..cf4984cc4 --- /dev/null +++ b/libclamav/c++/llvm/lib/System/TimeValue.cpp @@ -0,0 +1,58 @@ +//===-- TimeValue.cpp - Implement OS TimeValue Concept ----------*- 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 the operating system TimeValue concept. +// +//===----------------------------------------------------------------------===// + +#include "llvm/System/TimeValue.h" +#include "llvm/Config/config.h" + +namespace llvm { +using namespace sys; + +const TimeValue TimeValue::MinTime = TimeValue ( INT64_MIN,0 ); +const TimeValue TimeValue::MaxTime = TimeValue ( INT64_MAX,0 ); +const TimeValue TimeValue::ZeroTime = TimeValue ( 0,0 ); +const TimeValue TimeValue::PosixZeroTime = TimeValue ( -946684800,0 ); +const TimeValue TimeValue::Win32ZeroTime = TimeValue ( -12591158400ULL,0 ); + +void +TimeValue::normalize( void ) { + if ( nanos_ >= NANOSECONDS_PER_SECOND ) { + do { + seconds_++; + nanos_ -= NANOSECONDS_PER_SECOND; + } while ( nanos_ >= NANOSECONDS_PER_SECOND ); + } else if (nanos_ <= -NANOSECONDS_PER_SECOND ) { + do { + seconds_--; + nanos_ += NANOSECONDS_PER_SECOND; + } while (nanos_ <= -NANOSECONDS_PER_SECOND); + } + + if (seconds_ >= 1 && nanos_ < 0) { + seconds_--; + nanos_ += NANOSECONDS_PER_SECOND; + } else if (seconds_ < 0 && nanos_ > 0) { + seconds_++; + nanos_ -= NANOSECONDS_PER_SECOND; + } +} + +} + +/// Include the platform specific portion of TimeValue class +#ifdef LLVM_ON_UNIX +#include "Unix/TimeValue.inc" +#endif +#ifdef LLVM_ON_WIN32 +#include "Win32/TimeValue.inc" +#endif + diff --git a/libclamav/c++/llvm/lib/System/Unix/Alarm.inc b/libclamav/c++/llvm/lib/System/Unix/Alarm.inc new file mode 100644 index 000000000..fb42b6c65 --- /dev/null +++ b/libclamav/c++/llvm/lib/System/Unix/Alarm.inc @@ -0,0 +1,72 @@ +//===-- Alarm.inc - Implement Unix Alarm Support ----------------*- 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 the UNIX Alarm support. +// +//===----------------------------------------------------------------------===// + +#include +#include +#include +using namespace llvm; + +/// AlarmCancelled - This flag is set by the SIGINT signal handler if the +/// user presses CTRL-C. +static volatile bool AlarmCancelled = false; + +/// AlarmTriggered - This flag is set by the SIGALRM signal handler if the +/// alarm was triggered. +static volatile bool AlarmTriggered = false; + +/// NestedSOI - Sanity check. Alarms cannot be nested or run in parallel. +/// This ensures that they never do. +static bool NestedSOI = false; + +static RETSIGTYPE SigIntHandler(int Sig) { + AlarmCancelled = true; + signal(SIGINT, SigIntHandler); +} + +static RETSIGTYPE SigAlarmHandler(int Sig) { + AlarmTriggered = true; +} + +static void (*OldSigIntHandler) (int); + +void sys::SetupAlarm(unsigned seconds) { + assert(!NestedSOI && "sys::SetupAlarm calls cannot be nested!"); + NestedSOI = true; + AlarmCancelled = false; + AlarmTriggered = false; + ::signal(SIGALRM, SigAlarmHandler); + OldSigIntHandler = ::signal(SIGINT, SigIntHandler); + ::alarm(seconds); +} + +void sys::TerminateAlarm() { + assert(NestedSOI && "sys::TerminateAlarm called without sys::SetupAlarm!"); + ::alarm(0); + ::signal(SIGALRM, SIG_DFL); + ::signal(SIGINT, OldSigIntHandler); + AlarmCancelled = false; + AlarmTriggered = false; + NestedSOI = false; +} + +int sys::AlarmStatus() { + if (AlarmCancelled) + return -1; + if (AlarmTriggered) + return 1; + return 0; +} + +void sys::Sleep(unsigned n) { + ::sleep(n); +} diff --git a/libclamav/c++/llvm/lib/System/Unix/Host.inc b/libclamav/c++/llvm/lib/System/Unix/Host.inc new file mode 100644 index 000000000..c76d6a4e1 --- /dev/null +++ b/libclamav/c++/llvm/lib/System/Unix/Host.inc @@ -0,0 +1,96 @@ + //===- llvm/System/Unix/Host.inc -------------------------------*- 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 the UNIX Host support. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +//=== WARNING: Implementation here must contain only generic UNIX code that +//=== is guaranteed to work on *all* UNIX variants. +//===----------------------------------------------------------------------===// + +#include "llvm/Config/config.h" +#include "llvm/ADT/StringRef.h" +#include "Unix.h" +#include +#include + +using namespace llvm; + +static std::string getOSVersion() { + struct utsname info; + + if (uname(&info)) + return ""; + + return info.release; +} + +std::string sys::getHostTriple() { + // FIXME: Derive directly instead of relying on the autoconf generated + // variable. + + StringRef HostTripleString(LLVM_HOSTTRIPLE); + std::pair ArchSplit = HostTripleString.split('-'); + + // Normalize the arch, since the host triple may not actually match the host. + std::string Arch = ArchSplit.first; + + // It would be nice to do this in terms of llvm::Triple, but that is in + // Support which is layered above us. +#if defined(__x86_64__) + Arch = "x86_64"; +#elif defined(__i386__) + Arch = "i386"; +#elif defined(__ppc64__) + Arch = "powerpc64"; +#elif defined(__ppc__) + Arch = "powerpc"; +#elif defined(__arm__) + + // FIXME: We need to pick the right ARM triple (which involves querying the + // chip). However, for now this is most important for LLVM arch selection, so + // we only need to make sure to distinguish ARM and Thumb. +# if defined(__thumb__) + Arch = "thumb"; +# else + Arch = "arm"; +# endif + +#else + + // FIXME: When enough auto-detection is in place, this should just + // #error. Then at least the arch selection is done, and we only need the OS + // etc selection to kill off the use of LLVM_HOSTTRIPLE. + +#endif + + std::string Triple(Arch); + Triple += '-'; + Triple += ArchSplit.second; + + // Force i86 to i386. + if (Triple[0] == 'i' && isdigit(Triple[1]) && + Triple[2] == '8' && Triple[3] == '6') + Triple[1] = '3'; + + // On darwin, we want to update the version to match that of the + // host. + std::string::size_type DarwinDashIdx = Triple.find("-darwin"); + if (DarwinDashIdx != std::string::npos) { + Triple.resize(DarwinDashIdx + strlen("-darwin")); + + // Only add the major part of the os version. + std::string Version = getOSVersion(); + Triple += Version.substr(0, Version.find('.')); + } + + return Triple; +} diff --git a/libclamav/c++/llvm/lib/System/Unix/Memory.inc b/libclamav/c++/llvm/lib/System/Unix/Memory.inc new file mode 100644 index 000000000..1b038f9c6 --- /dev/null +++ b/libclamav/c++/llvm/lib/System/Unix/Memory.inc @@ -0,0 +1,151 @@ +//===- Unix/Memory.cpp - Generic UNIX System Configuration ------*- 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 some functions for various memory management utilities. +// +//===----------------------------------------------------------------------===// + +#include "Unix.h" +#include "llvm/System/DataTypes.h" +#include "llvm/System/Process.h" + +#ifdef HAVE_SYS_MMAN_H +#include +#endif + +#ifdef __APPLE__ +#include +#endif + +/// AllocateRWX - Allocate a slab of memory with read/write/execute +/// permissions. This is typically used for JIT applications where we want +/// to emit code to the memory then jump to it. Getting this type of memory +/// is very OS specific. +/// +llvm::sys::MemoryBlock +llvm::sys::Memory::AllocateRWX(size_t NumBytes, const MemoryBlock* NearBlock, + std::string *ErrMsg) { + if (NumBytes == 0) return MemoryBlock(); + + size_t pageSize = Process::GetPageSize(); + size_t NumPages = (NumBytes+pageSize-1)/pageSize; + + int fd = -1; +#ifdef NEED_DEV_ZERO_FOR_MMAP + static int zero_fd = open("/dev/zero", O_RDWR); + if (zero_fd == -1) { + MakeErrMsg(ErrMsg, "Can't open /dev/zero device"); + return MemoryBlock(); + } + fd = zero_fd; +#endif + + int flags = MAP_PRIVATE | +#ifdef HAVE_MMAP_ANONYMOUS + MAP_ANONYMOUS +#else + MAP_ANON +#endif + ; + + void* start = NearBlock ? (unsigned char*)NearBlock->base() + + NearBlock->size() : 0; + +#if defined(__APPLE__) && defined(__arm__) + void *pa = ::mmap(start, pageSize*NumPages, PROT_READ|PROT_EXEC, + flags, fd, 0); +#else + void *pa = ::mmap(start, pageSize*NumPages, PROT_READ|PROT_WRITE|PROT_EXEC, + flags, fd, 0); +#endif + if (pa == MAP_FAILED) { + if (NearBlock) //Try again without a near hint + return AllocateRWX(NumBytes, 0); + + MakeErrMsg(ErrMsg, "Can't allocate RWX Memory"); + return MemoryBlock(); + } + +#if defined(__APPLE__) && defined(__arm__) + kern_return_t kr = vm_protect(mach_task_self(), (vm_address_t)pa, + (vm_size_t)(pageSize*NumPages), 0, + VM_PROT_READ | VM_PROT_EXECUTE | VM_PROT_COPY); + if (KERN_SUCCESS != kr) { + MakeErrMsg(ErrMsg, "vm_protect max RX failed"); + return sys::MemoryBlock(); + } + + kr = vm_protect(mach_task_self(), (vm_address_t)pa, + (vm_size_t)(pageSize*NumPages), 0, + VM_PROT_READ | VM_PROT_WRITE); + if (KERN_SUCCESS != kr) { + MakeErrMsg(ErrMsg, "vm_protect RW failed"); + return sys::MemoryBlock(); + } +#endif + + MemoryBlock result; + result.Address = pa; + result.Size = NumPages*pageSize; + + return result; +} + +bool llvm::sys::Memory::ReleaseRWX(MemoryBlock &M, std::string *ErrMsg) { + if (M.Address == 0 || M.Size == 0) return false; + if (0 != ::munmap(M.Address, M.Size)) + return MakeErrMsg(ErrMsg, "Can't release RWX Memory"); + return false; +} + +bool llvm::sys::Memory::setWritable (MemoryBlock &M, std::string *ErrMsg) { +#if defined(__APPLE__) && defined(__arm__) + if (M.Address == 0 || M.Size == 0) return false; + sys::Memory::InvalidateInstructionCache(M.Address, M.Size); + kern_return_t kr = vm_protect(mach_task_self(), (vm_address_t)M.Address, + (vm_size_t)M.Size, 0, VM_PROT_READ | VM_PROT_WRITE); + return KERN_SUCCESS == kr; +#else + return true; +#endif +} + +bool llvm::sys::Memory::setExecutable (MemoryBlock &M, std::string *ErrMsg) { +#if defined(__APPLE__) && defined(__arm__) + if (M.Address == 0 || M.Size == 0) return false; + sys::Memory::InvalidateInstructionCache(M.Address, M.Size); + kern_return_t kr = vm_protect(mach_task_self(), (vm_address_t)M.Address, + (vm_size_t)M.Size, 0, VM_PROT_READ | VM_PROT_EXECUTE | VM_PROT_COPY); + return KERN_SUCCESS == kr; +#else + return false; +#endif +} + +bool llvm::sys::Memory::setRangeWritable(const void *Addr, size_t Size) { +#if defined(__APPLE__) && defined(__arm__) + kern_return_t kr = vm_protect(mach_task_self(), (vm_address_t)Addr, + (vm_size_t)Size, 0, + VM_PROT_READ | VM_PROT_WRITE); + return KERN_SUCCESS == kr; +#else + return true; +#endif +} + +bool llvm::sys::Memory::setRangeExecutable(const void *Addr, size_t Size) { +#if defined(__APPLE__) && defined(__arm__) + kern_return_t kr = vm_protect(mach_task_self(), (vm_address_t)Addr, + (vm_size_t)Size, 0, + VM_PROT_READ | VM_PROT_EXECUTE | VM_PROT_COPY); + return KERN_SUCCESS == kr; +#else + return true; +#endif +} diff --git a/libclamav/c++/llvm/lib/System/Unix/Mutex.inc b/libclamav/c++/llvm/lib/System/Unix/Mutex.inc new file mode 100644 index 000000000..10e7ecb75 --- /dev/null +++ b/libclamav/c++/llvm/lib/System/Unix/Mutex.inc @@ -0,0 +1,49 @@ +//===- llvm/System/Unix/Mutex.inc - Unix Mutex Implementation ---*- 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 the Unix specific (non-pthread) Mutex class. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +//=== WARNING: Implementation here must contain only generic UNIX code that +//=== is guaranteed to work on *all* UNIX variants. +//===----------------------------------------------------------------------===// + +namespace llvm +{ +using namespace sys; + +MutexImpl::MutexImpl( bool recursive) +{ +} + +MutexImpl::~MutexImpl() +{ +} + +bool +MutexImpl::MutexImpl() +{ + return true; +} + +bool +MutexImpl::release() +{ + return true; +} + +bool +MutexImpl::tryacquire( void ) +{ + return true; +} + +} diff --git a/libclamav/c++/llvm/lib/System/Unix/Path.inc b/libclamav/c++/llvm/lib/System/Unix/Path.inc new file mode 100644 index 000000000..4300d6719 --- /dev/null +++ b/libclamav/c++/llvm/lib/System/Unix/Path.inc @@ -0,0 +1,919 @@ +//===- llvm/System/Unix/Path.cpp - Unix Path Implementation -----*- 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 the Unix specific portion of the Path class. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +//=== WARNING: Implementation here must contain only generic UNIX code that +//=== is guaranteed to work on *all* UNIX variants. +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/SmallVector.h" +#include "Unix.h" +#if HAVE_SYS_STAT_H +#include +#endif +#if HAVE_FCNTL_H +#include +#endif +#ifdef HAVE_SYS_MMAN_H +#include +#endif +#ifdef HAVE_SYS_STAT_H +#include +#endif +#if HAVE_UTIME_H +#include +#endif +#if HAVE_TIME_H +#include +#endif +#if HAVE_DIRENT_H +# include +# define NAMLEN(dirent) strlen((dirent)->d_name) +#else +# define dirent direct +# define NAMLEN(dirent) (dirent)->d_namlen +# if HAVE_SYS_NDIR_H +# include +# endif +# if HAVE_SYS_DIR_H +# include +# endif +# if HAVE_NDIR_H +# include +# endif +#endif + +#if HAVE_DLFCN_H +#include +#endif + +#ifdef __APPLE__ +#include +#endif + +// Put in a hack for Cygwin which falsely reports that the mkdtemp function +// is available when it is not. +#ifdef __CYGWIN__ +# undef HAVE_MKDTEMP +#endif + +namespace { +inline bool lastIsSlash(const std::string& path) { + return !path.empty() && path[path.length() - 1] == '/'; +} + +} + +namespace llvm { +using namespace sys; + +extern const char sys::PathSeparator = ':'; + +Path::Path(const std::string& p) + : path(p) {} + +Path::Path(const char *StrStart, unsigned StrLen) + : path(StrStart, StrLen) {} + +Path& +Path::operator=(const std::string &that) { + path = that; + return *this; +} + +bool +Path::isValid() const { + // Check some obvious things + if (path.empty()) + return false; + return path.length() < MAXPATHLEN; +} + +bool +Path::isAbsolute(const char *NameStart, unsigned NameLen) { + assert(NameStart); + if (NameLen == 0) + return false; + return NameStart[0] == '/'; +} + +bool +Path::isAbsolute() const { + if (path.empty()) + return false; + return path[0] == '/'; +} + +void Path::makeAbsolute() { + if (isAbsolute()) + return; + + Path CWD = Path::GetCurrentDirectory(); + assert(CWD.isAbsolute() && "GetCurrentDirectory returned relative path!"); + + CWD.appendComponent(path); + + path = CWD.str(); +} + +Path +Path::GetRootDirectory() { + Path result; + result.set("/"); + return result; +} + +Path +Path::GetTemporaryDirectory(std::string *ErrMsg) { +#if defined(HAVE_MKDTEMP) + // The best way is with mkdtemp but that's not available on many systems, + // Linux and FreeBSD have it. Others probably won't. + char pathname[MAXPATHLEN]; + strcpy(pathname,"/tmp/llvm_XXXXXX"); + if (0 == mkdtemp(pathname)) { + MakeErrMsg(ErrMsg, + std::string(pathname) + ": can't create temporary directory"); + return Path(); + } + Path result; + result.set(pathname); + assert(result.isValid() && "mkdtemp didn't create a valid pathname!"); + return result; +#elif defined(HAVE_MKSTEMP) + // If no mkdtemp is available, mkstemp can be used to create a temporary file + // which is then removed and created as a directory. We prefer this over + // mktemp because of mktemp's inherent security and threading risks. We still + // have a slight race condition from the time the temporary file is created to + // the time it is re-created as a directoy. + char pathname[MAXPATHLEN]; + strcpy(pathname, "/tmp/llvm_XXXXXX"); + int fd = 0; + if (-1 == (fd = mkstemp(pathname))) { + MakeErrMsg(ErrMsg, + std::string(pathname) + ": can't create temporary directory"); + return Path(); + } + ::close(fd); + ::unlink(pathname); // start race condition, ignore errors + if (-1 == ::mkdir(pathname, S_IRWXU)) { // end race condition + MakeErrMsg(ErrMsg, + std::string(pathname) + ": can't create temporary directory"); + return Path(); + } + Path result; + result.set(pathname); + assert(result.isValid() && "mkstemp didn't create a valid pathname!"); + return result; +#elif defined(HAVE_MKTEMP) + // If a system doesn't have mkdtemp(3) or mkstemp(3) but it does have + // mktemp(3) then we'll assume that system (e.g. AIX) has a reasonable + // implementation of mktemp(3) and doesn't follow BSD 4.3's lead of replacing + // the XXXXXX with the pid of the process and a letter. That leads to only + // twenty six temporary files that can be generated. + char pathname[MAXPATHLEN]; + strcpy(pathname, "/tmp/llvm_XXXXXX"); + char *TmpName = ::mktemp(pathname); + if (TmpName == 0) { + MakeErrMsg(ErrMsg, + std::string(TmpName) + ": can't create unique directory name"); + return Path(); + } + if (-1 == ::mkdir(TmpName, S_IRWXU)) { + MakeErrMsg(ErrMsg, + std::string(TmpName) + ": can't create temporary directory"); + return Path(); + } + Path result; + result.set(TmpName); + assert(result.isValid() && "mktemp didn't create a valid pathname!"); + return result; +#else + // This is the worst case implementation. tempnam(3) leaks memory unless its + // on an SVID2 (or later) system. On BSD 4.3 it leaks. tmpnam(3) has thread + // issues. The mktemp(3) function doesn't have enough variability in the + // temporary name generated. So, we provide our own implementation that + // increments an integer from a random number seeded by the current time. This + // should be sufficiently unique that we don't have many collisions between + // processes. Generally LLVM processes don't run very long and don't use very + // many temporary files so this shouldn't be a big issue for LLVM. + static time_t num = ::time(0); + char pathname[MAXPATHLEN]; + do { + num++; + sprintf(pathname, "/tmp/llvm_%010u", unsigned(num)); + } while ( 0 == access(pathname, F_OK ) ); + if (-1 == ::mkdir(pathname, S_IRWXU)) { + MakeErrMsg(ErrMsg, + std::string(pathname) + ": can't create temporary directory"); + return Path(); + } + Path result; + result.set(pathname); + assert(result.isValid() && "mkstemp didn't create a valid pathname!"); + return result; +#endif +} + +void +Path::GetSystemLibraryPaths(std::vector& Paths) { +#ifdef LTDL_SHLIBPATH_VAR + char* env_var = getenv(LTDL_SHLIBPATH_VAR); + if (env_var != 0) { + getPathList(env_var,Paths); + } +#endif + // FIXME: Should this look at LD_LIBRARY_PATH too? + Paths.push_back(sys::Path("/usr/local/lib/")); + Paths.push_back(sys::Path("/usr/X11R6/lib/")); + Paths.push_back(sys::Path("/usr/lib/")); + Paths.push_back(sys::Path("/lib/")); +} + +void +Path::GetBitcodeLibraryPaths(std::vector& Paths) { + char * env_var = getenv("LLVM_LIB_SEARCH_PATH"); + if (env_var != 0) { + getPathList(env_var,Paths); + } +#ifdef LLVM_LIBDIR + { + Path tmpPath; + if (tmpPath.set(LLVM_LIBDIR)) + if (tmpPath.canRead()) + Paths.push_back(tmpPath); + } +#endif + GetSystemLibraryPaths(Paths); +} + +Path +Path::GetLLVMDefaultConfigDir() { + return Path("/etc/llvm/"); +} + +Path +Path::GetUserHomeDirectory() { + const char* home = getenv("HOME"); + if (home) { + Path result; + if (result.set(home)) + return result; + } + return GetRootDirectory(); +} + +Path +Path::GetCurrentDirectory() { + char pathname[MAXPATHLEN]; + if (!getcwd(pathname,MAXPATHLEN)) { + assert (false && "Could not query current working directory."); + return Path(""); + } + + return Path(pathname); +} + +#ifdef __FreeBSD__ +static int +test_dir(char buf[PATH_MAX], char ret[PATH_MAX], + const char *dir, const char *bin) +{ + struct stat sb; + + snprintf(buf, PATH_MAX, "%s//%s", dir, bin); + if (realpath(buf, ret) == NULL) + return (1); + if (stat(buf, &sb) != 0) + return (1); + + return (0); +} + +static char * +getprogpath(char ret[PATH_MAX], const char *bin) +{ + char *pv, *s, *t, buf[PATH_MAX]; + + /* First approach: absolute path. */ + if (bin[0] == '/') { + if (test_dir(buf, ret, "/", bin) == 0) + return (ret); + return (NULL); + } + + /* Second approach: relative path. */ + if (strchr(bin, '/') != NULL) { + if (getcwd(buf, PATH_MAX) == NULL) + return (NULL); + if (test_dir(buf, ret, buf, bin) == 0) + return (ret); + return (NULL); + } + + /* Third approach: $PATH */ + if ((pv = getenv("PATH")) == NULL) + return (NULL); + s = pv = strdup(pv); + if (pv == NULL) + return (NULL); + while ((t = strsep(&s, ":")) != NULL) { + if (test_dir(buf, ret, t, bin) == 0) { + free(pv); + return (ret); + } + } + free(pv); + return (NULL); +} +#endif // __FreeBSD__ + +/// GetMainExecutable - Return the path to the main executable, given the +/// value of argv[0] from program startup. +Path Path::GetMainExecutable(const char *argv0, void *MainAddr) { +#if defined(__APPLE__) + // On OS X the executable path is saved to the stack by dyld. Reading it + // from there is much faster than calling dladdr, especially for large + // binaries with symbols. + char exe_path[MAXPATHLEN]; + uint32_t size = sizeof(exe_path); + if (_NSGetExecutablePath(exe_path, &size) == 0) { + char link_path[MAXPATHLEN]; + return Path(std::string(realpath(exe_path, link_path))); + } +#elif defined(__FreeBSD__) + char exe_path[PATH_MAX]; + + if (getprogpath(exe_path, argv0) != NULL) + return Path(std::string(exe_path)); +#elif defined(__linux__) || defined(__CYGWIN__) + char exe_path[MAXPATHLEN]; + ssize_t len = readlink("/proc/self/exe", exe_path, sizeof(exe_path)); + if (len >= 0) + return Path(std::string(exe_path, len)); +#elif defined(HAVE_DLFCN_H) + // Use dladdr to get executable path if available. + Dl_info DLInfo; + int err = dladdr(MainAddr, &DLInfo); + if (err == 0) + return Path(); + + // If the filename is a symlink, we need to resolve and return the location of + // the actual executable. + char link_path[MAXPATHLEN]; + return Path(std::string(realpath(DLInfo.dli_fname, link_path))); +#endif + return Path(); +} + + +std::string Path::getDirname() const { + return getDirnameCharSep(path, '/'); +} + +std::string +Path::getBasename() const { + // Find the last slash + std::string::size_type slash = path.rfind('/'); + if (slash == std::string::npos) + slash = 0; + else + slash++; + + std::string::size_type dot = path.rfind('.'); + if (dot == std::string::npos || dot < slash) + return path.substr(slash); + else + return path.substr(slash, dot - slash); +} + +std::string +Path::getSuffix() const { + // Find the last slash + std::string::size_type slash = path.rfind('/'); + if (slash == std::string::npos) + slash = 0; + else + slash++; + + std::string::size_type dot = path.rfind('.'); + if (dot == std::string::npos || dot < slash) + return std::string(); + else + return path.substr(dot + 1); +} + +bool Path::getMagicNumber(std::string& Magic, unsigned len) const { + assert(len < 1024 && "Request for magic string too long"); + SmallVector Buf; + Buf.resize(1 + len); + char* buf = Buf.data(); + int fd = ::open(path.c_str(), O_RDONLY); + if (fd < 0) + return false; + ssize_t bytes_read = ::read(fd, buf, len); + ::close(fd); + if (ssize_t(len) != bytes_read) { + Magic.clear(); + return false; + } + Magic.assign(buf,len); + return true; +} + +bool +Path::exists() const { + return 0 == access(path.c_str(), F_OK ); +} + +bool +Path::isDirectory() const { + struct stat buf; + if (0 != stat(path.c_str(), &buf)) + return false; + return buf.st_mode & S_IFDIR ? true : false; +} + +bool +Path::canRead() const { + return 0 == access(path.c_str(), R_OK); +} + +bool +Path::canWrite() const { + return 0 == access(path.c_str(), W_OK); +} + +bool +Path::isRegularFile() const { + // Get the status so we can determine if its a file or directory + struct stat buf; + + if (0 != stat(path.c_str(), &buf)) + return false; + + if (S_ISREG(buf.st_mode)) + return true; + + return false; +} + +bool +Path::canExecute() const { + if (0 != access(path.c_str(), R_OK | X_OK )) + return false; + struct stat buf; + if (0 != stat(path.c_str(), &buf)) + return false; + if (!S_ISREG(buf.st_mode)) + return false; + return true; +} + +std::string +Path::getLast() const { + // Find the last slash + size_t pos = path.rfind('/'); + + // Handle the corner cases + if (pos == std::string::npos) + return path; + + // If the last character is a slash + if (pos == path.length()-1) { + // Find the second to last slash + size_t pos2 = path.rfind('/', pos-1); + if (pos2 == std::string::npos) + return path.substr(0,pos); + else + return path.substr(pos2+1,pos-pos2-1); + } + // Return everything after the last slash + return path.substr(pos+1); +} + +const FileStatus * +PathWithStatus::getFileStatus(bool update, std::string *ErrStr) const { + if (!fsIsValid || update) { + struct stat buf; + if (0 != stat(path.c_str(), &buf)) { + MakeErrMsg(ErrStr, path + ": can't get status of file"); + return 0; + } + status.fileSize = buf.st_size; + status.modTime.fromEpochTime(buf.st_mtime); + status.mode = buf.st_mode; + status.user = buf.st_uid; + status.group = buf.st_gid; + status.uniqueID = uint64_t(buf.st_ino); + status.isDir = S_ISDIR(buf.st_mode); + status.isFile = S_ISREG(buf.st_mode); + fsIsValid = true; + } + return &status; +} + +static bool AddPermissionBits(const Path &File, int bits) { + // Get the umask value from the operating system. We want to use it + // when changing the file's permissions. Since calling umask() sets + // the umask and returns its old value, we must call it a second + // time to reset it to the user's preference. + int mask = umask(0777); // The arg. to umask is arbitrary. + umask(mask); // Restore the umask. + + // Get the file's current mode. + struct stat buf; + if (0 != stat(File.c_str(), &buf)) + return false; + // Change the file to have whichever permissions bits from 'bits' + // that the umask would not disable. + if ((chmod(File.c_str(), (buf.st_mode | (bits & ~mask)))) == -1) + return false; + return true; +} + +bool Path::makeReadableOnDisk(std::string* ErrMsg) { + if (!AddPermissionBits(*this, 0444)) + return MakeErrMsg(ErrMsg, path + ": can't make file readable"); + return false; +} + +bool Path::makeWriteableOnDisk(std::string* ErrMsg) { + if (!AddPermissionBits(*this, 0222)) + return MakeErrMsg(ErrMsg, path + ": can't make file writable"); + return false; +} + +bool Path::makeExecutableOnDisk(std::string* ErrMsg) { + if (!AddPermissionBits(*this, 0111)) + return MakeErrMsg(ErrMsg, path + ": can't make file executable"); + return false; +} + +bool +Path::getDirectoryContents(std::set& result, std::string* ErrMsg) const { + DIR* direntries = ::opendir(path.c_str()); + if (direntries == 0) + return MakeErrMsg(ErrMsg, path + ": can't open directory"); + + std::string dirPath = path; + if (!lastIsSlash(dirPath)) + dirPath += '/'; + + result.clear(); + struct dirent* de = ::readdir(direntries); + for ( ; de != 0; de = ::readdir(direntries)) { + if (de->d_name[0] != '.') { + Path aPath(dirPath + (const char*)de->d_name); + struct stat st; + if (0 != lstat(aPath.path.c_str(), &st)) { + if (S_ISLNK(st.st_mode)) + continue; // dangling symlink -- ignore + return MakeErrMsg(ErrMsg, + aPath.path + ": can't determine file object type"); + } + result.insert(aPath); + } + } + + closedir(direntries); + return false; +} + +bool +Path::set(const std::string& a_path) { + if (a_path.empty()) + return false; + std::string save(path); + path = a_path; + if (!isValid()) { + path = save; + return false; + } + return true; +} + +bool +Path::appendComponent(const std::string& name) { + if (name.empty()) + return false; + std::string save(path); + if (!lastIsSlash(path)) + path += '/'; + path += name; + if (!isValid()) { + path = save; + return false; + } + return true; +} + +bool +Path::eraseComponent() { + size_t slashpos = path.rfind('/',path.size()); + if (slashpos == 0 || slashpos == std::string::npos) { + path.erase(); + return true; + } + if (slashpos == path.size() - 1) + slashpos = path.rfind('/',slashpos-1); + if (slashpos == std::string::npos) { + path.erase(); + return true; + } + path.erase(slashpos); + return true; +} + +bool +Path::appendSuffix(const std::string& suffix) { + std::string save(path); + path.append("."); + path.append(suffix); + if (!isValid()) { + path = save; + return false; + } + return true; +} + +bool +Path::eraseSuffix() { + std::string save = path; + size_t dotpos = path.rfind('.',path.size()); + size_t slashpos = path.rfind('/',path.size()); + if (dotpos != std::string::npos) { + if (slashpos == std::string::npos || dotpos > slashpos+1) { + path.erase(dotpos, path.size()-dotpos); + return true; + } + } + if (!isValid()) + path = save; + return false; +} + +static bool createDirectoryHelper(char* beg, char* end, bool create_parents) { + + if (access(beg, R_OK | W_OK) == 0) + return false; + + if (create_parents) { + + char* c = end; + + for (; c != beg; --c) + if (*c == '/') { + + // Recurse to handling the parent directory. + *c = '\0'; + bool x = createDirectoryHelper(beg, c, create_parents); + *c = '/'; + + // Return if we encountered an error. + if (x) + return true; + + break; + } + } + + return mkdir(beg, S_IRWXU | S_IRWXG) != 0; +} + +bool +Path::createDirectoryOnDisk( bool create_parents, std::string* ErrMsg ) { + // Get a writeable copy of the path name + char pathname[MAXPATHLEN]; + path.copy(pathname,MAXPATHLEN); + + // Null-terminate the last component + size_t lastchar = path.length() - 1 ; + + if (pathname[lastchar] != '/') + ++lastchar; + + pathname[lastchar] = 0; + + if (createDirectoryHelper(pathname, pathname+lastchar, create_parents)) + return MakeErrMsg(ErrMsg, + std::string(pathname) + ": can't create directory"); + + return false; +} + +bool +Path::createFileOnDisk(std::string* ErrMsg) { + // Create the file + int fd = ::creat(path.c_str(), S_IRUSR | S_IWUSR); + if (fd < 0) + return MakeErrMsg(ErrMsg, path + ": can't create file"); + ::close(fd); + return false; +} + +bool +Path::createTemporaryFileOnDisk(bool reuse_current, std::string* ErrMsg) { + // Make this into a unique file name + if (makeUnique( reuse_current, ErrMsg )) + return true; + + // create the file + int fd = ::open(path.c_str(), O_WRONLY|O_CREAT|O_TRUNC, 0666); + if (fd < 0) + return MakeErrMsg(ErrMsg, path + ": can't create temporary file"); + ::close(fd); + return false; +} + +bool +Path::eraseFromDisk(bool remove_contents, std::string *ErrStr) const { + // Get the status so we can determine if its a file or directory + struct stat buf; + if (0 != stat(path.c_str(), &buf)) { + MakeErrMsg(ErrStr, path + ": can't get status of file"); + return true; + } + + // Note: this check catches strange situations. In all cases, LLVM should + // only be involved in the creation and deletion of regular files. This + // check ensures that what we're trying to erase is a regular file. It + // effectively prevents LLVM from erasing things like /dev/null, any block + // special file, or other things that aren't "regular" files. + if (S_ISREG(buf.st_mode)) { + if (unlink(path.c_str()) != 0) + return MakeErrMsg(ErrStr, path + ": can't destroy file"); + return false; + } + + if (!S_ISDIR(buf.st_mode)) { + if (ErrStr) *ErrStr = "not a file or directory"; + return true; + } + + if (remove_contents) { + // Recursively descend the directory to remove its contents. + std::string cmd = "/bin/rm -rf " + path; + if (system(cmd.c_str()) != 0) { + MakeErrMsg(ErrStr, path + ": failed to recursively remove directory."); + return true; + } + return false; + } + + // Otherwise, try to just remove the one directory. + char pathname[MAXPATHLEN]; + path.copy(pathname, MAXPATHLEN); + size_t lastchar = path.length() - 1; + if (pathname[lastchar] == '/') + pathname[lastchar] = 0; + else + pathname[lastchar+1] = 0; + + if (rmdir(pathname) != 0) + return MakeErrMsg(ErrStr, + std::string(pathname) + ": can't erase directory"); + return false; +} + +bool +Path::renamePathOnDisk(const Path& newName, std::string* ErrMsg) { + if (0 != ::rename(path.c_str(), newName.c_str())) + return MakeErrMsg(ErrMsg, std::string("can't rename '") + path + "' as '" + + newName.str() + "'"); + return false; +} + +bool +Path::setStatusInfoOnDisk(const FileStatus &si, std::string *ErrStr) const { + struct utimbuf utb; + utb.actime = si.modTime.toPosixTime(); + utb.modtime = utb.actime; + if (0 != ::utime(path.c_str(),&utb)) + return MakeErrMsg(ErrStr, path + ": can't set file modification time"); + if (0 != ::chmod(path.c_str(),si.mode)) + return MakeErrMsg(ErrStr, path + ": can't set mode"); + return false; +} + +bool +sys::CopyFile(const sys::Path &Dest, const sys::Path &Src, std::string* ErrMsg){ + int inFile = -1; + int outFile = -1; + inFile = ::open(Src.c_str(), O_RDONLY); + if (inFile == -1) + return MakeErrMsg(ErrMsg, Src.str() + + ": can't open source file to copy"); + + outFile = ::open(Dest.c_str(), O_WRONLY|O_CREAT, 0666); + if (outFile == -1) { + ::close(inFile); + return MakeErrMsg(ErrMsg, Dest.str() + + ": can't create destination file for copy"); + } + + char Buffer[16*1024]; + while (ssize_t Amt = ::read(inFile, Buffer, 16*1024)) { + if (Amt == -1) { + if (errno != EINTR && errno != EAGAIN) { + ::close(inFile); + ::close(outFile); + return MakeErrMsg(ErrMsg, Src.str()+": can't read source file"); + } + } else { + char *BufPtr = Buffer; + while (Amt) { + ssize_t AmtWritten = ::write(outFile, BufPtr, Amt); + if (AmtWritten == -1) { + if (errno != EINTR && errno != EAGAIN) { + ::close(inFile); + ::close(outFile); + return MakeErrMsg(ErrMsg, Dest.str() + + ": can't write destination file"); + } + } else { + Amt -= AmtWritten; + BufPtr += AmtWritten; + } + } + } + } + ::close(inFile); + ::close(outFile); + return false; +} + +bool +Path::makeUnique(bool reuse_current, std::string* ErrMsg) { + if (reuse_current && !exists()) + return false; // File doesn't exist already, just use it! + + // Append an XXXXXX pattern to the end of the file for use with mkstemp, + // mktemp or our own implementation. + SmallVector Buf; + Buf.resize(path.size()+8); + char *FNBuffer = Buf.data(); + path.copy(FNBuffer,path.size()); + if (isDirectory()) + strcpy(FNBuffer+path.size(), "/XXXXXX"); + else + strcpy(FNBuffer+path.size(), "-XXXXXX"); + +#if defined(HAVE_MKSTEMP) + int TempFD; + if ((TempFD = mkstemp(FNBuffer)) == -1) + return MakeErrMsg(ErrMsg, path + ": can't make unique filename"); + + // We don't need to hold the temp file descriptor... we will trust that no one + // will overwrite/delete the file before we can open it again. + close(TempFD); + + // Save the name + path = FNBuffer; +#elif defined(HAVE_MKTEMP) + // If we don't have mkstemp, use the old and obsolete mktemp function. + if (mktemp(FNBuffer) == 0) + return MakeErrMsg(ErrMsg, path + ": can't make unique filename"); + + // Save the name + path = FNBuffer; +#else + // Okay, looks like we have to do it all by our lonesome. + static unsigned FCounter = 0; + unsigned offset = path.size() + 1; + while ( FCounter < 999999 && exists()) { + sprintf(FNBuffer+offset,"%06u",++FCounter); + path = FNBuffer; + } + if (FCounter > 999999) + return MakeErrMsg(ErrMsg, + path + ": can't make unique filename: too many files"); +#endif + return false; +} + +const char *Path::MapInFilePages(int FD, uint64_t FileSize) { + int Flags = MAP_PRIVATE; +#ifdef MAP_FILE + Flags |= MAP_FILE; +#endif + void *BasePtr = ::mmap(0, FileSize, PROT_READ, Flags, FD, 0); + if (BasePtr == MAP_FAILED) + return 0; + return (const char*)BasePtr; +} + +void Path::UnMapFilePages(const char *BasePtr, uint64_t FileSize) { + ::munmap((void*)BasePtr, FileSize); +} + +} // end llvm namespace diff --git a/libclamav/c++/llvm/lib/System/Unix/Process.inc b/libclamav/c++/llvm/lib/System/Unix/Process.inc new file mode 100644 index 000000000..911b8c325 --- /dev/null +++ b/libclamav/c++/llvm/lib/System/Unix/Process.inc @@ -0,0 +1,295 @@ +//===- Unix/Process.cpp - Unix Process Implementation --------- -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides the generic Unix implementation of the Process class. +// +//===----------------------------------------------------------------------===// + +#include "Unix.h" +#ifdef HAVE_SYS_TIME_H +#include +#endif +#ifdef HAVE_SYS_RESOURCE_H +#include +#endif +// DragonFly BSD has deprecated for instead, +// Unix.h includes this for us already. +#if defined(HAVE_MALLOC_H) && !defined(__DragonFly__) +#include +#endif +#ifdef HAVE_MALLOC_MALLOC_H +#include +#endif +#ifdef HAVE_SYS_IOCTL_H +# include +#endif +#ifdef HAVE_TERMIOS_H +# include +#endif + +//===----------------------------------------------------------------------===// +//=== WARNING: Implementation here must contain only generic UNIX code that +//=== is guaranteed to work on *all* UNIX variants. +//===----------------------------------------------------------------------===// + +using namespace llvm; +using namespace sys; + +unsigned +Process::GetPageSize() +{ +#if defined(__CYGWIN__) + // On Cygwin, getpagesize() returns 64k but the page size for the purposes of + // memory protection and mmap() is 4k. + // See http://www.cygwin.com/ml/cygwin/2009-01/threads.html#00492 + const int page_size = 0x1000; +#elif defined(HAVE_GETPAGESIZE) + const int page_size = ::getpagesize(); +#elif defined(HAVE_SYSCONF) + long page_size = ::sysconf(_SC_PAGE_SIZE); +#else +#warning Cannot get the page size on this machine +#endif + return static_cast(page_size); +} + +size_t Process::GetMallocUsage() { +#if defined(HAVE_MALLINFO) + struct mallinfo mi; + mi = ::mallinfo(); + return mi.uordblks; +#elif defined(HAVE_MALLOC_ZONE_STATISTICS) && defined(HAVE_MALLOC_MALLOC_H) + malloc_statistics_t Stats; + malloc_zone_statistics(malloc_default_zone(), &Stats); + return Stats.size_in_use; // darwin +#elif defined(HAVE_SBRK) + // Note this is only an approximation and more closely resembles + // the value returned by mallinfo in the arena field. + static char *StartOfMemory = reinterpret_cast(::sbrk(0)); + char *EndOfMemory = (char*)sbrk(0); + if (EndOfMemory != ((char*)-1) && StartOfMemory != ((char*)-1)) + return EndOfMemory - StartOfMemory; + else + return 0; +#else +#warning Cannot get malloc info on this platform + return 0; +#endif +} + +size_t +Process::GetTotalMemoryUsage() +{ +#if defined(HAVE_MALLINFO) + struct mallinfo mi = ::mallinfo(); + return mi.uordblks + mi.hblkhd; +#elif defined(HAVE_MALLOC_ZONE_STATISTICS) && defined(HAVE_MALLOC_MALLOC_H) + malloc_statistics_t Stats; + malloc_zone_statistics(malloc_default_zone(), &Stats); + return Stats.size_allocated; // darwin +#elif defined(HAVE_GETRUSAGE) && !defined(__HAIKU__) + struct rusage usage; + ::getrusage(RUSAGE_SELF, &usage); + return usage.ru_maxrss; +#else +#warning Cannot get total memory size on this platform + return 0; +#endif +} + +void +Process::GetTimeUsage(TimeValue& elapsed, TimeValue& user_time, + TimeValue& sys_time) +{ + elapsed = TimeValue::now(); +#if defined(HAVE_GETRUSAGE) + struct rusage usage; + ::getrusage(RUSAGE_SELF, &usage); + user_time = TimeValue( + static_cast( usage.ru_utime.tv_sec ), + static_cast( usage.ru_utime.tv_usec * + TimeValue::NANOSECONDS_PER_MICROSECOND ) ); + sys_time = TimeValue( + static_cast( usage.ru_stime.tv_sec ), + static_cast( usage.ru_stime.tv_usec * + TimeValue::NANOSECONDS_PER_MICROSECOND ) ); +#else +#warning Cannot get usage times on this platform + user_time.seconds(0); + user_time.microseconds(0); + sys_time.seconds(0); + sys_time.microseconds(0); +#endif +} + +int Process::GetCurrentUserId() { + return getuid(); +} + +int Process::GetCurrentGroupId() { + return getgid(); +} + +#ifdef HAVE_MACH_MACH_H +#include +#endif + +// Some LLVM programs such as bugpoint produce core files as a normal part of +// their operation. To prevent the disk from filling up, this function +// does what's necessary to prevent their generation. +void Process::PreventCoreFiles() { +#if HAVE_SETRLIMIT + struct rlimit rlim; + rlim.rlim_cur = rlim.rlim_max = 0; + setrlimit(RLIMIT_CORE, &rlim); +#endif + +#ifdef HAVE_MACH_MACH_H + // Disable crash reporting on Mac OS X 10.0-10.4 + + // get information about the original set of exception ports for the task + mach_msg_type_number_t Count = 0; + exception_mask_t OriginalMasks[EXC_TYPES_COUNT]; + exception_port_t OriginalPorts[EXC_TYPES_COUNT]; + exception_behavior_t OriginalBehaviors[EXC_TYPES_COUNT]; + thread_state_flavor_t OriginalFlavors[EXC_TYPES_COUNT]; + kern_return_t err = + task_get_exception_ports(mach_task_self(), EXC_MASK_ALL, OriginalMasks, + &Count, OriginalPorts, OriginalBehaviors, + OriginalFlavors); + if (err == KERN_SUCCESS) { + // replace each with MACH_PORT_NULL. + for (unsigned i = 0; i != Count; ++i) + task_set_exception_ports(mach_task_self(), OriginalMasks[i], + MACH_PORT_NULL, OriginalBehaviors[i], + OriginalFlavors[i]); + } + + // Disable crash reporting on Mac OS X 10.5 + signal(SIGABRT, _exit); + signal(SIGILL, _exit); + signal(SIGFPE, _exit); + signal(SIGSEGV, _exit); + signal(SIGBUS, _exit); +#endif +} + +bool Process::StandardInIsUserInput() { + return FileDescriptorIsDisplayed(STDIN_FILENO); +} + +bool Process::StandardOutIsDisplayed() { + return FileDescriptorIsDisplayed(STDOUT_FILENO); +} + +bool Process::StandardErrIsDisplayed() { + return FileDescriptorIsDisplayed(STDERR_FILENO); +} + +bool Process::FileDescriptorIsDisplayed(int fd) { +#if HAVE_ISATTY + return isatty(fd); +#else + // If we don't have isatty, just return false. + return false; +#endif +} + +static unsigned getColumns(int FileID) { + // If COLUMNS is defined in the environment, wrap to that many columns. + if (const char *ColumnsStr = std::getenv("COLUMNS")) { + int Columns = std::atoi(ColumnsStr); + if (Columns > 0) + return Columns; + } + + unsigned Columns = 0; + +#if defined(HAVE_SYS_IOCTL_H) && defined(HAVE_TERMIOS_H) + // Try to determine the width of the terminal. + struct winsize ws; + if (ioctl(FileID, TIOCGWINSZ, &ws) == 0) + Columns = ws.ws_col; +#endif + + return Columns; +} + +unsigned Process::StandardOutColumns() { + if (!StandardOutIsDisplayed()) + return 0; + + return getColumns(1); +} + +unsigned Process::StandardErrColumns() { + if (!StandardErrIsDisplayed()) + return 0; + + return getColumns(2); +} + +static bool terminalHasColors() { + if (const char *term = std::getenv("TERM")) { + // Most modern terminals support ANSI escape sequences for colors. + // We could check terminfo, or have a list of known terms that support + // colors, but that would be overkill. + // The user can always ask for no colors by setting TERM to dumb, or + // using a commandline flag. + return strcmp(term, "dumb") != 0; + } + return false; +} + +bool Process::StandardOutHasColors() { + if (!StandardOutIsDisplayed()) + return false; + return terminalHasColors(); +} + +bool Process::StandardErrHasColors() { + if (!StandardErrIsDisplayed()) + return false; + return terminalHasColors(); +} + +bool Process::ColorNeedsFlush() { + // No, we use ANSI escape sequences. + return false; +} + +#define COLOR(FGBG, CODE, BOLD) "\033[0;" BOLD FGBG CODE "m" + +#define ALLCOLORS(FGBG,BOLD) {\ + COLOR(FGBG, "0", BOLD),\ + COLOR(FGBG, "1", BOLD),\ + COLOR(FGBG, "2", BOLD),\ + COLOR(FGBG, "3", BOLD),\ + COLOR(FGBG, "4", BOLD),\ + COLOR(FGBG, "5", BOLD),\ + COLOR(FGBG, "6", BOLD),\ + COLOR(FGBG, "7", BOLD)\ + } + +static const char* colorcodes[2][2][8] = { + { ALLCOLORS("3",""), ALLCOLORS("3","1;") }, + { ALLCOLORS("4",""), ALLCOLORS("4","1;") } +}; + +const char *Process::OutputColor(char code, bool bold, bool bg) { + return colorcodes[bg?1:0][bold?1:0][code&7]; +} + +const char *Process::OutputBold(bool bg) { + return "\033[1m"; +} + +const char *Process::ResetColor() { + return "\033[0m"; +} diff --git a/libclamav/c++/llvm/lib/System/Unix/Program.inc b/libclamav/c++/llvm/lib/System/Unix/Program.inc new file mode 100644 index 000000000..43c3606d9 --- /dev/null +++ b/libclamav/c++/llvm/lib/System/Unix/Program.inc @@ -0,0 +1,326 @@ +//===- llvm/System/Unix/Program.cpp -----------------------------*- 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 the Unix specific portion of the Program class. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +//=== WARNING: Implementation here must contain only generic UNIX code that +//=== is guaranteed to work on *all* UNIX variants. +//===----------------------------------------------------------------------===// + +#include +#include "Unix.h" +#if HAVE_SYS_STAT_H +#include +#endif +#if HAVE_SYS_RESOURCE_H +#include +#endif +#if HAVE_SIGNAL_H +#include +#endif +#if HAVE_FCNTL_H +#include +#endif + +namespace llvm { +using namespace sys; + +Program::Program() : Data_(0) {} + +Program::~Program() {} + +unsigned Program::GetPid() const { + uint64_t pid = reinterpret_cast(Data_); + return static_cast(pid); +} + +// This function just uses the PATH environment variable to find the program. +Path +Program::FindProgramByName(const std::string& progName) { + + // Check some degenerate cases + if (progName.length() == 0) // no program + return Path(); + Path temp; + if (!temp.set(progName)) // invalid name + return Path(); + // Use the given path verbatim if it contains any slashes; this matches + // the behavior of sh(1) and friends. + if (progName.find('/') != std::string::npos) + return temp; + + // At this point, the file name does not contain slashes. Search for it + // through the directories specified in the PATH environment variable. + + // Get the path. If its empty, we can't do anything to find it. + const char *PathStr = getenv("PATH"); + if (PathStr == 0) + return Path(); + + // Now we have a colon separated list of directories to search; try them. + size_t PathLen = strlen(PathStr); + while (PathLen) { + // Find the first colon... + const char *Colon = std::find(PathStr, PathStr+PathLen, ':'); + + // Check to see if this first directory contains the executable... + Path FilePath; + if (FilePath.set(std::string(PathStr,Colon))) { + FilePath.appendComponent(progName); + if (FilePath.canExecute()) + return FilePath; // Found the executable! + } + + // Nope it wasn't in this directory, check the next path in the list! + PathLen -= Colon-PathStr; + PathStr = Colon; + + // Advance past duplicate colons + while (*PathStr == ':') { + PathStr++; + PathLen--; + } + } + return Path(); +} + +static bool RedirectIO(const Path *Path, int FD, std::string* ErrMsg) { + if (Path == 0) + // Noop + return false; + std::string File; + if (Path->isEmpty()) + // Redirect empty paths to /dev/null + File = "/dev/null"; + else + File = Path->str(); + + // Open the file + int InFD = open(File.c_str(), FD == 0 ? O_RDONLY : O_WRONLY|O_CREAT, 0666); + if (InFD == -1) { + MakeErrMsg(ErrMsg, "Cannot open file '" + File + "' for " + + (FD == 0 ? "input" : "output")); + return true; + } + + // Install it as the requested FD + if (-1 == dup2(InFD, FD)) { + MakeErrMsg(ErrMsg, "Cannot dup2"); + return true; + } + close(InFD); // Close the original FD + return false; +} + +static void TimeOutHandler(int Sig) { +} + +static void SetMemoryLimits (unsigned size) +{ +#if HAVE_SYS_RESOURCE_H + struct rlimit r; + __typeof__ (r.rlim_cur) limit = (__typeof__ (r.rlim_cur)) (size) * 1048576; + + // Heap size + getrlimit (RLIMIT_DATA, &r); + r.rlim_cur = limit; + setrlimit (RLIMIT_DATA, &r); +#ifdef RLIMIT_RSS + // Resident set size. + getrlimit (RLIMIT_RSS, &r); + r.rlim_cur = limit; + setrlimit (RLIMIT_RSS, &r); +#endif +#ifdef RLIMIT_AS // e.g. NetBSD doesn't have it. + // Virtual memory. + getrlimit (RLIMIT_AS, &r); + r.rlim_cur = limit; + setrlimit (RLIMIT_AS, &r); +#endif +#endif +} + +bool +Program::Execute(const Path& path, + const char** args, + const char** envp, + const Path** redirects, + unsigned memoryLimit, + std::string* ErrMsg) +{ + if (!path.canExecute()) { + if (ErrMsg) + *ErrMsg = path.str() + " is not executable"; + return false; + } + + // Create a child process. + int child = fork(); + switch (child) { + // An error occured: Return to the caller. + case -1: + MakeErrMsg(ErrMsg, "Couldn't fork"); + return false; + + // Child process: Execute the program. + case 0: { + // Redirect file descriptors... + if (redirects) { + // Redirect stdin + if (RedirectIO(redirects[0], 0, ErrMsg)) { return false; } + // Redirect stdout + if (RedirectIO(redirects[1], 1, ErrMsg)) { return false; } + if (redirects[1] && redirects[2] && + *(redirects[1]) == *(redirects[2])) { + // If stdout and stderr should go to the same place, redirect stderr + // to the FD already open for stdout. + if (-1 == dup2(1,2)) { + MakeErrMsg(ErrMsg, "Can't redirect stderr to stdout"); + return false; + } + } else { + // Just redirect stderr + if (RedirectIO(redirects[2], 2, ErrMsg)) { return false; } + } + } + + // Set memory limits + if (memoryLimit!=0) { + SetMemoryLimits(memoryLimit); + } + + // Execute! + if (envp != 0) + execve(path.c_str(), (char**)args, (char**)envp); + else + execv(path.c_str(), (char**)args); + // If the execve() failed, we should exit. Follow Unix protocol and + // return 127 if the executable was not found, and 126 otherwise. + // Use _exit rather than exit so that atexit functions and static + // object destructors cloned from the parent process aren't + // redundantly run, and so that any data buffered in stdio buffers + // cloned from the parent aren't redundantly written out. + _exit(errno == ENOENT ? 127 : 126); + } + + // Parent process: Break out of the switch to do our processing. + default: + break; + } + + Data_ = reinterpret_cast(child); + + return true; +} + +int +Program::Wait(unsigned secondsToWait, + std::string* ErrMsg) +{ +#ifdef HAVE_SYS_WAIT_H + struct sigaction Act, Old; + + if (Data_ == 0) { + MakeErrMsg(ErrMsg, "Process not started!"); + return -1; + } + + // Install a timeout handler. The handler itself does nothing, but the simple + // fact of having a handler at all causes the wait below to return with EINTR, + // unlike if we used SIG_IGN. + if (secondsToWait) { + Act.sa_sigaction = 0; + Act.sa_handler = TimeOutHandler; + sigemptyset(&Act.sa_mask); + Act.sa_flags = 0; + sigaction(SIGALRM, &Act, &Old); + alarm(secondsToWait); + } + + // Parent process: Wait for the child process to terminate. + int status; + uint64_t pid = reinterpret_cast(Data_); + pid_t child = static_cast(pid); + while (waitpid(pid, &status, 0) != child) + if (secondsToWait && errno == EINTR) { + // Kill the child. + kill(child, SIGKILL); + + // Turn off the alarm and restore the signal handler + alarm(0); + sigaction(SIGALRM, &Old, 0); + + // Wait for child to die + if (wait(&status) != child) + MakeErrMsg(ErrMsg, "Child timed out but wouldn't die"); + else + MakeErrMsg(ErrMsg, "Child timed out", 0); + + return -1; // Timeout detected + } else if (errno != EINTR) { + MakeErrMsg(ErrMsg, "Error waiting for child process"); + return -1; + } + + // We exited normally without timeout, so turn off the timer. + if (secondsToWait) { + alarm(0); + sigaction(SIGALRM, &Old, 0); + } + + // Return the proper exit status. 0=success, >0 is programs' exit status, + // <0 means a signal was returned, -9999999 means the program dumped core. + int result = 0; + if (WIFEXITED(status)) + result = WEXITSTATUS(status); + else if (WIFSIGNALED(status)) + result = 0 - WTERMSIG(status); +#ifdef WCOREDUMP + else if (WCOREDUMP(status)) + result |= 0x01000000; +#endif + return result; +#else + return -99; +#endif + +} + +bool +Program::Kill(std::string* ErrMsg) { + if (Data_ == 0) { + MakeErrMsg(ErrMsg, "Process not started!"); + return true; + } + + uint64_t pid64 = reinterpret_cast(Data_); + pid_t pid = static_cast(pid64); + + if (kill(pid, SIGKILL) != 0) { + MakeErrMsg(ErrMsg, "The process couldn't be killed!"); + return true; + } + + return false; +} + +bool Program::ChangeStdinToBinary(){ + // Do nothing, as Unix doesn't differentiate between text and binary. + return false; +} + +bool Program::ChangeStdoutToBinary(){ + // Do nothing, as Unix doesn't differentiate between text and binary. + return false; +} + +} diff --git a/libclamav/c++/llvm/lib/System/Unix/README.txt b/libclamav/c++/llvm/lib/System/Unix/README.txt new file mode 100644 index 000000000..b3bace483 --- /dev/null +++ b/libclamav/c++/llvm/lib/System/Unix/README.txt @@ -0,0 +1,16 @@ +llvm/lib/System/Unix README +=========================== + +This directory provides implementations of the lib/System classes that +are common to two or more variants of UNIX. For example, the directory +structure underneath this directory could look like this: + +Unix - only code that is truly generic to all UNIX platforms + Posix - code that is specific to Posix variants of UNIX + SUS - code that is specific to the Single Unix Specification + SysV - code that is specific to System V variants of UNIX + +As a rule, only those directories actually needing to be created should be +created. Also, further subdirectories could be created to reflect versions of +the various standards. For example, under SUS there could be v1, v2, and v3 +subdirectories to reflect the three major versions of SUS. diff --git a/libclamav/c++/llvm/lib/System/Unix/RWMutex.inc b/libclamav/c++/llvm/lib/System/Unix/RWMutex.inc new file mode 100644 index 000000000..e83d41ef4 --- /dev/null +++ b/libclamav/c++/llvm/lib/System/Unix/RWMutex.inc @@ -0,0 +1,43 @@ +//= llvm/System/Unix/RWMutex.inc - Unix Reader/Writer Mutual Exclusion Lock =// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the Unix specific (non-pthread) RWMutex class. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +//=== WARNING: Implementation here must contain only generic UNIX code that +//=== is guaranteed to work on *all* UNIX variants. +//===----------------------------------------------------------------------===// + +namespace llvm { + +using namespace sys; + +RWMutexImpl::RWMutexImpl() { } + +RWMutexImpl::~RWMutexImpl() { } + +bool RWMutexImpl::reader_acquire() { + return true; +} + +bool RWMutexImpl::reader_release() { + return true; +} + +bool RWMutexImpl::writer_acquire() { + return true; +} + +bool RWMutexImpl::writer_release() { + return true; +} + +} diff --git a/libclamav/c++/llvm/lib/System/Unix/Signals.inc b/libclamav/c++/llvm/lib/System/Unix/Signals.inc new file mode 100644 index 000000000..676e1e535 --- /dev/null +++ b/libclamav/c++/llvm/lib/System/Unix/Signals.inc @@ -0,0 +1,244 @@ +//===- Signals.cpp - Generic Unix Signals Implementation -----*- 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 some helpful functions for dealing with the possibility of +// Unix signals occuring while your program is running. +// +//===----------------------------------------------------------------------===// + +#include "Unix.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/System/Mutex.h" +#include +#include +#if HAVE_EXECINFO_H +# include // For backtrace(). +#endif +#if HAVE_SIGNAL_H +#include +#endif +#if HAVE_SYS_STAT_H +#include +#endif +#if HAVE_DLFCN_H && __GNUG__ +#include +#include +#endif +using namespace llvm; + +static RETSIGTYPE SignalHandler(int Sig); // defined below. + +static SmartMutex SignalsMutex; + +/// InterruptFunction - The function to call if ctrl-c is pressed. +static void (*InterruptFunction)() = 0; + +static std::vector *FilesToRemove = 0; +static std::vector > *CallBacksToRun = 0; + +// IntSigs - Signals that may interrupt the program at any time. +static const int IntSigs[] = { + SIGHUP, SIGINT, SIGQUIT, SIGPIPE, SIGTERM, SIGUSR1, SIGUSR2 +}; +static const int *const IntSigsEnd = + IntSigs + sizeof(IntSigs) / sizeof(IntSigs[0]); + +// KillSigs - Signals that are synchronous with the program that will cause it +// to die. +static const int KillSigs[] = { + SIGILL, SIGTRAP, SIGABRT, SIGFPE, SIGBUS, SIGSEGV, SIGSYS, SIGXCPU, SIGXFSZ +#ifdef SIGEMT + , SIGEMT +#endif +}; +static const int *const KillSigsEnd = + KillSigs + sizeof(KillSigs) / sizeof(KillSigs[0]); + +static unsigned NumRegisteredSignals = 0; +static struct { + struct sigaction SA; + int SigNo; +} RegisteredSignalInfo[(sizeof(IntSigs)+sizeof(KillSigs))/sizeof(KillSigs[0])]; + + +static void RegisterHandler(int Signal) { + assert(NumRegisteredSignals < + sizeof(RegisteredSignalInfo)/sizeof(RegisteredSignalInfo[0]) && + "Out of space for signal handlers!"); + + struct sigaction NewHandler; + + NewHandler.sa_handler = SignalHandler; + NewHandler.sa_flags = SA_NODEFER|SA_RESETHAND; + sigemptyset(&NewHandler.sa_mask); + + // Install the new handler, save the old one in RegisteredSignalInfo. + sigaction(Signal, &NewHandler, + &RegisteredSignalInfo[NumRegisteredSignals].SA); + RegisteredSignalInfo[NumRegisteredSignals].SigNo = Signal; + ++NumRegisteredSignals; +} + +static void RegisterHandlers() { + // If the handlers are already registered, we're done. + if (NumRegisteredSignals != 0) return; + + std::for_each(IntSigs, IntSigsEnd, RegisterHandler); + std::for_each(KillSigs, KillSigsEnd, RegisterHandler); +} + +static void UnregisterHandlers() { + // Restore all of the signal handlers to how they were before we showed up. + for (unsigned i = 0, e = NumRegisteredSignals; i != e; ++i) + sigaction(RegisteredSignalInfo[i].SigNo, + &RegisteredSignalInfo[i].SA, 0); + NumRegisteredSignals = 0; +} + + + +// SignalHandler - The signal handler that runs. +static RETSIGTYPE SignalHandler(int Sig) { + // Restore the signal behavior to default, so that the program actually + // crashes when we return and the signal reissues. This also ensures that if + // we crash in our signal handler that the program will terminate immediately + // instead of recursing in the signal handler. + UnregisterHandlers(); + + // Unmask all potentially blocked kill signals. + sigset_t SigMask; + sigfillset(&SigMask); + sigprocmask(SIG_UNBLOCK, &SigMask, 0); + + SignalsMutex.acquire(); + if (FilesToRemove != 0) + while (!FilesToRemove->empty()) { + FilesToRemove->back().eraseFromDisk(true); + FilesToRemove->pop_back(); + } + + if (std::find(IntSigs, IntSigsEnd, Sig) != IntSigsEnd) { + if (InterruptFunction) { + void (*IF)() = InterruptFunction; + SignalsMutex.release(); + InterruptFunction = 0; + IF(); // run the interrupt function. + return; + } + + SignalsMutex.release(); + raise(Sig); // Execute the default handler. + return; + } + + SignalsMutex.release(); + + // Otherwise if it is a fault (like SEGV) run any handler. + if (CallBacksToRun) + for (unsigned i = 0, e = CallBacksToRun->size(); i != e; ++i) + (*CallBacksToRun)[i].first((*CallBacksToRun)[i].second); +} + + + +void llvm::sys::SetInterruptFunction(void (*IF)()) { + SignalsMutex.acquire(); + InterruptFunction = IF; + SignalsMutex.release(); + RegisterHandlers(); +} + +// RemoveFileOnSignal - The public API +bool llvm::sys::RemoveFileOnSignal(const sys::Path &Filename, + std::string* ErrMsg) { + SignalsMutex.acquire(); + if (FilesToRemove == 0) + FilesToRemove = new std::vector(); + + FilesToRemove->push_back(Filename); + + SignalsMutex.release(); + + RegisterHandlers(); + return false; +} + +/// AddSignalHandler - Add a function to be called when a signal is delivered +/// to the process. The handler can have a cookie passed to it to identify +/// what instance of the handler it is. +void llvm::sys::AddSignalHandler(void (*FnPtr)(void *), void *Cookie) { + if (CallBacksToRun == 0) + CallBacksToRun = new std::vector >(); + CallBacksToRun->push_back(std::make_pair(FnPtr, Cookie)); + RegisterHandlers(); +} + + +// PrintStackTrace - In the case of a program crash or fault, print out a stack +// trace so that the user has an indication of why and where we died. +// +// On glibc systems we have the 'backtrace' function, which works nicely, but +// doesn't demangle symbols. +static void PrintStackTrace(void *) { +#ifdef HAVE_BACKTRACE + static void* StackTrace[256]; + // Use backtrace() to output a backtrace on Linux systems with glibc. + int depth = backtrace(StackTrace, + static_cast(array_lengthof(StackTrace))); +#if HAVE_DLFCN_H && __GNUG__ + int width = 0; + for (int i = 0; i < depth; ++i) { + Dl_info dlinfo; + dladdr(StackTrace[i], &dlinfo); + const char* name = strrchr(dlinfo.dli_fname, '/'); + + int nwidth; + if (name == NULL) nwidth = strlen(dlinfo.dli_fname); + else nwidth = strlen(name) - 1; + + if (nwidth > width) width = nwidth; + } + + for (int i = 0; i < depth; ++i) { + Dl_info dlinfo; + dladdr(StackTrace[i], &dlinfo); + + fprintf(stderr, "%-2d", i); + + const char* name = strrchr(dlinfo.dli_fname, '/'); + if (name == NULL) fprintf(stderr, " %-*s", width, dlinfo.dli_fname); + else fprintf(stderr, " %-*s", width, name+1); + + fprintf(stderr, " %#0*lx", + (int)(sizeof(void*) * 2) + 2, (unsigned long)StackTrace[i]); + + if (dlinfo.dli_sname != NULL) { + int res; + fputc(' ', stderr); + char* d = abi::__cxa_demangle(dlinfo.dli_sname, NULL, NULL, &res); + if (d == NULL) fputs(dlinfo.dli_sname, stderr); + else fputs(d, stderr); + free(d); + + fprintf(stderr, " + %tu",(char*)StackTrace[i]-(char*)dlinfo.dli_saddr); + } + fputc('\n', stderr); + } +#else + backtrace_symbols_fd(StackTrace, depth, STDERR_FILENO); +#endif +#endif +} + +/// PrintStackTraceOnErrorSignal - When an error signal (such as SIBABRT or +/// SIGSEGV) is delivered to the process, print a stack trace and then exit. +void llvm::sys::PrintStackTraceOnErrorSignal() { + AddSignalHandler(PrintStackTrace, 0); +} + diff --git a/libclamav/c++/llvm/lib/System/Unix/ThreadLocal.inc b/libclamav/c++/llvm/lib/System/Unix/ThreadLocal.inc new file mode 100644 index 000000000..83d554d30 --- /dev/null +++ b/libclamav/c++/llvm/lib/System/Unix/ThreadLocal.inc @@ -0,0 +1,25 @@ +//=== llvm/System/Unix/ThreadLocal.inc - Unix Thread Local Data -*- 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 the Unix specific (non-pthread) ThreadLocal class. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +//=== WARNING: Implementation here must contain only generic UNIX code that +//=== is guaranteed to work on *all* UNIX variants. +//===----------------------------------------------------------------------===// + +namespace llvm { +using namespace sys; +ThreadLocalImpl::ThreadLocalImpl() { } +ThreadLocalImpl::~ThreadLocalImpl() { } +void ThreadLocalImpl::setInstance(const void* d) { data = const_cast(d);} +const void* ThreadLocalImpl::getInstance() { return data; } +} diff --git a/libclamav/c++/llvm/lib/System/Unix/TimeValue.inc b/libclamav/c++/llvm/lib/System/Unix/TimeValue.inc new file mode 100644 index 000000000..1ae8c7184 --- /dev/null +++ b/libclamav/c++/llvm/lib/System/Unix/TimeValue.inc @@ -0,0 +1,56 @@ +//===- Unix/TimeValue.cpp - Unix TimeValue Implementation -------*- 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 the Unix specific portion of the TimeValue class. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +//=== WARNING: Implementation here must contain only generic UNIX code that +//=== is guaranteed to work on *all* UNIX variants. +//===----------------------------------------------------------------------===// + +#include "Unix.h" + +namespace llvm { + using namespace sys; + +std::string TimeValue::str() const { + char buffer[32]; + + time_t ourTime = time_t(this->toEpochTime()); +#ifdef __hpux +// note that the following line needs -D_REENTRANT on HP-UX to be picked up + asctime_r(localtime(&ourTime), buffer); +#else + ::asctime_r(::localtime(&ourTime), buffer); +#endif + + std::string result(buffer); + return result.substr(0,24); +} + +TimeValue TimeValue::now() { + struct timeval the_time; + timerclear(&the_time); + if (0 != ::gettimeofday(&the_time,0)) { + // This is *really* unlikely to occur because the only gettimeofday + // errors concern the timezone parameter which we're passing in as 0. + // In the unlikely case it does happen, just return MinTime, no error + // message needed. + return MinTime; + } + + return TimeValue( + static_cast( the_time.tv_sec ), + static_cast( the_time.tv_usec * + NANOSECONDS_PER_MICROSECOND ) ); +} + +} diff --git a/libclamav/c++/llvm/lib/System/Unix/Unix.h b/libclamav/c++/llvm/lib/System/Unix/Unix.h new file mode 100644 index 000000000..c15866f3d --- /dev/null +++ b/libclamav/c++/llvm/lib/System/Unix/Unix.h @@ -0,0 +1,87 @@ +//===- llvm/System/Unix/Unix.h - Common Unix Include File -------*- 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 things specific to Unix implementations. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SYSTEM_UNIX_UNIX_H +#define LLVM_SYSTEM_UNIX_UNIX_H + +//===----------------------------------------------------------------------===// +//=== WARNING: Implementation here must contain only generic UNIX code that +//=== is guaranteed to work on all UNIX variants. +//===----------------------------------------------------------------------===// + +#include "llvm/Config/config.h" // Get autoconf configuration settings +#include "llvm/System/Errno.h" +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_UNISTD_H +#include +#endif + +#ifdef HAVE_SYS_TYPES_H +#include +#endif + +#ifdef HAVE_SYS_PARAM_H +#include +#endif + +#ifdef HAVE_ASSERT_H +#include +#endif + +#ifdef TIME_WITH_SYS_TIME +# include +# include +#else +# ifdef HAVE_SYS_TIME_H +# include +# else +# include +# endif +#endif + +#ifdef HAVE_SYS_WAIT_H +# include +#endif + +#ifndef WEXITSTATUS +# define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8) +#endif + +#ifndef WIFEXITED +# define WIFEXITED(stat_val) (((stat_val) & 255) == 0) +#endif + +/// This function builds an error message into \p ErrMsg using the \p prefix +/// string and the Unix error number given by \p errnum. If errnum is -1, the +/// default then the value of errno is used. +/// @brief Make an error message +/// +/// If the error number can be converted to a string, it will be +/// separated from prefix by ": ". +static inline bool MakeErrMsg( + std::string* ErrMsg, const std::string& prefix, int errnum = -1) { + if (!ErrMsg) + return true; + if (errnum == -1) + errnum = errno; + *ErrMsg = prefix + ": " + llvm::sys::StrError(errnum); + return true; +} + +#endif diff --git a/libclamav/c++/llvm/lib/System/Win32/Alarm.inc b/libclamav/c++/llvm/lib/System/Win32/Alarm.inc new file mode 100644 index 000000000..e0d00a014 --- /dev/null +++ b/libclamav/c++/llvm/lib/System/Win32/Alarm.inc @@ -0,0 +1,43 @@ +//===-- Alarm.inc - Implement Win32 Alarm Support ---------------*- 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 the Win32 Alarm support. +// +//===----------------------------------------------------------------------===// + +#include +using namespace llvm; + +/// NestedSOI - Sanity check. Alarms cannot be nested or run in parallel. +/// This ensures that they never do. +static bool NestedSOI = false; + +void sys::SetupAlarm(unsigned seconds) { + assert(!NestedSOI && "sys::SetupAlarm calls cannot be nested!"); + NestedSOI = true; + // FIXME: Implement for Win32 +} + +void sys::TerminateAlarm() { + assert(NestedSOI && "sys::TerminateAlarm called without sys::SetupAlarm!"); + // FIXME: Implement for Win32 + NestedSOI = false; +} + +int sys::AlarmStatus() { + // FIXME: Implement for Win32 + return 0; +} + +// Don't pull in all of the Windows headers. +extern "C" void __stdcall Sleep(unsigned long); + +void sys::Sleep(unsigned n) { + ::Sleep(n*1000); +} diff --git a/libclamav/c++/llvm/lib/System/Win32/DynamicLibrary.inc b/libclamav/c++/llvm/lib/System/Win32/DynamicLibrary.inc new file mode 100644 index 000000000..10e64aa99 --- /dev/null +++ b/libclamav/c++/llvm/lib/System/Win32/DynamicLibrary.inc @@ -0,0 +1,200 @@ +//===- Win32/DynamicLibrary.cpp - Win32 DL Implementation -------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides the Win32 specific implementation of DynamicLibrary. +// +//===----------------------------------------------------------------------===// + +#include "Win32.h" + +#ifdef __MINGW32__ + #include +#else + #include +#endif + +#ifdef _MSC_VER + #include +#endif + +#ifdef __MINGW32__ + #if (HAVE_LIBIMAGEHLP != 1) + #error "libimagehlp.a should be present" + #endif +#else + #pragma comment(lib, "dbghelp.lib") +#endif + +namespace llvm { +using namespace sys; + +//===----------------------------------------------------------------------===// +//=== WARNING: Implementation here must contain only Win32 specific code +//=== and must not be UNIX code. +//===----------------------------------------------------------------------===// + +static std::vector OpenedHandles; + +#ifdef _WIN64 + typedef DWORD64 ModuleBaseType; +#else + typedef ULONG ModuleBaseType; +#endif + +extern "C" { +// Use old callback if: +// - Not using Visual Studio +// - Visual Studio 2005 or earlier but only if we are not using the Windows SDK +// or Windows SDK version is older than 6.0 +// Use new callback if: +// - Newer Visual Studio (comes with newer SDK). +// - Visual Studio 2005 with Windows SDK 6.0+ +#if !defined(_MSC_VER) || _MSC_VER < 1500 && (!defined(VER_PRODUCTBUILD) || VER_PRODUCTBUILD < 6000) + static BOOL CALLBACK ELM_Callback(PSTR ModuleName, + ModuleBaseType ModuleBase, + ULONG ModuleSize, + PVOID UserContext) +#else + static BOOL CALLBACK ELM_Callback(PCSTR ModuleName, + ModuleBaseType ModuleBase, + ULONG ModuleSize, + PVOID UserContext) +#endif + { + // Ignore VC++ runtimes prior to 7.1. Somehow some of them get loaded + // into the process. + if (stricmp(ModuleName, "msvci70") != 0 && + stricmp(ModuleName, "msvcirt") != 0 && + stricmp(ModuleName, "msvcp50") != 0 && + stricmp(ModuleName, "msvcp60") != 0 && + stricmp(ModuleName, "msvcp70") != 0 && + stricmp(ModuleName, "msvcr70") != 0 && +#ifndef __MINGW32__ + // Mingw32 uses msvcrt.dll by default. Don't ignore it. + // Otherwise, user should be aware, what he's doing :) + stricmp(ModuleName, "msvcrt") != 0 && +#endif + stricmp(ModuleName, "msvcrt20") != 0 && + stricmp(ModuleName, "msvcrt40") != 0) { + OpenedHandles.push_back((HMODULE)ModuleBase); + } + return TRUE; + } +} + +bool DynamicLibrary::LoadLibraryPermanently(const char *filename, + std::string *ErrMsg) { + if (filename) { + HMODULE a_handle = LoadLibrary(filename); + + if (a_handle == 0) + return MakeErrMsg(ErrMsg, std::string(filename) + ": Can't open : "); + + OpenedHandles.push_back(a_handle); + } else { + // When no file is specified, enumerate all DLLs and EXEs in the + // process. + EnumerateLoadedModules(GetCurrentProcess(), ELM_Callback, 0); + } + + // Because we don't remember the handle, we will never free it; hence, + // it is loaded permanently. + return false; +} + +// Stack probing routines are in the support library (e.g. libgcc), but we don't +// have dynamic linking on windows. Provide a hook. +#if defined(__MINGW32__) || defined (_MSC_VER) + #define EXPLICIT_SYMBOL(SYM) \ + if (!strcmp(symbolName, #SYM)) return (void*)&SYM + #define EXPLICIT_SYMBOL2(SYMFROM, SYMTO) \ + if (!strcmp(symbolName, #SYMFROM)) return (void*)&SYMTO + #define EXPLICIT_SYMBOL_DEF(SYM) \ + extern "C" { extern void *SYM; } + + #if defined(__MINGW32__) + EXPLICIT_SYMBOL_DEF(_alloca); + EXPLICIT_SYMBOL_DEF(__main); + EXPLICIT_SYMBOL_DEF(__ashldi3); + EXPLICIT_SYMBOL_DEF(__ashrdi3); + EXPLICIT_SYMBOL_DEF(__cmpdi2); + EXPLICIT_SYMBOL_DEF(__divdi3); + EXPLICIT_SYMBOL_DEF(__fixdfdi); + EXPLICIT_SYMBOL_DEF(__fixsfdi); + EXPLICIT_SYMBOL_DEF(__fixunsdfdi); + EXPLICIT_SYMBOL_DEF(__fixunssfdi); + EXPLICIT_SYMBOL_DEF(__floatdidf); + EXPLICIT_SYMBOL_DEF(__floatdisf); + EXPLICIT_SYMBOL_DEF(__lshrdi3); + EXPLICIT_SYMBOL_DEF(__moddi3); + EXPLICIT_SYMBOL_DEF(__udivdi3); + EXPLICIT_SYMBOL_DEF(__umoddi3); + #elif defined(_MSC_VER) + EXPLICIT_SYMBOL_DEF(_alloca_probe); + #endif +#endif + +void* DynamicLibrary::SearchForAddressOfSymbol(const char* symbolName) { + // First check symbols added via AddSymbol(). + if (ExplicitSymbols) { + std::map::iterator I = + ExplicitSymbols->find(symbolName); + std::map::iterator E = ExplicitSymbols->end(); + if (I != E) + return I->second; + } + + // Now search the libraries. + for (std::vector::iterator I = OpenedHandles.begin(), + E = OpenedHandles.end(); I != E; ++I) { + FARPROC ptr = GetProcAddress((HMODULE)*I, symbolName); + if (ptr) { + return (void *) ptr; + } + } + +#if defined(__MINGW32__) + { + EXPLICIT_SYMBOL(_alloca); + EXPLICIT_SYMBOL(__main); + EXPLICIT_SYMBOL(__ashldi3); + EXPLICIT_SYMBOL(__ashrdi3); + EXPLICIT_SYMBOL(__cmpdi2); + EXPLICIT_SYMBOL(__divdi3); + EXPLICIT_SYMBOL(__fixdfdi); + EXPLICIT_SYMBOL(__fixsfdi); + EXPLICIT_SYMBOL(__fixunsdfdi); + EXPLICIT_SYMBOL(__fixunssfdi); + EXPLICIT_SYMBOL(__floatdidf); + EXPLICIT_SYMBOL(__floatdisf); + EXPLICIT_SYMBOL(__lshrdi3); + EXPLICIT_SYMBOL(__moddi3); + EXPLICIT_SYMBOL(__udivdi3); + EXPLICIT_SYMBOL(__umoddi3); + + EXPLICIT_SYMBOL2(alloca, _alloca); +#undef EXPLICIT_SYMBOL +#undef EXPLICIT_SYMBOL2 +#undef EXPLICIT_SYMBOL_DEF + } +#elif defined(_MSC_VER) + { + EXPLICIT_SYMBOL2(alloca, _alloca_probe); + EXPLICIT_SYMBOL2(_alloca, _alloca_probe); +#undef EXPLICIT_SYMBOL +#undef EXPLICIT_SYMBOL2 +#undef EXPLICIT_SYMBOL_DEF + } +#endif + + return 0; +} + +} + diff --git a/libclamav/c++/llvm/lib/System/Win32/Host.inc b/libclamav/c++/llvm/lib/System/Win32/Host.inc new file mode 100644 index 000000000..18f00f8bc --- /dev/null +++ b/libclamav/c++/llvm/lib/System/Win32/Host.inc @@ -0,0 +1,23 @@ +//===- llvm/System/Win32/Host.inc -------------------------------*- 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 the Win32 Host support. +// +//===----------------------------------------------------------------------===// + +#include "Win32.h" +#include +#include + +using namespace llvm; + +std::string sys::getHostTriple() { + // FIXME: Adapt to running version. + return LLVM_HOSTTRIPLE; +} diff --git a/libclamav/c++/llvm/lib/System/Win32/Memory.inc b/libclamav/c++/llvm/lib/System/Win32/Memory.inc new file mode 100644 index 000000000..19fccbddc --- /dev/null +++ b/libclamav/c++/llvm/lib/System/Win32/Memory.inc @@ -0,0 +1,73 @@ +//===- Win32/Memory.cpp - Win32 Memory Implementation -----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides the Win32 specific implementation of various Memory +// management utilities +// +//===----------------------------------------------------------------------===// + +#include "Win32.h" +#include "llvm/System/DataTypes.h" +#include "llvm/System/Process.h" + +namespace llvm { +using namespace sys; + +//===----------------------------------------------------------------------===// +//=== WARNING: Implementation here must contain only Win32 specific code +//=== and must not be UNIX code +//===----------------------------------------------------------------------===// + +MemoryBlock Memory::AllocateRWX(size_t NumBytes, + const MemoryBlock *NearBlock, + std::string *ErrMsg) { + if (NumBytes == 0) return MemoryBlock(); + + static const size_t pageSize = Process::GetPageSize(); + size_t NumPages = (NumBytes+pageSize-1)/pageSize; + + //FIXME: support NearBlock if ever needed on Win64. + + void *pa = VirtualAlloc(NULL, NumPages*pageSize, MEM_COMMIT, + PAGE_EXECUTE_READWRITE); + if (pa == NULL) { + MakeErrMsg(ErrMsg, "Can't allocate RWX Memory: "); + return MemoryBlock(); + } + + MemoryBlock result; + result.Address = pa; + result.Size = NumPages*pageSize; + return result; +} + +bool Memory::ReleaseRWX(MemoryBlock &M, std::string *ErrMsg) { + if (M.Address == 0 || M.Size == 0) return false; + if (!VirtualFree(M.Address, 0, MEM_RELEASE)) + return MakeErrMsg(ErrMsg, "Can't release RWX Memory: "); + return false; +} + +bool Memory::setWritable(MemoryBlock &M, std::string *ErrMsg) { + return true; +} + +bool Memory::setExecutable(MemoryBlock &M, std::string *ErrMsg) { + return false; +} + +bool Memory::setRangeWritable(const void *Addr, size_t Size) { + return true; +} + +bool Memory::setRangeExecutable(const void *Addr, size_t Size) { + return false; +} + +} diff --git a/libclamav/c++/llvm/lib/System/Win32/Mutex.inc b/libclamav/c++/llvm/lib/System/Win32/Mutex.inc new file mode 100644 index 000000000..75f01fefa --- /dev/null +++ b/libclamav/c++/llvm/lib/System/Win32/Mutex.inc @@ -0,0 +1,58 @@ +//===- llvm/System/Win32/Mutex.inc - Win32 Mutex Implementation -*- 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 the Win32 specific (non-pthread) Mutex class. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +//=== WARNING: Implementation here must contain only generic Win32 code that +//=== is guaranteed to work on *all* Win32 variants. +//===----------------------------------------------------------------------===// + +#include "Win32.h" +#include "llvm/System/Mutex.h" + +namespace llvm { +using namespace sys; + +MutexImpl::MutexImpl(bool /*recursive*/) +{ + data_ = new CRITICAL_SECTION; + InitializeCriticalSection((LPCRITICAL_SECTION)data_); +} + +MutexImpl::~MutexImpl() +{ + DeleteCriticalSection((LPCRITICAL_SECTION)data_); + delete (LPCRITICAL_SECTION)data_; + data_ = 0; +} + +bool +MutexImpl::acquire() +{ + EnterCriticalSection((LPCRITICAL_SECTION)data_); + return true; +} + +bool +MutexImpl::release() +{ + LeaveCriticalSection((LPCRITICAL_SECTION)data_); + return true; +} + +bool +MutexImpl::tryacquire() +{ + return TryEnterCriticalSection((LPCRITICAL_SECTION)data_); +} + +} diff --git a/libclamav/c++/llvm/lib/System/Win32/Path.inc b/libclamav/c++/llvm/lib/System/Win32/Path.inc new file mode 100644 index 000000000..634fbc765 --- /dev/null +++ b/libclamav/c++/llvm/lib/System/Win32/Path.inc @@ -0,0 +1,874 @@ +//===- llvm/System/Win32/Path.cpp - Win32 Path Implementation ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +// Modified by Henrik Bach to comply with at least MinGW. +// Ported to Win32 by Jeff Cohen. +// +//===----------------------------------------------------------------------===// +// +// This file provides the Win32 specific implementation of the Path class. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +//=== WARNING: Implementation here must contain only generic Win32 code that +//=== is guaranteed to work on *all* Win32 variants. +//===----------------------------------------------------------------------===// + +#include "Win32.h" +#include +#include + +// We need to undo a macro defined in Windows.h, otherwise we won't compile: +#undef CopyFile +#undef GetCurrentDirectory + +// Windows happily accepts either forward or backward slashes, though any path +// returned by a Win32 API will have backward slashes. As LLVM code basically +// assumes forward slashes are used, backward slashs are converted where they +// can be introduced into a path. +// +// Another invariant is that a path ends with a slash if and only if the path +// is a root directory. Any other use of a trailing slash is stripped. Unlike +// in Unix, Windows has a rather complicated notion of a root path and this +// invariant helps simply the code. + +static void FlipBackSlashes(std::string& s) { + for (size_t i = 0; i < s.size(); i++) + if (s[i] == '\\') + s[i] = '/'; +} + +namespace llvm { +namespace sys { +const char PathSeparator = ';'; + +Path::Path(const std::string& p) + : path(p) { + FlipBackSlashes(path); +} + +Path::Path(const char *StrStart, unsigned StrLen) + : path(StrStart, StrLen) { + FlipBackSlashes(path); +} + +Path& +Path::operator=(const std::string &that) { + path = that; + FlipBackSlashes(path); + return *this; +} + +bool +Path::isValid() const { + if (path.empty()) + return false; + + // If there is a colon, it must be the second character, preceded by a letter + // and followed by something. + size_t len = path.size(); + size_t pos = path.rfind(':',len); + size_t rootslash = 0; + if (pos != std::string::npos) { + if (pos != 1 || !isalpha(path[0]) || len < 3) + return false; + rootslash = 2; + } + + // Look for a UNC path, and if found adjust our notion of the root slash. + if (len > 3 && path[0] == '/' && path[1] == '/') { + rootslash = path.find('/', 2); + if (rootslash == std::string::npos) + rootslash = 0; + } + + // Check for illegal characters. + if (path.find_first_of("\\<>\"|\001\002\003\004\005\006\007\010\011\012" + "\013\014\015\016\017\020\021\022\023\024\025\026" + "\027\030\031\032\033\034\035\036\037") + != std::string::npos) + return false; + + // Remove trailing slash, unless it's a root slash. + if (len > rootslash+1 && path[len-1] == '/') + path.erase(--len); + + // Check each component for legality. + for (pos = 0; pos < len; ++pos) { + // A component may not end in a space. + if (path[pos] == ' ') { + if (path[pos+1] == '/' || path[pos+1] == '\0') + return false; + } + + // A component may not end in a period. + if (path[pos] == '.') { + if (path[pos+1] == '/' || path[pos+1] == '\0') { + // Unless it is the pseudo-directory "."... + if (pos == 0 || path[pos-1] == '/' || path[pos-1] == ':') + return true; + // or "..". + if (pos > 0 && path[pos-1] == '.') { + if (pos == 1 || path[pos-2] == '/' || path[pos-2] == ':') + return true; + } + return false; + } + } + } + + return true; +} + +void Path::makeAbsolute() { + TCHAR FullPath[MAX_PATH + 1] = {0}; + LPTSTR FilePart = NULL; + + DWORD RetLength = ::GetFullPathNameA(path.c_str(), + sizeof(FullPath)/sizeof(FullPath[0]), + FullPath, &FilePart); + + if (0 == RetLength) { + // FIXME: Report the error GetLastError() + assert(0 && "Unable to make absolute path!"); + } else if (RetLength > MAX_PATH) { + // FIXME: Report too small buffer (needed RetLength bytes). + assert(0 && "Unable to make absolute path!"); + } else { + path = FullPath; + } +} + +bool +Path::isAbsolute(const char *NameStart, unsigned NameLen) { + assert(NameStart); + // FIXME: This does not handle correctly an absolute path starting from + // a drive letter or in UNC format. + switch (NameLen) { + case 0: + return false; + case 1: + case 2: + return NameStart[0] == '/'; + default: + return (NameStart[0] == '/' || (NameStart[1] == ':' && NameStart[2] == '/')) || + (NameStart[0] == '\\' || (NameStart[1] == ':' && NameStart[2] == '\\')); + } +} + +bool +Path::isAbsolute() const { + // FIXME: This does not handle correctly an absolute path starting from + // a drive letter or in UNC format. + switch (path.length()) { + case 0: + return false; + case 1: + case 2: + return path[0] == '/'; + default: + return path[0] == '/' || (path[1] == ':' && path[2] == '/'); + } +} + +static Path *TempDirectory = NULL; + +Path +Path::GetTemporaryDirectory(std::string* ErrMsg) { + if (TempDirectory) + return *TempDirectory; + + char pathname[MAX_PATH]; + if (!GetTempPath(MAX_PATH, pathname)) { + if (ErrMsg) + *ErrMsg = "Can't determine temporary directory"; + return Path(); + } + + Path result; + result.set(pathname); + + // Append a subdirectory passed on our process id so multiple LLVMs don't + // step on each other's toes. +#ifdef __MINGW32__ + // Mingw's Win32 header files are broken. + sprintf(pathname, "LLVM_%u", unsigned(GetCurrentProcessId())); +#else + sprintf(pathname, "LLVM_%u", GetCurrentProcessId()); +#endif + result.appendComponent(pathname); + + // If there's a directory left over from a previous LLVM execution that + // happened to have the same process id, get rid of it. + result.eraseFromDisk(true); + + // And finally (re-)create the empty directory. + result.createDirectoryOnDisk(false); + TempDirectory = new Path(result); + return *TempDirectory; +} + +// FIXME: the following set of functions don't map to Windows very well. +Path +Path::GetRootDirectory() { + Path result; + result.set("C:/"); + return result; +} + +void +Path::GetSystemLibraryPaths(std::vector& Paths) { + Paths.push_back(sys::Path("C:/WINDOWS/SYSTEM32")); + Paths.push_back(sys::Path("C:/WINDOWS")); +} + +void +Path::GetBitcodeLibraryPaths(std::vector& Paths) { + char * env_var = getenv("LLVM_LIB_SEARCH_PATH"); + if (env_var != 0) { + getPathList(env_var,Paths); + } +#ifdef LLVM_LIBDIR + { + Path tmpPath; + if (tmpPath.set(LLVM_LIBDIR)) + if (tmpPath.canRead()) + Paths.push_back(tmpPath); + } +#endif + GetSystemLibraryPaths(Paths); +} + +Path +Path::GetLLVMDefaultConfigDir() { + // TODO: this isn't going to fly on Windows + return Path("/etc/llvm"); +} + +Path +Path::GetUserHomeDirectory() { + // TODO: Typical Windows setup doesn't define HOME. + const char* home = getenv("HOME"); + if (home) { + Path result; + if (result.set(home)) + return result; + } + return GetRootDirectory(); +} + +Path +Path::GetCurrentDirectory() { + char pathname[MAX_PATH]; + ::GetCurrentDirectoryA(MAX_PATH,pathname); + return Path(pathname); +} + +/// GetMainExecutable - Return the path to the main executable, given the +/// value of argv[0] from program startup. +Path Path::GetMainExecutable(const char *argv0, void *MainAddr) { + char pathname[MAX_PATH]; + DWORD ret = ::GetModuleFileNameA(NULL, pathname, MAX_PATH); + return ret != MAX_PATH ? Path(pathname) : Path(); +} + + +// FIXME: the above set of functions don't map to Windows very well. + + +bool +Path::isRootDirectory() const { + size_t len = path.size(); + return len > 0 && path[len-1] == '/'; +} + +std::string Path::getDirname() const { + return getDirnameCharSep(path, '/'); +} + +std::string +Path::getBasename() const { + // Find the last slash + size_t slash = path.rfind('/'); + if (slash == std::string::npos) + slash = 0; + else + slash++; + + size_t dot = path.rfind('.'); + if (dot == std::string::npos || dot < slash) + return path.substr(slash); + else + return path.substr(slash, dot - slash); +} + +std::string +Path::getSuffix() const { + // Find the last slash + size_t slash = path.rfind('/'); + if (slash == std::string::npos) + slash = 0; + else + slash++; + + size_t dot = path.rfind('.'); + if (dot == std::string::npos || dot < slash) + return std::string(); + else + return path.substr(dot + 1); +} + +bool +Path::exists() const { + DWORD attr = GetFileAttributes(path.c_str()); + return attr != INVALID_FILE_ATTRIBUTES; +} + +bool +Path::isDirectory() const { + DWORD attr = GetFileAttributes(path.c_str()); + return (attr != INVALID_FILE_ATTRIBUTES) && + (attr & FILE_ATTRIBUTE_DIRECTORY); +} + +bool +Path::canRead() const { + // FIXME: take security attributes into account. + DWORD attr = GetFileAttributes(path.c_str()); + return attr != INVALID_FILE_ATTRIBUTES; +} + +bool +Path::canWrite() const { + // FIXME: take security attributes into account. + DWORD attr = GetFileAttributes(path.c_str()); + return (attr != INVALID_FILE_ATTRIBUTES) && !(attr & FILE_ATTRIBUTE_READONLY); +} + +bool +Path::canExecute() const { + // FIXME: take security attributes into account. + DWORD attr = GetFileAttributes(path.c_str()); + return attr != INVALID_FILE_ATTRIBUTES; +} + +bool +Path::isRegularFile() const { + if (isDirectory()) + return false; + return true; +} + +std::string +Path::getLast() const { + // Find the last slash + size_t pos = path.rfind('/'); + + // Handle the corner cases + if (pos == std::string::npos) + return path; + + // If the last character is a slash, we have a root directory + if (pos == path.length()-1) + return path; + + // Return everything after the last slash + return path.substr(pos+1); +} + +const FileStatus * +PathWithStatus::getFileStatus(bool update, std::string *ErrStr) const { + if (!fsIsValid || update) { + WIN32_FILE_ATTRIBUTE_DATA fi; + if (!GetFileAttributesEx(path.c_str(), GetFileExInfoStandard, &fi)) { + MakeErrMsg(ErrStr, "getStatusInfo():" + std::string(path) + + ": Can't get status: "); + return 0; + } + + status.fileSize = fi.nFileSizeHigh; + status.fileSize <<= sizeof(fi.nFileSizeHigh)*8; + status.fileSize += fi.nFileSizeLow; + + status.mode = fi.dwFileAttributes & FILE_ATTRIBUTE_READONLY ? 0555 : 0777; + status.user = 9999; // Not applicable to Windows, so... + status.group = 9999; // Not applicable to Windows, so... + + // FIXME: this is only unique if the file is accessed by the same file path. + // How do we do this for C:\dir\file and ..\dir\file ? Unix has inode + // numbers, but the concept doesn't exist in Windows. + status.uniqueID = 0; + for (unsigned i = 0; i < path.length(); ++i) + status.uniqueID += path[i]; + + __int64 ft = *reinterpret_cast<__int64*>(&fi.ftLastWriteTime); + status.modTime.fromWin32Time(ft); + + status.isDir = fi.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY; + fsIsValid = true; + } + return &status; +} + +bool Path::makeReadableOnDisk(std::string* ErrMsg) { + // All files are readable on Windows (ignoring security attributes). + return false; +} + +bool Path::makeWriteableOnDisk(std::string* ErrMsg) { + DWORD attr = GetFileAttributes(path.c_str()); + + // If it doesn't exist, we're done. + if (attr == INVALID_FILE_ATTRIBUTES) + return false; + + if (attr & FILE_ATTRIBUTE_READONLY) { + if (!SetFileAttributes(path.c_str(), attr & ~FILE_ATTRIBUTE_READONLY)) { + MakeErrMsg(ErrMsg, std::string(path) + ": Can't make file writable: "); + return true; + } + } + return false; +} + +bool Path::makeExecutableOnDisk(std::string* ErrMsg) { + // All files are executable on Windows (ignoring security attributes). + return false; +} + +bool +Path::getDirectoryContents(std::set& result, std::string* ErrMsg) const { + WIN32_FILE_ATTRIBUTE_DATA fi; + if (!GetFileAttributesEx(path.c_str(), GetFileExInfoStandard, &fi)) { + MakeErrMsg(ErrMsg, path + ": can't get status of file"); + return true; + } + + if (!(fi.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) { + if (ErrMsg) + *ErrMsg = path + ": not a directory"; + return true; + } + + result.clear(); + WIN32_FIND_DATA fd; + std::string searchpath = path; + if (path.size() == 0 || searchpath[path.size()-1] == '/') + searchpath += "*"; + else + searchpath += "/*"; + + HANDLE h = FindFirstFile(searchpath.c_str(), &fd); + if (h == INVALID_HANDLE_VALUE) { + if (GetLastError() == ERROR_FILE_NOT_FOUND) + return true; // not really an error, now is it? + MakeErrMsg(ErrMsg, path + ": Can't read directory: "); + return true; + } + + do { + if (fd.cFileName[0] == '.') + continue; + Path aPath(path); + aPath.appendComponent(&fd.cFileName[0]); + result.insert(aPath); + } while (FindNextFile(h, &fd)); + + DWORD err = GetLastError(); + FindClose(h); + if (err != ERROR_NO_MORE_FILES) { + SetLastError(err); + MakeErrMsg(ErrMsg, path + ": Can't read directory: "); + return true; + } + return false; +} + +bool +Path::set(const std::string& a_path) { + if (a_path.empty()) + return false; + std::string save(path); + path = a_path; + FlipBackSlashes(path); + if (!isValid()) { + path = save; + return false; + } + return true; +} + +bool +Path::appendComponent(const std::string& name) { + if (name.empty()) + return false; + std::string save(path); + if (!path.empty()) { + size_t last = path.size() - 1; + if (path[last] != '/') + path += '/'; + } + path += name; + if (!isValid()) { + path = save; + return false; + } + return true; +} + +bool +Path::eraseComponent() { + size_t slashpos = path.rfind('/',path.size()); + if (slashpos == path.size() - 1 || slashpos == std::string::npos) + return false; + std::string save(path); + path.erase(slashpos); + if (!isValid()) { + path = save; + return false; + } + return true; +} + +bool +Path::appendSuffix(const std::string& suffix) { + std::string save(path); + path.append("."); + path.append(suffix); + if (!isValid()) { + path = save; + return false; + } + return true; +} + +bool +Path::eraseSuffix() { + size_t dotpos = path.rfind('.',path.size()); + size_t slashpos = path.rfind('/',path.size()); + if (dotpos != std::string::npos) { + if (slashpos == std::string::npos || dotpos > slashpos+1) { + std::string save(path); + path.erase(dotpos, path.size()-dotpos); + if (!isValid()) { + path = save; + return false; + } + return true; + } + } + return false; +} + +inline bool PathMsg(std::string* ErrMsg, const char* pathname, const char*msg) { + if (ErrMsg) + *ErrMsg = std::string(pathname) + ": " + std::string(msg); + return true; +} + +bool +Path::createDirectoryOnDisk(bool create_parents, std::string* ErrMsg) { + // Get a writeable copy of the path name + size_t len = path.length(); + char *pathname = reinterpret_cast(_alloca(len+2)); + path.copy(pathname, len); + pathname[len] = 0; + + // Make sure it ends with a slash. + if (len == 0 || pathname[len - 1] != '/') { + pathname[len] = '/'; + pathname[++len] = 0; + } + + // Determine starting point for initial / search. + char *next = pathname; + if (pathname[0] == '/' && pathname[1] == '/') { + // Skip host name. + next = strchr(pathname+2, '/'); + if (next == NULL) + return PathMsg(ErrMsg, pathname, "badly formed remote directory"); + + // Skip share name. + next = strchr(next+1, '/'); + if (next == NULL) + return PathMsg(ErrMsg, pathname,"badly formed remote directory"); + + next++; + if (*next == 0) + return PathMsg(ErrMsg, pathname, "badly formed remote directory"); + + } else { + if (pathname[1] == ':') + next += 2; // skip drive letter + if (*next == '/') + next++; // skip root directory + } + + // If we're supposed to create intermediate directories + if (create_parents) { + // Loop through the directory components until we're done + while (*next) { + next = strchr(next, '/'); + *next = 0; + if (!CreateDirectory(pathname, NULL) && + GetLastError() != ERROR_ALREADY_EXISTS) + return MakeErrMsg(ErrMsg, + std::string(pathname) + ": Can't create directory: "); + *next++ = '/'; + } + } else { + // Drop trailing slash. + pathname[len-1] = 0; + if (!CreateDirectory(pathname, NULL) && + GetLastError() != ERROR_ALREADY_EXISTS) { + return MakeErrMsg(ErrMsg, std::string(pathname) + ": Can't create directory: "); + } + } + return false; +} + +bool +Path::createFileOnDisk(std::string* ErrMsg) { + // Create the file + HANDLE h = CreateFile(path.c_str(), GENERIC_WRITE, 0, NULL, CREATE_NEW, + FILE_ATTRIBUTE_NORMAL, NULL); + if (h == INVALID_HANDLE_VALUE) + return MakeErrMsg(ErrMsg, path + ": Can't create file: "); + + CloseHandle(h); + return false; +} + +bool +Path::eraseFromDisk(bool remove_contents, std::string *ErrStr) const { + WIN32_FILE_ATTRIBUTE_DATA fi; + if (!GetFileAttributesEx(path.c_str(), GetFileExInfoStandard, &fi)) + return true; + + if (fi.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { + // If it doesn't exist, we're done. + if (!exists()) + return false; + + char *pathname = reinterpret_cast(_alloca(path.length()+3)); + int lastchar = path.length() - 1 ; + path.copy(pathname, lastchar+1); + + // Make path end with '/*'. + if (pathname[lastchar] != '/') + pathname[++lastchar] = '/'; + pathname[lastchar+1] = '*'; + pathname[lastchar+2] = 0; + + if (remove_contents) { + WIN32_FIND_DATA fd; + HANDLE h = FindFirstFile(pathname, &fd); + + // It's a bad idea to alter the contents of a directory while enumerating + // its contents. So build a list of its contents first, then destroy them. + + if (h != INVALID_HANDLE_VALUE) { + std::vector list; + + do { + if (strcmp(fd.cFileName, ".") == 0) + continue; + if (strcmp(fd.cFileName, "..") == 0) + continue; + + Path aPath(path); + aPath.appendComponent(&fd.cFileName[0]); + list.push_back(aPath); + } while (FindNextFile(h, &fd)); + + DWORD err = GetLastError(); + FindClose(h); + if (err != ERROR_NO_MORE_FILES) { + SetLastError(err); + return MakeErrMsg(ErrStr, path + ": Can't read directory: "); + } + + for (std::vector::iterator I = list.begin(); I != list.end(); + ++I) { + Path &aPath = *I; + aPath.eraseFromDisk(true); + } + } else { + if (GetLastError() != ERROR_FILE_NOT_FOUND) + return MakeErrMsg(ErrStr, path + ": Can't read directory: "); + } + } + + pathname[lastchar] = 0; + if (!RemoveDirectory(pathname)) + return MakeErrMsg(ErrStr, + std::string(pathname) + ": Can't destroy directory: "); + return false; + } else { + // Read-only files cannot be deleted on Windows. Must remove the read-only + // attribute first. + if (fi.dwFileAttributes & FILE_ATTRIBUTE_READONLY) { + if (!SetFileAttributes(path.c_str(), + fi.dwFileAttributes & ~FILE_ATTRIBUTE_READONLY)) + return MakeErrMsg(ErrStr, path + ": Can't destroy file: "); + } + + if (!DeleteFile(path.c_str())) + return MakeErrMsg(ErrStr, path + ": Can't destroy file: "); + return false; + } +} + +bool Path::getMagicNumber(std::string& Magic, unsigned len) const { + assert(len < 1024 && "Request for magic string too long"); + char* buf = (char*) alloca(1 + len); + + HANDLE h = CreateFile(path.c_str(), + GENERIC_READ, + FILE_SHARE_READ, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL); + if (h == INVALID_HANDLE_VALUE) + return false; + + DWORD nRead = 0; + BOOL ret = ReadFile(h, buf, len, &nRead, NULL); + CloseHandle(h); + + if (!ret || nRead != len) + return false; + + buf[len] = '\0'; + Magic = buf; + return true; +} + +bool +Path::renamePathOnDisk(const Path& newName, std::string* ErrMsg) { + if (!MoveFileEx(path.c_str(), newName.c_str(), MOVEFILE_REPLACE_EXISTING)) + return MakeErrMsg(ErrMsg, "Can't move '" + path + "' to '" + newName.path + + "': "); + return false; +} + +bool +Path::setStatusInfoOnDisk(const FileStatus &si, std::string *ErrMsg) const { + // FIXME: should work on directories also. + if (!si.isFile) { + return true; + } + + HANDLE h = CreateFile(path.c_str(), + FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL); + if (h == INVALID_HANDLE_VALUE) + return true; + + BY_HANDLE_FILE_INFORMATION bhfi; + if (!GetFileInformationByHandle(h, &bhfi)) { + DWORD err = GetLastError(); + CloseHandle(h); + SetLastError(err); + return MakeErrMsg(ErrMsg, path + ": GetFileInformationByHandle: "); + } + + FILETIME ft; + (uint64_t&)ft = si.modTime.toWin32Time(); + BOOL ret = SetFileTime(h, NULL, &ft, &ft); + DWORD err = GetLastError(); + CloseHandle(h); + if (!ret) { + SetLastError(err); + return MakeErrMsg(ErrMsg, path + ": SetFileTime: "); + } + + // Best we can do with Unix permission bits is to interpret the owner + // writable bit. + if (si.mode & 0200) { + if (bhfi.dwFileAttributes & FILE_ATTRIBUTE_READONLY) { + if (!SetFileAttributes(path.c_str(), + bhfi.dwFileAttributes & ~FILE_ATTRIBUTE_READONLY)) + return MakeErrMsg(ErrMsg, path + ": SetFileAttributes: "); + } + } else { + if (!(bhfi.dwFileAttributes & FILE_ATTRIBUTE_READONLY)) { + if (!SetFileAttributes(path.c_str(), + bhfi.dwFileAttributes | FILE_ATTRIBUTE_READONLY)) + return MakeErrMsg(ErrMsg, path + ": SetFileAttributes: "); + } + } + + return false; +} + +bool +CopyFile(const sys::Path &Dest, const sys::Path &Src, std::string* ErrMsg) { + // Can't use CopyFile macro defined in Windows.h because it would mess up the + // above line. We use the expansion it would have in a non-UNICODE build. + if (!::CopyFileA(Src.c_str(), Dest.c_str(), false)) + return MakeErrMsg(ErrMsg, "Can't copy '" + Src.str() + + "' to '" + Dest.str() + "': "); + return false; +} + +bool +Path::makeUnique(bool reuse_current, std::string* ErrMsg) { + if (reuse_current && !exists()) + return false; // File doesn't exist already, just use it! + + // Reserve space for -XXXXXX at the end. + char *FNBuffer = (char*) alloca(path.size()+8); + unsigned offset = path.size(); + path.copy(FNBuffer, offset); + + // Find a numeric suffix that isn't used by an existing file. Assume there + // won't be more than 1 million files with the same prefix. Probably a safe + // bet. + static unsigned FCounter = 0; + do { + sprintf(FNBuffer+offset, "-%06u", FCounter); + if (++FCounter > 999999) + FCounter = 0; + path = FNBuffer; + } while (exists()); + return false; +} + +bool +Path::createTemporaryFileOnDisk(bool reuse_current, std::string* ErrMsg) { + // Make this into a unique file name + makeUnique(reuse_current, ErrMsg); + + // Now go and create it + HANDLE h = CreateFile(path.c_str(), GENERIC_WRITE, 0, NULL, CREATE_NEW, + FILE_ATTRIBUTE_NORMAL, NULL); + if (h == INVALID_HANDLE_VALUE) + return MakeErrMsg(ErrMsg, path + ": can't create file"); + + CloseHandle(h); + return false; +} + +/// MapInFilePages - Not yet implemented on win32. +const char *Path::MapInFilePages(int FD, uint64_t FileSize) { + return 0; +} + +/// MapInFilePages - Not yet implemented on win32. +void Path::UnMapFilePages(const char *Base, uint64_t FileSize) { + assert(0 && "NOT IMPLEMENTED"); +} + +} +} diff --git a/libclamav/c++/llvm/lib/System/Win32/Process.inc b/libclamav/c++/llvm/lib/System/Win32/Process.inc new file mode 100644 index 000000000..feb080611 --- /dev/null +++ b/libclamav/c++/llvm/lib/System/Win32/Process.inc @@ -0,0 +1,221 @@ +//===- Win32/Process.cpp - Win32 Process Implementation ------- -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides the Win32 specific implementation of the Process class. +// +//===----------------------------------------------------------------------===// + +#include "Win32.h" +#include +#include +#include + +#ifdef __MINGW32__ + #if (HAVE_LIBPSAPI != 1) + #error "libpsapi.a should be present" + #endif +#else + #pragma comment(lib, "psapi.lib") +#endif + +//===----------------------------------------------------------------------===// +//=== WARNING: Implementation here must contain only Win32 specific code +//=== and must not be UNIX code +//===----------------------------------------------------------------------===// + +#ifdef __MINGW32__ +// This ban should be lifted when MinGW 1.0+ has defined this value. +# define _HEAPOK (-2) +#endif + +namespace llvm { +using namespace sys; + +// This function retrieves the page size using GetSystemInfo and is present +// solely so it can be called once in Process::GetPageSize to initialize the +// static variable PageSize. +inline unsigned GetPageSizeOnce() { + // NOTE: A 32-bit application running under WOW64 is supposed to use + // GetNativeSystemInfo. However, this interface is not present prior + // to Windows XP so to use it requires dynamic linking. It is not clear + // how this affects the reported page size, if at all. One could argue + // that LLVM ought to run as 64-bits on a 64-bit system, anyway. + SYSTEM_INFO info; + GetSystemInfo(&info); + return static_cast(info.dwPageSize); +} + +unsigned +Process::GetPageSize() { + static const unsigned PageSize = GetPageSizeOnce(); + return PageSize; +} + +size_t +Process::GetMallocUsage() +{ + _HEAPINFO hinfo; + hinfo._pentry = NULL; + + size_t size = 0; + + while (_heapwalk(&hinfo) == _HEAPOK) + size += hinfo._size; + + return size; +} + +size_t +Process::GetTotalMemoryUsage() +{ + PROCESS_MEMORY_COUNTERS pmc; + GetProcessMemoryInfo(GetCurrentProcess(), &pmc, sizeof(pmc)); + return pmc.PagefileUsage; +} + +void +Process::GetTimeUsage( + TimeValue& elapsed, TimeValue& user_time, TimeValue& sys_time) +{ + elapsed = TimeValue::now(); + + uint64_t ProcCreate, ProcExit, KernelTime, UserTime; + GetProcessTimes(GetCurrentProcess(), (FILETIME*)&ProcCreate, + (FILETIME*)&ProcExit, (FILETIME*)&KernelTime, + (FILETIME*)&UserTime); + + // FILETIME's are # of 100 nanosecond ticks (1/10th of a microsecond) + user_time.seconds( UserTime / 10000000 ); + user_time.nanoseconds( unsigned(UserTime % 10000000) * 100 ); + sys_time.seconds( KernelTime / 10000000 ); + sys_time.nanoseconds( unsigned(KernelTime % 10000000) * 100 ); +} + +int Process::GetCurrentUserId() +{ + return 65536; +} + +int Process::GetCurrentGroupId() +{ + return 65536; +} + +// Some LLVM programs such as bugpoint produce core files as a normal part of +// their operation. To prevent the disk from filling up, this configuration item +// does what's necessary to prevent their generation. +void Process::PreventCoreFiles() { + // Windows doesn't do core files, but it does do modal pop-up message + // boxes. As this method is used by bugpoint, preventing these pop-ups + // is the moral equivalent of suppressing core files. + SetErrorMode(SEM_FAILCRITICALERRORS | + SEM_NOGPFAULTERRORBOX | + SEM_NOOPENFILEERRORBOX); +} + +bool Process::StandardInIsUserInput() { + return FileDescriptorIsDisplayed(0); +} + +bool Process::StandardOutIsDisplayed() { + return FileDescriptorIsDisplayed(1); +} + +bool Process::StandardErrIsDisplayed() { + return FileDescriptorIsDisplayed(2); +} + +bool Process::FileDescriptorIsDisplayed(int fd) { + return GetFileType((HANDLE)_get_osfhandle(fd)) == FILE_TYPE_CHAR; +} + +unsigned Process::StandardOutColumns() { + unsigned Columns = 0; + CONSOLE_SCREEN_BUFFER_INFO csbi; + if (GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi)) + Columns = csbi.dwSize.X; + return Columns; +} + +unsigned Process::StandardErrColumns() { + unsigned Columns = 0; + CONSOLE_SCREEN_BUFFER_INFO csbi; + if (GetConsoleScreenBufferInfo(GetStdHandle(STD_ERROR_HANDLE), &csbi)) + Columns = csbi.dwSize.X; + return Columns; +} + +// It always has colors. +bool Process::StandardErrHasColors() { + return StandardErrIsDisplayed(); +} + +bool Process::StandardOutHasColors() { + return StandardOutIsDisplayed(); +} + +namespace { +class DefaultColors +{ + private: + WORD defaultColor; + public: + DefaultColors() + :defaultColor(GetCurrentColor()) {} + static unsigned GetCurrentColor() { + CONSOLE_SCREEN_BUFFER_INFO csbi; + if (GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi)) + return csbi.wAttributes; + return 0; + } + WORD operator()() const { return defaultColor; } +}; + +DefaultColors defaultColors; +} + +bool Process::ColorNeedsFlush() { + return true; +} + +const char *Process::OutputBold(bool bg) { + WORD colors = DefaultColors::GetCurrentColor(); + if (bg) + colors |= BACKGROUND_INTENSITY; + else + colors |= FOREGROUND_INTENSITY; + SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), colors); + return 0; +} + +const char *Process::OutputColor(char code, bool bold, bool bg) { + WORD colors; + if (bg) { + colors = ((code&1) ? BACKGROUND_RED : 0) | + ((code&2) ? BACKGROUND_GREEN : 0 ) | + ((code&4) ? BACKGROUND_BLUE : 0); + if (bold) + colors |= BACKGROUND_INTENSITY; + } else { + colors = ((code&1) ? FOREGROUND_RED : 0) | + ((code&2) ? FOREGROUND_GREEN : 0 ) | + ((code&4) ? FOREGROUND_BLUE : 0); + if (bold) + colors |= FOREGROUND_INTENSITY; + } + SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), colors); + return 0; +} + +const char *Process::ResetColor() { + SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), defaultColors()); + return 0; +} + +} diff --git a/libclamav/c++/llvm/lib/System/Win32/Program.inc b/libclamav/c++/llvm/lib/System/Win32/Program.inc new file mode 100644 index 000000000..a69826fdc --- /dev/null +++ b/libclamav/c++/llvm/lib/System/Win32/Program.inc @@ -0,0 +1,382 @@ +//===- Win32/Program.cpp - Win32 Program Implementation ------- -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides the Win32 specific implementation of the Program class. +// +//===----------------------------------------------------------------------===// + +#include "Win32.h" +#include +#include +#include +#include + +//===----------------------------------------------------------------------===// +//=== WARNING: Implementation here must contain only Win32 specific code +//=== and must not be UNIX code +//===----------------------------------------------------------------------===// + +namespace { + struct Win32ProcessInfo { + HANDLE hProcess; + DWORD dwProcessId; + }; +} + +namespace llvm { +using namespace sys; + +Program::Program() : Data_(0) {} + +Program::~Program() { + if (Data_) { + Win32ProcessInfo* wpi = reinterpret_cast(Data_); + CloseHandle(wpi->hProcess); + delete wpi; + Data_ = 0; + } +} + +unsigned Program::GetPid() const { + Win32ProcessInfo* wpi = reinterpret_cast(Data_); + return wpi->dwProcessId; +} + +// This function just uses the PATH environment variable to find the program. +Path +Program::FindProgramByName(const std::string& progName) { + + // Check some degenerate cases + if (progName.length() == 0) // no program + return Path(); + Path temp; + if (!temp.set(progName)) // invalid name + return Path(); + if (temp.canExecute()) // already executable as is + return temp; + + // At this point, the file name is valid and its not executable. + // Let Windows search for it. + char buffer[MAX_PATH]; + char *dummy = NULL; + DWORD len = SearchPath(NULL, progName.c_str(), ".exe", MAX_PATH, + buffer, &dummy); + + // See if it wasn't found. + if (len == 0) + return Path(); + + // See if we got the entire path. + if (len < MAX_PATH) + return Path(buffer); + + // Buffer was too small; grow and retry. + while (true) { + char *b = reinterpret_cast(_alloca(len+1)); + DWORD len2 = SearchPath(NULL, progName.c_str(), ".exe", len+1, b, &dummy); + + // It is unlikely the search failed, but it's always possible some file + // was added or removed since the last search, so be paranoid... + if (len2 == 0) + return Path(); + else if (len2 <= len) + return Path(b); + + len = len2; + } +} + +static HANDLE RedirectIO(const Path *path, int fd, std::string* ErrMsg) { + HANDLE h; + if (path == 0) { + DuplicateHandle(GetCurrentProcess(), (HANDLE)_get_osfhandle(fd), + GetCurrentProcess(), &h, + 0, TRUE, DUPLICATE_SAME_ACCESS); + return h; + } + + const char *fname; + if (path->isEmpty()) + fname = "NUL"; + else + fname = path->c_str(); + + SECURITY_ATTRIBUTES sa; + sa.nLength = sizeof(sa); + sa.lpSecurityDescriptor = 0; + sa.bInheritHandle = TRUE; + + h = CreateFile(fname, fd ? GENERIC_WRITE : GENERIC_READ, FILE_SHARE_READ, + &sa, fd == 0 ? OPEN_EXISTING : CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, NULL); + if (h == INVALID_HANDLE_VALUE) { + MakeErrMsg(ErrMsg, std::string(fname) + ": Can't open file for " + + (fd ? "input: " : "output: ")); + } + + return h; +} + +#ifdef __MINGW32__ + // Due to unknown reason, mingw32's w32api doesn't have this declaration. + extern "C" + BOOL WINAPI SetInformationJobObject(HANDLE hJob, + JOBOBJECTINFOCLASS JobObjectInfoClass, + LPVOID lpJobObjectInfo, + DWORD cbJobObjectInfoLength); +#endif + +/// ArgNeedsQuotes - Check whether argument needs to be quoted when calling +/// CreateProcess. +static bool ArgNeedsQuotes(const char *Str) { + return Str[0] == '\0' || strchr(Str, ' ') != 0; +} + +bool +Program::Execute(const Path& path, + const char** args, + const char** envp, + const Path** redirects, + unsigned memoryLimit, + std::string* ErrMsg) { + if (Data_) { + Win32ProcessInfo* wpi = reinterpret_cast(Data_); + CloseHandle(wpi->hProcess); + delete wpi; + Data_ = 0; + } + + if (!path.canExecute()) { + if (ErrMsg) + *ErrMsg = "program not executable"; + return false; + } + + // Windows wants a command line, not an array of args, to pass to the new + // process. We have to concatenate them all, while quoting the args that + // have embedded spaces (or are empty). + + // First, determine the length of the command line. + unsigned len = 0; + for (unsigned i = 0; args[i]; i++) { + len += strlen(args[i]) + 1; + if (ArgNeedsQuotes(args[i])) + len += 2; + } + + // Now build the command line. + char *command = reinterpret_cast(_alloca(len+1)); + char *p = command; + + for (unsigned i = 0; args[i]; i++) { + const char *arg = args[i]; + size_t len = strlen(arg); + bool needsQuoting = ArgNeedsQuotes(arg); + if (needsQuoting) + *p++ = '"'; + memcpy(p, arg, len); + p += len; + if (needsQuoting) + *p++ = '"'; + *p++ = ' '; + } + + *p = 0; + + // The pointer to the environment block for the new process. + char *envblock = 0; + + if (envp) { + // An environment block consists of a null-terminated block of + // null-terminated strings. Convert the array of environment variables to + // an environment block by concatenating them. + + // First, determine the length of the environment block. + len = 0; + for (unsigned i = 0; envp[i]; i++) + len += strlen(envp[i]) + 1; + + // Now build the environment block. + envblock = reinterpret_cast(_alloca(len+1)); + p = envblock; + + for (unsigned i = 0; envp[i]; i++) { + const char *ev = envp[i]; + size_t len = strlen(ev) + 1; + memcpy(p, ev, len); + p += len; + } + + *p = 0; + } + + // Create a child process. + STARTUPINFO si; + memset(&si, 0, sizeof(si)); + si.cb = sizeof(si); + si.hStdInput = INVALID_HANDLE_VALUE; + si.hStdOutput = INVALID_HANDLE_VALUE; + si.hStdError = INVALID_HANDLE_VALUE; + + if (redirects) { + si.dwFlags = STARTF_USESTDHANDLES; + + si.hStdInput = RedirectIO(redirects[0], 0, ErrMsg); + if (si.hStdInput == INVALID_HANDLE_VALUE) { + MakeErrMsg(ErrMsg, "can't redirect stdin"); + return false; + } + si.hStdOutput = RedirectIO(redirects[1], 1, ErrMsg); + if (si.hStdOutput == INVALID_HANDLE_VALUE) { + CloseHandle(si.hStdInput); + MakeErrMsg(ErrMsg, "can't redirect stdout"); + return false; + } + if (redirects[1] && redirects[2] && *(redirects[1]) == *(redirects[2])) { + // If stdout and stderr should go to the same place, redirect stderr + // to the handle already open for stdout. + DuplicateHandle(GetCurrentProcess(), si.hStdOutput, + GetCurrentProcess(), &si.hStdError, + 0, TRUE, DUPLICATE_SAME_ACCESS); + } else { + // Just redirect stderr + si.hStdError = RedirectIO(redirects[2], 2, ErrMsg); + if (si.hStdError == INVALID_HANDLE_VALUE) { + CloseHandle(si.hStdInput); + CloseHandle(si.hStdOutput); + MakeErrMsg(ErrMsg, "can't redirect stderr"); + return false; + } + } + } + + PROCESS_INFORMATION pi; + memset(&pi, 0, sizeof(pi)); + + fflush(stdout); + fflush(stderr); + BOOL rc = CreateProcess(path.c_str(), command, NULL, NULL, TRUE, 0, + envblock, NULL, &si, &pi); + DWORD err = GetLastError(); + + // Regardless of whether the process got created or not, we are done with + // the handles we created for it to inherit. + CloseHandle(si.hStdInput); + CloseHandle(si.hStdOutput); + CloseHandle(si.hStdError); + + // Now return an error if the process didn't get created. + if (!rc) { + SetLastError(err); + MakeErrMsg(ErrMsg, std::string("Couldn't execute program '") + + path.str() + "'"); + return false; + } + Win32ProcessInfo* wpi = new Win32ProcessInfo; + wpi->hProcess = pi.hProcess; + wpi->dwProcessId = pi.dwProcessId; + Data_ = wpi; + + // Make sure these get closed no matter what. + AutoHandle hThread(pi.hThread); + + // Assign the process to a job if a memory limit is defined. + AutoHandle hJob(0); + if (memoryLimit != 0) { + hJob = CreateJobObject(0, 0); + bool success = false; + if (hJob != 0) { + JOBOBJECT_EXTENDED_LIMIT_INFORMATION jeli; + memset(&jeli, 0, sizeof(jeli)); + jeli.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_PROCESS_MEMORY; + jeli.ProcessMemoryLimit = uintptr_t(memoryLimit) * 1048576; + if (SetInformationJobObject(hJob, JobObjectExtendedLimitInformation, + &jeli, sizeof(jeli))) { + if (AssignProcessToJobObject(hJob, pi.hProcess)) + success = true; + } + } + if (!success) { + SetLastError(GetLastError()); + MakeErrMsg(ErrMsg, std::string("Unable to set memory limit")); + TerminateProcess(pi.hProcess, 1); + WaitForSingleObject(pi.hProcess, INFINITE); + return false; + } + } + + return true; +} + +int +Program::Wait(unsigned secondsToWait, + std::string* ErrMsg) { + if (Data_ == 0) { + MakeErrMsg(ErrMsg, "Process not started!"); + return -1; + } + + Win32ProcessInfo* wpi = reinterpret_cast(Data_); + HANDLE hProcess = wpi->hProcess; + + // Wait for the process to terminate. + DWORD millisecondsToWait = INFINITE; + if (secondsToWait > 0) + millisecondsToWait = secondsToWait * 1000; + + if (WaitForSingleObject(hProcess, millisecondsToWait) == WAIT_TIMEOUT) { + if (!TerminateProcess(hProcess, 1)) { + MakeErrMsg(ErrMsg, "Failed to terminate timed-out program."); + return -1; + } + WaitForSingleObject(hProcess, INFINITE); + } + + // Get its exit status. + DWORD status; + BOOL rc = GetExitCodeProcess(hProcess, &status); + DWORD err = GetLastError(); + + if (!rc) { + SetLastError(err); + MakeErrMsg(ErrMsg, "Failed getting status for program."); + return -1; + } + + return status; +} + +bool +Program::Kill(std::string* ErrMsg) { + if (Data_ == 0) { + MakeErrMsg(ErrMsg, "Process not started!"); + return true; + } + + Win32ProcessInfo* wpi = reinterpret_cast(Data_); + HANDLE hProcess = wpi->hProcess; + if (TerminateProcess(hProcess, 1) == 0) { + MakeErrMsg(ErrMsg, "The process couldn't be killed!"); + return true; + } + + return false; +} + +bool Program::ChangeStdinToBinary(){ + int result = _setmode( _fileno(stdin), _O_BINARY ); + return result == -1; +} + +bool Program::ChangeStdoutToBinary(){ + int result = _setmode( _fileno(stdout), _O_BINARY ); + return result == -1; +} + +} diff --git a/libclamav/c++/llvm/lib/System/Win32/RWMutex.inc b/libclamav/c++/llvm/lib/System/Win32/RWMutex.inc new file mode 100644 index 000000000..e2692269e --- /dev/null +++ b/libclamav/c++/llvm/lib/System/Win32/RWMutex.inc @@ -0,0 +1,58 @@ +//= llvm/System/Win32/Mutex.inc - Win32 Reader/Writer Mutual Exclusion Lock =// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the Win32 specific (non-pthread) RWMutex class. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +//=== WARNING: Implementation here must contain only generic Win32 code that +//=== is guaranteed to work on *all* Win32 variants. +//===----------------------------------------------------------------------===// + +#include "Win32.h" + +// FIXME: Windows does not have reader-writer locks pre-Vista. If you want +// real reader-writer locks, you a pthreads implementation for Windows. + +namespace llvm { +using namespace sys; + +RWMutexImpl::RWMutexImpl() { + data_ = calloc(1, sizeof(CRITICAL_SECTION)); + InitializeCriticalSection(static_cast(data_)); +} + +RWMutexImpl::~RWMutexImpl() { + DeleteCriticalSection(static_cast(data_)); + free(data_); +} + +bool RWMutexImpl::reader_acquire() { + EnterCriticalSection(static_cast(data_)); + return true; +} + +bool RWMutexImpl::reader_release() { + LeaveCriticalSection(static_cast(data_)); + return true; +} + +bool RWMutexImpl::writer_acquire() { + EnterCriticalSection(static_cast(data_)); + return true; +} + +bool RWMutexImpl::writer_release() { + LeaveCriticalSection(static_cast(data_)); + return true; +} + + +} diff --git a/libclamav/c++/llvm/lib/System/Win32/Signals.inc b/libclamav/c++/llvm/lib/System/Win32/Signals.inc new file mode 100644 index 000000000..dba22185a --- /dev/null +++ b/libclamav/c++/llvm/lib/System/Win32/Signals.inc @@ -0,0 +1,313 @@ +//===- Win32/Signals.cpp - Win32 Signals Implementation ---------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides the Win32 specific implementation of the Signals class. +// +//===----------------------------------------------------------------------===// + +#include "Win32.h" +#include +#include +#include + +#ifdef __MINGW32__ + #include +#else + #include +#endif +#include + +#ifdef __MINGW32__ + #if ((HAVE_LIBIMAGEHLP != 1) || (HAVE_LIBPSAPI != 1)) + #error "libimagehlp.a & libpsapi.a should be present" + #endif +#else + #pragma comment(lib, "psapi.lib") + #pragma comment(lib, "dbghelp.lib") +#endif + +// Forward declare. +static LONG WINAPI LLVMUnhandledExceptionFilter(LPEXCEPTION_POINTERS ep); +static BOOL WINAPI LLVMConsoleCtrlHandler(DWORD dwCtrlType); + +// InterruptFunction - The function to call if ctrl-c is pressed. +static void (*InterruptFunction)() = 0; + +static std::vector *FilesToRemove = NULL; +static std::vector > *CallBacksToRun = 0; +static bool RegisteredUnhandledExceptionFilter = false; +static bool CleanupExecuted = false; +#ifdef _MSC_VER +static bool ExitOnUnhandledExceptions = false; +#endif +static PTOP_LEVEL_EXCEPTION_FILTER OldFilter = NULL; + +// Windows creates a new thread to execute the console handler when an event +// (such as CTRL/C) occurs. This causes concurrency issues with the above +// globals which this critical section addresses. +static CRITICAL_SECTION CriticalSection; + +namespace llvm { + +//===----------------------------------------------------------------------===// +//=== WARNING: Implementation here must contain only Win32 specific code +//=== and must not be UNIX code +//===----------------------------------------------------------------------===// + +#ifdef _MSC_VER +/// CRTReportHook - Function called on a CRT debugging event. +static int CRTReportHook(int ReportType, char *Message, int *Return) { + // Don't cause a DebugBreak() on return. + if (Return) + *Return = 0; + + switch (ReportType) { + default: + case _CRT_ASSERT: + fprintf(stderr, "CRT assert: %s\n", Message); + // FIXME: Is there a way to just crash? Perhaps throw to the unhandled + // exception code? Perhaps SetErrorMode() handles this. + _exit(3); + break; + case _CRT_ERROR: + fprintf(stderr, "CRT error: %s\n", Message); + // FIXME: Is there a way to just crash? Perhaps throw to the unhandled + // exception code? Perhaps SetErrorMode() handles this. + _exit(3); + break; + case _CRT_WARN: + fprintf(stderr, "CRT warn: %s\n", Message); + break; + } + + // Don't call _CrtDbgReport. + return TRUE; +} +#endif + +static void RegisterHandler() { + if (RegisteredUnhandledExceptionFilter) { + EnterCriticalSection(&CriticalSection); + return; + } + + // Now's the time to create the critical section. This is the first time + // through here, and there's only one thread. + InitializeCriticalSection(&CriticalSection); + + // Enter it immediately. Now if someone hits CTRL/C, the console handler + // can't proceed until the globals are updated. + EnterCriticalSection(&CriticalSection); + + RegisteredUnhandledExceptionFilter = true; + OldFilter = SetUnhandledExceptionFilter(LLVMUnhandledExceptionFilter); + SetConsoleCtrlHandler(LLVMConsoleCtrlHandler, TRUE); + + // Environment variable to disable any kind of crash dialog. +#ifdef _MSC_VER + if (getenv("LLVM_DISABLE_CRT_DEBUG")) { + _CrtSetReportHook(CRTReportHook); + ExitOnUnhandledExceptions = true; + } +#endif + + // IMPORTANT NOTE: Caller must call LeaveCriticalSection(&CriticalSection) or + // else multi-threading problems will ensue. +} + +// RemoveFileOnSignal - The public API +bool sys::RemoveFileOnSignal(const sys::Path &Filename, std::string* ErrMsg) { + RegisterHandler(); + + if (CleanupExecuted) { + if (ErrMsg) + *ErrMsg = "Process terminating -- cannot register for removal"; + return true; + } + + if (FilesToRemove == NULL) + FilesToRemove = new std::vector; + + FilesToRemove->push_back(Filename); + + LeaveCriticalSection(&CriticalSection); + return false; +} + +/// PrintStackTraceOnErrorSignal - When an error signal (such as SIBABRT or +/// SIGSEGV) is delivered to the process, print a stack trace and then exit. +void sys::PrintStackTraceOnErrorSignal() { + RegisterHandler(); + LeaveCriticalSection(&CriticalSection); +} + + +void sys::SetInterruptFunction(void (*IF)()) { + RegisterHandler(); + InterruptFunction = IF; + LeaveCriticalSection(&CriticalSection); +} + + +/// AddSignalHandler - Add a function to be called when a signal is delivered +/// to the process. The handler can have a cookie passed to it to identify +/// what instance of the handler it is. +void sys::AddSignalHandler(void (*FnPtr)(void *), void *Cookie) { + if (CallBacksToRun == 0) + CallBacksToRun = new std::vector >(); + CallBacksToRun->push_back(std::make_pair(FnPtr, Cookie)); + RegisterHandler(); +} +} + +static void Cleanup() { + EnterCriticalSection(&CriticalSection); + + // Prevent other thread from registering new files and directories for + // removal, should we be executing because of the console handler callback. + CleanupExecuted = true; + + // FIXME: open files cannot be deleted. + + if (FilesToRemove != NULL) + while (!FilesToRemove->empty()) { + FilesToRemove->back().eraseFromDisk(); + FilesToRemove->pop_back(); + } + + if (CallBacksToRun) + for (unsigned i = 0, e = CallBacksToRun->size(); i != e; ++i) + (*CallBacksToRun)[i].first((*CallBacksToRun)[i].second); + + LeaveCriticalSection(&CriticalSection); +} + +static LONG WINAPI LLVMUnhandledExceptionFilter(LPEXCEPTION_POINTERS ep) { + try { + Cleanup(); + +#ifdef _WIN64 + // TODO: provide a x64 friendly version of the following +#else + + // Initialize the STACKFRAME structure. + STACKFRAME StackFrame; + memset(&StackFrame, 0, sizeof(StackFrame)); + + StackFrame.AddrPC.Offset = ep->ContextRecord->Eip; + StackFrame.AddrPC.Mode = AddrModeFlat; + StackFrame.AddrStack.Offset = ep->ContextRecord->Esp; + StackFrame.AddrStack.Mode = AddrModeFlat; + StackFrame.AddrFrame.Offset = ep->ContextRecord->Ebp; + StackFrame.AddrFrame.Mode = AddrModeFlat; + + HANDLE hProcess = GetCurrentProcess(); + HANDLE hThread = GetCurrentThread(); + + // Initialize the symbol handler. + SymSetOptions(SYMOPT_DEFERRED_LOADS|SYMOPT_LOAD_LINES); + SymInitialize(hProcess, NULL, TRUE); + + while (true) { + if (!StackWalk(IMAGE_FILE_MACHINE_I386, hProcess, hThread, &StackFrame, + ep->ContextRecord, NULL, SymFunctionTableAccess, + SymGetModuleBase, NULL)) { + break; + } + + if (StackFrame.AddrFrame.Offset == 0) + break; + + // Print the PC in hexadecimal. + DWORD PC = StackFrame.AddrPC.Offset; + fprintf(stderr, "%08lX", PC); + + // Print the parameters. Assume there are four. + fprintf(stderr, " (0x%08lX 0x%08lX 0x%08lX 0x%08lX)", StackFrame.Params[0], + StackFrame.Params[1], StackFrame.Params[2], StackFrame.Params[3]); + + // Verify the PC belongs to a module in this process. + if (!SymGetModuleBase(hProcess, PC)) { + fputs(" \n", stderr); + continue; + } + + // Print the symbol name. + char buffer[512]; + IMAGEHLP_SYMBOL *symbol = reinterpret_cast(buffer); + memset(symbol, 0, sizeof(IMAGEHLP_SYMBOL)); + symbol->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL); + symbol->MaxNameLength = 512 - sizeof(IMAGEHLP_SYMBOL); + + DWORD dwDisp; + if (!SymGetSymFromAddr(hProcess, PC, &dwDisp, symbol)) { + fputc('\n', stderr); + continue; + } + + buffer[511] = 0; + if (dwDisp > 0) + fprintf(stderr, ", %s()+%04lu bytes(s)", symbol->Name, dwDisp); + else + fprintf(stderr, ", %s", symbol->Name); + + // Print the source file and line number information. + IMAGEHLP_LINE line; + memset(&line, 0, sizeof(line)); + line.SizeOfStruct = sizeof(line); + if (SymGetLineFromAddr(hProcess, PC, &dwDisp, &line)) { + fprintf(stderr, ", %s, line %lu", line.FileName, line.LineNumber); + if (dwDisp > 0) + fprintf(stderr, "+%04lu byte(s)", dwDisp); + } + + fputc('\n', stderr); + } + +#endif + + } catch (...) { + assert(0 && "Crashed in LLVMUnhandledExceptionFilter"); + } + +#ifdef _MSC_VER + if (ExitOnUnhandledExceptions) + _exit(-3); +#endif + + // Allow dialog box to pop up allowing choice to start debugger. + if (OldFilter) + return (*OldFilter)(ep); + else + return EXCEPTION_CONTINUE_SEARCH; +} + +static BOOL WINAPI LLVMConsoleCtrlHandler(DWORD dwCtrlType) { + // We are running in our very own thread, courtesy of Windows. + EnterCriticalSection(&CriticalSection); + Cleanup(); + + // If an interrupt function has been set, go and run one it; otherwise, + // the process dies. + void (*IF)() = InterruptFunction; + InterruptFunction = 0; // Don't run it on another CTRL-C. + + if (IF) { + // Note: if the interrupt function throws an exception, there is nothing + // to catch it in this thread so it will kill the process. + IF(); // Run it now. + LeaveCriticalSection(&CriticalSection); + return TRUE; // Don't kill the process. + } + + // Allow normal processing to take place; i.e., the process dies. + LeaveCriticalSection(&CriticalSection); + return FALSE; +} + diff --git a/libclamav/c++/llvm/lib/System/Win32/ThreadLocal.inc b/libclamav/c++/llvm/lib/System/Win32/ThreadLocal.inc new file mode 100644 index 000000000..c8f7840b0 --- /dev/null +++ b/libclamav/c++/llvm/lib/System/Win32/ThreadLocal.inc @@ -0,0 +1,49 @@ +//= llvm/System/Win32/ThreadLocal.inc - Win32 Thread Local Data -*- 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 the Win32 specific (non-pthread) ThreadLocal class. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +//=== WARNING: Implementation here must contain only generic Win32 code that +//=== is guaranteed to work on *all* Win32 variants. +//===----------------------------------------------------------------------===// + +#include "Win32.h" +#include "llvm/System/ThreadLocal.h" + +namespace llvm { +using namespace sys; + +ThreadLocalImpl::ThreadLocalImpl() { + DWORD* tls = new DWORD; + *tls = TlsAlloc(); + assert(*tls != TLS_OUT_OF_INDEXES); + data = tls; +} + +ThreadLocalImpl::~ThreadLocalImpl() { + DWORD* tls = static_cast(data); + TlsFree(*tls); + delete tls; +} + +const void* ThreadLocalImpl::getInstance() { + DWORD* tls = static_cast(data); + return TlsGetValue(*tls); +} + +void ThreadLocalImpl::setInstance(const void* d){ + DWORD* tls = static_cast(data); + int errorcode = TlsSetValue(*tls, const_cast(d)); + assert(errorcode != 0); +} + +} diff --git a/libclamav/c++/llvm/lib/System/Win32/TimeValue.inc b/libclamav/c++/llvm/lib/System/Win32/TimeValue.inc new file mode 100644 index 000000000..e37f111fc --- /dev/null +++ b/libclamav/c++/llvm/lib/System/Win32/TimeValue.inc @@ -0,0 +1,51 @@ +//===- Win32/TimeValue.cpp - Win32 TimeValue Implementation -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides the Win32 implementation of the TimeValue class. +// +//===----------------------------------------------------------------------===// + +#include "Win32.h" +#include + +namespace llvm { +using namespace sys; + +//===----------------------------------------------------------------------===// +//=== WARNING: Implementation here must contain only Win32 specific code. +//===----------------------------------------------------------------------===// + +TimeValue TimeValue::now() { + uint64_t ft; + GetSystemTimeAsFileTime(reinterpret_cast(&ft)); + + TimeValue t(0, 0); + t.fromWin32Time(ft); + return t; +} + +std::string TimeValue::str() const { +#ifdef __MINGW32__ + // This ban may be lifted by either: + // (i) a future MinGW version other than 1.0 inherents the __time64_t type, or + // (ii) configure tests for either the time_t or __time64_t type. + time_t ourTime = time_t(this->toEpochTime()); + struct tm *lt = ::localtime(&ourTime); +#else + __time64_t ourTime = this->toEpochTime(); + struct tm *lt = ::_localtime64(&ourTime); +#endif + + char buffer[25]; + strftime(buffer, 25, "%a %b %d %H:%M:%S %Y", lt); + return std::string(buffer); +} + + +} diff --git a/libclamav/c++/llvm/lib/System/Win32/Win32.h b/libclamav/c++/llvm/lib/System/Win32/Win32.h new file mode 100644 index 000000000..8f505b1a6 --- /dev/null +++ b/libclamav/c++/llvm/lib/System/Win32/Win32.h @@ -0,0 +1,57 @@ +//===- Win32/Win32.h - Common Win32 Include File ----------------*- 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 things specific to Win32 implementations. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +//=== WARNING: Implementation here must contain only generic Win32 code that +//=== is guaranteed to work on *all* Win32 variants. +//===----------------------------------------------------------------------===// + +// Require at least Windows 2000 API. +#define _WIN32_WINNT 0x0500 + +#include "llvm/Config/config.h" // Get autoconf configuration settings +#include "windows.h" +#include +#include + +inline bool MakeErrMsg(std::string* ErrMsg, const std::string& prefix) { + if (!ErrMsg) + return true; + char *buffer = NULL; + FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM, + NULL, GetLastError(), 0, (LPSTR)&buffer, 1, NULL); + *ErrMsg = prefix + buffer; + LocalFree(buffer); + return true; +} + +class AutoHandle { + HANDLE handle; + +public: + AutoHandle(HANDLE h) : handle(h) {} + + ~AutoHandle() { + if (handle) + CloseHandle(handle); + } + + operator HANDLE() { + return handle; + } + + AutoHandle &operator=(HANDLE h) { + handle = h; + return *this; + } +}; diff --git a/libclamav/c++/llvm/lib/Target/ARM/ARM.h b/libclamav/c++/llvm/lib/Target/ARM/ARM.h new file mode 100644 index 000000000..ff1980d19 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/ARM/ARM.h @@ -0,0 +1,128 @@ +//===-- ARM.h - Top-level interface for ARM representation---- --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the entry points for global functions defined in the LLVM +// ARM back-end. +// +//===----------------------------------------------------------------------===// + +#ifndef TARGET_ARM_H +#define TARGET_ARM_H + +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Target/TargetMachine.h" +#include + +namespace llvm { + +class ARMBaseTargetMachine; +class FunctionPass; +class MachineCodeEmitter; +class JITCodeEmitter; +class ObjectCodeEmitter; +class formatted_raw_ostream; + +// Enums corresponding to ARM condition codes +namespace ARMCC { + // The CondCodes constants map directly to the 4-bit encoding of the + // condition field for predicated instructions. + enum CondCodes { + EQ, + NE, + HS, + LO, + MI, + PL, + VS, + VC, + HI, + LS, + GE, + LT, + GT, + LE, + AL + }; + + inline static CondCodes getOppositeCondition(CondCodes CC){ + switch (CC) { + default: llvm_unreachable("Unknown condition code"); + case EQ: return NE; + case NE: return EQ; + case HS: return LO; + case LO: return HS; + case MI: return PL; + case PL: return MI; + case VS: return VC; + case VC: return VS; + case HI: return LS; + case LS: return HI; + case GE: return LT; + case LT: return GE; + case GT: return LE; + case LE: return GT; + } + } +} + +inline static const char *ARMCondCodeToString(ARMCC::CondCodes CC) { + switch (CC) { + default: llvm_unreachable("Unknown condition code"); + case ARMCC::EQ: return "eq"; + case ARMCC::NE: return "ne"; + case ARMCC::HS: return "hs"; + case ARMCC::LO: return "lo"; + case ARMCC::MI: return "mi"; + case ARMCC::PL: return "pl"; + case ARMCC::VS: return "vs"; + case ARMCC::VC: return "vc"; + case ARMCC::HI: return "hi"; + case ARMCC::LS: return "ls"; + case ARMCC::GE: return "ge"; + case ARMCC::LT: return "lt"; + case ARMCC::GT: return "gt"; + case ARMCC::LE: return "le"; + case ARMCC::AL: return "al"; + } +} + +FunctionPass *createARMISelDag(ARMBaseTargetMachine &TM, + CodeGenOpt::Level OptLevel); + +FunctionPass *createARMCodeEmitterPass(ARMBaseTargetMachine &TM, + MachineCodeEmitter &MCE); +FunctionPass *createARMJITCodeEmitterPass(ARMBaseTargetMachine &TM, + JITCodeEmitter &JCE); +FunctionPass *createARMObjectCodeEmitterPass(ARMBaseTargetMachine &TM, + ObjectCodeEmitter &OCE); + +FunctionPass *createARMLoadStoreOptimizationPass(bool PreAlloc = false); +FunctionPass *createARMExpandPseudoPass(); +FunctionPass *createARMConstantIslandPass(); +FunctionPass *createNEONPreAllocPass(); +FunctionPass *createNEONMoveFixPass(); +FunctionPass *createThumb2ITBlockPass(); +FunctionPass *createThumb2SizeReductionPass(); +FunctionPass *createARMMaxStackAlignmentCalculatorPass(); + +extern Target TheARMTarget, TheThumbTarget; + +} // end namespace llvm; + +// Defines symbolic names for ARM registers. This defines a mapping from +// register name to register number. +// +#include "ARMGenRegisterNames.inc" + +// Defines symbolic names for the ARM instructions. +// +#include "ARMGenInstrNames.inc" + + +#endif diff --git a/libclamav/c++/llvm/lib/Target/ARM/ARM.td b/libclamav/c++/llvm/lib/Target/ARM/ARM.td new file mode 100644 index 000000000..70338612d --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/ARM/ARM.td @@ -0,0 +1,149 @@ +//===- ARM.td - Describe the ARM Target Machine -----------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// Target-independent interfaces which we are implementing +//===----------------------------------------------------------------------===// + +include "llvm/Target/Target.td" + +//===----------------------------------------------------------------------===// +// ARM Subtarget features. +// + +def ArchV4T : SubtargetFeature<"v4t", "ARMArchVersion", "V4T", + "ARM v4T">; +def ArchV5T : SubtargetFeature<"v5t", "ARMArchVersion", "V5T", + "ARM v5T">; +def ArchV5TE : SubtargetFeature<"v5te", "ARMArchVersion", "V5TE", + "ARM v5TE, v5TEj, v5TExp">; +def ArchV6 : SubtargetFeature<"v6", "ARMArchVersion", "V6", + "ARM v6">; +def ArchV6T2 : SubtargetFeature<"v6t2", "ARMArchVersion", "V6T2", + "ARM v6t2">; +def ArchV7A : SubtargetFeature<"v7a", "ARMArchVersion", "V7A", + "ARM v7A">; +def FeatureVFP2 : SubtargetFeature<"vfp2", "ARMFPUType", "VFPv2", + "Enable VFP2 instructions">; +def FeatureVFP3 : SubtargetFeature<"vfp3", "ARMFPUType", "VFPv3", + "Enable VFP3 instructions">; +def FeatureNEON : SubtargetFeature<"neon", "ARMFPUType", "NEON", + "Enable NEON instructions">; +def FeatureThumb2 : SubtargetFeature<"thumb2", "ThumbMode", "Thumb2", + "Enable Thumb2 instructions">; + +//===----------------------------------------------------------------------===// +// ARM Processors supported. +// + +include "ARMSchedule.td" + +class ProcNoItin Features> + : Processor; + +// V4 Processors. +def : ProcNoItin<"generic", []>; +def : ProcNoItin<"arm8", []>; +def : ProcNoItin<"arm810", []>; +def : ProcNoItin<"strongarm", []>; +def : ProcNoItin<"strongarm110", []>; +def : ProcNoItin<"strongarm1100", []>; +def : ProcNoItin<"strongarm1110", []>; + +// V4T Processors. +def : ProcNoItin<"arm7tdmi", [ArchV4T]>; +def : ProcNoItin<"arm7tdmi-s", [ArchV4T]>; +def : ProcNoItin<"arm710t", [ArchV4T]>; +def : ProcNoItin<"arm720t", [ArchV4T]>; +def : ProcNoItin<"arm9", [ArchV4T]>; +def : ProcNoItin<"arm9tdmi", [ArchV4T]>; +def : ProcNoItin<"arm920", [ArchV4T]>; +def : ProcNoItin<"arm920t", [ArchV4T]>; +def : ProcNoItin<"arm922t", [ArchV4T]>; +def : ProcNoItin<"arm940t", [ArchV4T]>; +def : ProcNoItin<"ep9312", [ArchV4T]>; + +// V5T Processors. +def : ProcNoItin<"arm10tdmi", [ArchV5T]>; +def : ProcNoItin<"arm1020t", [ArchV5T]>; + +// V5TE Processors. +def : ProcNoItin<"arm9e", [ArchV5TE]>; +def : ProcNoItin<"arm926ej-s", [ArchV5TE]>; +def : ProcNoItin<"arm946e-s", [ArchV5TE]>; +def : ProcNoItin<"arm966e-s", [ArchV5TE]>; +def : ProcNoItin<"arm968e-s", [ArchV5TE]>; +def : ProcNoItin<"arm10e", [ArchV5TE]>; +def : ProcNoItin<"arm1020e", [ArchV5TE]>; +def : ProcNoItin<"arm1022e", [ArchV5TE]>; +def : ProcNoItin<"xscale", [ArchV5TE]>; +def : ProcNoItin<"iwmmxt", [ArchV5TE]>; + +// V6 Processors. +def : Processor<"arm1136j-s", ARMV6Itineraries, [ArchV6]>; +def : Processor<"arm1136jf-s", ARMV6Itineraries, [ArchV6, FeatureVFP2]>; +def : Processor<"arm1176jz-s", ARMV6Itineraries, [ArchV6]>; +def : Processor<"arm1176jzf-s", ARMV6Itineraries, [ArchV6, FeatureVFP2]>; +def : Processor<"mpcorenovfp", ARMV6Itineraries, [ArchV6]>; +def : Processor<"mpcore", ARMV6Itineraries, [ArchV6, FeatureVFP2]>; + +// V6T2 Processors. +def : Processor<"arm1156t2-s", ARMV6Itineraries, + [ArchV6T2, FeatureThumb2]>; +def : Processor<"arm1156t2f-s", ARMV6Itineraries, + [ArchV6T2, FeatureThumb2, FeatureVFP2]>; + +// V7 Processors. +def : Processor<"cortex-a8", CortexA8Itineraries, + [ArchV7A, FeatureThumb2, FeatureNEON]>; +def : ProcNoItin<"cortex-a9", [ArchV7A, FeatureThumb2, FeatureNEON]>; + +//===----------------------------------------------------------------------===// +// Register File Description +//===----------------------------------------------------------------------===// + +include "ARMRegisterInfo.td" + +include "ARMCallingConv.td" + +//===----------------------------------------------------------------------===// +// Instruction Descriptions +//===----------------------------------------------------------------------===// + +include "ARMInstrInfo.td" + +def ARMInstrInfo : InstrInfo { + // Define how we want to layout our target-specific information field. + let TSFlagsFields = ["AddrModeBits", + "SizeFlag", + "IndexModeBits", + "Form", + "isUnaryDataProc", + "canXformTo16Bit", + "Dom"]; + let TSFlagsShifts = [0, + 4, + 7, + 9, + 15, + 16, + 17]; +} + +//===----------------------------------------------------------------------===// +// Declare the target which we are implementing +//===----------------------------------------------------------------------===// + +def ARM : Target { + // Pull in Instruction Info: + let InstructionSet = ARMInstrInfo; +} diff --git a/libclamav/c++/llvm/lib/Target/ARM/ARMAddressingModes.h b/libclamav/c++/llvm/lib/Target/ARM/ARMAddressingModes.h new file mode 100644 index 000000000..ddeb1b994 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/ARM/ARMAddressingModes.h @@ -0,0 +1,566 @@ +//===- ARMAddressingModes.h - ARM Addressing Modes --------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the ARM addressing mode implementation stuff. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TARGET_ARM_ARMADDRESSINGMODES_H +#define LLVM_TARGET_ARM_ARMADDRESSINGMODES_H + +#include "llvm/CodeGen/SelectionDAGNodes.h" +#include "llvm/Support/MathExtras.h" +#include + +namespace llvm { + +/// ARM_AM - ARM Addressing Mode Stuff +namespace ARM_AM { + enum ShiftOpc { + no_shift = 0, + asr, + lsl, + lsr, + ror, + rrx + }; + + enum AddrOpc { + add = '+', sub = '-' + }; + + static inline const char *getShiftOpcStr(ShiftOpc Op) { + switch (Op) { + default: assert(0 && "Unknown shift opc!"); + case ARM_AM::asr: return "asr"; + case ARM_AM::lsl: return "lsl"; + case ARM_AM::lsr: return "lsr"; + case ARM_AM::ror: return "ror"; + case ARM_AM::rrx: return "rrx"; + } + } + + static inline ShiftOpc getShiftOpcForNode(SDValue N) { + switch (N.getOpcode()) { + default: return ARM_AM::no_shift; + case ISD::SHL: return ARM_AM::lsl; + case ISD::SRL: return ARM_AM::lsr; + case ISD::SRA: return ARM_AM::asr; + case ISD::ROTR: return ARM_AM::ror; + //case ISD::ROTL: // Only if imm -> turn into ROTR. + // Can't handle RRX here, because it would require folding a flag into + // the addressing mode. :( This causes us to miss certain things. + //case ARMISD::RRX: return ARM_AM::rrx; + } + } + + enum AMSubMode { + bad_am_submode = 0, + ia, + ib, + da, + db + }; + + static inline const char *getAMSubModeStr(AMSubMode Mode) { + switch (Mode) { + default: assert(0 && "Unknown addressing sub-mode!"); + case ARM_AM::ia: return "ia"; + case ARM_AM::ib: return "ib"; + case ARM_AM::da: return "da"; + case ARM_AM::db: return "db"; + } + } + + static inline const char *getAMSubModeAltStr(AMSubMode Mode, bool isLD) { + switch (Mode) { + default: assert(0 && "Unknown addressing sub-mode!"); + case ARM_AM::ia: return isLD ? "fd" : "ea"; + case ARM_AM::ib: return isLD ? "ed" : "fa"; + case ARM_AM::da: return isLD ? "fa" : "ed"; + case ARM_AM::db: return isLD ? "ea" : "fd"; + } + } + + /// rotr32 - Rotate a 32-bit unsigned value right by a specified # bits. + /// + static inline unsigned rotr32(unsigned Val, unsigned Amt) { + assert(Amt < 32 && "Invalid rotate amount"); + return (Val >> Amt) | (Val << ((32-Amt)&31)); + } + + /// rotl32 - Rotate a 32-bit unsigned value left by a specified # bits. + /// + static inline unsigned rotl32(unsigned Val, unsigned Amt) { + assert(Amt < 32 && "Invalid rotate amount"); + return (Val << Amt) | (Val >> ((32-Amt)&31)); + } + + //===--------------------------------------------------------------------===// + // Addressing Mode #1: shift_operand with registers + //===--------------------------------------------------------------------===// + // + // This 'addressing mode' is used for arithmetic instructions. It can + // represent things like: + // reg + // reg [asr|lsl|lsr|ror|rrx] reg + // reg [asr|lsl|lsr|ror|rrx] imm + // + // This is stored three operands [rega, regb, opc]. The first is the base + // reg, the second is the shift amount (or reg0 if not present or imm). The + // third operand encodes the shift opcode and the imm if a reg isn't present. + // + static inline unsigned getSORegOpc(ShiftOpc ShOp, unsigned Imm) { + return ShOp | (Imm << 3); + } + static inline unsigned getSORegOffset(unsigned Op) { + return Op >> 3; + } + static inline ShiftOpc getSORegShOp(unsigned Op) { + return (ShiftOpc)(Op & 7); + } + + /// getSOImmValImm - Given an encoded imm field for the reg/imm form, return + /// the 8-bit imm value. + static inline unsigned getSOImmValImm(unsigned Imm) { + return Imm & 0xFF; + } + /// getSOImmValRot - Given an encoded imm field for the reg/imm form, return + /// the rotate amount. + static inline unsigned getSOImmValRot(unsigned Imm) { + return (Imm >> 8) * 2; + } + + /// getSOImmValRotate - Try to handle Imm with an immediate shifter operand, + /// computing the rotate amount to use. If this immediate value cannot be + /// handled with a single shifter-op, determine a good rotate amount that will + /// take a maximal chunk of bits out of the immediate. + static inline unsigned getSOImmValRotate(unsigned Imm) { + // 8-bit (or less) immediates are trivially shifter_operands with a rotate + // of zero. + if ((Imm & ~255U) == 0) return 0; + + // Use CTZ to compute the rotate amount. + unsigned TZ = CountTrailingZeros_32(Imm); + + // Rotate amount must be even. Something like 0x200 must be rotated 8 bits, + // not 9. + unsigned RotAmt = TZ & ~1; + + // If we can handle this spread, return it. + if ((rotr32(Imm, RotAmt) & ~255U) == 0) + return (32-RotAmt)&31; // HW rotates right, not left. + + // For values like 0xF000000F, we should skip the first run of ones, then + // retry the hunt. + if (Imm & 1) { + unsigned TrailingOnes = CountTrailingZeros_32(~Imm); + if (TrailingOnes != 32) { // Avoid overflow on 0xFFFFFFFF + // Restart the search for a high-order bit after the initial seconds of + // ones. + unsigned TZ2 = CountTrailingZeros_32(Imm & ~((1 << TrailingOnes)-1)); + + // Rotate amount must be even. + unsigned RotAmt2 = TZ2 & ~1; + + // If this fits, use it. + if (RotAmt2 != 32 && (rotr32(Imm, RotAmt2) & ~255U) == 0) + return (32-RotAmt2)&31; // HW rotates right, not left. + } + } + + // Otherwise, we have no way to cover this span of bits with a single + // shifter_op immediate. Return a chunk of bits that will be useful to + // handle. + return (32-RotAmt)&31; // HW rotates right, not left. + } + + /// getSOImmVal - Given a 32-bit immediate, if it is something that can fit + /// into an shifter_operand immediate operand, return the 12-bit encoding for + /// it. If not, return -1. + static inline int getSOImmVal(unsigned Arg) { + // 8-bit (or less) immediates are trivially shifter_operands with a rotate + // of zero. + if ((Arg & ~255U) == 0) return Arg; + + unsigned RotAmt = getSOImmValRotate(Arg); + + // If this cannot be handled with a single shifter_op, bail out. + if (rotr32(~255U, RotAmt) & Arg) + return -1; + + // Encode this correctly. + return rotl32(Arg, RotAmt) | ((RotAmt>>1) << 8); + } + + /// isSOImmTwoPartVal - Return true if the specified value can be obtained by + /// or'ing together two SOImmVal's. + static inline bool isSOImmTwoPartVal(unsigned V) { + // If this can be handled with a single shifter_op, bail out. + V = rotr32(~255U, getSOImmValRotate(V)) & V; + if (V == 0) + return false; + + // If this can be handled with two shifter_op's, accept. + V = rotr32(~255U, getSOImmValRotate(V)) & V; + return V == 0; + } + + /// getSOImmTwoPartFirst - If V is a value that satisfies isSOImmTwoPartVal, + /// return the first chunk of it. + static inline unsigned getSOImmTwoPartFirst(unsigned V) { + return rotr32(255U, getSOImmValRotate(V)) & V; + } + + /// getSOImmTwoPartSecond - If V is a value that satisfies isSOImmTwoPartVal, + /// return the second chunk of it. + static inline unsigned getSOImmTwoPartSecond(unsigned V) { + // Mask out the first hunk. + V = rotr32(~255U, getSOImmValRotate(V)) & V; + + // Take what's left. + assert(V == (rotr32(255U, getSOImmValRotate(V)) & V)); + return V; + } + + /// getThumbImmValShift - Try to handle Imm with a 8-bit immediate followed + /// by a left shift. Returns the shift amount to use. + static inline unsigned getThumbImmValShift(unsigned Imm) { + // 8-bit (or less) immediates are trivially immediate operand with a shift + // of zero. + if ((Imm & ~255U) == 0) return 0; + + // Use CTZ to compute the shift amount. + return CountTrailingZeros_32(Imm); + } + + /// isThumbImmShiftedVal - Return true if the specified value can be obtained + /// by left shifting a 8-bit immediate. + static inline bool isThumbImmShiftedVal(unsigned V) { + // If this can be handled with + V = (~255U << getThumbImmValShift(V)) & V; + return V == 0; + } + + /// getThumbImm16ValShift - Try to handle Imm with a 16-bit immediate followed + /// by a left shift. Returns the shift amount to use. + static inline unsigned getThumbImm16ValShift(unsigned Imm) { + // 16-bit (or less) immediates are trivially immediate operand with a shift + // of zero. + if ((Imm & ~65535U) == 0) return 0; + + // Use CTZ to compute the shift amount. + return CountTrailingZeros_32(Imm); + } + + /// isThumbImm16ShiftedVal - Return true if the specified value can be + /// obtained by left shifting a 16-bit immediate. + static inline bool isThumbImm16ShiftedVal(unsigned V) { + // If this can be handled with + V = (~65535U << getThumbImm16ValShift(V)) & V; + return V == 0; + } + + /// getThumbImmNonShiftedVal - If V is a value that satisfies + /// isThumbImmShiftedVal, return the non-shiftd value. + static inline unsigned getThumbImmNonShiftedVal(unsigned V) { + return V >> getThumbImmValShift(V); + } + + + /// getT2SOImmValSplat - Return the 12-bit encoded representation + /// if the specified value can be obtained by splatting the low 8 bits + /// into every other byte or every byte of a 32-bit value. i.e., + /// 00000000 00000000 00000000 abcdefgh control = 0 + /// 00000000 abcdefgh 00000000 abcdefgh control = 1 + /// abcdefgh 00000000 abcdefgh 00000000 control = 2 + /// abcdefgh abcdefgh abcdefgh abcdefgh control = 3 + /// Return -1 if none of the above apply. + /// See ARM Reference Manual A6.3.2. + static inline int getT2SOImmValSplatVal(unsigned V) { + unsigned u, Vs, Imm; + // control = 0 + if ((V & 0xffffff00) == 0) + return V; + + // If the value is zeroes in the first byte, just shift those off + Vs = ((V & 0xff) == 0) ? V >> 8 : V; + // Any passing value only has 8 bits of payload, splatted across the word + Imm = Vs & 0xff; + // Likewise, any passing values have the payload splatted into the 3rd byte + u = Imm | (Imm << 16); + + // control = 1 or 2 + if (Vs == u) + return (((Vs == V) ? 1 : 2) << 8) | Imm; + + // control = 3 + if (Vs == (u | (u << 8))) + return (3 << 8) | Imm; + + return -1; + } + + /// getT2SOImmValRotateVal - Return the 12-bit encoded representation if the + /// specified value is a rotated 8-bit value. Return -1 if no rotation + /// encoding is possible. + /// See ARM Reference Manual A6.3.2. + static inline int getT2SOImmValRotateVal(unsigned V) { + unsigned RotAmt = CountLeadingZeros_32(V); + if (RotAmt >= 24) + return -1; + + // If 'Arg' can be handled with a single shifter_op return the value. + if ((rotr32(0xff000000U, RotAmt) & V) == V) + return (rotr32(V, 24 - RotAmt) & 0x7f) | ((RotAmt + 8) << 7); + + return -1; + } + + /// getT2SOImmVal - Given a 32-bit immediate, if it is something that can fit + /// into a Thumb-2 shifter_operand immediate operand, return the 12-bit + /// encoding for it. If not, return -1. + /// See ARM Reference Manual A6.3.2. + static inline int getT2SOImmVal(unsigned Arg) { + // If 'Arg' is an 8-bit splat, then get the encoded value. + int Splat = getT2SOImmValSplatVal(Arg); + if (Splat != -1) + return Splat; + + // If 'Arg' can be handled with a single shifter_op return the value. + int Rot = getT2SOImmValRotateVal(Arg); + if (Rot != -1) + return Rot; + + return -1; + } + + static inline unsigned getT2SOImmValRotate(unsigned V) { + if ((V & ~255U) == 0) return 0; + // Use CTZ to compute the rotate amount. + unsigned RotAmt = CountTrailingZeros_32(V); + return (32 - RotAmt) & 31; + } + + static inline bool isT2SOImmTwoPartVal (unsigned Imm) { + unsigned V = Imm; + // Passing values can be any combination of splat values and shifter + // values. If this can be handled with a single shifter or splat, bail + // out. Those should be handled directly, not with a two-part val. + if (getT2SOImmValSplatVal(V) != -1) + return false; + V = rotr32 (~255U, getT2SOImmValRotate(V)) & V; + if (V == 0) + return false; + + // If this can be handled as an immediate, accept. + if (getT2SOImmVal(V) != -1) return true; + + // Likewise, try masking out a splat value first. + V = Imm; + if (getT2SOImmValSplatVal(V & 0xff00ff00U) != -1) + V &= ~0xff00ff00U; + else if (getT2SOImmValSplatVal(V & 0x00ff00ffU) != -1) + V &= ~0x00ff00ffU; + // If what's left can be handled as an immediate, accept. + if (getT2SOImmVal(V) != -1) return true; + + // Otherwise, do not accept. + return false; + } + + static inline unsigned getT2SOImmTwoPartFirst(unsigned Imm) { + assert (isT2SOImmTwoPartVal(Imm) && + "Immedate cannot be encoded as two part immediate!"); + // Try a shifter operand as one part + unsigned V = rotr32 (~255, getT2SOImmValRotate(Imm)) & Imm; + // If the rest is encodable as an immediate, then return it. + if (getT2SOImmVal(V) != -1) return V; + + // Try masking out a splat value first. + if (getT2SOImmValSplatVal(Imm & 0xff00ff00U) != -1) + return Imm & 0xff00ff00U; + + // The other splat is all that's left as an option. + assert (getT2SOImmValSplatVal(Imm & 0x00ff00ffU) != -1); + return Imm & 0x00ff00ffU; + } + + static inline unsigned getT2SOImmTwoPartSecond(unsigned Imm) { + // Mask out the first hunk + Imm ^= getT2SOImmTwoPartFirst(Imm); + // Return what's left + assert (getT2SOImmVal(Imm) != -1 && + "Unable to encode second part of T2 two part SO immediate"); + return Imm; + } + + + //===--------------------------------------------------------------------===// + // Addressing Mode #2 + //===--------------------------------------------------------------------===// + // + // This is used for most simple load/store instructions. + // + // addrmode2 := reg +/- reg shop imm + // addrmode2 := reg +/- imm12 + // + // The first operand is always a Reg. The second operand is a reg if in + // reg/reg form, otherwise it's reg#0. The third field encodes the operation + // in bit 12, the immediate in bits 0-11, and the shift op in 13-15. + // + // If this addressing mode is a frame index (before prolog/epilog insertion + // and code rewriting), this operand will have the form: FI#, reg0, + // with no shift amount for the frame offset. + // + static inline unsigned getAM2Opc(AddrOpc Opc, unsigned Imm12, ShiftOpc SO) { + assert(Imm12 < (1 << 12) && "Imm too large!"); + bool isSub = Opc == sub; + return Imm12 | ((int)isSub << 12) | (SO << 13); + } + static inline unsigned getAM2Offset(unsigned AM2Opc) { + return AM2Opc & ((1 << 12)-1); + } + static inline AddrOpc getAM2Op(unsigned AM2Opc) { + return ((AM2Opc >> 12) & 1) ? sub : add; + } + static inline ShiftOpc getAM2ShiftOpc(unsigned AM2Opc) { + return (ShiftOpc)(AM2Opc >> 13); + } + + + //===--------------------------------------------------------------------===// + // Addressing Mode #3 + //===--------------------------------------------------------------------===// + // + // This is used for sign-extending loads, and load/store-pair instructions. + // + // addrmode3 := reg +/- reg + // addrmode3 := reg +/- imm8 + // + // The first operand is always a Reg. The second operand is a reg if in + // reg/reg form, otherwise it's reg#0. The third field encodes the operation + // in bit 8, the immediate in bits 0-7. + + /// getAM3Opc - This function encodes the addrmode3 opc field. + static inline unsigned getAM3Opc(AddrOpc Opc, unsigned char Offset) { + bool isSub = Opc == sub; + return ((int)isSub << 8) | Offset; + } + static inline unsigned char getAM3Offset(unsigned AM3Opc) { + return AM3Opc & 0xFF; + } + static inline AddrOpc getAM3Op(unsigned AM3Opc) { + return ((AM3Opc >> 8) & 1) ? sub : add; + } + + //===--------------------------------------------------------------------===// + // Addressing Mode #4 + //===--------------------------------------------------------------------===// + // + // This is used for load / store multiple instructions. + // + // addrmode4 := reg, + // + // The four modes are: + // IA - Increment after + // IB - Increment before + // DA - Decrement after + // DB - Decrement before + // + // If the 4th bit (writeback)is set, then the base register is updated after + // the memory transfer. + + static inline AMSubMode getAM4SubMode(unsigned Mode) { + return (AMSubMode)(Mode & 0x7); + } + + static inline unsigned getAM4ModeImm(AMSubMode SubMode, bool WB = false) { + return (int)SubMode | ((int)WB << 3); + } + + static inline bool getAM4WBFlag(unsigned Mode) { + return (Mode >> 3) & 1; + } + + //===--------------------------------------------------------------------===// + // Addressing Mode #5 + //===--------------------------------------------------------------------===// + // + // This is used for coprocessor instructions, such as FP load/stores. + // + // addrmode5 := reg +/- imm8*4 + // + // The first operand is always a Reg. The second operand encodes the + // operation in bit 8 and the immediate in bits 0-7. + // + // This is also used for FP load/store multiple ops. The second operand + // encodes the writeback mode in bit 8 and the number of registers (or 2 + // times the number of registers for DPR ops) in bits 0-7. In addition, + // bits 9-11 encode one of the following two sub-modes: + // + // IA - Increment after + // DB - Decrement before + + /// getAM5Opc - This function encodes the addrmode5 opc field. + static inline unsigned getAM5Opc(AddrOpc Opc, unsigned char Offset) { + bool isSub = Opc == sub; + return ((int)isSub << 8) | Offset; + } + static inline unsigned char getAM5Offset(unsigned AM5Opc) { + return AM5Opc & 0xFF; + } + static inline AddrOpc getAM5Op(unsigned AM5Opc) { + return ((AM5Opc >> 8) & 1) ? sub : add; + } + + /// getAM5Opc - This function encodes the addrmode5 opc field for VLDM and + /// VSTM instructions. + static inline unsigned getAM5Opc(AMSubMode SubMode, bool WB, + unsigned char Offset) { + assert((SubMode == ia || SubMode == db) && + "Illegal addressing mode 5 sub-mode!"); + return ((int)SubMode << 9) | ((int)WB << 8) | Offset; + } + static inline AMSubMode getAM5SubMode(unsigned AM5Opc) { + return (AMSubMode)((AM5Opc >> 9) & 0x7); + } + static inline bool getAM5WBFlag(unsigned AM5Opc) { + return ((AM5Opc >> 8) & 1); + } + + //===--------------------------------------------------------------------===// + // Addressing Mode #6 + //===--------------------------------------------------------------------===// + // + // This is used for NEON load / store instructions. + // + // addrmode6 := reg with optional writeback and alignment + // + // This is stored in four operands [regaddr, regupdate, opc, align]. The + // first is the address register. The second register holds the value of + // a post-access increment for writeback or reg0 if no writeback or if the + // writeback increment is the size of the memory access. The third + // operand encodes whether there is writeback to the address register. The + // fourth operand is the value of the alignment specifier to use or zero if + // no explicit alignment. + + static inline unsigned getAM6Opc(bool WB = false) { + return (int)WB; + } + + static inline bool getAM6WBFlag(unsigned Mode) { + return Mode & 1; + } + +} // end namespace ARM_AM +} // end namespace llvm + +#endif + diff --git a/libclamav/c++/llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp b/libclamav/c++/llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp new file mode 100644 index 000000000..705f97097 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp @@ -0,0 +1,1214 @@ +//===- ARMBaseInstrInfo.cpp - ARM Instruction Information -------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the Base ARM implementation of the TargetInstrInfo class. +// +//===----------------------------------------------------------------------===// + +#include "ARMBaseInstrInfo.h" +#include "ARM.h" +#include "ARMAddressingModes.h" +#include "ARMConstantPoolValue.h" +#include "ARMGenInstrInfo.inc" +#include "ARMMachineFunctionInfo.h" +#include "ARMRegisterInfo.h" +#include "llvm/Constants.h" +#include "llvm/Function.h" +#include "llvm/GlobalValue.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/CodeGen/LiveVariables.h" +#include "llvm/CodeGen/MachineConstantPool.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineJumpTableInfo.h" +#include "llvm/CodeGen/MachineMemOperand.h" +#include "llvm/CodeGen/PseudoSourceValue.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +using namespace llvm; + +static cl::opt +EnableARM3Addr("enable-arm-3-addr-conv", cl::Hidden, + cl::desc("Enable ARM 2-addr to 3-addr conv")); + +ARMBaseInstrInfo::ARMBaseInstrInfo(const ARMSubtarget& STI) + : TargetInstrInfoImpl(ARMInsts, array_lengthof(ARMInsts)), + Subtarget(STI) { +} + +MachineInstr * +ARMBaseInstrInfo::convertToThreeAddress(MachineFunction::iterator &MFI, + MachineBasicBlock::iterator &MBBI, + LiveVariables *LV) const { + // FIXME: Thumb2 support. + + if (!EnableARM3Addr) + return NULL; + + MachineInstr *MI = MBBI; + MachineFunction &MF = *MI->getParent()->getParent(); + unsigned TSFlags = MI->getDesc().TSFlags; + bool isPre = false; + switch ((TSFlags & ARMII::IndexModeMask) >> ARMII::IndexModeShift) { + default: return NULL; + case ARMII::IndexModePre: + isPre = true; + break; + case ARMII::IndexModePost: + break; + } + + // Try splitting an indexed load/store to an un-indexed one plus an add/sub + // operation. + unsigned MemOpc = getUnindexedOpcode(MI->getOpcode()); + if (MemOpc == 0) + return NULL; + + MachineInstr *UpdateMI = NULL; + MachineInstr *MemMI = NULL; + unsigned AddrMode = (TSFlags & ARMII::AddrModeMask); + const TargetInstrDesc &TID = MI->getDesc(); + unsigned NumOps = TID.getNumOperands(); + bool isLoad = !TID.mayStore(); + const MachineOperand &WB = isLoad ? MI->getOperand(1) : MI->getOperand(0); + const MachineOperand &Base = MI->getOperand(2); + const MachineOperand &Offset = MI->getOperand(NumOps-3); + unsigned WBReg = WB.getReg(); + unsigned BaseReg = Base.getReg(); + unsigned OffReg = Offset.getReg(); + unsigned OffImm = MI->getOperand(NumOps-2).getImm(); + ARMCC::CondCodes Pred = (ARMCC::CondCodes)MI->getOperand(NumOps-1).getImm(); + switch (AddrMode) { + default: + assert(false && "Unknown indexed op!"); + return NULL; + case ARMII::AddrMode2: { + bool isSub = ARM_AM::getAM2Op(OffImm) == ARM_AM::sub; + unsigned Amt = ARM_AM::getAM2Offset(OffImm); + if (OffReg == 0) { + if (ARM_AM::getSOImmVal(Amt) == -1) + // Can't encode it in a so_imm operand. This transformation will + // add more than 1 instruction. Abandon! + return NULL; + UpdateMI = BuildMI(MF, MI->getDebugLoc(), + get(isSub ? ARM::SUBri : ARM::ADDri), WBReg) + .addReg(BaseReg).addImm(Amt) + .addImm(Pred).addReg(0).addReg(0); + } else if (Amt != 0) { + ARM_AM::ShiftOpc ShOpc = ARM_AM::getAM2ShiftOpc(OffImm); + unsigned SOOpc = ARM_AM::getSORegOpc(ShOpc, Amt); + UpdateMI = BuildMI(MF, MI->getDebugLoc(), + get(isSub ? ARM::SUBrs : ARM::ADDrs), WBReg) + .addReg(BaseReg).addReg(OffReg).addReg(0).addImm(SOOpc) + .addImm(Pred).addReg(0).addReg(0); + } else + UpdateMI = BuildMI(MF, MI->getDebugLoc(), + get(isSub ? ARM::SUBrr : ARM::ADDrr), WBReg) + .addReg(BaseReg).addReg(OffReg) + .addImm(Pred).addReg(0).addReg(0); + break; + } + case ARMII::AddrMode3 : { + bool isSub = ARM_AM::getAM3Op(OffImm) == ARM_AM::sub; + unsigned Amt = ARM_AM::getAM3Offset(OffImm); + if (OffReg == 0) + // Immediate is 8-bits. It's guaranteed to fit in a so_imm operand. + UpdateMI = BuildMI(MF, MI->getDebugLoc(), + get(isSub ? ARM::SUBri : ARM::ADDri), WBReg) + .addReg(BaseReg).addImm(Amt) + .addImm(Pred).addReg(0).addReg(0); + else + UpdateMI = BuildMI(MF, MI->getDebugLoc(), + get(isSub ? ARM::SUBrr : ARM::ADDrr), WBReg) + .addReg(BaseReg).addReg(OffReg) + .addImm(Pred).addReg(0).addReg(0); + break; + } + } + + std::vector NewMIs; + if (isPre) { + if (isLoad) + MemMI = BuildMI(MF, MI->getDebugLoc(), + get(MemOpc), MI->getOperand(0).getReg()) + .addReg(WBReg).addReg(0).addImm(0).addImm(Pred); + else + MemMI = BuildMI(MF, MI->getDebugLoc(), + get(MemOpc)).addReg(MI->getOperand(1).getReg()) + .addReg(WBReg).addReg(0).addImm(0).addImm(Pred); + NewMIs.push_back(MemMI); + NewMIs.push_back(UpdateMI); + } else { + if (isLoad) + MemMI = BuildMI(MF, MI->getDebugLoc(), + get(MemOpc), MI->getOperand(0).getReg()) + .addReg(BaseReg).addReg(0).addImm(0).addImm(Pred); + else + MemMI = BuildMI(MF, MI->getDebugLoc(), + get(MemOpc)).addReg(MI->getOperand(1).getReg()) + .addReg(BaseReg).addReg(0).addImm(0).addImm(Pred); + if (WB.isDead()) + UpdateMI->getOperand(0).setIsDead(); + NewMIs.push_back(UpdateMI); + NewMIs.push_back(MemMI); + } + + // Transfer LiveVariables states, kill / dead info. + if (LV) { + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + MachineOperand &MO = MI->getOperand(i); + if (MO.isReg() && MO.getReg() && + TargetRegisterInfo::isVirtualRegister(MO.getReg())) { + unsigned Reg = MO.getReg(); + + LiveVariables::VarInfo &VI = LV->getVarInfo(Reg); + if (MO.isDef()) { + MachineInstr *NewMI = (Reg == WBReg) ? UpdateMI : MemMI; + if (MO.isDead()) + LV->addVirtualRegisterDead(Reg, NewMI); + } + if (MO.isUse() && MO.isKill()) { + for (unsigned j = 0; j < 2; ++j) { + // Look at the two new MI's in reverse order. + MachineInstr *NewMI = NewMIs[j]; + if (!NewMI->readsRegister(Reg)) + continue; + LV->addVirtualRegisterKilled(Reg, NewMI); + if (VI.removeKill(MI)) + VI.Kills.push_back(NewMI); + break; + } + } + } + } + } + + MFI->insert(MBBI, NewMIs[1]); + MFI->insert(MBBI, NewMIs[0]); + return NewMIs[0]; +} + +// Branch analysis. +bool +ARMBaseInstrInfo::AnalyzeBranch(MachineBasicBlock &MBB,MachineBasicBlock *&TBB, + MachineBasicBlock *&FBB, + SmallVectorImpl &Cond, + bool AllowModify) const { + // If the block has no terminators, it just falls into the block after it. + MachineBasicBlock::iterator I = MBB.end(); + if (I == MBB.begin() || !isUnpredicatedTerminator(--I)) + return false; + + // Get the last instruction in the block. + MachineInstr *LastInst = I; + + // If there is only one terminator instruction, process it. + unsigned LastOpc = LastInst->getOpcode(); + if (I == MBB.begin() || !isUnpredicatedTerminator(--I)) { + if (isUncondBranchOpcode(LastOpc)) { + TBB = LastInst->getOperand(0).getMBB(); + return false; + } + if (isCondBranchOpcode(LastOpc)) { + // Block ends with fall-through condbranch. + TBB = LastInst->getOperand(0).getMBB(); + Cond.push_back(LastInst->getOperand(1)); + Cond.push_back(LastInst->getOperand(2)); + return false; + } + return true; // Can't handle indirect branch. + } + + // Get the instruction before it if it is a terminator. + MachineInstr *SecondLastInst = I; + + // If there are three terminators, we don't know what sort of block this is. + if (SecondLastInst && I != MBB.begin() && isUnpredicatedTerminator(--I)) + return true; + + // If the block ends with a B and a Bcc, handle it. + unsigned SecondLastOpc = SecondLastInst->getOpcode(); + if (isCondBranchOpcode(SecondLastOpc) && isUncondBranchOpcode(LastOpc)) { + TBB = SecondLastInst->getOperand(0).getMBB(); + Cond.push_back(SecondLastInst->getOperand(1)); + Cond.push_back(SecondLastInst->getOperand(2)); + FBB = LastInst->getOperand(0).getMBB(); + return false; + } + + // If the block ends with two unconditional branches, handle it. The second + // one is not executed, so remove it. + if (isUncondBranchOpcode(SecondLastOpc) && isUncondBranchOpcode(LastOpc)) { + TBB = SecondLastInst->getOperand(0).getMBB(); + I = LastInst; + if (AllowModify) + I->eraseFromParent(); + return false; + } + + // ...likewise if it ends with a branch table followed by an unconditional + // branch. The branch folder can create these, and we must get rid of them for + // correctness of Thumb constant islands. + if ((isJumpTableBranchOpcode(SecondLastOpc) || + isIndirectBranchOpcode(SecondLastOpc)) && + isUncondBranchOpcode(LastOpc)) { + I = LastInst; + if (AllowModify) + I->eraseFromParent(); + return true; + } + + // Otherwise, can't handle this. + return true; +} + + +unsigned ARMBaseInstrInfo::RemoveBranch(MachineBasicBlock &MBB) const { + MachineBasicBlock::iterator I = MBB.end(); + if (I == MBB.begin()) return 0; + --I; + if (!isUncondBranchOpcode(I->getOpcode()) && + !isCondBranchOpcode(I->getOpcode())) + return 0; + + // Remove the branch. + I->eraseFromParent(); + + I = MBB.end(); + + if (I == MBB.begin()) return 1; + --I; + if (!isCondBranchOpcode(I->getOpcode())) + return 1; + + // Remove the branch. + I->eraseFromParent(); + return 2; +} + +unsigned +ARMBaseInstrInfo::InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, + MachineBasicBlock *FBB, + const SmallVectorImpl &Cond) const { + // FIXME this should probably have a DebugLoc argument + DebugLoc dl = DebugLoc::getUnknownLoc(); + + ARMFunctionInfo *AFI = MBB.getParent()->getInfo(); + int BOpc = !AFI->isThumbFunction() + ? ARM::B : (AFI->isThumb2Function() ? ARM::t2B : ARM::tB); + int BccOpc = !AFI->isThumbFunction() + ? ARM::Bcc : (AFI->isThumb2Function() ? ARM::t2Bcc : ARM::tBcc); + + // Shouldn't be a fall through. + assert(TBB && "InsertBranch must not be told to insert a fallthrough"); + assert((Cond.size() == 2 || Cond.size() == 0) && + "ARM branch conditions have two components!"); + + if (FBB == 0) { + if (Cond.empty()) // Unconditional branch? + BuildMI(&MBB, dl, get(BOpc)).addMBB(TBB); + else + BuildMI(&MBB, dl, get(BccOpc)).addMBB(TBB) + .addImm(Cond[0].getImm()).addReg(Cond[1].getReg()); + return 1; + } + + // Two-way conditional branch. + BuildMI(&MBB, dl, get(BccOpc)).addMBB(TBB) + .addImm(Cond[0].getImm()).addReg(Cond[1].getReg()); + BuildMI(&MBB, dl, get(BOpc)).addMBB(FBB); + return 2; +} + +bool ARMBaseInstrInfo:: +ReverseBranchCondition(SmallVectorImpl &Cond) const { + ARMCC::CondCodes CC = (ARMCC::CondCodes)(int)Cond[0].getImm(); + Cond[0].setImm(ARMCC::getOppositeCondition(CC)); + return false; +} + +bool ARMBaseInstrInfo:: +PredicateInstruction(MachineInstr *MI, + const SmallVectorImpl &Pred) const { + unsigned Opc = MI->getOpcode(); + if (isUncondBranchOpcode(Opc)) { + MI->setDesc(get(getMatchingCondBranchOpcode(Opc))); + MI->addOperand(MachineOperand::CreateImm(Pred[0].getImm())); + MI->addOperand(MachineOperand::CreateReg(Pred[1].getReg(), false)); + return true; + } + + int PIdx = MI->findFirstPredOperandIdx(); + if (PIdx != -1) { + MachineOperand &PMO = MI->getOperand(PIdx); + PMO.setImm(Pred[0].getImm()); + MI->getOperand(PIdx+1).setReg(Pred[1].getReg()); + return true; + } + return false; +} + +bool ARMBaseInstrInfo:: +SubsumesPredicate(const SmallVectorImpl &Pred1, + const SmallVectorImpl &Pred2) const { + if (Pred1.size() > 2 || Pred2.size() > 2) + return false; + + ARMCC::CondCodes CC1 = (ARMCC::CondCodes)Pred1[0].getImm(); + ARMCC::CondCodes CC2 = (ARMCC::CondCodes)Pred2[0].getImm(); + if (CC1 == CC2) + return true; + + switch (CC1) { + default: + return false; + case ARMCC::AL: + return true; + case ARMCC::HS: + return CC2 == ARMCC::HI; + case ARMCC::LS: + return CC2 == ARMCC::LO || CC2 == ARMCC::EQ; + case ARMCC::GE: + return CC2 == ARMCC::GT; + case ARMCC::LE: + return CC2 == ARMCC::LT; + } +} + +bool ARMBaseInstrInfo::DefinesPredicate(MachineInstr *MI, + std::vector &Pred) const { + // FIXME: This confuses implicit_def with optional CPSR def. + const TargetInstrDesc &TID = MI->getDesc(); + if (!TID.getImplicitDefs() && !TID.hasOptionalDef()) + return false; + + bool Found = false; + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + const MachineOperand &MO = MI->getOperand(i); + if (MO.isReg() && MO.getReg() == ARM::CPSR) { + Pred.push_back(MO); + Found = true; + } + } + + return Found; +} + +/// isPredicable - Return true if the specified instruction can be predicated. +/// By default, this returns true for every instruction with a +/// PredicateOperand. +bool ARMBaseInstrInfo::isPredicable(MachineInstr *MI) const { + const TargetInstrDesc &TID = MI->getDesc(); + if (!TID.isPredicable()) + return false; + + if ((TID.TSFlags & ARMII::DomainMask) == ARMII::DomainNEON) { + ARMFunctionInfo *AFI = + MI->getParent()->getParent()->getInfo(); + return AFI->isThumb2Function(); + } + return true; +} + +/// FIXME: Works around a gcc miscompilation with -fstrict-aliasing +static unsigned getNumJTEntries(const std::vector &JT, + unsigned JTI) DISABLE_INLINE; +static unsigned getNumJTEntries(const std::vector &JT, + unsigned JTI) { + return JT[JTI].MBBs.size(); +} + +/// GetInstSize - Return the size of the specified MachineInstr. +/// +unsigned ARMBaseInstrInfo::GetInstSizeInBytes(const MachineInstr *MI) const { + const MachineBasicBlock &MBB = *MI->getParent(); + const MachineFunction *MF = MBB.getParent(); + const MCAsmInfo *MAI = MF->getTarget().getMCAsmInfo(); + + // Basic size info comes from the TSFlags field. + const TargetInstrDesc &TID = MI->getDesc(); + unsigned TSFlags = TID.TSFlags; + + unsigned Opc = MI->getOpcode(); + switch ((TSFlags & ARMII::SizeMask) >> ARMII::SizeShift) { + default: { + // If this machine instr is an inline asm, measure it. + if (MI->getOpcode() == ARM::INLINEASM) + return getInlineAsmLength(MI->getOperand(0).getSymbolName(), *MAI); + if (MI->isLabel()) + return 0; + switch (Opc) { + default: + llvm_unreachable("Unknown or unset size field for instr!"); + case TargetInstrInfo::IMPLICIT_DEF: + case TargetInstrInfo::KILL: + case TargetInstrInfo::DBG_LABEL: + case TargetInstrInfo::EH_LABEL: + return 0; + } + break; + } + case ARMII::Size8Bytes: return 8; // ARM instruction x 2. + case ARMII::Size4Bytes: return 4; // ARM / Thumb2 instruction. + case ARMII::Size2Bytes: return 2; // Thumb1 instruction. + case ARMII::SizeSpecial: { + switch (Opc) { + case ARM::CONSTPOOL_ENTRY: + // If this machine instr is a constant pool entry, its size is recorded as + // operand #2. + return MI->getOperand(2).getImm(); + case ARM::Int_eh_sjlj_setjmp: + return 24; + case ARM::t2Int_eh_sjlj_setjmp: + return 22; + case ARM::BR_JTr: + case ARM::BR_JTm: + case ARM::BR_JTadd: + case ARM::tBR_JTr: + case ARM::t2BR_JT: + case ARM::t2TBB: + case ARM::t2TBH: { + // These are jumptable branches, i.e. a branch followed by an inlined + // jumptable. The size is 4 + 4 * number of entries. For TBB, each + // entry is one byte; TBH two byte each. + unsigned EntrySize = (Opc == ARM::t2TBB) + ? 1 : ((Opc == ARM::t2TBH) ? 2 : 4); + unsigned NumOps = TID.getNumOperands(); + MachineOperand JTOP = + MI->getOperand(NumOps - (TID.isPredicable() ? 3 : 2)); + unsigned JTI = JTOP.getIndex(); + const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo(); + const std::vector &JT = MJTI->getJumpTables(); + assert(JTI < JT.size()); + // Thumb instructions are 2 byte aligned, but JT entries are 4 byte + // 4 aligned. The assembler / linker may add 2 byte padding just before + // the JT entries. The size does not include this padding; the + // constant islands pass does separate bookkeeping for it. + // FIXME: If we know the size of the function is less than (1 << 16) *2 + // bytes, we can use 16-bit entries instead. Then there won't be an + // alignment issue. + unsigned InstSize = (Opc == ARM::tBR_JTr || Opc == ARM::t2BR_JT) ? 2 : 4; + unsigned NumEntries = getNumJTEntries(JT, JTI); + if (Opc == ARM::t2TBB && (NumEntries & 1)) + // Make sure the instruction that follows TBB is 2-byte aligned. + // FIXME: Constant island pass should insert an "ALIGN" instruction + // instead. + ++NumEntries; + return NumEntries * EntrySize + InstSize; + } + default: + // Otherwise, pseudo-instruction sizes are zero. + return 0; + } + } + } + return 0; // Not reached +} + +/// Return true if the instruction is a register to register move and +/// leave the source and dest operands in the passed parameters. +/// +bool +ARMBaseInstrInfo::isMoveInstr(const MachineInstr &MI, + unsigned &SrcReg, unsigned &DstReg, + unsigned& SrcSubIdx, unsigned& DstSubIdx) const { + SrcSubIdx = DstSubIdx = 0; // No sub-registers. + + switch (MI.getOpcode()) { + default: break; + case ARM::VMOVS: + case ARM::VMOVD: + case ARM::VMOVDneon: + case ARM::VMOVQ: { + SrcReg = MI.getOperand(1).getReg(); + DstReg = MI.getOperand(0).getReg(); + return true; + } + case ARM::MOVr: + case ARM::tMOVr: + case ARM::tMOVgpr2tgpr: + case ARM::tMOVtgpr2gpr: + case ARM::tMOVgpr2gpr: + case ARM::t2MOVr: { + assert(MI.getDesc().getNumOperands() >= 2 && + MI.getOperand(0).isReg() && + MI.getOperand(1).isReg() && + "Invalid ARM MOV instruction"); + SrcReg = MI.getOperand(1).getReg(); + DstReg = MI.getOperand(0).getReg(); + return true; + } + } + + return false; +} + +unsigned +ARMBaseInstrInfo::isLoadFromStackSlot(const MachineInstr *MI, + int &FrameIndex) const { + switch (MI->getOpcode()) { + default: break; + case ARM::LDR: + case ARM::t2LDRs: // FIXME: don't use t2LDRs to access frame. + if (MI->getOperand(1).isFI() && + MI->getOperand(2).isReg() && + MI->getOperand(3).isImm() && + MI->getOperand(2).getReg() == 0 && + MI->getOperand(3).getImm() == 0) { + FrameIndex = MI->getOperand(1).getIndex(); + return MI->getOperand(0).getReg(); + } + break; + case ARM::t2LDRi12: + case ARM::tRestore: + if (MI->getOperand(1).isFI() && + MI->getOperand(2).isImm() && + MI->getOperand(2).getImm() == 0) { + FrameIndex = MI->getOperand(1).getIndex(); + return MI->getOperand(0).getReg(); + } + break; + case ARM::VLDRD: + case ARM::VLDRS: + if (MI->getOperand(1).isFI() && + MI->getOperand(2).isImm() && + MI->getOperand(2).getImm() == 0) { + FrameIndex = MI->getOperand(1).getIndex(); + return MI->getOperand(0).getReg(); + } + break; + } + + return 0; +} + +unsigned +ARMBaseInstrInfo::isStoreToStackSlot(const MachineInstr *MI, + int &FrameIndex) const { + switch (MI->getOpcode()) { + default: break; + case ARM::STR: + case ARM::t2STRs: // FIXME: don't use t2STRs to access frame. + if (MI->getOperand(1).isFI() && + MI->getOperand(2).isReg() && + MI->getOperand(3).isImm() && + MI->getOperand(2).getReg() == 0 && + MI->getOperand(3).getImm() == 0) { + FrameIndex = MI->getOperand(1).getIndex(); + return MI->getOperand(0).getReg(); + } + break; + case ARM::t2STRi12: + case ARM::tSpill: + if (MI->getOperand(1).isFI() && + MI->getOperand(2).isImm() && + MI->getOperand(2).getImm() == 0) { + FrameIndex = MI->getOperand(1).getIndex(); + return MI->getOperand(0).getReg(); + } + break; + case ARM::VSTRD: + case ARM::VSTRS: + if (MI->getOperand(1).isFI() && + MI->getOperand(2).isImm() && + MI->getOperand(2).getImm() == 0) { + FrameIndex = MI->getOperand(1).getIndex(); + return MI->getOperand(0).getReg(); + } + break; + } + + return 0; +} + +bool +ARMBaseInstrInfo::copyRegToReg(MachineBasicBlock &MBB, + MachineBasicBlock::iterator I, + unsigned DestReg, unsigned SrcReg, + const TargetRegisterClass *DestRC, + const TargetRegisterClass *SrcRC) const { + DebugLoc DL = DebugLoc::getUnknownLoc(); + if (I != MBB.end()) DL = I->getDebugLoc(); + + if (DestRC != SrcRC) { + if (DestRC->getSize() != SrcRC->getSize()) + return false; + + // Allow DPR / DPR_VFP2 / DPR_8 cross-class copies. + // Allow QPR / QPR_VFP2 / QPR_8 cross-class copies. + if (DestRC->getSize() != 8 && DestRC->getSize() != 16) + return false; + } + + if (DestRC == ARM::GPRRegisterClass) { + AddDefaultCC(AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::MOVr), + DestReg).addReg(SrcReg))); + } else if (DestRC == ARM::SPRRegisterClass) { + AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VMOVS), DestReg) + .addReg(SrcReg)); + } else if (DestRC == ARM::DPRRegisterClass) { + AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VMOVD), DestReg) + .addReg(SrcReg)); + } else if (DestRC == ARM::DPR_VFP2RegisterClass || + DestRC == ARM::DPR_8RegisterClass || + SrcRC == ARM::DPR_VFP2RegisterClass || + SrcRC == ARM::DPR_8RegisterClass) { + // Always use neon reg-reg move if source or dest is NEON-only regclass. + AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VMOVDneon), + DestReg).addReg(SrcReg)); + } else if (DestRC == ARM::QPRRegisterClass || + DestRC == ARM::QPR_VFP2RegisterClass || + DestRC == ARM::QPR_8RegisterClass) { + AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VMOVQ), + DestReg).addReg(SrcReg)); + } else { + return false; + } + + return true; +} + +void ARMBaseInstrInfo:: +storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, + unsigned SrcReg, bool isKill, int FI, + const TargetRegisterClass *RC) const { + DebugLoc DL = DebugLoc::getUnknownLoc(); + if (I != MBB.end()) DL = I->getDebugLoc(); + MachineFunction &MF = *MBB.getParent(); + MachineFrameInfo &MFI = *MF.getFrameInfo(); + unsigned Align = MFI.getObjectAlignment(FI); + + MachineMemOperand *MMO = + MF.getMachineMemOperand(PseudoSourceValue::getFixedStack(FI), + MachineMemOperand::MOStore, 0, + MFI.getObjectSize(FI), + Align); + + if (RC == ARM::GPRRegisterClass) { + AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::STR)) + .addReg(SrcReg, getKillRegState(isKill)) + .addFrameIndex(FI).addReg(0).addImm(0).addMemOperand(MMO)); + } else if (RC == ARM::DPRRegisterClass || + RC == ARM::DPR_VFP2RegisterClass || + RC == ARM::DPR_8RegisterClass) { + AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VSTRD)) + .addReg(SrcReg, getKillRegState(isKill)) + .addFrameIndex(FI).addImm(0).addMemOperand(MMO)); + } else if (RC == ARM::SPRRegisterClass) { + AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VSTRS)) + .addReg(SrcReg, getKillRegState(isKill)) + .addFrameIndex(FI).addImm(0).addMemOperand(MMO)); + } else { + assert((RC == ARM::QPRRegisterClass || + RC == ARM::QPR_VFP2RegisterClass) && "Unknown regclass!"); + // FIXME: Neon instructions should support predicates + if (Align >= 16 + && (getRegisterInfo().needsStackRealignment(MF))) { + AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VST1q64)) + .addFrameIndex(FI).addImm(0).addImm(0).addImm(128) + .addMemOperand(MMO) + .addReg(SrcReg, getKillRegState(isKill))); + } else { + AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VSTRQ)). + addReg(SrcReg, getKillRegState(isKill)) + .addFrameIndex(FI).addImm(0).addMemOperand(MMO)); + } + } +} + +void ARMBaseInstrInfo:: +loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, + unsigned DestReg, int FI, + const TargetRegisterClass *RC) const { + DebugLoc DL = DebugLoc::getUnknownLoc(); + if (I != MBB.end()) DL = I->getDebugLoc(); + MachineFunction &MF = *MBB.getParent(); + MachineFrameInfo &MFI = *MF.getFrameInfo(); + unsigned Align = MFI.getObjectAlignment(FI); + + MachineMemOperand *MMO = + MF.getMachineMemOperand(PseudoSourceValue::getFixedStack(FI), + MachineMemOperand::MOLoad, 0, + MFI.getObjectSize(FI), + Align); + + if (RC == ARM::GPRRegisterClass) { + AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::LDR), DestReg) + .addFrameIndex(FI).addReg(0).addImm(0).addMemOperand(MMO)); + } else if (RC == ARM::DPRRegisterClass || + RC == ARM::DPR_VFP2RegisterClass || + RC == ARM::DPR_8RegisterClass) { + AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VLDRD), DestReg) + .addFrameIndex(FI).addImm(0).addMemOperand(MMO)); + } else if (RC == ARM::SPRRegisterClass) { + AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VLDRS), DestReg) + .addFrameIndex(FI).addImm(0).addMemOperand(MMO)); + } else { + assert((RC == ARM::QPRRegisterClass || + RC == ARM::QPR_VFP2RegisterClass || + RC == ARM::QPR_8RegisterClass) && "Unknown regclass!"); + // FIXME: Neon instructions should support predicates + if (Align >= 16 + && (getRegisterInfo().needsStackRealignment(MF))) { + AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VLD1q64), DestReg) + .addFrameIndex(FI).addImm(0).addImm(0).addImm(128) + .addMemOperand(MMO)); + } else { + AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VLDRQ), DestReg) + .addFrameIndex(FI).addImm(0).addMemOperand(MMO)); + } + } +} + +MachineInstr *ARMBaseInstrInfo:: +foldMemoryOperandImpl(MachineFunction &MF, MachineInstr *MI, + const SmallVectorImpl &Ops, int FI) const { + if (Ops.size() != 1) return NULL; + + unsigned OpNum = Ops[0]; + unsigned Opc = MI->getOpcode(); + MachineInstr *NewMI = NULL; + if (Opc == ARM::MOVr || Opc == ARM::t2MOVr) { + // If it is updating CPSR, then it cannot be folded. + if (MI->getOperand(4).getReg() == ARM::CPSR && !MI->getOperand(4).isDead()) + return NULL; + unsigned Pred = MI->getOperand(2).getImm(); + unsigned PredReg = MI->getOperand(3).getReg(); + if (OpNum == 0) { // move -> store + unsigned SrcReg = MI->getOperand(1).getReg(); + unsigned SrcSubReg = MI->getOperand(1).getSubReg(); + bool isKill = MI->getOperand(1).isKill(); + bool isUndef = MI->getOperand(1).isUndef(); + if (Opc == ARM::MOVr) + NewMI = BuildMI(MF, MI->getDebugLoc(), get(ARM::STR)) + .addReg(SrcReg, + getKillRegState(isKill) | getUndefRegState(isUndef), + SrcSubReg) + .addFrameIndex(FI).addReg(0).addImm(0).addImm(Pred).addReg(PredReg); + else // ARM::t2MOVr + NewMI = BuildMI(MF, MI->getDebugLoc(), get(ARM::t2STRi12)) + .addReg(SrcReg, + getKillRegState(isKill) | getUndefRegState(isUndef), + SrcSubReg) + .addFrameIndex(FI).addImm(0).addImm(Pred).addReg(PredReg); + } else { // move -> load + unsigned DstReg = MI->getOperand(0).getReg(); + unsigned DstSubReg = MI->getOperand(0).getSubReg(); + bool isDead = MI->getOperand(0).isDead(); + bool isUndef = MI->getOperand(0).isUndef(); + if (Opc == ARM::MOVr) + NewMI = BuildMI(MF, MI->getDebugLoc(), get(ARM::LDR)) + .addReg(DstReg, + RegState::Define | + getDeadRegState(isDead) | + getUndefRegState(isUndef), DstSubReg) + .addFrameIndex(FI).addReg(0).addImm(0).addImm(Pred).addReg(PredReg); + else // ARM::t2MOVr + NewMI = BuildMI(MF, MI->getDebugLoc(), get(ARM::t2LDRi12)) + .addReg(DstReg, + RegState::Define | + getDeadRegState(isDead) | + getUndefRegState(isUndef), DstSubReg) + .addFrameIndex(FI).addImm(0).addImm(Pred).addReg(PredReg); + } + } else if (Opc == ARM::tMOVgpr2gpr || + Opc == ARM::tMOVtgpr2gpr || + Opc == ARM::tMOVgpr2tgpr) { + if (OpNum == 0) { // move -> store + unsigned SrcReg = MI->getOperand(1).getReg(); + unsigned SrcSubReg = MI->getOperand(1).getSubReg(); + bool isKill = MI->getOperand(1).isKill(); + bool isUndef = MI->getOperand(1).isUndef(); + NewMI = BuildMI(MF, MI->getDebugLoc(), get(ARM::t2STRi12)) + .addReg(SrcReg, + getKillRegState(isKill) | getUndefRegState(isUndef), + SrcSubReg) + .addFrameIndex(FI).addImm(0).addImm(ARMCC::AL).addReg(0); + } else { // move -> load + unsigned DstReg = MI->getOperand(0).getReg(); + unsigned DstSubReg = MI->getOperand(0).getSubReg(); + bool isDead = MI->getOperand(0).isDead(); + bool isUndef = MI->getOperand(0).isUndef(); + NewMI = BuildMI(MF, MI->getDebugLoc(), get(ARM::t2LDRi12)) + .addReg(DstReg, + RegState::Define | + getDeadRegState(isDead) | + getUndefRegState(isUndef), + DstSubReg) + .addFrameIndex(FI).addImm(0).addImm(ARMCC::AL).addReg(0); + } + } else if (Opc == ARM::VMOVS) { + unsigned Pred = MI->getOperand(2).getImm(); + unsigned PredReg = MI->getOperand(3).getReg(); + if (OpNum == 0) { // move -> store + unsigned SrcReg = MI->getOperand(1).getReg(); + unsigned SrcSubReg = MI->getOperand(1).getSubReg(); + bool isKill = MI->getOperand(1).isKill(); + bool isUndef = MI->getOperand(1).isUndef(); + NewMI = BuildMI(MF, MI->getDebugLoc(), get(ARM::VSTRS)) + .addReg(SrcReg, getKillRegState(isKill) | getUndefRegState(isUndef), + SrcSubReg) + .addFrameIndex(FI) + .addImm(0).addImm(Pred).addReg(PredReg); + } else { // move -> load + unsigned DstReg = MI->getOperand(0).getReg(); + unsigned DstSubReg = MI->getOperand(0).getSubReg(); + bool isDead = MI->getOperand(0).isDead(); + bool isUndef = MI->getOperand(0).isUndef(); + NewMI = BuildMI(MF, MI->getDebugLoc(), get(ARM::VLDRS)) + .addReg(DstReg, + RegState::Define | + getDeadRegState(isDead) | + getUndefRegState(isUndef), + DstSubReg) + .addFrameIndex(FI).addImm(0).addImm(Pred).addReg(PredReg); + } + } + else if (Opc == ARM::VMOVD) { + unsigned Pred = MI->getOperand(2).getImm(); + unsigned PredReg = MI->getOperand(3).getReg(); + if (OpNum == 0) { // move -> store + unsigned SrcReg = MI->getOperand(1).getReg(); + unsigned SrcSubReg = MI->getOperand(1).getSubReg(); + bool isKill = MI->getOperand(1).isKill(); + bool isUndef = MI->getOperand(1).isUndef(); + NewMI = BuildMI(MF, MI->getDebugLoc(), get(ARM::VSTRD)) + .addReg(SrcReg, + getKillRegState(isKill) | getUndefRegState(isUndef), + SrcSubReg) + .addFrameIndex(FI).addImm(0).addImm(Pred).addReg(PredReg); + } else { // move -> load + unsigned DstReg = MI->getOperand(0).getReg(); + unsigned DstSubReg = MI->getOperand(0).getSubReg(); + bool isDead = MI->getOperand(0).isDead(); + bool isUndef = MI->getOperand(0).isUndef(); + NewMI = BuildMI(MF, MI->getDebugLoc(), get(ARM::VLDRD)) + .addReg(DstReg, + RegState::Define | + getDeadRegState(isDead) | + getUndefRegState(isUndef), + DstSubReg) + .addFrameIndex(FI).addImm(0).addImm(Pred).addReg(PredReg); + } + } + + return NewMI; +} + +MachineInstr* +ARMBaseInstrInfo::foldMemoryOperandImpl(MachineFunction &MF, + MachineInstr* MI, + const SmallVectorImpl &Ops, + MachineInstr* LoadMI) const { + // FIXME + return 0; +} + +bool +ARMBaseInstrInfo::canFoldMemoryOperand(const MachineInstr *MI, + const SmallVectorImpl &Ops) const { + if (Ops.size() != 1) return false; + + unsigned Opc = MI->getOpcode(); + if (Opc == ARM::MOVr || Opc == ARM::t2MOVr) { + // If it is updating CPSR, then it cannot be folded. + return MI->getOperand(4).getReg() != ARM::CPSR || + MI->getOperand(4).isDead(); + } else if (Opc == ARM::tMOVgpr2gpr || + Opc == ARM::tMOVtgpr2gpr || + Opc == ARM::tMOVgpr2tgpr) { + return true; + } else if (Opc == ARM::VMOVS || Opc == ARM::VMOVD) { + return true; + } else if (Opc == ARM::VMOVDneon || Opc == ARM::VMOVQ) { + return false; // FIXME + } + + return false; +} + +void ARMBaseInstrInfo:: +reMaterialize(MachineBasicBlock &MBB, + MachineBasicBlock::iterator I, + unsigned DestReg, unsigned SubIdx, + const MachineInstr *Orig, + const TargetRegisterInfo *TRI) const { + DebugLoc dl = Orig->getDebugLoc(); + + if (SubIdx && TargetRegisterInfo::isPhysicalRegister(DestReg)) { + DestReg = TRI->getSubReg(DestReg, SubIdx); + SubIdx = 0; + } + + unsigned Opcode = Orig->getOpcode(); + switch (Opcode) { + default: { + MachineInstr *MI = MBB.getParent()->CloneMachineInstr(Orig); + MI->getOperand(0).setReg(DestReg); + MBB.insert(I, MI); + break; + } + case ARM::tLDRpci_pic: + case ARM::t2LDRpci_pic: { + MachineFunction &MF = *MBB.getParent(); + ARMFunctionInfo *AFI = MF.getInfo(); + MachineConstantPool *MCP = MF.getConstantPool(); + unsigned CPI = Orig->getOperand(1).getIndex(); + const MachineConstantPoolEntry &MCPE = MCP->getConstants()[CPI]; + assert(MCPE.isMachineConstantPoolEntry() && + "Expecting a machine constantpool entry!"); + ARMConstantPoolValue *ACPV = + static_cast(MCPE.Val.MachineCPVal); + unsigned PCLabelId = AFI->createConstPoolEntryUId(); + ARMConstantPoolValue *NewCPV = 0; + if (ACPV->isGlobalValue()) + NewCPV = new ARMConstantPoolValue(ACPV->getGV(), PCLabelId, + ARMCP::CPValue, 4); + else if (ACPV->isExtSymbol()) + NewCPV = new ARMConstantPoolValue(MF.getFunction()->getContext(), + ACPV->getSymbol(), PCLabelId, 4); + else if (ACPV->isBlockAddress()) + NewCPV = new ARMConstantPoolValue(ACPV->getBlockAddress(), PCLabelId, + ARMCP::CPBlockAddress, 4); + else + llvm_unreachable("Unexpected ARM constantpool value type!!"); + CPI = MCP->getConstantPoolIndex(NewCPV, MCPE.getAlignment()); + MachineInstrBuilder MIB = BuildMI(MBB, I, Orig->getDebugLoc(), get(Opcode), + DestReg) + .addConstantPoolIndex(CPI).addImm(PCLabelId); + (*MIB).setMemRefs(Orig->memoperands_begin(), Orig->memoperands_end()); + break; + } + } + + MachineInstr *NewMI = prior(I); + NewMI->getOperand(0).setSubReg(SubIdx); +} + +bool ARMBaseInstrInfo::isIdentical(const MachineInstr *MI0, + const MachineInstr *MI1, + const MachineRegisterInfo *MRI) const { + int Opcode = MI0->getOpcode(); + if (Opcode == ARM::t2LDRpci || + Opcode == ARM::t2LDRpci_pic || + Opcode == ARM::tLDRpci || + Opcode == ARM::tLDRpci_pic) { + if (MI1->getOpcode() != Opcode) + return false; + if (MI0->getNumOperands() != MI1->getNumOperands()) + return false; + + const MachineOperand &MO0 = MI0->getOperand(1); + const MachineOperand &MO1 = MI1->getOperand(1); + if (MO0.getOffset() != MO1.getOffset()) + return false; + + const MachineFunction *MF = MI0->getParent()->getParent(); + const MachineConstantPool *MCP = MF->getConstantPool(); + int CPI0 = MO0.getIndex(); + int CPI1 = MO1.getIndex(); + const MachineConstantPoolEntry &MCPE0 = MCP->getConstants()[CPI0]; + const MachineConstantPoolEntry &MCPE1 = MCP->getConstants()[CPI1]; + ARMConstantPoolValue *ACPV0 = + static_cast(MCPE0.Val.MachineCPVal); + ARMConstantPoolValue *ACPV1 = + static_cast(MCPE1.Val.MachineCPVal); + return ACPV0->hasSameValue(ACPV1); + } + + return TargetInstrInfoImpl::isIdentical(MI0, MI1, MRI); +} + +bool ARMBaseInstrInfo::isProfitableToDuplicateIndirectBranch() const { + // If the target processor can predict indirect branches, it is highly + // desirable to duplicate them, since it can often make them predictable. + return getSubtarget().hasBranchTargetBuffer(); +} + +/// getInstrPredicate - If instruction is predicated, returns its predicate +/// condition, otherwise returns AL. It also returns the condition code +/// register by reference. +ARMCC::CondCodes +llvm::getInstrPredicate(const MachineInstr *MI, unsigned &PredReg) { + int PIdx = MI->findFirstPredOperandIdx(); + if (PIdx == -1) { + PredReg = 0; + return ARMCC::AL; + } + + PredReg = MI->getOperand(PIdx+1).getReg(); + return (ARMCC::CondCodes)MI->getOperand(PIdx).getImm(); +} + + +int llvm::getMatchingCondBranchOpcode(int Opc) { + if (Opc == ARM::B) + return ARM::Bcc; + else if (Opc == ARM::tB) + return ARM::tBcc; + else if (Opc == ARM::t2B) + return ARM::t2Bcc; + + llvm_unreachable("Unknown unconditional branch opcode!"); + return 0; +} + + +void llvm::emitARMRegPlusImmediate(MachineBasicBlock &MBB, + MachineBasicBlock::iterator &MBBI, DebugLoc dl, + unsigned DestReg, unsigned BaseReg, int NumBytes, + ARMCC::CondCodes Pred, unsigned PredReg, + const ARMBaseInstrInfo &TII) { + bool isSub = NumBytes < 0; + if (isSub) NumBytes = -NumBytes; + + while (NumBytes) { + unsigned RotAmt = ARM_AM::getSOImmValRotate(NumBytes); + unsigned ThisVal = NumBytes & ARM_AM::rotr32(0xFF, RotAmt); + assert(ThisVal && "Didn't extract field correctly"); + + // We will handle these bits from offset, clear them. + NumBytes &= ~ThisVal; + + assert(ARM_AM::getSOImmVal(ThisVal) != -1 && "Bit extraction didn't work?"); + + // Build the new ADD / SUB. + unsigned Opc = isSub ? ARM::SUBri : ARM::ADDri; + BuildMI(MBB, MBBI, dl, TII.get(Opc), DestReg) + .addReg(BaseReg, RegState::Kill).addImm(ThisVal) + .addImm((unsigned)Pred).addReg(PredReg).addReg(0); + BaseReg = DestReg; + } +} + +bool llvm::rewriteARMFrameIndex(MachineInstr &MI, unsigned FrameRegIdx, + unsigned FrameReg, int &Offset, + const ARMBaseInstrInfo &TII) { + unsigned Opcode = MI.getOpcode(); + const TargetInstrDesc &Desc = MI.getDesc(); + unsigned AddrMode = (Desc.TSFlags & ARMII::AddrModeMask); + bool isSub = false; + + // Memory operands in inline assembly always use AddrMode2. + if (Opcode == ARM::INLINEASM) + AddrMode = ARMII::AddrMode2; + + if (Opcode == ARM::ADDri) { + Offset += MI.getOperand(FrameRegIdx+1).getImm(); + if (Offset == 0) { + // Turn it into a move. + MI.setDesc(TII.get(ARM::MOVr)); + MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false); + MI.RemoveOperand(FrameRegIdx+1); + Offset = 0; + return true; + } else if (Offset < 0) { + Offset = -Offset; + isSub = true; + MI.setDesc(TII.get(ARM::SUBri)); + } + + // Common case: small offset, fits into instruction. + if (ARM_AM::getSOImmVal(Offset) != -1) { + // Replace the FrameIndex with sp / fp + MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false); + MI.getOperand(FrameRegIdx+1).ChangeToImmediate(Offset); + Offset = 0; + return true; + } + + // Otherwise, pull as much of the immedidate into this ADDri/SUBri + // as possible. + unsigned RotAmt = ARM_AM::getSOImmValRotate(Offset); + unsigned ThisImmVal = Offset & ARM_AM::rotr32(0xFF, RotAmt); + + // We will handle these bits from offset, clear them. + Offset &= ~ThisImmVal; + + // Get the properly encoded SOImmVal field. + assert(ARM_AM::getSOImmVal(ThisImmVal) != -1 && + "Bit extraction didn't work?"); + MI.getOperand(FrameRegIdx+1).ChangeToImmediate(ThisImmVal); + } else { + unsigned ImmIdx = 0; + int InstrOffs = 0; + unsigned NumBits = 0; + unsigned Scale = 1; + switch (AddrMode) { + case ARMII::AddrMode2: { + ImmIdx = FrameRegIdx+2; + InstrOffs = ARM_AM::getAM2Offset(MI.getOperand(ImmIdx).getImm()); + if (ARM_AM::getAM2Op(MI.getOperand(ImmIdx).getImm()) == ARM_AM::sub) + InstrOffs *= -1; + NumBits = 12; + break; + } + case ARMII::AddrMode3: { + ImmIdx = FrameRegIdx+2; + InstrOffs = ARM_AM::getAM3Offset(MI.getOperand(ImmIdx).getImm()); + if (ARM_AM::getAM3Op(MI.getOperand(ImmIdx).getImm()) == ARM_AM::sub) + InstrOffs *= -1; + NumBits = 8; + break; + } + case ARMII::AddrMode4: + case ARMII::AddrMode6: + // Can't fold any offset even if it's zero. + return false; + case ARMII::AddrMode5: { + ImmIdx = FrameRegIdx+1; + InstrOffs = ARM_AM::getAM5Offset(MI.getOperand(ImmIdx).getImm()); + if (ARM_AM::getAM5Op(MI.getOperand(ImmIdx).getImm()) == ARM_AM::sub) + InstrOffs *= -1; + NumBits = 8; + Scale = 4; + break; + } + default: + llvm_unreachable("Unsupported addressing mode!"); + break; + } + + Offset += InstrOffs * Scale; + assert((Offset & (Scale-1)) == 0 && "Can't encode this offset!"); + if (Offset < 0) { + Offset = -Offset; + isSub = true; + } + + // Attempt to fold address comp. if opcode has offset bits + if (NumBits > 0) { + // Common case: small offset, fits into instruction. + MachineOperand &ImmOp = MI.getOperand(ImmIdx); + int ImmedOffset = Offset / Scale; + unsigned Mask = (1 << NumBits) - 1; + if ((unsigned)Offset <= Mask * Scale) { + // Replace the FrameIndex with sp + MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false); + if (isSub) + ImmedOffset |= 1 << NumBits; + ImmOp.ChangeToImmediate(ImmedOffset); + Offset = 0; + return true; + } + + // Otherwise, it didn't fit. Pull in what we can to simplify the immed. + ImmedOffset = ImmedOffset & Mask; + if (isSub) + ImmedOffset |= 1 << NumBits; + ImmOp.ChangeToImmediate(ImmedOffset); + Offset &= ~(Mask*Scale); + } + } + + Offset = (isSub) ? -Offset : Offset; + return Offset == 0; +} diff --git a/libclamav/c++/llvm/lib/Target/ARM/ARMBaseInstrInfo.h b/libclamav/c++/llvm/lib/Target/ARM/ARMBaseInstrInfo.h new file mode 100644 index 000000000..7944f354b --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/ARM/ARMBaseInstrInfo.h @@ -0,0 +1,376 @@ +//===- ARMBaseInstrInfo.h - ARM Base Instruction Information ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the Base ARM implementation of the TargetInstrInfo class. +// +//===----------------------------------------------------------------------===// + +#ifndef ARMBASEINSTRUCTIONINFO_H +#define ARMBASEINSTRUCTIONINFO_H + +#include "ARM.h" +#include "ARMRegisterInfo.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/Target/TargetInstrInfo.h" + +namespace llvm { + +/// ARMII - This namespace holds all of the target specific flags that +/// instruction info tracks. +/// +namespace ARMII { + enum { + //===------------------------------------------------------------------===// + // Instruction Flags. + + //===------------------------------------------------------------------===// + // This four-bit field describes the addressing mode used. + + AddrModeMask = 0xf, + AddrModeNone = 0, + AddrMode1 = 1, + AddrMode2 = 2, + AddrMode3 = 3, + AddrMode4 = 4, + AddrMode5 = 5, + AddrMode6 = 6, + AddrModeT1_1 = 7, + AddrModeT1_2 = 8, + AddrModeT1_4 = 9, + AddrModeT1_s = 10, // i8 * 4 for pc and sp relative data + AddrModeT2_i12 = 11, + AddrModeT2_i8 = 12, + AddrModeT2_so = 13, + AddrModeT2_pc = 14, // +/- i12 for pc relative data + AddrModeT2_i8s4 = 15, // i8 * 4 + + // Size* - Flags to keep track of the size of an instruction. + SizeShift = 4, + SizeMask = 7 << SizeShift, + SizeSpecial = 1, // 0 byte pseudo or special case. + Size8Bytes = 2, + Size4Bytes = 3, + Size2Bytes = 4, + + // IndexMode - Unindex, pre-indexed, or post-indexed. Only valid for load + // and store ops + IndexModeShift = 7, + IndexModeMask = 3 << IndexModeShift, + IndexModePre = 1, + IndexModePost = 2, + + //===------------------------------------------------------------------===// + // Instruction encoding formats. + // + FormShift = 9, + FormMask = 0x3f << FormShift, + + // Pseudo instructions + Pseudo = 0 << FormShift, + + // Multiply instructions + MulFrm = 1 << FormShift, + + // Branch instructions + BrFrm = 2 << FormShift, + BrMiscFrm = 3 << FormShift, + + // Data Processing instructions + DPFrm = 4 << FormShift, + DPSoRegFrm = 5 << FormShift, + + // Load and Store + LdFrm = 6 << FormShift, + StFrm = 7 << FormShift, + LdMiscFrm = 8 << FormShift, + StMiscFrm = 9 << FormShift, + LdStMulFrm = 10 << FormShift, + + // Miscellaneous arithmetic instructions + ArithMiscFrm = 11 << FormShift, + + // Extend instructions + ExtFrm = 12 << FormShift, + + // VFP formats + VFPUnaryFrm = 13 << FormShift, + VFPBinaryFrm = 14 << FormShift, + VFPConv1Frm = 15 << FormShift, + VFPConv2Frm = 16 << FormShift, + VFPConv3Frm = 17 << FormShift, + VFPConv4Frm = 18 << FormShift, + VFPConv5Frm = 19 << FormShift, + VFPLdStFrm = 20 << FormShift, + VFPLdStMulFrm = 21 << FormShift, + VFPMiscFrm = 22 << FormShift, + + // Thumb format + ThumbFrm = 23 << FormShift, + + // NEON format + NEONFrm = 24 << FormShift, + NEONGetLnFrm = 25 << FormShift, + NEONSetLnFrm = 26 << FormShift, + NEONDupFrm = 27 << FormShift, + + //===------------------------------------------------------------------===// + // Misc flags. + + // UnaryDP - Indicates this is a unary data processing instruction, i.e. + // it doesn't have a Rn operand. + UnaryDP = 1 << 15, + + // Xform16Bit - Indicates this Thumb2 instruction may be transformed into + // a 16-bit Thumb instruction if certain conditions are met. + Xform16Bit = 1 << 16, + + //===------------------------------------------------------------------===// + // Code domain. + DomainShift = 17, + DomainMask = 3 << DomainShift, + DomainGeneral = 0 << DomainShift, + DomainVFP = 1 << DomainShift, + DomainNEON = 2 << DomainShift, + + //===------------------------------------------------------------------===// + // Field shifts - such shifts are used to set field while generating + // machine instructions. + M_BitShift = 5, + ShiftImmShift = 5, + ShiftShift = 7, + N_BitShift = 7, + ImmHiShift = 8, + SoRotImmShift = 8, + RegRsShift = 8, + ExtRotImmShift = 10, + RegRdLoShift = 12, + RegRdShift = 12, + RegRdHiShift = 16, + RegRnShift = 16, + S_BitShift = 20, + W_BitShift = 21, + AM3_I_BitShift = 22, + D_BitShift = 22, + U_BitShift = 23, + P_BitShift = 24, + I_BitShift = 25, + CondShift = 28 + }; + + /// Target Operand Flag enum. + enum TOF { + //===------------------------------------------------------------------===// + // ARM Specific MachineOperand flags. + + MO_NO_FLAG, + + /// MO_LO16 - On a symbol operand, this represents a relocation containing + /// lower 16 bit of the address. Used only via movw instruction. + MO_LO16, + + /// MO_HI16 - On a symbol operand, this represents a relocation containing + /// higher 16 bit of the address. Used only via movt instruction. + MO_HI16 + }; +} + +class ARMBaseInstrInfo : public TargetInstrInfoImpl { + const ARMSubtarget& Subtarget; +protected: + // Can be only subclassed. + explicit ARMBaseInstrInfo(const ARMSubtarget &STI); +public: + // Return the non-pre/post incrementing version of 'Opc'. Return 0 + // if there is not such an opcode. + virtual unsigned getUnindexedOpcode(unsigned Opc) const =0; + + // Return true if the block does not fall through. + virtual bool BlockHasNoFallThrough(const MachineBasicBlock &MBB) const =0; + + virtual MachineInstr *convertToThreeAddress(MachineFunction::iterator &MFI, + MachineBasicBlock::iterator &MBBI, + LiveVariables *LV) const; + + virtual const ARMBaseRegisterInfo &getRegisterInfo() const =0; + const ARMSubtarget &getSubtarget() const { return Subtarget; } + + // Branch analysis. + virtual bool AnalyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, + MachineBasicBlock *&FBB, + SmallVectorImpl &Cond, + bool AllowModify) const; + virtual unsigned RemoveBranch(MachineBasicBlock &MBB) const; + virtual unsigned InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, + MachineBasicBlock *FBB, + const SmallVectorImpl &Cond) const; + + virtual + bool ReverseBranchCondition(SmallVectorImpl &Cond) const; + + // Predication support. + bool isPredicated(const MachineInstr *MI) const { + int PIdx = MI->findFirstPredOperandIdx(); + return PIdx != -1 && MI->getOperand(PIdx).getImm() != ARMCC::AL; + } + + ARMCC::CondCodes getPredicate(const MachineInstr *MI) const { + int PIdx = MI->findFirstPredOperandIdx(); + return PIdx != -1 ? (ARMCC::CondCodes)MI->getOperand(PIdx).getImm() + : ARMCC::AL; + } + + virtual + bool PredicateInstruction(MachineInstr *MI, + const SmallVectorImpl &Pred) const; + + virtual + bool SubsumesPredicate(const SmallVectorImpl &Pred1, + const SmallVectorImpl &Pred2) const; + + virtual bool DefinesPredicate(MachineInstr *MI, + std::vector &Pred) const; + + virtual bool isPredicable(MachineInstr *MI) const; + + /// GetInstSize - Returns the size of the specified MachineInstr. + /// + virtual unsigned GetInstSizeInBytes(const MachineInstr* MI) const; + + /// Return true if the instruction is a register to register move and return + /// the source and dest operands and their sub-register indices by reference. + virtual bool isMoveInstr(const MachineInstr &MI, + unsigned &SrcReg, unsigned &DstReg, + unsigned &SrcSubIdx, unsigned &DstSubIdx) const; + + virtual unsigned isLoadFromStackSlot(const MachineInstr *MI, + int &FrameIndex) const; + virtual unsigned isStoreToStackSlot(const MachineInstr *MI, + int &FrameIndex) const; + + virtual bool copyRegToReg(MachineBasicBlock &MBB, + MachineBasicBlock::iterator I, + unsigned DestReg, unsigned SrcReg, + const TargetRegisterClass *DestRC, + const TargetRegisterClass *SrcRC) const; + + virtual void storeRegToStackSlot(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MBBI, + unsigned SrcReg, bool isKill, int FrameIndex, + const TargetRegisterClass *RC) const; + + virtual void loadRegFromStackSlot(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MBBI, + unsigned DestReg, int FrameIndex, + const TargetRegisterClass *RC) const; + + virtual bool canFoldMemoryOperand(const MachineInstr *MI, + const SmallVectorImpl &Ops) const; + + virtual MachineInstr* foldMemoryOperandImpl(MachineFunction &MF, + MachineInstr* MI, + const SmallVectorImpl &Ops, + int FrameIndex) const; + + virtual MachineInstr* foldMemoryOperandImpl(MachineFunction &MF, + MachineInstr* MI, + const SmallVectorImpl &Ops, + MachineInstr* LoadMI) const; + + virtual void reMaterialize(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + unsigned DestReg, unsigned SubIdx, + const MachineInstr *Orig, + const TargetRegisterInfo *TRI) const; + + virtual bool isIdentical(const MachineInstr *MI, const MachineInstr *Other, + const MachineRegisterInfo *MRI) const; + + virtual bool isProfitableToDuplicateIndirectBranch() const; +}; + +static inline +const MachineInstrBuilder &AddDefaultPred(const MachineInstrBuilder &MIB) { + return MIB.addImm((int64_t)ARMCC::AL).addReg(0); +} + +static inline +const MachineInstrBuilder &AddDefaultCC(const MachineInstrBuilder &MIB) { + return MIB.addReg(0); +} + +static inline +const MachineInstrBuilder &AddDefaultT1CC(const MachineInstrBuilder &MIB, + bool isDead = false) { + return MIB.addReg(ARM::CPSR, getDefRegState(true) | getDeadRegState(isDead)); +} + +static inline +const MachineInstrBuilder &AddNoT1CC(const MachineInstrBuilder &MIB) { + return MIB.addReg(0); +} + +static inline +bool isUncondBranchOpcode(int Opc) { + return Opc == ARM::B || Opc == ARM::tB || Opc == ARM::t2B; +} + +static inline +bool isCondBranchOpcode(int Opc) { + return Opc == ARM::Bcc || Opc == ARM::tBcc || Opc == ARM::t2Bcc; +} + +static inline +bool isJumpTableBranchOpcode(int Opc) { + return Opc == ARM::BR_JTr || Opc == ARM::BR_JTm || Opc == ARM::BR_JTadd || + Opc == ARM::tBR_JTr || Opc == ARM::t2BR_JT; +} + +static inline +bool isIndirectBranchOpcode(int Opc) { + return Opc == ARM::BRIND || Opc == ARM::tBRIND; +} + +/// getInstrPredicate - If instruction is predicated, returns its predicate +/// condition, otherwise returns AL. It also returns the condition code +/// register by reference. +ARMCC::CondCodes getInstrPredicate(const MachineInstr *MI, unsigned &PredReg); + +int getMatchingCondBranchOpcode(int Opc); + +/// emitARMRegPlusImmediate / emitT2RegPlusImmediate - Emits a series of +/// instructions to materializea destreg = basereg + immediate in ARM / Thumb2 +/// code. +void emitARMRegPlusImmediate(MachineBasicBlock &MBB, + MachineBasicBlock::iterator &MBBI, DebugLoc dl, + unsigned DestReg, unsigned BaseReg, int NumBytes, + ARMCC::CondCodes Pred, unsigned PredReg, + const ARMBaseInstrInfo &TII); + +void emitT2RegPlusImmediate(MachineBasicBlock &MBB, + MachineBasicBlock::iterator &MBBI, DebugLoc dl, + unsigned DestReg, unsigned BaseReg, int NumBytes, + ARMCC::CondCodes Pred, unsigned PredReg, + const ARMBaseInstrInfo &TII); + + +/// rewriteARMFrameIndex / rewriteT2FrameIndex - +/// Rewrite MI to access 'Offset' bytes from the FP. Return false if the +/// offset could not be handled directly in MI, and return the left-over +/// portion by reference. +bool rewriteARMFrameIndex(MachineInstr &MI, unsigned FrameRegIdx, + unsigned FrameReg, int &Offset, + const ARMBaseInstrInfo &TII); + +bool rewriteT2FrameIndex(MachineInstr &MI, unsigned FrameRegIdx, + unsigned FrameReg, int &Offset, + const ARMBaseInstrInfo &TII); + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/lib/Target/ARM/ARMBaseRegisterInfo.cpp b/libclamav/c++/llvm/lib/Target/ARM/ARMBaseRegisterInfo.cpp new file mode 100644 index 000000000..653328d8d --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/ARM/ARMBaseRegisterInfo.cpp @@ -0,0 +1,1526 @@ +//===- ARMBaseRegisterInfo.cpp - ARM Register Information -------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the base ARM implementation of TargetRegisterInfo class. +// +//===----------------------------------------------------------------------===// + +#include "ARM.h" +#include "ARMAddressingModes.h" +#include "ARMBaseInstrInfo.h" +#include "ARMBaseRegisterInfo.h" +#include "ARMInstrInfo.h" +#include "ARMMachineFunctionInfo.h" +#include "ARMSubtarget.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Function.h" +#include "llvm/LLVMContext.h" +#include "llvm/CodeGen/MachineConstantPool.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineLocation.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/RegisterScavenging.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Target/TargetFrameInfo.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetOptions.h" +#include "llvm/ADT/BitVector.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/CommandLine.h" +using namespace llvm; + +static cl::opt +ReuseFrameIndexVals("arm-reuse-frame-index-vals", cl::Hidden, cl::init(true), + cl::desc("Reuse repeated frame index values")); + +unsigned ARMBaseRegisterInfo::getRegisterNumbering(unsigned RegEnum, + bool *isSPVFP) { + if (isSPVFP) + *isSPVFP = false; + + using namespace ARM; + switch (RegEnum) { + default: + llvm_unreachable("Unknown ARM register!"); + case R0: case D0: case Q0: return 0; + case R1: case D1: case Q1: return 1; + case R2: case D2: case Q2: return 2; + case R3: case D3: case Q3: return 3; + case R4: case D4: case Q4: return 4; + case R5: case D5: case Q5: return 5; + case R6: case D6: case Q6: return 6; + case R7: case D7: case Q7: return 7; + case R8: case D8: case Q8: return 8; + case R9: case D9: case Q9: return 9; + case R10: case D10: case Q10: return 10; + case R11: case D11: case Q11: return 11; + case R12: case D12: case Q12: return 12; + case SP: case D13: case Q13: return 13; + case LR: case D14: case Q14: return 14; + case PC: case D15: case Q15: return 15; + + case D16: return 16; + case D17: return 17; + case D18: return 18; + case D19: return 19; + case D20: return 20; + case D21: return 21; + case D22: return 22; + case D23: return 23; + case D24: return 24; + case D25: return 25; + case D26: return 27; + case D27: return 27; + case D28: return 28; + case D29: return 29; + case D30: return 30; + case D31: return 31; + + case S0: case S1: case S2: case S3: + case S4: case S5: case S6: case S7: + case S8: case S9: case S10: case S11: + case S12: case S13: case S14: case S15: + case S16: case S17: case S18: case S19: + case S20: case S21: case S22: case S23: + case S24: case S25: case S26: case S27: + case S28: case S29: case S30: case S31: { + if (isSPVFP) + *isSPVFP = true; + switch (RegEnum) { + default: return 0; // Avoid compile time warning. + case S0: return 0; + case S1: return 1; + case S2: return 2; + case S3: return 3; + case S4: return 4; + case S5: return 5; + case S6: return 6; + case S7: return 7; + case S8: return 8; + case S9: return 9; + case S10: return 10; + case S11: return 11; + case S12: return 12; + case S13: return 13; + case S14: return 14; + case S15: return 15; + case S16: return 16; + case S17: return 17; + case S18: return 18; + case S19: return 19; + case S20: return 20; + case S21: return 21; + case S22: return 22; + case S23: return 23; + case S24: return 24; + case S25: return 25; + case S26: return 26; + case S27: return 27; + case S28: return 28; + case S29: return 29; + case S30: return 30; + case S31: return 31; + } + } + } +} + +ARMBaseRegisterInfo::ARMBaseRegisterInfo(const ARMBaseInstrInfo &tii, + const ARMSubtarget &sti) + : ARMGenRegisterInfo(ARM::ADJCALLSTACKDOWN, ARM::ADJCALLSTACKUP), + TII(tii), STI(sti), + FramePtr((STI.isTargetDarwin() || STI.isThumb()) ? ARM::R7 : ARM::R11) { +} + +const unsigned* +ARMBaseRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const { + static const unsigned CalleeSavedRegs[] = { + ARM::LR, ARM::R11, ARM::R10, ARM::R9, ARM::R8, + ARM::R7, ARM::R6, ARM::R5, ARM::R4, + + ARM::D15, ARM::D14, ARM::D13, ARM::D12, + ARM::D11, ARM::D10, ARM::D9, ARM::D8, + 0 + }; + + static const unsigned DarwinCalleeSavedRegs[] = { + // Darwin ABI deviates from ARM standard ABI. R9 is not a callee-saved + // register. + ARM::LR, ARM::R7, ARM::R6, ARM::R5, ARM::R4, + ARM::R11, ARM::R10, ARM::R8, + + ARM::D15, ARM::D14, ARM::D13, ARM::D12, + ARM::D11, ARM::D10, ARM::D9, ARM::D8, + 0 + }; + return STI.isTargetDarwin() ? DarwinCalleeSavedRegs : CalleeSavedRegs; +} + +const TargetRegisterClass* const * +ARMBaseRegisterInfo::getCalleeSavedRegClasses(const MachineFunction *MF) const { + static const TargetRegisterClass * const CalleeSavedRegClasses[] = { + &ARM::GPRRegClass, &ARM::GPRRegClass, &ARM::GPRRegClass, + &ARM::GPRRegClass, &ARM::GPRRegClass, &ARM::GPRRegClass, + &ARM::GPRRegClass, &ARM::GPRRegClass, &ARM::GPRRegClass, + + &ARM::DPRRegClass, &ARM::DPRRegClass, &ARM::DPRRegClass, &ARM::DPRRegClass, + &ARM::DPRRegClass, &ARM::DPRRegClass, &ARM::DPRRegClass, &ARM::DPRRegClass, + 0 + }; + + static const TargetRegisterClass * const ThumbCalleeSavedRegClasses[] = { + &ARM::GPRRegClass, &ARM::GPRRegClass, &ARM::GPRRegClass, + &ARM::GPRRegClass, &ARM::GPRRegClass, &ARM::tGPRRegClass, + &ARM::tGPRRegClass,&ARM::tGPRRegClass,&ARM::tGPRRegClass, + + &ARM::DPRRegClass, &ARM::DPRRegClass, &ARM::DPRRegClass, &ARM::DPRRegClass, + &ARM::DPRRegClass, &ARM::DPRRegClass, &ARM::DPRRegClass, &ARM::DPRRegClass, + 0 + }; + + static const TargetRegisterClass * const DarwinCalleeSavedRegClasses[] = { + &ARM::GPRRegClass, &ARM::GPRRegClass, &ARM::GPRRegClass, + &ARM::GPRRegClass, &ARM::GPRRegClass, &ARM::GPRRegClass, + &ARM::GPRRegClass, &ARM::GPRRegClass, + + &ARM::DPRRegClass, &ARM::DPRRegClass, &ARM::DPRRegClass, &ARM::DPRRegClass, + &ARM::DPRRegClass, &ARM::DPRRegClass, &ARM::DPRRegClass, &ARM::DPRRegClass, + 0 + }; + + static const TargetRegisterClass * const DarwinThumbCalleeSavedRegClasses[] ={ + &ARM::GPRRegClass, &ARM::tGPRRegClass, &ARM::tGPRRegClass, + &ARM::tGPRRegClass, &ARM::tGPRRegClass, &ARM::GPRRegClass, + &ARM::GPRRegClass, &ARM::GPRRegClass, + + &ARM::DPRRegClass, &ARM::DPRRegClass, &ARM::DPRRegClass, &ARM::DPRRegClass, + &ARM::DPRRegClass, &ARM::DPRRegClass, &ARM::DPRRegClass, &ARM::DPRRegClass, + 0 + }; + + if (STI.isThumb1Only()) { + return STI.isTargetDarwin() + ? DarwinThumbCalleeSavedRegClasses : ThumbCalleeSavedRegClasses; + } + return STI.isTargetDarwin() + ? DarwinCalleeSavedRegClasses : CalleeSavedRegClasses; +} + +BitVector ARMBaseRegisterInfo::getReservedRegs(const MachineFunction &MF) const { + // FIXME: avoid re-calculating this everytime. + BitVector Reserved(getNumRegs()); + Reserved.set(ARM::SP); + Reserved.set(ARM::PC); + if (STI.isTargetDarwin() || hasFP(MF)) + Reserved.set(FramePtr); + // Some targets reserve R9. + if (STI.isR9Reserved()) + Reserved.set(ARM::R9); + return Reserved; +} + +bool ARMBaseRegisterInfo::isReservedReg(const MachineFunction &MF, + unsigned Reg) const { + switch (Reg) { + default: break; + case ARM::SP: + case ARM::PC: + return true; + case ARM::R7: + case ARM::R11: + if (FramePtr == Reg && (STI.isTargetDarwin() || hasFP(MF))) + return true; + break; + case ARM::R9: + return STI.isR9Reserved(); + } + + return false; +} + +const TargetRegisterClass * +ARMBaseRegisterInfo::getMatchingSuperRegClass(const TargetRegisterClass *A, + const TargetRegisterClass *B, + unsigned SubIdx) const { + switch (SubIdx) { + default: return 0; + case 1: + case 2: + case 3: + case 4: + // S sub-registers. + if (A->getSize() == 8) { + if (B == &ARM::SPR_8RegClass) + return &ARM::DPR_8RegClass; + assert(B == &ARM::SPRRegClass && "Expecting SPR register class!"); + if (A == &ARM::DPR_8RegClass) + return A; + return &ARM::DPR_VFP2RegClass; + } + + assert(A->getSize() == 16 && "Expecting a Q register class!"); + if (B == &ARM::SPR_8RegClass) + return &ARM::QPR_8RegClass; + return &ARM::QPR_VFP2RegClass; + case 5: + case 6: + // D sub-registers. + if (B == &ARM::DPR_VFP2RegClass) + return &ARM::QPR_VFP2RegClass; + if (B == &ARM::DPR_8RegClass) + return &ARM::QPR_8RegClass; + return A; + } + return 0; +} + +const TargetRegisterClass * +ARMBaseRegisterInfo::getPointerRegClass(unsigned Kind) const { + return ARM::GPRRegisterClass; +} + +/// getAllocationOrder - Returns the register allocation order for a specified +/// register class in the form of a pair of TargetRegisterClass iterators. +std::pair +ARMBaseRegisterInfo::getAllocationOrder(const TargetRegisterClass *RC, + unsigned HintType, unsigned HintReg, + const MachineFunction &MF) const { + // Alternative register allocation orders when favoring even / odd registers + // of register pairs. + + // No FP, R9 is available. + static const unsigned GPREven1[] = { + ARM::R0, ARM::R2, ARM::R4, ARM::R6, ARM::R8, ARM::R10, + ARM::R1, ARM::R3, ARM::R12,ARM::LR, ARM::R5, ARM::R7, + ARM::R9, ARM::R11 + }; + static const unsigned GPROdd1[] = { + ARM::R1, ARM::R3, ARM::R5, ARM::R7, ARM::R9, ARM::R11, + ARM::R0, ARM::R2, ARM::R12,ARM::LR, ARM::R4, ARM::R6, + ARM::R8, ARM::R10 + }; + + // FP is R7, R9 is available. + static const unsigned GPREven2[] = { + ARM::R0, ARM::R2, ARM::R4, ARM::R8, ARM::R10, + ARM::R1, ARM::R3, ARM::R12,ARM::LR, ARM::R5, ARM::R6, + ARM::R9, ARM::R11 + }; + static const unsigned GPROdd2[] = { + ARM::R1, ARM::R3, ARM::R5, ARM::R9, ARM::R11, + ARM::R0, ARM::R2, ARM::R12,ARM::LR, ARM::R4, ARM::R6, + ARM::R8, ARM::R10 + }; + + // FP is R11, R9 is available. + static const unsigned GPREven3[] = { + ARM::R0, ARM::R2, ARM::R4, ARM::R6, ARM::R8, + ARM::R1, ARM::R3, ARM::R10,ARM::R12,ARM::LR, ARM::R5, ARM::R7, + ARM::R9 + }; + static const unsigned GPROdd3[] = { + ARM::R1, ARM::R3, ARM::R5, ARM::R6, ARM::R9, + ARM::R0, ARM::R2, ARM::R10,ARM::R12,ARM::LR, ARM::R4, ARM::R7, + ARM::R8 + }; + + // No FP, R9 is not available. + static const unsigned GPREven4[] = { + ARM::R0, ARM::R2, ARM::R4, ARM::R6, ARM::R10, + ARM::R1, ARM::R3, ARM::R12,ARM::LR, ARM::R5, ARM::R7, ARM::R8, + ARM::R11 + }; + static const unsigned GPROdd4[] = { + ARM::R1, ARM::R3, ARM::R5, ARM::R7, ARM::R11, + ARM::R0, ARM::R2, ARM::R12,ARM::LR, ARM::R4, ARM::R6, ARM::R8, + ARM::R10 + }; + + // FP is R7, R9 is not available. + static const unsigned GPREven5[] = { + ARM::R0, ARM::R2, ARM::R4, ARM::R10, + ARM::R1, ARM::R3, ARM::R12,ARM::LR, ARM::R5, ARM::R6, ARM::R8, + ARM::R11 + }; + static const unsigned GPROdd5[] = { + ARM::R1, ARM::R3, ARM::R5, ARM::R11, + ARM::R0, ARM::R2, ARM::R12,ARM::LR, ARM::R4, ARM::R6, ARM::R8, + ARM::R10 + }; + + // FP is R11, R9 is not available. + static const unsigned GPREven6[] = { + ARM::R0, ARM::R2, ARM::R4, ARM::R6, + ARM::R1, ARM::R3, ARM::R10,ARM::R12,ARM::LR, ARM::R5, ARM::R7, ARM::R8 + }; + static const unsigned GPROdd6[] = { + ARM::R1, ARM::R3, ARM::R5, ARM::R7, + ARM::R0, ARM::R2, ARM::R10,ARM::R12,ARM::LR, ARM::R4, ARM::R6, ARM::R8 + }; + + + if (HintType == ARMRI::RegPairEven) { + if (isPhysicalRegister(HintReg) && getRegisterPairEven(HintReg, MF) == 0) + // It's no longer possible to fulfill this hint. Return the default + // allocation order. + return std::make_pair(RC->allocation_order_begin(MF), + RC->allocation_order_end(MF)); + + if (!STI.isTargetDarwin() && !hasFP(MF)) { + if (!STI.isR9Reserved()) + return std::make_pair(GPREven1, + GPREven1 + (sizeof(GPREven1)/sizeof(unsigned))); + else + return std::make_pair(GPREven4, + GPREven4 + (sizeof(GPREven4)/sizeof(unsigned))); + } else if (FramePtr == ARM::R7) { + if (!STI.isR9Reserved()) + return std::make_pair(GPREven2, + GPREven2 + (sizeof(GPREven2)/sizeof(unsigned))); + else + return std::make_pair(GPREven5, + GPREven5 + (sizeof(GPREven5)/sizeof(unsigned))); + } else { // FramePtr == ARM::R11 + if (!STI.isR9Reserved()) + return std::make_pair(GPREven3, + GPREven3 + (sizeof(GPREven3)/sizeof(unsigned))); + else + return std::make_pair(GPREven6, + GPREven6 + (sizeof(GPREven6)/sizeof(unsigned))); + } + } else if (HintType == ARMRI::RegPairOdd) { + if (isPhysicalRegister(HintReg) && getRegisterPairOdd(HintReg, MF) == 0) + // It's no longer possible to fulfill this hint. Return the default + // allocation order. + return std::make_pair(RC->allocation_order_begin(MF), + RC->allocation_order_end(MF)); + + if (!STI.isTargetDarwin() && !hasFP(MF)) { + if (!STI.isR9Reserved()) + return std::make_pair(GPROdd1, + GPROdd1 + (sizeof(GPROdd1)/sizeof(unsigned))); + else + return std::make_pair(GPROdd4, + GPROdd4 + (sizeof(GPROdd4)/sizeof(unsigned))); + } else if (FramePtr == ARM::R7) { + if (!STI.isR9Reserved()) + return std::make_pair(GPROdd2, + GPROdd2 + (sizeof(GPROdd2)/sizeof(unsigned))); + else + return std::make_pair(GPROdd5, + GPROdd5 + (sizeof(GPROdd5)/sizeof(unsigned))); + } else { // FramePtr == ARM::R11 + if (!STI.isR9Reserved()) + return std::make_pair(GPROdd3, + GPROdd3 + (sizeof(GPROdd3)/sizeof(unsigned))); + else + return std::make_pair(GPROdd6, + GPROdd6 + (sizeof(GPROdd6)/sizeof(unsigned))); + } + } + return std::make_pair(RC->allocation_order_begin(MF), + RC->allocation_order_end(MF)); +} + +/// ResolveRegAllocHint - Resolves the specified register allocation hint +/// to a physical register. Returns the physical register if it is successful. +unsigned +ARMBaseRegisterInfo::ResolveRegAllocHint(unsigned Type, unsigned Reg, + const MachineFunction &MF) const { + if (Reg == 0 || !isPhysicalRegister(Reg)) + return 0; + if (Type == 0) + return Reg; + else if (Type == (unsigned)ARMRI::RegPairOdd) + // Odd register. + return getRegisterPairOdd(Reg, MF); + else if (Type == (unsigned)ARMRI::RegPairEven) + // Even register. + return getRegisterPairEven(Reg, MF); + return 0; +} + +void +ARMBaseRegisterInfo::UpdateRegAllocHint(unsigned Reg, unsigned NewReg, + MachineFunction &MF) const { + MachineRegisterInfo *MRI = &MF.getRegInfo(); + std::pair Hint = MRI->getRegAllocationHint(Reg); + if ((Hint.first == (unsigned)ARMRI::RegPairOdd || + Hint.first == (unsigned)ARMRI::RegPairEven) && + Hint.second && TargetRegisterInfo::isVirtualRegister(Hint.second)) { + // If 'Reg' is one of the even / odd register pair and it's now changed + // (e.g. coalesced) into a different register. The other register of the + // pair allocation hint must be updated to reflect the relationship + // change. + unsigned OtherReg = Hint.second; + Hint = MRI->getRegAllocationHint(OtherReg); + if (Hint.second == Reg) + // Make sure the pair has not already divorced. + MRI->setRegAllocationHint(OtherReg, Hint.first, NewReg); + } +} + +static unsigned calculateMaxStackAlignment(const MachineFrameInfo *FFI) { + unsigned MaxAlign = 0; + + for (int i = FFI->getObjectIndexBegin(), + e = FFI->getObjectIndexEnd(); i != e; ++i) { + if (FFI->isDeadObjectIndex(i)) + continue; + + unsigned Align = FFI->getObjectAlignment(i); + MaxAlign = std::max(MaxAlign, Align); + } + + return MaxAlign; +} + +/// hasFP - Return true if the specified function should have a dedicated frame +/// pointer register. This is true if the function has variable sized allocas +/// or if frame pointer elimination is disabled. +/// +bool ARMBaseRegisterInfo::hasFP(const MachineFunction &MF) const { + const MachineFrameInfo *MFI = MF.getFrameInfo(); + return (NoFramePointerElim || + needsStackRealignment(MF) || + MFI->hasVarSizedObjects() || + MFI->isFrameAddressTaken()); +} + +bool ARMBaseRegisterInfo:: +needsStackRealignment(const MachineFunction &MF) const { + const MachineFrameInfo *MFI = MF.getFrameInfo(); + const ARMFunctionInfo *AFI = MF.getInfo(); + unsigned StackAlign = MF.getTarget().getFrameInfo()->getStackAlignment(); + return (RealignStack && + !AFI->isThumb1OnlyFunction() && + (MFI->getMaxAlignment() > StackAlign) && + !MFI->hasVarSizedObjects()); +} + +bool ARMBaseRegisterInfo::cannotEliminateFrame(const MachineFunction &MF) const { + const MachineFrameInfo *MFI = MF.getFrameInfo(); + if (NoFramePointerElim && MFI->hasCalls()) + return true; + return MFI->hasVarSizedObjects() || MFI->isFrameAddressTaken() + || needsStackRealignment(MF); +} + +/// estimateStackSize - Estimate and return the size of the frame. +static unsigned estimateStackSize(MachineFunction &MF, MachineFrameInfo *MFI) { + const MachineFrameInfo *FFI = MF.getFrameInfo(); + int Offset = 0; + for (int i = FFI->getObjectIndexBegin(); i != 0; ++i) { + int FixedOff = -FFI->getObjectOffset(i); + if (FixedOff > Offset) Offset = FixedOff; + } + for (unsigned i = 0, e = FFI->getObjectIndexEnd(); i != e; ++i) { + if (FFI->isDeadObjectIndex(i)) + continue; + Offset += FFI->getObjectSize(i); + unsigned Align = FFI->getObjectAlignment(i); + // Adjust to alignment boundary + Offset = (Offset+Align-1)/Align*Align; + } + return (unsigned)Offset; +} + +/// estimateRSStackSizeLimit - Look at each instruction that references stack +/// frames and return the stack size limit beyond which some of these +/// instructions will require scratch register during their expansion later. +unsigned +ARMBaseRegisterInfo::estimateRSStackSizeLimit(MachineFunction &MF) const { + unsigned Limit = (1 << 12) - 1; + for (MachineFunction::iterator BB = MF.begin(),E = MF.end(); BB != E; ++BB) { + for (MachineBasicBlock::iterator I = BB->begin(), E = BB->end(); + I != E; ++I) { + for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i) { + if (!I->getOperand(i).isFI()) continue; + + const TargetInstrDesc &Desc = TII.get(I->getOpcode()); + unsigned AddrMode = (Desc.TSFlags & ARMII::AddrModeMask); + if (AddrMode == ARMII::AddrMode3 || + AddrMode == ARMII::AddrModeT2_i8) + return (1 << 8) - 1; + + if (AddrMode == ARMII::AddrMode5 || + AddrMode == ARMII::AddrModeT2_i8s4) + Limit = std::min(Limit, ((1U << 8) - 1) * 4); + + if (AddrMode == ARMII::AddrModeT2_i12 && hasFP(MF)) + // When the stack offset is negative, we will end up using + // the i8 instructions instead. + return (1 << 8) - 1; + break; // At most one FI per instruction + } + } + } + + return Limit; +} + +void +ARMBaseRegisterInfo::processFunctionBeforeCalleeSavedScan(MachineFunction &MF, + RegScavenger *RS) const { + // This tells PEI to spill the FP as if it is any other callee-save register + // to take advantage the eliminateFrameIndex machinery. This also ensures it + // is spilled in the order specified by getCalleeSavedRegs() to make it easier + // to combine multiple loads / stores. + bool CanEliminateFrame = true; + bool CS1Spilled = false; + bool LRSpilled = false; + unsigned NumGPRSpills = 0; + SmallVector UnspilledCS1GPRs; + SmallVector UnspilledCS2GPRs; + ARMFunctionInfo *AFI = MF.getInfo(); + + MachineFrameInfo *MFI = MF.getFrameInfo(); + + // Calculate and set max stack object alignment early, so we can decide + // whether we will need stack realignment (and thus FP). + if (RealignStack) { + unsigned MaxAlign = std::max(MFI->getMaxAlignment(), + calculateMaxStackAlignment(MFI)); + MFI->setMaxAlignment(MaxAlign); + } + + // Don't spill FP if the frame can be eliminated. This is determined + // by scanning the callee-save registers to see if any is used. + const unsigned *CSRegs = getCalleeSavedRegs(); + const TargetRegisterClass* const *CSRegClasses = getCalleeSavedRegClasses(); + for (unsigned i = 0; CSRegs[i]; ++i) { + unsigned Reg = CSRegs[i]; + bool Spilled = false; + if (MF.getRegInfo().isPhysRegUsed(Reg)) { + AFI->setCSRegisterIsSpilled(Reg); + Spilled = true; + CanEliminateFrame = false; + } else { + // Check alias registers too. + for (const unsigned *Aliases = getAliasSet(Reg); *Aliases; ++Aliases) { + if (MF.getRegInfo().isPhysRegUsed(*Aliases)) { + Spilled = true; + CanEliminateFrame = false; + } + } + } + + if (CSRegClasses[i] == ARM::GPRRegisterClass || + CSRegClasses[i] == ARM::tGPRRegisterClass) { + if (Spilled) { + NumGPRSpills++; + + if (!STI.isTargetDarwin()) { + if (Reg == ARM::LR) + LRSpilled = true; + CS1Spilled = true; + continue; + } + + // Keep track if LR and any of R4, R5, R6, and R7 is spilled. + switch (Reg) { + case ARM::LR: + LRSpilled = true; + // Fallthrough + case ARM::R4: + case ARM::R5: + case ARM::R6: + case ARM::R7: + CS1Spilled = true; + break; + default: + break; + } + } else { + if (!STI.isTargetDarwin()) { + UnspilledCS1GPRs.push_back(Reg); + continue; + } + + switch (Reg) { + case ARM::R4: + case ARM::R5: + case ARM::R6: + case ARM::R7: + case ARM::LR: + UnspilledCS1GPRs.push_back(Reg); + break; + default: + UnspilledCS2GPRs.push_back(Reg); + break; + } + } + } + } + + bool ForceLRSpill = false; + if (!LRSpilled && AFI->isThumb1OnlyFunction()) { + unsigned FnSize = TII.GetFunctionSizeInBytes(MF); + // Force LR to be spilled if the Thumb function size is > 2048. This enables + // use of BL to implement far jump. If it turns out that it's not needed + // then the branch fix up path will undo it. + if (FnSize >= (1 << 11)) { + CanEliminateFrame = false; + ForceLRSpill = true; + } + } + + bool ExtraCSSpill = false; + if (!CanEliminateFrame || cannotEliminateFrame(MF)) { + AFI->setHasStackFrame(true); + + // If LR is not spilled, but at least one of R4, R5, R6, and R7 is spilled. + // Spill LR as well so we can fold BX_RET to the registers restore (LDM). + if (!LRSpilled && CS1Spilled) { + MF.getRegInfo().setPhysRegUsed(ARM::LR); + AFI->setCSRegisterIsSpilled(ARM::LR); + NumGPRSpills++; + UnspilledCS1GPRs.erase(std::find(UnspilledCS1GPRs.begin(), + UnspilledCS1GPRs.end(), (unsigned)ARM::LR)); + ForceLRSpill = false; + ExtraCSSpill = true; + } + + // Darwin ABI requires FP to point to the stack slot that contains the + // previous FP. + if (STI.isTargetDarwin() || hasFP(MF)) { + MF.getRegInfo().setPhysRegUsed(FramePtr); + NumGPRSpills++; + } + + // If stack and double are 8-byte aligned and we are spilling an odd number + // of GPRs. Spill one extra callee save GPR so we won't have to pad between + // the integer and double callee save areas. + unsigned TargetAlign = MF.getTarget().getFrameInfo()->getStackAlignment(); + if (TargetAlign == 8 && (NumGPRSpills & 1)) { + if (CS1Spilled && !UnspilledCS1GPRs.empty()) { + for (unsigned i = 0, e = UnspilledCS1GPRs.size(); i != e; ++i) { + unsigned Reg = UnspilledCS1GPRs[i]; + // Don't spill high register if the function is thumb1 + if (!AFI->isThumb1OnlyFunction() || + isARMLowRegister(Reg) || Reg == ARM::LR) { + MF.getRegInfo().setPhysRegUsed(Reg); + AFI->setCSRegisterIsSpilled(Reg); + if (!isReservedReg(MF, Reg)) + ExtraCSSpill = true; + break; + } + } + } else if (!UnspilledCS2GPRs.empty() && + !AFI->isThumb1OnlyFunction()) { + unsigned Reg = UnspilledCS2GPRs.front(); + MF.getRegInfo().setPhysRegUsed(Reg); + AFI->setCSRegisterIsSpilled(Reg); + if (!isReservedReg(MF, Reg)) + ExtraCSSpill = true; + } + } + + // Estimate if we might need to scavenge a register at some point in order + // to materialize a stack offset. If so, either spill one additional + // callee-saved register or reserve a special spill slot to facilitate + // register scavenging. Thumb1 needs a spill slot for stack pointer + // adjustments also, even when the frame itself is small. + if (RS && !ExtraCSSpill) { + MachineFrameInfo *MFI = MF.getFrameInfo(); + // If any of the stack slot references may be out of range of an + // immediate offset, make sure a register (or a spill slot) is + // available for the register scavenger. Note that if we're indexing + // off the frame pointer, the effective stack size is 4 bytes larger + // since the FP points to the stack slot of the previous FP. + if (estimateStackSize(MF, MFI) + (hasFP(MF) ? 4 : 0) + >= estimateRSStackSizeLimit(MF)) { + // If any non-reserved CS register isn't spilled, just spill one or two + // extra. That should take care of it! + unsigned NumExtras = TargetAlign / 4; + SmallVector Extras; + while (NumExtras && !UnspilledCS1GPRs.empty()) { + unsigned Reg = UnspilledCS1GPRs.back(); + UnspilledCS1GPRs.pop_back(); + if (!isReservedReg(MF, Reg)) { + Extras.push_back(Reg); + NumExtras--; + } + } + // For non-Thumb1 functions, also check for hi-reg CS registers + if (!AFI->isThumb1OnlyFunction()) { + while (NumExtras && !UnspilledCS2GPRs.empty()) { + unsigned Reg = UnspilledCS2GPRs.back(); + UnspilledCS2GPRs.pop_back(); + if (!isReservedReg(MF, Reg)) { + Extras.push_back(Reg); + NumExtras--; + } + } + } + if (Extras.size() && NumExtras == 0) { + for (unsigned i = 0, e = Extras.size(); i != e; ++i) { + MF.getRegInfo().setPhysRegUsed(Extras[i]); + AFI->setCSRegisterIsSpilled(Extras[i]); + } + } else if (!AFI->isThumb1OnlyFunction()) { + // note: Thumb1 functions spill to R12, not the stack. + // Reserve a slot closest to SP or frame pointer. + const TargetRegisterClass *RC = ARM::GPRRegisterClass; + RS->setScavengingFrameIndex(MFI->CreateStackObject(RC->getSize(), + RC->getAlignment(), + false)); + } + } + } + } + + if (ForceLRSpill) { + MF.getRegInfo().setPhysRegUsed(ARM::LR); + AFI->setCSRegisterIsSpilled(ARM::LR); + AFI->setLRIsSpilledForFarJump(true); + } +} + +unsigned ARMBaseRegisterInfo::getRARegister() const { + return ARM::LR; +} + +unsigned +ARMBaseRegisterInfo::getFrameRegister(const MachineFunction &MF) const { + if (STI.isTargetDarwin() || hasFP(MF)) + return FramePtr; + return ARM::SP; +} + +int +ARMBaseRegisterInfo::getFrameIndexReference(MachineFunction &MF, int FI, + unsigned &FrameReg) const { + const MachineFrameInfo *MFI = MF.getFrameInfo(); + ARMFunctionInfo *AFI = MF.getInfo(); + int Offset = MFI->getObjectOffset(FI) + MFI->getStackSize(); + bool isFixed = MFI->isFixedObjectIndex(FI); + + FrameReg = ARM::SP; + if (AFI->isGPRCalleeSavedArea1Frame(FI)) + Offset -= AFI->getGPRCalleeSavedArea1Offset(); + else if (AFI->isGPRCalleeSavedArea2Frame(FI)) + Offset -= AFI->getGPRCalleeSavedArea2Offset(); + else if (AFI->isDPRCalleeSavedAreaFrame(FI)) + Offset -= AFI->getDPRCalleeSavedAreaOffset(); + else if (needsStackRealignment(MF)) { + // When dynamically realigning the stack, use the frame pointer for + // parameters, and the stack pointer for locals. + assert (hasFP(MF) && "dynamic stack realignment without a FP!"); + if (isFixed) { + FrameReg = getFrameRegister(MF); + Offset -= AFI->getFramePtrSpillOffset(); + } + } else if (hasFP(MF) && AFI->hasStackFrame()) { + if (isFixed || MFI->hasVarSizedObjects()) { + // Use frame pointer to reference fixed objects unless this is a + // frameless function. + FrameReg = getFrameRegister(MF); + Offset -= AFI->getFramePtrSpillOffset(); + } else if (AFI->isThumb2Function()) { + // In Thumb2 mode, the negative offset is very limited. + int FPOffset = Offset - AFI->getFramePtrSpillOffset(); + if (FPOffset >= -255 && FPOffset < 0) { + FrameReg = getFrameRegister(MF); + Offset = FPOffset; + } + } + } + return Offset; +} + + +int +ARMBaseRegisterInfo::getFrameIndexOffset(MachineFunction &MF, int FI) const { + unsigned FrameReg; + return getFrameIndexReference(MF, FI, FrameReg); +} + +unsigned ARMBaseRegisterInfo::getEHExceptionRegister() const { + llvm_unreachable("What is the exception register"); + return 0; +} + +unsigned ARMBaseRegisterInfo::getEHHandlerRegister() const { + llvm_unreachable("What is the exception handler register"); + return 0; +} + +int ARMBaseRegisterInfo::getDwarfRegNum(unsigned RegNum, bool isEH) const { + return ARMGenRegisterInfo::getDwarfRegNumFull(RegNum, 0); +} + +unsigned ARMBaseRegisterInfo::getRegisterPairEven(unsigned Reg, + const MachineFunction &MF) const { + switch (Reg) { + default: break; + // Return 0 if either register of the pair is a special register. + // So no R12, etc. + case ARM::R1: + return ARM::R0; + case ARM::R3: + return ARM::R2; + case ARM::R5: + return ARM::R4; + case ARM::R7: + return isReservedReg(MF, ARM::R7) ? 0 : ARM::R6; + case ARM::R9: + return isReservedReg(MF, ARM::R9) ? 0 :ARM::R8; + case ARM::R11: + return isReservedReg(MF, ARM::R11) ? 0 : ARM::R10; + + case ARM::S1: + return ARM::S0; + case ARM::S3: + return ARM::S2; + case ARM::S5: + return ARM::S4; + case ARM::S7: + return ARM::S6; + case ARM::S9: + return ARM::S8; + case ARM::S11: + return ARM::S10; + case ARM::S13: + return ARM::S12; + case ARM::S15: + return ARM::S14; + case ARM::S17: + return ARM::S16; + case ARM::S19: + return ARM::S18; + case ARM::S21: + return ARM::S20; + case ARM::S23: + return ARM::S22; + case ARM::S25: + return ARM::S24; + case ARM::S27: + return ARM::S26; + case ARM::S29: + return ARM::S28; + case ARM::S31: + return ARM::S30; + + case ARM::D1: + return ARM::D0; + case ARM::D3: + return ARM::D2; + case ARM::D5: + return ARM::D4; + case ARM::D7: + return ARM::D6; + case ARM::D9: + return ARM::D8; + case ARM::D11: + return ARM::D10; + case ARM::D13: + return ARM::D12; + case ARM::D15: + return ARM::D14; + case ARM::D17: + return ARM::D16; + case ARM::D19: + return ARM::D18; + case ARM::D21: + return ARM::D20; + case ARM::D23: + return ARM::D22; + case ARM::D25: + return ARM::D24; + case ARM::D27: + return ARM::D26; + case ARM::D29: + return ARM::D28; + case ARM::D31: + return ARM::D30; + } + + return 0; +} + +unsigned ARMBaseRegisterInfo::getRegisterPairOdd(unsigned Reg, + const MachineFunction &MF) const { + switch (Reg) { + default: break; + // Return 0 if either register of the pair is a special register. + // So no R12, etc. + case ARM::R0: + return ARM::R1; + case ARM::R2: + return ARM::R3; + case ARM::R4: + return ARM::R5; + case ARM::R6: + return isReservedReg(MF, ARM::R7) ? 0 : ARM::R7; + case ARM::R8: + return isReservedReg(MF, ARM::R9) ? 0 :ARM::R9; + case ARM::R10: + return isReservedReg(MF, ARM::R11) ? 0 : ARM::R11; + + case ARM::S0: + return ARM::S1; + case ARM::S2: + return ARM::S3; + case ARM::S4: + return ARM::S5; + case ARM::S6: + return ARM::S7; + case ARM::S8: + return ARM::S9; + case ARM::S10: + return ARM::S11; + case ARM::S12: + return ARM::S13; + case ARM::S14: + return ARM::S15; + case ARM::S16: + return ARM::S17; + case ARM::S18: + return ARM::S19; + case ARM::S20: + return ARM::S21; + case ARM::S22: + return ARM::S23; + case ARM::S24: + return ARM::S25; + case ARM::S26: + return ARM::S27; + case ARM::S28: + return ARM::S29; + case ARM::S30: + return ARM::S31; + + case ARM::D0: + return ARM::D1; + case ARM::D2: + return ARM::D3; + case ARM::D4: + return ARM::D5; + case ARM::D6: + return ARM::D7; + case ARM::D8: + return ARM::D9; + case ARM::D10: + return ARM::D11; + case ARM::D12: + return ARM::D13; + case ARM::D14: + return ARM::D15; + case ARM::D16: + return ARM::D17; + case ARM::D18: + return ARM::D19; + case ARM::D20: + return ARM::D21; + case ARM::D22: + return ARM::D23; + case ARM::D24: + return ARM::D25; + case ARM::D26: + return ARM::D27; + case ARM::D28: + return ARM::D29; + case ARM::D30: + return ARM::D31; + } + + return 0; +} + +/// emitLoadConstPool - Emits a load from constpool to materialize the +/// specified immediate. +void ARMBaseRegisterInfo:: +emitLoadConstPool(MachineBasicBlock &MBB, + MachineBasicBlock::iterator &MBBI, + DebugLoc dl, + unsigned DestReg, unsigned SubIdx, int Val, + ARMCC::CondCodes Pred, + unsigned PredReg) const { + MachineFunction &MF = *MBB.getParent(); + MachineConstantPool *ConstantPool = MF.getConstantPool(); + Constant *C = + ConstantInt::get(Type::getInt32Ty(MF.getFunction()->getContext()), Val); + unsigned Idx = ConstantPool->getConstantPoolIndex(C, 4); + + BuildMI(MBB, MBBI, dl, TII.get(ARM::LDRcp)) + .addReg(DestReg, getDefRegState(true), SubIdx) + .addConstantPoolIndex(Idx) + .addReg(0).addImm(0).addImm(Pred).addReg(PredReg); +} + +bool ARMBaseRegisterInfo:: +requiresRegisterScavenging(const MachineFunction &MF) const { + return true; +} + +bool ARMBaseRegisterInfo:: +requiresFrameIndexScavenging(const MachineFunction &MF) const { + return true; +} + +// hasReservedCallFrame - Under normal circumstances, when a frame pointer is +// not required, we reserve argument space for call sites in the function +// immediately on entry to the current function. This eliminates the need for +// add/sub sp brackets around call sites. Returns true if the call frame is +// included as part of the stack frame. +bool ARMBaseRegisterInfo:: +hasReservedCallFrame(MachineFunction &MF) const { + const MachineFrameInfo *FFI = MF.getFrameInfo(); + unsigned CFSize = FFI->getMaxCallFrameSize(); + // It's not always a good idea to include the call frame as part of the + // stack frame. ARM (especially Thumb) has small immediate offset to + // address the stack frame. So a large call frame can cause poor codegen + // and may even makes it impossible to scavenge a register. + if (CFSize >= ((1 << 12) - 1) / 2) // Half of imm12 + return false; + + return !MF.getFrameInfo()->hasVarSizedObjects(); +} + +static void +emitSPUpdate(bool isARM, + MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI, + DebugLoc dl, const ARMBaseInstrInfo &TII, + int NumBytes, + ARMCC::CondCodes Pred = ARMCC::AL, unsigned PredReg = 0) { + if (isARM) + emitARMRegPlusImmediate(MBB, MBBI, dl, ARM::SP, ARM::SP, NumBytes, + Pred, PredReg, TII); + else + emitT2RegPlusImmediate(MBB, MBBI, dl, ARM::SP, ARM::SP, NumBytes, + Pred, PredReg, TII); +} + + +void ARMBaseRegisterInfo:: +eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, + MachineBasicBlock::iterator I) const { + if (!hasReservedCallFrame(MF)) { + // If we have alloca, convert as follows: + // ADJCALLSTACKDOWN -> sub, sp, sp, amount + // ADJCALLSTACKUP -> add, sp, sp, amount + MachineInstr *Old = I; + DebugLoc dl = Old->getDebugLoc(); + unsigned Amount = Old->getOperand(0).getImm(); + if (Amount != 0) { + // We need to keep the stack aligned properly. To do this, we round the + // amount of space needed for the outgoing arguments up to the next + // alignment boundary. + unsigned Align = MF.getTarget().getFrameInfo()->getStackAlignment(); + Amount = (Amount+Align-1)/Align*Align; + + ARMFunctionInfo *AFI = MF.getInfo(); + assert(!AFI->isThumb1OnlyFunction() && + "This eliminateCallFramePseudoInstr does not suppor Thumb1!"); + bool isARM = !AFI->isThumbFunction(); + + // Replace the pseudo instruction with a new instruction... + unsigned Opc = Old->getOpcode(); + ARMCC::CondCodes Pred = (ARMCC::CondCodes)Old->getOperand(1).getImm(); + // FIXME: Thumb2 version of ADJCALLSTACKUP and ADJCALLSTACKDOWN? + if (Opc == ARM::ADJCALLSTACKDOWN || Opc == ARM::tADJCALLSTACKDOWN) { + // Note: PredReg is operand 2 for ADJCALLSTACKDOWN. + unsigned PredReg = Old->getOperand(2).getReg(); + emitSPUpdate(isARM, MBB, I, dl, TII, -Amount, Pred, PredReg); + } else { + // Note: PredReg is operand 3 for ADJCALLSTACKUP. + unsigned PredReg = Old->getOperand(3).getReg(); + assert(Opc == ARM::ADJCALLSTACKUP || Opc == ARM::tADJCALLSTACKUP); + emitSPUpdate(isARM, MBB, I, dl, TII, Amount, Pred, PredReg); + } + } + } + MBB.erase(I); +} + +unsigned +ARMBaseRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, + int SPAdj, int *Value, + RegScavenger *RS) const { + unsigned i = 0; + MachineInstr &MI = *II; + MachineBasicBlock &MBB = *MI.getParent(); + MachineFunction &MF = *MBB.getParent(); + const MachineFrameInfo *MFI = MF.getFrameInfo(); + ARMFunctionInfo *AFI = MF.getInfo(); + assert(!AFI->isThumb1OnlyFunction() && + "This eliminateFrameIndex does not support Thumb1!"); + + while (!MI.getOperand(i).isFI()) { + ++i; + assert(i < MI.getNumOperands() && "Instr doesn't have FrameIndex operand!"); + } + + int FrameIndex = MI.getOperand(i).getIndex(); + int Offset = MFI->getObjectOffset(FrameIndex) + MFI->getStackSize() + SPAdj; + unsigned FrameReg; + + Offset = getFrameIndexReference(MF, FrameIndex, FrameReg); + if (FrameReg != ARM::SP) + SPAdj = 0; + + // Modify MI as necessary to handle as much of 'Offset' as possible + bool Done = false; + if (!AFI->isThumbFunction()) + Done = rewriteARMFrameIndex(MI, i, FrameReg, Offset, TII); + else { + assert(AFI->isThumb2Function()); + Done = rewriteT2FrameIndex(MI, i, FrameReg, Offset, TII); + } + if (Done) + return 0; + + // If we get here, the immediate doesn't fit into the instruction. We folded + // as much as possible above, handle the rest, providing a register that is + // SP+LargeImm. + assert((Offset || + (MI.getDesc().TSFlags & ARMII::AddrModeMask) == ARMII::AddrMode4 || + (MI.getDesc().TSFlags & ARMII::AddrModeMask) == ARMII::AddrMode6) && + "This code isn't needed if offset already handled!"); + + unsigned ScratchReg = 0; + int PIdx = MI.findFirstPredOperandIdx(); + ARMCC::CondCodes Pred = (PIdx == -1) + ? ARMCC::AL : (ARMCC::CondCodes)MI.getOperand(PIdx).getImm(); + unsigned PredReg = (PIdx == -1) ? 0 : MI.getOperand(PIdx+1).getReg(); + if (Offset == 0) + // Must be addrmode4/6. + MI.getOperand(i).ChangeToRegister(FrameReg, false, false, false); + else { + ScratchReg = MF.getRegInfo().createVirtualRegister(ARM::GPRRegisterClass); + if (Value) *Value = Offset; + if (!AFI->isThumbFunction()) + emitARMRegPlusImmediate(MBB, II, MI.getDebugLoc(), ScratchReg, FrameReg, + Offset, Pred, PredReg, TII); + else { + assert(AFI->isThumb2Function()); + emitT2RegPlusImmediate(MBB, II, MI.getDebugLoc(), ScratchReg, FrameReg, + Offset, Pred, PredReg, TII); + } + MI.getOperand(i).ChangeToRegister(ScratchReg, false, false, true); + if (!ReuseFrameIndexVals) + ScratchReg = 0; + } + return ScratchReg; +} + +/// Move iterator past the next bunch of callee save load / store ops for +/// the particular spill area (1: integer area 1, 2: integer area 2, +/// 3: fp area, 0: don't care). +static void movePastCSLoadStoreOps(MachineBasicBlock &MBB, + MachineBasicBlock::iterator &MBBI, + int Opc1, int Opc2, unsigned Area, + const ARMSubtarget &STI) { + while (MBBI != MBB.end() && + ((MBBI->getOpcode() == Opc1) || (MBBI->getOpcode() == Opc2)) && + MBBI->getOperand(1).isFI()) { + if (Area != 0) { + bool Done = false; + unsigned Category = 0; + switch (MBBI->getOperand(0).getReg()) { + case ARM::R4: case ARM::R5: case ARM::R6: case ARM::R7: + case ARM::LR: + Category = 1; + break; + case ARM::R8: case ARM::R9: case ARM::R10: case ARM::R11: + Category = STI.isTargetDarwin() ? 2 : 1; + break; + case ARM::D8: case ARM::D9: case ARM::D10: case ARM::D11: + case ARM::D12: case ARM::D13: case ARM::D14: case ARM::D15: + Category = 3; + break; + default: + Done = true; + break; + } + if (Done || Category != Area) + break; + } + + ++MBBI; + } +} + +void ARMBaseRegisterInfo:: +emitPrologue(MachineFunction &MF) const { + MachineBasicBlock &MBB = MF.front(); + MachineBasicBlock::iterator MBBI = MBB.begin(); + MachineFrameInfo *MFI = MF.getFrameInfo(); + ARMFunctionInfo *AFI = MF.getInfo(); + assert(!AFI->isThumb1OnlyFunction() && + "This emitPrologue does not suppor Thumb1!"); + bool isARM = !AFI->isThumbFunction(); + unsigned VARegSaveSize = AFI->getVarArgsRegSaveSize(); + unsigned NumBytes = MFI->getStackSize(); + const std::vector &CSI = MFI->getCalleeSavedInfo(); + DebugLoc dl = (MBBI != MBB.end() ? + MBBI->getDebugLoc() : DebugLoc::getUnknownLoc()); + + // Determine the sizes of each callee-save spill areas and record which frame + // belongs to which callee-save spill areas. + unsigned GPRCS1Size = 0, GPRCS2Size = 0, DPRCSSize = 0; + int FramePtrSpillFI = 0; + + // Allocate the vararg register save area. This is not counted in NumBytes. + if (VARegSaveSize) + emitSPUpdate(isARM, MBB, MBBI, dl, TII, -VARegSaveSize); + + if (!AFI->hasStackFrame()) { + if (NumBytes != 0) + emitSPUpdate(isARM, MBB, MBBI, dl, TII, -NumBytes); + return; + } + + for (unsigned i = 0, e = CSI.size(); i != e; ++i) { + unsigned Reg = CSI[i].getReg(); + int FI = CSI[i].getFrameIdx(); + switch (Reg) { + case ARM::R4: + case ARM::R5: + case ARM::R6: + case ARM::R7: + case ARM::LR: + if (Reg == FramePtr) + FramePtrSpillFI = FI; + AFI->addGPRCalleeSavedArea1Frame(FI); + GPRCS1Size += 4; + break; + case ARM::R8: + case ARM::R9: + case ARM::R10: + case ARM::R11: + if (Reg == FramePtr) + FramePtrSpillFI = FI; + if (STI.isTargetDarwin()) { + AFI->addGPRCalleeSavedArea2Frame(FI); + GPRCS2Size += 4; + } else { + AFI->addGPRCalleeSavedArea1Frame(FI); + GPRCS1Size += 4; + } + break; + default: + AFI->addDPRCalleeSavedAreaFrame(FI); + DPRCSSize += 8; + } + } + + // Build the new SUBri to adjust SP for integer callee-save spill area 1. + emitSPUpdate(isARM, MBB, MBBI, dl, TII, -GPRCS1Size); + movePastCSLoadStoreOps(MBB, MBBI, ARM::STR, ARM::t2STRi12, 1, STI); + + // Set FP to point to the stack slot that contains the previous FP. + // For Darwin, FP is R7, which has now been stored in spill area 1. + // Otherwise, if this is not Darwin, all the callee-saved registers go + // into spill area 1, including the FP in R11. In either case, it is + // now safe to emit this assignment. + if (STI.isTargetDarwin() || hasFP(MF)) { + unsigned ADDriOpc = !AFI->isThumbFunction() ? ARM::ADDri : ARM::t2ADDri; + MachineInstrBuilder MIB = + BuildMI(MBB, MBBI, dl, TII.get(ADDriOpc), FramePtr) + .addFrameIndex(FramePtrSpillFI).addImm(0); + AddDefaultCC(AddDefaultPred(MIB)); + } + + // Build the new SUBri to adjust SP for integer callee-save spill area 2. + emitSPUpdate(isARM, MBB, MBBI, dl, TII, -GPRCS2Size); + + // Build the new SUBri to adjust SP for FP callee-save spill area. + movePastCSLoadStoreOps(MBB, MBBI, ARM::STR, ARM::t2STRi12, 2, STI); + emitSPUpdate(isARM, MBB, MBBI, dl, TII, -DPRCSSize); + + // Determine starting offsets of spill areas. + unsigned DPRCSOffset = NumBytes - (GPRCS1Size + GPRCS2Size + DPRCSSize); + unsigned GPRCS2Offset = DPRCSOffset + DPRCSSize; + unsigned GPRCS1Offset = GPRCS2Offset + GPRCS2Size; + AFI->setFramePtrSpillOffset(MFI->getObjectOffset(FramePtrSpillFI) + NumBytes); + AFI->setGPRCalleeSavedArea1Offset(GPRCS1Offset); + AFI->setGPRCalleeSavedArea2Offset(GPRCS2Offset); + AFI->setDPRCalleeSavedAreaOffset(DPRCSOffset); + + movePastCSLoadStoreOps(MBB, MBBI, ARM::VSTRD, 0, 3, STI); + NumBytes = DPRCSOffset; + if (NumBytes) { + // Adjust SP after all the callee-save spills. + emitSPUpdate(isARM, MBB, MBBI, dl, TII, -NumBytes); + } + + if (STI.isTargetELF() && hasFP(MF)) { + MFI->setOffsetAdjustment(MFI->getOffsetAdjustment() - + AFI->getFramePtrSpillOffset()); + } + + AFI->setGPRCalleeSavedArea1Size(GPRCS1Size); + AFI->setGPRCalleeSavedArea2Size(GPRCS2Size); + AFI->setDPRCalleeSavedAreaSize(DPRCSSize); + + // If we need dynamic stack realignment, do it here. + if (needsStackRealignment(MF)) { + unsigned Opc; + unsigned MaxAlign = MFI->getMaxAlignment(); + assert (!AFI->isThumb1OnlyFunction()); + Opc = AFI->isThumbFunction() ? ARM::t2BICri : ARM::BICri; + + AddDefaultCC(AddDefaultPred(BuildMI(MBB, MBBI, dl, TII.get(Opc), ARM::SP) + .addReg(ARM::SP, RegState::Kill) + .addImm(MaxAlign-1))); + } +} + +static bool isCalleeSavedRegister(unsigned Reg, const unsigned *CSRegs) { + for (unsigned i = 0; CSRegs[i]; ++i) + if (Reg == CSRegs[i]) + return true; + return false; +} + +static bool isCSRestore(MachineInstr *MI, + const ARMBaseInstrInfo &TII, + const unsigned *CSRegs) { + return ((MI->getOpcode() == (int)ARM::VLDRD || + MI->getOpcode() == (int)ARM::LDR || + MI->getOpcode() == (int)ARM::t2LDRi12) && + MI->getOperand(1).isFI() && + isCalleeSavedRegister(MI->getOperand(0).getReg(), CSRegs)); +} + +void ARMBaseRegisterInfo:: +emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const { + MachineBasicBlock::iterator MBBI = prior(MBB.end()); + assert(MBBI->getDesc().isReturn() && + "Can only insert epilog into returning blocks"); + DebugLoc dl = MBBI->getDebugLoc(); + MachineFrameInfo *MFI = MF.getFrameInfo(); + ARMFunctionInfo *AFI = MF.getInfo(); + assert(!AFI->isThumb1OnlyFunction() && + "This emitEpilogue does not suppor Thumb1!"); + bool isARM = !AFI->isThumbFunction(); + + unsigned VARegSaveSize = AFI->getVarArgsRegSaveSize(); + int NumBytes = (int)MFI->getStackSize(); + + if (!AFI->hasStackFrame()) { + if (NumBytes != 0) + emitSPUpdate(isARM, MBB, MBBI, dl, TII, NumBytes); + } else { + // Unwind MBBI to point to first LDR / VLDRD. + const unsigned *CSRegs = getCalleeSavedRegs(); + if (MBBI != MBB.begin()) { + do + --MBBI; + while (MBBI != MBB.begin() && isCSRestore(MBBI, TII, CSRegs)); + if (!isCSRestore(MBBI, TII, CSRegs)) + ++MBBI; + } + + // Move SP to start of FP callee save spill area. + NumBytes -= (AFI->getGPRCalleeSavedArea1Size() + + AFI->getGPRCalleeSavedArea2Size() + + AFI->getDPRCalleeSavedAreaSize()); + + // Darwin ABI requires FP to point to the stack slot that contains the + // previous FP. + bool HasFP = hasFP(MF); + if ((STI.isTargetDarwin() && NumBytes) || HasFP) { + NumBytes = AFI->getFramePtrSpillOffset() - NumBytes; + // Reset SP based on frame pointer only if the stack frame extends beyond + // frame pointer stack slot or target is ELF and the function has FP. + if (HasFP || + AFI->getGPRCalleeSavedArea2Size() || + AFI->getDPRCalleeSavedAreaSize() || + AFI->getDPRCalleeSavedAreaOffset()) { + if (NumBytes) { + if (isARM) + emitARMRegPlusImmediate(MBB, MBBI, dl, ARM::SP, FramePtr, -NumBytes, + ARMCC::AL, 0, TII); + else + emitT2RegPlusImmediate(MBB, MBBI, dl, ARM::SP, FramePtr, -NumBytes, + ARMCC::AL, 0, TII); + } else { + // Thumb2 or ARM. + if (isARM) + BuildMI(MBB, MBBI, dl, TII.get(ARM::MOVr), ARM::SP) + .addReg(FramePtr) + .addImm((unsigned)ARMCC::AL).addReg(0).addReg(0); + else + BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVgpr2gpr), ARM::SP) + .addReg(FramePtr); + } + } + } else if (NumBytes) + emitSPUpdate(isARM, MBB, MBBI, dl, TII, NumBytes); + + // Move SP to start of integer callee save spill area 2. + movePastCSLoadStoreOps(MBB, MBBI, ARM::VLDRD, 0, 3, STI); + emitSPUpdate(isARM, MBB, MBBI, dl, TII, AFI->getDPRCalleeSavedAreaSize()); + + // Move SP to start of integer callee save spill area 1. + movePastCSLoadStoreOps(MBB, MBBI, ARM::LDR, ARM::t2LDRi12, 2, STI); + emitSPUpdate(isARM, MBB, MBBI, dl, TII, AFI->getGPRCalleeSavedArea2Size()); + + // Move SP to SP upon entry to the function. + movePastCSLoadStoreOps(MBB, MBBI, ARM::LDR, ARM::t2LDRi12, 1, STI); + emitSPUpdate(isARM, MBB, MBBI, dl, TII, AFI->getGPRCalleeSavedArea1Size()); + } + + if (VARegSaveSize) + emitSPUpdate(isARM, MBB, MBBI, dl, TII, VARegSaveSize); +} + +namespace { + struct MaximalStackAlignmentCalculator : public MachineFunctionPass { + static char ID; + MaximalStackAlignmentCalculator() : MachineFunctionPass(&ID) {} + + virtual bool runOnMachineFunction(MachineFunction &MF) { + MachineFrameInfo *FFI = MF.getFrameInfo(); + MachineRegisterInfo &RI = MF.getRegInfo(); + + // Calculate max stack alignment of all already allocated stack objects. + unsigned MaxAlign = calculateMaxStackAlignment(FFI); + + // Be over-conservative: scan over all vreg defs and find, whether vector + // registers are used. If yes - there is probability, that vector register + // will be spilled and thus stack needs to be aligned properly. + for (unsigned RegNum = TargetRegisterInfo::FirstVirtualRegister; + RegNum < RI.getLastVirtReg(); ++RegNum) + MaxAlign = std::max(MaxAlign, RI.getRegClass(RegNum)->getAlignment()); + + if (FFI->getMaxAlignment() == MaxAlign) + return false; + + FFI->setMaxAlignment(MaxAlign); + return true; + } + + virtual const char *getPassName() const { + return "ARM Stack Required Alignment Auto-Detector"; + } + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesCFG(); + MachineFunctionPass::getAnalysisUsage(AU); + } + }; + + char MaximalStackAlignmentCalculator::ID = 0; +} + +FunctionPass* +llvm::createARMMaxStackAlignmentCalculatorPass() { + return new MaximalStackAlignmentCalculator(); +} + +#include "ARMGenRegisterInfo.inc" diff --git a/libclamav/c++/llvm/lib/Target/ARM/ARMBaseRegisterInfo.h b/libclamav/c++/llvm/lib/Target/ARM/ARMBaseRegisterInfo.h new file mode 100644 index 000000000..2788d0733 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/ARM/ARMBaseRegisterInfo.h @@ -0,0 +1,162 @@ +//===- ARMBaseRegisterInfo.h - ARM Register Information Impl ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the base ARM implementation of TargetRegisterInfo class. +// +//===----------------------------------------------------------------------===// + +#ifndef ARMBASEREGISTERINFO_H +#define ARMBASEREGISTERINFO_H + +#include "ARM.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "ARMGenRegisterInfo.h.inc" + +namespace llvm { + class ARMSubtarget; + class ARMBaseInstrInfo; + class Type; + +/// Register allocation hints. +namespace ARMRI { + enum { + RegPairOdd = 1, + RegPairEven = 2 + }; +} + +/// isARMLowRegister - Returns true if the register is low register r0-r7. +/// +static inline bool isARMLowRegister(unsigned Reg) { + using namespace ARM; + switch (Reg) { + case R0: case R1: case R2: case R3: + case R4: case R5: case R6: case R7: + return true; + default: + return false; + } +} + +struct ARMBaseRegisterInfo : public ARMGenRegisterInfo { +protected: + const ARMBaseInstrInfo &TII; + const ARMSubtarget &STI; + + /// FramePtr - ARM physical register used as frame ptr. + unsigned FramePtr; + + // Can be only subclassed. + explicit ARMBaseRegisterInfo(const ARMBaseInstrInfo &tii, + const ARMSubtarget &STI); + + // Return the opcode that implements 'Op', or 0 if no opcode + unsigned getOpcode(int Op) const; + +public: + /// getRegisterNumbering - Given the enum value for some register, e.g. + /// ARM::LR, return the number that it corresponds to (e.g. 14). It + /// also returns true in isSPVFP if the register is a single precision + /// VFP register. + static unsigned getRegisterNumbering(unsigned RegEnum, bool *isSPVFP = 0); + + /// Code Generation virtual methods... + const unsigned *getCalleeSavedRegs(const MachineFunction *MF = 0) const; + + const TargetRegisterClass* const* + getCalleeSavedRegClasses(const MachineFunction *MF = 0) const; + + BitVector getReservedRegs(const MachineFunction &MF) const; + + /// getMatchingSuperRegClass - Return a subclass of the specified register + /// class A so that each register in it has a sub-register of the + /// specified sub-register index which is in the specified register class B. + virtual const TargetRegisterClass * + getMatchingSuperRegClass(const TargetRegisterClass *A, + const TargetRegisterClass *B, unsigned Idx) const; + + const TargetRegisterClass *getPointerRegClass(unsigned Kind = 0) const; + + std::pair + getAllocationOrder(const TargetRegisterClass *RC, + unsigned HintType, unsigned HintReg, + const MachineFunction &MF) const; + + unsigned ResolveRegAllocHint(unsigned Type, unsigned Reg, + const MachineFunction &MF) const; + + void UpdateRegAllocHint(unsigned Reg, unsigned NewReg, + MachineFunction &MF) const; + + bool hasFP(const MachineFunction &MF) const; + + bool needsStackRealignment(const MachineFunction &MF) const; + + bool cannotEliminateFrame(const MachineFunction &MF) const; + + void processFunctionBeforeCalleeSavedScan(MachineFunction &MF, + RegScavenger *RS = NULL) const; + + // Debug information queries. + unsigned getRARegister() const; + unsigned getFrameRegister(const MachineFunction &MF) const; + int getFrameIndexReference(MachineFunction &MF, int FI, + unsigned &FrameReg) const; + int getFrameIndexOffset(MachineFunction &MF, int FI) const; + + // Exception handling queries. + unsigned getEHExceptionRegister() const; + unsigned getEHHandlerRegister() const; + + int getDwarfRegNum(unsigned RegNum, bool isEH) const; + + bool isLowRegister(unsigned Reg) const; + + + /// emitLoadConstPool - Emits a load from constpool to materialize the + /// specified immediate. + virtual void emitLoadConstPool(MachineBasicBlock &MBB, + MachineBasicBlock::iterator &MBBI, + DebugLoc dl, + unsigned DestReg, unsigned SubIdx, + int Val, + ARMCC::CondCodes Pred = ARMCC::AL, + unsigned PredReg = 0) const; + + /// Code Generation virtual methods... + virtual bool isReservedReg(const MachineFunction &MF, unsigned Reg) const; + + virtual bool requiresRegisterScavenging(const MachineFunction &MF) const; + + virtual bool requiresFrameIndexScavenging(const MachineFunction &MF) const; + + virtual bool hasReservedCallFrame(MachineFunction &MF) const; + + virtual void eliminateCallFramePseudoInstr(MachineFunction &MF, + MachineBasicBlock &MBB, + MachineBasicBlock::iterator I) const; + + virtual unsigned eliminateFrameIndex(MachineBasicBlock::iterator II, + int SPAdj, int *Value = NULL, + RegScavenger *RS = NULL) const; + + virtual void emitPrologue(MachineFunction &MF) const; + virtual void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const; + +private: + unsigned estimateRSStackSizeLimit(MachineFunction &MF) const; + + unsigned getRegisterPairEven(unsigned Reg, const MachineFunction &MF) const; + + unsigned getRegisterPairOdd(unsigned Reg, const MachineFunction &MF) const; +}; + +} // end namespace llvm + +#endif diff --git a/libclamav/c++/llvm/lib/Target/ARM/ARMBuildAttrs.h b/libclamav/c++/llvm/lib/Target/ARM/ARMBuildAttrs.h new file mode 100644 index 000000000..3b38375fb --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/ARM/ARMBuildAttrs.h @@ -0,0 +1,64 @@ +//===-------- ARMBuildAttrs.h - ARM Build Attributes ------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains enumerations and support routines for ARM build attributes +// as defined in ARM ABI addenda document (ABI release 2.07). +// +//===----------------------------------------------------------------------===// + +#ifndef __TARGET_ARMBUILDATTRS_H__ +#define __TARGET_ARMBUILDATTRS_H__ + +namespace ARMBuildAttrs { + enum { + File = 1, + Section = 2, + Symbol = 3, + CPU_raw_name = 4, + CPU_name = 5, + CPU_arch = 6, + CPU_arch_profile = 7, + ARM_ISA_use = 8, + THUMB_ISA_use = 9, + VFP_arch = 10, + WMMX_arch = 11, + Advanced_SIMD_arch = 12, + PCS_config = 13, + ABI_PCS_R9_use = 14, + ABI_PCS_RW_data = 15, + ABI_PCS_RO_data = 16, + ABI_PCS_GOT_use = 17, + ABI_PCS_wchar_t = 18, + ABI_FP_rounding = 19, + ABI_FP_denormal = 20, + ABI_FP_exceptions = 21, + ABI_FP_user_exceptions = 22, + ABI_FP_number_model = 23, + ABI_align8_needed = 24, + ABI_align8_preserved = 25, + ABI_enum_size = 26, + ABI_HardFP_use = 27, + ABI_VFP_args = 28, + ABI_WMMX_args = 29, + ABI_optimization_goals = 30, + ABI_FP_optimization_goals = 31, + compatibility = 32, + CPU_unaligned_access = 34, + VFP_HP_extension = 36, + ABI_FP_16bit_format = 38, + nodefaults = 64, + also_compatible_with = 65, + T2EE_use = 66, + conformance = 67, + Virtualization_use = 68, + MPextension_use = 70 + }; +} + +#endif // __TARGET_ARMBUILDATTRS_H__ diff --git a/libclamav/c++/llvm/lib/Target/ARM/ARMCallingConv.td b/libclamav/c++/llvm/lib/Target/ARM/ARMCallingConv.td new file mode 100644 index 000000000..8fdb07f81 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/ARM/ARMCallingConv.td @@ -0,0 +1,132 @@ +//===- ARMCallingConv.td - Calling Conventions for ARM ----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// This describes the calling conventions for ARM architecture. +//===----------------------------------------------------------------------===// + +/// CCIfSubtarget - Match if the current subtarget has a feature F. +class CCIfSubtarget: + CCIf().", F), A>; + +/// CCIfAlign - Match of the original alignment of the arg +class CCIfAlign: + CCIf; + +//===----------------------------------------------------------------------===// +// ARM APCS Calling Convention +//===----------------------------------------------------------------------===// +def CC_ARM_APCS : CallingConv<[ + + CCIfType<[i8, i16], CCPromoteToType>, + + // Handle all vector types as either f64 or v2f64. + CCIfType<[v1i64, v2i32, v4i16, v8i8, v2f32], CCBitConvertToType>, + CCIfType<[v2i64, v4i32, v8i16, v16i8, v4f32], CCBitConvertToType>, + + // f64 and v2f64 are passed in adjacent GPRs, possibly split onto the stack + CCIfType<[f64, v2f64], CCCustom<"CC_ARM_APCS_Custom_f64">>, + + CCIfType<[f32], CCBitConvertToType>, + CCIfType<[i32], CCAssignToReg<[R0, R1, R2, R3]>>, + + CCIfType<[i32], CCAssignToStack<4, 4>>, + CCIfType<[f64], CCAssignToStack<8, 4>>, + CCIfType<[v2f64], CCAssignToStack<16, 4>> +]>; + +def RetCC_ARM_APCS : CallingConv<[ + CCIfType<[f32], CCBitConvertToType>, + + // Handle all vector types as either f64 or v2f64. + CCIfType<[v1i64, v2i32, v4i16, v8i8, v2f32], CCBitConvertToType>, + CCIfType<[v2i64, v4i32, v8i16, v16i8, v4f32], CCBitConvertToType>, + + CCIfType<[f64, v2f64], CCCustom<"RetCC_ARM_APCS_Custom_f64">>, + + CCIfType<[i32], CCAssignToReg<[R0, R1, R2, R3]>>, + CCIfType<[i64], CCAssignToRegWithShadow<[R0, R2], [R1, R3]>> +]>; + +//===----------------------------------------------------------------------===// +// ARM AAPCS (EABI) Calling Convention, common parts +//===----------------------------------------------------------------------===// + +def CC_ARM_AAPCS_Common : CallingConv<[ + + CCIfType<[i8, i16], CCPromoteToType>, + + // i64/f64 is passed in even pairs of GPRs + // i64 is 8-aligned i32 here, so we may need to eat R1 as a pad register + // (and the same is true for f64 if VFP is not enabled) + CCIfType<[i32], CCIfAlign<"8", CCAssignToRegWithShadow<[R0, R2], [R0, R1]>>>, + CCIfType<[i32], CCIf<"State.getNextStackOffset() == 0 &&" + "ArgFlags.getOrigAlign() != 8", + CCAssignToReg<[R0, R1, R2, R3]>>>, + + CCIfType<[i32], CCIfAlign<"8", CCAssignToStack<4, 8>>>, + CCIfType<[i32, f32], CCAssignToStack<4, 4>>, + CCIfType<[f64], CCAssignToStack<8, 8>>, + CCIfType<[v2f64], CCAssignToStack<16, 8>> +]>; + +def RetCC_ARM_AAPCS_Common : CallingConv<[ + CCIfType<[i32], CCAssignToReg<[R0, R1, R2, R3]>>, + CCIfType<[i64], CCAssignToRegWithShadow<[R0, R2], [R1, R3]>> +]>; + +//===----------------------------------------------------------------------===// +// ARM AAPCS (EABI) Calling Convention +//===----------------------------------------------------------------------===// + +def CC_ARM_AAPCS : CallingConv<[ + // Handle all vector types as either f64 or v2f64. + CCIfType<[v1i64, v2i32, v4i16, v8i8, v2f32], CCBitConvertToType>, + CCIfType<[v2i64, v4i32, v8i16, v16i8, v4f32], CCBitConvertToType>, + + CCIfType<[f64, v2f64], CCCustom<"CC_ARM_AAPCS_Custom_f64">>, + CCIfType<[f32], CCBitConvertToType>, + CCDelegateTo +]>; + +def RetCC_ARM_AAPCS : CallingConv<[ + // Handle all vector types as either f64 or v2f64. + CCIfType<[v1i64, v2i32, v4i16, v8i8, v2f32], CCBitConvertToType>, + CCIfType<[v2i64, v4i32, v8i16, v16i8, v4f32], CCBitConvertToType>, + + CCIfType<[f64, v2f64], CCCustom<"RetCC_ARM_AAPCS_Custom_f64">>, + CCIfType<[f32], CCBitConvertToType>, + CCDelegateTo +]>; + +//===----------------------------------------------------------------------===// +// ARM AAPCS-VFP (EABI) Calling Convention +//===----------------------------------------------------------------------===// + +def CC_ARM_AAPCS_VFP : CallingConv<[ + // Handle all vector types as either f64 or v2f64. + CCIfType<[v1i64, v2i32, v4i16, v8i8, v2f32], CCBitConvertToType>, + CCIfType<[v2i64, v4i32, v8i16, v16i8, v4f32], CCBitConvertToType>, + + CCIfType<[v2f64], CCAssignToReg<[Q0, Q1, Q2, Q3]>>, + CCIfType<[f64], CCAssignToReg<[D0, D1, D2, D3, D4, D5, D6, D7]>>, + CCIfType<[f32], CCAssignToReg<[S0, S1, S2, S3, S4, S5, S6, S7, S8, + S9, S10, S11, S12, S13, S14, S15]>>, + CCDelegateTo +]>; + +def RetCC_ARM_AAPCS_VFP : CallingConv<[ + // Handle all vector types as either f64 or v2f64. + CCIfType<[v1i64, v2i32, v4i16, v8i8, v2f32], CCBitConvertToType>, + CCIfType<[v2i64, v4i32, v8i16, v16i8, v4f32], CCBitConvertToType>, + + CCIfType<[v2f64], CCAssignToReg<[Q0, Q1, Q2, Q3]>>, + CCIfType<[f64], CCAssignToReg<[D0, D1, D2, D3, D4, D5, D6, D7]>>, + CCIfType<[f32], CCAssignToReg<[S0, S1, S2, S3, S4, S5, S6, S7, S8, + S9, S10, S11, S12, S13, S14, S15]>>, + CCDelegateTo +]>; diff --git a/libclamav/c++/llvm/lib/Target/ARM/ARMCodeEmitter.cpp b/libclamav/c++/llvm/lib/Target/ARM/ARMCodeEmitter.cpp new file mode 100644 index 000000000..17e7d4479 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/ARM/ARMCodeEmitter.cpp @@ -0,0 +1,1432 @@ +//===-- ARM/ARMCodeEmitter.cpp - Convert ARM code to machine code ---------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the pass that transforms the ARM machine instructions into +// relocatable machine code. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "jit" +#include "ARM.h" +#include "ARMAddressingModes.h" +#include "ARMConstantPoolValue.h" +#include "ARMInstrInfo.h" +#include "ARMRelocations.h" +#include "ARMSubtarget.h" +#include "ARMTargetMachine.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Function.h" +#include "llvm/PassManager.h" +#include "llvm/CodeGen/MachineCodeEmitter.h" +#include "llvm/CodeGen/JITCodeEmitter.h" +#include "llvm/CodeGen/ObjectCodeEmitter.h" +#include "llvm/CodeGen/MachineConstantPool.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/CodeGen/MachineJumpTableInfo.h" +#include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +#ifndef NDEBUG +#include +#endif +using namespace llvm; + +STATISTIC(NumEmitted, "Number of machine instructions emitted"); + +namespace { + + class ARMCodeEmitter { + public: + /// getBinaryCodeForInstr - This function, generated by the + /// CodeEmitterGenerator using TableGen, produces the binary encoding for + /// machine instructions. + unsigned getBinaryCodeForInstr(const MachineInstr &MI); + }; + + template + class Emitter : public MachineFunctionPass, public ARMCodeEmitter { + ARMJITInfo *JTI; + const ARMInstrInfo *II; + const TargetData *TD; + const ARMSubtarget *Subtarget; + TargetMachine &TM; + CodeEmitter &MCE; + const std::vector *MCPEs; + const std::vector *MJTEs; + bool IsPIC; + + void getAnalysisUsage(AnalysisUsage &AU) const { + AU.addRequired(); + MachineFunctionPass::getAnalysisUsage(AU); + } + + public: + static char ID; + explicit Emitter(TargetMachine &tm, CodeEmitter &mce) + : MachineFunctionPass(&ID), JTI(0), II(0), TD(0), TM(tm), + MCE(mce), MCPEs(0), MJTEs(0), + IsPIC(TM.getRelocationModel() == Reloc::PIC_) {} + Emitter(TargetMachine &tm, CodeEmitter &mce, + const ARMInstrInfo &ii, const TargetData &td) + : MachineFunctionPass(&ID), JTI(0), II(&ii), TD(&td), TM(tm), + MCE(mce), MCPEs(0), MJTEs(0), + IsPIC(TM.getRelocationModel() == Reloc::PIC_) {} + + bool runOnMachineFunction(MachineFunction &MF); + + virtual const char *getPassName() const { + return "ARM Machine Code Emitter"; + } + + void emitInstruction(const MachineInstr &MI); + + private: + + void emitWordLE(unsigned Binary); + + void emitDWordLE(uint64_t Binary); + + void emitConstPoolInstruction(const MachineInstr &MI); + + void emitMOVi2piecesInstruction(const MachineInstr &MI); + + void emitLEApcrelJTInstruction(const MachineInstr &MI); + + void emitPseudoMoveInstruction(const MachineInstr &MI); + + void addPCLabel(unsigned LabelID); + + void emitPseudoInstruction(const MachineInstr &MI); + + unsigned getMachineSoRegOpValue(const MachineInstr &MI, + const TargetInstrDesc &TID, + const MachineOperand &MO, + unsigned OpIdx); + + unsigned getMachineSoImmOpValue(unsigned SoImm); + + unsigned getAddrModeSBit(const MachineInstr &MI, + const TargetInstrDesc &TID) const; + + void emitDataProcessingInstruction(const MachineInstr &MI, + unsigned ImplicitRd = 0, + unsigned ImplicitRn = 0); + + void emitLoadStoreInstruction(const MachineInstr &MI, + unsigned ImplicitRd = 0, + unsigned ImplicitRn = 0); + + void emitMiscLoadStoreInstruction(const MachineInstr &MI, + unsigned ImplicitRn = 0); + + void emitLoadStoreMultipleInstruction(const MachineInstr &MI); + + void emitMulFrmInstruction(const MachineInstr &MI); + + void emitExtendInstruction(const MachineInstr &MI); + + void emitMiscArithInstruction(const MachineInstr &MI); + + void emitBranchInstruction(const MachineInstr &MI); + + void emitInlineJumpTable(unsigned JTIndex); + + void emitMiscBranchInstruction(const MachineInstr &MI); + + void emitVFPArithInstruction(const MachineInstr &MI); + + void emitVFPConversionInstruction(const MachineInstr &MI); + + void emitVFPLoadStoreInstruction(const MachineInstr &MI); + + void emitVFPLoadStoreMultipleInstruction(const MachineInstr &MI); + + void emitMiscInstruction(const MachineInstr &MI); + + /// getMachineOpValue - Return binary encoding of operand. If the machine + /// operand requires relocation, record the relocation and return zero. + unsigned getMachineOpValue(const MachineInstr &MI,const MachineOperand &MO); + unsigned getMachineOpValue(const MachineInstr &MI, unsigned OpIdx) { + return getMachineOpValue(MI, MI.getOperand(OpIdx)); + } + + /// getShiftOp - Return the shift opcode (bit[6:5]) of the immediate value. + /// + unsigned getShiftOp(unsigned Imm) const ; + + /// Routines that handle operands which add machine relocations which are + /// fixed up by the relocation stage. + void emitGlobalAddress(GlobalValue *GV, unsigned Reloc, + bool MayNeedFarStub, bool Indirect, + intptr_t ACPV = 0); + void emitExternalSymbolAddress(const char *ES, unsigned Reloc); + void emitConstPoolAddress(unsigned CPI, unsigned Reloc); + void emitJumpTableAddress(unsigned JTIndex, unsigned Reloc); + void emitMachineBasicBlock(MachineBasicBlock *BB, unsigned Reloc, + intptr_t JTBase = 0); + }; + template + char Emitter::ID = 0; +} + +/// createARMCodeEmitterPass - Return a pass that emits the collected ARM code +/// to the specified MCE object. + +FunctionPass *llvm::createARMCodeEmitterPass(ARMBaseTargetMachine &TM, + MachineCodeEmitter &MCE) { + return new Emitter(TM, MCE); +} +FunctionPass *llvm::createARMJITCodeEmitterPass(ARMBaseTargetMachine &TM, + JITCodeEmitter &JCE) { + return new Emitter(TM, JCE); +} +FunctionPass *llvm::createARMObjectCodeEmitterPass(ARMBaseTargetMachine &TM, + ObjectCodeEmitter &OCE) { + return new Emitter(TM, OCE); +} + +template +bool Emitter::runOnMachineFunction(MachineFunction &MF) { + assert((MF.getTarget().getRelocationModel() != Reloc::Default || + MF.getTarget().getRelocationModel() != Reloc::Static) && + "JIT relocation model must be set to static or default!"); + JTI = ((ARMTargetMachine&)MF.getTarget()).getJITInfo(); + II = ((ARMTargetMachine&)MF.getTarget()).getInstrInfo(); + TD = ((ARMTargetMachine&)MF.getTarget()).getTargetData(); + Subtarget = &TM.getSubtarget(); + MCPEs = &MF.getConstantPool()->getConstants(); + MJTEs = &MF.getJumpTableInfo()->getJumpTables(); + IsPIC = TM.getRelocationModel() == Reloc::PIC_; + JTI->Initialize(MF, IsPIC); + MCE.setModuleInfo(&getAnalysis()); + + do { + DEBUG(errs() << "JITTing function '" + << MF.getFunction()->getName() << "'\n"); + MCE.startFunction(MF); + for (MachineFunction::iterator MBB = MF.begin(), E = MF.end(); + MBB != E; ++MBB) { + MCE.StartMachineBasicBlock(MBB); + for (MachineBasicBlock::const_iterator I = MBB->begin(), E = MBB->end(); + I != E; ++I) + emitInstruction(*I); + } + } while (MCE.finishFunction(MF)); + + return false; +} + +/// getShiftOp - Return the shift opcode (bit[6:5]) of the immediate value. +/// +template +unsigned Emitter::getShiftOp(unsigned Imm) const { + switch (ARM_AM::getAM2ShiftOpc(Imm)) { + default: llvm_unreachable("Unknown shift opc!"); + case ARM_AM::asr: return 2; + case ARM_AM::lsl: return 0; + case ARM_AM::lsr: return 1; + case ARM_AM::ror: + case ARM_AM::rrx: return 3; + } + return 0; +} + +/// getMachineOpValue - Return binary encoding of operand. If the machine +/// operand requires relocation, record the relocation and return zero. +template +unsigned Emitter::getMachineOpValue(const MachineInstr &MI, + const MachineOperand &MO) { + if (MO.isReg()) + return ARMRegisterInfo::getRegisterNumbering(MO.getReg()); + else if (MO.isImm()) + return static_cast(MO.getImm()); + else if (MO.isGlobal()) + emitGlobalAddress(MO.getGlobal(), ARM::reloc_arm_branch, true, false); + else if (MO.isSymbol()) + emitExternalSymbolAddress(MO.getSymbolName(), ARM::reloc_arm_branch); + else if (MO.isCPI()) { + const TargetInstrDesc &TID = MI.getDesc(); + // For VFP load, the immediate offset is multiplied by 4. + unsigned Reloc = ((TID.TSFlags & ARMII::FormMask) == ARMII::VFPLdStFrm) + ? ARM::reloc_arm_vfp_cp_entry : ARM::reloc_arm_cp_entry; + emitConstPoolAddress(MO.getIndex(), Reloc); + } else if (MO.isJTI()) + emitJumpTableAddress(MO.getIndex(), ARM::reloc_arm_relative); + else if (MO.isMBB()) + emitMachineBasicBlock(MO.getMBB(), ARM::reloc_arm_branch); + else { +#ifndef NDEBUG + errs() << MO; +#endif + llvm_unreachable(0); + } + return 0; +} + +/// emitGlobalAddress - Emit the specified address to the code stream. +/// +template +void Emitter::emitGlobalAddress(GlobalValue *GV, unsigned Reloc, + bool MayNeedFarStub, bool Indirect, + intptr_t ACPV) { + MachineRelocation MR = Indirect + ? MachineRelocation::getIndirectSymbol(MCE.getCurrentPCOffset(), Reloc, + GV, ACPV, MayNeedFarStub) + : MachineRelocation::getGV(MCE.getCurrentPCOffset(), Reloc, + GV, ACPV, MayNeedFarStub); + MCE.addRelocation(MR); +} + +/// emitExternalSymbolAddress - Arrange for the address of an external symbol to +/// be emitted to the current location in the function, and allow it to be PC +/// relative. +template +void Emitter::emitExternalSymbolAddress(const char *ES, + unsigned Reloc) { + MCE.addRelocation(MachineRelocation::getExtSym(MCE.getCurrentPCOffset(), + Reloc, ES)); +} + +/// emitConstPoolAddress - Arrange for the address of an constant pool +/// to be emitted to the current location in the function, and allow it to be PC +/// relative. +template +void Emitter::emitConstPoolAddress(unsigned CPI, + unsigned Reloc) { + // Tell JIT emitter we'll resolve the address. + MCE.addRelocation(MachineRelocation::getConstPool(MCE.getCurrentPCOffset(), + Reloc, CPI, 0, true)); +} + +/// emitJumpTableAddress - Arrange for the address of a jump table to +/// be emitted to the current location in the function, and allow it to be PC +/// relative. +template +void Emitter::emitJumpTableAddress(unsigned JTIndex, + unsigned Reloc) { + MCE.addRelocation(MachineRelocation::getJumpTable(MCE.getCurrentPCOffset(), + Reloc, JTIndex, 0, true)); +} + +/// emitMachineBasicBlock - Emit the specified address basic block. +template +void Emitter::emitMachineBasicBlock(MachineBasicBlock *BB, + unsigned Reloc, intptr_t JTBase) { + MCE.addRelocation(MachineRelocation::getBB(MCE.getCurrentPCOffset(), + Reloc, BB, JTBase)); +} + +template +void Emitter::emitWordLE(unsigned Binary) { + DEBUG(errs() << " 0x"; + errs().write_hex(Binary) << "\n"); + MCE.emitWordLE(Binary); +} + +template +void Emitter::emitDWordLE(uint64_t Binary) { + DEBUG(errs() << " 0x"; + errs().write_hex(Binary) << "\n"); + MCE.emitDWordLE(Binary); +} + +template +void Emitter::emitInstruction(const MachineInstr &MI) { + DEBUG(errs() << "JIT: " << (void*)MCE.getCurrentPCValue() << ":\t" << MI); + + MCE.processDebugLoc(MI.getDebugLoc(), true); + + NumEmitted++; // Keep track of the # of mi's emitted + switch (MI.getDesc().TSFlags & ARMII::FormMask) { + default: { + llvm_unreachable("Unhandled instruction encoding format!"); + break; + } + case ARMII::Pseudo: + emitPseudoInstruction(MI); + break; + case ARMII::DPFrm: + case ARMII::DPSoRegFrm: + emitDataProcessingInstruction(MI); + break; + case ARMII::LdFrm: + case ARMII::StFrm: + emitLoadStoreInstruction(MI); + break; + case ARMII::LdMiscFrm: + case ARMII::StMiscFrm: + emitMiscLoadStoreInstruction(MI); + break; + case ARMII::LdStMulFrm: + emitLoadStoreMultipleInstruction(MI); + break; + case ARMII::MulFrm: + emitMulFrmInstruction(MI); + break; + case ARMII::ExtFrm: + emitExtendInstruction(MI); + break; + case ARMII::ArithMiscFrm: + emitMiscArithInstruction(MI); + break; + case ARMII::BrFrm: + emitBranchInstruction(MI); + break; + case ARMII::BrMiscFrm: + emitMiscBranchInstruction(MI); + break; + // VFP instructions. + case ARMII::VFPUnaryFrm: + case ARMII::VFPBinaryFrm: + emitVFPArithInstruction(MI); + break; + case ARMII::VFPConv1Frm: + case ARMII::VFPConv2Frm: + case ARMII::VFPConv3Frm: + case ARMII::VFPConv4Frm: + case ARMII::VFPConv5Frm: + emitVFPConversionInstruction(MI); + break; + case ARMII::VFPLdStFrm: + emitVFPLoadStoreInstruction(MI); + break; + case ARMII::VFPLdStMulFrm: + emitVFPLoadStoreMultipleInstruction(MI); + break; + case ARMII::VFPMiscFrm: + emitMiscInstruction(MI); + break; + } + MCE.processDebugLoc(MI.getDebugLoc(), false); +} + +template +void Emitter::emitConstPoolInstruction(const MachineInstr &MI) { + unsigned CPI = MI.getOperand(0).getImm(); // CP instruction index. + unsigned CPIndex = MI.getOperand(1).getIndex(); // Actual cp entry index. + const MachineConstantPoolEntry &MCPE = (*MCPEs)[CPIndex]; + + // Remember the CONSTPOOL_ENTRY address for later relocation. + JTI->addConstantPoolEntryAddr(CPI, MCE.getCurrentPCValue()); + + // Emit constpool island entry. In most cases, the actual values will be + // resolved and relocated after code emission. + if (MCPE.isMachineConstantPoolEntry()) { + ARMConstantPoolValue *ACPV = + static_cast(MCPE.Val.MachineCPVal); + + DEBUG(errs() << " ** ARM constant pool #" << CPI << " @ " + << (void*)MCE.getCurrentPCValue() << " " << *ACPV << '\n'); + + assert(ACPV->isGlobalValue() && "unsupported constant pool value"); + GlobalValue *GV = ACPV->getGV(); + if (GV) { + Reloc::Model RelocM = TM.getRelocationModel(); + emitGlobalAddress(GV, ARM::reloc_arm_machine_cp_entry, + isa(GV), + Subtarget->GVIsIndirectSymbol(GV, RelocM), + (intptr_t)ACPV); + } else { + emitExternalSymbolAddress(ACPV->getSymbol(), ARM::reloc_arm_absolute); + } + emitWordLE(0); + } else { + Constant *CV = MCPE.Val.ConstVal; + + DEBUG({ + errs() << " ** Constant pool #" << CPI << " @ " + << (void*)MCE.getCurrentPCValue() << " "; + if (const Function *F = dyn_cast(CV)) + errs() << F->getName(); + else + errs() << *CV; + errs() << '\n'; + }); + + if (GlobalValue *GV = dyn_cast(CV)) { + emitGlobalAddress(GV, ARM::reloc_arm_absolute, isa(GV), false); + emitWordLE(0); + } else if (const ConstantInt *CI = dyn_cast(CV)) { + uint32_t Val = *(uint32_t*)CI->getValue().getRawData(); + emitWordLE(Val); + } else if (const ConstantFP *CFP = dyn_cast(CV)) { + if (CFP->getType()->isFloatTy()) + emitWordLE(CFP->getValueAPF().bitcastToAPInt().getZExtValue()); + else if (CFP->getType()->isDoubleTy()) + emitDWordLE(CFP->getValueAPF().bitcastToAPInt().getZExtValue()); + else { + llvm_unreachable("Unable to handle this constantpool entry!"); + } + } else { + llvm_unreachable("Unable to handle this constantpool entry!"); + } + } +} + +template +void Emitter::emitMOVi2piecesInstruction(const MachineInstr &MI) { + const MachineOperand &MO0 = MI.getOperand(0); + const MachineOperand &MO1 = MI.getOperand(1); + assert(MO1.isImm() && ARM_AM::getSOImmVal(MO1.isImm()) != -1 && + "Not a valid so_imm value!"); + unsigned V1 = ARM_AM::getSOImmTwoPartFirst(MO1.getImm()); + unsigned V2 = ARM_AM::getSOImmTwoPartSecond(MO1.getImm()); + + // Emit the 'mov' instruction. + unsigned Binary = 0xd << 21; // mov: Insts{24-21} = 0b1101 + + // Set the conditional execution predicate. + Binary |= II->getPredicate(&MI) << ARMII::CondShift; + + // Encode Rd. + Binary |= getMachineOpValue(MI, MO0) << ARMII::RegRdShift; + + // Encode so_imm. + // Set bit I(25) to identify this is the immediate form of + Binary |= 1 << ARMII::I_BitShift; + Binary |= getMachineSoImmOpValue(V1); + emitWordLE(Binary); + + // Now the 'orr' instruction. + Binary = 0xc << 21; // orr: Insts{24-21} = 0b1100 + + // Set the conditional execution predicate. + Binary |= II->getPredicate(&MI) << ARMII::CondShift; + + // Encode Rd. + Binary |= getMachineOpValue(MI, MO0) << ARMII::RegRdShift; + + // Encode Rn. + Binary |= getMachineOpValue(MI, MO0) << ARMII::RegRnShift; + + // Encode so_imm. + // Set bit I(25) to identify this is the immediate form of + Binary |= 1 << ARMII::I_BitShift; + Binary |= getMachineSoImmOpValue(V2); + emitWordLE(Binary); +} + +template +void Emitter::emitLEApcrelJTInstruction(const MachineInstr &MI) { + // It's basically add r, pc, (LJTI - $+8) + + const TargetInstrDesc &TID = MI.getDesc(); + + // Emit the 'add' instruction. + unsigned Binary = 0x4 << 21; // add: Insts{24-31} = 0b0100 + + // Set the conditional execution predicate + Binary |= II->getPredicate(&MI) << ARMII::CondShift; + + // Encode S bit if MI modifies CPSR. + Binary |= getAddrModeSBit(MI, TID); + + // Encode Rd. + Binary |= getMachineOpValue(MI, 0) << ARMII::RegRdShift; + + // Encode Rn which is PC. + Binary |= ARMRegisterInfo::getRegisterNumbering(ARM::PC) << ARMII::RegRnShift; + + // Encode the displacement. + Binary |= 1 << ARMII::I_BitShift; + emitJumpTableAddress(MI.getOperand(1).getIndex(), ARM::reloc_arm_jt_base); + + emitWordLE(Binary); +} + +template +void Emitter::emitPseudoMoveInstruction(const MachineInstr &MI) { + unsigned Opcode = MI.getDesc().Opcode; + + // Part of binary is determined by TableGn. + unsigned Binary = getBinaryCodeForInstr(MI); + + // Set the conditional execution predicate + Binary |= II->getPredicate(&MI) << ARMII::CondShift; + + // Encode S bit if MI modifies CPSR. + if (Opcode == ARM::MOVsrl_flag || Opcode == ARM::MOVsra_flag) + Binary |= 1 << ARMII::S_BitShift; + + // Encode register def if there is one. + Binary |= getMachineOpValue(MI, 0) << ARMII::RegRdShift; + + // Encode the shift operation. + switch (Opcode) { + default: break; + case ARM::MOVrx: + // rrx + Binary |= 0x6 << 4; + break; + case ARM::MOVsrl_flag: + // lsr #1 + Binary |= (0x2 << 4) | (1 << 7); + break; + case ARM::MOVsra_flag: + // asr #1 + Binary |= (0x4 << 4) | (1 << 7); + break; + } + + // Encode register Rm. + Binary |= getMachineOpValue(MI, 1); + + emitWordLE(Binary); +} + +template +void Emitter::addPCLabel(unsigned LabelID) { + DEBUG(errs() << " ** LPC" << LabelID << " @ " + << (void*)MCE.getCurrentPCValue() << '\n'); + JTI->addPCLabelAddr(LabelID, MCE.getCurrentPCValue()); +} + +template +void Emitter::emitPseudoInstruction(const MachineInstr &MI) { + unsigned Opcode = MI.getDesc().Opcode; + switch (Opcode) { + default: + llvm_unreachable("ARMCodeEmitter::emitPseudoInstruction"); + // FIXME: Add support for MOVimm32. + case TargetInstrInfo::INLINEASM: { + // We allow inline assembler nodes with empty bodies - they can + // implicitly define registers, which is ok for JIT. + if (MI.getOperand(0).getSymbolName()[0]) { + llvm_report_error("JIT does not support inline asm!"); + } + break; + } + case TargetInstrInfo::DBG_LABEL: + case TargetInstrInfo::EH_LABEL: + MCE.emitLabel(MI.getOperand(0).getImm()); + break; + case TargetInstrInfo::IMPLICIT_DEF: + case TargetInstrInfo::KILL: + // Do nothing. + break; + case ARM::CONSTPOOL_ENTRY: + emitConstPoolInstruction(MI); + break; + case ARM::PICADD: { + // Remember of the address of the PC label for relocation later. + addPCLabel(MI.getOperand(2).getImm()); + // PICADD is just an add instruction that implicitly read pc. + emitDataProcessingInstruction(MI, 0, ARM::PC); + break; + } + case ARM::PICLDR: + case ARM::PICLDRB: + case ARM::PICSTR: + case ARM::PICSTRB: { + // Remember of the address of the PC label for relocation later. + addPCLabel(MI.getOperand(2).getImm()); + // These are just load / store instructions that implicitly read pc. + emitLoadStoreInstruction(MI, 0, ARM::PC); + break; + } + case ARM::PICLDRH: + case ARM::PICLDRSH: + case ARM::PICLDRSB: + case ARM::PICSTRH: { + // Remember of the address of the PC label for relocation later. + addPCLabel(MI.getOperand(2).getImm()); + // These are just load / store instructions that implicitly read pc. + emitMiscLoadStoreInstruction(MI, ARM::PC); + break; + } + case ARM::MOVi2pieces: + // Two instructions to materialize a constant. + emitMOVi2piecesInstruction(MI); + break; + case ARM::LEApcrelJT: + // Materialize jumptable address. + emitLEApcrelJTInstruction(MI); + break; + case ARM::MOVrx: + case ARM::MOVsrl_flag: + case ARM::MOVsra_flag: + emitPseudoMoveInstruction(MI); + break; + } +} + +template +unsigned Emitter::getMachineSoRegOpValue( + const MachineInstr &MI, + const TargetInstrDesc &TID, + const MachineOperand &MO, + unsigned OpIdx) { + unsigned Binary = getMachineOpValue(MI, MO); + + const MachineOperand &MO1 = MI.getOperand(OpIdx + 1); + const MachineOperand &MO2 = MI.getOperand(OpIdx + 2); + ARM_AM::ShiftOpc SOpc = ARM_AM::getSORegShOp(MO2.getImm()); + + // Encode the shift opcode. + unsigned SBits = 0; + unsigned Rs = MO1.getReg(); + if (Rs) { + // Set shift operand (bit[7:4]). + // LSL - 0001 + // LSR - 0011 + // ASR - 0101 + // ROR - 0111 + // RRX - 0110 and bit[11:8] clear. + switch (SOpc) { + default: llvm_unreachable("Unknown shift opc!"); + case ARM_AM::lsl: SBits = 0x1; break; + case ARM_AM::lsr: SBits = 0x3; break; + case ARM_AM::asr: SBits = 0x5; break; + case ARM_AM::ror: SBits = 0x7; break; + case ARM_AM::rrx: SBits = 0x6; break; + } + } else { + // Set shift operand (bit[6:4]). + // LSL - 000 + // LSR - 010 + // ASR - 100 + // ROR - 110 + switch (SOpc) { + default: llvm_unreachable("Unknown shift opc!"); + case ARM_AM::lsl: SBits = 0x0; break; + case ARM_AM::lsr: SBits = 0x2; break; + case ARM_AM::asr: SBits = 0x4; break; + case ARM_AM::ror: SBits = 0x6; break; + } + } + Binary |= SBits << 4; + if (SOpc == ARM_AM::rrx) + return Binary; + + // Encode the shift operation Rs or shift_imm (except rrx). + if (Rs) { + // Encode Rs bit[11:8]. + assert(ARM_AM::getSORegOffset(MO2.getImm()) == 0); + return Binary | + (ARMRegisterInfo::getRegisterNumbering(Rs) << ARMII::RegRsShift); + } + + // Encode shift_imm bit[11:7]. + return Binary | ARM_AM::getSORegOffset(MO2.getImm()) << 7; +} + +template +unsigned Emitter::getMachineSoImmOpValue(unsigned SoImm) { + int SoImmVal = ARM_AM::getSOImmVal(SoImm); + assert(SoImmVal != -1 && "Not a valid so_imm value!"); + + // Encode rotate_imm. + unsigned Binary = (ARM_AM::getSOImmValRot((unsigned)SoImmVal) >> 1) + << ARMII::SoRotImmShift; + + // Encode immed_8. + Binary |= ARM_AM::getSOImmValImm((unsigned)SoImmVal); + return Binary; +} + +template +unsigned Emitter::getAddrModeSBit(const MachineInstr &MI, + const TargetInstrDesc &TID) const { + for (unsigned i = MI.getNumOperands(), e = TID.getNumOperands(); i != e; --i){ + const MachineOperand &MO = MI.getOperand(i-1); + if (MO.isReg() && MO.isDef() && MO.getReg() == ARM::CPSR) + return 1 << ARMII::S_BitShift; + } + return 0; +} + +template +void Emitter::emitDataProcessingInstruction( + const MachineInstr &MI, + unsigned ImplicitRd, + unsigned ImplicitRn) { + const TargetInstrDesc &TID = MI.getDesc(); + + if (TID.Opcode == ARM::BFC) { + llvm_report_error("ARMv6t2 JIT is not yet supported."); + } + + // Part of binary is determined by TableGn. + unsigned Binary = getBinaryCodeForInstr(MI); + + // Set the conditional execution predicate + Binary |= II->getPredicate(&MI) << ARMII::CondShift; + + // Encode S bit if MI modifies CPSR. + Binary |= getAddrModeSBit(MI, TID); + + // Encode register def if there is one. + unsigned NumDefs = TID.getNumDefs(); + unsigned OpIdx = 0; + if (NumDefs) + Binary |= getMachineOpValue(MI, OpIdx++) << ARMII::RegRdShift; + else if (ImplicitRd) + // Special handling for implicit use (e.g. PC). + Binary |= (ARMRegisterInfo::getRegisterNumbering(ImplicitRd) + << ARMII::RegRdShift); + + // If this is a two-address operand, skip it. e.g. MOVCCr operand 1. + if (TID.getOperandConstraint(OpIdx, TOI::TIED_TO) != -1) + ++OpIdx; + + // Encode first non-shifter register operand if there is one. + bool isUnary = TID.TSFlags & ARMII::UnaryDP; + if (!isUnary) { + if (ImplicitRn) + // Special handling for implicit use (e.g. PC). + Binary |= (ARMRegisterInfo::getRegisterNumbering(ImplicitRn) + << ARMII::RegRnShift); + else { + Binary |= getMachineOpValue(MI, OpIdx) << ARMII::RegRnShift; + ++OpIdx; + } + } + + // Encode shifter operand. + const MachineOperand &MO = MI.getOperand(OpIdx); + if ((TID.TSFlags & ARMII::FormMask) == ARMII::DPSoRegFrm) { + // Encode SoReg. + emitWordLE(Binary | getMachineSoRegOpValue(MI, TID, MO, OpIdx)); + return; + } + + if (MO.isReg()) { + // Encode register Rm. + emitWordLE(Binary | ARMRegisterInfo::getRegisterNumbering(MO.getReg())); + return; + } + + // Encode so_imm. + Binary |= getMachineSoImmOpValue((unsigned)MO.getImm()); + + emitWordLE(Binary); +} + +template +void Emitter::emitLoadStoreInstruction( + const MachineInstr &MI, + unsigned ImplicitRd, + unsigned ImplicitRn) { + const TargetInstrDesc &TID = MI.getDesc(); + unsigned Form = TID.TSFlags & ARMII::FormMask; + bool IsPrePost = (TID.TSFlags & ARMII::IndexModeMask) != 0; + + // Part of binary is determined by TableGn. + unsigned Binary = getBinaryCodeForInstr(MI); + + // Set the conditional execution predicate + Binary |= II->getPredicate(&MI) << ARMII::CondShift; + + unsigned OpIdx = 0; + + // Operand 0 of a pre- and post-indexed store is the address base + // writeback. Skip it. + bool Skipped = false; + if (IsPrePost && Form == ARMII::StFrm) { + ++OpIdx; + Skipped = true; + } + + // Set first operand + if (ImplicitRd) + // Special handling for implicit use (e.g. PC). + Binary |= (ARMRegisterInfo::getRegisterNumbering(ImplicitRd) + << ARMII::RegRdShift); + else + Binary |= getMachineOpValue(MI, OpIdx++) << ARMII::RegRdShift; + + // Set second operand + if (ImplicitRn) + // Special handling for implicit use (e.g. PC). + Binary |= (ARMRegisterInfo::getRegisterNumbering(ImplicitRn) + << ARMII::RegRnShift); + else + Binary |= getMachineOpValue(MI, OpIdx++) << ARMII::RegRnShift; + + // If this is a two-address operand, skip it. e.g. LDR_PRE. + if (!Skipped && TID.getOperandConstraint(OpIdx, TOI::TIED_TO) != -1) + ++OpIdx; + + const MachineOperand &MO2 = MI.getOperand(OpIdx); + unsigned AM2Opc = (ImplicitRn == ARM::PC) + ? 0 : MI.getOperand(OpIdx+1).getImm(); + + // Set bit U(23) according to sign of immed value (positive or negative). + Binary |= ((ARM_AM::getAM2Op(AM2Opc) == ARM_AM::add ? 1 : 0) << + ARMII::U_BitShift); + if (!MO2.getReg()) { // is immediate + if (ARM_AM::getAM2Offset(AM2Opc)) + // Set the value of offset_12 field + Binary |= ARM_AM::getAM2Offset(AM2Opc); + emitWordLE(Binary); + return; + } + + // Set bit I(25), because this is not in immediate enconding. + Binary |= 1 << ARMII::I_BitShift; + assert(TargetRegisterInfo::isPhysicalRegister(MO2.getReg())); + // Set bit[3:0] to the corresponding Rm register + Binary |= ARMRegisterInfo::getRegisterNumbering(MO2.getReg()); + + // If this instr is in scaled register offset/index instruction, set + // shift_immed(bit[11:7]) and shift(bit[6:5]) fields. + if (unsigned ShImm = ARM_AM::getAM2Offset(AM2Opc)) { + Binary |= getShiftOp(AM2Opc) << ARMII::ShiftImmShift; // shift + Binary |= ShImm << ARMII::ShiftShift; // shift_immed + } + + emitWordLE(Binary); +} + +template +void Emitter::emitMiscLoadStoreInstruction(const MachineInstr &MI, + unsigned ImplicitRn) { + const TargetInstrDesc &TID = MI.getDesc(); + unsigned Form = TID.TSFlags & ARMII::FormMask; + bool IsPrePost = (TID.TSFlags & ARMII::IndexModeMask) != 0; + + // Part of binary is determined by TableGn. + unsigned Binary = getBinaryCodeForInstr(MI); + + // Set the conditional execution predicate + Binary |= II->getPredicate(&MI) << ARMII::CondShift; + + unsigned OpIdx = 0; + + // Operand 0 of a pre- and post-indexed store is the address base + // writeback. Skip it. + bool Skipped = false; + if (IsPrePost && Form == ARMII::StMiscFrm) { + ++OpIdx; + Skipped = true; + } + + // Set first operand + Binary |= getMachineOpValue(MI, OpIdx++) << ARMII::RegRdShift; + + // Skip LDRD and STRD's second operand. + if (TID.Opcode == ARM::LDRD || TID.Opcode == ARM::STRD) + ++OpIdx; + + // Set second operand + if (ImplicitRn) + // Special handling for implicit use (e.g. PC). + Binary |= (ARMRegisterInfo::getRegisterNumbering(ImplicitRn) + << ARMII::RegRnShift); + else + Binary |= getMachineOpValue(MI, OpIdx++) << ARMII::RegRnShift; + + // If this is a two-address operand, skip it. e.g. LDRH_POST. + if (!Skipped && TID.getOperandConstraint(OpIdx, TOI::TIED_TO) != -1) + ++OpIdx; + + const MachineOperand &MO2 = MI.getOperand(OpIdx); + unsigned AM3Opc = (ImplicitRn == ARM::PC) + ? 0 : MI.getOperand(OpIdx+1).getImm(); + + // Set bit U(23) according to sign of immed value (positive or negative) + Binary |= ((ARM_AM::getAM3Op(AM3Opc) == ARM_AM::add ? 1 : 0) << + ARMII::U_BitShift); + + // If this instr is in register offset/index encoding, set bit[3:0] + // to the corresponding Rm register. + if (MO2.getReg()) { + Binary |= ARMRegisterInfo::getRegisterNumbering(MO2.getReg()); + emitWordLE(Binary); + return; + } + + // This instr is in immediate offset/index encoding, set bit 22 to 1. + Binary |= 1 << ARMII::AM3_I_BitShift; + if (unsigned ImmOffs = ARM_AM::getAM3Offset(AM3Opc)) { + // Set operands + Binary |= (ImmOffs >> 4) << ARMII::ImmHiShift; // immedH + Binary |= (ImmOffs & 0xF); // immedL + } + + emitWordLE(Binary); +} + +static unsigned getAddrModeUPBits(unsigned Mode) { + unsigned Binary = 0; + + // Set addressing mode by modifying bits U(23) and P(24) + // IA - Increment after - bit U = 1 and bit P = 0 + // IB - Increment before - bit U = 1 and bit P = 1 + // DA - Decrement after - bit U = 0 and bit P = 0 + // DB - Decrement before - bit U = 0 and bit P = 1 + switch (Mode) { + default: llvm_unreachable("Unknown addressing sub-mode!"); + case ARM_AM::da: break; + case ARM_AM::db: Binary |= 0x1 << ARMII::P_BitShift; break; + case ARM_AM::ia: Binary |= 0x1 << ARMII::U_BitShift; break; + case ARM_AM::ib: Binary |= 0x3 << ARMII::U_BitShift; break; + } + + return Binary; +} + +template +void Emitter::emitLoadStoreMultipleInstruction( + const MachineInstr &MI) { + // Part of binary is determined by TableGn. + unsigned Binary = getBinaryCodeForInstr(MI); + + // Set the conditional execution predicate + Binary |= II->getPredicate(&MI) << ARMII::CondShift; + + // Set base address operand + Binary |= getMachineOpValue(MI, 0) << ARMII::RegRnShift; + + // Set addressing mode by modifying bits U(23) and P(24) + const MachineOperand &MO = MI.getOperand(1); + Binary |= getAddrModeUPBits(ARM_AM::getAM4SubMode(MO.getImm())); + + // Set bit W(21) + if (ARM_AM::getAM4WBFlag(MO.getImm())) + Binary |= 0x1 << ARMII::W_BitShift; + + // Set registers + for (unsigned i = 5, e = MI.getNumOperands(); i != e; ++i) { + const MachineOperand &MO = MI.getOperand(i); + if (!MO.isReg() || MO.isImplicit()) + break; + unsigned RegNum = ARMRegisterInfo::getRegisterNumbering(MO.getReg()); + assert(TargetRegisterInfo::isPhysicalRegister(MO.getReg()) && + RegNum < 16); + Binary |= 0x1 << RegNum; + } + + emitWordLE(Binary); +} + +template +void Emitter::emitMulFrmInstruction(const MachineInstr &MI) { + const TargetInstrDesc &TID = MI.getDesc(); + + // Part of binary is determined by TableGn. + unsigned Binary = getBinaryCodeForInstr(MI); + + // Set the conditional execution predicate + Binary |= II->getPredicate(&MI) << ARMII::CondShift; + + // Encode S bit if MI modifies CPSR. + Binary |= getAddrModeSBit(MI, TID); + + // 32x32->64bit operations have two destination registers. The number + // of register definitions will tell us if that's what we're dealing with. + unsigned OpIdx = 0; + if (TID.getNumDefs() == 2) + Binary |= getMachineOpValue (MI, OpIdx++) << ARMII::RegRdLoShift; + + // Encode Rd + Binary |= getMachineOpValue(MI, OpIdx++) << ARMII::RegRdHiShift; + + // Encode Rm + Binary |= getMachineOpValue(MI, OpIdx++); + + // Encode Rs + Binary |= getMachineOpValue(MI, OpIdx++) << ARMII::RegRsShift; + + // Many multiple instructions (e.g. MLA) have three src operands. Encode + // it as Rn (for multiply, that's in the same offset as RdLo. + if (TID.getNumOperands() > OpIdx && + !TID.OpInfo[OpIdx].isPredicate() && + !TID.OpInfo[OpIdx].isOptionalDef()) + Binary |= getMachineOpValue(MI, OpIdx) << ARMII::RegRdLoShift; + + emitWordLE(Binary); +} + +template +void Emitter::emitExtendInstruction(const MachineInstr &MI) { + const TargetInstrDesc &TID = MI.getDesc(); + + // Part of binary is determined by TableGn. + unsigned Binary = getBinaryCodeForInstr(MI); + + // Set the conditional execution predicate + Binary |= II->getPredicate(&MI) << ARMII::CondShift; + + unsigned OpIdx = 0; + + // Encode Rd + Binary |= getMachineOpValue(MI, OpIdx++) << ARMII::RegRdShift; + + const MachineOperand &MO1 = MI.getOperand(OpIdx++); + const MachineOperand &MO2 = MI.getOperand(OpIdx); + if (MO2.isReg()) { + // Two register operand form. + // Encode Rn. + Binary |= getMachineOpValue(MI, MO1) << ARMII::RegRnShift; + + // Encode Rm. + Binary |= getMachineOpValue(MI, MO2); + ++OpIdx; + } else { + Binary |= getMachineOpValue(MI, MO1); + } + + // Encode rot imm (0, 8, 16, or 24) if it has a rotate immediate operand. + if (MI.getOperand(OpIdx).isImm() && + !TID.OpInfo[OpIdx].isPredicate() && + !TID.OpInfo[OpIdx].isOptionalDef()) + Binary |= (getMachineOpValue(MI, OpIdx) / 8) << ARMII::ExtRotImmShift; + + emitWordLE(Binary); +} + +template +void Emitter::emitMiscArithInstruction(const MachineInstr &MI) { + const TargetInstrDesc &TID = MI.getDesc(); + + // Part of binary is determined by TableGn. + unsigned Binary = getBinaryCodeForInstr(MI); + + // Set the conditional execution predicate + Binary |= II->getPredicate(&MI) << ARMII::CondShift; + + unsigned OpIdx = 0; + + // Encode Rd + Binary |= getMachineOpValue(MI, OpIdx++) << ARMII::RegRdShift; + + const MachineOperand &MO = MI.getOperand(OpIdx++); + if (OpIdx == TID.getNumOperands() || + TID.OpInfo[OpIdx].isPredicate() || + TID.OpInfo[OpIdx].isOptionalDef()) { + // Encode Rm and it's done. + Binary |= getMachineOpValue(MI, MO); + emitWordLE(Binary); + return; + } + + // Encode Rn. + Binary |= getMachineOpValue(MI, MO) << ARMII::RegRnShift; + + // Encode Rm. + Binary |= getMachineOpValue(MI, OpIdx++); + + // Encode shift_imm. + unsigned ShiftAmt = MI.getOperand(OpIdx).getImm(); + assert(ShiftAmt < 32 && "shift_imm range is 0 to 31!"); + Binary |= ShiftAmt << ARMII::ShiftShift; + + emitWordLE(Binary); +} + +template +void Emitter::emitBranchInstruction(const MachineInstr &MI) { + const TargetInstrDesc &TID = MI.getDesc(); + + if (TID.Opcode == ARM::TPsoft) { + llvm_unreachable("ARM::TPsoft FIXME"); // FIXME + } + + // Part of binary is determined by TableGn. + unsigned Binary = getBinaryCodeForInstr(MI); + + // Set the conditional execution predicate + Binary |= II->getPredicate(&MI) << ARMII::CondShift; + + // Set signed_immed_24 field + Binary |= getMachineOpValue(MI, 0); + + emitWordLE(Binary); +} + +template +void Emitter::emitInlineJumpTable(unsigned JTIndex) { + // Remember the base address of the inline jump table. + uintptr_t JTBase = MCE.getCurrentPCValue(); + JTI->addJumpTableBaseAddr(JTIndex, JTBase); + DEBUG(errs() << " ** Jump Table #" << JTIndex << " @ " << (void*)JTBase + << '\n'); + + // Now emit the jump table entries. + const std::vector &MBBs = (*MJTEs)[JTIndex].MBBs; + for (unsigned i = 0, e = MBBs.size(); i != e; ++i) { + if (IsPIC) + // DestBB address - JT base. + emitMachineBasicBlock(MBBs[i], ARM::reloc_arm_pic_jt, JTBase); + else + // Absolute DestBB address. + emitMachineBasicBlock(MBBs[i], ARM::reloc_arm_absolute); + emitWordLE(0); + } +} + +template +void Emitter::emitMiscBranchInstruction(const MachineInstr &MI) { + const TargetInstrDesc &TID = MI.getDesc(); + + // Handle jump tables. + if (TID.Opcode == ARM::BR_JTr || TID.Opcode == ARM::BR_JTadd) { + // First emit a ldr pc, [] instruction. + emitDataProcessingInstruction(MI, ARM::PC); + + // Then emit the inline jump table. + unsigned JTIndex = + (TID.Opcode == ARM::BR_JTr) + ? MI.getOperand(1).getIndex() : MI.getOperand(2).getIndex(); + emitInlineJumpTable(JTIndex); + return; + } else if (TID.Opcode == ARM::BR_JTm) { + // First emit a ldr pc, [] instruction. + emitLoadStoreInstruction(MI, ARM::PC); + + // Then emit the inline jump table. + emitInlineJumpTable(MI.getOperand(3).getIndex()); + return; + } + + // Part of binary is determined by TableGn. + unsigned Binary = getBinaryCodeForInstr(MI); + + // Set the conditional execution predicate + Binary |= II->getPredicate(&MI) << ARMII::CondShift; + + if (TID.Opcode == ARM::BX_RET) + // The return register is LR. + Binary |= ARMRegisterInfo::getRegisterNumbering(ARM::LR); + else + // otherwise, set the return register + Binary |= getMachineOpValue(MI, 0); + + emitWordLE(Binary); +} + +static unsigned encodeVFPRd(const MachineInstr &MI, unsigned OpIdx) { + unsigned RegD = MI.getOperand(OpIdx).getReg(); + unsigned Binary = 0; + bool isSPVFP = false; + RegD = ARMRegisterInfo::getRegisterNumbering(RegD, &isSPVFP); + if (!isSPVFP) + Binary |= RegD << ARMII::RegRdShift; + else { + Binary |= ((RegD & 0x1E) >> 1) << ARMII::RegRdShift; + Binary |= (RegD & 0x01) << ARMII::D_BitShift; + } + return Binary; +} + +static unsigned encodeVFPRn(const MachineInstr &MI, unsigned OpIdx) { + unsigned RegN = MI.getOperand(OpIdx).getReg(); + unsigned Binary = 0; + bool isSPVFP = false; + RegN = ARMRegisterInfo::getRegisterNumbering(RegN, &isSPVFP); + if (!isSPVFP) + Binary |= RegN << ARMII::RegRnShift; + else { + Binary |= ((RegN & 0x1E) >> 1) << ARMII::RegRnShift; + Binary |= (RegN & 0x01) << ARMII::N_BitShift; + } + return Binary; +} + +static unsigned encodeVFPRm(const MachineInstr &MI, unsigned OpIdx) { + unsigned RegM = MI.getOperand(OpIdx).getReg(); + unsigned Binary = 0; + bool isSPVFP = false; + RegM = ARMRegisterInfo::getRegisterNumbering(RegM, &isSPVFP); + if (!isSPVFP) + Binary |= RegM; + else { + Binary |= ((RegM & 0x1E) >> 1); + Binary |= (RegM & 0x01) << ARMII::M_BitShift; + } + return Binary; +} + +template +void Emitter::emitVFPArithInstruction(const MachineInstr &MI) { + const TargetInstrDesc &TID = MI.getDesc(); + + // Part of binary is determined by TableGn. + unsigned Binary = getBinaryCodeForInstr(MI); + + // Set the conditional execution predicate + Binary |= II->getPredicate(&MI) << ARMII::CondShift; + + unsigned OpIdx = 0; + assert((Binary & ARMII::D_BitShift) == 0 && + (Binary & ARMII::N_BitShift) == 0 && + (Binary & ARMII::M_BitShift) == 0 && "VFP encoding bug!"); + + // Encode Dd / Sd. + Binary |= encodeVFPRd(MI, OpIdx++); + + // If this is a two-address operand, skip it, e.g. FMACD. + if (TID.getOperandConstraint(OpIdx, TOI::TIED_TO) != -1) + ++OpIdx; + + // Encode Dn / Sn. + if ((TID.TSFlags & ARMII::FormMask) == ARMII::VFPBinaryFrm) + Binary |= encodeVFPRn(MI, OpIdx++); + + if (OpIdx == TID.getNumOperands() || + TID.OpInfo[OpIdx].isPredicate() || + TID.OpInfo[OpIdx].isOptionalDef()) { + // FCMPEZD etc. has only one operand. + emitWordLE(Binary); + return; + } + + // Encode Dm / Sm. + Binary |= encodeVFPRm(MI, OpIdx); + + emitWordLE(Binary); +} + +template +void Emitter::emitVFPConversionInstruction( + const MachineInstr &MI) { + const TargetInstrDesc &TID = MI.getDesc(); + unsigned Form = TID.TSFlags & ARMII::FormMask; + + // Part of binary is determined by TableGn. + unsigned Binary = getBinaryCodeForInstr(MI); + + // Set the conditional execution predicate + Binary |= II->getPredicate(&MI) << ARMII::CondShift; + + switch (Form) { + default: break; + case ARMII::VFPConv1Frm: + case ARMII::VFPConv2Frm: + case ARMII::VFPConv3Frm: + // Encode Dd / Sd. + Binary |= encodeVFPRd(MI, 0); + break; + case ARMII::VFPConv4Frm: + // Encode Dn / Sn. + Binary |= encodeVFPRn(MI, 0); + break; + case ARMII::VFPConv5Frm: + // Encode Dm / Sm. + Binary |= encodeVFPRm(MI, 0); + break; + } + + switch (Form) { + default: break; + case ARMII::VFPConv1Frm: + // Encode Dm / Sm. + Binary |= encodeVFPRm(MI, 1); + break; + case ARMII::VFPConv2Frm: + case ARMII::VFPConv3Frm: + // Encode Dn / Sn. + Binary |= encodeVFPRn(MI, 1); + break; + case ARMII::VFPConv4Frm: + case ARMII::VFPConv5Frm: + // Encode Dd / Sd. + Binary |= encodeVFPRd(MI, 1); + break; + } + + if (Form == ARMII::VFPConv5Frm) + // Encode Dn / Sn. + Binary |= encodeVFPRn(MI, 2); + else if (Form == ARMII::VFPConv3Frm) + // Encode Dm / Sm. + Binary |= encodeVFPRm(MI, 2); + + emitWordLE(Binary); +} + +template +void Emitter::emitVFPLoadStoreInstruction(const MachineInstr &MI) { + // Part of binary is determined by TableGn. + unsigned Binary = getBinaryCodeForInstr(MI); + + // Set the conditional execution predicate + Binary |= II->getPredicate(&MI) << ARMII::CondShift; + + unsigned OpIdx = 0; + + // Encode Dd / Sd. + Binary |= encodeVFPRd(MI, OpIdx++); + + // Encode address base. + const MachineOperand &Base = MI.getOperand(OpIdx++); + Binary |= getMachineOpValue(MI, Base) << ARMII::RegRnShift; + + // If there is a non-zero immediate offset, encode it. + if (Base.isReg()) { + const MachineOperand &Offset = MI.getOperand(OpIdx); + if (unsigned ImmOffs = ARM_AM::getAM5Offset(Offset.getImm())) { + if (ARM_AM::getAM5Op(Offset.getImm()) == ARM_AM::add) + Binary |= 1 << ARMII::U_BitShift; + Binary |= ImmOffs; + emitWordLE(Binary); + return; + } + } + + // If immediate offset is omitted, default to +0. + Binary |= 1 << ARMII::U_BitShift; + + emitWordLE(Binary); +} + +template +void Emitter::emitVFPLoadStoreMultipleInstruction( + const MachineInstr &MI) { + // Part of binary is determined by TableGn. + unsigned Binary = getBinaryCodeForInstr(MI); + + // Set the conditional execution predicate + Binary |= II->getPredicate(&MI) << ARMII::CondShift; + + // Set base address operand + Binary |= getMachineOpValue(MI, 0) << ARMII::RegRnShift; + + // Set addressing mode by modifying bits U(23) and P(24) + const MachineOperand &MO = MI.getOperand(1); + Binary |= getAddrModeUPBits(ARM_AM::getAM5SubMode(MO.getImm())); + + // Set bit W(21) + if (ARM_AM::getAM5WBFlag(MO.getImm())) + Binary |= 0x1 << ARMII::W_BitShift; + + // First register is encoded in Dd. + Binary |= encodeVFPRd(MI, 5); + + // Number of registers are encoded in offset field. + unsigned NumRegs = 1; + for (unsigned i = 6, e = MI.getNumOperands(); i != e; ++i) { + const MachineOperand &MO = MI.getOperand(i); + if (!MO.isReg() || MO.isImplicit()) + break; + ++NumRegs; + } + Binary |= NumRegs * 2; + + emitWordLE(Binary); +} + +template +void Emitter::emitMiscInstruction(const MachineInstr &MI) { + // Part of binary is determined by TableGn. + unsigned Binary = getBinaryCodeForInstr(MI); + + // Set the conditional execution predicate + Binary |= II->getPredicate(&MI) << ARMII::CondShift; + + emitWordLE(Binary); +} + +#include "ARMGenCodeEmitter.inc" diff --git a/libclamav/c++/llvm/lib/Target/ARM/ARMConstantIslandPass.cpp b/libclamav/c++/llvm/lib/Target/ARM/ARMConstantIslandPass.cpp new file mode 100644 index 000000000..e59a315a4 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/ARM/ARMConstantIslandPass.cpp @@ -0,0 +1,1821 @@ +//===-- ARMConstantIslandPass.cpp - ARM constant islands --------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains a pass that splits the constant pool up into 'islands' +// which are scattered through-out the function. This is required due to the +// limited pc-relative displacements that ARM has. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "arm-cp-islands" +#include "ARM.h" +#include "ARMAddressingModes.h" +#include "ARMMachineFunctionInfo.h" +#include "ARMInstrInfo.h" +#include "llvm/CodeGen/MachineConstantPool.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineJumpTableInfo.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/ADT/SmallSet.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/Support/CommandLine.h" +#include +using namespace llvm; + +STATISTIC(NumCPEs, "Number of constpool entries"); +STATISTIC(NumSplit, "Number of uncond branches inserted"); +STATISTIC(NumCBrFixed, "Number of cond branches fixed"); +STATISTIC(NumUBrFixed, "Number of uncond branches fixed"); +STATISTIC(NumTBs, "Number of table branches generated"); +STATISTIC(NumT2CPShrunk, "Number of Thumb2 constantpool instructions shrunk"); +STATISTIC(NumT2BrShrunk, "Number of Thumb2 immediate branches shrunk"); +STATISTIC(NumCBZ, "Number of CBZ / CBNZ formed"); +STATISTIC(NumJTMoved, "Number of jump table destination blocks moved"); +STATISTIC(NumJTInserted, "Number of jump table intermediate blocks inserted"); + + +static cl::opt +AdjustJumpTableBlocks("arm-adjust-jump-tables", cl::Hidden, cl::init(true), + cl::desc("Adjust basic block layout to better use TB[BH]")); + +namespace { + /// ARMConstantIslands - Due to limited PC-relative displacements, ARM + /// requires constant pool entries to be scattered among the instructions + /// inside a function. To do this, it completely ignores the normal LLVM + /// constant pool; instead, it places constants wherever it feels like with + /// special instructions. + /// + /// The terminology used in this pass includes: + /// Islands - Clumps of constants placed in the function. + /// Water - Potential places where an island could be formed. + /// CPE - A constant pool entry that has been placed somewhere, which + /// tracks a list of users. + class ARMConstantIslands : public MachineFunctionPass { + /// BBSizes - The size of each MachineBasicBlock in bytes of code, indexed + /// by MBB Number. The two-byte pads required for Thumb alignment are + /// counted as part of the following block (i.e., the offset and size for + /// a padded block will both be ==2 mod 4). + std::vector BBSizes; + + /// BBOffsets - the offset of each MBB in bytes, starting from 0. + /// The two-byte pads required for Thumb alignment are counted as part of + /// the following block. + std::vector BBOffsets; + + /// WaterList - A sorted list of basic blocks where islands could be placed + /// (i.e. blocks that don't fall through to the following block, due + /// to a return, unreachable, or unconditional branch). + std::vector WaterList; + + /// NewWaterList - The subset of WaterList that was created since the + /// previous iteration by inserting unconditional branches. + SmallSet NewWaterList; + + typedef std::vector::iterator water_iterator; + + /// CPUser - One user of a constant pool, keeping the machine instruction + /// pointer, the constant pool being referenced, and the max displacement + /// allowed from the instruction to the CP. The HighWaterMark records the + /// highest basic block where a new CPEntry can be placed. To ensure this + /// pass terminates, the CP entries are initially placed at the end of the + /// function and then move monotonically to lower addresses. The + /// exception to this rule is when the current CP entry for a particular + /// CPUser is out of range, but there is another CP entry for the same + /// constant value in range. We want to use the existing in-range CP + /// entry, but if it later moves out of range, the search for new water + /// should resume where it left off. The HighWaterMark is used to record + /// that point. + struct CPUser { + MachineInstr *MI; + MachineInstr *CPEMI; + MachineBasicBlock *HighWaterMark; + unsigned MaxDisp; + bool NegOk; + bool IsSoImm; + CPUser(MachineInstr *mi, MachineInstr *cpemi, unsigned maxdisp, + bool neg, bool soimm) + : MI(mi), CPEMI(cpemi), MaxDisp(maxdisp), NegOk(neg), IsSoImm(soimm) { + HighWaterMark = CPEMI->getParent(); + } + }; + + /// CPUsers - Keep track of all of the machine instructions that use various + /// constant pools and their max displacement. + std::vector CPUsers; + + /// CPEntry - One per constant pool entry, keeping the machine instruction + /// pointer, the constpool index, and the number of CPUser's which + /// reference this entry. + struct CPEntry { + MachineInstr *CPEMI; + unsigned CPI; + unsigned RefCount; + CPEntry(MachineInstr *cpemi, unsigned cpi, unsigned rc = 0) + : CPEMI(cpemi), CPI(cpi), RefCount(rc) {} + }; + + /// CPEntries - Keep track of all of the constant pool entry machine + /// instructions. For each original constpool index (i.e. those that + /// existed upon entry to this pass), it keeps a vector of entries. + /// Original elements are cloned as we go along; the clones are + /// put in the vector of the original element, but have distinct CPIs. + std::vector > CPEntries; + + /// ImmBranch - One per immediate branch, keeping the machine instruction + /// pointer, conditional or unconditional, the max displacement, + /// and (if isCond is true) the corresponding unconditional branch + /// opcode. + struct ImmBranch { + MachineInstr *MI; + unsigned MaxDisp : 31; + bool isCond : 1; + int UncondBr; + ImmBranch(MachineInstr *mi, unsigned maxdisp, bool cond, int ubr) + : MI(mi), MaxDisp(maxdisp), isCond(cond), UncondBr(ubr) {} + }; + + /// ImmBranches - Keep track of all the immediate branch instructions. + /// + std::vector ImmBranches; + + /// PushPopMIs - Keep track of all the Thumb push / pop instructions. + /// + SmallVector PushPopMIs; + + /// T2JumpTables - Keep track of all the Thumb2 jumptable instructions. + SmallVector T2JumpTables; + + /// HasFarJump - True if any far jump instruction has been emitted during + /// the branch fix up pass. + bool HasFarJump; + + /// HasInlineAsm - True if the function contains inline assembly. + bool HasInlineAsm; + + const TargetInstrInfo *TII; + const ARMSubtarget *STI; + ARMFunctionInfo *AFI; + bool isThumb; + bool isThumb1; + bool isThumb2; + public: + static char ID; + ARMConstantIslands() : MachineFunctionPass(&ID) {} + + virtual bool runOnMachineFunction(MachineFunction &MF); + + virtual const char *getPassName() const { + return "ARM constant island placement and branch shortening pass"; + } + + private: + void DoInitialPlacement(MachineFunction &MF, + std::vector &CPEMIs); + CPEntry *findConstPoolEntry(unsigned CPI, const MachineInstr *CPEMI); + void JumpTableFunctionScan(MachineFunction &MF); + void InitialFunctionScan(MachineFunction &MF, + const std::vector &CPEMIs); + MachineBasicBlock *SplitBlockBeforeInstr(MachineInstr *MI); + void UpdateForInsertedWaterBlock(MachineBasicBlock *NewBB); + void AdjustBBOffsetsAfter(MachineBasicBlock *BB, int delta); + bool DecrementOldEntry(unsigned CPI, MachineInstr* CPEMI); + int LookForExistingCPEntry(CPUser& U, unsigned UserOffset); + bool LookForWater(CPUser&U, unsigned UserOffset, water_iterator &WaterIter); + void CreateNewWater(unsigned CPUserIndex, unsigned UserOffset, + MachineBasicBlock *&NewMBB); + bool HandleConstantPoolUser(MachineFunction &MF, unsigned CPUserIndex); + void RemoveDeadCPEMI(MachineInstr *CPEMI); + bool RemoveUnusedCPEntries(); + bool CPEIsInRange(MachineInstr *MI, unsigned UserOffset, + MachineInstr *CPEMI, unsigned Disp, bool NegOk, + bool DoDump = false); + bool WaterIsInRange(unsigned UserOffset, MachineBasicBlock *Water, + CPUser &U); + bool OffsetIsInRange(unsigned UserOffset, unsigned TrialOffset, + unsigned Disp, bool NegativeOK, bool IsSoImm = false); + bool BBIsInRange(MachineInstr *MI, MachineBasicBlock *BB, unsigned Disp); + bool FixUpImmediateBr(MachineFunction &MF, ImmBranch &Br); + bool FixUpConditionalBr(MachineFunction &MF, ImmBranch &Br); + bool FixUpUnconditionalBr(MachineFunction &MF, ImmBranch &Br); + bool UndoLRSpillRestore(); + bool OptimizeThumb2Instructions(MachineFunction &MF); + bool OptimizeThumb2Branches(MachineFunction &MF); + bool ReorderThumb2JumpTables(MachineFunction &MF); + bool OptimizeThumb2JumpTables(MachineFunction &MF); + MachineBasicBlock *AdjustJTTargetBlockForward(MachineBasicBlock *BB, + MachineBasicBlock *JTBB); + + unsigned GetOffsetOf(MachineInstr *MI) const; + void dumpBBs(); + void verify(MachineFunction &MF); + }; + char ARMConstantIslands::ID = 0; +} + +/// verify - check BBOffsets, BBSizes, alignment of islands +void ARMConstantIslands::verify(MachineFunction &MF) { + assert(BBOffsets.size() == BBSizes.size()); + for (unsigned i = 1, e = BBOffsets.size(); i != e; ++i) + assert(BBOffsets[i-1]+BBSizes[i-1] == BBOffsets[i]); + if (!isThumb) + return; +#ifndef NDEBUG + for (MachineFunction::iterator MBBI = MF.begin(), E = MF.end(); + MBBI != E; ++MBBI) { + MachineBasicBlock *MBB = MBBI; + if (!MBB->empty() && + MBB->begin()->getOpcode() == ARM::CONSTPOOL_ENTRY) { + unsigned MBBId = MBB->getNumber(); + assert(HasInlineAsm || + (BBOffsets[MBBId]%4 == 0 && BBSizes[MBBId]%4 == 0) || + (BBOffsets[MBBId]%4 != 0 && BBSizes[MBBId]%4 != 0)); + } + } + for (unsigned i = 0, e = CPUsers.size(); i != e; ++i) { + CPUser &U = CPUsers[i]; + unsigned UserOffset = GetOffsetOf(U.MI) + (isThumb ? 4 : 8); + unsigned CPEOffset = GetOffsetOf(U.CPEMI); + unsigned Disp = UserOffset < CPEOffset ? CPEOffset - UserOffset : + UserOffset - CPEOffset; + assert(Disp <= U.MaxDisp || "Constant pool entry out of range!"); + } +#endif +} + +/// print block size and offset information - debugging +void ARMConstantIslands::dumpBBs() { + for (unsigned J = 0, E = BBOffsets.size(); J !=E; ++J) { + DEBUG(errs() << "block " << J << " offset " << BBOffsets[J] + << " size " << BBSizes[J] << "\n"); + } +} + +/// createARMConstantIslandPass - returns an instance of the constpool +/// island pass. +FunctionPass *llvm::createARMConstantIslandPass() { + return new ARMConstantIslands(); +} + +bool ARMConstantIslands::runOnMachineFunction(MachineFunction &MF) { + MachineConstantPool &MCP = *MF.getConstantPool(); + + TII = MF.getTarget().getInstrInfo(); + AFI = MF.getInfo(); + STI = &MF.getTarget().getSubtarget(); + + isThumb = AFI->isThumbFunction(); + isThumb1 = AFI->isThumb1OnlyFunction(); + isThumb2 = AFI->isThumb2Function(); + + HasFarJump = false; + HasInlineAsm = false; + + // Renumber all of the machine basic blocks in the function, guaranteeing that + // the numbers agree with the position of the block in the function. + MF.RenumberBlocks(); + + // Try to reorder and otherwise adjust the block layout to make good use + // of the TB[BH] instructions. + bool MadeChange = false; + if (isThumb2 && AdjustJumpTableBlocks) { + JumpTableFunctionScan(MF); + MadeChange |= ReorderThumb2JumpTables(MF); + // Data is out of date, so clear it. It'll be re-computed later. + T2JumpTables.clear(); + // Blocks may have shifted around. Keep the numbering up to date. + MF.RenumberBlocks(); + } + + // Thumb1 functions containing constant pools get 4-byte alignment. + // This is so we can keep exact track of where the alignment padding goes. + + // Set default. Thumb1 function is 2-byte aligned, ARM and Thumb2 are 4-byte + // aligned. + AFI->setAlign(isThumb1 ? 1U : 2U); + + // Perform the initial placement of the constant pool entries. To start with, + // we put them all at the end of the function. + std::vector CPEMIs; + if (!MCP.isEmpty()) { + DoInitialPlacement(MF, CPEMIs); + if (isThumb1) + AFI->setAlign(2U); + } + + /// The next UID to take is the first unused one. + AFI->initConstPoolEntryUId(CPEMIs.size()); + + // Do the initial scan of the function, building up information about the + // sizes of each block, the location of all the water, and finding all of the + // constant pool users. + InitialFunctionScan(MF, CPEMIs); + CPEMIs.clear(); + + /// Remove dead constant pool entries. + RemoveUnusedCPEntries(); + + // Iteratively place constant pool entries and fix up branches until there + // is no change. + unsigned NoCPIters = 0, NoBRIters = 0; + while (true) { + bool CPChange = false; + for (unsigned i = 0, e = CPUsers.size(); i != e; ++i) + CPChange |= HandleConstantPoolUser(MF, i); + if (CPChange && ++NoCPIters > 30) + llvm_unreachable("Constant Island pass failed to converge!"); + DEBUG(dumpBBs()); + + // Clear NewWaterList now. If we split a block for branches, it should + // appear as "new water" for the next iteration of constant pool placement. + NewWaterList.clear(); + + bool BRChange = false; + for (unsigned i = 0, e = ImmBranches.size(); i != e; ++i) + BRChange |= FixUpImmediateBr(MF, ImmBranches[i]); + if (BRChange && ++NoBRIters > 30) + llvm_unreachable("Branch Fix Up pass failed to converge!"); + DEBUG(dumpBBs()); + + if (!CPChange && !BRChange) + break; + MadeChange = true; + } + + // Shrink 32-bit Thumb2 branch, load, and store instructions. + if (isThumb2) + MadeChange |= OptimizeThumb2Instructions(MF); + + // After a while, this might be made debug-only, but it is not expensive. + verify(MF); + + // If LR has been forced spilled and no far jumps (i.e. BL) has been issued. + // Undo the spill / restore of LR if possible. + if (isThumb && !HasFarJump && AFI->isLRSpilledForFarJump()) + MadeChange |= UndoLRSpillRestore(); + + BBSizes.clear(); + BBOffsets.clear(); + WaterList.clear(); + CPUsers.clear(); + CPEntries.clear(); + ImmBranches.clear(); + PushPopMIs.clear(); + T2JumpTables.clear(); + + return MadeChange; +} + +/// DoInitialPlacement - Perform the initial placement of the constant pool +/// entries. To start with, we put them all at the end of the function. +void ARMConstantIslands::DoInitialPlacement(MachineFunction &MF, + std::vector &CPEMIs) { + // Create the basic block to hold the CPE's. + MachineBasicBlock *BB = MF.CreateMachineBasicBlock(); + MF.push_back(BB); + + // Add all of the constants from the constant pool to the end block, use an + // identity mapping of CPI's to CPE's. + const std::vector &CPs = + MF.getConstantPool()->getConstants(); + + const TargetData &TD = *MF.getTarget().getTargetData(); + for (unsigned i = 0, e = CPs.size(); i != e; ++i) { + unsigned Size = TD.getTypeAllocSize(CPs[i].getType()); + // Verify that all constant pool entries are a multiple of 4 bytes. If not, + // we would have to pad them out or something so that instructions stay + // aligned. + assert((Size & 3) == 0 && "CP Entry not multiple of 4 bytes!"); + MachineInstr *CPEMI = + BuildMI(BB, DebugLoc::getUnknownLoc(), TII->get(ARM::CONSTPOOL_ENTRY)) + .addImm(i).addConstantPoolIndex(i).addImm(Size); + CPEMIs.push_back(CPEMI); + + // Add a new CPEntry, but no corresponding CPUser yet. + std::vector CPEs; + CPEs.push_back(CPEntry(CPEMI, i)); + CPEntries.push_back(CPEs); + NumCPEs++; + DEBUG(errs() << "Moved CPI#" << i << " to end of function as #" << i + << "\n"); + } +} + +/// BBHasFallthrough - Return true if the specified basic block can fallthrough +/// into the block immediately after it. +static bool BBHasFallthrough(MachineBasicBlock *MBB) { + // Get the next machine basic block in the function. + MachineFunction::iterator MBBI = MBB; + if (next(MBBI) == MBB->getParent()->end()) // Can't fall off end of function. + return false; + + MachineBasicBlock *NextBB = next(MBBI); + for (MachineBasicBlock::succ_iterator I = MBB->succ_begin(), + E = MBB->succ_end(); I != E; ++I) + if (*I == NextBB) + return true; + + return false; +} + +/// findConstPoolEntry - Given the constpool index and CONSTPOOL_ENTRY MI, +/// look up the corresponding CPEntry. +ARMConstantIslands::CPEntry +*ARMConstantIslands::findConstPoolEntry(unsigned CPI, + const MachineInstr *CPEMI) { + std::vector &CPEs = CPEntries[CPI]; + // Number of entries per constpool index should be small, just do a + // linear search. + for (unsigned i = 0, e = CPEs.size(); i != e; ++i) { + if (CPEs[i].CPEMI == CPEMI) + return &CPEs[i]; + } + return NULL; +} + +/// JumpTableFunctionScan - Do a scan of the function, building up +/// information about the sizes of each block and the locations of all +/// the jump tables. +void ARMConstantIslands::JumpTableFunctionScan(MachineFunction &MF) { + for (MachineFunction::iterator MBBI = MF.begin(), E = MF.end(); + MBBI != E; ++MBBI) { + MachineBasicBlock &MBB = *MBBI; + + for (MachineBasicBlock::iterator I = MBB.begin(), E = MBB.end(); + I != E; ++I) + if (I->getDesc().isBranch() && I->getOpcode() == ARM::t2BR_JT) + T2JumpTables.push_back(I); + } +} + +/// InitialFunctionScan - Do the initial scan of the function, building up +/// information about the sizes of each block, the location of all the water, +/// and finding all of the constant pool users. +void ARMConstantIslands::InitialFunctionScan(MachineFunction &MF, + const std::vector &CPEMIs) { + // First thing, see if the function has any inline assembly in it. If so, + // we have to be conservative about alignment assumptions, as we don't + // know for sure the size of any instructions in the inline assembly. + for (MachineFunction::iterator MBBI = MF.begin(), E = MF.end(); + MBBI != E; ++MBBI) { + MachineBasicBlock &MBB = *MBBI; + for (MachineBasicBlock::iterator I = MBB.begin(), E = MBB.end(); + I != E; ++I) + if (I->getOpcode() == ARM::INLINEASM) + HasInlineAsm = true; + } + + // Now go back through the instructions and build up our data structures + unsigned Offset = 0; + for (MachineFunction::iterator MBBI = MF.begin(), E = MF.end(); + MBBI != E; ++MBBI) { + MachineBasicBlock &MBB = *MBBI; + + // If this block doesn't fall through into the next MBB, then this is + // 'water' that a constant pool island could be placed. + if (!BBHasFallthrough(&MBB)) + WaterList.push_back(&MBB); + + unsigned MBBSize = 0; + for (MachineBasicBlock::iterator I = MBB.begin(), E = MBB.end(); + I != E; ++I) { + // Add instruction size to MBBSize. + MBBSize += TII->GetInstSizeInBytes(I); + + int Opc = I->getOpcode(); + if (I->getDesc().isBranch()) { + bool isCond = false; + unsigned Bits = 0; + unsigned Scale = 1; + int UOpc = Opc; + switch (Opc) { + default: + continue; // Ignore other JT branches + case ARM::tBR_JTr: + // A Thumb1 table jump may involve padding; for the offsets to + // be right, functions containing these must be 4-byte aligned. + AFI->setAlign(2U); + if ((Offset+MBBSize)%4 != 0 || HasInlineAsm) + // FIXME: Add a pseudo ALIGN instruction instead. + MBBSize += 2; // padding + continue; // Does not get an entry in ImmBranches + case ARM::t2BR_JT: + T2JumpTables.push_back(I); + continue; // Does not get an entry in ImmBranches + case ARM::Bcc: + isCond = true; + UOpc = ARM::B; + // Fallthrough + case ARM::B: + Bits = 24; + Scale = 4; + break; + case ARM::tBcc: + isCond = true; + UOpc = ARM::tB; + Bits = 8; + Scale = 2; + break; + case ARM::tB: + Bits = 11; + Scale = 2; + break; + case ARM::t2Bcc: + isCond = true; + UOpc = ARM::t2B; + Bits = 20; + Scale = 2; + break; + case ARM::t2B: + Bits = 24; + Scale = 2; + break; + } + + // Record this immediate branch. + unsigned MaxOffs = ((1 << (Bits-1))-1) * Scale; + ImmBranches.push_back(ImmBranch(I, MaxOffs, isCond, UOpc)); + } + + if (Opc == ARM::tPUSH || Opc == ARM::tPOP_RET) + PushPopMIs.push_back(I); + + if (Opc == ARM::CONSTPOOL_ENTRY) + continue; + + // Scan the instructions for constant pool operands. + for (unsigned op = 0, e = I->getNumOperands(); op != e; ++op) + if (I->getOperand(op).isCPI()) { + // We found one. The addressing mode tells us the max displacement + // from the PC that this instruction permits. + + // Basic size info comes from the TSFlags field. + unsigned Bits = 0; + unsigned Scale = 1; + bool NegOk = false; + bool IsSoImm = false; + + switch (Opc) { + default: + llvm_unreachable("Unknown addressing mode for CP reference!"); + break; + + // Taking the address of a CP entry. + case ARM::LEApcrel: + // This takes a SoImm, which is 8 bit immediate rotated. We'll + // pretend the maximum offset is 255 * 4. Since each instruction + // 4 byte wide, this is always correct. We'll check for other + // displacements that fits in a SoImm as well. + Bits = 8; + Scale = 4; + NegOk = true; + IsSoImm = true; + break; + case ARM::t2LEApcrel: + Bits = 12; + NegOk = true; + break; + case ARM::tLEApcrel: + Bits = 8; + Scale = 4; + break; + + case ARM::LDR: + case ARM::LDRcp: + case ARM::t2LDRpci: + Bits = 12; // +-offset_12 + NegOk = true; + break; + + case ARM::tLDRpci: + case ARM::tLDRcp: + Bits = 8; + Scale = 4; // +(offset_8*4) + break; + + case ARM::VLDRD: + case ARM::VLDRS: + Bits = 8; + Scale = 4; // +-(offset_8*4) + NegOk = true; + break; + } + + // Remember that this is a user of a CP entry. + unsigned CPI = I->getOperand(op).getIndex(); + MachineInstr *CPEMI = CPEMIs[CPI]; + unsigned MaxOffs = ((1 << Bits)-1) * Scale; + CPUsers.push_back(CPUser(I, CPEMI, MaxOffs, NegOk, IsSoImm)); + + // Increment corresponding CPEntry reference count. + CPEntry *CPE = findConstPoolEntry(CPI, CPEMI); + assert(CPE && "Cannot find a corresponding CPEntry!"); + CPE->RefCount++; + + // Instructions can only use one CP entry, don't bother scanning the + // rest of the operands. + break; + } + } + + // In thumb mode, if this block is a constpool island, we may need padding + // so it's aligned on 4 byte boundary. + if (isThumb && + !MBB.empty() && + MBB.begin()->getOpcode() == ARM::CONSTPOOL_ENTRY && + ((Offset%4) != 0 || HasInlineAsm)) + MBBSize += 2; + + BBSizes.push_back(MBBSize); + BBOffsets.push_back(Offset); + Offset += MBBSize; + } +} + +/// GetOffsetOf - Return the current offset of the specified machine instruction +/// from the start of the function. This offset changes as stuff is moved +/// around inside the function. +unsigned ARMConstantIslands::GetOffsetOf(MachineInstr *MI) const { + MachineBasicBlock *MBB = MI->getParent(); + + // The offset is composed of two things: the sum of the sizes of all MBB's + // before this instruction's block, and the offset from the start of the block + // it is in. + unsigned Offset = BBOffsets[MBB->getNumber()]; + + // If we're looking for a CONSTPOOL_ENTRY in Thumb, see if this block has + // alignment padding, and compensate if so. + if (isThumb && + MI->getOpcode() == ARM::CONSTPOOL_ENTRY && + (Offset%4 != 0 || HasInlineAsm)) + Offset += 2; + + // Sum instructions before MI in MBB. + for (MachineBasicBlock::iterator I = MBB->begin(); ; ++I) { + assert(I != MBB->end() && "Didn't find MI in its own basic block?"); + if (&*I == MI) return Offset; + Offset += TII->GetInstSizeInBytes(I); + } +} + +/// CompareMBBNumbers - Little predicate function to sort the WaterList by MBB +/// ID. +static bool CompareMBBNumbers(const MachineBasicBlock *LHS, + const MachineBasicBlock *RHS) { + return LHS->getNumber() < RHS->getNumber(); +} + +/// UpdateForInsertedWaterBlock - When a block is newly inserted into the +/// machine function, it upsets all of the block numbers. Renumber the blocks +/// and update the arrays that parallel this numbering. +void ARMConstantIslands::UpdateForInsertedWaterBlock(MachineBasicBlock *NewBB) { + // Renumber the MBB's to keep them consequtive. + NewBB->getParent()->RenumberBlocks(NewBB); + + // Insert a size into BBSizes to align it properly with the (newly + // renumbered) block numbers. + BBSizes.insert(BBSizes.begin()+NewBB->getNumber(), 0); + + // Likewise for BBOffsets. + BBOffsets.insert(BBOffsets.begin()+NewBB->getNumber(), 0); + + // Next, update WaterList. Specifically, we need to add NewMBB as having + // available water after it. + water_iterator IP = + std::lower_bound(WaterList.begin(), WaterList.end(), NewBB, + CompareMBBNumbers); + WaterList.insert(IP, NewBB); +} + + +/// Split the basic block containing MI into two blocks, which are joined by +/// an unconditional branch. Update data structures and renumber blocks to +/// account for this change and returns the newly created block. +MachineBasicBlock *ARMConstantIslands::SplitBlockBeforeInstr(MachineInstr *MI) { + MachineBasicBlock *OrigBB = MI->getParent(); + MachineFunction &MF = *OrigBB->getParent(); + + // Create a new MBB for the code after the OrigBB. + MachineBasicBlock *NewBB = + MF.CreateMachineBasicBlock(OrigBB->getBasicBlock()); + MachineFunction::iterator MBBI = OrigBB; ++MBBI; + MF.insert(MBBI, NewBB); + + // Splice the instructions starting with MI over to NewBB. + NewBB->splice(NewBB->end(), OrigBB, MI, OrigBB->end()); + + // Add an unconditional branch from OrigBB to NewBB. + // Note the new unconditional branch is not being recorded. + // There doesn't seem to be meaningful DebugInfo available; this doesn't + // correspond to anything in the source. + unsigned Opc = isThumb ? (isThumb2 ? ARM::t2B : ARM::tB) : ARM::B; + BuildMI(OrigBB, DebugLoc::getUnknownLoc(), TII->get(Opc)).addMBB(NewBB); + NumSplit++; + + // Update the CFG. All succs of OrigBB are now succs of NewBB. + while (!OrigBB->succ_empty()) { + MachineBasicBlock *Succ = *OrigBB->succ_begin(); + OrigBB->removeSuccessor(Succ); + NewBB->addSuccessor(Succ); + + // This pass should be run after register allocation, so there should be no + // PHI nodes to update. + assert((Succ->empty() || Succ->begin()->getOpcode() != TargetInstrInfo::PHI) + && "PHI nodes should be eliminated by now!"); + } + + // OrigBB branches to NewBB. + OrigBB->addSuccessor(NewBB); + + // Update internal data structures to account for the newly inserted MBB. + // This is almost the same as UpdateForInsertedWaterBlock, except that + // the Water goes after OrigBB, not NewBB. + MF.RenumberBlocks(NewBB); + + // Insert a size into BBSizes to align it properly with the (newly + // renumbered) block numbers. + BBSizes.insert(BBSizes.begin()+NewBB->getNumber(), 0); + + // Likewise for BBOffsets. + BBOffsets.insert(BBOffsets.begin()+NewBB->getNumber(), 0); + + // Next, update WaterList. Specifically, we need to add OrigMBB as having + // available water after it (but not if it's already there, which happens + // when splitting before a conditional branch that is followed by an + // unconditional branch - in that case we want to insert NewBB). + water_iterator IP = + std::lower_bound(WaterList.begin(), WaterList.end(), OrigBB, + CompareMBBNumbers); + MachineBasicBlock* WaterBB = *IP; + if (WaterBB == OrigBB) + WaterList.insert(next(IP), NewBB); + else + WaterList.insert(IP, OrigBB); + NewWaterList.insert(OrigBB); + + // Figure out how large the first NewMBB is. (It cannot + // contain a constpool_entry or tablejump.) + unsigned NewBBSize = 0; + for (MachineBasicBlock::iterator I = NewBB->begin(), E = NewBB->end(); + I != E; ++I) + NewBBSize += TII->GetInstSizeInBytes(I); + + unsigned OrigBBI = OrigBB->getNumber(); + unsigned NewBBI = NewBB->getNumber(); + // Set the size of NewBB in BBSizes. + BBSizes[NewBBI] = NewBBSize; + + // We removed instructions from UserMBB, subtract that off from its size. + // Add 2 or 4 to the block to count the unconditional branch we added to it. + int delta = isThumb1 ? 2 : 4; + BBSizes[OrigBBI] -= NewBBSize - delta; + + // ...and adjust BBOffsets for NewBB accordingly. + BBOffsets[NewBBI] = BBOffsets[OrigBBI] + BBSizes[OrigBBI]; + + // All BBOffsets following these blocks must be modified. + AdjustBBOffsetsAfter(NewBB, delta); + + return NewBB; +} + +/// OffsetIsInRange - Checks whether UserOffset (the location of a constant pool +/// reference) is within MaxDisp of TrialOffset (a proposed location of a +/// constant pool entry). +bool ARMConstantIslands::OffsetIsInRange(unsigned UserOffset, + unsigned TrialOffset, unsigned MaxDisp, + bool NegativeOK, bool IsSoImm) { + // On Thumb offsets==2 mod 4 are rounded down by the hardware for + // purposes of the displacement computation; compensate for that here. + // Effectively, the valid range of displacements is 2 bytes smaller for such + // references. + unsigned TotalAdj = 0; + if (isThumb && UserOffset%4 !=0) { + UserOffset -= 2; + TotalAdj = 2; + } + // CPEs will be rounded up to a multiple of 4. + if (isThumb && TrialOffset%4 != 0) { + TrialOffset += 2; + TotalAdj += 2; + } + + // In Thumb2 mode, later branch adjustments can shift instructions up and + // cause alignment change. In the worst case scenario this can cause the + // user's effective address to be subtracted by 2 and the CPE's address to + // be plus 2. + if (isThumb2 && TotalAdj != 4) + MaxDisp -= (4 - TotalAdj); + + if (UserOffset <= TrialOffset) { + // User before the Trial. + if (TrialOffset - UserOffset <= MaxDisp) + return true; + // FIXME: Make use full range of soimm values. + } else if (NegativeOK) { + if (UserOffset - TrialOffset <= MaxDisp) + return true; + // FIXME: Make use full range of soimm values. + } + return false; +} + +/// WaterIsInRange - Returns true if a CPE placed after the specified +/// Water (a basic block) will be in range for the specific MI. + +bool ARMConstantIslands::WaterIsInRange(unsigned UserOffset, + MachineBasicBlock* Water, CPUser &U) { + unsigned MaxDisp = U.MaxDisp; + unsigned CPEOffset = BBOffsets[Water->getNumber()] + + BBSizes[Water->getNumber()]; + + // If the CPE is to be inserted before the instruction, that will raise + // the offset of the instruction. + if (CPEOffset < UserOffset) + UserOffset += U.CPEMI->getOperand(2).getImm(); + + return OffsetIsInRange(UserOffset, CPEOffset, MaxDisp, U.NegOk, U.IsSoImm); +} + +/// CPEIsInRange - Returns true if the distance between specific MI and +/// specific ConstPool entry instruction can fit in MI's displacement field. +bool ARMConstantIslands::CPEIsInRange(MachineInstr *MI, unsigned UserOffset, + MachineInstr *CPEMI, unsigned MaxDisp, + bool NegOk, bool DoDump) { + unsigned CPEOffset = GetOffsetOf(CPEMI); + assert((CPEOffset%4 == 0 || HasInlineAsm) && "Misaligned CPE"); + + if (DoDump) { + DEBUG(errs() << "User of CPE#" << CPEMI->getOperand(0).getImm() + << " max delta=" << MaxDisp + << " insn address=" << UserOffset + << " CPE address=" << CPEOffset + << " offset=" << int(CPEOffset-UserOffset) << "\t" << *MI); + } + + return OffsetIsInRange(UserOffset, CPEOffset, MaxDisp, NegOk); +} + +#ifndef NDEBUG +/// BBIsJumpedOver - Return true of the specified basic block's only predecessor +/// unconditionally branches to its only successor. +static bool BBIsJumpedOver(MachineBasicBlock *MBB) { + if (MBB->pred_size() != 1 || MBB->succ_size() != 1) + return false; + + MachineBasicBlock *Succ = *MBB->succ_begin(); + MachineBasicBlock *Pred = *MBB->pred_begin(); + MachineInstr *PredMI = &Pred->back(); + if (PredMI->getOpcode() == ARM::B || PredMI->getOpcode() == ARM::tB + || PredMI->getOpcode() == ARM::t2B) + return PredMI->getOperand(0).getMBB() == Succ; + return false; +} +#endif // NDEBUG + +void ARMConstantIslands::AdjustBBOffsetsAfter(MachineBasicBlock *BB, + int delta) { + MachineFunction::iterator MBBI = BB; MBBI = next(MBBI); + for(unsigned i = BB->getNumber()+1, e = BB->getParent()->getNumBlockIDs(); + i < e; ++i) { + BBOffsets[i] += delta; + // If some existing blocks have padding, adjust the padding as needed, a + // bit tricky. delta can be negative so don't use % on that. + if (!isThumb) + continue; + MachineBasicBlock *MBB = MBBI; + if (!MBB->empty() && !HasInlineAsm) { + // Constant pool entries require padding. + if (MBB->begin()->getOpcode() == ARM::CONSTPOOL_ENTRY) { + unsigned OldOffset = BBOffsets[i] - delta; + if ((OldOffset%4) == 0 && (BBOffsets[i]%4) != 0) { + // add new padding + BBSizes[i] += 2; + delta += 2; + } else if ((OldOffset%4) != 0 && (BBOffsets[i]%4) == 0) { + // remove existing padding + BBSizes[i] -= 2; + delta -= 2; + } + } + // Thumb1 jump tables require padding. They should be at the end; + // following unconditional branches are removed by AnalyzeBranch. + MachineInstr *ThumbJTMI = prior(MBB->end()); + if (ThumbJTMI->getOpcode() == ARM::tBR_JTr) { + unsigned NewMIOffset = GetOffsetOf(ThumbJTMI); + unsigned OldMIOffset = NewMIOffset - delta; + if ((OldMIOffset%4) == 0 && (NewMIOffset%4) != 0) { + // remove existing padding + BBSizes[i] -= 2; + delta -= 2; + } else if ((OldMIOffset%4) != 0 && (NewMIOffset%4) == 0) { + // add new padding + BBSizes[i] += 2; + delta += 2; + } + } + if (delta==0) + return; + } + MBBI = next(MBBI); + } +} + +/// DecrementOldEntry - find the constant pool entry with index CPI +/// and instruction CPEMI, and decrement its refcount. If the refcount +/// becomes 0 remove the entry and instruction. Returns true if we removed +/// the entry, false if we didn't. + +bool ARMConstantIslands::DecrementOldEntry(unsigned CPI, MachineInstr *CPEMI) { + // Find the old entry. Eliminate it if it is no longer used. + CPEntry *CPE = findConstPoolEntry(CPI, CPEMI); + assert(CPE && "Unexpected!"); + if (--CPE->RefCount == 0) { + RemoveDeadCPEMI(CPEMI); + CPE->CPEMI = NULL; + NumCPEs--; + return true; + } + return false; +} + +/// LookForCPEntryInRange - see if the currently referenced CPE is in range; +/// if not, see if an in-range clone of the CPE is in range, and if so, +/// change the data structures so the user references the clone. Returns: +/// 0 = no existing entry found +/// 1 = entry found, and there were no code insertions or deletions +/// 2 = entry found, and there were code insertions or deletions +int ARMConstantIslands::LookForExistingCPEntry(CPUser& U, unsigned UserOffset) +{ + MachineInstr *UserMI = U.MI; + MachineInstr *CPEMI = U.CPEMI; + + // Check to see if the CPE is already in-range. + if (CPEIsInRange(UserMI, UserOffset, CPEMI, U.MaxDisp, U.NegOk, true)) { + DEBUG(errs() << "In range\n"); + return 1; + } + + // No. Look for previously created clones of the CPE that are in range. + unsigned CPI = CPEMI->getOperand(1).getIndex(); + std::vector &CPEs = CPEntries[CPI]; + for (unsigned i = 0, e = CPEs.size(); i != e; ++i) { + // We already tried this one + if (CPEs[i].CPEMI == CPEMI) + continue; + // Removing CPEs can leave empty entries, skip + if (CPEs[i].CPEMI == NULL) + continue; + if (CPEIsInRange(UserMI, UserOffset, CPEs[i].CPEMI, U.MaxDisp, U.NegOk)) { + DEBUG(errs() << "Replacing CPE#" << CPI << " with CPE#" + << CPEs[i].CPI << "\n"); + // Point the CPUser node to the replacement + U.CPEMI = CPEs[i].CPEMI; + // Change the CPI in the instruction operand to refer to the clone. + for (unsigned j = 0, e = UserMI->getNumOperands(); j != e; ++j) + if (UserMI->getOperand(j).isCPI()) { + UserMI->getOperand(j).setIndex(CPEs[i].CPI); + break; + } + // Adjust the refcount of the clone... + CPEs[i].RefCount++; + // ...and the original. If we didn't remove the old entry, none of the + // addresses changed, so we don't need another pass. + return DecrementOldEntry(CPI, CPEMI) ? 2 : 1; + } + } + return 0; +} + +/// getUnconditionalBrDisp - Returns the maximum displacement that can fit in +/// the specific unconditional branch instruction. +static inline unsigned getUnconditionalBrDisp(int Opc) { + switch (Opc) { + case ARM::tB: + return ((1<<10)-1)*2; + case ARM::t2B: + return ((1<<23)-1)*2; + default: + break; + } + + return ((1<<23)-1)*4; +} + +/// LookForWater - Look for an existing entry in the WaterList in which +/// we can place the CPE referenced from U so it's within range of U's MI. +/// Returns true if found, false if not. If it returns true, WaterIter +/// is set to the WaterList entry. For Thumb, prefer water that will not +/// introduce padding to water that will. To ensure that this pass +/// terminates, the CPE location for a particular CPUser is only allowed to +/// move to a lower address, so search backward from the end of the list and +/// prefer the first water that is in range. +bool ARMConstantIslands::LookForWater(CPUser &U, unsigned UserOffset, + water_iterator &WaterIter) { + if (WaterList.empty()) + return false; + + bool FoundWaterThatWouldPad = false; + water_iterator IPThatWouldPad; + for (water_iterator IP = prior(WaterList.end()), + B = WaterList.begin();; --IP) { + MachineBasicBlock* WaterBB = *IP; + // Check if water is in range and is either at a lower address than the + // current "high water mark" or a new water block that was created since + // the previous iteration by inserting an unconditional branch. In the + // latter case, we want to allow resetting the high water mark back to + // this new water since we haven't seen it before. Inserting branches + // should be relatively uncommon and when it does happen, we want to be + // sure to take advantage of it for all the CPEs near that block, so that + // we don't insert more branches than necessary. + if (WaterIsInRange(UserOffset, WaterBB, U) && + (WaterBB->getNumber() < U.HighWaterMark->getNumber() || + NewWaterList.count(WaterBB))) { + unsigned WBBId = WaterBB->getNumber(); + if (isThumb && + (BBOffsets[WBBId] + BBSizes[WBBId])%4 != 0) { + // This is valid Water, but would introduce padding. Remember + // it in case we don't find any Water that doesn't do this. + if (!FoundWaterThatWouldPad) { + FoundWaterThatWouldPad = true; + IPThatWouldPad = IP; + } + } else { + WaterIter = IP; + return true; + } + } + if (IP == B) + break; + } + if (FoundWaterThatWouldPad) { + WaterIter = IPThatWouldPad; + return true; + } + return false; +} + +/// CreateNewWater - No existing WaterList entry will work for +/// CPUsers[CPUserIndex], so create a place to put the CPE. The end of the +/// block is used if in range, and the conditional branch munged so control +/// flow is correct. Otherwise the block is split to create a hole with an +/// unconditional branch around it. In either case NewMBB is set to a +/// block following which the new island can be inserted (the WaterList +/// is not adjusted). +void ARMConstantIslands::CreateNewWater(unsigned CPUserIndex, + unsigned UserOffset, + MachineBasicBlock *&NewMBB) { + CPUser &U = CPUsers[CPUserIndex]; + MachineInstr *UserMI = U.MI; + MachineInstr *CPEMI = U.CPEMI; + MachineBasicBlock *UserMBB = UserMI->getParent(); + unsigned OffsetOfNextBlock = BBOffsets[UserMBB->getNumber()] + + BBSizes[UserMBB->getNumber()]; + assert(OffsetOfNextBlock== BBOffsets[UserMBB->getNumber()+1]); + + // If the block does not end in an unconditional branch already, and if the + // end of the block is within range, make new water there. (The addition + // below is for the unconditional branch we will be adding: 4 bytes on ARM + + // Thumb2, 2 on Thumb1. Possible Thumb1 alignment padding is allowed for + // inside OffsetIsInRange. + if (BBHasFallthrough(UserMBB) && + OffsetIsInRange(UserOffset, OffsetOfNextBlock + (isThumb1 ? 2: 4), + U.MaxDisp, U.NegOk, U.IsSoImm)) { + DEBUG(errs() << "Split at end of block\n"); + if (&UserMBB->back() == UserMI) + assert(BBHasFallthrough(UserMBB) && "Expected a fallthrough BB!"); + NewMBB = next(MachineFunction::iterator(UserMBB)); + // Add an unconditional branch from UserMBB to fallthrough block. + // Record it for branch lengthening; this new branch will not get out of + // range, but if the preceding conditional branch is out of range, the + // targets will be exchanged, and the altered branch may be out of + // range, so the machinery has to know about it. + int UncondBr = isThumb ? ((isThumb2) ? ARM::t2B : ARM::tB) : ARM::B; + BuildMI(UserMBB, DebugLoc::getUnknownLoc(), + TII->get(UncondBr)).addMBB(NewMBB); + unsigned MaxDisp = getUnconditionalBrDisp(UncondBr); + ImmBranches.push_back(ImmBranch(&UserMBB->back(), + MaxDisp, false, UncondBr)); + int delta = isThumb1 ? 2 : 4; + BBSizes[UserMBB->getNumber()] += delta; + AdjustBBOffsetsAfter(UserMBB, delta); + } else { + // What a big block. Find a place within the block to split it. + // This is a little tricky on Thumb1 since instructions are 2 bytes + // and constant pool entries are 4 bytes: if instruction I references + // island CPE, and instruction I+1 references CPE', it will + // not work well to put CPE as far forward as possible, since then + // CPE' cannot immediately follow it (that location is 2 bytes + // farther away from I+1 than CPE was from I) and we'd need to create + // a new island. So, we make a first guess, then walk through the + // instructions between the one currently being looked at and the + // possible insertion point, and make sure any other instructions + // that reference CPEs will be able to use the same island area; + // if not, we back up the insertion point. + + // The 4 in the following is for the unconditional branch we'll be + // inserting (allows for long branch on Thumb1). Alignment of the + // island is handled inside OffsetIsInRange. + unsigned BaseInsertOffset = UserOffset + U.MaxDisp -4; + // This could point off the end of the block if we've already got + // constant pool entries following this block; only the last one is + // in the water list. Back past any possible branches (allow for a + // conditional and a maximally long unconditional). + if (BaseInsertOffset >= BBOffsets[UserMBB->getNumber()+1]) + BaseInsertOffset = BBOffsets[UserMBB->getNumber()+1] - + (isThumb1 ? 6 : 8); + unsigned EndInsertOffset = BaseInsertOffset + + CPEMI->getOperand(2).getImm(); + MachineBasicBlock::iterator MI = UserMI; + ++MI; + unsigned CPUIndex = CPUserIndex+1; + for (unsigned Offset = UserOffset+TII->GetInstSizeInBytes(UserMI); + Offset < BaseInsertOffset; + Offset += TII->GetInstSizeInBytes(MI), + MI = next(MI)) { + if (CPUIndex < CPUsers.size() && CPUsers[CPUIndex].MI == MI) { + CPUser &U = CPUsers[CPUIndex]; + if (!OffsetIsInRange(Offset, EndInsertOffset, + U.MaxDisp, U.NegOk, U.IsSoImm)) { + BaseInsertOffset -= (isThumb1 ? 2 : 4); + EndInsertOffset -= (isThumb1 ? 2 : 4); + } + // This is overly conservative, as we don't account for CPEMIs + // being reused within the block, but it doesn't matter much. + EndInsertOffset += CPUsers[CPUIndex].CPEMI->getOperand(2).getImm(); + CPUIndex++; + } + } + DEBUG(errs() << "Split in middle of big block\n"); + NewMBB = SplitBlockBeforeInstr(prior(MI)); + } +} + +/// HandleConstantPoolUser - Analyze the specified user, checking to see if it +/// is out-of-range. If so, pick up the constant pool value and move it some +/// place in-range. Return true if we changed any addresses (thus must run +/// another pass of branch lengthening), false otherwise. +bool ARMConstantIslands::HandleConstantPoolUser(MachineFunction &MF, + unsigned CPUserIndex) { + CPUser &U = CPUsers[CPUserIndex]; + MachineInstr *UserMI = U.MI; + MachineInstr *CPEMI = U.CPEMI; + unsigned CPI = CPEMI->getOperand(1).getIndex(); + unsigned Size = CPEMI->getOperand(2).getImm(); + // Compute this only once, it's expensive. The 4 or 8 is the value the + // hardware keeps in the PC. + unsigned UserOffset = GetOffsetOf(UserMI) + (isThumb ? 4 : 8); + + // See if the current entry is within range, or there is a clone of it + // in range. + int result = LookForExistingCPEntry(U, UserOffset); + if (result==1) return false; + else if (result==2) return true; + + // No existing clone of this CPE is within range. + // We will be generating a new clone. Get a UID for it. + unsigned ID = AFI->createConstPoolEntryUId(); + + // Look for water where we can place this CPE. + MachineBasicBlock *NewIsland = MF.CreateMachineBasicBlock(); + MachineBasicBlock *NewMBB; + water_iterator IP; + if (LookForWater(U, UserOffset, IP)) { + DEBUG(errs() << "found water in range\n"); + MachineBasicBlock *WaterBB = *IP; + + // If the original WaterList entry was "new water" on this iteration, + // propagate that to the new island. This is just keeping NewWaterList + // updated to match the WaterList, which will be updated below. + if (NewWaterList.count(WaterBB)) { + NewWaterList.erase(WaterBB); + NewWaterList.insert(NewIsland); + } + // The new CPE goes before the following block (NewMBB). + NewMBB = next(MachineFunction::iterator(WaterBB)); + + } else { + // No water found. + DEBUG(errs() << "No water found\n"); + CreateNewWater(CPUserIndex, UserOffset, NewMBB); + + // SplitBlockBeforeInstr adds to WaterList, which is important when it is + // called while handling branches so that the water will be seen on the + // next iteration for constant pools, but in this context, we don't want + // it. Check for this so it will be removed from the WaterList. + // Also remove any entry from NewWaterList. + MachineBasicBlock *WaterBB = prior(MachineFunction::iterator(NewMBB)); + IP = std::find(WaterList.begin(), WaterList.end(), WaterBB); + if (IP != WaterList.end()) + NewWaterList.erase(WaterBB); + + // We are adding new water. Update NewWaterList. + NewWaterList.insert(NewIsland); + } + + // Remove the original WaterList entry; we want subsequent insertions in + // this vicinity to go after the one we're about to insert. This + // considerably reduces the number of times we have to move the same CPE + // more than once and is also important to ensure the algorithm terminates. + if (IP != WaterList.end()) + WaterList.erase(IP); + + // Okay, we know we can put an island before NewMBB now, do it! + MF.insert(NewMBB, NewIsland); + + // Update internal data structures to account for the newly inserted MBB. + UpdateForInsertedWaterBlock(NewIsland); + + // Decrement the old entry, and remove it if refcount becomes 0. + DecrementOldEntry(CPI, CPEMI); + + // Now that we have an island to add the CPE to, clone the original CPE and + // add it to the island. + U.HighWaterMark = NewIsland; + U.CPEMI = BuildMI(NewIsland, DebugLoc::getUnknownLoc(), + TII->get(ARM::CONSTPOOL_ENTRY)) + .addImm(ID).addConstantPoolIndex(CPI).addImm(Size); + CPEntries[CPI].push_back(CPEntry(U.CPEMI, ID, 1)); + NumCPEs++; + + BBOffsets[NewIsland->getNumber()] = BBOffsets[NewMBB->getNumber()]; + // Compensate for .align 2 in thumb mode. + if (isThumb && (BBOffsets[NewIsland->getNumber()]%4 != 0 || HasInlineAsm)) + Size += 2; + // Increase the size of the island block to account for the new entry. + BBSizes[NewIsland->getNumber()] += Size; + AdjustBBOffsetsAfter(NewIsland, Size); + + // Finally, change the CPI in the instruction operand to be ID. + for (unsigned i = 0, e = UserMI->getNumOperands(); i != e; ++i) + if (UserMI->getOperand(i).isCPI()) { + UserMI->getOperand(i).setIndex(ID); + break; + } + + DEBUG(errs() << " Moved CPE to #" << ID << " CPI=" << CPI + << '\t' << *UserMI); + + return true; +} + +/// RemoveDeadCPEMI - Remove a dead constant pool entry instruction. Update +/// sizes and offsets of impacted basic blocks. +void ARMConstantIslands::RemoveDeadCPEMI(MachineInstr *CPEMI) { + MachineBasicBlock *CPEBB = CPEMI->getParent(); + unsigned Size = CPEMI->getOperand(2).getImm(); + CPEMI->eraseFromParent(); + BBSizes[CPEBB->getNumber()] -= Size; + // All succeeding offsets have the current size value added in, fix this. + if (CPEBB->empty()) { + // In thumb1 mode, the size of island may be padded by two to compensate for + // the alignment requirement. Then it will now be 2 when the block is + // empty, so fix this. + // All succeeding offsets have the current size value added in, fix this. + if (BBSizes[CPEBB->getNumber()] != 0) { + Size += BBSizes[CPEBB->getNumber()]; + BBSizes[CPEBB->getNumber()] = 0; + } + } + AdjustBBOffsetsAfter(CPEBB, -Size); + // An island has only one predecessor BB and one successor BB. Check if + // this BB's predecessor jumps directly to this BB's successor. This + // shouldn't happen currently. + assert(!BBIsJumpedOver(CPEBB) && "How did this happen?"); + // FIXME: remove the empty blocks after all the work is done? +} + +/// RemoveUnusedCPEntries - Remove constant pool entries whose refcounts +/// are zero. +bool ARMConstantIslands::RemoveUnusedCPEntries() { + unsigned MadeChange = false; + for (unsigned i = 0, e = CPEntries.size(); i != e; ++i) { + std::vector &CPEs = CPEntries[i]; + for (unsigned j = 0, ee = CPEs.size(); j != ee; ++j) { + if (CPEs[j].RefCount == 0 && CPEs[j].CPEMI) { + RemoveDeadCPEMI(CPEs[j].CPEMI); + CPEs[j].CPEMI = NULL; + MadeChange = true; + } + } + } + return MadeChange; +} + +/// BBIsInRange - Returns true if the distance between specific MI and +/// specific BB can fit in MI's displacement field. +bool ARMConstantIslands::BBIsInRange(MachineInstr *MI,MachineBasicBlock *DestBB, + unsigned MaxDisp) { + unsigned PCAdj = isThumb ? 4 : 8; + unsigned BrOffset = GetOffsetOf(MI) + PCAdj; + unsigned DestOffset = BBOffsets[DestBB->getNumber()]; + + DEBUG(errs() << "Branch of destination BB#" << DestBB->getNumber() + << " from BB#" << MI->getParent()->getNumber() + << " max delta=" << MaxDisp + << " from " << GetOffsetOf(MI) << " to " << DestOffset + << " offset " << int(DestOffset-BrOffset) << "\t" << *MI); + + if (BrOffset <= DestOffset) { + // Branch before the Dest. + if (DestOffset-BrOffset <= MaxDisp) + return true; + } else { + if (BrOffset-DestOffset <= MaxDisp) + return true; + } + return false; +} + +/// FixUpImmediateBr - Fix up an immediate branch whose destination is too far +/// away to fit in its displacement field. +bool ARMConstantIslands::FixUpImmediateBr(MachineFunction &MF, ImmBranch &Br) { + MachineInstr *MI = Br.MI; + MachineBasicBlock *DestBB = MI->getOperand(0).getMBB(); + + // Check to see if the DestBB is already in-range. + if (BBIsInRange(MI, DestBB, Br.MaxDisp)) + return false; + + if (!Br.isCond) + return FixUpUnconditionalBr(MF, Br); + return FixUpConditionalBr(MF, Br); +} + +/// FixUpUnconditionalBr - Fix up an unconditional branch whose destination is +/// too far away to fit in its displacement field. If the LR register has been +/// spilled in the epilogue, then we can use BL to implement a far jump. +/// Otherwise, add an intermediate branch instruction to a branch. +bool +ARMConstantIslands::FixUpUnconditionalBr(MachineFunction &MF, ImmBranch &Br) { + MachineInstr *MI = Br.MI; + MachineBasicBlock *MBB = MI->getParent(); + if (!isThumb1) + llvm_unreachable("FixUpUnconditionalBr is Thumb1 only!"); + + // Use BL to implement far jump. + Br.MaxDisp = (1 << 21) * 2; + MI->setDesc(TII->get(ARM::tBfar)); + BBSizes[MBB->getNumber()] += 2; + AdjustBBOffsetsAfter(MBB, 2); + HasFarJump = true; + NumUBrFixed++; + + DEBUG(errs() << " Changed B to long jump " << *MI); + + return true; +} + +/// FixUpConditionalBr - Fix up a conditional branch whose destination is too +/// far away to fit in its displacement field. It is converted to an inverse +/// conditional branch + an unconditional branch to the destination. +bool +ARMConstantIslands::FixUpConditionalBr(MachineFunction &MF, ImmBranch &Br) { + MachineInstr *MI = Br.MI; + MachineBasicBlock *DestBB = MI->getOperand(0).getMBB(); + + // Add an unconditional branch to the destination and invert the branch + // condition to jump over it: + // blt L1 + // => + // bge L2 + // b L1 + // L2: + ARMCC::CondCodes CC = (ARMCC::CondCodes)MI->getOperand(1).getImm(); + CC = ARMCC::getOppositeCondition(CC); + unsigned CCReg = MI->getOperand(2).getReg(); + + // If the branch is at the end of its MBB and that has a fall-through block, + // direct the updated conditional branch to the fall-through block. Otherwise, + // split the MBB before the next instruction. + MachineBasicBlock *MBB = MI->getParent(); + MachineInstr *BMI = &MBB->back(); + bool NeedSplit = (BMI != MI) || !BBHasFallthrough(MBB); + + NumCBrFixed++; + if (BMI != MI) { + if (next(MachineBasicBlock::iterator(MI)) == prior(MBB->end()) && + BMI->getOpcode() == Br.UncondBr) { + // Last MI in the BB is an unconditional branch. Can we simply invert the + // condition and swap destinations: + // beq L1 + // b L2 + // => + // bne L2 + // b L1 + MachineBasicBlock *NewDest = BMI->getOperand(0).getMBB(); + if (BBIsInRange(MI, NewDest, Br.MaxDisp)) { + DEBUG(errs() << " Invert Bcc condition and swap its destination with " + << *BMI); + BMI->getOperand(0).setMBB(DestBB); + MI->getOperand(0).setMBB(NewDest); + MI->getOperand(1).setImm(CC); + return true; + } + } + } + + if (NeedSplit) { + SplitBlockBeforeInstr(MI); + // No need for the branch to the next block. We're adding an unconditional + // branch to the destination. + int delta = TII->GetInstSizeInBytes(&MBB->back()); + BBSizes[MBB->getNumber()] -= delta; + MachineBasicBlock* SplitBB = next(MachineFunction::iterator(MBB)); + AdjustBBOffsetsAfter(SplitBB, -delta); + MBB->back().eraseFromParent(); + // BBOffsets[SplitBB] is wrong temporarily, fixed below + } + MachineBasicBlock *NextBB = next(MachineFunction::iterator(MBB)); + + DEBUG(errs() << " Insert B to BB#" << DestBB->getNumber() + << " also invert condition and change dest. to BB#" + << NextBB->getNumber() << "\n"); + + // Insert a new conditional branch and a new unconditional branch. + // Also update the ImmBranch as well as adding a new entry for the new branch. + BuildMI(MBB, DebugLoc::getUnknownLoc(), + TII->get(MI->getOpcode())) + .addMBB(NextBB).addImm(CC).addReg(CCReg); + Br.MI = &MBB->back(); + BBSizes[MBB->getNumber()] += TII->GetInstSizeInBytes(&MBB->back()); + BuildMI(MBB, DebugLoc::getUnknownLoc(), TII->get(Br.UncondBr)).addMBB(DestBB); + BBSizes[MBB->getNumber()] += TII->GetInstSizeInBytes(&MBB->back()); + unsigned MaxDisp = getUnconditionalBrDisp(Br.UncondBr); + ImmBranches.push_back(ImmBranch(&MBB->back(), MaxDisp, false, Br.UncondBr)); + + // Remove the old conditional branch. It may or may not still be in MBB. + BBSizes[MI->getParent()->getNumber()] -= TII->GetInstSizeInBytes(MI); + MI->eraseFromParent(); + + // The net size change is an addition of one unconditional branch. + int delta = TII->GetInstSizeInBytes(&MBB->back()); + AdjustBBOffsetsAfter(MBB, delta); + return true; +} + +/// UndoLRSpillRestore - Remove Thumb push / pop instructions that only spills +/// LR / restores LR to pc. FIXME: This is done here because it's only possible +/// to do this if tBfar is not used. +bool ARMConstantIslands::UndoLRSpillRestore() { + bool MadeChange = false; + for (unsigned i = 0, e = PushPopMIs.size(); i != e; ++i) { + MachineInstr *MI = PushPopMIs[i]; + // First two operands are predicates, the third is a zero since there + // is no writeback. + if (MI->getOpcode() == ARM::tPOP_RET && + MI->getOperand(3).getReg() == ARM::PC && + MI->getNumExplicitOperands() == 4) { + BuildMI(MI->getParent(), MI->getDebugLoc(), TII->get(ARM::tBX_RET)); + MI->eraseFromParent(); + MadeChange = true; + } + } + return MadeChange; +} + +bool ARMConstantIslands::OptimizeThumb2Instructions(MachineFunction &MF) { + bool MadeChange = false; + + // Shrink ADR and LDR from constantpool. + for (unsigned i = 0, e = CPUsers.size(); i != e; ++i) { + CPUser &U = CPUsers[i]; + unsigned Opcode = U.MI->getOpcode(); + unsigned NewOpc = 0; + unsigned Scale = 1; + unsigned Bits = 0; + switch (Opcode) { + default: break; + case ARM::t2LEApcrel: + if (isARMLowRegister(U.MI->getOperand(0).getReg())) { + NewOpc = ARM::tLEApcrel; + Bits = 8; + Scale = 4; + } + break; + case ARM::t2LDRpci: + if (isARMLowRegister(U.MI->getOperand(0).getReg())) { + NewOpc = ARM::tLDRpci; + Bits = 8; + Scale = 4; + } + break; + } + + if (!NewOpc) + continue; + + unsigned UserOffset = GetOffsetOf(U.MI) + 4; + unsigned MaxOffs = ((1 << Bits) - 1) * Scale; + // FIXME: Check if offset is multiple of scale if scale is not 4. + if (CPEIsInRange(U.MI, UserOffset, U.CPEMI, MaxOffs, false, true)) { + U.MI->setDesc(TII->get(NewOpc)); + MachineBasicBlock *MBB = U.MI->getParent(); + BBSizes[MBB->getNumber()] -= 2; + AdjustBBOffsetsAfter(MBB, -2); + ++NumT2CPShrunk; + MadeChange = true; + } + } + + MadeChange |= OptimizeThumb2Branches(MF); + MadeChange |= OptimizeThumb2JumpTables(MF); + return MadeChange; +} + +bool ARMConstantIslands::OptimizeThumb2Branches(MachineFunction &MF) { + bool MadeChange = false; + + for (unsigned i = 0, e = ImmBranches.size(); i != e; ++i) { + ImmBranch &Br = ImmBranches[i]; + unsigned Opcode = Br.MI->getOpcode(); + unsigned NewOpc = 0; + unsigned Scale = 1; + unsigned Bits = 0; + switch (Opcode) { + default: break; + case ARM::t2B: + NewOpc = ARM::tB; + Bits = 11; + Scale = 2; + break; + case ARM::t2Bcc: { + NewOpc = ARM::tBcc; + Bits = 8; + Scale = 2; + break; + } + } + if (NewOpc) { + unsigned MaxOffs = ((1 << (Bits-1))-1) * Scale; + MachineBasicBlock *DestBB = Br.MI->getOperand(0).getMBB(); + if (BBIsInRange(Br.MI, DestBB, MaxOffs)) { + Br.MI->setDesc(TII->get(NewOpc)); + MachineBasicBlock *MBB = Br.MI->getParent(); + BBSizes[MBB->getNumber()] -= 2; + AdjustBBOffsetsAfter(MBB, -2); + ++NumT2BrShrunk; + MadeChange = true; + } + } + + Opcode = Br.MI->getOpcode(); + if (Opcode != ARM::tBcc) + continue; + + NewOpc = 0; + unsigned PredReg = 0; + ARMCC::CondCodes Pred = llvm::getInstrPredicate(Br.MI, PredReg); + if (Pred == ARMCC::EQ) + NewOpc = ARM::tCBZ; + else if (Pred == ARMCC::NE) + NewOpc = ARM::tCBNZ; + if (!NewOpc) + continue; + MachineBasicBlock *DestBB = Br.MI->getOperand(0).getMBB(); + // Check if the distance is within 126. Subtract starting offset by 2 + // because the cmp will be eliminated. + unsigned BrOffset = GetOffsetOf(Br.MI) + 4 - 2; + unsigned DestOffset = BBOffsets[DestBB->getNumber()]; + if (BrOffset < DestOffset && (DestOffset - BrOffset) <= 126) { + MachineBasicBlock::iterator CmpMI = Br.MI; --CmpMI; + if (CmpMI->getOpcode() == ARM::tCMPzi8) { + unsigned Reg = CmpMI->getOperand(0).getReg(); + Pred = llvm::getInstrPredicate(CmpMI, PredReg); + if (Pred == ARMCC::AL && + CmpMI->getOperand(1).getImm() == 0 && + isARMLowRegister(Reg)) { + MachineBasicBlock *MBB = Br.MI->getParent(); + MachineInstr *NewBR = + BuildMI(*MBB, CmpMI, Br.MI->getDebugLoc(), TII->get(NewOpc)) + .addReg(Reg).addMBB(DestBB, Br.MI->getOperand(0).getTargetFlags()); + CmpMI->eraseFromParent(); + Br.MI->eraseFromParent(); + Br.MI = NewBR; + BBSizes[MBB->getNumber()] -= 2; + AdjustBBOffsetsAfter(MBB, -2); + ++NumCBZ; + MadeChange = true; + } + } + } + } + + return MadeChange; +} + +/// OptimizeThumb2JumpTables - Use tbb / tbh instructions to generate smaller +/// jumptables when it's possible. +bool ARMConstantIslands::OptimizeThumb2JumpTables(MachineFunction &MF) { + bool MadeChange = false; + + // FIXME: After the tables are shrunk, can we get rid some of the + // constantpool tables? + MachineJumpTableInfo *MJTI = MF.getJumpTableInfo(); + const std::vector &JT = MJTI->getJumpTables(); + for (unsigned i = 0, e = T2JumpTables.size(); i != e; ++i) { + MachineInstr *MI = T2JumpTables[i]; + const TargetInstrDesc &TID = MI->getDesc(); + unsigned NumOps = TID.getNumOperands(); + unsigned JTOpIdx = NumOps - (TID.isPredicable() ? 3 : 2); + MachineOperand JTOP = MI->getOperand(JTOpIdx); + unsigned JTI = JTOP.getIndex(); + assert(JTI < JT.size()); + + bool ByteOk = true; + bool HalfWordOk = true; + unsigned JTOffset = GetOffsetOf(MI) + 4; + const std::vector &JTBBs = JT[JTI].MBBs; + for (unsigned j = 0, ee = JTBBs.size(); j != ee; ++j) { + MachineBasicBlock *MBB = JTBBs[j]; + unsigned DstOffset = BBOffsets[MBB->getNumber()]; + // Negative offset is not ok. FIXME: We should change BB layout to make + // sure all the branches are forward. + if (ByteOk && (DstOffset - JTOffset) > ((1<<8)-1)*2) + ByteOk = false; + unsigned TBHLimit = ((1<<16)-1)*2; + if (HalfWordOk && (DstOffset - JTOffset) > TBHLimit) + HalfWordOk = false; + if (!ByteOk && !HalfWordOk) + break; + } + + if (ByteOk || HalfWordOk) { + MachineBasicBlock *MBB = MI->getParent(); + unsigned BaseReg = MI->getOperand(0).getReg(); + bool BaseRegKill = MI->getOperand(0).isKill(); + if (!BaseRegKill) + continue; + unsigned IdxReg = MI->getOperand(1).getReg(); + bool IdxRegKill = MI->getOperand(1).isKill(); + MachineBasicBlock::iterator PrevI = MI; + if (PrevI == MBB->begin()) + continue; + + MachineInstr *AddrMI = --PrevI; + bool OptOk = true; + // Examine the instruction that calculate the jumptable entry address. + // If it's not the one just before the t2BR_JT, we won't delete it, then + // it's not worth doing the optimization. + for (unsigned k = 0, eee = AddrMI->getNumOperands(); k != eee; ++k) { + const MachineOperand &MO = AddrMI->getOperand(k); + if (!MO.isReg() || !MO.getReg()) + continue; + if (MO.isDef() && MO.getReg() != BaseReg) { + OptOk = false; + break; + } + if (MO.isUse() && !MO.isKill() && MO.getReg() != IdxReg) { + OptOk = false; + break; + } + } + if (!OptOk) + continue; + + // The previous instruction should be a tLEApcrel or t2LEApcrelJT, we want + // to delete it as well. + MachineInstr *LeaMI = --PrevI; + if ((LeaMI->getOpcode() != ARM::tLEApcrelJT && + LeaMI->getOpcode() != ARM::t2LEApcrelJT) || + LeaMI->getOperand(0).getReg() != BaseReg) + OptOk = false; + + if (!OptOk) + continue; + + unsigned Opc = ByteOk ? ARM::t2TBB : ARM::t2TBH; + MachineInstr *NewJTMI = BuildMI(MBB, MI->getDebugLoc(), TII->get(Opc)) + .addReg(IdxReg, getKillRegState(IdxRegKill)) + .addJumpTableIndex(JTI, JTOP.getTargetFlags()) + .addImm(MI->getOperand(JTOpIdx+1).getImm()); + // FIXME: Insert an "ALIGN" instruction to ensure the next instruction + // is 2-byte aligned. For now, asm printer will fix it up. + unsigned NewSize = TII->GetInstSizeInBytes(NewJTMI); + unsigned OrigSize = TII->GetInstSizeInBytes(AddrMI); + OrigSize += TII->GetInstSizeInBytes(LeaMI); + OrigSize += TII->GetInstSizeInBytes(MI); + + AddrMI->eraseFromParent(); + LeaMI->eraseFromParent(); + MI->eraseFromParent(); + + int delta = OrigSize - NewSize; + BBSizes[MBB->getNumber()] -= delta; + AdjustBBOffsetsAfter(MBB, -delta); + + ++NumTBs; + MadeChange = true; + } + } + + return MadeChange; +} + +/// ReorderThumb2JumpTables - Adjust the function's block layout to ensure that +/// jump tables always branch forwards, since that's what tbb and tbh need. +bool ARMConstantIslands::ReorderThumb2JumpTables(MachineFunction &MF) { + bool MadeChange = false; + + MachineJumpTableInfo *MJTI = MF.getJumpTableInfo(); + const std::vector &JT = MJTI->getJumpTables(); + for (unsigned i = 0, e = T2JumpTables.size(); i != e; ++i) { + MachineInstr *MI = T2JumpTables[i]; + const TargetInstrDesc &TID = MI->getDesc(); + unsigned NumOps = TID.getNumOperands(); + unsigned JTOpIdx = NumOps - (TID.isPredicable() ? 3 : 2); + MachineOperand JTOP = MI->getOperand(JTOpIdx); + unsigned JTI = JTOP.getIndex(); + assert(JTI < JT.size()); + + // We prefer if target blocks for the jump table come after the jump + // instruction so we can use TB[BH]. Loop through the target blocks + // and try to adjust them such that that's true. + int JTNumber = MI->getParent()->getNumber(); + const std::vector &JTBBs = JT[JTI].MBBs; + for (unsigned j = 0, ee = JTBBs.size(); j != ee; ++j) { + MachineBasicBlock *MBB = JTBBs[j]; + int DTNumber = MBB->getNumber(); + + if (DTNumber < JTNumber) { + // The destination precedes the switch. Try to move the block forward + // so we have a positive offset. + MachineBasicBlock *NewBB = + AdjustJTTargetBlockForward(MBB, MI->getParent()); + if (NewBB) + MJTI->ReplaceMBBInJumpTable(JTI, JTBBs[j], NewBB); + MadeChange = true; + } + } + } + + return MadeChange; +} + +MachineBasicBlock *ARMConstantIslands:: +AdjustJTTargetBlockForward(MachineBasicBlock *BB, MachineBasicBlock *JTBB) +{ + MachineFunction &MF = *BB->getParent(); + + // If it's the destination block is terminated by an unconditional branch, + // try to move it; otherwise, create a new block following the jump + // table that branches back to the actual target. This is a very simple + // heuristic. FIXME: We can definitely improve it. + MachineBasicBlock *TBB = 0, *FBB = 0; + SmallVector Cond; + SmallVector CondPrior; + MachineFunction::iterator BBi = BB; + MachineFunction::iterator OldPrior = prior(BBi); + + // If the block terminator isn't analyzable, don't try to move the block + bool B = TII->AnalyzeBranch(*BB, TBB, FBB, Cond); + + // If the block ends in an unconditional branch, move it. The prior block + // has to have an analyzable terminator for us to move this one. Be paranoid + // and make sure we're not trying to move the entry block of the function. + if (!B && Cond.empty() && BB != MF.begin() && + !TII->AnalyzeBranch(*OldPrior, TBB, FBB, CondPrior)) { + BB->moveAfter(JTBB); + OldPrior->updateTerminator(); + BB->updateTerminator(); + // Update numbering to account for the block being moved. + MF.RenumberBlocks(); + ++NumJTMoved; + return NULL; + } + + // Create a new MBB for the code after the jump BB. + MachineBasicBlock *NewBB = + MF.CreateMachineBasicBlock(JTBB->getBasicBlock()); + MachineFunction::iterator MBBI = JTBB; ++MBBI; + MF.insert(MBBI, NewBB); + + // Add an unconditional branch from NewBB to BB. + // There doesn't seem to be meaningful DebugInfo available; this doesn't + // correspond directly to anything in the source. + assert (isThumb2 && "Adjusting for TB[BH] but not in Thumb2?"); + BuildMI(NewBB, DebugLoc::getUnknownLoc(), TII->get(ARM::t2B)).addMBB(BB); + + // Update internal data structures to account for the newly inserted MBB. + MF.RenumberBlocks(NewBB); + + // Update the CFG. + NewBB->addSuccessor(BB); + JTBB->removeSuccessor(BB); + JTBB->addSuccessor(NewBB); + + ++NumJTInserted; + return NewBB; +} diff --git a/libclamav/c++/llvm/lib/Target/ARM/ARMConstantPoolValue.cpp b/libclamav/c++/llvm/lib/Target/ARM/ARMConstantPoolValue.cpp new file mode 100644 index 000000000..90dd0c7fd --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/ARM/ARMConstantPoolValue.cpp @@ -0,0 +1,121 @@ +//===- ARMConstantPoolValue.cpp - ARM constantpool value --------*- 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 the ARM specific constantpool value class. +// +//===----------------------------------------------------------------------===// + +#include "ARMConstantPoolValue.h" +#include "llvm/ADT/FoldingSet.h" +#include "llvm/Constant.h" +#include "llvm/Constants.h" +#include "llvm/GlobalValue.h" +#include "llvm/Type.h" +#include "llvm/Support/raw_ostream.h" +#include +using namespace llvm; + +ARMConstantPoolValue::ARMConstantPoolValue(Constant *cval, unsigned id, + ARMCP::ARMCPKind K, + unsigned char PCAdj, + const char *Modif, + bool AddCA) + : MachineConstantPoolValue((const Type*)cval->getType()), + CVal(cval), S(NULL), LabelId(id), Kind(K), PCAdjust(PCAdj), + Modifier(Modif), AddCurrentAddress(AddCA) {} + +ARMConstantPoolValue::ARMConstantPoolValue(LLVMContext &C, + const char *s, unsigned id, + unsigned char PCAdj, + const char *Modif, + bool AddCA) + : MachineConstantPoolValue((const Type*)Type::getInt32Ty(C)), + CVal(NULL), S(strdup(s)), LabelId(id), Kind(ARMCP::CPExtSymbol), + PCAdjust(PCAdj), Modifier(Modif), AddCurrentAddress(AddCA) {} + +ARMConstantPoolValue::ARMConstantPoolValue(GlobalValue *gv, const char *Modif) + : MachineConstantPoolValue((const Type*)Type::getInt32Ty(gv->getContext())), + CVal(gv), S(NULL), LabelId(0), Kind(ARMCP::CPValue), PCAdjust(0), + Modifier(Modif) {} + +GlobalValue *ARMConstantPoolValue::getGV() const { + return dyn_cast_or_null(CVal); +} + +BlockAddress *ARMConstantPoolValue::getBlockAddress() const { + return dyn_cast_or_null(CVal); +} + +int ARMConstantPoolValue::getExistingMachineCPValue(MachineConstantPool *CP, + unsigned Alignment) { + unsigned AlignMask = Alignment - 1; + const std::vector Constants = CP->getConstants(); + for (unsigned i = 0, e = Constants.size(); i != e; ++i) { + if (Constants[i].isMachineConstantPoolEntry() && + (Constants[i].getAlignment() & AlignMask) == 0) { + ARMConstantPoolValue *CPV = + (ARMConstantPoolValue *)Constants[i].Val.MachineCPVal; + if (CPV->CVal == CVal && + CPV->LabelId == LabelId && + CPV->PCAdjust == PCAdjust && + (CPV->S == S || strcmp(CPV->S, S) == 0) && + (CPV->Modifier == Modifier || strcmp(CPV->Modifier, Modifier) == 0)) + return i; + } + } + + return -1; +} + +ARMConstantPoolValue::~ARMConstantPoolValue() { + free((void*)S); +} + +void +ARMConstantPoolValue::AddSelectionDAGCSEId(FoldingSetNodeID &ID) { + ID.AddPointer(CVal); + ID.AddPointer(S); + ID.AddInteger(LabelId); + ID.AddInteger(PCAdjust); +} + +bool +ARMConstantPoolValue::hasSameValue(ARMConstantPoolValue *ACPV) { + if (ACPV->Kind == Kind && + ACPV->CVal == CVal && + ACPV->PCAdjust == PCAdjust && + (ACPV->S == S || strcmp(ACPV->S, S) == 0) && + (ACPV->Modifier == Modifier || strcmp(ACPV->Modifier, Modifier) == 0)) { + if (ACPV->LabelId == LabelId) + return true; + // Two PC relative constpool entries containing the same GV address or + // external symbols. FIXME: What about blockaddress? + if (Kind == ARMCP::CPValue || Kind == ARMCP::CPExtSymbol) + return true; + } + return false; +} + +void ARMConstantPoolValue::dump() const { + errs() << " " << *this; +} + + +void ARMConstantPoolValue::print(raw_ostream &O) const { + if (CVal) + O << CVal->getName(); + else + O << S; + if (Modifier) O << "(" << Modifier << ")"; + if (PCAdjust != 0) { + O << "-(LPC" << LabelId << "+" << (unsigned)PCAdjust; + if (AddCurrentAddress) O << "-."; + O << ")"; + } +} diff --git a/libclamav/c++/llvm/lib/Target/ARM/ARMConstantPoolValue.h b/libclamav/c++/llvm/lib/Target/ARM/ARMConstantPoolValue.h new file mode 100644 index 000000000..741acde27 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/ARM/ARMConstantPoolValue.h @@ -0,0 +1,100 @@ +//===- ARMConstantPoolValue.h - ARM constantpool value ----------*- 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 the ARM specific constantpool value class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TARGET_ARM_CONSTANTPOOLVALUE_H +#define LLVM_TARGET_ARM_CONSTANTPOOLVALUE_H + +#include "llvm/CodeGen/MachineConstantPool.h" + +namespace llvm { + +class Constant; +class BlockAddress; +class GlobalValue; +class LLVMContext; + +namespace ARMCP { + enum ARMCPKind { + CPValue, + CPExtSymbol, + CPBlockAddress, + CPLSDA + }; +} + +/// ARMConstantPoolValue - ARM specific constantpool value. This is used to +/// represent PC-relative displacement between the address of the load +/// instruction and the constant being loaded, i.e. (&GV-(LPIC+8)). +class ARMConstantPoolValue : public MachineConstantPoolValue { + Constant *CVal; // Constant being loaded. + const char *S; // ExtSymbol being loaded. + unsigned LabelId; // Label id of the load. + ARMCP::ARMCPKind Kind; // Kind of constant. + unsigned char PCAdjust; // Extra adjustment if constantpool is pc-relative. + // 8 for ARM, 4 for Thumb. + const char *Modifier; // GV modifier i.e. (&GV(modifier)-(LPIC+8)) + bool AddCurrentAddress; + +public: + ARMConstantPoolValue(Constant *cval, unsigned id, + ARMCP::ARMCPKind Kind = ARMCP::CPValue, + unsigned char PCAdj = 0, const char *Modifier = NULL, + bool AddCurrentAddress = false); + ARMConstantPoolValue(LLVMContext &C, const char *s, unsigned id, + unsigned char PCAdj = 0, const char *Modifier = NULL, + bool AddCurrentAddress = false); + ARMConstantPoolValue(GlobalValue *GV, const char *Modifier); + ARMConstantPoolValue(); + ~ARMConstantPoolValue(); + + GlobalValue *getGV() const; + const char *getSymbol() const { return S; } + BlockAddress *getBlockAddress() const; + const char *getModifier() const { return Modifier; } + bool hasModifier() const { return Modifier != NULL; } + bool mustAddCurrentAddress() const { return AddCurrentAddress; } + unsigned getLabelId() const { return LabelId; } + unsigned char getPCAdjustment() const { return PCAdjust; } + bool isGlobalValue() const { return Kind == ARMCP::CPValue; } + bool isExtSymbol() const { return Kind == ARMCP::CPExtSymbol; } + bool isBlockAddress() { return Kind == ARMCP::CPBlockAddress; } + bool isLSDA() { return Kind == ARMCP::CPLSDA; } + + virtual unsigned getRelocationInfo() const { + // FIXME: This is conservatively claiming that these entries require a + // relocation, we may be able to do better than this. + return 2; + } + + virtual int getExistingMachineCPValue(MachineConstantPool *CP, + unsigned Alignment); + + virtual void AddSelectionDAGCSEId(FoldingSetNodeID &ID); + + /// hasSameValue - Return true if this ARM constpool value + /// can share the same constantpool entry as another ARM constpool value. + bool hasSameValue(ARMConstantPoolValue *ACPV); + + void print(raw_ostream *O) const { if (O) print(*O); } + void print(raw_ostream &O) const; + void dump() const; +}; + +inline raw_ostream &operator<<(raw_ostream &O, const ARMConstantPoolValue &V) { + V.print(O); + return O; +} + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/lib/Target/ARM/ARMExpandPseudoInsts.cpp b/libclamav/c++/llvm/lib/Target/ARM/ARMExpandPseudoInsts.cpp new file mode 100644 index 000000000..c929c54d4 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/ARM/ARMExpandPseudoInsts.cpp @@ -0,0 +1,128 @@ +//===-- ARMExpandPseudoInsts.cpp - Expand pseudo instructions -----*- C++ -*-=// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains a pass that expand pseudo instructions into target +// instructions to allow proper scheduling, if-conversion, and other late +// optimizations. This pass should be run after register allocation but before +// post- regalloc scheduling pass. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "arm-pseudo" +#include "ARM.h" +#include "ARMBaseInstrInfo.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" + +using namespace llvm; + +namespace { + class ARMExpandPseudo : public MachineFunctionPass { + public: + static char ID; + ARMExpandPseudo() : MachineFunctionPass(&ID) {} + + const TargetInstrInfo *TII; + + virtual bool runOnMachineFunction(MachineFunction &Fn); + + virtual const char *getPassName() const { + return "ARM pseudo instruction expansion pass"; + } + + private: + bool ExpandMBB(MachineBasicBlock &MBB); + }; + char ARMExpandPseudo::ID = 0; +} + +bool ARMExpandPseudo::ExpandMBB(MachineBasicBlock &MBB) { + bool Modified = false; + + MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end(); + while (MBBI != E) { + MachineInstr &MI = *MBBI; + MachineBasicBlock::iterator NMBBI = next(MBBI); + + unsigned Opcode = MI.getOpcode(); + switch (Opcode) { + default: break; + case ARM::tLDRpci_pic: + case ARM::t2LDRpci_pic: { + unsigned NewLdOpc = (Opcode == ARM::tLDRpci_pic) + ? ARM::tLDRpci : ARM::t2LDRpci; + unsigned DstReg = MI.getOperand(0).getReg(); + if (!MI.getOperand(0).isDead()) { + MachineInstr *NewMI = + AddDefaultPred(BuildMI(MBB, MBBI, MI.getDebugLoc(), + TII->get(NewLdOpc), DstReg) + .addOperand(MI.getOperand(1))); + NewMI->setMemRefs(MI.memoperands_begin(), MI.memoperands_end()); + BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::tPICADD)) + .addReg(DstReg, getDefRegState(true)) + .addReg(DstReg) + .addOperand(MI.getOperand(2)); + } + MI.eraseFromParent(); + Modified = true; + break; + } + case ARM::t2MOVi32imm: { + unsigned DstReg = MI.getOperand(0).getReg(); + if (!MI.getOperand(0).isDead()) { + const MachineOperand &MO = MI.getOperand(1); + MachineInstrBuilder LO16, HI16; + + LO16 = BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::t2MOVi16), + DstReg); + HI16 = BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::t2MOVTi16)) + .addReg(DstReg, getDefRegState(true)).addReg(DstReg); + + if (MO.isImm()) { + unsigned Imm = MO.getImm(); + unsigned Lo16 = Imm & 0xffff; + unsigned Hi16 = (Imm >> 16) & 0xffff; + LO16 = LO16.addImm(Lo16); + HI16 = HI16.addImm(Hi16); + } else { + GlobalValue *GV = MO.getGlobal(); + unsigned TF = MO.getTargetFlags(); + LO16 = LO16.addGlobalAddress(GV, MO.getOffset(), TF | ARMII::MO_LO16); + HI16 = HI16.addGlobalAddress(GV, MO.getOffset(), TF | ARMII::MO_HI16); + // FIXME: What's about memoperands? + } + AddDefaultPred(LO16); + AddDefaultPred(HI16); + } + MI.eraseFromParent(); + Modified = true; + } + // FIXME: expand t2MOVi32imm + } + MBBI = NMBBI; + } + + return Modified; +} + +bool ARMExpandPseudo::runOnMachineFunction(MachineFunction &MF) { + TII = MF.getTarget().getInstrInfo(); + + bool Modified = false; + for (MachineFunction::iterator MFI = MF.begin(), E = MF.end(); MFI != E; + ++MFI) + Modified |= ExpandMBB(*MFI); + return Modified; +} + +/// createARMExpandPseudoPass - returns an instance of the pseudo instruction +/// expansion pass. +FunctionPass *llvm::createARMExpandPseudoPass() { + return new ARMExpandPseudo(); +} diff --git a/libclamav/c++/llvm/lib/Target/ARM/ARMFrameInfo.h b/libclamav/c++/llvm/lib/Target/ARM/ARMFrameInfo.h new file mode 100644 index 000000000..d5dae2442 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/ARM/ARMFrameInfo.h @@ -0,0 +1,32 @@ +//===-- ARMTargetFrameInfo.h - Define TargetFrameInfo for ARM ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// +// +//===----------------------------------------------------------------------===// + +#ifndef ARM_FRAMEINFO_H +#define ARM_FRAMEINFO_H + +#include "ARM.h" +#include "ARMSubtarget.h" +#include "llvm/Target/TargetFrameInfo.h" + +namespace llvm { + +class ARMFrameInfo : public TargetFrameInfo { +public: + explicit ARMFrameInfo(const ARMSubtarget &ST) + : TargetFrameInfo(StackGrowsDown, ST.getStackAlignment(), 0, 4) { + } +}; + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/lib/Target/ARM/ARMISelDAGToDAG.cpp b/libclamav/c++/llvm/lib/Target/ARM/ARMISelDAGToDAG.cpp new file mode 100644 index 000000000..d63f3e66f --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/ARM/ARMISelDAGToDAG.cpp @@ -0,0 +1,1973 @@ +//===-- ARMISelDAGToDAG.cpp - A dag to dag inst selector for ARM ----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines an instruction selector for the ARM target. +// +//===----------------------------------------------------------------------===// + +#include "ARM.h" +#include "ARMAddressingModes.h" +#include "ARMISelLowering.h" +#include "ARMTargetMachine.h" +#include "llvm/CallingConv.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Function.h" +#include "llvm/Intrinsics.h" +#include "llvm/LLVMContext.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/SelectionDAG.h" +#include "llvm/CodeGen/SelectionDAGISel.h" +#include "llvm/Target/TargetLowering.h" +#include "llvm/Target/TargetOptions.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" + +using namespace llvm; + +//===--------------------------------------------------------------------===// +/// ARMDAGToDAGISel - ARM specific code to select ARM machine +/// instructions for SelectionDAG operations. +/// +namespace { +class ARMDAGToDAGISel : public SelectionDAGISel { + ARMBaseTargetMachine &TM; + + /// Subtarget - Keep a pointer to the ARMSubtarget around so that we can + /// make the right decision when generating code for different targets. + const ARMSubtarget *Subtarget; + +public: + explicit ARMDAGToDAGISel(ARMBaseTargetMachine &tm, + CodeGenOpt::Level OptLevel) + : SelectionDAGISel(tm, OptLevel), TM(tm), + Subtarget(&TM.getSubtarget()) { + } + + virtual const char *getPassName() const { + return "ARM Instruction Selection"; + } + + /// getI32Imm - Return a target constant of type i32 with the specified + /// value. + inline SDValue getI32Imm(unsigned Imm) { + return CurDAG->getTargetConstant(Imm, MVT::i32); + } + + SDNode *Select(SDValue Op); + virtual void InstructionSelect(); + bool SelectShifterOperandReg(SDValue Op, SDValue N, SDValue &A, + SDValue &B, SDValue &C); + bool SelectAddrMode2(SDValue Op, SDValue N, SDValue &Base, + SDValue &Offset, SDValue &Opc); + bool SelectAddrMode2Offset(SDValue Op, SDValue N, + SDValue &Offset, SDValue &Opc); + bool SelectAddrMode3(SDValue Op, SDValue N, SDValue &Base, + SDValue &Offset, SDValue &Opc); + bool SelectAddrMode3Offset(SDValue Op, SDValue N, + SDValue &Offset, SDValue &Opc); + bool SelectAddrMode4(SDValue Op, SDValue N, SDValue &Addr, + SDValue &Mode); + bool SelectAddrMode5(SDValue Op, SDValue N, SDValue &Base, + SDValue &Offset); + bool SelectAddrMode6(SDValue Op, SDValue N, SDValue &Addr, SDValue &Update, + SDValue &Opc, SDValue &Align); + + bool SelectAddrModePC(SDValue Op, SDValue N, SDValue &Offset, + SDValue &Label); + + bool SelectThumbAddrModeRR(SDValue Op, SDValue N, SDValue &Base, + SDValue &Offset); + bool SelectThumbAddrModeRI5(SDValue Op, SDValue N, unsigned Scale, + SDValue &Base, SDValue &OffImm, + SDValue &Offset); + bool SelectThumbAddrModeS1(SDValue Op, SDValue N, SDValue &Base, + SDValue &OffImm, SDValue &Offset); + bool SelectThumbAddrModeS2(SDValue Op, SDValue N, SDValue &Base, + SDValue &OffImm, SDValue &Offset); + bool SelectThumbAddrModeS4(SDValue Op, SDValue N, SDValue &Base, + SDValue &OffImm, SDValue &Offset); + bool SelectThumbAddrModeSP(SDValue Op, SDValue N, SDValue &Base, + SDValue &OffImm); + + bool SelectT2ShifterOperandReg(SDValue Op, SDValue N, + SDValue &BaseReg, SDValue &Opc); + bool SelectT2AddrModeImm12(SDValue Op, SDValue N, SDValue &Base, + SDValue &OffImm); + bool SelectT2AddrModeImm8(SDValue Op, SDValue N, SDValue &Base, + SDValue &OffImm); + bool SelectT2AddrModeImm8Offset(SDValue Op, SDValue N, + SDValue &OffImm); + bool SelectT2AddrModeImm8s4(SDValue Op, SDValue N, SDValue &Base, + SDValue &OffImm); + bool SelectT2AddrModeSoReg(SDValue Op, SDValue N, SDValue &Base, + SDValue &OffReg, SDValue &ShImm); + + // Include the pieces autogenerated from the target description. +#include "ARMGenDAGISel.inc" + +private: + /// SelectARMIndexedLoad - Indexed (pre/post inc/dec) load matching code for + /// ARM. + SDNode *SelectARMIndexedLoad(SDValue Op); + SDNode *SelectT2IndexedLoad(SDValue Op); + + /// SelectDYN_ALLOC - Select dynamic alloc for Thumb. + SDNode *SelectDYN_ALLOC(SDValue Op); + + /// SelectVLD - Select NEON load intrinsics. NumVecs should + /// be 2, 3 or 4. The opcode arrays specify the instructions used for + /// loads of D registers and even subregs and odd subregs of Q registers. + /// For NumVecs == 2, QOpcodes1 is not used. + SDNode *SelectVLD(SDValue Op, unsigned NumVecs, unsigned *DOpcodes, + unsigned *QOpcodes0, unsigned *QOpcodes1); + + /// SelectVST - Select NEON store intrinsics. NumVecs should + /// be 2, 3 or 4. The opcode arrays specify the instructions used for + /// stores of D registers and even subregs and odd subregs of Q registers. + /// For NumVecs == 2, QOpcodes1 is not used. + SDNode *SelectVST(SDValue Op, unsigned NumVecs, unsigned *DOpcodes, + unsigned *QOpcodes0, unsigned *QOpcodes1); + + /// SelectVLDSTLane - Select NEON load/store lane intrinsics. NumVecs should + /// be 2, 3 or 4. The opcode arrays specify the instructions used for + /// load/store of D registers and even subregs and odd subregs of Q registers. + SDNode *SelectVLDSTLane(SDValue Op, bool IsLoad, unsigned NumVecs, + unsigned *DOpcodes, unsigned *QOpcodes0, + unsigned *QOpcodes1); + + /// SelectV6T2BitfieldExtractOp - Select SBFX/UBFX instructions for ARM. + SDNode *SelectV6T2BitfieldExtractOp(SDValue Op, unsigned Opc); + + /// SelectCMOVOp - Select CMOV instructions for ARM. + SDNode *SelectCMOVOp(SDValue Op); + SDNode *SelectT2CMOVShiftOp(SDValue Op, SDValue FalseVal, SDValue TrueVal, + ARMCC::CondCodes CCVal, SDValue CCR, + SDValue InFlag); + SDNode *SelectARMCMOVShiftOp(SDValue Op, SDValue FalseVal, SDValue TrueVal, + ARMCC::CondCodes CCVal, SDValue CCR, + SDValue InFlag); + SDNode *SelectT2CMOVSoImmOp(SDValue Op, SDValue FalseVal, SDValue TrueVal, + ARMCC::CondCodes CCVal, SDValue CCR, + SDValue InFlag); + SDNode *SelectARMCMOVSoImmOp(SDValue Op, SDValue FalseVal, SDValue TrueVal, + ARMCC::CondCodes CCVal, SDValue CCR, + SDValue InFlag); + + /// SelectInlineAsmMemoryOperand - Implement addressing mode selection for + /// inline asm expressions. + virtual bool SelectInlineAsmMemoryOperand(const SDValue &Op, + char ConstraintCode, + std::vector &OutOps); + + /// PairDRegs - Insert a pair of double registers into an implicit def to + /// form a quad register. + SDNode *PairDRegs(EVT VT, SDValue V0, SDValue V1); +}; +} + +/// isInt32Immediate - This method tests to see if the node is a 32-bit constant +/// operand. If so Imm will receive the 32-bit value. +static bool isInt32Immediate(SDNode *N, unsigned &Imm) { + if (N->getOpcode() == ISD::Constant && N->getValueType(0) == MVT::i32) { + Imm = cast(N)->getZExtValue(); + return true; + } + return false; +} + +// isInt32Immediate - This method tests to see if a constant operand. +// If so Imm will receive the 32 bit value. +static bool isInt32Immediate(SDValue N, unsigned &Imm) { + return isInt32Immediate(N.getNode(), Imm); +} + +// isOpcWithIntImmediate - This method tests to see if the node is a specific +// opcode and that it has a immediate integer right operand. +// If so Imm will receive the 32 bit value. +static bool isOpcWithIntImmediate(SDNode *N, unsigned Opc, unsigned& Imm) { + return N->getOpcode() == Opc && + isInt32Immediate(N->getOperand(1).getNode(), Imm); +} + + +void ARMDAGToDAGISel::InstructionSelect() { + SelectRoot(*CurDAG); + CurDAG->RemoveDeadNodes(); +} + +bool ARMDAGToDAGISel::SelectShifterOperandReg(SDValue Op, + SDValue N, + SDValue &BaseReg, + SDValue &ShReg, + SDValue &Opc) { + ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N); + + // Don't match base register only case. That is matched to a separate + // lower complexity pattern with explicit register operand. + if (ShOpcVal == ARM_AM::no_shift) return false; + + BaseReg = N.getOperand(0); + unsigned ShImmVal = 0; + if (ConstantSDNode *RHS = dyn_cast(N.getOperand(1))) { + ShReg = CurDAG->getRegister(0, MVT::i32); + ShImmVal = RHS->getZExtValue() & 31; + } else { + ShReg = N.getOperand(1); + } + Opc = CurDAG->getTargetConstant(ARM_AM::getSORegOpc(ShOpcVal, ShImmVal), + MVT::i32); + return true; +} + +bool ARMDAGToDAGISel::SelectAddrMode2(SDValue Op, SDValue N, + SDValue &Base, SDValue &Offset, + SDValue &Opc) { + if (N.getOpcode() == ISD::MUL) { + if (ConstantSDNode *RHS = dyn_cast(N.getOperand(1))) { + // X * [3,5,9] -> X + X * [2,4,8] etc. + int RHSC = (int)RHS->getZExtValue(); + if (RHSC & 1) { + RHSC = RHSC & ~1; + ARM_AM::AddrOpc AddSub = ARM_AM::add; + if (RHSC < 0) { + AddSub = ARM_AM::sub; + RHSC = - RHSC; + } + if (isPowerOf2_32(RHSC)) { + unsigned ShAmt = Log2_32(RHSC); + Base = Offset = N.getOperand(0); + Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt, + ARM_AM::lsl), + MVT::i32); + return true; + } + } + } + } + + if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB) { + Base = N; + if (N.getOpcode() == ISD::FrameIndex) { + int FI = cast(N)->getIndex(); + Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); + } else if (N.getOpcode() == ARMISD::Wrapper && + !(Subtarget->useMovt() && + N.getOperand(0).getOpcode() == ISD::TargetGlobalAddress)) { + Base = N.getOperand(0); + } + Offset = CurDAG->getRegister(0, MVT::i32); + Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(ARM_AM::add, 0, + ARM_AM::no_shift), + MVT::i32); + return true; + } + + // Match simple R +/- imm12 operands. + if (N.getOpcode() == ISD::ADD) + if (ConstantSDNode *RHS = dyn_cast(N.getOperand(1))) { + int RHSC = (int)RHS->getZExtValue(); + if ((RHSC >= 0 && RHSC < 0x1000) || + (RHSC < 0 && RHSC > -0x1000)) { // 12 bits. + Base = N.getOperand(0); + if (Base.getOpcode() == ISD::FrameIndex) { + int FI = cast(Base)->getIndex(); + Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); + } + Offset = CurDAG->getRegister(0, MVT::i32); + + ARM_AM::AddrOpc AddSub = ARM_AM::add; + if (RHSC < 0) { + AddSub = ARM_AM::sub; + RHSC = - RHSC; + } + Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, RHSC, + ARM_AM::no_shift), + MVT::i32); + return true; + } + } + + // Otherwise this is R +/- [possibly shifted] R. + ARM_AM::AddrOpc AddSub = N.getOpcode() == ISD::ADD ? ARM_AM::add:ARM_AM::sub; + ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOperand(1)); + unsigned ShAmt = 0; + + Base = N.getOperand(0); + Offset = N.getOperand(1); + + if (ShOpcVal != ARM_AM::no_shift) { + // Check to see if the RHS of the shift is a constant, if not, we can't fold + // it. + if (ConstantSDNode *Sh = + dyn_cast(N.getOperand(1).getOperand(1))) { + ShAmt = Sh->getZExtValue(); + Offset = N.getOperand(1).getOperand(0); + } else { + ShOpcVal = ARM_AM::no_shift; + } + } + + // Try matching (R shl C) + (R). + if (N.getOpcode() == ISD::ADD && ShOpcVal == ARM_AM::no_shift) { + ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOperand(0)); + if (ShOpcVal != ARM_AM::no_shift) { + // Check to see if the RHS of the shift is a constant, if not, we can't + // fold it. + if (ConstantSDNode *Sh = + dyn_cast(N.getOperand(0).getOperand(1))) { + ShAmt = Sh->getZExtValue(); + Offset = N.getOperand(0).getOperand(0); + Base = N.getOperand(1); + } else { + ShOpcVal = ARM_AM::no_shift; + } + } + } + + Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt, ShOpcVal), + MVT::i32); + return true; +} + +bool ARMDAGToDAGISel::SelectAddrMode2Offset(SDValue Op, SDValue N, + SDValue &Offset, SDValue &Opc) { + unsigned Opcode = Op.getOpcode(); + ISD::MemIndexedMode AM = (Opcode == ISD::LOAD) + ? cast(Op)->getAddressingMode() + : cast(Op)->getAddressingMode(); + ARM_AM::AddrOpc AddSub = (AM == ISD::PRE_INC || AM == ISD::POST_INC) + ? ARM_AM::add : ARM_AM::sub; + if (ConstantSDNode *C = dyn_cast(N)) { + int Val = (int)C->getZExtValue(); + if (Val >= 0 && Val < 0x1000) { // 12 bits. + Offset = CurDAG->getRegister(0, MVT::i32); + Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, Val, + ARM_AM::no_shift), + MVT::i32); + return true; + } + } + + Offset = N; + ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N); + unsigned ShAmt = 0; + if (ShOpcVal != ARM_AM::no_shift) { + // Check to see if the RHS of the shift is a constant, if not, we can't fold + // it. + if (ConstantSDNode *Sh = dyn_cast(N.getOperand(1))) { + ShAmt = Sh->getZExtValue(); + Offset = N.getOperand(0); + } else { + ShOpcVal = ARM_AM::no_shift; + } + } + + Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt, ShOpcVal), + MVT::i32); + return true; +} + + +bool ARMDAGToDAGISel::SelectAddrMode3(SDValue Op, SDValue N, + SDValue &Base, SDValue &Offset, + SDValue &Opc) { + if (N.getOpcode() == ISD::SUB) { + // X - C is canonicalize to X + -C, no need to handle it here. + Base = N.getOperand(0); + Offset = N.getOperand(1); + Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(ARM_AM::sub, 0),MVT::i32); + return true; + } + + if (N.getOpcode() != ISD::ADD) { + Base = N; + if (N.getOpcode() == ISD::FrameIndex) { + int FI = cast(N)->getIndex(); + Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); + } + Offset = CurDAG->getRegister(0, MVT::i32); + Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(ARM_AM::add, 0),MVT::i32); + return true; + } + + // If the RHS is +/- imm8, fold into addr mode. + if (ConstantSDNode *RHS = dyn_cast(N.getOperand(1))) { + int RHSC = (int)RHS->getZExtValue(); + if ((RHSC >= 0 && RHSC < 256) || + (RHSC < 0 && RHSC > -256)) { // note -256 itself isn't allowed. + Base = N.getOperand(0); + if (Base.getOpcode() == ISD::FrameIndex) { + int FI = cast(Base)->getIndex(); + Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); + } + Offset = CurDAG->getRegister(0, MVT::i32); + + ARM_AM::AddrOpc AddSub = ARM_AM::add; + if (RHSC < 0) { + AddSub = ARM_AM::sub; + RHSC = - RHSC; + } + Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(AddSub, RHSC),MVT::i32); + return true; + } + } + + Base = N.getOperand(0); + Offset = N.getOperand(1); + Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(ARM_AM::add, 0), MVT::i32); + return true; +} + +bool ARMDAGToDAGISel::SelectAddrMode3Offset(SDValue Op, SDValue N, + SDValue &Offset, SDValue &Opc) { + unsigned Opcode = Op.getOpcode(); + ISD::MemIndexedMode AM = (Opcode == ISD::LOAD) + ? cast(Op)->getAddressingMode() + : cast(Op)->getAddressingMode(); + ARM_AM::AddrOpc AddSub = (AM == ISD::PRE_INC || AM == ISD::POST_INC) + ? ARM_AM::add : ARM_AM::sub; + if (ConstantSDNode *C = dyn_cast(N)) { + int Val = (int)C->getZExtValue(); + if (Val >= 0 && Val < 256) { + Offset = CurDAG->getRegister(0, MVT::i32); + Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(AddSub, Val), MVT::i32); + return true; + } + } + + Offset = N; + Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(AddSub, 0), MVT::i32); + return true; +} + +bool ARMDAGToDAGISel::SelectAddrMode4(SDValue Op, SDValue N, + SDValue &Addr, SDValue &Mode) { + Addr = N; + Mode = CurDAG->getTargetConstant(0, MVT::i32); + return true; +} + +bool ARMDAGToDAGISel::SelectAddrMode5(SDValue Op, SDValue N, + SDValue &Base, SDValue &Offset) { + if (N.getOpcode() != ISD::ADD) { + Base = N; + if (N.getOpcode() == ISD::FrameIndex) { + int FI = cast(N)->getIndex(); + Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); + } else if (N.getOpcode() == ARMISD::Wrapper && + !(Subtarget->useMovt() && + N.getOperand(0).getOpcode() == ISD::TargetGlobalAddress)) { + Base = N.getOperand(0); + } + Offset = CurDAG->getTargetConstant(ARM_AM::getAM5Opc(ARM_AM::add, 0), + MVT::i32); + return true; + } + + // If the RHS is +/- imm8, fold into addr mode. + if (ConstantSDNode *RHS = dyn_cast(N.getOperand(1))) { + int RHSC = (int)RHS->getZExtValue(); + if ((RHSC & 3) == 0) { // The constant is implicitly multiplied by 4. + RHSC >>= 2; + if ((RHSC >= 0 && RHSC < 256) || + (RHSC < 0 && RHSC > -256)) { // note -256 itself isn't allowed. + Base = N.getOperand(0); + if (Base.getOpcode() == ISD::FrameIndex) { + int FI = cast(Base)->getIndex(); + Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); + } + + ARM_AM::AddrOpc AddSub = ARM_AM::add; + if (RHSC < 0) { + AddSub = ARM_AM::sub; + RHSC = - RHSC; + } + Offset = CurDAG->getTargetConstant(ARM_AM::getAM5Opc(AddSub, RHSC), + MVT::i32); + return true; + } + } + } + + Base = N; + Offset = CurDAG->getTargetConstant(ARM_AM::getAM5Opc(ARM_AM::add, 0), + MVT::i32); + return true; +} + +bool ARMDAGToDAGISel::SelectAddrMode6(SDValue Op, SDValue N, + SDValue &Addr, SDValue &Update, + SDValue &Opc, SDValue &Align) { + Addr = N; + // Default to no writeback. + Update = CurDAG->getRegister(0, MVT::i32); + Opc = CurDAG->getTargetConstant(ARM_AM::getAM6Opc(false), MVT::i32); + // Default to no alignment. + Align = CurDAG->getTargetConstant(0, MVT::i32); + return true; +} + +bool ARMDAGToDAGISel::SelectAddrModePC(SDValue Op, SDValue N, + SDValue &Offset, SDValue &Label) { + if (N.getOpcode() == ARMISD::PIC_ADD && N.hasOneUse()) { + Offset = N.getOperand(0); + SDValue N1 = N.getOperand(1); + Label = CurDAG->getTargetConstant(cast(N1)->getZExtValue(), + MVT::i32); + return true; + } + return false; +} + +bool ARMDAGToDAGISel::SelectThumbAddrModeRR(SDValue Op, SDValue N, + SDValue &Base, SDValue &Offset){ + // FIXME dl should come from the parent load or store, not the address + DebugLoc dl = Op.getDebugLoc(); + if (N.getOpcode() != ISD::ADD) { + ConstantSDNode *NC = dyn_cast(N); + if (!NC || NC->getZExtValue() != 0) + return false; + + Base = Offset = N; + return true; + } + + Base = N.getOperand(0); + Offset = N.getOperand(1); + return true; +} + +bool +ARMDAGToDAGISel::SelectThumbAddrModeRI5(SDValue Op, SDValue N, + unsigned Scale, SDValue &Base, + SDValue &OffImm, SDValue &Offset) { + if (Scale == 4) { + SDValue TmpBase, TmpOffImm; + if (SelectThumbAddrModeSP(Op, N, TmpBase, TmpOffImm)) + return false; // We want to select tLDRspi / tSTRspi instead. + if (N.getOpcode() == ARMISD::Wrapper && + N.getOperand(0).getOpcode() == ISD::TargetConstantPool) + return false; // We want to select tLDRpci instead. + } + + if (N.getOpcode() != ISD::ADD) { + if (N.getOpcode() == ARMISD::Wrapper && + !(Subtarget->useMovt() && + N.getOperand(0).getOpcode() == ISD::TargetGlobalAddress)) { + Base = N.getOperand(0); + } else + Base = N; + + Offset = CurDAG->getRegister(0, MVT::i32); + OffImm = CurDAG->getTargetConstant(0, MVT::i32); + return true; + } + + // Thumb does not have [sp, r] address mode. + RegisterSDNode *LHSR = dyn_cast(N.getOperand(0)); + RegisterSDNode *RHSR = dyn_cast(N.getOperand(1)); + if ((LHSR && LHSR->getReg() == ARM::SP) || + (RHSR && RHSR->getReg() == ARM::SP)) { + Base = N; + Offset = CurDAG->getRegister(0, MVT::i32); + OffImm = CurDAG->getTargetConstant(0, MVT::i32); + return true; + } + + // If the RHS is + imm5 * scale, fold into addr mode. + if (ConstantSDNode *RHS = dyn_cast(N.getOperand(1))) { + int RHSC = (int)RHS->getZExtValue(); + if ((RHSC & (Scale-1)) == 0) { // The constant is implicitly multiplied. + RHSC /= Scale; + if (RHSC >= 0 && RHSC < 32) { + Base = N.getOperand(0); + Offset = CurDAG->getRegister(0, MVT::i32); + OffImm = CurDAG->getTargetConstant(RHSC, MVT::i32); + return true; + } + } + } + + Base = N.getOperand(0); + Offset = N.getOperand(1); + OffImm = CurDAG->getTargetConstant(0, MVT::i32); + return true; +} + +bool ARMDAGToDAGISel::SelectThumbAddrModeS1(SDValue Op, SDValue N, + SDValue &Base, SDValue &OffImm, + SDValue &Offset) { + return SelectThumbAddrModeRI5(Op, N, 1, Base, OffImm, Offset); +} + +bool ARMDAGToDAGISel::SelectThumbAddrModeS2(SDValue Op, SDValue N, + SDValue &Base, SDValue &OffImm, + SDValue &Offset) { + return SelectThumbAddrModeRI5(Op, N, 2, Base, OffImm, Offset); +} + +bool ARMDAGToDAGISel::SelectThumbAddrModeS4(SDValue Op, SDValue N, + SDValue &Base, SDValue &OffImm, + SDValue &Offset) { + return SelectThumbAddrModeRI5(Op, N, 4, Base, OffImm, Offset); +} + +bool ARMDAGToDAGISel::SelectThumbAddrModeSP(SDValue Op, SDValue N, + SDValue &Base, SDValue &OffImm) { + if (N.getOpcode() == ISD::FrameIndex) { + int FI = cast(N)->getIndex(); + Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); + OffImm = CurDAG->getTargetConstant(0, MVT::i32); + return true; + } + + if (N.getOpcode() != ISD::ADD) + return false; + + RegisterSDNode *LHSR = dyn_cast(N.getOperand(0)); + if (N.getOperand(0).getOpcode() == ISD::FrameIndex || + (LHSR && LHSR->getReg() == ARM::SP)) { + // If the RHS is + imm8 * scale, fold into addr mode. + if (ConstantSDNode *RHS = dyn_cast(N.getOperand(1))) { + int RHSC = (int)RHS->getZExtValue(); + if ((RHSC & 3) == 0) { // The constant is implicitly multiplied. + RHSC >>= 2; + if (RHSC >= 0 && RHSC < 256) { + Base = N.getOperand(0); + if (Base.getOpcode() == ISD::FrameIndex) { + int FI = cast(Base)->getIndex(); + Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); + } + OffImm = CurDAG->getTargetConstant(RHSC, MVT::i32); + return true; + } + } + } + } + + return false; +} + +bool ARMDAGToDAGISel::SelectT2ShifterOperandReg(SDValue Op, SDValue N, + SDValue &BaseReg, + SDValue &Opc) { + ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N); + + // Don't match base register only case. That is matched to a separate + // lower complexity pattern with explicit register operand. + if (ShOpcVal == ARM_AM::no_shift) return false; + + BaseReg = N.getOperand(0); + unsigned ShImmVal = 0; + if (ConstantSDNode *RHS = dyn_cast(N.getOperand(1))) { + ShImmVal = RHS->getZExtValue() & 31; + Opc = getI32Imm(ARM_AM::getSORegOpc(ShOpcVal, ShImmVal)); + return true; + } + + return false; +} + +bool ARMDAGToDAGISel::SelectT2AddrModeImm12(SDValue Op, SDValue N, + SDValue &Base, SDValue &OffImm) { + // Match simple R + imm12 operands. + + // Base only. + if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB) { + if (N.getOpcode() == ISD::FrameIndex) { + // Match frame index... + int FI = cast(N)->getIndex(); + Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); + OffImm = CurDAG->getTargetConstant(0, MVT::i32); + return true; + } else if (N.getOpcode() == ARMISD::Wrapper && + !(Subtarget->useMovt() && + N.getOperand(0).getOpcode() == ISD::TargetGlobalAddress)) { + Base = N.getOperand(0); + if (Base.getOpcode() == ISD::TargetConstantPool) + return false; // We want to select t2LDRpci instead. + } else + Base = N; + OffImm = CurDAG->getTargetConstant(0, MVT::i32); + return true; + } + + if (ConstantSDNode *RHS = dyn_cast(N.getOperand(1))) { + if (SelectT2AddrModeImm8(Op, N, Base, OffImm)) + // Let t2LDRi8 handle (R - imm8). + return false; + + int RHSC = (int)RHS->getZExtValue(); + if (N.getOpcode() == ISD::SUB) + RHSC = -RHSC; + + if (RHSC >= 0 && RHSC < 0x1000) { // 12 bits (unsigned) + Base = N.getOperand(0); + if (Base.getOpcode() == ISD::FrameIndex) { + int FI = cast(Base)->getIndex(); + Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); + } + OffImm = CurDAG->getTargetConstant(RHSC, MVT::i32); + return true; + } + } + + // Base only. + Base = N; + OffImm = CurDAG->getTargetConstant(0, MVT::i32); + return true; +} + +bool ARMDAGToDAGISel::SelectT2AddrModeImm8(SDValue Op, SDValue N, + SDValue &Base, SDValue &OffImm) { + // Match simple R - imm8 operands. + if (N.getOpcode() == ISD::ADD || N.getOpcode() == ISD::SUB) { + if (ConstantSDNode *RHS = dyn_cast(N.getOperand(1))) { + int RHSC = (int)RHS->getSExtValue(); + if (N.getOpcode() == ISD::SUB) + RHSC = -RHSC; + + if ((RHSC >= -255) && (RHSC < 0)) { // 8 bits (always negative) + Base = N.getOperand(0); + if (Base.getOpcode() == ISD::FrameIndex) { + int FI = cast(Base)->getIndex(); + Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); + } + OffImm = CurDAG->getTargetConstant(RHSC, MVT::i32); + return true; + } + } + } + + return false; +} + +bool ARMDAGToDAGISel::SelectT2AddrModeImm8Offset(SDValue Op, SDValue N, + SDValue &OffImm){ + unsigned Opcode = Op.getOpcode(); + ISD::MemIndexedMode AM = (Opcode == ISD::LOAD) + ? cast(Op)->getAddressingMode() + : cast(Op)->getAddressingMode(); + if (ConstantSDNode *RHS = dyn_cast(N)) { + int RHSC = (int)RHS->getZExtValue(); + if (RHSC >= 0 && RHSC < 0x100) { // 8 bits. + OffImm = ((AM == ISD::PRE_INC) || (AM == ISD::POST_INC)) + ? CurDAG->getTargetConstant(RHSC, MVT::i32) + : CurDAG->getTargetConstant(-RHSC, MVT::i32); + return true; + } + } + + return false; +} + +bool ARMDAGToDAGISel::SelectT2AddrModeImm8s4(SDValue Op, SDValue N, + SDValue &Base, SDValue &OffImm) { + if (N.getOpcode() == ISD::ADD) { + if (ConstantSDNode *RHS = dyn_cast(N.getOperand(1))) { + int RHSC = (int)RHS->getZExtValue(); + if (((RHSC & 0x3) == 0) && + ((RHSC >= 0 && RHSC < 0x400) || (RHSC < 0 && RHSC > -0x400))) { // 8 bits. + Base = N.getOperand(0); + OffImm = CurDAG->getTargetConstant(RHSC, MVT::i32); + return true; + } + } + } else if (N.getOpcode() == ISD::SUB) { + if (ConstantSDNode *RHS = dyn_cast(N.getOperand(1))) { + int RHSC = (int)RHS->getZExtValue(); + if (((RHSC & 0x3) == 0) && (RHSC >= 0 && RHSC < 0x400)) { // 8 bits. + Base = N.getOperand(0); + OffImm = CurDAG->getTargetConstant(-RHSC, MVT::i32); + return true; + } + } + } + + return false; +} + +bool ARMDAGToDAGISel::SelectT2AddrModeSoReg(SDValue Op, SDValue N, + SDValue &Base, + SDValue &OffReg, SDValue &ShImm) { + // (R - imm8) should be handled by t2LDRi8. The rest are handled by t2LDRi12. + if (N.getOpcode() != ISD::ADD) + return false; + + // Leave (R + imm12) for t2LDRi12, (R - imm8) for t2LDRi8. + if (ConstantSDNode *RHS = dyn_cast(N.getOperand(1))) { + int RHSC = (int)RHS->getZExtValue(); + if (RHSC >= 0 && RHSC < 0x1000) // 12 bits (unsigned) + return false; + else if (RHSC < 0 && RHSC >= -255) // 8 bits + return false; + } + + // Look for (R + R) or (R + (R << [1,2,3])). + unsigned ShAmt = 0; + Base = N.getOperand(0); + OffReg = N.getOperand(1); + + // Swap if it is ((R << c) + R). + ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(OffReg); + if (ShOpcVal != ARM_AM::lsl) { + ShOpcVal = ARM_AM::getShiftOpcForNode(Base); + if (ShOpcVal == ARM_AM::lsl) + std::swap(Base, OffReg); + } + + if (ShOpcVal == ARM_AM::lsl) { + // Check to see if the RHS of the shift is a constant, if not, we can't fold + // it. + if (ConstantSDNode *Sh = dyn_cast(OffReg.getOperand(1))) { + ShAmt = Sh->getZExtValue(); + if (ShAmt >= 4) { + ShAmt = 0; + ShOpcVal = ARM_AM::no_shift; + } else + OffReg = OffReg.getOperand(0); + } else { + ShOpcVal = ARM_AM::no_shift; + } + } + + ShImm = CurDAG->getTargetConstant(ShAmt, MVT::i32); + + return true; +} + +//===--------------------------------------------------------------------===// + +/// getAL - Returns a ARMCC::AL immediate node. +static inline SDValue getAL(SelectionDAG *CurDAG) { + return CurDAG->getTargetConstant((uint64_t)ARMCC::AL, MVT::i32); +} + +SDNode *ARMDAGToDAGISel::SelectARMIndexedLoad(SDValue Op) { + LoadSDNode *LD = cast(Op); + ISD::MemIndexedMode AM = LD->getAddressingMode(); + if (AM == ISD::UNINDEXED) + return NULL; + + EVT LoadedVT = LD->getMemoryVT(); + SDValue Offset, AMOpc; + bool isPre = (AM == ISD::PRE_INC) || (AM == ISD::PRE_DEC); + unsigned Opcode = 0; + bool Match = false; + if (LoadedVT == MVT::i32 && + SelectAddrMode2Offset(Op, LD->getOffset(), Offset, AMOpc)) { + Opcode = isPre ? ARM::LDR_PRE : ARM::LDR_POST; + Match = true; + } else if (LoadedVT == MVT::i16 && + SelectAddrMode3Offset(Op, LD->getOffset(), Offset, AMOpc)) { + Match = true; + Opcode = (LD->getExtensionType() == ISD::SEXTLOAD) + ? (isPre ? ARM::LDRSH_PRE : ARM::LDRSH_POST) + : (isPre ? ARM::LDRH_PRE : ARM::LDRH_POST); + } else if (LoadedVT == MVT::i8 || LoadedVT == MVT::i1) { + if (LD->getExtensionType() == ISD::SEXTLOAD) { + if (SelectAddrMode3Offset(Op, LD->getOffset(), Offset, AMOpc)) { + Match = true; + Opcode = isPre ? ARM::LDRSB_PRE : ARM::LDRSB_POST; + } + } else { + if (SelectAddrMode2Offset(Op, LD->getOffset(), Offset, AMOpc)) { + Match = true; + Opcode = isPre ? ARM::LDRB_PRE : ARM::LDRB_POST; + } + } + } + + if (Match) { + SDValue Chain = LD->getChain(); + SDValue Base = LD->getBasePtr(); + SDValue Ops[]= { Base, Offset, AMOpc, getAL(CurDAG), + CurDAG->getRegister(0, MVT::i32), Chain }; + return CurDAG->getMachineNode(Opcode, Op.getDebugLoc(), MVT::i32, MVT::i32, + MVT::Other, Ops, 6); + } + + return NULL; +} + +SDNode *ARMDAGToDAGISel::SelectT2IndexedLoad(SDValue Op) { + LoadSDNode *LD = cast(Op); + ISD::MemIndexedMode AM = LD->getAddressingMode(); + if (AM == ISD::UNINDEXED) + return NULL; + + EVT LoadedVT = LD->getMemoryVT(); + bool isSExtLd = LD->getExtensionType() == ISD::SEXTLOAD; + SDValue Offset; + bool isPre = (AM == ISD::PRE_INC) || (AM == ISD::PRE_DEC); + unsigned Opcode = 0; + bool Match = false; + if (SelectT2AddrModeImm8Offset(Op, LD->getOffset(), Offset)) { + switch (LoadedVT.getSimpleVT().SimpleTy) { + case MVT::i32: + Opcode = isPre ? ARM::t2LDR_PRE : ARM::t2LDR_POST; + break; + case MVT::i16: + if (isSExtLd) + Opcode = isPre ? ARM::t2LDRSH_PRE : ARM::t2LDRSH_POST; + else + Opcode = isPre ? ARM::t2LDRH_PRE : ARM::t2LDRH_POST; + break; + case MVT::i8: + case MVT::i1: + if (isSExtLd) + Opcode = isPre ? ARM::t2LDRSB_PRE : ARM::t2LDRSB_POST; + else + Opcode = isPre ? ARM::t2LDRB_PRE : ARM::t2LDRB_POST; + break; + default: + return NULL; + } + Match = true; + } + + if (Match) { + SDValue Chain = LD->getChain(); + SDValue Base = LD->getBasePtr(); + SDValue Ops[]= { Base, Offset, getAL(CurDAG), + CurDAG->getRegister(0, MVT::i32), Chain }; + return CurDAG->getMachineNode(Opcode, Op.getDebugLoc(), MVT::i32, MVT::i32, + MVT::Other, Ops, 5); + } + + return NULL; +} + +SDNode *ARMDAGToDAGISel::SelectDYN_ALLOC(SDValue Op) { + SDNode *N = Op.getNode(); + DebugLoc dl = N->getDebugLoc(); + EVT VT = Op.getValueType(); + SDValue Chain = Op.getOperand(0); + SDValue Size = Op.getOperand(1); + SDValue Align = Op.getOperand(2); + SDValue SP = CurDAG->getRegister(ARM::SP, MVT::i32); + int32_t AlignVal = cast(Align)->getSExtValue(); + if (AlignVal < 0) + // We need to align the stack. Use Thumb1 tAND which is the only thumb + // instruction that can read and write SP. This matches to a pseudo + // instruction that has a chain to ensure the result is written back to + // the stack pointer. + SP = SDValue(CurDAG->getMachineNode(ARM::tANDsp, dl, VT, SP, Align), 0); + + bool isC = isa(Size); + uint32_t C = isC ? cast(Size)->getZExtValue() : ~0UL; + // Handle the most common case for both Thumb1 and Thumb2: + // tSUBspi - immediate is between 0 ... 508 inclusive. + if (C <= 508 && ((C & 3) == 0)) + // FIXME: tSUBspi encode scale 4 implicitly. + return CurDAG->SelectNodeTo(N, ARM::tSUBspi_, VT, MVT::Other, SP, + CurDAG->getTargetConstant(C/4, MVT::i32), + Chain); + + if (Subtarget->isThumb1Only()) { + // Use tADDspr since Thumb1 does not have a sub r, sp, r. ARMISelLowering + // should have negated the size operand already. FIXME: We can't insert + // new target independent node at this stage so we are forced to negate + // it earlier. Is there a better solution? + return CurDAG->SelectNodeTo(N, ARM::tADDspr_, VT, MVT::Other, SP, Size, + Chain); + } else if (Subtarget->isThumb2()) { + if (isC && Predicate_t2_so_imm(Size.getNode())) { + // t2SUBrSPi + SDValue Ops[] = { SP, CurDAG->getTargetConstant(C, MVT::i32), Chain }; + return CurDAG->SelectNodeTo(N, ARM::t2SUBrSPi_, VT, MVT::Other, Ops, 3); + } else if (isC && Predicate_imm0_4095(Size.getNode())) { + // t2SUBrSPi12 + SDValue Ops[] = { SP, CurDAG->getTargetConstant(C, MVT::i32), Chain }; + return CurDAG->SelectNodeTo(N, ARM::t2SUBrSPi12_, VT, MVT::Other, Ops, 3); + } else { + // t2SUBrSPs + SDValue Ops[] = { SP, Size, + getI32Imm(ARM_AM::getSORegOpc(ARM_AM::lsl,0)), Chain }; + return CurDAG->SelectNodeTo(N, ARM::t2SUBrSPs_, VT, MVT::Other, Ops, 4); + } + } + + // FIXME: Add ADD / SUB sp instructions for ARM. + return 0; +} + +/// PairDRegs - Insert a pair of double registers into an implicit def to +/// form a quad register. +SDNode *ARMDAGToDAGISel::PairDRegs(EVT VT, SDValue V0, SDValue V1) { + DebugLoc dl = V0.getNode()->getDebugLoc(); + SDValue Undef = + SDValue(CurDAG->getMachineNode(TargetInstrInfo::IMPLICIT_DEF, dl, VT), 0); + SDValue SubReg0 = CurDAG->getTargetConstant(ARM::DSUBREG_0, MVT::i32); + SDValue SubReg1 = CurDAG->getTargetConstant(ARM::DSUBREG_1, MVT::i32); + SDNode *Pair = CurDAG->getMachineNode(TargetInstrInfo::INSERT_SUBREG, dl, + VT, Undef, V0, SubReg0); + return CurDAG->getMachineNode(TargetInstrInfo::INSERT_SUBREG, dl, + VT, SDValue(Pair, 0), V1, SubReg1); +} + +/// GetNEONSubregVT - Given a type for a 128-bit NEON vector, return the type +/// for a 64-bit subregister of the vector. +static EVT GetNEONSubregVT(EVT VT) { + switch (VT.getSimpleVT().SimpleTy) { + default: llvm_unreachable("unhandled NEON type"); + case MVT::v16i8: return MVT::v8i8; + case MVT::v8i16: return MVT::v4i16; + case MVT::v4f32: return MVT::v2f32; + case MVT::v4i32: return MVT::v2i32; + case MVT::v2i64: return MVT::v1i64; + } +} + +SDNode *ARMDAGToDAGISel::SelectVLD(SDValue Op, unsigned NumVecs, + unsigned *DOpcodes, unsigned *QOpcodes0, + unsigned *QOpcodes1) { + assert(NumVecs >=2 && NumVecs <= 4 && "VLD NumVecs out-of-range"); + SDNode *N = Op.getNode(); + DebugLoc dl = N->getDebugLoc(); + + SDValue MemAddr, MemUpdate, MemOpc, Align; + if (!SelectAddrMode6(Op, N->getOperand(2), MemAddr, MemUpdate, MemOpc, Align)) + return NULL; + + SDValue Chain = N->getOperand(0); + EVT VT = N->getValueType(0); + bool is64BitVector = VT.is64BitVector(); + + unsigned OpcodeIndex; + switch (VT.getSimpleVT().SimpleTy) { + default: llvm_unreachable("unhandled vld type"); + // Double-register operations: + case MVT::v8i8: OpcodeIndex = 0; break; + case MVT::v4i16: OpcodeIndex = 1; break; + case MVT::v2f32: + case MVT::v2i32: OpcodeIndex = 2; break; + case MVT::v1i64: OpcodeIndex = 3; break; + // Quad-register operations: + case MVT::v16i8: OpcodeIndex = 0; break; + case MVT::v8i16: OpcodeIndex = 1; break; + case MVT::v4f32: + case MVT::v4i32: OpcodeIndex = 2; break; + } + + SDValue Pred = CurDAG->getTargetConstant(14, MVT::i32); + SDValue PredReg = CurDAG->getRegister(0, MVT::i32); + if (is64BitVector) { + unsigned Opc = DOpcodes[OpcodeIndex]; + const SDValue Ops[] = { MemAddr, MemUpdate, MemOpc, Align, + Pred, PredReg, Chain }; + std::vector ResTys(NumVecs, VT); + ResTys.push_back(MVT::Other); + return CurDAG->getMachineNode(Opc, dl, ResTys, Ops, 7); + } + + EVT RegVT = GetNEONSubregVT(VT); + if (NumVecs == 2) { + // Quad registers are directly supported for VLD2, + // loading 2 pairs of D regs. + unsigned Opc = QOpcodes0[OpcodeIndex]; + const SDValue Ops[] = { MemAddr, MemUpdate, MemOpc, Align, + Pred, PredReg, Chain }; + std::vector ResTys(4, VT); + ResTys.push_back(MVT::Other); + SDNode *VLd = CurDAG->getMachineNode(Opc, dl, ResTys, Ops, 7); + Chain = SDValue(VLd, 4); + + // Combine the even and odd subregs to produce the result. + for (unsigned Vec = 0; Vec < NumVecs; ++Vec) { + SDNode *Q = PairDRegs(VT, SDValue(VLd, 2*Vec), SDValue(VLd, 2*Vec+1)); + ReplaceUses(SDValue(N, Vec), SDValue(Q, 0)); + } + } else { + // Otherwise, quad registers are loaded with two separate instructions, + // where one loads the even registers and the other loads the odd registers. + + // Enable writeback to the address register. + MemOpc = CurDAG->getTargetConstant(ARM_AM::getAM6Opc(true), MVT::i32); + + std::vector ResTys(NumVecs, RegVT); + ResTys.push_back(MemAddr.getValueType()); + ResTys.push_back(MVT::Other); + + // Load the even subregs. + unsigned Opc = QOpcodes0[OpcodeIndex]; + const SDValue OpsA[] = { MemAddr, MemUpdate, MemOpc, Align, + Pred, PredReg, Chain }; + SDNode *VLdA = CurDAG->getMachineNode(Opc, dl, ResTys, OpsA, 7); + Chain = SDValue(VLdA, NumVecs+1); + + // Load the odd subregs. + Opc = QOpcodes1[OpcodeIndex]; + const SDValue OpsB[] = { SDValue(VLdA, NumVecs), MemUpdate, MemOpc, + Align, Pred, PredReg, Chain }; + SDNode *VLdB = CurDAG->getMachineNode(Opc, dl, ResTys, OpsB, 7); + Chain = SDValue(VLdB, NumVecs+1); + + // Combine the even and odd subregs to produce the result. + for (unsigned Vec = 0; Vec < NumVecs; ++Vec) { + SDNode *Q = PairDRegs(VT, SDValue(VLdA, Vec), SDValue(VLdB, Vec)); + ReplaceUses(SDValue(N, Vec), SDValue(Q, 0)); + } + } + ReplaceUses(SDValue(N, NumVecs), Chain); + return NULL; +} + +SDNode *ARMDAGToDAGISel::SelectVST(SDValue Op, unsigned NumVecs, + unsigned *DOpcodes, unsigned *QOpcodes0, + unsigned *QOpcodes1) { + assert(NumVecs >=2 && NumVecs <= 4 && "VST NumVecs out-of-range"); + SDNode *N = Op.getNode(); + DebugLoc dl = N->getDebugLoc(); + + SDValue MemAddr, MemUpdate, MemOpc, Align; + if (!SelectAddrMode6(Op, N->getOperand(2), MemAddr, MemUpdate, MemOpc, Align)) + return NULL; + + SDValue Chain = N->getOperand(0); + EVT VT = N->getOperand(3).getValueType(); + bool is64BitVector = VT.is64BitVector(); + + unsigned OpcodeIndex; + switch (VT.getSimpleVT().SimpleTy) { + default: llvm_unreachable("unhandled vst type"); + // Double-register operations: + case MVT::v8i8: OpcodeIndex = 0; break; + case MVT::v4i16: OpcodeIndex = 1; break; + case MVT::v2f32: + case MVT::v2i32: OpcodeIndex = 2; break; + case MVT::v1i64: OpcodeIndex = 3; break; + // Quad-register operations: + case MVT::v16i8: OpcodeIndex = 0; break; + case MVT::v8i16: OpcodeIndex = 1; break; + case MVT::v4f32: + case MVT::v4i32: OpcodeIndex = 2; break; + } + + SDValue Pred = CurDAG->getTargetConstant(14, MVT::i32); + SDValue PredReg = CurDAG->getRegister(0, MVT::i32); + + SmallVector Ops; + Ops.push_back(MemAddr); + Ops.push_back(MemUpdate); + Ops.push_back(MemOpc); + Ops.push_back(Align); + + if (is64BitVector) { + unsigned Opc = DOpcodes[OpcodeIndex]; + for (unsigned Vec = 0; Vec < NumVecs; ++Vec) + Ops.push_back(N->getOperand(Vec+3)); + Ops.push_back(Pred); + Ops.push_back(PredReg); + Ops.push_back(Chain); + return CurDAG->getMachineNode(Opc, dl, MVT::Other, Ops.data(), NumVecs+7); + } + + EVT RegVT = GetNEONSubregVT(VT); + if (NumVecs == 2) { + // Quad registers are directly supported for VST2, + // storing 2 pairs of D regs. + unsigned Opc = QOpcodes0[OpcodeIndex]; + for (unsigned Vec = 0; Vec < NumVecs; ++Vec) { + Ops.push_back(CurDAG->getTargetExtractSubreg(ARM::DSUBREG_0, dl, RegVT, + N->getOperand(Vec+3))); + Ops.push_back(CurDAG->getTargetExtractSubreg(ARM::DSUBREG_1, dl, RegVT, + N->getOperand(Vec+3))); + } + Ops.push_back(Pred); + Ops.push_back(PredReg); + Ops.push_back(Chain); + return CurDAG->getMachineNode(Opc, dl, MVT::Other, Ops.data(), 11); + } + + // Otherwise, quad registers are stored with two separate instructions, + // where one stores the even registers and the other stores the odd registers. + + // Enable writeback to the address register. + MemOpc = CurDAG->getTargetConstant(ARM_AM::getAM6Opc(true), MVT::i32); + + // Store the even subregs. + for (unsigned Vec = 0; Vec < NumVecs; ++Vec) + Ops.push_back(CurDAG->getTargetExtractSubreg(ARM::DSUBREG_0, dl, RegVT, + N->getOperand(Vec+3))); + Ops.push_back(Pred); + Ops.push_back(PredReg); + Ops.push_back(Chain); + unsigned Opc = QOpcodes0[OpcodeIndex]; + SDNode *VStA = CurDAG->getMachineNode(Opc, dl, MemAddr.getValueType(), + MVT::Other, Ops.data(), NumVecs+7); + Chain = SDValue(VStA, 1); + + // Store the odd subregs. + Ops[0] = SDValue(VStA, 0); // MemAddr + for (unsigned Vec = 0; Vec < NumVecs; ++Vec) + Ops[Vec+4] = CurDAG->getTargetExtractSubreg(ARM::DSUBREG_1, dl, RegVT, + N->getOperand(Vec+3)); + Ops[NumVecs+4] = Pred; + Ops[NumVecs+5] = PredReg; + Ops[NumVecs+6] = Chain; + Opc = QOpcodes1[OpcodeIndex]; + SDNode *VStB = CurDAG->getMachineNode(Opc, dl, MemAddr.getValueType(), + MVT::Other, Ops.data(), NumVecs+7); + Chain = SDValue(VStB, 1); + ReplaceUses(SDValue(N, 0), Chain); + return NULL; +} + +SDNode *ARMDAGToDAGISel::SelectVLDSTLane(SDValue Op, bool IsLoad, + unsigned NumVecs, unsigned *DOpcodes, + unsigned *QOpcodes0, + unsigned *QOpcodes1) { + assert(NumVecs >=2 && NumVecs <= 4 && "VLDSTLane NumVecs out-of-range"); + SDNode *N = Op.getNode(); + DebugLoc dl = N->getDebugLoc(); + + SDValue MemAddr, MemUpdate, MemOpc, Align; + if (!SelectAddrMode6(Op, N->getOperand(2), MemAddr, MemUpdate, MemOpc, Align)) + return NULL; + + SDValue Chain = N->getOperand(0); + unsigned Lane = + cast(N->getOperand(NumVecs+3))->getZExtValue(); + EVT VT = IsLoad ? N->getValueType(0) : N->getOperand(3).getValueType(); + bool is64BitVector = VT.is64BitVector(); + + // Quad registers are handled by load/store of subregs. Find the subreg info. + unsigned NumElts = 0; + int SubregIdx = 0; + EVT RegVT = VT; + if (!is64BitVector) { + RegVT = GetNEONSubregVT(VT); + NumElts = RegVT.getVectorNumElements(); + SubregIdx = (Lane < NumElts) ? ARM::DSUBREG_0 : ARM::DSUBREG_1; + } + + unsigned OpcodeIndex; + switch (VT.getSimpleVT().SimpleTy) { + default: llvm_unreachable("unhandled vld/vst lane type"); + // Double-register operations: + case MVT::v8i8: OpcodeIndex = 0; break; + case MVT::v4i16: OpcodeIndex = 1; break; + case MVT::v2f32: + case MVT::v2i32: OpcodeIndex = 2; break; + // Quad-register operations: + case MVT::v8i16: OpcodeIndex = 0; break; + case MVT::v4f32: + case MVT::v4i32: OpcodeIndex = 1; break; + } + + SDValue Pred = CurDAG->getTargetConstant(14, MVT::i32); + SDValue PredReg = CurDAG->getRegister(0, MVT::i32); + + SmallVector Ops; + Ops.push_back(MemAddr); + Ops.push_back(MemUpdate); + Ops.push_back(MemOpc); + Ops.push_back(Align); + + unsigned Opc = 0; + if (is64BitVector) { + Opc = DOpcodes[OpcodeIndex]; + for (unsigned Vec = 0; Vec < NumVecs; ++Vec) + Ops.push_back(N->getOperand(Vec+3)); + } else { + // Check if this is loading the even or odd subreg of a Q register. + if (Lane < NumElts) { + Opc = QOpcodes0[OpcodeIndex]; + } else { + Lane -= NumElts; + Opc = QOpcodes1[OpcodeIndex]; + } + // Extract the subregs of the input vector. + for (unsigned Vec = 0; Vec < NumVecs; ++Vec) + Ops.push_back(CurDAG->getTargetExtractSubreg(SubregIdx, dl, RegVT, + N->getOperand(Vec+3))); + } + Ops.push_back(getI32Imm(Lane)); + Ops.push_back(Pred); + Ops.push_back(PredReg); + Ops.push_back(Chain); + + if (!IsLoad) + return CurDAG->getMachineNode(Opc, dl, MVT::Other, Ops.data(), NumVecs+7); + + std::vector ResTys(NumVecs, RegVT); + ResTys.push_back(MVT::Other); + SDNode *VLdLn = + CurDAG->getMachineNode(Opc, dl, ResTys, Ops.data(), NumVecs+7); + // For a 64-bit vector load to D registers, nothing more needs to be done. + if (is64BitVector) + return VLdLn; + + // For 128-bit vectors, take the 64-bit results of the load and insert them + // as subregs into the result. + for (unsigned Vec = 0; Vec < NumVecs; ++Vec) { + SDValue QuadVec = CurDAG->getTargetInsertSubreg(SubregIdx, dl, VT, + N->getOperand(Vec+3), + SDValue(VLdLn, Vec)); + ReplaceUses(SDValue(N, Vec), QuadVec); + } + + Chain = SDValue(VLdLn, NumVecs); + ReplaceUses(SDValue(N, NumVecs), Chain); + return NULL; +} + +SDNode *ARMDAGToDAGISel::SelectV6T2BitfieldExtractOp(SDValue Op, + unsigned Opc) { + if (!Subtarget->hasV6T2Ops()) + return NULL; + + unsigned Shl_imm = 0; + if (isOpcWithIntImmediate(Op.getOperand(0).getNode(), ISD::SHL, Shl_imm)) { + assert(Shl_imm > 0 && Shl_imm < 32 && "bad amount in shift node!"); + unsigned Srl_imm = 0; + if (isInt32Immediate(Op.getOperand(1), Srl_imm)) { + assert(Srl_imm > 0 && Srl_imm < 32 && "bad amount in shift node!"); + unsigned Width = 32 - Srl_imm; + int LSB = Srl_imm - Shl_imm; + if (LSB < 0) + return NULL; + SDValue Reg0 = CurDAG->getRegister(0, MVT::i32); + SDValue Ops[] = { Op.getOperand(0).getOperand(0), + CurDAG->getTargetConstant(LSB, MVT::i32), + CurDAG->getTargetConstant(Width, MVT::i32), + getAL(CurDAG), Reg0 }; + return CurDAG->SelectNodeTo(Op.getNode(), Opc, MVT::i32, Ops, 5); + } + } + return NULL; +} + +SDNode *ARMDAGToDAGISel:: +SelectT2CMOVShiftOp(SDValue Op, SDValue FalseVal, SDValue TrueVal, + ARMCC::CondCodes CCVal, SDValue CCR, SDValue InFlag) { + SDValue CPTmp0; + SDValue CPTmp1; + if (SelectT2ShifterOperandReg(Op, TrueVal, CPTmp0, CPTmp1)) { + unsigned SOVal = cast(CPTmp1)->getZExtValue(); + unsigned SOShOp = ARM_AM::getSORegShOp(SOVal); + unsigned Opc = 0; + switch (SOShOp) { + case ARM_AM::lsl: Opc = ARM::t2MOVCClsl; break; + case ARM_AM::lsr: Opc = ARM::t2MOVCClsr; break; + case ARM_AM::asr: Opc = ARM::t2MOVCCasr; break; + case ARM_AM::ror: Opc = ARM::t2MOVCCror; break; + default: + llvm_unreachable("Unknown so_reg opcode!"); + break; + } + SDValue SOShImm = + CurDAG->getTargetConstant(ARM_AM::getSORegOffset(SOVal), MVT::i32); + SDValue CC = CurDAG->getTargetConstant(CCVal, MVT::i32); + SDValue Ops[] = { FalseVal, CPTmp0, SOShImm, CC, CCR, InFlag }; + return CurDAG->SelectNodeTo(Op.getNode(), Opc, MVT::i32,Ops, 6); + } + return 0; +} + +SDNode *ARMDAGToDAGISel:: +SelectARMCMOVShiftOp(SDValue Op, SDValue FalseVal, SDValue TrueVal, + ARMCC::CondCodes CCVal, SDValue CCR, SDValue InFlag) { + SDValue CPTmp0; + SDValue CPTmp1; + SDValue CPTmp2; + if (SelectShifterOperandReg(Op, TrueVal, CPTmp0, CPTmp1, CPTmp2)) { + SDValue CC = CurDAG->getTargetConstant(CCVal, MVT::i32); + SDValue Ops[] = { FalseVal, CPTmp0, CPTmp1, CPTmp2, CC, CCR, InFlag }; + return CurDAG->SelectNodeTo(Op.getNode(), ARM::MOVCCs, MVT::i32, Ops, 7); + } + return 0; +} + +SDNode *ARMDAGToDAGISel:: +SelectT2CMOVSoImmOp(SDValue Op, SDValue FalseVal, SDValue TrueVal, + ARMCC::CondCodes CCVal, SDValue CCR, SDValue InFlag) { + ConstantSDNode *T = dyn_cast(TrueVal); + if (!T) + return 0; + + if (Predicate_t2_so_imm(TrueVal.getNode())) { + SDValue True = CurDAG->getTargetConstant(T->getZExtValue(), MVT::i32); + SDValue CC = CurDAG->getTargetConstant(CCVal, MVT::i32); + SDValue Ops[] = { FalseVal, True, CC, CCR, InFlag }; + return CurDAG->SelectNodeTo(Op.getNode(), + ARM::t2MOVCCi, MVT::i32, Ops, 5); + } + return 0; +} + +SDNode *ARMDAGToDAGISel:: +SelectARMCMOVSoImmOp(SDValue Op, SDValue FalseVal, SDValue TrueVal, + ARMCC::CondCodes CCVal, SDValue CCR, SDValue InFlag) { + ConstantSDNode *T = dyn_cast(TrueVal); + if (!T) + return 0; + + if (Predicate_so_imm(TrueVal.getNode())) { + SDValue True = CurDAG->getTargetConstant(T->getZExtValue(), MVT::i32); + SDValue CC = CurDAG->getTargetConstant(CCVal, MVT::i32); + SDValue Ops[] = { FalseVal, True, CC, CCR, InFlag }; + return CurDAG->SelectNodeTo(Op.getNode(), + ARM::MOVCCi, MVT::i32, Ops, 5); + } + return 0; +} + +SDNode *ARMDAGToDAGISel::SelectCMOVOp(SDValue Op) { + EVT VT = Op.getValueType(); + SDValue FalseVal = Op.getOperand(0); + SDValue TrueVal = Op.getOperand(1); + SDValue CC = Op.getOperand(2); + SDValue CCR = Op.getOperand(3); + SDValue InFlag = Op.getOperand(4); + assert(CC.getOpcode() == ISD::Constant); + assert(CCR.getOpcode() == ISD::Register); + ARMCC::CondCodes CCVal = + (ARMCC::CondCodes)cast(CC)->getZExtValue(); + + if (!Subtarget->isThumb1Only() && VT == MVT::i32) { + // Pattern: (ARMcmov:i32 GPR:i32:$false, so_reg:i32:$true, (imm:i32):$cc) + // Emits: (MOVCCs:i32 GPR:i32:$false, so_reg:i32:$true, (imm:i32):$cc) + // Pattern complexity = 18 cost = 1 size = 0 + SDValue CPTmp0; + SDValue CPTmp1; + SDValue CPTmp2; + if (Subtarget->isThumb()) { + SDNode *Res = SelectT2CMOVShiftOp(Op, FalseVal, TrueVal, + CCVal, CCR, InFlag); + if (!Res) + Res = SelectT2CMOVShiftOp(Op, TrueVal, FalseVal, + ARMCC::getOppositeCondition(CCVal), CCR, InFlag); + if (Res) + return Res; + } else { + SDNode *Res = SelectARMCMOVShiftOp(Op, FalseVal, TrueVal, + CCVal, CCR, InFlag); + if (!Res) + Res = SelectARMCMOVShiftOp(Op, TrueVal, FalseVal, + ARMCC::getOppositeCondition(CCVal), CCR, InFlag); + if (Res) + return Res; + } + + // Pattern: (ARMcmov:i32 GPR:i32:$false, + // (imm:i32)<>:$true, + // (imm:i32):$cc) + // Emits: (MOVCCi:i32 GPR:i32:$false, + // (so_imm:i32 (imm:i32):$true), (imm:i32):$cc) + // Pattern complexity = 10 cost = 1 size = 0 + if (Subtarget->isThumb()) { + SDNode *Res = SelectT2CMOVSoImmOp(Op, FalseVal, TrueVal, + CCVal, CCR, InFlag); + if (!Res) + Res = SelectT2CMOVSoImmOp(Op, TrueVal, FalseVal, + ARMCC::getOppositeCondition(CCVal), CCR, InFlag); + if (Res) + return Res; + } else { + SDNode *Res = SelectARMCMOVSoImmOp(Op, FalseVal, TrueVal, + CCVal, CCR, InFlag); + if (!Res) + Res = SelectARMCMOVSoImmOp(Op, TrueVal, FalseVal, + ARMCC::getOppositeCondition(CCVal), CCR, InFlag); + if (Res) + return Res; + } + } + + // Pattern: (ARMcmov:i32 GPR:i32:$false, GPR:i32:$true, (imm:i32):$cc) + // Emits: (MOVCCr:i32 GPR:i32:$false, GPR:i32:$true, (imm:i32):$cc) + // Pattern complexity = 6 cost = 1 size = 0 + // + // Pattern: (ARMcmov:i32 GPR:i32:$false, GPR:i32:$true, (imm:i32):$cc) + // Emits: (tMOVCCr:i32 GPR:i32:$false, GPR:i32:$true, (imm:i32):$cc) + // Pattern complexity = 6 cost = 11 size = 0 + // + // Also FCPYScc and FCPYDcc. + SDValue Tmp2 = CurDAG->getTargetConstant(CCVal, MVT::i32); + SDValue Ops[] = { FalseVal, TrueVal, Tmp2, CCR, InFlag }; + unsigned Opc = 0; + switch (VT.getSimpleVT().SimpleTy) { + default: assert(false && "Illegal conditional move type!"); + break; + case MVT::i32: + Opc = Subtarget->isThumb() + ? (Subtarget->hasThumb2() ? ARM::t2MOVCCr : ARM::tMOVCCr_pseudo) + : ARM::MOVCCr; + break; + case MVT::f32: + Opc = ARM::VMOVScc; + break; + case MVT::f64: + Opc = ARM::VMOVDcc; + break; + } + return CurDAG->SelectNodeTo(Op.getNode(), Opc, VT, Ops, 5); +} + +SDNode *ARMDAGToDAGISel::Select(SDValue Op) { + SDNode *N = Op.getNode(); + DebugLoc dl = N->getDebugLoc(); + + if (N->isMachineOpcode()) + return NULL; // Already selected. + + switch (N->getOpcode()) { + default: break; + case ISD::Constant: { + unsigned Val = cast(N)->getZExtValue(); + bool UseCP = true; + if (Subtarget->hasThumb2()) + // Thumb2-aware targets have the MOVT instruction, so all immediates can + // be done with MOV + MOVT, at worst. + UseCP = 0; + else { + if (Subtarget->isThumb()) { + UseCP = (Val > 255 && // MOV + ~Val > 255 && // MOV + MVN + !ARM_AM::isThumbImmShiftedVal(Val)); // MOV + LSL + } else + UseCP = (ARM_AM::getSOImmVal(Val) == -1 && // MOV + ARM_AM::getSOImmVal(~Val) == -1 && // MVN + !ARM_AM::isSOImmTwoPartVal(Val)); // two instrs. + } + + if (UseCP) { + SDValue CPIdx = + CurDAG->getTargetConstantPool(ConstantInt::get( + Type::getInt32Ty(*CurDAG->getContext()), Val), + TLI.getPointerTy()); + + SDNode *ResNode; + if (Subtarget->isThumb1Only()) { + SDValue Pred = CurDAG->getTargetConstant(14, MVT::i32); + SDValue PredReg = CurDAG->getRegister(0, MVT::i32); + SDValue Ops[] = { CPIdx, Pred, PredReg, CurDAG->getEntryNode() }; + ResNode = CurDAG->getMachineNode(ARM::tLDRcp, dl, MVT::i32, MVT::Other, + Ops, 4); + } else { + SDValue Ops[] = { + CPIdx, + CurDAG->getRegister(0, MVT::i32), + CurDAG->getTargetConstant(0, MVT::i32), + getAL(CurDAG), + CurDAG->getRegister(0, MVT::i32), + CurDAG->getEntryNode() + }; + ResNode=CurDAG->getMachineNode(ARM::LDRcp, dl, MVT::i32, MVT::Other, + Ops, 6); + } + ReplaceUses(Op, SDValue(ResNode, 0)); + return NULL; + } + + // Other cases are autogenerated. + break; + } + case ISD::FrameIndex: { + // Selects to ADDri FI, 0 which in turn will become ADDri SP, imm. + int FI = cast(N)->getIndex(); + SDValue TFI = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); + if (Subtarget->isThumb1Only()) { + return CurDAG->SelectNodeTo(N, ARM::tADDrSPi, MVT::i32, TFI, + CurDAG->getTargetConstant(0, MVT::i32)); + } else { + unsigned Opc = ((Subtarget->isThumb() && Subtarget->hasThumb2()) ? + ARM::t2ADDri : ARM::ADDri); + SDValue Ops[] = { TFI, CurDAG->getTargetConstant(0, MVT::i32), + getAL(CurDAG), CurDAG->getRegister(0, MVT::i32), + CurDAG->getRegister(0, MVT::i32) }; + return CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops, 5); + } + } + case ARMISD::DYN_ALLOC: + return SelectDYN_ALLOC(Op); + case ISD::SRL: + if (SDNode *I = SelectV6T2BitfieldExtractOp(Op, + Subtarget->isThumb() ? ARM::t2UBFX : ARM::UBFX)) + return I; + break; + case ISD::SRA: + if (SDNode *I = SelectV6T2BitfieldExtractOp(Op, + Subtarget->isThumb() ? ARM::t2SBFX : ARM::SBFX)) + return I; + break; + case ISD::MUL: + if (Subtarget->isThumb1Only()) + break; + if (ConstantSDNode *C = dyn_cast(Op.getOperand(1))) { + unsigned RHSV = C->getZExtValue(); + if (!RHSV) break; + if (isPowerOf2_32(RHSV-1)) { // 2^n+1? + unsigned ShImm = Log2_32(RHSV-1); + if (ShImm >= 32) + break; + SDValue V = Op.getOperand(0); + ShImm = ARM_AM::getSORegOpc(ARM_AM::lsl, ShImm); + SDValue ShImmOp = CurDAG->getTargetConstant(ShImm, MVT::i32); + SDValue Reg0 = CurDAG->getRegister(0, MVT::i32); + if (Subtarget->isThumb()) { + SDValue Ops[] = { V, V, ShImmOp, getAL(CurDAG), Reg0, Reg0 }; + return CurDAG->SelectNodeTo(N, ARM::t2ADDrs, MVT::i32, Ops, 6); + } else { + SDValue Ops[] = { V, V, Reg0, ShImmOp, getAL(CurDAG), Reg0, Reg0 }; + return CurDAG->SelectNodeTo(N, ARM::ADDrs, MVT::i32, Ops, 7); + } + } + if (isPowerOf2_32(RHSV+1)) { // 2^n-1? + unsigned ShImm = Log2_32(RHSV+1); + if (ShImm >= 32) + break; + SDValue V = Op.getOperand(0); + ShImm = ARM_AM::getSORegOpc(ARM_AM::lsl, ShImm); + SDValue ShImmOp = CurDAG->getTargetConstant(ShImm, MVT::i32); + SDValue Reg0 = CurDAG->getRegister(0, MVT::i32); + if (Subtarget->isThumb()) { + SDValue Ops[] = { V, V, ShImmOp, getAL(CurDAG), Reg0 }; + return CurDAG->SelectNodeTo(N, ARM::t2RSBrs, MVT::i32, Ops, 5); + } else { + SDValue Ops[] = { V, V, Reg0, ShImmOp, getAL(CurDAG), Reg0, Reg0 }; + return CurDAG->SelectNodeTo(N, ARM::RSBrs, MVT::i32, Ops, 7); + } + } + } + break; + case ISD::AND: { + // (and (or x, c2), c1) and top 16-bits of c1 and c2 match, lower 16-bits + // of c1 are 0xffff, and lower 16-bit of c2 are 0. That is, the top 16-bits + // are entirely contributed by c2 and lower 16-bits are entirely contributed + // by x. That's equal to (or (and x, 0xffff), (and c1, 0xffff0000)). + // Select it to: "movt x, ((c1 & 0xffff) >> 16) + EVT VT = Op.getValueType(); + if (VT != MVT::i32) + break; + unsigned Opc = (Subtarget->isThumb() && Subtarget->hasThumb2()) + ? ARM::t2MOVTi16 + : (Subtarget->hasV6T2Ops() ? ARM::MOVTi16 : 0); + if (!Opc) + break; + SDValue N0 = Op.getOperand(0), N1 = Op.getOperand(1); + ConstantSDNode *N1C = dyn_cast(N1); + if (!N1C) + break; + if (N0.getOpcode() == ISD::OR && N0.getNode()->hasOneUse()) { + SDValue N2 = N0.getOperand(1); + ConstantSDNode *N2C = dyn_cast(N2); + if (!N2C) + break; + unsigned N1CVal = N1C->getZExtValue(); + unsigned N2CVal = N2C->getZExtValue(); + if ((N1CVal & 0xffff0000U) == (N2CVal & 0xffff0000U) && + (N1CVal & 0xffffU) == 0xffffU && + (N2CVal & 0xffffU) == 0x0U) { + SDValue Imm16 = CurDAG->getTargetConstant((N2CVal & 0xFFFF0000U) >> 16, + MVT::i32); + SDValue Ops[] = { N0.getOperand(0), Imm16, + getAL(CurDAG), CurDAG->getRegister(0, MVT::i32) }; + return CurDAG->getMachineNode(Opc, dl, VT, Ops, 4); + } + } + break; + } + case ARMISD::VMOVRRD: + return CurDAG->getMachineNode(ARM::VMOVRRD, dl, MVT::i32, MVT::i32, + Op.getOperand(0), getAL(CurDAG), + CurDAG->getRegister(0, MVT::i32)); + case ISD::UMUL_LOHI: { + if (Subtarget->isThumb1Only()) + break; + if (Subtarget->isThumb()) { + SDValue Ops[] = { Op.getOperand(0), Op.getOperand(1), + getAL(CurDAG), CurDAG->getRegister(0, MVT::i32), + CurDAG->getRegister(0, MVT::i32) }; + return CurDAG->getMachineNode(ARM::t2UMULL, dl, MVT::i32, MVT::i32, Ops,4); + } else { + SDValue Ops[] = { Op.getOperand(0), Op.getOperand(1), + getAL(CurDAG), CurDAG->getRegister(0, MVT::i32), + CurDAG->getRegister(0, MVT::i32) }; + return CurDAG->getMachineNode(ARM::UMULL, dl, MVT::i32, MVT::i32, Ops, 5); + } + } + case ISD::SMUL_LOHI: { + if (Subtarget->isThumb1Only()) + break; + if (Subtarget->isThumb()) { + SDValue Ops[] = { Op.getOperand(0), Op.getOperand(1), + getAL(CurDAG), CurDAG->getRegister(0, MVT::i32) }; + return CurDAG->getMachineNode(ARM::t2SMULL, dl, MVT::i32, MVT::i32, Ops,4); + } else { + SDValue Ops[] = { Op.getOperand(0), Op.getOperand(1), + getAL(CurDAG), CurDAG->getRegister(0, MVT::i32), + CurDAG->getRegister(0, MVT::i32) }; + return CurDAG->getMachineNode(ARM::SMULL, dl, MVT::i32, MVT::i32, Ops, 5); + } + } + case ISD::LOAD: { + SDNode *ResNode = 0; + if (Subtarget->isThumb() && Subtarget->hasThumb2()) + ResNode = SelectT2IndexedLoad(Op); + else + ResNode = SelectARMIndexedLoad(Op); + if (ResNode) + return ResNode; + // Other cases are autogenerated. + break; + } + case ARMISD::BRCOND: { + // Pattern: (ARMbrcond:void (bb:Other):$dst, (imm:i32):$cc) + // Emits: (Bcc:void (bb:Other):$dst, (imm:i32):$cc) + // Pattern complexity = 6 cost = 1 size = 0 + + // Pattern: (ARMbrcond:void (bb:Other):$dst, (imm:i32):$cc) + // Emits: (tBcc:void (bb:Other):$dst, (imm:i32):$cc) + // Pattern complexity = 6 cost = 1 size = 0 + + // Pattern: (ARMbrcond:void (bb:Other):$dst, (imm:i32):$cc) + // Emits: (t2Bcc:void (bb:Other):$dst, (imm:i32):$cc) + // Pattern complexity = 6 cost = 1 size = 0 + + unsigned Opc = Subtarget->isThumb() ? + ((Subtarget->hasThumb2()) ? ARM::t2Bcc : ARM::tBcc) : ARM::Bcc; + SDValue Chain = Op.getOperand(0); + SDValue N1 = Op.getOperand(1); + SDValue N2 = Op.getOperand(2); + SDValue N3 = Op.getOperand(3); + SDValue InFlag = Op.getOperand(4); + assert(N1.getOpcode() == ISD::BasicBlock); + assert(N2.getOpcode() == ISD::Constant); + assert(N3.getOpcode() == ISD::Register); + + SDValue Tmp2 = CurDAG->getTargetConstant(((unsigned) + cast(N2)->getZExtValue()), + MVT::i32); + SDValue Ops[] = { N1, Tmp2, N3, Chain, InFlag }; + SDNode *ResNode = CurDAG->getMachineNode(Opc, dl, MVT::Other, + MVT::Flag, Ops, 5); + Chain = SDValue(ResNode, 0); + if (Op.getNode()->getNumValues() == 2) { + InFlag = SDValue(ResNode, 1); + ReplaceUses(SDValue(Op.getNode(), 1), InFlag); + } + ReplaceUses(SDValue(Op.getNode(), 0), + SDValue(Chain.getNode(), Chain.getResNo())); + return NULL; + } + case ARMISD::CMOV: + return SelectCMOVOp(Op); + case ARMISD::CNEG: { + EVT VT = Op.getValueType(); + SDValue N0 = Op.getOperand(0); + SDValue N1 = Op.getOperand(1); + SDValue N2 = Op.getOperand(2); + SDValue N3 = Op.getOperand(3); + SDValue InFlag = Op.getOperand(4); + assert(N2.getOpcode() == ISD::Constant); + assert(N3.getOpcode() == ISD::Register); + + SDValue Tmp2 = CurDAG->getTargetConstant(((unsigned) + cast(N2)->getZExtValue()), + MVT::i32); + SDValue Ops[] = { N0, N1, Tmp2, N3, InFlag }; + unsigned Opc = 0; + switch (VT.getSimpleVT().SimpleTy) { + default: assert(false && "Illegal conditional move type!"); + break; + case MVT::f32: + Opc = ARM::VNEGScc; + break; + case MVT::f64: + Opc = ARM::VNEGDcc; + break; + } + return CurDAG->SelectNodeTo(Op.getNode(), Opc, VT, Ops, 5); + } + + case ARMISD::VZIP: { + unsigned Opc = 0; + EVT VT = N->getValueType(0); + switch (VT.getSimpleVT().SimpleTy) { + default: return NULL; + case MVT::v8i8: Opc = ARM::VZIPd8; break; + case MVT::v4i16: Opc = ARM::VZIPd16; break; + case MVT::v2f32: + case MVT::v2i32: Opc = ARM::VZIPd32; break; + case MVT::v16i8: Opc = ARM::VZIPq8; break; + case MVT::v8i16: Opc = ARM::VZIPq16; break; + case MVT::v4f32: + case MVT::v4i32: Opc = ARM::VZIPq32; break; + } + SDValue Pred = CurDAG->getTargetConstant(14, MVT::i32); + SDValue PredReg = CurDAG->getRegister(0, MVT::i32); + SDValue Ops[] = { N->getOperand(0), N->getOperand(1), Pred, PredReg }; + return CurDAG->getMachineNode(Opc, dl, VT, VT, Ops, 4); + } + case ARMISD::VUZP: { + unsigned Opc = 0; + EVT VT = N->getValueType(0); + switch (VT.getSimpleVT().SimpleTy) { + default: return NULL; + case MVT::v8i8: Opc = ARM::VUZPd8; break; + case MVT::v4i16: Opc = ARM::VUZPd16; break; + case MVT::v2f32: + case MVT::v2i32: Opc = ARM::VUZPd32; break; + case MVT::v16i8: Opc = ARM::VUZPq8; break; + case MVT::v8i16: Opc = ARM::VUZPq16; break; + case MVT::v4f32: + case MVT::v4i32: Opc = ARM::VUZPq32; break; + } + SDValue Pred = CurDAG->getTargetConstant(14, MVT::i32); + SDValue PredReg = CurDAG->getRegister(0, MVT::i32); + SDValue Ops[] = { N->getOperand(0), N->getOperand(1), Pred, PredReg }; + return CurDAG->getMachineNode(Opc, dl, VT, VT, Ops, 4); + } + case ARMISD::VTRN: { + unsigned Opc = 0; + EVT VT = N->getValueType(0); + switch (VT.getSimpleVT().SimpleTy) { + default: return NULL; + case MVT::v8i8: Opc = ARM::VTRNd8; break; + case MVT::v4i16: Opc = ARM::VTRNd16; break; + case MVT::v2f32: + case MVT::v2i32: Opc = ARM::VTRNd32; break; + case MVT::v16i8: Opc = ARM::VTRNq8; break; + case MVT::v8i16: Opc = ARM::VTRNq16; break; + case MVT::v4f32: + case MVT::v4i32: Opc = ARM::VTRNq32; break; + } + SDValue Pred = CurDAG->getTargetConstant(14, MVT::i32); + SDValue PredReg = CurDAG->getRegister(0, MVT::i32); + SDValue Ops[] = { N->getOperand(0), N->getOperand(1), Pred, PredReg }; + return CurDAG->getMachineNode(Opc, dl, VT, VT, Ops, 4); + } + + case ISD::INTRINSIC_VOID: + case ISD::INTRINSIC_W_CHAIN: { + unsigned IntNo = cast(N->getOperand(1))->getZExtValue(); + switch (IntNo) { + default: + break; + + case Intrinsic::arm_neon_vld2: { + unsigned DOpcodes[] = { ARM::VLD2d8, ARM::VLD2d16, + ARM::VLD2d32, ARM::VLD2d64 }; + unsigned QOpcodes[] = { ARM::VLD2q8, ARM::VLD2q16, ARM::VLD2q32 }; + return SelectVLD(Op, 2, DOpcodes, QOpcodes, 0); + } + + case Intrinsic::arm_neon_vld3: { + unsigned DOpcodes[] = { ARM::VLD3d8, ARM::VLD3d16, + ARM::VLD3d32, ARM::VLD3d64 }; + unsigned QOpcodes0[] = { ARM::VLD3q8a, ARM::VLD3q16a, ARM::VLD3q32a }; + unsigned QOpcodes1[] = { ARM::VLD3q8b, ARM::VLD3q16b, ARM::VLD3q32b }; + return SelectVLD(Op, 3, DOpcodes, QOpcodes0, QOpcodes1); + } + + case Intrinsic::arm_neon_vld4: { + unsigned DOpcodes[] = { ARM::VLD4d8, ARM::VLD4d16, + ARM::VLD4d32, ARM::VLD4d64 }; + unsigned QOpcodes0[] = { ARM::VLD4q8a, ARM::VLD4q16a, ARM::VLD4q32a }; + unsigned QOpcodes1[] = { ARM::VLD4q8b, ARM::VLD4q16b, ARM::VLD4q32b }; + return SelectVLD(Op, 4, DOpcodes, QOpcodes0, QOpcodes1); + } + + case Intrinsic::arm_neon_vld2lane: { + unsigned DOpcodes[] = { ARM::VLD2LNd8, ARM::VLD2LNd16, ARM::VLD2LNd32 }; + unsigned QOpcodes0[] = { ARM::VLD2LNq16a, ARM::VLD2LNq32a }; + unsigned QOpcodes1[] = { ARM::VLD2LNq16b, ARM::VLD2LNq32b }; + return SelectVLDSTLane(Op, true, 2, DOpcodes, QOpcodes0, QOpcodes1); + } + + case Intrinsic::arm_neon_vld3lane: { + unsigned DOpcodes[] = { ARM::VLD3LNd8, ARM::VLD3LNd16, ARM::VLD3LNd32 }; + unsigned QOpcodes0[] = { ARM::VLD3LNq16a, ARM::VLD3LNq32a }; + unsigned QOpcodes1[] = { ARM::VLD3LNq16b, ARM::VLD3LNq32b }; + return SelectVLDSTLane(Op, true, 3, DOpcodes, QOpcodes0, QOpcodes1); + } + + case Intrinsic::arm_neon_vld4lane: { + unsigned DOpcodes[] = { ARM::VLD4LNd8, ARM::VLD4LNd16, ARM::VLD4LNd32 }; + unsigned QOpcodes0[] = { ARM::VLD4LNq16a, ARM::VLD4LNq32a }; + unsigned QOpcodes1[] = { ARM::VLD4LNq16b, ARM::VLD4LNq32b }; + return SelectVLDSTLane(Op, true, 4, DOpcodes, QOpcodes0, QOpcodes1); + } + + case Intrinsic::arm_neon_vst2: { + unsigned DOpcodes[] = { ARM::VST2d8, ARM::VST2d16, + ARM::VST2d32, ARM::VST2d64 }; + unsigned QOpcodes[] = { ARM::VST2q8, ARM::VST2q16, ARM::VST2q32 }; + return SelectVST(Op, 2, DOpcodes, QOpcodes, 0); + } + + case Intrinsic::arm_neon_vst3: { + unsigned DOpcodes[] = { ARM::VST3d8, ARM::VST3d16, + ARM::VST3d32, ARM::VST3d64 }; + unsigned QOpcodes0[] = { ARM::VST3q8a, ARM::VST3q16a, ARM::VST3q32a }; + unsigned QOpcodes1[] = { ARM::VST3q8b, ARM::VST3q16b, ARM::VST3q32b }; + return SelectVST(Op, 3, DOpcodes, QOpcodes0, QOpcodes1); + } + + case Intrinsic::arm_neon_vst4: { + unsigned DOpcodes[] = { ARM::VST4d8, ARM::VST4d16, + ARM::VST4d32, ARM::VST4d64 }; + unsigned QOpcodes0[] = { ARM::VST4q8a, ARM::VST4q16a, ARM::VST4q32a }; + unsigned QOpcodes1[] = { ARM::VST4q8b, ARM::VST4q16b, ARM::VST4q32b }; + return SelectVST(Op, 4, DOpcodes, QOpcodes0, QOpcodes1); + } + + case Intrinsic::arm_neon_vst2lane: { + unsigned DOpcodes[] = { ARM::VST2LNd8, ARM::VST2LNd16, ARM::VST2LNd32 }; + unsigned QOpcodes0[] = { ARM::VST2LNq16a, ARM::VST2LNq32a }; + unsigned QOpcodes1[] = { ARM::VST2LNq16b, ARM::VST2LNq32b }; + return SelectVLDSTLane(Op, false, 2, DOpcodes, QOpcodes0, QOpcodes1); + } + + case Intrinsic::arm_neon_vst3lane: { + unsigned DOpcodes[] = { ARM::VST3LNd8, ARM::VST3LNd16, ARM::VST3LNd32 }; + unsigned QOpcodes0[] = { ARM::VST3LNq16a, ARM::VST3LNq32a }; + unsigned QOpcodes1[] = { ARM::VST3LNq16b, ARM::VST3LNq32b }; + return SelectVLDSTLane(Op, false, 3, DOpcodes, QOpcodes0, QOpcodes1); + } + + case Intrinsic::arm_neon_vst4lane: { + unsigned DOpcodes[] = { ARM::VST4LNd8, ARM::VST4LNd16, ARM::VST4LNd32 }; + unsigned QOpcodes0[] = { ARM::VST4LNq16a, ARM::VST4LNq32a }; + unsigned QOpcodes1[] = { ARM::VST4LNq16b, ARM::VST4LNq32b }; + return SelectVLDSTLane(Op, false, 4, DOpcodes, QOpcodes0, QOpcodes1); + } + } + } + } + + return SelectCode(Op); +} + +bool ARMDAGToDAGISel:: +SelectInlineAsmMemoryOperand(const SDValue &Op, char ConstraintCode, + std::vector &OutOps) { + assert(ConstraintCode == 'm' && "unexpected asm memory constraint"); + // Require the address to be in a register. That is safe for all ARM + // variants and it is hard to do anything much smarter without knowing + // how the operand is used. + OutOps.push_back(Op); + return false; +} + +/// createARMISelDag - This pass converts a legalized DAG into a +/// ARM-specific DAG, ready for instruction scheduling. +/// +FunctionPass *llvm::createARMISelDag(ARMBaseTargetMachine &TM, + CodeGenOpt::Level OptLevel) { + return new ARMDAGToDAGISel(TM, OptLevel); +} diff --git a/libclamav/c++/llvm/lib/Target/ARM/ARMISelLowering.cpp b/libclamav/c++/llvm/lib/Target/ARM/ARMISelLowering.cpp new file mode 100644 index 000000000..c839fc656 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/ARM/ARMISelLowering.cpp @@ -0,0 +1,4200 @@ +//===-- ARMISelLowering.cpp - ARM DAG Lowering Implementation -------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the interfaces that ARM uses to lower LLVM code into a +// selection DAG. +// +//===----------------------------------------------------------------------===// + +#include "ARM.h" +#include "ARMAddressingModes.h" +#include "ARMConstantPoolValue.h" +#include "ARMISelLowering.h" +#include "ARMMachineFunctionInfo.h" +#include "ARMPerfectShuffle.h" +#include "ARMRegisterInfo.h" +#include "ARMSubtarget.h" +#include "ARMTargetMachine.h" +#include "ARMTargetObjectFile.h" +#include "llvm/CallingConv.h" +#include "llvm/Constants.h" +#include "llvm/Function.h" +#include "llvm/GlobalValue.h" +#include "llvm/Instruction.h" +#include "llvm/Intrinsics.h" +#include "llvm/Type.h" +#include "llvm/CodeGen/CallingConvLower.h" +#include "llvm/CodeGen/MachineBasicBlock.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/PseudoSourceValue.h" +#include "llvm/CodeGen/SelectionDAG.h" +#include "llvm/Target/TargetOptions.h" +#include "llvm/ADT/VectorExtras.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/MathExtras.h" +#include +using namespace llvm; + +static bool CC_ARM_APCS_Custom_f64(unsigned &ValNo, EVT &ValVT, EVT &LocVT, + CCValAssign::LocInfo &LocInfo, + ISD::ArgFlagsTy &ArgFlags, + CCState &State); +static bool CC_ARM_AAPCS_Custom_f64(unsigned &ValNo, EVT &ValVT, EVT &LocVT, + CCValAssign::LocInfo &LocInfo, + ISD::ArgFlagsTy &ArgFlags, + CCState &State); +static bool RetCC_ARM_APCS_Custom_f64(unsigned &ValNo, EVT &ValVT, EVT &LocVT, + CCValAssign::LocInfo &LocInfo, + ISD::ArgFlagsTy &ArgFlags, + CCState &State); +static bool RetCC_ARM_AAPCS_Custom_f64(unsigned &ValNo, EVT &ValVT, EVT &LocVT, + CCValAssign::LocInfo &LocInfo, + ISD::ArgFlagsTy &ArgFlags, + CCState &State); + +void ARMTargetLowering::addTypeForNEON(EVT VT, EVT PromotedLdStVT, + EVT PromotedBitwiseVT) { + if (VT != PromotedLdStVT) { + setOperationAction(ISD::LOAD, VT.getSimpleVT(), Promote); + AddPromotedToType (ISD::LOAD, VT.getSimpleVT(), + PromotedLdStVT.getSimpleVT()); + + setOperationAction(ISD::STORE, VT.getSimpleVT(), Promote); + AddPromotedToType (ISD::STORE, VT.getSimpleVT(), + PromotedLdStVT.getSimpleVT()); + } + + EVT ElemTy = VT.getVectorElementType(); + if (ElemTy != MVT::i64 && ElemTy != MVT::f64) + setOperationAction(ISD::VSETCC, VT.getSimpleVT(), Custom); + if (ElemTy == MVT::i8 || ElemTy == MVT::i16) + setOperationAction(ISD::EXTRACT_VECTOR_ELT, VT.getSimpleVT(), Custom); + if (ElemTy != MVT::i32) { + setOperationAction(ISD::SINT_TO_FP, VT.getSimpleVT(), Expand); + setOperationAction(ISD::UINT_TO_FP, VT.getSimpleVT(), Expand); + setOperationAction(ISD::FP_TO_SINT, VT.getSimpleVT(), Expand); + setOperationAction(ISD::FP_TO_UINT, VT.getSimpleVT(), Expand); + } + setOperationAction(ISD::BUILD_VECTOR, VT.getSimpleVT(), Custom); + setOperationAction(ISD::VECTOR_SHUFFLE, VT.getSimpleVT(), Custom); + setOperationAction(ISD::CONCAT_VECTORS, VT.getSimpleVT(), Custom); + setOperationAction(ISD::EXTRACT_SUBVECTOR, VT.getSimpleVT(), Expand); + if (VT.isInteger()) { + setOperationAction(ISD::SHL, VT.getSimpleVT(), Custom); + setOperationAction(ISD::SRA, VT.getSimpleVT(), Custom); + setOperationAction(ISD::SRL, VT.getSimpleVT(), Custom); + } + + // Promote all bit-wise operations. + if (VT.isInteger() && VT != PromotedBitwiseVT) { + setOperationAction(ISD::AND, VT.getSimpleVT(), Promote); + AddPromotedToType (ISD::AND, VT.getSimpleVT(), + PromotedBitwiseVT.getSimpleVT()); + setOperationAction(ISD::OR, VT.getSimpleVT(), Promote); + AddPromotedToType (ISD::OR, VT.getSimpleVT(), + PromotedBitwiseVT.getSimpleVT()); + setOperationAction(ISD::XOR, VT.getSimpleVT(), Promote); + AddPromotedToType (ISD::XOR, VT.getSimpleVT(), + PromotedBitwiseVT.getSimpleVT()); + } + + // Neon does not support vector divide/remainder operations. + setOperationAction(ISD::SDIV, VT.getSimpleVT(), Expand); + setOperationAction(ISD::UDIV, VT.getSimpleVT(), Expand); + setOperationAction(ISD::FDIV, VT.getSimpleVT(), Expand); + setOperationAction(ISD::SREM, VT.getSimpleVT(), Expand); + setOperationAction(ISD::UREM, VT.getSimpleVT(), Expand); + setOperationAction(ISD::FREM, VT.getSimpleVT(), Expand); +} + +void ARMTargetLowering::addDRTypeForNEON(EVT VT) { + addRegisterClass(VT, ARM::DPRRegisterClass); + addTypeForNEON(VT, MVT::f64, MVT::v2i32); +} + +void ARMTargetLowering::addQRTypeForNEON(EVT VT) { + addRegisterClass(VT, ARM::QPRRegisterClass); + addTypeForNEON(VT, MVT::v2f64, MVT::v4i32); +} + +static TargetLoweringObjectFile *createTLOF(TargetMachine &TM) { + if (TM.getSubtarget().isTargetDarwin()) + return new TargetLoweringObjectFileMachO(); + return new ARMElfTargetObjectFile(); +} + +ARMTargetLowering::ARMTargetLowering(TargetMachine &TM) + : TargetLowering(TM, createTLOF(TM)) { + Subtarget = &TM.getSubtarget(); + + if (Subtarget->isTargetDarwin()) { + // Uses VFP for Thumb libfuncs if available. + if (Subtarget->isThumb() && Subtarget->hasVFP2()) { + // Single-precision floating-point arithmetic. + setLibcallName(RTLIB::ADD_F32, "__addsf3vfp"); + setLibcallName(RTLIB::SUB_F32, "__subsf3vfp"); + setLibcallName(RTLIB::MUL_F32, "__mulsf3vfp"); + setLibcallName(RTLIB::DIV_F32, "__divsf3vfp"); + + // Double-precision floating-point arithmetic. + setLibcallName(RTLIB::ADD_F64, "__adddf3vfp"); + setLibcallName(RTLIB::SUB_F64, "__subdf3vfp"); + setLibcallName(RTLIB::MUL_F64, "__muldf3vfp"); + setLibcallName(RTLIB::DIV_F64, "__divdf3vfp"); + + // Single-precision comparisons. + setLibcallName(RTLIB::OEQ_F32, "__eqsf2vfp"); + setLibcallName(RTLIB::UNE_F32, "__nesf2vfp"); + setLibcallName(RTLIB::OLT_F32, "__ltsf2vfp"); + setLibcallName(RTLIB::OLE_F32, "__lesf2vfp"); + setLibcallName(RTLIB::OGE_F32, "__gesf2vfp"); + setLibcallName(RTLIB::OGT_F32, "__gtsf2vfp"); + setLibcallName(RTLIB::UO_F32, "__unordsf2vfp"); + setLibcallName(RTLIB::O_F32, "__unordsf2vfp"); + + setCmpLibcallCC(RTLIB::OEQ_F32, ISD::SETNE); + setCmpLibcallCC(RTLIB::UNE_F32, ISD::SETNE); + setCmpLibcallCC(RTLIB::OLT_F32, ISD::SETNE); + setCmpLibcallCC(RTLIB::OLE_F32, ISD::SETNE); + setCmpLibcallCC(RTLIB::OGE_F32, ISD::SETNE); + setCmpLibcallCC(RTLIB::OGT_F32, ISD::SETNE); + setCmpLibcallCC(RTLIB::UO_F32, ISD::SETNE); + setCmpLibcallCC(RTLIB::O_F32, ISD::SETEQ); + + // Double-precision comparisons. + setLibcallName(RTLIB::OEQ_F64, "__eqdf2vfp"); + setLibcallName(RTLIB::UNE_F64, "__nedf2vfp"); + setLibcallName(RTLIB::OLT_F64, "__ltdf2vfp"); + setLibcallName(RTLIB::OLE_F64, "__ledf2vfp"); + setLibcallName(RTLIB::OGE_F64, "__gedf2vfp"); + setLibcallName(RTLIB::OGT_F64, "__gtdf2vfp"); + setLibcallName(RTLIB::UO_F64, "__unorddf2vfp"); + setLibcallName(RTLIB::O_F64, "__unorddf2vfp"); + + setCmpLibcallCC(RTLIB::OEQ_F64, ISD::SETNE); + setCmpLibcallCC(RTLIB::UNE_F64, ISD::SETNE); + setCmpLibcallCC(RTLIB::OLT_F64, ISD::SETNE); + setCmpLibcallCC(RTLIB::OLE_F64, ISD::SETNE); + setCmpLibcallCC(RTLIB::OGE_F64, ISD::SETNE); + setCmpLibcallCC(RTLIB::OGT_F64, ISD::SETNE); + setCmpLibcallCC(RTLIB::UO_F64, ISD::SETNE); + setCmpLibcallCC(RTLIB::O_F64, ISD::SETEQ); + + // Floating-point to integer conversions. + // i64 conversions are done via library routines even when generating VFP + // instructions, so use the same ones. + setLibcallName(RTLIB::FPTOSINT_F64_I32, "__fixdfsivfp"); + setLibcallName(RTLIB::FPTOUINT_F64_I32, "__fixunsdfsivfp"); + setLibcallName(RTLIB::FPTOSINT_F32_I32, "__fixsfsivfp"); + setLibcallName(RTLIB::FPTOUINT_F32_I32, "__fixunssfsivfp"); + + // Conversions between floating types. + setLibcallName(RTLIB::FPROUND_F64_F32, "__truncdfsf2vfp"); + setLibcallName(RTLIB::FPEXT_F32_F64, "__extendsfdf2vfp"); + + // Integer to floating-point conversions. + // i64 conversions are done via library routines even when generating VFP + // instructions, so use the same ones. + // FIXME: There appears to be some naming inconsistency in ARM libgcc: + // e.g., __floatunsidf vs. __floatunssidfvfp. + setLibcallName(RTLIB::SINTTOFP_I32_F64, "__floatsidfvfp"); + setLibcallName(RTLIB::UINTTOFP_I32_F64, "__floatunssidfvfp"); + setLibcallName(RTLIB::SINTTOFP_I32_F32, "__floatsisfvfp"); + setLibcallName(RTLIB::UINTTOFP_I32_F32, "__floatunssisfvfp"); + } + } + + // These libcalls are not available in 32-bit. + setLibcallName(RTLIB::SHL_I128, 0); + setLibcallName(RTLIB::SRL_I128, 0); + setLibcallName(RTLIB::SRA_I128, 0); + + // Libcalls should use the AAPCS base standard ABI, even if hard float + // is in effect, as per the ARM RTABI specification, section 4.1.2. + if (Subtarget->isAAPCS_ABI()) { + for (int i = 0; i < RTLIB::UNKNOWN_LIBCALL; ++i) { + setLibcallCallingConv(static_cast(i), + CallingConv::ARM_AAPCS); + } + } + + if (Subtarget->isThumb1Only()) + addRegisterClass(MVT::i32, ARM::tGPRRegisterClass); + else + addRegisterClass(MVT::i32, ARM::GPRRegisterClass); + if (!UseSoftFloat && Subtarget->hasVFP2() && !Subtarget->isThumb1Only()) { + addRegisterClass(MVT::f32, ARM::SPRRegisterClass); + addRegisterClass(MVT::f64, ARM::DPRRegisterClass); + + setTruncStoreAction(MVT::f64, MVT::f32, Expand); + } + + if (Subtarget->hasNEON()) { + addDRTypeForNEON(MVT::v2f32); + addDRTypeForNEON(MVT::v8i8); + addDRTypeForNEON(MVT::v4i16); + addDRTypeForNEON(MVT::v2i32); + addDRTypeForNEON(MVT::v1i64); + + addQRTypeForNEON(MVT::v4f32); + addQRTypeForNEON(MVT::v2f64); + addQRTypeForNEON(MVT::v16i8); + addQRTypeForNEON(MVT::v8i16); + addQRTypeForNEON(MVT::v4i32); + addQRTypeForNEON(MVT::v2i64); + + // v2f64 is legal so that QR subregs can be extracted as f64 elements, but + // neither Neon nor VFP support any arithmetic operations on it. + setOperationAction(ISD::FADD, MVT::v2f64, Expand); + setOperationAction(ISD::FSUB, MVT::v2f64, Expand); + setOperationAction(ISD::FMUL, MVT::v2f64, Expand); + setOperationAction(ISD::FDIV, MVT::v2f64, Expand); + setOperationAction(ISD::FREM, MVT::v2f64, Expand); + setOperationAction(ISD::FCOPYSIGN, MVT::v2f64, Expand); + setOperationAction(ISD::VSETCC, MVT::v2f64, Expand); + setOperationAction(ISD::FNEG, MVT::v2f64, Expand); + setOperationAction(ISD::FABS, MVT::v2f64, Expand); + setOperationAction(ISD::FSQRT, MVT::v2f64, Expand); + setOperationAction(ISD::FSIN, MVT::v2f64, Expand); + setOperationAction(ISD::FCOS, MVT::v2f64, Expand); + setOperationAction(ISD::FPOWI, MVT::v2f64, Expand); + setOperationAction(ISD::FPOW, MVT::v2f64, Expand); + setOperationAction(ISD::FLOG, MVT::v2f64, Expand); + setOperationAction(ISD::FLOG2, MVT::v2f64, Expand); + setOperationAction(ISD::FLOG10, MVT::v2f64, Expand); + setOperationAction(ISD::FEXP, MVT::v2f64, Expand); + setOperationAction(ISD::FEXP2, MVT::v2f64, Expand); + setOperationAction(ISD::FCEIL, MVT::v2f64, Expand); + setOperationAction(ISD::FTRUNC, MVT::v2f64, Expand); + setOperationAction(ISD::FRINT, MVT::v2f64, Expand); + setOperationAction(ISD::FNEARBYINT, MVT::v2f64, Expand); + setOperationAction(ISD::FFLOOR, MVT::v2f64, Expand); + + // Neon does not support some operations on v1i64 and v2i64 types. + setOperationAction(ISD::MUL, MVT::v1i64, Expand); + setOperationAction(ISD::MUL, MVT::v2i64, Expand); + setOperationAction(ISD::VSETCC, MVT::v1i64, Expand); + setOperationAction(ISD::VSETCC, MVT::v2i64, Expand); + + setTargetDAGCombine(ISD::INTRINSIC_WO_CHAIN); + setTargetDAGCombine(ISD::SHL); + setTargetDAGCombine(ISD::SRL); + setTargetDAGCombine(ISD::SRA); + setTargetDAGCombine(ISD::SIGN_EXTEND); + setTargetDAGCombine(ISD::ZERO_EXTEND); + setTargetDAGCombine(ISD::ANY_EXTEND); + } + + computeRegisterProperties(); + + // ARM does not have f32 extending load. + setLoadExtAction(ISD::EXTLOAD, MVT::f32, Expand); + + // ARM does not have i1 sign extending load. + setLoadExtAction(ISD::SEXTLOAD, MVT::i1, Promote); + + // ARM supports all 4 flavors of integer indexed load / store. + if (!Subtarget->isThumb1Only()) { + for (unsigned im = (unsigned)ISD::PRE_INC; + im != (unsigned)ISD::LAST_INDEXED_MODE; ++im) { + setIndexedLoadAction(im, MVT::i1, Legal); + setIndexedLoadAction(im, MVT::i8, Legal); + setIndexedLoadAction(im, MVT::i16, Legal); + setIndexedLoadAction(im, MVT::i32, Legal); + setIndexedStoreAction(im, MVT::i1, Legal); + setIndexedStoreAction(im, MVT::i8, Legal); + setIndexedStoreAction(im, MVT::i16, Legal); + setIndexedStoreAction(im, MVT::i32, Legal); + } + } + + // i64 operation support. + if (Subtarget->isThumb1Only()) { + setOperationAction(ISD::MUL, MVT::i64, Expand); + setOperationAction(ISD::MULHU, MVT::i32, Expand); + setOperationAction(ISD::MULHS, MVT::i32, Expand); + setOperationAction(ISD::UMUL_LOHI, MVT::i32, Expand); + setOperationAction(ISD::SMUL_LOHI, MVT::i32, Expand); + } else { + setOperationAction(ISD::MUL, MVT::i64, Expand); + setOperationAction(ISD::MULHU, MVT::i32, Expand); + if (!Subtarget->hasV6Ops()) + setOperationAction(ISD::MULHS, MVT::i32, Expand); + } + setOperationAction(ISD::SHL_PARTS, MVT::i32, Custom); + setOperationAction(ISD::SRA_PARTS, MVT::i32, Custom); + setOperationAction(ISD::SRL_PARTS, MVT::i32, Custom); + setOperationAction(ISD::SRL, MVT::i64, Custom); + setOperationAction(ISD::SRA, MVT::i64, Custom); + + // ARM does not have ROTL. + setOperationAction(ISD::ROTL, MVT::i32, Expand); + setOperationAction(ISD::CTTZ, MVT::i32, Expand); + setOperationAction(ISD::CTPOP, MVT::i32, Expand); + if (!Subtarget->hasV5TOps() || Subtarget->isThumb1Only()) + setOperationAction(ISD::CTLZ, MVT::i32, Expand); + + // Only ARMv6 has BSWAP. + if (!Subtarget->hasV6Ops()) + setOperationAction(ISD::BSWAP, MVT::i32, Expand); + + // These are expanded into libcalls. + setOperationAction(ISD::SDIV, MVT::i32, Expand); + setOperationAction(ISD::UDIV, MVT::i32, Expand); + setOperationAction(ISD::SREM, MVT::i32, Expand); + setOperationAction(ISD::UREM, MVT::i32, Expand); + setOperationAction(ISD::SDIVREM, MVT::i32, Expand); + setOperationAction(ISD::UDIVREM, MVT::i32, Expand); + + setOperationAction(ISD::GlobalAddress, MVT::i32, Custom); + setOperationAction(ISD::ConstantPool, MVT::i32, Custom); + setOperationAction(ISD::GLOBAL_OFFSET_TABLE, MVT::i32, Custom); + setOperationAction(ISD::GlobalTLSAddress, MVT::i32, Custom); + setOperationAction(ISD::BlockAddress, MVT::i32, Custom); + + // Use the default implementation. + setOperationAction(ISD::VASTART, MVT::Other, Custom); + setOperationAction(ISD::VAARG, MVT::Other, Expand); + setOperationAction(ISD::VACOPY, MVT::Other, Expand); + setOperationAction(ISD::VAEND, MVT::Other, Expand); + setOperationAction(ISD::STACKSAVE, MVT::Other, Expand); + setOperationAction(ISD::STACKRESTORE, MVT::Other, Expand); + setOperationAction(ISD::EHSELECTION, MVT::i32, Expand); + // FIXME: Shouldn't need this, since no register is used, but the legalizer + // doesn't yet know how to not do that for SjLj. + setExceptionSelectorRegister(ARM::R0); + if (Subtarget->isThumb()) + setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32, Custom); + else + setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32, Expand); + setOperationAction(ISD::MEMBARRIER, MVT::Other, Expand); + + if (!Subtarget->hasV6Ops() && !Subtarget->isThumb2()) { + setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i16, Expand); + setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i8, Expand); + } + setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Expand); + + if (!UseSoftFloat && Subtarget->hasVFP2() && !Subtarget->isThumb1Only()) + // Turn f64->i64 into VMOVRRD, i64 -> f64 to VMOVDRR iff target supports vfp2. + setOperationAction(ISD::BIT_CONVERT, MVT::i64, Custom); + + // We want to custom lower some of our intrinsics. + setOperationAction(ISD::INTRINSIC_WO_CHAIN, MVT::Other, Custom); + + setOperationAction(ISD::SETCC, MVT::i32, Expand); + setOperationAction(ISD::SETCC, MVT::f32, Expand); + setOperationAction(ISD::SETCC, MVT::f64, Expand); + setOperationAction(ISD::SELECT, MVT::i32, Expand); + setOperationAction(ISD::SELECT, MVT::f32, Expand); + setOperationAction(ISD::SELECT, MVT::f64, Expand); + setOperationAction(ISD::SELECT_CC, MVT::i32, Custom); + setOperationAction(ISD::SELECT_CC, MVT::f32, Custom); + setOperationAction(ISD::SELECT_CC, MVT::f64, Custom); + + setOperationAction(ISD::BRCOND, MVT::Other, Expand); + setOperationAction(ISD::BR_CC, MVT::i32, Custom); + setOperationAction(ISD::BR_CC, MVT::f32, Custom); + setOperationAction(ISD::BR_CC, MVT::f64, Custom); + setOperationAction(ISD::BR_JT, MVT::Other, Custom); + + // We don't support sin/cos/fmod/copysign/pow + setOperationAction(ISD::FSIN, MVT::f64, Expand); + setOperationAction(ISD::FSIN, MVT::f32, Expand); + setOperationAction(ISD::FCOS, MVT::f32, Expand); + setOperationAction(ISD::FCOS, MVT::f64, Expand); + setOperationAction(ISD::FREM, MVT::f64, Expand); + setOperationAction(ISD::FREM, MVT::f32, Expand); + if (!UseSoftFloat && Subtarget->hasVFP2() && !Subtarget->isThumb1Only()) { + setOperationAction(ISD::FCOPYSIGN, MVT::f64, Custom); + setOperationAction(ISD::FCOPYSIGN, MVT::f32, Custom); + } + setOperationAction(ISD::FPOW, MVT::f64, Expand); + setOperationAction(ISD::FPOW, MVT::f32, Expand); + + // int <-> fp are custom expanded into bit_convert + ARMISD ops. + if (!UseSoftFloat && Subtarget->hasVFP2() && !Subtarget->isThumb1Only()) { + setOperationAction(ISD::SINT_TO_FP, MVT::i32, Custom); + setOperationAction(ISD::UINT_TO_FP, MVT::i32, Custom); + setOperationAction(ISD::FP_TO_UINT, MVT::i32, Custom); + setOperationAction(ISD::FP_TO_SINT, MVT::i32, Custom); + } + + // We have target-specific dag combine patterns for the following nodes: + // ARMISD::VMOVRRD - No need to call setTargetDAGCombine + setTargetDAGCombine(ISD::ADD); + setTargetDAGCombine(ISD::SUB); + + setStackPointerRegisterToSaveRestore(ARM::SP); + setSchedulingPreference(SchedulingForRegPressure); + + // FIXME: If-converter should use instruction latency to determine + // profitability rather than relying on fixed limits. + if (Subtarget->getCPUString() == "generic") { + // Generic (and overly aggressive) if-conversion limits. + setIfCvtBlockSizeLimit(10); + setIfCvtDupBlockSizeLimit(2); + } else if (Subtarget->hasV6Ops()) { + setIfCvtBlockSizeLimit(2); + setIfCvtDupBlockSizeLimit(1); + } else { + setIfCvtBlockSizeLimit(3); + setIfCvtDupBlockSizeLimit(2); + } + + maxStoresPerMemcpy = 1; //// temporary - rewrite interface to use type + // Do not enable CodePlacementOpt for now: it currently runs after the + // ARMConstantIslandPass and messes up branch relaxation and placement + // of constant islands. + // benefitFromCodePlacementOpt = true; +} + +const char *ARMTargetLowering::getTargetNodeName(unsigned Opcode) const { + switch (Opcode) { + default: return 0; + case ARMISD::Wrapper: return "ARMISD::Wrapper"; + case ARMISD::WrapperJT: return "ARMISD::WrapperJT"; + case ARMISD::CALL: return "ARMISD::CALL"; + case ARMISD::CALL_PRED: return "ARMISD::CALL_PRED"; + case ARMISD::CALL_NOLINK: return "ARMISD::CALL_NOLINK"; + case ARMISD::tCALL: return "ARMISD::tCALL"; + case ARMISD::BRCOND: return "ARMISD::BRCOND"; + case ARMISD::BR_JT: return "ARMISD::BR_JT"; + case ARMISD::BR2_JT: return "ARMISD::BR2_JT"; + case ARMISD::RET_FLAG: return "ARMISD::RET_FLAG"; + case ARMISD::PIC_ADD: return "ARMISD::PIC_ADD"; + case ARMISD::CMP: return "ARMISD::CMP"; + case ARMISD::CMPZ: return "ARMISD::CMPZ"; + case ARMISD::CMPFP: return "ARMISD::CMPFP"; + case ARMISD::CMPFPw0: return "ARMISD::CMPFPw0"; + case ARMISD::FMSTAT: return "ARMISD::FMSTAT"; + case ARMISD::CMOV: return "ARMISD::CMOV"; + case ARMISD::CNEG: return "ARMISD::CNEG"; + + case ARMISD::FTOSI: return "ARMISD::FTOSI"; + case ARMISD::FTOUI: return "ARMISD::FTOUI"; + case ARMISD::SITOF: return "ARMISD::SITOF"; + case ARMISD::UITOF: return "ARMISD::UITOF"; + + case ARMISD::SRL_FLAG: return "ARMISD::SRL_FLAG"; + case ARMISD::SRA_FLAG: return "ARMISD::SRA_FLAG"; + case ARMISD::RRX: return "ARMISD::RRX"; + + case ARMISD::VMOVRRD: return "ARMISD::VMOVRRD"; + case ARMISD::VMOVDRR: return "ARMISD::VMOVDRR"; + + case ARMISD::EH_SJLJ_SETJMP: return "ARMISD::EH_SJLJ_SETJMP"; + case ARMISD::EH_SJLJ_LONGJMP:return "ARMISD::EH_SJLJ_LONGJMP"; + + case ARMISD::THREAD_POINTER:return "ARMISD::THREAD_POINTER"; + + case ARMISD::DYN_ALLOC: return "ARMISD::DYN_ALLOC"; + + case ARMISD::VCEQ: return "ARMISD::VCEQ"; + case ARMISD::VCGE: return "ARMISD::VCGE"; + case ARMISD::VCGEU: return "ARMISD::VCGEU"; + case ARMISD::VCGT: return "ARMISD::VCGT"; + case ARMISD::VCGTU: return "ARMISD::VCGTU"; + case ARMISD::VTST: return "ARMISD::VTST"; + + case ARMISD::VSHL: return "ARMISD::VSHL"; + case ARMISD::VSHRs: return "ARMISD::VSHRs"; + case ARMISD::VSHRu: return "ARMISD::VSHRu"; + case ARMISD::VSHLLs: return "ARMISD::VSHLLs"; + case ARMISD::VSHLLu: return "ARMISD::VSHLLu"; + case ARMISD::VSHLLi: return "ARMISD::VSHLLi"; + case ARMISD::VSHRN: return "ARMISD::VSHRN"; + case ARMISD::VRSHRs: return "ARMISD::VRSHRs"; + case ARMISD::VRSHRu: return "ARMISD::VRSHRu"; + case ARMISD::VRSHRN: return "ARMISD::VRSHRN"; + case ARMISD::VQSHLs: return "ARMISD::VQSHLs"; + case ARMISD::VQSHLu: return "ARMISD::VQSHLu"; + case ARMISD::VQSHLsu: return "ARMISD::VQSHLsu"; + case ARMISD::VQSHRNs: return "ARMISD::VQSHRNs"; + case ARMISD::VQSHRNu: return "ARMISD::VQSHRNu"; + case ARMISD::VQSHRNsu: return "ARMISD::VQSHRNsu"; + case ARMISD::VQRSHRNs: return "ARMISD::VQRSHRNs"; + case ARMISD::VQRSHRNu: return "ARMISD::VQRSHRNu"; + case ARMISD::VQRSHRNsu: return "ARMISD::VQRSHRNsu"; + case ARMISD::VGETLANEu: return "ARMISD::VGETLANEu"; + case ARMISD::VGETLANEs: return "ARMISD::VGETLANEs"; + case ARMISD::VDUP: return "ARMISD::VDUP"; + case ARMISD::VDUPLANE: return "ARMISD::VDUPLANE"; + case ARMISD::VEXT: return "ARMISD::VEXT"; + case ARMISD::VREV64: return "ARMISD::VREV64"; + case ARMISD::VREV32: return "ARMISD::VREV32"; + case ARMISD::VREV16: return "ARMISD::VREV16"; + case ARMISD::VZIP: return "ARMISD::VZIP"; + case ARMISD::VUZP: return "ARMISD::VUZP"; + case ARMISD::VTRN: return "ARMISD::VTRN"; + } +} + +/// getFunctionAlignment - Return the Log2 alignment of this function. +unsigned ARMTargetLowering::getFunctionAlignment(const Function *F) const { + return getTargetMachine().getSubtarget().isThumb() ? 0 : 1; +} + +//===----------------------------------------------------------------------===// +// Lowering Code +//===----------------------------------------------------------------------===// + +/// IntCCToARMCC - Convert a DAG integer condition code to an ARM CC +static ARMCC::CondCodes IntCCToARMCC(ISD::CondCode CC) { + switch (CC) { + default: llvm_unreachable("Unknown condition code!"); + case ISD::SETNE: return ARMCC::NE; + case ISD::SETEQ: return ARMCC::EQ; + case ISD::SETGT: return ARMCC::GT; + case ISD::SETGE: return ARMCC::GE; + case ISD::SETLT: return ARMCC::LT; + case ISD::SETLE: return ARMCC::LE; + case ISD::SETUGT: return ARMCC::HI; + case ISD::SETUGE: return ARMCC::HS; + case ISD::SETULT: return ARMCC::LO; + case ISD::SETULE: return ARMCC::LS; + } +} + +/// FPCCToARMCC - Convert a DAG fp condition code to an ARM CC. +static void FPCCToARMCC(ISD::CondCode CC, ARMCC::CondCodes &CondCode, + ARMCC::CondCodes &CondCode2) { + CondCode2 = ARMCC::AL; + switch (CC) { + default: llvm_unreachable("Unknown FP condition!"); + case ISD::SETEQ: + case ISD::SETOEQ: CondCode = ARMCC::EQ; break; + case ISD::SETGT: + case ISD::SETOGT: CondCode = ARMCC::GT; break; + case ISD::SETGE: + case ISD::SETOGE: CondCode = ARMCC::GE; break; + case ISD::SETOLT: CondCode = ARMCC::MI; break; + case ISD::SETOLE: CondCode = ARMCC::LS; break; + case ISD::SETONE: CondCode = ARMCC::MI; CondCode2 = ARMCC::GT; break; + case ISD::SETO: CondCode = ARMCC::VC; break; + case ISD::SETUO: CondCode = ARMCC::VS; break; + case ISD::SETUEQ: CondCode = ARMCC::EQ; CondCode2 = ARMCC::VS; break; + case ISD::SETUGT: CondCode = ARMCC::HI; break; + case ISD::SETUGE: CondCode = ARMCC::PL; break; + case ISD::SETLT: + case ISD::SETULT: CondCode = ARMCC::LT; break; + case ISD::SETLE: + case ISD::SETULE: CondCode = ARMCC::LE; break; + case ISD::SETNE: + case ISD::SETUNE: CondCode = ARMCC::NE; break; + } +} + +//===----------------------------------------------------------------------===// +// Calling Convention Implementation +//===----------------------------------------------------------------------===// + +#include "ARMGenCallingConv.inc" + +// APCS f64 is in register pairs, possibly split to stack +static bool f64AssignAPCS(unsigned &ValNo, EVT &ValVT, EVT &LocVT, + CCValAssign::LocInfo &LocInfo, + CCState &State, bool CanFail) { + static const unsigned RegList[] = { ARM::R0, ARM::R1, ARM::R2, ARM::R3 }; + + // Try to get the first register. + if (unsigned Reg = State.AllocateReg(RegList, 4)) + State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo)); + else { + // For the 2nd half of a v2f64, do not fail. + if (CanFail) + return false; + + // Put the whole thing on the stack. + State.addLoc(CCValAssign::getCustomMem(ValNo, ValVT, + State.AllocateStack(8, 4), + LocVT, LocInfo)); + return true; + } + + // Try to get the second register. + if (unsigned Reg = State.AllocateReg(RegList, 4)) + State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo)); + else + State.addLoc(CCValAssign::getCustomMem(ValNo, ValVT, + State.AllocateStack(4, 4), + LocVT, LocInfo)); + return true; +} + +static bool CC_ARM_APCS_Custom_f64(unsigned &ValNo, EVT &ValVT, EVT &LocVT, + CCValAssign::LocInfo &LocInfo, + ISD::ArgFlagsTy &ArgFlags, + CCState &State) { + if (!f64AssignAPCS(ValNo, ValVT, LocVT, LocInfo, State, true)) + return false; + if (LocVT == MVT::v2f64 && + !f64AssignAPCS(ValNo, ValVT, LocVT, LocInfo, State, false)) + return false; + return true; // we handled it +} + +// AAPCS f64 is in aligned register pairs +static bool f64AssignAAPCS(unsigned &ValNo, EVT &ValVT, EVT &LocVT, + CCValAssign::LocInfo &LocInfo, + CCState &State, bool CanFail) { + static const unsigned HiRegList[] = { ARM::R0, ARM::R2 }; + static const unsigned LoRegList[] = { ARM::R1, ARM::R3 }; + + unsigned Reg = State.AllocateReg(HiRegList, LoRegList, 2); + if (Reg == 0) { + // For the 2nd half of a v2f64, do not just fail. + if (CanFail) + return false; + + // Put the whole thing on the stack. + State.addLoc(CCValAssign::getCustomMem(ValNo, ValVT, + State.AllocateStack(8, 8), + LocVT, LocInfo)); + return true; + } + + unsigned i; + for (i = 0; i < 2; ++i) + if (HiRegList[i] == Reg) + break; + + State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo)); + State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, LoRegList[i], + LocVT, LocInfo)); + return true; +} + +static bool CC_ARM_AAPCS_Custom_f64(unsigned &ValNo, EVT &ValVT, EVT &LocVT, + CCValAssign::LocInfo &LocInfo, + ISD::ArgFlagsTy &ArgFlags, + CCState &State) { + if (!f64AssignAAPCS(ValNo, ValVT, LocVT, LocInfo, State, true)) + return false; + if (LocVT == MVT::v2f64 && + !f64AssignAAPCS(ValNo, ValVT, LocVT, LocInfo, State, false)) + return false; + return true; // we handled it +} + +static bool f64RetAssign(unsigned &ValNo, EVT &ValVT, EVT &LocVT, + CCValAssign::LocInfo &LocInfo, CCState &State) { + static const unsigned HiRegList[] = { ARM::R0, ARM::R2 }; + static const unsigned LoRegList[] = { ARM::R1, ARM::R3 }; + + unsigned Reg = State.AllocateReg(HiRegList, LoRegList, 2); + if (Reg == 0) + return false; // we didn't handle it + + unsigned i; + for (i = 0; i < 2; ++i) + if (HiRegList[i] == Reg) + break; + + State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo)); + State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, LoRegList[i], + LocVT, LocInfo)); + return true; +} + +static bool RetCC_ARM_APCS_Custom_f64(unsigned &ValNo, EVT &ValVT, EVT &LocVT, + CCValAssign::LocInfo &LocInfo, + ISD::ArgFlagsTy &ArgFlags, + CCState &State) { + if (!f64RetAssign(ValNo, ValVT, LocVT, LocInfo, State)) + return false; + if (LocVT == MVT::v2f64 && !f64RetAssign(ValNo, ValVT, LocVT, LocInfo, State)) + return false; + return true; // we handled it +} + +static bool RetCC_ARM_AAPCS_Custom_f64(unsigned &ValNo, EVT &ValVT, EVT &LocVT, + CCValAssign::LocInfo &LocInfo, + ISD::ArgFlagsTy &ArgFlags, + CCState &State) { + return RetCC_ARM_APCS_Custom_f64(ValNo, ValVT, LocVT, LocInfo, ArgFlags, + State); +} + +/// CCAssignFnForNode - Selects the correct CCAssignFn for a the +/// given CallingConvention value. +CCAssignFn *ARMTargetLowering::CCAssignFnForNode(CallingConv::ID CC, + bool Return, + bool isVarArg) const { + switch (CC) { + default: + llvm_unreachable("Unsupported calling convention"); + case CallingConv::C: + case CallingConv::Fast: + // Use target triple & subtarget features to do actual dispatch. + if (Subtarget->isAAPCS_ABI()) { + if (Subtarget->hasVFP2() && + FloatABIType == FloatABI::Hard && !isVarArg) + return (Return ? RetCC_ARM_AAPCS_VFP: CC_ARM_AAPCS_VFP); + else + return (Return ? RetCC_ARM_AAPCS: CC_ARM_AAPCS); + } else + return (Return ? RetCC_ARM_APCS: CC_ARM_APCS); + case CallingConv::ARM_AAPCS_VFP: + return (Return ? RetCC_ARM_AAPCS_VFP: CC_ARM_AAPCS_VFP); + case CallingConv::ARM_AAPCS: + return (Return ? RetCC_ARM_AAPCS: CC_ARM_AAPCS); + case CallingConv::ARM_APCS: + return (Return ? RetCC_ARM_APCS: CC_ARM_APCS); + } +} + +/// LowerCallResult - Lower the result values of a call into the +/// appropriate copies out of appropriate physical registers. +SDValue +ARMTargetLowering::LowerCallResult(SDValue Chain, SDValue InFlag, + CallingConv::ID CallConv, bool isVarArg, + const SmallVectorImpl &Ins, + DebugLoc dl, SelectionDAG &DAG, + SmallVectorImpl &InVals) { + + // Assign locations to each value returned by this call. + SmallVector RVLocs; + CCState CCInfo(CallConv, isVarArg, getTargetMachine(), + RVLocs, *DAG.getContext()); + CCInfo.AnalyzeCallResult(Ins, + CCAssignFnForNode(CallConv, /* Return*/ true, + isVarArg)); + + // Copy all of the result registers out of their specified physreg. + for (unsigned i = 0; i != RVLocs.size(); ++i) { + CCValAssign VA = RVLocs[i]; + + SDValue Val; + if (VA.needsCustom()) { + // Handle f64 or half of a v2f64. + SDValue Lo = DAG.getCopyFromReg(Chain, dl, VA.getLocReg(), MVT::i32, + InFlag); + Chain = Lo.getValue(1); + InFlag = Lo.getValue(2); + VA = RVLocs[++i]; // skip ahead to next loc + SDValue Hi = DAG.getCopyFromReg(Chain, dl, VA.getLocReg(), MVT::i32, + InFlag); + Chain = Hi.getValue(1); + InFlag = Hi.getValue(2); + Val = DAG.getNode(ARMISD::VMOVDRR, dl, MVT::f64, Lo, Hi); + + if (VA.getLocVT() == MVT::v2f64) { + SDValue Vec = DAG.getNode(ISD::UNDEF, dl, MVT::v2f64); + Vec = DAG.getNode(ISD::INSERT_VECTOR_ELT, dl, MVT::v2f64, Vec, Val, + DAG.getConstant(0, MVT::i32)); + + VA = RVLocs[++i]; // skip ahead to next loc + Lo = DAG.getCopyFromReg(Chain, dl, VA.getLocReg(), MVT::i32, InFlag); + Chain = Lo.getValue(1); + InFlag = Lo.getValue(2); + VA = RVLocs[++i]; // skip ahead to next loc + Hi = DAG.getCopyFromReg(Chain, dl, VA.getLocReg(), MVT::i32, InFlag); + Chain = Hi.getValue(1); + InFlag = Hi.getValue(2); + Val = DAG.getNode(ARMISD::VMOVDRR, dl, MVT::f64, Lo, Hi); + Val = DAG.getNode(ISD::INSERT_VECTOR_ELT, dl, MVT::v2f64, Vec, Val, + DAG.getConstant(1, MVT::i32)); + } + } else { + Val = DAG.getCopyFromReg(Chain, dl, VA.getLocReg(), VA.getLocVT(), + InFlag); + Chain = Val.getValue(1); + InFlag = Val.getValue(2); + } + + switch (VA.getLocInfo()) { + default: llvm_unreachable("Unknown loc info!"); + case CCValAssign::Full: break; + case CCValAssign::BCvt: + Val = DAG.getNode(ISD::BIT_CONVERT, dl, VA.getValVT(), Val); + break; + } + + InVals.push_back(Val); + } + + return Chain; +} + +/// CreateCopyOfByValArgument - Make a copy of an aggregate at address specified +/// by "Src" to address "Dst" of size "Size". Alignment information is +/// specified by the specific parameter attribute. The copy will be passed as +/// a byval function parameter. +/// Sometimes what we are copying is the end of a larger object, the part that +/// does not fit in registers. +static SDValue +CreateCopyOfByValArgument(SDValue Src, SDValue Dst, SDValue Chain, + ISD::ArgFlagsTy Flags, SelectionDAG &DAG, + DebugLoc dl) { + SDValue SizeNode = DAG.getConstant(Flags.getByValSize(), MVT::i32); + return DAG.getMemcpy(Chain, dl, Dst, Src, SizeNode, Flags.getByValAlign(), + /*AlwaysInline=*/false, NULL, 0, NULL, 0); +} + +/// LowerMemOpCallTo - Store the argument to the stack. +SDValue +ARMTargetLowering::LowerMemOpCallTo(SDValue Chain, + SDValue StackPtr, SDValue Arg, + DebugLoc dl, SelectionDAG &DAG, + const CCValAssign &VA, + ISD::ArgFlagsTy Flags) { + unsigned LocMemOffset = VA.getLocMemOffset(); + SDValue PtrOff = DAG.getIntPtrConstant(LocMemOffset); + PtrOff = DAG.getNode(ISD::ADD, dl, getPointerTy(), StackPtr, PtrOff); + if (Flags.isByVal()) { + return CreateCopyOfByValArgument(Arg, PtrOff, Chain, Flags, DAG, dl); + } + return DAG.getStore(Chain, dl, Arg, PtrOff, + PseudoSourceValue::getStack(), LocMemOffset); +} + +void ARMTargetLowering::PassF64ArgInRegs(DebugLoc dl, SelectionDAG &DAG, + SDValue Chain, SDValue &Arg, + RegsToPassVector &RegsToPass, + CCValAssign &VA, CCValAssign &NextVA, + SDValue &StackPtr, + SmallVector &MemOpChains, + ISD::ArgFlagsTy Flags) { + + SDValue fmrrd = DAG.getNode(ARMISD::VMOVRRD, dl, + DAG.getVTList(MVT::i32, MVT::i32), Arg); + RegsToPass.push_back(std::make_pair(VA.getLocReg(), fmrrd)); + + if (NextVA.isRegLoc()) + RegsToPass.push_back(std::make_pair(NextVA.getLocReg(), fmrrd.getValue(1))); + else { + assert(NextVA.isMemLoc()); + if (StackPtr.getNode() == 0) + StackPtr = DAG.getCopyFromReg(Chain, dl, ARM::SP, getPointerTy()); + + MemOpChains.push_back(LowerMemOpCallTo(Chain, StackPtr, fmrrd.getValue(1), + dl, DAG, NextVA, + Flags)); + } +} + +/// LowerCall - Lowering a call into a callseq_start <- +/// ARMISD:CALL <- callseq_end chain. Also add input and output parameter +/// nodes. +SDValue +ARMTargetLowering::LowerCall(SDValue Chain, SDValue Callee, + CallingConv::ID CallConv, bool isVarArg, + bool isTailCall, + const SmallVectorImpl &Outs, + const SmallVectorImpl &Ins, + DebugLoc dl, SelectionDAG &DAG, + SmallVectorImpl &InVals) { + + // Analyze operands of the call, assigning locations to each operand. + SmallVector ArgLocs; + CCState CCInfo(CallConv, isVarArg, getTargetMachine(), ArgLocs, + *DAG.getContext()); + CCInfo.AnalyzeCallOperands(Outs, + CCAssignFnForNode(CallConv, /* Return*/ false, + isVarArg)); + + // Get a count of how many bytes are to be pushed on the stack. + unsigned NumBytes = CCInfo.getNextStackOffset(); + + // Adjust the stack pointer for the new arguments... + // These operations are automatically eliminated by the prolog/epilog pass + Chain = DAG.getCALLSEQ_START(Chain, DAG.getIntPtrConstant(NumBytes, true)); + + SDValue StackPtr = DAG.getRegister(ARM::SP, MVT::i32); + + RegsToPassVector RegsToPass; + SmallVector MemOpChains; + + // Walk the register/memloc assignments, inserting copies/loads. In the case + // of tail call optimization, arguments are handled later. + for (unsigned i = 0, realArgIdx = 0, e = ArgLocs.size(); + i != e; + ++i, ++realArgIdx) { + CCValAssign &VA = ArgLocs[i]; + SDValue Arg = Outs[realArgIdx].Val; + ISD::ArgFlagsTy Flags = Outs[realArgIdx].Flags; + + // Promote the value if needed. + switch (VA.getLocInfo()) { + default: llvm_unreachable("Unknown loc info!"); + case CCValAssign::Full: break; + case CCValAssign::SExt: + Arg = DAG.getNode(ISD::SIGN_EXTEND, dl, VA.getLocVT(), Arg); + break; + case CCValAssign::ZExt: + Arg = DAG.getNode(ISD::ZERO_EXTEND, dl, VA.getLocVT(), Arg); + break; + case CCValAssign::AExt: + Arg = DAG.getNode(ISD::ANY_EXTEND, dl, VA.getLocVT(), Arg); + break; + case CCValAssign::BCvt: + Arg = DAG.getNode(ISD::BIT_CONVERT, dl, VA.getLocVT(), Arg); + break; + } + + // f64 and v2f64 might be passed in i32 pairs and must be split into pieces + if (VA.needsCustom()) { + if (VA.getLocVT() == MVT::v2f64) { + SDValue Op0 = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, MVT::f64, Arg, + DAG.getConstant(0, MVT::i32)); + SDValue Op1 = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, MVT::f64, Arg, + DAG.getConstant(1, MVT::i32)); + + PassF64ArgInRegs(dl, DAG, Chain, Op0, RegsToPass, + VA, ArgLocs[++i], StackPtr, MemOpChains, Flags); + + VA = ArgLocs[++i]; // skip ahead to next loc + if (VA.isRegLoc()) { + PassF64ArgInRegs(dl, DAG, Chain, Op1, RegsToPass, + VA, ArgLocs[++i], StackPtr, MemOpChains, Flags); + } else { + assert(VA.isMemLoc()); + if (StackPtr.getNode() == 0) + StackPtr = DAG.getCopyFromReg(Chain, dl, ARM::SP, getPointerTy()); + + MemOpChains.push_back(LowerMemOpCallTo(Chain, StackPtr, Op1, + dl, DAG, VA, Flags)); + } + } else { + PassF64ArgInRegs(dl, DAG, Chain, Arg, RegsToPass, VA, ArgLocs[++i], + StackPtr, MemOpChains, Flags); + } + } else if (VA.isRegLoc()) { + RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg)); + } else { + assert(VA.isMemLoc()); + if (StackPtr.getNode() == 0) + StackPtr = DAG.getCopyFromReg(Chain, dl, ARM::SP, getPointerTy()); + + MemOpChains.push_back(LowerMemOpCallTo(Chain, StackPtr, Arg, + dl, DAG, VA, Flags)); + } + } + + if (!MemOpChains.empty()) + Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, + &MemOpChains[0], MemOpChains.size()); + + // Build a sequence of copy-to-reg nodes chained together with token chain + // and flag operands which copy the outgoing args into the appropriate regs. + SDValue InFlag; + for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) { + Chain = DAG.getCopyToReg(Chain, dl, RegsToPass[i].first, + RegsToPass[i].second, InFlag); + InFlag = Chain.getValue(1); + } + + // If the callee is a GlobalAddress/ExternalSymbol node (quite common, every + // direct call is) turn it into a TargetGlobalAddress/TargetExternalSymbol + // node so that legalize doesn't hack it. + bool isDirect = false; + bool isARMFunc = false; + bool isLocalARMFunc = false; + MachineFunction &MF = DAG.getMachineFunction(); + ARMFunctionInfo *AFI = MF.getInfo(); + if (GlobalAddressSDNode *G = dyn_cast(Callee)) { + GlobalValue *GV = G->getGlobal(); + isDirect = true; + bool isExt = GV->isDeclaration() || GV->isWeakForLinker(); + bool isStub = (isExt && Subtarget->isTargetDarwin()) && + getTargetMachine().getRelocationModel() != Reloc::Static; + isARMFunc = !Subtarget->isThumb() || isStub; + // ARM call to a local ARM function is predicable. + isLocalARMFunc = !Subtarget->isThumb() && !isExt; + // tBX takes a register source operand. + if (isARMFunc && Subtarget->isThumb1Only() && !Subtarget->hasV5TOps()) { + unsigned ARMPCLabelIndex = AFI->createConstPoolEntryUId(); + ARMConstantPoolValue *CPV = new ARMConstantPoolValue(GV, + ARMPCLabelIndex, + ARMCP::CPValue, 4); + SDValue CPAddr = DAG.getTargetConstantPool(CPV, getPointerTy(), 4); + CPAddr = DAG.getNode(ARMISD::Wrapper, dl, MVT::i32, CPAddr); + Callee = DAG.getLoad(getPointerTy(), dl, + DAG.getEntryNode(), CPAddr, + PseudoSourceValue::getConstantPool(), 0); + SDValue PICLabel = DAG.getConstant(ARMPCLabelIndex, MVT::i32); + Callee = DAG.getNode(ARMISD::PIC_ADD, dl, + getPointerTy(), Callee, PICLabel); + } else + Callee = DAG.getTargetGlobalAddress(GV, getPointerTy()); + } else if (ExternalSymbolSDNode *S = dyn_cast(Callee)) { + isDirect = true; + bool isStub = Subtarget->isTargetDarwin() && + getTargetMachine().getRelocationModel() != Reloc::Static; + isARMFunc = !Subtarget->isThumb() || isStub; + // tBX takes a register source operand. + const char *Sym = S->getSymbol(); + if (isARMFunc && Subtarget->isThumb1Only() && !Subtarget->hasV5TOps()) { + unsigned ARMPCLabelIndex = AFI->createConstPoolEntryUId(); + ARMConstantPoolValue *CPV = new ARMConstantPoolValue(*DAG.getContext(), + Sym, ARMPCLabelIndex, 4); + SDValue CPAddr = DAG.getTargetConstantPool(CPV, getPointerTy(), 4); + CPAddr = DAG.getNode(ARMISD::Wrapper, dl, MVT::i32, CPAddr); + Callee = DAG.getLoad(getPointerTy(), dl, + DAG.getEntryNode(), CPAddr, + PseudoSourceValue::getConstantPool(), 0); + SDValue PICLabel = DAG.getConstant(ARMPCLabelIndex, MVT::i32); + Callee = DAG.getNode(ARMISD::PIC_ADD, dl, + getPointerTy(), Callee, PICLabel); + } else + Callee = DAG.getTargetExternalSymbol(Sym, getPointerTy()); + } + + // FIXME: handle tail calls differently. + unsigned CallOpc; + if (Subtarget->isThumb()) { + if ((!isDirect || isARMFunc) && !Subtarget->hasV5TOps()) + CallOpc = ARMISD::CALL_NOLINK; + else + CallOpc = isARMFunc ? ARMISD::CALL : ARMISD::tCALL; + } else { + CallOpc = (isDirect || Subtarget->hasV5TOps()) + ? (isLocalARMFunc ? ARMISD::CALL_PRED : ARMISD::CALL) + : ARMISD::CALL_NOLINK; + } + if (CallOpc == ARMISD::CALL_NOLINK && !Subtarget->isThumb1Only()) { + // implicit def LR - LR mustn't be allocated as GRP:$dst of CALL_NOLINK + Chain = DAG.getCopyToReg(Chain, dl, ARM::LR, DAG.getUNDEF(MVT::i32),InFlag); + InFlag = Chain.getValue(1); + } + + std::vector Ops; + Ops.push_back(Chain); + Ops.push_back(Callee); + + // Add argument registers to the end of the list so that they are known live + // into the call. + for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) + Ops.push_back(DAG.getRegister(RegsToPass[i].first, + RegsToPass[i].second.getValueType())); + + if (InFlag.getNode()) + Ops.push_back(InFlag); + // Returns a chain and a flag for retval copy to use. + Chain = DAG.getNode(CallOpc, dl, DAG.getVTList(MVT::Other, MVT::Flag), + &Ops[0], Ops.size()); + InFlag = Chain.getValue(1); + + Chain = DAG.getCALLSEQ_END(Chain, DAG.getIntPtrConstant(NumBytes, true), + DAG.getIntPtrConstant(0, true), InFlag); + if (!Ins.empty()) + InFlag = Chain.getValue(1); + + // Handle result values, copying them out of physregs into vregs that we + // return. + return LowerCallResult(Chain, InFlag, CallConv, isVarArg, Ins, + dl, DAG, InVals); +} + +SDValue +ARMTargetLowering::LowerReturn(SDValue Chain, + CallingConv::ID CallConv, bool isVarArg, + const SmallVectorImpl &Outs, + DebugLoc dl, SelectionDAG &DAG) { + + // CCValAssign - represent the assignment of the return value to a location. + SmallVector RVLocs; + + // CCState - Info about the registers and stack slots. + CCState CCInfo(CallConv, isVarArg, getTargetMachine(), RVLocs, + *DAG.getContext()); + + // Analyze outgoing return values. + CCInfo.AnalyzeReturn(Outs, CCAssignFnForNode(CallConv, /* Return */ true, + isVarArg)); + + // If this is the first return lowered for this function, add + // the regs to the liveout set for the function. + if (DAG.getMachineFunction().getRegInfo().liveout_empty()) { + for (unsigned i = 0; i != RVLocs.size(); ++i) + if (RVLocs[i].isRegLoc()) + DAG.getMachineFunction().getRegInfo().addLiveOut(RVLocs[i].getLocReg()); + } + + SDValue Flag; + + // Copy the result values into the output registers. + for (unsigned i = 0, realRVLocIdx = 0; + i != RVLocs.size(); + ++i, ++realRVLocIdx) { + CCValAssign &VA = RVLocs[i]; + assert(VA.isRegLoc() && "Can only return in registers!"); + + SDValue Arg = Outs[realRVLocIdx].Val; + + switch (VA.getLocInfo()) { + default: llvm_unreachable("Unknown loc info!"); + case CCValAssign::Full: break; + case CCValAssign::BCvt: + Arg = DAG.getNode(ISD::BIT_CONVERT, dl, VA.getLocVT(), Arg); + break; + } + + if (VA.needsCustom()) { + if (VA.getLocVT() == MVT::v2f64) { + // Extract the first half and return it in two registers. + SDValue Half = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, MVT::f64, Arg, + DAG.getConstant(0, MVT::i32)); + SDValue HalfGPRs = DAG.getNode(ARMISD::VMOVRRD, dl, + DAG.getVTList(MVT::i32, MVT::i32), Half); + + Chain = DAG.getCopyToReg(Chain, dl, VA.getLocReg(), HalfGPRs, Flag); + Flag = Chain.getValue(1); + VA = RVLocs[++i]; // skip ahead to next loc + Chain = DAG.getCopyToReg(Chain, dl, VA.getLocReg(), + HalfGPRs.getValue(1), Flag); + Flag = Chain.getValue(1); + VA = RVLocs[++i]; // skip ahead to next loc + + // Extract the 2nd half and fall through to handle it as an f64 value. + Arg = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, MVT::f64, Arg, + DAG.getConstant(1, MVT::i32)); + } + // Legalize ret f64 -> ret 2 x i32. We always have fmrrd if f64 is + // available. + SDValue fmrrd = DAG.getNode(ARMISD::VMOVRRD, dl, + DAG.getVTList(MVT::i32, MVT::i32), &Arg, 1); + Chain = DAG.getCopyToReg(Chain, dl, VA.getLocReg(), fmrrd, Flag); + Flag = Chain.getValue(1); + VA = RVLocs[++i]; // skip ahead to next loc + Chain = DAG.getCopyToReg(Chain, dl, VA.getLocReg(), fmrrd.getValue(1), + Flag); + } else + Chain = DAG.getCopyToReg(Chain, dl, VA.getLocReg(), Arg, Flag); + + // Guarantee that all emitted copies are + // stuck together, avoiding something bad. + Flag = Chain.getValue(1); + } + + SDValue result; + if (Flag.getNode()) + result = DAG.getNode(ARMISD::RET_FLAG, dl, MVT::Other, Chain, Flag); + else // Return Void + result = DAG.getNode(ARMISD::RET_FLAG, dl, MVT::Other, Chain); + + return result; +} + +// ConstantPool, JumpTable, GlobalAddress, and ExternalSymbol are lowered as +// their target counterpart wrapped in the ARMISD::Wrapper node. Suppose N is +// one of the above mentioned nodes. It has to be wrapped because otherwise +// Select(N) returns N. So the raw TargetGlobalAddress nodes, etc. can only +// be used to form addressing mode. These wrapped nodes will be selected +// into MOVi. +static SDValue LowerConstantPool(SDValue Op, SelectionDAG &DAG) { + EVT PtrVT = Op.getValueType(); + // FIXME there is no actual debug info here + DebugLoc dl = Op.getDebugLoc(); + ConstantPoolSDNode *CP = cast(Op); + SDValue Res; + if (CP->isMachineConstantPoolEntry()) + Res = DAG.getTargetConstantPool(CP->getMachineCPVal(), PtrVT, + CP->getAlignment()); + else + Res = DAG.getTargetConstantPool(CP->getConstVal(), PtrVT, + CP->getAlignment()); + return DAG.getNode(ARMISD::Wrapper, dl, MVT::i32, Res); +} + +SDValue ARMTargetLowering::LowerBlockAddress(SDValue Op, SelectionDAG &DAG) { + MachineFunction &MF = DAG.getMachineFunction(); + ARMFunctionInfo *AFI = MF.getInfo(); + unsigned ARMPCLabelIndex = 0; + DebugLoc DL = Op.getDebugLoc(); + EVT PtrVT = getPointerTy(); + BlockAddress *BA = cast(Op)->getBlockAddress(); + Reloc::Model RelocM = getTargetMachine().getRelocationModel(); + SDValue CPAddr; + if (RelocM == Reloc::Static) { + CPAddr = DAG.getTargetConstantPool(BA, PtrVT, 4); + } else { + unsigned PCAdj = Subtarget->isThumb() ? 4 : 8; + ARMPCLabelIndex = AFI->createConstPoolEntryUId(); + ARMConstantPoolValue *CPV = new ARMConstantPoolValue(BA, ARMPCLabelIndex, + ARMCP::CPBlockAddress, + PCAdj); + CPAddr = DAG.getTargetConstantPool(CPV, PtrVT, 4); + } + CPAddr = DAG.getNode(ARMISD::Wrapper, DL, PtrVT, CPAddr); + SDValue Result = DAG.getLoad(PtrVT, DL, DAG.getEntryNode(), CPAddr, + PseudoSourceValue::getConstantPool(), 0); + if (RelocM == Reloc::Static) + return Result; + SDValue PICLabel = DAG.getConstant(ARMPCLabelIndex, MVT::i32); + return DAG.getNode(ARMISD::PIC_ADD, DL, PtrVT, Result, PICLabel); +} + +// Lower ISD::GlobalTLSAddress using the "general dynamic" model +SDValue +ARMTargetLowering::LowerToTLSGeneralDynamicModel(GlobalAddressSDNode *GA, + SelectionDAG &DAG) { + DebugLoc dl = GA->getDebugLoc(); + EVT PtrVT = getPointerTy(); + unsigned char PCAdj = Subtarget->isThumb() ? 4 : 8; + MachineFunction &MF = DAG.getMachineFunction(); + ARMFunctionInfo *AFI = MF.getInfo(); + unsigned ARMPCLabelIndex = AFI->createConstPoolEntryUId(); + ARMConstantPoolValue *CPV = + new ARMConstantPoolValue(GA->getGlobal(), ARMPCLabelIndex, + ARMCP::CPValue, PCAdj, "tlsgd", true); + SDValue Argument = DAG.getTargetConstantPool(CPV, PtrVT, 4); + Argument = DAG.getNode(ARMISD::Wrapper, dl, MVT::i32, Argument); + Argument = DAG.getLoad(PtrVT, dl, DAG.getEntryNode(), Argument, + PseudoSourceValue::getConstantPool(), 0); + SDValue Chain = Argument.getValue(1); + + SDValue PICLabel = DAG.getConstant(ARMPCLabelIndex, MVT::i32); + Argument = DAG.getNode(ARMISD::PIC_ADD, dl, PtrVT, Argument, PICLabel); + + // call __tls_get_addr. + ArgListTy Args; + ArgListEntry Entry; + Entry.Node = Argument; + Entry.Ty = (const Type *) Type::getInt32Ty(*DAG.getContext()); + Args.push_back(Entry); + // FIXME: is there useful debug info available here? + std::pair CallResult = + LowerCallTo(Chain, (const Type *) Type::getInt32Ty(*DAG.getContext()), + false, false, false, false, + 0, CallingConv::C, false, /*isReturnValueUsed=*/true, + DAG.getExternalSymbol("__tls_get_addr", PtrVT), Args, DAG, dl); + return CallResult.first; +} + +// Lower ISD::GlobalTLSAddress using the "initial exec" or +// "local exec" model. +SDValue +ARMTargetLowering::LowerToTLSExecModels(GlobalAddressSDNode *GA, + SelectionDAG &DAG) { + GlobalValue *GV = GA->getGlobal(); + DebugLoc dl = GA->getDebugLoc(); + SDValue Offset; + SDValue Chain = DAG.getEntryNode(); + EVT PtrVT = getPointerTy(); + // Get the Thread Pointer + SDValue ThreadPointer = DAG.getNode(ARMISD::THREAD_POINTER, dl, PtrVT); + + if (GV->isDeclaration()) { + MachineFunction &MF = DAG.getMachineFunction(); + ARMFunctionInfo *AFI = MF.getInfo(); + unsigned ARMPCLabelIndex = AFI->createConstPoolEntryUId(); + // Initial exec model. + unsigned char PCAdj = Subtarget->isThumb() ? 4 : 8; + ARMConstantPoolValue *CPV = + new ARMConstantPoolValue(GA->getGlobal(), ARMPCLabelIndex, + ARMCP::CPValue, PCAdj, "gottpoff", true); + Offset = DAG.getTargetConstantPool(CPV, PtrVT, 4); + Offset = DAG.getNode(ARMISD::Wrapper, dl, MVT::i32, Offset); + Offset = DAG.getLoad(PtrVT, dl, Chain, Offset, + PseudoSourceValue::getConstantPool(), 0); + Chain = Offset.getValue(1); + + SDValue PICLabel = DAG.getConstant(ARMPCLabelIndex, MVT::i32); + Offset = DAG.getNode(ARMISD::PIC_ADD, dl, PtrVT, Offset, PICLabel); + + Offset = DAG.getLoad(PtrVT, dl, Chain, Offset, + PseudoSourceValue::getConstantPool(), 0); + } else { + // local exec model + ARMConstantPoolValue *CPV = new ARMConstantPoolValue(GV, "tpoff"); + Offset = DAG.getTargetConstantPool(CPV, PtrVT, 4); + Offset = DAG.getNode(ARMISD::Wrapper, dl, MVT::i32, Offset); + Offset = DAG.getLoad(PtrVT, dl, Chain, Offset, + PseudoSourceValue::getConstantPool(), 0); + } + + // The address of the thread local variable is the add of the thread + // pointer with the offset of the variable. + return DAG.getNode(ISD::ADD, dl, PtrVT, ThreadPointer, Offset); +} + +SDValue +ARMTargetLowering::LowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) { + // TODO: implement the "local dynamic" model + assert(Subtarget->isTargetELF() && + "TLS not implemented for non-ELF targets"); + GlobalAddressSDNode *GA = cast(Op); + // If the relocation model is PIC, use the "General Dynamic" TLS Model, + // otherwise use the "Local Exec" TLS Model + if (getTargetMachine().getRelocationModel() == Reloc::PIC_) + return LowerToTLSGeneralDynamicModel(GA, DAG); + else + return LowerToTLSExecModels(GA, DAG); +} + +SDValue ARMTargetLowering::LowerGlobalAddressELF(SDValue Op, + SelectionDAG &DAG) { + EVT PtrVT = getPointerTy(); + DebugLoc dl = Op.getDebugLoc(); + GlobalValue *GV = cast(Op)->getGlobal(); + Reloc::Model RelocM = getTargetMachine().getRelocationModel(); + if (RelocM == Reloc::PIC_) { + bool UseGOTOFF = GV->hasLocalLinkage() || GV->hasHiddenVisibility(); + ARMConstantPoolValue *CPV = + new ARMConstantPoolValue(GV, UseGOTOFF ? "GOTOFF" : "GOT"); + SDValue CPAddr = DAG.getTargetConstantPool(CPV, PtrVT, 4); + CPAddr = DAG.getNode(ARMISD::Wrapper, dl, MVT::i32, CPAddr); + SDValue Result = DAG.getLoad(PtrVT, dl, DAG.getEntryNode(), + CPAddr, + PseudoSourceValue::getConstantPool(), 0); + SDValue Chain = Result.getValue(1); + SDValue GOT = DAG.getGLOBAL_OFFSET_TABLE(PtrVT); + Result = DAG.getNode(ISD::ADD, dl, PtrVT, Result, GOT); + if (!UseGOTOFF) + Result = DAG.getLoad(PtrVT, dl, Chain, Result, + PseudoSourceValue::getGOT(), 0); + return Result; + } else { + // If we have T2 ops, we can materialize the address directly via movt/movw + // pair. This is always cheaper. + if (Subtarget->useMovt()) { + return DAG.getNode(ARMISD::Wrapper, dl, PtrVT, + DAG.getTargetGlobalAddress(GV, PtrVT)); + } else { + SDValue CPAddr = DAG.getTargetConstantPool(GV, PtrVT, 4); + CPAddr = DAG.getNode(ARMISD::Wrapper, dl, MVT::i32, CPAddr); + return DAG.getLoad(PtrVT, dl, DAG.getEntryNode(), CPAddr, + PseudoSourceValue::getConstantPool(), 0); + } + } +} + +SDValue ARMTargetLowering::LowerGlobalAddressDarwin(SDValue Op, + SelectionDAG &DAG) { + MachineFunction &MF = DAG.getMachineFunction(); + ARMFunctionInfo *AFI = MF.getInfo(); + unsigned ARMPCLabelIndex = 0; + EVT PtrVT = getPointerTy(); + DebugLoc dl = Op.getDebugLoc(); + GlobalValue *GV = cast(Op)->getGlobal(); + Reloc::Model RelocM = getTargetMachine().getRelocationModel(); + SDValue CPAddr; + if (RelocM == Reloc::Static) + CPAddr = DAG.getTargetConstantPool(GV, PtrVT, 4); + else { + ARMPCLabelIndex = AFI->createConstPoolEntryUId(); + unsigned PCAdj = (RelocM != Reloc::PIC_) ? 0 : (Subtarget->isThumb()?4:8); + ARMConstantPoolValue *CPV = + new ARMConstantPoolValue(GV, ARMPCLabelIndex, ARMCP::CPValue, PCAdj); + CPAddr = DAG.getTargetConstantPool(CPV, PtrVT, 4); + } + CPAddr = DAG.getNode(ARMISD::Wrapper, dl, MVT::i32, CPAddr); + + SDValue Result = DAG.getLoad(PtrVT, dl, DAG.getEntryNode(), CPAddr, + PseudoSourceValue::getConstantPool(), 0); + SDValue Chain = Result.getValue(1); + + if (RelocM == Reloc::PIC_) { + SDValue PICLabel = DAG.getConstant(ARMPCLabelIndex, MVT::i32); + Result = DAG.getNode(ARMISD::PIC_ADD, dl, PtrVT, Result, PICLabel); + } + + if (Subtarget->GVIsIndirectSymbol(GV, RelocM)) + Result = DAG.getLoad(PtrVT, dl, Chain, Result, + PseudoSourceValue::getGOT(), 0); + + return Result; +} + +SDValue ARMTargetLowering::LowerGLOBAL_OFFSET_TABLE(SDValue Op, + SelectionDAG &DAG){ + assert(Subtarget->isTargetELF() && + "GLOBAL OFFSET TABLE not implemented for non-ELF targets"); + MachineFunction &MF = DAG.getMachineFunction(); + ARMFunctionInfo *AFI = MF.getInfo(); + unsigned ARMPCLabelIndex = AFI->createConstPoolEntryUId(); + EVT PtrVT = getPointerTy(); + DebugLoc dl = Op.getDebugLoc(); + unsigned PCAdj = Subtarget->isThumb() ? 4 : 8; + ARMConstantPoolValue *CPV = new ARMConstantPoolValue(*DAG.getContext(), + "_GLOBAL_OFFSET_TABLE_", + ARMPCLabelIndex, PCAdj); + SDValue CPAddr = DAG.getTargetConstantPool(CPV, PtrVT, 4); + CPAddr = DAG.getNode(ARMISD::Wrapper, dl, MVT::i32, CPAddr); + SDValue Result = DAG.getLoad(PtrVT, dl, DAG.getEntryNode(), CPAddr, + PseudoSourceValue::getConstantPool(), 0); + SDValue PICLabel = DAG.getConstant(ARMPCLabelIndex, MVT::i32); + return DAG.getNode(ARMISD::PIC_ADD, dl, PtrVT, Result, PICLabel); +} + +SDValue +ARMTargetLowering::LowerINTRINSIC_WO_CHAIN(SDValue Op, SelectionDAG &DAG) { + unsigned IntNo = cast(Op.getOperand(0))->getZExtValue(); + DebugLoc dl = Op.getDebugLoc(); + switch (IntNo) { + default: return SDValue(); // Don't custom lower most intrinsics. + case Intrinsic::arm_thread_pointer: { + EVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy(); + return DAG.getNode(ARMISD::THREAD_POINTER, dl, PtrVT); + } + case Intrinsic::eh_sjlj_lsda: { + MachineFunction &MF = DAG.getMachineFunction(); + ARMFunctionInfo *AFI = MF.getInfo(); + unsigned ARMPCLabelIndex = AFI->createConstPoolEntryUId(); + EVT PtrVT = getPointerTy(); + DebugLoc dl = Op.getDebugLoc(); + Reloc::Model RelocM = getTargetMachine().getRelocationModel(); + SDValue CPAddr; + unsigned PCAdj = (RelocM != Reloc::PIC_) + ? 0 : (Subtarget->isThumb() ? 4 : 8); + ARMConstantPoolValue *CPV = + new ARMConstantPoolValue(MF.getFunction(), ARMPCLabelIndex, + ARMCP::CPLSDA, PCAdj); + CPAddr = DAG.getTargetConstantPool(CPV, PtrVT, 4); + CPAddr = DAG.getNode(ARMISD::Wrapper, dl, MVT::i32, CPAddr); + SDValue Result = + DAG.getLoad(PtrVT, dl, DAG.getEntryNode(), CPAddr, + PseudoSourceValue::getConstantPool(), 0); + SDValue Chain = Result.getValue(1); + + if (RelocM == Reloc::PIC_) { + SDValue PICLabel = DAG.getConstant(ARMPCLabelIndex, MVT::i32); + Result = DAG.getNode(ARMISD::PIC_ADD, dl, PtrVT, Result, PICLabel); + } + return Result; + } + case Intrinsic::eh_sjlj_setjmp: + return DAG.getNode(ARMISD::EH_SJLJ_SETJMP, dl, MVT::i32, Op.getOperand(1)); + } +} + +static SDValue LowerVASTART(SDValue Op, SelectionDAG &DAG, + unsigned VarArgsFrameIndex) { + // vastart just stores the address of the VarArgsFrameIndex slot into the + // memory location argument. + DebugLoc dl = Op.getDebugLoc(); + EVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy(); + SDValue FR = DAG.getFrameIndex(VarArgsFrameIndex, PtrVT); + const Value *SV = cast(Op.getOperand(2))->getValue(); + return DAG.getStore(Op.getOperand(0), dl, FR, Op.getOperand(1), SV, 0); +} + +SDValue +ARMTargetLowering::LowerDYNAMIC_STACKALLOC(SDValue Op, SelectionDAG &DAG) { + SDNode *Node = Op.getNode(); + DebugLoc dl = Node->getDebugLoc(); + EVT VT = Node->getValueType(0); + SDValue Chain = Op.getOperand(0); + SDValue Size = Op.getOperand(1); + SDValue Align = Op.getOperand(2); + + // Chain the dynamic stack allocation so that it doesn't modify the stack + // pointer when other instructions are using the stack. + Chain = DAG.getCALLSEQ_START(Chain, DAG.getIntPtrConstant(0, true)); + + unsigned AlignVal = cast(Align)->getZExtValue(); + unsigned StackAlign = getTargetMachine().getFrameInfo()->getStackAlignment(); + if (AlignVal > StackAlign) + // Do this now since selection pass cannot introduce new target + // independent node. + Align = DAG.getConstant(-(uint64_t)AlignVal, VT); + + // In Thumb1 mode, there isn't a "sub r, sp, r" instruction, we will end up + // using a "add r, sp, r" instead. Negate the size now so we don't have to + // do even more horrible hack later. + MachineFunction &MF = DAG.getMachineFunction(); + ARMFunctionInfo *AFI = MF.getInfo(); + if (AFI->isThumb1OnlyFunction()) { + bool Negate = true; + ConstantSDNode *C = dyn_cast(Size); + if (C) { + uint32_t Val = C->getZExtValue(); + if (Val <= 508 && ((Val & 3) == 0)) + Negate = false; + } + if (Negate) + Size = DAG.getNode(ISD::SUB, dl, VT, DAG.getConstant(0, VT), Size); + } + + SDVTList VTList = DAG.getVTList(VT, MVT::Other); + SDValue Ops1[] = { Chain, Size, Align }; + SDValue Res = DAG.getNode(ARMISD::DYN_ALLOC, dl, VTList, Ops1, 3); + Chain = Res.getValue(1); + Chain = DAG.getCALLSEQ_END(Chain, DAG.getIntPtrConstant(0, true), + DAG.getIntPtrConstant(0, true), SDValue()); + SDValue Ops2[] = { Res, Chain }; + return DAG.getMergeValues(Ops2, 2, dl); +} + +SDValue +ARMTargetLowering::GetF64FormalArgument(CCValAssign &VA, CCValAssign &NextVA, + SDValue &Root, SelectionDAG &DAG, + DebugLoc dl) { + MachineFunction &MF = DAG.getMachineFunction(); + ARMFunctionInfo *AFI = MF.getInfo(); + + TargetRegisterClass *RC; + if (AFI->isThumb1OnlyFunction()) + RC = ARM::tGPRRegisterClass; + else + RC = ARM::GPRRegisterClass; + + // Transform the arguments stored in physical registers into virtual ones. + unsigned Reg = MF.addLiveIn(VA.getLocReg(), RC); + SDValue ArgValue = DAG.getCopyFromReg(Root, dl, Reg, MVT::i32); + + SDValue ArgValue2; + if (NextVA.isMemLoc()) { + unsigned ArgSize = NextVA.getLocVT().getSizeInBits()/8; + MachineFrameInfo *MFI = MF.getFrameInfo(); + int FI = MFI->CreateFixedObject(ArgSize, NextVA.getLocMemOffset(), + true, false); + + // Create load node to retrieve arguments from the stack. + SDValue FIN = DAG.getFrameIndex(FI, getPointerTy()); + ArgValue2 = DAG.getLoad(MVT::i32, dl, Root, FIN, + PseudoSourceValue::getFixedStack(FI), 0); + } else { + Reg = MF.addLiveIn(NextVA.getLocReg(), RC); + ArgValue2 = DAG.getCopyFromReg(Root, dl, Reg, MVT::i32); + } + + return DAG.getNode(ARMISD::VMOVDRR, dl, MVT::f64, ArgValue, ArgValue2); +} + +SDValue +ARMTargetLowering::LowerFormalArguments(SDValue Chain, + CallingConv::ID CallConv, bool isVarArg, + const SmallVectorImpl + &Ins, + DebugLoc dl, SelectionDAG &DAG, + SmallVectorImpl &InVals) { + + MachineFunction &MF = DAG.getMachineFunction(); + MachineFrameInfo *MFI = MF.getFrameInfo(); + + ARMFunctionInfo *AFI = MF.getInfo(); + + // Assign locations to all of the incoming arguments. + SmallVector ArgLocs; + CCState CCInfo(CallConv, isVarArg, getTargetMachine(), ArgLocs, + *DAG.getContext()); + CCInfo.AnalyzeFormalArguments(Ins, + CCAssignFnForNode(CallConv, /* Return*/ false, + isVarArg)); + + SmallVector ArgValues; + + for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { + CCValAssign &VA = ArgLocs[i]; + + // Arguments stored in registers. + if (VA.isRegLoc()) { + EVT RegVT = VA.getLocVT(); + + SDValue ArgValue; + if (VA.needsCustom()) { + // f64 and vector types are split up into multiple registers or + // combinations of registers and stack slots. + RegVT = MVT::i32; + + if (VA.getLocVT() == MVT::v2f64) { + SDValue ArgValue1 = GetF64FormalArgument(VA, ArgLocs[++i], + Chain, DAG, dl); + VA = ArgLocs[++i]; // skip ahead to next loc + SDValue ArgValue2 = GetF64FormalArgument(VA, ArgLocs[++i], + Chain, DAG, dl); + ArgValue = DAG.getNode(ISD::UNDEF, dl, MVT::v2f64); + ArgValue = DAG.getNode(ISD::INSERT_VECTOR_ELT, dl, MVT::v2f64, + ArgValue, ArgValue1, DAG.getIntPtrConstant(0)); + ArgValue = DAG.getNode(ISD::INSERT_VECTOR_ELT, dl, MVT::v2f64, + ArgValue, ArgValue2, DAG.getIntPtrConstant(1)); + } else + ArgValue = GetF64FormalArgument(VA, ArgLocs[++i], Chain, DAG, dl); + + } else { + TargetRegisterClass *RC; + + if (RegVT == MVT::f32) + RC = ARM::SPRRegisterClass; + else if (RegVT == MVT::f64) + RC = ARM::DPRRegisterClass; + else if (RegVT == MVT::v2f64) + RC = ARM::QPRRegisterClass; + else if (RegVT == MVT::i32) + RC = (AFI->isThumb1OnlyFunction() ? + ARM::tGPRRegisterClass : ARM::GPRRegisterClass); + else + llvm_unreachable("RegVT not supported by FORMAL_ARGUMENTS Lowering"); + + // Transform the arguments in physical registers into virtual ones. + unsigned Reg = MF.addLiveIn(VA.getLocReg(), RC); + ArgValue = DAG.getCopyFromReg(Chain, dl, Reg, RegVT); + } + + // If this is an 8 or 16-bit value, it is really passed promoted + // to 32 bits. Insert an assert[sz]ext to capture this, then + // truncate to the right size. + switch (VA.getLocInfo()) { + default: llvm_unreachable("Unknown loc info!"); + case CCValAssign::Full: break; + case CCValAssign::BCvt: + ArgValue = DAG.getNode(ISD::BIT_CONVERT, dl, VA.getValVT(), ArgValue); + break; + case CCValAssign::SExt: + ArgValue = DAG.getNode(ISD::AssertSext, dl, RegVT, ArgValue, + DAG.getValueType(VA.getValVT())); + ArgValue = DAG.getNode(ISD::TRUNCATE, dl, VA.getValVT(), ArgValue); + break; + case CCValAssign::ZExt: + ArgValue = DAG.getNode(ISD::AssertZext, dl, RegVT, ArgValue, + DAG.getValueType(VA.getValVT())); + ArgValue = DAG.getNode(ISD::TRUNCATE, dl, VA.getValVT(), ArgValue); + break; + } + + InVals.push_back(ArgValue); + + } else { // VA.isRegLoc() + + // sanity check + assert(VA.isMemLoc()); + assert(VA.getValVT() != MVT::i64 && "i64 should already be lowered"); + + unsigned ArgSize = VA.getLocVT().getSizeInBits()/8; + int FI = MFI->CreateFixedObject(ArgSize, VA.getLocMemOffset(), + true, false); + + // Create load nodes to retrieve arguments from the stack. + SDValue FIN = DAG.getFrameIndex(FI, getPointerTy()); + InVals.push_back(DAG.getLoad(VA.getValVT(), dl, Chain, FIN, + PseudoSourceValue::getFixedStack(FI), 0)); + } + } + + // varargs + if (isVarArg) { + static const unsigned GPRArgRegs[] = { + ARM::R0, ARM::R1, ARM::R2, ARM::R3 + }; + + unsigned NumGPRs = CCInfo.getFirstUnallocated + (GPRArgRegs, sizeof(GPRArgRegs) / sizeof(GPRArgRegs[0])); + + unsigned Align = MF.getTarget().getFrameInfo()->getStackAlignment(); + unsigned VARegSize = (4 - NumGPRs) * 4; + unsigned VARegSaveSize = (VARegSize + Align - 1) & ~(Align - 1); + unsigned ArgOffset = CCInfo.getNextStackOffset(); + if (VARegSaveSize) { + // If this function is vararg, store any remaining integer argument regs + // to their spots on the stack so that they may be loaded by deferencing + // the result of va_next. + AFI->setVarArgsRegSaveSize(VARegSaveSize); + VarArgsFrameIndex = MFI->CreateFixedObject(VARegSaveSize, ArgOffset + + VARegSaveSize - VARegSize, + true, false); + SDValue FIN = DAG.getFrameIndex(VarArgsFrameIndex, getPointerTy()); + + SmallVector MemOps; + for (; NumGPRs < 4; ++NumGPRs) { + TargetRegisterClass *RC; + if (AFI->isThumb1OnlyFunction()) + RC = ARM::tGPRRegisterClass; + else + RC = ARM::GPRRegisterClass; + + unsigned VReg = MF.addLiveIn(GPRArgRegs[NumGPRs], RC); + SDValue Val = DAG.getCopyFromReg(Chain, dl, VReg, MVT::i32); + SDValue Store = DAG.getStore(Val.getValue(1), dl, Val, FIN, + PseudoSourceValue::getFixedStack(VarArgsFrameIndex), 0); + MemOps.push_back(Store); + FIN = DAG.getNode(ISD::ADD, dl, getPointerTy(), FIN, + DAG.getConstant(4, getPointerTy())); + } + if (!MemOps.empty()) + Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, + &MemOps[0], MemOps.size()); + } else + // This will point to the next argument passed via stack. + VarArgsFrameIndex = MFI->CreateFixedObject(4, ArgOffset, true, false); + } + + return Chain; +} + +/// isFloatingPointZero - Return true if this is +0.0. +static bool isFloatingPointZero(SDValue Op) { + if (ConstantFPSDNode *CFP = dyn_cast(Op)) + return CFP->getValueAPF().isPosZero(); + else if (ISD::isEXTLoad(Op.getNode()) || ISD::isNON_EXTLoad(Op.getNode())) { + // Maybe this has already been legalized into the constant pool? + if (Op.getOperand(1).getOpcode() == ARMISD::Wrapper) { + SDValue WrapperOp = Op.getOperand(1).getOperand(0); + if (ConstantPoolSDNode *CP = dyn_cast(WrapperOp)) + if (ConstantFP *CFP = dyn_cast(CP->getConstVal())) + return CFP->getValueAPF().isPosZero(); + } + } + return false; +} + +/// Returns appropriate ARM CMP (cmp) and corresponding condition code for +/// the given operands. +SDValue +ARMTargetLowering::getARMCmp(SDValue LHS, SDValue RHS, ISD::CondCode CC, + SDValue &ARMCC, SelectionDAG &DAG, DebugLoc dl) { + if (ConstantSDNode *RHSC = dyn_cast(RHS.getNode())) { + unsigned C = RHSC->getZExtValue(); + if (!isLegalICmpImmediate(C)) { + // Constant does not fit, try adjusting it by one? + switch (CC) { + default: break; + case ISD::SETLT: + case ISD::SETGE: + if (isLegalICmpImmediate(C-1)) { + CC = (CC == ISD::SETLT) ? ISD::SETLE : ISD::SETGT; + RHS = DAG.getConstant(C-1, MVT::i32); + } + break; + case ISD::SETULT: + case ISD::SETUGE: + if (C > 0 && isLegalICmpImmediate(C-1)) { + CC = (CC == ISD::SETULT) ? ISD::SETULE : ISD::SETUGT; + RHS = DAG.getConstant(C-1, MVT::i32); + } + break; + case ISD::SETLE: + case ISD::SETGT: + if (isLegalICmpImmediate(C+1)) { + CC = (CC == ISD::SETLE) ? ISD::SETLT : ISD::SETGE; + RHS = DAG.getConstant(C+1, MVT::i32); + } + break; + case ISD::SETULE: + case ISD::SETUGT: + if (C < 0xffffffff && isLegalICmpImmediate(C+1)) { + CC = (CC == ISD::SETULE) ? ISD::SETULT : ISD::SETUGE; + RHS = DAG.getConstant(C+1, MVT::i32); + } + break; + } + } + } + + ARMCC::CondCodes CondCode = IntCCToARMCC(CC); + ARMISD::NodeType CompareType; + switch (CondCode) { + default: + CompareType = ARMISD::CMP; + break; + case ARMCC::EQ: + case ARMCC::NE: + // Uses only Z Flag + CompareType = ARMISD::CMPZ; + break; + } + ARMCC = DAG.getConstant(CondCode, MVT::i32); + return DAG.getNode(CompareType, dl, MVT::Flag, LHS, RHS); +} + +/// Returns a appropriate VFP CMP (fcmp{s|d}+fmstat) for the given operands. +static SDValue getVFPCmp(SDValue LHS, SDValue RHS, SelectionDAG &DAG, + DebugLoc dl) { + SDValue Cmp; + if (!isFloatingPointZero(RHS)) + Cmp = DAG.getNode(ARMISD::CMPFP, dl, MVT::Flag, LHS, RHS); + else + Cmp = DAG.getNode(ARMISD::CMPFPw0, dl, MVT::Flag, LHS); + return DAG.getNode(ARMISD::FMSTAT, dl, MVT::Flag, Cmp); +} + +SDValue ARMTargetLowering::LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) { + EVT VT = Op.getValueType(); + SDValue LHS = Op.getOperand(0); + SDValue RHS = Op.getOperand(1); + ISD::CondCode CC = cast(Op.getOperand(4))->get(); + SDValue TrueVal = Op.getOperand(2); + SDValue FalseVal = Op.getOperand(3); + DebugLoc dl = Op.getDebugLoc(); + + if (LHS.getValueType() == MVT::i32) { + SDValue ARMCC; + SDValue CCR = DAG.getRegister(ARM::CPSR, MVT::i32); + SDValue Cmp = getARMCmp(LHS, RHS, CC, ARMCC, DAG, dl); + return DAG.getNode(ARMISD::CMOV, dl, VT, FalseVal, TrueVal, ARMCC, CCR,Cmp); + } + + ARMCC::CondCodes CondCode, CondCode2; + FPCCToARMCC(CC, CondCode, CondCode2); + + SDValue ARMCC = DAG.getConstant(CondCode, MVT::i32); + SDValue CCR = DAG.getRegister(ARM::CPSR, MVT::i32); + SDValue Cmp = getVFPCmp(LHS, RHS, DAG, dl); + SDValue Result = DAG.getNode(ARMISD::CMOV, dl, VT, FalseVal, TrueVal, + ARMCC, CCR, Cmp); + if (CondCode2 != ARMCC::AL) { + SDValue ARMCC2 = DAG.getConstant(CondCode2, MVT::i32); + // FIXME: Needs another CMP because flag can have but one use. + SDValue Cmp2 = getVFPCmp(LHS, RHS, DAG, dl); + Result = DAG.getNode(ARMISD::CMOV, dl, VT, + Result, TrueVal, ARMCC2, CCR, Cmp2); + } + return Result; +} + +SDValue ARMTargetLowering::LowerBR_CC(SDValue Op, SelectionDAG &DAG) { + SDValue Chain = Op.getOperand(0); + ISD::CondCode CC = cast(Op.getOperand(1))->get(); + SDValue LHS = Op.getOperand(2); + SDValue RHS = Op.getOperand(3); + SDValue Dest = Op.getOperand(4); + DebugLoc dl = Op.getDebugLoc(); + + if (LHS.getValueType() == MVT::i32) { + SDValue ARMCC; + SDValue CCR = DAG.getRegister(ARM::CPSR, MVT::i32); + SDValue Cmp = getARMCmp(LHS, RHS, CC, ARMCC, DAG, dl); + return DAG.getNode(ARMISD::BRCOND, dl, MVT::Other, + Chain, Dest, ARMCC, CCR,Cmp); + } + + assert(LHS.getValueType() == MVT::f32 || LHS.getValueType() == MVT::f64); + ARMCC::CondCodes CondCode, CondCode2; + FPCCToARMCC(CC, CondCode, CondCode2); + + SDValue Cmp = getVFPCmp(LHS, RHS, DAG, dl); + SDValue ARMCC = DAG.getConstant(CondCode, MVT::i32); + SDValue CCR = DAG.getRegister(ARM::CPSR, MVT::i32); + SDVTList VTList = DAG.getVTList(MVT::Other, MVT::Flag); + SDValue Ops[] = { Chain, Dest, ARMCC, CCR, Cmp }; + SDValue Res = DAG.getNode(ARMISD::BRCOND, dl, VTList, Ops, 5); + if (CondCode2 != ARMCC::AL) { + ARMCC = DAG.getConstant(CondCode2, MVT::i32); + SDValue Ops[] = { Res, Dest, ARMCC, CCR, Res.getValue(1) }; + Res = DAG.getNode(ARMISD::BRCOND, dl, VTList, Ops, 5); + } + return Res; +} + +SDValue ARMTargetLowering::LowerBR_JT(SDValue Op, SelectionDAG &DAG) { + SDValue Chain = Op.getOperand(0); + SDValue Table = Op.getOperand(1); + SDValue Index = Op.getOperand(2); + DebugLoc dl = Op.getDebugLoc(); + + EVT PTy = getPointerTy(); + JumpTableSDNode *JT = cast(Table); + ARMFunctionInfo *AFI = DAG.getMachineFunction().getInfo(); + SDValue UId = DAG.getConstant(AFI->createJumpTableUId(), PTy); + SDValue JTI = DAG.getTargetJumpTable(JT->getIndex(), PTy); + Table = DAG.getNode(ARMISD::WrapperJT, dl, MVT::i32, JTI, UId); + Index = DAG.getNode(ISD::MUL, dl, PTy, Index, DAG.getConstant(4, PTy)); + SDValue Addr = DAG.getNode(ISD::ADD, dl, PTy, Index, Table); + if (Subtarget->isThumb2()) { + // Thumb2 uses a two-level jump. That is, it jumps into the jump table + // which does another jump to the destination. This also makes it easier + // to translate it to TBB / TBH later. + // FIXME: This might not work if the function is extremely large. + return DAG.getNode(ARMISD::BR2_JT, dl, MVT::Other, Chain, + Addr, Op.getOperand(2), JTI, UId); + } + if (getTargetMachine().getRelocationModel() == Reloc::PIC_) { + Addr = DAG.getLoad((EVT)MVT::i32, dl, Chain, Addr, + PseudoSourceValue::getJumpTable(), 0); + Chain = Addr.getValue(1); + Addr = DAG.getNode(ISD::ADD, dl, PTy, Addr, Table); + return DAG.getNode(ARMISD::BR_JT, dl, MVT::Other, Chain, Addr, JTI, UId); + } else { + Addr = DAG.getLoad(PTy, dl, Chain, Addr, + PseudoSourceValue::getJumpTable(), 0); + Chain = Addr.getValue(1); + return DAG.getNode(ARMISD::BR_JT, dl, MVT::Other, Chain, Addr, JTI, UId); + } +} + +static SDValue LowerFP_TO_INT(SDValue Op, SelectionDAG &DAG) { + DebugLoc dl = Op.getDebugLoc(); + unsigned Opc = + Op.getOpcode() == ISD::FP_TO_SINT ? ARMISD::FTOSI : ARMISD::FTOUI; + Op = DAG.getNode(Opc, dl, MVT::f32, Op.getOperand(0)); + return DAG.getNode(ISD::BIT_CONVERT, dl, MVT::i32, Op); +} + +static SDValue LowerINT_TO_FP(SDValue Op, SelectionDAG &DAG) { + EVT VT = Op.getValueType(); + DebugLoc dl = Op.getDebugLoc(); + unsigned Opc = + Op.getOpcode() == ISD::SINT_TO_FP ? ARMISD::SITOF : ARMISD::UITOF; + + Op = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::f32, Op.getOperand(0)); + return DAG.getNode(Opc, dl, VT, Op); +} + +static SDValue LowerFCOPYSIGN(SDValue Op, SelectionDAG &DAG) { + // Implement fcopysign with a fabs and a conditional fneg. + SDValue Tmp0 = Op.getOperand(0); + SDValue Tmp1 = Op.getOperand(1); + DebugLoc dl = Op.getDebugLoc(); + EVT VT = Op.getValueType(); + EVT SrcVT = Tmp1.getValueType(); + SDValue AbsVal = DAG.getNode(ISD::FABS, dl, VT, Tmp0); + SDValue Cmp = getVFPCmp(Tmp1, DAG.getConstantFP(0.0, SrcVT), DAG, dl); + SDValue ARMCC = DAG.getConstant(ARMCC::LT, MVT::i32); + SDValue CCR = DAG.getRegister(ARM::CPSR, MVT::i32); + return DAG.getNode(ARMISD::CNEG, dl, VT, AbsVal, AbsVal, ARMCC, CCR, Cmp); +} + +SDValue ARMTargetLowering::LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) { + MachineFrameInfo *MFI = DAG.getMachineFunction().getFrameInfo(); + MFI->setFrameAddressIsTaken(true); + EVT VT = Op.getValueType(); + DebugLoc dl = Op.getDebugLoc(); // FIXME probably not meaningful + unsigned Depth = cast(Op.getOperand(0))->getZExtValue(); + unsigned FrameReg = (Subtarget->isThumb() || Subtarget->isTargetDarwin()) + ? ARM::R7 : ARM::R11; + SDValue FrameAddr = DAG.getCopyFromReg(DAG.getEntryNode(), dl, FrameReg, VT); + while (Depth--) + FrameAddr = DAG.getLoad(VT, dl, DAG.getEntryNode(), FrameAddr, NULL, 0); + return FrameAddr; +} + +SDValue +ARMTargetLowering::EmitTargetCodeForMemcpy(SelectionDAG &DAG, DebugLoc dl, + SDValue Chain, + SDValue Dst, SDValue Src, + SDValue Size, unsigned Align, + bool AlwaysInline, + const Value *DstSV, uint64_t DstSVOff, + const Value *SrcSV, uint64_t SrcSVOff){ + // Do repeated 4-byte loads and stores. To be improved. + // This requires 4-byte alignment. + if ((Align & 3) != 0) + return SDValue(); + // This requires the copy size to be a constant, preferrably + // within a subtarget-specific limit. + ConstantSDNode *ConstantSize = dyn_cast(Size); + if (!ConstantSize) + return SDValue(); + uint64_t SizeVal = ConstantSize->getZExtValue(); + if (!AlwaysInline && SizeVal > getSubtarget()->getMaxInlineSizeThreshold()) + return SDValue(); + + unsigned BytesLeft = SizeVal & 3; + unsigned NumMemOps = SizeVal >> 2; + unsigned EmittedNumMemOps = 0; + EVT VT = MVT::i32; + unsigned VTSize = 4; + unsigned i = 0; + const unsigned MAX_LOADS_IN_LDM = 6; + SDValue TFOps[MAX_LOADS_IN_LDM]; + SDValue Loads[MAX_LOADS_IN_LDM]; + uint64_t SrcOff = 0, DstOff = 0; + + // Emit up to MAX_LOADS_IN_LDM loads, then a TokenFactor barrier, then the + // same number of stores. The loads and stores will get combined into + // ldm/stm later on. + while (EmittedNumMemOps < NumMemOps) { + for (i = 0; + i < MAX_LOADS_IN_LDM && EmittedNumMemOps + i < NumMemOps; ++i) { + Loads[i] = DAG.getLoad(VT, dl, Chain, + DAG.getNode(ISD::ADD, dl, MVT::i32, Src, + DAG.getConstant(SrcOff, MVT::i32)), + SrcSV, SrcSVOff + SrcOff); + TFOps[i] = Loads[i].getValue(1); + SrcOff += VTSize; + } + Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, &TFOps[0], i); + + for (i = 0; + i < MAX_LOADS_IN_LDM && EmittedNumMemOps + i < NumMemOps; ++i) { + TFOps[i] = DAG.getStore(Chain, dl, Loads[i], + DAG.getNode(ISD::ADD, dl, MVT::i32, Dst, + DAG.getConstant(DstOff, MVT::i32)), + DstSV, DstSVOff + DstOff); + DstOff += VTSize; + } + Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, &TFOps[0], i); + + EmittedNumMemOps += i; + } + + if (BytesLeft == 0) + return Chain; + + // Issue loads / stores for the trailing (1 - 3) bytes. + unsigned BytesLeftSave = BytesLeft; + i = 0; + while (BytesLeft) { + if (BytesLeft >= 2) { + VT = MVT::i16; + VTSize = 2; + } else { + VT = MVT::i8; + VTSize = 1; + } + + Loads[i] = DAG.getLoad(VT, dl, Chain, + DAG.getNode(ISD::ADD, dl, MVT::i32, Src, + DAG.getConstant(SrcOff, MVT::i32)), + SrcSV, SrcSVOff + SrcOff); + TFOps[i] = Loads[i].getValue(1); + ++i; + SrcOff += VTSize; + BytesLeft -= VTSize; + } + Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, &TFOps[0], i); + + i = 0; + BytesLeft = BytesLeftSave; + while (BytesLeft) { + if (BytesLeft >= 2) { + VT = MVT::i16; + VTSize = 2; + } else { + VT = MVT::i8; + VTSize = 1; + } + + TFOps[i] = DAG.getStore(Chain, dl, Loads[i], + DAG.getNode(ISD::ADD, dl, MVT::i32, Dst, + DAG.getConstant(DstOff, MVT::i32)), + DstSV, DstSVOff + DstOff); + ++i; + DstOff += VTSize; + BytesLeft -= VTSize; + } + return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, &TFOps[0], i); +} + +static SDValue ExpandBIT_CONVERT(SDNode *N, SelectionDAG &DAG) { + SDValue Op = N->getOperand(0); + DebugLoc dl = N->getDebugLoc(); + if (N->getValueType(0) == MVT::f64) { + // Turn i64->f64 into VMOVDRR. + SDValue Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, Op, + DAG.getConstant(0, MVT::i32)); + SDValue Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, Op, + DAG.getConstant(1, MVT::i32)); + return DAG.getNode(ARMISD::VMOVDRR, dl, MVT::f64, Lo, Hi); + } + + // Turn f64->i64 into VMOVRRD. + SDValue Cvt = DAG.getNode(ARMISD::VMOVRRD, dl, + DAG.getVTList(MVT::i32, MVT::i32), &Op, 1); + + // Merge the pieces into a single i64 value. + return DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i64, Cvt, Cvt.getValue(1)); +} + +/// getZeroVector - Returns a vector of specified type with all zero elements. +/// +static SDValue getZeroVector(EVT VT, SelectionDAG &DAG, DebugLoc dl) { + assert(VT.isVector() && "Expected a vector type"); + + // Zero vectors are used to represent vector negation and in those cases + // will be implemented with the NEON VNEG instruction. However, VNEG does + // not support i64 elements, so sometimes the zero vectors will need to be + // explicitly constructed. For those cases, and potentially other uses in + // the future, always build zero vectors as <16 x i8> or <8 x i8> bitcasted + // to their dest type. This ensures they get CSE'd. + SDValue Vec; + SDValue Cst = DAG.getTargetConstant(0, MVT::i8); + SmallVector Ops; + MVT TVT; + + if (VT.getSizeInBits() == 64) { + Ops.assign(8, Cst); TVT = MVT::v8i8; + } else { + Ops.assign(16, Cst); TVT = MVT::v16i8; + } + Vec = DAG.getNode(ISD::BUILD_VECTOR, dl, TVT, &Ops[0], Ops.size()); + + return DAG.getNode(ISD::BIT_CONVERT, dl, VT, Vec); +} + +/// getOnesVector - Returns a vector of specified type with all bits set. +/// +static SDValue getOnesVector(EVT VT, SelectionDAG &DAG, DebugLoc dl) { + assert(VT.isVector() && "Expected a vector type"); + + // Always build ones vectors as <16 x i8> or <8 x i8> bitcasted to their + // dest type. This ensures they get CSE'd. + SDValue Vec; + SDValue Cst = DAG.getTargetConstant(0xFF, MVT::i8); + SmallVector Ops; + MVT TVT; + + if (VT.getSizeInBits() == 64) { + Ops.assign(8, Cst); TVT = MVT::v8i8; + } else { + Ops.assign(16, Cst); TVT = MVT::v16i8; + } + Vec = DAG.getNode(ISD::BUILD_VECTOR, dl, TVT, &Ops[0], Ops.size()); + + return DAG.getNode(ISD::BIT_CONVERT, dl, VT, Vec); +} + +/// LowerShiftRightParts - Lower SRA_PARTS, which returns two +/// i32 values and take a 2 x i32 value to shift plus a shift amount. +SDValue ARMTargetLowering::LowerShiftRightParts(SDValue Op, SelectionDAG &DAG) { + assert(Op.getNumOperands() == 3 && "Not a double-shift!"); + EVT VT = Op.getValueType(); + unsigned VTBits = VT.getSizeInBits(); + DebugLoc dl = Op.getDebugLoc(); + SDValue ShOpLo = Op.getOperand(0); + SDValue ShOpHi = Op.getOperand(1); + SDValue ShAmt = Op.getOperand(2); + SDValue ARMCC; + unsigned Opc = (Op.getOpcode() == ISD::SRA_PARTS) ? ISD::SRA : ISD::SRL; + + assert(Op.getOpcode() == ISD::SRA_PARTS || Op.getOpcode() == ISD::SRL_PARTS); + + SDValue RevShAmt = DAG.getNode(ISD::SUB, dl, MVT::i32, + DAG.getConstant(VTBits, MVT::i32), ShAmt); + SDValue Tmp1 = DAG.getNode(ISD::SRL, dl, VT, ShOpLo, ShAmt); + SDValue ExtraShAmt = DAG.getNode(ISD::SUB, dl, MVT::i32, ShAmt, + DAG.getConstant(VTBits, MVT::i32)); + SDValue Tmp2 = DAG.getNode(ISD::SHL, dl, VT, ShOpHi, RevShAmt); + SDValue FalseVal = DAG.getNode(ISD::OR, dl, VT, Tmp1, Tmp2); + SDValue TrueVal = DAG.getNode(Opc, dl, VT, ShOpHi, ExtraShAmt); + + SDValue CCR = DAG.getRegister(ARM::CPSR, MVT::i32); + SDValue Cmp = getARMCmp(ExtraShAmt, DAG.getConstant(0, MVT::i32), ISD::SETGE, + ARMCC, DAG, dl); + SDValue Hi = DAG.getNode(Opc, dl, VT, ShOpHi, ShAmt); + SDValue Lo = DAG.getNode(ARMISD::CMOV, dl, VT, FalseVal, TrueVal, ARMCC, + CCR, Cmp); + + SDValue Ops[2] = { Lo, Hi }; + return DAG.getMergeValues(Ops, 2, dl); +} + +/// LowerShiftLeftParts - Lower SHL_PARTS, which returns two +/// i32 values and take a 2 x i32 value to shift plus a shift amount. +SDValue ARMTargetLowering::LowerShiftLeftParts(SDValue Op, SelectionDAG &DAG) { + assert(Op.getNumOperands() == 3 && "Not a double-shift!"); + EVT VT = Op.getValueType(); + unsigned VTBits = VT.getSizeInBits(); + DebugLoc dl = Op.getDebugLoc(); + SDValue ShOpLo = Op.getOperand(0); + SDValue ShOpHi = Op.getOperand(1); + SDValue ShAmt = Op.getOperand(2); + SDValue ARMCC; + + assert(Op.getOpcode() == ISD::SHL_PARTS); + SDValue RevShAmt = DAG.getNode(ISD::SUB, dl, MVT::i32, + DAG.getConstant(VTBits, MVT::i32), ShAmt); + SDValue Tmp1 = DAG.getNode(ISD::SRL, dl, VT, ShOpLo, RevShAmt); + SDValue ExtraShAmt = DAG.getNode(ISD::SUB, dl, MVT::i32, ShAmt, + DAG.getConstant(VTBits, MVT::i32)); + SDValue Tmp2 = DAG.getNode(ISD::SHL, dl, VT, ShOpHi, ShAmt); + SDValue Tmp3 = DAG.getNode(ISD::SHL, dl, VT, ShOpLo, ExtraShAmt); + + SDValue FalseVal = DAG.getNode(ISD::OR, dl, VT, Tmp1, Tmp2); + SDValue CCR = DAG.getRegister(ARM::CPSR, MVT::i32); + SDValue Cmp = getARMCmp(ExtraShAmt, DAG.getConstant(0, MVT::i32), ISD::SETGE, + ARMCC, DAG, dl); + SDValue Lo = DAG.getNode(ISD::SHL, dl, VT, ShOpLo, ShAmt); + SDValue Hi = DAG.getNode(ARMISD::CMOV, dl, VT, FalseVal, Tmp3, ARMCC, + CCR, Cmp); + + SDValue Ops[2] = { Lo, Hi }; + return DAG.getMergeValues(Ops, 2, dl); +} + +static SDValue LowerShift(SDNode *N, SelectionDAG &DAG, + const ARMSubtarget *ST) { + EVT VT = N->getValueType(0); + DebugLoc dl = N->getDebugLoc(); + + // Lower vector shifts on NEON to use VSHL. + if (VT.isVector()) { + assert(ST->hasNEON() && "unexpected vector shift"); + + // Left shifts translate directly to the vshiftu intrinsic. + if (N->getOpcode() == ISD::SHL) + return DAG.getNode(ISD::INTRINSIC_WO_CHAIN, dl, VT, + DAG.getConstant(Intrinsic::arm_neon_vshiftu, MVT::i32), + N->getOperand(0), N->getOperand(1)); + + assert((N->getOpcode() == ISD::SRA || + N->getOpcode() == ISD::SRL) && "unexpected vector shift opcode"); + + // NEON uses the same intrinsics for both left and right shifts. For + // right shifts, the shift amounts are negative, so negate the vector of + // shift amounts. + EVT ShiftVT = N->getOperand(1).getValueType(); + SDValue NegatedCount = DAG.getNode(ISD::SUB, dl, ShiftVT, + getZeroVector(ShiftVT, DAG, dl), + N->getOperand(1)); + Intrinsic::ID vshiftInt = (N->getOpcode() == ISD::SRA ? + Intrinsic::arm_neon_vshifts : + Intrinsic::arm_neon_vshiftu); + return DAG.getNode(ISD::INTRINSIC_WO_CHAIN, dl, VT, + DAG.getConstant(vshiftInt, MVT::i32), + N->getOperand(0), NegatedCount); + } + + // We can get here for a node like i32 = ISD::SHL i32, i64 + if (VT != MVT::i64) + return SDValue(); + + assert((N->getOpcode() == ISD::SRL || N->getOpcode() == ISD::SRA) && + "Unknown shift to lower!"); + + // We only lower SRA, SRL of 1 here, all others use generic lowering. + if (!isa(N->getOperand(1)) || + cast(N->getOperand(1))->getZExtValue() != 1) + return SDValue(); + + // If we are in thumb mode, we don't have RRX. + if (ST->isThumb1Only()) return SDValue(); + + // Okay, we have a 64-bit SRA or SRL of 1. Lower this to an RRX expr. + SDValue Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, N->getOperand(0), + DAG.getConstant(0, MVT::i32)); + SDValue Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, N->getOperand(0), + DAG.getConstant(1, MVT::i32)); + + // First, build a SRA_FLAG/SRL_FLAG op, which shifts the top part by one and + // captures the result into a carry flag. + unsigned Opc = N->getOpcode() == ISD::SRL ? ARMISD::SRL_FLAG:ARMISD::SRA_FLAG; + Hi = DAG.getNode(Opc, dl, DAG.getVTList(MVT::i32, MVT::Flag), &Hi, 1); + + // The low part is an ARMISD::RRX operand, which shifts the carry in. + Lo = DAG.getNode(ARMISD::RRX, dl, MVT::i32, Lo, Hi.getValue(1)); + + // Merge the pieces into a single i64 value. + return DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i64, Lo, Hi); +} + +static SDValue LowerVSETCC(SDValue Op, SelectionDAG &DAG) { + SDValue TmpOp0, TmpOp1; + bool Invert = false; + bool Swap = false; + unsigned Opc = 0; + + SDValue Op0 = Op.getOperand(0); + SDValue Op1 = Op.getOperand(1); + SDValue CC = Op.getOperand(2); + EVT VT = Op.getValueType(); + ISD::CondCode SetCCOpcode = cast(CC)->get(); + DebugLoc dl = Op.getDebugLoc(); + + if (Op.getOperand(1).getValueType().isFloatingPoint()) { + switch (SetCCOpcode) { + default: llvm_unreachable("Illegal FP comparison"); break; + case ISD::SETUNE: + case ISD::SETNE: Invert = true; // Fallthrough + case ISD::SETOEQ: + case ISD::SETEQ: Opc = ARMISD::VCEQ; break; + case ISD::SETOLT: + case ISD::SETLT: Swap = true; // Fallthrough + case ISD::SETOGT: + case ISD::SETGT: Opc = ARMISD::VCGT; break; + case ISD::SETOLE: + case ISD::SETLE: Swap = true; // Fallthrough + case ISD::SETOGE: + case ISD::SETGE: Opc = ARMISD::VCGE; break; + case ISD::SETUGE: Swap = true; // Fallthrough + case ISD::SETULE: Invert = true; Opc = ARMISD::VCGT; break; + case ISD::SETUGT: Swap = true; // Fallthrough + case ISD::SETULT: Invert = true; Opc = ARMISD::VCGE; break; + case ISD::SETUEQ: Invert = true; // Fallthrough + case ISD::SETONE: + // Expand this to (OLT | OGT). + TmpOp0 = Op0; + TmpOp1 = Op1; + Opc = ISD::OR; + Op0 = DAG.getNode(ARMISD::VCGT, dl, VT, TmpOp1, TmpOp0); + Op1 = DAG.getNode(ARMISD::VCGT, dl, VT, TmpOp0, TmpOp1); + break; + case ISD::SETUO: Invert = true; // Fallthrough + case ISD::SETO: + // Expand this to (OLT | OGE). + TmpOp0 = Op0; + TmpOp1 = Op1; + Opc = ISD::OR; + Op0 = DAG.getNode(ARMISD::VCGT, dl, VT, TmpOp1, TmpOp0); + Op1 = DAG.getNode(ARMISD::VCGE, dl, VT, TmpOp0, TmpOp1); + break; + } + } else { + // Integer comparisons. + switch (SetCCOpcode) { + default: llvm_unreachable("Illegal integer comparison"); break; + case ISD::SETNE: Invert = true; + case ISD::SETEQ: Opc = ARMISD::VCEQ; break; + case ISD::SETLT: Swap = true; + case ISD::SETGT: Opc = ARMISD::VCGT; break; + case ISD::SETLE: Swap = true; + case ISD::SETGE: Opc = ARMISD::VCGE; break; + case ISD::SETULT: Swap = true; + case ISD::SETUGT: Opc = ARMISD::VCGTU; break; + case ISD::SETULE: Swap = true; + case ISD::SETUGE: Opc = ARMISD::VCGEU; break; + } + + // Detect VTST (Vector Test Bits) = icmp ne (and (op0, op1), zero). + if (Opc == ARMISD::VCEQ) { + + SDValue AndOp; + if (ISD::isBuildVectorAllZeros(Op1.getNode())) + AndOp = Op0; + else if (ISD::isBuildVectorAllZeros(Op0.getNode())) + AndOp = Op1; + + // Ignore bitconvert. + if (AndOp.getNode() && AndOp.getOpcode() == ISD::BIT_CONVERT) + AndOp = AndOp.getOperand(0); + + if (AndOp.getNode() && AndOp.getOpcode() == ISD::AND) { + Opc = ARMISD::VTST; + Op0 = DAG.getNode(ISD::BIT_CONVERT, dl, VT, AndOp.getOperand(0)); + Op1 = DAG.getNode(ISD::BIT_CONVERT, dl, VT, AndOp.getOperand(1)); + Invert = !Invert; + } + } + } + + if (Swap) + std::swap(Op0, Op1); + + SDValue Result = DAG.getNode(Opc, dl, VT, Op0, Op1); + + if (Invert) + Result = DAG.getNOT(dl, Result, VT); + + return Result; +} + +/// isVMOVSplat - Check if the specified splat value corresponds to an immediate +/// VMOV instruction, and if so, return the constant being splatted. +static SDValue isVMOVSplat(uint64_t SplatBits, uint64_t SplatUndef, + unsigned SplatBitSize, SelectionDAG &DAG) { + switch (SplatBitSize) { + case 8: + // Any 1-byte value is OK. + assert((SplatBits & ~0xff) == 0 && "one byte splat value is too big"); + return DAG.getTargetConstant(SplatBits, MVT::i8); + + case 16: + // NEON's 16-bit VMOV supports splat values where only one byte is nonzero. + if ((SplatBits & ~0xff) == 0 || + (SplatBits & ~0xff00) == 0) + return DAG.getTargetConstant(SplatBits, MVT::i16); + break; + + case 32: + // NEON's 32-bit VMOV supports splat values where: + // * only one byte is nonzero, or + // * the least significant byte is 0xff and the second byte is nonzero, or + // * the least significant 2 bytes are 0xff and the third is nonzero. + if ((SplatBits & ~0xff) == 0 || + (SplatBits & ~0xff00) == 0 || + (SplatBits & ~0xff0000) == 0 || + (SplatBits & ~0xff000000) == 0) + return DAG.getTargetConstant(SplatBits, MVT::i32); + + if ((SplatBits & ~0xffff) == 0 && + ((SplatBits | SplatUndef) & 0xff) == 0xff) + return DAG.getTargetConstant(SplatBits | 0xff, MVT::i32); + + if ((SplatBits & ~0xffffff) == 0 && + ((SplatBits | SplatUndef) & 0xffff) == 0xffff) + return DAG.getTargetConstant(SplatBits | 0xffff, MVT::i32); + + // Note: there are a few 32-bit splat values (specifically: 00ffff00, + // ff000000, ff0000ff, and ffff00ff) that are valid for VMOV.I64 but not + // VMOV.I32. A (very) minor optimization would be to replicate the value + // and fall through here to test for a valid 64-bit splat. But, then the + // caller would also need to check and handle the change in size. + break; + + case 64: { + // NEON has a 64-bit VMOV splat where each byte is either 0 or 0xff. + uint64_t BitMask = 0xff; + uint64_t Val = 0; + for (int ByteNum = 0; ByteNum < 8; ++ByteNum) { + if (((SplatBits | SplatUndef) & BitMask) == BitMask) + Val |= BitMask; + else if ((SplatBits & BitMask) != 0) + return SDValue(); + BitMask <<= 8; + } + return DAG.getTargetConstant(Val, MVT::i64); + } + + default: + llvm_unreachable("unexpected size for isVMOVSplat"); + break; + } + + return SDValue(); +} + +/// getVMOVImm - If this is a build_vector of constants which can be +/// formed by using a VMOV instruction of the specified element size, +/// return the constant being splatted. The ByteSize field indicates the +/// number of bytes of each element [1248]. +SDValue ARM::getVMOVImm(SDNode *N, unsigned ByteSize, SelectionDAG &DAG) { + BuildVectorSDNode *BVN = dyn_cast(N); + APInt SplatBits, SplatUndef; + unsigned SplatBitSize; + bool HasAnyUndefs; + if (! BVN || ! BVN->isConstantSplat(SplatBits, SplatUndef, SplatBitSize, + HasAnyUndefs, ByteSize * 8)) + return SDValue(); + + if (SplatBitSize > ByteSize * 8) + return SDValue(); + + return isVMOVSplat(SplatBits.getZExtValue(), SplatUndef.getZExtValue(), + SplatBitSize, DAG); +} + +static bool isVEXTMask(const SmallVectorImpl &M, EVT VT, + bool &ReverseVEXT, unsigned &Imm) { + unsigned NumElts = VT.getVectorNumElements(); + ReverseVEXT = false; + Imm = M[0]; + + // If this is a VEXT shuffle, the immediate value is the index of the first + // element. The other shuffle indices must be the successive elements after + // the first one. + unsigned ExpectedElt = Imm; + for (unsigned i = 1; i < NumElts; ++i) { + // Increment the expected index. If it wraps around, it may still be + // a VEXT but the source vectors must be swapped. + ExpectedElt += 1; + if (ExpectedElt == NumElts * 2) { + ExpectedElt = 0; + ReverseVEXT = true; + } + + if (ExpectedElt != static_cast(M[i])) + return false; + } + + // Adjust the index value if the source operands will be swapped. + if (ReverseVEXT) + Imm -= NumElts; + + return true; +} + +/// isVREVMask - Check if a vector shuffle corresponds to a VREV +/// instruction with the specified blocksize. (The order of the elements +/// within each block of the vector is reversed.) +static bool isVREVMask(const SmallVectorImpl &M, EVT VT, + unsigned BlockSize) { + assert((BlockSize==16 || BlockSize==32 || BlockSize==64) && + "Only possible block sizes for VREV are: 16, 32, 64"); + + unsigned EltSz = VT.getVectorElementType().getSizeInBits(); + if (EltSz == 64) + return false; + + unsigned NumElts = VT.getVectorNumElements(); + unsigned BlockElts = M[0] + 1; + + if (BlockSize <= EltSz || BlockSize != BlockElts * EltSz) + return false; + + for (unsigned i = 0; i < NumElts; ++i) { + if ((unsigned) M[i] != + (i - i%BlockElts) + (BlockElts - 1 - i%BlockElts)) + return false; + } + + return true; +} + +static bool isVTRNMask(const SmallVectorImpl &M, EVT VT, + unsigned &WhichResult) { + unsigned EltSz = VT.getVectorElementType().getSizeInBits(); + if (EltSz == 64) + return false; + + unsigned NumElts = VT.getVectorNumElements(); + WhichResult = (M[0] == 0 ? 0 : 1); + for (unsigned i = 0; i < NumElts; i += 2) { + if ((unsigned) M[i] != i + WhichResult || + (unsigned) M[i+1] != i + NumElts + WhichResult) + return false; + } + return true; +} + +static bool isVUZPMask(const SmallVectorImpl &M, EVT VT, + unsigned &WhichResult) { + unsigned EltSz = VT.getVectorElementType().getSizeInBits(); + if (EltSz == 64) + return false; + + unsigned NumElts = VT.getVectorNumElements(); + WhichResult = (M[0] == 0 ? 0 : 1); + for (unsigned i = 0; i != NumElts; ++i) { + if ((unsigned) M[i] != 2 * i + WhichResult) + return false; + } + + // VUZP.32 for 64-bit vectors is a pseudo-instruction alias for VTRN.32. + if (VT.is64BitVector() && EltSz == 32) + return false; + + return true; +} + +static bool isVZIPMask(const SmallVectorImpl &M, EVT VT, + unsigned &WhichResult) { + unsigned EltSz = VT.getVectorElementType().getSizeInBits(); + if (EltSz == 64) + return false; + + unsigned NumElts = VT.getVectorNumElements(); + WhichResult = (M[0] == 0 ? 0 : 1); + unsigned Idx = WhichResult * NumElts / 2; + for (unsigned i = 0; i != NumElts; i += 2) { + if ((unsigned) M[i] != Idx || + (unsigned) M[i+1] != Idx + NumElts) + return false; + Idx += 1; + } + + // VZIP.32 for 64-bit vectors is a pseudo-instruction alias for VTRN.32. + if (VT.is64BitVector() && EltSz == 32) + return false; + + return true; +} + +static SDValue BuildSplat(SDValue Val, EVT VT, SelectionDAG &DAG, DebugLoc dl) { + // Canonicalize all-zeros and all-ones vectors. + ConstantSDNode *ConstVal = cast(Val.getNode()); + if (ConstVal->isNullValue()) + return getZeroVector(VT, DAG, dl); + if (ConstVal->isAllOnesValue()) + return getOnesVector(VT, DAG, dl); + + EVT CanonicalVT; + if (VT.is64BitVector()) { + switch (Val.getValueType().getSizeInBits()) { + case 8: CanonicalVT = MVT::v8i8; break; + case 16: CanonicalVT = MVT::v4i16; break; + case 32: CanonicalVT = MVT::v2i32; break; + case 64: CanonicalVT = MVT::v1i64; break; + default: llvm_unreachable("unexpected splat element type"); break; + } + } else { + assert(VT.is128BitVector() && "unknown splat vector size"); + switch (Val.getValueType().getSizeInBits()) { + case 8: CanonicalVT = MVT::v16i8; break; + case 16: CanonicalVT = MVT::v8i16; break; + case 32: CanonicalVT = MVT::v4i32; break; + case 64: CanonicalVT = MVT::v2i64; break; + default: llvm_unreachable("unexpected splat element type"); break; + } + } + + // Build a canonical splat for this value. + SmallVector Ops; + Ops.assign(CanonicalVT.getVectorNumElements(), Val); + SDValue Res = DAG.getNode(ISD::BUILD_VECTOR, dl, CanonicalVT, &Ops[0], + Ops.size()); + return DAG.getNode(ISD::BIT_CONVERT, dl, VT, Res); +} + +// If this is a case we can't handle, return null and let the default +// expansion code take care of it. +static SDValue LowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG) { + BuildVectorSDNode *BVN = cast(Op.getNode()); + DebugLoc dl = Op.getDebugLoc(); + EVT VT = Op.getValueType(); + + APInt SplatBits, SplatUndef; + unsigned SplatBitSize; + bool HasAnyUndefs; + if (BVN->isConstantSplat(SplatBits, SplatUndef, SplatBitSize, HasAnyUndefs)) { + if (SplatBitSize <= 64) { + SDValue Val = isVMOVSplat(SplatBits.getZExtValue(), + SplatUndef.getZExtValue(), SplatBitSize, DAG); + if (Val.getNode()) + return BuildSplat(Val, VT, DAG, dl); + } + } + + // If there are only 2 elements in a 128-bit vector, insert them into an + // undef vector. This handles the common case for 128-bit vector argument + // passing, where the insertions should be translated to subreg accesses + // with no real instructions. + if (VT.is128BitVector() && Op.getNumOperands() == 2) { + SDValue Val = DAG.getUNDEF(VT); + SDValue Op0 = Op.getOperand(0); + SDValue Op1 = Op.getOperand(1); + if (Op0.getOpcode() != ISD::UNDEF) + Val = DAG.getNode(ISD::INSERT_VECTOR_ELT, dl, VT, Val, Op0, + DAG.getIntPtrConstant(0)); + if (Op1.getOpcode() != ISD::UNDEF) + Val = DAG.getNode(ISD::INSERT_VECTOR_ELT, dl, VT, Val, Op1, + DAG.getIntPtrConstant(1)); + return Val; + } + + return SDValue(); +} + +/// isShuffleMaskLegal - Targets can use this to indicate that they only +/// support *some* VECTOR_SHUFFLE operations, those with specific masks. +/// By default, if a target supports the VECTOR_SHUFFLE node, all mask values +/// are assumed to be legal. +bool +ARMTargetLowering::isShuffleMaskLegal(const SmallVectorImpl &M, + EVT VT) const { + if (VT.getVectorNumElements() == 4 && + (VT.is128BitVector() || VT.is64BitVector())) { + unsigned PFIndexes[4]; + for (unsigned i = 0; i != 4; ++i) { + if (M[i] < 0) + PFIndexes[i] = 8; + else + PFIndexes[i] = M[i]; + } + + // Compute the index in the perfect shuffle table. + unsigned PFTableIndex = + PFIndexes[0]*9*9*9+PFIndexes[1]*9*9+PFIndexes[2]*9+PFIndexes[3]; + unsigned PFEntry = PerfectShuffleTable[PFTableIndex]; + unsigned Cost = (PFEntry >> 30); + + if (Cost <= 4) + return true; + } + + bool ReverseVEXT; + unsigned Imm, WhichResult; + + return (ShuffleVectorSDNode::isSplatMask(&M[0], VT) || + isVREVMask(M, VT, 64) || + isVREVMask(M, VT, 32) || + isVREVMask(M, VT, 16) || + isVEXTMask(M, VT, ReverseVEXT, Imm) || + isVTRNMask(M, VT, WhichResult) || + isVUZPMask(M, VT, WhichResult) || + isVZIPMask(M, VT, WhichResult)); +} + +/// GeneratePerfectShuffle - Given an entry in the perfect-shuffle table, emit +/// the specified operations to build the shuffle. +static SDValue GeneratePerfectShuffle(unsigned PFEntry, SDValue LHS, + SDValue RHS, SelectionDAG &DAG, + DebugLoc dl) { + unsigned OpNum = (PFEntry >> 26) & 0x0F; + unsigned LHSID = (PFEntry >> 13) & ((1 << 13)-1); + unsigned RHSID = (PFEntry >> 0) & ((1 << 13)-1); + + enum { + OP_COPY = 0, // Copy, used for things like to say it is <0,1,2,3> + OP_VREV, + OP_VDUP0, + OP_VDUP1, + OP_VDUP2, + OP_VDUP3, + OP_VEXT1, + OP_VEXT2, + OP_VEXT3, + OP_VUZPL, // VUZP, left result + OP_VUZPR, // VUZP, right result + OP_VZIPL, // VZIP, left result + OP_VZIPR, // VZIP, right result + OP_VTRNL, // VTRN, left result + OP_VTRNR // VTRN, right result + }; + + if (OpNum == OP_COPY) { + if (LHSID == (1*9+2)*9+3) return LHS; + assert(LHSID == ((4*9+5)*9+6)*9+7 && "Illegal OP_COPY!"); + return RHS; + } + + SDValue OpLHS, OpRHS; + OpLHS = GeneratePerfectShuffle(PerfectShuffleTable[LHSID], LHS, RHS, DAG, dl); + OpRHS = GeneratePerfectShuffle(PerfectShuffleTable[RHSID], LHS, RHS, DAG, dl); + EVT VT = OpLHS.getValueType(); + + switch (OpNum) { + default: llvm_unreachable("Unknown shuffle opcode!"); + case OP_VREV: + return DAG.getNode(ARMISD::VREV64, dl, VT, OpLHS); + case OP_VDUP0: + case OP_VDUP1: + case OP_VDUP2: + case OP_VDUP3: + return DAG.getNode(ARMISD::VDUPLANE, dl, VT, + OpLHS, DAG.getConstant(OpNum-OP_VDUP0, MVT::i32)); + case OP_VEXT1: + case OP_VEXT2: + case OP_VEXT3: + return DAG.getNode(ARMISD::VEXT, dl, VT, + OpLHS, OpRHS, + DAG.getConstant(OpNum-OP_VEXT1+1, MVT::i32)); + case OP_VUZPL: + case OP_VUZPR: + return DAG.getNode(ARMISD::VUZP, dl, DAG.getVTList(VT, VT), + OpLHS, OpRHS).getValue(OpNum-OP_VUZPL); + case OP_VZIPL: + case OP_VZIPR: + return DAG.getNode(ARMISD::VZIP, dl, DAG.getVTList(VT, VT), + OpLHS, OpRHS).getValue(OpNum-OP_VZIPL); + case OP_VTRNL: + case OP_VTRNR: + return DAG.getNode(ARMISD::VTRN, dl, DAG.getVTList(VT, VT), + OpLHS, OpRHS).getValue(OpNum-OP_VTRNL); + } +} + +static SDValue LowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG) { + SDValue V1 = Op.getOperand(0); + SDValue V2 = Op.getOperand(1); + DebugLoc dl = Op.getDebugLoc(); + EVT VT = Op.getValueType(); + ShuffleVectorSDNode *SVN = cast(Op.getNode()); + SmallVector ShuffleMask; + + // Convert shuffles that are directly supported on NEON to target-specific + // DAG nodes, instead of keeping them as shuffles and matching them again + // during code selection. This is more efficient and avoids the possibility + // of inconsistencies between legalization and selection. + // FIXME: floating-point vectors should be canonicalized to integer vectors + // of the same time so that they get CSEd properly. + SVN->getMask(ShuffleMask); + + if (ShuffleVectorSDNode::isSplatMask(&ShuffleMask[0], VT)) { + int Lane = SVN->getSplatIndex(); + // If this is undef splat, generate it via "just" vdup, if possible. + if (Lane == -1) Lane = 0; + + if (Lane == 0 && V1.getOpcode() == ISD::SCALAR_TO_VECTOR) { + return DAG.getNode(ARMISD::VDUP, dl, VT, V1.getOperand(0)); + } + return DAG.getNode(ARMISD::VDUPLANE, dl, VT, V1, + DAG.getConstant(Lane, MVT::i32)); + } + + bool ReverseVEXT; + unsigned Imm; + if (isVEXTMask(ShuffleMask, VT, ReverseVEXT, Imm)) { + if (ReverseVEXT) + std::swap(V1, V2); + return DAG.getNode(ARMISD::VEXT, dl, VT, V1, V2, + DAG.getConstant(Imm, MVT::i32)); + } + + if (isVREVMask(ShuffleMask, VT, 64)) + return DAG.getNode(ARMISD::VREV64, dl, VT, V1); + if (isVREVMask(ShuffleMask, VT, 32)) + return DAG.getNode(ARMISD::VREV32, dl, VT, V1); + if (isVREVMask(ShuffleMask, VT, 16)) + return DAG.getNode(ARMISD::VREV16, dl, VT, V1); + + // Check for Neon shuffles that modify both input vectors in place. + // If both results are used, i.e., if there are two shuffles with the same + // source operands and with masks corresponding to both results of one of + // these operations, DAG memoization will ensure that a single node is + // used for both shuffles. + unsigned WhichResult; + if (isVTRNMask(ShuffleMask, VT, WhichResult)) + return DAG.getNode(ARMISD::VTRN, dl, DAG.getVTList(VT, VT), + V1, V2).getValue(WhichResult); + if (isVUZPMask(ShuffleMask, VT, WhichResult)) + return DAG.getNode(ARMISD::VUZP, dl, DAG.getVTList(VT, VT), + V1, V2).getValue(WhichResult); + if (isVZIPMask(ShuffleMask, VT, WhichResult)) + return DAG.getNode(ARMISD::VZIP, dl, DAG.getVTList(VT, VT), + V1, V2).getValue(WhichResult); + + // If the shuffle is not directly supported and it has 4 elements, use + // the PerfectShuffle-generated table to synthesize it from other shuffles. + if (VT.getVectorNumElements() == 4 && + (VT.is128BitVector() || VT.is64BitVector())) { + unsigned PFIndexes[4]; + for (unsigned i = 0; i != 4; ++i) { + if (ShuffleMask[i] < 0) + PFIndexes[i] = 8; + else + PFIndexes[i] = ShuffleMask[i]; + } + + // Compute the index in the perfect shuffle table. + unsigned PFTableIndex = + PFIndexes[0]*9*9*9+PFIndexes[1]*9*9+PFIndexes[2]*9+PFIndexes[3]; + + unsigned PFEntry = PerfectShuffleTable[PFTableIndex]; + unsigned Cost = (PFEntry >> 30); + + if (Cost <= 4) + return GeneratePerfectShuffle(PFEntry, V1, V2, DAG, dl); + } + + return SDValue(); +} + +static SDValue LowerEXTRACT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) { + EVT VT = Op.getValueType(); + DebugLoc dl = Op.getDebugLoc(); + SDValue Vec = Op.getOperand(0); + SDValue Lane = Op.getOperand(1); + assert(VT == MVT::i32 && + Vec.getValueType().getVectorElementType().getSizeInBits() < 32 && + "unexpected type for custom-lowering vector extract"); + return DAG.getNode(ARMISD::VGETLANEu, dl, MVT::i32, Vec, Lane); +} + +static SDValue LowerCONCAT_VECTORS(SDValue Op, SelectionDAG &DAG) { + // The only time a CONCAT_VECTORS operation can have legal types is when + // two 64-bit vectors are concatenated to a 128-bit vector. + assert(Op.getValueType().is128BitVector() && Op.getNumOperands() == 2 && + "unexpected CONCAT_VECTORS"); + DebugLoc dl = Op.getDebugLoc(); + SDValue Val = DAG.getUNDEF(MVT::v2f64); + SDValue Op0 = Op.getOperand(0); + SDValue Op1 = Op.getOperand(1); + if (Op0.getOpcode() != ISD::UNDEF) + Val = DAG.getNode(ISD::INSERT_VECTOR_ELT, dl, MVT::v2f64, Val, + DAG.getNode(ISD::BIT_CONVERT, dl, MVT::f64, Op0), + DAG.getIntPtrConstant(0)); + if (Op1.getOpcode() != ISD::UNDEF) + Val = DAG.getNode(ISD::INSERT_VECTOR_ELT, dl, MVT::v2f64, Val, + DAG.getNode(ISD::BIT_CONVERT, dl, MVT::f64, Op1), + DAG.getIntPtrConstant(1)); + return DAG.getNode(ISD::BIT_CONVERT, dl, Op.getValueType(), Val); +} + +SDValue ARMTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) { + switch (Op.getOpcode()) { + default: llvm_unreachable("Don't know how to custom lower this!"); + case ISD::ConstantPool: return LowerConstantPool(Op, DAG); + case ISD::BlockAddress: return LowerBlockAddress(Op, DAG); + case ISD::GlobalAddress: + return Subtarget->isTargetDarwin() ? LowerGlobalAddressDarwin(Op, DAG) : + LowerGlobalAddressELF(Op, DAG); + case ISD::GlobalTLSAddress: return LowerGlobalTLSAddress(Op, DAG); + case ISD::SELECT_CC: return LowerSELECT_CC(Op, DAG); + case ISD::BR_CC: return LowerBR_CC(Op, DAG); + case ISD::BR_JT: return LowerBR_JT(Op, DAG); + case ISD::DYNAMIC_STACKALLOC: return LowerDYNAMIC_STACKALLOC(Op, DAG); + case ISD::VASTART: return LowerVASTART(Op, DAG, VarArgsFrameIndex); + case ISD::SINT_TO_FP: + case ISD::UINT_TO_FP: return LowerINT_TO_FP(Op, DAG); + case ISD::FP_TO_SINT: + case ISD::FP_TO_UINT: return LowerFP_TO_INT(Op, DAG); + case ISD::FCOPYSIGN: return LowerFCOPYSIGN(Op, DAG); + case ISD::RETURNADDR: break; + case ISD::FRAMEADDR: return LowerFRAMEADDR(Op, DAG); + case ISD::GLOBAL_OFFSET_TABLE: return LowerGLOBAL_OFFSET_TABLE(Op, DAG); + case ISD::INTRINSIC_WO_CHAIN: return LowerINTRINSIC_WO_CHAIN(Op, DAG); + case ISD::BIT_CONVERT: return ExpandBIT_CONVERT(Op.getNode(), DAG); + case ISD::SHL: + case ISD::SRL: + case ISD::SRA: return LowerShift(Op.getNode(), DAG, Subtarget); + case ISD::SHL_PARTS: return LowerShiftLeftParts(Op, DAG); + case ISD::SRL_PARTS: + case ISD::SRA_PARTS: return LowerShiftRightParts(Op, DAG); + case ISD::VSETCC: return LowerVSETCC(Op, DAG); + case ISD::BUILD_VECTOR: return LowerBUILD_VECTOR(Op, DAG); + case ISD::VECTOR_SHUFFLE: return LowerVECTOR_SHUFFLE(Op, DAG); + case ISD::EXTRACT_VECTOR_ELT: return LowerEXTRACT_VECTOR_ELT(Op, DAG); + case ISD::CONCAT_VECTORS: return LowerCONCAT_VECTORS(Op, DAG); + } + return SDValue(); +} + +/// ReplaceNodeResults - Replace the results of node with an illegal result +/// type with new values built out of custom code. +void ARMTargetLowering::ReplaceNodeResults(SDNode *N, + SmallVectorImpl&Results, + SelectionDAG &DAG) { + switch (N->getOpcode()) { + default: + llvm_unreachable("Don't know how to custom expand this!"); + return; + case ISD::BIT_CONVERT: + Results.push_back(ExpandBIT_CONVERT(N, DAG)); + return; + case ISD::SRL: + case ISD::SRA: { + SDValue Res = LowerShift(N, DAG, Subtarget); + if (Res.getNode()) + Results.push_back(Res); + return; + } + } +} + +//===----------------------------------------------------------------------===// +// ARM Scheduler Hooks +//===----------------------------------------------------------------------===// + +MachineBasicBlock * +ARMTargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI, + MachineBasicBlock *BB, + DenseMap *EM) const { + const TargetInstrInfo *TII = getTargetMachine().getInstrInfo(); + DebugLoc dl = MI->getDebugLoc(); + switch (MI->getOpcode()) { + default: + llvm_unreachable("Unexpected instr type to insert"); + case ARM::tMOVCCr_pseudo: { + // To "insert" a SELECT_CC instruction, we actually have to insert the + // diamond control-flow pattern. The incoming instruction knows the + // destination vreg to set, the condition code register to branch on, the + // true/false values to select between, and a branch opcode to use. + const BasicBlock *LLVM_BB = BB->getBasicBlock(); + MachineFunction::iterator It = BB; + ++It; + + // thisMBB: + // ... + // TrueVal = ... + // cmpTY ccX, r1, r2 + // bCC copy1MBB + // fallthrough --> copy0MBB + MachineBasicBlock *thisMBB = BB; + MachineFunction *F = BB->getParent(); + MachineBasicBlock *copy0MBB = F->CreateMachineBasicBlock(LLVM_BB); + MachineBasicBlock *sinkMBB = F->CreateMachineBasicBlock(LLVM_BB); + BuildMI(BB, dl, TII->get(ARM::tBcc)).addMBB(sinkMBB) + .addImm(MI->getOperand(3).getImm()).addReg(MI->getOperand(4).getReg()); + F->insert(It, copy0MBB); + F->insert(It, sinkMBB); + // Update machine-CFG edges by first adding all successors of the current + // block to the new block which will contain the Phi node for the select. + // Also inform sdisel of the edge changes. + for (MachineBasicBlock::succ_iterator I = BB->succ_begin(), + E = BB->succ_end(); I != E; ++I) { + EM->insert(std::make_pair(*I, sinkMBB)); + sinkMBB->addSuccessor(*I); + } + // Next, remove all successors of the current block, and add the true + // and fallthrough blocks as its successors. + while (!BB->succ_empty()) + BB->removeSuccessor(BB->succ_begin()); + BB->addSuccessor(copy0MBB); + BB->addSuccessor(sinkMBB); + + // copy0MBB: + // %FalseValue = ... + // # fallthrough to sinkMBB + BB = copy0MBB; + + // Update machine-CFG edges + BB->addSuccessor(sinkMBB); + + // sinkMBB: + // %Result = phi [ %FalseValue, copy0MBB ], [ %TrueValue, thisMBB ] + // ... + BB = sinkMBB; + BuildMI(BB, dl, TII->get(ARM::PHI), MI->getOperand(0).getReg()) + .addReg(MI->getOperand(1).getReg()).addMBB(copy0MBB) + .addReg(MI->getOperand(2).getReg()).addMBB(thisMBB); + + F->DeleteMachineInstr(MI); // The pseudo instruction is gone now. + return BB; + } + + case ARM::tANDsp: + case ARM::tADDspr_: + case ARM::tSUBspi_: + case ARM::t2SUBrSPi_: + case ARM::t2SUBrSPi12_: + case ARM::t2SUBrSPs_: { + MachineFunction *MF = BB->getParent(); + unsigned DstReg = MI->getOperand(0).getReg(); + unsigned SrcReg = MI->getOperand(1).getReg(); + bool DstIsDead = MI->getOperand(0).isDead(); + bool SrcIsKill = MI->getOperand(1).isKill(); + + if (SrcReg != ARM::SP) { + // Copy the source to SP from virtual register. + const TargetRegisterClass *RC = MF->getRegInfo().getRegClass(SrcReg); + unsigned CopyOpc = (RC == ARM::tGPRRegisterClass) + ? ARM::tMOVtgpr2gpr : ARM::tMOVgpr2gpr; + BuildMI(BB, dl, TII->get(CopyOpc), ARM::SP) + .addReg(SrcReg, getKillRegState(SrcIsKill)); + } + + unsigned OpOpc = 0; + bool NeedPred = false, NeedCC = false, NeedOp3 = false; + switch (MI->getOpcode()) { + default: + llvm_unreachable("Unexpected pseudo instruction!"); + case ARM::tANDsp: + OpOpc = ARM::tAND; + NeedPred = true; + break; + case ARM::tADDspr_: + OpOpc = ARM::tADDspr; + break; + case ARM::tSUBspi_: + OpOpc = ARM::tSUBspi; + break; + case ARM::t2SUBrSPi_: + OpOpc = ARM::t2SUBrSPi; + NeedPred = true; NeedCC = true; + break; + case ARM::t2SUBrSPi12_: + OpOpc = ARM::t2SUBrSPi12; + NeedPred = true; + break; + case ARM::t2SUBrSPs_: + OpOpc = ARM::t2SUBrSPs; + NeedPred = true; NeedCC = true; NeedOp3 = true; + break; + } + MachineInstrBuilder MIB = BuildMI(BB, dl, TII->get(OpOpc), ARM::SP); + if (OpOpc == ARM::tAND) + AddDefaultT1CC(MIB); + MIB.addReg(ARM::SP); + MIB.addOperand(MI->getOperand(2)); + if (NeedOp3) + MIB.addOperand(MI->getOperand(3)); + if (NeedPred) + AddDefaultPred(MIB); + if (NeedCC) + AddDefaultCC(MIB); + + // Copy the result from SP to virtual register. + const TargetRegisterClass *RC = MF->getRegInfo().getRegClass(DstReg); + unsigned CopyOpc = (RC == ARM::tGPRRegisterClass) + ? ARM::tMOVgpr2tgpr : ARM::tMOVgpr2gpr; + BuildMI(BB, dl, TII->get(CopyOpc)) + .addReg(DstReg, getDefRegState(true) | getDeadRegState(DstIsDead)) + .addReg(ARM::SP); + MF->DeleteMachineInstr(MI); // The pseudo instruction is gone now. + return BB; + } + } +} + +//===----------------------------------------------------------------------===// +// ARM Optimization Hooks +//===----------------------------------------------------------------------===// + +static +SDValue combineSelectAndUse(SDNode *N, SDValue Slct, SDValue OtherOp, + TargetLowering::DAGCombinerInfo &DCI) { + SelectionDAG &DAG = DCI.DAG; + const TargetLowering &TLI = DAG.getTargetLoweringInfo(); + EVT VT = N->getValueType(0); + unsigned Opc = N->getOpcode(); + bool isSlctCC = Slct.getOpcode() == ISD::SELECT_CC; + SDValue LHS = isSlctCC ? Slct.getOperand(2) : Slct.getOperand(1); + SDValue RHS = isSlctCC ? Slct.getOperand(3) : Slct.getOperand(2); + ISD::CondCode CC = ISD::SETCC_INVALID; + + if (isSlctCC) { + CC = cast(Slct.getOperand(4))->get(); + } else { + SDValue CCOp = Slct.getOperand(0); + if (CCOp.getOpcode() == ISD::SETCC) + CC = cast(CCOp.getOperand(2))->get(); + } + + bool DoXform = false; + bool InvCC = false; + assert ((Opc == ISD::ADD || (Opc == ISD::SUB && Slct == N->getOperand(1))) && + "Bad input!"); + + if (LHS.getOpcode() == ISD::Constant && + cast(LHS)->isNullValue()) { + DoXform = true; + } else if (CC != ISD::SETCC_INVALID && + RHS.getOpcode() == ISD::Constant && + cast(RHS)->isNullValue()) { + std::swap(LHS, RHS); + SDValue Op0 = Slct.getOperand(0); + EVT OpVT = isSlctCC ? Op0.getValueType() : + Op0.getOperand(0).getValueType(); + bool isInt = OpVT.isInteger(); + CC = ISD::getSetCCInverse(CC, isInt); + + if (!TLI.isCondCodeLegal(CC, OpVT)) + return SDValue(); // Inverse operator isn't legal. + + DoXform = true; + InvCC = true; + } + + if (DoXform) { + SDValue Result = DAG.getNode(Opc, RHS.getDebugLoc(), VT, OtherOp, RHS); + if (isSlctCC) + return DAG.getSelectCC(N->getDebugLoc(), OtherOp, Result, + Slct.getOperand(0), Slct.getOperand(1), CC); + SDValue CCOp = Slct.getOperand(0); + if (InvCC) + CCOp = DAG.getSetCC(Slct.getDebugLoc(), CCOp.getValueType(), + CCOp.getOperand(0), CCOp.getOperand(1), CC); + return DAG.getNode(ISD::SELECT, N->getDebugLoc(), VT, + CCOp, OtherOp, Result); + } + return SDValue(); +} + +/// PerformADDCombine - Target-specific dag combine xforms for ISD::ADD. +static SDValue PerformADDCombine(SDNode *N, + TargetLowering::DAGCombinerInfo &DCI) { + // added by evan in r37685 with no testcase. + SDValue N0 = N->getOperand(0), N1 = N->getOperand(1); + + // fold (add (select cc, 0, c), x) -> (select cc, x, (add, x, c)) + if (N0.getOpcode() == ISD::SELECT && N0.getNode()->hasOneUse()) { + SDValue Result = combineSelectAndUse(N, N0, N1, DCI); + if (Result.getNode()) return Result; + } + if (N1.getOpcode() == ISD::SELECT && N1.getNode()->hasOneUse()) { + SDValue Result = combineSelectAndUse(N, N1, N0, DCI); + if (Result.getNode()) return Result; + } + + return SDValue(); +} + +/// PerformSUBCombine - Target-specific dag combine xforms for ISD::SUB. +static SDValue PerformSUBCombine(SDNode *N, + TargetLowering::DAGCombinerInfo &DCI) { + // added by evan in r37685 with no testcase. + SDValue N0 = N->getOperand(0), N1 = N->getOperand(1); + + // fold (sub x, (select cc, 0, c)) -> (select cc, x, (sub, x, c)) + if (N1.getOpcode() == ISD::SELECT && N1.getNode()->hasOneUse()) { + SDValue Result = combineSelectAndUse(N, N1, N0, DCI); + if (Result.getNode()) return Result; + } + + return SDValue(); +} + +/// PerformVMOVRRDCombine - Target-specific dag combine xforms for ARMISD::VMOVRRD. +static SDValue PerformVMOVRRDCombine(SDNode *N, + TargetLowering::DAGCombinerInfo &DCI) { + // fmrrd(fmdrr x, y) -> x,y + SDValue InDouble = N->getOperand(0); + if (InDouble.getOpcode() == ARMISD::VMOVDRR) + return DCI.CombineTo(N, InDouble.getOperand(0), InDouble.getOperand(1)); + return SDValue(); +} + +/// getVShiftImm - Check if this is a valid build_vector for the immediate +/// operand of a vector shift operation, where all the elements of the +/// build_vector must have the same constant integer value. +static bool getVShiftImm(SDValue Op, unsigned ElementBits, int64_t &Cnt) { + // Ignore bit_converts. + while (Op.getOpcode() == ISD::BIT_CONVERT) + Op = Op.getOperand(0); + BuildVectorSDNode *BVN = dyn_cast(Op.getNode()); + APInt SplatBits, SplatUndef; + unsigned SplatBitSize; + bool HasAnyUndefs; + if (! BVN || ! BVN->isConstantSplat(SplatBits, SplatUndef, SplatBitSize, + HasAnyUndefs, ElementBits) || + SplatBitSize > ElementBits) + return false; + Cnt = SplatBits.getSExtValue(); + return true; +} + +/// isVShiftLImm - Check if this is a valid build_vector for the immediate +/// operand of a vector shift left operation. That value must be in the range: +/// 0 <= Value < ElementBits for a left shift; or +/// 0 <= Value <= ElementBits for a long left shift. +static bool isVShiftLImm(SDValue Op, EVT VT, bool isLong, int64_t &Cnt) { + assert(VT.isVector() && "vector shift count is not a vector type"); + unsigned ElementBits = VT.getVectorElementType().getSizeInBits(); + if (! getVShiftImm(Op, ElementBits, Cnt)) + return false; + return (Cnt >= 0 && (isLong ? Cnt-1 : Cnt) < ElementBits); +} + +/// isVShiftRImm - Check if this is a valid build_vector for the immediate +/// operand of a vector shift right operation. For a shift opcode, the value +/// is positive, but for an intrinsic the value count must be negative. The +/// absolute value must be in the range: +/// 1 <= |Value| <= ElementBits for a right shift; or +/// 1 <= |Value| <= ElementBits/2 for a narrow right shift. +static bool isVShiftRImm(SDValue Op, EVT VT, bool isNarrow, bool isIntrinsic, + int64_t &Cnt) { + assert(VT.isVector() && "vector shift count is not a vector type"); + unsigned ElementBits = VT.getVectorElementType().getSizeInBits(); + if (! getVShiftImm(Op, ElementBits, Cnt)) + return false; + if (isIntrinsic) + Cnt = -Cnt; + return (Cnt >= 1 && Cnt <= (isNarrow ? ElementBits/2 : ElementBits)); +} + +/// PerformIntrinsicCombine - ARM-specific DAG combining for intrinsics. +static SDValue PerformIntrinsicCombine(SDNode *N, SelectionDAG &DAG) { + unsigned IntNo = cast(N->getOperand(0))->getZExtValue(); + switch (IntNo) { + default: + // Don't do anything for most intrinsics. + break; + + // Vector shifts: check for immediate versions and lower them. + // Note: This is done during DAG combining instead of DAG legalizing because + // the build_vectors for 64-bit vector element shift counts are generally + // not legal, and it is hard to see their values after they get legalized to + // loads from a constant pool. + case Intrinsic::arm_neon_vshifts: + case Intrinsic::arm_neon_vshiftu: + case Intrinsic::arm_neon_vshiftls: + case Intrinsic::arm_neon_vshiftlu: + case Intrinsic::arm_neon_vshiftn: + case Intrinsic::arm_neon_vrshifts: + case Intrinsic::arm_neon_vrshiftu: + case Intrinsic::arm_neon_vrshiftn: + case Intrinsic::arm_neon_vqshifts: + case Intrinsic::arm_neon_vqshiftu: + case Intrinsic::arm_neon_vqshiftsu: + case Intrinsic::arm_neon_vqshiftns: + case Intrinsic::arm_neon_vqshiftnu: + case Intrinsic::arm_neon_vqshiftnsu: + case Intrinsic::arm_neon_vqrshiftns: + case Intrinsic::arm_neon_vqrshiftnu: + case Intrinsic::arm_neon_vqrshiftnsu: { + EVT VT = N->getOperand(1).getValueType(); + int64_t Cnt; + unsigned VShiftOpc = 0; + + switch (IntNo) { + case Intrinsic::arm_neon_vshifts: + case Intrinsic::arm_neon_vshiftu: + if (isVShiftLImm(N->getOperand(2), VT, false, Cnt)) { + VShiftOpc = ARMISD::VSHL; + break; + } + if (isVShiftRImm(N->getOperand(2), VT, false, true, Cnt)) { + VShiftOpc = (IntNo == Intrinsic::arm_neon_vshifts ? + ARMISD::VSHRs : ARMISD::VSHRu); + break; + } + return SDValue(); + + case Intrinsic::arm_neon_vshiftls: + case Intrinsic::arm_neon_vshiftlu: + if (isVShiftLImm(N->getOperand(2), VT, true, Cnt)) + break; + llvm_unreachable("invalid shift count for vshll intrinsic"); + + case Intrinsic::arm_neon_vrshifts: + case Intrinsic::arm_neon_vrshiftu: + if (isVShiftRImm(N->getOperand(2), VT, false, true, Cnt)) + break; + return SDValue(); + + case Intrinsic::arm_neon_vqshifts: + case Intrinsic::arm_neon_vqshiftu: + if (isVShiftLImm(N->getOperand(2), VT, false, Cnt)) + break; + return SDValue(); + + case Intrinsic::arm_neon_vqshiftsu: + if (isVShiftLImm(N->getOperand(2), VT, false, Cnt)) + break; + llvm_unreachable("invalid shift count for vqshlu intrinsic"); + + case Intrinsic::arm_neon_vshiftn: + case Intrinsic::arm_neon_vrshiftn: + case Intrinsic::arm_neon_vqshiftns: + case Intrinsic::arm_neon_vqshiftnu: + case Intrinsic::arm_neon_vqshiftnsu: + case Intrinsic::arm_neon_vqrshiftns: + case Intrinsic::arm_neon_vqrshiftnu: + case Intrinsic::arm_neon_vqrshiftnsu: + // Narrowing shifts require an immediate right shift. + if (isVShiftRImm(N->getOperand(2), VT, true, true, Cnt)) + break; + llvm_unreachable("invalid shift count for narrowing vector shift intrinsic"); + + default: + llvm_unreachable("unhandled vector shift"); + } + + switch (IntNo) { + case Intrinsic::arm_neon_vshifts: + case Intrinsic::arm_neon_vshiftu: + // Opcode already set above. + break; + case Intrinsic::arm_neon_vshiftls: + case Intrinsic::arm_neon_vshiftlu: + if (Cnt == VT.getVectorElementType().getSizeInBits()) + VShiftOpc = ARMISD::VSHLLi; + else + VShiftOpc = (IntNo == Intrinsic::arm_neon_vshiftls ? + ARMISD::VSHLLs : ARMISD::VSHLLu); + break; + case Intrinsic::arm_neon_vshiftn: + VShiftOpc = ARMISD::VSHRN; break; + case Intrinsic::arm_neon_vrshifts: + VShiftOpc = ARMISD::VRSHRs; break; + case Intrinsic::arm_neon_vrshiftu: + VShiftOpc = ARMISD::VRSHRu; break; + case Intrinsic::arm_neon_vrshiftn: + VShiftOpc = ARMISD::VRSHRN; break; + case Intrinsic::arm_neon_vqshifts: + VShiftOpc = ARMISD::VQSHLs; break; + case Intrinsic::arm_neon_vqshiftu: + VShiftOpc = ARMISD::VQSHLu; break; + case Intrinsic::arm_neon_vqshiftsu: + VShiftOpc = ARMISD::VQSHLsu; break; + case Intrinsic::arm_neon_vqshiftns: + VShiftOpc = ARMISD::VQSHRNs; break; + case Intrinsic::arm_neon_vqshiftnu: + VShiftOpc = ARMISD::VQSHRNu; break; + case Intrinsic::arm_neon_vqshiftnsu: + VShiftOpc = ARMISD::VQSHRNsu; break; + case Intrinsic::arm_neon_vqrshiftns: + VShiftOpc = ARMISD::VQRSHRNs; break; + case Intrinsic::arm_neon_vqrshiftnu: + VShiftOpc = ARMISD::VQRSHRNu; break; + case Intrinsic::arm_neon_vqrshiftnsu: + VShiftOpc = ARMISD::VQRSHRNsu; break; + } + + return DAG.getNode(VShiftOpc, N->getDebugLoc(), N->getValueType(0), + N->getOperand(1), DAG.getConstant(Cnt, MVT::i32)); + } + + case Intrinsic::arm_neon_vshiftins: { + EVT VT = N->getOperand(1).getValueType(); + int64_t Cnt; + unsigned VShiftOpc = 0; + + if (isVShiftLImm(N->getOperand(3), VT, false, Cnt)) + VShiftOpc = ARMISD::VSLI; + else if (isVShiftRImm(N->getOperand(3), VT, false, true, Cnt)) + VShiftOpc = ARMISD::VSRI; + else { + llvm_unreachable("invalid shift count for vsli/vsri intrinsic"); + } + + return DAG.getNode(VShiftOpc, N->getDebugLoc(), N->getValueType(0), + N->getOperand(1), N->getOperand(2), + DAG.getConstant(Cnt, MVT::i32)); + } + + case Intrinsic::arm_neon_vqrshifts: + case Intrinsic::arm_neon_vqrshiftu: + // No immediate versions of these to check for. + break; + } + + return SDValue(); +} + +/// PerformShiftCombine - Checks for immediate versions of vector shifts and +/// lowers them. As with the vector shift intrinsics, this is done during DAG +/// combining instead of DAG legalizing because the build_vectors for 64-bit +/// vector element shift counts are generally not legal, and it is hard to see +/// their values after they get legalized to loads from a constant pool. +static SDValue PerformShiftCombine(SDNode *N, SelectionDAG &DAG, + const ARMSubtarget *ST) { + EVT VT = N->getValueType(0); + + // Nothing to be done for scalar shifts. + if (! VT.isVector()) + return SDValue(); + + assert(ST->hasNEON() && "unexpected vector shift"); + int64_t Cnt; + + switch (N->getOpcode()) { + default: llvm_unreachable("unexpected shift opcode"); + + case ISD::SHL: + if (isVShiftLImm(N->getOperand(1), VT, false, Cnt)) + return DAG.getNode(ARMISD::VSHL, N->getDebugLoc(), VT, N->getOperand(0), + DAG.getConstant(Cnt, MVT::i32)); + break; + + case ISD::SRA: + case ISD::SRL: + if (isVShiftRImm(N->getOperand(1), VT, false, false, Cnt)) { + unsigned VShiftOpc = (N->getOpcode() == ISD::SRA ? + ARMISD::VSHRs : ARMISD::VSHRu); + return DAG.getNode(VShiftOpc, N->getDebugLoc(), VT, N->getOperand(0), + DAG.getConstant(Cnt, MVT::i32)); + } + } + return SDValue(); +} + +/// PerformExtendCombine - Target-specific DAG combining for ISD::SIGN_EXTEND, +/// ISD::ZERO_EXTEND, and ISD::ANY_EXTEND. +static SDValue PerformExtendCombine(SDNode *N, SelectionDAG &DAG, + const ARMSubtarget *ST) { + SDValue N0 = N->getOperand(0); + + // Check for sign- and zero-extensions of vector extract operations of 8- + // and 16-bit vector elements. NEON supports these directly. They are + // handled during DAG combining because type legalization will promote them + // to 32-bit types and it is messy to recognize the operations after that. + if (ST->hasNEON() && N0.getOpcode() == ISD::EXTRACT_VECTOR_ELT) { + SDValue Vec = N0.getOperand(0); + SDValue Lane = N0.getOperand(1); + EVT VT = N->getValueType(0); + EVT EltVT = N0.getValueType(); + const TargetLowering &TLI = DAG.getTargetLoweringInfo(); + + if (VT == MVT::i32 && + (EltVT == MVT::i8 || EltVT == MVT::i16) && + TLI.isTypeLegal(Vec.getValueType())) { + + unsigned Opc = 0; + switch (N->getOpcode()) { + default: llvm_unreachable("unexpected opcode"); + case ISD::SIGN_EXTEND: + Opc = ARMISD::VGETLANEs; + break; + case ISD::ZERO_EXTEND: + case ISD::ANY_EXTEND: + Opc = ARMISD::VGETLANEu; + break; + } + return DAG.getNode(Opc, N->getDebugLoc(), VT, Vec, Lane); + } + } + + return SDValue(); +} + +SDValue ARMTargetLowering::PerformDAGCombine(SDNode *N, + DAGCombinerInfo &DCI) const { + switch (N->getOpcode()) { + default: break; + case ISD::ADD: return PerformADDCombine(N, DCI); + case ISD::SUB: return PerformSUBCombine(N, DCI); + case ARMISD::VMOVRRD: return PerformVMOVRRDCombine(N, DCI); + case ISD::INTRINSIC_WO_CHAIN: + return PerformIntrinsicCombine(N, DCI.DAG); + case ISD::SHL: + case ISD::SRA: + case ISD::SRL: + return PerformShiftCombine(N, DCI.DAG, Subtarget); + case ISD::SIGN_EXTEND: + case ISD::ZERO_EXTEND: + case ISD::ANY_EXTEND: + return PerformExtendCombine(N, DCI.DAG, Subtarget); + } + return SDValue(); +} + +bool ARMTargetLowering::allowsUnalignedMemoryAccesses(EVT VT) const { + if (!Subtarget->hasV6Ops()) + // Pre-v6 does not support unaligned mem access. + return false; + else if (!Subtarget->hasV6Ops()) { + // v6 may or may not support unaligned mem access. + if (!Subtarget->isTargetDarwin()) + return false; + } + + switch (VT.getSimpleVT().SimpleTy) { + default: + return false; + case MVT::i8: + case MVT::i16: + case MVT::i32: + return true; + // FIXME: VLD1 etc with standard alignment is legal. + } +} + +static bool isLegalT1AddressImmediate(int64_t V, EVT VT) { + if (V < 0) + return false; + + unsigned Scale = 1; + switch (VT.getSimpleVT().SimpleTy) { + default: return false; + case MVT::i1: + case MVT::i8: + // Scale == 1; + break; + case MVT::i16: + // Scale == 2; + Scale = 2; + break; + case MVT::i32: + // Scale == 4; + Scale = 4; + break; + } + + if ((V & (Scale - 1)) != 0) + return false; + V /= Scale; + return V == (V & ((1LL << 5) - 1)); +} + +static bool isLegalT2AddressImmediate(int64_t V, EVT VT, + const ARMSubtarget *Subtarget) { + bool isNeg = false; + if (V < 0) { + isNeg = true; + V = - V; + } + + switch (VT.getSimpleVT().SimpleTy) { + default: return false; + case MVT::i1: + case MVT::i8: + case MVT::i16: + case MVT::i32: + // + imm12 or - imm8 + if (isNeg) + return V == (V & ((1LL << 8) - 1)); + return V == (V & ((1LL << 12) - 1)); + case MVT::f32: + case MVT::f64: + // Same as ARM mode. FIXME: NEON? + if (!Subtarget->hasVFP2()) + return false; + if ((V & 3) != 0) + return false; + V >>= 2; + return V == (V & ((1LL << 8) - 1)); + } +} + +/// isLegalAddressImmediate - Return true if the integer value can be used +/// as the offset of the target addressing mode for load / store of the +/// given type. +static bool isLegalAddressImmediate(int64_t V, EVT VT, + const ARMSubtarget *Subtarget) { + if (V == 0) + return true; + + if (!VT.isSimple()) + return false; + + if (Subtarget->isThumb1Only()) + return isLegalT1AddressImmediate(V, VT); + else if (Subtarget->isThumb2()) + return isLegalT2AddressImmediate(V, VT, Subtarget); + + // ARM mode. + if (V < 0) + V = - V; + switch (VT.getSimpleVT().SimpleTy) { + default: return false; + case MVT::i1: + case MVT::i8: + case MVT::i32: + // +- imm12 + return V == (V & ((1LL << 12) - 1)); + case MVT::i16: + // +- imm8 + return V == (V & ((1LL << 8) - 1)); + case MVT::f32: + case MVT::f64: + if (!Subtarget->hasVFP2()) // FIXME: NEON? + return false; + if ((V & 3) != 0) + return false; + V >>= 2; + return V == (V & ((1LL << 8) - 1)); + } +} + +bool ARMTargetLowering::isLegalT2ScaledAddressingMode(const AddrMode &AM, + EVT VT) const { + int Scale = AM.Scale; + if (Scale < 0) + return false; + + switch (VT.getSimpleVT().SimpleTy) { + default: return false; + case MVT::i1: + case MVT::i8: + case MVT::i16: + case MVT::i32: + if (Scale == 1) + return true; + // r + r << imm + Scale = Scale & ~1; + return Scale == 2 || Scale == 4 || Scale == 8; + case MVT::i64: + // r + r + if (((unsigned)AM.HasBaseReg + Scale) <= 2) + return true; + return false; + case MVT::isVoid: + // Note, we allow "void" uses (basically, uses that aren't loads or + // stores), because arm allows folding a scale into many arithmetic + // operations. This should be made more precise and revisited later. + + // Allow r << imm, but the imm has to be a multiple of two. + if (Scale & 1) return false; + return isPowerOf2_32(Scale); + } +} + +/// isLegalAddressingMode - Return true if the addressing mode represented +/// by AM is legal for this target, for a load/store of the specified type. +bool ARMTargetLowering::isLegalAddressingMode(const AddrMode &AM, + const Type *Ty) const { + EVT VT = getValueType(Ty, true); + if (!isLegalAddressImmediate(AM.BaseOffs, VT, Subtarget)) + return false; + + // Can never fold addr of global into load/store. + if (AM.BaseGV) + return false; + + switch (AM.Scale) { + case 0: // no scale reg, must be "r+i" or "r", or "i". + break; + case 1: + if (Subtarget->isThumb1Only()) + return false; + // FALL THROUGH. + default: + // ARM doesn't support any R+R*scale+imm addr modes. + if (AM.BaseOffs) + return false; + + if (!VT.isSimple()) + return false; + + if (Subtarget->isThumb2()) + return isLegalT2ScaledAddressingMode(AM, VT); + + int Scale = AM.Scale; + switch (VT.getSimpleVT().SimpleTy) { + default: return false; + case MVT::i1: + case MVT::i8: + case MVT::i32: + if (Scale < 0) Scale = -Scale; + if (Scale == 1) + return true; + // r + r << imm + return isPowerOf2_32(Scale & ~1); + case MVT::i16: + case MVT::i64: + // r + r + if (((unsigned)AM.HasBaseReg + Scale) <= 2) + return true; + return false; + + case MVT::isVoid: + // Note, we allow "void" uses (basically, uses that aren't loads or + // stores), because arm allows folding a scale into many arithmetic + // operations. This should be made more precise and revisited later. + + // Allow r << imm, but the imm has to be a multiple of two. + if (Scale & 1) return false; + return isPowerOf2_32(Scale); + } + break; + } + return true; +} + +/// isLegalICmpImmediate - Return true if the specified immediate is legal +/// icmp immediate, that is the target has icmp instructions which can compare +/// a register against the immediate without having to materialize the +/// immediate into a register. +bool ARMTargetLowering::isLegalICmpImmediate(int64_t Imm) const { + if (!Subtarget->isThumb()) + return ARM_AM::getSOImmVal(Imm) != -1; + if (Subtarget->isThumb2()) + return ARM_AM::getT2SOImmVal(Imm) != -1; + return Imm >= 0 && Imm <= 255; +} + +static bool getARMIndexedAddressParts(SDNode *Ptr, EVT VT, + bool isSEXTLoad, SDValue &Base, + SDValue &Offset, bool &isInc, + SelectionDAG &DAG) { + if (Ptr->getOpcode() != ISD::ADD && Ptr->getOpcode() != ISD::SUB) + return false; + + if (VT == MVT::i16 || ((VT == MVT::i8 || VT == MVT::i1) && isSEXTLoad)) { + // AddressingMode 3 + Base = Ptr->getOperand(0); + if (ConstantSDNode *RHS = dyn_cast(Ptr->getOperand(1))) { + int RHSC = (int)RHS->getZExtValue(); + if (RHSC < 0 && RHSC > -256) { + assert(Ptr->getOpcode() == ISD::ADD); + isInc = false; + Offset = DAG.getConstant(-RHSC, RHS->getValueType(0)); + return true; + } + } + isInc = (Ptr->getOpcode() == ISD::ADD); + Offset = Ptr->getOperand(1); + return true; + } else if (VT == MVT::i32 || VT == MVT::i8 || VT == MVT::i1) { + // AddressingMode 2 + if (ConstantSDNode *RHS = dyn_cast(Ptr->getOperand(1))) { + int RHSC = (int)RHS->getZExtValue(); + if (RHSC < 0 && RHSC > -0x1000) { + assert(Ptr->getOpcode() == ISD::ADD); + isInc = false; + Offset = DAG.getConstant(-RHSC, RHS->getValueType(0)); + Base = Ptr->getOperand(0); + return true; + } + } + + if (Ptr->getOpcode() == ISD::ADD) { + isInc = true; + ARM_AM::ShiftOpc ShOpcVal= ARM_AM::getShiftOpcForNode(Ptr->getOperand(0)); + if (ShOpcVal != ARM_AM::no_shift) { + Base = Ptr->getOperand(1); + Offset = Ptr->getOperand(0); + } else { + Base = Ptr->getOperand(0); + Offset = Ptr->getOperand(1); + } + return true; + } + + isInc = (Ptr->getOpcode() == ISD::ADD); + Base = Ptr->getOperand(0); + Offset = Ptr->getOperand(1); + return true; + } + + // FIXME: Use VLDM / VSTM to emulate indexed FP load / store. + return false; +} + +static bool getT2IndexedAddressParts(SDNode *Ptr, EVT VT, + bool isSEXTLoad, SDValue &Base, + SDValue &Offset, bool &isInc, + SelectionDAG &DAG) { + if (Ptr->getOpcode() != ISD::ADD && Ptr->getOpcode() != ISD::SUB) + return false; + + Base = Ptr->getOperand(0); + if (ConstantSDNode *RHS = dyn_cast(Ptr->getOperand(1))) { + int RHSC = (int)RHS->getZExtValue(); + if (RHSC < 0 && RHSC > -0x100) { // 8 bits. + assert(Ptr->getOpcode() == ISD::ADD); + isInc = false; + Offset = DAG.getConstant(-RHSC, RHS->getValueType(0)); + return true; + } else if (RHSC > 0 && RHSC < 0x100) { // 8 bit, no zero. + isInc = Ptr->getOpcode() == ISD::ADD; + Offset = DAG.getConstant(RHSC, RHS->getValueType(0)); + return true; + } + } + + return false; +} + +/// getPreIndexedAddressParts - returns true by value, base pointer and +/// offset pointer and addressing mode by reference if the node's address +/// can be legally represented as pre-indexed load / store address. +bool +ARMTargetLowering::getPreIndexedAddressParts(SDNode *N, SDValue &Base, + SDValue &Offset, + ISD::MemIndexedMode &AM, + SelectionDAG &DAG) const { + if (Subtarget->isThumb1Only()) + return false; + + EVT VT; + SDValue Ptr; + bool isSEXTLoad = false; + if (LoadSDNode *LD = dyn_cast(N)) { + Ptr = LD->getBasePtr(); + VT = LD->getMemoryVT(); + isSEXTLoad = LD->getExtensionType() == ISD::SEXTLOAD; + } else if (StoreSDNode *ST = dyn_cast(N)) { + Ptr = ST->getBasePtr(); + VT = ST->getMemoryVT(); + } else + return false; + + bool isInc; + bool isLegal = false; + if (Subtarget->isThumb2()) + isLegal = getT2IndexedAddressParts(Ptr.getNode(), VT, isSEXTLoad, Base, + Offset, isInc, DAG); + else + isLegal = getARMIndexedAddressParts(Ptr.getNode(), VT, isSEXTLoad, Base, + Offset, isInc, DAG); + if (!isLegal) + return false; + + AM = isInc ? ISD::PRE_INC : ISD::PRE_DEC; + return true; +} + +/// getPostIndexedAddressParts - returns true by value, base pointer and +/// offset pointer and addressing mode by reference if this node can be +/// combined with a load / store to form a post-indexed load / store. +bool ARMTargetLowering::getPostIndexedAddressParts(SDNode *N, SDNode *Op, + SDValue &Base, + SDValue &Offset, + ISD::MemIndexedMode &AM, + SelectionDAG &DAG) const { + if (Subtarget->isThumb1Only()) + return false; + + EVT VT; + SDValue Ptr; + bool isSEXTLoad = false; + if (LoadSDNode *LD = dyn_cast(N)) { + VT = LD->getMemoryVT(); + isSEXTLoad = LD->getExtensionType() == ISD::SEXTLOAD; + } else if (StoreSDNode *ST = dyn_cast(N)) { + VT = ST->getMemoryVT(); + } else + return false; + + bool isInc; + bool isLegal = false; + if (Subtarget->isThumb2()) + isLegal = getT2IndexedAddressParts(Op, VT, isSEXTLoad, Base, Offset, + isInc, DAG); + else + isLegal = getARMIndexedAddressParts(Op, VT, isSEXTLoad, Base, Offset, + isInc, DAG); + if (!isLegal) + return false; + + AM = isInc ? ISD::POST_INC : ISD::POST_DEC; + return true; +} + +void ARMTargetLowering::computeMaskedBitsForTargetNode(const SDValue Op, + const APInt &Mask, + APInt &KnownZero, + APInt &KnownOne, + const SelectionDAG &DAG, + unsigned Depth) const { + KnownZero = KnownOne = APInt(Mask.getBitWidth(), 0); + switch (Op.getOpcode()) { + default: break; + case ARMISD::CMOV: { + // Bits are known zero/one if known on the LHS and RHS. + DAG.ComputeMaskedBits(Op.getOperand(0), Mask, KnownZero, KnownOne, Depth+1); + if (KnownZero == 0 && KnownOne == 0) return; + + APInt KnownZeroRHS, KnownOneRHS; + DAG.ComputeMaskedBits(Op.getOperand(1), Mask, + KnownZeroRHS, KnownOneRHS, Depth+1); + KnownZero &= KnownZeroRHS; + KnownOne &= KnownOneRHS; + return; + } + } +} + +//===----------------------------------------------------------------------===// +// ARM Inline Assembly Support +//===----------------------------------------------------------------------===// + +/// getConstraintType - Given a constraint letter, return the type of +/// constraint it is for this target. +ARMTargetLowering::ConstraintType +ARMTargetLowering::getConstraintType(const std::string &Constraint) const { + if (Constraint.size() == 1) { + switch (Constraint[0]) { + default: break; + case 'l': return C_RegisterClass; + case 'w': return C_RegisterClass; + } + } + return TargetLowering::getConstraintType(Constraint); +} + +std::pair +ARMTargetLowering::getRegForInlineAsmConstraint(const std::string &Constraint, + EVT VT) const { + if (Constraint.size() == 1) { + // GCC RS6000 Constraint Letters + switch (Constraint[0]) { + case 'l': + if (Subtarget->isThumb1Only()) + return std::make_pair(0U, ARM::tGPRRegisterClass); + else + return std::make_pair(0U, ARM::GPRRegisterClass); + case 'r': + return std::make_pair(0U, ARM::GPRRegisterClass); + case 'w': + if (VT == MVT::f32) + return std::make_pair(0U, ARM::SPRRegisterClass); + if (VT == MVT::f64) + return std::make_pair(0U, ARM::DPRRegisterClass); + break; + } + } + return TargetLowering::getRegForInlineAsmConstraint(Constraint, VT); +} + +std::vector ARMTargetLowering:: +getRegClassForInlineAsmConstraint(const std::string &Constraint, + EVT VT) const { + if (Constraint.size() != 1) + return std::vector(); + + switch (Constraint[0]) { // GCC ARM Constraint Letters + default: break; + case 'l': + return make_vector(ARM::R0, ARM::R1, ARM::R2, ARM::R3, + ARM::R4, ARM::R5, ARM::R6, ARM::R7, + 0); + case 'r': + return make_vector(ARM::R0, ARM::R1, ARM::R2, ARM::R3, + ARM::R4, ARM::R5, ARM::R6, ARM::R7, + ARM::R8, ARM::R9, ARM::R10, ARM::R11, + ARM::R12, ARM::LR, 0); + case 'w': + if (VT == MVT::f32) + return make_vector(ARM::S0, ARM::S1, ARM::S2, ARM::S3, + ARM::S4, ARM::S5, ARM::S6, ARM::S7, + ARM::S8, ARM::S9, ARM::S10, ARM::S11, + ARM::S12,ARM::S13,ARM::S14,ARM::S15, + ARM::S16,ARM::S17,ARM::S18,ARM::S19, + ARM::S20,ARM::S21,ARM::S22,ARM::S23, + ARM::S24,ARM::S25,ARM::S26,ARM::S27, + ARM::S28,ARM::S29,ARM::S30,ARM::S31, 0); + if (VT == MVT::f64) + return make_vector(ARM::D0, ARM::D1, ARM::D2, ARM::D3, + ARM::D4, ARM::D5, ARM::D6, ARM::D7, + ARM::D8, ARM::D9, ARM::D10,ARM::D11, + ARM::D12,ARM::D13,ARM::D14,ARM::D15, 0); + break; + } + + return std::vector(); +} + +/// LowerAsmOperandForConstraint - Lower the specified operand into the Ops +/// vector. If it is invalid, don't add anything to Ops. +void ARMTargetLowering::LowerAsmOperandForConstraint(SDValue Op, + char Constraint, + bool hasMemory, + std::vector&Ops, + SelectionDAG &DAG) const { + SDValue Result(0, 0); + + switch (Constraint) { + default: break; + case 'I': case 'J': case 'K': case 'L': + case 'M': case 'N': case 'O': + ConstantSDNode *C = dyn_cast(Op); + if (!C) + return; + + int64_t CVal64 = C->getSExtValue(); + int CVal = (int) CVal64; + // None of these constraints allow values larger than 32 bits. Check + // that the value fits in an int. + if (CVal != CVal64) + return; + + switch (Constraint) { + case 'I': + if (Subtarget->isThumb1Only()) { + // This must be a constant between 0 and 255, for ADD + // immediates. + if (CVal >= 0 && CVal <= 255) + break; + } else if (Subtarget->isThumb2()) { + // A constant that can be used as an immediate value in a + // data-processing instruction. + if (ARM_AM::getT2SOImmVal(CVal) != -1) + break; + } else { + // A constant that can be used as an immediate value in a + // data-processing instruction. + if (ARM_AM::getSOImmVal(CVal) != -1) + break; + } + return; + + case 'J': + if (Subtarget->isThumb()) { // FIXME thumb2 + // This must be a constant between -255 and -1, for negated ADD + // immediates. This can be used in GCC with an "n" modifier that + // prints the negated value, for use with SUB instructions. It is + // not useful otherwise but is implemented for compatibility. + if (CVal >= -255 && CVal <= -1) + break; + } else { + // This must be a constant between -4095 and 4095. It is not clear + // what this constraint is intended for. Implemented for + // compatibility with GCC. + if (CVal >= -4095 && CVal <= 4095) + break; + } + return; + + case 'K': + if (Subtarget->isThumb1Only()) { + // A 32-bit value where only one byte has a nonzero value. Exclude + // zero to match GCC. This constraint is used by GCC internally for + // constants that can be loaded with a move/shift combination. + // It is not useful otherwise but is implemented for compatibility. + if (CVal != 0 && ARM_AM::isThumbImmShiftedVal(CVal)) + break; + } else if (Subtarget->isThumb2()) { + // A constant whose bitwise inverse can be used as an immediate + // value in a data-processing instruction. This can be used in GCC + // with a "B" modifier that prints the inverted value, for use with + // BIC and MVN instructions. It is not useful otherwise but is + // implemented for compatibility. + if (ARM_AM::getT2SOImmVal(~CVal) != -1) + break; + } else { + // A constant whose bitwise inverse can be used as an immediate + // value in a data-processing instruction. This can be used in GCC + // with a "B" modifier that prints the inverted value, for use with + // BIC and MVN instructions. It is not useful otherwise but is + // implemented for compatibility. + if (ARM_AM::getSOImmVal(~CVal) != -1) + break; + } + return; + + case 'L': + if (Subtarget->isThumb1Only()) { + // This must be a constant between -7 and 7, + // for 3-operand ADD/SUB immediate instructions. + if (CVal >= -7 && CVal < 7) + break; + } else if (Subtarget->isThumb2()) { + // A constant whose negation can be used as an immediate value in a + // data-processing instruction. This can be used in GCC with an "n" + // modifier that prints the negated value, for use with SUB + // instructions. It is not useful otherwise but is implemented for + // compatibility. + if (ARM_AM::getT2SOImmVal(-CVal) != -1) + break; + } else { + // A constant whose negation can be used as an immediate value in a + // data-processing instruction. This can be used in GCC with an "n" + // modifier that prints the negated value, for use with SUB + // instructions. It is not useful otherwise but is implemented for + // compatibility. + if (ARM_AM::getSOImmVal(-CVal) != -1) + break; + } + return; + + case 'M': + if (Subtarget->isThumb()) { // FIXME thumb2 + // This must be a multiple of 4 between 0 and 1020, for + // ADD sp + immediate. + if ((CVal >= 0 && CVal <= 1020) && ((CVal & 3) == 0)) + break; + } else { + // A power of two or a constant between 0 and 32. This is used in + // GCC for the shift amount on shifted register operands, but it is + // useful in general for any shift amounts. + if ((CVal >= 0 && CVal <= 32) || ((CVal & (CVal - 1)) == 0)) + break; + } + return; + + case 'N': + if (Subtarget->isThumb()) { // FIXME thumb2 + // This must be a constant between 0 and 31, for shift amounts. + if (CVal >= 0 && CVal <= 31) + break; + } + return; + + case 'O': + if (Subtarget->isThumb()) { // FIXME thumb2 + // This must be a multiple of 4 between -508 and 508, for + // ADD/SUB sp = sp + immediate. + if ((CVal >= -508 && CVal <= 508) && ((CVal & 3) == 0)) + break; + } + return; + } + Result = DAG.getTargetConstant(CVal, Op.getValueType()); + break; + } + + if (Result.getNode()) { + Ops.push_back(Result); + return; + } + return TargetLowering::LowerAsmOperandForConstraint(Op, Constraint, hasMemory, + Ops, DAG); +} + +bool +ARMTargetLowering::isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const { + // The ARM target isn't yet aware of offsets. + return false; +} + +int ARM::getVFPf32Imm(const APFloat &FPImm) { + APInt Imm = FPImm.bitcastToAPInt(); + uint32_t Sign = Imm.lshr(31).getZExtValue() & 1; + int32_t Exp = (Imm.lshr(23).getSExtValue() & 0xff) - 127; // -126 to 127 + int64_t Mantissa = Imm.getZExtValue() & 0x7fffff; // 23 bits + + // We can handle 4 bits of mantissa. + // mantissa = (16+UInt(e:f:g:h))/16. + if (Mantissa & 0x7ffff) + return -1; + Mantissa >>= 19; + if ((Mantissa & 0xf) != Mantissa) + return -1; + + // We can handle 3 bits of exponent: exp == UInt(NOT(b):c:d)-3 + if (Exp < -3 || Exp > 4) + return -1; + Exp = ((Exp+3) & 0x7) ^ 4; + + return ((int)Sign << 7) | (Exp << 4) | Mantissa; +} + +int ARM::getVFPf64Imm(const APFloat &FPImm) { + APInt Imm = FPImm.bitcastToAPInt(); + uint64_t Sign = Imm.lshr(63).getZExtValue() & 1; + int64_t Exp = (Imm.lshr(52).getSExtValue() & 0x7ff) - 1023; // -1022 to 1023 + uint64_t Mantissa = Imm.getZExtValue() & 0xfffffffffffffLL; + + // We can handle 4 bits of mantissa. + // mantissa = (16+UInt(e:f:g:h))/16. + if (Mantissa & 0xffffffffffffLL) + return -1; + Mantissa >>= 48; + if ((Mantissa & 0xf) != Mantissa) + return -1; + + // We can handle 3 bits of exponent: exp == UInt(NOT(b):c:d)-3 + if (Exp < -3 || Exp > 4) + return -1; + Exp = ((Exp+3) & 0x7) ^ 4; + + return ((int)Sign << 7) | (Exp << 4) | Mantissa; +} + +/// isFPImmLegal - Returns true if the target can instruction select the +/// specified FP immediate natively. If false, the legalizer will +/// materialize the FP immediate as a load from a constant pool. +bool ARMTargetLowering::isFPImmLegal(const APFloat &Imm, EVT VT) const { + if (!Subtarget->hasVFP3()) + return false; + if (VT == MVT::f32) + return ARM::getVFPf32Imm(Imm) != -1; + if (VT == MVT::f64) + return ARM::getVFPf64Imm(Imm) != -1; + return false; +} diff --git a/libclamav/c++/llvm/lib/Target/ARM/ARMISelLowering.h b/libclamav/c++/llvm/lib/Target/ARM/ARMISelLowering.h new file mode 100644 index 000000000..4f31f8a8b --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/ARM/ARMISelLowering.h @@ -0,0 +1,334 @@ +//===-- ARMISelLowering.h - ARM DAG Lowering Interface ----------*- 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 the interfaces that ARM uses to lower LLVM code into a +// selection DAG. +// +//===----------------------------------------------------------------------===// + +#ifndef ARMISELLOWERING_H +#define ARMISELLOWERING_H + +#include "ARMSubtarget.h" +#include "llvm/Target/TargetLowering.h" +#include "llvm/CodeGen/SelectionDAG.h" +#include "llvm/CodeGen/CallingConvLower.h" +#include + +namespace llvm { + class ARMConstantPoolValue; + + namespace ARMISD { + // ARM Specific DAG Nodes + enum NodeType { + // Start the numbering where the builtin ops and target ops leave off. + FIRST_NUMBER = ISD::BUILTIN_OP_END, + + Wrapper, // Wrapper - A wrapper node for TargetConstantPool, + // TargetExternalSymbol, and TargetGlobalAddress. + WrapperJT, // WrapperJT - A wrapper node for TargetJumpTable + + CALL, // Function call. + CALL_PRED, // Function call that's predicable. + CALL_NOLINK, // Function call with branch not branch-and-link. + tCALL, // Thumb function call. + BRCOND, // Conditional branch. + BR_JT, // Jumptable branch. + BR2_JT, // Jumptable branch (2 level - jumptable entry is a jump). + RET_FLAG, // Return with a flag operand. + + PIC_ADD, // Add with a PC operand and a PIC label. + + CMP, // ARM compare instructions. + CMPZ, // ARM compare that sets only Z flag. + CMPFP, // ARM VFP compare instruction, sets FPSCR. + CMPFPw0, // ARM VFP compare against zero instruction, sets FPSCR. + FMSTAT, // ARM fmstat instruction. + CMOV, // ARM conditional move instructions. + CNEG, // ARM conditional negate instructions. + + FTOSI, // FP to sint within a FP register. + FTOUI, // FP to uint within a FP register. + SITOF, // sint to FP within a FP register. + UITOF, // uint to FP within a FP register. + + SRL_FLAG, // V,Flag = srl_flag X -> srl X, 1 + save carry out. + SRA_FLAG, // V,Flag = sra_flag X -> sra X, 1 + save carry out. + RRX, // V = RRX X, Flag -> srl X, 1 + shift in carry flag. + + VMOVRRD, // double to two gprs. + VMOVDRR, // Two gprs to double. + + EH_SJLJ_SETJMP, // SjLj exception handling setjmp. + EH_SJLJ_LONGJMP, // SjLj exception handling longjmp. + + THREAD_POINTER, + + DYN_ALLOC, // Dynamic allocation on the stack. + + VCEQ, // Vector compare equal. + VCGE, // Vector compare greater than or equal. + VCGEU, // Vector compare unsigned greater than or equal. + VCGT, // Vector compare greater than. + VCGTU, // Vector compare unsigned greater than. + VTST, // Vector test bits. + + // Vector shift by immediate: + VSHL, // ...left + VSHRs, // ...right (signed) + VSHRu, // ...right (unsigned) + VSHLLs, // ...left long (signed) + VSHLLu, // ...left long (unsigned) + VSHLLi, // ...left long (with maximum shift count) + VSHRN, // ...right narrow + + // Vector rounding shift by immediate: + VRSHRs, // ...right (signed) + VRSHRu, // ...right (unsigned) + VRSHRN, // ...right narrow + + // Vector saturating shift by immediate: + VQSHLs, // ...left (signed) + VQSHLu, // ...left (unsigned) + VQSHLsu, // ...left (signed to unsigned) + VQSHRNs, // ...right narrow (signed) + VQSHRNu, // ...right narrow (unsigned) + VQSHRNsu, // ...right narrow (signed to unsigned) + + // Vector saturating rounding shift by immediate: + VQRSHRNs, // ...right narrow (signed) + VQRSHRNu, // ...right narrow (unsigned) + VQRSHRNsu, // ...right narrow (signed to unsigned) + + // Vector shift and insert: + VSLI, // ...left + VSRI, // ...right + + // Vector get lane (VMOV scalar to ARM core register) + // (These are used for 8- and 16-bit element types only.) + VGETLANEu, // zero-extend vector extract element + VGETLANEs, // sign-extend vector extract element + + // Vector duplicate: + VDUP, + VDUPLANE, + + // Vector shuffles: + VEXT, // extract + VREV64, // reverse elements within 64-bit doublewords + VREV32, // reverse elements within 32-bit words + VREV16, // reverse elements within 16-bit halfwords + VZIP, // zip (interleave) + VUZP, // unzip (deinterleave) + VTRN // transpose + }; + } + + /// Define some predicates that are used for node matching. + namespace ARM { + /// getVMOVImm - If this is a build_vector of constants which can be + /// formed by using a VMOV instruction of the specified element size, + /// return the constant being splatted. The ByteSize field indicates the + /// number of bytes of each element [1248]. + SDValue getVMOVImm(SDNode *N, unsigned ByteSize, SelectionDAG &DAG); + + /// getVFPf32Imm / getVFPf64Imm - If the given fp immediate can be + /// materialized with a VMOV.f32 / VMOV.f64 (i.e. fconsts / fconstd) + /// instruction, returns its 8-bit integer representation. Otherwise, + /// returns -1. + int getVFPf32Imm(const APFloat &FPImm); + int getVFPf64Imm(const APFloat &FPImm); + } + + //===--------------------------------------------------------------------===// + // ARMTargetLowering - ARM Implementation of the TargetLowering interface + + class ARMTargetLowering : public TargetLowering { + int VarArgsFrameIndex; // FrameIndex for start of varargs area. + public: + explicit ARMTargetLowering(TargetMachine &TM); + + virtual SDValue LowerOperation(SDValue Op, SelectionDAG &DAG); + + /// ReplaceNodeResults - Replace the results of node with an illegal result + /// type with new values built out of custom code. + /// + virtual void ReplaceNodeResults(SDNode *N, SmallVectorImpl&Results, + SelectionDAG &DAG); + + virtual SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const; + + virtual const char *getTargetNodeName(unsigned Opcode) const; + + virtual MachineBasicBlock *EmitInstrWithCustomInserter(MachineInstr *MI, + MachineBasicBlock *MBB, + DenseMap*) const; + + /// allowsUnalignedMemoryAccesses - Returns true if the target allows + /// unaligned memory accesses. of the specified type. + /// FIXME: Add getOptimalMemOpType to implement memcpy with NEON? + virtual bool allowsUnalignedMemoryAccesses(EVT VT) const; + + /// isLegalAddressingMode - Return true if the addressing mode represented + /// by AM is legal for this target, for a load/store of the specified type. + virtual bool isLegalAddressingMode(const AddrMode &AM, const Type *Ty)const; + bool isLegalT2ScaledAddressingMode(const AddrMode &AM, EVT VT) const; + + /// isLegalICmpImmediate - Return true if the specified immediate is legal + /// icmp immediate, that is the target has icmp instructions which can compare + /// a register against the immediate without having to materialize the + /// immediate into a register. + virtual bool isLegalICmpImmediate(int64_t Imm) const; + + /// getPreIndexedAddressParts - returns true by value, base pointer and + /// offset pointer and addressing mode by reference if the node's address + /// can be legally represented as pre-indexed load / store address. + virtual bool getPreIndexedAddressParts(SDNode *N, SDValue &Base, + SDValue &Offset, + ISD::MemIndexedMode &AM, + SelectionDAG &DAG) const; + + /// getPostIndexedAddressParts - returns true by value, base pointer and + /// offset pointer and addressing mode by reference if this node can be + /// combined with a load / store to form a post-indexed load / store. + virtual bool getPostIndexedAddressParts(SDNode *N, SDNode *Op, + SDValue &Base, SDValue &Offset, + ISD::MemIndexedMode &AM, + SelectionDAG &DAG) const; + + virtual void computeMaskedBitsForTargetNode(const SDValue Op, + const APInt &Mask, + APInt &KnownZero, + APInt &KnownOne, + const SelectionDAG &DAG, + unsigned Depth) const; + + + ConstraintType getConstraintType(const std::string &Constraint) const; + std::pair + getRegForInlineAsmConstraint(const std::string &Constraint, + EVT VT) const; + std::vector + getRegClassForInlineAsmConstraint(const std::string &Constraint, + EVT VT) const; + + /// LowerAsmOperandForConstraint - Lower the specified operand into the Ops + /// vector. If it is invalid, don't add anything to Ops. If hasMemory is + /// true it means one of the asm constraint of the inline asm instruction + /// being processed is 'm'. + virtual void LowerAsmOperandForConstraint(SDValue Op, + char ConstraintLetter, + bool hasMemory, + std::vector &Ops, + SelectionDAG &DAG) const; + + virtual const ARMSubtarget* getSubtarget() { + return Subtarget; + } + + /// getFunctionAlignment - Return the Log2 alignment of this function. + virtual unsigned getFunctionAlignment(const Function *F) const; + + bool isShuffleMaskLegal(const SmallVectorImpl &M, EVT VT) const; + bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const; + + /// isFPImmLegal - Returns true if the target can instruction select the + /// specified FP immediate natively. If false, the legalizer will + /// materialize the FP immediate as a load from a constant pool. + virtual bool isFPImmLegal(const APFloat &Imm, EVT VT) const; + + private: + /// Subtarget - Keep a pointer to the ARMSubtarget around so that we can + /// make the right decision when generating code for different targets. + const ARMSubtarget *Subtarget; + + /// ARMPCLabelIndex - Keep track of the number of ARM PC labels created. + /// + unsigned ARMPCLabelIndex; + + void addTypeForNEON(EVT VT, EVT PromotedLdStVT, EVT PromotedBitwiseVT); + void addDRTypeForNEON(EVT VT); + void addQRTypeForNEON(EVT VT); + + typedef SmallVector, 8> RegsToPassVector; + void PassF64ArgInRegs(DebugLoc dl, SelectionDAG &DAG, + SDValue Chain, SDValue &Arg, + RegsToPassVector &RegsToPass, + CCValAssign &VA, CCValAssign &NextVA, + SDValue &StackPtr, + SmallVector &MemOpChains, + ISD::ArgFlagsTy Flags); + SDValue GetF64FormalArgument(CCValAssign &VA, CCValAssign &NextVA, + SDValue &Root, SelectionDAG &DAG, DebugLoc dl); + + CCAssignFn *CCAssignFnForNode(CallingConv::ID CC, bool Return, bool isVarArg) const; + SDValue LowerMemOpCallTo(SDValue Chain, SDValue StackPtr, SDValue Arg, + DebugLoc dl, SelectionDAG &DAG, + const CCValAssign &VA, + ISD::ArgFlagsTy Flags); + SDValue LowerINTRINSIC_W_CHAIN(SDValue Op, SelectionDAG &DAG); + SDValue LowerINTRINSIC_WO_CHAIN(SDValue Op, SelectionDAG &DAG); + SDValue LowerBlockAddress(SDValue Op, SelectionDAG &DAG); + SDValue LowerGlobalAddressDarwin(SDValue Op, SelectionDAG &DAG); + SDValue LowerGlobalAddressELF(SDValue Op, SelectionDAG &DAG); + SDValue LowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG); + SDValue LowerToTLSGeneralDynamicModel(GlobalAddressSDNode *GA, + SelectionDAG &DAG); + SDValue LowerToTLSExecModels(GlobalAddressSDNode *GA, + SelectionDAG &DAG); + SDValue LowerGLOBAL_OFFSET_TABLE(SDValue Op, SelectionDAG &DAG); + SDValue LowerBR_JT(SDValue Op, SelectionDAG &DAG); + SDValue LowerSELECT_CC(SDValue Op, SelectionDAG &DAG); + SDValue LowerBR_CC(SDValue Op, SelectionDAG &DAG); + SDValue LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG); + SDValue LowerDYNAMIC_STACKALLOC(SDValue Op, SelectionDAG &DAG); + SDValue LowerShiftRightParts(SDValue Op, SelectionDAG &DAG); + SDValue LowerShiftLeftParts(SDValue Op, SelectionDAG &DAG); + + SDValue EmitTargetCodeForMemcpy(SelectionDAG &DAG, DebugLoc dl, + SDValue Chain, + SDValue Dst, SDValue Src, + SDValue Size, unsigned Align, + bool AlwaysInline, + const Value *DstSV, uint64_t DstSVOff, + const Value *SrcSV, uint64_t SrcSVOff); + SDValue LowerCallResult(SDValue Chain, SDValue InFlag, + CallingConv::ID CallConv, bool isVarArg, + const SmallVectorImpl &Ins, + DebugLoc dl, SelectionDAG &DAG, + SmallVectorImpl &InVals); + + virtual SDValue + LowerFormalArguments(SDValue Chain, + CallingConv::ID CallConv, bool isVarArg, + const SmallVectorImpl &Ins, + DebugLoc dl, SelectionDAG &DAG, + SmallVectorImpl &InVals); + + virtual SDValue + LowerCall(SDValue Chain, SDValue Callee, + CallingConv::ID CallConv, bool isVarArg, + bool isTailCall, + const SmallVectorImpl &Outs, + const SmallVectorImpl &Ins, + DebugLoc dl, SelectionDAG &DAG, + SmallVectorImpl &InVals); + + virtual SDValue + LowerReturn(SDValue Chain, + CallingConv::ID CallConv, bool isVarArg, + const SmallVectorImpl &Outs, + DebugLoc dl, SelectionDAG &DAG); + + SDValue getARMCmp(SDValue LHS, SDValue RHS, ISD::CondCode CC, + SDValue &ARMCC, SelectionDAG &DAG, DebugLoc dl); + }; +} + +#endif // ARMISELLOWERING_H diff --git a/libclamav/c++/llvm/lib/Target/ARM/ARMInstrFormats.td b/libclamav/c++/llvm/lib/Target/ARM/ARMInstrFormats.td new file mode 100644 index 000000000..e76e93cf6 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/ARM/ARMInstrFormats.td @@ -0,0 +1,1403 @@ +//===- ARMInstrFormats.td - ARM Instruction Formats --*- tablegen -*---------=// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// +// ARM Instruction Format Definitions. +// + +// Format specifies the encoding used by the instruction. This is part of the +// ad-hoc solution used to emit machine instruction encodings by our machine +// code emitter. +class Format val> { + bits<5> Value = val; +} + +def Pseudo : Format<0>; +def MulFrm : Format<1>; +def BrFrm : Format<2>; +def BrMiscFrm : Format<3>; + +def DPFrm : Format<4>; +def DPSoRegFrm : Format<5>; + +def LdFrm : Format<6>; +def StFrm : Format<7>; +def LdMiscFrm : Format<8>; +def StMiscFrm : Format<9>; +def LdStMulFrm : Format<10>; + +def ArithMiscFrm : Format<11>; +def ExtFrm : Format<12>; + +def VFPUnaryFrm : Format<13>; +def VFPBinaryFrm : Format<14>; +def VFPConv1Frm : Format<15>; +def VFPConv2Frm : Format<16>; +def VFPConv3Frm : Format<17>; +def VFPConv4Frm : Format<18>; +def VFPConv5Frm : Format<19>; +def VFPLdStFrm : Format<20>; +def VFPLdStMulFrm : Format<21>; +def VFPMiscFrm : Format<22>; + +def ThumbFrm : Format<23>; + +def NEONFrm : Format<24>; +def NEONGetLnFrm : Format<25>; +def NEONSetLnFrm : Format<26>; +def NEONDupFrm : Format<27>; + +// Misc flags. + +// the instruction has a Rn register operand. +// UnaryDP - Indicates this is a unary data processing instruction, i.e. +// it doesn't have a Rn operand. +class UnaryDP { bit isUnaryDataProc = 1; } + +// Xform16Bit - Indicates this Thumb2 instruction may be transformed into +// a 16-bit Thumb instruction if certain conditions are met. +class Xform16Bit { bit canXformTo16Bit = 1; } + +//===----------------------------------------------------------------------===// +// ARM Instruction flags. These need to match ARMInstrInfo.h. +// + +// Addressing mode. +class AddrMode val> { + bits<4> Value = val; +} +def AddrModeNone : AddrMode<0>; +def AddrMode1 : AddrMode<1>; +def AddrMode2 : AddrMode<2>; +def AddrMode3 : AddrMode<3>; +def AddrMode4 : AddrMode<4>; +def AddrMode5 : AddrMode<5>; +def AddrMode6 : AddrMode<6>; +def AddrModeT1_1 : AddrMode<7>; +def AddrModeT1_2 : AddrMode<8>; +def AddrModeT1_4 : AddrMode<9>; +def AddrModeT1_s : AddrMode<10>; +def AddrModeT2_i12: AddrMode<11>; +def AddrModeT2_i8 : AddrMode<12>; +def AddrModeT2_so : AddrMode<13>; +def AddrModeT2_pc : AddrMode<14>; +def AddrModeT2_i8s4 : AddrMode<15>; + +// Instruction size. +class SizeFlagVal val> { + bits<3> Value = val; +} +def SizeInvalid : SizeFlagVal<0>; // Unset. +def SizeSpecial : SizeFlagVal<1>; // Pseudo or special. +def Size8Bytes : SizeFlagVal<2>; +def Size4Bytes : SizeFlagVal<3>; +def Size2Bytes : SizeFlagVal<4>; + +// Load / store index mode. +class IndexMode val> { + bits<2> Value = val; +} +def IndexModeNone : IndexMode<0>; +def IndexModePre : IndexMode<1>; +def IndexModePost : IndexMode<2>; + +// Instruction execution domain. +class Domain val> { + bits<2> Value = val; +} +def GenericDomain : Domain<0>; +def VFPDomain : Domain<1>; // Instructions in VFP domain only +def NeonDomain : Domain<2>; // Instructions in Neon domain only +def VFPNeonDomain : Domain<3>; // Instructions in both VFP & Neon domains + +//===----------------------------------------------------------------------===// + +// ARM special operands. +// + +// ARM Predicate operand. Default to 14 = always (AL). Second part is CC +// register whose default is 0 (no register). +def pred : PredicateOperand { + let PrintMethod = "printPredicateOperand"; +} + +// Conditional code result for instructions whose 's' bit is set, e.g. subs. +def cc_out : OptionalDefOperand { + let PrintMethod = "printSBitModifierOperand"; +} + +// Same as cc_out except it defaults to setting CPSR. +def s_cc_out : OptionalDefOperand { + let PrintMethod = "printSBitModifierOperand"; +} + +//===----------------------------------------------------------------------===// + +// ARM Instruction templates. +// + +class InstARM + : Instruction { + field bits<32> Inst; + + let Namespace = "ARM"; + + // TSFlagsFields + AddrMode AM = am; + bits<4> AddrModeBits = AM.Value; + + SizeFlagVal SZ = sz; + bits<3> SizeFlag = SZ.Value; + + IndexMode IM = im; + bits<2> IndexModeBits = IM.Value; + + Format F = f; + bits<5> Form = F.Value; + + Domain D = d; + bits<2> Dom = D.Value; + + // + // Attributes specific to ARM instructions... + // + bit isUnaryDataProc = 0; + bit canXformTo16Bit = 0; + + let Constraints = cstr; + let Itinerary = itin; +} + +class PseudoInst pattern> + : InstARM { + let OutOperandList = oops; + let InOperandList = iops; + let AsmString = asm; + let Pattern = pattern; +} + +// Almost all ARM instructions are predicable. +class I pattern> + : InstARM { + let OutOperandList = oops; + let InOperandList = !con(iops, (ops pred:$p)); + let AsmString = !strconcat(opc, !strconcat("${p}", asm)); + let Pattern = pattern; + list Predicates = [IsARM]; +} + +// Same as I except it can optionally modify CPSR. Note it's modeled as +// an input operand since by default it's a zero register. It will +// become an implicit def once it's "flipped". +class sI pattern> + : InstARM { + let OutOperandList = oops; + let InOperandList = !con(iops, (ops pred:$p, cc_out:$s)); + let AsmString = !strconcat(opc, !strconcat("${p}${s}", asm)); + let Pattern = pattern; + list Predicates = [IsARM]; +} + +// Special cases +class XI pattern> + : InstARM { + let OutOperandList = oops; + let InOperandList = iops; + let AsmString = asm; + let Pattern = pattern; + list Predicates = [IsARM]; +} + +class AI pattern> + : I; +class AsI pattern> + : sI; +class AXI pattern> + : XI; + +// Ctrl flow instructions +class ABI opcod, dag oops, dag iops, InstrItinClass itin, + string opc, string asm, list pattern> + : I { + let Inst{27-24} = opcod; +} +class ABXI opcod, dag oops, dag iops, InstrItinClass itin, + string asm, list pattern> + : XI { + let Inst{27-24} = opcod; +} +class ABXIx2 pattern> + : XI; + +// BR_JT instructions +class JTI pattern> + : XI; + +// addrmode1 instructions +class AI1 opcod, dag oops, dag iops, Format f, InstrItinClass itin, + string opc, string asm, list pattern> + : I { + let Inst{24-21} = opcod; + let Inst{27-26} = {0,0}; +} +class AsI1 opcod, dag oops, dag iops, Format f, InstrItinClass itin, + string opc, string asm, list pattern> + : sI { + let Inst{24-21} = opcod; + let Inst{27-26} = {0,0}; +} +class AXI1 opcod, dag oops, dag iops, Format f, InstrItinClass itin, + string asm, list pattern> + : XI { + let Inst{24-21} = opcod; + let Inst{27-26} = {0,0}; +} +class AI1x2 pattern> + : I; + + +// addrmode2 loads and stores +class AI2 pattern> + : I { + let Inst{27-26} = {0,1}; +} + +// loads +class AI2ldw pattern> + : I { + let Inst{20} = 1; // L bit + let Inst{21} = 0; // W bit + let Inst{22} = 0; // B bit + let Inst{24} = 1; // P bit + let Inst{27-26} = {0,1}; +} +class AXI2ldw pattern> + : XI { + let Inst{20} = 1; // L bit + let Inst{21} = 0; // W bit + let Inst{22} = 0; // B bit + let Inst{24} = 1; // P bit + let Inst{27-26} = {0,1}; +} +class AI2ldb pattern> + : I { + let Inst{20} = 1; // L bit + let Inst{21} = 0; // W bit + let Inst{22} = 1; // B bit + let Inst{24} = 1; // P bit + let Inst{27-26} = {0,1}; +} +class AXI2ldb pattern> + : XI { + let Inst{20} = 1; // L bit + let Inst{21} = 0; // W bit + let Inst{22} = 1; // B bit + let Inst{24} = 1; // P bit + let Inst{27-26} = {0,1}; +} + +// stores +class AI2stw pattern> + : I { + let Inst{20} = 0; // L bit + let Inst{21} = 0; // W bit + let Inst{22} = 0; // B bit + let Inst{24} = 1; // P bit + let Inst{27-26} = {0,1}; +} +class AXI2stw pattern> + : XI { + let Inst{20} = 0; // L bit + let Inst{21} = 0; // W bit + let Inst{22} = 0; // B bit + let Inst{24} = 1; // P bit + let Inst{27-26} = {0,1}; +} +class AI2stb pattern> + : I { + let Inst{20} = 0; // L bit + let Inst{21} = 0; // W bit + let Inst{22} = 1; // B bit + let Inst{24} = 1; // P bit + let Inst{27-26} = {0,1}; +} +class AXI2stb pattern> + : XI { + let Inst{20} = 0; // L bit + let Inst{21} = 0; // W bit + let Inst{22} = 1; // B bit + let Inst{24} = 1; // P bit + let Inst{27-26} = {0,1}; +} + +// Pre-indexed loads +class AI2ldwpr pattern> + : I { + let Inst{20} = 1; // L bit + let Inst{21} = 1; // W bit + let Inst{22} = 0; // B bit + let Inst{24} = 1; // P bit + let Inst{27-26} = {0,1}; +} +class AI2ldbpr pattern> + : I { + let Inst{20} = 1; // L bit + let Inst{21} = 1; // W bit + let Inst{22} = 1; // B bit + let Inst{24} = 1; // P bit + let Inst{27-26} = {0,1}; +} + +// Pre-indexed stores +class AI2stwpr pattern> + : I { + let Inst{20} = 0; // L bit + let Inst{21} = 1; // W bit + let Inst{22} = 0; // B bit + let Inst{24} = 1; // P bit + let Inst{27-26} = {0,1}; +} +class AI2stbpr pattern> + : I { + let Inst{20} = 0; // L bit + let Inst{21} = 1; // W bit + let Inst{22} = 1; // B bit + let Inst{24} = 1; // P bit + let Inst{27-26} = {0,1}; +} + +// Post-indexed loads +class AI2ldwpo pattern> + : I { + let Inst{20} = 1; // L bit + let Inst{21} = 0; // W bit + let Inst{22} = 0; // B bit + let Inst{24} = 0; // P bit + let Inst{27-26} = {0,1}; +} +class AI2ldbpo pattern> + : I { + let Inst{20} = 1; // L bit + let Inst{21} = 0; // W bit + let Inst{22} = 1; // B bit + let Inst{24} = 0; // P bit + let Inst{27-26} = {0,1}; +} + +// Post-indexed stores +class AI2stwpo pattern> + : I { + let Inst{20} = 0; // L bit + let Inst{21} = 0; // W bit + let Inst{22} = 0; // B bit + let Inst{24} = 0; // P bit + let Inst{27-26} = {0,1}; +} +class AI2stbpo pattern> + : I { + let Inst{20} = 0; // L bit + let Inst{21} = 0; // W bit + let Inst{22} = 1; // B bit + let Inst{24} = 0; // P bit + let Inst{27-26} = {0,1}; +} + +// addrmode3 instructions +class AI3 pattern> + : I; +class AXI3 pattern> + : XI; + +// loads +class AI3ldh pattern> + : I { + let Inst{4} = 1; + let Inst{5} = 1; // H bit + let Inst{6} = 0; // S bit + let Inst{7} = 1; + let Inst{20} = 1; // L bit + let Inst{21} = 0; // W bit + let Inst{24} = 1; // P bit + let Inst{27-25} = 0b000; +} +class AXI3ldh pattern> + : XI { + let Inst{4} = 1; + let Inst{5} = 1; // H bit + let Inst{6} = 0; // S bit + let Inst{7} = 1; + let Inst{20} = 1; // L bit + let Inst{21} = 0; // W bit + let Inst{24} = 1; // P bit +} +class AI3ldsh pattern> + : I { + let Inst{4} = 1; + let Inst{5} = 1; // H bit + let Inst{6} = 1; // S bit + let Inst{7} = 1; + let Inst{20} = 1; // L bit + let Inst{21} = 0; // W bit + let Inst{24} = 1; // P bit + let Inst{27-25} = 0b000; +} +class AXI3ldsh pattern> + : XI { + let Inst{4} = 1; + let Inst{5} = 1; // H bit + let Inst{6} = 1; // S bit + let Inst{7} = 1; + let Inst{20} = 1; // L bit + let Inst{21} = 0; // W bit + let Inst{24} = 1; // P bit +} +class AI3ldsb pattern> + : I { + let Inst{4} = 1; + let Inst{5} = 0; // H bit + let Inst{6} = 1; // S bit + let Inst{7} = 1; + let Inst{20} = 1; // L bit + let Inst{21} = 0; // W bit + let Inst{24} = 1; // P bit + let Inst{27-25} = 0b000; +} +class AXI3ldsb pattern> + : XI { + let Inst{4} = 1; + let Inst{5} = 0; // H bit + let Inst{6} = 1; // S bit + let Inst{7} = 1; + let Inst{20} = 1; // L bit + let Inst{21} = 0; // W bit + let Inst{24} = 1; // P bit +} +class AI3ldd pattern> + : I { + let Inst{4} = 1; + let Inst{5} = 0; // H bit + let Inst{6} = 1; // S bit + let Inst{7} = 1; + let Inst{20} = 0; // L bit + let Inst{21} = 0; // W bit + let Inst{24} = 1; // P bit + let Inst{27-25} = 0b000; +} + +// stores +class AI3sth pattern> + : I { + let Inst{4} = 1; + let Inst{5} = 1; // H bit + let Inst{6} = 0; // S bit + let Inst{7} = 1; + let Inst{20} = 0; // L bit + let Inst{21} = 0; // W bit + let Inst{24} = 1; // P bit + let Inst{27-25} = 0b000; +} +class AXI3sth pattern> + : XI { + let Inst{4} = 1; + let Inst{5} = 1; // H bit + let Inst{6} = 0; // S bit + let Inst{7} = 1; + let Inst{20} = 0; // L bit + let Inst{21} = 0; // W bit + let Inst{24} = 1; // P bit +} +class AI3std pattern> + : I { + let Inst{4} = 1; + let Inst{5} = 1; // H bit + let Inst{6} = 1; // S bit + let Inst{7} = 1; + let Inst{20} = 0; // L bit + let Inst{21} = 0; // W bit + let Inst{24} = 1; // P bit + let Inst{27-25} = 0b000; +} + +// Pre-indexed loads +class AI3ldhpr pattern> + : I { + let Inst{4} = 1; + let Inst{5} = 1; // H bit + let Inst{6} = 0; // S bit + let Inst{7} = 1; + let Inst{20} = 1; // L bit + let Inst{21} = 1; // W bit + let Inst{24} = 1; // P bit + let Inst{27-25} = 0b000; +} +class AI3ldshpr pattern> + : I { + let Inst{4} = 1; + let Inst{5} = 1; // H bit + let Inst{6} = 1; // S bit + let Inst{7} = 1; + let Inst{20} = 1; // L bit + let Inst{21} = 1; // W bit + let Inst{24} = 1; // P bit + let Inst{27-25} = 0b000; +} +class AI3ldsbpr pattern> + : I { + let Inst{4} = 1; + let Inst{5} = 0; // H bit + let Inst{6} = 1; // S bit + let Inst{7} = 1; + let Inst{20} = 1; // L bit + let Inst{21} = 1; // W bit + let Inst{24} = 1; // P bit + let Inst{27-25} = 0b000; +} + +// Pre-indexed stores +class AI3sthpr pattern> + : I { + let Inst{4} = 1; + let Inst{5} = 1; // H bit + let Inst{6} = 0; // S bit + let Inst{7} = 1; + let Inst{20} = 0; // L bit + let Inst{21} = 1; // W bit + let Inst{24} = 1; // P bit + let Inst{27-25} = 0b000; +} + +// Post-indexed loads +class AI3ldhpo pattern> + : I { + let Inst{4} = 1; + let Inst{5} = 1; // H bit + let Inst{6} = 0; // S bit + let Inst{7} = 1; + let Inst{20} = 1; // L bit + let Inst{21} = 1; // W bit + let Inst{24} = 0; // P bit + let Inst{27-25} = 0b000; +} +class AI3ldshpo pattern> + : I { + let Inst{4} = 1; + let Inst{5} = 1; // H bit + let Inst{6} = 1; // S bit + let Inst{7} = 1; + let Inst{20} = 1; // L bit + let Inst{21} = 1; // W bit + let Inst{24} = 0; // P bit + let Inst{27-25} = 0b000; +} +class AI3ldsbpo pattern> + : I { + let Inst{4} = 1; + let Inst{5} = 0; // H bit + let Inst{6} = 1; // S bit + let Inst{7} = 1; + let Inst{20} = 1; // L bit + let Inst{21} = 1; // W bit + let Inst{24} = 0; // P bit + let Inst{27-25} = 0b000; +} + +// Post-indexed stores +class AI3sthpo pattern> + : I { + let Inst{4} = 1; + let Inst{5} = 1; // H bit + let Inst{6} = 0; // S bit + let Inst{7} = 1; + let Inst{20} = 0; // L bit + let Inst{21} = 1; // W bit + let Inst{24} = 0; // P bit + let Inst{27-25} = 0b000; +} + + +// addrmode4 instructions +class AXI4ld pattern> + : XI { + let Inst{20} = 1; // L bit + let Inst{22} = 0; // S bit + let Inst{27-25} = 0b100; +} +class AXI4st pattern> + : XI { + let Inst{20} = 0; // L bit + let Inst{22} = 0; // S bit + let Inst{27-25} = 0b100; +} + +// Unsigned multiply, multiply-accumulate instructions. +class AMul1I opcod, dag oops, dag iops, InstrItinClass itin, + string opc, string asm, list pattern> + : I { + let Inst{7-4} = 0b1001; + let Inst{20} = 0; // S bit + let Inst{27-21} = opcod; +} +class AsMul1I opcod, dag oops, dag iops, InstrItinClass itin, + string opc, string asm, list pattern> + : sI { + let Inst{7-4} = 0b1001; + let Inst{27-21} = opcod; +} + +// Most significant word multiply +class AMul2I opcod, dag oops, dag iops, InstrItinClass itin, + string opc, string asm, list pattern> + : I { + let Inst{7-4} = 0b1001; + let Inst{20} = 1; + let Inst{27-21} = opcod; +} + +// SMUL / SMULW / SMLA / SMLAW +class AMulxyI opcod, dag oops, dag iops, InstrItinClass itin, + string opc, string asm, list pattern> + : I { + let Inst{4} = 0; + let Inst{7} = 1; + let Inst{20} = 0; + let Inst{27-21} = opcod; +} + +// Extend instructions. +class AExtI opcod, dag oops, dag iops, InstrItinClass itin, + string opc, string asm, list pattern> + : I { + let Inst{7-4} = 0b0111; + let Inst{27-20} = opcod; +} + +// Misc Arithmetic instructions. +class AMiscA1I opcod, dag oops, dag iops, InstrItinClass itin, + string opc, string asm, list pattern> + : I { + let Inst{27-20} = opcod; +} + +//===----------------------------------------------------------------------===// + +// ARMPat - Same as Pat<>, but requires that the compiler be in ARM mode. +class ARMPat : Pat { + list Predicates = [IsARM]; +} +class ARMV5TEPat : Pat { + list Predicates = [IsARM, HasV5TE]; +} +class ARMV6Pat : Pat { + list Predicates = [IsARM, HasV6]; +} + +//===----------------------------------------------------------------------===// +// +// Thumb Instruction Format Definitions. +// + +// TI - Thumb instruction. + +class ThumbI pattern> + : InstARM { + let OutOperandList = oops; + let InOperandList = iops; + let AsmString = asm; + let Pattern = pattern; + list Predicates = [IsThumb]; +} + +class TI pattern> + : ThumbI; + +// Two-address instructions +class TIt pattern> + : ThumbI; + +// tBL, tBX instructions +class TIx2 pattern> + : ThumbI; + +// BR_JT instructions +class TJTI pattern> + : ThumbI; + +// Thumb1 only +class Thumb1I pattern> + : InstARM { + let OutOperandList = oops; + let InOperandList = iops; + let AsmString = asm; + let Pattern = pattern; + list Predicates = [IsThumb1Only]; +} + +class T1I pattern> + : Thumb1I; +class T1Ix2 pattern> + : Thumb1I; +class T1JTI pattern> + : Thumb1I; + +// Two-address instructions +class T1It pattern> + : Thumb1I; + +// Thumb1 instruction that can either be predicated or set CPSR. +class Thumb1sI pattern> + : InstARM { + let OutOperandList = !con(oops, (ops s_cc_out:$s)); + let InOperandList = !con(iops, (ops pred:$p)); + let AsmString = !strconcat(opc, !strconcat("${s}${p}", asm)); + let Pattern = pattern; + list Predicates = [IsThumb1Only]; +} + +class T1sI pattern> + : Thumb1sI; + +// Two-address instructions +class T1sIt pattern> + : Thumb1sI; + +// Thumb1 instruction that can be predicated. +class Thumb1pI pattern> + : InstARM { + let OutOperandList = oops; + let InOperandList = !con(iops, (ops pred:$p)); + let AsmString = !strconcat(opc, !strconcat("${p}", asm)); + let Pattern = pattern; + list Predicates = [IsThumb1Only]; +} + +class T1pI pattern> + : Thumb1pI; + +// Two-address instructions +class T1pIt pattern> + : Thumb1pI; + +class T1pI1 pattern> + : Thumb1pI; +class T1pI2 pattern> + : Thumb1pI; +class T1pI4 pattern> + : Thumb1pI; +class T1pIs pattern> + : Thumb1pI; + +// Thumb2I - Thumb2 instruction. Almost all Thumb2 instructions are predicable. +class Thumb2I pattern> + : InstARM { + let OutOperandList = oops; + let InOperandList = !con(iops, (ops pred:$p)); + let AsmString = !strconcat(opc, !strconcat("${p}", asm)); + let Pattern = pattern; + list Predicates = [IsThumb2]; +} + +// Same as Thumb2I except it can optionally modify CPSR. Note it's modeled as +// an input operand since by default it's a zero register. It will +// become an implicit def once it's "flipped". +// FIXME: This uses unified syntax so {s} comes before {p}. We should make it +// more consistent. +class Thumb2sI pattern> + : InstARM { + let OutOperandList = oops; + let InOperandList = !con(iops, (ops pred:$p, cc_out:$s)); + let AsmString = !strconcat(opc, !strconcat("${s}${p}", asm)); + let Pattern = pattern; + list Predicates = [IsThumb2]; +} + +// Special cases +class Thumb2XI pattern> + : InstARM { + let OutOperandList = oops; + let InOperandList = iops; + let AsmString = asm; + let Pattern = pattern; + list Predicates = [IsThumb2]; +} + +class T2I pattern> + : Thumb2I; +class T2Ii12 pattern> + : Thumb2I; +class T2Ii8 pattern> + : Thumb2I; +class T2Iso pattern> + : Thumb2I; +class T2Ipc pattern> + : Thumb2I; +class T2Ii8s4 pattern> + : Thumb2I; + +class T2sI pattern> + : Thumb2sI; + +class T2XI pattern> + : Thumb2XI; +class T2JTI pattern> + : Thumb2XI; + +class T2Ix2 pattern> + : Thumb2I; + + +// T2Iidxldst - Thumb2 indexed load / store instructions. +class T2Iidxldst pattern> + : InstARM { + let OutOperandList = oops; + let InOperandList = !con(iops, (ops pred:$p)); + let AsmString = !strconcat(opc, !strconcat("${p}", asm)); + let Pattern = pattern; + list Predicates = [IsThumb2]; +} + +// Tv5Pat - Same as Pat<>, but requires V5T Thumb mode. +class Tv5Pat : Pat { + list Predicates = [IsThumb1Only, HasV5T]; +} + +// T1Pat - Same as Pat<>, but requires that the compiler be in Thumb1 mode. +class T1Pat : Pat { + list Predicates = [IsThumb1Only]; +} + +// T2Pat - Same as Pat<>, but requires that the compiler be in Thumb2 mode. +class T2Pat : Pat { + list Predicates = [IsThumb2]; +} + +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// ARM VFP Instruction templates. +// + +// Almost all VFP instructions are predicable. +class VFPI pattern> + : InstARM { + let OutOperandList = oops; + let InOperandList = !con(iops, (ops pred:$p)); + let AsmString = !strconcat(opc, !strconcat("${p}", asm)); + let Pattern = pattern; + list Predicates = [HasVFP2]; +} + +// Special cases +class VFPXI pattern> + : InstARM { + let OutOperandList = oops; + let InOperandList = iops; + let AsmString = asm; + let Pattern = pattern; + list Predicates = [HasVFP2]; +} + +class VFPAI pattern> + : VFPI; + +// ARM VFP addrmode5 loads and stores +class ADI5 opcod1, bits<2> opcod2, dag oops, dag iops, + InstrItinClass itin, + string opc, string asm, list pattern> + : VFPI { + // TODO: Mark the instructions with the appropriate subtarget info. + let Inst{27-24} = opcod1; + let Inst{21-20} = opcod2; + let Inst{11-8} = 0b1011; + + // 64-bit loads & stores operate on both NEON and VFP pipelines. + let Dom = VFPNeonDomain.Value; +} + +class ASI5 opcod1, bits<2> opcod2, dag oops, dag iops, + InstrItinClass itin, + string opc, string asm, list pattern> + : VFPI { + // TODO: Mark the instructions with the appropriate subtarget info. + let Inst{27-24} = opcod1; + let Inst{21-20} = opcod2; + let Inst{11-8} = 0b1010; +} + +// Load / store multiple +class AXDI5 pattern> + : VFPXI { + // TODO: Mark the instructions with the appropriate subtarget info. + let Inst{27-25} = 0b110; + let Inst{11-8} = 0b1011; + + // 64-bit loads & stores operate on both NEON and VFP pipelines. + let Dom = VFPNeonDomain.Value; +} + +class AXSI5 pattern> + : VFPXI { + // TODO: Mark the instructions with the appropriate subtarget info. + let Inst{27-25} = 0b110; + let Inst{11-8} = 0b1010; +} + +// Double precision, unary +class ADuI opcod1, bits<4> opcod2, bits<4> opcod3, dag oops, dag iops, + InstrItinClass itin, string opc, string asm, list pattern> + : VFPAI { + let Inst{27-20} = opcod1; + let Inst{19-16} = opcod2; + let Inst{11-8} = 0b1011; + let Inst{7-4} = opcod3; +} + +// Double precision, binary +class ADbI opcod, dag oops, dag iops, InstrItinClass itin, + string opc, string asm, list pattern> + : VFPAI { + let Inst{27-20} = opcod; + let Inst{11-8} = 0b1011; +} + +// Single precision, unary +class ASuI opcod1, bits<4> opcod2, bits<4> opcod3, dag oops, dag iops, + InstrItinClass itin, string opc, string asm, list pattern> + : VFPAI { + // Bits 22 (D bit) and 5 (M bit) will be changed during instruction encoding. + let Inst{27-20} = opcod1; + let Inst{19-16} = opcod2; + let Inst{11-8} = 0b1010; + let Inst{7-4} = opcod3; +} + +// Single precision unary, if no NEON +// Same as ASuI except not available if NEON is enabled +class ASuIn opcod1, bits<4> opcod2, bits<4> opcod3, dag oops, dag iops, + InstrItinClass itin, string opc, string asm, list pattern> + : ASuI { + list Predicates = [HasVFP2,DontUseNEONForFP]; +} + +// Single precision, binary +class ASbI opcod, dag oops, dag iops, InstrItinClass itin, + string opc, string asm, list pattern> + : VFPAI { + // Bit 22 (D bit) can be changed during instruction encoding. + let Inst{27-20} = opcod; + let Inst{11-8} = 0b1010; +} + +// Single precision binary, if no NEON +// Same as ASbI except not available if NEON is enabled +class ASbIn opcod, dag oops, dag iops, InstrItinClass itin, + string opc, string asm, list pattern> + : ASbI { + list Predicates = [HasVFP2,DontUseNEONForFP]; +} + +// VFP conversion instructions +class AVConv1I opcod1, bits<4> opcod2, bits<4> opcod3, + dag oops, dag iops, InstrItinClass itin, + string opc, string asm, list pattern> + : VFPAI { + let Inst{27-20} = opcod1; + let Inst{19-16} = opcod2; + let Inst{11-8} = opcod3; + let Inst{6} = 1; +} + +// VFP conversion instructions, if no NEON +class AVConv1In opcod1, bits<4> opcod2, bits<4> opcod3, + dag oops, dag iops, InstrItinClass itin, + string opc, string asm, list pattern> + : AVConv1I { + list Predicates = [HasVFP2,DontUseNEONForFP]; +} + +class AVConvXI opcod1, bits<4> opcod2, dag oops, dag iops, Format f, + InstrItinClass itin, + string opc, string asm, list pattern> + : VFPAI { + let Inst{27-20} = opcod1; + let Inst{11-8} = opcod2; + let Inst{4} = 1; +} + +class AVConv2I opcod1, bits<4> opcod2, dag oops, dag iops, + InstrItinClass itin, string opc, string asm, list pattern> + : AVConvXI; + +class AVConv3I opcod1, bits<4> opcod2, dag oops, dag iops, + InstrItinClass itin, string opc, string asm, list pattern> + : AVConvXI; + +class AVConv4I opcod1, bits<4> opcod2, dag oops, dag iops, + InstrItinClass itin, string opc, string asm, list pattern> + : AVConvXI; + +class AVConv5I opcod1, bits<4> opcod2, dag oops, dag iops, + InstrItinClass itin, string opc, string asm, list pattern> + : AVConvXI; + +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// ARM NEON Instruction templates. +// + +class NeonI pattern> + : InstARM { + let OutOperandList = oops; + let InOperandList = !con(iops, (ops pred:$p)); + let AsmString = !strconcat( + !strconcat(!strconcat(opc, "${p}"), !strconcat(".", dt)), + !strconcat("\t", asm)); + let Pattern = pattern; + list Predicates = [HasNEON]; +} + +// Same as NeonI except it does not have a "data type" specifier. +class NeonXI pattern> + : InstARM { + let OutOperandList = oops; + let InOperandList = !con(iops, (ops pred:$p)); + let AsmString = !strconcat(!strconcat(opc, "${p}"), !strconcat("\t", asm)); + let Pattern = pattern; + list Predicates = [HasNEON]; +} + +class NI pattern> + : NeonXI { +} + +class NI4 pattern> + : NeonXI { +} + +class NLdSt op21_20, bits<4> op11_8, bits<4> op7_4, + dag oops, dag iops, InstrItinClass itin, + string opc, string dt, string asm, string cstr, list pattern> + : NeonI { + let Inst{31-24} = 0b11110100; + let Inst{23} = op23; + let Inst{21-20} = op21_20; + let Inst{11-8} = op11_8; + let Inst{7-4} = op7_4; +} + +class NDataI pattern> + : NeonI { + let Inst{31-25} = 0b1111001; +} + +class NDataXI pattern> + : NeonXI { + let Inst{31-25} = 0b1111001; +} + +// NEON "one register and a modified immediate" format. +class N1ModImm op21_19, bits<4> op11_8, bit op7, bit op6, + bit op5, bit op4, + dag oops, dag iops, InstrItinClass itin, + string opc, string dt, string asm, string cstr, list pattern> + : NDataI { + let Inst{23} = op23; + let Inst{21-19} = op21_19; + let Inst{11-8} = op11_8; + let Inst{7} = op7; + let Inst{6} = op6; + let Inst{5} = op5; + let Inst{4} = op4; +} + +// NEON 2 vector register format. +class N2V op24_23, bits<2> op21_20, bits<2> op19_18, bits<2> op17_16, + bits<5> op11_7, bit op6, bit op4, + dag oops, dag iops, InstrItinClass itin, + string opc, string dt, string asm, string cstr, list pattern> + : NDataI { + let Inst{24-23} = op24_23; + let Inst{21-20} = op21_20; + let Inst{19-18} = op19_18; + let Inst{17-16} = op17_16; + let Inst{11-7} = op11_7; + let Inst{6} = op6; + let Inst{4} = op4; +} + +// Same as N2V except it doesn't have a datatype suffix. +class N2VX op24_23, bits<2> op21_20, bits<2> op19_18, bits<2> op17_16, + bits<5> op11_7, bit op6, bit op4, + dag oops, dag iops, InstrItinClass itin, + string opc, string asm, string cstr, list pattern> + : NDataXI { + let Inst{24-23} = op24_23; + let Inst{21-20} = op21_20; + let Inst{19-18} = op19_18; + let Inst{17-16} = op17_16; + let Inst{11-7} = op11_7; + let Inst{6} = op6; + let Inst{4} = op4; +} + +// NEON 2 vector register with immediate. +class N2VImm op11_8, bit op7, bit op6, bit op4, + dag oops, dag iops, InstrItinClass itin, + string opc, string dt, string asm, string cstr, list pattern> + : NDataI { + let Inst{24} = op24; + let Inst{23} = op23; + let Inst{11-8} = op11_8; + let Inst{7} = op7; + let Inst{6} = op6; + let Inst{4} = op4; +} + +// NEON 3 vector register format. +class N3V op21_20, bits<4> op11_8, bit op6, bit op4, + dag oops, dag iops, InstrItinClass itin, + string opc, string dt, string asm, string cstr, list pattern> + : NDataI { + let Inst{24} = op24; + let Inst{23} = op23; + let Inst{21-20} = op21_20; + let Inst{11-8} = op11_8; + let Inst{6} = op6; + let Inst{4} = op4; +} + +// Same as N3VX except it doesn't have a data type suffix. +class N3VX op21_20, bits<4> op11_8, bit op6, bit op4, + dag oops, dag iops, InstrItinClass itin, + string opc, string asm, string cstr, list pattern> + : NDataXI { + let Inst{24} = op24; + let Inst{23} = op23; + let Inst{21-20} = op21_20; + let Inst{11-8} = op11_8; + let Inst{6} = op6; + let Inst{4} = op4; +} + +// NEON VMOVs between scalar and core registers. +class NVLaneOp opcod1, bits<4> opcod2, bits<2> opcod3, + dag oops, dag iops, Format f, InstrItinClass itin, + string opc, string dt, string asm, list pattern> + : InstARM { + let Inst{27-20} = opcod1; + let Inst{11-8} = opcod2; + let Inst{6-5} = opcod3; + let Inst{4} = 1; + + let OutOperandList = oops; + let InOperandList = !con(iops, (ops pred:$p)); + let AsmString = !strconcat( + !strconcat(!strconcat(opc, "${p}"), !strconcat(".", dt)), + !strconcat("\t", asm)); + let Pattern = pattern; + list Predicates = [HasNEON]; +} +class NVGetLane opcod1, bits<4> opcod2, bits<2> opcod3, + dag oops, dag iops, InstrItinClass itin, + string opc, string dt, string asm, list pattern> + : NVLaneOp; +class NVSetLane opcod1, bits<4> opcod2, bits<2> opcod3, + dag oops, dag iops, InstrItinClass itin, + string opc, string dt, string asm, list pattern> + : NVLaneOp; +class NVDup opcod1, bits<4> opcod2, bits<2> opcod3, + dag oops, dag iops, InstrItinClass itin, + string opc, string dt, string asm, list pattern> + : NVLaneOp; + +// NEONFPPat - Same as Pat<>, but requires that the compiler be using NEON +// for single-precision FP. +class NEONFPPat : Pat { + list Predicates = [HasNEON,UseNEONForFP]; +} diff --git a/libclamav/c++/llvm/lib/Target/ARM/ARMInstrInfo.cpp b/libclamav/c++/llvm/lib/Target/ARM/ARMInstrInfo.cpp new file mode 100644 index 000000000..87bb12b51 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/ARM/ARMInstrInfo.cpp @@ -0,0 +1,105 @@ +//===- ARMInstrInfo.cpp - ARM Instruction Information -----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the ARM implementation of the TargetInstrInfo class. +// +//===----------------------------------------------------------------------===// + +#include "ARMInstrInfo.h" +#include "ARM.h" +#include "ARMAddressingModes.h" +#include "ARMGenInstrInfo.inc" +#include "ARMMachineFunctionInfo.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/CodeGen/LiveVariables.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineJumpTableInfo.h" +#include "llvm/MC/MCAsmInfo.h" +using namespace llvm; + +ARMInstrInfo::ARMInstrInfo(const ARMSubtarget &STI) + : ARMBaseInstrInfo(STI), RI(*this, STI) { +} + +unsigned ARMInstrInfo::getUnindexedOpcode(unsigned Opc) const { + switch (Opc) { + default: break; + case ARM::LDR_PRE: + case ARM::LDR_POST: + return ARM::LDR; + case ARM::LDRH_PRE: + case ARM::LDRH_POST: + return ARM::LDRH; + case ARM::LDRB_PRE: + case ARM::LDRB_POST: + return ARM::LDRB; + case ARM::LDRSH_PRE: + case ARM::LDRSH_POST: + return ARM::LDRSH; + case ARM::LDRSB_PRE: + case ARM::LDRSB_POST: + return ARM::LDRSB; + case ARM::STR_PRE: + case ARM::STR_POST: + return ARM::STR; + case ARM::STRH_PRE: + case ARM::STRH_POST: + return ARM::STRH; + case ARM::STRB_PRE: + case ARM::STRB_POST: + return ARM::STRB; + } + + return 0; +} + +bool ARMInstrInfo::BlockHasNoFallThrough(const MachineBasicBlock &MBB) const { + if (MBB.empty()) return false; + + switch (MBB.back().getOpcode()) { + case ARM::BX_RET: // Return. + case ARM::LDM_RET: + case ARM::B: + case ARM::BRIND: + case ARM::BR_JTr: // Jumptable branch. + case ARM::BR_JTm: // Jumptable branch through mem. + case ARM::BR_JTadd: // Jumptable branch add to pc. + return true; + default: + break; + } + + return false; +} + +void ARMInstrInfo:: +reMaterialize(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, + unsigned DestReg, unsigned SubIdx, const MachineInstr *Orig, + const TargetRegisterInfo *TRI) const { + DebugLoc dl = Orig->getDebugLoc(); + unsigned Opcode = Orig->getOpcode(); + switch (Opcode) { + default: + break; + case ARM::MOVi2pieces: { + RI.emitLoadConstPool(MBB, I, dl, + DestReg, SubIdx, + Orig->getOperand(1).getImm(), + (ARMCC::CondCodes)Orig->getOperand(2).getImm(), + Orig->getOperand(3).getReg()); + MachineInstr *NewMI = prior(I); + NewMI->getOperand(0).setSubReg(SubIdx); + return; + } + } + + return ARMBaseInstrInfo::reMaterialize(MBB, I, DestReg, SubIdx, Orig, TRI); +} + diff --git a/libclamav/c++/llvm/lib/Target/ARM/ARMInstrInfo.h b/libclamav/c++/llvm/lib/Target/ARM/ARMInstrInfo.h new file mode 100644 index 000000000..431957787 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/ARM/ARMInstrInfo.h @@ -0,0 +1,52 @@ +//===- ARMInstrInfo.h - ARM Instruction Information -------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the ARM implementation of the TargetInstrInfo class. +// +//===----------------------------------------------------------------------===// + +#ifndef ARMINSTRUCTIONINFO_H +#define ARMINSTRUCTIONINFO_H + +#include "llvm/Target/TargetInstrInfo.h" +#include "ARMBaseInstrInfo.h" +#include "ARMRegisterInfo.h" +#include "ARMSubtarget.h" +#include "ARM.h" + +namespace llvm { + class ARMSubtarget; + +class ARMInstrInfo : public ARMBaseInstrInfo { + ARMRegisterInfo RI; +public: + explicit ARMInstrInfo(const ARMSubtarget &STI); + + // Return the non-pre/post incrementing version of 'Opc'. Return 0 + // if there is not such an opcode. + unsigned getUnindexedOpcode(unsigned Opc) const; + + // Return true if the block does not fall through. + bool BlockHasNoFallThrough(const MachineBasicBlock &MBB) const; + + void reMaterialize(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, + unsigned DestReg, unsigned SubIdx, + const MachineInstr *Orig, + const TargetRegisterInfo *TRI) const; + + /// getRegisterInfo - TargetInstrInfo is a superset of MRegister info. As + /// such, whenever a client has an instance of instruction info, it should + /// always be able to get register info as well (through this method). + /// + const ARMRegisterInfo &getRegisterInfo() const { return RI; } +}; + +} + +#endif diff --git a/libclamav/c++/llvm/lib/Target/ARM/ARMInstrInfo.td b/libclamav/c++/llvm/lib/Target/ARM/ARMInstrInfo.td new file mode 100644 index 000000000..0a8ecc008 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/ARM/ARMInstrInfo.td @@ -0,0 +1,1745 @@ +//===- ARMInstrInfo.td - Target Description for ARM Target -*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file describes the ARM instructions in TableGen format. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// ARM specific DAG Nodes. +// + +// Type profiles. +def SDT_ARMCallSeqStart : SDCallSeqStart<[ SDTCisVT<0, i32> ]>; +def SDT_ARMCallSeqEnd : SDCallSeqEnd<[ SDTCisVT<0, i32>, SDTCisVT<1, i32> ]>; + +def SDT_ARMSaveCallPC : SDTypeProfile<0, 1, []>; + +def SDT_ARMcall : SDTypeProfile<0, -1, [SDTCisInt<0>]>; + +def SDT_ARMCMov : SDTypeProfile<1, 3, + [SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>, + SDTCisVT<3, i32>]>; + +def SDT_ARMBrcond : SDTypeProfile<0, 2, + [SDTCisVT<0, OtherVT>, SDTCisVT<1, i32>]>; + +def SDT_ARMBrJT : SDTypeProfile<0, 3, + [SDTCisPtrTy<0>, SDTCisVT<1, i32>, + SDTCisVT<2, i32>]>; + +def SDT_ARMBr2JT : SDTypeProfile<0, 4, + [SDTCisPtrTy<0>, SDTCisVT<1, i32>, + SDTCisVT<2, i32>, SDTCisVT<3, i32>]>; + +def SDT_ARMCmp : SDTypeProfile<0, 2, [SDTCisSameAs<0, 1>]>; + +def SDT_ARMPICAdd : SDTypeProfile<1, 2, [SDTCisSameAs<0, 1>, + SDTCisPtrTy<1>, SDTCisVT<2, i32>]>; + +def SDT_ARMThreadPointer : SDTypeProfile<1, 0, [SDTCisPtrTy<0>]>; +def SDT_ARMEH_SJLJ_Setjmp : SDTypeProfile<1, 1, [SDTCisInt<0>, SDTCisPtrTy<1>]>; + +// Node definitions. +def ARMWrapper : SDNode<"ARMISD::Wrapper", SDTIntUnaryOp>; +def ARMWrapperJT : SDNode<"ARMISD::WrapperJT", SDTIntBinOp>; + +def ARMcallseq_start : SDNode<"ISD::CALLSEQ_START", SDT_ARMCallSeqStart, + [SDNPHasChain, SDNPOutFlag]>; +def ARMcallseq_end : SDNode<"ISD::CALLSEQ_END", SDT_ARMCallSeqEnd, + [SDNPHasChain, SDNPOptInFlag, SDNPOutFlag]>; + +def ARMcall : SDNode<"ARMISD::CALL", SDT_ARMcall, + [SDNPHasChain, SDNPOptInFlag, SDNPOutFlag]>; +def ARMcall_pred : SDNode<"ARMISD::CALL_PRED", SDT_ARMcall, + [SDNPHasChain, SDNPOptInFlag, SDNPOutFlag]>; +def ARMcall_nolink : SDNode<"ARMISD::CALL_NOLINK", SDT_ARMcall, + [SDNPHasChain, SDNPOptInFlag, SDNPOutFlag]>; + +def ARMretflag : SDNode<"ARMISD::RET_FLAG", SDTNone, + [SDNPHasChain, SDNPOptInFlag]>; + +def ARMcmov : SDNode<"ARMISD::CMOV", SDT_ARMCMov, + [SDNPInFlag]>; +def ARMcneg : SDNode<"ARMISD::CNEG", SDT_ARMCMov, + [SDNPInFlag]>; + +def ARMbrcond : SDNode<"ARMISD::BRCOND", SDT_ARMBrcond, + [SDNPHasChain, SDNPInFlag, SDNPOutFlag]>; + +def ARMbrjt : SDNode<"ARMISD::BR_JT", SDT_ARMBrJT, + [SDNPHasChain]>; +def ARMbr2jt : SDNode<"ARMISD::BR2_JT", SDT_ARMBr2JT, + [SDNPHasChain]>; + +def ARMcmp : SDNode<"ARMISD::CMP", SDT_ARMCmp, + [SDNPOutFlag]>; + +def ARMcmpZ : SDNode<"ARMISD::CMPZ", SDT_ARMCmp, + [SDNPOutFlag,SDNPCommutative]>; + +def ARMpic_add : SDNode<"ARMISD::PIC_ADD", SDT_ARMPICAdd>; + +def ARMsrl_flag : SDNode<"ARMISD::SRL_FLAG", SDTIntUnaryOp, [SDNPOutFlag]>; +def ARMsra_flag : SDNode<"ARMISD::SRA_FLAG", SDTIntUnaryOp, [SDNPOutFlag]>; +def ARMrrx : SDNode<"ARMISD::RRX" , SDTIntUnaryOp, [SDNPInFlag ]>; + +def ARMthread_pointer: SDNode<"ARMISD::THREAD_POINTER", SDT_ARMThreadPointer>; +def ARMeh_sjlj_setjmp: SDNode<"ARMISD::EH_SJLJ_SETJMP", SDT_ARMEH_SJLJ_Setjmp>; + +//===----------------------------------------------------------------------===// +// ARM Instruction Predicate Definitions. +// +def HasV5T : Predicate<"Subtarget->hasV5TOps()">; +def HasV5TE : Predicate<"Subtarget->hasV5TEOps()">; +def HasV6 : Predicate<"Subtarget->hasV6Ops()">; +def HasV6T2 : Predicate<"Subtarget->hasV6T2Ops()">; +def NoV6T2 : Predicate<"!Subtarget->hasV6T2Ops()">; +def HasV7 : Predicate<"Subtarget->hasV7Ops()">; +def HasVFP2 : Predicate<"Subtarget->hasVFP2()">; +def HasVFP3 : Predicate<"Subtarget->hasVFP3()">; +def HasNEON : Predicate<"Subtarget->hasNEON()">; +def UseNEONForFP : Predicate<"Subtarget->useNEONForSinglePrecisionFP()">; +def DontUseNEONForFP : Predicate<"!Subtarget->useNEONForSinglePrecisionFP()">; +def IsThumb : Predicate<"Subtarget->isThumb()">; +def IsThumb1Only : Predicate<"Subtarget->isThumb1Only()">; +def IsThumb2 : Predicate<"Subtarget->isThumb2()">; +def IsARM : Predicate<"!Subtarget->isThumb()">; +def IsDarwin : Predicate<"Subtarget->isTargetDarwin()">; +def IsNotDarwin : Predicate<"!Subtarget->isTargetDarwin()">; +def CarryDefIsUnused : Predicate<"!N.getNode()->hasAnyUseOfValue(1)">; +def CarryDefIsUsed : Predicate<"N.getNode()->hasAnyUseOfValue(1)">; + +// FIXME: Eventually this will be just "hasV6T2Ops". +def UseMovt : Predicate<"Subtarget->useMovt()">; +def DontUseMovt : Predicate<"!Subtarget->useMovt()">; + +//===----------------------------------------------------------------------===// +// ARM Flag Definitions. + +class RegConstraint { + string Constraints = C; +} + +//===----------------------------------------------------------------------===// +// ARM specific transformation functions and pattern fragments. +// + +// so_imm_neg_XFORM - Return a so_imm value packed into the format described for +// so_imm_neg def below. +def so_imm_neg_XFORM : SDNodeXFormgetTargetConstant(-(int)N->getZExtValue(), MVT::i32); +}]>; + +// so_imm_not_XFORM - Return a so_imm value packed into the format described for +// so_imm_not def below. +def so_imm_not_XFORM : SDNodeXFormgetTargetConstant(~(int)N->getZExtValue(), MVT::i32); +}]>; + +// rot_imm predicate - True if the 32-bit immediate is equal to 8, 16, or 24. +def rot_imm : PatLeaf<(i32 imm), [{ + int32_t v = (int32_t)N->getZExtValue(); + return v == 8 || v == 16 || v == 24; +}]>; + +/// imm1_15 predicate - True if the 32-bit immediate is in the range [1,15]. +def imm1_15 : PatLeaf<(i32 imm), [{ + return (int32_t)N->getZExtValue() >= 1 && (int32_t)N->getZExtValue() < 16; +}]>; + +/// imm16_31 predicate - True if the 32-bit immediate is in the range [16,31]. +def imm16_31 : PatLeaf<(i32 imm), [{ + return (int32_t)N->getZExtValue() >= 16 && (int32_t)N->getZExtValue() < 32; +}]>; + +def so_imm_neg : + PatLeaf<(imm), [{ + return ARM_AM::getSOImmVal(-(int)N->getZExtValue()) != -1; + }], so_imm_neg_XFORM>; + +def so_imm_not : + PatLeaf<(imm), [{ + return ARM_AM::getSOImmVal(~(int)N->getZExtValue()) != -1; + }], so_imm_not_XFORM>; + +// sext_16_node predicate - True if the SDNode is sign-extended 16 or more bits. +def sext_16_node : PatLeaf<(i32 GPR:$a), [{ + return CurDAG->ComputeNumSignBits(SDValue(N,0)) >= 17; +}]>; + +/// bf_inv_mask_imm predicate - An AND mask to clear an arbitrary width bitfield +/// e.g., 0xf000ffff +def bf_inv_mask_imm : Operand, + PatLeaf<(imm), [{ + uint32_t v = (uint32_t)N->getZExtValue(); + if (v == 0xffffffff) + return 0; + // there can be 1's on either or both "outsides", all the "inside" + // bits must be 0's + unsigned int lsb = 0, msb = 31; + while (v & (1 << msb)) --msb; + while (v & (1 << lsb)) ++lsb; + for (unsigned int i = lsb; i <= msb; ++i) { + if (v & (1 << i)) + return 0; + } + return 1; +}] > { + let PrintMethod = "printBitfieldInvMaskImmOperand"; +} + +/// Split a 32-bit immediate into two 16 bit parts. +def lo16 : SDNodeXFormgetTargetConstant((uint32_t)N->getZExtValue() & 0xffff, + MVT::i32); +}]>; + +def hi16 : SDNodeXFormgetTargetConstant((uint32_t)N->getZExtValue() >> 16, MVT::i32); +}]>; + +def lo16AllZero : PatLeaf<(i32 imm), [{ + // Returns true if all low 16-bits are 0. + return (((uint32_t)N->getZExtValue()) & 0xFFFFUL) == 0; +}], hi16>; + +/// imm0_65535 predicate - True if the 32-bit immediate is in the range +/// [0.65535]. +def imm0_65535 : PatLeaf<(i32 imm), [{ + return (uint32_t)N->getZExtValue() < 65536; +}]>; + +class BinOpFrag : PatFrag<(ops node:$LHS, node:$RHS), res>; +class UnOpFrag : PatFrag<(ops node:$Src), res>; + +//===----------------------------------------------------------------------===// +// Operand Definitions. +// + +// Branch target. +def brtarget : Operand; + +// A list of registers separated by comma. Used by load/store multiple. +def reglist : Operand { + let PrintMethod = "printRegisterList"; +} + +// An operand for the CONSTPOOL_ENTRY pseudo-instruction. +def cpinst_operand : Operand { + let PrintMethod = "printCPInstOperand"; +} + +def jtblock_operand : Operand { + let PrintMethod = "printJTBlockOperand"; +} +def jt2block_operand : Operand { + let PrintMethod = "printJT2BlockOperand"; +} + +// Local PC labels. +def pclabel : Operand { + let PrintMethod = "printPCLabel"; +} + +// shifter_operand operands: so_reg and so_imm. +def so_reg : Operand, // reg reg imm + ComplexPattern { + let PrintMethod = "printSORegOperand"; + let MIOperandInfo = (ops GPR, GPR, i32imm); +} + +// so_imm - Match a 32-bit shifter_operand immediate operand, which is an +// 8-bit immediate rotated by an arbitrary number of bits. so_imm values are +// represented in the imm field in the same 12-bit form that they are encoded +// into so_imm instructions: the 8-bit immediate is the least significant bits +// [bits 0-7], the 4-bit shift amount is the next 4 bits [bits 8-11]. +def so_imm : Operand, + PatLeaf<(imm), [{ + return ARM_AM::getSOImmVal(N->getZExtValue()) != -1; + }]> { + let PrintMethod = "printSOImmOperand"; +} + +// Break so_imm's up into two pieces. This handles immediates with up to 16 +// bits set in them. This uses so_imm2part to match and so_imm2part_[12] to +// get the first/second pieces. +def so_imm2part : Operand, + PatLeaf<(imm), [{ + return ARM_AM::isSOImmTwoPartVal((unsigned)N->getZExtValue()); + }]> { + let PrintMethod = "printSOImm2PartOperand"; +} + +def so_imm2part_1 : SDNodeXFormgetZExtValue()); + return CurDAG->getTargetConstant(V, MVT::i32); +}]>; + +def so_imm2part_2 : SDNodeXFormgetZExtValue()); + return CurDAG->getTargetConstant(V, MVT::i32); +}]>; + +def so_neg_imm2part : Operand, PatLeaf<(imm), [{ + return ARM_AM::isSOImmTwoPartVal(-(int)N->getZExtValue()); + }]> { + let PrintMethod = "printSOImm2PartOperand"; +} + +def so_neg_imm2part_1 : SDNodeXFormgetZExtValue()); + return CurDAG->getTargetConstant(V, MVT::i32); +}]>; + +def so_neg_imm2part_2 : SDNodeXFormgetZExtValue()); + return CurDAG->getTargetConstant(V, MVT::i32); +}]>; + +/// imm0_31 predicate - True if the 32-bit immediate is in the range [0,31]. +def imm0_31 : Operand, PatLeaf<(imm), [{ + return (int32_t)N->getZExtValue() < 32; +}]>; + +// Define ARM specific addressing modes. + +// addrmode2 := reg +/- reg shop imm +// addrmode2 := reg +/- imm12 +// +def addrmode2 : Operand, + ComplexPattern { + let PrintMethod = "printAddrMode2Operand"; + let MIOperandInfo = (ops GPR:$base, GPR:$offsreg, i32imm:$offsimm); +} + +def am2offset : Operand, + ComplexPattern { + let PrintMethod = "printAddrMode2OffsetOperand"; + let MIOperandInfo = (ops GPR, i32imm); +} + +// addrmode3 := reg +/- reg +// addrmode3 := reg +/- imm8 +// +def addrmode3 : Operand, + ComplexPattern { + let PrintMethod = "printAddrMode3Operand"; + let MIOperandInfo = (ops GPR:$base, GPR:$offsreg, i32imm:$offsimm); +} + +def am3offset : Operand, + ComplexPattern { + let PrintMethod = "printAddrMode3OffsetOperand"; + let MIOperandInfo = (ops GPR, i32imm); +} + +// addrmode4 := reg, +// +def addrmode4 : Operand, + ComplexPattern { + let PrintMethod = "printAddrMode4Operand"; + let MIOperandInfo = (ops GPR, i32imm); +} + +// addrmode5 := reg +/- imm8*4 +// +def addrmode5 : Operand, + ComplexPattern { + let PrintMethod = "printAddrMode5Operand"; + let MIOperandInfo = (ops GPR, i32imm); +} + +// addrmode6 := reg with optional writeback +// +def addrmode6 : Operand, + ComplexPattern { + let PrintMethod = "printAddrMode6Operand"; + let MIOperandInfo = (ops GPR:$addr, GPR:$upd, i32imm, i32imm); +} + +// addrmodepc := pc + reg +// +def addrmodepc : Operand, + ComplexPattern { + let PrintMethod = "printAddrModePCOperand"; + let MIOperandInfo = (ops GPR, i32imm); +} + +def nohash_imm : Operand { + let PrintMethod = "printNoHashImmediate"; +} + +//===----------------------------------------------------------------------===// + +include "ARMInstrFormats.td" + +//===----------------------------------------------------------------------===// +// Multiclass helpers... +// + +/// AsI1_bin_irs - Defines a set of (op r, {so_imm|r|so_reg}) patterns for a +/// binop that produces a value. +multiclass AsI1_bin_irs opcod, string opc, PatFrag opnode, + bit Commutable = 0> { + def ri : AsI1 { + let Inst{25} = 1; + } + def rr : AsI1 { + let Inst{11-4} = 0b00000000; + let Inst{25} = 0; + let isCommutable = Commutable; + } + def rs : AsI1 { + let Inst{25} = 0; + } +} + +/// AI1_bin_s_irs - Similar to AsI1_bin_irs except it sets the 's' bit so the +/// instruction modifies the CPSR register. +let Defs = [CPSR] in { +multiclass AI1_bin_s_irs opcod, string opc, PatFrag opnode, + bit Commutable = 0> { + def ri : AI1 { + let Inst{20} = 1; + let Inst{25} = 1; + } + def rr : AI1 { + let isCommutable = Commutable; + let Inst{11-4} = 0b00000000; + let Inst{20} = 1; + let Inst{25} = 0; + } + def rs : AI1 { + let Inst{20} = 1; + let Inst{25} = 0; + } +} +} + +/// AI1_cmp_irs - Defines a set of (op r, {so_imm|r|so_reg}) cmp / test +/// patterns. Similar to AsI1_bin_irs except the instruction does not produce +/// a explicit result, only implicitly set CPSR. +let Defs = [CPSR] in { +multiclass AI1_cmp_irs opcod, string opc, PatFrag opnode, + bit Commutable = 0> { + def ri : AI1 { + let Inst{20} = 1; + let Inst{25} = 1; + } + def rr : AI1 { + let Inst{11-4} = 0b00000000; + let Inst{20} = 1; + let Inst{25} = 0; + let isCommutable = Commutable; + } + def rs : AI1 { + let Inst{20} = 1; + let Inst{25} = 0; + } +} +} + +/// AI_unary_rrot - A unary operation with two forms: one whose operand is a +/// register and one whose operand is a register rotated by 8/16/24. +/// FIXME: Remove the 'r' variant. Its rot_imm is zero. +multiclass AI_unary_rrot opcod, string opc, PatFrag opnode> { + def r : AExtI, + Requires<[IsARM, HasV6]> { + let Inst{11-10} = 0b00; + let Inst{19-16} = 0b1111; + } + def r_rot : AExtI, + Requires<[IsARM, HasV6]> { + let Inst{19-16} = 0b1111; + } +} + +/// AI_bin_rrot - A binary operation with two forms: one whose operand is a +/// register and one whose operand is a register rotated by 8/16/24. +multiclass AI_bin_rrot opcod, string opc, PatFrag opnode> { + def rr : AExtI, + Requires<[IsARM, HasV6]> { + let Inst{11-10} = 0b00; + } + def rr_rot : AExtI, + Requires<[IsARM, HasV6]>; +} + +/// AI1_adde_sube_irs - Define instructions and patterns for adde and sube. +let Uses = [CPSR] in { +multiclass AI1_adde_sube_irs opcod, string opc, PatFrag opnode, + bit Commutable = 0> { + def ri : AsI1, + Requires<[IsARM, CarryDefIsUnused]> { + let Inst{25} = 1; + } + def rr : AsI1, + Requires<[IsARM, CarryDefIsUnused]> { + let isCommutable = Commutable; + let Inst{11-4} = 0b00000000; + let Inst{25} = 0; + } + def rs : AsI1, + Requires<[IsARM, CarryDefIsUnused]> { + let Inst{25} = 0; + } +} +// Carry setting variants +let Defs = [CPSR] in { +multiclass AI1_adde_sube_s_irs opcod, string opc, PatFrag opnode, + bit Commutable = 0> { + def Sri : AXI1, + Requires<[IsARM, CarryDefIsUsed]> { + let Defs = [CPSR]; + let Inst{20} = 1; + let Inst{25} = 1; + } + def Srr : AXI1, + Requires<[IsARM, CarryDefIsUsed]> { + let Defs = [CPSR]; + let Inst{11-4} = 0b00000000; + let Inst{20} = 1; + let Inst{25} = 0; + } + def Srs : AXI1, + Requires<[IsARM, CarryDefIsUsed]> { + let Defs = [CPSR]; + let Inst{20} = 1; + let Inst{25} = 0; + } +} +} +} + +//===----------------------------------------------------------------------===// +// Instructions +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// Miscellaneous Instructions. +// + +/// CONSTPOOL_ENTRY - This instruction represents a floating constant pool in +/// the function. The first operand is the ID# for this instruction, the second +/// is the index into the MachineConstantPool that this is, the third is the +/// size in bytes of this constant pool entry. +let neverHasSideEffects = 1, isNotDuplicable = 1 in +def CONSTPOOL_ENTRY : +PseudoInst<(outs), (ins cpinst_operand:$instid, cpinst_operand:$cpidx, + i32imm:$size), NoItinerary, + "${instid:label} ${cpidx:cpentry}", []>; + +let Defs = [SP], Uses = [SP] in { +def ADJCALLSTACKUP : +PseudoInst<(outs), (ins i32imm:$amt1, i32imm:$amt2, pred:$p), NoItinerary, + "@ ADJCALLSTACKUP $amt1", + [(ARMcallseq_end timm:$amt1, timm:$amt2)]>; + +def ADJCALLSTACKDOWN : +PseudoInst<(outs), (ins i32imm:$amt, pred:$p), NoItinerary, + "@ ADJCALLSTACKDOWN $amt", + [(ARMcallseq_start timm:$amt)]>; +} + +// Address computation and loads and stores in PIC mode. +let isNotDuplicable = 1 in { +def PICADD : AXI1<0b0100, (outs GPR:$dst), (ins GPR:$a, pclabel:$cp, pred:$p), + Pseudo, IIC_iALUr, "\n$cp:\n\tadd$p\t$dst, pc, $a", + [(set GPR:$dst, (ARMpic_add GPR:$a, imm:$cp))]>; + +let AddedComplexity = 10 in { +def PICLDR : AXI2ldw<(outs GPR:$dst), (ins addrmodepc:$addr, pred:$p), + Pseudo, IIC_iLoadr, "\n${addr:label}:\n\tldr$p\t$dst, $addr", + [(set GPR:$dst, (load addrmodepc:$addr))]>; + +def PICLDRH : AXI3ldh<(outs GPR:$dst), (ins addrmodepc:$addr, pred:$p), + Pseudo, IIC_iLoadr, "\n${addr:label}:\n\tldr${p}h\t$dst, $addr", + [(set GPR:$dst, (zextloadi16 addrmodepc:$addr))]>; + +def PICLDRB : AXI2ldb<(outs GPR:$dst), (ins addrmodepc:$addr, pred:$p), + Pseudo, IIC_iLoadr, "\n${addr:label}:\n\tldr${p}b\t$dst, $addr", + [(set GPR:$dst, (zextloadi8 addrmodepc:$addr))]>; + +def PICLDRSH : AXI3ldsh<(outs GPR:$dst), (ins addrmodepc:$addr, pred:$p), + Pseudo, IIC_iLoadr, "\n${addr:label}:\n\tldr${p}sh\t$dst, $addr", + [(set GPR:$dst, (sextloadi16 addrmodepc:$addr))]>; + +def PICLDRSB : AXI3ldsb<(outs GPR:$dst), (ins addrmodepc:$addr, pred:$p), + Pseudo, IIC_iLoadr, "\n${addr:label}:\n\tldr${p}sb\t$dst, $addr", + [(set GPR:$dst, (sextloadi8 addrmodepc:$addr))]>; +} +let AddedComplexity = 10 in { +def PICSTR : AXI2stw<(outs), (ins GPR:$src, addrmodepc:$addr, pred:$p), + Pseudo, IIC_iStorer, "\n${addr:label}:\n\tstr$p\t$src, $addr", + [(store GPR:$src, addrmodepc:$addr)]>; + +def PICSTRH : AXI3sth<(outs), (ins GPR:$src, addrmodepc:$addr, pred:$p), + Pseudo, IIC_iStorer, "\n${addr:label}:\n\tstrh${p}\t$src, $addr", + [(truncstorei16 GPR:$src, addrmodepc:$addr)]>; + +def PICSTRB : AXI2stb<(outs), (ins GPR:$src, addrmodepc:$addr, pred:$p), + Pseudo, IIC_iStorer, "\n${addr:label}:\n\tstrb${p}\t$src, $addr", + [(truncstorei8 GPR:$src, addrmodepc:$addr)]>; +} +} // isNotDuplicable = 1 + + +// LEApcrel - Load a pc-relative address into a register without offending the +// assembler. +def LEApcrel : AXI1<0x0, (outs GPR:$dst), (ins i32imm:$label, pred:$p), + Pseudo, IIC_iALUi, + !strconcat(!strconcat(".set ${:private}PCRELV${:uid}, ($label-(", + "${:private}PCRELL${:uid}+8))\n"), + !strconcat("${:private}PCRELL${:uid}:\n\t", + "add$p\t$dst, pc, #${:private}PCRELV${:uid}")), + []>; + +def LEApcrelJT : AXI1<0x0, (outs GPR:$dst), + (ins i32imm:$label, nohash_imm:$id, pred:$p), + Pseudo, IIC_iALUi, + !strconcat(!strconcat(".set ${:private}PCRELV${:uid}, " + "(${label}_${id}-(", + "${:private}PCRELL${:uid}+8))\n"), + !strconcat("${:private}PCRELL${:uid}:\n\t", + "add$p\t$dst, pc, #${:private}PCRELV${:uid}")), + []> { + let Inst{25} = 1; +} + +//===----------------------------------------------------------------------===// +// Control Flow Instructions. +// + +let isReturn = 1, isTerminator = 1, isBarrier = 1 in + def BX_RET : AI<(outs), (ins), BrMiscFrm, IIC_Br, + "bx", "\tlr", [(ARMretflag)]> { + let Inst{3-0} = 0b1110; + let Inst{7-4} = 0b0001; + let Inst{19-8} = 0b111111111111; + let Inst{27-20} = 0b00010010; +} + +// Indirect branches +let isBranch = 1, isTerminator = 1, isBarrier = 1, isIndirectBranch = 1 in { + def BRIND : AXI<(outs), (ins GPR:$dst), BrMiscFrm, IIC_Br, "bx\t$dst", + [(brind GPR:$dst)]> { + let Inst{7-4} = 0b0001; + let Inst{19-8} = 0b111111111111; + let Inst{27-20} = 0b00010010; + let Inst{31-28} = 0b1110; + } +} + +// FIXME: remove when we have a way to marking a MI with these properties. +// FIXME: Should pc be an implicit operand like PICADD, etc? +let isReturn = 1, isTerminator = 1, isBarrier = 1, mayLoad = 1, + hasExtraDefRegAllocReq = 1 in + def LDM_RET : AXI4ld<(outs), + (ins addrmode4:$addr, pred:$p, reglist:$wb, variable_ops), + LdStMulFrm, IIC_Br, "ldm${addr:submode}${p}\t$addr, $wb", + []>; + +// On non-Darwin platforms R9 is callee-saved. +let isCall = 1, + Defs = [R0, R1, R2, R3, R12, LR, + D0, D1, D2, D3, D4, D5, D6, D7, + D16, D17, D18, D19, D20, D21, D22, D23, + D24, D25, D26, D27, D28, D29, D30, D31, CPSR, FPSCR] in { + def BL : ABXI<0b1011, (outs), (ins i32imm:$func, variable_ops), + IIC_Br, "bl\t${func:call}", + [(ARMcall tglobaladdr:$func)]>, + Requires<[IsARM, IsNotDarwin]> { + let Inst{31-28} = 0b1110; + } + + def BL_pred : ABI<0b1011, (outs), (ins i32imm:$func, variable_ops), + IIC_Br, "bl", "\t${func:call}", + [(ARMcall_pred tglobaladdr:$func)]>, + Requires<[IsARM, IsNotDarwin]>; + + // ARMv5T and above + def BLX : AXI<(outs), (ins GPR:$func, variable_ops), BrMiscFrm, + IIC_Br, "blx\t$func", + [(ARMcall GPR:$func)]>, + Requires<[IsARM, HasV5T, IsNotDarwin]> { + let Inst{7-4} = 0b0011; + let Inst{19-8} = 0b111111111111; + let Inst{27-20} = 0b00010010; + } + + // ARMv4T + def BX : ABXIx2<(outs), (ins GPR:$func, variable_ops), + IIC_Br, "mov\tlr, pc\n\tbx\t$func", + [(ARMcall_nolink GPR:$func)]>, + Requires<[IsARM, IsNotDarwin]> { + let Inst{7-4} = 0b0001; + let Inst{19-8} = 0b111111111111; + let Inst{27-20} = 0b00010010; + } +} + +// On Darwin R9 is call-clobbered. +let isCall = 1, + Defs = [R0, R1, R2, R3, R9, R12, LR, + D0, D1, D2, D3, D4, D5, D6, D7, + D16, D17, D18, D19, D20, D21, D22, D23, + D24, D25, D26, D27, D28, D29, D30, D31, CPSR, FPSCR] in { + def BLr9 : ABXI<0b1011, (outs), (ins i32imm:$func, variable_ops), + IIC_Br, "bl\t${func:call}", + [(ARMcall tglobaladdr:$func)]>, Requires<[IsARM, IsDarwin]> { + let Inst{31-28} = 0b1110; + } + + def BLr9_pred : ABI<0b1011, (outs), (ins i32imm:$func, variable_ops), + IIC_Br, "bl", "\t${func:call}", + [(ARMcall_pred tglobaladdr:$func)]>, + Requires<[IsARM, IsDarwin]>; + + // ARMv5T and above + def BLXr9 : AXI<(outs), (ins GPR:$func, variable_ops), BrMiscFrm, + IIC_Br, "blx\t$func", + [(ARMcall GPR:$func)]>, Requires<[IsARM, HasV5T, IsDarwin]> { + let Inst{7-4} = 0b0011; + let Inst{19-8} = 0b111111111111; + let Inst{27-20} = 0b00010010; + } + + // ARMv4T + def BXr9 : ABXIx2<(outs), (ins GPR:$func, variable_ops), + IIC_Br, "mov\tlr, pc\n\tbx\t$func", + [(ARMcall_nolink GPR:$func)]>, Requires<[IsARM, IsDarwin]> { + let Inst{7-4} = 0b0001; + let Inst{19-8} = 0b111111111111; + let Inst{27-20} = 0b00010010; + } +} + +let isBranch = 1, isTerminator = 1 in { + // B is "predicable" since it can be xformed into a Bcc. + let isBarrier = 1 in { + let isPredicable = 1 in + def B : ABXI<0b1010, (outs), (ins brtarget:$target), IIC_Br, + "b\t$target", [(br bb:$target)]>; + + let isNotDuplicable = 1, isIndirectBranch = 1 in { + def BR_JTr : JTI<(outs), (ins GPR:$target, jtblock_operand:$jt, i32imm:$id), + IIC_Br, "mov\tpc, $target \n$jt", + [(ARMbrjt GPR:$target, tjumptable:$jt, imm:$id)]> { + let Inst{15-12} = 0b1111; + let Inst{20} = 0; // S Bit + let Inst{24-21} = 0b1101; + let Inst{27-25} = 0b000; + } + def BR_JTm : JTI<(outs), + (ins addrmode2:$target, jtblock_operand:$jt, i32imm:$id), + IIC_Br, "ldr\tpc, $target \n$jt", + [(ARMbrjt (i32 (load addrmode2:$target)), tjumptable:$jt, + imm:$id)]> { + let Inst{15-12} = 0b1111; + let Inst{20} = 1; // L bit + let Inst{21} = 0; // W bit + let Inst{22} = 0; // B bit + let Inst{24} = 1; // P bit + let Inst{27-25} = 0b011; + } + def BR_JTadd : JTI<(outs), + (ins GPR:$target, GPR:$idx, jtblock_operand:$jt, i32imm:$id), + IIC_Br, "add\tpc, $target, $idx \n$jt", + [(ARMbrjt (add GPR:$target, GPR:$idx), tjumptable:$jt, + imm:$id)]> { + let Inst{15-12} = 0b1111; + let Inst{20} = 0; // S bit + let Inst{24-21} = 0b0100; + let Inst{27-25} = 0b000; + } + } // isNotDuplicable = 1, isIndirectBranch = 1 + } // isBarrier = 1 + + // FIXME: should be able to write a pattern for ARMBrcond, but can't use + // a two-value operand where a dag node expects two operands. :( + def Bcc : ABI<0b1010, (outs), (ins brtarget:$target), + IIC_Br, "b", "\t$target", + [/*(ARMbrcond bb:$target, imm:$cc, CCR:$ccr)*/]>; +} + +//===----------------------------------------------------------------------===// +// Load / store Instructions. +// + +// Load +let canFoldAsLoad = 1, isReMaterializable = 1, mayHaveSideEffects = 1 in +def LDR : AI2ldw<(outs GPR:$dst), (ins addrmode2:$addr), LdFrm, IIC_iLoadr, + "ldr", "\t$dst, $addr", + [(set GPR:$dst, (load addrmode2:$addr))]>; + +// Special LDR for loads from non-pc-relative constpools. +let canFoldAsLoad = 1, mayLoad = 1, isReMaterializable = 1, + mayHaveSideEffects = 1 in +def LDRcp : AI2ldw<(outs GPR:$dst), (ins addrmode2:$addr), LdFrm, IIC_iLoadr, + "ldr", "\t$dst, $addr", []>; + +// Loads with zero extension +def LDRH : AI3ldh<(outs GPR:$dst), (ins addrmode3:$addr), LdMiscFrm, + IIC_iLoadr, "ldrh", "\t$dst, $addr", + [(set GPR:$dst, (zextloadi16 addrmode3:$addr))]>; + +def LDRB : AI2ldb<(outs GPR:$dst), (ins addrmode2:$addr), LdFrm, + IIC_iLoadr, "ldrb", "\t$dst, $addr", + [(set GPR:$dst, (zextloadi8 addrmode2:$addr))]>; + +// Loads with sign extension +def LDRSH : AI3ldsh<(outs GPR:$dst), (ins addrmode3:$addr), LdMiscFrm, + IIC_iLoadr, "ldrsh", "\t$dst, $addr", + [(set GPR:$dst, (sextloadi16 addrmode3:$addr))]>; + +def LDRSB : AI3ldsb<(outs GPR:$dst), (ins addrmode3:$addr), LdMiscFrm, + IIC_iLoadr, "ldrsb", "\t$dst, $addr", + [(set GPR:$dst, (sextloadi8 addrmode3:$addr))]>; + +let mayLoad = 1, hasExtraDefRegAllocReq = 1 in { +// Load doubleword +def LDRD : AI3ldd<(outs GPR:$dst1, GPR:$dst2), (ins addrmode3:$addr), LdMiscFrm, + IIC_iLoadr, "ldrd", "\t$dst1, $addr", + []>, Requires<[IsARM, HasV5TE]>; + +// Indexed loads +def LDR_PRE : AI2ldwpr<(outs GPR:$dst, GPR:$base_wb), + (ins addrmode2:$addr), LdFrm, IIC_iLoadru, + "ldr", "\t$dst, $addr!", "$addr.base = $base_wb", []>; + +def LDR_POST : AI2ldwpo<(outs GPR:$dst, GPR:$base_wb), + (ins GPR:$base, am2offset:$offset), LdFrm, IIC_iLoadru, + "ldr", "\t$dst, [$base], $offset", "$base = $base_wb", []>; + +def LDRH_PRE : AI3ldhpr<(outs GPR:$dst, GPR:$base_wb), + (ins addrmode3:$addr), LdMiscFrm, IIC_iLoadru, + "ldrh", "\t$dst, $addr!", "$addr.base = $base_wb", []>; + +def LDRH_POST : AI3ldhpo<(outs GPR:$dst, GPR:$base_wb), + (ins GPR:$base,am3offset:$offset), LdMiscFrm, IIC_iLoadru, + "ldrh", "\t$dst, [$base], $offset", "$base = $base_wb", []>; + +def LDRB_PRE : AI2ldbpr<(outs GPR:$dst, GPR:$base_wb), + (ins addrmode2:$addr), LdFrm, IIC_iLoadru, + "ldrb", "\t$dst, $addr!", "$addr.base = $base_wb", []>; + +def LDRB_POST : AI2ldbpo<(outs GPR:$dst, GPR:$base_wb), + (ins GPR:$base,am2offset:$offset), LdFrm, IIC_iLoadru, + "ldrb", "\t$dst, [$base], $offset", "$base = $base_wb", []>; + +def LDRSH_PRE : AI3ldshpr<(outs GPR:$dst, GPR:$base_wb), + (ins addrmode3:$addr), LdMiscFrm, IIC_iLoadru, + "ldrsh", "\t$dst, $addr!", "$addr.base = $base_wb", []>; + +def LDRSH_POST: AI3ldshpo<(outs GPR:$dst, GPR:$base_wb), + (ins GPR:$base,am3offset:$offset), LdMiscFrm, IIC_iLoadru, + "ldrsh", "\t$dst, [$base], $offset", "$base = $base_wb", []>; + +def LDRSB_PRE : AI3ldsbpr<(outs GPR:$dst, GPR:$base_wb), + (ins addrmode3:$addr), LdMiscFrm, IIC_iLoadru, + "ldrsb", "\t$dst, $addr!", "$addr.base = $base_wb", []>; + +def LDRSB_POST: AI3ldsbpo<(outs GPR:$dst, GPR:$base_wb), + (ins GPR:$base,am3offset:$offset), LdMiscFrm, IIC_iLoadru, + "ldrsb", "\t$dst, [$base], $offset", "$base = $base_wb", []>; +} + +// Store +def STR : AI2stw<(outs), (ins GPR:$src, addrmode2:$addr), StFrm, IIC_iStorer, + "str", "\t$src, $addr", + [(store GPR:$src, addrmode2:$addr)]>; + +// Stores with truncate +def STRH : AI3sth<(outs), (ins GPR:$src, addrmode3:$addr), StMiscFrm, IIC_iStorer, + "strh", "\t$src, $addr", + [(truncstorei16 GPR:$src, addrmode3:$addr)]>; + +def STRB : AI2stb<(outs), (ins GPR:$src, addrmode2:$addr), StFrm, IIC_iStorer, + "strb", "\t$src, $addr", + [(truncstorei8 GPR:$src, addrmode2:$addr)]>; + +// Store doubleword +let mayStore = 1, hasExtraSrcRegAllocReq = 1 in +def STRD : AI3std<(outs), (ins GPR:$src1, GPR:$src2, addrmode3:$addr), + StMiscFrm, IIC_iStorer, + "strd", "\t$src1, $addr", []>, Requires<[IsARM, HasV5TE]>; + +// Indexed stores +def STR_PRE : AI2stwpr<(outs GPR:$base_wb), + (ins GPR:$src, GPR:$base, am2offset:$offset), + StFrm, IIC_iStoreru, + "str", "\t$src, [$base, $offset]!", "$base = $base_wb", + [(set GPR:$base_wb, + (pre_store GPR:$src, GPR:$base, am2offset:$offset))]>; + +def STR_POST : AI2stwpo<(outs GPR:$base_wb), + (ins GPR:$src, GPR:$base,am2offset:$offset), + StFrm, IIC_iStoreru, + "str", "\t$src, [$base], $offset", "$base = $base_wb", + [(set GPR:$base_wb, + (post_store GPR:$src, GPR:$base, am2offset:$offset))]>; + +def STRH_PRE : AI3sthpr<(outs GPR:$base_wb), + (ins GPR:$src, GPR:$base,am3offset:$offset), + StMiscFrm, IIC_iStoreru, + "strh", "\t$src, [$base, $offset]!", "$base = $base_wb", + [(set GPR:$base_wb, + (pre_truncsti16 GPR:$src, GPR:$base,am3offset:$offset))]>; + +def STRH_POST: AI3sthpo<(outs GPR:$base_wb), + (ins GPR:$src, GPR:$base,am3offset:$offset), + StMiscFrm, IIC_iStoreru, + "strh", "\t$src, [$base], $offset", "$base = $base_wb", + [(set GPR:$base_wb, (post_truncsti16 GPR:$src, + GPR:$base, am3offset:$offset))]>; + +def STRB_PRE : AI2stbpr<(outs GPR:$base_wb), + (ins GPR:$src, GPR:$base,am2offset:$offset), + StFrm, IIC_iStoreru, + "strb", "\t$src, [$base, $offset]!", "$base = $base_wb", + [(set GPR:$base_wb, (pre_truncsti8 GPR:$src, + GPR:$base, am2offset:$offset))]>; + +def STRB_POST: AI2stbpo<(outs GPR:$base_wb), + (ins GPR:$src, GPR:$base,am2offset:$offset), + StFrm, IIC_iStoreru, + "strb", "\t$src, [$base], $offset", "$base = $base_wb", + [(set GPR:$base_wb, (post_truncsti8 GPR:$src, + GPR:$base, am2offset:$offset))]>; + +//===----------------------------------------------------------------------===// +// Load / store multiple Instructions. +// + +let mayLoad = 1, hasExtraDefRegAllocReq = 1 in +def LDM : AXI4ld<(outs), + (ins addrmode4:$addr, pred:$p, reglist:$wb, variable_ops), + LdStMulFrm, IIC_iLoadm, "ldm${addr:submode}${p}\t$addr, $wb", + []>; + +let mayStore = 1, hasExtraSrcRegAllocReq = 1 in +def STM : AXI4st<(outs), + (ins addrmode4:$addr, pred:$p, reglist:$wb, variable_ops), + LdStMulFrm, IIC_iStorem, "stm${addr:submode}${p}\t$addr, $wb", + []>; + +//===----------------------------------------------------------------------===// +// Move Instructions. +// + +let neverHasSideEffects = 1 in +def MOVr : AsI1<0b1101, (outs GPR:$dst), (ins GPR:$src), DPFrm, IIC_iMOVr, + "mov", "\t$dst, $src", []>, UnaryDP { + let Inst{11-4} = 0b00000000; + let Inst{25} = 0; +} + +def MOVs : AsI1<0b1101, (outs GPR:$dst), (ins so_reg:$src), + DPSoRegFrm, IIC_iMOVsr, + "mov", "\t$dst, $src", [(set GPR:$dst, so_reg:$src)]>, UnaryDP { + let Inst{25} = 0; +} + +let isReMaterializable = 1, isAsCheapAsAMove = 1 in +def MOVi : AsI1<0b1101, (outs GPR:$dst), (ins so_imm:$src), DPFrm, IIC_iMOVi, + "mov", "\t$dst, $src", [(set GPR:$dst, so_imm:$src)]>, UnaryDP { + let Inst{25} = 1; +} + +let isReMaterializable = 1, isAsCheapAsAMove = 1 in +def MOVi16 : AI1<0b1000, (outs GPR:$dst), (ins i32imm:$src), + DPFrm, IIC_iMOVi, + "movw", "\t$dst, $src", + [(set GPR:$dst, imm0_65535:$src)]>, + Requires<[IsARM, HasV6T2]> { + let Inst{20} = 0; + let Inst{25} = 1; +} + +let Constraints = "$src = $dst" in +def MOVTi16 : AI1<0b1010, (outs GPR:$dst), (ins GPR:$src, i32imm:$imm), + DPFrm, IIC_iMOVi, + "movt", "\t$dst, $imm", + [(set GPR:$dst, + (or (and GPR:$src, 0xffff), + lo16AllZero:$imm))]>, UnaryDP, + Requires<[IsARM, HasV6T2]> { + let Inst{20} = 0; + let Inst{25} = 1; +} + +def : ARMPat<(or GPR:$src, 0xffff0000), (MOVTi16 GPR:$src, 0xffff)>, + Requires<[IsARM, HasV6T2]>; + +let Uses = [CPSR] in +def MOVrx : AsI1<0b1101, (outs GPR:$dst), (ins GPR:$src), Pseudo, IIC_iMOVsi, + "mov", "\t$dst, $src, rrx", + [(set GPR:$dst, (ARMrrx GPR:$src))]>, UnaryDP; + +// These aren't really mov instructions, but we have to define them this way +// due to flag operands. + +let Defs = [CPSR] in { +def MOVsrl_flag : AI1<0b1101, (outs GPR:$dst), (ins GPR:$src), Pseudo, + IIC_iMOVsi, "movs", "\t$dst, $src, lsr #1", + [(set GPR:$dst, (ARMsrl_flag GPR:$src))]>, UnaryDP; +def MOVsra_flag : AI1<0b1101, (outs GPR:$dst), (ins GPR:$src), Pseudo, + IIC_iMOVsi, "movs", "\t$dst, $src, asr #1", + [(set GPR:$dst, (ARMsra_flag GPR:$src))]>, UnaryDP; +} + +//===----------------------------------------------------------------------===// +// Extend Instructions. +// + +// Sign extenders + +defm SXTB : AI_unary_rrot<0b01101010, + "sxtb", UnOpFrag<(sext_inreg node:$Src, i8)>>; +defm SXTH : AI_unary_rrot<0b01101011, + "sxth", UnOpFrag<(sext_inreg node:$Src, i16)>>; + +defm SXTAB : AI_bin_rrot<0b01101010, + "sxtab", BinOpFrag<(add node:$LHS, (sext_inreg node:$RHS, i8))>>; +defm SXTAH : AI_bin_rrot<0b01101011, + "sxtah", BinOpFrag<(add node:$LHS, (sext_inreg node:$RHS,i16))>>; + +// TODO: SXT(A){B|H}16 + +// Zero extenders + +let AddedComplexity = 16 in { +defm UXTB : AI_unary_rrot<0b01101110, + "uxtb" , UnOpFrag<(and node:$Src, 0x000000FF)>>; +defm UXTH : AI_unary_rrot<0b01101111, + "uxth" , UnOpFrag<(and node:$Src, 0x0000FFFF)>>; +defm UXTB16 : AI_unary_rrot<0b01101100, + "uxtb16", UnOpFrag<(and node:$Src, 0x00FF00FF)>>; + +def : ARMV6Pat<(and (shl GPR:$Src, (i32 8)), 0xFF00FF), + (UXTB16r_rot GPR:$Src, 24)>; +def : ARMV6Pat<(and (srl GPR:$Src, (i32 8)), 0xFF00FF), + (UXTB16r_rot GPR:$Src, 8)>; + +defm UXTAB : AI_bin_rrot<0b01101110, "uxtab", + BinOpFrag<(add node:$LHS, (and node:$RHS, 0x00FF))>>; +defm UXTAH : AI_bin_rrot<0b01101111, "uxtah", + BinOpFrag<(add node:$LHS, (and node:$RHS, 0xFFFF))>>; +} + +// This isn't safe in general, the add is two 16-bit units, not a 32-bit add. +//defm UXTAB16 : xxx<"uxtab16", 0xff00ff>; + +// TODO: UXT(A){B|H}16 + +def SBFX : I<(outs GPR:$dst), + (ins GPR:$src, imm0_31:$lsb, imm0_31:$width), + AddrMode1, Size4Bytes, IndexModeNone, DPFrm, IIC_iALUi, + "sbfx", "\t$dst, $src, $lsb, $width", "", []>, + Requires<[IsARM, HasV6T2]> { + let Inst{27-21} = 0b0111101; + let Inst{6-4} = 0b101; +} + +def UBFX : I<(outs GPR:$dst), + (ins GPR:$src, imm0_31:$lsb, imm0_31:$width), + AddrMode1, Size4Bytes, IndexModeNone, DPFrm, IIC_iALUi, + "ubfx", "\t$dst, $src, $lsb, $width", "", []>, + Requires<[IsARM, HasV6T2]> { + let Inst{27-21} = 0b0111111; + let Inst{6-4} = 0b101; +} + +//===----------------------------------------------------------------------===// +// Arithmetic Instructions. +// + +defm ADD : AsI1_bin_irs<0b0100, "add", + BinOpFrag<(add node:$LHS, node:$RHS)>, 1>; +defm SUB : AsI1_bin_irs<0b0010, "sub", + BinOpFrag<(sub node:$LHS, node:$RHS)>>; + +// ADD and SUB with 's' bit set. +defm ADDS : AI1_bin_s_irs<0b0100, "adds", + BinOpFrag<(addc node:$LHS, node:$RHS)>, 1>; +defm SUBS : AI1_bin_s_irs<0b0010, "subs", + BinOpFrag<(subc node:$LHS, node:$RHS)>>; + +defm ADC : AI1_adde_sube_irs<0b0101, "adc", + BinOpFrag<(adde node:$LHS, node:$RHS)>, 1>; +defm SBC : AI1_adde_sube_irs<0b0110, "sbc", + BinOpFrag<(sube node:$LHS, node:$RHS)>>; +defm ADCS : AI1_adde_sube_s_irs<0b0101, "adcs", + BinOpFrag<(adde node:$LHS, node:$RHS)>, 1>; +defm SBCS : AI1_adde_sube_s_irs<0b0110, "sbcs", + BinOpFrag<(sube node:$LHS, node:$RHS)>>; + +// These don't define reg/reg forms, because they are handled above. +def RSBri : AsI1<0b0011, (outs GPR:$dst), (ins GPR:$a, so_imm:$b), DPFrm, + IIC_iALUi, "rsb", "\t$dst, $a, $b", + [(set GPR:$dst, (sub so_imm:$b, GPR:$a))]> { + let Inst{25} = 1; +} + +def RSBrs : AsI1<0b0011, (outs GPR:$dst), (ins GPR:$a, so_reg:$b), DPSoRegFrm, + IIC_iALUsr, "rsb", "\t$dst, $a, $b", + [(set GPR:$dst, (sub so_reg:$b, GPR:$a))]> { + let Inst{25} = 0; +} + +// RSB with 's' bit set. +let Defs = [CPSR] in { +def RSBSri : AI1<0b0011, (outs GPR:$dst), (ins GPR:$a, so_imm:$b), DPFrm, + IIC_iALUi, "rsbs", "\t$dst, $a, $b", + [(set GPR:$dst, (subc so_imm:$b, GPR:$a))]> { + let Inst{20} = 1; + let Inst{25} = 1; +} +def RSBSrs : AI1<0b0011, (outs GPR:$dst), (ins GPR:$a, so_reg:$b), DPSoRegFrm, + IIC_iALUsr, "rsbs", "\t$dst, $a, $b", + [(set GPR:$dst, (subc so_reg:$b, GPR:$a))]> { + let Inst{20} = 1; + let Inst{25} = 0; +} +} + +let Uses = [CPSR] in { +def RSCri : AsI1<0b0111, (outs GPR:$dst), (ins GPR:$a, so_imm:$b), + DPFrm, IIC_iALUi, "rsc", "\t$dst, $a, $b", + [(set GPR:$dst, (sube so_imm:$b, GPR:$a))]>, + Requires<[IsARM, CarryDefIsUnused]> { + let Inst{25} = 1; +} +def RSCrs : AsI1<0b0111, (outs GPR:$dst), (ins GPR:$a, so_reg:$b), + DPSoRegFrm, IIC_iALUsr, "rsc", "\t$dst, $a, $b", + [(set GPR:$dst, (sube so_reg:$b, GPR:$a))]>, + Requires<[IsARM, CarryDefIsUnused]> { + let Inst{25} = 0; +} +} + +// FIXME: Allow these to be predicated. +let Defs = [CPSR], Uses = [CPSR] in { +def RSCSri : AXI1<0b0111, (outs GPR:$dst), (ins GPR:$a, so_imm:$b), + DPFrm, IIC_iALUi, "rscs\t$dst, $a, $b", + [(set GPR:$dst, (sube so_imm:$b, GPR:$a))]>, + Requires<[IsARM, CarryDefIsUnused]> { + let Inst{20} = 1; + let Inst{25} = 1; +} +def RSCSrs : AXI1<0b0111, (outs GPR:$dst), (ins GPR:$a, so_reg:$b), + DPSoRegFrm, IIC_iALUsr, "rscs\t$dst, $a, $b", + [(set GPR:$dst, (sube so_reg:$b, GPR:$a))]>, + Requires<[IsARM, CarryDefIsUnused]> { + let Inst{20} = 1; + let Inst{25} = 0; +} +} + +// (sub X, imm) gets canonicalized to (add X, -imm). Match this form. +def : ARMPat<(add GPR:$src, so_imm_neg:$imm), + (SUBri GPR:$src, so_imm_neg:$imm)>; + +//def : ARMPat<(addc GPR:$src, so_imm_neg:$imm), +// (SUBSri GPR:$src, so_imm_neg:$imm)>; +//def : ARMPat<(adde GPR:$src, so_imm_neg:$imm), +// (SBCri GPR:$src, so_imm_neg:$imm)>; + +// Note: These are implemented in C++ code, because they have to generate +// ADD/SUBrs instructions, which use a complex pattern that a xform function +// cannot produce. +// (mul X, 2^n+1) -> (add (X << n), X) +// (mul X, 2^n-1) -> (rsb X, (X << n)) + + +//===----------------------------------------------------------------------===// +// Bitwise Instructions. +// + +defm AND : AsI1_bin_irs<0b0000, "and", + BinOpFrag<(and node:$LHS, node:$RHS)>, 1>; +defm ORR : AsI1_bin_irs<0b1100, "orr", + BinOpFrag<(or node:$LHS, node:$RHS)>, 1>; +defm EOR : AsI1_bin_irs<0b0001, "eor", + BinOpFrag<(xor node:$LHS, node:$RHS)>, 1>; +defm BIC : AsI1_bin_irs<0b1110, "bic", + BinOpFrag<(and node:$LHS, (not node:$RHS))>>; + +def BFC : I<(outs GPR:$dst), (ins GPR:$src, bf_inv_mask_imm:$imm), + AddrMode1, Size4Bytes, IndexModeNone, DPFrm, IIC_iUNAsi, + "bfc", "\t$dst, $imm", "$src = $dst", + [(set GPR:$dst, (and GPR:$src, bf_inv_mask_imm:$imm))]>, + Requires<[IsARM, HasV6T2]> { + let Inst{27-21} = 0b0111110; + let Inst{6-0} = 0b0011111; +} + +def MVNr : AsI1<0b1111, (outs GPR:$dst), (ins GPR:$src), DPFrm, IIC_iMOVr, + "mvn", "\t$dst, $src", + [(set GPR:$dst, (not GPR:$src))]>, UnaryDP { + let Inst{11-4} = 0b00000000; +} +def MVNs : AsI1<0b1111, (outs GPR:$dst), (ins so_reg:$src), DPSoRegFrm, + IIC_iMOVsr, "mvn", "\t$dst, $src", + [(set GPR:$dst, (not so_reg:$src))]>, UnaryDP; +let isReMaterializable = 1, isAsCheapAsAMove = 1 in +def MVNi : AsI1<0b1111, (outs GPR:$dst), (ins so_imm:$imm), DPFrm, + IIC_iMOVi, "mvn", "\t$dst, $imm", + [(set GPR:$dst, so_imm_not:$imm)]>,UnaryDP { + let Inst{25} = 1; +} + +def : ARMPat<(and GPR:$src, so_imm_not:$imm), + (BICri GPR:$src, so_imm_not:$imm)>; + +//===----------------------------------------------------------------------===// +// Multiply Instructions. +// + +let isCommutable = 1 in +def MUL : AsMul1I<0b0000000, (outs GPR:$dst), (ins GPR:$a, GPR:$b), + IIC_iMUL32, "mul", "\t$dst, $a, $b", + [(set GPR:$dst, (mul GPR:$a, GPR:$b))]>; + +def MLA : AsMul1I<0b0000001, (outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$c), + IIC_iMAC32, "mla", "\t$dst, $a, $b, $c", + [(set GPR:$dst, (add (mul GPR:$a, GPR:$b), GPR:$c))]>; + +def MLS : AMul1I<0b0000011, (outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$c), + IIC_iMAC32, "mls", "\t$dst, $a, $b, $c", + [(set GPR:$dst, (sub GPR:$c, (mul GPR:$a, GPR:$b)))]>, + Requires<[IsARM, HasV6T2]>; + +// Extra precision multiplies with low / high results +let neverHasSideEffects = 1 in { +let isCommutable = 1 in { +def SMULL : AsMul1I<0b0000110, (outs GPR:$ldst, GPR:$hdst), + (ins GPR:$a, GPR:$b), IIC_iMUL64, + "smull", "\t$ldst, $hdst, $a, $b", []>; + +def UMULL : AsMul1I<0b0000100, (outs GPR:$ldst, GPR:$hdst), + (ins GPR:$a, GPR:$b), IIC_iMUL64, + "umull", "\t$ldst, $hdst, $a, $b", []>; +} + +// Multiply + accumulate +def SMLAL : AsMul1I<0b0000111, (outs GPR:$ldst, GPR:$hdst), + (ins GPR:$a, GPR:$b), IIC_iMAC64, + "smlal", "\t$ldst, $hdst, $a, $b", []>; + +def UMLAL : AsMul1I<0b0000101, (outs GPR:$ldst, GPR:$hdst), + (ins GPR:$a, GPR:$b), IIC_iMAC64, + "umlal", "\t$ldst, $hdst, $a, $b", []>; + +def UMAAL : AMul1I <0b0000010, (outs GPR:$ldst, GPR:$hdst), + (ins GPR:$a, GPR:$b), IIC_iMAC64, + "umaal", "\t$ldst, $hdst, $a, $b", []>, + Requires<[IsARM, HasV6]>; +} // neverHasSideEffects + +// Most significant word multiply +def SMMUL : AMul2I <0b0111010, (outs GPR:$dst), (ins GPR:$a, GPR:$b), + IIC_iMUL32, "smmul", "\t$dst, $a, $b", + [(set GPR:$dst, (mulhs GPR:$a, GPR:$b))]>, + Requires<[IsARM, HasV6]> { + let Inst{7-4} = 0b0001; + let Inst{15-12} = 0b1111; +} + +def SMMLA : AMul2I <0b0111010, (outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$c), + IIC_iMAC32, "smmla", "\t$dst, $a, $b, $c", + [(set GPR:$dst, (add (mulhs GPR:$a, GPR:$b), GPR:$c))]>, + Requires<[IsARM, HasV6]> { + let Inst{7-4} = 0b0001; +} + + +def SMMLS : AMul2I <0b0111010, (outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$c), + IIC_iMAC32, "smmls", "\t$dst, $a, $b, $c", + [(set GPR:$dst, (sub GPR:$c, (mulhs GPR:$a, GPR:$b)))]>, + Requires<[IsARM, HasV6]> { + let Inst{7-4} = 0b1101; +} + +multiclass AI_smul { + def BB : AMulxyI<0b0001011, (outs GPR:$dst), (ins GPR:$a, GPR:$b), + IIC_iMUL32, !strconcat(opc, "bb"), "\t$dst, $a, $b", + [(set GPR:$dst, (opnode (sext_inreg GPR:$a, i16), + (sext_inreg GPR:$b, i16)))]>, + Requires<[IsARM, HasV5TE]> { + let Inst{5} = 0; + let Inst{6} = 0; + } + + def BT : AMulxyI<0b0001011, (outs GPR:$dst), (ins GPR:$a, GPR:$b), + IIC_iMUL32, !strconcat(opc, "bt"), "\t$dst, $a, $b", + [(set GPR:$dst, (opnode (sext_inreg GPR:$a, i16), + (sra GPR:$b, (i32 16))))]>, + Requires<[IsARM, HasV5TE]> { + let Inst{5} = 0; + let Inst{6} = 1; + } + + def TB : AMulxyI<0b0001011, (outs GPR:$dst), (ins GPR:$a, GPR:$b), + IIC_iMUL32, !strconcat(opc, "tb"), "\t$dst, $a, $b", + [(set GPR:$dst, (opnode (sra GPR:$a, (i32 16)), + (sext_inreg GPR:$b, i16)))]>, + Requires<[IsARM, HasV5TE]> { + let Inst{5} = 1; + let Inst{6} = 0; + } + + def TT : AMulxyI<0b0001011, (outs GPR:$dst), (ins GPR:$a, GPR:$b), + IIC_iMUL32, !strconcat(opc, "tt"), "\t$dst, $a, $b", + [(set GPR:$dst, (opnode (sra GPR:$a, (i32 16)), + (sra GPR:$b, (i32 16))))]>, + Requires<[IsARM, HasV5TE]> { + let Inst{5} = 1; + let Inst{6} = 1; + } + + def WB : AMulxyI<0b0001001, (outs GPR:$dst), (ins GPR:$a, GPR:$b), + IIC_iMUL16, !strconcat(opc, "wb"), "\t$dst, $a, $b", + [(set GPR:$dst, (sra (opnode GPR:$a, + (sext_inreg GPR:$b, i16)), (i32 16)))]>, + Requires<[IsARM, HasV5TE]> { + let Inst{5} = 1; + let Inst{6} = 0; + } + + def WT : AMulxyI<0b0001001, (outs GPR:$dst), (ins GPR:$a, GPR:$b), + IIC_iMUL16, !strconcat(opc, "wt"), "\t$dst, $a, $b", + [(set GPR:$dst, (sra (opnode GPR:$a, + (sra GPR:$b, (i32 16))), (i32 16)))]>, + Requires<[IsARM, HasV5TE]> { + let Inst{5} = 1; + let Inst{6} = 1; + } +} + + +multiclass AI_smla { + def BB : AMulxyI<0b0001000, (outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$acc), + IIC_iMAC16, !strconcat(opc, "bb"), "\t$dst, $a, $b, $acc", + [(set GPR:$dst, (add GPR:$acc, + (opnode (sext_inreg GPR:$a, i16), + (sext_inreg GPR:$b, i16))))]>, + Requires<[IsARM, HasV5TE]> { + let Inst{5} = 0; + let Inst{6} = 0; + } + + def BT : AMulxyI<0b0001000, (outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$acc), + IIC_iMAC16, !strconcat(opc, "bt"), "\t$dst, $a, $b, $acc", + [(set GPR:$dst, (add GPR:$acc, (opnode (sext_inreg GPR:$a, i16), + (sra GPR:$b, (i32 16)))))]>, + Requires<[IsARM, HasV5TE]> { + let Inst{5} = 0; + let Inst{6} = 1; + } + + def TB : AMulxyI<0b0001000, (outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$acc), + IIC_iMAC16, !strconcat(opc, "tb"), "\t$dst, $a, $b, $acc", + [(set GPR:$dst, (add GPR:$acc, (opnode (sra GPR:$a, (i32 16)), + (sext_inreg GPR:$b, i16))))]>, + Requires<[IsARM, HasV5TE]> { + let Inst{5} = 1; + let Inst{6} = 0; + } + + def TT : AMulxyI<0b0001000, (outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$acc), + IIC_iMAC16, !strconcat(opc, "tt"), "\t$dst, $a, $b, $acc", + [(set GPR:$dst, (add GPR:$acc, (opnode (sra GPR:$a, (i32 16)), + (sra GPR:$b, (i32 16)))))]>, + Requires<[IsARM, HasV5TE]> { + let Inst{5} = 1; + let Inst{6} = 1; + } + + def WB : AMulxyI<0b0001001, (outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$acc), + IIC_iMAC16, !strconcat(opc, "wb"), "\t$dst, $a, $b, $acc", + [(set GPR:$dst, (add GPR:$acc, (sra (opnode GPR:$a, + (sext_inreg GPR:$b, i16)), (i32 16))))]>, + Requires<[IsARM, HasV5TE]> { + let Inst{5} = 0; + let Inst{6} = 0; + } + + def WT : AMulxyI<0b0001001, (outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$acc), + IIC_iMAC16, !strconcat(opc, "wt"), "\t$dst, $a, $b, $acc", + [(set GPR:$dst, (add GPR:$acc, (sra (opnode GPR:$a, + (sra GPR:$b, (i32 16))), (i32 16))))]>, + Requires<[IsARM, HasV5TE]> { + let Inst{5} = 0; + let Inst{6} = 1; + } +} + +defm SMUL : AI_smul<"smul", BinOpFrag<(mul node:$LHS, node:$RHS)>>; +defm SMLA : AI_smla<"smla", BinOpFrag<(mul node:$LHS, node:$RHS)>>; + +// TODO: Halfword multiple accumulate long: SMLAL +// TODO: Dual halfword multiple: SMUAD, SMUSD, SMLAD, SMLSD, SMLALD, SMLSLD + +//===----------------------------------------------------------------------===// +// Misc. Arithmetic Instructions. +// + +def CLZ : AMiscA1I<0b000010110, (outs GPR:$dst), (ins GPR:$src), IIC_iUNAr, + "clz", "\t$dst, $src", + [(set GPR:$dst, (ctlz GPR:$src))]>, Requires<[IsARM, HasV5T]> { + let Inst{7-4} = 0b0001; + let Inst{11-8} = 0b1111; + let Inst{19-16} = 0b1111; +} + +def REV : AMiscA1I<0b01101011, (outs GPR:$dst), (ins GPR:$src), IIC_iUNAr, + "rev", "\t$dst, $src", + [(set GPR:$dst, (bswap GPR:$src))]>, Requires<[IsARM, HasV6]> { + let Inst{7-4} = 0b0011; + let Inst{11-8} = 0b1111; + let Inst{19-16} = 0b1111; +} + +def REV16 : AMiscA1I<0b01101011, (outs GPR:$dst), (ins GPR:$src), IIC_iUNAr, + "rev16", "\t$dst, $src", + [(set GPR:$dst, + (or (and (srl GPR:$src, (i32 8)), 0xFF), + (or (and (shl GPR:$src, (i32 8)), 0xFF00), + (or (and (srl GPR:$src, (i32 8)), 0xFF0000), + (and (shl GPR:$src, (i32 8)), 0xFF000000)))))]>, + Requires<[IsARM, HasV6]> { + let Inst{7-4} = 0b1011; + let Inst{11-8} = 0b1111; + let Inst{19-16} = 0b1111; +} + +def REVSH : AMiscA1I<0b01101111, (outs GPR:$dst), (ins GPR:$src), IIC_iUNAr, + "revsh", "\t$dst, $src", + [(set GPR:$dst, + (sext_inreg + (or (srl (and GPR:$src, 0xFF00), (i32 8)), + (shl GPR:$src, (i32 8))), i16))]>, + Requires<[IsARM, HasV6]> { + let Inst{7-4} = 0b1011; + let Inst{11-8} = 0b1111; + let Inst{19-16} = 0b1111; +} + +def PKHBT : AMiscA1I<0b01101000, (outs GPR:$dst), + (ins GPR:$src1, GPR:$src2, i32imm:$shamt), + IIC_iALUsi, "pkhbt", "\t$dst, $src1, $src2, LSL $shamt", + [(set GPR:$dst, (or (and GPR:$src1, 0xFFFF), + (and (shl GPR:$src2, (i32 imm:$shamt)), + 0xFFFF0000)))]>, + Requires<[IsARM, HasV6]> { + let Inst{6-4} = 0b001; +} + +// Alternate cases for PKHBT where identities eliminate some nodes. +def : ARMV6Pat<(or (and GPR:$src1, 0xFFFF), (and GPR:$src2, 0xFFFF0000)), + (PKHBT GPR:$src1, GPR:$src2, 0)>; +def : ARMV6Pat<(or (and GPR:$src1, 0xFFFF), (shl GPR:$src2, imm16_31:$shamt)), + (PKHBT GPR:$src1, GPR:$src2, imm16_31:$shamt)>; + + +def PKHTB : AMiscA1I<0b01101000, (outs GPR:$dst), + (ins GPR:$src1, GPR:$src2, i32imm:$shamt), + IIC_iALUsi, "pkhtb", "\t$dst, $src1, $src2, ASR $shamt", + [(set GPR:$dst, (or (and GPR:$src1, 0xFFFF0000), + (and (sra GPR:$src2, imm16_31:$shamt), + 0xFFFF)))]>, Requires<[IsARM, HasV6]> { + let Inst{6-4} = 0b101; +} + +// Alternate cases for PKHTB where identities eliminate some nodes. Note that +// a shift amount of 0 is *not legal* here, it is PKHBT instead. +def : ARMV6Pat<(or (and GPR:$src1, 0xFFFF0000), (srl GPR:$src2, (i32 16))), + (PKHTB GPR:$src1, GPR:$src2, 16)>; +def : ARMV6Pat<(or (and GPR:$src1, 0xFFFF0000), + (and (srl GPR:$src2, imm1_15:$shamt), 0xFFFF)), + (PKHTB GPR:$src1, GPR:$src2, imm1_15:$shamt)>; + +//===----------------------------------------------------------------------===// +// Comparison Instructions... +// + +defm CMP : AI1_cmp_irs<0b1010, "cmp", + BinOpFrag<(ARMcmp node:$LHS, node:$RHS)>>; +defm CMN : AI1_cmp_irs<0b1011, "cmn", + BinOpFrag<(ARMcmp node:$LHS,(ineg node:$RHS))>>; + +// Note that TST/TEQ don't set all the same flags that CMP does! +defm TST : AI1_cmp_irs<0b1000, "tst", + BinOpFrag<(ARMcmpZ (and node:$LHS, node:$RHS), 0)>, 1>; +defm TEQ : AI1_cmp_irs<0b1001, "teq", + BinOpFrag<(ARMcmpZ (xor node:$LHS, node:$RHS), 0)>, 1>; + +defm CMPz : AI1_cmp_irs<0b1010, "cmp", + BinOpFrag<(ARMcmpZ node:$LHS, node:$RHS)>>; +defm CMNz : AI1_cmp_irs<0b1011, "cmn", + BinOpFrag<(ARMcmpZ node:$LHS,(ineg node:$RHS))>>; + +def : ARMPat<(ARMcmp GPR:$src, so_imm_neg:$imm), + (CMNri GPR:$src, so_imm_neg:$imm)>; + +def : ARMPat<(ARMcmpZ GPR:$src, so_imm_neg:$imm), + (CMNri GPR:$src, so_imm_neg:$imm)>; + + +// Conditional moves +// FIXME: should be able to write a pattern for ARMcmov, but can't use +// a two-value operand where a dag node expects two operands. :( +def MOVCCr : AI1<0b1101, (outs GPR:$dst), (ins GPR:$false, GPR:$true), DPFrm, + IIC_iCMOVr, "mov", "\t$dst, $true", + [/*(set GPR:$dst, (ARMcmov GPR:$false, GPR:$true, imm:$cc, CCR:$ccr))*/]>, + RegConstraint<"$false = $dst">, UnaryDP { + let Inst{11-4} = 0b00000000; + let Inst{25} = 0; +} + +def MOVCCs : AI1<0b1101, (outs GPR:$dst), + (ins GPR:$false, so_reg:$true), DPSoRegFrm, IIC_iCMOVsr, + "mov", "\t$dst, $true", + [/*(set GPR:$dst, (ARMcmov GPR:$false, so_reg:$true, imm:$cc, CCR:$ccr))*/]>, + RegConstraint<"$false = $dst">, UnaryDP { + let Inst{25} = 0; +} + +def MOVCCi : AI1<0b1101, (outs GPR:$dst), + (ins GPR:$false, so_imm:$true), DPFrm, IIC_iCMOVi, + "mov", "\t$dst, $true", + [/*(set GPR:$dst, (ARMcmov GPR:$false, so_imm:$true, imm:$cc, CCR:$ccr))*/]>, + RegConstraint<"$false = $dst">, UnaryDP { + let Inst{25} = 1; +} + + +//===----------------------------------------------------------------------===// +// TLS Instructions +// + +// __aeabi_read_tp preserves the registers r1-r3. +let isCall = 1, + Defs = [R0, R12, LR, CPSR] in { + def TPsoft : ABXI<0b1011, (outs), (ins), IIC_Br, + "bl\t__aeabi_read_tp", + [(set R0, ARMthread_pointer)]>; +} + +//===----------------------------------------------------------------------===// +// SJLJ Exception handling intrinsics +// eh_sjlj_setjmp() is an instruction sequence to store the return +// address and save #0 in R0 for the non-longjmp case. +// Since by its nature we may be coming from some other function to get +// here, and we're using the stack frame for the containing function to +// save/restore registers, we can't keep anything live in regs across +// the eh_sjlj_setjmp(), else it will almost certainly have been tromped upon +// when we get here from a longjmp(). We force everthing out of registers +// except for our own input by listing the relevant registers in Defs. By +// doing so, we also cause the prologue/epilogue code to actively preserve +// all of the callee-saved resgisters, which is exactly what we want. +let Defs = + [ R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, LR, D0, + D1, D2, D3, D4, D5, D6, D7, D8, D9, D10, D11, D12, D13, D14, D15, + D16, D17, D18, D19, D20, D21, D22, D23, D24, D25, D26, D27, D28, D29, D30, + D31 ] in { + def Int_eh_sjlj_setjmp : XI<(outs), (ins GPR:$src), + AddrModeNone, SizeSpecial, IndexModeNone, + Pseudo, NoItinerary, + "str\tsp, [$src, #+8] @ eh_setjmp begin\n\t" + "add\tr12, pc, #8\n\t" + "str\tr12, [$src, #+4]\n\t" + "mov\tr0, #0\n\t" + "add\tpc, pc, #0\n\t" + "mov\tr0, #1 @ eh_setjmp end", "", + [(set R0, (ARMeh_sjlj_setjmp GPR:$src))]>; +} + +//===----------------------------------------------------------------------===// +// Non-Instruction Patterns +// + +// Large immediate handling. + +// Two piece so_imms. +let isReMaterializable = 1 in +def MOVi2pieces : AI1x2<(outs GPR:$dst), (ins so_imm2part:$src), + Pseudo, IIC_iMOVi, + "mov", "\t$dst, $src", + [(set GPR:$dst, so_imm2part:$src)]>, + Requires<[IsARM, NoV6T2]>; + +def : ARMPat<(or GPR:$LHS, so_imm2part:$RHS), + (ORRri (ORRri GPR:$LHS, (so_imm2part_1 imm:$RHS)), + (so_imm2part_2 imm:$RHS))>; +def : ARMPat<(xor GPR:$LHS, so_imm2part:$RHS), + (EORri (EORri GPR:$LHS, (so_imm2part_1 imm:$RHS)), + (so_imm2part_2 imm:$RHS))>; +def : ARMPat<(add GPR:$LHS, so_imm2part:$RHS), + (ADDri (ADDri GPR:$LHS, (so_imm2part_1 imm:$RHS)), + (so_imm2part_2 imm:$RHS))>; +def : ARMPat<(add GPR:$LHS, so_neg_imm2part:$RHS), + (SUBri (SUBri GPR:$LHS, (so_neg_imm2part_1 imm:$RHS)), + (so_neg_imm2part_2 imm:$RHS))>; + +// 32-bit immediate using movw + movt. +// This is a single pseudo instruction, the benefit is that it can be remat'd +// as a single unit instead of having to handle reg inputs. +// FIXME: Remove this when we can do generalized remat. +let isReMaterializable = 1 in +def MOVi32imm : AI1x2<(outs GPR:$dst), (ins i32imm:$src), Pseudo, IIC_iMOVi, + "movw", "\t$dst, ${src:lo16}\n\tmovt${p}\t$dst, ${src:hi16}", + [(set GPR:$dst, (i32 imm:$src))]>, + Requires<[IsARM, HasV6T2]>; + +// ConstantPool, GlobalAddress, and JumpTable +def : ARMPat<(ARMWrapper tglobaladdr :$dst), (LEApcrel tglobaladdr :$dst)>, + Requires<[IsARM, DontUseMovt]>; +def : ARMPat<(ARMWrapper tconstpool :$dst), (LEApcrel tconstpool :$dst)>; +def : ARMPat<(ARMWrapper tglobaladdr :$dst), (MOVi32imm tglobaladdr :$dst)>, + Requires<[IsARM, UseMovt]>; +def : ARMPat<(ARMWrapperJT tjumptable:$dst, imm:$id), + (LEApcrelJT tjumptable:$dst, imm:$id)>; + +// TODO: add,sub,and, 3-instr forms? + + +// Direct calls +def : ARMPat<(ARMcall texternalsym:$func), (BL texternalsym:$func)>, + Requires<[IsARM, IsNotDarwin]>; +def : ARMPat<(ARMcall texternalsym:$func), (BLr9 texternalsym:$func)>, + Requires<[IsARM, IsDarwin]>; + +// zextload i1 -> zextload i8 +def : ARMPat<(zextloadi1 addrmode2:$addr), (LDRB addrmode2:$addr)>; + +// extload -> zextload +def : ARMPat<(extloadi1 addrmode2:$addr), (LDRB addrmode2:$addr)>; +def : ARMPat<(extloadi8 addrmode2:$addr), (LDRB addrmode2:$addr)>; +def : ARMPat<(extloadi16 addrmode3:$addr), (LDRH addrmode3:$addr)>; + +def : ARMPat<(extloadi8 addrmodepc:$addr), (PICLDRB addrmodepc:$addr)>; +def : ARMPat<(extloadi16 addrmodepc:$addr), (PICLDRH addrmodepc:$addr)>; + +// smul* and smla* +def : ARMV5TEPat<(mul (sra (shl GPR:$a, (i32 16)), (i32 16)), + (sra (shl GPR:$b, (i32 16)), (i32 16))), + (SMULBB GPR:$a, GPR:$b)>; +def : ARMV5TEPat<(mul sext_16_node:$a, sext_16_node:$b), + (SMULBB GPR:$a, GPR:$b)>; +def : ARMV5TEPat<(mul (sra (shl GPR:$a, (i32 16)), (i32 16)), + (sra GPR:$b, (i32 16))), + (SMULBT GPR:$a, GPR:$b)>; +def : ARMV5TEPat<(mul sext_16_node:$a, (sra GPR:$b, (i32 16))), + (SMULBT GPR:$a, GPR:$b)>; +def : ARMV5TEPat<(mul (sra GPR:$a, (i32 16)), + (sra (shl GPR:$b, (i32 16)), (i32 16))), + (SMULTB GPR:$a, GPR:$b)>; +def : ARMV5TEPat<(mul (sra GPR:$a, (i32 16)), sext_16_node:$b), + (SMULTB GPR:$a, GPR:$b)>; +def : ARMV5TEPat<(sra (mul GPR:$a, (sra (shl GPR:$b, (i32 16)), (i32 16))), + (i32 16)), + (SMULWB GPR:$a, GPR:$b)>; +def : ARMV5TEPat<(sra (mul GPR:$a, sext_16_node:$b), (i32 16)), + (SMULWB GPR:$a, GPR:$b)>; + +def : ARMV5TEPat<(add GPR:$acc, + (mul (sra (shl GPR:$a, (i32 16)), (i32 16)), + (sra (shl GPR:$b, (i32 16)), (i32 16)))), + (SMLABB GPR:$a, GPR:$b, GPR:$acc)>; +def : ARMV5TEPat<(add GPR:$acc, + (mul sext_16_node:$a, sext_16_node:$b)), + (SMLABB GPR:$a, GPR:$b, GPR:$acc)>; +def : ARMV5TEPat<(add GPR:$acc, + (mul (sra (shl GPR:$a, (i32 16)), (i32 16)), + (sra GPR:$b, (i32 16)))), + (SMLABT GPR:$a, GPR:$b, GPR:$acc)>; +def : ARMV5TEPat<(add GPR:$acc, + (mul sext_16_node:$a, (sra GPR:$b, (i32 16)))), + (SMLABT GPR:$a, GPR:$b, GPR:$acc)>; +def : ARMV5TEPat<(add GPR:$acc, + (mul (sra GPR:$a, (i32 16)), + (sra (shl GPR:$b, (i32 16)), (i32 16)))), + (SMLATB GPR:$a, GPR:$b, GPR:$acc)>; +def : ARMV5TEPat<(add GPR:$acc, + (mul (sra GPR:$a, (i32 16)), sext_16_node:$b)), + (SMLATB GPR:$a, GPR:$b, GPR:$acc)>; +def : ARMV5TEPat<(add GPR:$acc, + (sra (mul GPR:$a, (sra (shl GPR:$b, (i32 16)), (i32 16))), + (i32 16))), + (SMLAWB GPR:$a, GPR:$b, GPR:$acc)>; +def : ARMV5TEPat<(add GPR:$acc, + (sra (mul GPR:$a, sext_16_node:$b), (i32 16))), + (SMLAWB GPR:$a, GPR:$b, GPR:$acc)>; + +//===----------------------------------------------------------------------===// +// Thumb Support +// + +include "ARMInstrThumb.td" + +//===----------------------------------------------------------------------===// +// Thumb2 Support +// + +include "ARMInstrThumb2.td" + +//===----------------------------------------------------------------------===// +// Floating Point Support +// + +include "ARMInstrVFP.td" + +//===----------------------------------------------------------------------===// +// Advanced SIMD (NEON) Support +// + +include "ARMInstrNEON.td" diff --git a/libclamav/c++/llvm/lib/Target/ARM/ARMInstrNEON.td b/libclamav/c++/llvm/lib/Target/ARM/ARMInstrNEON.td new file mode 100644 index 000000000..a4fe75236 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/ARM/ARMInstrNEON.td @@ -0,0 +1,3204 @@ +//===- ARMInstrNEON.td - NEON support for ARM -----------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file describes the ARM NEON instruction set. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// NEON-specific DAG Nodes. +//===----------------------------------------------------------------------===// + +def SDTARMVCMP : SDTypeProfile<1, 2, [SDTCisInt<0>, SDTCisSameAs<1, 2>]>; + +def NEONvceq : SDNode<"ARMISD::VCEQ", SDTARMVCMP>; +def NEONvcge : SDNode<"ARMISD::VCGE", SDTARMVCMP>; +def NEONvcgeu : SDNode<"ARMISD::VCGEU", SDTARMVCMP>; +def NEONvcgt : SDNode<"ARMISD::VCGT", SDTARMVCMP>; +def NEONvcgtu : SDNode<"ARMISD::VCGTU", SDTARMVCMP>; +def NEONvtst : SDNode<"ARMISD::VTST", SDTARMVCMP>; + +// Types for vector shift by immediates. The "SHX" version is for long and +// narrow operations where the source and destination vectors have different +// types. The "SHINS" version is for shift and insert operations. +def SDTARMVSH : SDTypeProfile<1, 2, [SDTCisInt<0>, SDTCisSameAs<0, 1>, + SDTCisVT<2, i32>]>; +def SDTARMVSHX : SDTypeProfile<1, 2, [SDTCisInt<0>, SDTCisInt<1>, + SDTCisVT<2, i32>]>; +def SDTARMVSHINS : SDTypeProfile<1, 3, [SDTCisInt<0>, SDTCisSameAs<0, 1>, + SDTCisSameAs<0, 2>, SDTCisVT<3, i32>]>; + +def NEONvshl : SDNode<"ARMISD::VSHL", SDTARMVSH>; +def NEONvshrs : SDNode<"ARMISD::VSHRs", SDTARMVSH>; +def NEONvshru : SDNode<"ARMISD::VSHRu", SDTARMVSH>; +def NEONvshlls : SDNode<"ARMISD::VSHLLs", SDTARMVSHX>; +def NEONvshllu : SDNode<"ARMISD::VSHLLu", SDTARMVSHX>; +def NEONvshlli : SDNode<"ARMISD::VSHLLi", SDTARMVSHX>; +def NEONvshrn : SDNode<"ARMISD::VSHRN", SDTARMVSHX>; + +def NEONvrshrs : SDNode<"ARMISD::VRSHRs", SDTARMVSH>; +def NEONvrshru : SDNode<"ARMISD::VRSHRu", SDTARMVSH>; +def NEONvrshrn : SDNode<"ARMISD::VRSHRN", SDTARMVSHX>; + +def NEONvqshls : SDNode<"ARMISD::VQSHLs", SDTARMVSH>; +def NEONvqshlu : SDNode<"ARMISD::VQSHLu", SDTARMVSH>; +def NEONvqshlsu : SDNode<"ARMISD::VQSHLsu", SDTARMVSH>; +def NEONvqshrns : SDNode<"ARMISD::VQSHRNs", SDTARMVSHX>; +def NEONvqshrnu : SDNode<"ARMISD::VQSHRNu", SDTARMVSHX>; +def NEONvqshrnsu : SDNode<"ARMISD::VQSHRNsu", SDTARMVSHX>; + +def NEONvqrshrns : SDNode<"ARMISD::VQRSHRNs", SDTARMVSHX>; +def NEONvqrshrnu : SDNode<"ARMISD::VQRSHRNu", SDTARMVSHX>; +def NEONvqrshrnsu : SDNode<"ARMISD::VQRSHRNsu", SDTARMVSHX>; + +def NEONvsli : SDNode<"ARMISD::VSLI", SDTARMVSHINS>; +def NEONvsri : SDNode<"ARMISD::VSRI", SDTARMVSHINS>; + +def SDTARMVGETLN : SDTypeProfile<1, 2, [SDTCisVT<0, i32>, SDTCisInt<1>, + SDTCisVT<2, i32>]>; +def NEONvgetlaneu : SDNode<"ARMISD::VGETLANEu", SDTARMVGETLN>; +def NEONvgetlanes : SDNode<"ARMISD::VGETLANEs", SDTARMVGETLN>; + +def NEONvdup : SDNode<"ARMISD::VDUP", SDTypeProfile<1, 1, [SDTCisVec<0>]>>; + +// VDUPLANE can produce a quad-register result from a double-register source, +// so the result is not constrained to match the source. +def NEONvduplane : SDNode<"ARMISD::VDUPLANE", + SDTypeProfile<1, 2, [SDTCisVec<0>, SDTCisVec<1>, + SDTCisVT<2, i32>]>>; + +def SDTARMVEXT : SDTypeProfile<1, 3, [SDTCisVec<0>, SDTCisSameAs<0, 1>, + SDTCisSameAs<0, 2>, SDTCisVT<3, i32>]>; +def NEONvext : SDNode<"ARMISD::VEXT", SDTARMVEXT>; + +def SDTARMVSHUF : SDTypeProfile<1, 1, [SDTCisVec<0>, SDTCisSameAs<0, 1>]>; +def NEONvrev64 : SDNode<"ARMISD::VREV64", SDTARMVSHUF>; +def NEONvrev32 : SDNode<"ARMISD::VREV32", SDTARMVSHUF>; +def NEONvrev16 : SDNode<"ARMISD::VREV16", SDTARMVSHUF>; + +def SDTARMVSHUF2 : SDTypeProfile<2, 2, [SDTCisVec<0>, SDTCisSameAs<0, 1>, + SDTCisSameAs<0, 2>, SDTCisSameAs<0, 3>]>; +def NEONzip : SDNode<"ARMISD::VZIP", SDTARMVSHUF2>; +def NEONuzp : SDNode<"ARMISD::VUZP", SDTARMVSHUF2>; +def NEONtrn : SDNode<"ARMISD::VTRN", SDTARMVSHUF2>; + +//===----------------------------------------------------------------------===// +// NEON operand definitions +//===----------------------------------------------------------------------===// + +// addrmode_neonldstm := reg +// +/* TODO: Take advantage of vldm. +def addrmode_neonldstm : Operand, + ComplexPattern { + let PrintMethod = "printAddrNeonLdStMOperand"; + let MIOperandInfo = (ops GPR, i32imm); +} +*/ + +def h8imm : Operand { + let PrintMethod = "printHex8ImmOperand"; +} +def h16imm : Operand { + let PrintMethod = "printHex16ImmOperand"; +} +def h32imm : Operand { + let PrintMethod = "printHex32ImmOperand"; +} +def h64imm : Operand { + let PrintMethod = "printHex64ImmOperand"; +} + +//===----------------------------------------------------------------------===// +// NEON load / store instructions +//===----------------------------------------------------------------------===// + +/* TODO: Take advantage of vldm. +let mayLoad = 1, hasExtraDefRegAllocReq = 1 in { +def VLDMD : NI<(outs), + (ins addrmode_neonldstm:$addr, reglist:$dst1, variable_ops), + IIC_fpLoadm, + "vldm", "${addr:submode} ${addr:base}, $dst1", + []> { + let Inst{27-25} = 0b110; + let Inst{20} = 1; + let Inst{11-9} = 0b101; +} + +def VLDMS : NI<(outs), + (ins addrmode_neonldstm:$addr, reglist:$dst1, variable_ops), + IIC_fpLoadm, + "vldm", "${addr:submode} ${addr:base}, $dst1", + []> { + let Inst{27-25} = 0b110; + let Inst{20} = 1; + let Inst{11-9} = 0b101; +} +} +*/ + +// Use vldmia to load a Q register as a D register pair. +def VLDRQ : NI4<(outs QPR:$dst), (ins addrmode4:$addr), + IIC_fpLoadm, + "vldmia", "$addr, ${dst:dregpair}", + [(set QPR:$dst, (v2f64 (load addrmode4:$addr)))]> { + let Inst{27-25} = 0b110; + let Inst{24} = 0; // P bit + let Inst{23} = 1; // U bit + let Inst{20} = 1; + let Inst{11-9} = 0b101; +} + +// Use vstmia to store a Q register as a D register pair. +def VSTRQ : NI4<(outs), (ins QPR:$src, addrmode4:$addr), + IIC_fpStorem, + "vstmia", "$addr, ${src:dregpair}", + [(store (v2f64 QPR:$src), addrmode4:$addr)]> { + let Inst{27-25} = 0b110; + let Inst{24} = 0; // P bit + let Inst{23} = 1; // U bit + let Inst{20} = 0; + let Inst{11-9} = 0b101; +} + +// VLD1 : Vector Load (multiple single elements) +class VLD1D op7_4, string OpcodeStr, string Dt, + ValueType Ty, Intrinsic IntOp> + : NLdSt<0,0b10,0b0111,op7_4, (outs DPR:$dst), (ins addrmode6:$addr), IIC_VLD1, + OpcodeStr, Dt, "\\{$dst\\}, $addr", "", + [(set DPR:$dst, (Ty (IntOp addrmode6:$addr)))]>; +class VLD1Q op7_4, string OpcodeStr, string Dt, + ValueType Ty, Intrinsic IntOp> + : NLdSt<0,0b10,0b1010,op7_4, (outs QPR:$dst), (ins addrmode6:$addr), IIC_VLD1, + OpcodeStr, Dt, "${dst:dregpair}, $addr", "", + [(set QPR:$dst, (Ty (IntOp addrmode6:$addr)))]>; + +def VLD1d8 : VLD1D<0b0000, "vld1", "8", v8i8, int_arm_neon_vld1>; +def VLD1d16 : VLD1D<0b0100, "vld1", "16", v4i16, int_arm_neon_vld1>; +def VLD1d32 : VLD1D<0b1000, "vld1", "32", v2i32, int_arm_neon_vld1>; +def VLD1df : VLD1D<0b1000, "vld1", "32", v2f32, int_arm_neon_vld1>; +def VLD1d64 : VLD1D<0b1100, "vld1", "64", v1i64, int_arm_neon_vld1>; + +def VLD1q8 : VLD1Q<0b0000, "vld1", "8", v16i8, int_arm_neon_vld1>; +def VLD1q16 : VLD1Q<0b0100, "vld1", "16", v8i16, int_arm_neon_vld1>; +def VLD1q32 : VLD1Q<0b1000, "vld1", "32", v4i32, int_arm_neon_vld1>; +def VLD1qf : VLD1Q<0b1000, "vld1", "32", v4f32, int_arm_neon_vld1>; +def VLD1q64 : VLD1Q<0b1100, "vld1", "64", v2i64, int_arm_neon_vld1>; + +let mayLoad = 1, hasExtraDefRegAllocReq = 1 in { + +// VLD2 : Vector Load (multiple 2-element structures) +class VLD2D op7_4, string OpcodeStr, string Dt> + : NLdSt<0,0b10,0b1000,op7_4, (outs DPR:$dst1, DPR:$dst2), + (ins addrmode6:$addr), IIC_VLD2, + OpcodeStr, Dt, "\\{$dst1,$dst2\\}, $addr", "", []>; +class VLD2Q op7_4, string OpcodeStr, string Dt> + : NLdSt<0,0b10,0b0011,op7_4, + (outs DPR:$dst1, DPR:$dst2, DPR:$dst3, DPR:$dst4), + (ins addrmode6:$addr), IIC_VLD2, + OpcodeStr, Dt, "\\{$dst1,$dst2,$dst3,$dst4\\}, $addr", + "", []>; + +def VLD2d8 : VLD2D<0b0000, "vld2", "8">; +def VLD2d16 : VLD2D<0b0100, "vld2", "16">; +def VLD2d32 : VLD2D<0b1000, "vld2", "32">; +def VLD2d64 : NLdSt<0,0b10,0b1010,0b1100, (outs DPR:$dst1, DPR:$dst2), + (ins addrmode6:$addr), IIC_VLD1, + "vld1", "64", "\\{$dst1,$dst2\\}, $addr", "", []>; + +def VLD2q8 : VLD2Q<0b0000, "vld2", "8">; +def VLD2q16 : VLD2Q<0b0100, "vld2", "16">; +def VLD2q32 : VLD2Q<0b1000, "vld2", "32">; + +// VLD3 : Vector Load (multiple 3-element structures) +class VLD3D op7_4, string OpcodeStr, string Dt> + : NLdSt<0,0b10,0b0100,op7_4, (outs DPR:$dst1, DPR:$dst2, DPR:$dst3), + (ins addrmode6:$addr), IIC_VLD3, + OpcodeStr, Dt, "\\{$dst1,$dst2,$dst3\\}, $addr", "", []>; +class VLD3WB op7_4, string OpcodeStr, string Dt> + : NLdSt<0,0b10,0b0101,op7_4, (outs DPR:$dst1, DPR:$dst2, DPR:$dst3, GPR:$wb), + (ins addrmode6:$addr), IIC_VLD3, + OpcodeStr, Dt, "\\{$dst1,$dst2,$dst3\\}, $addr", + "$addr.addr = $wb", []>; + +def VLD3d8 : VLD3D<0b0000, "vld3", "8">; +def VLD3d16 : VLD3D<0b0100, "vld3", "16">; +def VLD3d32 : VLD3D<0b1000, "vld3", "32">; +def VLD3d64 : NLdSt<0,0b10,0b0110,0b1100, + (outs DPR:$dst1, DPR:$dst2, DPR:$dst3), + (ins addrmode6:$addr), IIC_VLD1, + "vld1", "64", "\\{$dst1,$dst2,$dst3\\}, $addr", "", []>; + +// vld3 to double-spaced even registers. +def VLD3q8a : VLD3WB<0b0000, "vld3", "8">; +def VLD3q16a : VLD3WB<0b0100, "vld3", "16">; +def VLD3q32a : VLD3WB<0b1000, "vld3", "32">; + +// vld3 to double-spaced odd registers. +def VLD3q8b : VLD3WB<0b0000, "vld3", "8">; +def VLD3q16b : VLD3WB<0b0100, "vld3", "16">; +def VLD3q32b : VLD3WB<0b1000, "vld3", "32">; + +// VLD4 : Vector Load (multiple 4-element structures) +class VLD4D op7_4, string OpcodeStr, string Dt> + : NLdSt<0,0b10,0b0000,op7_4, + (outs DPR:$dst1, DPR:$dst2, DPR:$dst3, DPR:$dst4), + (ins addrmode6:$addr), IIC_VLD4, + OpcodeStr, Dt, "\\{$dst1,$dst2,$dst3,$dst4\\}, $addr", + "", []>; +class VLD4WB op7_4, string OpcodeStr, string Dt> + : NLdSt<0,0b10,0b0001,op7_4, + (outs DPR:$dst1, DPR:$dst2, DPR:$dst3, DPR:$dst4, GPR:$wb), + (ins addrmode6:$addr), IIC_VLD4, + OpcodeStr, Dt, "\\{$dst1,$dst2,$dst3,$dst4\\}, $addr", + "$addr.addr = $wb", []>; + +def VLD4d8 : VLD4D<0b0000, "vld4", "8">; +def VLD4d16 : VLD4D<0b0100, "vld4", "16">; +def VLD4d32 : VLD4D<0b1000, "vld4", "32">; +def VLD4d64 : NLdSt<0,0b10,0b0010,0b1100, + (outs DPR:$dst1, DPR:$dst2, DPR:$dst3, DPR:$dst4), + (ins addrmode6:$addr), IIC_VLD1, + "vld1", "64", "\\{$dst1,$dst2,$dst3,$dst4\\}, $addr", "", []>; + +// vld4 to double-spaced even registers. +def VLD4q8a : VLD4WB<0b0000, "vld4", "8">; +def VLD4q16a : VLD4WB<0b0100, "vld4", "16">; +def VLD4q32a : VLD4WB<0b1000, "vld4", "32">; + +// vld4 to double-spaced odd registers. +def VLD4q8b : VLD4WB<0b0000, "vld4", "8">; +def VLD4q16b : VLD4WB<0b0100, "vld4", "16">; +def VLD4q32b : VLD4WB<0b1000, "vld4", "32">; + +// VLD1LN : Vector Load (single element to one lane) +// FIXME: Not yet implemented. + +// VLD2LN : Vector Load (single 2-element structure to one lane) +class VLD2LN op11_8, string OpcodeStr, string Dt> + : NLdSt<1,0b10,op11_8,{?,?,?,?}, (outs DPR:$dst1, DPR:$dst2), + (ins addrmode6:$addr, DPR:$src1, DPR:$src2, nohash_imm:$lane), + IIC_VLD2, + OpcodeStr, Dt, "\\{$dst1[$lane],$dst2[$lane]\\}, $addr", + "$src1 = $dst1, $src2 = $dst2", []>; + +// vld2 to single-spaced registers. +def VLD2LNd8 : VLD2LN<0b0001, "vld2", "8">; +def VLD2LNd16 : VLD2LN<0b0101, "vld2", "16"> { + let Inst{5} = 0; +} +def VLD2LNd32 : VLD2LN<0b1001, "vld2", "32"> { + let Inst{6} = 0; +} + +// vld2 to double-spaced even registers. +def VLD2LNq16a: VLD2LN<0b0101, "vld2", "16"> { + let Inst{5} = 1; +} +def VLD2LNq32a: VLD2LN<0b1001, "vld2", "32"> { + let Inst{6} = 1; +} + +// vld2 to double-spaced odd registers. +def VLD2LNq16b: VLD2LN<0b0101, "vld2", "16"> { + let Inst{5} = 1; +} +def VLD2LNq32b: VLD2LN<0b1001, "vld2", "32"> { + let Inst{6} = 1; +} + +// VLD3LN : Vector Load (single 3-element structure to one lane) +class VLD3LN op11_8, string OpcodeStr, string Dt> + : NLdSt<1,0b10,op11_8,{?,?,?,?}, (outs DPR:$dst1, DPR:$dst2, DPR:$dst3), + (ins addrmode6:$addr, DPR:$src1, DPR:$src2, DPR:$src3, + nohash_imm:$lane), IIC_VLD3, + OpcodeStr, Dt, + "\\{$dst1[$lane],$dst2[$lane],$dst3[$lane]\\}, $addr", + "$src1 = $dst1, $src2 = $dst2, $src3 = $dst3", []>; + +// vld3 to single-spaced registers. +def VLD3LNd8 : VLD3LN<0b0010, "vld3", "8"> { + let Inst{4} = 0; +} +def VLD3LNd16 : VLD3LN<0b0110, "vld3", "16"> { + let Inst{5-4} = 0b00; +} +def VLD3LNd32 : VLD3LN<0b1010, "vld3", "32"> { + let Inst{6-4} = 0b000; +} + +// vld3 to double-spaced even registers. +def VLD3LNq16a: VLD3LN<0b0110, "vld3", "16"> { + let Inst{5-4} = 0b10; +} +def VLD3LNq32a: VLD3LN<0b1010, "vld3", "32"> { + let Inst{6-4} = 0b100; +} + +// vld3 to double-spaced odd registers. +def VLD3LNq16b: VLD3LN<0b0110, "vld3", "16"> { + let Inst{5-4} = 0b10; +} +def VLD3LNq32b: VLD3LN<0b1010, "vld3", "32"> { + let Inst{6-4} = 0b100; +} + +// VLD4LN : Vector Load (single 4-element structure to one lane) +class VLD4LN op11_8, string OpcodeStr, string Dt> + : NLdSt<1,0b10,op11_8,{?,?,?,?}, + (outs DPR:$dst1, DPR:$dst2, DPR:$dst3, DPR:$dst4), + (ins addrmode6:$addr, DPR:$src1, DPR:$src2, DPR:$src3, DPR:$src4, + nohash_imm:$lane), IIC_VLD4, + OpcodeStr, Dt, + "\\{$dst1[$lane],$dst2[$lane],$dst3[$lane],$dst4[$lane]\\}, $addr", + "$src1 = $dst1, $src2 = $dst2, $src3 = $dst3, $src4 = $dst4", []>; + +// vld4 to single-spaced registers. +def VLD4LNd8 : VLD4LN<0b0011, "vld4", "8">; +def VLD4LNd16 : VLD4LN<0b0111, "vld4", "16"> { + let Inst{5} = 0; +} +def VLD4LNd32 : VLD4LN<0b1011, "vld4", "32"> { + let Inst{6} = 0; +} + +// vld4 to double-spaced even registers. +def VLD4LNq16a: VLD4LN<0b0111, "vld4", "16"> { + let Inst{5} = 1; +} +def VLD4LNq32a: VLD4LN<0b1011, "vld4", "32"> { + let Inst{6} = 1; +} + +// vld4 to double-spaced odd registers. +def VLD4LNq16b: VLD4LN<0b0111, "vld4", "16"> { + let Inst{5} = 1; +} +def VLD4LNq32b: VLD4LN<0b1011, "vld4", "32"> { + let Inst{6} = 1; +} + +// VLD1DUP : Vector Load (single element to all lanes) +// VLD2DUP : Vector Load (single 2-element structure to all lanes) +// VLD3DUP : Vector Load (single 3-element structure to all lanes) +// VLD4DUP : Vector Load (single 4-element structure to all lanes) +// FIXME: Not yet implemented. +} // mayLoad = 1, hasExtraDefRegAllocReq = 1 + +// VST1 : Vector Store (multiple single elements) +class VST1D op7_4, string OpcodeStr, string Dt, + ValueType Ty, Intrinsic IntOp> + : NLdSt<0,0b00,0b0111,op7_4, (outs), (ins addrmode6:$addr, DPR:$src), IIC_VST, + OpcodeStr, Dt, "\\{$src\\}, $addr", "", + [(IntOp addrmode6:$addr, (Ty DPR:$src))]>; +class VST1Q op7_4, string OpcodeStr, string Dt, + ValueType Ty, Intrinsic IntOp> + : NLdSt<0,0b00,0b1010,op7_4, (outs), (ins addrmode6:$addr, QPR:$src), IIC_VST, + OpcodeStr, Dt, "${src:dregpair}, $addr", "", + [(IntOp addrmode6:$addr, (Ty QPR:$src))]>; + +let hasExtraSrcRegAllocReq = 1 in { +def VST1d8 : VST1D<0b0000, "vst1", "8", v8i8, int_arm_neon_vst1>; +def VST1d16 : VST1D<0b0100, "vst1", "16", v4i16, int_arm_neon_vst1>; +def VST1d32 : VST1D<0b1000, "vst1", "32", v2i32, int_arm_neon_vst1>; +def VST1df : VST1D<0b1000, "vst1", "32", v2f32, int_arm_neon_vst1>; +def VST1d64 : VST1D<0b1100, "vst1", "64", v1i64, int_arm_neon_vst1>; + +def VST1q8 : VST1Q<0b0000, "vst1", "8", v16i8, int_arm_neon_vst1>; +def VST1q16 : VST1Q<0b0100, "vst1", "16", v8i16, int_arm_neon_vst1>; +def VST1q32 : VST1Q<0b1000, "vst1", "32", v4i32, int_arm_neon_vst1>; +def VST1qf : VST1Q<0b1000, "vst1", "32", v4f32, int_arm_neon_vst1>; +def VST1q64 : VST1Q<0b1100, "vst1", "64", v2i64, int_arm_neon_vst1>; +} // hasExtraSrcRegAllocReq + +let mayStore = 1, hasExtraSrcRegAllocReq = 1 in { + +// VST2 : Vector Store (multiple 2-element structures) +class VST2D op7_4, string OpcodeStr, string Dt> + : NLdSt<0,0b00,0b1000,op7_4, (outs), + (ins addrmode6:$addr, DPR:$src1, DPR:$src2), IIC_VST, + OpcodeStr, Dt, "\\{$src1,$src2\\}, $addr", "", []>; +class VST2Q op7_4, string OpcodeStr, string Dt> + : NLdSt<0,0b00,0b0011,op7_4, (outs), + (ins addrmode6:$addr, DPR:$src1, DPR:$src2, DPR:$src3, DPR:$src4), + IIC_VST, + OpcodeStr, Dt, "\\{$src1,$src2,$src3,$src4\\}, $addr", + "", []>; + +def VST2d8 : VST2D<0b0000, "vst2", "8">; +def VST2d16 : VST2D<0b0100, "vst2", "16">; +def VST2d32 : VST2D<0b1000, "vst2", "32">; +def VST2d64 : NLdSt<0,0b00,0b1010,0b1100, (outs), + (ins addrmode6:$addr, DPR:$src1, DPR:$src2), IIC_VST, + "vst1", "64", "\\{$src1,$src2\\}, $addr", "", []>; + +def VST2q8 : VST2Q<0b0000, "vst2", "8">; +def VST2q16 : VST2Q<0b0100, "vst2", "16">; +def VST2q32 : VST2Q<0b1000, "vst2", "32">; + +// VST3 : Vector Store (multiple 3-element structures) +class VST3D op7_4, string OpcodeStr, string Dt> + : NLdSt<0,0b00,0b0100,op7_4, (outs), + (ins addrmode6:$addr, DPR:$src1, DPR:$src2, DPR:$src3), IIC_VST, + OpcodeStr, Dt, "\\{$src1,$src2,$src3\\}, $addr", "", []>; +class VST3WB op7_4, string OpcodeStr, string Dt> + : NLdSt<0,0b00,0b0101,op7_4, (outs GPR:$wb), + (ins addrmode6:$addr, DPR:$src1, DPR:$src2, DPR:$src3), IIC_VST, + OpcodeStr, Dt, "\\{$src1,$src2,$src3\\}, $addr", + "$addr.addr = $wb", []>; + +def VST3d8 : VST3D<0b0000, "vst3", "8">; +def VST3d16 : VST3D<0b0100, "vst3", "16">; +def VST3d32 : VST3D<0b1000, "vst3", "32">; +def VST3d64 : NLdSt<0,0b00,0b0110,0b1100, (outs), + (ins addrmode6:$addr, DPR:$src1, DPR:$src2, DPR:$src3), + IIC_VST, + "vst1", "64", "\\{$src1,$src2,$src3\\}, $addr", "", []>; + +// vst3 to double-spaced even registers. +def VST3q8a : VST3WB<0b0000, "vst3", "8">; +def VST3q16a : VST3WB<0b0100, "vst3", "16">; +def VST3q32a : VST3WB<0b1000, "vst3", "32">; + +// vst3 to double-spaced odd registers. +def VST3q8b : VST3WB<0b0000, "vst3", "8">; +def VST3q16b : VST3WB<0b0100, "vst3", "16">; +def VST3q32b : VST3WB<0b1000, "vst3", "32">; + +// VST4 : Vector Store (multiple 4-element structures) +class VST4D op7_4, string OpcodeStr, string Dt> + : NLdSt<0,0b00,0b0000,op7_4, (outs), + (ins addrmode6:$addr, DPR:$src1, DPR:$src2, DPR:$src3, DPR:$src4), + IIC_VST, + OpcodeStr, Dt, "\\{$src1,$src2,$src3,$src4\\}, $addr", + "", []>; +class VST4WB op7_4, string OpcodeStr, string Dt> + : NLdSt<0,0b00,0b0001,op7_4, (outs GPR:$wb), + (ins addrmode6:$addr, DPR:$src1, DPR:$src2, DPR:$src3, DPR:$src4), + IIC_VST, + OpcodeStr, Dt, "\\{$src1,$src2,$src3,$src4\\}, $addr", + "$addr.addr = $wb", []>; + +def VST4d8 : VST4D<0b0000, "vst4", "8">; +def VST4d16 : VST4D<0b0100, "vst4", "16">; +def VST4d32 : VST4D<0b1000, "vst4", "32">; +def VST4d64 : NLdSt<0,0b00,0b0010,0b1100, (outs), + (ins addrmode6:$addr, DPR:$src1, DPR:$src2, DPR:$src3, + DPR:$src4), IIC_VST, + "vst1", "64", "\\{$src1,$src2,$src3,$src4\\}, $addr", "", []>; + +// vst4 to double-spaced even registers. +def VST4q8a : VST4WB<0b0000, "vst4", "8">; +def VST4q16a : VST4WB<0b0100, "vst4", "16">; +def VST4q32a : VST4WB<0b1000, "vst4", "32">; + +// vst4 to double-spaced odd registers. +def VST4q8b : VST4WB<0b0000, "vst4", "8">; +def VST4q16b : VST4WB<0b0100, "vst4", "16">; +def VST4q32b : VST4WB<0b1000, "vst4", "32">; + +// VST1LN : Vector Store (single element from one lane) +// FIXME: Not yet implemented. + +// VST2LN : Vector Store (single 2-element structure from one lane) +class VST2LN op11_8, string OpcodeStr, string Dt> + : NLdSt<1,0b00,op11_8,{?,?,?,?}, (outs), + (ins addrmode6:$addr, DPR:$src1, DPR:$src2, nohash_imm:$lane), + IIC_VST, + OpcodeStr, Dt, "\\{$src1[$lane],$src2[$lane]\\}, $addr", + "", []>; + +// vst2 to single-spaced registers. +def VST2LNd8 : VST2LN<0b0001, "vst2", "8">; +def VST2LNd16 : VST2LN<0b0101, "vst2", "16"> { + let Inst{5} = 0; +} +def VST2LNd32 : VST2LN<0b1001, "vst2", "32"> { + let Inst{6} = 0; +} + +// vst2 to double-spaced even registers. +def VST2LNq16a: VST2LN<0b0101, "vst2", "16"> { + let Inst{5} = 1; +} +def VST2LNq32a: VST2LN<0b1001, "vst2", "32"> { + let Inst{6} = 1; +} + +// vst2 to double-spaced odd registers. +def VST2LNq16b: VST2LN<0b0101, "vst2", "16"> { + let Inst{5} = 1; +} +def VST2LNq32b: VST2LN<0b1001, "vst2", "32"> { + let Inst{6} = 1; +} + +// VST3LN : Vector Store (single 3-element structure from one lane) +class VST3LN op11_8, string OpcodeStr, string Dt> + : NLdSt<1,0b00,op11_8,{?,?,?,?}, (outs), + (ins addrmode6:$addr, DPR:$src1, DPR:$src2, DPR:$src3, + nohash_imm:$lane), IIC_VST, + OpcodeStr, Dt, + "\\{$src1[$lane],$src2[$lane],$src3[$lane]\\}, $addr", "", []>; + +// vst3 to single-spaced registers. +def VST3LNd8 : VST3LN<0b0010, "vst3", "8"> { + let Inst{4} = 0; +} +def VST3LNd16 : VST3LN<0b0110, "vst3", "16"> { + let Inst{5-4} = 0b00; +} +def VST3LNd32 : VST3LN<0b1010, "vst3", "32"> { + let Inst{6-4} = 0b000; +} + +// vst3 to double-spaced even registers. +def VST3LNq16a: VST3LN<0b0110, "vst3", "16"> { + let Inst{5-4} = 0b10; +} +def VST3LNq32a: VST3LN<0b1010, "vst3", "32"> { + let Inst{6-4} = 0b100; +} + +// vst3 to double-spaced odd registers. +def VST3LNq16b: VST3LN<0b0110, "vst3", "16"> { + let Inst{5-4} = 0b10; +} +def VST3LNq32b: VST3LN<0b1010, "vst3", "32"> { + let Inst{6-4} = 0b100; +} + +// VST4LN : Vector Store (single 4-element structure from one lane) +class VST4LN op11_8, string OpcodeStr, string Dt> + : NLdSt<1,0b00,op11_8,{?,?,?,?}, (outs), + (ins addrmode6:$addr, DPR:$src1, DPR:$src2, DPR:$src3, DPR:$src4, + nohash_imm:$lane), IIC_VST, + OpcodeStr, Dt, + "\\{$src1[$lane],$src2[$lane],$src3[$lane],$src4[$lane]\\}, $addr", + "", []>; + +// vst4 to single-spaced registers. +def VST4LNd8 : VST4LN<0b0011, "vst4", "8">; +def VST4LNd16 : VST4LN<0b0111, "vst4", "16"> { + let Inst{5} = 0; +} +def VST4LNd32 : VST4LN<0b1011, "vst4", "32"> { + let Inst{6} = 0; +} + +// vst4 to double-spaced even registers. +def VST4LNq16a: VST4LN<0b0111, "vst4", "16"> { + let Inst{5} = 1; +} +def VST4LNq32a: VST4LN<0b1011, "vst4", "32"> { + let Inst{6} = 1; +} + +// vst4 to double-spaced odd registers. +def VST4LNq16b: VST4LN<0b0111, "vst4", "16"> { + let Inst{5} = 1; +} +def VST4LNq32b: VST4LN<0b1011, "vst4", "32"> { + let Inst{6} = 1; +} + +} // mayStore = 1, hasExtraSrcRegAllocReq = 1 + + +//===----------------------------------------------------------------------===// +// NEON pattern fragments +//===----------------------------------------------------------------------===// + +// Extract D sub-registers of Q registers. +// (arm_dsubreg_0 is 5; arm_dsubreg_1 is 6) +def DSubReg_i8_reg : SDNodeXFormgetTargetConstant(5 + N->getZExtValue() / 8, MVT::i32); +}]>; +def DSubReg_i16_reg : SDNodeXFormgetTargetConstant(5 + N->getZExtValue() / 4, MVT::i32); +}]>; +def DSubReg_i32_reg : SDNodeXFormgetTargetConstant(5 + N->getZExtValue() / 2, MVT::i32); +}]>; +def DSubReg_f64_reg : SDNodeXFormgetTargetConstant(5 + N->getZExtValue(), MVT::i32); +}]>; +def DSubReg_f64_other_reg : SDNodeXFormgetTargetConstant(5 + (1 - N->getZExtValue()), MVT::i32); +}]>; + +// Extract S sub-registers of Q/D registers. +// (arm_ssubreg_0 is 1; arm_ssubreg_1 is 2; etc.) +def SSubReg_f32_reg : SDNodeXFormgetTargetConstant(1 + N->getZExtValue(), MVT::i32); +}]>; + +// Translate lane numbers from Q registers to D subregs. +def SubReg_i8_lane : SDNodeXFormgetTargetConstant(N->getZExtValue() & 7, MVT::i32); +}]>; +def SubReg_i16_lane : SDNodeXFormgetTargetConstant(N->getZExtValue() & 3, MVT::i32); +}]>; +def SubReg_i32_lane : SDNodeXFormgetTargetConstant(N->getZExtValue() & 1, MVT::i32); +}]>; + +//===----------------------------------------------------------------------===// +// Instruction Classes +//===----------------------------------------------------------------------===// + +// Basic 2-register operations, both double- and quad-register. +class N2VD op24_23, bits<2> op21_20, bits<2> op19_18, + bits<2> op17_16, bits<5> op11_7, bit op4, string OpcodeStr,string Dt, + ValueType ResTy, ValueType OpTy, SDNode OpNode> + : N2V; +class N2VQ op24_23, bits<2> op21_20, bits<2> op19_18, + bits<2> op17_16, bits<5> op11_7, bit op4, string OpcodeStr,string Dt, + ValueType ResTy, ValueType OpTy, SDNode OpNode> + : N2V; + +// Basic 2-register operations, scalar single-precision. +class N2VDs op24_23, bits<2> op21_20, bits<2> op19_18, + bits<2> op17_16, bits<5> op11_7, bit op4, string OpcodeStr,string Dt, + ValueType ResTy, ValueType OpTy, SDNode OpNode> + : N2V; + +class N2VDsPat + : NEONFPPat<(ResTy (OpNode SPR:$a)), + (EXTRACT_SUBREG + (Inst (INSERT_SUBREG (OpTy (IMPLICIT_DEF)), SPR:$a, arm_ssubreg_0)), + arm_ssubreg_0)>; + +// Basic 2-register intrinsics, both double- and quad-register. +class N2VDInt op24_23, bits<2> op21_20, bits<2> op19_18, + bits<2> op17_16, bits<5> op11_7, bit op4, + InstrItinClass itin, string OpcodeStr, string Dt, + ValueType ResTy, ValueType OpTy, Intrinsic IntOp> + : N2V; +class N2VQInt op24_23, bits<2> op21_20, bits<2> op19_18, + bits<2> op17_16, bits<5> op11_7, bit op4, + InstrItinClass itin, string OpcodeStr, string Dt, + ValueType ResTy, ValueType OpTy, Intrinsic IntOp> + : N2V; + +// Basic 2-register intrinsics, scalar single-precision +class N2VDInts op24_23, bits<2> op21_20, bits<2> op19_18, + bits<2> op17_16, bits<5> op11_7, bit op4, + InstrItinClass itin, string OpcodeStr, string Dt, + ValueType ResTy, ValueType OpTy, Intrinsic IntOp> + : N2V; + +class N2VDIntsPat + : NEONFPPat<(f32 (OpNode SPR:$a)), + (EXTRACT_SUBREG + (Inst (INSERT_SUBREG (v2f32 (IMPLICIT_DEF)), SPR:$a, arm_ssubreg_0)), + arm_ssubreg_0)>; + +// Narrow 2-register intrinsics. +class N2VNInt op24_23, bits<2> op21_20, bits<2> op19_18, + bits<2> op17_16, bits<5> op11_7, bit op6, bit op4, + InstrItinClass itin, string OpcodeStr, string Dt, + ValueType TyD, ValueType TyQ, Intrinsic IntOp> + : N2V; + +// Long 2-register intrinsics (currently only used for VMOVL). +class N2VLInt op24_23, bits<2> op21_20, bits<2> op19_18, + bits<2> op17_16, bits<5> op11_7, bit op6, bit op4, + InstrItinClass itin, string OpcodeStr, string Dt, + ValueType TyQ, ValueType TyD, Intrinsic IntOp> + : N2V; + +// 2-register shuffles (VTRN/VZIP/VUZP), both double- and quad-register. +class N2VDShuffle op19_18, bits<5> op11_7, string OpcodeStr, string Dt> + : N2V<0b11, 0b11, op19_18, 0b10, op11_7, 0, 0, (outs DPR:$dst1, DPR:$dst2), + (ins DPR:$src1, DPR:$src2), IIC_VPERMD, + OpcodeStr, Dt, "$dst1, $dst2", + "$src1 = $dst1, $src2 = $dst2", []>; +class N2VQShuffle op19_18, bits<5> op11_7, + InstrItinClass itin, string OpcodeStr, string Dt> + : N2V<0b11, 0b11, op19_18, 0b10, op11_7, 1, 0, (outs QPR:$dst1, QPR:$dst2), + (ins QPR:$src1, QPR:$src2), itin, + OpcodeStr, Dt, "$dst1, $dst2", + "$src1 = $dst1, $src2 = $dst2", []>; + +// Basic 3-register operations, both double- and quad-register. +class N3VD op21_20, bits<4> op11_8, bit op4, + InstrItinClass itin, string OpcodeStr, string Dt, + ValueType ResTy, ValueType OpTy, + SDNode OpNode, bit Commutable> + : N3V { + let isCommutable = Commutable; +} +// Same as N3VD but no data type. +class N3VDX op21_20, bits<4> op11_8, bit op4, + InstrItinClass itin, string OpcodeStr, + ValueType ResTy, ValueType OpTy, + SDNode OpNode, bit Commutable> + : N3VX { + let isCommutable = Commutable; +} +class N3VDSL op21_20, bits<4> op11_8, + InstrItinClass itin, string OpcodeStr, string Dt, + ValueType Ty, SDNode ShOp> + : N3V<0, 1, op21_20, op11_8, 1, 0, + (outs DPR:$dst), (ins DPR:$src1, DPR_VFP2:$src2, nohash_imm:$lane), + itin, OpcodeStr, Dt, "$dst, $src1, $src2[$lane]", "", + [(set (Ty DPR:$dst), + (Ty (ShOp (Ty DPR:$src1), + (Ty (NEONvduplane (Ty DPR_VFP2:$src2), + imm:$lane)))))]> { + let isCommutable = 0; +} +class N3VDSL16 op21_20, bits<4> op11_8, + string OpcodeStr, string Dt, ValueType Ty, SDNode ShOp> + : N3V<0, 1, op21_20, op11_8, 1, 0, + (outs DPR:$dst), (ins DPR:$src1, DPR_8:$src2, nohash_imm:$lane), + IIC_VMULi16D, + OpcodeStr, Dt, "$dst, $src1, $src2[$lane]", "", + [(set (Ty DPR:$dst), + (Ty (ShOp (Ty DPR:$src1), + (Ty (NEONvduplane (Ty DPR_8:$src2), + imm:$lane)))))]> { + let isCommutable = 0; +} + +class N3VQ op21_20, bits<4> op11_8, bit op4, + InstrItinClass itin, string OpcodeStr, string Dt, + ValueType ResTy, ValueType OpTy, + SDNode OpNode, bit Commutable> + : N3V { + let isCommutable = Commutable; +} +class N3VQX op21_20, bits<4> op11_8, bit op4, + InstrItinClass itin, string OpcodeStr, + ValueType ResTy, ValueType OpTy, + SDNode OpNode, bit Commutable> + : N3VX { + let isCommutable = Commutable; +} +class N3VQSL op21_20, bits<4> op11_8, + InstrItinClass itin, string OpcodeStr, string Dt, + ValueType ResTy, ValueType OpTy, SDNode ShOp> + : N3V<1, 1, op21_20, op11_8, 1, 0, + (outs QPR:$dst), (ins QPR:$src1, DPR_VFP2:$src2, nohash_imm:$lane), + itin, OpcodeStr, Dt, "$dst, $src1, $src2[$lane]", "", + [(set (ResTy QPR:$dst), + (ResTy (ShOp (ResTy QPR:$src1), + (ResTy (NEONvduplane (OpTy DPR_VFP2:$src2), + imm:$lane)))))]> { + let isCommutable = 0; +} +class N3VQSL16 op21_20, bits<4> op11_8, + string OpcodeStr, string Dt, + ValueType ResTy, ValueType OpTy, SDNode ShOp> + : N3V<1, 1, op21_20, op11_8, 1, 0, + (outs QPR:$dst), (ins QPR:$src1, DPR_8:$src2, nohash_imm:$lane), + IIC_VMULi16Q, + OpcodeStr, Dt, "$dst, $src1, $src2[$lane]", "", + [(set (ResTy QPR:$dst), + (ResTy (ShOp (ResTy QPR:$src1), + (ResTy (NEONvduplane (OpTy DPR_8:$src2), + imm:$lane)))))]> { + let isCommutable = 0; +} + +// Basic 3-register operations, scalar single-precision +class N3VDs op21_20, bits<4> op11_8, bit op4, + string OpcodeStr, string Dt, ValueType ResTy, ValueType OpTy, + SDNode OpNode, bit Commutable> + : N3V { + let isCommutable = Commutable; +} +class N3VDsPat + : NEONFPPat<(f32 (OpNode SPR:$a, SPR:$b)), + (EXTRACT_SUBREG + (Inst (INSERT_SUBREG (v2f32 (IMPLICIT_DEF)), SPR:$a, arm_ssubreg_0), + (INSERT_SUBREG (v2f32 (IMPLICIT_DEF)), SPR:$b, arm_ssubreg_0)), + arm_ssubreg_0)>; + +// Basic 3-register intrinsics, both double- and quad-register. +class N3VDInt op21_20, bits<4> op11_8, bit op4, + InstrItinClass itin, string OpcodeStr, string Dt, + ValueType ResTy, ValueType OpTy, + Intrinsic IntOp, bit Commutable> + : N3V { + let isCommutable = Commutable; +} +class N3VDIntSL op21_20, bits<4> op11_8, InstrItinClass itin, + string OpcodeStr, string Dt, ValueType Ty, Intrinsic IntOp> + : N3V<0, 1, op21_20, op11_8, 1, 0, + (outs DPR:$dst), (ins DPR:$src1, DPR_VFP2:$src2, nohash_imm:$lane), + itin, OpcodeStr, Dt, "$dst, $src1, $src2[$lane]", "", + [(set (Ty DPR:$dst), + (Ty (IntOp (Ty DPR:$src1), + (Ty (NEONvduplane (Ty DPR_VFP2:$src2), + imm:$lane)))))]> { + let isCommutable = 0; +} +class N3VDIntSL16 op21_20, bits<4> op11_8, InstrItinClass itin, + string OpcodeStr, string Dt, ValueType Ty, Intrinsic IntOp> + : N3V<0, 1, op21_20, op11_8, 1, 0, + (outs DPR:$dst), (ins DPR:$src1, DPR_8:$src2, nohash_imm:$lane), + itin, OpcodeStr, Dt, "$dst, $src1, $src2[$lane]", "", + [(set (Ty DPR:$dst), + (Ty (IntOp (Ty DPR:$src1), + (Ty (NEONvduplane (Ty DPR_8:$src2), + imm:$lane)))))]> { + let isCommutable = 0; +} + +class N3VQInt op21_20, bits<4> op11_8, bit op4, + InstrItinClass itin, string OpcodeStr, string Dt, + ValueType ResTy, ValueType OpTy, + Intrinsic IntOp, bit Commutable> + : N3V { + let isCommutable = Commutable; +} +class N3VQIntSL op21_20, bits<4> op11_8, InstrItinClass itin, + string OpcodeStr, string Dt, + ValueType ResTy, ValueType OpTy, Intrinsic IntOp> + : N3V<1, 1, op21_20, op11_8, 1, 0, + (outs QPR:$dst), (ins QPR:$src1, DPR_VFP2:$src2, nohash_imm:$lane), + itin, OpcodeStr, Dt, "$dst, $src1, $src2[$lane]", "", + [(set (ResTy QPR:$dst), + (ResTy (IntOp (ResTy QPR:$src1), + (ResTy (NEONvduplane (OpTy DPR_VFP2:$src2), + imm:$lane)))))]> { + let isCommutable = 0; +} +class N3VQIntSL16 op21_20, bits<4> op11_8, InstrItinClass itin, + string OpcodeStr, string Dt, + ValueType ResTy, ValueType OpTy, Intrinsic IntOp> + : N3V<1, 1, op21_20, op11_8, 1, 0, + (outs QPR:$dst), (ins QPR:$src1, DPR_8:$src2, nohash_imm:$lane), + itin, OpcodeStr, Dt, "$dst, $src1, $src2[$lane]", "", + [(set (ResTy QPR:$dst), + (ResTy (IntOp (ResTy QPR:$src1), + (ResTy (NEONvduplane (OpTy DPR_8:$src2), + imm:$lane)))))]> { + let isCommutable = 0; +} + +// Multiply-Add/Sub operations, both double- and quad-register. +class N3VDMulOp op21_20, bits<4> op11_8, bit op4, + InstrItinClass itin, string OpcodeStr, string Dt, + ValueType Ty, SDNode MulOp, SDNode OpNode> + : N3V; +class N3VDMulOpSL op21_20, bits<4> op11_8, InstrItinClass itin, + string OpcodeStr, string Dt, + ValueType Ty, SDNode MulOp, SDNode ShOp> + : N3V<0, 1, op21_20, op11_8, 1, 0, + (outs DPR:$dst), + (ins DPR:$src1, DPR:$src2, DPR_VFP2:$src3, nohash_imm:$lane), itin, + OpcodeStr, Dt, "$dst, $src2, $src3[$lane]", "$src1 = $dst", + [(set (Ty DPR:$dst), + (Ty (ShOp (Ty DPR:$src1), + (Ty (MulOp DPR:$src2, + (Ty (NEONvduplane (Ty DPR_VFP2:$src3), + imm:$lane)))))))]>; +class N3VDMulOpSL16 op21_20, bits<4> op11_8, InstrItinClass itin, + string OpcodeStr, string Dt, + ValueType Ty, SDNode MulOp, SDNode ShOp> + : N3V<0, 1, op21_20, op11_8, 1, 0, + (outs DPR:$dst), + (ins DPR:$src1, DPR:$src2, DPR_8:$src3, nohash_imm:$lane), itin, + OpcodeStr, Dt, "$dst, $src2, $src3[$lane]", "$src1 = $dst", + [(set (Ty DPR:$dst), + (Ty (ShOp (Ty DPR:$src1), + (Ty (MulOp DPR:$src2, + (Ty (NEONvduplane (Ty DPR_8:$src3), + imm:$lane)))))))]>; + +class N3VQMulOp op21_20, bits<4> op11_8, bit op4, + InstrItinClass itin, string OpcodeStr, string Dt, ValueType Ty, + SDNode MulOp, SDNode OpNode> + : N3V; +class N3VQMulOpSL op21_20, bits<4> op11_8, InstrItinClass itin, + string OpcodeStr, string Dt, ValueType ResTy, ValueType OpTy, + SDNode MulOp, SDNode ShOp> + : N3V<1, 1, op21_20, op11_8, 1, 0, + (outs QPR:$dst), + (ins QPR:$src1, QPR:$src2, DPR_VFP2:$src3, nohash_imm:$lane), itin, + OpcodeStr, Dt, "$dst, $src2, $src3[$lane]", "$src1 = $dst", + [(set (ResTy QPR:$dst), + (ResTy (ShOp (ResTy QPR:$src1), + (ResTy (MulOp QPR:$src2, + (ResTy (NEONvduplane (OpTy DPR_VFP2:$src3), + imm:$lane)))))))]>; +class N3VQMulOpSL16 op21_20, bits<4> op11_8, InstrItinClass itin, + string OpcodeStr, string Dt, + ValueType ResTy, ValueType OpTy, + SDNode MulOp, SDNode ShOp> + : N3V<1, 1, op21_20, op11_8, 1, 0, + (outs QPR:$dst), + (ins QPR:$src1, QPR:$src2, DPR_8:$src3, nohash_imm:$lane), itin, + OpcodeStr, Dt, "$dst, $src2, $src3[$lane]", "$src1 = $dst", + [(set (ResTy QPR:$dst), + (ResTy (ShOp (ResTy QPR:$src1), + (ResTy (MulOp QPR:$src2, + (ResTy (NEONvduplane (OpTy DPR_8:$src3), + imm:$lane)))))))]>; + +// Multiply-Add/Sub operations, scalar single-precision +class N3VDMulOps op21_20, bits<4> op11_8, bit op4, + InstrItinClass itin, string OpcodeStr, string Dt, + ValueType Ty, SDNode MulOp, SDNode OpNode> + : N3V; + +class N3VDMulOpsPat + : NEONFPPat<(f32 (OpNode SPR:$acc, (f32 (MulNode SPR:$a, SPR:$b)))), + (EXTRACT_SUBREG + (Inst (INSERT_SUBREG (v2f32 (IMPLICIT_DEF)), SPR:$acc, arm_ssubreg_0), + (INSERT_SUBREG (v2f32 (IMPLICIT_DEF)), SPR:$a, arm_ssubreg_0), + (INSERT_SUBREG (v2f32 (IMPLICIT_DEF)), SPR:$b, arm_ssubreg_0)), + arm_ssubreg_0)>; + +// Neon 3-argument intrinsics, both double- and quad-register. +// The destination register is also used as the first source operand register. +class N3VDInt3 op21_20, bits<4> op11_8, bit op4, + InstrItinClass itin, string OpcodeStr, string Dt, + ValueType ResTy, ValueType OpTy, Intrinsic IntOp> + : N3V; +class N3VQInt3 op21_20, bits<4> op11_8, bit op4, + InstrItinClass itin, string OpcodeStr, string Dt, + ValueType ResTy, ValueType OpTy, Intrinsic IntOp> + : N3V; + +// Neon Long 3-argument intrinsic. The destination register is +// a quad-register and is also used as the first source operand register. +class N3VLInt3 op21_20, bits<4> op11_8, bit op4, + InstrItinClass itin, string OpcodeStr, string Dt, + ValueType TyQ, ValueType TyD, Intrinsic IntOp> + : N3V; +class N3VLInt3SL op21_20, bits<4> op11_8, InstrItinClass itin, + string OpcodeStr, string Dt, + ValueType ResTy, ValueType OpTy, Intrinsic IntOp> + : N3V; +class N3VLInt3SL16 op21_20, bits<4> op11_8, InstrItinClass itin, + string OpcodeStr, string Dt, ValueType ResTy, ValueType OpTy, + Intrinsic IntOp> + : N3V; + + +// Narrowing 3-register intrinsics. +class N3VNInt op21_20, bits<4> op11_8, bit op4, + string OpcodeStr, string Dt, ValueType TyD, ValueType TyQ, + Intrinsic IntOp, bit Commutable> + : N3V { + let isCommutable = Commutable; +} + +// Long 3-register intrinsics. +class N3VLInt op21_20, bits<4> op11_8, bit op4, + InstrItinClass itin, string OpcodeStr, string Dt, + ValueType TyQ, ValueType TyD, Intrinsic IntOp, bit Commutable> + : N3V { + let isCommutable = Commutable; +} +class N3VLIntSL op21_20, bits<4> op11_8, InstrItinClass itin, + string OpcodeStr, string Dt, + ValueType ResTy, ValueType OpTy, Intrinsic IntOp> + : N3V; +class N3VLIntSL16 op21_20, bits<4> op11_8, InstrItinClass itin, + string OpcodeStr, string Dt, ValueType ResTy, ValueType OpTy, + Intrinsic IntOp> + : N3V; + +// Wide 3-register intrinsics. +class N3VWInt op21_20, bits<4> op11_8, bit op4, + string OpcodeStr, string Dt, ValueType TyQ, ValueType TyD, + Intrinsic IntOp, bit Commutable> + : N3V { + let isCommutable = Commutable; +} + +// Pairwise long 2-register intrinsics, both double- and quad-register. +class N2VDPLInt op24_23, bits<2> op21_20, bits<2> op19_18, + bits<2> op17_16, bits<5> op11_7, bit op4, + string OpcodeStr, string Dt, + ValueType ResTy, ValueType OpTy, Intrinsic IntOp> + : N2V; +class N2VQPLInt op24_23, bits<2> op21_20, bits<2> op19_18, + bits<2> op17_16, bits<5> op11_7, bit op4, + string OpcodeStr, string Dt, + ValueType ResTy, ValueType OpTy, Intrinsic IntOp> + : N2V; + +// Pairwise long 2-register accumulate intrinsics, +// both double- and quad-register. +// The destination register is also used as the first source operand register. +class N2VDPLInt2 op24_23, bits<2> op21_20, bits<2> op19_18, + bits<2> op17_16, bits<5> op11_7, bit op4, + string OpcodeStr, string Dt, + ValueType ResTy, ValueType OpTy, Intrinsic IntOp> + : N2V; +class N2VQPLInt2 op24_23, bits<2> op21_20, bits<2> op19_18, + bits<2> op17_16, bits<5> op11_7, bit op4, + string OpcodeStr, string Dt, + ValueType ResTy, ValueType OpTy, Intrinsic IntOp> + : N2V; + +// Shift by immediate, +// both double- and quad-register. +class N2VDSh op11_8, bit op7, bit op4, + InstrItinClass itin, string OpcodeStr, string Dt, + ValueType Ty, SDNode OpNode> + : N2VImm; +class N2VQSh op11_8, bit op7, bit op4, + InstrItinClass itin, string OpcodeStr, string Dt, + ValueType Ty, SDNode OpNode> + : N2VImm; + +// Long shift by immediate. +class N2VLSh op11_8, bit op7, bit op6, bit op4, + string OpcodeStr, string Dt, + ValueType ResTy, ValueType OpTy, SDNode OpNode> + : N2VImm; + +// Narrow shift by immediate. +class N2VNSh op11_8, bit op7, bit op6, bit op4, + InstrItinClass itin, string OpcodeStr, string Dt, + ValueType ResTy, ValueType OpTy, SDNode OpNode> + : N2VImm; + +// Shift right by immediate and accumulate, +// both double- and quad-register. +class N2VDShAdd op11_8, bit op7, bit op4, + string OpcodeStr, string Dt, ValueType Ty, SDNode ShOp> + : N2VImm; +class N2VQShAdd op11_8, bit op7, bit op4, + string OpcodeStr, string Dt, ValueType Ty, SDNode ShOp> + : N2VImm; + +// Shift by immediate and insert, +// both double- and quad-register. +class N2VDShIns op11_8, bit op7, bit op4, + string OpcodeStr, string Dt, ValueType Ty, SDNode ShOp> + : N2VImm; +class N2VQShIns op11_8, bit op7, bit op4, + string OpcodeStr, string Dt, ValueType Ty, SDNode ShOp> + : N2VImm; + +// Convert, with fractional bits immediate, +// both double- and quad-register. +class N2VCvtD op11_8, bit op7, bit op4, + string OpcodeStr, string Dt, ValueType ResTy, ValueType OpTy, + Intrinsic IntOp> + : N2VImm; +class N2VCvtQ op11_8, bit op7, bit op4, + string OpcodeStr, string Dt, ValueType ResTy, ValueType OpTy, + Intrinsic IntOp> + : N2VImm; + +//===----------------------------------------------------------------------===// +// Multiclasses +//===----------------------------------------------------------------------===// + +// Abbreviations used in multiclass suffixes: +// Q = quarter int (8 bit) elements +// H = half int (16 bit) elements +// S = single int (32 bit) elements +// D = double int (64 bit) elements + +// Neon 3-register vector operations. + +// First with only element sizes of 8, 16 and 32 bits: +multiclass N3V_QHS op11_8, bit op4, + InstrItinClass itinD16, InstrItinClass itinD32, + InstrItinClass itinQ16, InstrItinClass itinQ32, + string OpcodeStr, string Dt, + SDNode OpNode, bit Commutable = 0> { + // 64-bit vector types. + def v8i8 : N3VD; + def v4i16 : N3VD; + def v2i32 : N3VD; + + // 128-bit vector types. + def v16i8 : N3VQ; + def v8i16 : N3VQ; + def v4i32 : N3VQ; +} + +multiclass N3VSL_HS op11_8, string OpcodeStr, string Dt, SDNode ShOp> { + def v4i16 : N3VDSL16<0b01, op11_8, OpcodeStr, !strconcat(Dt, "16"), + v4i16, ShOp>; + def v2i32 : N3VDSL<0b10, op11_8, IIC_VMULi32D, OpcodeStr, !strconcat(Dt,"32"), + v2i32, ShOp>; + def v8i16 : N3VQSL16<0b01, op11_8, OpcodeStr, !strconcat(Dt, "16"), + v8i16, v4i16, ShOp>; + def v4i32 : N3VQSL<0b10, op11_8, IIC_VMULi32Q, OpcodeStr, !strconcat(Dt,"32"), + v4i32, v2i32, ShOp>; +} + +// ....then also with element size 64 bits: +multiclass N3V_QHSD op11_8, bit op4, + InstrItinClass itinD, InstrItinClass itinQ, + string OpcodeStr, string Dt, + SDNode OpNode, bit Commutable = 0> + : N3V_QHS { + def v1i64 : N3VD; + def v2i64 : N3VQ; +} + + +// Neon Narrowing 2-register vector intrinsics, +// source operand element sizes of 16, 32 and 64 bits: +multiclass N2VNInt_HSD op24_23, bits<2> op21_20, bits<2> op17_16, + bits<5> op11_7, bit op6, bit op4, + InstrItinClass itin, string OpcodeStr, string Dt, + Intrinsic IntOp> { + def v8i8 : N2VNInt; + def v4i16 : N2VNInt; + def v2i32 : N2VNInt; +} + + +// Neon Lengthening 2-register vector intrinsic (currently specific to VMOVL). +// source operand element sizes of 16, 32 and 64 bits: +multiclass N2VLInt_QHS op24_23, bits<5> op11_7, bit op6, bit op4, + string OpcodeStr, string Dt, Intrinsic IntOp> { + def v8i16 : N2VLInt; + def v4i32 : N2VLInt; + def v2i64 : N2VLInt; +} + + +// Neon 3-register vector intrinsics. + +// First with only element sizes of 16 and 32 bits: +multiclass N3VInt_HS op11_8, bit op4, + InstrItinClass itinD16, InstrItinClass itinD32, + InstrItinClass itinQ16, InstrItinClass itinQ32, + string OpcodeStr, string Dt, + Intrinsic IntOp, bit Commutable = 0> { + // 64-bit vector types. + def v4i16 : N3VDInt; + def v2i32 : N3VDInt; + + // 128-bit vector types. + def v8i16 : N3VQInt; + def v4i32 : N3VQInt; +} + +multiclass N3VIntSL_HS op11_8, + InstrItinClass itinD16, InstrItinClass itinD32, + InstrItinClass itinQ16, InstrItinClass itinQ32, + string OpcodeStr, string Dt, Intrinsic IntOp> { + def v4i16 : N3VDIntSL16<0b01, op11_8, itinD16, + OpcodeStr, !strconcat(Dt, "16"), v4i16, IntOp>; + def v2i32 : N3VDIntSL<0b10, op11_8, itinD32, + OpcodeStr, !strconcat(Dt, "32"), v2i32, IntOp>; + def v8i16 : N3VQIntSL16<0b01, op11_8, itinQ16, + OpcodeStr, !strconcat(Dt, "16"), v8i16, v4i16, IntOp>; + def v4i32 : N3VQIntSL<0b10, op11_8, itinQ32, + OpcodeStr, !strconcat(Dt, "32"), v4i32, v2i32, IntOp>; +} + +// ....then also with element size of 8 bits: +multiclass N3VInt_QHS op11_8, bit op4, + InstrItinClass itinD16, InstrItinClass itinD32, + InstrItinClass itinQ16, InstrItinClass itinQ32, + string OpcodeStr, string Dt, + Intrinsic IntOp, bit Commutable = 0> + : N3VInt_HS { + def v8i8 : N3VDInt; + def v16i8 : N3VQInt; +} + +// ....then also with element size of 64 bits: +multiclass N3VInt_QHSD op11_8, bit op4, + InstrItinClass itinD16, InstrItinClass itinD32, + InstrItinClass itinQ16, InstrItinClass itinQ32, + string OpcodeStr, string Dt, + Intrinsic IntOp, bit Commutable = 0> + : N3VInt_QHS { + def v1i64 : N3VDInt; + def v2i64 : N3VQInt; +} + + +// Neon Narrowing 3-register vector intrinsics, +// source operand element sizes of 16, 32 and 64 bits: +multiclass N3VNInt_HSD op11_8, bit op4, + string OpcodeStr, string Dt, + Intrinsic IntOp, bit Commutable = 0> { + def v8i8 : N3VNInt; + def v4i16 : N3VNInt; + def v2i32 : N3VNInt; +} + + +// Neon Long 3-register vector intrinsics. + +// First with only element sizes of 16 and 32 bits: +multiclass N3VLInt_HS op11_8, bit op4, + InstrItinClass itin, string OpcodeStr, string Dt, + Intrinsic IntOp, bit Commutable = 0> { + def v4i32 : N3VLInt; + def v2i64 : N3VLInt; +} + +multiclass N3VLIntSL_HS op11_8, + InstrItinClass itin, string OpcodeStr, string Dt, + Intrinsic IntOp> { + def v4i16 : N3VLIntSL16; + def v2i32 : N3VLIntSL; +} + +// ....then also with element size of 8 bits: +multiclass N3VLInt_QHS op11_8, bit op4, + InstrItinClass itin, string OpcodeStr, string Dt, + Intrinsic IntOp, bit Commutable = 0> + : N3VLInt_HS { + def v8i16 : N3VLInt; +} + + +// Neon Wide 3-register vector intrinsics, +// source operand element sizes of 8, 16 and 32 bits: +multiclass N3VWInt_QHS op11_8, bit op4, + string OpcodeStr, string Dt, + Intrinsic IntOp, bit Commutable = 0> { + def v8i16 : N3VWInt; + def v4i32 : N3VWInt; + def v2i64 : N3VWInt; +} + + +// Neon Multiply-Op vector operations, +// element sizes of 8, 16 and 32 bits: +multiclass N3VMulOp_QHS op11_8, bit op4, + InstrItinClass itinD16, InstrItinClass itinD32, + InstrItinClass itinQ16, InstrItinClass itinQ32, + string OpcodeStr, string Dt, SDNode OpNode> { + // 64-bit vector types. + def v8i8 : N3VDMulOp; + def v4i16 : N3VDMulOp; + def v2i32 : N3VDMulOp; + + // 128-bit vector types. + def v16i8 : N3VQMulOp; + def v8i16 : N3VQMulOp; + def v4i32 : N3VQMulOp; +} + +multiclass N3VMulOpSL_HS op11_8, + InstrItinClass itinD16, InstrItinClass itinD32, + InstrItinClass itinQ16, InstrItinClass itinQ32, + string OpcodeStr, string Dt, SDNode ShOp> { + def v4i16 : N3VDMulOpSL16<0b01, op11_8, itinD16, + OpcodeStr, !strconcat(Dt, "16"), v4i16, mul, ShOp>; + def v2i32 : N3VDMulOpSL<0b10, op11_8, itinD32, + OpcodeStr, !strconcat(Dt, "32"), v2i32, mul, ShOp>; + def v8i16 : N3VQMulOpSL16<0b01, op11_8, itinQ16, + OpcodeStr, !strconcat(Dt, "16"), v8i16, v4i16, mul, ShOp>; + def v4i32 : N3VQMulOpSL<0b10, op11_8, itinQ32, + OpcodeStr, !strconcat(Dt, "32"), v4i32, v2i32, mul, ShOp>; +} + +// Neon 3-argument intrinsics, +// element sizes of 8, 16 and 32 bits: +multiclass N3VInt3_QHS op11_8, bit op4, + string OpcodeStr, string Dt, Intrinsic IntOp> { + // 64-bit vector types. + def v8i8 : N3VDInt3; + def v4i16 : N3VDInt3; + def v2i32 : N3VDInt3; + + // 128-bit vector types. + def v16i8 : N3VQInt3; + def v8i16 : N3VQInt3; + def v4i32 : N3VQInt3; +} + + +// Neon Long 3-argument intrinsics. + +// First with only element sizes of 16 and 32 bits: +multiclass N3VLInt3_HS op11_8, bit op4, + string OpcodeStr, string Dt, Intrinsic IntOp> { + def v4i32 : N3VLInt3; + def v2i64 : N3VLInt3; +} + +multiclass N3VLInt3SL_HS op11_8, + string OpcodeStr, string Dt, Intrinsic IntOp> { + def v4i16 : N3VLInt3SL16; + def v2i32 : N3VLInt3SL; +} + +// ....then also with element size of 8 bits: +multiclass N3VLInt3_QHS op11_8, bit op4, + string OpcodeStr, string Dt, Intrinsic IntOp> + : N3VLInt3_HS { + def v8i16 : N3VLInt3; +} + + +// Neon 2-register vector intrinsics, +// element sizes of 8, 16 and 32 bits: +multiclass N2VInt_QHS op24_23, bits<2> op21_20, bits<2> op17_16, + bits<5> op11_7, bit op4, + InstrItinClass itinD, InstrItinClass itinQ, + string OpcodeStr, string Dt, Intrinsic IntOp> { + // 64-bit vector types. + def v8i8 : N2VDInt; + def v4i16 : N2VDInt; + def v2i32 : N2VDInt; + + // 128-bit vector types. + def v16i8 : N2VQInt; + def v8i16 : N2VQInt; + def v4i32 : N2VQInt; +} + + +// Neon Pairwise long 2-register intrinsics, +// element sizes of 8, 16 and 32 bits: +multiclass N2VPLInt_QHS op24_23, bits<2> op21_20, bits<2> op17_16, + bits<5> op11_7, bit op4, + string OpcodeStr, string Dt, Intrinsic IntOp> { + // 64-bit vector types. + def v8i8 : N2VDPLInt; + def v4i16 : N2VDPLInt; + def v2i32 : N2VDPLInt; + + // 128-bit vector types. + def v16i8 : N2VQPLInt; + def v8i16 : N2VQPLInt; + def v4i32 : N2VQPLInt; +} + + +// Neon Pairwise long 2-register accumulate intrinsics, +// element sizes of 8, 16 and 32 bits: +multiclass N2VPLInt2_QHS op24_23, bits<2> op21_20, bits<2> op17_16, + bits<5> op11_7, bit op4, + string OpcodeStr, string Dt, Intrinsic IntOp> { + // 64-bit vector types. + def v8i8 : N2VDPLInt2; + def v4i16 : N2VDPLInt2; + def v2i32 : N2VDPLInt2; + + // 128-bit vector types. + def v16i8 : N2VQPLInt2; + def v8i16 : N2VQPLInt2; + def v4i32 : N2VQPLInt2; +} + + +// Neon 2-register vector shift by immediate, +// element sizes of 8, 16, 32 and 64 bits: +multiclass N2VSh_QHSD op11_8, bit op4, + InstrItinClass itin, string OpcodeStr, string Dt, + SDNode OpNode> { + // 64-bit vector types. + def v8i8 : N2VDSh { + let Inst{21-19} = 0b001; // imm6 = 001xxx + } + def v4i16 : N2VDSh { + let Inst{21-20} = 0b01; // imm6 = 01xxxx + } + def v2i32 : N2VDSh { + let Inst{21} = 0b1; // imm6 = 1xxxxx + } + def v1i64 : N2VDSh; + // imm6 = xxxxxx + + // 128-bit vector types. + def v16i8 : N2VQSh { + let Inst{21-19} = 0b001; // imm6 = 001xxx + } + def v8i16 : N2VQSh { + let Inst{21-20} = 0b01; // imm6 = 01xxxx + } + def v4i32 : N2VQSh { + let Inst{21} = 0b1; // imm6 = 1xxxxx + } + def v2i64 : N2VQSh; + // imm6 = xxxxxx +} + + +// Neon Shift-Accumulate vector operations, +// element sizes of 8, 16, 32 and 64 bits: +multiclass N2VShAdd_QHSD op11_8, bit op4, + string OpcodeStr, string Dt, SDNode ShOp> { + // 64-bit vector types. + def v8i8 : N2VDShAdd { + let Inst{21-19} = 0b001; // imm6 = 001xxx + } + def v4i16 : N2VDShAdd { + let Inst{21-20} = 0b01; // imm6 = 01xxxx + } + def v2i32 : N2VDShAdd { + let Inst{21} = 0b1; // imm6 = 1xxxxx + } + def v1i64 : N2VDShAdd; + // imm6 = xxxxxx + + // 128-bit vector types. + def v16i8 : N2VQShAdd { + let Inst{21-19} = 0b001; // imm6 = 001xxx + } + def v8i16 : N2VQShAdd { + let Inst{21-20} = 0b01; // imm6 = 01xxxx + } + def v4i32 : N2VQShAdd { + let Inst{21} = 0b1; // imm6 = 1xxxxx + } + def v2i64 : N2VQShAdd; + // imm6 = xxxxxx +} + + +// Neon Shift-Insert vector operations, +// element sizes of 8, 16, 32 and 64 bits: +multiclass N2VShIns_QHSD op11_8, bit op4, + string OpcodeStr, SDNode ShOp> { + // 64-bit vector types. + def v8i8 : N2VDShIns { + let Inst{21-19} = 0b001; // imm6 = 001xxx + } + def v4i16 : N2VDShIns { + let Inst{21-20} = 0b01; // imm6 = 01xxxx + } + def v2i32 : N2VDShIns { + let Inst{21} = 0b1; // imm6 = 1xxxxx + } + def v1i64 : N2VDShIns; + // imm6 = xxxxxx + + // 128-bit vector types. + def v16i8 : N2VQShIns { + let Inst{21-19} = 0b001; // imm6 = 001xxx + } + def v8i16 : N2VQShIns { + let Inst{21-20} = 0b01; // imm6 = 01xxxx + } + def v4i32 : N2VQShIns { + let Inst{21} = 0b1; // imm6 = 1xxxxx + } + def v2i64 : N2VQShIns; + // imm6 = xxxxxx +} + +// Neon Shift Long operations, +// element sizes of 8, 16, 32 bits: +multiclass N2VLSh_QHS op11_8, bit op7, bit op6, + bit op4, string OpcodeStr, string Dt, SDNode OpNode> { + def v8i16 : N2VLSh { + let Inst{21-19} = 0b001; // imm6 = 001xxx + } + def v4i32 : N2VLSh { + let Inst{21-20} = 0b01; // imm6 = 01xxxx + } + def v2i64 : N2VLSh { + let Inst{21} = 0b1; // imm6 = 1xxxxx + } +} + +// Neon Shift Narrow operations, +// element sizes of 16, 32, 64 bits: +multiclass N2VNSh_HSD op11_8, bit op7, bit op6, + bit op4, InstrItinClass itin, string OpcodeStr, string Dt, + SDNode OpNode> { + def v8i8 : N2VNSh { + let Inst{21-19} = 0b001; // imm6 = 001xxx + } + def v4i16 : N2VNSh { + let Inst{21-20} = 0b01; // imm6 = 01xxxx + } + def v2i32 : N2VNSh { + let Inst{21} = 0b1; // imm6 = 1xxxxx + } +} + +//===----------------------------------------------------------------------===// +// Instruction Definitions. +//===----------------------------------------------------------------------===// + +// Vector Add Operations. + +// VADD : Vector Add (integer and floating-point) +defm VADD : N3V_QHSD<0, 0, 0b1000, 0, IIC_VBINiD, IIC_VBINiQ, "vadd", "i", + add, 1>; +def VADDfd : N3VD<0, 0, 0b00, 0b1101, 0, IIC_VBIND, "vadd", "f32", + v2f32, v2f32, fadd, 1>; +def VADDfq : N3VQ<0, 0, 0b00, 0b1101, 0, IIC_VBINQ, "vadd", "f32", + v4f32, v4f32, fadd, 1>; +// VADDL : Vector Add Long (Q = D + D) +defm VADDLs : N3VLInt_QHS<0,1,0b0000,0, IIC_VSHLiD, "vaddl", "s", + int_arm_neon_vaddls, 1>; +defm VADDLu : N3VLInt_QHS<1,1,0b0000,0, IIC_VSHLiD, "vaddl", "u", + int_arm_neon_vaddlu, 1>; +// VADDW : Vector Add Wide (Q = Q + D) +defm VADDWs : N3VWInt_QHS<0,1,0b0001,0, "vaddw", "s", int_arm_neon_vaddws, 0>; +defm VADDWu : N3VWInt_QHS<1,1,0b0001,0, "vaddw", "u", int_arm_neon_vaddwu, 0>; +// VHADD : Vector Halving Add +defm VHADDs : N3VInt_QHS<0,0,0b0000,0, IIC_VBINi4D, IIC_VBINi4D, IIC_VBINi4Q, + IIC_VBINi4Q, "vhadd", "s", int_arm_neon_vhadds, 1>; +defm VHADDu : N3VInt_QHS<1,0,0b0000,0, IIC_VBINi4D, IIC_VBINi4D, IIC_VBINi4Q, + IIC_VBINi4Q, "vhadd", "u", int_arm_neon_vhaddu, 1>; +// VRHADD : Vector Rounding Halving Add +defm VRHADDs : N3VInt_QHS<0,0,0b0001,0, IIC_VBINi4D, IIC_VBINi4D, IIC_VBINi4Q, + IIC_VBINi4Q, "vrhadd", "s", int_arm_neon_vrhadds, 1>; +defm VRHADDu : N3VInt_QHS<1,0,0b0001,0, IIC_VBINi4D, IIC_VBINi4D, IIC_VBINi4Q, + IIC_VBINi4Q, "vrhadd", "u", int_arm_neon_vrhaddu, 1>; +// VQADD : Vector Saturating Add +defm VQADDs : N3VInt_QHSD<0,0,0b0000,1, IIC_VBINi4D, IIC_VBINi4D, IIC_VBINi4Q, + IIC_VBINi4Q, "vqadd", "s", int_arm_neon_vqadds, 1>; +defm VQADDu : N3VInt_QHSD<1,0,0b0000,1, IIC_VBINi4D, IIC_VBINi4D, IIC_VBINi4Q, + IIC_VBINi4Q, "vqadd", "u", int_arm_neon_vqaddu, 1>; +// VADDHN : Vector Add and Narrow Returning High Half (D = Q + Q) +defm VADDHN : N3VNInt_HSD<0,1,0b0100,0, "vaddhn", "i", + int_arm_neon_vaddhn, 1>; +// VRADDHN : Vector Rounding Add and Narrow Returning High Half (D = Q + Q) +defm VRADDHN : N3VNInt_HSD<1,1,0b0100,0, "vraddhn", "i", + int_arm_neon_vraddhn, 1>; + +// Vector Multiply Operations. + +// VMUL : Vector Multiply (integer, polynomial and floating-point) +defm VMUL : N3V_QHS<0, 0, 0b1001, 1, IIC_VMULi16D, IIC_VMULi32D, + IIC_VMULi16Q, IIC_VMULi32Q, "vmul", "i", mul, 1>; +def VMULpd : N3VDInt<1, 0, 0b00, 0b1001, 1, IIC_VMULi16D, "vmul", "p8", + v8i8, v8i8, int_arm_neon_vmulp, 1>; +def VMULpq : N3VQInt<1, 0, 0b00, 0b1001, 1, IIC_VMULi16Q, "vmul", "p8", + v16i8, v16i8, int_arm_neon_vmulp, 1>; +def VMULfd : N3VD<1, 0, 0b00, 0b1101, 1, IIC_VBIND, "vmul", "f32", + v2f32, v2f32, fmul, 1>; +def VMULfq : N3VQ<1, 0, 0b00, 0b1101, 1, IIC_VBINQ, "vmul", "f32", + v4f32, v4f32, fmul, 1>; +defm VMULsl : N3VSL_HS<0b1000, "vmul", "i", mul>; +def VMULslfd : N3VDSL<0b10, 0b1001, IIC_VBIND, "vmul", "f32", v2f32, fmul>; +def VMULslfq : N3VQSL<0b10, 0b1001, IIC_VBINQ, "vmul", "f32", v4f32, v2f32, fmul>; +def : Pat<(v8i16 (mul (v8i16 QPR:$src1), + (v8i16 (NEONvduplane (v8i16 QPR:$src2), imm:$lane)))), + (v8i16 (VMULslv8i16 (v8i16 QPR:$src1), + (v4i16 (EXTRACT_SUBREG QPR:$src2, + (DSubReg_i16_reg imm:$lane))), + (SubReg_i16_lane imm:$lane)))>; +def : Pat<(v4i32 (mul (v4i32 QPR:$src1), + (v4i32 (NEONvduplane (v4i32 QPR:$src2), imm:$lane)))), + (v4i32 (VMULslv4i32 (v4i32 QPR:$src1), + (v2i32 (EXTRACT_SUBREG QPR:$src2, + (DSubReg_i32_reg imm:$lane))), + (SubReg_i32_lane imm:$lane)))>; +def : Pat<(v4f32 (fmul (v4f32 QPR:$src1), + (v4f32 (NEONvduplane (v4f32 QPR:$src2), imm:$lane)))), + (v4f32 (VMULslfq (v4f32 QPR:$src1), + (v2f32 (EXTRACT_SUBREG QPR:$src2, + (DSubReg_i32_reg imm:$lane))), + (SubReg_i32_lane imm:$lane)))>; + +// VQDMULH : Vector Saturating Doubling Multiply Returning High Half +defm VQDMULH : N3VInt_HS<0, 0, 0b1011, 0, IIC_VMULi16D, IIC_VMULi32D, + IIC_VMULi16Q, IIC_VMULi32Q, + "vqdmulh", "s", int_arm_neon_vqdmulh, 1>; +defm VQDMULHsl: N3VIntSL_HS<0b1100, IIC_VMULi16D, IIC_VMULi32D, + IIC_VMULi16Q, IIC_VMULi32Q, + "vqdmulh", "s", int_arm_neon_vqdmulh>; +def : Pat<(v8i16 (int_arm_neon_vqdmulh (v8i16 QPR:$src1), + (v8i16 (NEONvduplane (v8i16 QPR:$src2), + imm:$lane)))), + (v8i16 (VQDMULHslv8i16 (v8i16 QPR:$src1), + (v4i16 (EXTRACT_SUBREG QPR:$src2, + (DSubReg_i16_reg imm:$lane))), + (SubReg_i16_lane imm:$lane)))>; +def : Pat<(v4i32 (int_arm_neon_vqdmulh (v4i32 QPR:$src1), + (v4i32 (NEONvduplane (v4i32 QPR:$src2), + imm:$lane)))), + (v4i32 (VQDMULHslv4i32 (v4i32 QPR:$src1), + (v2i32 (EXTRACT_SUBREG QPR:$src2, + (DSubReg_i32_reg imm:$lane))), + (SubReg_i32_lane imm:$lane)))>; + +// VQRDMULH : Vector Rounding Saturating Doubling Multiply Returning High Half +defm VQRDMULH : N3VInt_HS<1, 0, 0b1011, 0, IIC_VMULi16D, IIC_VMULi32D, + IIC_VMULi16Q, IIC_VMULi32Q, + "vqrdmulh", "s", int_arm_neon_vqrdmulh, 1>; +defm VQRDMULHsl : N3VIntSL_HS<0b1101, IIC_VMULi16D, IIC_VMULi32D, + IIC_VMULi16Q, IIC_VMULi32Q, + "vqrdmulh", "s", int_arm_neon_vqrdmulh>; +def : Pat<(v8i16 (int_arm_neon_vqrdmulh (v8i16 QPR:$src1), + (v8i16 (NEONvduplane (v8i16 QPR:$src2), + imm:$lane)))), + (v8i16 (VQRDMULHslv8i16 (v8i16 QPR:$src1), + (v4i16 (EXTRACT_SUBREG QPR:$src2, + (DSubReg_i16_reg imm:$lane))), + (SubReg_i16_lane imm:$lane)))>; +def : Pat<(v4i32 (int_arm_neon_vqrdmulh (v4i32 QPR:$src1), + (v4i32 (NEONvduplane (v4i32 QPR:$src2), + imm:$lane)))), + (v4i32 (VQRDMULHslv4i32 (v4i32 QPR:$src1), + (v2i32 (EXTRACT_SUBREG QPR:$src2, + (DSubReg_i32_reg imm:$lane))), + (SubReg_i32_lane imm:$lane)))>; + +// VMULL : Vector Multiply Long (integer and polynomial) (Q = D * D) +defm VMULLs : N3VLInt_QHS<0,1,0b1100,0, IIC_VMULi16D, "vmull", "s", + int_arm_neon_vmulls, 1>; +defm VMULLu : N3VLInt_QHS<1,1,0b1100,0, IIC_VMULi16D, "vmull", "u", + int_arm_neon_vmullu, 1>; +def VMULLp : N3VLInt<0, 1, 0b00, 0b1110, 0, IIC_VMULi16D, "vmull", "p8", + v8i16, v8i8, int_arm_neon_vmullp, 1>; +defm VMULLsls : N3VLIntSL_HS<0, 0b1010, IIC_VMULi16D, "vmull", "s", + int_arm_neon_vmulls>; +defm VMULLslu : N3VLIntSL_HS<1, 0b1010, IIC_VMULi16D, "vmull", "u", + int_arm_neon_vmullu>; + +// VQDMULL : Vector Saturating Doubling Multiply Long (Q = D * D) +defm VQDMULL : N3VLInt_HS<0,1,0b1101,0, IIC_VMULi16D, "vqdmull", "s", + int_arm_neon_vqdmull, 1>; +defm VQDMULLsl: N3VLIntSL_HS<0, 0b1011, IIC_VMULi16D, "vqdmull", "s", + int_arm_neon_vqdmull>; + +// Vector Multiply-Accumulate and Multiply-Subtract Operations. + +// VMLA : Vector Multiply Accumulate (integer and floating-point) +defm VMLA : N3VMulOp_QHS<0, 0, 0b1001, 0, IIC_VMACi16D, IIC_VMACi32D, + IIC_VMACi16Q, IIC_VMACi32Q, "vmla", "i", add>; +def VMLAfd : N3VDMulOp<0, 0, 0b00, 0b1101, 1, IIC_VMACD, "vmla", "f32", + v2f32, fmul, fadd>; +def VMLAfq : N3VQMulOp<0, 0, 0b00, 0b1101, 1, IIC_VMACQ, "vmla", "f32", + v4f32, fmul, fadd>; +defm VMLAsl : N3VMulOpSL_HS<0b0000, IIC_VMACi16D, IIC_VMACi32D, + IIC_VMACi16Q, IIC_VMACi32Q, "vmla", "i", add>; +def VMLAslfd : N3VDMulOpSL<0b10, 0b0001, IIC_VMACD, "vmla", "f32", + v2f32, fmul, fadd>; +def VMLAslfq : N3VQMulOpSL<0b10, 0b0001, IIC_VMACQ, "vmla", "f32", + v4f32, v2f32, fmul, fadd>; + +def : Pat<(v8i16 (add (v8i16 QPR:$src1), + (mul (v8i16 QPR:$src2), + (v8i16 (NEONvduplane (v8i16 QPR:$src3), imm:$lane))))), + (v8i16 (VMLAslv8i16 (v8i16 QPR:$src1), + (v8i16 QPR:$src2), + (v4i16 (EXTRACT_SUBREG QPR:$src3, + (DSubReg_i16_reg imm:$lane))), + (SubReg_i16_lane imm:$lane)))>; + +def : Pat<(v4i32 (add (v4i32 QPR:$src1), + (mul (v4i32 QPR:$src2), + (v4i32 (NEONvduplane (v4i32 QPR:$src3), imm:$lane))))), + (v4i32 (VMLAslv4i32 (v4i32 QPR:$src1), + (v4i32 QPR:$src2), + (v2i32 (EXTRACT_SUBREG QPR:$src3, + (DSubReg_i32_reg imm:$lane))), + (SubReg_i32_lane imm:$lane)))>; + +def : Pat<(v4f32 (fadd (v4f32 QPR:$src1), + (fmul (v4f32 QPR:$src2), + (v4f32 (NEONvduplane (v4f32 QPR:$src3), imm:$lane))))), + (v4f32 (VMLAslfq (v4f32 QPR:$src1), + (v4f32 QPR:$src2), + (v2f32 (EXTRACT_SUBREG QPR:$src3, + (DSubReg_i32_reg imm:$lane))), + (SubReg_i32_lane imm:$lane)))>; + +// VMLAL : Vector Multiply Accumulate Long (Q += D * D) +defm VMLALs : N3VLInt3_QHS<0,1,0b1000,0, "vmlal", "s", int_arm_neon_vmlals>; +defm VMLALu : N3VLInt3_QHS<1,1,0b1000,0, "vmlal", "u", int_arm_neon_vmlalu>; + +defm VMLALsls : N3VLInt3SL_HS<0, 0b0010, "vmlal", "s", int_arm_neon_vmlals>; +defm VMLALslu : N3VLInt3SL_HS<1, 0b0010, "vmlal", "u", int_arm_neon_vmlalu>; + +// VQDMLAL : Vector Saturating Doubling Multiply Accumulate Long (Q += D * D) +defm VQDMLAL : N3VLInt3_HS<0, 1, 0b1001, 0, "vqdmlal", "s", + int_arm_neon_vqdmlal>; +defm VQDMLALsl: N3VLInt3SL_HS<0, 0b0011, "vqdmlal", "s", int_arm_neon_vqdmlal>; + +// VMLS : Vector Multiply Subtract (integer and floating-point) +defm VMLS : N3VMulOp_QHS<1, 0, 0b1001, 0, IIC_VMACi16D, IIC_VMACi32D, + IIC_VMACi16Q, IIC_VMACi32Q, "vmls", "i", sub>; +def VMLSfd : N3VDMulOp<0, 0, 0b10, 0b1101, 1, IIC_VMACD, "vmls", "f32", + v2f32, fmul, fsub>; +def VMLSfq : N3VQMulOp<0, 0, 0b10, 0b1101, 1, IIC_VMACQ, "vmls", "f32", + v4f32, fmul, fsub>; +defm VMLSsl : N3VMulOpSL_HS<0b0100, IIC_VMACi16D, IIC_VMACi32D, + IIC_VMACi16Q, IIC_VMACi32Q, "vmls", "i", sub>; +def VMLSslfd : N3VDMulOpSL<0b10, 0b0101, IIC_VMACD, "vmls", "f32", + v2f32, fmul, fsub>; +def VMLSslfq : N3VQMulOpSL<0b10, 0b0101, IIC_VMACQ, "vmls", "f32", + v4f32, v2f32, fmul, fsub>; + +def : Pat<(v8i16 (sub (v8i16 QPR:$src1), + (mul (v8i16 QPR:$src2), + (v8i16 (NEONvduplane (v8i16 QPR:$src3), imm:$lane))))), + (v8i16 (VMLSslv8i16 (v8i16 QPR:$src1), + (v8i16 QPR:$src2), + (v4i16 (EXTRACT_SUBREG QPR:$src3, + (DSubReg_i16_reg imm:$lane))), + (SubReg_i16_lane imm:$lane)))>; + +def : Pat<(v4i32 (sub (v4i32 QPR:$src1), + (mul (v4i32 QPR:$src2), + (v4i32 (NEONvduplane (v4i32 QPR:$src3), imm:$lane))))), + (v4i32 (VMLSslv4i32 (v4i32 QPR:$src1), + (v4i32 QPR:$src2), + (v2i32 (EXTRACT_SUBREG QPR:$src3, + (DSubReg_i32_reg imm:$lane))), + (SubReg_i32_lane imm:$lane)))>; + +def : Pat<(v4f32 (fsub (v4f32 QPR:$src1), + (fmul (v4f32 QPR:$src2), + (v4f32 (NEONvduplane (v4f32 QPR:$src3), imm:$lane))))), + (v4f32 (VMLSslfq (v4f32 QPR:$src1), + (v4f32 QPR:$src2), + (v2f32 (EXTRACT_SUBREG QPR:$src3, + (DSubReg_i32_reg imm:$lane))), + (SubReg_i32_lane imm:$lane)))>; + +// VMLSL : Vector Multiply Subtract Long (Q -= D * D) +defm VMLSLs : N3VLInt3_QHS<0,1,0b1010,0, "vmlsl", "s", int_arm_neon_vmlsls>; +defm VMLSLu : N3VLInt3_QHS<1,1,0b1010,0, "vmlsl", "u", int_arm_neon_vmlslu>; + +defm VMLSLsls : N3VLInt3SL_HS<0, 0b0110, "vmlsl", "s", int_arm_neon_vmlsls>; +defm VMLSLslu : N3VLInt3SL_HS<1, 0b0110, "vmlsl", "u", int_arm_neon_vmlslu>; + +// VQDMLSL : Vector Saturating Doubling Multiply Subtract Long (Q -= D * D) +defm VQDMLSL : N3VLInt3_HS<0, 1, 0b1011, 0, "vqdmlsl", "s", + int_arm_neon_vqdmlsl>; +defm VQDMLSLsl: N3VLInt3SL_HS<0, 0b111, "vqdmlsl", "s", int_arm_neon_vqdmlsl>; + +// Vector Subtract Operations. + +// VSUB : Vector Subtract (integer and floating-point) +defm VSUB : N3V_QHSD<1, 0, 0b1000, 0, IIC_VSUBiD, IIC_VSUBiQ, + "vsub", "i", sub, 0>; +def VSUBfd : N3VD<0, 0, 0b10, 0b1101, 0, IIC_VBIND, "vsub", "f32", + v2f32, v2f32, fsub, 0>; +def VSUBfq : N3VQ<0, 0, 0b10, 0b1101, 0, IIC_VBINQ, "vsub", "f32", + v4f32, v4f32, fsub, 0>; +// VSUBL : Vector Subtract Long (Q = D - D) +defm VSUBLs : N3VLInt_QHS<0,1,0b0010,0, IIC_VSHLiD, "vsubl", "s", + int_arm_neon_vsubls, 1>; +defm VSUBLu : N3VLInt_QHS<1,1,0b0010,0, IIC_VSHLiD, "vsubl", "u", + int_arm_neon_vsublu, 1>; +// VSUBW : Vector Subtract Wide (Q = Q - D) +defm VSUBWs : N3VWInt_QHS<0,1,0b0011,0, "vsubw", "s", int_arm_neon_vsubws, 0>; +defm VSUBWu : N3VWInt_QHS<1,1,0b0011,0, "vsubw", "u", int_arm_neon_vsubwu, 0>; +// VHSUB : Vector Halving Subtract +defm VHSUBs : N3VInt_QHS<0, 0, 0b0010, 0, IIC_VBINi4D, IIC_VBINi4D, + IIC_VBINi4Q, IIC_VBINi4Q, + "vhsub", "s", int_arm_neon_vhsubs, 0>; +defm VHSUBu : N3VInt_QHS<1, 0, 0b0010, 0, IIC_VBINi4D, IIC_VBINi4D, + IIC_VBINi4Q, IIC_VBINi4Q, + "vhsub", "u", int_arm_neon_vhsubu, 0>; +// VQSUB : Vector Saturing Subtract +defm VQSUBs : N3VInt_QHSD<0, 0, 0b0010, 1, IIC_VBINi4D, IIC_VBINi4D, + IIC_VBINi4Q, IIC_VBINi4Q, + "vqsub", "s", int_arm_neon_vqsubs, 0>; +defm VQSUBu : N3VInt_QHSD<1, 0, 0b0010, 1, IIC_VBINi4D, IIC_VBINi4D, + IIC_VBINi4Q, IIC_VBINi4Q, + "vqsub", "u", int_arm_neon_vqsubu, 0>; +// VSUBHN : Vector Subtract and Narrow Returning High Half (D = Q - Q) +defm VSUBHN : N3VNInt_HSD<0,1,0b0110,0, "vsubhn", "i", + int_arm_neon_vsubhn, 0>; +// VRSUBHN : Vector Rounding Subtract and Narrow Returning High Half (D=Q-Q) +defm VRSUBHN : N3VNInt_HSD<1,1,0b0110,0, "vrsubhn", "i", + int_arm_neon_vrsubhn, 0>; + +// Vector Comparisons. + +// VCEQ : Vector Compare Equal +defm VCEQ : N3V_QHS<1, 0, 0b1000, 1, IIC_VBINi4D, IIC_VBINi4D, IIC_VBINi4Q, + IIC_VBINi4Q, "vceq", "i", NEONvceq, 1>; +def VCEQfd : N3VD<0,0,0b00,0b1110,0, IIC_VBIND, "vceq", "f32", v2i32, v2f32, + NEONvceq, 1>; +def VCEQfq : N3VQ<0,0,0b00,0b1110,0, IIC_VBINQ, "vceq", "f32", v4i32, v4f32, + NEONvceq, 1>; +// VCGE : Vector Compare Greater Than or Equal +defm VCGEs : N3V_QHS<0, 0, 0b0011, 1, IIC_VBINi4D, IIC_VBINi4D, IIC_VBINi4Q, + IIC_VBINi4Q, "vcge", "s", NEONvcge, 0>; +defm VCGEu : N3V_QHS<1, 0, 0b0011, 1, IIC_VBINi4D, IIC_VBINi4D, IIC_VBINi4Q, + IIC_VBINi4Q, "vcge", "u", NEONvcgeu, 0>; +def VCGEfd : N3VD<1,0,0b00,0b1110,0, IIC_VBIND, "vcge", "f32", + v2i32, v2f32, NEONvcge, 0>; +def VCGEfq : N3VQ<1,0,0b00,0b1110,0, IIC_VBINQ, "vcge", "f32", v4i32, v4f32, + NEONvcge, 0>; +// VCGT : Vector Compare Greater Than +defm VCGTs : N3V_QHS<0, 0, 0b0011, 0, IIC_VBINi4D, IIC_VBINi4D, IIC_VBINi4Q, + IIC_VBINi4Q, "vcgt", "s", NEONvcgt, 0>; +defm VCGTu : N3V_QHS<1, 0, 0b0011, 0, IIC_VBINi4D, IIC_VBINi4D, IIC_VBINi4Q, + IIC_VBINi4Q, "vcgt", "u", NEONvcgtu, 0>; +def VCGTfd : N3VD<1,0,0b10,0b1110,0, IIC_VBIND, "vcgt", "f32", v2i32, v2f32, + NEONvcgt, 0>; +def VCGTfq : N3VQ<1,0,0b10,0b1110,0, IIC_VBINQ, "vcgt", "f32", v4i32, v4f32, + NEONvcgt, 0>; +// VACGE : Vector Absolute Compare Greater Than or Equal (aka VCAGE) +def VACGEd : N3VDInt<1, 0, 0b00, 0b1110, 1, IIC_VBIND, "vacge", "f32", + v2i32, v2f32, int_arm_neon_vacged, 0>; +def VACGEq : N3VQInt<1, 0, 0b00, 0b1110, 1, IIC_VBINQ, "vacge", "f32", + v4i32, v4f32, int_arm_neon_vacgeq, 0>; +// VACGT : Vector Absolute Compare Greater Than (aka VCAGT) +def VACGTd : N3VDInt<1, 0, 0b10, 0b1110, 1, IIC_VBIND, "vacgt", "f32", + v2i32, v2f32, int_arm_neon_vacgtd, 0>; +def VACGTq : N3VQInt<1, 0, 0b10, 0b1110, 1, IIC_VBINQ, "vacgt", "f32", + v4i32, v4f32, int_arm_neon_vacgtq, 0>; +// VTST : Vector Test Bits +defm VTST : N3V_QHS<0, 0, 0b1000, 1, IIC_VBINi4D, IIC_VBINi4D, IIC_VBINi4Q, + IIC_VBINi4Q, "vtst", "i", NEONvtst, 1>; + +// Vector Bitwise Operations. + +// VAND : Vector Bitwise AND +def VANDd : N3VDX<0, 0, 0b00, 0b0001, 1, IIC_VBINiD, "vand", + v2i32, v2i32, and, 1>; +def VANDq : N3VQX<0, 0, 0b00, 0b0001, 1, IIC_VBINiQ, "vand", + v4i32, v4i32, and, 1>; + +// VEOR : Vector Bitwise Exclusive OR +def VEORd : N3VDX<1, 0, 0b00, 0b0001, 1, IIC_VBINiD, "veor", + v2i32, v2i32, xor, 1>; +def VEORq : N3VQX<1, 0, 0b00, 0b0001, 1, IIC_VBINiQ, "veor", + v4i32, v4i32, xor, 1>; + +// VORR : Vector Bitwise OR +def VORRd : N3VDX<0, 0, 0b10, 0b0001, 1, IIC_VBINiD, "vorr", + v2i32, v2i32, or, 1>; +def VORRq : N3VQX<0, 0, 0b10, 0b0001, 1, IIC_VBINiQ, "vorr", + v4i32, v4i32, or, 1>; + +// VBIC : Vector Bitwise Bit Clear (AND NOT) +def VBICd : N3VX<0, 0, 0b01, 0b0001, 0, 1, (outs DPR:$dst), + (ins DPR:$src1, DPR:$src2), IIC_VBINiD, + "vbic", "$dst, $src1, $src2", "", + [(set DPR:$dst, (v2i32 (and DPR:$src1, + (vnot_conv DPR:$src2))))]>; +def VBICq : N3VX<0, 0, 0b01, 0b0001, 1, 1, (outs QPR:$dst), + (ins QPR:$src1, QPR:$src2), IIC_VBINiQ, + "vbic", "$dst, $src1, $src2", "", + [(set QPR:$dst, (v4i32 (and QPR:$src1, + (vnot_conv QPR:$src2))))]>; + +// VORN : Vector Bitwise OR NOT +def VORNd : N3VX<0, 0, 0b11, 0b0001, 0, 1, (outs DPR:$dst), + (ins DPR:$src1, DPR:$src2), IIC_VBINiD, + "vorn", "$dst, $src1, $src2", "", + [(set DPR:$dst, (v2i32 (or DPR:$src1, + (vnot_conv DPR:$src2))))]>; +def VORNq : N3VX<0, 0, 0b11, 0b0001, 1, 1, (outs QPR:$dst), + (ins QPR:$src1, QPR:$src2), IIC_VBINiQ, + "vorn", "$dst, $src1, $src2", "", + [(set QPR:$dst, (v4i32 (or QPR:$src1, + (vnot_conv QPR:$src2))))]>; + +// VMVN : Vector Bitwise NOT +def VMVNd : N2VX<0b11, 0b11, 0b00, 0b00, 0b01011, 0, 0, + (outs DPR:$dst), (ins DPR:$src), IIC_VSHLiD, + "vmvn", "$dst, $src", "", + [(set DPR:$dst, (v2i32 (vnot DPR:$src)))]>; +def VMVNq : N2VX<0b11, 0b11, 0b00, 0b00, 0b01011, 1, 0, + (outs QPR:$dst), (ins QPR:$src), IIC_VSHLiD, + "vmvn", "$dst, $src", "", + [(set QPR:$dst, (v4i32 (vnot QPR:$src)))]>; +def : Pat<(v2i32 (vnot_conv DPR:$src)), (VMVNd DPR:$src)>; +def : Pat<(v4i32 (vnot_conv QPR:$src)), (VMVNq QPR:$src)>; + +// VBSL : Vector Bitwise Select +def VBSLd : N3VX<1, 0, 0b01, 0b0001, 0, 1, (outs DPR:$dst), + (ins DPR:$src1, DPR:$src2, DPR:$src3), IIC_VCNTiD, + "vbsl", "$dst, $src2, $src3", "$src1 = $dst", + [(set DPR:$dst, + (v2i32 (or (and DPR:$src2, DPR:$src1), + (and DPR:$src3, (vnot_conv DPR:$src1)))))]>; +def VBSLq : N3VX<1, 0, 0b01, 0b0001, 1, 1, (outs QPR:$dst), + (ins QPR:$src1, QPR:$src2, QPR:$src3), IIC_VCNTiQ, + "vbsl", "$dst, $src2, $src3", "$src1 = $dst", + [(set QPR:$dst, + (v4i32 (or (and QPR:$src2, QPR:$src1), + (and QPR:$src3, (vnot_conv QPR:$src1)))))]>; + +// VBIF : Vector Bitwise Insert if False +// like VBSL but with: "vbif $dst, $src3, $src1", "$src2 = $dst", +// VBIT : Vector Bitwise Insert if True +// like VBSL but with: "vbit $dst, $src2, $src1", "$src3 = $dst", +// These are not yet implemented. The TwoAddress pass will not go looking +// for equivalent operations with different register constraints; it just +// inserts copies. + +// Vector Absolute Differences. + +// VABD : Vector Absolute Difference +defm VABDs : N3VInt_QHS<0, 0, 0b0111, 0, IIC_VBINi4D, IIC_VBINi4D, + IIC_VBINi4Q, IIC_VBINi4Q, + "vabd", "s", int_arm_neon_vabds, 0>; +defm VABDu : N3VInt_QHS<1, 0, 0b0111, 0, IIC_VBINi4D, IIC_VBINi4D, + IIC_VBINi4Q, IIC_VBINi4Q, + "vabd", "u", int_arm_neon_vabdu, 0>; +def VABDfd : N3VDInt<1, 0, 0b10, 0b1101, 0, IIC_VBIND, + "vabd", "f32", v2f32, v2f32, int_arm_neon_vabds, 0>; +def VABDfq : N3VQInt<1, 0, 0b10, 0b1101, 0, IIC_VBINQ, + "vabd", "f32", v4f32, v4f32, int_arm_neon_vabds, 0>; + +// VABDL : Vector Absolute Difference Long (Q = | D - D |) +defm VABDLs : N3VLInt_QHS<0,1,0b0111,0, IIC_VBINi4Q, + "vabdl", "s", int_arm_neon_vabdls, 0>; +defm VABDLu : N3VLInt_QHS<1,1,0b0111,0, IIC_VBINi4Q, + "vabdl", "u", int_arm_neon_vabdlu, 0>; + +// VABA : Vector Absolute Difference and Accumulate +defm VABAs : N3VInt3_QHS<0,0,0b0111,1, "vaba", "s", int_arm_neon_vabas>; +defm VABAu : N3VInt3_QHS<1,0,0b0111,1, "vaba", "u", int_arm_neon_vabau>; + +// VABAL : Vector Absolute Difference and Accumulate Long (Q += | D - D |) +defm VABALs : N3VLInt3_QHS<0,1,0b0101,0, "vabal", "s", int_arm_neon_vabals>; +defm VABALu : N3VLInt3_QHS<1,1,0b0101,0, "vabal", "u", int_arm_neon_vabalu>; + +// Vector Maximum and Minimum. + +// VMAX : Vector Maximum +defm VMAXs : N3VInt_QHS<0, 0, 0b0110, 0, IIC_VBINi4D, IIC_VBINi4D, IIC_VBINi4Q, + IIC_VBINi4Q, "vmax", "s", int_arm_neon_vmaxs, 1>; +defm VMAXu : N3VInt_QHS<1, 0, 0b0110, 0, IIC_VBINi4D, IIC_VBINi4D, IIC_VBINi4Q, + IIC_VBINi4Q, "vmax", "u", int_arm_neon_vmaxu, 1>; +def VMAXfd : N3VDInt<0, 0, 0b00, 0b1111, 0, IIC_VBIND, "vmax", "f32", + v2f32, v2f32, int_arm_neon_vmaxs, 1>; +def VMAXfq : N3VQInt<0, 0, 0b00, 0b1111, 0, IIC_VBINQ, "vmax", "f32", + v4f32, v4f32, int_arm_neon_vmaxs, 1>; + +// VMIN : Vector Minimum +defm VMINs : N3VInt_QHS<0, 0, 0b0110, 1, IIC_VBINi4D, IIC_VBINi4D, IIC_VBINi4Q, + IIC_VBINi4Q, "vmin", "s", int_arm_neon_vmins, 1>; +defm VMINu : N3VInt_QHS<1, 0, 0b0110, 1, IIC_VBINi4D, IIC_VBINi4D, IIC_VBINi4Q, + IIC_VBINi4Q, "vmin", "u", int_arm_neon_vminu, 1>; +def VMINfd : N3VDInt<0, 0, 0b10, 0b1111, 0, IIC_VBIND, "vmin", "f32", + v2f32, v2f32, int_arm_neon_vmins, 1>; +def VMINfq : N3VQInt<0, 0, 0b10, 0b1111, 0, IIC_VBINQ, "vmin", "f32", + v4f32, v4f32, int_arm_neon_vmins, 1>; + +// Vector Pairwise Operations. + +// VPADD : Vector Pairwise Add +def VPADDi8 : N3VDInt<0, 0, 0b00, 0b1011, 1, IIC_VBINiD, "vpadd", "i8", + v8i8, v8i8, int_arm_neon_vpadd, 0>; +def VPADDi16 : N3VDInt<0, 0, 0b01, 0b1011, 1, IIC_VBINiD, "vpadd", "i16", + v4i16, v4i16, int_arm_neon_vpadd, 0>; +def VPADDi32 : N3VDInt<0, 0, 0b10, 0b1011, 1, IIC_VBINiD, "vpadd", "i32", + v2i32, v2i32, int_arm_neon_vpadd, 0>; +def VPADDf : N3VDInt<1, 0, 0b00, 0b1101, 0, IIC_VBIND, "vpadd", "f32", + v2f32, v2f32, int_arm_neon_vpadd, 0>; + +// VPADDL : Vector Pairwise Add Long +defm VPADDLs : N2VPLInt_QHS<0b11, 0b11, 0b00, 0b00100, 0, "vpaddl", "s", + int_arm_neon_vpaddls>; +defm VPADDLu : N2VPLInt_QHS<0b11, 0b11, 0b00, 0b00101, 0, "vpaddl", "u", + int_arm_neon_vpaddlu>; + +// VPADAL : Vector Pairwise Add and Accumulate Long +defm VPADALs : N2VPLInt2_QHS<0b11, 0b11, 0b00, 0b01100, 0, "vpadal", "s", + int_arm_neon_vpadals>; +defm VPADALu : N2VPLInt2_QHS<0b11, 0b11, 0b00, 0b01101, 0, "vpadal", "u", + int_arm_neon_vpadalu>; + +// VPMAX : Vector Pairwise Maximum +def VPMAXs8 : N3VDInt<0, 0, 0b00, 0b1010, 0, IIC_VBINi4D, "vpmax", "s8", + v8i8, v8i8, int_arm_neon_vpmaxs, 0>; +def VPMAXs16 : N3VDInt<0, 0, 0b01, 0b1010, 0, IIC_VBINi4D, "vpmax", "s16", + v4i16, v4i16, int_arm_neon_vpmaxs, 0>; +def VPMAXs32 : N3VDInt<0, 0, 0b10, 0b1010, 0, IIC_VBINi4D, "vpmax", "s32", + v2i32, v2i32, int_arm_neon_vpmaxs, 0>; +def VPMAXu8 : N3VDInt<1, 0, 0b00, 0b1010, 0, IIC_VBINi4D, "vpmax", "u8", + v8i8, v8i8, int_arm_neon_vpmaxu, 0>; +def VPMAXu16 : N3VDInt<1, 0, 0b01, 0b1010, 0, IIC_VBINi4D, "vpmax", "u16", + v4i16, v4i16, int_arm_neon_vpmaxu, 0>; +def VPMAXu32 : N3VDInt<1, 0, 0b10, 0b1010, 0, IIC_VBINi4D, "vpmax", "u32", + v2i32, v2i32, int_arm_neon_vpmaxu, 0>; +def VPMAXf : N3VDInt<1, 0, 0b00, 0b1111, 0, IIC_VBINi4D, "vpmax", "f32", + v2f32, v2f32, int_arm_neon_vpmaxs, 0>; + +// VPMIN : Vector Pairwise Minimum +def VPMINs8 : N3VDInt<0, 0, 0b00, 0b1010, 1, IIC_VBINi4D, "vpmin", "s8", + v8i8, v8i8, int_arm_neon_vpmins, 0>; +def VPMINs16 : N3VDInt<0, 0, 0b01, 0b1010, 1, IIC_VBINi4D, "vpmin", "s16", + v4i16, v4i16, int_arm_neon_vpmins, 0>; +def VPMINs32 : N3VDInt<0, 0, 0b10, 0b1010, 1, IIC_VBINi4D, "vpmin", "s32", + v2i32, v2i32, int_arm_neon_vpmins, 0>; +def VPMINu8 : N3VDInt<1, 0, 0b00, 0b1010, 1, IIC_VBINi4D, "vpmin", "u8", + v8i8, v8i8, int_arm_neon_vpminu, 0>; +def VPMINu16 : N3VDInt<1, 0, 0b01, 0b1010, 1, IIC_VBINi4D, "vpmin", "u16", + v4i16, v4i16, int_arm_neon_vpminu, 0>; +def VPMINu32 : N3VDInt<1, 0, 0b10, 0b1010, 1, IIC_VBINi4D, "vpmin", "u32", + v2i32, v2i32, int_arm_neon_vpminu, 0>; +def VPMINf : N3VDInt<1, 0, 0b10, 0b1111, 0, IIC_VBINi4D, "vpmin", "f32", + v2f32, v2f32, int_arm_neon_vpmins, 0>; + +// Vector Reciprocal and Reciprocal Square Root Estimate and Step. + +// VRECPE : Vector Reciprocal Estimate +def VRECPEd : N2VDInt<0b11, 0b11, 0b10, 0b11, 0b01000, 0, + IIC_VUNAD, "vrecpe", "u32", + v2i32, v2i32, int_arm_neon_vrecpe>; +def VRECPEq : N2VQInt<0b11, 0b11, 0b10, 0b11, 0b01000, 0, + IIC_VUNAQ, "vrecpe", "u32", + v4i32, v4i32, int_arm_neon_vrecpe>; +def VRECPEfd : N2VDInt<0b11, 0b11, 0b10, 0b11, 0b01010, 0, + IIC_VUNAD, "vrecpe", "f32", + v2f32, v2f32, int_arm_neon_vrecpe>; +def VRECPEfq : N2VQInt<0b11, 0b11, 0b10, 0b11, 0b01010, 0, + IIC_VUNAQ, "vrecpe", "f32", + v4f32, v4f32, int_arm_neon_vrecpe>; + +// VRECPS : Vector Reciprocal Step +def VRECPSfd : N3VDInt<0, 0, 0b00, 0b1111, 1, + IIC_VRECSD, "vrecps", "f32", + v2f32, v2f32, int_arm_neon_vrecps, 1>; +def VRECPSfq : N3VQInt<0, 0, 0b00, 0b1111, 1, + IIC_VRECSQ, "vrecps", "f32", + v4f32, v4f32, int_arm_neon_vrecps, 1>; + +// VRSQRTE : Vector Reciprocal Square Root Estimate +def VRSQRTEd : N2VDInt<0b11, 0b11, 0b10, 0b11, 0b01001, 0, + IIC_VUNAD, "vrsqrte", "u32", + v2i32, v2i32, int_arm_neon_vrsqrte>; +def VRSQRTEq : N2VQInt<0b11, 0b11, 0b10, 0b11, 0b01001, 0, + IIC_VUNAQ, "vrsqrte", "u32", + v4i32, v4i32, int_arm_neon_vrsqrte>; +def VRSQRTEfd : N2VDInt<0b11, 0b11, 0b10, 0b11, 0b01011, 0, + IIC_VUNAD, "vrsqrte", "f32", + v2f32, v2f32, int_arm_neon_vrsqrte>; +def VRSQRTEfq : N2VQInt<0b11, 0b11, 0b10, 0b11, 0b01011, 0, + IIC_VUNAQ, "vrsqrte", "f32", + v4f32, v4f32, int_arm_neon_vrsqrte>; + +// VRSQRTS : Vector Reciprocal Square Root Step +def VRSQRTSfd : N3VDInt<0, 0, 0b10, 0b1111, 1, + IIC_VRECSD, "vrsqrts", "f32", + v2f32, v2f32, int_arm_neon_vrsqrts, 1>; +def VRSQRTSfq : N3VQInt<0, 0, 0b10, 0b1111, 1, + IIC_VRECSQ, "vrsqrts", "f32", + v4f32, v4f32, int_arm_neon_vrsqrts, 1>; + +// Vector Shifts. + +// VSHL : Vector Shift +defm VSHLs : N3VInt_QHSD<0, 0, 0b0100, 0, IIC_VSHLiD, IIC_VSHLiD, IIC_VSHLiQ, + IIC_VSHLiQ, "vshl", "s", int_arm_neon_vshifts, 0>; +defm VSHLu : N3VInt_QHSD<1, 0, 0b0100, 0, IIC_VSHLiD, IIC_VSHLiD, IIC_VSHLiQ, + IIC_VSHLiQ, "vshl", "u", int_arm_neon_vshiftu, 0>; +// VSHL : Vector Shift Left (Immediate) +defm VSHLi : N2VSh_QHSD<0, 1, 0b0101, 1, IIC_VSHLiD, "vshl", "i", NEONvshl>; +// VSHR : Vector Shift Right (Immediate) +defm VSHRs : N2VSh_QHSD<0, 1, 0b0000, 1, IIC_VSHLiD, "vshr", "s", NEONvshrs>; +defm VSHRu : N2VSh_QHSD<1, 1, 0b0000, 1, IIC_VSHLiD, "vshr", "u", NEONvshru>; + +// VSHLL : Vector Shift Left Long +defm VSHLLs : N2VLSh_QHS<0, 1, 0b1010, 0, 0, 1, "vshll", "s", NEONvshlls>; +defm VSHLLu : N2VLSh_QHS<1, 1, 0b1010, 0, 0, 1, "vshll", "u", NEONvshllu>; + +// VSHLL : Vector Shift Left Long (with maximum shift count) +class N2VLShMax op21_16, bits<4> op11_8, bit op7, + bit op6, bit op4, string OpcodeStr, string Dt, ValueType ResTy, + ValueType OpTy, SDNode OpNode> + : N2VLSh { + let Inst{21-16} = op21_16; +} +def VSHLLi8 : N2VLShMax<1, 1, 0b110010, 0b0011, 0, 0, 0, "vshll", "i8", + v8i16, v8i8, NEONvshlli>; +def VSHLLi16 : N2VLShMax<1, 1, 0b110110, 0b0011, 0, 0, 0, "vshll", "i16", + v4i32, v4i16, NEONvshlli>; +def VSHLLi32 : N2VLShMax<1, 1, 0b111010, 0b0011, 0, 0, 0, "vshll", "i32", + v2i64, v2i32, NEONvshlli>; + +// VSHRN : Vector Shift Right and Narrow +defm VSHRN : N2VNSh_HSD<0,1,0b1000,0,0,1, IIC_VSHLiD, "vshrn", "i", NEONvshrn>; + +// VRSHL : Vector Rounding Shift +defm VRSHLs : N3VInt_QHSD<0,0,0b0101,0, IIC_VSHLi4D, IIC_VSHLi4D, IIC_VSHLi4Q, + IIC_VSHLi4Q, "vrshl", "s", int_arm_neon_vrshifts, 0>; +defm VRSHLu : N3VInt_QHSD<1,0,0b0101,0, IIC_VSHLi4D, IIC_VSHLi4D, IIC_VSHLi4Q, + IIC_VSHLi4Q, "vrshl", "u", int_arm_neon_vrshiftu, 0>; +// VRSHR : Vector Rounding Shift Right +defm VRSHRs : N2VSh_QHSD<0, 1, 0b0010, 1, IIC_VSHLi4D, "vrshr", "s", NEONvrshrs>; +defm VRSHRu : N2VSh_QHSD<1, 1, 0b0010, 1, IIC_VSHLi4D, "vrshr", "u", NEONvrshru>; + +// VRSHRN : Vector Rounding Shift Right and Narrow +defm VRSHRN : N2VNSh_HSD<0, 1, 0b1000, 0, 1, 1, IIC_VSHLi4D, "vrshrn", "i", + NEONvrshrn>; + +// VQSHL : Vector Saturating Shift +defm VQSHLs : N3VInt_QHSD<0,0,0b0100,1, IIC_VSHLi4D, IIC_VSHLi4D, IIC_VSHLi4Q, + IIC_VSHLi4Q, "vqshl", "s", int_arm_neon_vqshifts, 0>; +defm VQSHLu : N3VInt_QHSD<1,0,0b0100,1, IIC_VSHLi4D, IIC_VSHLi4D, IIC_VSHLi4Q, + IIC_VSHLi4Q, "vqshl", "u", int_arm_neon_vqshiftu, 0>; +// VQSHL : Vector Saturating Shift Left (Immediate) +defm VQSHLsi : N2VSh_QHSD<0, 1, 0b0111, 1, IIC_VSHLi4D, "vqshl", "s", NEONvqshls>; +defm VQSHLui : N2VSh_QHSD<1, 1, 0b0111, 1, IIC_VSHLi4D, "vqshl", "u", NEONvqshlu>; +// VQSHLU : Vector Saturating Shift Left (Immediate, Unsigned) +defm VQSHLsu : N2VSh_QHSD<1, 1, 0b0110, 1, IIC_VSHLi4D, "vqshlu", "s", NEONvqshlsu>; + +// VQSHRN : Vector Saturating Shift Right and Narrow +defm VQSHRNs : N2VNSh_HSD<0, 1, 0b1001, 0, 0, 1, IIC_VSHLi4D, "vqshrn", "s", + NEONvqshrns>; +defm VQSHRNu : N2VNSh_HSD<1, 1, 0b1001, 0, 0, 1, IIC_VSHLi4D, "vqshrn", "u", + NEONvqshrnu>; + +// VQSHRUN : Vector Saturating Shift Right and Narrow (Unsigned) +defm VQSHRUN : N2VNSh_HSD<1, 1, 0b1000, 0, 0, 1, IIC_VSHLi4D, "vqshrun", "s", + NEONvqshrnsu>; + +// VQRSHL : Vector Saturating Rounding Shift +defm VQRSHLs : N3VInt_QHSD<0, 0, 0b0101, 1, IIC_VSHLi4D, IIC_VSHLi4D, IIC_VSHLi4Q, + IIC_VSHLi4Q, "vqrshl", "s", + int_arm_neon_vqrshifts, 0>; +defm VQRSHLu : N3VInt_QHSD<1, 0, 0b0101, 1, IIC_VSHLi4D, IIC_VSHLi4D, IIC_VSHLi4Q, + IIC_VSHLi4Q, "vqrshl", "u", + int_arm_neon_vqrshiftu, 0>; + +// VQRSHRN : Vector Saturating Rounding Shift Right and Narrow +defm VQRSHRNs : N2VNSh_HSD<0, 1, 0b1001, 0, 1, 1, IIC_VSHLi4D, "vqrshrn", "s", + NEONvqrshrns>; +defm VQRSHRNu : N2VNSh_HSD<1, 1, 0b1001, 0, 1, 1, IIC_VSHLi4D, "vqrshrn", "u", + NEONvqrshrnu>; + +// VQRSHRUN : Vector Saturating Rounding Shift Right and Narrow (Unsigned) +defm VQRSHRUN : N2VNSh_HSD<1, 1, 0b1000, 0, 1, 1, IIC_VSHLi4D, "vqrshrun", "s", + NEONvqrshrnsu>; + +// VSRA : Vector Shift Right and Accumulate +defm VSRAs : N2VShAdd_QHSD<0, 1, 0b0001, 1, "vsra", "s", NEONvshrs>; +defm VSRAu : N2VShAdd_QHSD<1, 1, 0b0001, 1, "vsra", "u", NEONvshru>; +// VRSRA : Vector Rounding Shift Right and Accumulate +defm VRSRAs : N2VShAdd_QHSD<0, 1, 0b0011, 1, "vrsra", "s", NEONvrshrs>; +defm VRSRAu : N2VShAdd_QHSD<1, 1, 0b0011, 1, "vrsra", "u", NEONvrshru>; + +// VSLI : Vector Shift Left and Insert +defm VSLI : N2VShIns_QHSD<1, 1, 0b0101, 1, "vsli", NEONvsli>; +// VSRI : Vector Shift Right and Insert +defm VSRI : N2VShIns_QHSD<1, 1, 0b0100, 1, "vsri", NEONvsri>; + +// Vector Absolute and Saturating Absolute. + +// VABS : Vector Absolute Value +defm VABS : N2VInt_QHS<0b11, 0b11, 0b01, 0b00110, 0, + IIC_VUNAiD, IIC_VUNAiQ, "vabs", "s", + int_arm_neon_vabs>; +def VABSfd : N2VDInt<0b11, 0b11, 0b10, 0b01, 0b01110, 0, + IIC_VUNAD, "vabs", "f32", + v2f32, v2f32, int_arm_neon_vabs>; +def VABSfq : N2VQInt<0b11, 0b11, 0b10, 0b01, 0b01110, 0, + IIC_VUNAQ, "vabs", "f32", + v4f32, v4f32, int_arm_neon_vabs>; + +// VQABS : Vector Saturating Absolute Value +defm VQABS : N2VInt_QHS<0b11, 0b11, 0b00, 0b01110, 0, + IIC_VQUNAiD, IIC_VQUNAiQ, "vqabs", "s", + int_arm_neon_vqabs>; + +// Vector Negate. + +def vneg : PatFrag<(ops node:$in), (sub immAllZerosV, node:$in)>; +def vneg_conv : PatFrag<(ops node:$in), (sub immAllZerosV_bc, node:$in)>; + +class VNEGD size, string OpcodeStr, string Dt, ValueType Ty> + : N2V<0b11, 0b11, size, 0b01, 0b00111, 0, 0, (outs DPR:$dst), (ins DPR:$src), + IIC_VSHLiD, OpcodeStr, Dt, "$dst, $src", "", + [(set DPR:$dst, (Ty (vneg DPR:$src)))]>; +class VNEGQ size, string OpcodeStr, string Dt, ValueType Ty> + : N2V<0b11, 0b11, size, 0b01, 0b00111, 1, 0, (outs QPR:$dst), (ins QPR:$src), + IIC_VSHLiD, OpcodeStr, Dt, "$dst, $src", "", + [(set QPR:$dst, (Ty (vneg QPR:$src)))]>; + +// VNEG : Vector Negate +def VNEGs8d : VNEGD<0b00, "vneg", "s8", v8i8>; +def VNEGs16d : VNEGD<0b01, "vneg", "s16", v4i16>; +def VNEGs32d : VNEGD<0b10, "vneg", "s32", v2i32>; +def VNEGs8q : VNEGQ<0b00, "vneg", "s8", v16i8>; +def VNEGs16q : VNEGQ<0b01, "vneg", "s16", v8i16>; +def VNEGs32q : VNEGQ<0b10, "vneg", "s32", v4i32>; + +// VNEG : Vector Negate (floating-point) +def VNEGf32d : N2V<0b11, 0b11, 0b10, 0b01, 0b01111, 0, 0, + (outs DPR:$dst), (ins DPR:$src), IIC_VUNAD, + "vneg", "f32", "$dst, $src", "", + [(set DPR:$dst, (v2f32 (fneg DPR:$src)))]>; +def VNEGf32q : N2V<0b11, 0b11, 0b10, 0b01, 0b01111, 1, 0, + (outs QPR:$dst), (ins QPR:$src), IIC_VUNAQ, + "vneg", "f32", "$dst, $src", "", + [(set QPR:$dst, (v4f32 (fneg QPR:$src)))]>; + +def : Pat<(v8i8 (vneg_conv DPR:$src)), (VNEGs8d DPR:$src)>; +def : Pat<(v4i16 (vneg_conv DPR:$src)), (VNEGs16d DPR:$src)>; +def : Pat<(v2i32 (vneg_conv DPR:$src)), (VNEGs32d DPR:$src)>; +def : Pat<(v16i8 (vneg_conv QPR:$src)), (VNEGs8q QPR:$src)>; +def : Pat<(v8i16 (vneg_conv QPR:$src)), (VNEGs16q QPR:$src)>; +def : Pat<(v4i32 (vneg_conv QPR:$src)), (VNEGs32q QPR:$src)>; + +// VQNEG : Vector Saturating Negate +defm VQNEG : N2VInt_QHS<0b11, 0b11, 0b00, 0b01111, 0, + IIC_VQUNAiD, IIC_VQUNAiQ, "vqneg", "s", + int_arm_neon_vqneg>; + +// Vector Bit Counting Operations. + +// VCLS : Vector Count Leading Sign Bits +defm VCLS : N2VInt_QHS<0b11, 0b11, 0b00, 0b01000, 0, + IIC_VCNTiD, IIC_VCNTiQ, "vcls", "s", + int_arm_neon_vcls>; +// VCLZ : Vector Count Leading Zeros +defm VCLZ : N2VInt_QHS<0b11, 0b11, 0b00, 0b01001, 0, + IIC_VCNTiD, IIC_VCNTiQ, "vclz", "i", + int_arm_neon_vclz>; +// VCNT : Vector Count One Bits +def VCNTd : N2VDInt<0b11, 0b11, 0b00, 0b00, 0b01010, 0, + IIC_VCNTiD, "vcnt", "8", + v8i8, v8i8, int_arm_neon_vcnt>; +def VCNTq : N2VQInt<0b11, 0b11, 0b00, 0b00, 0b01010, 0, + IIC_VCNTiQ, "vcnt", "8", + v16i8, v16i8, int_arm_neon_vcnt>; + +// Vector Move Operations. + +// VMOV : Vector Move (Register) + +def VMOVDneon: N3VX<0, 0, 0b10, 0b0001, 0, 1, (outs DPR:$dst), (ins DPR:$src), + IIC_VMOVD, "vmov", "$dst, $src", "", []>; +def VMOVQ : N3VX<0, 0, 0b10, 0b0001, 1, 1, (outs QPR:$dst), (ins QPR:$src), + IIC_VMOVD, "vmov", "$dst, $src", "", []>; + +// VMOV : Vector Move (Immediate) + +// VMOV_get_imm8 xform function: convert build_vector to VMOV.i8 imm. +def VMOV_get_imm8 : SDNodeXForm; +def vmovImm8 : PatLeaf<(build_vector), [{ + return ARM::getVMOVImm(N, 1, *CurDAG).getNode() != 0; +}], VMOV_get_imm8>; + +// VMOV_get_imm16 xform function: convert build_vector to VMOV.i16 imm. +def VMOV_get_imm16 : SDNodeXForm; +def vmovImm16 : PatLeaf<(build_vector), [{ + return ARM::getVMOVImm(N, 2, *CurDAG).getNode() != 0; +}], VMOV_get_imm16>; + +// VMOV_get_imm32 xform function: convert build_vector to VMOV.i32 imm. +def VMOV_get_imm32 : SDNodeXForm; +def vmovImm32 : PatLeaf<(build_vector), [{ + return ARM::getVMOVImm(N, 4, *CurDAG).getNode() != 0; +}], VMOV_get_imm32>; + +// VMOV_get_imm64 xform function: convert build_vector to VMOV.i64 imm. +def VMOV_get_imm64 : SDNodeXForm; +def vmovImm64 : PatLeaf<(build_vector), [{ + return ARM::getVMOVImm(N, 8, *CurDAG).getNode() != 0; +}], VMOV_get_imm64>; + +// Note: Some of the cmode bits in the following VMOV instructions need to +// be encoded based on the immed values. + +def VMOVv8i8 : N1ModImm<1, 0b000, 0b1110, 0, 0, 0, 1, (outs DPR:$dst), + (ins h8imm:$SIMM), IIC_VMOVImm, + "vmov", "i8", "$dst, $SIMM", "", + [(set DPR:$dst, (v8i8 vmovImm8:$SIMM))]>; +def VMOVv16i8 : N1ModImm<1, 0b000, 0b1110, 0, 1, 0, 1, (outs QPR:$dst), + (ins h8imm:$SIMM), IIC_VMOVImm, + "vmov", "i8", "$dst, $SIMM", "", + [(set QPR:$dst, (v16i8 vmovImm8:$SIMM))]>; + +def VMOVv4i16 : N1ModImm<1, 0b000, 0b1000, 0, 0, 0, 1, (outs DPR:$dst), + (ins h16imm:$SIMM), IIC_VMOVImm, + "vmov", "i16", "$dst, $SIMM", "", + [(set DPR:$dst, (v4i16 vmovImm16:$SIMM))]>; +def VMOVv8i16 : N1ModImm<1, 0b000, 0b1000, 0, 1, 0, 1, (outs QPR:$dst), + (ins h16imm:$SIMM), IIC_VMOVImm, + "vmov", "i16", "$dst, $SIMM", "", + [(set QPR:$dst, (v8i16 vmovImm16:$SIMM))]>; + +def VMOVv2i32 : N1ModImm<1, 0b000, 0b0000, 0, 0, 0, 1, (outs DPR:$dst), + (ins h32imm:$SIMM), IIC_VMOVImm, + "vmov", "i32", "$dst, $SIMM", "", + [(set DPR:$dst, (v2i32 vmovImm32:$SIMM))]>; +def VMOVv4i32 : N1ModImm<1, 0b000, 0b0000, 0, 1, 0, 1, (outs QPR:$dst), + (ins h32imm:$SIMM), IIC_VMOVImm, + "vmov", "i32", "$dst, $SIMM", "", + [(set QPR:$dst, (v4i32 vmovImm32:$SIMM))]>; + +def VMOVv1i64 : N1ModImm<1, 0b000, 0b1110, 0, 0, 1, 1, (outs DPR:$dst), + (ins h64imm:$SIMM), IIC_VMOVImm, + "vmov", "i64", "$dst, $SIMM", "", + [(set DPR:$dst, (v1i64 vmovImm64:$SIMM))]>; +def VMOVv2i64 : N1ModImm<1, 0b000, 0b1110, 0, 1, 1, 1, (outs QPR:$dst), + (ins h64imm:$SIMM), IIC_VMOVImm, + "vmov", "i64", "$dst, $SIMM", "", + [(set QPR:$dst, (v2i64 vmovImm64:$SIMM))]>; + +// VMOV : Vector Get Lane (move scalar to ARM core register) + +def VGETLNs8 : NVGetLane<{1,1,1,0,0,1,?,1}, 0b1011, {?,?}, + (outs GPR:$dst), (ins DPR:$src, nohash_imm:$lane), + IIC_VMOVSI, "vmov", "s8", "$dst, $src[$lane]", + [(set GPR:$dst, (NEONvgetlanes (v8i8 DPR:$src), + imm:$lane))]>; +def VGETLNs16 : NVGetLane<{1,1,1,0,0,0,?,1}, 0b1011, {?,1}, + (outs GPR:$dst), (ins DPR:$src, nohash_imm:$lane), + IIC_VMOVSI, "vmov", "s16", "$dst, $src[$lane]", + [(set GPR:$dst, (NEONvgetlanes (v4i16 DPR:$src), + imm:$lane))]>; +def VGETLNu8 : NVGetLane<{1,1,1,0,1,1,?,1}, 0b1011, {?,?}, + (outs GPR:$dst), (ins DPR:$src, nohash_imm:$lane), + IIC_VMOVSI, "vmov", "u8", "$dst, $src[$lane]", + [(set GPR:$dst, (NEONvgetlaneu (v8i8 DPR:$src), + imm:$lane))]>; +def VGETLNu16 : NVGetLane<{1,1,1,0,1,0,?,1}, 0b1011, {?,1}, + (outs GPR:$dst), (ins DPR:$src, nohash_imm:$lane), + IIC_VMOVSI, "vmov", "u16", "$dst, $src[$lane]", + [(set GPR:$dst, (NEONvgetlaneu (v4i16 DPR:$src), + imm:$lane))]>; +def VGETLNi32 : NVGetLane<{1,1,1,0,0,0,?,1}, 0b1011, 0b00, + (outs GPR:$dst), (ins DPR:$src, nohash_imm:$lane), + IIC_VMOVSI, "vmov", "32", "$dst, $src[$lane]", + [(set GPR:$dst, (extractelt (v2i32 DPR:$src), + imm:$lane))]>; +// def VGETLNf32: see FMRDH and FMRDL in ARMInstrVFP.td +def : Pat<(NEONvgetlanes (v16i8 QPR:$src), imm:$lane), + (VGETLNs8 (v8i8 (EXTRACT_SUBREG QPR:$src, + (DSubReg_i8_reg imm:$lane))), + (SubReg_i8_lane imm:$lane))>; +def : Pat<(NEONvgetlanes (v8i16 QPR:$src), imm:$lane), + (VGETLNs16 (v4i16 (EXTRACT_SUBREG QPR:$src, + (DSubReg_i16_reg imm:$lane))), + (SubReg_i16_lane imm:$lane))>; +def : Pat<(NEONvgetlaneu (v16i8 QPR:$src), imm:$lane), + (VGETLNu8 (v8i8 (EXTRACT_SUBREG QPR:$src, + (DSubReg_i8_reg imm:$lane))), + (SubReg_i8_lane imm:$lane))>; +def : Pat<(NEONvgetlaneu (v8i16 QPR:$src), imm:$lane), + (VGETLNu16 (v4i16 (EXTRACT_SUBREG QPR:$src, + (DSubReg_i16_reg imm:$lane))), + (SubReg_i16_lane imm:$lane))>; +def : Pat<(extractelt (v4i32 QPR:$src), imm:$lane), + (VGETLNi32 (v2i32 (EXTRACT_SUBREG QPR:$src, + (DSubReg_i32_reg imm:$lane))), + (SubReg_i32_lane imm:$lane))>; +def : Pat<(extractelt (v2f32 DPR:$src1), imm:$src2), + (EXTRACT_SUBREG (v2f32 (COPY_TO_REGCLASS (v2f32 DPR:$src1), DPR_VFP2)), + (SSubReg_f32_reg imm:$src2))>; +def : Pat<(extractelt (v4f32 QPR:$src1), imm:$src2), + (EXTRACT_SUBREG (v4f32 (COPY_TO_REGCLASS (v4f32 QPR:$src1), QPR_VFP2)), + (SSubReg_f32_reg imm:$src2))>; +//def : Pat<(extractelt (v2i64 QPR:$src1), imm:$src2), +// (EXTRACT_SUBREG QPR:$src1, (DSubReg_f64_reg imm:$src2))>; +def : Pat<(extractelt (v2f64 QPR:$src1), imm:$src2), + (EXTRACT_SUBREG QPR:$src1, (DSubReg_f64_reg imm:$src2))>; + + +// VMOV : Vector Set Lane (move ARM core register to scalar) + +let Constraints = "$src1 = $dst" in { +def VSETLNi8 : NVSetLane<{1,1,1,0,0,1,?,0}, 0b1011, {?,?}, (outs DPR:$dst), + (ins DPR:$src1, GPR:$src2, nohash_imm:$lane), + IIC_VMOVISL, "vmov", "8", "$dst[$lane], $src2", + [(set DPR:$dst, (vector_insert (v8i8 DPR:$src1), + GPR:$src2, imm:$lane))]>; +def VSETLNi16 : NVSetLane<{1,1,1,0,0,0,?,0}, 0b1011, {?,1}, (outs DPR:$dst), + (ins DPR:$src1, GPR:$src2, nohash_imm:$lane), + IIC_VMOVISL, "vmov", "16", "$dst[$lane], $src2", + [(set DPR:$dst, (vector_insert (v4i16 DPR:$src1), + GPR:$src2, imm:$lane))]>; +def VSETLNi32 : NVSetLane<{1,1,1,0,0,0,?,0}, 0b1011, 0b00, (outs DPR:$dst), + (ins DPR:$src1, GPR:$src2, nohash_imm:$lane), + IIC_VMOVISL, "vmov", "32", "$dst[$lane], $src2", + [(set DPR:$dst, (insertelt (v2i32 DPR:$src1), + GPR:$src2, imm:$lane))]>; +} +def : Pat<(vector_insert (v16i8 QPR:$src1), GPR:$src2, imm:$lane), + (v16i8 (INSERT_SUBREG QPR:$src1, + (VSETLNi8 (v8i8 (EXTRACT_SUBREG QPR:$src1, + (DSubReg_i8_reg imm:$lane))), + GPR:$src2, (SubReg_i8_lane imm:$lane)), + (DSubReg_i8_reg imm:$lane)))>; +def : Pat<(vector_insert (v8i16 QPR:$src1), GPR:$src2, imm:$lane), + (v8i16 (INSERT_SUBREG QPR:$src1, + (VSETLNi16 (v4i16 (EXTRACT_SUBREG QPR:$src1, + (DSubReg_i16_reg imm:$lane))), + GPR:$src2, (SubReg_i16_lane imm:$lane)), + (DSubReg_i16_reg imm:$lane)))>; +def : Pat<(insertelt (v4i32 QPR:$src1), GPR:$src2, imm:$lane), + (v4i32 (INSERT_SUBREG QPR:$src1, + (VSETLNi32 (v2i32 (EXTRACT_SUBREG QPR:$src1, + (DSubReg_i32_reg imm:$lane))), + GPR:$src2, (SubReg_i32_lane imm:$lane)), + (DSubReg_i32_reg imm:$lane)))>; + +def : Pat<(v2f32 (insertelt DPR:$src1, SPR:$src2, imm:$src3)), + (INSERT_SUBREG (v2f32 (COPY_TO_REGCLASS DPR:$src1, DPR_VFP2)), + SPR:$src2, (SSubReg_f32_reg imm:$src3))>; +def : Pat<(v4f32 (insertelt QPR:$src1, SPR:$src2, imm:$src3)), + (INSERT_SUBREG (v4f32 (COPY_TO_REGCLASS QPR:$src1, QPR_VFP2)), + SPR:$src2, (SSubReg_f32_reg imm:$src3))>; + +//def : Pat<(v2i64 (insertelt QPR:$src1, DPR:$src2, imm:$src3)), +// (INSERT_SUBREG QPR:$src1, DPR:$src2, (DSubReg_f64_reg imm:$src3))>; +def : Pat<(v2f64 (insertelt QPR:$src1, DPR:$src2, imm:$src3)), + (INSERT_SUBREG QPR:$src1, DPR:$src2, (DSubReg_f64_reg imm:$src3))>; + +def : Pat<(v2f32 (scalar_to_vector SPR:$src)), + (INSERT_SUBREG (v2f32 (IMPLICIT_DEF)), SPR:$src, arm_ssubreg_0)>; +def : Pat<(v2f64 (scalar_to_vector DPR:$src)), + (INSERT_SUBREG (v2f64 (IMPLICIT_DEF)), DPR:$src, arm_dsubreg_0)>; +def : Pat<(v4f32 (scalar_to_vector SPR:$src)), + (INSERT_SUBREG (v4f32 (IMPLICIT_DEF)), SPR:$src, arm_ssubreg_0)>; + +def : Pat<(v8i8 (scalar_to_vector GPR:$src)), + (VSETLNi8 (v8i8 (IMPLICIT_DEF)), GPR:$src, (i32 0))>; +def : Pat<(v4i16 (scalar_to_vector GPR:$src)), + (VSETLNi16 (v4i16 (IMPLICIT_DEF)), GPR:$src, (i32 0))>; +def : Pat<(v2i32 (scalar_to_vector GPR:$src)), + (VSETLNi32 (v2i32 (IMPLICIT_DEF)), GPR:$src, (i32 0))>; + +def : Pat<(v16i8 (scalar_to_vector GPR:$src)), + (INSERT_SUBREG (v16i8 (IMPLICIT_DEF)), + (VSETLNi8 (v8i8 (IMPLICIT_DEF)), GPR:$src, (i32 0)), + arm_dsubreg_0)>; +def : Pat<(v8i16 (scalar_to_vector GPR:$src)), + (INSERT_SUBREG (v8i16 (IMPLICIT_DEF)), + (VSETLNi16 (v4i16 (IMPLICIT_DEF)), GPR:$src, (i32 0)), + arm_dsubreg_0)>; +def : Pat<(v4i32 (scalar_to_vector GPR:$src)), + (INSERT_SUBREG (v4i32 (IMPLICIT_DEF)), + (VSETLNi32 (v2i32 (IMPLICIT_DEF)), GPR:$src, (i32 0)), + arm_dsubreg_0)>; + +// VDUP : Vector Duplicate (from ARM core register to all elements) + +class VDUPD opcod1, bits<2> opcod3, string Dt, ValueType Ty> + : NVDup; +class VDUPQ opcod1, bits<2> opcod3, string Dt, ValueType Ty> + : NVDup; + +def VDUP8d : VDUPD<0b11101100, 0b00, "8", v8i8>; +def VDUP16d : VDUPD<0b11101000, 0b01, "16", v4i16>; +def VDUP32d : VDUPD<0b11101000, 0b00, "32", v2i32>; +def VDUP8q : VDUPQ<0b11101110, 0b00, "8", v16i8>; +def VDUP16q : VDUPQ<0b11101010, 0b01, "16", v8i16>; +def VDUP32q : VDUPQ<0b11101010, 0b00, "32", v4i32>; + +def VDUPfd : NVDup<0b11101000, 0b1011, 0b00, (outs DPR:$dst), (ins GPR:$src), + IIC_VMOVIS, "vdup", "32", "$dst, $src", + [(set DPR:$dst, (v2f32 (NEONvdup + (f32 (bitconvert GPR:$src)))))]>; +def VDUPfq : NVDup<0b11101010, 0b1011, 0b00, (outs QPR:$dst), (ins GPR:$src), + IIC_VMOVIS, "vdup", "32", "$dst, $src", + [(set QPR:$dst, (v4f32 (NEONvdup + (f32 (bitconvert GPR:$src)))))]>; + +// VDUP : Vector Duplicate Lane (from scalar to all elements) + +class VDUPLND op19_18, bits<2> op17_16, + string OpcodeStr, string Dt, ValueType Ty> + : N2V<0b11, 0b11, op19_18, op17_16, 0b11000, 0, 0, + (outs DPR:$dst), (ins DPR:$src, nohash_imm:$lane), IIC_VMOVD, + OpcodeStr, Dt, "$dst, $src[$lane]", "", + [(set DPR:$dst, (Ty (NEONvduplane (Ty DPR:$src), imm:$lane)))]>; + +class VDUPLNQ op19_18, bits<2> op17_16, string OpcodeStr, string Dt, + ValueType ResTy, ValueType OpTy> + : N2V<0b11, 0b11, op19_18, op17_16, 0b11000, 1, 0, + (outs QPR:$dst), (ins DPR:$src, nohash_imm:$lane), IIC_VMOVD, + OpcodeStr, Dt, "$dst, $src[$lane]", "", + [(set QPR:$dst, (ResTy (NEONvduplane (OpTy DPR:$src), imm:$lane)))]>; + +// Inst{19-16} is partially specified depending on the element size. + +def VDUPLN8d : VDUPLND<{?,?}, {?,1}, "vdup", "8", v8i8>; +def VDUPLN16d : VDUPLND<{?,?}, {1,0}, "vdup", "16", v4i16>; +def VDUPLN32d : VDUPLND<{?,1}, {0,0}, "vdup", "32", v2i32>; +def VDUPLNfd : VDUPLND<{?,1}, {0,0}, "vdup", "32", v2f32>; +def VDUPLN8q : VDUPLNQ<{?,?}, {?,1}, "vdup", "8", v16i8, v8i8>; +def VDUPLN16q : VDUPLNQ<{?,?}, {1,0}, "vdup", "16", v8i16, v4i16>; +def VDUPLN32q : VDUPLNQ<{?,1}, {0,0}, "vdup", "32", v4i32, v2i32>; +def VDUPLNfq : VDUPLNQ<{?,1}, {0,0}, "vdup", "32", v4f32, v2f32>; + +def : Pat<(v16i8 (NEONvduplane (v16i8 QPR:$src), imm:$lane)), + (v16i8 (VDUPLN8q (v8i8 (EXTRACT_SUBREG QPR:$src, + (DSubReg_i8_reg imm:$lane))), + (SubReg_i8_lane imm:$lane)))>; +def : Pat<(v8i16 (NEONvduplane (v8i16 QPR:$src), imm:$lane)), + (v8i16 (VDUPLN16q (v4i16 (EXTRACT_SUBREG QPR:$src, + (DSubReg_i16_reg imm:$lane))), + (SubReg_i16_lane imm:$lane)))>; +def : Pat<(v4i32 (NEONvduplane (v4i32 QPR:$src), imm:$lane)), + (v4i32 (VDUPLN32q (v2i32 (EXTRACT_SUBREG QPR:$src, + (DSubReg_i32_reg imm:$lane))), + (SubReg_i32_lane imm:$lane)))>; +def : Pat<(v4f32 (NEONvduplane (v4f32 QPR:$src), imm:$lane)), + (v4f32 (VDUPLNfq (v2f32 (EXTRACT_SUBREG QPR:$src, + (DSubReg_i32_reg imm:$lane))), + (SubReg_i32_lane imm:$lane)))>; + +def VDUPfdf : N2V<0b11, 0b11, {?,1}, {0,0}, 0b11000, 0, 0, + (outs DPR:$dst), (ins SPR:$src), + IIC_VMOVD, "vdup", "32", "$dst, ${src:lane}", "", + [(set DPR:$dst, (v2f32 (NEONvdup (f32 SPR:$src))))]>; + +def VDUPfqf : N2V<0b11, 0b11, {?,1}, {0,0}, 0b11000, 1, 0, + (outs QPR:$dst), (ins SPR:$src), + IIC_VMOVD, "vdup", "32", "$dst, ${src:lane}", "", + [(set QPR:$dst, (v4f32 (NEONvdup (f32 SPR:$src))))]>; + +def : Pat<(v2i64 (NEONvduplane (v2i64 QPR:$src), imm:$lane)), + (INSERT_SUBREG QPR:$src, + (i64 (EXTRACT_SUBREG QPR:$src, (DSubReg_f64_reg imm:$lane))), + (DSubReg_f64_other_reg imm:$lane))>; +def : Pat<(v2f64 (NEONvduplane (v2f64 QPR:$src), imm:$lane)), + (INSERT_SUBREG QPR:$src, + (f64 (EXTRACT_SUBREG QPR:$src, (DSubReg_f64_reg imm:$lane))), + (DSubReg_f64_other_reg imm:$lane))>; + +// VMOVN : Vector Narrowing Move +defm VMOVN : N2VNInt_HSD<0b11,0b11,0b10,0b00100,0,0, IIC_VMOVD, + "vmovn", "i", int_arm_neon_vmovn>; +// VQMOVN : Vector Saturating Narrowing Move +defm VQMOVNs : N2VNInt_HSD<0b11,0b11,0b10,0b00101,0,0, IIC_VQUNAiD, + "vqmovn", "s", int_arm_neon_vqmovns>; +defm VQMOVNu : N2VNInt_HSD<0b11,0b11,0b10,0b00101,1,0, IIC_VQUNAiD, + "vqmovn", "u", int_arm_neon_vqmovnu>; +defm VQMOVNsu : N2VNInt_HSD<0b11,0b11,0b10,0b00100,1,0, IIC_VQUNAiD, + "vqmovun", "s", int_arm_neon_vqmovnsu>; +// VMOVL : Vector Lengthening Move +defm VMOVLs : N2VLInt_QHS<0b01,0b10100,0,1, "vmovl", "s", + int_arm_neon_vmovls>; +defm VMOVLu : N2VLInt_QHS<0b11,0b10100,0,1, "vmovl", "u", + int_arm_neon_vmovlu>; + +// Vector Conversions. + +// VCVT : Vector Convert Between Floating-Point and Integers +def VCVTf2sd : N2VD<0b11, 0b11, 0b10, 0b11, 0b01110, 0, "vcvt", "s32.f32", + v2i32, v2f32, fp_to_sint>; +def VCVTf2ud : N2VD<0b11, 0b11, 0b10, 0b11, 0b01111, 0, "vcvt", "u32.f32", + v2i32, v2f32, fp_to_uint>; +def VCVTs2fd : N2VD<0b11, 0b11, 0b10, 0b11, 0b01100, 0, "vcvt", "f32.s32", + v2f32, v2i32, sint_to_fp>; +def VCVTu2fd : N2VD<0b11, 0b11, 0b10, 0b11, 0b01101, 0, "vcvt", "f32.u32", + v2f32, v2i32, uint_to_fp>; + +def VCVTf2sq : N2VQ<0b11, 0b11, 0b10, 0b11, 0b01110, 0, "vcvt", "s32.f32", + v4i32, v4f32, fp_to_sint>; +def VCVTf2uq : N2VQ<0b11, 0b11, 0b10, 0b11, 0b01111, 0, "vcvt", "u32.f32", + v4i32, v4f32, fp_to_uint>; +def VCVTs2fq : N2VQ<0b11, 0b11, 0b10, 0b11, 0b01100, 0, "vcvt", "f32.s32", + v4f32, v4i32, sint_to_fp>; +def VCVTu2fq : N2VQ<0b11, 0b11, 0b10, 0b11, 0b01101, 0, "vcvt", "f32.u32", + v4f32, v4i32, uint_to_fp>; + +// VCVT : Vector Convert Between Floating-Point and Fixed-Point. +def VCVTf2xsd : N2VCvtD<0, 1, 0b1111, 0, 1, "vcvt", "s32.f32", + v2i32, v2f32, int_arm_neon_vcvtfp2fxs>; +def VCVTf2xud : N2VCvtD<1, 1, 0b1111, 0, 1, "vcvt", "u32.f32", + v2i32, v2f32, int_arm_neon_vcvtfp2fxu>; +def VCVTxs2fd : N2VCvtD<0, 1, 0b1110, 0, 1, "vcvt", "f32.s32", + v2f32, v2i32, int_arm_neon_vcvtfxs2fp>; +def VCVTxu2fd : N2VCvtD<1, 1, 0b1110, 0, 1, "vcvt", "f32.u32", + v2f32, v2i32, int_arm_neon_vcvtfxu2fp>; + +def VCVTf2xsq : N2VCvtQ<0, 1, 0b1111, 0, 1, "vcvt", "s32.f32", + v4i32, v4f32, int_arm_neon_vcvtfp2fxs>; +def VCVTf2xuq : N2VCvtQ<1, 1, 0b1111, 0, 1, "vcvt", "u32.f32", + v4i32, v4f32, int_arm_neon_vcvtfp2fxu>; +def VCVTxs2fq : N2VCvtQ<0, 1, 0b1110, 0, 1, "vcvt", "f32.s32", + v4f32, v4i32, int_arm_neon_vcvtfxs2fp>; +def VCVTxu2fq : N2VCvtQ<1, 1, 0b1110, 0, 1, "vcvt", "f32.u32", + v4f32, v4i32, int_arm_neon_vcvtfxu2fp>; + +// Vector Reverse. + +// VREV64 : Vector Reverse elements within 64-bit doublewords + +class VREV64D op19_18, string OpcodeStr, string Dt, ValueType Ty> + : N2V<0b11, 0b11, op19_18, 0b00, 0b00000, 0, 0, (outs DPR:$dst), + (ins DPR:$src), IIC_VMOVD, + OpcodeStr, Dt, "$dst, $src", "", + [(set DPR:$dst, (Ty (NEONvrev64 (Ty DPR:$src))))]>; +class VREV64Q op19_18, string OpcodeStr, string Dt, ValueType Ty> + : N2V<0b11, 0b11, op19_18, 0b00, 0b00000, 1, 0, (outs QPR:$dst), + (ins QPR:$src), IIC_VMOVD, + OpcodeStr, Dt, "$dst, $src", "", + [(set QPR:$dst, (Ty (NEONvrev64 (Ty QPR:$src))))]>; + +def VREV64d8 : VREV64D<0b00, "vrev64", "8", v8i8>; +def VREV64d16 : VREV64D<0b01, "vrev64", "16", v4i16>; +def VREV64d32 : VREV64D<0b10, "vrev64", "32", v2i32>; +def VREV64df : VREV64D<0b10, "vrev64", "32", v2f32>; + +def VREV64q8 : VREV64Q<0b00, "vrev64", "8", v16i8>; +def VREV64q16 : VREV64Q<0b01, "vrev64", "16", v8i16>; +def VREV64q32 : VREV64Q<0b10, "vrev64", "32", v4i32>; +def VREV64qf : VREV64Q<0b10, "vrev64", "32", v4f32>; + +// VREV32 : Vector Reverse elements within 32-bit words + +class VREV32D op19_18, string OpcodeStr, string Dt, ValueType Ty> + : N2V<0b11, 0b11, op19_18, 0b00, 0b00001, 0, 0, (outs DPR:$dst), + (ins DPR:$src), IIC_VMOVD, + OpcodeStr, Dt, "$dst, $src", "", + [(set DPR:$dst, (Ty (NEONvrev32 (Ty DPR:$src))))]>; +class VREV32Q op19_18, string OpcodeStr, string Dt, ValueType Ty> + : N2V<0b11, 0b11, op19_18, 0b00, 0b00001, 1, 0, (outs QPR:$dst), + (ins QPR:$src), IIC_VMOVD, + OpcodeStr, Dt, "$dst, $src", "", + [(set QPR:$dst, (Ty (NEONvrev32 (Ty QPR:$src))))]>; + +def VREV32d8 : VREV32D<0b00, "vrev32", "8", v8i8>; +def VREV32d16 : VREV32D<0b01, "vrev32", "16", v4i16>; + +def VREV32q8 : VREV32Q<0b00, "vrev32", "8", v16i8>; +def VREV32q16 : VREV32Q<0b01, "vrev32", "16", v8i16>; + +// VREV16 : Vector Reverse elements within 16-bit halfwords + +class VREV16D op19_18, string OpcodeStr, string Dt, ValueType Ty> + : N2V<0b11, 0b11, op19_18, 0b00, 0b00010, 0, 0, (outs DPR:$dst), + (ins DPR:$src), IIC_VMOVD, + OpcodeStr, Dt, "$dst, $src", "", + [(set DPR:$dst, (Ty (NEONvrev16 (Ty DPR:$src))))]>; +class VREV16Q op19_18, string OpcodeStr, string Dt, ValueType Ty> + : N2V<0b11, 0b11, op19_18, 0b00, 0b00010, 1, 0, (outs QPR:$dst), + (ins QPR:$src), IIC_VMOVD, + OpcodeStr, Dt, "$dst, $src", "", + [(set QPR:$dst, (Ty (NEONvrev16 (Ty QPR:$src))))]>; + +def VREV16d8 : VREV16D<0b00, "vrev16", "8", v8i8>; +def VREV16q8 : VREV16Q<0b00, "vrev16", "8", v16i8>; + +// Other Vector Shuffles. + +// VEXT : Vector Extract + +class VEXTd + : N3V<0,1,0b11,{?,?,?,?},0,0, (outs DPR:$dst), + (ins DPR:$lhs, DPR:$rhs, i32imm:$index), IIC_VEXTD, + OpcodeStr, Dt, "$dst, $lhs, $rhs, $index", "", + [(set DPR:$dst, (Ty (NEONvext (Ty DPR:$lhs), + (Ty DPR:$rhs), imm:$index)))]>; + +class VEXTq + : N3V<0,1,0b11,{?,?,?,?},1,0, (outs QPR:$dst), + (ins QPR:$lhs, QPR:$rhs, i32imm:$index), IIC_VEXTQ, + OpcodeStr, Dt, "$dst, $lhs, $rhs, $index", "", + [(set QPR:$dst, (Ty (NEONvext (Ty QPR:$lhs), + (Ty QPR:$rhs), imm:$index)))]>; + +def VEXTd8 : VEXTd<"vext", "8", v8i8>; +def VEXTd16 : VEXTd<"vext", "16", v4i16>; +def VEXTd32 : VEXTd<"vext", "32", v2i32>; +def VEXTdf : VEXTd<"vext", "32", v2f32>; + +def VEXTq8 : VEXTq<"vext", "8", v16i8>; +def VEXTq16 : VEXTq<"vext", "16", v8i16>; +def VEXTq32 : VEXTq<"vext", "32", v4i32>; +def VEXTqf : VEXTq<"vext", "32", v4f32>; + +// VTRN : Vector Transpose + +def VTRNd8 : N2VDShuffle<0b00, 0b00001, "vtrn", "8">; +def VTRNd16 : N2VDShuffle<0b01, 0b00001, "vtrn", "16">; +def VTRNd32 : N2VDShuffle<0b10, 0b00001, "vtrn", "32">; + +def VTRNq8 : N2VQShuffle<0b00, 0b00001, IIC_VPERMQ, "vtrn", "8">; +def VTRNq16 : N2VQShuffle<0b01, 0b00001, IIC_VPERMQ, "vtrn", "16">; +def VTRNq32 : N2VQShuffle<0b10, 0b00001, IIC_VPERMQ, "vtrn", "32">; + +// VUZP : Vector Unzip (Deinterleave) + +def VUZPd8 : N2VDShuffle<0b00, 0b00010, "vuzp", "8">; +def VUZPd16 : N2VDShuffle<0b01, 0b00010, "vuzp", "16">; +def VUZPd32 : N2VDShuffle<0b10, 0b00010, "vuzp", "32">; + +def VUZPq8 : N2VQShuffle<0b00, 0b00010, IIC_VPERMQ3, "vuzp", "8">; +def VUZPq16 : N2VQShuffle<0b01, 0b00010, IIC_VPERMQ3, "vuzp", "16">; +def VUZPq32 : N2VQShuffle<0b10, 0b00010, IIC_VPERMQ3, "vuzp", "32">; + +// VZIP : Vector Zip (Interleave) + +def VZIPd8 : N2VDShuffle<0b00, 0b00011, "vzip", "8">; +def VZIPd16 : N2VDShuffle<0b01, 0b00011, "vzip", "16">; +def VZIPd32 : N2VDShuffle<0b10, 0b00011, "vzip", "32">; + +def VZIPq8 : N2VQShuffle<0b00, 0b00011, IIC_VPERMQ3, "vzip", "8">; +def VZIPq16 : N2VQShuffle<0b01, 0b00011, IIC_VPERMQ3, "vzip", "16">; +def VZIPq32 : N2VQShuffle<0b10, 0b00011, IIC_VPERMQ3, "vzip", "32">; + +// Vector Table Lookup and Table Extension. + +// VTBL : Vector Table Lookup +def VTBL1 + : N3V<1,1,0b11,0b1000,0,0, (outs DPR:$dst), + (ins DPR:$tbl1, DPR:$src), IIC_VTB1, + "vtbl", "8", "$dst, \\{$tbl1\\}, $src", "", + [(set DPR:$dst, (v8i8 (int_arm_neon_vtbl1 DPR:$tbl1, DPR:$src)))]>; +let hasExtraSrcRegAllocReq = 1 in { +def VTBL2 + : N3V<1,1,0b11,0b1001,0,0, (outs DPR:$dst), + (ins DPR:$tbl1, DPR:$tbl2, DPR:$src), IIC_VTB2, + "vtbl", "8", "$dst, \\{$tbl1,$tbl2\\}, $src", "", + [(set DPR:$dst, (v8i8 (int_arm_neon_vtbl2 + DPR:$tbl1, DPR:$tbl2, DPR:$src)))]>; +def VTBL3 + : N3V<1,1,0b11,0b1010,0,0, (outs DPR:$dst), + (ins DPR:$tbl1, DPR:$tbl2, DPR:$tbl3, DPR:$src), IIC_VTB3, + "vtbl", "8", "$dst, \\{$tbl1,$tbl2,$tbl3\\}, $src", "", + [(set DPR:$dst, (v8i8 (int_arm_neon_vtbl3 + DPR:$tbl1, DPR:$tbl2, DPR:$tbl3, DPR:$src)))]>; +def VTBL4 + : N3V<1,1,0b11,0b1011,0,0, (outs DPR:$dst), + (ins DPR:$tbl1, DPR:$tbl2, DPR:$tbl3, DPR:$tbl4, DPR:$src), IIC_VTB4, + "vtbl", "8", "$dst, \\{$tbl1,$tbl2,$tbl3,$tbl4\\}, $src", "", + [(set DPR:$dst, (v8i8 (int_arm_neon_vtbl4 DPR:$tbl1, DPR:$tbl2, + DPR:$tbl3, DPR:$tbl4, DPR:$src)))]>; +} // hasExtraSrcRegAllocReq = 1 + +// VTBX : Vector Table Extension +def VTBX1 + : N3V<1,1,0b11,0b1000,1,0, (outs DPR:$dst), + (ins DPR:$orig, DPR:$tbl1, DPR:$src), IIC_VTBX1, + "vtbx", "8", "$dst, \\{$tbl1\\}, $src", "$orig = $dst", + [(set DPR:$dst, (v8i8 (int_arm_neon_vtbx1 + DPR:$orig, DPR:$tbl1, DPR:$src)))]>; +let hasExtraSrcRegAllocReq = 1 in { +def VTBX2 + : N3V<1,1,0b11,0b1001,1,0, (outs DPR:$dst), + (ins DPR:$orig, DPR:$tbl1, DPR:$tbl2, DPR:$src), IIC_VTBX2, + "vtbx", "8", "$dst, \\{$tbl1,$tbl2\\}, $src", "$orig = $dst", + [(set DPR:$dst, (v8i8 (int_arm_neon_vtbx2 + DPR:$orig, DPR:$tbl1, DPR:$tbl2, DPR:$src)))]>; +def VTBX3 + : N3V<1,1,0b11,0b1010,1,0, (outs DPR:$dst), + (ins DPR:$orig, DPR:$tbl1, DPR:$tbl2, DPR:$tbl3, DPR:$src), IIC_VTBX3, + "vtbx", "8", "$dst, \\{$tbl1,$tbl2,$tbl3\\}, $src", "$orig = $dst", + [(set DPR:$dst, (v8i8 (int_arm_neon_vtbx3 DPR:$orig, DPR:$tbl1, + DPR:$tbl2, DPR:$tbl3, DPR:$src)))]>; +def VTBX4 + : N3V<1,1,0b11,0b1011,1,0, (outs DPR:$dst), (ins DPR:$orig, DPR:$tbl1, + DPR:$tbl2, DPR:$tbl3, DPR:$tbl4, DPR:$src), IIC_VTBX4, + "vtbx", "8", "$dst, \\{$tbl1,$tbl2,$tbl3,$tbl4\\}, $src", "$orig = $dst", + [(set DPR:$dst, (v8i8 (int_arm_neon_vtbx4 DPR:$orig, DPR:$tbl1, + DPR:$tbl2, DPR:$tbl3, DPR:$tbl4, DPR:$src)))]>; +} // hasExtraSrcRegAllocReq = 1 + +//===----------------------------------------------------------------------===// +// NEON instructions for single-precision FP math +//===----------------------------------------------------------------------===// + +// These need separate instructions because they must use DPR_VFP2 register +// class which have SPR sub-registers. + +// Vector Add Operations used for single-precision FP +let neverHasSideEffects = 1 in +def VADDfd_sfp : N3VDs<0, 0, 0b00, 0b1101, 0, "vadd", "f32", v2f32, v2f32, fadd,1>; +def : N3VDsPat; + +// Vector Sub Operations used for single-precision FP +let neverHasSideEffects = 1 in +def VSUBfd_sfp : N3VDs<0, 0, 0b10, 0b1101, 0, "vsub", "f32", v2f32, v2f32, fsub,0>; +def : N3VDsPat; + +// Vector Multiply Operations used for single-precision FP +let neverHasSideEffects = 1 in +def VMULfd_sfp : N3VDs<1, 0, 0b00, 0b1101, 1, "vmul", "f32", v2f32, v2f32, fmul,1>; +def : N3VDsPat; + +// Vector Multiply-Accumulate/Subtract used for single-precision FP +// vml[as].f32 can cause 4-8 cycle stalls in following ASIMD instructions, so +// we want to avoid them for now. e.g., alternating vmla/vadd instructions. + +//let neverHasSideEffects = 1 in +//def VMLAfd_sfp : N3VDMulOps<0, 0, 0b00, 0b1101, 1, IIC_VMACD, "vmla", "f32", v2f32,fmul,fadd>; +//def : N3VDMulOpsPat; + +//let neverHasSideEffects = 1 in +//def VMLSfd_sfp : N3VDMulOps<0, 0, 0b10, 0b1101, 1, IIC_VMACD, "vmls", "f32", v2f32,fmul,fsub>; +//def : N3VDMulOpsPat; + +// Vector Absolute used for single-precision FP +let neverHasSideEffects = 1 in +def VABSfd_sfp : N2VDInts<0b11, 0b11, 0b10, 0b01, 0b01110, 0, + IIC_VUNAD, "vabs", "f32", + v2f32, v2f32, int_arm_neon_vabs>; +def : N2VDIntsPat; + +// Vector Negate used for single-precision FP +let neverHasSideEffects = 1 in +def VNEGf32d_sfp : N2V<0b11, 0b11, 0b10, 0b01, 0b01111, 0, 0, + (outs DPR_VFP2:$dst), (ins DPR_VFP2:$src), IIC_VUNAD, + "vneg", "f32", "$dst, $src", "", []>; +def : N2VDIntsPat; + +// Vector Convert between single-precision FP and integer +let neverHasSideEffects = 1 in +def VCVTf2sd_sfp : N2VDs<0b11, 0b11, 0b10, 0b11, 0b01110, 0, "vcvt", "s32.f32", + v2i32, v2f32, fp_to_sint>; +def : N2VDsPat; + +let neverHasSideEffects = 1 in +def VCVTf2ud_sfp : N2VDs<0b11, 0b11, 0b10, 0b11, 0b01111, 0, "vcvt", "u32.f32", + v2i32, v2f32, fp_to_uint>; +def : N2VDsPat; + +let neverHasSideEffects = 1 in +def VCVTs2fd_sfp : N2VDs<0b11, 0b11, 0b10, 0b11, 0b01100, 0, "vcvt", "f32.s32", + v2f32, v2i32, sint_to_fp>; +def : N2VDsPat; + +let neverHasSideEffects = 1 in +def VCVTu2fd_sfp : N2VDs<0b11, 0b11, 0b10, 0b11, 0b01101, 0, "vcvt", "f32.u32", + v2f32, v2i32, uint_to_fp>; +def : N2VDsPat; + +//===----------------------------------------------------------------------===// +// Non-Instruction Patterns +//===----------------------------------------------------------------------===// + +// bit_convert +def : Pat<(v1i64 (bitconvert (v2i32 DPR:$src))), (v1i64 DPR:$src)>; +def : Pat<(v1i64 (bitconvert (v4i16 DPR:$src))), (v1i64 DPR:$src)>; +def : Pat<(v1i64 (bitconvert (v8i8 DPR:$src))), (v1i64 DPR:$src)>; +def : Pat<(v1i64 (bitconvert (f64 DPR:$src))), (v1i64 DPR:$src)>; +def : Pat<(v1i64 (bitconvert (v2f32 DPR:$src))), (v1i64 DPR:$src)>; +def : Pat<(v2i32 (bitconvert (v1i64 DPR:$src))), (v2i32 DPR:$src)>; +def : Pat<(v2i32 (bitconvert (v4i16 DPR:$src))), (v2i32 DPR:$src)>; +def : Pat<(v2i32 (bitconvert (v8i8 DPR:$src))), (v2i32 DPR:$src)>; +def : Pat<(v2i32 (bitconvert (f64 DPR:$src))), (v2i32 DPR:$src)>; +def : Pat<(v2i32 (bitconvert (v2f32 DPR:$src))), (v2i32 DPR:$src)>; +def : Pat<(v4i16 (bitconvert (v1i64 DPR:$src))), (v4i16 DPR:$src)>; +def : Pat<(v4i16 (bitconvert (v2i32 DPR:$src))), (v4i16 DPR:$src)>; +def : Pat<(v4i16 (bitconvert (v8i8 DPR:$src))), (v4i16 DPR:$src)>; +def : Pat<(v4i16 (bitconvert (f64 DPR:$src))), (v4i16 DPR:$src)>; +def : Pat<(v4i16 (bitconvert (v2f32 DPR:$src))), (v4i16 DPR:$src)>; +def : Pat<(v8i8 (bitconvert (v1i64 DPR:$src))), (v8i8 DPR:$src)>; +def : Pat<(v8i8 (bitconvert (v2i32 DPR:$src))), (v8i8 DPR:$src)>; +def : Pat<(v8i8 (bitconvert (v4i16 DPR:$src))), (v8i8 DPR:$src)>; +def : Pat<(v8i8 (bitconvert (f64 DPR:$src))), (v8i8 DPR:$src)>; +def : Pat<(v8i8 (bitconvert (v2f32 DPR:$src))), (v8i8 DPR:$src)>; +def : Pat<(f64 (bitconvert (v1i64 DPR:$src))), (f64 DPR:$src)>; +def : Pat<(f64 (bitconvert (v2i32 DPR:$src))), (f64 DPR:$src)>; +def : Pat<(f64 (bitconvert (v4i16 DPR:$src))), (f64 DPR:$src)>; +def : Pat<(f64 (bitconvert (v8i8 DPR:$src))), (f64 DPR:$src)>; +def : Pat<(f64 (bitconvert (v2f32 DPR:$src))), (f64 DPR:$src)>; +def : Pat<(v2f32 (bitconvert (f64 DPR:$src))), (v2f32 DPR:$src)>; +def : Pat<(v2f32 (bitconvert (v1i64 DPR:$src))), (v2f32 DPR:$src)>; +def : Pat<(v2f32 (bitconvert (v2i32 DPR:$src))), (v2f32 DPR:$src)>; +def : Pat<(v2f32 (bitconvert (v4i16 DPR:$src))), (v2f32 DPR:$src)>; +def : Pat<(v2f32 (bitconvert (v8i8 DPR:$src))), (v2f32 DPR:$src)>; + +def : Pat<(v2i64 (bitconvert (v4i32 QPR:$src))), (v2i64 QPR:$src)>; +def : Pat<(v2i64 (bitconvert (v8i16 QPR:$src))), (v2i64 QPR:$src)>; +def : Pat<(v2i64 (bitconvert (v16i8 QPR:$src))), (v2i64 QPR:$src)>; +def : Pat<(v2i64 (bitconvert (v2f64 QPR:$src))), (v2i64 QPR:$src)>; +def : Pat<(v2i64 (bitconvert (v4f32 QPR:$src))), (v2i64 QPR:$src)>; +def : Pat<(v4i32 (bitconvert (v2i64 QPR:$src))), (v4i32 QPR:$src)>; +def : Pat<(v4i32 (bitconvert (v8i16 QPR:$src))), (v4i32 QPR:$src)>; +def : Pat<(v4i32 (bitconvert (v16i8 QPR:$src))), (v4i32 QPR:$src)>; +def : Pat<(v4i32 (bitconvert (v2f64 QPR:$src))), (v4i32 QPR:$src)>; +def : Pat<(v4i32 (bitconvert (v4f32 QPR:$src))), (v4i32 QPR:$src)>; +def : Pat<(v8i16 (bitconvert (v2i64 QPR:$src))), (v8i16 QPR:$src)>; +def : Pat<(v8i16 (bitconvert (v4i32 QPR:$src))), (v8i16 QPR:$src)>; +def : Pat<(v8i16 (bitconvert (v16i8 QPR:$src))), (v8i16 QPR:$src)>; +def : Pat<(v8i16 (bitconvert (v2f64 QPR:$src))), (v8i16 QPR:$src)>; +def : Pat<(v8i16 (bitconvert (v4f32 QPR:$src))), (v8i16 QPR:$src)>; +def : Pat<(v16i8 (bitconvert (v2i64 QPR:$src))), (v16i8 QPR:$src)>; +def : Pat<(v16i8 (bitconvert (v4i32 QPR:$src))), (v16i8 QPR:$src)>; +def : Pat<(v16i8 (bitconvert (v8i16 QPR:$src))), (v16i8 QPR:$src)>; +def : Pat<(v16i8 (bitconvert (v2f64 QPR:$src))), (v16i8 QPR:$src)>; +def : Pat<(v16i8 (bitconvert (v4f32 QPR:$src))), (v16i8 QPR:$src)>; +def : Pat<(v4f32 (bitconvert (v2i64 QPR:$src))), (v4f32 QPR:$src)>; +def : Pat<(v4f32 (bitconvert (v4i32 QPR:$src))), (v4f32 QPR:$src)>; +def : Pat<(v4f32 (bitconvert (v8i16 QPR:$src))), (v4f32 QPR:$src)>; +def : Pat<(v4f32 (bitconvert (v16i8 QPR:$src))), (v4f32 QPR:$src)>; +def : Pat<(v4f32 (bitconvert (v2f64 QPR:$src))), (v4f32 QPR:$src)>; +def : Pat<(v2f64 (bitconvert (v2i64 QPR:$src))), (v2f64 QPR:$src)>; +def : Pat<(v2f64 (bitconvert (v4i32 QPR:$src))), (v2f64 QPR:$src)>; +def : Pat<(v2f64 (bitconvert (v8i16 QPR:$src))), (v2f64 QPR:$src)>; +def : Pat<(v2f64 (bitconvert (v16i8 QPR:$src))), (v2f64 QPR:$src)>; +def : Pat<(v2f64 (bitconvert (v4f32 QPR:$src))), (v2f64 QPR:$src)>; diff --git a/libclamav/c++/llvm/lib/Target/ARM/ARMInstrThumb.td b/libclamav/c++/llvm/lib/Target/ARM/ARMInstrThumb.td new file mode 100644 index 000000000..b5956a32c --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/ARM/ARMInstrThumb.td @@ -0,0 +1,758 @@ +//===- ARMInstrThumb.td - Thumb support for ARM ---------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file describes the Thumb instruction set. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// Thumb specific DAG Nodes. +// + +def ARMtcall : SDNode<"ARMISD::tCALL", SDT_ARMcall, + [SDNPHasChain, SDNPOptInFlag, SDNPOutFlag]>; + +def imm_neg_XFORM : SDNodeXFormgetTargetConstant(-(int)N->getZExtValue(), MVT::i32); +}]>; +def imm_comp_XFORM : SDNodeXFormgetTargetConstant(~((uint32_t)N->getZExtValue()), MVT::i32); +}]>; + + +/// imm0_7 predicate - True if the 32-bit immediate is in the range [0,7]. +def imm0_7 : PatLeaf<(i32 imm), [{ + return (uint32_t)N->getZExtValue() < 8; +}]>; +def imm0_7_neg : PatLeaf<(i32 imm), [{ + return (uint32_t)-N->getZExtValue() < 8; +}], imm_neg_XFORM>; + +def imm0_255 : PatLeaf<(i32 imm), [{ + return (uint32_t)N->getZExtValue() < 256; +}]>; +def imm0_255_comp : PatLeaf<(i32 imm), [{ + return ~((uint32_t)N->getZExtValue()) < 256; +}]>; + +def imm8_255 : PatLeaf<(i32 imm), [{ + return (uint32_t)N->getZExtValue() >= 8 && (uint32_t)N->getZExtValue() < 256; +}]>; +def imm8_255_neg : PatLeaf<(i32 imm), [{ + unsigned Val = -N->getZExtValue(); + return Val >= 8 && Val < 256; +}], imm_neg_XFORM>; + +// Break imm's up into two pieces: an immediate + a left shift. +// This uses thumb_immshifted to match and thumb_immshifted_val and +// thumb_immshifted_shamt to get the val/shift pieces. +def thumb_immshifted : PatLeaf<(imm), [{ + return ARM_AM::isThumbImmShiftedVal((unsigned)N->getZExtValue()); +}]>; + +def thumb_immshifted_val : SDNodeXFormgetZExtValue()); + return CurDAG->getTargetConstant(V, MVT::i32); +}]>; + +def thumb_immshifted_shamt : SDNodeXFormgetZExtValue()); + return CurDAG->getTargetConstant(V, MVT::i32); +}]>; + +// Scaled 4 immediate. +def t_imm_s4 : Operand { + let PrintMethod = "printThumbS4ImmOperand"; +} + +// Define Thumb specific addressing modes. + +// t_addrmode_rr := reg + reg +// +def t_addrmode_rr : Operand, + ComplexPattern { + let PrintMethod = "printThumbAddrModeRROperand"; + let MIOperandInfo = (ops tGPR:$base, tGPR:$offsreg); +} + +// t_addrmode_s4 := reg + reg +// reg + imm5 * 4 +// +def t_addrmode_s4 : Operand, + ComplexPattern { + let PrintMethod = "printThumbAddrModeS4Operand"; + let MIOperandInfo = (ops tGPR:$base, i32imm:$offsimm, tGPR:$offsreg); +} + +// t_addrmode_s2 := reg + reg +// reg + imm5 * 2 +// +def t_addrmode_s2 : Operand, + ComplexPattern { + let PrintMethod = "printThumbAddrModeS2Operand"; + let MIOperandInfo = (ops tGPR:$base, i32imm:$offsimm, tGPR:$offsreg); +} + +// t_addrmode_s1 := reg + reg +// reg + imm5 +// +def t_addrmode_s1 : Operand, + ComplexPattern { + let PrintMethod = "printThumbAddrModeS1Operand"; + let MIOperandInfo = (ops tGPR:$base, i32imm:$offsimm, tGPR:$offsreg); +} + +// t_addrmode_sp := sp + imm8 * 4 +// +def t_addrmode_sp : Operand, + ComplexPattern { + let PrintMethod = "printThumbAddrModeSPOperand"; + let MIOperandInfo = (ops tGPR:$base, i32imm:$offsimm); +} + +//===----------------------------------------------------------------------===// +// Miscellaneous Instructions. +// + +let Defs = [SP], Uses = [SP] in { +def tADJCALLSTACKUP : +PseudoInst<(outs), (ins i32imm:$amt1, i32imm:$amt2), NoItinerary, + "@ tADJCALLSTACKUP $amt1", + [(ARMcallseq_end imm:$amt1, imm:$amt2)]>, Requires<[IsThumb1Only]>; + +def tADJCALLSTACKDOWN : +PseudoInst<(outs), (ins i32imm:$amt), NoItinerary, + "@ tADJCALLSTACKDOWN $amt", + [(ARMcallseq_start imm:$amt)]>, Requires<[IsThumb1Only]>; +} + +// For both thumb1 and thumb2. +let isNotDuplicable = 1 in +def tPICADD : TIt<(outs GPR:$dst), (ins GPR:$lhs, pclabel:$cp), IIC_iALUr, + "\n$cp:\n\tadd\t$dst, pc", + [(set GPR:$dst, (ARMpic_add GPR:$lhs, imm:$cp))]>; + +// PC relative add. +def tADDrPCi : T1I<(outs tGPR:$dst), (ins t_imm_s4:$rhs), IIC_iALUi, + "add\t$dst, pc, $rhs", []>; + +// ADD rd, sp, #imm8 +def tADDrSPi : T1I<(outs tGPR:$dst), (ins GPR:$sp, t_imm_s4:$rhs), IIC_iALUi, + "add\t$dst, $sp, $rhs", []>; + +// ADD sp, sp, #imm7 +def tADDspi : TIt<(outs GPR:$dst), (ins GPR:$lhs, t_imm_s4:$rhs), IIC_iALUi, + "add\t$dst, $rhs", []>; + +// SUB sp, sp, #imm7 +def tSUBspi : TIt<(outs GPR:$dst), (ins GPR:$lhs, t_imm_s4:$rhs), IIC_iALUi, + "sub\t$dst, $rhs", []>; + +// ADD rm, sp +def tADDrSP : TIt<(outs GPR:$dst), (ins GPR:$lhs, GPR:$rhs), IIC_iALUr, + "add\t$dst, $rhs", []>; + +// ADD sp, rm +def tADDspr : TIt<(outs GPR:$dst), (ins GPR:$lhs, GPR:$rhs), IIC_iALUr, + "add\t$dst, $rhs", []>; + +// Pseudo instruction that will expand into a tSUBspi + a copy. +let usesCustomInserter = 1 in { // Expanded after instruction selection. +def tSUBspi_ : PseudoInst<(outs GPR:$dst), (ins GPR:$lhs, t_imm_s4:$rhs), + NoItinerary, "@ sub\t$dst, $rhs", []>; + +def tADDspr_ : PseudoInst<(outs GPR:$dst), (ins GPR:$lhs, GPR:$rhs), + NoItinerary, "@ add\t$dst, $rhs", []>; + +let Defs = [CPSR] in +def tANDsp : PseudoInst<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), + NoItinerary, "@ and\t$dst, $rhs", []>; +} // usesCustomInserter + +//===----------------------------------------------------------------------===// +// Control Flow Instructions. +// + +let isReturn = 1, isTerminator = 1, isBarrier = 1 in { + def tBX_RET : TI<(outs), (ins), IIC_Br, "bx\tlr", [(ARMretflag)]>; + // Alternative return instruction used by vararg functions. + def tBX_RET_vararg : TI<(outs), (ins tGPR:$target), IIC_Br, "bx\t$target", []>; +} + +// Indirect branches +let isBranch = 1, isTerminator = 1, isBarrier = 1, isIndirectBranch = 1 in { + def tBRIND : TI<(outs), (ins GPR:$dst), IIC_Br, "mov\tpc, $dst", + [(brind GPR:$dst)]>; +} + +// FIXME: remove when we have a way to marking a MI with these properties. +let isReturn = 1, isTerminator = 1, isBarrier = 1, mayLoad = 1, + hasExtraDefRegAllocReq = 1 in +def tPOP_RET : T1I<(outs), (ins pred:$p, reglist:$wb, variable_ops), IIC_Br, + "pop${p}\t$wb", []>; + +let isCall = 1, + Defs = [R0, R1, R2, R3, R12, LR, + D0, D1, D2, D3, D4, D5, D6, D7, + D16, D17, D18, D19, D20, D21, D22, D23, + D24, D25, D26, D27, D28, D29, D30, D31, CPSR, FPSCR] in { + // Also used for Thumb2 + def tBL : TIx2<(outs), (ins i32imm:$func, variable_ops), IIC_Br, + "bl\t${func:call}", + [(ARMtcall tglobaladdr:$func)]>, + Requires<[IsThumb, IsNotDarwin]>; + + // ARMv5T and above, also used for Thumb2 + def tBLXi : TIx2<(outs), (ins i32imm:$func, variable_ops), IIC_Br, + "blx\t${func:call}", + [(ARMcall tglobaladdr:$func)]>, + Requires<[IsThumb, HasV5T, IsNotDarwin]>; + + // Also used for Thumb2 + def tBLXr : TI<(outs), (ins GPR:$func, variable_ops), IIC_Br, + "blx\t$func", + [(ARMtcall GPR:$func)]>, + Requires<[IsThumb, HasV5T, IsNotDarwin]>; + + // ARMv4T + def tBX : TIx2<(outs), (ins tGPR:$func, variable_ops), IIC_Br, + "mov\tlr, pc\n\tbx\t$func", + [(ARMcall_nolink tGPR:$func)]>, + Requires<[IsThumb1Only, IsNotDarwin]>; +} + +// On Darwin R9 is call-clobbered. +let isCall = 1, + Defs = [R0, R1, R2, R3, R9, R12, LR, + D0, D1, D2, D3, D4, D5, D6, D7, + D16, D17, D18, D19, D20, D21, D22, D23, + D24, D25, D26, D27, D28, D29, D30, D31, CPSR, FPSCR] in { + // Also used for Thumb2 + def tBLr9 : TIx2<(outs), (ins i32imm:$func, variable_ops), IIC_Br, + "bl\t${func:call}", + [(ARMtcall tglobaladdr:$func)]>, + Requires<[IsThumb, IsDarwin]>; + + // ARMv5T and above, also used for Thumb2 + def tBLXi_r9 : TIx2<(outs), (ins i32imm:$func, variable_ops), IIC_Br, + "blx\t${func:call}", + [(ARMcall tglobaladdr:$func)]>, + Requires<[IsThumb, HasV5T, IsDarwin]>; + + // Also used for Thumb2 + def tBLXr_r9 : TI<(outs), (ins GPR:$func, variable_ops), IIC_Br, + "blx\t$func", + [(ARMtcall GPR:$func)]>, + Requires<[IsThumb, HasV5T, IsDarwin]>; + + // ARMv4T + def tBXr9 : TIx2<(outs), (ins tGPR:$func, variable_ops), IIC_Br, + "mov\tlr, pc\n\tbx\t$func", + [(ARMcall_nolink tGPR:$func)]>, + Requires<[IsThumb1Only, IsDarwin]>; +} + +let isBranch = 1, isTerminator = 1 in { + let isBarrier = 1 in { + let isPredicable = 1 in + def tB : T1I<(outs), (ins brtarget:$target), IIC_Br, + "b\t$target", [(br bb:$target)]>; + + // Far jump + let Defs = [LR] in + def tBfar : TIx2<(outs), (ins brtarget:$target), IIC_Br, + "bl\t$target\t@ far jump",[]>; + + def tBR_JTr : T1JTI<(outs), + (ins tGPR:$target, jtblock_operand:$jt, i32imm:$id), + IIC_Br, "mov\tpc, $target\n\t.align\t2\n$jt", + [(ARMbrjt tGPR:$target, tjumptable:$jt, imm:$id)]>; + } +} + +// FIXME: should be able to write a pattern for ARMBrcond, but can't use +// a two-value operand where a dag node expects two operands. :( +let isBranch = 1, isTerminator = 1 in + def tBcc : T1I<(outs), (ins brtarget:$target, pred:$cc), IIC_Br, + "b$cc\t$target", + [/*(ARMbrcond bb:$target, imm:$cc)*/]>; + +// Compare and branch on zero / non-zero +let isBranch = 1, isTerminator = 1 in { + def tCBZ : T1I<(outs), (ins tGPR:$cmp, brtarget:$target), IIC_Br, + "cbz\t$cmp, $target", []>; + + def tCBNZ : T1I<(outs), (ins tGPR:$cmp, brtarget:$target), IIC_Br, + "cbnz\t$cmp, $target", []>; +} + +//===----------------------------------------------------------------------===// +// Load Store Instructions. +// + +let canFoldAsLoad = 1, isReMaterializable = 1, mayHaveSideEffects = 1 in +def tLDR : T1pI4<(outs tGPR:$dst), (ins t_addrmode_s4:$addr), IIC_iLoadr, + "ldr", "\t$dst, $addr", + [(set tGPR:$dst, (load t_addrmode_s4:$addr))]>; + +def tLDRB : T1pI1<(outs tGPR:$dst), (ins t_addrmode_s1:$addr), IIC_iLoadr, + "ldrb", "\t$dst, $addr", + [(set tGPR:$dst, (zextloadi8 t_addrmode_s1:$addr))]>; + +def tLDRH : T1pI2<(outs tGPR:$dst), (ins t_addrmode_s2:$addr), IIC_iLoadr, + "ldrh", "\t$dst, $addr", + [(set tGPR:$dst, (zextloadi16 t_addrmode_s2:$addr))]>; + +let AddedComplexity = 10 in +def tLDRSB : T1pI1<(outs tGPR:$dst), (ins t_addrmode_rr:$addr), IIC_iLoadr, + "ldrsb", "\t$dst, $addr", + [(set tGPR:$dst, (sextloadi8 t_addrmode_rr:$addr))]>; + +let AddedComplexity = 10 in +def tLDRSH : T1pI2<(outs tGPR:$dst), (ins t_addrmode_rr:$addr), IIC_iLoadr, + "ldrsh", "\t$dst, $addr", + [(set tGPR:$dst, (sextloadi16 t_addrmode_rr:$addr))]>; + +let canFoldAsLoad = 1 in +def tLDRspi : T1pIs<(outs tGPR:$dst), (ins t_addrmode_sp:$addr), IIC_iLoadi, + "ldr", "\t$dst, $addr", + [(set tGPR:$dst, (load t_addrmode_sp:$addr))]>; + +// Special instruction for restore. It cannot clobber condition register +// when it's expanded by eliminateCallFramePseudoInstr(). +let canFoldAsLoad = 1, mayLoad = 1 in +def tRestore : T1pIs<(outs tGPR:$dst), (ins t_addrmode_sp:$addr), IIC_iLoadi, + "ldr", "\t$dst, $addr", []>; + +// Load tconstpool +// FIXME: Use ldr.n to work around a Darwin assembler bug. +let canFoldAsLoad = 1, isReMaterializable = 1, mayHaveSideEffects = 1 in +def tLDRpci : T1pIs<(outs tGPR:$dst), (ins i32imm:$addr), IIC_iLoadi, + "ldr", ".n\t$dst, $addr", + [(set tGPR:$dst, (load (ARMWrapper tconstpool:$addr)))]>; + +// Special LDR for loads from non-pc-relative constpools. +let canFoldAsLoad = 1, mayLoad = 1, isReMaterializable = 1, + mayHaveSideEffects = 1 in +def tLDRcp : T1pIs<(outs tGPR:$dst), (ins i32imm:$addr), IIC_iLoadi, + "ldr", "\t$dst, $addr", []>; + +def tSTR : T1pI4<(outs), (ins tGPR:$src, t_addrmode_s4:$addr), IIC_iStorer, + "str", "\t$src, $addr", + [(store tGPR:$src, t_addrmode_s4:$addr)]>; + +def tSTRB : T1pI1<(outs), (ins tGPR:$src, t_addrmode_s1:$addr), IIC_iStorer, + "strb", "\t$src, $addr", + [(truncstorei8 tGPR:$src, t_addrmode_s1:$addr)]>; + +def tSTRH : T1pI2<(outs), (ins tGPR:$src, t_addrmode_s2:$addr), IIC_iStorer, + "strh", "\t$src, $addr", + [(truncstorei16 tGPR:$src, t_addrmode_s2:$addr)]>; + +def tSTRspi : T1pIs<(outs), (ins tGPR:$src, t_addrmode_sp:$addr), IIC_iStorei, + "str", "\t$src, $addr", + [(store tGPR:$src, t_addrmode_sp:$addr)]>; + +let mayStore = 1 in { +// Special instruction for spill. It cannot clobber condition register +// when it's expanded by eliminateCallFramePseudoInstr(). +def tSpill : T1pIs<(outs), (ins tGPR:$src, t_addrmode_sp:$addr), IIC_iStorei, + "str", "\t$src, $addr", []>; +} + +//===----------------------------------------------------------------------===// +// Load / store multiple Instructions. +// + +// These requires base address to be written back or one of the loaded regs. +let mayLoad = 1, hasExtraDefRegAllocReq = 1 in +def tLDM : T1I<(outs), + (ins addrmode4:$addr, pred:$p, reglist:$wb, variable_ops), + IIC_iLoadm, + "ldm${addr:submode}${p}\t$addr, $wb", []>; + +let mayStore = 1, hasExtraSrcRegAllocReq = 1 in +def tSTM : T1I<(outs), + (ins addrmode4:$addr, pred:$p, reglist:$wb, variable_ops), + IIC_iStorem, + "stm${addr:submode}${p}\t$addr, $wb", []>; + +let mayLoad = 1, Uses = [SP], Defs = [SP], hasExtraDefRegAllocReq = 1 in +def tPOP : T1I<(outs), (ins pred:$p, reglist:$wb, variable_ops), IIC_Br, + "pop${p}\t$wb", []>; + +let mayStore = 1, Uses = [SP], Defs = [SP], hasExtraSrcRegAllocReq = 1 in +def tPUSH : T1I<(outs), (ins pred:$p, reglist:$wb, variable_ops), IIC_Br, + "push${p}\t$wb", []>; + +//===----------------------------------------------------------------------===// +// Arithmetic Instructions. +// + +// Add with carry register +let isCommutable = 1, Uses = [CPSR] in +def tADC : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iALUr, + "adc", "\t$dst, $rhs", + [(set tGPR:$dst, (adde tGPR:$lhs, tGPR:$rhs))]>; + +// Add immediate +def tADDi3 : T1sI<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs), IIC_iALUi, + "add", "\t$dst, $lhs, $rhs", + [(set tGPR:$dst, (add tGPR:$lhs, imm0_7:$rhs))]>; + +def tADDi8 : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs), IIC_iALUi, + "add", "\t$dst, $rhs", + [(set tGPR:$dst, (add tGPR:$lhs, imm8_255:$rhs))]>; + +// Add register +let isCommutable = 1 in +def tADDrr : T1sI<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iALUr, + "add", "\t$dst, $lhs, $rhs", + [(set tGPR:$dst, (add tGPR:$lhs, tGPR:$rhs))]>; + +let neverHasSideEffects = 1 in +def tADDhirr : T1pIt<(outs GPR:$dst), (ins GPR:$lhs, GPR:$rhs), IIC_iALUr, + "add", "\t$dst, $rhs", []>; + +// And register +let isCommutable = 1 in +def tAND : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iALUr, + "and", "\t$dst, $rhs", + [(set tGPR:$dst, (and tGPR:$lhs, tGPR:$rhs))]>; + +// ASR immediate +def tASRri : T1sI<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs), IIC_iMOVsi, + "asr", "\t$dst, $lhs, $rhs", + [(set tGPR:$dst, (sra tGPR:$lhs, (i32 imm:$rhs)))]>; + +// ASR register +def tASRrr : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iMOVsr, + "asr", "\t$dst, $rhs", + [(set tGPR:$dst, (sra tGPR:$lhs, tGPR:$rhs))]>; + +// BIC register +def tBIC : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iALUr, + "bic", "\t$dst, $rhs", + [(set tGPR:$dst, (and tGPR:$lhs, (not tGPR:$rhs)))]>; + +// CMN register +let Defs = [CPSR] in { +def tCMN : T1pI<(outs), (ins tGPR:$lhs, tGPR:$rhs), IIC_iCMPr, + "cmn", "\t$lhs, $rhs", + [(ARMcmp tGPR:$lhs, (ineg tGPR:$rhs))]>; +def tCMNZ : T1pI<(outs), (ins tGPR:$lhs, tGPR:$rhs), IIC_iCMPr, + "cmn", "\t$lhs, $rhs", + [(ARMcmpZ tGPR:$lhs, (ineg tGPR:$rhs))]>; +} + +// CMP immediate +let Defs = [CPSR] in { +def tCMPi8 : T1pI<(outs), (ins tGPR:$lhs, i32imm:$rhs), IIC_iCMPi, + "cmp", "\t$lhs, $rhs", + [(ARMcmp tGPR:$lhs, imm0_255:$rhs)]>; +def tCMPzi8 : T1pI<(outs), (ins tGPR:$lhs, i32imm:$rhs), IIC_iCMPi, + "cmp", "\t$lhs, $rhs", + [(ARMcmpZ tGPR:$lhs, imm0_255:$rhs)]>; + +} + +// CMP register +let Defs = [CPSR] in { +def tCMPr : T1pI<(outs), (ins tGPR:$lhs, tGPR:$rhs), IIC_iCMPr, + "cmp", "\t$lhs, $rhs", + [(ARMcmp tGPR:$lhs, tGPR:$rhs)]>; +def tCMPzr : T1pI<(outs), (ins tGPR:$lhs, tGPR:$rhs), IIC_iCMPr, + "cmp", "\t$lhs, $rhs", + [(ARMcmpZ tGPR:$lhs, tGPR:$rhs)]>; + +def tCMPhir : T1pI<(outs), (ins GPR:$lhs, GPR:$rhs), IIC_iCMPr, + "cmp", "\t$lhs, $rhs", []>; +def tCMPzhir : T1pI<(outs), (ins GPR:$lhs, GPR:$rhs), IIC_iCMPr, + "cmp", "\t$lhs, $rhs", []>; +} + + +// XOR register +let isCommutable = 1 in +def tEOR : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iALUr, + "eor", "\t$dst, $rhs", + [(set tGPR:$dst, (xor tGPR:$lhs, tGPR:$rhs))]>; + +// LSL immediate +def tLSLri : T1sI<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs), IIC_iMOVsi, + "lsl", "\t$dst, $lhs, $rhs", + [(set tGPR:$dst, (shl tGPR:$lhs, (i32 imm:$rhs)))]>; + +// LSL register +def tLSLrr : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iMOVsr, + "lsl", "\t$dst, $rhs", + [(set tGPR:$dst, (shl tGPR:$lhs, tGPR:$rhs))]>; + +// LSR immediate +def tLSRri : T1sI<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs), IIC_iMOVsi, + "lsr", "\t$dst, $lhs, $rhs", + [(set tGPR:$dst, (srl tGPR:$lhs, (i32 imm:$rhs)))]>; + +// LSR register +def tLSRrr : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iMOVsr, + "lsr", "\t$dst, $rhs", + [(set tGPR:$dst, (srl tGPR:$lhs, tGPR:$rhs))]>; + +// move register +def tMOVi8 : T1sI<(outs tGPR:$dst), (ins i32imm:$src), IIC_iMOVi, + "mov", "\t$dst, $src", + [(set tGPR:$dst, imm0_255:$src)]>; + +// TODO: A7-73: MOV(2) - mov setting flag. + + +let neverHasSideEffects = 1 in { +// FIXME: Make this predicable. +def tMOVr : T1I<(outs tGPR:$dst), (ins tGPR:$src), IIC_iMOVr, + "mov\t$dst, $src", []>; +let Defs = [CPSR] in +def tMOVSr : T1I<(outs tGPR:$dst), (ins tGPR:$src), IIC_iMOVr, + "movs\t$dst, $src", []>; + +// FIXME: Make these predicable. +def tMOVgpr2tgpr : T1I<(outs tGPR:$dst), (ins GPR:$src), IIC_iMOVr, + "mov\t$dst, $src", []>; +def tMOVtgpr2gpr : T1I<(outs GPR:$dst), (ins tGPR:$src), IIC_iMOVr, + "mov\t$dst, $src", []>; +def tMOVgpr2gpr : T1I<(outs GPR:$dst), (ins GPR:$src), IIC_iMOVr, + "mov\t$dst, $src", []>; +} // neverHasSideEffects + +// multiply register +let isCommutable = 1 in +def tMUL : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iMUL32, + "mul", "\t$dst, $rhs", + [(set tGPR:$dst, (mul tGPR:$lhs, tGPR:$rhs))]>; + +// move inverse register +def tMVN : T1sI<(outs tGPR:$dst), (ins tGPR:$src), IIC_iMOVr, + "mvn", "\t$dst, $src", + [(set tGPR:$dst, (not tGPR:$src))]>; + +// bitwise or register +let isCommutable = 1 in +def tORR : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iALUr, + "orr", "\t$dst, $rhs", + [(set tGPR:$dst, (or tGPR:$lhs, tGPR:$rhs))]>; + +// swaps +def tREV : T1pI<(outs tGPR:$dst), (ins tGPR:$src), IIC_iUNAr, + "rev", "\t$dst, $src", + [(set tGPR:$dst, (bswap tGPR:$src))]>, + Requires<[IsThumb1Only, HasV6]>; + +def tREV16 : T1pI<(outs tGPR:$dst), (ins tGPR:$src), IIC_iUNAr, + "rev16", "\t$dst, $src", + [(set tGPR:$dst, + (or (and (srl tGPR:$src, (i32 8)), 0xFF), + (or (and (shl tGPR:$src, (i32 8)), 0xFF00), + (or (and (srl tGPR:$src, (i32 8)), 0xFF0000), + (and (shl tGPR:$src, (i32 8)), 0xFF000000)))))]>, + Requires<[IsThumb1Only, HasV6]>; + +def tREVSH : T1pI<(outs tGPR:$dst), (ins tGPR:$src), IIC_iUNAr, + "revsh", "\t$dst, $src", + [(set tGPR:$dst, + (sext_inreg + (or (srl (and tGPR:$src, 0xFF00), (i32 8)), + (shl tGPR:$src, (i32 8))), i16))]>, + Requires<[IsThumb1Only, HasV6]>; + +// rotate right register +def tROR : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iMOVsr, + "ror", "\t$dst, $rhs", + [(set tGPR:$dst, (rotr tGPR:$lhs, tGPR:$rhs))]>; + +// negate register +def tRSB : T1sI<(outs tGPR:$dst), (ins tGPR:$src), IIC_iALUi, + "rsb", "\t$dst, $src, #0", + [(set tGPR:$dst, (ineg tGPR:$src))]>; + +// Subtract with carry register +let Uses = [CPSR] in +def tSBC : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iALUr, + "sbc", "\t$dst, $rhs", + [(set tGPR:$dst, (sube tGPR:$lhs, tGPR:$rhs))]>; + +// Subtract immediate +def tSUBi3 : T1sI<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs), IIC_iALUi, + "sub", "\t$dst, $lhs, $rhs", + [(set tGPR:$dst, (add tGPR:$lhs, imm0_7_neg:$rhs))]>; + +def tSUBi8 : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs), IIC_iALUi, + "sub", "\t$dst, $rhs", + [(set tGPR:$dst, (add tGPR:$lhs, imm8_255_neg:$rhs))]>; + +// subtract register +def tSUBrr : T1sI<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iALUr, + "sub", "\t$dst, $lhs, $rhs", + [(set tGPR:$dst, (sub tGPR:$lhs, tGPR:$rhs))]>; + +// TODO: A7-96: STMIA - store multiple. + +// sign-extend byte +def tSXTB : T1pI<(outs tGPR:$dst), (ins tGPR:$src), IIC_iUNAr, + "sxtb", "\t$dst, $src", + [(set tGPR:$dst, (sext_inreg tGPR:$src, i8))]>, + Requires<[IsThumb1Only, HasV6]>; + +// sign-extend short +def tSXTH : T1pI<(outs tGPR:$dst), (ins tGPR:$src), IIC_iUNAr, + "sxth", "\t$dst, $src", + [(set tGPR:$dst, (sext_inreg tGPR:$src, i16))]>, + Requires<[IsThumb1Only, HasV6]>; + +// test +let isCommutable = 1, Defs = [CPSR] in +def tTST : T1pI<(outs), (ins tGPR:$lhs, tGPR:$rhs), IIC_iCMPr, + "tst", "\t$lhs, $rhs", + [(ARMcmpZ (and tGPR:$lhs, tGPR:$rhs), 0)]>; + +// zero-extend byte +def tUXTB : T1pI<(outs tGPR:$dst), (ins tGPR:$src), IIC_iUNAr, + "uxtb", "\t$dst, $src", + [(set tGPR:$dst, (and tGPR:$src, 0xFF))]>, + Requires<[IsThumb1Only, HasV6]>; + +// zero-extend short +def tUXTH : T1pI<(outs tGPR:$dst), (ins tGPR:$src), IIC_iUNAr, + "uxth", "\t$dst, $src", + [(set tGPR:$dst, (and tGPR:$src, 0xFFFF))]>, + Requires<[IsThumb1Only, HasV6]>; + + +// Conditional move tMOVCCr - Used to implement the Thumb SELECT_CC DAG operation. +// Expanded after instruction selection into a branch sequence. +let usesCustomInserter = 1 in // Expanded after instruction selection. + def tMOVCCr_pseudo : + PseudoInst<(outs tGPR:$dst), (ins tGPR:$false, tGPR:$true, pred:$cc), + NoItinerary, "@ tMOVCCr $cc", + [/*(set tGPR:$dst, (ARMcmov tGPR:$false, tGPR:$true, imm:$cc))*/]>; + + +// 16-bit movcc in IT blocks for Thumb2. +def tMOVCCr : T1pIt<(outs GPR:$dst), (ins GPR:$lhs, GPR:$rhs), IIC_iCMOVr, + "mov", "\t$dst, $rhs", []>; + +def tMOVCCi : T1pIt<(outs GPR:$dst), (ins GPR:$lhs, i32imm:$rhs), IIC_iCMOVi, + "mov", "\t$dst, $rhs", []>; + +// tLEApcrel - Load a pc-relative address into a register without offending the +// assembler. +def tLEApcrel : T1I<(outs tGPR:$dst), (ins i32imm:$label, pred:$p), IIC_iALUi, + "adr$p\t$dst, #$label", []>; + +def tLEApcrelJT : T1I<(outs tGPR:$dst), + (ins i32imm:$label, nohash_imm:$id, pred:$p), + IIC_iALUi, "adr$p\t$dst, #${label}_${id}", []>; + +//===----------------------------------------------------------------------===// +// TLS Instructions +// + +// __aeabi_read_tp preserves the registers r1-r3. +let isCall = 1, + Defs = [R0, LR] in { + def tTPsoft : TIx2<(outs), (ins), IIC_Br, + "bl\t__aeabi_read_tp", + [(set R0, ARMthread_pointer)]>; +} + +//===----------------------------------------------------------------------===// +// Non-Instruction Patterns +// + +// Add with carry +def : T1Pat<(addc tGPR:$lhs, imm0_7:$rhs), + (tADDi3 tGPR:$lhs, imm0_7:$rhs)>; +def : T1Pat<(addc tGPR:$lhs, imm8_255:$rhs), + (tADDi8 tGPR:$lhs, imm8_255:$rhs)>; +def : T1Pat<(addc tGPR:$lhs, tGPR:$rhs), + (tADDrr tGPR:$lhs, tGPR:$rhs)>; + +// Subtract with carry +def : T1Pat<(addc tGPR:$lhs, imm0_7_neg:$rhs), + (tSUBi3 tGPR:$lhs, imm0_7_neg:$rhs)>; +def : T1Pat<(addc tGPR:$lhs, imm8_255_neg:$rhs), + (tSUBi8 tGPR:$lhs, imm8_255_neg:$rhs)>; +def : T1Pat<(subc tGPR:$lhs, tGPR:$rhs), + (tSUBrr tGPR:$lhs, tGPR:$rhs)>; + +// ConstantPool, GlobalAddress +def : T1Pat<(ARMWrapper tglobaladdr :$dst), (tLEApcrel tglobaladdr :$dst)>; +def : T1Pat<(ARMWrapper tconstpool :$dst), (tLEApcrel tconstpool :$dst)>; + +// JumpTable +def : T1Pat<(ARMWrapperJT tjumptable:$dst, imm:$id), + (tLEApcrelJT tjumptable:$dst, imm:$id)>; + +// Direct calls +def : T1Pat<(ARMtcall texternalsym:$func), (tBL texternalsym:$func)>, + Requires<[IsThumb, IsNotDarwin]>; +def : T1Pat<(ARMtcall texternalsym:$func), (tBLr9 texternalsym:$func)>, + Requires<[IsThumb, IsDarwin]>; + +def : Tv5Pat<(ARMcall texternalsym:$func), (tBLXi texternalsym:$func)>, + Requires<[IsThumb, HasV5T, IsNotDarwin]>; +def : Tv5Pat<(ARMcall texternalsym:$func), (tBLXi_r9 texternalsym:$func)>, + Requires<[IsThumb, HasV5T, IsDarwin]>; + +// Indirect calls to ARM routines +def : Tv5Pat<(ARMcall GPR:$dst), (tBLXr GPR:$dst)>, + Requires<[IsThumb, HasV5T, IsNotDarwin]>; +def : Tv5Pat<(ARMcall GPR:$dst), (tBLXr_r9 GPR:$dst)>, + Requires<[IsThumb, HasV5T, IsDarwin]>; + +// zextload i1 -> zextload i8 +def : T1Pat<(zextloadi1 t_addrmode_s1:$addr), + (tLDRB t_addrmode_s1:$addr)>; + +// extload -> zextload +def : T1Pat<(extloadi1 t_addrmode_s1:$addr), (tLDRB t_addrmode_s1:$addr)>; +def : T1Pat<(extloadi8 t_addrmode_s1:$addr), (tLDRB t_addrmode_s1:$addr)>; +def : T1Pat<(extloadi16 t_addrmode_s2:$addr), (tLDRH t_addrmode_s2:$addr)>; + +// If it's impossible to use [r,r] address mode for sextload, select to +// ldr{b|h} + sxt{b|h} instead. +def : T1Pat<(sextloadi8 t_addrmode_s1:$addr), + (tSXTB (tLDRB t_addrmode_s1:$addr))>, + Requires<[IsThumb1Only, HasV6]>; +def : T1Pat<(sextloadi16 t_addrmode_s2:$addr), + (tSXTH (tLDRH t_addrmode_s2:$addr))>, + Requires<[IsThumb1Only, HasV6]>; + +def : T1Pat<(sextloadi8 t_addrmode_s1:$addr), + (tASRri (tLSLri (tLDRB t_addrmode_s1:$addr), 24), 24)>; +def : T1Pat<(sextloadi16 t_addrmode_s1:$addr), + (tASRri (tLSLri (tLDRH t_addrmode_s1:$addr), 16), 16)>; + +// Large immediate handling. + +// Two piece imms. +def : T1Pat<(i32 thumb_immshifted:$src), + (tLSLri (tMOVi8 (thumb_immshifted_val imm:$src)), + (thumb_immshifted_shamt imm:$src))>; + +def : T1Pat<(i32 imm0_255_comp:$src), + (tMVN (tMOVi8 (imm_comp_XFORM imm:$src)))>; + +// Pseudo instruction that combines ldr from constpool and add pc. This should +// be expanded into two instructions late to allow if-conversion and +// scheduling. +let isReMaterializable = 1 in +def tLDRpci_pic : PseudoInst<(outs GPR:$dst), (ins i32imm:$addr, pclabel:$cp), + NoItinerary, "@ ldr.n\t$dst, $addr\n$cp:\n\tadd\t$dst, pc", + [(set GPR:$dst, (ARMpic_add (load (ARMWrapper tconstpool:$addr)), + imm:$cp))]>, + Requires<[IsThumb1Only]>; diff --git a/libclamav/c++/llvm/lib/Target/ARM/ARMInstrThumb2.td b/libclamav/c++/llvm/lib/Target/ARM/ARMInstrThumb2.td new file mode 100644 index 000000000..948981529 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/ARM/ARMInstrThumb2.td @@ -0,0 +1,1210 @@ +//===- ARMInstrThumb2.td - Thumb2 support for ARM -------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file describes the Thumb2 instruction set. +// +//===----------------------------------------------------------------------===// + +// IT block predicate field +def it_pred : Operand { + let PrintMethod = "printPredicateOperand"; +} + +// IT block condition mask +def it_mask : Operand { + let PrintMethod = "printThumbITMask"; +} + +// Table branch address +def tb_addrmode : Operand { + let PrintMethod = "printTBAddrMode"; +} + +// Shifted operands. No register controlled shifts for Thumb2. +// Note: We do not support rrx shifted operands yet. +def t2_so_reg : Operand, // reg imm + ComplexPattern { + let PrintMethod = "printT2SOOperand"; + let MIOperandInfo = (ops GPR, i32imm); +} + +// t2_so_imm_not_XFORM - Return the complement of a t2_so_imm value +def t2_so_imm_not_XFORM : SDNodeXFormgetTargetConstant(~((uint32_t)N->getZExtValue()), MVT::i32); +}]>; + +// t2_so_imm_neg_XFORM - Return the negation of a t2_so_imm value +def t2_so_imm_neg_XFORM : SDNodeXFormgetTargetConstant(-((int)N->getZExtValue()), MVT::i32); +}]>; + +// t2_so_imm - Match a 32-bit immediate operand, which is an +// 8-bit immediate rotated by an arbitrary number of bits, or an 8-bit +// immediate splatted into multiple bytes of the word. t2_so_imm values are +// represented in the imm field in the same 12-bit form that they are encoded +// into t2_so_imm instructions: the 8-bit immediate is the least significant +// bits [bits 0-7], the 4-bit shift/splat amount is the next 4 bits [bits 8-11]. +def t2_so_imm : Operand, + PatLeaf<(imm), [{ + return ARM_AM::getT2SOImmVal((uint32_t)N->getZExtValue()) != -1; +}]>; + +// t2_so_imm_not - Match an immediate that is a complement +// of a t2_so_imm. +def t2_so_imm_not : Operand, + PatLeaf<(imm), [{ + return ARM_AM::getT2SOImmVal(~((uint32_t)N->getZExtValue())) != -1; +}], t2_so_imm_not_XFORM>; + +// t2_so_imm_neg - Match an immediate that is a negation of a t2_so_imm. +def t2_so_imm_neg : Operand, + PatLeaf<(imm), [{ + return ARM_AM::getT2SOImmVal(-((int)N->getZExtValue())) != -1; +}], t2_so_imm_neg_XFORM>; + +// Break t2_so_imm's up into two pieces. This handles immediates with up to 16 +// bits set in them. This uses t2_so_imm2part to match and t2_so_imm2part_[12] +// to get the first/second pieces. +def t2_so_imm2part : Operand, + PatLeaf<(imm), [{ + return ARM_AM::isT2SOImmTwoPartVal((unsigned)N->getZExtValue()); + }]> { +} + +def t2_so_imm2part_1 : SDNodeXFormgetZExtValue()); + return CurDAG->getTargetConstant(V, MVT::i32); +}]>; + +def t2_so_imm2part_2 : SDNodeXFormgetZExtValue()); + return CurDAG->getTargetConstant(V, MVT::i32); +}]>; + +def t2_so_neg_imm2part : Operand, PatLeaf<(imm), [{ + return ARM_AM::isT2SOImmTwoPartVal(-(int)N->getZExtValue()); + }]> { +} + +def t2_so_neg_imm2part_1 : SDNodeXFormgetZExtValue()); + return CurDAG->getTargetConstant(V, MVT::i32); +}]>; + +def t2_so_neg_imm2part_2 : SDNodeXFormgetZExtValue()); + return CurDAG->getTargetConstant(V, MVT::i32); +}]>; + +/// imm1_31 predicate - True if the 32-bit immediate is in the range [1,31]. +def imm1_31 : PatLeaf<(i32 imm), [{ + return (int32_t)N->getZExtValue() >= 1 && (int32_t)N->getZExtValue() < 32; +}]>; + +/// imm0_4095 predicate - True if the 32-bit immediate is in the range [0.4095]. +def imm0_4095 : Operand, + PatLeaf<(i32 imm), [{ + return (uint32_t)N->getZExtValue() < 4096; +}]>; + +def imm0_4095_neg : PatLeaf<(i32 imm), [{ + return (uint32_t)(-N->getZExtValue()) < 4096; +}], imm_neg_XFORM>; + +def imm0_255_neg : PatLeaf<(i32 imm), [{ + return (uint32_t)(-N->getZExtValue()) < 255; +}], imm_neg_XFORM>; + +// Define Thumb2 specific addressing modes. + +// t2addrmode_imm12 := reg + imm12 +def t2addrmode_imm12 : Operand, + ComplexPattern { + let PrintMethod = "printT2AddrModeImm12Operand"; + let MIOperandInfo = (ops GPR:$base, i32imm:$offsimm); +} + +// t2addrmode_imm8 := reg - imm8 +def t2addrmode_imm8 : Operand, + ComplexPattern { + let PrintMethod = "printT2AddrModeImm8Operand"; + let MIOperandInfo = (ops GPR:$base, i32imm:$offsimm); +} + +def t2am_imm8_offset : Operand, + ComplexPattern{ + let PrintMethod = "printT2AddrModeImm8OffsetOperand"; +} + +// t2addrmode_imm8s4 := reg +/- (imm8 << 2) +def t2addrmode_imm8s4 : Operand, + ComplexPattern { + let PrintMethod = "printT2AddrModeImm8s4Operand"; + let MIOperandInfo = (ops GPR:$base, i32imm:$offsimm); +} + +// t2addrmode_so_reg := reg + (reg << imm2) +def t2addrmode_so_reg : Operand, + ComplexPattern { + let PrintMethod = "printT2AddrModeSoRegOperand"; + let MIOperandInfo = (ops GPR:$base, GPR:$offsreg, i32imm:$offsimm); +} + + +//===----------------------------------------------------------------------===// +// Multiclass helpers... +// + +/// T2I_un_irs - Defines a set of (op reg, {so_imm|r|so_reg}) patterns for a +/// unary operation that produces a value. These are predicable and can be +/// changed to modify CPSR. +multiclass T2I_un_irs{ + // shifted imm + def i : T2sI<(outs GPR:$dst), (ins t2_so_imm:$src), IIC_iMOVi, + opc, "\t$dst, $src", + [(set GPR:$dst, (opnode t2_so_imm:$src))]> { + let isAsCheapAsAMove = Cheap; + let isReMaterializable = ReMat; + } + // register + def r : T2I<(outs GPR:$dst), (ins GPR:$src), IIC_iMOVr, + opc, ".w\t$dst, $src", + [(set GPR:$dst, (opnode GPR:$src))]>; + // shifted register + def s : T2I<(outs GPR:$dst), (ins t2_so_reg:$src), IIC_iMOVsi, + opc, ".w\t$dst, $src", + [(set GPR:$dst, (opnode t2_so_reg:$src))]>; +} + +/// T2I_bin_irs - Defines a set of (op reg, {so_imm|r|so_reg}) patterns for a +// binary operation that produces a value. These are predicable and can be +/// changed to modify CPSR. +multiclass T2I_bin_irs { + // shifted imm + def ri : T2sI<(outs GPR:$dst), (ins GPR:$lhs, t2_so_imm:$rhs), IIC_iALUi, + opc, "\t$dst, $lhs, $rhs", + [(set GPR:$dst, (opnode GPR:$lhs, t2_so_imm:$rhs))]>; + // register + def rr : T2sI<(outs GPR:$dst), (ins GPR:$lhs, GPR:$rhs), IIC_iALUr, + opc, !strconcat(wide, "\t$dst, $lhs, $rhs"), + [(set GPR:$dst, (opnode GPR:$lhs, GPR:$rhs))]> { + let isCommutable = Commutable; + } + // shifted register + def rs : T2sI<(outs GPR:$dst), (ins GPR:$lhs, t2_so_reg:$rhs), IIC_iALUsi, + opc, !strconcat(wide, "\t$dst, $lhs, $rhs"), + [(set GPR:$dst, (opnode GPR:$lhs, t2_so_reg:$rhs))]>; +} + +/// T2I_bin_w_irs - Same as T2I_bin_irs except these operations need +// the ".w" prefix to indicate that they are wide. +multiclass T2I_bin_w_irs : + T2I_bin_irs; + +/// T2I_rbin_is - Same as T2I_bin_irs except the order of operands are +/// reversed. It doesn't define the 'rr' form since it's handled by its +/// T2I_bin_irs counterpart. +multiclass T2I_rbin_is { + // shifted imm + def ri : T2I<(outs GPR:$dst), (ins GPR:$rhs, t2_so_imm:$lhs), IIC_iALUi, + opc, ".w\t$dst, $rhs, $lhs", + [(set GPR:$dst, (opnode t2_so_imm:$lhs, GPR:$rhs))]>; + // shifted register + def rs : T2I<(outs GPR:$dst), (ins GPR:$rhs, t2_so_reg:$lhs), IIC_iALUsi, + opc, "\t$dst, $rhs, $lhs", + [(set GPR:$dst, (opnode t2_so_reg:$lhs, GPR:$rhs))]>; +} + +/// T2I_bin_s_irs - Similar to T2I_bin_irs except it sets the 's' bit so the +/// instruction modifies the CPSR register. +let Defs = [CPSR] in { +multiclass T2I_bin_s_irs { + // shifted imm + def ri : T2I<(outs GPR:$dst), (ins GPR:$lhs, t2_so_imm:$rhs), IIC_iALUi, + !strconcat(opc, "s"), ".w\t$dst, $lhs, $rhs", + [(set GPR:$dst, (opnode GPR:$lhs, t2_so_imm:$rhs))]>; + // register + def rr : T2I<(outs GPR:$dst), (ins GPR:$lhs, GPR:$rhs), IIC_iALUr, + !strconcat(opc, "s"), ".w\t$dst, $lhs, $rhs", + [(set GPR:$dst, (opnode GPR:$lhs, GPR:$rhs))]> { + let isCommutable = Commutable; + } + // shifted register + def rs : T2I<(outs GPR:$dst), (ins GPR:$lhs, t2_so_reg:$rhs), IIC_iALUsi, + !strconcat(opc, "s"), ".w\t$dst, $lhs, $rhs", + [(set GPR:$dst, (opnode GPR:$lhs, t2_so_reg:$rhs))]>; +} +} + +/// T2I_bin_ii12rs - Defines a set of (op reg, {so_imm|imm0_4095|r|so_reg}) +/// patterns for a binary operation that produces a value. +multiclass T2I_bin_ii12rs { + // shifted imm + def ri : T2sI<(outs GPR:$dst), (ins GPR:$lhs, t2_so_imm:$rhs), IIC_iALUi, + opc, ".w\t$dst, $lhs, $rhs", + [(set GPR:$dst, (opnode GPR:$lhs, t2_so_imm:$rhs))]>; + // 12-bit imm + def ri12 : T2sI<(outs GPR:$dst), (ins GPR:$lhs, imm0_4095:$rhs), IIC_iALUi, + !strconcat(opc, "w"), "\t$dst, $lhs, $rhs", + [(set GPR:$dst, (opnode GPR:$lhs, imm0_4095:$rhs))]>; + // register + def rr : T2sI<(outs GPR:$dst), (ins GPR:$lhs, GPR:$rhs), IIC_iALUr, + opc, ".w\t$dst, $lhs, $rhs", + [(set GPR:$dst, (opnode GPR:$lhs, GPR:$rhs))]> { + let isCommutable = Commutable; + } + // shifted register + def rs : T2sI<(outs GPR:$dst), (ins GPR:$lhs, t2_so_reg:$rhs), IIC_iALUsi, + opc, ".w\t$dst, $lhs, $rhs", + [(set GPR:$dst, (opnode GPR:$lhs, t2_so_reg:$rhs))]>; +} + +/// T2I_adde_sube_irs - Defines a set of (op reg, {so_imm|r|so_reg}) patterns +/// for a binary operation that produces a value and use and define the carry +/// bit. It's not predicable. +let Uses = [CPSR] in { +multiclass T2I_adde_sube_irs { + // shifted imm + def ri : T2sI<(outs GPR:$dst), (ins GPR:$lhs, t2_so_imm:$rhs), IIC_iALUi, + opc, "\t$dst, $lhs, $rhs", + [(set GPR:$dst, (opnode GPR:$lhs, t2_so_imm:$rhs))]>, + Requires<[IsThumb2, CarryDefIsUnused]>; + // register + def rr : T2sI<(outs GPR:$dst), (ins GPR:$lhs, GPR:$rhs), IIC_iALUr, + opc, ".w\t$dst, $lhs, $rhs", + [(set GPR:$dst, (opnode GPR:$lhs, GPR:$rhs))]>, + Requires<[IsThumb2, CarryDefIsUnused]> { + let isCommutable = Commutable; + } + // shifted register + def rs : T2sI<(outs GPR:$dst), (ins GPR:$lhs, t2_so_reg:$rhs), IIC_iALUsi, + opc, ".w\t$dst, $lhs, $rhs", + [(set GPR:$dst, (opnode GPR:$lhs, t2_so_reg:$rhs))]>, + Requires<[IsThumb2, CarryDefIsUnused]>; + // Carry setting variants + // shifted imm + def Sri : T2XI<(outs GPR:$dst), (ins GPR:$lhs, t2_so_imm:$rhs), IIC_iALUi, + !strconcat(opc, "s\t$dst, $lhs, $rhs"), + [(set GPR:$dst, (opnode GPR:$lhs, t2_so_imm:$rhs))]>, + Requires<[IsThumb2, CarryDefIsUsed]> { + let Defs = [CPSR]; + } + // register + def Srr : T2XI<(outs GPR:$dst), (ins GPR:$lhs, GPR:$rhs), IIC_iALUr, + !strconcat(opc, "s.w\t$dst, $lhs, $rhs"), + [(set GPR:$dst, (opnode GPR:$lhs, GPR:$rhs))]>, + Requires<[IsThumb2, CarryDefIsUsed]> { + let Defs = [CPSR]; + let isCommutable = Commutable; + } + // shifted register + def Srs : T2XI<(outs GPR:$dst), (ins GPR:$lhs, t2_so_reg:$rhs), IIC_iALUsi, + !strconcat(opc, "s.w\t$dst, $lhs, $rhs"), + [(set GPR:$dst, (opnode GPR:$lhs, t2_so_reg:$rhs))]>, + Requires<[IsThumb2, CarryDefIsUsed]> { + let Defs = [CPSR]; + } +} +} + +/// T2I_rbin_s_is - Same as T2I_rbin_is except sets 's' bit. +let Defs = [CPSR] in { +multiclass T2I_rbin_s_is { + // shifted imm + def ri : T2XI<(outs GPR:$dst), (ins GPR:$rhs, t2_so_imm:$lhs, cc_out:$s), + IIC_iALUi, + !strconcat(opc, "${s}.w\t$dst, $rhs, $lhs"), + [(set GPR:$dst, (opnode t2_so_imm:$lhs, GPR:$rhs))]>; + // shifted register + def rs : T2XI<(outs GPR:$dst), (ins GPR:$rhs, t2_so_reg:$lhs, cc_out:$s), + IIC_iALUsi, + !strconcat(opc, "${s}\t$dst, $rhs, $lhs"), + [(set GPR:$dst, (opnode t2_so_reg:$lhs, GPR:$rhs))]>; +} +} + +/// T2I_sh_ir - Defines a set of (op reg, {so_imm|r}) patterns for a shift / +// rotate operation that produces a value. +multiclass T2I_sh_ir { + // 5-bit imm + def ri : T2sI<(outs GPR:$dst), (ins GPR:$lhs, i32imm:$rhs), IIC_iMOVsi, + opc, ".w\t$dst, $lhs, $rhs", + [(set GPR:$dst, (opnode GPR:$lhs, imm1_31:$rhs))]>; + // register + def rr : T2sI<(outs GPR:$dst), (ins GPR:$lhs, GPR:$rhs), IIC_iMOVsr, + opc, ".w\t$dst, $lhs, $rhs", + [(set GPR:$dst, (opnode GPR:$lhs, GPR:$rhs))]>; +} + +/// T2I_cmp_is - Defines a set of (op r, {so_imm|r|so_reg}) cmp / test +/// patterns. Similar to T2I_bin_irs except the instruction does not produce +/// a explicit result, only implicitly set CPSR. +let Defs = [CPSR] in { +multiclass T2I_cmp_is { + // shifted imm + def ri : T2I<(outs), (ins GPR:$lhs, t2_so_imm:$rhs), IIC_iCMPi, + opc, ".w\t$lhs, $rhs", + [(opnode GPR:$lhs, t2_so_imm:$rhs)]>; + // register + def rr : T2I<(outs), (ins GPR:$lhs, GPR:$rhs), IIC_iCMPr, + opc, ".w\t$lhs, $rhs", + [(opnode GPR:$lhs, GPR:$rhs)]>; + // shifted register + def rs : T2I<(outs), (ins GPR:$lhs, t2_so_reg:$rhs), IIC_iCMPsi, + opc, ".w\t$lhs, $rhs", + [(opnode GPR:$lhs, t2_so_reg:$rhs)]>; +} +} + +/// T2I_ld - Defines a set of (op r, {imm12|imm8|so_reg}) load patterns. +multiclass T2I_ld { + def i12 : T2Ii12<(outs GPR:$dst), (ins t2addrmode_imm12:$addr), IIC_iLoadi, + opc, ".w\t$dst, $addr", + [(set GPR:$dst, (opnode t2addrmode_imm12:$addr))]>; + def i8 : T2Ii8 <(outs GPR:$dst), (ins t2addrmode_imm8:$addr), IIC_iLoadi, + opc, "\t$dst, $addr", + [(set GPR:$dst, (opnode t2addrmode_imm8:$addr))]>; + def s : T2Iso <(outs GPR:$dst), (ins t2addrmode_so_reg:$addr), IIC_iLoadr, + opc, ".w\t$dst, $addr", + [(set GPR:$dst, (opnode t2addrmode_so_reg:$addr))]>; + def pci : T2Ipc <(outs GPR:$dst), (ins i32imm:$addr), IIC_iLoadi, + opc, ".w\t$dst, $addr", + [(set GPR:$dst, (opnode (ARMWrapper tconstpool:$addr)))]> { + let isReMaterializable = 1; + } +} + +/// T2I_st - Defines a set of (op r, {imm12|imm8|so_reg}) store patterns. +multiclass T2I_st { + def i12 : T2Ii12<(outs), (ins GPR:$src, t2addrmode_imm12:$addr), IIC_iStorei, + opc, ".w\t$src, $addr", + [(opnode GPR:$src, t2addrmode_imm12:$addr)]>; + def i8 : T2Ii8 <(outs), (ins GPR:$src, t2addrmode_imm8:$addr), IIC_iStorei, + opc, "\t$src, $addr", + [(opnode GPR:$src, t2addrmode_imm8:$addr)]>; + def s : T2Iso <(outs), (ins GPR:$src, t2addrmode_so_reg:$addr), IIC_iStorer, + opc, ".w\t$src, $addr", + [(opnode GPR:$src, t2addrmode_so_reg:$addr)]>; +} + +/// T2I_picld - Defines the PIC load pattern. +class T2I_picld : + T2I<(outs GPR:$dst), (ins addrmodepc:$addr), IIC_iLoadi, + !strconcat("\n${addr:label}:\n\t", opc), "\t$dst, $addr", + [(set GPR:$dst, (opnode addrmodepc:$addr))]>; + +/// T2I_picst - Defines the PIC store pattern. +class T2I_picst : + T2I<(outs), (ins GPR:$src, addrmodepc:$addr), IIC_iStorer, + !strconcat("\n${addr:label}:\n\t", opc), "\t$src, $addr", + [(opnode GPR:$src, addrmodepc:$addr)]>; + + +/// T2I_unary_rrot - A unary operation with two forms: one whose operand is a +/// register and one whose operand is a register rotated by 8/16/24. +multiclass T2I_unary_rrot { + def r : T2I<(outs GPR:$dst), (ins GPR:$src), IIC_iUNAr, + opc, ".w\t$dst, $src", + [(set GPR:$dst, (opnode GPR:$src))]>; + def r_rot : T2I<(outs GPR:$dst), (ins GPR:$src, i32imm:$rot), IIC_iUNAsi, + opc, ".w\t$dst, $src, ror $rot", + [(set GPR:$dst, (opnode (rotr GPR:$src, rot_imm:$rot)))]>; +} + +/// T2I_bin_rrot - A binary operation with two forms: one whose operand is a +/// register and one whose operand is a register rotated by 8/16/24. +multiclass T2I_bin_rrot { + def rr : T2I<(outs GPR:$dst), (ins GPR:$LHS, GPR:$RHS), IIC_iALUr, + opc, "\t$dst, $LHS, $RHS", + [(set GPR:$dst, (opnode GPR:$LHS, GPR:$RHS))]>; + def rr_rot : T2I<(outs GPR:$dst), (ins GPR:$LHS, GPR:$RHS, i32imm:$rot), + IIC_iALUsr, opc, "\t$dst, $LHS, $RHS, ror $rot", + [(set GPR:$dst, (opnode GPR:$LHS, + (rotr GPR:$RHS, rot_imm:$rot)))]>; +} + +//===----------------------------------------------------------------------===// +// Instructions +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// Miscellaneous Instructions. +// + +// LEApcrel - Load a pc-relative address into a register without offending the +// assembler. +def t2LEApcrel : T2XI<(outs GPR:$dst), (ins i32imm:$label, pred:$p), IIC_iALUi, + "adr$p.w\t$dst, #$label", []>; + +def t2LEApcrelJT : T2XI<(outs GPR:$dst), + (ins i32imm:$label, nohash_imm:$id, pred:$p), IIC_iALUi, + "adr$p.w\t$dst, #${label}_${id}", []>; + +// ADD r, sp, {so_imm|i12} +def t2ADDrSPi : T2sI<(outs GPR:$dst), (ins GPR:$sp, t2_so_imm:$imm), + IIC_iALUi, "add", ".w\t$dst, $sp, $imm", []>; +def t2ADDrSPi12 : T2I<(outs GPR:$dst), (ins GPR:$sp, imm0_4095:$imm), + IIC_iALUi, "addw", "\t$dst, $sp, $imm", []>; + +// ADD r, sp, so_reg +def t2ADDrSPs : T2sI<(outs GPR:$dst), (ins GPR:$sp, t2_so_reg:$rhs), + IIC_iALUsi, "add", ".w\t$dst, $sp, $rhs", []>; + +// SUB r, sp, {so_imm|i12} +def t2SUBrSPi : T2sI<(outs GPR:$dst), (ins GPR:$sp, t2_so_imm:$imm), + IIC_iALUi, "sub", ".w\t$dst, $sp, $imm", []>; +def t2SUBrSPi12 : T2I<(outs GPR:$dst), (ins GPR:$sp, imm0_4095:$imm), + IIC_iALUi, "subw", "\t$dst, $sp, $imm", []>; + +// SUB r, sp, so_reg +def t2SUBrSPs : T2sI<(outs GPR:$dst), (ins GPR:$sp, t2_so_reg:$rhs), + IIC_iALUsi, + "sub", "\t$dst, $sp, $rhs", []>; + + +// Pseudo instruction that will expand into a t2SUBrSPi + a copy. +let usesCustomInserter = 1 in { // Expanded after instruction selection. +def t2SUBrSPi_ : PseudoInst<(outs GPR:$dst), (ins GPR:$sp, t2_so_imm:$imm), + NoItinerary, "@ sub.w\t$dst, $sp, $imm", []>; +def t2SUBrSPi12_ : PseudoInst<(outs GPR:$dst), (ins GPR:$sp, imm0_4095:$imm), + NoItinerary, "@ subw\t$dst, $sp, $imm", []>; +def t2SUBrSPs_ : PseudoInst<(outs GPR:$dst), (ins GPR:$sp, t2_so_reg:$rhs), + NoItinerary, "@ sub\t$dst, $sp, $rhs", []>; +} // usesCustomInserter + + +//===----------------------------------------------------------------------===// +// Load / store Instructions. +// + +// Load +let canFoldAsLoad = 1, isReMaterializable = 1, mayHaveSideEffects = 1 in +defm t2LDR : T2I_ld<"ldr", UnOpFrag<(load node:$Src)>>; + +// Loads with zero extension +defm t2LDRH : T2I_ld<"ldrh", UnOpFrag<(zextloadi16 node:$Src)>>; +defm t2LDRB : T2I_ld<"ldrb", UnOpFrag<(zextloadi8 node:$Src)>>; + +// Loads with sign extension +defm t2LDRSH : T2I_ld<"ldrsh", UnOpFrag<(sextloadi16 node:$Src)>>; +defm t2LDRSB : T2I_ld<"ldrsb", UnOpFrag<(sextloadi8 node:$Src)>>; + +let mayLoad = 1, hasExtraDefRegAllocReq = 1 in { +// Load doubleword +def t2LDRDi8 : T2Ii8s4<(outs GPR:$dst1, GPR:$dst2), + (ins t2addrmode_imm8s4:$addr), + IIC_iLoadi, "ldrd", "\t$dst1, $addr", []>; +def t2LDRDpci : T2Ii8s4<(outs GPR:$dst1, GPR:$dst2), + (ins i32imm:$addr), IIC_iLoadi, + "ldrd", "\t$dst1, $addr", []>; +} + +// zextload i1 -> zextload i8 +def : T2Pat<(zextloadi1 t2addrmode_imm12:$addr), + (t2LDRBi12 t2addrmode_imm12:$addr)>; +def : T2Pat<(zextloadi1 t2addrmode_imm8:$addr), + (t2LDRBi8 t2addrmode_imm8:$addr)>; +def : T2Pat<(zextloadi1 t2addrmode_so_reg:$addr), + (t2LDRBs t2addrmode_so_reg:$addr)>; +def : T2Pat<(zextloadi1 (ARMWrapper tconstpool:$addr)), + (t2LDRBpci tconstpool:$addr)>; + +// extload -> zextload +// FIXME: Reduce the number of patterns by legalizing extload to zextload +// earlier? +def : T2Pat<(extloadi1 t2addrmode_imm12:$addr), + (t2LDRBi12 t2addrmode_imm12:$addr)>; +def : T2Pat<(extloadi1 t2addrmode_imm8:$addr), + (t2LDRBi8 t2addrmode_imm8:$addr)>; +def : T2Pat<(extloadi1 t2addrmode_so_reg:$addr), + (t2LDRBs t2addrmode_so_reg:$addr)>; +def : T2Pat<(extloadi1 (ARMWrapper tconstpool:$addr)), + (t2LDRBpci tconstpool:$addr)>; + +def : T2Pat<(extloadi8 t2addrmode_imm12:$addr), + (t2LDRBi12 t2addrmode_imm12:$addr)>; +def : T2Pat<(extloadi8 t2addrmode_imm8:$addr), + (t2LDRBi8 t2addrmode_imm8:$addr)>; +def : T2Pat<(extloadi8 t2addrmode_so_reg:$addr), + (t2LDRBs t2addrmode_so_reg:$addr)>; +def : T2Pat<(extloadi8 (ARMWrapper tconstpool:$addr)), + (t2LDRBpci tconstpool:$addr)>; + +def : T2Pat<(extloadi16 t2addrmode_imm12:$addr), + (t2LDRHi12 t2addrmode_imm12:$addr)>; +def : T2Pat<(extloadi16 t2addrmode_imm8:$addr), + (t2LDRHi8 t2addrmode_imm8:$addr)>; +def : T2Pat<(extloadi16 t2addrmode_so_reg:$addr), + (t2LDRHs t2addrmode_so_reg:$addr)>; +def : T2Pat<(extloadi16 (ARMWrapper tconstpool:$addr)), + (t2LDRHpci tconstpool:$addr)>; + +// Indexed loads +let mayLoad = 1 in { +def t2LDR_PRE : T2Iidxldst<(outs GPR:$dst, GPR:$base_wb), + (ins t2addrmode_imm8:$addr), + AddrModeT2_i8, IndexModePre, IIC_iLoadiu, + "ldr", "\t$dst, $addr!", "$addr.base = $base_wb", + []>; + +def t2LDR_POST : T2Iidxldst<(outs GPR:$dst, GPR:$base_wb), + (ins GPR:$base, t2am_imm8_offset:$offset), + AddrModeT2_i8, IndexModePost, IIC_iLoadiu, + "ldr", "\t$dst, [$base], $offset", "$base = $base_wb", + []>; + +def t2LDRB_PRE : T2Iidxldst<(outs GPR:$dst, GPR:$base_wb), + (ins t2addrmode_imm8:$addr), + AddrModeT2_i8, IndexModePre, IIC_iLoadiu, + "ldrb", "\t$dst, $addr!", "$addr.base = $base_wb", + []>; +def t2LDRB_POST : T2Iidxldst<(outs GPR:$dst, GPR:$base_wb), + (ins GPR:$base, t2am_imm8_offset:$offset), + AddrModeT2_i8, IndexModePost, IIC_iLoadiu, + "ldrb", "\t$dst, [$base], $offset", "$base = $base_wb", + []>; + +def t2LDRH_PRE : T2Iidxldst<(outs GPR:$dst, GPR:$base_wb), + (ins t2addrmode_imm8:$addr), + AddrModeT2_i8, IndexModePre, IIC_iLoadiu, + "ldrh", "\t$dst, $addr!", "$addr.base = $base_wb", + []>; +def t2LDRH_POST : T2Iidxldst<(outs GPR:$dst, GPR:$base_wb), + (ins GPR:$base, t2am_imm8_offset:$offset), + AddrModeT2_i8, IndexModePost, IIC_iLoadiu, + "ldrh", "\t$dst, [$base], $offset", "$base = $base_wb", + []>; + +def t2LDRSB_PRE : T2Iidxldst<(outs GPR:$dst, GPR:$base_wb), + (ins t2addrmode_imm8:$addr), + AddrModeT2_i8, IndexModePre, IIC_iLoadiu, + "ldrsb", "\t$dst, $addr!", "$addr.base = $base_wb", + []>; +def t2LDRSB_POST : T2Iidxldst<(outs GPR:$dst, GPR:$base_wb), + (ins GPR:$base, t2am_imm8_offset:$offset), + AddrModeT2_i8, IndexModePost, IIC_iLoadiu, + "ldrsb", "\t$dst, [$base], $offset", "$base = $base_wb", + []>; + +def t2LDRSH_PRE : T2Iidxldst<(outs GPR:$dst, GPR:$base_wb), + (ins t2addrmode_imm8:$addr), + AddrModeT2_i8, IndexModePre, IIC_iLoadiu, + "ldrsh", "\t$dst, $addr!", "$addr.base = $base_wb", + []>; +def t2LDRSH_POST : T2Iidxldst<(outs GPR:$dst, GPR:$base_wb), + (ins GPR:$base, t2am_imm8_offset:$offset), + AddrModeT2_i8, IndexModePost, IIC_iLoadiu, + "ldrsh", "\t$dst, [$base], $offset", "$base = $base_wb", + []>; +} + +// Store +defm t2STR : T2I_st<"str", BinOpFrag<(store node:$LHS, node:$RHS)>>; +defm t2STRB : T2I_st<"strb", BinOpFrag<(truncstorei8 node:$LHS, node:$RHS)>>; +defm t2STRH : T2I_st<"strh", BinOpFrag<(truncstorei16 node:$LHS, node:$RHS)>>; + +// Store doubleword +let mayLoad = 1, hasExtraSrcRegAllocReq = 1 in +def t2STRDi8 : T2Ii8s4<(outs), + (ins GPR:$src1, GPR:$src2, t2addrmode_imm8s4:$addr), + IIC_iStorer, "strd", "\t$src1, $addr", []>; + +// Indexed stores +def t2STR_PRE : T2Iidxldst<(outs GPR:$base_wb), + (ins GPR:$src, GPR:$base, t2am_imm8_offset:$offset), + AddrModeT2_i8, IndexModePre, IIC_iStoreiu, + "str", "\t$src, [$base, $offset]!", "$base = $base_wb", + [(set GPR:$base_wb, + (pre_store GPR:$src, GPR:$base, t2am_imm8_offset:$offset))]>; + +def t2STR_POST : T2Iidxldst<(outs GPR:$base_wb), + (ins GPR:$src, GPR:$base, t2am_imm8_offset:$offset), + AddrModeT2_i8, IndexModePost, IIC_iStoreiu, + "str", "\t$src, [$base], $offset", "$base = $base_wb", + [(set GPR:$base_wb, + (post_store GPR:$src, GPR:$base, t2am_imm8_offset:$offset))]>; + +def t2STRH_PRE : T2Iidxldst<(outs GPR:$base_wb), + (ins GPR:$src, GPR:$base, t2am_imm8_offset:$offset), + AddrModeT2_i8, IndexModePre, IIC_iStoreiu, + "strh", "\t$src, [$base, $offset]!", "$base = $base_wb", + [(set GPR:$base_wb, + (pre_truncsti16 GPR:$src, GPR:$base, t2am_imm8_offset:$offset))]>; + +def t2STRH_POST : T2Iidxldst<(outs GPR:$base_wb), + (ins GPR:$src, GPR:$base, t2am_imm8_offset:$offset), + AddrModeT2_i8, IndexModePost, IIC_iStoreiu, + "strh", "\t$src, [$base], $offset", "$base = $base_wb", + [(set GPR:$base_wb, + (post_truncsti16 GPR:$src, GPR:$base, t2am_imm8_offset:$offset))]>; + +def t2STRB_PRE : T2Iidxldst<(outs GPR:$base_wb), + (ins GPR:$src, GPR:$base, t2am_imm8_offset:$offset), + AddrModeT2_i8, IndexModePre, IIC_iStoreiu, + "strb", "\t$src, [$base, $offset]!", "$base = $base_wb", + [(set GPR:$base_wb, + (pre_truncsti8 GPR:$src, GPR:$base, t2am_imm8_offset:$offset))]>; + +def t2STRB_POST : T2Iidxldst<(outs GPR:$base_wb), + (ins GPR:$src, GPR:$base, t2am_imm8_offset:$offset), + AddrModeT2_i8, IndexModePost, IIC_iStoreiu, + "strb", "\t$src, [$base], $offset", "$base = $base_wb", + [(set GPR:$base_wb, + (post_truncsti8 GPR:$src, GPR:$base, t2am_imm8_offset:$offset))]>; + + +// FIXME: ldrd / strd pre / post variants + +//===----------------------------------------------------------------------===// +// Load / store multiple Instructions. +// + +let mayLoad = 1, hasExtraDefRegAllocReq = 1 in +def t2LDM : T2XI<(outs), + (ins addrmode4:$addr, pred:$p, reglist:$wb, variable_ops), + IIC_iLoadm, "ldm${addr:submode}${p}${addr:wide}\t$addr, $wb", []>; + +let mayStore = 1, hasExtraSrcRegAllocReq = 1 in +def t2STM : T2XI<(outs), + (ins addrmode4:$addr, pred:$p, reglist:$wb, variable_ops), + IIC_iStorem, "stm${addr:submode}${p}${addr:wide}\t$addr, $wb", []>; + +//===----------------------------------------------------------------------===// +// Move Instructions. +// + +let neverHasSideEffects = 1 in +def t2MOVr : T2sI<(outs GPR:$dst), (ins GPR:$src), IIC_iMOVr, + "mov", ".w\t$dst, $src", []>; + +// AddedComplexity to ensure isel tries t2MOVi before t2MOVi16. +let isReMaterializable = 1, isAsCheapAsAMove = 1, AddedComplexity = 1 in +def t2MOVi : T2sI<(outs GPR:$dst), (ins t2_so_imm:$src), IIC_iMOVi, + "mov", ".w\t$dst, $src", + [(set GPR:$dst, t2_so_imm:$src)]>; + +let isReMaterializable = 1, isAsCheapAsAMove = 1 in +def t2MOVi16 : T2I<(outs GPR:$dst), (ins i32imm:$src), IIC_iMOVi, + "movw", "\t$dst, $src", + [(set GPR:$dst, imm0_65535:$src)]>; + +let Constraints = "$src = $dst" in +def t2MOVTi16 : T2I<(outs GPR:$dst), (ins GPR:$src, i32imm:$imm), IIC_iMOVi, + "movt", "\t$dst, $imm", + [(set GPR:$dst, + (or (and GPR:$src, 0xffff), lo16AllZero:$imm))]>; + +def : T2Pat<(or GPR:$src, 0xffff0000), (t2MOVTi16 GPR:$src, 0xffff)>; + +//===----------------------------------------------------------------------===// +// Extend Instructions. +// + +// Sign extenders + +defm t2SXTB : T2I_unary_rrot<"sxtb", UnOpFrag<(sext_inreg node:$Src, i8)>>; +defm t2SXTH : T2I_unary_rrot<"sxth", UnOpFrag<(sext_inreg node:$Src, i16)>>; + +defm t2SXTAB : T2I_bin_rrot<"sxtab", + BinOpFrag<(add node:$LHS, (sext_inreg node:$RHS, i8))>>; +defm t2SXTAH : T2I_bin_rrot<"sxtah", + BinOpFrag<(add node:$LHS, (sext_inreg node:$RHS,i16))>>; + +// TODO: SXT(A){B|H}16 + +// Zero extenders + +let AddedComplexity = 16 in { +defm t2UXTB : T2I_unary_rrot<"uxtb" , UnOpFrag<(and node:$Src, 0x000000FF)>>; +defm t2UXTH : T2I_unary_rrot<"uxth" , UnOpFrag<(and node:$Src, 0x0000FFFF)>>; +defm t2UXTB16 : T2I_unary_rrot<"uxtb16", UnOpFrag<(and node:$Src, 0x00FF00FF)>>; + +def : T2Pat<(and (shl GPR:$Src, (i32 8)), 0xFF00FF), + (t2UXTB16r_rot GPR:$Src, 24)>; +def : T2Pat<(and (srl GPR:$Src, (i32 8)), 0xFF00FF), + (t2UXTB16r_rot GPR:$Src, 8)>; + +defm t2UXTAB : T2I_bin_rrot<"uxtab", + BinOpFrag<(add node:$LHS, (and node:$RHS, 0x00FF))>>; +defm t2UXTAH : T2I_bin_rrot<"uxtah", + BinOpFrag<(add node:$LHS, (and node:$RHS, 0xFFFF))>>; +} + +//===----------------------------------------------------------------------===// +// Arithmetic Instructions. +// + +defm t2ADD : T2I_bin_ii12rs<"add", BinOpFrag<(add node:$LHS, node:$RHS)>, 1>; +defm t2SUB : T2I_bin_ii12rs<"sub", BinOpFrag<(sub node:$LHS, node:$RHS)>>; + +// ADD and SUB with 's' bit set. No 12-bit immediate (T4) variants. +defm t2ADDS : T2I_bin_s_irs <"add", BinOpFrag<(addc node:$LHS, node:$RHS)>, 1>; +defm t2SUBS : T2I_bin_s_irs <"sub", BinOpFrag<(subc node:$LHS, node:$RHS)>>; + +defm t2ADC : T2I_adde_sube_irs<"adc",BinOpFrag<(adde node:$LHS, node:$RHS)>,1>; +defm t2SBC : T2I_adde_sube_irs<"sbc",BinOpFrag<(sube node:$LHS, node:$RHS)>>; + +// RSB +defm t2RSB : T2I_rbin_is <"rsb", BinOpFrag<(sub node:$LHS, node:$RHS)>>; +defm t2RSBS : T2I_rbin_s_is <"rsb", BinOpFrag<(subc node:$LHS, node:$RHS)>>; + +// (sub X, imm) gets canonicalized to (add X, -imm). Match this form. +let AddedComplexity = 1 in +def : T2Pat<(add GPR:$src, imm0_255_neg:$imm), + (t2SUBri GPR:$src, imm0_255_neg:$imm)>; +def : T2Pat<(add GPR:$src, t2_so_imm_neg:$imm), + (t2SUBri GPR:$src, t2_so_imm_neg:$imm)>; +def : T2Pat<(add GPR:$src, imm0_4095_neg:$imm), + (t2SUBri12 GPR:$src, imm0_4095_neg:$imm)>; + + +//===----------------------------------------------------------------------===// +// Shift and rotate Instructions. +// + +defm t2LSL : T2I_sh_ir<"lsl", BinOpFrag<(shl node:$LHS, node:$RHS)>>; +defm t2LSR : T2I_sh_ir<"lsr", BinOpFrag<(srl node:$LHS, node:$RHS)>>; +defm t2ASR : T2I_sh_ir<"asr", BinOpFrag<(sra node:$LHS, node:$RHS)>>; +defm t2ROR : T2I_sh_ir<"ror", BinOpFrag<(rotr node:$LHS, node:$RHS)>>; + +let Uses = [CPSR] in { +def t2MOVrx : T2sI<(outs GPR:$dst), (ins GPR:$src), IIC_iMOVsi, + "rrx", "\t$dst, $src", + [(set GPR:$dst, (ARMrrx GPR:$src))]>; +} + +let Defs = [CPSR] in { +def t2MOVsrl_flag : T2XI<(outs GPR:$dst), (ins GPR:$src), IIC_iMOVsi, + "lsrs.w\t$dst, $src, #1", + [(set GPR:$dst, (ARMsrl_flag GPR:$src))]>; +def t2MOVsra_flag : T2XI<(outs GPR:$dst), (ins GPR:$src), IIC_iMOVsi, + "asrs.w\t$dst, $src, #1", + [(set GPR:$dst, (ARMsra_flag GPR:$src))]>; +} + +//===----------------------------------------------------------------------===// +// Bitwise Instructions. +// + +defm t2AND : T2I_bin_w_irs<"and", BinOpFrag<(and node:$LHS, node:$RHS)>, 1>; +defm t2ORR : T2I_bin_w_irs<"orr", BinOpFrag<(or node:$LHS, node:$RHS)>, 1>; +defm t2EOR : T2I_bin_w_irs<"eor", BinOpFrag<(xor node:$LHS, node:$RHS)>, 1>; + +defm t2BIC : T2I_bin_w_irs<"bic", BinOpFrag<(and node:$LHS, (not node:$RHS))>>; + +let Constraints = "$src = $dst" in +def t2BFC : T2I<(outs GPR:$dst), (ins GPR:$src, bf_inv_mask_imm:$imm), + IIC_iUNAsi, "bfc", "\t$dst, $imm", + [(set GPR:$dst, (and GPR:$src, bf_inv_mask_imm:$imm))]>; + +def t2SBFX : T2I<(outs GPR:$dst), (ins GPR:$src, imm0_31:$lsb, imm0_31:$width), + IIC_iALUi, "sbfx", "\t$dst, $src, $lsb, $width", []>; + +def t2UBFX : T2I<(outs GPR:$dst), (ins GPR:$src, imm0_31:$lsb, imm0_31:$width), + IIC_iALUi, "ubfx", "\t$dst, $src, $lsb, $width", []>; + +// FIXME: A8.6.18 BFI - Bitfield insert (Encoding T1) + +defm t2ORN : T2I_bin_irs<"orn", BinOpFrag<(or node:$LHS, (not node:$RHS))>>; + +// Prefer over of t2EORri ra, rb, -1 because mvn has 16-bit version +let AddedComplexity = 1 in +defm t2MVN : T2I_un_irs <"mvn", UnOpFrag<(not node:$Src)>, 1, 1>; + + +def : T2Pat<(and GPR:$src, t2_so_imm_not:$imm), + (t2BICri GPR:$src, t2_so_imm_not:$imm)>; + +// FIXME: Disable this pattern on Darwin to workaround an assembler bug. +def : T2Pat<(or GPR:$src, t2_so_imm_not:$imm), + (t2ORNri GPR:$src, t2_so_imm_not:$imm)>, + Requires<[IsThumb2]>; + +def : T2Pat<(t2_so_imm_not:$src), + (t2MVNi t2_so_imm_not:$src)>; + +//===----------------------------------------------------------------------===// +// Multiply Instructions. +// +let isCommutable = 1 in +def t2MUL: T2I<(outs GPR:$dst), (ins GPR:$a, GPR:$b), IIC_iMUL32, + "mul", "\t$dst, $a, $b", + [(set GPR:$dst, (mul GPR:$a, GPR:$b))]>; + +def t2MLA: T2I<(outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$c), IIC_iMAC32, + "mla", "\t$dst, $a, $b, $c", + [(set GPR:$dst, (add (mul GPR:$a, GPR:$b), GPR:$c))]>; + +def t2MLS: T2I<(outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$c), IIC_iMAC32, + "mls", "\t$dst, $a, $b, $c", + [(set GPR:$dst, (sub GPR:$c, (mul GPR:$a, GPR:$b)))]>; + +// Extra precision multiplies with low / high results +let neverHasSideEffects = 1 in { +let isCommutable = 1 in { +def t2SMULL : T2I<(outs GPR:$ldst, GPR:$hdst), (ins GPR:$a, GPR:$b), IIC_iMUL64, + "smull", "\t$ldst, $hdst, $a, $b", []>; + +def t2UMULL : T2I<(outs GPR:$ldst, GPR:$hdst), (ins GPR:$a, GPR:$b), IIC_iMUL64, + "umull", "\t$ldst, $hdst, $a, $b", []>; +} + +// Multiply + accumulate +def t2SMLAL : T2I<(outs GPR:$ldst, GPR:$hdst), (ins GPR:$a, GPR:$b), IIC_iMAC64, + "smlal", "\t$ldst, $hdst, $a, $b", []>; + +def t2UMLAL : T2I<(outs GPR:$ldst, GPR:$hdst), (ins GPR:$a, GPR:$b), IIC_iMAC64, + "umlal", "\t$ldst, $hdst, $a, $b", []>; + +def t2UMAAL : T2I<(outs GPR:$ldst, GPR:$hdst), (ins GPR:$a, GPR:$b), IIC_iMAC64, + "umaal", "\t$ldst, $hdst, $a, $b", []>; +} // neverHasSideEffects + +// Most significant word multiply +def t2SMMUL : T2I<(outs GPR:$dst), (ins GPR:$a, GPR:$b), IIC_iMUL32, + "smmul", "\t$dst, $a, $b", + [(set GPR:$dst, (mulhs GPR:$a, GPR:$b))]>; + +def t2SMMLA : T2I<(outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$c), IIC_iMAC32, + "smmla", "\t$dst, $a, $b, $c", + [(set GPR:$dst, (add (mulhs GPR:$a, GPR:$b), GPR:$c))]>; + + +def t2SMMLS : T2I <(outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$c), IIC_iMAC32, + "smmls", "\t$dst, $a, $b, $c", + [(set GPR:$dst, (sub GPR:$c, (mulhs GPR:$a, GPR:$b)))]>; + +multiclass T2I_smul { + def BB : T2I<(outs GPR:$dst), (ins GPR:$a, GPR:$b), IIC_iMUL32, + !strconcat(opc, "bb"), "\t$dst, $a, $b", + [(set GPR:$dst, (opnode (sext_inreg GPR:$a, i16), + (sext_inreg GPR:$b, i16)))]>; + + def BT : T2I<(outs GPR:$dst), (ins GPR:$a, GPR:$b), IIC_iMUL32, + !strconcat(opc, "bt"), "\t$dst, $a, $b", + [(set GPR:$dst, (opnode (sext_inreg GPR:$a, i16), + (sra GPR:$b, (i32 16))))]>; + + def TB : T2I<(outs GPR:$dst), (ins GPR:$a, GPR:$b), IIC_iMUL32, + !strconcat(opc, "tb"), "\t$dst, $a, $b", + [(set GPR:$dst, (opnode (sra GPR:$a, (i32 16)), + (sext_inreg GPR:$b, i16)))]>; + + def TT : T2I<(outs GPR:$dst), (ins GPR:$a, GPR:$b), IIC_iMUL32, + !strconcat(opc, "tt"), "\t$dst, $a, $b", + [(set GPR:$dst, (opnode (sra GPR:$a, (i32 16)), + (sra GPR:$b, (i32 16))))]>; + + def WB : T2I<(outs GPR:$dst), (ins GPR:$a, GPR:$b), IIC_iMUL16, + !strconcat(opc, "wb"), "\t$dst, $a, $b", + [(set GPR:$dst, (sra (opnode GPR:$a, + (sext_inreg GPR:$b, i16)), (i32 16)))]>; + + def WT : T2I<(outs GPR:$dst), (ins GPR:$a, GPR:$b), IIC_iMUL16, + !strconcat(opc, "wt"), "\t$dst, $a, $b", + [(set GPR:$dst, (sra (opnode GPR:$a, + (sra GPR:$b, (i32 16))), (i32 16)))]>; +} + + +multiclass T2I_smla { + def BB : T2I<(outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$acc), IIC_iMAC16, + !strconcat(opc, "bb"), "\t$dst, $a, $b, $acc", + [(set GPR:$dst, (add GPR:$acc, + (opnode (sext_inreg GPR:$a, i16), + (sext_inreg GPR:$b, i16))))]>; + + def BT : T2I<(outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$acc), IIC_iMAC16, + !strconcat(opc, "bt"), "\t$dst, $a, $b, $acc", + [(set GPR:$dst, (add GPR:$acc, (opnode (sext_inreg GPR:$a, i16), + (sra GPR:$b, (i32 16)))))]>; + + def TB : T2I<(outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$acc), IIC_iMAC16, + !strconcat(opc, "tb"), "\t$dst, $a, $b, $acc", + [(set GPR:$dst, (add GPR:$acc, (opnode (sra GPR:$a, (i32 16)), + (sext_inreg GPR:$b, i16))))]>; + + def TT : T2I<(outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$acc), IIC_iMAC16, + !strconcat(opc, "tt"), "\t$dst, $a, $b, $acc", + [(set GPR:$dst, (add GPR:$acc, (opnode (sra GPR:$a, (i32 16)), + (sra GPR:$b, (i32 16)))))]>; + + def WB : T2I<(outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$acc), IIC_iMAC16, + !strconcat(opc, "wb"), "\t$dst, $a, $b, $acc", + [(set GPR:$dst, (add GPR:$acc, (sra (opnode GPR:$a, + (sext_inreg GPR:$b, i16)), (i32 16))))]>; + + def WT : T2I<(outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$acc), IIC_iMAC16, + !strconcat(opc, "wt"), "\t$dst, $a, $b, $acc", + [(set GPR:$dst, (add GPR:$acc, (sra (opnode GPR:$a, + (sra GPR:$b, (i32 16))), (i32 16))))]>; +} + +defm t2SMUL : T2I_smul<"smul", BinOpFrag<(mul node:$LHS, node:$RHS)>>; +defm t2SMLA : T2I_smla<"smla", BinOpFrag<(mul node:$LHS, node:$RHS)>>; + +// TODO: Halfword multiple accumulate long: SMLAL +// TODO: Dual halfword multiple: SMUAD, SMUSD, SMLAD, SMLSD, SMLALD, SMLSLD + + +//===----------------------------------------------------------------------===// +// Misc. Arithmetic Instructions. +// + +def t2CLZ : T2I<(outs GPR:$dst), (ins GPR:$src), IIC_iUNAr, + "clz", "\t$dst, $src", + [(set GPR:$dst, (ctlz GPR:$src))]>; + +def t2REV : T2I<(outs GPR:$dst), (ins GPR:$src), IIC_iUNAr, + "rev", ".w\t$dst, $src", + [(set GPR:$dst, (bswap GPR:$src))]>; + +def t2REV16 : T2I<(outs GPR:$dst), (ins GPR:$src), IIC_iUNAr, + "rev16", ".w\t$dst, $src", + [(set GPR:$dst, + (or (and (srl GPR:$src, (i32 8)), 0xFF), + (or (and (shl GPR:$src, (i32 8)), 0xFF00), + (or (and (srl GPR:$src, (i32 8)), 0xFF0000), + (and (shl GPR:$src, (i32 8)), 0xFF000000)))))]>; + +def t2REVSH : T2I<(outs GPR:$dst), (ins GPR:$src), IIC_iUNAr, + "revsh", ".w\t$dst, $src", + [(set GPR:$dst, + (sext_inreg + (or (srl (and GPR:$src, 0xFF00), (i32 8)), + (shl GPR:$src, (i32 8))), i16))]>; + +def t2PKHBT : T2I<(outs GPR:$dst), (ins GPR:$src1, GPR:$src2, i32imm:$shamt), + IIC_iALUsi, "pkhbt", "\t$dst, $src1, $src2, LSL $shamt", + [(set GPR:$dst, (or (and GPR:$src1, 0xFFFF), + (and (shl GPR:$src2, (i32 imm:$shamt)), + 0xFFFF0000)))]>; + +// Alternate cases for PKHBT where identities eliminate some nodes. +def : T2Pat<(or (and GPR:$src1, 0xFFFF), (and GPR:$src2, 0xFFFF0000)), + (t2PKHBT GPR:$src1, GPR:$src2, 0)>; +def : T2Pat<(or (and GPR:$src1, 0xFFFF), (shl GPR:$src2, imm16_31:$shamt)), + (t2PKHBT GPR:$src1, GPR:$src2, imm16_31:$shamt)>; + +def t2PKHTB : T2I<(outs GPR:$dst), (ins GPR:$src1, GPR:$src2, i32imm:$shamt), + IIC_iALUsi, "pkhtb", "\t$dst, $src1, $src2, ASR $shamt", + [(set GPR:$dst, (or (and GPR:$src1, 0xFFFF0000), + (and (sra GPR:$src2, imm16_31:$shamt), + 0xFFFF)))]>; + +// Alternate cases for PKHTB where identities eliminate some nodes. Note that +// a shift amount of 0 is *not legal* here, it is PKHBT instead. +def : T2Pat<(or (and GPR:$src1, 0xFFFF0000), (srl GPR:$src2, (i32 16))), + (t2PKHTB GPR:$src1, GPR:$src2, 16)>; +def : T2Pat<(or (and GPR:$src1, 0xFFFF0000), + (and (srl GPR:$src2, imm1_15:$shamt), 0xFFFF)), + (t2PKHTB GPR:$src1, GPR:$src2, imm1_15:$shamt)>; + +//===----------------------------------------------------------------------===// +// Comparison Instructions... +// + +defm t2CMP : T2I_cmp_is<"cmp", + BinOpFrag<(ARMcmp node:$LHS, node:$RHS)>>; +defm t2CMPz : T2I_cmp_is<"cmp", + BinOpFrag<(ARMcmpZ node:$LHS, node:$RHS)>>; + +defm t2CMN : T2I_cmp_is<"cmn", + BinOpFrag<(ARMcmp node:$LHS,(ineg node:$RHS))>>; +defm t2CMNz : T2I_cmp_is<"cmn", + BinOpFrag<(ARMcmpZ node:$LHS,(ineg node:$RHS))>>; + +def : T2Pat<(ARMcmp GPR:$src, t2_so_imm_neg:$imm), + (t2CMNri GPR:$src, t2_so_imm_neg:$imm)>; + +def : T2Pat<(ARMcmpZ GPR:$src, t2_so_imm_neg:$imm), + (t2CMNri GPR:$src, t2_so_imm_neg:$imm)>; + +defm t2TST : T2I_cmp_is<"tst", + BinOpFrag<(ARMcmpZ (and node:$LHS, node:$RHS), 0)>>; +defm t2TEQ : T2I_cmp_is<"teq", + BinOpFrag<(ARMcmpZ (xor node:$LHS, node:$RHS), 0)>>; + +// A8.6.27 CBNZ, CBZ - Compare and branch on (non)zero. +// Short range conditional branch. Looks awesome for loops. Need to figure +// out how to use this one. + + +// Conditional moves +// FIXME: should be able to write a pattern for ARMcmov, but can't use +// a two-value operand where a dag node expects two operands. :( +def t2MOVCCr : T2I<(outs GPR:$dst), (ins GPR:$false, GPR:$true), IIC_iCMOVr, + "mov", ".w\t$dst, $true", + [/*(set GPR:$dst, (ARMcmov GPR:$false, GPR:$true, imm:$cc, CCR:$ccr))*/]>, + RegConstraint<"$false = $dst">; + +def t2MOVCCi : T2I<(outs GPR:$dst), (ins GPR:$false, t2_so_imm:$true), + IIC_iCMOVi, "mov", ".w\t$dst, $true", +[/*(set GPR:$dst, (ARMcmov GPR:$false, t2_so_imm:$true, imm:$cc, CCR:$ccr))*/]>, + RegConstraint<"$false = $dst">; + +def t2MOVCClsl : T2I<(outs GPR:$dst), (ins GPR:$false, GPR:$true, i32imm:$rhs), + IIC_iCMOVsi, "lsl", ".w\t$dst, $true, $rhs", []>, + RegConstraint<"$false = $dst">; +def t2MOVCClsr : T2I<(outs GPR:$dst), (ins GPR:$false, GPR:$true, i32imm:$rhs), + IIC_iCMOVsi, "lsr", ".w\t$dst, $true, $rhs", []>, + RegConstraint<"$false = $dst">; +def t2MOVCCasr : T2I<(outs GPR:$dst), (ins GPR:$false, GPR:$true, i32imm:$rhs), + IIC_iCMOVsi, "asr", ".w\t$dst, $true, $rhs", []>, + RegConstraint<"$false = $dst">; +def t2MOVCCror : T2I<(outs GPR:$dst), (ins GPR:$false, GPR:$true, i32imm:$rhs), + IIC_iCMOVsi, "ror", ".w\t$dst, $true, $rhs", []>, + RegConstraint<"$false = $dst">; + +//===----------------------------------------------------------------------===// +// TLS Instructions +// + +// __aeabi_read_tp preserves the registers r1-r3. +let isCall = 1, + Defs = [R0, R12, LR, CPSR] in { + def t2TPsoft : T2XI<(outs), (ins), IIC_Br, + "bl\t__aeabi_read_tp", + [(set R0, ARMthread_pointer)]>; +} + +//===----------------------------------------------------------------------===// +// SJLJ Exception handling intrinsics +// eh_sjlj_setjmp() is an instruction sequence to store the return +// address and save #0 in R0 for the non-longjmp case. +// Since by its nature we may be coming from some other function to get +// here, and we're using the stack frame for the containing function to +// save/restore registers, we can't keep anything live in regs across +// the eh_sjlj_setjmp(), else it will almost certainly have been tromped upon +// when we get here from a longjmp(). We force everthing out of registers +// except for our own input by listing the relevant registers in Defs. By +// doing so, we also cause the prologue/epilogue code to actively preserve +// all of the callee-saved resgisters, which is exactly what we want. +let Defs = + [ R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, LR, D0, + D1, D2, D3, D4, D5, D6, D7, D8, D9, D10, D11, D12, D13, D14, D15, + D16, D17, D18, D19, D20, D21, D22, D23, D24, D25, D26, D27, D28, D29, D30, + D31 ] in { + def t2Int_eh_sjlj_setjmp : Thumb2XI<(outs), (ins GPR:$src), + AddrModeNone, SizeSpecial, NoItinerary, + "str.w\tsp, [$src, #+8] @ eh_setjmp begin\n" + "\tadr\tr12, 0f\n" + "\torr.w\tr12, r12, #1\n" + "\tstr.w\tr12, [$src, #+4]\n" + "\tmovs\tr0, #0\n" + "\tb\t1f\n" + "0:\tmovs\tr0, #1 @ eh_setjmp end\n" + "1:", "", + [(set R0, (ARMeh_sjlj_setjmp GPR:$src))]>; +} + + + +//===----------------------------------------------------------------------===// +// Control-Flow Instructions +// + +// FIXME: remove when we have a way to marking a MI with these properties. +// FIXME: $dst1 should be a def. But the extra ops must be in the end of the +// operand list. +// FIXME: Should pc be an implicit operand like PICADD, etc? +let isReturn = 1, isTerminator = 1, isBarrier = 1, mayLoad = 1, + hasExtraDefRegAllocReq = 1 in + def t2LDM_RET : T2XI<(outs), + (ins addrmode4:$addr, pred:$p, reglist:$wb, variable_ops), + IIC_Br, "ldm${addr:submode}${p}${addr:wide}\t$addr, $wb", + []>; + +let isBranch = 1, isTerminator = 1, isBarrier = 1 in { +let isPredicable = 1 in +def t2B : T2XI<(outs), (ins brtarget:$target), IIC_Br, + "b.w\t$target", + [(br bb:$target)]>; + +let isNotDuplicable = 1, isIndirectBranch = 1 in { +def t2BR_JT : + T2JTI<(outs), + (ins GPR:$target, GPR:$index, jt2block_operand:$jt, i32imm:$id), + IIC_Br, "mov\tpc, $target\n$jt", + [(ARMbr2jt GPR:$target, GPR:$index, tjumptable:$jt, imm:$id)]>; + +// FIXME: Add a non-pc based case that can be predicated. +def t2TBB : + T2JTI<(outs), + (ins tb_addrmode:$index, jt2block_operand:$jt, i32imm:$id), + IIC_Br, "tbb\t$index\n$jt", []>; + +def t2TBH : + T2JTI<(outs), + (ins tb_addrmode:$index, jt2block_operand:$jt, i32imm:$id), + IIC_Br, "tbh\t$index\n$jt", []>; +} // isNotDuplicable, isIndirectBranch + +} // isBranch, isTerminator, isBarrier + +// FIXME: should be able to write a pattern for ARMBrcond, but can't use +// a two-value operand where a dag node expects two operands. :( +let isBranch = 1, isTerminator = 1 in +def t2Bcc : T2I<(outs), (ins brtarget:$target), IIC_Br, + "b", ".w\t$target", + [/*(ARMbrcond bb:$target, imm:$cc)*/]>; + + +// IT block +def t2IT : Thumb2XI<(outs), (ins it_pred:$cc, it_mask:$mask), + AddrModeNone, Size2Bytes, IIC_iALUx, + "it$mask\t$cc", "", []>; + +//===----------------------------------------------------------------------===// +// Non-Instruction Patterns +// + +// Two piece so_imms. +def : T2Pat<(or GPR:$LHS, t2_so_imm2part:$RHS), + (t2ORRri (t2ORRri GPR:$LHS, (t2_so_imm2part_1 imm:$RHS)), + (t2_so_imm2part_2 imm:$RHS))>; +def : T2Pat<(xor GPR:$LHS, t2_so_imm2part:$RHS), + (t2EORri (t2EORri GPR:$LHS, (t2_so_imm2part_1 imm:$RHS)), + (t2_so_imm2part_2 imm:$RHS))>; +def : T2Pat<(add GPR:$LHS, t2_so_imm2part:$RHS), + (t2ADDri (t2ADDri GPR:$LHS, (t2_so_imm2part_1 imm:$RHS)), + (t2_so_imm2part_2 imm:$RHS))>; +def : T2Pat<(add GPR:$LHS, t2_so_neg_imm2part:$RHS), + (t2SUBri (t2SUBri GPR:$LHS, (t2_so_neg_imm2part_1 imm:$RHS)), + (t2_so_neg_imm2part_2 imm:$RHS))>; + +// 32-bit immediate using movw + movt. +// This is a single pseudo instruction to make it re-materializable. Remove +// when we can do generalized remat. +let isReMaterializable = 1 in +def t2MOVi32imm : T2Ix2<(outs GPR:$dst), (ins i32imm:$src), IIC_iMOVi, + "movw", "\t$dst, ${src:lo16}\n\tmovt${p}\t$dst, ${src:hi16}", + [(set GPR:$dst, (i32 imm:$src))]>; + +// ConstantPool, GlobalAddress, and JumpTable +def : T2Pat<(ARMWrapper tglobaladdr :$dst), (t2LEApcrel tglobaladdr :$dst)>, + Requires<[IsThumb2, DontUseMovt]>; +def : T2Pat<(ARMWrapper tconstpool :$dst), (t2LEApcrel tconstpool :$dst)>; +def : T2Pat<(ARMWrapper tglobaladdr :$dst), (t2MOVi32imm tglobaladdr :$dst)>, + Requires<[IsThumb2, UseMovt]>; + +def : T2Pat<(ARMWrapperJT tjumptable:$dst, imm:$id), + (t2LEApcrelJT tjumptable:$dst, imm:$id)>; + +// Pseudo instruction that combines ldr from constpool and add pc. This should +// be expanded into two instructions late to allow if-conversion and +// scheduling. +let canFoldAsLoad = 1, isReMaterializable = 1, mayHaveSideEffects = 1 in +def t2LDRpci_pic : PseudoInst<(outs GPR:$dst), (ins i32imm:$addr, pclabel:$cp), + NoItinerary, "@ ldr.w\t$dst, $addr\n$cp:\n\tadd\t$dst, pc", + [(set GPR:$dst, (ARMpic_add (load (ARMWrapper tconstpool:$addr)), + imm:$cp))]>, + Requires<[IsThumb2]>; diff --git a/libclamav/c++/llvm/lib/Target/ARM/ARMInstrVFP.td b/libclamav/c++/llvm/lib/Target/ARM/ARMInstrVFP.td new file mode 100644 index 000000000..5bfe89d25 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/ARM/ARMInstrVFP.td @@ -0,0 +1,459 @@ +//===- ARMInstrVFP.td - VFP support for ARM -------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file describes the ARM VFP instruction set. +// +//===----------------------------------------------------------------------===// + +def SDT_FTOI : +SDTypeProfile<1, 1, [SDTCisVT<0, f32>, SDTCisFP<1>]>; +def SDT_ITOF : +SDTypeProfile<1, 1, [SDTCisFP<0>, SDTCisVT<1, f32>]>; +def SDT_CMPFP0 : +SDTypeProfile<0, 1, [SDTCisFP<0>]>; +def SDT_VMOVDRR : +SDTypeProfile<1, 2, [SDTCisVT<0, f64>, SDTCisVT<1, i32>, + SDTCisSameAs<1, 2>]>; + +def arm_ftoui : SDNode<"ARMISD::FTOUI", SDT_FTOI>; +def arm_ftosi : SDNode<"ARMISD::FTOSI", SDT_FTOI>; +def arm_sitof : SDNode<"ARMISD::SITOF", SDT_ITOF>; +def arm_uitof : SDNode<"ARMISD::UITOF", SDT_ITOF>; +def arm_fmstat : SDNode<"ARMISD::FMSTAT", SDTNone, [SDNPInFlag,SDNPOutFlag]>; +def arm_cmpfp : SDNode<"ARMISD::CMPFP", SDT_ARMCmp, [SDNPOutFlag]>; +def arm_cmpfp0 : SDNode<"ARMISD::CMPFPw0",SDT_CMPFP0, [SDNPOutFlag]>; +def arm_fmdrr : SDNode<"ARMISD::VMOVDRR", SDT_VMOVDRR>; + +//===----------------------------------------------------------------------===// +// Operand Definitions. +// + + +def vfp_f32imm : Operand, + PatLeaf<(f32 fpimm), [{ + return ARM::getVFPf32Imm(N->getValueAPF()) != -1; + }]> { + let PrintMethod = "printVFPf32ImmOperand"; +} + +def vfp_f64imm : Operand, + PatLeaf<(f64 fpimm), [{ + return ARM::getVFPf64Imm(N->getValueAPF()) != -1; + }]> { + let PrintMethod = "printVFPf64ImmOperand"; +} + + +//===----------------------------------------------------------------------===// +// Load / store Instructions. +// + +let canFoldAsLoad = 1, isReMaterializable = 1, mayHaveSideEffects = 1 in { +def VLDRD : ADI5<0b1101, 0b01, (outs DPR:$dst), (ins addrmode5:$addr), + IIC_fpLoad64, "vldr", ".64\t$dst, $addr", + [(set DPR:$dst, (load addrmode5:$addr))]>; + +def VLDRS : ASI5<0b1101, 0b01, (outs SPR:$dst), (ins addrmode5:$addr), + IIC_fpLoad32, "vldr", ".32\t$dst, $addr", + [(set SPR:$dst, (load addrmode5:$addr))]>; +} // canFoldAsLoad + +def VSTRD : ADI5<0b1101, 0b00, (outs), (ins DPR:$src, addrmode5:$addr), + IIC_fpStore64, "vstr", ".64\t$src, $addr", + [(store DPR:$src, addrmode5:$addr)]>; + +def VSTRS : ASI5<0b1101, 0b00, (outs), (ins SPR:$src, addrmode5:$addr), + IIC_fpStore32, "vstr", ".32\t$src, $addr", + [(store SPR:$src, addrmode5:$addr)]>; + +//===----------------------------------------------------------------------===// +// Load / store multiple Instructions. +// + +let mayLoad = 1, hasExtraDefRegAllocReq = 1 in { +def VLDMD : AXDI5<(outs), (ins addrmode5:$addr, pred:$p, reglist:$wb, + variable_ops), IIC_fpLoadm, + "vldm${addr:submode}${p}\t${addr:base}, $wb", + []> { + let Inst{20} = 1; +} + +def VLDMS : AXSI5<(outs), (ins addrmode5:$addr, pred:$p, reglist:$wb, + variable_ops), IIC_fpLoadm, + "vldm${addr:submode}${p}\t${addr:base}, $wb", + []> { + let Inst{20} = 1; +} +} // mayLoad, hasExtraDefRegAllocReq + +let mayStore = 1, hasExtraSrcRegAllocReq = 1 in { +def VSTMD : AXDI5<(outs), (ins addrmode5:$addr, pred:$p, reglist:$wb, + variable_ops), IIC_fpStorem, + "vstm${addr:submode}${p}\t${addr:base}, $wb", + []> { + let Inst{20} = 0; +} + +def VSTMS : AXSI5<(outs), (ins addrmode5:$addr, pred:$p, reglist:$wb, + variable_ops), IIC_fpStorem, + "vstm${addr:submode}${p}\t${addr:base}, $wb", + []> { + let Inst{20} = 0; +} +} // mayStore, hasExtraSrcRegAllocReq + +// FLDMX, FSTMX - mixing S/D registers for pre-armv6 cores + +//===----------------------------------------------------------------------===// +// FP Binary Operations. +// + +def VADDD : ADbI<0b11100011, (outs DPR:$dst), (ins DPR:$a, DPR:$b), + IIC_fpALU64, "vadd", ".f64\t$dst, $a, $b", + [(set DPR:$dst, (fadd DPR:$a, DPR:$b))]>; + +def VADDS : ASbIn<0b11100011, (outs SPR:$dst), (ins SPR:$a, SPR:$b), + IIC_fpALU32, "vadd", ".f32\t$dst, $a, $b", + [(set SPR:$dst, (fadd SPR:$a, SPR:$b))]>; + +// These are encoded as unary instructions. +let Defs = [FPSCR] in { +def VCMPED : ADuI<0b11101011, 0b0100, 0b1100, (outs), (ins DPR:$a, DPR:$b), + IIC_fpCMP64, "vcmpe", ".f64\t$a, $b", + [(arm_cmpfp DPR:$a, DPR:$b)]>; + +def VCMPES : ASuI<0b11101011, 0b0100, 0b1100, (outs), (ins SPR:$a, SPR:$b), + IIC_fpCMP32, "vcmpe", ".f32\t$a, $b", + [(arm_cmpfp SPR:$a, SPR:$b)]>; +} + +def VDIVD : ADbI<0b11101000, (outs DPR:$dst), (ins DPR:$a, DPR:$b), + IIC_fpDIV64, "vdiv", ".f64\t$dst, $a, $b", + [(set DPR:$dst, (fdiv DPR:$a, DPR:$b))]>; + +def VDIVS : ASbI<0b11101000, (outs SPR:$dst), (ins SPR:$a, SPR:$b), + IIC_fpDIV32, "vdiv", ".f32\t$dst, $a, $b", + [(set SPR:$dst, (fdiv SPR:$a, SPR:$b))]>; + +def VMULD : ADbI<0b11100010, (outs DPR:$dst), (ins DPR:$a, DPR:$b), + IIC_fpMUL64, "vmul", ".f64\t$dst, $a, $b", + [(set DPR:$dst, (fmul DPR:$a, DPR:$b))]>; + +def VMULS : ASbIn<0b11100010, (outs SPR:$dst), (ins SPR:$a, SPR:$b), + IIC_fpMUL32, "vmul", ".f32\t$dst, $a, $b", + [(set SPR:$dst, (fmul SPR:$a, SPR:$b))]>; + +def VNMULD : ADbI<0b11100010, (outs DPR:$dst), (ins DPR:$a, DPR:$b), + IIC_fpMUL64, "vnmul", ".f64\t$dst, $a, $b", + [(set DPR:$dst, (fneg (fmul DPR:$a, DPR:$b)))]> { + let Inst{6} = 1; +} + +def VNMULS : ASbI<0b11100010, (outs SPR:$dst), (ins SPR:$a, SPR:$b), + IIC_fpMUL32, "vnmul", ".f32\t$dst, $a, $b", + [(set SPR:$dst, (fneg (fmul SPR:$a, SPR:$b)))]> { + let Inst{6} = 1; +} + +// Match reassociated forms only if not sign dependent rounding. +def : Pat<(fmul (fneg DPR:$a), DPR:$b), + (VNMULD DPR:$a, DPR:$b)>, Requires<[NoHonorSignDependentRounding]>; +def : Pat<(fmul (fneg SPR:$a), SPR:$b), + (VNMULS SPR:$a, SPR:$b)>, Requires<[NoHonorSignDependentRounding]>; + + +def VSUBD : ADbI<0b11100011, (outs DPR:$dst), (ins DPR:$a, DPR:$b), + IIC_fpALU64, "vsub", ".f64\t$dst, $a, $b", + [(set DPR:$dst, (fsub DPR:$a, DPR:$b))]> { + let Inst{6} = 1; +} + +def VSUBS : ASbIn<0b11100011, (outs SPR:$dst), (ins SPR:$a, SPR:$b), + IIC_fpALU32, "vsub", ".f32\t$dst, $a, $b", + [(set SPR:$dst, (fsub SPR:$a, SPR:$b))]> { + let Inst{6} = 1; +} + +//===----------------------------------------------------------------------===// +// FP Unary Operations. +// + +def VABSD : ADuI<0b11101011, 0b0000, 0b1100, (outs DPR:$dst), (ins DPR:$a), + IIC_fpUNA64, "vabs", ".f64\t$dst, $a", + [(set DPR:$dst, (fabs DPR:$a))]>; + +def VABSS : ASuIn<0b11101011, 0b0000, 0b1100, (outs SPR:$dst), (ins SPR:$a), + IIC_fpUNA32, "vabs", ".f32\t$dst, $a", + [(set SPR:$dst, (fabs SPR:$a))]>; + +let Defs = [FPSCR] in { +def VCMPEZD : ADuI<0b11101011, 0b0101, 0b1100, (outs), (ins DPR:$a), + IIC_fpCMP64, "vcmpe", ".f64\t$a, #0", + [(arm_cmpfp0 DPR:$a)]>; + +def VCMPEZS : ASuI<0b11101011, 0b0101, 0b1100, (outs), (ins SPR:$a), + IIC_fpCMP32, "vcmpe", ".f32\t$a, #0", + [(arm_cmpfp0 SPR:$a)]>; +} + +def VCVTDS : ASuI<0b11101011, 0b0111, 0b1100, (outs DPR:$dst), (ins SPR:$a), + IIC_fpCVTDS, "vcvt", ".f64.f32\t$dst, $a", + [(set DPR:$dst, (fextend SPR:$a))]>; + +// Special case encoding: bits 11-8 is 0b1011. +def VCVTSD : VFPAI<(outs SPR:$dst), (ins DPR:$a), VFPUnaryFrm, + IIC_fpCVTSD, "vcvt", ".f32.f64\t$dst, $a", + [(set SPR:$dst, (fround DPR:$a))]> { + let Inst{27-23} = 0b11101; + let Inst{21-16} = 0b110111; + let Inst{11-8} = 0b1011; + let Inst{7-4} = 0b1100; +} + +let neverHasSideEffects = 1 in { +def VMOVD: ADuI<0b11101011, 0b0000, 0b0100, (outs DPR:$dst), (ins DPR:$a), + IIC_fpUNA64, "vmov", ".f64\t$dst, $a", []>; + +def VMOVS: ASuI<0b11101011, 0b0000, 0b0100, (outs SPR:$dst), (ins SPR:$a), + IIC_fpUNA32, "vmov", ".f32\t$dst, $a", []>; +} // neverHasSideEffects + +def VNEGD : ADuI<0b11101011, 0b0001, 0b0100, (outs DPR:$dst), (ins DPR:$a), + IIC_fpUNA64, "vneg", ".f64\t$dst, $a", + [(set DPR:$dst, (fneg DPR:$a))]>; + +def VNEGS : ASuIn<0b11101011, 0b0001, 0b0100, (outs SPR:$dst), (ins SPR:$a), + IIC_fpUNA32, "vneg", ".f32\t$dst, $a", + [(set SPR:$dst, (fneg SPR:$a))]>; + +def VSQRTD : ADuI<0b11101011, 0b0001, 0b1100, (outs DPR:$dst), (ins DPR:$a), + IIC_fpSQRT64, "vsqrt", ".f64\t$dst, $a", + [(set DPR:$dst, (fsqrt DPR:$a))]>; + +def VSQRTS : ASuI<0b11101011, 0b0001, 0b1100, (outs SPR:$dst), (ins SPR:$a), + IIC_fpSQRT32, "vsqrt", ".f32\t$dst, $a", + [(set SPR:$dst, (fsqrt SPR:$a))]>; + +//===----------------------------------------------------------------------===// +// FP <-> GPR Copies. Int <-> FP Conversions. +// + +def VMOVRS : AVConv2I<0b11100001, 0b1010, (outs GPR:$dst), (ins SPR:$src), + IIC_VMOVSI, "vmov", "\t$dst, $src", + [(set GPR:$dst, (bitconvert SPR:$src))]>; + +def VMOVSR : AVConv4I<0b11100000, 0b1010, (outs SPR:$dst), (ins GPR:$src), + IIC_VMOVIS, "vmov", "\t$dst, $src", + [(set SPR:$dst, (bitconvert GPR:$src))]>; + +def VMOVRRD : AVConv3I<0b11000101, 0b1011, + (outs GPR:$wb, GPR:$dst2), (ins DPR:$src), + IIC_VMOVDI, "vmov", "\t$wb, $dst2, $src", + [/* FIXME: Can't write pattern for multiple result instr*/]>; + +// FMDHR: GPR -> SPR +// FMDLR: GPR -> SPR + +def VMOVDRR : AVConv5I<0b11000100, 0b1011, + (outs DPR:$dst), (ins GPR:$src1, GPR:$src2), + IIC_VMOVID, "vmov", "\t$dst, $src1, $src2", + [(set DPR:$dst, (arm_fmdrr GPR:$src1, GPR:$src2))]>; + +// FMRDH: SPR -> GPR +// FMRDL: SPR -> GPR +// FMRRS: SPR -> GPR +// FMRX : SPR system reg -> GPR + +// FMSRR: GPR -> SPR + +// FMXR: GPR -> VFP Sstem reg + + +// Int to FP: + +def VSITOD : AVConv1I<0b11101011, 0b1000, 0b1011, (outs DPR:$dst), (ins SPR:$a), + IIC_fpCVTID, "vcvt", ".f64.s32\t$dst, $a", + [(set DPR:$dst, (arm_sitof SPR:$a))]> { + let Inst{7} = 1; +} + +def VSITOS : AVConv1In<0b11101011, 0b1000, 0b1010, (outs SPR:$dst),(ins SPR:$a), + IIC_fpCVTIS, "vcvt", ".f32.s32\t$dst, $a", + [(set SPR:$dst, (arm_sitof SPR:$a))]> { + let Inst{7} = 1; +} + +def VUITOD : AVConv1I<0b11101011, 0b1000, 0b1011, (outs DPR:$dst), (ins SPR:$a), + IIC_fpCVTID, "vcvt", ".f64.u32\t$dst, $a", + [(set DPR:$dst, (arm_uitof SPR:$a))]>; + +def VUITOS : AVConv1In<0b11101011, 0b1000, 0b1010, (outs SPR:$dst),(ins SPR:$a), + IIC_fpCVTIS, "vcvt", ".f32.u32\t$dst, $a", + [(set SPR:$dst, (arm_uitof SPR:$a))]>; + +// FP to Int: +// Always set Z bit in the instruction, i.e. "round towards zero" variants. + +def VTOSIZD : AVConv1I<0b11101011, 0b1101, 0b1011, + (outs SPR:$dst), (ins DPR:$a), + IIC_fpCVTDI, "vcvt", ".s32.f64\t$dst, $a", + [(set SPR:$dst, (arm_ftosi DPR:$a))]> { + let Inst{7} = 1; // Z bit +} + +def VTOSIZS : AVConv1In<0b11101011, 0b1101, 0b1010, + (outs SPR:$dst), (ins SPR:$a), + IIC_fpCVTSI, "vcvt", ".s32.f32\t$dst, $a", + [(set SPR:$dst, (arm_ftosi SPR:$a))]> { + let Inst{7} = 1; // Z bit +} + +def VTOUIZD : AVConv1I<0b11101011, 0b1100, 0b1011, + (outs SPR:$dst), (ins DPR:$a), + IIC_fpCVTDI, "vcvt", ".u32.f64\t$dst, $a", + [(set SPR:$dst, (arm_ftoui DPR:$a))]> { + let Inst{7} = 1; // Z bit +} + +def VTOUIZS : AVConv1In<0b11101011, 0b1100, 0b1010, + (outs SPR:$dst), (ins SPR:$a), + IIC_fpCVTSI, "vcvt", ".u32.f32\t$dst, $a", + [(set SPR:$dst, (arm_ftoui SPR:$a))]> { + let Inst{7} = 1; // Z bit +} + +//===----------------------------------------------------------------------===// +// FP FMA Operations. +// + +def VMLAD : ADbI<0b11100000, (outs DPR:$dst), (ins DPR:$dstin, DPR:$a, DPR:$b), + IIC_fpMAC64, "vmla", ".f64\t$dst, $a, $b", + [(set DPR:$dst, (fadd (fmul DPR:$a, DPR:$b), DPR:$dstin))]>, + RegConstraint<"$dstin = $dst">; + +def VMLAS : ASbIn<0b11100000, (outs SPR:$dst), (ins SPR:$dstin, SPR:$a, SPR:$b), + IIC_fpMAC32, "vmla", ".f32\t$dst, $a, $b", + [(set SPR:$dst, (fadd (fmul SPR:$a, SPR:$b), SPR:$dstin))]>, + RegConstraint<"$dstin = $dst">; + +def VNMLSD : ADbI<0b11100001, (outs DPR:$dst), (ins DPR:$dstin, DPR:$a, DPR:$b), + IIC_fpMAC64, "vnmls", ".f64\t$dst, $a, $b", + [(set DPR:$dst, (fsub (fmul DPR:$a, DPR:$b), DPR:$dstin))]>, + RegConstraint<"$dstin = $dst">; + +def VNMLSS : ASbI<0b11100001, (outs SPR:$dst), (ins SPR:$dstin, SPR:$a, SPR:$b), + IIC_fpMAC32, "vnmls", ".f32\t$dst, $a, $b", + [(set SPR:$dst, (fsub (fmul SPR:$a, SPR:$b), SPR:$dstin))]>, + RegConstraint<"$dstin = $dst">; + +def VMLSD : ADbI<0b11100000, (outs DPR:$dst), (ins DPR:$dstin, DPR:$a, DPR:$b), + IIC_fpMAC64, "vmls", ".f64\t$dst, $a, $b", + [(set DPR:$dst, (fadd (fneg (fmul DPR:$a, DPR:$b)), DPR:$dstin))]>, + RegConstraint<"$dstin = $dst"> { + let Inst{6} = 1; +} + +def VMLSS : ASbIn<0b11100000, (outs SPR:$dst), (ins SPR:$dstin, SPR:$a, SPR:$b), + IIC_fpMAC32, "vmls", ".f32\t$dst, $a, $b", + [(set SPR:$dst, (fadd (fneg (fmul SPR:$a, SPR:$b)), SPR:$dstin))]>, + RegConstraint<"$dstin = $dst"> { + let Inst{6} = 1; +} + +def : Pat<(fsub DPR:$dstin, (fmul DPR:$a, DPR:$b)), + (VMLSD DPR:$dstin, DPR:$a, DPR:$b)>, Requires<[DontUseNEONForFP]>; +def : Pat<(fsub SPR:$dstin, (fmul SPR:$a, SPR:$b)), + (VMLSS SPR:$dstin, SPR:$a, SPR:$b)>, Requires<[DontUseNEONForFP]>; + +def VNMLAD : ADbI<0b11100001, (outs DPR:$dst), (ins DPR:$dstin, DPR:$a, DPR:$b), + IIC_fpMAC64, "vnmla", ".f64\t$dst, $a, $b", + [(set DPR:$dst, (fsub (fneg (fmul DPR:$a, DPR:$b)), DPR:$dstin))]>, + RegConstraint<"$dstin = $dst"> { + let Inst{6} = 1; +} + +def VNMLAS : ASbI<0b11100001, (outs SPR:$dst), (ins SPR:$dstin, SPR:$a, SPR:$b), + IIC_fpMAC32, "vnmla", ".f32\t$dst, $a, $b", + [(set SPR:$dst, (fsub (fneg (fmul SPR:$a, SPR:$b)), SPR:$dstin))]>, + RegConstraint<"$dstin = $dst"> { + let Inst{6} = 1; +} + +//===----------------------------------------------------------------------===// +// FP Conditional moves. +// + +def VMOVDcc : ADuI<0b11101011, 0b0000, 0b0100, + (outs DPR:$dst), (ins DPR:$false, DPR:$true), + IIC_fpUNA64, "vmov", ".f64\t$dst, $true", + [/*(set DPR:$dst, (ARMcmov DPR:$false, DPR:$true, imm:$cc))*/]>, + RegConstraint<"$false = $dst">; + +def VMOVScc : ASuI<0b11101011, 0b0000, 0b0100, + (outs SPR:$dst), (ins SPR:$false, SPR:$true), + IIC_fpUNA32, "vmov", ".f32\t$dst, $true", + [/*(set SPR:$dst, (ARMcmov SPR:$false, SPR:$true, imm:$cc))*/]>, + RegConstraint<"$false = $dst">; + +def VNEGDcc : ADuI<0b11101011, 0b0001, 0b0100, + (outs DPR:$dst), (ins DPR:$false, DPR:$true), + IIC_fpUNA64, "vneg", ".f64\t$dst, $true", + [/*(set DPR:$dst, (ARMcneg DPR:$false, DPR:$true, imm:$cc))*/]>, + RegConstraint<"$false = $dst">; + +def VNEGScc : ASuI<0b11101011, 0b0001, 0b0100, + (outs SPR:$dst), (ins SPR:$false, SPR:$true), + IIC_fpUNA32, "vneg", ".f32\t$dst, $true", + [/*(set SPR:$dst, (ARMcneg SPR:$false, SPR:$true, imm:$cc))*/]>, + RegConstraint<"$false = $dst">; + + +//===----------------------------------------------------------------------===// +// Misc. +// + +// APSR is the application level alias of CPSR. This FPSCR N, Z, C, V flags +// to APSR. +let Defs = [CPSR], Uses = [FPSCR] in +def FMSTAT : VFPAI<(outs), (ins), VFPMiscFrm, IIC_fpSTAT, "vmrs", + "\tapsr_nzcv, fpscr", + [(arm_fmstat)]> { + let Inst{27-20} = 0b11101111; + let Inst{19-16} = 0b0001; + let Inst{15-12} = 0b1111; + let Inst{11-8} = 0b1010; + let Inst{7} = 0; + let Inst{4} = 1; +} + + +// Materialize FP immediates. VFP3 only. +let isReMaterializable = 1 in { +def FCONSTD : VFPAI<(outs DPR:$dst), (ins vfp_f64imm:$imm), + VFPMiscFrm, IIC_VMOVImm, + "vmov", ".f64\t$dst, $imm", + [(set DPR:$dst, vfp_f64imm:$imm)]>, Requires<[HasVFP3]> { + let Inst{27-23} = 0b11101; + let Inst{21-20} = 0b11; + let Inst{11-9} = 0b101; + let Inst{8} = 1; + let Inst{7-4} = 0b0000; +} + +def FCONSTS : VFPAI<(outs SPR:$dst), (ins vfp_f32imm:$imm), + VFPMiscFrm, IIC_VMOVImm, + "vmov", ".f32\t$dst, $imm", + [(set SPR:$dst, vfp_f32imm:$imm)]>, Requires<[HasVFP3]> { + let Inst{27-23} = 0b11101; + let Inst{21-20} = 0b11; + let Inst{11-9} = 0b101; + let Inst{8} = 0; + let Inst{7-4} = 0b0000; +} +} diff --git a/libclamav/c++/llvm/lib/Target/ARM/ARMJITInfo.cpp b/libclamav/c++/llvm/lib/Target/ARM/ARMJITInfo.cpp new file mode 100644 index 000000000..aa50cfd30 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/ARM/ARMJITInfo.cpp @@ -0,0 +1,329 @@ +//===-- ARMJITInfo.cpp - Implement the JIT interfaces for the ARM target --===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the JIT interfaces for the ARM target. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "jit" +#include "ARMJITInfo.h" +#include "ARMInstrInfo.h" +#include "ARMConstantPoolValue.h" +#include "ARMRelocations.h" +#include "ARMSubtarget.h" +#include "llvm/Function.h" +#include "llvm/CodeGen/JITCodeEmitter.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/System/Memory.h" +#include +using namespace llvm; + +void ARMJITInfo::replaceMachineCodeForFunction(void *Old, void *New) { + llvm_report_error("ARMJITInfo::replaceMachineCodeForFunction"); +} + +/// JITCompilerFunction - This contains the address of the JIT function used to +/// compile a function lazily. +static TargetJITInfo::JITCompilerFn JITCompilerFunction; + +// Get the ASMPREFIX for the current host. This is often '_'. +#ifndef __USER_LABEL_PREFIX__ +#define __USER_LABEL_PREFIX__ +#endif +#define GETASMPREFIX2(X) #X +#define GETASMPREFIX(X) GETASMPREFIX2(X) +#define ASMPREFIX GETASMPREFIX(__USER_LABEL_PREFIX__) + +// CompilationCallback stub - We can't use a C function with inline assembly in +// it, because we the prolog/epilog inserted by GCC won't work for us (we need +// to preserve more context and manipulate the stack directly). Instead, +// write our own wrapper, which does things our way, so we have complete +// control over register saving and restoring. +extern "C" { +#if defined(__arm__) + void ARMCompilationCallback(); + asm( + ".text\n" + ".align 2\n" + ".globl " ASMPREFIX "ARMCompilationCallback\n" + ASMPREFIX "ARMCompilationCallback:\n" + // Save caller saved registers since they may contain stuff + // for the real target function right now. We have to act as if this + // whole compilation callback doesn't exist as far as the caller is + // concerned, so we can't just preserve the callee saved regs. + "stmdb sp!, {r0, r1, r2, r3, lr}\n" +#ifndef __SOFTFP__ + "fstmfdd sp!, {d0, d1, d2, d3, d4, d5, d6, d7}\n" +#endif + // The LR contains the address of the stub function on entry. + // pass it as the argument to the C part of the callback + "mov r0, lr\n" + "sub sp, sp, #4\n" + // Call the C portion of the callback + "bl " ASMPREFIX "ARMCompilationCallbackC\n" + "add sp, sp, #4\n" + // Restoring the LR to the return address of the function that invoked + // the stub and de-allocating the stack space for it requires us to + // swap the two saved LR values on the stack, as they're backwards + // for what we need since the pop instruction has a pre-determined + // order for the registers. + // +--------+ + // 0 | LR | Original return address + // +--------+ + // 1 | LR | Stub address (start of stub) + // 2-5 | R3..R0 | Saved registers (we need to preserve all regs) + // 6-20 | D0..D7 | Saved VFP registers + // +--------+ + // +#ifndef __SOFTFP__ + // Restore VFP caller-saved registers. + "fldmfdd sp!, {d0, d1, d2, d3, d4, d5, d6, d7}\n" +#endif + // + // We need to exchange the values in slots 0 and 1 so we can + // return to the address in slot 1 with the address in slot 0 + // restored to the LR. + "ldr r0, [sp,#20]\n" + "ldr r1, [sp,#16]\n" + "str r1, [sp,#20]\n" + "str r0, [sp,#16]\n" + // Return to the (newly modified) stub to invoke the real function. + // The above twiddling of the saved return addresses allows us to + // deallocate everything, including the LR the stub saved, all in one + // pop instruction. + "ldmia sp!, {r0, r1, r2, r3, lr, pc}\n" + ); +#else // Not an ARM host + void ARMCompilationCallback() { + llvm_unreachable("Cannot call ARMCompilationCallback() on a non-ARM arch!"); + } +#endif +} + +/// ARMCompilationCallbackC - This is the target-specific function invoked +/// by the function stub when we did not know the real target of a call. +/// This function must locate the start of the stub or call site and pass +/// it into the JIT compiler function. +extern "C" void ARMCompilationCallbackC(intptr_t StubAddr) { + // Get the address of the compiled code for this function. + intptr_t NewVal = (intptr_t)JITCompilerFunction((void*)StubAddr); + + // Rewrite the call target... so that we don't end up here every time we + // execute the call. We're replacing the first two instructions of the + // stub with: + // ldr pc, [pc,#-4] + // + if (!sys::Memory::setRangeWritable((void*)StubAddr, 8)) { + llvm_unreachable("ERROR: Unable to mark stub writable"); + } + *(intptr_t *)StubAddr = 0xe51ff004; // ldr pc, [pc, #-4] + *(intptr_t *)(StubAddr+4) = NewVal; + if (!sys::Memory::setRangeExecutable((void*)StubAddr, 8)) { + llvm_unreachable("ERROR: Unable to mark stub executable"); + } +} + +TargetJITInfo::LazyResolverFn +ARMJITInfo::getLazyResolverFunction(JITCompilerFn F) { + JITCompilerFunction = F; + return ARMCompilationCallback; +} + +void *ARMJITInfo::emitGlobalValueIndirectSym(const GlobalValue *GV, void *Ptr, + JITCodeEmitter &JCE) { + MachineCodeEmitter::BufferState BS; + JCE.startGVStub(BS, GV, 4, 4); + intptr_t Addr = (intptr_t)JCE.getCurrentPCValue(); + if (!sys::Memory::setRangeWritable((void*)Addr, 4)) { + llvm_unreachable("ERROR: Unable to mark indirect symbol writable"); + } + JCE.emitWordLE((intptr_t)Ptr); + if (!sys::Memory::setRangeExecutable((void*)Addr, 4)) { + llvm_unreachable("ERROR: Unable to mark indirect symbol executable"); + } + void *PtrAddr = JCE.finishGVStub(BS); + addIndirectSymAddr(Ptr, (intptr_t)PtrAddr); + return PtrAddr; +} + +TargetJITInfo::StubLayout ARMJITInfo::getStubLayout() { + // The stub contains up to 3 4-byte instructions, aligned at 4 bytes, and a + // 4-byte address. See emitFunctionStub for details. + StubLayout Result = {16, 4}; + return Result; +} + +void *ARMJITInfo::emitFunctionStub(const Function* F, void *Fn, + JITCodeEmitter &JCE) { + void *Addr; + // If this is just a call to an external function, emit a branch instead of a + // call. The code is the same except for one bit of the last instruction. + if (Fn != (void*)(intptr_t)ARMCompilationCallback) { + // Branch to the corresponding function addr. + if (IsPIC) { + // The stub is 16-byte size and 4-aligned. + intptr_t LazyPtr = getIndirectSymAddr(Fn); + if (!LazyPtr) { + // In PIC mode, the function stub is loading a lazy-ptr. + LazyPtr= (intptr_t)emitGlobalValueIndirectSym((GlobalValue*)F, Fn, JCE); + DEBUG(if (F) + errs() << "JIT: Indirect symbol emitted at [" << LazyPtr + << "] for GV '" << F->getName() << "'\n"; + else + errs() << "JIT: Stub emitted at [" << LazyPtr + << "] for external function at '" << Fn << "'\n"); + } + JCE.emitAlignment(4); + Addr = (void*)JCE.getCurrentPCValue(); + if (!sys::Memory::setRangeWritable(Addr, 16)) { + llvm_unreachable("ERROR: Unable to mark stub writable"); + } + JCE.emitWordLE(0xe59fc004); // ldr ip, [pc, #+4] + JCE.emitWordLE(0xe08fc00c); // L_func$scv: add ip, pc, ip + JCE.emitWordLE(0xe59cf000); // ldr pc, [ip] + JCE.emitWordLE(LazyPtr - (intptr_t(Addr)+4+8)); // func - (L_func$scv+8) + sys::Memory::InvalidateInstructionCache(Addr, 16); + if (!sys::Memory::setRangeExecutable(Addr, 16)) { + llvm_unreachable("ERROR: Unable to mark stub executable"); + } + } else { + // The stub is 8-byte size and 4-aligned. + JCE.emitAlignment(4); + Addr = (void*)JCE.getCurrentPCValue(); + if (!sys::Memory::setRangeWritable(Addr, 8)) { + llvm_unreachable("ERROR: Unable to mark stub writable"); + } + JCE.emitWordLE(0xe51ff004); // ldr pc, [pc, #-4] + JCE.emitWordLE((intptr_t)Fn); // addr of function + sys::Memory::InvalidateInstructionCache(Addr, 8); + if (!sys::Memory::setRangeExecutable(Addr, 8)) { + llvm_unreachable("ERROR: Unable to mark stub executable"); + } + } + } else { + // The compilation callback will overwrite the first two words of this + // stub with indirect branch instructions targeting the compiled code. + // This stub sets the return address to restart the stub, so that + // the new branch will be invoked when we come back. + // + // Branch and link to the compilation callback. + // The stub is 16-byte size and 4-byte aligned. + JCE.emitAlignment(4); + Addr = (void*)JCE.getCurrentPCValue(); + if (!sys::Memory::setRangeWritable(Addr, 16)) { + llvm_unreachable("ERROR: Unable to mark stub writable"); + } + // Save LR so the callback can determine which stub called it. + // The compilation callback is responsible for popping this prior + // to returning. + JCE.emitWordLE(0xe92d4000); // push {lr} + // Set the return address to go back to the start of this stub. + JCE.emitWordLE(0xe24fe00c); // sub lr, pc, #12 + // Invoke the compilation callback. + JCE.emitWordLE(0xe51ff004); // ldr pc, [pc, #-4] + // The address of the compilation callback. + JCE.emitWordLE((intptr_t)ARMCompilationCallback); + sys::Memory::InvalidateInstructionCache(Addr, 16); + if (!sys::Memory::setRangeExecutable(Addr, 16)) { + llvm_unreachable("ERROR: Unable to mark stub executable"); + } + } + + return Addr; +} + +intptr_t ARMJITInfo::resolveRelocDestAddr(MachineRelocation *MR) const { + ARM::RelocationType RT = (ARM::RelocationType)MR->getRelocationType(); + switch (RT) { + default: + return (intptr_t)(MR->getResultPointer()); + case ARM::reloc_arm_pic_jt: + // Destination address - jump table base. + return (intptr_t)(MR->getResultPointer()) - MR->getConstantVal(); + case ARM::reloc_arm_jt_base: + // Jump table base address. + return getJumpTableBaseAddr(MR->getJumpTableIndex()); + case ARM::reloc_arm_cp_entry: + case ARM::reloc_arm_vfp_cp_entry: + // Constant pool entry address. + return getConstantPoolEntryAddr(MR->getConstantPoolIndex()); + case ARM::reloc_arm_machine_cp_entry: { + ARMConstantPoolValue *ACPV = (ARMConstantPoolValue*)MR->getConstantVal(); + assert((!ACPV->hasModifier() && !ACPV->mustAddCurrentAddress()) && + "Can't handle this machine constant pool entry yet!"); + intptr_t Addr = (intptr_t)(MR->getResultPointer()); + Addr -= getPCLabelAddr(ACPV->getLabelId()) + ACPV->getPCAdjustment(); + return Addr; + } + } +} + +/// relocate - Before the JIT can run a block of code that has been emitted, +/// it must rewrite the code to contain the actual addresses of any +/// referenced global symbols. +void ARMJITInfo::relocate(void *Function, MachineRelocation *MR, + unsigned NumRelocs, unsigned char* GOTBase) { + for (unsigned i = 0; i != NumRelocs; ++i, ++MR) { + void *RelocPos = (char*)Function + MR->getMachineCodeOffset(); + intptr_t ResultPtr = resolveRelocDestAddr(MR); + switch ((ARM::RelocationType)MR->getRelocationType()) { + case ARM::reloc_arm_cp_entry: + case ARM::reloc_arm_vfp_cp_entry: + case ARM::reloc_arm_relative: { + // It is necessary to calculate the correct PC relative value. We + // subtract the base addr from the target addr to form a byte offset. + ResultPtr = ResultPtr - (intptr_t)RelocPos - 8; + // If the result is positive, set bit U(23) to 1. + if (ResultPtr >= 0) + *((intptr_t*)RelocPos) |= 1 << ARMII::U_BitShift; + else { + // Otherwise, obtain the absolute value and set bit U(23) to 0. + *((intptr_t*)RelocPos) &= ~(1 << ARMII::U_BitShift); + ResultPtr = - ResultPtr; + } + // Set the immed value calculated. + // VFP immediate offset is multiplied by 4. + if (MR->getRelocationType() == ARM::reloc_arm_vfp_cp_entry) + ResultPtr = ResultPtr >> 2; + *((intptr_t*)RelocPos) |= ResultPtr; + // Set register Rn to PC. + *((intptr_t*)RelocPos) |= + ARMRegisterInfo::getRegisterNumbering(ARM::PC) << ARMII::RegRnShift; + break; + } + case ARM::reloc_arm_pic_jt: + case ARM::reloc_arm_machine_cp_entry: + case ARM::reloc_arm_absolute: { + // These addresses have already been resolved. + *((intptr_t*)RelocPos) |= (intptr_t)ResultPtr; + break; + } + case ARM::reloc_arm_branch: { + // It is necessary to calculate the correct value of signed_immed_24 + // field. We subtract the base addr from the target addr to form a + // byte offset, which must be inside the range -33554432 and +33554428. + // Then, we set the signed_immed_24 field of the instruction to bits + // [25:2] of the byte offset. More details ARM-ARM p. A4-11. + ResultPtr = ResultPtr - (intptr_t)RelocPos - 8; + ResultPtr = (ResultPtr & 0x03FFFFFC) >> 2; + assert(ResultPtr >= -33554432 && ResultPtr <= 33554428); + *((intptr_t*)RelocPos) |= ResultPtr; + break; + } + case ARM::reloc_arm_jt_base: { + // JT base - (instruction addr + 8) + ResultPtr = ResultPtr - (intptr_t)RelocPos - 8; + *((intptr_t*)RelocPos) |= ResultPtr; + break; + } + } + } +} diff --git a/libclamav/c++/llvm/lib/Target/ARM/ARMJITInfo.h b/libclamav/c++/llvm/lib/Target/ARM/ARMJITInfo.h new file mode 100644 index 000000000..ff332b7ee --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/ARM/ARMJITInfo.h @@ -0,0 +1,182 @@ +//===- ARMJITInfo.h - ARM implementation of the JIT interface --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the declaration of the ARMJITInfo class. +// +//===----------------------------------------------------------------------===// + +#ifndef ARMJITINFO_H +#define ARMJITINFO_H + +#include "ARMMachineFunctionInfo.h" +#include "llvm/CodeGen/MachineConstantPool.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineJumpTableInfo.h" +#include "llvm/Target/TargetJITInfo.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallVector.h" + +namespace llvm { + class ARMTargetMachine; + + class ARMJITInfo : public TargetJITInfo { + // ConstPoolId2AddrMap - A map from constant pool ids to the corresponding + // CONSTPOOL_ENTRY addresses. + SmallVector ConstPoolId2AddrMap; + + // JumpTableId2AddrMap - A map from inline jumptable ids to the + // corresponding inline jump table bases. + SmallVector JumpTableId2AddrMap; + + // PCLabelMap - A map from PC labels to addresses. + DenseMap PCLabelMap; + + // Sym2IndirectSymMap - A map from symbol (GlobalValue and ExternalSymbol) + // addresses to their indirect symbol addresses. + DenseMap Sym2IndirectSymMap; + + // IsPIC - True if the relocation model is PIC. This is used to determine + // how to codegen function stubs. + bool IsPIC; + + public: + explicit ARMJITInfo() : IsPIC(false) { useGOT = false; } + + /// replaceMachineCodeForFunction - Make it so that calling the function + /// whose machine code is at OLD turns into a call to NEW, perhaps by + /// overwriting OLD with a branch to NEW. This is used for self-modifying + /// code. + /// + virtual void replaceMachineCodeForFunction(void *Old, void *New); + + /// emitGlobalValueIndirectSym - Use the specified JITCodeEmitter object + /// to emit an indirect symbol which contains the address of the specified + /// ptr. + virtual void *emitGlobalValueIndirectSym(const GlobalValue* GV, void *ptr, + JITCodeEmitter &JCE); + + // getStubLayout - Returns the size and alignment of the largest call stub + // on ARM. + virtual StubLayout getStubLayout(); + + /// emitFunctionStub - Use the specified JITCodeEmitter object to emit a + /// small native function that simply calls the function at the specified + /// address. + virtual void *emitFunctionStub(const Function* F, void *Fn, + JITCodeEmitter &JCE); + + /// getLazyResolverFunction - Expose the lazy resolver to the JIT. + virtual LazyResolverFn getLazyResolverFunction(JITCompilerFn); + + /// relocate - Before the JIT can run a block of code that has been emitted, + /// it must rewrite the code to contain the actual addresses of any + /// referenced global symbols. + virtual void relocate(void *Function, MachineRelocation *MR, + unsigned NumRelocs, unsigned char* GOTBase); + + /// hasCustomConstantPool - Allows a target to specify that constant + /// pool address resolution is handled by the target. + virtual bool hasCustomConstantPool() const { return true; } + + /// hasCustomJumpTables - Allows a target to specify that jumptables + /// are emitted by the target. + virtual bool hasCustomJumpTables() const { return true; } + + /// allocateSeparateGVMemory - If true, globals should be placed in + /// separately allocated heap memory rather than in the same + /// code memory allocated by JITCodeEmitter. + virtual bool allocateSeparateGVMemory() const { +#ifdef __APPLE__ + return true; +#else + return false; +#endif + } + + /// Initialize - Initialize internal stage for the function being JITted. + /// Resize constant pool ids to CONSTPOOL_ENTRY addresses map; resize + /// jump table ids to jump table bases map; remember if codegen relocation + /// model is PIC. + void Initialize(const MachineFunction &MF, bool isPIC) { + const ARMFunctionInfo *AFI = MF.getInfo(); + ConstPoolId2AddrMap.resize(AFI->getNumConstPoolEntries()); + JumpTableId2AddrMap.resize(AFI->getNumJumpTables()); + IsPIC = isPIC; + } + + /// getConstantPoolEntryAddr - The ARM target puts all constant + /// pool entries into constant islands. This returns the address of the + /// constant pool entry of the specified index. + intptr_t getConstantPoolEntryAddr(unsigned CPI) const { + assert(CPI < ConstPoolId2AddrMap.size()); + return ConstPoolId2AddrMap[CPI]; + } + + /// addConstantPoolEntryAddr - Map a Constant Pool Index to the address + /// where its associated value is stored. When relocations are processed, + /// this value will be used to resolve references to the constant. + void addConstantPoolEntryAddr(unsigned CPI, intptr_t Addr) { + assert(CPI < ConstPoolId2AddrMap.size()); + ConstPoolId2AddrMap[CPI] = Addr; + } + + /// getJumpTableBaseAddr - The ARM target inline all jump tables within + /// text section of the function. This returns the address of the base of + /// the jump table of the specified index. + intptr_t getJumpTableBaseAddr(unsigned JTI) const { + assert(JTI < JumpTableId2AddrMap.size()); + return JumpTableId2AddrMap[JTI]; + } + + /// addJumpTableBaseAddr - Map a jump table index to the address where + /// the corresponding inline jump table is emitted. When relocations are + /// processed, this value will be used to resolve references to the + /// jump table. + void addJumpTableBaseAddr(unsigned JTI, intptr_t Addr) { + assert(JTI < JumpTableId2AddrMap.size()); + JumpTableId2AddrMap[JTI] = Addr; + } + + /// getPCLabelAddr - Retrieve the address of the PC label of the specified id. + intptr_t getPCLabelAddr(unsigned Id) const { + DenseMap::const_iterator I = PCLabelMap.find(Id); + assert(I != PCLabelMap.end()); + return I->second; + } + + /// addPCLabelAddr - Remember the address of the specified PC label. + void addPCLabelAddr(unsigned Id, intptr_t Addr) { + PCLabelMap.insert(std::make_pair(Id, Addr)); + } + + /// getIndirectSymAddr - Retrieve the address of the indirect symbol of the + /// specified symbol located at address. Returns 0 if the indirect symbol + /// has not been emitted. + intptr_t getIndirectSymAddr(void *Addr) const { + DenseMap::const_iterator I= Sym2IndirectSymMap.find(Addr); + if (I != Sym2IndirectSymMap.end()) + return I->second; + return 0; + } + + /// addIndirectSymAddr - Add a mapping from address of an emitted symbol to + /// its indirect symbol address. + void addIndirectSymAddr(void *SymAddr, intptr_t IndSymAddr) { + Sym2IndirectSymMap.insert(std::make_pair(SymAddr, IndSymAddr)); + } + + private: + /// resolveRelocDestAddr - Resolve the resulting address of the relocation + /// if it's not already solved. Constantpool entries must be resolved by + /// ARM target. + intptr_t resolveRelocDestAddr(MachineRelocation *MR) const; + }; +} + +#endif diff --git a/libclamav/c++/llvm/lib/Target/ARM/ARMLoadStoreOptimizer.cpp b/libclamav/c++/llvm/lib/Target/ARM/ARMLoadStoreOptimizer.cpp new file mode 100644 index 000000000..304d0ef66 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/ARM/ARMLoadStoreOptimizer.cpp @@ -0,0 +1,1551 @@ +//===-- ARMLoadStoreOptimizer.cpp - ARM load / store opt. pass ----*- C++ -*-=// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains a pass that performs load / store related peephole +// optimizations. This pass should be run after register allocation. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "arm-ldst-opt" +#include "ARM.h" +#include "ARMAddressingModes.h" +#include "ARMBaseInstrInfo.h" +#include "ARMMachineFunctionInfo.h" +#include "ARMRegisterInfo.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Function.h" +#include "llvm/CodeGen/MachineBasicBlock.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/RegisterScavenging.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallSet.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/Statistic.h" +using namespace llvm; + +STATISTIC(NumLDMGened , "Number of ldm instructions generated"); +STATISTIC(NumSTMGened , "Number of stm instructions generated"); +STATISTIC(NumVLDMGened, "Number of vldm instructions generated"); +STATISTIC(NumVSTMGened, "Number of vstm instructions generated"); +STATISTIC(NumLdStMoved, "Number of load / store instructions moved"); +STATISTIC(NumLDRDFormed,"Number of ldrd created before allocation"); +STATISTIC(NumSTRDFormed,"Number of strd created before allocation"); +STATISTIC(NumLDRD2LDM, "Number of ldrd instructions turned back into ldm"); +STATISTIC(NumSTRD2STM, "Number of strd instructions turned back into stm"); +STATISTIC(NumLDRD2LDR, "Number of ldrd instructions turned back into ldr's"); +STATISTIC(NumSTRD2STR, "Number of strd instructions turned back into str's"); + +/// ARMAllocLoadStoreOpt - Post- register allocation pass the combine +/// load / store instructions to form ldm / stm instructions. + +namespace { + struct ARMLoadStoreOpt : public MachineFunctionPass { + static char ID; + ARMLoadStoreOpt() : MachineFunctionPass(&ID) {} + + const TargetInstrInfo *TII; + const TargetRegisterInfo *TRI; + ARMFunctionInfo *AFI; + RegScavenger *RS; + bool isThumb2; + + virtual bool runOnMachineFunction(MachineFunction &Fn); + + virtual const char *getPassName() const { + return "ARM load / store optimization pass"; + } + + private: + struct MemOpQueueEntry { + int Offset; + unsigned Position; + MachineBasicBlock::iterator MBBI; + bool Merged; + MemOpQueueEntry(int o, int p, MachineBasicBlock::iterator i) + : Offset(o), Position(p), MBBI(i), Merged(false) {}; + }; + typedef SmallVector MemOpQueue; + typedef MemOpQueue::iterator MemOpQueueIter; + + bool MergeOps(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, + int Offset, unsigned Base, bool BaseKill, int Opcode, + ARMCC::CondCodes Pred, unsigned PredReg, unsigned Scratch, + DebugLoc dl, SmallVector, 8> &Regs); + void MergeLDR_STR(MachineBasicBlock &MBB, unsigned SIndex, unsigned Base, + int Opcode, unsigned Size, + ARMCC::CondCodes Pred, unsigned PredReg, + unsigned Scratch, MemOpQueue &MemOps, + SmallVector &Merges); + + void AdvanceRS(MachineBasicBlock &MBB, MemOpQueue &MemOps); + bool FixInvalidRegPairOp(MachineBasicBlock &MBB, + MachineBasicBlock::iterator &MBBI); + bool MergeBaseUpdateLoadStore(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MBBI, + const TargetInstrInfo *TII, + bool &Advance, + MachineBasicBlock::iterator &I); + bool MergeBaseUpdateLSMultiple(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MBBI, + bool &Advance, + MachineBasicBlock::iterator &I); + bool LoadStoreMultipleOpti(MachineBasicBlock &MBB); + bool MergeReturnIntoLDM(MachineBasicBlock &MBB); + }; + char ARMLoadStoreOpt::ID = 0; +} + +static int getLoadStoreMultipleOpcode(int Opcode) { + switch (Opcode) { + case ARM::LDR: + NumLDMGened++; + return ARM::LDM; + case ARM::STR: + NumSTMGened++; + return ARM::STM; + case ARM::t2LDRi8: + case ARM::t2LDRi12: + NumLDMGened++; + return ARM::t2LDM; + case ARM::t2STRi8: + case ARM::t2STRi12: + NumSTMGened++; + return ARM::t2STM; + case ARM::VLDRS: + NumVLDMGened++; + return ARM::VLDMS; + case ARM::VSTRS: + NumVSTMGened++; + return ARM::VSTMS; + case ARM::VLDRD: + NumVLDMGened++; + return ARM::VLDMD; + case ARM::VSTRD: + NumVSTMGened++; + return ARM::VSTMD; + default: llvm_unreachable("Unhandled opcode!"); + } + return 0; +} + +static bool isT2i32Load(unsigned Opc) { + return Opc == ARM::t2LDRi12 || Opc == ARM::t2LDRi8; +} + +static bool isi32Load(unsigned Opc) { + return Opc == ARM::LDR || isT2i32Load(Opc); +} + +static bool isT2i32Store(unsigned Opc) { + return Opc == ARM::t2STRi12 || Opc == ARM::t2STRi8; +} + +static bool isi32Store(unsigned Opc) { + return Opc == ARM::STR || isT2i32Store(Opc); +} + +/// MergeOps - Create and insert a LDM or STM with Base as base register and +/// registers in Regs as the register operands that would be loaded / stored. +/// It returns true if the transformation is done. +bool +ARMLoadStoreOpt::MergeOps(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MBBI, + int Offset, unsigned Base, bool BaseKill, + int Opcode, ARMCC::CondCodes Pred, + unsigned PredReg, unsigned Scratch, DebugLoc dl, + SmallVector, 8> &Regs) { + // Only a single register to load / store. Don't bother. + unsigned NumRegs = Regs.size(); + if (NumRegs <= 1) + return false; + + ARM_AM::AMSubMode Mode = ARM_AM::ia; + bool isAM4 = isi32Load(Opcode) || isi32Store(Opcode); + if (isAM4 && Offset == 4) { + if (isThumb2) + // Thumb2 does not support ldmib / stmib. + return false; + Mode = ARM_AM::ib; + } else if (isAM4 && Offset == -4 * (int)NumRegs + 4) { + if (isThumb2) + // Thumb2 does not support ldmda / stmda. + return false; + Mode = ARM_AM::da; + } else if (isAM4 && Offset == -4 * (int)NumRegs) { + Mode = ARM_AM::db; + } else if (Offset != 0) { + // If starting offset isn't zero, insert a MI to materialize a new base. + // But only do so if it is cost effective, i.e. merging more than two + // loads / stores. + if (NumRegs <= 2) + return false; + + unsigned NewBase; + if (isi32Load(Opcode)) + // If it is a load, then just use one of the destination register to + // use as the new base. + NewBase = Regs[NumRegs-1].first; + else { + // Use the scratch register to use as a new base. + NewBase = Scratch; + if (NewBase == 0) + return false; + } + int BaseOpc = !isThumb2 + ? ARM::ADDri + : ((Base == ARM::SP) ? ARM::t2ADDrSPi : ARM::t2ADDri); + if (Offset < 0) { + BaseOpc = !isThumb2 + ? ARM::SUBri + : ((Base == ARM::SP) ? ARM::t2SUBrSPi : ARM::t2SUBri); + Offset = - Offset; + } + int ImmedOffset = isThumb2 + ? ARM_AM::getT2SOImmVal(Offset) : ARM_AM::getSOImmVal(Offset); + if (ImmedOffset == -1) + // FIXME: Try t2ADDri12 or t2SUBri12? + return false; // Probably not worth it then. + + BuildMI(MBB, MBBI, dl, TII->get(BaseOpc), NewBase) + .addReg(Base, getKillRegState(BaseKill)).addImm(Offset) + .addImm(Pred).addReg(PredReg).addReg(0); + Base = NewBase; + BaseKill = true; // New base is always killed right its use. + } + + bool isDPR = Opcode == ARM::VLDRD || Opcode == ARM::VSTRD; + bool isDef = isi32Load(Opcode) || Opcode == ARM::VLDRS || Opcode == ARM::VLDRD; + Opcode = getLoadStoreMultipleOpcode(Opcode); + MachineInstrBuilder MIB = (isAM4) + ? BuildMI(MBB, MBBI, dl, TII->get(Opcode)) + .addReg(Base, getKillRegState(BaseKill)) + .addImm(ARM_AM::getAM4ModeImm(Mode)).addImm(Pred).addReg(PredReg) + : BuildMI(MBB, MBBI, dl, TII->get(Opcode)) + .addReg(Base, getKillRegState(BaseKill)) + .addImm(ARM_AM::getAM5Opc(Mode, false, isDPR ? NumRegs<<1 : NumRegs)) + .addImm(Pred).addReg(PredReg); + MIB.addReg(0); // Add optional writeback (0 for now). + for (unsigned i = 0; i != NumRegs; ++i) + MIB = MIB.addReg(Regs[i].first, getDefRegState(isDef) + | getKillRegState(Regs[i].second)); + + return true; +} + +/// MergeLDR_STR - Merge a number of load / store instructions into one or more +/// load / store multiple instructions. +void +ARMLoadStoreOpt::MergeLDR_STR(MachineBasicBlock &MBB, unsigned SIndex, + unsigned Base, int Opcode, unsigned Size, + ARMCC::CondCodes Pred, unsigned PredReg, + unsigned Scratch, MemOpQueue &MemOps, + SmallVector &Merges) { + bool isAM4 = isi32Load(Opcode) || isi32Store(Opcode); + int Offset = MemOps[SIndex].Offset; + int SOffset = Offset; + unsigned Pos = MemOps[SIndex].Position; + MachineBasicBlock::iterator Loc = MemOps[SIndex].MBBI; + DebugLoc dl = Loc->getDebugLoc(); + unsigned PReg = Loc->getOperand(0).getReg(); + unsigned PRegNum = ARMRegisterInfo::getRegisterNumbering(PReg); + bool isKill = Loc->getOperand(0).isKill(); + + SmallVector, 8> Regs; + Regs.push_back(std::make_pair(PReg, isKill)); + for (unsigned i = SIndex+1, e = MemOps.size(); i != e; ++i) { + int NewOffset = MemOps[i].Offset; + unsigned Reg = MemOps[i].MBBI->getOperand(0).getReg(); + unsigned RegNum = ARMRegisterInfo::getRegisterNumbering(Reg); + isKill = MemOps[i].MBBI->getOperand(0).isKill(); + // AM4 - register numbers in ascending order. + // AM5 - consecutive register numbers in ascending order. + if (NewOffset == Offset + (int)Size && + ((isAM4 && RegNum > PRegNum) || RegNum == PRegNum+1)) { + Offset += Size; + Regs.push_back(std::make_pair(Reg, isKill)); + PRegNum = RegNum; + } else { + // Can't merge this in. Try merge the earlier ones first. + if (MergeOps(MBB, ++Loc, SOffset, Base, false, Opcode, Pred, PredReg, + Scratch, dl, Regs)) { + Merges.push_back(prior(Loc)); + for (unsigned j = SIndex; j < i; ++j) { + MBB.erase(MemOps[j].MBBI); + MemOps[j].Merged = true; + } + } + MergeLDR_STR(MBB, i, Base, Opcode, Size, Pred, PredReg, Scratch, + MemOps, Merges); + return; + } + + if (MemOps[i].Position > Pos) { + Pos = MemOps[i].Position; + Loc = MemOps[i].MBBI; + } + } + + bool BaseKill = Loc->findRegisterUseOperandIdx(Base, true) != -1; + if (MergeOps(MBB, ++Loc, SOffset, Base, BaseKill, Opcode, Pred, PredReg, + Scratch, dl, Regs)) { + Merges.push_back(prior(Loc)); + for (unsigned i = SIndex, e = MemOps.size(); i != e; ++i) { + MBB.erase(MemOps[i].MBBI); + MemOps[i].Merged = true; + } + } + + return; +} + +static inline bool isMatchingDecrement(MachineInstr *MI, unsigned Base, + unsigned Bytes, unsigned Limit, + ARMCC::CondCodes Pred, unsigned PredReg){ + unsigned MyPredReg = 0; + if (!MI) + return false; + if (MI->getOpcode() != ARM::t2SUBri && + MI->getOpcode() != ARM::t2SUBrSPi && + MI->getOpcode() != ARM::t2SUBrSPi12 && + MI->getOpcode() != ARM::tSUBspi && + MI->getOpcode() != ARM::SUBri) + return false; + + // Make sure the offset fits in 8 bits. + if (Bytes <= 0 || (Limit && Bytes >= Limit)) + return false; + + unsigned Scale = (MI->getOpcode() == ARM::tSUBspi) ? 4 : 1; // FIXME + return (MI->getOperand(0).getReg() == Base && + MI->getOperand(1).getReg() == Base && + (MI->getOperand(2).getImm()*Scale) == Bytes && + llvm::getInstrPredicate(MI, MyPredReg) == Pred && + MyPredReg == PredReg); +} + +static inline bool isMatchingIncrement(MachineInstr *MI, unsigned Base, + unsigned Bytes, unsigned Limit, + ARMCC::CondCodes Pred, unsigned PredReg){ + unsigned MyPredReg = 0; + if (!MI) + return false; + if (MI->getOpcode() != ARM::t2ADDri && + MI->getOpcode() != ARM::t2ADDrSPi && + MI->getOpcode() != ARM::t2ADDrSPi12 && + MI->getOpcode() != ARM::tADDspi && + MI->getOpcode() != ARM::ADDri) + return false; + + if (Bytes <= 0 || (Limit && Bytes >= Limit)) + // Make sure the offset fits in 8 bits. + return false; + + unsigned Scale = (MI->getOpcode() == ARM::tADDspi) ? 4 : 1; // FIXME + return (MI->getOperand(0).getReg() == Base && + MI->getOperand(1).getReg() == Base && + (MI->getOperand(2).getImm()*Scale) == Bytes && + llvm::getInstrPredicate(MI, MyPredReg) == Pred && + MyPredReg == PredReg); +} + +static inline unsigned getLSMultipleTransferSize(MachineInstr *MI) { + switch (MI->getOpcode()) { + default: return 0; + case ARM::LDR: + case ARM::STR: + case ARM::t2LDRi8: + case ARM::t2LDRi12: + case ARM::t2STRi8: + case ARM::t2STRi12: + case ARM::VLDRS: + case ARM::VSTRS: + return 4; + case ARM::VLDRD: + case ARM::VSTRD: + return 8; + case ARM::LDM: + case ARM::STM: + case ARM::t2LDM: + case ARM::t2STM: + return (MI->getNumOperands() - 5) * 4; + case ARM::VLDMS: + case ARM::VSTMS: + case ARM::VLDMD: + case ARM::VSTMD: + return ARM_AM::getAM5Offset(MI->getOperand(1).getImm()) * 4; + } +} + +/// MergeBaseUpdateLSMultiple - Fold proceeding/trailing inc/dec of base +/// register into the LDM/STM/VLDM{D|S}/VSTM{D|S} op when possible: +/// +/// stmia rn, +/// rn := rn + 4 * 3; +/// => +/// stmia rn!, +/// +/// rn := rn - 4 * 3; +/// ldmia rn, +/// => +/// ldmdb rn!, +bool ARMLoadStoreOpt::MergeBaseUpdateLSMultiple(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MBBI, + bool &Advance, + MachineBasicBlock::iterator &I) { + MachineInstr *MI = MBBI; + unsigned Base = MI->getOperand(0).getReg(); + unsigned Bytes = getLSMultipleTransferSize(MI); + unsigned PredReg = 0; + ARMCC::CondCodes Pred = llvm::getInstrPredicate(MI, PredReg); + int Opcode = MI->getOpcode(); + bool isAM4 = Opcode == ARM::LDM || Opcode == ARM::t2LDM || + Opcode == ARM::STM || Opcode == ARM::t2STM; + + if (isAM4) { + if (ARM_AM::getAM4WBFlag(MI->getOperand(1).getImm())) + return false; + + // Can't use the updating AM4 sub-mode if the base register is also a dest + // register. e.g. ldmdb r0!, {r0, r1, r2}. The behavior is undefined. + for (unsigned i = 3, e = MI->getNumOperands(); i != e; ++i) { + if (MI->getOperand(i).getReg() == Base) + return false; + } + + ARM_AM::AMSubMode Mode = ARM_AM::getAM4SubMode(MI->getOperand(1).getImm()); + if (MBBI != MBB.begin()) { + MachineBasicBlock::iterator PrevMBBI = prior(MBBI); + if (Mode == ARM_AM::ia && + isMatchingDecrement(PrevMBBI, Base, Bytes, 0, Pred, PredReg)) { + MI->getOperand(1).setImm(ARM_AM::getAM4ModeImm(ARM_AM::db, true)); + MI->getOperand(4).setReg(Base); + MI->getOperand(4).setIsDef(); + MBB.erase(PrevMBBI); + return true; + } else if (Mode == ARM_AM::ib && + isMatchingDecrement(PrevMBBI, Base, Bytes, 0, Pred, PredReg)) { + MI->getOperand(1).setImm(ARM_AM::getAM4ModeImm(ARM_AM::da, true)); + MI->getOperand(4).setReg(Base); // WB to base + MI->getOperand(4).setIsDef(); + MBB.erase(PrevMBBI); + return true; + } + } + + if (MBBI != MBB.end()) { + MachineBasicBlock::iterator NextMBBI = next(MBBI); + if ((Mode == ARM_AM::ia || Mode == ARM_AM::ib) && + isMatchingIncrement(NextMBBI, Base, Bytes, 0, Pred, PredReg)) { + MI->getOperand(1).setImm(ARM_AM::getAM4ModeImm(Mode, true)); + MI->getOperand(4).setReg(Base); // WB to base + MI->getOperand(4).setIsDef(); + if (NextMBBI == I) { + Advance = true; + ++I; + } + MBB.erase(NextMBBI); + return true; + } else if ((Mode == ARM_AM::da || Mode == ARM_AM::db) && + isMatchingDecrement(NextMBBI, Base, Bytes, 0, Pred, PredReg)) { + MI->getOperand(1).setImm(ARM_AM::getAM4ModeImm(Mode, true)); + MI->getOperand(4).setReg(Base); // WB to base + MI->getOperand(4).setIsDef(); + if (NextMBBI == I) { + Advance = true; + ++I; + } + MBB.erase(NextMBBI); + return true; + } + } + } else { + // VLDM{D|S}, VSTM{D|S} addressing mode 5 ops. + if (ARM_AM::getAM5WBFlag(MI->getOperand(1).getImm())) + return false; + + ARM_AM::AMSubMode Mode = ARM_AM::getAM5SubMode(MI->getOperand(1).getImm()); + unsigned Offset = ARM_AM::getAM5Offset(MI->getOperand(1).getImm()); + if (MBBI != MBB.begin()) { + MachineBasicBlock::iterator PrevMBBI = prior(MBBI); + if (Mode == ARM_AM::ia && + isMatchingDecrement(PrevMBBI, Base, Bytes, 0, Pred, PredReg)) { + MI->getOperand(1).setImm(ARM_AM::getAM5Opc(ARM_AM::db, true, Offset)); + MI->getOperand(4).setReg(Base); // WB to base + MI->getOperand(4).setIsDef(); + MBB.erase(PrevMBBI); + return true; + } + } + + if (MBBI != MBB.end()) { + MachineBasicBlock::iterator NextMBBI = next(MBBI); + if (Mode == ARM_AM::ia && + isMatchingIncrement(NextMBBI, Base, Bytes, 0, Pred, PredReg)) { + MI->getOperand(1).setImm(ARM_AM::getAM5Opc(ARM_AM::ia, true, Offset)); + MI->getOperand(4).setReg(Base); // WB to base + MI->getOperand(4).setIsDef(); + if (NextMBBI == I) { + Advance = true; + ++I; + } + MBB.erase(NextMBBI); + } + return true; + } + } + + return false; +} + +static unsigned getPreIndexedLoadStoreOpcode(unsigned Opc) { + switch (Opc) { + case ARM::LDR: return ARM::LDR_PRE; + case ARM::STR: return ARM::STR_PRE; + case ARM::VLDRS: return ARM::VLDMS; + case ARM::VLDRD: return ARM::VLDMD; + case ARM::VSTRS: return ARM::VSTMS; + case ARM::VSTRD: return ARM::VSTMD; + case ARM::t2LDRi8: + case ARM::t2LDRi12: + return ARM::t2LDR_PRE; + case ARM::t2STRi8: + case ARM::t2STRi12: + return ARM::t2STR_PRE; + default: llvm_unreachable("Unhandled opcode!"); + } + return 0; +} + +static unsigned getPostIndexedLoadStoreOpcode(unsigned Opc) { + switch (Opc) { + case ARM::LDR: return ARM::LDR_POST; + case ARM::STR: return ARM::STR_POST; + case ARM::VLDRS: return ARM::VLDMS; + case ARM::VLDRD: return ARM::VLDMD; + case ARM::VSTRS: return ARM::VSTMS; + case ARM::VSTRD: return ARM::VSTMD; + case ARM::t2LDRi8: + case ARM::t2LDRi12: + return ARM::t2LDR_POST; + case ARM::t2STRi8: + case ARM::t2STRi12: + return ARM::t2STR_POST; + default: llvm_unreachable("Unhandled opcode!"); + } + return 0; +} + +/// MergeBaseUpdateLoadStore - Fold proceeding/trailing inc/dec of base +/// register into the LDR/STR/FLD{D|S}/FST{D|S} op when possible: +bool ARMLoadStoreOpt::MergeBaseUpdateLoadStore(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MBBI, + const TargetInstrInfo *TII, + bool &Advance, + MachineBasicBlock::iterator &I) { + MachineInstr *MI = MBBI; + unsigned Base = MI->getOperand(1).getReg(); + bool BaseKill = MI->getOperand(1).isKill(); + unsigned Bytes = getLSMultipleTransferSize(MI); + int Opcode = MI->getOpcode(); + DebugLoc dl = MI->getDebugLoc(); + bool isAM5 = Opcode == ARM::VLDRD || Opcode == ARM::VLDRS || + Opcode == ARM::VSTRD || Opcode == ARM::VSTRS; + bool isAM2 = Opcode == ARM::LDR || Opcode == ARM::STR; + if (isAM2 && ARM_AM::getAM2Offset(MI->getOperand(3).getImm()) != 0) + return false; + else if (isAM5 && ARM_AM::getAM5Offset(MI->getOperand(2).getImm()) != 0) + return false; + else if (isT2i32Load(Opcode) || isT2i32Store(Opcode)) + if (MI->getOperand(2).getImm() != 0) + return false; + + bool isLd = isi32Load(Opcode) || Opcode == ARM::VLDRS || Opcode == ARM::VLDRD; + // Can't do the merge if the destination register is the same as the would-be + // writeback register. + if (isLd && MI->getOperand(0).getReg() == Base) + return false; + + unsigned PredReg = 0; + ARMCC::CondCodes Pred = llvm::getInstrPredicate(MI, PredReg); + bool DoMerge = false; + ARM_AM::AddrOpc AddSub = ARM_AM::add; + unsigned NewOpc = 0; + // AM2 - 12 bits, thumb2 - 8 bits. + unsigned Limit = isAM5 ? 0 : (isAM2 ? 0x1000 : 0x100); + if (MBBI != MBB.begin()) { + MachineBasicBlock::iterator PrevMBBI = prior(MBBI); + if (isMatchingDecrement(PrevMBBI, Base, Bytes, Limit, Pred, PredReg)) { + DoMerge = true; + AddSub = ARM_AM::sub; + NewOpc = getPreIndexedLoadStoreOpcode(Opcode); + } else if (!isAM5 && + isMatchingIncrement(PrevMBBI, Base, Bytes, Limit,Pred,PredReg)) { + DoMerge = true; + NewOpc = getPreIndexedLoadStoreOpcode(Opcode); + } + if (DoMerge) + MBB.erase(PrevMBBI); + } + + if (!DoMerge && MBBI != MBB.end()) { + MachineBasicBlock::iterator NextMBBI = next(MBBI); + if (!isAM5 && + isMatchingDecrement(NextMBBI, Base, Bytes, Limit, Pred, PredReg)) { + DoMerge = true; + AddSub = ARM_AM::sub; + NewOpc = getPostIndexedLoadStoreOpcode(Opcode); + } else if (isMatchingIncrement(NextMBBI, Base, Bytes, Limit,Pred,PredReg)) { + DoMerge = true; + NewOpc = getPostIndexedLoadStoreOpcode(Opcode); + } + if (DoMerge) { + if (NextMBBI == I) { + Advance = true; + ++I; + } + MBB.erase(NextMBBI); + } + } + + if (!DoMerge) + return false; + + bool isDPR = NewOpc == ARM::VLDMD || NewOpc == ARM::VSTMD; + unsigned Offset = 0; + if (isAM5) + Offset = ARM_AM::getAM5Opc((AddSub == ARM_AM::sub) + ? ARM_AM::db + : ARM_AM::ia, true, (isDPR ? 2 : 1)); + else if (isAM2) + Offset = ARM_AM::getAM2Opc(AddSub, Bytes, ARM_AM::no_shift); + else + Offset = AddSub == ARM_AM::sub ? -Bytes : Bytes; + if (isLd) { + if (isAM5) + // VLDMS, VLDMD + BuildMI(MBB, MBBI, dl, TII->get(NewOpc)) + .addReg(Base, getKillRegState(BaseKill)) + .addImm(Offset).addImm(Pred).addReg(PredReg) + .addReg(Base, getDefRegState(true)) // WB base register + .addReg(MI->getOperand(0).getReg(), RegState::Define); + else if (isAM2) + // LDR_PRE, LDR_POST, + BuildMI(MBB, MBBI, dl, TII->get(NewOpc), MI->getOperand(0).getReg()) + .addReg(Base, RegState::Define) + .addReg(Base).addReg(0).addImm(Offset).addImm(Pred).addReg(PredReg); + else + // t2LDR_PRE, t2LDR_POST + BuildMI(MBB, MBBI, dl, TII->get(NewOpc), MI->getOperand(0).getReg()) + .addReg(Base, RegState::Define) + .addReg(Base).addImm(Offset).addImm(Pred).addReg(PredReg); + } else { + MachineOperand &MO = MI->getOperand(0); + if (isAM5) + // VSTMS, VSTMD + BuildMI(MBB, MBBI, dl, TII->get(NewOpc)).addReg(Base).addImm(Offset) + .addImm(Pred).addReg(PredReg) + .addReg(Base, getDefRegState(true)) // WB base register + .addReg(MO.getReg(), getKillRegState(MO.isKill())); + else if (isAM2) + // STR_PRE, STR_POST + BuildMI(MBB, MBBI, dl, TII->get(NewOpc), Base) + .addReg(MO.getReg(), getKillRegState(MO.isKill())) + .addReg(Base).addReg(0).addImm(Offset).addImm(Pred).addReg(PredReg); + else + // t2STR_PRE, t2STR_POST + BuildMI(MBB, MBBI, dl, TII->get(NewOpc), Base) + .addReg(MO.getReg(), getKillRegState(MO.isKill())) + .addReg(Base).addImm(Offset).addImm(Pred).addReg(PredReg); + } + MBB.erase(MBBI); + + return true; +} + +/// isMemoryOp - Returns true if instruction is a memory operations (that this +/// pass is capable of operating on). +static bool isMemoryOp(const MachineInstr *MI) { + int Opcode = MI->getOpcode(); + switch (Opcode) { + default: break; + case ARM::LDR: + case ARM::STR: + return MI->getOperand(1).isReg() && MI->getOperand(2).getReg() == 0; + case ARM::VLDRS: + case ARM::VSTRS: + return MI->getOperand(1).isReg(); + case ARM::VLDRD: + case ARM::VSTRD: + return MI->getOperand(1).isReg(); + case ARM::t2LDRi8: + case ARM::t2LDRi12: + case ARM::t2STRi8: + case ARM::t2STRi12: + return MI->getOperand(1).isReg(); + } + return false; +} + +/// AdvanceRS - Advance register scavenger to just before the earliest memory +/// op that is being merged. +void ARMLoadStoreOpt::AdvanceRS(MachineBasicBlock &MBB, MemOpQueue &MemOps) { + MachineBasicBlock::iterator Loc = MemOps[0].MBBI; + unsigned Position = MemOps[0].Position; + for (unsigned i = 1, e = MemOps.size(); i != e; ++i) { + if (MemOps[i].Position < Position) { + Position = MemOps[i].Position; + Loc = MemOps[i].MBBI; + } + } + + if (Loc != MBB.begin()) + RS->forward(prior(Loc)); +} + +static int getMemoryOpOffset(const MachineInstr *MI) { + int Opcode = MI->getOpcode(); + bool isAM2 = Opcode == ARM::LDR || Opcode == ARM::STR; + bool isAM3 = Opcode == ARM::LDRD || Opcode == ARM::STRD; + unsigned NumOperands = MI->getDesc().getNumOperands(); + unsigned OffField = MI->getOperand(NumOperands-3).getImm(); + + if (Opcode == ARM::t2LDRi12 || Opcode == ARM::t2LDRi8 || + Opcode == ARM::t2STRi12 || Opcode == ARM::t2STRi8 || + Opcode == ARM::t2LDRDi8 || Opcode == ARM::t2STRDi8) + return OffField; + + int Offset = isAM2 + ? ARM_AM::getAM2Offset(OffField) + : (isAM3 ? ARM_AM::getAM3Offset(OffField) + : ARM_AM::getAM5Offset(OffField) * 4); + if (isAM2) { + if (ARM_AM::getAM2Op(OffField) == ARM_AM::sub) + Offset = -Offset; + } else if (isAM3) { + if (ARM_AM::getAM3Op(OffField) == ARM_AM::sub) + Offset = -Offset; + } else { + if (ARM_AM::getAM5Op(OffField) == ARM_AM::sub) + Offset = -Offset; + } + return Offset; +} + +static void InsertLDR_STR(MachineBasicBlock &MBB, + MachineBasicBlock::iterator &MBBI, + int OffImm, bool isDef, + DebugLoc dl, unsigned NewOpc, + unsigned Reg, bool RegDeadKill, bool RegUndef, + unsigned BaseReg, bool BaseKill, bool BaseUndef, + unsigned OffReg, bool OffKill, bool OffUndef, + ARMCC::CondCodes Pred, unsigned PredReg, + const TargetInstrInfo *TII, bool isT2) { + int Offset = OffImm; + if (!isT2) { + if (OffImm < 0) + Offset = ARM_AM::getAM2Opc(ARM_AM::sub, -OffImm, ARM_AM::no_shift); + else + Offset = ARM_AM::getAM2Opc(ARM_AM::add, OffImm, ARM_AM::no_shift); + } + if (isDef) { + MachineInstrBuilder MIB = BuildMI(MBB, MBBI, MBBI->getDebugLoc(), + TII->get(NewOpc)) + .addReg(Reg, getDefRegState(true) | getDeadRegState(RegDeadKill)) + .addReg(BaseReg, getKillRegState(BaseKill)|getUndefRegState(BaseUndef)); + if (!isT2) + MIB.addReg(OffReg, getKillRegState(OffKill)|getUndefRegState(OffUndef)); + MIB.addImm(Offset).addImm(Pred).addReg(PredReg); + } else { + MachineInstrBuilder MIB = BuildMI(MBB, MBBI, MBBI->getDebugLoc(), + TII->get(NewOpc)) + .addReg(Reg, getKillRegState(RegDeadKill) | getUndefRegState(RegUndef)) + .addReg(BaseReg, getKillRegState(BaseKill)|getUndefRegState(BaseUndef)); + if (!isT2) + MIB.addReg(OffReg, getKillRegState(OffKill)|getUndefRegState(OffUndef)); + MIB.addImm(Offset).addImm(Pred).addReg(PredReg); + } +} + +bool ARMLoadStoreOpt::FixInvalidRegPairOp(MachineBasicBlock &MBB, + MachineBasicBlock::iterator &MBBI) { + MachineInstr *MI = &*MBBI; + unsigned Opcode = MI->getOpcode(); + if (Opcode == ARM::LDRD || Opcode == ARM::STRD || + Opcode == ARM::t2LDRDi8 || Opcode == ARM::t2STRDi8) { + unsigned EvenReg = MI->getOperand(0).getReg(); + unsigned OddReg = MI->getOperand(1).getReg(); + unsigned EvenRegNum = TRI->getDwarfRegNum(EvenReg, false); + unsigned OddRegNum = TRI->getDwarfRegNum(OddReg, false); + if ((EvenRegNum & 1) == 0 && (EvenRegNum + 1) == OddRegNum) + return false; + + bool isT2 = Opcode == ARM::t2LDRDi8 || Opcode == ARM::t2STRDi8; + bool isLd = Opcode == ARM::LDRD || Opcode == ARM::t2LDRDi8; + bool EvenDeadKill = isLd ? + MI->getOperand(0).isDead() : MI->getOperand(0).isKill(); + bool EvenUndef = MI->getOperand(0).isUndef(); + bool OddDeadKill = isLd ? + MI->getOperand(1).isDead() : MI->getOperand(1).isKill(); + bool OddUndef = MI->getOperand(1).isUndef(); + const MachineOperand &BaseOp = MI->getOperand(2); + unsigned BaseReg = BaseOp.getReg(); + bool BaseKill = BaseOp.isKill(); + bool BaseUndef = BaseOp.isUndef(); + unsigned OffReg = isT2 ? 0 : MI->getOperand(3).getReg(); + bool OffKill = isT2 ? false : MI->getOperand(3).isKill(); + bool OffUndef = isT2 ? false : MI->getOperand(3).isUndef(); + int OffImm = getMemoryOpOffset(MI); + unsigned PredReg = 0; + ARMCC::CondCodes Pred = llvm::getInstrPredicate(MI, PredReg); + + if (OddRegNum > EvenRegNum && OffReg == 0 && OffImm == 0) { + // Ascending register numbers and no offset. It's safe to change it to a + // ldm or stm. + unsigned NewOpc = (isLd) + ? (isT2 ? ARM::t2LDM : ARM::LDM) + : (isT2 ? ARM::t2STM : ARM::STM); + if (isLd) { + BuildMI(MBB, MBBI, MBBI->getDebugLoc(), TII->get(NewOpc)) + .addReg(BaseReg, getKillRegState(BaseKill)) + .addImm(ARM_AM::getAM4ModeImm(ARM_AM::ia)) + .addImm(Pred).addReg(PredReg) + .addReg(0) + .addReg(EvenReg, getDefRegState(isLd) | getDeadRegState(EvenDeadKill)) + .addReg(OddReg, getDefRegState(isLd) | getDeadRegState(OddDeadKill)); + ++NumLDRD2LDM; + } else { + BuildMI(MBB, MBBI, MBBI->getDebugLoc(), TII->get(NewOpc)) + .addReg(BaseReg, getKillRegState(BaseKill)) + .addImm(ARM_AM::getAM4ModeImm(ARM_AM::ia)) + .addImm(Pred).addReg(PredReg) + .addReg(0) + .addReg(EvenReg, + getKillRegState(EvenDeadKill) | getUndefRegState(EvenUndef)) + .addReg(OddReg, + getKillRegState(OddDeadKill) | getUndefRegState(OddUndef)); + ++NumSTRD2STM; + } + } else { + // Split into two instructions. + assert((!isT2 || !OffReg) && + "Thumb2 ldrd / strd does not encode offset register!"); + unsigned NewOpc = (isLd) + ? (isT2 ? (OffImm < 0 ? ARM::t2LDRi8 : ARM::t2LDRi12) : ARM::LDR) + : (isT2 ? (OffImm < 0 ? ARM::t2STRi8 : ARM::t2STRi12) : ARM::STR); + DebugLoc dl = MBBI->getDebugLoc(); + // If this is a load and base register is killed, it may have been + // re-defed by the load, make sure the first load does not clobber it. + if (isLd && + (BaseKill || OffKill) && + (TRI->regsOverlap(EvenReg, BaseReg) || + (OffReg && TRI->regsOverlap(EvenReg, OffReg)))) { + assert(!TRI->regsOverlap(OddReg, BaseReg) && + (!OffReg || !TRI->regsOverlap(OddReg, OffReg))); + InsertLDR_STR(MBB, MBBI, OffImm+4, isLd, dl, NewOpc, + OddReg, OddDeadKill, false, + BaseReg, false, BaseUndef, OffReg, false, OffUndef, + Pred, PredReg, TII, isT2); + InsertLDR_STR(MBB, MBBI, OffImm, isLd, dl, NewOpc, + EvenReg, EvenDeadKill, false, + BaseReg, BaseKill, BaseUndef, OffReg, OffKill, OffUndef, + Pred, PredReg, TII, isT2); + } else { + if (OddReg == EvenReg && EvenDeadKill) { + // If the two source operands are the same, the kill marker is probably + // on the first one. e.g. + // t2STRDi8 %R5, %R5, %R9, 0, 14, %reg0 + EvenDeadKill = false; + OddDeadKill = true; + } + InsertLDR_STR(MBB, MBBI, OffImm, isLd, dl, NewOpc, + EvenReg, EvenDeadKill, EvenUndef, + BaseReg, false, BaseUndef, OffReg, false, OffUndef, + Pred, PredReg, TII, isT2); + InsertLDR_STR(MBB, MBBI, OffImm+4, isLd, dl, NewOpc, + OddReg, OddDeadKill, OddUndef, + BaseReg, BaseKill, BaseUndef, OffReg, OffKill, OffUndef, + Pred, PredReg, TII, isT2); + } + if (isLd) + ++NumLDRD2LDR; + else + ++NumSTRD2STR; + } + + MBBI = prior(MBBI); + MBB.erase(MI); + } + return false; +} + +/// LoadStoreMultipleOpti - An optimization pass to turn multiple LDR / STR +/// ops of the same base and incrementing offset into LDM / STM ops. +bool ARMLoadStoreOpt::LoadStoreMultipleOpti(MachineBasicBlock &MBB) { + unsigned NumMerges = 0; + unsigned NumMemOps = 0; + MemOpQueue MemOps; + unsigned CurrBase = 0; + int CurrOpc = -1; + unsigned CurrSize = 0; + ARMCC::CondCodes CurrPred = ARMCC::AL; + unsigned CurrPredReg = 0; + unsigned Position = 0; + SmallVector Merges; + + RS->enterBasicBlock(&MBB); + MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end(); + while (MBBI != E) { + if (FixInvalidRegPairOp(MBB, MBBI)) + continue; + + bool Advance = false; + bool TryMerge = false; + bool Clobber = false; + + bool isMemOp = isMemoryOp(MBBI); + if (isMemOp) { + int Opcode = MBBI->getOpcode(); + unsigned Size = getLSMultipleTransferSize(MBBI); + unsigned Base = MBBI->getOperand(1).getReg(); + unsigned PredReg = 0; + ARMCC::CondCodes Pred = llvm::getInstrPredicate(MBBI, PredReg); + int Offset = getMemoryOpOffset(MBBI); + // Watch out for: + // r4 := ldr [r5] + // r5 := ldr [r5, #4] + // r6 := ldr [r5, #8] + // + // The second ldr has effectively broken the chain even though it + // looks like the later ldr(s) use the same base register. Try to + // merge the ldr's so far, including this one. But don't try to + // combine the following ldr(s). + Clobber = (isi32Load(Opcode) && Base == MBBI->getOperand(0).getReg()); + if (CurrBase == 0 && !Clobber) { + // Start of a new chain. + CurrBase = Base; + CurrOpc = Opcode; + CurrSize = Size; + CurrPred = Pred; + CurrPredReg = PredReg; + MemOps.push_back(MemOpQueueEntry(Offset, Position, MBBI)); + NumMemOps++; + Advance = true; + } else { + if (Clobber) { + TryMerge = true; + Advance = true; + } + + if (CurrOpc == Opcode && CurrBase == Base && CurrPred == Pred) { + // No need to match PredReg. + // Continue adding to the queue. + if (Offset > MemOps.back().Offset) { + MemOps.push_back(MemOpQueueEntry(Offset, Position, MBBI)); + NumMemOps++; + Advance = true; + } else { + for (MemOpQueueIter I = MemOps.begin(), E = MemOps.end(); + I != E; ++I) { + if (Offset < I->Offset) { + MemOps.insert(I, MemOpQueueEntry(Offset, Position, MBBI)); + NumMemOps++; + Advance = true; + break; + } else if (Offset == I->Offset) { + // Collision! This can't be merged! + break; + } + } + } + } + } + } + + if (Advance) { + ++Position; + ++MBBI; + if (MBBI == E) + // Reach the end of the block, try merging the memory instructions. + TryMerge = true; + } else + TryMerge = true; + + if (TryMerge) { + if (NumMemOps > 1) { + // Try to find a free register to use as a new base in case it's needed. + // First advance to the instruction just before the start of the chain. + AdvanceRS(MBB, MemOps); + // Find a scratch register. + unsigned Scratch = RS->FindUnusedReg(ARM::GPRRegisterClass); + // Process the load / store instructions. + RS->forward(prior(MBBI)); + + // Merge ops. + Merges.clear(); + MergeLDR_STR(MBB, 0, CurrBase, CurrOpc, CurrSize, + CurrPred, CurrPredReg, Scratch, MemOps, Merges); + + // Try folding preceeding/trailing base inc/dec into the generated + // LDM/STM ops. + for (unsigned i = 0, e = Merges.size(); i < e; ++i) + if (MergeBaseUpdateLSMultiple(MBB, Merges[i], Advance, MBBI)) + ++NumMerges; + NumMerges += Merges.size(); + + // Try folding preceeding/trailing base inc/dec into those load/store + // that were not merged to form LDM/STM ops. + for (unsigned i = 0; i != NumMemOps; ++i) + if (!MemOps[i].Merged) + if (MergeBaseUpdateLoadStore(MBB, MemOps[i].MBBI, TII,Advance,MBBI)) + ++NumMerges; + + // RS may be pointing to an instruction that's deleted. + RS->skipTo(prior(MBBI)); + } else if (NumMemOps == 1) { + // Try folding preceeding/trailing base inc/dec into the single + // load/store. + if (MergeBaseUpdateLoadStore(MBB, MemOps[0].MBBI, TII, Advance, MBBI)) { + ++NumMerges; + RS->forward(prior(MBBI)); + } + } + + CurrBase = 0; + CurrOpc = -1; + CurrSize = 0; + CurrPred = ARMCC::AL; + CurrPredReg = 0; + if (NumMemOps) { + MemOps.clear(); + NumMemOps = 0; + } + + // If iterator hasn't been advanced and this is not a memory op, skip it. + // It can't start a new chain anyway. + if (!Advance && !isMemOp && MBBI != E) { + ++Position; + ++MBBI; + } + } + } + return NumMerges > 0; +} + +namespace { + struct OffsetCompare { + bool operator()(const MachineInstr *LHS, const MachineInstr *RHS) const { + int LOffset = getMemoryOpOffset(LHS); + int ROffset = getMemoryOpOffset(RHS); + assert(LHS == RHS || LOffset != ROffset); + return LOffset > ROffset; + } + }; +} + +/// MergeReturnIntoLDM - If this is a exit BB, try merging the return op +/// (bx lr) into the preceeding stack restore so it directly restore the value +/// of LR into pc. +/// ldmfd sp!, {r7, lr} +/// bx lr +/// => +/// ldmfd sp!, {r7, pc} +bool ARMLoadStoreOpt::MergeReturnIntoLDM(MachineBasicBlock &MBB) { + if (MBB.empty()) return false; + + MachineBasicBlock::iterator MBBI = prior(MBB.end()); + if (MBBI != MBB.begin() && + (MBBI->getOpcode() == ARM::BX_RET || MBBI->getOpcode() == ARM::tBX_RET)) { + MachineInstr *PrevMI = prior(MBBI); + if (PrevMI->getOpcode() == ARM::LDM || PrevMI->getOpcode() == ARM::t2LDM) { + MachineOperand &MO = PrevMI->getOperand(PrevMI->getNumOperands()-1); + if (MO.getReg() != ARM::LR) + return false; + unsigned NewOpc = isThumb2 ? ARM::t2LDM_RET : ARM::LDM_RET; + PrevMI->setDesc(TII->get(NewOpc)); + MO.setReg(ARM::PC); + MBB.erase(MBBI); + return true; + } + } + return false; +} + +bool ARMLoadStoreOpt::runOnMachineFunction(MachineFunction &Fn) { + const TargetMachine &TM = Fn.getTarget(); + AFI = Fn.getInfo(); + TII = TM.getInstrInfo(); + TRI = TM.getRegisterInfo(); + RS = new RegScavenger(); + isThumb2 = AFI->isThumb2Function(); + + bool Modified = false; + for (MachineFunction::iterator MFI = Fn.begin(), E = Fn.end(); MFI != E; + ++MFI) { + MachineBasicBlock &MBB = *MFI; + Modified |= LoadStoreMultipleOpti(MBB); + Modified |= MergeReturnIntoLDM(MBB); + } + + delete RS; + return Modified; +} + + +/// ARMPreAllocLoadStoreOpt - Pre- register allocation pass that move +/// load / stores from consecutive locations close to make it more +/// likely they will be combined later. + +namespace { + struct ARMPreAllocLoadStoreOpt : public MachineFunctionPass{ + static char ID; + ARMPreAllocLoadStoreOpt() : MachineFunctionPass(&ID) {} + + const TargetData *TD; + const TargetInstrInfo *TII; + const TargetRegisterInfo *TRI; + const ARMSubtarget *STI; + MachineRegisterInfo *MRI; + MachineFunction *MF; + + virtual bool runOnMachineFunction(MachineFunction &Fn); + + virtual const char *getPassName() const { + return "ARM pre- register allocation load / store optimization pass"; + } + + private: + bool CanFormLdStDWord(MachineInstr *Op0, MachineInstr *Op1, DebugLoc &dl, + unsigned &NewOpc, unsigned &EvenReg, + unsigned &OddReg, unsigned &BaseReg, + unsigned &OffReg, int &Offset, + unsigned &PredReg, ARMCC::CondCodes &Pred, + bool &isT2); + bool RescheduleOps(MachineBasicBlock *MBB, + SmallVector &Ops, + unsigned Base, bool isLd, + DenseMap &MI2LocMap); + bool RescheduleLoadStoreInstrs(MachineBasicBlock *MBB); + }; + char ARMPreAllocLoadStoreOpt::ID = 0; +} + +bool ARMPreAllocLoadStoreOpt::runOnMachineFunction(MachineFunction &Fn) { + TD = Fn.getTarget().getTargetData(); + TII = Fn.getTarget().getInstrInfo(); + TRI = Fn.getTarget().getRegisterInfo(); + STI = &Fn.getTarget().getSubtarget(); + MRI = &Fn.getRegInfo(); + MF = &Fn; + + bool Modified = false; + for (MachineFunction::iterator MFI = Fn.begin(), E = Fn.end(); MFI != E; + ++MFI) + Modified |= RescheduleLoadStoreInstrs(MFI); + + return Modified; +} + +static bool IsSafeAndProfitableToMove(bool isLd, unsigned Base, + MachineBasicBlock::iterator I, + MachineBasicBlock::iterator E, + SmallPtrSet &MemOps, + SmallSet &MemRegs, + const TargetRegisterInfo *TRI) { + // Are there stores / loads / calls between them? + // FIXME: This is overly conservative. We should make use of alias information + // some day. + SmallSet AddedRegPressure; + while (++I != E) { + if (MemOps.count(&*I)) + continue; + const TargetInstrDesc &TID = I->getDesc(); + if (TID.isCall() || TID.isTerminator() || TID.hasUnmodeledSideEffects()) + return false; + if (isLd && TID.mayStore()) + return false; + if (!isLd) { + if (TID.mayLoad()) + return false; + // It's not safe to move the first 'str' down. + // str r1, [r0] + // strh r5, [r0] + // str r4, [r0, #+4] + if (TID.mayStore()) + return false; + } + for (unsigned j = 0, NumOps = I->getNumOperands(); j != NumOps; ++j) { + MachineOperand &MO = I->getOperand(j); + if (!MO.isReg()) + continue; + unsigned Reg = MO.getReg(); + if (MO.isDef() && TRI->regsOverlap(Reg, Base)) + return false; + if (Reg != Base && !MemRegs.count(Reg)) + AddedRegPressure.insert(Reg); + } + } + + // Estimate register pressure increase due to the transformation. + if (MemRegs.size() <= 4) + // Ok if we are moving small number of instructions. + return true; + return AddedRegPressure.size() <= MemRegs.size() * 2; +} + +bool +ARMPreAllocLoadStoreOpt::CanFormLdStDWord(MachineInstr *Op0, MachineInstr *Op1, + DebugLoc &dl, + unsigned &NewOpc, unsigned &EvenReg, + unsigned &OddReg, unsigned &BaseReg, + unsigned &OffReg, int &Offset, + unsigned &PredReg, + ARMCC::CondCodes &Pred, + bool &isT2) { + // Make sure we're allowed to generate LDRD/STRD. + if (!STI->hasV5TEOps()) + return false; + + // FIXME: VLDRS / VSTRS -> VLDRD / VSTRD + unsigned Scale = 1; + unsigned Opcode = Op0->getOpcode(); + if (Opcode == ARM::LDR) + NewOpc = ARM::LDRD; + else if (Opcode == ARM::STR) + NewOpc = ARM::STRD; + else if (Opcode == ARM::t2LDRi8 || Opcode == ARM::t2LDRi12) { + NewOpc = ARM::t2LDRDi8; + Scale = 4; + isT2 = true; + } else if (Opcode == ARM::t2STRi8 || Opcode == ARM::t2STRi12) { + NewOpc = ARM::t2STRDi8; + Scale = 4; + isT2 = true; + } else + return false; + + // Make sure the offset registers match. + if (!isT2 && + (Op0->getOperand(2).getReg() != Op1->getOperand(2).getReg())) + return false; + + // Must sure the base address satisfies i64 ld / st alignment requirement. + if (!Op0->hasOneMemOperand() || + !(*Op0->memoperands_begin())->getValue() || + (*Op0->memoperands_begin())->isVolatile()) + return false; + + unsigned Align = (*Op0->memoperands_begin())->getAlignment(); + Function *Func = MF->getFunction(); + unsigned ReqAlign = STI->hasV6Ops() + ? TD->getPrefTypeAlignment(Type::getInt64Ty(Func->getContext())) + : 8; // Pre-v6 need 8-byte align + if (Align < ReqAlign) + return false; + + // Then make sure the immediate offset fits. + int OffImm = getMemoryOpOffset(Op0); + if (isT2) { + if (OffImm < 0) { + if (OffImm < -255) + // Can't fall back to t2LDRi8 / t2STRi8. + return false; + } else { + int Limit = (1 << 8) * Scale; + if (OffImm >= Limit || (OffImm & (Scale-1))) + return false; + } + Offset = OffImm; + } else { + ARM_AM::AddrOpc AddSub = ARM_AM::add; + if (OffImm < 0) { + AddSub = ARM_AM::sub; + OffImm = - OffImm; + } + int Limit = (1 << 8) * Scale; + if (OffImm >= Limit || (OffImm & (Scale-1))) + return false; + Offset = ARM_AM::getAM3Opc(AddSub, OffImm); + } + EvenReg = Op0->getOperand(0).getReg(); + OddReg = Op1->getOperand(0).getReg(); + if (EvenReg == OddReg) + return false; + BaseReg = Op0->getOperand(1).getReg(); + if (!isT2) + OffReg = Op0->getOperand(2).getReg(); + Pred = llvm::getInstrPredicate(Op0, PredReg); + dl = Op0->getDebugLoc(); + return true; +} + +bool ARMPreAllocLoadStoreOpt::RescheduleOps(MachineBasicBlock *MBB, + SmallVector &Ops, + unsigned Base, bool isLd, + DenseMap &MI2LocMap) { + bool RetVal = false; + + // Sort by offset (in reverse order). + std::sort(Ops.begin(), Ops.end(), OffsetCompare()); + + // The loads / stores of the same base are in order. Scan them from first to + // last and check for the followins: + // 1. Any def of base. + // 2. Any gaps. + while (Ops.size() > 1) { + unsigned FirstLoc = ~0U; + unsigned LastLoc = 0; + MachineInstr *FirstOp = 0; + MachineInstr *LastOp = 0; + int LastOffset = 0; + unsigned LastOpcode = 0; + unsigned LastBytes = 0; + unsigned NumMove = 0; + for (int i = Ops.size() - 1; i >= 0; --i) { + MachineInstr *Op = Ops[i]; + unsigned Loc = MI2LocMap[Op]; + if (Loc <= FirstLoc) { + FirstLoc = Loc; + FirstOp = Op; + } + if (Loc >= LastLoc) { + LastLoc = Loc; + LastOp = Op; + } + + unsigned Opcode = Op->getOpcode(); + if (LastOpcode && Opcode != LastOpcode) + break; + + int Offset = getMemoryOpOffset(Op); + unsigned Bytes = getLSMultipleTransferSize(Op); + if (LastBytes) { + if (Bytes != LastBytes || Offset != (LastOffset + (int)Bytes)) + break; + } + LastOffset = Offset; + LastBytes = Bytes; + LastOpcode = Opcode; + if (++NumMove == 8) // FIXME: Tune this limit. + break; + } + + if (NumMove <= 1) + Ops.pop_back(); + else { + SmallPtrSet MemOps; + SmallSet MemRegs; + for (int i = NumMove-1; i >= 0; --i) { + MemOps.insert(Ops[i]); + MemRegs.insert(Ops[i]->getOperand(0).getReg()); + } + + // Be conservative, if the instructions are too far apart, don't + // move them. We want to limit the increase of register pressure. + bool DoMove = (LastLoc - FirstLoc) <= NumMove*4; // FIXME: Tune this. + if (DoMove) + DoMove = IsSafeAndProfitableToMove(isLd, Base, FirstOp, LastOp, + MemOps, MemRegs, TRI); + if (!DoMove) { + for (unsigned i = 0; i != NumMove; ++i) + Ops.pop_back(); + } else { + // This is the new location for the loads / stores. + MachineBasicBlock::iterator InsertPos = isLd ? FirstOp : LastOp; + while (InsertPos != MBB->end() && MemOps.count(InsertPos)) + ++InsertPos; + + // If we are moving a pair of loads / stores, see if it makes sense + // to try to allocate a pair of registers that can form register pairs. + MachineInstr *Op0 = Ops.back(); + MachineInstr *Op1 = Ops[Ops.size()-2]; + unsigned EvenReg = 0, OddReg = 0; + unsigned BaseReg = 0, OffReg = 0, PredReg = 0; + ARMCC::CondCodes Pred = ARMCC::AL; + bool isT2 = false; + unsigned NewOpc = 0; + int Offset = 0; + DebugLoc dl; + if (NumMove == 2 && CanFormLdStDWord(Op0, Op1, dl, NewOpc, + EvenReg, OddReg, BaseReg, OffReg, + Offset, PredReg, Pred, isT2)) { + Ops.pop_back(); + Ops.pop_back(); + + // Form the pair instruction. + if (isLd) { + MachineInstrBuilder MIB = BuildMI(*MBB, InsertPos, + dl, TII->get(NewOpc)) + .addReg(EvenReg, RegState::Define) + .addReg(OddReg, RegState::Define) + .addReg(BaseReg); + if (!isT2) + MIB.addReg(OffReg); + MIB.addImm(Offset).addImm(Pred).addReg(PredReg); + ++NumLDRDFormed; + } else { + MachineInstrBuilder MIB = BuildMI(*MBB, InsertPos, + dl, TII->get(NewOpc)) + .addReg(EvenReg) + .addReg(OddReg) + .addReg(BaseReg); + if (!isT2) + MIB.addReg(OffReg); + MIB.addImm(Offset).addImm(Pred).addReg(PredReg); + ++NumSTRDFormed; + } + MBB->erase(Op0); + MBB->erase(Op1); + + // Add register allocation hints to form register pairs. + MRI->setRegAllocationHint(EvenReg, ARMRI::RegPairEven, OddReg); + MRI->setRegAllocationHint(OddReg, ARMRI::RegPairOdd, EvenReg); + } else { + for (unsigned i = 0; i != NumMove; ++i) { + MachineInstr *Op = Ops.back(); + Ops.pop_back(); + MBB->splice(InsertPos, MBB, Op); + } + } + + NumLdStMoved += NumMove; + RetVal = true; + } + } + } + + return RetVal; +} + +bool +ARMPreAllocLoadStoreOpt::RescheduleLoadStoreInstrs(MachineBasicBlock *MBB) { + bool RetVal = false; + + DenseMap MI2LocMap; + DenseMap > Base2LdsMap; + DenseMap > Base2StsMap; + SmallVector LdBases; + SmallVector StBases; + + unsigned Loc = 0; + MachineBasicBlock::iterator MBBI = MBB->begin(); + MachineBasicBlock::iterator E = MBB->end(); + while (MBBI != E) { + for (; MBBI != E; ++MBBI) { + MachineInstr *MI = MBBI; + const TargetInstrDesc &TID = MI->getDesc(); + if (TID.isCall() || TID.isTerminator()) { + // Stop at barriers. + ++MBBI; + break; + } + + MI2LocMap[MI] = Loc++; + if (!isMemoryOp(MI)) + continue; + unsigned PredReg = 0; + if (llvm::getInstrPredicate(MI, PredReg) != ARMCC::AL) + continue; + + int Opc = MI->getOpcode(); + bool isLd = isi32Load(Opc) || Opc == ARM::VLDRS || Opc == ARM::VLDRD; + unsigned Base = MI->getOperand(1).getReg(); + int Offset = getMemoryOpOffset(MI); + + bool StopHere = false; + if (isLd) { + DenseMap >::iterator BI = + Base2LdsMap.find(Base); + if (BI != Base2LdsMap.end()) { + for (unsigned i = 0, e = BI->second.size(); i != e; ++i) { + if (Offset == getMemoryOpOffset(BI->second[i])) { + StopHere = true; + break; + } + } + if (!StopHere) + BI->second.push_back(MI); + } else { + SmallVector MIs; + MIs.push_back(MI); + Base2LdsMap[Base] = MIs; + LdBases.push_back(Base); + } + } else { + DenseMap >::iterator BI = + Base2StsMap.find(Base); + if (BI != Base2StsMap.end()) { + for (unsigned i = 0, e = BI->second.size(); i != e; ++i) { + if (Offset == getMemoryOpOffset(BI->second[i])) { + StopHere = true; + break; + } + } + if (!StopHere) + BI->second.push_back(MI); + } else { + SmallVector MIs; + MIs.push_back(MI); + Base2StsMap[Base] = MIs; + StBases.push_back(Base); + } + } + + if (StopHere) { + // Found a duplicate (a base+offset combination that's seen earlier). + // Backtrack. + --Loc; + break; + } + } + + // Re-schedule loads. + for (unsigned i = 0, e = LdBases.size(); i != e; ++i) { + unsigned Base = LdBases[i]; + SmallVector &Lds = Base2LdsMap[Base]; + if (Lds.size() > 1) + RetVal |= RescheduleOps(MBB, Lds, Base, true, MI2LocMap); + } + + // Re-schedule stores. + for (unsigned i = 0, e = StBases.size(); i != e; ++i) { + unsigned Base = StBases[i]; + SmallVector &Sts = Base2StsMap[Base]; + if (Sts.size() > 1) + RetVal |= RescheduleOps(MBB, Sts, Base, false, MI2LocMap); + } + + if (MBBI != E) { + Base2LdsMap.clear(); + Base2StsMap.clear(); + LdBases.clear(); + StBases.clear(); + } + } + + return RetVal; +} + + +/// createARMLoadStoreOptimizationPass - returns an instance of the load / store +/// optimization pass. +FunctionPass *llvm::createARMLoadStoreOptimizationPass(bool PreAlloc) { + if (PreAlloc) + return new ARMPreAllocLoadStoreOpt(); + return new ARMLoadStoreOpt(); +} diff --git a/libclamav/c++/llvm/lib/Target/ARM/ARMMCAsmInfo.cpp b/libclamav/c++/llvm/lib/Target/ARM/ARMMCAsmInfo.cpp new file mode 100644 index 000000000..0ff65d2af --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/ARM/ARMMCAsmInfo.cpp @@ -0,0 +1,72 @@ +//===-- ARMMCAsmInfo.cpp - ARM asm properties -------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the declarations of the ARMMCAsmInfo properties. +// +//===----------------------------------------------------------------------===// + +#include "ARMMCAsmInfo.h" +using namespace llvm; + +static const char *const arm_asm_table[] = { + "{r0}", "r0", + "{r1}", "r1", + "{r2}", "r2", + "{r3}", "r3", + "{r4}", "r4", + "{r5}", "r5", + "{r6}", "r6", + "{r7}", "r7", + "{r8}", "r8", + "{r9}", "r9", + "{r10}", "r10", + "{r11}", "r11", + "{r12}", "r12", + "{r13}", "r13", + "{r14}", "r14", + "{lr}", "lr", + "{sp}", "sp", + "{ip}", "ip", + "{fp}", "fp", + "{sl}", "sl", + "{memory}", "memory", + "{cc}", "cc", + 0,0 +}; + +ARMMCAsmInfoDarwin::ARMMCAsmInfoDarwin() { + AsmTransCBE = arm_asm_table; + Data64bitsDirective = 0; + CommentString = "@"; + COMMDirectiveTakesAlignment = false; + SupportsDebugInformation = true; + + // Exceptions handling + ExceptionsType = ExceptionHandling::SjLj; + AbsoluteEHSectionOffsets = false; +} + +ARMELFMCAsmInfo::ARMELFMCAsmInfo() { + AlignmentIsInBytes = false; + Data64bitsDirective = 0; + CommentString = "@"; + COMMDirectiveTakesAlignment = false; + + NeedsSet = false; + HasLEB128 = true; + AbsoluteDebugSectionOffsets = true; + PrivateGlobalPrefix = ".L"; + WeakRefDirective = "\t.weak\t"; + SetDirective = "\t.set\t"; + LCOMMDirective = "\t.lcomm\t"; + + DwarfRequiresFrameSection = false; + + SupportsDebugInformation = true; +} diff --git a/libclamav/c++/llvm/lib/Target/ARM/ARMMCAsmInfo.h b/libclamav/c++/llvm/lib/Target/ARM/ARMMCAsmInfo.h new file mode 100644 index 000000000..90f7822ea --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/ARM/ARMMCAsmInfo.h @@ -0,0 +1,31 @@ +//=====-- ARMMCAsmInfo.h - ARM asm properties -------------*- C++ -*--====// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the declaration of the ARMMCAsmInfo class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ARMTARGETASMINFO_H +#define LLVM_ARMTARGETASMINFO_H + +#include "llvm/MC/MCAsmInfoDarwin.h" + +namespace llvm { + + struct ARMMCAsmInfoDarwin : public MCAsmInfoDarwin { + explicit ARMMCAsmInfoDarwin(); + }; + + struct ARMELFMCAsmInfo : public MCAsmInfo { + explicit ARMELFMCAsmInfo(); + }; + +} // namespace llvm + +#endif diff --git a/libclamav/c++/llvm/lib/Target/ARM/ARMMachineFunctionInfo.h b/libclamav/c++/llvm/lib/Target/ARM/ARMMachineFunctionInfo.h new file mode 100644 index 000000000..2176b2735 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/ARM/ARMMachineFunctionInfo.h @@ -0,0 +1,239 @@ +//====- ARMMachineFuctionInfo.h - ARM machine function 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 declares ARM-specific per-machine-function information. +// +//===----------------------------------------------------------------------===// + +#ifndef ARMMACHINEFUNCTIONINFO_H +#define ARMMACHINEFUNCTIONINFO_H + +#include "ARMSubtarget.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/ADT/BitVector.h" + +namespace llvm { + +/// ARMFunctionInfo - This class is derived from MachineFunction private +/// ARM target-specific information for each MachineFunction. +class ARMFunctionInfo : public MachineFunctionInfo { + + /// isThumb - True if this function is compiled under Thumb mode. + /// Used to initialized Align, so must precede it. + bool isThumb; + + /// hasThumb2 - True if the target architecture supports Thumb2. Do not use + /// to determine if function is compiled under Thumb mode, for that use + /// 'isThumb'. + bool hasThumb2; + + /// Align - required alignment. ARM functions and Thumb functions with + /// constant pools require 4-byte alignment; other Thumb functions + /// require only 2-byte alignment. + unsigned Align; + + /// VarArgsRegSaveSize - Size of the register save area for vararg functions. + /// + unsigned VarArgsRegSaveSize; + + /// HasStackFrame - True if this function has a stack frame. Set by + /// processFunctionBeforeCalleeSavedScan(). + bool HasStackFrame; + + /// LRSpilledForFarJump - True if the LR register has been for spilled to + /// enable far jump. + bool LRSpilledForFarJump; + + /// FramePtrSpillOffset - If HasStackFrame, this records the frame pointer + /// spill stack offset. + unsigned FramePtrSpillOffset; + + /// GPRCS1Offset, GPRCS2Offset, DPRCSOffset - Starting offset of callee saved + /// register spills areas. For Mac OS X: + /// + /// GPR callee-saved (1) : r4, r5, r6, r7, lr + /// -------------------------------------------- + /// GPR callee-saved (2) : r8, r10, r11 + /// -------------------------------------------- + /// DPR callee-saved : d8 - d15 + unsigned GPRCS1Offset; + unsigned GPRCS2Offset; + unsigned DPRCSOffset; + + /// GPRCS1Size, GPRCS2Size, DPRCSSize - Sizes of callee saved register spills + /// areas. + unsigned GPRCS1Size; + unsigned GPRCS2Size; + unsigned DPRCSSize; + + /// GPRCS1Frames, GPRCS2Frames, DPRCSFrames - Keeps track of frame indices + /// which belong to these spill areas. + BitVector GPRCS1Frames; + BitVector GPRCS2Frames; + BitVector DPRCSFrames; + + /// SpilledCSRegs - A BitVector mask of all spilled callee-saved registers. + /// + BitVector SpilledCSRegs; + + /// JumpTableUId - Unique id for jumptables. + /// + unsigned JumpTableUId; + + unsigned ConstPoolEntryUId; + +public: + ARMFunctionInfo() : + isThumb(false), + hasThumb2(false), + Align(2U), + VarArgsRegSaveSize(0), HasStackFrame(false), + LRSpilledForFarJump(false), + FramePtrSpillOffset(0), GPRCS1Offset(0), GPRCS2Offset(0), DPRCSOffset(0), + GPRCS1Size(0), GPRCS2Size(0), DPRCSSize(0), + GPRCS1Frames(0), GPRCS2Frames(0), DPRCSFrames(0), + JumpTableUId(0), ConstPoolEntryUId(0) {} + + explicit ARMFunctionInfo(MachineFunction &MF) : + isThumb(MF.getTarget().getSubtarget().isThumb()), + hasThumb2(MF.getTarget().getSubtarget().hasThumb2()), + Align(isThumb ? 1U : 2U), + VarArgsRegSaveSize(0), HasStackFrame(false), + LRSpilledForFarJump(false), + FramePtrSpillOffset(0), GPRCS1Offset(0), GPRCS2Offset(0), DPRCSOffset(0), + GPRCS1Size(0), GPRCS2Size(0), DPRCSSize(0), + GPRCS1Frames(32), GPRCS2Frames(32), DPRCSFrames(32), + SpilledCSRegs(MF.getTarget().getRegisterInfo()->getNumRegs()), + JumpTableUId(0), ConstPoolEntryUId(0) {} + + bool isThumbFunction() const { return isThumb; } + bool isThumb1OnlyFunction() const { return isThumb && !hasThumb2; } + bool isThumb2Function() const { return isThumb && hasThumb2; } + + unsigned getAlign() const { return Align; } + void setAlign(unsigned a) { Align = a; } + + unsigned getVarArgsRegSaveSize() const { return VarArgsRegSaveSize; } + void setVarArgsRegSaveSize(unsigned s) { VarArgsRegSaveSize = s; } + + bool hasStackFrame() const { return HasStackFrame; } + void setHasStackFrame(bool s) { HasStackFrame = s; } + + bool isLRSpilledForFarJump() const { return LRSpilledForFarJump; } + void setLRIsSpilledForFarJump(bool s) { LRSpilledForFarJump = s; } + + unsigned getFramePtrSpillOffset() const { return FramePtrSpillOffset; } + void setFramePtrSpillOffset(unsigned o) { FramePtrSpillOffset = o; } + + unsigned getGPRCalleeSavedArea1Offset() const { return GPRCS1Offset; } + unsigned getGPRCalleeSavedArea2Offset() const { return GPRCS2Offset; } + unsigned getDPRCalleeSavedAreaOffset() const { return DPRCSOffset; } + + void setGPRCalleeSavedArea1Offset(unsigned o) { GPRCS1Offset = o; } + void setGPRCalleeSavedArea2Offset(unsigned o) { GPRCS2Offset = o; } + void setDPRCalleeSavedAreaOffset(unsigned o) { DPRCSOffset = o; } + + unsigned getGPRCalleeSavedArea1Size() const { return GPRCS1Size; } + unsigned getGPRCalleeSavedArea2Size() const { return GPRCS2Size; } + unsigned getDPRCalleeSavedAreaSize() const { return DPRCSSize; } + + void setGPRCalleeSavedArea1Size(unsigned s) { GPRCS1Size = s; } + void setGPRCalleeSavedArea2Size(unsigned s) { GPRCS2Size = s; } + void setDPRCalleeSavedAreaSize(unsigned s) { DPRCSSize = s; } + + bool isGPRCalleeSavedArea1Frame(int fi) const { + if (fi < 0 || fi >= (int)GPRCS1Frames.size()) + return false; + return GPRCS1Frames[fi]; + } + bool isGPRCalleeSavedArea2Frame(int fi) const { + if (fi < 0 || fi >= (int)GPRCS2Frames.size()) + return false; + return GPRCS2Frames[fi]; + } + bool isDPRCalleeSavedAreaFrame(int fi) const { + if (fi < 0 || fi >= (int)DPRCSFrames.size()) + return false; + return DPRCSFrames[fi]; + } + + void addGPRCalleeSavedArea1Frame(int fi) { + if (fi >= 0) { + int Size = GPRCS1Frames.size(); + if (fi >= Size) { + Size *= 2; + if (fi >= Size) + Size = fi+1; + GPRCS1Frames.resize(Size); + } + GPRCS1Frames[fi] = true; + } + } + void addGPRCalleeSavedArea2Frame(int fi) { + if (fi >= 0) { + int Size = GPRCS2Frames.size(); + if (fi >= Size) { + Size *= 2; + if (fi >= Size) + Size = fi+1; + GPRCS2Frames.resize(Size); + } + GPRCS2Frames[fi] = true; + } + } + void addDPRCalleeSavedAreaFrame(int fi) { + if (fi >= 0) { + int Size = DPRCSFrames.size(); + if (fi >= Size) { + Size *= 2; + if (fi >= Size) + Size = fi+1; + DPRCSFrames.resize(Size); + } + DPRCSFrames[fi] = true; + } + } + + void setCSRegisterIsSpilled(unsigned Reg) { + SpilledCSRegs.set(Reg); + } + + bool isCSRegisterSpilled(unsigned Reg) const { + return SpilledCSRegs[Reg]; + } + + const BitVector &getSpilledCSRegisters() const { + return SpilledCSRegs; + } + + unsigned createJumpTableUId() { + return JumpTableUId++; + } + + unsigned getNumJumpTables() const { + return JumpTableUId; + } + + void initConstPoolEntryUId(unsigned UId) { + ConstPoolEntryUId = UId; + } + + unsigned getNumConstPoolEntries() const { + return ConstPoolEntryUId; + } + + unsigned createConstPoolEntryUId() { + return ConstPoolEntryUId++; + } +}; +} // End llvm namespace + +#endif // ARMMACHINEFUNCTIONINFO_H diff --git a/libclamav/c++/llvm/lib/Target/ARM/ARMPerfectShuffle.h b/libclamav/c++/llvm/lib/Target/ARM/ARMPerfectShuffle.h new file mode 100644 index 000000000..5ff7c381b --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/ARM/ARMPerfectShuffle.h @@ -0,0 +1,6586 @@ +//===-- ARMPerfectShuffle.h - NEON Perfect Shuffle Table ------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file, which was autogenerated by llvm-PerfectShuffle, contains data +// for the optimal way to build a perfect shuffle using neon instructions. +// +//===----------------------------------------------------------------------===// + +// 31 entries have cost 0 +// 242 entries have cost 1 +// 1447 entries have cost 2 +// 3602 entries have cost 3 +// 1237 entries have cost 4 +// 2 entries have cost 5 + +// This table is 6561*4 = 26244 bytes in size. +static const unsigned PerfectShuffleTable[6561+1] = { + 135053414U, // <0,0,0,0>: Cost 1 vdup0 LHS + 1543503974U, // <0,0,0,1>: Cost 2 vext2 <0,0,0,0>, LHS + 2618572962U, // <0,0,0,2>: Cost 3 vext2 <0,2,0,0>, <0,2,0,0> + 2568054923U, // <0,0,0,3>: Cost 3 vext1 <3,0,0,0>, <3,0,0,0> + 1476398390U, // <0,0,0,4>: Cost 2 vext1 <0,0,0,0>, RHS + 2550140624U, // <0,0,0,5>: Cost 3 vext1 <0,0,0,0>, <5,1,7,3> + 2550141434U, // <0,0,0,6>: Cost 3 vext1 <0,0,0,0>, <6,2,7,3> + 2591945711U, // <0,0,0,7>: Cost 3 vext1 <7,0,0,0>, <7,0,0,0> + 135053414U, // <0,0,0,u>: Cost 1 vdup0 LHS + 2886516736U, // <0,0,1,0>: Cost 3 vzipl LHS, <0,0,0,0> + 1812775014U, // <0,0,1,1>: Cost 2 vzipl LHS, LHS + 1618133094U, // <0,0,1,2>: Cost 2 vext3 <1,2,3,0>, LHS + 2625209292U, // <0,0,1,3>: Cost 3 vext2 <1,3,0,0>, <1,3,0,0> + 2886558034U, // <0,0,1,4>: Cost 3 vzipl LHS, <0,4,1,5> + 2617246864U, // <0,0,1,5>: Cost 3 vext2 <0,0,0,0>, <1,5,3,7> + 3659723031U, // <0,0,1,6>: Cost 4 vext1 <6,0,0,1>, <6,0,0,1> + 2591953904U, // <0,0,1,7>: Cost 3 vext1 <7,0,0,1>, <7,0,0,1> + 1812775581U, // <0,0,1,u>: Cost 2 vzipl LHS, LHS + 3020734464U, // <0,0,2,0>: Cost 3 vtrnl LHS, <0,0,0,0> + 3020734474U, // <0,0,2,1>: Cost 3 vtrnl LHS, <0,0,1,1> + 1946992742U, // <0,0,2,2>: Cost 2 vtrnl LHS, LHS + 2631181989U, // <0,0,2,3>: Cost 3 vext2 <2,3,0,0>, <2,3,0,0> + 3020734668U, // <0,0,2,4>: Cost 3 vtrnl LHS, <0,2,4,6> + 3826550569U, // <0,0,2,5>: Cost 4 vuzpl <0,2,0,2>, <2,4,5,6> + 2617247674U, // <0,0,2,6>: Cost 3 vext2 <0,0,0,0>, <2,6,3,7> + 2591962097U, // <0,0,2,7>: Cost 3 vext1 <7,0,0,2>, <7,0,0,2> + 1946992796U, // <0,0,2,u>: Cost 2 vtrnl LHS, LHS + 2635163787U, // <0,0,3,0>: Cost 3 vext2 <3,0,0,0>, <3,0,0,0> + 2686419196U, // <0,0,3,1>: Cost 3 vext3 <0,3,1,0>, <0,3,1,0> + 2686492933U, // <0,0,3,2>: Cost 3 vext3 <0,3,2,0>, <0,3,2,0> + 2617248156U, // <0,0,3,3>: Cost 3 vext2 <0,0,0,0>, <3,3,3,3> + 2617248258U, // <0,0,3,4>: Cost 3 vext2 <0,0,0,0>, <3,4,5,6> + 3826551298U, // <0,0,3,5>: Cost 4 vuzpl <0,2,0,2>, <3,4,5,6> + 3690990200U, // <0,0,3,6>: Cost 4 vext2 <0,0,0,0>, <3,6,0,7> + 3713551042U, // <0,0,3,7>: Cost 4 vext2 <3,7,0,0>, <3,7,0,0> + 2635163787U, // <0,0,3,u>: Cost 3 vext2 <3,0,0,0>, <3,0,0,0> + 2617248658U, // <0,0,4,0>: Cost 3 vext2 <0,0,0,0>, <4,0,5,1> + 2888450150U, // <0,0,4,1>: Cost 3 vzipl <0,4,1,5>, LHS + 3021570150U, // <0,0,4,2>: Cost 3 vtrnl <0,2,4,6>, LHS + 3641829519U, // <0,0,4,3>: Cost 4 vext1 <3,0,0,4>, <3,0,0,4> + 3021570252U, // <0,0,4,4>: Cost 3 vtrnl <0,2,4,6>, <0,2,4,6> + 1543507254U, // <0,0,4,5>: Cost 2 vext2 <0,0,0,0>, RHS + 2752810294U, // <0,0,4,6>: Cost 3 vuzpl <0,2,0,2>, RHS + 3786998152U, // <0,0,4,7>: Cost 4 vext3 <4,7,5,0>, <0,4,7,5> + 1543507497U, // <0,0,4,u>: Cost 2 vext2 <0,0,0,0>, RHS + 2684354972U, // <0,0,5,0>: Cost 3 vext3 <0,0,0,0>, <0,5,0,7> + 2617249488U, // <0,0,5,1>: Cost 3 vext2 <0,0,0,0>, <5,1,7,3> + 3765617070U, // <0,0,5,2>: Cost 4 vext3 <1,2,3,0>, <0,5,2,7> + 3635865780U, // <0,0,5,3>: Cost 4 vext1 <2,0,0,5>, <3,0,4,5> + 2617249734U, // <0,0,5,4>: Cost 3 vext2 <0,0,0,0>, <5,4,7,6> + 2617249796U, // <0,0,5,5>: Cost 3 vext2 <0,0,0,0>, <5,5,5,5> + 2718712274U, // <0,0,5,6>: Cost 3 vext3 <5,6,7,0>, <0,5,6,7> + 2617249960U, // <0,0,5,7>: Cost 3 vext2 <0,0,0,0>, <5,7,5,7> + 2720039396U, // <0,0,5,u>: Cost 3 vext3 <5,u,7,0>, <0,5,u,7> + 2684355053U, // <0,0,6,0>: Cost 3 vext3 <0,0,0,0>, <0,6,0,7> + 3963609190U, // <0,0,6,1>: Cost 4 vzipl <0,6,2,7>, LHS + 2617250298U, // <0,0,6,2>: Cost 3 vext2 <0,0,0,0>, <6,2,7,3> + 3796435464U, // <0,0,6,3>: Cost 4 vext3 <6,3,7,0>, <0,6,3,7> + 3659762998U, // <0,0,6,4>: Cost 4 vext1 <6,0,0,6>, RHS + 3659763810U, // <0,0,6,5>: Cost 4 vext1 <6,0,0,6>, <5,6,7,0> + 2617250616U, // <0,0,6,6>: Cost 3 vext2 <0,0,0,0>, <6,6,6,6> + 2657727309U, // <0,0,6,7>: Cost 3 vext2 <6,7,0,0>, <6,7,0,0> + 2658390942U, // <0,0,6,u>: Cost 3 vext2 <6,u,0,0>, <6,u,0,0> + 2659054575U, // <0,0,7,0>: Cost 3 vext2 <7,0,0,0>, <7,0,0,0> + 3635880854U, // <0,0,7,1>: Cost 4 vext1 <2,0,0,7>, <1,2,3,0> + 3635881401U, // <0,0,7,2>: Cost 4 vext1 <2,0,0,7>, <2,0,0,7> + 3734787298U, // <0,0,7,3>: Cost 4 vext2 <7,3,0,0>, <7,3,0,0> + 2617251174U, // <0,0,7,4>: Cost 3 vext2 <0,0,0,0>, <7,4,5,6> + 3659772002U, // <0,0,7,5>: Cost 4 vext1 <6,0,0,7>, <5,6,7,0> + 3659772189U, // <0,0,7,6>: Cost 4 vext1 <6,0,0,7>, <6,0,0,7> + 2617251436U, // <0,0,7,7>: Cost 3 vext2 <0,0,0,0>, <7,7,7,7> + 2659054575U, // <0,0,7,u>: Cost 3 vext2 <7,0,0,0>, <7,0,0,0> + 135053414U, // <0,0,u,0>: Cost 1 vdup0 LHS + 1817419878U, // <0,0,u,1>: Cost 2 vzipl LHS, LHS + 1947435110U, // <0,0,u,2>: Cost 2 vtrnl LHS, LHS + 2568120467U, // <0,0,u,3>: Cost 3 vext1 <3,0,0,u>, <3,0,0,u> + 1476463926U, // <0,0,u,4>: Cost 2 vext1 <0,0,0,u>, RHS + 1543510170U, // <0,0,u,5>: Cost 2 vext2 <0,0,0,0>, RHS + 2752813210U, // <0,0,u,6>: Cost 3 vuzpl <0,2,0,2>, RHS + 2592011255U, // <0,0,u,7>: Cost 3 vext1 <7,0,0,u>, <7,0,0,u> + 135053414U, // <0,0,u,u>: Cost 1 vdup0 LHS + 2618581002U, // <0,1,0,0>: Cost 3 vext2 <0,2,0,1>, <0,0,1,1> + 1557446758U, // <0,1,0,1>: Cost 2 vext2 <2,3,0,1>, LHS + 2618581155U, // <0,1,0,2>: Cost 3 vext2 <0,2,0,1>, <0,2,0,1> + 2690548468U, // <0,1,0,3>: Cost 3 vext3 <1,0,3,0>, <1,0,3,0> + 2626543954U, // <0,1,0,4>: Cost 3 vext2 <1,5,0,1>, <0,4,1,5> + 4094985216U, // <0,1,0,5>: Cost 4 vtrnl <0,2,0,2>, <1,3,5,7> + 2592019278U, // <0,1,0,6>: Cost 3 vext1 <7,0,1,0>, <6,7,0,1> + 2592019448U, // <0,1,0,7>: Cost 3 vext1 <7,0,1,0>, <7,0,1,0> + 1557447325U, // <0,1,0,u>: Cost 2 vext2 <2,3,0,1>, LHS + 1476476938U, // <0,1,1,0>: Cost 2 vext1 <0,0,1,1>, <0,0,1,1> + 2886517556U, // <0,1,1,1>: Cost 3 vzipl LHS, <1,1,1,1> + 2886517654U, // <0,1,1,2>: Cost 3 vzipl LHS, <1,2,3,0> + 2886517720U, // <0,1,1,3>: Cost 3 vzipl LHS, <1,3,1,3> + 1476480310U, // <0,1,1,4>: Cost 2 vext1 <0,0,1,1>, RHS + 2886558864U, // <0,1,1,5>: Cost 3 vzipl LHS, <1,5,3,7> + 2550223354U, // <0,1,1,6>: Cost 3 vext1 <0,0,1,1>, <6,2,7,3> + 2550223856U, // <0,1,1,7>: Cost 3 vext1 <0,0,1,1>, <7,0,0,1> + 1476482862U, // <0,1,1,u>: Cost 2 vext1 <0,0,1,1>, LHS + 1494401126U, // <0,1,2,0>: Cost 2 vext1 <3,0,1,2>, LHS + 3020735284U, // <0,1,2,1>: Cost 3 vtrnl LHS, <1,1,1,1> + 2562172349U, // <0,1,2,2>: Cost 3 vext1 <2,0,1,2>, <2,0,1,2> + 835584U, // <0,1,2,3>: Cost 0 copy LHS + 1494404406U, // <0,1,2,4>: Cost 2 vext1 <3,0,1,2>, RHS + 3020735488U, // <0,1,2,5>: Cost 3 vtrnl LHS, <1,3,5,7> + 2631190458U, // <0,1,2,6>: Cost 3 vext2 <2,3,0,1>, <2,6,3,7> + 1518294010U, // <0,1,2,7>: Cost 2 vext1 <7,0,1,2>, <7,0,1,2> + 835584U, // <0,1,2,u>: Cost 0 copy LHS + 2692318156U, // <0,1,3,0>: Cost 3 vext3 <1,3,0,0>, <1,3,0,0> + 2691875800U, // <0,1,3,1>: Cost 3 vext3 <1,2,3,0>, <1,3,1,3> + 2691875806U, // <0,1,3,2>: Cost 3 vext3 <1,2,3,0>, <1,3,2,0> + 2692539367U, // <0,1,3,3>: Cost 3 vext3 <1,3,3,0>, <1,3,3,0> + 2562182454U, // <0,1,3,4>: Cost 3 vext1 <2,0,1,3>, RHS + 2691875840U, // <0,1,3,5>: Cost 3 vext3 <1,2,3,0>, <1,3,5,7> + 2692760578U, // <0,1,3,6>: Cost 3 vext3 <1,3,6,0>, <1,3,6,0> + 2639817411U, // <0,1,3,7>: Cost 3 vext2 <3,7,0,1>, <3,7,0,1> + 2691875863U, // <0,1,3,u>: Cost 3 vext3 <1,2,3,0>, <1,3,u,3> + 2568159334U, // <0,1,4,0>: Cost 3 vext1 <3,0,1,4>, LHS + 4095312692U, // <0,1,4,1>: Cost 4 vtrnl <0,2,4,6>, <1,1,1,1> + 2568160934U, // <0,1,4,2>: Cost 3 vext1 <3,0,1,4>, <2,3,0,1> + 2568161432U, // <0,1,4,3>: Cost 3 vext1 <3,0,1,4>, <3,0,1,4> + 2568162614U, // <0,1,4,4>: Cost 3 vext1 <3,0,1,4>, RHS + 1557450038U, // <0,1,4,5>: Cost 2 vext2 <2,3,0,1>, RHS + 2754235702U, // <0,1,4,6>: Cost 3 vuzpl <0,4,1,5>, RHS + 2592052220U, // <0,1,4,7>: Cost 3 vext1 <7,0,1,4>, <7,0,1,4> + 1557450281U, // <0,1,4,u>: Cost 2 vext2 <2,3,0,1>, RHS + 3765617775U, // <0,1,5,0>: Cost 4 vext3 <1,2,3,0>, <1,5,0,1> + 2647781007U, // <0,1,5,1>: Cost 3 vext2 <5,1,0,1>, <5,1,0,1> + 3704934138U, // <0,1,5,2>: Cost 4 vext2 <2,3,0,1>, <5,2,3,0> + 2691875984U, // <0,1,5,3>: Cost 3 vext3 <1,2,3,0>, <1,5,3,7> + 2657734598U, // <0,1,5,4>: Cost 3 vext2 <6,7,0,1>, <5,4,7,6> + 2650435539U, // <0,1,5,5>: Cost 3 vext2 <5,5,0,1>, <5,5,0,1> + 2651099172U, // <0,1,5,6>: Cost 3 vext2 <5,6,0,1>, <5,6,0,1> + 2651762805U, // <0,1,5,7>: Cost 3 vext2 <5,7,0,1>, <5,7,0,1> + 2691876029U, // <0,1,5,u>: Cost 3 vext3 <1,2,3,0>, <1,5,u,7> + 2592063590U, // <0,1,6,0>: Cost 3 vext1 <7,0,1,6>, LHS + 3765617871U, // <0,1,6,1>: Cost 4 vext3 <1,2,3,0>, <1,6,1,7> + 2654417337U, // <0,1,6,2>: Cost 3 vext2 <6,2,0,1>, <6,2,0,1> + 3765617889U, // <0,1,6,3>: Cost 4 vext3 <1,2,3,0>, <1,6,3,7> + 2592066870U, // <0,1,6,4>: Cost 3 vext1 <7,0,1,6>, RHS + 3765617907U, // <0,1,6,5>: Cost 4 vext3 <1,2,3,0>, <1,6,5,7> + 2657071869U, // <0,1,6,6>: Cost 3 vext2 <6,6,0,1>, <6,6,0,1> + 1583993678U, // <0,1,6,7>: Cost 2 vext2 <6,7,0,1>, <6,7,0,1> + 1584657311U, // <0,1,6,u>: Cost 2 vext2 <6,u,0,1>, <6,u,0,1> + 2657735672U, // <0,1,7,0>: Cost 3 vext2 <6,7,0,1>, <7,0,1,0> + 2657735808U, // <0,1,7,1>: Cost 3 vext2 <6,7,0,1>, <7,1,7,1> + 2631193772U, // <0,1,7,2>: Cost 3 vext2 <2,3,0,1>, <7,2,3,0> + 2661053667U, // <0,1,7,3>: Cost 3 vext2 <7,3,0,1>, <7,3,0,1> + 2657736038U, // <0,1,7,4>: Cost 3 vext2 <6,7,0,1>, <7,4,5,6> + 3721524621U, // <0,1,7,5>: Cost 4 vext2 <5,1,0,1>, <7,5,1,0> + 2657736158U, // <0,1,7,6>: Cost 3 vext2 <6,7,0,1>, <7,6,1,0> + 2657736300U, // <0,1,7,7>: Cost 3 vext2 <6,7,0,1>, <7,7,7,7> + 2657736322U, // <0,1,7,u>: Cost 3 vext2 <6,7,0,1>, <7,u,1,2> + 1494450278U, // <0,1,u,0>: Cost 2 vext1 <3,0,1,u>, LHS + 1557452590U, // <0,1,u,1>: Cost 2 vext2 <2,3,0,1>, LHS + 2754238254U, // <0,1,u,2>: Cost 3 vuzpl <0,4,1,5>, LHS + 835584U, // <0,1,u,3>: Cost 0 copy LHS + 1494453558U, // <0,1,u,4>: Cost 2 vext1 <3,0,1,u>, RHS + 1557452954U, // <0,1,u,5>: Cost 2 vext2 <2,3,0,1>, RHS + 2754238618U, // <0,1,u,6>: Cost 3 vuzpl <0,4,1,5>, RHS + 1518343168U, // <0,1,u,7>: Cost 2 vext1 <7,0,1,u>, <7,0,1,u> + 835584U, // <0,1,u,u>: Cost 0 copy LHS + 2752299008U, // <0,2,0,0>: Cost 3 vuzpl LHS, <0,0,0,0> + 1544847462U, // <0,2,0,1>: Cost 2 vext2 <0,2,0,2>, LHS + 1678557286U, // <0,2,0,2>: Cost 2 vuzpl LHS, LHS + 2696521165U, // <0,2,0,3>: Cost 3 vext3 <2,0,3,0>, <2,0,3,0> + 2752340172U, // <0,2,0,4>: Cost 3 vuzpl LHS, <0,2,4,6> + 2691876326U, // <0,2,0,5>: Cost 3 vext3 <1,2,3,0>, <2,0,5,7> + 2618589695U, // <0,2,0,6>: Cost 3 vext2 <0,2,0,2>, <0,6,2,7> + 2592093185U, // <0,2,0,7>: Cost 3 vext1 <7,0,2,0>, <7,0,2,0> + 1678557340U, // <0,2,0,u>: Cost 2 vuzpl LHS, LHS + 2618589942U, // <0,2,1,0>: Cost 3 vext2 <0,2,0,2>, <1,0,3,2> + 2752299828U, // <0,2,1,1>: Cost 3 vuzpl LHS, <1,1,1,1> + 2886518376U, // <0,2,1,2>: Cost 3 vzipl LHS, <2,2,2,2> + 2752299766U, // <0,2,1,3>: Cost 3 vuzpl LHS, <1,0,3,2> + 2550295862U, // <0,2,1,4>: Cost 3 vext1 <0,0,2,1>, RHS + 2752340992U, // <0,2,1,5>: Cost 3 vuzpl LHS, <1,3,5,7> + 2886559674U, // <0,2,1,6>: Cost 3 vzipl LHS, <2,6,3,7> + 3934208106U, // <0,2,1,7>: Cost 4 vuzpr <7,0,1,2>, <0,1,2,7> + 2752340771U, // <0,2,1,u>: Cost 3 vuzpl LHS, <1,0,u,2> + 1476558868U, // <0,2,2,0>: Cost 2 vext1 <0,0,2,2>, <0,0,2,2> + 2226628029U, // <0,2,2,1>: Cost 3 vrev <2,0,1,2> + 2752300648U, // <0,2,2,2>: Cost 3 vuzpl LHS, <2,2,2,2> + 3020736114U, // <0,2,2,3>: Cost 3 vtrnl LHS, <2,2,3,3> + 1476562230U, // <0,2,2,4>: Cost 2 vext1 <0,0,2,2>, RHS + 2550304464U, // <0,2,2,5>: Cost 3 vext1 <0,0,2,2>, <5,1,7,3> + 2618591162U, // <0,2,2,6>: Cost 3 vext2 <0,2,0,2>, <2,6,3,7> + 2550305777U, // <0,2,2,7>: Cost 3 vext1 <0,0,2,2>, <7,0,0,2> + 1476564782U, // <0,2,2,u>: Cost 2 vext1 <0,0,2,2>, LHS + 2618591382U, // <0,2,3,0>: Cost 3 vext2 <0,2,0,2>, <3,0,1,2> + 2752301206U, // <0,2,3,1>: Cost 3 vuzpl LHS, <3,0,1,2> + 3826043121U, // <0,2,3,2>: Cost 4 vuzpl LHS, <3,1,2,3> + 2752301468U, // <0,2,3,3>: Cost 3 vuzpl LHS, <3,3,3,3> + 2618591746U, // <0,2,3,4>: Cost 3 vext2 <0,2,0,2>, <3,4,5,6> + 2752301570U, // <0,2,3,5>: Cost 3 vuzpl LHS, <3,4,5,6> + 3830688102U, // <0,2,3,6>: Cost 4 vuzpl LHS, <3,2,6,3> + 2698807012U, // <0,2,3,7>: Cost 3 vext3 <2,3,7,0>, <2,3,7,0> + 2752301269U, // <0,2,3,u>: Cost 3 vuzpl LHS, <3,0,u,2> + 2562261094U, // <0,2,4,0>: Cost 3 vext1 <2,0,2,4>, LHS + 4095313828U, // <0,2,4,1>: Cost 4 vtrnl <0,2,4,6>, <2,6,1,3> + 2226718152U, // <0,2,4,2>: Cost 3 vrev <2,0,2,4> + 2568235169U, // <0,2,4,3>: Cost 3 vext1 <3,0,2,4>, <3,0,2,4> + 2562264374U, // <0,2,4,4>: Cost 3 vext1 <2,0,2,4>, RHS + 1544850742U, // <0,2,4,5>: Cost 2 vext2 <0,2,0,2>, RHS + 1678560566U, // <0,2,4,6>: Cost 2 vuzpl LHS, RHS + 2592125957U, // <0,2,4,7>: Cost 3 vext1 <7,0,2,4>, <7,0,2,4> + 1678560584U, // <0,2,4,u>: Cost 2 vuzpl LHS, RHS + 2691876686U, // <0,2,5,0>: Cost 3 vext3 <1,2,3,0>, <2,5,0,7> + 2618592976U, // <0,2,5,1>: Cost 3 vext2 <0,2,0,2>, <5,1,7,3> + 3765618528U, // <0,2,5,2>: Cost 4 vext3 <1,2,3,0>, <2,5,2,7> + 3765618536U, // <0,2,5,3>: Cost 4 vext3 <1,2,3,0>, <2,5,3,6> + 2618593222U, // <0,2,5,4>: Cost 3 vext2 <0,2,0,2>, <5,4,7,6> + 2752303108U, // <0,2,5,5>: Cost 3 vuzpl LHS, <5,5,5,5> + 2618593378U, // <0,2,5,6>: Cost 3 vext2 <0,2,0,2>, <5,6,7,0> + 2824785206U, // <0,2,5,7>: Cost 3 vuzpr <1,0,3,2>, RHS + 2824785207U, // <0,2,5,u>: Cost 3 vuzpr <1,0,3,2>, RHS + 2752303950U, // <0,2,6,0>: Cost 3 vuzpl LHS, <6,7,0,1> + 3830690081U, // <0,2,6,1>: Cost 4 vuzpl LHS, <6,0,1,2> + 2618593786U, // <0,2,6,2>: Cost 3 vext2 <0,2,0,2>, <6,2,7,3> + 2691876794U, // <0,2,6,3>: Cost 3 vext3 <1,2,3,0>, <2,6,3,7> + 2752303990U, // <0,2,6,4>: Cost 3 vuzpl LHS, <6,7,4,5> + 3830690445U, // <0,2,6,5>: Cost 4 vuzpl LHS, <6,4,5,6> + 2752303928U, // <0,2,6,6>: Cost 3 vuzpl LHS, <6,6,6,6> + 2657743695U, // <0,2,6,7>: Cost 3 vext2 <6,7,0,2>, <6,7,0,2> + 2691876839U, // <0,2,6,u>: Cost 3 vext3 <1,2,3,0>, <2,6,u,7> + 2659070961U, // <0,2,7,0>: Cost 3 vext2 <7,0,0,2>, <7,0,0,2> + 2659734594U, // <0,2,7,1>: Cost 3 vext2 <7,1,0,2>, <7,1,0,2> + 3734140051U, // <0,2,7,2>: Cost 4 vext2 <7,2,0,2>, <7,2,0,2> + 2701166596U, // <0,2,7,3>: Cost 3 vext3 <2,7,3,0>, <2,7,3,0> + 2662389094U, // <0,2,7,4>: Cost 3 vext2 <7,5,0,2>, <7,4,5,6> + 2662389126U, // <0,2,7,5>: Cost 3 vext2 <7,5,0,2>, <7,5,0,2> + 3736794583U, // <0,2,7,6>: Cost 4 vext2 <7,6,0,2>, <7,6,0,2> + 2752304748U, // <0,2,7,7>: Cost 3 vuzpl LHS, <7,7,7,7> + 2659070961U, // <0,2,7,u>: Cost 3 vext2 <7,0,0,2>, <7,0,0,2> + 1476608026U, // <0,2,u,0>: Cost 2 vext1 <0,0,2,u>, <0,0,2,u> + 1544853294U, // <0,2,u,1>: Cost 2 vext2 <0,2,0,2>, LHS + 1678563118U, // <0,2,u,2>: Cost 2 vuzpl LHS, LHS + 3021178482U, // <0,2,u,3>: Cost 3 vtrnl LHS, <2,2,3,3> + 1476611382U, // <0,2,u,4>: Cost 2 vext1 <0,0,2,u>, RHS + 1544853658U, // <0,2,u,5>: Cost 2 vext2 <0,2,0,2>, RHS + 1678563482U, // <0,2,u,6>: Cost 2 vuzpl LHS, RHS + 2824785449U, // <0,2,u,7>: Cost 3 vuzpr <1,0,3,2>, RHS + 1678563172U, // <0,2,u,u>: Cost 2 vuzpl LHS, LHS + 2556329984U, // <0,3,0,0>: Cost 3 vext1 <1,0,3,0>, <0,0,0,0> + 2686421142U, // <0,3,0,1>: Cost 3 vext3 <0,3,1,0>, <3,0,1,2> + 2562303437U, // <0,3,0,2>: Cost 3 vext1 <2,0,3,0>, <2,0,3,0> + 4094986652U, // <0,3,0,3>: Cost 4 vtrnl <0,2,0,2>, <3,3,3,3> + 2556333366U, // <0,3,0,4>: Cost 3 vext1 <1,0,3,0>, RHS + 4094986754U, // <0,3,0,5>: Cost 4 vtrnl <0,2,0,2>, <3,4,5,6> + 3798796488U, // <0,3,0,6>: Cost 4 vext3 <6,7,3,0>, <3,0,6,7> + 3776530634U, // <0,3,0,7>: Cost 4 vext3 <3,0,7,0>, <3,0,7,0> + 2556335918U, // <0,3,0,u>: Cost 3 vext1 <1,0,3,0>, LHS + 2886518934U, // <0,3,1,0>: Cost 3 vzipl LHS, <3,0,1,2> + 2556338933U, // <0,3,1,1>: Cost 3 vext1 <1,0,3,1>, <1,0,3,1> + 2691877105U, // <0,3,1,2>: Cost 3 vext3 <1,2,3,0>, <3,1,2,3> + 2886519196U, // <0,3,1,3>: Cost 3 vzipl LHS, <3,3,3,3> + 2886519298U, // <0,3,1,4>: Cost 3 vzipl LHS, <3,4,5,6> + 4095740418U, // <0,3,1,5>: Cost 4 vtrnl <0,3,1,4>, <3,4,5,6> + 3659944242U, // <0,3,1,6>: Cost 4 vext1 <6,0,3,1>, <6,0,3,1> + 3769600286U, // <0,3,1,7>: Cost 4 vext3 <1,u,3,0>, <3,1,7,3> + 2886519582U, // <0,3,1,u>: Cost 3 vzipl LHS, <3,u,1,2> + 1482604646U, // <0,3,2,0>: Cost 2 vext1 <1,0,3,2>, LHS + 1482605302U, // <0,3,2,1>: Cost 2 vext1 <1,0,3,2>, <1,0,3,2> + 2556348008U, // <0,3,2,2>: Cost 3 vext1 <1,0,3,2>, <2,2,2,2> + 3020736924U, // <0,3,2,3>: Cost 3 vtrnl LHS, <3,3,3,3> + 1482607926U, // <0,3,2,4>: Cost 2 vext1 <1,0,3,2>, RHS + 3020737026U, // <0,3,2,5>: Cost 3 vtrnl LHS, <3,4,5,6> + 2598154746U, // <0,3,2,6>: Cost 3 vext1 , <6,2,7,3> + 2598155258U, // <0,3,2,7>: Cost 3 vext1 , <7,0,1,2> + 1482610478U, // <0,3,2,u>: Cost 2 vext1 <1,0,3,2>, LHS + 3692341398U, // <0,3,3,0>: Cost 4 vext2 <0,2,0,3>, <3,0,1,2> + 2635851999U, // <0,3,3,1>: Cost 3 vext2 <3,1,0,3>, <3,1,0,3> + 3636069840U, // <0,3,3,2>: Cost 4 vext1 <2,0,3,3>, <2,0,3,3> + 2691877276U, // <0,3,3,3>: Cost 3 vext3 <1,2,3,0>, <3,3,3,3> + 3961522690U, // <0,3,3,4>: Cost 4 vzipl <0,3,1,4>, <3,4,5,6> + 3826797058U, // <0,3,3,5>: Cost 4 vuzpl <0,2,3,5>, <3,4,5,6> + 3703622282U, // <0,3,3,6>: Cost 4 vext2 <2,1,0,3>, <3,6,2,7> + 3769600452U, // <0,3,3,7>: Cost 4 vext3 <1,u,3,0>, <3,3,7,7> + 2640497430U, // <0,3,3,u>: Cost 3 vext2 <3,u,0,3>, <3,u,0,3> + 3962194070U, // <0,3,4,0>: Cost 4 vzipl <0,4,1,5>, <3,0,1,2> + 2232617112U, // <0,3,4,1>: Cost 3 vrev <3,0,1,4> + 2232690849U, // <0,3,4,2>: Cost 3 vrev <3,0,2,4> + 4095314332U, // <0,3,4,3>: Cost 4 vtrnl <0,2,4,6>, <3,3,3,3> + 3962194434U, // <0,3,4,4>: Cost 4 vzipl <0,4,1,5>, <3,4,5,6> + 2691877378U, // <0,3,4,5>: Cost 3 vext3 <1,2,3,0>, <3,4,5,6> + 3826765110U, // <0,3,4,6>: Cost 4 vuzpl <0,2,3,1>, RHS + 3665941518U, // <0,3,4,7>: Cost 4 vext1 <7,0,3,4>, <7,0,3,4> + 2691877405U, // <0,3,4,u>: Cost 3 vext3 <1,2,3,0>, <3,4,u,6> + 3630112870U, // <0,3,5,0>: Cost 4 vext1 <1,0,3,5>, LHS + 3630113526U, // <0,3,5,1>: Cost 4 vext1 <1,0,3,5>, <1,0,3,2> + 4035199734U, // <0,3,5,2>: Cost 4 vzipr <1,4,0,5>, <1,0,3,2> + 3769600578U, // <0,3,5,3>: Cost 4 vext3 <1,u,3,0>, <3,5,3,7> + 2232846516U, // <0,3,5,4>: Cost 3 vrev <3,0,4,5> + 3779037780U, // <0,3,5,5>: Cost 4 vext3 <3,4,5,0>, <3,5,5,7> + 2718714461U, // <0,3,5,6>: Cost 3 vext3 <5,6,7,0>, <3,5,6,7> + 2706106975U, // <0,3,5,7>: Cost 3 vext3 <3,5,7,0>, <3,5,7,0> + 2233141464U, // <0,3,5,u>: Cost 3 vrev <3,0,u,5> + 2691877496U, // <0,3,6,0>: Cost 3 vext3 <1,2,3,0>, <3,6,0,7> + 3727511914U, // <0,3,6,1>: Cost 4 vext2 <6,1,0,3>, <6,1,0,3> + 3765619338U, // <0,3,6,2>: Cost 4 vext3 <1,2,3,0>, <3,6,2,7> + 3765619347U, // <0,3,6,3>: Cost 4 vext3 <1,2,3,0>, <3,6,3,7> + 3765987996U, // <0,3,6,4>: Cost 4 vext3 <1,2,u,0>, <3,6,4,7> + 3306670270U, // <0,3,6,5>: Cost 4 vrev <3,0,5,6> + 3792456365U, // <0,3,6,6>: Cost 4 vext3 <5,6,7,0>, <3,6,6,6> + 2706770608U, // <0,3,6,7>: Cost 3 vext3 <3,6,7,0>, <3,6,7,0> + 2706844345U, // <0,3,6,u>: Cost 3 vext3 <3,6,u,0>, <3,6,u,0> + 3769600707U, // <0,3,7,0>: Cost 4 vext3 <1,u,3,0>, <3,7,0,1> + 2659742787U, // <0,3,7,1>: Cost 3 vext2 <7,1,0,3>, <7,1,0,3> + 3636102612U, // <0,3,7,2>: Cost 4 vext1 <2,0,3,7>, <2,0,3,7> + 3769600740U, // <0,3,7,3>: Cost 4 vext3 <1,u,3,0>, <3,7,3,7> + 3769600747U, // <0,3,7,4>: Cost 4 vext3 <1,u,3,0>, <3,7,4,5> + 3769600758U, // <0,3,7,5>: Cost 4 vext3 <1,u,3,0>, <3,7,5,7> + 3659993400U, // <0,3,7,6>: Cost 4 vext1 <6,0,3,7>, <6,0,3,7> + 3781176065U, // <0,3,7,7>: Cost 4 vext3 <3,7,7,0>, <3,7,7,0> + 2664388218U, // <0,3,7,u>: Cost 3 vext2 <7,u,0,3>, <7,u,0,3> + 1482653798U, // <0,3,u,0>: Cost 2 vext1 <1,0,3,u>, LHS + 1482654460U, // <0,3,u,1>: Cost 2 vext1 <1,0,3,u>, <1,0,3,u> + 2556397160U, // <0,3,u,2>: Cost 3 vext1 <1,0,3,u>, <2,2,2,2> + 3021179292U, // <0,3,u,3>: Cost 3 vtrnl LHS, <3,3,3,3> + 1482657078U, // <0,3,u,4>: Cost 2 vext1 <1,0,3,u>, RHS + 3021179394U, // <0,3,u,5>: Cost 3 vtrnl LHS, <3,4,5,6> + 2598203898U, // <0,3,u,6>: Cost 3 vext1 , <6,2,7,3> + 2708097874U, // <0,3,u,7>: Cost 3 vext3 <3,u,7,0>, <3,u,7,0> + 1482659630U, // <0,3,u,u>: Cost 2 vext1 <1,0,3,u>, LHS + 2617278468U, // <0,4,0,0>: Cost 3 vext2 <0,0,0,4>, <0,0,0,4> + 2618605670U, // <0,4,0,1>: Cost 3 vext2 <0,2,0,4>, LHS + 2618605734U, // <0,4,0,2>: Cost 3 vext2 <0,2,0,4>, <0,2,0,4> + 3642091695U, // <0,4,0,3>: Cost 4 vext1 <3,0,4,0>, <3,0,4,0> + 2753134796U, // <0,4,0,4>: Cost 3 vuzpl <0,2,4,6>, <0,2,4,6> + 2718714770U, // <0,4,0,5>: Cost 3 vext3 <5,6,7,0>, <4,0,5,1> + 3021245750U, // <0,4,0,6>: Cost 3 vtrnl <0,2,0,2>, RHS + 3665982483U, // <0,4,0,7>: Cost 4 vext1 <7,0,4,0>, <7,0,4,0> + 3021245768U, // <0,4,0,u>: Cost 3 vtrnl <0,2,0,2>, RHS + 2568355942U, // <0,4,1,0>: Cost 3 vext1 <3,0,4,1>, LHS + 3692348212U, // <0,4,1,1>: Cost 4 vext2 <0,2,0,4>, <1,1,1,1> + 3692348310U, // <0,4,1,2>: Cost 4 vext2 <0,2,0,4>, <1,2,3,0> + 2568358064U, // <0,4,1,3>: Cost 3 vext1 <3,0,4,1>, <3,0,4,1> + 2568359222U, // <0,4,1,4>: Cost 3 vext1 <3,0,4,1>, RHS + 1812778294U, // <0,4,1,5>: Cost 2 vzipl LHS, RHS + 3022671158U, // <0,4,1,6>: Cost 3 vtrnl <0,4,1,5>, RHS + 2592248852U, // <0,4,1,7>: Cost 3 vext1 <7,0,4,1>, <7,0,4,1> + 1812778537U, // <0,4,1,u>: Cost 2 vzipl LHS, RHS + 2568364134U, // <0,4,2,0>: Cost 3 vext1 <3,0,4,2>, LHS + 2238573423U, // <0,4,2,1>: Cost 3 vrev <4,0,1,2> + 3692349032U, // <0,4,2,2>: Cost 4 vext2 <0,2,0,4>, <2,2,2,2> + 2631214761U, // <0,4,2,3>: Cost 3 vext2 <2,3,0,4>, <2,3,0,4> + 2568367414U, // <0,4,2,4>: Cost 3 vext1 <3,0,4,2>, RHS + 2887028022U, // <0,4,2,5>: Cost 3 vzipl <0,2,0,2>, RHS + 1946996022U, // <0,4,2,6>: Cost 2 vtrnl LHS, RHS + 2592257045U, // <0,4,2,7>: Cost 3 vext1 <7,0,4,2>, <7,0,4,2> + 1946996040U, // <0,4,2,u>: Cost 2 vtrnl LHS, RHS + 3692349590U, // <0,4,3,0>: Cost 4 vext2 <0,2,0,4>, <3,0,1,2> + 3826878614U, // <0,4,3,1>: Cost 4 vuzpl <0,2,4,6>, <3,0,1,2> + 3826878625U, // <0,4,3,2>: Cost 4 vuzpl <0,2,4,6>, <3,0,2,4> + 3692349852U, // <0,4,3,3>: Cost 4 vext2 <0,2,0,4>, <3,3,3,3> + 3692349954U, // <0,4,3,4>: Cost 4 vext2 <0,2,0,4>, <3,4,5,6> + 3826878978U, // <0,4,3,5>: Cost 4 vuzpl <0,2,4,6>, <3,4,5,6> + 4095200566U, // <0,4,3,6>: Cost 4 vtrnl <0,2,3,1>, RHS + 3713583814U, // <0,4,3,7>: Cost 4 vext2 <3,7,0,4>, <3,7,0,4> + 3692350238U, // <0,4,3,u>: Cost 4 vext2 <0,2,0,4>, <3,u,1,2> + 2550464552U, // <0,4,4,0>: Cost 3 vext1 <0,0,4,4>, <0,0,4,4> + 3962194914U, // <0,4,4,1>: Cost 4 vzipl <0,4,1,5>, <4,1,5,0> + 3693677631U, // <0,4,4,2>: Cost 4 vext2 <0,4,0,4>, <4,2,6,3> + 3642124467U, // <0,4,4,3>: Cost 4 vext1 <3,0,4,4>, <3,0,4,4> + 2718715088U, // <0,4,4,4>: Cost 3 vext3 <5,6,7,0>, <4,4,4,4> + 2618608950U, // <0,4,4,5>: Cost 3 vext2 <0,2,0,4>, RHS + 2753137974U, // <0,4,4,6>: Cost 3 vuzpl <0,2,4,6>, RHS + 3666015255U, // <0,4,4,7>: Cost 4 vext1 <7,0,4,4>, <7,0,4,4> + 2618609193U, // <0,4,4,u>: Cost 3 vext2 <0,2,0,4>, RHS + 2568388710U, // <0,4,5,0>: Cost 3 vext1 <3,0,4,5>, LHS + 2568389526U, // <0,4,5,1>: Cost 3 vext1 <3,0,4,5>, <1,2,3,0> + 3636159963U, // <0,4,5,2>: Cost 4 vext1 <2,0,4,5>, <2,0,4,5> + 2568390836U, // <0,4,5,3>: Cost 3 vext1 <3,0,4,5>, <3,0,4,5> + 2568391990U, // <0,4,5,4>: Cost 3 vext1 <3,0,4,5>, RHS + 2718715180U, // <0,4,5,5>: Cost 3 vext3 <5,6,7,0>, <4,5,5,6> + 1618136374U, // <0,4,5,6>: Cost 2 vext3 <1,2,3,0>, RHS + 2592281624U, // <0,4,5,7>: Cost 3 vext1 <7,0,4,5>, <7,0,4,5> + 1618136392U, // <0,4,5,u>: Cost 2 vext3 <1,2,3,0>, RHS + 2550480938U, // <0,4,6,0>: Cost 3 vext1 <0,0,4,6>, <0,0,4,6> + 3826880801U, // <0,4,6,1>: Cost 4 vuzpl <0,2,4,6>, <6,0,1,2> + 2562426332U, // <0,4,6,2>: Cost 3 vext1 <2,0,4,6>, <2,0,4,6> + 3786190181U, // <0,4,6,3>: Cost 4 vext3 <4,6,3,0>, <4,6,3,0> + 2718715252U, // <0,4,6,4>: Cost 3 vext3 <5,6,7,0>, <4,6,4,6> + 3826881165U, // <0,4,6,5>: Cost 4 vuzpl <0,2,4,6>, <6,4,5,6> + 2712669568U, // <0,4,6,6>: Cost 3 vext3 <4,6,6,0>, <4,6,6,0> + 2657760081U, // <0,4,6,7>: Cost 3 vext2 <6,7,0,4>, <6,7,0,4> + 2718715284U, // <0,4,6,u>: Cost 3 vext3 <5,6,7,0>, <4,6,u,2> + 3654090854U, // <0,4,7,0>: Cost 4 vext1 <5,0,4,7>, LHS + 3934229326U, // <0,4,7,1>: Cost 4 vuzpr <7,0,1,4>, <6,7,0,1> + 3734156437U, // <0,4,7,2>: Cost 4 vext2 <7,2,0,4>, <7,2,0,4> + 3734820070U, // <0,4,7,3>: Cost 4 vext2 <7,3,0,4>, <7,3,0,4> + 3654094134U, // <0,4,7,4>: Cost 4 vext1 <5,0,4,7>, RHS + 2713259464U, // <0,4,7,5>: Cost 3 vext3 <4,7,5,0>, <4,7,5,0> + 2713333201U, // <0,4,7,6>: Cost 3 vext3 <4,7,6,0>, <4,7,6,0> + 3654095866U, // <0,4,7,7>: Cost 4 vext1 <5,0,4,7>, <7,0,1,2> + 2713259464U, // <0,4,7,u>: Cost 3 vext3 <4,7,5,0>, <4,7,5,0> + 2568413286U, // <0,4,u,0>: Cost 3 vext1 <3,0,4,u>, LHS + 2618611502U, // <0,4,u,1>: Cost 3 vext2 <0,2,0,4>, LHS + 2753140526U, // <0,4,u,2>: Cost 3 vuzpl <0,2,4,6>, LHS + 2568415415U, // <0,4,u,3>: Cost 3 vext1 <3,0,4,u>, <3,0,4,u> + 2568416566U, // <0,4,u,4>: Cost 3 vext1 <3,0,4,u>, RHS + 1817423158U, // <0,4,u,5>: Cost 2 vzipl LHS, RHS + 1947438390U, // <0,4,u,6>: Cost 2 vtrnl LHS, RHS + 2592306203U, // <0,4,u,7>: Cost 3 vext1 <7,0,4,u>, <7,0,4,u> + 1947438408U, // <0,4,u,u>: Cost 2 vtrnl LHS, RHS + 3630219264U, // <0,5,0,0>: Cost 4 vext1 <1,0,5,0>, <0,0,0,0> + 2625912934U, // <0,5,0,1>: Cost 3 vext2 <1,4,0,5>, LHS + 3692355748U, // <0,5,0,2>: Cost 4 vext2 <0,2,0,5>, <0,2,0,2> + 3693019384U, // <0,5,0,3>: Cost 4 vext2 <0,3,0,5>, <0,3,0,5> + 3630222646U, // <0,5,0,4>: Cost 4 vext1 <1,0,5,0>, RHS + 3699655062U, // <0,5,0,5>: Cost 4 vext2 <1,4,0,5>, <0,5,0,1> + 2718715508U, // <0,5,0,6>: Cost 3 vext3 <5,6,7,0>, <5,0,6,1> + 3087011126U, // <0,5,0,7>: Cost 3 vtrnr <0,0,0,0>, RHS + 2625913501U, // <0,5,0,u>: Cost 3 vext2 <1,4,0,5>, LHS + 1500659814U, // <0,5,1,0>: Cost 2 vext1 <4,0,5,1>, LHS + 2886520528U, // <0,5,1,1>: Cost 3 vzipl LHS, <5,1,7,3> + 2574403176U, // <0,5,1,2>: Cost 3 vext1 <4,0,5,1>, <2,2,2,2> + 2574403734U, // <0,5,1,3>: Cost 3 vext1 <4,0,5,1>, <3,0,1,2> + 1500662674U, // <0,5,1,4>: Cost 2 vext1 <4,0,5,1>, <4,0,5,1> + 2886520836U, // <0,5,1,5>: Cost 3 vzipl LHS, <5,5,5,5> + 2886520930U, // <0,5,1,6>: Cost 3 vzipl LHS, <5,6,7,0> + 2718715600U, // <0,5,1,7>: Cost 3 vext3 <5,6,7,0>, <5,1,7,3> + 1500665646U, // <0,5,1,u>: Cost 2 vext1 <4,0,5,1>, LHS + 2556493926U, // <0,5,2,0>: Cost 3 vext1 <1,0,5,2>, LHS + 2244546120U, // <0,5,2,1>: Cost 3 vrev <5,0,1,2> + 3692357256U, // <0,5,2,2>: Cost 4 vext2 <0,2,0,5>, <2,2,5,7> + 2568439994U, // <0,5,2,3>: Cost 3 vext1 <3,0,5,2>, <3,0,5,2> + 2556497206U, // <0,5,2,4>: Cost 3 vext1 <1,0,5,2>, RHS + 3020738564U, // <0,5,2,5>: Cost 3 vtrnl LHS, <5,5,5,5> + 4027877161U, // <0,5,2,6>: Cost 4 vzipr <0,2,0,2>, <2,4,5,6> + 3093220662U, // <0,5,2,7>: Cost 3 vtrnr <1,0,3,2>, RHS + 3093220663U, // <0,5,2,u>: Cost 3 vtrnr <1,0,3,2>, RHS + 3699656854U, // <0,5,3,0>: Cost 4 vext2 <1,4,0,5>, <3,0,1,2> + 3699656927U, // <0,5,3,1>: Cost 4 vext2 <1,4,0,5>, <3,1,0,3> + 3699657006U, // <0,5,3,2>: Cost 4 vext2 <1,4,0,5>, <3,2,0,1> + 3699657116U, // <0,5,3,3>: Cost 4 vext2 <1,4,0,5>, <3,3,3,3> + 2637859284U, // <0,5,3,4>: Cost 3 vext2 <3,4,0,5>, <3,4,0,5> + 3790319453U, // <0,5,3,5>: Cost 4 vext3 <5,3,5,0>, <5,3,5,0> + 3699657354U, // <0,5,3,6>: Cost 4 vext2 <1,4,0,5>, <3,6,2,7> + 2716725103U, // <0,5,3,7>: Cost 3 vext3 <5,3,7,0>, <5,3,7,0> + 2716798840U, // <0,5,3,u>: Cost 3 vext3 <5,3,u,0>, <5,3,u,0> + 2661747602U, // <0,5,4,0>: Cost 3 vext2 <7,4,0,5>, <4,0,5,1> + 3630252810U, // <0,5,4,1>: Cost 4 vext1 <1,0,5,4>, <1,0,5,4> + 3636225507U, // <0,5,4,2>: Cost 4 vext1 <2,0,5,4>, <2,0,5,4> + 3716910172U, // <0,5,4,3>: Cost 4 vext2 <4,3,0,5>, <4,3,0,5> + 3962195892U, // <0,5,4,4>: Cost 4 vzipl <0,4,1,5>, <5,4,5,6> + 2625916214U, // <0,5,4,5>: Cost 3 vext2 <1,4,0,5>, RHS + 3718901071U, // <0,5,4,6>: Cost 4 vext2 <4,6,0,5>, <4,6,0,5> + 2718715846U, // <0,5,4,7>: Cost 3 vext3 <5,6,7,0>, <5,4,7,6> + 2625916457U, // <0,5,4,u>: Cost 3 vext2 <1,4,0,5>, RHS + 3791278034U, // <0,5,5,0>: Cost 4 vext3 <5,5,0,0>, <5,5,0,0> + 3791351771U, // <0,5,5,1>: Cost 4 vext3 <5,5,1,0>, <5,5,1,0> + 3318386260U, // <0,5,5,2>: Cost 4 vrev <5,0,2,5> + 3791499245U, // <0,5,5,3>: Cost 4 vext3 <5,5,3,0>, <5,5,3,0> + 3318533734U, // <0,5,5,4>: Cost 4 vrev <5,0,4,5> + 2718715908U, // <0,5,5,5>: Cost 3 vext3 <5,6,7,0>, <5,5,5,5> + 2657767522U, // <0,5,5,6>: Cost 3 vext2 <6,7,0,5>, <5,6,7,0> + 2718715928U, // <0,5,5,7>: Cost 3 vext3 <5,6,7,0>, <5,5,7,7> + 2718715937U, // <0,5,5,u>: Cost 3 vext3 <5,6,7,0>, <5,5,u,7> + 2592358502U, // <0,5,6,0>: Cost 3 vext1 <7,0,5,6>, LHS + 3792015404U, // <0,5,6,1>: Cost 4 vext3 <5,6,1,0>, <5,6,1,0> + 3731509754U, // <0,5,6,2>: Cost 4 vext2 <6,7,0,5>, <6,2,7,3> + 3785748546U, // <0,5,6,3>: Cost 4 vext3 <4,5,6,0>, <5,6,3,4> + 2592361782U, // <0,5,6,4>: Cost 3 vext1 <7,0,5,6>, RHS + 2592362594U, // <0,5,6,5>: Cost 3 vext1 <7,0,5,6>, <5,6,7,0> + 3785748576U, // <0,5,6,6>: Cost 4 vext3 <4,5,6,0>, <5,6,6,7> + 1644974178U, // <0,5,6,7>: Cost 2 vext3 <5,6,7,0>, <5,6,7,0> + 1645047915U, // <0,5,6,u>: Cost 2 vext3 <5,6,u,0>, <5,6,u,0> + 2562506854U, // <0,5,7,0>: Cost 3 vext1 <2,0,5,7>, LHS + 2562507670U, // <0,5,7,1>: Cost 3 vext1 <2,0,5,7>, <1,2,3,0> + 2562508262U, // <0,5,7,2>: Cost 3 vext1 <2,0,5,7>, <2,0,5,7> + 3636250774U, // <0,5,7,3>: Cost 4 vext1 <2,0,5,7>, <3,0,1,2> + 2562510134U, // <0,5,7,4>: Cost 3 vext1 <2,0,5,7>, RHS + 2718716072U, // <0,5,7,5>: Cost 3 vext3 <5,6,7,0>, <5,7,5,7> + 2718716074U, // <0,5,7,6>: Cost 3 vext3 <5,6,7,0>, <5,7,6,0> + 2719379635U, // <0,5,7,7>: Cost 3 vext3 <5,7,7,0>, <5,7,7,0> + 2562512686U, // <0,5,7,u>: Cost 3 vext1 <2,0,5,7>, LHS + 1500717158U, // <0,5,u,0>: Cost 2 vext1 <4,0,5,u>, LHS + 2625918766U, // <0,5,u,1>: Cost 3 vext2 <1,4,0,5>, LHS + 2719674583U, // <0,5,u,2>: Cost 3 vext3 <5,u,2,0>, <5,u,2,0> + 2568489152U, // <0,5,u,3>: Cost 3 vext1 <3,0,5,u>, <3,0,5,u> + 1500720025U, // <0,5,u,4>: Cost 2 vext1 <4,0,5,u>, <4,0,5,u> + 2625919130U, // <0,5,u,5>: Cost 3 vext2 <1,4,0,5>, RHS + 2586407243U, // <0,5,u,6>: Cost 3 vext1 <6,0,5,u>, <6,0,5,u> + 1646301444U, // <0,5,u,7>: Cost 2 vext3 <5,u,7,0>, <5,u,7,0> + 1646375181U, // <0,5,u,u>: Cost 2 vext3 <5,u,u,0>, <5,u,u,0> + 2586411110U, // <0,6,0,0>: Cost 3 vext1 <6,0,6,0>, LHS + 2619949158U, // <0,6,0,1>: Cost 3 vext2 <0,4,0,6>, LHS + 2619949220U, // <0,6,0,2>: Cost 3 vext2 <0,4,0,6>, <0,2,0,2> + 3785748789U, // <0,6,0,3>: Cost 4 vext3 <4,5,6,0>, <6,0,3,4> + 2619949386U, // <0,6,0,4>: Cost 3 vext2 <0,4,0,6>, <0,4,0,6> + 2586415202U, // <0,6,0,5>: Cost 3 vext1 <6,0,6,0>, <5,6,7,0> + 2586415436U, // <0,6,0,6>: Cost 3 vext1 <6,0,6,0>, <6,0,6,0> + 2952793398U, // <0,6,0,7>: Cost 3 vzipr <0,0,0,0>, RHS + 2619949725U, // <0,6,0,u>: Cost 3 vext2 <0,4,0,6>, LHS + 2562531430U, // <0,6,1,0>: Cost 3 vext1 <2,0,6,1>, LHS + 3693691700U, // <0,6,1,1>: Cost 4 vext2 <0,4,0,6>, <1,1,1,1> + 2886521338U, // <0,6,1,2>: Cost 3 vzipl LHS, <6,2,7,3> + 3693691864U, // <0,6,1,3>: Cost 4 vext2 <0,4,0,6>, <1,3,1,3> + 2562534710U, // <0,6,1,4>: Cost 3 vext1 <2,0,6,1>, RHS + 2580450932U, // <0,6,1,5>: Cost 3 vext1 <5,0,6,1>, <5,0,6,1> + 2886521656U, // <0,6,1,6>: Cost 3 vzipl LHS, <6,6,6,6> + 2966736182U, // <0,6,1,7>: Cost 3 vzipr <2,3,0,1>, RHS + 2966736183U, // <0,6,1,u>: Cost 3 vzipr <2,3,0,1>, RHS + 1500741734U, // <0,6,2,0>: Cost 2 vext1 <4,0,6,2>, LHS + 2250518817U, // <0,6,2,1>: Cost 3 vrev <6,0,1,2> + 2574485096U, // <0,6,2,2>: Cost 3 vext1 <4,0,6,2>, <2,2,2,2> + 2631894694U, // <0,6,2,3>: Cost 3 vext2 <2,4,0,6>, <2,3,0,1> + 1500744604U, // <0,6,2,4>: Cost 2 vext1 <4,0,6,2>, <4,0,6,2> + 2574487248U, // <0,6,2,5>: Cost 3 vext1 <4,0,6,2>, <5,1,7,3> + 3020739384U, // <0,6,2,6>: Cost 3 vtrnl LHS, <6,6,6,6> + 2954136886U, // <0,6,2,7>: Cost 3 vzipr <0,2,0,2>, RHS + 1500747566U, // <0,6,2,u>: Cost 2 vext1 <4,0,6,2>, LHS + 3693693078U, // <0,6,3,0>: Cost 4 vext2 <0,4,0,6>, <3,0,1,2> + 3705637136U, // <0,6,3,1>: Cost 4 vext2 <2,4,0,6>, <3,1,5,7> + 3705637192U, // <0,6,3,2>: Cost 4 vext2 <2,4,0,6>, <3,2,3,0> + 3693693340U, // <0,6,3,3>: Cost 4 vext2 <0,4,0,6>, <3,3,3,3> + 2637867477U, // <0,6,3,4>: Cost 3 vext2 <3,4,0,6>, <3,4,0,6> + 3705637424U, // <0,6,3,5>: Cost 4 vext2 <2,4,0,6>, <3,5,1,7> + 3666154056U, // <0,6,3,6>: Cost 4 vext1 <7,0,6,3>, <6,3,7,0> + 2722697800U, // <0,6,3,7>: Cost 3 vext3 <6,3,7,0>, <6,3,7,0> + 2722771537U, // <0,6,3,u>: Cost 3 vext3 <6,3,u,0>, <6,3,u,0> + 2562556006U, // <0,6,4,0>: Cost 3 vext1 <2,0,6,4>, LHS + 4095316257U, // <0,6,4,1>: Cost 4 vtrnl <0,2,4,6>, <6,0,1,2> + 2562557420U, // <0,6,4,2>: Cost 3 vext1 <2,0,6,4>, <2,0,6,4> + 3636299926U, // <0,6,4,3>: Cost 4 vext1 <2,0,6,4>, <3,0,1,2> + 2562559286U, // <0,6,4,4>: Cost 3 vext1 <2,0,6,4>, RHS + 2619952438U, // <0,6,4,5>: Cost 3 vext2 <0,4,0,6>, RHS + 2723287696U, // <0,6,4,6>: Cost 3 vext3 <6,4,6,0>, <6,4,6,0> + 4027895094U, // <0,6,4,7>: Cost 4 vzipr <0,2,0,4>, RHS + 2619952681U, // <0,6,4,u>: Cost 3 vext2 <0,4,0,6>, RHS + 2718716594U, // <0,6,5,0>: Cost 3 vext3 <5,6,7,0>, <6,5,0,7> + 3648250774U, // <0,6,5,1>: Cost 4 vext1 <4,0,6,5>, <1,2,3,0> + 3792458436U, // <0,6,5,2>: Cost 4 vext3 <5,6,7,0>, <6,5,2,7> + 3705638767U, // <0,6,5,3>: Cost 5 vext2 <2,4,0,6>, <5,3,7,0> + 3648252831U, // <0,6,5,4>: Cost 4 vext1 <4,0,6,5>, <4,0,6,5> + 3797619416U, // <0,6,5,5>: Cost 4 vext3 <6,5,5,0>, <6,5,5,0> + 3792458472U, // <0,6,5,6>: Cost 4 vext3 <5,6,7,0>, <6,5,6,7> + 4035202358U, // <0,6,5,7>: Cost 4 vzipr <1,4,0,5>, RHS + 2718716594U, // <0,6,5,u>: Cost 3 vext3 <5,6,7,0>, <6,5,0,7> + 3786412796U, // <0,6,6,0>: Cost 4 vext3 <4,6,6,0>, <6,6,0,0> + 3792458504U, // <0,6,6,1>: Cost 4 vext3 <5,6,7,0>, <6,6,1,3> + 3728200126U, // <0,6,6,2>: Cost 4 vext2 <6,2,0,6>, <6,2,0,6> + 3798135575U, // <0,6,6,3>: Cost 4 vext3 <6,6,3,0>, <6,6,3,0> + 3786412836U, // <0,6,6,4>: Cost 4 vext3 <4,6,6,0>, <6,6,4,4> + 3792458543U, // <0,6,6,5>: Cost 4 vext3 <5,6,7,0>, <6,6,5,6> + 2718716728U, // <0,6,6,6>: Cost 3 vext3 <5,6,7,0>, <6,6,6,6> + 2718716738U, // <0,6,6,7>: Cost 3 vext3 <5,6,7,0>, <6,6,7,7> + 2718716747U, // <0,6,6,u>: Cost 3 vext3 <5,6,7,0>, <6,6,u,7> + 2718716750U, // <0,6,7,0>: Cost 3 vext3 <5,6,7,0>, <6,7,0,1> + 2724909910U, // <0,6,7,1>: Cost 3 vext3 <6,7,1,0>, <6,7,1,0> + 3636323823U, // <0,6,7,2>: Cost 4 vext1 <2,0,6,7>, <2,0,6,7> + 2725057384U, // <0,6,7,3>: Cost 3 vext3 <6,7,3,0>, <6,7,3,0> + 2718716790U, // <0,6,7,4>: Cost 3 vext3 <5,6,7,0>, <6,7,4,5> + 2718716800U, // <0,6,7,5>: Cost 3 vext3 <5,6,7,0>, <6,7,5,6> + 3792458629U, // <0,6,7,6>: Cost 4 vext3 <5,6,7,0>, <6,7,6,2> + 2725352332U, // <0,6,7,7>: Cost 3 vext3 <6,7,7,0>, <6,7,7,0> + 2718716822U, // <0,6,7,u>: Cost 3 vext3 <5,6,7,0>, <6,7,u,1> + 1500790886U, // <0,6,u,0>: Cost 2 vext1 <4,0,6,u>, LHS + 2619954990U, // <0,6,u,1>: Cost 3 vext2 <0,4,0,6>, LHS + 2562590192U, // <0,6,u,2>: Cost 3 vext1 <2,0,6,u>, <2,0,6,u> + 2725721017U, // <0,6,u,3>: Cost 3 vext3 <6,u,3,0>, <6,u,3,0> + 1500793762U, // <0,6,u,4>: Cost 2 vext1 <4,0,6,u>, <4,0,6,u> + 2619955354U, // <0,6,u,5>: Cost 3 vext2 <0,4,0,6>, RHS + 2725942228U, // <0,6,u,6>: Cost 3 vext3 <6,u,6,0>, <6,u,6,0> + 2954186038U, // <0,6,u,7>: Cost 3 vzipr <0,2,0,u>, RHS + 1500796718U, // <0,6,u,u>: Cost 2 vext1 <4,0,6,u>, LHS + 2256401391U, // <0,7,0,0>: Cost 3 vrev <7,0,0,0> + 2632564838U, // <0,7,0,1>: Cost 3 vext2 <2,5,0,7>, LHS + 2256548865U, // <0,7,0,2>: Cost 3 vrev <7,0,2,0> + 3700998396U, // <0,7,0,3>: Cost 4 vext2 <1,6,0,7>, <0,3,1,0> + 2718716952U, // <0,7,0,4>: Cost 3 vext3 <5,6,7,0>, <7,0,4,5> + 2718716962U, // <0,7,0,5>: Cost 3 vext3 <5,6,7,0>, <7,0,5,6> + 2621284845U, // <0,7,0,6>: Cost 3 vext2 <0,6,0,7>, <0,6,0,7> + 3904685542U, // <0,7,0,7>: Cost 4 vuzpr <2,0,5,7>, <2,0,5,7> + 2632565405U, // <0,7,0,u>: Cost 3 vext2 <2,5,0,7>, LHS + 2256409584U, // <0,7,1,0>: Cost 3 vrev <7,0,0,1> + 3706307380U, // <0,7,1,1>: Cost 4 vext2 <2,5,0,7>, <1,1,1,1> + 2632565654U, // <0,7,1,2>: Cost 3 vext2 <2,5,0,7>, <1,2,3,0> + 3769603168U, // <0,7,1,3>: Cost 4 vext3 <1,u,3,0>, <7,1,3,5> + 2256704532U, // <0,7,1,4>: Cost 3 vrev <7,0,4,1> + 3769603184U, // <0,7,1,5>: Cost 4 vext3 <1,u,3,0>, <7,1,5,3> + 3700999366U, // <0,7,1,6>: Cost 4 vext2 <1,6,0,7>, <1,6,0,7> + 2886522476U, // <0,7,1,7>: Cost 3 vzipl LHS, <7,7,7,7> + 2256999480U, // <0,7,1,u>: Cost 3 vrev <7,0,u,1> + 2586501222U, // <0,7,2,0>: Cost 3 vext1 <6,0,7,2>, LHS + 1182749690U, // <0,7,2,1>: Cost 2 vrev <7,0,1,2> + 3636356595U, // <0,7,2,2>: Cost 4 vext1 <2,0,7,2>, <2,0,7,2> + 2727711916U, // <0,7,2,3>: Cost 3 vext3 <7,2,3,0>, <7,2,3,0> + 2586504502U, // <0,7,2,4>: Cost 3 vext1 <6,0,7,2>, RHS + 2632566606U, // <0,7,2,5>: Cost 3 vext2 <2,5,0,7>, <2,5,0,7> + 2586505559U, // <0,7,2,6>: Cost 3 vext1 <6,0,7,2>, <6,0,7,2> + 3020740204U, // <0,7,2,7>: Cost 3 vtrnl LHS, <7,7,7,7> + 1183265849U, // <0,7,2,u>: Cost 2 vrev <7,0,u,2> + 3701000342U, // <0,7,3,0>: Cost 4 vext2 <1,6,0,7>, <3,0,1,2> + 3706308849U, // <0,7,3,1>: Cost 4 vext2 <2,5,0,7>, <3,1,2,3> + 3330315268U, // <0,7,3,2>: Cost 4 vrev <7,0,2,3> + 3706309020U, // <0,7,3,3>: Cost 4 vext2 <2,5,0,7>, <3,3,3,3> + 3706309122U, // <0,7,3,4>: Cost 4 vext2 <2,5,0,7>, <3,4,5,6> + 3712281127U, // <0,7,3,5>: Cost 4 vext2 <3,5,0,7>, <3,5,0,7> + 2639202936U, // <0,7,3,6>: Cost 3 vext2 <3,6,0,7>, <3,6,0,7> + 3802412321U, // <0,7,3,7>: Cost 4 vext3 <7,3,7,0>, <7,3,7,0> + 2640530202U, // <0,7,3,u>: Cost 3 vext2 <3,u,0,7>, <3,u,0,7> + 3654287462U, // <0,7,4,0>: Cost 4 vext1 <5,0,7,4>, LHS + 2256507900U, // <0,7,4,1>: Cost 3 vrev <7,0,1,4> + 2256581637U, // <0,7,4,2>: Cost 3 vrev <7,0,2,4> + 3660262008U, // <0,7,4,3>: Cost 4 vext1 <6,0,7,4>, <3,6,0,7> + 3786413405U, // <0,7,4,4>: Cost 4 vext3 <4,6,6,0>, <7,4,4,6> + 2632568118U, // <0,7,4,5>: Cost 3 vext2 <2,5,0,7>, RHS + 3718917457U, // <0,7,4,6>: Cost 4 vext2 <4,6,0,7>, <4,6,0,7> + 3787003255U, // <0,7,4,7>: Cost 4 vext3 <4,7,5,0>, <7,4,7,5> + 2632568361U, // <0,7,4,u>: Cost 3 vext2 <2,5,0,7>, RHS + 3706310268U, // <0,7,5,0>: Cost 4 vext2 <2,5,0,7>, <5,0,7,0> + 3792459156U, // <0,7,5,1>: Cost 4 vext3 <5,6,7,0>, <7,5,1,7> + 3330331654U, // <0,7,5,2>: Cost 4 vrev <7,0,2,5> + 3722899255U, // <0,7,5,3>: Cost 4 vext2 <5,3,0,7>, <5,3,0,7> + 2256737304U, // <0,7,5,4>: Cost 3 vrev <7,0,4,5> + 3724226521U, // <0,7,5,5>: Cost 4 vext2 <5,5,0,7>, <5,5,0,7> + 2718717377U, // <0,7,5,6>: Cost 3 vext3 <5,6,7,0>, <7,5,6,7> + 2729997763U, // <0,7,5,7>: Cost 3 vext3 <7,5,7,0>, <7,5,7,0> + 2720044499U, // <0,7,5,u>: Cost 3 vext3 <5,u,7,0>, <7,5,u,7> + 3712946517U, // <0,7,6,0>: Cost 4 vext2 <3,6,0,7>, <6,0,7,0> + 2256524286U, // <0,7,6,1>: Cost 3 vrev <7,0,1,6> + 3792459246U, // <0,7,6,2>: Cost 4 vext3 <5,6,7,0>, <7,6,2,7> + 3796440567U, // <0,7,6,3>: Cost 4 vext3 <6,3,7,0>, <7,6,3,7> + 3654307126U, // <0,7,6,4>: Cost 4 vext1 <5,0,7,6>, RHS + 2656457394U, // <0,7,6,5>: Cost 3 vext2 <6,5,0,7>, <6,5,0,7> + 3792459281U, // <0,7,6,6>: Cost 4 vext3 <5,6,7,0>, <7,6,6,6> + 2730661396U, // <0,7,6,7>: Cost 3 vext3 <7,6,7,0>, <7,6,7,0> + 2658448293U, // <0,7,6,u>: Cost 3 vext2 <6,u,0,7>, <6,u,0,7> + 3787003431U, // <0,7,7,0>: Cost 4 vext3 <4,7,5,0>, <7,7,0,1> + 3654312854U, // <0,7,7,1>: Cost 4 vext1 <5,0,7,7>, <1,2,3,0> + 3654313446U, // <0,7,7,2>: Cost 4 vext1 <5,0,7,7>, <2,0,5,7> + 3804771905U, // <0,7,7,3>: Cost 4 vext3 <7,7,3,0>, <7,7,3,0> + 3654315318U, // <0,7,7,4>: Cost 4 vext1 <5,0,7,7>, RHS + 3654315651U, // <0,7,7,5>: Cost 4 vext1 <5,0,7,7>, <5,0,7,7> + 3660288348U, // <0,7,7,6>: Cost 4 vext1 <6,0,7,7>, <6,0,7,7> + 2718717548U, // <0,7,7,7>: Cost 3 vext3 <5,6,7,0>, <7,7,7,7> + 2664420990U, // <0,7,7,u>: Cost 3 vext2 <7,u,0,7>, <7,u,0,7> + 2256466935U, // <0,7,u,0>: Cost 3 vrev <7,0,0,u> + 1182798848U, // <0,7,u,1>: Cost 2 vrev <7,0,1,u> + 2256614409U, // <0,7,u,2>: Cost 3 vrev <7,0,2,u> + 2731693714U, // <0,7,u,3>: Cost 3 vext3 <7,u,3,0>, <7,u,3,0> + 2256761883U, // <0,7,u,4>: Cost 3 vrev <7,0,4,u> + 2632571034U, // <0,7,u,5>: Cost 3 vext2 <2,5,0,7>, RHS + 2669066421U, // <0,7,u,6>: Cost 3 vext2 , + 2731988662U, // <0,7,u,7>: Cost 3 vext3 <7,u,7,0>, <7,u,7,0> + 1183315007U, // <0,7,u,u>: Cost 2 vrev <7,0,u,u> + 135053414U, // <0,u,0,0>: Cost 1 vdup0 LHS + 1544896614U, // <0,u,0,1>: Cost 2 vext2 <0,2,0,u>, LHS + 1678999654U, // <0,u,0,2>: Cost 2 vuzpl LHS, LHS + 2691880677U, // <0,u,0,3>: Cost 3 vext3 <1,2,3,0>, + 1476988214U, // <0,u,0,4>: Cost 2 vext1 <0,0,u,0>, RHS + 2718791419U, // <0,u,0,5>: Cost 3 vext3 <5,6,u,0>, + 3021248666U, // <0,u,0,6>: Cost 3 vtrnl <0,2,0,2>, RHS + 2592535607U, // <0,u,0,7>: Cost 3 vext1 <7,0,u,0>, <7,0,u,0> + 135053414U, // <0,u,0,u>: Cost 1 vdup0 LHS + 1476993097U, // <0,u,1,0>: Cost 2 vext1 <0,0,u,1>, <0,0,u,1> + 1812780846U, // <0,u,1,1>: Cost 2 vzipl LHS, LHS + 1618138926U, // <0,u,1,2>: Cost 2 vext3 <1,2,3,0>, LHS + 2752742134U, // <0,u,1,3>: Cost 3 vuzpl LHS, <1,0,3,2> + 1476996406U, // <0,u,1,4>: Cost 2 vext1 <0,0,u,1>, RHS + 1812781210U, // <0,u,1,5>: Cost 2 vzipl LHS, RHS + 2887006416U, // <0,u,1,6>: Cost 3 vzipl LHS, + 2966736200U, // <0,u,1,7>: Cost 3 vzipr <2,3,0,1>, RHS + 1812781413U, // <0,u,1,u>: Cost 2 vzipl LHS, LHS + 1482973286U, // <0,u,2,0>: Cost 2 vext1 <1,0,u,2>, LHS + 1482973987U, // <0,u,2,1>: Cost 2 vext1 <1,0,u,2>, <1,0,u,2> + 1946998574U, // <0,u,2,2>: Cost 2 vtrnl LHS, LHS + 835584U, // <0,u,2,3>: Cost 0 copy LHS + 1482976566U, // <0,u,2,4>: Cost 2 vext1 <1,0,u,2>, RHS + 3020781631U, // <0,u,2,5>: Cost 3 vtrnl LHS, + 1946998938U, // <0,u,2,6>: Cost 2 vtrnl LHS, RHS + 1518810169U, // <0,u,2,7>: Cost 2 vext1 <7,0,u,2>, <7,0,u,2> + 835584U, // <0,u,2,u>: Cost 0 copy LHS + 2618640534U, // <0,u,3,0>: Cost 3 vext2 <0,2,0,u>, <3,0,1,2> + 2752743574U, // <0,u,3,1>: Cost 3 vuzpl LHS, <3,0,1,2> + 2636556597U, // <0,u,3,2>: Cost 3 vext2 <3,2,0,u>, <3,2,0,u> + 2752743836U, // <0,u,3,3>: Cost 3 vuzpl LHS, <3,3,3,3> + 2618640898U, // <0,u,3,4>: Cost 3 vext2 <0,2,0,u>, <3,4,5,6> + 2752743938U, // <0,u,3,5>: Cost 3 vuzpl LHS, <3,4,5,6> + 2639202936U, // <0,u,3,6>: Cost 3 vext2 <3,6,0,7>, <3,6,0,7> + 2639874762U, // <0,u,3,7>: Cost 3 vext2 <3,7,0,u>, <3,7,0,u> + 2752743637U, // <0,u,3,u>: Cost 3 vuzpl LHS, <3,0,u,2> + 2562703462U, // <0,u,4,0>: Cost 3 vext1 <2,0,u,4>, LHS + 2888455982U, // <0,u,4,1>: Cost 3 vzipl <0,4,1,5>, LHS + 3021575982U, // <0,u,4,2>: Cost 3 vtrnl <0,2,4,6>, LHS + 2568677591U, // <0,u,4,3>: Cost 3 vext1 <3,0,u,4>, <3,0,u,4> + 2562706742U, // <0,u,4,4>: Cost 3 vext1 <2,0,u,4>, RHS + 1544899894U, // <0,u,4,5>: Cost 2 vext2 <0,2,0,u>, RHS + 1679002934U, // <0,u,4,6>: Cost 2 vuzpl LHS, RHS + 2718718033U, // <0,u,4,7>: Cost 3 vext3 <5,6,7,0>, + 1679002952U, // <0,u,4,u>: Cost 2 vuzpl LHS, RHS + 2568683622U, // <0,u,5,0>: Cost 3 vext1 <3,0,u,5>, LHS + 2568684438U, // <0,u,5,1>: Cost 3 vext1 <3,0,u,5>, <1,2,3,0> + 3765622902U, // <0,u,5,2>: Cost 4 vext3 <1,2,3,0>, + 2691881087U, // <0,u,5,3>: Cost 3 vext3 <1,2,3,0>, + 2568686902U, // <0,u,5,4>: Cost 3 vext1 <3,0,u,5>, RHS + 2650492890U, // <0,u,5,5>: Cost 3 vext2 <5,5,0,u>, <5,5,0,u> + 1618139290U, // <0,u,5,6>: Cost 2 vext3 <1,2,3,0>, RHS + 2824834358U, // <0,u,5,7>: Cost 3 vuzpr <1,0,3,u>, RHS + 1618139308U, // <0,u,5,u>: Cost 2 vext3 <1,2,3,0>, RHS + 2592579686U, // <0,u,6,0>: Cost 3 vext1 <7,0,u,6>, LHS + 2262496983U, // <0,u,6,1>: Cost 3 vrev + 2654474688U, // <0,u,6,2>: Cost 3 vext2 <6,2,0,u>, <6,2,0,u> + 2691881168U, // <0,u,6,3>: Cost 3 vext3 <1,2,3,0>, + 2592582966U, // <0,u,6,4>: Cost 3 vext1 <7,0,u,6>, RHS + 2656465587U, // <0,u,6,5>: Cost 3 vext2 <6,5,0,u>, <6,5,0,u> + 2657129220U, // <0,u,6,6>: Cost 3 vext2 <6,6,0,u>, <6,6,0,u> + 1584051029U, // <0,u,6,7>: Cost 2 vext2 <6,7,0,u>, <6,7,0,u> + 1584714662U, // <0,u,6,u>: Cost 2 vext2 <6,u,0,u>, <6,u,0,u> + 2562728038U, // <0,u,7,0>: Cost 3 vext1 <2,0,u,7>, LHS + 2562728854U, // <0,u,7,1>: Cost 3 vext1 <2,0,u,7>, <1,2,3,0> + 2562729473U, // <0,u,7,2>: Cost 3 vext1 <2,0,u,7>, <2,0,u,7> + 2661111018U, // <0,u,7,3>: Cost 3 vext2 <7,3,0,u>, <7,3,0,u> + 2562731318U, // <0,u,7,4>: Cost 3 vext1 <2,0,u,7>, RHS + 2718718258U, // <0,u,7,5>: Cost 3 vext3 <5,6,7,0>, + 2586620261U, // <0,u,7,6>: Cost 3 vext1 <6,0,u,7>, <6,0,u,7> + 2657793644U, // <0,u,7,7>: Cost 3 vext2 <6,7,0,u>, <7,7,7,7> + 2562733870U, // <0,u,7,u>: Cost 3 vext1 <2,0,u,7>, LHS + 135053414U, // <0,u,u,0>: Cost 1 vdup0 LHS + 1544902446U, // <0,u,u,1>: Cost 2 vext2 <0,2,0,u>, LHS + 1679005486U, // <0,u,u,2>: Cost 2 vuzpl LHS, LHS + 835584U, // <0,u,u,3>: Cost 0 copy LHS + 1483025718U, // <0,u,u,4>: Cost 2 vext1 <1,0,u,u>, RHS + 1544902810U, // <0,u,u,5>: Cost 2 vext2 <0,2,0,u>, RHS + 1679005850U, // <0,u,u,6>: Cost 2 vuzpl LHS, RHS + 1518859327U, // <0,u,u,7>: Cost 2 vext1 <7,0,u,u>, <7,0,u,u> + 835584U, // <0,u,u,u>: Cost 0 copy LHS + 2689744896U, // <1,0,0,0>: Cost 3 vext3 <0,u,1,1>, <0,0,0,0> + 1610694666U, // <1,0,0,1>: Cost 2 vext3 <0,0,1,1>, <0,0,1,1> + 2689744916U, // <1,0,0,2>: Cost 3 vext3 <0,u,1,1>, <0,0,2,2> + 2619310332U, // <1,0,0,3>: Cost 3 vext2 <0,3,1,0>, <0,3,1,0> + 2684657701U, // <1,0,0,4>: Cost 3 vext3 <0,0,4,1>, <0,0,4,1> + 2620637598U, // <1,0,0,5>: Cost 3 vext2 <0,5,1,0>, <0,5,1,0> + 3708977654U, // <1,0,0,6>: Cost 4 vext2 <3,0,1,0>, <0,6,1,7> + 3666351168U, // <1,0,0,7>: Cost 4 vext1 <7,1,0,0>, <7,1,0,0> + 1611210825U, // <1,0,0,u>: Cost 2 vext3 <0,0,u,1>, <0,0,u,1> + 2556780646U, // <1,0,1,0>: Cost 3 vext1 <1,1,0,1>, LHS + 2556781355U, // <1,0,1,1>: Cost 3 vext1 <1,1,0,1>, <1,1,0,1> + 1616003174U, // <1,0,1,2>: Cost 2 vext3 <0,u,1,1>, LHS + 3693052888U, // <1,0,1,3>: Cost 4 vext2 <0,3,1,0>, <1,3,1,3> + 2556783926U, // <1,0,1,4>: Cost 3 vext1 <1,1,0,1>, RHS + 2580672143U, // <1,0,1,5>: Cost 3 vext1 <5,1,0,1>, <5,1,0,1> + 2724839566U, // <1,0,1,6>: Cost 3 vext3 <6,7,0,1>, <0,1,6,7> + 3654415354U, // <1,0,1,7>: Cost 4 vext1 <5,1,0,1>, <7,0,1,2> + 1616003228U, // <1,0,1,u>: Cost 2 vext3 <0,u,1,1>, LHS + 2685690019U, // <1,0,2,0>: Cost 3 vext3 <0,2,0,1>, <0,2,0,1> + 2685763756U, // <1,0,2,1>: Cost 3 vext3 <0,2,1,1>, <0,2,1,1> + 2698297524U, // <1,0,2,2>: Cost 3 vext3 <2,3,0,1>, <0,2,2,0> + 2685911230U, // <1,0,2,3>: Cost 3 vext3 <0,2,3,1>, <0,2,3,1> + 2689745100U, // <1,0,2,4>: Cost 3 vext3 <0,u,1,1>, <0,2,4,6> + 3764814038U, // <1,0,2,5>: Cost 4 vext3 <1,1,1,1>, <0,2,5,7> + 2724839640U, // <1,0,2,6>: Cost 3 vext3 <6,7,0,1>, <0,2,6,0> + 2592625658U, // <1,0,2,7>: Cost 3 vext1 <7,1,0,2>, <7,0,1,2> + 2686279915U, // <1,0,2,u>: Cost 3 vext3 <0,2,u,1>, <0,2,u,1> + 3087843328U, // <1,0,3,0>: Cost 3 vtrnr LHS, <0,0,0,0> + 3087843338U, // <1,0,3,1>: Cost 3 vtrnr LHS, <0,0,1,1> + 67944550U, // <1,0,3,2>: Cost 1 vrev LHS + 2568743135U, // <1,0,3,3>: Cost 3 vext1 <3,1,0,3>, <3,1,0,3> + 2562772278U, // <1,0,3,4>: Cost 3 vext1 <2,1,0,3>, RHS + 4099850454U, // <1,0,3,5>: Cost 4 vtrnl <1,0,3,2>, <0,2,5,7> + 3704998538U, // <1,0,3,6>: Cost 4 vext2 <2,3,1,0>, <3,6,2,7> + 2592633923U, // <1,0,3,7>: Cost 3 vext1 <7,1,0,3>, <7,1,0,3> + 68386972U, // <1,0,3,u>: Cost 1 vrev LHS + 2620640146U, // <1,0,4,0>: Cost 3 vext2 <0,5,1,0>, <4,0,5,1> + 2689745234U, // <1,0,4,1>: Cost 3 vext3 <0,u,1,1>, <0,4,1,5> + 2689745244U, // <1,0,4,2>: Cost 3 vext3 <0,u,1,1>, <0,4,2,6> + 3760980320U, // <1,0,4,3>: Cost 4 vext3 <0,4,3,1>, <0,4,3,1> + 3761054057U, // <1,0,4,4>: Cost 4 vext3 <0,4,4,1>, <0,4,4,1> + 2619313462U, // <1,0,4,5>: Cost 3 vext2 <0,3,1,0>, RHS + 3761201531U, // <1,0,4,6>: Cost 4 vext3 <0,4,6,1>, <0,4,6,1> + 3666383940U, // <1,0,4,7>: Cost 4 vext1 <7,1,0,4>, <7,1,0,4> + 2619313705U, // <1,0,4,u>: Cost 3 vext2 <0,3,1,0>, RHS + 4029300736U, // <1,0,5,0>: Cost 4 vzipr <0,4,1,5>, <0,0,0,0> + 2895249510U, // <1,0,5,1>: Cost 3 vzipl <1,5,3,7>, LHS + 3028287590U, // <1,0,5,2>: Cost 3 vtrnl <1,3,5,7>, LHS + 3642501345U, // <1,0,5,3>: Cost 4 vext1 <3,1,0,5>, <3,1,0,5> + 2215592058U, // <1,0,5,4>: Cost 3 vrev <0,1,4,5> + 3724242907U, // <1,0,5,5>: Cost 4 vext2 <5,5,1,0>, <5,5,1,0> + 3724906540U, // <1,0,5,6>: Cost 4 vext2 <5,6,1,0>, <5,6,1,0> + 3911118134U, // <1,0,5,7>: Cost 4 vuzpr <3,1,3,0>, RHS + 3028287644U, // <1,0,5,u>: Cost 3 vtrnl <1,3,5,7>, LHS + 3762086375U, // <1,0,6,0>: Cost 4 vext3 <0,6,0,1>, <0,6,0,1> + 2698297846U, // <1,0,6,1>: Cost 3 vext3 <2,3,0,1>, <0,6,1,7> + 3760022015U, // <1,0,6,2>: Cost 4 vext3 <0,2,u,1>, <0,6,2,7> + 3642509538U, // <1,0,6,3>: Cost 4 vext1 <3,1,0,6>, <3,1,0,6> + 3762381323U, // <1,0,6,4>: Cost 4 vext3 <0,6,4,1>, <0,6,4,1> + 3730215604U, // <1,0,6,5>: Cost 4 vext2 <6,5,1,0>, <6,5,1,0> + 3730879237U, // <1,0,6,6>: Cost 4 vext2 <6,6,1,0>, <6,6,1,0> + 2657801046U, // <1,0,6,7>: Cost 3 vext2 <6,7,1,0>, <6,7,1,0> + 2658464679U, // <1,0,6,u>: Cost 3 vext2 <6,u,1,0>, <6,u,1,0> + 2659128312U, // <1,0,7,0>: Cost 3 vext2 <7,0,1,0>, <7,0,1,0> + 4047898278U, // <1,0,7,1>: Cost 4 vzipr <3,5,1,7>, <2,3,0,1> + 2215460970U, // <1,0,7,2>: Cost 3 vrev <0,1,2,7> + 3734861035U, // <1,0,7,3>: Cost 4 vext2 <7,3,1,0>, <7,3,1,0> + 3731543398U, // <1,0,7,4>: Cost 4 vext2 <6,7,1,0>, <7,4,5,6> + 3736188301U, // <1,0,7,5>: Cost 4 vext2 <7,5,1,0>, <7,5,1,0> + 2663110110U, // <1,0,7,6>: Cost 3 vext2 <7,6,1,0>, <7,6,1,0> + 3731543660U, // <1,0,7,7>: Cost 4 vext2 <6,7,1,0>, <7,7,7,7> + 2664437376U, // <1,0,7,u>: Cost 3 vext2 <7,u,1,0>, <7,u,1,0> + 3087884288U, // <1,0,u,0>: Cost 3 vtrnr LHS, <0,0,0,0> + 1616003730U, // <1,0,u,1>: Cost 2 vext3 <0,u,1,1>, <0,u,1,1> + 67985515U, // <1,0,u,2>: Cost 1 vrev LHS + 2689893028U, // <1,0,u,3>: Cost 3 vext3 <0,u,3,1>, <0,u,3,1> + 2689745586U, // <1,0,u,4>: Cost 3 vext3 <0,u,1,1>, <0,u,4,6> + 2619316378U, // <1,0,u,5>: Cost 3 vext2 <0,3,1,0>, RHS + 2669082807U, // <1,0,u,6>: Cost 3 vext2 , + 2592674888U, // <1,0,u,7>: Cost 3 vext1 <7,1,0,u>, <7,1,0,u> + 68427937U, // <1,0,u,u>: Cost 1 vrev LHS + 1543585802U, // <1,1,0,0>: Cost 2 vext2 <0,0,1,1>, <0,0,1,1> + 1548894310U, // <1,1,0,1>: Cost 2 vext2 <0,u,1,1>, LHS + 2618654892U, // <1,1,0,2>: Cost 3 vext2 <0,2,1,1>, <0,2,1,1> + 2689745654U, // <1,1,0,3>: Cost 3 vext3 <0,u,1,1>, <1,0,3,2> + 2622636370U, // <1,1,0,4>: Cost 3 vext2 <0,u,1,1>, <0,4,1,5> + 2620645791U, // <1,1,0,5>: Cost 3 vext2 <0,5,1,1>, <0,5,1,1> + 3696378367U, // <1,1,0,6>: Cost 4 vext2 <0,u,1,1>, <0,6,2,7> + 3666424905U, // <1,1,0,7>: Cost 4 vext1 <7,1,1,0>, <7,1,1,0> + 1548894866U, // <1,1,0,u>: Cost 2 vext2 <0,u,1,1>, <0,u,1,1> + 1483112550U, // <1,1,1,0>: Cost 2 vext1 <1,1,1,1>, LHS + 202162278U, // <1,1,1,1>: Cost 1 vdup1 LHS + 2622636950U, // <1,1,1,2>: Cost 3 vext2 <0,u,1,1>, <1,2,3,0> + 2622637016U, // <1,1,1,3>: Cost 3 vext2 <0,u,1,1>, <1,3,1,3> + 1483115830U, // <1,1,1,4>: Cost 2 vext1 <1,1,1,1>, RHS + 2622637200U, // <1,1,1,5>: Cost 3 vext2 <0,u,1,1>, <1,5,3,7> + 2622637263U, // <1,1,1,6>: Cost 3 vext2 <0,u,1,1>, <1,6,1,7> + 2592691274U, // <1,1,1,7>: Cost 3 vext1 <7,1,1,1>, <7,1,1,1> + 202162278U, // <1,1,1,u>: Cost 1 vdup1 LHS + 2550890588U, // <1,1,2,0>: Cost 3 vext1 <0,1,1,2>, <0,1,1,2> + 2617329183U, // <1,1,2,1>: Cost 3 vext2 <0,0,1,1>, <2,1,3,1> + 2622637672U, // <1,1,2,2>: Cost 3 vext2 <0,u,1,1>, <2,2,2,2> + 2622637734U, // <1,1,2,3>: Cost 3 vext2 <0,u,1,1>, <2,3,0,1> + 2550893878U, // <1,1,2,4>: Cost 3 vext1 <0,1,1,2>, RHS + 3696379744U, // <1,1,2,5>: Cost 4 vext2 <0,u,1,1>, <2,5,2,7> + 2622638010U, // <1,1,2,6>: Cost 3 vext2 <0,u,1,1>, <2,6,3,7> + 3804554170U, // <1,1,2,7>: Cost 4 vext3 <7,7,0,1>, <1,2,7,0> + 2622638139U, // <1,1,2,u>: Cost 3 vext2 <0,u,1,1>, <2,u,0,1> + 2622638230U, // <1,1,3,0>: Cost 3 vext2 <0,u,1,1>, <3,0,1,2> + 3087844148U, // <1,1,3,1>: Cost 3 vtrnr LHS, <1,1,1,1> + 4161585244U, // <1,1,3,2>: Cost 4 vtrnr LHS, <0,1,1,2> + 2014101606U, // <1,1,3,3>: Cost 2 vtrnr LHS, LHS + 2622638594U, // <1,1,3,4>: Cost 3 vext2 <0,u,1,1>, <3,4,5,6> + 2689745920U, // <1,1,3,5>: Cost 3 vext3 <0,u,1,1>, <1,3,5,7> + 3763487753U, // <1,1,3,6>: Cost 4 vext3 <0,u,1,1>, <1,3,6,7> + 2592707660U, // <1,1,3,7>: Cost 3 vext1 <7,1,1,3>, <7,1,1,3> + 2014101611U, // <1,1,3,u>: Cost 2 vtrnr LHS, LHS + 2556878950U, // <1,1,4,0>: Cost 3 vext1 <1,1,1,4>, LHS + 2221335351U, // <1,1,4,1>: Cost 3 vrev <1,1,1,4> + 3696380988U, // <1,1,4,2>: Cost 4 vext2 <0,u,1,1>, <4,2,6,0> + 3763487805U, // <1,1,4,3>: Cost 4 vext3 <0,u,1,1>, <1,4,3,5> + 2556882230U, // <1,1,4,4>: Cost 3 vext1 <1,1,1,4>, RHS + 1548897590U, // <1,1,4,5>: Cost 2 vext2 <0,u,1,1>, RHS + 2758184246U, // <1,1,4,6>: Cost 3 vuzpl <1,1,1,1>, RHS + 3666457677U, // <1,1,4,7>: Cost 4 vext1 <7,1,1,4>, <7,1,1,4> + 1548897833U, // <1,1,4,u>: Cost 2 vext2 <0,u,1,1>, RHS + 2693653615U, // <1,1,5,0>: Cost 3 vext3 <1,5,0,1>, <1,5,0,1> + 2617331408U, // <1,1,5,1>: Cost 3 vext2 <0,0,1,1>, <5,1,7,3> + 4029302934U, // <1,1,5,2>: Cost 4 vzipr <0,4,1,5>, <3,0,1,2> + 2689746064U, // <1,1,5,3>: Cost 3 vext3 <0,u,1,1>, <1,5,3,7> + 2221564755U, // <1,1,5,4>: Cost 3 vrev <1,1,4,5> + 2955559250U, // <1,1,5,5>: Cost 3 vzipr <0,4,1,5>, <0,4,1,5> + 2617331810U, // <1,1,5,6>: Cost 3 vext2 <0,0,1,1>, <5,6,7,0> + 2825293110U, // <1,1,5,7>: Cost 3 vuzpr <1,1,1,1>, RHS + 2689746109U, // <1,1,5,u>: Cost 3 vext3 <0,u,1,1>, <1,5,u,7> + 3696382241U, // <1,1,6,0>: Cost 4 vext2 <0,u,1,1>, <6,0,1,2> + 2689746127U, // <1,1,6,1>: Cost 3 vext3 <0,u,1,1>, <1,6,1,7> + 2617332218U, // <1,1,6,2>: Cost 3 vext2 <0,0,1,1>, <6,2,7,3> + 3763487969U, // <1,1,6,3>: Cost 4 vext3 <0,u,1,1>, <1,6,3,7> + 3696382605U, // <1,1,6,4>: Cost 4 vext2 <0,u,1,1>, <6,4,5,6> + 4029309266U, // <1,1,6,5>: Cost 4 vzipr <0,4,1,6>, <0,4,1,5> + 2617332536U, // <1,1,6,6>: Cost 3 vext2 <0,0,1,1>, <6,6,6,6> + 2724840702U, // <1,1,6,7>: Cost 3 vext3 <6,7,0,1>, <1,6,7,0> + 2725504263U, // <1,1,6,u>: Cost 3 vext3 <6,u,0,1>, <1,6,u,0> + 2617332720U, // <1,1,7,0>: Cost 3 vext2 <0,0,1,1>, <7,0,0,1> + 2659800138U, // <1,1,7,1>: Cost 3 vext2 <7,1,1,1>, <7,1,1,1> + 3691074717U, // <1,1,7,2>: Cost 4 vext2 <0,0,1,1>, <7,2,1,3> + 4167811174U, // <1,1,7,3>: Cost 4 vtrnr <1,1,5,7>, LHS + 2617333094U, // <1,1,7,4>: Cost 3 vext2 <0,0,1,1>, <7,4,5,6> + 3295396702U, // <1,1,7,5>: Cost 4 vrev <1,1,5,7> + 3803891014U, // <1,1,7,6>: Cost 4 vext3 <7,6,0,1>, <1,7,6,0> + 2617333356U, // <1,1,7,7>: Cost 3 vext2 <0,0,1,1>, <7,7,7,7> + 2659800138U, // <1,1,7,u>: Cost 3 vext2 <7,1,1,1>, <7,1,1,1> + 1483112550U, // <1,1,u,0>: Cost 2 vext1 <1,1,1,1>, LHS + 202162278U, // <1,1,u,1>: Cost 1 vdup1 LHS + 2622642056U, // <1,1,u,2>: Cost 3 vext2 <0,u,1,1>, + 2014142566U, // <1,1,u,3>: Cost 2 vtrnr LHS, LHS + 1483115830U, // <1,1,u,4>: Cost 2 vext1 <1,1,1,1>, RHS + 1548900506U, // <1,1,u,5>: Cost 2 vext2 <0,u,1,1>, RHS + 2622642384U, // <1,1,u,6>: Cost 3 vext2 <0,u,1,1>, + 2825293353U, // <1,1,u,7>: Cost 3 vuzpr <1,1,1,1>, RHS + 202162278U, // <1,1,u,u>: Cost 1 vdup1 LHS + 2635251712U, // <1,2,0,0>: Cost 3 vext2 <3,0,1,2>, <0,0,0,0> + 1561509990U, // <1,2,0,1>: Cost 2 vext2 <3,0,1,2>, LHS + 2618663085U, // <1,2,0,2>: Cost 3 vext2 <0,2,1,2>, <0,2,1,2> + 2696529358U, // <1,2,0,3>: Cost 3 vext3 <2,0,3,1>, <2,0,3,1> + 2635252050U, // <1,2,0,4>: Cost 3 vext2 <3,0,1,2>, <0,4,1,5> + 3769533926U, // <1,2,0,5>: Cost 4 vext3 <1,u,2,1>, <2,0,5,7> + 2621317617U, // <1,2,0,6>: Cost 3 vext2 <0,6,1,2>, <0,6,1,2> + 2659140170U, // <1,2,0,7>: Cost 3 vext2 <7,0,1,2>, <0,7,2,1> + 1561510557U, // <1,2,0,u>: Cost 2 vext2 <3,0,1,2>, LHS + 2623308516U, // <1,2,1,0>: Cost 3 vext2 <1,0,1,2>, <1,0,1,2> + 2635252532U, // <1,2,1,1>: Cost 3 vext2 <3,0,1,2>, <1,1,1,1> + 2631271318U, // <1,2,1,2>: Cost 3 vext2 <2,3,1,2>, <1,2,3,0> + 2958180454U, // <1,2,1,3>: Cost 3 vzipr <0,u,1,1>, LHS + 2550959414U, // <1,2,1,4>: Cost 3 vext1 <0,1,2,1>, RHS + 2635252880U, // <1,2,1,5>: Cost 3 vext2 <3,0,1,2>, <1,5,3,7> + 2635252952U, // <1,2,1,6>: Cost 3 vext2 <3,0,1,2>, <1,6,2,7> + 3732882731U, // <1,2,1,7>: Cost 4 vext2 <7,0,1,2>, <1,7,3,0> + 2958180459U, // <1,2,1,u>: Cost 3 vzipr <0,u,1,1>, LHS + 2629281213U, // <1,2,2,0>: Cost 3 vext2 <2,0,1,2>, <2,0,1,2> + 2635253280U, // <1,2,2,1>: Cost 3 vext2 <3,0,1,2>, <2,1,3,2> + 2618664552U, // <1,2,2,2>: Cost 3 vext2 <0,2,1,2>, <2,2,2,2> + 2689746546U, // <1,2,2,3>: Cost 3 vext3 <0,u,1,1>, <2,2,3,3> + 3764815485U, // <1,2,2,4>: Cost 4 vext3 <1,1,1,1>, <2,2,4,5> + 3760023176U, // <1,2,2,5>: Cost 4 vext3 <0,2,u,1>, <2,2,5,7> + 2635253690U, // <1,2,2,6>: Cost 3 vext2 <3,0,1,2>, <2,6,3,7> + 2659141610U, // <1,2,2,7>: Cost 3 vext2 <7,0,1,2>, <2,7,0,1> + 2689746591U, // <1,2,2,u>: Cost 3 vext3 <0,u,1,1>, <2,2,u,3> + 403488870U, // <1,2,3,0>: Cost 1 vext1 LHS, LHS + 1477231350U, // <1,2,3,1>: Cost 2 vext1 LHS, <1,0,3,2> + 1477232232U, // <1,2,3,2>: Cost 2 vext1 LHS, <2,2,2,2> + 1477233052U, // <1,2,3,3>: Cost 2 vext1 LHS, <3,3,3,3> + 403492150U, // <1,2,3,4>: Cost 1 vext1 LHS, RHS + 1525010128U, // <1,2,3,5>: Cost 2 vext1 LHS, <5,1,7,3> + 1525010938U, // <1,2,3,6>: Cost 2 vext1 LHS, <6,2,7,3> + 1525011450U, // <1,2,3,7>: Cost 2 vext1 LHS, <7,0,1,2> + 403494702U, // <1,2,3,u>: Cost 1 vext1 LHS, LHS + 2641226607U, // <1,2,4,0>: Cost 3 vext2 <4,0,1,2>, <4,0,1,2> + 3624723446U, // <1,2,4,1>: Cost 4 vext1 <0,1,2,4>, <1,3,4,6> + 3301123609U, // <1,2,4,2>: Cost 4 vrev <2,1,2,4> + 2598759198U, // <1,2,4,3>: Cost 3 vext1 , <3,u,1,2> + 2659142864U, // <1,2,4,4>: Cost 3 vext2 <7,0,1,2>, <4,4,4,4> + 1561513270U, // <1,2,4,5>: Cost 2 vext2 <3,0,1,2>, RHS + 2659143028U, // <1,2,4,6>: Cost 3 vext2 <7,0,1,2>, <4,6,4,6> + 2659143112U, // <1,2,4,7>: Cost 3 vext2 <7,0,1,2>, <4,7,5,0> + 1561513513U, // <1,2,4,u>: Cost 2 vext2 <3,0,1,2>, RHS + 2550988902U, // <1,2,5,0>: Cost 3 vext1 <0,1,2,5>, LHS + 2550989824U, // <1,2,5,1>: Cost 3 vext1 <0,1,2,5>, <1,3,5,7> + 3624732264U, // <1,2,5,2>: Cost 4 vext1 <0,1,2,5>, <2,2,2,2> + 2955559014U, // <1,2,5,3>: Cost 3 vzipr <0,4,1,5>, LHS + 2550992182U, // <1,2,5,4>: Cost 3 vext1 <0,1,2,5>, RHS + 2659143684U, // <1,2,5,5>: Cost 3 vext2 <7,0,1,2>, <5,5,5,5> + 2659143778U, // <1,2,5,6>: Cost 3 vext2 <7,0,1,2>, <5,6,7,0> + 2659143848U, // <1,2,5,7>: Cost 3 vext2 <7,0,1,2>, <5,7,5,7> + 2550994734U, // <1,2,5,u>: Cost 3 vext1 <0,1,2,5>, LHS + 2700289945U, // <1,2,6,0>: Cost 3 vext3 <2,6,0,1>, <2,6,0,1> + 2635256232U, // <1,2,6,1>: Cost 3 vext2 <3,0,1,2>, <6,1,7,2> + 2659144186U, // <1,2,6,2>: Cost 3 vext2 <7,0,1,2>, <6,2,7,3> + 2689746874U, // <1,2,6,3>: Cost 3 vext3 <0,u,1,1>, <2,6,3,7> + 3763488705U, // <1,2,6,4>: Cost 4 vext3 <0,u,1,1>, <2,6,4,5> + 3763488716U, // <1,2,6,5>: Cost 4 vext3 <0,u,1,1>, <2,6,5,7> + 2659144504U, // <1,2,6,6>: Cost 3 vext2 <7,0,1,2>, <6,6,6,6> + 2657817432U, // <1,2,6,7>: Cost 3 vext2 <6,7,1,2>, <6,7,1,2> + 2689746919U, // <1,2,6,u>: Cost 3 vext3 <0,u,1,1>, <2,6,u,7> + 1585402874U, // <1,2,7,0>: Cost 2 vext2 <7,0,1,2>, <7,0,1,2> + 2659144770U, // <1,2,7,1>: Cost 3 vext2 <7,0,1,2>, <7,1,0,2> + 3708998858U, // <1,2,7,2>: Cost 4 vext2 <3,0,1,2>, <7,2,6,3> + 2635257059U, // <1,2,7,3>: Cost 3 vext2 <3,0,1,2>, <7,3,0,1> + 2659145062U, // <1,2,7,4>: Cost 3 vext2 <7,0,1,2>, <7,4,5,6> + 3732886916U, // <1,2,7,5>: Cost 4 vext2 <7,0,1,2>, <7,5,0,0> + 3732886998U, // <1,2,7,6>: Cost 4 vext2 <7,0,1,2>, <7,6,0,1> + 2659145255U, // <1,2,7,7>: Cost 3 vext2 <7,0,1,2>, <7,7,0,1> + 1590711938U, // <1,2,7,u>: Cost 2 vext2 <7,u,1,2>, <7,u,1,2> + 403529835U, // <1,2,u,0>: Cost 1 vext1 LHS, LHS + 1477272310U, // <1,2,u,1>: Cost 2 vext1 LHS, <1,0,3,2> + 1477273192U, // <1,2,u,2>: Cost 2 vext1 LHS, <2,2,2,2> + 1477273750U, // <1,2,u,3>: Cost 2 vext1 LHS, <3,0,1,2> + 403533110U, // <1,2,u,4>: Cost 1 vext1 LHS, RHS + 1561516186U, // <1,2,u,5>: Cost 2 vext2 <3,0,1,2>, RHS + 1525051898U, // <1,2,u,6>: Cost 2 vext1 LHS, <6,2,7,3> + 1525052410U, // <1,2,u,7>: Cost 2 vext1 LHS, <7,0,1,2> + 403535662U, // <1,2,u,u>: Cost 1 vext1 LHS, LHS + 2819407872U, // <1,3,0,0>: Cost 3 vuzpr LHS, <0,0,0,0> + 1551564902U, // <1,3,0,1>: Cost 2 vext2 <1,3,1,3>, LHS + 2819408630U, // <1,3,0,2>: Cost 3 vuzpr LHS, <1,0,3,2> + 2619334911U, // <1,3,0,3>: Cost 3 vext2 <0,3,1,3>, <0,3,1,3> + 2625306962U, // <1,3,0,4>: Cost 3 vext2 <1,3,1,3>, <0,4,1,5> + 3832725879U, // <1,3,0,5>: Cost 4 vuzpl <1,2,3,0>, <0,4,5,6> + 3699048959U, // <1,3,0,6>: Cost 4 vext2 <1,3,1,3>, <0,6,2,7> + 3776538827U, // <1,3,0,7>: Cost 4 vext3 <3,0,7,1>, <3,0,7,1> + 1551565469U, // <1,3,0,u>: Cost 2 vext2 <1,3,1,3>, LHS + 2618671862U, // <1,3,1,0>: Cost 3 vext2 <0,2,1,3>, <1,0,3,2> + 2819408692U, // <1,3,1,1>: Cost 3 vuzpr LHS, <1,1,1,1> + 2624643975U, // <1,3,1,2>: Cost 3 vext2 <1,2,1,3>, <1,2,1,3> + 1745666150U, // <1,3,1,3>: Cost 2 vuzpr LHS, LHS + 2557005110U, // <1,3,1,4>: Cost 3 vext1 <1,1,3,1>, RHS + 2625307792U, // <1,3,1,5>: Cost 3 vext2 <1,3,1,3>, <1,5,3,7> + 3698386127U, // <1,3,1,6>: Cost 4 vext2 <1,2,1,3>, <1,6,1,7> + 2592838748U, // <1,3,1,7>: Cost 3 vext1 <7,1,3,1>, <7,1,3,1> + 1745666155U, // <1,3,1,u>: Cost 2 vuzpr LHS, LHS + 2819408790U, // <1,3,2,0>: Cost 3 vuzpr LHS, <1,2,3,0> + 2625308193U, // <1,3,2,1>: Cost 3 vext2 <1,3,1,3>, <2,1,3,3> + 2819408036U, // <1,3,2,2>: Cost 3 vuzpr LHS, <0,2,0,2> + 2819851890U, // <1,3,2,3>: Cost 3 vuzpr LHS, <2,2,3,3> + 2819408794U, // <1,3,2,4>: Cost 3 vuzpr LHS, <1,2,3,4> + 3893149890U, // <1,3,2,5>: Cost 4 vuzpr LHS, <0,2,3,5> + 2819408076U, // <1,3,2,6>: Cost 3 vuzpr LHS, <0,2,4,6> + 3772041583U, // <1,3,2,7>: Cost 4 vext3 <2,3,0,1>, <3,2,7,3> + 2819408042U, // <1,3,2,u>: Cost 3 vuzpr LHS, <0,2,0,u> + 1483276390U, // <1,3,3,0>: Cost 2 vext1 <1,1,3,3>, LHS + 1483277128U, // <1,3,3,1>: Cost 2 vext1 <1,1,3,3>, <1,1,3,3> + 2557019752U, // <1,3,3,2>: Cost 3 vext1 <1,1,3,3>, <2,2,2,2> + 2819408856U, // <1,3,3,3>: Cost 3 vuzpr LHS, <1,3,1,3> + 1483279670U, // <1,3,3,4>: Cost 2 vext1 <1,1,3,3>, RHS + 2819409614U, // <1,3,3,5>: Cost 3 vuzpr LHS, <2,3,4,5> + 2598826490U, // <1,3,3,6>: Cost 3 vext1 , <6,2,7,3> + 3087844352U, // <1,3,3,7>: Cost 3 vtrnr LHS, <1,3,5,7> + 1483282222U, // <1,3,3,u>: Cost 2 vext1 <1,1,3,3>, LHS + 2568970342U, // <1,3,4,0>: Cost 3 vext1 <3,1,3,4>, LHS + 2568971224U, // <1,3,4,1>: Cost 3 vext1 <3,1,3,4>, <1,3,1,3> + 3832761290U, // <1,3,4,2>: Cost 4 vuzpl <1,2,3,4>, <4,1,2,3> + 2233428219U, // <1,3,4,3>: Cost 3 vrev <3,1,3,4> + 2568973622U, // <1,3,4,4>: Cost 3 vext1 <3,1,3,4>, RHS + 1551568182U, // <1,3,4,5>: Cost 2 vext2 <1,3,1,3>, RHS + 2819410434U, // <1,3,4,6>: Cost 3 vuzpr LHS, <3,4,5,6> + 3666605151U, // <1,3,4,7>: Cost 4 vext1 <7,1,3,4>, <7,1,3,4> + 1551568425U, // <1,3,4,u>: Cost 2 vext2 <1,3,1,3>, RHS + 2563006566U, // <1,3,5,0>: Cost 3 vext1 <2,1,3,5>, LHS + 2568979456U, // <1,3,5,1>: Cost 3 vext1 <3,1,3,5>, <1,3,5,7> + 2563008035U, // <1,3,5,2>: Cost 3 vext1 <2,1,3,5>, <2,1,3,5> + 2233436412U, // <1,3,5,3>: Cost 3 vrev <3,1,3,5> + 2563009846U, // <1,3,5,4>: Cost 3 vext1 <2,1,3,5>, RHS + 2867187716U, // <1,3,5,5>: Cost 3 vuzpr LHS, <5,5,5,5> + 2655834214U, // <1,3,5,6>: Cost 3 vext2 <6,4,1,3>, <5,6,7,4> + 1745669430U, // <1,3,5,7>: Cost 2 vuzpr LHS, RHS + 1745669431U, // <1,3,5,u>: Cost 2 vuzpr LHS, RHS + 2867187810U, // <1,3,6,0>: Cost 3 vuzpr LHS, <5,6,7,0> + 3699052931U, // <1,3,6,1>: Cost 4 vext2 <1,3,1,3>, <6,1,3,1> + 2654507460U, // <1,3,6,2>: Cost 3 vext2 <6,2,1,3>, <6,2,1,3> + 3766291091U, // <1,3,6,3>: Cost 4 vext3 <1,3,3,1>, <3,6,3,7> + 2655834726U, // <1,3,6,4>: Cost 3 vext2 <6,4,1,3>, <6,4,1,3> + 3923384562U, // <1,3,6,5>: Cost 4 vuzpr <5,1,7,3>, + 2657161992U, // <1,3,6,6>: Cost 3 vext2 <6,6,1,3>, <6,6,1,3> + 2819852218U, // <1,3,6,7>: Cost 3 vuzpr LHS, <2,6,3,7> + 2819852219U, // <1,3,6,u>: Cost 3 vuzpr LHS, <2,6,3,u> + 2706926275U, // <1,3,7,0>: Cost 3 vext3 <3,7,0,1>, <3,7,0,1> + 2659816524U, // <1,3,7,1>: Cost 3 vext2 <7,1,1,3>, <7,1,1,3> + 3636766245U, // <1,3,7,2>: Cost 4 vext1 <2,1,3,7>, <2,1,3,7> + 2867187903U, // <1,3,7,3>: Cost 3 vuzpr LHS, <5,7,u,3> + 2625312102U, // <1,3,7,4>: Cost 3 vext2 <1,3,1,3>, <7,4,5,6> + 2867188598U, // <1,3,7,5>: Cost 3 vuzpr LHS, <6,7,4,5> + 3728250344U, // <1,3,7,6>: Cost 4 vext2 <6,2,1,3>, <7,6,2,1> + 2867187880U, // <1,3,7,7>: Cost 3 vuzpr LHS, <5,7,5,7> + 2707516171U, // <1,3,7,u>: Cost 3 vext3 <3,7,u,1>, <3,7,u,1> + 1483317350U, // <1,3,u,0>: Cost 2 vext1 <1,1,3,u>, LHS + 1483318093U, // <1,3,u,1>: Cost 2 vext1 <1,1,3,u>, <1,1,3,u> + 2819410718U, // <1,3,u,2>: Cost 3 vuzpr LHS, <3,u,1,2> + 1745666717U, // <1,3,u,3>: Cost 2 vuzpr LHS, LHS + 1483320630U, // <1,3,u,4>: Cost 2 vext1 <1,1,3,u>, RHS + 1551571098U, // <1,3,u,5>: Cost 2 vext2 <1,3,1,3>, RHS + 2819410758U, // <1,3,u,6>: Cost 3 vuzpr LHS, <3,u,5,6> + 1745669673U, // <1,3,u,7>: Cost 2 vuzpr LHS, RHS + 1745666722U, // <1,3,u,u>: Cost 2 vuzpr LHS, LHS + 2617352205U, // <1,4,0,0>: Cost 3 vext2 <0,0,1,4>, <0,0,1,4> + 2619342950U, // <1,4,0,1>: Cost 3 vext2 <0,3,1,4>, LHS + 3692421295U, // <1,4,0,2>: Cost 4 vext2 <0,2,1,4>, <0,2,1,4> + 2619343104U, // <1,4,0,3>: Cost 3 vext2 <0,3,1,4>, <0,3,1,4> + 2617352530U, // <1,4,0,4>: Cost 3 vext2 <0,0,1,4>, <0,4,1,5> + 1634880402U, // <1,4,0,5>: Cost 2 vext3 <4,0,5,1>, <4,0,5,1> + 2713930652U, // <1,4,0,6>: Cost 3 vext3 <4,u,5,1>, <4,0,6,2> + 3732898396U, // <1,4,0,7>: Cost 4 vext2 <7,0,1,4>, <0,7,4,1> + 1635101613U, // <1,4,0,u>: Cost 2 vext3 <4,0,u,1>, <4,0,u,1> + 3693085430U, // <1,4,1,0>: Cost 4 vext2 <0,3,1,4>, <1,0,3,2> + 2623988535U, // <1,4,1,1>: Cost 3 vext2 <1,1,1,4>, <1,1,1,4> + 3693085590U, // <1,4,1,2>: Cost 4 vext2 <0,3,1,4>, <1,2,3,0> + 3692422134U, // <1,4,1,3>: Cost 4 vext2 <0,2,1,4>, <1,3,4,6> + 3693085726U, // <1,4,1,4>: Cost 4 vext2 <0,3,1,4>, <1,4,0,1> + 2892401974U, // <1,4,1,5>: Cost 3 vzipl <1,1,1,1>, RHS + 3026619702U, // <1,4,1,6>: Cost 3 vtrnl <1,1,1,1>, RHS + 3800206324U, // <1,4,1,7>: Cost 4 vext3 <7,0,4,1>, <4,1,7,0> + 2892402217U, // <1,4,1,u>: Cost 3 vzipl <1,1,1,1>, RHS + 3966978927U, // <1,4,2,0>: Cost 4 vzipl <1,2,3,4>, <4,0,1,2> + 3966979018U, // <1,4,2,1>: Cost 4 vzipl <1,2,3,4>, <4,1,2,3> + 3693086312U, // <1,4,2,2>: Cost 4 vext2 <0,3,1,4>, <2,2,2,2> + 2635269798U, // <1,4,2,3>: Cost 3 vext2 <3,0,1,4>, <2,3,0,1> + 3966979280U, // <1,4,2,4>: Cost 4 vzipl <1,2,3,4>, <4,4,4,4> + 2893204790U, // <1,4,2,5>: Cost 3 vzipl <1,2,3,0>, RHS + 3693086650U, // <1,4,2,6>: Cost 4 vext2 <0,3,1,4>, <2,6,3,7> + 3666662502U, // <1,4,2,7>: Cost 4 vext1 <7,1,4,2>, <7,1,4,2> + 2893205033U, // <1,4,2,u>: Cost 3 vzipl <1,2,3,0>, RHS + 2563063910U, // <1,4,3,0>: Cost 3 vext1 <2,1,4,3>, LHS + 2563064730U, // <1,4,3,1>: Cost 3 vext1 <2,1,4,3>, <1,2,3,4> + 2563065386U, // <1,4,3,2>: Cost 3 vext1 <2,1,4,3>, <2,1,4,3> + 3693087132U, // <1,4,3,3>: Cost 4 vext2 <0,3,1,4>, <3,3,3,3> + 2619345410U, // <1,4,3,4>: Cost 3 vext2 <0,3,1,4>, <3,4,5,6> + 3087843666U, // <1,4,3,5>: Cost 3 vtrnr LHS, <0,4,1,5> + 3087843676U, // <1,4,3,6>: Cost 3 vtrnr LHS, <0,4,2,6> + 3666670695U, // <1,4,3,7>: Cost 4 vext1 <7,1,4,3>, <7,1,4,3> + 3087843669U, // <1,4,3,u>: Cost 3 vtrnr LHS, <0,4,1,u> + 2620672914U, // <1,4,4,0>: Cost 3 vext2 <0,5,1,4>, <4,0,5,1> + 3630842706U, // <1,4,4,1>: Cost 4 vext1 <1,1,4,4>, <1,1,4,4> + 3313069003U, // <1,4,4,2>: Cost 4 vrev <4,1,2,4> + 3642788100U, // <1,4,4,3>: Cost 4 vext1 <3,1,4,4>, <3,1,4,4> + 2713930960U, // <1,4,4,4>: Cost 3 vext3 <4,u,5,1>, <4,4,4,4> + 2619346230U, // <1,4,4,5>: Cost 3 vext2 <0,3,1,4>, RHS + 2713930980U, // <1,4,4,6>: Cost 3 vext3 <4,u,5,1>, <4,4,6,6> + 3736882642U, // <1,4,4,7>: Cost 4 vext2 <7,6,1,4>, <4,7,6,1> + 2619346473U, // <1,4,4,u>: Cost 3 vext2 <0,3,1,4>, RHS + 2557108326U, // <1,4,5,0>: Cost 3 vext1 <1,1,4,5>, LHS + 2557109075U, // <1,4,5,1>: Cost 3 vext1 <1,1,4,5>, <1,1,4,5> + 2598913774U, // <1,4,5,2>: Cost 3 vext1 , <2,3,u,1> + 3630852246U, // <1,4,5,3>: Cost 4 vext1 <1,1,4,5>, <3,0,1,2> + 2557111606U, // <1,4,5,4>: Cost 3 vext1 <1,1,4,5>, RHS + 2895252790U, // <1,4,5,5>: Cost 3 vzipl <1,5,3,7>, RHS + 1616006454U, // <1,4,5,6>: Cost 2 vext3 <0,u,1,1>, RHS + 3899059510U, // <1,4,5,7>: Cost 4 vuzpr <1,1,1,4>, RHS + 1616006472U, // <1,4,5,u>: Cost 2 vext3 <0,u,1,1>, RHS + 2557116518U, // <1,4,6,0>: Cost 3 vext1 <1,1,4,6>, LHS + 2557117236U, // <1,4,6,1>: Cost 3 vext1 <1,1,4,6>, <1,1,1,1> + 3630859880U, // <1,4,6,2>: Cost 4 vext1 <1,1,4,6>, <2,2,2,2> + 2569062550U, // <1,4,6,3>: Cost 3 vext1 <3,1,4,6>, <3,0,1,2> + 2557119798U, // <1,4,6,4>: Cost 3 vext1 <1,1,4,6>, RHS + 3763490174U, // <1,4,6,5>: Cost 4 vext3 <0,u,1,1>, <4,6,5,7> + 3763490183U, // <1,4,6,6>: Cost 4 vext3 <0,u,1,1>, <4,6,6,7> + 2712751498U, // <1,4,6,7>: Cost 3 vext3 <4,6,7,1>, <4,6,7,1> + 2557122350U, // <1,4,6,u>: Cost 3 vext1 <1,1,4,6>, LHS + 2659161084U, // <1,4,7,0>: Cost 3 vext2 <7,0,1,4>, <7,0,1,4> + 3732903040U, // <1,4,7,1>: Cost 4 vext2 <7,0,1,4>, <7,1,7,1> + 3734230174U, // <1,4,7,2>: Cost 4 vext2 <7,2,1,4>, <7,2,1,4> + 3734893807U, // <1,4,7,3>: Cost 4 vext2 <7,3,1,4>, <7,3,1,4> + 3660729654U, // <1,4,7,4>: Cost 4 vext1 <6,1,4,7>, RHS + 3786493384U, // <1,4,7,5>: Cost 4 vext3 <4,6,7,1>, <4,7,5,0> + 2713341394U, // <1,4,7,6>: Cost 3 vext3 <4,7,6,1>, <4,7,6,1> + 3660731386U, // <1,4,7,7>: Cost 4 vext1 <6,1,4,7>, <7,0,1,2> + 2664470148U, // <1,4,7,u>: Cost 3 vext2 <7,u,1,4>, <7,u,1,4> + 2557132902U, // <1,4,u,0>: Cost 3 vext1 <1,1,4,u>, LHS + 2619348782U, // <1,4,u,1>: Cost 3 vext2 <0,3,1,4>, LHS + 2563106351U, // <1,4,u,2>: Cost 3 vext1 <2,1,4,u>, <2,1,4,u> + 2713783816U, // <1,4,u,3>: Cost 3 vext3 <4,u,3,1>, <4,u,3,1> + 2622666815U, // <1,4,u,4>: Cost 3 vext2 <0,u,1,4>, + 1640189466U, // <1,4,u,5>: Cost 2 vext3 <4,u,5,1>, <4,u,5,1> + 1616006697U, // <1,4,u,6>: Cost 2 vext3 <0,u,1,1>, RHS + 2712751498U, // <1,4,u,7>: Cost 3 vext3 <4,6,7,1>, <4,6,7,1> + 1616006715U, // <1,4,u,u>: Cost 2 vext3 <0,u,1,1>, RHS + 2620014592U, // <1,5,0,0>: Cost 3 vext2 <0,4,1,5>, <0,0,0,0> + 1546272870U, // <1,5,0,1>: Cost 2 vext2 <0,4,1,5>, LHS + 2618687664U, // <1,5,0,2>: Cost 3 vext2 <0,2,1,5>, <0,2,1,5> + 3693093120U, // <1,5,0,3>: Cost 4 vext2 <0,3,1,5>, <0,3,1,4> + 1546273106U, // <1,5,0,4>: Cost 2 vext2 <0,4,1,5>, <0,4,1,5> + 2620678563U, // <1,5,0,5>: Cost 3 vext2 <0,5,1,5>, <0,5,1,5> + 2714668660U, // <1,5,0,6>: Cost 3 vext3 <5,0,6,1>, <5,0,6,1> + 3772042877U, // <1,5,0,7>: Cost 4 vext3 <2,3,0,1>, <5,0,7,1> + 1546273437U, // <1,5,0,u>: Cost 2 vext2 <0,4,1,5>, LHS + 2620015350U, // <1,5,1,0>: Cost 3 vext2 <0,4,1,5>, <1,0,3,2> + 2620015412U, // <1,5,1,1>: Cost 3 vext2 <0,4,1,5>, <1,1,1,1> + 2620015510U, // <1,5,1,2>: Cost 3 vext2 <0,4,1,5>, <1,2,3,0> + 2618688512U, // <1,5,1,3>: Cost 3 vext2 <0,2,1,5>, <1,3,5,7> + 2620015677U, // <1,5,1,4>: Cost 3 vext2 <0,4,1,5>, <1,4,3,5> + 2620015727U, // <1,5,1,5>: Cost 3 vext2 <0,4,1,5>, <1,5,0,1> + 2620015859U, // <1,5,1,6>: Cost 3 vext2 <0,4,1,5>, <1,6,5,7> + 3093728566U, // <1,5,1,7>: Cost 3 vtrnr <1,1,1,1>, RHS + 2620015981U, // <1,5,1,u>: Cost 3 vext2 <0,4,1,5>, <1,u,1,3> + 3692430816U, // <1,5,2,0>: Cost 4 vext2 <0,2,1,5>, <2,0,5,1> + 2620016163U, // <1,5,2,1>: Cost 3 vext2 <0,4,1,5>, <2,1,3,5> + 2620016232U, // <1,5,2,2>: Cost 3 vext2 <0,4,1,5>, <2,2,2,2> + 2620016294U, // <1,5,2,3>: Cost 3 vext2 <0,4,1,5>, <2,3,0,1> + 3693758221U, // <1,5,2,4>: Cost 4 vext2 <0,4,1,5>, <2,4,2,5> + 3692431209U, // <1,5,2,5>: Cost 4 vext2 <0,2,1,5>, <2,5,3,7> + 2620016570U, // <1,5,2,6>: Cost 3 vext2 <0,4,1,5>, <2,6,3,7> + 4173598006U, // <1,5,2,7>: Cost 4 vtrnr <2,1,3,2>, RHS + 2620016699U, // <1,5,2,u>: Cost 3 vext2 <0,4,1,5>, <2,u,0,1> + 2620016790U, // <1,5,3,0>: Cost 3 vext2 <0,4,1,5>, <3,0,1,2> + 2569110672U, // <1,5,3,1>: Cost 3 vext1 <3,1,5,3>, <1,5,3,7> + 3693758785U, // <1,5,3,2>: Cost 4 vext2 <0,4,1,5>, <3,2,2,2> + 2620017052U, // <1,5,3,3>: Cost 3 vext2 <0,4,1,5>, <3,3,3,3> + 2620017154U, // <1,5,3,4>: Cost 3 vext2 <0,4,1,5>, <3,4,5,6> + 3135623172U, // <1,5,3,5>: Cost 3 vtrnr LHS, <5,5,5,5> + 4161587048U, // <1,5,3,6>: Cost 4 vtrnr LHS, <2,5,3,6> + 2014104886U, // <1,5,3,7>: Cost 2 vtrnr LHS, RHS + 2014104887U, // <1,5,3,u>: Cost 2 vtrnr LHS, RHS + 2620017554U, // <1,5,4,0>: Cost 3 vext2 <0,4,1,5>, <4,0,5,1> + 2620017634U, // <1,5,4,1>: Cost 3 vext2 <0,4,1,5>, <4,1,5,0> + 3693759551U, // <1,5,4,2>: Cost 4 vext2 <0,4,1,5>, <4,2,6,3> + 3642861837U, // <1,5,4,3>: Cost 4 vext1 <3,1,5,4>, <3,1,5,4> + 2575092710U, // <1,5,4,4>: Cost 3 vext1 <4,1,5,4>, <4,1,5,4> + 1546276150U, // <1,5,4,5>: Cost 2 vext2 <0,4,1,5>, RHS + 2759855414U, // <1,5,4,6>: Cost 3 vuzpl <1,3,5,7>, RHS + 2713931718U, // <1,5,4,7>: Cost 3 vext3 <4,u,5,1>, <5,4,7,6> + 1546276393U, // <1,5,4,u>: Cost 2 vext2 <0,4,1,5>, RHS + 2557182054U, // <1,5,5,0>: Cost 3 vext1 <1,1,5,5>, LHS + 2557182812U, // <1,5,5,1>: Cost 3 vext1 <1,1,5,5>, <1,1,5,5> + 3630925347U, // <1,5,5,2>: Cost 4 vext1 <1,1,5,5>, <2,1,3,5> + 4029301675U, // <1,5,5,3>: Cost 4 vzipr <0,4,1,5>, <1,2,5,3> + 2557185334U, // <1,5,5,4>: Cost 3 vext1 <1,1,5,5>, RHS + 2713931780U, // <1,5,5,5>: Cost 3 vext3 <4,u,5,1>, <5,5,5,5> + 2667794530U, // <1,5,5,6>: Cost 3 vext2 , <5,6,7,0> + 2713931800U, // <1,5,5,7>: Cost 3 vext3 <4,u,5,1>, <5,5,7,7> + 2557187886U, // <1,5,5,u>: Cost 3 vext1 <1,1,5,5>, LHS + 2718208036U, // <1,5,6,0>: Cost 3 vext3 <5,6,0,1>, <5,6,0,1> + 2620019115U, // <1,5,6,1>: Cost 3 vext2 <0,4,1,5>, <6,1,7,5> + 2667794938U, // <1,5,6,2>: Cost 3 vext2 , <6,2,7,3> + 3787673666U, // <1,5,6,3>: Cost 4 vext3 <4,u,5,1>, <5,6,3,4> + 3693761165U, // <1,5,6,4>: Cost 4 vext2 <0,4,1,5>, <6,4,5,6> + 3319279297U, // <1,5,6,5>: Cost 4 vrev <5,1,5,6> + 2667795256U, // <1,5,6,6>: Cost 3 vext2 , <6,6,6,6> + 2713931874U, // <1,5,6,7>: Cost 3 vext3 <4,u,5,1>, <5,6,7,0> + 2713931883U, // <1,5,6,u>: Cost 3 vext3 <4,u,5,1>, <5,6,u,0> + 2557198438U, // <1,5,7,0>: Cost 3 vext1 <1,1,5,7>, LHS + 2557199156U, // <1,5,7,1>: Cost 3 vext1 <1,1,5,7>, <1,1,1,1> + 2569143974U, // <1,5,7,2>: Cost 3 vext1 <3,1,5,7>, <2,3,0,1> + 2569144592U, // <1,5,7,3>: Cost 3 vext1 <3,1,5,7>, <3,1,5,7> + 2557201718U, // <1,5,7,4>: Cost 3 vext1 <1,1,5,7>, RHS + 2713931944U, // <1,5,7,5>: Cost 3 vext3 <4,u,5,1>, <5,7,5,7> + 3787673770U, // <1,5,7,6>: Cost 4 vext3 <4,u,5,1>, <5,7,6,0> + 2719387828U, // <1,5,7,7>: Cost 3 vext3 <5,7,7,1>, <5,7,7,1> + 2557204270U, // <1,5,7,u>: Cost 3 vext1 <1,1,5,7>, LHS + 2620020435U, // <1,5,u,0>: Cost 3 vext2 <0,4,1,5>, + 1546278702U, // <1,5,u,1>: Cost 2 vext2 <0,4,1,5>, LHS + 2620020616U, // <1,5,u,2>: Cost 3 vext2 <0,4,1,5>, + 2620020668U, // <1,5,u,3>: Cost 3 vext2 <0,4,1,5>, + 1594054682U, // <1,5,u,4>: Cost 2 vext2 , + 1546279066U, // <1,5,u,5>: Cost 2 vext2 <0,4,1,5>, RHS + 2620020944U, // <1,5,u,6>: Cost 3 vext2 <0,4,1,5>, + 2014145846U, // <1,5,u,7>: Cost 2 vtrnr LHS, RHS + 2014145847U, // <1,5,u,u>: Cost 2 vtrnr LHS, RHS + 3692437504U, // <1,6,0,0>: Cost 4 vext2 <0,2,1,6>, <0,0,0,0> + 2618695782U, // <1,6,0,1>: Cost 3 vext2 <0,2,1,6>, LHS + 2618695857U, // <1,6,0,2>: Cost 3 vext2 <0,2,1,6>, <0,2,1,6> + 3794161970U, // <1,6,0,3>: Cost 4 vext3 <6,0,3,1>, <6,0,3,1> + 2620023122U, // <1,6,0,4>: Cost 3 vext2 <0,4,1,6>, <0,4,1,5> + 2620686756U, // <1,6,0,5>: Cost 3 vext2 <0,5,1,6>, <0,5,1,6> + 2621350389U, // <1,6,0,6>: Cost 3 vext2 <0,6,1,6>, <0,6,1,6> + 4028599606U, // <1,6,0,7>: Cost 4 vzipr <0,3,1,0>, RHS + 2618696349U, // <1,6,0,u>: Cost 3 vext2 <0,2,1,6>, LHS + 3692438262U, // <1,6,1,0>: Cost 4 vext2 <0,2,1,6>, <1,0,3,2> + 2625995572U, // <1,6,1,1>: Cost 3 vext2 <1,4,1,6>, <1,1,1,1> + 3692438422U, // <1,6,1,2>: Cost 4 vext2 <0,2,1,6>, <1,2,3,0> + 3692438488U, // <1,6,1,3>: Cost 4 vext2 <0,2,1,6>, <1,3,1,3> + 2625995820U, // <1,6,1,4>: Cost 3 vext2 <1,4,1,6>, <1,4,1,6> + 3692438672U, // <1,6,1,5>: Cost 4 vext2 <0,2,1,6>, <1,5,3,7> + 3692438720U, // <1,6,1,6>: Cost 4 vext2 <0,2,1,6>, <1,6,0,1> + 2958183734U, // <1,6,1,7>: Cost 3 vzipr <0,u,1,1>, RHS + 2958183735U, // <1,6,1,u>: Cost 3 vzipr <0,u,1,1>, RHS + 2721526201U, // <1,6,2,0>: Cost 3 vext3 <6,2,0,1>, <6,2,0,1> + 3692439097U, // <1,6,2,1>: Cost 4 vext2 <0,2,1,6>, <2,1,6,0> + 3692439144U, // <1,6,2,2>: Cost 4 vext2 <0,2,1,6>, <2,2,2,2> + 3692439206U, // <1,6,2,3>: Cost 4 vext2 <0,2,1,6>, <2,3,0,1> + 3636948278U, // <1,6,2,4>: Cost 4 vext1 <2,1,6,2>, RHS + 3787674092U, // <1,6,2,5>: Cost 4 vext3 <4,u,5,1>, <6,2,5,7> + 2618697658U, // <1,6,2,6>: Cost 3 vext2 <0,2,1,6>, <2,6,3,7> + 2970799414U, // <1,6,2,7>: Cost 3 vzipr <3,0,1,2>, RHS + 2970799415U, // <1,6,2,u>: Cost 3 vzipr <3,0,1,2>, RHS + 2563211366U, // <1,6,3,0>: Cost 3 vext1 <2,1,6,3>, LHS + 3699738854U, // <1,6,3,1>: Cost 4 vext2 <1,4,1,6>, <3,1,1,1> + 2563212860U, // <1,6,3,2>: Cost 3 vext1 <2,1,6,3>, <2,1,6,3> + 3692439964U, // <1,6,3,3>: Cost 4 vext2 <0,2,1,6>, <3,3,3,3> + 2563214646U, // <1,6,3,4>: Cost 3 vext1 <2,1,6,3>, RHS + 4191820018U, // <1,6,3,5>: Cost 4 vtrnr <5,1,7,3>, + 2587103648U, // <1,6,3,6>: Cost 3 vext1 <6,1,6,3>, <6,1,6,3> + 3087845306U, // <1,6,3,7>: Cost 3 vtrnr LHS, <2,6,3,7> + 3087845307U, // <1,6,3,u>: Cost 3 vtrnr LHS, <2,6,3,u> + 3693767570U, // <1,6,4,0>: Cost 4 vext2 <0,4,1,6>, <4,0,5,1> + 3693767650U, // <1,6,4,1>: Cost 4 vext2 <0,4,1,6>, <4,1,5,0> + 3636962877U, // <1,6,4,2>: Cost 4 vext1 <2,1,6,4>, <2,1,6,4> + 3325088134U, // <1,6,4,3>: Cost 4 vrev <6,1,3,4> + 3693767898U, // <1,6,4,4>: Cost 4 vext2 <0,4,1,6>, <4,4,5,5> + 2618699062U, // <1,6,4,5>: Cost 3 vext2 <0,2,1,6>, RHS + 3833670966U, // <1,6,4,6>: Cost 4 vuzpl <1,3,6,7>, RHS + 4028632374U, // <1,6,4,7>: Cost 4 vzipr <0,3,1,4>, RHS + 2618699305U, // <1,6,4,u>: Cost 3 vext2 <0,2,1,6>, RHS + 3693768264U, // <1,6,5,0>: Cost 4 vext2 <0,4,1,6>, <5,0,1,2> + 3630998373U, // <1,6,5,1>: Cost 4 vext1 <1,1,6,5>, <1,1,6,5> + 3636971070U, // <1,6,5,2>: Cost 4 vext1 <2,1,6,5>, <2,1,6,5> + 3642943767U, // <1,6,5,3>: Cost 4 vext1 <3,1,6,5>, <3,1,6,5> + 3693768628U, // <1,6,5,4>: Cost 4 vext2 <0,4,1,6>, <5,4,5,6> + 3732918276U, // <1,6,5,5>: Cost 4 vext2 <7,0,1,6>, <5,5,5,5> + 2620690530U, // <1,6,5,6>: Cost 3 vext2 <0,5,1,6>, <5,6,7,0> + 2955562294U, // <1,6,5,7>: Cost 3 vzipr <0,4,1,5>, RHS + 2955562295U, // <1,6,5,u>: Cost 3 vzipr <0,4,1,5>, RHS + 2724180733U, // <1,6,6,0>: Cost 3 vext3 <6,6,0,1>, <6,6,0,1> + 3631006566U, // <1,6,6,1>: Cost 4 vext1 <1,1,6,6>, <1,1,6,6> + 3631007674U, // <1,6,6,2>: Cost 4 vext1 <1,1,6,6>, <2,6,3,7> + 3692442184U, // <1,6,6,3>: Cost 4 vext2 <0,2,1,6>, <6,3,7,0> + 3631009078U, // <1,6,6,4>: Cost 4 vext1 <1,1,6,6>, RHS + 3787674416U, // <1,6,6,5>: Cost 4 vext3 <4,u,5,1>, <6,6,5,7> + 2713932600U, // <1,6,6,6>: Cost 3 vext3 <4,u,5,1>, <6,6,6,6> + 2713932610U, // <1,6,6,7>: Cost 3 vext3 <4,u,5,1>, <6,6,7,7> + 2713932619U, // <1,6,6,u>: Cost 3 vext3 <4,u,5,1>, <6,6,u,7> + 1651102542U, // <1,6,7,0>: Cost 2 vext3 <6,7,0,1>, <6,7,0,1> + 2724918103U, // <1,6,7,1>: Cost 3 vext3 <6,7,1,1>, <6,7,1,1> + 2698302306U, // <1,6,7,2>: Cost 3 vext3 <2,3,0,1>, <6,7,2,3> + 3642960153U, // <1,6,7,3>: Cost 4 vext1 <3,1,6,7>, <3,1,6,7> + 2713932662U, // <1,6,7,4>: Cost 3 vext3 <4,u,5,1>, <6,7,4,5> + 2725213051U, // <1,6,7,5>: Cost 3 vext3 <6,7,5,1>, <6,7,5,1> + 2724844426U, // <1,6,7,6>: Cost 3 vext3 <6,7,0,1>, <6,7,6,7> + 4035956022U, // <1,6,7,7>: Cost 4 vzipr <1,5,1,7>, RHS + 1651692438U, // <1,6,7,u>: Cost 2 vext3 <6,7,u,1>, <6,7,u,1> + 1651766175U, // <1,6,u,0>: Cost 2 vext3 <6,u,0,1>, <6,u,0,1> + 2618701614U, // <1,6,u,1>: Cost 3 vext2 <0,2,1,6>, LHS + 3135663508U, // <1,6,u,2>: Cost 3 vtrnr LHS, <4,6,u,2> + 3692443580U, // <1,6,u,3>: Cost 4 vext2 <0,2,1,6>, + 2713932743U, // <1,6,u,4>: Cost 3 vext3 <4,u,5,1>, <6,u,4,5> + 2618701978U, // <1,6,u,5>: Cost 3 vext2 <0,2,1,6>, RHS + 2622683344U, // <1,6,u,6>: Cost 3 vext2 <0,u,1,6>, + 3087886266U, // <1,6,u,7>: Cost 3 vtrnr LHS, <2,6,3,7> + 1652356071U, // <1,6,u,u>: Cost 2 vext3 <6,u,u,1>, <6,u,u,1> + 2726171632U, // <1,7,0,0>: Cost 3 vext3 <7,0,0,1>, <7,0,0,1> + 2626666598U, // <1,7,0,1>: Cost 3 vext2 <1,5,1,7>, LHS + 3695100067U, // <1,7,0,2>: Cost 4 vext2 <0,6,1,7>, <0,2,0,1> + 3707044102U, // <1,7,0,3>: Cost 4 vext2 <2,6,1,7>, <0,3,2,1> + 2726466580U, // <1,7,0,4>: Cost 3 vext3 <7,0,4,1>, <7,0,4,1> + 3654921933U, // <1,7,0,5>: Cost 4 vext1 <5,1,7,0>, <5,1,7,0> + 2621358582U, // <1,7,0,6>: Cost 3 vext2 <0,6,1,7>, <0,6,1,7> + 2622022215U, // <1,7,0,7>: Cost 3 vext2 <0,7,1,7>, <0,7,1,7> + 2626667165U, // <1,7,0,u>: Cost 3 vext2 <1,5,1,7>, LHS + 2593128550U, // <1,7,1,0>: Cost 3 vext1 <7,1,7,1>, LHS + 2626667316U, // <1,7,1,1>: Cost 3 vext2 <1,5,1,7>, <1,1,1,1> + 3700409238U, // <1,7,1,2>: Cost 4 vext2 <1,5,1,7>, <1,2,3,0> + 2257294428U, // <1,7,1,3>: Cost 3 vrev <7,1,3,1> + 2593131830U, // <1,7,1,4>: Cost 3 vext1 <7,1,7,1>, RHS + 2626667646U, // <1,7,1,5>: Cost 3 vext2 <1,5,1,7>, <1,5,1,7> + 2627331279U, // <1,7,1,6>: Cost 3 vext2 <1,6,1,7>, <1,6,1,7> + 2593133696U, // <1,7,1,7>: Cost 3 vext1 <7,1,7,1>, <7,1,7,1> + 2628658545U, // <1,7,1,u>: Cost 3 vext2 <1,u,1,7>, <1,u,1,7> + 2587164774U, // <1,7,2,0>: Cost 3 vext1 <6,1,7,2>, LHS + 3701073445U, // <1,7,2,1>: Cost 4 vext2 <1,6,1,7>, <2,1,3,7> + 3700409960U, // <1,7,2,2>: Cost 4 vext2 <1,5,1,7>, <2,2,2,2> + 2638612134U, // <1,7,2,3>: Cost 3 vext2 <3,5,1,7>, <2,3,0,1> + 2587168054U, // <1,7,2,4>: Cost 3 vext1 <6,1,7,2>, RHS + 3706382167U, // <1,7,2,5>: Cost 4 vext2 <2,5,1,7>, <2,5,1,7> + 2587169192U, // <1,7,2,6>: Cost 3 vext1 <6,1,7,2>, <6,1,7,2> + 3660911610U, // <1,7,2,7>: Cost 4 vext1 <6,1,7,2>, <7,0,1,2> + 2587170606U, // <1,7,2,u>: Cost 3 vext1 <6,1,7,2>, LHS + 1507459174U, // <1,7,3,0>: Cost 2 vext1 <5,1,7,3>, LHS + 2569257984U, // <1,7,3,1>: Cost 3 vext1 <3,1,7,3>, <1,3,5,7> + 2581202536U, // <1,7,3,2>: Cost 3 vext1 <5,1,7,3>, <2,2,2,2> + 2569259294U, // <1,7,3,3>: Cost 3 vext1 <3,1,7,3>, <3,1,7,3> + 1507462454U, // <1,7,3,4>: Cost 2 vext1 <5,1,7,3>, RHS + 1507462864U, // <1,7,3,5>: Cost 2 vext1 <5,1,7,3>, <5,1,7,3> + 2581205498U, // <1,7,3,6>: Cost 3 vext1 <5,1,7,3>, <6,2,7,3> + 2581206010U, // <1,7,3,7>: Cost 3 vext1 <5,1,7,3>, <7,0,1,2> + 1507465006U, // <1,7,3,u>: Cost 2 vext1 <5,1,7,3>, LHS + 2728826164U, // <1,7,4,0>: Cost 3 vext3 <7,4,0,1>, <7,4,0,1> + 3654951732U, // <1,7,4,1>: Cost 4 vext1 <5,1,7,4>, <1,1,1,1> + 3330987094U, // <1,7,4,2>: Cost 4 vrev <7,1,2,4> + 3331060831U, // <1,7,4,3>: Cost 4 vrev <7,1,3,4> + 3787674971U, // <1,7,4,4>: Cost 4 vext3 <4,u,5,1>, <7,4,4,4> + 2626669878U, // <1,7,4,5>: Cost 3 vext2 <1,5,1,7>, RHS + 3785979241U, // <1,7,4,6>: Cost 4 vext3 <4,6,0,1>, <7,4,6,0> + 3787085176U, // <1,7,4,7>: Cost 4 vext3 <4,7,6,1>, <7,4,7,6> + 2626670121U, // <1,7,4,u>: Cost 3 vext2 <1,5,1,7>, RHS + 2569273446U, // <1,7,5,0>: Cost 3 vext1 <3,1,7,5>, LHS + 2569274368U, // <1,7,5,1>: Cost 3 vext1 <3,1,7,5>, <1,3,5,7> + 3643016808U, // <1,7,5,2>: Cost 4 vext1 <3,1,7,5>, <2,2,2,2> + 2569275680U, // <1,7,5,3>: Cost 3 vext1 <3,1,7,5>, <3,1,7,5> + 2569276726U, // <1,7,5,4>: Cost 3 vext1 <3,1,7,5>, RHS + 4102034790U, // <1,7,5,5>: Cost 4 vtrnl <1,3,5,7>, <7,4,5,6> + 2651222067U, // <1,7,5,6>: Cost 3 vext2 <5,6,1,7>, <5,6,1,7> + 3899378998U, // <1,7,5,7>: Cost 4 vuzpr <1,1,5,7>, RHS + 2569279278U, // <1,7,5,u>: Cost 3 vext1 <3,1,7,5>, LHS + 2730153430U, // <1,7,6,0>: Cost 3 vext3 <7,6,0,1>, <7,6,0,1> + 2724845022U, // <1,7,6,1>: Cost 3 vext3 <6,7,0,1>, <7,6,1,0> + 3643025338U, // <1,7,6,2>: Cost 4 vext1 <3,1,7,6>, <2,6,3,7> + 3643025697U, // <1,7,6,3>: Cost 4 vext1 <3,1,7,6>, <3,1,7,6> + 3643026742U, // <1,7,6,4>: Cost 4 vext1 <3,1,7,6>, RHS + 3654971091U, // <1,7,6,5>: Cost 4 vext1 <5,1,7,6>, <5,1,7,6> + 3787675153U, // <1,7,6,6>: Cost 4 vext3 <4,u,5,1>, <7,6,6,6> + 2724845076U, // <1,7,6,7>: Cost 3 vext3 <6,7,0,1>, <7,6,7,0> + 2725508637U, // <1,7,6,u>: Cost 3 vext3 <6,u,0,1>, <7,6,u,0> + 2730817063U, // <1,7,7,0>: Cost 3 vext3 <7,7,0,1>, <7,7,0,1> + 3631088436U, // <1,7,7,1>: Cost 4 vext1 <1,1,7,7>, <1,1,1,1> + 3660949158U, // <1,7,7,2>: Cost 4 vext1 <6,1,7,7>, <2,3,0,1> + 3801904705U, // <1,7,7,3>: Cost 4 vext3 <7,3,0,1>, <7,7,3,0> + 3631090998U, // <1,7,7,4>: Cost 4 vext1 <1,1,7,7>, RHS + 2662503828U, // <1,7,7,5>: Cost 3 vext2 <7,5,1,7>, <7,5,1,7> + 3660951981U, // <1,7,7,6>: Cost 4 vext1 <6,1,7,7>, <6,1,7,7> + 2713933420U, // <1,7,7,7>: Cost 3 vext3 <4,u,5,1>, <7,7,7,7> + 2731406959U, // <1,7,7,u>: Cost 3 vext3 <7,7,u,1>, <7,7,u,1> + 1507500134U, // <1,7,u,0>: Cost 2 vext1 <5,1,7,u>, LHS + 2626672430U, // <1,7,u,1>: Cost 3 vext2 <1,5,1,7>, LHS + 2581243496U, // <1,7,u,2>: Cost 3 vext1 <5,1,7,u>, <2,2,2,2> + 2569300259U, // <1,7,u,3>: Cost 3 vext1 <3,1,7,u>, <3,1,7,u> + 1507503414U, // <1,7,u,4>: Cost 2 vext1 <5,1,7,u>, RHS + 1507503829U, // <1,7,u,5>: Cost 2 vext1 <5,1,7,u>, <5,1,7,u> + 2581246458U, // <1,7,u,6>: Cost 3 vext1 <5,1,7,u>, <6,2,7,3> + 2581246970U, // <1,7,u,7>: Cost 3 vext1 <5,1,7,u>, <7,0,1,2> + 1507505966U, // <1,7,u,u>: Cost 2 vext1 <5,1,7,u>, LHS + 1543643153U, // <1,u,0,0>: Cost 2 vext2 <0,0,1,u>, <0,0,1,u> + 1546297446U, // <1,u,0,1>: Cost 2 vext2 <0,4,1,u>, LHS + 2819448852U, // <1,u,0,2>: Cost 3 vuzpr LHS, <0,0,2,2> + 2619375876U, // <1,u,0,3>: Cost 3 vext2 <0,3,1,u>, <0,3,1,u> + 1546297685U, // <1,u,0,4>: Cost 2 vext2 <0,4,1,u>, <0,4,1,u> + 1658771190U, // <1,u,0,5>: Cost 2 vext3 , + 2736789248U, // <1,u,0,6>: Cost 3 vext3 , + 2659189376U, // <1,u,0,7>: Cost 3 vext2 <7,0,1,u>, <0,7,u,1> + 1546298013U, // <1,u,0,u>: Cost 2 vext2 <0,4,1,u>, LHS + 1483112550U, // <1,u,1,0>: Cost 2 vext1 <1,1,1,1>, LHS + 202162278U, // <1,u,1,1>: Cost 1 vdup1 LHS + 1616009006U, // <1,u,1,2>: Cost 2 vext3 <0,u,1,1>, LHS + 1745707110U, // <1,u,1,3>: Cost 2 vuzpr LHS, LHS + 1483115830U, // <1,u,1,4>: Cost 2 vext1 <1,1,1,1>, RHS + 2620040336U, // <1,u,1,5>: Cost 3 vext2 <0,4,1,u>, <1,5,3,7> + 3026622618U, // <1,u,1,6>: Cost 3 vtrnl <1,1,1,1>, RHS + 2958183752U, // <1,u,1,7>: Cost 3 vzipr <0,u,1,1>, RHS + 202162278U, // <1,u,1,u>: Cost 1 vdup1 LHS + 2819449750U, // <1,u,2,0>: Cost 3 vuzpr LHS, <1,2,3,0> + 2893207342U, // <1,u,2,1>: Cost 3 vzipl <1,2,3,0>, LHS + 2819448996U, // <1,u,2,2>: Cost 3 vuzpr LHS, <0,2,0,2> + 2819450482U, // <1,u,2,3>: Cost 3 vuzpr LHS, <2,2,3,3> + 2819449754U, // <1,u,2,4>: Cost 3 vuzpr LHS, <1,2,3,4> + 2893207706U, // <1,u,2,5>: Cost 3 vzipl <1,2,3,0>, RHS + 2819449036U, // <1,u,2,6>: Cost 3 vuzpr LHS, <0,2,4,6> + 2970799432U, // <1,u,2,7>: Cost 3 vzipr <3,0,1,2>, RHS + 2819449002U, // <1,u,2,u>: Cost 3 vuzpr LHS, <0,2,0,u> + 403931292U, // <1,u,3,0>: Cost 1 vext1 LHS, LHS + 1477673718U, // <1,u,3,1>: Cost 2 vext1 LHS, <1,0,3,2> + 115726126U, // <1,u,3,2>: Cost 1 vrev LHS + 2014102173U, // <1,u,3,3>: Cost 2 vtrnr LHS, LHS + 403934518U, // <1,u,3,4>: Cost 1 vext1 LHS, RHS + 1507536601U, // <1,u,3,5>: Cost 2 vext1 <5,1,u,3>, <5,1,u,3> + 1525453306U, // <1,u,3,6>: Cost 2 vext1 LHS, <6,2,7,3> + 2014105129U, // <1,u,3,7>: Cost 2 vtrnr LHS, RHS + 403937070U, // <1,u,3,u>: Cost 1 vext1 LHS, LHS + 2620042157U, // <1,u,4,0>: Cost 3 vext2 <0,4,1,u>, <4,0,u,1> + 2620042237U, // <1,u,4,1>: Cost 3 vext2 <0,4,1,u>, <4,1,u,0> + 2263217967U, // <1,u,4,2>: Cost 3 vrev + 2569341224U, // <1,u,4,3>: Cost 3 vext1 <3,1,u,4>, <3,1,u,4> + 2569342262U, // <1,u,4,4>: Cost 3 vext1 <3,1,u,4>, RHS + 1546300726U, // <1,u,4,5>: Cost 2 vext2 <0,4,1,u>, RHS + 2819449180U, // <1,u,4,6>: Cost 3 vuzpr LHS, <0,4,2,6> + 2724845649U, // <1,u,4,7>: Cost 3 vext3 <6,7,0,1>, + 1546300969U, // <1,u,4,u>: Cost 2 vext2 <0,4,1,u>, RHS + 2551431270U, // <1,u,5,0>: Cost 3 vext1 <0,1,u,5>, LHS + 2551432192U, // <1,u,5,1>: Cost 3 vext1 <0,1,u,5>, <1,3,5,7> + 3028293422U, // <1,u,5,2>: Cost 3 vtrnl <1,3,5,7>, LHS + 2955559068U, // <1,u,5,3>: Cost 3 vzipr <0,4,1,5>, LHS + 2551434550U, // <1,u,5,4>: Cost 3 vext1 <0,1,u,5>, RHS + 2895255706U, // <1,u,5,5>: Cost 3 vzipl <1,5,3,7>, RHS + 1616009370U, // <1,u,5,6>: Cost 2 vext3 <0,u,1,1>, RHS + 1745710390U, // <1,u,5,7>: Cost 2 vuzpr LHS, RHS + 1745710391U, // <1,u,5,u>: Cost 2 vuzpr LHS, RHS + 2653221159U, // <1,u,6,0>: Cost 3 vext2 <6,0,1,u>, <6,0,1,u> + 2725509303U, // <1,u,6,1>: Cost 3 vext3 <6,u,0,1>, + 2659193338U, // <1,u,6,2>: Cost 3 vext2 <7,0,1,u>, <6,2,7,3> + 2689751248U, // <1,u,6,3>: Cost 3 vext3 <0,u,1,1>, + 2867228774U, // <1,u,6,4>: Cost 3 vuzpr LHS, <5,6,7,4> + 3764820194U, // <1,u,6,5>: Cost 4 vext3 <1,1,1,1>, + 2657202957U, // <1,u,6,6>: Cost 3 vext2 <6,6,1,u>, <6,6,1,u> + 2819450810U, // <1,u,6,7>: Cost 3 vuzpr LHS, <2,6,3,7> + 2819450811U, // <1,u,6,u>: Cost 3 vuzpr LHS, <2,6,3,u> + 1585452032U, // <1,u,7,0>: Cost 2 vext2 <7,0,1,u>, <7,0,1,u> + 2557420340U, // <1,u,7,1>: Cost 3 vext1 <1,1,u,7>, <1,1,1,1> + 2569365158U, // <1,u,7,2>: Cost 3 vext1 <3,1,u,7>, <2,3,0,1> + 2569365803U, // <1,u,7,3>: Cost 3 vext1 <3,1,u,7>, <3,1,u,7> + 2557422902U, // <1,u,7,4>: Cost 3 vext1 <1,1,u,7>, RHS + 2662512021U, // <1,u,7,5>: Cost 3 vext2 <7,5,1,u>, <7,5,1,u> + 2724845884U, // <1,u,7,6>: Cost 3 vext3 <6,7,0,1>, + 2659194476U, // <1,u,7,7>: Cost 3 vext2 <7,0,1,u>, <7,7,7,7> + 1590761096U, // <1,u,7,u>: Cost 2 vext2 <7,u,1,u>, <7,u,1,u> + 403972257U, // <1,u,u,0>: Cost 1 vext1 LHS, LHS + 202162278U, // <1,u,u,1>: Cost 1 vdup1 LHS + 115767091U, // <1,u,u,2>: Cost 1 vrev LHS + 1745707677U, // <1,u,u,3>: Cost 2 vuzpr LHS, LHS + 403975478U, // <1,u,u,4>: Cost 1 vext1 LHS, RHS + 1546303642U, // <1,u,u,5>: Cost 2 vext2 <0,4,1,u>, RHS + 1616009613U, // <1,u,u,6>: Cost 2 vext3 <0,u,1,1>, RHS + 1745710633U, // <1,u,u,7>: Cost 2 vuzpr LHS, RHS + 403978030U, // <1,u,u,u>: Cost 1 vext1 LHS, LHS + 2551463936U, // <2,0,0,0>: Cost 3 vext1 <0,2,0,0>, <0,0,0,0> + 2685698058U, // <2,0,0,1>: Cost 3 vext3 <0,2,0,2>, <0,0,1,1> + 1610776596U, // <2,0,0,2>: Cost 2 vext3 <0,0,2,2>, <0,0,2,2> + 2619384069U, // <2,0,0,3>: Cost 3 vext2 <0,3,2,0>, <0,3,2,0> + 2551467318U, // <2,0,0,4>: Cost 3 vext1 <0,2,0,0>, RHS + 3899836596U, // <2,0,0,5>: Cost 4 vuzpr <1,2,3,0>, <3,0,4,5> + 2621374968U, // <2,0,0,6>: Cost 3 vext2 <0,6,2,0>, <0,6,2,0> + 4168271334U, // <2,0,0,7>: Cost 4 vtrnr <1,2,3,0>, <2,0,5,7> + 1611219018U, // <2,0,0,u>: Cost 2 vext3 <0,0,u,2>, <0,0,u,2> + 2551472138U, // <2,0,1,0>: Cost 3 vext1 <0,2,0,1>, <0,0,1,1> + 2690564186U, // <2,0,1,1>: Cost 3 vext3 <1,0,3,2>, <0,1,1,0> + 1611956326U, // <2,0,1,2>: Cost 2 vext3 <0,2,0,2>, LHS + 2826092646U, // <2,0,1,3>: Cost 3 vuzpr <1,2,3,0>, LHS + 2551475510U, // <2,0,1,4>: Cost 3 vext1 <0,2,0,1>, RHS + 3692463248U, // <2,0,1,5>: Cost 4 vext2 <0,2,2,0>, <1,5,3,7> + 2587308473U, // <2,0,1,6>: Cost 3 vext1 <6,2,0,1>, <6,2,0,1> + 3661050874U, // <2,0,1,7>: Cost 4 vext1 <6,2,0,1>, <7,0,1,2> + 1611956380U, // <2,0,1,u>: Cost 2 vext3 <0,2,0,2>, LHS + 1477738598U, // <2,0,2,0>: Cost 2 vext1 <0,2,0,2>, LHS + 2551481078U, // <2,0,2,1>: Cost 3 vext1 <0,2,0,2>, <1,0,3,2> + 2551481796U, // <2,0,2,2>: Cost 3 vext1 <0,2,0,2>, <2,0,2,0> + 2551482518U, // <2,0,2,3>: Cost 3 vext1 <0,2,0,2>, <3,0,1,2> + 1477741878U, // <2,0,2,4>: Cost 2 vext1 <0,2,0,2>, RHS + 2551484112U, // <2,0,2,5>: Cost 3 vext1 <0,2,0,2>, <5,1,7,3> + 2551484759U, // <2,0,2,6>: Cost 3 vext1 <0,2,0,2>, <6,0,7,2> + 2551485434U, // <2,0,2,7>: Cost 3 vext1 <0,2,0,2>, <7,0,1,2> + 1477744430U, // <2,0,2,u>: Cost 2 vext1 <0,2,0,2>, LHS + 2953625600U, // <2,0,3,0>: Cost 3 vzipr LHS, <0,0,0,0> + 2953627302U, // <2,0,3,1>: Cost 3 vzipr LHS, <2,3,0,1> + 2953625764U, // <2,0,3,2>: Cost 3 vzipr LHS, <0,2,0,2> + 4027369695U, // <2,0,3,3>: Cost 4 vzipr LHS, <3,1,0,3> + 3625233718U, // <2,0,3,4>: Cost 4 vext1 <0,2,0,3>, RHS + 3899836110U, // <2,0,3,5>: Cost 4 vuzpr <1,2,3,0>, <2,3,4,5> + 4032012618U, // <2,0,3,6>: Cost 4 vzipr LHS, <0,4,0,6> + 3899835392U, // <2,0,3,7>: Cost 4 vuzpr <1,2,3,0>, <1,3,5,7> + 2953625770U, // <2,0,3,u>: Cost 3 vzipr LHS, <0,2,0,u> + 2551496806U, // <2,0,4,0>: Cost 3 vext1 <0,2,0,4>, LHS + 2685698386U, // <2,0,4,1>: Cost 3 vext3 <0,2,0,2>, <0,4,1,5> + 2685698396U, // <2,0,4,2>: Cost 3 vext3 <0,2,0,2>, <0,4,2,6> + 3625240726U, // <2,0,4,3>: Cost 4 vext1 <0,2,0,4>, <3,0,1,2> + 2551500086U, // <2,0,4,4>: Cost 3 vext1 <0,2,0,4>, RHS + 2618723638U, // <2,0,4,5>: Cost 3 vext2 <0,2,2,0>, RHS + 2765409590U, // <2,0,4,6>: Cost 3 vuzpl <2,3,0,1>, RHS + 3799990664U, // <2,0,4,7>: Cost 4 vext3 <7,0,1,2>, <0,4,7,5> + 2685698450U, // <2,0,4,u>: Cost 3 vext3 <0,2,0,2>, <0,4,u,6> + 3625246822U, // <2,0,5,0>: Cost 4 vext1 <0,2,0,5>, LHS + 3289776304U, // <2,0,5,1>: Cost 4 vrev <0,2,1,5> + 2690564526U, // <2,0,5,2>: Cost 3 vext3 <1,0,3,2>, <0,5,2,7> + 3289923778U, // <2,0,5,3>: Cost 4 vrev <0,2,3,5> + 2216255691U, // <2,0,5,4>: Cost 3 vrev <0,2,4,5> + 3726307332U, // <2,0,5,5>: Cost 4 vext2 <5,u,2,0>, <5,5,5,5> + 3726307426U, // <2,0,5,6>: Cost 4 vext2 <5,u,2,0>, <5,6,7,0> + 2826095926U, // <2,0,5,7>: Cost 3 vuzpr <1,2,3,0>, RHS + 2216550639U, // <2,0,5,u>: Cost 3 vrev <0,2,u,5> + 4162420736U, // <2,0,6,0>: Cost 4 vtrnr <0,2,4,6>, <0,0,0,0> + 2901885030U, // <2,0,6,1>: Cost 3 vzipl <2,6,3,7>, LHS + 2685698559U, // <2,0,6,2>: Cost 3 vext3 <0,2,0,2>, <0,6,2,7> + 3643173171U, // <2,0,6,3>: Cost 4 vext1 <3,2,0,6>, <3,2,0,6> + 2216263884U, // <2,0,6,4>: Cost 3 vrev <0,2,4,6> + 3730289341U, // <2,0,6,5>: Cost 4 vext2 <6,5,2,0>, <6,5,2,0> + 3726308152U, // <2,0,6,6>: Cost 4 vext2 <5,u,2,0>, <6,6,6,6> + 3899836346U, // <2,0,6,7>: Cost 4 vuzpr <1,2,3,0>, <2,6,3,7> + 2216558832U, // <2,0,6,u>: Cost 3 vrev <0,2,u,6> + 2659202049U, // <2,0,7,0>: Cost 3 vext2 <7,0,2,0>, <7,0,2,0> + 3726308437U, // <2,0,7,1>: Cost 4 vext2 <5,u,2,0>, <7,1,2,3> + 2726249034U, // <2,0,7,2>: Cost 3 vext3 <7,0,1,2>, <0,7,2,1> + 3734934772U, // <2,0,7,3>: Cost 4 vext2 <7,3,2,0>, <7,3,2,0> + 3726308710U, // <2,0,7,4>: Cost 4 vext2 <5,u,2,0>, <7,4,5,6> + 3726308814U, // <2,0,7,5>: Cost 4 vext2 <5,u,2,0>, <7,5,u,2> + 3736925671U, // <2,0,7,6>: Cost 4 vext2 <7,6,2,0>, <7,6,2,0> + 3726308972U, // <2,0,7,7>: Cost 4 vext2 <5,u,2,0>, <7,7,7,7> + 2659202049U, // <2,0,7,u>: Cost 3 vext2 <7,0,2,0>, <7,0,2,0> + 1477787750U, // <2,0,u,0>: Cost 2 vext1 <0,2,0,u>, LHS + 2953668262U, // <2,0,u,1>: Cost 3 vzipr LHS, <2,3,0,1> + 1611956893U, // <2,0,u,2>: Cost 2 vext3 <0,2,0,2>, LHS + 2551531670U, // <2,0,u,3>: Cost 3 vext1 <0,2,0,u>, <3,0,1,2> + 1477791030U, // <2,0,u,4>: Cost 2 vext1 <0,2,0,u>, RHS + 2618726554U, // <2,0,u,5>: Cost 3 vext2 <0,2,2,0>, RHS + 2765412506U, // <2,0,u,6>: Cost 3 vuzpl <2,3,0,1>, RHS + 2826096169U, // <2,0,u,7>: Cost 3 vuzpr <1,2,3,0>, RHS + 1611956947U, // <2,0,u,u>: Cost 2 vext3 <0,2,0,2>, LHS + 2569453670U, // <2,1,0,0>: Cost 3 vext1 <3,2,1,0>, LHS + 2619392102U, // <2,1,0,1>: Cost 3 vext2 <0,3,2,1>, LHS + 3759440619U, // <2,1,0,2>: Cost 4 vext3 <0,2,0,2>, <1,0,2,0> + 1616823030U, // <2,1,0,3>: Cost 2 vext3 <1,0,3,2>, <1,0,3,2> + 2569456950U, // <2,1,0,4>: Cost 3 vext1 <3,2,1,0>, RHS + 2690712328U, // <2,1,0,5>: Cost 3 vext3 <1,0,5,2>, <1,0,5,2> + 3661115841U, // <2,1,0,6>: Cost 4 vext1 <6,2,1,0>, <6,2,1,0> + 2622046794U, // <2,1,0,7>: Cost 3 vext2 <0,7,2,1>, <0,7,2,1> + 1617191715U, // <2,1,0,u>: Cost 2 vext3 <1,0,u,2>, <1,0,u,2> + 2551545958U, // <2,1,1,0>: Cost 3 vext1 <0,2,1,1>, LHS + 2685698868U, // <2,1,1,1>: Cost 3 vext3 <0,2,0,2>, <1,1,1,1> + 2628682646U, // <2,1,1,2>: Cost 3 vext2 <1,u,2,1>, <1,2,3,0> + 2685698888U, // <2,1,1,3>: Cost 3 vext3 <0,2,0,2>, <1,1,3,3> + 2551549238U, // <2,1,1,4>: Cost 3 vext1 <0,2,1,1>, RHS + 3693134992U, // <2,1,1,5>: Cost 4 vext2 <0,3,2,1>, <1,5,3,7> + 3661124034U, // <2,1,1,6>: Cost 4 vext1 <6,2,1,1>, <6,2,1,1> + 3625292794U, // <2,1,1,7>: Cost 4 vext1 <0,2,1,1>, <7,0,1,2> + 2685698933U, // <2,1,1,u>: Cost 3 vext3 <0,2,0,2>, <1,1,u,3> + 2551554150U, // <2,1,2,0>: Cost 3 vext1 <0,2,1,2>, LHS + 3893649571U, // <2,1,2,1>: Cost 4 vuzpr <0,2,0,1>, <0,2,0,1> + 2551555688U, // <2,1,2,2>: Cost 3 vext1 <0,2,1,2>, <2,2,2,2> + 2685698966U, // <2,1,2,3>: Cost 3 vext3 <0,2,0,2>, <1,2,3,0> + 2551557430U, // <2,1,2,4>: Cost 3 vext1 <0,2,1,2>, RHS + 3763422123U, // <2,1,2,5>: Cost 4 vext3 <0,u,0,2>, <1,2,5,3> + 3693135802U, // <2,1,2,6>: Cost 4 vext2 <0,3,2,1>, <2,6,3,7> + 2726249402U, // <2,1,2,7>: Cost 3 vext3 <7,0,1,2>, <1,2,7,0> + 2685699011U, // <2,1,2,u>: Cost 3 vext3 <0,2,0,2>, <1,2,u,0> + 2551562342U, // <2,1,3,0>: Cost 3 vext1 <0,2,1,3>, LHS + 2953625610U, // <2,1,3,1>: Cost 3 vzipr LHS, <0,0,1,1> + 2953627798U, // <2,1,3,2>: Cost 3 vzipr LHS, <3,0,1,2> + 2953626584U, // <2,1,3,3>: Cost 3 vzipr LHS, <1,3,1,3> + 2551565622U, // <2,1,3,4>: Cost 3 vext1 <0,2,1,3>, RHS + 2953625938U, // <2,1,3,5>: Cost 3 vzipr LHS, <0,4,1,5> + 2587398596U, // <2,1,3,6>: Cost 3 vext1 <6,2,1,3>, <6,2,1,3> + 4032013519U, // <2,1,3,7>: Cost 4 vzipr LHS, <1,6,1,7> + 2953625617U, // <2,1,3,u>: Cost 3 vzipr LHS, <0,0,1,u> + 2690565154U, // <2,1,4,0>: Cost 3 vext3 <1,0,3,2>, <1,4,0,5> + 3625313270U, // <2,1,4,1>: Cost 4 vext1 <0,2,1,4>, <1,3,4,6> + 3771532340U, // <2,1,4,2>: Cost 4 vext3 <2,2,2,2>, <1,4,2,5> + 1148404634U, // <2,1,4,3>: Cost 2 vrev <1,2,3,4> + 3625315638U, // <2,1,4,4>: Cost 4 vext1 <0,2,1,4>, RHS + 2619395382U, // <2,1,4,5>: Cost 3 vext2 <0,3,2,1>, RHS + 3837242678U, // <2,1,4,6>: Cost 4 vuzpl <2,0,1,2>, RHS + 3799991394U, // <2,1,4,7>: Cost 4 vext3 <7,0,1,2>, <1,4,7,6> + 1148773319U, // <2,1,4,u>: Cost 2 vrev <1,2,u,4> + 2551578726U, // <2,1,5,0>: Cost 3 vext1 <0,2,1,5>, LHS + 2551579648U, // <2,1,5,1>: Cost 3 vext1 <0,2,1,5>, <1,3,5,7> + 3625321952U, // <2,1,5,2>: Cost 4 vext1 <0,2,1,5>, <2,0,5,1> + 2685699216U, // <2,1,5,3>: Cost 3 vext3 <0,2,0,2>, <1,5,3,7> + 2551582006U, // <2,1,5,4>: Cost 3 vext1 <0,2,1,5>, RHS + 3740913668U, // <2,1,5,5>: Cost 4 vext2 , <5,5,5,5> + 3661156806U, // <2,1,5,6>: Cost 4 vext1 <6,2,1,5>, <6,2,1,5> + 3893652790U, // <2,1,5,7>: Cost 4 vuzpr <0,2,0,1>, RHS + 2685699261U, // <2,1,5,u>: Cost 3 vext3 <0,2,0,2>, <1,5,u,7> + 2551586918U, // <2,1,6,0>: Cost 3 vext1 <0,2,1,6>, LHS + 3625329398U, // <2,1,6,1>: Cost 4 vext1 <0,2,1,6>, <1,0,3,2> + 2551588794U, // <2,1,6,2>: Cost 3 vext1 <0,2,1,6>, <2,6,3,7> + 3088679014U, // <2,1,6,3>: Cost 3 vtrnr <0,2,4,6>, LHS + 2551590198U, // <2,1,6,4>: Cost 3 vext1 <0,2,1,6>, RHS + 4029382994U, // <2,1,6,5>: Cost 4 vzipr <0,4,2,6>, <0,4,1,5> + 3625333560U, // <2,1,6,6>: Cost 4 vext1 <0,2,1,6>, <6,6,6,6> + 3731624800U, // <2,1,6,7>: Cost 4 vext2 <6,7,2,1>, <6,7,2,1> + 2551592750U, // <2,1,6,u>: Cost 3 vext1 <0,2,1,6>, LHS + 2622051322U, // <2,1,7,0>: Cost 3 vext2 <0,7,2,1>, <7,0,1,2> + 3733615699U, // <2,1,7,1>: Cost 4 vext2 <7,1,2,1>, <7,1,2,1> + 3795125538U, // <2,1,7,2>: Cost 4 vext3 <6,1,7,2>, <1,7,2,0> + 2222171037U, // <2,1,7,3>: Cost 3 vrev <1,2,3,7> + 3740915046U, // <2,1,7,4>: Cost 4 vext2 , <7,4,5,6> + 3296060335U, // <2,1,7,5>: Cost 4 vrev <1,2,5,7> + 3736933864U, // <2,1,7,6>: Cost 4 vext2 <7,6,2,1>, <7,6,2,1> + 3805300055U, // <2,1,7,7>: Cost 4 vext3 <7,u,1,2>, <1,7,7,u> + 2669827714U, // <2,1,7,u>: Cost 3 vext2 , <7,u,1,2> + 2551603302U, // <2,1,u,0>: Cost 3 vext1 <0,2,1,u>, LHS + 2953666570U, // <2,1,u,1>: Cost 3 vzipr LHS, <0,0,1,1> + 2953668758U, // <2,1,u,2>: Cost 3 vzipr LHS, <3,0,1,2> + 1148437406U, // <2,1,u,3>: Cost 2 vrev <1,2,3,u> + 2551606582U, // <2,1,u,4>: Cost 3 vext1 <0,2,1,u>, RHS + 2953666898U, // <2,1,u,5>: Cost 3 vzipr LHS, <0,4,1,5> + 2587398596U, // <2,1,u,6>: Cost 3 vext1 <6,2,1,3>, <6,2,1,3> + 2669828370U, // <2,1,u,7>: Cost 3 vext2 , + 1148806091U, // <2,1,u,u>: Cost 2 vrev <1,2,u,u> + 1543667732U, // <2,2,0,0>: Cost 2 vext2 <0,0,2,2>, <0,0,2,2> + 1548976230U, // <2,2,0,1>: Cost 2 vext2 <0,u,2,2>, LHS + 2685699524U, // <2,2,0,2>: Cost 3 vext3 <0,2,0,2>, <2,0,2,0> + 2685699535U, // <2,2,0,3>: Cost 3 vext3 <0,2,0,2>, <2,0,3,2> + 2551614774U, // <2,2,0,4>: Cost 3 vext1 <0,2,2,0>, RHS + 3704422830U, // <2,2,0,5>: Cost 4 vext2 <2,2,2,2>, <0,5,2,7> + 3893657642U, // <2,2,0,6>: Cost 4 vuzpr <0,2,0,2>, <0,0,4,6> + 3770574323U, // <2,2,0,7>: Cost 4 vext3 <2,0,7,2>, <2,0,7,2> + 1548976796U, // <2,2,0,u>: Cost 2 vext2 <0,u,2,2>, <0,u,2,2> + 2622718710U, // <2,2,1,0>: Cost 3 vext2 <0,u,2,2>, <1,0,3,2> + 2622718772U, // <2,2,1,1>: Cost 3 vext2 <0,u,2,2>, <1,1,1,1> + 2622718870U, // <2,2,1,2>: Cost 3 vext2 <0,u,2,2>, <1,2,3,0> + 2819915878U, // <2,2,1,3>: Cost 3 vuzpr <0,2,0,2>, LHS + 3625364790U, // <2,2,1,4>: Cost 4 vext1 <0,2,2,1>, RHS + 2622719120U, // <2,2,1,5>: Cost 3 vext2 <0,u,2,2>, <1,5,3,7> + 3760031292U, // <2,2,1,6>: Cost 4 vext3 <0,2,u,2>, <2,1,6,3> + 3667170468U, // <2,2,1,7>: Cost 4 vext1 <7,2,2,1>, <7,2,2,1> + 2819915883U, // <2,2,1,u>: Cost 3 vuzpr <0,2,0,2>, LHS + 1489829990U, // <2,2,2,0>: Cost 2 vext1 <2,2,2,2>, LHS + 2563572470U, // <2,2,2,1>: Cost 3 vext1 <2,2,2,2>, <1,0,3,2> + 269271142U, // <2,2,2,2>: Cost 1 vdup2 LHS + 2685699698U, // <2,2,2,3>: Cost 3 vext3 <0,2,0,2>, <2,2,3,3> + 1489833270U, // <2,2,2,4>: Cost 2 vext1 <2,2,2,2>, RHS + 2685699720U, // <2,2,2,5>: Cost 3 vext3 <0,2,0,2>, <2,2,5,7> + 2622719930U, // <2,2,2,6>: Cost 3 vext2 <0,u,2,2>, <2,6,3,7> + 2593436837U, // <2,2,2,7>: Cost 3 vext1 <7,2,2,2>, <7,2,2,2> + 269271142U, // <2,2,2,u>: Cost 1 vdup2 LHS + 2685699750U, // <2,2,3,0>: Cost 3 vext3 <0,2,0,2>, <2,3,0,1> + 2690565806U, // <2,2,3,1>: Cost 3 vext3 <1,0,3,2>, <2,3,1,0> + 2953627240U, // <2,2,3,2>: Cost 3 vzipr LHS, <2,2,2,2> + 1879883878U, // <2,2,3,3>: Cost 2 vzipr LHS, LHS + 2685699790U, // <2,2,3,4>: Cost 3 vext3 <0,2,0,2>, <2,3,4,5> + 3893659342U, // <2,2,3,5>: Cost 4 vuzpr <0,2,0,2>, <2,3,4,5> + 2958270812U, // <2,2,3,6>: Cost 3 vzipr LHS, <0,4,2,6> + 2593445030U, // <2,2,3,7>: Cost 3 vext1 <7,2,2,3>, <7,2,2,3> + 1879883883U, // <2,2,3,u>: Cost 2 vzipr LHS, LHS + 2551644262U, // <2,2,4,0>: Cost 3 vext1 <0,2,2,4>, LHS + 3625386742U, // <2,2,4,1>: Cost 4 vext1 <0,2,2,4>, <1,0,3,2> + 2551645902U, // <2,2,4,2>: Cost 3 vext1 <0,2,2,4>, <2,3,4,5> + 3759441686U, // <2,2,4,3>: Cost 4 vext3 <0,2,0,2>, <2,4,3,5> + 2551647542U, // <2,2,4,4>: Cost 3 vext1 <0,2,2,4>, RHS + 1548979510U, // <2,2,4,5>: Cost 2 vext2 <0,u,2,2>, RHS + 2764901686U, // <2,2,4,6>: Cost 3 vuzpl <2,2,2,2>, RHS + 3667195047U, // <2,2,4,7>: Cost 4 vext1 <7,2,2,4>, <7,2,2,4> + 1548979753U, // <2,2,4,u>: Cost 2 vext2 <0,u,2,2>, RHS + 3696463432U, // <2,2,5,0>: Cost 4 vext2 <0,u,2,2>, <5,0,1,2> + 2617413328U, // <2,2,5,1>: Cost 3 vext2 <0,0,2,2>, <5,1,7,3> + 2685699936U, // <2,2,5,2>: Cost 3 vext3 <0,2,0,2>, <2,5,2,7> + 4027383910U, // <2,2,5,3>: Cost 4 vzipr <0,1,2,5>, LHS + 2228201085U, // <2,2,5,4>: Cost 3 vrev <2,2,4,5> + 2617413636U, // <2,2,5,5>: Cost 3 vext2 <0,0,2,2>, <5,5,5,5> + 2617413730U, // <2,2,5,6>: Cost 3 vext2 <0,0,2,2>, <5,6,7,0> + 2819919158U, // <2,2,5,7>: Cost 3 vuzpr <0,2,0,2>, RHS + 2819919159U, // <2,2,5,u>: Cost 3 vuzpr <0,2,0,2>, RHS + 3625402554U, // <2,2,6,0>: Cost 4 vext1 <0,2,2,6>, <0,2,2,6> + 3760031652U, // <2,2,6,1>: Cost 4 vext3 <0,2,u,2>, <2,6,1,3> + 2617414138U, // <2,2,6,2>: Cost 3 vext2 <0,0,2,2>, <6,2,7,3> + 2685700026U, // <2,2,6,3>: Cost 3 vext3 <0,2,0,2>, <2,6,3,7> + 3625405750U, // <2,2,6,4>: Cost 4 vext1 <0,2,2,6>, RHS + 3760031692U, // <2,2,6,5>: Cost 4 vext3 <0,2,u,2>, <2,6,5,7> + 3088679116U, // <2,2,6,6>: Cost 3 vtrnr <0,2,4,6>, <0,2,4,6> + 2657891169U, // <2,2,6,7>: Cost 3 vext2 <6,7,2,2>, <6,7,2,2> + 2685700071U, // <2,2,6,u>: Cost 3 vext3 <0,2,0,2>, <2,6,u,7> + 2726250474U, // <2,2,7,0>: Cost 3 vext3 <7,0,1,2>, <2,7,0,1> + 3704427616U, // <2,2,7,1>: Cost 4 vext2 <2,2,2,2>, <7,1,3,5> + 2660545701U, // <2,2,7,2>: Cost 3 vext2 <7,2,2,2>, <7,2,2,2> + 4030718054U, // <2,2,7,3>: Cost 4 vzipr <0,6,2,7>, LHS + 2617415014U, // <2,2,7,4>: Cost 3 vext2 <0,0,2,2>, <7,4,5,6> + 3302033032U, // <2,2,7,5>: Cost 4 vrev <2,2,5,7> + 3661246929U, // <2,2,7,6>: Cost 4 vext1 <6,2,2,7>, <6,2,2,7> + 2617415276U, // <2,2,7,7>: Cost 3 vext2 <0,0,2,2>, <7,7,7,7> + 2731558962U, // <2,2,7,u>: Cost 3 vext3 <7,u,1,2>, <2,7,u,1> + 1489829990U, // <2,2,u,0>: Cost 2 vext1 <2,2,2,2>, LHS + 1548982062U, // <2,2,u,1>: Cost 2 vext2 <0,u,2,2>, LHS + 269271142U, // <2,2,u,2>: Cost 1 vdup2 LHS + 1879924838U, // <2,2,u,3>: Cost 2 vzipr LHS, LHS + 1489833270U, // <2,2,u,4>: Cost 2 vext1 <2,2,2,2>, RHS + 1548982426U, // <2,2,u,5>: Cost 2 vext2 <0,u,2,2>, RHS + 2953666908U, // <2,2,u,6>: Cost 3 vzipr LHS, <0,4,2,6> + 2819919401U, // <2,2,u,7>: Cost 3 vuzpr <0,2,0,2>, RHS + 269271142U, // <2,2,u,u>: Cost 1 vdup2 LHS + 1544339456U, // <2,3,0,0>: Cost 2 vext2 LHS, <0,0,0,0> + 470597734U, // <2,3,0,1>: Cost 1 vext2 LHS, LHS + 1548984484U, // <2,3,0,2>: Cost 2 vext2 LHS, <0,2,0,2> + 2619408648U, // <2,3,0,3>: Cost 3 vext2 <0,3,2,3>, <0,3,2,3> + 1548984658U, // <2,3,0,4>: Cost 2 vext2 LHS, <0,4,1,5> + 2665857454U, // <2,3,0,5>: Cost 3 vext2 LHS, <0,5,2,7> + 2622726655U, // <2,3,0,6>: Cost 3 vext2 LHS, <0,6,2,7> + 2593494188U, // <2,3,0,7>: Cost 3 vext1 <7,2,3,0>, <7,2,3,0> + 470598301U, // <2,3,0,u>: Cost 1 vext2 LHS, LHS + 1544340214U, // <2,3,1,0>: Cost 2 vext2 LHS, <1,0,3,2> + 1544340276U, // <2,3,1,1>: Cost 2 vext2 LHS, <1,1,1,1> + 1544340374U, // <2,3,1,2>: Cost 2 vext2 LHS, <1,2,3,0> + 1548985304U, // <2,3,1,3>: Cost 2 vext2 LHS, <1,3,1,3> + 2551696694U, // <2,3,1,4>: Cost 3 vext1 <0,2,3,1>, RHS + 1548985488U, // <2,3,1,5>: Cost 2 vext2 LHS, <1,5,3,7> + 2622727375U, // <2,3,1,6>: Cost 3 vext2 LHS, <1,6,1,7> + 2665858347U, // <2,3,1,7>: Cost 3 vext2 LHS, <1,7,3,0> + 1548985709U, // <2,3,1,u>: Cost 2 vext2 LHS, <1,u,1,3> + 2622727613U, // <2,3,2,0>: Cost 3 vext2 LHS, <2,0,1,2> + 2622727711U, // <2,3,2,1>: Cost 3 vext2 LHS, <2,1,3,1> + 1544341096U, // <2,3,2,2>: Cost 2 vext2 LHS, <2,2,2,2> + 1544341158U, // <2,3,2,3>: Cost 2 vext2 LHS, <2,3,0,1> + 2622727958U, // <2,3,2,4>: Cost 3 vext2 LHS, <2,4,3,5> + 2622728032U, // <2,3,2,5>: Cost 3 vext2 LHS, <2,5,2,7> + 1548986298U, // <2,3,2,6>: Cost 2 vext2 LHS, <2,6,3,7> + 2665859050U, // <2,3,2,7>: Cost 3 vext2 LHS, <2,7,0,1> + 1548986427U, // <2,3,2,u>: Cost 2 vext2 LHS, <2,u,0,1> + 1548986518U, // <2,3,3,0>: Cost 2 vext2 LHS, <3,0,1,2> + 2622728415U, // <2,3,3,1>: Cost 3 vext2 LHS, <3,1,0,3> + 1489913458U, // <2,3,3,2>: Cost 2 vext1 <2,2,3,3>, <2,2,3,3> + 1544341916U, // <2,3,3,3>: Cost 2 vext2 LHS, <3,3,3,3> + 1548986882U, // <2,3,3,4>: Cost 2 vext2 LHS, <3,4,5,6> + 2665859632U, // <2,3,3,5>: Cost 3 vext2 LHS, <3,5,1,7> + 2234304870U, // <2,3,3,6>: Cost 3 vrev <3,2,6,3> + 2958271632U, // <2,3,3,7>: Cost 3 vzipr LHS, <1,5,3,7> + 1548987166U, // <2,3,3,u>: Cost 2 vext2 LHS, <3,u,1,2> + 1483948134U, // <2,3,4,0>: Cost 2 vext1 <1,2,3,4>, LHS + 1483948954U, // <2,3,4,1>: Cost 2 vext1 <1,2,3,4>, <1,2,3,4> + 2622729276U, // <2,3,4,2>: Cost 3 vext2 LHS, <4,2,6,0> + 2557692054U, // <2,3,4,3>: Cost 3 vext1 <1,2,3,4>, <3,0,1,2> + 1483951414U, // <2,3,4,4>: Cost 2 vext1 <1,2,3,4>, RHS + 470601014U, // <2,3,4,5>: Cost 1 vext2 LHS, RHS + 1592118644U, // <2,3,4,6>: Cost 2 vext2 LHS, <4,6,4,6> + 2593526960U, // <2,3,4,7>: Cost 3 vext1 <7,2,3,4>, <7,2,3,4> + 470601257U, // <2,3,4,u>: Cost 1 vext2 LHS, RHS + 2551726182U, // <2,3,5,0>: Cost 3 vext1 <0,2,3,5>, LHS + 1592118992U, // <2,3,5,1>: Cost 2 vext2 LHS, <5,1,7,3> + 2665860862U, // <2,3,5,2>: Cost 3 vext2 LHS, <5,2,3,4> + 2551728642U, // <2,3,5,3>: Cost 3 vext1 <0,2,3,5>, <3,4,5,6> + 1592119238U, // <2,3,5,4>: Cost 2 vext2 LHS, <5,4,7,6> + 1592119300U, // <2,3,5,5>: Cost 2 vext2 LHS, <5,5,5,5> + 1592119394U, // <2,3,5,6>: Cost 2 vext2 LHS, <5,6,7,0> + 1592119464U, // <2,3,5,7>: Cost 2 vext2 LHS, <5,7,5,7> + 1592119545U, // <2,3,5,u>: Cost 2 vext2 LHS, <5,u,5,7> + 2622730529U, // <2,3,6,0>: Cost 3 vext2 LHS, <6,0,1,2> + 2557707164U, // <2,3,6,1>: Cost 3 vext1 <1,2,3,6>, <1,2,3,6> + 1592119802U, // <2,3,6,2>: Cost 2 vext2 LHS, <6,2,7,3> + 2665861682U, // <2,3,6,3>: Cost 3 vext2 LHS, <6,3,4,5> + 2622730893U, // <2,3,6,4>: Cost 3 vext2 LHS, <6,4,5,6> + 2665861810U, // <2,3,6,5>: Cost 3 vext2 LHS, <6,5,0,7> + 1592120120U, // <2,3,6,6>: Cost 2 vext2 LHS, <6,6,6,6> + 1592120142U, // <2,3,6,7>: Cost 2 vext2 LHS, <6,7,0,1> + 1592120223U, // <2,3,6,u>: Cost 2 vext2 LHS, <6,u,0,1> + 1592120314U, // <2,3,7,0>: Cost 2 vext2 LHS, <7,0,1,2> + 2659890261U, // <2,3,7,1>: Cost 3 vext2 <7,1,2,3>, <7,1,2,3> + 2660553894U, // <2,3,7,2>: Cost 3 vext2 <7,2,2,3>, <7,2,2,3> + 2665862371U, // <2,3,7,3>: Cost 3 vext2 LHS, <7,3,0,1> + 1592120678U, // <2,3,7,4>: Cost 2 vext2 LHS, <7,4,5,6> + 2665862534U, // <2,3,7,5>: Cost 3 vext2 LHS, <7,5,0,2> + 2665862614U, // <2,3,7,6>: Cost 3 vext2 LHS, <7,6,0,1> + 1592120940U, // <2,3,7,7>: Cost 2 vext2 LHS, <7,7,7,7> + 1592120962U, // <2,3,7,u>: Cost 2 vext2 LHS, <7,u,1,2> + 1548990163U, // <2,3,u,0>: Cost 2 vext2 LHS, + 470603566U, // <2,3,u,1>: Cost 1 vext2 LHS, LHS + 1548990341U, // <2,3,u,2>: Cost 2 vext2 LHS, + 1548990396U, // <2,3,u,3>: Cost 2 vext2 LHS, + 1548990527U, // <2,3,u,4>: Cost 2 vext2 LHS, + 470603930U, // <2,3,u,5>: Cost 1 vext2 LHS, RHS + 1548990672U, // <2,3,u,6>: Cost 2 vext2 LHS, + 1592121600U, // <2,3,u,7>: Cost 2 vext2 LHS, + 470604133U, // <2,3,u,u>: Cost 1 vext2 LHS, LHS + 2617425942U, // <2,4,0,0>: Cost 3 vext2 <0,0,2,4>, <0,0,2,4> + 2618753126U, // <2,4,0,1>: Cost 3 vext2 <0,2,2,4>, LHS + 2618753208U, // <2,4,0,2>: Cost 3 vext2 <0,2,2,4>, <0,2,2,4> + 2619416841U, // <2,4,0,3>: Cost 3 vext2 <0,3,2,4>, <0,3,2,4> + 2587593628U, // <2,4,0,4>: Cost 3 vext1 <6,2,4,0>, <4,0,6,2> + 2712832914U, // <2,4,0,5>: Cost 3 vext3 <4,6,u,2>, <4,0,5,1> + 1634962332U, // <2,4,0,6>: Cost 2 vext3 <4,0,6,2>, <4,0,6,2> + 3799993252U, // <2,4,0,7>: Cost 4 vext3 <7,0,1,2>, <4,0,7,1> + 1634962332U, // <2,4,0,u>: Cost 2 vext3 <4,0,6,2>, <4,0,6,2> + 2619417334U, // <2,4,1,0>: Cost 3 vext2 <0,3,2,4>, <1,0,3,2> + 3692495668U, // <2,4,1,1>: Cost 4 vext2 <0,2,2,4>, <1,1,1,1> + 2625389466U, // <2,4,1,2>: Cost 3 vext2 <1,3,2,4>, <1,2,3,4> + 2826125414U, // <2,4,1,3>: Cost 3 vuzpr <1,2,3,4>, LHS + 3699794995U, // <2,4,1,4>: Cost 4 vext2 <1,4,2,4>, <1,4,2,4> + 3692496016U, // <2,4,1,5>: Cost 4 vext2 <0,2,2,4>, <1,5,3,7> + 3763424238U, // <2,4,1,6>: Cost 4 vext3 <0,u,0,2>, <4,1,6,3> + 3667317942U, // <2,4,1,7>: Cost 4 vext1 <7,2,4,1>, <7,2,4,1> + 2826125419U, // <2,4,1,u>: Cost 3 vuzpr <1,2,3,4>, LHS + 2629371336U, // <2,4,2,0>: Cost 3 vext2 <2,0,2,4>, <2,0,2,4> + 3699131946U, // <2,4,2,1>: Cost 4 vext2 <1,3,2,4>, <2,1,4,3> + 2630698602U, // <2,4,2,2>: Cost 3 vext2 <2,2,2,4>, <2,2,2,4> + 2618754766U, // <2,4,2,3>: Cost 3 vext2 <0,2,2,4>, <2,3,4,5> + 2826126234U, // <2,4,2,4>: Cost 3 vuzpr <1,2,3,4>, <1,2,3,4> + 2899119414U, // <2,4,2,5>: Cost 3 vzipl <2,2,2,2>, RHS + 3033337142U, // <2,4,2,6>: Cost 3 vtrnl <2,2,2,2>, RHS + 3800214597U, // <2,4,2,7>: Cost 4 vext3 <7,0,4,2>, <4,2,7,0> + 2899119657U, // <2,4,2,u>: Cost 3 vzipl <2,2,2,2>, RHS + 2635344033U, // <2,4,3,0>: Cost 3 vext2 <3,0,2,4>, <3,0,2,4> + 4032012325U, // <2,4,3,1>: Cost 4 vzipr LHS, <0,0,4,1> + 3692497228U, // <2,4,3,2>: Cost 4 vext2 <0,2,2,4>, <3,2,3,4> + 3692497308U, // <2,4,3,3>: Cost 4 vext2 <0,2,2,4>, <3,3,3,3> + 3001404624U, // <2,4,3,4>: Cost 3 vzipr LHS, <4,4,4,4> + 2953627342U, // <2,4,3,5>: Cost 3 vzipr LHS, <2,3,4,5> + 2953625804U, // <2,4,3,6>: Cost 3 vzipr LHS, <0,2,4,6> + 3899868160U, // <2,4,3,7>: Cost 4 vuzpr <1,2,3,4>, <1,3,5,7> + 2953625806U, // <2,4,3,u>: Cost 3 vzipr LHS, <0,2,4,u> + 2710916266U, // <2,4,4,0>: Cost 3 vext3 <4,4,0,2>, <4,4,0,2> + 3899869648U, // <2,4,4,1>: Cost 4 vuzpr <1,2,3,4>, <3,4,0,1> + 3899869658U, // <2,4,4,2>: Cost 4 vuzpr <1,2,3,4>, <3,4,1,2> + 3899868930U, // <2,4,4,3>: Cost 4 vuzpr <1,2,3,4>, <2,4,1,3> + 2712833232U, // <2,4,4,4>: Cost 3 vext3 <4,6,u,2>, <4,4,4,4> + 2618756406U, // <2,4,4,5>: Cost 3 vext2 <0,2,2,4>, RHS + 2765737270U, // <2,4,4,6>: Cost 3 vuzpl <2,3,4,5>, RHS + 4168304426U, // <2,4,4,7>: Cost 4 vtrnr <1,2,3,4>, <2,4,5,7> + 2618756649U, // <2,4,4,u>: Cost 3 vext2 <0,2,2,4>, RHS + 2551800011U, // <2,4,5,0>: Cost 3 vext1 <0,2,4,5>, <0,2,4,5> + 2569716470U, // <2,4,5,1>: Cost 3 vext1 <3,2,4,5>, <1,0,3,2> + 2563745405U, // <2,4,5,2>: Cost 3 vext1 <2,2,4,5>, <2,2,4,5> + 2569718102U, // <2,4,5,3>: Cost 3 vext1 <3,2,4,5>, <3,2,4,5> + 2551803190U, // <2,4,5,4>: Cost 3 vext1 <0,2,4,5>, RHS + 3625545732U, // <2,4,5,5>: Cost 4 vext1 <0,2,4,5>, <5,5,5,5> + 1611959606U, // <2,4,5,6>: Cost 2 vext3 <0,2,0,2>, RHS + 2826128694U, // <2,4,5,7>: Cost 3 vuzpr <1,2,3,4>, RHS + 1611959624U, // <2,4,5,u>: Cost 2 vext3 <0,2,0,2>, RHS + 1478066278U, // <2,4,6,0>: Cost 2 vext1 <0,2,4,6>, LHS + 2551808758U, // <2,4,6,1>: Cost 3 vext1 <0,2,4,6>, <1,0,3,2> + 2551809516U, // <2,4,6,2>: Cost 3 vext1 <0,2,4,6>, <2,0,6,4> + 2551810198U, // <2,4,6,3>: Cost 3 vext1 <0,2,4,6>, <3,0,1,2> + 1478069558U, // <2,4,6,4>: Cost 2 vext1 <0,2,4,6>, RHS + 2901888310U, // <2,4,6,5>: Cost 3 vzipl <2,6,3,7>, RHS + 2551812920U, // <2,4,6,6>: Cost 3 vext1 <0,2,4,6>, <6,6,6,6> + 2726251914U, // <2,4,6,7>: Cost 3 vext3 <7,0,1,2>, <4,6,7,1> + 1478072110U, // <2,4,6,u>: Cost 2 vext1 <0,2,4,6>, LHS + 2659234821U, // <2,4,7,0>: Cost 3 vext2 <7,0,2,4>, <7,0,2,4> + 3786722726U, // <2,4,7,1>: Cost 4 vext3 <4,7,1,2>, <4,7,1,2> + 3734303911U, // <2,4,7,2>: Cost 4 vext2 <7,2,2,4>, <7,2,2,4> + 3734967544U, // <2,4,7,3>: Cost 4 vext2 <7,3,2,4>, <7,3,2,4> + 3727005030U, // <2,4,7,4>: Cost 4 vext2 <6,0,2,4>, <7,4,5,6> + 2726251976U, // <2,4,7,5>: Cost 3 vext3 <7,0,1,2>, <4,7,5,0> + 2726251986U, // <2,4,7,6>: Cost 3 vext3 <7,0,1,2>, <4,7,6,1> + 3727005292U, // <2,4,7,7>: Cost 4 vext2 <6,0,2,4>, <7,7,7,7> + 2659234821U, // <2,4,7,u>: Cost 3 vext2 <7,0,2,4>, <7,0,2,4> + 1478082662U, // <2,4,u,0>: Cost 2 vext1 <0,2,4,u>, LHS + 2618758958U, // <2,4,u,1>: Cost 3 vext2 <0,2,2,4>, LHS + 2551826024U, // <2,4,u,2>: Cost 3 vext1 <0,2,4,u>, <2,2,2,2> + 2551826582U, // <2,4,u,3>: Cost 3 vext1 <0,2,4,u>, <3,0,1,2> + 1478085942U, // <2,4,u,4>: Cost 2 vext1 <0,2,4,u>, RHS + 2953668302U, // <2,4,u,5>: Cost 3 vzipr LHS, <2,3,4,5> + 1611959849U, // <2,4,u,6>: Cost 2 vext3 <0,2,0,2>, RHS + 2826128937U, // <2,4,u,7>: Cost 3 vuzpr <1,2,3,4>, RHS + 1611959867U, // <2,4,u,u>: Cost 2 vext3 <0,2,0,2>, RHS + 3691839488U, // <2,5,0,0>: Cost 4 vext2 <0,1,2,5>, <0,0,0,0> + 2618097766U, // <2,5,0,1>: Cost 3 vext2 <0,1,2,5>, LHS + 2620088484U, // <2,5,0,2>: Cost 3 vext2 <0,4,2,5>, <0,2,0,2> + 2619425034U, // <2,5,0,3>: Cost 3 vext2 <0,3,2,5>, <0,3,2,5> + 2620088667U, // <2,5,0,4>: Cost 3 vext2 <0,4,2,5>, <0,4,2,5> + 2620752300U, // <2,5,0,5>: Cost 3 vext2 <0,5,2,5>, <0,5,2,5> + 3693830655U, // <2,5,0,6>: Cost 4 vext2 <0,4,2,5>, <0,6,2,7> + 3094531382U, // <2,5,0,7>: Cost 3 vtrnr <1,2,3,0>, RHS + 2618098333U, // <2,5,0,u>: Cost 3 vext2 <0,1,2,5>, LHS + 3691840246U, // <2,5,1,0>: Cost 4 vext2 <0,1,2,5>, <1,0,3,2> + 3691840308U, // <2,5,1,1>: Cost 4 vext2 <0,1,2,5>, <1,1,1,1> + 2626061206U, // <2,5,1,2>: Cost 3 vext2 <1,4,2,5>, <1,2,3,0> + 2618098688U, // <2,5,1,3>: Cost 3 vext2 <0,1,2,5>, <1,3,5,7> + 2626061364U, // <2,5,1,4>: Cost 3 vext2 <1,4,2,5>, <1,4,2,5> + 3691840656U, // <2,5,1,5>: Cost 4 vext2 <0,1,2,5>, <1,5,3,7> + 3789082310U, // <2,5,1,6>: Cost 4 vext3 <5,1,6,2>, <5,1,6,2> + 2712833744U, // <2,5,1,7>: Cost 3 vext3 <4,6,u,2>, <5,1,7,3> + 2628715896U, // <2,5,1,u>: Cost 3 vext2 <1,u,2,5>, <1,u,2,5> + 3693831613U, // <2,5,2,0>: Cost 4 vext2 <0,4,2,5>, <2,0,1,2> + 4026698642U, // <2,5,2,1>: Cost 4 vzipr <0,0,2,2>, <4,0,5,1> + 2632033896U, // <2,5,2,2>: Cost 3 vext2 <2,4,2,5>, <2,2,2,2> + 3691841190U, // <2,5,2,3>: Cost 4 vext2 <0,1,2,5>, <2,3,0,1> + 2632034061U, // <2,5,2,4>: Cost 3 vext2 <2,4,2,5>, <2,4,2,5> + 3691841352U, // <2,5,2,5>: Cost 4 vext2 <0,1,2,5>, <2,5,0,1> + 3691841466U, // <2,5,2,6>: Cost 4 vext2 <0,1,2,5>, <2,6,3,7> + 3088354614U, // <2,5,2,7>: Cost 3 vtrnr <0,2,0,2>, RHS + 3088354615U, // <2,5,2,u>: Cost 3 vtrnr <0,2,0,2>, RHS + 2557829222U, // <2,5,3,0>: Cost 3 vext1 <1,2,5,3>, LHS + 2557830059U, // <2,5,3,1>: Cost 3 vext1 <1,2,5,3>, <1,2,5,3> + 2575746766U, // <2,5,3,2>: Cost 3 vext1 <4,2,5,3>, <2,3,4,5> + 3691841948U, // <2,5,3,3>: Cost 4 vext2 <0,1,2,5>, <3,3,3,3> + 2619427330U, // <2,5,3,4>: Cost 3 vext2 <0,3,2,5>, <3,4,5,6> + 2581720847U, // <2,5,3,5>: Cost 3 vext1 <5,2,5,3>, <5,2,5,3> + 2953628162U, // <2,5,3,6>: Cost 3 vzipr LHS, <3,4,5,6> + 2953626624U, // <2,5,3,7>: Cost 3 vzipr LHS, <1,3,5,7> + 2953626625U, // <2,5,3,u>: Cost 3 vzipr LHS, <1,3,5,u> + 2569781350U, // <2,5,4,0>: Cost 3 vext1 <3,2,5,4>, LHS + 3631580076U, // <2,5,4,1>: Cost 4 vext1 <1,2,5,4>, <1,2,5,4> + 2569782990U, // <2,5,4,2>: Cost 3 vext1 <3,2,5,4>, <2,3,4,5> + 2569783646U, // <2,5,4,3>: Cost 3 vext1 <3,2,5,4>, <3,2,5,4> + 2569784630U, // <2,5,4,4>: Cost 3 vext1 <3,2,5,4>, RHS + 2618101046U, // <2,5,4,5>: Cost 3 vext2 <0,1,2,5>, RHS + 3893905922U, // <2,5,4,6>: Cost 4 vuzpr <0,2,3,5>, <3,4,5,6> + 3094564150U, // <2,5,4,7>: Cost 3 vtrnr <1,2,3,4>, RHS + 2618101289U, // <2,5,4,u>: Cost 3 vext2 <0,1,2,5>, RHS + 2551873638U, // <2,5,5,0>: Cost 3 vext1 <0,2,5,5>, LHS + 3637560320U, // <2,5,5,1>: Cost 4 vext1 <2,2,5,5>, <1,3,5,7> + 3637560966U, // <2,5,5,2>: Cost 4 vext1 <2,2,5,5>, <2,2,5,5> + 3723030343U, // <2,5,5,3>: Cost 4 vext2 <5,3,2,5>, <5,3,2,5> + 2551876918U, // <2,5,5,4>: Cost 3 vext1 <0,2,5,5>, RHS + 2712834052U, // <2,5,5,5>: Cost 3 vext3 <4,6,u,2>, <5,5,5,5> + 4028713474U, // <2,5,5,6>: Cost 4 vzipr <0,3,2,5>, <3,4,5,6> + 2712834072U, // <2,5,5,7>: Cost 3 vext3 <4,6,u,2>, <5,5,7,7> + 2712834081U, // <2,5,5,u>: Cost 3 vext3 <4,6,u,2>, <5,5,u,7> + 2575769702U, // <2,5,6,0>: Cost 3 vext1 <4,2,5,6>, LHS + 3631596462U, // <2,5,6,1>: Cost 4 vext1 <1,2,5,6>, <1,2,5,6> + 2655924730U, // <2,5,6,2>: Cost 3 vext2 <6,4,2,5>, <6,2,7,3> + 3643541856U, // <2,5,6,3>: Cost 4 vext1 <3,2,5,6>, <3,2,5,6> + 2655924849U, // <2,5,6,4>: Cost 3 vext2 <6,4,2,5>, <6,4,2,5> + 3787755607U, // <2,5,6,5>: Cost 4 vext3 <4,u,6,2>, <5,6,5,7> + 4029385218U, // <2,5,6,6>: Cost 4 vzipr <0,4,2,6>, <3,4,5,6> + 3088682294U, // <2,5,6,7>: Cost 3 vtrnr <0,2,4,6>, RHS + 3088682295U, // <2,5,6,u>: Cost 3 vtrnr <0,2,4,6>, RHS + 2563833958U, // <2,5,7,0>: Cost 3 vext1 <2,2,5,7>, LHS + 2551890678U, // <2,5,7,1>: Cost 3 vext1 <0,2,5,7>, <1,0,3,2> + 2563835528U, // <2,5,7,2>: Cost 3 vext1 <2,2,5,7>, <2,2,5,7> + 3637577878U, // <2,5,7,3>: Cost 4 vext1 <2,2,5,7>, <3,0,1,2> + 2563837238U, // <2,5,7,4>: Cost 3 vext1 <2,2,5,7>, RHS + 2712834216U, // <2,5,7,5>: Cost 3 vext3 <4,6,u,2>, <5,7,5,7> + 2712834220U, // <2,5,7,6>: Cost 3 vext3 <4,6,u,2>, <5,7,6,2> + 4174449974U, // <2,5,7,7>: Cost 4 vtrnr <2,2,5,7>, RHS + 2563839790U, // <2,5,7,u>: Cost 3 vext1 <2,2,5,7>, LHS + 2563842150U, // <2,5,u,0>: Cost 3 vext1 <2,2,5,u>, LHS + 2618103598U, // <2,5,u,1>: Cost 3 vext2 <0,1,2,5>, LHS + 2563843721U, // <2,5,u,2>: Cost 3 vext1 <2,2,5,u>, <2,2,5,u> + 2569816418U, // <2,5,u,3>: Cost 3 vext1 <3,2,5,u>, <3,2,5,u> + 2622748735U, // <2,5,u,4>: Cost 3 vext2 <0,u,2,5>, + 2618103962U, // <2,5,u,5>: Cost 3 vext2 <0,1,2,5>, RHS + 2953669122U, // <2,5,u,6>: Cost 3 vzipr LHS, <3,4,5,6> + 2953667584U, // <2,5,u,7>: Cost 3 vzipr LHS, <1,3,5,7> + 2618104165U, // <2,5,u,u>: Cost 3 vext2 <0,1,2,5>, LHS + 2620096512U, // <2,6,0,0>: Cost 3 vext2 <0,4,2,6>, <0,0,0,0> + 1546354790U, // <2,6,0,1>: Cost 2 vext2 <0,4,2,6>, LHS + 2620096676U, // <2,6,0,2>: Cost 3 vext2 <0,4,2,6>, <0,2,0,2> + 3693838588U, // <2,6,0,3>: Cost 4 vext2 <0,4,2,6>, <0,3,1,0> + 1546355036U, // <2,6,0,4>: Cost 2 vext2 <0,4,2,6>, <0,4,2,6> + 3694502317U, // <2,6,0,5>: Cost 4 vext2 <0,5,2,6>, <0,5,2,6> + 2551911246U, // <2,6,0,6>: Cost 3 vext1 <0,2,6,0>, <6,7,0,1> + 2720723287U, // <2,6,0,7>: Cost 3 vext3 <6,0,7,2>, <6,0,7,2> + 1546355357U, // <2,6,0,u>: Cost 2 vext2 <0,4,2,6>, LHS + 2620097270U, // <2,6,1,0>: Cost 3 vext2 <0,4,2,6>, <1,0,3,2> + 2620097332U, // <2,6,1,1>: Cost 3 vext2 <0,4,2,6>, <1,1,1,1> + 2620097430U, // <2,6,1,2>: Cost 3 vext2 <0,4,2,6>, <1,2,3,0> + 2820243558U, // <2,6,1,3>: Cost 3 vuzpr <0,2,4,6>, LHS + 2620097598U, // <2,6,1,4>: Cost 3 vext2 <0,4,2,6>, <1,4,3,6> + 2620097680U, // <2,6,1,5>: Cost 3 vext2 <0,4,2,6>, <1,5,3,7> + 3693839585U, // <2,6,1,6>: Cost 4 vext2 <0,4,2,6>, <1,6,3,7> + 2721386920U, // <2,6,1,7>: Cost 3 vext3 <6,1,7,2>, <6,1,7,2> + 2820243563U, // <2,6,1,u>: Cost 3 vuzpr <0,2,4,6>, LHS + 2714014137U, // <2,6,2,0>: Cost 3 vext3 <4,u,6,2>, <6,2,0,1> + 2712834500U, // <2,6,2,1>: Cost 3 vext3 <4,6,u,2>, <6,2,1,3> + 2620098152U, // <2,6,2,2>: Cost 3 vext2 <0,4,2,6>, <2,2,2,2> + 2620098214U, // <2,6,2,3>: Cost 3 vext2 <0,4,2,6>, <2,3,0,1> + 2632042254U, // <2,6,2,4>: Cost 3 vext2 <2,4,2,6>, <2,4,2,6> + 2712834540U, // <2,6,2,5>: Cost 3 vext3 <4,6,u,2>, <6,2,5,7> + 2820243660U, // <2,6,2,6>: Cost 3 vuzpr <0,2,4,6>, <0,2,4,6> + 2958265654U, // <2,6,2,7>: Cost 3 vzipr <0,u,2,2>, RHS + 2620098619U, // <2,6,2,u>: Cost 3 vext2 <0,4,2,6>, <2,u,0,1> + 2620098710U, // <2,6,3,0>: Cost 3 vext2 <0,4,2,6>, <3,0,1,2> + 3893986982U, // <2,6,3,1>: Cost 4 vuzpr <0,2,4,6>, <2,3,0,1> + 2569848762U, // <2,6,3,2>: Cost 3 vext1 <3,2,6,3>, <2,6,3,7> + 2620098972U, // <2,6,3,3>: Cost 3 vext2 <0,4,2,6>, <3,3,3,3> + 2620099074U, // <2,6,3,4>: Cost 3 vext2 <0,4,2,6>, <3,4,5,6> + 3893987022U, // <2,6,3,5>: Cost 4 vuzpr <0,2,4,6>, <2,3,4,5> + 3001404644U, // <2,6,3,6>: Cost 3 vzipr LHS, <4,4,6,6> + 1879887158U, // <2,6,3,7>: Cost 2 vzipr LHS, RHS + 1879887159U, // <2,6,3,u>: Cost 2 vzipr LHS, RHS + 2620099484U, // <2,6,4,0>: Cost 3 vext2 <0,4,2,6>, <4,0,6,2> + 2620099566U, // <2,6,4,1>: Cost 3 vext2 <0,4,2,6>, <4,1,6,3> + 2620099644U, // <2,6,4,2>: Cost 3 vext2 <0,4,2,6>, <4,2,6,0> + 3643599207U, // <2,6,4,3>: Cost 4 vext1 <3,2,6,4>, <3,2,6,4> + 2575830080U, // <2,6,4,4>: Cost 3 vext1 <4,2,6,4>, <4,2,6,4> + 1546358070U, // <2,6,4,5>: Cost 2 vext2 <0,4,2,6>, RHS + 2667875700U, // <2,6,4,6>: Cost 3 vext2 , <4,6,4,6> + 4028042550U, // <2,6,4,7>: Cost 4 vzipr <0,2,2,4>, RHS + 1546358313U, // <2,6,4,u>: Cost 2 vext2 <0,4,2,6>, RHS + 3693841992U, // <2,6,5,0>: Cost 4 vext2 <0,4,2,6>, <5,0,1,2> + 2667876048U, // <2,6,5,1>: Cost 3 vext2 , <5,1,7,3> + 2712834756U, // <2,6,5,2>: Cost 3 vext3 <4,6,u,2>, <6,5,2,7> + 3643607400U, // <2,6,5,3>: Cost 4 vext1 <3,2,6,5>, <3,2,6,5> + 2252091873U, // <2,6,5,4>: Cost 3 vrev <6,2,4,5> + 2667876356U, // <2,6,5,5>: Cost 3 vext2 , <5,5,5,5> + 2667876450U, // <2,6,5,6>: Cost 3 vext2 , <5,6,7,0> + 2820246838U, // <2,6,5,7>: Cost 3 vuzpr <0,2,4,6>, RHS + 2820246839U, // <2,6,5,u>: Cost 3 vuzpr <0,2,4,6>, RHS + 2563899494U, // <2,6,6,0>: Cost 3 vext1 <2,2,6,6>, LHS + 3893988683U, // <2,6,6,1>: Cost 4 vuzpr <0,2,4,6>, <4,6,0,1> + 2563901072U, // <2,6,6,2>: Cost 3 vext1 <2,2,6,6>, <2,2,6,6> + 3893987236U, // <2,6,6,3>: Cost 4 vuzpr <0,2,4,6>, <2,6,1,3> + 2563902774U, // <2,6,6,4>: Cost 3 vext1 <2,2,6,6>, RHS + 3893988723U, // <2,6,6,5>: Cost 4 vuzpr <0,2,4,6>, <4,6,4,5> + 2712834872U, // <2,6,6,6>: Cost 3 vext3 <4,6,u,2>, <6,6,6,6> + 2955644214U, // <2,6,6,7>: Cost 3 vzipr <0,4,2,6>, RHS + 2955644215U, // <2,6,6,u>: Cost 3 vzipr <0,4,2,6>, RHS + 2712834894U, // <2,6,7,0>: Cost 3 vext3 <4,6,u,2>, <6,7,0,1> + 2724926296U, // <2,6,7,1>: Cost 3 vext3 <6,7,1,2>, <6,7,1,2> + 2725000033U, // <2,6,7,2>: Cost 3 vext3 <6,7,2,2>, <6,7,2,2> + 2702365544U, // <2,6,7,3>: Cost 3 vext3 <3,0,1,2>, <6,7,3,0> + 2712834934U, // <2,6,7,4>: Cost 3 vext3 <4,6,u,2>, <6,7,4,5> + 3776107393U, // <2,6,7,5>: Cost 4 vext3 <3,0,1,2>, <6,7,5,7> + 2725294981U, // <2,6,7,6>: Cost 3 vext3 <6,7,6,2>, <6,7,6,2> + 2726253452U, // <2,6,7,7>: Cost 3 vext3 <7,0,1,2>, <6,7,7,0> + 2712834966U, // <2,6,7,u>: Cost 3 vext3 <4,6,u,2>, <6,7,u,1> + 2620102355U, // <2,6,u,0>: Cost 3 vext2 <0,4,2,6>, + 1546360622U, // <2,6,u,1>: Cost 2 vext2 <0,4,2,6>, LHS + 2620102536U, // <2,6,u,2>: Cost 3 vext2 <0,4,2,6>, + 2820244125U, // <2,6,u,3>: Cost 3 vuzpr <0,2,4,6>, LHS + 1594136612U, // <2,6,u,4>: Cost 2 vext2 , + 1546360986U, // <2,6,u,5>: Cost 2 vext2 <0,4,2,6>, RHS + 2620102864U, // <2,6,u,6>: Cost 3 vext2 <0,4,2,6>, + 1879928118U, // <2,6,u,7>: Cost 2 vzipr LHS, RHS + 1879928119U, // <2,6,u,u>: Cost 2 vzipr LHS, RHS + 2726179825U, // <2,7,0,0>: Cost 3 vext3 <7,0,0,2>, <7,0,0,2> + 1652511738U, // <2,7,0,1>: Cost 2 vext3 <7,0,1,2>, <7,0,1,2> + 2621431972U, // <2,7,0,2>: Cost 3 vext2 <0,6,2,7>, <0,2,0,2> + 2257949868U, // <2,7,0,3>: Cost 3 vrev <7,2,3,0> + 2726474773U, // <2,7,0,4>: Cost 3 vext3 <7,0,4,2>, <7,0,4,2> + 2620768686U, // <2,7,0,5>: Cost 3 vext2 <0,5,2,7>, <0,5,2,7> + 2621432319U, // <2,7,0,6>: Cost 3 vext2 <0,6,2,7>, <0,6,2,7> + 2599760953U, // <2,7,0,7>: Cost 3 vext1 , <7,0,u,2> + 1653027897U, // <2,7,0,u>: Cost 2 vext3 <7,0,u,2>, <7,0,u,2> + 2639348470U, // <2,7,1,0>: Cost 3 vext2 <3,6,2,7>, <1,0,3,2> + 3695174452U, // <2,7,1,1>: Cost 4 vext2 <0,6,2,7>, <1,1,1,1> + 3695174550U, // <2,7,1,2>: Cost 4 vext2 <0,6,2,7>, <1,2,3,0> + 3694511104U, // <2,7,1,3>: Cost 4 vext2 <0,5,2,7>, <1,3,5,7> + 3713090594U, // <2,7,1,4>: Cost 4 vext2 <3,6,2,7>, <1,4,0,5> + 3693184144U, // <2,7,1,5>: Cost 4 vext2 <0,3,2,7>, <1,5,3,7> + 2627405016U, // <2,7,1,6>: Cost 3 vext2 <1,6,2,7>, <1,6,2,7> + 3799995519U, // <2,7,1,7>: Cost 4 vext3 <7,0,1,2>, <7,1,7,0> + 2639348470U, // <2,7,1,u>: Cost 3 vext2 <3,6,2,7>, <1,0,3,2> + 3695175101U, // <2,7,2,0>: Cost 4 vext2 <0,6,2,7>, <2,0,1,2> + 3643655168U, // <2,7,2,1>: Cost 4 vext1 <3,2,7,2>, <1,3,5,7> + 2257892517U, // <2,7,2,2>: Cost 3 vrev <7,2,2,2> + 3695175334U, // <2,7,2,3>: Cost 4 vext2 <0,6,2,7>, <2,3,0,1> + 3695175465U, // <2,7,2,4>: Cost 4 vext2 <0,6,2,7>, <2,4,5,6> + 2632714080U, // <2,7,2,5>: Cost 3 vext2 <2,5,2,7>, <2,5,2,7> + 2633377713U, // <2,7,2,6>: Cost 3 vext2 <2,6,2,7>, <2,6,2,7> + 3695175658U, // <2,7,2,7>: Cost 4 vext2 <0,6,2,7>, <2,7,0,1> + 2634704979U, // <2,7,2,u>: Cost 3 vext2 <2,u,2,7>, <2,u,2,7> + 1514094694U, // <2,7,3,0>: Cost 2 vext1 <6,2,7,3>, LHS + 2569921680U, // <2,7,3,1>: Cost 3 vext1 <3,2,7,3>, <1,5,3,7> + 2587838056U, // <2,7,3,2>: Cost 3 vext1 <6,2,7,3>, <2,2,2,2> + 2569922927U, // <2,7,3,3>: Cost 3 vext1 <3,2,7,3>, <3,2,7,3> + 1514097974U, // <2,7,3,4>: Cost 2 vext1 <6,2,7,3>, RHS + 2581868321U, // <2,7,3,5>: Cost 3 vext1 <5,2,7,3>, <5,2,7,3> + 1514099194U, // <2,7,3,6>: Cost 2 vext1 <6,2,7,3>, <6,2,7,3> + 2587841530U, // <2,7,3,7>: Cost 3 vext1 <6,2,7,3>, <7,0,1,2> + 1514100526U, // <2,7,3,u>: Cost 2 vext1 <6,2,7,3>, LHS + 2708706617U, // <2,7,4,0>: Cost 3 vext3 <4,0,6,2>, <7,4,0,6> + 3649643418U, // <2,7,4,1>: Cost 4 vext1 <4,2,7,4>, <1,2,3,4> + 3649644330U, // <2,7,4,2>: Cost 4 vext1 <4,2,7,4>, <2,4,5,7> + 2257982640U, // <2,7,4,3>: Cost 3 vrev <7,2,3,4> + 3649645641U, // <2,7,4,4>: Cost 4 vext1 <4,2,7,4>, <4,2,7,4> + 2621435190U, // <2,7,4,5>: Cost 3 vext2 <0,6,2,7>, RHS + 2712835441U, // <2,7,4,6>: Cost 3 vext3 <4,6,u,2>, <7,4,6,u> + 3799995762U, // <2,7,4,7>: Cost 4 vext3 <7,0,1,2>, <7,4,7,0> + 2621435433U, // <2,7,4,u>: Cost 3 vext2 <0,6,2,7>, RHS + 2729497990U, // <2,7,5,0>: Cost 3 vext3 <7,5,0,2>, <7,5,0,2> + 3643679744U, // <2,7,5,1>: Cost 4 vext1 <3,2,7,5>, <1,3,5,7> + 3637708424U, // <2,7,5,2>: Cost 4 vext1 <2,2,7,5>, <2,2,5,7> + 3643681137U, // <2,7,5,3>: Cost 4 vext1 <3,2,7,5>, <3,2,7,5> + 2599800118U, // <2,7,5,4>: Cost 3 vext1 , RHS + 3786577334U, // <2,7,5,5>: Cost 4 vext3 <4,6,u,2>, <7,5,5,5> + 3786577345U, // <2,7,5,6>: Cost 4 vext3 <4,6,u,2>, <7,5,6,7> + 2599802214U, // <2,7,5,7>: Cost 3 vext1 , <7,4,5,6> + 2599802670U, // <2,7,5,u>: Cost 3 vext1 , LHS + 2581889126U, // <2,7,6,0>: Cost 3 vext1 <5,2,7,6>, LHS + 3643687936U, // <2,7,6,1>: Cost 4 vext1 <3,2,7,6>, <1,3,5,7> + 2663240186U, // <2,7,6,2>: Cost 3 vext2 <7,6,2,7>, <6,2,7,3> + 3643689330U, // <2,7,6,3>: Cost 4 vext1 <3,2,7,6>, <3,2,7,6> + 2581892406U, // <2,7,6,4>: Cost 3 vext1 <5,2,7,6>, RHS + 2581892900U, // <2,7,6,5>: Cost 3 vext1 <5,2,7,6>, <5,2,7,6> + 2587865597U, // <2,7,6,6>: Cost 3 vext1 <6,2,7,6>, <6,2,7,6> + 3786577428U, // <2,7,6,7>: Cost 4 vext3 <4,6,u,2>, <7,6,7,0> + 2581894958U, // <2,7,6,u>: Cost 3 vext1 <5,2,7,6>, LHS + 2726254119U, // <2,7,7,0>: Cost 3 vext3 <7,0,1,2>, <7,7,0,1> + 3804640817U, // <2,7,7,1>: Cost 4 vext3 <7,7,1,2>, <7,7,1,2> + 3637724826U, // <2,7,7,2>: Cost 4 vext1 <2,2,7,7>, <2,2,7,7> + 3734992123U, // <2,7,7,3>: Cost 4 vext2 <7,3,2,7>, <7,3,2,7> + 2552040758U, // <2,7,7,4>: Cost 3 vext1 <0,2,7,7>, RHS + 3799995992U, // <2,7,7,5>: Cost 4 vext3 <7,0,1,2>, <7,7,5,5> + 2663241198U, // <2,7,7,6>: Cost 3 vext2 <7,6,2,7>, <7,6,2,7> + 2712835692U, // <2,7,7,7>: Cost 3 vext3 <4,6,u,2>, <7,7,7,7> + 2731562607U, // <2,7,7,u>: Cost 3 vext3 <7,u,1,2>, <7,7,u,1> + 1514135654U, // <2,7,u,0>: Cost 2 vext1 <6,2,7,u>, LHS + 1657820802U, // <2,7,u,1>: Cost 2 vext3 <7,u,1,2>, <7,u,1,2> + 2587879016U, // <2,7,u,2>: Cost 3 vext1 <6,2,7,u>, <2,2,2,2> + 2569963892U, // <2,7,u,3>: Cost 3 vext1 <3,2,7,u>, <3,2,7,u> + 1514138934U, // <2,7,u,4>: Cost 2 vext1 <6,2,7,u>, RHS + 2621438106U, // <2,7,u,5>: Cost 3 vext2 <0,6,2,7>, RHS + 1514140159U, // <2,7,u,6>: Cost 2 vext1 <6,2,7,u>, <6,2,7,u> + 2587882490U, // <2,7,u,7>: Cost 3 vext1 <6,2,7,u>, <7,0,1,2> + 1514141486U, // <2,7,u,u>: Cost 2 vext1 <6,2,7,u>, LHS + 1544380416U, // <2,u,0,0>: Cost 2 vext2 LHS, <0,0,0,0> + 470638699U, // <2,u,0,1>: Cost 1 vext2 LHS, LHS + 1544380580U, // <2,u,0,2>: Cost 2 vext2 LHS, <0,2,0,2> + 1658631909U, // <2,u,0,3>: Cost 2 vext3 , + 1544380754U, // <2,u,0,4>: Cost 2 vext2 LHS, <0,4,1,5> + 2665898414U, // <2,u,0,5>: Cost 3 vext2 LHS, <0,5,2,7> + 1658853120U, // <2,u,0,6>: Cost 2 vext3 , + 3094531625U, // <2,u,0,7>: Cost 3 vtrnr <1,2,3,0>, RHS + 470639261U, // <2,u,0,u>: Cost 1 vext2 LHS, LHS + 1544381174U, // <2,u,1,0>: Cost 2 vext2 LHS, <1,0,3,2> + 1544381236U, // <2,u,1,1>: Cost 2 vext2 LHS, <1,1,1,1> + 1544381334U, // <2,u,1,2>: Cost 2 vext2 LHS, <1,2,3,0> + 1544381400U, // <2,u,1,3>: Cost 2 vext2 LHS, <1,3,1,3> + 2618123325U, // <2,u,1,4>: Cost 3 vext2 LHS, <1,4,3,5> + 1544381584U, // <2,u,1,5>: Cost 2 vext2 LHS, <1,5,3,7> + 2618123489U, // <2,u,1,6>: Cost 3 vext2 LHS, <1,6,3,7> + 2726254427U, // <2,u,1,7>: Cost 3 vext3 <7,0,1,2>, + 1544381823U, // <2,u,1,u>: Cost 2 vext2 LHS, <1,u,3,3> + 1478328422U, // <2,u,2,0>: Cost 2 vext1 <0,2,u,2>, LHS + 2618123807U, // <2,u,2,1>: Cost 3 vext2 LHS, <2,1,3,1> + 269271142U, // <2,u,2,2>: Cost 1 vdup2 LHS + 1544382118U, // <2,u,2,3>: Cost 2 vext2 LHS, <2,3,0,1> + 1478331702U, // <2,u,2,4>: Cost 2 vext1 <0,2,u,2>, RHS + 2618124136U, // <2,u,2,5>: Cost 3 vext2 LHS, <2,5,3,6> + 1544382394U, // <2,u,2,6>: Cost 2 vext2 LHS, <2,6,3,7> + 3088354857U, // <2,u,2,7>: Cost 3 vtrnr <0,2,0,2>, RHS + 269271142U, // <2,u,2,u>: Cost 1 vdup2 LHS + 1544382614U, // <2,u,3,0>: Cost 2 vext2 LHS, <3,0,1,2> + 2953627374U, // <2,u,3,1>: Cost 3 vzipr LHS, <2,3,u,1> + 1490282143U, // <2,u,3,2>: Cost 2 vext1 <2,2,u,3>, <2,2,u,3> + 1879883932U, // <2,u,3,3>: Cost 2 vzipr LHS, LHS + 1544382978U, // <2,u,3,4>: Cost 2 vext2 LHS, <3,4,5,6> + 2953627378U, // <2,u,3,5>: Cost 3 vzipr LHS, <2,3,u,5> + 1514172931U, // <2,u,3,6>: Cost 2 vext1 <6,2,u,3>, <6,2,u,3> + 1879887176U, // <2,u,3,7>: Cost 2 vzipr LHS, RHS + 1879883937U, // <2,u,3,u>: Cost 2 vzipr LHS, LHS + 1484316774U, // <2,u,4,0>: Cost 2 vext1 <1,2,u,4>, LHS + 1484317639U, // <2,u,4,1>: Cost 2 vext1 <1,2,u,4>, <1,2,u,4> + 2552088270U, // <2,u,4,2>: Cost 3 vext1 <0,2,u,4>, <2,3,4,5> + 1190213513U, // <2,u,4,3>: Cost 2 vrev + 1484320054U, // <2,u,4,4>: Cost 2 vext1 <1,2,u,4>, RHS + 470641974U, // <2,u,4,5>: Cost 1 vext2 LHS, RHS + 1592159604U, // <2,u,4,6>: Cost 2 vext2 LHS, <4,6,4,6> + 3094564393U, // <2,u,4,7>: Cost 3 vtrnr <1,2,3,4>, RHS + 470642217U, // <2,u,4,u>: Cost 1 vext2 LHS, RHS + 2552094959U, // <2,u,5,0>: Cost 3 vext1 <0,2,u,5>, <0,2,u,5> + 1592159952U, // <2,u,5,1>: Cost 2 vext2 LHS, <5,1,7,3> + 2564040353U, // <2,u,5,2>: Cost 3 vext1 <2,2,u,5>, <2,2,u,5> + 2690275455U, // <2,u,5,3>: Cost 3 vext3 <0,u,u,2>, + 1592160198U, // <2,u,5,4>: Cost 2 vext2 LHS, <5,4,7,6> + 1592160260U, // <2,u,5,5>: Cost 2 vext2 LHS, <5,5,5,5> + 1611962522U, // <2,u,5,6>: Cost 2 vext3 <0,2,0,2>, RHS + 1592160424U, // <2,u,5,7>: Cost 2 vext2 LHS, <5,7,5,7> + 1611962540U, // <2,u,5,u>: Cost 2 vext3 <0,2,0,2>, RHS + 1478361190U, // <2,u,6,0>: Cost 2 vext1 <0,2,u,6>, LHS + 2552103670U, // <2,u,6,1>: Cost 3 vext1 <0,2,u,6>, <1,0,3,2> + 1592160762U, // <2,u,6,2>: Cost 2 vext2 LHS, <6,2,7,3> + 2685704400U, // <2,u,6,3>: Cost 3 vext3 <0,2,0,2>, + 1478364470U, // <2,u,6,4>: Cost 2 vext1 <0,2,u,6>, RHS + 2901891226U, // <2,u,6,5>: Cost 3 vzipl <2,6,3,7>, RHS + 1592161080U, // <2,u,6,6>: Cost 2 vext2 LHS, <6,6,6,6> + 1592161102U, // <2,u,6,7>: Cost 2 vext2 LHS, <6,7,0,1> + 1478367022U, // <2,u,6,u>: Cost 2 vext1 <0,2,u,6>, LHS + 1592161274U, // <2,u,7,0>: Cost 2 vext2 LHS, <7,0,1,2> + 2659931226U, // <2,u,7,1>: Cost 3 vext2 <7,1,2,u>, <7,1,2,u> + 2564056739U, // <2,u,7,2>: Cost 3 vext1 <2,2,u,7>, <2,2,u,7> + 2665903331U, // <2,u,7,3>: Cost 3 vext2 LHS, <7,3,0,1> + 1592161638U, // <2,u,7,4>: Cost 2 vext2 LHS, <7,4,5,6> + 2665903494U, // <2,u,7,5>: Cost 3 vext2 LHS, <7,5,0,2> + 2587947527U, // <2,u,7,6>: Cost 3 vext1 <6,2,u,7>, <6,2,u,7> + 1592161900U, // <2,u,7,7>: Cost 2 vext2 LHS, <7,7,7,7> + 1592161922U, // <2,u,7,u>: Cost 2 vext2 LHS, <7,u,1,2> + 1478377574U, // <2,u,u,0>: Cost 2 vext1 <0,2,u,u>, LHS + 470644526U, // <2,u,u,1>: Cost 1 vext2 LHS, LHS + 269271142U, // <2,u,u,2>: Cost 1 vdup2 LHS + 1879924892U, // <2,u,u,3>: Cost 2 vzipr LHS, LHS + 1478380854U, // <2,u,u,4>: Cost 2 vext1 <0,2,u,u>, RHS + 470644890U, // <2,u,u,5>: Cost 1 vext2 LHS, RHS + 1611962765U, // <2,u,u,6>: Cost 2 vext3 <0,2,0,2>, RHS + 1879928136U, // <2,u,u,7>: Cost 2 vzipr LHS, RHS + 470645093U, // <2,u,u,u>: Cost 1 vext2 LHS, LHS + 1611448320U, // <3,0,0,0>: Cost 2 vext3 LHS, <0,0,0,0> + 1611890698U, // <3,0,0,1>: Cost 2 vext3 LHS, <0,0,1,1> + 1611890708U, // <3,0,0,2>: Cost 2 vext3 LHS, <0,0,2,2> + 3763576860U, // <3,0,0,3>: Cost 4 vext3 LHS, <0,0,3,1> + 2689835045U, // <3,0,0,4>: Cost 3 vext3 LHS, <0,0,4,1> + 3698508206U, // <3,0,0,5>: Cost 4 vext2 <1,2,3,0>, <0,5,2,7> + 3763576887U, // <3,0,0,6>: Cost 4 vext3 LHS, <0,0,6,1> + 3667678434U, // <3,0,0,7>: Cost 4 vext1 <7,3,0,0>, <7,3,0,0> + 1616093258U, // <3,0,0,u>: Cost 2 vext3 LHS, <0,0,u,2> + 1490337894U, // <3,0,1,0>: Cost 2 vext1 <2,3,0,1>, LHS + 2685632602U, // <3,0,1,1>: Cost 3 vext3 LHS, <0,1,1,0> + 537706598U, // <3,0,1,2>: Cost 1 vext3 LHS, LHS + 2624766936U, // <3,0,1,3>: Cost 3 vext2 <1,2,3,0>, <1,3,1,3> + 1490341174U, // <3,0,1,4>: Cost 2 vext1 <2,3,0,1>, RHS + 2624767120U, // <3,0,1,5>: Cost 3 vext2 <1,2,3,0>, <1,5,3,7> + 2732966030U, // <3,0,1,6>: Cost 3 vext3 LHS, <0,1,6,7> + 2593944803U, // <3,0,1,7>: Cost 3 vext1 <7,3,0,1>, <7,3,0,1> + 537706652U, // <3,0,1,u>: Cost 1 vext3 LHS, LHS + 1611890852U, // <3,0,2,0>: Cost 2 vext3 LHS, <0,2,0,2> + 2685632684U, // <3,0,2,1>: Cost 3 vext3 LHS, <0,2,1,1> + 2685632692U, // <3,0,2,2>: Cost 3 vext3 LHS, <0,2,2,0> + 2685632702U, // <3,0,2,3>: Cost 3 vext3 LHS, <0,2,3,1> + 1611890892U, // <3,0,2,4>: Cost 2 vext3 LHS, <0,2,4,6> + 2732966102U, // <3,0,2,5>: Cost 3 vext3 LHS, <0,2,5,7> + 2624767930U, // <3,0,2,6>: Cost 3 vext2 <1,2,3,0>, <2,6,3,7> + 2685632744U, // <3,0,2,7>: Cost 3 vext3 LHS, <0,2,7,7> + 1611890924U, // <3,0,2,u>: Cost 2 vext3 LHS, <0,2,u,2> + 2624768150U, // <3,0,3,0>: Cost 3 vext2 <1,2,3,0>, <3,0,1,2> + 2685632764U, // <3,0,3,1>: Cost 3 vext3 LHS, <0,3,1,0> + 2685632774U, // <3,0,3,2>: Cost 3 vext3 LHS, <0,3,2,1> + 2624768412U, // <3,0,3,3>: Cost 3 vext2 <1,2,3,0>, <3,3,3,3> + 2624768514U, // <3,0,3,4>: Cost 3 vext2 <1,2,3,0>, <3,4,5,6> + 3702491714U, // <3,0,3,5>: Cost 4 vext2 <1,u,3,0>, <3,5,3,7> + 2624768632U, // <3,0,3,6>: Cost 3 vext2 <1,2,3,0>, <3,6,0,7> + 3702491843U, // <3,0,3,7>: Cost 4 vext2 <1,u,3,0>, <3,7,0,1> + 2686959934U, // <3,0,3,u>: Cost 3 vext3 <0,3,u,3>, <0,3,u,3> + 2689835336U, // <3,0,4,0>: Cost 3 vext3 LHS, <0,4,0,4> + 1611891026U, // <3,0,4,1>: Cost 2 vext3 LHS, <0,4,1,5> + 1611891036U, // <3,0,4,2>: Cost 2 vext3 LHS, <0,4,2,6> + 3763577184U, // <3,0,4,3>: Cost 4 vext3 LHS, <0,4,3,1> + 2689835374U, // <3,0,4,4>: Cost 3 vext3 LHS, <0,4,4,6> + 1551027510U, // <3,0,4,5>: Cost 2 vext2 <1,2,3,0>, RHS + 2666573172U, // <3,0,4,6>: Cost 3 vext2 , <4,6,4,6> + 3667711206U, // <3,0,4,7>: Cost 4 vext1 <7,3,0,4>, <7,3,0,4> + 1616093586U, // <3,0,4,u>: Cost 2 vext3 LHS, <0,4,u,6> + 2685190556U, // <3,0,5,0>: Cost 3 vext3 LHS, <0,5,0,7> + 2666573520U, // <3,0,5,1>: Cost 3 vext2 , <5,1,7,3> + 3040886886U, // <3,0,5,2>: Cost 3 vtrnl <3,4,5,6>, LHS + 3625912834U, // <3,0,5,3>: Cost 4 vext1 <0,3,0,5>, <3,4,5,6> + 2666573766U, // <3,0,5,4>: Cost 3 vext2 , <5,4,7,6> + 2666573828U, // <3,0,5,5>: Cost 3 vext2 , <5,5,5,5> + 2732966354U, // <3,0,5,6>: Cost 3 vext3 LHS, <0,5,6,7> + 2666573992U, // <3,0,5,7>: Cost 3 vext2 , <5,7,5,7> + 3040886940U, // <3,0,5,u>: Cost 3 vtrnl <3,4,5,6>, LHS + 2685190637U, // <3,0,6,0>: Cost 3 vext3 LHS, <0,6,0,7> + 2732966390U, // <3,0,6,1>: Cost 3 vext3 LHS, <0,6,1,7> + 2689835519U, // <3,0,6,2>: Cost 3 vext3 LHS, <0,6,2,7> + 3667724438U, // <3,0,6,3>: Cost 4 vext1 <7,3,0,6>, <3,0,1,2> + 3763577355U, // <3,0,6,4>: Cost 4 vext3 LHS, <0,6,4,1> + 3806708243U, // <3,0,6,5>: Cost 4 vext3 LHS, <0,6,5,0> + 2666574648U, // <3,0,6,6>: Cost 3 vext2 , <6,6,6,6> + 2657948520U, // <3,0,6,7>: Cost 3 vext2 <6,7,3,0>, <6,7,3,0> + 2689835573U, // <3,0,6,u>: Cost 3 vext3 LHS, <0,6,u,7> + 2666574842U, // <3,0,7,0>: Cost 3 vext2 , <7,0,1,2> + 2685633095U, // <3,0,7,1>: Cost 3 vext3 LHS, <0,7,1,7> + 2660603052U, // <3,0,7,2>: Cost 3 vext2 <7,2,3,0>, <7,2,3,0> + 3643844997U, // <3,0,7,3>: Cost 4 vext1 <3,3,0,7>, <3,3,0,7> + 2666575206U, // <3,0,7,4>: Cost 3 vext2 , <7,4,5,6> + 3655790391U, // <3,0,7,5>: Cost 4 vext1 <5,3,0,7>, <5,3,0,7> + 3731690968U, // <3,0,7,6>: Cost 4 vext2 <6,7,3,0>, <7,6,0,3> + 2666575468U, // <3,0,7,7>: Cost 3 vext2 , <7,7,7,7> + 2664584850U, // <3,0,7,u>: Cost 3 vext2 <7,u,3,0>, <7,u,3,0> + 1616093834U, // <3,0,u,0>: Cost 2 vext3 LHS, <0,u,0,2> + 1611891346U, // <3,0,u,1>: Cost 2 vext3 LHS, <0,u,1,1> + 537707165U, // <3,0,u,2>: Cost 1 vext3 LHS, LHS + 2689835684U, // <3,0,u,3>: Cost 3 vext3 LHS, <0,u,3,1> + 1616093874U, // <3,0,u,4>: Cost 2 vext3 LHS, <0,u,4,6> + 1551030426U, // <3,0,u,5>: Cost 2 vext2 <1,2,3,0>, RHS + 2624772304U, // <3,0,u,6>: Cost 3 vext2 <1,2,3,0>, + 2594002154U, // <3,0,u,7>: Cost 3 vext1 <7,3,0,u>, <7,3,0,u> + 537707219U, // <3,0,u,u>: Cost 1 vext3 LHS, LHS + 2552201318U, // <3,1,0,0>: Cost 3 vext1 <0,3,1,0>, LHS + 2618802278U, // <3,1,0,1>: Cost 3 vext2 <0,2,3,1>, LHS + 2618802366U, // <3,1,0,2>: Cost 3 vext2 <0,2,3,1>, <0,2,3,1> + 1611449078U, // <3,1,0,3>: Cost 2 vext3 LHS, <1,0,3,2> + 2552204598U, // <3,1,0,4>: Cost 3 vext1 <0,3,1,0>, RHS + 2732966663U, // <3,1,0,5>: Cost 3 vext3 LHS, <1,0,5,1> + 3906258396U, // <3,1,0,6>: Cost 4 vuzpr <2,3,0,1>, <2,0,4,6> + 3667752171U, // <3,1,0,7>: Cost 4 vext1 <7,3,1,0>, <7,3,1,0> + 1611891491U, // <3,1,0,u>: Cost 2 vext3 LHS, <1,0,u,2> + 2689835819U, // <3,1,1,0>: Cost 3 vext3 LHS, <1,1,0,1> + 1611449140U, // <3,1,1,1>: Cost 2 vext3 LHS, <1,1,1,1> + 2624775063U, // <3,1,1,2>: Cost 3 vext2 <1,2,3,1>, <1,2,3,1> + 1611891528U, // <3,1,1,3>: Cost 2 vext3 LHS, <1,1,3,3> + 2689835859U, // <3,1,1,4>: Cost 3 vext3 LHS, <1,1,4,5> + 2689835868U, // <3,1,1,5>: Cost 3 vext3 LHS, <1,1,5,5> + 3763577701U, // <3,1,1,6>: Cost 4 vext3 LHS, <1,1,6,5> + 3765273452U, // <3,1,1,7>: Cost 4 vext3 <1,1,7,3>, <1,1,7,3> + 1611891573U, // <3,1,1,u>: Cost 2 vext3 LHS, <1,1,u,3> + 2629420494U, // <3,1,2,0>: Cost 3 vext2 <2,0,3,1>, <2,0,3,1> + 2689835911U, // <3,1,2,1>: Cost 3 vext3 LHS, <1,2,1,3> + 2564163248U, // <3,1,2,2>: Cost 3 vext1 <2,3,1,2>, <2,3,1,2> + 1611449238U, // <3,1,2,3>: Cost 2 vext3 LHS, <1,2,3,0> + 2564164918U, // <3,1,2,4>: Cost 3 vext1 <2,3,1,2>, RHS + 2689835947U, // <3,1,2,5>: Cost 3 vext3 LHS, <1,2,5,3> + 3692545978U, // <3,1,2,6>: Cost 4 vext2 <0,2,3,1>, <2,6,3,7> + 2732966842U, // <3,1,2,7>: Cost 3 vext3 LHS, <1,2,7,0> + 1611891651U, // <3,1,2,u>: Cost 2 vext3 LHS, <1,2,u,0> + 1484456038U, // <3,1,3,0>: Cost 2 vext1 <1,3,1,3>, LHS + 1611891672U, // <3,1,3,1>: Cost 2 vext3 LHS, <1,3,1,3> + 2685633502U, // <3,1,3,2>: Cost 3 vext3 LHS, <1,3,2,0> + 2685633512U, // <3,1,3,3>: Cost 3 vext3 LHS, <1,3,3,1> + 1484459318U, // <3,1,3,4>: Cost 2 vext1 <1,3,1,3>, RHS + 1611891712U, // <3,1,3,5>: Cost 2 vext3 LHS, <1,3,5,7> + 2689836041U, // <3,1,3,6>: Cost 3 vext3 LHS, <1,3,6,7> + 2733409294U, // <3,1,3,7>: Cost 3 vext3 LHS, <1,3,7,3> + 1611891735U, // <3,1,3,u>: Cost 2 vext3 LHS, <1,3,u,3> + 2552234086U, // <3,1,4,0>: Cost 3 vext1 <0,3,1,4>, LHS + 2732966955U, // <3,1,4,1>: Cost 3 vext3 LHS, <1,4,1,5> + 2732966964U, // <3,1,4,2>: Cost 3 vext3 LHS, <1,4,2,5> + 2685633597U, // <3,1,4,3>: Cost 3 vext3 LHS, <1,4,3,5> + 2552237366U, // <3,1,4,4>: Cost 3 vext1 <0,3,1,4>, RHS + 2618805558U, // <3,1,4,5>: Cost 3 vext2 <0,2,3,1>, RHS + 2769472822U, // <3,1,4,6>: Cost 3 vuzpl <3,0,1,2>, RHS + 3667784943U, // <3,1,4,7>: Cost 4 vext1 <7,3,1,4>, <7,3,1,4> + 2685633642U, // <3,1,4,u>: Cost 3 vext3 LHS, <1,4,u,5> + 2689836143U, // <3,1,5,0>: Cost 3 vext3 LHS, <1,5,0,1> + 2564187280U, // <3,1,5,1>: Cost 3 vext1 <2,3,1,5>, <1,5,3,7> + 2564187827U, // <3,1,5,2>: Cost 3 vext1 <2,3,1,5>, <2,3,1,5> + 1611891856U, // <3,1,5,3>: Cost 2 vext3 LHS, <1,5,3,7> + 2689836183U, // <3,1,5,4>: Cost 3 vext3 LHS, <1,5,4,5> + 3759375522U, // <3,1,5,5>: Cost 4 vext3 LHS, <1,5,5,7> + 3720417378U, // <3,1,5,6>: Cost 4 vext2 <4,u,3,1>, <5,6,7,0> + 2832518454U, // <3,1,5,7>: Cost 3 vuzpr <2,3,0,1>, RHS + 1611891901U, // <3,1,5,u>: Cost 2 vext3 LHS, <1,5,u,7> + 3763578048U, // <3,1,6,0>: Cost 4 vext3 LHS, <1,6,0,1> + 2689836239U, // <3,1,6,1>: Cost 3 vext3 LHS, <1,6,1,7> + 2732967128U, // <3,1,6,2>: Cost 3 vext3 LHS, <1,6,2,7> + 2685633761U, // <3,1,6,3>: Cost 3 vext3 LHS, <1,6,3,7> + 3763578088U, // <3,1,6,4>: Cost 4 vext3 LHS, <1,6,4,5> + 2689836275U, // <3,1,6,5>: Cost 3 vext3 LHS, <1,6,5,7> + 3763578108U, // <3,1,6,6>: Cost 4 vext3 LHS, <1,6,6,7> + 2732967166U, // <3,1,6,7>: Cost 3 vext3 LHS, <1,6,7,0> + 2685633806U, // <3,1,6,u>: Cost 3 vext3 LHS, <1,6,u,7> + 3631972454U, // <3,1,7,0>: Cost 4 vext1 <1,3,1,7>, LHS + 2659947612U, // <3,1,7,1>: Cost 3 vext2 <7,1,3,1>, <7,1,3,1> + 4036102294U, // <3,1,7,2>: Cost 4 vzipr <1,5,3,7>, <3,0,1,2> + 3095396454U, // <3,1,7,3>: Cost 3 vtrnr <1,3,5,7>, LHS + 3631975734U, // <3,1,7,4>: Cost 4 vext1 <1,3,1,7>, RHS + 2222982144U, // <3,1,7,5>: Cost 3 vrev <1,3,5,7> + 3296797705U, // <3,1,7,6>: Cost 4 vrev <1,3,6,7> + 3720418924U, // <3,1,7,7>: Cost 4 vext2 <4,u,3,1>, <7,7,7,7> + 3095396459U, // <3,1,7,u>: Cost 3 vtrnr <1,3,5,7>, LHS + 1484496998U, // <3,1,u,0>: Cost 2 vext1 <1,3,1,u>, LHS + 1611892077U, // <3,1,u,1>: Cost 2 vext3 LHS, <1,u,1,3> + 2685633907U, // <3,1,u,2>: Cost 3 vext3 LHS, <1,u,2,0> + 1611892092U, // <3,1,u,3>: Cost 2 vext3 LHS, <1,u,3,0> + 1484500278U, // <3,1,u,4>: Cost 2 vext1 <1,3,1,u>, RHS + 1611892117U, // <3,1,u,5>: Cost 2 vext3 LHS, <1,u,5,7> + 2685633950U, // <3,1,u,6>: Cost 3 vext3 LHS, <1,u,6,7> + 2832518697U, // <3,1,u,7>: Cost 3 vuzpr <2,3,0,1>, RHS + 1611892140U, // <3,1,u,u>: Cost 2 vext3 LHS, <1,u,u,3> + 2623455232U, // <3,2,0,0>: Cost 3 vext2 <1,0,3,2>, <0,0,0,0> + 1549713510U, // <3,2,0,1>: Cost 2 vext2 <1,0,3,2>, LHS + 2689836484U, // <3,2,0,2>: Cost 3 vext3 LHS, <2,0,2,0> + 2685633997U, // <3,2,0,3>: Cost 3 vext3 LHS, <2,0,3,0> + 2623455570U, // <3,2,0,4>: Cost 3 vext2 <1,0,3,2>, <0,4,1,5> + 2732967398U, // <3,2,0,5>: Cost 3 vext3 LHS, <2,0,5,7> + 2689836524U, // <3,2,0,6>: Cost 3 vext3 LHS, <2,0,6,4> + 2229044964U, // <3,2,0,7>: Cost 3 vrev <2,3,7,0> + 1549714077U, // <3,2,0,u>: Cost 2 vext2 <1,0,3,2>, LHS + 1549714166U, // <3,2,1,0>: Cost 2 vext2 <1,0,3,2>, <1,0,3,2> + 2623456052U, // <3,2,1,1>: Cost 3 vext2 <1,0,3,2>, <1,1,1,1> + 2623456150U, // <3,2,1,2>: Cost 3 vext2 <1,0,3,2>, <1,2,3,0> + 2685634079U, // <3,2,1,3>: Cost 3 vext3 LHS, <2,1,3,1> + 2552286518U, // <3,2,1,4>: Cost 3 vext1 <0,3,2,1>, RHS + 2623456400U, // <3,2,1,5>: Cost 3 vext2 <1,0,3,2>, <1,5,3,7> + 2689836604U, // <3,2,1,6>: Cost 3 vext3 LHS, <2,1,6,3> + 3667834101U, // <3,2,1,7>: Cost 4 vext1 <7,3,2,1>, <7,3,2,1> + 1155385070U, // <3,2,1,u>: Cost 2 vrev <2,3,u,1> + 2689836629U, // <3,2,2,0>: Cost 3 vext3 LHS, <2,2,0,1> + 2689836640U, // <3,2,2,1>: Cost 3 vext3 LHS, <2,2,1,3> + 1611449960U, // <3,2,2,2>: Cost 2 vext3 LHS, <2,2,2,2> + 1611892338U, // <3,2,2,3>: Cost 2 vext3 LHS, <2,2,3,3> + 2689836669U, // <3,2,2,4>: Cost 3 vext3 LHS, <2,2,4,5> + 2689836680U, // <3,2,2,5>: Cost 3 vext3 LHS, <2,2,5,7> + 2689836688U, // <3,2,2,6>: Cost 3 vext3 LHS, <2,2,6,6> + 3763578518U, // <3,2,2,7>: Cost 4 vext3 LHS, <2,2,7,3> + 1611892383U, // <3,2,2,u>: Cost 2 vext3 LHS, <2,2,u,3> + 1611450022U, // <3,2,3,0>: Cost 2 vext3 LHS, <2,3,0,1> + 2685191854U, // <3,2,3,1>: Cost 3 vext3 LHS, <2,3,1,0> + 2685191865U, // <3,2,3,2>: Cost 3 vext3 LHS, <2,3,2,2> + 2685191875U, // <3,2,3,3>: Cost 3 vext3 LHS, <2,3,3,3> + 1611450062U, // <3,2,3,4>: Cost 2 vext3 LHS, <2,3,4,5> + 2732967635U, // <3,2,3,5>: Cost 3 vext3 LHS, <2,3,5,1> + 2732967645U, // <3,2,3,6>: Cost 3 vext3 LHS, <2,3,6,2> + 2732967652U, // <3,2,3,7>: Cost 3 vext3 LHS, <2,3,7,0> + 1611450094U, // <3,2,3,u>: Cost 2 vext3 LHS, <2,3,u,1> + 2558279782U, // <3,2,4,0>: Cost 3 vext1 <1,3,2,4>, LHS + 2558280602U, // <3,2,4,1>: Cost 3 vext1 <1,3,2,4>, <1,2,3,4> + 2732967692U, // <3,2,4,2>: Cost 3 vext3 LHS, <2,4,2,4> + 2685634326U, // <3,2,4,3>: Cost 3 vext3 LHS, <2,4,3,5> + 2558283062U, // <3,2,4,4>: Cost 3 vext1 <1,3,2,4>, RHS + 1549716790U, // <3,2,4,5>: Cost 2 vext2 <1,0,3,2>, RHS + 2689836844U, // <3,2,4,6>: Cost 3 vext3 LHS, <2,4,6,0> + 2229077736U, // <3,2,4,7>: Cost 3 vrev <2,3,7,4> + 1549717033U, // <3,2,4,u>: Cost 2 vext2 <1,0,3,2>, RHS + 2552316006U, // <3,2,5,0>: Cost 3 vext1 <0,3,2,5>, LHS + 2228643507U, // <3,2,5,1>: Cost 3 vrev <2,3,1,5> + 2689836896U, // <3,2,5,2>: Cost 3 vext3 LHS, <2,5,2,7> + 2685634408U, // <3,2,5,3>: Cost 3 vext3 LHS, <2,5,3,6> + 1155122894U, // <3,2,5,4>: Cost 2 vrev <2,3,4,5> + 2665263108U, // <3,2,5,5>: Cost 3 vext2 , <5,5,5,5> + 2689836932U, // <3,2,5,6>: Cost 3 vext3 LHS, <2,5,6,7> + 2665263272U, // <3,2,5,7>: Cost 3 vext2 , <5,7,5,7> + 1155417842U, // <3,2,5,u>: Cost 2 vrev <2,3,u,5> + 2689836953U, // <3,2,6,0>: Cost 3 vext3 LHS, <2,6,0,1> + 2689836964U, // <3,2,6,1>: Cost 3 vext3 LHS, <2,6,1,3> + 2689836976U, // <3,2,6,2>: Cost 3 vext3 LHS, <2,6,2,6> + 1611892666U, // <3,2,6,3>: Cost 2 vext3 LHS, <2,6,3,7> + 2689836993U, // <3,2,6,4>: Cost 3 vext3 LHS, <2,6,4,5> + 2689837004U, // <3,2,6,5>: Cost 3 vext3 LHS, <2,6,5,7> + 2689837013U, // <3,2,6,6>: Cost 3 vext3 LHS, <2,6,6,7> + 2665263950U, // <3,2,6,7>: Cost 3 vext2 , <6,7,0,1> + 1611892711U, // <3,2,6,u>: Cost 2 vext3 LHS, <2,6,u,7> + 2665264122U, // <3,2,7,0>: Cost 3 vext2 , <7,0,1,2> + 2623460419U, // <3,2,7,1>: Cost 3 vext2 <1,0,3,2>, <7,1,0,3> + 4169138340U, // <3,2,7,2>: Cost 4 vtrnr <1,3,5,7>, <0,2,0,2> + 2962358374U, // <3,2,7,3>: Cost 3 vzipr <1,5,3,7>, LHS + 2665264486U, // <3,2,7,4>: Cost 3 vext2 , <7,4,5,6> + 2228954841U, // <3,2,7,5>: Cost 3 vrev <2,3,5,7> + 2229028578U, // <3,2,7,6>: Cost 3 vrev <2,3,6,7> + 2665264748U, // <3,2,7,7>: Cost 3 vext2 , <7,7,7,7> + 2962358379U, // <3,2,7,u>: Cost 3 vzipr <1,5,3,7>, LHS + 1611892795U, // <3,2,u,0>: Cost 2 vext3 LHS, <2,u,0,1> + 1549719342U, // <3,2,u,1>: Cost 2 vext2 <1,0,3,2>, LHS + 1611449960U, // <3,2,u,2>: Cost 2 vext3 LHS, <2,2,2,2> + 1611892824U, // <3,2,u,3>: Cost 2 vext3 LHS, <2,u,3,3> + 1611892835U, // <3,2,u,4>: Cost 2 vext3 LHS, <2,u,4,5> + 1549719706U, // <3,2,u,5>: Cost 2 vext2 <1,0,3,2>, RHS + 2689837168U, // <3,2,u,6>: Cost 3 vext3 LHS, <2,u,6,0> + 2665265408U, // <3,2,u,7>: Cost 3 vext2 , + 1611892867U, // <3,2,u,u>: Cost 2 vext3 LHS, <2,u,u,1> + 2685192331U, // <3,3,0,0>: Cost 3 vext3 LHS, <3,0,0,0> + 1611450518U, // <3,3,0,1>: Cost 2 vext3 LHS, <3,0,1,2> + 2685634717U, // <3,3,0,2>: Cost 3 vext3 LHS, <3,0,2,0> + 2564294806U, // <3,3,0,3>: Cost 3 vext1 <2,3,3,0>, <3,0,1,2> + 2685634736U, // <3,3,0,4>: Cost 3 vext3 LHS, <3,0,4,1> + 2732968122U, // <3,3,0,5>: Cost 3 vext3 LHS, <3,0,5,2> + 3763579075U, // <3,3,0,6>: Cost 4 vext3 LHS, <3,0,6,2> + 4034053264U, // <3,3,0,7>: Cost 4 vzipr <1,2,3,0>, <1,5,3,7> + 1611450581U, // <3,3,0,u>: Cost 2 vext3 LHS, <3,0,u,2> + 2685192415U, // <3,3,1,0>: Cost 3 vext3 LHS, <3,1,0,3> + 1550385992U, // <3,3,1,1>: Cost 2 vext2 <1,1,3,3>, <1,1,3,3> + 2685192433U, // <3,3,1,2>: Cost 3 vext3 LHS, <3,1,2,3> + 2685634808U, // <3,3,1,3>: Cost 3 vext3 LHS, <3,1,3,1> + 2558332214U, // <3,3,1,4>: Cost 3 vext1 <1,3,3,1>, RHS + 2685634828U, // <3,3,1,5>: Cost 3 vext3 LHS, <3,1,5,3> + 3759376661U, // <3,3,1,6>: Cost 4 vext3 LHS, <3,1,6,3> + 2703477022U, // <3,3,1,7>: Cost 3 vext3 <3,1,7,3>, <3,1,7,3> + 1555031423U, // <3,3,1,u>: Cost 2 vext2 <1,u,3,3>, <1,u,3,3> + 2564309094U, // <3,3,2,0>: Cost 3 vext1 <2,3,3,2>, LHS + 2630100513U, // <3,3,2,1>: Cost 3 vext2 <2,1,3,3>, <2,1,3,3> + 1557022322U, // <3,3,2,2>: Cost 2 vext2 <2,2,3,3>, <2,2,3,3> + 2685192520U, // <3,3,2,3>: Cost 3 vext3 LHS, <3,2,3,0> + 2564312374U, // <3,3,2,4>: Cost 3 vext1 <2,3,3,2>, RHS + 2732968286U, // <3,3,2,5>: Cost 3 vext3 LHS, <3,2,5,4> + 2685634918U, // <3,3,2,6>: Cost 3 vext3 LHS, <3,2,6,3> + 2704140655U, // <3,3,2,7>: Cost 3 vext3 <3,2,7,3>, <3,2,7,3> + 1561004120U, // <3,3,2,u>: Cost 2 vext2 <2,u,3,3>, <2,u,3,3> + 1496547430U, // <3,3,3,0>: Cost 2 vext1 <3,3,3,3>, LHS + 2624129256U, // <3,3,3,1>: Cost 3 vext2 <1,1,3,3>, <3,1,1,3> + 2630764866U, // <3,3,3,2>: Cost 3 vext2 <2,2,3,3>, <3,2,2,3> + 336380006U, // <3,3,3,3>: Cost 1 vdup3 LHS + 1496550710U, // <3,3,3,4>: Cost 2 vext1 <3,3,3,3>, RHS + 2732968368U, // <3,3,3,5>: Cost 3 vext3 LHS, <3,3,5,5> + 2624129683U, // <3,3,3,6>: Cost 3 vext2 <1,1,3,3>, <3,6,3,7> + 2594182400U, // <3,3,3,7>: Cost 3 vext1 <7,3,3,3>, <7,3,3,3> + 336380006U, // <3,3,3,u>: Cost 1 vdup3 LHS + 2558353510U, // <3,3,4,0>: Cost 3 vext1 <1,3,3,4>, LHS + 2558354411U, // <3,3,4,1>: Cost 3 vext1 <1,3,3,4>, <1,3,3,4> + 2564327108U, // <3,3,4,2>: Cost 3 vext1 <2,3,3,4>, <2,3,3,4> + 2564327938U, // <3,3,4,3>: Cost 3 vext1 <2,3,3,4>, <3,4,5,6> + 2960343962U, // <3,3,4,4>: Cost 3 vzipr <1,2,3,4>, <1,2,3,4> + 1611893250U, // <3,3,4,5>: Cost 2 vext3 LHS, <3,4,5,6> + 2771619126U, // <3,3,4,6>: Cost 3 vuzpl <3,3,3,3>, RHS + 4034086032U, // <3,3,4,7>: Cost 4 vzipr <1,2,3,4>, <1,5,3,7> + 1611893277U, // <3,3,4,u>: Cost 2 vext3 LHS, <3,4,u,6> + 2558361702U, // <3,3,5,0>: Cost 3 vext1 <1,3,3,5>, LHS + 2558362604U, // <3,3,5,1>: Cost 3 vext1 <1,3,3,5>, <1,3,3,5> + 2558363342U, // <3,3,5,2>: Cost 3 vext1 <1,3,3,5>, <2,3,4,5> + 2732968512U, // <3,3,5,3>: Cost 3 vext3 LHS, <3,5,3,5> + 2558364982U, // <3,3,5,4>: Cost 3 vext1 <1,3,3,5>, RHS + 3101279950U, // <3,3,5,5>: Cost 3 vtrnr <2,3,4,5>, <2,3,4,5> + 2665934946U, // <3,3,5,6>: Cost 3 vext2 , <5,6,7,0> + 2826636598U, // <3,3,5,7>: Cost 3 vuzpr <1,3,1,3>, RHS + 2826636599U, // <3,3,5,u>: Cost 3 vuzpr <1,3,1,3>, RHS + 2732968568U, // <3,3,6,0>: Cost 3 vext3 LHS, <3,6,0,7> + 3763579521U, // <3,3,6,1>: Cost 4 vext3 LHS, <3,6,1,7> + 2732968586U, // <3,3,6,2>: Cost 3 vext3 LHS, <3,6,2,7> + 2732968595U, // <3,3,6,3>: Cost 3 vext3 LHS, <3,6,3,7> + 2732968604U, // <3,3,6,4>: Cost 3 vext3 LHS, <3,6,4,7> + 3763579557U, // <3,3,6,5>: Cost 4 vext3 LHS, <3,6,5,7> + 2732968621U, // <3,3,6,6>: Cost 3 vext3 LHS, <3,6,6,6> + 2657973099U, // <3,3,6,7>: Cost 3 vext2 <6,7,3,3>, <6,7,3,3> + 2658636732U, // <3,3,6,u>: Cost 3 vext2 <6,u,3,3>, <6,u,3,3> + 2558378086U, // <3,3,7,0>: Cost 3 vext1 <1,3,3,7>, LHS + 2558378990U, // <3,3,7,1>: Cost 3 vext1 <1,3,3,7>, <1,3,3,7> + 2564351687U, // <3,3,7,2>: Cost 3 vext1 <2,3,3,7>, <2,3,3,7> + 2661291264U, // <3,3,7,3>: Cost 3 vext2 <7,3,3,3>, <7,3,3,3> + 2558381366U, // <3,3,7,4>: Cost 3 vext1 <1,3,3,7>, RHS + 2732968694U, // <3,3,7,5>: Cost 3 vext3 LHS, <3,7,5,7> + 3781126907U, // <3,3,7,6>: Cost 4 vext3 <3,7,6,3>, <3,7,6,3> + 3095397376U, // <3,3,7,7>: Cost 3 vtrnr <1,3,5,7>, <1,3,5,7> + 2558383918U, // <3,3,7,u>: Cost 3 vext1 <1,3,3,7>, LHS + 1496547430U, // <3,3,u,0>: Cost 2 vext1 <3,3,3,3>, LHS + 1611893534U, // <3,3,u,1>: Cost 2 vext3 LHS, <3,u,1,2> + 1592858504U, // <3,3,u,2>: Cost 2 vext2 , + 336380006U, // <3,3,u,3>: Cost 1 vdup3 LHS + 1496550710U, // <3,3,u,4>: Cost 2 vext1 <3,3,3,3>, RHS + 1611893574U, // <3,3,u,5>: Cost 2 vext3 LHS, <3,u,5,6> + 2690280268U, // <3,3,u,6>: Cost 3 vext3 LHS, <3,u,6,3> + 2826636841U, // <3,3,u,7>: Cost 3 vuzpr <1,3,1,3>, RHS + 336380006U, // <3,3,u,u>: Cost 1 vdup3 LHS + 2624798720U, // <3,4,0,0>: Cost 3 vext2 <1,2,3,4>, <0,0,0,0> + 1551056998U, // <3,4,0,1>: Cost 2 vext2 <1,2,3,4>, LHS + 2624798884U, // <3,4,0,2>: Cost 3 vext2 <1,2,3,4>, <0,2,0,2> + 3693232384U, // <3,4,0,3>: Cost 4 vext2 <0,3,3,4>, <0,3,1,4> + 2624799058U, // <3,4,0,4>: Cost 3 vext2 <1,2,3,4>, <0,4,1,5> + 1659227026U, // <3,4,0,5>: Cost 2 vext3 LHS, <4,0,5,1> + 1659227036U, // <3,4,0,6>: Cost 2 vext3 LHS, <4,0,6,2> + 3667973382U, // <3,4,0,7>: Cost 4 vext1 <7,3,4,0>, <7,3,4,0> + 1551057565U, // <3,4,0,u>: Cost 2 vext2 <1,2,3,4>, LHS + 2624799478U, // <3,4,1,0>: Cost 3 vext2 <1,2,3,4>, <1,0,3,2> + 2624799540U, // <3,4,1,1>: Cost 3 vext2 <1,2,3,4>, <1,1,1,1> + 1551057818U, // <3,4,1,2>: Cost 2 vext2 <1,2,3,4>, <1,2,3,4> + 2624799704U, // <3,4,1,3>: Cost 3 vext2 <1,2,3,4>, <1,3,1,3> + 2564377910U, // <3,4,1,4>: Cost 3 vext1 <2,3,4,1>, RHS + 2689838050U, // <3,4,1,5>: Cost 3 vext3 LHS, <4,1,5,0> + 2689838062U, // <3,4,1,6>: Cost 3 vext3 LHS, <4,1,6,3> + 2628117807U, // <3,4,1,7>: Cost 3 vext2 <1,7,3,4>, <1,7,3,4> + 1555039616U, // <3,4,1,u>: Cost 2 vext2 <1,u,3,4>, <1,u,3,4> + 3626180710U, // <3,4,2,0>: Cost 4 vext1 <0,3,4,2>, LHS + 2624800298U, // <3,4,2,1>: Cost 3 vext2 <1,2,3,4>, <2,1,4,3> + 2624800360U, // <3,4,2,2>: Cost 3 vext2 <1,2,3,4>, <2,2,2,2> + 2624800422U, // <3,4,2,3>: Cost 3 vext2 <1,2,3,4>, <2,3,0,1> + 2624800514U, // <3,4,2,4>: Cost 3 vext2 <1,2,3,4>, <2,4,1,3> + 2709965878U, // <3,4,2,5>: Cost 3 vext3 <4,2,5,3>, <4,2,5,3> + 2689838140U, // <3,4,2,6>: Cost 3 vext3 LHS, <4,2,6,0> + 2634090504U, // <3,4,2,7>: Cost 3 vext2 <2,7,3,4>, <2,7,3,4> + 2689838158U, // <3,4,2,u>: Cost 3 vext3 LHS, <4,2,u,0> + 2624800918U, // <3,4,3,0>: Cost 3 vext2 <1,2,3,4>, <3,0,1,2> + 2636081403U, // <3,4,3,1>: Cost 3 vext2 <3,1,3,4>, <3,1,3,4> + 2636745036U, // <3,4,3,2>: Cost 3 vext2 <3,2,3,4>, <3,2,3,4> + 2624801180U, // <3,4,3,3>: Cost 3 vext2 <1,2,3,4>, <3,3,3,3> + 2624801232U, // <3,4,3,4>: Cost 3 vext2 <1,2,3,4>, <3,4,0,1> + 2905836854U, // <3,4,3,5>: Cost 3 vzipl <3,3,3,3>, RHS + 3040054582U, // <3,4,3,6>: Cost 3 vtrnl <3,3,3,3>, RHS + 3702524611U, // <3,4,3,7>: Cost 4 vext2 <1,u,3,4>, <3,7,0,1> + 2624801566U, // <3,4,3,u>: Cost 3 vext2 <1,2,3,4>, <3,u,1,2> + 2564399206U, // <3,4,4,0>: Cost 3 vext1 <2,3,4,4>, LHS + 2564400026U, // <3,4,4,1>: Cost 3 vext1 <2,3,4,4>, <1,2,3,4> + 2564400845U, // <3,4,4,2>: Cost 3 vext1 <2,3,4,4>, <2,3,4,4> + 2570373542U, // <3,4,4,3>: Cost 3 vext1 <3,3,4,4>, <3,3,4,4> + 1659227344U, // <3,4,4,4>: Cost 2 vext3 LHS, <4,4,4,4> + 1551060278U, // <3,4,4,5>: Cost 2 vext2 <1,2,3,4>, RHS + 1659227364U, // <3,4,4,6>: Cost 2 vext3 LHS, <4,4,6,6> + 3668006154U, // <3,4,4,7>: Cost 4 vext1 <7,3,4,4>, <7,3,4,4> + 1551060521U, // <3,4,4,u>: Cost 2 vext2 <1,2,3,4>, RHS + 1490665574U, // <3,4,5,0>: Cost 2 vext1 <2,3,4,5>, LHS + 2689838341U, // <3,4,5,1>: Cost 3 vext3 LHS, <4,5,1,3> + 1490667214U, // <3,4,5,2>: Cost 2 vext1 <2,3,4,5>, <2,3,4,5> + 2564409494U, // <3,4,5,3>: Cost 3 vext1 <2,3,4,5>, <3,0,1,2> + 1490668854U, // <3,4,5,4>: Cost 2 vext1 <2,3,4,5>, RHS + 2689838381U, // <3,4,5,5>: Cost 3 vext3 LHS, <4,5,5,7> + 537709878U, // <3,4,5,6>: Cost 1 vext3 LHS, RHS + 2594272523U, // <3,4,5,7>: Cost 3 vext1 <7,3,4,5>, <7,3,4,5> + 537709896U, // <3,4,5,u>: Cost 1 vext3 LHS, RHS + 2689838411U, // <3,4,6,0>: Cost 3 vext3 LHS, <4,6,0,1> + 2558444534U, // <3,4,6,1>: Cost 3 vext1 <1,3,4,6>, <1,3,4,6> + 2666607098U, // <3,4,6,2>: Cost 3 vext2 , <6,2,7,3> + 2558446082U, // <3,4,6,3>: Cost 3 vext1 <1,3,4,6>, <3,4,5,6> + 1659227508U, // <3,4,6,4>: Cost 2 vext3 LHS, <4,6,4,6> + 2689838462U, // <3,4,6,5>: Cost 3 vext3 LHS, <4,6,5,7> + 2689838471U, // <3,4,6,6>: Cost 3 vext3 LHS, <4,6,6,7> + 2657981292U, // <3,4,6,7>: Cost 3 vext2 <6,7,3,4>, <6,7,3,4> + 1659227540U, // <3,4,6,u>: Cost 2 vext3 LHS, <4,6,u,2> + 2666607610U, // <3,4,7,0>: Cost 3 vext2 , <7,0,1,2> + 3702527072U, // <3,4,7,1>: Cost 4 vext2 <1,u,3,4>, <7,1,3,5> + 2660635824U, // <3,4,7,2>: Cost 3 vext2 <7,2,3,4>, <7,2,3,4> + 3644139945U, // <3,4,7,3>: Cost 4 vext1 <3,3,4,7>, <3,3,4,7> + 2666607974U, // <3,4,7,4>: Cost 3 vext2 , <7,4,5,6> + 2732969416U, // <3,4,7,5>: Cost 3 vext3 LHS, <4,7,5,0> + 2732969425U, // <3,4,7,6>: Cost 3 vext3 LHS, <4,7,6,0> + 2666608236U, // <3,4,7,7>: Cost 3 vext2 , <7,7,7,7> + 2664617622U, // <3,4,7,u>: Cost 3 vext2 <7,u,3,4>, <7,u,3,4> + 1490690150U, // <3,4,u,0>: Cost 2 vext1 <2,3,4,u>, LHS + 1551062830U, // <3,4,u,1>: Cost 2 vext2 <1,2,3,4>, LHS + 1490691793U, // <3,4,u,2>: Cost 2 vext1 <2,3,4,u>, <2,3,4,u> + 2624804796U, // <3,4,u,3>: Cost 3 vext2 <1,2,3,4>, + 1490693430U, // <3,4,u,4>: Cost 2 vext1 <2,3,4,u>, RHS + 1551063194U, // <3,4,u,5>: Cost 2 vext2 <1,2,3,4>, RHS + 537710121U, // <3,4,u,6>: Cost 1 vext3 LHS, RHS + 2594297102U, // <3,4,u,7>: Cost 3 vext1 <7,3,4,u>, <7,3,4,u> + 537710139U, // <3,4,u,u>: Cost 1 vext3 LHS, RHS + 3692576768U, // <3,5,0,0>: Cost 4 vext2 <0,2,3,5>, <0,0,0,0> + 2618835046U, // <3,5,0,1>: Cost 3 vext2 <0,2,3,5>, LHS + 2618835138U, // <3,5,0,2>: Cost 3 vext2 <0,2,3,5>, <0,2,3,5> + 3692577024U, // <3,5,0,3>: Cost 4 vext2 <0,2,3,5>, <0,3,1,4> + 2689838690U, // <3,5,0,4>: Cost 3 vext3 LHS, <5,0,4,1> + 2732969579U, // <3,5,0,5>: Cost 3 vext3 LHS, <5,0,5,1> + 2732969588U, // <3,5,0,6>: Cost 3 vext3 LHS, <5,0,6,1> + 2246963055U, // <3,5,0,7>: Cost 3 vrev <5,3,7,0> + 2618835613U, // <3,5,0,u>: Cost 3 vext2 <0,2,3,5>, LHS + 2594308198U, // <3,5,1,0>: Cost 3 vext1 <7,3,5,1>, LHS + 3692577588U, // <3,5,1,1>: Cost 4 vext2 <0,2,3,5>, <1,1,1,1> + 2624807835U, // <3,5,1,2>: Cost 3 vext2 <1,2,3,5>, <1,2,3,5> + 2625471468U, // <3,5,1,3>: Cost 3 vext2 <1,3,3,5>, <1,3,3,5> + 2626135101U, // <3,5,1,4>: Cost 3 vext2 <1,4,3,5>, <1,4,3,5> + 2594311888U, // <3,5,1,5>: Cost 3 vext1 <7,3,5,1>, <5,1,7,3> + 3699877107U, // <3,5,1,6>: Cost 4 vext2 <1,4,3,5>, <1,6,5,7> + 1641680592U, // <3,5,1,7>: Cost 2 vext3 <5,1,7,3>, <5,1,7,3> + 1641754329U, // <3,5,1,u>: Cost 2 vext3 <5,1,u,3>, <5,1,u,3> + 3692578274U, // <3,5,2,0>: Cost 4 vext2 <0,2,3,5>, <2,0,5,3> + 2630116899U, // <3,5,2,1>: Cost 3 vext2 <2,1,3,5>, <2,1,3,5> + 3692578408U, // <3,5,2,2>: Cost 4 vext2 <0,2,3,5>, <2,2,2,2> + 2625472206U, // <3,5,2,3>: Cost 3 vext2 <1,3,3,5>, <2,3,4,5> + 2632107798U, // <3,5,2,4>: Cost 3 vext2 <2,4,3,5>, <2,4,3,5> + 2715938575U, // <3,5,2,5>: Cost 3 vext3 <5,2,5,3>, <5,2,5,3> + 3692578746U, // <3,5,2,6>: Cost 4 vext2 <0,2,3,5>, <2,6,3,7> + 2716086049U, // <3,5,2,7>: Cost 3 vext3 <5,2,7,3>, <5,2,7,3> + 2634762330U, // <3,5,2,u>: Cost 3 vext2 <2,u,3,5>, <2,u,3,5> + 3692578966U, // <3,5,3,0>: Cost 4 vext2 <0,2,3,5>, <3,0,1,2> + 2636089596U, // <3,5,3,1>: Cost 3 vext2 <3,1,3,5>, <3,1,3,5> + 3699214668U, // <3,5,3,2>: Cost 4 vext2 <1,3,3,5>, <3,2,3,4> + 2638080412U, // <3,5,3,3>: Cost 3 vext2 <3,4,3,5>, <3,3,3,3> + 2618837506U, // <3,5,3,4>: Cost 3 vext2 <0,2,3,5>, <3,4,5,6> + 2832844494U, // <3,5,3,5>: Cost 3 vuzpr <2,3,4,5>, <2,3,4,5> + 4033415682U, // <3,5,3,6>: Cost 4 vzipr <1,1,3,3>, <3,4,5,6> + 3095072054U, // <3,5,3,7>: Cost 3 vtrnr <1,3,1,3>, RHS + 3095072055U, // <3,5,3,u>: Cost 3 vtrnr <1,3,1,3>, RHS + 2600304742U, // <3,5,4,0>: Cost 3 vext1 , LHS + 3763580815U, // <3,5,4,1>: Cost 4 vext3 LHS, <5,4,1,5> + 2564474582U, // <3,5,4,2>: Cost 3 vext1 <2,3,5,4>, <2,3,5,4> + 3699879044U, // <3,5,4,3>: Cost 4 vext2 <1,4,3,5>, <4,3,5,0> + 2600308022U, // <3,5,4,4>: Cost 3 vext1 , RHS + 2618838326U, // <3,5,4,5>: Cost 3 vext2 <0,2,3,5>, RHS + 2772454710U, // <3,5,4,6>: Cost 3 vuzpl <3,4,5,6>, RHS + 1659228102U, // <3,5,4,7>: Cost 2 vext3 LHS, <5,4,7,6> + 1659228111U, // <3,5,4,u>: Cost 2 vext3 LHS, <5,4,u,6> + 2570453094U, // <3,5,5,0>: Cost 3 vext1 <3,3,5,5>, LHS + 2624810704U, // <3,5,5,1>: Cost 3 vext2 <1,2,3,5>, <5,1,7,3> + 2570454734U, // <3,5,5,2>: Cost 3 vext1 <3,3,5,5>, <2,3,4,5> + 2570455472U, // <3,5,5,3>: Cost 3 vext1 <3,3,5,5>, <3,3,5,5> + 2570456374U, // <3,5,5,4>: Cost 3 vext1 <3,3,5,5>, RHS + 1659228164U, // <3,5,5,5>: Cost 2 vext3 LHS, <5,5,5,5> + 2732969998U, // <3,5,5,6>: Cost 3 vext3 LHS, <5,5,6,6> + 1659228184U, // <3,5,5,7>: Cost 2 vext3 LHS, <5,5,7,7> + 1659228193U, // <3,5,5,u>: Cost 2 vext3 LHS, <5,5,u,7> + 2732970020U, // <3,5,6,0>: Cost 3 vext3 LHS, <5,6,0,1> + 2732970035U, // <3,5,6,1>: Cost 3 vext3 LHS, <5,6,1,7> + 2564490968U, // <3,5,6,2>: Cost 3 vext1 <2,3,5,6>, <2,3,5,6> + 2732970050U, // <3,5,6,3>: Cost 3 vext3 LHS, <5,6,3,4> + 2732970060U, // <3,5,6,4>: Cost 3 vext3 LHS, <5,6,4,5> + 2732970071U, // <3,5,6,5>: Cost 3 vext3 LHS, <5,6,5,7> + 2732970080U, // <3,5,6,6>: Cost 3 vext3 LHS, <5,6,6,7> + 1659228258U, // <3,5,6,7>: Cost 2 vext3 LHS, <5,6,7,0> + 1659228267U, // <3,5,6,u>: Cost 2 vext3 LHS, <5,6,u,0> + 1484783718U, // <3,5,7,0>: Cost 2 vext1 <1,3,5,7>, LHS + 1484784640U, // <3,5,7,1>: Cost 2 vext1 <1,3,5,7>, <1,3,5,7> + 2558527080U, // <3,5,7,2>: Cost 3 vext1 <1,3,5,7>, <2,2,2,2> + 2558527638U, // <3,5,7,3>: Cost 3 vext1 <1,3,5,7>, <3,0,1,2> + 1484786998U, // <3,5,7,4>: Cost 2 vext1 <1,3,5,7>, RHS + 1659228328U, // <3,5,7,5>: Cost 2 vext3 LHS, <5,7,5,7> + 2732970154U, // <3,5,7,6>: Cost 3 vext3 LHS, <5,7,6,0> + 2558531180U, // <3,5,7,7>: Cost 3 vext1 <1,3,5,7>, <7,7,7,7> + 1484789550U, // <3,5,7,u>: Cost 2 vext1 <1,3,5,7>, LHS + 1484791910U, // <3,5,u,0>: Cost 2 vext1 <1,3,5,u>, LHS + 1484792833U, // <3,5,u,1>: Cost 2 vext1 <1,3,5,u>, <1,3,5,u> + 2558535272U, // <3,5,u,2>: Cost 3 vext1 <1,3,5,u>, <2,2,2,2> + 2558535830U, // <3,5,u,3>: Cost 3 vext1 <1,3,5,u>, <3,0,1,2> + 1484795190U, // <3,5,u,4>: Cost 2 vext1 <1,3,5,u>, RHS + 1659228409U, // <3,5,u,5>: Cost 2 vext3 LHS, <5,u,5,7> + 2772457626U, // <3,5,u,6>: Cost 3 vuzpl <3,4,5,6>, RHS + 1646326023U, // <3,5,u,7>: Cost 2 vext3 <5,u,7,3>, <5,u,7,3> + 1484797742U, // <3,5,u,u>: Cost 2 vext1 <1,3,5,u>, LHS + 2558541926U, // <3,6,0,0>: Cost 3 vext1 <1,3,6,0>, LHS + 2689839393U, // <3,6,0,1>: Cost 3 vext3 LHS, <6,0,1,2> + 2689839404U, // <3,6,0,2>: Cost 3 vext3 LHS, <6,0,2,4> + 3706519808U, // <3,6,0,3>: Cost 4 vext2 <2,5,3,6>, <0,3,1,4> + 2689839420U, // <3,6,0,4>: Cost 3 vext3 LHS, <6,0,4,2> + 2732970314U, // <3,6,0,5>: Cost 3 vext3 LHS, <6,0,5,7> + 2732970316U, // <3,6,0,6>: Cost 3 vext3 LHS, <6,0,6,0> + 2960313654U, // <3,6,0,7>: Cost 3 vzipr <1,2,3,0>, RHS + 2689839456U, // <3,6,0,u>: Cost 3 vext3 LHS, <6,0,u,2> + 3763581290U, // <3,6,1,0>: Cost 4 vext3 LHS, <6,1,0,3> + 3763581297U, // <3,6,1,1>: Cost 4 vext3 LHS, <6,1,1,1> + 2624816028U, // <3,6,1,2>: Cost 3 vext2 <1,2,3,6>, <1,2,3,6> + 3763581315U, // <3,6,1,3>: Cost 4 vext3 LHS, <6,1,3,1> + 2626143294U, // <3,6,1,4>: Cost 3 vext2 <1,4,3,6>, <1,4,3,6> + 3763581335U, // <3,6,1,5>: Cost 4 vext3 LHS, <6,1,5,3> + 2721321376U, // <3,6,1,6>: Cost 3 vext3 <6,1,6,3>, <6,1,6,3> + 2721395113U, // <3,6,1,7>: Cost 3 vext3 <6,1,7,3>, <6,1,7,3> + 2628797826U, // <3,6,1,u>: Cost 3 vext2 <1,u,3,6>, <1,u,3,6> + 2594390118U, // <3,6,2,0>: Cost 3 vext1 <7,3,6,2>, LHS + 2721616324U, // <3,6,2,1>: Cost 3 vext3 <6,2,1,3>, <6,2,1,3> + 2630788725U, // <3,6,2,2>: Cost 3 vext2 <2,2,3,6>, <2,2,3,6> + 3763581395U, // <3,6,2,3>: Cost 4 vext3 LHS, <6,2,3,0> + 2632115991U, // <3,6,2,4>: Cost 3 vext2 <2,4,3,6>, <2,4,3,6> + 2632779624U, // <3,6,2,5>: Cost 3 vext2 <2,5,3,6>, <2,5,3,6> + 2594394618U, // <3,6,2,6>: Cost 3 vext1 <7,3,6,2>, <6,2,7,3> + 1648316922U, // <3,6,2,7>: Cost 2 vext3 <6,2,7,3>, <6,2,7,3> + 1648390659U, // <3,6,2,u>: Cost 2 vext3 <6,2,u,3>, <6,2,u,3> + 3693914262U, // <3,6,3,0>: Cost 4 vext2 <0,4,3,6>, <3,0,1,2> + 3638281176U, // <3,6,3,1>: Cost 4 vext1 <2,3,6,3>, <1,3,1,3> + 3696568678U, // <3,6,3,2>: Cost 4 vext2 <0,u,3,6>, <3,2,6,3> + 2638088604U, // <3,6,3,3>: Cost 3 vext2 <3,4,3,6>, <3,3,3,3> + 2632780290U, // <3,6,3,4>: Cost 3 vext2 <2,5,3,6>, <3,4,5,6> + 3712494145U, // <3,6,3,5>: Cost 4 vext2 <3,5,3,6>, <3,5,3,6> + 3698559612U, // <3,6,3,6>: Cost 4 vext2 <1,2,3,6>, <3,6,1,2> + 2959674678U, // <3,6,3,7>: Cost 3 vzipr <1,1,3,3>, RHS + 2959674679U, // <3,6,3,u>: Cost 3 vzipr <1,1,3,3>, RHS + 3763581536U, // <3,6,4,0>: Cost 4 vext3 LHS, <6,4,0,6> + 2722943590U, // <3,6,4,1>: Cost 3 vext3 <6,4,1,3>, <6,4,1,3> + 2732970609U, // <3,6,4,2>: Cost 3 vext3 LHS, <6,4,2,5> + 3698560147U, // <3,6,4,3>: Cost 4 vext2 <1,2,3,6>, <4,3,6,6> + 2732970628U, // <3,6,4,4>: Cost 3 vext3 LHS, <6,4,4,6> + 2689839757U, // <3,6,4,5>: Cost 3 vext3 LHS, <6,4,5,6> + 2732970640U, // <3,6,4,6>: Cost 3 vext3 LHS, <6,4,6,0> + 2960346422U, // <3,6,4,7>: Cost 3 vzipr <1,2,3,4>, RHS + 2689839784U, // <3,6,4,u>: Cost 3 vext3 LHS, <6,4,u,6> + 2576498790U, // <3,6,5,0>: Cost 3 vext1 <4,3,6,5>, LHS + 3650241270U, // <3,6,5,1>: Cost 4 vext1 <4,3,6,5>, <1,0,3,2> + 2732970692U, // <3,6,5,2>: Cost 3 vext3 LHS, <6,5,2,7> + 2576501250U, // <3,6,5,3>: Cost 3 vext1 <4,3,6,5>, <3,4,5,6> + 2576501906U, // <3,6,5,4>: Cost 3 vext1 <4,3,6,5>, <4,3,6,5> + 3650244622U, // <3,6,5,5>: Cost 4 vext1 <4,3,6,5>, <5,5,6,6> + 4114633528U, // <3,6,5,6>: Cost 4 vtrnl <3,4,5,6>, <6,6,6,6> + 2732970735U, // <3,6,5,7>: Cost 3 vext3 LHS, <6,5,7,5> + 2576504622U, // <3,6,5,u>: Cost 3 vext1 <4,3,6,5>, LHS + 2732970749U, // <3,6,6,0>: Cost 3 vext3 LHS, <6,6,0,1> + 2724270856U, // <3,6,6,1>: Cost 3 vext3 <6,6,1,3>, <6,6,1,3> + 2624819706U, // <3,6,6,2>: Cost 3 vext2 <1,2,3,6>, <6,2,7,3> + 3656223234U, // <3,6,6,3>: Cost 4 vext1 <5,3,6,6>, <3,4,5,6> + 2732970788U, // <3,6,6,4>: Cost 3 vext3 LHS, <6,6,4,4> + 2732970800U, // <3,6,6,5>: Cost 3 vext3 LHS, <6,6,5,7> + 1659228984U, // <3,6,6,6>: Cost 2 vext3 LHS, <6,6,6,6> + 1659228994U, // <3,6,6,7>: Cost 2 vext3 LHS, <6,6,7,7> + 1659229003U, // <3,6,6,u>: Cost 2 vext3 LHS, <6,6,u,7> + 1659229006U, // <3,6,7,0>: Cost 2 vext3 LHS, <6,7,0,1> + 2558600201U, // <3,6,7,1>: Cost 3 vext1 <1,3,6,7>, <1,3,6,7> + 2558601146U, // <3,6,7,2>: Cost 3 vext1 <1,3,6,7>, <2,6,3,7> + 2725081963U, // <3,6,7,3>: Cost 3 vext3 <6,7,3,3>, <6,7,3,3> + 1659229046U, // <3,6,7,4>: Cost 2 vext3 LHS, <6,7,4,5> + 2715423611U, // <3,6,7,5>: Cost 3 vext3 <5,1,7,3>, <6,7,5,1> + 2722059141U, // <3,6,7,6>: Cost 3 vext3 <6,2,7,3>, <6,7,6,2> + 2962361654U, // <3,6,7,7>: Cost 3 vzipr <1,5,3,7>, RHS + 1659229078U, // <3,6,7,u>: Cost 2 vext3 LHS, <6,7,u,1> + 1659229087U, // <3,6,u,0>: Cost 2 vext3 LHS, <6,u,0,1> + 2689840041U, // <3,6,u,1>: Cost 3 vext3 LHS, <6,u,1,2> + 2558609339U, // <3,6,u,2>: Cost 3 vext1 <1,3,6,u>, <2,6,3,u> + 2576525853U, // <3,6,u,3>: Cost 3 vext1 <4,3,6,u>, <3,4,u,6> + 1659229127U, // <3,6,u,4>: Cost 2 vext3 LHS, <6,u,4,5> + 2689840081U, // <3,6,u,5>: Cost 3 vext3 LHS, <6,u,5,6> + 1659228984U, // <3,6,u,6>: Cost 2 vext3 LHS, <6,6,6,6> + 1652298720U, // <3,6,u,7>: Cost 2 vext3 <6,u,7,3>, <6,u,7,3> + 1659229159U, // <3,6,u,u>: Cost 2 vext3 LHS, <6,u,u,1> + 2626813952U, // <3,7,0,0>: Cost 3 vext2 <1,5,3,7>, <0,0,0,0> + 1553072230U, // <3,7,0,1>: Cost 2 vext2 <1,5,3,7>, LHS + 2626814116U, // <3,7,0,2>: Cost 3 vext2 <1,5,3,7>, <0,2,0,2> + 3700556028U, // <3,7,0,3>: Cost 4 vext2 <1,5,3,7>, <0,3,1,0> + 2626814290U, // <3,7,0,4>: Cost 3 vext2 <1,5,3,7>, <0,4,1,5> + 2582507375U, // <3,7,0,5>: Cost 3 vext1 <5,3,7,0>, <5,3,7,0> + 2588480072U, // <3,7,0,6>: Cost 3 vext1 <6,3,7,0>, <6,3,7,0> + 2732971055U, // <3,7,0,7>: Cost 3 vext3 LHS, <7,0,7,1> + 1553072797U, // <3,7,0,u>: Cost 2 vext2 <1,5,3,7>, LHS + 2626814710U, // <3,7,1,0>: Cost 3 vext2 <1,5,3,7>, <1,0,3,2> + 2626814772U, // <3,7,1,1>: Cost 3 vext2 <1,5,3,7>, <1,1,1,1> + 2626814870U, // <3,7,1,2>: Cost 3 vext2 <1,5,3,7>, <1,2,3,0> + 2625487854U, // <3,7,1,3>: Cost 3 vext2 <1,3,3,7>, <1,3,3,7> + 2582514998U, // <3,7,1,4>: Cost 3 vext1 <5,3,7,1>, RHS + 1553073296U, // <3,7,1,5>: Cost 2 vext2 <1,5,3,7>, <1,5,3,7> + 2627478753U, // <3,7,1,6>: Cost 3 vext2 <1,6,3,7>, <1,6,3,7> + 2727367810U, // <3,7,1,7>: Cost 3 vext3 <7,1,7,3>, <7,1,7,3> + 1555064195U, // <3,7,1,u>: Cost 2 vext2 <1,u,3,7>, <1,u,3,7> + 2588491878U, // <3,7,2,0>: Cost 3 vext1 <6,3,7,2>, LHS + 3700557318U, // <3,7,2,1>: Cost 4 vext2 <1,5,3,7>, <2,1,0,3> + 2626815592U, // <3,7,2,2>: Cost 3 vext2 <1,5,3,7>, <2,2,2,2> + 2626815654U, // <3,7,2,3>: Cost 3 vext2 <1,5,3,7>, <2,3,0,1> + 2588495158U, // <3,7,2,4>: Cost 3 vext1 <6,3,7,2>, RHS + 2632787817U, // <3,7,2,5>: Cost 3 vext2 <2,5,3,7>, <2,5,3,7> + 1559709626U, // <3,7,2,6>: Cost 2 vext2 <2,6,3,7>, <2,6,3,7> + 2728031443U, // <3,7,2,7>: Cost 3 vext3 <7,2,7,3>, <7,2,7,3> + 1561036892U, // <3,7,2,u>: Cost 2 vext2 <2,u,3,7>, <2,u,3,7> + 2626816150U, // <3,7,3,0>: Cost 3 vext2 <1,5,3,7>, <3,0,1,2> + 2626816268U, // <3,7,3,1>: Cost 3 vext2 <1,5,3,7>, <3,1,5,3> + 2633451878U, // <3,7,3,2>: Cost 3 vext2 <2,6,3,7>, <3,2,6,3> + 2626816412U, // <3,7,3,3>: Cost 3 vext2 <1,5,3,7>, <3,3,3,3> + 2626816514U, // <3,7,3,4>: Cost 3 vext2 <1,5,3,7>, <3,4,5,6> + 2638760514U, // <3,7,3,5>: Cost 3 vext2 <3,5,3,7>, <3,5,3,7> + 2639424147U, // <3,7,3,6>: Cost 3 vext2 <3,6,3,7>, <3,6,3,7> + 2826961920U, // <3,7,3,7>: Cost 3 vuzpr <1,3,5,7>, <1,3,5,7> + 2626816798U, // <3,7,3,u>: Cost 3 vext2 <1,5,3,7>, <3,u,1,2> + 2582536294U, // <3,7,4,0>: Cost 3 vext1 <5,3,7,4>, LHS + 2582537360U, // <3,7,4,1>: Cost 3 vext1 <5,3,7,4>, <1,5,3,7> + 2588510138U, // <3,7,4,2>: Cost 3 vext1 <6,3,7,4>, <2,6,3,7> + 3700558996U, // <3,7,4,3>: Cost 4 vext2 <1,5,3,7>, <4,3,6,7> + 2582539574U, // <3,7,4,4>: Cost 3 vext1 <5,3,7,4>, RHS + 1553075510U, // <3,7,4,5>: Cost 2 vext2 <1,5,3,7>, RHS + 2588512844U, // <3,7,4,6>: Cost 3 vext1 <6,3,7,4>, <6,3,7,4> + 2564625766U, // <3,7,4,7>: Cost 3 vext1 <2,3,7,4>, <7,4,5,6> + 1553075753U, // <3,7,4,u>: Cost 2 vext2 <1,5,3,7>, RHS + 2732971398U, // <3,7,5,0>: Cost 3 vext3 LHS, <7,5,0,2> + 2626817744U, // <3,7,5,1>: Cost 3 vext2 <1,5,3,7>, <5,1,7,3> + 3700559649U, // <3,7,5,2>: Cost 4 vext2 <1,5,3,7>, <5,2,7,3> + 2626817903U, // <3,7,5,3>: Cost 3 vext2 <1,5,3,7>, <5,3,7,0> + 2258728203U, // <3,7,5,4>: Cost 3 vrev <7,3,4,5> + 2732971446U, // <3,7,5,5>: Cost 3 vext3 LHS, <7,5,5,5> + 2732971457U, // <3,7,5,6>: Cost 3 vext3 LHS, <7,5,6,7> + 2826964278U, // <3,7,5,7>: Cost 3 vuzpr <1,3,5,7>, RHS + 2826964279U, // <3,7,5,u>: Cost 3 vuzpr <1,3,5,7>, RHS + 2732971478U, // <3,7,6,0>: Cost 3 vext3 LHS, <7,6,0,1> + 2732971486U, // <3,7,6,1>: Cost 3 vext3 LHS, <7,6,1,0> + 2633454074U, // <3,7,6,2>: Cost 3 vext2 <2,6,3,7>, <6,2,7,3> + 2633454152U, // <3,7,6,3>: Cost 3 vext2 <2,6,3,7>, <6,3,7,0> + 2732971518U, // <3,7,6,4>: Cost 3 vext3 LHS, <7,6,4,5> + 2732971526U, // <3,7,6,5>: Cost 3 vext3 LHS, <7,6,5,4> + 2732971537U, // <3,7,6,6>: Cost 3 vext3 LHS, <7,6,6,6> + 2732971540U, // <3,7,6,7>: Cost 3 vext3 LHS, <7,6,7,0> + 2726041124U, // <3,7,6,u>: Cost 3 vext3 <6,u,7,3>, <7,6,u,7> + 2570616934U, // <3,7,7,0>: Cost 3 vext1 <3,3,7,7>, LHS + 2570617856U, // <3,7,7,1>: Cost 3 vext1 <3,3,7,7>, <1,3,5,7> + 2564646635U, // <3,7,7,2>: Cost 3 vext1 <2,3,7,7>, <2,3,7,7> + 2570619332U, // <3,7,7,3>: Cost 3 vext1 <3,3,7,7>, <3,3,7,7> + 2570620214U, // <3,7,7,4>: Cost 3 vext1 <3,3,7,7>, RHS + 2582564726U, // <3,7,7,5>: Cost 3 vext1 <5,3,7,7>, <5,3,7,7> + 2588537423U, // <3,7,7,6>: Cost 3 vext1 <6,3,7,7>, <6,3,7,7> + 1659229804U, // <3,7,7,7>: Cost 2 vext3 LHS, <7,7,7,7> + 1659229804U, // <3,7,7,u>: Cost 2 vext3 LHS, <7,7,7,7> + 2626819795U, // <3,7,u,0>: Cost 3 vext2 <1,5,3,7>, + 1553078062U, // <3,7,u,1>: Cost 2 vext2 <1,5,3,7>, LHS + 2626819973U, // <3,7,u,2>: Cost 3 vext2 <1,5,3,7>, + 2826961565U, // <3,7,u,3>: Cost 3 vuzpr <1,3,5,7>, LHS + 2626820159U, // <3,7,u,4>: Cost 3 vext2 <1,5,3,7>, + 1553078426U, // <3,7,u,5>: Cost 2 vext2 <1,5,3,7>, RHS + 1595545808U, // <3,7,u,6>: Cost 2 vext2 , + 1659229804U, // <3,7,u,7>: Cost 2 vext3 LHS, <7,7,7,7> + 1553078629U, // <3,7,u,u>: Cost 2 vext2 <1,5,3,7>, LHS + 1611448320U, // <3,u,0,0>: Cost 2 vext3 LHS, <0,0,0,0> + 1611896531U, // <3,u,0,1>: Cost 2 vext3 LHS, + 1659672284U, // <3,u,0,2>: Cost 2 vext3 LHS, + 1616099045U, // <3,u,0,3>: Cost 2 vext3 LHS, + 2685638381U, // <3,u,0,4>: Cost 3 vext3 LHS, + 1663874806U, // <3,u,0,5>: Cost 2 vext3 LHS, + 1663874816U, // <3,u,0,6>: Cost 2 vext3 LHS, + 2960313672U, // <3,u,0,7>: Cost 3 vzipr <1,2,3,0>, RHS + 1611896594U, // <3,u,0,u>: Cost 2 vext3 LHS, + 1549763324U, // <3,u,1,0>: Cost 2 vext2 <1,0,3,u>, <1,0,3,u> + 1550426957U, // <3,u,1,1>: Cost 2 vext2 <1,1,3,u>, <1,1,3,u> + 537712430U, // <3,u,1,2>: Cost 1 vext3 LHS, LHS + 1616541495U, // <3,u,1,3>: Cost 2 vext3 LHS, + 1490930998U, // <3,u,1,4>: Cost 2 vext1 <2,3,u,1>, RHS + 1553081489U, // <3,u,1,5>: Cost 2 vext2 <1,5,3,u>, <1,5,3,u> + 2627486946U, // <3,u,1,6>: Cost 3 vext2 <1,6,3,u>, <1,6,3,u> + 1659230043U, // <3,u,1,7>: Cost 2 vext3 LHS, + 537712484U, // <3,u,1,u>: Cost 1 vext3 LHS, LHS + 1611890852U, // <3,u,2,0>: Cost 2 vext3 LHS, <0,2,0,2> + 2624833102U, // <3,u,2,1>: Cost 3 vext2 <1,2,3,u>, <2,1,u,3> + 1557063287U, // <3,u,2,2>: Cost 2 vext2 <2,2,3,u>, <2,2,3,u> + 1616099205U, // <3,u,2,3>: Cost 2 vext3 LHS, + 1611890892U, // <3,u,2,4>: Cost 2 vext3 LHS, <0,2,4,6> + 2689841054U, // <3,u,2,5>: Cost 3 vext3 LHS, + 1559717819U, // <3,u,2,6>: Cost 2 vext2 <2,6,3,u>, <2,6,3,u> + 1659230124U, // <3,u,2,7>: Cost 2 vext3 LHS, + 1616541618U, // <3,u,2,u>: Cost 2 vext3 LHS, + 1611896764U, // <3,u,3,0>: Cost 2 vext3 LHS, + 1484973079U, // <3,u,3,1>: Cost 2 vext1 <1,3,u,3>, <1,3,u,3> + 2685638607U, // <3,u,3,2>: Cost 3 vext3 LHS, + 336380006U, // <3,u,3,3>: Cost 1 vdup3 LHS + 1611896804U, // <3,u,3,4>: Cost 2 vext3 LHS, + 1616541679U, // <3,u,3,5>: Cost 2 vext3 LHS, + 2690283512U, // <3,u,3,6>: Cost 3 vext3 LHS, + 2959674696U, // <3,u,3,7>: Cost 3 vzipr <1,1,3,3>, RHS + 336380006U, // <3,u,3,u>: Cost 1 vdup3 LHS + 2558722150U, // <3,u,4,0>: Cost 3 vext1 <1,3,u,4>, LHS + 1659672602U, // <3,u,4,1>: Cost 2 vext3 LHS, + 1659672612U, // <3,u,4,2>: Cost 2 vext3 LHS, + 2689841196U, // <3,u,4,3>: Cost 3 vext3 LHS, + 1659227344U, // <3,u,4,4>: Cost 2 vext3 LHS, <4,4,4,4> + 1611896895U, // <3,u,4,5>: Cost 2 vext3 LHS, + 1663875144U, // <3,u,4,6>: Cost 2 vext3 LHS, + 1659230289U, // <3,u,4,7>: Cost 2 vext3 LHS, + 1611896922U, // <3,u,4,u>: Cost 2 vext3 LHS, + 1490960486U, // <3,u,5,0>: Cost 2 vext1 <2,3,u,5>, LHS + 2689841261U, // <3,u,5,1>: Cost 3 vext3 LHS, + 1490962162U, // <3,u,5,2>: Cost 2 vext1 <2,3,u,5>, <2,3,u,5> + 1616541823U, // <3,u,5,3>: Cost 2 vext3 LHS, + 1490963766U, // <3,u,5,4>: Cost 2 vext1 <2,3,u,5>, RHS + 1659228164U, // <3,u,5,5>: Cost 2 vext3 LHS, <5,5,5,5> + 537712794U, // <3,u,5,6>: Cost 1 vext3 LHS, RHS + 1659230371U, // <3,u,5,7>: Cost 2 vext3 LHS, + 537712812U, // <3,u,5,u>: Cost 1 vext3 LHS, RHS + 2689841327U, // <3,u,6,0>: Cost 3 vext3 LHS, + 2558739482U, // <3,u,6,1>: Cost 3 vext1 <1,3,u,6>, <1,3,u,6> + 2689841351U, // <3,u,6,2>: Cost 3 vext3 LHS, + 1616099536U, // <3,u,6,3>: Cost 2 vext3 LHS, + 1659227508U, // <3,u,6,4>: Cost 2 vext3 LHS, <4,6,4,6> + 2690283746U, // <3,u,6,5>: Cost 3 vext3 LHS, + 1659228984U, // <3,u,6,6>: Cost 2 vext3 LHS, <6,6,6,6> + 1659230445U, // <3,u,6,7>: Cost 2 vext3 LHS, + 1616099581U, // <3,u,6,u>: Cost 2 vext3 LHS, + 1485004902U, // <3,u,7,0>: Cost 2 vext1 <1,3,u,7>, LHS + 1485005851U, // <3,u,7,1>: Cost 2 vext1 <1,3,u,7>, <1,3,u,7> + 2558748264U, // <3,u,7,2>: Cost 3 vext1 <1,3,u,7>, <2,2,2,2> + 3095397021U, // <3,u,7,3>: Cost 3 vtrnr <1,3,5,7>, LHS + 1485008182U, // <3,u,7,4>: Cost 2 vext1 <1,3,u,7>, RHS + 1659228328U, // <3,u,7,5>: Cost 2 vext3 LHS, <5,7,5,7> + 2722060599U, // <3,u,7,6>: Cost 3 vext3 <6,2,7,3>, + 1659229804U, // <3,u,7,7>: Cost 2 vext3 LHS, <7,7,7,7> + 1485010734U, // <3,u,7,u>: Cost 2 vext1 <1,3,u,7>, LHS + 1616099665U, // <3,u,u,0>: Cost 2 vext3 LHS, + 1611897179U, // <3,u,u,1>: Cost 2 vext3 LHS, + 537712997U, // <3,u,u,2>: Cost 1 vext3 LHS, LHS + 336380006U, // <3,u,u,3>: Cost 1 vdup3 LHS + 1616099705U, // <3,u,u,4>: Cost 2 vext3 LHS, + 1611897219U, // <3,u,u,5>: Cost 2 vext3 LHS, + 537713037U, // <3,u,u,6>: Cost 1 vext3 LHS, RHS + 1659230607U, // <3,u,u,7>: Cost 2 vext3 LHS, + 537713051U, // <3,u,u,u>: Cost 1 vext3 LHS, LHS + 2691907584U, // <4,0,0,0>: Cost 3 vext3 <1,2,3,4>, <0,0,0,0> + 2691907594U, // <4,0,0,1>: Cost 3 vext3 <1,2,3,4>, <0,0,1,1> + 2691907604U, // <4,0,0,2>: Cost 3 vext3 <1,2,3,4>, <0,0,2,2> + 3709862144U, // <4,0,0,3>: Cost 4 vext2 <3,1,4,0>, <0,3,1,4> + 2684682280U, // <4,0,0,4>: Cost 3 vext3 <0,0,4,4>, <0,0,4,4> + 3694600633U, // <4,0,0,5>: Cost 4 vext2 <0,5,4,0>, <0,5,4,0> + 3291431290U, // <4,0,0,6>: Cost 4 vrev <0,4,6,0> + 3668342067U, // <4,0,0,7>: Cost 4 vext1 <7,4,0,0>, <7,4,0,0> + 2691907657U, // <4,0,0,u>: Cost 3 vext3 <1,2,3,4>, <0,0,u,1> + 2570715238U, // <4,0,1,0>: Cost 3 vext1 <3,4,0,1>, LHS + 2570716058U, // <4,0,1,1>: Cost 3 vext1 <3,4,0,1>, <1,2,3,4> + 1618165862U, // <4,0,1,2>: Cost 2 vext3 <1,2,3,4>, LHS + 2570717648U, // <4,0,1,3>: Cost 3 vext1 <3,4,0,1>, <3,4,0,1> + 2570718518U, // <4,0,1,4>: Cost 3 vext1 <3,4,0,1>, RHS + 2594607206U, // <4,0,1,5>: Cost 3 vext1 <7,4,0,1>, <5,6,7,4> + 3662377563U, // <4,0,1,6>: Cost 4 vext1 <6,4,0,1>, <6,4,0,1> + 2594608436U, // <4,0,1,7>: Cost 3 vext1 <7,4,0,1>, <7,4,0,1> + 1618165916U, // <4,0,1,u>: Cost 2 vext3 <1,2,3,4>, LHS + 2685714598U, // <4,0,2,0>: Cost 3 vext3 <0,2,0,4>, <0,2,0,4> + 3759530159U, // <4,0,2,1>: Cost 4 vext3 <0,2,1,4>, <0,2,1,4> + 2685862072U, // <4,0,2,2>: Cost 3 vext3 <0,2,2,4>, <0,2,2,4> + 2631476937U, // <4,0,2,3>: Cost 3 vext2 <2,3,4,0>, <2,3,4,0> + 2685714636U, // <4,0,2,4>: Cost 3 vext3 <0,2,0,4>, <0,2,4,6> + 3765649622U, // <4,0,2,5>: Cost 4 vext3 <1,2,3,4>, <0,2,5,7> + 2686157020U, // <4,0,2,6>: Cost 3 vext3 <0,2,6,4>, <0,2,6,4> + 3668358453U, // <4,0,2,7>: Cost 4 vext1 <7,4,0,2>, <7,4,0,2> + 2686304494U, // <4,0,2,u>: Cost 3 vext3 <0,2,u,4>, <0,2,u,4> + 3632529510U, // <4,0,3,0>: Cost 4 vext1 <1,4,0,3>, LHS + 2686451968U, // <4,0,3,1>: Cost 3 vext3 <0,3,1,4>, <0,3,1,4> + 2686525705U, // <4,0,3,2>: Cost 3 vext3 <0,3,2,4>, <0,3,2,4> + 3760341266U, // <4,0,3,3>: Cost 4 vext3 <0,3,3,4>, <0,3,3,4> + 3632532790U, // <4,0,3,4>: Cost 4 vext1 <1,4,0,3>, RHS + 3913254606U, // <4,0,3,5>: Cost 4 vuzpr <3,4,5,0>, <2,3,4,5> + 3705219740U, // <4,0,3,6>: Cost 4 vext2 <2,3,4,0>, <3,6,4,7> + 3713845990U, // <4,0,3,7>: Cost 4 vext2 <3,7,4,0>, <3,7,4,0> + 2686451968U, // <4,0,3,u>: Cost 3 vext3 <0,3,1,4>, <0,3,1,4> + 2552823910U, // <4,0,4,0>: Cost 3 vext1 <0,4,0,4>, LHS + 2691907922U, // <4,0,4,1>: Cost 3 vext3 <1,2,3,4>, <0,4,1,5> + 2691907932U, // <4,0,4,2>: Cost 3 vext3 <1,2,3,4>, <0,4,2,6> + 3626567830U, // <4,0,4,3>: Cost 4 vext1 <0,4,0,4>, <3,0,1,2> + 2552827190U, // <4,0,4,4>: Cost 3 vext1 <0,4,0,4>, RHS + 2631478582U, // <4,0,4,5>: Cost 3 vext2 <2,3,4,0>, RHS + 3626570017U, // <4,0,4,6>: Cost 4 vext1 <0,4,0,4>, <6,0,1,2> + 3668374839U, // <4,0,4,7>: Cost 4 vext1 <7,4,0,4>, <7,4,0,4> + 2552829742U, // <4,0,4,u>: Cost 3 vext1 <0,4,0,4>, LHS + 2558804070U, // <4,0,5,0>: Cost 3 vext1 <1,4,0,5>, LHS + 1839644774U, // <4,0,5,1>: Cost 2 vzipl RHS, LHS + 2913386660U, // <4,0,5,2>: Cost 3 vzipl RHS, <0,2,0,2> + 2570750420U, // <4,0,5,3>: Cost 3 vext1 <3,4,0,5>, <3,4,0,5> + 2558807350U, // <4,0,5,4>: Cost 3 vext1 <1,4,0,5>, RHS + 3987128750U, // <4,0,5,5>: Cost 4 vzipl RHS, <0,5,2,7> + 3987128822U, // <4,0,5,6>: Cost 4 vzipl RHS, <0,6,1,7> + 2594641208U, // <4,0,5,7>: Cost 3 vext1 <7,4,0,5>, <7,4,0,5> + 1839645341U, // <4,0,5,u>: Cost 2 vzipl RHS, LHS + 2552840294U, // <4,0,6,0>: Cost 3 vext1 <0,4,0,6>, LHS + 3047604234U, // <4,0,6,1>: Cost 3 vtrnl RHS, <0,0,1,1> + 1973862502U, // <4,0,6,2>: Cost 2 vtrnl RHS, LHS + 2570758613U, // <4,0,6,3>: Cost 3 vext1 <3,4,0,6>, <3,4,0,6> + 2552843574U, // <4,0,6,4>: Cost 3 vext1 <0,4,0,6>, RHS + 2217664887U, // <4,0,6,5>: Cost 3 vrev <0,4,5,6> + 3662418528U, // <4,0,6,6>: Cost 4 vext1 <6,4,0,6>, <6,4,0,6> + 2658022257U, // <4,0,6,7>: Cost 3 vext2 <6,7,4,0>, <6,7,4,0> + 1973862556U, // <4,0,6,u>: Cost 2 vtrnl RHS, LHS + 3731764218U, // <4,0,7,0>: Cost 4 vext2 <6,7,4,0>, <7,0,1,2> + 3988324454U, // <4,0,7,1>: Cost 4 vzipl <4,7,5,0>, LHS + 4122034278U, // <4,0,7,2>: Cost 4 vtrnl <4,6,7,1>, LHS + 3735082246U, // <4,0,7,3>: Cost 4 vext2 <7,3,4,0>, <7,3,4,0> + 3731764536U, // <4,0,7,4>: Cost 4 vext2 <6,7,4,0>, <7,4,0,5> + 3937145718U, // <4,0,7,5>: Cost 4 vuzpr <7,4,5,0>, <6,7,4,5> + 3737073145U, // <4,0,7,6>: Cost 4 vext2 <7,6,4,0>, <7,6,4,0> + 3731764844U, // <4,0,7,7>: Cost 4 vext2 <6,7,4,0>, <7,7,7,7> + 4122034332U, // <4,0,7,u>: Cost 4 vtrnl <4,6,7,1>, LHS + 2552856678U, // <4,0,u,0>: Cost 3 vext1 <0,4,0,u>, LHS + 1841635430U, // <4,0,u,1>: Cost 2 vzipl RHS, LHS + 1618166429U, // <4,0,u,2>: Cost 2 vext3 <1,2,3,4>, LHS + 2570774999U, // <4,0,u,3>: Cost 3 vext1 <3,4,0,u>, <3,4,0,u> + 2552859958U, // <4,0,u,4>: Cost 3 vext1 <0,4,0,u>, RHS + 2631481498U, // <4,0,u,5>: Cost 3 vext2 <2,3,4,0>, RHS + 2686157020U, // <4,0,u,6>: Cost 3 vext3 <0,2,6,4>, <0,2,6,4> + 2594665787U, // <4,0,u,7>: Cost 3 vext1 <7,4,0,u>, <7,4,0,u> + 1618166483U, // <4,0,u,u>: Cost 2 vext3 <1,2,3,4>, LHS + 2617548837U, // <4,1,0,0>: Cost 3 vext2 <0,0,4,1>, <0,0,4,1> + 2622857318U, // <4,1,0,1>: Cost 3 vext2 <0,u,4,1>, LHS + 3693281484U, // <4,1,0,2>: Cost 4 vext2 <0,3,4,1>, <0,2,4,6> + 2691908342U, // <4,1,0,3>: Cost 3 vext3 <1,2,3,4>, <1,0,3,2> + 2622857554U, // <4,1,0,4>: Cost 3 vext2 <0,u,4,1>, <0,4,1,5> + 3764470538U, // <4,1,0,5>: Cost 4 vext3 <1,0,5,4>, <1,0,5,4> + 3695272459U, // <4,1,0,6>: Cost 4 vext2 <0,6,4,1>, <0,6,4,1> + 3733094980U, // <4,1,0,7>: Cost 4 vext2 <7,0,4,1>, <0,7,1,4> + 2622857885U, // <4,1,0,u>: Cost 3 vext2 <0,u,4,1>, LHS + 3696599798U, // <4,1,1,0>: Cost 4 vext2 <0,u,4,1>, <1,0,3,2> + 2691097399U, // <4,1,1,1>: Cost 3 vext3 <1,1,1,4>, <1,1,1,4> + 2631484314U, // <4,1,1,2>: Cost 3 vext2 <2,3,4,1>, <1,2,3,4> + 2691908424U, // <4,1,1,3>: Cost 3 vext3 <1,2,3,4>, <1,1,3,3> + 3696600125U, // <4,1,1,4>: Cost 4 vext2 <0,u,4,1>, <1,4,3,5> + 3696600175U, // <4,1,1,5>: Cost 4 vext2 <0,u,4,1>, <1,5,0,1> + 3696600307U, // <4,1,1,6>: Cost 4 vext2 <0,u,4,1>, <1,6,5,7> + 3668423997U, // <4,1,1,7>: Cost 4 vext1 <7,4,1,1>, <7,4,1,1> + 2691908469U, // <4,1,1,u>: Cost 3 vext3 <1,2,3,4>, <1,1,u,3> + 2570797158U, // <4,1,2,0>: Cost 3 vext1 <3,4,1,2>, LHS + 2570797978U, // <4,1,2,1>: Cost 3 vext1 <3,4,1,2>, <1,2,3,4> + 3696600680U, // <4,1,2,2>: Cost 4 vext2 <0,u,4,1>, <2,2,2,2> + 1618166682U, // <4,1,2,3>: Cost 2 vext3 <1,2,3,4>, <1,2,3,4> + 2570800438U, // <4,1,2,4>: Cost 3 vext1 <3,4,1,2>, RHS + 3765650347U, // <4,1,2,5>: Cost 4 vext3 <1,2,3,4>, <1,2,5,3> + 3696601018U, // <4,1,2,6>: Cost 4 vext2 <0,u,4,1>, <2,6,3,7> + 3668432190U, // <4,1,2,7>: Cost 4 vext1 <7,4,1,2>, <7,4,1,2> + 1618535367U, // <4,1,2,u>: Cost 2 vext3 <1,2,u,4>, <1,2,u,4> + 2564833382U, // <4,1,3,0>: Cost 3 vext1 <2,4,1,3>, LHS + 2691908568U, // <4,1,3,1>: Cost 3 vext3 <1,2,3,4>, <1,3,1,3> + 2691908578U, // <4,1,3,2>: Cost 3 vext3 <1,2,3,4>, <1,3,2,4> + 2692572139U, // <4,1,3,3>: Cost 3 vext3 <1,3,3,4>, <1,3,3,4> + 2564836662U, // <4,1,3,4>: Cost 3 vext1 <2,4,1,3>, RHS + 2691908608U, // <4,1,3,5>: Cost 3 vext3 <1,2,3,4>, <1,3,5,7> + 2588725862U, // <4,1,3,6>: Cost 3 vext1 <6,4,1,3>, <6,4,1,3> + 3662468090U, // <4,1,3,7>: Cost 4 vext1 <6,4,1,3>, <7,0,1,2> + 2691908631U, // <4,1,3,u>: Cost 3 vext3 <1,2,3,4>, <1,3,u,3> + 3760194590U, // <4,1,4,0>: Cost 4 vext3 <0,3,1,4>, <1,4,0,1> + 3693947874U, // <4,1,4,1>: Cost 4 vext2 <0,4,4,1>, <4,1,5,0> + 3765650484U, // <4,1,4,2>: Cost 4 vext3 <1,2,3,4>, <1,4,2,5> + 3113877606U, // <4,1,4,3>: Cost 3 vtrnr <4,4,4,4>, LHS + 3760194630U, // <4,1,4,4>: Cost 4 vext3 <0,3,1,4>, <1,4,4,5> + 2622860598U, // <4,1,4,5>: Cost 3 vext2 <0,u,4,1>, RHS + 3297436759U, // <4,1,4,6>: Cost 4 vrev <1,4,6,4> + 3800007772U, // <4,1,4,7>: Cost 4 vext3 <7,0,1,4>, <1,4,7,0> + 2622860841U, // <4,1,4,u>: Cost 3 vext2 <0,u,4,1>, RHS + 1479164006U, // <4,1,5,0>: Cost 2 vext1 <0,4,1,5>, LHS + 2552906486U, // <4,1,5,1>: Cost 3 vext1 <0,4,1,5>, <1,0,3,2> + 2552907299U, // <4,1,5,2>: Cost 3 vext1 <0,4,1,5>, <2,1,3,5> + 2552907926U, // <4,1,5,3>: Cost 3 vext1 <0,4,1,5>, <3,0,1,2> + 1479167286U, // <4,1,5,4>: Cost 2 vext1 <0,4,1,5>, RHS + 2913387664U, // <4,1,5,5>: Cost 3 vzipl RHS, <1,5,3,7> + 2600686074U, // <4,1,5,6>: Cost 3 vext1 , <6,2,7,3> + 2600686586U, // <4,1,5,7>: Cost 3 vext1 , <7,0,1,2> + 1479169838U, // <4,1,5,u>: Cost 2 vext1 <0,4,1,5>, LHS + 2552914022U, // <4,1,6,0>: Cost 3 vext1 <0,4,1,6>, LHS + 2558886708U, // <4,1,6,1>: Cost 3 vext1 <1,4,1,6>, <1,1,1,1> + 4028205206U, // <4,1,6,2>: Cost 4 vzipr <0,2,4,6>, <3,0,1,2> + 3089858662U, // <4,1,6,3>: Cost 3 vtrnr <0,4,2,6>, LHS + 2552917302U, // <4,1,6,4>: Cost 3 vext1 <0,4,1,6>, RHS + 2223637584U, // <4,1,6,5>: Cost 3 vrev <1,4,5,6> + 4121347081U, // <4,1,6,6>: Cost 4 vtrnl RHS, <1,3,6,7> + 3721155406U, // <4,1,6,7>: Cost 4 vext2 <5,0,4,1>, <6,7,0,1> + 2552919854U, // <4,1,6,u>: Cost 3 vext1 <0,4,1,6>, LHS + 2659357716U, // <4,1,7,0>: Cost 3 vext2 <7,0,4,1>, <7,0,4,1> + 3733763173U, // <4,1,7,1>: Cost 4 vext2 <7,1,4,1>, <7,1,4,1> + 3734426806U, // <4,1,7,2>: Cost 4 vext2 <7,2,4,1>, <7,2,4,1> + 2695226671U, // <4,1,7,3>: Cost 3 vext3 <1,7,3,4>, <1,7,3,4> + 3721155942U, // <4,1,7,4>: Cost 4 vext2 <5,0,4,1>, <7,4,5,6> + 3721155976U, // <4,1,7,5>: Cost 4 vext2 <5,0,4,1>, <7,5,0,4> + 3662500458U, // <4,1,7,6>: Cost 4 vext1 <6,4,1,7>, <6,4,1,7> + 3721156204U, // <4,1,7,7>: Cost 4 vext2 <5,0,4,1>, <7,7,7,7> + 2659357716U, // <4,1,7,u>: Cost 3 vext2 <7,0,4,1>, <7,0,4,1> + 1479188582U, // <4,1,u,0>: Cost 2 vext1 <0,4,1,u>, LHS + 2552931062U, // <4,1,u,1>: Cost 3 vext1 <0,4,1,u>, <1,0,3,2> + 2552931944U, // <4,1,u,2>: Cost 3 vext1 <0,4,1,u>, <2,2,2,2> + 1622148480U, // <4,1,u,3>: Cost 2 vext3 <1,u,3,4>, <1,u,3,4> + 1479191862U, // <4,1,u,4>: Cost 2 vext1 <0,4,1,u>, RHS + 2622863514U, // <4,1,u,5>: Cost 3 vext2 <0,u,4,1>, RHS + 2588725862U, // <4,1,u,6>: Cost 3 vext1 <6,4,1,3>, <6,4,1,3> + 2600686586U, // <4,1,u,7>: Cost 3 vext1 , <7,0,1,2> + 1479194414U, // <4,1,u,u>: Cost 2 vext1 <0,4,1,u>, LHS + 2617557030U, // <4,2,0,0>: Cost 3 vext2 <0,0,4,2>, <0,0,4,2> + 2622865510U, // <4,2,0,1>: Cost 3 vext2 <0,u,4,2>, LHS + 2622865612U, // <4,2,0,2>: Cost 3 vext2 <0,u,4,2>, <0,2,4,6> + 3693289753U, // <4,2,0,3>: Cost 4 vext2 <0,3,4,2>, <0,3,4,2> + 2635473244U, // <4,2,0,4>: Cost 3 vext2 <3,0,4,2>, <0,4,2,6> + 3765650918U, // <4,2,0,5>: Cost 4 vext3 <1,2,3,4>, <2,0,5,7> + 2696775148U, // <4,2,0,6>: Cost 3 vext3 <2,0,6,4>, <2,0,6,4> + 3695944285U, // <4,2,0,7>: Cost 4 vext2 <0,7,4,2>, <0,7,4,2> + 2622866077U, // <4,2,0,u>: Cost 3 vext2 <0,u,4,2>, LHS + 3696607990U, // <4,2,1,0>: Cost 4 vext2 <0,u,4,2>, <1,0,3,2> + 3696608052U, // <4,2,1,1>: Cost 4 vext2 <0,u,4,2>, <1,1,1,1> + 3696608150U, // <4,2,1,2>: Cost 4 vext2 <0,u,4,2>, <1,2,3,0> + 3895574630U, // <4,2,1,3>: Cost 4 vuzpr <0,4,u,2>, LHS + 2691909162U, // <4,2,1,4>: Cost 3 vext3 <1,2,3,4>, <2,1,4,3> + 3696608400U, // <4,2,1,5>: Cost 4 vext2 <0,u,4,2>, <1,5,3,7> + 3760784956U, // <4,2,1,6>: Cost 4 vext3 <0,4,0,4>, <2,1,6,3> + 3773908549U, // <4,2,1,7>: Cost 5 vext3 <2,5,7,4>, <2,1,7,3> + 2691909162U, // <4,2,1,u>: Cost 3 vext3 <1,2,3,4>, <2,1,4,3> + 3696608748U, // <4,2,2,0>: Cost 4 vext2 <0,u,4,2>, <2,0,6,4> + 3696608828U, // <4,2,2,1>: Cost 4 vext2 <0,u,4,2>, <2,1,6,3> + 2691909224U, // <4,2,2,2>: Cost 3 vext3 <1,2,3,4>, <2,2,2,2> + 2691909234U, // <4,2,2,3>: Cost 3 vext3 <1,2,3,4>, <2,2,3,3> + 3759605368U, // <4,2,2,4>: Cost 4 vext3 <0,2,2,4>, <2,2,4,0> + 3696609156U, // <4,2,2,5>: Cost 4 vext2 <0,u,4,2>, <2,5,6,7> + 3760785040U, // <4,2,2,6>: Cost 4 vext3 <0,4,0,4>, <2,2,6,6> + 3668505927U, // <4,2,2,7>: Cost 4 vext1 <7,4,2,2>, <7,4,2,2> + 2691909279U, // <4,2,2,u>: Cost 3 vext3 <1,2,3,4>, <2,2,u,3> + 2691909286U, // <4,2,3,0>: Cost 3 vext3 <1,2,3,4>, <2,3,0,1> + 3764840111U, // <4,2,3,1>: Cost 4 vext3 <1,1,1,4>, <2,3,1,1> + 3765651129U, // <4,2,3,2>: Cost 4 vext3 <1,2,3,4>, <2,3,2,2> + 2698544836U, // <4,2,3,3>: Cost 3 vext3 <2,3,3,4>, <2,3,3,4> + 2685863630U, // <4,2,3,4>: Cost 3 vext3 <0,2,2,4>, <2,3,4,5> + 2698692310U, // <4,2,3,5>: Cost 3 vext3 <2,3,5,4>, <2,3,5,4> + 3772507871U, // <4,2,3,6>: Cost 4 vext3 <2,3,6,4>, <2,3,6,4> + 2698839784U, // <4,2,3,7>: Cost 3 vext3 <2,3,7,4>, <2,3,7,4> + 2691909358U, // <4,2,3,u>: Cost 3 vext3 <1,2,3,4>, <2,3,u,1> + 2564915302U, // <4,2,4,0>: Cost 3 vext1 <2,4,2,4>, LHS + 2564916122U, // <4,2,4,1>: Cost 3 vext1 <2,4,2,4>, <1,2,3,4> + 2564917004U, // <4,2,4,2>: Cost 3 vext1 <2,4,2,4>, <2,4,2,4> + 2699208469U, // <4,2,4,3>: Cost 3 vext3 <2,4,3,4>, <2,4,3,4> + 2564918582U, // <4,2,4,4>: Cost 3 vext1 <2,4,2,4>, RHS + 2622868790U, // <4,2,4,5>: Cost 3 vext2 <0,u,4,2>, RHS + 2229667632U, // <4,2,4,6>: Cost 3 vrev <2,4,6,4> + 3800082229U, // <4,2,4,7>: Cost 4 vext3 <7,0,2,4>, <2,4,7,0> + 2622869033U, // <4,2,4,u>: Cost 3 vext2 <0,u,4,2>, RHS + 2552979558U, // <4,2,5,0>: Cost 3 vext1 <0,4,2,5>, LHS + 2558952342U, // <4,2,5,1>: Cost 3 vext1 <1,4,2,5>, <1,2,3,0> + 2564925032U, // <4,2,5,2>: Cost 3 vext1 <2,4,2,5>, <2,2,2,2> + 2967060582U, // <4,2,5,3>: Cost 3 vzipr <2,3,4,5>, LHS + 2552982838U, // <4,2,5,4>: Cost 3 vext1 <0,4,2,5>, RHS + 3987130190U, // <4,2,5,5>: Cost 4 vzipl RHS, <2,5,0,7> + 2913388474U, // <4,2,5,6>: Cost 3 vzipl RHS, <2,6,3,7> + 3895577910U, // <4,2,5,7>: Cost 4 vuzpr <0,4,u,2>, RHS + 2552985390U, // <4,2,5,u>: Cost 3 vext1 <0,4,2,5>, LHS + 1479245926U, // <4,2,6,0>: Cost 2 vext1 <0,4,2,6>, LHS + 2552988406U, // <4,2,6,1>: Cost 3 vext1 <0,4,2,6>, <1,0,3,2> + 2552989288U, // <4,2,6,2>: Cost 3 vext1 <0,4,2,6>, <2,2,2,2> + 2954461286U, // <4,2,6,3>: Cost 3 vzipr <0,2,4,6>, LHS + 1479249206U, // <4,2,6,4>: Cost 2 vext1 <0,4,2,6>, RHS + 2229610281U, // <4,2,6,5>: Cost 3 vrev <2,4,5,6> + 2600767994U, // <4,2,6,6>: Cost 3 vext1 , <6,2,7,3> + 2600768506U, // <4,2,6,7>: Cost 3 vext1 , <7,0,1,2> + 1479251758U, // <4,2,6,u>: Cost 2 vext1 <0,4,2,6>, LHS + 2659365909U, // <4,2,7,0>: Cost 3 vext2 <7,0,4,2>, <7,0,4,2> + 3733771366U, // <4,2,7,1>: Cost 4 vext2 <7,1,4,2>, <7,1,4,2> + 3734434999U, // <4,2,7,2>: Cost 4 vext2 <7,2,4,2>, <7,2,4,2> + 2701199368U, // <4,2,7,3>: Cost 3 vext3 <2,7,3,4>, <2,7,3,4> + 4175774618U, // <4,2,7,4>: Cost 4 vtrnr <2,4,5,7>, <1,2,3,4> + 3303360298U, // <4,2,7,5>: Cost 4 vrev <2,4,5,7> + 3727136217U, // <4,2,7,6>: Cost 4 vext2 <6,0,4,2>, <7,6,0,4> + 3727136364U, // <4,2,7,7>: Cost 4 vext2 <6,0,4,2>, <7,7,7,7> + 2659365909U, // <4,2,7,u>: Cost 3 vext2 <7,0,4,2>, <7,0,4,2> + 1479262310U, // <4,2,u,0>: Cost 2 vext1 <0,4,2,u>, LHS + 2553004790U, // <4,2,u,1>: Cost 3 vext1 <0,4,2,u>, <1,0,3,2> + 2553005672U, // <4,2,u,2>: Cost 3 vext1 <0,4,2,u>, <2,2,2,2> + 2954477670U, // <4,2,u,3>: Cost 3 vzipr <0,2,4,u>, LHS + 1479265590U, // <4,2,u,4>: Cost 2 vext1 <0,4,2,u>, RHS + 2622871706U, // <4,2,u,5>: Cost 3 vext2 <0,u,4,2>, RHS + 2229700404U, // <4,2,u,6>: Cost 3 vrev <2,4,6,u> + 2600784890U, // <4,2,u,7>: Cost 3 vext1 , <7,0,1,2> + 1479268142U, // <4,2,u,u>: Cost 2 vext1 <0,4,2,u>, LHS + 3765651595U, // <4,3,0,0>: Cost 4 vext3 <1,2,3,4>, <3,0,0,0> + 2691909782U, // <4,3,0,1>: Cost 3 vext3 <1,2,3,4>, <3,0,1,2> + 2702452897U, // <4,3,0,2>: Cost 3 vext3 <3,0,2,4>, <3,0,2,4> + 3693297946U, // <4,3,0,3>: Cost 4 vext2 <0,3,4,3>, <0,3,4,3> + 3760711856U, // <4,3,0,4>: Cost 4 vext3 <0,3,u,4>, <3,0,4,1> + 2235533820U, // <4,3,0,5>: Cost 3 vrev <3,4,5,0> + 3309349381U, // <4,3,0,6>: Cost 4 vrev <3,4,6,0> + 3668563278U, // <4,3,0,7>: Cost 4 vext1 <7,4,3,0>, <7,4,3,0> + 2691909845U, // <4,3,0,u>: Cost 3 vext3 <1,2,3,4>, <3,0,u,2> + 2235173328U, // <4,3,1,0>: Cost 3 vrev <3,4,0,1> + 3764840678U, // <4,3,1,1>: Cost 4 vext3 <1,1,1,4>, <3,1,1,1> + 2630173594U, // <4,3,1,2>: Cost 3 vext2 <2,1,4,3>, <1,2,3,4> + 2703190267U, // <4,3,1,3>: Cost 3 vext3 <3,1,3,4>, <3,1,3,4> + 3760195840U, // <4,3,1,4>: Cost 4 vext3 <0,3,1,4>, <3,1,4,0> + 3765651724U, // <4,3,1,5>: Cost 4 vext3 <1,2,3,4>, <3,1,5,3> + 3309357574U, // <4,3,1,6>: Cost 4 vrev <3,4,6,1> + 3769633054U, // <4,3,1,7>: Cost 4 vext3 <1,u,3,4>, <3,1,7,3> + 2703558952U, // <4,3,1,u>: Cost 3 vext3 <3,1,u,4>, <3,1,u,4> + 3626770534U, // <4,3,2,0>: Cost 4 vext1 <0,4,3,2>, LHS + 2630174250U, // <4,3,2,1>: Cost 3 vext2 <2,1,4,3>, <2,1,4,3> + 3765651777U, // <4,3,2,2>: Cost 4 vext3 <1,2,3,4>, <3,2,2,2> + 2703853900U, // <4,3,2,3>: Cost 3 vext3 <3,2,3,4>, <3,2,3,4> + 3626773814U, // <4,3,2,4>: Cost 4 vext1 <0,4,3,2>, RHS + 2704001374U, // <4,3,2,5>: Cost 3 vext3 <3,2,5,4>, <3,2,5,4> + 3765651814U, // <4,3,2,6>: Cost 4 vext3 <1,2,3,4>, <3,2,6,3> + 3769633135U, // <4,3,2,7>: Cost 4 vext3 <1,u,3,4>, <3,2,7,3> + 2634819681U, // <4,3,2,u>: Cost 3 vext2 <2,u,4,3>, <2,u,4,3> + 3765651839U, // <4,3,3,0>: Cost 4 vext3 <1,2,3,4>, <3,3,0,1> + 3765651848U, // <4,3,3,1>: Cost 4 vext3 <1,2,3,4>, <3,3,1,1> + 3710552404U, // <4,3,3,2>: Cost 4 vext2 <3,2,4,3>, <3,2,4,3> + 2691910044U, // <4,3,3,3>: Cost 3 vext3 <1,2,3,4>, <3,3,3,3> + 2704591270U, // <4,3,3,4>: Cost 3 vext3 <3,3,4,4>, <3,3,4,4> + 3769633202U, // <4,3,3,5>: Cost 4 vext3 <1,u,3,4>, <3,3,5,7> + 3703917212U, // <4,3,3,6>: Cost 4 vext2 <2,1,4,3>, <3,6,4,7> + 3769633220U, // <4,3,3,7>: Cost 4 vext3 <1,u,3,4>, <3,3,7,7> + 2691910044U, // <4,3,3,u>: Cost 3 vext3 <1,2,3,4>, <3,3,3,3> + 2691910096U, // <4,3,4,0>: Cost 3 vext3 <1,2,3,4>, <3,4,0,1> + 2691910106U, // <4,3,4,1>: Cost 3 vext3 <1,2,3,4>, <3,4,1,2> + 2564990741U, // <4,3,4,2>: Cost 3 vext1 <2,4,3,4>, <2,4,3,4> + 3765651946U, // <4,3,4,3>: Cost 4 vext3 <1,2,3,4>, <3,4,3,0> + 2691910136U, // <4,3,4,4>: Cost 3 vext3 <1,2,3,4>, <3,4,4,5> + 2686454274U, // <4,3,4,5>: Cost 3 vext3 <0,3,1,4>, <3,4,5,6> + 2235640329U, // <4,3,4,6>: Cost 3 vrev <3,4,6,4> + 3801483792U, // <4,3,4,7>: Cost 4 vext3 <7,2,3,4>, <3,4,7,2> + 2691910168U, // <4,3,4,u>: Cost 3 vext3 <1,2,3,4>, <3,4,u,1> + 2559025254U, // <4,3,5,0>: Cost 3 vext1 <1,4,3,5>, LHS + 2559026237U, // <4,3,5,1>: Cost 3 vext1 <1,4,3,5>, <1,4,3,5> + 2564998862U, // <4,3,5,2>: Cost 3 vext1 <2,4,3,5>, <2,3,4,5> + 2570971548U, // <4,3,5,3>: Cost 3 vext1 <3,4,3,5>, <3,3,3,3> + 2559028534U, // <4,3,5,4>: Cost 3 vext1 <1,4,3,5>, RHS + 4163519477U, // <4,3,5,5>: Cost 4 vtrnr <0,4,1,5>, <1,3,4,5> + 3309390346U, // <4,3,5,6>: Cost 4 vrev <3,4,6,5> + 2706139747U, // <4,3,5,7>: Cost 3 vext3 <3,5,7,4>, <3,5,7,4> + 2559031086U, // <4,3,5,u>: Cost 3 vext1 <1,4,3,5>, LHS + 2559033446U, // <4,3,6,0>: Cost 3 vext1 <1,4,3,6>, LHS + 2559034430U, // <4,3,6,1>: Cost 3 vext1 <1,4,3,6>, <1,4,3,6> + 2565007127U, // <4,3,6,2>: Cost 3 vext1 <2,4,3,6>, <2,4,3,6> + 2570979740U, // <4,3,6,3>: Cost 3 vext1 <3,4,3,6>, <3,3,3,3> + 2559036726U, // <4,3,6,4>: Cost 3 vext1 <1,4,3,6>, RHS + 1161841154U, // <4,3,6,5>: Cost 2 vrev <3,4,5,6> + 4028203932U, // <4,3,6,6>: Cost 4 vzipr <0,2,4,6>, <1,2,3,6> + 2706803380U, // <4,3,6,7>: Cost 3 vext3 <3,6,7,4>, <3,6,7,4> + 1162062365U, // <4,3,6,u>: Cost 2 vrev <3,4,u,6> + 3769633475U, // <4,3,7,0>: Cost 4 vext3 <1,u,3,4>, <3,7,0,1> + 3769633488U, // <4,3,7,1>: Cost 4 vext3 <1,u,3,4>, <3,7,1,5> + 3638757144U, // <4,3,7,2>: Cost 4 vext1 <2,4,3,7>, <2,4,3,7> + 3769633508U, // <4,3,7,3>: Cost 4 vext3 <1,u,3,4>, <3,7,3,7> + 3769633515U, // <4,3,7,4>: Cost 4 vext3 <1,u,3,4>, <3,7,4,5> + 3769633526U, // <4,3,7,5>: Cost 4 vext3 <1,u,3,4>, <3,7,5,7> + 3662647932U, // <4,3,7,6>: Cost 4 vext1 <6,4,3,7>, <6,4,3,7> + 3781208837U, // <4,3,7,7>: Cost 4 vext3 <3,7,7,4>, <3,7,7,4> + 3769633547U, // <4,3,7,u>: Cost 4 vext3 <1,u,3,4>, <3,7,u,1> + 2559049830U, // <4,3,u,0>: Cost 3 vext1 <1,4,3,u>, LHS + 2691910430U, // <4,3,u,1>: Cost 3 vext3 <1,2,3,4>, <3,u,1,2> + 2565023513U, // <4,3,u,2>: Cost 3 vext1 <2,4,3,u>, <2,4,3,u> + 2707835698U, // <4,3,u,3>: Cost 3 vext3 <3,u,3,4>, <3,u,3,4> + 2559053110U, // <4,3,u,4>: Cost 3 vext1 <1,4,3,u>, RHS + 1161857540U, // <4,3,u,5>: Cost 2 vrev <3,4,5,u> + 2235673101U, // <4,3,u,6>: Cost 3 vrev <3,4,6,u> + 2708130646U, // <4,3,u,7>: Cost 3 vext3 <3,u,7,4>, <3,u,7,4> + 1162078751U, // <4,3,u,u>: Cost 2 vrev <3,4,u,u> + 2617573416U, // <4,4,0,0>: Cost 3 vext2 <0,0,4,4>, <0,0,4,4> + 1570373734U, // <4,4,0,1>: Cost 2 vext2 <4,4,4,4>, LHS + 2779676774U, // <4,4,0,2>: Cost 3 vuzpl <4,6,4,6>, LHS + 3760196480U, // <4,4,0,3>: Cost 4 vext3 <0,3,1,4>, <4,0,3,1> + 2576977100U, // <4,4,0,4>: Cost 3 vext1 <4,4,4,0>, <4,4,4,0> + 2718747538U, // <4,4,0,5>: Cost 3 vext3 <5,6,7,4>, <4,0,5,1> + 2718747548U, // <4,4,0,6>: Cost 3 vext3 <5,6,7,4>, <4,0,6,2> + 3668637015U, // <4,4,0,7>: Cost 4 vext1 <7,4,4,0>, <7,4,4,0> + 1570374301U, // <4,4,0,u>: Cost 2 vext2 <4,4,4,4>, LHS + 2644116214U, // <4,4,1,0>: Cost 3 vext2 <4,4,4,4>, <1,0,3,2> + 2644116276U, // <4,4,1,1>: Cost 3 vext2 <4,4,4,4>, <1,1,1,1> + 2691910602U, // <4,4,1,2>: Cost 3 vext3 <1,2,3,4>, <4,1,2,3> + 2644116440U, // <4,4,1,3>: Cost 3 vext2 <4,4,4,4>, <1,3,1,3> + 2711227356U, // <4,4,1,4>: Cost 3 vext3 <4,4,4,4>, <4,1,4,3> + 2709310438U, // <4,4,1,5>: Cost 3 vext3 <4,1,5,4>, <4,1,5,4> + 3765652462U, // <4,4,1,6>: Cost 4 vext3 <1,2,3,4>, <4,1,6,3> + 3768970231U, // <4,4,1,7>: Cost 4 vext3 <1,7,3,4>, <4,1,7,3> + 2695891968U, // <4,4,1,u>: Cost 3 vext3 <1,u,3,4>, <4,1,u,3> + 3703260634U, // <4,4,2,0>: Cost 4 vext2 <2,0,4,4>, <2,0,4,4> + 3765652499U, // <4,4,2,1>: Cost 4 vext3 <1,2,3,4>, <4,2,1,4> + 2644117096U, // <4,4,2,2>: Cost 3 vext2 <4,4,4,4>, <2,2,2,2> + 2631509709U, // <4,4,2,3>: Cost 3 vext2 <2,3,4,4>, <2,3,4,4> + 2644117269U, // <4,4,2,4>: Cost 3 vext2 <4,4,4,4>, <2,4,3,4> + 3705251698U, // <4,4,2,5>: Cost 4 vext2 <2,3,4,4>, <2,5,4,7> + 2710047808U, // <4,4,2,6>: Cost 3 vext3 <4,2,6,4>, <4,2,6,4> + 3783863369U, // <4,4,2,7>: Cost 4 vext3 <4,2,7,4>, <4,2,7,4> + 2634827874U, // <4,4,2,u>: Cost 3 vext2 <2,u,4,4>, <2,u,4,4> + 2644117654U, // <4,4,3,0>: Cost 3 vext2 <4,4,4,4>, <3,0,1,2> + 3638797210U, // <4,4,3,1>: Cost 4 vext1 <2,4,4,3>, <1,2,3,4> + 3638798082U, // <4,4,3,2>: Cost 4 vext1 <2,4,4,3>, <2,4,1,3> + 2637482406U, // <4,4,3,3>: Cost 3 vext2 <3,3,4,4>, <3,3,4,4> + 2638146039U, // <4,4,3,4>: Cost 3 vext2 <3,4,4,4>, <3,4,4,4> + 3913287374U, // <4,4,3,5>: Cost 4 vuzpr <3,4,5,4>, <2,3,4,5> + 3765652625U, // <4,4,3,6>: Cost 4 vext3 <1,2,3,4>, <4,3,6,4> + 3713878762U, // <4,4,3,7>: Cost 4 vext2 <3,7,4,4>, <3,7,4,4> + 2637482406U, // <4,4,3,u>: Cost 3 vext2 <3,3,4,4>, <3,3,4,4> + 1503264870U, // <4,4,4,0>: Cost 2 vext1 <4,4,4,4>, LHS + 2577007514U, // <4,4,4,1>: Cost 3 vext1 <4,4,4,4>, <1,2,3,4> + 2577008232U, // <4,4,4,2>: Cost 3 vext1 <4,4,4,4>, <2,2,2,2> + 2571037175U, // <4,4,4,3>: Cost 3 vext1 <3,4,4,4>, <3,4,4,4> + 161926454U, // <4,4,4,4>: Cost 1 vdup0 RHS + 1570377014U, // <4,4,4,5>: Cost 2 vext2 <4,4,4,4>, RHS + 2779680054U, // <4,4,4,6>: Cost 3 vuzpl <4,6,4,6>, RHS + 2594927963U, // <4,4,4,7>: Cost 3 vext1 <7,4,4,4>, <7,4,4,4> + 161926454U, // <4,4,4,u>: Cost 1 vdup0 RHS + 2571042918U, // <4,4,5,0>: Cost 3 vext1 <3,4,4,5>, LHS + 2571043738U, // <4,4,5,1>: Cost 3 vext1 <3,4,4,5>, <1,2,3,4> + 3638814495U, // <4,4,5,2>: Cost 4 vext1 <2,4,4,5>, <2,4,4,5> + 2571045368U, // <4,4,5,3>: Cost 3 vext1 <3,4,4,5>, <3,4,4,5> + 2571046198U, // <4,4,5,4>: Cost 3 vext1 <3,4,4,5>, RHS + 1839648054U, // <4,4,5,5>: Cost 2 vzipl RHS, RHS + 1618169142U, // <4,4,5,6>: Cost 2 vext3 <1,2,3,4>, RHS + 2594936156U, // <4,4,5,7>: Cost 3 vext1 <7,4,4,5>, <7,4,4,5> + 1618169160U, // <4,4,5,u>: Cost 2 vext3 <1,2,3,4>, RHS + 2553135206U, // <4,4,6,0>: Cost 3 vext1 <0,4,4,6>, LHS + 3626877686U, // <4,4,6,1>: Cost 4 vext1 <0,4,4,6>, <1,0,3,2> + 2565080782U, // <4,4,6,2>: Cost 3 vext1 <2,4,4,6>, <2,3,4,5> + 2571053561U, // <4,4,6,3>: Cost 3 vext1 <3,4,4,6>, <3,4,4,6> + 2553138486U, // <4,4,6,4>: Cost 3 vext1 <0,4,4,6>, RHS + 2241555675U, // <4,4,6,5>: Cost 3 vrev <4,4,5,6> + 1973865782U, // <4,4,6,6>: Cost 2 vtrnl RHS, RHS + 2658055029U, // <4,4,6,7>: Cost 3 vext2 <6,7,4,4>, <6,7,4,4> + 1973865800U, // <4,4,6,u>: Cost 2 vtrnl RHS, RHS + 2644120570U, // <4,4,7,0>: Cost 3 vext2 <4,4,4,4>, <7,0,1,2> + 3638829978U, // <4,4,7,1>: Cost 4 vext1 <2,4,4,7>, <1,2,3,4> + 3638830881U, // <4,4,7,2>: Cost 4 vext1 <2,4,4,7>, <2,4,4,7> + 3735115018U, // <4,4,7,3>: Cost 4 vext2 <7,3,4,4>, <7,3,4,4> + 2662036827U, // <4,4,7,4>: Cost 3 vext2 <7,4,4,4>, <7,4,4,4> + 2713292236U, // <4,4,7,5>: Cost 3 vext3 <4,7,5,4>, <4,7,5,4> + 2713365973U, // <4,4,7,6>: Cost 3 vext3 <4,7,6,4>, <4,7,6,4> + 2644121196U, // <4,4,7,7>: Cost 3 vext2 <4,4,4,4>, <7,7,7,7> + 2662036827U, // <4,4,7,u>: Cost 3 vext2 <7,4,4,4>, <7,4,4,4> + 1503297638U, // <4,4,u,0>: Cost 2 vext1 <4,4,4,u>, LHS + 1570379566U, // <4,4,u,1>: Cost 2 vext2 <4,4,4,4>, LHS + 2779682606U, // <4,4,u,2>: Cost 3 vuzpl <4,6,4,6>, LHS + 2571069947U, // <4,4,u,3>: Cost 3 vext1 <3,4,4,u>, <3,4,4,u> + 161926454U, // <4,4,u,4>: Cost 1 vdup0 RHS + 1841638710U, // <4,4,u,5>: Cost 2 vzipl RHS, RHS + 1618169385U, // <4,4,u,6>: Cost 2 vext3 <1,2,3,4>, RHS + 2594960735U, // <4,4,u,7>: Cost 3 vext1 <7,4,4,u>, <7,4,4,u> + 161926454U, // <4,4,u,u>: Cost 1 vdup0 RHS + 2631516160U, // <4,5,0,0>: Cost 3 vext2 <2,3,4,5>, <0,0,0,0> + 1557774438U, // <4,5,0,1>: Cost 2 vext2 <2,3,4,5>, LHS + 2618908875U, // <4,5,0,2>: Cost 3 vext2 <0,2,4,5>, <0,2,4,5> + 2571078140U, // <4,5,0,3>: Cost 3 vext1 <3,4,5,0>, <3,4,5,0> + 2626871634U, // <4,5,0,4>: Cost 3 vext2 <1,5,4,5>, <0,4,1,5> + 3705258414U, // <4,5,0,5>: Cost 4 vext2 <2,3,4,5>, <0,5,2,7> + 2594968438U, // <4,5,0,6>: Cost 3 vext1 <7,4,5,0>, <6,7,4,5> + 2594968928U, // <4,5,0,7>: Cost 3 vext1 <7,4,5,0>, <7,4,5,0> + 1557775005U, // <4,5,0,u>: Cost 2 vext2 <2,3,4,5>, LHS + 2631516918U, // <4,5,1,0>: Cost 3 vext2 <2,3,4,5>, <1,0,3,2> + 2624217939U, // <4,5,1,1>: Cost 3 vext2 <1,1,4,5>, <1,1,4,5> + 2631517078U, // <4,5,1,2>: Cost 3 vext2 <2,3,4,5>, <1,2,3,0> + 2821341286U, // <4,5,1,3>: Cost 3 vuzpr <0,4,1,5>, LHS + 3895086054U, // <4,5,1,4>: Cost 4 vuzpr <0,4,1,5>, <4,1,5,4> + 2626872471U, // <4,5,1,5>: Cost 3 vext2 <1,5,4,5>, <1,5,4,5> + 3895083131U, // <4,5,1,6>: Cost 4 vuzpr <0,4,1,5>, <0,1,4,6> + 2718748368U, // <4,5,1,7>: Cost 3 vext3 <5,6,7,4>, <5,1,7,3> + 2821341291U, // <4,5,1,u>: Cost 3 vuzpr <0,4,1,5>, LHS + 2571092070U, // <4,5,2,0>: Cost 3 vext1 <3,4,5,2>, LHS + 3699287585U, // <4,5,2,1>: Cost 4 vext2 <1,3,4,5>, <2,1,3,3> + 2630854269U, // <4,5,2,2>: Cost 3 vext2 <2,2,4,5>, <2,2,4,5> + 1557776078U, // <4,5,2,3>: Cost 2 vext2 <2,3,4,5>, <2,3,4,5> + 2631517974U, // <4,5,2,4>: Cost 3 vext2 <2,3,4,5>, <2,4,3,5> + 3692652384U, // <4,5,2,5>: Cost 4 vext2 <0,2,4,5>, <2,5,2,7> + 2631518138U, // <4,5,2,6>: Cost 3 vext2 <2,3,4,5>, <2,6,3,7> + 4164013366U, // <4,5,2,7>: Cost 4 vtrnr <0,4,u,2>, RHS + 1561094243U, // <4,5,2,u>: Cost 2 vext2 <2,u,4,5>, <2,u,4,5> + 2631518358U, // <4,5,3,0>: Cost 3 vext2 <2,3,4,5>, <3,0,1,2> + 3895084710U, // <4,5,3,1>: Cost 4 vuzpr <0,4,1,5>, <2,3,0,1> + 2631518540U, // <4,5,3,2>: Cost 3 vext2 <2,3,4,5>, <3,2,3,4> + 2631518620U, // <4,5,3,3>: Cost 3 vext2 <2,3,4,5>, <3,3,3,3> + 2631518716U, // <4,5,3,4>: Cost 3 vext2 <2,3,4,5>, <3,4,5,0> + 2631518784U, // <4,5,3,5>: Cost 3 vext2 <2,3,4,5>, <3,5,3,5> + 2658060980U, // <4,5,3,6>: Cost 3 vext2 <6,7,4,5>, <3,6,7,4> + 2640145131U, // <4,5,3,7>: Cost 3 vext2 <3,7,4,5>, <3,7,4,5> + 2631519006U, // <4,5,3,u>: Cost 3 vext2 <2,3,4,5>, <3,u,1,2> + 2571108454U, // <4,5,4,0>: Cost 3 vext1 <3,4,5,4>, LHS + 3632907342U, // <4,5,4,1>: Cost 4 vext1 <1,4,5,4>, <1,4,5,4> + 2571110094U, // <4,5,4,2>: Cost 3 vext1 <3,4,5,4>, <2,3,4,5> + 2571110912U, // <4,5,4,3>: Cost 3 vext1 <3,4,5,4>, <3,4,5,4> + 2571111734U, // <4,5,4,4>: Cost 3 vext1 <3,4,5,4>, RHS + 1557777718U, // <4,5,4,5>: Cost 2 vext2 <2,3,4,5>, RHS + 2645454195U, // <4,5,4,6>: Cost 3 vext2 <4,6,4,5>, <4,6,4,5> + 2718748614U, // <4,5,4,7>: Cost 3 vext3 <5,6,7,4>, <5,4,7,6> + 1557777961U, // <4,5,4,u>: Cost 2 vext2 <2,3,4,5>, RHS + 1503346790U, // <4,5,5,0>: Cost 2 vext1 <4,4,5,5>, LHS + 2913398480U, // <4,5,5,1>: Cost 3 vzipl RHS, <5,1,7,3> + 2631519998U, // <4,5,5,2>: Cost 3 vext2 <2,3,4,5>, <5,2,3,4> + 2577090710U, // <4,5,5,3>: Cost 3 vext1 <4,4,5,5>, <3,0,1,2> + 1503349978U, // <4,5,5,4>: Cost 2 vext1 <4,4,5,5>, <4,4,5,5> + 2631520260U, // <4,5,5,5>: Cost 3 vext2 <2,3,4,5>, <5,5,5,5> + 2913390690U, // <4,5,5,6>: Cost 3 vzipl RHS, <5,6,7,0> + 2821344566U, // <4,5,5,7>: Cost 3 vuzpr <0,4,1,5>, RHS + 1503352622U, // <4,5,5,u>: Cost 2 vext1 <4,4,5,5>, LHS + 1497383014U, // <4,5,6,0>: Cost 2 vext1 <3,4,5,6>, LHS + 2559181904U, // <4,5,6,1>: Cost 3 vext1 <1,4,5,6>, <1,4,5,6> + 2565154601U, // <4,5,6,2>: Cost 3 vext1 <2,4,5,6>, <2,4,5,6> + 1497385474U, // <4,5,6,3>: Cost 2 vext1 <3,4,5,6>, <3,4,5,6> + 1497386294U, // <4,5,6,4>: Cost 2 vext1 <3,4,5,6>, RHS + 3047608324U, // <4,5,6,5>: Cost 3 vtrnl RHS, <5,5,5,5> + 2571129656U, // <4,5,6,6>: Cost 3 vext1 <3,4,5,6>, <6,6,6,6> + 27705344U, // <4,5,6,7>: Cost 0 copy RHS + 27705344U, // <4,5,6,u>: Cost 0 copy RHS + 2565161062U, // <4,5,7,0>: Cost 3 vext1 <2,4,5,7>, LHS + 2565161882U, // <4,5,7,1>: Cost 3 vext1 <2,4,5,7>, <1,2,3,4> + 2565162794U, // <4,5,7,2>: Cost 3 vext1 <2,4,5,7>, <2,4,5,7> + 2661381387U, // <4,5,7,3>: Cost 3 vext2 <7,3,4,5>, <7,3,4,5> + 2565164342U, // <4,5,7,4>: Cost 3 vext1 <2,4,5,7>, RHS + 2718748840U, // <4,5,7,5>: Cost 3 vext3 <5,6,7,4>, <5,7,5,7> + 2718748846U, // <4,5,7,6>: Cost 3 vext3 <5,6,7,4>, <5,7,6,4> + 2719412407U, // <4,5,7,7>: Cost 3 vext3 <5,7,7,4>, <5,7,7,4> + 2565166894U, // <4,5,7,u>: Cost 3 vext1 <2,4,5,7>, LHS + 1497399398U, // <4,5,u,0>: Cost 2 vext1 <3,4,5,u>, LHS + 1557780270U, // <4,5,u,1>: Cost 2 vext2 <2,3,4,5>, LHS + 2631522181U, // <4,5,u,2>: Cost 3 vext2 <2,3,4,5>, + 1497401860U, // <4,5,u,3>: Cost 2 vext1 <3,4,5,u>, <3,4,5,u> + 1497402678U, // <4,5,u,4>: Cost 2 vext1 <3,4,5,u>, RHS + 1557780634U, // <4,5,u,5>: Cost 2 vext2 <2,3,4,5>, RHS + 2631522512U, // <4,5,u,6>: Cost 3 vext2 <2,3,4,5>, + 27705344U, // <4,5,u,7>: Cost 0 copy RHS + 27705344U, // <4,5,u,u>: Cost 0 copy RHS + 2618916864U, // <4,6,0,0>: Cost 3 vext2 <0,2,4,6>, <0,0,0,0> + 1545175142U, // <4,6,0,1>: Cost 2 vext2 <0,2,4,6>, LHS + 1545175244U, // <4,6,0,2>: Cost 2 vext2 <0,2,4,6>, <0,2,4,6> + 3692658940U, // <4,6,0,3>: Cost 4 vext2 <0,2,4,6>, <0,3,1,0> + 2618917202U, // <4,6,0,4>: Cost 3 vext2 <0,2,4,6>, <0,4,1,5> + 3852910806U, // <4,6,0,5>: Cost 4 vuzpl RHS, <0,2,5,7> + 2253525648U, // <4,6,0,6>: Cost 3 vrev <6,4,6,0> + 4040764726U, // <4,6,0,7>: Cost 4 vzipr <2,3,4,0>, RHS + 1545175709U, // <4,6,0,u>: Cost 2 vext2 <0,2,4,6>, LHS + 2618917622U, // <4,6,1,0>: Cost 3 vext2 <0,2,4,6>, <1,0,3,2> + 2618917684U, // <4,6,1,1>: Cost 3 vext2 <0,2,4,6>, <1,1,1,1> + 2618917782U, // <4,6,1,2>: Cost 3 vext2 <0,2,4,6>, <1,2,3,0> + 2618917848U, // <4,6,1,3>: Cost 3 vext2 <0,2,4,6>, <1,3,1,3> + 3692659773U, // <4,6,1,4>: Cost 4 vext2 <0,2,4,6>, <1,4,3,5> + 2618918032U, // <4,6,1,5>: Cost 3 vext2 <0,2,4,6>, <1,5,3,7> + 3692659937U, // <4,6,1,6>: Cost 4 vext2 <0,2,4,6>, <1,6,3,7> + 4032146742U, // <4,6,1,7>: Cost 4 vzipr <0,u,4,1>, RHS + 2618918253U, // <4,6,1,u>: Cost 3 vext2 <0,2,4,6>, <1,u,1,3> + 2618918380U, // <4,6,2,0>: Cost 3 vext2 <0,2,4,6>, <2,0,6,4> + 2618918460U, // <4,6,2,1>: Cost 3 vext2 <0,2,4,6>, <2,1,6,3> + 2618918504U, // <4,6,2,2>: Cost 3 vext2 <0,2,4,6>, <2,2,2,2> + 2618918566U, // <4,6,2,3>: Cost 3 vext2 <0,2,4,6>, <2,3,0,1> + 2618918679U, // <4,6,2,4>: Cost 3 vext2 <0,2,4,6>, <2,4,3,6> + 2618918788U, // <4,6,2,5>: Cost 3 vext2 <0,2,4,6>, <2,5,6,7> + 2618918842U, // <4,6,2,6>: Cost 3 vext2 <0,2,4,6>, <2,6,3,7> + 2718749178U, // <4,6,2,7>: Cost 3 vext3 <5,6,7,4>, <6,2,7,3> + 2618918971U, // <4,6,2,u>: Cost 3 vext2 <0,2,4,6>, <2,u,0,1> + 2618919062U, // <4,6,3,0>: Cost 3 vext2 <0,2,4,6>, <3,0,1,2> + 2636171526U, // <4,6,3,1>: Cost 3 vext2 <3,1,4,6>, <3,1,4,6> + 3692661057U, // <4,6,3,2>: Cost 4 vext2 <0,2,4,6>, <3,2,2,2> + 2618919324U, // <4,6,3,3>: Cost 3 vext2 <0,2,4,6>, <3,3,3,3> + 2618919426U, // <4,6,3,4>: Cost 3 vext2 <0,2,4,6>, <3,4,5,6> + 2638826058U, // <4,6,3,5>: Cost 3 vext2 <3,5,4,6>, <3,5,4,6> + 3913303030U, // <4,6,3,6>: Cost 4 vuzpr <3,4,5,6>, <1,3,4,6> + 2722730572U, // <4,6,3,7>: Cost 3 vext3 <6,3,7,4>, <6,3,7,4> + 2618919710U, // <4,6,3,u>: Cost 3 vext2 <0,2,4,6>, <3,u,1,2> + 2565210214U, // <4,6,4,0>: Cost 3 vext1 <2,4,6,4>, LHS + 2718749286U, // <4,6,4,1>: Cost 3 vext3 <5,6,7,4>, <6,4,1,3> + 2565211952U, // <4,6,4,2>: Cost 3 vext1 <2,4,6,4>, <2,4,6,4> + 2571184649U, // <4,6,4,3>: Cost 3 vext1 <3,4,6,4>, <3,4,6,4> + 2565213494U, // <4,6,4,4>: Cost 3 vext1 <2,4,6,4>, RHS + 1545178422U, // <4,6,4,5>: Cost 2 vext2 <0,2,4,6>, RHS + 1705430326U, // <4,6,4,6>: Cost 2 vuzpl RHS, RHS + 2595075437U, // <4,6,4,7>: Cost 3 vext1 <7,4,6,4>, <7,4,6,4> + 1545178665U, // <4,6,4,u>: Cost 2 vext2 <0,2,4,6>, RHS + 2565218406U, // <4,6,5,0>: Cost 3 vext1 <2,4,6,5>, LHS + 2645462736U, // <4,6,5,1>: Cost 3 vext2 <4,6,4,6>, <5,1,7,3> + 2913399290U, // <4,6,5,2>: Cost 3 vzipl RHS, <6,2,7,3> + 3913305394U, // <4,6,5,3>: Cost 4 vuzpr <3,4,5,6>, <4,5,6,3> + 2645462982U, // <4,6,5,4>: Cost 3 vext2 <4,6,4,6>, <5,4,7,6> + 2779172868U, // <4,6,5,5>: Cost 3 vuzpl RHS, <5,5,5,5> + 2913391416U, // <4,6,5,6>: Cost 3 vzipl RHS, <6,6,6,6> + 2821426486U, // <4,6,5,7>: Cost 3 vuzpr <0,4,2,6>, RHS + 2821426487U, // <4,6,5,u>: Cost 3 vuzpr <0,4,2,6>, RHS + 1503428710U, // <4,6,6,0>: Cost 2 vext1 <4,4,6,6>, LHS + 2577171190U, // <4,6,6,1>: Cost 3 vext1 <4,4,6,6>, <1,0,3,2> + 2645463546U, // <4,6,6,2>: Cost 3 vext2 <4,6,4,6>, <6,2,7,3> + 2577172630U, // <4,6,6,3>: Cost 3 vext1 <4,4,6,6>, <3,0,1,2> + 1503431908U, // <4,6,6,4>: Cost 2 vext1 <4,4,6,6>, <4,4,6,6> + 2253501069U, // <4,6,6,5>: Cost 3 vrev <6,4,5,6> + 2618921784U, // <4,6,6,6>: Cost 3 vext2 <0,2,4,6>, <6,6,6,6> + 2954464566U, // <4,6,6,7>: Cost 3 vzipr <0,2,4,6>, RHS + 1503434542U, // <4,6,6,u>: Cost 2 vext1 <4,4,6,6>, LHS + 2645464058U, // <4,6,7,0>: Cost 3 vext2 <4,6,4,6>, <7,0,1,2> + 2779173882U, // <4,6,7,1>: Cost 3 vuzpl RHS, <7,0,1,2> + 3638978355U, // <4,6,7,2>: Cost 4 vext1 <2,4,6,7>, <2,4,6,7> + 2725090156U, // <4,6,7,3>: Cost 3 vext3 <6,7,3,4>, <6,7,3,4> + 2645464422U, // <4,6,7,4>: Cost 3 vext2 <4,6,4,6>, <7,4,5,6> + 2779174246U, // <4,6,7,5>: Cost 3 vuzpl RHS, <7,4,5,6> + 3852915914U, // <4,6,7,6>: Cost 4 vuzpl RHS, <7,2,6,3> + 2779174508U, // <4,6,7,7>: Cost 3 vuzpl RHS, <7,7,7,7> + 2779173945U, // <4,6,7,u>: Cost 3 vuzpl RHS, <7,0,u,2> + 1503445094U, // <4,6,u,0>: Cost 2 vext1 <4,4,6,u>, LHS + 1545180974U, // <4,6,u,1>: Cost 2 vext2 <0,2,4,6>, LHS + 1705432878U, // <4,6,u,2>: Cost 2 vuzpl RHS, LHS + 2618922940U, // <4,6,u,3>: Cost 3 vext2 <0,2,4,6>, + 1503448294U, // <4,6,u,4>: Cost 2 vext1 <4,4,6,u>, <4,4,6,u> + 1545181338U, // <4,6,u,5>: Cost 2 vext2 <0,2,4,6>, RHS + 1705433242U, // <4,6,u,6>: Cost 2 vuzpl RHS, RHS + 2954480950U, // <4,6,u,7>: Cost 3 vzipr <0,2,4,u>, RHS + 1545181541U, // <4,6,u,u>: Cost 2 vext2 <0,2,4,6>, LHS + 3706601472U, // <4,7,0,0>: Cost 4 vext2 <2,5,4,7>, <0,0,0,0> + 2632859750U, // <4,7,0,1>: Cost 3 vext2 <2,5,4,7>, LHS + 2726343685U, // <4,7,0,2>: Cost 3 vext3 <7,0,2,4>, <7,0,2,4> + 3701293312U, // <4,7,0,3>: Cost 4 vext2 <1,6,4,7>, <0,3,1,4> + 3706601810U, // <4,7,0,4>: Cost 4 vext2 <2,5,4,7>, <0,4,1,5> + 2259424608U, // <4,7,0,5>: Cost 3 vrev <7,4,5,0> + 3695321617U, // <4,7,0,6>: Cost 4 vext2 <0,6,4,7>, <0,6,4,7> + 3800454194U, // <4,7,0,7>: Cost 4 vext3 <7,0,7,4>, <7,0,7,4> + 2632860317U, // <4,7,0,u>: Cost 3 vext2 <2,5,4,7>, LHS + 2259064116U, // <4,7,1,0>: Cost 3 vrev <7,4,0,1> + 3700630324U, // <4,7,1,1>: Cost 4 vext2 <1,5,4,7>, <1,1,1,1> + 2632860570U, // <4,7,1,2>: Cost 3 vext2 <2,5,4,7>, <1,2,3,4> + 3769635936U, // <4,7,1,3>: Cost 4 vext3 <1,u,3,4>, <7,1,3,5> + 3656920374U, // <4,7,1,4>: Cost 4 vext1 <5,4,7,1>, RHS + 3700630681U, // <4,7,1,5>: Cost 4 vext2 <1,5,4,7>, <1,5,4,7> + 3701294314U, // <4,7,1,6>: Cost 4 vext2 <1,6,4,7>, <1,6,4,7> + 3793818754U, // <4,7,1,7>: Cost 4 vext3 <5,u,7,4>, <7,1,7,3> + 2259654012U, // <4,7,1,u>: Cost 3 vrev <7,4,u,1> + 3656925286U, // <4,7,2,0>: Cost 4 vext1 <5,4,7,2>, LHS + 3706603050U, // <4,7,2,1>: Cost 4 vext2 <2,5,4,7>, <2,1,4,3> + 3706603112U, // <4,7,2,2>: Cost 4 vext2 <2,5,4,7>, <2,2,2,2> + 2727744688U, // <4,7,2,3>: Cost 3 vext3 <7,2,3,4>, <7,2,3,4> + 3705939745U, // <4,7,2,4>: Cost 4 vext2 <2,4,4,7>, <2,4,4,7> + 2632861554U, // <4,7,2,5>: Cost 3 vext2 <2,5,4,7>, <2,5,4,7> + 3706603450U, // <4,7,2,6>: Cost 4 vext2 <2,5,4,7>, <2,6,3,7> + 3792491731U, // <4,7,2,7>: Cost 4 vext3 <5,6,7,4>, <7,2,7,3> + 2634852453U, // <4,7,2,u>: Cost 3 vext2 <2,u,4,7>, <2,u,4,7> + 3706603670U, // <4,7,3,0>: Cost 4 vext2 <2,5,4,7>, <3,0,1,2> + 3662906266U, // <4,7,3,1>: Cost 4 vext1 <6,4,7,3>, <1,2,3,4> + 3725183326U, // <4,7,3,2>: Cost 4 vext2 <5,6,4,7>, <3,2,5,4> + 3706603932U, // <4,7,3,3>: Cost 4 vext2 <2,5,4,7>, <3,3,3,3> + 3701295618U, // <4,7,3,4>: Cost 4 vext2 <1,6,4,7>, <3,4,5,6> + 2638834251U, // <4,7,3,5>: Cost 3 vext2 <3,5,4,7>, <3,5,4,7> + 2639497884U, // <4,7,3,6>: Cost 3 vext2 <3,6,4,7>, <3,6,4,7> + 3802445093U, // <4,7,3,7>: Cost 4 vext3 <7,3,7,4>, <7,3,7,4> + 2640825150U, // <4,7,3,u>: Cost 3 vext2 <3,u,4,7>, <3,u,4,7> + 2718750004U, // <4,7,4,0>: Cost 3 vext3 <5,6,7,4>, <7,4,0,1> + 3706604490U, // <4,7,4,1>: Cost 4 vext2 <2,5,4,7>, <4,1,2,3> + 3656943474U, // <4,7,4,2>: Cost 4 vext1 <5,4,7,4>, <2,5,4,7> + 3779884371U, // <4,7,4,3>: Cost 4 vext3 <3,5,7,4>, <7,4,3,5> + 2259383643U, // <4,7,4,4>: Cost 3 vrev <7,4,4,4> + 2632863030U, // <4,7,4,5>: Cost 3 vext2 <2,5,4,7>, RHS + 2259531117U, // <4,7,4,6>: Cost 3 vrev <7,4,6,4> + 3907340074U, // <4,7,4,7>: Cost 4 vuzpr <2,4,5,7>, <2,4,5,7> + 2632863273U, // <4,7,4,u>: Cost 3 vext2 <2,5,4,7>, RHS + 2913391610U, // <4,7,5,0>: Cost 3 vzipl RHS, <7,0,1,2> + 3645006848U, // <4,7,5,1>: Cost 4 vext1 <3,4,7,5>, <1,3,5,7> + 2589181646U, // <4,7,5,2>: Cost 3 vext1 <6,4,7,5>, <2,3,4,5> + 3645008403U, // <4,7,5,3>: Cost 4 vext1 <3,4,7,5>, <3,4,7,5> + 2913391974U, // <4,7,5,4>: Cost 3 vzipl RHS, <7,4,5,6> + 2583211973U, // <4,7,5,5>: Cost 3 vext1 <5,4,7,5>, <5,4,7,5> + 2589184670U, // <4,7,5,6>: Cost 3 vext1 <6,4,7,5>, <6,4,7,5> + 2913392236U, // <4,7,5,7>: Cost 3 vzipl RHS, <7,7,7,7> + 2913392258U, // <4,7,5,u>: Cost 3 vzipl RHS, <7,u,1,2> + 1509474406U, // <4,7,6,0>: Cost 2 vext1 <5,4,7,6>, LHS + 3047609338U, // <4,7,6,1>: Cost 3 vtrnl RHS, <7,0,1,2> + 2583217768U, // <4,7,6,2>: Cost 3 vext1 <5,4,7,6>, <2,2,2,2> + 2583218326U, // <4,7,6,3>: Cost 3 vext1 <5,4,7,6>, <3,0,1,2> + 1509477686U, // <4,7,6,4>: Cost 2 vext1 <5,4,7,6>, RHS + 1509478342U, // <4,7,6,5>: Cost 2 vext1 <5,4,7,6>, <5,4,7,6> + 2583220730U, // <4,7,6,6>: Cost 3 vext1 <5,4,7,6>, <6,2,7,3> + 3047609964U, // <4,7,6,7>: Cost 3 vtrnl RHS, <7,7,7,7> + 1509480238U, // <4,7,6,u>: Cost 2 vext1 <5,4,7,6>, LHS + 3650994278U, // <4,7,7,0>: Cost 4 vext1 <4,4,7,7>, LHS + 3650995098U, // <4,7,7,1>: Cost 4 vext1 <4,4,7,7>, <1,2,3,4> + 3650996010U, // <4,7,7,2>: Cost 4 vext1 <4,4,7,7>, <2,4,5,7> + 3804804677U, // <4,7,7,3>: Cost 4 vext3 <7,7,3,4>, <7,7,3,4> + 3650997486U, // <4,7,7,4>: Cost 4 vext1 <4,4,7,7>, <4,4,7,7> + 2662725039U, // <4,7,7,5>: Cost 3 vext2 <7,5,4,7>, <7,5,4,7> + 3662942880U, // <4,7,7,6>: Cost 4 vext1 <6,4,7,7>, <6,4,7,7> + 2718750316U, // <4,7,7,7>: Cost 3 vext3 <5,6,7,4>, <7,7,7,7> + 2664715938U, // <4,7,7,u>: Cost 3 vext2 <7,u,4,7>, <7,u,4,7> + 1509490790U, // <4,7,u,0>: Cost 2 vext1 <5,4,7,u>, LHS + 2632865582U, // <4,7,u,1>: Cost 3 vext2 <2,5,4,7>, LHS + 2583234152U, // <4,7,u,2>: Cost 3 vext1 <5,4,7,u>, <2,2,2,2> + 2583234710U, // <4,7,u,3>: Cost 3 vext1 <5,4,7,u>, <3,0,1,2> + 1509494070U, // <4,7,u,4>: Cost 2 vext1 <5,4,7,u>, RHS + 1509494728U, // <4,7,u,5>: Cost 2 vext1 <5,4,7,u>, <5,4,7,u> + 2583237114U, // <4,7,u,6>: Cost 3 vext1 <5,4,7,u>, <6,2,7,3> + 3047757420U, // <4,7,u,7>: Cost 3 vtrnl RHS, <7,7,7,7> + 1509496622U, // <4,7,u,u>: Cost 2 vext1 <5,4,7,u>, LHS + 2618933248U, // <4,u,0,0>: Cost 3 vext2 <0,2,4,u>, <0,0,0,0> + 1545191526U, // <4,u,0,1>: Cost 2 vext2 <0,2,4,u>, LHS + 1545191630U, // <4,u,0,2>: Cost 2 vext2 <0,2,4,u>, <0,2,4,u> + 2691913445U, // <4,u,0,3>: Cost 3 vext3 <1,2,3,4>, + 2618933586U, // <4,u,0,4>: Cost 3 vext2 <0,2,4,u>, <0,4,1,5> + 2265397305U, // <4,u,0,5>: Cost 3 vrev + 2595189625U, // <4,u,0,6>: Cost 3 vext1 <7,4,u,0>, <6,7,4,u> + 2595190139U, // <4,u,0,7>: Cost 3 vext1 <7,4,u,0>, <7,4,u,0> + 1545192093U, // <4,u,0,u>: Cost 2 vext2 <0,2,4,u>, LHS + 2618934006U, // <4,u,1,0>: Cost 3 vext2 <0,2,4,u>, <1,0,3,2> + 2618934068U, // <4,u,1,1>: Cost 3 vext2 <0,2,4,u>, <1,1,1,1> + 1618171694U, // <4,u,1,2>: Cost 2 vext3 <1,2,3,4>, LHS + 2618934232U, // <4,u,1,3>: Cost 3 vext2 <0,2,4,u>, <1,3,1,3> + 2695894848U, // <4,u,1,4>: Cost 3 vext3 <1,u,3,4>, + 2618934416U, // <4,u,1,5>: Cost 3 vext2 <0,2,4,u>, <1,5,3,7> + 3692676321U, // <4,u,1,6>: Cost 4 vext2 <0,2,4,u>, <1,6,3,7> + 2718750555U, // <4,u,1,7>: Cost 3 vext3 <5,6,7,4>, + 1618171748U, // <4,u,1,u>: Cost 2 vext3 <1,2,3,4>, LHS + 2553397350U, // <4,u,2,0>: Cost 3 vext1 <0,4,u,2>, LHS + 2630215215U, // <4,u,2,1>: Cost 3 vext2 <2,1,4,u>, <2,1,4,u> + 2618934888U, // <4,u,2,2>: Cost 3 vext2 <0,2,4,u>, <2,2,2,2> + 1557800657U, // <4,u,2,3>: Cost 2 vext2 <2,3,4,u>, <2,3,4,u> + 2618935065U, // <4,u,2,4>: Cost 3 vext2 <0,2,4,u>, <2,4,3,u> + 2733864859U, // <4,u,2,5>: Cost 3 vext3 , + 2618935226U, // <4,u,2,6>: Cost 3 vext2 <0,2,4,u>, <2,6,3,7> + 2718750636U, // <4,u,2,7>: Cost 3 vext3 <5,6,7,4>, + 1561118822U, // <4,u,2,u>: Cost 2 vext2 <2,u,4,u>, <2,u,4,u> + 2618935446U, // <4,u,3,0>: Cost 3 vext2 <0,2,4,u>, <3,0,1,2> + 2779318422U, // <4,u,3,1>: Cost 3 vuzpl RHS, <3,0,1,2> + 2636851545U, // <4,u,3,2>: Cost 3 vext2 <3,2,4,u>, <3,2,4,u> + 2618935708U, // <4,u,3,3>: Cost 3 vext2 <0,2,4,u>, <3,3,3,3> + 2618935810U, // <4,u,3,4>: Cost 3 vext2 <0,2,4,u>, <3,4,5,6> + 2691913711U, // <4,u,3,5>: Cost 3 vext3 <1,2,3,4>, + 2588725862U, // <4,u,3,6>: Cost 3 vext1 <6,4,1,3>, <6,4,1,3> + 2640169710U, // <4,u,3,7>: Cost 3 vext2 <3,7,4,u>, <3,7,4,u> + 2618936094U, // <4,u,3,u>: Cost 3 vext2 <0,2,4,u>, <3,u,1,2> + 1503559782U, // <4,u,4,0>: Cost 2 vext1 <4,4,u,4>, LHS + 2692282391U, // <4,u,4,1>: Cost 3 vext3 <1,2,u,4>, + 2565359426U, // <4,u,4,2>: Cost 3 vext1 <2,4,u,4>, <2,4,u,4> + 2571332123U, // <4,u,4,3>: Cost 3 vext1 <3,4,u,4>, <3,4,u,4> + 161926454U, // <4,u,4,4>: Cost 1 vdup0 RHS + 1545194806U, // <4,u,4,5>: Cost 2 vext2 <0,2,4,u>, RHS + 1705577782U, // <4,u,4,6>: Cost 2 vuzpl RHS, RHS + 2718750801U, // <4,u,4,7>: Cost 3 vext3 <5,6,7,4>, + 161926454U, // <4,u,4,u>: Cost 1 vdup0 RHS + 1479164006U, // <4,u,5,0>: Cost 2 vext1 <0,4,1,5>, LHS + 1839650606U, // <4,u,5,1>: Cost 2 vzipl RHS, LHS + 2565367502U, // <4,u,5,2>: Cost 3 vext1 <2,4,u,5>, <2,3,4,5> + 3089777309U, // <4,u,5,3>: Cost 3 vtrnr <0,4,1,5>, LHS + 1479167286U, // <4,u,5,4>: Cost 2 vext1 <0,4,1,5>, RHS + 1839650970U, // <4,u,5,5>: Cost 2 vzipl RHS, RHS + 1618172058U, // <4,u,5,6>: Cost 2 vext3 <1,2,3,4>, RHS + 3089780265U, // <4,u,5,7>: Cost 3 vtrnr <0,4,1,5>, RHS + 1618172076U, // <4,u,5,u>: Cost 2 vext3 <1,2,3,4>, RHS + 1479688294U, // <4,u,6,0>: Cost 2 vext1 <0,4,u,6>, LHS + 2553430774U, // <4,u,6,1>: Cost 3 vext1 <0,4,u,6>, <1,0,3,2> + 1973868334U, // <4,u,6,2>: Cost 2 vtrnl RHS, LHS + 1497606685U, // <4,u,6,3>: Cost 2 vext1 <3,4,u,6>, <3,4,u,6> + 1479691574U, // <4,u,6,4>: Cost 2 vext1 <0,4,u,6>, RHS + 1509552079U, // <4,u,6,5>: Cost 2 vext1 <5,4,u,6>, <5,4,u,6> + 1973868698U, // <4,u,6,6>: Cost 2 vtrnl RHS, RHS + 27705344U, // <4,u,6,7>: Cost 0 copy RHS + 27705344U, // <4,u,6,u>: Cost 0 copy RHS + 2565382246U, // <4,u,7,0>: Cost 3 vext1 <2,4,u,7>, LHS + 2565383066U, // <4,u,7,1>: Cost 3 vext1 <2,4,u,7>, <1,2,3,4> + 2565384005U, // <4,u,7,2>: Cost 3 vext1 <2,4,u,7>, <2,4,u,7> + 2661405966U, // <4,u,7,3>: Cost 3 vext2 <7,3,4,u>, <7,3,4,u> + 2565385526U, // <4,u,7,4>: Cost 3 vext1 <2,4,u,7>, RHS + 2779321702U, // <4,u,7,5>: Cost 3 vuzpl RHS, <7,4,5,6> + 2589274793U, // <4,u,7,6>: Cost 3 vext1 <6,4,u,7>, <6,4,u,7> + 2779321964U, // <4,u,7,7>: Cost 3 vuzpl RHS, <7,7,7,7> + 2565388078U, // <4,u,7,u>: Cost 3 vext1 <2,4,u,7>, LHS + 1479704678U, // <4,u,u,0>: Cost 2 vext1 <0,4,u,u>, LHS + 1545197358U, // <4,u,u,1>: Cost 2 vext2 <0,2,4,u>, LHS + 1618172261U, // <4,u,u,2>: Cost 2 vext3 <1,2,3,4>, LHS + 1497623071U, // <4,u,u,3>: Cost 2 vext1 <3,4,u,u>, <3,4,u,u> + 161926454U, // <4,u,u,4>: Cost 1 vdup0 RHS + 1545197722U, // <4,u,u,5>: Cost 2 vext2 <0,2,4,u>, RHS + 1618172301U, // <4,u,u,6>: Cost 2 vext3 <1,2,3,4>, RHS + 27705344U, // <4,u,u,7>: Cost 0 copy RHS + 27705344U, // <4,u,u,u>: Cost 0 copy RHS + 2687123456U, // <5,0,0,0>: Cost 3 vext3 <0,4,1,5>, <0,0,0,0> + 2687123466U, // <5,0,0,1>: Cost 3 vext3 <0,4,1,5>, <0,0,1,1> + 2687123476U, // <5,0,0,2>: Cost 3 vext3 <0,4,1,5>, <0,0,2,2> + 3710599434U, // <5,0,0,3>: Cost 4 vext2 <3,2,5,0>, <0,3,2,5> + 2642166098U, // <5,0,0,4>: Cost 3 vext2 <4,1,5,0>, <0,4,1,5> + 3657060306U, // <5,0,0,5>: Cost 4 vext1 <5,5,0,0>, <5,5,0,0> + 3292094923U, // <5,0,0,6>: Cost 4 vrev <0,5,6,0> + 3669005700U, // <5,0,0,7>: Cost 4 vext1 <7,5,0,0>, <7,5,0,0> + 2687123530U, // <5,0,0,u>: Cost 3 vext3 <0,4,1,5>, <0,0,u,2> + 2559434854U, // <5,0,1,0>: Cost 3 vext1 <1,5,0,1>, LHS + 2559435887U, // <5,0,1,1>: Cost 3 vext1 <1,5,0,1>, <1,5,0,1> + 1613381734U, // <5,0,1,2>: Cost 2 vext3 <0,4,1,5>, LHS + 3698656256U, // <5,0,1,3>: Cost 4 vext2 <1,2,5,0>, <1,3,5,7> + 2559438134U, // <5,0,1,4>: Cost 3 vext1 <1,5,0,1>, RHS + 2583326675U, // <5,0,1,5>: Cost 3 vext1 <5,5,0,1>, <5,5,0,1> + 3715908851U, // <5,0,1,6>: Cost 4 vext2 <4,1,5,0>, <1,6,5,7> + 3657069562U, // <5,0,1,7>: Cost 4 vext1 <5,5,0,1>, <7,0,1,2> + 1613381788U, // <5,0,1,u>: Cost 2 vext3 <0,4,1,5>, LHS + 2686017700U, // <5,0,2,0>: Cost 3 vext3 <0,2,4,5>, <0,2,0,2> + 2685796528U, // <5,0,2,1>: Cost 3 vext3 <0,2,1,5>, <0,2,1,5> + 2698625208U, // <5,0,2,2>: Cost 3 vext3 <2,3,4,5>, <0,2,2,4> + 2685944002U, // <5,0,2,3>: Cost 3 vext3 <0,2,3,5>, <0,2,3,5> + 2686017739U, // <5,0,2,4>: Cost 3 vext3 <0,2,4,5>, <0,2,4,5> + 2686091476U, // <5,0,2,5>: Cost 3 vext3 <0,2,5,5>, <0,2,5,5> + 2725167324U, // <5,0,2,6>: Cost 3 vext3 <6,7,4,5>, <0,2,6,4> + 2595280230U, // <5,0,2,7>: Cost 3 vext1 <7,5,0,2>, <7,4,5,6> + 2686312687U, // <5,0,2,u>: Cost 3 vext3 <0,2,u,5>, <0,2,u,5> + 3760128248U, // <5,0,3,0>: Cost 4 vext3 <0,3,0,5>, <0,3,0,5> + 3759685888U, // <5,0,3,1>: Cost 4 vext3 <0,2,3,5>, <0,3,1,4> + 2686533898U, // <5,0,3,2>: Cost 3 vext3 <0,3,2,5>, <0,3,2,5> + 3760349459U, // <5,0,3,3>: Cost 4 vext3 <0,3,3,5>, <0,3,3,5> + 2638187004U, // <5,0,3,4>: Cost 3 vext2 <3,4,5,0>, <3,4,5,0> + 3776348452U, // <5,0,3,5>: Cost 4 vext3 <3,0,4,5>, <0,3,5,4> + 3713256094U, // <5,0,3,6>: Cost 4 vext2 <3,6,5,0>, <3,6,5,0> + 3914064896U, // <5,0,3,7>: Cost 4 vuzpr <3,5,7,0>, <1,3,5,7> + 2686976320U, // <5,0,3,u>: Cost 3 vext3 <0,3,u,5>, <0,3,u,5> + 2559459430U, // <5,0,4,0>: Cost 3 vext1 <1,5,0,4>, LHS + 1613381970U, // <5,0,4,1>: Cost 2 vext3 <0,4,1,5>, <0,4,1,5> + 2687123804U, // <5,0,4,2>: Cost 3 vext3 <0,4,1,5>, <0,4,2,6> + 3761013092U, // <5,0,4,3>: Cost 4 vext3 <0,4,3,5>, <0,4,3,5> + 2559462710U, // <5,0,4,4>: Cost 3 vext1 <1,5,0,4>, RHS + 2638187830U, // <5,0,4,5>: Cost 3 vext2 <3,4,5,0>, RHS + 3761234303U, // <5,0,4,6>: Cost 4 vext3 <0,4,6,5>, <0,4,6,5> + 2646150600U, // <5,0,4,7>: Cost 3 vext2 <4,7,5,0>, <4,7,5,0> + 1613381970U, // <5,0,4,u>: Cost 2 vext3 <0,4,1,5>, <0,4,1,5> + 3766763926U, // <5,0,5,0>: Cost 4 vext3 <1,4,0,5>, <0,5,0,1> + 2919268454U, // <5,0,5,1>: Cost 3 vzipl <5,5,5,5>, LHS + 3053486182U, // <5,0,5,2>: Cost 3 vtrnl <5,5,5,5>, LHS + 3723210589U, // <5,0,5,3>: Cost 4 vext2 <5,3,5,0>, <5,3,5,0> + 3766763966U, // <5,0,5,4>: Cost 4 vext3 <1,4,0,5>, <0,5,4,5> + 2650796031U, // <5,0,5,5>: Cost 3 vext2 <5,5,5,0>, <5,5,5,0> + 3719893090U, // <5,0,5,6>: Cost 4 vext2 <4,7,5,0>, <5,6,7,0> + 3914067254U, // <5,0,5,7>: Cost 4 vuzpr <3,5,7,0>, RHS + 2919269021U, // <5,0,5,u>: Cost 3 vzipl <5,5,5,5>, LHS + 4047519744U, // <5,0,6,0>: Cost 4 vzipr <3,4,5,6>, <0,0,0,0> + 2920038502U, // <5,0,6,1>: Cost 3 vzipl <5,6,7,0>, LHS + 3759759871U, // <5,0,6,2>: Cost 4 vext3 <0,2,4,5>, <0,6,2,7> + 3645164070U, // <5,0,6,3>: Cost 4 vext1 <3,5,0,6>, <3,5,0,6> + 3762414095U, // <5,0,6,4>: Cost 4 vext3 <0,6,4,5>, <0,6,4,5> + 3993780690U, // <5,0,6,5>: Cost 4 vzipl <5,6,7,0>, <0,5,6,7> + 3719893816U, // <5,0,6,6>: Cost 4 vext2 <4,7,5,0>, <6,6,6,6> + 2662077302U, // <5,0,6,7>: Cost 3 vext2 <7,4,5,0>, <6,7,4,5> + 2920039069U, // <5,0,6,u>: Cost 3 vzipl <5,6,7,0>, LHS + 2565455974U, // <5,0,7,0>: Cost 3 vext1 <2,5,0,7>, LHS + 2565456790U, // <5,0,7,1>: Cost 3 vext1 <2,5,0,7>, <1,2,3,0> + 2565457742U, // <5,0,7,2>: Cost 3 vext1 <2,5,0,7>, <2,5,0,7> + 3639199894U, // <5,0,7,3>: Cost 4 vext1 <2,5,0,7>, <3,0,1,2> + 2565459254U, // <5,0,7,4>: Cost 3 vext1 <2,5,0,7>, RHS + 2589347938U, // <5,0,7,5>: Cost 3 vext1 <6,5,0,7>, <5,6,7,0> + 2589348530U, // <5,0,7,6>: Cost 3 vext1 <6,5,0,7>, <6,5,0,7> + 4188456422U, // <5,0,7,7>: Cost 4 vtrnr RHS, <2,0,5,7> + 2565461806U, // <5,0,7,u>: Cost 3 vext1 <2,5,0,7>, LHS + 2687124106U, // <5,0,u,0>: Cost 3 vext3 <0,4,1,5>, <0,u,0,2> + 1616036502U, // <5,0,u,1>: Cost 2 vext3 <0,u,1,5>, <0,u,1,5> + 1613382301U, // <5,0,u,2>: Cost 2 vext3 <0,4,1,5>, LHS + 2689925800U, // <5,0,u,3>: Cost 3 vext3 <0,u,3,5>, <0,u,3,5> + 2687124146U, // <5,0,u,4>: Cost 3 vext3 <0,4,1,5>, <0,u,4,6> + 2638190746U, // <5,0,u,5>: Cost 3 vext2 <3,4,5,0>, RHS + 2589356723U, // <5,0,u,6>: Cost 3 vext1 <6,5,0,u>, <6,5,0,u> + 2595280230U, // <5,0,u,7>: Cost 3 vext1 <7,5,0,2>, <7,4,5,6> + 1613382355U, // <5,0,u,u>: Cost 2 vext3 <0,4,1,5>, LHS + 2646818816U, // <5,1,0,0>: Cost 3 vext2 <4,u,5,1>, <0,0,0,0> + 1573077094U, // <5,1,0,1>: Cost 2 vext2 <4,u,5,1>, LHS + 2646818980U, // <5,1,0,2>: Cost 3 vext2 <4,u,5,1>, <0,2,0,2> + 2687124214U, // <5,1,0,3>: Cost 3 vext3 <0,4,1,5>, <1,0,3,2> + 2641510738U, // <5,1,0,4>: Cost 3 vext2 <4,0,5,1>, <0,4,1,5> + 2641510814U, // <5,1,0,5>: Cost 3 vext2 <4,0,5,1>, <0,5,1,0> + 3720561142U, // <5,1,0,6>: Cost 4 vext2 <4,u,5,1>, <0,6,1,7> + 3298141357U, // <5,1,0,7>: Cost 4 vrev <1,5,7,0> + 1573077661U, // <5,1,0,u>: Cost 2 vext2 <4,u,5,1>, LHS + 2223891567U, // <5,1,1,0>: Cost 3 vrev <1,5,0,1> + 2687124276U, // <5,1,1,1>: Cost 3 vext3 <0,4,1,5>, <1,1,1,1> + 2646819734U, // <5,1,1,2>: Cost 3 vext2 <4,u,5,1>, <1,2,3,0> + 2687124296U, // <5,1,1,3>: Cost 3 vext3 <0,4,1,5>, <1,1,3,3> + 2691326803U, // <5,1,1,4>: Cost 3 vext3 <1,1,4,5>, <1,1,4,5> + 2691400540U, // <5,1,1,5>: Cost 3 vext3 <1,1,5,5>, <1,1,5,5> + 3765216101U, // <5,1,1,6>: Cost 4 vext3 <1,1,6,5>, <1,1,6,5> + 3765289838U, // <5,1,1,7>: Cost 4 vext3 <1,1,7,5>, <1,1,7,5> + 2687124341U, // <5,1,1,u>: Cost 3 vext3 <0,4,1,5>, <1,1,u,3> + 3297641584U, // <5,1,2,0>: Cost 4 vrev <1,5,0,2> + 3763520391U, // <5,1,2,1>: Cost 4 vext3 <0,u,1,5>, <1,2,1,3> + 2646820456U, // <5,1,2,2>: Cost 3 vext2 <4,u,5,1>, <2,2,2,2> + 2687124374U, // <5,1,2,3>: Cost 3 vext3 <0,4,1,5>, <1,2,3,0> + 2691990436U, // <5,1,2,4>: Cost 3 vext3 <1,2,4,5>, <1,2,4,5> + 2687124395U, // <5,1,2,5>: Cost 3 vext3 <0,4,1,5>, <1,2,5,3> + 2646820794U, // <5,1,2,6>: Cost 3 vext2 <4,u,5,1>, <2,6,3,7> + 3808199610U, // <5,1,2,7>: Cost 4 vext3 , <1,2,7,0> + 2687124419U, // <5,1,2,u>: Cost 3 vext3 <0,4,1,5>, <1,2,u,0> + 2577440870U, // <5,1,3,0>: Cost 3 vext1 <4,5,1,3>, LHS + 2687124440U, // <5,1,3,1>: Cost 3 vext3 <0,4,1,5>, <1,3,1,3> + 3759686627U, // <5,1,3,2>: Cost 4 vext3 <0,2,3,5>, <1,3,2,5> + 2692580332U, // <5,1,3,3>: Cost 3 vext3 <1,3,3,5>, <1,3,3,5> + 2687124469U, // <5,1,3,4>: Cost 3 vext3 <0,4,1,5>, <1,3,4,5> + 2685207552U, // <5,1,3,5>: Cost 3 vext3 <0,1,2,5>, <1,3,5,7> + 3760866313U, // <5,1,3,6>: Cost 4 vext3 <0,4,1,5>, <1,3,6,7> + 2692875280U, // <5,1,3,7>: Cost 3 vext3 <1,3,7,5>, <1,3,7,5> + 2687124503U, // <5,1,3,u>: Cost 3 vext3 <0,4,1,5>, <1,3,u,3> + 1567771538U, // <5,1,4,0>: Cost 2 vext2 <4,0,5,1>, <4,0,5,1> + 2693096491U, // <5,1,4,1>: Cost 3 vext3 <1,4,1,5>, <1,4,1,5> + 2693170228U, // <5,1,4,2>: Cost 3 vext3 <1,4,2,5>, <1,4,2,5> + 2687124541U, // <5,1,4,3>: Cost 3 vext3 <0,4,1,5>, <1,4,3,5> + 2646822096U, // <5,1,4,4>: Cost 3 vext2 <4,u,5,1>, <4,4,4,4> + 1573080374U, // <5,1,4,5>: Cost 2 vext2 <4,u,5,1>, RHS + 2646822260U, // <5,1,4,6>: Cost 3 vext2 <4,u,5,1>, <4,6,4,6> + 3298174129U, // <5,1,4,7>: Cost 4 vrev <1,5,7,4> + 1573080602U, // <5,1,4,u>: Cost 2 vext2 <4,u,5,1>, <4,u,5,1> + 2687124591U, // <5,1,5,0>: Cost 3 vext3 <0,4,1,5>, <1,5,0,1> + 2646822543U, // <5,1,5,1>: Cost 3 vext2 <4,u,5,1>, <5,1,0,1> + 3760866433U, // <5,1,5,2>: Cost 4 vext3 <0,4,1,5>, <1,5,2,1> + 2687124624U, // <5,1,5,3>: Cost 3 vext3 <0,4,1,5>, <1,5,3,7> + 2687124631U, // <5,1,5,4>: Cost 3 vext3 <0,4,1,5>, <1,5,4,5> + 2646822916U, // <5,1,5,5>: Cost 3 vext2 <4,u,5,1>, <5,5,5,5> + 2646823010U, // <5,1,5,6>: Cost 3 vext2 <4,u,5,1>, <5,6,7,0> + 2646823080U, // <5,1,5,7>: Cost 3 vext2 <4,u,5,1>, <5,7,5,7> + 2687124663U, // <5,1,5,u>: Cost 3 vext3 <0,4,1,5>, <1,5,u,1> + 2553577574U, // <5,1,6,0>: Cost 3 vext1 <0,5,1,6>, LHS + 3763520719U, // <5,1,6,1>: Cost 4 vext3 <0,u,1,5>, <1,6,1,7> + 2646823418U, // <5,1,6,2>: Cost 3 vext2 <4,u,5,1>, <6,2,7,3> + 3760866529U, // <5,1,6,3>: Cost 4 vext3 <0,4,1,5>, <1,6,3,7> + 2553580854U, // <5,1,6,4>: Cost 3 vext1 <0,5,1,6>, RHS + 2687124723U, // <5,1,6,5>: Cost 3 vext3 <0,4,1,5>, <1,6,5,7> + 2646823736U, // <5,1,6,6>: Cost 3 vext2 <4,u,5,1>, <6,6,6,6> + 2646823758U, // <5,1,6,7>: Cost 3 vext2 <4,u,5,1>, <6,7,0,1> + 2646823839U, // <5,1,6,u>: Cost 3 vext2 <4,u,5,1>, <6,u,0,1> + 2559557734U, // <5,1,7,0>: Cost 3 vext1 <1,5,1,7>, LHS + 2559558452U, // <5,1,7,1>: Cost 3 vext1 <1,5,1,7>, <1,1,1,1> + 2571503270U, // <5,1,7,2>: Cost 3 vext1 <3,5,1,7>, <2,3,0,1> + 2040971366U, // <5,1,7,3>: Cost 2 vtrnr RHS, LHS + 2559561014U, // <5,1,7,4>: Cost 3 vext1 <1,5,1,7>, RHS + 2595393232U, // <5,1,7,5>: Cost 3 vext1 <7,5,1,7>, <5,1,7,3> + 4188455035U, // <5,1,7,6>: Cost 4 vtrnr RHS, <0,1,4,6> + 2646824556U, // <5,1,7,7>: Cost 3 vext2 <4,u,5,1>, <7,7,7,7> + 2040971371U, // <5,1,7,u>: Cost 2 vtrnr RHS, LHS + 1591662326U, // <5,1,u,0>: Cost 2 vext2 , + 1573082926U, // <5,1,u,1>: Cost 2 vext2 <4,u,5,1>, LHS + 2695824760U, // <5,1,u,2>: Cost 3 vext3 <1,u,2,5>, <1,u,2,5> + 2040979558U, // <5,1,u,3>: Cost 2 vtrnr RHS, LHS + 2687124874U, // <5,1,u,4>: Cost 3 vext3 <0,4,1,5>, <1,u,4,5> + 1573083290U, // <5,1,u,5>: Cost 2 vext2 <4,u,5,1>, RHS + 2646825168U, // <5,1,u,6>: Cost 3 vext2 <4,u,5,1>, + 2646825216U, // <5,1,u,7>: Cost 3 vext2 <4,u,5,1>, + 2040979563U, // <5,1,u,u>: Cost 2 vtrnr RHS, LHS + 3702652928U, // <5,2,0,0>: Cost 4 vext2 <1,u,5,2>, <0,0,0,0> + 2628911206U, // <5,2,0,1>: Cost 3 vext2 <1,u,5,2>, LHS + 2641518756U, // <5,2,0,2>: Cost 3 vext2 <4,0,5,2>, <0,2,0,2> + 3759760847U, // <5,2,0,3>: Cost 4 vext3 <0,2,4,5>, <2,0,3,2> + 3760866775U, // <5,2,0,4>: Cost 4 vext3 <0,4,1,5>, <2,0,4,1> + 3759539680U, // <5,2,0,5>: Cost 4 vext3 <0,2,1,5>, <2,0,5,1> + 3760866796U, // <5,2,0,6>: Cost 4 vext3 <0,4,1,5>, <2,0,6,4> + 3304114054U, // <5,2,0,7>: Cost 4 vrev <2,5,7,0> + 2628911773U, // <5,2,0,u>: Cost 3 vext2 <1,u,5,2>, LHS + 2623603464U, // <5,2,1,0>: Cost 3 vext2 <1,0,5,2>, <1,0,5,2> + 3698008921U, // <5,2,1,1>: Cost 4 vext2 <1,1,5,2>, <1,1,5,2> + 3633325603U, // <5,2,1,2>: Cost 4 vext1 <1,5,2,1>, <2,1,3,5> + 2687125027U, // <5,2,1,3>: Cost 3 vext3 <0,4,1,5>, <2,1,3,5> + 3633327414U, // <5,2,1,4>: Cost 4 vext1 <1,5,2,1>, RHS + 3759539760U, // <5,2,1,5>: Cost 4 vext3 <0,2,1,5>, <2,1,5,0> + 3760866876U, // <5,2,1,6>: Cost 4 vext3 <0,4,1,5>, <2,1,6,3> + 3304122247U, // <5,2,1,7>: Cost 4 vrev <2,5,7,1> + 2687125072U, // <5,2,1,u>: Cost 3 vext3 <0,4,1,5>, <2,1,u,5> + 3633332326U, // <5,2,2,0>: Cost 4 vext1 <1,5,2,2>, LHS + 3759760992U, // <5,2,2,1>: Cost 4 vext3 <0,2,4,5>, <2,2,1,3> + 2687125096U, // <5,2,2,2>: Cost 3 vext3 <0,4,1,5>, <2,2,2,2> + 2687125106U, // <5,2,2,3>: Cost 3 vext3 <0,4,1,5>, <2,2,3,3> + 2697963133U, // <5,2,2,4>: Cost 3 vext3 <2,2,4,5>, <2,2,4,5> + 3759466120U, // <5,2,2,5>: Cost 4 vext3 <0,2,0,5>, <2,2,5,7> + 3760866960U, // <5,2,2,6>: Cost 4 vext3 <0,4,1,5>, <2,2,6,6> + 3771926168U, // <5,2,2,7>: Cost 4 vext3 <2,2,7,5>, <2,2,7,5> + 2687125151U, // <5,2,2,u>: Cost 3 vext3 <0,4,1,5>, <2,2,u,3> + 2687125158U, // <5,2,3,0>: Cost 3 vext3 <0,4,1,5>, <2,3,0,1> + 2698405555U, // <5,2,3,1>: Cost 3 vext3 <2,3,1,5>, <2,3,1,5> + 2577516238U, // <5,2,3,2>: Cost 3 vext1 <4,5,2,3>, <2,3,4,5> + 3759687365U, // <5,2,3,3>: Cost 4 vext3 <0,2,3,5>, <2,3,3,5> + 1624884942U, // <5,2,3,4>: Cost 2 vext3 <2,3,4,5>, <2,3,4,5> + 2698700503U, // <5,2,3,5>: Cost 3 vext3 <2,3,5,5>, <2,3,5,5> + 3772368608U, // <5,2,3,6>: Cost 4 vext3 <2,3,4,5>, <2,3,6,5> + 3702655716U, // <5,2,3,7>: Cost 4 vext2 <1,u,5,2>, <3,7,3,7> + 1625179890U, // <5,2,3,u>: Cost 2 vext3 <2,3,u,5>, <2,3,u,5> + 2641521555U, // <5,2,4,0>: Cost 3 vext2 <4,0,5,2>, <4,0,5,2> + 3772368642U, // <5,2,4,1>: Cost 4 vext3 <2,3,4,5>, <2,4,1,3> + 2699142925U, // <5,2,4,2>: Cost 3 vext3 <2,4,2,5>, <2,4,2,5> + 2698626838U, // <5,2,4,3>: Cost 3 vext3 <2,3,4,5>, <2,4,3,5> + 2698626848U, // <5,2,4,4>: Cost 3 vext3 <2,3,4,5>, <2,4,4,6> + 2628914486U, // <5,2,4,5>: Cost 3 vext2 <1,u,5,2>, RHS + 2645503353U, // <5,2,4,6>: Cost 3 vext2 <4,6,5,2>, <4,6,5,2> + 3304146826U, // <5,2,4,7>: Cost 4 vrev <2,5,7,4> + 2628914729U, // <5,2,4,u>: Cost 3 vext2 <1,u,5,2>, RHS + 2553643110U, // <5,2,5,0>: Cost 3 vext1 <0,5,2,5>, LHS + 3758950227U, // <5,2,5,1>: Cost 4 vext3 <0,1,2,5>, <2,5,1,3> + 3759761248U, // <5,2,5,2>: Cost 4 vext3 <0,2,4,5>, <2,5,2,7> + 2982396006U, // <5,2,5,3>: Cost 3 vzipr <4,u,5,5>, LHS + 2553646390U, // <5,2,5,4>: Cost 3 vext1 <0,5,2,5>, RHS + 2553647108U, // <5,2,5,5>: Cost 3 vext1 <0,5,2,5>, <5,5,5,5> + 3760867204U, // <5,2,5,6>: Cost 4 vext3 <0,4,1,5>, <2,5,6,7> + 3702657141U, // <5,2,5,7>: Cost 4 vext2 <1,u,5,2>, <5,7,0,1> + 2982396011U, // <5,2,5,u>: Cost 3 vzipr <4,u,5,5>, LHS + 3627393126U, // <5,2,6,0>: Cost 4 vext1 <0,5,2,6>, LHS + 3760867236U, // <5,2,6,1>: Cost 4 vext3 <0,4,1,5>, <2,6,1,3> + 2645504506U, // <5,2,6,2>: Cost 3 vext2 <4,6,5,2>, <6,2,7,3> + 2687125434U, // <5,2,6,3>: Cost 3 vext3 <0,4,1,5>, <2,6,3,7> + 2700617665U, // <5,2,6,4>: Cost 3 vext3 <2,6,4,5>, <2,6,4,5> + 3760867276U, // <5,2,6,5>: Cost 4 vext3 <0,4,1,5>, <2,6,5,7> + 3763521493U, // <5,2,6,6>: Cost 4 vext3 <0,u,1,5>, <2,6,6,7> + 3719246670U, // <5,2,6,7>: Cost 4 vext2 <4,6,5,2>, <6,7,0,1> + 2687125479U, // <5,2,6,u>: Cost 3 vext3 <0,4,1,5>, <2,6,u,7> + 2565603430U, // <5,2,7,0>: Cost 3 vext1 <2,5,2,7>, LHS + 2553660150U, // <5,2,7,1>: Cost 3 vext1 <0,5,2,7>, <1,0,3,2> + 2565605216U, // <5,2,7,2>: Cost 3 vext1 <2,5,2,7>, <2,5,2,7> + 2961178726U, // <5,2,7,3>: Cost 3 vzipr <1,3,5,7>, LHS + 2565606710U, // <5,2,7,4>: Cost 3 vext1 <2,5,2,7>, RHS + 4034920552U, // <5,2,7,5>: Cost 4 vzipr <1,3,5,7>, <0,1,2,5> + 3114713292U, // <5,2,7,6>: Cost 3 vtrnr RHS, <0,2,4,6> + 3702658668U, // <5,2,7,7>: Cost 4 vext2 <1,u,5,2>, <7,7,7,7> + 2961178731U, // <5,2,7,u>: Cost 3 vzipr <1,3,5,7>, LHS + 2687125563U, // <5,2,u,0>: Cost 3 vext3 <0,4,1,5>, <2,u,0,1> + 2628917038U, // <5,2,u,1>: Cost 3 vext2 <1,u,5,2>, LHS + 2565613409U, // <5,2,u,2>: Cost 3 vext1 <2,5,2,u>, <2,5,2,u> + 2687125592U, // <5,2,u,3>: Cost 3 vext3 <0,4,1,5>, <2,u,3,3> + 1628203107U, // <5,2,u,4>: Cost 2 vext3 <2,u,4,5>, <2,u,4,5> + 2628917402U, // <5,2,u,5>: Cost 3 vext2 <1,u,5,2>, RHS + 2702092405U, // <5,2,u,6>: Cost 3 vext3 <2,u,6,5>, <2,u,6,5> + 3304179598U, // <5,2,u,7>: Cost 4 vrev <2,5,7,u> + 1628498055U, // <5,2,u,u>: Cost 2 vext3 <2,u,u,5>, <2,u,u,5> + 3760867467U, // <5,3,0,0>: Cost 4 vext3 <0,4,1,5>, <3,0,0,0> + 2687125654U, // <5,3,0,1>: Cost 3 vext3 <0,4,1,5>, <3,0,1,2> + 3759761565U, // <5,3,0,2>: Cost 4 vext3 <0,2,4,5>, <3,0,2,0> + 3633391766U, // <5,3,0,3>: Cost 4 vext1 <1,5,3,0>, <3,0,1,2> + 2687125680U, // <5,3,0,4>: Cost 3 vext3 <0,4,1,5>, <3,0,4,1> + 3760277690U, // <5,3,0,5>: Cost 4 vext3 <0,3,2,5>, <3,0,5,2> + 3310013014U, // <5,3,0,6>: Cost 4 vrev <3,5,6,0> + 2236344927U, // <5,3,0,7>: Cost 3 vrev <3,5,7,0> + 2687125717U, // <5,3,0,u>: Cost 3 vext3 <0,4,1,5>, <3,0,u,2> + 3760867551U, // <5,3,1,0>: Cost 4 vext3 <0,4,1,5>, <3,1,0,3> + 3760867558U, // <5,3,1,1>: Cost 4 vext3 <0,4,1,5>, <3,1,1,1> + 2624938923U, // <5,3,1,2>: Cost 3 vext2 <1,2,5,3>, <1,2,5,3> + 2703198460U, // <5,3,1,3>: Cost 3 vext3 <3,1,3,5>, <3,1,3,5> + 3760867587U, // <5,3,1,4>: Cost 4 vext3 <0,4,1,5>, <3,1,4,3> + 2636219536U, // <5,3,1,5>: Cost 3 vext2 <3,1,5,3>, <1,5,3,7> + 3698681075U, // <5,3,1,6>: Cost 4 vext2 <1,2,5,3>, <1,6,5,7> + 2703493408U, // <5,3,1,7>: Cost 3 vext3 <3,1,7,5>, <3,1,7,5> + 2628920721U, // <5,3,1,u>: Cost 3 vext2 <1,u,5,3>, <1,u,5,3> + 3766765870U, // <5,3,2,0>: Cost 4 vext3 <1,4,0,5>, <3,2,0,1> + 3698681379U, // <5,3,2,1>: Cost 4 vext2 <1,2,5,3>, <2,1,3,5> + 3760867649U, // <5,3,2,2>: Cost 4 vext3 <0,4,1,5>, <3,2,2,2> + 2698627404U, // <5,3,2,3>: Cost 3 vext3 <2,3,4,5>, <3,2,3,4> + 2703935830U, // <5,3,2,4>: Cost 3 vext3 <3,2,4,5>, <3,2,4,5> + 2698627422U, // <5,3,2,5>: Cost 3 vext3 <2,3,4,5>, <3,2,5,4> + 3760867686U, // <5,3,2,6>: Cost 4 vext3 <0,4,1,5>, <3,2,6,3> + 3769788783U, // <5,3,2,7>: Cost 4 vext3 <1,u,5,5>, <3,2,7,3> + 2701945209U, // <5,3,2,u>: Cost 3 vext3 <2,u,4,5>, <3,2,u,4> + 3760867711U, // <5,3,3,0>: Cost 4 vext3 <0,4,1,5>, <3,3,0,1> + 2636220684U, // <5,3,3,1>: Cost 3 vext2 <3,1,5,3>, <3,1,5,3> + 3772369298U, // <5,3,3,2>: Cost 4 vext3 <2,3,4,5>, <3,3,2,2> + 2687125916U, // <5,3,3,3>: Cost 3 vext3 <0,4,1,5>, <3,3,3,3> + 2704599463U, // <5,3,3,4>: Cost 3 vext3 <3,3,4,5>, <3,3,4,5> + 2704673200U, // <5,3,3,5>: Cost 3 vext3 <3,3,5,5>, <3,3,5,5> + 3709962935U, // <5,3,3,6>: Cost 4 vext2 <3,1,5,3>, <3,6,7,7> + 3772369346U, // <5,3,3,7>: Cost 4 vext3 <2,3,4,5>, <3,3,7,5> + 2704894411U, // <5,3,3,u>: Cost 3 vext3 <3,3,u,5>, <3,3,u,5> + 2704968148U, // <5,3,4,0>: Cost 3 vext3 <3,4,0,5>, <3,4,0,5> + 3698682850U, // <5,3,4,1>: Cost 4 vext2 <1,2,5,3>, <4,1,5,0> + 2642857014U, // <5,3,4,2>: Cost 3 vext2 <4,2,5,3>, <4,2,5,3> + 2705189359U, // <5,3,4,3>: Cost 3 vext3 <3,4,3,5>, <3,4,3,5> + 2705263096U, // <5,3,4,4>: Cost 3 vext3 <3,4,4,5>, <3,4,4,5> + 2685946370U, // <5,3,4,5>: Cost 3 vext3 <0,2,3,5>, <3,4,5,6> + 3779152394U, // <5,3,4,6>: Cost 4 vext3 <3,4,6,5>, <3,4,6,5> + 2236377699U, // <5,3,4,7>: Cost 3 vrev <3,5,7,4> + 2687126045U, // <5,3,4,u>: Cost 3 vext3 <0,4,1,5>, <3,4,u,6> + 2571632742U, // <5,3,5,0>: Cost 3 vext1 <3,5,3,5>, LHS + 2559689870U, // <5,3,5,1>: Cost 3 vext1 <1,5,3,5>, <1,5,3,5> + 2571634382U, // <5,3,5,2>: Cost 3 vext1 <3,5,3,5>, <2,3,4,5> + 2571635264U, // <5,3,5,3>: Cost 3 vext1 <3,5,3,5>, <3,5,3,5> + 2571636022U, // <5,3,5,4>: Cost 3 vext1 <3,5,3,5>, RHS + 2559692804U, // <5,3,5,5>: Cost 3 vext1 <1,5,3,5>, <5,5,5,5> + 3720581218U, // <5,3,5,6>: Cost 4 vext2 <4,u,5,3>, <5,6,7,0> + 2236385892U, // <5,3,5,7>: Cost 3 vrev <3,5,7,5> + 2571638574U, // <5,3,5,u>: Cost 3 vext1 <3,5,3,5>, LHS + 2565668966U, // <5,3,6,0>: Cost 3 vext1 <2,5,3,6>, LHS + 3633439887U, // <5,3,6,1>: Cost 4 vext1 <1,5,3,6>, <1,5,3,6> + 2565670760U, // <5,3,6,2>: Cost 3 vext1 <2,5,3,6>, <2,5,3,6> + 2565671426U, // <5,3,6,3>: Cost 3 vext1 <2,5,3,6>, <3,4,5,6> + 2565672246U, // <5,3,6,4>: Cost 3 vext1 <2,5,3,6>, RHS + 3639414630U, // <5,3,6,5>: Cost 4 vext1 <2,5,3,6>, <5,3,6,0> + 4047521640U, // <5,3,6,6>: Cost 4 vzipr <3,4,5,6>, <2,5,3,6> + 2725169844U, // <5,3,6,7>: Cost 3 vext3 <6,7,4,5>, <3,6,7,4> + 2565674798U, // <5,3,6,u>: Cost 3 vext1 <2,5,3,6>, LHS + 1485963366U, // <5,3,7,0>: Cost 2 vext1 <1,5,3,7>, LHS + 1485964432U, // <5,3,7,1>: Cost 2 vext1 <1,5,3,7>, <1,5,3,7> + 2559706728U, // <5,3,7,2>: Cost 3 vext1 <1,5,3,7>, <2,2,2,2> + 2559707286U, // <5,3,7,3>: Cost 3 vext1 <1,5,3,7>, <3,0,1,2> + 1485966646U, // <5,3,7,4>: Cost 2 vext1 <1,5,3,7>, RHS + 2559708880U, // <5,3,7,5>: Cost 3 vext1 <1,5,3,7>, <5,1,7,3> + 2601513466U, // <5,3,7,6>: Cost 3 vext1 , <6,2,7,3> + 3114714112U, // <5,3,7,7>: Cost 3 vtrnr RHS, <1,3,5,7> + 1485969198U, // <5,3,7,u>: Cost 2 vext1 <1,5,3,7>, LHS + 1485971558U, // <5,3,u,0>: Cost 2 vext1 <1,5,3,u>, LHS + 1485972625U, // <5,3,u,1>: Cost 2 vext1 <1,5,3,u>, <1,5,3,u> + 2559714920U, // <5,3,u,2>: Cost 3 vext1 <1,5,3,u>, <2,2,2,2> + 2559715478U, // <5,3,u,3>: Cost 3 vext1 <1,5,3,u>, <3,0,1,2> + 1485974838U, // <5,3,u,4>: Cost 2 vext1 <1,5,3,u>, RHS + 2687126342U, // <5,3,u,5>: Cost 3 vext3 <0,4,1,5>, <3,u,5,6> + 2601521658U, // <5,3,u,6>: Cost 3 vext1 , <6,2,7,3> + 2236410471U, // <5,3,u,7>: Cost 3 vrev <3,5,7,u> + 1485977390U, // <5,3,u,u>: Cost 2 vext1 <1,5,3,u>, LHS + 3627491430U, // <5,4,0,0>: Cost 4 vext1 <0,5,4,0>, LHS + 2636890214U, // <5,4,0,1>: Cost 3 vext2 <3,2,5,4>, LHS + 3703333028U, // <5,4,0,2>: Cost 4 vext2 <2,0,5,4>, <0,2,0,2> + 3782249348U, // <5,4,0,3>: Cost 4 vext3 <4,0,3,5>, <4,0,3,5> + 2642198866U, // <5,4,0,4>: Cost 3 vext2 <4,1,5,4>, <0,4,1,5> + 2687126418U, // <5,4,0,5>: Cost 3 vext3 <0,4,1,5>, <4,0,5,1> + 2242243887U, // <5,4,0,6>: Cost 3 vrev <4,5,6,0> + 3316059448U, // <5,4,0,7>: Cost 4 vrev <4,5,7,0> + 2636890781U, // <5,4,0,u>: Cost 3 vext2 <3,2,5,4>, LHS + 2241809658U, // <5,4,1,0>: Cost 3 vrev <4,5,0,1> + 3698025307U, // <5,4,1,1>: Cost 4 vext2 <1,1,5,4>, <1,1,5,4> + 3698688940U, // <5,4,1,2>: Cost 4 vext2 <1,2,5,4>, <1,2,5,4> + 3698689024U, // <5,4,1,3>: Cost 4 vext2 <1,2,5,4>, <1,3,5,7> + 3700016206U, // <5,4,1,4>: Cost 4 vext2 <1,4,5,4>, <1,4,5,4> + 2687126498U, // <5,4,1,5>: Cost 3 vext3 <0,4,1,5>, <4,1,5,0> + 3760868336U, // <5,4,1,6>: Cost 4 vext3 <0,4,1,5>, <4,1,6,5> + 3316067641U, // <5,4,1,7>: Cost 4 vrev <4,5,7,1> + 2242399554U, // <5,4,1,u>: Cost 3 vrev <4,5,u,1> + 3703334371U, // <5,4,2,0>: Cost 4 vext2 <2,0,5,4>, <2,0,5,4> + 3703998004U, // <5,4,2,1>: Cost 4 vext2 <2,1,5,4>, <2,1,5,4> + 3704661637U, // <5,4,2,2>: Cost 4 vext2 <2,2,5,4>, <2,2,5,4> + 2636891854U, // <5,4,2,3>: Cost 3 vext2 <3,2,5,4>, <2,3,4,5> + 3705988903U, // <5,4,2,4>: Cost 4 vext2 <2,4,5,4>, <2,4,5,4> + 2698628150U, // <5,4,2,5>: Cost 3 vext3 <2,3,4,5>, <4,2,5,3> + 3760868415U, // <5,4,2,6>: Cost 4 vext3 <0,4,1,5>, <4,2,6,3> + 3783871562U, // <5,4,2,7>: Cost 4 vext3 <4,2,7,5>, <4,2,7,5> + 2666752099U, // <5,4,2,u>: Cost 3 vext2 , <2,u,4,5> + 3639459942U, // <5,4,3,0>: Cost 4 vext1 <2,5,4,3>, LHS + 3709970701U, // <5,4,3,1>: Cost 4 vext2 <3,1,5,4>, <3,1,5,4> + 2636892510U, // <5,4,3,2>: Cost 3 vext2 <3,2,5,4>, <3,2,5,4> + 3710634396U, // <5,4,3,3>: Cost 4 vext2 <3,2,5,4>, <3,3,3,3> + 2638219776U, // <5,4,3,4>: Cost 3 vext2 <3,4,5,4>, <3,4,5,4> + 3766987908U, // <5,4,3,5>: Cost 4 vext3 <1,4,3,5>, <4,3,5,0> + 2710719634U, // <5,4,3,6>: Cost 3 vext3 <4,3,6,5>, <4,3,6,5> + 3914097664U, // <5,4,3,7>: Cost 4 vuzpr <3,5,7,4>, <1,3,5,7> + 2640874308U, // <5,4,3,u>: Cost 3 vext2 <3,u,5,4>, <3,u,5,4> + 2583642214U, // <5,4,4,0>: Cost 3 vext1 <5,5,4,4>, LHS + 2642201574U, // <5,4,4,1>: Cost 3 vext2 <4,1,5,4>, <4,1,5,4> + 3710635062U, // <5,4,4,2>: Cost 4 vext2 <3,2,5,4>, <4,2,5,3> + 3717270664U, // <5,4,4,3>: Cost 4 vext2 <4,3,5,4>, <4,3,5,4> + 2713963728U, // <5,4,4,4>: Cost 3 vext3 <4,u,5,5>, <4,4,4,4> + 1637567706U, // <5,4,4,5>: Cost 2 vext3 <4,4,5,5>, <4,4,5,5> + 2242276659U, // <5,4,4,6>: Cost 3 vrev <4,5,6,4> + 2646183372U, // <5,4,4,7>: Cost 3 vext2 <4,7,5,4>, <4,7,5,4> + 1637788917U, // <5,4,4,u>: Cost 2 vext3 <4,4,u,5>, <4,4,u,5> + 2559762534U, // <5,4,5,0>: Cost 3 vext1 <1,5,4,5>, LHS + 2559763607U, // <5,4,5,1>: Cost 3 vext1 <1,5,4,5>, <1,5,4,5> + 2698628366U, // <5,4,5,2>: Cost 3 vext3 <2,3,4,5>, <4,5,2,3> + 3633506454U, // <5,4,5,3>: Cost 4 vext1 <1,5,4,5>, <3,0,1,2> + 2559765814U, // <5,4,5,4>: Cost 3 vext1 <1,5,4,5>, RHS + 2583654395U, // <5,4,5,5>: Cost 3 vext1 <5,5,4,5>, <5,5,4,5> + 1613385014U, // <5,4,5,6>: Cost 2 vext3 <0,4,1,5>, RHS + 3901639990U, // <5,4,5,7>: Cost 4 vuzpr <1,5,0,4>, RHS + 1613385032U, // <5,4,5,u>: Cost 2 vext3 <0,4,1,5>, RHS + 2559770726U, // <5,4,6,0>: Cost 3 vext1 <1,5,4,6>, LHS + 2559771648U, // <5,4,6,1>: Cost 3 vext1 <1,5,4,6>, <1,3,5,7> + 3633514088U, // <5,4,6,2>: Cost 4 vext1 <1,5,4,6>, <2,2,2,2> + 2571717122U, // <5,4,6,3>: Cost 3 vext1 <3,5,4,6>, <3,4,5,6> + 2559774006U, // <5,4,6,4>: Cost 3 vext1 <1,5,4,6>, RHS + 2712636796U, // <5,4,6,5>: Cost 3 vext3 <4,6,5,5>, <4,6,5,5> + 3760868743U, // <5,4,6,6>: Cost 4 vext3 <0,4,1,5>, <4,6,6,7> + 2712784270U, // <5,4,6,7>: Cost 3 vext3 <4,6,7,5>, <4,6,7,5> + 2559776558U, // <5,4,6,u>: Cost 3 vext1 <1,5,4,6>, LHS + 2565750886U, // <5,4,7,0>: Cost 3 vext1 <2,5,4,7>, LHS + 2565751706U, // <5,4,7,1>: Cost 3 vext1 <2,5,4,7>, <1,2,3,4> + 2565752690U, // <5,4,7,2>: Cost 3 vext1 <2,5,4,7>, <2,5,4,7> + 2571725387U, // <5,4,7,3>: Cost 3 vext1 <3,5,4,7>, <3,5,4,7> + 2565754166U, // <5,4,7,4>: Cost 3 vext1 <2,5,4,7>, RHS + 3114713426U, // <5,4,7,5>: Cost 3 vtrnr RHS, <0,4,1,5> + 94817590U, // <5,4,7,6>: Cost 1 vrev RHS + 2595616175U, // <5,4,7,7>: Cost 3 vext1 <7,5,4,7>, <7,5,4,7> + 94965064U, // <5,4,7,u>: Cost 1 vrev RHS + 2559787110U, // <5,4,u,0>: Cost 3 vext1 <1,5,4,u>, LHS + 2559788186U, // <5,4,u,1>: Cost 3 vext1 <1,5,4,u>, <1,5,4,u> + 2242014483U, // <5,4,u,2>: Cost 3 vrev <4,5,2,u> + 2667419628U, // <5,4,u,3>: Cost 3 vext2 , + 2559790390U, // <5,4,u,4>: Cost 3 vext1 <1,5,4,u>, RHS + 1640222238U, // <5,4,u,5>: Cost 2 vext3 <4,u,5,5>, <4,u,5,5> + 94825783U, // <5,4,u,6>: Cost 1 vrev RHS + 2714111536U, // <5,4,u,7>: Cost 3 vext3 <4,u,7,5>, <4,u,7,5> + 94973257U, // <5,4,u,u>: Cost 1 vrev RHS + 2646851584U, // <5,5,0,0>: Cost 3 vext2 <4,u,5,5>, <0,0,0,0> + 1573109862U, // <5,5,0,1>: Cost 2 vext2 <4,u,5,5>, LHS + 2646851748U, // <5,5,0,2>: Cost 3 vext2 <4,u,5,5>, <0,2,0,2> + 3760279130U, // <5,5,0,3>: Cost 4 vext3 <0,3,2,5>, <5,0,3,2> + 2687127138U, // <5,5,0,4>: Cost 3 vext3 <0,4,1,5>, <5,0,4,1> + 2248142847U, // <5,5,0,5>: Cost 3 vrev <5,5,5,0> + 3720593910U, // <5,5,0,6>: Cost 4 vext2 <4,u,5,5>, <0,6,1,7> + 4182502710U, // <5,5,0,7>: Cost 4 vtrnr <3,5,7,0>, RHS + 1573110429U, // <5,5,0,u>: Cost 2 vext2 <4,u,5,5>, LHS + 2646852342U, // <5,5,1,0>: Cost 3 vext2 <4,u,5,5>, <1,0,3,2> + 2624291676U, // <5,5,1,1>: Cost 3 vext2 <1,1,5,5>, <1,1,5,5> + 2646852502U, // <5,5,1,2>: Cost 3 vext2 <4,u,5,5>, <1,2,3,0> + 2646852568U, // <5,5,1,3>: Cost 3 vext2 <4,u,5,5>, <1,3,1,3> + 2715217591U, // <5,5,1,4>: Cost 3 vext3 <5,1,4,5>, <5,1,4,5> + 2628936848U, // <5,5,1,5>: Cost 3 vext2 <1,u,5,5>, <1,5,3,7> + 3698033907U, // <5,5,1,6>: Cost 4 vext2 <1,1,5,5>, <1,6,5,7> + 2713964240U, // <5,5,1,7>: Cost 3 vext3 <4,u,5,5>, <5,1,7,3> + 2628937107U, // <5,5,1,u>: Cost 3 vext2 <1,u,5,5>, <1,u,5,5> + 3645497446U, // <5,5,2,0>: Cost 4 vext1 <3,5,5,2>, LHS + 3760869099U, // <5,5,2,1>: Cost 4 vext3 <0,4,1,5>, <5,2,1,3> + 2646853224U, // <5,5,2,2>: Cost 3 vext2 <4,u,5,5>, <2,2,2,2> + 2698628862U, // <5,5,2,3>: Cost 3 vext3 <2,3,4,5>, <5,2,3,4> + 3772370694U, // <5,5,2,4>: Cost 4 vext3 <2,3,4,5>, <5,2,4,3> + 2713964303U, // <5,5,2,5>: Cost 3 vext3 <4,u,5,5>, <5,2,5,3> + 2646853562U, // <5,5,2,6>: Cost 3 vext2 <4,u,5,5>, <2,6,3,7> + 4038198272U, // <5,5,2,7>: Cost 4 vzipr <1,u,5,2>, <1,3,5,7> + 2701946667U, // <5,5,2,u>: Cost 3 vext3 <2,u,4,5>, <5,2,u,4> + 2646853782U, // <5,5,3,0>: Cost 3 vext2 <4,u,5,5>, <3,0,1,2> + 3698034922U, // <5,5,3,1>: Cost 4 vext2 <1,1,5,5>, <3,1,1,5> + 3702679919U, // <5,5,3,2>: Cost 4 vext2 <1,u,5,5>, <3,2,7,3> + 2637564336U, // <5,5,3,3>: Cost 3 vext2 <3,3,5,5>, <3,3,5,5> + 2646854146U, // <5,5,3,4>: Cost 3 vext2 <4,u,5,5>, <3,4,5,6> + 2638891602U, // <5,5,3,5>: Cost 3 vext2 <3,5,5,5>, <3,5,5,5> + 3702680247U, // <5,5,3,6>: Cost 4 vext2 <1,u,5,5>, <3,6,7,7> + 3702680259U, // <5,5,3,7>: Cost 4 vext2 <1,u,5,5>, <3,7,0,1> + 2646854430U, // <5,5,3,u>: Cost 3 vext2 <4,u,5,5>, <3,u,1,2> + 2646854546U, // <5,5,4,0>: Cost 3 vext2 <4,u,5,5>, <4,0,5,1> + 2642209767U, // <5,5,4,1>: Cost 3 vext2 <4,1,5,5>, <4,1,5,5> + 3711306806U, // <5,5,4,2>: Cost 4 vext2 <3,3,5,5>, <4,2,5,3> + 3645516369U, // <5,5,4,3>: Cost 4 vext1 <3,5,5,4>, <3,5,5,4> + 1570458842U, // <5,5,4,4>: Cost 2 vext2 <4,4,5,5>, <4,4,5,5> + 1573113142U, // <5,5,4,5>: Cost 2 vext2 <4,u,5,5>, RHS + 2645527932U, // <5,5,4,6>: Cost 3 vext2 <4,6,5,5>, <4,6,5,5> + 2713964486U, // <5,5,4,7>: Cost 3 vext3 <4,u,5,5>, <5,4,7,6> + 1573113374U, // <5,5,4,u>: Cost 2 vext2 <4,u,5,5>, <4,u,5,5> + 1509982310U, // <5,5,5,0>: Cost 2 vext1 <5,5,5,5>, LHS + 2646855376U, // <5,5,5,1>: Cost 3 vext2 <4,u,5,5>, <5,1,7,3> + 2583725672U, // <5,5,5,2>: Cost 3 vext1 <5,5,5,5>, <2,2,2,2> + 2583726230U, // <5,5,5,3>: Cost 3 vext1 <5,5,5,5>, <3,0,1,2> + 1509985590U, // <5,5,5,4>: Cost 2 vext1 <5,5,5,5>, RHS + 229035318U, // <5,5,5,5>: Cost 1 vdup1 RHS + 2646855778U, // <5,5,5,6>: Cost 3 vext2 <4,u,5,5>, <5,6,7,0> + 2646855848U, // <5,5,5,7>: Cost 3 vext2 <4,u,5,5>, <5,7,5,7> + 229035318U, // <5,5,5,u>: Cost 1 vdup1 RHS + 2577760358U, // <5,5,6,0>: Cost 3 vext1 <4,5,5,6>, LHS + 3633587361U, // <5,5,6,1>: Cost 4 vext1 <1,5,5,6>, <1,5,5,6> + 2646856186U, // <5,5,6,2>: Cost 3 vext2 <4,u,5,5>, <6,2,7,3> + 3633588738U, // <5,5,6,3>: Cost 4 vext1 <1,5,5,6>, <3,4,5,6> + 2718535756U, // <5,5,6,4>: Cost 3 vext3 <5,6,4,5>, <5,6,4,5> + 2644202223U, // <5,5,6,5>: Cost 3 vext2 <4,4,5,5>, <6,5,7,5> + 2973780482U, // <5,5,6,6>: Cost 3 vzipr <3,4,5,6>, <3,4,5,6> + 2646856526U, // <5,5,6,7>: Cost 3 vext2 <4,u,5,5>, <6,7,0,1> + 2646856607U, // <5,5,6,u>: Cost 3 vext2 <4,u,5,5>, <6,u,0,1> + 2571796582U, // <5,5,7,0>: Cost 3 vext1 <3,5,5,7>, LHS + 3633595392U, // <5,5,7,1>: Cost 4 vext1 <1,5,5,7>, <1,3,5,7> + 2571798222U, // <5,5,7,2>: Cost 3 vext1 <3,5,5,7>, <2,3,4,5> + 2571799124U, // <5,5,7,3>: Cost 3 vext1 <3,5,5,7>, <3,5,5,7> + 2571799862U, // <5,5,7,4>: Cost 3 vext1 <3,5,5,7>, RHS + 3114717188U, // <5,5,7,5>: Cost 3 vtrnr RHS, <5,5,5,5> + 4034923010U, // <5,5,7,6>: Cost 4 vzipr <1,3,5,7>, <3,4,5,6> + 2040974646U, // <5,5,7,7>: Cost 2 vtrnr RHS, RHS + 2040974647U, // <5,5,7,u>: Cost 2 vtrnr RHS, RHS + 1509982310U, // <5,5,u,0>: Cost 2 vext1 <5,5,5,5>, LHS + 1573115694U, // <5,5,u,1>: Cost 2 vext2 <4,u,5,5>, LHS + 2571806414U, // <5,5,u,2>: Cost 3 vext1 <3,5,5,u>, <2,3,4,5> + 2571807317U, // <5,5,u,3>: Cost 3 vext1 <3,5,5,u>, <3,5,5,u> + 1509985590U, // <5,5,u,4>: Cost 2 vext1 <5,5,5,5>, RHS + 229035318U, // <5,5,u,5>: Cost 1 vdup1 RHS + 2646857936U, // <5,5,u,6>: Cost 3 vext2 <4,u,5,5>, + 2040982838U, // <5,5,u,7>: Cost 2 vtrnr RHS, RHS + 229035318U, // <5,5,u,u>: Cost 1 vdup1 RHS + 2638233600U, // <5,6,0,0>: Cost 3 vext2 <3,4,5,6>, <0,0,0,0> + 1564491878U, // <5,6,0,1>: Cost 2 vext2 <3,4,5,6>, LHS + 2632261796U, // <5,6,0,2>: Cost 3 vext2 <2,4,5,6>, <0,2,0,2> + 2638233856U, // <5,6,0,3>: Cost 3 vext2 <3,4,5,6>, <0,3,1,4> + 2638233938U, // <5,6,0,4>: Cost 3 vext2 <3,4,5,6>, <0,4,1,5> + 3706003885U, // <5,6,0,5>: Cost 4 vext2 <2,4,5,6>, <0,5,2,6> + 3706003967U, // <5,6,0,6>: Cost 4 vext2 <2,4,5,6>, <0,6,2,7> + 4047473974U, // <5,6,0,7>: Cost 4 vzipr <3,4,5,0>, RHS + 1564492445U, // <5,6,0,u>: Cost 2 vext2 <3,4,5,6>, LHS + 2638234358U, // <5,6,1,0>: Cost 3 vext2 <3,4,5,6>, <1,0,3,2> + 2638234420U, // <5,6,1,1>: Cost 3 vext2 <3,4,5,6>, <1,1,1,1> + 2638234518U, // <5,6,1,2>: Cost 3 vext2 <3,4,5,6>, <1,2,3,0> + 2638234584U, // <5,6,1,3>: Cost 3 vext2 <3,4,5,6>, <1,3,1,3> + 2626290768U, // <5,6,1,4>: Cost 3 vext2 <1,4,5,6>, <1,4,5,6> + 2638234768U, // <5,6,1,5>: Cost 3 vext2 <3,4,5,6>, <1,5,3,7> + 3700032719U, // <5,6,1,6>: Cost 4 vext2 <1,4,5,6>, <1,6,1,7> + 2982366518U, // <5,6,1,7>: Cost 3 vzipr <4,u,5,1>, RHS + 2628945300U, // <5,6,1,u>: Cost 3 vext2 <1,u,5,6>, <1,u,5,6> + 3706004925U, // <5,6,2,0>: Cost 4 vext2 <2,4,5,6>, <2,0,1,2> + 3711976966U, // <5,6,2,1>: Cost 4 vext2 <3,4,5,6>, <2,1,0,3> + 2638235240U, // <5,6,2,2>: Cost 3 vext2 <3,4,5,6>, <2,2,2,2> + 2638235302U, // <5,6,2,3>: Cost 3 vext2 <3,4,5,6>, <2,3,0,1> + 2632263465U, // <5,6,2,4>: Cost 3 vext2 <2,4,5,6>, <2,4,5,6> + 2638235496U, // <5,6,2,5>: Cost 3 vext2 <3,4,5,6>, <2,5,3,6> + 2638235578U, // <5,6,2,6>: Cost 3 vext2 <3,4,5,6>, <2,6,3,7> + 2713965050U, // <5,6,2,7>: Cost 3 vext3 <4,u,5,5>, <6,2,7,3> + 2634917997U, // <5,6,2,u>: Cost 3 vext2 <2,u,5,6>, <2,u,5,6> + 2638235798U, // <5,6,3,0>: Cost 3 vext2 <3,4,5,6>, <3,0,1,2> + 3711977695U, // <5,6,3,1>: Cost 4 vext2 <3,4,5,6>, <3,1,0,3> + 3710650720U, // <5,6,3,2>: Cost 4 vext2 <3,2,5,6>, <3,2,5,6> + 2638236060U, // <5,6,3,3>: Cost 3 vext2 <3,4,5,6>, <3,3,3,3> + 1564494338U, // <5,6,3,4>: Cost 2 vext2 <3,4,5,6>, <3,4,5,6> + 2638236234U, // <5,6,3,5>: Cost 3 vext2 <3,4,5,6>, <3,5,4,6> + 3711978104U, // <5,6,3,6>: Cost 4 vext2 <3,4,5,6>, <3,6,0,7> + 4034227510U, // <5,6,3,7>: Cost 4 vzipr <1,2,5,3>, RHS + 1567148870U, // <5,6,3,u>: Cost 2 vext2 <3,u,5,6>, <3,u,5,6> + 2577817702U, // <5,6,4,0>: Cost 3 vext1 <4,5,6,4>, LHS + 3700034544U, // <5,6,4,1>: Cost 4 vext2 <1,4,5,6>, <4,1,6,5> + 2723033713U, // <5,6,4,2>: Cost 3 vext3 <6,4,2,5>, <6,4,2,5> + 2638236818U, // <5,6,4,3>: Cost 3 vext2 <3,4,5,6>, <4,3,6,5> + 2644208859U, // <5,6,4,4>: Cost 3 vext2 <4,4,5,6>, <4,4,5,6> + 1564495158U, // <5,6,4,5>: Cost 2 vext2 <3,4,5,6>, RHS + 2645536125U, // <5,6,4,6>: Cost 3 vext2 <4,6,5,6>, <4,6,5,6> + 2723402398U, // <5,6,4,7>: Cost 3 vext3 <6,4,7,5>, <6,4,7,5> + 1564495401U, // <5,6,4,u>: Cost 2 vext2 <3,4,5,6>, RHS + 2577825894U, // <5,6,5,0>: Cost 3 vext1 <4,5,6,5>, LHS + 2662125264U, // <5,6,5,1>: Cost 3 vext2 <7,4,5,6>, <5,1,7,3> + 3775836867U, // <5,6,5,2>: Cost 4 vext3 <2,u,6,5>, <6,5,2,6> + 3711979343U, // <5,6,5,3>: Cost 4 vext2 <3,4,5,6>, <5,3,3,4> + 2650181556U, // <5,6,5,4>: Cost 3 vext2 <5,4,5,6>, <5,4,5,6> + 2662125572U, // <5,6,5,5>: Cost 3 vext2 <7,4,5,6>, <5,5,5,5> + 2638237732U, // <5,6,5,6>: Cost 3 vext2 <3,4,5,6>, <5,6,0,1> + 2982399286U, // <5,6,5,7>: Cost 3 vzipr <4,u,5,5>, RHS + 2982399287U, // <5,6,5,u>: Cost 3 vzipr <4,u,5,5>, RHS + 2583806054U, // <5,6,6,0>: Cost 3 vext1 <5,5,6,6>, LHS + 3711979910U, // <5,6,6,1>: Cost 4 vext2 <3,4,5,6>, <6,1,3,4> + 2662126074U, // <5,6,6,2>: Cost 3 vext2 <7,4,5,6>, <6,2,7,3> + 2583808514U, // <5,6,6,3>: Cost 3 vext1 <5,5,6,6>, <3,4,5,6> + 2583809334U, // <5,6,6,4>: Cost 3 vext1 <5,5,6,6>, RHS + 2583810062U, // <5,6,6,5>: Cost 3 vext1 <5,5,6,6>, <5,5,6,6> + 2638238520U, // <5,6,6,6>: Cost 3 vext2 <3,4,5,6>, <6,6,6,6> + 2973781302U, // <5,6,6,7>: Cost 3 vzipr <3,4,5,6>, RHS + 2973781303U, // <5,6,6,u>: Cost 3 vzipr <3,4,5,6>, RHS + 430358630U, // <5,6,7,0>: Cost 1 vext1 RHS, LHS + 1504101110U, // <5,6,7,1>: Cost 2 vext1 RHS, <1,0,3,2> + 1504101992U, // <5,6,7,2>: Cost 2 vext1 RHS, <2,2,2,2> + 1504102550U, // <5,6,7,3>: Cost 2 vext1 RHS, <3,0,1,2> + 430361910U, // <5,6,7,4>: Cost 1 vext1 RHS, RHS + 1504104390U, // <5,6,7,5>: Cost 2 vext1 RHS, <5,4,7,6> + 1504105272U, // <5,6,7,6>: Cost 2 vext1 RHS, <6,6,6,6> + 1504106092U, // <5,6,7,7>: Cost 2 vext1 RHS, <7,7,7,7> + 430364462U, // <5,6,7,u>: Cost 1 vext1 RHS, LHS + 430366822U, // <5,6,u,0>: Cost 1 vext1 RHS, LHS + 1564497710U, // <5,6,u,1>: Cost 2 vext2 <3,4,5,6>, LHS + 1504110184U, // <5,6,u,2>: Cost 2 vext1 RHS, <2,2,2,2> + 1504110742U, // <5,6,u,3>: Cost 2 vext1 RHS, <3,0,1,2> + 430370103U, // <5,6,u,4>: Cost 1 vext1 RHS, RHS + 1564498074U, // <5,6,u,5>: Cost 2 vext2 <3,4,5,6>, RHS + 1504113146U, // <5,6,u,6>: Cost 2 vext1 RHS, <6,2,7,3> + 1504113658U, // <5,6,u,7>: Cost 2 vext1 RHS, <7,0,1,2> + 430372654U, // <5,6,u,u>: Cost 1 vext1 RHS, LHS + 2625634304U, // <5,7,0,0>: Cost 3 vext2 <1,3,5,7>, <0,0,0,0> + 1551892582U, // <5,7,0,1>: Cost 2 vext2 <1,3,5,7>, LHS + 2625634468U, // <5,7,0,2>: Cost 3 vext2 <1,3,5,7>, <0,2,0,2> + 2571889247U, // <5,7,0,3>: Cost 3 vext1 <3,5,7,0>, <3,5,7,0> + 2625634642U, // <5,7,0,4>: Cost 3 vext2 <1,3,5,7>, <0,4,1,5> + 2595778728U, // <5,7,0,5>: Cost 3 vext1 <7,5,7,0>, <5,7,5,7> + 3699376639U, // <5,7,0,6>: Cost 4 vext2 <1,3,5,7>, <0,6,2,7> + 2260235715U, // <5,7,0,7>: Cost 3 vrev <7,5,7,0> + 1551893149U, // <5,7,0,u>: Cost 2 vext2 <1,3,5,7>, LHS + 2625635062U, // <5,7,1,0>: Cost 3 vext2 <1,3,5,7>, <1,0,3,2> + 2624308020U, // <5,7,1,1>: Cost 3 vext2 <1,1,5,7>, <1,1,1,1> + 2625635222U, // <5,7,1,2>: Cost 3 vext2 <1,3,5,7>, <1,2,3,0> + 1551893504U, // <5,7,1,3>: Cost 2 vext2 <1,3,5,7>, <1,3,5,7> + 2571898166U, // <5,7,1,4>: Cost 3 vext1 <3,5,7,1>, RHS + 2625635472U, // <5,7,1,5>: Cost 3 vext2 <1,3,5,7>, <1,5,3,7> + 2627626227U, // <5,7,1,6>: Cost 3 vext2 <1,6,5,7>, <1,6,5,7> + 3702031684U, // <5,7,1,7>: Cost 4 vext2 <1,7,5,7>, <1,7,5,7> + 1555211669U, // <5,7,1,u>: Cost 2 vext2 <1,u,5,7>, <1,u,5,7> + 2629617126U, // <5,7,2,0>: Cost 3 vext2 <2,0,5,7>, <2,0,5,7> + 3699377670U, // <5,7,2,1>: Cost 4 vext2 <1,3,5,7>, <2,1,0,3> + 2625635944U, // <5,7,2,2>: Cost 3 vext2 <1,3,5,7>, <2,2,2,2> + 2625636006U, // <5,7,2,3>: Cost 3 vext2 <1,3,5,7>, <2,3,0,1> + 2632271658U, // <5,7,2,4>: Cost 3 vext2 <2,4,5,7>, <2,4,5,7> + 2625636201U, // <5,7,2,5>: Cost 3 vext2 <1,3,5,7>, <2,5,3,7> + 2625636282U, // <5,7,2,6>: Cost 3 vext2 <1,3,5,7>, <2,6,3,7> + 3708004381U, // <5,7,2,7>: Cost 4 vext2 <2,7,5,7>, <2,7,5,7> + 2625636411U, // <5,7,2,u>: Cost 3 vext2 <1,3,5,7>, <2,u,0,1> + 2625636502U, // <5,7,3,0>: Cost 3 vext2 <1,3,5,7>, <3,0,1,2> + 2625636604U, // <5,7,3,1>: Cost 3 vext2 <1,3,5,7>, <3,1,3,5> + 3699378478U, // <5,7,3,2>: Cost 4 vext2 <1,3,5,7>, <3,2,0,1> + 2625636764U, // <5,7,3,3>: Cost 3 vext2 <1,3,5,7>, <3,3,3,3> + 2625636866U, // <5,7,3,4>: Cost 3 vext2 <1,3,5,7>, <3,4,5,6> + 2625636959U, // <5,7,3,5>: Cost 3 vext2 <1,3,5,7>, <3,5,7,0> + 3699378808U, // <5,7,3,6>: Cost 4 vext2 <1,3,5,7>, <3,6,0,7> + 2640235254U, // <5,7,3,7>: Cost 3 vext2 <3,7,5,7>, <3,7,5,7> + 2625637150U, // <5,7,3,u>: Cost 3 vext2 <1,3,5,7>, <3,u,1,2> + 2571919462U, // <5,7,4,0>: Cost 3 vext1 <3,5,7,4>, LHS + 2571920384U, // <5,7,4,1>: Cost 3 vext1 <3,5,7,4>, <1,3,5,7> + 3699379260U, // <5,7,4,2>: Cost 4 vext2 <1,3,5,7>, <4,2,6,0> + 2571922019U, // <5,7,4,3>: Cost 3 vext1 <3,5,7,4>, <3,5,7,4> + 2571922742U, // <5,7,4,4>: Cost 3 vext1 <3,5,7,4>, RHS + 1551895862U, // <5,7,4,5>: Cost 2 vext2 <1,3,5,7>, RHS + 2846277980U, // <5,7,4,6>: Cost 3 vuzpr RHS, <0,4,2,6> + 2646207951U, // <5,7,4,7>: Cost 3 vext2 <4,7,5,7>, <4,7,5,7> + 1551896105U, // <5,7,4,u>: Cost 2 vext2 <1,3,5,7>, RHS + 2583871590U, // <5,7,5,0>: Cost 3 vext1 <5,5,7,5>, LHS + 2652180176U, // <5,7,5,1>: Cost 3 vext2 <5,7,5,7>, <5,1,7,3> + 2625638177U, // <5,7,5,2>: Cost 3 vext2 <1,3,5,7>, <5,2,7,3> + 2625638262U, // <5,7,5,3>: Cost 3 vext2 <1,3,5,7>, <5,3,7,7> + 2583874870U, // <5,7,5,4>: Cost 3 vext1 <5,5,7,5>, RHS + 2846281732U, // <5,7,5,5>: Cost 3 vuzpr RHS, <5,5,5,5> + 2651517015U, // <5,7,5,6>: Cost 3 vext2 <5,6,5,7>, <5,6,5,7> + 1772539190U, // <5,7,5,7>: Cost 2 vuzpr RHS, RHS + 1772539191U, // <5,7,5,u>: Cost 2 vuzpr RHS, RHS + 2846281826U, // <5,7,6,0>: Cost 3 vuzpr RHS, <5,6,7,0> + 3699380615U, // <5,7,6,1>: Cost 4 vext2 <1,3,5,7>, <6,1,3,5> + 2846281108U, // <5,7,6,2>: Cost 3 vuzpr RHS, <4,6,u,2> + 2589854210U, // <5,7,6,3>: Cost 3 vext1 <6,5,7,6>, <3,4,5,6> + 2846281830U, // <5,7,6,4>: Cost 3 vuzpr RHS, <5,6,7,4> + 2725467658U, // <5,7,6,5>: Cost 3 vext3 <6,7,u,5>, <7,6,5,u> + 2846281076U, // <5,7,6,6>: Cost 3 vuzpr RHS, <4,6,4,6> + 2846279610U, // <5,7,6,7>: Cost 3 vuzpr RHS, <2,6,3,7> + 2846279611U, // <5,7,6,u>: Cost 3 vuzpr RHS, <2,6,3,u> + 1510146150U, // <5,7,7,0>: Cost 2 vext1 <5,5,7,7>, LHS + 2846282574U, // <5,7,7,1>: Cost 3 vuzpr RHS, <6,7,0,1> + 2583889512U, // <5,7,7,2>: Cost 3 vext1 <5,5,7,7>, <2,2,2,2> + 2846281919U, // <5,7,7,3>: Cost 3 vuzpr RHS, <5,7,u,3> + 1510149430U, // <5,7,7,4>: Cost 2 vext1 <5,5,7,7>, RHS + 1510150168U, // <5,7,7,5>: Cost 2 vext1 <5,5,7,7>, <5,5,7,7> + 2583892474U, // <5,7,7,6>: Cost 3 vext1 <5,5,7,7>, <6,2,7,3> + 2625640044U, // <5,7,7,7>: Cost 3 vext2 <1,3,5,7>, <7,7,7,7> + 1510151982U, // <5,7,7,u>: Cost 2 vext1 <5,5,7,7>, LHS + 1510154342U, // <5,7,u,0>: Cost 2 vext1 <5,5,7,u>, LHS + 1551898414U, // <5,7,u,1>: Cost 2 vext2 <1,3,5,7>, LHS + 2625640325U, // <5,7,u,2>: Cost 3 vext2 <1,3,5,7>, + 1772536477U, // <5,7,u,3>: Cost 2 vuzpr RHS, LHS + 1510157622U, // <5,7,u,4>: Cost 2 vext1 <5,5,7,u>, RHS + 1551898778U, // <5,7,u,5>: Cost 2 vext2 <1,3,5,7>, RHS + 2625640656U, // <5,7,u,6>: Cost 3 vext2 <1,3,5,7>, + 1772539433U, // <5,7,u,7>: Cost 2 vuzpr RHS, RHS + 1551898981U, // <5,7,u,u>: Cost 2 vext2 <1,3,5,7>, LHS + 2625642496U, // <5,u,0,0>: Cost 3 vext2 <1,3,5,u>, <0,0,0,0> + 1551900774U, // <5,u,0,1>: Cost 2 vext2 <1,3,5,u>, LHS + 2625642660U, // <5,u,0,2>: Cost 3 vext2 <1,3,5,u>, <0,2,0,2> + 2698630885U, // <5,u,0,3>: Cost 3 vext3 <2,3,4,5>, + 2687129325U, // <5,u,0,4>: Cost 3 vext3 <0,4,1,5>, + 2689783542U, // <5,u,0,5>: Cost 3 vext3 <0,u,1,5>, + 2266134675U, // <5,u,0,6>: Cost 3 vrev + 2595853772U, // <5,u,0,7>: Cost 3 vext1 <7,5,u,0>, <7,5,u,0> + 1551901341U, // <5,u,0,u>: Cost 2 vext2 <1,3,5,u>, LHS + 2625643254U, // <5,u,1,0>: Cost 3 vext2 <1,3,5,u>, <1,0,3,2> + 2625643316U, // <5,u,1,1>: Cost 3 vext2 <1,3,5,u>, <1,1,1,1> + 1613387566U, // <5,u,1,2>: Cost 2 vext3 <0,4,1,5>, LHS + 1551901697U, // <5,u,1,3>: Cost 2 vext2 <1,3,5,u>, <1,3,5,u> + 2626307154U, // <5,u,1,4>: Cost 3 vext2 <1,4,5,u>, <1,4,5,u> + 2689783622U, // <5,u,1,5>: Cost 3 vext3 <0,u,1,5>, + 2627634420U, // <5,u,1,6>: Cost 3 vext2 <1,6,5,u>, <1,6,5,u> + 2982366536U, // <5,u,1,7>: Cost 3 vzipr <4,u,5,1>, RHS + 1613387620U, // <5,u,1,u>: Cost 2 vext3 <0,4,1,5>, LHS + 2846286742U, // <5,u,2,0>: Cost 3 vuzpr RHS, <1,2,3,0> + 2685796528U, // <5,u,2,1>: Cost 3 vext3 <0,2,1,5>, <0,2,1,5> + 2625644136U, // <5,u,2,2>: Cost 3 vext2 <1,3,5,u>, <2,2,2,2> + 2687129480U, // <5,u,2,3>: Cost 3 vext3 <0,4,1,5>, + 2632279851U, // <5,u,2,4>: Cost 3 vext2 <2,4,5,u>, <2,4,5,u> + 2625644394U, // <5,u,2,5>: Cost 3 vext2 <1,3,5,u>, <2,5,3,u> + 2625644474U, // <5,u,2,6>: Cost 3 vext2 <1,3,5,u>, <2,6,3,7> + 2713966508U, // <5,u,2,7>: Cost 3 vext3 <4,u,5,5>, + 2625644603U, // <5,u,2,u>: Cost 3 vext2 <1,3,5,u>, <2,u,0,1> + 2687129532U, // <5,u,3,0>: Cost 3 vext3 <0,4,1,5>, + 2636261649U, // <5,u,3,1>: Cost 3 vext2 <3,1,5,u>, <3,1,5,u> + 2636925282U, // <5,u,3,2>: Cost 3 vext2 <3,2,5,u>, <3,2,5,u> + 2625644956U, // <5,u,3,3>: Cost 3 vext2 <1,3,5,u>, <3,3,3,3> + 1564510724U, // <5,u,3,4>: Cost 2 vext2 <3,4,5,u>, <3,4,5,u> + 2625645160U, // <5,u,3,5>: Cost 3 vext2 <1,3,5,u>, <3,5,u,0> + 2734610422U, // <5,u,3,6>: Cost 3 vext3 , + 2640243447U, // <5,u,3,7>: Cost 3 vext2 <3,7,5,u>, <3,7,5,u> + 1567165256U, // <5,u,3,u>: Cost 2 vext2 <3,u,5,u>, <3,u,5,u> + 1567828889U, // <5,u,4,0>: Cost 2 vext2 <4,0,5,u>, <4,0,5,u> + 1661163546U, // <5,u,4,1>: Cost 2 vext3 , + 2734463012U, // <5,u,4,2>: Cost 3 vext3 , + 2698631212U, // <5,u,4,3>: Cost 3 vext3 <2,3,4,5>, + 1570458842U, // <5,u,4,4>: Cost 2 vext2 <4,4,5,5>, <4,4,5,5> + 1551904054U, // <5,u,4,5>: Cost 2 vext2 <1,3,5,u>, RHS + 2846286172U, // <5,u,4,6>: Cost 3 vuzpr RHS, <0,4,2,6> + 2646216144U, // <5,u,4,7>: Cost 3 vext2 <4,7,5,u>, <4,7,5,u> + 1551904297U, // <5,u,4,u>: Cost 2 vext2 <1,3,5,u>, RHS + 1509982310U, // <5,u,5,0>: Cost 2 vext1 <5,5,5,5>, LHS + 2560058555U, // <5,u,5,1>: Cost 3 vext1 <1,5,u,5>, <1,5,u,5> + 2698926194U, // <5,u,5,2>: Cost 3 vext3 <2,3,u,5>, + 2698631295U, // <5,u,5,3>: Cost 3 vext3 <2,3,4,5>, + 1509985590U, // <5,u,5,4>: Cost 2 vext1 <5,5,5,5>, RHS + 229035318U, // <5,u,5,5>: Cost 1 vdup1 RHS + 1613387930U, // <5,u,5,6>: Cost 2 vext3 <0,4,1,5>, RHS + 1772547382U, // <5,u,5,7>: Cost 2 vuzpr RHS, RHS + 229035318U, // <5,u,5,u>: Cost 1 vdup1 RHS + 2566037606U, // <5,u,6,0>: Cost 3 vext1 <2,5,u,6>, LHS + 2920044334U, // <5,u,6,1>: Cost 3 vzipl <5,6,7,0>, LHS + 2566039445U, // <5,u,6,2>: Cost 3 vext1 <2,5,u,6>, <2,5,u,6> + 2687129808U, // <5,u,6,3>: Cost 3 vext3 <0,4,1,5>, + 2566040886U, // <5,u,6,4>: Cost 3 vext1 <2,5,u,6>, RHS + 2920044698U, // <5,u,6,5>: Cost 3 vzipl <5,6,7,0>, RHS + 2846289268U, // <5,u,6,6>: Cost 3 vuzpr RHS, <4,6,4,6> + 2973781320U, // <5,u,6,7>: Cost 3 vzipr <3,4,5,6>, RHS + 2687129853U, // <5,u,6,u>: Cost 3 vext3 <0,4,1,5>, + 430506086U, // <5,u,7,0>: Cost 1 vext1 RHS, LHS + 1486333117U, // <5,u,7,1>: Cost 2 vext1 <1,5,u,7>, <1,5,u,7> + 1504249448U, // <5,u,7,2>: Cost 2 vext1 RHS, <2,2,2,2> + 2040971933U, // <5,u,7,3>: Cost 2 vtrnr RHS, LHS + 430509384U, // <5,u,7,4>: Cost 1 vext1 RHS, RHS + 1504251600U, // <5,u,7,5>: Cost 2 vext1 RHS, <5,1,7,3> + 118708378U, // <5,u,7,6>: Cost 1 vrev RHS + 2040974889U, // <5,u,7,7>: Cost 2 vtrnr RHS, RHS + 430511918U, // <5,u,7,u>: Cost 1 vext1 RHS, LHS + 430514278U, // <5,u,u,0>: Cost 1 vext1 RHS, LHS + 1551906606U, // <5,u,u,1>: Cost 2 vext2 <1,3,5,u>, LHS + 1613388133U, // <5,u,u,2>: Cost 2 vext3 <0,4,1,5>, LHS + 1772544669U, // <5,u,u,3>: Cost 2 vuzpr RHS, LHS + 430517577U, // <5,u,u,4>: Cost 1 vext1 RHS, RHS + 229035318U, // <5,u,u,5>: Cost 1 vdup1 RHS + 118716571U, // <5,u,u,6>: Cost 1 vrev RHS + 1772547625U, // <5,u,u,7>: Cost 2 vuzpr RHS, RHS + 430520110U, // <5,u,u,u>: Cost 1 vext1 RHS, LHS + 2686025728U, // <6,0,0,0>: Cost 3 vext3 <0,2,4,6>, <0,0,0,0> + 2686025738U, // <6,0,0,1>: Cost 3 vext3 <0,2,4,6>, <0,0,1,1> + 2686025748U, // <6,0,0,2>: Cost 3 vext3 <0,2,4,6>, <0,0,2,2> + 3779084320U, // <6,0,0,3>: Cost 4 vext3 <3,4,5,6>, <0,0,3,5> + 2642903388U, // <6,0,0,4>: Cost 3 vext2 <4,2,6,0>, <0,4,2,6> + 3657723939U, // <6,0,0,5>: Cost 4 vext1 <5,6,0,0>, <5,6,0,0> + 3926676514U, // <6,0,0,6>: Cost 4 vuzpr <5,6,7,0>, <7,0,5,6> + 3926675786U, // <6,0,0,7>: Cost 4 vuzpr <5,6,7,0>, <6,0,5,7> + 2686025802U, // <6,0,0,u>: Cost 3 vext3 <0,2,4,6>, <0,0,u,2> + 2566070374U, // <6,0,1,0>: Cost 3 vext1 <2,6,0,1>, LHS + 3759767642U, // <6,0,1,1>: Cost 4 vext3 <0,2,4,6>, <0,1,1,0> + 1612284006U, // <6,0,1,2>: Cost 2 vext3 <0,2,4,6>, LHS + 2583988738U, // <6,0,1,3>: Cost 3 vext1 <5,6,0,1>, <3,4,5,6> + 2566073654U, // <6,0,1,4>: Cost 3 vext1 <2,6,0,1>, RHS + 2583990308U, // <6,0,1,5>: Cost 3 vext1 <5,6,0,1>, <5,6,0,1> + 2589963005U, // <6,0,1,6>: Cost 3 vext1 <6,6,0,1>, <6,6,0,1> + 2595935702U, // <6,0,1,7>: Cost 3 vext1 <7,6,0,1>, <7,6,0,1> + 1612284060U, // <6,0,1,u>: Cost 2 vext3 <0,2,4,6>, LHS + 2686025892U, // <6,0,2,0>: Cost 3 vext3 <0,2,4,6>, <0,2,0,2> + 2685804721U, // <6,0,2,1>: Cost 3 vext3 <0,2,1,6>, <0,2,1,6> + 3759620282U, // <6,0,2,2>: Cost 4 vext3 <0,2,2,6>, <0,2,2,6> + 2705342658U, // <6,0,2,3>: Cost 3 vext3 <3,4,5,6>, <0,2,3,5> + 1612284108U, // <6,0,2,4>: Cost 2 vext3 <0,2,4,6>, <0,2,4,6> + 3706029956U, // <6,0,2,5>: Cost 4 vext2 <2,4,6,0>, <2,5,6,7> + 2686173406U, // <6,0,2,6>: Cost 3 vext3 <0,2,6,6>, <0,2,6,6> + 3651769338U, // <6,0,2,7>: Cost 4 vext1 <4,6,0,2>, <7,0,1,2> + 1612579056U, // <6,0,2,u>: Cost 2 vext3 <0,2,u,6>, <0,2,u,6> + 3706030230U, // <6,0,3,0>: Cost 4 vext2 <2,4,6,0>, <3,0,1,2> + 2705342720U, // <6,0,3,1>: Cost 3 vext3 <3,4,5,6>, <0,3,1,4> + 2705342730U, // <6,0,3,2>: Cost 3 vext3 <3,4,5,6>, <0,3,2,5> + 3706030492U, // <6,0,3,3>: Cost 4 vext2 <2,4,6,0>, <3,3,3,3> + 2644896258U, // <6,0,3,4>: Cost 3 vext2 <4,5,6,0>, <3,4,5,6> + 3718638154U, // <6,0,3,5>: Cost 4 vext2 <4,5,6,0>, <3,5,4,6> + 3729918619U, // <6,0,3,6>: Cost 4 vext2 <6,4,6,0>, <3,6,4,6> + 3926672384U, // <6,0,3,7>: Cost 4 vuzpr <5,6,7,0>, <1,3,5,7> + 2705342784U, // <6,0,3,u>: Cost 3 vext3 <3,4,5,6>, <0,3,u,5> + 2687058250U, // <6,0,4,0>: Cost 3 vext3 <0,4,0,6>, <0,4,0,6> + 2686026066U, // <6,0,4,1>: Cost 3 vext3 <0,2,4,6>, <0,4,1,5> + 1613463900U, // <6,0,4,2>: Cost 2 vext3 <0,4,2,6>, <0,4,2,6> + 3761021285U, // <6,0,4,3>: Cost 4 vext3 <0,4,3,6>, <0,4,3,6> + 2687353198U, // <6,0,4,4>: Cost 3 vext3 <0,4,4,6>, <0,4,4,6> + 2632289590U, // <6,0,4,5>: Cost 3 vext2 <2,4,6,0>, RHS + 2645560704U, // <6,0,4,6>: Cost 3 vext2 <4,6,6,0>, <4,6,6,0> + 2646224337U, // <6,0,4,7>: Cost 3 vext2 <4,7,6,0>, <4,7,6,0> + 1613906322U, // <6,0,4,u>: Cost 2 vext3 <0,4,u,6>, <0,4,u,6> + 3651788902U, // <6,0,5,0>: Cost 4 vext1 <4,6,0,5>, LHS + 2687795620U, // <6,0,5,1>: Cost 3 vext3 <0,5,1,6>, <0,5,1,6> + 3761611181U, // <6,0,5,2>: Cost 4 vext3 <0,5,2,6>, <0,5,2,6> + 3723284326U, // <6,0,5,3>: Cost 4 vext2 <5,3,6,0>, <5,3,6,0> + 2646224838U, // <6,0,5,4>: Cost 3 vext2 <4,7,6,0>, <5,4,7,6> + 3718639630U, // <6,0,5,5>: Cost 4 vext2 <4,5,6,0>, <5,5,6,6> + 2652196962U, // <6,0,5,6>: Cost 3 vext2 <5,7,6,0>, <5,6,7,0> + 2852932918U, // <6,0,5,7>: Cost 3 vuzpr <5,6,7,0>, RHS + 2852932919U, // <6,0,5,u>: Cost 3 vuzpr <5,6,7,0>, RHS + 2852933730U, // <6,0,6,0>: Cost 3 vuzpr <5,6,7,0>, <5,6,7,0> + 2925985894U, // <6,0,6,1>: Cost 3 vzipl <6,6,6,6>, LHS + 3060203622U, // <6,0,6,2>: Cost 3 vtrnl <6,6,6,6>, LHS + 3718640178U, // <6,0,6,3>: Cost 4 vext2 <4,5,6,0>, <6,3,4,5> + 2656178832U, // <6,0,6,4>: Cost 3 vext2 <6,4,6,0>, <6,4,6,0> + 3725939378U, // <6,0,6,5>: Cost 4 vext2 <5,7,6,0>, <6,5,0,7> + 2657506098U, // <6,0,6,6>: Cost 3 vext2 <6,6,6,0>, <6,6,6,0> + 2619020110U, // <6,0,6,7>: Cost 3 vext2 <0,2,6,0>, <6,7,0,1> + 2925986461U, // <6,0,6,u>: Cost 3 vzipl <6,6,6,6>, LHS + 2572091494U, // <6,0,7,0>: Cost 3 vext1 <3,6,0,7>, LHS + 2572092310U, // <6,0,7,1>: Cost 3 vext1 <3,6,0,7>, <1,2,3,0> + 2980495524U, // <6,0,7,2>: Cost 3 vzipr RHS, <0,2,0,2> + 2572094072U, // <6,0,7,3>: Cost 3 vext1 <3,6,0,7>, <3,6,0,7> + 2572094774U, // <6,0,7,4>: Cost 3 vext1 <3,6,0,7>, RHS + 4054238242U, // <6,0,7,5>: Cost 4 vzipr RHS, <1,4,0,5> + 3645837653U, // <6,0,7,6>: Cost 4 vext1 <3,6,0,7>, <6,0,7,0> + 4054239054U, // <6,0,7,7>: Cost 4 vzipr RHS, <2,5,0,7> + 2572097326U, // <6,0,7,u>: Cost 3 vext1 <3,6,0,7>, LHS + 2686026378U, // <6,0,u,0>: Cost 3 vext3 <0,2,4,6>, <0,u,0,2> + 2686026386U, // <6,0,u,1>: Cost 3 vext3 <0,2,4,6>, <0,u,1,1> + 1612284573U, // <6,0,u,2>: Cost 2 vext3 <0,2,4,6>, LHS + 2705343144U, // <6,0,u,3>: Cost 3 vext3 <3,4,5,6>, <0,u,3,5> + 1616265906U, // <6,0,u,4>: Cost 2 vext3 <0,u,4,6>, <0,u,4,6> + 2632292506U, // <6,0,u,5>: Cost 3 vext2 <2,4,6,0>, RHS + 2590020356U, // <6,0,u,6>: Cost 3 vext1 <6,6,0,u>, <6,6,0,u> + 2852933161U, // <6,0,u,7>: Cost 3 vuzpr <5,6,7,0>, RHS + 1612284627U, // <6,0,u,u>: Cost 2 vext3 <0,2,4,6>, LHS + 2595995750U, // <6,1,0,0>: Cost 3 vext1 <7,6,1,0>, LHS + 2646229094U, // <6,1,0,1>: Cost 3 vext2 <4,7,6,1>, LHS + 3694092492U, // <6,1,0,2>: Cost 4 vext2 <0,4,6,1>, <0,2,4,6> + 2686026486U, // <6,1,0,3>: Cost 3 vext3 <0,2,4,6>, <1,0,3,2> + 2595999030U, // <6,1,0,4>: Cost 3 vext1 <7,6,1,0>, RHS + 3767730952U, // <6,1,0,5>: Cost 4 vext3 <1,5,4,6>, <1,0,5,2> + 2596000590U, // <6,1,0,6>: Cost 3 vext1 <7,6,1,0>, <6,7,0,1> + 2596001246U, // <6,1,0,7>: Cost 3 vext1 <7,6,1,0>, <7,6,1,0> + 2686026531U, // <6,1,0,u>: Cost 3 vext3 <0,2,4,6>, <1,0,u,2> + 3763602219U, // <6,1,1,0>: Cost 4 vext3 <0,u,2,6>, <1,1,0,1> + 2686026548U, // <6,1,1,1>: Cost 3 vext3 <0,2,4,6>, <1,1,1,1> + 3764929346U, // <6,1,1,2>: Cost 4 vext3 <1,1,2,6>, <1,1,2,6> + 2686026568U, // <6,1,1,3>: Cost 3 vext3 <0,2,4,6>, <1,1,3,3> + 2691334996U, // <6,1,1,4>: Cost 3 vext3 <1,1,4,6>, <1,1,4,6> + 3760874332U, // <6,1,1,5>: Cost 4 vext3 <0,4,1,6>, <1,1,5,5> + 3765224294U, // <6,1,1,6>: Cost 4 vext3 <1,1,6,6>, <1,1,6,6> + 3669751263U, // <6,1,1,7>: Cost 4 vext1 <7,6,1,1>, <7,6,1,1> + 2686026613U, // <6,1,1,u>: Cost 3 vext3 <0,2,4,6>, <1,1,u,3> + 2554208358U, // <6,1,2,0>: Cost 3 vext1 <0,6,1,2>, LHS + 3763602311U, // <6,1,2,1>: Cost 4 vext3 <0,u,2,6>, <1,2,1,3> + 3639895971U, // <6,1,2,2>: Cost 4 vext1 <2,6,1,2>, <2,6,1,2> + 2686026646U, // <6,1,2,3>: Cost 3 vext3 <0,2,4,6>, <1,2,3,0> + 2554211638U, // <6,1,2,4>: Cost 3 vext1 <0,6,1,2>, RHS + 3760874411U, // <6,1,2,5>: Cost 4 vext3 <0,4,1,6>, <1,2,5,3> + 2554212858U, // <6,1,2,6>: Cost 3 vext1 <0,6,1,2>, <6,2,7,3> + 3802973114U, // <6,1,2,7>: Cost 4 vext3 <7,4,5,6>, <1,2,7,0> + 2686026691U, // <6,1,2,u>: Cost 3 vext3 <0,2,4,6>, <1,2,u,0> + 2566160486U, // <6,1,3,0>: Cost 3 vext1 <2,6,1,3>, LHS + 2686026712U, // <6,1,3,1>: Cost 3 vext3 <0,2,4,6>, <1,3,1,3> + 2686026724U, // <6,1,3,2>: Cost 3 vext3 <0,2,4,6>, <1,3,2,6> + 3759768552U, // <6,1,3,3>: Cost 4 vext3 <0,2,4,6>, <1,3,3,1> + 2692662262U, // <6,1,3,4>: Cost 3 vext3 <1,3,4,6>, <1,3,4,6> + 2686026752U, // <6,1,3,5>: Cost 3 vext3 <0,2,4,6>, <1,3,5,7> + 2590053128U, // <6,1,3,6>: Cost 3 vext1 <6,6,1,3>, <6,6,1,3> + 3663795194U, // <6,1,3,7>: Cost 4 vext1 <6,6,1,3>, <7,0,1,2> + 2686026775U, // <6,1,3,u>: Cost 3 vext3 <0,2,4,6>, <1,3,u,3> + 2641587099U, // <6,1,4,0>: Cost 3 vext2 <4,0,6,1>, <4,0,6,1> + 2693104684U, // <6,1,4,1>: Cost 3 vext3 <1,4,1,6>, <1,4,1,6> + 3639912357U, // <6,1,4,2>: Cost 4 vext1 <2,6,1,4>, <2,6,1,4> + 2687206462U, // <6,1,4,3>: Cost 3 vext3 <0,4,2,6>, <1,4,3,6> + 3633941814U, // <6,1,4,4>: Cost 4 vext1 <1,6,1,4>, RHS + 2693399632U, // <6,1,4,5>: Cost 3 vext3 <1,4,5,6>, <1,4,5,6> + 3765077075U, // <6,1,4,6>: Cost 4 vext3 <1,1,4,6>, <1,4,6,0> + 2646232530U, // <6,1,4,7>: Cost 3 vext2 <4,7,6,1>, <4,7,6,1> + 2687206507U, // <6,1,4,u>: Cost 3 vext3 <0,4,2,6>, <1,4,u,6> + 2647559796U, // <6,1,5,0>: Cost 3 vext2 <5,0,6,1>, <5,0,6,1> + 3765077118U, // <6,1,5,1>: Cost 4 vext3 <1,1,4,6>, <1,5,1,7> + 3767583878U, // <6,1,5,2>: Cost 4 vext3 <1,5,2,6>, <1,5,2,6> + 2686026896U, // <6,1,5,3>: Cost 3 vext3 <0,2,4,6>, <1,5,3,7> + 2693989528U, // <6,1,5,4>: Cost 3 vext3 <1,5,4,6>, <1,5,4,6> + 3767805089U, // <6,1,5,5>: Cost 4 vext3 <1,5,5,6>, <1,5,5,6> + 2652868706U, // <6,1,5,6>: Cost 3 vext2 <5,u,6,1>, <5,6,7,0> + 3908250934U, // <6,1,5,7>: Cost 4 vuzpr <2,6,0,1>, RHS + 2686026941U, // <6,1,5,u>: Cost 3 vext3 <0,2,4,6>, <1,5,u,7> + 2554241126U, // <6,1,6,0>: Cost 3 vext1 <0,6,1,6>, LHS + 3763602639U, // <6,1,6,1>: Cost 4 vext3 <0,u,2,6>, <1,6,1,7> + 3759547607U, // <6,1,6,2>: Cost 4 vext3 <0,2,1,6>, <1,6,2,6> + 3115221094U, // <6,1,6,3>: Cost 3 vtrnr <4,6,4,6>, LHS + 2554244406U, // <6,1,6,4>: Cost 3 vext1 <0,6,1,6>, RHS + 3760874739U, // <6,1,6,5>: Cost 4 vext3 <0,4,1,6>, <1,6,5,7> + 2554245944U, // <6,1,6,6>: Cost 3 vext1 <0,6,1,6>, <6,6,6,6> + 3719975758U, // <6,1,6,7>: Cost 4 vext2 <4,7,6,1>, <6,7,0,1> + 3115221099U, // <6,1,6,u>: Cost 3 vtrnr <4,6,4,6>, LHS + 2560221286U, // <6,1,7,0>: Cost 3 vext1 <1,6,1,7>, LHS + 2560222415U, // <6,1,7,1>: Cost 3 vext1 <1,6,1,7>, <1,6,1,7> + 2980497558U, // <6,1,7,2>: Cost 3 vzipr RHS, <3,0,1,2> + 3103211622U, // <6,1,7,3>: Cost 3 vtrnr <2,6,3,7>, LHS + 2560224566U, // <6,1,7,4>: Cost 3 vext1 <1,6,1,7>, RHS + 2980495698U, // <6,1,7,5>: Cost 3 vzipr RHS, <0,4,1,5> + 3633967526U, // <6,1,7,6>: Cost 4 vext1 <1,6,1,7>, <6,1,7,0> + 4054237686U, // <6,1,7,7>: Cost 4 vzipr RHS, <0,6,1,7> + 2560227118U, // <6,1,7,u>: Cost 3 vext1 <1,6,1,7>, LHS + 2560229478U, // <6,1,u,0>: Cost 3 vext1 <1,6,1,u>, LHS + 2686027117U, // <6,1,u,1>: Cost 3 vext3 <0,2,4,6>, <1,u,1,3> + 2686027129U, // <6,1,u,2>: Cost 3 vext3 <0,2,4,6>, <1,u,2,6> + 2686027132U, // <6,1,u,3>: Cost 3 vext3 <0,2,4,6>, <1,u,3,0> + 2687206795U, // <6,1,u,4>: Cost 3 vext3 <0,4,2,6>, <1,u,4,6> + 2686027157U, // <6,1,u,5>: Cost 3 vext3 <0,2,4,6>, <1,u,5,7> + 2590094093U, // <6,1,u,6>: Cost 3 vext1 <6,6,1,u>, <6,6,1,u> + 2596066790U, // <6,1,u,7>: Cost 3 vext1 <7,6,1,u>, <7,6,1,u> + 2686027177U, // <6,1,u,u>: Cost 3 vext3 <0,2,4,6>, <1,u,u,0> + 2646900736U, // <6,2,0,0>: Cost 3 vext2 <4,u,6,2>, <0,0,0,0> + 1573159014U, // <6,2,0,1>: Cost 2 vext2 <4,u,6,2>, LHS + 2646900900U, // <6,2,0,2>: Cost 3 vext2 <4,u,6,2>, <0,2,0,2> + 3759769037U, // <6,2,0,3>: Cost 4 vext3 <0,2,4,6>, <2,0,3,0> + 2641592668U, // <6,2,0,4>: Cost 3 vext2 <4,0,6,2>, <0,4,2,6> + 3779085794U, // <6,2,0,5>: Cost 4 vext3 <3,4,5,6>, <2,0,5,3> + 2686027244U, // <6,2,0,6>: Cost 3 vext3 <0,2,4,6>, <2,0,6,4> + 3669816807U, // <6,2,0,7>: Cost 4 vext1 <7,6,2,0>, <7,6,2,0> + 1573159581U, // <6,2,0,u>: Cost 2 vext2 <4,u,6,2>, LHS + 2230527897U, // <6,2,1,0>: Cost 3 vrev <2,6,0,1> + 2646901556U, // <6,2,1,1>: Cost 3 vext2 <4,u,6,2>, <1,1,1,1> + 2646901654U, // <6,2,1,2>: Cost 3 vext2 <4,u,6,2>, <1,2,3,0> + 2847047782U, // <6,2,1,3>: Cost 3 vuzpr <4,6,u,2>, LHS + 3771049517U, // <6,2,1,4>: Cost 4 vext3 <2,1,4,6>, <2,1,4,6> + 2646901904U, // <6,2,1,5>: Cost 3 vext2 <4,u,6,2>, <1,5,3,7> + 2686027324U, // <6,2,1,6>: Cost 3 vext3 <0,2,4,6>, <2,1,6,3> + 3669825000U, // <6,2,1,7>: Cost 4 vext1 <7,6,2,1>, <7,6,2,1> + 2231117793U, // <6,2,1,u>: Cost 3 vrev <2,6,u,1> + 3763603029U, // <6,2,2,0>: Cost 4 vext3 <0,u,2,6>, <2,2,0,1> + 3759769184U, // <6,2,2,1>: Cost 4 vext3 <0,2,4,6>, <2,2,1,3> + 2686027368U, // <6,2,2,2>: Cost 3 vext3 <0,2,4,6>, <2,2,2,2> + 2686027378U, // <6,2,2,3>: Cost 3 vext3 <0,2,4,6>, <2,2,3,3> + 2697971326U, // <6,2,2,4>: Cost 3 vext3 <2,2,4,6>, <2,2,4,6> + 3759769224U, // <6,2,2,5>: Cost 4 vext3 <0,2,4,6>, <2,2,5,7> + 2698118800U, // <6,2,2,6>: Cost 3 vext3 <2,2,6,6>, <2,2,6,6> + 3920794092U, // <6,2,2,7>: Cost 4 vuzpr <4,6,u,2>, <6,2,5,7> + 2686027423U, // <6,2,2,u>: Cost 3 vext3 <0,2,4,6>, <2,2,u,3> + 2686027430U, // <6,2,3,0>: Cost 3 vext3 <0,2,4,6>, <2,3,0,1> + 3759769262U, // <6,2,3,1>: Cost 4 vext3 <0,2,4,6>, <2,3,1,0> + 2698487485U, // <6,2,3,2>: Cost 3 vext3 <2,3,2,6>, <2,3,2,6> + 2705344196U, // <6,2,3,3>: Cost 3 vext3 <3,4,5,6>, <2,3,3,4> + 2686027470U, // <6,2,3,4>: Cost 3 vext3 <0,2,4,6>, <2,3,4,5> + 2698708696U, // <6,2,3,5>: Cost 3 vext3 <2,3,5,6>, <2,3,5,6> + 2724660961U, // <6,2,3,6>: Cost 3 vext3 <6,6,6,6>, <2,3,6,6> + 2729232104U, // <6,2,3,7>: Cost 3 vext3 <7,4,5,6>, <2,3,7,4> + 2686027502U, // <6,2,3,u>: Cost 3 vext3 <0,2,4,6>, <2,3,u,1> + 1567853468U, // <6,2,4,0>: Cost 2 vext2 <4,0,6,2>, <4,0,6,2> + 3759769351U, // <6,2,4,1>: Cost 4 vext3 <0,2,4,6>, <2,4,1,u> + 2699151118U, // <6,2,4,2>: Cost 3 vext3 <2,4,2,6>, <2,4,2,6> + 2686027543U, // <6,2,4,3>: Cost 3 vext3 <0,2,4,6>, <2,4,3,6> + 2699298592U, // <6,2,4,4>: Cost 3 vext3 <2,4,4,6>, <2,4,4,6> + 1573162294U, // <6,2,4,5>: Cost 2 vext2 <4,u,6,2>, RHS + 2686027564U, // <6,2,4,6>: Cost 3 vext3 <0,2,4,6>, <2,4,6,0> + 3719982547U, // <6,2,4,7>: Cost 4 vext2 <4,7,6,2>, <4,7,6,2> + 1573162532U, // <6,2,4,u>: Cost 2 vext2 <4,u,6,2>, <4,u,6,2> + 3779086154U, // <6,2,5,0>: Cost 4 vext3 <3,4,5,6>, <2,5,0,3> + 2646904528U, // <6,2,5,1>: Cost 3 vext2 <4,u,6,2>, <5,1,7,3> + 3759769440U, // <6,2,5,2>: Cost 4 vext3 <0,2,4,6>, <2,5,2,7> + 2699888488U, // <6,2,5,3>: Cost 3 vext3 <2,5,3,6>, <2,5,3,6> + 2230855617U, // <6,2,5,4>: Cost 3 vrev <2,6,4,5> + 2646904836U, // <6,2,5,5>: Cost 3 vext2 <4,u,6,2>, <5,5,5,5> + 2646904930U, // <6,2,5,6>: Cost 3 vext2 <4,u,6,2>, <5,6,7,0> + 2847051062U, // <6,2,5,7>: Cost 3 vuzpr <4,6,u,2>, RHS + 2700257173U, // <6,2,5,u>: Cost 3 vext3 <2,5,u,6>, <2,5,u,6> + 2687207321U, // <6,2,6,0>: Cost 3 vext3 <0,4,2,6>, <2,6,0,1> + 2686027684U, // <6,2,6,1>: Cost 3 vext3 <0,2,4,6>, <2,6,1,3> + 2566260656U, // <6,2,6,2>: Cost 3 vext1 <2,6,2,6>, <2,6,2,6> + 2685806522U, // <6,2,6,3>: Cost 3 vext3 <0,2,1,6>, <2,6,3,7> + 2687207361U, // <6,2,6,4>: Cost 3 vext3 <0,4,2,6>, <2,6,4,5> + 2686027724U, // <6,2,6,5>: Cost 3 vext3 <0,2,4,6>, <2,6,5,7> + 2646905656U, // <6,2,6,6>: Cost 3 vext2 <4,u,6,2>, <6,6,6,6> + 2646905678U, // <6,2,6,7>: Cost 3 vext2 <4,u,6,2>, <6,7,0,1> + 2686027751U, // <6,2,6,u>: Cost 3 vext3 <0,2,4,6>, <2,6,u,7> + 2554323046U, // <6,2,7,0>: Cost 3 vext1 <0,6,2,7>, LHS + 2572239606U, // <6,2,7,1>: Cost 3 vext1 <3,6,2,7>, <1,0,3,2> + 2566268849U, // <6,2,7,2>: Cost 3 vext1 <2,6,2,7>, <2,6,2,7> + 1906753638U, // <6,2,7,3>: Cost 2 vzipr RHS, LHS + 2554326326U, // <6,2,7,4>: Cost 3 vext1 <0,6,2,7>, RHS + 3304687564U, // <6,2,7,5>: Cost 4 vrev <2,6,5,7> + 2980495708U, // <6,2,7,6>: Cost 3 vzipr RHS, <0,4,2,6> + 2646906476U, // <6,2,7,7>: Cost 3 vext2 <4,u,6,2>, <7,7,7,7> + 1906753643U, // <6,2,7,u>: Cost 2 vzipr RHS, LHS + 1591744256U, // <6,2,u,0>: Cost 2 vext2 , + 1573164846U, // <6,2,u,1>: Cost 2 vext2 <4,u,6,2>, LHS + 2701805650U, // <6,2,u,2>: Cost 3 vext3 <2,u,2,6>, <2,u,2,6> + 1906761830U, // <6,2,u,3>: Cost 2 vzipr RHS, LHS + 2686027875U, // <6,2,u,4>: Cost 3 vext3 <0,2,4,6>, <2,u,4,5> + 1573165210U, // <6,2,u,5>: Cost 2 vext2 <4,u,6,2>, RHS + 2686322800U, // <6,2,u,6>: Cost 3 vext3 <0,2,u,6>, <2,u,6,0> + 2847051305U, // <6,2,u,7>: Cost 3 vuzpr <4,6,u,2>, RHS + 1906761835U, // <6,2,u,u>: Cost 2 vzipr RHS, LHS + 3759769739U, // <6,3,0,0>: Cost 4 vext3 <0,2,4,6>, <3,0,0,0> + 2686027926U, // <6,3,0,1>: Cost 3 vext3 <0,2,4,6>, <3,0,1,2> + 2686027937U, // <6,3,0,2>: Cost 3 vext3 <0,2,4,6>, <3,0,2,4> + 3640027286U, // <6,3,0,3>: Cost 4 vext1 <2,6,3,0>, <3,0,1,2> + 2687207601U, // <6,3,0,4>: Cost 3 vext3 <0,4,2,6>, <3,0,4,2> + 2705344698U, // <6,3,0,5>: Cost 3 vext3 <3,4,5,6>, <3,0,5,2> + 3663917847U, // <6,3,0,6>: Cost 4 vext1 <6,6,3,0>, <6,6,3,0> + 2237008560U, // <6,3,0,7>: Cost 3 vrev <3,6,7,0> + 2686027989U, // <6,3,0,u>: Cost 3 vext3 <0,2,4,6>, <3,0,u,2> + 3759769823U, // <6,3,1,0>: Cost 4 vext3 <0,2,4,6>, <3,1,0,3> + 3759769830U, // <6,3,1,1>: Cost 4 vext3 <0,2,4,6>, <3,1,1,1> + 3759769841U, // <6,3,1,2>: Cost 4 vext3 <0,2,4,6>, <3,1,2,3> + 3759769848U, // <6,3,1,3>: Cost 4 vext3 <0,2,4,6>, <3,1,3,1> + 2703280390U, // <6,3,1,4>: Cost 3 vext3 <3,1,4,6>, <3,1,4,6> + 3759769868U, // <6,3,1,5>: Cost 4 vext3 <0,2,4,6>, <3,1,5,3> + 3704063194U, // <6,3,1,6>: Cost 4 vext2 <2,1,6,3>, <1,6,3,0> + 3767732510U, // <6,3,1,7>: Cost 4 vext3 <1,5,4,6>, <3,1,7,3> + 2703280390U, // <6,3,1,u>: Cost 3 vext3 <3,1,4,6>, <3,1,4,6> + 3704063468U, // <6,3,2,0>: Cost 4 vext2 <2,1,6,3>, <2,0,6,4> + 2630321724U, // <6,3,2,1>: Cost 3 vext2 <2,1,6,3>, <2,1,6,3> + 3759769921U, // <6,3,2,2>: Cost 4 vext3 <0,2,4,6>, <3,2,2,2> + 3759769928U, // <6,3,2,3>: Cost 4 vext3 <0,2,4,6>, <3,2,3,0> + 3704063767U, // <6,3,2,4>: Cost 4 vext2 <2,1,6,3>, <2,4,3,6> + 3704063876U, // <6,3,2,5>: Cost 4 vext2 <2,1,6,3>, <2,5,6,7> + 2636957626U, // <6,3,2,6>: Cost 3 vext2 <3,2,6,3>, <2,6,3,7> + 3777907058U, // <6,3,2,7>: Cost 4 vext3 <3,2,7,6>, <3,2,7,6> + 2630321724U, // <6,3,2,u>: Cost 3 vext2 <2,1,6,3>, <2,1,6,3> + 3759769983U, // <6,3,3,0>: Cost 4 vext3 <0,2,4,6>, <3,3,0,1> + 3710036245U, // <6,3,3,1>: Cost 4 vext2 <3,1,6,3>, <3,1,6,3> + 2636958054U, // <6,3,3,2>: Cost 3 vext2 <3,2,6,3>, <3,2,6,3> + 2686028188U, // <6,3,3,3>: Cost 3 vext3 <0,2,4,6>, <3,3,3,3> + 2704607656U, // <6,3,3,4>: Cost 3 vext3 <3,3,4,6>, <3,3,4,6> + 3773041072U, // <6,3,3,5>: Cost 4 vext3 <2,4,4,6>, <3,3,5,5> + 3711363731U, // <6,3,3,6>: Cost 4 vext2 <3,3,6,3>, <3,6,3,7> + 3767732676U, // <6,3,3,7>: Cost 4 vext3 <1,5,4,6>, <3,3,7,7> + 2707999179U, // <6,3,3,u>: Cost 3 vext3 <3,u,5,6>, <3,3,u,5> + 2584232038U, // <6,3,4,0>: Cost 3 vext1 <5,6,3,4>, LHS + 2642267118U, // <6,3,4,1>: Cost 3 vext2 <4,1,6,3>, <4,1,6,3> + 2642930751U, // <6,3,4,2>: Cost 3 vext2 <4,2,6,3>, <4,2,6,3> + 2705197552U, // <6,3,4,3>: Cost 3 vext3 <3,4,3,6>, <3,4,3,6> + 2584235318U, // <6,3,4,4>: Cost 3 vext1 <5,6,3,4>, RHS + 1631603202U, // <6,3,4,5>: Cost 2 vext3 <3,4,5,6>, <3,4,5,6> + 2654211444U, // <6,3,4,6>: Cost 3 vext2 <6,1,6,3>, <4,6,4,6> + 2237041332U, // <6,3,4,7>: Cost 3 vrev <3,6,7,4> + 1631824413U, // <6,3,4,u>: Cost 2 vext3 <3,4,u,6>, <3,4,u,6> + 3640066150U, // <6,3,5,0>: Cost 4 vext1 <2,6,3,5>, LHS + 3772746288U, // <6,3,5,1>: Cost 4 vext3 <2,4,0,6>, <3,5,1,7> + 3640067790U, // <6,3,5,2>: Cost 4 vext1 <2,6,3,5>, <2,3,4,5> + 3773041216U, // <6,3,5,3>: Cost 4 vext3 <2,4,4,6>, <3,5,3,5> + 2705934922U, // <6,3,5,4>: Cost 3 vext3 <3,5,4,6>, <3,5,4,6> + 3773041236U, // <6,3,5,5>: Cost 4 vext3 <2,4,4,6>, <3,5,5,7> + 3779086940U, // <6,3,5,6>: Cost 4 vext3 <3,4,5,6>, <3,5,6,6> + 3767732831U, // <6,3,5,7>: Cost 4 vext3 <1,5,4,6>, <3,5,7,0> + 2706229870U, // <6,3,5,u>: Cost 3 vext3 <3,5,u,6>, <3,5,u,6> + 2602164326U, // <6,3,6,0>: Cost 3 vext1 , LHS + 2654212512U, // <6,3,6,1>: Cost 3 vext2 <6,1,6,3>, <6,1,6,3> + 2566334393U, // <6,3,6,2>: Cost 3 vext1 <2,6,3,6>, <2,6,3,6> + 3704066588U, // <6,3,6,3>: Cost 4 vext2 <2,1,6,3>, <6,3,2,1> + 2602167524U, // <6,3,6,4>: Cost 3 vext1 , <4,4,6,6> + 3710702321U, // <6,3,6,5>: Cost 4 vext2 <3,2,6,3>, <6,5,7,7> + 2724661933U, // <6,3,6,6>: Cost 3 vext3 <6,6,6,6>, <3,6,6,6> + 3710702465U, // <6,3,6,7>: Cost 4 vext2 <3,2,6,3>, <6,7,5,7> + 2602170158U, // <6,3,6,u>: Cost 3 vext1 , LHS + 1492598886U, // <6,3,7,0>: Cost 2 vext1 <2,6,3,7>, LHS + 2560369889U, // <6,3,7,1>: Cost 3 vext1 <1,6,3,7>, <1,6,3,7> + 1492600762U, // <6,3,7,2>: Cost 2 vext1 <2,6,3,7>, <2,6,3,7> + 2566342806U, // <6,3,7,3>: Cost 3 vext1 <2,6,3,7>, <3,0,1,2> + 1492602166U, // <6,3,7,4>: Cost 2 vext1 <2,6,3,7>, RHS + 2602176208U, // <6,3,7,5>: Cost 3 vext1 , <5,1,7,3> + 2566345210U, // <6,3,7,6>: Cost 3 vext1 <2,6,3,7>, <6,2,7,3> + 2980496528U, // <6,3,7,7>: Cost 3 vzipr RHS, <1,5,3,7> + 1492604718U, // <6,3,7,u>: Cost 2 vext1 <2,6,3,7>, LHS + 1492607078U, // <6,3,u,0>: Cost 2 vext1 <2,6,3,u>, LHS + 2686028574U, // <6,3,u,1>: Cost 3 vext3 <0,2,4,6>, <3,u,1,2> + 1492608955U, // <6,3,u,2>: Cost 2 vext1 <2,6,3,u>, <2,6,3,u> + 2566350998U, // <6,3,u,3>: Cost 3 vext1 <2,6,3,u>, <3,0,1,2> + 1492610358U, // <6,3,u,4>: Cost 2 vext1 <2,6,3,u>, RHS + 1634257734U, // <6,3,u,5>: Cost 2 vext3 <3,u,5,6>, <3,u,5,6> + 2566353489U, // <6,3,u,6>: Cost 3 vext1 <2,6,3,u>, <6,3,u,0> + 2980504720U, // <6,3,u,7>: Cost 3 vzipr RHS, <1,5,3,7> + 1492612910U, // <6,3,u,u>: Cost 2 vext1 <2,6,3,u>, LHS + 3703406592U, // <6,4,0,0>: Cost 4 vext2 <2,0,6,4>, <0,0,0,0> + 2629664870U, // <6,4,0,1>: Cost 3 vext2 <2,0,6,4>, LHS + 2629664972U, // <6,4,0,2>: Cost 3 vext2 <2,0,6,4>, <0,2,4,6> + 3779087232U, // <6,4,0,3>: Cost 4 vext3 <3,4,5,6>, <4,0,3,1> + 2642936156U, // <6,4,0,4>: Cost 3 vext2 <4,2,6,4>, <0,4,2,6> + 2712570770U, // <6,4,0,5>: Cost 3 vext3 <4,6,4,6>, <4,0,5,1> + 2687208348U, // <6,4,0,6>: Cost 3 vext3 <0,4,2,6>, <4,0,6,2> + 3316723081U, // <6,4,0,7>: Cost 4 vrev <4,6,7,0> + 2629665437U, // <6,4,0,u>: Cost 3 vext2 <2,0,6,4>, LHS + 2242473291U, // <6,4,1,0>: Cost 3 vrev <4,6,0,1> + 3700089652U, // <6,4,1,1>: Cost 4 vext2 <1,4,6,4>, <1,1,1,1> + 3703407510U, // <6,4,1,2>: Cost 4 vext2 <2,0,6,4>, <1,2,3,0> + 2852962406U, // <6,4,1,3>: Cost 3 vuzpr <5,6,7,4>, LHS + 3628166454U, // <6,4,1,4>: Cost 4 vext1 <0,6,4,1>, RHS + 3760876514U, // <6,4,1,5>: Cost 4 vext3 <0,4,1,6>, <4,1,5,0> + 2687208430U, // <6,4,1,6>: Cost 3 vext3 <0,4,2,6>, <4,1,6,3> + 3316731274U, // <6,4,1,7>: Cost 4 vrev <4,6,7,1> + 2243063187U, // <6,4,1,u>: Cost 3 vrev <4,6,u,1> + 2629666284U, // <6,4,2,0>: Cost 3 vext2 <2,0,6,4>, <2,0,6,4> + 3703408188U, // <6,4,2,1>: Cost 4 vext2 <2,0,6,4>, <2,1,6,3> + 3703408232U, // <6,4,2,2>: Cost 4 vext2 <2,0,6,4>, <2,2,2,2> + 3703408294U, // <6,4,2,3>: Cost 4 vext2 <2,0,6,4>, <2,3,0,1> + 2632320816U, // <6,4,2,4>: Cost 3 vext2 <2,4,6,4>, <2,4,6,4> + 2923384118U, // <6,4,2,5>: Cost 3 vzipl <6,2,7,3>, RHS + 2687208508U, // <6,4,2,6>: Cost 3 vext3 <0,4,2,6>, <4,2,6,0> + 3760950341U, // <6,4,2,7>: Cost 4 vext3 <0,4,2,6>, <4,2,7,0> + 2634975348U, // <6,4,2,u>: Cost 3 vext2 <2,u,6,4>, <2,u,6,4> + 3703408790U, // <6,4,3,0>: Cost 4 vext2 <2,0,6,4>, <3,0,1,2> + 3316305238U, // <6,4,3,1>: Cost 4 vrev <4,6,1,3> + 3703408947U, // <6,4,3,2>: Cost 4 vext2 <2,0,6,4>, <3,2,0,6> + 3703409052U, // <6,4,3,3>: Cost 4 vext2 <2,0,6,4>, <3,3,3,3> + 2644929026U, // <6,4,3,4>: Cost 3 vext2 <4,5,6,4>, <3,4,5,6> + 3718670922U, // <6,4,3,5>: Cost 4 vext2 <4,5,6,4>, <3,5,4,6> + 2705345682U, // <6,4,3,6>: Cost 3 vext3 <3,4,5,6>, <4,3,6,5> + 3926705152U, // <6,4,3,7>: Cost 4 vuzpr <5,6,7,4>, <1,3,5,7> + 2668817222U, // <6,4,3,u>: Cost 3 vext2 , <3,u,5,6> + 2590277734U, // <6,4,4,0>: Cost 3 vext1 <6,6,4,4>, LHS + 3716017135U, // <6,4,4,1>: Cost 4 vext2 <4,1,6,4>, <4,1,6,4> + 2642938944U, // <6,4,4,2>: Cost 3 vext2 <4,2,6,4>, <4,2,6,4> + 3717344401U, // <6,4,4,3>: Cost 4 vext2 <4,3,6,4>, <4,3,6,4> + 2712571088U, // <6,4,4,4>: Cost 3 vext3 <4,6,4,6>, <4,4,4,4> + 2629668150U, // <6,4,4,5>: Cost 3 vext2 <2,0,6,4>, RHS + 1637649636U, // <6,4,4,6>: Cost 2 vext3 <4,4,6,6>, <4,4,6,6> + 2646257109U, // <6,4,4,7>: Cost 3 vext2 <4,7,6,4>, <4,7,6,4> + 1637649636U, // <6,4,4,u>: Cost 2 vext3 <4,4,6,6>, <4,4,6,6> + 2566398054U, // <6,4,5,0>: Cost 3 vext1 <2,6,4,5>, LHS + 3760876805U, // <6,4,5,1>: Cost 4 vext3 <0,4,1,6>, <4,5,1,3> + 2566399937U, // <6,4,5,2>: Cost 3 vext1 <2,6,4,5>, <2,6,4,5> + 2584316418U, // <6,4,5,3>: Cost 3 vext1 <5,6,4,5>, <3,4,5,6> + 2566401334U, // <6,4,5,4>: Cost 3 vext1 <2,6,4,5>, RHS + 2584318028U, // <6,4,5,5>: Cost 3 vext1 <5,6,4,5>, <5,6,4,5> + 1612287286U, // <6,4,5,6>: Cost 2 vext3 <0,2,4,6>, RHS + 2852965686U, // <6,4,5,7>: Cost 3 vuzpr <5,6,7,4>, RHS + 1612287304U, // <6,4,5,u>: Cost 2 vext3 <0,2,4,6>, RHS + 1504608358U, // <6,4,6,0>: Cost 2 vext1 <4,6,4,6>, LHS + 2578350838U, // <6,4,6,1>: Cost 3 vext1 <4,6,4,6>, <1,0,3,2> + 2578351720U, // <6,4,6,2>: Cost 3 vext1 <4,6,4,6>, <2,2,2,2> + 2578352278U, // <6,4,6,3>: Cost 3 vext1 <4,6,4,6>, <3,0,1,2> + 1504611638U, // <6,4,6,4>: Cost 2 vext1 <4,6,4,6>, RHS + 2578353872U, // <6,4,6,5>: Cost 3 vext1 <4,6,4,6>, <5,1,7,3> + 2578354682U, // <6,4,6,6>: Cost 3 vext1 <4,6,4,6>, <6,2,7,3> + 2578355194U, // <6,4,6,7>: Cost 3 vext1 <4,6,4,6>, <7,0,1,2> + 1504614190U, // <6,4,6,u>: Cost 2 vext1 <4,6,4,6>, LHS + 2572386406U, // <6,4,7,0>: Cost 3 vext1 <3,6,4,7>, LHS + 2572387226U, // <6,4,7,1>: Cost 3 vext1 <3,6,4,7>, <1,2,3,4> + 3640157902U, // <6,4,7,2>: Cost 4 vext1 <2,6,4,7>, <2,3,4,5> + 2572389020U, // <6,4,7,3>: Cost 3 vext1 <3,6,4,7>, <3,6,4,7> + 2572389686U, // <6,4,7,4>: Cost 3 vext1 <3,6,4,7>, RHS + 2980497102U, // <6,4,7,5>: Cost 3 vzipr RHS, <2,3,4,5> + 2980495564U, // <6,4,7,6>: Cost 3 vzipr RHS, <0,2,4,6> + 4054239090U, // <6,4,7,7>: Cost 4 vzipr RHS, <2,5,4,7> + 2572392238U, // <6,4,7,u>: Cost 3 vext1 <3,6,4,7>, LHS + 1504608358U, // <6,4,u,0>: Cost 2 vext1 <4,6,4,6>, LHS + 2629670702U, // <6,4,u,1>: Cost 3 vext2 <2,0,6,4>, LHS + 2566424516U, // <6,4,u,2>: Cost 3 vext1 <2,6,4,u>, <2,6,4,u> + 2584340994U, // <6,4,u,3>: Cost 3 vext1 <5,6,4,u>, <3,4,5,6> + 1640156694U, // <6,4,u,4>: Cost 2 vext3 <4,u,4,6>, <4,u,4,6> + 2629671066U, // <6,4,u,5>: Cost 3 vext2 <2,0,6,4>, RHS + 1612287529U, // <6,4,u,6>: Cost 2 vext3 <0,2,4,6>, RHS + 2852965929U, // <6,4,u,7>: Cost 3 vuzpr <5,6,7,4>, RHS + 1612287547U, // <6,4,u,u>: Cost 2 vext3 <0,2,4,6>, RHS + 3708723200U, // <6,5,0,0>: Cost 4 vext2 <2,u,6,5>, <0,0,0,0> + 2634981478U, // <6,5,0,1>: Cost 3 vext2 <2,u,6,5>, LHS + 3694125260U, // <6,5,0,2>: Cost 4 vext2 <0,4,6,5>, <0,2,4,6> + 3779087962U, // <6,5,0,3>: Cost 4 vext3 <3,4,5,6>, <5,0,3,2> + 3760877154U, // <6,5,0,4>: Cost 4 vext3 <0,4,1,6>, <5,0,4,1> + 4195110916U, // <6,5,0,5>: Cost 4 vtrnr <5,6,7,0>, <5,5,5,5> + 3696779775U, // <6,5,0,6>: Cost 4 vext2 <0,u,6,5>, <0,6,2,7> + 1175212130U, // <6,5,0,7>: Cost 2 vrev <5,6,7,0> + 1175285867U, // <6,5,0,u>: Cost 2 vrev <5,6,u,0> + 2248445988U, // <6,5,1,0>: Cost 3 vrev <5,6,0,1> + 3698107237U, // <6,5,1,1>: Cost 4 vext2 <1,1,6,5>, <1,1,6,5> + 3708724118U, // <6,5,1,2>: Cost 4 vext2 <2,u,6,5>, <1,2,3,0> + 3908575334U, // <6,5,1,3>: Cost 4 vuzpr <2,6,4,5>, LHS + 3716023376U, // <6,5,1,4>: Cost 4 vext2 <4,1,6,5>, <1,4,5,6> + 3708724368U, // <6,5,1,5>: Cost 4 vext2 <2,u,6,5>, <1,5,3,7> + 3767733960U, // <6,5,1,6>: Cost 4 vext3 <1,5,4,6>, <5,1,6,4> + 2712571600U, // <6,5,1,7>: Cost 3 vext3 <4,6,4,6>, <5,1,7,3> + 2712571609U, // <6,5,1,u>: Cost 3 vext3 <4,6,4,6>, <5,1,u,3> + 2578391142U, // <6,5,2,0>: Cost 3 vext1 <4,6,5,2>, LHS + 3704079934U, // <6,5,2,1>: Cost 4 vext2 <2,1,6,5>, <2,1,6,5> + 3708724840U, // <6,5,2,2>: Cost 4 vext2 <2,u,6,5>, <2,2,2,2> + 3705407182U, // <6,5,2,3>: Cost 4 vext2 <2,3,6,5>, <2,3,4,5> + 2578394422U, // <6,5,2,4>: Cost 3 vext1 <4,6,5,2>, RHS + 3717351272U, // <6,5,2,5>: Cost 4 vext2 <4,3,6,5>, <2,5,3,6> + 2634983354U, // <6,5,2,6>: Cost 3 vext2 <2,u,6,5>, <2,6,3,7> + 3115486518U, // <6,5,2,7>: Cost 3 vtrnr <4,6,u,2>, RHS + 2634983541U, // <6,5,2,u>: Cost 3 vext2 <2,u,6,5>, <2,u,6,5> + 3708725398U, // <6,5,3,0>: Cost 4 vext2 <2,u,6,5>, <3,0,1,2> + 3710052631U, // <6,5,3,1>: Cost 4 vext2 <3,1,6,5>, <3,1,6,5> + 3708725606U, // <6,5,3,2>: Cost 4 vext2 <2,u,6,5>, <3,2,6,3> + 3708725660U, // <6,5,3,3>: Cost 4 vext2 <2,u,6,5>, <3,3,3,3> + 2643610114U, // <6,5,3,4>: Cost 3 vext2 <4,3,6,5>, <3,4,5,6> + 3717352010U, // <6,5,3,5>: Cost 4 vext2 <4,3,6,5>, <3,5,4,6> + 3773632358U, // <6,5,3,6>: Cost 4 vext3 <2,5,3,6>, <5,3,6,0> + 2248978533U, // <6,5,3,7>: Cost 3 vrev <5,6,7,3> + 2249052270U, // <6,5,3,u>: Cost 3 vrev <5,6,u,3> + 2596323430U, // <6,5,4,0>: Cost 3 vext1 <7,6,5,4>, LHS + 3716025328U, // <6,5,4,1>: Cost 4 vext2 <4,1,6,5>, <4,1,6,5> + 3716688961U, // <6,5,4,2>: Cost 4 vext2 <4,2,6,5>, <4,2,6,5> + 2643610770U, // <6,5,4,3>: Cost 3 vext2 <4,3,6,5>, <4,3,6,5> + 2596326710U, // <6,5,4,4>: Cost 3 vext1 <7,6,5,4>, RHS + 2634984758U, // <6,5,4,5>: Cost 3 vext2 <2,u,6,5>, RHS + 3767734199U, // <6,5,4,6>: Cost 4 vext3 <1,5,4,6>, <5,4,6,0> + 1643696070U, // <6,5,4,7>: Cost 2 vext3 <5,4,7,6>, <5,4,7,6> + 1643769807U, // <6,5,4,u>: Cost 2 vext3 <5,4,u,6>, <5,4,u,6> + 2578415718U, // <6,5,5,0>: Cost 3 vext1 <4,6,5,5>, LHS + 3652158198U, // <6,5,5,1>: Cost 4 vext1 <4,6,5,5>, <1,0,3,2> + 3652159080U, // <6,5,5,2>: Cost 4 vext1 <4,6,5,5>, <2,2,2,2> + 3652159638U, // <6,5,5,3>: Cost 4 vext1 <4,6,5,5>, <3,0,1,2> + 2578418998U, // <6,5,5,4>: Cost 3 vext1 <4,6,5,5>, RHS + 2712571908U, // <6,5,5,5>: Cost 3 vext3 <4,6,4,6>, <5,5,5,5> + 2718027790U, // <6,5,5,6>: Cost 3 vext3 <5,5,6,6>, <5,5,6,6> + 2712571928U, // <6,5,5,7>: Cost 3 vext3 <4,6,4,6>, <5,5,7,7> + 2712571937U, // <6,5,5,u>: Cost 3 vext3 <4,6,4,6>, <5,5,u,7> + 2705346596U, // <6,5,6,0>: Cost 3 vext3 <3,4,5,6>, <5,6,0,1> + 3767144496U, // <6,5,6,1>: Cost 4 vext3 <1,4,5,6>, <5,6,1,4> + 3773116473U, // <6,5,6,2>: Cost 4 vext3 <2,4,5,6>, <5,6,2,4> + 2705346626U, // <6,5,6,3>: Cost 3 vext3 <3,4,5,6>, <5,6,3,4> + 2705346636U, // <6,5,6,4>: Cost 3 vext3 <3,4,5,6>, <5,6,4,5> + 3908577217U, // <6,5,6,5>: Cost 4 vuzpr <2,6,4,5>, <2,6,4,5> + 2578428728U, // <6,5,6,6>: Cost 3 vext1 <4,6,5,6>, <6,6,6,6> + 2712572002U, // <6,5,6,7>: Cost 3 vext3 <4,6,4,6>, <5,6,7,0> + 2705346668U, // <6,5,6,u>: Cost 3 vext3 <3,4,5,6>, <5,6,u,1> + 2560516198U, // <6,5,7,0>: Cost 3 vext1 <1,6,5,7>, LHS + 2560517363U, // <6,5,7,1>: Cost 3 vext1 <1,6,5,7>, <1,6,5,7> + 2566490060U, // <6,5,7,2>: Cost 3 vext1 <2,6,5,7>, <2,6,5,7> + 3634260118U, // <6,5,7,3>: Cost 4 vext1 <1,6,5,7>, <3,0,1,2> + 2560519478U, // <6,5,7,4>: Cost 3 vext1 <1,6,5,7>, RHS + 2980498650U, // <6,5,7,5>: Cost 3 vzipr RHS, <4,4,5,5> + 2980497922U, // <6,5,7,6>: Cost 3 vzipr RHS, <3,4,5,6> + 3103214902U, // <6,5,7,7>: Cost 3 vtrnr <2,6,3,7>, RHS + 2560522030U, // <6,5,7,u>: Cost 3 vext1 <1,6,5,7>, LHS + 2560524390U, // <6,5,u,0>: Cost 3 vext1 <1,6,5,u>, LHS + 2560525556U, // <6,5,u,1>: Cost 3 vext1 <1,6,5,u>, <1,6,5,u> + 2566498253U, // <6,5,u,2>: Cost 3 vext1 <2,6,5,u>, <2,6,5,u> + 2646931439U, // <6,5,u,3>: Cost 3 vext2 <4,u,6,5>, + 2560527670U, // <6,5,u,4>: Cost 3 vext1 <1,6,5,u>, RHS + 2634987674U, // <6,5,u,5>: Cost 3 vext2 <2,u,6,5>, RHS + 2980506114U, // <6,5,u,6>: Cost 3 vzipr RHS, <3,4,5,6> + 1175277674U, // <6,5,u,7>: Cost 2 vrev <5,6,7,u> + 1175351411U, // <6,5,u,u>: Cost 2 vrev <5,6,u,u> + 2578448486U, // <6,6,0,0>: Cost 3 vext1 <4,6,6,0>, LHS + 1573191782U, // <6,6,0,1>: Cost 2 vext2 <4,u,6,6>, LHS + 2686030124U, // <6,6,0,2>: Cost 3 vext3 <0,2,4,6>, <6,0,2,4> + 3779088690U, // <6,6,0,3>: Cost 4 vext3 <3,4,5,6>, <6,0,3,1> + 2687209788U, // <6,6,0,4>: Cost 3 vext3 <0,4,2,6>, <6,0,4,2> + 3652194000U, // <6,6,0,5>: Cost 4 vext1 <4,6,6,0>, <5,1,7,3> + 2254852914U, // <6,6,0,6>: Cost 3 vrev <6,6,6,0> + 4041575734U, // <6,6,0,7>: Cost 4 vzipr <2,4,6,0>, RHS + 1573192349U, // <6,6,0,u>: Cost 2 vext2 <4,u,6,6>, LHS + 2646934262U, // <6,6,1,0>: Cost 3 vext2 <4,u,6,6>, <1,0,3,2> + 2646934324U, // <6,6,1,1>: Cost 3 vext2 <4,u,6,6>, <1,1,1,1> + 2646934422U, // <6,6,1,2>: Cost 3 vext2 <4,u,6,6>, <1,2,3,0> + 2846785638U, // <6,6,1,3>: Cost 3 vuzpr <4,6,4,6>, LHS + 3760951694U, // <6,6,1,4>: Cost 4 vext3 <0,4,2,6>, <6,1,4,3> + 2646934672U, // <6,6,1,5>: Cost 3 vext2 <4,u,6,6>, <1,5,3,7> + 2712572320U, // <6,6,1,6>: Cost 3 vext3 <4,6,4,6>, <6,1,6,3> + 3775549865U, // <6,6,1,7>: Cost 4 vext3 <2,u,2,6>, <6,1,7,3> + 2846785643U, // <6,6,1,u>: Cost 3 vuzpr <4,6,4,6>, LHS + 3759772094U, // <6,6,2,0>: Cost 4 vext3 <0,2,4,6>, <6,2,0,6> + 3704751676U, // <6,6,2,1>: Cost 4 vext2 <2,2,6,6>, <2,1,6,3> + 2631009936U, // <6,6,2,2>: Cost 3 vext2 <2,2,6,6>, <2,2,6,6> + 2646935206U, // <6,6,2,3>: Cost 3 vext2 <4,u,6,6>, <2,3,0,1> + 3759772127U, // <6,6,2,4>: Cost 4 vext3 <0,2,4,6>, <6,2,4,3> + 3704752004U, // <6,6,2,5>: Cost 4 vext2 <2,2,6,6>, <2,5,6,7> + 2646935482U, // <6,6,2,6>: Cost 3 vext2 <4,u,6,6>, <2,6,3,7> + 2712572410U, // <6,6,2,7>: Cost 3 vext3 <4,6,4,6>, <6,2,7,3> + 2712572419U, // <6,6,2,u>: Cost 3 vext3 <4,6,4,6>, <6,2,u,3> + 2646935702U, // <6,6,3,0>: Cost 3 vext2 <4,u,6,6>, <3,0,1,2> + 3777024534U, // <6,6,3,1>: Cost 4 vext3 <3,1,4,6>, <6,3,1,4> + 3704752453U, // <6,6,3,2>: Cost 4 vext2 <2,2,6,6>, <3,2,2,6> + 2646935964U, // <6,6,3,3>: Cost 3 vext2 <4,u,6,6>, <3,3,3,3> + 2705347122U, // <6,6,3,4>: Cost 3 vext3 <3,4,5,6>, <6,3,4,5> + 3779678778U, // <6,6,3,5>: Cost 4 vext3 <3,5,4,6>, <6,3,5,4> + 2657553069U, // <6,6,3,6>: Cost 3 vext2 <6,6,6,6>, <3,6,6,6> + 4039609654U, // <6,6,3,7>: Cost 4 vzipr <2,1,6,3>, RHS + 2708001366U, // <6,6,3,u>: Cost 3 vext3 <3,u,5,6>, <6,3,u,5> + 2578481254U, // <6,6,4,0>: Cost 3 vext1 <4,6,6,4>, LHS + 3652223734U, // <6,6,4,1>: Cost 4 vext1 <4,6,6,4>, <1,0,3,2> + 3760951922U, // <6,6,4,2>: Cost 4 vext3 <0,4,2,6>, <6,4,2,6> + 3779089019U, // <6,6,4,3>: Cost 4 vext3 <3,4,5,6>, <6,4,3,6> + 1570540772U, // <6,6,4,4>: Cost 2 vext2 <4,4,6,6>, <4,4,6,6> + 1573195062U, // <6,6,4,5>: Cost 2 vext2 <4,u,6,6>, RHS + 2712572560U, // <6,6,4,6>: Cost 3 vext3 <4,6,4,6>, <6,4,6,0> + 2723410591U, // <6,6,4,7>: Cost 3 vext3 <6,4,7,6>, <6,4,7,6> + 1573195304U, // <6,6,4,u>: Cost 2 vext2 <4,u,6,6>, <4,u,6,6> + 3640287334U, // <6,6,5,0>: Cost 4 vext1 <2,6,6,5>, LHS + 2646937296U, // <6,6,5,1>: Cost 3 vext2 <4,u,6,6>, <5,1,7,3> + 3640289235U, // <6,6,5,2>: Cost 4 vext1 <2,6,6,5>, <2,6,6,5> + 3720679279U, // <6,6,5,3>: Cost 4 vext2 <4,u,6,6>, <5,3,7,0> + 2646937542U, // <6,6,5,4>: Cost 3 vext2 <4,u,6,6>, <5,4,7,6> + 2646937604U, // <6,6,5,5>: Cost 3 vext2 <4,u,6,6>, <5,5,5,5> + 2646937698U, // <6,6,5,6>: Cost 3 vext2 <4,u,6,6>, <5,6,7,0> + 2846788918U, // <6,6,5,7>: Cost 3 vuzpr <4,6,4,6>, RHS + 2846788919U, // <6,6,5,u>: Cost 3 vuzpr <4,6,4,6>, RHS + 1516699750U, // <6,6,6,0>: Cost 2 vext1 <6,6,6,6>, LHS + 2590442230U, // <6,6,6,1>: Cost 3 vext1 <6,6,6,6>, <1,0,3,2> + 2646938106U, // <6,6,6,2>: Cost 3 vext2 <4,u,6,6>, <6,2,7,3> + 2590443670U, // <6,6,6,3>: Cost 3 vext1 <6,6,6,6>, <3,0,1,2> + 1516703030U, // <6,6,6,4>: Cost 2 vext1 <6,6,6,6>, RHS + 2590445264U, // <6,6,6,5>: Cost 3 vext1 <6,6,6,6>, <5,1,7,3> + 296144182U, // <6,6,6,6>: Cost 1 vdup2 RHS + 2712572738U, // <6,6,6,7>: Cost 3 vext3 <4,6,4,6>, <6,6,7,7> + 296144182U, // <6,6,6,u>: Cost 1 vdup2 RHS + 2566561894U, // <6,6,7,0>: Cost 3 vext1 <2,6,6,7>, LHS + 3634332924U, // <6,6,7,1>: Cost 4 vext1 <1,6,6,7>, <1,6,6,7> + 2566563797U, // <6,6,7,2>: Cost 3 vext1 <2,6,6,7>, <2,6,6,7> + 2584480258U, // <6,6,7,3>: Cost 3 vext1 <5,6,6,7>, <3,4,5,6> + 2566565174U, // <6,6,7,4>: Cost 3 vext1 <2,6,6,7>, RHS + 2717438846U, // <6,6,7,5>: Cost 3 vext3 <5,4,7,6>, <6,7,5,4> + 2980500280U, // <6,6,7,6>: Cost 3 vzipr RHS, <6,6,6,6> + 1906756918U, // <6,6,7,7>: Cost 2 vzipr RHS, RHS + 1906756919U, // <6,6,7,u>: Cost 2 vzipr RHS, RHS + 1516699750U, // <6,6,u,0>: Cost 2 vext1 <6,6,6,6>, LHS + 1573197614U, // <6,6,u,1>: Cost 2 vext2 <4,u,6,6>, LHS + 2566571990U, // <6,6,u,2>: Cost 3 vext1 <2,6,6,u>, <2,6,6,u> + 2846786205U, // <6,6,u,3>: Cost 3 vuzpr <4,6,4,6>, LHS + 1516703030U, // <6,6,u,4>: Cost 2 vext1 <6,6,6,6>, RHS + 1573197978U, // <6,6,u,5>: Cost 2 vext2 <4,u,6,6>, RHS + 296144182U, // <6,6,u,6>: Cost 1 vdup2 RHS + 1906765110U, // <6,6,u,7>: Cost 2 vzipr RHS, RHS + 296144182U, // <6,6,u,u>: Cost 1 vdup2 RHS + 1571209216U, // <6,7,0,0>: Cost 2 vext2 RHS, <0,0,0,0> + 497467494U, // <6,7,0,1>: Cost 1 vext2 RHS, LHS + 1571209380U, // <6,7,0,2>: Cost 2 vext2 RHS, <0,2,0,2> + 2644951292U, // <6,7,0,3>: Cost 3 vext2 RHS, <0,3,1,0> + 1571209554U, // <6,7,0,4>: Cost 2 vext2 RHS, <0,4,1,5> + 1510756450U, // <6,7,0,5>: Cost 2 vext1 <5,6,7,0>, <5,6,7,0> + 2644951542U, // <6,7,0,6>: Cost 3 vext2 RHS, <0,6,1,7> + 2584499194U, // <6,7,0,7>: Cost 3 vext1 <5,6,7,0>, <7,0,1,2> + 497468061U, // <6,7,0,u>: Cost 1 vext2 RHS, LHS + 1571209974U, // <6,7,1,0>: Cost 2 vext2 RHS, <1,0,3,2> + 1571210036U, // <6,7,1,1>: Cost 2 vext2 RHS, <1,1,1,1> + 1571210134U, // <6,7,1,2>: Cost 2 vext2 RHS, <1,2,3,0> + 1571210200U, // <6,7,1,3>: Cost 2 vext2 RHS, <1,3,1,3> + 2644952098U, // <6,7,1,4>: Cost 3 vext2 RHS, <1,4,0,5> + 1571210384U, // <6,7,1,5>: Cost 2 vext2 RHS, <1,5,3,7> + 2644952271U, // <6,7,1,6>: Cost 3 vext2 RHS, <1,6,1,7> + 2578535418U, // <6,7,1,7>: Cost 3 vext1 <4,6,7,1>, <7,0,1,2> + 1571210605U, // <6,7,1,u>: Cost 2 vext2 RHS, <1,u,1,3> + 2644952509U, // <6,7,2,0>: Cost 3 vext2 RHS, <2,0,1,2> + 2644952582U, // <6,7,2,1>: Cost 3 vext2 RHS, <2,1,0,3> + 1571210856U, // <6,7,2,2>: Cost 2 vext2 RHS, <2,2,2,2> + 1571210918U, // <6,7,2,3>: Cost 2 vext2 RHS, <2,3,0,1> + 2644952828U, // <6,7,2,4>: Cost 3 vext2 RHS, <2,4,0,6> + 2633009028U, // <6,7,2,5>: Cost 3 vext2 <2,5,6,7>, <2,5,6,7> + 1571211194U, // <6,7,2,6>: Cost 2 vext2 RHS, <2,6,3,7> + 2668840938U, // <6,7,2,7>: Cost 3 vext2 RHS, <2,7,0,1> + 1571211323U, // <6,7,2,u>: Cost 2 vext2 RHS, <2,u,0,1> + 1571211414U, // <6,7,3,0>: Cost 2 vext2 RHS, <3,0,1,2> + 2644953311U, // <6,7,3,1>: Cost 3 vext2 RHS, <3,1,0,3> + 2644953390U, // <6,7,3,2>: Cost 3 vext2 RHS, <3,2,0,1> + 1571211676U, // <6,7,3,3>: Cost 2 vext2 RHS, <3,3,3,3> + 1571211778U, // <6,7,3,4>: Cost 2 vext2 RHS, <3,4,5,6> + 2644953648U, // <6,7,3,5>: Cost 3 vext2 RHS, <3,5,1,7> + 2644953720U, // <6,7,3,6>: Cost 3 vext2 RHS, <3,6,0,7> + 2644953795U, // <6,7,3,7>: Cost 3 vext2 RHS, <3,7,0,1> + 1571212062U, // <6,7,3,u>: Cost 2 vext2 RHS, <3,u,1,2> + 1573202834U, // <6,7,4,0>: Cost 2 vext2 RHS, <4,0,5,1> + 2644954058U, // <6,7,4,1>: Cost 3 vext2 RHS, <4,1,2,3> + 2644954166U, // <6,7,4,2>: Cost 3 vext2 RHS, <4,2,5,3> + 2644954258U, // <6,7,4,3>: Cost 3 vext2 RHS, <4,3,6,5> + 1571212496U, // <6,7,4,4>: Cost 2 vext2 RHS, <4,4,4,4> + 497470774U, // <6,7,4,5>: Cost 1 vext2 RHS, RHS + 1573203316U, // <6,7,4,6>: Cost 2 vext2 RHS, <4,6,4,6> + 2646281688U, // <6,7,4,7>: Cost 3 vext2 <4,7,6,7>, <4,7,6,7> + 497471017U, // <6,7,4,u>: Cost 1 vext2 RHS, RHS + 2644954696U, // <6,7,5,0>: Cost 3 vext2 RHS, <5,0,1,2> + 1573203664U, // <6,7,5,1>: Cost 2 vext2 RHS, <5,1,7,3> + 2644954878U, // <6,7,5,2>: Cost 3 vext2 RHS, <5,2,3,4> + 2644954991U, // <6,7,5,3>: Cost 3 vext2 RHS, <5,3,7,0> + 1571213254U, // <6,7,5,4>: Cost 2 vext2 RHS, <5,4,7,6> + 1571213316U, // <6,7,5,5>: Cost 2 vext2 RHS, <5,5,5,5> + 1571213410U, // <6,7,5,6>: Cost 2 vext2 RHS, <5,6,7,0> + 1573204136U, // <6,7,5,7>: Cost 2 vext2 RHS, <5,7,5,7> + 1573204217U, // <6,7,5,u>: Cost 2 vext2 RHS, <5,u,5,7> + 2644955425U, // <6,7,6,0>: Cost 3 vext2 RHS, <6,0,1,2> + 2644955561U, // <6,7,6,1>: Cost 3 vext2 RHS, <6,1,7,3> + 1573204474U, // <6,7,6,2>: Cost 2 vext2 RHS, <6,2,7,3> + 2644955698U, // <6,7,6,3>: Cost 3 vext2 RHS, <6,3,4,5> + 2644955789U, // <6,7,6,4>: Cost 3 vext2 RHS, <6,4,5,6> + 2644955889U, // <6,7,6,5>: Cost 3 vext2 RHS, <6,5,7,7> + 1571214136U, // <6,7,6,6>: Cost 2 vext2 RHS, <6,6,6,6> + 1571214158U, // <6,7,6,7>: Cost 2 vext2 RHS, <6,7,0,1> + 1573204895U, // <6,7,6,u>: Cost 2 vext2 RHS, <6,u,0,1> + 1573204986U, // <6,7,7,0>: Cost 2 vext2 RHS, <7,0,1,2> + 2572608656U, // <6,7,7,1>: Cost 3 vext1 <3,6,7,7>, <1,5,3,7> + 2644956362U, // <6,7,7,2>: Cost 3 vext2 RHS, <7,2,6,3> + 2572610231U, // <6,7,7,3>: Cost 3 vext1 <3,6,7,7>, <3,6,7,7> + 1573205350U, // <6,7,7,4>: Cost 2 vext2 RHS, <7,4,5,6> + 2646947220U, // <6,7,7,5>: Cost 3 vext2 RHS, <7,5,1,7> + 1516786498U, // <6,7,7,6>: Cost 2 vext1 <6,6,7,7>, <6,6,7,7> + 1571214956U, // <6,7,7,7>: Cost 2 vext2 RHS, <7,7,7,7> + 1573205634U, // <6,7,7,u>: Cost 2 vext2 RHS, <7,u,1,2> + 1571215059U, // <6,7,u,0>: Cost 2 vext2 RHS, + 497473326U, // <6,7,u,1>: Cost 1 vext2 RHS, LHS + 1571215237U, // <6,7,u,2>: Cost 2 vext2 RHS, + 1571215292U, // <6,7,u,3>: Cost 2 vext2 RHS, + 1571215423U, // <6,7,u,4>: Cost 2 vext2 RHS, + 497473690U, // <6,7,u,5>: Cost 1 vext2 RHS, RHS + 1571215568U, // <6,7,u,6>: Cost 2 vext2 RHS, + 1573206272U, // <6,7,u,7>: Cost 2 vext2 RHS, + 497473893U, // <6,7,u,u>: Cost 1 vext2 RHS, LHS + 1571217408U, // <6,u,0,0>: Cost 2 vext2 RHS, <0,0,0,0> + 497475686U, // <6,u,0,1>: Cost 1 vext2 RHS, LHS + 1571217572U, // <6,u,0,2>: Cost 2 vext2 RHS, <0,2,0,2> + 2689865445U, // <6,u,0,3>: Cost 3 vext3 <0,u,2,6>, + 1571217746U, // <6,u,0,4>: Cost 2 vext2 RHS, <0,4,1,5> + 1510830187U, // <6,u,0,5>: Cost 2 vext1 <5,6,u,0>, <5,6,u,0> + 2644959734U, // <6,u,0,6>: Cost 3 vext2 RHS, <0,6,1,7> + 1193130221U, // <6,u,0,7>: Cost 2 vrev + 497476253U, // <6,u,0,u>: Cost 1 vext2 RHS, LHS + 1571218166U, // <6,u,1,0>: Cost 2 vext2 RHS, <1,0,3,2> + 1571218228U, // <6,u,1,1>: Cost 2 vext2 RHS, <1,1,1,1> + 1612289838U, // <6,u,1,2>: Cost 2 vext3 <0,2,4,6>, LHS + 1571218392U, // <6,u,1,3>: Cost 2 vext2 RHS, <1,3,1,3> + 2566663478U, // <6,u,1,4>: Cost 3 vext1 <2,6,u,1>, RHS + 1571218576U, // <6,u,1,5>: Cost 2 vext2 RHS, <1,5,3,7> + 2644960463U, // <6,u,1,6>: Cost 3 vext2 RHS, <1,6,1,7> + 2717439835U, // <6,u,1,7>: Cost 3 vext3 <5,4,7,6>, + 1612289892U, // <6,u,1,u>: Cost 2 vext3 <0,2,4,6>, LHS + 1504870502U, // <6,u,2,0>: Cost 2 vext1 <4,6,u,2>, LHS + 2644960774U, // <6,u,2,1>: Cost 3 vext2 RHS, <2,1,0,3> + 1571219048U, // <6,u,2,2>: Cost 2 vext2 RHS, <2,2,2,2> + 1571219110U, // <6,u,2,3>: Cost 2 vext2 RHS, <2,3,0,1> + 1504873782U, // <6,u,2,4>: Cost 2 vext1 <4,6,u,2>, RHS + 2633017221U, // <6,u,2,5>: Cost 3 vext2 <2,5,6,u>, <2,5,6,u> + 1571219386U, // <6,u,2,6>: Cost 2 vext2 RHS, <2,6,3,7> + 2712573868U, // <6,u,2,7>: Cost 3 vext3 <4,6,4,6>, + 1571219515U, // <6,u,2,u>: Cost 2 vext2 RHS, <2,u,0,1> + 1571219606U, // <6,u,3,0>: Cost 2 vext2 RHS, <3,0,1,2> + 2644961503U, // <6,u,3,1>: Cost 3 vext2 RHS, <3,1,0,3> + 2566678499U, // <6,u,3,2>: Cost 3 vext1 <2,6,u,3>, <2,6,u,3> + 1571219868U, // <6,u,3,3>: Cost 2 vext2 RHS, <3,3,3,3> + 1571219970U, // <6,u,3,4>: Cost 2 vext2 RHS, <3,4,5,6> + 2689865711U, // <6,u,3,5>: Cost 3 vext3 <0,u,2,6>, + 2708002806U, // <6,u,3,6>: Cost 3 vext3 <3,u,5,6>, + 2644961987U, // <6,u,3,7>: Cost 3 vext2 RHS, <3,7,0,1> + 1571220254U, // <6,u,3,u>: Cost 2 vext2 RHS, <3,u,1,2> + 1571220370U, // <6,u,4,0>: Cost 2 vext2 RHS, <4,0,5,1> + 2644962250U, // <6,u,4,1>: Cost 3 vext2 RHS, <4,1,2,3> + 1661245476U, // <6,u,4,2>: Cost 2 vext3 , + 2686031917U, // <6,u,4,3>: Cost 3 vext3 <0,2,4,6>, + 1571220688U, // <6,u,4,4>: Cost 2 vext2 RHS, <4,4,4,4> + 497478967U, // <6,u,4,5>: Cost 1 vext2 RHS, RHS + 1571220852U, // <6,u,4,6>: Cost 2 vext2 RHS, <4,6,4,6> + 1661614161U, // <6,u,4,7>: Cost 2 vext3 , + 497479209U, // <6,u,4,u>: Cost 1 vext2 RHS, RHS + 2566692966U, // <6,u,5,0>: Cost 3 vext1 <2,6,u,5>, LHS + 1571221200U, // <6,u,5,1>: Cost 2 vext2 RHS, <5,1,7,3> + 2566694885U, // <6,u,5,2>: Cost 3 vext1 <2,6,u,5>, <2,6,u,5> + 2689865855U, // <6,u,5,3>: Cost 3 vext3 <0,u,2,6>, + 1571221446U, // <6,u,5,4>: Cost 2 vext2 RHS, <5,4,7,6> + 1571221508U, // <6,u,5,5>: Cost 2 vext2 RHS, <5,5,5,5> + 1612290202U, // <6,u,5,6>: Cost 2 vext3 <0,2,4,6>, RHS + 1571221672U, // <6,u,5,7>: Cost 2 vext2 RHS, <5,7,5,7> + 1612290220U, // <6,u,5,u>: Cost 2 vext3 <0,2,4,6>, RHS + 1504903270U, // <6,u,6,0>: Cost 2 vext1 <4,6,u,6>, LHS + 2644963752U, // <6,u,6,1>: Cost 3 vext2 RHS, <6,1,7,2> + 1571222010U, // <6,u,6,2>: Cost 2 vext2 RHS, <6,2,7,3> + 2686032080U, // <6,u,6,3>: Cost 3 vext3 <0,2,4,6>, + 1504906550U, // <6,u,6,4>: Cost 2 vext1 <4,6,u,6>, RHS + 2644964079U, // <6,u,6,5>: Cost 3 vext2 RHS, <6,5,7,5> + 296144182U, // <6,u,6,6>: Cost 1 vdup2 RHS + 1571222350U, // <6,u,6,7>: Cost 2 vext2 RHS, <6,7,0,1> + 296144182U, // <6,u,6,u>: Cost 1 vdup2 RHS + 1492967526U, // <6,u,7,0>: Cost 2 vext1 <2,6,u,7>, LHS + 2560738574U, // <6,u,7,1>: Cost 3 vext1 <1,6,u,7>, <1,6,u,7> + 1492969447U, // <6,u,7,2>: Cost 2 vext1 <2,6,u,7>, <2,6,u,7> + 1906753692U, // <6,u,7,3>: Cost 2 vzipr RHS, LHS + 1492970806U, // <6,u,7,4>: Cost 2 vext1 <2,6,u,7>, RHS + 2980495761U, // <6,u,7,5>: Cost 3 vzipr RHS, <0,4,u,5> + 1516860235U, // <6,u,7,6>: Cost 2 vext1 <6,6,u,7>, <6,6,u,7> + 1906756936U, // <6,u,7,7>: Cost 2 vzipr RHS, RHS + 1492973358U, // <6,u,7,u>: Cost 2 vext1 <2,6,u,7>, LHS + 1492975718U, // <6,u,u,0>: Cost 2 vext1 <2,6,u,u>, LHS + 497481518U, // <6,u,u,1>: Cost 1 vext2 RHS, LHS + 1612290405U, // <6,u,u,2>: Cost 2 vext3 <0,2,4,6>, LHS + 1571223484U, // <6,u,u,3>: Cost 2 vext2 RHS, + 1492978998U, // <6,u,u,4>: Cost 2 vext1 <2,6,u,u>, RHS + 497481882U, // <6,u,u,5>: Cost 1 vext2 RHS, RHS + 296144182U, // <6,u,u,6>: Cost 1 vdup2 RHS + 1906765128U, // <6,u,u,7>: Cost 2 vzipr RHS, RHS + 497482085U, // <6,u,u,u>: Cost 1 vext2 RHS, LHS + 1638318080U, // <7,0,0,0>: Cost 2 vext3 RHS, <0,0,0,0> + 1638318090U, // <7,0,0,1>: Cost 2 vext3 RHS, <0,0,1,1> + 1638318100U, // <7,0,0,2>: Cost 2 vext3 RHS, <0,0,2,2> + 3646442178U, // <7,0,0,3>: Cost 4 vext1 <3,7,0,0>, <3,7,0,0> + 2712059941U, // <7,0,0,4>: Cost 3 vext3 RHS, <0,0,4,1> + 2651603364U, // <7,0,0,5>: Cost 3 vext2 <5,6,7,0>, <0,5,1,6> + 2590618445U, // <7,0,0,6>: Cost 3 vext1 <6,7,0,0>, <6,7,0,0> + 3785801798U, // <7,0,0,7>: Cost 4 vext3 RHS, <0,0,7,7> + 1638318153U, // <7,0,0,u>: Cost 2 vext3 RHS, <0,0,u,1> + 1516879974U, // <7,0,1,0>: Cost 2 vext1 <6,7,0,1>, LHS + 2693922911U, // <7,0,1,1>: Cost 3 vext3 <1,5,3,7>, <0,1,1,5> + 564576358U, // <7,0,1,2>: Cost 1 vext3 RHS, LHS + 2638996480U, // <7,0,1,3>: Cost 3 vext2 <3,5,7,0>, <1,3,5,7> + 1516883254U, // <7,0,1,4>: Cost 2 vext1 <6,7,0,1>, RHS + 2649613456U, // <7,0,1,5>: Cost 3 vext2 <5,3,7,0>, <1,5,3,7> + 1516884814U, // <7,0,1,6>: Cost 2 vext1 <6,7,0,1>, <6,7,0,1> + 2590626808U, // <7,0,1,7>: Cost 3 vext1 <6,7,0,1>, <7,0,1,0> + 564576412U, // <7,0,1,u>: Cost 1 vext3 RHS, LHS + 1638318244U, // <7,0,2,0>: Cost 2 vext3 RHS, <0,2,0,2> + 2692743344U, // <7,0,2,1>: Cost 3 vext3 <1,3,5,7>, <0,2,1,5> + 2712060084U, // <7,0,2,2>: Cost 3 vext3 RHS, <0,2,2,0> + 2712060094U, // <7,0,2,3>: Cost 3 vext3 RHS, <0,2,3,1> + 1638318284U, // <7,0,2,4>: Cost 2 vext3 RHS, <0,2,4,6> + 2712060118U, // <7,0,2,5>: Cost 3 vext3 RHS, <0,2,5,7> + 2651604922U, // <7,0,2,6>: Cost 3 vext2 <5,6,7,0>, <2,6,3,7> + 2686255336U, // <7,0,2,7>: Cost 3 vext3 <0,2,7,7>, <0,2,7,7> + 1638318316U, // <7,0,2,u>: Cost 2 vext3 RHS, <0,2,u,2> + 2651605142U, // <7,0,3,0>: Cost 3 vext2 <5,6,7,0>, <3,0,1,2> + 2712060156U, // <7,0,3,1>: Cost 3 vext3 RHS, <0,3,1,0> + 2712060165U, // <7,0,3,2>: Cost 3 vext3 RHS, <0,3,2,0> + 2651605404U, // <7,0,3,3>: Cost 3 vext2 <5,6,7,0>, <3,3,3,3> + 2651605506U, // <7,0,3,4>: Cost 3 vext2 <5,6,7,0>, <3,4,5,6> + 2638998111U, // <7,0,3,5>: Cost 3 vext2 <3,5,7,0>, <3,5,7,0> + 2639661744U, // <7,0,3,6>: Cost 3 vext2 <3,6,7,0>, <3,6,7,0> + 3712740068U, // <7,0,3,7>: Cost 4 vext2 <3,5,7,0>, <3,7,3,7> + 2640989010U, // <7,0,3,u>: Cost 3 vext2 <3,u,7,0>, <3,u,7,0> + 2712060232U, // <7,0,4,0>: Cost 3 vext3 RHS, <0,4,0,4> + 1638318418U, // <7,0,4,1>: Cost 2 vext3 RHS, <0,4,1,5> + 1638318428U, // <7,0,4,2>: Cost 2 vext3 RHS, <0,4,2,6> + 3646474950U, // <7,0,4,3>: Cost 4 vext1 <3,7,0,4>, <3,7,0,4> + 2712060270U, // <7,0,4,4>: Cost 3 vext3 RHS, <0,4,4,6> + 1577864502U, // <7,0,4,5>: Cost 2 vext2 <5,6,7,0>, RHS + 2651606388U, // <7,0,4,6>: Cost 3 vext2 <5,6,7,0>, <4,6,4,6> + 3787792776U, // <7,0,4,7>: Cost 4 vext3 RHS, <0,4,7,5> + 1638318481U, // <7,0,4,u>: Cost 2 vext3 RHS, <0,4,u,5> + 2590654566U, // <7,0,5,0>: Cost 3 vext1 <6,7,0,5>, LHS + 2651606736U, // <7,0,5,1>: Cost 3 vext2 <5,6,7,0>, <5,1,7,3> + 2712060334U, // <7,0,5,2>: Cost 3 vext3 RHS, <0,5,2,7> + 2649616239U, // <7,0,5,3>: Cost 3 vext2 <5,3,7,0>, <5,3,7,0> + 2651606982U, // <7,0,5,4>: Cost 3 vext2 <5,6,7,0>, <5,4,7,6> + 2651607044U, // <7,0,5,5>: Cost 3 vext2 <5,6,7,0>, <5,5,5,5> + 1577865314U, // <7,0,5,6>: Cost 2 vext2 <5,6,7,0>, <5,6,7,0> + 2651607208U, // <7,0,5,7>: Cost 3 vext2 <5,6,7,0>, <5,7,5,7> + 1579192580U, // <7,0,5,u>: Cost 2 vext2 <5,u,7,0>, <5,u,7,0> + 2688393709U, // <7,0,6,0>: Cost 3 vext3 <0,6,0,7>, <0,6,0,7> + 2712060406U, // <7,0,6,1>: Cost 3 vext3 RHS, <0,6,1,7> + 2688541183U, // <7,0,6,2>: Cost 3 vext3 <0,6,2,7>, <0,6,2,7> + 2655588936U, // <7,0,6,3>: Cost 3 vext2 <6,3,7,0>, <6,3,7,0> + 3762430481U, // <7,0,6,4>: Cost 4 vext3 <0,6,4,7>, <0,6,4,7> + 2651607730U, // <7,0,6,5>: Cost 3 vext2 <5,6,7,0>, <6,5,0,7> + 2651607864U, // <7,0,6,6>: Cost 3 vext2 <5,6,7,0>, <6,6,6,6> + 2651607886U, // <7,0,6,7>: Cost 3 vext2 <5,6,7,0>, <6,7,0,1> + 2688983605U, // <7,0,6,u>: Cost 3 vext3 <0,6,u,7>, <0,6,u,7> + 2651608058U, // <7,0,7,0>: Cost 3 vext2 <5,6,7,0>, <7,0,1,2> + 2932703334U, // <7,0,7,1>: Cost 3 vzipl <7,7,7,7>, LHS + 3066921062U, // <7,0,7,2>: Cost 3 vtrnl <7,7,7,7>, LHS + 3712742678U, // <7,0,7,3>: Cost 4 vext2 <3,5,7,0>, <7,3,5,7> + 2651608422U, // <7,0,7,4>: Cost 3 vext2 <5,6,7,0>, <7,4,5,6> + 2651608513U, // <7,0,7,5>: Cost 3 vext2 <5,6,7,0>, <7,5,6,7> + 2663552532U, // <7,0,7,6>: Cost 3 vext2 <7,6,7,0>, <7,6,7,0> + 2651608684U, // <7,0,7,7>: Cost 3 vext2 <5,6,7,0>, <7,7,7,7> + 2651608706U, // <7,0,7,u>: Cost 3 vext2 <5,6,7,0>, <7,u,1,2> + 1638318730U, // <7,0,u,0>: Cost 2 vext3 RHS, <0,u,0,2> + 1638318738U, // <7,0,u,1>: Cost 2 vext3 RHS, <0,u,1,1> + 564576925U, // <7,0,u,2>: Cost 1 vext3 RHS, LHS + 2572765898U, // <7,0,u,3>: Cost 3 vext1 <3,7,0,u>, <3,7,0,u> + 1638318770U, // <7,0,u,4>: Cost 2 vext3 RHS, <0,u,4,6> + 1577867418U, // <7,0,u,5>: Cost 2 vext2 <5,6,7,0>, RHS + 1516942165U, // <7,0,u,6>: Cost 2 vext1 <6,7,0,u>, <6,7,0,u> + 2651609344U, // <7,0,u,7>: Cost 3 vext2 <5,6,7,0>, + 564576979U, // <7,0,u,u>: Cost 1 vext3 RHS, LHS + 2590687334U, // <7,1,0,0>: Cost 3 vext1 <6,7,1,0>, LHS + 2639003750U, // <7,1,0,1>: Cost 3 vext2 <3,5,7,1>, LHS + 2793357414U, // <7,1,0,2>: Cost 3 vuzpl <7,0,1,2>, LHS + 1638318838U, // <7,1,0,3>: Cost 2 vext3 RHS, <1,0,3,2> + 2590690614U, // <7,1,0,4>: Cost 3 vext1 <6,7,1,0>, RHS + 2712060679U, // <7,1,0,5>: Cost 3 vext3 RHS, <1,0,5,1> + 2590692182U, // <7,1,0,6>: Cost 3 vext1 <6,7,1,0>, <6,7,1,0> + 3785802521U, // <7,1,0,7>: Cost 4 vext3 RHS, <1,0,7,1> + 1638318883U, // <7,1,0,u>: Cost 2 vext3 RHS, <1,0,u,2> + 2712060715U, // <7,1,1,0>: Cost 3 vext3 RHS, <1,1,0,1> + 1638318900U, // <7,1,1,1>: Cost 2 vext3 RHS, <1,1,1,1> + 3774300994U, // <7,1,1,2>: Cost 4 vext3 <2,6,3,7>, <1,1,2,6> + 1638318920U, // <7,1,1,3>: Cost 2 vext3 RHS, <1,1,3,3> + 2712060755U, // <7,1,1,4>: Cost 3 vext3 RHS, <1,1,4,5> + 2691416926U, // <7,1,1,5>: Cost 3 vext3 <1,1,5,7>, <1,1,5,7> + 2590700375U, // <7,1,1,6>: Cost 3 vext1 <6,7,1,1>, <6,7,1,1> + 3765158766U, // <7,1,1,7>: Cost 4 vext3 <1,1,5,7>, <1,1,7,5> + 1638318965U, // <7,1,1,u>: Cost 2 vext3 RHS, <1,1,u,3> + 2712060796U, // <7,1,2,0>: Cost 3 vext3 RHS, <1,2,0,1> + 2712060807U, // <7,1,2,1>: Cost 3 vext3 RHS, <1,2,1,3> + 3712747112U, // <7,1,2,2>: Cost 4 vext2 <3,5,7,1>, <2,2,2,2> + 1638318998U, // <7,1,2,3>: Cost 2 vext3 RHS, <1,2,3,0> + 2712060836U, // <7,1,2,4>: Cost 3 vext3 RHS, <1,2,4,5> + 2712060843U, // <7,1,2,5>: Cost 3 vext3 RHS, <1,2,5,3> + 2590708568U, // <7,1,2,6>: Cost 3 vext1 <6,7,1,2>, <6,7,1,2> + 2735948730U, // <7,1,2,7>: Cost 3 vext3 RHS, <1,2,7,0> + 1638319043U, // <7,1,2,u>: Cost 2 vext3 RHS, <1,2,u,0> + 2712060876U, // <7,1,3,0>: Cost 3 vext3 RHS, <1,3,0,0> + 1638319064U, // <7,1,3,1>: Cost 2 vext3 RHS, <1,3,1,3> + 2712060894U, // <7,1,3,2>: Cost 3 vext3 RHS, <1,3,2,0> + 2692596718U, // <7,1,3,3>: Cost 3 vext3 <1,3,3,7>, <1,3,3,7> + 2712060917U, // <7,1,3,4>: Cost 3 vext3 RHS, <1,3,4,5> + 1619002368U, // <7,1,3,5>: Cost 2 vext3 <1,3,5,7>, <1,3,5,7> + 2692817929U, // <7,1,3,6>: Cost 3 vext3 <1,3,6,7>, <1,3,6,7> + 2735948814U, // <7,1,3,7>: Cost 3 vext3 RHS, <1,3,7,3> + 1619223579U, // <7,1,3,u>: Cost 2 vext3 <1,3,u,7>, <1,3,u,7> + 2712060962U, // <7,1,4,0>: Cost 3 vext3 RHS, <1,4,0,5> + 2712060971U, // <7,1,4,1>: Cost 3 vext3 RHS, <1,4,1,5> + 2712060980U, // <7,1,4,2>: Cost 3 vext3 RHS, <1,4,2,5> + 2712060989U, // <7,1,4,3>: Cost 3 vext3 RHS, <1,4,3,5> + 3785802822U, // <7,1,4,4>: Cost 4 vext3 RHS, <1,4,4,5> + 2639007030U, // <7,1,4,5>: Cost 3 vext2 <3,5,7,1>, RHS + 2645642634U, // <7,1,4,6>: Cost 3 vext2 <4,6,7,1>, <4,6,7,1> + 3719384520U, // <7,1,4,7>: Cost 4 vext2 <4,6,7,1>, <4,7,5,0> + 2639007273U, // <7,1,4,u>: Cost 3 vext2 <3,5,7,1>, RHS + 2572812390U, // <7,1,5,0>: Cost 3 vext1 <3,7,1,5>, LHS + 2693776510U, // <7,1,5,1>: Cost 3 vext3 <1,5,1,7>, <1,5,1,7> + 3774301318U, // <7,1,5,2>: Cost 4 vext3 <2,6,3,7>, <1,5,2,6> + 1620182160U, // <7,1,5,3>: Cost 2 vext3 <1,5,3,7>, <1,5,3,7> + 2572815670U, // <7,1,5,4>: Cost 3 vext1 <3,7,1,5>, RHS + 3766486178U, // <7,1,5,5>: Cost 4 vext3 <1,3,5,7>, <1,5,5,7> + 2651615331U, // <7,1,5,6>: Cost 3 vext2 <5,6,7,1>, <5,6,7,1> + 2652278964U, // <7,1,5,7>: Cost 3 vext2 <5,7,7,1>, <5,7,7,1> + 1620550845U, // <7,1,5,u>: Cost 2 vext3 <1,5,u,7>, <1,5,u,7> + 3768108230U, // <7,1,6,0>: Cost 4 vext3 <1,6,0,7>, <1,6,0,7> + 2694440143U, // <7,1,6,1>: Cost 3 vext3 <1,6,1,7>, <1,6,1,7> + 2712061144U, // <7,1,6,2>: Cost 3 vext3 RHS, <1,6,2,7> + 2694587617U, // <7,1,6,3>: Cost 3 vext3 <1,6,3,7>, <1,6,3,7> + 3768403178U, // <7,1,6,4>: Cost 4 vext3 <1,6,4,7>, <1,6,4,7> + 2694735091U, // <7,1,6,5>: Cost 3 vext3 <1,6,5,7>, <1,6,5,7> + 3768550652U, // <7,1,6,6>: Cost 4 vext3 <1,6,6,7>, <1,6,6,7> + 2652279630U, // <7,1,6,7>: Cost 3 vext2 <5,7,7,1>, <6,7,0,1> + 2694956302U, // <7,1,6,u>: Cost 3 vext3 <1,6,u,7>, <1,6,u,7> + 2645644282U, // <7,1,7,0>: Cost 3 vext2 <4,6,7,1>, <7,0,1,2> + 2859062094U, // <7,1,7,1>: Cost 3 vuzpr <6,7,0,1>, <6,7,0,1> + 3779462437U, // <7,1,7,2>: Cost 4 vext3 <3,5,1,7>, <1,7,2,3> + 3121938534U, // <7,1,7,3>: Cost 3 vtrnr <5,7,5,7>, LHS + 2554916150U, // <7,1,7,4>: Cost 3 vext1 <0,7,1,7>, RHS + 3769140548U, // <7,1,7,5>: Cost 4 vext3 <1,7,5,7>, <1,7,5,7> + 3726022164U, // <7,1,7,6>: Cost 4 vext2 <5,7,7,1>, <7,6,7,0> + 2554918508U, // <7,1,7,7>: Cost 3 vext1 <0,7,1,7>, <7,7,7,7> + 3121938539U, // <7,1,7,u>: Cost 3 vtrnr <5,7,5,7>, LHS + 2572836966U, // <7,1,u,0>: Cost 3 vext1 <3,7,1,u>, LHS + 1638319469U, // <7,1,u,1>: Cost 2 vext3 RHS, <1,u,1,3> + 2712061299U, // <7,1,u,2>: Cost 3 vext3 RHS, <1,u,2,0> + 1622173059U, // <7,1,u,3>: Cost 2 vext3 <1,u,3,7>, <1,u,3,7> + 2572840246U, // <7,1,u,4>: Cost 3 vext1 <3,7,1,u>, RHS + 1622320533U, // <7,1,u,5>: Cost 2 vext3 <1,u,5,7>, <1,u,5,7> + 2696136094U, // <7,1,u,6>: Cost 3 vext3 <1,u,6,7>, <1,u,6,7> + 2859060777U, // <7,1,u,7>: Cost 3 vuzpr <6,7,0,1>, RHS + 1622541744U, // <7,1,u,u>: Cost 2 vext3 <1,u,u,7>, <1,u,u,7> + 2712061364U, // <7,2,0,0>: Cost 3 vext3 RHS, <2,0,0,2> + 2712061373U, // <7,2,0,1>: Cost 3 vext3 RHS, <2,0,1,2> + 2712061380U, // <7,2,0,2>: Cost 3 vext3 RHS, <2,0,2,0> + 2712061389U, // <7,2,0,3>: Cost 3 vext3 RHS, <2,0,3,0> + 2712061404U, // <7,2,0,4>: Cost 3 vext3 RHS, <2,0,4,6> + 2696725990U, // <7,2,0,5>: Cost 3 vext3 <2,0,5,7>, <2,0,5,7> + 2712061417U, // <7,2,0,6>: Cost 3 vext3 RHS, <2,0,6,1> + 3785803251U, // <7,2,0,7>: Cost 4 vext3 RHS, <2,0,7,2> + 2696947201U, // <7,2,0,u>: Cost 3 vext3 <2,0,u,7>, <2,0,u,7> + 2712061446U, // <7,2,1,0>: Cost 3 vext3 RHS, <2,1,0,3> + 3785803276U, // <7,2,1,1>: Cost 4 vext3 RHS, <2,1,1,0> + 3785803285U, // <7,2,1,2>: Cost 4 vext3 RHS, <2,1,2,0> + 2712061471U, // <7,2,1,3>: Cost 3 vext3 RHS, <2,1,3,1> + 2712061482U, // <7,2,1,4>: Cost 3 vext3 RHS, <2,1,4,3> + 3766486576U, // <7,2,1,5>: Cost 4 vext3 <1,3,5,7>, <2,1,5,0> + 2712061500U, // <7,2,1,6>: Cost 3 vext3 RHS, <2,1,6,3> + 2602718850U, // <7,2,1,7>: Cost 3 vext1 , <7,u,1,2> + 2712061516U, // <7,2,1,u>: Cost 3 vext3 RHS, <2,1,u,1> + 2712061525U, // <7,2,2,0>: Cost 3 vext3 RHS, <2,2,0,1> + 2712061536U, // <7,2,2,1>: Cost 3 vext3 RHS, <2,2,1,3> + 1638319720U, // <7,2,2,2>: Cost 2 vext3 RHS, <2,2,2,2> + 1638319730U, // <7,2,2,3>: Cost 2 vext3 RHS, <2,2,3,3> + 2712061565U, // <7,2,2,4>: Cost 3 vext3 RHS, <2,2,4,5> + 2698053256U, // <7,2,2,5>: Cost 3 vext3 <2,2,5,7>, <2,2,5,7> + 2712061584U, // <7,2,2,6>: Cost 3 vext3 RHS, <2,2,6,6> + 3771795096U, // <7,2,2,7>: Cost 4 vext3 <2,2,5,7>, <2,2,7,5> + 1638319775U, // <7,2,2,u>: Cost 2 vext3 RHS, <2,2,u,3> + 1638319782U, // <7,2,3,0>: Cost 2 vext3 RHS, <2,3,0,1> + 2693924531U, // <7,2,3,1>: Cost 3 vext3 <1,5,3,7>, <2,3,1,5> + 2700560061U, // <7,2,3,2>: Cost 3 vext3 <2,6,3,7>, <2,3,2,6> + 2693924551U, // <7,2,3,3>: Cost 3 vext3 <1,5,3,7>, <2,3,3,7> + 1638319822U, // <7,2,3,4>: Cost 2 vext3 RHS, <2,3,4,5> + 2698716889U, // <7,2,3,5>: Cost 3 vext3 <2,3,5,7>, <2,3,5,7> + 2712061665U, // <7,2,3,6>: Cost 3 vext3 RHS, <2,3,6,6> + 2735949540U, // <7,2,3,7>: Cost 3 vext3 RHS, <2,3,7,0> + 1638319854U, // <7,2,3,u>: Cost 2 vext3 RHS, <2,3,u,1> + 2712061692U, // <7,2,4,0>: Cost 3 vext3 RHS, <2,4,0,6> + 2712061698U, // <7,2,4,1>: Cost 3 vext3 RHS, <2,4,1,3> + 2712061708U, // <7,2,4,2>: Cost 3 vext3 RHS, <2,4,2,4> + 2712061718U, // <7,2,4,3>: Cost 3 vext3 RHS, <2,4,3,5> + 2712061728U, // <7,2,4,4>: Cost 3 vext3 RHS, <2,4,4,6> + 2699380522U, // <7,2,4,5>: Cost 3 vext3 <2,4,5,7>, <2,4,5,7> + 2712061740U, // <7,2,4,6>: Cost 3 vext3 RHS, <2,4,6,0> + 3809691445U, // <7,2,4,7>: Cost 4 vext3 RHS, <2,4,7,0> + 2699601733U, // <7,2,4,u>: Cost 3 vext3 <2,4,u,7>, <2,4,u,7> + 2699675470U, // <7,2,5,0>: Cost 3 vext3 <2,5,0,7>, <2,5,0,7> + 3766486867U, // <7,2,5,1>: Cost 4 vext3 <1,3,5,7>, <2,5,1,3> + 2699822944U, // <7,2,5,2>: Cost 3 vext3 <2,5,2,7>, <2,5,2,7> + 2692745065U, // <7,2,5,3>: Cost 3 vext3 <1,3,5,7>, <2,5,3,7> + 2699970418U, // <7,2,5,4>: Cost 3 vext3 <2,5,4,7>, <2,5,4,7> + 3766486907U, // <7,2,5,5>: Cost 4 vext3 <1,3,5,7>, <2,5,5,7> + 2700117892U, // <7,2,5,6>: Cost 3 vext3 <2,5,6,7>, <2,5,6,7> + 3771795334U, // <7,2,5,7>: Cost 4 vext3 <2,2,5,7>, <2,5,7,0> + 2692745110U, // <7,2,5,u>: Cost 3 vext3 <1,3,5,7>, <2,5,u,7> + 2572894310U, // <7,2,6,0>: Cost 3 vext1 <3,7,2,6>, LHS + 2712061860U, // <7,2,6,1>: Cost 3 vext3 RHS, <2,6,1,3> + 2700486577U, // <7,2,6,2>: Cost 3 vext3 <2,6,2,7>, <2,6,2,7> + 1626818490U, // <7,2,6,3>: Cost 2 vext3 <2,6,3,7>, <2,6,3,7> + 2572897590U, // <7,2,6,4>: Cost 3 vext1 <3,7,2,6>, RHS + 2700707788U, // <7,2,6,5>: Cost 3 vext3 <2,6,5,7>, <2,6,5,7> + 2700781525U, // <7,2,6,6>: Cost 3 vext3 <2,6,6,7>, <2,6,6,7> + 3774597086U, // <7,2,6,7>: Cost 4 vext3 <2,6,7,7>, <2,6,7,7> + 1627187175U, // <7,2,6,u>: Cost 2 vext3 <2,6,u,7>, <2,6,u,7> + 2735949802U, // <7,2,7,0>: Cost 3 vext3 RHS, <2,7,0,1> + 3780200434U, // <7,2,7,1>: Cost 4 vext3 <3,6,2,7>, <2,7,1,0> + 3773564928U, // <7,2,7,2>: Cost 4 vext3 <2,5,2,7>, <2,7,2,5> + 2986541158U, // <7,2,7,3>: Cost 3 vzipr <5,5,7,7>, LHS + 2554989878U, // <7,2,7,4>: Cost 3 vext1 <0,7,2,7>, RHS + 3775113245U, // <7,2,7,5>: Cost 4 vext3 <2,7,5,7>, <2,7,5,7> + 4060283228U, // <7,2,7,6>: Cost 4 vzipr <5,5,7,7>, <0,4,2,6> + 2554992236U, // <7,2,7,7>: Cost 3 vext1 <0,7,2,7>, <7,7,7,7> + 2986541163U, // <7,2,7,u>: Cost 3 vzipr <5,5,7,7>, LHS + 1638320187U, // <7,2,u,0>: Cost 2 vext3 RHS, <2,u,0,1> + 2693924936U, // <7,2,u,1>: Cost 3 vext3 <1,5,3,7>, <2,u,1,5> + 1638319720U, // <7,2,u,2>: Cost 2 vext3 RHS, <2,2,2,2> + 1628145756U, // <7,2,u,3>: Cost 2 vext3 <2,u,3,7>, <2,u,3,7> + 1638320227U, // <7,2,u,4>: Cost 2 vext3 RHS, <2,u,4,5> + 2702035054U, // <7,2,u,5>: Cost 3 vext3 <2,u,5,7>, <2,u,5,7> + 2702108791U, // <7,2,u,6>: Cost 3 vext3 <2,u,6,7>, <2,u,6,7> + 2735949945U, // <7,2,u,7>: Cost 3 vext3 RHS, <2,u,7,0> + 1628514441U, // <7,2,u,u>: Cost 2 vext3 <2,u,u,7>, <2,u,u,7> + 2712062091U, // <7,3,0,0>: Cost 3 vext3 RHS, <3,0,0,0> + 1638320278U, // <7,3,0,1>: Cost 2 vext3 RHS, <3,0,1,2> + 2712062109U, // <7,3,0,2>: Cost 3 vext3 RHS, <3,0,2,0> + 2590836886U, // <7,3,0,3>: Cost 3 vext1 <6,7,3,0>, <3,0,1,2> + 2712062128U, // <7,3,0,4>: Cost 3 vext3 RHS, <3,0,4,1> + 2712062138U, // <7,3,0,5>: Cost 3 vext3 RHS, <3,0,5,2> + 2590839656U, // <7,3,0,6>: Cost 3 vext1 <6,7,3,0>, <6,7,3,0> + 3311414017U, // <7,3,0,7>: Cost 4 vrev <3,7,7,0> + 1638320341U, // <7,3,0,u>: Cost 2 vext3 RHS, <3,0,u,2> + 2237164227U, // <7,3,1,0>: Cost 3 vrev <3,7,0,1> + 2712062182U, // <7,3,1,1>: Cost 3 vext3 RHS, <3,1,1,1> + 2712062193U, // <7,3,1,2>: Cost 3 vext3 RHS, <3,1,2,3> + 2692745468U, // <7,3,1,3>: Cost 3 vext3 <1,3,5,7>, <3,1,3,5> + 2712062214U, // <7,3,1,4>: Cost 3 vext3 RHS, <3,1,4,6> + 2693925132U, // <7,3,1,5>: Cost 3 vext3 <1,5,3,7>, <3,1,5,3> + 3768183059U, // <7,3,1,6>: Cost 4 vext3 <1,6,1,7>, <3,1,6,1> + 2692745504U, // <7,3,1,7>: Cost 3 vext3 <1,3,5,7>, <3,1,7,5> + 2696063273U, // <7,3,1,u>: Cost 3 vext3 <1,u,5,7>, <3,1,u,5> + 2712062254U, // <7,3,2,0>: Cost 3 vext3 RHS, <3,2,0,1> + 2712062262U, // <7,3,2,1>: Cost 3 vext3 RHS, <3,2,1,0> + 2712062273U, // <7,3,2,2>: Cost 3 vext3 RHS, <3,2,2,2> + 2712062280U, // <7,3,2,3>: Cost 3 vext3 RHS, <3,2,3,0> + 2712062294U, // <7,3,2,4>: Cost 3 vext3 RHS, <3,2,4,5> + 2712062302U, // <7,3,2,5>: Cost 3 vext3 RHS, <3,2,5,4> + 2700560742U, // <7,3,2,6>: Cost 3 vext3 <2,6,3,7>, <3,2,6,3> + 2712062319U, // <7,3,2,7>: Cost 3 vext3 RHS, <3,2,7,3> + 2712062325U, // <7,3,2,u>: Cost 3 vext3 RHS, <3,2,u,0> + 2712062335U, // <7,3,3,0>: Cost 3 vext3 RHS, <3,3,0,1> + 2636368158U, // <7,3,3,1>: Cost 3 vext2 <3,1,7,3>, <3,1,7,3> + 2637031791U, // <7,3,3,2>: Cost 3 vext2 <3,2,7,3>, <3,2,7,3> + 1638320540U, // <7,3,3,3>: Cost 2 vext3 RHS, <3,3,3,3> + 2712062374U, // <7,3,3,4>: Cost 3 vext3 RHS, <3,3,4,4> + 2704689586U, // <7,3,3,5>: Cost 3 vext3 <3,3,5,7>, <3,3,5,7> + 2590864235U, // <7,3,3,6>: Cost 3 vext1 <6,7,3,3>, <6,7,3,3> + 2704837060U, // <7,3,3,7>: Cost 3 vext3 <3,3,7,7>, <3,3,7,7> + 1638320540U, // <7,3,3,u>: Cost 2 vext3 RHS, <3,3,3,3> + 2712062416U, // <7,3,4,0>: Cost 3 vext3 RHS, <3,4,0,1> + 2712062426U, // <7,3,4,1>: Cost 3 vext3 RHS, <3,4,1,2> + 2566981640U, // <7,3,4,2>: Cost 3 vext1 <2,7,3,4>, <2,7,3,4> + 2712062447U, // <7,3,4,3>: Cost 3 vext3 RHS, <3,4,3,5> + 2712062456U, // <7,3,4,4>: Cost 3 vext3 RHS, <3,4,4,5> + 1638320642U, // <7,3,4,5>: Cost 2 vext3 RHS, <3,4,5,6> + 2648313204U, // <7,3,4,6>: Cost 3 vext2 <5,1,7,3>, <4,6,4,6> + 3311446789U, // <7,3,4,7>: Cost 4 vrev <3,7,7,4> + 1638320669U, // <7,3,4,u>: Cost 2 vext3 RHS, <3,4,u,6> + 2602819686U, // <7,3,5,0>: Cost 3 vext1 , LHS + 1574571728U, // <7,3,5,1>: Cost 2 vext2 <5,1,7,3>, <5,1,7,3> + 2648977185U, // <7,3,5,2>: Cost 3 vext2 <5,2,7,3>, <5,2,7,3> + 2705869378U, // <7,3,5,3>: Cost 3 vext3 <3,5,3,7>, <3,5,3,7> + 2237491947U, // <7,3,5,4>: Cost 3 vrev <3,7,4,5> + 2706016852U, // <7,3,5,5>: Cost 3 vext3 <3,5,5,7>, <3,5,5,7> + 2648313954U, // <7,3,5,6>: Cost 3 vext2 <5,1,7,3>, <5,6,7,0> + 2692745823U, // <7,3,5,7>: Cost 3 vext3 <1,3,5,7>, <3,5,7,0> + 1579217159U, // <7,3,5,u>: Cost 2 vext2 <5,u,7,3>, <5,u,7,3> + 2706311800U, // <7,3,6,0>: Cost 3 vext3 <3,6,0,7>, <3,6,0,7> + 2654286249U, // <7,3,6,1>: Cost 3 vext2 <6,1,7,3>, <6,1,7,3> + 1581208058U, // <7,3,6,2>: Cost 2 vext2 <6,2,7,3>, <6,2,7,3> + 2706533011U, // <7,3,6,3>: Cost 3 vext3 <3,6,3,7>, <3,6,3,7> + 2706606748U, // <7,3,6,4>: Cost 3 vext3 <3,6,4,7>, <3,6,4,7> + 3780422309U, // <7,3,6,5>: Cost 4 vext3 <3,6,5,7>, <3,6,5,7> + 2712062637U, // <7,3,6,6>: Cost 3 vext3 RHS, <3,6,6,6> + 2706827959U, // <7,3,6,7>: Cost 3 vext3 <3,6,7,7>, <3,6,7,7> + 1585189856U, // <7,3,6,u>: Cost 2 vext2 <6,u,7,3>, <6,u,7,3> + 2693925571U, // <7,3,7,0>: Cost 3 vext3 <1,5,3,7>, <3,7,0,1> + 2693925584U, // <7,3,7,1>: Cost 3 vext3 <1,5,3,7>, <3,7,1,5> + 2700561114U, // <7,3,7,2>: Cost 3 vext3 <2,6,3,7>, <3,7,2,6> + 2572978916U, // <7,3,7,3>: Cost 3 vext1 <3,7,3,7>, <3,7,3,7> + 2693925611U, // <7,3,7,4>: Cost 3 vext3 <1,5,3,7>, <3,7,4,5> + 2707344118U, // <7,3,7,5>: Cost 3 vext3 <3,7,5,7>, <3,7,5,7> + 2654950894U, // <7,3,7,6>: Cost 3 vext2 <6,2,7,3>, <7,6,2,7> + 2648315500U, // <7,3,7,7>: Cost 3 vext2 <5,1,7,3>, <7,7,7,7> + 2693925643U, // <7,3,7,u>: Cost 3 vext3 <1,5,3,7>, <3,7,u,1> + 2237221578U, // <7,3,u,0>: Cost 3 vrev <3,7,0,u> + 1638320926U, // <7,3,u,1>: Cost 2 vext3 RHS, <3,u,1,2> + 1593153452U, // <7,3,u,2>: Cost 2 vext2 , + 1638320540U, // <7,3,u,3>: Cost 2 vext3 RHS, <3,3,3,3> + 2237516526U, // <7,3,u,4>: Cost 3 vrev <3,7,4,u> + 1638320966U, // <7,3,u,5>: Cost 2 vext3 RHS, <3,u,5,6> + 2712062796U, // <7,3,u,6>: Cost 3 vext3 RHS, <3,u,6,3> + 2692967250U, // <7,3,u,7>: Cost 3 vext3 <1,3,u,7>, <3,u,7,0> + 1638320989U, // <7,3,u,u>: Cost 2 vext3 RHS, <3,u,u,2> + 2651635712U, // <7,4,0,0>: Cost 3 vext2 <5,6,7,4>, <0,0,0,0> + 1577893990U, // <7,4,0,1>: Cost 2 vext2 <5,6,7,4>, LHS + 2651635876U, // <7,4,0,2>: Cost 3 vext2 <5,6,7,4>, <0,2,0,2> + 3785804672U, // <7,4,0,3>: Cost 4 vext3 RHS, <4,0,3,1> + 2651636050U, // <7,4,0,4>: Cost 3 vext2 <5,6,7,4>, <0,4,1,5> + 1638468498U, // <7,4,0,5>: Cost 2 vext3 RHS, <4,0,5,1> + 1638468508U, // <7,4,0,6>: Cost 2 vext3 RHS, <4,0,6,2> + 3787795364U, // <7,4,0,7>: Cost 4 vext3 RHS, <4,0,7,1> + 1640459181U, // <7,4,0,u>: Cost 2 vext3 RHS, <4,0,u,1> + 2651636470U, // <7,4,1,0>: Cost 3 vext2 <5,6,7,4>, <1,0,3,2> + 2651636532U, // <7,4,1,1>: Cost 3 vext2 <5,6,7,4>, <1,1,1,1> + 2712062922U, // <7,4,1,2>: Cost 3 vext3 RHS, <4,1,2,3> + 2639029248U, // <7,4,1,3>: Cost 3 vext2 <3,5,7,4>, <1,3,5,7> + 2712062940U, // <7,4,1,4>: Cost 3 vext3 RHS, <4,1,4,3> + 2712062946U, // <7,4,1,5>: Cost 3 vext3 RHS, <4,1,5,0> + 2712062958U, // <7,4,1,6>: Cost 3 vext3 RHS, <4,1,6,3> + 3785804791U, // <7,4,1,7>: Cost 4 vext3 RHS, <4,1,7,3> + 2712062973U, // <7,4,1,u>: Cost 3 vext3 RHS, <4,1,u,0> + 3785804807U, // <7,4,2,0>: Cost 4 vext3 RHS, <4,2,0,1> + 3785804818U, // <7,4,2,1>: Cost 4 vext3 RHS, <4,2,1,3> + 2651637352U, // <7,4,2,2>: Cost 3 vext2 <5,6,7,4>, <2,2,2,2> + 2651637414U, // <7,4,2,3>: Cost 3 vext2 <5,6,7,4>, <2,3,0,1> + 3716753194U, // <7,4,2,4>: Cost 4 vext2 <4,2,7,4>, <2,4,5,7> + 2712063030U, // <7,4,2,5>: Cost 3 vext3 RHS, <4,2,5,3> + 2712063036U, // <7,4,2,6>: Cost 3 vext3 RHS, <4,2,6,0> + 3773123658U, // <7,4,2,7>: Cost 4 vext3 <2,4,5,7>, <4,2,7,5> + 2712063054U, // <7,4,2,u>: Cost 3 vext3 RHS, <4,2,u,0> + 2651637910U, // <7,4,3,0>: Cost 3 vext2 <5,6,7,4>, <3,0,1,2> + 3712772348U, // <7,4,3,1>: Cost 4 vext2 <3,5,7,4>, <3,1,3,5> + 3785804906U, // <7,4,3,2>: Cost 4 vext3 RHS, <4,3,2,1> + 2651638172U, // <7,4,3,3>: Cost 3 vext2 <5,6,7,4>, <3,3,3,3> + 2651638274U, // <7,4,3,4>: Cost 3 vext2 <5,6,7,4>, <3,4,5,6> + 2639030883U, // <7,4,3,5>: Cost 3 vext2 <3,5,7,4>, <3,5,7,4> + 2712063122U, // <7,4,3,6>: Cost 3 vext3 RHS, <4,3,6,5> + 3712772836U, // <7,4,3,7>: Cost 4 vext2 <3,5,7,4>, <3,7,3,7> + 2641021782U, // <7,4,3,u>: Cost 3 vext2 <3,u,7,4>, <3,u,7,4> + 2714053802U, // <7,4,4,0>: Cost 3 vext3 RHS, <4,4,0,2> + 3785804978U, // <7,4,4,1>: Cost 4 vext3 RHS, <4,4,1,1> + 3716754505U, // <7,4,4,2>: Cost 4 vext2 <4,2,7,4>, <4,2,7,4> + 3785804998U, // <7,4,4,3>: Cost 4 vext3 RHS, <4,4,3,3> + 1638321360U, // <7,4,4,4>: Cost 2 vext3 RHS, <4,4,4,4> + 1638468826U, // <7,4,4,5>: Cost 2 vext3 RHS, <4,4,5,5> + 1638468836U, // <7,4,4,6>: Cost 2 vext3 RHS, <4,4,6,6> + 3785215214U, // <7,4,4,7>: Cost 4 vext3 <4,4,7,7>, <4,4,7,7> + 1640459509U, // <7,4,4,u>: Cost 2 vext3 RHS, <4,4,u,5> + 1517207654U, // <7,4,5,0>: Cost 2 vext1 <6,7,4,5>, LHS + 2573034640U, // <7,4,5,1>: Cost 3 vext1 <3,7,4,5>, <1,5,3,7> + 2712063246U, // <7,4,5,2>: Cost 3 vext3 RHS, <4,5,2,3> + 2573036267U, // <7,4,5,3>: Cost 3 vext1 <3,7,4,5>, <3,7,4,5> + 1517210934U, // <7,4,5,4>: Cost 2 vext1 <6,7,4,5>, RHS + 2711989549U, // <7,4,5,5>: Cost 3 vext3 <4,5,5,7>, <4,5,5,7> + 564579638U, // <7,4,5,6>: Cost 1 vext3 RHS, RHS + 2651639976U, // <7,4,5,7>: Cost 3 vext2 <5,6,7,4>, <5,7,5,7> + 564579656U, // <7,4,5,u>: Cost 1 vext3 RHS, RHS + 2712063307U, // <7,4,6,0>: Cost 3 vext3 RHS, <4,6,0,1> + 3767668056U, // <7,4,6,1>: Cost 4 vext3 <1,5,3,7>, <4,6,1,5> + 2651640314U, // <7,4,6,2>: Cost 3 vext2 <5,6,7,4>, <6,2,7,3> + 2655621708U, // <7,4,6,3>: Cost 3 vext2 <6,3,7,4>, <6,3,7,4> + 1638468980U, // <7,4,6,4>: Cost 2 vext3 RHS, <4,6,4,6> + 2712063358U, // <7,4,6,5>: Cost 3 vext3 RHS, <4,6,5,7> + 2712063367U, // <7,4,6,6>: Cost 3 vext3 RHS, <4,6,6,7> + 2712210826U, // <7,4,6,7>: Cost 3 vext3 RHS, <4,6,7,1> + 1638469012U, // <7,4,6,u>: Cost 2 vext3 RHS, <4,6,u,2> + 2651640826U, // <7,4,7,0>: Cost 3 vext2 <5,6,7,4>, <7,0,1,2> + 3773713830U, // <7,4,7,1>: Cost 4 vext3 <2,5,4,7>, <4,7,1,2> + 3773713842U, // <7,4,7,2>: Cost 4 vext3 <2,5,4,7>, <4,7,2,5> + 3780349372U, // <7,4,7,3>: Cost 4 vext3 <3,6,4,7>, <4,7,3,6> + 2651641140U, // <7,4,7,4>: Cost 3 vext2 <5,6,7,4>, <7,4,0,1> + 2712210888U, // <7,4,7,5>: Cost 3 vext3 RHS, <4,7,5,0> + 2712210898U, // <7,4,7,6>: Cost 3 vext3 RHS, <4,7,6,1> + 2651641452U, // <7,4,7,7>: Cost 3 vext2 <5,6,7,4>, <7,7,7,7> + 2713538026U, // <7,4,7,u>: Cost 3 vext3 <4,7,u,7>, <4,7,u,7> + 1517232230U, // <7,4,u,0>: Cost 2 vext1 <6,7,4,u>, LHS + 1577899822U, // <7,4,u,1>: Cost 2 vext2 <5,6,7,4>, LHS + 2712063489U, // <7,4,u,2>: Cost 3 vext3 RHS, <4,u,2,3> + 2573060846U, // <7,4,u,3>: Cost 3 vext1 <3,7,4,u>, <3,7,4,u> + 1640312342U, // <7,4,u,4>: Cost 2 vext3 RHS, <4,u,4,6> + 1638469146U, // <7,4,u,5>: Cost 2 vext3 RHS, <4,u,5,1> + 564579881U, // <7,4,u,6>: Cost 1 vext3 RHS, RHS + 2714054192U, // <7,4,u,7>: Cost 3 vext3 RHS, <4,u,7,5> + 564579899U, // <7,4,u,u>: Cost 1 vext3 RHS, RHS + 2579038310U, // <7,5,0,0>: Cost 3 vext1 <4,7,5,0>, LHS + 2636382310U, // <7,5,0,1>: Cost 3 vext2 <3,1,7,5>, LHS + 2796339302U, // <7,5,0,2>: Cost 3 vuzpl <7,4,5,6>, LHS + 3646810719U, // <7,5,0,3>: Cost 4 vext1 <3,7,5,0>, <3,5,7,0> + 2712063586U, // <7,5,0,4>: Cost 3 vext3 RHS, <5,0,4,1> + 2735951467U, // <7,5,0,5>: Cost 3 vext3 RHS, <5,0,5,1> + 2735951476U, // <7,5,0,6>: Cost 3 vext3 RHS, <5,0,6,1> + 2579043322U, // <7,5,0,7>: Cost 3 vext1 <4,7,5,0>, <7,0,1,2> + 2636382877U, // <7,5,0,u>: Cost 3 vext2 <3,1,7,5>, LHS + 2712211087U, // <7,5,1,0>: Cost 3 vext3 RHS, <5,1,0,1> + 3698180916U, // <7,5,1,1>: Cost 4 vext2 <1,1,7,5>, <1,1,1,1> + 3710124950U, // <7,5,1,2>: Cost 4 vext2 <3,1,7,5>, <1,2,3,0> + 2636383232U, // <7,5,1,3>: Cost 3 vext2 <3,1,7,5>, <1,3,5,7> + 2712211127U, // <7,5,1,4>: Cost 3 vext3 RHS, <5,1,4,5> + 2590994128U, // <7,5,1,5>: Cost 3 vext1 <6,7,5,1>, <5,1,7,3> + 2590995323U, // <7,5,1,6>: Cost 3 vext1 <6,7,5,1>, <6,7,5,1> + 1638469328U, // <7,5,1,7>: Cost 2 vext3 RHS, <5,1,7,3> + 1638469337U, // <7,5,1,u>: Cost 2 vext3 RHS, <5,1,u,3> + 3785805536U, // <7,5,2,0>: Cost 4 vext3 RHS, <5,2,0,1> + 3785805544U, // <7,5,2,1>: Cost 4 vext3 RHS, <5,2,1,0> + 3704817288U, // <7,5,2,2>: Cost 4 vext2 <2,2,7,5>, <2,2,5,7> + 2712063742U, // <7,5,2,3>: Cost 3 vext3 RHS, <5,2,3,4> + 3716761386U, // <7,5,2,4>: Cost 4 vext2 <4,2,7,5>, <2,4,5,7> + 2714054415U, // <7,5,2,5>: Cost 3 vext3 RHS, <5,2,5,3> + 3774304024U, // <7,5,2,6>: Cost 4 vext3 <2,6,3,7>, <5,2,6,3> + 2712063777U, // <7,5,2,7>: Cost 3 vext3 RHS, <5,2,7,3> + 2712063787U, // <7,5,2,u>: Cost 3 vext3 RHS, <5,2,u,4> + 3634888806U, // <7,5,3,0>: Cost 4 vext1 <1,7,5,3>, LHS + 2636384544U, // <7,5,3,1>: Cost 3 vext2 <3,1,7,5>, <3,1,7,5> + 3710790001U, // <7,5,3,2>: Cost 4 vext2 <3,2,7,5>, <3,2,7,5> + 3710126492U, // <7,5,3,3>: Cost 4 vext2 <3,1,7,5>, <3,3,3,3> + 3634892086U, // <7,5,3,4>: Cost 4 vext1 <1,7,5,3>, RHS + 2639039076U, // <7,5,3,5>: Cost 3 vext2 <3,5,7,5>, <3,5,7,5> + 3713444533U, // <7,5,3,6>: Cost 4 vext2 <3,6,7,5>, <3,6,7,5> + 2693926767U, // <7,5,3,7>: Cost 3 vext3 <1,5,3,7>, <5,3,7,0> + 2712063864U, // <7,5,3,u>: Cost 3 vext3 RHS, <5,3,u,0> + 2579071078U, // <7,5,4,0>: Cost 3 vext1 <4,7,5,4>, LHS + 3646841856U, // <7,5,4,1>: Cost 4 vext1 <3,7,5,4>, <1,3,5,7> + 3716762698U, // <7,5,4,2>: Cost 4 vext2 <4,2,7,5>, <4,2,7,5> + 3646843491U, // <7,5,4,3>: Cost 4 vext1 <3,7,5,4>, <3,5,7,4> + 2579074358U, // <7,5,4,4>: Cost 3 vext1 <4,7,5,4>, RHS + 2636385590U, // <7,5,4,5>: Cost 3 vext2 <3,1,7,5>, RHS + 2645675406U, // <7,5,4,6>: Cost 3 vext2 <4,6,7,5>, <4,6,7,5> + 1638322118U, // <7,5,4,7>: Cost 2 vext3 RHS, <5,4,7,6> + 1638469583U, // <7,5,4,u>: Cost 2 vext3 RHS, <5,4,u,6> + 2714054611U, // <7,5,5,0>: Cost 3 vext3 RHS, <5,5,0,1> + 2652974800U, // <7,5,5,1>: Cost 3 vext2 <5,u,7,5>, <5,1,7,3> + 3710127905U, // <7,5,5,2>: Cost 4 vext2 <3,1,7,5>, <5,2,7,3> + 3785805808U, // <7,5,5,3>: Cost 4 vext3 RHS, <5,5,3,3> + 2712211450U, // <7,5,5,4>: Cost 3 vext3 RHS, <5,5,4,4> + 1638322180U, // <7,5,5,5>: Cost 2 vext3 RHS, <5,5,5,5> + 2712064014U, // <7,5,5,6>: Cost 3 vext3 RHS, <5,5,6,6> + 1638469656U, // <7,5,5,7>: Cost 2 vext3 RHS, <5,5,7,7> + 1638469665U, // <7,5,5,u>: Cost 2 vext3 RHS, <5,5,u,7> + 2712064036U, // <7,5,6,0>: Cost 3 vext3 RHS, <5,6,0,1> + 2714054707U, // <7,5,6,1>: Cost 3 vext3 RHS, <5,6,1,7> + 3785805879U, // <7,5,6,2>: Cost 4 vext3 RHS, <5,6,2,2> + 2712064066U, // <7,5,6,3>: Cost 3 vext3 RHS, <5,6,3,4> + 2712064076U, // <7,5,6,4>: Cost 3 vext3 RHS, <5,6,4,5> + 2714054743U, // <7,5,6,5>: Cost 3 vext3 RHS, <5,6,5,7> + 2712064096U, // <7,5,6,6>: Cost 3 vext3 RHS, <5,6,6,7> + 1638322274U, // <7,5,6,7>: Cost 2 vext3 RHS, <5,6,7,0> + 1638469739U, // <7,5,6,u>: Cost 2 vext3 RHS, <5,6,u,0> + 1511325798U, // <7,5,7,0>: Cost 2 vext1 <5,7,5,7>, LHS + 2692747392U, // <7,5,7,1>: Cost 3 vext3 <1,3,5,7>, <5,7,1,3> + 2585069160U, // <7,5,7,2>: Cost 3 vext1 <5,7,5,7>, <2,2,2,2> + 2573126390U, // <7,5,7,3>: Cost 3 vext1 <3,7,5,7>, <3,7,5,7> + 1511329078U, // <7,5,7,4>: Cost 2 vext1 <5,7,5,7>, RHS + 1638469800U, // <7,5,7,5>: Cost 2 vext3 RHS, <5,7,5,7> + 2712211626U, // <7,5,7,6>: Cost 3 vext3 RHS, <5,7,6,0> + 2712211636U, // <7,5,7,7>: Cost 3 vext3 RHS, <5,7,7,1> + 1638469823U, // <7,5,7,u>: Cost 2 vext3 RHS, <5,7,u,3> + 1511333990U, // <7,5,u,0>: Cost 2 vext1 <5,7,5,u>, LHS + 2636388142U, // <7,5,u,1>: Cost 3 vext2 <3,1,7,5>, LHS + 2712211671U, // <7,5,u,2>: Cost 3 vext3 RHS, <5,u,2,0> + 2573134583U, // <7,5,u,3>: Cost 3 vext1 <3,7,5,u>, <3,7,5,u> + 1511337270U, // <7,5,u,4>: Cost 2 vext1 <5,7,5,u>, RHS + 1638469881U, // <7,5,u,5>: Cost 2 vext3 RHS, <5,u,5,7> + 2712064258U, // <7,5,u,6>: Cost 3 vext3 RHS, <5,u,6,7> + 1638469892U, // <7,5,u,7>: Cost 2 vext3 RHS, <5,u,7,0> + 1638469904U, // <7,5,u,u>: Cost 2 vext3 RHS, <5,u,u,3> + 2650324992U, // <7,6,0,0>: Cost 3 vext2 <5,4,7,6>, <0,0,0,0> + 1576583270U, // <7,6,0,1>: Cost 2 vext2 <5,4,7,6>, LHS + 2712064300U, // <7,6,0,2>: Cost 3 vext3 RHS, <6,0,2,4> + 2255295336U, // <7,6,0,3>: Cost 3 vrev <6,7,3,0> + 2712064316U, // <7,6,0,4>: Cost 3 vext3 RHS, <6,0,4,2> + 2585088098U, // <7,6,0,5>: Cost 3 vext1 <5,7,6,0>, <5,6,7,0> + 2735952204U, // <7,6,0,6>: Cost 3 vext3 RHS, <6,0,6,0> + 2712211799U, // <7,6,0,7>: Cost 3 vext3 RHS, <6,0,7,2> + 1576583837U, // <7,6,0,u>: Cost 2 vext2 <5,4,7,6>, LHS + 1181340494U, // <7,6,1,0>: Cost 2 vrev <6,7,0,1> + 2650325812U, // <7,6,1,1>: Cost 3 vext2 <5,4,7,6>, <1,1,1,1> + 2650325910U, // <7,6,1,2>: Cost 3 vext2 <5,4,7,6>, <1,2,3,0> + 2650325976U, // <7,6,1,3>: Cost 3 vext2 <5,4,7,6>, <1,3,1,3> + 2579123510U, // <7,6,1,4>: Cost 3 vext1 <4,7,6,1>, RHS + 2650326160U, // <7,6,1,5>: Cost 3 vext2 <5,4,7,6>, <1,5,3,7> + 2714055072U, // <7,6,1,6>: Cost 3 vext3 RHS, <6,1,6,3> + 2712064425U, // <7,6,1,7>: Cost 3 vext3 RHS, <6,1,7,3> + 1181930390U, // <7,6,1,u>: Cost 2 vrev <6,7,u,1> + 2712211897U, // <7,6,2,0>: Cost 3 vext3 RHS, <6,2,0,1> + 2714055108U, // <7,6,2,1>: Cost 3 vext3 RHS, <6,2,1,3> + 2650326632U, // <7,6,2,2>: Cost 3 vext2 <5,4,7,6>, <2,2,2,2> + 2650326694U, // <7,6,2,3>: Cost 3 vext2 <5,4,7,6>, <2,3,0,1> + 2714055137U, // <7,6,2,4>: Cost 3 vext3 RHS, <6,2,4,5> + 2714055148U, // <7,6,2,5>: Cost 3 vext3 RHS, <6,2,5,7> + 2650326970U, // <7,6,2,6>: Cost 3 vext2 <5,4,7,6>, <2,6,3,7> + 1638470138U, // <7,6,2,7>: Cost 2 vext3 RHS, <6,2,7,3> + 1638470147U, // <7,6,2,u>: Cost 2 vext3 RHS, <6,2,u,3> + 2650327190U, // <7,6,3,0>: Cost 3 vext2 <5,4,7,6>, <3,0,1,2> + 2255172441U, // <7,6,3,1>: Cost 3 vrev <6,7,1,3> + 2255246178U, // <7,6,3,2>: Cost 3 vrev <6,7,2,3> + 2650327452U, // <7,6,3,3>: Cost 3 vext2 <5,4,7,6>, <3,3,3,3> + 2712064562U, // <7,6,3,4>: Cost 3 vext3 RHS, <6,3,4,5> + 2650327627U, // <7,6,3,5>: Cost 3 vext2 <5,4,7,6>, <3,5,4,7> + 3713452726U, // <7,6,3,6>: Cost 4 vext2 <3,6,7,6>, <3,6,7,6> + 2700563016U, // <7,6,3,7>: Cost 3 vext3 <2,6,3,7>, <6,3,7,0> + 2712064593U, // <7,6,3,u>: Cost 3 vext3 RHS, <6,3,u,0> + 2650327954U, // <7,6,4,0>: Cost 3 vext2 <5,4,7,6>, <4,0,5,1> + 2735952486U, // <7,6,4,1>: Cost 3 vext3 RHS, <6,4,1,3> + 2735952497U, // <7,6,4,2>: Cost 3 vext3 RHS, <6,4,2,5> + 2255328108U, // <7,6,4,3>: Cost 3 vrev <6,7,3,4> + 2712212100U, // <7,6,4,4>: Cost 3 vext3 RHS, <6,4,4,6> + 1576586550U, // <7,6,4,5>: Cost 2 vext2 <5,4,7,6>, RHS + 2714055312U, // <7,6,4,6>: Cost 3 vext3 RHS, <6,4,6,0> + 2712212126U, // <7,6,4,7>: Cost 3 vext3 RHS, <6,4,7,5> + 1576586793U, // <7,6,4,u>: Cost 2 vext2 <5,4,7,6>, RHS + 2579152998U, // <7,6,5,0>: Cost 3 vext1 <4,7,6,5>, LHS + 2650328784U, // <7,6,5,1>: Cost 3 vext2 <5,4,7,6>, <5,1,7,3> + 2714055364U, // <7,6,5,2>: Cost 3 vext3 RHS, <6,5,2,7> + 3785806538U, // <7,6,5,3>: Cost 4 vext3 RHS, <6,5,3,4> + 1576587206U, // <7,6,5,4>: Cost 2 vext2 <5,4,7,6>, <5,4,7,6> + 2650329092U, // <7,6,5,5>: Cost 3 vext2 <5,4,7,6>, <5,5,5,5> + 2650329186U, // <7,6,5,6>: Cost 3 vext2 <5,4,7,6>, <5,6,7,0> + 2712064753U, // <7,6,5,7>: Cost 3 vext3 RHS, <6,5,7,7> + 1181963162U, // <7,6,5,u>: Cost 2 vrev <6,7,u,5> + 2714055421U, // <7,6,6,0>: Cost 3 vext3 RHS, <6,6,0,1> + 2714055432U, // <7,6,6,1>: Cost 3 vext3 RHS, <6,6,1,3> + 2650329594U, // <7,6,6,2>: Cost 3 vext2 <5,4,7,6>, <6,2,7,3> + 3785806619U, // <7,6,6,3>: Cost 4 vext3 RHS, <6,6,3,4> + 2712212260U, // <7,6,6,4>: Cost 3 vext3 RHS, <6,6,4,4> + 2714055472U, // <7,6,6,5>: Cost 3 vext3 RHS, <6,6,5,7> + 1638323000U, // <7,6,6,6>: Cost 2 vext3 RHS, <6,6,6,6> + 1638470466U, // <7,6,6,7>: Cost 2 vext3 RHS, <6,6,7,7> + 1638470475U, // <7,6,6,u>: Cost 2 vext3 RHS, <6,6,u,7> + 1638323022U, // <7,6,7,0>: Cost 2 vext3 RHS, <6,7,0,1> + 2712064854U, // <7,6,7,1>: Cost 3 vext3 RHS, <6,7,1,0> + 2712064865U, // <7,6,7,2>: Cost 3 vext3 RHS, <6,7,2,2> + 2712064872U, // <7,6,7,3>: Cost 3 vext3 RHS, <6,7,3,0> + 1638323062U, // <7,6,7,4>: Cost 2 vext3 RHS, <6,7,4,5> + 2712064894U, // <7,6,7,5>: Cost 3 vext3 RHS, <6,7,5,4> + 2712064905U, // <7,6,7,6>: Cost 3 vext3 RHS, <6,7,6,6> + 2712064915U, // <7,6,7,7>: Cost 3 vext3 RHS, <6,7,7,7> + 1638323094U, // <7,6,7,u>: Cost 2 vext3 RHS, <6,7,u,1> + 1638470559U, // <7,6,u,0>: Cost 2 vext3 RHS, <6,u,0,1> + 1576589102U, // <7,6,u,1>: Cost 2 vext2 <5,4,7,6>, LHS + 2712212402U, // <7,6,u,2>: Cost 3 vext3 RHS, <6,u,2,2> + 2712212409U, // <7,6,u,3>: Cost 3 vext3 RHS, <6,u,3,0> + 1638470599U, // <7,6,u,4>: Cost 2 vext3 RHS, <6,u,4,5> + 1576589466U, // <7,6,u,5>: Cost 2 vext2 <5,4,7,6>, RHS + 1638323000U, // <7,6,u,6>: Cost 2 vext3 RHS, <6,6,6,6> + 1638470624U, // <7,6,u,7>: Cost 2 vext3 RHS, <6,u,7,3> + 1638470631U, // <7,6,u,u>: Cost 2 vext3 RHS, <6,u,u,1> + 2712065007U, // <7,7,0,0>: Cost 3 vext3 RHS, <7,0,0,0> + 1638323194U, // <7,7,0,1>: Cost 2 vext3 RHS, <7,0,1,2> + 2712065025U, // <7,7,0,2>: Cost 3 vext3 RHS, <7,0,2,0> + 3646958337U, // <7,7,0,3>: Cost 4 vext1 <3,7,7,0>, <3,7,7,0> + 2712065044U, // <7,7,0,4>: Cost 3 vext3 RHS, <7,0,4,1> + 2585161907U, // <7,7,0,5>: Cost 3 vext1 <5,7,7,0>, <5,7,7,0> + 2591134604U, // <7,7,0,6>: Cost 3 vext1 <6,7,7,0>, <6,7,7,0> + 2591134714U, // <7,7,0,7>: Cost 3 vext1 <6,7,7,0>, <7,0,1,2> + 1638323257U, // <7,7,0,u>: Cost 2 vext3 RHS, <7,0,u,2> + 2712065091U, // <7,7,1,0>: Cost 3 vext3 RHS, <7,1,0,3> + 2712065098U, // <7,7,1,1>: Cost 3 vext3 RHS, <7,1,1,1> + 2712065109U, // <7,7,1,2>: Cost 3 vext3 RHS, <7,1,2,3> + 2692748384U, // <7,7,1,3>: Cost 3 vext3 <1,3,5,7>, <7,1,3,5> + 2585169206U, // <7,7,1,4>: Cost 3 vext1 <5,7,7,1>, RHS + 2693928048U, // <7,7,1,5>: Cost 3 vext3 <1,5,3,7>, <7,1,5,3> + 2585170766U, // <7,7,1,6>: Cost 3 vext1 <5,7,7,1>, <6,7,0,1> + 2735953024U, // <7,7,1,7>: Cost 3 vext3 RHS, <7,1,7,1> + 2695918731U, // <7,7,1,u>: Cost 3 vext3 <1,u,3,7>, <7,1,u,3> + 3770471574U, // <7,7,2,0>: Cost 4 vext3 <2,0,5,7>, <7,2,0,5> + 3785807002U, // <7,7,2,1>: Cost 4 vext3 RHS, <7,2,1,0> + 2712065189U, // <7,7,2,2>: Cost 3 vext3 RHS, <7,2,2,2> + 2712065196U, // <7,7,2,3>: Cost 3 vext3 RHS, <7,2,3,0> + 3773125818U, // <7,7,2,4>: Cost 4 vext3 <2,4,5,7>, <7,2,4,5> + 3766490305U, // <7,7,2,5>: Cost 4 vext3 <1,3,5,7>, <7,2,5,3> + 2700563658U, // <7,7,2,6>: Cost 3 vext3 <2,6,3,7>, <7,2,6,3> + 2735953107U, // <7,7,2,7>: Cost 3 vext3 RHS, <7,2,7,3> + 2701890780U, // <7,7,2,u>: Cost 3 vext3 <2,u,3,7>, <7,2,u,3> + 2712065251U, // <7,7,3,0>: Cost 3 vext3 RHS, <7,3,0,1> + 3766490350U, // <7,7,3,1>: Cost 4 vext3 <1,3,5,7>, <7,3,1,3> + 3774305530U, // <7,7,3,2>: Cost 4 vext3 <2,6,3,7>, <7,3,2,6> + 2637728196U, // <7,7,3,3>: Cost 3 vext2 <3,3,7,7>, <3,3,7,7> + 2712065291U, // <7,7,3,4>: Cost 3 vext3 RHS, <7,3,4,5> + 2585186486U, // <7,7,3,5>: Cost 3 vext1 <5,7,7,3>, <5,7,7,3> + 2639719095U, // <7,7,3,6>: Cost 3 vext2 <3,6,7,7>, <3,6,7,7> + 2640382728U, // <7,7,3,7>: Cost 3 vext2 <3,7,7,7>, <3,7,7,7> + 2641046361U, // <7,7,3,u>: Cost 3 vext2 <3,u,7,7>, <3,u,7,7> + 2712212792U, // <7,7,4,0>: Cost 3 vext3 RHS, <7,4,0,5> + 3646989312U, // <7,7,4,1>: Cost 4 vext1 <3,7,7,4>, <1,3,5,7> + 3785807176U, // <7,7,4,2>: Cost 4 vext3 RHS, <7,4,2,3> + 3646991109U, // <7,7,4,3>: Cost 4 vext1 <3,7,7,4>, <3,7,7,4> + 2712065371U, // <7,7,4,4>: Cost 3 vext3 RHS, <7,4,4,4> + 1638323558U, // <7,7,4,5>: Cost 2 vext3 RHS, <7,4,5,6> + 2712212845U, // <7,7,4,6>: Cost 3 vext3 RHS, <7,4,6,4> + 2591167846U, // <7,7,4,7>: Cost 3 vext1 <6,7,7,4>, <7,4,5,6> + 1638323585U, // <7,7,4,u>: Cost 2 vext3 RHS, <7,4,u,6> + 2585198694U, // <7,7,5,0>: Cost 3 vext1 <5,7,7,5>, LHS + 2712212884U, // <7,7,5,1>: Cost 3 vext3 RHS, <7,5,1,7> + 3711471393U, // <7,7,5,2>: Cost 4 vext2 <3,3,7,7>, <5,2,7,3> + 2649673590U, // <7,7,5,3>: Cost 3 vext2 <5,3,7,7>, <5,3,7,7> + 2712065455U, // <7,7,5,4>: Cost 3 vext3 RHS, <7,5,4,7> + 1577259032U, // <7,7,5,5>: Cost 2 vext2 <5,5,7,7>, <5,5,7,7> + 2712065473U, // <7,7,5,6>: Cost 3 vext3 RHS, <7,5,6,7> + 2712212936U, // <7,7,5,7>: Cost 3 vext3 RHS, <7,5,7,5> + 1579249931U, // <7,7,5,u>: Cost 2 vext2 <5,u,7,7>, <5,u,7,7> + 2591178854U, // <7,7,6,0>: Cost 3 vext1 <6,7,7,6>, LHS + 2735953374U, // <7,7,6,1>: Cost 3 vext3 RHS, <7,6,1,0> + 2712212974U, // <7,7,6,2>: Cost 3 vext3 RHS, <7,6,2,7> + 2655646287U, // <7,7,6,3>: Cost 3 vext2 <6,3,7,7>, <6,3,7,7> + 2591182134U, // <7,7,6,4>: Cost 3 vext1 <6,7,7,6>, RHS + 2656973553U, // <7,7,6,5>: Cost 3 vext2 <6,5,7,7>, <6,5,7,7> + 1583895362U, // <7,7,6,6>: Cost 2 vext2 <6,6,7,7>, <6,6,7,7> + 2712065556U, // <7,7,6,7>: Cost 3 vext3 RHS, <7,6,7,0> + 1585222628U, // <7,7,6,u>: Cost 2 vext2 <6,u,7,7>, <6,u,7,7> + 1523417190U, // <7,7,7,0>: Cost 2 vext1 <7,7,7,7>, LHS + 2597159670U, // <7,7,7,1>: Cost 3 vext1 <7,7,7,7>, <1,0,3,2> + 2597160552U, // <7,7,7,2>: Cost 3 vext1 <7,7,7,7>, <2,2,2,2> + 2597161110U, // <7,7,7,3>: Cost 3 vext1 <7,7,7,7>, <3,0,1,2> + 1523420470U, // <7,7,7,4>: Cost 2 vext1 <7,7,7,7>, RHS + 2651002296U, // <7,7,7,5>: Cost 3 vext2 <5,5,7,7>, <7,5,5,7> + 2657637906U, // <7,7,7,6>: Cost 3 vext2 <6,6,7,7>, <7,6,6,7> + 363253046U, // <7,7,7,7>: Cost 1 vdup3 RHS + 363253046U, // <7,7,7,u>: Cost 1 vdup3 RHS + 1523417190U, // <7,7,u,0>: Cost 2 vext1 <7,7,7,7>, LHS + 1638471298U, // <7,7,u,1>: Cost 2 vext3 RHS, <7,u,1,2> + 2712213132U, // <7,7,u,2>: Cost 3 vext3 RHS, <7,u,2,3> + 2712213138U, // <7,7,u,3>: Cost 3 vext3 RHS, <7,u,3,0> + 1523420470U, // <7,7,u,4>: Cost 2 vext1 <7,7,7,7>, RHS + 1638471338U, // <7,7,u,5>: Cost 2 vext3 RHS, <7,u,5,6> + 1595840756U, // <7,7,u,6>: Cost 2 vext2 , + 363253046U, // <7,7,u,7>: Cost 1 vdup3 RHS + 363253046U, // <7,7,u,u>: Cost 1 vdup3 RHS + 1638318080U, // <7,u,0,0>: Cost 2 vext3 RHS, <0,0,0,0> + 1638323923U, // <7,u,0,1>: Cost 2 vext3 RHS, + 1662211804U, // <7,u,0,2>: Cost 2 vext3 RHS, + 1638323941U, // <7,u,0,3>: Cost 2 vext3 RHS, + 2712065773U, // <7,u,0,4>: Cost 3 vext3 RHS, + 1662359286U, // <7,u,0,5>: Cost 2 vext3 RHS, + 1662359296U, // <7,u,0,6>: Cost 2 vext3 RHS, + 2987150664U, // <7,u,0,7>: Cost 3 vzipr <5,6,7,0>, RHS + 1638323986U, // <7,u,0,u>: Cost 2 vext3 RHS, + 1517469798U, // <7,u,1,0>: Cost 2 vext1 <6,7,u,1>, LHS + 1638318900U, // <7,u,1,1>: Cost 2 vext3 RHS, <1,1,1,1> + 564582190U, // <7,u,1,2>: Cost 1 vext3 RHS, LHS + 1638324023U, // <7,u,1,3>: Cost 2 vext3 RHS, + 1517473078U, // <7,u,1,4>: Cost 2 vext1 <6,7,u,1>, RHS + 2693928777U, // <7,u,1,5>: Cost 3 vext3 <1,5,3,7>, + 1517474710U, // <7,u,1,6>: Cost 2 vext1 <6,7,u,1>, <6,7,u,1> + 1640462171U, // <7,u,1,7>: Cost 2 vext3 RHS, + 564582244U, // <7,u,1,u>: Cost 1 vext3 RHS, LHS + 1638318244U, // <7,u,2,0>: Cost 2 vext3 RHS, <0,2,0,2> + 2712065907U, // <7,u,2,1>: Cost 3 vext3 RHS, + 1638319720U, // <7,u,2,2>: Cost 2 vext3 RHS, <2,2,2,2> + 1638324101U, // <7,u,2,3>: Cost 2 vext3 RHS, + 1638318284U, // <7,u,2,4>: Cost 2 vext3 RHS, <0,2,4,6> + 2712065947U, // <7,u,2,5>: Cost 3 vext3 RHS, + 2700564387U, // <7,u,2,6>: Cost 3 vext3 <2,6,3,7>, + 1640314796U, // <7,u,2,7>: Cost 2 vext3 RHS, + 1638324146U, // <7,u,2,u>: Cost 2 vext3 RHS, + 1638324156U, // <7,u,3,0>: Cost 2 vext3 RHS, + 1638319064U, // <7,u,3,1>: Cost 2 vext3 RHS, <1,3,1,3> + 2700564435U, // <7,u,3,2>: Cost 3 vext3 <2,6,3,7>, + 1638320540U, // <7,u,3,3>: Cost 2 vext3 RHS, <3,3,3,3> + 1638324196U, // <7,u,3,4>: Cost 2 vext3 RHS, + 1638324207U, // <7,u,3,5>: Cost 2 vext3 RHS, + 2700564472U, // <7,u,3,6>: Cost 3 vext3 <2,6,3,7>, + 2695919610U, // <7,u,3,7>: Cost 3 vext3 <1,u,3,7>, + 1638324228U, // <7,u,3,u>: Cost 2 vext3 RHS, + 2712066061U, // <7,u,4,0>: Cost 3 vext3 RHS, + 1662212122U, // <7,u,4,1>: Cost 2 vext3 RHS, + 1662212132U, // <7,u,4,2>: Cost 2 vext3 RHS, + 2712066092U, // <7,u,4,3>: Cost 3 vext3 RHS, + 1638321360U, // <7,u,4,4>: Cost 2 vext3 RHS, <4,4,4,4> + 1638324287U, // <7,u,4,5>: Cost 2 vext3 RHS, + 1662359624U, // <7,u,4,6>: Cost 2 vext3 RHS, + 1640314961U, // <7,u,4,7>: Cost 2 vext3 RHS, + 1638324314U, // <7,u,4,u>: Cost 2 vext3 RHS, + 1517502566U, // <7,u,5,0>: Cost 2 vext1 <6,7,u,5>, LHS + 1574612693U, // <7,u,5,1>: Cost 2 vext2 <5,1,7,u>, <5,1,7,u> + 2712066162U, // <7,u,5,2>: Cost 3 vext3 RHS, + 1638324351U, // <7,u,5,3>: Cost 2 vext3 RHS, + 1576603592U, // <7,u,5,4>: Cost 2 vext2 <5,4,7,u>, <5,4,7,u> + 1577267225U, // <7,u,5,5>: Cost 2 vext2 <5,5,7,u>, <5,5,7,u> + 564582554U, // <7,u,5,6>: Cost 1 vext3 RHS, RHS + 1640462499U, // <7,u,5,7>: Cost 2 vext3 RHS, + 564582572U, // <7,u,5,u>: Cost 1 vext3 RHS, RHS + 2712066223U, // <7,u,6,0>: Cost 3 vext3 RHS, + 2712066238U, // <7,u,6,1>: Cost 3 vext3 RHS, + 1581249023U, // <7,u,6,2>: Cost 2 vext2 <6,2,7,u>, <6,2,7,u> + 1638324432U, // <7,u,6,3>: Cost 2 vext3 RHS, + 1638468980U, // <7,u,6,4>: Cost 2 vext3 RHS, <4,6,4,6> + 2712066274U, // <7,u,6,5>: Cost 3 vext3 RHS, + 1583903555U, // <7,u,6,6>: Cost 2 vext2 <6,6,7,u>, <6,6,7,u> + 1640315117U, // <7,u,6,7>: Cost 2 vext3 RHS, + 1638324477U, // <7,u,6,u>: Cost 2 vext3 RHS, + 1638471936U, // <7,u,7,0>: Cost 2 vext3 RHS, + 2692970763U, // <7,u,7,1>: Cost 3 vext3 <1,3,u,7>, + 2700933399U, // <7,u,7,2>: Cost 3 vext3 <2,6,u,7>, + 2573347601U, // <7,u,7,3>: Cost 3 vext1 <3,7,u,7>, <3,7,u,7> + 1638471976U, // <7,u,7,4>: Cost 2 vext3 RHS, + 1511551171U, // <7,u,7,5>: Cost 2 vext1 <5,7,u,7>, <5,7,u,7> + 2712213815U, // <7,u,7,6>: Cost 3 vext3 RHS, + 363253046U, // <7,u,7,7>: Cost 1 vdup3 RHS + 363253046U, // <7,u,7,u>: Cost 1 vdup3 RHS + 1638324561U, // <7,u,u,0>: Cost 2 vext3 RHS, + 1638324571U, // <7,u,u,1>: Cost 2 vext3 RHS, + 564582757U, // <7,u,u,2>: Cost 1 vext3 RHS, LHS + 1638324587U, // <7,u,u,3>: Cost 2 vext3 RHS, + 1638324601U, // <7,u,u,4>: Cost 2 vext3 RHS, + 1638324611U, // <7,u,u,5>: Cost 2 vext3 RHS, + 564582797U, // <7,u,u,6>: Cost 1 vext3 RHS, RHS + 363253046U, // <7,u,u,7>: Cost 1 vdup3 RHS + 564582811U, // <7,u,u,u>: Cost 1 vext3 RHS, LHS + 135053414U, // : Cost 1 vdup0 LHS + 1611489290U, // : Cost 2 vext3 LHS, <0,0,1,1> + 1611489300U, // : Cost 2 vext3 LHS, <0,0,2,2> + 2568054923U, // : Cost 3 vext1 <3,0,0,0>, <3,0,0,0> + 1481706806U, // : Cost 2 vext1 <0,u,0,0>, RHS + 2555449040U, // : Cost 3 vext1 <0,u,0,0>, <5,1,7,3> + 2591282078U, // : Cost 3 vext1 <6,u,0,0>, <6,u,0,0> + 2591945711U, // : Cost 3 vext1 <7,0,0,0>, <7,0,0,0> + 135053414U, // : Cost 1 vdup0 LHS + 1493655654U, // : Cost 2 vext1 <2,u,0,1>, LHS + 1860550758U, // : Cost 2 vzipl LHS, LHS + 537747563U, // : Cost 1 vext3 LHS, LHS + 2625135576U, // : Cost 3 vext2 <1,2,u,0>, <1,3,1,3> + 1493658934U, // : Cost 2 vext1 <2,u,0,1>, RHS + 2625135760U, // : Cost 3 vext2 <1,2,u,0>, <1,5,3,7> + 1517548447U, // : Cost 2 vext1 <6,u,0,1>, <6,u,0,1> + 2591290362U, // : Cost 3 vext1 <6,u,0,1>, <7,0,1,2> + 537747612U, // : Cost 1 vext3 LHS, LHS + 1611489444U, // : Cost 2 vext3 LHS, <0,2,0,2> + 2685231276U, // : Cost 3 vext3 LHS, <0,2,1,1> + 1994768486U, // : Cost 2 vtrnl LHS, LHS + 2685231294U, // : Cost 3 vext3 LHS, <0,2,3,1> + 1611489484U, // : Cost 2 vext3 LHS, <0,2,4,6> + 2712068310U, // : Cost 3 vext3 RHS, <0,2,5,7> + 2625136570U, // : Cost 3 vext2 <1,2,u,0>, <2,6,3,7> + 2591962097U, // : Cost 3 vext1 <7,0,0,2>, <7,0,0,2> + 1611489516U, // : Cost 2 vext3 LHS, <0,2,u,2> + 2954067968U, // : Cost 3 vzipr LHS, <0,0,0,0> + 2685231356U, // : Cost 3 vext3 LHS, <0,3,1,0> + 72589981U, // : Cost 1 vrev LHS + 2625137052U, // : Cost 3 vext2 <1,2,u,0>, <3,3,3,3> + 2625137154U, // : Cost 3 vext2 <1,2,u,0>, <3,4,5,6> + 2639071848U, // : Cost 3 vext2 <3,5,u,0>, <3,5,u,0> + 2639735481U, // : Cost 3 vext2 <3,6,u,0>, <3,6,u,0> + 2597279354U, // : Cost 3 vext1 <7,u,0,3>, <7,u,0,3> + 73032403U, // : Cost 1 vrev LHS + 2687074636U, // : Cost 3 vext3 <0,4,0,u>, <0,4,0,u> + 1611489618U, // : Cost 2 vext3 LHS, <0,4,1,5> + 1611489628U, // : Cost 2 vext3 LHS, <0,4,2,6> + 3629222038U, // : Cost 4 vext1 <0,u,0,4>, <3,0,1,2> + 2555481398U, // : Cost 3 vext1 <0,u,0,4>, RHS + 1551396150U, // : Cost 2 vext2 <1,2,u,0>, RHS + 2651680116U, // : Cost 3 vext2 <5,6,u,0>, <4,6,4,6> + 2646150600U, // : Cost 3 vext2 <4,7,5,0>, <4,7,5,0> + 1611932050U, // : Cost 2 vext3 LHS, <0,4,u,6> + 2561458278U, // : Cost 3 vext1 <1,u,0,5>, LHS + 1863532646U, // : Cost 2 vzipl RHS, LHS + 2712068526U, // : Cost 3 vext3 RHS, <0,5,2,7> + 2649689976U, // : Cost 3 vext2 <5,3,u,0>, <5,3,u,0> + 2220237489U, // : Cost 3 vrev <0,u,4,5> + 2651680772U, // : Cost 3 vext2 <5,6,u,0>, <5,5,5,5> + 1577939051U, // : Cost 2 vext2 <5,6,u,0>, <5,6,u,0> + 2830077238U, // : Cost 3 vuzpr <1,u,3,0>, RHS + 1579266317U, // : Cost 2 vext2 <5,u,u,0>, <5,u,u,0> + 2555494502U, // : Cost 3 vext1 <0,u,0,6>, LHS + 2712068598U, // : Cost 3 vext3 RHS, <0,6,1,7> + 1997750374U, // : Cost 2 vtrnl RHS, LHS + 2655662673U, // : Cost 3 vext2 <6,3,u,0>, <6,3,u,0> + 2555497782U, // : Cost 3 vext1 <0,u,0,6>, RHS + 2651681459U, // : Cost 3 vext2 <5,6,u,0>, <6,5,0,u> + 2651681592U, // : Cost 3 vext2 <5,6,u,0>, <6,6,6,6> + 2651681614U, // : Cost 3 vext2 <5,6,u,0>, <6,7,0,1> + 1997750428U, // : Cost 2 vtrnl RHS, LHS + 2567446630U, // : Cost 3 vext1 <2,u,0,7>, LHS + 2567447446U, // : Cost 3 vext1 <2,u,0,7>, <1,2,3,0> + 2567448641U, // : Cost 3 vext1 <2,u,0,7>, <2,u,0,7> + 2573421338U, // : Cost 3 vext1 <3,u,0,7>, <3,u,0,7> + 2567449910U, // : Cost 3 vext1 <2,u,0,7>, RHS + 2651682242U, // : Cost 3 vext2 <5,6,u,0>, <7,5,6,u> + 2591339429U, // : Cost 3 vext1 <6,u,0,7>, <6,u,0,7> + 2651682412U, // : Cost 3 vext2 <5,6,u,0>, <7,7,7,7> + 2567452462U, // : Cost 3 vext1 <2,u,0,7>, LHS + 135053414U, // : Cost 1 vdup0 LHS + 1611489938U, // : Cost 2 vext3 LHS, <0,u,1,1> + 537748125U, // : Cost 1 vext3 LHS, LHS + 2685674148U, // : Cost 3 vext3 LHS, <0,u,3,1> + 1611932338U, // : Cost 2 vext3 LHS, <0,u,4,6> + 1551399066U, // : Cost 2 vext2 <1,2,u,0>, RHS + 1517605798U, // : Cost 2 vext1 <6,u,0,u>, <6,u,0,u> + 2830077481U, // : Cost 3 vuzpr <1,u,3,0>, RHS + 537748179U, // : Cost 1 vext3 LHS, LHS + 1544101961U, // : Cost 2 vext2 <0,0,u,1>, <0,0,u,1> + 1558036582U, // : Cost 2 vext2 <2,3,u,1>, LHS + 2619171051U, // : Cost 3 vext2 <0,2,u,1>, <0,2,u,1> + 1611490038U, // : Cost 2 vext3 LHS, <1,0,3,2> + 2555522358U, // : Cost 3 vext1 <0,u,1,0>, RHS + 2712068871U, // : Cost 3 vext3 RHS, <1,0,5,1> + 2591355815U, // : Cost 3 vext1 <6,u,1,0>, <6,u,1,0> + 2597328512U, // : Cost 3 vext1 <7,u,1,0>, <7,u,1,0> + 1611490083U, // : Cost 2 vext3 LHS, <1,0,u,2> + 1481785446U, // : Cost 2 vext1 <0,u,1,1>, LHS + 202162278U, // : Cost 1 vdup1 LHS + 2555528808U, // : Cost 3 vext1 <0,u,1,1>, <2,2,2,2> + 1611490120U, // : Cost 2 vext3 LHS, <1,1,3,3> + 1481788726U, // : Cost 2 vext1 <0,u,1,1>, RHS + 2689876828U, // : Cost 3 vext3 LHS, <1,1,5,5> + 2591364008U, // : Cost 3 vext1 <6,u,1,1>, <6,u,1,1> + 2592691274U, // : Cost 3 vext1 <7,1,1,1>, <7,1,1,1> + 202162278U, // : Cost 1 vdup1 LHS + 1499709542U, // : Cost 2 vext1 <3,u,1,2>, LHS + 2689876871U, // : Cost 3 vext3 LHS, <1,2,1,3> + 2631116445U, // : Cost 3 vext2 <2,2,u,1>, <2,2,u,1> + 835584U, // : Cost 0 copy LHS + 1499712822U, // : Cost 2 vext1 <3,u,1,2>, RHS + 2689876907U, // : Cost 3 vext3 LHS, <1,2,5,3> + 2631780282U, // : Cost 3 vext2 <2,3,u,1>, <2,6,3,7> + 1523603074U, // : Cost 2 vext1 <7,u,1,2>, <7,u,1,2> + 835584U, // : Cost 0 copy LHS + 1487773798U, // : Cost 2 vext1 <1,u,1,3>, LHS + 1611490264U, // : Cost 2 vext3 LHS, <1,3,1,3> + 2685232094U, // : Cost 3 vext3 LHS, <1,3,2,0> + 2018746470U, // : Cost 2 vtrnr LHS, LHS + 1487777078U, // : Cost 2 vext1 <1,u,1,3>, RHS + 1611490304U, // : Cost 2 vext3 LHS, <1,3,5,7> + 2685674505U, // : Cost 3 vext3 LHS, <1,3,6,7> + 2640407307U, // : Cost 3 vext2 <3,7,u,1>, <3,7,u,1> + 1611490327U, // : Cost 2 vext3 LHS, <1,3,u,3> + 1567992749U, // : Cost 2 vext2 <4,0,u,1>, <4,0,u,1> + 2693121070U, // : Cost 3 vext3 <1,4,1,u>, <1,4,1,u> + 2693194807U, // : Cost 3 vext3 <1,4,2,u>, <1,4,2,u> + 1152386432U, // : Cost 2 vrev <1,u,3,4> + 2555555126U, // : Cost 3 vext1 <0,u,1,4>, RHS + 1558039862U, // : Cost 2 vext2 <2,3,u,1>, RHS + 2645716371U, // : Cost 3 vext2 <4,6,u,1>, <4,6,u,1> + 2597361284U, // : Cost 3 vext1 <7,u,1,4>, <7,u,1,4> + 1152755117U, // : Cost 2 vrev <1,u,u,4> + 1481818214U, // : Cost 2 vext1 <0,u,1,5>, LHS + 2555560694U, // : Cost 3 vext1 <0,u,1,5>, <1,0,3,2> + 2555561576U, // : Cost 3 vext1 <0,u,1,5>, <2,2,2,2> + 1611490448U, // : Cost 2 vext3 LHS, <1,5,3,7> + 1481821494U, // : Cost 2 vext1 <0,u,1,5>, RHS + 2651025435U, // : Cost 3 vext2 <5,5,u,1>, <5,5,u,1> + 2651689068U, // : Cost 3 vext2 <5,6,u,1>, <5,6,u,1> + 2823966006U, // : Cost 3 vuzpr <0,u,1,1>, RHS + 1611932861U, // : Cost 2 vext3 LHS, <1,5,u,7> + 2555568230U, // : Cost 3 vext1 <0,u,1,6>, LHS + 2689877199U, // : Cost 3 vext3 LHS, <1,6,1,7> + 2712069336U, // : Cost 3 vext3 RHS, <1,6,2,7> + 2685232353U, // : Cost 3 vext3 LHS, <1,6,3,7> + 2555571510U, // : Cost 3 vext1 <0,u,1,6>, RHS + 2689877235U, // : Cost 3 vext3 LHS, <1,6,5,7> + 2657661765U, // : Cost 3 vext2 <6,6,u,1>, <6,6,u,1> + 1584583574U, // : Cost 2 vext2 <6,7,u,1>, <6,7,u,1> + 1585247207U, // : Cost 2 vext2 <6,u,u,1>, <6,u,u,1> + 2561548390U, // : Cost 3 vext1 <1,u,1,7>, LHS + 2561549681U, // : Cost 3 vext1 <1,u,1,7>, <1,u,1,7> + 2573493926U, // : Cost 3 vext1 <3,u,1,7>, <2,3,0,1> + 2042962022U, // : Cost 2 vtrnr RHS, LHS + 2561551670U, // : Cost 3 vext1 <1,u,1,7>, RHS + 2226300309U, // : Cost 3 vrev <1,u,5,7> + 2658325990U, // : Cost 3 vext2 <6,7,u,1>, <7,6,1,u> + 2658326124U, // : Cost 3 vext2 <6,7,u,1>, <7,7,7,7> + 2042962027U, // : Cost 2 vtrnr RHS, LHS + 1481842790U, // : Cost 2 vext1 <0,u,1,u>, LHS + 202162278U, // : Cost 1 vdup1 LHS + 2685674867U, // : Cost 3 vext3 LHS, <1,u,2,0> + 835584U, // : Cost 0 copy LHS + 1481846070U, // : Cost 2 vext1 <0,u,1,u>, RHS + 1611933077U, // : Cost 2 vext3 LHS, <1,u,5,7> + 2685674910U, // : Cost 3 vext3 LHS, <1,u,6,7> + 1523652232U, // : Cost 2 vext1 <7,u,1,u>, <7,u,1,u> + 835584U, // : Cost 0 copy LHS + 1544110154U, // : Cost 2 vext2 <0,0,u,2>, <0,0,u,2> + 1545437286U, // : Cost 2 vext2 <0,2,u,2>, LHS + 1545437420U, // : Cost 2 vext2 <0,2,u,2>, <0,2,u,2> + 2685232589U, // : Cost 3 vext3 LHS, <2,0,3,0> + 2619179346U, // : Cost 3 vext2 <0,2,u,2>, <0,4,1,5> + 2712069606U, // : Cost 3 vext3 RHS, <2,0,5,7> + 2689877484U, // : Cost 3 vext3 LHS, <2,0,6,4> + 2659656273U, // : Cost 3 vext2 <7,0,u,2>, <0,7,2,u> + 1545437853U, // : Cost 2 vext2 <0,2,u,2>, LHS + 1550082851U, // : Cost 2 vext2 <1,0,u,2>, <1,0,u,2> + 2619179828U, // : Cost 3 vext2 <0,2,u,2>, <1,1,1,1> + 2619179926U, // : Cost 3 vext2 <0,2,u,2>, <1,2,3,0> + 2685232671U, // : Cost 3 vext3 LHS, <2,1,3,1> + 2555604278U, // : Cost 3 vext1 <0,u,2,1>, RHS + 2619180176U, // : Cost 3 vext2 <0,2,u,2>, <1,5,3,7> + 2689877564U, // : Cost 3 vext3 LHS, <2,1,6,3> + 2602718850U, // : Cost 3 vext1 , <7,u,1,2> + 1158703235U, // : Cost 2 vrev <2,u,u,1> + 1481867366U, // : Cost 2 vext1 <0,u,2,2>, LHS + 2555609846U, // : Cost 3 vext1 <0,u,2,2>, <1,0,3,2> + 269271142U, // : Cost 1 vdup2 LHS + 1611490930U, // : Cost 2 vext3 LHS, <2,2,3,3> + 1481870646U, // : Cost 2 vext1 <0,u,2,2>, RHS + 2689877640U, // : Cost 3 vext3 LHS, <2,2,5,7> + 2619180986U, // : Cost 3 vext2 <0,2,u,2>, <2,6,3,7> + 2593436837U, // : Cost 3 vext1 <7,2,2,2>, <7,2,2,2> + 269271142U, // : Cost 1 vdup2 LHS + 408134301U, // : Cost 1 vext1 LHS, LHS + 1481876214U, // : Cost 2 vext1 LHS, <1,0,3,2> + 1481877096U, // : Cost 2 vext1 LHS, <2,2,2,2> + 1880326246U, // : Cost 2 vzipr LHS, LHS + 408137014U, // : Cost 1 vext1 LHS, RHS + 1529654992U, // : Cost 2 vext1 LHS, <5,1,7,3> + 1529655802U, // : Cost 2 vext1 LHS, <6,2,7,3> + 1529656314U, // : Cost 2 vext1 LHS, <7,0,1,2> + 408139566U, // : Cost 1 vext1 LHS, LHS + 1567853468U, // : Cost 2 vext2 <4,0,6,2>, <4,0,6,2> + 2561598362U, // : Cost 3 vext1 <1,u,2,4>, <1,2,3,4> + 2555627214U, // : Cost 3 vext1 <0,u,2,4>, <2,3,4,5> + 2685232918U, // : Cost 3 vext3 LHS, <2,4,3,5> + 2555628854U, // : Cost 3 vext1 <0,u,2,4>, RHS + 1545440566U, // : Cost 2 vext2 <0,2,u,2>, RHS + 1571982740U, // : Cost 2 vext2 <4,6,u,2>, <4,6,u,2> + 2592125957U, // : Cost 3 vext1 <7,0,2,4>, <7,0,2,4> + 1545440809U, // : Cost 2 vext2 <0,2,u,2>, RHS + 2555633766U, // : Cost 3 vext1 <0,u,2,5>, LHS + 2561606550U, // : Cost 3 vext1 <1,u,2,5>, <1,2,3,0> + 2689877856U, // : Cost 3 vext3 LHS, <2,5,2,7> + 2685233000U, // : Cost 3 vext3 LHS, <2,5,3,6> + 1158441059U, // : Cost 2 vrev <2,u,4,5> + 2645725188U, // : Cost 3 vext2 <4,6,u,2>, <5,5,5,5> + 2689877892U, // : Cost 3 vext3 LHS, <2,5,6,7> + 2823900470U, // : Cost 3 vuzpr <0,u,0,2>, RHS + 1158736007U, // : Cost 2 vrev <2,u,u,5> + 1481900134U, // : Cost 2 vext1 <0,u,2,6>, LHS + 2555642614U, // : Cost 3 vext1 <0,u,2,6>, <1,0,3,2> + 2555643496U, // : Cost 3 vext1 <0,u,2,6>, <2,2,2,2> + 1611491258U, // : Cost 2 vext3 LHS, <2,6,3,7> + 1481903414U, // : Cost 2 vext1 <0,u,2,6>, RHS + 2689877964U, // : Cost 3 vext3 LHS, <2,6,5,7> + 2689877973U, // : Cost 3 vext3 LHS, <2,6,6,7> + 2645726030U, // : Cost 3 vext2 <4,6,u,2>, <6,7,0,1> + 1611933671U, // : Cost 2 vext3 LHS, <2,6,u,7> + 1585919033U, // : Cost 2 vext2 <7,0,u,2>, <7,0,u,2> + 2573566710U, // : Cost 3 vext1 <3,u,2,7>, <1,0,3,2> + 2567596115U, // : Cost 3 vext1 <2,u,2,7>, <2,u,2,7> + 1906901094U, // : Cost 2 vzipr RHS, LHS + 2555653430U, // : Cost 3 vext1 <0,u,2,7>, RHS + 2800080230U, // : Cost 3 vuzpl LHS, <7,4,5,6> + 2980643164U, // : Cost 3 vzipr RHS, <0,4,2,6> + 2645726828U, // : Cost 3 vext2 <4,6,u,2>, <7,7,7,7> + 1906901099U, // : Cost 2 vzipr RHS, LHS + 408175266U, // : Cost 1 vext1 LHS, LHS + 1545443118U, // : Cost 2 vext2 <0,2,u,2>, LHS + 269271142U, // : Cost 1 vdup2 LHS + 1611491416U, // : Cost 2 vext3 LHS, <2,u,3,3> + 408177974U, // : Cost 1 vext1 LHS, RHS + 1545443482U, // : Cost 2 vext2 <0,2,u,2>, RHS + 1726339226U, // : Cost 2 vuzpl LHS, RHS + 1529697274U, // : Cost 2 vext1 LHS, <7,0,1,2> + 408180526U, // : Cost 1 vext1 LHS, LHS + 1544781824U, // : Cost 2 vext2 LHS, <0,0,0,0> + 471040156U, // : Cost 1 vext2 LHS, LHS + 1544781988U, // : Cost 2 vext2 LHS, <0,2,0,2> + 2618523900U, // : Cost 3 vext2 LHS, <0,3,1,0> + 1544782162U, // : Cost 2 vext2 LHS, <0,4,1,5> + 2238188352U, // : Cost 3 vrev <3,u,5,0> + 2623169023U, // : Cost 3 vext2 LHS, <0,6,2,7> + 2238335826U, // : Cost 3 vrev <3,u,7,0> + 471040669U, // : Cost 1 vext2 LHS, LHS + 1544782582U, // : Cost 2 vext2 LHS, <1,0,3,2> + 1544782644U, // : Cost 2 vext2 LHS, <1,1,1,1> + 1544782742U, // : Cost 2 vext2 LHS, <1,2,3,0> + 1544782808U, // : Cost 2 vext2 LHS, <1,3,1,3> + 2618524733U, // : Cost 3 vext2 LHS, <1,4,3,5> + 1544782992U, // : Cost 2 vext2 LHS, <1,5,3,7> + 2618524897U, // : Cost 3 vext2 LHS, <1,6,3,7> + 2703517987U, // : Cost 3 vext3 <3,1,7,u>, <3,1,7,u> + 1544783213U, // : Cost 2 vext2 LHS, <1,u,1,3> + 1529716838U, // : Cost 2 vext1 , LHS + 1164167966U, // : Cost 2 vrev <3,u,1,2> + 1544783464U, // : Cost 2 vext2 LHS, <2,2,2,2> + 1544783526U, // : Cost 2 vext2 LHS, <2,3,0,1> + 1529720118U, // : Cost 2 vext1 , RHS + 2618525544U, // : Cost 3 vext2 LHS, <2,5,3,6> + 1544783802U, // : Cost 2 vext2 LHS, <2,6,3,7> + 2704181620U, // : Cost 3 vext3 <3,2,7,u>, <3,2,7,u> + 1544783931U, // : Cost 2 vext2 LHS, <2,u,0,1> + 1544784022U, // : Cost 2 vext2 LHS, <3,0,1,2> + 1487922559U, // : Cost 2 vext1 <1,u,3,3>, <1,u,3,3> + 1493895256U, // : Cost 2 vext1 <2,u,3,3>, <2,u,3,3> + 336380006U, // : Cost 1 vdup3 LHS + 1544784386U, // : Cost 2 vext2 LHS, <3,4,5,6> + 2824054478U, // : Cost 3 vuzpr LHS, <2,3,4,5> + 2238286668U, // : Cost 3 vrev <3,u,6,3> + 2954069136U, // : Cost 3 vzipr LHS, <1,5,3,7> + 336380006U, // : Cost 1 vdup3 LHS + 1487929446U, // : Cost 2 vext1 <1,u,3,4>, LHS + 1487930752U, // : Cost 2 vext1 <1,u,3,4>, <1,u,3,4> + 2623171644U, // : Cost 3 vext2 LHS, <4,2,6,0> + 2561673366U, // : Cost 3 vext1 <1,u,3,4>, <3,0,1,2> + 1487932726U, // : Cost 2 vext1 <1,u,3,4>, RHS + 471043382U, // : Cost 1 vext2 LHS, RHS + 1592561012U, // : Cost 2 vext2 LHS, <4,6,4,6> + 2238368598U, // : Cost 3 vrev <3,u,7,4> + 471043625U, // : Cost 1 vext2 LHS, RHS + 2555707494U, // : Cost 3 vext1 <0,u,3,5>, LHS + 1574645465U, // : Cost 2 vext2 <5,1,u,3>, <5,1,u,3> + 2567653106U, // : Cost 3 vext1 <2,u,3,5>, <2,3,u,5> + 2555709954U, // : Cost 3 vext1 <0,u,3,5>, <3,4,5,6> + 1592561606U, // : Cost 2 vext2 LHS, <5,4,7,6> + 1592561668U, // : Cost 2 vext2 LHS, <5,5,5,5> + 1592561762U, // : Cost 2 vext2 LHS, <5,6,7,0> + 1750314294U, // : Cost 2 vuzpr LHS, RHS + 1750314295U, // : Cost 2 vuzpr LHS, RHS + 2623172897U, // : Cost 3 vext2 LHS, <6,0,1,2> + 2561688962U, // : Cost 3 vext1 <1,u,3,6>, <1,u,3,6> + 1581281795U, // : Cost 2 vext2 <6,2,u,3>, <6,2,u,3> + 2706541204U, // : Cost 3 vext3 <3,6,3,u>, <3,6,3,u> + 2623173261U, // : Cost 3 vext2 LHS, <6,4,5,6> + 1164495686U, // : Cost 2 vrev <3,u,5,6> + 1592562488U, // : Cost 2 vext2 LHS, <6,6,6,6> + 1592562510U, // : Cost 2 vext2 LHS, <6,7,0,1> + 1164716897U, // : Cost 2 vrev <3,u,u,6> + 1487954022U, // : Cost 2 vext1 <1,u,3,7>, LHS + 1487955331U, // : Cost 2 vext1 <1,u,3,7>, <1,u,3,7> + 1493928028U, // : Cost 2 vext1 <2,u,3,7>, <2,u,3,7> + 2561697942U, // : Cost 3 vext1 <1,u,3,7>, <3,0,1,2> + 1487957302U, // : Cost 2 vext1 <1,u,3,7>, RHS + 2707352311U, // : Cost 3 vext3 <3,7,5,u>, <3,7,5,u> + 2655024623U, // : Cost 3 vext2 <6,2,u,3>, <7,6,2,u> + 1592563308U, // : Cost 2 vext2 LHS, <7,7,7,7> + 1487959854U, // : Cost 2 vext1 <1,u,3,7>, LHS + 1544787667U, // : Cost 2 vext2 LHS, + 471045934U, // : Cost 1 vext2 LHS, LHS + 1549432709U, // : Cost 2 vext2 LHS, + 336380006U, // : Cost 1 vdup3 LHS + 1544788031U, // : Cost 2 vext2 LHS, + 471046298U, // : Cost 1 vext2 LHS, RHS + 1549433040U, // : Cost 2 vext2 LHS, + 1750314537U, // : Cost 2 vuzpr LHS, RHS + 471046501U, // : Cost 1 vext2 LHS, LHS + 2625167360U, // : Cost 3 vext2 <1,2,u,4>, <0,0,0,0> + 1551425638U, // : Cost 2 vext2 <1,2,u,4>, LHS + 2619195630U, // : Cost 3 vext2 <0,2,u,4>, <0,2,u,4> + 2619343104U, // : Cost 3 vext2 <0,3,1,4>, <0,3,1,4> + 2625167698U, // : Cost 3 vext2 <1,2,u,4>, <0,4,1,5> + 1638329234U, // : Cost 2 vext3 RHS, <4,0,5,1> + 1638329244U, // : Cost 2 vext3 RHS, <4,0,6,2> + 3787803556U, // : Cost 4 vext3 RHS, <4,0,7,1> + 1551426205U, // : Cost 2 vext2 <1,2,u,4>, LHS + 2555748454U, // : Cost 3 vext1 <0,u,4,1>, LHS + 2625168180U, // : Cost 3 vext2 <1,2,u,4>, <1,1,1,1> + 1551426503U, // : Cost 2 vext2 <1,2,u,4>, <1,2,u,4> + 2625168344U, // : Cost 3 vext2 <1,2,u,4>, <1,3,1,3> + 2555751734U, // : Cost 3 vext1 <0,u,4,1>, RHS + 1860554038U, // : Cost 2 vzipl LHS, RHS + 2689879022U, // : Cost 3 vext3 LHS, <4,1,6,3> + 2592248852U, // : Cost 3 vext1 <7,0,4,1>, <7,0,4,1> + 1555408301U, // : Cost 2 vext2 <1,u,u,4>, <1,u,u,4> + 2555756646U, // : Cost 3 vext1 <0,u,4,2>, LHS + 2625168943U, // : Cost 3 vext2 <1,2,u,4>, <2,1,4,u> + 2625169000U, // : Cost 3 vext2 <1,2,u,4>, <2,2,2,2> + 2619197134U, // : Cost 3 vext2 <0,2,u,4>, <2,3,4,5> + 2555759926U, // : Cost 3 vext1 <0,u,4,2>, RHS + 2712071222U, // : Cost 3 vext3 RHS, <4,2,5,3> + 1994771766U, // : Cost 2 vtrnl LHS, RHS + 2592257045U, // : Cost 3 vext1 <7,0,4,2>, <7,0,4,2> + 1994771784U, // : Cost 2 vtrnl LHS, RHS + 2625169558U, // : Cost 3 vext2 <1,2,u,4>, <3,0,1,2> + 2567709594U, // : Cost 3 vext1 <2,u,4,3>, <1,2,3,4> + 2567710817U, // : Cost 3 vext1 <2,u,4,3>, <2,u,4,3> + 2625169820U, // : Cost 3 vext2 <1,2,u,4>, <3,3,3,3> + 2625169922U, // : Cost 3 vext2 <1,2,u,4>, <3,4,5,6> + 2954069710U, // : Cost 3 vzipr LHS, <2,3,4,5> + 2954068172U, // : Cost 3 vzipr LHS, <0,2,4,6> + 3903849472U, // : Cost 4 vuzpr <1,u,3,4>, <1,3,5,7> + 2954068174U, // : Cost 3 vzipr LHS, <0,2,4,u> + 1505919078U, // : Cost 2 vext1 <4,u,4,4>, LHS + 2567717831U, // : Cost 3 vext1 <2,u,4,4>, <1,2,u,4> + 2567719010U, // : Cost 3 vext1 <2,u,4,4>, <2,u,4,4> + 2570373542U, // : Cost 3 vext1 <3,3,4,4>, <3,3,4,4> + 161926454U, // : Cost 1 vdup0 RHS + 1551428918U, // : Cost 2 vext2 <1,2,u,4>, RHS + 1638329572U, // : Cost 2 vext3 RHS, <4,4,6,6> + 2594927963U, // : Cost 3 vext1 <7,4,4,4>, <7,4,4,4> + 161926454U, // : Cost 1 vdup0 RHS + 1493983334U, // : Cost 2 vext1 <2,u,4,5>, LHS + 2689879301U, // : Cost 3 vext3 LHS, <4,5,1,3> + 1493985379U, // : Cost 2 vext1 <2,u,4,5>, <2,u,4,5> + 2567727254U, // : Cost 3 vext1 <2,u,4,5>, <3,0,1,2> + 1493986614U, // : Cost 2 vext1 <2,u,4,5>, RHS + 1863535926U, // : Cost 2 vzipl RHS, RHS + 537750838U, // : Cost 1 vext3 LHS, RHS + 2830110006U, // : Cost 3 vuzpr <1,u,3,4>, RHS + 537750856U, // : Cost 1 vext3 LHS, RHS + 1482047590U, // : Cost 2 vext1 <0,u,4,6>, LHS + 2555790070U, // : Cost 3 vext1 <0,u,4,6>, <1,0,3,2> + 2555790952U, // : Cost 3 vext1 <0,u,4,6>, <2,2,2,2> + 2555791510U, // : Cost 3 vext1 <0,u,4,6>, <3,0,1,2> + 1482050870U, // : Cost 2 vext1 <0,u,4,6>, RHS + 2689879422U, // : Cost 3 vext3 LHS, <4,6,5,7> + 1997753654U, // : Cost 2 vtrnl RHS, RHS + 2712071562U, // : Cost 3 vext3 RHS, <4,6,7,1> + 1482053422U, // : Cost 2 vext1 <0,u,4,6>, LHS + 2567741542U, // : Cost 3 vext1 <2,u,4,7>, LHS + 2567742362U, // : Cost 3 vext1 <2,u,4,7>, <1,2,3,4> + 2567743589U, // : Cost 3 vext1 <2,u,4,7>, <2,u,4,7> + 2573716286U, // : Cost 3 vext1 <3,u,4,7>, <3,u,4,7> + 2567744822U, // : Cost 3 vext1 <2,u,4,7>, RHS + 2712071624U, // : Cost 3 vext3 RHS, <4,7,5,0> + 96808489U, // : Cost 1 vrev RHS + 2651715180U, // : Cost 3 vext2 <5,6,u,4>, <7,7,7,7> + 96955963U, // : Cost 1 vrev RHS + 1482063974U, // : Cost 2 vext1 <0,u,4,u>, LHS + 1551431470U, // : Cost 2 vext2 <1,2,u,4>, LHS + 1494009958U, // : Cost 2 vext1 <2,u,4,u>, <2,u,4,u> + 2555807894U, // : Cost 3 vext1 <0,u,4,u>, <3,0,1,2> + 161926454U, // : Cost 1 vdup0 RHS + 1551431834U, // : Cost 2 vext2 <1,2,u,4>, RHS + 537751081U, // : Cost 1 vext3 LHS, RHS + 2830110249U, // : Cost 3 vuzpr <1,u,3,4>, RHS + 537751099U, // : Cost 1 vext3 LHS, RHS + 2631811072U, // : Cost 3 vext2 <2,3,u,5>, <0,0,0,0> + 1558069350U, // : Cost 2 vext2 <2,3,u,5>, LHS + 2619203823U, // : Cost 3 vext2 <0,2,u,5>, <0,2,u,5> + 2619867456U, // : Cost 3 vext2 <0,3,u,5>, <0,3,u,5> + 1546273106U, // : Cost 2 vext2 <0,4,1,5>, <0,4,1,5> + 2733010539U, // : Cost 3 vext3 LHS, <5,0,5,1> + 2597622682U, // : Cost 3 vext1 <7,u,5,0>, <6,7,u,5> + 1176539396U, // : Cost 2 vrev <5,u,7,0> + 1558069917U, // : Cost 2 vext2 <2,3,u,5>, LHS + 1505968230U, // : Cost 2 vext1 <4,u,5,1>, LHS + 2624512887U, // : Cost 3 vext2 <1,1,u,5>, <1,1,u,5> + 2631811990U, // : Cost 3 vext2 <2,3,u,5>, <1,2,3,0> + 2618541056U, // : Cost 3 vext2 <0,1,u,5>, <1,3,5,7> + 1505971510U, // : Cost 2 vext1 <4,u,5,1>, RHS + 2627167419U, // : Cost 3 vext2 <1,5,u,5>, <1,5,u,5> + 2579714554U, // : Cost 3 vext1 <4,u,5,1>, <6,2,7,3> + 1638330064U, // : Cost 2 vext3 RHS, <5,1,7,3> + 1638477529U, // : Cost 2 vext3 RHS, <5,1,u,3> + 2561802342U, // : Cost 3 vext1 <1,u,5,2>, LHS + 2561803264U, // : Cost 3 vext1 <1,u,5,2>, <1,3,5,7> + 2631149217U, // : Cost 3 vext2 <2,2,u,5>, <2,2,u,5> + 1558071026U, // : Cost 2 vext2 <2,3,u,5>, <2,3,u,5> + 2561805622U, // : Cost 3 vext1 <1,u,5,2>, RHS + 2714062607U, // : Cost 3 vext3 RHS, <5,2,5,3> + 2631813050U, // : Cost 3 vext2 <2,3,u,5>, <2,6,3,7> + 3092335926U, // : Cost 3 vtrnr <0,u,0,2>, RHS + 1561389191U, // : Cost 2 vext2 <2,u,u,5>, <2,u,u,5> + 2561810534U, // : Cost 3 vext1 <1,u,5,3>, LHS + 2561811857U, // : Cost 3 vext1 <1,u,5,3>, <1,u,5,3> + 2631813474U, // : Cost 3 vext2 <2,3,u,5>, <3,2,5,u> + 2631813532U, // : Cost 3 vext2 <2,3,u,5>, <3,3,3,3> + 2619869698U, // : Cost 3 vext2 <0,3,u,5>, <3,4,5,6> + 3001847002U, // : Cost 3 vzipr LHS, <4,4,5,5> + 2954070530U, // : Cost 3 vzipr LHS, <3,4,5,6> + 2018749750U, // : Cost 2 vtrnr LHS, RHS + 2018749751U, // : Cost 2 vtrnr LHS, RHS + 2573762662U, // : Cost 3 vext1 <3,u,5,4>, LHS + 2620017634U, // : Cost 3 vext2 <0,4,1,5>, <4,1,5,0> + 2573764338U, // : Cost 3 vext1 <3,u,5,4>, <2,3,u,5> + 2573765444U, // : Cost 3 vext1 <3,u,5,4>, <3,u,5,4> + 1570680053U, // : Cost 2 vext2 <4,4,u,5>, <4,4,u,5> + 1558072630U, // : Cost 2 vext2 <2,3,u,5>, RHS + 2645749143U, // : Cost 3 vext2 <4,6,u,5>, <4,6,u,5> + 1638330310U, // : Cost 2 vext3 RHS, <5,4,7,6> + 1558072873U, // : Cost 2 vext2 <2,3,u,5>, RHS + 1506000998U, // : Cost 2 vext1 <4,u,5,5>, LHS + 2561827984U, // : Cost 3 vext1 <1,u,5,5>, <1,5,3,7> + 2579744360U, // : Cost 3 vext1 <4,u,5,5>, <2,2,2,2> + 2579744918U, // : Cost 3 vext1 <4,u,5,5>, <3,0,1,2> + 1506004278U, // : Cost 2 vext1 <4,u,5,5>, RHS + 229035318U, // : Cost 1 vdup1 RHS + 2712072206U, // : Cost 3 vext3 RHS, <5,5,6,6> + 1638330392U, // : Cost 2 vext3 RHS, <5,5,7,7> + 229035318U, // : Cost 1 vdup1 RHS + 1500037222U, // : Cost 2 vext1 <3,u,5,6>, LHS + 2561836436U, // : Cost 3 vext1 <1,u,5,6>, <1,u,5,6> + 2567809133U, // : Cost 3 vext1 <2,u,5,6>, <2,u,5,6> + 1500040006U, // : Cost 2 vext1 <3,u,5,6>, <3,u,5,6> + 1500040502U, // : Cost 2 vext1 <3,u,5,6>, RHS + 2714062935U, // : Cost 3 vext3 RHS, <5,6,5,7> + 2712072288U, // : Cost 3 vext3 RHS, <5,6,6,7> + 27705344U, // : Cost 0 copy RHS + 27705344U, // : Cost 0 copy RHS + 1488101478U, // : Cost 2 vext1 <1,u,5,7>, LHS + 1488102805U, // : Cost 2 vext1 <1,u,5,7>, <1,u,5,7> + 2561844840U, // : Cost 3 vext1 <1,u,5,7>, <2,2,2,2> + 2561845398U, // : Cost 3 vext1 <1,u,5,7>, <3,0,1,2> + 1488104758U, // : Cost 2 vext1 <1,u,5,7>, RHS + 1638330536U, // : Cost 2 vext3 RHS, <5,7,5,7> + 2712072362U, // : Cost 3 vext3 RHS, <5,7,6,0> + 2042965302U, // : Cost 2 vtrnr RHS, RHS + 1488107310U, // : Cost 2 vext1 <1,u,5,7>, LHS + 1488109670U, // : Cost 2 vext1 <1,u,5,u>, LHS + 1488110998U, // : Cost 2 vext1 <1,u,5,u>, <1,u,5,u> + 2561853032U, // : Cost 3 vext1 <1,u,5,u>, <2,2,2,2> + 1500056392U, // : Cost 2 vext1 <3,u,5,u>, <3,u,5,u> + 1488112950U, // : Cost 2 vext1 <1,u,5,u>, RHS + 229035318U, // : Cost 1 vdup1 RHS + 2954111490U, // : Cost 3 vzipr LHS, <3,4,5,6> + 27705344U, // : Cost 0 copy RHS + 27705344U, // : Cost 0 copy RHS + 2619211776U, // : Cost 3 vext2 <0,2,u,6>, <0,0,0,0> + 1545470054U, // : Cost 2 vext2 <0,2,u,6>, LHS + 1545470192U, // : Cost 2 vext2 <0,2,u,6>, <0,2,u,6> + 2255958969U, // : Cost 3 vrev <6,u,3,0> + 1546797458U, // : Cost 2 vext2 <0,4,u,6>, <0,4,u,6> + 2720624971U, // : Cost 3 vext3 <6,0,5,u>, <6,0,5,u> + 2256180180U, // : Cost 3 vrev <6,u,6,0> + 2960682294U, // : Cost 3 vzipr <1,2,u,0>, RHS + 1545470621U, // : Cost 2 vext2 <0,2,u,6>, LHS + 1182004127U, // : Cost 2 vrev <6,u,0,1> + 2619212596U, // : Cost 3 vext2 <0,2,u,6>, <1,1,1,1> + 2619212694U, // : Cost 3 vext2 <0,2,u,6>, <1,2,3,0> + 2619212760U, // : Cost 3 vext2 <0,2,u,6>, <1,3,1,3> + 2626511979U, // : Cost 3 vext2 <1,4,u,6>, <1,4,u,6> + 2619212944U, // : Cost 3 vext2 <0,2,u,6>, <1,5,3,7> + 2714063264U, // : Cost 3 vext3 RHS, <6,1,6,3> + 2967326006U, // : Cost 3 vzipr <2,3,u,1>, RHS + 1182594023U, // : Cost 2 vrev <6,u,u,1> + 1506050150U, // : Cost 2 vext1 <4,u,6,2>, LHS + 2579792630U, // : Cost 3 vext1 <4,u,6,2>, <1,0,3,2> + 2619213416U, // : Cost 3 vext2 <0,2,u,6>, <2,2,2,2> + 2619213478U, // : Cost 3 vext2 <0,2,u,6>, <2,3,0,1> + 1506053430U, // : Cost 2 vext1 <4,u,6,2>, RHS + 2633148309U, // : Cost 3 vext2 <2,5,u,6>, <2,5,u,6> + 2619213754U, // : Cost 3 vext2 <0,2,u,6>, <2,6,3,7> + 1638330874U, // : Cost 2 vext3 RHS, <6,2,7,3> + 1638478339U, // : Cost 2 vext3 RHS, <6,2,u,3> + 2619213974U, // : Cost 3 vext2 <0,2,u,6>, <3,0,1,2> + 2255836074U, // : Cost 3 vrev <6,u,1,3> + 2255909811U, // : Cost 3 vrev <6,u,2,3> + 2619214236U, // : Cost 3 vext2 <0,2,u,6>, <3,3,3,3> + 1564715549U, // : Cost 2 vext2 <3,4,u,6>, <3,4,u,6> + 2639121006U, // : Cost 3 vext2 <3,5,u,6>, <3,5,u,6> + 3001847012U, // : Cost 3 vzipr LHS, <4,4,6,6> + 1880329526U, // : Cost 2 vzipr LHS, RHS + 1880329527U, // : Cost 2 vzipr LHS, RHS + 2567864422U, // : Cost 3 vext1 <2,u,6,4>, LHS + 2733011558U, // : Cost 3 vext3 LHS, <6,4,1,3> + 2567866484U, // : Cost 3 vext1 <2,u,6,4>, <2,u,6,4> + 2638458005U, // : Cost 3 vext2 <3,4,u,6>, <4,3,6,u> + 1570540772U, // : Cost 2 vext2 <4,4,6,6>, <4,4,6,6> + 1545473334U, // : Cost 2 vext2 <0,2,u,6>, RHS + 1572015512U, // : Cost 2 vext2 <4,6,u,6>, <4,6,u,6> + 2960715062U, // : Cost 3 vzipr <1,2,u,4>, RHS + 1545473577U, // : Cost 2 vext2 <0,2,u,6>, RHS + 2567872614U, // : Cost 3 vext1 <2,u,6,5>, LHS + 2645757648U, // : Cost 3 vext2 <4,6,u,6>, <5,1,7,3> + 2567874490U, // : Cost 3 vext1 <2,u,6,5>, <2,6,3,7> + 2576501250U, // : Cost 3 vext1 <4,3,6,5>, <3,4,5,6> + 1576660943U, // : Cost 2 vext2 <5,4,u,6>, <5,4,u,6> + 2645757956U, // : Cost 3 vext2 <4,6,u,6>, <5,5,5,5> + 2645758050U, // : Cost 3 vext2 <4,6,u,6>, <5,6,7,0> + 2824080694U, // : Cost 3 vuzpr <0,u,2,6>, RHS + 1182626795U, // : Cost 2 vrev <6,u,u,5> + 1506082918U, // : Cost 2 vext1 <4,u,6,6>, LHS + 2579825398U, // : Cost 3 vext1 <4,u,6,6>, <1,0,3,2> + 2645758458U, // : Cost 3 vext2 <4,6,u,6>, <6,2,7,3> + 2579826838U, // : Cost 3 vext1 <4,u,6,6>, <3,0,1,2> + 1506086198U, // : Cost 2 vext1 <4,u,6,6>, RHS + 2579828432U, // : Cost 3 vext1 <4,u,6,6>, <5,1,7,3> + 296144182U, // : Cost 1 vdup2 RHS + 1638331202U, // : Cost 2 vext3 RHS, <6,6,7,7> + 296144182U, // : Cost 1 vdup2 RHS + 432349286U, // : Cost 1 vext1 RHS, LHS + 1506091766U, // : Cost 2 vext1 RHS, <1,0,3,2> + 1506092648U, // : Cost 2 vext1 RHS, <2,2,2,2> + 1506093206U, // : Cost 2 vext1 RHS, <3,0,1,2> + 432352809U, // : Cost 1 vext1 RHS, RHS + 1506094800U, // : Cost 2 vext1 RHS, <5,1,7,3> + 1506095610U, // : Cost 2 vext1 RHS, <6,2,7,3> + 1906904374U, // : Cost 2 vzipr RHS, RHS + 432355118U, // : Cost 1 vext1 RHS, LHS + 432357478U, // : Cost 1 vext1 RHS, LHS + 1545475886U, // : Cost 2 vext2 <0,2,u,6>, LHS + 1506100840U, // : Cost 2 vext1 RHS, <2,2,2,2> + 1506101398U, // : Cost 2 vext1 RHS, <3,0,1,2> + 432361002U, // : Cost 1 vext1 RHS, RHS + 1545476250U, // : Cost 2 vext2 <0,2,u,6>, RHS + 296144182U, // : Cost 1 vdup2 RHS + 1880370486U, // : Cost 2 vzipr LHS, RHS + 432363310U, // : Cost 1 vext1 RHS, LHS + 1571356672U, // : Cost 2 vext2 RHS, <0,0,0,0> + 497614950U, // : Cost 1 vext2 RHS, LHS + 1571356836U, // : Cost 2 vext2 RHS, <0,2,0,2> + 2573880146U, // : Cost 3 vext1 <3,u,7,0>, <3,u,7,0> + 1571357010U, // : Cost 2 vext2 RHS, <0,4,1,5> + 1512083716U, // : Cost 2 vext1 <5,u,7,0>, <5,u,7,0> + 2621874741U, // : Cost 3 vext2 <0,6,u,7>, <0,6,u,7> + 2585826298U, // : Cost 3 vext1 <5,u,7,0>, <7,0,1,2> + 497615517U, // : Cost 1 vext2 RHS, LHS + 1571357430U, // : Cost 2 vext2 RHS, <1,0,3,2> + 1571357492U, // : Cost 2 vext2 RHS, <1,1,1,1> + 1571357590U, // : Cost 2 vext2 RHS, <1,2,3,0> + 1552114715U, // : Cost 2 vext2 <1,3,u,7>, <1,3,u,7> + 2573888822U, // : Cost 3 vext1 <3,u,7,1>, RHS + 1553441981U, // : Cost 2 vext2 <1,5,u,7>, <1,5,u,7> + 2627847438U, // : Cost 3 vext2 <1,6,u,7>, <1,6,u,7> + 2727408775U, // : Cost 3 vext3 <7,1,7,u>, <7,1,7,u> + 1555432880U, // : Cost 2 vext2 <1,u,u,7>, <1,u,u,7> + 2629838337U, // : Cost 3 vext2 <2,0,u,7>, <2,0,u,7> + 1188058754U, // : Cost 2 vrev <7,u,1,2> + 1571358312U, // : Cost 2 vext2 RHS, <2,2,2,2> + 1571358374U, // : Cost 2 vext2 RHS, <2,3,0,1> + 2632492869U, // : Cost 3 vext2 <2,4,u,7>, <2,4,u,7> + 2633156502U, // : Cost 3 vext2 <2,5,u,7>, <2,5,u,7> + 1560078311U, // : Cost 2 vext2 <2,6,u,7>, <2,6,u,7> + 2728072408U, // : Cost 3 vext3 <7,2,7,u>, <7,2,7,u> + 1561405577U, // : Cost 2 vext2 <2,u,u,7>, <2,u,u,7> + 1571358870U, // : Cost 2 vext2 RHS, <3,0,1,2> + 2627184913U, // : Cost 3 vext2 <1,5,u,7>, <3,1,5,u> + 2633820523U, // : Cost 3 vext2 <2,6,u,7>, <3,2,6,u> + 1571359132U, // : Cost 2 vext2 RHS, <3,3,3,3> + 1571359234U, // : Cost 2 vext2 RHS, <3,4,5,6> + 1512108295U, // : Cost 2 vext1 <5,u,7,3>, <5,u,7,3> + 1518080992U, // : Cost 2 vext1 <6,u,7,3>, <6,u,7,3> + 2640456465U, // : Cost 3 vext2 <3,7,u,7>, <3,7,u,7> + 1571359518U, // : Cost 2 vext2 RHS, <3,u,1,2> + 1571359634U, // : Cost 2 vext2 RHS, <4,0,5,1> + 2573911067U, // : Cost 3 vext1 <3,u,7,4>, <1,3,u,7> + 2645101622U, // : Cost 3 vext2 RHS, <4,2,5,3> + 2573912918U, // : Cost 3 vext1 <3,u,7,4>, <3,u,7,4> + 1571359952U, // : Cost 2 vext2 RHS, <4,4,4,4> + 497618248U, // : Cost 1 vext2 RHS, RHS + 1571360116U, // : Cost 2 vext2 RHS, <4,6,4,6> + 2645102024U, // : Cost 3 vext2 RHS, <4,7,5,0> + 497618473U, // : Cost 1 vext2 RHS, RHS + 2645102152U, // : Cost 3 vext2 RHS, <5,0,1,2> + 1571360464U, // : Cost 2 vext2 RHS, <5,1,7,3> + 2645102334U, // : Cost 3 vext2 RHS, <5,2,3,4> + 2645102447U, // : Cost 3 vext2 RHS, <5,3,7,0> + 1571360710U, // : Cost 2 vext2 RHS, <5,4,7,6> + 1571360772U, // : Cost 2 vext2 RHS, <5,5,5,5> + 1571360866U, // : Cost 2 vext2 RHS, <5,6,7,0> + 1571360936U, // : Cost 2 vext2 RHS, <5,7,5,7> + 1571361017U, // : Cost 2 vext2 RHS, <5,u,5,7> + 1530044518U, // : Cost 2 vext1 , LHS + 2645103016U, // : Cost 3 vext2 RHS, <6,1,7,2> + 1571361274U, // : Cost 2 vext2 RHS, <6,2,7,3> + 2645103154U, // : Cost 3 vext2 RHS, <6,3,4,5> + 1530047798U, // : Cost 2 vext1 , RHS + 1188386474U, // : Cost 2 vrev <7,u,5,6> + 1571361592U, // : Cost 2 vext2 RHS, <6,6,6,6> + 1571361614U, // : Cost 2 vext2 RHS, <6,7,0,1> + 1571361695U, // : Cost 2 vext2 RHS, <6,u,0,1> + 1571361786U, // : Cost 2 vext2 RHS, <7,0,1,2> + 2573935616U, // : Cost 3 vext1 <3,u,7,7>, <1,3,5,7> + 2645103781U, // : Cost 3 vext2 RHS, <7,2,2,2> + 2573937497U, // : Cost 3 vext1 <3,u,7,7>, <3,u,7,7> + 1571362150U, // : Cost 2 vext2 RHS, <7,4,5,6> + 1512141067U, // : Cost 2 vext1 <5,u,7,7>, <5,u,7,7> + 1518113764U, // : Cost 2 vext1 <6,u,7,7>, <6,u,7,7> + 363253046U, // : Cost 1 vdup3 RHS + 363253046U, // : Cost 1 vdup3 RHS + 1571362515U, // : Cost 2 vext2 RHS, + 497620782U, // : Cost 1 vext2 RHS, LHS + 1571362693U, // : Cost 2 vext2 RHS, + 1571362748U, // : Cost 2 vext2 RHS, + 1571362879U, // : Cost 2 vext2 RHS, + 497621146U, // : Cost 1 vext2 RHS, RHS + 1571363024U, // : Cost 2 vext2 RHS, + 363253046U, // : Cost 1 vdup3 RHS + 497621349U, // : Cost 1 vext2 RHS, LHS + 135053414U, // : Cost 1 vdup0 LHS + 471081121U, // : Cost 1 vext2 LHS, LHS + 1544822948U, // : Cost 2 vext2 LHS, <0,2,0,2> + 1616140005U, // : Cost 2 vext3 LHS, + 1544823122U, // : Cost 2 vext2 LHS, <0,4,1,5> + 1512157453U, // : Cost 2 vext1 <5,u,u,0>, <5,u,u,0> + 1662220032U, // : Cost 2 vext3 RHS, + 1194457487U, // : Cost 2 vrev + 471081629U, // : Cost 1 vext2 LHS, LHS + 1544823542U, // : Cost 2 vext2 LHS, <1,0,3,2> + 202162278U, // : Cost 1 vdup1 LHS + 537753390U, // : Cost 1 vext3 LHS, LHS + 1544823768U, // : Cost 2 vext2 LHS, <1,3,1,3> + 1494248758U, // : Cost 2 vext1 <2,u,u,1>, RHS + 1544823952U, // : Cost 2 vext2 LHS, <1,5,3,7> + 1518138343U, // : Cost 2 vext1 <6,u,u,1>, <6,u,u,1> + 1640322907U, // : Cost 2 vext3 RHS, + 537753444U, // : Cost 1 vext3 LHS, LHS + 1482309734U, // : Cost 2 vext1 <0,u,u,2>, LHS + 1194031451U, // : Cost 2 vrev + 269271142U, // : Cost 1 vdup2 LHS + 835584U, // : Cost 0 copy LHS + 1482313014U, // : Cost 2 vext1 <0,u,u,2>, RHS + 2618566504U, // : Cost 3 vext2 LHS, <2,5,3,6> + 1544824762U, // : Cost 2 vext2 LHS, <2,6,3,7> + 1638479788U, // : Cost 2 vext3 RHS, + 835584U, // : Cost 0 copy LHS + 408576723U, // : Cost 1 vext1 LHS, LHS + 1482318582U, // : Cost 2 vext1 LHS, <1,0,3,2> + 120371557U, // : Cost 1 vrev LHS + 336380006U, // : Cost 1 vdup3 LHS + 408579382U, // : Cost 1 vext1 LHS, RHS + 1616140271U, // : Cost 2 vext3 LHS, + 1530098170U, // : Cost 2 vext1 LHS, <6,2,7,3> + 1880329544U, // : Cost 2 vzipr LHS, RHS + 408581934U, // : Cost 1 vext1 LHS, LHS + 1488298086U, // : Cost 2 vext1 <1,u,u,4>, LHS + 1488299437U, // : Cost 2 vext1 <1,u,u,4>, <1,u,u,4> + 1659271204U, // : Cost 2 vext3 LHS, + 1194195311U, // : Cost 2 vrev + 161926454U, // : Cost 1 vdup0 RHS + 471084342U, // : Cost 1 vext2 LHS, RHS + 1571368308U, // : Cost 2 vext2 RHS, <4,6,4,6> + 1640323153U, // : Cost 2 vext3 RHS, + 471084585U, // : Cost 1 vext2 LHS, RHS + 1494278246U, // : Cost 2 vext1 <2,u,u,5>, LHS + 1571368656U, // : Cost 2 vext2 RHS, <5,1,7,3> + 1494280327U, // : Cost 2 vext1 <2,u,u,5>, <2,u,u,5> + 1616140415U, // : Cost 2 vext3 LHS, + 1494281526U, // : Cost 2 vext1 <2,u,u,5>, RHS + 229035318U, // : Cost 1 vdup1 RHS + 537753754U, // : Cost 1 vext3 LHS, RHS + 1750355254U, // : Cost 2 vuzpr LHS, RHS + 537753772U, // : Cost 1 vext3 LHS, RHS + 1482342502U, // : Cost 2 vext1 <0,u,u,6>, LHS + 2556084982U, // : Cost 3 vext1 <0,u,u,6>, <1,0,3,2> + 1571369466U, // : Cost 2 vext2 RHS, <6,2,7,3> + 1611938000U, // : Cost 2 vext3 LHS, + 1482345782U, // : Cost 2 vext1 <0,u,u,6>, RHS + 1194359171U, // : Cost 2 vrev + 296144182U, // : Cost 1 vdup2 RHS + 27705344U, // : Cost 0 copy RHS + 27705344U, // : Cost 0 copy RHS + 432496742U, // : Cost 1 vext1 RHS, LHS + 1488324016U, // : Cost 2 vext1 <1,u,u,7>, <1,u,u,7> + 1494296713U, // : Cost 2 vext1 <2,u,u,7>, <2,u,u,7> + 1906901148U, // : Cost 2 vzipr RHS, LHS + 432500283U, // : Cost 1 vext1 RHS, RHS + 1506242256U, // : Cost 2 vext1 RHS, <5,1,7,3> + 120699277U, // : Cost 1 vrev RHS + 363253046U, // : Cost 1 vdup3 RHS + 432502574U, // : Cost 1 vext1 RHS, LHS + 408617688U, // : Cost 1 vext1 LHS, LHS + 471086894U, // : Cost 1 vext2 LHS, LHS + 537753957U, // : Cost 1 vext3 LHS, LHS + 835584U, // : Cost 0 copy LHS + 408620342U, // : Cost 1 vext1 LHS, RHS + 471087258U, // : Cost 1 vext2 LHS, RHS + 537753997U, // : Cost 1 vext3 LHS, RHS + 27705344U, // : Cost 0 copy RHS + 835584U, // : Cost 0 copy LHS + 0 +}; diff --git a/libclamav/c++/llvm/lib/Target/ARM/ARMRegisterInfo.cpp b/libclamav/c++/llvm/lib/Target/ARM/ARMRegisterInfo.cpp new file mode 100644 index 000000000..d5bc3f60b --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/ARM/ARMRegisterInfo.cpp @@ -0,0 +1,41 @@ +//===- ARMRegisterInfo.cpp - ARM Register Information -----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the ARM implementation of the TargetRegisterInfo class. +// +//===----------------------------------------------------------------------===// + +#include "ARM.h" +#include "ARMAddressingModes.h" +#include "ARMBaseInstrInfo.h" +#include "ARMInstrInfo.h" +#include "ARMMachineFunctionInfo.h" +#include "ARMRegisterInfo.h" +#include "ARMSubtarget.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/CodeGen/MachineConstantPool.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineLocation.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/RegisterScavenging.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Target/TargetFrameInfo.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetOptions.h" +#include "llvm/ADT/BitVector.h" +#include "llvm/ADT/SmallVector.h" +using namespace llvm; + +ARMRegisterInfo::ARMRegisterInfo(const ARMBaseInstrInfo &tii, + const ARMSubtarget &sti) + : ARMBaseRegisterInfo(tii, sti) { +} diff --git a/libclamav/c++/llvm/lib/Target/ARM/ARMRegisterInfo.h b/libclamav/c++/llvm/lib/Target/ARM/ARMRegisterInfo.h new file mode 100644 index 000000000..041afd041 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/ARM/ARMRegisterInfo.h @@ -0,0 +1,43 @@ +//===- ARMRegisterInfo.h - ARM Register Information Impl --------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the ARM implementation of the TargetRegisterInfo class. +// +//===----------------------------------------------------------------------===// + +#ifndef ARMREGISTERINFO_H +#define ARMREGISTERINFO_H + +#include "ARM.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "ARMBaseRegisterInfo.h" + +namespace llvm { + class ARMSubtarget; + class ARMBaseInstrInfo; + class Type; + +namespace ARM { + /// SubregIndex - The index of various subregister classes. Note that + /// these indices must be kept in sync with the class indices in the + /// ARMRegisterInfo.td file. + enum SubregIndex { + SSUBREG_0 = 1, SSUBREG_1 = 2, SSUBREG_2 = 3, SSUBREG_3 = 4, + DSUBREG_0 = 5, DSUBREG_1 = 6 + }; +} + +struct ARMRegisterInfo : public ARMBaseRegisterInfo { +public: + ARMRegisterInfo(const ARMBaseInstrInfo &tii, const ARMSubtarget &STI); +}; + +} // end namespace llvm + +#endif diff --git a/libclamav/c++/llvm/lib/Target/ARM/ARMRegisterInfo.td b/libclamav/c++/llvm/lib/Target/ARM/ARMRegisterInfo.td new file mode 100644 index 000000000..d393e8d7e --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/ARM/ARMRegisterInfo.td @@ -0,0 +1,410 @@ +//===- ARMRegisterInfo.td - ARM Register defs -------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// Declarations that describe the ARM register file +//===----------------------------------------------------------------------===// + +// Registers are identified with 4-bit ID numbers. +class ARMReg num, string n, list subregs = []> : Register { + field bits<4> Num; + let Namespace = "ARM"; + let SubRegs = subregs; +} + +class ARMFReg num, string n> : Register { + field bits<6> Num; + let Namespace = "ARM"; +} + +// Integer registers +def R0 : ARMReg< 0, "r0">, DwarfRegNum<[0]>; +def R1 : ARMReg< 1, "r1">, DwarfRegNum<[1]>; +def R2 : ARMReg< 2, "r2">, DwarfRegNum<[2]>; +def R3 : ARMReg< 3, "r3">, DwarfRegNum<[3]>; +def R4 : ARMReg< 4, "r4">, DwarfRegNum<[4]>; +def R5 : ARMReg< 5, "r5">, DwarfRegNum<[5]>; +def R6 : ARMReg< 6, "r6">, DwarfRegNum<[6]>; +def R7 : ARMReg< 7, "r7">, DwarfRegNum<[7]>; +def R8 : ARMReg< 8, "r8">, DwarfRegNum<[8]>; +def R9 : ARMReg< 9, "r9">, DwarfRegNum<[9]>; +def R10 : ARMReg<10, "r10">, DwarfRegNum<[10]>; +def R11 : ARMReg<11, "r11">, DwarfRegNum<[11]>; +def R12 : ARMReg<12, "r12">, DwarfRegNum<[12]>; +def SP : ARMReg<13, "sp">, DwarfRegNum<[13]>; +def LR : ARMReg<14, "lr">, DwarfRegNum<[14]>; +def PC : ARMReg<15, "pc">, DwarfRegNum<[15]>; + +// Float registers +def S0 : ARMFReg< 0, "s0">; def S1 : ARMFReg< 1, "s1">; +def S2 : ARMFReg< 2, "s2">; def S3 : ARMFReg< 3, "s3">; +def S4 : ARMFReg< 4, "s4">; def S5 : ARMFReg< 5, "s5">; +def S6 : ARMFReg< 6, "s6">; def S7 : ARMFReg< 7, "s7">; +def S8 : ARMFReg< 8, "s8">; def S9 : ARMFReg< 9, "s9">; +def S10 : ARMFReg<10, "s10">; def S11 : ARMFReg<11, "s11">; +def S12 : ARMFReg<12, "s12">; def S13 : ARMFReg<13, "s13">; +def S14 : ARMFReg<14, "s14">; def S15 : ARMFReg<15, "s15">; +def S16 : ARMFReg<16, "s16">; def S17 : ARMFReg<17, "s17">; +def S18 : ARMFReg<18, "s18">; def S19 : ARMFReg<19, "s19">; +def S20 : ARMFReg<20, "s20">; def S21 : ARMFReg<21, "s21">; +def S22 : ARMFReg<22, "s22">; def S23 : ARMFReg<23, "s23">; +def S24 : ARMFReg<24, "s24">; def S25 : ARMFReg<25, "s25">; +def S26 : ARMFReg<26, "s26">; def S27 : ARMFReg<27, "s27">; +def S28 : ARMFReg<28, "s28">; def S29 : ARMFReg<29, "s29">; +def S30 : ARMFReg<30, "s30">; def S31 : ARMFReg<31, "s31">; +def SDummy : ARMFReg<63, "sINVALID">; + +// Aliases of the F* registers used to hold 64-bit fp values (doubles) +def D0 : ARMReg< 0, "d0", [S0, S1]>; +def D1 : ARMReg< 1, "d1", [S2, S3]>; +def D2 : ARMReg< 2, "d2", [S4, S5]>; +def D3 : ARMReg< 3, "d3", [S6, S7]>; +def D4 : ARMReg< 4, "d4", [S8, S9]>; +def D5 : ARMReg< 5, "d5", [S10, S11]>; +def D6 : ARMReg< 6, "d6", [S12, S13]>; +def D7 : ARMReg< 7, "d7", [S14, S15]>; +def D8 : ARMReg< 8, "d8", [S16, S17]>; +def D9 : ARMReg< 9, "d9", [S18, S19]>; +def D10 : ARMReg<10, "d10", [S20, S21]>; +def D11 : ARMReg<11, "d11", [S22, S23]>; +def D12 : ARMReg<12, "d12", [S24, S25]>; +def D13 : ARMReg<13, "d13", [S26, S27]>; +def D14 : ARMReg<14, "d14", [S28, S29]>; +def D15 : ARMReg<15, "d15", [S30, S31]>; + +// VFP3 defines 16 additional double registers +def D16 : ARMFReg<16, "d16">; def D17 : ARMFReg<17, "d17">; +def D18 : ARMFReg<18, "d18">; def D19 : ARMFReg<19, "d19">; +def D20 : ARMFReg<20, "d20">; def D21 : ARMFReg<21, "d21">; +def D22 : ARMFReg<22, "d22">; def D23 : ARMFReg<23, "d23">; +def D24 : ARMFReg<24, "d24">; def D25 : ARMFReg<25, "d25">; +def D26 : ARMFReg<26, "d26">; def D27 : ARMFReg<27, "d27">; +def D28 : ARMFReg<28, "d28">; def D29 : ARMFReg<29, "d29">; +def D30 : ARMFReg<30, "d30">; def D31 : ARMFReg<31, "d31">; + +// Advanced SIMD (NEON) defines 16 quad-word aliases +def Q0 : ARMReg< 0, "q0", [D0, D1]>; +def Q1 : ARMReg< 1, "q1", [D2, D3]>; +def Q2 : ARMReg< 2, "q2", [D4, D5]>; +def Q3 : ARMReg< 3, "q3", [D6, D7]>; +def Q4 : ARMReg< 4, "q4", [D8, D9]>; +def Q5 : ARMReg< 5, "q5", [D10, D11]>; +def Q6 : ARMReg< 6, "q6", [D12, D13]>; +def Q7 : ARMReg< 7, "q7", [D14, D15]>; +def Q8 : ARMReg< 8, "q8", [D16, D17]>; +def Q9 : ARMReg< 9, "q9", [D18, D19]>; +def Q10 : ARMReg<10, "q10", [D20, D21]>; +def Q11 : ARMReg<11, "q11", [D22, D23]>; +def Q12 : ARMReg<12, "q12", [D24, D25]>; +def Q13 : ARMReg<13, "q13", [D26, D27]>; +def Q14 : ARMReg<14, "q14", [D28, D29]>; +def Q15 : ARMReg<15, "q15", [D30, D31]>; + +// Current Program Status Register. +def CPSR : ARMReg<0, "cpsr">; + +def FPSCR : ARMReg<1, "fpscr">; + +// Register classes. +// +// pc == Program Counter +// lr == Link Register +// sp == Stack Pointer +// r12 == ip (scratch) +// r7 == Frame Pointer (thumb-style backtraces) +// r9 == May be reserved as Thread Register +// r11 == Frame Pointer (arm-style backtraces) +// r10 == Stack Limit +// +def GPR : RegisterClass<"ARM", [i32], 32, [R0, R1, R2, R3, R4, R5, R6, + R7, R8, R9, R10, R12, R11, + LR, SP, PC]> { + let MethodProtos = [{ + iterator allocation_order_begin(const MachineFunction &MF) const; + iterator allocation_order_end(const MachineFunction &MF) const; + }]; + let MethodBodies = [{ + // FP is R11, R9 is available. + static const unsigned ARM_GPR_AO_1[] = { + ARM::R0, ARM::R1, ARM::R2, ARM::R3, + ARM::R12,ARM::LR, + ARM::R4, ARM::R5, ARM::R6, ARM::R7, + ARM::R8, ARM::R9, ARM::R10, + ARM::R11 }; + // FP is R11, R9 is not available. + static const unsigned ARM_GPR_AO_2[] = { + ARM::R0, ARM::R1, ARM::R2, ARM::R3, + ARM::R12,ARM::LR, + ARM::R4, ARM::R5, ARM::R6, ARM::R7, + ARM::R8, ARM::R10, + ARM::R11 }; + // FP is R7, R9 is available as non-callee-saved register. + // This is used by Darwin. + static const unsigned ARM_GPR_AO_3[] = { + ARM::R0, ARM::R1, ARM::R2, ARM::R3, + ARM::R9, ARM::R12,ARM::LR, + ARM::R4, ARM::R5, ARM::R6, + ARM::R8, ARM::R10,ARM::R11,ARM::R7 }; + // FP is R7, R9 is not available. + static const unsigned ARM_GPR_AO_4[] = { + ARM::R0, ARM::R1, ARM::R2, ARM::R3, + ARM::R12,ARM::LR, + ARM::R4, ARM::R5, ARM::R6, + ARM::R8, ARM::R10,ARM::R11, + ARM::R7 }; + // FP is R7, R9 is available as callee-saved register. + // This is used by non-Darwin platform in Thumb mode. + static const unsigned ARM_GPR_AO_5[] = { + ARM::R0, ARM::R1, ARM::R2, ARM::R3, + ARM::R12,ARM::LR, + ARM::R4, ARM::R5, ARM::R6, + ARM::R8, ARM::R9, ARM::R10,ARM::R11,ARM::R7 }; + + // For Thumb1 mode, we don't want to allocate hi regs at all, as we + // don't know how to spill them. If we make our prologue/epilogue code + // smarter at some point, we can go back to using the above allocation + // orders for the Thumb1 instructions that know how to use hi regs. + static const unsigned THUMB_GPR_AO[] = { + ARM::R0, ARM::R1, ARM::R2, ARM::R3, + ARM::R4, ARM::R5, ARM::R6, ARM::R7 }; + + GPRClass::iterator + GPRClass::allocation_order_begin(const MachineFunction &MF) const { + const TargetMachine &TM = MF.getTarget(); + const ARMSubtarget &Subtarget = TM.getSubtarget(); + if (Subtarget.isThumb1Only()) + return THUMB_GPR_AO; + if (Subtarget.isTargetDarwin()) { + if (Subtarget.isR9Reserved()) + return ARM_GPR_AO_4; + else + return ARM_GPR_AO_3; + } else { + if (Subtarget.isR9Reserved()) + return ARM_GPR_AO_2; + else if (Subtarget.isThumb()) + return ARM_GPR_AO_5; + else + return ARM_GPR_AO_1; + } + } + + GPRClass::iterator + GPRClass::allocation_order_end(const MachineFunction &MF) const { + const TargetMachine &TM = MF.getTarget(); + const TargetRegisterInfo *RI = TM.getRegisterInfo(); + const ARMSubtarget &Subtarget = TM.getSubtarget(); + GPRClass::iterator I; + + if (Subtarget.isThumb1Only()) { + I = THUMB_GPR_AO + (sizeof(THUMB_GPR_AO)/sizeof(unsigned)); + // Mac OS X requires FP not to be clobbered for backtracing purpose. + return (Subtarget.isTargetDarwin() || RI->hasFP(MF)) ? I-1 : I; + } + + if (Subtarget.isTargetDarwin()) { + if (Subtarget.isR9Reserved()) + I = ARM_GPR_AO_4 + (sizeof(ARM_GPR_AO_4)/sizeof(unsigned)); + else + I = ARM_GPR_AO_3 + (sizeof(ARM_GPR_AO_3)/sizeof(unsigned)); + } else { + if (Subtarget.isR9Reserved()) + I = ARM_GPR_AO_2 + (sizeof(ARM_GPR_AO_2)/sizeof(unsigned)); + else if (Subtarget.isThumb()) + I = ARM_GPR_AO_5 + (sizeof(ARM_GPR_AO_5)/sizeof(unsigned)); + else + I = ARM_GPR_AO_1 + (sizeof(ARM_GPR_AO_1)/sizeof(unsigned)); + } + + // Mac OS X requires FP not to be clobbered for backtracing purpose. + return (Subtarget.isTargetDarwin() || RI->hasFP(MF)) ? I-1 : I; + } + }]; +} + +// Thumb registers are R0-R7 normally. Some instructions can still use +// the general GPR register class above (MOV, e.g.) +def tGPR : RegisterClass<"ARM", [i32], 32, [R0, R1, R2, R3, R4, R5, R6, R7]> { + let MethodProtos = [{ + iterator allocation_order_begin(const MachineFunction &MF) const; + iterator allocation_order_end(const MachineFunction &MF) const; + }]; + let MethodBodies = [{ + static const unsigned THUMB_tGPR_AO[] = { + ARM::R0, ARM::R1, ARM::R2, ARM::R3, + ARM::R4, ARM::R5, ARM::R6, ARM::R7 }; + + // FP is R7, only low registers available. + tGPRClass::iterator + tGPRClass::allocation_order_begin(const MachineFunction &MF) const { + return THUMB_tGPR_AO; + } + + tGPRClass::iterator + tGPRClass::allocation_order_end(const MachineFunction &MF) const { + const TargetMachine &TM = MF.getTarget(); + const TargetRegisterInfo *RI = TM.getRegisterInfo(); + const ARMSubtarget &Subtarget = TM.getSubtarget(); + tGPRClass::iterator I = + THUMB_tGPR_AO + (sizeof(THUMB_tGPR_AO)/sizeof(unsigned)); + // Mac OS X requires FP not to be clobbered for backtracing purpose. + return (Subtarget.isTargetDarwin() || RI->hasFP(MF)) ? I-1 : I; + } + }]; +} + +// Scalar single precision floating point register class.. +def SPR : RegisterClass<"ARM", [f32], 32, [S0, S1, S2, S3, S4, S5, S6, S7, S8, + S9, S10, S11, S12, S13, S14, S15, S16, S17, S18, S19, S20, S21, S22, + S23, S24, S25, S26, S27, S28, S29, S30, S31]>; + +// Subset of SPR which can be used as a source of NEON scalars for 16-bit +// operations +def SPR_8 : RegisterClass<"ARM", [f32], 32, + [S0, S1, S2, S3, S4, S5, S6, S7, + S8, S9, S10, S11, S12, S13, S14, S15]>; + +// Dummy f32 regclass to represent impossible subreg indices. +def SPR_INVALID : RegisterClass<"ARM", [f32], 32, [SDummy]> { + let CopyCost = -1; +} + +// Scalar double precision floating point / generic 64-bit vector register +// class. +// ARM requires only word alignment for double. It's more performant if it +// is double-word alignment though. +def DPR : RegisterClass<"ARM", [f64, v8i8, v4i16, v2i32, v1i64, v2f32], 64, + [D0, D1, D2, D3, D4, D5, D6, D7, + D8, D9, D10, D11, D12, D13, D14, D15, + D16, D17, D18, D19, D20, D21, D22, D23, + D24, D25, D26, D27, D28, D29, D30, D31]> { + let SubRegClassList = [SPR_INVALID, SPR_INVALID]; + let MethodProtos = [{ + iterator allocation_order_begin(const MachineFunction &MF) const; + iterator allocation_order_end(const MachineFunction &MF) const; + }]; + let MethodBodies = [{ + // VFP2 + static const unsigned ARM_DPR_VFP2[] = { + ARM::D0, ARM::D1, ARM::D2, ARM::D3, + ARM::D4, ARM::D5, ARM::D6, ARM::D7, + ARM::D8, ARM::D9, ARM::D10, ARM::D11, + ARM::D12, ARM::D13, ARM::D14, ARM::D15 }; + // VFP3 + static const unsigned ARM_DPR_VFP3[] = { + ARM::D0, ARM::D1, ARM::D2, ARM::D3, + ARM::D4, ARM::D5, ARM::D6, ARM::D7, + ARM::D8, ARM::D9, ARM::D10, ARM::D11, + ARM::D12, ARM::D13, ARM::D14, ARM::D15, + ARM::D16, ARM::D17, ARM::D18, ARM::D19, + ARM::D20, ARM::D21, ARM::D22, ARM::D23, + ARM::D24, ARM::D25, ARM::D26, ARM::D27, + ARM::D28, ARM::D29, ARM::D30, ARM::D31 }; + DPRClass::iterator + DPRClass::allocation_order_begin(const MachineFunction &MF) const { + const TargetMachine &TM = MF.getTarget(); + const ARMSubtarget &Subtarget = TM.getSubtarget(); + if (Subtarget.hasVFP3()) + return ARM_DPR_VFP3; + return ARM_DPR_VFP2; + } + + DPRClass::iterator + DPRClass::allocation_order_end(const MachineFunction &MF) const { + const TargetMachine &TM = MF.getTarget(); + const ARMSubtarget &Subtarget = TM.getSubtarget(); + if (Subtarget.hasVFP3()) + return ARM_DPR_VFP3 + (sizeof(ARM_DPR_VFP3)/sizeof(unsigned)); + else + return ARM_DPR_VFP2 + (sizeof(ARM_DPR_VFP2)/sizeof(unsigned)); + } + }]; +} + +// Subset of DPR that are accessible with VFP2 (and so that also have +// 32-bit SPR subregs). +def DPR_VFP2 : RegisterClass<"ARM", [f64, v8i8, v4i16, v2i32, v1i64, v2f32], 64, + [D0, D1, D2, D3, D4, D5, D6, D7, + D8, D9, D10, D11, D12, D13, D14, D15]> { + let SubRegClassList = [SPR, SPR]; +} + +// Subset of DPR which can be used as a source of NEON scalars for 16-bit +// operations +def DPR_8 : RegisterClass<"ARM", [f64, v8i8, v4i16, v2i32, v1i64, v2f32], 64, + [D0, D1, D2, D3, D4, D5, D6, D7]> { + let SubRegClassList = [SPR_8, SPR_8]; +} + +// Generic 128-bit vector register class. +def QPR : RegisterClass<"ARM", [v16i8, v8i16, v4i32, v2i64, v4f32, v2f64], 128, + [Q0, Q1, Q2, Q3, Q4, Q5, Q6, Q7, + Q8, Q9, Q10, Q11, Q12, Q13, Q14, Q15]> { + let SubRegClassList = [SPR_INVALID, SPR_INVALID, SPR_INVALID, SPR_INVALID, + DPR, DPR]; +} + +// Subset of QPR that have 32-bit SPR subregs. +def QPR_VFP2 : RegisterClass<"ARM", [v16i8, v8i16, v4i32, v2i64, v4f32, v2f64], + 128, + [Q0, Q1, Q2, Q3, Q4, Q5, Q6, Q7]> { + let SubRegClassList = [SPR, SPR, SPR, SPR, DPR_VFP2, DPR_VFP2]; +} + +// Subset of QPR that have DPR_8 and SPR_8 subregs. +def QPR_8 : RegisterClass<"ARM", [v16i8, v8i16, v4i32, v2i64, v4f32, v2f64], + 128, + [Q0, Q1, Q2, Q3]> { + let SubRegClassList = [SPR_8, SPR_8, SPR_8, SPR_8, DPR_8, DPR_8]; +} + +// Condition code registers. +def CCR : RegisterClass<"ARM", [i32], 32, [CPSR]>; + +//===----------------------------------------------------------------------===// +// Subregister Set Definitions... now that we have all of the pieces, define the +// sub registers for each register. +// + +def arm_ssubreg_0 : PatLeaf<(i32 1)>; +def arm_ssubreg_1 : PatLeaf<(i32 2)>; +def arm_ssubreg_2 : PatLeaf<(i32 3)>; +def arm_ssubreg_3 : PatLeaf<(i32 4)>; +def arm_dsubreg_0 : PatLeaf<(i32 5)>; +def arm_dsubreg_1 : PatLeaf<(i32 6)>; + +// S sub-registers of D registers. +def : SubRegSet<1, [D0, D1, D2, D3, D4, D5, D6, D7, + D8, D9, D10, D11, D12, D13, D14, D15], + [S0, S2, S4, S6, S8, S10, S12, S14, + S16, S18, S20, S22, S24, S26, S28, S30]>; +def : SubRegSet<2, [D0, D1, D2, D3, D4, D5, D6, D7, + D8, D9, D10, D11, D12, D13, D14, D15], + [S1, S3, S5, S7, S9, S11, S13, S15, + S17, S19, S21, S23, S25, S27, S29, S31]>; + +// S sub-registers of Q registers. +def : SubRegSet<1, [Q0, Q1, Q2, Q3, Q4, Q5, Q6, Q7], + [S0, S4, S8, S12, S16, S20, S24, S28]>; +def : SubRegSet<2, [Q0, Q1, Q2, Q3, Q4, Q5, Q6, Q7], + [S1, S5, S9, S13, S17, S21, S25, S29]>; +def : SubRegSet<3, [Q0, Q1, Q2, Q3, Q4, Q5, Q6, Q7], + [S2, S6, S10, S14, S18, S22, S26, S30]>; +def : SubRegSet<4, [Q0, Q1, Q2, Q3, Q4, Q5, Q6, Q7], + [S3, S7, S11, S15, S19, S23, S27, S31]>; + +// D sub-registers of Q registers. +def : SubRegSet<5, [Q0, Q1, Q2, Q3, Q4, Q5, Q6, Q7, + Q8, Q9, Q10, Q11, Q12, Q13, Q14, Q15], + [D0, D2, D4, D6, D8, D10, D12, D14, + D16, D18, D20, D22, D24, D26, D28, D30]>; +def : SubRegSet<6, [Q0, Q1, Q2, Q3, Q4, Q5, Q6, Q7, + Q8, Q9, Q10, Q11, Q12, Q13, Q14, Q15], + [D1, D3, D5, D7, D9, D11, D13, D15, + D17, D19, D21, D23, D25, D27, D29, D31]>; diff --git a/libclamav/c++/llvm/lib/Target/ARM/ARMRelocations.h b/libclamav/c++/llvm/lib/Target/ARM/ARMRelocations.h new file mode 100644 index 000000000..2cc295085 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/ARM/ARMRelocations.h @@ -0,0 +1,56 @@ +//===- ARMRelocations.h - ARM Code Relocations ------------------*- 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 the ARM target-specific relocation types. +// +//===----------------------------------------------------------------------===// + +#ifndef ARMRELOCATIONS_H +#define ARMRELOCATIONS_H + +#include "llvm/CodeGen/MachineRelocation.h" + +namespace llvm { + namespace ARM { + enum RelocationType { + // reloc_arm_absolute - Absolute relocation, just add the relocated value + // to the value already in memory. + reloc_arm_absolute, + + // reloc_arm_relative - PC relative relocation, add the relocated value to + // the value already in memory, after we adjust it for where the PC is. + reloc_arm_relative, + + // reloc_arm_cp_entry - PC relative relocation for constpool_entry's whose + // addresses are kept locally in a map. + reloc_arm_cp_entry, + + // reloc_arm_vfp_cp_entry - Same as reloc_arm_cp_entry except the offset + // should be divided by 4. + reloc_arm_vfp_cp_entry, + + // reloc_arm_machine_cp_entry - Relocation of a ARM machine constantpool + // entry. + reloc_arm_machine_cp_entry, + + // reloc_arm_jt_base - PC relative relocation for jump tables whose + // addresses are kept locally in a map. + reloc_arm_jt_base, + + // reloc_arm_pic_jt - PIC jump table entry relocation: dest bb - jt base. + reloc_arm_pic_jt, + + // reloc_arm_branch - Branch address relocation. + reloc_arm_branch + }; + } +} + +#endif + diff --git a/libclamav/c++/llvm/lib/Target/ARM/ARMSchedule.td b/libclamav/c++/llvm/lib/Target/ARM/ARMSchedule.td new file mode 100644 index 000000000..fc4c5f583 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/ARM/ARMSchedule.td @@ -0,0 +1,160 @@ +//===- ARMSchedule.td - ARM Scheduling Definitions ---------*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// Functional units across ARM processors +// +def FU_Issue : FuncUnit; // issue +def FU_Pipe0 : FuncUnit; // pipeline 0 +def FU_Pipe1 : FuncUnit; // pipeline 1 +def FU_LdSt0 : FuncUnit; // pipeline 0 load/store +def FU_LdSt1 : FuncUnit; // pipeline 1 load/store +def FU_NPipe : FuncUnit; // NEON ALU/MUL pipe +def FU_NLSPipe : FuncUnit; // NEON LS pipe + +//===----------------------------------------------------------------------===// +// Instruction Itinerary classes used for ARM +// +def IIC_iALUx : InstrItinClass; +def IIC_iALUi : InstrItinClass; +def IIC_iALUr : InstrItinClass; +def IIC_iALUsi : InstrItinClass; +def IIC_iALUsr : InstrItinClass; +def IIC_iUNAr : InstrItinClass; +def IIC_iUNAsi : InstrItinClass; +def IIC_iUNAsr : InstrItinClass; +def IIC_iCMPi : InstrItinClass; +def IIC_iCMPr : InstrItinClass; +def IIC_iCMPsi : InstrItinClass; +def IIC_iCMPsr : InstrItinClass; +def IIC_iMOVi : InstrItinClass; +def IIC_iMOVr : InstrItinClass; +def IIC_iMOVsi : InstrItinClass; +def IIC_iMOVsr : InstrItinClass; +def IIC_iCMOVi : InstrItinClass; +def IIC_iCMOVr : InstrItinClass; +def IIC_iCMOVsi : InstrItinClass; +def IIC_iCMOVsr : InstrItinClass; +def IIC_iMUL16 : InstrItinClass; +def IIC_iMAC16 : InstrItinClass; +def IIC_iMUL32 : InstrItinClass; +def IIC_iMAC32 : InstrItinClass; +def IIC_iMUL64 : InstrItinClass; +def IIC_iMAC64 : InstrItinClass; +def IIC_iLoadi : InstrItinClass; +def IIC_iLoadr : InstrItinClass; +def IIC_iLoadsi : InstrItinClass; +def IIC_iLoadiu : InstrItinClass; +def IIC_iLoadru : InstrItinClass; +def IIC_iLoadsiu : InstrItinClass; +def IIC_iLoadm : InstrItinClass; +def IIC_iStorei : InstrItinClass; +def IIC_iStorer : InstrItinClass; +def IIC_iStoresi : InstrItinClass; +def IIC_iStoreiu : InstrItinClass; +def IIC_iStoreru : InstrItinClass; +def IIC_iStoresiu : InstrItinClass; +def IIC_iStorem : InstrItinClass; +def IIC_Br : InstrItinClass; +def IIC_fpSTAT : InstrItinClass; +def IIC_fpUNA32 : InstrItinClass; +def IIC_fpUNA64 : InstrItinClass; +def IIC_fpCMP32 : InstrItinClass; +def IIC_fpCMP64 : InstrItinClass; +def IIC_fpCVTSD : InstrItinClass; +def IIC_fpCVTDS : InstrItinClass; +def IIC_fpCVTIS : InstrItinClass; +def IIC_fpCVTID : InstrItinClass; +def IIC_fpCVTSI : InstrItinClass; +def IIC_fpCVTDI : InstrItinClass; +def IIC_fpALU32 : InstrItinClass; +def IIC_fpALU64 : InstrItinClass; +def IIC_fpMUL32 : InstrItinClass; +def IIC_fpMUL64 : InstrItinClass; +def IIC_fpMAC32 : InstrItinClass; +def IIC_fpMAC64 : InstrItinClass; +def IIC_fpDIV32 : InstrItinClass; +def IIC_fpDIV64 : InstrItinClass; +def IIC_fpSQRT32 : InstrItinClass; +def IIC_fpSQRT64 : InstrItinClass; +def IIC_fpLoad32 : InstrItinClass; +def IIC_fpLoad64 : InstrItinClass; +def IIC_fpLoadm : InstrItinClass; +def IIC_fpStore32 : InstrItinClass; +def IIC_fpStore64 : InstrItinClass; +def IIC_fpStorem : InstrItinClass; +def IIC_VLD1 : InstrItinClass; +def IIC_VLD2 : InstrItinClass; +def IIC_VLD3 : InstrItinClass; +def IIC_VLD4 : InstrItinClass; +def IIC_VST : InstrItinClass; +def IIC_VUNAD : InstrItinClass; +def IIC_VUNAQ : InstrItinClass; +def IIC_VBIND : InstrItinClass; +def IIC_VBINQ : InstrItinClass; +def IIC_VMOVImm : InstrItinClass; +def IIC_VMOVD : InstrItinClass; +def IIC_VMOVQ : InstrItinClass; +def IIC_VMOVIS : InstrItinClass; +def IIC_VMOVID : InstrItinClass; +def IIC_VMOVISL : InstrItinClass; +def IIC_VMOVSI : InstrItinClass; +def IIC_VMOVDI : InstrItinClass; +def IIC_VPERMD : InstrItinClass; +def IIC_VPERMQ : InstrItinClass; +def IIC_VPERMQ3 : InstrItinClass; +def IIC_VMACD : InstrItinClass; +def IIC_VMACQ : InstrItinClass; +def IIC_VRECSD : InstrItinClass; +def IIC_VRECSQ : InstrItinClass; +def IIC_VCNTiD : InstrItinClass; +def IIC_VCNTiQ : InstrItinClass; +def IIC_VUNAiD : InstrItinClass; +def IIC_VUNAiQ : InstrItinClass; +def IIC_VQUNAiD : InstrItinClass; +def IIC_VQUNAiQ : InstrItinClass; +def IIC_VBINiD : InstrItinClass; +def IIC_VBINiQ : InstrItinClass; +def IIC_VSUBiD : InstrItinClass; +def IIC_VSUBiQ : InstrItinClass; +def IIC_VBINi4D : InstrItinClass; +def IIC_VBINi4Q : InstrItinClass; +def IIC_VSHLiD : InstrItinClass; +def IIC_VSHLiQ : InstrItinClass; +def IIC_VSHLi4D : InstrItinClass; +def IIC_VSHLi4Q : InstrItinClass; +def IIC_VPALiD : InstrItinClass; +def IIC_VPALiQ : InstrItinClass; +def IIC_VMULi16D : InstrItinClass; +def IIC_VMULi32D : InstrItinClass; +def IIC_VMULi16Q : InstrItinClass; +def IIC_VMULi32Q : InstrItinClass; +def IIC_VMACi16D : InstrItinClass; +def IIC_VMACi32D : InstrItinClass; +def IIC_VMACi16Q : InstrItinClass; +def IIC_VMACi32Q : InstrItinClass; +def IIC_VEXTD : InstrItinClass; +def IIC_VEXTQ : InstrItinClass; +def IIC_VTB1 : InstrItinClass; +def IIC_VTB2 : InstrItinClass; +def IIC_VTB3 : InstrItinClass; +def IIC_VTB4 : InstrItinClass; +def IIC_VTBX1 : InstrItinClass; +def IIC_VTBX2 : InstrItinClass; +def IIC_VTBX3 : InstrItinClass; +def IIC_VTBX4 : InstrItinClass; + +//===----------------------------------------------------------------------===// +// Processor instruction itineraries. + +def GenericItineraries : ProcessorItineraries<[]>; + + +include "ARMScheduleV6.td" +include "ARMScheduleV7.td" diff --git a/libclamav/c++/llvm/lib/Target/ARM/ARMScheduleV6.td b/libclamav/c++/llvm/lib/Target/ARM/ARMScheduleV6.td new file mode 100644 index 000000000..0fef466ad --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/ARM/ARMScheduleV6.td @@ -0,0 +1,200 @@ +//===- ARMScheduleV6.td - ARM v6 Scheduling Definitions ----*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the itinerary class data for the ARM v6 processors. +// +//===----------------------------------------------------------------------===// + +// Model based on ARM1176 +// +// Scheduling information derived from "ARM1176JZF-S Technical Reference Manual". +// +def ARMV6Itineraries : ProcessorItineraries<[ + // + // No operand cycles + InstrItinData]>, + // + // Binary Instructions that produce a result + InstrItinData], [2, 2]>, + InstrItinData], [2, 2, 2]>, + InstrItinData], [2, 2, 1]>, + InstrItinData], [3, 3, 2, 1]>, + // + // Unary Instructions that produce a result + InstrItinData], [2, 2]>, + InstrItinData], [2, 1]>, + InstrItinData], [3, 2, 1]>, + // + // Compare instructions + InstrItinData], [2]>, + InstrItinData], [2, 2]>, + InstrItinData], [2, 1]>, + InstrItinData], [3, 2, 1]>, + // + // Move instructions, unconditional + InstrItinData], [2]>, + InstrItinData], [2, 2]>, + InstrItinData], [2, 1]>, + InstrItinData], [3, 2, 1]>, + // + // Move instructions, conditional + InstrItinData], [3]>, + InstrItinData], [3, 2]>, + InstrItinData], [3, 1]>, + InstrItinData], [4, 2, 1]>, + + // Integer multiply pipeline + // + InstrItinData], [4, 1, 1]>, + InstrItinData], [4, 1, 1, 2]>, + InstrItinData], [5, 1, 1]>, + InstrItinData], [5, 1, 1, 2]>, + InstrItinData], [6, 1, 1]>, + InstrItinData], [6, 1, 1, 2]>, + + // Integer load pipeline + // + // Immediate offset + InstrItinData], [4, 1]>, + // + // Register offset + InstrItinData], [4, 1, 1]>, + // + // Scaled register offset, issues over 2 cycles + InstrItinData], [5, 2, 1]>, + // + // Immediate offset with update + InstrItinData], [4, 2, 1]>, + // + // Register offset with update + InstrItinData], [4, 2, 1, 1]>, + // + // Scaled register offset with update, issues over 2 cycles + InstrItinData], [5, 2, 2, 1]>, + + // + // Load multiple + InstrItinData]>, + + // Integer store pipeline + // + // Immediate offset + InstrItinData], [2, 1]>, + // + // Register offset + InstrItinData], [2, 1, 1]>, + + // + // Scaled register offset, issues over 2 cycles + InstrItinData], [2, 2, 1]>, + // + // Immediate offset with update + InstrItinData], [2, 2, 1]>, + // + // Register offset with update + InstrItinData], [2, 2, 1, 1]>, + // + // Scaled register offset with update, issues over 2 cycles + InstrItinData], [2, 2, 2, 1]>, + // + // Store multiple + InstrItinData]>, + + // Branch + // + // no delay slots, so the latency of a branch is unimportant + InstrItinData]>, + + // VFP + // Issue through integer pipeline, and execute in NEON unit. We assume + // RunFast mode so that NFP pipeline is used for single-precision when + // possible. + // + // FP Special Register to Integer Register File Move + InstrItinData], [3]>, + // + // Single-precision FP Unary + InstrItinData], [5, 2]>, + // + // Double-precision FP Unary + InstrItinData], [5, 2]>, + // + // Single-precision FP Compare + InstrItinData], [2, 2]>, + // + // Double-precision FP Compare + InstrItinData], [2, 2]>, + // + // Single to Double FP Convert + InstrItinData], [5, 2]>, + // + // Double to Single FP Convert + InstrItinData], [5, 2]>, + // + // Single-Precision FP to Integer Convert + InstrItinData], [9, 2]>, + // + // Double-Precision FP to Integer Convert + InstrItinData], [9, 2]>, + // + // Integer to Single-Precision FP Convert + InstrItinData], [9, 2]>, + // + // Integer to Double-Precision FP Convert + InstrItinData], [9, 2]>, + // + // Single-precision FP ALU + InstrItinData], [9, 2, 2]>, + // + // Double-precision FP ALU + InstrItinData], [9, 2, 2]>, + // + // Single-precision FP Multiply + InstrItinData], [9, 2, 2]>, + // + // Double-precision FP Multiply + InstrItinData], [9, 2, 2]>, + // + // Single-precision FP MAC + InstrItinData], [9, 2, 2, 2]>, + // + // Double-precision FP MAC + InstrItinData], [9, 2, 2, 2]>, + // + // Single-precision FP DIV + InstrItinData], [20, 2, 2]>, + // + // Double-precision FP DIV + InstrItinData], [34, 2, 2]>, + // + // Single-precision FP SQRT + InstrItinData], [20, 2, 2]>, + // + // Double-precision FP SQRT + InstrItinData], [34, 2, 2]>, + // + // Single-precision FP Load + InstrItinData], [5, 2, 2]>, + // + // Double-precision FP Load + InstrItinData], [5, 2, 2]>, + // + // FP Load Multiple + InstrItinData]>, + // + // Single-precision FP Store + InstrItinData], [2, 2, 2]>, + // + // Double-precision FP Store + // use FU_Issue to enforce the 1 load/store per cycle limit + InstrItinData], [2, 2, 2]>, + // + // FP Store Multiple + InstrItinData]> +]>; diff --git a/libclamav/c++/llvm/lib/Target/ARM/ARMScheduleV7.td b/libclamav/c++/llvm/lib/Target/ARM/ARMScheduleV7.td new file mode 100644 index 000000000..bbbf41397 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/ARM/ARMScheduleV7.td @@ -0,0 +1,587 @@ +//===- ARMScheduleV7.td - ARM v7 Scheduling Definitions ----*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the itinerary class data for the ARM v7 processors. +// +//===----------------------------------------------------------------------===// + +// +// Scheduling information derived from "Cortex-A8 Technical Reference Manual". +// +// Dual issue pipeline represented by FU_Pipe0 | FU_Pipe1 +// +def CortexA8Itineraries : ProcessorItineraries<[ + + // Two fully-pipelined integer ALU pipelines + // + // No operand cycles + InstrItinData]>, + // + // Binary Instructions that produce a result + InstrItinData], [2, 2]>, + InstrItinData], [2, 2, 2]>, + InstrItinData], [2, 2, 1]>, + InstrItinData], [2, 2, 1, 1]>, + // + // Unary Instructions that produce a result + InstrItinData], [2, 2]>, + InstrItinData], [2, 1]>, + InstrItinData], [2, 1, 1]>, + // + // Compare instructions + InstrItinData], [2]>, + InstrItinData], [2, 2]>, + InstrItinData], [2, 1]>, + InstrItinData], [2, 1, 1]>, + // + // Move instructions, unconditional + InstrItinData], [1]>, + InstrItinData], [1, 1]>, + InstrItinData], [1, 1]>, + InstrItinData], [1, 1, 1]>, + // + // Move instructions, conditional + InstrItinData], [2]>, + InstrItinData], [2, 1]>, + InstrItinData], [2, 1]>, + InstrItinData], [2, 1, 1]>, + + // Integer multiply pipeline + // Result written in E5, but that is relative to the last cycle of multicycle, + // so we use 6 for those cases + // + InstrItinData], [5, 1, 1]>, + InstrItinData, + InstrStage<2, [FU_Pipe0]>], [6, 1, 1, 4]>, + InstrItinData, + InstrStage<2, [FU_Pipe0]>], [6, 1, 1]>, + InstrItinData, + InstrStage<2, [FU_Pipe0]>], [6, 1, 1, 4]>, + InstrItinData, + InstrStage<3, [FU_Pipe0]>], [6, 6, 1, 1]>, + InstrItinData, + InstrStage<3, [FU_Pipe0]>], [6, 6, 1, 1]>, + + // Integer load pipeline + // + // loads have an extra cycle of latency, but are fully pipelined + // use FU_Issue to enforce the 1 load/store per cycle limit + // + // Immediate offset + InstrItinData, + InstrStage<1, [FU_Pipe0, FU_Pipe1]>, + InstrStage<1, [FU_LdSt0]>], [3, 1]>, + // + // Register offset + InstrItinData, + InstrStage<1, [FU_Pipe0, FU_Pipe1]>, + InstrStage<1, [FU_LdSt0]>], [3, 1, 1]>, + // + // Scaled register offset, issues over 2 cycles + InstrItinData, + InstrStage<1, [FU_Pipe0], 0>, + InstrStage<1, [FU_Pipe1]>, + InstrStage<1, [FU_Pipe0, FU_Pipe1]>, + InstrStage<1, [FU_LdSt0]>], [4, 1, 1]>, + // + // Immediate offset with update + InstrItinData, + InstrStage<1, [FU_Pipe0, FU_Pipe1]>, + InstrStage<1, [FU_LdSt0]>], [3, 2, 1]>, + // + // Register offset with update + InstrItinData, + InstrStage<1, [FU_Pipe0, FU_Pipe1]>, + InstrStage<1, [FU_LdSt0]>], [3, 2, 1, 1]>, + // + // Scaled register offset with update, issues over 2 cycles + InstrItinData, + InstrStage<1, [FU_Pipe0], 0>, + InstrStage<1, [FU_Pipe1]>, + InstrStage<1, [FU_Pipe0, FU_Pipe1]>, + InstrStage<1, [FU_LdSt0]>], [4, 3, 1, 1]>, + // + // Load multiple + InstrItinData, + InstrStage<2, [FU_Pipe0], 0>, + InstrStage<2, [FU_Pipe1]>, + InstrStage<1, [FU_Pipe0, FU_Pipe1]>, + InstrStage<1, [FU_LdSt0]>]>, + + // Integer store pipeline + // + // use FU_Issue to enforce the 1 load/store per cycle limit + // + // Immediate offset + InstrItinData, + InstrStage<1, [FU_Pipe0, FU_Pipe1]>, + InstrStage<1, [FU_LdSt0]>], [3, 1]>, + // + // Register offset + InstrItinData, + InstrStage<1, [FU_Pipe0, FU_Pipe1]>, + InstrStage<1, [FU_LdSt0]>], [3, 1, 1]>, + // + // Scaled register offset, issues over 2 cycles + InstrItinData, + InstrStage<1, [FU_Pipe0], 0>, + InstrStage<1, [FU_Pipe1]>, + InstrStage<1, [FU_Pipe0, FU_Pipe1]>, + InstrStage<1, [FU_LdSt0]>], [3, 1, 1]>, + // + // Immediate offset with update + InstrItinData, + InstrStage<1, [FU_Pipe0, FU_Pipe1]>, + InstrStage<1, [FU_LdSt0]>], [2, 3, 1]>, + // + // Register offset with update + InstrItinData, + InstrStage<1, [FU_Pipe0, FU_Pipe1]>, + InstrStage<1, [FU_LdSt0]>], [2, 3, 1, 1]>, + // + // Scaled register offset with update, issues over 2 cycles + InstrItinData, + InstrStage<1, [FU_Pipe0], 0>, + InstrStage<1, [FU_Pipe1]>, + InstrStage<1, [FU_Pipe0, FU_Pipe1]>, + InstrStage<1, [FU_LdSt0]>], [3, 3, 1, 1]>, + // + // Store multiple + InstrItinData, + InstrStage<2, [FU_Pipe0], 0>, + InstrStage<2, [FU_Pipe1]>, + InstrStage<1, [FU_Pipe0, FU_Pipe1]>, + InstrStage<1, [FU_LdSt0]>]>, + + // Branch + // + // no delay slots, so the latency of a branch is unimportant + InstrItinData]>, + + // VFP + // Issue through integer pipeline, and execute in NEON unit. We assume + // RunFast mode so that NFP pipeline is used for single-precision when + // possible. + // + // FP Special Register to Integer Register File Move + InstrItinData, + InstrStage<1, [FU_NLSPipe]>]>, + // + // Single-precision FP Unary + InstrItinData, + InstrStage<1, [FU_NPipe]>], [7, 1]>, + // + // Double-precision FP Unary + InstrItinData, + InstrStage<4, [FU_NPipe], 0>, + InstrStage<4, [FU_NLSPipe]>], [4, 1]>, + // + // Single-precision FP Compare + InstrItinData, + InstrStage<1, [FU_NPipe]>], [1, 1]>, + // + // Double-precision FP Compare + InstrItinData, + InstrStage<4, [FU_NPipe], 0>, + InstrStage<4, [FU_NLSPipe]>], [4, 1]>, + // + // Single to Double FP Convert + InstrItinData, + InstrStage<7, [FU_NPipe], 0>, + InstrStage<7, [FU_NLSPipe]>], [7, 1]>, + // + // Double to Single FP Convert + InstrItinData, + InstrStage<5, [FU_NPipe], 0>, + InstrStage<5, [FU_NLSPipe]>], [5, 1]>, + // + // Single-Precision FP to Integer Convert + InstrItinData, + InstrStage<1, [FU_NPipe]>], [7, 1]>, + // + // Double-Precision FP to Integer Convert + InstrItinData, + InstrStage<8, [FU_NPipe], 0>, + InstrStage<8, [FU_NLSPipe]>], [8, 1]>, + // + // Integer to Single-Precision FP Convert + InstrItinData, + InstrStage<1, [FU_NPipe]>], [7, 1]>, + // + // Integer to Double-Precision FP Convert + InstrItinData, + InstrStage<8, [FU_NPipe], 0>, + InstrStage<8, [FU_NLSPipe]>], [8, 1]>, + // + // Single-precision FP ALU + InstrItinData, + InstrStage<1, [FU_NPipe]>], [7, 1, 1]>, + // + // Double-precision FP ALU + InstrItinData, + InstrStage<9, [FU_NPipe], 0>, + InstrStage<9, [FU_NLSPipe]>], [9, 1, 1]>, + // + // Single-precision FP Multiply + InstrItinData, + InstrStage<1, [FU_NPipe]>], [7, 1, 1]>, + // + // Double-precision FP Multiply + InstrItinData, + InstrStage<11, [FU_NPipe], 0>, + InstrStage<11, [FU_NLSPipe]>], [11, 1, 1]>, + // + // Single-precision FP MAC + InstrItinData, + InstrStage<1, [FU_NPipe]>], [7, 2, 1, 1]>, + // + // Double-precision FP MAC + InstrItinData, + InstrStage<19, [FU_NPipe], 0>, + InstrStage<19, [FU_NLSPipe]>], [19, 2, 1, 1]>, + // + // Single-precision FP DIV + InstrItinData, + InstrStage<20, [FU_NPipe], 0>, + InstrStage<20, [FU_NLSPipe]>], [20, 1, 1]>, + // + // Double-precision FP DIV + InstrItinData, + InstrStage<29, [FU_NPipe], 0>, + InstrStage<29, [FU_NLSPipe]>], [29, 1, 1]>, + // + // Single-precision FP SQRT + InstrItinData, + InstrStage<19, [FU_NPipe], 0>, + InstrStage<19, [FU_NLSPipe]>], [19, 1]>, + // + // Double-precision FP SQRT + InstrItinData, + InstrStage<29, [FU_NPipe], 0>, + InstrStage<29, [FU_NLSPipe]>], [29, 1]>, + // + // Single-precision FP Load + // use FU_Issue to enforce the 1 load/store per cycle limit + InstrItinData, + InstrStage<1, [FU_Pipe0, FU_Pipe1]>, + InstrStage<1, [FU_LdSt0], 0>, + InstrStage<1, [FU_NLSPipe]>]>, + // + // Double-precision FP Load + // use FU_Issue to enforce the 1 load/store per cycle limit + InstrItinData, + InstrStage<1, [FU_Pipe0], 0>, + InstrStage<1, [FU_Pipe1]>, + InstrStage<1, [FU_Pipe0, FU_Pipe1]>, + InstrStage<1, [FU_LdSt0], 0>, + InstrStage<1, [FU_NLSPipe]>]>, + // + // FP Load Multiple + // use FU_Issue to enforce the 1 load/store per cycle limit + InstrItinData, + InstrStage<2, [FU_Pipe0], 0>, + InstrStage<2, [FU_Pipe1]>, + InstrStage<1, [FU_Pipe0, FU_Pipe1]>, + InstrStage<1, [FU_LdSt0], 0>, + InstrStage<1, [FU_NLSPipe]>]>, + // + // Single-precision FP Store + // use FU_Issue to enforce the 1 load/store per cycle limit + InstrItinData, + InstrStage<1, [FU_Pipe0, FU_Pipe1]>, + InstrStage<1, [FU_LdSt0], 0>, + InstrStage<1, [FU_NLSPipe]>]>, + // + // Double-precision FP Store + // use FU_Issue to enforce the 1 load/store per cycle limit + InstrItinData, + InstrStage<1, [FU_Pipe0], 0>, + InstrStage<1, [FU_Pipe1]>, + InstrStage<1, [FU_Pipe0, FU_Pipe1]>, + InstrStage<1, [FU_LdSt0], 0>, + InstrStage<1, [FU_NLSPipe]>]>, + // + // FP Store Multiple + // use FU_Issue to enforce the 1 load/store per cycle limit + InstrItinData, + InstrStage<2, [FU_Pipe0], 0>, + InstrStage<2, [FU_Pipe1]>, + InstrStage<1, [FU_Pipe0, FU_Pipe1]>, + InstrStage<1, [FU_LdSt0], 0>, + InstrStage<1, [FU_NLSPipe]>]>, + + // NEON + // Issue through integer pipeline, and execute in NEON unit. + // + // VLD1 + InstrItinData, + InstrStage<1, [FU_Pipe0, FU_Pipe1]>, + InstrStage<1, [FU_LdSt0], 0>, + InstrStage<1, [FU_NLSPipe]>]>, + // + // VLD2 + InstrItinData, + InstrStage<1, [FU_Pipe0, FU_Pipe1]>, + InstrStage<1, [FU_LdSt0], 0>, + InstrStage<1, [FU_NLSPipe]>], [2, 2, 1]>, + // + // VLD3 + InstrItinData, + InstrStage<1, [FU_Pipe0, FU_Pipe1]>, + InstrStage<1, [FU_LdSt0], 0>, + InstrStage<1, [FU_NLSPipe]>], [2, 2, 2, 1]>, + // + // VLD4 + InstrItinData, + InstrStage<1, [FU_Pipe0, FU_Pipe1]>, + InstrStage<1, [FU_LdSt0], 0>, + InstrStage<1, [FU_NLSPipe]>], [2, 2, 2, 2, 1]>, + // + // VST + InstrItinData, + InstrStage<1, [FU_Pipe0, FU_Pipe1]>, + InstrStage<1, [FU_LdSt0], 0>, + InstrStage<1, [FU_NLSPipe]>]>, + // + // Double-register FP Unary + InstrItinData, + InstrStage<1, [FU_NPipe]>], [5, 2]>, + // + // Quad-register FP Unary + // Result written in N5, but that is relative to the last cycle of multicycle, + // so we use 6 for those cases + InstrItinData, + InstrStage<2, [FU_NPipe]>], [6, 2]>, + // + // Double-register FP Binary + InstrItinData, + InstrStage<1, [FU_NPipe]>], [5, 2, 2]>, + // + // Quad-register FP Binary + // Result written in N5, but that is relative to the last cycle of multicycle, + // so we use 6 for those cases + InstrItinData, + InstrStage<2, [FU_NPipe]>], [6, 2, 2]>, + // + // Move Immediate + InstrItinData, + InstrStage<1, [FU_NPipe]>], [3]>, + // + // Double-register Permute Move + InstrItinData, + InstrStage<1, [FU_NLSPipe]>], [2, 1]>, + // + // Quad-register Permute Move + // Result written in N2, but that is relative to the last cycle of multicycle, + // so we use 3 for those cases + InstrItinData, + InstrStage<2, [FU_NLSPipe]>], [3, 1]>, + // + // Integer to Single-precision Move + InstrItinData, + InstrStage<1, [FU_NLSPipe]>], [2, 1]>, + // + // Integer to Double-precision Move + InstrItinData, + InstrStage<1, [FU_NLSPipe]>], [2, 1, 1]>, + // + // Single-precision to Integer Move + InstrItinData, + InstrStage<1, [FU_NLSPipe]>], [20, 1]>, + // + // Double-precision to Integer Move + InstrItinData, + InstrStage<1, [FU_NLSPipe]>], [20, 20, 1]>, + // + // Integer to Lane Move + InstrItinData, + InstrStage<2, [FU_NLSPipe]>], [3, 1, 1]>, + // + // Double-register Permute + InstrItinData, + InstrStage<1, [FU_NLSPipe]>], [2, 2, 1, 1]>, + // + // Quad-register Permute + // Result written in N2, but that is relative to the last cycle of multicycle, + // so we use 3 for those cases + InstrItinData, + InstrStage<2, [FU_NLSPipe]>], [3, 3, 1, 1]>, + // + // Quad-register Permute (3 cycle issue) + // Result written in N2, but that is relative to the last cycle of multicycle, + // so we use 4 for those cases + InstrItinData, + InstrStage<1, [FU_NLSPipe]>, + InstrStage<1, [FU_NPipe], 0>, + InstrStage<2, [FU_NLSPipe]>], [4, 4, 1, 1]>, + // + // Double-register FP Multiple-Accumulate + InstrItinData, + InstrStage<1, [FU_NPipe]>], [9, 2, 2, 3]>, + // + // Quad-register FP Multiple-Accumulate + // Result written in N9, but that is relative to the last cycle of multicycle, + // so we use 10 for those cases + InstrItinData, + InstrStage<2, [FU_NPipe]>], [10, 2, 2, 3]>, + // + // Double-register Reciprical Step + InstrItinData, + InstrStage<1, [FU_NPipe]>], [9, 2, 2]>, + // + // Quad-register Reciprical Step + InstrItinData, + InstrStage<2, [FU_NPipe]>], [10, 2, 2]>, + // + // Double-register Integer Count + InstrItinData, + InstrStage<1, [FU_NPipe]>], [3, 2, 2]>, + // + // Quad-register Integer Count + // Result written in N3, but that is relative to the last cycle of multicycle, + // so we use 4 for those cases + InstrItinData, + InstrStage<2, [FU_NPipe]>], [4, 2, 2]>, + // + // Double-register Integer Unary + InstrItinData, + InstrStage<1, [FU_NPipe]>], [4, 2]>, + // + // Quad-register Integer Unary + InstrItinData, + InstrStage<1, [FU_NPipe]>], [4, 2]>, + // + // Double-register Integer Q-Unary + InstrItinData, + InstrStage<1, [FU_NPipe]>], [4, 1]>, + // + // Quad-register Integer CountQ-Unary + InstrItinData, + InstrStage<1, [FU_NPipe]>], [4, 1]>, + // + // Double-register Integer Binary + InstrItinData, + InstrStage<1, [FU_NPipe]>], [3, 2, 2]>, + // + // Quad-register Integer Binary + InstrItinData, + InstrStage<1, [FU_NPipe]>], [3, 2, 2]>, + // + // Double-register Integer Binary (4 cycle) + InstrItinData, + InstrStage<1, [FU_NPipe]>], [4, 2, 1]>, + // + // Quad-register Integer Binary (4 cycle) + InstrItinData, + InstrStage<1, [FU_NPipe]>], [4, 2, 1]>, + // + // Double-register Integer Subtract + InstrItinData, + InstrStage<1, [FU_NPipe]>], [3, 2, 1]>, + // + // Quad-register Integer Subtract + InstrItinData, + InstrStage<1, [FU_NPipe]>], [3, 2, 1]>, + // + // Double-register Integer Shift + InstrItinData, + InstrStage<1, [FU_NPipe]>], [3, 1, 1]>, + // + // Quad-register Integer Shift + InstrItinData, + InstrStage<2, [FU_NPipe]>], [4, 1, 1]>, + // + // Double-register Integer Shift (4 cycle) + InstrItinData, + InstrStage<1, [FU_NPipe]>], [4, 1, 1]>, + // + // Quad-register Integer Shift (4 cycle) + InstrItinData, + InstrStage<2, [FU_NPipe]>], [5, 1, 1]>, + // + // Double-register Integer Pair Add Long + InstrItinData, + InstrStage<1, [FU_NPipe]>], [6, 3, 2, 1]>, + // + // Quad-register Integer Pair Add Long + InstrItinData, + InstrStage<2, [FU_NPipe]>], [7, 3, 2, 1]>, + // + // Double-register Integer Multiply (.8, .16) + InstrItinData, + InstrStage<1, [FU_NPipe]>], [6, 2, 2]>, + // + // Double-register Integer Multiply (.32) + InstrItinData, + InstrStage<2, [FU_NPipe]>], [7, 2, 1]>, + // + // Quad-register Integer Multiply (.8, .16) + InstrItinData, + InstrStage<2, [FU_NPipe]>], [7, 2, 2]>, + // + // Quad-register Integer Multiply (.32) + InstrItinData, + InstrStage<1, [FU_NPipe]>, + InstrStage<2, [FU_NLSPipe], 0>, + InstrStage<3, [FU_NPipe]>], [9, 2, 1]>, + // + // Double-register Integer Multiply-Accumulate (.8, .16) + InstrItinData, + InstrStage<1, [FU_NPipe]>], [6, 2, 2, 3]>, + // + // Double-register Integer Multiply-Accumulate (.32) + InstrItinData, + InstrStage<2, [FU_NPipe]>], [7, 2, 1, 3]>, + // + // Quad-register Integer Multiply-Accumulate (.8, .16) + InstrItinData, + InstrStage<2, [FU_NPipe]>], [7, 2, 2, 3]>, + // + // Quad-register Integer Multiply-Accumulate (.32) + InstrItinData, + InstrStage<1, [FU_NPipe]>, + InstrStage<2, [FU_NLSPipe], 0>, + InstrStage<3, [FU_NPipe]>], [9, 2, 1, 3]>, + // + // Double-register VEXT + InstrItinData, + InstrStage<1, [FU_NLSPipe]>], [2, 1, 1]>, + // + // Quad-register VEXT + InstrItinData, + InstrStage<2, [FU_NLSPipe]>], [3, 1, 1]>, + // + // VTB + InstrItinData, + InstrStage<2, [FU_NLSPipe]>], [3, 2, 1]>, + InstrItinData, + InstrStage<2, [FU_NLSPipe]>], [3, 2, 2, 1]>, + InstrItinData, + InstrStage<1, [FU_NLSPipe]>, + InstrStage<1, [FU_NPipe], 0>, + InstrStage<2, [FU_NLSPipe]>], [4, 2, 2, 3, 1]>, + InstrItinData, + InstrStage<1, [FU_NLSPipe]>, + InstrStage<1, [FU_NPipe], 0>, + InstrStage<2, [FU_NLSPipe]>], [4, 2, 2, 3, 3, 1]>, + // + // VTBX + InstrItinData, + InstrStage<2, [FU_NLSPipe]>], [3, 1, 2, 1]>, + InstrItinData, + InstrStage<2, [FU_NLSPipe]>], [3, 1, 2, 2, 1]>, + InstrItinData, + InstrStage<1, [FU_NLSPipe]>, + InstrStage<1, [FU_NPipe], 0>, + InstrStage<2, [FU_NLSPipe]>], [4, 1, 2, 2, 3, 1]>, + InstrItinData, + InstrStage<1, [FU_NLSPipe]>, + InstrStage<1, [FU_NPipe], 0>, + InstrStage<2, [FU_NLSPipe]>], [4, 1, 2, 2, 3, 3, 1]> +]>; diff --git a/libclamav/c++/llvm/lib/Target/ARM/ARMSubtarget.cpp b/libclamav/c++/llvm/lib/Target/ARM/ARMSubtarget.cpp new file mode 100644 index 000000000..d6b072b6c --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/ARM/ARMSubtarget.cpp @@ -0,0 +1,179 @@ +//===-- ARMSubtarget.cpp - ARM Subtarget Information ------------*- 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 the ARM specific subclass of TargetSubtarget. +// +//===----------------------------------------------------------------------===// + +#include "ARMSubtarget.h" +#include "ARMGenSubtarget.inc" +#include "llvm/GlobalValue.h" +#include "llvm/Target/TargetOptions.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/ADT/SmallVector.h" +using namespace llvm; + +static cl::opt +ReserveR9("arm-reserve-r9", cl::Hidden, + cl::desc("Reserve R9, making it unavailable as GPR")); +static cl::opt +UseNEONFP("arm-use-neon-fp", + cl::desc("Use NEON for single-precision FP"), + cl::init(false), cl::Hidden); + +static cl::opt +UseMOVT("arm-use-movt", + cl::init(true), cl::Hidden); + +ARMSubtarget::ARMSubtarget(const std::string &TT, const std::string &FS, + bool isT) + : ARMArchVersion(V4T) + , ARMFPUType(None) + , UseNEONForSinglePrecisionFP(UseNEONFP) + , IsThumb(isT) + , ThumbMode(Thumb1) + , PostRAScheduler(false) + , IsR9Reserved(ReserveR9) + , UseMovt(UseMOVT) + , stackAlignment(4) + , CPUString("generic") + , TargetType(isELF) // Default to ELF unless otherwise specified. + , TargetABI(ARM_ABI_APCS) { + // default to soft float ABI + if (FloatABIType == FloatABI::Default) + FloatABIType = FloatABI::Soft; + + // Determine default and user specified characteristics + + // Parse features string. + CPUString = ParseSubtargetFeatures(FS, CPUString); + + // Set the boolean corresponding to the current target triple, or the default + // if one cannot be determined, to true. + unsigned Len = TT.length(); + unsigned Idx = 0; + + if (Len >= 5 && TT.substr(0, 4) == "armv") + Idx = 4; + else if (Len >= 6 && TT.substr(0, 5) == "thumb") { + IsThumb = true; + if (Len >= 7 && TT[5] == 'v') + Idx = 6; + } + if (Idx) { + unsigned SubVer = TT[Idx]; + if (SubVer > '4' && SubVer <= '9') { + if (SubVer >= '7') { + ARMArchVersion = V7A; + } else if (SubVer == '6') { + ARMArchVersion = V6; + if (Len >= Idx+3 && TT[Idx+1] == 't' && TT[Idx+2] == '2') + ARMArchVersion = V6T2; + } else if (SubVer == '5') { + ARMArchVersion = V5T; + if (Len >= Idx+3 && TT[Idx+1] == 't' && TT[Idx+2] == 'e') + ARMArchVersion = V5TE; + } + if (ARMArchVersion >= V6T2) + ThumbMode = Thumb2; + } + } + + // Thumb2 implies at least V6T2. + if (ARMArchVersion < V6T2 && ThumbMode >= Thumb2) + ARMArchVersion = V6T2; + + if (Len >= 10) { + if (TT.find("-darwin") != std::string::npos) + // arm-darwin + TargetType = isDarwin; + } + + if (TT.find("eabi") != std::string::npos) + TargetABI = ARM_ABI_AAPCS; + + if (isAAPCS_ABI()) + stackAlignment = 8; + + if (isTargetDarwin()) + IsR9Reserved = ReserveR9 | (ARMArchVersion < V6); + + if (!isThumb() || hasThumb2()) + PostRAScheduler = true; + + // Set CPU specific features. + if (CPUString == "cortex-a8") { + // On Cortex-a8, it's faster to perform some single-precision FP + // operations with NEON instructions. + if (UseNEONFP.getPosition() == 0) + UseNEONForSinglePrecisionFP = true; + } + HasBranchTargetBuffer = (CPUString == "cortex-a8" || + CPUString == "cortex-a9"); +} + +/// GVIsIndirectSymbol - true if the GV will be accessed via an indirect symbol. +bool +ARMSubtarget::GVIsIndirectSymbol(GlobalValue *GV, Reloc::Model RelocM) const { + if (RelocM == Reloc::Static) + return false; + + // GV with ghost linkage (in JIT lazy compilation mode) do not require an + // extra load from stub. + bool isDecl = GV->isDeclaration() && !GV->hasNotBeenReadFromBitcode(); + + if (!isTargetDarwin()) { + // Extra load is needed for all externally visible. + if (GV->hasLocalLinkage() || GV->hasHiddenVisibility()) + return false; + return true; + } else { + if (RelocM == Reloc::PIC_) { + // If this is a strong reference to a definition, it is definitely not + // through a stub. + if (!isDecl && !GV->isWeakForLinker()) + return false; + + // Unless we have a symbol with hidden visibility, we have to go through a + // normal $non_lazy_ptr stub because this symbol might be resolved late. + if (!GV->hasHiddenVisibility()) // Non-hidden $non_lazy_ptr reference. + return true; + + // If symbol visibility is hidden, we have a stub for common symbol + // references and external declarations. + if (isDecl || GV->hasCommonLinkage()) + // Hidden $non_lazy_ptr reference. + return true; + + return false; + } else { + // If this is a strong reference to a definition, it is definitely not + // through a stub. + if (!isDecl && !GV->isWeakForLinker()) + return false; + + // Unless we have a symbol with hidden visibility, we have to go through a + // normal $non_lazy_ptr stub because this symbol might be resolved late. + if (!GV->hasHiddenVisibility()) // Non-hidden $non_lazy_ptr reference. + return true; + } + } + + return false; +} + +bool ARMSubtarget::enablePostRAScheduler( + CodeGenOpt::Level OptLevel, + TargetSubtarget::AntiDepBreakMode& Mode, + RegClassVector& CriticalPathRCs) const { + Mode = TargetSubtarget::ANTIDEP_CRITICAL; + CriticalPathRCs.clear(); + CriticalPathRCs.push_back(&ARM::GPRRegClass); + return PostRAScheduler && OptLevel >= CodeGenOpt::Default; +} diff --git a/libclamav/c++/llvm/lib/Target/ARM/ARMSubtarget.h b/libclamav/c++/llvm/lib/Target/ARM/ARMSubtarget.h new file mode 100644 index 000000000..b2467b073 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/ARM/ARMSubtarget.h @@ -0,0 +1,161 @@ +//=====---- ARMSubtarget.h - Define Subtarget for the ARM -----*- C++ -*--====// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the ARM specific subclass of TargetSubtarget. +// +//===----------------------------------------------------------------------===// + +#ifndef ARMSUBTARGET_H +#define ARMSUBTARGET_H + +#include "llvm/Target/TargetInstrItineraries.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetSubtarget.h" +#include "ARMBaseRegisterInfo.h" +#include + +namespace llvm { +class GlobalValue; + +class ARMSubtarget : public TargetSubtarget { +protected: + enum ARMArchEnum { + V4T, V5T, V5TE, V6, V6T2, V7A + }; + + enum ARMFPEnum { + None, VFPv2, VFPv3, NEON + }; + + enum ThumbTypeEnum { + Thumb1, + Thumb2 + }; + + /// ARMArchVersion - ARM architecture version: V4T (base), V5T, V5TE, + /// V6, V6T2, V7A. + ARMArchEnum ARMArchVersion; + + /// ARMFPUType - Floating Point Unit type. + ARMFPEnum ARMFPUType; + + /// UseNEONForSinglePrecisionFP - if the NEONFP attribute has been + /// specified. Use the method useNEONForSinglePrecisionFP() to + /// determine if NEON should actually be used. + bool UseNEONForSinglePrecisionFP; + + /// HasBranchTargetBuffer - True if processor can predict indirect branches. + bool HasBranchTargetBuffer; + + /// IsThumb - True if we are in thumb mode, false if in ARM mode. + bool IsThumb; + + /// ThumbMode - Indicates supported Thumb version. + ThumbTypeEnum ThumbMode; + + /// PostRAScheduler - True if using post-register-allocation scheduler. + bool PostRAScheduler; + + /// IsR9Reserved - True if R9 is a not available as general purpose register. + bool IsR9Reserved; + + /// UseMovt - True if MOVT / MOVW pairs are used for materialization of 32-bit + /// imms (including global addresses). + bool UseMovt; + + /// stackAlignment - The minimum alignment known to hold of the stack frame on + /// entry to the function and which must be maintained by every function. + unsigned stackAlignment; + + /// CPUString - String name of used CPU. + std::string CPUString; + + /// Selected instruction itineraries (one entry per itinerary class.) + InstrItineraryData InstrItins; + + public: + enum { + isELF, isDarwin + } TargetType; + + enum { + ARM_ABI_APCS, + ARM_ABI_AAPCS // ARM EABI + } TargetABI; + + /// This constructor initializes the data members to match that + /// of the specified triple. + /// + ARMSubtarget(const std::string &TT, const std::string &FS, bool isThumb); + + /// getMaxInlineSizeThreshold - Returns the maximum memset / memcpy size + /// that still makes it profitable to inline the call. + unsigned getMaxInlineSizeThreshold() const { + // FIXME: For now, we don't lower memcpy's to loads / stores for Thumb. + // Change this once Thumb ldmia / stmia support is added. + return isThumb() ? 0 : 64; + } + /// ParseSubtargetFeatures - Parses features string setting specified + /// subtarget options. Definition of function is auto generated by tblgen. + std::string ParseSubtargetFeatures(const std::string &FS, + const std::string &CPU); + + bool hasV4TOps() const { return ARMArchVersion >= V4T; } + bool hasV5TOps() const { return ARMArchVersion >= V5T; } + bool hasV5TEOps() const { return ARMArchVersion >= V5TE; } + bool hasV6Ops() const { return ARMArchVersion >= V6; } + bool hasV6T2Ops() const { return ARMArchVersion >= V6T2; } + bool hasV7Ops() const { return ARMArchVersion >= V7A; } + + bool hasVFP2() const { return ARMFPUType >= VFPv2; } + bool hasVFP3() const { return ARMFPUType >= VFPv3; } + bool hasNEON() const { return ARMFPUType >= NEON; } + bool useNEONForSinglePrecisionFP() const { + return hasNEON() && UseNEONForSinglePrecisionFP; } + + bool isTargetDarwin() const { return TargetType == isDarwin; } + bool isTargetELF() const { return TargetType == isELF; } + + bool isAPCS_ABI() const { return TargetABI == ARM_ABI_APCS; } + bool isAAPCS_ABI() const { return TargetABI == ARM_ABI_AAPCS; } + + bool isThumb() const { return IsThumb; } + bool isThumb1Only() const { return IsThumb && (ThumbMode == Thumb1); } + bool isThumb2() const { return IsThumb && (ThumbMode == Thumb2); } + bool hasThumb2() const { return ThumbMode >= Thumb2; } + + bool hasBranchTargetBuffer() const { return HasBranchTargetBuffer; } + + bool isR9Reserved() const { return IsR9Reserved; } + + bool useMovt() const { return UseMovt && hasV6T2Ops(); } + + const std::string & getCPUString() const { return CPUString; } + + /// enablePostRAScheduler - True at 'More' optimization. + bool enablePostRAScheduler(CodeGenOpt::Level OptLevel, + TargetSubtarget::AntiDepBreakMode& Mode, + RegClassVector& CriticalPathRCs) const; + + /// getInstrItins - Return the instruction itineraies based on subtarget + /// selection. + const InstrItineraryData &getInstrItineraryData() const { return InstrItins; } + + /// getStackAlignment - Returns the minimum alignment known to hold of the + /// stack frame on entry to the function and which must be maintained by every + /// function for this subtarget. + unsigned getStackAlignment() const { return stackAlignment; } + + /// GVIsIndirectSymbol - true if the GV will be accessed via an indirect + /// symbol. + bool GVIsIndirectSymbol(GlobalValue *GV, Reloc::Model RelocM) const; +}; +} // End llvm namespace + +#endif // ARMSUBTARGET_H diff --git a/libclamav/c++/llvm/lib/Target/ARM/ARMTargetMachine.cpp b/libclamav/c++/llvm/lib/Target/ARM/ARMTargetMachine.cpp new file mode 100644 index 000000000..2564ed925 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/ARM/ARMTargetMachine.cpp @@ -0,0 +1,197 @@ +//===-- ARMTargetMachine.cpp - Define TargetMachine for ARM ---------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// +//===----------------------------------------------------------------------===// + +#include "ARMTargetMachine.h" +#include "ARMMCAsmInfo.h" +#include "ARMFrameInfo.h" +#include "ARM.h" +#include "llvm/PassManager.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/Support/FormattedStream.h" +#include "llvm/Target/TargetOptions.h" +#include "llvm/Target/TargetRegistry.h" +using namespace llvm; + +static const MCAsmInfo *createMCAsmInfo(const Target &T, StringRef TT) { + Triple TheTriple(TT); + switch (TheTriple.getOS()) { + case Triple::Darwin: + return new ARMMCAsmInfoDarwin(); + default: + return new ARMELFMCAsmInfo(); + } +} + + +extern "C" void LLVMInitializeARMTarget() { + // Register the target. + RegisterTargetMachine X(TheARMTarget); + RegisterTargetMachine Y(TheThumbTarget); + + // Register the target asm info. + RegisterAsmInfoFn A(TheARMTarget, createMCAsmInfo); + RegisterAsmInfoFn B(TheThumbTarget, createMCAsmInfo); +} + +/// TargetMachine ctor - Create an ARM architecture model. +/// +ARMBaseTargetMachine::ARMBaseTargetMachine(const Target &T, + const std::string &TT, + const std::string &FS, + bool isThumb) + : LLVMTargetMachine(T, TT), + Subtarget(TT, FS, isThumb), + FrameInfo(Subtarget), + JITInfo(), + InstrItins(Subtarget.getInstrItineraryData()) { + DefRelocModel = getRelocationModel(); +} + +ARMTargetMachine::ARMTargetMachine(const Target &T, const std::string &TT, + const std::string &FS) + : ARMBaseTargetMachine(T, TT, FS, false), InstrInfo(Subtarget), + DataLayout(Subtarget.isAPCS_ABI() ? + std::string("e-p:32:32-f64:32:32-i64:32:32-n32") : + std::string("e-p:32:32-f64:64:64-i64:64:64-n32")), + TLInfo(*this) { +} + +ThumbTargetMachine::ThumbTargetMachine(const Target &T, const std::string &TT, + const std::string &FS) + : ARMBaseTargetMachine(T, TT, FS, true), + InstrInfo(Subtarget.hasThumb2() + ? ((ARMBaseInstrInfo*)new Thumb2InstrInfo(Subtarget)) + : ((ARMBaseInstrInfo*)new Thumb1InstrInfo(Subtarget))), + DataLayout(Subtarget.isAPCS_ABI() ? + std::string("e-p:32:32-f64:32:32-i64:32:32-" + "i16:16:32-i8:8:32-i1:8:32-a:0:32-n32") : + std::string("e-p:32:32-f64:64:64-i64:64:64-" + "i16:16:32-i8:8:32-i1:8:32-a:0:32-n32")), + TLInfo(*this) { +} + + + +// Pass Pipeline Configuration +bool ARMBaseTargetMachine::addInstSelector(PassManagerBase &PM, + CodeGenOpt::Level OptLevel) { + PM.add(createARMISelDag(*this, OptLevel)); + return false; +} + +bool ARMBaseTargetMachine::addPreRegAlloc(PassManagerBase &PM, + CodeGenOpt::Level OptLevel) { + if (Subtarget.hasNEON()) + PM.add(createNEONPreAllocPass()); + + // Calculate and set max stack object alignment early, so we can decide + // whether we will need stack realignment (and thus FP). + PM.add(createARMMaxStackAlignmentCalculatorPass()); + + // FIXME: temporarily disabling load / store optimization pass for Thumb1. + if (OptLevel != CodeGenOpt::None && !Subtarget.isThumb1Only()) + PM.add(createARMLoadStoreOptimizationPass(true)); + return true; +} + +bool ARMBaseTargetMachine::addPreSched2(PassManagerBase &PM, + CodeGenOpt::Level OptLevel) { + // FIXME: temporarily disabling load / store optimization pass for Thumb1. + if (OptLevel != CodeGenOpt::None && !Subtarget.isThumb1Only()) + PM.add(createARMLoadStoreOptimizationPass()); + + // Expand some pseudo instructions into multiple instructions to allow + // proper scheduling. + PM.add(createARMExpandPseudoPass()); + + return true; +} + +bool ARMBaseTargetMachine::addPreEmitPass(PassManagerBase &PM, + CodeGenOpt::Level OptLevel) { + // FIXME: temporarily disabling load / store optimization pass for Thumb1. + if (OptLevel != CodeGenOpt::None) { + if (!Subtarget.isThumb1Only()) + PM.add(createIfConverterPass()); + if (Subtarget.hasNEON()) + PM.add(createNEONMoveFixPass()); + } + + if (Subtarget.isThumb2()) { + PM.add(createThumb2ITBlockPass()); + PM.add(createThumb2SizeReductionPass()); + } + + PM.add(createARMConstantIslandPass()); + return true; +} + +bool ARMBaseTargetMachine::addCodeEmitter(PassManagerBase &PM, + CodeGenOpt::Level OptLevel, + MachineCodeEmitter &MCE) { + // FIXME: Move this to TargetJITInfo! + if (DefRelocModel == Reloc::Default) + setRelocationModel(Reloc::Static); + + // Machine code emitter pass for ARM. + PM.add(createARMCodeEmitterPass(*this, MCE)); + return false; +} + +bool ARMBaseTargetMachine::addCodeEmitter(PassManagerBase &PM, + CodeGenOpt::Level OptLevel, + JITCodeEmitter &JCE) { + // FIXME: Move this to TargetJITInfo! + if (DefRelocModel == Reloc::Default) + setRelocationModel(Reloc::Static); + + // Machine code emitter pass for ARM. + PM.add(createARMJITCodeEmitterPass(*this, JCE)); + return false; +} + +bool ARMBaseTargetMachine::addCodeEmitter(PassManagerBase &PM, + CodeGenOpt::Level OptLevel, + ObjectCodeEmitter &OCE) { + // FIXME: Move this to TargetJITInfo! + if (DefRelocModel == Reloc::Default) + setRelocationModel(Reloc::Static); + + // Machine code emitter pass for ARM. + PM.add(createARMObjectCodeEmitterPass(*this, OCE)); + return false; +} + +bool ARMBaseTargetMachine::addSimpleCodeEmitter(PassManagerBase &PM, + CodeGenOpt::Level OptLevel, + MachineCodeEmitter &MCE) { + // Machine code emitter pass for ARM. + PM.add(createARMCodeEmitterPass(*this, MCE)); + return false; +} + +bool ARMBaseTargetMachine::addSimpleCodeEmitter(PassManagerBase &PM, + CodeGenOpt::Level OptLevel, + JITCodeEmitter &JCE) { + // Machine code emitter pass for ARM. + PM.add(createARMJITCodeEmitterPass(*this, JCE)); + return false; +} + +bool ARMBaseTargetMachine::addSimpleCodeEmitter(PassManagerBase &PM, + CodeGenOpt::Level OptLevel, + ObjectCodeEmitter &OCE) { + // Machine code emitter pass for ARM. + PM.add(createARMObjectCodeEmitterPass(*this, OCE)); + return false; +} + diff --git a/libclamav/c++/llvm/lib/Target/ARM/ARMTargetMachine.h b/libclamav/c++/llvm/lib/Target/ARM/ARMTargetMachine.h new file mode 100644 index 000000000..dd9542ea8 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/ARM/ARMTargetMachine.h @@ -0,0 +1,122 @@ +//===-- ARMTargetMachine.h - Define TargetMachine for ARM -------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the ARM specific subclass of TargetMachine. +// +//===----------------------------------------------------------------------===// + +#ifndef ARMTARGETMACHINE_H +#define ARMTARGETMACHINE_H + +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetData.h" +#include "ARMInstrInfo.h" +#include "ARMFrameInfo.h" +#include "ARMJITInfo.h" +#include "ARMSubtarget.h" +#include "ARMISelLowering.h" +#include "Thumb1InstrInfo.h" +#include "Thumb2InstrInfo.h" + +namespace llvm { + +class ARMBaseTargetMachine : public LLVMTargetMachine { +protected: + ARMSubtarget Subtarget; + +private: + ARMFrameInfo FrameInfo; + ARMJITInfo JITInfo; + InstrItineraryData InstrItins; + Reloc::Model DefRelocModel; // Reloc model before it's overridden. + +public: + ARMBaseTargetMachine(const Target &T, const std::string &TT, + const std::string &FS, bool isThumb); + + virtual const ARMFrameInfo *getFrameInfo() const { return &FrameInfo; } + virtual ARMJITInfo *getJITInfo() { return &JITInfo; } + virtual const ARMSubtarget *getSubtargetImpl() const { return &Subtarget; } + virtual const InstrItineraryData getInstrItineraryData() const { + return InstrItins; + } + + // Pass Pipeline Configuration + virtual bool addInstSelector(PassManagerBase &PM, CodeGenOpt::Level OptLevel); + virtual bool addPreRegAlloc(PassManagerBase &PM, CodeGenOpt::Level OptLevel); + virtual bool addPreSched2(PassManagerBase &PM, CodeGenOpt::Level OptLevel); + virtual bool addPreEmitPass(PassManagerBase &PM, CodeGenOpt::Level OptLevel); + virtual bool addCodeEmitter(PassManagerBase &PM, CodeGenOpt::Level OptLevel, + MachineCodeEmitter &MCE); + virtual bool addCodeEmitter(PassManagerBase &PM, CodeGenOpt::Level OptLevel, + JITCodeEmitter &MCE); + virtual bool addCodeEmitter(PassManagerBase &PM, CodeGenOpt::Level OptLevel, + ObjectCodeEmitter &OCE); + virtual bool addSimpleCodeEmitter(PassManagerBase &PM, + CodeGenOpt::Level OptLevel, + MachineCodeEmitter &MCE); + virtual bool addSimpleCodeEmitter(PassManagerBase &PM, + CodeGenOpt::Level OptLevel, + JITCodeEmitter &MCE); + virtual bool addSimpleCodeEmitter(PassManagerBase &PM, + CodeGenOpt::Level OptLevel, + ObjectCodeEmitter &OCE); +}; + +/// ARMTargetMachine - ARM target machine. +/// +class ARMTargetMachine : public ARMBaseTargetMachine { + ARMInstrInfo InstrInfo; + const TargetData DataLayout; // Calculates type size & alignment + ARMTargetLowering TLInfo; +public: + ARMTargetMachine(const Target &T, const std::string &TT, + const std::string &FS); + + virtual const ARMRegisterInfo *getRegisterInfo() const { + return &InstrInfo.getRegisterInfo(); + } + + virtual ARMTargetLowering *getTargetLowering() const { + return const_cast(&TLInfo); + } + + virtual const ARMInstrInfo *getInstrInfo() const { return &InstrInfo; } + virtual const TargetData *getTargetData() const { return &DataLayout; } +}; + +/// ThumbTargetMachine - Thumb target machine. +/// Due to the way architectures are handled, this represents both +/// Thumb-1 and Thumb-2. +/// +class ThumbTargetMachine : public ARMBaseTargetMachine { + ARMBaseInstrInfo *InstrInfo; // either Thumb1InstrInfo or Thumb2InstrInfo + const TargetData DataLayout; // Calculates type size & alignment + ARMTargetLowering TLInfo; +public: + ThumbTargetMachine(const Target &T, const std::string &TT, + const std::string &FS); + + /// returns either Thumb1RegisterInfo or Thumb2RegisterInfo + virtual const ARMBaseRegisterInfo *getRegisterInfo() const { + return &InstrInfo->getRegisterInfo(); + } + + virtual ARMTargetLowering *getTargetLowering() const { + return const_cast(&TLInfo); + } + + /// returns either Thumb1InstrInfo or Thumb2InstrInfo + virtual const ARMBaseInstrInfo *getInstrInfo() const { return InstrInfo; } + virtual const TargetData *getTargetData() const { return &DataLayout; } +}; + +} // end namespace llvm + +#endif diff --git a/libclamav/c++/llvm/lib/Target/ARM/ARMTargetObjectFile.h b/libclamav/c++/llvm/lib/Target/ARM/ARMTargetObjectFile.h new file mode 100644 index 000000000..9703403db --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/ARM/ARMTargetObjectFile.h @@ -0,0 +1,39 @@ +//===-- llvm/Target/ARMTargetObjectFile.h - ARM Object Info -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TARGET_ARM_TARGETOBJECTFILE_H +#define LLVM_TARGET_ARM_TARGETOBJECTFILE_H + +#include "llvm/Target/TargetLoweringObjectFile.h" +#include "llvm/MC/MCSectionELF.h" + +namespace llvm { + + class ARMElfTargetObjectFile : public TargetLoweringObjectFileELF { + public: + ARMElfTargetObjectFile() : TargetLoweringObjectFileELF() {} + + void Initialize(MCContext &Ctx, const TargetMachine &TM) { + TargetLoweringObjectFileELF::Initialize(Ctx, TM); + + if (TM.getSubtarget().isAAPCS_ABI()) { + StaticCtorSection = + getELFSection(".init_array", MCSectionELF::SHT_INIT_ARRAY, + MCSectionELF::SHF_WRITE | MCSectionELF::SHF_ALLOC, + SectionKind::getDataRel()); + StaticDtorSection = + getELFSection(".fini_array", MCSectionELF::SHT_FINI_ARRAY, + MCSectionELF::SHF_WRITE | MCSectionELF::SHF_ALLOC, + SectionKind::getDataRel()); + } + } + }; +} // end namespace llvm + +#endif diff --git a/libclamav/c++/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/libclamav/c++/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp new file mode 100644 index 000000000..894f913a7 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -0,0 +1,745 @@ +//===-- ARMAsmParser.cpp - Parse ARM assembly to MCInst instructions ------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "ARM.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/Twine.h" +#include "llvm/MC/MCAsmLexer.h" +#include "llvm/MC/MCAsmParser.h" +#include "llvm/MC/MCStreamer.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCInst.h" +#include "llvm/Support/SourceMgr.h" +#include "llvm/Target/TargetRegistry.h" +#include "llvm/Target/TargetAsmParser.h" +using namespace llvm; + +namespace { +struct ARMOperand; + +// The shift types for register controlled shifts in arm memory addressing +enum ShiftType { + Lsl, + Lsr, + Asr, + Ror, + Rrx +}; + +class ARMAsmParser : public TargetAsmParser { + MCAsmParser &Parser; + +private: + MCAsmParser &getParser() const { return Parser; } + + MCAsmLexer &getLexer() const { return Parser.getLexer(); } + + void Warning(SMLoc L, const Twine &Msg) { Parser.Warning(L, Msg); } + + bool Error(SMLoc L, const Twine &Msg) { return Parser.Error(L, Msg); } + + bool MaybeParseRegister(ARMOperand &Op, bool ParseWriteBack); + + bool ParseRegisterList(ARMOperand &Op); + + bool ParseMemory(ARMOperand &Op); + + bool ParseMemoryOffsetReg(bool &Negative, + bool &OffsetRegShifted, + enum ShiftType &ShiftType, + const MCExpr *&ShiftAmount, + const MCExpr *&Offset, + bool &OffsetIsReg, + int &OffsetRegNum); + + bool ParseShift(enum ShiftType &St, const MCExpr *&ShiftAmount); + + bool ParseOperand(ARMOperand &Op); + + bool ParseDirectiveWord(unsigned Size, SMLoc L); + + bool ParseDirectiveThumb(SMLoc L); + + bool ParseDirectiveThumbFunc(SMLoc L); + + bool ParseDirectiveCode(SMLoc L); + + bool ParseDirectiveSyntax(SMLoc L); + + // TODO - For now hacked versions of the next two are in here in this file to + // allow some parser testing until the table gen versions are implemented. + + /// @name Auto-generated Match Functions + /// { + bool MatchInstruction(SmallVectorImpl &Operands, + MCInst &Inst); + + /// MatchRegisterName - Match the given string to a register name and return + /// its register number, or -1 if there is no match. To allow return values + /// to be used directly in register lists, arm registers have values between + /// 0 and 15. + int MatchRegisterName(const StringRef &Name); + + /// } + + +public: + ARMAsmParser(const Target &T, MCAsmParser &_Parser) + : TargetAsmParser(T), Parser(_Parser) {} + + virtual bool ParseInstruction(const StringRef &Name, MCInst &Inst); + + virtual bool ParseDirective(AsmToken DirectiveID); +}; + +} // end anonymous namespace + +namespace { + +/// ARMOperand - Instances of this class represent a parsed ARM machine +/// instruction. +struct ARMOperand { + enum { + Token, + Register, + Immediate, + Memory + } Kind; + + + union { + struct { + const char *Data; + unsigned Length; + } Tok; + + struct { + unsigned RegNum; + bool Writeback; + } Reg; + + struct { + const MCExpr *Val; + } Imm; + + // This is for all forms of ARM address expressions + struct { + unsigned BaseRegNum; + unsigned OffsetRegNum; // used when OffsetIsReg is true + const MCExpr *Offset; // used when OffsetIsReg is false + const MCExpr *ShiftAmount; // used when OffsetRegShifted is true + enum ShiftType ShiftType; // used when OffsetRegShifted is true + unsigned + OffsetRegShifted : 1, // only used when OffsetIsReg is true + Preindexed : 1, + Postindexed : 1, + OffsetIsReg : 1, + Negative : 1, // only used when OffsetIsReg is true + Writeback : 1; + } Mem; + + }; + + StringRef getToken() const { + assert(Kind == Token && "Invalid access!"); + return StringRef(Tok.Data, Tok.Length); + } + + unsigned getReg() const { + assert(Kind == Register && "Invalid access!"); + return Reg.RegNum; + } + + const MCExpr *getImm() const { + assert(Kind == Immediate && "Invalid access!"); + return Imm.Val; + } + + bool isToken() const {return Kind == Token; } + + bool isReg() const { return Kind == Register; } + + void addRegOperands(MCInst &Inst, unsigned N) const { + assert(N == 1 && "Invalid number of operands!"); + Inst.addOperand(MCOperand::CreateReg(getReg())); + } + + static ARMOperand CreateToken(StringRef Str) { + ARMOperand Res; + Res.Kind = Token; + Res.Tok.Data = Str.data(); + Res.Tok.Length = Str.size(); + return Res; + } + + static ARMOperand CreateReg(unsigned RegNum, bool Writeback) { + ARMOperand Res; + Res.Kind = Register; + Res.Reg.RegNum = RegNum; + Res.Reg.Writeback = Writeback; + return Res; + } + + static ARMOperand CreateImm(const MCExpr *Val) { + ARMOperand Res; + Res.Kind = Immediate; + Res.Imm.Val = Val; + return Res; + } + + static ARMOperand CreateMem(unsigned BaseRegNum, bool OffsetIsReg, + const MCExpr *Offset, unsigned OffsetRegNum, + bool OffsetRegShifted, enum ShiftType ShiftType, + const MCExpr *ShiftAmount, bool Preindexed, + bool Postindexed, bool Negative, bool Writeback) { + ARMOperand Res; + Res.Kind = Memory; + Res.Mem.BaseRegNum = BaseRegNum; + Res.Mem.OffsetIsReg = OffsetIsReg; + Res.Mem.Offset = Offset; + Res.Mem.OffsetRegNum = OffsetRegNum; + Res.Mem.OffsetRegShifted = OffsetRegShifted; + Res.Mem.ShiftType = ShiftType; + Res.Mem.ShiftAmount = ShiftAmount; + Res.Mem.Preindexed = Preindexed; + Res.Mem.Postindexed = Postindexed; + Res.Mem.Negative = Negative; + Res.Mem.Writeback = Writeback; + return Res; + } +}; + +} // end anonymous namespace. + +/// Try to parse a register name. The token must be an Identifier when called, +/// and if it is a register name a Reg operand is created, the token is eaten +/// and false is returned. Else true is returned and no token is eaten. +/// TODO this is likely to change to allow different register types and or to +/// parse for a specific register type. +bool ARMAsmParser::MaybeParseRegister(ARMOperand &Op, bool ParseWriteBack) { + const AsmToken &Tok = getLexer().getTok(); + assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier"); + + // FIXME: Validate register for the current architecture; we have to do + // validation later, so maybe there is no need for this here. + int RegNum; + + RegNum = MatchRegisterName(Tok.getString()); + if (RegNum == -1) + return true; + getLexer().Lex(); // Eat identifier token. + + bool Writeback = false; + if (ParseWriteBack) { + const AsmToken &ExclaimTok = getLexer().getTok(); + if (ExclaimTok.is(AsmToken::Exclaim)) { + Writeback = true; + getLexer().Lex(); // Eat exclaim token + } + } + + Op = ARMOperand::CreateReg(RegNum, Writeback); + + return false; +} + +/// Parse a register list, return false if successful else return true or an +/// error. The first token must be a '{' when called. +bool ARMAsmParser::ParseRegisterList(ARMOperand &Op) { + assert(getLexer().getTok().is(AsmToken::LCurly) && + "Token is not an Left Curly Brace"); + getLexer().Lex(); // Eat left curly brace token. + + const AsmToken &RegTok = getLexer().getTok(); + SMLoc RegLoc = RegTok.getLoc(); + if (RegTok.isNot(AsmToken::Identifier)) + return Error(RegLoc, "register expected"); + int RegNum = MatchRegisterName(RegTok.getString()); + if (RegNum == -1) + return Error(RegLoc, "register expected"); + getLexer().Lex(); // Eat identifier token. + unsigned RegList = 1 << RegNum; + + int HighRegNum = RegNum; + // TODO ranges like "{Rn-Rm}" + while (getLexer().getTok().is(AsmToken::Comma)) { + getLexer().Lex(); // Eat comma token. + + const AsmToken &RegTok = getLexer().getTok(); + SMLoc RegLoc = RegTok.getLoc(); + if (RegTok.isNot(AsmToken::Identifier)) + return Error(RegLoc, "register expected"); + int RegNum = MatchRegisterName(RegTok.getString()); + if (RegNum == -1) + return Error(RegLoc, "register expected"); + + if (RegList & (1 << RegNum)) + Warning(RegLoc, "register duplicated in register list"); + else if (RegNum <= HighRegNum) + Warning(RegLoc, "register not in ascending order in register list"); + RegList |= 1 << RegNum; + HighRegNum = RegNum; + + getLexer().Lex(); // Eat identifier token. + } + const AsmToken &RCurlyTok = getLexer().getTok(); + if (RCurlyTok.isNot(AsmToken::RCurly)) + return Error(RCurlyTok.getLoc(), "'}' expected"); + getLexer().Lex(); // Eat left curly brace token. + + return false; +} + +/// Parse an arm memory expression, return false if successful else return true +/// or an error. The first token must be a '[' when called. +/// TODO Only preindexing and postindexing addressing are started, unindexed +/// with option, etc are still to do. +bool ARMAsmParser::ParseMemory(ARMOperand &Op) { + assert(getLexer().getTok().is(AsmToken::LBrac) && + "Token is not an Left Bracket"); + getLexer().Lex(); // Eat left bracket token. + + const AsmToken &BaseRegTok = getLexer().getTok(); + if (BaseRegTok.isNot(AsmToken::Identifier)) + return Error(BaseRegTok.getLoc(), "register expected"); + if (MaybeParseRegister(Op, false)) + return Error(BaseRegTok.getLoc(), "register expected"); + int BaseRegNum = Op.getReg(); + + bool Preindexed = false; + bool Postindexed = false; + bool OffsetIsReg = false; + bool Negative = false; + bool Writeback = false; + + // First look for preindexed address forms, that is after the "[Rn" we now + // have to see if the next token is a comma. + const AsmToken &Tok = getLexer().getTok(); + if (Tok.is(AsmToken::Comma)) { + Preindexed = true; + getLexer().Lex(); // Eat comma token. + int OffsetRegNum; + bool OffsetRegShifted; + enum ShiftType ShiftType; + const MCExpr *ShiftAmount; + const MCExpr *Offset; + if(ParseMemoryOffsetReg(Negative, OffsetRegShifted, ShiftType, ShiftAmount, + Offset, OffsetIsReg, OffsetRegNum)) + return true; + const AsmToken &RBracTok = getLexer().getTok(); + if (RBracTok.isNot(AsmToken::RBrac)) + return Error(RBracTok.getLoc(), "']' expected"); + getLexer().Lex(); // Eat right bracket token. + + const AsmToken &ExclaimTok = getLexer().getTok(); + if (ExclaimTok.is(AsmToken::Exclaim)) { + Writeback = true; + getLexer().Lex(); // Eat exclaim token + } + Op = ARMOperand::CreateMem(BaseRegNum, OffsetIsReg, Offset, OffsetRegNum, + OffsetRegShifted, ShiftType, ShiftAmount, + Preindexed, Postindexed, Negative, Writeback); + return false; + } + // The "[Rn" we have so far was not followed by a comma. + else if (Tok.is(AsmToken::RBrac)) { + // This is a post indexing addressing forms, that is a ']' follows after + // the "[Rn". + Postindexed = true; + Writeback = true; + getLexer().Lex(); // Eat right bracket token. + + int OffsetRegNum = 0; + bool OffsetRegShifted = false; + enum ShiftType ShiftType; + const MCExpr *ShiftAmount; + const MCExpr *Offset; + + const AsmToken &NextTok = getLexer().getTok(); + if (NextTok.isNot(AsmToken::EndOfStatement)) { + if (NextTok.isNot(AsmToken::Comma)) + return Error(NextTok.getLoc(), "',' expected"); + getLexer().Lex(); // Eat comma token. + if(ParseMemoryOffsetReg(Negative, OffsetRegShifted, ShiftType, + ShiftAmount, Offset, OffsetIsReg, OffsetRegNum)) + return true; + } + + Op = ARMOperand::CreateMem(BaseRegNum, OffsetIsReg, Offset, OffsetRegNum, + OffsetRegShifted, ShiftType, ShiftAmount, + Preindexed, Postindexed, Negative, Writeback); + return false; + } + + return true; +} + +/// Parse the offset of a memory operand after we have seen "[Rn," or "[Rn]," +/// we will parse the following (were +/- means that a plus or minus is +/// optional): +/// +/-Rm +/// +/-Rm, shift +/// #offset +/// we return false on success or an error otherwise. +bool ARMAsmParser::ParseMemoryOffsetReg(bool &Negative, + bool &OffsetRegShifted, + enum ShiftType &ShiftType, + const MCExpr *&ShiftAmount, + const MCExpr *&Offset, + bool &OffsetIsReg, + int &OffsetRegNum) { + ARMOperand Op; + Negative = false; + OffsetRegShifted = false; + OffsetIsReg = false; + OffsetRegNum = -1; + const AsmToken &NextTok = getLexer().getTok(); + if (NextTok.is(AsmToken::Plus)) + getLexer().Lex(); // Eat plus token. + else if (NextTok.is(AsmToken::Minus)) { + Negative = true; + getLexer().Lex(); // Eat minus token + } + // See if there is a register following the "[Rn," or "[Rn]," we have so far. + const AsmToken &OffsetRegTok = getLexer().getTok(); + if (OffsetRegTok.is(AsmToken::Identifier)) { + OffsetIsReg = !MaybeParseRegister(Op, false); + if (OffsetIsReg) + OffsetRegNum = Op.getReg(); + } + // If we parsed a register as the offset then their can be a shift after that + if (OffsetRegNum != -1) { + // Look for a comma then a shift + const AsmToken &Tok = getLexer().getTok(); + if (Tok.is(AsmToken::Comma)) { + getLexer().Lex(); // Eat comma token. + + const AsmToken &Tok = getLexer().getTok(); + if (ParseShift(ShiftType, ShiftAmount)) + return Error(Tok.getLoc(), "shift expected"); + OffsetRegShifted = true; + } + } + else { // the "[Rn," or "[Rn,]" we have so far was not followed by "Rm" + // Look for #offset following the "[Rn," or "[Rn]," + const AsmToken &HashTok = getLexer().getTok(); + if (HashTok.isNot(AsmToken::Hash)) + return Error(HashTok.getLoc(), "'#' expected"); + getLexer().Lex(); // Eat hash token. + + if (getParser().ParseExpression(Offset)) + return true; + } + return false; +} + +/// ParseShift as one of these two: +/// ( lsl | lsr | asr | ror ) , # shift_amount +/// rrx +/// and returns true if it parses a shift otherwise it returns false. +bool ARMAsmParser::ParseShift(ShiftType &St, const MCExpr *&ShiftAmount) { + const AsmToken &Tok = getLexer().getTok(); + if (Tok.isNot(AsmToken::Identifier)) + return true; + const StringRef &ShiftName = Tok.getString(); + if (ShiftName == "lsl" || ShiftName == "LSL") + St = Lsl; + else if (ShiftName == "lsr" || ShiftName == "LSR") + St = Lsr; + else if (ShiftName == "asr" || ShiftName == "ASR") + St = Asr; + else if (ShiftName == "ror" || ShiftName == "ROR") + St = Ror; + else if (ShiftName == "rrx" || ShiftName == "RRX") + St = Rrx; + else + return true; + getLexer().Lex(); // Eat shift type token. + + // Rrx stands alone. + if (St == Rrx) + return false; + + // Otherwise, there must be a '#' and a shift amount. + const AsmToken &HashTok = getLexer().getTok(); + if (HashTok.isNot(AsmToken::Hash)) + return Error(HashTok.getLoc(), "'#' expected"); + getLexer().Lex(); // Eat hash token. + + if (getParser().ParseExpression(ShiftAmount)) + return true; + + return false; +} + +/// A hack to allow some testing, to be replaced by a real table gen version. +int ARMAsmParser::MatchRegisterName(const StringRef &Name) { + if (Name == "r0" || Name == "R0") + return 0; + else if (Name == "r1" || Name == "R1") + return 1; + else if (Name == "r2" || Name == "R2") + return 2; + else if (Name == "r3" || Name == "R3") + return 3; + else if (Name == "r3" || Name == "R3") + return 3; + else if (Name == "r4" || Name == "R4") + return 4; + else if (Name == "r5" || Name == "R5") + return 5; + else if (Name == "r6" || Name == "R6") + return 6; + else if (Name == "r7" || Name == "R7") + return 7; + else if (Name == "r8" || Name == "R8") + return 8; + else if (Name == "r9" || Name == "R9") + return 9; + else if (Name == "r10" || Name == "R10") + return 10; + else if (Name == "r11" || Name == "R11" || Name == "fp") + return 11; + else if (Name == "r12" || Name == "R12" || Name == "ip") + return 12; + else if (Name == "r13" || Name == "R13" || Name == "sp") + return 13; + else if (Name == "r14" || Name == "R14" || Name == "lr") + return 14; + else if (Name == "r15" || Name == "R15" || Name == "pc") + return 15; + return -1; +} + +/// A hack to allow some testing, to be replaced by a real table gen version. +bool ARMAsmParser::MatchInstruction(SmallVectorImpl &Operands, + MCInst &Inst) { + struct ARMOperand Op0 = Operands[0]; + assert(Op0.Kind == ARMOperand::Token && "First operand not a Token"); + const StringRef &Mnemonic = Op0.getToken(); + if (Mnemonic == "add" || + Mnemonic == "stmfd" || + Mnemonic == "str" || + Mnemonic == "ldmfd" || + Mnemonic == "ldr" || + Mnemonic == "mov" || + Mnemonic == "sub" || + Mnemonic == "bl" || + Mnemonic == "push" || + Mnemonic == "blx" || + Mnemonic == "pop") { + // Hard-coded to a valid instruction, till we have a real matcher. + Inst = MCInst(); + Inst.setOpcode(ARM::MOVr); + Inst.addOperand(MCOperand::CreateReg(2)); + Inst.addOperand(MCOperand::CreateReg(2)); + Inst.addOperand(MCOperand::CreateImm(0)); + Inst.addOperand(MCOperand::CreateImm(0)); + Inst.addOperand(MCOperand::CreateReg(0)); + return false; + } + + return true; +} + +/// Parse a arm instruction operand. For now this parses the operand regardless +/// of the mnemonic. +bool ARMAsmParser::ParseOperand(ARMOperand &Op) { + switch (getLexer().getKind()) { + case AsmToken::Identifier: + if (!MaybeParseRegister(Op, true)) + return false; + // This was not a register so parse other operands that start with an + // identifier (like labels) as expressions and create them as immediates. + const MCExpr *IdVal; + if (getParser().ParseExpression(IdVal)) + return true; + Op = ARMOperand::CreateImm(IdVal); + return false; + case AsmToken::LBrac: + return ParseMemory(Op); + case AsmToken::LCurly: + return ParseRegisterList(Op); + case AsmToken::Hash: + // #42 -> immediate. + // TODO: ":lower16:" and ":upper16:" modifiers after # before immediate + getLexer().Lex(); + const MCExpr *ImmVal; + if (getParser().ParseExpression(ImmVal)) + return true; + Op = ARMOperand::CreateImm(ImmVal); + return false; + default: + return Error(getLexer().getTok().getLoc(), "unexpected token in operand"); + } +} + +/// Parse an arm instruction mnemonic followed by its operands. +bool ARMAsmParser::ParseInstruction(const StringRef &Name, MCInst &Inst) { + SmallVector Operands; + + Operands.push_back(ARMOperand::CreateToken(Name)); + + SMLoc Loc = getLexer().getTok().getLoc(); + if (getLexer().isNot(AsmToken::EndOfStatement)) { + + // Read the first operand. + Operands.push_back(ARMOperand()); + if (ParseOperand(Operands.back())) + return true; + + while (getLexer().is(AsmToken::Comma)) { + getLexer().Lex(); // Eat the comma. + + // Parse and remember the operand. + Operands.push_back(ARMOperand()); + if (ParseOperand(Operands.back())) + return true; + } + } + if (!MatchInstruction(Operands, Inst)) + return false; + + Error(Loc, "ARMAsmParser::ParseInstruction only partly implemented"); + return true; +} + +/// ParseDirective parses the arm specific directives +bool ARMAsmParser::ParseDirective(AsmToken DirectiveID) { + StringRef IDVal = DirectiveID.getIdentifier(); + if (IDVal == ".word") + return ParseDirectiveWord(4, DirectiveID.getLoc()); + else if (IDVal == ".thumb") + return ParseDirectiveThumb(DirectiveID.getLoc()); + else if (IDVal == ".thumb_func") + return ParseDirectiveThumbFunc(DirectiveID.getLoc()); + else if (IDVal == ".code") + return ParseDirectiveCode(DirectiveID.getLoc()); + else if (IDVal == ".syntax") + return ParseDirectiveSyntax(DirectiveID.getLoc()); + return true; +} + +/// ParseDirectiveWord +/// ::= .word [ expression (, expression)* ] +bool ARMAsmParser::ParseDirectiveWord(unsigned Size, SMLoc L) { + if (getLexer().isNot(AsmToken::EndOfStatement)) { + for (;;) { + const MCExpr *Value; + if (getParser().ParseExpression(Value)) + return true; + + getParser().getStreamer().EmitValue(Value, Size); + + if (getLexer().is(AsmToken::EndOfStatement)) + break; + + // FIXME: Improve diagnostic. + if (getLexer().isNot(AsmToken::Comma)) + return Error(L, "unexpected token in directive"); + getLexer().Lex(); + } + } + + getLexer().Lex(); + return false; +} + +/// ParseDirectiveThumb +/// ::= .thumb +bool ARMAsmParser::ParseDirectiveThumb(SMLoc L) { + if (getLexer().isNot(AsmToken::EndOfStatement)) + return Error(L, "unexpected token in directive"); + getLexer().Lex(); + + // TODO: set thumb mode + // TODO: tell the MC streamer the mode + // getParser().getStreamer().Emit???(); + return false; +} + +/// ParseDirectiveThumbFunc +/// ::= .thumbfunc symbol_name +bool ARMAsmParser::ParseDirectiveThumbFunc(SMLoc L) { + const AsmToken &Tok = getLexer().getTok(); + if (Tok.isNot(AsmToken::Identifier) && Tok.isNot(AsmToken::String)) + return Error(L, "unexpected token in .syntax directive"); + StringRef SymbolName = getLexer().getTok().getIdentifier(); + getLexer().Lex(); // Consume the identifier token. + + if (getLexer().isNot(AsmToken::EndOfStatement)) + return Error(L, "unexpected token in directive"); + getLexer().Lex(); + + // TODO: mark symbol as a thumb symbol + // getParser().getStreamer().Emit???(); + return false; +} + +/// ParseDirectiveSyntax +/// ::= .syntax unified | divided +bool ARMAsmParser::ParseDirectiveSyntax(SMLoc L) { + const AsmToken &Tok = getLexer().getTok(); + if (Tok.isNot(AsmToken::Identifier)) + return Error(L, "unexpected token in .syntax directive"); + const StringRef &Mode = Tok.getString(); + bool unified_syntax; + if (Mode == "unified" || Mode == "UNIFIED") { + getLexer().Lex(); + unified_syntax = true; + } + else if (Mode == "divided" || Mode == "DIVIDED") { + getLexer().Lex(); + unified_syntax = false; + } + else + return Error(L, "unrecognized syntax mode in .syntax directive"); + + if (getLexer().isNot(AsmToken::EndOfStatement)) + return Error(getLexer().getTok().getLoc(), "unexpected token in directive"); + getLexer().Lex(); + + // TODO tell the MC streamer the mode + // getParser().getStreamer().Emit???(); + return false; +} + +/// ParseDirectiveCode +/// ::= .code 16 | 32 +bool ARMAsmParser::ParseDirectiveCode(SMLoc L) { + const AsmToken &Tok = getLexer().getTok(); + if (Tok.isNot(AsmToken::Integer)) + return Error(L, "unexpected token in .code directive"); + int64_t Val = getLexer().getTok().getIntVal(); + bool thumb_mode; + if (Val == 16) { + getLexer().Lex(); + thumb_mode = true; + } + else if (Val == 32) { + getLexer().Lex(); + thumb_mode = false; + } + else + return Error(L, "invalid operand to .code directive"); + + if (getLexer().isNot(AsmToken::EndOfStatement)) + return Error(getLexer().getTok().getLoc(), "unexpected token in directive"); + getLexer().Lex(); + + // TODO tell the MC streamer the mode + // getParser().getStreamer().Emit???(); + return false; +} + +/// Force static initialization. +extern "C" void LLVMInitializeARMAsmParser() { + RegisterAsmParser X(TheARMTarget); + RegisterAsmParser Y(TheThumbTarget); +} diff --git a/libclamav/c++/llvm/lib/Target/ARM/AsmParser/CMakeLists.txt b/libclamav/c++/llvm/lib/Target/ARM/AsmParser/CMakeLists.txt new file mode 100644 index 000000000..308c6cff8 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/ARM/AsmParser/CMakeLists.txt @@ -0,0 +1,6 @@ +include_directories( ${CMAKE_CURRENT_BINARY_DIR}/.. ${CMAKE_CURRENT_SOURCE_DIR}/.. ) + +add_llvm_library(LLVMARMAsmParser + ARMAsmParser.cpp + ) + diff --git a/libclamav/c++/llvm/lib/Target/ARM/AsmParser/Makefile b/libclamav/c++/llvm/lib/Target/ARM/AsmParser/Makefile new file mode 100644 index 000000000..97e56126d --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/ARM/AsmParser/Makefile @@ -0,0 +1,15 @@ +##===- lib/Target/ARM/AsmParser/Makefile -------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## +LEVEL = ../../../.. +LIBRARYNAME = LLVMARMAsmParser + +# Hack: we need to include 'main' ARM target directory to grab private headers +CPPFLAGS = -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. + +include $(LEVEL)/Makefile.common diff --git a/libclamav/c++/llvm/lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp b/libclamav/c++/llvm/lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp new file mode 100644 index 000000000..692bb1924 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp @@ -0,0 +1,1533 @@ +//===-- ARMAsmPrinter.cpp - Print machine code to an ARM .s file ----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains a printer that converts from our internal representation +// of machine-dependent LLVM code to GAS-format ARM assembly language. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "asm-printer" +#include "ARM.h" +#include "ARMBuildAttrs.h" +#include "ARMAddressingModes.h" +#include "ARMConstantPoolValue.h" +#include "ARMInstPrinter.h" +#include "ARMMachineFunctionInfo.h" +#include "ARMMCInstLower.h" +#include "ARMTargetMachine.h" +#include "llvm/Constants.h" +#include "llvm/Module.h" +#include "llvm/Assembly/Writer.h" +#include "llvm/CodeGen/AsmPrinter.h" +#include "llvm/CodeGen/DwarfWriter.h" +#include "llvm/CodeGen/MachineModuleInfoImpls.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineJumpTableInfo.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCInst.h" +#include "llvm/MC/MCSectionMachO.h" +#include "llvm/MC/MCStreamer.h" +#include "llvm/MC/MCSymbol.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetLoweringObjectFile.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetOptions.h" +#include "llvm/Target/TargetRegistry.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/StringSet.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/FormattedStream.h" +#include "llvm/Support/Mangler.h" +#include "llvm/Support/MathExtras.h" +#include +using namespace llvm; + +STATISTIC(EmittedInsts, "Number of machine instrs printed"); + +static cl::opt +EnableMCInst("enable-arm-mcinst-printer", cl::Hidden, + cl::desc("enable experimental asmprinter gunk in the arm backend")); + +namespace { + class ARMAsmPrinter : public AsmPrinter { + + /// Subtarget - Keep a pointer to the ARMSubtarget around so that we can + /// make the right decision when printing asm code for different targets. + const ARMSubtarget *Subtarget; + + /// AFI - Keep a pointer to ARMFunctionInfo for the current + /// MachineFunction. + ARMFunctionInfo *AFI; + + /// MCP - Keep a pointer to constantpool entries of the current + /// MachineFunction. + const MachineConstantPool *MCP; + + public: + explicit ARMAsmPrinter(formatted_raw_ostream &O, TargetMachine &TM, + const MCAsmInfo *T, bool V) + : AsmPrinter(O, TM, T, V), AFI(NULL), MCP(NULL) { + Subtarget = &TM.getSubtarget(); + } + + virtual const char *getPassName() const { + return "ARM Assembly Printer"; + } + + void printMCInst(const MCInst *MI) { + ARMInstPrinter(O, *MAI, VerboseAsm).printInstruction(MI); + } + + void printInstructionThroughMCStreamer(const MachineInstr *MI); + + + void printOperand(const MachineInstr *MI, int OpNum, + const char *Modifier = 0); + void printSOImmOperand(const MachineInstr *MI, int OpNum); + void printSOImm2PartOperand(const MachineInstr *MI, int OpNum); + void printSORegOperand(const MachineInstr *MI, int OpNum); + void printAddrMode2Operand(const MachineInstr *MI, int OpNum); + void printAddrMode2OffsetOperand(const MachineInstr *MI, int OpNum); + void printAddrMode3Operand(const MachineInstr *MI, int OpNum); + void printAddrMode3OffsetOperand(const MachineInstr *MI, int OpNum); + void printAddrMode4Operand(const MachineInstr *MI, int OpNum, + const char *Modifier = 0); + void printAddrMode5Operand(const MachineInstr *MI, int OpNum, + const char *Modifier = 0); + void printAddrMode6Operand(const MachineInstr *MI, int OpNum); + void printAddrModePCOperand(const MachineInstr *MI, int OpNum, + const char *Modifier = 0); + void printBitfieldInvMaskImmOperand (const MachineInstr *MI, int OpNum); + + void printThumbS4ImmOperand(const MachineInstr *MI, int OpNum); + void printThumbITMask(const MachineInstr *MI, int OpNum); + void printThumbAddrModeRROperand(const MachineInstr *MI, int OpNum); + void printThumbAddrModeRI5Operand(const MachineInstr *MI, int OpNum, + unsigned Scale); + void printThumbAddrModeS1Operand(const MachineInstr *MI, int OpNum); + void printThumbAddrModeS2Operand(const MachineInstr *MI, int OpNum); + void printThumbAddrModeS4Operand(const MachineInstr *MI, int OpNum); + void printThumbAddrModeSPOperand(const MachineInstr *MI, int OpNum); + + void printT2SOOperand(const MachineInstr *MI, int OpNum); + void printT2AddrModeImm12Operand(const MachineInstr *MI, int OpNum); + void printT2AddrModeImm8Operand(const MachineInstr *MI, int OpNum); + void printT2AddrModeImm8s4Operand(const MachineInstr *MI, int OpNum); + void printT2AddrModeImm8OffsetOperand(const MachineInstr *MI, int OpNum); + void printT2AddrModeSoRegOperand(const MachineInstr *MI, int OpNum); + + void printPredicateOperand(const MachineInstr *MI, int OpNum); + void printSBitModifierOperand(const MachineInstr *MI, int OpNum); + void printPCLabel(const MachineInstr *MI, int OpNum); + void printRegisterList(const MachineInstr *MI, int OpNum); + void printCPInstOperand(const MachineInstr *MI, int OpNum, + const char *Modifier); + void printJTBlockOperand(const MachineInstr *MI, int OpNum); + void printJT2BlockOperand(const MachineInstr *MI, int OpNum); + void printTBAddrMode(const MachineInstr *MI, int OpNum); + void printNoHashImmediate(const MachineInstr *MI, int OpNum); + void printVFPf32ImmOperand(const MachineInstr *MI, int OpNum); + void printVFPf64ImmOperand(const MachineInstr *MI, int OpNum); + + void printHex8ImmOperand(const MachineInstr *MI, int OpNum) { + O << "#0x" << utohexstr(MI->getOperand(OpNum).getImm() & 0xff); + } + void printHex16ImmOperand(const MachineInstr *MI, int OpNum) { + O << "#0x" << utohexstr(MI->getOperand(OpNum).getImm() & 0xffff); + } + void printHex32ImmOperand(const MachineInstr *MI, int OpNum) { + O << "#0x" << utohexstr(MI->getOperand(OpNum).getImm() & 0xffffffff); + } + void printHex64ImmOperand(const MachineInstr *MI, int OpNum) { + O << "#0x" << utohexstr(MI->getOperand(OpNum).getImm()); + } + + virtual bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNum, + unsigned AsmVariant, const char *ExtraCode); + virtual bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNum, + unsigned AsmVariant, + const char *ExtraCode); + + void PrintGlobalVariable(const GlobalVariable* GVar); + void printInstruction(const MachineInstr *MI); // autogenerated. + static const char *getRegisterName(unsigned RegNo); + + void printMachineInstruction(const MachineInstr *MI); + bool runOnMachineFunction(MachineFunction &F); + void EmitStartOfAsmFile(Module &M); + void EmitEndOfAsmFile(Module &M); + + /// EmitMachineConstantPoolValue - Print a machine constantpool value to + /// the .s file. + virtual void EmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV) { + printDataDirective(MCPV->getType()); + + ARMConstantPoolValue *ACPV = static_cast(MCPV); + std::string Name; + + if (ACPV->isLSDA()) { + SmallString<16> LSDAName; + raw_svector_ostream(LSDAName) << MAI->getPrivateGlobalPrefix() << + "_LSDA_" << getFunctionNumber(); + Name = LSDAName.str(); + } else if (ACPV->isBlockAddress()) { + Name = GetBlockAddressSymbol(ACPV->getBlockAddress())->getName(); + } else if (ACPV->isGlobalValue()) { + GlobalValue *GV = ACPV->getGV(); + bool isIndirect = Subtarget->isTargetDarwin() && + Subtarget->GVIsIndirectSymbol(GV, TM.getRelocationModel()); + if (!isIndirect) + Name = Mang->getMangledName(GV); + else { + // FIXME: Remove this when Darwin transition to @GOT like syntax. + Name = Mang->getMangledName(GV, "$non_lazy_ptr", true); + MCSymbol *Sym = OutContext.GetOrCreateSymbol(StringRef(Name)); + + MachineModuleInfoMachO &MMIMachO = + MMI->getObjFileInfo(); + const MCSymbol *&StubSym = + GV->hasHiddenVisibility() ? MMIMachO.getHiddenGVStubEntry(Sym) : + MMIMachO.getGVStubEntry(Sym); + if (StubSym == 0) { + SmallString<128> NameStr; + Mang->getNameWithPrefix(NameStr, GV, false); + StubSym = OutContext.GetOrCreateSymbol(NameStr.str()); + } + } + } else { + assert(ACPV->isExtSymbol() && "unrecognized constant pool value"); + Name = Mang->makeNameProper(ACPV->getSymbol()); + } + O << Name; + + if (ACPV->hasModifier()) O << "(" << ACPV->getModifier() << ")"; + if (ACPV->getPCAdjustment() != 0) { + O << "-(" << MAI->getPrivateGlobalPrefix() << "PC" + << getFunctionNumber() << "_" << ACPV->getLabelId() + << "+" << (unsigned)ACPV->getPCAdjustment(); + if (ACPV->mustAddCurrentAddress()) + O << "-."; + O << ")"; + } + O << "\n"; + } + + void getAnalysisUsage(AnalysisUsage &AU) const { + AsmPrinter::getAnalysisUsage(AU); + AU.setPreservesAll(); + AU.addRequired(); + AU.addRequired(); + } + }; +} // end of anonymous namespace + +#include "ARMGenAsmWriter.inc" + +/// runOnMachineFunction - This uses the printInstruction() +/// method to print assembly for each instruction. +/// +bool ARMAsmPrinter::runOnMachineFunction(MachineFunction &MF) { + this->MF = &MF; + + AFI = MF.getInfo(); + MCP = MF.getConstantPool(); + + SetupMachineFunction(MF); + O << "\n"; + + // NOTE: we don't print out constant pools here, they are handled as + // instructions. + + O << '\n'; + + // Print out labels for the function. + const Function *F = MF.getFunction(); + OutStreamer.SwitchSection(getObjFileLowering().SectionForGlobal(F, Mang, TM)); + + switch (F->getLinkage()) { + default: llvm_unreachable("Unknown linkage type!"); + case Function::PrivateLinkage: + case Function::InternalLinkage: + break; + case Function::ExternalLinkage: + O << "\t.globl\t" << CurrentFnName << "\n"; + break; + case Function::LinkerPrivateLinkage: + case Function::WeakAnyLinkage: + case Function::WeakODRLinkage: + case Function::LinkOnceAnyLinkage: + case Function::LinkOnceODRLinkage: + if (Subtarget->isTargetDarwin()) { + O << "\t.globl\t" << CurrentFnName << "\n"; + O << "\t.weak_definition\t" << CurrentFnName << "\n"; + } else { + O << MAI->getWeakRefDirective() << CurrentFnName << "\n"; + } + break; + } + + printVisibility(CurrentFnName, F->getVisibility()); + + unsigned FnAlign = 1 << MF.getAlignment(); // MF alignment is log2. + if (AFI->isThumbFunction()) { + EmitAlignment(FnAlign, F, AFI->getAlign()); + O << "\t.code\t16\n"; + O << "\t.thumb_func"; + if (Subtarget->isTargetDarwin()) + O << "\t" << CurrentFnName; + O << "\n"; + } else { + EmitAlignment(FnAlign, F); + } + + O << CurrentFnName << ":\n"; + // Emit pre-function debug information. + DW->BeginFunction(&MF); + + if (Subtarget->isTargetDarwin()) { + // If the function is empty, then we need to emit *something*. Otherwise, + // the function's label might be associated with something that it wasn't + // meant to be associated with. We emit a noop in this situation. + MachineFunction::iterator I = MF.begin(); + + if (++I == MF.end() && MF.front().empty()) + O << "\tnop\n"; + } + + // Print out code for the function. + for (MachineFunction::const_iterator I = MF.begin(), E = MF.end(); + I != E; ++I) { + // Print a label for the basic block. + if (I != MF.begin()) + EmitBasicBlockStart(I); + + // Print the assembly for the instruction. + for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end(); + II != E; ++II) + printMachineInstruction(II); + } + + if (MAI->hasDotTypeDotSizeDirective()) + O << "\t.size " << CurrentFnName << ", .-" << CurrentFnName << "\n"; + + // Emit post-function debug information. + DW->EndFunction(&MF); + + return false; +} + +void ARMAsmPrinter::printOperand(const MachineInstr *MI, int OpNum, + const char *Modifier) { + const MachineOperand &MO = MI->getOperand(OpNum); + unsigned TF = MO.getTargetFlags(); + + switch (MO.getType()) { + default: + assert(0 && ""); + case MachineOperand::MO_Register: { + unsigned Reg = MO.getReg(); + assert(TargetRegisterInfo::isPhysicalRegister(Reg)); + if (Modifier && strcmp(Modifier, "dregpair") == 0) { + unsigned DRegLo = TRI->getSubReg(Reg, 5); // arm_dsubreg_0 + unsigned DRegHi = TRI->getSubReg(Reg, 6); // arm_dsubreg_1 + O << '{' + << getRegisterName(DRegLo) << ',' << getRegisterName(DRegHi) + << '}'; + } else if (Modifier && strcmp(Modifier, "lane") == 0) { + unsigned RegNum = ARMRegisterInfo::getRegisterNumbering(Reg); + unsigned DReg = TRI->getMatchingSuperReg(Reg, RegNum & 1 ? 2 : 1, + &ARM::DPR_VFP2RegClass); + O << getRegisterName(DReg) << '[' << (RegNum & 1) << ']'; + } else { + assert(!MO.getSubReg() && "Subregs should be eliminated!"); + O << getRegisterName(Reg); + } + break; + } + case MachineOperand::MO_Immediate: { + int64_t Imm = MO.getImm(); + O << '#'; + if ((Modifier && strcmp(Modifier, "lo16") == 0) || + (TF & ARMII::MO_LO16)) + O << ":lower16:"; + else if ((Modifier && strcmp(Modifier, "hi16") == 0) || + (TF & ARMII::MO_HI16)) + O << ":upper16:"; + O << Imm; + break; + } + case MachineOperand::MO_MachineBasicBlock: + GetMBBSymbol(MO.getMBB()->getNumber())->print(O, MAI); + return; + case MachineOperand::MO_GlobalAddress: { + bool isCallOp = Modifier && !strcmp(Modifier, "call"); + GlobalValue *GV = MO.getGlobal(); + + if ((Modifier && strcmp(Modifier, "lo16") == 0) || + (TF & ARMII::MO_LO16)) + O << ":lower16:"; + else if ((Modifier && strcmp(Modifier, "hi16") == 0) || + (TF & ARMII::MO_HI16)) + O << ":upper16:"; + O << Mang->getMangledName(GV); + + printOffset(MO.getOffset()); + + if (isCallOp && Subtarget->isTargetELF() && + TM.getRelocationModel() == Reloc::PIC_) + O << "(PLT)"; + break; + } + case MachineOperand::MO_ExternalSymbol: { + bool isCallOp = Modifier && !strcmp(Modifier, "call"); + std::string Name = Mang->makeNameProper(MO.getSymbolName()); + + O << Name; + if (isCallOp && Subtarget->isTargetELF() && + TM.getRelocationModel() == Reloc::PIC_) + O << "(PLT)"; + break; + } + case MachineOperand::MO_ConstantPoolIndex: + O << MAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() + << '_' << MO.getIndex(); + break; + case MachineOperand::MO_JumpTableIndex: + O << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() + << '_' << MO.getIndex(); + break; + } +} + +static void printSOImm(formatted_raw_ostream &O, int64_t V, bool VerboseAsm, + const MCAsmInfo *MAI) { + // Break it up into two parts that make up a shifter immediate. + V = ARM_AM::getSOImmVal(V); + assert(V != -1 && "Not a valid so_imm value!"); + + unsigned Imm = ARM_AM::getSOImmValImm(V); + unsigned Rot = ARM_AM::getSOImmValRot(V); + + // Print low-level immediate formation info, per + // A5.1.3: "Data-processing operands - Immediate". + if (Rot) { + O << "#" << Imm << ", " << Rot; + // Pretty printed version. + if (VerboseAsm) { + O.PadToColumn(MAI->getCommentColumn()); + O << MAI->getCommentString() << ' '; + O << (int)ARM_AM::rotr32(Imm, Rot); + } + } else { + O << "#" << Imm; + } +} + +/// printSOImmOperand - SOImm is 4-bit rotate amount in bits 8-11 with 8-bit +/// immediate in bits 0-7. +void ARMAsmPrinter::printSOImmOperand(const MachineInstr *MI, int OpNum) { + const MachineOperand &MO = MI->getOperand(OpNum); + assert(MO.isImm() && "Not a valid so_imm value!"); + printSOImm(O, MO.getImm(), VerboseAsm, MAI); +} + +/// printSOImm2PartOperand - SOImm is broken into two pieces using a 'mov' +/// followed by an 'orr' to materialize. +void ARMAsmPrinter::printSOImm2PartOperand(const MachineInstr *MI, int OpNum) { + const MachineOperand &MO = MI->getOperand(OpNum); + assert(MO.isImm() && "Not a valid so_imm value!"); + unsigned V1 = ARM_AM::getSOImmTwoPartFirst(MO.getImm()); + unsigned V2 = ARM_AM::getSOImmTwoPartSecond(MO.getImm()); + printSOImm(O, V1, VerboseAsm, MAI); + O << "\n\torr"; + printPredicateOperand(MI, 2); + O << "\t"; + printOperand(MI, 0); + O << ", "; + printOperand(MI, 0); + O << ", "; + printSOImm(O, V2, VerboseAsm, MAI); +} + +// so_reg is a 4-operand unit corresponding to register forms of the A5.1 +// "Addressing Mode 1 - Data-processing operands" forms. This includes: +// REG 0 0 - e.g. R5 +// REG REG 0,SH_OPC - e.g. R5, ROR R3 +// REG 0 IMM,SH_OPC - e.g. R5, LSL #3 +void ARMAsmPrinter::printSORegOperand(const MachineInstr *MI, int Op) { + const MachineOperand &MO1 = MI->getOperand(Op); + const MachineOperand &MO2 = MI->getOperand(Op+1); + const MachineOperand &MO3 = MI->getOperand(Op+2); + + O << getRegisterName(MO1.getReg()); + + // Print the shift opc. + O << ", " + << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(MO3.getImm())) + << " "; + + if (MO2.getReg()) { + O << getRegisterName(MO2.getReg()); + assert(ARM_AM::getSORegOffset(MO3.getImm()) == 0); + } else { + O << "#" << ARM_AM::getSORegOffset(MO3.getImm()); + } +} + +void ARMAsmPrinter::printAddrMode2Operand(const MachineInstr *MI, int Op) { + const MachineOperand &MO1 = MI->getOperand(Op); + const MachineOperand &MO2 = MI->getOperand(Op+1); + const MachineOperand &MO3 = MI->getOperand(Op+2); + + if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right. + printOperand(MI, Op); + return; + } + + O << "[" << getRegisterName(MO1.getReg()); + + if (!MO2.getReg()) { + if (ARM_AM::getAM2Offset(MO3.getImm())) // Don't print +0. + O << ", #" + << (char)ARM_AM::getAM2Op(MO3.getImm()) + << ARM_AM::getAM2Offset(MO3.getImm()); + O << "]"; + return; + } + + O << ", " + << (char)ARM_AM::getAM2Op(MO3.getImm()) + << getRegisterName(MO2.getReg()); + + if (unsigned ShImm = ARM_AM::getAM2Offset(MO3.getImm())) + O << ", " + << ARM_AM::getShiftOpcStr(ARM_AM::getAM2ShiftOpc(MO3.getImm())) + << " #" << ShImm; + O << "]"; +} + +void ARMAsmPrinter::printAddrMode2OffsetOperand(const MachineInstr *MI, int Op){ + const MachineOperand &MO1 = MI->getOperand(Op); + const MachineOperand &MO2 = MI->getOperand(Op+1); + + if (!MO1.getReg()) { + unsigned ImmOffs = ARM_AM::getAM2Offset(MO2.getImm()); + assert(ImmOffs && "Malformed indexed load / store!"); + O << "#" + << (char)ARM_AM::getAM2Op(MO2.getImm()) + << ImmOffs; + return; + } + + O << (char)ARM_AM::getAM2Op(MO2.getImm()) + << getRegisterName(MO1.getReg()); + + if (unsigned ShImm = ARM_AM::getAM2Offset(MO2.getImm())) + O << ", " + << ARM_AM::getShiftOpcStr(ARM_AM::getAM2ShiftOpc(MO2.getImm())) + << " #" << ShImm; +} + +void ARMAsmPrinter::printAddrMode3Operand(const MachineInstr *MI, int Op) { + const MachineOperand &MO1 = MI->getOperand(Op); + const MachineOperand &MO2 = MI->getOperand(Op+1); + const MachineOperand &MO3 = MI->getOperand(Op+2); + + assert(TargetRegisterInfo::isPhysicalRegister(MO1.getReg())); + O << "[" << getRegisterName(MO1.getReg()); + + if (MO2.getReg()) { + O << ", " + << (char)ARM_AM::getAM3Op(MO3.getImm()) + << getRegisterName(MO2.getReg()) + << "]"; + return; + } + + if (unsigned ImmOffs = ARM_AM::getAM3Offset(MO3.getImm())) + O << ", #" + << (char)ARM_AM::getAM3Op(MO3.getImm()) + << ImmOffs; + O << "]"; +} + +void ARMAsmPrinter::printAddrMode3OffsetOperand(const MachineInstr *MI, int Op){ + const MachineOperand &MO1 = MI->getOperand(Op); + const MachineOperand &MO2 = MI->getOperand(Op+1); + + if (MO1.getReg()) { + O << (char)ARM_AM::getAM3Op(MO2.getImm()) + << getRegisterName(MO1.getReg()); + return; + } + + unsigned ImmOffs = ARM_AM::getAM3Offset(MO2.getImm()); + assert(ImmOffs && "Malformed indexed load / store!"); + O << "#" + << (char)ARM_AM::getAM3Op(MO2.getImm()) + << ImmOffs; +} + +void ARMAsmPrinter::printAddrMode4Operand(const MachineInstr *MI, int Op, + const char *Modifier) { + const MachineOperand &MO1 = MI->getOperand(Op); + const MachineOperand &MO2 = MI->getOperand(Op+1); + ARM_AM::AMSubMode Mode = ARM_AM::getAM4SubMode(MO2.getImm()); + if (Modifier && strcmp(Modifier, "submode") == 0) { + if (MO1.getReg() == ARM::SP) { + // FIXME + bool isLDM = (MI->getOpcode() == ARM::LDM || + MI->getOpcode() == ARM::LDM_RET || + MI->getOpcode() == ARM::t2LDM || + MI->getOpcode() == ARM::t2LDM_RET); + O << ARM_AM::getAMSubModeAltStr(Mode, isLDM); + } else + O << ARM_AM::getAMSubModeStr(Mode); + } else if (Modifier && strcmp(Modifier, "wide") == 0) { + ARM_AM::AMSubMode Mode = ARM_AM::getAM4SubMode(MO2.getImm()); + if (Mode == ARM_AM::ia) + O << ".w"; + } else { + printOperand(MI, Op); + if (ARM_AM::getAM4WBFlag(MO2.getImm())) + O << "!"; + } +} + +void ARMAsmPrinter::printAddrMode5Operand(const MachineInstr *MI, int Op, + const char *Modifier) { + const MachineOperand &MO1 = MI->getOperand(Op); + const MachineOperand &MO2 = MI->getOperand(Op+1); + + if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right. + printOperand(MI, Op); + return; + } + + assert(TargetRegisterInfo::isPhysicalRegister(MO1.getReg())); + + if (Modifier && strcmp(Modifier, "submode") == 0) { + ARM_AM::AMSubMode Mode = ARM_AM::getAM5SubMode(MO2.getImm()); + O << ARM_AM::getAMSubModeStr(Mode); + return; + } else if (Modifier && strcmp(Modifier, "base") == 0) { + // Used for FSTM{D|S} and LSTM{D|S} operations. + O << getRegisterName(MO1.getReg()); + if (ARM_AM::getAM5WBFlag(MO2.getImm())) + O << "!"; + return; + } + + O << "[" << getRegisterName(MO1.getReg()); + + if (unsigned ImmOffs = ARM_AM::getAM5Offset(MO2.getImm())) { + O << ", #" + << (char)ARM_AM::getAM5Op(MO2.getImm()) + << ImmOffs*4; + } + O << "]"; +} + +void ARMAsmPrinter::printAddrMode6Operand(const MachineInstr *MI, int Op) { + const MachineOperand &MO1 = MI->getOperand(Op); + const MachineOperand &MO2 = MI->getOperand(Op+1); + const MachineOperand &MO3 = MI->getOperand(Op+2); + const MachineOperand &MO4 = MI->getOperand(Op+3); + + O << "[" << getRegisterName(MO1.getReg()); + if (MO4.getImm()) { + // FIXME: Both darwin as and GNU as violate ARM docs here. + O << ", :" << MO4.getImm(); + } + O << "]"; + + if (ARM_AM::getAM6WBFlag(MO3.getImm())) { + if (MO2.getReg() == 0) + O << "!"; + else + O << ", " << getRegisterName(MO2.getReg()); + } +} + +void ARMAsmPrinter::printAddrModePCOperand(const MachineInstr *MI, int Op, + const char *Modifier) { + if (Modifier && strcmp(Modifier, "label") == 0) { + printPCLabel(MI, Op+1); + return; + } + + const MachineOperand &MO1 = MI->getOperand(Op); + assert(TargetRegisterInfo::isPhysicalRegister(MO1.getReg())); + O << "[pc, +" << getRegisterName(MO1.getReg()) << "]"; +} + +void +ARMAsmPrinter::printBitfieldInvMaskImmOperand(const MachineInstr *MI, int Op) { + const MachineOperand &MO = MI->getOperand(Op); + uint32_t v = ~MO.getImm(); + int32_t lsb = CountTrailingZeros_32(v); + int32_t width = (32 - CountLeadingZeros_32 (v)) - lsb; + assert(MO.isImm() && "Not a valid bf_inv_mask_imm value!"); + O << "#" << lsb << ", #" << width; +} + +//===--------------------------------------------------------------------===// + +void ARMAsmPrinter::printThumbS4ImmOperand(const MachineInstr *MI, int Op) { + O << "#" << MI->getOperand(Op).getImm() * 4; +} + +void +ARMAsmPrinter::printThumbITMask(const MachineInstr *MI, int Op) { + // (3 - the number of trailing zeros) is the number of then / else. + unsigned Mask = MI->getOperand(Op).getImm(); + unsigned NumTZ = CountTrailingZeros_32(Mask); + assert(NumTZ <= 3 && "Invalid IT mask!"); + for (unsigned Pos = 3, e = NumTZ; Pos > e; --Pos) { + bool T = (Mask & (1 << Pos)) == 0; + if (T) + O << 't'; + else + O << 'e'; + } +} + +void +ARMAsmPrinter::printThumbAddrModeRROperand(const MachineInstr *MI, int Op) { + const MachineOperand &MO1 = MI->getOperand(Op); + const MachineOperand &MO2 = MI->getOperand(Op+1); + O << "[" << getRegisterName(MO1.getReg()); + O << ", " << getRegisterName(MO2.getReg()) << "]"; +} + +void +ARMAsmPrinter::printThumbAddrModeRI5Operand(const MachineInstr *MI, int Op, + unsigned Scale) { + const MachineOperand &MO1 = MI->getOperand(Op); + const MachineOperand &MO2 = MI->getOperand(Op+1); + const MachineOperand &MO3 = MI->getOperand(Op+2); + + if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right. + printOperand(MI, Op); + return; + } + + O << "[" << getRegisterName(MO1.getReg()); + if (MO3.getReg()) + O << ", " << getRegisterName(MO3.getReg()); + else if (unsigned ImmOffs = MO2.getImm()) + O << ", #+" << ImmOffs * Scale; + O << "]"; +} + +void +ARMAsmPrinter::printThumbAddrModeS1Operand(const MachineInstr *MI, int Op) { + printThumbAddrModeRI5Operand(MI, Op, 1); +} +void +ARMAsmPrinter::printThumbAddrModeS2Operand(const MachineInstr *MI, int Op) { + printThumbAddrModeRI5Operand(MI, Op, 2); +} +void +ARMAsmPrinter::printThumbAddrModeS4Operand(const MachineInstr *MI, int Op) { + printThumbAddrModeRI5Operand(MI, Op, 4); +} + +void ARMAsmPrinter::printThumbAddrModeSPOperand(const MachineInstr *MI,int Op) { + const MachineOperand &MO1 = MI->getOperand(Op); + const MachineOperand &MO2 = MI->getOperand(Op+1); + O << "[" << getRegisterName(MO1.getReg()); + if (unsigned ImmOffs = MO2.getImm()) + O << ", #+" << ImmOffs*4; + O << "]"; +} + +//===--------------------------------------------------------------------===// + +// Constant shifts t2_so_reg is a 2-operand unit corresponding to the Thumb2 +// register with shift forms. +// REG 0 0 - e.g. R5 +// REG IMM, SH_OPC - e.g. R5, LSL #3 +void ARMAsmPrinter::printT2SOOperand(const MachineInstr *MI, int OpNum) { + const MachineOperand &MO1 = MI->getOperand(OpNum); + const MachineOperand &MO2 = MI->getOperand(OpNum+1); + + unsigned Reg = MO1.getReg(); + assert(TargetRegisterInfo::isPhysicalRegister(Reg)); + O << getRegisterName(Reg); + + // Print the shift opc. + O << ", " + << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(MO2.getImm())) + << " "; + + assert(MO2.isImm() && "Not a valid t2_so_reg value!"); + O << "#" << ARM_AM::getSORegOffset(MO2.getImm()); +} + +void ARMAsmPrinter::printT2AddrModeImm12Operand(const MachineInstr *MI, + int OpNum) { + const MachineOperand &MO1 = MI->getOperand(OpNum); + const MachineOperand &MO2 = MI->getOperand(OpNum+1); + + O << "[" << getRegisterName(MO1.getReg()); + + unsigned OffImm = MO2.getImm(); + if (OffImm) // Don't print +0. + O << ", #+" << OffImm; + O << "]"; +} + +void ARMAsmPrinter::printT2AddrModeImm8Operand(const MachineInstr *MI, + int OpNum) { + const MachineOperand &MO1 = MI->getOperand(OpNum); + const MachineOperand &MO2 = MI->getOperand(OpNum+1); + + O << "[" << getRegisterName(MO1.getReg()); + + int32_t OffImm = (int32_t)MO2.getImm(); + // Don't print +0. + if (OffImm < 0) + O << ", #-" << -OffImm; + else if (OffImm > 0) + O << ", #+" << OffImm; + O << "]"; +} + +void ARMAsmPrinter::printT2AddrModeImm8s4Operand(const MachineInstr *MI, + int OpNum) { + const MachineOperand &MO1 = MI->getOperand(OpNum); + const MachineOperand &MO2 = MI->getOperand(OpNum+1); + + O << "[" << getRegisterName(MO1.getReg()); + + int32_t OffImm = (int32_t)MO2.getImm() / 4; + // Don't print +0. + if (OffImm < 0) + O << ", #-" << -OffImm * 4; + else if (OffImm > 0) + O << ", #+" << OffImm * 4; + O << "]"; +} + +void ARMAsmPrinter::printT2AddrModeImm8OffsetOperand(const MachineInstr *MI, + int OpNum) { + const MachineOperand &MO1 = MI->getOperand(OpNum); + int32_t OffImm = (int32_t)MO1.getImm(); + // Don't print +0. + if (OffImm < 0) + O << "#-" << -OffImm; + else if (OffImm > 0) + O << "#+" << OffImm; +} + +void ARMAsmPrinter::printT2AddrModeSoRegOperand(const MachineInstr *MI, + int OpNum) { + const MachineOperand &MO1 = MI->getOperand(OpNum); + const MachineOperand &MO2 = MI->getOperand(OpNum+1); + const MachineOperand &MO3 = MI->getOperand(OpNum+2); + + O << "[" << getRegisterName(MO1.getReg()); + + assert(MO2.getReg() && "Invalid so_reg load / store address!"); + O << ", " << getRegisterName(MO2.getReg()); + + unsigned ShAmt = MO3.getImm(); + if (ShAmt) { + assert(ShAmt <= 3 && "Not a valid Thumb2 addressing mode!"); + O << ", lsl #" << ShAmt; + } + O << "]"; +} + + +//===--------------------------------------------------------------------===// + +void ARMAsmPrinter::printPredicateOperand(const MachineInstr *MI, int OpNum) { + ARMCC::CondCodes CC = (ARMCC::CondCodes)MI->getOperand(OpNum).getImm(); + if (CC != ARMCC::AL) + O << ARMCondCodeToString(CC); +} + +void ARMAsmPrinter::printSBitModifierOperand(const MachineInstr *MI, int OpNum){ + unsigned Reg = MI->getOperand(OpNum).getReg(); + if (Reg) { + assert(Reg == ARM::CPSR && "Expect ARM CPSR register!"); + O << 's'; + } +} + +void ARMAsmPrinter::printPCLabel(const MachineInstr *MI, int OpNum) { + int Id = (int)MI->getOperand(OpNum).getImm(); + O << MAI->getPrivateGlobalPrefix() + << "PC" << getFunctionNumber() << "_" << Id; +} + +void ARMAsmPrinter::printRegisterList(const MachineInstr *MI, int OpNum) { + O << "{"; + // Always skip the first operand, it's the optional (and implicit writeback). + for (unsigned i = OpNum+1, e = MI->getNumOperands(); i != e; ++i) { + if (MI->getOperand(i).isImplicit()) + continue; + if ((int)i != OpNum+1) O << ", "; + printOperand(MI, i); + } + O << "}"; +} + +void ARMAsmPrinter::printCPInstOperand(const MachineInstr *MI, int OpNum, + const char *Modifier) { + assert(Modifier && "This operand only works with a modifier!"); + // There are two aspects to a CONSTANTPOOL_ENTRY operand, the label and the + // data itself. + if (!strcmp(Modifier, "label")) { + unsigned ID = MI->getOperand(OpNum).getImm(); + O << MAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() + << '_' << ID << ":\n"; + } else { + assert(!strcmp(Modifier, "cpentry") && "Unknown modifier for CPE"); + unsigned CPI = MI->getOperand(OpNum).getIndex(); + + const MachineConstantPoolEntry &MCPE = MCP->getConstants()[CPI]; + + if (MCPE.isMachineConstantPoolEntry()) { + EmitMachineConstantPoolValue(MCPE.Val.MachineCPVal); + } else { + EmitGlobalConstant(MCPE.Val.ConstVal); + } + } +} + +void ARMAsmPrinter::printJTBlockOperand(const MachineInstr *MI, int OpNum) { + assert(!Subtarget->isThumb2() && "Thumb2 should use double-jump jumptables!"); + + const MachineOperand &MO1 = MI->getOperand(OpNum); + const MachineOperand &MO2 = MI->getOperand(OpNum+1); // Unique Id + unsigned JTI = MO1.getIndex(); + O << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() + << '_' << JTI << '_' << MO2.getImm() << ":\n"; + + const char *JTEntryDirective = MAI->getData32bitsDirective(); + + const MachineFunction *MF = MI->getParent()->getParent(); + const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo(); + const std::vector &JT = MJTI->getJumpTables(); + const std::vector &JTBBs = JT[JTI].MBBs; + bool UseSet= MAI->getSetDirective() && TM.getRelocationModel() == Reloc::PIC_; + SmallPtrSet JTSets; + for (unsigned i = 0, e = JTBBs.size(); i != e; ++i) { + MachineBasicBlock *MBB = JTBBs[i]; + bool isNew = JTSets.insert(MBB); + + if (UseSet && isNew) + printPICJumpTableSetLabel(JTI, MO2.getImm(), MBB); + + O << JTEntryDirective << ' '; + if (UseSet) + O << MAI->getPrivateGlobalPrefix() << getFunctionNumber() + << '_' << JTI << '_' << MO2.getImm() + << "_set_" << MBB->getNumber(); + else if (TM.getRelocationModel() == Reloc::PIC_) { + GetMBBSymbol(MBB->getNumber())->print(O, MAI); + O << '-' << MAI->getPrivateGlobalPrefix() << "JTI" + << getFunctionNumber() << '_' << JTI << '_' << MO2.getImm(); + } else { + GetMBBSymbol(MBB->getNumber())->print(O, MAI); + } + if (i != e-1) + O << '\n'; + } +} + +void ARMAsmPrinter::printJT2BlockOperand(const MachineInstr *MI, int OpNum) { + const MachineOperand &MO1 = MI->getOperand(OpNum); + const MachineOperand &MO2 = MI->getOperand(OpNum+1); // Unique Id + unsigned JTI = MO1.getIndex(); + O << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() + << '_' << JTI << '_' << MO2.getImm() << ":\n"; + + const MachineFunction *MF = MI->getParent()->getParent(); + const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo(); + const std::vector &JT = MJTI->getJumpTables(); + const std::vector &JTBBs = JT[JTI].MBBs; + bool ByteOffset = false, HalfWordOffset = false; + if (MI->getOpcode() == ARM::t2TBB) + ByteOffset = true; + else if (MI->getOpcode() == ARM::t2TBH) + HalfWordOffset = true; + + for (unsigned i = 0, e = JTBBs.size(); i != e; ++i) { + MachineBasicBlock *MBB = JTBBs[i]; + if (ByteOffset) + O << MAI->getData8bitsDirective(); + else if (HalfWordOffset) + O << MAI->getData16bitsDirective(); + if (ByteOffset || HalfWordOffset) { + O << '('; + GetMBBSymbol(MBB->getNumber())->print(O, MAI); + O << "-" << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() + << '_' << JTI << '_' << MO2.getImm() << ")/2"; + } else { + O << "\tb.w "; + GetMBBSymbol(MBB->getNumber())->print(O, MAI); + } + if (i != e-1) + O << '\n'; + } + + // Make sure the instruction that follows TBB is 2-byte aligned. + // FIXME: Constant island pass should insert an "ALIGN" instruction instead. + if (ByteOffset && (JTBBs.size() & 1)) { + O << '\n'; + EmitAlignment(1); + } +} + +void ARMAsmPrinter::printTBAddrMode(const MachineInstr *MI, int OpNum) { + O << "[pc, " << getRegisterName(MI->getOperand(OpNum).getReg()); + if (MI->getOpcode() == ARM::t2TBH) + O << ", lsl #1"; + O << ']'; +} + +void ARMAsmPrinter::printNoHashImmediate(const MachineInstr *MI, int OpNum) { + O << MI->getOperand(OpNum).getImm(); +} + +void ARMAsmPrinter::printVFPf32ImmOperand(const MachineInstr *MI, int OpNum) { + const ConstantFP *FP = MI->getOperand(OpNum).getFPImm(); + O << '#' << FP->getValueAPF().convertToFloat(); + if (VerboseAsm) { + O.PadToColumn(MAI->getCommentColumn()); + O << MAI->getCommentString() << ' '; + WriteAsOperand(O, FP, /*PrintType=*/false); + } +} + +void ARMAsmPrinter::printVFPf64ImmOperand(const MachineInstr *MI, int OpNum) { + const ConstantFP *FP = MI->getOperand(OpNum).getFPImm(); + O << '#' << FP->getValueAPF().convertToDouble(); + if (VerboseAsm) { + O.PadToColumn(MAI->getCommentColumn()); + O << MAI->getCommentString() << ' '; + WriteAsOperand(O, FP, /*PrintType=*/false); + } +} + +bool ARMAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNum, + unsigned AsmVariant, const char *ExtraCode){ + // Does this asm operand have a single letter operand modifier? + if (ExtraCode && ExtraCode[0]) { + if (ExtraCode[1] != 0) return true; // Unknown modifier. + + switch (ExtraCode[0]) { + default: return true; // Unknown modifier. + case 'a': // Print as a memory address. + if (MI->getOperand(OpNum).isReg()) { + O << "[" << getRegisterName(MI->getOperand(OpNum).getReg()) << "]"; + return false; + } + // Fallthrough + case 'c': // Don't print "#" before an immediate operand. + if (!MI->getOperand(OpNum).isImm()) + return true; + printNoHashImmediate(MI, OpNum); + return false; + case 'P': // Print a VFP double precision register. + printOperand(MI, OpNum); + return false; + case 'Q': + if (TM.getTargetData()->isLittleEndian()) + break; + // Fallthrough + case 'R': + if (TM.getTargetData()->isBigEndian()) + break; + // Fallthrough + case 'H': // Write second word of DI / DF reference. + // Verify that this operand has two consecutive registers. + if (!MI->getOperand(OpNum).isReg() || + OpNum+1 == MI->getNumOperands() || + !MI->getOperand(OpNum+1).isReg()) + return true; + ++OpNum; // Return the high-part. + } + } + + printOperand(MI, OpNum); + return false; +} + +bool ARMAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, + unsigned OpNum, unsigned AsmVariant, + const char *ExtraCode) { + if (ExtraCode && ExtraCode[0]) + return true; // Unknown modifier. + + const MachineOperand &MO = MI->getOperand(OpNum); + assert(MO.isReg() && "unexpected inline asm memory operand"); + O << "[" << getRegisterName(MO.getReg()) << "]"; + return false; +} + +void ARMAsmPrinter::printMachineInstruction(const MachineInstr *MI) { + ++EmittedInsts; + + // Call the autogenerated instruction printer routines. + processDebugLoc(MI, true); + + if (EnableMCInst) { + printInstructionThroughMCStreamer(MI); + } else { + int Opc = MI->getOpcode(); + if (Opc == ARM::CONSTPOOL_ENTRY) + EmitAlignment(2); + + printInstruction(MI); + } + + if (VerboseAsm) + EmitComments(*MI); + O << '\n'; + processDebugLoc(MI, false); +} + +void ARMAsmPrinter::EmitStartOfAsmFile(Module &M) { + if (Subtarget->isTargetDarwin()) { + Reloc::Model RelocM = TM.getRelocationModel(); + if (RelocM == Reloc::PIC_ || RelocM == Reloc::DynamicNoPIC) { + // Declare all the text sections up front (before the DWARF sections + // emitted by AsmPrinter::doInitialization) so the assembler will keep + // them together at the beginning of the object file. This helps + // avoid out-of-range branches that are due a fundamental limitation of + // the way symbol offsets are encoded with the current Darwin ARM + // relocations. + TargetLoweringObjectFileMachO &TLOFMacho = + static_cast(getObjFileLowering()); + OutStreamer.SwitchSection(TLOFMacho.getTextSection()); + OutStreamer.SwitchSection(TLOFMacho.getTextCoalSection()); + OutStreamer.SwitchSection(TLOFMacho.getConstTextCoalSection()); + if (RelocM == Reloc::DynamicNoPIC) { + const MCSection *sect = + TLOFMacho.getMachOSection("__TEXT", "__symbol_stub4", + MCSectionMachO::S_SYMBOL_STUBS, + 12, SectionKind::getText()); + OutStreamer.SwitchSection(sect); + } else { + const MCSection *sect = + TLOFMacho.getMachOSection("__TEXT", "__picsymbolstub4", + MCSectionMachO::S_SYMBOL_STUBS, + 16, SectionKind::getText()); + OutStreamer.SwitchSection(sect); + } + } + } + + // Use unified assembler syntax. + O << "\t.syntax unified\n"; + + // Emit ARM Build Attributes + if (Subtarget->isTargetELF()) { + // CPU Type + std::string CPUString = Subtarget->getCPUString(); + if (CPUString != "generic") + O << "\t.cpu " << CPUString << '\n'; + + // FIXME: Emit FPU type + if (Subtarget->hasVFP2()) + O << "\t.eabi_attribute " << ARMBuildAttrs::VFP_arch << ", 2\n"; + + // Signal various FP modes. + if (!UnsafeFPMath) + O << "\t.eabi_attribute " << ARMBuildAttrs::ABI_FP_denormal << ", 1\n" + << "\t.eabi_attribute " << ARMBuildAttrs::ABI_FP_exceptions << ", 1\n"; + + if (FiniteOnlyFPMath()) + O << "\t.eabi_attribute " << ARMBuildAttrs::ABI_FP_number_model << ", 1\n"; + else + O << "\t.eabi_attribute " << ARMBuildAttrs::ABI_FP_number_model << ", 3\n"; + + // 8-bytes alignment stuff. + O << "\t.eabi_attribute " << ARMBuildAttrs::ABI_align8_needed << ", 1\n" + << "\t.eabi_attribute " << ARMBuildAttrs::ABI_align8_preserved << ", 1\n"; + + // Hard float. Use both S and D registers and conform to AAPCS-VFP. + if (Subtarget->isAAPCS_ABI() && FloatABIType == FloatABI::Hard) + O << "\t.eabi_attribute " << ARMBuildAttrs::ABI_HardFP_use << ", 3\n" + << "\t.eabi_attribute " << ARMBuildAttrs::ABI_VFP_args << ", 1\n"; + + // FIXME: Should we signal R9 usage? + } +} + +void ARMAsmPrinter::PrintGlobalVariable(const GlobalVariable* GVar) { + const TargetData *TD = TM.getTargetData(); + + if (!GVar->hasInitializer()) // External global require no code + return; + + // Check to see if this is a special global used by LLVM, if so, emit it. + + if (EmitSpecialLLVMGlobal(GVar)) { + if (Subtarget->isTargetDarwin() && + TM.getRelocationModel() == Reloc::Static) { + if (GVar->getName() == "llvm.global_ctors") + O << ".reference .constructors_used\n"; + else if (GVar->getName() == "llvm.global_dtors") + O << ".reference .destructors_used\n"; + } + return; + } + + std::string name = Mang->getMangledName(GVar); + Constant *C = GVar->getInitializer(); + const Type *Type = C->getType(); + unsigned Size = TD->getTypeAllocSize(Type); + unsigned Align = TD->getPreferredAlignmentLog(GVar); + bool isDarwin = Subtarget->isTargetDarwin(); + + printVisibility(name, GVar->getVisibility()); + + if (Subtarget->isTargetELF()) + O << "\t.type " << name << ",%object\n"; + + const MCSection *TheSection = + getObjFileLowering().SectionForGlobal(GVar, Mang, TM); + OutStreamer.SwitchSection(TheSection); + + // FIXME: get this stuff from section kind flags. + if (C->isNullValue() && !GVar->hasSection() && !GVar->isThreadLocal() && + // Don't put things that should go in the cstring section into "comm". + !TheSection->getKind().isMergeableCString()) { + if (GVar->hasExternalLinkage()) { + if (const char *Directive = MAI->getZeroFillDirective()) { + O << "\t.globl\t" << name << "\n"; + O << Directive << "__DATA, __common, " << name << ", " + << Size << ", " << Align << "\n"; + return; + } + } + + if (GVar->hasLocalLinkage() || GVar->isWeakForLinker()) { + if (Size == 0) Size = 1; // .comm Foo, 0 is undefined, avoid it. + + if (isDarwin) { + if (GVar->hasLocalLinkage()) { + O << MAI->getLCOMMDirective() << name << "," << Size + << ',' << Align; + } else if (GVar->hasCommonLinkage()) { + O << MAI->getCOMMDirective() << name << "," << Size + << ',' << Align; + } else { + OutStreamer.SwitchSection(TheSection); + O << "\t.globl " << name << '\n' + << MAI->getWeakDefDirective() << name << '\n'; + EmitAlignment(Align, GVar); + O << name << ":"; + if (VerboseAsm) { + O.PadToColumn(MAI->getCommentColumn()); + O << MAI->getCommentString() << ' '; + WriteAsOperand(O, GVar, /*PrintType=*/false, GVar->getParent()); + } + O << '\n'; + EmitGlobalConstant(C); + return; + } + } else if (MAI->getLCOMMDirective() != NULL) { + if (GVar->hasLocalLinkage()) { + O << MAI->getLCOMMDirective() << name << "," << Size; + } else { + O << MAI->getCOMMDirective() << name << "," << Size; + if (MAI->getCOMMDirectiveTakesAlignment()) + O << ',' << (MAI->getAlignmentIsInBytes() ? (1 << Align) : Align); + } + } else { + if (GVar->hasLocalLinkage()) + O << "\t.local\t" << name << "\n"; + O << MAI->getCOMMDirective() << name << "," << Size; + if (MAI->getCOMMDirectiveTakesAlignment()) + O << "," << (MAI->getAlignmentIsInBytes() ? (1 << Align) : Align); + } + if (VerboseAsm) { + O.PadToColumn(MAI->getCommentColumn()); + O << MAI->getCommentString() << ' '; + WriteAsOperand(O, GVar, /*PrintType=*/false, GVar->getParent()); + } + O << "\n"; + return; + } + } + + switch (GVar->getLinkage()) { + case GlobalValue::CommonLinkage: + case GlobalValue::LinkOnceAnyLinkage: + case GlobalValue::LinkOnceODRLinkage: + case GlobalValue::WeakAnyLinkage: + case GlobalValue::WeakODRLinkage: + case GlobalValue::LinkerPrivateLinkage: + if (isDarwin) { + O << "\t.globl " << name << "\n" + << "\t.weak_definition " << name << "\n"; + } else { + O << "\t.weak " << name << "\n"; + } + break; + case GlobalValue::AppendingLinkage: + // FIXME: appending linkage variables should go into a section of + // their name or something. For now, just emit them as external. + case GlobalValue::ExternalLinkage: + O << "\t.globl " << name << "\n"; + break; + case GlobalValue::PrivateLinkage: + case GlobalValue::InternalLinkage: + break; + default: + llvm_unreachable("Unknown linkage type!"); + } + + EmitAlignment(Align, GVar); + O << name << ":"; + if (VerboseAsm) { + O.PadToColumn(MAI->getCommentColumn()); + O << MAI->getCommentString() << ' '; + WriteAsOperand(O, GVar, /*PrintType=*/false, GVar->getParent()); + } + O << "\n"; + if (MAI->hasDotTypeDotSizeDirective()) + O << "\t.size " << name << ", " << Size << "\n"; + + EmitGlobalConstant(C); + O << '\n'; +} + + +void ARMAsmPrinter::EmitEndOfAsmFile(Module &M) { + if (Subtarget->isTargetDarwin()) { + // All darwin targets use mach-o. + TargetLoweringObjectFileMachO &TLOFMacho = + static_cast(getObjFileLowering()); + MachineModuleInfoMachO &MMIMacho = + MMI->getObjFileInfo(); + + O << '\n'; + + // Output non-lazy-pointers for external and common global variables. + MachineModuleInfoMachO::SymbolListTy Stubs = MMIMacho.GetGVStubList(); + + if (!Stubs.empty()) { + // Switch with ".non_lazy_symbol_pointer" directive. + OutStreamer.SwitchSection(TLOFMacho.getNonLazySymbolPointerSection()); + EmitAlignment(2); + for (unsigned i = 0, e = Stubs.size(); i != e; ++i) { + Stubs[i].first->print(O, MAI); + O << ":\n\t.indirect_symbol "; + Stubs[i].second->print(O, MAI); + O << "\n\t.long\t0\n"; + } + } + + Stubs = MMIMacho.GetHiddenGVStubList(); + if (!Stubs.empty()) { + OutStreamer.SwitchSection(getObjFileLowering().getDataSection()); + EmitAlignment(2); + for (unsigned i = 0, e = Stubs.size(); i != e; ++i) { + Stubs[i].first->print(O, MAI); + O << ":\n\t.long "; + Stubs[i].second->print(O, MAI); + O << "\n"; + } + } + + // Funny Darwin hack: This flag tells the linker that no global symbols + // contain code that falls through to other global symbols (e.g. the obvious + // implementation of multiple entry points). If this doesn't occur, the + // linker can safely perform dead code stripping. Since LLVM never + // generates code that does this, it is always safe to set. + OutStreamer.EmitAssemblerFlag(MCStreamer::SubsectionsViaSymbols); + } +} + +//===----------------------------------------------------------------------===// + +void ARMAsmPrinter::printInstructionThroughMCStreamer(const MachineInstr *MI) { + ARMMCInstLower MCInstLowering(OutContext, *Mang, *this); + switch (MI->getOpcode()) { + case ARM::t2MOVi32imm: + assert(0 && "Should be lowered by thumb2it pass"); + default: break; + case TargetInstrInfo::DBG_LABEL: + case TargetInstrInfo::EH_LABEL: + case TargetInstrInfo::GC_LABEL: + printLabel(MI); + return; + case TargetInstrInfo::KILL: + printKill(MI); + return; + case TargetInstrInfo::INLINEASM: + printInlineAsm(MI); + return; + case TargetInstrInfo::IMPLICIT_DEF: + printImplicitDef(MI); + return; + case ARM::PICADD: { // FIXME: Remove asm string from td file. + // This is a pseudo op for a label + instruction sequence, which looks like: + // LPC0: + // add r0, pc, r0 + // This adds the address of LPC0 to r0. + + // Emit the label. + // FIXME: MOVE TO SHARED PLACE. + unsigned Id = (unsigned)MI->getOperand(2).getImm(); + const char *Prefix = MAI->getPrivateGlobalPrefix(); + MCSymbol *Label =OutContext.GetOrCreateSymbol(Twine(Prefix) + + "PC" + Twine(getFunctionNumber()) + "_" + Twine(Id)); + OutStreamer.EmitLabel(Label); + + + // Form and emit tha dd. + MCInst AddInst; + AddInst.setOpcode(ARM::ADDrr); + AddInst.addOperand(MCOperand::CreateReg(MI->getOperand(0).getReg())); + AddInst.addOperand(MCOperand::CreateReg(ARM::PC)); + AddInst.addOperand(MCOperand::CreateReg(MI->getOperand(1).getReg())); + printMCInst(&AddInst); + return; + } + case ARM::CONSTPOOL_ENTRY: { // FIXME: Remove asm string from td file. + /// CONSTPOOL_ENTRY - This instruction represents a floating constant pool + /// in the function. The first operand is the ID# for this instruction, the + /// second is the index into the MachineConstantPool that this is, the third + /// is the size in bytes of this constant pool entry. + unsigned LabelId = (unsigned)MI->getOperand(0).getImm(); + unsigned CPIdx = (unsigned)MI->getOperand(1).getIndex(); + + EmitAlignment(2); + + const char *Prefix = MAI->getPrivateGlobalPrefix(); + MCSymbol *Label = OutContext.GetOrCreateSymbol(Twine(Prefix)+"CPI"+ + Twine(getFunctionNumber())+ + "_"+ Twine(LabelId)); + OutStreamer.EmitLabel(Label); + + const MachineConstantPoolEntry &MCPE = MCP->getConstants()[CPIdx]; + if (MCPE.isMachineConstantPoolEntry()) + EmitMachineConstantPoolValue(MCPE.Val.MachineCPVal); + else + EmitGlobalConstant(MCPE.Val.ConstVal); + + return; + } + case ARM::MOVi2pieces: { // FIXME: Remove asmstring from td file. + // This is a hack that lowers as a two instruction sequence. + unsigned DstReg = MI->getOperand(0).getReg(); + unsigned ImmVal = (unsigned)MI->getOperand(1).getImm(); + + unsigned SOImmValV1 = ARM_AM::getSOImmTwoPartFirst(ImmVal); + unsigned SOImmValV2 = ARM_AM::getSOImmTwoPartSecond(ImmVal); + + { + MCInst TmpInst; + TmpInst.setOpcode(ARM::MOVi); + TmpInst.addOperand(MCOperand::CreateReg(DstReg)); + TmpInst.addOperand(MCOperand::CreateImm(SOImmValV1)); + + // Predicate. + TmpInst.addOperand(MCOperand::CreateImm(MI->getOperand(2).getImm())); + TmpInst.addOperand(MCOperand::CreateReg(MI->getOperand(3).getReg())); + + TmpInst.addOperand(MCOperand::CreateReg(0)); // cc_out + printMCInst(&TmpInst); + O << '\n'; + } + + { + MCInst TmpInst; + TmpInst.setOpcode(ARM::ORRri); + TmpInst.addOperand(MCOperand::CreateReg(DstReg)); // dstreg + TmpInst.addOperand(MCOperand::CreateReg(DstReg)); // inreg + TmpInst.addOperand(MCOperand::CreateImm(SOImmValV2)); // so_imm + // Predicate. + TmpInst.addOperand(MCOperand::CreateImm(MI->getOperand(2).getImm())); + TmpInst.addOperand(MCOperand::CreateReg(MI->getOperand(3).getReg())); + + TmpInst.addOperand(MCOperand::CreateReg(0)); // cc_out + printMCInst(&TmpInst); + } + return; + } + case ARM::MOVi32imm: { // FIXME: Remove asmstring from td file. + // This is a hack that lowers as a two instruction sequence. + unsigned DstReg = MI->getOperand(0).getReg(); + unsigned ImmVal = (unsigned)MI->getOperand(1).getImm(); + + { + MCInst TmpInst; + TmpInst.setOpcode(ARM::MOVi16); + TmpInst.addOperand(MCOperand::CreateReg(DstReg)); // dstreg + TmpInst.addOperand(MCOperand::CreateImm(ImmVal & 65535)); // lower16(imm) + + // Predicate. + TmpInst.addOperand(MCOperand::CreateImm(MI->getOperand(2).getImm())); + TmpInst.addOperand(MCOperand::CreateReg(MI->getOperand(3).getReg())); + + printMCInst(&TmpInst); + O << '\n'; + } + + { + MCInst TmpInst; + TmpInst.setOpcode(ARM::MOVTi16); + TmpInst.addOperand(MCOperand::CreateReg(DstReg)); // dstreg + TmpInst.addOperand(MCOperand::CreateReg(DstReg)); // srcreg + TmpInst.addOperand(MCOperand::CreateImm(ImmVal >> 16)); // upper16(imm) + + // Predicate. + TmpInst.addOperand(MCOperand::CreateImm(MI->getOperand(2).getImm())); + TmpInst.addOperand(MCOperand::CreateReg(MI->getOperand(3).getReg())); + + printMCInst(&TmpInst); + } + + return; + } + } + + MCInst TmpInst; + MCInstLowering.Lower(MI, TmpInst); + + printMCInst(&TmpInst); +} + +//===----------------------------------------------------------------------===// +// Target Registry Stuff +//===----------------------------------------------------------------------===// + +static MCInstPrinter *createARMMCInstPrinter(const Target &T, + unsigned SyntaxVariant, + const MCAsmInfo &MAI, + raw_ostream &O) { + if (SyntaxVariant == 0) + return new ARMInstPrinter(O, MAI, false); + return 0; +} + +// Force static initialization. +extern "C" void LLVMInitializeARMAsmPrinter() { + RegisterAsmPrinter X(TheARMTarget); + RegisterAsmPrinter Y(TheThumbTarget); + + TargetRegistry::RegisterMCInstPrinter(TheARMTarget, createARMMCInstPrinter); + TargetRegistry::RegisterMCInstPrinter(TheThumbTarget, createARMMCInstPrinter); +} + diff --git a/libclamav/c++/llvm/lib/Target/ARM/AsmPrinter/ARMInstPrinter.cpp b/libclamav/c++/llvm/lib/Target/ARM/AsmPrinter/ARMInstPrinter.cpp new file mode 100644 index 000000000..9fc57e0de --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/ARM/AsmPrinter/ARMInstPrinter.cpp @@ -0,0 +1,358 @@ +//===-- ARMInstPrinter.cpp - Convert ARM MCInst to assembly syntax --------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This class prints an ARM MCInst to a .s file. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "asm-printer" +#include "ARM.h" // FIXME: FACTOR ENUMS BETTER. +#include "ARMInstPrinter.h" +#include "ARMAddressingModes.h" +#include "llvm/MC/MCInst.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +// Include the auto-generated portion of the assembly writer. +#define MachineInstr MCInst +#define ARMAsmPrinter ARMInstPrinter // FIXME: REMOVE. +#define NO_ASM_WRITER_BOILERPLATE +#include "ARMGenAsmWriter.inc" +#undef MachineInstr +#undef ARMAsmPrinter + +void ARMInstPrinter::printInst(const MCInst *MI) { printInstruction(MI); } + +void ARMInstPrinter::printOperand(const MCInst *MI, unsigned OpNo, + const char *Modifier) { + const MCOperand &Op = MI->getOperand(OpNo); + if (Op.isReg()) { + unsigned Reg = Op.getReg(); + if (Modifier && strcmp(Modifier, "dregpair") == 0) { + // FIXME: Breaks e.g. ARM/vmul.ll. + assert(0); + /* + unsigned DRegLo = TRI->getSubReg(Reg, 5); // arm_dsubreg_0 + unsigned DRegHi = TRI->getSubReg(Reg, 6); // arm_dsubreg_1 + O << '{' + << getRegisterName(DRegLo) << ',' << getRegisterName(DRegHi) + << '}';*/ + } else if (Modifier && strcmp(Modifier, "lane") == 0) { + assert(0); + /* + unsigned RegNum = ARMRegisterInfo::getRegisterNumbering(Reg); + unsigned DReg = TRI->getMatchingSuperReg(Reg, RegNum & 1 ? 2 : 1, + &ARM::DPR_VFP2RegClass); + O << getRegisterName(DReg) << '[' << (RegNum & 1) << ']'; + */ + } else { + O << getRegisterName(Reg); + } + } else if (Op.isImm()) { + assert((Modifier == 0 || Modifier[0] == 0) && "No modifiers supported"); + O << '#' << Op.getImm(); + } else { + assert((Modifier == 0 || Modifier[0] == 0) && "No modifiers supported"); + assert(Op.isExpr() && "unknown operand kind in printOperand"); + Op.getExpr()->print(O, &MAI); + } +} + +static void printSOImm(raw_ostream &O, int64_t V, bool VerboseAsm, + const MCAsmInfo *MAI) { + // Break it up into two parts that make up a shifter immediate. + V = ARM_AM::getSOImmVal(V); + assert(V != -1 && "Not a valid so_imm value!"); + + unsigned Imm = ARM_AM::getSOImmValImm(V); + unsigned Rot = ARM_AM::getSOImmValRot(V); + + // Print low-level immediate formation info, per + // A5.1.3: "Data-processing operands - Immediate". + if (Rot) { + O << "#" << Imm << ", " << Rot; + // Pretty printed version. + if (VerboseAsm) + O << ' ' << MAI->getCommentString() + << ' ' << (int)ARM_AM::rotr32(Imm, Rot); + } else { + O << "#" << Imm; + } +} + + +/// printSOImmOperand - SOImm is 4-bit rotate amount in bits 8-11 with 8-bit +/// immediate in bits 0-7. +void ARMInstPrinter::printSOImmOperand(const MCInst *MI, unsigned OpNum) { + const MCOperand &MO = MI->getOperand(OpNum); + assert(MO.isImm() && "Not a valid so_imm value!"); + printSOImm(O, MO.getImm(), VerboseAsm, &MAI); +} + +/// printSOImm2PartOperand - SOImm is broken into two pieces using a 'mov' +/// followed by an 'orr' to materialize. +void ARMInstPrinter::printSOImm2PartOperand(const MCInst *MI, unsigned OpNum) { + // FIXME: REMOVE this method. + abort(); +} + +// so_reg is a 4-operand unit corresponding to register forms of the A5.1 +// "Addressing Mode 1 - Data-processing operands" forms. This includes: +// REG 0 0 - e.g. R5 +// REG REG 0,SH_OPC - e.g. R5, ROR R3 +// REG 0 IMM,SH_OPC - e.g. R5, LSL #3 +void ARMInstPrinter::printSORegOperand(const MCInst *MI, unsigned OpNum) { + const MCOperand &MO1 = MI->getOperand(OpNum); + const MCOperand &MO2 = MI->getOperand(OpNum+1); + const MCOperand &MO3 = MI->getOperand(OpNum+2); + + O << getRegisterName(MO1.getReg()); + + // Print the shift opc. + O << ", " + << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(MO3.getImm())) + << ' '; + + if (MO2.getReg()) { + O << getRegisterName(MO2.getReg()); + assert(ARM_AM::getSORegOffset(MO3.getImm()) == 0); + } else { + O << "#" << ARM_AM::getSORegOffset(MO3.getImm()); + } +} + + +void ARMInstPrinter::printAddrMode2Operand(const MCInst *MI, unsigned Op) { + const MCOperand &MO1 = MI->getOperand(Op); + const MCOperand &MO2 = MI->getOperand(Op+1); + const MCOperand &MO3 = MI->getOperand(Op+2); + + if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right. + printOperand(MI, Op); + return; + } + + O << "[" << getRegisterName(MO1.getReg()); + + if (!MO2.getReg()) { + if (ARM_AM::getAM2Offset(MO3.getImm())) // Don't print +0. + O << ", #" + << (char)ARM_AM::getAM2Op(MO3.getImm()) + << ARM_AM::getAM2Offset(MO3.getImm()); + O << "]"; + return; + } + + O << ", " + << (char)ARM_AM::getAM2Op(MO3.getImm()) + << getRegisterName(MO2.getReg()); + + if (unsigned ShImm = ARM_AM::getAM2Offset(MO3.getImm())) + O << ", " + << ARM_AM::getShiftOpcStr(ARM_AM::getAM2ShiftOpc(MO3.getImm())) + << " #" << ShImm; + O << "]"; +} + +void ARMInstPrinter::printAddrMode2OffsetOperand(const MCInst *MI, + unsigned OpNum) { + const MCOperand &MO1 = MI->getOperand(OpNum); + const MCOperand &MO2 = MI->getOperand(OpNum+1); + + if (!MO1.getReg()) { + unsigned ImmOffs = ARM_AM::getAM2Offset(MO2.getImm()); + assert(ImmOffs && "Malformed indexed load / store!"); + O << '#' << (char)ARM_AM::getAM2Op(MO2.getImm()) << ImmOffs; + return; + } + + O << (char)ARM_AM::getAM2Op(MO2.getImm()) << getRegisterName(MO1.getReg()); + + if (unsigned ShImm = ARM_AM::getAM2Offset(MO2.getImm())) + O << ", " + << ARM_AM::getShiftOpcStr(ARM_AM::getAM2ShiftOpc(MO2.getImm())) + << " #" << ShImm; +} + +void ARMInstPrinter::printAddrMode3Operand(const MCInst *MI, unsigned OpNum) { + const MCOperand &MO1 = MI->getOperand(OpNum); + const MCOperand &MO2 = MI->getOperand(OpNum+1); + const MCOperand &MO3 = MI->getOperand(OpNum+2); + + O << '[' << getRegisterName(MO1.getReg()); + + if (MO2.getReg()) { + O << ", " << (char)ARM_AM::getAM3Op(MO3.getImm()) + << getRegisterName(MO2.getReg()) << ']'; + return; + } + + if (unsigned ImmOffs = ARM_AM::getAM3Offset(MO3.getImm())) + O << ", #" + << (char)ARM_AM::getAM3Op(MO3.getImm()) + << ImmOffs; + O << ']'; +} + +void ARMInstPrinter::printAddrMode3OffsetOperand(const MCInst *MI, + unsigned OpNum) { + const MCOperand &MO1 = MI->getOperand(OpNum); + const MCOperand &MO2 = MI->getOperand(OpNum+1); + + if (MO1.getReg()) { + O << (char)ARM_AM::getAM3Op(MO2.getImm()) + << getRegisterName(MO1.getReg()); + return; + } + + unsigned ImmOffs = ARM_AM::getAM3Offset(MO2.getImm()); + assert(ImmOffs && "Malformed indexed load / store!"); + O << "#" + << (char)ARM_AM::getAM3Op(MO2.getImm()) + << ImmOffs; +} + + +void ARMInstPrinter::printAddrMode4Operand(const MCInst *MI, unsigned OpNum, + const char *Modifier) { + const MCOperand &MO1 = MI->getOperand(OpNum); + const MCOperand &MO2 = MI->getOperand(OpNum+1); + ARM_AM::AMSubMode Mode = ARM_AM::getAM4SubMode(MO2.getImm()); + if (Modifier && strcmp(Modifier, "submode") == 0) { + if (MO1.getReg() == ARM::SP) { + // FIXME + bool isLDM = (MI->getOpcode() == ARM::LDM || + MI->getOpcode() == ARM::LDM_RET || + MI->getOpcode() == ARM::t2LDM || + MI->getOpcode() == ARM::t2LDM_RET); + O << ARM_AM::getAMSubModeAltStr(Mode, isLDM); + } else + O << ARM_AM::getAMSubModeStr(Mode); + } else if (Modifier && strcmp(Modifier, "wide") == 0) { + ARM_AM::AMSubMode Mode = ARM_AM::getAM4SubMode(MO2.getImm()); + if (Mode == ARM_AM::ia) + O << ".w"; + } else { + printOperand(MI, OpNum); + if (ARM_AM::getAM4WBFlag(MO2.getImm())) + O << "!"; + } +} + +void ARMInstPrinter::printAddrMode5Operand(const MCInst *MI, unsigned OpNum, + const char *Modifier) { + const MCOperand &MO1 = MI->getOperand(OpNum); + const MCOperand &MO2 = MI->getOperand(OpNum+1); + + if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right. + printOperand(MI, OpNum); + return; + } + + if (Modifier && strcmp(Modifier, "submode") == 0) { + ARM_AM::AMSubMode Mode = ARM_AM::getAM5SubMode(MO2.getImm()); + O << ARM_AM::getAMSubModeStr(Mode); + return; + } else if (Modifier && strcmp(Modifier, "base") == 0) { + // Used for FSTM{D|S} and LSTM{D|S} operations. + O << getRegisterName(MO1.getReg()); + if (ARM_AM::getAM5WBFlag(MO2.getImm())) + O << "!"; + return; + } + + O << "[" << getRegisterName(MO1.getReg()); + + if (unsigned ImmOffs = ARM_AM::getAM5Offset(MO2.getImm())) { + O << ", #" + << (char)ARM_AM::getAM5Op(MO2.getImm()) + << ImmOffs*4; + } + O << "]"; +} + +void ARMInstPrinter::printAddrMode6Operand(const MCInst *MI, unsigned OpNum) { + const MCOperand &MO1 = MI->getOperand(OpNum); + const MCOperand &MO2 = MI->getOperand(OpNum+1); + const MCOperand &MO3 = MI->getOperand(OpNum+2); + + // FIXME: No support yet for specifying alignment. + O << '[' << getRegisterName(MO1.getReg()) << ']'; + + if (ARM_AM::getAM6WBFlag(MO3.getImm())) { + if (MO2.getReg() == 0) + O << '!'; + else + O << ", " << getRegisterName(MO2.getReg()); + } +} + +void ARMInstPrinter::printAddrModePCOperand(const MCInst *MI, unsigned OpNum, + const char *Modifier) { + assert(0 && "FIXME: Implement printAddrModePCOperand"); +} + +void ARMInstPrinter::printBitfieldInvMaskImmOperand (const MCInst *MI, + unsigned OpNum) { + const MCOperand &MO = MI->getOperand(OpNum); + uint32_t v = ~MO.getImm(); + int32_t lsb = CountTrailingZeros_32(v); + int32_t width = (32 - CountLeadingZeros_32 (v)) - lsb; + assert(MO.isImm() && "Not a valid bf_inv_mask_imm value!"); + O << '#' << lsb << ", #" << width; +} + +void ARMInstPrinter::printRegisterList(const MCInst *MI, unsigned OpNum) { + O << "{"; + // Always skip the first operand, it's the optional (and implicit writeback). + for (unsigned i = OpNum+1, e = MI->getNumOperands(); i != e; ++i) { + if (i != OpNum+1) O << ", "; + O << getRegisterName(MI->getOperand(i).getReg()); + } + O << "}"; +} + +void ARMInstPrinter::printPredicateOperand(const MCInst *MI, unsigned OpNum) { + ARMCC::CondCodes CC = (ARMCC::CondCodes)MI->getOperand(OpNum).getImm(); + if (CC != ARMCC::AL) + O << ARMCondCodeToString(CC); +} + +void ARMInstPrinter::printSBitModifierOperand(const MCInst *MI, unsigned OpNum){ + if (MI->getOperand(OpNum).getReg()) { + assert(MI->getOperand(OpNum).getReg() == ARM::CPSR && + "Expect ARM CPSR register!"); + O << 's'; + } +} + + + +void ARMInstPrinter::printCPInstOperand(const MCInst *MI, unsigned OpNum, + const char *Modifier) { + // FIXME: remove this. + abort(); +} + +void ARMInstPrinter::printNoHashImmediate(const MCInst *MI, unsigned OpNum) { + O << MI->getOperand(OpNum).getImm(); +} + + +void ARMInstPrinter::printPCLabel(const MCInst *MI, unsigned OpNum) { + // FIXME: remove this. + abort(); +} + +void ARMInstPrinter::printThumbS4ImmOperand(const MCInst *MI, unsigned OpNum) { + // FIXME: remove this. + abort(); +} diff --git a/libclamav/c++/llvm/lib/Target/ARM/AsmPrinter/ARMInstPrinter.h b/libclamav/c++/llvm/lib/Target/ARM/AsmPrinter/ARMInstPrinter.h new file mode 100644 index 000000000..23a7f05db --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/ARM/AsmPrinter/ARMInstPrinter.h @@ -0,0 +1,96 @@ +//===-- ARMInstPrinter.h - Convert ARM MCInst to assembly syntax ----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This class prints an ARM MCInst to a .s file. +// +//===----------------------------------------------------------------------===// + +#ifndef ARMINSTPRINTER_H +#define ARMINSTPRINTER_H + +#include "llvm/MC/MCInstPrinter.h" + +namespace llvm { + class MCOperand; + +class ARMInstPrinter : public MCInstPrinter { + bool VerboseAsm; +public: + ARMInstPrinter(raw_ostream &O, const MCAsmInfo &MAI, bool verboseAsm) + : MCInstPrinter(O, MAI), VerboseAsm(verboseAsm) {} + + virtual void printInst(const MCInst *MI); + + // Autogenerated by tblgen. + void printInstruction(const MCInst *MI); + static const char *getRegisterName(unsigned RegNo); + + + void printOperand(const MCInst *MI, unsigned OpNo, + const char *Modifier = 0); + + void printSOImmOperand(const MCInst *MI, unsigned OpNum); + void printSOImm2PartOperand(const MCInst *MI, unsigned OpNum); + + void printSORegOperand(const MCInst *MI, unsigned OpNum); + void printAddrMode2Operand(const MCInst *MI, unsigned OpNum); + void printAddrMode2OffsetOperand(const MCInst *MI, unsigned OpNum); + void printAddrMode3Operand(const MCInst *MI, unsigned OpNum); + void printAddrMode3OffsetOperand(const MCInst *MI, unsigned OpNum); + void printAddrMode4Operand(const MCInst *MI, unsigned OpNum, + const char *Modifier = 0); + void printAddrMode5Operand(const MCInst *MI, unsigned OpNum, + const char *Modifier = 0); + void printAddrMode6Operand(const MCInst *MI, unsigned OpNum); + void printAddrModePCOperand(const MCInst *MI, unsigned OpNum, + const char *Modifier = 0); + + void printBitfieldInvMaskImmOperand(const MCInst *MI, unsigned OpNum); + + void printThumbS4ImmOperand(const MCInst *MI, unsigned OpNum); + void printThumbITMask(const MCInst *MI, unsigned OpNum) {} + void printThumbAddrModeRROperand(const MCInst *MI, unsigned OpNum) {} + void printThumbAddrModeRI5Operand(const MCInst *MI, unsigned OpNum, + unsigned Scale) {} + void printThumbAddrModeS1Operand(const MCInst *MI, unsigned OpNum) {} + void printThumbAddrModeS2Operand(const MCInst *MI, unsigned OpNum) {} + void printThumbAddrModeS4Operand(const MCInst *MI, unsigned OpNum) {} + void printThumbAddrModeSPOperand(const MCInst *MI, unsigned OpNum) {} + + void printT2SOOperand(const MCInst *MI, unsigned OpNum) {} + void printT2AddrModeImm12Operand(const MCInst *MI, unsigned OpNum) {} + void printT2AddrModeImm8Operand(const MCInst *MI, unsigned OpNum) {} + void printT2AddrModeImm8s4Operand(const MCInst *MI, unsigned OpNum) {} + void printT2AddrModeImm8OffsetOperand(const MCInst *MI, unsigned OpNum) {} + void printT2AddrModeSoRegOperand(const MCInst *MI, unsigned OpNum) {} + + void printPredicateOperand(const MCInst *MI, unsigned OpNum); + void printSBitModifierOperand(const MCInst *MI, unsigned OpNum); + void printRegisterList(const MCInst *MI, unsigned OpNum); + void printCPInstOperand(const MCInst *MI, unsigned OpNum, + const char *Modifier); + void printJTBlockOperand(const MCInst *MI, unsigned OpNum) {} + void printJT2BlockOperand(const MCInst *MI, unsigned OpNum) {} + void printTBAddrMode(const MCInst *MI, unsigned OpNum) {} + void printNoHashImmediate(const MCInst *MI, unsigned OpNum); + void printVFPf32ImmOperand(const MCInst *MI, int OpNum) {} + void printVFPf64ImmOperand(const MCInst *MI, int OpNum) {} + void printHex8ImmOperand(const MCInst *MI, int OpNum) {} + void printHex16ImmOperand(const MCInst *MI, int OpNum) {} + void printHex32ImmOperand(const MCInst *MI, int OpNum) {} + void printHex64ImmOperand(const MCInst *MI, int OpNum) {} + + void printPCLabel(const MCInst *MI, unsigned OpNum); + // FIXME: Implement. + void PrintSpecial(const MCInst *MI, const char *Kind) {} +}; + +} + +#endif diff --git a/libclamav/c++/llvm/lib/Target/ARM/AsmPrinter/ARMMCInstLower.cpp b/libclamav/c++/llvm/lib/Target/ARM/AsmPrinter/ARMMCInstLower.cpp new file mode 100644 index 000000000..c49fee3a5 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/ARM/AsmPrinter/ARMMCInstLower.cpp @@ -0,0 +1,171 @@ +//===-- ARMMCInstLower.cpp - Convert ARM MachineInstr to an MCInst --------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains code to lower ARM MachineInstrs to their corresponding +// MCInst records. +// +//===----------------------------------------------------------------------===// + +#include "ARMMCInstLower.h" +//#include "llvm/CodeGen/MachineModuleInfoImpls.h" +#include "llvm/CodeGen/AsmPrinter.h" +#include "llvm/CodeGen/MachineBasicBlock.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCInst.h" +//#include "llvm/MC/MCStreamer.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/Mangler.h" +#include "llvm/ADT/SmallString.h" +using namespace llvm; + + +#if 0 +const ARMSubtarget &ARMMCInstLower::getSubtarget() const { + return AsmPrinter.getSubtarget(); +} + +MachineModuleInfoMachO &ARMMCInstLower::getMachOMMI() const { + assert(getSubtarget().isTargetDarwin() &&"Can only get MachO info on darwin"); + return AsmPrinter.MMI->getObjFileInfo(); +} +#endif + +MCSymbol *ARMMCInstLower:: +GetGlobalAddressSymbol(const MachineOperand &MO) const { + const GlobalValue *GV = MO.getGlobal(); + + SmallString<128> Name; + Mang.getNameWithPrefix(Name, GV, false); + + // FIXME: HANDLE PLT references how?? + switch (MO.getTargetFlags()) { + default: assert(0 && "Unknown target flag on GV operand"); + case 0: break; + } + + return Ctx.GetOrCreateSymbol(Name.str()); +} + +MCSymbol *ARMMCInstLower:: +GetExternalSymbolSymbol(const MachineOperand &MO) const { + SmallString<128> Name; + Name += Printer.MAI->getGlobalPrefix(); + Name += MO.getSymbolName(); + + // FIXME: HANDLE PLT references how?? + switch (MO.getTargetFlags()) { + default: assert(0 && "Unknown target flag on GV operand"); + case 0: break; + } + + return Ctx.GetOrCreateSymbol(Name.str()); +} + + + +MCSymbol *ARMMCInstLower:: +GetJumpTableSymbol(const MachineOperand &MO) const { + SmallString<256> Name; + raw_svector_ostream(Name) << Printer.MAI->getPrivateGlobalPrefix() << "JTI" + << Printer.getFunctionNumber() << '_' << MO.getIndex(); + +#if 0 + switch (MO.getTargetFlags()) { + default: llvm_unreachable("Unknown target flag on GV operand"); + } +#endif + + // Create a symbol for the name. + return Ctx.GetOrCreateSymbol(Name.str()); +} + +MCSymbol *ARMMCInstLower:: +GetConstantPoolIndexSymbol(const MachineOperand &MO) const { + SmallString<256> Name; + raw_svector_ostream(Name) << Printer.MAI->getPrivateGlobalPrefix() << "CPI" + << Printer.getFunctionNumber() << '_' << MO.getIndex(); + +#if 0 + switch (MO.getTargetFlags()) { + default: llvm_unreachable("Unknown target flag on GV operand"); + } +#endif + + // Create a symbol for the name. + return Ctx.GetOrCreateSymbol(Name.str()); +} + +MCOperand ARMMCInstLower:: +LowerSymbolOperand(const MachineOperand &MO, MCSymbol *Sym) const { + // FIXME: We would like an efficient form for this, so we don't have to do a + // lot of extra uniquing. + const MCExpr *Expr = MCSymbolRefExpr::Create(Sym, Ctx); + +#if 0 + switch (MO.getTargetFlags()) { + default: llvm_unreachable("Unknown target flag on GV operand"); + } +#endif + + if (!MO.isJTI() && MO.getOffset()) + Expr = MCBinaryExpr::CreateAdd(Expr, + MCConstantExpr::Create(MO.getOffset(), Ctx), + Ctx); + return MCOperand::CreateExpr(Expr); +} + + +void ARMMCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const { + OutMI.setOpcode(MI->getOpcode()); + + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + const MachineOperand &MO = MI->getOperand(i); + + MCOperand MCOp; + switch (MO.getType()) { + default: + MI->dump(); + assert(0 && "unknown operand type"); + case MachineOperand::MO_Register: + // Ignore all implicit register operands. + if (MO.isImplicit()) continue; + assert(!MO.getSubReg() && "Subregs should be eliminated!"); + MCOp = MCOperand::CreateReg(MO.getReg()); + break; + case MachineOperand::MO_Immediate: + MCOp = MCOperand::CreateImm(MO.getImm()); + break; + case MachineOperand::MO_MachineBasicBlock: + MCOp = MCOperand::CreateExpr(MCSymbolRefExpr::Create( + Printer.GetMBBSymbol(MO.getMBB()->getNumber()), Ctx)); + break; + case MachineOperand::MO_GlobalAddress: + MCOp = LowerSymbolOperand(MO, GetGlobalAddressSymbol(MO)); + break; + case MachineOperand::MO_ExternalSymbol: + MCOp = LowerSymbolOperand(MO, GetExternalSymbolSymbol(MO)); + break; + case MachineOperand::MO_JumpTableIndex: + MCOp = LowerSymbolOperand(MO, GetJumpTableSymbol(MO)); + break; + case MachineOperand::MO_ConstantPoolIndex: + MCOp = LowerSymbolOperand(MO, GetConstantPoolIndexSymbol(MO)); + break; + case MachineOperand::MO_BlockAddress: + MCOp = LowerSymbolOperand(MO, Printer.GetBlockAddressSymbol( + MO.getBlockAddress())); + break; + } + + OutMI.addOperand(MCOp); + } + +} diff --git a/libclamav/c++/llvm/lib/Target/ARM/AsmPrinter/ARMMCInstLower.h b/libclamav/c++/llvm/lib/Target/ARM/AsmPrinter/ARMMCInstLower.h new file mode 100644 index 000000000..383d30d5d --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/ARM/AsmPrinter/ARMMCInstLower.h @@ -0,0 +1,56 @@ +//===-- ARMMCInstLower.h - Lower MachineInstr to MCInst -------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef ARM_MCINSTLOWER_H +#define ARM_MCINSTLOWER_H + +#include "llvm/Support/Compiler.h" + +namespace llvm { + class AsmPrinter; + class MCAsmInfo; + class MCContext; + class MCInst; + class MCOperand; + class MCSymbol; + class MachineInstr; + class MachineModuleInfoMachO; + class MachineOperand; + class Mangler; + //class ARMSubtarget; + +/// ARMMCInstLower - This class is used to lower an MachineInstr into an MCInst. +class VISIBILITY_HIDDEN ARMMCInstLower { + MCContext &Ctx; + Mangler &Mang; + AsmPrinter &Printer; + + //const ARMSubtarget &getSubtarget() const; +public: + ARMMCInstLower(MCContext &ctx, Mangler &mang, AsmPrinter &printer) + : Ctx(ctx), Mang(mang), Printer(printer) {} + + void Lower(const MachineInstr *MI, MCInst &OutMI) const; + + //MCSymbol *GetPICBaseSymbol() const; + MCSymbol *GetGlobalAddressSymbol(const MachineOperand &MO) const; + MCSymbol *GetExternalSymbolSymbol(const MachineOperand &MO) const; + MCSymbol *GetJumpTableSymbol(const MachineOperand &MO) const; + MCSymbol *GetConstantPoolIndexSymbol(const MachineOperand &MO) const; + MCOperand LowerSymbolOperand(const MachineOperand &MO, MCSymbol *Sym) const; + +/* +private: + MachineModuleInfoMachO &getMachOMMI() const; + */ +}; + +} + +#endif diff --git a/libclamav/c++/llvm/lib/Target/ARM/AsmPrinter/CMakeLists.txt b/libclamav/c++/llvm/lib/Target/ARM/AsmPrinter/CMakeLists.txt new file mode 100644 index 000000000..4e299f86e --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/ARM/AsmPrinter/CMakeLists.txt @@ -0,0 +1,8 @@ +include_directories( ${CMAKE_CURRENT_BINARY_DIR}/.. ${CMAKE_CURRENT_SOURCE_DIR}/.. ) + +add_llvm_library(LLVMARMAsmPrinter + ARMAsmPrinter.cpp + ARMInstPrinter.cpp + ARMMCInstLower.cpp + ) +add_dependencies(LLVMARMAsmPrinter ARMCodeGenTable_gen) diff --git a/libclamav/c++/llvm/lib/Target/ARM/AsmPrinter/Makefile b/libclamav/c++/llvm/lib/Target/ARM/AsmPrinter/Makefile new file mode 100644 index 000000000..208beccce --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/ARM/AsmPrinter/Makefile @@ -0,0 +1,15 @@ +##===- lib/Target/ARM/AsmPrinter/Makefile ------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## +LEVEL = ../../../.. +LIBRARYNAME = LLVMARMAsmPrinter + +# Hack: we need to include 'main' arm target directory to grab private headers +CPPFLAGS = -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. + +include $(LEVEL)/Makefile.common diff --git a/libclamav/c++/llvm/lib/Target/ARM/CMakeLists.txt b/libclamav/c++/llvm/lib/Target/ARM/CMakeLists.txt new file mode 100644 index 000000000..964551f91 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/ARM/CMakeLists.txt @@ -0,0 +1,40 @@ +set(LLVM_TARGET_DEFINITIONS ARM.td) + +tablegen(ARMGenRegisterInfo.h.inc -gen-register-desc-header) +tablegen(ARMGenRegisterNames.inc -gen-register-enums) +tablegen(ARMGenRegisterInfo.inc -gen-register-desc) +tablegen(ARMGenInstrNames.inc -gen-instr-enums) +tablegen(ARMGenInstrInfo.inc -gen-instr-desc) +tablegen(ARMGenCodeEmitter.inc -gen-emitter) +tablegen(ARMGenAsmWriter.inc -gen-asm-writer) +tablegen(ARMGenDAGISel.inc -gen-dag-isel) +tablegen(ARMGenCallingConv.inc -gen-callingconv) +tablegen(ARMGenSubtarget.inc -gen-subtarget) + +add_llvm_target(ARMCodeGen + ARMBaseInstrInfo.cpp + ARMBaseRegisterInfo.cpp + ARMCodeEmitter.cpp + ARMConstantIslandPass.cpp + ARMConstantPoolValue.cpp + ARMExpandPseudoInsts.cpp + ARMISelDAGToDAG.cpp + ARMISelLowering.cpp + ARMInstrInfo.cpp + ARMJITInfo.cpp + ARMLoadStoreOptimizer.cpp + ARMMCAsmInfo.cpp + ARMRegisterInfo.cpp + ARMSubtarget.cpp + ARMTargetMachine.cpp + NEONMoveFix.cpp + NEONPreAllocPass.cpp + Thumb1InstrInfo.cpp + Thumb1RegisterInfo.cpp + Thumb2ITBlockPass.cpp + Thumb2InstrInfo.cpp + Thumb2RegisterInfo.cpp + Thumb2SizeReduction.cpp + ) + +target_link_libraries (LLVMARMCodeGen LLVMSelectionDAG) diff --git a/libclamav/c++/llvm/lib/Target/ARM/Makefile b/libclamav/c++/llvm/lib/Target/ARM/Makefile new file mode 100644 index 000000000..a8dd38cb3 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/ARM/Makefile @@ -0,0 +1,23 @@ +##===- lib/Target/ARM/Makefile -----------------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LEVEL = ../../.. +LIBRARYNAME = LLVMARMCodeGen +TARGET = ARM + +# Make sure that tblgen is run, first thing. +BUILT_SOURCES = ARMGenRegisterInfo.h.inc ARMGenRegisterNames.inc \ + ARMGenRegisterInfo.inc ARMGenInstrNames.inc \ + ARMGenInstrInfo.inc ARMGenAsmWriter.inc \ + ARMGenDAGISel.inc ARMGenSubtarget.inc \ + ARMGenCodeEmitter.inc ARMGenCallingConv.inc + +DIRS = AsmPrinter AsmParser TargetInfo + +include $(LEVEL)/Makefile.common diff --git a/libclamav/c++/llvm/lib/Target/ARM/NEONMoveFix.cpp b/libclamav/c++/llvm/lib/Target/ARM/NEONMoveFix.cpp new file mode 100644 index 000000000..50abcf464 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/ARM/NEONMoveFix.cpp @@ -0,0 +1,141 @@ +//===-- NEONMoveFix.cpp - Convert vfp reg-reg moves into neon ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "neon-mov-fix" +#include "ARM.h" +#include "ARMMachineFunctionInfo.h" +#include "ARMInstrInfo.h" +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +STATISTIC(NumVMovs, "Number of reg-reg moves converted"); + +namespace { + struct NEONMoveFixPass : public MachineFunctionPass { + static char ID; + NEONMoveFixPass() : MachineFunctionPass(&ID) {} + + virtual bool runOnMachineFunction(MachineFunction &Fn); + + virtual const char *getPassName() const { + return "NEON reg-reg move conversion"; + } + + private: + const TargetRegisterInfo *TRI; + const ARMBaseInstrInfo *TII; + + typedef DenseMap RegMap; + + bool InsertMoves(MachineBasicBlock &MBB); + }; + char NEONMoveFixPass::ID = 0; +} + +bool NEONMoveFixPass::InsertMoves(MachineBasicBlock &MBB) { + RegMap Defs; + bool Modified = false; + + // Walk over MBB tracking the def points of the registers. + MachineBasicBlock::iterator MII = MBB.begin(), E = MBB.end(); + MachineBasicBlock::iterator NextMII; + for (; MII != E; MII = NextMII) { + NextMII = next(MII); + MachineInstr *MI = &*MII; + + if (MI->getOpcode() == ARM::VMOVD && + !TII->isPredicated(MI)) { + unsigned SrcReg = MI->getOperand(1).getReg(); + // If we do not find an instruction defining the reg, this means the + // register should be live-in for this BB. It's always to better to use + // NEON reg-reg moves. + unsigned Domain = ARMII::DomainNEON; + RegMap::iterator DefMI = Defs.find(SrcReg); + if (DefMI != Defs.end()) { + Domain = DefMI->second->getDesc().TSFlags & ARMII::DomainMask; + // Instructions in general domain are subreg accesses. + // Map them to NEON reg-reg moves. + if (Domain == ARMII::DomainGeneral) + Domain = ARMII::DomainNEON; + } + + if (Domain & ARMII::DomainNEON) { + // Convert VMOVD to VMOVDneon + unsigned DestReg = MI->getOperand(0).getReg(); + + DEBUG({errs() << "vmov convert: "; MI->dump();}); + + // It's safe to ignore imp-defs / imp-uses here, since: + // - We're running late, no intelligent condegen passes should be run + // afterwards + // - The imp-defs / imp-uses are superregs only, we don't care about + // them. + AddDefaultPred(BuildMI(MBB, *MI, MI->getDebugLoc(), + TII->get(ARM::VMOVDneon), DestReg).addReg(SrcReg)); + MBB.erase(MI); + MachineBasicBlock::iterator I = prior(NextMII); + MI = &*I; + + DEBUG({errs() << " into: "; MI->dump();}); + + Modified = true; + ++NumVMovs; + } else { + assert((Domain & ARMII::DomainVFP) && "Invalid domain!"); + // Do nothing. + } + } + + // Update def information. + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + const MachineOperand& MO = MI->getOperand(i); + if (!MO.isReg() || !MO.isDef()) + continue; + unsigned MOReg = MO.getReg(); + + Defs[MOReg] = MI; + // Catch subregs as well. + for (const unsigned *R = TRI->getSubRegisters(MOReg); *R; ++R) + Defs[*R] = MI; + } + } + + return Modified; +} + +bool NEONMoveFixPass::runOnMachineFunction(MachineFunction &Fn) { + ARMFunctionInfo *AFI = Fn.getInfo(); + const TargetMachine &TM = Fn.getTarget(); + + if (AFI->isThumbFunction()) + return false; + + TRI = TM.getRegisterInfo(); + TII = static_cast(TM.getInstrInfo()); + + bool Modified = false; + for (MachineFunction::iterator MFI = Fn.begin(), E = Fn.end(); MFI != E; + ++MFI) { + MachineBasicBlock &MBB = *MFI; + Modified |= InsertMoves(MBB); + } + + return Modified; +} + +/// createNEONMoveFixPass - Returns an instance of the NEON reg-reg moves fix +/// pass. +FunctionPass *llvm::createNEONMoveFixPass() { + return new NEONMoveFixPass(); +} diff --git a/libclamav/c++/llvm/lib/Target/ARM/NEONPreAllocPass.cpp b/libclamav/c++/llvm/lib/Target/ARM/NEONPreAllocPass.cpp new file mode 100644 index 000000000..206677b0a --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/ARM/NEONPreAllocPass.cpp @@ -0,0 +1,394 @@ +//===-- NEONPreAllocPass.cpp - Allocate adjacent NEON registers--*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "neon-prealloc" +#include "ARM.h" +#include "ARMInstrInfo.h" +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +using namespace llvm; + +namespace { + class NEONPreAllocPass : public MachineFunctionPass { + const TargetInstrInfo *TII; + + public: + static char ID; + NEONPreAllocPass() : MachineFunctionPass(&ID) {} + + virtual bool runOnMachineFunction(MachineFunction &MF); + + virtual const char *getPassName() const { + return "NEON register pre-allocation pass"; + } + + private: + bool PreAllocNEONRegisters(MachineBasicBlock &MBB); + }; + + char NEONPreAllocPass::ID = 0; +} + +static bool isNEONMultiRegOp(int Opcode, unsigned &FirstOpnd, unsigned &NumRegs, + unsigned &Offset, unsigned &Stride) { + // Default to unit stride with no offset. + Stride = 1; + Offset = 0; + + switch (Opcode) { + default: + break; + + case ARM::VLD2d8: + case ARM::VLD2d16: + case ARM::VLD2d32: + case ARM::VLD2d64: + case ARM::VLD2LNd8: + case ARM::VLD2LNd16: + case ARM::VLD2LNd32: + FirstOpnd = 0; + NumRegs = 2; + return true; + + case ARM::VLD2q8: + case ARM::VLD2q16: + case ARM::VLD2q32: + FirstOpnd = 0; + NumRegs = 4; + return true; + + case ARM::VLD2LNq16a: + case ARM::VLD2LNq32a: + FirstOpnd = 0; + NumRegs = 2; + Offset = 0; + Stride = 2; + return true; + + case ARM::VLD2LNq16b: + case ARM::VLD2LNq32b: + FirstOpnd = 0; + NumRegs = 2; + Offset = 1; + Stride = 2; + return true; + + case ARM::VLD3d8: + case ARM::VLD3d16: + case ARM::VLD3d32: + case ARM::VLD3d64: + case ARM::VLD3LNd8: + case ARM::VLD3LNd16: + case ARM::VLD3LNd32: + FirstOpnd = 0; + NumRegs = 3; + return true; + + case ARM::VLD3q8a: + case ARM::VLD3q16a: + case ARM::VLD3q32a: + FirstOpnd = 0; + NumRegs = 3; + Offset = 0; + Stride = 2; + return true; + + case ARM::VLD3q8b: + case ARM::VLD3q16b: + case ARM::VLD3q32b: + FirstOpnd = 0; + NumRegs = 3; + Offset = 1; + Stride = 2; + return true; + + case ARM::VLD3LNq16a: + case ARM::VLD3LNq32a: + FirstOpnd = 0; + NumRegs = 3; + Offset = 0; + Stride = 2; + return true; + + case ARM::VLD3LNq16b: + case ARM::VLD3LNq32b: + FirstOpnd = 0; + NumRegs = 3; + Offset = 1; + Stride = 2; + return true; + + case ARM::VLD4d8: + case ARM::VLD4d16: + case ARM::VLD4d32: + case ARM::VLD4d64: + case ARM::VLD4LNd8: + case ARM::VLD4LNd16: + case ARM::VLD4LNd32: + FirstOpnd = 0; + NumRegs = 4; + return true; + + case ARM::VLD4q8a: + case ARM::VLD4q16a: + case ARM::VLD4q32a: + FirstOpnd = 0; + NumRegs = 4; + Offset = 0; + Stride = 2; + return true; + + case ARM::VLD4q8b: + case ARM::VLD4q16b: + case ARM::VLD4q32b: + FirstOpnd = 0; + NumRegs = 4; + Offset = 1; + Stride = 2; + return true; + + case ARM::VLD4LNq16a: + case ARM::VLD4LNq32a: + FirstOpnd = 0; + NumRegs = 4; + Offset = 0; + Stride = 2; + return true; + + case ARM::VLD4LNq16b: + case ARM::VLD4LNq32b: + FirstOpnd = 0; + NumRegs = 4; + Offset = 1; + Stride = 2; + return true; + + case ARM::VST2d8: + case ARM::VST2d16: + case ARM::VST2d32: + case ARM::VST2d64: + case ARM::VST2LNd8: + case ARM::VST2LNd16: + case ARM::VST2LNd32: + FirstOpnd = 4; + NumRegs = 2; + return true; + + case ARM::VST2q8: + case ARM::VST2q16: + case ARM::VST2q32: + FirstOpnd = 4; + NumRegs = 4; + return true; + + case ARM::VST2LNq16a: + case ARM::VST2LNq32a: + FirstOpnd = 4; + NumRegs = 2; + Offset = 0; + Stride = 2; + return true; + + case ARM::VST2LNq16b: + case ARM::VST2LNq32b: + FirstOpnd = 4; + NumRegs = 2; + Offset = 1; + Stride = 2; + return true; + + case ARM::VST3d8: + case ARM::VST3d16: + case ARM::VST3d32: + case ARM::VST3d64: + case ARM::VST3LNd8: + case ARM::VST3LNd16: + case ARM::VST3LNd32: + FirstOpnd = 4; + NumRegs = 3; + return true; + + case ARM::VST3q8a: + case ARM::VST3q16a: + case ARM::VST3q32a: + FirstOpnd = 5; + NumRegs = 3; + Offset = 0; + Stride = 2; + return true; + + case ARM::VST3q8b: + case ARM::VST3q16b: + case ARM::VST3q32b: + FirstOpnd = 5; + NumRegs = 3; + Offset = 1; + Stride = 2; + return true; + + case ARM::VST3LNq16a: + case ARM::VST3LNq32a: + FirstOpnd = 4; + NumRegs = 3; + Offset = 0; + Stride = 2; + return true; + + case ARM::VST3LNq16b: + case ARM::VST3LNq32b: + FirstOpnd = 4; + NumRegs = 3; + Offset = 1; + Stride = 2; + return true; + + case ARM::VST4d8: + case ARM::VST4d16: + case ARM::VST4d32: + case ARM::VST4d64: + case ARM::VST4LNd8: + case ARM::VST4LNd16: + case ARM::VST4LNd32: + FirstOpnd = 4; + NumRegs = 4; + return true; + + case ARM::VST4q8a: + case ARM::VST4q16a: + case ARM::VST4q32a: + FirstOpnd = 5; + NumRegs = 4; + Offset = 0; + Stride = 2; + return true; + + case ARM::VST4q8b: + case ARM::VST4q16b: + case ARM::VST4q32b: + FirstOpnd = 5; + NumRegs = 4; + Offset = 1; + Stride = 2; + return true; + + case ARM::VST4LNq16a: + case ARM::VST4LNq32a: + FirstOpnd = 4; + NumRegs = 4; + Offset = 0; + Stride = 2; + return true; + + case ARM::VST4LNq16b: + case ARM::VST4LNq32b: + FirstOpnd = 4; + NumRegs = 4; + Offset = 1; + Stride = 2; + return true; + + case ARM::VTBL2: + FirstOpnd = 1; + NumRegs = 2; + return true; + + case ARM::VTBL3: + FirstOpnd = 1; + NumRegs = 3; + return true; + + case ARM::VTBL4: + FirstOpnd = 1; + NumRegs = 4; + return true; + + case ARM::VTBX2: + FirstOpnd = 2; + NumRegs = 2; + return true; + + case ARM::VTBX3: + FirstOpnd = 2; + NumRegs = 3; + return true; + + case ARM::VTBX4: + FirstOpnd = 2; + NumRegs = 4; + return true; + } + + return false; +} + +bool NEONPreAllocPass::PreAllocNEONRegisters(MachineBasicBlock &MBB) { + bool Modified = false; + + MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end(); + for (; MBBI != E; ++MBBI) { + MachineInstr *MI = &*MBBI; + unsigned FirstOpnd, NumRegs, Offset, Stride; + if (!isNEONMultiRegOp(MI->getOpcode(), FirstOpnd, NumRegs, Offset, Stride)) + continue; + + MachineBasicBlock::iterator NextI = next(MBBI); + for (unsigned R = 0; R < NumRegs; ++R) { + MachineOperand &MO = MI->getOperand(FirstOpnd + R); + assert(MO.isReg() && MO.getSubReg() == 0 && "unexpected operand"); + unsigned VirtReg = MO.getReg(); + assert(TargetRegisterInfo::isVirtualRegister(VirtReg) && + "expected a virtual register"); + + // For now, just assign a fixed set of adjacent registers. + // This leaves plenty of room for future improvements. + static const unsigned NEONDRegs[] = { + ARM::D0, ARM::D1, ARM::D2, ARM::D3, + ARM::D4, ARM::D5, ARM::D6, ARM::D7 + }; + MO.setReg(NEONDRegs[Offset + R * Stride]); + + if (MO.isUse()) { + // Insert a copy from VirtReg. + TII->copyRegToReg(MBB, MBBI, MO.getReg(), VirtReg, + ARM::DPRRegisterClass, ARM::DPRRegisterClass); + if (MO.isKill()) { + MachineInstr *CopyMI = prior(MBBI); + CopyMI->findRegisterUseOperand(VirtReg)->setIsKill(); + } + MO.setIsKill(); + } else if (MO.isDef() && !MO.isDead()) { + // Add a copy to VirtReg. + TII->copyRegToReg(MBB, NextI, VirtReg, MO.getReg(), + ARM::DPRRegisterClass, ARM::DPRRegisterClass); + } + } + } + + return Modified; +} + +bool NEONPreAllocPass::runOnMachineFunction(MachineFunction &MF) { + TII = MF.getTarget().getInstrInfo(); + + bool Modified = false; + for (MachineFunction::iterator MFI = MF.begin(), E = MF.end(); MFI != E; + ++MFI) { + MachineBasicBlock &MBB = *MFI; + Modified |= PreAllocNEONRegisters(MBB); + } + + return Modified; +} + +/// createNEONPreAllocPass - returns an instance of the NEON register +/// pre-allocation pass. +FunctionPass *llvm::createNEONPreAllocPass() { + return new NEONPreAllocPass(); +} diff --git a/libclamav/c++/llvm/lib/Target/ARM/README-Thumb.txt b/libclamav/c++/llvm/lib/Target/ARM/README-Thumb.txt new file mode 100644 index 000000000..6b605bb0a --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/ARM/README-Thumb.txt @@ -0,0 +1,248 @@ +//===---------------------------------------------------------------------===// +// Random ideas for the ARM backend (Thumb specific). +//===---------------------------------------------------------------------===// + +* Add support for compiling functions in both ARM and Thumb mode, then taking + the smallest. + +* Add support for compiling individual basic blocks in thumb mode, when in a + larger ARM function. This can be used for presumed cold code, like paths + to abort (failure path of asserts), EH handling code, etc. + +* Thumb doesn't have normal pre/post increment addressing modes, but you can + load/store 32-bit integers with pre/postinc by using load/store multiple + instrs with a single register. + +* Make better use of high registers r8, r10, r11, r12 (ip). Some variants of add + and cmp instructions can use high registers. Also, we can use them as + temporaries to spill values into. + +* In thumb mode, short, byte, and bool preferred alignments are currently set + to 4 to accommodate ISA restriction (i.e. add sp, #imm, imm must be multiple + of 4). + +//===---------------------------------------------------------------------===// + +Potential jumptable improvements: + +* If we know function size is less than (1 << 16) * 2 bytes, we can use 16-bit + jumptable entries (e.g. (L1 - L2) >> 1). Or even smaller entries if the + function is even smaller. This also applies to ARM. + +* Thumb jumptable codegen can improve given some help from the assembler. This + is what we generate right now: + + .set PCRELV0, (LJTI1_0_0-(LPCRELL0+4)) +LPCRELL0: + mov r1, #PCRELV0 + add r1, pc + ldr r0, [r0, r1] + mov pc, r0 + .align 2 +LJTI1_0_0: + .long LBB1_3 + ... + +Note there is another pc relative add that we can take advantage of. + add r1, pc, #imm_8 * 4 + +We should be able to generate: + +LPCRELL0: + add r1, LJTI1_0_0 + ldr r0, [r0, r1] + mov pc, r0 + .align 2 +LJTI1_0_0: + .long LBB1_3 + +if the assembler can translate the add to: + add r1, pc, #((LJTI1_0_0-(LPCRELL0+4))&0xfffffffc) + +Note the assembler also does something similar to constpool load: +LPCRELL0: + ldr r0, LCPI1_0 +=> + ldr r0, pc, #((LCPI1_0-(LPCRELL0+4))&0xfffffffc) + + +//===---------------------------------------------------------------------===// + +We compiles the following: + +define i16 @func_entry_2E_ce(i32 %i) { + switch i32 %i, label %bb12.exitStub [ + i32 0, label %bb4.exitStub + i32 1, label %bb9.exitStub + i32 2, label %bb4.exitStub + i32 3, label %bb4.exitStub + i32 7, label %bb9.exitStub + i32 8, label %bb.exitStub + i32 9, label %bb9.exitStub + ] + +bb12.exitStub: + ret i16 0 + +bb4.exitStub: + ret i16 1 + +bb9.exitStub: + ret i16 2 + +bb.exitStub: + ret i16 3 +} + +into: + +_func_entry_2E_ce: + mov r2, #1 + lsl r2, r0 + cmp r0, #9 + bhi LBB1_4 @bb12.exitStub +LBB1_1: @newFuncRoot + mov r1, #13 + tst r2, r1 + bne LBB1_5 @bb4.exitStub +LBB1_2: @newFuncRoot + ldr r1, LCPI1_0 + tst r2, r1 + bne LBB1_6 @bb9.exitStub +LBB1_3: @newFuncRoot + mov r1, #1 + lsl r1, r1, #8 + tst r2, r1 + bne LBB1_7 @bb.exitStub +LBB1_4: @bb12.exitStub + mov r0, #0 + bx lr +LBB1_5: @bb4.exitStub + mov r0, #1 + bx lr +LBB1_6: @bb9.exitStub + mov r0, #2 + bx lr +LBB1_7: @bb.exitStub + mov r0, #3 + bx lr +LBB1_8: + .align 2 +LCPI1_0: + .long 642 + + +gcc compiles to: + + cmp r0, #9 + @ lr needed for prologue + bhi L2 + ldr r3, L11 + mov r2, #1 + mov r1, r2, asl r0 + ands r0, r3, r2, asl r0 + movne r0, #2 + bxne lr + tst r1, #13 + beq L9 +L3: + mov r0, r2 + bx lr +L9: + tst r1, #256 + movne r0, #3 + bxne lr +L2: + mov r0, #0 + bx lr +L12: + .align 2 +L11: + .long 642 + + +GCC is doing a couple of clever things here: + 1. It is predicating one of the returns. This isn't a clear win though: in + cases where that return isn't taken, it is replacing one condbranch with + two 'ne' predicated instructions. + 2. It is sinking the shift of "1 << i" into the tst, and using ands instead of + tst. This will probably require whole function isel. + 3. GCC emits: + tst r1, #256 + we emit: + mov r1, #1 + lsl r1, r1, #8 + tst r2, r1 + + +//===---------------------------------------------------------------------===// + +When spilling in thumb mode and the sp offset is too large to fit in the ldr / +str offset field, we load the offset from a constpool entry and add it to sp: + +ldr r2, LCPI +add r2, sp +ldr r2, [r2] + +These instructions preserve the condition code which is important if the spill +is between a cmp and a bcc instruction. However, we can use the (potentially) +cheaper sequnce if we know it's ok to clobber the condition register. + +add r2, sp, #255 * 4 +add r2, #132 +ldr r2, [r2, #7 * 4] + +This is especially bad when dynamic alloca is used. The all fixed size stack +objects are referenced off the frame pointer with negative offsets. See +oggenc for an example. + + +//===---------------------------------------------------------------------===// + +Poor codegen test/CodeGen/ARM/select.ll f7: + + ldr r5, LCPI1_0 +LPC0: + add r5, pc + ldr r6, LCPI1_1 + ldr r2, LCPI1_2 + mov r3, r6 + mov lr, pc + bx r5 + +//===---------------------------------------------------------------------===// + +Make register allocator / spiller smarter so we can re-materialize "mov r, imm", +etc. Almost all Thumb instructions clobber condition code. + +//===---------------------------------------------------------------------===// + +Add ldmia, stmia support. + +//===---------------------------------------------------------------------===// + +Thumb load / store address mode offsets are scaled. The values kept in the +instruction operands are pre-scale values. This probably ought to be changed +to avoid extra work when we convert Thumb2 instructions to Thumb1 instructions. + +//===---------------------------------------------------------------------===// + +We need to make (some of the) Thumb1 instructions predicable. That will allow +shrinking of predicated Thumb2 instructions. To allow this, we need to be able +to toggle the 's' bit since they do not set CPSR when they are inside IT blocks. + +//===---------------------------------------------------------------------===// + +Make use of hi register variants of cmp: tCMPhir / tCMPZhir. + +//===---------------------------------------------------------------------===// + +Thumb1 immediate field sometimes keep pre-scaled values. See +Thumb1RegisterInfo::eliminateFrameIndex. This is inconsistent from ARM and +Thumb2. + +//===---------------------------------------------------------------------===// + +Rather than having tBR_JTr print a ".align 2" and constant island pass pad it, +add a target specific ALIGN instruction instead. That way, GetInstSizeInBytes +won't have to over-estimate. It can also be used for loop alignment pass. diff --git a/libclamav/c++/llvm/lib/Target/ARM/README-Thumb2.txt b/libclamav/c++/llvm/lib/Target/ARM/README-Thumb2.txt new file mode 100644 index 000000000..e7c2552d9 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/ARM/README-Thumb2.txt @@ -0,0 +1,6 @@ +//===---------------------------------------------------------------------===// +// Random ideas for the ARM backend (Thumb2 specific). +//===---------------------------------------------------------------------===// + +Make sure jumptable destinations are below the jumptable in order to make use +of tbb / tbh. diff --git a/libclamav/c++/llvm/lib/Target/ARM/README.txt b/libclamav/c++/llvm/lib/Target/ARM/README.txt new file mode 100644 index 000000000..11c48add2 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/ARM/README.txt @@ -0,0 +1,598 @@ +//===---------------------------------------------------------------------===// +// Random ideas for the ARM backend. +//===---------------------------------------------------------------------===// + +Reimplement 'select' in terms of 'SEL'. + +* We would really like to support UXTAB16, but we need to prove that the + add doesn't need to overflow between the two 16-bit chunks. + +* Implement pre/post increment support. (e.g. PR935) +* Implement smarter constant generation for binops with large immediates. + +//===---------------------------------------------------------------------===// + +Crazy idea: Consider code that uses lots of 8-bit or 16-bit values. By the +time regalloc happens, these values are now in a 32-bit register, usually with +the top-bits known to be sign or zero extended. If spilled, we should be able +to spill these to a 8-bit or 16-bit stack slot, zero or sign extending as part +of the reload. + +Doing this reduces the size of the stack frame (important for thumb etc), and +also increases the likelihood that we will be able to reload multiple values +from the stack with a single load. + +//===---------------------------------------------------------------------===// + +The constant island pass is in good shape. Some cleanups might be desirable, +but there is unlikely to be much improvement in the generated code. + +1. There may be some advantage to trying to be smarter about the initial +placement, rather than putting everything at the end. + +2. There might be some compile-time efficiency to be had by representing +consecutive islands as a single block rather than multiple blocks. + +3. Use a priority queue to sort constant pool users in inverse order of + position so we always process the one closed to the end of functions + first. This may simply CreateNewWater. + +//===---------------------------------------------------------------------===// + +Eliminate copysign custom expansion. We are still generating crappy code with +default expansion + if-conversion. + +//===---------------------------------------------------------------------===// + +Eliminate one instruction from: + +define i32 @_Z6slow4bii(i32 %x, i32 %y) { + %tmp = icmp sgt i32 %x, %y + %retval = select i1 %tmp, i32 %x, i32 %y + ret i32 %retval +} + +__Z6slow4bii: + cmp r0, r1 + movgt r1, r0 + mov r0, r1 + bx lr +=> + +__Z6slow4bii: + cmp r0, r1 + movle r0, r1 + bx lr + +//===---------------------------------------------------------------------===// + +Implement long long "X-3" with instructions that fold the immediate in. These +were disabled due to badness with the ARM carry flag on subtracts. + +//===---------------------------------------------------------------------===// + +We currently compile abs: +int foo(int p) { return p < 0 ? -p : p; } + +into: + +_foo: + rsb r1, r0, #0 + cmn r0, #1 + movgt r1, r0 + mov r0, r1 + bx lr + +This is very, uh, literal. This could be a 3 operation sequence: + t = (p sra 31); + res = (p xor t)-t + +Which would be better. This occurs in png decode. + +//===---------------------------------------------------------------------===// + +More load / store optimizations: +1) Better representation for block transfer? This is from Olden/power: + + fldd d0, [r4] + fstd d0, [r4, #+32] + fldd d0, [r4, #+8] + fstd d0, [r4, #+40] + fldd d0, [r4, #+16] + fstd d0, [r4, #+48] + fldd d0, [r4, #+24] + fstd d0, [r4, #+56] + +If we can spare the registers, it would be better to use fldm and fstm here. +Need major register allocator enhancement though. + +2) Can we recognize the relative position of constantpool entries? i.e. Treat + + ldr r0, LCPI17_3 + ldr r1, LCPI17_4 + ldr r2, LCPI17_5 + + as + ldr r0, LCPI17 + ldr r1, LCPI17+4 + ldr r2, LCPI17+8 + + Then the ldr's can be combined into a single ldm. See Olden/power. + +Note for ARM v4 gcc uses ldmia to load a pair of 32-bit values to represent a +double 64-bit FP constant: + + adr r0, L6 + ldmia r0, {r0-r1} + + .align 2 +L6: + .long -858993459 + .long 1074318540 + +3) struct copies appear to be done field by field +instead of by words, at least sometimes: + +struct foo { int x; short s; char c1; char c2; }; +void cpy(struct foo*a, struct foo*b) { *a = *b; } + +llvm code (-O2) + ldrb r3, [r1, #+6] + ldr r2, [r1] + ldrb r12, [r1, #+7] + ldrh r1, [r1, #+4] + str r2, [r0] + strh r1, [r0, #+4] + strb r3, [r0, #+6] + strb r12, [r0, #+7] +gcc code (-O2) + ldmia r1, {r1-r2} + stmia r0, {r1-r2} + +In this benchmark poor handling of aggregate copies has shown up as +having a large effect on size, and possibly speed as well (we don't have +a good way to measure on ARM). + +//===---------------------------------------------------------------------===// + +* Consider this silly example: + +double bar(double x) { + double r = foo(3.1); + return x+r; +} + +_bar: + stmfd sp!, {r4, r5, r7, lr} + add r7, sp, #8 + mov r4, r0 + mov r5, r1 + fldd d0, LCPI1_0 + fmrrd r0, r1, d0 + bl _foo + fmdrr d0, r4, r5 + fmsr s2, r0 + fsitod d1, s2 + faddd d0, d1, d0 + fmrrd r0, r1, d0 + ldmfd sp!, {r4, r5, r7, pc} + +Ignore the prologue and epilogue stuff for a second. Note + mov r4, r0 + mov r5, r1 +the copys to callee-save registers and the fact they are only being used by the +fmdrr instruction. It would have been better had the fmdrr been scheduled +before the call and place the result in a callee-save DPR register. The two +mov ops would not have been necessary. + +//===---------------------------------------------------------------------===// + +Calling convention related stuff: + +* gcc's parameter passing implementation is terrible and we suffer as a result: + +e.g. +struct s { + double d1; + int s1; +}; + +void foo(struct s S) { + printf("%g, %d\n", S.d1, S.s1); +} + +'S' is passed via registers r0, r1, r2. But gcc stores them to the stack, and +then reload them to r1, r2, and r3 before issuing the call (r0 contains the +address of the format string): + + stmfd sp!, {r7, lr} + add r7, sp, #0 + sub sp, sp, #12 + stmia sp, {r0, r1, r2} + ldmia sp, {r1-r2} + ldr r0, L5 + ldr r3, [sp, #8] +L2: + add r0, pc, r0 + bl L_printf$stub + +Instead of a stmia, ldmia, and a ldr, wouldn't it be better to do three moves? + +* Return an aggregate type is even worse: + +e.g. +struct s foo(void) { + struct s S = {1.1, 2}; + return S; +} + + mov ip, r0 + ldr r0, L5 + sub sp, sp, #12 +L2: + add r0, pc, r0 + @ lr needed for prologue + ldmia r0, {r0, r1, r2} + stmia sp, {r0, r1, r2} + stmia ip, {r0, r1, r2} + mov r0, ip + add sp, sp, #12 + bx lr + +r0 (and later ip) is the hidden parameter from caller to store the value in. The +first ldmia loads the constants into r0, r1, r2. The last stmia stores r0, r1, +r2 into the address passed in. However, there is one additional stmia that +stores r0, r1, and r2 to some stack location. The store is dead. + +The llvm-gcc generated code looks like this: + +csretcc void %foo(%struct.s* %agg.result) { +entry: + %S = alloca %struct.s, align 4 ; <%struct.s*> [#uses=1] + %memtmp = alloca %struct.s ; <%struct.s*> [#uses=1] + cast %struct.s* %S to sbyte* ; :0 [#uses=2] + call void %llvm.memcpy.i32( sbyte* %0, sbyte* cast ({ double, int }* %C.0.904 to sbyte*), uint 12, uint 4 ) + cast %struct.s* %agg.result to sbyte* ; :1 [#uses=2] + call void %llvm.memcpy.i32( sbyte* %1, sbyte* %0, uint 12, uint 0 ) + cast %struct.s* %memtmp to sbyte* ; :2 [#uses=1] + call void %llvm.memcpy.i32( sbyte* %2, sbyte* %1, uint 12, uint 0 ) + ret void +} + +llc ends up issuing two memcpy's (the first memcpy becomes 3 loads from +constantpool). Perhaps we should 1) fix llvm-gcc so the memcpy is translated +into a number of load and stores, or 2) custom lower memcpy (of small size) to +be ldmia / stmia. I think option 2 is better but the current register +allocator cannot allocate a chunk of registers at a time. + +A feasible temporary solution is to use specific physical registers at the +lowering time for small (<= 4 words?) transfer size. + +* ARM CSRet calling convention requires the hidden argument to be returned by +the callee. + +//===---------------------------------------------------------------------===// + +We can definitely do a better job on BB placements to eliminate some branches. +It's very common to see llvm generated assembly code that looks like this: + +LBB3: + ... +LBB4: +... + beq LBB3 + b LBB2 + +If BB4 is the only predecessor of BB3, then we can emit BB3 after BB4. We can +then eliminate beq and and turn the unconditional branch to LBB2 to a bne. + +See McCat/18-imp/ComputeBoundingBoxes for an example. + +//===---------------------------------------------------------------------===// + +Pre-/post- indexed load / stores: + +1) We should not make the pre/post- indexed load/store transform if the base ptr +is guaranteed to be live beyond the load/store. This can happen if the base +ptr is live out of the block we are performing the optimization. e.g. + +mov r1, r2 +ldr r3, [r1], #4 +... + +vs. + +ldr r3, [r2] +add r1, r2, #4 +... + +In most cases, this is just a wasted optimization. However, sometimes it can +negatively impact the performance because two-address code is more restrictive +when it comes to scheduling. + +Unfortunately, liveout information is currently unavailable during DAG combine +time. + +2) Consider spliting a indexed load / store into a pair of add/sub + load/store + to solve #1 (in TwoAddressInstructionPass.cpp). + +3) Enhance LSR to generate more opportunities for indexed ops. + +4) Once we added support for multiple result patterns, write indexed loads + patterns instead of C++ instruction selection code. + +5) Use VLDM / VSTM to emulate indexed FP load / store. + +//===---------------------------------------------------------------------===// + +Implement support for some more tricky ways to materialize immediates. For +example, to get 0xffff8000, we can use: + +mov r9, #&3f8000 +sub r9, r9, #&400000 + +//===---------------------------------------------------------------------===// + +We sometimes generate multiple add / sub instructions to update sp in prologue +and epilogue if the inc / dec value is too large to fit in a single immediate +operand. In some cases, perhaps it might be better to load the value from a +constantpool instead. + +//===---------------------------------------------------------------------===// + +GCC generates significantly better code for this function. + +int foo(int StackPtr, unsigned char *Line, unsigned char *Stack, int LineLen) { + int i = 0; + + if (StackPtr != 0) { + while (StackPtr != 0 && i < (((LineLen) < (32768))? (LineLen) : (32768))) + Line[i++] = Stack[--StackPtr]; + if (LineLen > 32768) + { + while (StackPtr != 0 && i < LineLen) + { + i++; + --StackPtr; + } + } + } + return StackPtr; +} + +//===---------------------------------------------------------------------===// + +This should compile to the mlas instruction: +int mlas(int x, int y, int z) { return ((x * y + z) < 0) ? 7 : 13; } + +//===---------------------------------------------------------------------===// + +At some point, we should triage these to see if they still apply to us: + +http://gcc.gnu.org/bugzilla/show_bug.cgi?id=19598 +http://gcc.gnu.org/bugzilla/show_bug.cgi?id=18560 +http://gcc.gnu.org/bugzilla/show_bug.cgi?id=27016 + +http://gcc.gnu.org/bugzilla/show_bug.cgi?id=11831 +http://gcc.gnu.org/bugzilla/show_bug.cgi?id=11826 +http://gcc.gnu.org/bugzilla/show_bug.cgi?id=11825 +http://gcc.gnu.org/bugzilla/show_bug.cgi?id=11824 +http://gcc.gnu.org/bugzilla/show_bug.cgi?id=11823 +http://gcc.gnu.org/bugzilla/show_bug.cgi?id=11820 +http://gcc.gnu.org/bugzilla/show_bug.cgi?id=10982 + +http://gcc.gnu.org/bugzilla/show_bug.cgi?id=10242 +http://gcc.gnu.org/bugzilla/show_bug.cgi?id=9831 +http://gcc.gnu.org/bugzilla/show_bug.cgi?id=9760 +http://gcc.gnu.org/bugzilla/show_bug.cgi?id=9759 +http://gcc.gnu.org/bugzilla/show_bug.cgi?id=9703 +http://gcc.gnu.org/bugzilla/show_bug.cgi?id=9702 +http://gcc.gnu.org/bugzilla/show_bug.cgi?id=9663 + +http://www.inf.u-szeged.hu/gcc-arm/ +http://citeseer.ist.psu.edu/debus04linktime.html + +//===---------------------------------------------------------------------===// + +gcc generates smaller code for this function at -O2 or -Os: + +void foo(signed char* p) { + if (*p == 3) + bar(); + else if (*p == 4) + baz(); + else if (*p == 5) + quux(); +} + +llvm decides it's a good idea to turn the repeated if...else into a +binary tree, as if it were a switch; the resulting code requires -1 +compare-and-branches when *p<=2 or *p==5, the same number if *p==4 +or *p>6, and +1 if *p==3. So it should be a speed win +(on balance). However, the revised code is larger, with 4 conditional +branches instead of 3. + +More seriously, there is a byte->word extend before +each comparison, where there should be only one, and the condition codes +are not remembered when the same two values are compared twice. + +//===---------------------------------------------------------------------===// + +More LSR enhancements possible: + +1. Teach LSR about pre- and post- indexed ops to allow iv increment be merged + in a load / store. +2. Allow iv reuse even when a type conversion is required. For example, i8 + and i32 load / store addressing modes are identical. + + +//===---------------------------------------------------------------------===// + +This: + +int foo(int a, int b, int c, int d) { + long long acc = (long long)a * (long long)b; + acc += (long long)c * (long long)d; + return (int)(acc >> 32); +} + +Should compile to use SMLAL (Signed Multiply Accumulate Long) which multiplies +two signed 32-bit values to produce a 64-bit value, and accumulates this with +a 64-bit value. + +We currently get this with both v4 and v6: + +_foo: + smull r1, r0, r1, r0 + smull r3, r2, r3, r2 + adds r3, r3, r1 + adc r0, r2, r0 + bx lr + +//===---------------------------------------------------------------------===// + +This: + #include + std::pair full_add(unsigned a, unsigned b) + { return std::make_pair(a + b, a + b < a); } + bool no_overflow(unsigned a, unsigned b) + { return !full_add(a, b).second; } + +Should compile to: + +_Z8full_addjj: + adds r2, r1, r2 + movcc r1, #0 + movcs r1, #1 + str r2, [r0, #0] + strb r1, [r0, #4] + mov pc, lr + +_Z11no_overflowjj: + cmn r0, r1 + movcs r0, #0 + movcc r0, #1 + mov pc, lr + +not: + +__Z8full_addjj: + add r3, r2, r1 + str r3, [r0] + mov r2, #1 + mov r12, #0 + cmp r3, r1 + movlo r12, r2 + str r12, [r0, #+4] + bx lr +__Z11no_overflowjj: + add r3, r1, r0 + mov r2, #1 + mov r1, #0 + cmp r3, r0 + movhs r1, r2 + mov r0, r1 + bx lr + +//===---------------------------------------------------------------------===// + +Some of the NEON intrinsics may be appropriate for more general use, either +as target-independent intrinsics or perhaps elsewhere in the ARM backend. +Some of them may also be lowered to target-independent SDNodes, and perhaps +some new SDNodes could be added. + +For example, maximum, minimum, and absolute value operations are well-defined +and standard operations, both for vector and scalar types. + +The current NEON-specific intrinsics for count leading zeros and count one +bits could perhaps be replaced by the target-independent ctlz and ctpop +intrinsics. It may also make sense to add a target-independent "ctls" +intrinsic for "count leading sign bits". Likewise, the backend could use +the target-independent SDNodes for these operations. + +ARMv6 has scalar saturating and halving adds and subtracts. The same +intrinsics could possibly be used for both NEON's vector implementations of +those operations and the ARMv6 scalar versions. + +//===---------------------------------------------------------------------===// + +ARM::MOVCCr is commutable (by flipping the condition). But we need to implement +ARMInstrInfo::commuteInstruction() to support it. + +//===---------------------------------------------------------------------===// + +Split out LDR (literal) from normal ARM LDR instruction. Also consider spliting +LDR into imm12 and so_reg forms. This allows us to clean up some code. e.g. +ARMLoadStoreOptimizer does not need to look at LDR (literal) and LDR (so_reg) +while ARMConstantIslandPass only need to worry about LDR (literal). + +//===---------------------------------------------------------------------===// + +Constant island pass should make use of full range SoImm values for LEApcrel. +Be careful though as the last attempt caused infinite looping on lencod. + +//===---------------------------------------------------------------------===// + +Predication issue. This function: + +extern unsigned array[ 128 ]; +int foo( int x ) { + int y; + y = array[ x & 127 ]; + if ( x & 128 ) + y = 123456789 & ( y >> 2 ); + else + y = 123456789 & y; + return y; +} + +compiles to: + +_foo: + and r1, r0, #127 + ldr r2, LCPI1_0 + ldr r2, [r2] + ldr r1, [r2, +r1, lsl #2] + mov r2, r1, lsr #2 + tst r0, #128 + moveq r2, r1 + ldr r0, LCPI1_1 + and r0, r2, r0 + bx lr + +It would be better to do something like this, to fold the shift into the +conditional move: + + and r1, r0, #127 + ldr r2, LCPI1_0 + ldr r2, [r2] + ldr r1, [r2, +r1, lsl #2] + tst r0, #128 + movne r1, r1, lsr #2 + ldr r0, LCPI1_1 + and r0, r1, r0 + bx lr + +it saves an instruction and a register. + +//===---------------------------------------------------------------------===// + +It might be profitable to cse MOVi16 if there are lots of 32-bit immediates +with the same bottom half. + +//===---------------------------------------------------------------------===// + +Robert Muth started working on an alternate jump table implementation that +does not put the tables in-line in the text. This is more like the llvm +default jump table implementation. This might be useful sometime. Several +revisions of patches are on the mailing list, beginning at: +http://lists.cs.uiuc.edu/pipermail/llvmdev/2009-June/022763.html + +//===---------------------------------------------------------------------===// + +Make use of the "rbit" instruction. + +//===---------------------------------------------------------------------===// + +Take a look at test/CodeGen/Thumb2/machine-licm.ll. ARM should be taught how +to licm and cse the unnecessary load from cp#1. diff --git a/libclamav/c++/llvm/lib/Target/ARM/TargetInfo/ARMTargetInfo.cpp b/libclamav/c++/llvm/lib/Target/ARM/TargetInfo/ARMTargetInfo.cpp new file mode 100644 index 000000000..163a0a987 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/ARM/TargetInfo/ARMTargetInfo.cpp @@ -0,0 +1,23 @@ +//===-- ARMTargetInfo.cpp - ARM Target Implementation ---------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "ARM.h" +#include "llvm/Module.h" +#include "llvm/Target/TargetRegistry.h" +using namespace llvm; + +Target llvm::TheARMTarget, llvm::TheThumbTarget; + +extern "C" void LLVMInitializeARMTargetInfo() { + RegisterTarget + X(TheARMTarget, "arm", "ARM"); + + RegisterTarget + Y(TheThumbTarget, "thumb", "Thumb"); +} diff --git a/libclamav/c++/llvm/lib/Target/ARM/TargetInfo/CMakeLists.txt b/libclamav/c++/llvm/lib/Target/ARM/TargetInfo/CMakeLists.txt new file mode 100644 index 000000000..3910bb02e --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/ARM/TargetInfo/CMakeLists.txt @@ -0,0 +1,7 @@ +include_directories( ${CMAKE_CURRENT_BINARY_DIR}/.. ${CMAKE_CURRENT_SOURCE_DIR}/.. ) + +add_llvm_library(LLVMARMInfo + ARMTargetInfo.cpp + ) + +add_dependencies(LLVMARMInfo ARMCodeGenTable_gen) diff --git a/libclamav/c++/llvm/lib/Target/ARM/TargetInfo/Makefile b/libclamav/c++/llvm/lib/Target/ARM/TargetInfo/Makefile new file mode 100644 index 000000000..6292ab14b --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/ARM/TargetInfo/Makefile @@ -0,0 +1,15 @@ +##===- lib/Target/ARM/TargetInfo/Makefile ------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## +LEVEL = ../../../.. +LIBRARYNAME = LLVMARMInfo + +# Hack: we need to include 'main' target directory to grab private headers +CPPFLAGS = -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. + +include $(LEVEL)/Makefile.common diff --git a/libclamav/c++/llvm/lib/Target/ARM/Thumb1InstrInfo.cpp b/libclamav/c++/llvm/lib/Target/ARM/Thumb1InstrInfo.cpp new file mode 100644 index 000000000..7602b6ded --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/ARM/Thumb1InstrInfo.cpp @@ -0,0 +1,265 @@ +//===- Thumb1InstrInfo.cpp - Thumb-1 Instruction Information ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the Thumb-1 implementation of the TargetInstrInfo class. +// +//===----------------------------------------------------------------------===// + +#include "Thumb1InstrInfo.h" +#include "ARM.h" +#include "ARMGenInstrInfo.inc" +#include "ARMMachineFunctionInfo.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineMemOperand.h" +#include "llvm/CodeGen/PseudoSourceValue.h" +#include "llvm/ADT/SmallVector.h" +#include "Thumb1InstrInfo.h" + +using namespace llvm; + +Thumb1InstrInfo::Thumb1InstrInfo(const ARMSubtarget &STI) + : ARMBaseInstrInfo(STI), RI(*this, STI) { +} + +unsigned Thumb1InstrInfo::getUnindexedOpcode(unsigned Opc) const { + return 0; +} + +bool +Thumb1InstrInfo::BlockHasNoFallThrough(const MachineBasicBlock &MBB) const { + if (MBB.empty()) return false; + + switch (MBB.back().getOpcode()) { + case ARM::tBX_RET: + case ARM::tBX_RET_vararg: + case ARM::tPOP_RET: + case ARM::tB: + case ARM::tBRIND: + case ARM::tBR_JTr: + return true; + default: + break; + } + + return false; +} + +bool Thumb1InstrInfo::copyRegToReg(MachineBasicBlock &MBB, + MachineBasicBlock::iterator I, + unsigned DestReg, unsigned SrcReg, + const TargetRegisterClass *DestRC, + const TargetRegisterClass *SrcRC) const { + DebugLoc DL = DebugLoc::getUnknownLoc(); + if (I != MBB.end()) DL = I->getDebugLoc(); + + if (DestRC == ARM::GPRRegisterClass) { + if (SrcRC == ARM::GPRRegisterClass) { + BuildMI(MBB, I, DL, get(ARM::tMOVgpr2gpr), DestReg).addReg(SrcReg); + return true; + } else if (SrcRC == ARM::tGPRRegisterClass) { + BuildMI(MBB, I, DL, get(ARM::tMOVtgpr2gpr), DestReg).addReg(SrcReg); + return true; + } + } else if (DestRC == ARM::tGPRRegisterClass) { + if (SrcRC == ARM::GPRRegisterClass) { + BuildMI(MBB, I, DL, get(ARM::tMOVgpr2tgpr), DestReg).addReg(SrcReg); + return true; + } else if (SrcRC == ARM::tGPRRegisterClass) { + BuildMI(MBB, I, DL, get(ARM::tMOVr), DestReg).addReg(SrcReg); + return true; + } + } + + return false; +} + +bool Thumb1InstrInfo:: +canFoldMemoryOperand(const MachineInstr *MI, + const SmallVectorImpl &Ops) const { + if (Ops.size() != 1) return false; + + unsigned OpNum = Ops[0]; + unsigned Opc = MI->getOpcode(); + switch (Opc) { + default: break; + case ARM::tMOVr: + case ARM::tMOVtgpr2gpr: + case ARM::tMOVgpr2tgpr: + case ARM::tMOVgpr2gpr: { + if (OpNum == 0) { // move -> store + unsigned SrcReg = MI->getOperand(1).getReg(); + if (TargetRegisterInfo::isPhysicalRegister(SrcReg) && + !isARMLowRegister(SrcReg)) + // tSpill cannot take a high register operand. + return false; + } else { // move -> load + unsigned DstReg = MI->getOperand(0).getReg(); + if (TargetRegisterInfo::isPhysicalRegister(DstReg) && + !isARMLowRegister(DstReg)) + // tRestore cannot target a high register operand. + return false; + } + return true; + } + } + + return false; +} + +void Thumb1InstrInfo:: +storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, + unsigned SrcReg, bool isKill, int FI, + const TargetRegisterClass *RC) const { + DebugLoc DL = DebugLoc::getUnknownLoc(); + if (I != MBB.end()) DL = I->getDebugLoc(); + + assert((RC == ARM::tGPRRegisterClass || + (TargetRegisterInfo::isPhysicalRegister(SrcReg) && + isARMLowRegister(SrcReg))) && "Unknown regclass!"); + + if (RC == ARM::tGPRRegisterClass) { + MachineFunction &MF = *MBB.getParent(); + MachineFrameInfo &MFI = *MF.getFrameInfo(); + MachineMemOperand *MMO = + MF.getMachineMemOperand(PseudoSourceValue::getFixedStack(FI), + MachineMemOperand::MOStore, 0, + MFI.getObjectSize(FI), + MFI.getObjectAlignment(FI)); + AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::tSpill)) + .addReg(SrcReg, getKillRegState(isKill)) + .addFrameIndex(FI).addImm(0).addMemOperand(MMO)); + } +} + +void Thumb1InstrInfo:: +loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, + unsigned DestReg, int FI, + const TargetRegisterClass *RC) const { + DebugLoc DL = DebugLoc::getUnknownLoc(); + if (I != MBB.end()) DL = I->getDebugLoc(); + + assert((RC == ARM::tGPRRegisterClass || + (TargetRegisterInfo::isPhysicalRegister(DestReg) && + isARMLowRegister(DestReg))) && "Unknown regclass!"); + + if (RC == ARM::tGPRRegisterClass) { + MachineFunction &MF = *MBB.getParent(); + MachineFrameInfo &MFI = *MF.getFrameInfo(); + MachineMemOperand *MMO = + MF.getMachineMemOperand(PseudoSourceValue::getFixedStack(FI), + MachineMemOperand::MOLoad, 0, + MFI.getObjectSize(FI), + MFI.getObjectAlignment(FI)); + AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::tRestore), DestReg) + .addFrameIndex(FI).addImm(0).addMemOperand(MMO)); + } +} + +bool Thumb1InstrInfo:: +spillCalleeSavedRegisters(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + const std::vector &CSI) const { + if (CSI.empty()) + return false; + + DebugLoc DL = DebugLoc::getUnknownLoc(); + if (MI != MBB.end()) DL = MI->getDebugLoc(); + + MachineInstrBuilder MIB = BuildMI(MBB, MI, DL, get(ARM::tPUSH)); + AddDefaultPred(MIB); + MIB.addReg(0); // No write back. + for (unsigned i = CSI.size(); i != 0; --i) { + unsigned Reg = CSI[i-1].getReg(); + // Add the callee-saved register as live-in. It's killed at the spill. + MBB.addLiveIn(Reg); + MIB.addReg(Reg, RegState::Kill); + } + return true; +} + +bool Thumb1InstrInfo:: +restoreCalleeSavedRegisters(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + const std::vector &CSI) const { + MachineFunction &MF = *MBB.getParent(); + ARMFunctionInfo *AFI = MF.getInfo(); + if (CSI.empty()) + return false; + + bool isVarArg = AFI->getVarArgsRegSaveSize() > 0; + DebugLoc DL = MI->getDebugLoc(); + MachineInstrBuilder MIB = BuildMI(MF, DL, get(ARM::tPOP)); + AddDefaultPred(MIB); + MIB.addReg(0); // No write back. + + bool NumRegs = 0; + for (unsigned i = CSI.size(); i != 0; --i) { + unsigned Reg = CSI[i-1].getReg(); + if (Reg == ARM::LR) { + // Special epilogue for vararg functions. See emitEpilogue + if (isVarArg) + continue; + Reg = ARM::PC; + (*MIB).setDesc(get(ARM::tPOP_RET)); + MI = MBB.erase(MI); + } + MIB.addReg(Reg, getDefRegState(true)); + ++NumRegs; + } + + // It's illegal to emit pop instruction without operands. + if (NumRegs) + MBB.insert(MI, &*MIB); + + return true; +} + +MachineInstr *Thumb1InstrInfo:: +foldMemoryOperandImpl(MachineFunction &MF, MachineInstr *MI, + const SmallVectorImpl &Ops, int FI) const { + if (Ops.size() != 1) return NULL; + + unsigned OpNum = Ops[0]; + unsigned Opc = MI->getOpcode(); + MachineInstr *NewMI = NULL; + switch (Opc) { + default: break; + case ARM::tMOVr: + case ARM::tMOVtgpr2gpr: + case ARM::tMOVgpr2tgpr: + case ARM::tMOVgpr2gpr: { + if (OpNum == 0) { // move -> store + unsigned SrcReg = MI->getOperand(1).getReg(); + bool isKill = MI->getOperand(1).isKill(); + if (TargetRegisterInfo::isPhysicalRegister(SrcReg) && + !isARMLowRegister(SrcReg)) + // tSpill cannot take a high register operand. + break; + NewMI = AddDefaultPred(BuildMI(MF, MI->getDebugLoc(), get(ARM::tSpill)) + .addReg(SrcReg, getKillRegState(isKill)) + .addFrameIndex(FI).addImm(0)); + } else { // move -> load + unsigned DstReg = MI->getOperand(0).getReg(); + if (TargetRegisterInfo::isPhysicalRegister(DstReg) && + !isARMLowRegister(DstReg)) + // tRestore cannot target a high register operand. + break; + bool isDead = MI->getOperand(0).isDead(); + NewMI = AddDefaultPred(BuildMI(MF, MI->getDebugLoc(), get(ARM::tRestore)) + .addReg(DstReg, + RegState::Define | getDeadRegState(isDead)) + .addFrameIndex(FI).addImm(0)); + } + break; + } + } + + return NewMI; +} diff --git a/libclamav/c++/llvm/lib/Target/ARM/Thumb1InstrInfo.h b/libclamav/c++/llvm/lib/Target/ARM/Thumb1InstrInfo.h new file mode 100644 index 000000000..b28229dd3 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/ARM/Thumb1InstrInfo.h @@ -0,0 +1,82 @@ +//===- Thumb1InstrInfo.h - Thumb-1 Instruction Information ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the Thumb-1 implementation of the TargetInstrInfo class. +// +//===----------------------------------------------------------------------===// + +#ifndef THUMB1INSTRUCTIONINFO_H +#define THUMB1INSTRUCTIONINFO_H + +#include "llvm/Target/TargetInstrInfo.h" +#include "ARM.h" +#include "ARMInstrInfo.h" +#include "Thumb1RegisterInfo.h" + +namespace llvm { + class ARMSubtarget; + +class Thumb1InstrInfo : public ARMBaseInstrInfo { + Thumb1RegisterInfo RI; +public: + explicit Thumb1InstrInfo(const ARMSubtarget &STI); + + // Return the non-pre/post incrementing version of 'Opc'. Return 0 + // if there is not such an opcode. + unsigned getUnindexedOpcode(unsigned Opc) const; + + // Return true if the block does not fall through. + bool BlockHasNoFallThrough(const MachineBasicBlock &MBB) const; + + /// getRegisterInfo - TargetInstrInfo is a superset of MRegister info. As + /// such, whenever a client has an instance of instruction info, it should + /// always be able to get register info as well (through this method). + /// + const Thumb1RegisterInfo &getRegisterInfo() const { return RI; } + + bool spillCalleeSavedRegisters(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + const std::vector &CSI) const; + bool restoreCalleeSavedRegisters(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + const std::vector &CSI) const; + + bool copyRegToReg(MachineBasicBlock &MBB, + MachineBasicBlock::iterator I, + unsigned DestReg, unsigned SrcReg, + const TargetRegisterClass *DestRC, + const TargetRegisterClass *SrcRC) const; + void storeRegToStackSlot(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MBBI, + unsigned SrcReg, bool isKill, int FrameIndex, + const TargetRegisterClass *RC) const; + + void loadRegFromStackSlot(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MBBI, + unsigned DestReg, int FrameIndex, + const TargetRegisterClass *RC) const; + + bool canFoldMemoryOperand(const MachineInstr *MI, + const SmallVectorImpl &Ops) const; + + MachineInstr* foldMemoryOperandImpl(MachineFunction &MF, + MachineInstr* MI, + const SmallVectorImpl &Ops, + int FrameIndex) const; + + MachineInstr* foldMemoryOperandImpl(MachineFunction &MF, + MachineInstr* MI, + const SmallVectorImpl &Ops, + MachineInstr* LoadMI) const { + return 0; + } +}; +} + +#endif // THUMB1INSTRUCTIONINFO_H diff --git a/libclamav/c++/llvm/lib/Target/ARM/Thumb1RegisterInfo.cpp b/libclamav/c++/llvm/lib/Target/ARM/Thumb1RegisterInfo.cpp new file mode 100644 index 000000000..37adf37af --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/ARM/Thumb1RegisterInfo.cpp @@ -0,0 +1,846 @@ +//===- Thumb1RegisterInfo.cpp - Thumb-1 Register Information ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the Thumb-1 implementation of the TargetRegisterInfo +// class. +// +//===----------------------------------------------------------------------===// + +#include "ARM.h" +#include "ARMAddressingModes.h" +#include "ARMBaseInstrInfo.h" +#include "ARMMachineFunctionInfo.h" +#include "ARMSubtarget.h" +#include "Thumb1InstrInfo.h" +#include "Thumb1RegisterInfo.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Function.h" +#include "llvm/LLVMContext.h" +#include "llvm/CodeGen/MachineConstantPool.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineLocation.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/Target/TargetFrameInfo.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/ADT/BitVector.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +Thumb1RegisterInfo::Thumb1RegisterInfo(const ARMBaseInstrInfo &tii, + const ARMSubtarget &sti) + : ARMBaseRegisterInfo(tii, sti) { +} + +/// emitLoadConstPool - Emits a load from constpool to materialize the +/// specified immediate. +void Thumb1RegisterInfo::emitLoadConstPool(MachineBasicBlock &MBB, + MachineBasicBlock::iterator &MBBI, + DebugLoc dl, + unsigned DestReg, unsigned SubIdx, + int Val, + ARMCC::CondCodes Pred, + unsigned PredReg) const { + MachineFunction &MF = *MBB.getParent(); + MachineConstantPool *ConstantPool = MF.getConstantPool(); + Constant *C = ConstantInt::get( + Type::getInt32Ty(MBB.getParent()->getFunction()->getContext()), Val); + unsigned Idx = ConstantPool->getConstantPoolIndex(C, 4); + + BuildMI(MBB, MBBI, dl, TII.get(ARM::tLDRcp)) + .addReg(DestReg, getDefRegState(true), SubIdx) + .addConstantPoolIndex(Idx).addImm(Pred).addReg(PredReg); +} + +const TargetRegisterClass* +Thumb1RegisterInfo::getPhysicalRegisterRegClass(unsigned Reg, EVT VT) const { + if (isARMLowRegister(Reg)) + return ARM::tGPRRegisterClass; + switch (Reg) { + default: + break; + case ARM::R8: case ARM::R9: case ARM::R10: case ARM::R11: + case ARM::R12: case ARM::SP: case ARM::LR: case ARM::PC: + return ARM::GPRRegisterClass; + } + + return TargetRegisterInfo::getPhysicalRegisterRegClass(Reg, VT); +} + +bool Thumb1RegisterInfo::hasReservedCallFrame(MachineFunction &MF) const { + const MachineFrameInfo *FFI = MF.getFrameInfo(); + unsigned CFSize = FFI->getMaxCallFrameSize(); + // It's not always a good idea to include the call frame as part of the + // stack frame. ARM (especially Thumb) has small immediate offset to + // address the stack frame. So a large call frame can cause poor codegen + // and may even makes it impossible to scavenge a register. + if (CFSize >= ((1 << 8) - 1) * 4 / 2) // Half of imm8 * 4 + return false; + + return !MF.getFrameInfo()->hasVarSizedObjects(); +} + + +/// emitThumbRegPlusImmInReg - Emits a series of instructions to materialize +/// a destreg = basereg + immediate in Thumb code. Materialize the immediate +/// in a register using mov / mvn sequences or load the immediate from a +/// constpool entry. +static +void emitThumbRegPlusImmInReg(MachineBasicBlock &MBB, + MachineBasicBlock::iterator &MBBI, + unsigned DestReg, unsigned BaseReg, + int NumBytes, bool CanChangeCC, + const TargetInstrInfo &TII, + const Thumb1RegisterInfo& MRI, + DebugLoc dl) { + MachineFunction &MF = *MBB.getParent(); + bool isHigh = !isARMLowRegister(DestReg) || + (BaseReg != 0 && !isARMLowRegister(BaseReg)); + bool isSub = false; + // Subtract doesn't have high register version. Load the negative value + // if either base or dest register is a high register. Also, if do not + // issue sub as part of the sequence if condition register is to be + // preserved. + if (NumBytes < 0 && !isHigh && CanChangeCC) { + isSub = true; + NumBytes = -NumBytes; + } + unsigned LdReg = DestReg; + if (DestReg == ARM::SP) { + assert(BaseReg == ARM::SP && "Unexpected!"); + LdReg = MF.getRegInfo().createVirtualRegister(ARM::tGPRRegisterClass); + } + + if (NumBytes <= 255 && NumBytes >= 0) + AddDefaultT1CC(BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVi8), LdReg)) + .addImm(NumBytes); + else if (NumBytes < 0 && NumBytes >= -255) { + AddDefaultT1CC(BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVi8), LdReg)) + .addImm(NumBytes); + AddDefaultT1CC(BuildMI(MBB, MBBI, dl, TII.get(ARM::tRSB), LdReg)) + .addReg(LdReg, RegState::Kill); + } else + MRI.emitLoadConstPool(MBB, MBBI, dl, LdReg, 0, NumBytes); + + // Emit add / sub. + int Opc = (isSub) ? ARM::tSUBrr : (isHigh ? ARM::tADDhirr : ARM::tADDrr); + MachineInstrBuilder MIB = + BuildMI(MBB, MBBI, dl, TII.get(Opc), DestReg); + if (Opc != ARM::tADDhirr) + MIB = AddDefaultT1CC(MIB); + if (DestReg == ARM::SP || isSub) + MIB.addReg(BaseReg).addReg(LdReg, RegState::Kill); + else + MIB.addReg(LdReg).addReg(BaseReg, RegState::Kill); + AddDefaultPred(MIB); +} + +/// calcNumMI - Returns the number of instructions required to materialize +/// the specific add / sub r, c instruction. +static unsigned calcNumMI(int Opc, int ExtraOpc, unsigned Bytes, + unsigned NumBits, unsigned Scale) { + unsigned NumMIs = 0; + unsigned Chunk = ((1 << NumBits) - 1) * Scale; + + if (Opc == ARM::tADDrSPi) { + unsigned ThisVal = (Bytes > Chunk) ? Chunk : Bytes; + Bytes -= ThisVal; + NumMIs++; + NumBits = 8; + Scale = 1; // Followed by a number of tADDi8. + Chunk = ((1 << NumBits) - 1) * Scale; + } + + NumMIs += Bytes / Chunk; + if ((Bytes % Chunk) != 0) + NumMIs++; + if (ExtraOpc) + NumMIs++; + return NumMIs; +} + +/// emitThumbRegPlusImmediate - Emits a series of instructions to materialize +/// a destreg = basereg + immediate in Thumb code. +static +void emitThumbRegPlusImmediate(MachineBasicBlock &MBB, + MachineBasicBlock::iterator &MBBI, + unsigned DestReg, unsigned BaseReg, + int NumBytes, const TargetInstrInfo &TII, + const Thumb1RegisterInfo& MRI, + DebugLoc dl) { + bool isSub = NumBytes < 0; + unsigned Bytes = (unsigned)NumBytes; + if (isSub) Bytes = -NumBytes; + bool isMul4 = (Bytes & 3) == 0; + bool isTwoAddr = false; + bool DstNotEqBase = false; + unsigned NumBits = 1; + unsigned Scale = 1; + int Opc = 0; + int ExtraOpc = 0; + bool NeedCC = false; + bool NeedPred = false; + + if (DestReg == BaseReg && BaseReg == ARM::SP) { + assert(isMul4 && "Thumb sp inc / dec size must be multiple of 4!"); + NumBits = 7; + Scale = 4; + Opc = isSub ? ARM::tSUBspi : ARM::tADDspi; + isTwoAddr = true; + } else if (!isSub && BaseReg == ARM::SP) { + // r1 = add sp, 403 + // => + // r1 = add sp, 100 * 4 + // r1 = add r1, 3 + if (!isMul4) { + Bytes &= ~3; + ExtraOpc = ARM::tADDi3; + } + NumBits = 8; + Scale = 4; + Opc = ARM::tADDrSPi; + } else { + // sp = sub sp, c + // r1 = sub sp, c + // r8 = sub sp, c + if (DestReg != BaseReg) + DstNotEqBase = true; + NumBits = 8; + if (DestReg == ARM::SP) { + Opc = isSub ? ARM::tSUBspi : ARM::tADDspi; + assert(isMul4 && "Thumb sp inc / dec size must be multiple of 4!"); + NumBits = 7; + Scale = 4; + } else { + Opc = isSub ? ARM::tSUBi8 : ARM::tADDi8; + NumBits = 8; + NeedPred = NeedCC = true; + } + isTwoAddr = true; + } + + unsigned NumMIs = calcNumMI(Opc, ExtraOpc, Bytes, NumBits, Scale); + unsigned Threshold = (DestReg == ARM::SP) ? 3 : 2; + if (NumMIs > Threshold) { + // This will expand into too many instructions. Load the immediate from a + // constpool entry. + emitThumbRegPlusImmInReg(MBB, MBBI, DestReg, BaseReg, NumBytes, true, TII, + MRI, dl); + return; + } + + if (DstNotEqBase) { + if (isARMLowRegister(DestReg) && isARMLowRegister(BaseReg)) { + // If both are low registers, emit DestReg = add BaseReg, max(Imm, 7) + unsigned Chunk = (1 << 3) - 1; + unsigned ThisVal = (Bytes > Chunk) ? Chunk : Bytes; + Bytes -= ThisVal; + const TargetInstrDesc &TID = TII.get(isSub ? ARM::tSUBi3 : ARM::tADDi3); + const MachineInstrBuilder MIB = + AddDefaultT1CC(BuildMI(MBB, MBBI, dl, TID, DestReg)); + AddDefaultPred(MIB.addReg(BaseReg, RegState::Kill).addImm(ThisVal)); + } else { + BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVr), DestReg) + .addReg(BaseReg, RegState::Kill); + } + BaseReg = DestReg; + } + + unsigned Chunk = ((1 << NumBits) - 1) * Scale; + while (Bytes) { + unsigned ThisVal = (Bytes > Chunk) ? Chunk : Bytes; + Bytes -= ThisVal; + ThisVal /= Scale; + // Build the new tADD / tSUB. + if (isTwoAddr) { + MachineInstrBuilder MIB = BuildMI(MBB, MBBI, dl, TII.get(Opc), DestReg); + if (NeedCC) + MIB = AddDefaultT1CC(MIB); + MIB .addReg(DestReg).addImm(ThisVal); + if (NeedPred) + MIB = AddDefaultPred(MIB); + } + else { + bool isKill = BaseReg != ARM::SP; + MachineInstrBuilder MIB = BuildMI(MBB, MBBI, dl, TII.get(Opc), DestReg); + if (NeedCC) + MIB = AddDefaultT1CC(MIB); + MIB.addReg(BaseReg, getKillRegState(isKill)).addImm(ThisVal); + if (NeedPred) + MIB = AddDefaultPred(MIB); + BaseReg = DestReg; + + if (Opc == ARM::tADDrSPi) { + // r4 = add sp, imm + // r4 = add r4, imm + // ... + NumBits = 8; + Scale = 1; + Chunk = ((1 << NumBits) - 1) * Scale; + Opc = isSub ? ARM::tSUBi8 : ARM::tADDi8; + NeedPred = NeedCC = isTwoAddr = true; + } + } + } + + if (ExtraOpc) { + const TargetInstrDesc &TID = TII.get(ExtraOpc); + AddDefaultPred(AddDefaultT1CC(BuildMI(MBB, MBBI, dl, TID, DestReg)) + .addReg(DestReg, RegState::Kill) + .addImm(((unsigned)NumBytes) & 3)); + } +} + +static void emitSPUpdate(MachineBasicBlock &MBB, + MachineBasicBlock::iterator &MBBI, + const TargetInstrInfo &TII, DebugLoc dl, + const Thumb1RegisterInfo &MRI, + int NumBytes) { + emitThumbRegPlusImmediate(MBB, MBBI, ARM::SP, ARM::SP, NumBytes, TII, + MRI, dl); +} + +void Thumb1RegisterInfo:: +eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, + MachineBasicBlock::iterator I) const { + if (!hasReservedCallFrame(MF)) { + // If we have alloca, convert as follows: + // ADJCALLSTACKDOWN -> sub, sp, sp, amount + // ADJCALLSTACKUP -> add, sp, sp, amount + MachineInstr *Old = I; + DebugLoc dl = Old->getDebugLoc(); + unsigned Amount = Old->getOperand(0).getImm(); + if (Amount != 0) { + // We need to keep the stack aligned properly. To do this, we round the + // amount of space needed for the outgoing arguments up to the next + // alignment boundary. + unsigned Align = MF.getTarget().getFrameInfo()->getStackAlignment(); + Amount = (Amount+Align-1)/Align*Align; + + // Replace the pseudo instruction with a new instruction... + unsigned Opc = Old->getOpcode(); + if (Opc == ARM::ADJCALLSTACKDOWN || Opc == ARM::tADJCALLSTACKDOWN) { + emitSPUpdate(MBB, I, TII, dl, *this, -Amount); + } else { + assert(Opc == ARM::ADJCALLSTACKUP || Opc == ARM::tADJCALLSTACKUP); + emitSPUpdate(MBB, I, TII, dl, *this, Amount); + } + } + } + MBB.erase(I); +} + +/// emitThumbConstant - Emit a series of instructions to materialize a +/// constant. +static void emitThumbConstant(MachineBasicBlock &MBB, + MachineBasicBlock::iterator &MBBI, + unsigned DestReg, int Imm, + const TargetInstrInfo &TII, + const Thumb1RegisterInfo& MRI, + DebugLoc dl) { + bool isSub = Imm < 0; + if (isSub) Imm = -Imm; + + int Chunk = (1 << 8) - 1; + int ThisVal = (Imm > Chunk) ? Chunk : Imm; + Imm -= ThisVal; + AddDefaultPred(AddDefaultT1CC(BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVi8), + DestReg)) + .addImm(ThisVal)); + if (Imm > 0) + emitThumbRegPlusImmediate(MBB, MBBI, DestReg, DestReg, Imm, TII, MRI, dl); + if (isSub) { + const TargetInstrDesc &TID = TII.get(ARM::tRSB); + AddDefaultPred(AddDefaultT1CC(BuildMI(MBB, MBBI, dl, TID, DestReg)) + .addReg(DestReg, RegState::Kill)); + } +} + +static void removeOperands(MachineInstr &MI, unsigned i) { + unsigned Op = i; + for (unsigned e = MI.getNumOperands(); i != e; ++i) + MI.RemoveOperand(Op); +} + +int Thumb1RegisterInfo:: +rewriteFrameIndex(MachineInstr &MI, unsigned FrameRegIdx, + unsigned FrameReg, int Offset, + unsigned MOVOpc, unsigned ADDriOpc, unsigned SUBriOpc) const +{ + // if/when eliminateFrameIndex() conforms with ARMBaseRegisterInfo + // version then can pull out Thumb1 specific parts here + return 0; +} + +/// saveScavengerRegister - Spill the register so it can be used by the +/// register scavenger. Return true. +bool +Thumb1RegisterInfo::saveScavengerRegister(MachineBasicBlock &MBB, + MachineBasicBlock::iterator I, + MachineBasicBlock::iterator &UseMI, + const TargetRegisterClass *RC, + unsigned Reg) const { + // Thumb1 can't use the emergency spill slot on the stack because + // ldr/str immediate offsets must be positive, and if we're referencing + // off the frame pointer (if, for example, there are alloca() calls in + // the function, the offset will be negative. Use R12 instead since that's + // a call clobbered register that we know won't be used in Thumb1 mode. + DebugLoc DL = DebugLoc::getUnknownLoc(); + BuildMI(MBB, I, DL, TII.get(ARM::tMOVtgpr2gpr)). + addReg(ARM::R12, RegState::Define).addReg(Reg, RegState::Kill); + + // The UseMI is where we would like to restore the register. If there's + // interference with R12 before then, however, we'll need to restore it + // before that instead and adjust the UseMI. + bool done = false; + for (MachineBasicBlock::iterator II = I; !done && II != UseMI ; ++II) { + // If this instruction affects R12, adjust our restore point. + for (unsigned i = 0, e = II->getNumOperands(); i != e; ++i) { + const MachineOperand &MO = II->getOperand(i); + if (!MO.isReg() || MO.isUndef() || !MO.getReg() || + TargetRegisterInfo::isVirtualRegister(MO.getReg())) + continue; + if (MO.getReg() == ARM::R12) { + UseMI = II; + done = true; + break; + } + } + } + // Restore the register from R12 + BuildMI(MBB, UseMI, DL, TII.get(ARM::tMOVgpr2tgpr)). + addReg(Reg, RegState::Define).addReg(ARM::R12, RegState::Kill); + + return true; +} + +unsigned +Thumb1RegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, + int SPAdj, int *Value, + RegScavenger *RS) const{ + unsigned VReg = 0; + unsigned i = 0; + MachineInstr &MI = *II; + MachineBasicBlock &MBB = *MI.getParent(); + MachineFunction &MF = *MBB.getParent(); + ARMFunctionInfo *AFI = MF.getInfo(); + DebugLoc dl = MI.getDebugLoc(); + + while (!MI.getOperand(i).isFI()) { + ++i; + assert(i < MI.getNumOperands() && "Instr doesn't have FrameIndex operand!"); + } + + unsigned FrameReg = ARM::SP; + int FrameIndex = MI.getOperand(i).getIndex(); + int Offset = MF.getFrameInfo()->getObjectOffset(FrameIndex) + + MF.getFrameInfo()->getStackSize() + SPAdj; + + if (AFI->isGPRCalleeSavedArea1Frame(FrameIndex)) + Offset -= AFI->getGPRCalleeSavedArea1Offset(); + else if (AFI->isGPRCalleeSavedArea2Frame(FrameIndex)) + Offset -= AFI->getGPRCalleeSavedArea2Offset(); + else if (hasFP(MF)) { + assert(SPAdj == 0 && "Unexpected"); + // There is alloca()'s in this function, must reference off the frame + // pointer instead. + FrameReg = getFrameRegister(MF); + Offset -= AFI->getFramePtrSpillOffset(); + } + + unsigned Opcode = MI.getOpcode(); + const TargetInstrDesc &Desc = MI.getDesc(); + unsigned AddrMode = (Desc.TSFlags & ARMII::AddrModeMask); + + if (Opcode == ARM::tADDrSPi) { + Offset += MI.getOperand(i+1).getImm(); + + // Can't use tADDrSPi if it's based off the frame pointer. + unsigned NumBits = 0; + unsigned Scale = 1; + if (FrameReg != ARM::SP) { + Opcode = ARM::tADDi3; + MI.setDesc(TII.get(Opcode)); + NumBits = 3; + } else { + NumBits = 8; + Scale = 4; + assert((Offset & 3) == 0 && + "Thumb add/sub sp, #imm immediate must be multiple of 4!"); + } + + if (Offset == 0) { + // Turn it into a move. + MI.setDesc(TII.get(ARM::tMOVgpr2tgpr)); + MI.getOperand(i).ChangeToRegister(FrameReg, false); + MI.RemoveOperand(i+1); + return 0; + } + + // Common case: small offset, fits into instruction. + unsigned Mask = (1 << NumBits) - 1; + if (((Offset / Scale) & ~Mask) == 0) { + // Replace the FrameIndex with sp / fp + if (Opcode == ARM::tADDi3) { + removeOperands(MI, i); + MachineInstrBuilder MIB(&MI); + AddDefaultPred(AddDefaultT1CC(MIB).addReg(FrameReg) + .addImm(Offset / Scale)); + } else { + MI.getOperand(i).ChangeToRegister(FrameReg, false); + MI.getOperand(i+1).ChangeToImmediate(Offset / Scale); + } + return 0; + } + + unsigned DestReg = MI.getOperand(0).getReg(); + unsigned Bytes = (Offset > 0) ? Offset : -Offset; + unsigned NumMIs = calcNumMI(Opcode, 0, Bytes, NumBits, Scale); + // MI would expand into a large number of instructions. Don't try to + // simplify the immediate. + if (NumMIs > 2) { + emitThumbRegPlusImmediate(MBB, II, DestReg, FrameReg, Offset, TII, + *this, dl); + MBB.erase(II); + return 0; + } + + if (Offset > 0) { + // Translate r0 = add sp, imm to + // r0 = add sp, 255*4 + // r0 = add r0, (imm - 255*4) + if (Opcode == ARM::tADDi3) { + removeOperands(MI, i); + MachineInstrBuilder MIB(&MI); + AddDefaultPred(AddDefaultT1CC(MIB).addReg(FrameReg).addImm(Mask)); + } else { + MI.getOperand(i).ChangeToRegister(FrameReg, false); + MI.getOperand(i+1).ChangeToImmediate(Mask); + } + Offset = (Offset - Mask * Scale); + MachineBasicBlock::iterator NII = next(II); + emitThumbRegPlusImmediate(MBB, NII, DestReg, DestReg, Offset, TII, + *this, dl); + } else { + // Translate r0 = add sp, -imm to + // r0 = -imm (this is then translated into a series of instructons) + // r0 = add r0, sp + emitThumbConstant(MBB, II, DestReg, Offset, TII, *this, dl); + + MI.setDesc(TII.get(ARM::tADDhirr)); + MI.getOperand(i).ChangeToRegister(DestReg, false, false, true); + MI.getOperand(i+1).ChangeToRegister(FrameReg, false); + if (Opcode == ARM::tADDi3) { + MachineInstrBuilder MIB(&MI); + AddDefaultPred(MIB); + } + } + return 0; + } else { + unsigned ImmIdx = 0; + int InstrOffs = 0; + unsigned NumBits = 0; + unsigned Scale = 1; + switch (AddrMode) { + case ARMII::AddrModeT1_s: { + ImmIdx = i+1; + InstrOffs = MI.getOperand(ImmIdx).getImm(); + NumBits = (FrameReg == ARM::SP) ? 8 : 5; + Scale = 4; + break; + } + default: + llvm_unreachable("Unsupported addressing mode!"); + break; + } + + Offset += InstrOffs * Scale; + assert((Offset & (Scale-1)) == 0 && "Can't encode this offset!"); + + // Common case: small offset, fits into instruction. + MachineOperand &ImmOp = MI.getOperand(ImmIdx); + int ImmedOffset = Offset / Scale; + unsigned Mask = (1 << NumBits) - 1; + if ((unsigned)Offset <= Mask * Scale) { + // Replace the FrameIndex with sp + MI.getOperand(i).ChangeToRegister(FrameReg, false); + ImmOp.ChangeToImmediate(ImmedOffset); + return 0; + } + + bool isThumSpillRestore = Opcode == ARM::tRestore || Opcode == ARM::tSpill; + if (AddrMode == ARMII::AddrModeT1_s) { + // Thumb tLDRspi, tSTRspi. These will change to instructions that use + // a different base register. + NumBits = 5; + Mask = (1 << NumBits) - 1; + } + // If this is a thumb spill / restore, we will be using a constpool load to + // materialize the offset. + if (AddrMode == ARMII::AddrModeT1_s && isThumSpillRestore) + ImmOp.ChangeToImmediate(0); + else { + // Otherwise, it didn't fit. Pull in what we can to simplify the immed. + ImmedOffset = ImmedOffset & Mask; + ImmOp.ChangeToImmediate(ImmedOffset); + Offset &= ~(Mask*Scale); + } + } + + // If we get here, the immediate doesn't fit into the instruction. We folded + // as much as possible above, handle the rest, providing a register that is + // SP+LargeImm. + assert(Offset && "This code isn't needed if offset already handled!"); + + // Remove predicate first. + int PIdx = MI.findFirstPredOperandIdx(); + if (PIdx != -1) + removeOperands(MI, PIdx); + + if (Desc.mayLoad()) { + // Use the destination register to materialize sp + offset. + unsigned TmpReg = MI.getOperand(0).getReg(); + bool UseRR = false; + if (Opcode == ARM::tRestore) { + if (FrameReg == ARM::SP) + emitThumbRegPlusImmInReg(MBB, II, TmpReg, FrameReg, + Offset, false, TII, *this, dl); + else { + emitLoadConstPool(MBB, II, dl, TmpReg, 0, Offset); + UseRR = true; + } + } else { + emitThumbRegPlusImmediate(MBB, II, TmpReg, FrameReg, Offset, TII, + *this, dl); + } + + MI.setDesc(TII.get(ARM::tLDR)); + MI.getOperand(i).ChangeToRegister(TmpReg, false, false, true); + if (UseRR) + // Use [reg, reg] addrmode. + MI.addOperand(MachineOperand::CreateReg(FrameReg, false)); + else // tLDR has an extra register operand. + MI.addOperand(MachineOperand::CreateReg(0, false)); + } else if (Desc.mayStore()) { + VReg = MF.getRegInfo().createVirtualRegister(ARM::tGPRRegisterClass); + assert (Value && "Frame index virtual allocated, but Value arg is NULL!"); + *Value = Offset; + bool UseRR = false; + + if (Opcode == ARM::tSpill) { + if (FrameReg == ARM::SP) + emitThumbRegPlusImmInReg(MBB, II, VReg, FrameReg, + Offset, false, TII, *this, dl); + else { + emitLoadConstPool(MBB, II, dl, VReg, 0, Offset); + UseRR = true; + } + } else + emitThumbRegPlusImmediate(MBB, II, VReg, FrameReg, Offset, TII, + *this, dl); + MI.setDesc(TII.get(ARM::tSTR)); + MI.getOperand(i).ChangeToRegister(VReg, false, false, true); + if (UseRR) // Use [reg, reg] addrmode. + MI.addOperand(MachineOperand::CreateReg(FrameReg, false)); + else // tSTR has an extra register operand. + MI.addOperand(MachineOperand::CreateReg(0, false)); + } else + assert(false && "Unexpected opcode!"); + + // Add predicate back if it's needed. + if (MI.getDesc().isPredicable()) { + MachineInstrBuilder MIB(&MI); + AddDefaultPred(MIB); + } + return VReg; +} + +void Thumb1RegisterInfo::emitPrologue(MachineFunction &MF) const { + MachineBasicBlock &MBB = MF.front(); + MachineBasicBlock::iterator MBBI = MBB.begin(); + MachineFrameInfo *MFI = MF.getFrameInfo(); + ARMFunctionInfo *AFI = MF.getInfo(); + unsigned VARegSaveSize = AFI->getVarArgsRegSaveSize(); + unsigned NumBytes = MFI->getStackSize(); + const std::vector &CSI = MFI->getCalleeSavedInfo(); + DebugLoc dl = (MBBI != MBB.end() ? + MBBI->getDebugLoc() : DebugLoc::getUnknownLoc()); + + // Thumb add/sub sp, imm8 instructions implicitly multiply the offset by 4. + NumBytes = (NumBytes + 3) & ~3; + MFI->setStackSize(NumBytes); + + // Determine the sizes of each callee-save spill areas and record which frame + // belongs to which callee-save spill areas. + unsigned GPRCS1Size = 0, GPRCS2Size = 0, DPRCSSize = 0; + int FramePtrSpillFI = 0; + + if (VARegSaveSize) + emitSPUpdate(MBB, MBBI, TII, dl, *this, -VARegSaveSize); + + if (!AFI->hasStackFrame()) { + if (NumBytes != 0) + emitSPUpdate(MBB, MBBI, TII, dl, *this, -NumBytes); + return; + } + + for (unsigned i = 0, e = CSI.size(); i != e; ++i) { + unsigned Reg = CSI[i].getReg(); + int FI = CSI[i].getFrameIdx(); + switch (Reg) { + case ARM::R4: + case ARM::R5: + case ARM::R6: + case ARM::R7: + case ARM::LR: + if (Reg == FramePtr) + FramePtrSpillFI = FI; + AFI->addGPRCalleeSavedArea1Frame(FI); + GPRCS1Size += 4; + break; + case ARM::R8: + case ARM::R9: + case ARM::R10: + case ARM::R11: + if (Reg == FramePtr) + FramePtrSpillFI = FI; + if (STI.isTargetDarwin()) { + AFI->addGPRCalleeSavedArea2Frame(FI); + GPRCS2Size += 4; + } else { + AFI->addGPRCalleeSavedArea1Frame(FI); + GPRCS1Size += 4; + } + break; + default: + AFI->addDPRCalleeSavedAreaFrame(FI); + DPRCSSize += 8; + } + } + + if (MBBI != MBB.end() && MBBI->getOpcode() == ARM::tPUSH) { + ++MBBI; + if (MBBI != MBB.end()) + dl = MBBI->getDebugLoc(); + } + + // Darwin ABI requires FP to point to the stack slot that contains the + // previous FP. + if (STI.isTargetDarwin() || hasFP(MF)) { + BuildMI(MBB, MBBI, dl, TII.get(ARM::tADDrSPi), FramePtr) + .addFrameIndex(FramePtrSpillFI).addImm(0); + } + + // Determine starting offsets of spill areas. + unsigned DPRCSOffset = NumBytes - (GPRCS1Size + GPRCS2Size + DPRCSSize); + unsigned GPRCS2Offset = DPRCSOffset + DPRCSSize; + unsigned GPRCS1Offset = GPRCS2Offset + GPRCS2Size; + AFI->setFramePtrSpillOffset(MFI->getObjectOffset(FramePtrSpillFI) + NumBytes); + AFI->setGPRCalleeSavedArea1Offset(GPRCS1Offset); + AFI->setGPRCalleeSavedArea2Offset(GPRCS2Offset); + AFI->setDPRCalleeSavedAreaOffset(DPRCSOffset); + + NumBytes = DPRCSOffset; + if (NumBytes) { + // Insert it after all the callee-save spills. + emitSPUpdate(MBB, MBBI, TII, dl, *this, -NumBytes); + } + + if (STI.isTargetELF() && hasFP(MF)) { + MFI->setOffsetAdjustment(MFI->getOffsetAdjustment() - + AFI->getFramePtrSpillOffset()); + } + + AFI->setGPRCalleeSavedArea1Size(GPRCS1Size); + AFI->setGPRCalleeSavedArea2Size(GPRCS2Size); + AFI->setDPRCalleeSavedAreaSize(DPRCSSize); +} + +static bool isCalleeSavedRegister(unsigned Reg, const unsigned *CSRegs) { + for (unsigned i = 0; CSRegs[i]; ++i) + if (Reg == CSRegs[i]) + return true; + return false; +} + +static bool isCSRestore(MachineInstr *MI, const unsigned *CSRegs) { + return (MI->getOpcode() == ARM::tRestore && + MI->getOperand(1).isFI() && + isCalleeSavedRegister(MI->getOperand(0).getReg(), CSRegs)); +} + +void Thumb1RegisterInfo::emitEpilogue(MachineFunction &MF, + MachineBasicBlock &MBB) const { + MachineBasicBlock::iterator MBBI = prior(MBB.end()); + assert((MBBI->getOpcode() == ARM::tBX_RET || + MBBI->getOpcode() == ARM::tPOP_RET) && + "Can only insert epilog into returning blocks"); + DebugLoc dl = MBBI->getDebugLoc(); + MachineFrameInfo *MFI = MF.getFrameInfo(); + ARMFunctionInfo *AFI = MF.getInfo(); + unsigned VARegSaveSize = AFI->getVarArgsRegSaveSize(); + int NumBytes = (int)MFI->getStackSize(); + + if (!AFI->hasStackFrame()) { + if (NumBytes != 0) + emitSPUpdate(MBB, MBBI, TII, dl, *this, NumBytes); + } else { + // Unwind MBBI to point to first LDR / VLDRD. + const unsigned *CSRegs = getCalleeSavedRegs(); + if (MBBI != MBB.begin()) { + do + --MBBI; + while (MBBI != MBB.begin() && isCSRestore(MBBI, CSRegs)); + if (!isCSRestore(MBBI, CSRegs)) + ++MBBI; + } + + // Move SP to start of FP callee save spill area. + NumBytes -= (AFI->getGPRCalleeSavedArea1Size() + + AFI->getGPRCalleeSavedArea2Size() + + AFI->getDPRCalleeSavedAreaSize()); + + if (hasFP(MF)) { + NumBytes = AFI->getFramePtrSpillOffset() - NumBytes; + // Reset SP based on frame pointer only if the stack frame extends beyond + // frame pointer stack slot or target is ELF and the function has FP. + if (NumBytes) + emitThumbRegPlusImmediate(MBB, MBBI, ARM::SP, FramePtr, -NumBytes, + TII, *this, dl); + else + BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVtgpr2gpr), ARM::SP) + .addReg(FramePtr); + } else { + if (MBBI->getOpcode() == ARM::tBX_RET && + &MBB.front() != MBBI && + prior(MBBI)->getOpcode() == ARM::tPOP) { + MachineBasicBlock::iterator PMBBI = prior(MBBI); + emitSPUpdate(MBB, PMBBI, TII, dl, *this, NumBytes); + } else + emitSPUpdate(MBB, MBBI, TII, dl, *this, NumBytes); + } + } + + if (VARegSaveSize) { + // Epilogue for vararg functions: pop LR to R3 and branch off it. + AddDefaultPred(BuildMI(MBB, MBBI, dl, TII.get(ARM::tPOP))) + .addReg(0) // No write back. + .addReg(ARM::R3, RegState::Define); + + emitSPUpdate(MBB, MBBI, TII, dl, *this, VARegSaveSize); + + BuildMI(MBB, MBBI, dl, TII.get(ARM::tBX_RET_vararg)) + .addReg(ARM::R3, RegState::Kill); + MBB.erase(MBBI); + } +} diff --git a/libclamav/c++/llvm/lib/Target/ARM/Thumb1RegisterInfo.h b/libclamav/c++/llvm/lib/Target/ARM/Thumb1RegisterInfo.h new file mode 100644 index 000000000..37ad3881b --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/ARM/Thumb1RegisterInfo.h @@ -0,0 +1,70 @@ +//===- Thumb1RegisterInfo.h - Thumb-1 Register Information Impl -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the Thumb-1 implementation of the TargetRegisterInfo +// class. +// +//===----------------------------------------------------------------------===// + +#ifndef THUMB1REGISTERINFO_H +#define THUMB1REGISTERINFO_H + +#include "ARM.h" +#include "ARMRegisterInfo.h" +#include "llvm/Target/TargetRegisterInfo.h" + +namespace llvm { + class ARMSubtarget; + class ARMBaseInstrInfo; + class Type; + +struct Thumb1RegisterInfo : public ARMBaseRegisterInfo { +public: + Thumb1RegisterInfo(const ARMBaseInstrInfo &tii, const ARMSubtarget &STI); + + /// emitLoadConstPool - Emits a load from constpool to materialize the + /// specified immediate. + void emitLoadConstPool(MachineBasicBlock &MBB, + MachineBasicBlock::iterator &MBBI, + DebugLoc dl, + unsigned DestReg, unsigned SubIdx, int Val, + ARMCC::CondCodes Pred = ARMCC::AL, + unsigned PredReg = 0) const; + + /// Code Generation virtual methods... + const TargetRegisterClass * + getPhysicalRegisterRegClass(unsigned Reg, EVT VT = MVT::Other) const; + + bool hasReservedCallFrame(MachineFunction &MF) const; + + void eliminateCallFramePseudoInstr(MachineFunction &MF, + MachineBasicBlock &MBB, + MachineBasicBlock::iterator I) const; + + // rewrite MI to access 'Offset' bytes from the FP. Return the offset that + // could not be handled directly in MI. + int rewriteFrameIndex(MachineInstr &MI, unsigned FrameRegIdx, + unsigned FrameReg, int Offset, + unsigned MOVOpc, unsigned ADDriOpc, unsigned SUBriOpc) const; + + bool saveScavengerRegister(MachineBasicBlock &MBB, + MachineBasicBlock::iterator I, + MachineBasicBlock::iterator &UseMI, + const TargetRegisterClass *RC, + unsigned Reg) const; + unsigned eliminateFrameIndex(MachineBasicBlock::iterator II, + int SPAdj, int *Value = NULL, + RegScavenger *RS = NULL) const; + + void emitPrologue(MachineFunction &MF) const; + void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const; +}; +} + +#endif // THUMB1REGISTERINFO_H diff --git a/libclamav/c++/llvm/lib/Target/ARM/Thumb2ITBlockPass.cpp b/libclamav/c++/llvm/lib/Target/ARM/Thumb2ITBlockPass.cpp new file mode 100644 index 000000000..f5ba155f4 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/ARM/Thumb2ITBlockPass.cpp @@ -0,0 +1,119 @@ +//===-- Thumb2ITBlockPass.cpp - Insert Thumb IT blocks ----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "thumb2-it" +#include "ARM.h" +#include "ARMMachineFunctionInfo.h" +#include "Thumb2InstrInfo.h" +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/ADT/Statistic.h" +using namespace llvm; + +STATISTIC(NumITs, "Number of IT blocks inserted"); + +namespace { + struct Thumb2ITBlockPass : public MachineFunctionPass { + static char ID; + Thumb2ITBlockPass() : MachineFunctionPass(&ID) {} + + const Thumb2InstrInfo *TII; + ARMFunctionInfo *AFI; + + virtual bool runOnMachineFunction(MachineFunction &Fn); + + virtual const char *getPassName() const { + return "Thumb IT blocks insertion pass"; + } + + private: + bool InsertITBlocks(MachineBasicBlock &MBB); + }; + char Thumb2ITBlockPass::ID = 0; +} + +static ARMCC::CondCodes getPredicate(const MachineInstr *MI, unsigned &PredReg){ + unsigned Opc = MI->getOpcode(); + if (Opc == ARM::tBcc || Opc == ARM::t2Bcc) + return ARMCC::AL; + return llvm::getInstrPredicate(MI, PredReg); +} + +bool Thumb2ITBlockPass::InsertITBlocks(MachineBasicBlock &MBB) { + bool Modified = false; + + MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end(); + while (MBBI != E) { + MachineInstr *MI = &*MBBI; + DebugLoc dl = MI->getDebugLoc(); + unsigned PredReg = 0; + ARMCC::CondCodes CC = getPredicate(MI, PredReg); + + if (CC == ARMCC::AL) { + ++MBBI; + continue; + } + + // Insert an IT instruction. + MachineInstrBuilder MIB = BuildMI(MBB, MBBI, dl, TII->get(ARM::t2IT)) + .addImm(CC); + ++MBBI; + + // Finalize IT mask. + ARMCC::CondCodes OCC = ARMCC::getOppositeCondition(CC); + unsigned Mask = 0, Pos = 3; + // Branches, including tricky ones like LDM_RET, need to end an IT + // block so check the instruction we just put in the block. + while (MBBI != E && Pos && + (!MI->getDesc().isBranch() && !MI->getDesc().isReturn())) { + MachineInstr *NMI = &*MBBI; + MI = NMI; + DebugLoc ndl = NMI->getDebugLoc(); + unsigned NPredReg = 0; + ARMCC::CondCodes NCC = getPredicate(NMI, NPredReg); + if (NCC == OCC) { + Mask |= (1 << Pos); + } else if (NCC != CC) + break; + --Pos; + ++MBBI; + } + Mask |= (1 << Pos); + MIB.addImm(Mask); + Modified = true; + ++NumITs; + } + + return Modified; +} + +bool Thumb2ITBlockPass::runOnMachineFunction(MachineFunction &Fn) { + const TargetMachine &TM = Fn.getTarget(); + AFI = Fn.getInfo(); + TII = static_cast(TM.getInstrInfo()); + + if (!AFI->isThumbFunction()) + return false; + + bool Modified = false; + for (MachineFunction::iterator MFI = Fn.begin(), E = Fn.end(); MFI != E; + ++MFI) { + MachineBasicBlock &MBB = *MFI; + Modified |= InsertITBlocks(MBB); + } + + return Modified; +} + +/// createThumb2ITBlockPass - Returns an instance of the Thumb2 IT blocks +/// insertion pass. +FunctionPass *llvm::createThumb2ITBlockPass() { + return new Thumb2ITBlockPass(); +} diff --git a/libclamav/c++/llvm/lib/Target/ARM/Thumb2InstrInfo.cpp b/libclamav/c++/llvm/lib/Target/ARM/Thumb2InstrInfo.cpp new file mode 100644 index 000000000..16c1e6f5b --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/ARM/Thumb2InstrInfo.cpp @@ -0,0 +1,503 @@ +//===- Thumb2InstrInfo.cpp - Thumb-2 Instruction Information ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the Thumb-2 implementation of the TargetInstrInfo class. +// +//===----------------------------------------------------------------------===// + +#include "Thumb2InstrInfo.h" +#include "ARM.h" +#include "ARMConstantPoolValue.h" +#include "ARMAddressingModes.h" +#include "ARMGenInstrInfo.inc" +#include "ARMMachineFunctionInfo.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineMemOperand.h" +#include "llvm/CodeGen/PseudoSourceValue.h" +#include "llvm/ADT/SmallVector.h" +#include "Thumb2InstrInfo.h" + +using namespace llvm; + +Thumb2InstrInfo::Thumb2InstrInfo(const ARMSubtarget &STI) + : ARMBaseInstrInfo(STI), RI(*this, STI) { +} + +unsigned Thumb2InstrInfo::getUnindexedOpcode(unsigned Opc) const { + // FIXME + return 0; +} + +bool +Thumb2InstrInfo::BlockHasNoFallThrough(const MachineBasicBlock &MBB) const { + if (MBB.empty()) return false; + + switch (MBB.back().getOpcode()) { + case ARM::t2LDM_RET: + case ARM::t2B: // Uncond branch. + case ARM::t2BR_JT: // Jumptable branch. + case ARM::t2TBB: // Table branch byte. + case ARM::t2TBH: // Table branch halfword. + case ARM::tBR_JTr: // Jumptable branch (16-bit version). + case ARM::tBX_RET: + case ARM::tBX_RET_vararg: + case ARM::tPOP_RET: + case ARM::tB: + case ARM::tBRIND: + return true; + default: + break; + } + + return false; +} + +bool +Thumb2InstrInfo::copyRegToReg(MachineBasicBlock &MBB, + MachineBasicBlock::iterator I, + unsigned DestReg, unsigned SrcReg, + const TargetRegisterClass *DestRC, + const TargetRegisterClass *SrcRC) const { + DebugLoc DL = DebugLoc::getUnknownLoc(); + if (I != MBB.end()) DL = I->getDebugLoc(); + + if (DestRC == ARM::GPRRegisterClass && + SrcRC == ARM::GPRRegisterClass) { + BuildMI(MBB, I, DL, get(ARM::tMOVgpr2gpr), DestReg).addReg(SrcReg); + return true; + } else if (DestRC == ARM::GPRRegisterClass && + SrcRC == ARM::tGPRRegisterClass) { + BuildMI(MBB, I, DL, get(ARM::tMOVtgpr2gpr), DestReg).addReg(SrcReg); + return true; + } else if (DestRC == ARM::tGPRRegisterClass && + SrcRC == ARM::GPRRegisterClass) { + BuildMI(MBB, I, DL, get(ARM::tMOVgpr2tgpr), DestReg).addReg(SrcReg); + return true; + } + + // Handle SPR, DPR, and QPR copies. + return ARMBaseInstrInfo::copyRegToReg(MBB, I, DestReg, SrcReg, DestRC, SrcRC); +} + +void Thumb2InstrInfo:: +storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, + unsigned SrcReg, bool isKill, int FI, + const TargetRegisterClass *RC) const { + DebugLoc DL = DebugLoc::getUnknownLoc(); + if (I != MBB.end()) DL = I->getDebugLoc(); + + if (RC == ARM::GPRRegisterClass) { + MachineFunction &MF = *MBB.getParent(); + MachineFrameInfo &MFI = *MF.getFrameInfo(); + MachineMemOperand *MMO = + MF.getMachineMemOperand(PseudoSourceValue::getFixedStack(FI), + MachineMemOperand::MOStore, 0, + MFI.getObjectSize(FI), + MFI.getObjectAlignment(FI)); + AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::t2STRi12)) + .addReg(SrcReg, getKillRegState(isKill)) + .addFrameIndex(FI).addImm(0).addMemOperand(MMO)); + return; + } + + ARMBaseInstrInfo::storeRegToStackSlot(MBB, I, SrcReg, isKill, FI, RC); +} + +void Thumb2InstrInfo:: +loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, + unsigned DestReg, int FI, + const TargetRegisterClass *RC) const { + DebugLoc DL = DebugLoc::getUnknownLoc(); + if (I != MBB.end()) DL = I->getDebugLoc(); + + if (RC == ARM::GPRRegisterClass) { + MachineFunction &MF = *MBB.getParent(); + MachineFrameInfo &MFI = *MF.getFrameInfo(); + MachineMemOperand *MMO = + MF.getMachineMemOperand(PseudoSourceValue::getFixedStack(FI), + MachineMemOperand::MOLoad, 0, + MFI.getObjectSize(FI), + MFI.getObjectAlignment(FI)); + AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::t2LDRi12), DestReg) + .addFrameIndex(FI).addImm(0).addMemOperand(MMO)); + return; + } + + ARMBaseInstrInfo::loadRegFromStackSlot(MBB, I, DestReg, FI, RC); +} + +void llvm::emitT2RegPlusImmediate(MachineBasicBlock &MBB, + MachineBasicBlock::iterator &MBBI, DebugLoc dl, + unsigned DestReg, unsigned BaseReg, int NumBytes, + ARMCC::CondCodes Pred, unsigned PredReg, + const ARMBaseInstrInfo &TII) { + bool isSub = NumBytes < 0; + if (isSub) NumBytes = -NumBytes; + + // If profitable, use a movw or movt to materialize the offset. + // FIXME: Use the scavenger to grab a scratch register. + if (DestReg != ARM::SP && DestReg != BaseReg && + NumBytes >= 4096 && + ARM_AM::getT2SOImmVal(NumBytes) == -1) { + bool Fits = false; + if (NumBytes < 65536) { + // Use a movw to materialize the 16-bit constant. + BuildMI(MBB, MBBI, dl, TII.get(ARM::t2MOVi16), DestReg) + .addImm(NumBytes) + .addImm((unsigned)Pred).addReg(PredReg).addReg(0); + Fits = true; + } else if ((NumBytes & 0xffff) == 0) { + // Use a movt to materialize the 32-bit constant. + BuildMI(MBB, MBBI, dl, TII.get(ARM::t2MOVTi16), DestReg) + .addReg(DestReg) + .addImm(NumBytes >> 16) + .addImm((unsigned)Pred).addReg(PredReg).addReg(0); + Fits = true; + } + + if (Fits) { + if (isSub) { + BuildMI(MBB, MBBI, dl, TII.get(ARM::t2SUBrr), DestReg) + .addReg(BaseReg, RegState::Kill) + .addReg(DestReg, RegState::Kill) + .addImm((unsigned)Pred).addReg(PredReg).addReg(0); + } else { + BuildMI(MBB, MBBI, dl, TII.get(ARM::t2ADDrr), DestReg) + .addReg(DestReg, RegState::Kill) + .addReg(BaseReg, RegState::Kill) + .addImm((unsigned)Pred).addReg(PredReg).addReg(0); + } + return; + } + } + + while (NumBytes) { + unsigned ThisVal = NumBytes; + unsigned Opc = 0; + if (DestReg == ARM::SP && BaseReg != ARM::SP) { + // mov sp, rn. Note t2MOVr cannot be used. + BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVgpr2gpr),DestReg).addReg(BaseReg); + BaseReg = ARM::SP; + continue; + } + + if (BaseReg == ARM::SP) { + // sub sp, sp, #imm7 + if (DestReg == ARM::SP && (ThisVal < ((1 << 7)-1) * 4)) { + assert((ThisVal & 3) == 0 && "Stack update is not multiple of 4?"); + Opc = isSub ? ARM::tSUBspi : ARM::tADDspi; + // FIXME: Fix Thumb1 immediate encoding. + BuildMI(MBB, MBBI, dl, TII.get(Opc), DestReg) + .addReg(BaseReg).addImm(ThisVal/4); + NumBytes = 0; + continue; + } + + // sub rd, sp, so_imm + Opc = isSub ? ARM::t2SUBrSPi : ARM::t2ADDrSPi; + if (ARM_AM::getT2SOImmVal(NumBytes) != -1) { + NumBytes = 0; + } else { + // FIXME: Move this to ARMAddressingModes.h? + unsigned RotAmt = CountLeadingZeros_32(ThisVal); + ThisVal = ThisVal & ARM_AM::rotr32(0xff000000U, RotAmt); + NumBytes &= ~ThisVal; + assert(ARM_AM::getT2SOImmVal(ThisVal) != -1 && + "Bit extraction didn't work?"); + } + } else { + assert(DestReg != ARM::SP && BaseReg != ARM::SP); + Opc = isSub ? ARM::t2SUBri : ARM::t2ADDri; + if (ARM_AM::getT2SOImmVal(NumBytes) != -1) { + NumBytes = 0; + } else if (ThisVal < 4096) { + Opc = isSub ? ARM::t2SUBri12 : ARM::t2ADDri12; + NumBytes = 0; + } else { + // FIXME: Move this to ARMAddressingModes.h? + unsigned RotAmt = CountLeadingZeros_32(ThisVal); + ThisVal = ThisVal & ARM_AM::rotr32(0xff000000U, RotAmt); + NumBytes &= ~ThisVal; + assert(ARM_AM::getT2SOImmVal(ThisVal) != -1 && + "Bit extraction didn't work?"); + } + } + + // Build the new ADD / SUB. + AddDefaultCC(AddDefaultPred(BuildMI(MBB, MBBI, dl, TII.get(Opc), DestReg) + .addReg(BaseReg, RegState::Kill) + .addImm(ThisVal))); + + BaseReg = DestReg; + } +} + +static unsigned +negativeOffsetOpcode(unsigned opcode) +{ + switch (opcode) { + case ARM::t2LDRi12: return ARM::t2LDRi8; + case ARM::t2LDRHi12: return ARM::t2LDRHi8; + case ARM::t2LDRBi12: return ARM::t2LDRBi8; + case ARM::t2LDRSHi12: return ARM::t2LDRSHi8; + case ARM::t2LDRSBi12: return ARM::t2LDRSBi8; + case ARM::t2STRi12: return ARM::t2STRi8; + case ARM::t2STRBi12: return ARM::t2STRBi8; + case ARM::t2STRHi12: return ARM::t2STRHi8; + + case ARM::t2LDRi8: + case ARM::t2LDRHi8: + case ARM::t2LDRBi8: + case ARM::t2LDRSHi8: + case ARM::t2LDRSBi8: + case ARM::t2STRi8: + case ARM::t2STRBi8: + case ARM::t2STRHi8: + return opcode; + + default: + break; + } + + return 0; +} + +static unsigned +positiveOffsetOpcode(unsigned opcode) +{ + switch (opcode) { + case ARM::t2LDRi8: return ARM::t2LDRi12; + case ARM::t2LDRHi8: return ARM::t2LDRHi12; + case ARM::t2LDRBi8: return ARM::t2LDRBi12; + case ARM::t2LDRSHi8: return ARM::t2LDRSHi12; + case ARM::t2LDRSBi8: return ARM::t2LDRSBi12; + case ARM::t2STRi8: return ARM::t2STRi12; + case ARM::t2STRBi8: return ARM::t2STRBi12; + case ARM::t2STRHi8: return ARM::t2STRHi12; + + case ARM::t2LDRi12: + case ARM::t2LDRHi12: + case ARM::t2LDRBi12: + case ARM::t2LDRSHi12: + case ARM::t2LDRSBi12: + case ARM::t2STRi12: + case ARM::t2STRBi12: + case ARM::t2STRHi12: + return opcode; + + default: + break; + } + + return 0; +} + +static unsigned +immediateOffsetOpcode(unsigned opcode) +{ + switch (opcode) { + case ARM::t2LDRs: return ARM::t2LDRi12; + case ARM::t2LDRHs: return ARM::t2LDRHi12; + case ARM::t2LDRBs: return ARM::t2LDRBi12; + case ARM::t2LDRSHs: return ARM::t2LDRSHi12; + case ARM::t2LDRSBs: return ARM::t2LDRSBi12; + case ARM::t2STRs: return ARM::t2STRi12; + case ARM::t2STRBs: return ARM::t2STRBi12; + case ARM::t2STRHs: return ARM::t2STRHi12; + + case ARM::t2LDRi12: + case ARM::t2LDRHi12: + case ARM::t2LDRBi12: + case ARM::t2LDRSHi12: + case ARM::t2LDRSBi12: + case ARM::t2STRi12: + case ARM::t2STRBi12: + case ARM::t2STRHi12: + case ARM::t2LDRi8: + case ARM::t2LDRHi8: + case ARM::t2LDRBi8: + case ARM::t2LDRSHi8: + case ARM::t2LDRSBi8: + case ARM::t2STRi8: + case ARM::t2STRBi8: + case ARM::t2STRHi8: + return opcode; + + default: + break; + } + + return 0; +} + +bool llvm::rewriteT2FrameIndex(MachineInstr &MI, unsigned FrameRegIdx, + unsigned FrameReg, int &Offset, + const ARMBaseInstrInfo &TII) { + unsigned Opcode = MI.getOpcode(); + const TargetInstrDesc &Desc = MI.getDesc(); + unsigned AddrMode = (Desc.TSFlags & ARMII::AddrModeMask); + bool isSub = false; + + // Memory operands in inline assembly always use AddrModeT2_i12. + if (Opcode == ARM::INLINEASM) + AddrMode = ARMII::AddrModeT2_i12; // FIXME. mode for thumb2? + + if (Opcode == ARM::t2ADDri || Opcode == ARM::t2ADDri12) { + Offset += MI.getOperand(FrameRegIdx+1).getImm(); + + bool isSP = FrameReg == ARM::SP; + if (Offset == 0) { + // Turn it into a move. + MI.setDesc(TII.get(ARM::tMOVgpr2gpr)); + MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false); + MI.RemoveOperand(FrameRegIdx+1); + Offset = 0; + return true; + } + + if (Offset < 0) { + Offset = -Offset; + isSub = true; + MI.setDesc(TII.get(isSP ? ARM::t2SUBrSPi : ARM::t2SUBri)); + } else { + MI.setDesc(TII.get(isSP ? ARM::t2ADDrSPi : ARM::t2ADDri)); + } + + // Common case: small offset, fits into instruction. + if (ARM_AM::getT2SOImmVal(Offset) != -1) { + MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false); + MI.getOperand(FrameRegIdx+1).ChangeToImmediate(Offset); + Offset = 0; + return true; + } + // Another common case: imm12. + if (Offset < 4096) { + unsigned NewOpc = isSP + ? (isSub ? ARM::t2SUBrSPi12 : ARM::t2ADDrSPi12) + : (isSub ? ARM::t2SUBri12 : ARM::t2ADDri12); + MI.setDesc(TII.get(NewOpc)); + MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false); + MI.getOperand(FrameRegIdx+1).ChangeToImmediate(Offset); + Offset = 0; + return true; + } + + // Otherwise, extract 8 adjacent bits from the immediate into this + // t2ADDri/t2SUBri. + unsigned RotAmt = CountLeadingZeros_32(Offset); + unsigned ThisImmVal = Offset & ARM_AM::rotr32(0xff000000U, RotAmt); + + // We will handle these bits from offset, clear them. + Offset &= ~ThisImmVal; + + assert(ARM_AM::getT2SOImmVal(ThisImmVal) != -1 && + "Bit extraction didn't work?"); + MI.getOperand(FrameRegIdx+1).ChangeToImmediate(ThisImmVal); + } else { + + // AddrMode4 cannot handle any offset. + if (AddrMode == ARMII::AddrMode4) + return false; + + // AddrModeT2_so cannot handle any offset. If there is no offset + // register then we change to an immediate version. + unsigned NewOpc = Opcode; + if (AddrMode == ARMII::AddrModeT2_so) { + unsigned OffsetReg = MI.getOperand(FrameRegIdx+1).getReg(); + if (OffsetReg != 0) { + MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false); + return Offset == 0; + } + + MI.RemoveOperand(FrameRegIdx+1); + MI.getOperand(FrameRegIdx+1).ChangeToImmediate(0); + NewOpc = immediateOffsetOpcode(Opcode); + AddrMode = ARMII::AddrModeT2_i12; + } + + unsigned NumBits = 0; + unsigned Scale = 1; + if (AddrMode == ARMII::AddrModeT2_i8 || AddrMode == ARMII::AddrModeT2_i12) { + // i8 supports only negative, and i12 supports only positive, so + // based on Offset sign convert Opcode to the appropriate + // instruction + Offset += MI.getOperand(FrameRegIdx+1).getImm(); + if (Offset < 0) { + NewOpc = negativeOffsetOpcode(Opcode); + NumBits = 8; + isSub = true; + Offset = -Offset; + } else { + NewOpc = positiveOffsetOpcode(Opcode); + NumBits = 12; + } + } else { + // VFP and NEON address modes. + int InstrOffs = 0; + if (AddrMode == ARMII::AddrMode5) { + const MachineOperand &OffOp = MI.getOperand(FrameRegIdx+1); + InstrOffs = ARM_AM::getAM5Offset(OffOp.getImm()); + if (ARM_AM::getAM5Op(OffOp.getImm()) == ARM_AM::sub) + InstrOffs *= -1; + } + NumBits = 8; + Scale = 4; + Offset += InstrOffs * 4; + assert((Offset & (Scale-1)) == 0 && "Can't encode this offset!"); + if (Offset < 0) { + Offset = -Offset; + isSub = true; + } + } + + if (NewOpc != Opcode) + MI.setDesc(TII.get(NewOpc)); + + MachineOperand &ImmOp = MI.getOperand(FrameRegIdx+1); + + // Attempt to fold address computation + // Common case: small offset, fits into instruction. + int ImmedOffset = Offset / Scale; + unsigned Mask = (1 << NumBits) - 1; + if ((unsigned)Offset <= Mask * Scale) { + // Replace the FrameIndex with fp/sp + MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false); + if (isSub) { + if (AddrMode == ARMII::AddrMode5) + // FIXME: Not consistent. + ImmedOffset |= 1 << NumBits; + else + ImmedOffset = -ImmedOffset; + } + ImmOp.ChangeToImmediate(ImmedOffset); + Offset = 0; + return true; + } + + // Otherwise, offset doesn't fit. Pull in what we can to simplify + ImmedOffset = ImmedOffset & Mask; + if (isSub) { + if (AddrMode == ARMII::AddrMode5) + // FIXME: Not consistent. + ImmedOffset |= 1 << NumBits; + else { + ImmedOffset = -ImmedOffset; + if (ImmedOffset == 0) + // Change the opcode back if the encoded offset is zero. + MI.setDesc(TII.get(positiveOffsetOpcode(NewOpc))); + } + } + ImmOp.ChangeToImmediate(ImmedOffset); + Offset &= ~(Mask*Scale); + } + + Offset = (isSub) ? -Offset : Offset; + return Offset == 0; +} diff --git a/libclamav/c++/llvm/lib/Target/ARM/Thumb2InstrInfo.h b/libclamav/c++/llvm/lib/Target/ARM/Thumb2InstrInfo.h new file mode 100644 index 000000000..663a60b8c --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/ARM/Thumb2InstrInfo.h @@ -0,0 +1,61 @@ +//===- Thumb2InstrInfo.h - Thumb-2 Instruction Information ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the Thumb-2 implementation of the TargetInstrInfo class. +// +//===----------------------------------------------------------------------===// + +#ifndef THUMB2INSTRUCTIONINFO_H +#define THUMB2INSTRUCTIONINFO_H + +#include "llvm/Target/TargetInstrInfo.h" +#include "ARM.h" +#include "ARMInstrInfo.h" +#include "Thumb2RegisterInfo.h" + +namespace llvm { + class ARMSubtarget; + +class Thumb2InstrInfo : public ARMBaseInstrInfo { + Thumb2RegisterInfo RI; +public: + explicit Thumb2InstrInfo(const ARMSubtarget &STI); + + // Return the non-pre/post incrementing version of 'Opc'. Return 0 + // if there is not such an opcode. + unsigned getUnindexedOpcode(unsigned Opc) const; + + // Return true if the block does not fall through. + bool BlockHasNoFallThrough(const MachineBasicBlock &MBB) const; + + bool copyRegToReg(MachineBasicBlock &MBB, + MachineBasicBlock::iterator I, + unsigned DestReg, unsigned SrcReg, + const TargetRegisterClass *DestRC, + const TargetRegisterClass *SrcRC) const; + + void storeRegToStackSlot(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MBBI, + unsigned SrcReg, bool isKill, int FrameIndex, + const TargetRegisterClass *RC) const; + + void loadRegFromStackSlot(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MBBI, + unsigned DestReg, int FrameIndex, + const TargetRegisterClass *RC) const; + + /// getRegisterInfo - TargetInstrInfo is a superset of MRegister info. As + /// such, whenever a client has an instance of instruction info, it should + /// always be able to get register info as well (through this method). + /// + const Thumb2RegisterInfo &getRegisterInfo() const { return RI; } +}; +} + +#endif // THUMB2INSTRUCTIONINFO_H diff --git a/libclamav/c++/llvm/lib/Target/ARM/Thumb2RegisterInfo.cpp b/libclamav/c++/llvm/lib/Target/ARM/Thumb2RegisterInfo.cpp new file mode 100644 index 000000000..f24d3e256 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/ARM/Thumb2RegisterInfo.cpp @@ -0,0 +1,62 @@ +//===- Thumb2RegisterInfo.cpp - Thumb-2 Register Information ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the Thumb-2 implementation of the TargetRegisterInfo +// class. +// +//===----------------------------------------------------------------------===// + +#include "ARM.h" +#include "ARMAddressingModes.h" +#include "ARMBaseInstrInfo.h" +#include "ARMMachineFunctionInfo.h" +#include "ARMSubtarget.h" +#include "Thumb2InstrInfo.h" +#include "Thumb2RegisterInfo.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Function.h" +#include "llvm/LLVMContext.h" +#include "llvm/CodeGen/MachineConstantPool.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineLocation.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/Target/TargetFrameInfo.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/ADT/BitVector.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/ErrorHandling.h" +using namespace llvm; + +Thumb2RegisterInfo::Thumb2RegisterInfo(const ARMBaseInstrInfo &tii, + const ARMSubtarget &sti) + : ARMBaseRegisterInfo(tii, sti) { +} + +/// emitLoadConstPool - Emits a load from constpool to materialize the +/// specified immediate. +void Thumb2RegisterInfo::emitLoadConstPool(MachineBasicBlock &MBB, + MachineBasicBlock::iterator &MBBI, + DebugLoc dl, + unsigned DestReg, unsigned SubIdx, + int Val, + ARMCC::CondCodes Pred, + unsigned PredReg) const { + MachineFunction &MF = *MBB.getParent(); + MachineConstantPool *ConstantPool = MF.getConstantPool(); + Constant *C = ConstantInt::get( + Type::getInt32Ty(MBB.getParent()->getFunction()->getContext()), Val); + unsigned Idx = ConstantPool->getConstantPoolIndex(C, 4); + + BuildMI(MBB, MBBI, dl, TII.get(ARM::t2LDRpci)) + .addReg(DestReg, getDefRegState(true), SubIdx) + .addConstantPoolIndex(Idx).addImm((int64_t)ARMCC::AL).addReg(0); +} diff --git a/libclamav/c++/llvm/lib/Target/ARM/Thumb2RegisterInfo.h b/libclamav/c++/llvm/lib/Target/ARM/Thumb2RegisterInfo.h new file mode 100644 index 000000000..b3cf2e5b0 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/ARM/Thumb2RegisterInfo.h @@ -0,0 +1,42 @@ +//===- Thumb2RegisterInfo.h - Thumb-2 Register Information Impl -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the Thumb-2 implementation of the TargetRegisterInfo +// class. +// +//===----------------------------------------------------------------------===// + +#ifndef THUMB2REGISTERINFO_H +#define THUMB2REGISTERINFO_H + +#include "ARM.h" +#include "ARMRegisterInfo.h" +#include "llvm/Target/TargetRegisterInfo.h" + +namespace llvm { + class ARMSubtarget; + class ARMBaseInstrInfo; + class Type; + +struct Thumb2RegisterInfo : public ARMBaseRegisterInfo { +public: + Thumb2RegisterInfo(const ARMBaseInstrInfo &tii, const ARMSubtarget &STI); + + /// emitLoadConstPool - Emits a load from constpool to materialize the + /// specified immediate. + void emitLoadConstPool(MachineBasicBlock &MBB, + MachineBasicBlock::iterator &MBBI, + DebugLoc dl, + unsigned DestReg, unsigned SubIdx, int Val, + ARMCC::CondCodes Pred = ARMCC::AL, + unsigned PredReg = 0) const; +}; +} + +#endif // THUMB2REGISTERINFO_H diff --git a/libclamav/c++/llvm/lib/Target/ARM/Thumb2SizeReduction.cpp b/libclamav/c++/llvm/lib/Target/ARM/Thumb2SizeReduction.cpp new file mode 100644 index 000000000..b2fd7b334 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/ARM/Thumb2SizeReduction.cpp @@ -0,0 +1,708 @@ +//===-- Thumb2SizeReduction.cpp - Thumb2 code size reduction pass -*- C++ -*-=// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "t2-reduce-size" +#include "ARM.h" +#include "ARMAddressingModes.h" +#include "ARMBaseRegisterInfo.h" +#include "ARMBaseInstrInfo.h" +#include "Thumb2InstrInfo.h" +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/Statistic.h" +using namespace llvm; + +STATISTIC(NumNarrows, "Number of 32-bit instrs reduced to 16-bit ones"); +STATISTIC(Num2Addrs, "Number of 32-bit instrs reduced to 2addr 16-bit ones"); +STATISTIC(NumLdSts, "Number of 32-bit load / store reduced to 16-bit ones"); + +static cl::opt ReduceLimit("t2-reduce-limit", + cl::init(-1), cl::Hidden); +static cl::opt ReduceLimit2Addr("t2-reduce-limit2", + cl::init(-1), cl::Hidden); +static cl::opt ReduceLimitLdSt("t2-reduce-limit3", + cl::init(-1), cl::Hidden); + +namespace { + /// ReduceTable - A static table with information on mapping from wide + /// opcodes to narrow + struct ReduceEntry { + unsigned WideOpc; // Wide opcode + unsigned NarrowOpc1; // Narrow opcode to transform to + unsigned NarrowOpc2; // Narrow opcode when it's two-address + uint8_t Imm1Limit; // Limit of immediate field (bits) + uint8_t Imm2Limit; // Limit of immediate field when it's two-address + unsigned LowRegs1 : 1; // Only possible if low-registers are used + unsigned LowRegs2 : 1; // Only possible if low-registers are used (2addr) + unsigned PredCC1 : 2; // 0 - If predicated, cc is on and vice versa. + // 1 - No cc field. + // 2 - Always set CPSR. + unsigned PredCC2 : 2; + unsigned Special : 1; // Needs to be dealt with specially + }; + + static const ReduceEntry ReduceTable[] = { + // Wide, Narrow1, Narrow2, imm1,imm2, lo1, lo2, P/C, S + { ARM::t2ADCrr, 0, ARM::tADC, 0, 0, 0, 1, 0,0, 0 }, + { ARM::t2ADDri, ARM::tADDi3, ARM::tADDi8, 3, 8, 1, 1, 0,0, 0 }, + { ARM::t2ADDrr, ARM::tADDrr, ARM::tADDhirr, 0, 0, 1, 0, 0,1, 0 }, + // Note: immediate scale is 4. + { ARM::t2ADDrSPi,ARM::tADDrSPi,0, 8, 0, 1, 0, 1,0, 0 }, + { ARM::t2ADDSri,ARM::tADDi3, ARM::tADDi8, 3, 8, 1, 1, 2,2, 1 }, + { ARM::t2ADDSrr,ARM::tADDrr, 0, 0, 0, 1, 0, 2,0, 1 }, + { ARM::t2ANDrr, 0, ARM::tAND, 0, 0, 0, 1, 0,0, 0 }, + { ARM::t2ASRri, ARM::tASRri, 0, 5, 0, 1, 0, 0,0, 0 }, + { ARM::t2ASRrr, 0, ARM::tASRrr, 0, 0, 0, 1, 0,0, 0 }, + { ARM::t2BICrr, 0, ARM::tBIC, 0, 0, 0, 1, 0,0, 0 }, + { ARM::t2CMNrr, ARM::tCMN, 0, 0, 0, 1, 0, 2,0, 0 }, + { ARM::t2CMPri, ARM::tCMPi8, 0, 8, 0, 1, 0, 2,0, 0 }, + { ARM::t2CMPrr, ARM::tCMPhir, 0, 0, 0, 0, 0, 2,0, 0 }, + { ARM::t2CMPzri,ARM::tCMPzi8, 0, 8, 0, 1, 0, 2,0, 0 }, + { ARM::t2CMPzrr,ARM::tCMPzhir,0, 0, 0, 0, 0, 2,0, 0 }, + { ARM::t2EORrr, 0, ARM::tEOR, 0, 0, 0, 1, 0,0, 0 }, + // FIXME: adr.n immediate offset must be multiple of 4. + //{ ARM::t2LEApcrelJT,ARM::tLEApcrelJT, 0, 0, 0, 1, 0, 1,0, 0 }, + { ARM::t2LSLri, ARM::tLSLri, 0, 5, 0, 1, 0, 0,0, 0 }, + { ARM::t2LSLrr, 0, ARM::tLSLrr, 0, 0, 0, 1, 0,0, 0 }, + { ARM::t2LSRri, ARM::tLSRri, 0, 5, 0, 1, 0, 0,0, 0 }, + { ARM::t2LSRrr, 0, ARM::tLSRrr, 0, 0, 0, 1, 0,0, 0 }, + { ARM::t2MOVi, ARM::tMOVi8, 0, 8, 0, 1, 0, 0,0, 0 }, + { ARM::t2MOVi16,ARM::tMOVi8, 0, 8, 0, 1, 0, 0,0, 1 }, + // FIXME: Do we need the 16-bit 'S' variant? + { ARM::t2MOVr,ARM::tMOVgpr2gpr,0, 0, 0, 0, 0, 1,0, 0 }, + { ARM::t2MOVCCr,0, ARM::tMOVCCr, 0, 0, 0, 0, 0,1, 0 }, + { ARM::t2MOVCCi,0, ARM::tMOVCCi, 0, 8, 0, 0, 0,1, 0 }, + { ARM::t2MUL, 0, ARM::tMUL, 0, 0, 0, 1, 0,0, 0 }, + { ARM::t2MVNr, ARM::tMVN, 0, 0, 0, 1, 0, 0,0, 0 }, + { ARM::t2ORRrr, 0, ARM::tORR, 0, 0, 0, 1, 0,0, 0 }, + { ARM::t2REV, ARM::tREV, 0, 0, 0, 1, 0, 1,0, 0 }, + { ARM::t2REV16, ARM::tREV16, 0, 0, 0, 1, 0, 1,0, 0 }, + { ARM::t2REVSH, ARM::tREVSH, 0, 0, 0, 1, 0, 1,0, 0 }, + { ARM::t2RORrr, 0, ARM::tROR, 0, 0, 0, 1, 0,0, 0 }, + { ARM::t2RSBri, ARM::tRSB, 0, 0, 0, 1, 0, 0,0, 1 }, + { ARM::t2RSBSri,ARM::tRSB, 0, 0, 0, 1, 0, 2,0, 1 }, + { ARM::t2SBCrr, 0, ARM::tSBC, 0, 0, 0, 1, 0,0, 0 }, + { ARM::t2SUBri, ARM::tSUBi3, ARM::tSUBi8, 3, 8, 1, 1, 0,0, 0 }, + { ARM::t2SUBrr, ARM::tSUBrr, 0, 0, 0, 1, 0, 0,0, 0 }, + { ARM::t2SUBSri,ARM::tSUBi3, ARM::tSUBi8, 3, 8, 1, 1, 2,2, 0 }, + { ARM::t2SUBSrr,ARM::tSUBrr, 0, 0, 0, 1, 0, 2,0, 0 }, + { ARM::t2SXTBr, ARM::tSXTB, 0, 0, 0, 1, 0, 1,0, 0 }, + { ARM::t2SXTHr, ARM::tSXTH, 0, 0, 0, 1, 0, 1,0, 0 }, + { ARM::t2TSTrr, ARM::tTST, 0, 0, 0, 1, 0, 2,0, 0 }, + { ARM::t2UXTBr, ARM::tUXTB, 0, 0, 0, 1, 0, 1,0, 0 }, + { ARM::t2UXTHr, ARM::tUXTH, 0, 0, 0, 1, 0, 1,0, 0 }, + + // FIXME: Clean this up after splitting each Thumb load / store opcode + // into multiple ones. + { ARM::t2LDRi12,ARM::tLDR, ARM::tLDRspi, 5, 8, 1, 0, 0,0, 1 }, + { ARM::t2LDRs, ARM::tLDR, 0, 0, 0, 1, 0, 0,0, 1 }, + { ARM::t2LDRBi12,ARM::tLDRB, 0, 5, 0, 1, 0, 0,0, 1 }, + { ARM::t2LDRBs, ARM::tLDRB, 0, 0, 0, 1, 0, 0,0, 1 }, + { ARM::t2LDRHi12,ARM::tLDRH, 0, 5, 0, 1, 0, 0,0, 1 }, + { ARM::t2LDRHs, ARM::tLDRH, 0, 0, 0, 1, 0, 0,0, 1 }, + { ARM::t2LDRSBs,ARM::tLDRSB, 0, 0, 0, 1, 0, 0,0, 1 }, + { ARM::t2LDRSHs,ARM::tLDRSH, 0, 0, 0, 1, 0, 0,0, 1 }, + { ARM::t2STRi12,ARM::tSTR, ARM::tSTRspi, 5, 8, 1, 0, 0,0, 1 }, + { ARM::t2STRs, ARM::tSTR, 0, 0, 0, 1, 0, 0,0, 1 }, + { ARM::t2STRBi12,ARM::tSTRB, 0, 5, 0, 1, 0, 0,0, 1 }, + { ARM::t2STRBs, ARM::tSTRB, 0, 0, 0, 1, 0, 0,0, 1 }, + { ARM::t2STRHi12,ARM::tSTRH, 0, 5, 0, 1, 0, 0,0, 1 }, + { ARM::t2STRHs, ARM::tSTRH, 0, 0, 0, 1, 0, 0,0, 1 }, + + { ARM::t2LDM_RET,0, ARM::tPOP_RET, 0, 0, 1, 1, 1,1, 1 }, + { ARM::t2LDM, ARM::tLDM, ARM::tPOP, 0, 0, 1, 1, 1,1, 1 }, + { ARM::t2STM, ARM::tSTM, ARM::tPUSH, 0, 0, 1, 1, 1,1, 1 }, + }; + + class Thumb2SizeReduce : public MachineFunctionPass { + public: + static char ID; + Thumb2SizeReduce(); + + const Thumb2InstrInfo *TII; + + virtual bool runOnMachineFunction(MachineFunction &MF); + + virtual const char *getPassName() const { + return "Thumb2 instruction size reduction pass"; + } + + private: + /// ReduceOpcodeMap - Maps wide opcode to index of entry in ReduceTable. + DenseMap ReduceOpcodeMap; + + bool VerifyPredAndCC(MachineInstr *MI, const ReduceEntry &Entry, + bool is2Addr, ARMCC::CondCodes Pred, + bool LiveCPSR, bool &HasCC, bool &CCDead); + + bool ReduceLoadStore(MachineBasicBlock &MBB, MachineInstr *MI, + const ReduceEntry &Entry); + + bool ReduceSpecial(MachineBasicBlock &MBB, MachineInstr *MI, + const ReduceEntry &Entry, bool LiveCPSR); + + /// ReduceTo2Addr - Reduce a 32-bit instruction to a 16-bit two-address + /// instruction. + bool ReduceTo2Addr(MachineBasicBlock &MBB, MachineInstr *MI, + const ReduceEntry &Entry, + bool LiveCPSR); + + /// ReduceToNarrow - Reduce a 32-bit instruction to a 16-bit + /// non-two-address instruction. + bool ReduceToNarrow(MachineBasicBlock &MBB, MachineInstr *MI, + const ReduceEntry &Entry, + bool LiveCPSR); + + /// ReduceMBB - Reduce width of instructions in the specified basic block. + bool ReduceMBB(MachineBasicBlock &MBB); + }; + char Thumb2SizeReduce::ID = 0; +} + +Thumb2SizeReduce::Thumb2SizeReduce() : MachineFunctionPass(&ID) { + for (unsigned i = 0, e = array_lengthof(ReduceTable); i != e; ++i) { + unsigned FromOpc = ReduceTable[i].WideOpc; + if (!ReduceOpcodeMap.insert(std::make_pair(FromOpc, i)).second) + assert(false && "Duplicated entries?"); + } +} + +static bool HasImplicitCPSRDef(const TargetInstrDesc &TID) { + for (const unsigned *Regs = TID.ImplicitDefs; *Regs; ++Regs) + if (*Regs == ARM::CPSR) + return true; + return false; +} + +bool +Thumb2SizeReduce::VerifyPredAndCC(MachineInstr *MI, const ReduceEntry &Entry, + bool is2Addr, ARMCC::CondCodes Pred, + bool LiveCPSR, bool &HasCC, bool &CCDead) { + if ((is2Addr && Entry.PredCC2 == 0) || + (!is2Addr && Entry.PredCC1 == 0)) { + if (Pred == ARMCC::AL) { + // Not predicated, must set CPSR. + if (!HasCC) { + // Original instruction was not setting CPSR, but CPSR is not + // currently live anyway. It's ok to set it. The CPSR def is + // dead though. + if (!LiveCPSR) { + HasCC = true; + CCDead = true; + return true; + } + return false; + } + } else { + // Predicated, must not set CPSR. + if (HasCC) + return false; + } + } else if ((is2Addr && Entry.PredCC2 == 2) || + (!is2Addr && Entry.PredCC1 == 2)) { + /// Old opcode has an optional def of CPSR. + if (HasCC) + return true; + // If both old opcode does not implicit CPSR def, then it's not ok since + // these new opcodes CPSR def is not meant to be thrown away. e.g. CMP. + if (!HasImplicitCPSRDef(MI->getDesc())) + return false; + HasCC = true; + } else { + // 16-bit instruction does not set CPSR. + if (HasCC) + return false; + } + + return true; +} + +static bool VerifyLowRegs(MachineInstr *MI) { + unsigned Opc = MI->getOpcode(); + bool isPCOk = (Opc == ARM::t2LDM_RET) || (Opc == ARM::t2LDM); + bool isLROk = (Opc == ARM::t2STM); + bool isSPOk = isPCOk || isLROk || (Opc == ARM::t2ADDrSPi); + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + const MachineOperand &MO = MI->getOperand(i); + if (!MO.isReg() || MO.isImplicit()) + continue; + unsigned Reg = MO.getReg(); + if (Reg == 0 || Reg == ARM::CPSR) + continue; + if (isPCOk && Reg == ARM::PC) + continue; + if (isLROk && Reg == ARM::LR) + continue; + if (Reg == ARM::SP) { + if (isSPOk) + continue; + if (i == 1 && (Opc == ARM::t2LDRi12 || Opc == ARM::t2STRi12)) + // Special case for these ldr / str with sp as base register. + continue; + } + if (!isARMLowRegister(Reg)) + return false; + } + return true; +} + +bool +Thumb2SizeReduce::ReduceLoadStore(MachineBasicBlock &MBB, MachineInstr *MI, + const ReduceEntry &Entry) { + if (ReduceLimitLdSt != -1 && ((int)NumLdSts >= ReduceLimitLdSt)) + return false; + + unsigned Scale = 1; + bool HasImmOffset = false; + bool HasShift = false; + bool HasOffReg = true; + bool isLdStMul = false; + unsigned Opc = Entry.NarrowOpc1; + unsigned OpNum = 3; // First 'rest' of operands. + uint8_t ImmLimit = Entry.Imm1Limit; + switch (Entry.WideOpc) { + default: + llvm_unreachable("Unexpected Thumb2 load / store opcode!"); + case ARM::t2LDRi12: + case ARM::t2STRi12: { + unsigned BaseReg = MI->getOperand(1).getReg(); + if (BaseReg == ARM::SP) { + Opc = Entry.NarrowOpc2; + ImmLimit = Entry.Imm2Limit; + HasOffReg = false; + } + Scale = 4; + HasImmOffset = true; + break; + } + case ARM::t2LDRBi12: + case ARM::t2STRBi12: + HasImmOffset = true; + break; + case ARM::t2LDRHi12: + case ARM::t2STRHi12: + Scale = 2; + HasImmOffset = true; + break; + case ARM::t2LDRs: + case ARM::t2LDRBs: + case ARM::t2LDRHs: + case ARM::t2LDRSBs: + case ARM::t2LDRSHs: + case ARM::t2STRs: + case ARM::t2STRBs: + case ARM::t2STRHs: + HasShift = true; + OpNum = 4; + break; + case ARM::t2LDM_RET: + case ARM::t2LDM: + case ARM::t2STM: { + OpNum = 0; + unsigned BaseReg = MI->getOperand(0).getReg(); + unsigned Mode = MI->getOperand(1).getImm(); + if (BaseReg == ARM::SP && ARM_AM::getAM4WBFlag(Mode)) { + Opc = Entry.NarrowOpc2; + OpNum = 2; + } else if (Entry.WideOpc == ARM::t2LDM_RET || + !isARMLowRegister(BaseReg) || + !ARM_AM::getAM4WBFlag(Mode) || + ARM_AM::getAM4SubMode(Mode) != ARM_AM::ia) { + return false; + } + isLdStMul = true; + break; + } + } + + unsigned OffsetReg = 0; + bool OffsetKill = false; + if (HasShift) { + OffsetReg = MI->getOperand(2).getReg(); + OffsetKill = MI->getOperand(2).isKill(); + if (MI->getOperand(3).getImm()) + // Thumb1 addressing mode doesn't support shift. + return false; + } + + unsigned OffsetImm = 0; + if (HasImmOffset) { + OffsetImm = MI->getOperand(2).getImm(); + unsigned MaxOffset = ((1 << ImmLimit) - 1) * Scale; + if ((OffsetImm & (Scale-1)) || OffsetImm > MaxOffset) + // Make sure the immediate field fits. + return false; + } + + // Add the 16-bit load / store instruction. + // FIXME: Thumb1 addressing mode encode both immediate and register offset. + DebugLoc dl = MI->getDebugLoc(); + MachineInstrBuilder MIB = BuildMI(MBB, *MI, dl, TII->get(Opc)); + if (!isLdStMul) { + MIB.addOperand(MI->getOperand(0)).addOperand(MI->getOperand(1)); + if (Opc != ARM::tLDRSB && Opc != ARM::tLDRSH) { + // tLDRSB and tLDRSH do not have an immediate offset field. On the other + // hand, it must have an offset register. + // FIXME: Remove this special case. + MIB.addImm(OffsetImm/Scale); + } + assert((!HasShift || OffsetReg) && "Invalid so_reg load / store address!"); + + if (HasOffReg) + MIB.addReg(OffsetReg, getKillRegState(OffsetKill)); + } + + // Transfer the rest of operands. + for (unsigned e = MI->getNumOperands(); OpNum != e; ++OpNum) + MIB.addOperand(MI->getOperand(OpNum)); + + // Transfer memoperands. + (*MIB).setMemRefs(MI->memoperands_begin(), MI->memoperands_end()); + + DEBUG(errs() << "Converted 32-bit: " << *MI << " to 16-bit: " << *MIB); + + MBB.erase(MI); + ++NumLdSts; + return true; +} + +bool +Thumb2SizeReduce::ReduceSpecial(MachineBasicBlock &MBB, MachineInstr *MI, + const ReduceEntry &Entry, + bool LiveCPSR) { + if (Entry.LowRegs1 && !VerifyLowRegs(MI)) + return false; + + const TargetInstrDesc &TID = MI->getDesc(); + if (TID.mayLoad() || TID.mayStore()) + return ReduceLoadStore(MBB, MI, Entry); + + unsigned Opc = MI->getOpcode(); + switch (Opc) { + default: break; + case ARM::t2ADDSri: + case ARM::t2ADDSrr: { + unsigned PredReg = 0; + if (getInstrPredicate(MI, PredReg) == ARMCC::AL) { + switch (Opc) { + default: break; + case ARM::t2ADDSri: { + if (ReduceTo2Addr(MBB, MI, Entry, LiveCPSR)) + return true; + // fallthrough + } + case ARM::t2ADDSrr: + return ReduceToNarrow(MBB, MI, Entry, LiveCPSR); + } + } + break; + } + case ARM::t2RSBri: + case ARM::t2RSBSri: + if (MI->getOperand(2).getImm() == 0) + return ReduceToNarrow(MBB, MI, Entry, LiveCPSR); + break; + case ARM::t2MOVi16: + // Can convert only 'pure' immediate operands, not immediates obtained as + // globals' addresses. + if (MI->getOperand(1).isImm()) + return ReduceToNarrow(MBB, MI, Entry, LiveCPSR); + break; + } + return false; +} + +bool +Thumb2SizeReduce::ReduceTo2Addr(MachineBasicBlock &MBB, MachineInstr *MI, + const ReduceEntry &Entry, + bool LiveCPSR) { + + if (ReduceLimit2Addr != -1 && ((int)Num2Addrs >= ReduceLimit2Addr)) + return false; + + const TargetInstrDesc &TID = MI->getDesc(); + unsigned Reg0 = MI->getOperand(0).getReg(); + unsigned Reg1 = MI->getOperand(1).getReg(); + if (Reg0 != Reg1) + return false; + if (Entry.LowRegs2 && !isARMLowRegister(Reg0)) + return false; + if (Entry.Imm2Limit) { + unsigned Imm = MI->getOperand(2).getImm(); + unsigned Limit = (1 << Entry.Imm2Limit) - 1; + if (Imm > Limit) + return false; + } else { + unsigned Reg2 = MI->getOperand(2).getReg(); + if (Entry.LowRegs2 && !isARMLowRegister(Reg2)) + return false; + } + + // Check if it's possible / necessary to transfer the predicate. + const TargetInstrDesc &NewTID = TII->get(Entry.NarrowOpc2); + unsigned PredReg = 0; + ARMCC::CondCodes Pred = getInstrPredicate(MI, PredReg); + bool SkipPred = false; + if (Pred != ARMCC::AL) { + if (!NewTID.isPredicable()) + // Can't transfer predicate, fail. + return false; + } else { + SkipPred = !NewTID.isPredicable(); + } + + bool HasCC = false; + bool CCDead = false; + if (TID.hasOptionalDef()) { + unsigned NumOps = TID.getNumOperands(); + HasCC = (MI->getOperand(NumOps-1).getReg() == ARM::CPSR); + if (HasCC && MI->getOperand(NumOps-1).isDead()) + CCDead = true; + } + if (!VerifyPredAndCC(MI, Entry, true, Pred, LiveCPSR, HasCC, CCDead)) + return false; + + // Add the 16-bit instruction. + DebugLoc dl = MI->getDebugLoc(); + MachineInstrBuilder MIB = BuildMI(MBB, *MI, dl, NewTID); + MIB.addOperand(MI->getOperand(0)); + if (NewTID.hasOptionalDef()) { + if (HasCC) + AddDefaultT1CC(MIB, CCDead); + else + AddNoT1CC(MIB); + } + + // Transfer the rest of operands. + unsigned NumOps = TID.getNumOperands(); + for (unsigned i = 1, e = MI->getNumOperands(); i != e; ++i) { + if (i < NumOps && TID.OpInfo[i].isOptionalDef()) + continue; + if (SkipPred && TID.OpInfo[i].isPredicate()) + continue; + MIB.addOperand(MI->getOperand(i)); + } + + DEBUG(errs() << "Converted 32-bit: " << *MI << " to 16-bit: " << *MIB); + + MBB.erase(MI); + ++Num2Addrs; + return true; +} + +bool +Thumb2SizeReduce::ReduceToNarrow(MachineBasicBlock &MBB, MachineInstr *MI, + const ReduceEntry &Entry, + bool LiveCPSR) { + if (ReduceLimit != -1 && ((int)NumNarrows >= ReduceLimit)) + return false; + + unsigned Limit = ~0U; + unsigned Scale = (Entry.WideOpc == ARM::t2ADDrSPi) ? 4 : 1; + if (Entry.Imm1Limit) + Limit = ((1 << Entry.Imm1Limit) - 1) * Scale; + + const TargetInstrDesc &TID = MI->getDesc(); + for (unsigned i = 0, e = TID.getNumOperands(); i != e; ++i) { + if (TID.OpInfo[i].isPredicate()) + continue; + const MachineOperand &MO = MI->getOperand(i); + if (MO.isReg()) { + unsigned Reg = MO.getReg(); + if (!Reg || Reg == ARM::CPSR) + continue; + if (Entry.WideOpc == ARM::t2ADDrSPi && Reg == ARM::SP) + continue; + if (Entry.LowRegs1 && !isARMLowRegister(Reg)) + return false; + } else if (MO.isImm() && + !TID.OpInfo[i].isPredicate()) { + if (((unsigned)MO.getImm()) > Limit || (MO.getImm() & (Scale-1)) != 0) + return false; + } + } + + // Check if it's possible / necessary to transfer the predicate. + const TargetInstrDesc &NewTID = TII->get(Entry.NarrowOpc1); + unsigned PredReg = 0; + ARMCC::CondCodes Pred = getInstrPredicate(MI, PredReg); + bool SkipPred = false; + if (Pred != ARMCC::AL) { + if (!NewTID.isPredicable()) + // Can't transfer predicate, fail. + return false; + } else { + SkipPred = !NewTID.isPredicable(); + } + + bool HasCC = false; + bool CCDead = false; + if (TID.hasOptionalDef()) { + unsigned NumOps = TID.getNumOperands(); + HasCC = (MI->getOperand(NumOps-1).getReg() == ARM::CPSR); + if (HasCC && MI->getOperand(NumOps-1).isDead()) + CCDead = true; + } + if (!VerifyPredAndCC(MI, Entry, false, Pred, LiveCPSR, HasCC, CCDead)) + return false; + + // Add the 16-bit instruction. + DebugLoc dl = MI->getDebugLoc(); + MachineInstrBuilder MIB = BuildMI(MBB, *MI, dl, NewTID); + MIB.addOperand(MI->getOperand(0)); + if (NewTID.hasOptionalDef()) { + if (HasCC) + AddDefaultT1CC(MIB, CCDead); + else + AddNoT1CC(MIB); + } + + // Transfer the rest of operands. + unsigned NumOps = TID.getNumOperands(); + for (unsigned i = 1, e = MI->getNumOperands(); i != e; ++i) { + if (i < NumOps && TID.OpInfo[i].isOptionalDef()) + continue; + if ((TID.getOpcode() == ARM::t2RSBSri || + TID.getOpcode() == ARM::t2RSBri) && i == 2) + // Skip the zero immediate operand, it's now implicit. + continue; + bool isPred = (i < NumOps && TID.OpInfo[i].isPredicate()); + if (SkipPred && isPred) + continue; + const MachineOperand &MO = MI->getOperand(i); + if (Scale > 1 && !isPred && MO.isImm()) + MIB.addImm(MO.getImm() / Scale); + else { + if (MO.isReg() && MO.isImplicit() && MO.getReg() == ARM::CPSR) + // Skip implicit def of CPSR. Either it's modeled as an optional + // def now or it's already an implicit def on the new instruction. + continue; + MIB.addOperand(MO); + } + } + if (!TID.isPredicable() && NewTID.isPredicable()) + AddDefaultPred(MIB); + + DEBUG(errs() << "Converted 32-bit: " << *MI << " to 16-bit: " << *MIB); + + MBB.erase(MI); + ++NumNarrows; + return true; +} + +static bool UpdateCPSRDef(MachineInstr &MI, bool LiveCPSR) { + bool HasDef = false; + for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) { + const MachineOperand &MO = MI.getOperand(i); + if (!MO.isReg() || MO.isUndef() || MO.isUse()) + continue; + if (MO.getReg() != ARM::CPSR) + continue; + if (!MO.isDead()) + HasDef = true; + } + + return HasDef || LiveCPSR; +} + +static bool UpdateCPSRUse(MachineInstr &MI, bool LiveCPSR) { + for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) { + const MachineOperand &MO = MI.getOperand(i); + if (!MO.isReg() || MO.isUndef() || MO.isDef()) + continue; + if (MO.getReg() != ARM::CPSR) + continue; + assert(LiveCPSR && "CPSR liveness tracking is wrong!"); + if (MO.isKill()) { + LiveCPSR = false; + break; + } + } + + return LiveCPSR; +} + +bool Thumb2SizeReduce::ReduceMBB(MachineBasicBlock &MBB) { + bool Modified = false; + + bool LiveCPSR = false; + // Yes, CPSR could be livein. + for (MachineBasicBlock::const_livein_iterator I = MBB.livein_begin(), + E = MBB.livein_end(); I != E; ++I) { + if (*I == ARM::CPSR) { + LiveCPSR = true; + break; + } + } + + MachineBasicBlock::iterator MII = MBB.begin(), E = MBB.end(); + MachineBasicBlock::iterator NextMII; + for (; MII != E; MII = NextMII) { + NextMII = next(MII); + + MachineInstr *MI = &*MII; + LiveCPSR = UpdateCPSRUse(*MI, LiveCPSR); + + unsigned Opcode = MI->getOpcode(); + DenseMap::iterator OPI = ReduceOpcodeMap.find(Opcode); + if (OPI != ReduceOpcodeMap.end()) { + const ReduceEntry &Entry = ReduceTable[OPI->second]; + // Ignore "special" cases for now. + if (Entry.Special) { + if (ReduceSpecial(MBB, MI, Entry, LiveCPSR)) { + Modified = true; + MachineBasicBlock::iterator I = prior(NextMII); + MI = &*I; + } + goto ProcessNext; + } + + // Try to transform to a 16-bit two-address instruction. + if (Entry.NarrowOpc2 && ReduceTo2Addr(MBB, MI, Entry, LiveCPSR)) { + Modified = true; + MachineBasicBlock::iterator I = prior(NextMII); + MI = &*I; + goto ProcessNext; + } + + // Try to transform ro a 16-bit non-two-address instruction. + if (Entry.NarrowOpc1 && ReduceToNarrow(MBB, MI, Entry, LiveCPSR)) { + Modified = true; + MachineBasicBlock::iterator I = prior(NextMII); + MI = &*I; + } + } + + ProcessNext: + LiveCPSR = UpdateCPSRDef(*MI, LiveCPSR); + } + + return Modified; +} + +bool Thumb2SizeReduce::runOnMachineFunction(MachineFunction &MF) { + const TargetMachine &TM = MF.getTarget(); + TII = static_cast(TM.getInstrInfo()); + + bool Modified = false; + for (MachineFunction::iterator I = MF.begin(), E = MF.end(); I != E; ++I) + Modified |= ReduceMBB(*I); + return Modified; +} + +/// createThumb2SizeReductionPass - Returns an instance of the Thumb2 size +/// reduction pass. +FunctionPass *llvm::createThumb2SizeReductionPass() { + return new Thumb2SizeReduce(); +} diff --git a/libclamav/c++/llvm/lib/Target/CMakeLists.txt b/libclamav/c++/llvm/lib/Target/CMakeLists.txt new file mode 100644 index 000000000..8769ee297 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/CMakeLists.txt @@ -0,0 +1,14 @@ +add_llvm_library(LLVMTarget + SubtargetFeature.cpp + Target.cpp + TargetData.cpp + TargetELFWriterInfo.cpp + TargetFrameInfo.cpp + TargetInstrInfo.cpp + TargetIntrinsicInfo.cpp + TargetLoweringObjectFile.cpp + TargetMachOWriterInfo.cpp + TargetMachine.cpp + TargetRegisterInfo.cpp + TargetSubtarget.cpp + ) diff --git a/libclamav/c++/llvm/lib/Target/MSP430/AsmPrinter/Makefile b/libclamav/c++/llvm/lib/Target/MSP430/AsmPrinter/Makefile new file mode 100644 index 000000000..e69de29bb diff --git a/libclamav/c++/llvm/lib/Target/Makefile b/libclamav/c++/llvm/lib/Target/Makefile new file mode 100644 index 000000000..50a360f1f --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/Makefile @@ -0,0 +1,20 @@ +#===- lib/Target/Makefile ----------------------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LEVEL = ../.. +LIBRARYNAME = LLVMTarget +BUILD_ARCHIVE = 1 + +# We include this early so we can access the value of TARGETS_TO_BUILD as the +# value for PARALLEL_DIRS which must be set before Makefile.rules is included +include $(LEVEL)/Makefile.config + +PARALLEL_DIRS := $(TARGETS_TO_BUILD) + +include $(LLVM_SRC_ROOT)/Makefile.rules diff --git a/libclamav/c++/llvm/lib/Target/PIC16/AsmPrinter/Makefile b/libclamav/c++/llvm/lib/Target/PIC16/AsmPrinter/Makefile new file mode 100644 index 000000000..e69de29bb diff --git a/libclamav/c++/llvm/lib/Target/PowerPC/AsmPrinter/CMakeLists.txt b/libclamav/c++/llvm/lib/Target/PowerPC/AsmPrinter/CMakeLists.txt new file mode 100644 index 000000000..236b264d8 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/PowerPC/AsmPrinter/CMakeLists.txt @@ -0,0 +1,6 @@ +include_directories( ${CMAKE_CURRENT_BINARY_DIR}/.. ${CMAKE_CURRENT_SOURCE_DIR}/.. ) + +add_llvm_library(LLVMPowerPCAsmPrinter + PPCAsmPrinter.cpp + ) +add_dependencies(LLVMPowerPCAsmPrinter PowerPCCodeGenTable_gen) \ No newline at end of file diff --git a/libclamav/c++/llvm/lib/Target/PowerPC/AsmPrinter/Makefile b/libclamav/c++/llvm/lib/Target/PowerPC/AsmPrinter/Makefile new file mode 100644 index 000000000..269ef9204 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/PowerPC/AsmPrinter/Makefile @@ -0,0 +1,15 @@ +##===- lib/Target/PowerPC/AsmPrinter/Makefile --------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## +LEVEL = ../../../.. +LIBRARYNAME = LLVMPowerPCAsmPrinter + +# Hack: we need to include 'main' PowerPC target directory to grab private headers +CPPFLAGS = -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. + +include $(LEVEL)/Makefile.common diff --git a/libclamav/c++/llvm/lib/Target/PowerPC/AsmPrinter/PPCAsmPrinter.cpp b/libclamav/c++/llvm/lib/Target/PowerPC/AsmPrinter/PPCAsmPrinter.cpp new file mode 100644 index 000000000..aae4607f4 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/PowerPC/AsmPrinter/PPCAsmPrinter.cpp @@ -0,0 +1,1160 @@ +//===-- PPCAsmPrinter.cpp - Print machine instrs to PowerPC assembly --------=// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains a printer that converts from our internal representation +// of machine-dependent LLVM code to PowerPC assembly language. This printer is +// the output mechanism used by `llc'. +// +// Documentation at http://developer.apple.com/documentation/DeveloperTools/ +// Reference/Assembler/ASMIntroduction/chapter_1_section_1.html +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "asmprinter" +#include "PPC.h" +#include "PPCPredicates.h" +#include "PPCTargetMachine.h" +#include "PPCSubtarget.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Module.h" +#include "llvm/Assembly/Writer.h" +#include "llvm/CodeGen/AsmPrinter.h" +#include "llvm/CodeGen/DwarfWriter.h" +#include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCSectionMachO.h" +#include "llvm/MC/MCStreamer.h" +#include "llvm/MC/MCSymbol.h" +#include "llvm/Target/TargetLoweringObjectFile.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetOptions.h" +#include "llvm/Target/TargetRegistry.h" +#include "llvm/Support/Mangler.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/FormattedStream.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/StringSet.h" +using namespace llvm; + +STATISTIC(EmittedInsts, "Number of machine instrs printed"); + +namespace { + class PPCAsmPrinter : public AsmPrinter { + protected: + struct FnStubInfo { + std::string Stub, LazyPtr, AnonSymbol; + + FnStubInfo() {} + + void Init(const GlobalValue *GV, Mangler *Mang) { + // Already initialized. + if (!Stub.empty()) return; + Stub = Mang->getMangledName(GV, "$stub", true); + LazyPtr = Mang->getMangledName(GV, "$lazy_ptr", true); + AnonSymbol = Mang->getMangledName(GV, "$stub$tmp", true); + } + + void Init(const std::string &GV, Mangler *Mang) { + // Already initialized. + if (!Stub.empty()) return; + Stub = Mang->makeNameProper(GV + "$stub", + Mangler::Private); + LazyPtr = Mang->makeNameProper(GV + "$lazy_ptr", + Mangler::Private); + AnonSymbol = Mang->makeNameProper(GV + "$stub$tmp", + Mangler::Private); + } + }; + + StringMap FnStubs; + StringMap GVStubs, HiddenGVStubs, TOC; + const PPCSubtarget &Subtarget; + uint64_t LabelID; + public: + explicit PPCAsmPrinter(formatted_raw_ostream &O, TargetMachine &TM, + const MCAsmInfo *T, bool V) + : AsmPrinter(O, TM, T, V), + Subtarget(TM.getSubtarget()), LabelID(0) {} + + virtual const char *getPassName() const { + return "PowerPC Assembly Printer"; + } + + PPCTargetMachine &getTM() { + return static_cast(TM); + } + + unsigned enumRegToMachineReg(unsigned enumReg) { + switch (enumReg) { + default: llvm_unreachable("Unhandled register!"); + case PPC::CR0: return 0; + case PPC::CR1: return 1; + case PPC::CR2: return 2; + case PPC::CR3: return 3; + case PPC::CR4: return 4; + case PPC::CR5: return 5; + case PPC::CR6: return 6; + case PPC::CR7: return 7; + } + llvm_unreachable(0); + } + + /// printInstruction - This method is automatically generated by tablegen + /// from the instruction set description. This method returns true if the + /// machine instruction was sufficiently described to print it, otherwise it + /// returns false. + void printInstruction(const MachineInstr *MI); + static const char *getRegisterName(unsigned RegNo); + + + void printMachineInstruction(const MachineInstr *MI); + void printOp(const MachineOperand &MO); + + /// stripRegisterPrefix - This method strips the character prefix from a + /// register name so that only the number is left. Used by for linux asm. + const char *stripRegisterPrefix(const char *RegName) { + switch (RegName[0]) { + case 'r': + case 'f': + case 'v': return RegName + 1; + case 'c': if (RegName[1] == 'r') return RegName + 2; + } + + return RegName; + } + + /// printRegister - Print register according to target requirements. + /// + void printRegister(const MachineOperand &MO, bool R0AsZero) { + unsigned RegNo = MO.getReg(); + assert(TargetRegisterInfo::isPhysicalRegister(RegNo) && "Not physreg??"); + + // If we should use 0 for R0. + if (R0AsZero && RegNo == PPC::R0) { + O << "0"; + return; + } + + const char *RegName = getRegisterName(RegNo); + // Linux assembler (Others?) does not take register mnemonics. + // FIXME - What about special registers used in mfspr/mtspr? + if (!Subtarget.isDarwin()) RegName = stripRegisterPrefix(RegName); + O << RegName; + } + + void printOperand(const MachineInstr *MI, unsigned OpNo) { + const MachineOperand &MO = MI->getOperand(OpNo); + if (MO.isReg()) { + printRegister(MO, false); + } else if (MO.isImm()) { + O << MO.getImm(); + } else { + printOp(MO); + } + } + + bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, + unsigned AsmVariant, const char *ExtraCode); + bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo, + unsigned AsmVariant, const char *ExtraCode); + + + void printS5ImmOperand(const MachineInstr *MI, unsigned OpNo) { + char value = MI->getOperand(OpNo).getImm(); + value = (value << (32-5)) >> (32-5); + O << (int)value; + } + void printU5ImmOperand(const MachineInstr *MI, unsigned OpNo) { + unsigned char value = MI->getOperand(OpNo).getImm(); + assert(value <= 31 && "Invalid u5imm argument!"); + O << (unsigned int)value; + } + void printU6ImmOperand(const MachineInstr *MI, unsigned OpNo) { + unsigned char value = MI->getOperand(OpNo).getImm(); + assert(value <= 63 && "Invalid u6imm argument!"); + O << (unsigned int)value; + } + void printS16ImmOperand(const MachineInstr *MI, unsigned OpNo) { + O << (short)MI->getOperand(OpNo).getImm(); + } + void printU16ImmOperand(const MachineInstr *MI, unsigned OpNo) { + O << (unsigned short)MI->getOperand(OpNo).getImm(); + } + void printS16X4ImmOperand(const MachineInstr *MI, unsigned OpNo) { + if (MI->getOperand(OpNo).isImm()) { + O << (short)(MI->getOperand(OpNo).getImm()*4); + } else { + O << "lo16("; + printOp(MI->getOperand(OpNo)); + if (TM.getRelocationModel() == Reloc::PIC_) + O << "-\"L" << getFunctionNumber() << "$pb\")"; + else + O << ')'; + } + } + void printBranchOperand(const MachineInstr *MI, unsigned OpNo) { + // Branches can take an immediate operand. This is used by the branch + // selection pass to print $+8, an eight byte displacement from the PC. + if (MI->getOperand(OpNo).isImm()) { + O << "$+" << MI->getOperand(OpNo).getImm()*4; + } else { + printOp(MI->getOperand(OpNo)); + } + } + void printCallOperand(const MachineInstr *MI, unsigned OpNo) { + const MachineOperand &MO = MI->getOperand(OpNo); + if (TM.getRelocationModel() != Reloc::Static) { + if (MO.getType() == MachineOperand::MO_GlobalAddress) { + GlobalValue *GV = MO.getGlobal(); + if (GV->isDeclaration() || GV->isWeakForLinker()) { + // Dynamically-resolved functions need a stub for the function. + FnStubInfo &FnInfo = FnStubs[Mang->getMangledName(GV)]; + FnInfo.Init(GV, Mang); + O << FnInfo.Stub; + return; + } + } + if (MO.getType() == MachineOperand::MO_ExternalSymbol) { + FnStubInfo &FnInfo =FnStubs[Mang->makeNameProper(MO.getSymbolName())]; + FnInfo.Init(MO.getSymbolName(), Mang); + O << FnInfo.Stub; + return; + } + } + + printOp(MI->getOperand(OpNo)); + } + void printAbsAddrOperand(const MachineInstr *MI, unsigned OpNo) { + O << (int)MI->getOperand(OpNo).getImm()*4; + } + void printPICLabel(const MachineInstr *MI, unsigned OpNo) { + O << "\"L" << getFunctionNumber() << "$pb\"\n"; + O << "\"L" << getFunctionNumber() << "$pb\":"; + } + void printSymbolHi(const MachineInstr *MI, unsigned OpNo) { + if (MI->getOperand(OpNo).isImm()) { + printS16ImmOperand(MI, OpNo); + } else { + if (Subtarget.isDarwin()) O << "ha16("; + printOp(MI->getOperand(OpNo)); + if (TM.getRelocationModel() == Reloc::PIC_) + O << "-\"L" << getFunctionNumber() << "$pb\""; + if (Subtarget.isDarwin()) + O << ')'; + else + O << "@ha"; + } + } + void printSymbolLo(const MachineInstr *MI, unsigned OpNo) { + if (MI->getOperand(OpNo).isImm()) { + printS16ImmOperand(MI, OpNo); + } else { + if (Subtarget.isDarwin()) O << "lo16("; + printOp(MI->getOperand(OpNo)); + if (TM.getRelocationModel() == Reloc::PIC_) + O << "-\"L" << getFunctionNumber() << "$pb\""; + if (Subtarget.isDarwin()) + O << ')'; + else + O << "@l"; + } + } + void printcrbitm(const MachineInstr *MI, unsigned OpNo) { + unsigned CCReg = MI->getOperand(OpNo).getReg(); + unsigned RegNo = enumRegToMachineReg(CCReg); + O << (0x80 >> RegNo); + } + // The new addressing mode printers. + void printMemRegImm(const MachineInstr *MI, unsigned OpNo) { + printSymbolLo(MI, OpNo); + O << '('; + if (MI->getOperand(OpNo+1).isReg() && + MI->getOperand(OpNo+1).getReg() == PPC::R0) + O << "0"; + else + printOperand(MI, OpNo+1); + O << ')'; + } + void printMemRegImmShifted(const MachineInstr *MI, unsigned OpNo) { + if (MI->getOperand(OpNo).isImm()) + printS16X4ImmOperand(MI, OpNo); + else + printSymbolLo(MI, OpNo); + O << '('; + if (MI->getOperand(OpNo+1).isReg() && + MI->getOperand(OpNo+1).getReg() == PPC::R0) + O << "0"; + else + printOperand(MI, OpNo+1); + O << ')'; + } + + void printMemRegReg(const MachineInstr *MI, unsigned OpNo) { + // When used as the base register, r0 reads constant zero rather than + // the value contained in the register. For this reason, the darwin + // assembler requires that we print r0 as 0 (no r) when used as the base. + const MachineOperand &MO = MI->getOperand(OpNo); + printRegister(MO, true); + O << ", "; + printOperand(MI, OpNo+1); + } + + void printTOCEntryLabel(const MachineInstr *MI, unsigned OpNo) { + const MachineOperand &MO = MI->getOperand(OpNo); + + assert(MO.getType() == MachineOperand::MO_GlobalAddress); + + GlobalValue *GV = MO.getGlobal(); + + std::string Name = Mang->getMangledName(GV); + + // Map symbol -> label of TOC entry. + if (TOC.count(Name) == 0) { + std::string Label; + Label += MAI->getPrivateGlobalPrefix(); + Label += "C"; + Label += utostr(LabelID++); + + TOC[Name] = Label; + } + + O << TOC[Name] << "@toc"; + } + + void printPredicateOperand(const MachineInstr *MI, unsigned OpNo, + const char *Modifier); + + virtual bool runOnMachineFunction(MachineFunction &F) = 0; + }; + + /// PPCLinuxAsmPrinter - PowerPC assembly printer, customized for Linux + class PPCLinuxAsmPrinter : public PPCAsmPrinter { + public: + explicit PPCLinuxAsmPrinter(formatted_raw_ostream &O, TargetMachine &TM, + const MCAsmInfo *T, bool V) + : PPCAsmPrinter(O, TM, T, V){} + + virtual const char *getPassName() const { + return "Linux PPC Assembly Printer"; + } + + bool runOnMachineFunction(MachineFunction &F); + bool doFinalization(Module &M); + + void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + AU.addRequired(); + AU.addRequired(); + PPCAsmPrinter::getAnalysisUsage(AU); + } + + void PrintGlobalVariable(const GlobalVariable *GVar); + }; + + /// PPCDarwinAsmPrinter - PowerPC assembly printer, customized for Darwin/Mac + /// OS X + class PPCDarwinAsmPrinter : public PPCAsmPrinter { + formatted_raw_ostream &OS; + public: + explicit PPCDarwinAsmPrinter(formatted_raw_ostream &O, TargetMachine &TM, + const MCAsmInfo *T, bool V) + : PPCAsmPrinter(O, TM, T, V), OS(O) {} + + virtual const char *getPassName() const { + return "Darwin PPC Assembly Printer"; + } + + bool runOnMachineFunction(MachineFunction &F); + bool doFinalization(Module &M); + void EmitStartOfAsmFile(Module &M); + + void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + AU.addRequired(); + AU.addRequired(); + PPCAsmPrinter::getAnalysisUsage(AU); + } + + void PrintGlobalVariable(const GlobalVariable *GVar); + }; +} // end of anonymous namespace + +// Include the auto-generated portion of the assembly writer +#include "PPCGenAsmWriter.inc" + +void PPCAsmPrinter::printOp(const MachineOperand &MO) { + switch (MO.getType()) { + case MachineOperand::MO_Immediate: + llvm_unreachable("printOp() does not handle immediate values"); + + case MachineOperand::MO_MachineBasicBlock: + GetMBBSymbol(MO.getMBB()->getNumber())->print(O, MAI); + return; + case MachineOperand::MO_JumpTableIndex: + O << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() + << '_' << MO.getIndex(); + // FIXME: PIC relocation model + return; + case MachineOperand::MO_ConstantPoolIndex: + O << MAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() + << '_' << MO.getIndex(); + return; + case MachineOperand::MO_BlockAddress: + GetBlockAddressSymbol(MO.getBlockAddress())->print(O, MAI); + return; + case MachineOperand::MO_ExternalSymbol: { + // Computing the address of an external symbol, not calling it. + std::string Name(MAI->getGlobalPrefix()); + Name += MO.getSymbolName(); + + if (TM.getRelocationModel() != Reloc::Static) { + GVStubs[Name] = Name+"$non_lazy_ptr"; + Name += "$non_lazy_ptr"; + } + O << Name; + return; + } + case MachineOperand::MO_GlobalAddress: { + // Computing the address of a global symbol, not calling it. + GlobalValue *GV = MO.getGlobal(); + std::string Name; + + // External or weakly linked global variables need non-lazily-resolved stubs + if (TM.getRelocationModel() != Reloc::Static && + (GV->isDeclaration() || GV->isWeakForLinker())) { + if (!GV->hasHiddenVisibility()) { + Name = Mang->getMangledName(GV, "$non_lazy_ptr", true); + GVStubs[Mang->getMangledName(GV)] = Name; + } else if (GV->isDeclaration() || GV->hasCommonLinkage() || + GV->hasAvailableExternallyLinkage()) { + Name = Mang->getMangledName(GV, "$non_lazy_ptr", true); + HiddenGVStubs[Mang->getMangledName(GV)] = Name; + } else { + Name = Mang->getMangledName(GV); + } + } else { + Name = Mang->getMangledName(GV); + } + O << Name; + + printOffset(MO.getOffset()); + return; + } + + default: + O << ""; + return; + } +} + +/// PrintAsmOperand - Print out an operand for an inline asm expression. +/// +bool PPCAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, + unsigned AsmVariant, + const char *ExtraCode) { + // Does this asm operand have a single letter operand modifier? + if (ExtraCode && ExtraCode[0]) { + if (ExtraCode[1] != 0) return true; // Unknown modifier. + + switch (ExtraCode[0]) { + default: return true; // Unknown modifier. + case 'c': // Don't print "$" before a global var name or constant. + // PPC never has a prefix. + printOperand(MI, OpNo); + return false; + case 'L': // Write second word of DImode reference. + // Verify that this operand has two consecutive registers. + if (!MI->getOperand(OpNo).isReg() || + OpNo+1 == MI->getNumOperands() || + !MI->getOperand(OpNo+1).isReg()) + return true; + ++OpNo; // Return the high-part. + break; + case 'I': + // Write 'i' if an integer constant, otherwise nothing. Used to print + // addi vs add, etc. + if (MI->getOperand(OpNo).isImm()) + O << "i"; + return false; + } + } + + printOperand(MI, OpNo); + return false; +} + +// At the moment, all inline asm memory operands are a single register. +// In any case, the output of this routine should always be just one +// assembler operand. + +bool PPCAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo, + unsigned AsmVariant, + const char *ExtraCode) { + if (ExtraCode && ExtraCode[0]) + return true; // Unknown modifier. + assert (MI->getOperand(OpNo).isReg()); + O << "0("; + printOperand(MI, OpNo); + O << ")"; + return false; +} + +void PPCAsmPrinter::printPredicateOperand(const MachineInstr *MI, unsigned OpNo, + const char *Modifier) { + assert(Modifier && "Must specify 'cc' or 'reg' as predicate op modifier!"); + unsigned Code = MI->getOperand(OpNo).getImm(); + if (!strcmp(Modifier, "cc")) { + switch ((PPC::Predicate)Code) { + case PPC::PRED_ALWAYS: return; // Don't print anything for always. + case PPC::PRED_LT: O << "lt"; return; + case PPC::PRED_LE: O << "le"; return; + case PPC::PRED_EQ: O << "eq"; return; + case PPC::PRED_GE: O << "ge"; return; + case PPC::PRED_GT: O << "gt"; return; + case PPC::PRED_NE: O << "ne"; return; + case PPC::PRED_UN: O << "un"; return; + case PPC::PRED_NU: O << "nu"; return; + } + + } else { + assert(!strcmp(Modifier, "reg") && + "Need to specify 'cc' or 'reg' as predicate op modifier!"); + // Don't print the register for 'always'. + if (Code == PPC::PRED_ALWAYS) return; + printOperand(MI, OpNo+1); + } +} + + +/// printMachineInstruction -- Print out a single PowerPC MI in Darwin syntax to +/// the current output stream. +/// +void PPCAsmPrinter::printMachineInstruction(const MachineInstr *MI) { + ++EmittedInsts; + + processDebugLoc(MI, true); + + // Check for slwi/srwi mnemonics. + if (MI->getOpcode() == PPC::RLWINM) { + bool FoundMnemonic = false; + unsigned char SH = MI->getOperand(2).getImm(); + unsigned char MB = MI->getOperand(3).getImm(); + unsigned char ME = MI->getOperand(4).getImm(); + if (SH <= 31 && MB == 0 && ME == (31-SH)) { + O << "\tslwi "; FoundMnemonic = true; + } + if (SH <= 31 && MB == (32-SH) && ME == 31) { + O << "\tsrwi "; FoundMnemonic = true; + SH = 32-SH; + } + if (FoundMnemonic) { + printOperand(MI, 0); + O << ", "; + printOperand(MI, 1); + O << ", " << (unsigned int)SH << '\n'; + return; + } + } else if (MI->getOpcode() == PPC::OR || MI->getOpcode() == PPC::OR8) { + if (MI->getOperand(1).getReg() == MI->getOperand(2).getReg()) { + O << "\tmr "; + printOperand(MI, 0); + O << ", "; + printOperand(MI, 1); + O << '\n'; + return; + } + } else if (MI->getOpcode() == PPC::RLDICR) { + unsigned char SH = MI->getOperand(2).getImm(); + unsigned char ME = MI->getOperand(3).getImm(); + // rldicr RA, RS, SH, 63-SH == sldi RA, RS, SH + if (63-SH == ME) { + O << "\tsldi "; + printOperand(MI, 0); + O << ", "; + printOperand(MI, 1); + O << ", " << (unsigned int)SH << '\n'; + return; + } + } + + printInstruction(MI); + + if (VerboseAsm) + EmitComments(*MI); + O << '\n'; + + processDebugLoc(MI, false); +} + +/// runOnMachineFunction - This uses the printMachineInstruction() +/// method to print assembly for each instruction. +/// +bool PPCLinuxAsmPrinter::runOnMachineFunction(MachineFunction &MF) { + this->MF = &MF; + + SetupMachineFunction(MF); + O << "\n\n"; + + // Print out constants referenced by the function + EmitConstantPool(MF.getConstantPool()); + + // Print out labels for the function. + const Function *F = MF.getFunction(); + OutStreamer.SwitchSection(getObjFileLowering().SectionForGlobal(F, Mang, TM)); + + switch (F->getLinkage()) { + default: llvm_unreachable("Unknown linkage type!"); + case Function::PrivateLinkage: + case Function::InternalLinkage: // Symbols default to internal. + break; + case Function::ExternalLinkage: + O << "\t.global\t" << CurrentFnName << '\n' + << "\t.type\t" << CurrentFnName << ", @function\n"; + break; + case Function::LinkerPrivateLinkage: + case Function::WeakAnyLinkage: + case Function::WeakODRLinkage: + case Function::LinkOnceAnyLinkage: + case Function::LinkOnceODRLinkage: + O << "\t.global\t" << CurrentFnName << '\n'; + O << "\t.weak\t" << CurrentFnName << '\n'; + break; + } + + printVisibility(CurrentFnName, F->getVisibility()); + + EmitAlignment(MF.getAlignment(), F); + + if (Subtarget.isPPC64()) { + // Emit an official procedure descriptor. + // FIXME 64-bit SVR4: Use MCSection here? + O << "\t.section\t\".opd\",\"aw\"\n"; + O << "\t.align 3\n"; + O << CurrentFnName << ":\n"; + O << "\t.quad .L." << CurrentFnName << ",.TOC.@tocbase\n"; + O << "\t.previous\n"; + O << ".L." << CurrentFnName << ":\n"; + } else { + O << CurrentFnName << ":\n"; + } + + // Emit pre-function debug information. + DW->BeginFunction(&MF); + + // Print out code for the function. + for (MachineFunction::const_iterator I = MF.begin(), E = MF.end(); + I != E; ++I) { + // Print a label for the basic block. + if (I != MF.begin()) { + EmitBasicBlockStart(I); + } + for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end(); + II != E; ++II) { + // Print the assembly for the instruction. + printMachineInstruction(II); + } + } + + O << "\t.size\t" << CurrentFnName << ",.-" << CurrentFnName << '\n'; + + OutStreamer.SwitchSection(getObjFileLowering().SectionForGlobal(F, Mang, TM)); + + // Emit post-function debug information. + DW->EndFunction(&MF); + + // Print out jump tables referenced by the function. + EmitJumpTableInfo(MF.getJumpTableInfo(), MF); + + // We didn't modify anything. + return false; +} + +void PPCLinuxAsmPrinter::PrintGlobalVariable(const GlobalVariable *GVar) { + const TargetData *TD = TM.getTargetData(); + + if (!GVar->hasInitializer()) + return; // External global require no code + + // Check to see if this is a special global used by LLVM, if so, emit it. + if (EmitSpecialLLVMGlobal(GVar)) + return; + + std::string name = Mang->getMangledName(GVar); + + printVisibility(name, GVar->getVisibility()); + + Constant *C = GVar->getInitializer(); + const Type *Type = C->getType(); + unsigned Size = TD->getTypeAllocSize(Type); + unsigned Align = TD->getPreferredAlignmentLog(GVar); + + OutStreamer.SwitchSection(getObjFileLowering().SectionForGlobal(GVar, Mang, + TM)); + + if (C->isNullValue() && /* FIXME: Verify correct */ + !GVar->hasSection() && + (GVar->hasLocalLinkage() || GVar->hasExternalLinkage() || + GVar->isWeakForLinker())) { + if (Size == 0) Size = 1; // .comm Foo, 0 is undefined, avoid it. + + if (GVar->hasExternalLinkage()) { + O << "\t.global " << name << '\n'; + O << "\t.type " << name << ", @object\n"; + O << name << ":\n"; + O << "\t.zero " << Size << '\n'; + } else if (GVar->hasLocalLinkage()) { + O << MAI->getLCOMMDirective() << name << ',' << Size; + } else { + O << ".comm " << name << ',' << Size; + } + if (VerboseAsm) { + O << "\t\t" << MAI->getCommentString() << " '"; + WriteAsOperand(O, GVar, /*PrintType=*/false, GVar->getParent()); + O << "'"; + } + O << '\n'; + return; + } + + switch (GVar->getLinkage()) { + case GlobalValue::LinkOnceAnyLinkage: + case GlobalValue::LinkOnceODRLinkage: + case GlobalValue::WeakAnyLinkage: + case GlobalValue::WeakODRLinkage: + case GlobalValue::CommonLinkage: + case GlobalValue::LinkerPrivateLinkage: + O << "\t.global " << name << '\n' + << "\t.type " << name << ", @object\n" + << "\t.weak " << name << '\n'; + break; + case GlobalValue::AppendingLinkage: + // FIXME: appending linkage variables should go into a section of + // their name or something. For now, just emit them as external. + case GlobalValue::ExternalLinkage: + // If external or appending, declare as a global symbol + O << "\t.global " << name << '\n' + << "\t.type " << name << ", @object\n"; + // FALL THROUGH + case GlobalValue::InternalLinkage: + case GlobalValue::PrivateLinkage: + break; + default: + llvm_unreachable("Unknown linkage type!"); + } + + EmitAlignment(Align, GVar); + O << name << ":"; + if (VerboseAsm) { + O << "\t\t\t\t" << MAI->getCommentString() << " '"; + WriteAsOperand(O, GVar, /*PrintType=*/false, GVar->getParent()); + O << "'"; + } + O << '\n'; + + EmitGlobalConstant(C); + O << '\n'; +} + +bool PPCLinuxAsmPrinter::doFinalization(Module &M) { + const TargetData *TD = TM.getTargetData(); + + bool isPPC64 = TD->getPointerSizeInBits() == 64; + + if (isPPC64 && !TOC.empty()) { + // FIXME 64-bit SVR4: Use MCSection here? + O << "\t.section\t\".toc\",\"aw\"\n"; + + for (StringMap::iterator I = TOC.begin(), E = TOC.end(); + I != E; ++I) { + O << I->second << ":\n"; + O << "\t.tc " << I->getKeyData() << "[TC]," << I->getKeyData() << '\n'; + } + } + + return AsmPrinter::doFinalization(M); +} + +/// runOnMachineFunction - This uses the printMachineInstruction() +/// method to print assembly for each instruction. +/// +bool PPCDarwinAsmPrinter::runOnMachineFunction(MachineFunction &MF) { + this->MF = &MF; + + SetupMachineFunction(MF); + O << "\n\n"; + + // Print out constants referenced by the function + EmitConstantPool(MF.getConstantPool()); + + // Print out labels for the function. + const Function *F = MF.getFunction(); + OutStreamer.SwitchSection(getObjFileLowering().SectionForGlobal(F, Mang, TM)); + + switch (F->getLinkage()) { + default: llvm_unreachable("Unknown linkage type!"); + case Function::PrivateLinkage: + case Function::InternalLinkage: // Symbols default to internal. + break; + case Function::ExternalLinkage: + O << "\t.globl\t" << CurrentFnName << '\n'; + break; + case Function::WeakAnyLinkage: + case Function::WeakODRLinkage: + case Function::LinkOnceAnyLinkage: + case Function::LinkOnceODRLinkage: + case Function::LinkerPrivateLinkage: + O << "\t.globl\t" << CurrentFnName << '\n'; + O << "\t.weak_definition\t" << CurrentFnName << '\n'; + break; + } + + printVisibility(CurrentFnName, F->getVisibility()); + + EmitAlignment(MF.getAlignment(), F); + O << CurrentFnName << ":\n"; + + // Emit pre-function debug information. + DW->BeginFunction(&MF); + + // If the function is empty, then we need to emit *something*. Otherwise, the + // function's label might be associated with something that it wasn't meant to + // be associated with. We emit a noop in this situation. + MachineFunction::iterator I = MF.begin(); + + if (++I == MF.end() && MF.front().empty()) + O << "\tnop\n"; + + // Print out code for the function. + for (MachineFunction::const_iterator I = MF.begin(), E = MF.end(); + I != E; ++I) { + // Print a label for the basic block. + if (I != MF.begin()) { + EmitBasicBlockStart(I); + } + for (MachineBasicBlock::const_iterator II = I->begin(), IE = I->end(); + II != IE; ++II) { + // Print the assembly for the instruction. + printMachineInstruction(II); + } + } + + // Emit post-function debug information. + DW->EndFunction(&MF); + + // Print out jump tables referenced by the function. + EmitJumpTableInfo(MF.getJumpTableInfo(), MF); + + // We didn't modify anything. + return false; +} + + +void PPCDarwinAsmPrinter::EmitStartOfAsmFile(Module &M) { + static const char *const CPUDirectives[] = { + "", + "ppc", + "ppc601", + "ppc602", + "ppc603", + "ppc7400", + "ppc750", + "ppc970", + "ppc64" + }; + + unsigned Directive = Subtarget.getDarwinDirective(); + if (Subtarget.isGigaProcessor() && Directive < PPC::DIR_970) + Directive = PPC::DIR_970; + if (Subtarget.hasAltivec() && Directive < PPC::DIR_7400) + Directive = PPC::DIR_7400; + if (Subtarget.isPPC64() && Directive < PPC::DIR_970) + Directive = PPC::DIR_64; + assert(Directive <= PPC::DIR_64 && "Directive out of range."); + O << "\t.machine " << CPUDirectives[Directive] << '\n'; + + // Prime text sections so they are adjacent. This reduces the likelihood a + // large data or debug section causes a branch to exceed 16M limit. + TargetLoweringObjectFileMachO &TLOFMacho = + static_cast(getObjFileLowering()); + OutStreamer.SwitchSection(TLOFMacho.getTextCoalSection()); + if (TM.getRelocationModel() == Reloc::PIC_) { + OutStreamer.SwitchSection( + TLOFMacho.getMachOSection("__TEXT", "__picsymbolstub1", + MCSectionMachO::S_SYMBOL_STUBS | + MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS, + 32, SectionKind::getText())); + } else if (TM.getRelocationModel() == Reloc::DynamicNoPIC) { + OutStreamer.SwitchSection( + TLOFMacho.getMachOSection("__TEXT","__symbol_stub1", + MCSectionMachO::S_SYMBOL_STUBS | + MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS, + 16, SectionKind::getText())); + } + OutStreamer.SwitchSection(getObjFileLowering().getTextSection()); +} + +void PPCDarwinAsmPrinter::PrintGlobalVariable(const GlobalVariable *GVar) { + const TargetData *TD = TM.getTargetData(); + + if (!GVar->hasInitializer()) + return; // External global require no code + + // Check to see if this is a special global used by LLVM, if so, emit it. + if (EmitSpecialLLVMGlobal(GVar)) { + if (TM.getRelocationModel() == Reloc::Static) { + if (GVar->getName() == "llvm.global_ctors") + O << ".reference .constructors_used\n"; + else if (GVar->getName() == "llvm.global_dtors") + O << ".reference .destructors_used\n"; + } + return; + } + + std::string name = Mang->getMangledName(GVar); + printVisibility(name, GVar->getVisibility()); + + Constant *C = GVar->getInitializer(); + const Type *Type = C->getType(); + unsigned Size = TD->getTypeAllocSize(Type); + unsigned Align = TD->getPreferredAlignmentLog(GVar); + + const MCSection *TheSection = + getObjFileLowering().SectionForGlobal(GVar, Mang, TM); + OutStreamer.SwitchSection(TheSection); + + /// FIXME: Drive this off the section! + if (C->isNullValue() && /* FIXME: Verify correct */ + !GVar->hasSection() && + (GVar->hasLocalLinkage() || GVar->hasExternalLinkage() || + GVar->isWeakForLinker()) && + // Don't put things that should go in the cstring section into "comm". + !TheSection->getKind().isMergeableCString()) { + if (Size == 0) Size = 1; // .comm Foo, 0 is undefined, avoid it. + + if (GVar->hasExternalLinkage()) { + O << "\t.globl " << name << '\n'; + O << "\t.zerofill __DATA, __common, " << name << ", " + << Size << ", " << Align; + } else if (GVar->hasLocalLinkage()) { + O << MAI->getLCOMMDirective() << name << ',' << Size << ',' << Align; + } else if (!GVar->hasCommonLinkage()) { + O << "\t.globl " << name << '\n' + << MAI->getWeakDefDirective() << name << '\n'; + EmitAlignment(Align, GVar); + O << name << ":"; + if (VerboseAsm) { + O << "\t\t\t\t" << MAI->getCommentString() << " "; + WriteAsOperand(O, GVar, /*PrintType=*/false, GVar->getParent()); + } + O << '\n'; + EmitGlobalConstant(C); + return; + } else { + O << ".comm " << name << ',' << Size; + // Darwin 9 and above support aligned common data. + if (Subtarget.isDarwin9()) + O << ',' << Align; + } + if (VerboseAsm) { + O << "\t\t" << MAI->getCommentString() << " '"; + WriteAsOperand(O, GVar, /*PrintType=*/false, GVar->getParent()); + O << "'"; + } + O << '\n'; + return; + } + + switch (GVar->getLinkage()) { + case GlobalValue::LinkOnceAnyLinkage: + case GlobalValue::LinkOnceODRLinkage: + case GlobalValue::WeakAnyLinkage: + case GlobalValue::WeakODRLinkage: + case GlobalValue::CommonLinkage: + case GlobalValue::LinkerPrivateLinkage: + O << "\t.globl " << name << '\n' + << "\t.weak_definition " << name << '\n'; + break; + case GlobalValue::AppendingLinkage: + // FIXME: appending linkage variables should go into a section of + // their name or something. For now, just emit them as external. + case GlobalValue::ExternalLinkage: + // If external or appending, declare as a global symbol + O << "\t.globl " << name << '\n'; + // FALL THROUGH + case GlobalValue::InternalLinkage: + case GlobalValue::PrivateLinkage: + break; + default: + llvm_unreachable("Unknown linkage type!"); + } + + EmitAlignment(Align, GVar); + O << name << ":"; + if (VerboseAsm) { + O << "\t\t\t\t" << MAI->getCommentString() << " '"; + WriteAsOperand(O, GVar, /*PrintType=*/false, GVar->getParent()); + O << "'"; + } + O << '\n'; + + EmitGlobalConstant(C); + O << '\n'; +} + +bool PPCDarwinAsmPrinter::doFinalization(Module &M) { + const TargetData *TD = TM.getTargetData(); + + bool isPPC64 = TD->getPointerSizeInBits() == 64; + + // Darwin/PPC always uses mach-o. + TargetLoweringObjectFileMachO &TLOFMacho = + static_cast(getObjFileLowering()); + + + const MCSection *LSPSection = 0; + if (!FnStubs.empty()) // .lazy_symbol_pointer + LSPSection = TLOFMacho.getLazySymbolPointerSection(); + + + // Output stubs for dynamically-linked functions + if (TM.getRelocationModel() == Reloc::PIC_ && !FnStubs.empty()) { + const MCSection *StubSection = + TLOFMacho.getMachOSection("__TEXT", "__picsymbolstub1", + MCSectionMachO::S_SYMBOL_STUBS | + MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS, + 32, SectionKind::getText()); + for (StringMap::iterator I = FnStubs.begin(), E = FnStubs.end(); + I != E; ++I) { + OutStreamer.SwitchSection(StubSection); + EmitAlignment(4); + const FnStubInfo &Info = I->second; + O << Info.Stub << ":\n"; + O << "\t.indirect_symbol " << I->getKeyData() << '\n'; + O << "\tmflr r0\n"; + O << "\tbcl 20,31," << Info.AnonSymbol << '\n'; + O << Info.AnonSymbol << ":\n"; + O << "\tmflr r11\n"; + O << "\taddis r11,r11,ha16(" << Info.LazyPtr << "-" << Info.AnonSymbol; + O << ")\n"; + O << "\tmtlr r0\n"; + O << (isPPC64 ? "\tldu" : "\tlwzu") << " r12,lo16("; + O << Info.LazyPtr << "-" << Info.AnonSymbol << ")(r11)\n"; + O << "\tmtctr r12\n"; + O << "\tbctr\n"; + + OutStreamer.SwitchSection(LSPSection); + O << Info.LazyPtr << ":\n"; + O << "\t.indirect_symbol " << I->getKeyData() << '\n'; + O << (isPPC64 ? "\t.quad" : "\t.long") << " dyld_stub_binding_helper\n"; + } + } else if (!FnStubs.empty()) { + const MCSection *StubSection = + TLOFMacho.getMachOSection("__TEXT","__symbol_stub1", + MCSectionMachO::S_SYMBOL_STUBS | + MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS, + 16, SectionKind::getText()); + + for (StringMap::iterator I = FnStubs.begin(), E = FnStubs.end(); + I != E; ++I) { + OutStreamer.SwitchSection(StubSection); + EmitAlignment(4); + const FnStubInfo &Info = I->second; + O << Info.Stub << ":\n"; + O << "\t.indirect_symbol " << I->getKeyData() << '\n'; + O << "\tlis r11,ha16(" << Info.LazyPtr << ")\n"; + O << (isPPC64 ? "\tldu" : "\tlwzu") << " r12,lo16("; + O << Info.LazyPtr << ")(r11)\n"; + O << "\tmtctr r12\n"; + O << "\tbctr\n"; + OutStreamer.SwitchSection(LSPSection); + O << Info.LazyPtr << ":\n"; + O << "\t.indirect_symbol " << I->getKeyData() << '\n'; + O << (isPPC64 ? "\t.quad" : "\t.long") << " dyld_stub_binding_helper\n"; + } + } + + O << '\n'; + + if (MAI->doesSupportExceptionHandling() && MMI) { + // Add the (possibly multiple) personalities to the set of global values. + // Only referenced functions get into the Personalities list. + const std::vector &Personalities = MMI->getPersonalities(); + for (std::vector::const_iterator I = Personalities.begin(), + E = Personalities.end(); I != E; ++I) { + if (*I) + GVStubs[Mang->getMangledName(*I)] = + Mang->getMangledName(*I, "$non_lazy_ptr", true); + } + } + + // Output macho stubs for external and common global variables. + if (!GVStubs.empty()) { + // Switch with ".non_lazy_symbol_pointer" directive. + OutStreamer.SwitchSection(TLOFMacho.getNonLazySymbolPointerSection()); + EmitAlignment(isPPC64 ? 3 : 2); + + for (StringMap::iterator I = GVStubs.begin(), + E = GVStubs.end(); I != E; ++I) { + O << I->second << ":\n"; + O << "\t.indirect_symbol " << I->getKeyData() << '\n'; + O << (isPPC64 ? "\t.quad\t0\n" : "\t.long\t0\n"); + } + } + + if (!HiddenGVStubs.empty()) { + OutStreamer.SwitchSection(getObjFileLowering().getDataSection()); + EmitAlignment(isPPC64 ? 3 : 2); + for (StringMap::iterator I = HiddenGVStubs.begin(), + E = HiddenGVStubs.end(); I != E; ++I) { + O << I->second << ":\n"; + O << (isPPC64 ? "\t.quad\t" : "\t.long\t") << I->getKeyData() << '\n'; + } + } + + // Funny Darwin hack: This flag tells the linker that no global symbols + // contain code that falls through to other global symbols (e.g. the obvious + // implementation of multiple entry points). If this doesn't occur, the + // linker can safely perform dead code stripping. Since LLVM never generates + // code that does this, it is always safe to set. + OutStreamer.EmitAssemblerFlag(MCStreamer::SubsectionsViaSymbols); + + return AsmPrinter::doFinalization(M); +} + + + +/// createPPCAsmPrinterPass - Returns a pass that prints the PPC assembly code +/// for a MachineFunction to the given output stream, in a format that the +/// Darwin assembler can deal with. +/// +static AsmPrinter *createPPCAsmPrinterPass(formatted_raw_ostream &o, + TargetMachine &tm, + const MCAsmInfo *tai, + bool verbose) { + const PPCSubtarget *Subtarget = &tm.getSubtarget(); + + if (Subtarget->isDarwin()) + return new PPCDarwinAsmPrinter(o, tm, tai, verbose); + return new PPCLinuxAsmPrinter(o, tm, tai, verbose); +} + +// Force static initialization. +extern "C" void LLVMInitializePowerPCAsmPrinter() { + TargetRegistry::RegisterAsmPrinter(ThePPC32Target, createPPCAsmPrinterPass); + TargetRegistry::RegisterAsmPrinter(ThePPC64Target, createPPCAsmPrinterPass); +} diff --git a/libclamav/c++/llvm/lib/Target/PowerPC/CMakeLists.txt b/libclamav/c++/llvm/lib/Target/PowerPC/CMakeLists.txt new file mode 100644 index 000000000..bdd6d3623 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/PowerPC/CMakeLists.txt @@ -0,0 +1,30 @@ +set(LLVM_TARGET_DEFINITIONS PPC.td) + +tablegen(PPCGenInstrNames.inc -gen-instr-enums) +tablegen(PPCGenRegisterNames.inc -gen-register-enums) +tablegen(PPCGenAsmWriter.inc -gen-asm-writer) +tablegen(PPCGenCodeEmitter.inc -gen-emitter) +tablegen(PPCGenRegisterInfo.h.inc -gen-register-desc-header) +tablegen(PPCGenRegisterInfo.inc -gen-register-desc) +tablegen(PPCGenInstrInfo.inc -gen-instr-desc) +tablegen(PPCGenDAGISel.inc -gen-dag-isel) +tablegen(PPCGenCallingConv.inc -gen-callingconv) +tablegen(PPCGenSubtarget.inc -gen-subtarget) + +add_llvm_target(PowerPCCodeGen + PPCBranchSelector.cpp + PPCCodeEmitter.cpp + PPCHazardRecognizers.cpp + PPCInstrInfo.cpp + PPCISelDAGToDAG.cpp + PPCISelLowering.cpp + PPCJITInfo.cpp + PPCMachOWriterInfo.cpp + PPCMCAsmInfo.cpp + PPCPredicates.cpp + PPCRegisterInfo.cpp + PPCSubtarget.cpp + PPCTargetMachine.cpp + ) + +target_link_libraries (LLVMPowerPCCodeGen LLVMSelectionDAG) diff --git a/libclamav/c++/llvm/lib/Target/PowerPC/Makefile b/libclamav/c++/llvm/lib/Target/PowerPC/Makefile new file mode 100644 index 000000000..4015d4aa1 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/PowerPC/Makefile @@ -0,0 +1,22 @@ +##===- lib/Target/PowerPC/Makefile -------------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## +LEVEL = ../../.. +LIBRARYNAME = LLVMPowerPCCodeGen +TARGET = PPC + +# Make sure that tblgen is run, first thing. +BUILT_SOURCES = PPCGenInstrNames.inc PPCGenRegisterNames.inc \ + PPCGenAsmWriter.inc PPCGenCodeEmitter.inc \ + PPCGenRegisterInfo.h.inc PPCGenRegisterInfo.inc \ + PPCGenInstrInfo.inc PPCGenDAGISel.inc \ + PPCGenSubtarget.inc PPCGenCallingConv.inc + +DIRS = AsmPrinter TargetInfo + +include $(LEVEL)/Makefile.common diff --git a/libclamav/c++/llvm/lib/Target/PowerPC/PPC.h b/libclamav/c++/llvm/lib/Target/PowerPC/PPC.h new file mode 100644 index 000000000..7b98268bd --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/PowerPC/PPC.h @@ -0,0 +1,53 @@ +//===-- PPC.h - Top-level interface for PowerPC Target ----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the entry points for global functions defined in the LLVM +// PowerPC back-end. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TARGET_POWERPC_H +#define LLVM_TARGET_POWERPC_H + +// GCC #defines PPC on Linux but we use it as our namespace name +#undef PPC + +#include "llvm/Target/TargetMachine.h" + +namespace llvm { + class PPCTargetMachine; + class FunctionPass; + class MachineCodeEmitter; + class ObjectCodeEmitter; + class formatted_raw_ostream; + +FunctionPass *createPPCBranchSelectionPass(); +FunctionPass *createPPCISelDag(PPCTargetMachine &TM); +FunctionPass *createPPCCodeEmitterPass(PPCTargetMachine &TM, + MachineCodeEmitter &MCE); +FunctionPass *createPPCJITCodeEmitterPass(PPCTargetMachine &TM, + JITCodeEmitter &MCE); +FunctionPass *createPPCObjectCodeEmitterPass(PPCTargetMachine &TM, + ObjectCodeEmitter &OCE); + +extern Target ThePPC32Target; +extern Target ThePPC64Target; + +} // end namespace llvm; + +// Defines symbolic names for PowerPC registers. This defines a mapping from +// register name to register number. +// +#include "PPCGenRegisterNames.inc" + +// Defines symbolic names for the PowerPC instructions. +// +#include "PPCGenInstrNames.inc" + +#endif diff --git a/libclamav/c++/llvm/lib/Target/PowerPC/PPC.td b/libclamav/c++/llvm/lib/Target/PowerPC/PPC.td new file mode 100644 index 000000000..08f5bb430 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/PowerPC/PPC.td @@ -0,0 +1,114 @@ +//===- PPC.td - Describe the PowerPC Target Machine --------*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This is the top level entry point for the PowerPC target. +// +//===----------------------------------------------------------------------===// + +// Get the target-independent interfaces which we are implementing. +// +include "llvm/Target/Target.td" + +//===----------------------------------------------------------------------===// +// PowerPC Subtarget features. +// + +//===----------------------------------------------------------------------===// +// CPU Directives // +//===----------------------------------------------------------------------===// + +def Directive601 : SubtargetFeature<"", "DarwinDirective", "PPC::DIR_601", "">; +def Directive602 : SubtargetFeature<"", "DarwinDirective", "PPC::DIR_602", "">; +def Directive603 : SubtargetFeature<"", "DarwinDirective", "PPC::DIR_603", "">; +def Directive604 : SubtargetFeature<"", "DarwinDirective", "PPC::DIR_603", "">; +def Directive620 : SubtargetFeature<"", "DarwinDirective", "PPC::DIR_603", "">; +def Directive7400: SubtargetFeature<"", "DarwinDirective", "PPC::DIR_7400", "">; +def Directive750 : SubtargetFeature<"", "DarwinDirective", "PPC::DIR_750", "">; +def Directive970 : SubtargetFeature<"", "DarwinDirective", "PPC::DIR_970", "">; +def Directive32 : SubtargetFeature<"", "DarwinDirective", "PPC::DIR_32", "">; +def Directive64 : SubtargetFeature<"", "DarwinDirective", "PPC::DIR_64", "">; + +def Feature64Bit : SubtargetFeature<"64bit","Has64BitSupport", "true", + "Enable 64-bit instructions">; +def Feature64BitRegs : SubtargetFeature<"64bitregs","Use64BitRegs", "true", + "Enable 64-bit registers usage for ppc32 [beta]">; +def FeatureAltivec : SubtargetFeature<"altivec","HasAltivec", "true", + "Enable Altivec instructions">; +def FeatureGPUL : SubtargetFeature<"gpul","IsGigaProcessor", "true", + "Enable GPUL instructions">; +def FeatureFSqrt : SubtargetFeature<"fsqrt","HasFSQRT", "true", + "Enable the fsqrt instruction">; +def FeatureSTFIWX : SubtargetFeature<"stfiwx","HasSTFIWX", "true", + "Enable the stfiwx instruction">; + +//===----------------------------------------------------------------------===// +// Register File Description +//===----------------------------------------------------------------------===// + +include "PPCRegisterInfo.td" +include "PPCSchedule.td" +include "PPCInstrInfo.td" + +//===----------------------------------------------------------------------===// +// PowerPC processors supported. +// + +def : Processor<"generic", G3Itineraries, [Directive32]>; +def : Processor<"601", G3Itineraries, [Directive601]>; +def : Processor<"602", G3Itineraries, [Directive602]>; +def : Processor<"603", G3Itineraries, [Directive603]>; +def : Processor<"603e", G3Itineraries, [Directive603]>; +def : Processor<"603ev", G3Itineraries, [Directive603]>; +def : Processor<"604", G3Itineraries, [Directive604]>; +def : Processor<"604e", G3Itineraries, [Directive604]>; +def : Processor<"620", G3Itineraries, [Directive620]>; +def : Processor<"g3", G3Itineraries, [Directive7400]>; +def : Processor<"7400", G4Itineraries, [Directive7400, FeatureAltivec]>; +def : Processor<"g4", G4Itineraries, [Directive7400, FeatureAltivec]>; +def : Processor<"7450", G4PlusItineraries, [Directive7400, FeatureAltivec]>; +def : Processor<"g4+", G4PlusItineraries, [Directive750, FeatureAltivec]>; +def : Processor<"750", G4Itineraries, [Directive750, FeatureAltivec]>; +def : Processor<"970", G5Itineraries, + [Directive970, FeatureAltivec, + FeatureGPUL, FeatureFSqrt, FeatureSTFIWX, + Feature64Bit /*, Feature64BitRegs */]>; +def : Processor<"g5", G5Itineraries, + [Directive970, FeatureAltivec, + FeatureGPUL, FeatureFSqrt, FeatureSTFIWX, + Feature64Bit /*, Feature64BitRegs */]>; +def : Processor<"ppc", G3Itineraries, [Directive32]>; +def : Processor<"ppc64", G5Itineraries, + [Directive64, FeatureAltivec, + FeatureGPUL, FeatureFSqrt, FeatureSTFIWX, + Feature64Bit /*, Feature64BitRegs */]>; + + +//===----------------------------------------------------------------------===// +// Calling Conventions +//===----------------------------------------------------------------------===// + +include "PPCCallingConv.td" + +def PPCInstrInfo : InstrInfo { + // Define how we want to layout our TargetSpecific information field... This + // should be kept up-to-date with the fields in the PPCInstrInfo.h file. + let TSFlagsFields = ["PPC970_First", + "PPC970_Single", + "PPC970_Cracked", + "PPC970_Unit"]; + let TSFlagsShifts = [0, 1, 2, 3]; + + let isLittleEndianEncoding = 1; +} + + +def PPC : Target { + // Information about the instructions. + let InstructionSet = PPCInstrInfo; +} diff --git a/libclamav/c++/llvm/lib/Target/PowerPC/PPCBranchSelector.cpp b/libclamav/c++/llvm/lib/Target/PowerPC/PPCBranchSelector.cpp new file mode 100644 index 000000000..a75242158 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/PowerPC/PPCBranchSelector.cpp @@ -0,0 +1,173 @@ +//===-- PPCBranchSelector.cpp - Emit long conditional branches-----*- C++ -*-=// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains a pass that scans a machine function to determine which +// conditional branches need more than 16 bits of displacement to reach their +// target basic block. It does this in two passes; a calculation of basic block +// positions pass, and a branch psuedo op to machine branch opcode pass. This +// pass should be run last, just before the assembly printer. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "ppc-branch-select" +#include "PPC.h" +#include "PPCInstrBuilder.h" +#include "PPCInstrInfo.h" +#include "PPCPredicates.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/Support/MathExtras.h" +using namespace llvm; + +STATISTIC(NumExpanded, "Number of branches expanded to long format"); + +namespace { + struct PPCBSel : public MachineFunctionPass { + static char ID; + PPCBSel() : MachineFunctionPass(&ID) {} + + /// BlockSizes - The sizes of the basic blocks in the function. + std::vector BlockSizes; + + virtual bool runOnMachineFunction(MachineFunction &Fn); + + virtual const char *getPassName() const { + return "PowerPC Branch Selector"; + } + }; + char PPCBSel::ID = 0; +} + +/// createPPCBranchSelectionPass - returns an instance of the Branch Selection +/// Pass +/// +FunctionPass *llvm::createPPCBranchSelectionPass() { + return new PPCBSel(); +} + +bool PPCBSel::runOnMachineFunction(MachineFunction &Fn) { + const TargetInstrInfo *TII = Fn.getTarget().getInstrInfo(); + // Give the blocks of the function a dense, in-order, numbering. + Fn.RenumberBlocks(); + BlockSizes.resize(Fn.getNumBlockIDs()); + + // Measure each MBB and compute a size for the entire function. + unsigned FuncSize = 0; + for (MachineFunction::iterator MFI = Fn.begin(), E = Fn.end(); MFI != E; + ++MFI) { + MachineBasicBlock *MBB = MFI; + + unsigned BlockSize = 0; + for (MachineBasicBlock::iterator MBBI = MBB->begin(), EE = MBB->end(); + MBBI != EE; ++MBBI) + BlockSize += TII->GetInstSizeInBytes(MBBI); + + BlockSizes[MBB->getNumber()] = BlockSize; + FuncSize += BlockSize; + } + + // If the entire function is smaller than the displacement of a branch field, + // we know we don't need to shrink any branches in this function. This is a + // common case. + if (FuncSize < (1 << 15)) { + BlockSizes.clear(); + return false; + } + + // For each conditional branch, if the offset to its destination is larger + // than the offset field allows, transform it into a long branch sequence + // like this: + // short branch: + // bCC MBB + // long branch: + // b!CC $PC+8 + // b MBB + // + bool MadeChange = true; + bool EverMadeChange = false; + while (MadeChange) { + // Iteratively expand branches until we reach a fixed point. + MadeChange = false; + + for (MachineFunction::iterator MFI = Fn.begin(), E = Fn.end(); MFI != E; + ++MFI) { + MachineBasicBlock &MBB = *MFI; + unsigned MBBStartOffset = 0; + for (MachineBasicBlock::iterator I = MBB.begin(), E = MBB.end(); + I != E; ++I) { + if (I->getOpcode() != PPC::BCC || I->getOperand(2).isImm()) { + MBBStartOffset += TII->GetInstSizeInBytes(I); + continue; + } + + // Determine the offset from the current branch to the destination + // block. + MachineBasicBlock *Dest = I->getOperand(2).getMBB(); + + int BranchSize; + if (Dest->getNumber() <= MBB.getNumber()) { + // If this is a backwards branch, the delta is the offset from the + // start of this block to this branch, plus the sizes of all blocks + // from this block to the dest. + BranchSize = MBBStartOffset; + + for (unsigned i = Dest->getNumber(), e = MBB.getNumber(); i != e; ++i) + BranchSize += BlockSizes[i]; + } else { + // Otherwise, add the size of the blocks between this block and the + // dest to the number of bytes left in this block. + BranchSize = -MBBStartOffset; + + for (unsigned i = MBB.getNumber(), e = Dest->getNumber(); i != e; ++i) + BranchSize += BlockSizes[i]; + } + + // If this branch is in range, ignore it. + if (isInt16(BranchSize)) { + MBBStartOffset += 4; + continue; + } + + // Otherwise, we have to expand it to a long branch. + // The BCC operands are: + // 0. PPC branch predicate + // 1. CR register + // 2. Target MBB + PPC::Predicate Pred = (PPC::Predicate)I->getOperand(0).getImm(); + unsigned CRReg = I->getOperand(1).getReg(); + + MachineInstr *OldBranch = I; + DebugLoc dl = OldBranch->getDebugLoc(); + + // Jump over the uncond branch inst (i.e. $PC+8) on opposite condition. + BuildMI(MBB, I, dl, TII->get(PPC::BCC)) + .addImm(PPC::InvertPredicate(Pred)).addReg(CRReg).addImm(2); + + // Uncond branch to the real destination. + I = BuildMI(MBB, I, dl, TII->get(PPC::B)).addMBB(Dest); + + // Remove the old branch from the function. + OldBranch->eraseFromParent(); + + // Remember that this instruction is 8-bytes, increase the size of the + // block by 4, remember to iterate. + BlockSizes[MBB.getNumber()] += 4; + MBBStartOffset += 8; + ++NumExpanded; + MadeChange = true; + } + } + EverMadeChange |= MadeChange; + } + + BlockSizes.clear(); + return true; +} + diff --git a/libclamav/c++/llvm/lib/Target/PowerPC/PPCCallingConv.td b/libclamav/c++/llvm/lib/Target/PowerPC/PPCCallingConv.td new file mode 100644 index 000000000..c7ce171da --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/PowerPC/PPCCallingConv.td @@ -0,0 +1,147 @@ +//===- PPCCallingConv.td - Calling Conventions for PowerPC ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This describes the calling conventions for the PowerPC 32- and 64-bit +// architectures. +// +//===----------------------------------------------------------------------===// + +/// CCIfSubtarget - Match if the current subtarget has a feature F. +class CCIfSubtarget + : CCIf().", F), A>; + +//===----------------------------------------------------------------------===// +// Return Value Calling Convention +//===----------------------------------------------------------------------===// + +// Return-value convention for PowerPC +def RetCC_PPC : CallingConv<[ + CCIfType<[i32], CCAssignToReg<[R3, R4, R5, R6, R7, R8, R9, R10]>>, + CCIfType<[i64], CCAssignToReg<[X3, X4, X5, X6]>>, + + CCIfType<[f32], CCAssignToReg<[F1]>>, + CCIfType<[f64], CCAssignToReg<[F1, F2]>>, + + // Vector types are always returned in V2. + CCIfType<[v16i8, v8i16, v4i32, v4f32], CCAssignToReg<[V2]>> +]>; + + +//===----------------------------------------------------------------------===// +// PowerPC Argument Calling Conventions +//===----------------------------------------------------------------------===// +/* +def CC_PPC : CallingConv<[ + // The first 8 integer arguments are passed in integer registers. + CCIfType<[i32], CCAssignToReg<[R3, R4, R5, R6, R7, R8, R9, R10]>>, + CCIfType<[i64], CCAssignToReg<[X3, X4, X5, X6, X7, X8, X9, X10]>>, + + // Common sub-targets passes FP values in F1 - F13 + CCIfType<[f32, f64], + CCAssignToReg<[F1, F2, F3, F4, F5, F6, F7, F8,F9,F10,F11,F12,F13]>>, + + // The first 12 Vector arguments are passed in altivec registers. + CCIfType<[v16i8, v8i16, v4i32, v4f32], + CCAssignToReg<[V2, V3, V4, V5, V6, V7, V8, V9, V10,V11,V12,V13]>> + +/* + // Integer/FP values get stored in stack slots that are 8 bytes in size and + // 8-byte aligned if there are no more registers to hold them. + CCIfType<[i32, i64, f32, f64], CCAssignToStack<8, 8>>, + + // Vectors get 16-byte stack slots that are 16-byte aligned. + CCIfType<[v16i8, v8i16, v4i32, v2i64, v4f32, v2f64], + CCAssignToStack<16, 16>>*/ +]>; + +*/ + +//===----------------------------------------------------------------------===// +// PowerPC System V Release 4 ABI +//===----------------------------------------------------------------------===// + +// _Complex arguments are never split, thus their two scalars are either +// passed both in argument registers or both on the stack. Also _Complex +// arguments are always passed in general purpose registers, never in +// Floating-point registers or vector registers. Arguments which should go +// on the stack are marked with the inreg parameter attribute. +// Giving inreg this target-dependent (and counter-intuitive) meaning +// simplifies things, because functions calls are not always coming from the +// frontend but are also created implicitly e.g. for libcalls. If inreg would +// actually mean that the argument is passed in a register, then all places +// which create function calls/function definitions implicitly would need to +// be aware of this fact and would need to mark arguments accordingly. With +// inreg meaning that the argument is passed on the stack, this is not an +// issue, except for calls which involve _Complex types. + +def CC_PPC_SVR4_Common : CallingConv<[ + // The ABI requires i64 to be passed in two adjacent registers with the first + // register having an odd register number. + CCIfType<[i32], CCIfSplit>>, + + // The first 8 integer arguments are passed in integer registers. + CCIfType<[i32], CCIf<"!ArgFlags.isInReg()", + CCAssignToReg<[R3, R4, R5, R6, R7, R8, R9, R10]>>>, + + // Make sure the i64 words from a long double are either both passed in + // registers or both passed on the stack. + CCIfType<[f64], CCIfSplit>>, + + // FP values are passed in F1 - F8. + CCIfType<[f32, f64], CCAssignToReg<[F1, F2, F3, F4, F5, F6, F7, F8]>>, + + // Split arguments have an alignment of 8 bytes on the stack. + CCIfType<[i32], CCIfSplit>>, + + CCIfType<[i32], CCAssignToStack<4, 4>>, + + // Floats are stored in double precision format, thus they have the same + // alignment and size as doubles. + CCIfType<[f32,f64], CCAssignToStack<8, 8>>, + + // Vectors get 16-byte stack slots that are 16-byte aligned. + CCIfType<[v16i8, v8i16, v4i32, v4f32], CCAssignToStack<16, 16>> +]>; + +// This calling convention puts vector arguments always on the stack. It is used +// to assign vector arguments which belong to the variable portion of the +// parameter list of a variable argument function. +def CC_PPC_SVR4_VarArg : CallingConv<[ + CCDelegateTo +]>; + +// In contrast to CC_PPC_SVR4_VarArg, this calling convention first tries to put +// vector arguments in vector registers before putting them on the stack. +def CC_PPC_SVR4 : CallingConv<[ + // The first 12 Vector arguments are passed in AltiVec registers. + CCIfType<[v16i8, v8i16, v4i32, v4f32], + CCAssignToReg<[V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13]>>, + + CCDelegateTo +]>; + +// Helper "calling convention" to handle aggregate by value arguments. +// Aggregate by value arguments are always placed in the local variable space +// of the caller. This calling convention is only used to assign those stack +// offsets in the callers stack frame. +// +// Still, the address of the aggregate copy in the callers stack frame is passed +// in a GPR (or in the parameter list area if all GPRs are allocated) from the +// caller to the callee. The location for the address argument is assigned by +// the CC_PPC_SVR4 calling convention. +// +// The only purpose of CC_PPC_SVR4_Custom_Dummy is to skip arguments which are +// not passed by value. + +def CC_PPC_SVR4_ByVal : CallingConv<[ + CCIfByVal>, + + CCCustom<"CC_PPC_SVR4_Custom_Dummy"> +]>; + diff --git a/libclamav/c++/llvm/lib/Target/PowerPC/PPCCodeEmitter.cpp b/libclamav/c++/llvm/lib/Target/PowerPC/PPCCodeEmitter.cpp new file mode 100644 index 000000000..da9ea3617 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/PowerPC/PPCCodeEmitter.cpp @@ -0,0 +1,277 @@ +//===-- PPCCodeEmitter.cpp - JIT Code Emitter for PowerPC32 -------*- 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 the PowerPC 32-bit CodeEmitter and associated machinery to +// JIT-compile bitcode to native PowerPC. +// +//===----------------------------------------------------------------------===// + +#include "PPCTargetMachine.h" +#include "PPCRelocations.h" +#include "PPC.h" +#include "llvm/Module.h" +#include "llvm/PassManager.h" +#include "llvm/CodeGen/MachineCodeEmitter.h" +#include "llvm/CodeGen/JITCodeEmitter.h" +#include "llvm/CodeGen/ObjectCodeEmitter.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Target/TargetOptions.h" +using namespace llvm; + +namespace { + class PPCCodeEmitter { + TargetMachine &TM; + MachineCodeEmitter &MCE; + public: + PPCCodeEmitter(TargetMachine &tm, MachineCodeEmitter &mce): + TM(tm), MCE(mce) {} + + /// getBinaryCodeForInstr - This function, generated by the + /// CodeEmitterGenerator using TableGen, produces the binary encoding for + /// machine instructions. + + unsigned getBinaryCodeForInstr(const MachineInstr &MI); + + /// getMachineOpValue - evaluates the MachineOperand of a given MachineInstr + + unsigned getMachineOpValue(const MachineInstr &MI, + const MachineOperand &MO); + + /// MovePCtoLROffset - When/if we see a MovePCtoLR instruction, we record + /// its address in the function into this pointer. + + void *MovePCtoLROffset; + }; + + template + class Emitter : public MachineFunctionPass, public PPCCodeEmitter { + TargetMachine &TM; + CodeEmitter &MCE; + + void getAnalysisUsage(AnalysisUsage &AU) const { + AU.addRequired(); + MachineFunctionPass::getAnalysisUsage(AU); + } + + public: + static char ID; + Emitter(TargetMachine &tm, CodeEmitter &mce) + : MachineFunctionPass(&ID), PPCCodeEmitter(tm, mce), TM(tm), MCE(mce) {} + + const char *getPassName() const { return "PowerPC Machine Code Emitter"; } + + /// runOnMachineFunction - emits the given MachineFunction to memory + /// + bool runOnMachineFunction(MachineFunction &MF); + + /// emitBasicBlock - emits the given MachineBasicBlock to memory + /// + void emitBasicBlock(MachineBasicBlock &MBB); + + /// getValueBit - return the particular bit of Val + /// + unsigned getValueBit(int64_t Val, unsigned bit) { return (Val >> bit) & 1; } + }; + + template + char Emitter::ID = 0; +} + +/// createPPCCodeEmitterPass - Return a pass that emits the collected PPC code +/// to the specified MCE object. + +FunctionPass *llvm::createPPCCodeEmitterPass(PPCTargetMachine &TM, + MachineCodeEmitter &MCE) { + return new Emitter(TM, MCE); +} + +FunctionPass *llvm::createPPCJITCodeEmitterPass(PPCTargetMachine &TM, + JITCodeEmitter &JCE) { + return new Emitter(TM, JCE); +} + +FunctionPass *llvm::createPPCObjectCodeEmitterPass(PPCTargetMachine &TM, + ObjectCodeEmitter &OCE) { + return new Emitter(TM, OCE); +} + +template +bool Emitter::runOnMachineFunction(MachineFunction &MF) { + assert((MF.getTarget().getRelocationModel() != Reloc::Default || + MF.getTarget().getRelocationModel() != Reloc::Static) && + "JIT relocation model must be set to static or default!"); + + MCE.setModuleInfo(&getAnalysis()); + do { + MovePCtoLROffset = 0; + MCE.startFunction(MF); + for (MachineFunction::iterator BB = MF.begin(), E = MF.end(); BB != E; ++BB) + emitBasicBlock(*BB); + } while (MCE.finishFunction(MF)); + + return false; +} + +template +void Emitter::emitBasicBlock(MachineBasicBlock &MBB) { + MCE.StartMachineBasicBlock(&MBB); + + for (MachineBasicBlock::iterator I = MBB.begin(), E = MBB.end(); I != E; ++I){ + const MachineInstr &MI = *I; + MCE.processDebugLoc(MI.getDebugLoc(), true); + switch (MI.getOpcode()) { + default: + MCE.emitWordBE(getBinaryCodeForInstr(MI)); + break; + case TargetInstrInfo::DBG_LABEL: + case TargetInstrInfo::EH_LABEL: + MCE.emitLabel(MI.getOperand(0).getImm()); + break; + case TargetInstrInfo::IMPLICIT_DEF: + case TargetInstrInfo::KILL: + break; // pseudo opcode, no side effects + case PPC::MovePCtoLR: + case PPC::MovePCtoLR8: + assert(TM.getRelocationModel() == Reloc::PIC_); + MovePCtoLROffset = (void*)MCE.getCurrentPCValue(); + MCE.emitWordBE(0x48000005); // bl 1 + break; + } + MCE.processDebugLoc(MI.getDebugLoc(), false); + } +} + +unsigned PPCCodeEmitter::getMachineOpValue(const MachineInstr &MI, + const MachineOperand &MO) { + + unsigned rv = 0; // Return value; defaults to 0 for unhandled cases + // or things that get fixed up later by the JIT. + if (MO.isReg()) { + rv = PPCRegisterInfo::getRegisterNumbering(MO.getReg()); + + // Special encoding for MTCRF and MFOCRF, which uses a bit mask for the + // register, not the register number directly. + if ((MI.getOpcode() == PPC::MTCRF || MI.getOpcode() == PPC::MFOCRF) && + (MO.getReg() >= PPC::CR0 && MO.getReg() <= PPC::CR7)) { + rv = 0x80 >> rv; + } + } else if (MO.isImm()) { + rv = MO.getImm(); + } else if (MO.isGlobal() || MO.isSymbol() || + MO.isCPI() || MO.isJTI()) { + unsigned Reloc = 0; + if (MI.getOpcode() == PPC::BL_Darwin || MI.getOpcode() == PPC::BL8_Darwin || + MI.getOpcode() == PPC::BL_SVR4 || MI.getOpcode() == PPC::BL8_ELF || + MI.getOpcode() == PPC::TAILB || MI.getOpcode() == PPC::TAILB8) + Reloc = PPC::reloc_pcrel_bx; + else { + if (TM.getRelocationModel() == Reloc::PIC_) { + assert(MovePCtoLROffset && "MovePCtoLR not seen yet?"); + } + switch (MI.getOpcode()) { + default: MI.dump(); llvm_unreachable("Unknown instruction for relocation!"); + case PPC::LIS: + case PPC::LIS8: + case PPC::ADDIS: + case PPC::ADDIS8: + Reloc = PPC::reloc_absolute_high; // Pointer to symbol + break; + case PPC::LI: + case PPC::LI8: + case PPC::LA: + // Loads. + case PPC::LBZ: + case PPC::LBZ8: + case PPC::LHA: + case PPC::LHA8: + case PPC::LHZ: + case PPC::LHZ8: + case PPC::LWZ: + case PPC::LWZ8: + case PPC::LFS: + case PPC::LFD: + + // Stores. + case PPC::STB: + case PPC::STB8: + case PPC::STH: + case PPC::STH8: + case PPC::STW: + case PPC::STW8: + case PPC::STFS: + case PPC::STFD: + Reloc = PPC::reloc_absolute_low; + break; + + case PPC::LWA: + case PPC::LD: + case PPC::STD: + case PPC::STD_32: + Reloc = PPC::reloc_absolute_low_ix; + break; + } + } + + MachineRelocation R; + if (MO.isGlobal()) { + R = MachineRelocation::getGV(MCE.getCurrentPCOffset(), Reloc, + MO.getGlobal(), 0, + isa(MO.getGlobal())); + } else if (MO.isSymbol()) { + R = MachineRelocation::getExtSym(MCE.getCurrentPCOffset(), + Reloc, MO.getSymbolName(), 0); + } else if (MO.isCPI()) { + R = MachineRelocation::getConstPool(MCE.getCurrentPCOffset(), + Reloc, MO.getIndex(), 0); + } else { + assert(MO.isJTI()); + R = MachineRelocation::getJumpTable(MCE.getCurrentPCOffset(), + Reloc, MO.getIndex(), 0); + } + + // If in PIC mode, we need to encode the negated address of the + // 'movepctolr' into the unrelocated field. After relocation, we'll have + // &gv-&movepctolr-4 in the imm field. Once &movepctolr is added to the imm + // field, we get &gv. This doesn't happen for branch relocations, which are + // always implicitly pc relative. + if (TM.getRelocationModel() == Reloc::PIC_ && Reloc != PPC::reloc_pcrel_bx){ + assert(MovePCtoLROffset && "MovePCtoLR not seen yet?"); + R.setConstantVal(-(intptr_t)MovePCtoLROffset - 4); + } + MCE.addRelocation(R); + + } else if (MO.isMBB()) { + unsigned Reloc = 0; + unsigned Opcode = MI.getOpcode(); + if (Opcode == PPC::B || Opcode == PPC::BL_Darwin || + Opcode == PPC::BLA_Darwin|| Opcode == PPC::BL_SVR4 || + Opcode == PPC::BLA_SVR4) + Reloc = PPC::reloc_pcrel_bx; + else // BCC instruction + Reloc = PPC::reloc_pcrel_bcx; + + MCE.addRelocation(MachineRelocation::getBB(MCE.getCurrentPCOffset(), + Reloc, MO.getMBB())); + } else { +#ifndef NDEBUG + errs() << "ERROR: Unknown type of MachineOperand: " << MO << "\n"; +#endif + llvm_unreachable(0); + } + + return rv; +} + +#include "PPCGenCodeEmitter.inc" diff --git a/libclamav/c++/llvm/lib/Target/PowerPC/PPCFrameInfo.h b/libclamav/c++/llvm/lib/Target/PowerPC/PPCFrameInfo.h new file mode 100644 index 000000000..73d30bf5b --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/PowerPC/PPCFrameInfo.h @@ -0,0 +1,300 @@ +//===-- PPCFrameInfo.h - Define TargetFrameInfo for PowerPC -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// +//===----------------------------------------------------------------------===// + +#ifndef POWERPC_FRAMEINFO_H +#define POWERPC_FRAMEINFO_H + +#include "PPC.h" +#include "PPCSubtarget.h" +#include "llvm/Target/TargetFrameInfo.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/ADT/STLExtras.h" + +namespace llvm { + +class PPCFrameInfo: public TargetFrameInfo { + const TargetMachine &TM; + +public: + PPCFrameInfo(const TargetMachine &tm, bool LP64) + : TargetFrameInfo(TargetFrameInfo::StackGrowsDown, 16, 0), TM(tm) { + } + + /// getReturnSaveOffset - Return the previous frame offset to save the + /// return address. + static unsigned getReturnSaveOffset(bool isPPC64, bool isDarwinABI) { + if (isDarwinABI) + return isPPC64 ? 16 : 8; + // SVR4 ABI: + return isPPC64 ? 16 : 4; + } + + /// getFramePointerSaveOffset - Return the previous frame offset to save the + /// frame pointer. + static unsigned getFramePointerSaveOffset(bool isPPC64, bool isDarwinABI) { + // For the Darwin ABI: + // We cannot use the TOC save slot (offset +20) in the PowerPC linkage area + // for saving the frame pointer (if needed.) While the published ABI has + // not used this slot since at least MacOSX 10.2, there is older code + // around that does use it, and that needs to continue to work. + if (isDarwinABI) + return isPPC64 ? -8U : -4U; + + // SVR4 ABI: First slot in the general register save area. + return -4U; + } + + /// getLinkageSize - Return the size of the PowerPC ABI linkage area. + /// + static unsigned getLinkageSize(bool isPPC64, bool isDarwinABI) { + if (isDarwinABI || isPPC64) + return 6 * (isPPC64 ? 8 : 4); + + // SVR4 ABI: + return 8; + } + + /// getMinCallArgumentsSize - Return the size of the minium PowerPC ABI + /// argument area. + static unsigned getMinCallArgumentsSize(bool isPPC64, bool isDarwinABI) { + // For the Darwin ABI / 64-bit SVR4 ABI: + // The prolog code of the callee may store up to 8 GPR argument registers to + // the stack, allowing va_start to index over them in memory if its varargs. + // Because we cannot tell if this is needed on the caller side, we have to + // conservatively assume that it is needed. As such, make sure we have at + // least enough stack space for the caller to store the 8 GPRs. + if (isDarwinABI || isPPC64) + return 8 * (isPPC64 ? 8 : 4); + + // 32-bit SVR4 ABI: + // There is no default stack allocated for the 8 first GPR arguments. + return 0; + } + + /// getMinCallFrameSize - Return the minimum size a call frame can be using + /// the PowerPC ABI. + static unsigned getMinCallFrameSize(bool isPPC64, bool isDarwinABI) { + // The call frame needs to be at least big enough for linkage and 8 args. + return getLinkageSize(isPPC64, isDarwinABI) + + getMinCallArgumentsSize(isPPC64, isDarwinABI); + } + + // With the SVR4 ABI, callee-saved registers have fixed offsets on the stack. + const SpillSlot * + getCalleeSavedSpillSlots(unsigned &NumEntries) const { + if (TM.getSubtarget().isDarwinABI()) { + NumEntries = 1; + if (TM.getSubtarget().isPPC64()) { + static const SpillSlot darwin64Offsets = {PPC::X31, -8}; + return &darwin64Offsets; + } else { + static const SpillSlot darwinOffsets = {PPC::R31, -4}; + return &darwinOffsets; + } + } + + // Early exit if not using the SVR4 ABI. + if (!TM.getSubtarget().isSVR4ABI()) { + NumEntries = 0; + return 0; + } + + static const SpillSlot Offsets[] = { + // Floating-point register save area offsets. + {PPC::F31, -8}, + {PPC::F30, -16}, + {PPC::F29, -24}, + {PPC::F28, -32}, + {PPC::F27, -40}, + {PPC::F26, -48}, + {PPC::F25, -56}, + {PPC::F24, -64}, + {PPC::F23, -72}, + {PPC::F22, -80}, + {PPC::F21, -88}, + {PPC::F20, -96}, + {PPC::F19, -104}, + {PPC::F18, -112}, + {PPC::F17, -120}, + {PPC::F16, -128}, + {PPC::F15, -136}, + {PPC::F14, -144}, + + // General register save area offsets. + {PPC::R31, -4}, + {PPC::R30, -8}, + {PPC::R29, -12}, + {PPC::R28, -16}, + {PPC::R27, -20}, + {PPC::R26, -24}, + {PPC::R25, -28}, + {PPC::R24, -32}, + {PPC::R23, -36}, + {PPC::R22, -40}, + {PPC::R21, -44}, + {PPC::R20, -48}, + {PPC::R19, -52}, + {PPC::R18, -56}, + {PPC::R17, -60}, + {PPC::R16, -64}, + {PPC::R15, -68}, + {PPC::R14, -72}, + + // CR save area offset. + // FIXME SVR4: Disable CR save area for now. +// {PPC::CR2, -4}, +// {PPC::CR3, -4}, +// {PPC::CR4, -4}, +// {PPC::CR2LT, -4}, +// {PPC::CR2GT, -4}, +// {PPC::CR2EQ, -4}, +// {PPC::CR2UN, -4}, +// {PPC::CR3LT, -4}, +// {PPC::CR3GT, -4}, +// {PPC::CR3EQ, -4}, +// {PPC::CR3UN, -4}, +// {PPC::CR4LT, -4}, +// {PPC::CR4GT, -4}, +// {PPC::CR4EQ, -4}, +// {PPC::CR4UN, -4}, + + // VRSAVE save area offset. + {PPC::VRSAVE, -4}, + + // Vector register save area + {PPC::V31, -16}, + {PPC::V30, -32}, + {PPC::V29, -48}, + {PPC::V28, -64}, + {PPC::V27, -80}, + {PPC::V26, -96}, + {PPC::V25, -112}, + {PPC::V24, -128}, + {PPC::V23, -144}, + {PPC::V22, -160}, + {PPC::V21, -176}, + {PPC::V20, -192} + }; + + static const SpillSlot Offsets64[] = { + // Floating-point register save area offsets. + {PPC::F31, -8}, + {PPC::F30, -16}, + {PPC::F29, -24}, + {PPC::F28, -32}, + {PPC::F27, -40}, + {PPC::F26, -48}, + {PPC::F25, -56}, + {PPC::F24, -64}, + {PPC::F23, -72}, + {PPC::F22, -80}, + {PPC::F21, -88}, + {PPC::F20, -96}, + {PPC::F19, -104}, + {PPC::F18, -112}, + {PPC::F17, -120}, + {PPC::F16, -128}, + {PPC::F15, -136}, + {PPC::F14, -144}, + + // General register save area offsets. + // FIXME 64-bit SVR4: Are 32-bit registers actually allocated in 64-bit + // mode? + {PPC::R31, -4}, + {PPC::R30, -12}, + {PPC::R29, -20}, + {PPC::R28, -28}, + {PPC::R27, -36}, + {PPC::R26, -44}, + {PPC::R25, -52}, + {PPC::R24, -60}, + {PPC::R23, -68}, + {PPC::R22, -76}, + {PPC::R21, -84}, + {PPC::R20, -92}, + {PPC::R19, -100}, + {PPC::R18, -108}, + {PPC::R17, -116}, + {PPC::R16, -124}, + {PPC::R15, -132}, + {PPC::R14, -140}, + + {PPC::X31, -8}, + {PPC::X30, -16}, + {PPC::X29, -24}, + {PPC::X28, -32}, + {PPC::X27, -40}, + {PPC::X26, -48}, + {PPC::X25, -56}, + {PPC::X24, -64}, + {PPC::X23, -72}, + {PPC::X22, -80}, + {PPC::X21, -88}, + {PPC::X20, -96}, + {PPC::X19, -104}, + {PPC::X18, -112}, + {PPC::X17, -120}, + {PPC::X16, -128}, + {PPC::X15, -136}, + {PPC::X14, -144}, + + // CR save area offset. + // FIXME SVR4: Disable CR save area for now. +// {PPC::CR2, -4}, +// {PPC::CR3, -4}, +// {PPC::CR4, -4}, +// {PPC::CR2LT, -4}, +// {PPC::CR2GT, -4}, +// {PPC::CR2EQ, -4}, +// {PPC::CR2UN, -4}, +// {PPC::CR3LT, -4}, +// {PPC::CR3GT, -4}, +// {PPC::CR3EQ, -4}, +// {PPC::CR3UN, -4}, +// {PPC::CR4LT, -4}, +// {PPC::CR4GT, -4}, +// {PPC::CR4EQ, -4}, +// {PPC::CR4UN, -4}, + + // VRSAVE save area offset. + {PPC::VRSAVE, -4}, + + // Vector register save area + {PPC::V31, -16}, + {PPC::V30, -32}, + {PPC::V29, -48}, + {PPC::V28, -64}, + {PPC::V27, -80}, + {PPC::V26, -96}, + {PPC::V25, -112}, + {PPC::V24, -128}, + {PPC::V23, -144}, + {PPC::V22, -160}, + {PPC::V21, -176}, + {PPC::V20, -192} + }; + + if (TM.getSubtarget().isPPC64()) { + NumEntries = array_lengthof(Offsets64); + + return Offsets64; + } else { + NumEntries = array_lengthof(Offsets); + + return Offsets; + } + } +}; + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/lib/Target/PowerPC/PPCHazardRecognizers.cpp b/libclamav/c++/llvm/lib/Target/PowerPC/PPCHazardRecognizers.cpp new file mode 100644 index 000000000..6af7e0ffb --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/PowerPC/PPCHazardRecognizers.cpp @@ -0,0 +1,306 @@ +//===-- PPCHazardRecognizers.cpp - PowerPC Hazard Recognizer Impls --------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements hazard recognizers for scheduling on PowerPC processors. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "pre-RA-sched" +#include "PPCHazardRecognizers.h" +#include "PPC.h" +#include "PPCInstrInfo.h" +#include "llvm/CodeGen/ScheduleDAG.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +//===----------------------------------------------------------------------===// +// PowerPC 970 Hazard Recognizer +// +// This models the dispatch group formation of the PPC970 processor. Dispatch +// groups are bundles of up to five instructions that can contain various mixes +// of instructions. The PPC970 can dispatch a peak of 4 non-branch and one +// branch instruction per-cycle. +// +// There are a number of restrictions to dispatch group formation: some +// instructions can only be issued in the first slot of a dispatch group, & some +// instructions fill an entire dispatch group. Additionally, only branches can +// issue in the 5th (last) slot. +// +// Finally, there are a number of "structural" hazards on the PPC970. These +// conditions cause large performance penalties due to misprediction, recovery, +// and replay logic that has to happen. These cases include setting a CTR and +// branching through it in the same dispatch group, and storing to an address, +// then loading from the same address within a dispatch group. To avoid these +// conditions, we insert no-op instructions when appropriate. +// +// FIXME: This is missing some significant cases: +// 1. Modeling of microcoded instructions. +// 2. Handling of serialized operations. +// 3. Handling of the esoteric cases in "Resource-based Instruction Grouping". +// + +PPCHazardRecognizer970::PPCHazardRecognizer970(const TargetInstrInfo &tii) + : TII(tii) { + EndDispatchGroup(); +} + +void PPCHazardRecognizer970::EndDispatchGroup() { + DEBUG(errs() << "=== Start of dispatch group\n"); + NumIssued = 0; + + // Structural hazard info. + HasCTRSet = false; + NumStores = 0; +} + + +PPCII::PPC970_Unit +PPCHazardRecognizer970::GetInstrType(unsigned Opcode, + bool &isFirst, bool &isSingle, + bool &isCracked, + bool &isLoad, bool &isStore) { + if ((int)Opcode >= 0) { + isFirst = isSingle = isCracked = isLoad = isStore = false; + return PPCII::PPC970_Pseudo; + } + Opcode = ~Opcode; + + const TargetInstrDesc &TID = TII.get(Opcode); + + isLoad = TID.mayLoad(); + isStore = TID.mayStore(); + + unsigned TSFlags = TID.TSFlags; + + isFirst = TSFlags & PPCII::PPC970_First; + isSingle = TSFlags & PPCII::PPC970_Single; + isCracked = TSFlags & PPCII::PPC970_Cracked; + return (PPCII::PPC970_Unit)(TSFlags & PPCII::PPC970_Mask); +} + +/// isLoadOfStoredAddress - If we have a load from the previously stored pointer +/// as indicated by StorePtr1/StorePtr2/StoreSize, return true. +bool PPCHazardRecognizer970:: +isLoadOfStoredAddress(unsigned LoadSize, SDValue Ptr1, SDValue Ptr2) const { + for (unsigned i = 0, e = NumStores; i != e; ++i) { + // Handle exact and commuted addresses. + if (Ptr1 == StorePtr1[i] && Ptr2 == StorePtr2[i]) + return true; + if (Ptr2 == StorePtr1[i] && Ptr1 == StorePtr2[i]) + return true; + + // Okay, we don't have an exact match, if this is an indexed offset, see if + // we have overlap (which happens during fp->int conversion for example). + if (StorePtr2[i] == Ptr2) { + if (ConstantSDNode *StoreOffset = dyn_cast(StorePtr1[i])) + if (ConstantSDNode *LoadOffset = dyn_cast(Ptr1)) { + // Okay the base pointers match, so we have [c1+r] vs [c2+r]. Check + // to see if the load and store actually overlap. + int StoreOffs = StoreOffset->getZExtValue(); + int LoadOffs = LoadOffset->getZExtValue(); + if (StoreOffs < LoadOffs) { + if (int(StoreOffs+StoreSize[i]) > LoadOffs) return true; + } else { + if (int(LoadOffs+LoadSize) > StoreOffs) return true; + } + } + } + } + return false; +} + +/// getHazardType - We return hazard for any non-branch instruction that would +/// terminate terminate the dispatch group. We turn NoopHazard for any +/// instructions that wouldn't terminate the dispatch group that would cause a +/// pipeline flush. +ScheduleHazardRecognizer::HazardType PPCHazardRecognizer970:: +getHazardType(SUnit *SU) { + const SDNode *Node = SU->getNode()->getFlaggedMachineNode(); + bool isFirst, isSingle, isCracked, isLoad, isStore; + PPCII::PPC970_Unit InstrType = + GetInstrType(Node->getOpcode(), isFirst, isSingle, isCracked, + isLoad, isStore); + if (InstrType == PPCII::PPC970_Pseudo) return NoHazard; + unsigned Opcode = Node->getMachineOpcode(); + + // We can only issue a PPC970_First/PPC970_Single instruction (such as + // crand/mtspr/etc) if this is the first cycle of the dispatch group. + if (NumIssued != 0 && (isFirst || isSingle)) + return Hazard; + + // If this instruction is cracked into two ops by the decoder, we know that + // it is not a branch and that it cannot issue if 3 other instructions are + // already in the dispatch group. + if (isCracked && NumIssued > 2) + return Hazard; + + switch (InstrType) { + default: llvm_unreachable("Unknown instruction type!"); + case PPCII::PPC970_FXU: + case PPCII::PPC970_LSU: + case PPCII::PPC970_FPU: + case PPCII::PPC970_VALU: + case PPCII::PPC970_VPERM: + // We can only issue a branch as the last instruction in a group. + if (NumIssued == 4) return Hazard; + break; + case PPCII::PPC970_CRU: + // We can only issue a CR instruction in the first two slots. + if (NumIssued >= 2) return Hazard; + break; + case PPCII::PPC970_BRU: + break; + } + + // Do not allow MTCTR and BCTRL to be in the same dispatch group. + if (HasCTRSet && (Opcode == PPC::BCTRL_Darwin || Opcode == PPC::BCTRL_SVR4)) + return NoopHazard; + + // If this is a load following a store, make sure it's not to the same or + // overlapping address. + if (isLoad && NumStores) { + unsigned LoadSize; + switch (Opcode) { + default: llvm_unreachable("Unknown load!"); + case PPC::LBZ: case PPC::LBZU: + case PPC::LBZX: + case PPC::LBZ8: case PPC::LBZU8: + case PPC::LBZX8: + case PPC::LVEBX: + LoadSize = 1; + break; + case PPC::LHA: case PPC::LHAU: + case PPC::LHAX: + case PPC::LHZ: case PPC::LHZU: + case PPC::LHZX: + case PPC::LVEHX: + case PPC::LHBRX: + case PPC::LHA8: case PPC::LHAU8: + case PPC::LHAX8: + case PPC::LHZ8: case PPC::LHZU8: + case PPC::LHZX8: + LoadSize = 2; + break; + case PPC::LFS: case PPC::LFSU: + case PPC::LFSX: + case PPC::LWZ: case PPC::LWZU: + case PPC::LWZX: + case PPC::LWA: + case PPC::LWAX: + case PPC::LVEWX: + case PPC::LWBRX: + case PPC::LWZ8: + case PPC::LWZX8: + LoadSize = 4; + break; + case PPC::LFD: case PPC::LFDU: + case PPC::LFDX: + case PPC::LD: case PPC::LDU: + case PPC::LDX: + LoadSize = 8; + break; + case PPC::LVX: + case PPC::LVXL: + LoadSize = 16; + break; + } + + if (isLoadOfStoredAddress(LoadSize, + Node->getOperand(0), Node->getOperand(1))) + return NoopHazard; + } + + return NoHazard; +} + +void PPCHazardRecognizer970::EmitInstruction(SUnit *SU) { + const SDNode *Node = SU->getNode()->getFlaggedMachineNode(); + bool isFirst, isSingle, isCracked, isLoad, isStore; + PPCII::PPC970_Unit InstrType = + GetInstrType(Node->getOpcode(), isFirst, isSingle, isCracked, + isLoad, isStore); + if (InstrType == PPCII::PPC970_Pseudo) return; + unsigned Opcode = Node->getMachineOpcode(); + + // Update structural hazard information. + if (Opcode == PPC::MTCTR) HasCTRSet = true; + + // Track the address stored to. + if (isStore) { + unsigned ThisStoreSize; + switch (Opcode) { + default: llvm_unreachable("Unknown store instruction!"); + case PPC::STB: case PPC::STB8: + case PPC::STBU: case PPC::STBU8: + case PPC::STBX: case PPC::STBX8: + case PPC::STVEBX: + ThisStoreSize = 1; + break; + case PPC::STH: case PPC::STH8: + case PPC::STHU: case PPC::STHU8: + case PPC::STHX: case PPC::STHX8: + case PPC::STVEHX: + case PPC::STHBRX: + ThisStoreSize = 2; + break; + case PPC::STFS: + case PPC::STFSU: + case PPC::STFSX: + case PPC::STWX: case PPC::STWX8: + case PPC::STWUX: + case PPC::STW: case PPC::STW8: + case PPC::STWU: case PPC::STWU8: + case PPC::STVEWX: + case PPC::STFIWX: + case PPC::STWBRX: + ThisStoreSize = 4; + break; + case PPC::STD_32: + case PPC::STDX_32: + case PPC::STD: + case PPC::STDU: + case PPC::STFD: + case PPC::STFDX: + case PPC::STDX: + case PPC::STDUX: + ThisStoreSize = 8; + break; + case PPC::STVX: + case PPC::STVXL: + ThisStoreSize = 16; + break; + } + + StoreSize[NumStores] = ThisStoreSize; + StorePtr1[NumStores] = Node->getOperand(1); + StorePtr2[NumStores] = Node->getOperand(2); + ++NumStores; + } + + if (InstrType == PPCII::PPC970_BRU || isSingle) + NumIssued = 4; // Terminate a d-group. + ++NumIssued; + + // If this instruction is cracked into two ops by the decoder, remember that + // we issued two pieces. + if (isCracked) + ++NumIssued; + + if (NumIssued == 5) + EndDispatchGroup(); +} + +void PPCHazardRecognizer970::AdvanceCycle() { + assert(NumIssued < 5 && "Illegal dispatch group!"); + ++NumIssued; + if (NumIssued == 5) + EndDispatchGroup(); +} diff --git a/libclamav/c++/llvm/lib/Target/PowerPC/PPCHazardRecognizers.h b/libclamav/c++/llvm/lib/Target/PowerPC/PPCHazardRecognizers.h new file mode 100644 index 000000000..74bf8e52d --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/PowerPC/PPCHazardRecognizers.h @@ -0,0 +1,73 @@ +//===-- PPCHazardRecognizers.h - PowerPC Hazard Recognizers -----*- 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 hazard recognizers for scheduling on PowerPC processors. +// +//===----------------------------------------------------------------------===// + +#ifndef PPCHAZRECS_H +#define PPCHAZRECS_H + +#include "llvm/CodeGen/ScheduleHazardRecognizer.h" +#include "llvm/CodeGen/SelectionDAGNodes.h" +#include "PPCInstrInfo.h" + +namespace llvm { + +/// PPCHazardRecognizer970 - This class defines a finite state automata that +/// models the dispatch logic on the PowerPC 970 (aka G5) processor. This +/// promotes good dispatch group formation and implements noop insertion to +/// avoid structural hazards that cause significant performance penalties (e.g. +/// setting the CTR register then branching through it within a dispatch group), +/// or storing then loading from the same address within a dispatch group. +class PPCHazardRecognizer970 : public ScheduleHazardRecognizer { + const TargetInstrInfo &TII; + + unsigned NumIssued; // Number of insts issued, including advanced cycles. + + // Various things that can cause a structural hazard. + + // HasCTRSet - If the CTR register is set in this group, disallow BCTRL. + bool HasCTRSet; + + // StoredPtr - Keep track of the address of any store. If we see a load from + // the same address (or one that aliases it), disallow the store. We can have + // up to four stores in one dispatch group, hence we track up to 4. + // + // This is null if we haven't seen a store yet. We keep track of both + // operands of the store here, since we support [r+r] and [r+i] addressing. + SDValue StorePtr1[4], StorePtr2[4]; + unsigned StoreSize[4]; + unsigned NumStores; + +public: + PPCHazardRecognizer970(const TargetInstrInfo &TII); + virtual HazardType getHazardType(SUnit *SU); + virtual void EmitInstruction(SUnit *SU); + virtual void AdvanceCycle(); + +private: + /// EndDispatchGroup - Called when we are finishing a new dispatch group. + /// + void EndDispatchGroup(); + + /// GetInstrType - Classify the specified powerpc opcode according to its + /// pipeline. + PPCII::PPC970_Unit GetInstrType(unsigned Opcode, + bool &isFirst, bool &isSingle,bool &isCracked, + bool &isLoad, bool &isStore); + + bool isLoadOfStoredAddress(unsigned LoadSize, + SDValue Ptr1, SDValue Ptr2) const; +}; + +} // end namespace llvm + +#endif + diff --git a/libclamav/c++/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp b/libclamav/c++/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp new file mode 100644 index 000000000..e7334b54d --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp @@ -0,0 +1,1106 @@ +//===-- PPCISelDAGToDAG.cpp - PPC --pattern matching inst selector --------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines a pattern matching instruction selector for PowerPC, +// converting from a legalized dag to a PPC dag. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "ppc-codegen" +#include "PPC.h" +#include "PPCPredicates.h" +#include "PPCTargetMachine.h" +#include "PPCISelLowering.h" +#include "PPCHazardRecognizers.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineFunctionAnalysis.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/SelectionDAG.h" +#include "llvm/CodeGen/SelectionDAGISel.h" +#include "llvm/Target/TargetOptions.h" +#include "llvm/Constants.h" +#include "llvm/Function.h" +#include "llvm/GlobalValue.h" +#include "llvm/Intrinsics.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +namespace { + //===--------------------------------------------------------------------===// + /// PPCDAGToDAGISel - PPC specific code to select PPC machine + /// instructions for SelectionDAG operations. + /// + class PPCDAGToDAGISel : public SelectionDAGISel { + PPCTargetMachine &TM; + PPCTargetLowering &PPCLowering; + const PPCSubtarget &PPCSubTarget; + unsigned GlobalBaseReg; + public: + explicit PPCDAGToDAGISel(PPCTargetMachine &tm) + : SelectionDAGISel(tm), TM(tm), + PPCLowering(*TM.getTargetLowering()), + PPCSubTarget(*TM.getSubtargetImpl()) {} + + virtual bool runOnMachineFunction(MachineFunction &MF) { + // Make sure we re-emit a set of the global base reg if necessary + GlobalBaseReg = 0; + SelectionDAGISel::runOnMachineFunction(MF); + + InsertVRSaveCode(MF); + return true; + } + + /// getI32Imm - Return a target constant with the specified value, of type + /// i32. + inline SDValue getI32Imm(unsigned Imm) { + return CurDAG->getTargetConstant(Imm, MVT::i32); + } + + /// getI64Imm - Return a target constant with the specified value, of type + /// i64. + inline SDValue getI64Imm(uint64_t Imm) { + return CurDAG->getTargetConstant(Imm, MVT::i64); + } + + /// getSmallIPtrImm - Return a target constant of pointer type. + inline SDValue getSmallIPtrImm(unsigned Imm) { + return CurDAG->getTargetConstant(Imm, PPCLowering.getPointerTy()); + } + + /// isRunOfOnes - Returns true iff Val consists of one contiguous run of 1s + /// with any number of 0s on either side. The 1s are allowed to wrap from + /// LSB to MSB, so 0x000FFF0, 0x0000FFFF, and 0xFF0000FF are all runs. + /// 0x0F0F0000 is not, since all 1s are not contiguous. + static bool isRunOfOnes(unsigned Val, unsigned &MB, unsigned &ME); + + + /// isRotateAndMask - Returns true if Mask and Shift can be folded into a + /// rotate and mask opcode and mask operation. + static bool isRotateAndMask(SDNode *N, unsigned Mask, bool isShiftMask, + unsigned &SH, unsigned &MB, unsigned &ME); + + /// getGlobalBaseReg - insert code into the entry mbb to materialize the PIC + /// base register. Return the virtual register that holds this value. + SDNode *getGlobalBaseReg(); + + // Select - Convert the specified operand from a target-independent to a + // target-specific node if it hasn't already been changed. + SDNode *Select(SDValue Op); + + SDNode *SelectBitfieldInsert(SDNode *N); + + /// SelectCC - Select a comparison of the specified values with the + /// specified condition code, returning the CR# of the expression. + SDValue SelectCC(SDValue LHS, SDValue RHS, ISD::CondCode CC, DebugLoc dl); + + /// SelectAddrImm - Returns true if the address N can be represented by + /// a base register plus a signed 16-bit displacement [r+imm]. + bool SelectAddrImm(SDValue Op, SDValue N, SDValue &Disp, + SDValue &Base) { + return PPCLowering.SelectAddressRegImm(N, Disp, Base, *CurDAG); + } + + /// SelectAddrImmOffs - Return true if the operand is valid for a preinc + /// immediate field. Because preinc imms have already been validated, just + /// accept it. + bool SelectAddrImmOffs(SDValue Op, SDValue N, SDValue &Out) const { + Out = N; + return true; + } + + /// SelectAddrIdx - Given the specified addressed, check to see if it can be + /// represented as an indexed [r+r] operation. Returns false if it can + /// be represented by [r+imm], which are preferred. + bool SelectAddrIdx(SDValue Op, SDValue N, SDValue &Base, + SDValue &Index) { + return PPCLowering.SelectAddressRegReg(N, Base, Index, *CurDAG); + } + + /// SelectAddrIdxOnly - Given the specified addressed, force it to be + /// represented as an indexed [r+r] operation. + bool SelectAddrIdxOnly(SDValue Op, SDValue N, SDValue &Base, + SDValue &Index) { + return PPCLowering.SelectAddressRegRegOnly(N, Base, Index, *CurDAG); + } + + /// SelectAddrImmShift - Returns true if the address N can be represented by + /// a base register plus a signed 14-bit displacement [r+imm*4]. Suitable + /// for use by STD and friends. + bool SelectAddrImmShift(SDValue Op, SDValue N, SDValue &Disp, + SDValue &Base) { + return PPCLowering.SelectAddressRegImmShift(N, Disp, Base, *CurDAG); + } + + /// SelectInlineAsmMemoryOperand - Implement addressing mode selection for + /// inline asm expressions. It is always correct to compute the value into + /// a register. The case of adding a (possibly relocatable) constant to a + /// register can be improved, but it is wrong to substitute Reg+Reg for + /// Reg in an asm, because the load or store opcode would have to change. + virtual bool SelectInlineAsmMemoryOperand(const SDValue &Op, + char ConstraintCode, + std::vector &OutOps) { + OutOps.push_back(Op); + return false; + } + + SDValue BuildSDIVSequence(SDNode *N); + SDValue BuildUDIVSequence(SDNode *N); + + /// InstructionSelect - This callback is invoked by + /// SelectionDAGISel when it has created a SelectionDAG for us to codegen. + virtual void InstructionSelect(); + + void InsertVRSaveCode(MachineFunction &MF); + + virtual const char *getPassName() const { + return "PowerPC DAG->DAG Pattern Instruction Selection"; + } + + /// CreateTargetHazardRecognizer - Return the hazard recognizer to use for + /// this target when scheduling the DAG. + virtual ScheduleHazardRecognizer *CreateTargetHazardRecognizer() { + // Should use subtarget info to pick the right hazard recognizer. For + // now, always return a PPC970 recognizer. + const TargetInstrInfo *II = TM.getInstrInfo(); + assert(II && "No InstrInfo?"); + return new PPCHazardRecognizer970(*II); + } + +// Include the pieces autogenerated from the target description. +#include "PPCGenDAGISel.inc" + +private: + SDNode *SelectSETCC(SDValue Op); + }; +} + +/// InstructionSelect - This callback is invoked by +/// SelectionDAGISel when it has created a SelectionDAG for us to codegen. +void PPCDAGToDAGISel::InstructionSelect() { + // Select target instructions for the DAG. + SelectRoot(*CurDAG); + CurDAG->RemoveDeadNodes(); +} + +/// InsertVRSaveCode - Once the entire function has been instruction selected, +/// all virtual registers are created and all machine instructions are built, +/// check to see if we need to save/restore VRSAVE. If so, do it. +void PPCDAGToDAGISel::InsertVRSaveCode(MachineFunction &Fn) { + // Check to see if this function uses vector registers, which means we have to + // save and restore the VRSAVE register and update it with the regs we use. + // + // In this case, there will be virtual registers of vector type type created + // by the scheduler. Detect them now. + bool HasVectorVReg = false; + for (unsigned i = TargetRegisterInfo::FirstVirtualRegister, + e = RegInfo->getLastVirtReg()+1; i != e; ++i) + if (RegInfo->getRegClass(i) == &PPC::VRRCRegClass) { + HasVectorVReg = true; + break; + } + if (!HasVectorVReg) return; // nothing to do. + + // If we have a vector register, we want to emit code into the entry and exit + // blocks to save and restore the VRSAVE register. We do this here (instead + // of marking all vector instructions as clobbering VRSAVE) for two reasons: + // + // 1. This (trivially) reduces the load on the register allocator, by not + // having to represent the live range of the VRSAVE register. + // 2. This (more significantly) allows us to create a temporary virtual + // register to hold the saved VRSAVE value, allowing this temporary to be + // register allocated, instead of forcing it to be spilled to the stack. + + // Create two vregs - one to hold the VRSAVE register that is live-in to the + // function and one for the value after having bits or'd into it. + unsigned InVRSAVE = RegInfo->createVirtualRegister(&PPC::GPRCRegClass); + unsigned UpdatedVRSAVE = RegInfo->createVirtualRegister(&PPC::GPRCRegClass); + + const TargetInstrInfo &TII = *TM.getInstrInfo(); + MachineBasicBlock &EntryBB = *Fn.begin(); + DebugLoc dl = DebugLoc::getUnknownLoc(); + // Emit the following code into the entry block: + // InVRSAVE = MFVRSAVE + // UpdatedVRSAVE = UPDATE_VRSAVE InVRSAVE + // MTVRSAVE UpdatedVRSAVE + MachineBasicBlock::iterator IP = EntryBB.begin(); // Insert Point + BuildMI(EntryBB, IP, dl, TII.get(PPC::MFVRSAVE), InVRSAVE); + BuildMI(EntryBB, IP, dl, TII.get(PPC::UPDATE_VRSAVE), + UpdatedVRSAVE).addReg(InVRSAVE); + BuildMI(EntryBB, IP, dl, TII.get(PPC::MTVRSAVE)).addReg(UpdatedVRSAVE); + + // Find all return blocks, outputting a restore in each epilog. + for (MachineFunction::iterator BB = Fn.begin(), E = Fn.end(); BB != E; ++BB) { + if (!BB->empty() && BB->back().getDesc().isReturn()) { + IP = BB->end(); --IP; + + // Skip over all terminator instructions, which are part of the return + // sequence. + MachineBasicBlock::iterator I2 = IP; + while (I2 != BB->begin() && (--I2)->getDesc().isTerminator()) + IP = I2; + + // Emit: MTVRSAVE InVRSave + BuildMI(*BB, IP, dl, TII.get(PPC::MTVRSAVE)).addReg(InVRSAVE); + } + } +} + + +/// getGlobalBaseReg - Output the instructions required to put the +/// base address to use for accessing globals into a register. +/// +SDNode *PPCDAGToDAGISel::getGlobalBaseReg() { + if (!GlobalBaseReg) { + const TargetInstrInfo &TII = *TM.getInstrInfo(); + // Insert the set of GlobalBaseReg into the first MBB of the function + MachineBasicBlock &FirstMBB = MF->front(); + MachineBasicBlock::iterator MBBI = FirstMBB.begin(); + DebugLoc dl = DebugLoc::getUnknownLoc(); + + if (PPCLowering.getPointerTy() == MVT::i32) { + GlobalBaseReg = RegInfo->createVirtualRegister(PPC::GPRCRegisterClass); + BuildMI(FirstMBB, MBBI, dl, TII.get(PPC::MovePCtoLR), PPC::LR); + BuildMI(FirstMBB, MBBI, dl, TII.get(PPC::MFLR), GlobalBaseReg); + } else { + GlobalBaseReg = RegInfo->createVirtualRegister(PPC::G8RCRegisterClass); + BuildMI(FirstMBB, MBBI, dl, TII.get(PPC::MovePCtoLR8), PPC::LR8); + BuildMI(FirstMBB, MBBI, dl, TII.get(PPC::MFLR8), GlobalBaseReg); + } + } + return CurDAG->getRegister(GlobalBaseReg, + PPCLowering.getPointerTy()).getNode(); +} + +/// isIntS16Immediate - This method tests to see if the node is either a 32-bit +/// or 64-bit immediate, and if the value can be accurately represented as a +/// sign extension from a 16-bit value. If so, this returns true and the +/// immediate. +static bool isIntS16Immediate(SDNode *N, short &Imm) { + if (N->getOpcode() != ISD::Constant) + return false; + + Imm = (short)cast(N)->getZExtValue(); + if (N->getValueType(0) == MVT::i32) + return Imm == (int32_t)cast(N)->getZExtValue(); + else + return Imm == (int64_t)cast(N)->getZExtValue(); +} + +static bool isIntS16Immediate(SDValue Op, short &Imm) { + return isIntS16Immediate(Op.getNode(), Imm); +} + + +/// isInt32Immediate - This method tests to see if the node is a 32-bit constant +/// operand. If so Imm will receive the 32-bit value. +static bool isInt32Immediate(SDNode *N, unsigned &Imm) { + if (N->getOpcode() == ISD::Constant && N->getValueType(0) == MVT::i32) { + Imm = cast(N)->getZExtValue(); + return true; + } + return false; +} + +/// isInt64Immediate - This method tests to see if the node is a 64-bit constant +/// operand. If so Imm will receive the 64-bit value. +static bool isInt64Immediate(SDNode *N, uint64_t &Imm) { + if (N->getOpcode() == ISD::Constant && N->getValueType(0) == MVT::i64) { + Imm = cast(N)->getZExtValue(); + return true; + } + return false; +} + +// isInt32Immediate - This method tests to see if a constant operand. +// If so Imm will receive the 32 bit value. +static bool isInt32Immediate(SDValue N, unsigned &Imm) { + return isInt32Immediate(N.getNode(), Imm); +} + + +// isOpcWithIntImmediate - This method tests to see if the node is a specific +// opcode and that it has a immediate integer right operand. +// If so Imm will receive the 32 bit value. +static bool isOpcWithIntImmediate(SDNode *N, unsigned Opc, unsigned& Imm) { + return N->getOpcode() == Opc + && isInt32Immediate(N->getOperand(1).getNode(), Imm); +} + +bool PPCDAGToDAGISel::isRunOfOnes(unsigned Val, unsigned &MB, unsigned &ME) { + if (isShiftedMask_32(Val)) { + // look for the first non-zero bit + MB = CountLeadingZeros_32(Val); + // look for the first zero bit after the run of ones + ME = CountLeadingZeros_32((Val - 1) ^ Val); + return true; + } else { + Val = ~Val; // invert mask + if (isShiftedMask_32(Val)) { + // effectively look for the first zero bit + ME = CountLeadingZeros_32(Val) - 1; + // effectively look for the first one bit after the run of zeros + MB = CountLeadingZeros_32((Val - 1) ^ Val) + 1; + return true; + } + } + // no run present + return false; +} + +bool PPCDAGToDAGISel::isRotateAndMask(SDNode *N, unsigned Mask, + bool isShiftMask, unsigned &SH, + unsigned &MB, unsigned &ME) { + // Don't even go down this path for i64, since different logic will be + // necessary for rldicl/rldicr/rldimi. + if (N->getValueType(0) != MVT::i32) + return false; + + unsigned Shift = 32; + unsigned Indeterminant = ~0; // bit mask marking indeterminant results + unsigned Opcode = N->getOpcode(); + if (N->getNumOperands() != 2 || + !isInt32Immediate(N->getOperand(1).getNode(), Shift) || (Shift > 31)) + return false; + + if (Opcode == ISD::SHL) { + // apply shift left to mask if it comes first + if (isShiftMask) Mask = Mask << Shift; + // determine which bits are made indeterminant by shift + Indeterminant = ~(0xFFFFFFFFu << Shift); + } else if (Opcode == ISD::SRL) { + // apply shift right to mask if it comes first + if (isShiftMask) Mask = Mask >> Shift; + // determine which bits are made indeterminant by shift + Indeterminant = ~(0xFFFFFFFFu >> Shift); + // adjust for the left rotate + Shift = 32 - Shift; + } else if (Opcode == ISD::ROTL) { + Indeterminant = 0; + } else { + return false; + } + + // if the mask doesn't intersect any Indeterminant bits + if (Mask && !(Mask & Indeterminant)) { + SH = Shift & 31; + // make sure the mask is still a mask (wrap arounds may not be) + return isRunOfOnes(Mask, MB, ME); + } + return false; +} + +/// SelectBitfieldInsert - turn an or of two masked values into +/// the rotate left word immediate then mask insert (rlwimi) instruction. +SDNode *PPCDAGToDAGISel::SelectBitfieldInsert(SDNode *N) { + SDValue Op0 = N->getOperand(0); + SDValue Op1 = N->getOperand(1); + DebugLoc dl = N->getDebugLoc(); + + APInt LKZ, LKO, RKZ, RKO; + CurDAG->ComputeMaskedBits(Op0, APInt::getAllOnesValue(32), LKZ, LKO); + CurDAG->ComputeMaskedBits(Op1, APInt::getAllOnesValue(32), RKZ, RKO); + + unsigned TargetMask = LKZ.getZExtValue(); + unsigned InsertMask = RKZ.getZExtValue(); + + if ((TargetMask | InsertMask) == 0xFFFFFFFF) { + unsigned Op0Opc = Op0.getOpcode(); + unsigned Op1Opc = Op1.getOpcode(); + unsigned Value, SH = 0; + TargetMask = ~TargetMask; + InsertMask = ~InsertMask; + + // If the LHS has a foldable shift and the RHS does not, then swap it to the + // RHS so that we can fold the shift into the insert. + if (Op0Opc == ISD::AND && Op1Opc == ISD::AND) { + if (Op0.getOperand(0).getOpcode() == ISD::SHL || + Op0.getOperand(0).getOpcode() == ISD::SRL) { + if (Op1.getOperand(0).getOpcode() != ISD::SHL && + Op1.getOperand(0).getOpcode() != ISD::SRL) { + std::swap(Op0, Op1); + std::swap(Op0Opc, Op1Opc); + std::swap(TargetMask, InsertMask); + } + } + } else if (Op0Opc == ISD::SHL || Op0Opc == ISD::SRL) { + if (Op1Opc == ISD::AND && Op1.getOperand(0).getOpcode() != ISD::SHL && + Op1.getOperand(0).getOpcode() != ISD::SRL) { + std::swap(Op0, Op1); + std::swap(Op0Opc, Op1Opc); + std::swap(TargetMask, InsertMask); + } + } + + unsigned MB, ME; + if (InsertMask && isRunOfOnes(InsertMask, MB, ME)) { + SDValue Tmp1, Tmp2; + + if ((Op1Opc == ISD::SHL || Op1Opc == ISD::SRL) && + isInt32Immediate(Op1.getOperand(1), Value)) { + Op1 = Op1.getOperand(0); + SH = (Op1Opc == ISD::SHL) ? Value : 32 - Value; + } + if (Op1Opc == ISD::AND) { + unsigned SHOpc = Op1.getOperand(0).getOpcode(); + if ((SHOpc == ISD::SHL || SHOpc == ISD::SRL) && + isInt32Immediate(Op1.getOperand(0).getOperand(1), Value)) { + Op1 = Op1.getOperand(0).getOperand(0); + SH = (SHOpc == ISD::SHL) ? Value : 32 - Value; + } else { + Op1 = Op1.getOperand(0); + } + } + + SH &= 31; + SDValue Ops[] = { Op0, Op1, getI32Imm(SH), getI32Imm(MB), + getI32Imm(ME) }; + return CurDAG->getMachineNode(PPC::RLWIMI, dl, MVT::i32, Ops, 5); + } + } + return 0; +} + +/// SelectCC - Select a comparison of the specified values with the specified +/// condition code, returning the CR# of the expression. +SDValue PPCDAGToDAGISel::SelectCC(SDValue LHS, SDValue RHS, + ISD::CondCode CC, DebugLoc dl) { + // Always select the LHS. + unsigned Opc; + + if (LHS.getValueType() == MVT::i32) { + unsigned Imm; + if (CC == ISD::SETEQ || CC == ISD::SETNE) { + if (isInt32Immediate(RHS, Imm)) { + // SETEQ/SETNE comparison with 16-bit immediate, fold it. + if (isUInt16(Imm)) + return SDValue(CurDAG->getMachineNode(PPC::CMPLWI, dl, MVT::i32, LHS, + getI32Imm(Imm & 0xFFFF)), 0); + // If this is a 16-bit signed immediate, fold it. + if (isInt16((int)Imm)) + return SDValue(CurDAG->getMachineNode(PPC::CMPWI, dl, MVT::i32, LHS, + getI32Imm(Imm & 0xFFFF)), 0); + + // For non-equality comparisons, the default code would materialize the + // constant, then compare against it, like this: + // lis r2, 4660 + // ori r2, r2, 22136 + // cmpw cr0, r3, r2 + // Since we are just comparing for equality, we can emit this instead: + // xoris r0,r3,0x1234 + // cmplwi cr0,r0,0x5678 + // beq cr0,L6 + SDValue Xor(CurDAG->getMachineNode(PPC::XORIS, dl, MVT::i32, LHS, + getI32Imm(Imm >> 16)), 0); + return SDValue(CurDAG->getMachineNode(PPC::CMPLWI, dl, MVT::i32, Xor, + getI32Imm(Imm & 0xFFFF)), 0); + } + Opc = PPC::CMPLW; + } else if (ISD::isUnsignedIntSetCC(CC)) { + if (isInt32Immediate(RHS, Imm) && isUInt16(Imm)) + return SDValue(CurDAG->getMachineNode(PPC::CMPLWI, dl, MVT::i32, LHS, + getI32Imm(Imm & 0xFFFF)), 0); + Opc = PPC::CMPLW; + } else { + short SImm; + if (isIntS16Immediate(RHS, SImm)) + return SDValue(CurDAG->getMachineNode(PPC::CMPWI, dl, MVT::i32, LHS, + getI32Imm((int)SImm & 0xFFFF)), + 0); + Opc = PPC::CMPW; + } + } else if (LHS.getValueType() == MVT::i64) { + uint64_t Imm; + if (CC == ISD::SETEQ || CC == ISD::SETNE) { + if (isInt64Immediate(RHS.getNode(), Imm)) { + // SETEQ/SETNE comparison with 16-bit immediate, fold it. + if (isUInt16(Imm)) + return SDValue(CurDAG->getMachineNode(PPC::CMPLDI, dl, MVT::i64, LHS, + getI32Imm(Imm & 0xFFFF)), 0); + // If this is a 16-bit signed immediate, fold it. + if (isInt16(Imm)) + return SDValue(CurDAG->getMachineNode(PPC::CMPDI, dl, MVT::i64, LHS, + getI32Imm(Imm & 0xFFFF)), 0); + + // For non-equality comparisons, the default code would materialize the + // constant, then compare against it, like this: + // lis r2, 4660 + // ori r2, r2, 22136 + // cmpd cr0, r3, r2 + // Since we are just comparing for equality, we can emit this instead: + // xoris r0,r3,0x1234 + // cmpldi cr0,r0,0x5678 + // beq cr0,L6 + if (isUInt32(Imm)) { + SDValue Xor(CurDAG->getMachineNode(PPC::XORIS8, dl, MVT::i64, LHS, + getI64Imm(Imm >> 16)), 0); + return SDValue(CurDAG->getMachineNode(PPC::CMPLDI, dl, MVT::i64, Xor, + getI64Imm(Imm & 0xFFFF)), 0); + } + } + Opc = PPC::CMPLD; + } else if (ISD::isUnsignedIntSetCC(CC)) { + if (isInt64Immediate(RHS.getNode(), Imm) && isUInt16(Imm)) + return SDValue(CurDAG->getMachineNode(PPC::CMPLDI, dl, MVT::i64, LHS, + getI64Imm(Imm & 0xFFFF)), 0); + Opc = PPC::CMPLD; + } else { + short SImm; + if (isIntS16Immediate(RHS, SImm)) + return SDValue(CurDAG->getMachineNode(PPC::CMPDI, dl, MVT::i64, LHS, + getI64Imm(SImm & 0xFFFF)), + 0); + Opc = PPC::CMPD; + } + } else if (LHS.getValueType() == MVT::f32) { + Opc = PPC::FCMPUS; + } else { + assert(LHS.getValueType() == MVT::f64 && "Unknown vt!"); + Opc = PPC::FCMPUD; + } + return SDValue(CurDAG->getMachineNode(Opc, dl, MVT::i32, LHS, RHS), 0); +} + +static PPC::Predicate getPredicateForSetCC(ISD::CondCode CC) { + switch (CC) { + case ISD::SETUEQ: + case ISD::SETONE: + case ISD::SETOLE: + case ISD::SETOGE: + llvm_unreachable("Should be lowered by legalize!"); + default: llvm_unreachable("Unknown condition!"); + case ISD::SETOEQ: + case ISD::SETEQ: return PPC::PRED_EQ; + case ISD::SETUNE: + case ISD::SETNE: return PPC::PRED_NE; + case ISD::SETOLT: + case ISD::SETLT: return PPC::PRED_LT; + case ISD::SETULE: + case ISD::SETLE: return PPC::PRED_LE; + case ISD::SETOGT: + case ISD::SETGT: return PPC::PRED_GT; + case ISD::SETUGE: + case ISD::SETGE: return PPC::PRED_GE; + case ISD::SETO: return PPC::PRED_NU; + case ISD::SETUO: return PPC::PRED_UN; + // These two are invalid for floating point. Assume we have int. + case ISD::SETULT: return PPC::PRED_LT; + case ISD::SETUGT: return PPC::PRED_GT; + } +} + +/// getCRIdxForSetCC - Return the index of the condition register field +/// associated with the SetCC condition, and whether or not the field is +/// treated as inverted. That is, lt = 0; ge = 0 inverted. +/// +/// If this returns with Other != -1, then the returned comparison is an or of +/// two simpler comparisons. In this case, Invert is guaranteed to be false. +static unsigned getCRIdxForSetCC(ISD::CondCode CC, bool &Invert, int &Other) { + Invert = false; + Other = -1; + switch (CC) { + default: llvm_unreachable("Unknown condition!"); + case ISD::SETOLT: + case ISD::SETLT: return 0; // Bit #0 = SETOLT + case ISD::SETOGT: + case ISD::SETGT: return 1; // Bit #1 = SETOGT + case ISD::SETOEQ: + case ISD::SETEQ: return 2; // Bit #2 = SETOEQ + case ISD::SETUO: return 3; // Bit #3 = SETUO + case ISD::SETUGE: + case ISD::SETGE: Invert = true; return 0; // !Bit #0 = SETUGE + case ISD::SETULE: + case ISD::SETLE: Invert = true; return 1; // !Bit #1 = SETULE + case ISD::SETUNE: + case ISD::SETNE: Invert = true; return 2; // !Bit #2 = SETUNE + case ISD::SETO: Invert = true; return 3; // !Bit #3 = SETO + case ISD::SETUEQ: + case ISD::SETOGE: + case ISD::SETOLE: + case ISD::SETONE: + llvm_unreachable("Invalid branch code: should be expanded by legalize"); + // These are invalid for floating point. Assume integer. + case ISD::SETULT: return 0; + case ISD::SETUGT: return 1; + } + return 0; +} + +SDNode *PPCDAGToDAGISel::SelectSETCC(SDValue Op) { + SDNode *N = Op.getNode(); + DebugLoc dl = N->getDebugLoc(); + unsigned Imm; + ISD::CondCode CC = cast(N->getOperand(2))->get(); + if (isInt32Immediate(N->getOperand(1), Imm)) { + // We can codegen setcc op, imm very efficiently compared to a brcond. + // Check for those cases here. + // setcc op, 0 + if (Imm == 0) { + SDValue Op = N->getOperand(0); + switch (CC) { + default: break; + case ISD::SETEQ: { + Op = SDValue(CurDAG->getMachineNode(PPC::CNTLZW, dl, MVT::i32, Op), 0); + SDValue Ops[] = { Op, getI32Imm(27), getI32Imm(5), getI32Imm(31) }; + return CurDAG->SelectNodeTo(N, PPC::RLWINM, MVT::i32, Ops, 4); + } + case ISD::SETNE: { + SDValue AD = + SDValue(CurDAG->getMachineNode(PPC::ADDIC, dl, MVT::i32, MVT::Flag, + Op, getI32Imm(~0U)), 0); + return CurDAG->SelectNodeTo(N, PPC::SUBFE, MVT::i32, AD, Op, + AD.getValue(1)); + } + case ISD::SETLT: { + SDValue Ops[] = { Op, getI32Imm(1), getI32Imm(31), getI32Imm(31) }; + return CurDAG->SelectNodeTo(N, PPC::RLWINM, MVT::i32, Ops, 4); + } + case ISD::SETGT: { + SDValue T = + SDValue(CurDAG->getMachineNode(PPC::NEG, dl, MVT::i32, Op), 0); + T = SDValue(CurDAG->getMachineNode(PPC::ANDC, dl, MVT::i32, T, Op), 0); + SDValue Ops[] = { T, getI32Imm(1), getI32Imm(31), getI32Imm(31) }; + return CurDAG->SelectNodeTo(N, PPC::RLWINM, MVT::i32, Ops, 4); + } + } + } else if (Imm == ~0U) { // setcc op, -1 + SDValue Op = N->getOperand(0); + switch (CC) { + default: break; + case ISD::SETEQ: + Op = SDValue(CurDAG->getMachineNode(PPC::ADDIC, dl, MVT::i32, MVT::Flag, + Op, getI32Imm(1)), 0); + return CurDAG->SelectNodeTo(N, PPC::ADDZE, MVT::i32, + SDValue(CurDAG->getMachineNode(PPC::LI, dl, + MVT::i32, + getI32Imm(0)), 0), + Op.getValue(1)); + case ISD::SETNE: { + Op = SDValue(CurDAG->getMachineNode(PPC::NOR, dl, MVT::i32, Op, Op), 0); + SDNode *AD = CurDAG->getMachineNode(PPC::ADDIC, dl, MVT::i32, MVT::Flag, + Op, getI32Imm(~0U)); + return CurDAG->SelectNodeTo(N, PPC::SUBFE, MVT::i32, SDValue(AD, 0), + Op, SDValue(AD, 1)); + } + case ISD::SETLT: { + SDValue AD = SDValue(CurDAG->getMachineNode(PPC::ADDI, dl, MVT::i32, Op, + getI32Imm(1)), 0); + SDValue AN = SDValue(CurDAG->getMachineNode(PPC::AND, dl, MVT::i32, AD, + Op), 0); + SDValue Ops[] = { AN, getI32Imm(1), getI32Imm(31), getI32Imm(31) }; + return CurDAG->SelectNodeTo(N, PPC::RLWINM, MVT::i32, Ops, 4); + } + case ISD::SETGT: { + SDValue Ops[] = { Op, getI32Imm(1), getI32Imm(31), getI32Imm(31) }; + Op = SDValue(CurDAG->getMachineNode(PPC::RLWINM, dl, MVT::i32, Ops, 4), + 0); + return CurDAG->SelectNodeTo(N, PPC::XORI, MVT::i32, Op, + getI32Imm(1)); + } + } + } + } + + bool Inv; + int OtherCondIdx; + unsigned Idx = getCRIdxForSetCC(CC, Inv, OtherCondIdx); + SDValue CCReg = SelectCC(N->getOperand(0), N->getOperand(1), CC, dl); + SDValue IntCR; + + // Force the ccreg into CR7. + SDValue CR7Reg = CurDAG->getRegister(PPC::CR7, MVT::i32); + + SDValue InFlag(0, 0); // Null incoming flag value. + CCReg = CurDAG->getCopyToReg(CurDAG->getEntryNode(), dl, CR7Reg, CCReg, + InFlag).getValue(1); + + if (PPCSubTarget.isGigaProcessor() && OtherCondIdx == -1) + IntCR = SDValue(CurDAG->getMachineNode(PPC::MFOCRF, dl, MVT::i32, CR7Reg, + CCReg), 0); + else + IntCR = SDValue(CurDAG->getMachineNode(PPC::MFCR, dl, MVT::i32, CCReg), 0); + + SDValue Ops[] = { IntCR, getI32Imm((32-(3-Idx)) & 31), + getI32Imm(31), getI32Imm(31) }; + if (OtherCondIdx == -1 && !Inv) + return CurDAG->SelectNodeTo(N, PPC::RLWINM, MVT::i32, Ops, 4); + + // Get the specified bit. + SDValue Tmp = + SDValue(CurDAG->getMachineNode(PPC::RLWINM, dl, MVT::i32, Ops, 4), 0); + if (Inv) { + assert(OtherCondIdx == -1 && "Can't have split plus negation"); + return CurDAG->SelectNodeTo(N, PPC::XORI, MVT::i32, Tmp, getI32Imm(1)); + } + + // Otherwise, we have to turn an operation like SETONE -> SETOLT | SETOGT. + // We already got the bit for the first part of the comparison (e.g. SETULE). + + // Get the other bit of the comparison. + Ops[1] = getI32Imm((32-(3-OtherCondIdx)) & 31); + SDValue OtherCond = + SDValue(CurDAG->getMachineNode(PPC::RLWINM, dl, MVT::i32, Ops, 4), 0); + + return CurDAG->SelectNodeTo(N, PPC::OR, MVT::i32, Tmp, OtherCond); +} + + +// Select - Convert the specified operand from a target-independent to a +// target-specific node if it hasn't already been changed. +SDNode *PPCDAGToDAGISel::Select(SDValue Op) { + SDNode *N = Op.getNode(); + DebugLoc dl = Op.getDebugLoc(); + if (N->isMachineOpcode()) + return NULL; // Already selected. + + switch (N->getOpcode()) { + default: break; + + case ISD::Constant: { + if (N->getValueType(0) == MVT::i64) { + // Get 64 bit value. + int64_t Imm = cast(N)->getZExtValue(); + // Assume no remaining bits. + unsigned Remainder = 0; + // Assume no shift required. + unsigned Shift = 0; + + // If it can't be represented as a 32 bit value. + if (!isInt32(Imm)) { + Shift = CountTrailingZeros_64(Imm); + int64_t ImmSh = static_cast(Imm) >> Shift; + + // If the shifted value fits 32 bits. + if (isInt32(ImmSh)) { + // Go with the shifted value. + Imm = ImmSh; + } else { + // Still stuck with a 64 bit value. + Remainder = Imm; + Shift = 32; + Imm >>= 32; + } + } + + // Intermediate operand. + SDNode *Result; + + // Handle first 32 bits. + unsigned Lo = Imm & 0xFFFF; + unsigned Hi = (Imm >> 16) & 0xFFFF; + + // Simple value. + if (isInt16(Imm)) { + // Just the Lo bits. + Result = CurDAG->getMachineNode(PPC::LI8, dl, MVT::i64, getI32Imm(Lo)); + } else if (Lo) { + // Handle the Hi bits. + unsigned OpC = Hi ? PPC::LIS8 : PPC::LI8; + Result = CurDAG->getMachineNode(OpC, dl, MVT::i64, getI32Imm(Hi)); + // And Lo bits. + Result = CurDAG->getMachineNode(PPC::ORI8, dl, MVT::i64, + SDValue(Result, 0), getI32Imm(Lo)); + } else { + // Just the Hi bits. + Result = CurDAG->getMachineNode(PPC::LIS8, dl, MVT::i64, getI32Imm(Hi)); + } + + // If no shift, we're done. + if (!Shift) return Result; + + // Shift for next step if the upper 32-bits were not zero. + if (Imm) { + Result = CurDAG->getMachineNode(PPC::RLDICR, dl, MVT::i64, + SDValue(Result, 0), + getI32Imm(Shift), + getI32Imm(63 - Shift)); + } + + // Add in the last bits as required. + if ((Hi = (Remainder >> 16) & 0xFFFF)) { + Result = CurDAG->getMachineNode(PPC::ORIS8, dl, MVT::i64, + SDValue(Result, 0), getI32Imm(Hi)); + } + if ((Lo = Remainder & 0xFFFF)) { + Result = CurDAG->getMachineNode(PPC::ORI8, dl, MVT::i64, + SDValue(Result, 0), getI32Imm(Lo)); + } + + return Result; + } + break; + } + + case ISD::SETCC: + return SelectSETCC(Op); + case PPCISD::GlobalBaseReg: + return getGlobalBaseReg(); + + case ISD::FrameIndex: { + int FI = cast(N)->getIndex(); + SDValue TFI = CurDAG->getTargetFrameIndex(FI, Op.getValueType()); + unsigned Opc = Op.getValueType() == MVT::i32 ? PPC::ADDI : PPC::ADDI8; + if (N->hasOneUse()) + return CurDAG->SelectNodeTo(N, Opc, Op.getValueType(), TFI, + getSmallIPtrImm(0)); + return CurDAG->getMachineNode(Opc, dl, Op.getValueType(), TFI, + getSmallIPtrImm(0)); + } + + case PPCISD::MFCR: { + SDValue InFlag = N->getOperand(1); + // Use MFOCRF if supported. + if (PPCSubTarget.isGigaProcessor()) + return CurDAG->getMachineNode(PPC::MFOCRF, dl, MVT::i32, + N->getOperand(0), InFlag); + else + return CurDAG->getMachineNode(PPC::MFCR, dl, MVT::i32, InFlag); + } + + case ISD::SDIV: { + // FIXME: since this depends on the setting of the carry flag from the srawi + // we should really be making notes about that for the scheduler. + // FIXME: It sure would be nice if we could cheaply recognize the + // srl/add/sra pattern the dag combiner will generate for this as + // sra/addze rather than having to handle sdiv ourselves. oh well. + unsigned Imm; + if (isInt32Immediate(N->getOperand(1), Imm)) { + SDValue N0 = N->getOperand(0); + if ((signed)Imm > 0 && isPowerOf2_32(Imm)) { + SDNode *Op = + CurDAG->getMachineNode(PPC::SRAWI, dl, MVT::i32, MVT::Flag, + N0, getI32Imm(Log2_32(Imm))); + return CurDAG->SelectNodeTo(N, PPC::ADDZE, MVT::i32, + SDValue(Op, 0), SDValue(Op, 1)); + } else if ((signed)Imm < 0 && isPowerOf2_32(-Imm)) { + SDNode *Op = + CurDAG->getMachineNode(PPC::SRAWI, dl, MVT::i32, MVT::Flag, + N0, getI32Imm(Log2_32(-Imm))); + SDValue PT = + SDValue(CurDAG->getMachineNode(PPC::ADDZE, dl, MVT::i32, + SDValue(Op, 0), SDValue(Op, 1)), + 0); + return CurDAG->SelectNodeTo(N, PPC::NEG, MVT::i32, PT); + } + } + + // Other cases are autogenerated. + break; + } + + case ISD::LOAD: { + // Handle preincrement loads. + LoadSDNode *LD = cast(Op); + EVT LoadedVT = LD->getMemoryVT(); + + // Normal loads are handled by code generated from the .td file. + if (LD->getAddressingMode() != ISD::PRE_INC) + break; + + SDValue Offset = LD->getOffset(); + if (isa(Offset) || + Offset.getOpcode() == ISD::TargetGlobalAddress) { + + unsigned Opcode; + bool isSExt = LD->getExtensionType() == ISD::SEXTLOAD; + if (LD->getValueType(0) != MVT::i64) { + // Handle PPC32 integer and normal FP loads. + assert((!isSExt || LoadedVT == MVT::i16) && "Invalid sext update load"); + switch (LoadedVT.getSimpleVT().SimpleTy) { + default: llvm_unreachable("Invalid PPC load type!"); + case MVT::f64: Opcode = PPC::LFDU; break; + case MVT::f32: Opcode = PPC::LFSU; break; + case MVT::i32: Opcode = PPC::LWZU; break; + case MVT::i16: Opcode = isSExt ? PPC::LHAU : PPC::LHZU; break; + case MVT::i1: + case MVT::i8: Opcode = PPC::LBZU; break; + } + } else { + assert(LD->getValueType(0) == MVT::i64 && "Unknown load result type!"); + assert((!isSExt || LoadedVT == MVT::i16) && "Invalid sext update load"); + switch (LoadedVT.getSimpleVT().SimpleTy) { + default: llvm_unreachable("Invalid PPC load type!"); + case MVT::i64: Opcode = PPC::LDU; break; + case MVT::i32: Opcode = PPC::LWZU8; break; + case MVT::i16: Opcode = isSExt ? PPC::LHAU8 : PPC::LHZU8; break; + case MVT::i1: + case MVT::i8: Opcode = PPC::LBZU8; break; + } + } + + SDValue Chain = LD->getChain(); + SDValue Base = LD->getBasePtr(); + SDValue Ops[] = { Offset, Base, Chain }; + // FIXME: PPC64 + return CurDAG->getMachineNode(Opcode, dl, LD->getValueType(0), + PPCLowering.getPointerTy(), + MVT::Other, Ops, 3); + } else { + llvm_unreachable("R+R preindex loads not supported yet!"); + } + } + + case ISD::AND: { + unsigned Imm, Imm2, SH, MB, ME; + + // If this is an and of a value rotated between 0 and 31 bits and then and'd + // with a mask, emit rlwinm + if (isInt32Immediate(N->getOperand(1), Imm) && + isRotateAndMask(N->getOperand(0).getNode(), Imm, false, SH, MB, ME)) { + SDValue Val = N->getOperand(0).getOperand(0); + SDValue Ops[] = { Val, getI32Imm(SH), getI32Imm(MB), getI32Imm(ME) }; + return CurDAG->SelectNodeTo(N, PPC::RLWINM, MVT::i32, Ops, 4); + } + // If this is just a masked value where the input is not handled above, and + // is not a rotate-left (handled by a pattern in the .td file), emit rlwinm + if (isInt32Immediate(N->getOperand(1), Imm) && + isRunOfOnes(Imm, MB, ME) && + N->getOperand(0).getOpcode() != ISD::ROTL) { + SDValue Val = N->getOperand(0); + SDValue Ops[] = { Val, getI32Imm(0), getI32Imm(MB), getI32Imm(ME) }; + return CurDAG->SelectNodeTo(N, PPC::RLWINM, MVT::i32, Ops, 4); + } + // AND X, 0 -> 0, not "rlwinm 32". + if (isInt32Immediate(N->getOperand(1), Imm) && (Imm == 0)) { + ReplaceUses(SDValue(N, 0), N->getOperand(1)); + return NULL; + } + // ISD::OR doesn't get all the bitfield insertion fun. + // (and (or x, c1), c2) where isRunOfOnes(~(c1^c2)) is a bitfield insert + if (isInt32Immediate(N->getOperand(1), Imm) && + N->getOperand(0).getOpcode() == ISD::OR && + isInt32Immediate(N->getOperand(0).getOperand(1), Imm2)) { + unsigned MB, ME; + Imm = ~(Imm^Imm2); + if (isRunOfOnes(Imm, MB, ME)) { + SDValue Ops[] = { N->getOperand(0).getOperand(0), + N->getOperand(0).getOperand(1), + getI32Imm(0), getI32Imm(MB),getI32Imm(ME) }; + return CurDAG->getMachineNode(PPC::RLWIMI, dl, MVT::i32, Ops, 5); + } + } + + // Other cases are autogenerated. + break; + } + case ISD::OR: + if (N->getValueType(0) == MVT::i32) + if (SDNode *I = SelectBitfieldInsert(N)) + return I; + + // Other cases are autogenerated. + break; + case ISD::SHL: { + unsigned Imm, SH, MB, ME; + if (isOpcWithIntImmediate(N->getOperand(0).getNode(), ISD::AND, Imm) && + isRotateAndMask(N, Imm, true, SH, MB, ME)) { + SDValue Ops[] = { N->getOperand(0).getOperand(0), + getI32Imm(SH), getI32Imm(MB), getI32Imm(ME) }; + return CurDAG->SelectNodeTo(N, PPC::RLWINM, MVT::i32, Ops, 4); + } + + // Other cases are autogenerated. + break; + } + case ISD::SRL: { + unsigned Imm, SH, MB, ME; + if (isOpcWithIntImmediate(N->getOperand(0).getNode(), ISD::AND, Imm) && + isRotateAndMask(N, Imm, true, SH, MB, ME)) { + SDValue Ops[] = { N->getOperand(0).getOperand(0), + getI32Imm(SH), getI32Imm(MB), getI32Imm(ME) }; + return CurDAG->SelectNodeTo(N, PPC::RLWINM, MVT::i32, Ops, 4); + } + + // Other cases are autogenerated. + break; + } + case ISD::SELECT_CC: { + ISD::CondCode CC = cast(N->getOperand(4))->get(); + + // Handle the setcc cases here. select_cc lhs, 0, 1, 0, cc + if (ConstantSDNode *N1C = dyn_cast(N->getOperand(1))) + if (ConstantSDNode *N2C = dyn_cast(N->getOperand(2))) + if (ConstantSDNode *N3C = dyn_cast(N->getOperand(3))) + if (N1C->isNullValue() && N3C->isNullValue() && + N2C->getZExtValue() == 1ULL && CC == ISD::SETNE && + // FIXME: Implement this optzn for PPC64. + N->getValueType(0) == MVT::i32) { + SDNode *Tmp = + CurDAG->getMachineNode(PPC::ADDIC, dl, MVT::i32, MVT::Flag, + N->getOperand(0), getI32Imm(~0U)); + return CurDAG->SelectNodeTo(N, PPC::SUBFE, MVT::i32, + SDValue(Tmp, 0), N->getOperand(0), + SDValue(Tmp, 1)); + } + + SDValue CCReg = SelectCC(N->getOperand(0), N->getOperand(1), CC, dl); + unsigned BROpc = getPredicateForSetCC(CC); + + unsigned SelectCCOp; + if (N->getValueType(0) == MVT::i32) + SelectCCOp = PPC::SELECT_CC_I4; + else if (N->getValueType(0) == MVT::i64) + SelectCCOp = PPC::SELECT_CC_I8; + else if (N->getValueType(0) == MVT::f32) + SelectCCOp = PPC::SELECT_CC_F4; + else if (N->getValueType(0) == MVT::f64) + SelectCCOp = PPC::SELECT_CC_F8; + else + SelectCCOp = PPC::SELECT_CC_VRRC; + + SDValue Ops[] = { CCReg, N->getOperand(2), N->getOperand(3), + getI32Imm(BROpc) }; + return CurDAG->SelectNodeTo(N, SelectCCOp, N->getValueType(0), Ops, 4); + } + case PPCISD::COND_BRANCH: { + // Op #0 is the Chain. + // Op #1 is the PPC::PRED_* number. + // Op #2 is the CR# + // Op #3 is the Dest MBB + // Op #4 is the Flag. + // Prevent PPC::PRED_* from being selected into LI. + SDValue Pred = + getI32Imm(cast(N->getOperand(1))->getZExtValue()); + SDValue Ops[] = { Pred, N->getOperand(2), N->getOperand(3), + N->getOperand(0), N->getOperand(4) }; + return CurDAG->SelectNodeTo(N, PPC::BCC, MVT::Other, Ops, 5); + } + case ISD::BR_CC: { + ISD::CondCode CC = cast(N->getOperand(1))->get(); + SDValue CondCode = SelectCC(N->getOperand(2), N->getOperand(3), CC, dl); + SDValue Ops[] = { getI32Imm(getPredicateForSetCC(CC)), CondCode, + N->getOperand(4), N->getOperand(0) }; + return CurDAG->SelectNodeTo(N, PPC::BCC, MVT::Other, Ops, 4); + } + case ISD::BRIND: { + // FIXME: Should custom lower this. + SDValue Chain = N->getOperand(0); + SDValue Target = N->getOperand(1); + unsigned Opc = Target.getValueType() == MVT::i32 ? PPC::MTCTR : PPC::MTCTR8; + Chain = SDValue(CurDAG->getMachineNode(Opc, dl, MVT::Other, Target, + Chain), 0); + return CurDAG->SelectNodeTo(N, PPC::BCTR, MVT::Other, Chain); + } + } + + return SelectCode(Op); +} + + + +/// createPPCISelDag - This pass converts a legalized DAG into a +/// PowerPC-specific DAG, ready for instruction scheduling. +/// +FunctionPass *llvm::createPPCISelDag(PPCTargetMachine &TM) { + return new PPCDAGToDAGISel(TM); +} + diff --git a/libclamav/c++/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/libclamav/c++/llvm/lib/Target/PowerPC/PPCISelLowering.cpp new file mode 100644 index 000000000..30a7861a6 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/PowerPC/PPCISelLowering.cpp @@ -0,0 +1,5397 @@ +//===-- PPCISelLowering.cpp - PPC DAG Lowering Implementation -------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the PPCISelLowering class. +// +//===----------------------------------------------------------------------===// + +#include "PPCISelLowering.h" +#include "PPCMachineFunctionInfo.h" +#include "PPCPredicates.h" +#include "PPCTargetMachine.h" +#include "PPCPerfectShuffle.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/VectorExtras.h" +#include "llvm/CodeGen/CallingConvLower.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/PseudoSourceValue.h" +#include "llvm/CodeGen/SelectionDAG.h" +#include "llvm/CallingConv.h" +#include "llvm/Constants.h" +#include "llvm/Function.h" +#include "llvm/Intrinsics.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/Target/TargetOptions.h" +#include "llvm/Target/TargetLoweringObjectFile.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/DerivedTypes.h" +using namespace llvm; + +static bool CC_PPC_SVR4_Custom_Dummy(unsigned &ValNo, EVT &ValVT, EVT &LocVT, + CCValAssign::LocInfo &LocInfo, + ISD::ArgFlagsTy &ArgFlags, + CCState &State); +static bool CC_PPC_SVR4_Custom_AlignArgRegs(unsigned &ValNo, EVT &ValVT, + EVT &LocVT, + CCValAssign::LocInfo &LocInfo, + ISD::ArgFlagsTy &ArgFlags, + CCState &State); +static bool CC_PPC_SVR4_Custom_AlignFPArgRegs(unsigned &ValNo, EVT &ValVT, + EVT &LocVT, + CCValAssign::LocInfo &LocInfo, + ISD::ArgFlagsTy &ArgFlags, + CCState &State); + +static cl::opt EnablePPCPreinc("enable-ppc-preinc", +cl::desc("enable preincrement load/store generation on PPC (experimental)"), + cl::Hidden); + +static TargetLoweringObjectFile *CreateTLOF(const PPCTargetMachine &TM) { + if (TM.getSubtargetImpl()->isDarwin()) + return new TargetLoweringObjectFileMachO(); + return new TargetLoweringObjectFileELF(); +} + + +PPCTargetLowering::PPCTargetLowering(PPCTargetMachine &TM) + : TargetLowering(TM, CreateTLOF(TM)), PPCSubTarget(*TM.getSubtargetImpl()) { + + setPow2DivIsCheap(); + + // Use _setjmp/_longjmp instead of setjmp/longjmp. + setUseUnderscoreSetJmp(true); + setUseUnderscoreLongJmp(true); + + // Set up the register classes. + addRegisterClass(MVT::i32, PPC::GPRCRegisterClass); + addRegisterClass(MVT::f32, PPC::F4RCRegisterClass); + addRegisterClass(MVT::f64, PPC::F8RCRegisterClass); + + // PowerPC has an i16 but no i8 (or i1) SEXTLOAD + setLoadExtAction(ISD::SEXTLOAD, MVT::i1, Promote); + setLoadExtAction(ISD::SEXTLOAD, MVT::i8, Expand); + + setTruncStoreAction(MVT::f64, MVT::f32, Expand); + + // PowerPC has pre-inc load and store's. + setIndexedLoadAction(ISD::PRE_INC, MVT::i1, Legal); + setIndexedLoadAction(ISD::PRE_INC, MVT::i8, Legal); + setIndexedLoadAction(ISD::PRE_INC, MVT::i16, Legal); + setIndexedLoadAction(ISD::PRE_INC, MVT::i32, Legal); + setIndexedLoadAction(ISD::PRE_INC, MVT::i64, Legal); + setIndexedStoreAction(ISD::PRE_INC, MVT::i1, Legal); + setIndexedStoreAction(ISD::PRE_INC, MVT::i8, Legal); + setIndexedStoreAction(ISD::PRE_INC, MVT::i16, Legal); + setIndexedStoreAction(ISD::PRE_INC, MVT::i32, Legal); + setIndexedStoreAction(ISD::PRE_INC, MVT::i64, Legal); + + // This is used in the ppcf128->int sequence. Note it has different semantics + // from FP_ROUND: that rounds to nearest, this rounds to zero. + setOperationAction(ISD::FP_ROUND_INREG, MVT::ppcf128, Custom); + + // PowerPC has no SREM/UREM instructions + setOperationAction(ISD::SREM, MVT::i32, Expand); + setOperationAction(ISD::UREM, MVT::i32, Expand); + setOperationAction(ISD::SREM, MVT::i64, Expand); + setOperationAction(ISD::UREM, MVT::i64, Expand); + + // Don't use SMUL_LOHI/UMUL_LOHI or SDIVREM/UDIVREM to lower SREM/UREM. + setOperationAction(ISD::UMUL_LOHI, MVT::i32, Expand); + setOperationAction(ISD::SMUL_LOHI, MVT::i32, Expand); + setOperationAction(ISD::UMUL_LOHI, MVT::i64, Expand); + setOperationAction(ISD::SMUL_LOHI, MVT::i64, Expand); + setOperationAction(ISD::UDIVREM, MVT::i32, Expand); + setOperationAction(ISD::SDIVREM, MVT::i32, Expand); + setOperationAction(ISD::UDIVREM, MVT::i64, Expand); + setOperationAction(ISD::SDIVREM, MVT::i64, Expand); + + // We don't support sin/cos/sqrt/fmod/pow + setOperationAction(ISD::FSIN , MVT::f64, Expand); + setOperationAction(ISD::FCOS , MVT::f64, Expand); + setOperationAction(ISD::FREM , MVT::f64, Expand); + setOperationAction(ISD::FPOW , MVT::f64, Expand); + setOperationAction(ISD::FSIN , MVT::f32, Expand); + setOperationAction(ISD::FCOS , MVT::f32, Expand); + setOperationAction(ISD::FREM , MVT::f32, Expand); + setOperationAction(ISD::FPOW , MVT::f32, Expand); + + setOperationAction(ISD::FLT_ROUNDS_, MVT::i32, Custom); + + // If we're enabling GP optimizations, use hardware square root + if (!TM.getSubtarget().hasFSQRT()) { + setOperationAction(ISD::FSQRT, MVT::f64, Expand); + setOperationAction(ISD::FSQRT, MVT::f32, Expand); + } + + setOperationAction(ISD::FCOPYSIGN, MVT::f64, Expand); + setOperationAction(ISD::FCOPYSIGN, MVT::f32, Expand); + + // PowerPC does not have BSWAP, CTPOP or CTTZ + setOperationAction(ISD::BSWAP, MVT::i32 , Expand); + setOperationAction(ISD::CTPOP, MVT::i32 , Expand); + setOperationAction(ISD::CTTZ , MVT::i32 , Expand); + setOperationAction(ISD::BSWAP, MVT::i64 , Expand); + setOperationAction(ISD::CTPOP, MVT::i64 , Expand); + setOperationAction(ISD::CTTZ , MVT::i64 , Expand); + + // PowerPC does not have ROTR + setOperationAction(ISD::ROTR, MVT::i32 , Expand); + setOperationAction(ISD::ROTR, MVT::i64 , Expand); + + // PowerPC does not have Select + setOperationAction(ISD::SELECT, MVT::i32, Expand); + setOperationAction(ISD::SELECT, MVT::i64, Expand); + setOperationAction(ISD::SELECT, MVT::f32, Expand); + setOperationAction(ISD::SELECT, MVT::f64, Expand); + + // PowerPC wants to turn select_cc of FP into fsel when possible. + setOperationAction(ISD::SELECT_CC, MVT::f32, Custom); + setOperationAction(ISD::SELECT_CC, MVT::f64, Custom); + + // PowerPC wants to optimize integer setcc a bit + setOperationAction(ISD::SETCC, MVT::i32, Custom); + + // PowerPC does not have BRCOND which requires SetCC + setOperationAction(ISD::BRCOND, MVT::Other, Expand); + + setOperationAction(ISD::BR_JT, MVT::Other, Expand); + + // PowerPC turns FP_TO_SINT into FCTIWZ and some load/stores. + setOperationAction(ISD::FP_TO_SINT, MVT::i32, Custom); + + // PowerPC does not have [U|S]INT_TO_FP + setOperationAction(ISD::SINT_TO_FP, MVT::i32, Expand); + setOperationAction(ISD::UINT_TO_FP, MVT::i32, Expand); + + setOperationAction(ISD::BIT_CONVERT, MVT::f32, Expand); + setOperationAction(ISD::BIT_CONVERT, MVT::i32, Expand); + setOperationAction(ISD::BIT_CONVERT, MVT::i64, Expand); + setOperationAction(ISD::BIT_CONVERT, MVT::f64, Expand); + + // We cannot sextinreg(i1). Expand to shifts. + setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Expand); + + setOperationAction(ISD::EXCEPTIONADDR, MVT::i64, Expand); + setOperationAction(ISD::EHSELECTION, MVT::i64, Expand); + setOperationAction(ISD::EXCEPTIONADDR, MVT::i32, Expand); + setOperationAction(ISD::EHSELECTION, MVT::i32, Expand); + + + // We want to legalize GlobalAddress and ConstantPool nodes into the + // appropriate instructions to materialize the address. + setOperationAction(ISD::GlobalAddress, MVT::i32, Custom); + setOperationAction(ISD::GlobalTLSAddress, MVT::i32, Custom); + setOperationAction(ISD::BlockAddress, MVT::i32, Custom); + setOperationAction(ISD::ConstantPool, MVT::i32, Custom); + setOperationAction(ISD::JumpTable, MVT::i32, Custom); + setOperationAction(ISD::GlobalAddress, MVT::i64, Custom); + setOperationAction(ISD::GlobalTLSAddress, MVT::i64, Custom); + setOperationAction(ISD::BlockAddress, MVT::i64, Custom); + setOperationAction(ISD::ConstantPool, MVT::i64, Custom); + setOperationAction(ISD::JumpTable, MVT::i64, Custom); + + // TRAP is legal. + setOperationAction(ISD::TRAP, MVT::Other, Legal); + + // TRAMPOLINE is custom lowered. + setOperationAction(ISD::TRAMPOLINE, MVT::Other, Custom); + + // VASTART needs to be custom lowered to use the VarArgsFrameIndex + setOperationAction(ISD::VASTART , MVT::Other, Custom); + + // VAARG is custom lowered with the 32-bit SVR4 ABI. + if ( TM.getSubtarget().isSVR4ABI() + && !TM.getSubtarget().isPPC64()) + setOperationAction(ISD::VAARG, MVT::Other, Custom); + else + setOperationAction(ISD::VAARG, MVT::Other, Expand); + + // Use the default implementation. + setOperationAction(ISD::VACOPY , MVT::Other, Expand); + setOperationAction(ISD::VAEND , MVT::Other, Expand); + setOperationAction(ISD::STACKSAVE , MVT::Other, Expand); + setOperationAction(ISD::STACKRESTORE , MVT::Other, Custom); + setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32 , Custom); + setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i64 , Custom); + + // We want to custom lower some of our intrinsics. + setOperationAction(ISD::INTRINSIC_WO_CHAIN, MVT::Other, Custom); + + // Comparisons that require checking two conditions. + setCondCodeAction(ISD::SETULT, MVT::f32, Expand); + setCondCodeAction(ISD::SETULT, MVT::f64, Expand); + setCondCodeAction(ISD::SETUGT, MVT::f32, Expand); + setCondCodeAction(ISD::SETUGT, MVT::f64, Expand); + setCondCodeAction(ISD::SETUEQ, MVT::f32, Expand); + setCondCodeAction(ISD::SETUEQ, MVT::f64, Expand); + setCondCodeAction(ISD::SETOGE, MVT::f32, Expand); + setCondCodeAction(ISD::SETOGE, MVT::f64, Expand); + setCondCodeAction(ISD::SETOLE, MVT::f32, Expand); + setCondCodeAction(ISD::SETOLE, MVT::f64, Expand); + setCondCodeAction(ISD::SETONE, MVT::f32, Expand); + setCondCodeAction(ISD::SETONE, MVT::f64, Expand); + + if (TM.getSubtarget().has64BitSupport()) { + // They also have instructions for converting between i64 and fp. + setOperationAction(ISD::FP_TO_SINT, MVT::i64, Custom); + setOperationAction(ISD::FP_TO_UINT, MVT::i64, Expand); + setOperationAction(ISD::SINT_TO_FP, MVT::i64, Custom); + setOperationAction(ISD::UINT_TO_FP, MVT::i64, Expand); + // This is just the low 32 bits of a (signed) fp->i64 conversion. + // We cannot do this with Promote because i64 is not a legal type. + setOperationAction(ISD::FP_TO_UINT, MVT::i32, Custom); + + // FIXME: disable this lowered code. This generates 64-bit register values, + // and we don't model the fact that the top part is clobbered by calls. We + // need to flag these together so that the value isn't live across a call. + //setOperationAction(ISD::SINT_TO_FP, MVT::i32, Custom); + } else { + // PowerPC does not have FP_TO_UINT on 32-bit implementations. + setOperationAction(ISD::FP_TO_UINT, MVT::i32, Expand); + } + + if (TM.getSubtarget().use64BitRegs()) { + // 64-bit PowerPC implementations can support i64 types directly + addRegisterClass(MVT::i64, PPC::G8RCRegisterClass); + // BUILD_PAIR can't be handled natively, and should be expanded to shl/or + setOperationAction(ISD::BUILD_PAIR, MVT::i64, Expand); + // 64-bit PowerPC wants to expand i128 shifts itself. + setOperationAction(ISD::SHL_PARTS, MVT::i64, Custom); + setOperationAction(ISD::SRA_PARTS, MVT::i64, Custom); + setOperationAction(ISD::SRL_PARTS, MVT::i64, Custom); + } else { + // 32-bit PowerPC wants to expand i64 shifts itself. + setOperationAction(ISD::SHL_PARTS, MVT::i32, Custom); + setOperationAction(ISD::SRA_PARTS, MVT::i32, Custom); + setOperationAction(ISD::SRL_PARTS, MVT::i32, Custom); + } + + if (TM.getSubtarget().hasAltivec()) { + // First set operation action for all vector types to expand. Then we + // will selectively turn on ones that can be effectively codegen'd. + for (unsigned i = (unsigned)MVT::FIRST_VECTOR_VALUETYPE; + i <= (unsigned)MVT::LAST_VECTOR_VALUETYPE; ++i) { + MVT::SimpleValueType VT = (MVT::SimpleValueType)i; + + // add/sub are legal for all supported vector VT's. + setOperationAction(ISD::ADD , VT, Legal); + setOperationAction(ISD::SUB , VT, Legal); + + // We promote all shuffles to v16i8. + setOperationAction(ISD::VECTOR_SHUFFLE, VT, Promote); + AddPromotedToType (ISD::VECTOR_SHUFFLE, VT, MVT::v16i8); + + // We promote all non-typed operations to v4i32. + setOperationAction(ISD::AND , VT, Promote); + AddPromotedToType (ISD::AND , VT, MVT::v4i32); + setOperationAction(ISD::OR , VT, Promote); + AddPromotedToType (ISD::OR , VT, MVT::v4i32); + setOperationAction(ISD::XOR , VT, Promote); + AddPromotedToType (ISD::XOR , VT, MVT::v4i32); + setOperationAction(ISD::LOAD , VT, Promote); + AddPromotedToType (ISD::LOAD , VT, MVT::v4i32); + setOperationAction(ISD::SELECT, VT, Promote); + AddPromotedToType (ISD::SELECT, VT, MVT::v4i32); + setOperationAction(ISD::STORE, VT, Promote); + AddPromotedToType (ISD::STORE, VT, MVT::v4i32); + + // No other operations are legal. + setOperationAction(ISD::MUL , VT, Expand); + setOperationAction(ISD::SDIV, VT, Expand); + setOperationAction(ISD::SREM, VT, Expand); + setOperationAction(ISD::UDIV, VT, Expand); + setOperationAction(ISD::UREM, VT, Expand); + setOperationAction(ISD::FDIV, VT, Expand); + setOperationAction(ISD::FNEG, VT, Expand); + setOperationAction(ISD::EXTRACT_VECTOR_ELT, VT, Expand); + setOperationAction(ISD::INSERT_VECTOR_ELT, VT, Expand); + setOperationAction(ISD::BUILD_VECTOR, VT, Expand); + setOperationAction(ISD::UMUL_LOHI, VT, Expand); + setOperationAction(ISD::SMUL_LOHI, VT, Expand); + setOperationAction(ISD::UDIVREM, VT, Expand); + setOperationAction(ISD::SDIVREM, VT, Expand); + setOperationAction(ISD::SCALAR_TO_VECTOR, VT, Expand); + setOperationAction(ISD::FPOW, VT, Expand); + setOperationAction(ISD::CTPOP, VT, Expand); + setOperationAction(ISD::CTLZ, VT, Expand); + setOperationAction(ISD::CTTZ, VT, Expand); + } + + // We can custom expand all VECTOR_SHUFFLEs to VPERM, others we can handle + // with merges, splats, etc. + setOperationAction(ISD::VECTOR_SHUFFLE, MVT::v16i8, Custom); + + setOperationAction(ISD::AND , MVT::v4i32, Legal); + setOperationAction(ISD::OR , MVT::v4i32, Legal); + setOperationAction(ISD::XOR , MVT::v4i32, Legal); + setOperationAction(ISD::LOAD , MVT::v4i32, Legal); + setOperationAction(ISD::SELECT, MVT::v4i32, Expand); + setOperationAction(ISD::STORE , MVT::v4i32, Legal); + + addRegisterClass(MVT::v4f32, PPC::VRRCRegisterClass); + addRegisterClass(MVT::v4i32, PPC::VRRCRegisterClass); + addRegisterClass(MVT::v8i16, PPC::VRRCRegisterClass); + addRegisterClass(MVT::v16i8, PPC::VRRCRegisterClass); + + setOperationAction(ISD::MUL, MVT::v4f32, Legal); + setOperationAction(ISD::MUL, MVT::v4i32, Custom); + setOperationAction(ISD::MUL, MVT::v8i16, Custom); + setOperationAction(ISD::MUL, MVT::v16i8, Custom); + + setOperationAction(ISD::SCALAR_TO_VECTOR, MVT::v4f32, Custom); + setOperationAction(ISD::SCALAR_TO_VECTOR, MVT::v4i32, Custom); + + setOperationAction(ISD::BUILD_VECTOR, MVT::v16i8, Custom); + setOperationAction(ISD::BUILD_VECTOR, MVT::v8i16, Custom); + setOperationAction(ISD::BUILD_VECTOR, MVT::v4i32, Custom); + setOperationAction(ISD::BUILD_VECTOR, MVT::v4f32, Custom); + } + + setShiftAmountType(MVT::i32); + setBooleanContents(ZeroOrOneBooleanContent); + + if (TM.getSubtarget().isPPC64()) { + setStackPointerRegisterToSaveRestore(PPC::X1); + setExceptionPointerRegister(PPC::X3); + setExceptionSelectorRegister(PPC::X4); + } else { + setStackPointerRegisterToSaveRestore(PPC::R1); + setExceptionPointerRegister(PPC::R3); + setExceptionSelectorRegister(PPC::R4); + } + + // We have target-specific dag combine patterns for the following nodes: + setTargetDAGCombine(ISD::SINT_TO_FP); + setTargetDAGCombine(ISD::STORE); + setTargetDAGCombine(ISD::BR_CC); + setTargetDAGCombine(ISD::BSWAP); + + // Darwin long double math library functions have $LDBL128 appended. + if (TM.getSubtarget().isDarwin()) { + setLibcallName(RTLIB::COS_PPCF128, "cosl$LDBL128"); + setLibcallName(RTLIB::POW_PPCF128, "powl$LDBL128"); + setLibcallName(RTLIB::REM_PPCF128, "fmodl$LDBL128"); + setLibcallName(RTLIB::SIN_PPCF128, "sinl$LDBL128"); + setLibcallName(RTLIB::SQRT_PPCF128, "sqrtl$LDBL128"); + setLibcallName(RTLIB::LOG_PPCF128, "logl$LDBL128"); + setLibcallName(RTLIB::LOG2_PPCF128, "log2l$LDBL128"); + setLibcallName(RTLIB::LOG10_PPCF128, "log10l$LDBL128"); + setLibcallName(RTLIB::EXP_PPCF128, "expl$LDBL128"); + setLibcallName(RTLIB::EXP2_PPCF128, "exp2l$LDBL128"); + } + + computeRegisterProperties(); +} + +/// getByValTypeAlignment - Return the desired alignment for ByVal aggregate +/// function arguments in the caller parameter area. +unsigned PPCTargetLowering::getByValTypeAlignment(const Type *Ty) const { + TargetMachine &TM = getTargetMachine(); + // Darwin passes everything on 4 byte boundary. + if (TM.getSubtarget().isDarwin()) + return 4; + // FIXME SVR4 TBD + return 4; +} + +const char *PPCTargetLowering::getTargetNodeName(unsigned Opcode) const { + switch (Opcode) { + default: return 0; + case PPCISD::FSEL: return "PPCISD::FSEL"; + case PPCISD::FCFID: return "PPCISD::FCFID"; + case PPCISD::FCTIDZ: return "PPCISD::FCTIDZ"; + case PPCISD::FCTIWZ: return "PPCISD::FCTIWZ"; + case PPCISD::STFIWX: return "PPCISD::STFIWX"; + case PPCISD::VMADDFP: return "PPCISD::VMADDFP"; + case PPCISD::VNMSUBFP: return "PPCISD::VNMSUBFP"; + case PPCISD::VPERM: return "PPCISD::VPERM"; + case PPCISD::Hi: return "PPCISD::Hi"; + case PPCISD::Lo: return "PPCISD::Lo"; + case PPCISD::TOC_ENTRY: return "PPCISD::TOC_ENTRY"; + case PPCISD::DYNALLOC: return "PPCISD::DYNALLOC"; + case PPCISD::GlobalBaseReg: return "PPCISD::GlobalBaseReg"; + case PPCISD::SRL: return "PPCISD::SRL"; + case PPCISD::SRA: return "PPCISD::SRA"; + case PPCISD::SHL: return "PPCISD::SHL"; + case PPCISD::EXTSW_32: return "PPCISD::EXTSW_32"; + case PPCISD::STD_32: return "PPCISD::STD_32"; + case PPCISD::CALL_SVR4: return "PPCISD::CALL_SVR4"; + case PPCISD::CALL_Darwin: return "PPCISD::CALL_Darwin"; + case PPCISD::NOP: return "PPCISD::NOP"; + case PPCISD::MTCTR: return "PPCISD::MTCTR"; + case PPCISD::BCTRL_Darwin: return "PPCISD::BCTRL_Darwin"; + case PPCISD::BCTRL_SVR4: return "PPCISD::BCTRL_SVR4"; + case PPCISD::RET_FLAG: return "PPCISD::RET_FLAG"; + case PPCISD::MFCR: return "PPCISD::MFCR"; + case PPCISD::VCMP: return "PPCISD::VCMP"; + case PPCISD::VCMPo: return "PPCISD::VCMPo"; + case PPCISD::LBRX: return "PPCISD::LBRX"; + case PPCISD::STBRX: return "PPCISD::STBRX"; + case PPCISD::LARX: return "PPCISD::LARX"; + case PPCISD::STCX: return "PPCISD::STCX"; + case PPCISD::COND_BRANCH: return "PPCISD::COND_BRANCH"; + case PPCISD::MFFS: return "PPCISD::MFFS"; + case PPCISD::MTFSB0: return "PPCISD::MTFSB0"; + case PPCISD::MTFSB1: return "PPCISD::MTFSB1"; + case PPCISD::FADDRTZ: return "PPCISD::FADDRTZ"; + case PPCISD::MTFSF: return "PPCISD::MTFSF"; + case PPCISD::TC_RETURN: return "PPCISD::TC_RETURN"; + } +} + +MVT::SimpleValueType PPCTargetLowering::getSetCCResultType(EVT VT) const { + return MVT::i32; +} + +/// getFunctionAlignment - Return the Log2 alignment of this function. +unsigned PPCTargetLowering::getFunctionAlignment(const Function *F) const { + if (getTargetMachine().getSubtarget().isDarwin()) + return F->hasFnAttr(Attribute::OptimizeForSize) ? 2 : 4; + else + return 2; +} + +//===----------------------------------------------------------------------===// +// Node matching predicates, for use by the tblgen matching code. +//===----------------------------------------------------------------------===// + +/// isFloatingPointZero - Return true if this is 0.0 or -0.0. +static bool isFloatingPointZero(SDValue Op) { + if (ConstantFPSDNode *CFP = dyn_cast(Op)) + return CFP->getValueAPF().isZero(); + else if (ISD::isEXTLoad(Op.getNode()) || ISD::isNON_EXTLoad(Op.getNode())) { + // Maybe this has already been legalized into the constant pool? + if (ConstantPoolSDNode *CP = dyn_cast(Op.getOperand(1))) + if (ConstantFP *CFP = dyn_cast(CP->getConstVal())) + return CFP->getValueAPF().isZero(); + } + return false; +} + +/// isConstantOrUndef - Op is either an undef node or a ConstantSDNode. Return +/// true if Op is undef or if it matches the specified value. +static bool isConstantOrUndef(int Op, int Val) { + return Op < 0 || Op == Val; +} + +/// isVPKUHUMShuffleMask - Return true if this is the shuffle mask for a +/// VPKUHUM instruction. +bool PPC::isVPKUHUMShuffleMask(ShuffleVectorSDNode *N, bool isUnary) { + if (!isUnary) { + for (unsigned i = 0; i != 16; ++i) + if (!isConstantOrUndef(N->getMaskElt(i), i*2+1)) + return false; + } else { + for (unsigned i = 0; i != 8; ++i) + if (!isConstantOrUndef(N->getMaskElt(i), i*2+1) || + !isConstantOrUndef(N->getMaskElt(i+8), i*2+1)) + return false; + } + return true; +} + +/// isVPKUWUMShuffleMask - Return true if this is the shuffle mask for a +/// VPKUWUM instruction. +bool PPC::isVPKUWUMShuffleMask(ShuffleVectorSDNode *N, bool isUnary) { + if (!isUnary) { + for (unsigned i = 0; i != 16; i += 2) + if (!isConstantOrUndef(N->getMaskElt(i ), i*2+2) || + !isConstantOrUndef(N->getMaskElt(i+1), i*2+3)) + return false; + } else { + for (unsigned i = 0; i != 8; i += 2) + if (!isConstantOrUndef(N->getMaskElt(i ), i*2+2) || + !isConstantOrUndef(N->getMaskElt(i+1), i*2+3) || + !isConstantOrUndef(N->getMaskElt(i+8), i*2+2) || + !isConstantOrUndef(N->getMaskElt(i+9), i*2+3)) + return false; + } + return true; +} + +/// isVMerge - Common function, used to match vmrg* shuffles. +/// +static bool isVMerge(ShuffleVectorSDNode *N, unsigned UnitSize, + unsigned LHSStart, unsigned RHSStart) { + assert(N->getValueType(0) == MVT::v16i8 && + "PPC only supports shuffles by bytes!"); + assert((UnitSize == 1 || UnitSize == 2 || UnitSize == 4) && + "Unsupported merge size!"); + + for (unsigned i = 0; i != 8/UnitSize; ++i) // Step over units + for (unsigned j = 0; j != UnitSize; ++j) { // Step over bytes within unit + if (!isConstantOrUndef(N->getMaskElt(i*UnitSize*2+j), + LHSStart+j+i*UnitSize) || + !isConstantOrUndef(N->getMaskElt(i*UnitSize*2+UnitSize+j), + RHSStart+j+i*UnitSize)) + return false; + } + return true; +} + +/// isVMRGLShuffleMask - Return true if this is a shuffle mask suitable for +/// a VRGL* instruction with the specified unit size (1,2 or 4 bytes). +bool PPC::isVMRGLShuffleMask(ShuffleVectorSDNode *N, unsigned UnitSize, + bool isUnary) { + if (!isUnary) + return isVMerge(N, UnitSize, 8, 24); + return isVMerge(N, UnitSize, 8, 8); +} + +/// isVMRGHShuffleMask - Return true if this is a shuffle mask suitable for +/// a VRGH* instruction with the specified unit size (1,2 or 4 bytes). +bool PPC::isVMRGHShuffleMask(ShuffleVectorSDNode *N, unsigned UnitSize, + bool isUnary) { + if (!isUnary) + return isVMerge(N, UnitSize, 0, 16); + return isVMerge(N, UnitSize, 0, 0); +} + + +/// isVSLDOIShuffleMask - If this is a vsldoi shuffle mask, return the shift +/// amount, otherwise return -1. +int PPC::isVSLDOIShuffleMask(SDNode *N, bool isUnary) { + assert(N->getValueType(0) == MVT::v16i8 && + "PPC only supports shuffles by bytes!"); + + ShuffleVectorSDNode *SVOp = cast(N); + + // Find the first non-undef value in the shuffle mask. + unsigned i; + for (i = 0; i != 16 && SVOp->getMaskElt(i) < 0; ++i) + /*search*/; + + if (i == 16) return -1; // all undef. + + // Otherwise, check to see if the rest of the elements are consecutively + // numbered from this value. + unsigned ShiftAmt = SVOp->getMaskElt(i); + if (ShiftAmt < i) return -1; + ShiftAmt -= i; + + if (!isUnary) { + // Check the rest of the elements to see if they are consecutive. + for (++i; i != 16; ++i) + if (!isConstantOrUndef(SVOp->getMaskElt(i), ShiftAmt+i)) + return -1; + } else { + // Check the rest of the elements to see if they are consecutive. + for (++i; i != 16; ++i) + if (!isConstantOrUndef(SVOp->getMaskElt(i), (ShiftAmt+i) & 15)) + return -1; + } + return ShiftAmt; +} + +/// isSplatShuffleMask - Return true if the specified VECTOR_SHUFFLE operand +/// specifies a splat of a single element that is suitable for input to +/// VSPLTB/VSPLTH/VSPLTW. +bool PPC::isSplatShuffleMask(ShuffleVectorSDNode *N, unsigned EltSize) { + assert(N->getValueType(0) == MVT::v16i8 && + (EltSize == 1 || EltSize == 2 || EltSize == 4)); + + // This is a splat operation if each element of the permute is the same, and + // if the value doesn't reference the second vector. + unsigned ElementBase = N->getMaskElt(0); + + // FIXME: Handle UNDEF elements too! + if (ElementBase >= 16) + return false; + + // Check that the indices are consecutive, in the case of a multi-byte element + // splatted with a v16i8 mask. + for (unsigned i = 1; i != EltSize; ++i) + if (N->getMaskElt(i) < 0 || N->getMaskElt(i) != (int)(i+ElementBase)) + return false; + + for (unsigned i = EltSize, e = 16; i != e; i += EltSize) { + if (N->getMaskElt(i) < 0) continue; + for (unsigned j = 0; j != EltSize; ++j) + if (N->getMaskElt(i+j) != N->getMaskElt(j)) + return false; + } + return true; +} + +/// isAllNegativeZeroVector - Returns true if all elements of build_vector +/// are -0.0. +bool PPC::isAllNegativeZeroVector(SDNode *N) { + BuildVectorSDNode *BV = cast(N); + + APInt APVal, APUndef; + unsigned BitSize; + bool HasAnyUndefs; + + if (BV->isConstantSplat(APVal, APUndef, BitSize, HasAnyUndefs, 32, true)) + if (ConstantFPSDNode *CFP = dyn_cast(N->getOperand(0))) + return CFP->getValueAPF().isNegZero(); + + return false; +} + +/// getVSPLTImmediate - Return the appropriate VSPLT* immediate to splat the +/// specified isSplatShuffleMask VECTOR_SHUFFLE mask. +unsigned PPC::getVSPLTImmediate(SDNode *N, unsigned EltSize) { + ShuffleVectorSDNode *SVOp = cast(N); + assert(isSplatShuffleMask(SVOp, EltSize)); + return SVOp->getMaskElt(0) / EltSize; +} + +/// get_VSPLTI_elt - If this is a build_vector of constants which can be formed +/// by using a vspltis[bhw] instruction of the specified element size, return +/// the constant being splatted. The ByteSize field indicates the number of +/// bytes of each element [124] -> [bhw]. +SDValue PPC::get_VSPLTI_elt(SDNode *N, unsigned ByteSize, SelectionDAG &DAG) { + SDValue OpVal(0, 0); + + // If ByteSize of the splat is bigger than the element size of the + // build_vector, then we have a case where we are checking for a splat where + // multiple elements of the buildvector are folded together into a single + // logical element of the splat (e.g. "vsplish 1" to splat {0,1}*8). + unsigned EltSize = 16/N->getNumOperands(); + if (EltSize < ByteSize) { + unsigned Multiple = ByteSize/EltSize; // Number of BV entries per spltval. + SDValue UniquedVals[4]; + assert(Multiple > 1 && Multiple <= 4 && "How can this happen?"); + + // See if all of the elements in the buildvector agree across. + for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) { + if (N->getOperand(i).getOpcode() == ISD::UNDEF) continue; + // If the element isn't a constant, bail fully out. + if (!isa(N->getOperand(i))) return SDValue(); + + + if (UniquedVals[i&(Multiple-1)].getNode() == 0) + UniquedVals[i&(Multiple-1)] = N->getOperand(i); + else if (UniquedVals[i&(Multiple-1)] != N->getOperand(i)) + return SDValue(); // no match. + } + + // Okay, if we reached this point, UniquedVals[0..Multiple-1] contains + // either constant or undef values that are identical for each chunk. See + // if these chunks can form into a larger vspltis*. + + // Check to see if all of the leading entries are either 0 or -1. If + // neither, then this won't fit into the immediate field. + bool LeadingZero = true; + bool LeadingOnes = true; + for (unsigned i = 0; i != Multiple-1; ++i) { + if (UniquedVals[i].getNode() == 0) continue; // Must have been undefs. + + LeadingZero &= cast(UniquedVals[i])->isNullValue(); + LeadingOnes &= cast(UniquedVals[i])->isAllOnesValue(); + } + // Finally, check the least significant entry. + if (LeadingZero) { + if (UniquedVals[Multiple-1].getNode() == 0) + return DAG.getTargetConstant(0, MVT::i32); // 0,0,0,undef + int Val = cast(UniquedVals[Multiple-1])->getZExtValue(); + if (Val < 16) + return DAG.getTargetConstant(Val, MVT::i32); // 0,0,0,4 -> vspltisw(4) + } + if (LeadingOnes) { + if (UniquedVals[Multiple-1].getNode() == 0) + return DAG.getTargetConstant(~0U, MVT::i32); // -1,-1,-1,undef + int Val =cast(UniquedVals[Multiple-1])->getSExtValue(); + if (Val >= -16) // -1,-1,-1,-2 -> vspltisw(-2) + return DAG.getTargetConstant(Val, MVT::i32); + } + + return SDValue(); + } + + // Check to see if this buildvec has a single non-undef value in its elements. + for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) { + if (N->getOperand(i).getOpcode() == ISD::UNDEF) continue; + if (OpVal.getNode() == 0) + OpVal = N->getOperand(i); + else if (OpVal != N->getOperand(i)) + return SDValue(); + } + + if (OpVal.getNode() == 0) return SDValue(); // All UNDEF: use implicit def. + + unsigned ValSizeInBytes = EltSize; + uint64_t Value = 0; + if (ConstantSDNode *CN = dyn_cast(OpVal)) { + Value = CN->getZExtValue(); + } else if (ConstantFPSDNode *CN = dyn_cast(OpVal)) { + assert(CN->getValueType(0) == MVT::f32 && "Only one legal FP vector type!"); + Value = FloatToBits(CN->getValueAPF().convertToFloat()); + } + + // If the splat value is larger than the element value, then we can never do + // this splat. The only case that we could fit the replicated bits into our + // immediate field for would be zero, and we prefer to use vxor for it. + if (ValSizeInBytes < ByteSize) return SDValue(); + + // If the element value is larger than the splat value, cut it in half and + // check to see if the two halves are equal. Continue doing this until we + // get to ByteSize. This allows us to handle 0x01010101 as 0x01. + while (ValSizeInBytes > ByteSize) { + ValSizeInBytes >>= 1; + + // If the top half equals the bottom half, we're still ok. + if (((Value >> (ValSizeInBytes*8)) & ((1 << (8*ValSizeInBytes))-1)) != + (Value & ((1 << (8*ValSizeInBytes))-1))) + return SDValue(); + } + + // Properly sign extend the value. + int ShAmt = (4-ByteSize)*8; + int MaskVal = ((int)Value << ShAmt) >> ShAmt; + + // If this is zero, don't match, zero matches ISD::isBuildVectorAllZeros. + if (MaskVal == 0) return SDValue(); + + // Finally, if this value fits in a 5 bit sext field, return it + if (((MaskVal << (32-5)) >> (32-5)) == MaskVal) + return DAG.getTargetConstant(MaskVal, MVT::i32); + return SDValue(); +} + +//===----------------------------------------------------------------------===// +// Addressing Mode Selection +//===----------------------------------------------------------------------===// + +/// isIntS16Immediate - This method tests to see if the node is either a 32-bit +/// or 64-bit immediate, and if the value can be accurately represented as a +/// sign extension from a 16-bit value. If so, this returns true and the +/// immediate. +static bool isIntS16Immediate(SDNode *N, short &Imm) { + if (N->getOpcode() != ISD::Constant) + return false; + + Imm = (short)cast(N)->getZExtValue(); + if (N->getValueType(0) == MVT::i32) + return Imm == (int32_t)cast(N)->getZExtValue(); + else + return Imm == (int64_t)cast(N)->getZExtValue(); +} +static bool isIntS16Immediate(SDValue Op, short &Imm) { + return isIntS16Immediate(Op.getNode(), Imm); +} + + +/// SelectAddressRegReg - Given the specified addressed, check to see if it +/// can be represented as an indexed [r+r] operation. Returns false if it +/// can be more efficiently represented with [r+imm]. +bool PPCTargetLowering::SelectAddressRegReg(SDValue N, SDValue &Base, + SDValue &Index, + SelectionDAG &DAG) const { + short imm = 0; + if (N.getOpcode() == ISD::ADD) { + if (isIntS16Immediate(N.getOperand(1), imm)) + return false; // r+i + if (N.getOperand(1).getOpcode() == PPCISD::Lo) + return false; // r+i + + Base = N.getOperand(0); + Index = N.getOperand(1); + return true; + } else if (N.getOpcode() == ISD::OR) { + if (isIntS16Immediate(N.getOperand(1), imm)) + return false; // r+i can fold it if we can. + + // If this is an or of disjoint bitfields, we can codegen this as an add + // (for better address arithmetic) if the LHS and RHS of the OR are provably + // disjoint. + APInt LHSKnownZero, LHSKnownOne; + APInt RHSKnownZero, RHSKnownOne; + DAG.ComputeMaskedBits(N.getOperand(0), + APInt::getAllOnesValue(N.getOperand(0) + .getValueSizeInBits()), + LHSKnownZero, LHSKnownOne); + + if (LHSKnownZero.getBoolValue()) { + DAG.ComputeMaskedBits(N.getOperand(1), + APInt::getAllOnesValue(N.getOperand(1) + .getValueSizeInBits()), + RHSKnownZero, RHSKnownOne); + // If all of the bits are known zero on the LHS or RHS, the add won't + // carry. + if (~(LHSKnownZero | RHSKnownZero) == 0) { + Base = N.getOperand(0); + Index = N.getOperand(1); + return true; + } + } + } + + return false; +} + +/// Returns true if the address N can be represented by a base register plus +/// a signed 16-bit displacement [r+imm], and if it is not better +/// represented as reg+reg. +bool PPCTargetLowering::SelectAddressRegImm(SDValue N, SDValue &Disp, + SDValue &Base, + SelectionDAG &DAG) const { + // FIXME dl should come from parent load or store, not from address + DebugLoc dl = N.getDebugLoc(); + // If this can be more profitably realized as r+r, fail. + if (SelectAddressRegReg(N, Disp, Base, DAG)) + return false; + + if (N.getOpcode() == ISD::ADD) { + short imm = 0; + if (isIntS16Immediate(N.getOperand(1), imm)) { + Disp = DAG.getTargetConstant((int)imm & 0xFFFF, MVT::i32); + if (FrameIndexSDNode *FI = dyn_cast(N.getOperand(0))) { + Base = DAG.getTargetFrameIndex(FI->getIndex(), N.getValueType()); + } else { + Base = N.getOperand(0); + } + return true; // [r+i] + } else if (N.getOperand(1).getOpcode() == PPCISD::Lo) { + // Match LOAD (ADD (X, Lo(G))). + assert(!cast(N.getOperand(1).getOperand(1))->getZExtValue() + && "Cannot handle constant offsets yet!"); + Disp = N.getOperand(1).getOperand(0); // The global address. + assert(Disp.getOpcode() == ISD::TargetGlobalAddress || + Disp.getOpcode() == ISD::TargetConstantPool || + Disp.getOpcode() == ISD::TargetJumpTable); + Base = N.getOperand(0); + return true; // [&g+r] + } + } else if (N.getOpcode() == ISD::OR) { + short imm = 0; + if (isIntS16Immediate(N.getOperand(1), imm)) { + // If this is an or of disjoint bitfields, we can codegen this as an add + // (for better address arithmetic) if the LHS and RHS of the OR are + // provably disjoint. + APInt LHSKnownZero, LHSKnownOne; + DAG.ComputeMaskedBits(N.getOperand(0), + APInt::getAllOnesValue(N.getOperand(0) + .getValueSizeInBits()), + LHSKnownZero, LHSKnownOne); + + if ((LHSKnownZero.getZExtValue()|~(uint64_t)imm) == ~0ULL) { + // If all of the bits are known zero on the LHS or RHS, the add won't + // carry. + Base = N.getOperand(0); + Disp = DAG.getTargetConstant((int)imm & 0xFFFF, MVT::i32); + return true; + } + } + } else if (ConstantSDNode *CN = dyn_cast(N)) { + // Loading from a constant address. + + // If this address fits entirely in a 16-bit sext immediate field, codegen + // this as "d, 0" + short Imm; + if (isIntS16Immediate(CN, Imm)) { + Disp = DAG.getTargetConstant(Imm, CN->getValueType(0)); + Base = DAG.getRegister(PPC::R0, CN->getValueType(0)); + return true; + } + + // Handle 32-bit sext immediates with LIS + addr mode. + if (CN->getValueType(0) == MVT::i32 || + (int64_t)CN->getZExtValue() == (int)CN->getZExtValue()) { + int Addr = (int)CN->getZExtValue(); + + // Otherwise, break this down into an LIS + disp. + Disp = DAG.getTargetConstant((short)Addr, MVT::i32); + + Base = DAG.getTargetConstant((Addr - (signed short)Addr) >> 16, MVT::i32); + unsigned Opc = CN->getValueType(0) == MVT::i32 ? PPC::LIS : PPC::LIS8; + Base = SDValue(DAG.getMachineNode(Opc, dl, CN->getValueType(0), Base), 0); + return true; + } + } + + Disp = DAG.getTargetConstant(0, getPointerTy()); + if (FrameIndexSDNode *FI = dyn_cast(N)) + Base = DAG.getTargetFrameIndex(FI->getIndex(), N.getValueType()); + else + Base = N; + return true; // [r+0] +} + +/// SelectAddressRegRegOnly - Given the specified addressed, force it to be +/// represented as an indexed [r+r] operation. +bool PPCTargetLowering::SelectAddressRegRegOnly(SDValue N, SDValue &Base, + SDValue &Index, + SelectionDAG &DAG) const { + // Check to see if we can easily represent this as an [r+r] address. This + // will fail if it thinks that the address is more profitably represented as + // reg+imm, e.g. where imm = 0. + if (SelectAddressRegReg(N, Base, Index, DAG)) + return true; + + // If the operand is an addition, always emit this as [r+r], since this is + // better (for code size, and execution, as the memop does the add for free) + // than emitting an explicit add. + if (N.getOpcode() == ISD::ADD) { + Base = N.getOperand(0); + Index = N.getOperand(1); + return true; + } + + // Otherwise, do it the hard way, using R0 as the base register. + Base = DAG.getRegister(PPC::R0, N.getValueType()); + Index = N; + return true; +} + +/// SelectAddressRegImmShift - Returns true if the address N can be +/// represented by a base register plus a signed 14-bit displacement +/// [r+imm*4]. Suitable for use by STD and friends. +bool PPCTargetLowering::SelectAddressRegImmShift(SDValue N, SDValue &Disp, + SDValue &Base, + SelectionDAG &DAG) const { + // FIXME dl should come from the parent load or store, not the address + DebugLoc dl = N.getDebugLoc(); + // If this can be more profitably realized as r+r, fail. + if (SelectAddressRegReg(N, Disp, Base, DAG)) + return false; + + if (N.getOpcode() == ISD::ADD) { + short imm = 0; + if (isIntS16Immediate(N.getOperand(1), imm) && (imm & 3) == 0) { + Disp = DAG.getTargetConstant(((int)imm & 0xFFFF) >> 2, MVT::i32); + if (FrameIndexSDNode *FI = dyn_cast(N.getOperand(0))) { + Base = DAG.getTargetFrameIndex(FI->getIndex(), N.getValueType()); + } else { + Base = N.getOperand(0); + } + return true; // [r+i] + } else if (N.getOperand(1).getOpcode() == PPCISD::Lo) { + // Match LOAD (ADD (X, Lo(G))). + assert(!cast(N.getOperand(1).getOperand(1))->getZExtValue() + && "Cannot handle constant offsets yet!"); + Disp = N.getOperand(1).getOperand(0); // The global address. + assert(Disp.getOpcode() == ISD::TargetGlobalAddress || + Disp.getOpcode() == ISD::TargetConstantPool || + Disp.getOpcode() == ISD::TargetJumpTable); + Base = N.getOperand(0); + return true; // [&g+r] + } + } else if (N.getOpcode() == ISD::OR) { + short imm = 0; + if (isIntS16Immediate(N.getOperand(1), imm) && (imm & 3) == 0) { + // If this is an or of disjoint bitfields, we can codegen this as an add + // (for better address arithmetic) if the LHS and RHS of the OR are + // provably disjoint. + APInt LHSKnownZero, LHSKnownOne; + DAG.ComputeMaskedBits(N.getOperand(0), + APInt::getAllOnesValue(N.getOperand(0) + .getValueSizeInBits()), + LHSKnownZero, LHSKnownOne); + if ((LHSKnownZero.getZExtValue()|~(uint64_t)imm) == ~0ULL) { + // If all of the bits are known zero on the LHS or RHS, the add won't + // carry. + Base = N.getOperand(0); + Disp = DAG.getTargetConstant(((int)imm & 0xFFFF) >> 2, MVT::i32); + return true; + } + } + } else if (ConstantSDNode *CN = dyn_cast(N)) { + // Loading from a constant address. Verify low two bits are clear. + if ((CN->getZExtValue() & 3) == 0) { + // If this address fits entirely in a 14-bit sext immediate field, codegen + // this as "d, 0" + short Imm; + if (isIntS16Immediate(CN, Imm)) { + Disp = DAG.getTargetConstant((unsigned short)Imm >> 2, getPointerTy()); + Base = DAG.getRegister(PPC::R0, CN->getValueType(0)); + return true; + } + + // Fold the low-part of 32-bit absolute addresses into addr mode. + if (CN->getValueType(0) == MVT::i32 || + (int64_t)CN->getZExtValue() == (int)CN->getZExtValue()) { + int Addr = (int)CN->getZExtValue(); + + // Otherwise, break this down into an LIS + disp. + Disp = DAG.getTargetConstant((short)Addr >> 2, MVT::i32); + Base = DAG.getTargetConstant((Addr-(signed short)Addr) >> 16, MVT::i32); + unsigned Opc = CN->getValueType(0) == MVT::i32 ? PPC::LIS : PPC::LIS8; + Base = SDValue(DAG.getMachineNode(Opc, dl, CN->getValueType(0), Base),0); + return true; + } + } + } + + Disp = DAG.getTargetConstant(0, getPointerTy()); + if (FrameIndexSDNode *FI = dyn_cast(N)) + Base = DAG.getTargetFrameIndex(FI->getIndex(), N.getValueType()); + else + Base = N; + return true; // [r+0] +} + + +/// getPreIndexedAddressParts - returns true by value, base pointer and +/// offset pointer and addressing mode by reference if the node's address +/// can be legally represented as pre-indexed load / store address. +bool PPCTargetLowering::getPreIndexedAddressParts(SDNode *N, SDValue &Base, + SDValue &Offset, + ISD::MemIndexedMode &AM, + SelectionDAG &DAG) const { + // Disabled by default for now. + if (!EnablePPCPreinc) return false; + + SDValue Ptr; + EVT VT; + if (LoadSDNode *LD = dyn_cast(N)) { + Ptr = LD->getBasePtr(); + VT = LD->getMemoryVT(); + + } else if (StoreSDNode *ST = dyn_cast(N)) { + ST = ST; + Ptr = ST->getBasePtr(); + VT = ST->getMemoryVT(); + } else + return false; + + // PowerPC doesn't have preinc load/store instructions for vectors. + if (VT.isVector()) + return false; + + // TODO: Check reg+reg first. + + // LDU/STU use reg+imm*4, others use reg+imm. + if (VT != MVT::i64) { + // reg + imm + if (!SelectAddressRegImm(Ptr, Offset, Base, DAG)) + return false; + } else { + // reg + imm * 4. + if (!SelectAddressRegImmShift(Ptr, Offset, Base, DAG)) + return false; + } + + if (LoadSDNode *LD = dyn_cast(N)) { + // PPC64 doesn't have lwau, but it does have lwaux. Reject preinc load of + // sext i32 to i64 when addr mode is r+i. + if (LD->getValueType(0) == MVT::i64 && LD->getMemoryVT() == MVT::i32 && + LD->getExtensionType() == ISD::SEXTLOAD && + isa(Offset)) + return false; + } + + AM = ISD::PRE_INC; + return true; +} + +//===----------------------------------------------------------------------===// +// LowerOperation implementation +//===----------------------------------------------------------------------===// + +SDValue PPCTargetLowering::LowerConstantPool(SDValue Op, + SelectionDAG &DAG) { + EVT PtrVT = Op.getValueType(); + ConstantPoolSDNode *CP = cast(Op); + Constant *C = CP->getConstVal(); + SDValue CPI = DAG.getTargetConstantPool(C, PtrVT, CP->getAlignment()); + SDValue Zero = DAG.getConstant(0, PtrVT); + // FIXME there isn't really any debug info here + DebugLoc dl = Op.getDebugLoc(); + + const TargetMachine &TM = DAG.getTarget(); + + SDValue Hi = DAG.getNode(PPCISD::Hi, dl, PtrVT, CPI, Zero); + SDValue Lo = DAG.getNode(PPCISD::Lo, dl, PtrVT, CPI, Zero); + + // If this is a non-darwin platform, we don't support non-static relo models + // yet. + if (TM.getRelocationModel() == Reloc::Static || + !TM.getSubtarget().isDarwin()) { + // Generate non-pic code that has direct accesses to the constant pool. + // The address of the global is just (hi(&g)+lo(&g)). + return DAG.getNode(ISD::ADD, dl, PtrVT, Hi, Lo); + } + + if (TM.getRelocationModel() == Reloc::PIC_) { + // With PIC, the first instruction is actually "GR+hi(&G)". + Hi = DAG.getNode(ISD::ADD, dl, PtrVT, + DAG.getNode(PPCISD::GlobalBaseReg, + DebugLoc::getUnknownLoc(), PtrVT), Hi); + } + + Lo = DAG.getNode(ISD::ADD, dl, PtrVT, Hi, Lo); + return Lo; +} + +SDValue PPCTargetLowering::LowerJumpTable(SDValue Op, SelectionDAG &DAG) { + EVT PtrVT = Op.getValueType(); + JumpTableSDNode *JT = cast(Op); + SDValue JTI = DAG.getTargetJumpTable(JT->getIndex(), PtrVT); + SDValue Zero = DAG.getConstant(0, PtrVT); + // FIXME there isn't really any debug loc here + DebugLoc dl = Op.getDebugLoc(); + + const TargetMachine &TM = DAG.getTarget(); + + SDValue Hi = DAG.getNode(PPCISD::Hi, dl, PtrVT, JTI, Zero); + SDValue Lo = DAG.getNode(PPCISD::Lo, dl, PtrVT, JTI, Zero); + + // If this is a non-darwin platform, we don't support non-static relo models + // yet. + if (TM.getRelocationModel() == Reloc::Static || + !TM.getSubtarget().isDarwin()) { + // Generate non-pic code that has direct accesses to the constant pool. + // The address of the global is just (hi(&g)+lo(&g)). + return DAG.getNode(ISD::ADD, dl, PtrVT, Hi, Lo); + } + + if (TM.getRelocationModel() == Reloc::PIC_) { + // With PIC, the first instruction is actually "GR+hi(&G)". + Hi = DAG.getNode(ISD::ADD, dl, PtrVT, + DAG.getNode(PPCISD::GlobalBaseReg, + DebugLoc::getUnknownLoc(), PtrVT), Hi); + } + + Lo = DAG.getNode(ISD::ADD, dl, PtrVT, Hi, Lo); + return Lo; +} + +SDValue PPCTargetLowering::LowerGlobalTLSAddress(SDValue Op, + SelectionDAG &DAG) { + llvm_unreachable("TLS not implemented for PPC."); + return SDValue(); // Not reached +} + +SDValue PPCTargetLowering::LowerBlockAddress(SDValue Op, SelectionDAG &DAG) { + EVT PtrVT = Op.getValueType(); + DebugLoc DL = Op.getDebugLoc(); + + BlockAddress *BA = cast(Op)->getBlockAddress(); + SDValue TgtBA = DAG.getBlockAddress(BA, PtrVT, /*isTarget=*/true); + SDValue Zero = DAG.getConstant(0, PtrVT); + SDValue Hi = DAG.getNode(PPCISD::Hi, DL, PtrVT, TgtBA, Zero); + SDValue Lo = DAG.getNode(PPCISD::Lo, DL, PtrVT, TgtBA, Zero); + + // If this is a non-darwin platform, we don't support non-static relo models + // yet. + const TargetMachine &TM = DAG.getTarget(); + if (TM.getRelocationModel() == Reloc::Static || + !TM.getSubtarget().isDarwin()) { + // Generate non-pic code that has direct accesses to globals. + // The address of the global is just (hi(&g)+lo(&g)). + return DAG.getNode(ISD::ADD, DL, PtrVT, Hi, Lo); + } + + if (TM.getRelocationModel() == Reloc::PIC_) { + // With PIC, the first instruction is actually "GR+hi(&G)". + Hi = DAG.getNode(ISD::ADD, DL, PtrVT, + DAG.getNode(PPCISD::GlobalBaseReg, + DebugLoc::getUnknownLoc(), PtrVT), Hi); + } + + return DAG.getNode(ISD::ADD, DL, PtrVT, Hi, Lo); +} + +SDValue PPCTargetLowering::LowerGlobalAddress(SDValue Op, + SelectionDAG &DAG) { + EVT PtrVT = Op.getValueType(); + GlobalAddressSDNode *GSDN = cast(Op); + GlobalValue *GV = GSDN->getGlobal(); + SDValue GA = DAG.getTargetGlobalAddress(GV, PtrVT, GSDN->getOffset()); + SDValue Zero = DAG.getConstant(0, PtrVT); + // FIXME there isn't really any debug info here + DebugLoc dl = GSDN->getDebugLoc(); + + const TargetMachine &TM = DAG.getTarget(); + + // 64-bit SVR4 ABI code is always position-independent. + // The actual address of the GlobalValue is stored in the TOC. + if (PPCSubTarget.isSVR4ABI() && PPCSubTarget.isPPC64()) { + return DAG.getNode(PPCISD::TOC_ENTRY, dl, MVT::i64, GA, + DAG.getRegister(PPC::X2, MVT::i64)); + } + + SDValue Hi = DAG.getNode(PPCISD::Hi, dl, PtrVT, GA, Zero); + SDValue Lo = DAG.getNode(PPCISD::Lo, dl, PtrVT, GA, Zero); + + // If this is a non-darwin platform, we don't support non-static relo models + // yet. + if (TM.getRelocationModel() == Reloc::Static || + !TM.getSubtarget().isDarwin()) { + // Generate non-pic code that has direct accesses to globals. + // The address of the global is just (hi(&g)+lo(&g)). + return DAG.getNode(ISD::ADD, dl, PtrVT, Hi, Lo); + } + + if (TM.getRelocationModel() == Reloc::PIC_) { + // With PIC, the first instruction is actually "GR+hi(&G)". + Hi = DAG.getNode(ISD::ADD, dl, PtrVT, + DAG.getNode(PPCISD::GlobalBaseReg, + DebugLoc::getUnknownLoc(), PtrVT), Hi); + } + + Lo = DAG.getNode(ISD::ADD, dl, PtrVT, Hi, Lo); + + if (!TM.getSubtarget().hasLazyResolverStub(GV, TM)) + return Lo; + + // If the global is weak or external, we have to go through the lazy + // resolution stub. + return DAG.getLoad(PtrVT, dl, DAG.getEntryNode(), Lo, NULL, 0); +} + +SDValue PPCTargetLowering::LowerSETCC(SDValue Op, SelectionDAG &DAG) { + ISD::CondCode CC = cast(Op.getOperand(2))->get(); + DebugLoc dl = Op.getDebugLoc(); + + // If we're comparing for equality to zero, expose the fact that this is + // implented as a ctlz/srl pair on ppc, so that the dag combiner can + // fold the new nodes. + if (ConstantSDNode *C = dyn_cast(Op.getOperand(1))) { + if (C->isNullValue() && CC == ISD::SETEQ) { + EVT VT = Op.getOperand(0).getValueType(); + SDValue Zext = Op.getOperand(0); + if (VT.bitsLT(MVT::i32)) { + VT = MVT::i32; + Zext = DAG.getNode(ISD::ZERO_EXTEND, dl, VT, Op.getOperand(0)); + } + unsigned Log2b = Log2_32(VT.getSizeInBits()); + SDValue Clz = DAG.getNode(ISD::CTLZ, dl, VT, Zext); + SDValue Scc = DAG.getNode(ISD::SRL, dl, VT, Clz, + DAG.getConstant(Log2b, MVT::i32)); + return DAG.getNode(ISD::TRUNCATE, dl, MVT::i32, Scc); + } + // Leave comparisons against 0 and -1 alone for now, since they're usually + // optimized. FIXME: revisit this when we can custom lower all setcc + // optimizations. + if (C->isAllOnesValue() || C->isNullValue()) + return SDValue(); + } + + // If we have an integer seteq/setne, turn it into a compare against zero + // by xor'ing the rhs with the lhs, which is faster than setting a + // condition register, reading it back out, and masking the correct bit. The + // normal approach here uses sub to do this instead of xor. Using xor exposes + // the result to other bit-twiddling opportunities. + EVT LHSVT = Op.getOperand(0).getValueType(); + if (LHSVT.isInteger() && (CC == ISD::SETEQ || CC == ISD::SETNE)) { + EVT VT = Op.getValueType(); + SDValue Sub = DAG.getNode(ISD::XOR, dl, LHSVT, Op.getOperand(0), + Op.getOperand(1)); + return DAG.getSetCC(dl, VT, Sub, DAG.getConstant(0, LHSVT), CC); + } + return SDValue(); +} + +SDValue PPCTargetLowering::LowerVAARG(SDValue Op, SelectionDAG &DAG, + int VarArgsFrameIndex, + int VarArgsStackOffset, + unsigned VarArgsNumGPR, + unsigned VarArgsNumFPR, + const PPCSubtarget &Subtarget) { + + llvm_unreachable("VAARG not yet implemented for the SVR4 ABI!"); + return SDValue(); // Not reached +} + +SDValue PPCTargetLowering::LowerTRAMPOLINE(SDValue Op, SelectionDAG &DAG) { + SDValue Chain = Op.getOperand(0); + SDValue Trmp = Op.getOperand(1); // trampoline + SDValue FPtr = Op.getOperand(2); // nested function + SDValue Nest = Op.getOperand(3); // 'nest' parameter value + DebugLoc dl = Op.getDebugLoc(); + + EVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy(); + bool isPPC64 = (PtrVT == MVT::i64); + const Type *IntPtrTy = + DAG.getTargetLoweringInfo().getTargetData()->getIntPtrType( + *DAG.getContext()); + + TargetLowering::ArgListTy Args; + TargetLowering::ArgListEntry Entry; + + Entry.Ty = IntPtrTy; + Entry.Node = Trmp; Args.push_back(Entry); + + // TrampSize == (isPPC64 ? 48 : 40); + Entry.Node = DAG.getConstant(isPPC64 ? 48 : 40, + isPPC64 ? MVT::i64 : MVT::i32); + Args.push_back(Entry); + + Entry.Node = FPtr; Args.push_back(Entry); + Entry.Node = Nest; Args.push_back(Entry); + + // Lower to a call to __trampoline_setup(Trmp, TrampSize, FPtr, ctx_reg) + std::pair CallResult = + LowerCallTo(Chain, Op.getValueType().getTypeForEVT(*DAG.getContext()), + false, false, false, false, 0, CallingConv::C, false, + /*isReturnValueUsed=*/true, + DAG.getExternalSymbol("__trampoline_setup", PtrVT), + Args, DAG, dl); + + SDValue Ops[] = + { CallResult.first, CallResult.second }; + + return DAG.getMergeValues(Ops, 2, dl); +} + +SDValue PPCTargetLowering::LowerVASTART(SDValue Op, SelectionDAG &DAG, + int VarArgsFrameIndex, + int VarArgsStackOffset, + unsigned VarArgsNumGPR, + unsigned VarArgsNumFPR, + const PPCSubtarget &Subtarget) { + DebugLoc dl = Op.getDebugLoc(); + + if (Subtarget.isDarwinABI() || Subtarget.isPPC64()) { + // vastart just stores the address of the VarArgsFrameIndex slot into the + // memory location argument. + EVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy(); + SDValue FR = DAG.getFrameIndex(VarArgsFrameIndex, PtrVT); + const Value *SV = cast(Op.getOperand(2))->getValue(); + return DAG.getStore(Op.getOperand(0), dl, FR, Op.getOperand(1), SV, 0); + } + + // For the 32-bit SVR4 ABI we follow the layout of the va_list struct. + // We suppose the given va_list is already allocated. + // + // typedef struct { + // char gpr; /* index into the array of 8 GPRs + // * stored in the register save area + // * gpr=0 corresponds to r3, + // * gpr=1 to r4, etc. + // */ + // char fpr; /* index into the array of 8 FPRs + // * stored in the register save area + // * fpr=0 corresponds to f1, + // * fpr=1 to f2, etc. + // */ + // char *overflow_arg_area; + // /* location on stack that holds + // * the next overflow argument + // */ + // char *reg_save_area; + // /* where r3:r10 and f1:f8 (if saved) + // * are stored + // */ + // } va_list[1]; + + + SDValue ArgGPR = DAG.getConstant(VarArgsNumGPR, MVT::i32); + SDValue ArgFPR = DAG.getConstant(VarArgsNumFPR, MVT::i32); + + + EVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy(); + + SDValue StackOffsetFI = DAG.getFrameIndex(VarArgsStackOffset, PtrVT); + SDValue FR = DAG.getFrameIndex(VarArgsFrameIndex, PtrVT); + + uint64_t FrameOffset = PtrVT.getSizeInBits()/8; + SDValue ConstFrameOffset = DAG.getConstant(FrameOffset, PtrVT); + + uint64_t StackOffset = PtrVT.getSizeInBits()/8 - 1; + SDValue ConstStackOffset = DAG.getConstant(StackOffset, PtrVT); + + uint64_t FPROffset = 1; + SDValue ConstFPROffset = DAG.getConstant(FPROffset, PtrVT); + + const Value *SV = cast(Op.getOperand(2))->getValue(); + + // Store first byte : number of int regs + SDValue firstStore = DAG.getTruncStore(Op.getOperand(0), dl, ArgGPR, + Op.getOperand(1), SV, 0, MVT::i8); + uint64_t nextOffset = FPROffset; + SDValue nextPtr = DAG.getNode(ISD::ADD, dl, PtrVT, Op.getOperand(1), + ConstFPROffset); + + // Store second byte : number of float regs + SDValue secondStore = + DAG.getTruncStore(firstStore, dl, ArgFPR, nextPtr, SV, nextOffset, MVT::i8); + nextOffset += StackOffset; + nextPtr = DAG.getNode(ISD::ADD, dl, PtrVT, nextPtr, ConstStackOffset); + + // Store second word : arguments given on stack + SDValue thirdStore = + DAG.getStore(secondStore, dl, StackOffsetFI, nextPtr, SV, nextOffset); + nextOffset += FrameOffset; + nextPtr = DAG.getNode(ISD::ADD, dl, PtrVT, nextPtr, ConstFrameOffset); + + // Store third word : arguments given in registers + return DAG.getStore(thirdStore, dl, FR, nextPtr, SV, nextOffset); + +} + +#include "PPCGenCallingConv.inc" + +static bool CC_PPC_SVR4_Custom_Dummy(unsigned &ValNo, EVT &ValVT, EVT &LocVT, + CCValAssign::LocInfo &LocInfo, + ISD::ArgFlagsTy &ArgFlags, + CCState &State) { + return true; +} + +static bool CC_PPC_SVR4_Custom_AlignArgRegs(unsigned &ValNo, EVT &ValVT, + EVT &LocVT, + CCValAssign::LocInfo &LocInfo, + ISD::ArgFlagsTy &ArgFlags, + CCState &State) { + static const unsigned ArgRegs[] = { + PPC::R3, PPC::R4, PPC::R5, PPC::R6, + PPC::R7, PPC::R8, PPC::R9, PPC::R10, + }; + const unsigned NumArgRegs = array_lengthof(ArgRegs); + + unsigned RegNum = State.getFirstUnallocated(ArgRegs, NumArgRegs); + + // Skip one register if the first unallocated register has an even register + // number and there are still argument registers available which have not been + // allocated yet. RegNum is actually an index into ArgRegs, which means we + // need to skip a register if RegNum is odd. + if (RegNum != NumArgRegs && RegNum % 2 == 1) { + State.AllocateReg(ArgRegs[RegNum]); + } + + // Always return false here, as this function only makes sure that the first + // unallocated register has an odd register number and does not actually + // allocate a register for the current argument. + return false; +} + +static bool CC_PPC_SVR4_Custom_AlignFPArgRegs(unsigned &ValNo, EVT &ValVT, + EVT &LocVT, + CCValAssign::LocInfo &LocInfo, + ISD::ArgFlagsTy &ArgFlags, + CCState &State) { + static const unsigned ArgRegs[] = { + PPC::F1, PPC::F2, PPC::F3, PPC::F4, PPC::F5, PPC::F6, PPC::F7, + PPC::F8 + }; + + const unsigned NumArgRegs = array_lengthof(ArgRegs); + + unsigned RegNum = State.getFirstUnallocated(ArgRegs, NumArgRegs); + + // If there is only one Floating-point register left we need to put both f64 + // values of a split ppc_fp128 value on the stack. + if (RegNum != NumArgRegs && ArgRegs[RegNum] == PPC::F8) { + State.AllocateReg(ArgRegs[RegNum]); + } + + // Always return false here, as this function only makes sure that the two f64 + // values a ppc_fp128 value is split into are both passed in registers or both + // passed on the stack and does not actually allocate a register for the + // current argument. + return false; +} + +/// GetFPR - Get the set of FP registers that should be allocated for arguments, +/// on Darwin. +static const unsigned *GetFPR() { + static const unsigned FPR[] = { + PPC::F1, PPC::F2, PPC::F3, PPC::F4, PPC::F5, PPC::F6, PPC::F7, + PPC::F8, PPC::F9, PPC::F10, PPC::F11, PPC::F12, PPC::F13 + }; + + return FPR; +} + +/// CalculateStackSlotSize - Calculates the size reserved for this argument on +/// the stack. +static unsigned CalculateStackSlotSize(EVT ArgVT, ISD::ArgFlagsTy Flags, + unsigned PtrByteSize) { + unsigned ArgSize = ArgVT.getSizeInBits()/8; + if (Flags.isByVal()) + ArgSize = Flags.getByValSize(); + ArgSize = ((ArgSize + PtrByteSize - 1)/PtrByteSize) * PtrByteSize; + + return ArgSize; +} + +SDValue +PPCTargetLowering::LowerFormalArguments(SDValue Chain, + CallingConv::ID CallConv, bool isVarArg, + const SmallVectorImpl + &Ins, + DebugLoc dl, SelectionDAG &DAG, + SmallVectorImpl &InVals) { + if (PPCSubTarget.isSVR4ABI() && !PPCSubTarget.isPPC64()) { + return LowerFormalArguments_SVR4(Chain, CallConv, isVarArg, Ins, + dl, DAG, InVals); + } else { + return LowerFormalArguments_Darwin(Chain, CallConv, isVarArg, Ins, + dl, DAG, InVals); + } +} + +SDValue +PPCTargetLowering::LowerFormalArguments_SVR4( + SDValue Chain, + CallingConv::ID CallConv, bool isVarArg, + const SmallVectorImpl + &Ins, + DebugLoc dl, SelectionDAG &DAG, + SmallVectorImpl &InVals) { + + // 32-bit SVR4 ABI Stack Frame Layout: + // +-----------------------------------+ + // +--> | Back chain | + // | +-----------------------------------+ + // | | Floating-point register save area | + // | +-----------------------------------+ + // | | General register save area | + // | +-----------------------------------+ + // | | CR save word | + // | +-----------------------------------+ + // | | VRSAVE save word | + // | +-----------------------------------+ + // | | Alignment padding | + // | +-----------------------------------+ + // | | Vector register save area | + // | +-----------------------------------+ + // | | Local variable space | + // | +-----------------------------------+ + // | | Parameter list area | + // | +-----------------------------------+ + // | | LR save word | + // | +-----------------------------------+ + // SP--> +--- | Back chain | + // +-----------------------------------+ + // + // Specifications: + // System V Application Binary Interface PowerPC Processor Supplement + // AltiVec Technology Programming Interface Manual + + MachineFunction &MF = DAG.getMachineFunction(); + MachineFrameInfo *MFI = MF.getFrameInfo(); + + EVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy(); + // Potential tail calls could cause overwriting of argument stack slots. + bool isImmutable = !(PerformTailCallOpt && (CallConv==CallingConv::Fast)); + unsigned PtrByteSize = 4; + + // Assign locations to all of the incoming arguments. + SmallVector ArgLocs; + CCState CCInfo(CallConv, isVarArg, getTargetMachine(), ArgLocs, + *DAG.getContext()); + + // Reserve space for the linkage area on the stack. + CCInfo.AllocateStack(PPCFrameInfo::getLinkageSize(false, false), PtrByteSize); + + CCInfo.AnalyzeFormalArguments(Ins, CC_PPC_SVR4); + + for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { + CCValAssign &VA = ArgLocs[i]; + + // Arguments stored in registers. + if (VA.isRegLoc()) { + TargetRegisterClass *RC; + EVT ValVT = VA.getValVT(); + + switch (ValVT.getSimpleVT().SimpleTy) { + default: + llvm_unreachable("ValVT not supported by formal arguments Lowering"); + case MVT::i32: + RC = PPC::GPRCRegisterClass; + break; + case MVT::f32: + RC = PPC::F4RCRegisterClass; + break; + case MVT::f64: + RC = PPC::F8RCRegisterClass; + break; + case MVT::v16i8: + case MVT::v8i16: + case MVT::v4i32: + case MVT::v4f32: + RC = PPC::VRRCRegisterClass; + break; + } + + // Transform the arguments stored in physical registers into virtual ones. + unsigned Reg = MF.addLiveIn(VA.getLocReg(), RC); + SDValue ArgValue = DAG.getCopyFromReg(Chain, dl, Reg, ValVT); + + InVals.push_back(ArgValue); + } else { + // Argument stored in memory. + assert(VA.isMemLoc()); + + unsigned ArgSize = VA.getLocVT().getSizeInBits() / 8; + int FI = MFI->CreateFixedObject(ArgSize, VA.getLocMemOffset(), + isImmutable, false); + + // Create load nodes to retrieve arguments from the stack. + SDValue FIN = DAG.getFrameIndex(FI, PtrVT); + InVals.push_back(DAG.getLoad(VA.getValVT(), dl, Chain, FIN, NULL, 0)); + } + } + + // Assign locations to all of the incoming aggregate by value arguments. + // Aggregates passed by value are stored in the local variable space of the + // caller's stack frame, right above the parameter list area. + SmallVector ByValArgLocs; + CCState CCByValInfo(CallConv, isVarArg, getTargetMachine(), + ByValArgLocs, *DAG.getContext()); + + // Reserve stack space for the allocations in CCInfo. + CCByValInfo.AllocateStack(CCInfo.getNextStackOffset(), PtrByteSize); + + CCByValInfo.AnalyzeFormalArguments(Ins, CC_PPC_SVR4_ByVal); + + // Area that is at least reserved in the caller of this function. + unsigned MinReservedArea = CCByValInfo.getNextStackOffset(); + + // Set the size that is at least reserved in caller of this function. Tail + // call optimized function's reserved stack space needs to be aligned so that + // taking the difference between two stack areas will result in an aligned + // stack. + PPCFunctionInfo *FI = MF.getInfo(); + + MinReservedArea = + std::max(MinReservedArea, + PPCFrameInfo::getMinCallFrameSize(false, false)); + + unsigned TargetAlign = DAG.getMachineFunction().getTarget().getFrameInfo()-> + getStackAlignment(); + unsigned AlignMask = TargetAlign-1; + MinReservedArea = (MinReservedArea + AlignMask) & ~AlignMask; + + FI->setMinReservedArea(MinReservedArea); + + SmallVector MemOps; + + // If the function takes variable number of arguments, make a frame index for + // the start of the first vararg value... for expansion of llvm.va_start. + if (isVarArg) { + static const unsigned GPArgRegs[] = { + PPC::R3, PPC::R4, PPC::R5, PPC::R6, + PPC::R7, PPC::R8, PPC::R9, PPC::R10, + }; + const unsigned NumGPArgRegs = array_lengthof(GPArgRegs); + + static const unsigned FPArgRegs[] = { + PPC::F1, PPC::F2, PPC::F3, PPC::F4, PPC::F5, PPC::F6, PPC::F7, + PPC::F8 + }; + const unsigned NumFPArgRegs = array_lengthof(FPArgRegs); + + VarArgsNumGPR = CCInfo.getFirstUnallocated(GPArgRegs, NumGPArgRegs); + VarArgsNumFPR = CCInfo.getFirstUnallocated(FPArgRegs, NumFPArgRegs); + + // Make room for NumGPArgRegs and NumFPArgRegs. + int Depth = NumGPArgRegs * PtrVT.getSizeInBits()/8 + + NumFPArgRegs * EVT(MVT::f64).getSizeInBits()/8; + + VarArgsStackOffset = MFI->CreateFixedObject(PtrVT.getSizeInBits()/8, + CCInfo.getNextStackOffset(), + true, false); + + VarArgsFrameIndex = MFI->CreateStackObject(Depth, 8, false); + SDValue FIN = DAG.getFrameIndex(VarArgsFrameIndex, PtrVT); + + // The fixed integer arguments of a variadic function are + // stored to the VarArgsFrameIndex on the stack. + unsigned GPRIndex = 0; + for (; GPRIndex != VarArgsNumGPR; ++GPRIndex) { + SDValue Val = DAG.getRegister(GPArgRegs[GPRIndex], PtrVT); + SDValue Store = DAG.getStore(Chain, dl, Val, FIN, NULL, 0); + MemOps.push_back(Store); + // Increment the address by four for the next argument to store + SDValue PtrOff = DAG.getConstant(PtrVT.getSizeInBits()/8, PtrVT); + FIN = DAG.getNode(ISD::ADD, dl, PtrOff.getValueType(), FIN, PtrOff); + } + + // If this function is vararg, store any remaining integer argument regs + // to their spots on the stack so that they may be loaded by deferencing the + // result of va_next. + for (; GPRIndex != NumGPArgRegs; ++GPRIndex) { + unsigned VReg = MF.addLiveIn(GPArgRegs[GPRIndex], &PPC::GPRCRegClass); + + SDValue Val = DAG.getCopyFromReg(Chain, dl, VReg, PtrVT); + SDValue Store = DAG.getStore(Val.getValue(1), dl, Val, FIN, NULL, 0); + MemOps.push_back(Store); + // Increment the address by four for the next argument to store + SDValue PtrOff = DAG.getConstant(PtrVT.getSizeInBits()/8, PtrVT); + FIN = DAG.getNode(ISD::ADD, dl, PtrOff.getValueType(), FIN, PtrOff); + } + + // FIXME 32-bit SVR4: We only need to save FP argument registers if CR bit 6 + // is set. + + // The double arguments are stored to the VarArgsFrameIndex + // on the stack. + unsigned FPRIndex = 0; + for (FPRIndex = 0; FPRIndex != VarArgsNumFPR; ++FPRIndex) { + SDValue Val = DAG.getRegister(FPArgRegs[FPRIndex], MVT::f64); + SDValue Store = DAG.getStore(Chain, dl, Val, FIN, NULL, 0); + MemOps.push_back(Store); + // Increment the address by eight for the next argument to store + SDValue PtrOff = DAG.getConstant(EVT(MVT::f64).getSizeInBits()/8, + PtrVT); + FIN = DAG.getNode(ISD::ADD, dl, PtrOff.getValueType(), FIN, PtrOff); + } + + for (; FPRIndex != NumFPArgRegs; ++FPRIndex) { + unsigned VReg = MF.addLiveIn(FPArgRegs[FPRIndex], &PPC::F8RCRegClass); + + SDValue Val = DAG.getCopyFromReg(Chain, dl, VReg, MVT::f64); + SDValue Store = DAG.getStore(Val.getValue(1), dl, Val, FIN, NULL, 0); + MemOps.push_back(Store); + // Increment the address by eight for the next argument to store + SDValue PtrOff = DAG.getConstant(EVT(MVT::f64).getSizeInBits()/8, + PtrVT); + FIN = DAG.getNode(ISD::ADD, dl, PtrOff.getValueType(), FIN, PtrOff); + } + } + + if (!MemOps.empty()) + Chain = DAG.getNode(ISD::TokenFactor, dl, + MVT::Other, &MemOps[0], MemOps.size()); + + return Chain; +} + +SDValue +PPCTargetLowering::LowerFormalArguments_Darwin( + SDValue Chain, + CallingConv::ID CallConv, bool isVarArg, + const SmallVectorImpl + &Ins, + DebugLoc dl, SelectionDAG &DAG, + SmallVectorImpl &InVals) { + // TODO: add description of PPC stack frame format, or at least some docs. + // + MachineFunction &MF = DAG.getMachineFunction(); + MachineFrameInfo *MFI = MF.getFrameInfo(); + + EVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy(); + bool isPPC64 = PtrVT == MVT::i64; + // Potential tail calls could cause overwriting of argument stack slots. + bool isImmutable = !(PerformTailCallOpt && (CallConv==CallingConv::Fast)); + unsigned PtrByteSize = isPPC64 ? 8 : 4; + + unsigned ArgOffset = PPCFrameInfo::getLinkageSize(isPPC64, true); + // Area that is at least reserved in caller of this function. + unsigned MinReservedArea = ArgOffset; + + static const unsigned GPR_32[] = { // 32-bit registers. + PPC::R3, PPC::R4, PPC::R5, PPC::R6, + PPC::R7, PPC::R8, PPC::R9, PPC::R10, + }; + static const unsigned GPR_64[] = { // 64-bit registers. + PPC::X3, PPC::X4, PPC::X5, PPC::X6, + PPC::X7, PPC::X8, PPC::X9, PPC::X10, + }; + + static const unsigned *FPR = GetFPR(); + + static const unsigned VR[] = { + PPC::V2, PPC::V3, PPC::V4, PPC::V5, PPC::V6, PPC::V7, PPC::V8, + PPC::V9, PPC::V10, PPC::V11, PPC::V12, PPC::V13 + }; + + const unsigned Num_GPR_Regs = array_lengthof(GPR_32); + const unsigned Num_FPR_Regs = 13; + const unsigned Num_VR_Regs = array_lengthof( VR); + + unsigned GPR_idx = 0, FPR_idx = 0, VR_idx = 0; + + const unsigned *GPR = isPPC64 ? GPR_64 : GPR_32; + + // In 32-bit non-varargs functions, the stack space for vectors is after the + // stack space for non-vectors. We do not use this space unless we have + // too many vectors to fit in registers, something that only occurs in + // constructed examples:), but we have to walk the arglist to figure + // that out...for the pathological case, compute VecArgOffset as the + // start of the vector parameter area. Computing VecArgOffset is the + // entire point of the following loop. + unsigned VecArgOffset = ArgOffset; + if (!isVarArg && !isPPC64) { + for (unsigned ArgNo = 0, e = Ins.size(); ArgNo != e; + ++ArgNo) { + EVT ObjectVT = Ins[ArgNo].VT; + unsigned ObjSize = ObjectVT.getSizeInBits()/8; + ISD::ArgFlagsTy Flags = Ins[ArgNo].Flags; + + if (Flags.isByVal()) { + // ObjSize is the true size, ArgSize rounded up to multiple of regs. + ObjSize = Flags.getByValSize(); + unsigned ArgSize = + ((ObjSize + PtrByteSize - 1)/PtrByteSize) * PtrByteSize; + VecArgOffset += ArgSize; + continue; + } + + switch(ObjectVT.getSimpleVT().SimpleTy) { + default: llvm_unreachable("Unhandled argument type!"); + case MVT::i32: + case MVT::f32: + VecArgOffset += isPPC64 ? 8 : 4; + break; + case MVT::i64: // PPC64 + case MVT::f64: + VecArgOffset += 8; + break; + case MVT::v4f32: + case MVT::v4i32: + case MVT::v8i16: + case MVT::v16i8: + // Nothing to do, we're only looking at Nonvector args here. + break; + } + } + } + // We've found where the vector parameter area in memory is. Skip the + // first 12 parameters; these don't use that memory. + VecArgOffset = ((VecArgOffset+15)/16)*16; + VecArgOffset += 12*16; + + // Add DAG nodes to load the arguments or copy them out of registers. On + // entry to a function on PPC, the arguments start after the linkage area, + // although the first ones are often in registers. + + SmallVector MemOps; + unsigned nAltivecParamsAtEnd = 0; + for (unsigned ArgNo = 0, e = Ins.size(); ArgNo != e; ++ArgNo) { + SDValue ArgVal; + bool needsLoad = false; + EVT ObjectVT = Ins[ArgNo].VT; + unsigned ObjSize = ObjectVT.getSizeInBits()/8; + unsigned ArgSize = ObjSize; + ISD::ArgFlagsTy Flags = Ins[ArgNo].Flags; + + unsigned CurArgOffset = ArgOffset; + + // Varargs or 64 bit Altivec parameters are padded to a 16 byte boundary. + if (ObjectVT==MVT::v4f32 || ObjectVT==MVT::v4i32 || + ObjectVT==MVT::v8i16 || ObjectVT==MVT::v16i8) { + if (isVarArg || isPPC64) { + MinReservedArea = ((MinReservedArea+15)/16)*16; + MinReservedArea += CalculateStackSlotSize(ObjectVT, + Flags, + PtrByteSize); + } else nAltivecParamsAtEnd++; + } else + // Calculate min reserved area. + MinReservedArea += CalculateStackSlotSize(Ins[ArgNo].VT, + Flags, + PtrByteSize); + + // FIXME the codegen can be much improved in some cases. + // We do not have to keep everything in memory. + if (Flags.isByVal()) { + // ObjSize is the true size, ArgSize rounded up to multiple of registers. + ObjSize = Flags.getByValSize(); + ArgSize = ((ObjSize + PtrByteSize - 1)/PtrByteSize) * PtrByteSize; + // Objects of size 1 and 2 are right justified, everything else is + // left justified. This means the memory address is adjusted forwards. + if (ObjSize==1 || ObjSize==2) { + CurArgOffset = CurArgOffset + (4 - ObjSize); + } + // The value of the object is its address. + int FI = MFI->CreateFixedObject(ObjSize, CurArgOffset, true, false); + SDValue FIN = DAG.getFrameIndex(FI, PtrVT); + InVals.push_back(FIN); + if (ObjSize==1 || ObjSize==2) { + if (GPR_idx != Num_GPR_Regs) { + unsigned VReg = MF.addLiveIn(GPR[GPR_idx], &PPC::GPRCRegClass); + SDValue Val = DAG.getCopyFromReg(Chain, dl, VReg, PtrVT); + SDValue Store = DAG.getTruncStore(Val.getValue(1), dl, Val, FIN, + NULL, 0, ObjSize==1 ? MVT::i8 : MVT::i16 ); + MemOps.push_back(Store); + ++GPR_idx; + } + + ArgOffset += PtrByteSize; + + continue; + } + for (unsigned j = 0; j < ArgSize; j += PtrByteSize) { + // Store whatever pieces of the object are in registers + // to memory. ArgVal will be address of the beginning of + // the object. + if (GPR_idx != Num_GPR_Regs) { + unsigned VReg = MF.addLiveIn(GPR[GPR_idx], &PPC::GPRCRegClass); + int FI = MFI->CreateFixedObject(PtrByteSize, ArgOffset, true, false); + SDValue FIN = DAG.getFrameIndex(FI, PtrVT); + SDValue Val = DAG.getCopyFromReg(Chain, dl, VReg, PtrVT); + SDValue Store = DAG.getStore(Val.getValue(1), dl, Val, FIN, NULL, 0); + MemOps.push_back(Store); + ++GPR_idx; + ArgOffset += PtrByteSize; + } else { + ArgOffset += ArgSize - (ArgOffset-CurArgOffset); + break; + } + } + continue; + } + + switch (ObjectVT.getSimpleVT().SimpleTy) { + default: llvm_unreachable("Unhandled argument type!"); + case MVT::i32: + if (!isPPC64) { + if (GPR_idx != Num_GPR_Regs) { + unsigned VReg = MF.addLiveIn(GPR[GPR_idx], &PPC::GPRCRegClass); + ArgVal = DAG.getCopyFromReg(Chain, dl, VReg, MVT::i32); + ++GPR_idx; + } else { + needsLoad = true; + ArgSize = PtrByteSize; + } + // All int arguments reserve stack space in the Darwin ABI. + ArgOffset += PtrByteSize; + break; + } + // FALLTHROUGH + case MVT::i64: // PPC64 + if (GPR_idx != Num_GPR_Regs) { + unsigned VReg = MF.addLiveIn(GPR[GPR_idx], &PPC::G8RCRegClass); + ArgVal = DAG.getCopyFromReg(Chain, dl, VReg, MVT::i64); + + if (ObjectVT == MVT::i32) { + // PPC64 passes i8, i16, and i32 values in i64 registers. Promote + // value to MVT::i64 and then truncate to the correct register size. + if (Flags.isSExt()) + ArgVal = DAG.getNode(ISD::AssertSext, dl, MVT::i64, ArgVal, + DAG.getValueType(ObjectVT)); + else if (Flags.isZExt()) + ArgVal = DAG.getNode(ISD::AssertZext, dl, MVT::i64, ArgVal, + DAG.getValueType(ObjectVT)); + + ArgVal = DAG.getNode(ISD::TRUNCATE, dl, MVT::i32, ArgVal); + } + + ++GPR_idx; + } else { + needsLoad = true; + ArgSize = PtrByteSize; + } + // All int arguments reserve stack space in the Darwin ABI. + ArgOffset += 8; + break; + + case MVT::f32: + case MVT::f64: + // Every 4 bytes of argument space consumes one of the GPRs available for + // argument passing. + if (GPR_idx != Num_GPR_Regs) { + ++GPR_idx; + if (ObjSize == 8 && GPR_idx != Num_GPR_Regs && !isPPC64) + ++GPR_idx; + } + if (FPR_idx != Num_FPR_Regs) { + unsigned VReg; + + if (ObjectVT == MVT::f32) + VReg = MF.addLiveIn(FPR[FPR_idx], &PPC::F4RCRegClass); + else + VReg = MF.addLiveIn(FPR[FPR_idx], &PPC::F8RCRegClass); + + ArgVal = DAG.getCopyFromReg(Chain, dl, VReg, ObjectVT); + ++FPR_idx; + } else { + needsLoad = true; + } + + // All FP arguments reserve stack space in the Darwin ABI. + ArgOffset += isPPC64 ? 8 : ObjSize; + break; + case MVT::v4f32: + case MVT::v4i32: + case MVT::v8i16: + case MVT::v16i8: + // Note that vector arguments in registers don't reserve stack space, + // except in varargs functions. + if (VR_idx != Num_VR_Regs) { + unsigned VReg = MF.addLiveIn(VR[VR_idx], &PPC::VRRCRegClass); + ArgVal = DAG.getCopyFromReg(Chain, dl, VReg, ObjectVT); + if (isVarArg) { + while ((ArgOffset % 16) != 0) { + ArgOffset += PtrByteSize; + if (GPR_idx != Num_GPR_Regs) + GPR_idx++; + } + ArgOffset += 16; + GPR_idx = std::min(GPR_idx+4, Num_GPR_Regs); // FIXME correct for ppc64? + } + ++VR_idx; + } else { + if (!isVarArg && !isPPC64) { + // Vectors go after all the nonvectors. + CurArgOffset = VecArgOffset; + VecArgOffset += 16; + } else { + // Vectors are aligned. + ArgOffset = ((ArgOffset+15)/16)*16; + CurArgOffset = ArgOffset; + ArgOffset += 16; + } + needsLoad = true; + } + break; + } + + // We need to load the argument to a virtual register if we determined above + // that we ran out of physical registers of the appropriate type. + if (needsLoad) { + int FI = MFI->CreateFixedObject(ObjSize, + CurArgOffset + (ArgSize - ObjSize), + isImmutable, false); + SDValue FIN = DAG.getFrameIndex(FI, PtrVT); + ArgVal = DAG.getLoad(ObjectVT, dl, Chain, FIN, NULL, 0); + } + + InVals.push_back(ArgVal); + } + + // Set the size that is at least reserved in caller of this function. Tail + // call optimized function's reserved stack space needs to be aligned so that + // taking the difference between two stack areas will result in an aligned + // stack. + PPCFunctionInfo *FI = MF.getInfo(); + // Add the Altivec parameters at the end, if needed. + if (nAltivecParamsAtEnd) { + MinReservedArea = ((MinReservedArea+15)/16)*16; + MinReservedArea += 16*nAltivecParamsAtEnd; + } + MinReservedArea = + std::max(MinReservedArea, + PPCFrameInfo::getMinCallFrameSize(isPPC64, true)); + unsigned TargetAlign = DAG.getMachineFunction().getTarget().getFrameInfo()-> + getStackAlignment(); + unsigned AlignMask = TargetAlign-1; + MinReservedArea = (MinReservedArea + AlignMask) & ~AlignMask; + FI->setMinReservedArea(MinReservedArea); + + // If the function takes variable number of arguments, make a frame index for + // the start of the first vararg value... for expansion of llvm.va_start. + if (isVarArg) { + int Depth = ArgOffset; + + VarArgsFrameIndex = MFI->CreateFixedObject(PtrVT.getSizeInBits()/8, + Depth, true, false); + SDValue FIN = DAG.getFrameIndex(VarArgsFrameIndex, PtrVT); + + // If this function is vararg, store any remaining integer argument regs + // to their spots on the stack so that they may be loaded by deferencing the + // result of va_next. + for (; GPR_idx != Num_GPR_Regs; ++GPR_idx) { + unsigned VReg; + + if (isPPC64) + VReg = MF.addLiveIn(GPR[GPR_idx], &PPC::G8RCRegClass); + else + VReg = MF.addLiveIn(GPR[GPR_idx], &PPC::GPRCRegClass); + + SDValue Val = DAG.getCopyFromReg(Chain, dl, VReg, PtrVT); + SDValue Store = DAG.getStore(Val.getValue(1), dl, Val, FIN, NULL, 0); + MemOps.push_back(Store); + // Increment the address by four for the next argument to store + SDValue PtrOff = DAG.getConstant(PtrVT.getSizeInBits()/8, PtrVT); + FIN = DAG.getNode(ISD::ADD, dl, PtrOff.getValueType(), FIN, PtrOff); + } + } + + if (!MemOps.empty()) + Chain = DAG.getNode(ISD::TokenFactor, dl, + MVT::Other, &MemOps[0], MemOps.size()); + + return Chain; +} + +/// CalculateParameterAndLinkageAreaSize - Get the size of the paramter plus +/// linkage area for the Darwin ABI. +static unsigned +CalculateParameterAndLinkageAreaSize(SelectionDAG &DAG, + bool isPPC64, + bool isVarArg, + unsigned CC, + const SmallVectorImpl + &Outs, + unsigned &nAltivecParamsAtEnd) { + // Count how many bytes are to be pushed on the stack, including the linkage + // area, and parameter passing area. We start with 24/48 bytes, which is + // prereserved space for [SP][CR][LR][3 x unused]. + unsigned NumBytes = PPCFrameInfo::getLinkageSize(isPPC64, true); + unsigned NumOps = Outs.size(); + unsigned PtrByteSize = isPPC64 ? 8 : 4; + + // Add up all the space actually used. + // In 32-bit non-varargs calls, Altivec parameters all go at the end; usually + // they all go in registers, but we must reserve stack space for them for + // possible use by the caller. In varargs or 64-bit calls, parameters are + // assigned stack space in order, with padding so Altivec parameters are + // 16-byte aligned. + nAltivecParamsAtEnd = 0; + for (unsigned i = 0; i != NumOps; ++i) { + SDValue Arg = Outs[i].Val; + ISD::ArgFlagsTy Flags = Outs[i].Flags; + EVT ArgVT = Arg.getValueType(); + // Varargs Altivec parameters are padded to a 16 byte boundary. + if (ArgVT==MVT::v4f32 || ArgVT==MVT::v4i32 || + ArgVT==MVT::v8i16 || ArgVT==MVT::v16i8) { + if (!isVarArg && !isPPC64) { + // Non-varargs Altivec parameters go after all the non-Altivec + // parameters; handle those later so we know how much padding we need. + nAltivecParamsAtEnd++; + continue; + } + // Varargs and 64-bit Altivec parameters are padded to 16 byte boundary. + NumBytes = ((NumBytes+15)/16)*16; + } + NumBytes += CalculateStackSlotSize(ArgVT, Flags, PtrByteSize); + } + + // Allow for Altivec parameters at the end, if needed. + if (nAltivecParamsAtEnd) { + NumBytes = ((NumBytes+15)/16)*16; + NumBytes += 16*nAltivecParamsAtEnd; + } + + // The prolog code of the callee may store up to 8 GPR argument registers to + // the stack, allowing va_start to index over them in memory if its varargs. + // Because we cannot tell if this is needed on the caller side, we have to + // conservatively assume that it is needed. As such, make sure we have at + // least enough stack space for the caller to store the 8 GPRs. + NumBytes = std::max(NumBytes, + PPCFrameInfo::getMinCallFrameSize(isPPC64, true)); + + // Tail call needs the stack to be aligned. + if (CC==CallingConv::Fast && PerformTailCallOpt) { + unsigned TargetAlign = DAG.getMachineFunction().getTarget().getFrameInfo()-> + getStackAlignment(); + unsigned AlignMask = TargetAlign-1; + NumBytes = (NumBytes + AlignMask) & ~AlignMask; + } + + return NumBytes; +} + +/// CalculateTailCallSPDiff - Get the amount the stack pointer has to be +/// adjusted to accomodate the arguments for the tailcall. +static int CalculateTailCallSPDiff(SelectionDAG& DAG, bool isTailCall, + unsigned ParamSize) { + + if (!isTailCall) return 0; + + PPCFunctionInfo *FI = DAG.getMachineFunction().getInfo(); + unsigned CallerMinReservedArea = FI->getMinReservedArea(); + int SPDiff = (int)CallerMinReservedArea - (int)ParamSize; + // Remember only if the new adjustement is bigger. + if (SPDiff < FI->getTailCallSPDelta()) + FI->setTailCallSPDelta(SPDiff); + + return SPDiff; +} + +/// IsEligibleForTailCallOptimization - Check whether the call is eligible +/// for tail call optimization. Targets which want to do tail call +/// optimization should implement this function. +bool +PPCTargetLowering::IsEligibleForTailCallOptimization(SDValue Callee, + CallingConv::ID CalleeCC, + bool isVarArg, + const SmallVectorImpl &Ins, + SelectionDAG& DAG) const { + // Variable argument functions are not supported. + if (isVarArg) + return false; + + MachineFunction &MF = DAG.getMachineFunction(); + CallingConv::ID CallerCC = MF.getFunction()->getCallingConv(); + if (CalleeCC == CallingConv::Fast && CallerCC == CalleeCC) { + // Functions containing by val parameters are not supported. + for (unsigned i = 0; i != Ins.size(); i++) { + ISD::ArgFlagsTy Flags = Ins[i].Flags; + if (Flags.isByVal()) return false; + } + + // Non PIC/GOT tail calls are supported. + if (getTargetMachine().getRelocationModel() != Reloc::PIC_) + return true; + + // At the moment we can only do local tail calls (in same module, hidden + // or protected) if we are generating PIC. + if (GlobalAddressSDNode *G = dyn_cast(Callee)) + return G->getGlobal()->hasHiddenVisibility() + || G->getGlobal()->hasProtectedVisibility(); + } + + return false; +} + +/// isCallCompatibleAddress - Return the immediate to use if the specified +/// 32-bit value is representable in the immediate field of a BxA instruction. +static SDNode *isBLACompatibleAddress(SDValue Op, SelectionDAG &DAG) { + ConstantSDNode *C = dyn_cast(Op); + if (!C) return 0; + + int Addr = C->getZExtValue(); + if ((Addr & 3) != 0 || // Low 2 bits are implicitly zero. + (Addr << 6 >> 6) != Addr) + return 0; // Top 6 bits have to be sext of immediate. + + return DAG.getConstant((int)C->getZExtValue() >> 2, + DAG.getTargetLoweringInfo().getPointerTy()).getNode(); +} + +namespace { + +struct TailCallArgumentInfo { + SDValue Arg; + SDValue FrameIdxOp; + int FrameIdx; + + TailCallArgumentInfo() : FrameIdx(0) {} +}; + +} + +/// StoreTailCallArgumentsToStackSlot - Stores arguments to their stack slot. +static void +StoreTailCallArgumentsToStackSlot(SelectionDAG &DAG, + SDValue Chain, + const SmallVector &TailCallArgs, + SmallVector &MemOpChains, + DebugLoc dl) { + for (unsigned i = 0, e = TailCallArgs.size(); i != e; ++i) { + SDValue Arg = TailCallArgs[i].Arg; + SDValue FIN = TailCallArgs[i].FrameIdxOp; + int FI = TailCallArgs[i].FrameIdx; + // Store relative to framepointer. + MemOpChains.push_back(DAG.getStore(Chain, dl, Arg, FIN, + PseudoSourceValue::getFixedStack(FI), + 0)); + } +} + +/// EmitTailCallStoreFPAndRetAddr - Move the frame pointer and return address to +/// the appropriate stack slot for the tail call optimized function call. +static SDValue EmitTailCallStoreFPAndRetAddr(SelectionDAG &DAG, + MachineFunction &MF, + SDValue Chain, + SDValue OldRetAddr, + SDValue OldFP, + int SPDiff, + bool isPPC64, + bool isDarwinABI, + DebugLoc dl) { + if (SPDiff) { + // Calculate the new stack slot for the return address. + int SlotSize = isPPC64 ? 8 : 4; + int NewRetAddrLoc = SPDiff + PPCFrameInfo::getReturnSaveOffset(isPPC64, + isDarwinABI); + int NewRetAddr = MF.getFrameInfo()->CreateFixedObject(SlotSize, + NewRetAddrLoc, + true, false); + EVT VT = isPPC64 ? MVT::i64 : MVT::i32; + SDValue NewRetAddrFrIdx = DAG.getFrameIndex(NewRetAddr, VT); + Chain = DAG.getStore(Chain, dl, OldRetAddr, NewRetAddrFrIdx, + PseudoSourceValue::getFixedStack(NewRetAddr), 0); + + // When using the 32/64-bit SVR4 ABI there is no need to move the FP stack + // slot as the FP is never overwritten. + if (isDarwinABI) { + int NewFPLoc = + SPDiff + PPCFrameInfo::getFramePointerSaveOffset(isPPC64, isDarwinABI); + int NewFPIdx = MF.getFrameInfo()->CreateFixedObject(SlotSize, NewFPLoc, + true, false); + SDValue NewFramePtrIdx = DAG.getFrameIndex(NewFPIdx, VT); + Chain = DAG.getStore(Chain, dl, OldFP, NewFramePtrIdx, + PseudoSourceValue::getFixedStack(NewFPIdx), 0); + } + } + return Chain; +} + +/// CalculateTailCallArgDest - Remember Argument for later processing. Calculate +/// the position of the argument. +static void +CalculateTailCallArgDest(SelectionDAG &DAG, MachineFunction &MF, bool isPPC64, + SDValue Arg, int SPDiff, unsigned ArgOffset, + SmallVector& TailCallArguments) { + int Offset = ArgOffset + SPDiff; + uint32_t OpSize = (Arg.getValueType().getSizeInBits()+7)/8; + int FI = MF.getFrameInfo()->CreateFixedObject(OpSize, Offset, true,false); + EVT VT = isPPC64 ? MVT::i64 : MVT::i32; + SDValue FIN = DAG.getFrameIndex(FI, VT); + TailCallArgumentInfo Info; + Info.Arg = Arg; + Info.FrameIdxOp = FIN; + Info.FrameIdx = FI; + TailCallArguments.push_back(Info); +} + +/// EmitTCFPAndRetAddrLoad - Emit load from frame pointer and return address +/// stack slot. Returns the chain as result and the loaded frame pointers in +/// LROpOut/FPOpout. Used when tail calling. +SDValue PPCTargetLowering::EmitTailCallLoadFPAndRetAddr(SelectionDAG & DAG, + int SPDiff, + SDValue Chain, + SDValue &LROpOut, + SDValue &FPOpOut, + bool isDarwinABI, + DebugLoc dl) { + if (SPDiff) { + // Load the LR and FP stack slot for later adjusting. + EVT VT = PPCSubTarget.isPPC64() ? MVT::i64 : MVT::i32; + LROpOut = getReturnAddrFrameIndex(DAG); + LROpOut = DAG.getLoad(VT, dl, Chain, LROpOut, NULL, 0); + Chain = SDValue(LROpOut.getNode(), 1); + + // When using the 32/64-bit SVR4 ABI there is no need to load the FP stack + // slot as the FP is never overwritten. + if (isDarwinABI) { + FPOpOut = getFramePointerFrameIndex(DAG); + FPOpOut = DAG.getLoad(VT, dl, Chain, FPOpOut, NULL, 0); + Chain = SDValue(FPOpOut.getNode(), 1); + } + } + return Chain; +} + +/// CreateCopyOfByValArgument - Make a copy of an aggregate at address specified +/// by "Src" to address "Dst" of size "Size". Alignment information is +/// specified by the specific parameter attribute. The copy will be passed as +/// a byval function parameter. +/// Sometimes what we are copying is the end of a larger object, the part that +/// does not fit in registers. +static SDValue +CreateCopyOfByValArgument(SDValue Src, SDValue Dst, SDValue Chain, + ISD::ArgFlagsTy Flags, SelectionDAG &DAG, + DebugLoc dl) { + SDValue SizeNode = DAG.getConstant(Flags.getByValSize(), MVT::i32); + return DAG.getMemcpy(Chain, dl, Dst, Src, SizeNode, Flags.getByValAlign(), + false, NULL, 0, NULL, 0); +} + +/// LowerMemOpCallTo - Store the argument to the stack or remember it in case of +/// tail calls. +static void +LowerMemOpCallTo(SelectionDAG &DAG, MachineFunction &MF, SDValue Chain, + SDValue Arg, SDValue PtrOff, int SPDiff, + unsigned ArgOffset, bool isPPC64, bool isTailCall, + bool isVector, SmallVector &MemOpChains, + SmallVector& TailCallArguments, + DebugLoc dl) { + EVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy(); + if (!isTailCall) { + if (isVector) { + SDValue StackPtr; + if (isPPC64) + StackPtr = DAG.getRegister(PPC::X1, MVT::i64); + else + StackPtr = DAG.getRegister(PPC::R1, MVT::i32); + PtrOff = DAG.getNode(ISD::ADD, dl, PtrVT, StackPtr, + DAG.getConstant(ArgOffset, PtrVT)); + } + MemOpChains.push_back(DAG.getStore(Chain, dl, Arg, PtrOff, NULL, 0)); + // Calculate and remember argument location. + } else CalculateTailCallArgDest(DAG, MF, isPPC64, Arg, SPDiff, ArgOffset, + TailCallArguments); +} + +static +void PrepareTailCall(SelectionDAG &DAG, SDValue &InFlag, SDValue &Chain, + DebugLoc dl, bool isPPC64, int SPDiff, unsigned NumBytes, + SDValue LROp, SDValue FPOp, bool isDarwinABI, + SmallVector &TailCallArguments) { + MachineFunction &MF = DAG.getMachineFunction(); + + // Emit a sequence of copyto/copyfrom virtual registers for arguments that + // might overwrite each other in case of tail call optimization. + SmallVector MemOpChains2; + // Do not flag preceeding copytoreg stuff together with the following stuff. + InFlag = SDValue(); + StoreTailCallArgumentsToStackSlot(DAG, Chain, TailCallArguments, + MemOpChains2, dl); + if (!MemOpChains2.empty()) + Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, + &MemOpChains2[0], MemOpChains2.size()); + + // Store the return address to the appropriate stack slot. + Chain = EmitTailCallStoreFPAndRetAddr(DAG, MF, Chain, LROp, FPOp, SPDiff, + isPPC64, isDarwinABI, dl); + + // Emit callseq_end just before tailcall node. + Chain = DAG.getCALLSEQ_END(Chain, DAG.getIntPtrConstant(NumBytes, true), + DAG.getIntPtrConstant(0, true), InFlag); + InFlag = Chain.getValue(1); +} + +static +unsigned PrepareCall(SelectionDAG &DAG, SDValue &Callee, SDValue &InFlag, + SDValue &Chain, DebugLoc dl, int SPDiff, bool isTailCall, + SmallVector, 8> &RegsToPass, + SmallVector &Ops, std::vector &NodeTys, + bool isSVR4ABI) { + EVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy(); + NodeTys.push_back(MVT::Other); // Returns a chain + NodeTys.push_back(MVT::Flag); // Returns a flag for retval copy to use. + + unsigned CallOpc = isSVR4ABI ? PPCISD::CALL_SVR4 : PPCISD::CALL_Darwin; + + // If the callee is a GlobalAddress/ExternalSymbol node (quite common, every + // direct call is) turn it into a TargetGlobalAddress/TargetExternalSymbol + // node so that legalize doesn't hack it. + if (GlobalAddressSDNode *G = dyn_cast(Callee)) + Callee = DAG.getTargetGlobalAddress(G->getGlobal(), Callee.getValueType()); + else if (ExternalSymbolSDNode *S = dyn_cast(Callee)) + Callee = DAG.getTargetExternalSymbol(S->getSymbol(), Callee.getValueType()); + else if (SDNode *Dest = isBLACompatibleAddress(Callee, DAG)) + // If this is an absolute destination address, use the munged value. + Callee = SDValue(Dest, 0); + else { + // Otherwise, this is an indirect call. We have to use a MTCTR/BCTRL pair + // to do the call, we can't use PPCISD::CALL. + SDValue MTCTROps[] = {Chain, Callee, InFlag}; + Chain = DAG.getNode(PPCISD::MTCTR, dl, NodeTys, MTCTROps, + 2 + (InFlag.getNode() != 0)); + InFlag = Chain.getValue(1); + + NodeTys.clear(); + NodeTys.push_back(MVT::Other); + NodeTys.push_back(MVT::Flag); + Ops.push_back(Chain); + CallOpc = isSVR4ABI ? PPCISD::BCTRL_SVR4 : PPCISD::BCTRL_Darwin; + Callee.setNode(0); + // Add CTR register as callee so a bctr can be emitted later. + if (isTailCall) + Ops.push_back(DAG.getRegister(PPC::CTR, PtrVT)); + } + + // If this is a direct call, pass the chain and the callee. + if (Callee.getNode()) { + Ops.push_back(Chain); + Ops.push_back(Callee); + } + // If this is a tail call add stack pointer delta. + if (isTailCall) + Ops.push_back(DAG.getConstant(SPDiff, MVT::i32)); + + // Add argument registers to the end of the list so that they are known live + // into the call. + for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) + Ops.push_back(DAG.getRegister(RegsToPass[i].first, + RegsToPass[i].second.getValueType())); + + return CallOpc; +} + +SDValue +PPCTargetLowering::LowerCallResult(SDValue Chain, SDValue InFlag, + CallingConv::ID CallConv, bool isVarArg, + const SmallVectorImpl &Ins, + DebugLoc dl, SelectionDAG &DAG, + SmallVectorImpl &InVals) { + + SmallVector RVLocs; + CCState CCRetInfo(CallConv, isVarArg, getTargetMachine(), + RVLocs, *DAG.getContext()); + CCRetInfo.AnalyzeCallResult(Ins, RetCC_PPC); + + // Copy all of the result registers out of their specified physreg. + for (unsigned i = 0, e = RVLocs.size(); i != e; ++i) { + CCValAssign &VA = RVLocs[i]; + EVT VT = VA.getValVT(); + assert(VA.isRegLoc() && "Can only return in registers!"); + Chain = DAG.getCopyFromReg(Chain, dl, + VA.getLocReg(), VT, InFlag).getValue(1); + InVals.push_back(Chain.getValue(0)); + InFlag = Chain.getValue(2); + } + + return Chain; +} + +SDValue +PPCTargetLowering::FinishCall(CallingConv::ID CallConv, DebugLoc dl, + bool isTailCall, bool isVarArg, + SelectionDAG &DAG, + SmallVector, 8> + &RegsToPass, + SDValue InFlag, SDValue Chain, + SDValue &Callee, + int SPDiff, unsigned NumBytes, + const SmallVectorImpl &Ins, + SmallVectorImpl &InVals) { + std::vector NodeTys; + SmallVector Ops; + unsigned CallOpc = PrepareCall(DAG, Callee, InFlag, Chain, dl, SPDiff, + isTailCall, RegsToPass, Ops, NodeTys, + PPCSubTarget.isSVR4ABI()); + + // When performing tail call optimization the callee pops its arguments off + // the stack. Account for this here so these bytes can be pushed back on in + // PPCRegisterInfo::eliminateCallFramePseudoInstr. + int BytesCalleePops = + (CallConv==CallingConv::Fast && PerformTailCallOpt) ? NumBytes : 0; + + if (InFlag.getNode()) + Ops.push_back(InFlag); + + // Emit tail call. + if (isTailCall) { + // If this is the first return lowered for this function, add the regs + // to the liveout set for the function. + if (DAG.getMachineFunction().getRegInfo().liveout_empty()) { + SmallVector RVLocs; + CCState CCInfo(CallConv, isVarArg, getTargetMachine(), RVLocs, + *DAG.getContext()); + CCInfo.AnalyzeCallResult(Ins, RetCC_PPC); + for (unsigned i = 0; i != RVLocs.size(); ++i) + DAG.getMachineFunction().getRegInfo().addLiveOut(RVLocs[i].getLocReg()); + } + + assert(((Callee.getOpcode() == ISD::Register && + cast(Callee)->getReg() == PPC::CTR) || + Callee.getOpcode() == ISD::TargetExternalSymbol || + Callee.getOpcode() == ISD::TargetGlobalAddress || + isa(Callee)) && + "Expecting an global address, external symbol, absolute value or register"); + + return DAG.getNode(PPCISD::TC_RETURN, dl, MVT::Other, &Ops[0], Ops.size()); + } + + Chain = DAG.getNode(CallOpc, dl, NodeTys, &Ops[0], Ops.size()); + InFlag = Chain.getValue(1); + + // Add a NOP immediately after the branch instruction when using the 64-bit + // SVR4 ABI. At link time, if caller and callee are in a different module and + // thus have a different TOC, the call will be replaced with a call to a stub + // function which saves the current TOC, loads the TOC of the callee and + // branches to the callee. The NOP will be replaced with a load instruction + // which restores the TOC of the caller from the TOC save slot of the current + // stack frame. If caller and callee belong to the same module (and have the + // same TOC), the NOP will remain unchanged. + if (!isTailCall && PPCSubTarget.isSVR4ABI()&& PPCSubTarget.isPPC64()) { + // Insert NOP. + InFlag = DAG.getNode(PPCISD::NOP, dl, MVT::Flag, InFlag); + } + + Chain = DAG.getCALLSEQ_END(Chain, DAG.getIntPtrConstant(NumBytes, true), + DAG.getIntPtrConstant(BytesCalleePops, true), + InFlag); + if (!Ins.empty()) + InFlag = Chain.getValue(1); + + return LowerCallResult(Chain, InFlag, CallConv, isVarArg, + Ins, dl, DAG, InVals); +} + +SDValue +PPCTargetLowering::LowerCall(SDValue Chain, SDValue Callee, + CallingConv::ID CallConv, bool isVarArg, + bool isTailCall, + const SmallVectorImpl &Outs, + const SmallVectorImpl &Ins, + DebugLoc dl, SelectionDAG &DAG, + SmallVectorImpl &InVals) { + if (PPCSubTarget.isSVR4ABI() && !PPCSubTarget.isPPC64()) { + return LowerCall_SVR4(Chain, Callee, CallConv, isVarArg, + isTailCall, Outs, Ins, + dl, DAG, InVals); + } else { + return LowerCall_Darwin(Chain, Callee, CallConv, isVarArg, + isTailCall, Outs, Ins, + dl, DAG, InVals); + } +} + +SDValue +PPCTargetLowering::LowerCall_SVR4(SDValue Chain, SDValue Callee, + CallingConv::ID CallConv, bool isVarArg, + bool isTailCall, + const SmallVectorImpl &Outs, + const SmallVectorImpl &Ins, + DebugLoc dl, SelectionDAG &DAG, + SmallVectorImpl &InVals) { + // See PPCTargetLowering::LowerFormalArguments_SVR4() for a description + // of the 32-bit SVR4 ABI stack frame layout. + + assert((!isTailCall || + (CallConv == CallingConv::Fast && PerformTailCallOpt)) && + "IsEligibleForTailCallOptimization missed a case!"); + + assert((CallConv == CallingConv::C || + CallConv == CallingConv::Fast) && "Unknown calling convention!"); + + EVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy(); + unsigned PtrByteSize = 4; + + MachineFunction &MF = DAG.getMachineFunction(); + + // Mark this function as potentially containing a function that contains a + // tail call. As a consequence the frame pointer will be used for dynamicalloc + // and restoring the callers stack pointer in this functions epilog. This is + // done because by tail calling the called function might overwrite the value + // in this function's (MF) stack pointer stack slot 0(SP). + if (PerformTailCallOpt && CallConv==CallingConv::Fast) + MF.getInfo()->setHasFastCall(); + + // Count how many bytes are to be pushed on the stack, including the linkage + // area, parameter list area and the part of the local variable space which + // contains copies of aggregates which are passed by value. + + // Assign locations to all of the outgoing arguments. + SmallVector ArgLocs; + CCState CCInfo(CallConv, isVarArg, getTargetMachine(), + ArgLocs, *DAG.getContext()); + + // Reserve space for the linkage area on the stack. + CCInfo.AllocateStack(PPCFrameInfo::getLinkageSize(false, false), PtrByteSize); + + if (isVarArg) { + // Handle fixed and variable vector arguments differently. + // Fixed vector arguments go into registers as long as registers are + // available. Variable vector arguments always go into memory. + unsigned NumArgs = Outs.size(); + + for (unsigned i = 0; i != NumArgs; ++i) { + EVT ArgVT = Outs[i].Val.getValueType(); + ISD::ArgFlagsTy ArgFlags = Outs[i].Flags; + bool Result; + + if (Outs[i].IsFixed) { + Result = CC_PPC_SVR4(i, ArgVT, ArgVT, CCValAssign::Full, ArgFlags, + CCInfo); + } else { + Result = CC_PPC_SVR4_VarArg(i, ArgVT, ArgVT, CCValAssign::Full, + ArgFlags, CCInfo); + } + + if (Result) { +#ifndef NDEBUG + errs() << "Call operand #" << i << " has unhandled type " + << ArgVT.getEVTString() << "\n"; +#endif + llvm_unreachable(0); + } + } + } else { + // All arguments are treated the same. + CCInfo.AnalyzeCallOperands(Outs, CC_PPC_SVR4); + } + + // Assign locations to all of the outgoing aggregate by value arguments. + SmallVector ByValArgLocs; + CCState CCByValInfo(CallConv, isVarArg, getTargetMachine(), ByValArgLocs, + *DAG.getContext()); + + // Reserve stack space for the allocations in CCInfo. + CCByValInfo.AllocateStack(CCInfo.getNextStackOffset(), PtrByteSize); + + CCByValInfo.AnalyzeCallOperands(Outs, CC_PPC_SVR4_ByVal); + + // Size of the linkage area, parameter list area and the part of the local + // space variable where copies of aggregates which are passed by value are + // stored. + unsigned NumBytes = CCByValInfo.getNextStackOffset(); + + // Calculate by how many bytes the stack has to be adjusted in case of tail + // call optimization. + int SPDiff = CalculateTailCallSPDiff(DAG, isTailCall, NumBytes); + + // Adjust the stack pointer for the new arguments... + // These operations are automatically eliminated by the prolog/epilog pass + Chain = DAG.getCALLSEQ_START(Chain, DAG.getIntPtrConstant(NumBytes, true)); + SDValue CallSeqStart = Chain; + + // Load the return address and frame pointer so it can be moved somewhere else + // later. + SDValue LROp, FPOp; + Chain = EmitTailCallLoadFPAndRetAddr(DAG, SPDiff, Chain, LROp, FPOp, false, + dl); + + // Set up a copy of the stack pointer for use loading and storing any + // arguments that may not fit in the registers available for argument + // passing. + SDValue StackPtr = DAG.getRegister(PPC::R1, MVT::i32); + + SmallVector, 8> RegsToPass; + SmallVector TailCallArguments; + SmallVector MemOpChains; + + // Walk the register/memloc assignments, inserting copies/loads. + for (unsigned i = 0, j = 0, e = ArgLocs.size(); + i != e; + ++i) { + CCValAssign &VA = ArgLocs[i]; + SDValue Arg = Outs[i].Val; + ISD::ArgFlagsTy Flags = Outs[i].Flags; + + if (Flags.isByVal()) { + // Argument is an aggregate which is passed by value, thus we need to + // create a copy of it in the local variable space of the current stack + // frame (which is the stack frame of the caller) and pass the address of + // this copy to the callee. + assert((j < ByValArgLocs.size()) && "Index out of bounds!"); + CCValAssign &ByValVA = ByValArgLocs[j++]; + assert((VA.getValNo() == ByValVA.getValNo()) && "ValNo mismatch!"); + + // Memory reserved in the local variable space of the callers stack frame. + unsigned LocMemOffset = ByValVA.getLocMemOffset(); + + SDValue PtrOff = DAG.getIntPtrConstant(LocMemOffset); + PtrOff = DAG.getNode(ISD::ADD, dl, getPointerTy(), StackPtr, PtrOff); + + // Create a copy of the argument in the local area of the current + // stack frame. + SDValue MemcpyCall = + CreateCopyOfByValArgument(Arg, PtrOff, + CallSeqStart.getNode()->getOperand(0), + Flags, DAG, dl); + + // This must go outside the CALLSEQ_START..END. + SDValue NewCallSeqStart = DAG.getCALLSEQ_START(MemcpyCall, + CallSeqStart.getNode()->getOperand(1)); + DAG.ReplaceAllUsesWith(CallSeqStart.getNode(), + NewCallSeqStart.getNode()); + Chain = CallSeqStart = NewCallSeqStart; + + // Pass the address of the aggregate copy on the stack either in a + // physical register or in the parameter list area of the current stack + // frame to the callee. + Arg = PtrOff; + } + + if (VA.isRegLoc()) { + // Put argument in a physical register. + RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg)); + } else { + // Put argument in the parameter list area of the current stack frame. + assert(VA.isMemLoc()); + unsigned LocMemOffset = VA.getLocMemOffset(); + + if (!isTailCall) { + SDValue PtrOff = DAG.getIntPtrConstant(LocMemOffset); + PtrOff = DAG.getNode(ISD::ADD, dl, getPointerTy(), StackPtr, PtrOff); + + MemOpChains.push_back(DAG.getStore(Chain, dl, Arg, PtrOff, + PseudoSourceValue::getStack(), LocMemOffset)); + } else { + // Calculate and remember argument location. + CalculateTailCallArgDest(DAG, MF, false, Arg, SPDiff, LocMemOffset, + TailCallArguments); + } + } + } + + if (!MemOpChains.empty()) + Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, + &MemOpChains[0], MemOpChains.size()); + + // Build a sequence of copy-to-reg nodes chained together with token chain + // and flag operands which copy the outgoing args into the appropriate regs. + SDValue InFlag; + for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) { + Chain = DAG.getCopyToReg(Chain, dl, RegsToPass[i].first, + RegsToPass[i].second, InFlag); + InFlag = Chain.getValue(1); + } + + // Set CR6 to true if this is a vararg call. + if (isVarArg) { + SDValue SetCR(DAG.getMachineNode(PPC::CRSET, dl, MVT::i32), 0); + Chain = DAG.getCopyToReg(Chain, dl, PPC::CR1EQ, SetCR, InFlag); + InFlag = Chain.getValue(1); + } + + if (isTailCall) { + PrepareTailCall(DAG, InFlag, Chain, dl, false, SPDiff, NumBytes, LROp, FPOp, + false, TailCallArguments); + } + + return FinishCall(CallConv, dl, isTailCall, isVarArg, DAG, + RegsToPass, InFlag, Chain, Callee, SPDiff, NumBytes, + Ins, InVals); +} + +SDValue +PPCTargetLowering::LowerCall_Darwin(SDValue Chain, SDValue Callee, + CallingConv::ID CallConv, bool isVarArg, + bool isTailCall, + const SmallVectorImpl &Outs, + const SmallVectorImpl &Ins, + DebugLoc dl, SelectionDAG &DAG, + SmallVectorImpl &InVals) { + + unsigned NumOps = Outs.size(); + + EVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy(); + bool isPPC64 = PtrVT == MVT::i64; + unsigned PtrByteSize = isPPC64 ? 8 : 4; + + MachineFunction &MF = DAG.getMachineFunction(); + + // Mark this function as potentially containing a function that contains a + // tail call. As a consequence the frame pointer will be used for dynamicalloc + // and restoring the callers stack pointer in this functions epilog. This is + // done because by tail calling the called function might overwrite the value + // in this function's (MF) stack pointer stack slot 0(SP). + if (PerformTailCallOpt && CallConv==CallingConv::Fast) + MF.getInfo()->setHasFastCall(); + + unsigned nAltivecParamsAtEnd = 0; + + // Count how many bytes are to be pushed on the stack, including the linkage + // area, and parameter passing area. We start with 24/48 bytes, which is + // prereserved space for [SP][CR][LR][3 x unused]. + unsigned NumBytes = + CalculateParameterAndLinkageAreaSize(DAG, isPPC64, isVarArg, CallConv, + Outs, + nAltivecParamsAtEnd); + + // Calculate by how many bytes the stack has to be adjusted in case of tail + // call optimization. + int SPDiff = CalculateTailCallSPDiff(DAG, isTailCall, NumBytes); + + // To protect arguments on the stack from being clobbered in a tail call, + // force all the loads to happen before doing any other lowering. + if (isTailCall) + Chain = DAG.getStackArgumentTokenFactor(Chain); + + // Adjust the stack pointer for the new arguments... + // These operations are automatically eliminated by the prolog/epilog pass + Chain = DAG.getCALLSEQ_START(Chain, DAG.getIntPtrConstant(NumBytes, true)); + SDValue CallSeqStart = Chain; + + // Load the return address and frame pointer so it can be move somewhere else + // later. + SDValue LROp, FPOp; + Chain = EmitTailCallLoadFPAndRetAddr(DAG, SPDiff, Chain, LROp, FPOp, true, + dl); + + // Set up a copy of the stack pointer for use loading and storing any + // arguments that may not fit in the registers available for argument + // passing. + SDValue StackPtr; + if (isPPC64) + StackPtr = DAG.getRegister(PPC::X1, MVT::i64); + else + StackPtr = DAG.getRegister(PPC::R1, MVT::i32); + + // Figure out which arguments are going to go in registers, and which in + // memory. Also, if this is a vararg function, floating point operations + // must be stored to our stack, and loaded into integer regs as well, if + // any integer regs are available for argument passing. + unsigned ArgOffset = PPCFrameInfo::getLinkageSize(isPPC64, true); + unsigned GPR_idx = 0, FPR_idx = 0, VR_idx = 0; + + static const unsigned GPR_32[] = { // 32-bit registers. + PPC::R3, PPC::R4, PPC::R5, PPC::R6, + PPC::R7, PPC::R8, PPC::R9, PPC::R10, + }; + static const unsigned GPR_64[] = { // 64-bit registers. + PPC::X3, PPC::X4, PPC::X5, PPC::X6, + PPC::X7, PPC::X8, PPC::X9, PPC::X10, + }; + static const unsigned *FPR = GetFPR(); + + static const unsigned VR[] = { + PPC::V2, PPC::V3, PPC::V4, PPC::V5, PPC::V6, PPC::V7, PPC::V8, + PPC::V9, PPC::V10, PPC::V11, PPC::V12, PPC::V13 + }; + const unsigned NumGPRs = array_lengthof(GPR_32); + const unsigned NumFPRs = 13; + const unsigned NumVRs = array_lengthof(VR); + + const unsigned *GPR = isPPC64 ? GPR_64 : GPR_32; + + SmallVector, 8> RegsToPass; + SmallVector TailCallArguments; + + SmallVector MemOpChains; + for (unsigned i = 0; i != NumOps; ++i) { + SDValue Arg = Outs[i].Val; + ISD::ArgFlagsTy Flags = Outs[i].Flags; + + // PtrOff will be used to store the current argument to the stack if a + // register cannot be found for it. + SDValue PtrOff; + + PtrOff = DAG.getConstant(ArgOffset, StackPtr.getValueType()); + + PtrOff = DAG.getNode(ISD::ADD, dl, PtrVT, StackPtr, PtrOff); + + // On PPC64, promote integers to 64-bit values. + if (isPPC64 && Arg.getValueType() == MVT::i32) { + // FIXME: Should this use ANY_EXTEND if neither sext nor zext? + unsigned ExtOp = Flags.isSExt() ? ISD::SIGN_EXTEND : ISD::ZERO_EXTEND; + Arg = DAG.getNode(ExtOp, dl, MVT::i64, Arg); + } + + // FIXME memcpy is used way more than necessary. Correctness first. + if (Flags.isByVal()) { + unsigned Size = Flags.getByValSize(); + if (Size==1 || Size==2) { + // Very small objects are passed right-justified. + // Everything else is passed left-justified. + EVT VT = (Size==1) ? MVT::i8 : MVT::i16; + if (GPR_idx != NumGPRs) { + SDValue Load = DAG.getExtLoad(ISD::EXTLOAD, dl, PtrVT, Chain, Arg, + NULL, 0, VT); + MemOpChains.push_back(Load.getValue(1)); + RegsToPass.push_back(std::make_pair(GPR[GPR_idx++], Load)); + + ArgOffset += PtrByteSize; + } else { + SDValue Const = DAG.getConstant(4 - Size, PtrOff.getValueType()); + SDValue AddPtr = DAG.getNode(ISD::ADD, dl, PtrVT, PtrOff, Const); + SDValue MemcpyCall = CreateCopyOfByValArgument(Arg, AddPtr, + CallSeqStart.getNode()->getOperand(0), + Flags, DAG, dl); + // This must go outside the CALLSEQ_START..END. + SDValue NewCallSeqStart = DAG.getCALLSEQ_START(MemcpyCall, + CallSeqStart.getNode()->getOperand(1)); + DAG.ReplaceAllUsesWith(CallSeqStart.getNode(), + NewCallSeqStart.getNode()); + Chain = CallSeqStart = NewCallSeqStart; + ArgOffset += PtrByteSize; + } + continue; + } + // Copy entire object into memory. There are cases where gcc-generated + // code assumes it is there, even if it could be put entirely into + // registers. (This is not what the doc says.) + SDValue MemcpyCall = CreateCopyOfByValArgument(Arg, PtrOff, + CallSeqStart.getNode()->getOperand(0), + Flags, DAG, dl); + // This must go outside the CALLSEQ_START..END. + SDValue NewCallSeqStart = DAG.getCALLSEQ_START(MemcpyCall, + CallSeqStart.getNode()->getOperand(1)); + DAG.ReplaceAllUsesWith(CallSeqStart.getNode(), NewCallSeqStart.getNode()); + Chain = CallSeqStart = NewCallSeqStart; + // And copy the pieces of it that fit into registers. + for (unsigned j=0; j NumVRs) { + unsigned j = 0; + // Offset is aligned; skip 1st 12 params which go in V registers. + ArgOffset = ((ArgOffset+15)/16)*16; + ArgOffset += 12*16; + for (unsigned i = 0; i != NumOps; ++i) { + SDValue Arg = Outs[i].Val; + EVT ArgType = Arg.getValueType(); + if (ArgType==MVT::v4f32 || ArgType==MVT::v4i32 || + ArgType==MVT::v8i16 || ArgType==MVT::v16i8) { + if (++j > NumVRs) { + SDValue PtrOff; + // We are emitting Altivec params in order. + LowerMemOpCallTo(DAG, MF, Chain, Arg, PtrOff, SPDiff, ArgOffset, + isPPC64, isTailCall, true, MemOpChains, + TailCallArguments, dl); + ArgOffset += 16; + } + } + } + } + + if (!MemOpChains.empty()) + Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, + &MemOpChains[0], MemOpChains.size()); + + // Build a sequence of copy-to-reg nodes chained together with token chain + // and flag operands which copy the outgoing args into the appropriate regs. + SDValue InFlag; + for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) { + Chain = DAG.getCopyToReg(Chain, dl, RegsToPass[i].first, + RegsToPass[i].second, InFlag); + InFlag = Chain.getValue(1); + } + + if (isTailCall) { + PrepareTailCall(DAG, InFlag, Chain, dl, isPPC64, SPDiff, NumBytes, LROp, + FPOp, true, TailCallArguments); + } + + return FinishCall(CallConv, dl, isTailCall, isVarArg, DAG, + RegsToPass, InFlag, Chain, Callee, SPDiff, NumBytes, + Ins, InVals); +} + +SDValue +PPCTargetLowering::LowerReturn(SDValue Chain, + CallingConv::ID CallConv, bool isVarArg, + const SmallVectorImpl &Outs, + DebugLoc dl, SelectionDAG &DAG) { + + SmallVector RVLocs; + CCState CCInfo(CallConv, isVarArg, getTargetMachine(), + RVLocs, *DAG.getContext()); + CCInfo.AnalyzeReturn(Outs, RetCC_PPC); + + // If this is the first return lowered for this function, add the regs to the + // liveout set for the function. + if (DAG.getMachineFunction().getRegInfo().liveout_empty()) { + for (unsigned i = 0; i != RVLocs.size(); ++i) + DAG.getMachineFunction().getRegInfo().addLiveOut(RVLocs[i].getLocReg()); + } + + SDValue Flag; + + // Copy the result values into the output registers. + for (unsigned i = 0; i != RVLocs.size(); ++i) { + CCValAssign &VA = RVLocs[i]; + assert(VA.isRegLoc() && "Can only return in registers!"); + Chain = DAG.getCopyToReg(Chain, dl, VA.getLocReg(), + Outs[i].Val, Flag); + Flag = Chain.getValue(1); + } + + if (Flag.getNode()) + return DAG.getNode(PPCISD::RET_FLAG, dl, MVT::Other, Chain, Flag); + else + return DAG.getNode(PPCISD::RET_FLAG, dl, MVT::Other, Chain); +} + +SDValue PPCTargetLowering::LowerSTACKRESTORE(SDValue Op, SelectionDAG &DAG, + const PPCSubtarget &Subtarget) { + // When we pop the dynamic allocation we need to restore the SP link. + DebugLoc dl = Op.getDebugLoc(); + + // Get the corect type for pointers. + EVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy(); + + // Construct the stack pointer operand. + bool isPPC64 = Subtarget.isPPC64(); + unsigned SP = isPPC64 ? PPC::X1 : PPC::R1; + SDValue StackPtr = DAG.getRegister(SP, PtrVT); + + // Get the operands for the STACKRESTORE. + SDValue Chain = Op.getOperand(0); + SDValue SaveSP = Op.getOperand(1); + + // Load the old link SP. + SDValue LoadLinkSP = DAG.getLoad(PtrVT, dl, Chain, StackPtr, NULL, 0); + + // Restore the stack pointer. + Chain = DAG.getCopyToReg(LoadLinkSP.getValue(1), dl, SP, SaveSP); + + // Store the old link SP. + return DAG.getStore(Chain, dl, LoadLinkSP, StackPtr, NULL, 0); +} + + + +SDValue +PPCTargetLowering::getReturnAddrFrameIndex(SelectionDAG & DAG) const { + MachineFunction &MF = DAG.getMachineFunction(); + bool isPPC64 = PPCSubTarget.isPPC64(); + bool isDarwinABI = PPCSubTarget.isDarwinABI(); + EVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy(); + + // Get current frame pointer save index. The users of this index will be + // primarily DYNALLOC instructions. + PPCFunctionInfo *FI = MF.getInfo(); + int RASI = FI->getReturnAddrSaveIndex(); + + // If the frame pointer save index hasn't been defined yet. + if (!RASI) { + // Find out what the fix offset of the frame pointer save area. + int LROffset = PPCFrameInfo::getReturnSaveOffset(isPPC64, isDarwinABI); + // Allocate the frame index for frame pointer save area. + RASI = MF.getFrameInfo()->CreateFixedObject(isPPC64? 8 : 4, LROffset, + true, false); + // Save the result. + FI->setReturnAddrSaveIndex(RASI); + } + return DAG.getFrameIndex(RASI, PtrVT); +} + +SDValue +PPCTargetLowering::getFramePointerFrameIndex(SelectionDAG & DAG) const { + MachineFunction &MF = DAG.getMachineFunction(); + bool isPPC64 = PPCSubTarget.isPPC64(); + bool isDarwinABI = PPCSubTarget.isDarwinABI(); + EVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy(); + + // Get current frame pointer save index. The users of this index will be + // primarily DYNALLOC instructions. + PPCFunctionInfo *FI = MF.getInfo(); + int FPSI = FI->getFramePointerSaveIndex(); + + // If the frame pointer save index hasn't been defined yet. + if (!FPSI) { + // Find out what the fix offset of the frame pointer save area. + int FPOffset = PPCFrameInfo::getFramePointerSaveOffset(isPPC64, + isDarwinABI); + + // Allocate the frame index for frame pointer save area. + FPSI = MF.getFrameInfo()->CreateFixedObject(isPPC64? 8 : 4, FPOffset, + true, false); + // Save the result. + FI->setFramePointerSaveIndex(FPSI); + } + return DAG.getFrameIndex(FPSI, PtrVT); +} + +SDValue PPCTargetLowering::LowerDYNAMIC_STACKALLOC(SDValue Op, + SelectionDAG &DAG, + const PPCSubtarget &Subtarget) { + // Get the inputs. + SDValue Chain = Op.getOperand(0); + SDValue Size = Op.getOperand(1); + DebugLoc dl = Op.getDebugLoc(); + + // Get the corect type for pointers. + EVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy(); + // Negate the size. + SDValue NegSize = DAG.getNode(ISD::SUB, dl, PtrVT, + DAG.getConstant(0, PtrVT), Size); + // Construct a node for the frame pointer save index. + SDValue FPSIdx = getFramePointerFrameIndex(DAG); + // Build a DYNALLOC node. + SDValue Ops[3] = { Chain, NegSize, FPSIdx }; + SDVTList VTs = DAG.getVTList(PtrVT, MVT::Other); + return DAG.getNode(PPCISD::DYNALLOC, dl, VTs, Ops, 3); +} + +/// LowerSELECT_CC - Lower floating point select_cc's into fsel instruction when +/// possible. +SDValue PPCTargetLowering::LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) { + // Not FP? Not a fsel. + if (!Op.getOperand(0).getValueType().isFloatingPoint() || + !Op.getOperand(2).getValueType().isFloatingPoint()) + return Op; + + ISD::CondCode CC = cast(Op.getOperand(4))->get(); + + // Cannot handle SETEQ/SETNE. + if (CC == ISD::SETEQ || CC == ISD::SETNE) return Op; + + EVT ResVT = Op.getValueType(); + EVT CmpVT = Op.getOperand(0).getValueType(); + SDValue LHS = Op.getOperand(0), RHS = Op.getOperand(1); + SDValue TV = Op.getOperand(2), FV = Op.getOperand(3); + DebugLoc dl = Op.getDebugLoc(); + + // If the RHS of the comparison is a 0.0, we don't need to do the + // subtraction at all. + if (isFloatingPointZero(RHS)) + switch (CC) { + default: break; // SETUO etc aren't handled by fsel. + case ISD::SETULT: + case ISD::SETLT: + std::swap(TV, FV); // fsel is natively setge, swap operands for setlt + case ISD::SETOGE: + case ISD::SETGE: + if (LHS.getValueType() == MVT::f32) // Comparison is always 64-bits + LHS = DAG.getNode(ISD::FP_EXTEND, dl, MVT::f64, LHS); + return DAG.getNode(PPCISD::FSEL, dl, ResVT, LHS, TV, FV); + case ISD::SETUGT: + case ISD::SETGT: + std::swap(TV, FV); // fsel is natively setge, swap operands for setlt + case ISD::SETOLE: + case ISD::SETLE: + if (LHS.getValueType() == MVT::f32) // Comparison is always 64-bits + LHS = DAG.getNode(ISD::FP_EXTEND, dl, MVT::f64, LHS); + return DAG.getNode(PPCISD::FSEL, dl, ResVT, + DAG.getNode(ISD::FNEG, dl, MVT::f64, LHS), TV, FV); + } + + SDValue Cmp; + switch (CC) { + default: break; // SETUO etc aren't handled by fsel. + case ISD::SETULT: + case ISD::SETLT: + Cmp = DAG.getNode(ISD::FSUB, dl, CmpVT, LHS, RHS); + if (Cmp.getValueType() == MVT::f32) // Comparison is always 64-bits + Cmp = DAG.getNode(ISD::FP_EXTEND, dl, MVT::f64, Cmp); + return DAG.getNode(PPCISD::FSEL, dl, ResVT, Cmp, FV, TV); + case ISD::SETOGE: + case ISD::SETGE: + Cmp = DAG.getNode(ISD::FSUB, dl, CmpVT, LHS, RHS); + if (Cmp.getValueType() == MVT::f32) // Comparison is always 64-bits + Cmp = DAG.getNode(ISD::FP_EXTEND, dl, MVT::f64, Cmp); + return DAG.getNode(PPCISD::FSEL, dl, ResVT, Cmp, TV, FV); + case ISD::SETUGT: + case ISD::SETGT: + Cmp = DAG.getNode(ISD::FSUB, dl, CmpVT, RHS, LHS); + if (Cmp.getValueType() == MVT::f32) // Comparison is always 64-bits + Cmp = DAG.getNode(ISD::FP_EXTEND, dl, MVT::f64, Cmp); + return DAG.getNode(PPCISD::FSEL, dl, ResVT, Cmp, FV, TV); + case ISD::SETOLE: + case ISD::SETLE: + Cmp = DAG.getNode(ISD::FSUB, dl, CmpVT, RHS, LHS); + if (Cmp.getValueType() == MVT::f32) // Comparison is always 64-bits + Cmp = DAG.getNode(ISD::FP_EXTEND, dl, MVT::f64, Cmp); + return DAG.getNode(PPCISD::FSEL, dl, ResVT, Cmp, TV, FV); + } + return Op; +} + +// FIXME: Split this code up when LegalizeDAGTypes lands. +SDValue PPCTargetLowering::LowerFP_TO_INT(SDValue Op, SelectionDAG &DAG, + DebugLoc dl) { + assert(Op.getOperand(0).getValueType().isFloatingPoint()); + SDValue Src = Op.getOperand(0); + if (Src.getValueType() == MVT::f32) + Src = DAG.getNode(ISD::FP_EXTEND, dl, MVT::f64, Src); + + SDValue Tmp; + switch (Op.getValueType().getSimpleVT().SimpleTy) { + default: llvm_unreachable("Unhandled FP_TO_INT type in custom expander!"); + case MVT::i32: + Tmp = DAG.getNode(Op.getOpcode()==ISD::FP_TO_SINT ? PPCISD::FCTIWZ : + PPCISD::FCTIDZ, + dl, MVT::f64, Src); + break; + case MVT::i64: + Tmp = DAG.getNode(PPCISD::FCTIDZ, dl, MVT::f64, Src); + break; + } + + // Convert the FP value to an int value through memory. + SDValue FIPtr = DAG.CreateStackTemporary(MVT::f64); + + // Emit a store to the stack slot. + SDValue Chain = DAG.getStore(DAG.getEntryNode(), dl, Tmp, FIPtr, NULL, 0); + + // Result is a load from the stack slot. If loading 4 bytes, make sure to + // add in a bias. + if (Op.getValueType() == MVT::i32) + FIPtr = DAG.getNode(ISD::ADD, dl, FIPtr.getValueType(), FIPtr, + DAG.getConstant(4, FIPtr.getValueType())); + return DAG.getLoad(Op.getValueType(), dl, Chain, FIPtr, NULL, 0); +} + +SDValue PPCTargetLowering::LowerSINT_TO_FP(SDValue Op, SelectionDAG &DAG) { + DebugLoc dl = Op.getDebugLoc(); + // Don't handle ppc_fp128 here; let it be lowered to a libcall. + if (Op.getValueType() != MVT::f32 && Op.getValueType() != MVT::f64) + return SDValue(); + + if (Op.getOperand(0).getValueType() == MVT::i64) { + SDValue Bits = DAG.getNode(ISD::BIT_CONVERT, dl, + MVT::f64, Op.getOperand(0)); + SDValue FP = DAG.getNode(PPCISD::FCFID, dl, MVT::f64, Bits); + if (Op.getValueType() == MVT::f32) + FP = DAG.getNode(ISD::FP_ROUND, dl, + MVT::f32, FP, DAG.getIntPtrConstant(0)); + return FP; + } + + assert(Op.getOperand(0).getValueType() == MVT::i32 && + "Unhandled SINT_TO_FP type in custom expander!"); + // Since we only generate this in 64-bit mode, we can take advantage of + // 64-bit registers. In particular, sign extend the input value into the + // 64-bit register with extsw, store the WHOLE 64-bit value into the stack + // then lfd it and fcfid it. + MachineFunction &MF = DAG.getMachineFunction(); + MachineFrameInfo *FrameInfo = MF.getFrameInfo(); + int FrameIdx = FrameInfo->CreateStackObject(8, 8, false); + EVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy(); + SDValue FIdx = DAG.getFrameIndex(FrameIdx, PtrVT); + + SDValue Ext64 = DAG.getNode(PPCISD::EXTSW_32, dl, MVT::i32, + Op.getOperand(0)); + + // STD the extended value into the stack slot. + MachineMemOperand *MMO = + MF.getMachineMemOperand(PseudoSourceValue::getFixedStack(FrameIdx), + MachineMemOperand::MOStore, 0, 8, 8); + SDValue Ops[] = { DAG.getEntryNode(), Ext64, FIdx }; + SDValue Store = + DAG.getMemIntrinsicNode(PPCISD::STD_32, dl, DAG.getVTList(MVT::Other), + Ops, 4, MVT::i64, MMO); + // Load the value as a double. + SDValue Ld = DAG.getLoad(MVT::f64, dl, Store, FIdx, NULL, 0); + + // FCFID it and return it. + SDValue FP = DAG.getNode(PPCISD::FCFID, dl, MVT::f64, Ld); + if (Op.getValueType() == MVT::f32) + FP = DAG.getNode(ISD::FP_ROUND, dl, MVT::f32, FP, DAG.getIntPtrConstant(0)); + return FP; +} + +SDValue PPCTargetLowering::LowerFLT_ROUNDS_(SDValue Op, SelectionDAG &DAG) { + DebugLoc dl = Op.getDebugLoc(); + /* + The rounding mode is in bits 30:31 of FPSR, and has the following + settings: + 00 Round to nearest + 01 Round to 0 + 10 Round to +inf + 11 Round to -inf + + FLT_ROUNDS, on the other hand, expects the following: + -1 Undefined + 0 Round to 0 + 1 Round to nearest + 2 Round to +inf + 3 Round to -inf + + To perform the conversion, we do: + ((FPSCR & 0x3) ^ ((~FPSCR & 0x3) >> 1)) + */ + + MachineFunction &MF = DAG.getMachineFunction(); + EVT VT = Op.getValueType(); + EVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy(); + std::vector NodeTys; + SDValue MFFSreg, InFlag; + + // Save FP Control Word to register + NodeTys.push_back(MVT::f64); // return register + NodeTys.push_back(MVT::Flag); // unused in this context + SDValue Chain = DAG.getNode(PPCISD::MFFS, dl, NodeTys, &InFlag, 0); + + // Save FP register to stack slot + int SSFI = MF.getFrameInfo()->CreateStackObject(8, 8, false); + SDValue StackSlot = DAG.getFrameIndex(SSFI, PtrVT); + SDValue Store = DAG.getStore(DAG.getEntryNode(), dl, Chain, + StackSlot, NULL, 0); + + // Load FP Control Word from low 32 bits of stack slot. + SDValue Four = DAG.getConstant(4, PtrVT); + SDValue Addr = DAG.getNode(ISD::ADD, dl, PtrVT, StackSlot, Four); + SDValue CWD = DAG.getLoad(MVT::i32, dl, Store, Addr, NULL, 0); + + // Transform as necessary + SDValue CWD1 = + DAG.getNode(ISD::AND, dl, MVT::i32, + CWD, DAG.getConstant(3, MVT::i32)); + SDValue CWD2 = + DAG.getNode(ISD::SRL, dl, MVT::i32, + DAG.getNode(ISD::AND, dl, MVT::i32, + DAG.getNode(ISD::XOR, dl, MVT::i32, + CWD, DAG.getConstant(3, MVT::i32)), + DAG.getConstant(3, MVT::i32)), + DAG.getConstant(1, MVT::i32)); + + SDValue RetVal = + DAG.getNode(ISD::XOR, dl, MVT::i32, CWD1, CWD2); + + return DAG.getNode((VT.getSizeInBits() < 16 ? + ISD::TRUNCATE : ISD::ZERO_EXTEND), dl, VT, RetVal); +} + +SDValue PPCTargetLowering::LowerSHL_PARTS(SDValue Op, SelectionDAG &DAG) { + EVT VT = Op.getValueType(); + unsigned BitWidth = VT.getSizeInBits(); + DebugLoc dl = Op.getDebugLoc(); + assert(Op.getNumOperands() == 3 && + VT == Op.getOperand(1).getValueType() && + "Unexpected SHL!"); + + // Expand into a bunch of logical ops. Note that these ops + // depend on the PPC behavior for oversized shift amounts. + SDValue Lo = Op.getOperand(0); + SDValue Hi = Op.getOperand(1); + SDValue Amt = Op.getOperand(2); + EVT AmtVT = Amt.getValueType(); + + SDValue Tmp1 = DAG.getNode(ISD::SUB, dl, AmtVT, + DAG.getConstant(BitWidth, AmtVT), Amt); + SDValue Tmp2 = DAG.getNode(PPCISD::SHL, dl, VT, Hi, Amt); + SDValue Tmp3 = DAG.getNode(PPCISD::SRL, dl, VT, Lo, Tmp1); + SDValue Tmp4 = DAG.getNode(ISD::OR , dl, VT, Tmp2, Tmp3); + SDValue Tmp5 = DAG.getNode(ISD::ADD, dl, AmtVT, Amt, + DAG.getConstant(-BitWidth, AmtVT)); + SDValue Tmp6 = DAG.getNode(PPCISD::SHL, dl, VT, Lo, Tmp5); + SDValue OutHi = DAG.getNode(ISD::OR, dl, VT, Tmp4, Tmp6); + SDValue OutLo = DAG.getNode(PPCISD::SHL, dl, VT, Lo, Amt); + SDValue OutOps[] = { OutLo, OutHi }; + return DAG.getMergeValues(OutOps, 2, dl); +} + +SDValue PPCTargetLowering::LowerSRL_PARTS(SDValue Op, SelectionDAG &DAG) { + EVT VT = Op.getValueType(); + DebugLoc dl = Op.getDebugLoc(); + unsigned BitWidth = VT.getSizeInBits(); + assert(Op.getNumOperands() == 3 && + VT == Op.getOperand(1).getValueType() && + "Unexpected SRL!"); + + // Expand into a bunch of logical ops. Note that these ops + // depend on the PPC behavior for oversized shift amounts. + SDValue Lo = Op.getOperand(0); + SDValue Hi = Op.getOperand(1); + SDValue Amt = Op.getOperand(2); + EVT AmtVT = Amt.getValueType(); + + SDValue Tmp1 = DAG.getNode(ISD::SUB, dl, AmtVT, + DAG.getConstant(BitWidth, AmtVT), Amt); + SDValue Tmp2 = DAG.getNode(PPCISD::SRL, dl, VT, Lo, Amt); + SDValue Tmp3 = DAG.getNode(PPCISD::SHL, dl, VT, Hi, Tmp1); + SDValue Tmp4 = DAG.getNode(ISD::OR, dl, VT, Tmp2, Tmp3); + SDValue Tmp5 = DAG.getNode(ISD::ADD, dl, AmtVT, Amt, + DAG.getConstant(-BitWidth, AmtVT)); + SDValue Tmp6 = DAG.getNode(PPCISD::SRL, dl, VT, Hi, Tmp5); + SDValue OutLo = DAG.getNode(ISD::OR, dl, VT, Tmp4, Tmp6); + SDValue OutHi = DAG.getNode(PPCISD::SRL, dl, VT, Hi, Amt); + SDValue OutOps[] = { OutLo, OutHi }; + return DAG.getMergeValues(OutOps, 2, dl); +} + +SDValue PPCTargetLowering::LowerSRA_PARTS(SDValue Op, SelectionDAG &DAG) { + DebugLoc dl = Op.getDebugLoc(); + EVT VT = Op.getValueType(); + unsigned BitWidth = VT.getSizeInBits(); + assert(Op.getNumOperands() == 3 && + VT == Op.getOperand(1).getValueType() && + "Unexpected SRA!"); + + // Expand into a bunch of logical ops, followed by a select_cc. + SDValue Lo = Op.getOperand(0); + SDValue Hi = Op.getOperand(1); + SDValue Amt = Op.getOperand(2); + EVT AmtVT = Amt.getValueType(); + + SDValue Tmp1 = DAG.getNode(ISD::SUB, dl, AmtVT, + DAG.getConstant(BitWidth, AmtVT), Amt); + SDValue Tmp2 = DAG.getNode(PPCISD::SRL, dl, VT, Lo, Amt); + SDValue Tmp3 = DAG.getNode(PPCISD::SHL, dl, VT, Hi, Tmp1); + SDValue Tmp4 = DAG.getNode(ISD::OR, dl, VT, Tmp2, Tmp3); + SDValue Tmp5 = DAG.getNode(ISD::ADD, dl, AmtVT, Amt, + DAG.getConstant(-BitWidth, AmtVT)); + SDValue Tmp6 = DAG.getNode(PPCISD::SRA, dl, VT, Hi, Tmp5); + SDValue OutHi = DAG.getNode(PPCISD::SRA, dl, VT, Hi, Amt); + SDValue OutLo = DAG.getSelectCC(dl, Tmp5, DAG.getConstant(0, AmtVT), + Tmp4, Tmp6, ISD::SETLE); + SDValue OutOps[] = { OutLo, OutHi }; + return DAG.getMergeValues(OutOps, 2, dl); +} + +//===----------------------------------------------------------------------===// +// Vector related lowering. +// + +/// BuildSplatI - Build a canonical splati of Val with an element size of +/// SplatSize. Cast the result to VT. +static SDValue BuildSplatI(int Val, unsigned SplatSize, EVT VT, + SelectionDAG &DAG, DebugLoc dl) { + assert(Val >= -16 && Val <= 15 && "vsplti is out of range!"); + + static const EVT VTys[] = { // canonical VT to use for each size. + MVT::v16i8, MVT::v8i16, MVT::Other, MVT::v4i32 + }; + + EVT ReqVT = VT != MVT::Other ? VT : VTys[SplatSize-1]; + + // Force vspltis[hw] -1 to vspltisb -1 to canonicalize. + if (Val == -1) + SplatSize = 1; + + EVT CanonicalVT = VTys[SplatSize-1]; + + // Build a canonical splat for this value. + SDValue Elt = DAG.getConstant(Val, MVT::i32); + SmallVector Ops; + Ops.assign(CanonicalVT.getVectorNumElements(), Elt); + SDValue Res = DAG.getNode(ISD::BUILD_VECTOR, dl, CanonicalVT, + &Ops[0], Ops.size()); + return DAG.getNode(ISD::BIT_CONVERT, dl, ReqVT, Res); +} + +/// BuildIntrinsicOp - Return a binary operator intrinsic node with the +/// specified intrinsic ID. +static SDValue BuildIntrinsicOp(unsigned IID, SDValue LHS, SDValue RHS, + SelectionDAG &DAG, DebugLoc dl, + EVT DestVT = MVT::Other) { + if (DestVT == MVT::Other) DestVT = LHS.getValueType(); + return DAG.getNode(ISD::INTRINSIC_WO_CHAIN, dl, DestVT, + DAG.getConstant(IID, MVT::i32), LHS, RHS); +} + +/// BuildIntrinsicOp - Return a ternary operator intrinsic node with the +/// specified intrinsic ID. +static SDValue BuildIntrinsicOp(unsigned IID, SDValue Op0, SDValue Op1, + SDValue Op2, SelectionDAG &DAG, + DebugLoc dl, EVT DestVT = MVT::Other) { + if (DestVT == MVT::Other) DestVT = Op0.getValueType(); + return DAG.getNode(ISD::INTRINSIC_WO_CHAIN, dl, DestVT, + DAG.getConstant(IID, MVT::i32), Op0, Op1, Op2); +} + + +/// BuildVSLDOI - Return a VECTOR_SHUFFLE that is a vsldoi of the specified +/// amount. The result has the specified value type. +static SDValue BuildVSLDOI(SDValue LHS, SDValue RHS, unsigned Amt, + EVT VT, SelectionDAG &DAG, DebugLoc dl) { + // Force LHS/RHS to be the right type. + LHS = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::v16i8, LHS); + RHS = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::v16i8, RHS); + + int Ops[16]; + for (unsigned i = 0; i != 16; ++i) + Ops[i] = i + Amt; + SDValue T = DAG.getVectorShuffle(MVT::v16i8, dl, LHS, RHS, Ops); + return DAG.getNode(ISD::BIT_CONVERT, dl, VT, T); +} + +// If this is a case we can't handle, return null and let the default +// expansion code take care of it. If we CAN select this case, and if it +// selects to a single instruction, return Op. Otherwise, if we can codegen +// this case more efficiently than a constant pool load, lower it to the +// sequence of ops that should be used. +SDValue PPCTargetLowering::LowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG) { + DebugLoc dl = Op.getDebugLoc(); + BuildVectorSDNode *BVN = dyn_cast(Op.getNode()); + assert(BVN != 0 && "Expected a BuildVectorSDNode in LowerBUILD_VECTOR"); + + // Check if this is a splat of a constant value. + APInt APSplatBits, APSplatUndef; + unsigned SplatBitSize; + bool HasAnyUndefs; + if (! BVN->isConstantSplat(APSplatBits, APSplatUndef, SplatBitSize, + HasAnyUndefs, 0, true) || SplatBitSize > 32) + return SDValue(); + + unsigned SplatBits = APSplatBits.getZExtValue(); + unsigned SplatUndef = APSplatUndef.getZExtValue(); + unsigned SplatSize = SplatBitSize / 8; + + // First, handle single instruction cases. + + // All zeros? + if (SplatBits == 0) { + // Canonicalize all zero vectors to be v4i32. + if (Op.getValueType() != MVT::v4i32 || HasAnyUndefs) { + SDValue Z = DAG.getConstant(0, MVT::i32); + Z = DAG.getNode(ISD::BUILD_VECTOR, dl, MVT::v4i32, Z, Z, Z, Z); + Op = DAG.getNode(ISD::BIT_CONVERT, dl, Op.getValueType(), Z); + } + return Op; + } + + // If the sign extended value is in the range [-16,15], use VSPLTI[bhw]. + int32_t SextVal= (int32_t(SplatBits << (32-SplatBitSize)) >> + (32-SplatBitSize)); + if (SextVal >= -16 && SextVal <= 15) + return BuildSplatI(SextVal, SplatSize, Op.getValueType(), DAG, dl); + + + // Two instruction sequences. + + // If this value is in the range [-32,30] and is even, use: + // tmp = VSPLTI[bhw], result = add tmp, tmp + if (SextVal >= -32 && SextVal <= 30 && (SextVal & 1) == 0) { + SDValue Res = BuildSplatI(SextVal >> 1, SplatSize, MVT::Other, DAG, dl); + Res = DAG.getNode(ISD::ADD, dl, Res.getValueType(), Res, Res); + return DAG.getNode(ISD::BIT_CONVERT, dl, Op.getValueType(), Res); + } + + // If this is 0x8000_0000 x 4, turn into vspltisw + vslw. If it is + // 0x7FFF_FFFF x 4, turn it into not(0x8000_0000). This is important + // for fneg/fabs. + if (SplatSize == 4 && SplatBits == (0x7FFFFFFF&~SplatUndef)) { + // Make -1 and vspltisw -1: + SDValue OnesV = BuildSplatI(-1, 4, MVT::v4i32, DAG, dl); + + // Make the VSLW intrinsic, computing 0x8000_0000. + SDValue Res = BuildIntrinsicOp(Intrinsic::ppc_altivec_vslw, OnesV, + OnesV, DAG, dl); + + // xor by OnesV to invert it. + Res = DAG.getNode(ISD::XOR, dl, MVT::v4i32, Res, OnesV); + return DAG.getNode(ISD::BIT_CONVERT, dl, Op.getValueType(), Res); + } + + // Check to see if this is a wide variety of vsplti*, binop self cases. + static const signed char SplatCsts[] = { + -1, 1, -2, 2, -3, 3, -4, 4, -5, 5, -6, 6, -7, 7, + -8, 8, -9, 9, -10, 10, -11, 11, -12, 12, -13, 13, 14, -14, 15, -15, -16 + }; + + for (unsigned idx = 0; idx < array_lengthof(SplatCsts); ++idx) { + // Indirect through the SplatCsts array so that we favor 'vsplti -1' for + // cases which are ambiguous (e.g. formation of 0x8000_0000). 'vsplti -1' + int i = SplatCsts[idx]; + + // Figure out what shift amount will be used by altivec if shifted by i in + // this splat size. + unsigned TypeShiftAmt = i & (SplatBitSize-1); + + // vsplti + shl self. + if (SextVal == (i << (int)TypeShiftAmt)) { + SDValue Res = BuildSplatI(i, SplatSize, MVT::Other, DAG, dl); + static const unsigned IIDs[] = { // Intrinsic to use for each size. + Intrinsic::ppc_altivec_vslb, Intrinsic::ppc_altivec_vslh, 0, + Intrinsic::ppc_altivec_vslw + }; + Res = BuildIntrinsicOp(IIDs[SplatSize-1], Res, Res, DAG, dl); + return DAG.getNode(ISD::BIT_CONVERT, dl, Op.getValueType(), Res); + } + + // vsplti + srl self. + if (SextVal == (int)((unsigned)i >> TypeShiftAmt)) { + SDValue Res = BuildSplatI(i, SplatSize, MVT::Other, DAG, dl); + static const unsigned IIDs[] = { // Intrinsic to use for each size. + Intrinsic::ppc_altivec_vsrb, Intrinsic::ppc_altivec_vsrh, 0, + Intrinsic::ppc_altivec_vsrw + }; + Res = BuildIntrinsicOp(IIDs[SplatSize-1], Res, Res, DAG, dl); + return DAG.getNode(ISD::BIT_CONVERT, dl, Op.getValueType(), Res); + } + + // vsplti + sra self. + if (SextVal == (int)((unsigned)i >> TypeShiftAmt)) { + SDValue Res = BuildSplatI(i, SplatSize, MVT::Other, DAG, dl); + static const unsigned IIDs[] = { // Intrinsic to use for each size. + Intrinsic::ppc_altivec_vsrab, Intrinsic::ppc_altivec_vsrah, 0, + Intrinsic::ppc_altivec_vsraw + }; + Res = BuildIntrinsicOp(IIDs[SplatSize-1], Res, Res, DAG, dl); + return DAG.getNode(ISD::BIT_CONVERT, dl, Op.getValueType(), Res); + } + + // vsplti + rol self. + if (SextVal == (int)(((unsigned)i << TypeShiftAmt) | + ((unsigned)i >> (SplatBitSize-TypeShiftAmt)))) { + SDValue Res = BuildSplatI(i, SplatSize, MVT::Other, DAG, dl); + static const unsigned IIDs[] = { // Intrinsic to use for each size. + Intrinsic::ppc_altivec_vrlb, Intrinsic::ppc_altivec_vrlh, 0, + Intrinsic::ppc_altivec_vrlw + }; + Res = BuildIntrinsicOp(IIDs[SplatSize-1], Res, Res, DAG, dl); + return DAG.getNode(ISD::BIT_CONVERT, dl, Op.getValueType(), Res); + } + + // t = vsplti c, result = vsldoi t, t, 1 + if (SextVal == ((i << 8) | (i >> (TypeShiftAmt-8)))) { + SDValue T = BuildSplatI(i, SplatSize, MVT::v16i8, DAG, dl); + return BuildVSLDOI(T, T, 1, Op.getValueType(), DAG, dl); + } + // t = vsplti c, result = vsldoi t, t, 2 + if (SextVal == ((i << 16) | (i >> (TypeShiftAmt-16)))) { + SDValue T = BuildSplatI(i, SplatSize, MVT::v16i8, DAG, dl); + return BuildVSLDOI(T, T, 2, Op.getValueType(), DAG, dl); + } + // t = vsplti c, result = vsldoi t, t, 3 + if (SextVal == ((i << 24) | (i >> (TypeShiftAmt-24)))) { + SDValue T = BuildSplatI(i, SplatSize, MVT::v16i8, DAG, dl); + return BuildVSLDOI(T, T, 3, Op.getValueType(), DAG, dl); + } + } + + // Three instruction sequences. + + // Odd, in range [17,31]: (vsplti C)-(vsplti -16). + if (SextVal >= 0 && SextVal <= 31) { + SDValue LHS = BuildSplatI(SextVal-16, SplatSize, MVT::Other, DAG, dl); + SDValue RHS = BuildSplatI(-16, SplatSize, MVT::Other, DAG, dl); + LHS = DAG.getNode(ISD::SUB, dl, LHS.getValueType(), LHS, RHS); + return DAG.getNode(ISD::BIT_CONVERT, dl, Op.getValueType(), LHS); + } + // Odd, in range [-31,-17]: (vsplti C)+(vsplti -16). + if (SextVal >= -31 && SextVal <= 0) { + SDValue LHS = BuildSplatI(SextVal+16, SplatSize, MVT::Other, DAG, dl); + SDValue RHS = BuildSplatI(-16, SplatSize, MVT::Other, DAG, dl); + LHS = DAG.getNode(ISD::ADD, dl, LHS.getValueType(), LHS, RHS); + return DAG.getNode(ISD::BIT_CONVERT, dl, Op.getValueType(), LHS); + } + + return SDValue(); +} + +/// GeneratePerfectShuffle - Given an entry in the perfect-shuffle table, emit +/// the specified operations to build the shuffle. +static SDValue GeneratePerfectShuffle(unsigned PFEntry, SDValue LHS, + SDValue RHS, SelectionDAG &DAG, + DebugLoc dl) { + unsigned OpNum = (PFEntry >> 26) & 0x0F; + unsigned LHSID = (PFEntry >> 13) & ((1 << 13)-1); + unsigned RHSID = (PFEntry >> 0) & ((1 << 13)-1); + + enum { + OP_COPY = 0, // Copy, used for things like to say it is <0,1,2,3> + OP_VMRGHW, + OP_VMRGLW, + OP_VSPLTISW0, + OP_VSPLTISW1, + OP_VSPLTISW2, + OP_VSPLTISW3, + OP_VSLDOI4, + OP_VSLDOI8, + OP_VSLDOI12 + }; + + if (OpNum == OP_COPY) { + if (LHSID == (1*9+2)*9+3) return LHS; + assert(LHSID == ((4*9+5)*9+6)*9+7 && "Illegal OP_COPY!"); + return RHS; + } + + SDValue OpLHS, OpRHS; + OpLHS = GeneratePerfectShuffle(PerfectShuffleTable[LHSID], LHS, RHS, DAG, dl); + OpRHS = GeneratePerfectShuffle(PerfectShuffleTable[RHSID], LHS, RHS, DAG, dl); + + int ShufIdxs[16]; + switch (OpNum) { + default: llvm_unreachable("Unknown i32 permute!"); + case OP_VMRGHW: + ShufIdxs[ 0] = 0; ShufIdxs[ 1] = 1; ShufIdxs[ 2] = 2; ShufIdxs[ 3] = 3; + ShufIdxs[ 4] = 16; ShufIdxs[ 5] = 17; ShufIdxs[ 6] = 18; ShufIdxs[ 7] = 19; + ShufIdxs[ 8] = 4; ShufIdxs[ 9] = 5; ShufIdxs[10] = 6; ShufIdxs[11] = 7; + ShufIdxs[12] = 20; ShufIdxs[13] = 21; ShufIdxs[14] = 22; ShufIdxs[15] = 23; + break; + case OP_VMRGLW: + ShufIdxs[ 0] = 8; ShufIdxs[ 1] = 9; ShufIdxs[ 2] = 10; ShufIdxs[ 3] = 11; + ShufIdxs[ 4] = 24; ShufIdxs[ 5] = 25; ShufIdxs[ 6] = 26; ShufIdxs[ 7] = 27; + ShufIdxs[ 8] = 12; ShufIdxs[ 9] = 13; ShufIdxs[10] = 14; ShufIdxs[11] = 15; + ShufIdxs[12] = 28; ShufIdxs[13] = 29; ShufIdxs[14] = 30; ShufIdxs[15] = 31; + break; + case OP_VSPLTISW0: + for (unsigned i = 0; i != 16; ++i) + ShufIdxs[i] = (i&3)+0; + break; + case OP_VSPLTISW1: + for (unsigned i = 0; i != 16; ++i) + ShufIdxs[i] = (i&3)+4; + break; + case OP_VSPLTISW2: + for (unsigned i = 0; i != 16; ++i) + ShufIdxs[i] = (i&3)+8; + break; + case OP_VSPLTISW3: + for (unsigned i = 0; i != 16; ++i) + ShufIdxs[i] = (i&3)+12; + break; + case OP_VSLDOI4: + return BuildVSLDOI(OpLHS, OpRHS, 4, OpLHS.getValueType(), DAG, dl); + case OP_VSLDOI8: + return BuildVSLDOI(OpLHS, OpRHS, 8, OpLHS.getValueType(), DAG, dl); + case OP_VSLDOI12: + return BuildVSLDOI(OpLHS, OpRHS, 12, OpLHS.getValueType(), DAG, dl); + } + EVT VT = OpLHS.getValueType(); + OpLHS = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::v16i8, OpLHS); + OpRHS = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::v16i8, OpRHS); + SDValue T = DAG.getVectorShuffle(MVT::v16i8, dl, OpLHS, OpRHS, ShufIdxs); + return DAG.getNode(ISD::BIT_CONVERT, dl, VT, T); +} + +/// LowerVECTOR_SHUFFLE - Return the code we lower for VECTOR_SHUFFLE. If this +/// is a shuffle we can handle in a single instruction, return it. Otherwise, +/// return the code it can be lowered into. Worst case, it can always be +/// lowered into a vperm. +SDValue PPCTargetLowering::LowerVECTOR_SHUFFLE(SDValue Op, + SelectionDAG &DAG) { + DebugLoc dl = Op.getDebugLoc(); + SDValue V1 = Op.getOperand(0); + SDValue V2 = Op.getOperand(1); + ShuffleVectorSDNode *SVOp = cast(Op); + EVT VT = Op.getValueType(); + + // Cases that are handled by instructions that take permute immediates + // (such as vsplt*) should be left as VECTOR_SHUFFLE nodes so they can be + // selected by the instruction selector. + if (V2.getOpcode() == ISD::UNDEF) { + if (PPC::isSplatShuffleMask(SVOp, 1) || + PPC::isSplatShuffleMask(SVOp, 2) || + PPC::isSplatShuffleMask(SVOp, 4) || + PPC::isVPKUWUMShuffleMask(SVOp, true) || + PPC::isVPKUHUMShuffleMask(SVOp, true) || + PPC::isVSLDOIShuffleMask(SVOp, true) != -1 || + PPC::isVMRGLShuffleMask(SVOp, 1, true) || + PPC::isVMRGLShuffleMask(SVOp, 2, true) || + PPC::isVMRGLShuffleMask(SVOp, 4, true) || + PPC::isVMRGHShuffleMask(SVOp, 1, true) || + PPC::isVMRGHShuffleMask(SVOp, 2, true) || + PPC::isVMRGHShuffleMask(SVOp, 4, true)) { + return Op; + } + } + + // Altivec has a variety of "shuffle immediates" that take two vector inputs + // and produce a fixed permutation. If any of these match, do not lower to + // VPERM. + if (PPC::isVPKUWUMShuffleMask(SVOp, false) || + PPC::isVPKUHUMShuffleMask(SVOp, false) || + PPC::isVSLDOIShuffleMask(SVOp, false) != -1 || + PPC::isVMRGLShuffleMask(SVOp, 1, false) || + PPC::isVMRGLShuffleMask(SVOp, 2, false) || + PPC::isVMRGLShuffleMask(SVOp, 4, false) || + PPC::isVMRGHShuffleMask(SVOp, 1, false) || + PPC::isVMRGHShuffleMask(SVOp, 2, false) || + PPC::isVMRGHShuffleMask(SVOp, 4, false)) + return Op; + + // Check to see if this is a shuffle of 4-byte values. If so, we can use our + // perfect shuffle table to emit an optimal matching sequence. + SmallVector PermMask; + SVOp->getMask(PermMask); + + unsigned PFIndexes[4]; + bool isFourElementShuffle = true; + for (unsigned i = 0; i != 4 && isFourElementShuffle; ++i) { // Element number + unsigned EltNo = 8; // Start out undef. + for (unsigned j = 0; j != 4; ++j) { // Intra-element byte. + if (PermMask[i*4+j] < 0) + continue; // Undef, ignore it. + + unsigned ByteSource = PermMask[i*4+j]; + if ((ByteSource & 3) != j) { + isFourElementShuffle = false; + break; + } + + if (EltNo == 8) { + EltNo = ByteSource/4; + } else if (EltNo != ByteSource/4) { + isFourElementShuffle = false; + break; + } + } + PFIndexes[i] = EltNo; + } + + // If this shuffle can be expressed as a shuffle of 4-byte elements, use the + // perfect shuffle vector to determine if it is cost effective to do this as + // discrete instructions, or whether we should use a vperm. + if (isFourElementShuffle) { + // Compute the index in the perfect shuffle table. + unsigned PFTableIndex = + PFIndexes[0]*9*9*9+PFIndexes[1]*9*9+PFIndexes[2]*9+PFIndexes[3]; + + unsigned PFEntry = PerfectShuffleTable[PFTableIndex]; + unsigned Cost = (PFEntry >> 30); + + // Determining when to avoid vperm is tricky. Many things affect the cost + // of vperm, particularly how many times the perm mask needs to be computed. + // For example, if the perm mask can be hoisted out of a loop or is already + // used (perhaps because there are multiple permutes with the same shuffle + // mask?) the vperm has a cost of 1. OTOH, hoisting the permute mask out of + // the loop requires an extra register. + // + // As a compromise, we only emit discrete instructions if the shuffle can be + // generated in 3 or fewer operations. When we have loop information + // available, if this block is within a loop, we should avoid using vperm + // for 3-operation perms and use a constant pool load instead. + if (Cost < 3) + return GeneratePerfectShuffle(PFEntry, V1, V2, DAG, dl); + } + + // Lower this to a VPERM(V1, V2, V3) expression, where V3 is a constant + // vector that will get spilled to the constant pool. + if (V2.getOpcode() == ISD::UNDEF) V2 = V1; + + // The SHUFFLE_VECTOR mask is almost exactly what we want for vperm, except + // that it is in input element units, not in bytes. Convert now. + EVT EltVT = V1.getValueType().getVectorElementType(); + unsigned BytesPerElement = EltVT.getSizeInBits()/8; + + SmallVector ResultMask; + for (unsigned i = 0, e = VT.getVectorNumElements(); i != e; ++i) { + unsigned SrcElt = PermMask[i] < 0 ? 0 : PermMask[i]; + + for (unsigned j = 0; j != BytesPerElement; ++j) + ResultMask.push_back(DAG.getConstant(SrcElt*BytesPerElement+j, + MVT::i32)); + } + + SDValue VPermMask = DAG.getNode(ISD::BUILD_VECTOR, dl, MVT::v16i8, + &ResultMask[0], ResultMask.size()); + return DAG.getNode(PPCISD::VPERM, dl, V1.getValueType(), V1, V2, VPermMask); +} + +/// getAltivecCompareInfo - Given an intrinsic, return false if it is not an +/// altivec comparison. If it is, return true and fill in Opc/isDot with +/// information about the intrinsic. +static bool getAltivecCompareInfo(SDValue Intrin, int &CompareOpc, + bool &isDot) { + unsigned IntrinsicID = + cast(Intrin.getOperand(0))->getZExtValue(); + CompareOpc = -1; + isDot = false; + switch (IntrinsicID) { + default: return false; + // Comparison predicates. + case Intrinsic::ppc_altivec_vcmpbfp_p: CompareOpc = 966; isDot = 1; break; + case Intrinsic::ppc_altivec_vcmpeqfp_p: CompareOpc = 198; isDot = 1; break; + case Intrinsic::ppc_altivec_vcmpequb_p: CompareOpc = 6; isDot = 1; break; + case Intrinsic::ppc_altivec_vcmpequh_p: CompareOpc = 70; isDot = 1; break; + case Intrinsic::ppc_altivec_vcmpequw_p: CompareOpc = 134; isDot = 1; break; + case Intrinsic::ppc_altivec_vcmpgefp_p: CompareOpc = 454; isDot = 1; break; + case Intrinsic::ppc_altivec_vcmpgtfp_p: CompareOpc = 710; isDot = 1; break; + case Intrinsic::ppc_altivec_vcmpgtsb_p: CompareOpc = 774; isDot = 1; break; + case Intrinsic::ppc_altivec_vcmpgtsh_p: CompareOpc = 838; isDot = 1; break; + case Intrinsic::ppc_altivec_vcmpgtsw_p: CompareOpc = 902; isDot = 1; break; + case Intrinsic::ppc_altivec_vcmpgtub_p: CompareOpc = 518; isDot = 1; break; + case Intrinsic::ppc_altivec_vcmpgtuh_p: CompareOpc = 582; isDot = 1; break; + case Intrinsic::ppc_altivec_vcmpgtuw_p: CompareOpc = 646; isDot = 1; break; + + // Normal Comparisons. + case Intrinsic::ppc_altivec_vcmpbfp: CompareOpc = 966; isDot = 0; break; + case Intrinsic::ppc_altivec_vcmpeqfp: CompareOpc = 198; isDot = 0; break; + case Intrinsic::ppc_altivec_vcmpequb: CompareOpc = 6; isDot = 0; break; + case Intrinsic::ppc_altivec_vcmpequh: CompareOpc = 70; isDot = 0; break; + case Intrinsic::ppc_altivec_vcmpequw: CompareOpc = 134; isDot = 0; break; + case Intrinsic::ppc_altivec_vcmpgefp: CompareOpc = 454; isDot = 0; break; + case Intrinsic::ppc_altivec_vcmpgtfp: CompareOpc = 710; isDot = 0; break; + case Intrinsic::ppc_altivec_vcmpgtsb: CompareOpc = 774; isDot = 0; break; + case Intrinsic::ppc_altivec_vcmpgtsh: CompareOpc = 838; isDot = 0; break; + case Intrinsic::ppc_altivec_vcmpgtsw: CompareOpc = 902; isDot = 0; break; + case Intrinsic::ppc_altivec_vcmpgtub: CompareOpc = 518; isDot = 0; break; + case Intrinsic::ppc_altivec_vcmpgtuh: CompareOpc = 582; isDot = 0; break; + case Intrinsic::ppc_altivec_vcmpgtuw: CompareOpc = 646; isDot = 0; break; + } + return true; +} + +/// LowerINTRINSIC_WO_CHAIN - If this is an intrinsic that we want to custom +/// lower, do it, otherwise return null. +SDValue PPCTargetLowering::LowerINTRINSIC_WO_CHAIN(SDValue Op, + SelectionDAG &DAG) { + // If this is a lowered altivec predicate compare, CompareOpc is set to the + // opcode number of the comparison. + DebugLoc dl = Op.getDebugLoc(); + int CompareOpc; + bool isDot; + if (!getAltivecCompareInfo(Op, CompareOpc, isDot)) + return SDValue(); // Don't custom lower most intrinsics. + + // If this is a non-dot comparison, make the VCMP node and we are done. + if (!isDot) { + SDValue Tmp = DAG.getNode(PPCISD::VCMP, dl, Op.getOperand(2).getValueType(), + Op.getOperand(1), Op.getOperand(2), + DAG.getConstant(CompareOpc, MVT::i32)); + return DAG.getNode(ISD::BIT_CONVERT, dl, Op.getValueType(), Tmp); + } + + // Create the PPCISD altivec 'dot' comparison node. + SDValue Ops[] = { + Op.getOperand(2), // LHS + Op.getOperand(3), // RHS + DAG.getConstant(CompareOpc, MVT::i32) + }; + std::vector VTs; + VTs.push_back(Op.getOperand(2).getValueType()); + VTs.push_back(MVT::Flag); + SDValue CompNode = DAG.getNode(PPCISD::VCMPo, dl, VTs, Ops, 3); + + // Now that we have the comparison, emit a copy from the CR to a GPR. + // This is flagged to the above dot comparison. + SDValue Flags = DAG.getNode(PPCISD::MFCR, dl, MVT::i32, + DAG.getRegister(PPC::CR6, MVT::i32), + CompNode.getValue(1)); + + // Unpack the result based on how the target uses it. + unsigned BitNo; // Bit # of CR6. + bool InvertBit; // Invert result? + switch (cast(Op.getOperand(1))->getZExtValue()) { + default: // Can't happen, don't crash on invalid number though. + case 0: // Return the value of the EQ bit of CR6. + BitNo = 0; InvertBit = false; + break; + case 1: // Return the inverted value of the EQ bit of CR6. + BitNo = 0; InvertBit = true; + break; + case 2: // Return the value of the LT bit of CR6. + BitNo = 2; InvertBit = false; + break; + case 3: // Return the inverted value of the LT bit of CR6. + BitNo = 2; InvertBit = true; + break; + } + + // Shift the bit into the low position. + Flags = DAG.getNode(ISD::SRL, dl, MVT::i32, Flags, + DAG.getConstant(8-(3-BitNo), MVT::i32)); + // Isolate the bit. + Flags = DAG.getNode(ISD::AND, dl, MVT::i32, Flags, + DAG.getConstant(1, MVT::i32)); + + // If we are supposed to, toggle the bit. + if (InvertBit) + Flags = DAG.getNode(ISD::XOR, dl, MVT::i32, Flags, + DAG.getConstant(1, MVT::i32)); + return Flags; +} + +SDValue PPCTargetLowering::LowerSCALAR_TO_VECTOR(SDValue Op, + SelectionDAG &DAG) { + DebugLoc dl = Op.getDebugLoc(); + // Create a stack slot that is 16-byte aligned. + MachineFrameInfo *FrameInfo = DAG.getMachineFunction().getFrameInfo(); + int FrameIdx = FrameInfo->CreateStackObject(16, 16, false); + EVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy(); + SDValue FIdx = DAG.getFrameIndex(FrameIdx, PtrVT); + + // Store the input value into Value#0 of the stack slot. + SDValue Store = DAG.getStore(DAG.getEntryNode(), dl, + Op.getOperand(0), FIdx, NULL, 0); + // Load it out. + return DAG.getLoad(Op.getValueType(), dl, Store, FIdx, NULL, 0); +} + +SDValue PPCTargetLowering::LowerMUL(SDValue Op, SelectionDAG &DAG) { + DebugLoc dl = Op.getDebugLoc(); + if (Op.getValueType() == MVT::v4i32) { + SDValue LHS = Op.getOperand(0), RHS = Op.getOperand(1); + + SDValue Zero = BuildSplatI( 0, 1, MVT::v4i32, DAG, dl); + SDValue Neg16 = BuildSplatI(-16, 4, MVT::v4i32, DAG, dl);//+16 as shift amt. + + SDValue RHSSwap = // = vrlw RHS, 16 + BuildIntrinsicOp(Intrinsic::ppc_altivec_vrlw, RHS, Neg16, DAG, dl); + + // Shrinkify inputs to v8i16. + LHS = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::v8i16, LHS); + RHS = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::v8i16, RHS); + RHSSwap = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::v8i16, RHSSwap); + + // Low parts multiplied together, generating 32-bit results (we ignore the + // top parts). + SDValue LoProd = BuildIntrinsicOp(Intrinsic::ppc_altivec_vmulouh, + LHS, RHS, DAG, dl, MVT::v4i32); + + SDValue HiProd = BuildIntrinsicOp(Intrinsic::ppc_altivec_vmsumuhm, + LHS, RHSSwap, Zero, DAG, dl, MVT::v4i32); + // Shift the high parts up 16 bits. + HiProd = BuildIntrinsicOp(Intrinsic::ppc_altivec_vslw, HiProd, + Neg16, DAG, dl); + return DAG.getNode(ISD::ADD, dl, MVT::v4i32, LoProd, HiProd); + } else if (Op.getValueType() == MVT::v8i16) { + SDValue LHS = Op.getOperand(0), RHS = Op.getOperand(1); + + SDValue Zero = BuildSplatI(0, 1, MVT::v8i16, DAG, dl); + + return BuildIntrinsicOp(Intrinsic::ppc_altivec_vmladduhm, + LHS, RHS, Zero, DAG, dl); + } else if (Op.getValueType() == MVT::v16i8) { + SDValue LHS = Op.getOperand(0), RHS = Op.getOperand(1); + + // Multiply the even 8-bit parts, producing 16-bit sums. + SDValue EvenParts = BuildIntrinsicOp(Intrinsic::ppc_altivec_vmuleub, + LHS, RHS, DAG, dl, MVT::v8i16); + EvenParts = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::v16i8, EvenParts); + + // Multiply the odd 8-bit parts, producing 16-bit sums. + SDValue OddParts = BuildIntrinsicOp(Intrinsic::ppc_altivec_vmuloub, + LHS, RHS, DAG, dl, MVT::v8i16); + OddParts = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::v16i8, OddParts); + + // Merge the results together. + int Ops[16]; + for (unsigned i = 0; i != 8; ++i) { + Ops[i*2 ] = 2*i+1; + Ops[i*2+1] = 2*i+1+16; + } + return DAG.getVectorShuffle(MVT::v16i8, dl, EvenParts, OddParts, Ops); + } else { + llvm_unreachable("Unknown mul to lower!"); + } +} + +/// LowerOperation - Provide custom lowering hooks for some operations. +/// +SDValue PPCTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) { + switch (Op.getOpcode()) { + default: llvm_unreachable("Wasn't expecting to be able to lower this!"); + case ISD::ConstantPool: return LowerConstantPool(Op, DAG); + case ISD::BlockAddress: return LowerBlockAddress(Op, DAG); + case ISD::GlobalAddress: return LowerGlobalAddress(Op, DAG); + case ISD::GlobalTLSAddress: return LowerGlobalTLSAddress(Op, DAG); + case ISD::JumpTable: return LowerJumpTable(Op, DAG); + case ISD::SETCC: return LowerSETCC(Op, DAG); + case ISD::TRAMPOLINE: return LowerTRAMPOLINE(Op, DAG); + case ISD::VASTART: + return LowerVASTART(Op, DAG, VarArgsFrameIndex, VarArgsStackOffset, + VarArgsNumGPR, VarArgsNumFPR, PPCSubTarget); + + case ISD::VAARG: + return LowerVAARG(Op, DAG, VarArgsFrameIndex, VarArgsStackOffset, + VarArgsNumGPR, VarArgsNumFPR, PPCSubTarget); + + case ISD::STACKRESTORE: return LowerSTACKRESTORE(Op, DAG, PPCSubTarget); + case ISD::DYNAMIC_STACKALLOC: + return LowerDYNAMIC_STACKALLOC(Op, DAG, PPCSubTarget); + + case ISD::SELECT_CC: return LowerSELECT_CC(Op, DAG); + case ISD::FP_TO_UINT: + case ISD::FP_TO_SINT: return LowerFP_TO_INT(Op, DAG, + Op.getDebugLoc()); + case ISD::SINT_TO_FP: return LowerSINT_TO_FP(Op, DAG); + case ISD::FLT_ROUNDS_: return LowerFLT_ROUNDS_(Op, DAG); + + // Lower 64-bit shifts. + case ISD::SHL_PARTS: return LowerSHL_PARTS(Op, DAG); + case ISD::SRL_PARTS: return LowerSRL_PARTS(Op, DAG); + case ISD::SRA_PARTS: return LowerSRA_PARTS(Op, DAG); + + // Vector-related lowering. + case ISD::BUILD_VECTOR: return LowerBUILD_VECTOR(Op, DAG); + case ISD::VECTOR_SHUFFLE: return LowerVECTOR_SHUFFLE(Op, DAG); + case ISD::INTRINSIC_WO_CHAIN: return LowerINTRINSIC_WO_CHAIN(Op, DAG); + case ISD::SCALAR_TO_VECTOR: return LowerSCALAR_TO_VECTOR(Op, DAG); + case ISD::MUL: return LowerMUL(Op, DAG); + + // Frame & Return address. + case ISD::RETURNADDR: return LowerRETURNADDR(Op, DAG); + case ISD::FRAMEADDR: return LowerFRAMEADDR(Op, DAG); + } + return SDValue(); +} + +void PPCTargetLowering::ReplaceNodeResults(SDNode *N, + SmallVectorImpl&Results, + SelectionDAG &DAG) { + DebugLoc dl = N->getDebugLoc(); + switch (N->getOpcode()) { + default: + assert(false && "Do not know how to custom type legalize this operation!"); + return; + case ISD::FP_ROUND_INREG: { + assert(N->getValueType(0) == MVT::ppcf128); + assert(N->getOperand(0).getValueType() == MVT::ppcf128); + SDValue Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, + MVT::f64, N->getOperand(0), + DAG.getIntPtrConstant(0)); + SDValue Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, + MVT::f64, N->getOperand(0), + DAG.getIntPtrConstant(1)); + + // This sequence changes FPSCR to do round-to-zero, adds the two halves + // of the long double, and puts FPSCR back the way it was. We do not + // actually model FPSCR. + std::vector NodeTys; + SDValue Ops[4], Result, MFFSreg, InFlag, FPreg; + + NodeTys.push_back(MVT::f64); // Return register + NodeTys.push_back(MVT::Flag); // Returns a flag for later insns + Result = DAG.getNode(PPCISD::MFFS, dl, NodeTys, &InFlag, 0); + MFFSreg = Result.getValue(0); + InFlag = Result.getValue(1); + + NodeTys.clear(); + NodeTys.push_back(MVT::Flag); // Returns a flag + Ops[0] = DAG.getConstant(31, MVT::i32); + Ops[1] = InFlag; + Result = DAG.getNode(PPCISD::MTFSB1, dl, NodeTys, Ops, 2); + InFlag = Result.getValue(0); + + NodeTys.clear(); + NodeTys.push_back(MVT::Flag); // Returns a flag + Ops[0] = DAG.getConstant(30, MVT::i32); + Ops[1] = InFlag; + Result = DAG.getNode(PPCISD::MTFSB0, dl, NodeTys, Ops, 2); + InFlag = Result.getValue(0); + + NodeTys.clear(); + NodeTys.push_back(MVT::f64); // result of add + NodeTys.push_back(MVT::Flag); // Returns a flag + Ops[0] = Lo; + Ops[1] = Hi; + Ops[2] = InFlag; + Result = DAG.getNode(PPCISD::FADDRTZ, dl, NodeTys, Ops, 3); + FPreg = Result.getValue(0); + InFlag = Result.getValue(1); + + NodeTys.clear(); + NodeTys.push_back(MVT::f64); + Ops[0] = DAG.getConstant(1, MVT::i32); + Ops[1] = MFFSreg; + Ops[2] = FPreg; + Ops[3] = InFlag; + Result = DAG.getNode(PPCISD::MTFSF, dl, NodeTys, Ops, 4); + FPreg = Result.getValue(0); + + // We know the low half is about to be thrown away, so just use something + // convenient. + Results.push_back(DAG.getNode(ISD::BUILD_PAIR, dl, MVT::ppcf128, + FPreg, FPreg)); + return; + } + case ISD::FP_TO_SINT: + Results.push_back(LowerFP_TO_INT(SDValue(N, 0), DAG, dl)); + return; + } +} + + +//===----------------------------------------------------------------------===// +// Other Lowering Code +//===----------------------------------------------------------------------===// + +MachineBasicBlock * +PPCTargetLowering::EmitAtomicBinary(MachineInstr *MI, MachineBasicBlock *BB, + bool is64bit, unsigned BinOpcode) const { + // This also handles ATOMIC_SWAP, indicated by BinOpcode==0. + const TargetInstrInfo *TII = getTargetMachine().getInstrInfo(); + + const BasicBlock *LLVM_BB = BB->getBasicBlock(); + MachineFunction *F = BB->getParent(); + MachineFunction::iterator It = BB; + ++It; + + unsigned dest = MI->getOperand(0).getReg(); + unsigned ptrA = MI->getOperand(1).getReg(); + unsigned ptrB = MI->getOperand(2).getReg(); + unsigned incr = MI->getOperand(3).getReg(); + DebugLoc dl = MI->getDebugLoc(); + + MachineBasicBlock *loopMBB = F->CreateMachineBasicBlock(LLVM_BB); + MachineBasicBlock *exitMBB = F->CreateMachineBasicBlock(LLVM_BB); + F->insert(It, loopMBB); + F->insert(It, exitMBB); + exitMBB->transferSuccessors(BB); + + MachineRegisterInfo &RegInfo = F->getRegInfo(); + unsigned TmpReg = (!BinOpcode) ? incr : + RegInfo.createVirtualRegister( + is64bit ? (const TargetRegisterClass *) &PPC::G8RCRegClass : + (const TargetRegisterClass *) &PPC::GPRCRegClass); + + // thisMBB: + // ... + // fallthrough --> loopMBB + BB->addSuccessor(loopMBB); + + // loopMBB: + // l[wd]arx dest, ptr + // add r0, dest, incr + // st[wd]cx. r0, ptr + // bne- loopMBB + // fallthrough --> exitMBB + BB = loopMBB; + BuildMI(BB, dl, TII->get(is64bit ? PPC::LDARX : PPC::LWARX), dest) + .addReg(ptrA).addReg(ptrB); + if (BinOpcode) + BuildMI(BB, dl, TII->get(BinOpcode), TmpReg).addReg(incr).addReg(dest); + BuildMI(BB, dl, TII->get(is64bit ? PPC::STDCX : PPC::STWCX)) + .addReg(TmpReg).addReg(ptrA).addReg(ptrB); + BuildMI(BB, dl, TII->get(PPC::BCC)) + .addImm(PPC::PRED_NE).addReg(PPC::CR0).addMBB(loopMBB); + BB->addSuccessor(loopMBB); + BB->addSuccessor(exitMBB); + + // exitMBB: + // ... + BB = exitMBB; + return BB; +} + +MachineBasicBlock * +PPCTargetLowering::EmitPartwordAtomicBinary(MachineInstr *MI, + MachineBasicBlock *BB, + bool is8bit, // operation + unsigned BinOpcode) const { + // This also handles ATOMIC_SWAP, indicated by BinOpcode==0. + const TargetInstrInfo *TII = getTargetMachine().getInstrInfo(); + // In 64 bit mode we have to use 64 bits for addresses, even though the + // lwarx/stwcx are 32 bits. With the 32-bit atomics we can use address + // registers without caring whether they're 32 or 64, but here we're + // doing actual arithmetic on the addresses. + bool is64bit = PPCSubTarget.isPPC64(); + + const BasicBlock *LLVM_BB = BB->getBasicBlock(); + MachineFunction *F = BB->getParent(); + MachineFunction::iterator It = BB; + ++It; + + unsigned dest = MI->getOperand(0).getReg(); + unsigned ptrA = MI->getOperand(1).getReg(); + unsigned ptrB = MI->getOperand(2).getReg(); + unsigned incr = MI->getOperand(3).getReg(); + DebugLoc dl = MI->getDebugLoc(); + + MachineBasicBlock *loopMBB = F->CreateMachineBasicBlock(LLVM_BB); + MachineBasicBlock *exitMBB = F->CreateMachineBasicBlock(LLVM_BB); + F->insert(It, loopMBB); + F->insert(It, exitMBB); + exitMBB->transferSuccessors(BB); + + MachineRegisterInfo &RegInfo = F->getRegInfo(); + const TargetRegisterClass *RC = + is64bit ? (const TargetRegisterClass *) &PPC::G8RCRegClass : + (const TargetRegisterClass *) &PPC::GPRCRegClass; + unsigned PtrReg = RegInfo.createVirtualRegister(RC); + unsigned Shift1Reg = RegInfo.createVirtualRegister(RC); + unsigned ShiftReg = RegInfo.createVirtualRegister(RC); + unsigned Incr2Reg = RegInfo.createVirtualRegister(RC); + unsigned MaskReg = RegInfo.createVirtualRegister(RC); + unsigned Mask2Reg = RegInfo.createVirtualRegister(RC); + unsigned Mask3Reg = RegInfo.createVirtualRegister(RC); + unsigned Tmp2Reg = RegInfo.createVirtualRegister(RC); + unsigned Tmp3Reg = RegInfo.createVirtualRegister(RC); + unsigned Tmp4Reg = RegInfo.createVirtualRegister(RC); + unsigned TmpDestReg = RegInfo.createVirtualRegister(RC); + unsigned Ptr1Reg; + unsigned TmpReg = (!BinOpcode) ? Incr2Reg : RegInfo.createVirtualRegister(RC); + + // thisMBB: + // ... + // fallthrough --> loopMBB + BB->addSuccessor(loopMBB); + + // The 4-byte load must be aligned, while a char or short may be + // anywhere in the word. Hence all this nasty bookkeeping code. + // add ptr1, ptrA, ptrB [copy if ptrA==0] + // rlwinm shift1, ptr1, 3, 27, 28 [3, 27, 27] + // xori shift, shift1, 24 [16] + // rlwinm ptr, ptr1, 0, 0, 29 + // slw incr2, incr, shift + // li mask2, 255 [li mask3, 0; ori mask2, mask3, 65535] + // slw mask, mask2, shift + // loopMBB: + // lwarx tmpDest, ptr + // add tmp, tmpDest, incr2 + // andc tmp2, tmpDest, mask + // and tmp3, tmp, mask + // or tmp4, tmp3, tmp2 + // stwcx. tmp4, ptr + // bne- loopMBB + // fallthrough --> exitMBB + // srw dest, tmpDest, shift + + if (ptrA!=PPC::R0) { + Ptr1Reg = RegInfo.createVirtualRegister(RC); + BuildMI(BB, dl, TII->get(is64bit ? PPC::ADD8 : PPC::ADD4), Ptr1Reg) + .addReg(ptrA).addReg(ptrB); + } else { + Ptr1Reg = ptrB; + } + BuildMI(BB, dl, TII->get(PPC::RLWINM), Shift1Reg).addReg(Ptr1Reg) + .addImm(3).addImm(27).addImm(is8bit ? 28 : 27); + BuildMI(BB, dl, TII->get(is64bit ? PPC::XORI8 : PPC::XORI), ShiftReg) + .addReg(Shift1Reg).addImm(is8bit ? 24 : 16); + if (is64bit) + BuildMI(BB, dl, TII->get(PPC::RLDICR), PtrReg) + .addReg(Ptr1Reg).addImm(0).addImm(61); + else + BuildMI(BB, dl, TII->get(PPC::RLWINM), PtrReg) + .addReg(Ptr1Reg).addImm(0).addImm(0).addImm(29); + BuildMI(BB, dl, TII->get(PPC::SLW), Incr2Reg) + .addReg(incr).addReg(ShiftReg); + if (is8bit) + BuildMI(BB, dl, TII->get(PPC::LI), Mask2Reg).addImm(255); + else { + BuildMI(BB, dl, TII->get(PPC::LI), Mask3Reg).addImm(0); + BuildMI(BB, dl, TII->get(PPC::ORI),Mask2Reg).addReg(Mask3Reg).addImm(65535); + } + BuildMI(BB, dl, TII->get(PPC::SLW), MaskReg) + .addReg(Mask2Reg).addReg(ShiftReg); + + BB = loopMBB; + BuildMI(BB, dl, TII->get(PPC::LWARX), TmpDestReg) + .addReg(PPC::R0).addReg(PtrReg); + if (BinOpcode) + BuildMI(BB, dl, TII->get(BinOpcode), TmpReg) + .addReg(Incr2Reg).addReg(TmpDestReg); + BuildMI(BB, dl, TII->get(is64bit ? PPC::ANDC8 : PPC::ANDC), Tmp2Reg) + .addReg(TmpDestReg).addReg(MaskReg); + BuildMI(BB, dl, TII->get(is64bit ? PPC::AND8 : PPC::AND), Tmp3Reg) + .addReg(TmpReg).addReg(MaskReg); + BuildMI(BB, dl, TII->get(is64bit ? PPC::OR8 : PPC::OR), Tmp4Reg) + .addReg(Tmp3Reg).addReg(Tmp2Reg); + BuildMI(BB, dl, TII->get(PPC::STWCX)) + .addReg(Tmp4Reg).addReg(PPC::R0).addReg(PtrReg); + BuildMI(BB, dl, TII->get(PPC::BCC)) + .addImm(PPC::PRED_NE).addReg(PPC::CR0).addMBB(loopMBB); + BB->addSuccessor(loopMBB); + BB->addSuccessor(exitMBB); + + // exitMBB: + // ... + BB = exitMBB; + BuildMI(BB, dl, TII->get(PPC::SRW), dest).addReg(TmpDestReg).addReg(ShiftReg); + return BB; +} + +MachineBasicBlock * +PPCTargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI, + MachineBasicBlock *BB, + DenseMap *EM) const { + const TargetInstrInfo *TII = getTargetMachine().getInstrInfo(); + + // To "insert" these instructions we actually have to insert their + // control-flow patterns. + const BasicBlock *LLVM_BB = BB->getBasicBlock(); + MachineFunction::iterator It = BB; + ++It; + + MachineFunction *F = BB->getParent(); + + if (MI->getOpcode() == PPC::SELECT_CC_I4 || + MI->getOpcode() == PPC::SELECT_CC_I8 || + MI->getOpcode() == PPC::SELECT_CC_F4 || + MI->getOpcode() == PPC::SELECT_CC_F8 || + MI->getOpcode() == PPC::SELECT_CC_VRRC) { + + // The incoming instruction knows the destination vreg to set, the + // condition code register to branch on, the true/false values to + // select between, and a branch opcode to use. + + // thisMBB: + // ... + // TrueVal = ... + // cmpTY ccX, r1, r2 + // bCC copy1MBB + // fallthrough --> copy0MBB + MachineBasicBlock *thisMBB = BB; + MachineBasicBlock *copy0MBB = F->CreateMachineBasicBlock(LLVM_BB); + MachineBasicBlock *sinkMBB = F->CreateMachineBasicBlock(LLVM_BB); + unsigned SelectPred = MI->getOperand(4).getImm(); + DebugLoc dl = MI->getDebugLoc(); + BuildMI(BB, dl, TII->get(PPC::BCC)) + .addImm(SelectPred).addReg(MI->getOperand(1).getReg()).addMBB(sinkMBB); + F->insert(It, copy0MBB); + F->insert(It, sinkMBB); + // Update machine-CFG edges by first adding all successors of the current + // block to the new block which will contain the Phi node for the select. + // Also inform sdisel of the edge changes. + for (MachineBasicBlock::succ_iterator I = BB->succ_begin(), + E = BB->succ_end(); I != E; ++I) { + EM->insert(std::make_pair(*I, sinkMBB)); + sinkMBB->addSuccessor(*I); + } + // Next, remove all successors of the current block, and add the true + // and fallthrough blocks as its successors. + while (!BB->succ_empty()) + BB->removeSuccessor(BB->succ_begin()); + // Next, add the true and fallthrough blocks as its successors. + BB->addSuccessor(copy0MBB); + BB->addSuccessor(sinkMBB); + + // copy0MBB: + // %FalseValue = ... + // # fallthrough to sinkMBB + BB = copy0MBB; + + // Update machine-CFG edges + BB->addSuccessor(sinkMBB); + + // sinkMBB: + // %Result = phi [ %FalseValue, copy0MBB ], [ %TrueValue, thisMBB ] + // ... + BB = sinkMBB; + BuildMI(BB, dl, TII->get(PPC::PHI), MI->getOperand(0).getReg()) + .addReg(MI->getOperand(3).getReg()).addMBB(copy0MBB) + .addReg(MI->getOperand(2).getReg()).addMBB(thisMBB); + } + else if (MI->getOpcode() == PPC::ATOMIC_LOAD_ADD_I8) + BB = EmitPartwordAtomicBinary(MI, BB, true, PPC::ADD4); + else if (MI->getOpcode() == PPC::ATOMIC_LOAD_ADD_I16) + BB = EmitPartwordAtomicBinary(MI, BB, false, PPC::ADD4); + else if (MI->getOpcode() == PPC::ATOMIC_LOAD_ADD_I32) + BB = EmitAtomicBinary(MI, BB, false, PPC::ADD4); + else if (MI->getOpcode() == PPC::ATOMIC_LOAD_ADD_I64) + BB = EmitAtomicBinary(MI, BB, true, PPC::ADD8); + + else if (MI->getOpcode() == PPC::ATOMIC_LOAD_AND_I8) + BB = EmitPartwordAtomicBinary(MI, BB, true, PPC::AND); + else if (MI->getOpcode() == PPC::ATOMIC_LOAD_AND_I16) + BB = EmitPartwordAtomicBinary(MI, BB, false, PPC::AND); + else if (MI->getOpcode() == PPC::ATOMIC_LOAD_AND_I32) + BB = EmitAtomicBinary(MI, BB, false, PPC::AND); + else if (MI->getOpcode() == PPC::ATOMIC_LOAD_AND_I64) + BB = EmitAtomicBinary(MI, BB, true, PPC::AND8); + + else if (MI->getOpcode() == PPC::ATOMIC_LOAD_OR_I8) + BB = EmitPartwordAtomicBinary(MI, BB, true, PPC::OR); + else if (MI->getOpcode() == PPC::ATOMIC_LOAD_OR_I16) + BB = EmitPartwordAtomicBinary(MI, BB, false, PPC::OR); + else if (MI->getOpcode() == PPC::ATOMIC_LOAD_OR_I32) + BB = EmitAtomicBinary(MI, BB, false, PPC::OR); + else if (MI->getOpcode() == PPC::ATOMIC_LOAD_OR_I64) + BB = EmitAtomicBinary(MI, BB, true, PPC::OR8); + + else if (MI->getOpcode() == PPC::ATOMIC_LOAD_XOR_I8) + BB = EmitPartwordAtomicBinary(MI, BB, true, PPC::XOR); + else if (MI->getOpcode() == PPC::ATOMIC_LOAD_XOR_I16) + BB = EmitPartwordAtomicBinary(MI, BB, false, PPC::XOR); + else if (MI->getOpcode() == PPC::ATOMIC_LOAD_XOR_I32) + BB = EmitAtomicBinary(MI, BB, false, PPC::XOR); + else if (MI->getOpcode() == PPC::ATOMIC_LOAD_XOR_I64) + BB = EmitAtomicBinary(MI, BB, true, PPC::XOR8); + + else if (MI->getOpcode() == PPC::ATOMIC_LOAD_NAND_I8) + BB = EmitPartwordAtomicBinary(MI, BB, true, PPC::ANDC); + else if (MI->getOpcode() == PPC::ATOMIC_LOAD_NAND_I16) + BB = EmitPartwordAtomicBinary(MI, BB, false, PPC::ANDC); + else if (MI->getOpcode() == PPC::ATOMIC_LOAD_NAND_I32) + BB = EmitAtomicBinary(MI, BB, false, PPC::ANDC); + else if (MI->getOpcode() == PPC::ATOMIC_LOAD_NAND_I64) + BB = EmitAtomicBinary(MI, BB, true, PPC::ANDC8); + + else if (MI->getOpcode() == PPC::ATOMIC_LOAD_SUB_I8) + BB = EmitPartwordAtomicBinary(MI, BB, true, PPC::SUBF); + else if (MI->getOpcode() == PPC::ATOMIC_LOAD_SUB_I16) + BB = EmitPartwordAtomicBinary(MI, BB, false, PPC::SUBF); + else if (MI->getOpcode() == PPC::ATOMIC_LOAD_SUB_I32) + BB = EmitAtomicBinary(MI, BB, false, PPC::SUBF); + else if (MI->getOpcode() == PPC::ATOMIC_LOAD_SUB_I64) + BB = EmitAtomicBinary(MI, BB, true, PPC::SUBF8); + + else if (MI->getOpcode() == PPC::ATOMIC_SWAP_I8) + BB = EmitPartwordAtomicBinary(MI, BB, true, 0); + else if (MI->getOpcode() == PPC::ATOMIC_SWAP_I16) + BB = EmitPartwordAtomicBinary(MI, BB, false, 0); + else if (MI->getOpcode() == PPC::ATOMIC_SWAP_I32) + BB = EmitAtomicBinary(MI, BB, false, 0); + else if (MI->getOpcode() == PPC::ATOMIC_SWAP_I64) + BB = EmitAtomicBinary(MI, BB, true, 0); + + else if (MI->getOpcode() == PPC::ATOMIC_CMP_SWAP_I32 || + MI->getOpcode() == PPC::ATOMIC_CMP_SWAP_I64) { + bool is64bit = MI->getOpcode() == PPC::ATOMIC_CMP_SWAP_I64; + + unsigned dest = MI->getOperand(0).getReg(); + unsigned ptrA = MI->getOperand(1).getReg(); + unsigned ptrB = MI->getOperand(2).getReg(); + unsigned oldval = MI->getOperand(3).getReg(); + unsigned newval = MI->getOperand(4).getReg(); + DebugLoc dl = MI->getDebugLoc(); + + MachineBasicBlock *loop1MBB = F->CreateMachineBasicBlock(LLVM_BB); + MachineBasicBlock *loop2MBB = F->CreateMachineBasicBlock(LLVM_BB); + MachineBasicBlock *midMBB = F->CreateMachineBasicBlock(LLVM_BB); + MachineBasicBlock *exitMBB = F->CreateMachineBasicBlock(LLVM_BB); + F->insert(It, loop1MBB); + F->insert(It, loop2MBB); + F->insert(It, midMBB); + F->insert(It, exitMBB); + exitMBB->transferSuccessors(BB); + + // thisMBB: + // ... + // fallthrough --> loopMBB + BB->addSuccessor(loop1MBB); + + // loop1MBB: + // l[wd]arx dest, ptr + // cmp[wd] dest, oldval + // bne- midMBB + // loop2MBB: + // st[wd]cx. newval, ptr + // bne- loopMBB + // b exitBB + // midMBB: + // st[wd]cx. dest, ptr + // exitBB: + BB = loop1MBB; + BuildMI(BB, dl, TII->get(is64bit ? PPC::LDARX : PPC::LWARX), dest) + .addReg(ptrA).addReg(ptrB); + BuildMI(BB, dl, TII->get(is64bit ? PPC::CMPD : PPC::CMPW), PPC::CR0) + .addReg(oldval).addReg(dest); + BuildMI(BB, dl, TII->get(PPC::BCC)) + .addImm(PPC::PRED_NE).addReg(PPC::CR0).addMBB(midMBB); + BB->addSuccessor(loop2MBB); + BB->addSuccessor(midMBB); + + BB = loop2MBB; + BuildMI(BB, dl, TII->get(is64bit ? PPC::STDCX : PPC::STWCX)) + .addReg(newval).addReg(ptrA).addReg(ptrB); + BuildMI(BB, dl, TII->get(PPC::BCC)) + .addImm(PPC::PRED_NE).addReg(PPC::CR0).addMBB(loop1MBB); + BuildMI(BB, dl, TII->get(PPC::B)).addMBB(exitMBB); + BB->addSuccessor(loop1MBB); + BB->addSuccessor(exitMBB); + + BB = midMBB; + BuildMI(BB, dl, TII->get(is64bit ? PPC::STDCX : PPC::STWCX)) + .addReg(dest).addReg(ptrA).addReg(ptrB); + BB->addSuccessor(exitMBB); + + // exitMBB: + // ... + BB = exitMBB; + } else if (MI->getOpcode() == PPC::ATOMIC_CMP_SWAP_I8 || + MI->getOpcode() == PPC::ATOMIC_CMP_SWAP_I16) { + // We must use 64-bit registers for addresses when targeting 64-bit, + // since we're actually doing arithmetic on them. Other registers + // can be 32-bit. + bool is64bit = PPCSubTarget.isPPC64(); + bool is8bit = MI->getOpcode() == PPC::ATOMIC_CMP_SWAP_I8; + + unsigned dest = MI->getOperand(0).getReg(); + unsigned ptrA = MI->getOperand(1).getReg(); + unsigned ptrB = MI->getOperand(2).getReg(); + unsigned oldval = MI->getOperand(3).getReg(); + unsigned newval = MI->getOperand(4).getReg(); + DebugLoc dl = MI->getDebugLoc(); + + MachineBasicBlock *loop1MBB = F->CreateMachineBasicBlock(LLVM_BB); + MachineBasicBlock *loop2MBB = F->CreateMachineBasicBlock(LLVM_BB); + MachineBasicBlock *midMBB = F->CreateMachineBasicBlock(LLVM_BB); + MachineBasicBlock *exitMBB = F->CreateMachineBasicBlock(LLVM_BB); + F->insert(It, loop1MBB); + F->insert(It, loop2MBB); + F->insert(It, midMBB); + F->insert(It, exitMBB); + exitMBB->transferSuccessors(BB); + + MachineRegisterInfo &RegInfo = F->getRegInfo(); + const TargetRegisterClass *RC = + is64bit ? (const TargetRegisterClass *) &PPC::G8RCRegClass : + (const TargetRegisterClass *) &PPC::GPRCRegClass; + unsigned PtrReg = RegInfo.createVirtualRegister(RC); + unsigned Shift1Reg = RegInfo.createVirtualRegister(RC); + unsigned ShiftReg = RegInfo.createVirtualRegister(RC); + unsigned NewVal2Reg = RegInfo.createVirtualRegister(RC); + unsigned NewVal3Reg = RegInfo.createVirtualRegister(RC); + unsigned OldVal2Reg = RegInfo.createVirtualRegister(RC); + unsigned OldVal3Reg = RegInfo.createVirtualRegister(RC); + unsigned MaskReg = RegInfo.createVirtualRegister(RC); + unsigned Mask2Reg = RegInfo.createVirtualRegister(RC); + unsigned Mask3Reg = RegInfo.createVirtualRegister(RC); + unsigned Tmp2Reg = RegInfo.createVirtualRegister(RC); + unsigned Tmp4Reg = RegInfo.createVirtualRegister(RC); + unsigned TmpDestReg = RegInfo.createVirtualRegister(RC); + unsigned Ptr1Reg; + unsigned TmpReg = RegInfo.createVirtualRegister(RC); + // thisMBB: + // ... + // fallthrough --> loopMBB + BB->addSuccessor(loop1MBB); + + // The 4-byte load must be aligned, while a char or short may be + // anywhere in the word. Hence all this nasty bookkeeping code. + // add ptr1, ptrA, ptrB [copy if ptrA==0] + // rlwinm shift1, ptr1, 3, 27, 28 [3, 27, 27] + // xori shift, shift1, 24 [16] + // rlwinm ptr, ptr1, 0, 0, 29 + // slw newval2, newval, shift + // slw oldval2, oldval,shift + // li mask2, 255 [li mask3, 0; ori mask2, mask3, 65535] + // slw mask, mask2, shift + // and newval3, newval2, mask + // and oldval3, oldval2, mask + // loop1MBB: + // lwarx tmpDest, ptr + // and tmp, tmpDest, mask + // cmpw tmp, oldval3 + // bne- midMBB + // loop2MBB: + // andc tmp2, tmpDest, mask + // or tmp4, tmp2, newval3 + // stwcx. tmp4, ptr + // bne- loop1MBB + // b exitBB + // midMBB: + // stwcx. tmpDest, ptr + // exitBB: + // srw dest, tmpDest, shift + if (ptrA!=PPC::R0) { + Ptr1Reg = RegInfo.createVirtualRegister(RC); + BuildMI(BB, dl, TII->get(is64bit ? PPC::ADD8 : PPC::ADD4), Ptr1Reg) + .addReg(ptrA).addReg(ptrB); + } else { + Ptr1Reg = ptrB; + } + BuildMI(BB, dl, TII->get(PPC::RLWINM), Shift1Reg).addReg(Ptr1Reg) + .addImm(3).addImm(27).addImm(is8bit ? 28 : 27); + BuildMI(BB, dl, TII->get(is64bit ? PPC::XORI8 : PPC::XORI), ShiftReg) + .addReg(Shift1Reg).addImm(is8bit ? 24 : 16); + if (is64bit) + BuildMI(BB, dl, TII->get(PPC::RLDICR), PtrReg) + .addReg(Ptr1Reg).addImm(0).addImm(61); + else + BuildMI(BB, dl, TII->get(PPC::RLWINM), PtrReg) + .addReg(Ptr1Reg).addImm(0).addImm(0).addImm(29); + BuildMI(BB, dl, TII->get(PPC::SLW), NewVal2Reg) + .addReg(newval).addReg(ShiftReg); + BuildMI(BB, dl, TII->get(PPC::SLW), OldVal2Reg) + .addReg(oldval).addReg(ShiftReg); + if (is8bit) + BuildMI(BB, dl, TII->get(PPC::LI), Mask2Reg).addImm(255); + else { + BuildMI(BB, dl, TII->get(PPC::LI), Mask3Reg).addImm(0); + BuildMI(BB, dl, TII->get(PPC::ORI), Mask2Reg) + .addReg(Mask3Reg).addImm(65535); + } + BuildMI(BB, dl, TII->get(PPC::SLW), MaskReg) + .addReg(Mask2Reg).addReg(ShiftReg); + BuildMI(BB, dl, TII->get(PPC::AND), NewVal3Reg) + .addReg(NewVal2Reg).addReg(MaskReg); + BuildMI(BB, dl, TII->get(PPC::AND), OldVal3Reg) + .addReg(OldVal2Reg).addReg(MaskReg); + + BB = loop1MBB; + BuildMI(BB, dl, TII->get(PPC::LWARX), TmpDestReg) + .addReg(PPC::R0).addReg(PtrReg); + BuildMI(BB, dl, TII->get(PPC::AND),TmpReg) + .addReg(TmpDestReg).addReg(MaskReg); + BuildMI(BB, dl, TII->get(PPC::CMPW), PPC::CR0) + .addReg(TmpReg).addReg(OldVal3Reg); + BuildMI(BB, dl, TII->get(PPC::BCC)) + .addImm(PPC::PRED_NE).addReg(PPC::CR0).addMBB(midMBB); + BB->addSuccessor(loop2MBB); + BB->addSuccessor(midMBB); + + BB = loop2MBB; + BuildMI(BB, dl, TII->get(PPC::ANDC),Tmp2Reg) + .addReg(TmpDestReg).addReg(MaskReg); + BuildMI(BB, dl, TII->get(PPC::OR),Tmp4Reg) + .addReg(Tmp2Reg).addReg(NewVal3Reg); + BuildMI(BB, dl, TII->get(PPC::STWCX)).addReg(Tmp4Reg) + .addReg(PPC::R0).addReg(PtrReg); + BuildMI(BB, dl, TII->get(PPC::BCC)) + .addImm(PPC::PRED_NE).addReg(PPC::CR0).addMBB(loop1MBB); + BuildMI(BB, dl, TII->get(PPC::B)).addMBB(exitMBB); + BB->addSuccessor(loop1MBB); + BB->addSuccessor(exitMBB); + + BB = midMBB; + BuildMI(BB, dl, TII->get(PPC::STWCX)).addReg(TmpDestReg) + .addReg(PPC::R0).addReg(PtrReg); + BB->addSuccessor(exitMBB); + + // exitMBB: + // ... + BB = exitMBB; + BuildMI(BB, dl, TII->get(PPC::SRW),dest).addReg(TmpReg).addReg(ShiftReg); + } else { + llvm_unreachable("Unexpected instr type to insert"); + } + + F->DeleteMachineInstr(MI); // The pseudo instruction is gone now. + return BB; +} + +//===----------------------------------------------------------------------===// +// Target Optimization Hooks +//===----------------------------------------------------------------------===// + +SDValue PPCTargetLowering::PerformDAGCombine(SDNode *N, + DAGCombinerInfo &DCI) const { + TargetMachine &TM = getTargetMachine(); + SelectionDAG &DAG = DCI.DAG; + DebugLoc dl = N->getDebugLoc(); + switch (N->getOpcode()) { + default: break; + case PPCISD::SHL: + if (ConstantSDNode *C = dyn_cast(N->getOperand(0))) { + if (C->getZExtValue() == 0) // 0 << V -> 0. + return N->getOperand(0); + } + break; + case PPCISD::SRL: + if (ConstantSDNode *C = dyn_cast(N->getOperand(0))) { + if (C->getZExtValue() == 0) // 0 >>u V -> 0. + return N->getOperand(0); + } + break; + case PPCISD::SRA: + if (ConstantSDNode *C = dyn_cast(N->getOperand(0))) { + if (C->getZExtValue() == 0 || // 0 >>s V -> 0. + C->isAllOnesValue()) // -1 >>s V -> -1. + return N->getOperand(0); + } + break; + + case ISD::SINT_TO_FP: + if (TM.getSubtarget().has64BitSupport()) { + if (N->getOperand(0).getOpcode() == ISD::FP_TO_SINT) { + // Turn (sint_to_fp (fp_to_sint X)) -> fctidz/fcfid without load/stores. + // We allow the src/dst to be either f32/f64, but the intermediate + // type must be i64. + if (N->getOperand(0).getValueType() == MVT::i64 && + N->getOperand(0).getOperand(0).getValueType() != MVT::ppcf128) { + SDValue Val = N->getOperand(0).getOperand(0); + if (Val.getValueType() == MVT::f32) { + Val = DAG.getNode(ISD::FP_EXTEND, dl, MVT::f64, Val); + DCI.AddToWorklist(Val.getNode()); + } + + Val = DAG.getNode(PPCISD::FCTIDZ, dl, MVT::f64, Val); + DCI.AddToWorklist(Val.getNode()); + Val = DAG.getNode(PPCISD::FCFID, dl, MVT::f64, Val); + DCI.AddToWorklist(Val.getNode()); + if (N->getValueType(0) == MVT::f32) { + Val = DAG.getNode(ISD::FP_ROUND, dl, MVT::f32, Val, + DAG.getIntPtrConstant(0)); + DCI.AddToWorklist(Val.getNode()); + } + return Val; + } else if (N->getOperand(0).getValueType() == MVT::i32) { + // If the intermediate type is i32, we can avoid the load/store here + // too. + } + } + } + break; + case ISD::STORE: + // Turn STORE (FP_TO_SINT F) -> STFIWX(FCTIWZ(F)). + if (TM.getSubtarget().hasSTFIWX() && + !cast(N)->isTruncatingStore() && + N->getOperand(1).getOpcode() == ISD::FP_TO_SINT && + N->getOperand(1).getValueType() == MVT::i32 && + N->getOperand(1).getOperand(0).getValueType() != MVT::ppcf128) { + SDValue Val = N->getOperand(1).getOperand(0); + if (Val.getValueType() == MVT::f32) { + Val = DAG.getNode(ISD::FP_EXTEND, dl, MVT::f64, Val); + DCI.AddToWorklist(Val.getNode()); + } + Val = DAG.getNode(PPCISD::FCTIWZ, dl, MVT::f64, Val); + DCI.AddToWorklist(Val.getNode()); + + Val = DAG.getNode(PPCISD::STFIWX, dl, MVT::Other, N->getOperand(0), Val, + N->getOperand(2), N->getOperand(3)); + DCI.AddToWorklist(Val.getNode()); + return Val; + } + + // Turn STORE (BSWAP) -> sthbrx/stwbrx. + if (cast(N)->isUnindexed() && + N->getOperand(1).getOpcode() == ISD::BSWAP && + N->getOperand(1).getNode()->hasOneUse() && + (N->getOperand(1).getValueType() == MVT::i32 || + N->getOperand(1).getValueType() == MVT::i16)) { + SDValue BSwapOp = N->getOperand(1).getOperand(0); + // Do an any-extend to 32-bits if this is a half-word input. + if (BSwapOp.getValueType() == MVT::i16) + BSwapOp = DAG.getNode(ISD::ANY_EXTEND, dl, MVT::i32, BSwapOp); + + SDValue Ops[] = { + N->getOperand(0), BSwapOp, N->getOperand(2), + DAG.getValueType(N->getOperand(1).getValueType()) + }; + return + DAG.getMemIntrinsicNode(PPCISD::STBRX, dl, DAG.getVTList(MVT::Other), + Ops, array_lengthof(Ops), + cast(N)->getMemoryVT(), + cast(N)->getMemOperand()); + } + break; + case ISD::BSWAP: + // Turn BSWAP (LOAD) -> lhbrx/lwbrx. + if (ISD::isNON_EXTLoad(N->getOperand(0).getNode()) && + N->getOperand(0).hasOneUse() && + (N->getValueType(0) == MVT::i32 || N->getValueType(0) == MVT::i16)) { + SDValue Load = N->getOperand(0); + LoadSDNode *LD = cast(Load); + // Create the byte-swapping load. + SDValue Ops[] = { + LD->getChain(), // Chain + LD->getBasePtr(), // Ptr + DAG.getValueType(N->getValueType(0)) // VT + }; + SDValue BSLoad = + DAG.getMemIntrinsicNode(PPCISD::LBRX, dl, + DAG.getVTList(MVT::i32, MVT::Other), Ops, 3, + LD->getMemoryVT(), LD->getMemOperand()); + + // If this is an i16 load, insert the truncate. + SDValue ResVal = BSLoad; + if (N->getValueType(0) == MVT::i16) + ResVal = DAG.getNode(ISD::TRUNCATE, dl, MVT::i16, BSLoad); + + // First, combine the bswap away. This makes the value produced by the + // load dead. + DCI.CombineTo(N, ResVal); + + // Next, combine the load away, we give it a bogus result value but a real + // chain result. The result value is dead because the bswap is dead. + DCI.CombineTo(Load.getNode(), ResVal, BSLoad.getValue(1)); + + // Return N so it doesn't get rechecked! + return SDValue(N, 0); + } + + break; + case PPCISD::VCMP: { + // If a VCMPo node already exists with exactly the same operands as this + // node, use its result instead of this node (VCMPo computes both a CR6 and + // a normal output). + // + if (!N->getOperand(0).hasOneUse() && + !N->getOperand(1).hasOneUse() && + !N->getOperand(2).hasOneUse()) { + + // Scan all of the users of the LHS, looking for VCMPo's that match. + SDNode *VCMPoNode = 0; + + SDNode *LHSN = N->getOperand(0).getNode(); + for (SDNode::use_iterator UI = LHSN->use_begin(), E = LHSN->use_end(); + UI != E; ++UI) + if (UI->getOpcode() == PPCISD::VCMPo && + UI->getOperand(1) == N->getOperand(1) && + UI->getOperand(2) == N->getOperand(2) && + UI->getOperand(0) == N->getOperand(0)) { + VCMPoNode = *UI; + break; + } + + // If there is no VCMPo node, or if the flag value has a single use, don't + // transform this. + if (!VCMPoNode || VCMPoNode->hasNUsesOfValue(0, 1)) + break; + + // Look at the (necessarily single) use of the flag value. If it has a + // chain, this transformation is more complex. Note that multiple things + // could use the value result, which we should ignore. + SDNode *FlagUser = 0; + for (SDNode::use_iterator UI = VCMPoNode->use_begin(); + FlagUser == 0; ++UI) { + assert(UI != VCMPoNode->use_end() && "Didn't find user!"); + SDNode *User = *UI; + for (unsigned i = 0, e = User->getNumOperands(); i != e; ++i) { + if (User->getOperand(i) == SDValue(VCMPoNode, 1)) { + FlagUser = User; + break; + } + } + } + + // If the user is a MFCR instruction, we know this is safe. Otherwise we + // give up for right now. + if (FlagUser->getOpcode() == PPCISD::MFCR) + return SDValue(VCMPoNode, 0); + } + break; + } + case ISD::BR_CC: { + // If this is a branch on an altivec predicate comparison, lower this so + // that we don't have to do a MFCR: instead, branch directly on CR6. This + // lowering is done pre-legalize, because the legalizer lowers the predicate + // compare down to code that is difficult to reassemble. + ISD::CondCode CC = cast(N->getOperand(1))->get(); + SDValue LHS = N->getOperand(2), RHS = N->getOperand(3); + int CompareOpc; + bool isDot; + + if (LHS.getOpcode() == ISD::INTRINSIC_WO_CHAIN && + isa(RHS) && (CC == ISD::SETEQ || CC == ISD::SETNE) && + getAltivecCompareInfo(LHS, CompareOpc, isDot)) { + assert(isDot && "Can't compare against a vector result!"); + + // If this is a comparison against something other than 0/1, then we know + // that the condition is never/always true. + unsigned Val = cast(RHS)->getZExtValue(); + if (Val != 0 && Val != 1) { + if (CC == ISD::SETEQ) // Cond never true, remove branch. + return N->getOperand(0); + // Always !=, turn it into an unconditional branch. + return DAG.getNode(ISD::BR, dl, MVT::Other, + N->getOperand(0), N->getOperand(4)); + } + + bool BranchOnWhenPredTrue = (CC == ISD::SETEQ) ^ (Val == 0); + + // Create the PPCISD altivec 'dot' comparison node. + std::vector VTs; + SDValue Ops[] = { + LHS.getOperand(2), // LHS of compare + LHS.getOperand(3), // RHS of compare + DAG.getConstant(CompareOpc, MVT::i32) + }; + VTs.push_back(LHS.getOperand(2).getValueType()); + VTs.push_back(MVT::Flag); + SDValue CompNode = DAG.getNode(PPCISD::VCMPo, dl, VTs, Ops, 3); + + // Unpack the result based on how the target uses it. + PPC::Predicate CompOpc; + switch (cast(LHS.getOperand(1))->getZExtValue()) { + default: // Can't happen, don't crash on invalid number though. + case 0: // Branch on the value of the EQ bit of CR6. + CompOpc = BranchOnWhenPredTrue ? PPC::PRED_EQ : PPC::PRED_NE; + break; + case 1: // Branch on the inverted value of the EQ bit of CR6. + CompOpc = BranchOnWhenPredTrue ? PPC::PRED_NE : PPC::PRED_EQ; + break; + case 2: // Branch on the value of the LT bit of CR6. + CompOpc = BranchOnWhenPredTrue ? PPC::PRED_LT : PPC::PRED_GE; + break; + case 3: // Branch on the inverted value of the LT bit of CR6. + CompOpc = BranchOnWhenPredTrue ? PPC::PRED_GE : PPC::PRED_LT; + break; + } + + return DAG.getNode(PPCISD::COND_BRANCH, dl, MVT::Other, N->getOperand(0), + DAG.getConstant(CompOpc, MVT::i32), + DAG.getRegister(PPC::CR6, MVT::i32), + N->getOperand(4), CompNode.getValue(1)); + } + break; + } + } + + return SDValue(); +} + +//===----------------------------------------------------------------------===// +// Inline Assembly Support +//===----------------------------------------------------------------------===// + +void PPCTargetLowering::computeMaskedBitsForTargetNode(const SDValue Op, + const APInt &Mask, + APInt &KnownZero, + APInt &KnownOne, + const SelectionDAG &DAG, + unsigned Depth) const { + KnownZero = KnownOne = APInt(Mask.getBitWidth(), 0); + switch (Op.getOpcode()) { + default: break; + case PPCISD::LBRX: { + // lhbrx is known to have the top bits cleared out. + if (cast(Op.getOperand(2))->getVT() == MVT::i16) + KnownZero = 0xFFFF0000; + break; + } + case ISD::INTRINSIC_WO_CHAIN: { + switch (cast(Op.getOperand(0))->getZExtValue()) { + default: break; + case Intrinsic::ppc_altivec_vcmpbfp_p: + case Intrinsic::ppc_altivec_vcmpeqfp_p: + case Intrinsic::ppc_altivec_vcmpequb_p: + case Intrinsic::ppc_altivec_vcmpequh_p: + case Intrinsic::ppc_altivec_vcmpequw_p: + case Intrinsic::ppc_altivec_vcmpgefp_p: + case Intrinsic::ppc_altivec_vcmpgtfp_p: + case Intrinsic::ppc_altivec_vcmpgtsb_p: + case Intrinsic::ppc_altivec_vcmpgtsh_p: + case Intrinsic::ppc_altivec_vcmpgtsw_p: + case Intrinsic::ppc_altivec_vcmpgtub_p: + case Intrinsic::ppc_altivec_vcmpgtuh_p: + case Intrinsic::ppc_altivec_vcmpgtuw_p: + KnownZero = ~1U; // All bits but the low one are known to be zero. + break; + } + } + } +} + + +/// getConstraintType - Given a constraint, return the type of +/// constraint it is for this target. +PPCTargetLowering::ConstraintType +PPCTargetLowering::getConstraintType(const std::string &Constraint) const { + if (Constraint.size() == 1) { + switch (Constraint[0]) { + default: break; + case 'b': + case 'r': + case 'f': + case 'v': + case 'y': + return C_RegisterClass; + } + } + return TargetLowering::getConstraintType(Constraint); +} + +std::pair +PPCTargetLowering::getRegForInlineAsmConstraint(const std::string &Constraint, + EVT VT) const { + if (Constraint.size() == 1) { + // GCC RS6000 Constraint Letters + switch (Constraint[0]) { + case 'b': // R1-R31 + case 'r': // R0-R31 + if (VT == MVT::i64 && PPCSubTarget.isPPC64()) + return std::make_pair(0U, PPC::G8RCRegisterClass); + return std::make_pair(0U, PPC::GPRCRegisterClass); + case 'f': + if (VT == MVT::f32) + return std::make_pair(0U, PPC::F4RCRegisterClass); + else if (VT == MVT::f64) + return std::make_pair(0U, PPC::F8RCRegisterClass); + break; + case 'v': + return std::make_pair(0U, PPC::VRRCRegisterClass); + case 'y': // crrc + return std::make_pair(0U, PPC::CRRCRegisterClass); + } + } + + return TargetLowering::getRegForInlineAsmConstraint(Constraint, VT); +} + + +/// LowerAsmOperandForConstraint - Lower the specified operand into the Ops +/// vector. If it is invalid, don't add anything to Ops. If hasMemory is true +/// it means one of the asm constraint of the inline asm instruction being +/// processed is 'm'. +void PPCTargetLowering::LowerAsmOperandForConstraint(SDValue Op, char Letter, + bool hasMemory, + std::vector&Ops, + SelectionDAG &DAG) const { + SDValue Result(0,0); + switch (Letter) { + default: break; + case 'I': + case 'J': + case 'K': + case 'L': + case 'M': + case 'N': + case 'O': + case 'P': { + ConstantSDNode *CST = dyn_cast(Op); + if (!CST) return; // Must be an immediate to match. + unsigned Value = CST->getZExtValue(); + switch (Letter) { + default: llvm_unreachable("Unknown constraint letter!"); + case 'I': // "I" is a signed 16-bit constant. + if ((short)Value == (int)Value) + Result = DAG.getTargetConstant(Value, Op.getValueType()); + break; + case 'J': // "J" is a constant with only the high-order 16 bits nonzero. + case 'L': // "L" is a signed 16-bit constant shifted left 16 bits. + if ((short)Value == 0) + Result = DAG.getTargetConstant(Value, Op.getValueType()); + break; + case 'K': // "K" is a constant with only the low-order 16 bits nonzero. + if ((Value >> 16) == 0) + Result = DAG.getTargetConstant(Value, Op.getValueType()); + break; + case 'M': // "M" is a constant that is greater than 31. + if (Value > 31) + Result = DAG.getTargetConstant(Value, Op.getValueType()); + break; + case 'N': // "N" is a positive constant that is an exact power of two. + if ((int)Value > 0 && isPowerOf2_32(Value)) + Result = DAG.getTargetConstant(Value, Op.getValueType()); + break; + case 'O': // "O" is the constant zero. + if (Value == 0) + Result = DAG.getTargetConstant(Value, Op.getValueType()); + break; + case 'P': // "P" is a constant whose negation is a signed 16-bit constant. + if ((short)-Value == (int)-Value) + Result = DAG.getTargetConstant(Value, Op.getValueType()); + break; + } + break; + } + } + + if (Result.getNode()) { + Ops.push_back(Result); + return; + } + + // Handle standard constraint letters. + TargetLowering::LowerAsmOperandForConstraint(Op, Letter, hasMemory, Ops, DAG); +} + +// isLegalAddressingMode - Return true if the addressing mode represented +// by AM is legal for this target, for a load/store of the specified type. +bool PPCTargetLowering::isLegalAddressingMode(const AddrMode &AM, + const Type *Ty) const { + // FIXME: PPC does not allow r+i addressing modes for vectors! + + // PPC allows a sign-extended 16-bit immediate field. + if (AM.BaseOffs <= -(1LL << 16) || AM.BaseOffs >= (1LL << 16)-1) + return false; + + // No global is ever allowed as a base. + if (AM.BaseGV) + return false; + + // PPC only support r+r, + switch (AM.Scale) { + case 0: // "r+i" or just "i", depending on HasBaseReg. + break; + case 1: + if (AM.HasBaseReg && AM.BaseOffs) // "r+r+i" is not allowed. + return false; + // Otherwise we have r+r or r+i. + break; + case 2: + if (AM.HasBaseReg || AM.BaseOffs) // 2*r+r or 2*r+i is not allowed. + return false; + // Allow 2*r as r+r. + break; + default: + // No other scales are supported. + return false; + } + + return true; +} + +/// isLegalAddressImmediate - Return true if the integer value can be used +/// as the offset of the target addressing mode for load / store of the +/// given type. +bool PPCTargetLowering::isLegalAddressImmediate(int64_t V,const Type *Ty) const{ + // PPC allows a sign-extended 16-bit immediate field. + return (V > -(1 << 16) && V < (1 << 16)-1); +} + +bool PPCTargetLowering::isLegalAddressImmediate(llvm::GlobalValue* GV) const { + return false; +} + +SDValue PPCTargetLowering::LowerRETURNADDR(SDValue Op, SelectionDAG &DAG) { + DebugLoc dl = Op.getDebugLoc(); + // Depths > 0 not supported yet! + if (cast(Op.getOperand(0))->getZExtValue() > 0) + return SDValue(); + + MachineFunction &MF = DAG.getMachineFunction(); + PPCFunctionInfo *FuncInfo = MF.getInfo(); + + // Just load the return address off the stack. + SDValue RetAddrFI = getReturnAddrFrameIndex(DAG); + + // Make sure the function really does not optimize away the store of the RA + // to the stack. + FuncInfo->setLRStoreRequired(); + return DAG.getLoad(getPointerTy(), dl, + DAG.getEntryNode(), RetAddrFI, NULL, 0); +} + +SDValue PPCTargetLowering::LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) { + DebugLoc dl = Op.getDebugLoc(); + // Depths > 0 not supported yet! + if (cast(Op.getOperand(0))->getZExtValue() > 0) + return SDValue(); + + EVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy(); + bool isPPC64 = PtrVT == MVT::i64; + + MachineFunction &MF = DAG.getMachineFunction(); + MachineFrameInfo *MFI = MF.getFrameInfo(); + bool is31 = (NoFramePointerElim || MFI->hasVarSizedObjects()) + && MFI->getStackSize(); + + if (isPPC64) + return DAG.getCopyFromReg(DAG.getEntryNode(), dl, is31 ? PPC::X31 : PPC::X1, + MVT::i64); + else + return DAG.getCopyFromReg(DAG.getEntryNode(), dl, is31 ? PPC::R31 : PPC::R1, + MVT::i32); +} + +bool +PPCTargetLowering::isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const { + // The PowerPC target isn't yet aware of offsets. + return false; +} + +EVT PPCTargetLowering::getOptimalMemOpType(uint64_t Size, unsigned Align, + bool isSrcConst, bool isSrcStr, + SelectionDAG &DAG) const { + if (this->PPCSubTarget.isPPC64()) { + return MVT::i64; + } else { + return MVT::i32; + } +} diff --git a/libclamav/c++/llvm/lib/Target/PowerPC/PPCISelLowering.h b/libclamav/c++/llvm/lib/Target/PowerPC/PPCISelLowering.h new file mode 100644 index 000000000..e45b261f1 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/PowerPC/PPCISelLowering.h @@ -0,0 +1,461 @@ +//===-- PPCISelLowering.h - PPC32 DAG Lowering Interface --------*- 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 the interfaces that PPC uses to lower LLVM code into a +// selection DAG. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TARGET_POWERPC_PPC32ISELLOWERING_H +#define LLVM_TARGET_POWERPC_PPC32ISELLOWERING_H + +#include "llvm/Target/TargetLowering.h" +#include "llvm/CodeGen/SelectionDAG.h" +#include "PPC.h" +#include "PPCSubtarget.h" + +namespace llvm { + namespace PPCISD { + enum NodeType { + // Start the numbering where the builtin ops and target ops leave off. + FIRST_NUMBER = ISD::BUILTIN_OP_END, + + /// FSEL - Traditional three-operand fsel node. + /// + FSEL, + + /// FCFID - The FCFID instruction, taking an f64 operand and producing + /// and f64 value containing the FP representation of the integer that + /// was temporarily in the f64 operand. + FCFID, + + /// FCTI[D,W]Z - The FCTIDZ and FCTIWZ instructions, taking an f32 or f64 + /// operand, producing an f64 value containing the integer representation + /// of that FP value. + FCTIDZ, FCTIWZ, + + /// STFIWX - The STFIWX instruction. The first operand is an input token + /// chain, then an f64 value to store, then an address to store it to. + STFIWX, + + // VMADDFP, VNMSUBFP - The VMADDFP and VNMSUBFP instructions, taking + // three v4f32 operands and producing a v4f32 result. + VMADDFP, VNMSUBFP, + + /// VPERM - The PPC VPERM Instruction. + /// + VPERM, + + /// Hi/Lo - These represent the high and low 16-bit parts of a global + /// address respectively. These nodes have two operands, the first of + /// which must be a TargetGlobalAddress, and the second of which must be a + /// Constant. Selected naively, these turn into 'lis G+C' and 'li G+C', + /// though these are usually folded into other nodes. + Hi, Lo, + + TOC_ENTRY, + + /// OPRC, CHAIN = DYNALLOC(CHAIN, NEGSIZE, FRAME_INDEX) + /// This instruction is lowered in PPCRegisterInfo::eliminateFrameIndex to + /// compute an allocation on the stack. + DYNALLOC, + + /// GlobalBaseReg - On Darwin, this node represents the result of the mflr + /// at function entry, used for PIC code. + GlobalBaseReg, + + /// These nodes represent the 32-bit PPC shifts that operate on 6-bit + /// shift amounts. These nodes are generated by the multi-precision shift + /// code. + SRL, SRA, SHL, + + /// EXTSW_32 - This is the EXTSW instruction for use with "32-bit" + /// registers. + EXTSW_32, + + /// CALL - A direct function call. + CALL_Darwin, CALL_SVR4, + + /// NOP - Special NOP which follows 64-bit SVR4 calls. + NOP, + + /// CHAIN,FLAG = MTCTR(VAL, CHAIN[, INFLAG]) - Directly corresponds to a + /// MTCTR instruction. + MTCTR, + + /// CHAIN,FLAG = BCTRL(CHAIN, INFLAG) - Directly corresponds to a + /// BCTRL instruction. + BCTRL_Darwin, BCTRL_SVR4, + + /// Return with a flag operand, matched by 'blr' + RET_FLAG, + + /// R32 = MFCR(CRREG, INFLAG) - Represents the MFCR/MFOCRF instructions. + /// This copies the bits corresponding to the specified CRREG into the + /// resultant GPR. Bits corresponding to other CR regs are undefined. + MFCR, + + /// RESVEC = VCMP(LHS, RHS, OPC) - Represents one of the altivec VCMP* + /// instructions. For lack of better number, we use the opcode number + /// encoding for the OPC field to identify the compare. For example, 838 + /// is VCMPGTSH. + VCMP, + + /// RESVEC, OUTFLAG = VCMPo(LHS, RHS, OPC) - Represents one of the + /// altivec VCMP*o instructions. For lack of better number, we use the + /// opcode number encoding for the OPC field to identify the compare. For + /// example, 838 is VCMPGTSH. + VCMPo, + + /// CHAIN = COND_BRANCH CHAIN, CRRC, OPC, DESTBB [, INFLAG] - This + /// corresponds to the COND_BRANCH pseudo instruction. CRRC is the + /// condition register to branch on, OPC is the branch opcode to use (e.g. + /// PPC::BLE), DESTBB is the destination block to branch to, and INFLAG is + /// an optional input flag argument. + COND_BRANCH, + + // The following 5 instructions are used only as part of the + // long double-to-int conversion sequence. + + /// OUTFLAG = MFFS F8RC - This moves the FPSCR (not modelled) into the + /// register. + MFFS, + + /// OUTFLAG = MTFSB0 INFLAG - This clears a bit in the FPSCR. + MTFSB0, + + /// OUTFLAG = MTFSB1 INFLAG - This sets a bit in the FPSCR. + MTFSB1, + + /// F8RC, OUTFLAG = FADDRTZ F8RC, F8RC, INFLAG - This is an FADD done with + /// rounding towards zero. It has flags added so it won't move past the + /// FPSCR-setting instructions. + FADDRTZ, + + /// MTFSF = F8RC, INFLAG - This moves the register into the FPSCR. + MTFSF, + + /// LARX = This corresponds to PPC l{w|d}arx instrcution: load and + /// reserve indexed. This is used to implement atomic operations. + LARX, + + /// STCX = This corresponds to PPC stcx. instrcution: store conditional + /// indexed. This is used to implement atomic operations. + STCX, + + /// TC_RETURN - A tail call return. + /// operand #0 chain + /// operand #1 callee (register or absolute) + /// operand #2 stack adjustment + /// operand #3 optional in flag + TC_RETURN, + + /// STD_32 - This is the STD instruction for use with "32-bit" registers. + STD_32 = ISD::FIRST_TARGET_MEMORY_OPCODE, + + /// CHAIN = STBRX CHAIN, GPRC, Ptr, Type - This is a + /// byte-swapping store instruction. It byte-swaps the low "Type" bits of + /// the GPRC input, then stores it through Ptr. Type can be either i16 or + /// i32. + STBRX, + + /// GPRC, CHAIN = LBRX CHAIN, Ptr, Type - This is a + /// byte-swapping load instruction. It loads "Type" bits, byte swaps it, + /// then puts it in the bottom bits of the GPRC. TYPE can be either i16 + /// or i32. + LBRX + }; + } + + /// Define some predicates that are used for node matching. + namespace PPC { + /// isVPKUHUMShuffleMask - Return true if this is the shuffle mask for a + /// VPKUHUM instruction. + bool isVPKUHUMShuffleMask(ShuffleVectorSDNode *N, bool isUnary); + + /// isVPKUWUMShuffleMask - Return true if this is the shuffle mask for a + /// VPKUWUM instruction. + bool isVPKUWUMShuffleMask(ShuffleVectorSDNode *N, bool isUnary); + + /// isVMRGLShuffleMask - Return true if this is a shuffle mask suitable for + /// a VRGL* instruction with the specified unit size (1,2 or 4 bytes). + bool isVMRGLShuffleMask(ShuffleVectorSDNode *N, unsigned UnitSize, + bool isUnary); + + /// isVMRGHShuffleMask - Return true if this is a shuffle mask suitable for + /// a VRGH* instruction with the specified unit size (1,2 or 4 bytes). + bool isVMRGHShuffleMask(ShuffleVectorSDNode *N, unsigned UnitSize, + bool isUnary); + + /// isVSLDOIShuffleMask - If this is a vsldoi shuffle mask, return the shift + /// amount, otherwise return -1. + int isVSLDOIShuffleMask(SDNode *N, bool isUnary); + + /// isSplatShuffleMask - Return true if the specified VECTOR_SHUFFLE operand + /// specifies a splat of a single element that is suitable for input to + /// VSPLTB/VSPLTH/VSPLTW. + bool isSplatShuffleMask(ShuffleVectorSDNode *N, unsigned EltSize); + + /// isAllNegativeZeroVector - Returns true if all elements of build_vector + /// are -0.0. + bool isAllNegativeZeroVector(SDNode *N); + + /// getVSPLTImmediate - Return the appropriate VSPLT* immediate to splat the + /// specified isSplatShuffleMask VECTOR_SHUFFLE mask. + unsigned getVSPLTImmediate(SDNode *N, unsigned EltSize); + + /// get_VSPLTI_elt - If this is a build_vector of constants which can be + /// formed by using a vspltis[bhw] instruction of the specified element + /// size, return the constant being splatted. The ByteSize field indicates + /// the number of bytes of each element [124] -> [bhw]. + SDValue get_VSPLTI_elt(SDNode *N, unsigned ByteSize, SelectionDAG &DAG); + } + + class PPCTargetLowering : public TargetLowering { + int VarArgsFrameIndex; // FrameIndex for start of varargs area. + int VarArgsStackOffset; // StackOffset for start of stack + // arguments. + unsigned VarArgsNumGPR; // Index of the first unused integer + // register for parameter passing. + unsigned VarArgsNumFPR; // Index of the first unused double + // register for parameter passing. + const PPCSubtarget &PPCSubTarget; + public: + explicit PPCTargetLowering(PPCTargetMachine &TM); + + /// getTargetNodeName() - This method returns the name of a target specific + /// DAG node. + virtual const char *getTargetNodeName(unsigned Opcode) const; + + /// getSetCCResultType - Return the ISD::SETCC ValueType + virtual MVT::SimpleValueType getSetCCResultType(EVT VT) const; + + /// getPreIndexedAddressParts - returns true by value, base pointer and + /// offset pointer and addressing mode by reference if the node's address + /// can be legally represented as pre-indexed load / store address. + virtual bool getPreIndexedAddressParts(SDNode *N, SDValue &Base, + SDValue &Offset, + ISD::MemIndexedMode &AM, + SelectionDAG &DAG) const; + + /// SelectAddressRegReg - Given the specified addressed, check to see if it + /// can be represented as an indexed [r+r] operation. Returns false if it + /// can be more efficiently represented with [r+imm]. + bool SelectAddressRegReg(SDValue N, SDValue &Base, SDValue &Index, + SelectionDAG &DAG) const; + + /// SelectAddressRegImm - Returns true if the address N can be represented + /// by a base register plus a signed 16-bit displacement [r+imm], and if it + /// is not better represented as reg+reg. + bool SelectAddressRegImm(SDValue N, SDValue &Disp, SDValue &Base, + SelectionDAG &DAG) const; + + /// SelectAddressRegRegOnly - Given the specified addressed, force it to be + /// represented as an indexed [r+r] operation. + bool SelectAddressRegRegOnly(SDValue N, SDValue &Base, SDValue &Index, + SelectionDAG &DAG) const; + + /// SelectAddressRegImmShift - Returns true if the address N can be + /// represented by a base register plus a signed 14-bit displacement + /// [r+imm*4]. Suitable for use by STD and friends. + bool SelectAddressRegImmShift(SDValue N, SDValue &Disp, SDValue &Base, + SelectionDAG &DAG) const; + + + /// LowerOperation - Provide custom lowering hooks for some operations. + /// + virtual SDValue LowerOperation(SDValue Op, SelectionDAG &DAG); + + /// ReplaceNodeResults - Replace the results of node with an illegal result + /// type with new values built out of custom code. + /// + virtual void ReplaceNodeResults(SDNode *N, SmallVectorImpl&Results, + SelectionDAG &DAG); + + virtual SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const; + + virtual void computeMaskedBitsForTargetNode(const SDValue Op, + const APInt &Mask, + APInt &KnownZero, + APInt &KnownOne, + const SelectionDAG &DAG, + unsigned Depth = 0) const; + + virtual MachineBasicBlock *EmitInstrWithCustomInserter(MachineInstr *MI, + MachineBasicBlock *MBB, + DenseMap *EM) const; + MachineBasicBlock *EmitAtomicBinary(MachineInstr *MI, + MachineBasicBlock *MBB, bool is64Bit, + unsigned BinOpcode) const; + MachineBasicBlock *EmitPartwordAtomicBinary(MachineInstr *MI, + MachineBasicBlock *MBB, + bool is8bit, unsigned Opcode) const; + + ConstraintType getConstraintType(const std::string &Constraint) const; + std::pair + getRegForInlineAsmConstraint(const std::string &Constraint, + EVT VT) const; + + /// getByValTypeAlignment - Return the desired alignment for ByVal aggregate + /// function arguments in the caller parameter area. This is the actual + /// alignment, not its logarithm. + unsigned getByValTypeAlignment(const Type *Ty) const; + + /// LowerAsmOperandForConstraint - Lower the specified operand into the Ops + /// vector. If it is invalid, don't add anything to Ops. If hasMemory is + /// true it means one of the asm constraint of the inline asm instruction + /// being processed is 'm'. + virtual void LowerAsmOperandForConstraint(SDValue Op, + char ConstraintLetter, + bool hasMemory, + std::vector &Ops, + SelectionDAG &DAG) const; + + /// isLegalAddressingMode - Return true if the addressing mode represented + /// by AM is legal for this target, for a load/store of the specified type. + virtual bool isLegalAddressingMode(const AddrMode &AM, const Type *Ty)const; + + /// isLegalAddressImmediate - Return true if the integer value can be used + /// as the offset of the target addressing mode for load / store of the + /// given type. + virtual bool isLegalAddressImmediate(int64_t V, const Type *Ty) const; + + /// isLegalAddressImmediate - Return true if the GlobalValue can be used as + /// the offset of the target addressing mode. + virtual bool isLegalAddressImmediate(GlobalValue *GV) const; + + virtual bool + IsEligibleForTailCallOptimization(SDValue Callee, + CallingConv::ID CalleeCC, + bool isVarArg, + const SmallVectorImpl &Ins, + SelectionDAG& DAG) const; + + virtual bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const; + + virtual EVT getOptimalMemOpType(uint64_t Size, unsigned Align, + bool isSrcConst, bool isSrcStr, + SelectionDAG &DAG) const; + + /// getFunctionAlignment - Return the Log2 alignment of this function. + virtual unsigned getFunctionAlignment(const Function *F) const; + + private: + SDValue getFramePointerFrameIndex(SelectionDAG & DAG) const; + SDValue getReturnAddrFrameIndex(SelectionDAG & DAG) const; + + SDValue EmitTailCallLoadFPAndRetAddr(SelectionDAG & DAG, + int SPDiff, + SDValue Chain, + SDValue &LROpOut, + SDValue &FPOpOut, + bool isDarwinABI, + DebugLoc dl); + + SDValue LowerRETURNADDR(SDValue Op, SelectionDAG &DAG); + SDValue LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG); + SDValue LowerConstantPool(SDValue Op, SelectionDAG &DAG); + SDValue LowerBlockAddress(SDValue Op, SelectionDAG &DAG); + SDValue LowerGlobalAddress(SDValue Op, SelectionDAG &DAG); + SDValue LowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG); + SDValue LowerJumpTable(SDValue Op, SelectionDAG &DAG); + SDValue LowerSETCC(SDValue Op, SelectionDAG &DAG); + SDValue LowerTRAMPOLINE(SDValue Op, SelectionDAG &DAG); + SDValue LowerVASTART(SDValue Op, SelectionDAG &DAG, + int VarArgsFrameIndex, int VarArgsStackOffset, + unsigned VarArgsNumGPR, unsigned VarArgsNumFPR, + const PPCSubtarget &Subtarget); + SDValue LowerVAARG(SDValue Op, SelectionDAG &DAG, int VarArgsFrameIndex, + int VarArgsStackOffset, unsigned VarArgsNumGPR, + unsigned VarArgsNumFPR, const PPCSubtarget &Subtarget); + SDValue LowerSTACKRESTORE(SDValue Op, SelectionDAG &DAG, + const PPCSubtarget &Subtarget); + SDValue LowerDYNAMIC_STACKALLOC(SDValue Op, SelectionDAG &DAG, + const PPCSubtarget &Subtarget); + SDValue LowerSELECT_CC(SDValue Op, SelectionDAG &DAG); + SDValue LowerFP_TO_INT(SDValue Op, SelectionDAG &DAG, DebugLoc dl); + SDValue LowerSINT_TO_FP(SDValue Op, SelectionDAG &DAG); + SDValue LowerFLT_ROUNDS_(SDValue Op, SelectionDAG &DAG); + SDValue LowerSHL_PARTS(SDValue Op, SelectionDAG &DAG); + SDValue LowerSRL_PARTS(SDValue Op, SelectionDAG &DAG); + SDValue LowerSRA_PARTS(SDValue Op, SelectionDAG &DAG); + SDValue LowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG); + SDValue LowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG); + SDValue LowerINTRINSIC_WO_CHAIN(SDValue Op, SelectionDAG &DAG); + SDValue LowerSCALAR_TO_VECTOR(SDValue Op, SelectionDAG &DAG); + SDValue LowerMUL(SDValue Op, SelectionDAG &DAG); + + SDValue LowerCallResult(SDValue Chain, SDValue InFlag, + CallingConv::ID CallConv, bool isVarArg, + const SmallVectorImpl &Ins, + DebugLoc dl, SelectionDAG &DAG, + SmallVectorImpl &InVals); + SDValue FinishCall(CallingConv::ID CallConv, DebugLoc dl, bool isTailCall, + bool isVarArg, + SelectionDAG &DAG, + SmallVector, 8> + &RegsToPass, + SDValue InFlag, SDValue Chain, + SDValue &Callee, + int SPDiff, unsigned NumBytes, + const SmallVectorImpl &Ins, + SmallVectorImpl &InVals); + + virtual SDValue + LowerFormalArguments(SDValue Chain, + CallingConv::ID CallConv, bool isVarArg, + const SmallVectorImpl &Ins, + DebugLoc dl, SelectionDAG &DAG, + SmallVectorImpl &InVals); + + virtual SDValue + LowerCall(SDValue Chain, SDValue Callee, + CallingConv::ID CallConv, bool isVarArg, bool isTailCall, + const SmallVectorImpl &Outs, + const SmallVectorImpl &Ins, + DebugLoc dl, SelectionDAG &DAG, + SmallVectorImpl &InVals); + + virtual SDValue + LowerReturn(SDValue Chain, + CallingConv::ID CallConv, bool isVarArg, + const SmallVectorImpl &Outs, + DebugLoc dl, SelectionDAG &DAG); + + SDValue + LowerFormalArguments_Darwin(SDValue Chain, + CallingConv::ID CallConv, bool isVarArg, + const SmallVectorImpl &Ins, + DebugLoc dl, SelectionDAG &DAG, + SmallVectorImpl &InVals); + SDValue + LowerFormalArguments_SVR4(SDValue Chain, + CallingConv::ID CallConv, bool isVarArg, + const SmallVectorImpl &Ins, + DebugLoc dl, SelectionDAG &DAG, + SmallVectorImpl &InVals); + + SDValue + LowerCall_Darwin(SDValue Chain, SDValue Callee, + CallingConv::ID CallConv, bool isVarArg, bool isTailCall, + const SmallVectorImpl &Outs, + const SmallVectorImpl &Ins, + DebugLoc dl, SelectionDAG &DAG, + SmallVectorImpl &InVals); + SDValue + LowerCall_SVR4(SDValue Chain, SDValue Callee, + CallingConv::ID CallConv, bool isVarArg, bool isTailCall, + const SmallVectorImpl &Outs, + const SmallVectorImpl &Ins, + DebugLoc dl, SelectionDAG &DAG, + SmallVectorImpl &InVals); + }; +} + +#endif // LLVM_TARGET_POWERPC_PPC32ISELLOWERING_H diff --git a/libclamav/c++/llvm/lib/Target/PowerPC/PPCInstr64Bit.td b/libclamav/c++/llvm/lib/Target/PowerPC/PPCInstr64Bit.td new file mode 100644 index 000000000..ebdc58b69 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/PowerPC/PPCInstr64Bit.td @@ -0,0 +1,743 @@ +//===- PPCInstr64Bit.td - The PowerPC 64-bit Support -------*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file describes the PowerPC 64-bit instructions. These patterns are used +// both when in ppc64 mode and when in "use 64-bit extensions in 32-bit" mode. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// 64-bit operands. +// +def s16imm64 : Operand { + let PrintMethod = "printS16ImmOperand"; +} +def u16imm64 : Operand { + let PrintMethod = "printU16ImmOperand"; +} +def symbolHi64 : Operand { + let PrintMethod = "printSymbolHi"; +} +def symbolLo64 : Operand { + let PrintMethod = "printSymbolLo"; +} + +//===----------------------------------------------------------------------===// +// 64-bit transformation functions. +// + +def SHL64 : SDNodeXFormgetZExtValue()); +}]>; + +def SRL64 : SDNodeXFormgetZExtValue() ? getI32Imm(64 - N->getZExtValue()) : getI32Imm(0); +}]>; + +def HI32_48 : SDNodeXFormgetZExtValue() >> 32)); +}]>; + +def HI48_64 : SDNodeXFormgetZExtValue() >> 48)); +}]>; + + +//===----------------------------------------------------------------------===// +// Calls. +// + +let Defs = [LR8] in + def MovePCtoLR8 : Pseudo<(outs), (ins piclabel:$label), "bl $label", []>, + PPC970_Unit_BRU; + +// Darwin ABI Calls. +let isCall = 1, PPC970_Unit = 7, + // All calls clobber the PPC64 non-callee saved registers. + Defs = [X0,X2,X3,X4,X5,X6,X7,X8,X9,X10,X11,X12, + F0,F1,F2,F3,F4,F5,F6,F7,F8,F9,F10,F11,F12,F13, + V0,V1,V2,V3,V4,V5,V6,V7,V8,V9,V10,V11,V12,V13,V14,V15,V16,V17,V18,V19, + LR8,CTR8, + CR0,CR1,CR5,CR6,CR7,CARRY] in { + // Convenient aliases for call instructions + let Uses = [RM] in { + def BL8_Darwin : IForm<18, 0, 1, + (outs), (ins calltarget:$func, variable_ops), + "bl $func", BrB, []>; // See Pat patterns below. + def BLA8_Darwin : IForm<18, 1, 1, + (outs), (ins aaddr:$func, variable_ops), + "bla $func", BrB, [(PPCcall_Darwin (i64 imm:$func))]>; + } + let Uses = [CTR8, RM] in { + def BCTRL8_Darwin : XLForm_2_ext<19, 528, 20, 0, 1, + (outs), (ins variable_ops), + "bctrl", BrB, + [(PPCbctrl_Darwin)]>, Requires<[In64BitMode]>; + } +} + +// ELF 64 ABI Calls = Darwin ABI Calls +// Used to define BL8_ELF and BLA8_ELF +let isCall = 1, PPC970_Unit = 7, + // All calls clobber the PPC64 non-callee saved registers. + Defs = [X0,X2,X3,X4,X5,X6,X7,X8,X9,X10,X11,X12, + F0,F1,F2,F3,F4,F5,F6,F7,F8,F9,F10,F11,F12,F13, + V0,V1,V2,V3,V4,V5,V6,V7,V8,V9,V10,V11,V12,V13,V14,V15,V16,V17,V18,V19, + LR8,CTR8, + CR0,CR1,CR5,CR6,CR7,CARRY] in { + // Convenient aliases for call instructions + let Uses = [RM] in { + def BL8_ELF : IForm<18, 0, 1, + (outs), (ins calltarget:$func, variable_ops), + "bl $func", BrB, []>; // See Pat patterns below. + def BLA8_ELF : IForm<18, 1, 1, + (outs), (ins aaddr:$func, variable_ops), + "bla $func", BrB, [(PPCcall_SVR4 (i64 imm:$func))]>; + } + let Uses = [CTR8, RM] in { + def BCTRL8_ELF : XLForm_2_ext<19, 528, 20, 0, 1, + (outs), (ins variable_ops), + "bctrl", BrB, + [(PPCbctrl_SVR4)]>, Requires<[In64BitMode]>; + } +} + + +// Calls +def : Pat<(PPCcall_Darwin (i64 tglobaladdr:$dst)), + (BL8_Darwin tglobaladdr:$dst)>; +def : Pat<(PPCcall_Darwin (i64 texternalsym:$dst)), + (BL8_Darwin texternalsym:$dst)>; + +def : Pat<(PPCcall_SVR4 (i64 tglobaladdr:$dst)), + (BL8_ELF tglobaladdr:$dst)>; +def : Pat<(PPCcall_SVR4 (i64 texternalsym:$dst)), + (BL8_ELF texternalsym:$dst)>; +def : Pat<(PPCnop), + (NOP)>; + +// Atomic operations +let usesCustomInserter = 1 in { + let Uses = [CR0] in { + def ATOMIC_LOAD_ADD_I64 : Pseudo< + (outs G8RC:$dst), (ins memrr:$ptr, G8RC:$incr), + "${:comment} ATOMIC_LOAD_ADD_I64 PSEUDO!", + [(set G8RC:$dst, (atomic_load_add_64 xoaddr:$ptr, G8RC:$incr))]>; + def ATOMIC_LOAD_SUB_I64 : Pseudo< + (outs G8RC:$dst), (ins memrr:$ptr, G8RC:$incr), + "${:comment} ATOMIC_LOAD_SUB_I64 PSEUDO!", + [(set G8RC:$dst, (atomic_load_sub_64 xoaddr:$ptr, G8RC:$incr))]>; + def ATOMIC_LOAD_OR_I64 : Pseudo< + (outs G8RC:$dst), (ins memrr:$ptr, G8RC:$incr), + "${:comment} ATOMIC_LOAD_OR_I64 PSEUDO!", + [(set G8RC:$dst, (atomic_load_or_64 xoaddr:$ptr, G8RC:$incr))]>; + def ATOMIC_LOAD_XOR_I64 : Pseudo< + (outs G8RC:$dst), (ins memrr:$ptr, G8RC:$incr), + "${:comment} ATOMIC_LOAD_XOR_I64 PSEUDO!", + [(set G8RC:$dst, (atomic_load_xor_64 xoaddr:$ptr, G8RC:$incr))]>; + def ATOMIC_LOAD_AND_I64 : Pseudo< + (outs G8RC:$dst), (ins memrr:$ptr, G8RC:$incr), + "${:comment} ATOMIC_LOAD_AND_I64 PSEUDO!", + [(set G8RC:$dst, (atomic_load_and_64 xoaddr:$ptr, G8RC:$incr))]>; + def ATOMIC_LOAD_NAND_I64 : Pseudo< + (outs G8RC:$dst), (ins memrr:$ptr, G8RC:$incr), + "${:comment} ATOMIC_LOAD_NAND_I64 PSEUDO!", + [(set G8RC:$dst, (atomic_load_nand_64 xoaddr:$ptr, G8RC:$incr))]>; + + def ATOMIC_CMP_SWAP_I64 : Pseudo< + (outs G8RC:$dst), (ins memrr:$ptr, G8RC:$old, G8RC:$new), + "${:comment} ATOMIC_CMP_SWAP_I64 PSEUDO!", + [(set G8RC:$dst, + (atomic_cmp_swap_64 xoaddr:$ptr, G8RC:$old, G8RC:$new))]>; + + def ATOMIC_SWAP_I64 : Pseudo< + (outs G8RC:$dst), (ins memrr:$ptr, G8RC:$new), + "${:comment} ATOMIC_SWAP_I64 PSEUDO!", + [(set G8RC:$dst, (atomic_swap_64 xoaddr:$ptr, G8RC:$new))]>; + } +} + +// Instructions to support atomic operations +def LDARX : XForm_1<31, 84, (outs G8RC:$rD), (ins memrr:$ptr), + "ldarx $rD, $ptr", LdStLDARX, + [(set G8RC:$rD, (PPClarx xoaddr:$ptr))]>; + +let Defs = [CR0] in +def STDCX : XForm_1<31, 214, (outs), (ins G8RC:$rS, memrr:$dst), + "stdcx. $rS, $dst", LdStSTDCX, + [(PPCstcx G8RC:$rS, xoaddr:$dst)]>, + isDOT; + +let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, Uses = [RM] in +def TCRETURNdi8 :Pseudo< (outs), + (ins calltarget:$dst, i32imm:$offset, variable_ops), + "#TC_RETURNd8 $dst $offset", + []>; + +let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, Uses = [RM] in +def TCRETURNai8 :Pseudo<(outs), (ins aaddr:$func, i32imm:$offset, variable_ops), + "#TC_RETURNa8 $func $offset", + [(PPCtc_return (i64 imm:$func), imm:$offset)]>; + +let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, Uses = [RM] in +def TCRETURNri8 : Pseudo<(outs), (ins CTRRC8:$dst, i32imm:$offset, variable_ops), + "#TC_RETURNr8 $dst $offset", + []>; + + +let isTerminator = 1, isBarrier = 1, PPC970_Unit = 7, isBranch = 1, + isIndirectBranch = 1, isCall = 1, isReturn = 1, Uses = [CTR, RM] in +def TAILBCTR8 : XLForm_2_ext<19, 528, 20, 0, 0, (outs), (ins), "bctr", BrB, []>, + Requires<[In64BitMode]>; + + + +let isBranch = 1, isTerminator = 1, hasCtrlDep = 1, PPC970_Unit = 7, + isBarrier = 1, isCall = 1, isReturn = 1, Uses = [RM] in +def TAILB8 : IForm<18, 0, 0, (outs), (ins calltarget:$dst), + "b $dst", BrB, + []>; + + +let isBranch = 1, isTerminator = 1, hasCtrlDep = 1, PPC970_Unit = 7, + isBarrier = 1, isCall = 1, isReturn = 1, Uses = [RM] in +def TAILBA8 : IForm<18, 0, 0, (outs), (ins aaddr:$dst), + "ba $dst", BrB, + []>; + +def : Pat<(PPCtc_return (i64 tglobaladdr:$dst), imm:$imm), + (TCRETURNdi8 tglobaladdr:$dst, imm:$imm)>; + +def : Pat<(PPCtc_return (i64 texternalsym:$dst), imm:$imm), + (TCRETURNdi8 texternalsym:$dst, imm:$imm)>; + +def : Pat<(PPCtc_return CTRRC8:$dst, imm:$imm), + (TCRETURNri8 CTRRC8:$dst, imm:$imm)>; + + +//===----------------------------------------------------------------------===// +// 64-bit SPR manipulation instrs. + +let Uses = [CTR8] in { +def MFCTR8 : XFXForm_1_ext<31, 339, 9, (outs G8RC:$rT), (ins), + "mfctr $rT", SprMFSPR>, + PPC970_DGroup_First, PPC970_Unit_FXU; +} +let Pattern = [(PPCmtctr G8RC:$rS)], Defs = [CTR8] in { +def MTCTR8 : XFXForm_7_ext<31, 467, 9, (outs), (ins G8RC:$rS), + "mtctr $rS", SprMTSPR>, + PPC970_DGroup_First, PPC970_Unit_FXU; +} + +let Defs = [X1], Uses = [X1] in +def DYNALLOC8 : Pseudo<(outs G8RC:$result), (ins G8RC:$negsize, memri:$fpsi), + "${:comment} DYNALLOC8 $result, $negsize, $fpsi", + [(set G8RC:$result, + (PPCdynalloc G8RC:$negsize, iaddr:$fpsi))]>; + +let Defs = [LR8] in { +def MTLR8 : XFXForm_7_ext<31, 467, 8, (outs), (ins G8RC:$rS), + "mtlr $rS", SprMTSPR>, + PPC970_DGroup_First, PPC970_Unit_FXU; +} +let Uses = [LR8] in { +def MFLR8 : XFXForm_1_ext<31, 339, 8, (outs G8RC:$rT), (ins), + "mflr $rT", SprMFSPR>, + PPC970_DGroup_First, PPC970_Unit_FXU; +} + +//===----------------------------------------------------------------------===// +// Fixed point instructions. +// + +let PPC970_Unit = 1 in { // FXU Operations. + +// Copies, extends, truncates. +def OR4To8 : XForm_6<31, 444, (outs G8RC:$rA), (ins GPRC:$rS, GPRC:$rB), + "or $rA, $rS, $rB", IntGeneral, + []>; +def OR8To4 : XForm_6<31, 444, (outs GPRC:$rA), (ins G8RC:$rS, G8RC:$rB), + "or $rA, $rS, $rB", IntGeneral, + []>; + +def LI8 : DForm_2_r0<14, (outs G8RC:$rD), (ins symbolLo64:$imm), + "li $rD, $imm", IntGeneral, + [(set G8RC:$rD, immSExt16:$imm)]>; +def LIS8 : DForm_2_r0<15, (outs G8RC:$rD), (ins symbolHi64:$imm), + "lis $rD, $imm", IntGeneral, + [(set G8RC:$rD, imm16ShiftedSExt:$imm)]>; + +// Logical ops. +def NAND8: XForm_6<31, 476, (outs G8RC:$rA), (ins G8RC:$rS, G8RC:$rB), + "nand $rA, $rS, $rB", IntGeneral, + [(set G8RC:$rA, (not (and G8RC:$rS, G8RC:$rB)))]>; +def AND8 : XForm_6<31, 28, (outs G8RC:$rA), (ins G8RC:$rS, G8RC:$rB), + "and $rA, $rS, $rB", IntGeneral, + [(set G8RC:$rA, (and G8RC:$rS, G8RC:$rB))]>; +def ANDC8: XForm_6<31, 60, (outs G8RC:$rA), (ins G8RC:$rS, G8RC:$rB), + "andc $rA, $rS, $rB", IntGeneral, + [(set G8RC:$rA, (and G8RC:$rS, (not G8RC:$rB)))]>; +def OR8 : XForm_6<31, 444, (outs G8RC:$rA), (ins G8RC:$rS, G8RC:$rB), + "or $rA, $rS, $rB", IntGeneral, + [(set G8RC:$rA, (or G8RC:$rS, G8RC:$rB))]>; +def NOR8 : XForm_6<31, 124, (outs G8RC:$rA), (ins G8RC:$rS, G8RC:$rB), + "nor $rA, $rS, $rB", IntGeneral, + [(set G8RC:$rA, (not (or G8RC:$rS, G8RC:$rB)))]>; +def ORC8 : XForm_6<31, 412, (outs G8RC:$rA), (ins G8RC:$rS, G8RC:$rB), + "orc $rA, $rS, $rB", IntGeneral, + [(set G8RC:$rA, (or G8RC:$rS, (not G8RC:$rB)))]>; +def EQV8 : XForm_6<31, 284, (outs G8RC:$rA), (ins G8RC:$rS, G8RC:$rB), + "eqv $rA, $rS, $rB", IntGeneral, + [(set G8RC:$rA, (not (xor G8RC:$rS, G8RC:$rB)))]>; +def XOR8 : XForm_6<31, 316, (outs G8RC:$rA), (ins G8RC:$rS, G8RC:$rB), + "xor $rA, $rS, $rB", IntGeneral, + [(set G8RC:$rA, (xor G8RC:$rS, G8RC:$rB))]>; + +// Logical ops with immediate. +def ANDIo8 : DForm_4<28, (outs G8RC:$dst), (ins G8RC:$src1, u16imm:$src2), + "andi. $dst, $src1, $src2", IntGeneral, + [(set G8RC:$dst, (and G8RC:$src1, immZExt16:$src2))]>, + isDOT; +def ANDISo8 : DForm_4<29, (outs G8RC:$dst), (ins G8RC:$src1, u16imm:$src2), + "andis. $dst, $src1, $src2", IntGeneral, + [(set G8RC:$dst, (and G8RC:$src1,imm16ShiftedZExt:$src2))]>, + isDOT; +def ORI8 : DForm_4<24, (outs G8RC:$dst), (ins G8RC:$src1, u16imm:$src2), + "ori $dst, $src1, $src2", IntGeneral, + [(set G8RC:$dst, (or G8RC:$src1, immZExt16:$src2))]>; +def ORIS8 : DForm_4<25, (outs G8RC:$dst), (ins G8RC:$src1, u16imm:$src2), + "oris $dst, $src1, $src2", IntGeneral, + [(set G8RC:$dst, (or G8RC:$src1, imm16ShiftedZExt:$src2))]>; +def XORI8 : DForm_4<26, (outs G8RC:$dst), (ins G8RC:$src1, u16imm:$src2), + "xori $dst, $src1, $src2", IntGeneral, + [(set G8RC:$dst, (xor G8RC:$src1, immZExt16:$src2))]>; +def XORIS8 : DForm_4<27, (outs G8RC:$dst), (ins G8RC:$src1, u16imm:$src2), + "xoris $dst, $src1, $src2", IntGeneral, + [(set G8RC:$dst, (xor G8RC:$src1, imm16ShiftedZExt:$src2))]>; + +def ADD8 : XOForm_1<31, 266, 0, (outs G8RC:$rT), (ins G8RC:$rA, G8RC:$rB), + "add $rT, $rA, $rB", IntGeneral, + [(set G8RC:$rT, (add G8RC:$rA, G8RC:$rB))]>; + +let Defs = [CARRY] in { +def ADDC8 : XOForm_1<31, 10, 0, (outs G8RC:$rT), (ins G8RC:$rA, G8RC:$rB), + "addc $rT, $rA, $rB", IntGeneral, + [(set G8RC:$rT, (addc G8RC:$rA, G8RC:$rB))]>, + PPC970_DGroup_Cracked; +def ADDIC8 : DForm_2<12, (outs G8RC:$rD), (ins G8RC:$rA, s16imm64:$imm), + "addic $rD, $rA, $imm", IntGeneral, + [(set G8RC:$rD, (addc G8RC:$rA, immSExt16:$imm))]>; +} +def ADDI8 : DForm_2<14, (outs G8RC:$rD), (ins G8RC:$rA, s16imm64:$imm), + "addi $rD, $rA, $imm", IntGeneral, + [(set G8RC:$rD, (add G8RC:$rA, immSExt16:$imm))]>; +def ADDIS8 : DForm_2<15, (outs G8RC:$rD), (ins G8RC:$rA, symbolHi64:$imm), + "addis $rD, $rA, $imm", IntGeneral, + [(set G8RC:$rD, (add G8RC:$rA, imm16ShiftedSExt:$imm))]>; + +let Defs = [CARRY] in { +def SUBFIC8: DForm_2< 8, (outs G8RC:$rD), (ins G8RC:$rA, s16imm64:$imm), + "subfic $rD, $rA, $imm", IntGeneral, + [(set G8RC:$rD, (subc immSExt16:$imm, G8RC:$rA))]>; +def SUBFC8 : XOForm_1<31, 8, 0, (outs G8RC:$rT), (ins G8RC:$rA, G8RC:$rB), + "subfc $rT, $rA, $rB", IntGeneral, + [(set G8RC:$rT, (subc G8RC:$rB, G8RC:$rA))]>, + PPC970_DGroup_Cracked; +} +def SUBF8 : XOForm_1<31, 40, 0, (outs G8RC:$rT), (ins G8RC:$rA, G8RC:$rB), + "subf $rT, $rA, $rB", IntGeneral, + [(set G8RC:$rT, (sub G8RC:$rB, G8RC:$rA))]>; +def NEG8 : XOForm_3<31, 104, 0, (outs G8RC:$rT), (ins G8RC:$rA), + "neg $rT, $rA", IntGeneral, + [(set G8RC:$rT, (ineg G8RC:$rA))]>; +let Uses = [CARRY], Defs = [CARRY] in { +def ADDE8 : XOForm_1<31, 138, 0, (outs G8RC:$rT), (ins G8RC:$rA, G8RC:$rB), + "adde $rT, $rA, $rB", IntGeneral, + [(set G8RC:$rT, (adde G8RC:$rA, G8RC:$rB))]>; +def ADDME8 : XOForm_3<31, 234, 0, (outs G8RC:$rT), (ins G8RC:$rA), + "addme $rT, $rA", IntGeneral, + [(set G8RC:$rT, (adde G8RC:$rA, immAllOnes))]>; +def ADDZE8 : XOForm_3<31, 202, 0, (outs G8RC:$rT), (ins G8RC:$rA), + "addze $rT, $rA", IntGeneral, + [(set G8RC:$rT, (adde G8RC:$rA, 0))]>; +def SUBFE8 : XOForm_1<31, 136, 0, (outs G8RC:$rT), (ins G8RC:$rA, G8RC:$rB), + "subfe $rT, $rA, $rB", IntGeneral, + [(set G8RC:$rT, (sube G8RC:$rB, G8RC:$rA))]>; +def SUBFME8 : XOForm_3<31, 232, 0, (outs G8RC:$rT), (ins G8RC:$rA), + "subfme $rT, $rA", IntGeneral, + [(set G8RC:$rT, (sube immAllOnes, G8RC:$rA))]>; +def SUBFZE8 : XOForm_3<31, 200, 0, (outs G8RC:$rT), (ins G8RC:$rA), + "subfze $rT, $rA", IntGeneral, + [(set G8RC:$rT, (sube 0, G8RC:$rA))]>; +} + + +def MULHD : XOForm_1<31, 73, 0, (outs G8RC:$rT), (ins G8RC:$rA, G8RC:$rB), + "mulhd $rT, $rA, $rB", IntMulHW, + [(set G8RC:$rT, (mulhs G8RC:$rA, G8RC:$rB))]>; +def MULHDU : XOForm_1<31, 9, 0, (outs G8RC:$rT), (ins G8RC:$rA, G8RC:$rB), + "mulhdu $rT, $rA, $rB", IntMulHWU, + [(set G8RC:$rT, (mulhu G8RC:$rA, G8RC:$rB))]>; + +def CMPD : XForm_16_ext<31, 0, (outs CRRC:$crD), (ins G8RC:$rA, G8RC:$rB), + "cmpd $crD, $rA, $rB", IntCompare>, isPPC64; +def CMPLD : XForm_16_ext<31, 32, (outs CRRC:$crD), (ins G8RC:$rA, G8RC:$rB), + "cmpld $crD, $rA, $rB", IntCompare>, isPPC64; +def CMPDI : DForm_5_ext<11, (outs CRRC:$crD), (ins G8RC:$rA, s16imm:$imm), + "cmpdi $crD, $rA, $imm", IntCompare>, isPPC64; +def CMPLDI : DForm_6_ext<10, (outs CRRC:$dst), (ins G8RC:$src1, u16imm:$src2), + "cmpldi $dst, $src1, $src2", IntCompare>, isPPC64; + +def SLD : XForm_6<31, 27, (outs G8RC:$rA), (ins G8RC:$rS, GPRC:$rB), + "sld $rA, $rS, $rB", IntRotateD, + [(set G8RC:$rA, (PPCshl G8RC:$rS, GPRC:$rB))]>, isPPC64; +def SRD : XForm_6<31, 539, (outs G8RC:$rA), (ins G8RC:$rS, GPRC:$rB), + "srd $rA, $rS, $rB", IntRotateD, + [(set G8RC:$rA, (PPCsrl G8RC:$rS, GPRC:$rB))]>, isPPC64; +let Defs = [CARRY] in { +def SRAD : XForm_6<31, 794, (outs G8RC:$rA), (ins G8RC:$rS, GPRC:$rB), + "srad $rA, $rS, $rB", IntRotateD, + [(set G8RC:$rA, (PPCsra G8RC:$rS, GPRC:$rB))]>, isPPC64; +} + +def EXTSB8 : XForm_11<31, 954, (outs G8RC:$rA), (ins G8RC:$rS), + "extsb $rA, $rS", IntGeneral, + [(set G8RC:$rA, (sext_inreg G8RC:$rS, i8))]>; +def EXTSH8 : XForm_11<31, 922, (outs G8RC:$rA), (ins G8RC:$rS), + "extsh $rA, $rS", IntGeneral, + [(set G8RC:$rA, (sext_inreg G8RC:$rS, i16))]>; + +def EXTSW : XForm_11<31, 986, (outs G8RC:$rA), (ins G8RC:$rS), + "extsw $rA, $rS", IntGeneral, + [(set G8RC:$rA, (sext_inreg G8RC:$rS, i32))]>, isPPC64; +/// EXTSW_32 - Just like EXTSW, but works on '32-bit' registers. +def EXTSW_32 : XForm_11<31, 986, (outs GPRC:$rA), (ins GPRC:$rS), + "extsw $rA, $rS", IntGeneral, + [(set GPRC:$rA, (PPCextsw_32 GPRC:$rS))]>, isPPC64; +def EXTSW_32_64 : XForm_11<31, 986, (outs G8RC:$rA), (ins GPRC:$rS), + "extsw $rA, $rS", IntGeneral, + [(set G8RC:$rA, (sext GPRC:$rS))]>, isPPC64; + +let Defs = [CARRY] in { +def SRADI : XSForm_1<31, 413, (outs G8RC:$rA), (ins G8RC:$rS, u6imm:$SH), + "sradi $rA, $rS, $SH", IntRotateD, + [(set G8RC:$rA, (sra G8RC:$rS, (i32 imm:$SH)))]>, isPPC64; +} +def CNTLZD : XForm_11<31, 58, (outs G8RC:$rA), (ins G8RC:$rS), + "cntlzd $rA, $rS", IntGeneral, + [(set G8RC:$rA, (ctlz G8RC:$rS))]>; + +def DIVD : XOForm_1<31, 489, 0, (outs G8RC:$rT), (ins G8RC:$rA, G8RC:$rB), + "divd $rT, $rA, $rB", IntDivD, + [(set G8RC:$rT, (sdiv G8RC:$rA, G8RC:$rB))]>, isPPC64, + PPC970_DGroup_First, PPC970_DGroup_Cracked; +def DIVDU : XOForm_1<31, 457, 0, (outs G8RC:$rT), (ins G8RC:$rA, G8RC:$rB), + "divdu $rT, $rA, $rB", IntDivD, + [(set G8RC:$rT, (udiv G8RC:$rA, G8RC:$rB))]>, isPPC64, + PPC970_DGroup_First, PPC970_DGroup_Cracked; +def MULLD : XOForm_1<31, 233, 0, (outs G8RC:$rT), (ins G8RC:$rA, G8RC:$rB), + "mulld $rT, $rA, $rB", IntMulHD, + [(set G8RC:$rT, (mul G8RC:$rA, G8RC:$rB))]>, isPPC64; + + +let isCommutable = 1 in { +def RLDIMI : MDForm_1<30, 3, + (outs G8RC:$rA), (ins G8RC:$rSi, G8RC:$rS, u6imm:$SH, u6imm:$MB), + "rldimi $rA, $rS, $SH, $MB", IntRotateD, + []>, isPPC64, RegConstraint<"$rSi = $rA">, + NoEncode<"$rSi">; +} + +// Rotate instructions. +def RLDCL : MDForm_1<30, 0, + (outs G8RC:$rA), (ins G8RC:$rS, GPRC:$rB, u6imm:$MB), + "rldcl $rA, $rS, $rB, $MB", IntRotateD, + []>, isPPC64; +def RLDICL : MDForm_1<30, 0, + (outs G8RC:$rA), (ins G8RC:$rS, u6imm:$SH, u6imm:$MB), + "rldicl $rA, $rS, $SH, $MB", IntRotateD, + []>, isPPC64; +def RLDICR : MDForm_1<30, 1, + (outs G8RC:$rA), (ins G8RC:$rS, u6imm:$SH, u6imm:$ME), + "rldicr $rA, $rS, $SH, $ME", IntRotateD, + []>, isPPC64; +} // End FXU Operations. + + +//===----------------------------------------------------------------------===// +// Load/Store instructions. +// + + +// Sign extending loads. +let canFoldAsLoad = 1, PPC970_Unit = 2 in { +def LHA8: DForm_1<42, (outs G8RC:$rD), (ins memri:$src), + "lha $rD, $src", LdStLHA, + [(set G8RC:$rD, (sextloadi16 iaddr:$src))]>, + PPC970_DGroup_Cracked; +def LWA : DSForm_1<58, 2, (outs G8RC:$rD), (ins memrix:$src), + "lwa $rD, $src", LdStLWA, + [(set G8RC:$rD, (sextloadi32 ixaddr:$src))]>, isPPC64, + PPC970_DGroup_Cracked; +def LHAX8: XForm_1<31, 343, (outs G8RC:$rD), (ins memrr:$src), + "lhax $rD, $src", LdStLHA, + [(set G8RC:$rD, (sextloadi16 xaddr:$src))]>, + PPC970_DGroup_Cracked; +def LWAX : XForm_1<31, 341, (outs G8RC:$rD), (ins memrr:$src), + "lwax $rD, $src", LdStLHA, + [(set G8RC:$rD, (sextloadi32 xaddr:$src))]>, isPPC64, + PPC970_DGroup_Cracked; + +// Update forms. +let mayLoad = 1 in +def LHAU8 : DForm_1<43, (outs G8RC:$rD, ptr_rc:$ea_result), (ins symbolLo:$disp, + ptr_rc:$rA), + "lhau $rD, $disp($rA)", LdStGeneral, + []>, RegConstraint<"$rA = $ea_result">, + NoEncode<"$ea_result">; +// NO LWAU! + +} + +// Zero extending loads. +let canFoldAsLoad = 1, PPC970_Unit = 2 in { +def LBZ8 : DForm_1<34, (outs G8RC:$rD), (ins memri:$src), + "lbz $rD, $src", LdStGeneral, + [(set G8RC:$rD, (zextloadi8 iaddr:$src))]>; +def LHZ8 : DForm_1<40, (outs G8RC:$rD), (ins memri:$src), + "lhz $rD, $src", LdStGeneral, + [(set G8RC:$rD, (zextloadi16 iaddr:$src))]>; +def LWZ8 : DForm_1<32, (outs G8RC:$rD), (ins memri:$src), + "lwz $rD, $src", LdStGeneral, + [(set G8RC:$rD, (zextloadi32 iaddr:$src))]>, isPPC64; + +def LBZX8 : XForm_1<31, 87, (outs G8RC:$rD), (ins memrr:$src), + "lbzx $rD, $src", LdStGeneral, + [(set G8RC:$rD, (zextloadi8 xaddr:$src))]>; +def LHZX8 : XForm_1<31, 279, (outs G8RC:$rD), (ins memrr:$src), + "lhzx $rD, $src", LdStGeneral, + [(set G8RC:$rD, (zextloadi16 xaddr:$src))]>; +def LWZX8 : XForm_1<31, 23, (outs G8RC:$rD), (ins memrr:$src), + "lwzx $rD, $src", LdStGeneral, + [(set G8RC:$rD, (zextloadi32 xaddr:$src))]>; + + +// Update forms. +let mayLoad = 1 in { +def LBZU8 : DForm_1<35, (outs G8RC:$rD, ptr_rc:$ea_result), (ins memri:$addr), + "lbzu $rD, $addr", LdStGeneral, + []>, RegConstraint<"$addr.reg = $ea_result">, + NoEncode<"$ea_result">; +def LHZU8 : DForm_1<41, (outs G8RC:$rD, ptr_rc:$ea_result), (ins memri:$addr), + "lhzu $rD, $addr", LdStGeneral, + []>, RegConstraint<"$addr.reg = $ea_result">, + NoEncode<"$ea_result">; +def LWZU8 : DForm_1<33, (outs G8RC:$rD, ptr_rc:$ea_result), (ins memri:$addr), + "lwzu $rD, $addr", LdStGeneral, + []>, RegConstraint<"$addr.reg = $ea_result">, + NoEncode<"$ea_result">; +} +} + + +// Full 8-byte loads. +let canFoldAsLoad = 1, PPC970_Unit = 2 in { +def LD : DSForm_1<58, 0, (outs G8RC:$rD), (ins memrix:$src), + "ld $rD, $src", LdStLD, + [(set G8RC:$rD, (load ixaddr:$src))]>, isPPC64; +def LDtoc: DSForm_1<58, 0, (outs G8RC:$rD), (ins tocentry:$disp, G8RC:$reg), + "ld $rD, $disp($reg)", LdStLD, + [(set G8RC:$rD, + (PPCtoc_entry tglobaladdr:$disp, G8RC:$reg))]>, isPPC64; +def LDX : XForm_1<31, 21, (outs G8RC:$rD), (ins memrr:$src), + "ldx $rD, $src", LdStLD, + [(set G8RC:$rD, (load xaddr:$src))]>, isPPC64; + +let mayLoad = 1 in +def LDU : DSForm_1<58, 1, (outs G8RC:$rD, ptr_rc:$ea_result), (ins memrix:$addr), + "ldu $rD, $addr", LdStLD, + []>, RegConstraint<"$addr.reg = $ea_result">, isPPC64, + NoEncode<"$ea_result">; + +} + +let PPC970_Unit = 2 in { +// Truncating stores. +def STB8 : DForm_1<38, (outs), (ins G8RC:$rS, memri:$src), + "stb $rS, $src", LdStGeneral, + [(truncstorei8 G8RC:$rS, iaddr:$src)]>; +def STH8 : DForm_1<44, (outs), (ins G8RC:$rS, memri:$src), + "sth $rS, $src", LdStGeneral, + [(truncstorei16 G8RC:$rS, iaddr:$src)]>; +def STW8 : DForm_1<36, (outs), (ins G8RC:$rS, memri:$src), + "stw $rS, $src", LdStGeneral, + [(truncstorei32 G8RC:$rS, iaddr:$src)]>; +def STBX8 : XForm_8<31, 215, (outs), (ins G8RC:$rS, memrr:$dst), + "stbx $rS, $dst", LdStGeneral, + [(truncstorei8 G8RC:$rS, xaddr:$dst)]>, + PPC970_DGroup_Cracked; +def STHX8 : XForm_8<31, 407, (outs), (ins G8RC:$rS, memrr:$dst), + "sthx $rS, $dst", LdStGeneral, + [(truncstorei16 G8RC:$rS, xaddr:$dst)]>, + PPC970_DGroup_Cracked; +def STWX8 : XForm_8<31, 151, (outs), (ins G8RC:$rS, memrr:$dst), + "stwx $rS, $dst", LdStGeneral, + [(truncstorei32 G8RC:$rS, xaddr:$dst)]>, + PPC970_DGroup_Cracked; +// Normal 8-byte stores. +def STD : DSForm_1<62, 0, (outs), (ins G8RC:$rS, memrix:$dst), + "std $rS, $dst", LdStSTD, + [(store G8RC:$rS, ixaddr:$dst)]>, isPPC64; +def STDX : XForm_8<31, 149, (outs), (ins G8RC:$rS, memrr:$dst), + "stdx $rS, $dst", LdStSTD, + [(store G8RC:$rS, xaddr:$dst)]>, isPPC64, + PPC970_DGroup_Cracked; +} + +let PPC970_Unit = 2 in { + +def STBU8 : DForm_1<38, (outs ptr_rc:$ea_res), (ins G8RC:$rS, + symbolLo:$ptroff, ptr_rc:$ptrreg), + "stbu $rS, $ptroff($ptrreg)", LdStGeneral, + [(set ptr_rc:$ea_res, + (pre_truncsti8 G8RC:$rS, ptr_rc:$ptrreg, + iaddroff:$ptroff))]>, + RegConstraint<"$ptrreg = $ea_res">, NoEncode<"$ea_res">; +def STHU8 : DForm_1<45, (outs ptr_rc:$ea_res), (ins G8RC:$rS, + symbolLo:$ptroff, ptr_rc:$ptrreg), + "sthu $rS, $ptroff($ptrreg)", LdStGeneral, + [(set ptr_rc:$ea_res, + (pre_truncsti16 G8RC:$rS, ptr_rc:$ptrreg, + iaddroff:$ptroff))]>, + RegConstraint<"$ptrreg = $ea_res">, NoEncode<"$ea_res">; +def STWU8 : DForm_1<37, (outs ptr_rc:$ea_res), (ins G8RC:$rS, + symbolLo:$ptroff, ptr_rc:$ptrreg), + "stwu $rS, $ptroff($ptrreg)", LdStGeneral, + [(set ptr_rc:$ea_res, (pre_store G8RC:$rS, ptr_rc:$ptrreg, + iaddroff:$ptroff))]>, + RegConstraint<"$ptrreg = $ea_res">, NoEncode<"$ea_res">; + + +def STDU : DSForm_1<62, 1, (outs ptr_rc:$ea_res), (ins G8RC:$rS, + s16immX4:$ptroff, ptr_rc:$ptrreg), + "stdu $rS, $ptroff($ptrreg)", LdStSTD, + [(set ptr_rc:$ea_res, (pre_store G8RC:$rS, ptr_rc:$ptrreg, + iaddroff:$ptroff))]>, + RegConstraint<"$ptrreg = $ea_res">, NoEncode<"$ea_res">, + isPPC64; + +let mayStore = 1 in +def STDUX : XForm_8<31, 181, (outs), (ins G8RC:$rS, memrr:$dst), + "stdux $rS, $dst", LdStSTD, + []>, isPPC64; + +// STD_32/STDX_32 - Just like STD/STDX, but uses a '32-bit' input register. +def STD_32 : DSForm_1<62, 0, (outs), (ins GPRC:$rT, memrix:$dst), + "std $rT, $dst", LdStSTD, + [(PPCstd_32 GPRC:$rT, ixaddr:$dst)]>, isPPC64; +def STDX_32 : XForm_8<31, 149, (outs), (ins GPRC:$rT, memrr:$dst), + "stdx $rT, $dst", LdStSTD, + [(PPCstd_32 GPRC:$rT, xaddr:$dst)]>, isPPC64, + PPC970_DGroup_Cracked; +} + + + +//===----------------------------------------------------------------------===// +// Floating point instructions. +// + + +let PPC970_Unit = 3, Uses = [RM] in { // FPU Operations. +def FCFID : XForm_26<63, 846, (outs F8RC:$frD), (ins F8RC:$frB), + "fcfid $frD, $frB", FPGeneral, + [(set F8RC:$frD, (PPCfcfid F8RC:$frB))]>, isPPC64; +def FCTIDZ : XForm_26<63, 815, (outs F8RC:$frD), (ins F8RC:$frB), + "fctidz $frD, $frB", FPGeneral, + [(set F8RC:$frD, (PPCfctidz F8RC:$frB))]>, isPPC64; +} + + +//===----------------------------------------------------------------------===// +// Instruction Patterns +// + +// Extensions and truncates to/from 32-bit regs. +def : Pat<(i64 (zext GPRC:$in)), + (RLDICL (OR4To8 GPRC:$in, GPRC:$in), 0, 32)>; +def : Pat<(i64 (anyext GPRC:$in)), + (OR4To8 GPRC:$in, GPRC:$in)>; +def : Pat<(i32 (trunc G8RC:$in)), + (OR8To4 G8RC:$in, G8RC:$in)>; + +// Extending loads with i64 targets. +def : Pat<(zextloadi1 iaddr:$src), + (LBZ8 iaddr:$src)>; +def : Pat<(zextloadi1 xaddr:$src), + (LBZX8 xaddr:$src)>; +def : Pat<(extloadi1 iaddr:$src), + (LBZ8 iaddr:$src)>; +def : Pat<(extloadi1 xaddr:$src), + (LBZX8 xaddr:$src)>; +def : Pat<(extloadi8 iaddr:$src), + (LBZ8 iaddr:$src)>; +def : Pat<(extloadi8 xaddr:$src), + (LBZX8 xaddr:$src)>; +def : Pat<(extloadi16 iaddr:$src), + (LHZ8 iaddr:$src)>; +def : Pat<(extloadi16 xaddr:$src), + (LHZX8 xaddr:$src)>; +def : Pat<(extloadi32 iaddr:$src), + (LWZ8 iaddr:$src)>; +def : Pat<(extloadi32 xaddr:$src), + (LWZX8 xaddr:$src)>; + +// Standard shifts. These are represented separately from the real shifts above +// so that we can distinguish between shifts that allow 6-bit and 7-bit shift +// amounts. +def : Pat<(sra G8RC:$rS, GPRC:$rB), + (SRAD G8RC:$rS, GPRC:$rB)>; +def : Pat<(srl G8RC:$rS, GPRC:$rB), + (SRD G8RC:$rS, GPRC:$rB)>; +def : Pat<(shl G8RC:$rS, GPRC:$rB), + (SLD G8RC:$rS, GPRC:$rB)>; + +// SHL/SRL +def : Pat<(shl G8RC:$in, (i32 imm:$imm)), + (RLDICR G8RC:$in, imm:$imm, (SHL64 imm:$imm))>; +def : Pat<(srl G8RC:$in, (i32 imm:$imm)), + (RLDICL G8RC:$in, (SRL64 imm:$imm), imm:$imm)>; + +// ROTL +def : Pat<(rotl G8RC:$in, GPRC:$sh), + (RLDCL G8RC:$in, GPRC:$sh, 0)>; +def : Pat<(rotl G8RC:$in, (i32 imm:$imm)), + (RLDICL G8RC:$in, imm:$imm, 0)>; + +// Hi and Lo for Darwin Global Addresses. +def : Pat<(PPChi tglobaladdr:$in, 0), (LIS8 tglobaladdr:$in)>; +def : Pat<(PPClo tglobaladdr:$in, 0), (LI8 tglobaladdr:$in)>; +def : Pat<(PPChi tconstpool:$in , 0), (LIS8 tconstpool:$in)>; +def : Pat<(PPClo tconstpool:$in , 0), (LI8 tconstpool:$in)>; +def : Pat<(PPChi tjumptable:$in , 0), (LIS8 tjumptable:$in)>; +def : Pat<(PPClo tjumptable:$in , 0), (LI8 tjumptable:$in)>; +def : Pat<(PPChi tblockaddress:$in, 0), (LIS8 tblockaddress:$in)>; +def : Pat<(PPClo tblockaddress:$in, 0), (LI8 tblockaddress:$in)>; +def : Pat<(add G8RC:$in, (PPChi tglobaladdr:$g, 0)), + (ADDIS8 G8RC:$in, tglobaladdr:$g)>; +def : Pat<(add G8RC:$in, (PPChi tconstpool:$g, 0)), + (ADDIS8 G8RC:$in, tconstpool:$g)>; +def : Pat<(add G8RC:$in, (PPChi tjumptable:$g, 0)), + (ADDIS8 G8RC:$in, tjumptable:$g)>; +def : Pat<(add G8RC:$in, (PPChi tblockaddress:$g, 0)), + (ADDIS8 G8RC:$in, tblockaddress:$g)>; diff --git a/libclamav/c++/llvm/lib/Target/PowerPC/PPCInstrAltivec.td b/libclamav/c++/llvm/lib/Target/PowerPC/PPCInstrAltivec.td new file mode 100644 index 000000000..3f4d3296b --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/PowerPC/PPCInstrAltivec.td @@ -0,0 +1,690 @@ +//===- PPCInstrAltivec.td - The PowerPC Altivec Extension --*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file describes the Altivec extension to the PowerPC instruction set. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// Altivec transformation functions and pattern fragments. +// + + +def vpkuhum_shuffle : PatFrag<(ops node:$lhs, node:$rhs), + (vector_shuffle node:$lhs, node:$rhs), [{ + return PPC::isVPKUHUMShuffleMask(cast(N), false); +}]>; +def vpkuwum_shuffle : PatFrag<(ops node:$lhs, node:$rhs), + (vector_shuffle node:$lhs, node:$rhs), [{ + return PPC::isVPKUWUMShuffleMask(cast(N), false); +}]>; +def vpkuhum_unary_shuffle : PatFrag<(ops node:$lhs, node:$rhs), + (vector_shuffle node:$lhs, node:$rhs), [{ + return PPC::isVPKUHUMShuffleMask(cast(N), true); +}]>; +def vpkuwum_unary_shuffle : PatFrag<(ops node:$lhs, node:$rhs), + (vector_shuffle node:$lhs, node:$rhs), [{ + return PPC::isVPKUWUMShuffleMask(cast(N), true); +}]>; + + +def vmrglb_shuffle : PatFrag<(ops node:$lhs, node:$rhs), + (vector_shuffle node:$lhs, node:$rhs), [{ + return PPC::isVMRGLShuffleMask(cast(N), 1, false); +}]>; +def vmrglh_shuffle : PatFrag<(ops node:$lhs, node:$rhs), + (vector_shuffle node:$lhs, node:$rhs), [{ + return PPC::isVMRGLShuffleMask(cast(N), 2, false); +}]>; +def vmrglw_shuffle : PatFrag<(ops node:$lhs, node:$rhs), + (vector_shuffle node:$lhs, node:$rhs), [{ + return PPC::isVMRGLShuffleMask(cast(N), 4, false); +}]>; +def vmrghb_shuffle : PatFrag<(ops node:$lhs, node:$rhs), + (vector_shuffle node:$lhs, node:$rhs), [{ + return PPC::isVMRGHShuffleMask(cast(N), 1, false); +}]>; +def vmrghh_shuffle : PatFrag<(ops node:$lhs, node:$rhs), + (vector_shuffle node:$lhs, node:$rhs), [{ + return PPC::isVMRGHShuffleMask(cast(N), 2, false); +}]>; +def vmrghw_shuffle : PatFrag<(ops node:$lhs, node:$rhs), + (vector_shuffle node:$lhs, node:$rhs), [{ + return PPC::isVMRGHShuffleMask(cast(N), 4, false); +}]>; + + +def vmrglb_unary_shuffle : PatFrag<(ops node:$lhs, node:$rhs), + (vector_shuffle node:$lhs, node:$rhs), [{ + return PPC::isVMRGLShuffleMask(cast(N), 1, true); +}]>; +def vmrglh_unary_shuffle : PatFrag<(ops node:$lhs, node:$rhs), + (vector_shuffle node:$lhs, node:$rhs), [{ + return PPC::isVMRGLShuffleMask(cast(N), 2, true); +}]>; +def vmrglw_unary_shuffle : PatFrag<(ops node:$lhs, node:$rhs), + (vector_shuffle node:$lhs, node:$rhs), [{ + return PPC::isVMRGLShuffleMask(cast(N), 4, true); +}]>; +def vmrghb_unary_shuffle : PatFrag<(ops node:$lhs, node:$rhs), + (vector_shuffle node:$lhs, node:$rhs), [{ + return PPC::isVMRGHShuffleMask(cast(N), 1, true); +}]>; +def vmrghh_unary_shuffle : PatFrag<(ops node:$lhs, node:$rhs), + (vector_shuffle node:$lhs, node:$rhs), [{ + return PPC::isVMRGHShuffleMask(cast(N), 2, true); +}]>; +def vmrghw_unary_shuffle : PatFrag<(ops node:$lhs, node:$rhs), + (vector_shuffle node:$lhs, node:$rhs), [{ + return PPC::isVMRGHShuffleMask(cast(N), 4, true); +}]>; + + +def VSLDOI_get_imm : SDNodeXForm; +def vsldoi_shuffle : PatFrag<(ops node:$lhs, node:$rhs), + (vector_shuffle node:$lhs, node:$rhs), [{ + return PPC::isVSLDOIShuffleMask(N, false) != -1; +}], VSLDOI_get_imm>; + + +/// VSLDOI_unary* - These are used to match vsldoi(X,X), which is turned into +/// vector_shuffle(X,undef,mask) by the dag combiner. +def VSLDOI_unary_get_imm : SDNodeXForm; +def vsldoi_unary_shuffle : PatFrag<(ops node:$lhs, node:$rhs), + (vector_shuffle node:$lhs, node:$rhs), [{ + return PPC::isVSLDOIShuffleMask(N, true) != -1; +}], VSLDOI_unary_get_imm>; + + +// VSPLT*_get_imm xform function: convert vector_shuffle mask to VSPLT* imm. +def VSPLTB_get_imm : SDNodeXForm; +def vspltb_shuffle : PatFrag<(ops node:$lhs, node:$rhs), + (vector_shuffle node:$lhs, node:$rhs), [{ + return PPC::isSplatShuffleMask(cast(N), 1); +}], VSPLTB_get_imm>; +def VSPLTH_get_imm : SDNodeXForm; +def vsplth_shuffle : PatFrag<(ops node:$lhs, node:$rhs), + (vector_shuffle node:$lhs, node:$rhs), [{ + return PPC::isSplatShuffleMask(cast(N), 2); +}], VSPLTH_get_imm>; +def VSPLTW_get_imm : SDNodeXForm; +def vspltw_shuffle : PatFrag<(ops node:$lhs, node:$rhs), + (vector_shuffle node:$lhs, node:$rhs), [{ + return PPC::isSplatShuffleMask(cast(N), 4); +}], VSPLTW_get_imm>; + + +// VSPLTISB_get_imm xform function: convert build_vector to VSPLTISB imm. +def VSPLTISB_get_imm : SDNodeXForm; +def vecspltisb : PatLeaf<(build_vector), [{ + return PPC::get_VSPLTI_elt(N, 1, *CurDAG).getNode() != 0; +}], VSPLTISB_get_imm>; + +// VSPLTISH_get_imm xform function: convert build_vector to VSPLTISH imm. +def VSPLTISH_get_imm : SDNodeXForm; +def vecspltish : PatLeaf<(build_vector), [{ + return PPC::get_VSPLTI_elt(N, 2, *CurDAG).getNode() != 0; +}], VSPLTISH_get_imm>; + +// VSPLTISW_get_imm xform function: convert build_vector to VSPLTISW imm. +def VSPLTISW_get_imm : SDNodeXForm; +def vecspltisw : PatLeaf<(build_vector), [{ + return PPC::get_VSPLTI_elt(N, 4, *CurDAG).getNode() != 0; +}], VSPLTISW_get_imm>; + +def V_immneg0 : PatLeaf<(build_vector), [{ + return PPC::isAllNegativeZeroVector(N); +}]>; + +//===----------------------------------------------------------------------===// +// Helpers for defining instructions that directly correspond to intrinsics. + +// VA1a_Int - A VAForm_1a intrinsic definition. +class VA1a_Int xo, string opc, Intrinsic IntID> + : VAForm_1a; + +// VX1_Int - A VXForm_1 intrinsic definition. +class VX1_Int xo, string opc, Intrinsic IntID> + : VXForm_1; + +// VX2_Int - A VXForm_2 intrinsic definition. +class VX2_Int xo, string opc, Intrinsic IntID> + : VXForm_2; + +//===----------------------------------------------------------------------===// +// Instruction Definitions. + +def DSS : DSS_Form<822, (outs), + (ins u5imm:$ZERO0, u5imm:$STRM,u5imm:$ZERO1,u5imm:$ZERO2), + "dss $STRM", LdStGeneral /*FIXME*/, []>; +def DSSALL : DSS_Form<822, (outs), + (ins u5imm:$ONE, u5imm:$ZERO0,u5imm:$ZERO1,u5imm:$ZERO2), + "dssall", LdStGeneral /*FIXME*/, []>; +def DST : DSS_Form<342, (outs), + (ins u5imm:$ZERO, u5imm:$STRM, GPRC:$rA, GPRC:$rB), + "dst $rA, $rB, $STRM", LdStGeneral /*FIXME*/, []>; +def DSTT : DSS_Form<342, (outs), + (ins u5imm:$ONE, u5imm:$STRM, GPRC:$rA, GPRC:$rB), + "dstt $rA, $rB, $STRM", LdStGeneral /*FIXME*/, []>; +def DSTST : DSS_Form<374, (outs), + (ins u5imm:$ZERO, u5imm:$STRM, GPRC:$rA, GPRC:$rB), + "dstst $rA, $rB, $STRM", LdStGeneral /*FIXME*/, []>; +def DSTSTT : DSS_Form<374, (outs), + (ins u5imm:$ONE, u5imm:$STRM, GPRC:$rA, GPRC:$rB), + "dststt $rA, $rB, $STRM", LdStGeneral /*FIXME*/, []>; + +def DST64 : DSS_Form<342, (outs), + (ins u5imm:$ZERO, u5imm:$STRM, G8RC:$rA, GPRC:$rB), + "dst $rA, $rB, $STRM", LdStGeneral /*FIXME*/, []>; +def DSTT64 : DSS_Form<342, (outs), + (ins u5imm:$ONE, u5imm:$STRM, G8RC:$rA, GPRC:$rB), + "dstt $rA, $rB, $STRM", LdStGeneral /*FIXME*/, []>; +def DSTST64 : DSS_Form<374, (outs), + (ins u5imm:$ZERO, u5imm:$STRM, G8RC:$rA, GPRC:$rB), + "dstst $rA, $rB, $STRM", LdStGeneral /*FIXME*/, []>; +def DSTSTT64 : DSS_Form<374, (outs), + (ins u5imm:$ONE, u5imm:$STRM, G8RC:$rA, GPRC:$rB), + "dststt $rA, $rB, $STRM", LdStGeneral /*FIXME*/, []>; + +def MFVSCR : VXForm_4<1540, (outs VRRC:$vD), (ins), + "mfvscr $vD", LdStGeneral, + [(set VRRC:$vD, (int_ppc_altivec_mfvscr))]>; +def MTVSCR : VXForm_5<1604, (outs), (ins VRRC:$vB), + "mtvscr $vB", LdStGeneral, + [(int_ppc_altivec_mtvscr VRRC:$vB)]>; + +let canFoldAsLoad = 1, PPC970_Unit = 2 in { // Loads. +def LVEBX: XForm_1<31, 7, (outs VRRC:$vD), (ins memrr:$src), + "lvebx $vD, $src", LdStGeneral, + [(set VRRC:$vD, (int_ppc_altivec_lvebx xoaddr:$src))]>; +def LVEHX: XForm_1<31, 39, (outs VRRC:$vD), (ins memrr:$src), + "lvehx $vD, $src", LdStGeneral, + [(set VRRC:$vD, (int_ppc_altivec_lvehx xoaddr:$src))]>; +def LVEWX: XForm_1<31, 71, (outs VRRC:$vD), (ins memrr:$src), + "lvewx $vD, $src", LdStGeneral, + [(set VRRC:$vD, (int_ppc_altivec_lvewx xoaddr:$src))]>; +def LVX : XForm_1<31, 103, (outs VRRC:$vD), (ins memrr:$src), + "lvx $vD, $src", LdStGeneral, + [(set VRRC:$vD, (int_ppc_altivec_lvx xoaddr:$src))]>; +def LVXL : XForm_1<31, 359, (outs VRRC:$vD), (ins memrr:$src), + "lvxl $vD, $src", LdStGeneral, + [(set VRRC:$vD, (int_ppc_altivec_lvxl xoaddr:$src))]>; +} + +def LVSL : XForm_1<31, 6, (outs VRRC:$vD), (ins memrr:$src), + "lvsl $vD, $src", LdStGeneral, + [(set VRRC:$vD, (int_ppc_altivec_lvsl xoaddr:$src))]>, + PPC970_Unit_LSU; +def LVSR : XForm_1<31, 38, (outs VRRC:$vD), (ins memrr:$src), + "lvsr $vD, $src", LdStGeneral, + [(set VRRC:$vD, (int_ppc_altivec_lvsr xoaddr:$src))]>, + PPC970_Unit_LSU; + +let PPC970_Unit = 2 in { // Stores. +def STVEBX: XForm_8<31, 135, (outs), (ins VRRC:$rS, memrr:$dst), + "stvebx $rS, $dst", LdStGeneral, + [(int_ppc_altivec_stvebx VRRC:$rS, xoaddr:$dst)]>; +def STVEHX: XForm_8<31, 167, (outs), (ins VRRC:$rS, memrr:$dst), + "stvehx $rS, $dst", LdStGeneral, + [(int_ppc_altivec_stvehx VRRC:$rS, xoaddr:$dst)]>; +def STVEWX: XForm_8<31, 199, (outs), (ins VRRC:$rS, memrr:$dst), + "stvewx $rS, $dst", LdStGeneral, + [(int_ppc_altivec_stvewx VRRC:$rS, xoaddr:$dst)]>; +def STVX : XForm_8<31, 231, (outs), (ins VRRC:$rS, memrr:$dst), + "stvx $rS, $dst", LdStGeneral, + [(int_ppc_altivec_stvx VRRC:$rS, xoaddr:$dst)]>; +def STVXL : XForm_8<31, 487, (outs), (ins VRRC:$rS, memrr:$dst), + "stvxl $rS, $dst", LdStGeneral, + [(int_ppc_altivec_stvxl VRRC:$rS, xoaddr:$dst)]>; +} + +let PPC970_Unit = 5 in { // VALU Operations. +// VA-Form instructions. 3-input AltiVec ops. +def VMADDFP : VAForm_1<46, (outs VRRC:$vD), (ins VRRC:$vA, VRRC:$vC, VRRC:$vB), + "vmaddfp $vD, $vA, $vC, $vB", VecFP, + [(set VRRC:$vD, (fadd (fmul VRRC:$vA, VRRC:$vC), + VRRC:$vB))]>, + Requires<[FPContractions]>; +def VNMSUBFP: VAForm_1<47, (outs VRRC:$vD), (ins VRRC:$vA, VRRC:$vC, VRRC:$vB), + "vnmsubfp $vD, $vA, $vC, $vB", VecFP, + [(set VRRC:$vD, (fsub V_immneg0, + (fsub (fmul VRRC:$vA, VRRC:$vC), + VRRC:$vB)))]>, + Requires<[FPContractions]>; + +def VMHADDSHS : VA1a_Int<32, "vmhaddshs", int_ppc_altivec_vmhaddshs>; +def VMHRADDSHS : VA1a_Int<33, "vmhraddshs", int_ppc_altivec_vmhraddshs>; +def VMLADDUHM : VA1a_Int<34, "vmladduhm", int_ppc_altivec_vmladduhm>; +def VPERM : VA1a_Int<43, "vperm", int_ppc_altivec_vperm>; +def VSEL : VA1a_Int<42, "vsel", int_ppc_altivec_vsel>; + +// Shuffles. +def VSLDOI : VAForm_2<44, (outs VRRC:$vD), (ins VRRC:$vA, VRRC:$vB, u5imm:$SH), + "vsldoi $vD, $vA, $vB, $SH", VecFP, + [(set VRRC:$vD, + (vsldoi_shuffle:$SH (v16i8 VRRC:$vA), VRRC:$vB))]>; + +// VX-Form instructions. AltiVec arithmetic ops. +def VADDFP : VXForm_1<10, (outs VRRC:$vD), (ins VRRC:$vA, VRRC:$vB), + "vaddfp $vD, $vA, $vB", VecFP, + [(set VRRC:$vD, (fadd VRRC:$vA, VRRC:$vB))]>; + +def VADDUBM : VXForm_1<0, (outs VRRC:$vD), (ins VRRC:$vA, VRRC:$vB), + "vaddubm $vD, $vA, $vB", VecGeneral, + [(set VRRC:$vD, (add (v16i8 VRRC:$vA), VRRC:$vB))]>; +def VADDUHM : VXForm_1<64, (outs VRRC:$vD), (ins VRRC:$vA, VRRC:$vB), + "vadduhm $vD, $vA, $vB", VecGeneral, + [(set VRRC:$vD, (add (v8i16 VRRC:$vA), VRRC:$vB))]>; +def VADDUWM : VXForm_1<128, (outs VRRC:$vD), (ins VRRC:$vA, VRRC:$vB), + "vadduwm $vD, $vA, $vB", VecGeneral, + [(set VRRC:$vD, (add (v4i32 VRRC:$vA), VRRC:$vB))]>; + +def VADDCUW : VX1_Int<384, "vaddcuw", int_ppc_altivec_vaddcuw>; +def VADDSBS : VX1_Int<768, "vaddsbs", int_ppc_altivec_vaddsbs>; +def VADDSHS : VX1_Int<832, "vaddshs", int_ppc_altivec_vaddshs>; +def VADDSWS : VX1_Int<896, "vaddsws", int_ppc_altivec_vaddsws>; +def VADDUBS : VX1_Int<512, "vaddubs", int_ppc_altivec_vaddubs>; +def VADDUHS : VX1_Int<576, "vadduhs", int_ppc_altivec_vadduhs>; +def VADDUWS : VX1_Int<640, "vadduws", int_ppc_altivec_vadduws>; + + +def VAND : VXForm_1<1028, (outs VRRC:$vD), (ins VRRC:$vA, VRRC:$vB), + "vand $vD, $vA, $vB", VecFP, + [(set VRRC:$vD, (and (v4i32 VRRC:$vA), VRRC:$vB))]>; +def VANDC : VXForm_1<1092, (outs VRRC:$vD), (ins VRRC:$vA, VRRC:$vB), + "vandc $vD, $vA, $vB", VecFP, + [(set VRRC:$vD, (and (v4i32 VRRC:$vA), (vnot VRRC:$vB)))]>; + +def VCFSX : VXForm_1<842, (outs VRRC:$vD), (ins u5imm:$UIMM, VRRC:$vB), + "vcfsx $vD, $vB, $UIMM", VecFP, + [(set VRRC:$vD, + (int_ppc_altivec_vcfsx VRRC:$vB, imm:$UIMM))]>; +def VCFUX : VXForm_1<778, (outs VRRC:$vD), (ins u5imm:$UIMM, VRRC:$vB), + "vcfux $vD, $vB, $UIMM", VecFP, + [(set VRRC:$vD, + (int_ppc_altivec_vcfux VRRC:$vB, imm:$UIMM))]>; +def VCTSXS : VXForm_1<970, (outs VRRC:$vD), (ins u5imm:$UIMM, VRRC:$vB), + "vctsxs $vD, $vB, $UIMM", VecFP, + [(set VRRC:$vD, + (int_ppc_altivec_vctsxs VRRC:$vB, imm:$UIMM))]>; +def VCTUXS : VXForm_1<906, (outs VRRC:$vD), (ins u5imm:$UIMM, VRRC:$vB), + "vctuxs $vD, $vB, $UIMM", VecFP, + [(set VRRC:$vD, + (int_ppc_altivec_vctuxs VRRC:$vB, imm:$UIMM))]>; +def VEXPTEFP : VX2_Int<394, "vexptefp", int_ppc_altivec_vexptefp>; +def VLOGEFP : VX2_Int<458, "vlogefp", int_ppc_altivec_vlogefp>; + +def VAVGSB : VX1_Int<1282, "vavgsb", int_ppc_altivec_vavgsb>; +def VAVGSH : VX1_Int<1346, "vavgsh", int_ppc_altivec_vavgsh>; +def VAVGSW : VX1_Int<1410, "vavgsw", int_ppc_altivec_vavgsw>; +def VAVGUB : VX1_Int<1026, "vavgub", int_ppc_altivec_vavgub>; +def VAVGUH : VX1_Int<1090, "vavguh", int_ppc_altivec_vavguh>; +def VAVGUW : VX1_Int<1154, "vavguw", int_ppc_altivec_vavguw>; + +def VMAXFP : VX1_Int<1034, "vmaxfp", int_ppc_altivec_vmaxfp>; +def VMAXSB : VX1_Int< 258, "vmaxsb", int_ppc_altivec_vmaxsb>; +def VMAXSH : VX1_Int< 322, "vmaxsh", int_ppc_altivec_vmaxsh>; +def VMAXSW : VX1_Int< 386, "vmaxsw", int_ppc_altivec_vmaxsw>; +def VMAXUB : VX1_Int< 2, "vmaxub", int_ppc_altivec_vmaxub>; +def VMAXUH : VX1_Int< 66, "vmaxuh", int_ppc_altivec_vmaxuh>; +def VMAXUW : VX1_Int< 130, "vmaxuw", int_ppc_altivec_vmaxuw>; +def VMINFP : VX1_Int<1098, "vminfp", int_ppc_altivec_vminfp>; +def VMINSB : VX1_Int< 770, "vminsb", int_ppc_altivec_vminsb>; +def VMINSH : VX1_Int< 834, "vminsh", int_ppc_altivec_vminsh>; +def VMINSW : VX1_Int< 898, "vminsw", int_ppc_altivec_vminsw>; +def VMINUB : VX1_Int< 514, "vminub", int_ppc_altivec_vminub>; +def VMINUH : VX1_Int< 578, "vminuh", int_ppc_altivec_vminuh>; +def VMINUW : VX1_Int< 642, "vminuw", int_ppc_altivec_vminuw>; + +def VMRGHB : VXForm_1< 12, (outs VRRC:$vD), (ins VRRC:$vA, VRRC:$vB), + "vmrghb $vD, $vA, $vB", VecFP, + [(set VRRC:$vD, (vmrghb_shuffle VRRC:$vA, VRRC:$vB))]>; +def VMRGHH : VXForm_1< 76, (outs VRRC:$vD), (ins VRRC:$vA, VRRC:$vB), + "vmrghh $vD, $vA, $vB", VecFP, + [(set VRRC:$vD, (vmrghh_shuffle VRRC:$vA, VRRC:$vB))]>; +def VMRGHW : VXForm_1<140, (outs VRRC:$vD), (ins VRRC:$vA, VRRC:$vB), + "vmrghw $vD, $vA, $vB", VecFP, + [(set VRRC:$vD, (vmrghw_shuffle VRRC:$vA, VRRC:$vB))]>; +def VMRGLB : VXForm_1<268, (outs VRRC:$vD), (ins VRRC:$vA, VRRC:$vB), + "vmrglb $vD, $vA, $vB", VecFP, + [(set VRRC:$vD, (vmrglb_shuffle VRRC:$vA, VRRC:$vB))]>; +def VMRGLH : VXForm_1<332, (outs VRRC:$vD), (ins VRRC:$vA, VRRC:$vB), + "vmrglh $vD, $vA, $vB", VecFP, + [(set VRRC:$vD, (vmrglh_shuffle VRRC:$vA, VRRC:$vB))]>; +def VMRGLW : VXForm_1<396, (outs VRRC:$vD), (ins VRRC:$vA, VRRC:$vB), + "vmrglw $vD, $vA, $vB", VecFP, + [(set VRRC:$vD, (vmrglw_shuffle VRRC:$vA, VRRC:$vB))]>; + +def VMSUMMBM : VA1a_Int<37, "vmsummbm", int_ppc_altivec_vmsummbm>; +def VMSUMSHM : VA1a_Int<40, "vmsumshm", int_ppc_altivec_vmsumshm>; +def VMSUMSHS : VA1a_Int<41, "vmsumshs", int_ppc_altivec_vmsumshs>; +def VMSUMUBM : VA1a_Int<36, "vmsumubm", int_ppc_altivec_vmsumubm>; +def VMSUMUHM : VA1a_Int<38, "vmsumuhm", int_ppc_altivec_vmsumuhm>; +def VMSUMUHS : VA1a_Int<39, "vmsumuhs", int_ppc_altivec_vmsumuhs>; + +def VMULESB : VX1_Int<776, "vmulesb", int_ppc_altivec_vmulesb>; +def VMULESH : VX1_Int<840, "vmulesh", int_ppc_altivec_vmulesh>; +def VMULEUB : VX1_Int<520, "vmuleub", int_ppc_altivec_vmuleub>; +def VMULEUH : VX1_Int<584, "vmuleuh", int_ppc_altivec_vmuleuh>; +def VMULOSB : VX1_Int<264, "vmulosb", int_ppc_altivec_vmulosb>; +def VMULOSH : VX1_Int<328, "vmulosh", int_ppc_altivec_vmulosh>; +def VMULOUB : VX1_Int< 8, "vmuloub", int_ppc_altivec_vmuloub>; +def VMULOUH : VX1_Int< 72, "vmulouh", int_ppc_altivec_vmulouh>; + +def VREFP : VX2_Int<266, "vrefp", int_ppc_altivec_vrefp>; +def VRFIM : VX2_Int<714, "vrfim", int_ppc_altivec_vrfim>; +def VRFIN : VX2_Int<522, "vrfin", int_ppc_altivec_vrfin>; +def VRFIP : VX2_Int<650, "vrfip", int_ppc_altivec_vrfip>; +def VRFIZ : VX2_Int<586, "vrfiz", int_ppc_altivec_vrfiz>; +def VRSQRTEFP : VX2_Int<330, "vrsqrtefp", int_ppc_altivec_vrsqrtefp>; + +def VSUBCUW : VX1_Int<74, "vsubcuw", int_ppc_altivec_vsubcuw>; + +def VSUBFP : VXForm_1<74, (outs VRRC:$vD), (ins VRRC:$vA, VRRC:$vB), + "vsubfp $vD, $vA, $vB", VecGeneral, + [(set VRRC:$vD, (fsub VRRC:$vA, VRRC:$vB))]>; +def VSUBUBM : VXForm_1<1024, (outs VRRC:$vD), (ins VRRC:$vA, VRRC:$vB), + "vsububm $vD, $vA, $vB", VecGeneral, + [(set VRRC:$vD, (sub (v16i8 VRRC:$vA), VRRC:$vB))]>; +def VSUBUHM : VXForm_1<1088, (outs VRRC:$vD), (ins VRRC:$vA, VRRC:$vB), + "vsubuhm $vD, $vA, $vB", VecGeneral, + [(set VRRC:$vD, (sub (v8i16 VRRC:$vA), VRRC:$vB))]>; +def VSUBUWM : VXForm_1<1152, (outs VRRC:$vD), (ins VRRC:$vA, VRRC:$vB), + "vsubuwm $vD, $vA, $vB", VecGeneral, + [(set VRRC:$vD, (sub (v4i32 VRRC:$vA), VRRC:$vB))]>; + +def VSUBSBS : VX1_Int<1792, "vsubsbs" , int_ppc_altivec_vsubsbs>; +def VSUBSHS : VX1_Int<1856, "vsubshs" , int_ppc_altivec_vsubshs>; +def VSUBSWS : VX1_Int<1920, "vsubsws" , int_ppc_altivec_vsubsws>; +def VSUBUBS : VX1_Int<1536, "vsububs" , int_ppc_altivec_vsububs>; +def VSUBUHS : VX1_Int<1600, "vsubuhs" , int_ppc_altivec_vsubuhs>; +def VSUBUWS : VX1_Int<1664, "vsubuws" , int_ppc_altivec_vsubuws>; +def VSUMSWS : VX1_Int<1928, "vsumsws" , int_ppc_altivec_vsumsws>; +def VSUM2SWS: VX1_Int<1672, "vsum2sws", int_ppc_altivec_vsum2sws>; +def VSUM4SBS: VX1_Int<1672, "vsum4sbs", int_ppc_altivec_vsum4sbs>; +def VSUM4SHS: VX1_Int<1608, "vsum4shs", int_ppc_altivec_vsum4shs>; +def VSUM4UBS: VX1_Int<1544, "vsum4ubs", int_ppc_altivec_vsum4ubs>; + +def VNOR : VXForm_1<1284, (outs VRRC:$vD), (ins VRRC:$vA, VRRC:$vB), + "vnor $vD, $vA, $vB", VecFP, + [(set VRRC:$vD, (vnot (or (v4i32 VRRC:$vA), VRRC:$vB)))]>; +def VOR : VXForm_1<1156, (outs VRRC:$vD), (ins VRRC:$vA, VRRC:$vB), + "vor $vD, $vA, $vB", VecFP, + [(set VRRC:$vD, (or (v4i32 VRRC:$vA), VRRC:$vB))]>; +def VXOR : VXForm_1<1220, (outs VRRC:$vD), (ins VRRC:$vA, VRRC:$vB), + "vxor $vD, $vA, $vB", VecFP, + [(set VRRC:$vD, (xor (v4i32 VRRC:$vA), VRRC:$vB))]>; + +def VRLB : VX1_Int< 4, "vrlb", int_ppc_altivec_vrlb>; +def VRLH : VX1_Int< 68, "vrlh", int_ppc_altivec_vrlh>; +def VRLW : VX1_Int< 132, "vrlw", int_ppc_altivec_vrlw>; + +def VSL : VX1_Int< 452, "vsl" , int_ppc_altivec_vsl >; +def VSLO : VX1_Int<1036, "vslo", int_ppc_altivec_vslo>; +def VSLB : VX1_Int< 260, "vslb", int_ppc_altivec_vslb>; +def VSLH : VX1_Int< 324, "vslh", int_ppc_altivec_vslh>; +def VSLW : VX1_Int< 388, "vslw", int_ppc_altivec_vslw>; + +def VSPLTB : VXForm_1<524, (outs VRRC:$vD), (ins u5imm:$UIMM, VRRC:$vB), + "vspltb $vD, $vB, $UIMM", VecPerm, + [(set VRRC:$vD, + (vspltb_shuffle:$UIMM (v16i8 VRRC:$vB), (undef)))]>; +def VSPLTH : VXForm_1<588, (outs VRRC:$vD), (ins u5imm:$UIMM, VRRC:$vB), + "vsplth $vD, $vB, $UIMM", VecPerm, + [(set VRRC:$vD, + (vsplth_shuffle:$UIMM (v16i8 VRRC:$vB), (undef)))]>; +def VSPLTW : VXForm_1<652, (outs VRRC:$vD), (ins u5imm:$UIMM, VRRC:$vB), + "vspltw $vD, $vB, $UIMM", VecPerm, + [(set VRRC:$vD, + (vspltw_shuffle:$UIMM (v16i8 VRRC:$vB), (undef)))]>; + +def VSR : VX1_Int< 708, "vsr" , int_ppc_altivec_vsr>; +def VSRO : VX1_Int<1100, "vsro" , int_ppc_altivec_vsro>; +def VSRAB : VX1_Int< 772, "vsrab", int_ppc_altivec_vsrab>; +def VSRAH : VX1_Int< 836, "vsrah", int_ppc_altivec_vsrah>; +def VSRAW : VX1_Int< 900, "vsraw", int_ppc_altivec_vsraw>; +def VSRB : VX1_Int< 516, "vsrb" , int_ppc_altivec_vsrb>; +def VSRH : VX1_Int< 580, "vsrh" , int_ppc_altivec_vsrh>; +def VSRW : VX1_Int< 644, "vsrw" , int_ppc_altivec_vsrw>; + + +def VSPLTISB : VXForm_3<780, (outs VRRC:$vD), (ins s5imm:$SIMM), + "vspltisb $vD, $SIMM", VecPerm, + [(set VRRC:$vD, (v16i8 vecspltisb:$SIMM))]>; +def VSPLTISH : VXForm_3<844, (outs VRRC:$vD), (ins s5imm:$SIMM), + "vspltish $vD, $SIMM", VecPerm, + [(set VRRC:$vD, (v8i16 vecspltish:$SIMM))]>; +def VSPLTISW : VXForm_3<908, (outs VRRC:$vD), (ins s5imm:$SIMM), + "vspltisw $vD, $SIMM", VecPerm, + [(set VRRC:$vD, (v4i32 vecspltisw:$SIMM))]>; + +// Vector Pack. +def VPKPX : VX1_Int<782, "vpkpx", int_ppc_altivec_vpkpx>; +def VPKSHSS : VX1_Int<398, "vpkshss", int_ppc_altivec_vpkshss>; +def VPKSHUS : VX1_Int<270, "vpkshus", int_ppc_altivec_vpkshus>; +def VPKSWSS : VX1_Int<462, "vpkswss", int_ppc_altivec_vpkswss>; +def VPKSWUS : VX1_Int<334, "vpkswus", int_ppc_altivec_vpkswus>; +def VPKUHUM : VXForm_1<14, (outs VRRC:$vD), (ins VRRC:$vA, VRRC:$vB), + "vpkuhum $vD, $vA, $vB", VecFP, + [(set VRRC:$vD, + (vpkuhum_shuffle (v16i8 VRRC:$vA), VRRC:$vB))]>; +def VPKUHUS : VX1_Int<142, "vpkuhus", int_ppc_altivec_vpkuhus>; +def VPKUWUM : VXForm_1<78, (outs VRRC:$vD), (ins VRRC:$vA, VRRC:$vB), + "vpkuwum $vD, $vA, $vB", VecFP, + [(set VRRC:$vD, + (vpkuwum_shuffle (v16i8 VRRC:$vA), VRRC:$vB))]>; +def VPKUWUS : VX1_Int<206, "vpkuwus", int_ppc_altivec_vpkuwus>; + +// Vector Unpack. +def VUPKHPX : VX2_Int<846, "vupkhpx", int_ppc_altivec_vupkhpx>; +def VUPKHSB : VX2_Int<526, "vupkhsb", int_ppc_altivec_vupkhsb>; +def VUPKHSH : VX2_Int<590, "vupkhsh", int_ppc_altivec_vupkhsh>; +def VUPKLPX : VX2_Int<974, "vupklpx", int_ppc_altivec_vupklpx>; +def VUPKLSB : VX2_Int<654, "vupklsb", int_ppc_altivec_vupklsb>; +def VUPKLSH : VX2_Int<718, "vupklsh", int_ppc_altivec_vupklsh>; + + +// Altivec Comparisons. + +class VCMP xo, string asmstr, ValueType Ty> + : VXRForm_1; +class VCMPo xo, string asmstr, ValueType Ty> + : VXRForm_1 { + let Defs = [CR6]; + let RC = 1; +} + +// f32 element comparisons.0 +def VCMPBFP : VCMP <966, "vcmpbfp $vD, $vA, $vB" , v4f32>; +def VCMPBFPo : VCMPo<966, "vcmpbfp. $vD, $vA, $vB" , v4f32>; +def VCMPEQFP : VCMP <198, "vcmpeqfp $vD, $vA, $vB" , v4f32>; +def VCMPEQFPo : VCMPo<198, "vcmpeqfp. $vD, $vA, $vB", v4f32>; +def VCMPGEFP : VCMP <454, "vcmpgefp $vD, $vA, $vB" , v4f32>; +def VCMPGEFPo : VCMPo<454, "vcmpgefp. $vD, $vA, $vB", v4f32>; +def VCMPGTFP : VCMP <710, "vcmpgtfp $vD, $vA, $vB" , v4f32>; +def VCMPGTFPo : VCMPo<710, "vcmpgtfp. $vD, $vA, $vB", v4f32>; + +// i8 element comparisons. +def VCMPEQUB : VCMP < 6, "vcmpequb $vD, $vA, $vB" , v16i8>; +def VCMPEQUBo : VCMPo< 6, "vcmpequb. $vD, $vA, $vB", v16i8>; +def VCMPGTSB : VCMP <774, "vcmpgtsb $vD, $vA, $vB" , v16i8>; +def VCMPGTSBo : VCMPo<774, "vcmpgtsb. $vD, $vA, $vB", v16i8>; +def VCMPGTUB : VCMP <518, "vcmpgtub $vD, $vA, $vB" , v16i8>; +def VCMPGTUBo : VCMPo<518, "vcmpgtub. $vD, $vA, $vB", v16i8>; + +// i16 element comparisons. +def VCMPEQUH : VCMP < 70, "vcmpequh $vD, $vA, $vB" , v8i16>; +def VCMPEQUHo : VCMPo< 70, "vcmpequh. $vD, $vA, $vB", v8i16>; +def VCMPGTSH : VCMP <838, "vcmpgtsh $vD, $vA, $vB" , v8i16>; +def VCMPGTSHo : VCMPo<838, "vcmpgtsh. $vD, $vA, $vB", v8i16>; +def VCMPGTUH : VCMP <582, "vcmpgtuh $vD, $vA, $vB" , v8i16>; +def VCMPGTUHo : VCMPo<582, "vcmpgtuh. $vD, $vA, $vB", v8i16>; + +// i32 element comparisons. +def VCMPEQUW : VCMP <134, "vcmpequw $vD, $vA, $vB" , v4i32>; +def VCMPEQUWo : VCMPo<134, "vcmpequw. $vD, $vA, $vB", v4i32>; +def VCMPGTSW : VCMP <902, "vcmpgtsw $vD, $vA, $vB" , v4i32>; +def VCMPGTSWo : VCMPo<902, "vcmpgtsw. $vD, $vA, $vB", v4i32>; +def VCMPGTUW : VCMP <646, "vcmpgtuw $vD, $vA, $vB" , v4i32>; +def VCMPGTUWo : VCMPo<646, "vcmpgtuw. $vD, $vA, $vB", v4i32>; + +def V_SET0 : VXForm_setzero<1220, (outs VRRC:$vD), (ins), + "vxor $vD, $vD, $vD", VecFP, + [(set VRRC:$vD, (v4i32 immAllZerosV))]>; +} + +//===----------------------------------------------------------------------===// +// Additional Altivec Patterns +// + +// DS* intrinsics +def : Pat<(int_ppc_altivec_dssall), (DSSALL 1, 0, 0, 0)>; +def : Pat<(int_ppc_altivec_dss imm:$STRM), (DSS 0, imm:$STRM, 0, 0)>; + +// * 32-bit +def : Pat<(int_ppc_altivec_dst GPRC:$rA, GPRC:$rB, imm:$STRM), + (DST 0, imm:$STRM, GPRC:$rA, GPRC:$rB)>; +def : Pat<(int_ppc_altivec_dstt GPRC:$rA, GPRC:$rB, imm:$STRM), + (DSTT 1, imm:$STRM, GPRC:$rA, GPRC:$rB)>; +def : Pat<(int_ppc_altivec_dstst GPRC:$rA, GPRC:$rB, imm:$STRM), + (DSTST 0, imm:$STRM, GPRC:$rA, GPRC:$rB)>; +def : Pat<(int_ppc_altivec_dststt GPRC:$rA, GPRC:$rB, imm:$STRM), + (DSTSTT 1, imm:$STRM, GPRC:$rA, GPRC:$rB)>; + +// * 64-bit +def : Pat<(int_ppc_altivec_dst G8RC:$rA, GPRC:$rB, imm:$STRM), + (DST64 0, imm:$STRM, (i64 G8RC:$rA), GPRC:$rB)>; +def : Pat<(int_ppc_altivec_dstt G8RC:$rA, GPRC:$rB, imm:$STRM), + (DSTT64 1, imm:$STRM, (i64 G8RC:$rA), GPRC:$rB)>; +def : Pat<(int_ppc_altivec_dstst G8RC:$rA, GPRC:$rB, imm:$STRM), + (DSTST64 0, imm:$STRM, (i64 G8RC:$rA), GPRC:$rB)>; +def : Pat<(int_ppc_altivec_dststt G8RC:$rA, GPRC:$rB, imm:$STRM), + (DSTSTT64 1, imm:$STRM, (i64 G8RC:$rA), GPRC:$rB)>; + +// Loads. +def : Pat<(v4i32 (load xoaddr:$src)), (LVX xoaddr:$src)>; + +// Stores. +def : Pat<(store (v4i32 VRRC:$rS), xoaddr:$dst), + (STVX (v4i32 VRRC:$rS), xoaddr:$dst)>; + +// Bit conversions. +def : Pat<(v16i8 (bitconvert (v8i16 VRRC:$src))), (v16i8 VRRC:$src)>; +def : Pat<(v16i8 (bitconvert (v4i32 VRRC:$src))), (v16i8 VRRC:$src)>; +def : Pat<(v16i8 (bitconvert (v4f32 VRRC:$src))), (v16i8 VRRC:$src)>; + +def : Pat<(v8i16 (bitconvert (v16i8 VRRC:$src))), (v8i16 VRRC:$src)>; +def : Pat<(v8i16 (bitconvert (v4i32 VRRC:$src))), (v8i16 VRRC:$src)>; +def : Pat<(v8i16 (bitconvert (v4f32 VRRC:$src))), (v8i16 VRRC:$src)>; + +def : Pat<(v4i32 (bitconvert (v16i8 VRRC:$src))), (v4i32 VRRC:$src)>; +def : Pat<(v4i32 (bitconvert (v8i16 VRRC:$src))), (v4i32 VRRC:$src)>; +def : Pat<(v4i32 (bitconvert (v4f32 VRRC:$src))), (v4i32 VRRC:$src)>; + +def : Pat<(v4f32 (bitconvert (v16i8 VRRC:$src))), (v4f32 VRRC:$src)>; +def : Pat<(v4f32 (bitconvert (v8i16 VRRC:$src))), (v4f32 VRRC:$src)>; +def : Pat<(v4f32 (bitconvert (v4i32 VRRC:$src))), (v4f32 VRRC:$src)>; + +// Shuffles. + +// Match vsldoi(x,x), vpkuwum(x,x), vpkuhum(x,x) +def:Pat<(vsldoi_unary_shuffle:$in (v16i8 VRRC:$vA), undef), + (VSLDOI VRRC:$vA, VRRC:$vA, (VSLDOI_unary_get_imm VRRC:$in))>; +def:Pat<(vpkuwum_unary_shuffle (v16i8 VRRC:$vA), undef), + (VPKUWUM VRRC:$vA, VRRC:$vA)>; +def:Pat<(vpkuhum_unary_shuffle (v16i8 VRRC:$vA), undef), + (VPKUHUM VRRC:$vA, VRRC:$vA)>; + +// Match vmrg*(x,x) +def:Pat<(vmrglb_unary_shuffle (v16i8 VRRC:$vA), undef), + (VMRGLB VRRC:$vA, VRRC:$vA)>; +def:Pat<(vmrglh_unary_shuffle (v16i8 VRRC:$vA), undef), + (VMRGLH VRRC:$vA, VRRC:$vA)>; +def:Pat<(vmrglw_unary_shuffle (v16i8 VRRC:$vA), undef), + (VMRGLW VRRC:$vA, VRRC:$vA)>; +def:Pat<(vmrghb_unary_shuffle (v16i8 VRRC:$vA), undef), + (VMRGHB VRRC:$vA, VRRC:$vA)>; +def:Pat<(vmrghh_unary_shuffle (v16i8 VRRC:$vA), undef), + (VMRGHH VRRC:$vA, VRRC:$vA)>; +def:Pat<(vmrghw_unary_shuffle (v16i8 VRRC:$vA), undef), + (VMRGHW VRRC:$vA, VRRC:$vA)>; + +// Logical Operations +def : Pat<(v4i32 (vnot VRRC:$vA)), (VNOR VRRC:$vA, VRRC:$vA)>; +def : Pat<(v4i32 (vnot_conv VRRC:$vA)), (VNOR VRRC:$vA, VRRC:$vA)>; + +def : Pat<(v4i32 (vnot_conv (or VRRC:$A, VRRC:$B))), + (VNOR VRRC:$A, VRRC:$B)>; +def : Pat<(v4i32 (and VRRC:$A, (vnot_conv VRRC:$B))), + (VANDC VRRC:$A, VRRC:$B)>; + +def : Pat<(fmul VRRC:$vA, VRRC:$vB), + (VMADDFP VRRC:$vA, VRRC:$vB, (v4i32 (V_SET0)))>; + +// Fused multiply add and multiply sub for packed float. These are represented +// separately from the real instructions above, for operations that must have +// the additional precision, such as Newton-Rhapson (used by divide, sqrt) +def : Pat<(PPCvmaddfp VRRC:$A, VRRC:$B, VRRC:$C), + (VMADDFP VRRC:$A, VRRC:$B, VRRC:$C)>; +def : Pat<(PPCvnmsubfp VRRC:$A, VRRC:$B, VRRC:$C), + (VNMSUBFP VRRC:$A, VRRC:$B, VRRC:$C)>; + +def : Pat<(int_ppc_altivec_vmaddfp VRRC:$A, VRRC:$B, VRRC:$C), + (VMADDFP VRRC:$A, VRRC:$B, VRRC:$C)>; +def : Pat<(int_ppc_altivec_vnmsubfp VRRC:$A, VRRC:$B, VRRC:$C), + (VNMSUBFP VRRC:$A, VRRC:$B, VRRC:$C)>; + +def : Pat<(PPCvperm (v16i8 VRRC:$vA), VRRC:$vB, VRRC:$vC), + (VPERM VRRC:$vA, VRRC:$vB, VRRC:$vC)>; + +// Vector shifts +def : Pat<(v16i8 (shl (v16i8 VRRC:$vA), (v16i8 VRRC:$vB))), + (v16i8 (VSLB VRRC:$vA, VRRC:$vB))>; +def : Pat<(v8i16 (shl (v8i16 VRRC:$vA), (v8i16 VRRC:$vB))), + (v8i16 (VSLH VRRC:$vA, VRRC:$vB))>; +def : Pat<(v4i32 (shl (v4i32 VRRC:$vA), (v4i32 VRRC:$vB))), + (v4i32 (VSLW VRRC:$vA, VRRC:$vB))>; + +def : Pat<(v16i8 (srl (v16i8 VRRC:$vA), (v16i8 VRRC:$vB))), + (v16i8 (VSRB VRRC:$vA, VRRC:$vB))>; +def : Pat<(v8i16 (srl (v8i16 VRRC:$vA), (v8i16 VRRC:$vB))), + (v8i16 (VSRH VRRC:$vA, VRRC:$vB))>; +def : Pat<(v4i32 (srl (v4i32 VRRC:$vA), (v4i32 VRRC:$vB))), + (v4i32 (VSRW VRRC:$vA, VRRC:$vB))>; + +def : Pat<(v16i8 (sra (v16i8 VRRC:$vA), (v16i8 VRRC:$vB))), + (v16i8 (VSRAB VRRC:$vA, VRRC:$vB))>; +def : Pat<(v8i16 (sra (v8i16 VRRC:$vA), (v8i16 VRRC:$vB))), + (v8i16 (VSRAH VRRC:$vA, VRRC:$vB))>; +def : Pat<(v4i32 (sra (v4i32 VRRC:$vA), (v4i32 VRRC:$vB))), + (v4i32 (VSRAW VRRC:$vA, VRRC:$vB))>; diff --git a/libclamav/c++/llvm/lib/Target/PowerPC/PPCInstrBuilder.h b/libclamav/c++/llvm/lib/Target/PowerPC/PPCInstrBuilder.h new file mode 100644 index 000000000..b424d1101 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/PowerPC/PPCInstrBuilder.h @@ -0,0 +1,43 @@ +//===-- PPCInstrBuilder.h - Aides for building PPC insts --------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file exposes functions that may be used with BuildMI from the +// MachineInstrBuilder.h file to simplify generating frame and constant pool +// references. +// +// For reference, the order of operands for memory references is: +// (Operand), Dest Reg, Base Reg, and either Reg Index or Immediate +// Displacement. +// +//===----------------------------------------------------------------------===// + +#ifndef POWERPC_INSTRBUILDER_H +#define POWERPC_INSTRBUILDER_H + +#include "llvm/CodeGen/MachineInstrBuilder.h" + +namespace llvm { + +/// addFrameReference - This function is used to add a reference to the base of +/// an abstract object on the stack frame of the current function. This +/// reference has base register as the FrameIndex offset until it is resolved. +/// This allows a constant offset to be specified as well... +/// +static inline const MachineInstrBuilder& +addFrameReference(const MachineInstrBuilder &MIB, int FI, int Offset = 0, + bool mem = true) { + if (mem) + return MIB.addImm(Offset).addFrameIndex(FI); + else + return MIB.addFrameIndex(FI).addImm(Offset); +} + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/lib/Target/PowerPC/PPCInstrFormats.td b/libclamav/c++/llvm/lib/Target/PowerPC/PPCInstrFormats.td new file mode 100644 index 000000000..54cebcdec --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/PowerPC/PPCInstrFormats.td @@ -0,0 +1,875 @@ +//===- PowerPCInstrFormats.td - PowerPC Instruction Formats --*- tablegen -*-=// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// +// PowerPC instruction formats + +class I opcode, dag OOL, dag IOL, string asmstr, InstrItinClass itin> + : Instruction { + field bits<32> Inst; + + bit PPC64 = 0; // Default value, override with isPPC64 + + let Namespace = "PPC"; + let Inst{0-5} = opcode; + let OutOperandList = OOL; + let InOperandList = IOL; + let AsmString = asmstr; + let Itinerary = itin; + + /// These fields correspond to the fields in PPCInstrInfo.h. Any changes to + /// these must be reflected there! See comments there for what these are. + bits<1> PPC970_First = 0; + bits<1> PPC970_Single = 0; + bits<1> PPC970_Cracked = 0; + bits<3> PPC970_Unit = 0; +} + +class PPC970_DGroup_First { bits<1> PPC970_First = 1; } +class PPC970_DGroup_Single { bits<1> PPC970_Single = 1; } +class PPC970_DGroup_Cracked { bits<1> PPC970_Cracked = 1; } +class PPC970_MicroCode; + +class PPC970_Unit_Pseudo { bits<3> PPC970_Unit = 0; } +class PPC970_Unit_FXU { bits<3> PPC970_Unit = 1; } +class PPC970_Unit_LSU { bits<3> PPC970_Unit = 2; } +class PPC970_Unit_FPU { bits<3> PPC970_Unit = 3; } +class PPC970_Unit_CRU { bits<3> PPC970_Unit = 4; } +class PPC970_Unit_VALU { bits<3> PPC970_Unit = 5; } +class PPC970_Unit_VPERM { bits<3> PPC970_Unit = 6; } +class PPC970_Unit_BRU { bits<3> PPC970_Unit = 7; } + + +// 1.7.1 I-Form +class IForm opcode, bit aa, bit lk, dag OOL, dag IOL, string asmstr, + InstrItinClass itin, list pattern> + : I { + let Pattern = pattern; + bits<24> LI; + + let Inst{6-29} = LI; + let Inst{30} = aa; + let Inst{31} = lk; +} + +// 1.7.2 B-Form +class BForm opcode, bit aa, bit lk, dag OOL, dag IOL, string asmstr> + : I { + bits<7> BIBO; // 2 bits of BI and 5 bits of BO. + bits<3> CR; + bits<14> BD; + + bits<5> BI; + let BI{0-1} = BIBO{5-6}; + let BI{2-4} = CR{0-2}; + + let Inst{6-10} = BIBO{4-0}; + let Inst{11-15} = BI; + let Inst{16-29} = BD; + let Inst{30} = aa; + let Inst{31} = lk; +} + + +// 1.7.4 D-Form +class DForm_base opcode, dag OOL, dag IOL, string asmstr, + InstrItinClass itin, list pattern> + : I { + bits<5> A; + bits<5> B; + bits<16> C; + + let Pattern = pattern; + + let Inst{6-10} = A; + let Inst{11-15} = B; + let Inst{16-31} = C; +} + +class DForm_1 opcode, dag OOL, dag IOL, string asmstr, + InstrItinClass itin, list pattern> + : I { + bits<5> A; + bits<16> C; + bits<5> B; + + let Pattern = pattern; + + let Inst{6-10} = A; + let Inst{11-15} = B; + let Inst{16-31} = C; +} + +class DForm_2 opcode, dag OOL, dag IOL, string asmstr, + InstrItinClass itin, list pattern> + : DForm_base; + +class DForm_2_r0 opcode, dag OOL, dag IOL, string asmstr, + InstrItinClass itin, list pattern> + : I { + bits<5> A; + bits<16> B; + + let Pattern = pattern; + + let Inst{6-10} = A; + let Inst{11-15} = 0; + let Inst{16-31} = B; +} + +class DForm_4 opcode, dag OOL, dag IOL, string asmstr, + InstrItinClass itin, list pattern> + : I { + bits<5> B; + bits<5> A; + bits<16> C; + + let Pattern = pattern; + + let Inst{6-10} = A; + let Inst{11-15} = B; + let Inst{16-31} = C; +} + +class DForm_4_zero opcode, dag OOL, dag IOL, string asmstr, + InstrItinClass itin, list pattern> + : DForm_1 { + let A = 0; + let B = 0; + let C = 0; +} + +class DForm_5 opcode, dag OOL, dag IOL, string asmstr, + InstrItinClass itin> + : I { + bits<3> BF; + bits<1> L; + bits<5> RA; + bits<16> I; + + let Inst{6-8} = BF; + let Inst{9} = 0; + let Inst{10} = L; + let Inst{11-15} = RA; + let Inst{16-31} = I; +} + +class DForm_5_ext opcode, dag OOL, dag IOL, string asmstr, + InstrItinClass itin> + : DForm_5 { + let L = PPC64; +} + +class DForm_6 opcode, dag OOL, dag IOL, string asmstr, + InstrItinClass itin> + : DForm_5; + +class DForm_6_ext opcode, dag OOL, dag IOL, string asmstr, + InstrItinClass itin> + : DForm_6 { + let L = PPC64; +} + + +// 1.7.5 DS-Form +class DSForm_1 opcode, bits<2> xo, dag OOL, dag IOL, string asmstr, + InstrItinClass itin, list pattern> + : I { + bits<5> RST; + bits<14> DS; + bits<5> RA; + + let Pattern = pattern; + + let Inst{6-10} = RST; + let Inst{11-15} = RA; + let Inst{16-29} = DS; + let Inst{30-31} = xo; +} + +// 1.7.6 X-Form +class XForm_base_r3xo opcode, bits<10> xo, dag OOL, dag IOL, string asmstr, + InstrItinClass itin, list pattern> + : I { + bits<5> RST; + bits<5> A; + bits<5> B; + + let Pattern = pattern; + + bit RC = 0; // set by isDOT + + let Inst{6-10} = RST; + let Inst{11-15} = A; + let Inst{16-20} = B; + let Inst{21-30} = xo; + let Inst{31} = RC; +} + +// This is the same as XForm_base_r3xo, but the first two operands are swapped +// when code is emitted. +class XForm_base_r3xo_swapped + opcode, bits<10> xo, dag OOL, dag IOL, string asmstr, + InstrItinClass itin> + : I { + bits<5> A; + bits<5> RST; + bits<5> B; + + bit RC = 0; // set by isDOT + + let Inst{6-10} = RST; + let Inst{11-15} = A; + let Inst{16-20} = B; + let Inst{21-30} = xo; + let Inst{31} = RC; +} + + +class XForm_1 opcode, bits<10> xo, dag OOL, dag IOL, string asmstr, + InstrItinClass itin, list pattern> + : XForm_base_r3xo; + +class XForm_6 opcode, bits<10> xo, dag OOL, dag IOL, string asmstr, + InstrItinClass itin, list pattern> + : XForm_base_r3xo_swapped { + let Pattern = pattern; +} + +class XForm_8 opcode, bits<10> xo, dag OOL, dag IOL, string asmstr, + InstrItinClass itin, list pattern> + : XForm_base_r3xo; + +class XForm_10 opcode, bits<10> xo, dag OOL, dag IOL, string asmstr, + InstrItinClass itin, list pattern> + : XForm_base_r3xo_swapped { + let Pattern = pattern; +} + +class XForm_11 opcode, bits<10> xo, dag OOL, dag IOL, string asmstr, + InstrItinClass itin, list pattern> + : XForm_base_r3xo_swapped { + let B = 0; + let Pattern = pattern; +} + +class XForm_16 opcode, bits<10> xo, dag OOL, dag IOL, string asmstr, + InstrItinClass itin> + : I { + bits<3> BF; + bits<1> L; + bits<5> RA; + bits<5> RB; + + let Inst{6-8} = BF; + let Inst{9} = 0; + let Inst{10} = L; + let Inst{11-15} = RA; + let Inst{16-20} = RB; + let Inst{21-30} = xo; + let Inst{31} = 0; +} + +class XForm_16_ext opcode, bits<10> xo, dag OOL, dag IOL, string asmstr, + InstrItinClass itin> + : XForm_16 { + let L = PPC64; +} + +class XForm_17 opcode, bits<10> xo, dag OOL, dag IOL, string asmstr, + InstrItinClass itin> + : I { + bits<3> BF; + bits<5> FRA; + bits<5> FRB; + + let Inst{6-8} = BF; + let Inst{9-10} = 0; + let Inst{11-15} = FRA; + let Inst{16-20} = FRB; + let Inst{21-30} = xo; + let Inst{31} = 0; +} + +class XForm_24 opcode, bits<10> xo, dag OOL, dag IOL, string asmstr, + InstrItinClass itin, list pattern> + : I { + let Pattern = pattern; + let Inst{6-10} = 31; + let Inst{11-15} = 0; + let Inst{16-20} = 0; + let Inst{21-30} = xo; + let Inst{31} = 0; +} + +class XForm_24_sync opcode, bits<10> xo, dag OOL, dag IOL, + string asmstr, InstrItinClass itin, list pattern> + : I { + let Pattern = pattern; + let Inst{6-10} = 0; + let Inst{11-15} = 0; + let Inst{16-20} = 0; + let Inst{21-30} = xo; + let Inst{31} = 0; +} + +class XForm_25 opcode, bits<10> xo, dag OOL, dag IOL, string asmstr, + InstrItinClass itin, list pattern> + : XForm_base_r3xo { +} + +class XForm_26 opcode, bits<10> xo, dag OOL, dag IOL, string asmstr, + InstrItinClass itin, list pattern> + : XForm_base_r3xo { + let A = 0; +} + +class XForm_28 opcode, bits<10> xo, dag OOL, dag IOL, string asmstr, + InstrItinClass itin, list pattern> + : XForm_base_r3xo { +} + +// This is used for MFFS, MTFSB0, MTFSB1. 42 is arbitrary; this series of +// numbers presumably relates to some document, but I haven't found it. +class XForm_42 opcode, bits<10> xo, dag OOL, dag IOL, string asmstr, + InstrItinClass itin, list pattern> + : XForm_base_r3xo { + let Pattern = pattern; + + bit RC = 0; // set by isDOT + + let Inst{6-10} = RST; + let Inst{11-20} = 0; + let Inst{21-30} = xo; + let Inst{31} = RC; +} +class XForm_43 opcode, bits<10> xo, dag OOL, dag IOL, string asmstr, + InstrItinClass itin, list pattern> + : XForm_base_r3xo { + let Pattern = pattern; + bits<5> FM; + + bit RC = 0; // set by isDOT + + let Inst{6-10} = FM; + let Inst{11-20} = 0; + let Inst{21-30} = xo; + let Inst{31} = RC; +} + +// DCB_Form - Form X instruction, used for dcb* instructions. +class DCB_Form xo, bits<5> immfield, dag OOL, dag IOL, string asmstr, + InstrItinClass itin, list pattern> + : I<31, OOL, IOL, asmstr, itin> { + bits<5> A; + bits<5> B; + + let Pattern = pattern; + + let Inst{6-10} = immfield; + let Inst{11-15} = A; + let Inst{16-20} = B; + let Inst{21-30} = xo; + let Inst{31} = 0; +} + + +// DSS_Form - Form X instruction, used for altivec dss* instructions. +class DSS_Form xo, dag OOL, dag IOL, string asmstr, + InstrItinClass itin, list pattern> + : I<31, OOL, IOL, asmstr, itin> { + bits<1> T; + bits<2> STRM; + bits<5> A; + bits<5> B; + + let Pattern = pattern; + + let Inst{6} = T; + let Inst{7-8} = 0; + let Inst{9-10} = STRM; + let Inst{11-15} = A; + let Inst{16-20} = B; + let Inst{21-30} = xo; + let Inst{31} = 0; +} + +// 1.7.7 XL-Form +class XLForm_1 opcode, bits<10> xo, dag OOL, dag IOL, string asmstr, + InstrItinClass itin, list pattern> + : I { + bits<5> CRD; + bits<5> CRA; + bits<5> CRB; + + let Pattern = pattern; + + let Inst{6-10} = CRD; + let Inst{11-15} = CRA; + let Inst{16-20} = CRB; + let Inst{21-30} = xo; + let Inst{31} = 0; +} + +class XLForm_1_ext opcode, bits<10> xo, dag OOL, dag IOL, string asmstr, + InstrItinClass itin, list pattern> + : I { + bits<5> CRD; + + let Pattern = pattern; + + let Inst{6-10} = CRD; + let Inst{11-15} = CRD; + let Inst{16-20} = CRD; + let Inst{21-30} = xo; + let Inst{31} = 0; +} + +class XLForm_2 opcode, bits<10> xo, bit lk, dag OOL, dag IOL, string asmstr, + InstrItinClass itin, list pattern> + : I { + bits<5> BO; + bits<5> BI; + bits<2> BH; + + let Pattern = pattern; + + let Inst{6-10} = BO; + let Inst{11-15} = BI; + let Inst{16-18} = 0; + let Inst{19-20} = BH; + let Inst{21-30} = xo; + let Inst{31} = lk; +} + +class XLForm_2_br opcode, bits<10> xo, bit lk, + dag OOL, dag IOL, string asmstr, InstrItinClass itin, list pattern> + : XLForm_2 { + bits<7> BIBO; // 2 bits of BI and 5 bits of BO. + bits<3> CR; + + let BO = BIBO{2-6}; + let BI{0-1} = BIBO{0-1}; + let BI{2-4} = CR; + let BH = 0; +} + + +class XLForm_2_ext opcode, bits<10> xo, bits<5> bo, bits<5> bi, bit lk, + dag OOL, dag IOL, string asmstr, InstrItinClass itin, list pattern> + : XLForm_2 { + let BO = bo; + let BI = bi; + let BH = 0; +} + +class XLForm_3 opcode, bits<10> xo, dag OOL, dag IOL, string asmstr, + InstrItinClass itin> + : I { + bits<3> BF; + bits<3> BFA; + + let Inst{6-8} = BF; + let Inst{9-10} = 0; + let Inst{11-13} = BFA; + let Inst{14-15} = 0; + let Inst{16-20} = 0; + let Inst{21-30} = xo; + let Inst{31} = 0; +} + +// 1.7.8 XFX-Form +class XFXForm_1 opcode, bits<10> xo, dag OOL, dag IOL, string asmstr, + InstrItinClass itin> + : I { + bits<5> RT; + bits<10> SPR; + + let Inst{6-10} = RT; + let Inst{11} = SPR{4}; + let Inst{12} = SPR{3}; + let Inst{13} = SPR{2}; + let Inst{14} = SPR{1}; + let Inst{15} = SPR{0}; + let Inst{16} = SPR{9}; + let Inst{17} = SPR{8}; + let Inst{18} = SPR{7}; + let Inst{19} = SPR{6}; + let Inst{20} = SPR{5}; + let Inst{21-30} = xo; + let Inst{31} = 0; +} + +class XFXForm_1_ext opcode, bits<10> xo, bits<10> spr, + dag OOL, dag IOL, string asmstr, InstrItinClass itin> + : XFXForm_1 { + let SPR = spr; +} + +class XFXForm_3 opcode, bits<10> xo, dag OOL, dag IOL, string asmstr, + InstrItinClass itin> + : I { + bits<5> RT; + + let Inst{6-10} = RT; + let Inst{11-20} = 0; + let Inst{21-30} = xo; + let Inst{31} = 0; +} + +class XFXForm_5 opcode, bits<10> xo, dag OOL, dag IOL, string asmstr, + InstrItinClass itin> + : I { + bits<8> FXM; + bits<5> ST; + + let Inst{6-10} = ST; + let Inst{11} = 0; + let Inst{12-19} = FXM; + let Inst{20} = 0; + let Inst{21-30} = xo; + let Inst{31} = 0; +} + +class XFXForm_5a opcode, bits<10> xo, dag OOL, dag IOL, string asmstr, + InstrItinClass itin> + : I { + bits<5> ST; + bits<8> FXM; + + let Inst{6-10} = ST; + let Inst{11} = 1; + let Inst{12-19} = FXM; + let Inst{20} = 0; + let Inst{21-30} = xo; + let Inst{31} = 0; +} + +class XFXForm_7 opcode, bits<10> xo, dag OOL, dag IOL, string asmstr, + InstrItinClass itin> + : XFXForm_1; + +class XFXForm_7_ext opcode, bits<10> xo, bits<10> spr, + dag OOL, dag IOL, string asmstr, InstrItinClass itin> + : XFXForm_7 { + let SPR = spr; +} + +// XFL-Form - MTFSF +// This is probably 1.7.9, but I don't have the reference that uses this +// numbering scheme... +class XFLForm opcode, bits<10> xo, dag OOL, dag IOL, string asmstr, + string cstr, InstrItinClass itin, listpattern> + : I { + bits<8> FM; + bits<5> RT; + + bit RC = 0; // set by isDOT + let Pattern = pattern; + let Constraints = cstr; + + let Inst{6} = 0; + let Inst{7-14} = FM; + let Inst{15} = 0; + let Inst{16-20} = RT; + let Inst{21-30} = xo; + let Inst{31} = RC; +} + +// 1.7.10 XS-Form - SRADI. +class XSForm_1 opcode, bits<9> xo, dag OOL, dag IOL, string asmstr, + InstrItinClass itin, list pattern> + : I { + bits<5> A; + bits<5> RS; + bits<6> SH; + + bit RC = 0; // set by isDOT + let Pattern = pattern; + + let Inst{6-10} = RS; + let Inst{11-15} = A; + let Inst{16-20} = SH{4,3,2,1,0}; + let Inst{21-29} = xo; + let Inst{30} = SH{5}; + let Inst{31} = RC; +} + +// 1.7.11 XO-Form +class XOForm_1 opcode, bits<9> xo, bit oe, dag OOL, dag IOL, string asmstr, + InstrItinClass itin, list pattern> + : I { + bits<5> RT; + bits<5> RA; + bits<5> RB; + + let Pattern = pattern; + + bit RC = 0; // set by isDOT + + let Inst{6-10} = RT; + let Inst{11-15} = RA; + let Inst{16-20} = RB; + let Inst{21} = oe; + let Inst{22-30} = xo; + let Inst{31} = RC; +} + +class XOForm_3 opcode, bits<9> xo, bit oe, + dag OOL, dag IOL, string asmstr, InstrItinClass itin, list pattern> + : XOForm_1 { + let RB = 0; +} + +// 1.7.12 A-Form +class AForm_1 opcode, bits<5> xo, dag OOL, dag IOL, string asmstr, + InstrItinClass itin, list pattern> + : I { + bits<5> FRT; + bits<5> FRA; + bits<5> FRC; + bits<5> FRB; + + let Pattern = pattern; + + bit RC = 0; // set by isDOT + + let Inst{6-10} = FRT; + let Inst{11-15} = FRA; + let Inst{16-20} = FRB; + let Inst{21-25} = FRC; + let Inst{26-30} = xo; + let Inst{31} = RC; +} + +class AForm_2 opcode, bits<5> xo, dag OOL, dag IOL, string asmstr, + InstrItinClass itin, list pattern> + : AForm_1 { + let FRC = 0; +} + +class AForm_3 opcode, bits<5> xo, dag OOL, dag IOL, string asmstr, + InstrItinClass itin, list pattern> + : AForm_1 { + let FRB = 0; +} + +// 1.7.13 M-Form +class MForm_1 opcode, dag OOL, dag IOL, string asmstr, + InstrItinClass itin, list pattern> + : I { + bits<5> RA; + bits<5> RS; + bits<5> RB; + bits<5> MB; + bits<5> ME; + + let Pattern = pattern; + + bit RC = 0; // set by isDOT + + let Inst{6-10} = RS; + let Inst{11-15} = RA; + let Inst{16-20} = RB; + let Inst{21-25} = MB; + let Inst{26-30} = ME; + let Inst{31} = RC; +} + +class MForm_2 opcode, dag OOL, dag IOL, string asmstr, + InstrItinClass itin, list pattern> + : MForm_1 { +} + +// 1.7.14 MD-Form +class MDForm_1 opcode, bits<3> xo, dag OOL, dag IOL, string asmstr, + InstrItinClass itin, list pattern> + : I { + bits<5> RA; + bits<5> RS; + bits<6> SH; + bits<6> MBE; + + let Pattern = pattern; + + bit RC = 0; // set by isDOT + + let Inst{6-10} = RS; + let Inst{11-15} = RA; + let Inst{16-20} = SH{4,3,2,1,0}; + let Inst{21-26} = MBE{4,3,2,1,0,5}; + let Inst{27-29} = xo; + let Inst{30} = SH{5}; + let Inst{31} = RC; +} + + + +// E-1 VA-Form + +// VAForm_1 - DACB ordering. +class VAForm_1 xo, dag OOL, dag IOL, string asmstr, + InstrItinClass itin, list pattern> + : I<4, OOL, IOL, asmstr, itin> { + bits<5> VD; + bits<5> VA; + bits<5> VC; + bits<5> VB; + + let Pattern = pattern; + + let Inst{6-10} = VD; + let Inst{11-15} = VA; + let Inst{16-20} = VB; + let Inst{21-25} = VC; + let Inst{26-31} = xo; +} + +// VAForm_1a - DABC ordering. +class VAForm_1a xo, dag OOL, dag IOL, string asmstr, + InstrItinClass itin, list pattern> + : I<4, OOL, IOL, asmstr, itin> { + bits<5> VD; + bits<5> VA; + bits<5> VB; + bits<5> VC; + + let Pattern = pattern; + + let Inst{6-10} = VD; + let Inst{11-15} = VA; + let Inst{16-20} = VB; + let Inst{21-25} = VC; + let Inst{26-31} = xo; +} + +class VAForm_2 xo, dag OOL, dag IOL, string asmstr, + InstrItinClass itin, list pattern> + : I<4, OOL, IOL, asmstr, itin> { + bits<5> VD; + bits<5> VA; + bits<5> VB; + bits<4> SH; + + let Pattern = pattern; + + let Inst{6-10} = VD; + let Inst{11-15} = VA; + let Inst{16-20} = VB; + let Inst{21} = 0; + let Inst{22-25} = SH; + let Inst{26-31} = xo; +} + +// E-2 VX-Form +class VXForm_1 xo, dag OOL, dag IOL, string asmstr, + InstrItinClass itin, list pattern> + : I<4, OOL, IOL, asmstr, itin> { + bits<5> VD; + bits<5> VA; + bits<5> VB; + + let Pattern = pattern; + + let Inst{6-10} = VD; + let Inst{11-15} = VA; + let Inst{16-20} = VB; + let Inst{21-31} = xo; +} + +class VXForm_setzero xo, dag OOL, dag IOL, string asmstr, + InstrItinClass itin, list pattern> + : VXForm_1 { + let VA = VD; + let VB = VD; +} + + +class VXForm_2 xo, dag OOL, dag IOL, string asmstr, + InstrItinClass itin, list pattern> + : I<4, OOL, IOL, asmstr, itin> { + bits<5> VD; + bits<5> VB; + + let Pattern = pattern; + + let Inst{6-10} = VD; + let Inst{11-15} = 0; + let Inst{16-20} = VB; + let Inst{21-31} = xo; +} + +class VXForm_3 xo, dag OOL, dag IOL, string asmstr, + InstrItinClass itin, list pattern> + : I<4, OOL, IOL, asmstr, itin> { + bits<5> VD; + bits<5> IMM; + + let Pattern = pattern; + + let Inst{6-10} = VD; + let Inst{11-15} = IMM; + let Inst{16-20} = 0; + let Inst{21-31} = xo; +} + +/// VXForm_4 - VX instructions with "VD,0,0" register fields, like mfvscr. +class VXForm_4 xo, dag OOL, dag IOL, string asmstr, + InstrItinClass itin, list pattern> + : I<4, OOL, IOL, asmstr, itin> { + bits<5> VD; + + let Pattern = pattern; + + let Inst{6-10} = VD; + let Inst{11-15} = 0; + let Inst{16-20} = 0; + let Inst{21-31} = xo; +} + +/// VXForm_5 - VX instructions with "0,0,VB" register fields, like mtvscr. +class VXForm_5 xo, dag OOL, dag IOL, string asmstr, + InstrItinClass itin, list pattern> + : I<4, OOL, IOL, asmstr, itin> { + bits<5> VB; + + let Pattern = pattern; + + let Inst{6-10} = 0; + let Inst{11-15} = 0; + let Inst{16-20} = VB; + let Inst{21-31} = xo; +} + +// E-4 VXR-Form +class VXRForm_1 xo, dag OOL, dag IOL, string asmstr, + InstrItinClass itin, list pattern> + : I<4, OOL, IOL, asmstr, itin> { + bits<5> VD; + bits<5> VA; + bits<5> VB; + bit RC = 0; + + let Pattern = pattern; + + let Inst{6-10} = VD; + let Inst{11-15} = VA; + let Inst{16-20} = VB; + let Inst{21} = RC; + let Inst{22-31} = xo; +} + +//===----------------------------------------------------------------------===// +class Pseudo pattern> + : I<0, OOL, IOL, asmstr, NoItinerary> { + let PPC64 = 0; + let Pattern = pattern; + let Inst{31-0} = 0; +} diff --git a/libclamav/c++/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp b/libclamav/c++/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp new file mode 100644 index 000000000..0083598cf --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp @@ -0,0 +1,780 @@ +//===- PPCInstrInfo.cpp - PowerPC32 Instruction Information -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the PowerPC implementation of the TargetInstrInfo class. +// +//===----------------------------------------------------------------------===// + +#include "PPCInstrInfo.h" +#include "PPCInstrBuilder.h" +#include "PPCMachineFunctionInfo.h" +#include "PPCPredicates.h" +#include "PPCGenInstrInfo.inc" +#include "PPCTargetMachine.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/MC/MCAsmInfo.h" +using namespace llvm; + +extern cl::opt EnablePPC32RS; // FIXME (64-bit): See PPCRegisterInfo.cpp. +extern cl::opt EnablePPC64RS; // FIXME (64-bit): See PPCRegisterInfo.cpp. + +PPCInstrInfo::PPCInstrInfo(PPCTargetMachine &tm) + : TargetInstrInfoImpl(PPCInsts, array_lengthof(PPCInsts)), TM(tm), + RI(*TM.getSubtargetImpl(), *this) {} + +bool PPCInstrInfo::isMoveInstr(const MachineInstr& MI, + unsigned& sourceReg, + unsigned& destReg, + unsigned& sourceSubIdx, + unsigned& destSubIdx) const { + sourceSubIdx = destSubIdx = 0; // No sub-registers. + + unsigned oc = MI.getOpcode(); + if (oc == PPC::OR || oc == PPC::OR8 || oc == PPC::VOR || + oc == PPC::OR4To8 || oc == PPC::OR8To4) { // or r1, r2, r2 + assert(MI.getNumOperands() >= 3 && + MI.getOperand(0).isReg() && + MI.getOperand(1).isReg() && + MI.getOperand(2).isReg() && + "invalid PPC OR instruction!"); + if (MI.getOperand(1).getReg() == MI.getOperand(2).getReg()) { + sourceReg = MI.getOperand(1).getReg(); + destReg = MI.getOperand(0).getReg(); + return true; + } + } else if (oc == PPC::ADDI) { // addi r1, r2, 0 + assert(MI.getNumOperands() >= 3 && + MI.getOperand(0).isReg() && + MI.getOperand(2).isImm() && + "invalid PPC ADDI instruction!"); + if (MI.getOperand(1).isReg() && MI.getOperand(2).getImm() == 0) { + sourceReg = MI.getOperand(1).getReg(); + destReg = MI.getOperand(0).getReg(); + return true; + } + } else if (oc == PPC::ORI) { // ori r1, r2, 0 + assert(MI.getNumOperands() >= 3 && + MI.getOperand(0).isReg() && + MI.getOperand(1).isReg() && + MI.getOperand(2).isImm() && + "invalid PPC ORI instruction!"); + if (MI.getOperand(2).getImm() == 0) { + sourceReg = MI.getOperand(1).getReg(); + destReg = MI.getOperand(0).getReg(); + return true; + } + } else if (oc == PPC::FMRS || oc == PPC::FMRD || + oc == PPC::FMRSD) { // fmr r1, r2 + assert(MI.getNumOperands() >= 2 && + MI.getOperand(0).isReg() && + MI.getOperand(1).isReg() && + "invalid PPC FMR instruction"); + sourceReg = MI.getOperand(1).getReg(); + destReg = MI.getOperand(0).getReg(); + return true; + } else if (oc == PPC::MCRF) { // mcrf cr1, cr2 + assert(MI.getNumOperands() >= 2 && + MI.getOperand(0).isReg() && + MI.getOperand(1).isReg() && + "invalid PPC MCRF instruction"); + sourceReg = MI.getOperand(1).getReg(); + destReg = MI.getOperand(0).getReg(); + return true; + } + return false; +} + +unsigned PPCInstrInfo::isLoadFromStackSlot(const MachineInstr *MI, + int &FrameIndex) const { + switch (MI->getOpcode()) { + default: break; + case PPC::LD: + case PPC::LWZ: + case PPC::LFS: + case PPC::LFD: + if (MI->getOperand(1).isImm() && !MI->getOperand(1).getImm() && + MI->getOperand(2).isFI()) { + FrameIndex = MI->getOperand(2).getIndex(); + return MI->getOperand(0).getReg(); + } + break; + } + return 0; +} + +unsigned PPCInstrInfo::isStoreToStackSlot(const MachineInstr *MI, + int &FrameIndex) const { + switch (MI->getOpcode()) { + default: break; + case PPC::STD: + case PPC::STW: + case PPC::STFS: + case PPC::STFD: + if (MI->getOperand(1).isImm() && !MI->getOperand(1).getImm() && + MI->getOperand(2).isFI()) { + FrameIndex = MI->getOperand(2).getIndex(); + return MI->getOperand(0).getReg(); + } + break; + } + return 0; +} + +// commuteInstruction - We can commute rlwimi instructions, but only if the +// rotate amt is zero. We also have to munge the immediates a bit. +MachineInstr * +PPCInstrInfo::commuteInstruction(MachineInstr *MI, bool NewMI) const { + MachineFunction &MF = *MI->getParent()->getParent(); + + // Normal instructions can be commuted the obvious way. + if (MI->getOpcode() != PPC::RLWIMI) + return TargetInstrInfoImpl::commuteInstruction(MI, NewMI); + + // Cannot commute if it has a non-zero rotate count. + if (MI->getOperand(3).getImm() != 0) + return 0; + + // If we have a zero rotate count, we have: + // M = mask(MB,ME) + // Op0 = (Op1 & ~M) | (Op2 & M) + // Change this to: + // M = mask((ME+1)&31, (MB-1)&31) + // Op0 = (Op2 & ~M) | (Op1 & M) + + // Swap op1/op2 + unsigned Reg0 = MI->getOperand(0).getReg(); + unsigned Reg1 = MI->getOperand(1).getReg(); + unsigned Reg2 = MI->getOperand(2).getReg(); + bool Reg1IsKill = MI->getOperand(1).isKill(); + bool Reg2IsKill = MI->getOperand(2).isKill(); + bool ChangeReg0 = false; + // If machine instrs are no longer in two-address forms, update + // destination register as well. + if (Reg0 == Reg1) { + // Must be two address instruction! + assert(MI->getDesc().getOperandConstraint(0, TOI::TIED_TO) && + "Expecting a two-address instruction!"); + Reg2IsKill = false; + ChangeReg0 = true; + } + + // Masks. + unsigned MB = MI->getOperand(4).getImm(); + unsigned ME = MI->getOperand(5).getImm(); + + if (NewMI) { + // Create a new instruction. + unsigned Reg0 = ChangeReg0 ? Reg2 : MI->getOperand(0).getReg(); + bool Reg0IsDead = MI->getOperand(0).isDead(); + return BuildMI(MF, MI->getDebugLoc(), MI->getDesc()) + .addReg(Reg0, RegState::Define | getDeadRegState(Reg0IsDead)) + .addReg(Reg2, getKillRegState(Reg2IsKill)) + .addReg(Reg1, getKillRegState(Reg1IsKill)) + .addImm((ME+1) & 31) + .addImm((MB-1) & 31); + } + + if (ChangeReg0) + MI->getOperand(0).setReg(Reg2); + MI->getOperand(2).setReg(Reg1); + MI->getOperand(1).setReg(Reg2); + MI->getOperand(2).setIsKill(Reg1IsKill); + MI->getOperand(1).setIsKill(Reg2IsKill); + + // Swap the mask around. + MI->getOperand(4).setImm((ME+1) & 31); + MI->getOperand(5).setImm((MB-1) & 31); + return MI; +} + +void PPCInstrInfo::insertNoop(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI) const { + DebugLoc DL = DebugLoc::getUnknownLoc(); + if (MI != MBB.end()) DL = MI->getDebugLoc(); + + BuildMI(MBB, MI, DL, get(PPC::NOP)); +} + + +// Branch analysis. +bool PPCInstrInfo::AnalyzeBranch(MachineBasicBlock &MBB,MachineBasicBlock *&TBB, + MachineBasicBlock *&FBB, + SmallVectorImpl &Cond, + bool AllowModify) const { + // If the block has no terminators, it just falls into the block after it. + MachineBasicBlock::iterator I = MBB.end(); + if (I == MBB.begin() || !isUnpredicatedTerminator(--I)) + return false; + + // Get the last instruction in the block. + MachineInstr *LastInst = I; + + // If there is only one terminator instruction, process it. + if (I == MBB.begin() || !isUnpredicatedTerminator(--I)) { + if (LastInst->getOpcode() == PPC::B) { + if (!LastInst->getOperand(0).isMBB()) + return true; + TBB = LastInst->getOperand(0).getMBB(); + return false; + } else if (LastInst->getOpcode() == PPC::BCC) { + if (!LastInst->getOperand(2).isMBB()) + return true; + // Block ends with fall-through condbranch. + TBB = LastInst->getOperand(2).getMBB(); + Cond.push_back(LastInst->getOperand(0)); + Cond.push_back(LastInst->getOperand(1)); + return false; + } + // Otherwise, don't know what this is. + return true; + } + + // Get the instruction before it if it's a terminator. + MachineInstr *SecondLastInst = I; + + // If there are three terminators, we don't know what sort of block this is. + if (SecondLastInst && I != MBB.begin() && + isUnpredicatedTerminator(--I)) + return true; + + // If the block ends with PPC::B and PPC:BCC, handle it. + if (SecondLastInst->getOpcode() == PPC::BCC && + LastInst->getOpcode() == PPC::B) { + if (!SecondLastInst->getOperand(2).isMBB() || + !LastInst->getOperand(0).isMBB()) + return true; + TBB = SecondLastInst->getOperand(2).getMBB(); + Cond.push_back(SecondLastInst->getOperand(0)); + Cond.push_back(SecondLastInst->getOperand(1)); + FBB = LastInst->getOperand(0).getMBB(); + return false; + } + + // If the block ends with two PPC:Bs, handle it. The second one is not + // executed, so remove it. + if (SecondLastInst->getOpcode() == PPC::B && + LastInst->getOpcode() == PPC::B) { + if (!SecondLastInst->getOperand(0).isMBB()) + return true; + TBB = SecondLastInst->getOperand(0).getMBB(); + I = LastInst; + if (AllowModify) + I->eraseFromParent(); + return false; + } + + // Otherwise, can't handle this. + return true; +} + +unsigned PPCInstrInfo::RemoveBranch(MachineBasicBlock &MBB) const { + MachineBasicBlock::iterator I = MBB.end(); + if (I == MBB.begin()) return 0; + --I; + if (I->getOpcode() != PPC::B && I->getOpcode() != PPC::BCC) + return 0; + + // Remove the branch. + I->eraseFromParent(); + + I = MBB.end(); + + if (I == MBB.begin()) return 1; + --I; + if (I->getOpcode() != PPC::BCC) + return 1; + + // Remove the branch. + I->eraseFromParent(); + return 2; +} + +unsigned +PPCInstrInfo::InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, + MachineBasicBlock *FBB, + const SmallVectorImpl &Cond) const { + // FIXME this should probably have a DebugLoc argument + DebugLoc dl = DebugLoc::getUnknownLoc(); + // Shouldn't be a fall through. + assert(TBB && "InsertBranch must not be told to insert a fallthrough"); + assert((Cond.size() == 2 || Cond.size() == 0) && + "PPC branch conditions have two components!"); + + // One-way branch. + if (FBB == 0) { + if (Cond.empty()) // Unconditional branch + BuildMI(&MBB, dl, get(PPC::B)).addMBB(TBB); + else // Conditional branch + BuildMI(&MBB, dl, get(PPC::BCC)) + .addImm(Cond[0].getImm()).addReg(Cond[1].getReg()).addMBB(TBB); + return 1; + } + + // Two-way Conditional Branch. + BuildMI(&MBB, dl, get(PPC::BCC)) + .addImm(Cond[0].getImm()).addReg(Cond[1].getReg()).addMBB(TBB); + BuildMI(&MBB, dl, get(PPC::B)).addMBB(FBB); + return 2; +} + +bool PPCInstrInfo::copyRegToReg(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + unsigned DestReg, unsigned SrcReg, + const TargetRegisterClass *DestRC, + const TargetRegisterClass *SrcRC) const { + if (DestRC != SrcRC) { + // Not yet supported! + return false; + } + + DebugLoc DL = DebugLoc::getUnknownLoc(); + if (MI != MBB.end()) DL = MI->getDebugLoc(); + + if (DestRC == PPC::GPRCRegisterClass) { + BuildMI(MBB, MI, DL, get(PPC::OR), DestReg).addReg(SrcReg).addReg(SrcReg); + } else if (DestRC == PPC::G8RCRegisterClass) { + BuildMI(MBB, MI, DL, get(PPC::OR8), DestReg).addReg(SrcReg).addReg(SrcReg); + } else if (DestRC == PPC::F4RCRegisterClass) { + BuildMI(MBB, MI, DL, get(PPC::FMRS), DestReg).addReg(SrcReg); + } else if (DestRC == PPC::F8RCRegisterClass) { + BuildMI(MBB, MI, DL, get(PPC::FMRD), DestReg).addReg(SrcReg); + } else if (DestRC == PPC::CRRCRegisterClass) { + BuildMI(MBB, MI, DL, get(PPC::MCRF), DestReg).addReg(SrcReg); + } else if (DestRC == PPC::VRRCRegisterClass) { + BuildMI(MBB, MI, DL, get(PPC::VOR), DestReg).addReg(SrcReg).addReg(SrcReg); + } else if (DestRC == PPC::CRBITRCRegisterClass) { + BuildMI(MBB, MI, DL, get(PPC::CROR), DestReg).addReg(SrcReg).addReg(SrcReg); + } else { + // Attempt to copy register that is not GPR or FPR + return false; + } + + return true; +} + +bool +PPCInstrInfo::StoreRegToStackSlot(MachineFunction &MF, + unsigned SrcReg, bool isKill, + int FrameIdx, + const TargetRegisterClass *RC, + SmallVectorImpl &NewMIs) const{ + DebugLoc DL = DebugLoc::getUnknownLoc(); + if (RC == PPC::GPRCRegisterClass) { + if (SrcReg != PPC::LR) { + NewMIs.push_back(addFrameReference(BuildMI(MF, DL, get(PPC::STW)) + .addReg(SrcReg, + getKillRegState(isKill)), + FrameIdx)); + } else { + // FIXME: this spills LR immediately to memory in one step. To do this, + // we use R11, which we know cannot be used in the prolog/epilog. This is + // a hack. + NewMIs.push_back(BuildMI(MF, DL, get(PPC::MFLR), PPC::R11)); + NewMIs.push_back(addFrameReference(BuildMI(MF, DL, get(PPC::STW)) + .addReg(PPC::R11, + getKillRegState(isKill)), + FrameIdx)); + } + } else if (RC == PPC::G8RCRegisterClass) { + if (SrcReg != PPC::LR8) { + NewMIs.push_back(addFrameReference(BuildMI(MF, DL, get(PPC::STD)) + .addReg(SrcReg, + getKillRegState(isKill)), + FrameIdx)); + } else { + // FIXME: this spills LR immediately to memory in one step. To do this, + // we use R11, which we know cannot be used in the prolog/epilog. This is + // a hack. + NewMIs.push_back(BuildMI(MF, DL, get(PPC::MFLR8), PPC::X11)); + NewMIs.push_back(addFrameReference(BuildMI(MF, DL, get(PPC::STD)) + .addReg(PPC::X11, + getKillRegState(isKill)), + FrameIdx)); + } + } else if (RC == PPC::F8RCRegisterClass) { + NewMIs.push_back(addFrameReference(BuildMI(MF, DL, get(PPC::STFD)) + .addReg(SrcReg, + getKillRegState(isKill)), + FrameIdx)); + } else if (RC == PPC::F4RCRegisterClass) { + NewMIs.push_back(addFrameReference(BuildMI(MF, DL, get(PPC::STFS)) + .addReg(SrcReg, + getKillRegState(isKill)), + FrameIdx)); + } else if (RC == PPC::CRRCRegisterClass) { + if ((EnablePPC32RS && !TM.getSubtargetImpl()->isPPC64()) || + (EnablePPC64RS && TM.getSubtargetImpl()->isPPC64())) { + // FIXME (64-bit): Enable + NewMIs.push_back(addFrameReference(BuildMI(MF, DL, get(PPC::SPILL_CR)) + .addReg(SrcReg, + getKillRegState(isKill)), + FrameIdx)); + return true; + } else { + // FIXME: We use R0 here, because it isn't available for RA. We need to + // store the CR in the low 4-bits of the saved value. First, issue a MFCR + // to save all of the CRBits. + NewMIs.push_back(BuildMI(MF, DL, get(PPC::MFCR), PPC::R0)); + + // If the saved register wasn't CR0, shift the bits left so that they are + // in CR0's slot. + if (SrcReg != PPC::CR0) { + unsigned ShiftBits = PPCRegisterInfo::getRegisterNumbering(SrcReg)*4; + // rlwinm r0, r0, ShiftBits, 0, 31. + NewMIs.push_back(BuildMI(MF, DL, get(PPC::RLWINM), PPC::R0) + .addReg(PPC::R0).addImm(ShiftBits).addImm(0).addImm(31)); + } + + NewMIs.push_back(addFrameReference(BuildMI(MF, DL, get(PPC::STW)) + .addReg(PPC::R0, + getKillRegState(isKill)), + FrameIdx)); + } + } else if (RC == PPC::CRBITRCRegisterClass) { + // FIXME: We use CRi here because there is no mtcrf on a bit. Since the + // backend currently only uses CR1EQ as an individual bit, this should + // not cause any bug. If we need other uses of CR bits, the following + // code may be invalid. + unsigned Reg = 0; + if (SrcReg == PPC::CR0LT || SrcReg == PPC::CR0GT || + SrcReg == PPC::CR0EQ || SrcReg == PPC::CR0UN) + Reg = PPC::CR0; + else if (SrcReg == PPC::CR1LT || SrcReg == PPC::CR1GT || + SrcReg == PPC::CR1EQ || SrcReg == PPC::CR1UN) + Reg = PPC::CR1; + else if (SrcReg == PPC::CR2LT || SrcReg == PPC::CR2GT || + SrcReg == PPC::CR2EQ || SrcReg == PPC::CR2UN) + Reg = PPC::CR2; + else if (SrcReg == PPC::CR3LT || SrcReg == PPC::CR3GT || + SrcReg == PPC::CR3EQ || SrcReg == PPC::CR3UN) + Reg = PPC::CR3; + else if (SrcReg == PPC::CR4LT || SrcReg == PPC::CR4GT || + SrcReg == PPC::CR4EQ || SrcReg == PPC::CR4UN) + Reg = PPC::CR4; + else if (SrcReg == PPC::CR5LT || SrcReg == PPC::CR5GT || + SrcReg == PPC::CR5EQ || SrcReg == PPC::CR5UN) + Reg = PPC::CR5; + else if (SrcReg == PPC::CR6LT || SrcReg == PPC::CR6GT || + SrcReg == PPC::CR6EQ || SrcReg == PPC::CR6UN) + Reg = PPC::CR6; + else if (SrcReg == PPC::CR7LT || SrcReg == PPC::CR7GT || + SrcReg == PPC::CR7EQ || SrcReg == PPC::CR7UN) + Reg = PPC::CR7; + + return StoreRegToStackSlot(MF, Reg, isKill, FrameIdx, + PPC::CRRCRegisterClass, NewMIs); + + } else if (RC == PPC::VRRCRegisterClass) { + // We don't have indexed addressing for vector loads. Emit: + // R0 = ADDI FI# + // STVX VAL, 0, R0 + // + // FIXME: We use R0 here, because it isn't available for RA. + NewMIs.push_back(addFrameReference(BuildMI(MF, DL, get(PPC::ADDI), PPC::R0), + FrameIdx, 0, 0)); + NewMIs.push_back(BuildMI(MF, DL, get(PPC::STVX)) + .addReg(SrcReg, getKillRegState(isKill)) + .addReg(PPC::R0) + .addReg(PPC::R0)); + } else { + llvm_unreachable("Unknown regclass!"); + } + + return false; +} + +void +PPCInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + unsigned SrcReg, bool isKill, int FrameIdx, + const TargetRegisterClass *RC) const { + MachineFunction &MF = *MBB.getParent(); + SmallVector NewMIs; + + if (StoreRegToStackSlot(MF, SrcReg, isKill, FrameIdx, RC, NewMIs)) { + PPCFunctionInfo *FuncInfo = MF.getInfo(); + FuncInfo->setSpillsCR(); + } + + for (unsigned i = 0, e = NewMIs.size(); i != e; ++i) + MBB.insert(MI, NewMIs[i]); +} + +void +PPCInstrInfo::LoadRegFromStackSlot(MachineFunction &MF, DebugLoc DL, + unsigned DestReg, int FrameIdx, + const TargetRegisterClass *RC, + SmallVectorImpl &NewMIs)const{ + if (RC == PPC::GPRCRegisterClass) { + if (DestReg != PPC::LR) { + NewMIs.push_back(addFrameReference(BuildMI(MF, DL, get(PPC::LWZ), + DestReg), FrameIdx)); + } else { + NewMIs.push_back(addFrameReference(BuildMI(MF, DL, get(PPC::LWZ), + PPC::R11), FrameIdx)); + NewMIs.push_back(BuildMI(MF, DL, get(PPC::MTLR)).addReg(PPC::R11)); + } + } else if (RC == PPC::G8RCRegisterClass) { + if (DestReg != PPC::LR8) { + NewMIs.push_back(addFrameReference(BuildMI(MF, DL, get(PPC::LD), DestReg), + FrameIdx)); + } else { + NewMIs.push_back(addFrameReference(BuildMI(MF, DL, get(PPC::LD), + PPC::R11), FrameIdx)); + NewMIs.push_back(BuildMI(MF, DL, get(PPC::MTLR8)).addReg(PPC::R11)); + } + } else if (RC == PPC::F8RCRegisterClass) { + NewMIs.push_back(addFrameReference(BuildMI(MF, DL, get(PPC::LFD), DestReg), + FrameIdx)); + } else if (RC == PPC::F4RCRegisterClass) { + NewMIs.push_back(addFrameReference(BuildMI(MF, DL, get(PPC::LFS), DestReg), + FrameIdx)); + } else if (RC == PPC::CRRCRegisterClass) { + // FIXME: We use R0 here, because it isn't available for RA. + NewMIs.push_back(addFrameReference(BuildMI(MF, DL, get(PPC::LWZ), PPC::R0), + FrameIdx)); + + // If the reloaded register isn't CR0, shift the bits right so that they are + // in the right CR's slot. + if (DestReg != PPC::CR0) { + unsigned ShiftBits = PPCRegisterInfo::getRegisterNumbering(DestReg)*4; + // rlwinm r11, r11, 32-ShiftBits, 0, 31. + NewMIs.push_back(BuildMI(MF, DL, get(PPC::RLWINM), PPC::R0) + .addReg(PPC::R0).addImm(32-ShiftBits).addImm(0).addImm(31)); + } + + NewMIs.push_back(BuildMI(MF, DL, get(PPC::MTCRF), DestReg).addReg(PPC::R0)); + } else if (RC == PPC::CRBITRCRegisterClass) { + + unsigned Reg = 0; + if (DestReg == PPC::CR0LT || DestReg == PPC::CR0GT || + DestReg == PPC::CR0EQ || DestReg == PPC::CR0UN) + Reg = PPC::CR0; + else if (DestReg == PPC::CR1LT || DestReg == PPC::CR1GT || + DestReg == PPC::CR1EQ || DestReg == PPC::CR1UN) + Reg = PPC::CR1; + else if (DestReg == PPC::CR2LT || DestReg == PPC::CR2GT || + DestReg == PPC::CR2EQ || DestReg == PPC::CR2UN) + Reg = PPC::CR2; + else if (DestReg == PPC::CR3LT || DestReg == PPC::CR3GT || + DestReg == PPC::CR3EQ || DestReg == PPC::CR3UN) + Reg = PPC::CR3; + else if (DestReg == PPC::CR4LT || DestReg == PPC::CR4GT || + DestReg == PPC::CR4EQ || DestReg == PPC::CR4UN) + Reg = PPC::CR4; + else if (DestReg == PPC::CR5LT || DestReg == PPC::CR5GT || + DestReg == PPC::CR5EQ || DestReg == PPC::CR5UN) + Reg = PPC::CR5; + else if (DestReg == PPC::CR6LT || DestReg == PPC::CR6GT || + DestReg == PPC::CR6EQ || DestReg == PPC::CR6UN) + Reg = PPC::CR6; + else if (DestReg == PPC::CR7LT || DestReg == PPC::CR7GT || + DestReg == PPC::CR7EQ || DestReg == PPC::CR7UN) + Reg = PPC::CR7; + + return LoadRegFromStackSlot(MF, DL, Reg, FrameIdx, + PPC::CRRCRegisterClass, NewMIs); + + } else if (RC == PPC::VRRCRegisterClass) { + // We don't have indexed addressing for vector loads. Emit: + // R0 = ADDI FI# + // Dest = LVX 0, R0 + // + // FIXME: We use R0 here, because it isn't available for RA. + NewMIs.push_back(addFrameReference(BuildMI(MF, DL, get(PPC::ADDI), PPC::R0), + FrameIdx, 0, 0)); + NewMIs.push_back(BuildMI(MF, DL, get(PPC::LVX),DestReg).addReg(PPC::R0) + .addReg(PPC::R0)); + } else { + llvm_unreachable("Unknown regclass!"); + } +} + +void +PPCInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + unsigned DestReg, int FrameIdx, + const TargetRegisterClass *RC) const { + MachineFunction &MF = *MBB.getParent(); + SmallVector NewMIs; + DebugLoc DL = DebugLoc::getUnknownLoc(); + if (MI != MBB.end()) DL = MI->getDebugLoc(); + LoadRegFromStackSlot(MF, DL, DestReg, FrameIdx, RC, NewMIs); + for (unsigned i = 0, e = NewMIs.size(); i != e; ++i) + MBB.insert(MI, NewMIs[i]); +} + +/// foldMemoryOperand - PowerPC (like most RISC's) can only fold spills into +/// copy instructions, turning them into load/store instructions. +MachineInstr *PPCInstrInfo::foldMemoryOperandImpl(MachineFunction &MF, + MachineInstr *MI, + const SmallVectorImpl &Ops, + int FrameIndex) const { + if (Ops.size() != 1) return NULL; + + // Make sure this is a reg-reg copy. Note that we can't handle MCRF, because + // it takes more than one instruction to store it. + unsigned Opc = MI->getOpcode(); + unsigned OpNum = Ops[0]; + + MachineInstr *NewMI = NULL; + if ((Opc == PPC::OR && + MI->getOperand(1).getReg() == MI->getOperand(2).getReg())) { + if (OpNum == 0) { // move -> store + unsigned InReg = MI->getOperand(1).getReg(); + bool isKill = MI->getOperand(1).isKill(); + bool isUndef = MI->getOperand(1).isUndef(); + NewMI = addFrameReference(BuildMI(MF, MI->getDebugLoc(), get(PPC::STW)) + .addReg(InReg, + getKillRegState(isKill) | + getUndefRegState(isUndef)), + FrameIndex); + } else { // move -> load + unsigned OutReg = MI->getOperand(0).getReg(); + bool isDead = MI->getOperand(0).isDead(); + bool isUndef = MI->getOperand(0).isUndef(); + NewMI = addFrameReference(BuildMI(MF, MI->getDebugLoc(), get(PPC::LWZ)) + .addReg(OutReg, + RegState::Define | + getDeadRegState(isDead) | + getUndefRegState(isUndef)), + FrameIndex); + } + } else if ((Opc == PPC::OR8 && + MI->getOperand(1).getReg() == MI->getOperand(2).getReg())) { + if (OpNum == 0) { // move -> store + unsigned InReg = MI->getOperand(1).getReg(); + bool isKill = MI->getOperand(1).isKill(); + bool isUndef = MI->getOperand(1).isUndef(); + NewMI = addFrameReference(BuildMI(MF, MI->getDebugLoc(), get(PPC::STD)) + .addReg(InReg, + getKillRegState(isKill) | + getUndefRegState(isUndef)), + FrameIndex); + } else { // move -> load + unsigned OutReg = MI->getOperand(0).getReg(); + bool isDead = MI->getOperand(0).isDead(); + bool isUndef = MI->getOperand(0).isUndef(); + NewMI = addFrameReference(BuildMI(MF, MI->getDebugLoc(), get(PPC::LD)) + .addReg(OutReg, + RegState::Define | + getDeadRegState(isDead) | + getUndefRegState(isUndef)), + FrameIndex); + } + } else if (Opc == PPC::FMRD) { + if (OpNum == 0) { // move -> store + unsigned InReg = MI->getOperand(1).getReg(); + bool isKill = MI->getOperand(1).isKill(); + bool isUndef = MI->getOperand(1).isUndef(); + NewMI = addFrameReference(BuildMI(MF, MI->getDebugLoc(), get(PPC::STFD)) + .addReg(InReg, + getKillRegState(isKill) | + getUndefRegState(isUndef)), + FrameIndex); + } else { // move -> load + unsigned OutReg = MI->getOperand(0).getReg(); + bool isDead = MI->getOperand(0).isDead(); + bool isUndef = MI->getOperand(0).isUndef(); + NewMI = addFrameReference(BuildMI(MF, MI->getDebugLoc(), get(PPC::LFD)) + .addReg(OutReg, + RegState::Define | + getDeadRegState(isDead) | + getUndefRegState(isUndef)), + FrameIndex); + } + } else if (Opc == PPC::FMRS) { + if (OpNum == 0) { // move -> store + unsigned InReg = MI->getOperand(1).getReg(); + bool isKill = MI->getOperand(1).isKill(); + bool isUndef = MI->getOperand(1).isUndef(); + NewMI = addFrameReference(BuildMI(MF, MI->getDebugLoc(), get(PPC::STFS)) + .addReg(InReg, + getKillRegState(isKill) | + getUndefRegState(isUndef)), + FrameIndex); + } else { // move -> load + unsigned OutReg = MI->getOperand(0).getReg(); + bool isDead = MI->getOperand(0).isDead(); + bool isUndef = MI->getOperand(0).isUndef(); + NewMI = addFrameReference(BuildMI(MF, MI->getDebugLoc(), get(PPC::LFS)) + .addReg(OutReg, + RegState::Define | + getDeadRegState(isDead) | + getUndefRegState(isUndef)), + FrameIndex); + } + } + + return NewMI; +} + +bool PPCInstrInfo::canFoldMemoryOperand(const MachineInstr *MI, + const SmallVectorImpl &Ops) const { + if (Ops.size() != 1) return false; + + // Make sure this is a reg-reg copy. Note that we can't handle MCRF, because + // it takes more than one instruction to store it. + unsigned Opc = MI->getOpcode(); + + if ((Opc == PPC::OR && + MI->getOperand(1).getReg() == MI->getOperand(2).getReg())) + return true; + else if ((Opc == PPC::OR8 && + MI->getOperand(1).getReg() == MI->getOperand(2).getReg())) + return true; + else if (Opc == PPC::FMRD || Opc == PPC::FMRS) + return true; + + return false; +} + + +bool PPCInstrInfo::BlockHasNoFallThrough(const MachineBasicBlock &MBB) const { + if (MBB.empty()) return false; + + switch (MBB.back().getOpcode()) { + case PPC::BLR: // Return. + case PPC::B: // Uncond branch. + case PPC::BCTR: // Indirect branch. + return true; + default: return false; + } +} + +bool PPCInstrInfo:: +ReverseBranchCondition(SmallVectorImpl &Cond) const { + assert(Cond.size() == 2 && "Invalid PPC branch opcode!"); + // Leave the CR# the same, but invert the condition. + Cond[0].setImm(PPC::InvertPredicate((PPC::Predicate)Cond[0].getImm())); + return false; +} + +/// GetInstSize - Return the number of bytes of code the specified +/// instruction may be. This returns the maximum number of bytes. +/// +unsigned PPCInstrInfo::GetInstSizeInBytes(const MachineInstr *MI) const { + switch (MI->getOpcode()) { + case PPC::INLINEASM: { // Inline Asm: Variable size. + const MachineFunction *MF = MI->getParent()->getParent(); + const char *AsmStr = MI->getOperand(0).getSymbolName(); + return getInlineAsmLength(AsmStr, *MF->getTarget().getMCAsmInfo()); + } + case PPC::DBG_LABEL: + case PPC::EH_LABEL: + case PPC::GC_LABEL: + return 0; + default: + return 4; // PowerPC instructions are all 4 bytes + } +} diff --git a/libclamav/c++/llvm/lib/Target/PowerPC/PPCInstrInfo.h b/libclamav/c++/llvm/lib/Target/PowerPC/PPCInstrInfo.h new file mode 100644 index 000000000..ab341bd77 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/PowerPC/PPCInstrInfo.h @@ -0,0 +1,160 @@ +//===- PPCInstrInfo.h - PowerPC Instruction Information ---------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the PowerPC implementation of the TargetInstrInfo class. +// +//===----------------------------------------------------------------------===// + +#ifndef POWERPC32_INSTRUCTIONINFO_H +#define POWERPC32_INSTRUCTIONINFO_H + +#include "PPC.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "PPCRegisterInfo.h" + +namespace llvm { + +/// PPCII - This namespace holds all of the PowerPC target-specific +/// per-instruction flags. These must match the corresponding definitions in +/// PPC.td and PPCInstrFormats.td. +namespace PPCII { +enum { + // PPC970 Instruction Flags. These flags describe the characteristics of the + // PowerPC 970 (aka G5) dispatch groups and how they are formed out of + // raw machine instructions. + + /// PPC970_First - This instruction starts a new dispatch group, so it will + /// always be the first one in the group. + PPC970_First = 0x1, + + /// PPC970_Single - This instruction starts a new dispatch group and + /// terminates it, so it will be the sole instruction in the group. + PPC970_Single = 0x2, + + /// PPC970_Cracked - This instruction is cracked into two pieces, requiring + /// two dispatch pipes to be available to issue. + PPC970_Cracked = 0x4, + + /// PPC970_Mask/Shift - This is a bitmask that selects the pipeline type that + /// an instruction is issued to. + PPC970_Shift = 3, + PPC970_Mask = 0x07 << PPC970_Shift +}; +enum PPC970_Unit { + /// These are the various PPC970 execution unit pipelines. Each instruction + /// is one of these. + PPC970_Pseudo = 0 << PPC970_Shift, // Pseudo instruction + PPC970_FXU = 1 << PPC970_Shift, // Fixed Point (aka Integer/ALU) Unit + PPC970_LSU = 2 << PPC970_Shift, // Load Store Unit + PPC970_FPU = 3 << PPC970_Shift, // Floating Point Unit + PPC970_CRU = 4 << PPC970_Shift, // Control Register Unit + PPC970_VALU = 5 << PPC970_Shift, // Vector ALU + PPC970_VPERM = 6 << PPC970_Shift, // Vector Permute Unit + PPC970_BRU = 7 << PPC970_Shift // Branch Unit +}; +} + + +class PPCInstrInfo : public TargetInstrInfoImpl { + PPCTargetMachine &TM; + const PPCRegisterInfo RI; + + bool StoreRegToStackSlot(MachineFunction &MF, + unsigned SrcReg, bool isKill, int FrameIdx, + const TargetRegisterClass *RC, + SmallVectorImpl &NewMIs) const; + void LoadRegFromStackSlot(MachineFunction &MF, DebugLoc DL, + unsigned DestReg, int FrameIdx, + const TargetRegisterClass *RC, + SmallVectorImpl &NewMIs) const; +public: + explicit PPCInstrInfo(PPCTargetMachine &TM); + + /// getRegisterInfo - TargetInstrInfo is a superset of MRegister info. As + /// such, whenever a client has an instance of instruction info, it should + /// always be able to get register info as well (through this method). + /// + virtual const PPCRegisterInfo &getRegisterInfo() const { return RI; } + + /// Return true if the instruction is a register to register move and return + /// the source and dest operands and their sub-register indices by reference. + virtual bool isMoveInstr(const MachineInstr &MI, + unsigned &SrcReg, unsigned &DstReg, + unsigned &SrcSubIdx, unsigned &DstSubIdx) const; + + unsigned isLoadFromStackSlot(const MachineInstr *MI, + int &FrameIndex) const; + unsigned isStoreToStackSlot(const MachineInstr *MI, + int &FrameIndex) const; + + // commuteInstruction - We can commute rlwimi instructions, but only if the + // rotate amt is zero. We also have to munge the immediates a bit. + virtual MachineInstr *commuteInstruction(MachineInstr *MI, bool NewMI) const; + + virtual void insertNoop(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI) const; + + + // Branch analysis. + virtual bool AnalyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, + MachineBasicBlock *&FBB, + SmallVectorImpl &Cond, + bool AllowModify) const; + virtual unsigned RemoveBranch(MachineBasicBlock &MBB) const; + virtual unsigned InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, + MachineBasicBlock *FBB, + const SmallVectorImpl &Cond) const; + virtual bool copyRegToReg(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + unsigned DestReg, unsigned SrcReg, + const TargetRegisterClass *DestRC, + const TargetRegisterClass *SrcRC) const; + + virtual void storeRegToStackSlot(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MBBI, + unsigned SrcReg, bool isKill, int FrameIndex, + const TargetRegisterClass *RC) const; + + virtual void loadRegFromStackSlot(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MBBI, + unsigned DestReg, int FrameIndex, + const TargetRegisterClass *RC) const; + + /// foldMemoryOperand - PowerPC (like most RISC's) can only fold spills into + /// copy instructions, turning them into load/store instructions. + virtual MachineInstr* foldMemoryOperandImpl(MachineFunction &MF, + MachineInstr* MI, + const SmallVectorImpl &Ops, + int FrameIndex) const; + + virtual MachineInstr* foldMemoryOperandImpl(MachineFunction &MF, + MachineInstr* MI, + const SmallVectorImpl &Ops, + MachineInstr* LoadMI) const { + return 0; + } + + virtual bool canFoldMemoryOperand(const MachineInstr *MI, + const SmallVectorImpl &Ops) const; + + virtual bool BlockHasNoFallThrough(const MachineBasicBlock &MBB) const; + virtual + bool ReverseBranchCondition(SmallVectorImpl &Cond) const; + + /// GetInstSize - Return the number of bytes of code the specified + /// instruction may be. This returns the maximum number of bytes. + /// + virtual unsigned GetInstSizeInBytes(const MachineInstr *MI) const; + + virtual bool isProfitableToDuplicateIndirectBranch() const { return true; } +}; + +} + +#endif diff --git a/libclamav/c++/llvm/lib/Target/PowerPC/PPCInstrInfo.td b/libclamav/c++/llvm/lib/Target/PowerPC/PPCInstrInfo.td new file mode 100644 index 000000000..2b3f80da5 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/PowerPC/PPCInstrInfo.td @@ -0,0 +1,1489 @@ +//===- PPCInstrInfo.td - The PowerPC Instruction Set -------*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file describes the subset of the 32-bit PowerPC instruction set, as used +// by the PowerPC instruction selector. +// +//===----------------------------------------------------------------------===// + +include "PPCInstrFormats.td" + +//===----------------------------------------------------------------------===// +// PowerPC specific type constraints. +// +def SDT_PPCstfiwx : SDTypeProfile<0, 2, [ // stfiwx + SDTCisVT<0, f64>, SDTCisPtrTy<1> +]>; +def SDT_PPCCallSeqStart : SDCallSeqStart<[ SDTCisVT<0, i32> ]>; +def SDT_PPCCallSeqEnd : SDCallSeqEnd<[ SDTCisVT<0, i32>, + SDTCisVT<1, i32> ]>; +def SDT_PPCvperm : SDTypeProfile<1, 3, [ + SDTCisVT<3, v16i8>, SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2> +]>; + +def SDT_PPCvcmp : SDTypeProfile<1, 3, [ + SDTCisSameAs<0, 1>, SDTCisSameAs<1, 2>, SDTCisVT<3, i32> +]>; + +def SDT_PPCcondbr : SDTypeProfile<0, 3, [ + SDTCisVT<0, i32>, SDTCisVT<2, OtherVT> +]>; + +def SDT_PPClbrx : SDTypeProfile<1, 2, [ + SDTCisVT<0, i32>, SDTCisPtrTy<1>, SDTCisVT<2, OtherVT> +]>; +def SDT_PPCstbrx : SDTypeProfile<0, 3, [ + SDTCisVT<0, i32>, SDTCisPtrTy<1>, SDTCisVT<2, OtherVT> +]>; + +def SDT_PPClarx : SDTypeProfile<1, 1, [ + SDTCisInt<0>, SDTCisPtrTy<1> +]>; +def SDT_PPCstcx : SDTypeProfile<0, 2, [ + SDTCisInt<0>, SDTCisPtrTy<1> +]>; + +def SDT_PPCTC_ret : SDTypeProfile<0, 2, [ + SDTCisPtrTy<0>, SDTCisVT<1, i32> +]>; + +def SDT_PPCnop : SDTypeProfile<0, 0, []>; + +//===----------------------------------------------------------------------===// +// PowerPC specific DAG Nodes. +// + +def PPCfcfid : SDNode<"PPCISD::FCFID" , SDTFPUnaryOp, []>; +def PPCfctidz : SDNode<"PPCISD::FCTIDZ", SDTFPUnaryOp, []>; +def PPCfctiwz : SDNode<"PPCISD::FCTIWZ", SDTFPUnaryOp, []>; +def PPCstfiwx : SDNode<"PPCISD::STFIWX", SDT_PPCstfiwx, + [SDNPHasChain, SDNPMayStore]>; + +// This sequence is used for long double->int conversions. It changes the +// bits in the FPSCR which is not modelled. +def PPCmffs : SDNode<"PPCISD::MFFS", SDTypeProfile<1, 0, [SDTCisVT<0, f64>]>, + [SDNPOutFlag]>; +def PPCmtfsb0 : SDNode<"PPCISD::MTFSB0", SDTypeProfile<0, 1, [SDTCisInt<0>]>, + [SDNPInFlag, SDNPOutFlag]>; +def PPCmtfsb1 : SDNode<"PPCISD::MTFSB1", SDTypeProfile<0, 1, [SDTCisInt<0>]>, + [SDNPInFlag, SDNPOutFlag]>; +def PPCfaddrtz: SDNode<"PPCISD::FADDRTZ", SDTFPBinOp, + [SDNPInFlag, SDNPOutFlag]>; +def PPCmtfsf : SDNode<"PPCISD::MTFSF", SDTypeProfile<1, 3, + [SDTCisVT<0, f64>, SDTCisInt<1>, SDTCisVT<2, f64>, + SDTCisVT<3, f64>]>, + [SDNPInFlag]>; + +def PPCfsel : SDNode<"PPCISD::FSEL", + // Type constraint for fsel. + SDTypeProfile<1, 3, [SDTCisSameAs<0, 2>, SDTCisSameAs<0, 3>, + SDTCisFP<0>, SDTCisVT<1, f64>]>, []>; + +def PPChi : SDNode<"PPCISD::Hi", SDTIntBinOp, []>; +def PPClo : SDNode<"PPCISD::Lo", SDTIntBinOp, []>; +def PPCtoc_entry: SDNode<"PPCISD::TOC_ENTRY", SDTIntBinOp, [SDNPMayLoad]>; +def PPCvmaddfp : SDNode<"PPCISD::VMADDFP", SDTFPTernaryOp, []>; +def PPCvnmsubfp : SDNode<"PPCISD::VNMSUBFP", SDTFPTernaryOp, []>; + +def PPCvperm : SDNode<"PPCISD::VPERM", SDT_PPCvperm, []>; + +// These nodes represent the 32-bit PPC shifts that operate on 6-bit shift +// amounts. These nodes are generated by the multi-precision shift code. +def PPCsrl : SDNode<"PPCISD::SRL" , SDTIntShiftOp>; +def PPCsra : SDNode<"PPCISD::SRA" , SDTIntShiftOp>; +def PPCshl : SDNode<"PPCISD::SHL" , SDTIntShiftOp>; + +def PPCextsw_32 : SDNode<"PPCISD::EXTSW_32" , SDTIntUnaryOp>; +def PPCstd_32 : SDNode<"PPCISD::STD_32" , SDTStore, + [SDNPHasChain, SDNPMayStore]>; + +// These are target-independent nodes, but have target-specific formats. +def callseq_start : SDNode<"ISD::CALLSEQ_START", SDT_PPCCallSeqStart, + [SDNPHasChain, SDNPOutFlag]>; +def callseq_end : SDNode<"ISD::CALLSEQ_END", SDT_PPCCallSeqEnd, + [SDNPHasChain, SDNPOptInFlag, SDNPOutFlag]>; + +def SDT_PPCCall : SDTypeProfile<0, -1, [SDTCisInt<0>]>; +def PPCcall_Darwin : SDNode<"PPCISD::CALL_Darwin", SDT_PPCCall, + [SDNPHasChain, SDNPOptInFlag, SDNPOutFlag]>; +def PPCcall_SVR4 : SDNode<"PPCISD::CALL_SVR4", SDT_PPCCall, + [SDNPHasChain, SDNPOptInFlag, SDNPOutFlag]>; +def PPCnop : SDNode<"PPCISD::NOP", SDT_PPCnop, [SDNPInFlag, SDNPOutFlag]>; +def PPCmtctr : SDNode<"PPCISD::MTCTR", SDT_PPCCall, + [SDNPHasChain, SDNPOptInFlag, SDNPOutFlag]>; +def PPCbctrl_Darwin : SDNode<"PPCISD::BCTRL_Darwin", SDTNone, + [SDNPHasChain, SDNPOptInFlag, SDNPOutFlag]>; + +def PPCbctrl_SVR4 : SDNode<"PPCISD::BCTRL_SVR4", SDTNone, + [SDNPHasChain, SDNPOptInFlag, SDNPOutFlag]>; + +def retflag : SDNode<"PPCISD::RET_FLAG", SDTNone, + [SDNPHasChain, SDNPOptInFlag]>; + +def PPCtc_return : SDNode<"PPCISD::TC_RETURN", SDT_PPCTC_ret, + [SDNPHasChain, SDNPOptInFlag]>; + +def PPCvcmp : SDNode<"PPCISD::VCMP" , SDT_PPCvcmp, []>; +def PPCvcmp_o : SDNode<"PPCISD::VCMPo", SDT_PPCvcmp, [SDNPOutFlag]>; + +def PPCcondbranch : SDNode<"PPCISD::COND_BRANCH", SDT_PPCcondbr, + [SDNPHasChain, SDNPOptInFlag]>; + +def PPClbrx : SDNode<"PPCISD::LBRX", SDT_PPClbrx, + [SDNPHasChain, SDNPMayLoad]>; +def PPCstbrx : SDNode<"PPCISD::STBRX", SDT_PPCstbrx, + [SDNPHasChain, SDNPMayStore]>; + +// Instructions to support atomic operations +def PPClarx : SDNode<"PPCISD::LARX", SDT_PPClarx, + [SDNPHasChain, SDNPMayLoad]>; +def PPCstcx : SDNode<"PPCISD::STCX", SDT_PPCstcx, + [SDNPHasChain, SDNPMayStore]>; + +// Instructions to support dynamic alloca. +def SDTDynOp : SDTypeProfile<1, 2, []>; +def PPCdynalloc : SDNode<"PPCISD::DYNALLOC", SDTDynOp, [SDNPHasChain]>; + +//===----------------------------------------------------------------------===// +// PowerPC specific transformation functions and pattern fragments. +// + +def SHL32 : SDNodeXFormgetZExtValue()); +}]>; + +def SRL32 : SDNodeXFormgetZExtValue() ? getI32Imm(32 - N->getZExtValue()) : getI32Imm(0); +}]>; + +def LO16 : SDNodeXFormgetZExtValue()); +}]>; + +def HI16 : SDNodeXFormgetZExtValue() >> 16); +}]>; + +def HA16 : SDNodeXFormgetZExtValue(); + return getI32Imm((Val - (signed short)Val) >> 16); +}]>; +def MB : SDNodeXFormgetZExtValue(), mb, me); + return getI32Imm(mb); +}]>; + +def ME : SDNodeXFormgetZExtValue(), mb, me); + return getI32Imm(me); +}]>; +def maskimm32 : PatLeaf<(imm), [{ + // maskImm predicate - True if immediate is a run of ones. + unsigned mb, me; + if (N->getValueType(0) == MVT::i32) + return isRunOfOnes((unsigned)N->getZExtValue(), mb, me); + else + return false; +}]>; + +def immSExt16 : PatLeaf<(imm), [{ + // immSExt16 predicate - True if the immediate fits in a 16-bit sign extended + // field. Used by instructions like 'addi'. + if (N->getValueType(0) == MVT::i32) + return (int32_t)N->getZExtValue() == (short)N->getZExtValue(); + else + return (int64_t)N->getZExtValue() == (short)N->getZExtValue(); +}]>; +def immZExt16 : PatLeaf<(imm), [{ + // immZExt16 predicate - True if the immediate fits in a 16-bit zero extended + // field. Used by instructions like 'ori'. + return (uint64_t)N->getZExtValue() == (unsigned short)N->getZExtValue(); +}], LO16>; + +// imm16Shifted* - These match immediates where the low 16-bits are zero. There +// are two forms: imm16ShiftedSExt and imm16ShiftedZExt. These two forms are +// identical in 32-bit mode, but in 64-bit mode, they return true if the +// immediate fits into a sign/zero extended 32-bit immediate (with the low bits +// clear). +def imm16ShiftedZExt : PatLeaf<(imm), [{ + // imm16ShiftedZExt predicate - True if only bits in the top 16-bits of the + // immediate are set. Used by instructions like 'xoris'. + return (N->getZExtValue() & ~uint64_t(0xFFFF0000)) == 0; +}], HI16>; + +def imm16ShiftedSExt : PatLeaf<(imm), [{ + // imm16ShiftedSExt predicate - True if only bits in the top 16-bits of the + // immediate are set. Used by instructions like 'addis'. Identical to + // imm16ShiftedZExt in 32-bit mode. + if (N->getZExtValue() & 0xFFFF) return false; + if (N->getValueType(0) == MVT::i32) + return true; + // For 64-bit, make sure it is sext right. + return N->getZExtValue() == (uint64_t)(int)N->getZExtValue(); +}], HI16>; + + +//===----------------------------------------------------------------------===// +// PowerPC Flag Definitions. + +class isPPC64 { bit PPC64 = 1; } +class isDOT { + list Defs = [CR0]; + bit RC = 1; +} + +class RegConstraint { + string Constraints = C; +} +class NoEncode { + string DisableEncoding = E; +} + + +//===----------------------------------------------------------------------===// +// PowerPC Operand Definitions. + +def s5imm : Operand { + let PrintMethod = "printS5ImmOperand"; +} +def u5imm : Operand { + let PrintMethod = "printU5ImmOperand"; +} +def u6imm : Operand { + let PrintMethod = "printU6ImmOperand"; +} +def s16imm : Operand { + let PrintMethod = "printS16ImmOperand"; +} +def u16imm : Operand { + let PrintMethod = "printU16ImmOperand"; +} +def s16immX4 : Operand { // Multiply imm by 4 before printing. + let PrintMethod = "printS16X4ImmOperand"; +} +def target : Operand { + let PrintMethod = "printBranchOperand"; +} +def calltarget : Operand { + let PrintMethod = "printCallOperand"; +} +def aaddr : Operand { + let PrintMethod = "printAbsAddrOperand"; +} +def piclabel: Operand { + let PrintMethod = "printPICLabel"; +} +def symbolHi: Operand { + let PrintMethod = "printSymbolHi"; +} +def symbolLo: Operand { + let PrintMethod = "printSymbolLo"; +} +def crbitm: Operand { + let PrintMethod = "printcrbitm"; +} +// Address operands +def memri : Operand { + let PrintMethod = "printMemRegImm"; + let MIOperandInfo = (ops i32imm:$imm, ptr_rc:$reg); +} +def memrr : Operand { + let PrintMethod = "printMemRegReg"; + let MIOperandInfo = (ops ptr_rc, ptr_rc); +} +def memrix : Operand { // memri where the imm is shifted 2 bits. + let PrintMethod = "printMemRegImmShifted"; + let MIOperandInfo = (ops i32imm:$imm, ptr_rc:$reg); +} +def tocentry : Operand { + let PrintMethod = "printTOCEntryLabel"; + let MIOperandInfo = (ops i32imm:$imm); +} + +// PowerPC Predicate operand. 20 = (0<<5)|20 = always, CR0 is a dummy reg +// that doesn't matter. +def pred : PredicateOperand { + let PrintMethod = "printPredicateOperand"; +} + +// Define PowerPC specific addressing mode. +def iaddr : ComplexPattern; +def xaddr : ComplexPattern; +def xoaddr : ComplexPattern; +def ixaddr : ComplexPattern; // "std" + +/// This is just the offset part of iaddr, used for preinc. +def iaddroff : ComplexPattern; + +//===----------------------------------------------------------------------===// +// PowerPC Instruction Predicate Definitions. +def FPContractions : Predicate<"!NoExcessFPPrecision">; +def In32BitMode : Predicate<"!PPCSubTarget.isPPC64()">; +def In64BitMode : Predicate<"PPCSubTarget.isPPC64()">; + + +//===----------------------------------------------------------------------===// +// PowerPC Instruction Definitions. + +// Pseudo-instructions: + +let hasCtrlDep = 1 in { +let Defs = [R1], Uses = [R1] in { +def ADJCALLSTACKDOWN : Pseudo<(outs), (ins u16imm:$amt), + "${:comment} ADJCALLSTACKDOWN", + [(callseq_start timm:$amt)]>; +def ADJCALLSTACKUP : Pseudo<(outs), (ins u16imm:$amt1, u16imm:$amt2), + "${:comment} ADJCALLSTACKUP", + [(callseq_end timm:$amt1, timm:$amt2)]>; +} + +def UPDATE_VRSAVE : Pseudo<(outs GPRC:$rD), (ins GPRC:$rS), + "UPDATE_VRSAVE $rD, $rS", []>; +} + +let Defs = [R1], Uses = [R1] in +def DYNALLOC : Pseudo<(outs GPRC:$result), (ins GPRC:$negsize, memri:$fpsi), + "${:comment} DYNALLOC $result, $negsize, $fpsi", + [(set GPRC:$result, + (PPCdynalloc GPRC:$negsize, iaddr:$fpsi))]>; + +// SELECT_CC_* - Used to implement the SELECT_CC DAG operation. Expanded after +// instruction selection into a branch sequence. +let usesCustomInserter = 1, // Expanded after instruction selection. + PPC970_Single = 1 in { + def SELECT_CC_I4 : Pseudo<(outs GPRC:$dst), (ins CRRC:$cond, GPRC:$T, GPRC:$F, + i32imm:$BROPC), "${:comment} SELECT_CC PSEUDO!", + []>; + def SELECT_CC_I8 : Pseudo<(outs G8RC:$dst), (ins CRRC:$cond, G8RC:$T, G8RC:$F, + i32imm:$BROPC), "${:comment} SELECT_CC PSEUDO!", + []>; + def SELECT_CC_F4 : Pseudo<(outs F4RC:$dst), (ins CRRC:$cond, F4RC:$T, F4RC:$F, + i32imm:$BROPC), "${:comment} SELECT_CC PSEUDO!", + []>; + def SELECT_CC_F8 : Pseudo<(outs F8RC:$dst), (ins CRRC:$cond, F8RC:$T, F8RC:$F, + i32imm:$BROPC), "${:comment} SELECT_CC PSEUDO!", + []>; + def SELECT_CC_VRRC: Pseudo<(outs VRRC:$dst), (ins CRRC:$cond, VRRC:$T, VRRC:$F, + i32imm:$BROPC), "${:comment} SELECT_CC PSEUDO!", + []>; +} + +// SPILL_CR - Indicate that we're dumping the CR register, so we'll need to +// scavenge a register for it. +def SPILL_CR : Pseudo<(outs), (ins GPRC:$cond, memri:$F), + "${:comment} SPILL_CR $cond $F", []>; + +let isTerminator = 1, isBarrier = 1, PPC970_Unit = 7 in { + let isReturn = 1, Uses = [LR, RM] in + def BLR : XLForm_2_br<19, 16, 0, (outs), (ins pred:$p), + "b${p:cc}lr ${p:reg}", BrB, + [(retflag)]>; + let isBranch = 1, isIndirectBranch = 1, Uses = [CTR] in + def BCTR : XLForm_2_ext<19, 528, 20, 0, 0, (outs), (ins), "bctr", BrB, []>; +} + +let Defs = [LR] in + def MovePCtoLR : Pseudo<(outs), (ins piclabel:$label), "bl $label", []>, + PPC970_Unit_BRU; + +let isBranch = 1, isTerminator = 1, hasCtrlDep = 1, PPC970_Unit = 7 in { + let isBarrier = 1 in { + def B : IForm<18, 0, 0, (outs), (ins target:$dst), + "b $dst", BrB, + [(br bb:$dst)]>; + } + + // BCC represents an arbitrary conditional branch on a predicate. + // FIXME: should be able to write a pattern for PPCcondbranch, but can't use + // a two-value operand where a dag node expects two operands. :( + def BCC : BForm<16, 0, 0, (outs), (ins pred:$cond, target:$dst), + "b${cond:cc} ${cond:reg}, $dst" + /*[(PPCcondbranch CRRC:$crS, imm:$opc, bb:$dst)]*/>; +} + +// Darwin ABI Calls. +let isCall = 1, PPC970_Unit = 7, + // All calls clobber the non-callee saved registers... + Defs = [R0,R2,R3,R4,R5,R6,R7,R8,R9,R10,R11,R12, + F0,F1,F2,F3,F4,F5,F6,F7,F8,F9,F10,F11,F12,F13, + V0,V1,V2,V3,V4,V5,V6,V7,V8,V9,V10,V11,V12,V13,V14,V15,V16,V17,V18,V19, + LR,CTR, + CR0,CR1,CR5,CR6,CR7, + CR0LT,CR0GT,CR0EQ,CR0UN,CR1LT,CR1GT,CR1EQ,CR1UN,CR5LT,CR5GT,CR5EQ, + CR5UN,CR6LT,CR6GT,CR6EQ,CR6UN,CR7LT,CR7GT,CR7EQ,CR7UN,CARRY] in { + // Convenient aliases for call instructions + let Uses = [RM] in { + def BL_Darwin : IForm<18, 0, 1, + (outs), (ins calltarget:$func, variable_ops), + "bl $func", BrB, []>; // See Pat patterns below. + def BLA_Darwin : IForm<18, 1, 1, + (outs), (ins aaddr:$func, variable_ops), + "bla $func", BrB, [(PPCcall_Darwin (i32 imm:$func))]>; + } + let Uses = [CTR, RM] in { + def BCTRL_Darwin : XLForm_2_ext<19, 528, 20, 0, 1, + (outs), (ins variable_ops), + "bctrl", BrB, + [(PPCbctrl_Darwin)]>, Requires<[In32BitMode]>; + } +} + +// SVR4 ABI Calls. +let isCall = 1, PPC970_Unit = 7, + // All calls clobber the non-callee saved registers... + Defs = [R0,R3,R4,R5,R6,R7,R8,R9,R10,R11,R12, + F0,F1,F2,F3,F4,F5,F6,F7,F8,F9,F10,F11,F12,F13, + V0,V1,V2,V3,V4,V5,V6,V7,V8,V9,V10,V11,V12,V13,V14,V15,V16,V17,V18,V19, + LR,CTR, + CR0,CR1,CR5,CR6,CR7, + CR0LT,CR0GT,CR0EQ,CR0UN,CR1LT,CR1GT,CR1EQ,CR1UN,CR5LT,CR5GT,CR5EQ, + CR5UN,CR6LT,CR6GT,CR6EQ,CR6UN,CR7LT,CR7GT,CR7EQ,CR7UN,CARRY] in { + // Convenient aliases for call instructions + let Uses = [RM] in { + def BL_SVR4 : IForm<18, 0, 1, + (outs), (ins calltarget:$func, variable_ops), + "bl $func", BrB, []>; // See Pat patterns below. + def BLA_SVR4 : IForm<18, 1, 1, + (outs), (ins aaddr:$func, variable_ops), + "bla $func", BrB, + [(PPCcall_SVR4 (i32 imm:$func))]>; + } + let Uses = [CTR, RM] in { + def BCTRL_SVR4 : XLForm_2_ext<19, 528, 20, 0, 1, + (outs), (ins variable_ops), + "bctrl", BrB, + [(PPCbctrl_SVR4)]>, Requires<[In32BitMode]>; + } +} + + +let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, Uses = [RM] in +def TCRETURNdi :Pseudo< (outs), + (ins calltarget:$dst, i32imm:$offset, variable_ops), + "#TC_RETURNd $dst $offset", + []>; + + +let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, Uses = [RM] in +def TCRETURNai :Pseudo<(outs), (ins aaddr:$func, i32imm:$offset, variable_ops), + "#TC_RETURNa $func $offset", + [(PPCtc_return (i32 imm:$func), imm:$offset)]>; + +let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, Uses = [RM] in +def TCRETURNri : Pseudo<(outs), (ins CTRRC:$dst, i32imm:$offset, variable_ops), + "#TC_RETURNr $dst $offset", + []>; + + +let isTerminator = 1, isBarrier = 1, PPC970_Unit = 7, isBranch = 1, + isIndirectBranch = 1, isCall = 1, isReturn = 1, Uses = [CTR, RM] in +def TAILBCTR : XLForm_2_ext<19, 528, 20, 0, 0, (outs), (ins), "bctr", BrB, []>, + Requires<[In32BitMode]>; + + + +let isBranch = 1, isTerminator = 1, hasCtrlDep = 1, PPC970_Unit = 7, + isBarrier = 1, isCall = 1, isReturn = 1, Uses = [RM] in +def TAILB : IForm<18, 0, 0, (outs), (ins calltarget:$dst), + "b $dst", BrB, + []>; + + +let isBranch = 1, isTerminator = 1, hasCtrlDep = 1, PPC970_Unit = 7, + isBarrier = 1, isCall = 1, isReturn = 1, Uses = [RM] in +def TAILBA : IForm<18, 0, 0, (outs), (ins aaddr:$dst), + "ba $dst", BrB, + []>; + + +// DCB* instructions. +def DCBA : DCB_Form<758, 0, (outs), (ins memrr:$dst), + "dcba $dst", LdStDCBF, [(int_ppc_dcba xoaddr:$dst)]>, + PPC970_DGroup_Single; +def DCBF : DCB_Form<86, 0, (outs), (ins memrr:$dst), + "dcbf $dst", LdStDCBF, [(int_ppc_dcbf xoaddr:$dst)]>, + PPC970_DGroup_Single; +def DCBI : DCB_Form<470, 0, (outs), (ins memrr:$dst), + "dcbi $dst", LdStDCBF, [(int_ppc_dcbi xoaddr:$dst)]>, + PPC970_DGroup_Single; +def DCBST : DCB_Form<54, 0, (outs), (ins memrr:$dst), + "dcbst $dst", LdStDCBF, [(int_ppc_dcbst xoaddr:$dst)]>, + PPC970_DGroup_Single; +def DCBT : DCB_Form<278, 0, (outs), (ins memrr:$dst), + "dcbt $dst", LdStDCBF, [(int_ppc_dcbt xoaddr:$dst)]>, + PPC970_DGroup_Single; +def DCBTST : DCB_Form<246, 0, (outs), (ins memrr:$dst), + "dcbtst $dst", LdStDCBF, [(int_ppc_dcbtst xoaddr:$dst)]>, + PPC970_DGroup_Single; +def DCBZ : DCB_Form<1014, 0, (outs), (ins memrr:$dst), + "dcbz $dst", LdStDCBF, [(int_ppc_dcbz xoaddr:$dst)]>, + PPC970_DGroup_Single; +def DCBZL : DCB_Form<1014, 1, (outs), (ins memrr:$dst), + "dcbzl $dst", LdStDCBF, [(int_ppc_dcbzl xoaddr:$dst)]>, + PPC970_DGroup_Single; + +// Atomic operations +let usesCustomInserter = 1 in { + let Uses = [CR0] in { + def ATOMIC_LOAD_ADD_I8 : Pseudo< + (outs GPRC:$dst), (ins memrr:$ptr, GPRC:$incr), + "${:comment} ATOMIC_LOAD_ADD_I8 PSEUDO!", + [(set GPRC:$dst, (atomic_load_add_8 xoaddr:$ptr, GPRC:$incr))]>; + def ATOMIC_LOAD_SUB_I8 : Pseudo< + (outs GPRC:$dst), (ins memrr:$ptr, GPRC:$incr), + "${:comment} ATOMIC_LOAD_SUB_I8 PSEUDO!", + [(set GPRC:$dst, (atomic_load_sub_8 xoaddr:$ptr, GPRC:$incr))]>; + def ATOMIC_LOAD_AND_I8 : Pseudo< + (outs GPRC:$dst), (ins memrr:$ptr, GPRC:$incr), + "${:comment} ATOMIC_LOAD_AND_I8 PSEUDO!", + [(set GPRC:$dst, (atomic_load_and_8 xoaddr:$ptr, GPRC:$incr))]>; + def ATOMIC_LOAD_OR_I8 : Pseudo< + (outs GPRC:$dst), (ins memrr:$ptr, GPRC:$incr), + "${:comment} ATOMIC_LOAD_OR_I8 PSEUDO!", + [(set GPRC:$dst, (atomic_load_or_8 xoaddr:$ptr, GPRC:$incr))]>; + def ATOMIC_LOAD_XOR_I8 : Pseudo< + (outs GPRC:$dst), (ins memrr:$ptr, GPRC:$incr), + "${:comment} ATOMIC_LOAD_XOR_I8 PSEUDO!", + [(set GPRC:$dst, (atomic_load_xor_8 xoaddr:$ptr, GPRC:$incr))]>; + def ATOMIC_LOAD_NAND_I8 : Pseudo< + (outs GPRC:$dst), (ins memrr:$ptr, GPRC:$incr), + "${:comment} ATOMIC_LOAD_NAND_I8 PSEUDO!", + [(set GPRC:$dst, (atomic_load_nand_8 xoaddr:$ptr, GPRC:$incr))]>; + def ATOMIC_LOAD_ADD_I16 : Pseudo< + (outs GPRC:$dst), (ins memrr:$ptr, GPRC:$incr), + "${:comment} ATOMIC_LOAD_ADD_I16 PSEUDO!", + [(set GPRC:$dst, (atomic_load_add_16 xoaddr:$ptr, GPRC:$incr))]>; + def ATOMIC_LOAD_SUB_I16 : Pseudo< + (outs GPRC:$dst), (ins memrr:$ptr, GPRC:$incr), + "${:comment} ATOMIC_LOAD_SUB_I16 PSEUDO!", + [(set GPRC:$dst, (atomic_load_sub_16 xoaddr:$ptr, GPRC:$incr))]>; + def ATOMIC_LOAD_AND_I16 : Pseudo< + (outs GPRC:$dst), (ins memrr:$ptr, GPRC:$incr), + "${:comment} ATOMIC_LOAD_AND_I16 PSEUDO!", + [(set GPRC:$dst, (atomic_load_and_16 xoaddr:$ptr, GPRC:$incr))]>; + def ATOMIC_LOAD_OR_I16 : Pseudo< + (outs GPRC:$dst), (ins memrr:$ptr, GPRC:$incr), + "${:comment} ATOMIC_LOAD_OR_I16 PSEUDO!", + [(set GPRC:$dst, (atomic_load_or_16 xoaddr:$ptr, GPRC:$incr))]>; + def ATOMIC_LOAD_XOR_I16 : Pseudo< + (outs GPRC:$dst), (ins memrr:$ptr, GPRC:$incr), + "${:comment} ATOMIC_LOAD_XOR_I16 PSEUDO!", + [(set GPRC:$dst, (atomic_load_xor_16 xoaddr:$ptr, GPRC:$incr))]>; + def ATOMIC_LOAD_NAND_I16 : Pseudo< + (outs GPRC:$dst), (ins memrr:$ptr, GPRC:$incr), + "${:comment} ATOMIC_LOAD_NAND_I16 PSEUDO!", + [(set GPRC:$dst, (atomic_load_nand_16 xoaddr:$ptr, GPRC:$incr))]>; + def ATOMIC_LOAD_ADD_I32 : Pseudo< + (outs GPRC:$dst), (ins memrr:$ptr, GPRC:$incr), + "${:comment} ATOMIC_LOAD_ADD_I32 PSEUDO!", + [(set GPRC:$dst, (atomic_load_add_32 xoaddr:$ptr, GPRC:$incr))]>; + def ATOMIC_LOAD_SUB_I32 : Pseudo< + (outs GPRC:$dst), (ins memrr:$ptr, GPRC:$incr), + "${:comment} ATOMIC_LOAD_SUB_I32 PSEUDO!", + [(set GPRC:$dst, (atomic_load_sub_32 xoaddr:$ptr, GPRC:$incr))]>; + def ATOMIC_LOAD_AND_I32 : Pseudo< + (outs GPRC:$dst), (ins memrr:$ptr, GPRC:$incr), + "${:comment} ATOMIC_LOAD_AND_I32 PSEUDO!", + [(set GPRC:$dst, (atomic_load_and_32 xoaddr:$ptr, GPRC:$incr))]>; + def ATOMIC_LOAD_OR_I32 : Pseudo< + (outs GPRC:$dst), (ins memrr:$ptr, GPRC:$incr), + "${:comment} ATOMIC_LOAD_OR_I32 PSEUDO!", + [(set GPRC:$dst, (atomic_load_or_32 xoaddr:$ptr, GPRC:$incr))]>; + def ATOMIC_LOAD_XOR_I32 : Pseudo< + (outs GPRC:$dst), (ins memrr:$ptr, GPRC:$incr), + "${:comment} ATOMIC_LOAD_XOR_I32 PSEUDO!", + [(set GPRC:$dst, (atomic_load_xor_32 xoaddr:$ptr, GPRC:$incr))]>; + def ATOMIC_LOAD_NAND_I32 : Pseudo< + (outs GPRC:$dst), (ins memrr:$ptr, GPRC:$incr), + "${:comment} ATOMIC_LOAD_NAND_I32 PSEUDO!", + [(set GPRC:$dst, (atomic_load_nand_32 xoaddr:$ptr, GPRC:$incr))]>; + + def ATOMIC_CMP_SWAP_I8 : Pseudo< + (outs GPRC:$dst), (ins memrr:$ptr, GPRC:$old, GPRC:$new), + "${:comment} ATOMIC_CMP_SWAP_I8 PSEUDO!", + [(set GPRC:$dst, + (atomic_cmp_swap_8 xoaddr:$ptr, GPRC:$old, GPRC:$new))]>; + def ATOMIC_CMP_SWAP_I16 : Pseudo< + (outs GPRC:$dst), (ins memrr:$ptr, GPRC:$old, GPRC:$new), + "${:comment} ATOMIC_CMP_SWAP_I16 PSEUDO!", + [(set GPRC:$dst, + (atomic_cmp_swap_16 xoaddr:$ptr, GPRC:$old, GPRC:$new))]>; + def ATOMIC_CMP_SWAP_I32 : Pseudo< + (outs GPRC:$dst), (ins memrr:$ptr, GPRC:$old, GPRC:$new), + "${:comment} ATOMIC_CMP_SWAP_I32 PSEUDO!", + [(set GPRC:$dst, + (atomic_cmp_swap_32 xoaddr:$ptr, GPRC:$old, GPRC:$new))]>; + + def ATOMIC_SWAP_I8 : Pseudo< + (outs GPRC:$dst), (ins memrr:$ptr, GPRC:$new), + "${:comment} ATOMIC_SWAP_I8 PSEUDO!", + [(set GPRC:$dst, (atomic_swap_8 xoaddr:$ptr, GPRC:$new))]>; + def ATOMIC_SWAP_I16 : Pseudo< + (outs GPRC:$dst), (ins memrr:$ptr, GPRC:$new), + "${:comment} ATOMIC_SWAP_I16 PSEUDO!", + [(set GPRC:$dst, (atomic_swap_16 xoaddr:$ptr, GPRC:$new))]>; + def ATOMIC_SWAP_I32 : Pseudo< + (outs GPRC:$dst), (ins memrr:$ptr, GPRC:$new), + "${:comment} ATOMIC_SWAP_I32 PSEUDO!", + [(set GPRC:$dst, (atomic_swap_32 xoaddr:$ptr, GPRC:$new))]>; + } +} + +// Instructions to support atomic operations +def LWARX : XForm_1<31, 20, (outs GPRC:$rD), (ins memrr:$src), + "lwarx $rD, $src", LdStLWARX, + [(set GPRC:$rD, (PPClarx xoaddr:$src))]>; + +let Defs = [CR0] in +def STWCX : XForm_1<31, 150, (outs), (ins GPRC:$rS, memrr:$dst), + "stwcx. $rS, $dst", LdStSTWCX, + [(PPCstcx GPRC:$rS, xoaddr:$dst)]>, + isDOT; + +let isBarrier = 1, hasCtrlDep = 1 in +def TRAP : XForm_24<31, 4, (outs), (ins), "trap", LdStGeneral, [(trap)]>; + +//===----------------------------------------------------------------------===// +// PPC32 Load Instructions. +// + +// Unindexed (r+i) Loads. +let canFoldAsLoad = 1, PPC970_Unit = 2 in { +def LBZ : DForm_1<34, (outs GPRC:$rD), (ins memri:$src), + "lbz $rD, $src", LdStGeneral, + [(set GPRC:$rD, (zextloadi8 iaddr:$src))]>; +def LHA : DForm_1<42, (outs GPRC:$rD), (ins memri:$src), + "lha $rD, $src", LdStLHA, + [(set GPRC:$rD, (sextloadi16 iaddr:$src))]>, + PPC970_DGroup_Cracked; +def LHZ : DForm_1<40, (outs GPRC:$rD), (ins memri:$src), + "lhz $rD, $src", LdStGeneral, + [(set GPRC:$rD, (zextloadi16 iaddr:$src))]>; +def LWZ : DForm_1<32, (outs GPRC:$rD), (ins memri:$src), + "lwz $rD, $src", LdStGeneral, + [(set GPRC:$rD, (load iaddr:$src))]>; + +def LFS : DForm_1<48, (outs F4RC:$rD), (ins memri:$src), + "lfs $rD, $src", LdStLFDU, + [(set F4RC:$rD, (load iaddr:$src))]>; +def LFD : DForm_1<50, (outs F8RC:$rD), (ins memri:$src), + "lfd $rD, $src", LdStLFD, + [(set F8RC:$rD, (load iaddr:$src))]>; + + +// Unindexed (r+i) Loads with Update (preinc). +let mayLoad = 1 in { +def LBZU : DForm_1<35, (outs GPRC:$rD, ptr_rc:$ea_result), (ins memri:$addr), + "lbzu $rD, $addr", LdStGeneral, + []>, RegConstraint<"$addr.reg = $ea_result">, + NoEncode<"$ea_result">; + +def LHAU : DForm_1<43, (outs GPRC:$rD, ptr_rc:$ea_result), (ins memri:$addr), + "lhau $rD, $addr", LdStGeneral, + []>, RegConstraint<"$addr.reg = $ea_result">, + NoEncode<"$ea_result">; + +def LHZU : DForm_1<41, (outs GPRC:$rD, ptr_rc:$ea_result), (ins memri:$addr), + "lhzu $rD, $addr", LdStGeneral, + []>, RegConstraint<"$addr.reg = $ea_result">, + NoEncode<"$ea_result">; + +def LWZU : DForm_1<33, (outs GPRC:$rD, ptr_rc:$ea_result), (ins memri:$addr), + "lwzu $rD, $addr", LdStGeneral, + []>, RegConstraint<"$addr.reg = $ea_result">, + NoEncode<"$ea_result">; + +def LFSU : DForm_1<49, (outs F4RC:$rD, ptr_rc:$ea_result), (ins memri:$addr), + "lfs $rD, $addr", LdStLFDU, + []>, RegConstraint<"$addr.reg = $ea_result">, + NoEncode<"$ea_result">; + +def LFDU : DForm_1<51, (outs F8RC:$rD, ptr_rc:$ea_result), (ins memri:$addr), + "lfd $rD, $addr", LdStLFD, + []>, RegConstraint<"$addr.reg = $ea_result">, + NoEncode<"$ea_result">; +} +} + +// Indexed (r+r) Loads. +// +let canFoldAsLoad = 1, PPC970_Unit = 2 in { +def LBZX : XForm_1<31, 87, (outs GPRC:$rD), (ins memrr:$src), + "lbzx $rD, $src", LdStGeneral, + [(set GPRC:$rD, (zextloadi8 xaddr:$src))]>; +def LHAX : XForm_1<31, 343, (outs GPRC:$rD), (ins memrr:$src), + "lhax $rD, $src", LdStLHA, + [(set GPRC:$rD, (sextloadi16 xaddr:$src))]>, + PPC970_DGroup_Cracked; +def LHZX : XForm_1<31, 279, (outs GPRC:$rD), (ins memrr:$src), + "lhzx $rD, $src", LdStGeneral, + [(set GPRC:$rD, (zextloadi16 xaddr:$src))]>; +def LWZX : XForm_1<31, 23, (outs GPRC:$rD), (ins memrr:$src), + "lwzx $rD, $src", LdStGeneral, + [(set GPRC:$rD, (load xaddr:$src))]>; + + +def LHBRX : XForm_1<31, 790, (outs GPRC:$rD), (ins memrr:$src), + "lhbrx $rD, $src", LdStGeneral, + [(set GPRC:$rD, (PPClbrx xoaddr:$src, i16))]>; +def LWBRX : XForm_1<31, 534, (outs GPRC:$rD), (ins memrr:$src), + "lwbrx $rD, $src", LdStGeneral, + [(set GPRC:$rD, (PPClbrx xoaddr:$src, i32))]>; + +def LFSX : XForm_25<31, 535, (outs F4RC:$frD), (ins memrr:$src), + "lfsx $frD, $src", LdStLFDU, + [(set F4RC:$frD, (load xaddr:$src))]>; +def LFDX : XForm_25<31, 599, (outs F8RC:$frD), (ins memrr:$src), + "lfdx $frD, $src", LdStLFDU, + [(set F8RC:$frD, (load xaddr:$src))]>; +} + +//===----------------------------------------------------------------------===// +// PPC32 Store Instructions. +// + +// Unindexed (r+i) Stores. +let PPC970_Unit = 2 in { +def STB : DForm_1<38, (outs), (ins GPRC:$rS, memri:$src), + "stb $rS, $src", LdStGeneral, + [(truncstorei8 GPRC:$rS, iaddr:$src)]>; +def STH : DForm_1<44, (outs), (ins GPRC:$rS, memri:$src), + "sth $rS, $src", LdStGeneral, + [(truncstorei16 GPRC:$rS, iaddr:$src)]>; +def STW : DForm_1<36, (outs), (ins GPRC:$rS, memri:$src), + "stw $rS, $src", LdStGeneral, + [(store GPRC:$rS, iaddr:$src)]>; +def STFS : DForm_1<52, (outs), (ins F4RC:$rS, memri:$dst), + "stfs $rS, $dst", LdStUX, + [(store F4RC:$rS, iaddr:$dst)]>; +def STFD : DForm_1<54, (outs), (ins F8RC:$rS, memri:$dst), + "stfd $rS, $dst", LdStUX, + [(store F8RC:$rS, iaddr:$dst)]>; +} + +// Unindexed (r+i) Stores with Update (preinc). +let PPC970_Unit = 2 in { +def STBU : DForm_1<39, (outs ptr_rc:$ea_res), (ins GPRC:$rS, + symbolLo:$ptroff, ptr_rc:$ptrreg), + "stbu $rS, $ptroff($ptrreg)", LdStGeneral, + [(set ptr_rc:$ea_res, + (pre_truncsti8 GPRC:$rS, ptr_rc:$ptrreg, + iaddroff:$ptroff))]>, + RegConstraint<"$ptrreg = $ea_res">, NoEncode<"$ea_res">; +def STHU : DForm_1<45, (outs ptr_rc:$ea_res), (ins GPRC:$rS, + symbolLo:$ptroff, ptr_rc:$ptrreg), + "sthu $rS, $ptroff($ptrreg)", LdStGeneral, + [(set ptr_rc:$ea_res, + (pre_truncsti16 GPRC:$rS, ptr_rc:$ptrreg, + iaddroff:$ptroff))]>, + RegConstraint<"$ptrreg = $ea_res">, NoEncode<"$ea_res">; +def STWU : DForm_1<37, (outs ptr_rc:$ea_res), (ins GPRC:$rS, + symbolLo:$ptroff, ptr_rc:$ptrreg), + "stwu $rS, $ptroff($ptrreg)", LdStGeneral, + [(set ptr_rc:$ea_res, (pre_store GPRC:$rS, ptr_rc:$ptrreg, + iaddroff:$ptroff))]>, + RegConstraint<"$ptrreg = $ea_res">, NoEncode<"$ea_res">; +def STFSU : DForm_1<37, (outs ptr_rc:$ea_res), (ins F4RC:$rS, + symbolLo:$ptroff, ptr_rc:$ptrreg), + "stfsu $rS, $ptroff($ptrreg)", LdStGeneral, + [(set ptr_rc:$ea_res, (pre_store F4RC:$rS, ptr_rc:$ptrreg, + iaddroff:$ptroff))]>, + RegConstraint<"$ptrreg = $ea_res">, NoEncode<"$ea_res">; +def STFDU : DForm_1<37, (outs ptr_rc:$ea_res), (ins F8RC:$rS, + symbolLo:$ptroff, ptr_rc:$ptrreg), + "stfdu $rS, $ptroff($ptrreg)", LdStGeneral, + [(set ptr_rc:$ea_res, (pre_store F8RC:$rS, ptr_rc:$ptrreg, + iaddroff:$ptroff))]>, + RegConstraint<"$ptrreg = $ea_res">, NoEncode<"$ea_res">; +} + + +// Indexed (r+r) Stores. +// +let PPC970_Unit = 2 in { +def STBX : XForm_8<31, 215, (outs), (ins GPRC:$rS, memrr:$dst), + "stbx $rS, $dst", LdStGeneral, + [(truncstorei8 GPRC:$rS, xaddr:$dst)]>, + PPC970_DGroup_Cracked; +def STHX : XForm_8<31, 407, (outs), (ins GPRC:$rS, memrr:$dst), + "sthx $rS, $dst", LdStGeneral, + [(truncstorei16 GPRC:$rS, xaddr:$dst)]>, + PPC970_DGroup_Cracked; +def STWX : XForm_8<31, 151, (outs), (ins GPRC:$rS, memrr:$dst), + "stwx $rS, $dst", LdStGeneral, + [(store GPRC:$rS, xaddr:$dst)]>, + PPC970_DGroup_Cracked; + +let mayStore = 1 in { +def STWUX : XForm_8<31, 183, (outs), (ins GPRC:$rS, GPRC:$rA, GPRC:$rB), + "stwux $rS, $rA, $rB", LdStGeneral, + []>; +} +def STHBRX: XForm_8<31, 918, (outs), (ins GPRC:$rS, memrr:$dst), + "sthbrx $rS, $dst", LdStGeneral, + [(PPCstbrx GPRC:$rS, xoaddr:$dst, i16)]>, + PPC970_DGroup_Cracked; +def STWBRX: XForm_8<31, 662, (outs), (ins GPRC:$rS, memrr:$dst), + "stwbrx $rS, $dst", LdStGeneral, + [(PPCstbrx GPRC:$rS, xoaddr:$dst, i32)]>, + PPC970_DGroup_Cracked; + +def STFIWX: XForm_28<31, 983, (outs), (ins F8RC:$frS, memrr:$dst), + "stfiwx $frS, $dst", LdStUX, + [(PPCstfiwx F8RC:$frS, xoaddr:$dst)]>; + +def STFSX : XForm_28<31, 663, (outs), (ins F4RC:$frS, memrr:$dst), + "stfsx $frS, $dst", LdStUX, + [(store F4RC:$frS, xaddr:$dst)]>; +def STFDX : XForm_28<31, 727, (outs), (ins F8RC:$frS, memrr:$dst), + "stfdx $frS, $dst", LdStUX, + [(store F8RC:$frS, xaddr:$dst)]>; +} + +let isBarrier = 1 in +def SYNC : XForm_24_sync<31, 598, (outs), (ins), + "sync", LdStSync, + [(int_ppc_sync)]>; + +//===----------------------------------------------------------------------===// +// PPC32 Arithmetic Instructions. +// + +let PPC970_Unit = 1 in { // FXU Operations. +def ADDI : DForm_2<14, (outs GPRC:$rD), (ins GPRC:$rA, s16imm:$imm), + "addi $rD, $rA, $imm", IntGeneral, + [(set GPRC:$rD, (add GPRC:$rA, immSExt16:$imm))]>; +let Defs = [CARRY] in { +def ADDIC : DForm_2<12, (outs GPRC:$rD), (ins GPRC:$rA, s16imm:$imm), + "addic $rD, $rA, $imm", IntGeneral, + [(set GPRC:$rD, (addc GPRC:$rA, immSExt16:$imm))]>, + PPC970_DGroup_Cracked; +def ADDICo : DForm_2<13, (outs GPRC:$rD), (ins GPRC:$rA, s16imm:$imm), + "addic. $rD, $rA, $imm", IntGeneral, + []>; +} +def ADDIS : DForm_2<15, (outs GPRC:$rD), (ins GPRC:$rA, symbolHi:$imm), + "addis $rD, $rA, $imm", IntGeneral, + [(set GPRC:$rD, (add GPRC:$rA, imm16ShiftedSExt:$imm))]>; +def LA : DForm_2<14, (outs GPRC:$rD), (ins GPRC:$rA, symbolLo:$sym), + "la $rD, $sym($rA)", IntGeneral, + [(set GPRC:$rD, (add GPRC:$rA, + (PPClo tglobaladdr:$sym, 0)))]>; +def MULLI : DForm_2< 7, (outs GPRC:$rD), (ins GPRC:$rA, s16imm:$imm), + "mulli $rD, $rA, $imm", IntMulLI, + [(set GPRC:$rD, (mul GPRC:$rA, immSExt16:$imm))]>; +let Defs = [CARRY] in { +def SUBFIC : DForm_2< 8, (outs GPRC:$rD), (ins GPRC:$rA, s16imm:$imm), + "subfic $rD, $rA, $imm", IntGeneral, + [(set GPRC:$rD, (subc immSExt16:$imm, GPRC:$rA))]>; +} + +let isReMaterializable = 1 in { + def LI : DForm_2_r0<14, (outs GPRC:$rD), (ins symbolLo:$imm), + "li $rD, $imm", IntGeneral, + [(set GPRC:$rD, immSExt16:$imm)]>; + def LIS : DForm_2_r0<15, (outs GPRC:$rD), (ins symbolHi:$imm), + "lis $rD, $imm", IntGeneral, + [(set GPRC:$rD, imm16ShiftedSExt:$imm)]>; +} +} + +let PPC970_Unit = 1 in { // FXU Operations. +def ANDIo : DForm_4<28, (outs GPRC:$dst), (ins GPRC:$src1, u16imm:$src2), + "andi. $dst, $src1, $src2", IntGeneral, + [(set GPRC:$dst, (and GPRC:$src1, immZExt16:$src2))]>, + isDOT; +def ANDISo : DForm_4<29, (outs GPRC:$dst), (ins GPRC:$src1, u16imm:$src2), + "andis. $dst, $src1, $src2", IntGeneral, + [(set GPRC:$dst, (and GPRC:$src1,imm16ShiftedZExt:$src2))]>, + isDOT; +def ORI : DForm_4<24, (outs GPRC:$dst), (ins GPRC:$src1, u16imm:$src2), + "ori $dst, $src1, $src2", IntGeneral, + [(set GPRC:$dst, (or GPRC:$src1, immZExt16:$src2))]>; +def ORIS : DForm_4<25, (outs GPRC:$dst), (ins GPRC:$src1, u16imm:$src2), + "oris $dst, $src1, $src2", IntGeneral, + [(set GPRC:$dst, (or GPRC:$src1, imm16ShiftedZExt:$src2))]>; +def XORI : DForm_4<26, (outs GPRC:$dst), (ins GPRC:$src1, u16imm:$src2), + "xori $dst, $src1, $src2", IntGeneral, + [(set GPRC:$dst, (xor GPRC:$src1, immZExt16:$src2))]>; +def XORIS : DForm_4<27, (outs GPRC:$dst), (ins GPRC:$src1, u16imm:$src2), + "xoris $dst, $src1, $src2", IntGeneral, + [(set GPRC:$dst, (xor GPRC:$src1,imm16ShiftedZExt:$src2))]>; +def NOP : DForm_4_zero<24, (outs), (ins), "nop", IntGeneral, + []>; +def CMPWI : DForm_5_ext<11, (outs CRRC:$crD), (ins GPRC:$rA, s16imm:$imm), + "cmpwi $crD, $rA, $imm", IntCompare>; +def CMPLWI : DForm_6_ext<10, (outs CRRC:$dst), (ins GPRC:$src1, u16imm:$src2), + "cmplwi $dst, $src1, $src2", IntCompare>; +} + + +let PPC970_Unit = 1 in { // FXU Operations. +def NAND : XForm_6<31, 476, (outs GPRC:$rA), (ins GPRC:$rS, GPRC:$rB), + "nand $rA, $rS, $rB", IntGeneral, + [(set GPRC:$rA, (not (and GPRC:$rS, GPRC:$rB)))]>; +def AND : XForm_6<31, 28, (outs GPRC:$rA), (ins GPRC:$rS, GPRC:$rB), + "and $rA, $rS, $rB", IntGeneral, + [(set GPRC:$rA, (and GPRC:$rS, GPRC:$rB))]>; +def ANDC : XForm_6<31, 60, (outs GPRC:$rA), (ins GPRC:$rS, GPRC:$rB), + "andc $rA, $rS, $rB", IntGeneral, + [(set GPRC:$rA, (and GPRC:$rS, (not GPRC:$rB)))]>; +def OR : XForm_6<31, 444, (outs GPRC:$rA), (ins GPRC:$rS, GPRC:$rB), + "or $rA, $rS, $rB", IntGeneral, + [(set GPRC:$rA, (or GPRC:$rS, GPRC:$rB))]>; +def NOR : XForm_6<31, 124, (outs GPRC:$rA), (ins GPRC:$rS, GPRC:$rB), + "nor $rA, $rS, $rB", IntGeneral, + [(set GPRC:$rA, (not (or GPRC:$rS, GPRC:$rB)))]>; +def ORC : XForm_6<31, 412, (outs GPRC:$rA), (ins GPRC:$rS, GPRC:$rB), + "orc $rA, $rS, $rB", IntGeneral, + [(set GPRC:$rA, (or GPRC:$rS, (not GPRC:$rB)))]>; +def EQV : XForm_6<31, 284, (outs GPRC:$rA), (ins GPRC:$rS, GPRC:$rB), + "eqv $rA, $rS, $rB", IntGeneral, + [(set GPRC:$rA, (not (xor GPRC:$rS, GPRC:$rB)))]>; +def XOR : XForm_6<31, 316, (outs GPRC:$rA), (ins GPRC:$rS, GPRC:$rB), + "xor $rA, $rS, $rB", IntGeneral, + [(set GPRC:$rA, (xor GPRC:$rS, GPRC:$rB))]>; +def SLW : XForm_6<31, 24, (outs GPRC:$rA), (ins GPRC:$rS, GPRC:$rB), + "slw $rA, $rS, $rB", IntGeneral, + [(set GPRC:$rA, (PPCshl GPRC:$rS, GPRC:$rB))]>; +def SRW : XForm_6<31, 536, (outs GPRC:$rA), (ins GPRC:$rS, GPRC:$rB), + "srw $rA, $rS, $rB", IntGeneral, + [(set GPRC:$rA, (PPCsrl GPRC:$rS, GPRC:$rB))]>; +let Defs = [CARRY] in { +def SRAW : XForm_6<31, 792, (outs GPRC:$rA), (ins GPRC:$rS, GPRC:$rB), + "sraw $rA, $rS, $rB", IntShift, + [(set GPRC:$rA, (PPCsra GPRC:$rS, GPRC:$rB))]>; +} +} + +let PPC970_Unit = 1 in { // FXU Operations. +let Defs = [CARRY] in { +def SRAWI : XForm_10<31, 824, (outs GPRC:$rA), (ins GPRC:$rS, u5imm:$SH), + "srawi $rA, $rS, $SH", IntShift, + [(set GPRC:$rA, (sra GPRC:$rS, (i32 imm:$SH)))]>; +} +def CNTLZW : XForm_11<31, 26, (outs GPRC:$rA), (ins GPRC:$rS), + "cntlzw $rA, $rS", IntGeneral, + [(set GPRC:$rA, (ctlz GPRC:$rS))]>; +def EXTSB : XForm_11<31, 954, (outs GPRC:$rA), (ins GPRC:$rS), + "extsb $rA, $rS", IntGeneral, + [(set GPRC:$rA, (sext_inreg GPRC:$rS, i8))]>; +def EXTSH : XForm_11<31, 922, (outs GPRC:$rA), (ins GPRC:$rS), + "extsh $rA, $rS", IntGeneral, + [(set GPRC:$rA, (sext_inreg GPRC:$rS, i16))]>; + +def CMPW : XForm_16_ext<31, 0, (outs CRRC:$crD), (ins GPRC:$rA, GPRC:$rB), + "cmpw $crD, $rA, $rB", IntCompare>; +def CMPLW : XForm_16_ext<31, 32, (outs CRRC:$crD), (ins GPRC:$rA, GPRC:$rB), + "cmplw $crD, $rA, $rB", IntCompare>; +} +let PPC970_Unit = 3 in { // FPU Operations. +//def FCMPO : XForm_17<63, 32, (outs CRRC:$crD), (ins FPRC:$fA, FPRC:$fB), +// "fcmpo $crD, $fA, $fB", FPCompare>; +def FCMPUS : XForm_17<63, 0, (outs CRRC:$crD), (ins F4RC:$fA, F4RC:$fB), + "fcmpu $crD, $fA, $fB", FPCompare>; +def FCMPUD : XForm_17<63, 0, (outs CRRC:$crD), (ins F8RC:$fA, F8RC:$fB), + "fcmpu $crD, $fA, $fB", FPCompare>; + +let Uses = [RM] in { + def FCTIWZ : XForm_26<63, 15, (outs F8RC:$frD), (ins F8RC:$frB), + "fctiwz $frD, $frB", FPGeneral, + [(set F8RC:$frD, (PPCfctiwz F8RC:$frB))]>; + def FRSP : XForm_26<63, 12, (outs F4RC:$frD), (ins F8RC:$frB), + "frsp $frD, $frB", FPGeneral, + [(set F4RC:$frD, (fround F8RC:$frB))]>; + def FSQRT : XForm_26<63, 22, (outs F8RC:$frD), (ins F8RC:$frB), + "fsqrt $frD, $frB", FPSqrt, + [(set F8RC:$frD, (fsqrt F8RC:$frB))]>; + def FSQRTS : XForm_26<59, 22, (outs F4RC:$frD), (ins F4RC:$frB), + "fsqrts $frD, $frB", FPSqrt, + [(set F4RC:$frD, (fsqrt F4RC:$frB))]>; + } +} + +/// FMR is split into 3 versions, one for 4/8 byte FP, and one for extending. +/// +/// Note that these are defined as pseudo-ops on the PPC970 because they are +/// often coalesced away and we don't want the dispatch group builder to think +/// that they will fill slots (which could cause the load of a LSU reject to +/// sneak into a d-group with a store). +def FMRS : XForm_26<63, 72, (outs F4RC:$frD), (ins F4RC:$frB), + "fmr $frD, $frB", FPGeneral, + []>, // (set F4RC:$frD, F4RC:$frB) + PPC970_Unit_Pseudo; +def FMRD : XForm_26<63, 72, (outs F8RC:$frD), (ins F8RC:$frB), + "fmr $frD, $frB", FPGeneral, + []>, // (set F8RC:$frD, F8RC:$frB) + PPC970_Unit_Pseudo; +def FMRSD : XForm_26<63, 72, (outs F8RC:$frD), (ins F4RC:$frB), + "fmr $frD, $frB", FPGeneral, + [(set F8RC:$frD, (fextend F4RC:$frB))]>, + PPC970_Unit_Pseudo; + +let PPC970_Unit = 3 in { // FPU Operations. +// These are artificially split into two different forms, for 4/8 byte FP. +def FABSS : XForm_26<63, 264, (outs F4RC:$frD), (ins F4RC:$frB), + "fabs $frD, $frB", FPGeneral, + [(set F4RC:$frD, (fabs F4RC:$frB))]>; +def FABSD : XForm_26<63, 264, (outs F8RC:$frD), (ins F8RC:$frB), + "fabs $frD, $frB", FPGeneral, + [(set F8RC:$frD, (fabs F8RC:$frB))]>; +def FNABSS : XForm_26<63, 136, (outs F4RC:$frD), (ins F4RC:$frB), + "fnabs $frD, $frB", FPGeneral, + [(set F4RC:$frD, (fneg (fabs F4RC:$frB)))]>; +def FNABSD : XForm_26<63, 136, (outs F8RC:$frD), (ins F8RC:$frB), + "fnabs $frD, $frB", FPGeneral, + [(set F8RC:$frD, (fneg (fabs F8RC:$frB)))]>; +def FNEGS : XForm_26<63, 40, (outs F4RC:$frD), (ins F4RC:$frB), + "fneg $frD, $frB", FPGeneral, + [(set F4RC:$frD, (fneg F4RC:$frB))]>; +def FNEGD : XForm_26<63, 40, (outs F8RC:$frD), (ins F8RC:$frB), + "fneg $frD, $frB", FPGeneral, + [(set F8RC:$frD, (fneg F8RC:$frB))]>; +} + + +// XL-Form instructions. condition register logical ops. +// +def MCRF : XLForm_3<19, 0, (outs CRRC:$BF), (ins CRRC:$BFA), + "mcrf $BF, $BFA", BrMCR>, + PPC970_DGroup_First, PPC970_Unit_CRU; + +def CREQV : XLForm_1<19, 289, (outs CRBITRC:$CRD), + (ins CRBITRC:$CRA, CRBITRC:$CRB), + "creqv $CRD, $CRA, $CRB", BrCR, + []>; + +def CROR : XLForm_1<19, 449, (outs CRBITRC:$CRD), + (ins CRBITRC:$CRA, CRBITRC:$CRB), + "cror $CRD, $CRA, $CRB", BrCR, + []>; + +def CRSET : XLForm_1_ext<19, 289, (outs CRBITRC:$dst), (ins), + "creqv $dst, $dst, $dst", BrCR, + []>; + +// XFX-Form instructions. Instructions that deal with SPRs. +// +let Uses = [CTR] in { +def MFCTR : XFXForm_1_ext<31, 339, 9, (outs GPRC:$rT), (ins), + "mfctr $rT", SprMFSPR>, + PPC970_DGroup_First, PPC970_Unit_FXU; +} +let Defs = [CTR], Pattern = [(PPCmtctr GPRC:$rS)] in { +def MTCTR : XFXForm_7_ext<31, 467, 9, (outs), (ins GPRC:$rS), + "mtctr $rS", SprMTSPR>, + PPC970_DGroup_First, PPC970_Unit_FXU; +} + +let Defs = [LR] in { +def MTLR : XFXForm_7_ext<31, 467, 8, (outs), (ins GPRC:$rS), + "mtlr $rS", SprMTSPR>, + PPC970_DGroup_First, PPC970_Unit_FXU; +} +let Uses = [LR] in { +def MFLR : XFXForm_1_ext<31, 339, 8, (outs GPRC:$rT), (ins), + "mflr $rT", SprMFSPR>, + PPC970_DGroup_First, PPC970_Unit_FXU; +} + +// Move to/from VRSAVE: despite being a SPR, the VRSAVE register is renamed like +// a GPR on the PPC970. As such, copies in and out have the same performance +// characteristics as an OR instruction. +def MTVRSAVE : XFXForm_7_ext<31, 467, 256, (outs), (ins GPRC:$rS), + "mtspr 256, $rS", IntGeneral>, + PPC970_DGroup_Single, PPC970_Unit_FXU; +def MFVRSAVE : XFXForm_1_ext<31, 339, 256, (outs GPRC:$rT), (ins), + "mfspr $rT, 256", IntGeneral>, + PPC970_DGroup_First, PPC970_Unit_FXU; + +def MTCRF : XFXForm_5<31, 144, (outs), (ins crbitm:$FXM, GPRC:$rS), + "mtcrf $FXM, $rS", BrMCRX>, + PPC970_MicroCode, PPC970_Unit_CRU; +// FIXME: this Uses all the CR registers. Marking it as such is +// necessary for DeadMachineInstructionElim to do the right thing. +// However, marking it also exposes PR 2964, and causes crashes in +// the Local RA because it doesn't like this sequence: +// vreg = MCRF CR0 +// MFCR +// For now DeadMachineInstructionElim is turned off, so don't do the marking. +def MFCR : XFXForm_3<31, 19, (outs GPRC:$rT), (ins), "mfcr $rT", SprMFCR>, + PPC970_MicroCode, PPC970_Unit_CRU; +def MFOCRF: XFXForm_5a<31, 19, (outs GPRC:$rT), (ins crbitm:$FXM), + "mfcr $rT, $FXM", SprMFCR>, + PPC970_DGroup_First, PPC970_Unit_CRU; + +// Instructions to manipulate FPSCR. Only long double handling uses these. +// FPSCR is not modelled; we use the SDNode Flag to keep things in order. + +let Uses = [RM], Defs = [RM] in { + def MTFSB0 : XForm_43<63, 70, (outs), (ins u5imm:$FM), + "mtfsb0 $FM", IntMTFSB0, + [(PPCmtfsb0 (i32 imm:$FM))]>, + PPC970_DGroup_Single, PPC970_Unit_FPU; + def MTFSB1 : XForm_43<63, 38, (outs), (ins u5imm:$FM), + "mtfsb1 $FM", IntMTFSB0, + [(PPCmtfsb1 (i32 imm:$FM))]>, + PPC970_DGroup_Single, PPC970_Unit_FPU; + // MTFSF does not actually produce an FP result. We pretend it copies + // input reg B to the output. If we didn't do this it would look like the + // instruction had no outputs (because we aren't modelling the FPSCR) and + // it would be deleted. + def MTFSF : XFLForm<63, 711, (outs F8RC:$FRA), + (ins i32imm:$FM, F8RC:$rT, F8RC:$FRB), + "mtfsf $FM, $rT", "$FRB = $FRA", IntMTFSB0, + [(set F8RC:$FRA, (PPCmtfsf (i32 imm:$FM), + F8RC:$rT, F8RC:$FRB))]>, + PPC970_DGroup_Single, PPC970_Unit_FPU; +} +let Uses = [RM] in { + def MFFS : XForm_42<63, 583, (outs F8RC:$rT), (ins), + "mffs $rT", IntMFFS, + [(set F8RC:$rT, (PPCmffs))]>, + PPC970_DGroup_Single, PPC970_Unit_FPU; + def FADDrtz: AForm_2<63, 21, + (outs F8RC:$FRT), (ins F8RC:$FRA, F8RC:$FRB), + "fadd $FRT, $FRA, $FRB", FPGeneral, + [(set F8RC:$FRT, (PPCfaddrtz F8RC:$FRA, F8RC:$FRB))]>, + PPC970_DGroup_Single, PPC970_Unit_FPU; +} + + +let PPC970_Unit = 1 in { // FXU Operations. + +// XO-Form instructions. Arithmetic instructions that can set overflow bit +// +def ADD4 : XOForm_1<31, 266, 0, (outs GPRC:$rT), (ins GPRC:$rA, GPRC:$rB), + "add $rT, $rA, $rB", IntGeneral, + [(set GPRC:$rT, (add GPRC:$rA, GPRC:$rB))]>; +let Defs = [CARRY] in { +def ADDC : XOForm_1<31, 10, 0, (outs GPRC:$rT), (ins GPRC:$rA, GPRC:$rB), + "addc $rT, $rA, $rB", IntGeneral, + [(set GPRC:$rT, (addc GPRC:$rA, GPRC:$rB))]>, + PPC970_DGroup_Cracked; +} +def DIVW : XOForm_1<31, 491, 0, (outs GPRC:$rT), (ins GPRC:$rA, GPRC:$rB), + "divw $rT, $rA, $rB", IntDivW, + [(set GPRC:$rT, (sdiv GPRC:$rA, GPRC:$rB))]>, + PPC970_DGroup_First, PPC970_DGroup_Cracked; +def DIVWU : XOForm_1<31, 459, 0, (outs GPRC:$rT), (ins GPRC:$rA, GPRC:$rB), + "divwu $rT, $rA, $rB", IntDivW, + [(set GPRC:$rT, (udiv GPRC:$rA, GPRC:$rB))]>, + PPC970_DGroup_First, PPC970_DGroup_Cracked; +def MULHW : XOForm_1<31, 75, 0, (outs GPRC:$rT), (ins GPRC:$rA, GPRC:$rB), + "mulhw $rT, $rA, $rB", IntMulHW, + [(set GPRC:$rT, (mulhs GPRC:$rA, GPRC:$rB))]>; +def MULHWU : XOForm_1<31, 11, 0, (outs GPRC:$rT), (ins GPRC:$rA, GPRC:$rB), + "mulhwu $rT, $rA, $rB", IntMulHWU, + [(set GPRC:$rT, (mulhu GPRC:$rA, GPRC:$rB))]>; +def MULLW : XOForm_1<31, 235, 0, (outs GPRC:$rT), (ins GPRC:$rA, GPRC:$rB), + "mullw $rT, $rA, $rB", IntMulHW, + [(set GPRC:$rT, (mul GPRC:$rA, GPRC:$rB))]>; +def SUBF : XOForm_1<31, 40, 0, (outs GPRC:$rT), (ins GPRC:$rA, GPRC:$rB), + "subf $rT, $rA, $rB", IntGeneral, + [(set GPRC:$rT, (sub GPRC:$rB, GPRC:$rA))]>; +let Defs = [CARRY] in { +def SUBFC : XOForm_1<31, 8, 0, (outs GPRC:$rT), (ins GPRC:$rA, GPRC:$rB), + "subfc $rT, $rA, $rB", IntGeneral, + [(set GPRC:$rT, (subc GPRC:$rB, GPRC:$rA))]>, + PPC970_DGroup_Cracked; +} +def NEG : XOForm_3<31, 104, 0, (outs GPRC:$rT), (ins GPRC:$rA), + "neg $rT, $rA", IntGeneral, + [(set GPRC:$rT, (ineg GPRC:$rA))]>; +let Uses = [CARRY], Defs = [CARRY] in { +def ADDE : XOForm_1<31, 138, 0, (outs GPRC:$rT), (ins GPRC:$rA, GPRC:$rB), + "adde $rT, $rA, $rB", IntGeneral, + [(set GPRC:$rT, (adde GPRC:$rA, GPRC:$rB))]>; +def ADDME : XOForm_3<31, 234, 0, (outs GPRC:$rT), (ins GPRC:$rA), + "addme $rT, $rA", IntGeneral, + [(set GPRC:$rT, (adde GPRC:$rA, immAllOnes))]>; +def ADDZE : XOForm_3<31, 202, 0, (outs GPRC:$rT), (ins GPRC:$rA), + "addze $rT, $rA", IntGeneral, + [(set GPRC:$rT, (adde GPRC:$rA, 0))]>; +def SUBFE : XOForm_1<31, 136, 0, (outs GPRC:$rT), (ins GPRC:$rA, GPRC:$rB), + "subfe $rT, $rA, $rB", IntGeneral, + [(set GPRC:$rT, (sube GPRC:$rB, GPRC:$rA))]>; +def SUBFME : XOForm_3<31, 232, 0, (outs GPRC:$rT), (ins GPRC:$rA), + "subfme $rT, $rA", IntGeneral, + [(set GPRC:$rT, (sube immAllOnes, GPRC:$rA))]>; +def SUBFZE : XOForm_3<31, 200, 0, (outs GPRC:$rT), (ins GPRC:$rA), + "subfze $rT, $rA", IntGeneral, + [(set GPRC:$rT, (sube 0, GPRC:$rA))]>; +} +} + +// A-Form instructions. Most of the instructions executed in the FPU are of +// this type. +// +let PPC970_Unit = 3 in { // FPU Operations. +let Uses = [RM] in { + def FMADD : AForm_1<63, 29, + (outs F8RC:$FRT), (ins F8RC:$FRA, F8RC:$FRC, F8RC:$FRB), + "fmadd $FRT, $FRA, $FRC, $FRB", FPFused, + [(set F8RC:$FRT, (fadd (fmul F8RC:$FRA, F8RC:$FRC), + F8RC:$FRB))]>, + Requires<[FPContractions]>; + def FMADDS : AForm_1<59, 29, + (outs F4RC:$FRT), (ins F4RC:$FRA, F4RC:$FRC, F4RC:$FRB), + "fmadds $FRT, $FRA, $FRC, $FRB", FPGeneral, + [(set F4RC:$FRT, (fadd (fmul F4RC:$FRA, F4RC:$FRC), + F4RC:$FRB))]>, + Requires<[FPContractions]>; + def FMSUB : AForm_1<63, 28, + (outs F8RC:$FRT), (ins F8RC:$FRA, F8RC:$FRC, F8RC:$FRB), + "fmsub $FRT, $FRA, $FRC, $FRB", FPFused, + [(set F8RC:$FRT, (fsub (fmul F8RC:$FRA, F8RC:$FRC), + F8RC:$FRB))]>, + Requires<[FPContractions]>; + def FMSUBS : AForm_1<59, 28, + (outs F4RC:$FRT), (ins F4RC:$FRA, F4RC:$FRC, F4RC:$FRB), + "fmsubs $FRT, $FRA, $FRC, $FRB", FPGeneral, + [(set F4RC:$FRT, (fsub (fmul F4RC:$FRA, F4RC:$FRC), + F4RC:$FRB))]>, + Requires<[FPContractions]>; + def FNMADD : AForm_1<63, 31, + (outs F8RC:$FRT), (ins F8RC:$FRA, F8RC:$FRC, F8RC:$FRB), + "fnmadd $FRT, $FRA, $FRC, $FRB", FPFused, + [(set F8RC:$FRT, (fneg (fadd (fmul F8RC:$FRA, F8RC:$FRC), + F8RC:$FRB)))]>, + Requires<[FPContractions]>; + def FNMADDS : AForm_1<59, 31, + (outs F4RC:$FRT), (ins F4RC:$FRA, F4RC:$FRC, F4RC:$FRB), + "fnmadds $FRT, $FRA, $FRC, $FRB", FPGeneral, + [(set F4RC:$FRT, (fneg (fadd (fmul F4RC:$FRA, F4RC:$FRC), + F4RC:$FRB)))]>, + Requires<[FPContractions]>; + def FNMSUB : AForm_1<63, 30, + (outs F8RC:$FRT), (ins F8RC:$FRA, F8RC:$FRC, F8RC:$FRB), + "fnmsub $FRT, $FRA, $FRC, $FRB", FPFused, + [(set F8RC:$FRT, (fneg (fsub (fmul F8RC:$FRA, F8RC:$FRC), + F8RC:$FRB)))]>, + Requires<[FPContractions]>; + def FNMSUBS : AForm_1<59, 30, + (outs F4RC:$FRT), (ins F4RC:$FRA, F4RC:$FRC, F4RC:$FRB), + "fnmsubs $FRT, $FRA, $FRC, $FRB", FPGeneral, + [(set F4RC:$FRT, (fneg (fsub (fmul F4RC:$FRA, F4RC:$FRC), + F4RC:$FRB)))]>, + Requires<[FPContractions]>; +} +// FSEL is artificially split into 4 and 8-byte forms for the result. To avoid +// having 4 of these, force the comparison to always be an 8-byte double (code +// should use an FMRSD if the input comparison value really wants to be a float) +// and 4/8 byte forms for the result and operand type.. +def FSELD : AForm_1<63, 23, + (outs F8RC:$FRT), (ins F8RC:$FRA, F8RC:$FRC, F8RC:$FRB), + "fsel $FRT, $FRA, $FRC, $FRB", FPGeneral, + [(set F8RC:$FRT, (PPCfsel F8RC:$FRA,F8RC:$FRC,F8RC:$FRB))]>; +def FSELS : AForm_1<63, 23, + (outs F4RC:$FRT), (ins F8RC:$FRA, F4RC:$FRC, F4RC:$FRB), + "fsel $FRT, $FRA, $FRC, $FRB", FPGeneral, + [(set F4RC:$FRT, (PPCfsel F8RC:$FRA,F4RC:$FRC,F4RC:$FRB))]>; +let Uses = [RM] in { + def FADD : AForm_2<63, 21, + (outs F8RC:$FRT), (ins F8RC:$FRA, F8RC:$FRB), + "fadd $FRT, $FRA, $FRB", FPGeneral, + [(set F8RC:$FRT, (fadd F8RC:$FRA, F8RC:$FRB))]>; + def FADDS : AForm_2<59, 21, + (outs F4RC:$FRT), (ins F4RC:$FRA, F4RC:$FRB), + "fadds $FRT, $FRA, $FRB", FPGeneral, + [(set F4RC:$FRT, (fadd F4RC:$FRA, F4RC:$FRB))]>; + def FDIV : AForm_2<63, 18, + (outs F8RC:$FRT), (ins F8RC:$FRA, F8RC:$FRB), + "fdiv $FRT, $FRA, $FRB", FPDivD, + [(set F8RC:$FRT, (fdiv F8RC:$FRA, F8RC:$FRB))]>; + def FDIVS : AForm_2<59, 18, + (outs F4RC:$FRT), (ins F4RC:$FRA, F4RC:$FRB), + "fdivs $FRT, $FRA, $FRB", FPDivS, + [(set F4RC:$FRT, (fdiv F4RC:$FRA, F4RC:$FRB))]>; + def FMUL : AForm_3<63, 25, + (outs F8RC:$FRT), (ins F8RC:$FRA, F8RC:$FRB), + "fmul $FRT, $FRA, $FRB", FPFused, + [(set F8RC:$FRT, (fmul F8RC:$FRA, F8RC:$FRB))]>; + def FMULS : AForm_3<59, 25, + (outs F4RC:$FRT), (ins F4RC:$FRA, F4RC:$FRB), + "fmuls $FRT, $FRA, $FRB", FPGeneral, + [(set F4RC:$FRT, (fmul F4RC:$FRA, F4RC:$FRB))]>; + def FSUB : AForm_2<63, 20, + (outs F8RC:$FRT), (ins F8RC:$FRA, F8RC:$FRB), + "fsub $FRT, $FRA, $FRB", FPGeneral, + [(set F8RC:$FRT, (fsub F8RC:$FRA, F8RC:$FRB))]>; + def FSUBS : AForm_2<59, 20, + (outs F4RC:$FRT), (ins F4RC:$FRA, F4RC:$FRB), + "fsubs $FRT, $FRA, $FRB", FPGeneral, + [(set F4RC:$FRT, (fsub F4RC:$FRA, F4RC:$FRB))]>; + } +} + +let PPC970_Unit = 1 in { // FXU Operations. +// M-Form instructions. rotate and mask instructions. +// +let isCommutable = 1 in { +// RLWIMI can be commuted if the rotate amount is zero. +def RLWIMI : MForm_2<20, + (outs GPRC:$rA), (ins GPRC:$rSi, GPRC:$rS, u5imm:$SH, u5imm:$MB, + u5imm:$ME), "rlwimi $rA, $rS, $SH, $MB, $ME", IntRotate, + []>, PPC970_DGroup_Cracked, RegConstraint<"$rSi = $rA">, + NoEncode<"$rSi">; +} +def RLWINM : MForm_2<21, + (outs GPRC:$rA), (ins GPRC:$rS, u5imm:$SH, u5imm:$MB, u5imm:$ME), + "rlwinm $rA, $rS, $SH, $MB, $ME", IntGeneral, + []>; +def RLWINMo : MForm_2<21, + (outs GPRC:$rA), (ins GPRC:$rS, u5imm:$SH, u5imm:$MB, u5imm:$ME), + "rlwinm. $rA, $rS, $SH, $MB, $ME", IntGeneral, + []>, isDOT, PPC970_DGroup_Cracked; +def RLWNM : MForm_2<23, + (outs GPRC:$rA), (ins GPRC:$rS, GPRC:$rB, u5imm:$MB, u5imm:$ME), + "rlwnm $rA, $rS, $rB, $MB, $ME", IntGeneral, + []>; +} + + +//===----------------------------------------------------------------------===// +// PowerPC Instruction Patterns +// + +// Arbitrary immediate support. Implement in terms of LIS/ORI. +def : Pat<(i32 imm:$imm), + (ORI (LIS (HI16 imm:$imm)), (LO16 imm:$imm))>; + +// Implement the 'not' operation with the NOR instruction. +def NOT : Pat<(not GPRC:$in), + (NOR GPRC:$in, GPRC:$in)>; + +// ADD an arbitrary immediate. +def : Pat<(add GPRC:$in, imm:$imm), + (ADDIS (ADDI GPRC:$in, (LO16 imm:$imm)), (HA16 imm:$imm))>; +// OR an arbitrary immediate. +def : Pat<(or GPRC:$in, imm:$imm), + (ORIS (ORI GPRC:$in, (LO16 imm:$imm)), (HI16 imm:$imm))>; +// XOR an arbitrary immediate. +def : Pat<(xor GPRC:$in, imm:$imm), + (XORIS (XORI GPRC:$in, (LO16 imm:$imm)), (HI16 imm:$imm))>; +// SUBFIC +def : Pat<(sub immSExt16:$imm, GPRC:$in), + (SUBFIC GPRC:$in, imm:$imm)>; + +// SHL/SRL +def : Pat<(shl GPRC:$in, (i32 imm:$imm)), + (RLWINM GPRC:$in, imm:$imm, 0, (SHL32 imm:$imm))>; +def : Pat<(srl GPRC:$in, (i32 imm:$imm)), + (RLWINM GPRC:$in, (SRL32 imm:$imm), imm:$imm, 31)>; + +// ROTL +def : Pat<(rotl GPRC:$in, GPRC:$sh), + (RLWNM GPRC:$in, GPRC:$sh, 0, 31)>; +def : Pat<(rotl GPRC:$in, (i32 imm:$imm)), + (RLWINM GPRC:$in, imm:$imm, 0, 31)>; + +// RLWNM +def : Pat<(and (rotl GPRC:$in, GPRC:$sh), maskimm32:$imm), + (RLWNM GPRC:$in, GPRC:$sh, (MB maskimm32:$imm), (ME maskimm32:$imm))>; + +// Calls +def : Pat<(PPCcall_Darwin (i32 tglobaladdr:$dst)), + (BL_Darwin tglobaladdr:$dst)>; +def : Pat<(PPCcall_Darwin (i32 texternalsym:$dst)), + (BL_Darwin texternalsym:$dst)>; +def : Pat<(PPCcall_SVR4 (i32 tglobaladdr:$dst)), + (BL_SVR4 tglobaladdr:$dst)>; +def : Pat<(PPCcall_SVR4 (i32 texternalsym:$dst)), + (BL_SVR4 texternalsym:$dst)>; + + +def : Pat<(PPCtc_return (i32 tglobaladdr:$dst), imm:$imm), + (TCRETURNdi tglobaladdr:$dst, imm:$imm)>; + +def : Pat<(PPCtc_return (i32 texternalsym:$dst), imm:$imm), + (TCRETURNdi texternalsym:$dst, imm:$imm)>; + +def : Pat<(PPCtc_return CTRRC:$dst, imm:$imm), + (TCRETURNri CTRRC:$dst, imm:$imm)>; + + + +// Hi and Lo for Darwin Global Addresses. +def : Pat<(PPChi tglobaladdr:$in, 0), (LIS tglobaladdr:$in)>; +def : Pat<(PPClo tglobaladdr:$in, 0), (LI tglobaladdr:$in)>; +def : Pat<(PPChi tconstpool:$in, 0), (LIS tconstpool:$in)>; +def : Pat<(PPClo tconstpool:$in, 0), (LI tconstpool:$in)>; +def : Pat<(PPChi tjumptable:$in, 0), (LIS tjumptable:$in)>; +def : Pat<(PPClo tjumptable:$in, 0), (LI tjumptable:$in)>; +def : Pat<(PPChi tblockaddress:$in, 0), (LIS tblockaddress:$in)>; +def : Pat<(PPClo tblockaddress:$in, 0), (LI tblockaddress:$in)>; +def : Pat<(add GPRC:$in, (PPChi tglobaladdr:$g, 0)), + (ADDIS GPRC:$in, tglobaladdr:$g)>; +def : Pat<(add GPRC:$in, (PPChi tconstpool:$g, 0)), + (ADDIS GPRC:$in, tconstpool:$g)>; +def : Pat<(add GPRC:$in, (PPChi tjumptable:$g, 0)), + (ADDIS GPRC:$in, tjumptable:$g)>; +def : Pat<(add GPRC:$in, (PPChi tblockaddress:$g, 0)), + (ADDIS GPRC:$in, tblockaddress:$g)>; + +// Fused negative multiply subtract, alternate pattern +def : Pat<(fsub F8RC:$B, (fmul F8RC:$A, F8RC:$C)), + (FNMSUB F8RC:$A, F8RC:$C, F8RC:$B)>, + Requires<[FPContractions]>; +def : Pat<(fsub F4RC:$B, (fmul F4RC:$A, F4RC:$C)), + (FNMSUBS F4RC:$A, F4RC:$C, F4RC:$B)>, + Requires<[FPContractions]>; + +// Standard shifts. These are represented separately from the real shifts above +// so that we can distinguish between shifts that allow 5-bit and 6-bit shift +// amounts. +def : Pat<(sra GPRC:$rS, GPRC:$rB), + (SRAW GPRC:$rS, GPRC:$rB)>; +def : Pat<(srl GPRC:$rS, GPRC:$rB), + (SRW GPRC:$rS, GPRC:$rB)>; +def : Pat<(shl GPRC:$rS, GPRC:$rB), + (SLW GPRC:$rS, GPRC:$rB)>; + +def : Pat<(zextloadi1 iaddr:$src), + (LBZ iaddr:$src)>; +def : Pat<(zextloadi1 xaddr:$src), + (LBZX xaddr:$src)>; +def : Pat<(extloadi1 iaddr:$src), + (LBZ iaddr:$src)>; +def : Pat<(extloadi1 xaddr:$src), + (LBZX xaddr:$src)>; +def : Pat<(extloadi8 iaddr:$src), + (LBZ iaddr:$src)>; +def : Pat<(extloadi8 xaddr:$src), + (LBZX xaddr:$src)>; +def : Pat<(extloadi16 iaddr:$src), + (LHZ iaddr:$src)>; +def : Pat<(extloadi16 xaddr:$src), + (LHZX xaddr:$src)>; +def : Pat<(extloadf32 iaddr:$src), + (FMRSD (LFS iaddr:$src))>; +def : Pat<(extloadf32 xaddr:$src), + (FMRSD (LFSX xaddr:$src))>; + +// Memory barriers +def : Pat<(membarrier (i32 imm:$ll), + (i32 imm:$ls), + (i32 imm:$sl), + (i32 imm:$ss), + (i32 imm:$device)), + (SYNC)>; + +include "PPCInstrAltivec.td" +include "PPCInstr64Bit.td" diff --git a/libclamav/c++/llvm/lib/Target/PowerPC/PPCJITInfo.cpp b/libclamav/c++/llvm/lib/Target/PowerPC/PPCJITInfo.cpp new file mode 100644 index 000000000..c679bcdf5 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/PowerPC/PPCJITInfo.cpp @@ -0,0 +1,445 @@ +//===-- PPCJITInfo.cpp - Implement the JIT interfaces for the PowerPC -----===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the JIT interfaces for the 32-bit PowerPC target. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "jit" +#include "PPCJITInfo.h" +#include "PPCRelocations.h" +#include "PPCTargetMachine.h" +#include "llvm/Function.h" +#include "llvm/System/Memory.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +static TargetJITInfo::JITCompilerFn JITCompilerFunction; + +#define BUILD_ADDIS(RD,RS,IMM16) \ + ((15 << 26) | ((RD) << 21) | ((RS) << 16) | ((IMM16) & 65535)) +#define BUILD_ORI(RD,RS,UIMM16) \ + ((24 << 26) | ((RS) << 21) | ((RD) << 16) | ((UIMM16) & 65535)) +#define BUILD_ORIS(RD,RS,UIMM16) \ + ((25 << 26) | ((RS) << 21) | ((RD) << 16) | ((UIMM16) & 65535)) +#define BUILD_RLDICR(RD,RS,SH,ME) \ + ((30 << 26) | ((RS) << 21) | ((RD) << 16) | (((SH) & 31) << 11) | \ + (((ME) & 63) << 6) | (1 << 2) | ((((SH) >> 5) & 1) << 1)) +#define BUILD_MTSPR(RS,SPR) \ + ((31 << 26) | ((RS) << 21) | ((SPR) << 16) | (467 << 1)) +#define BUILD_BCCTRx(BO,BI,LINK) \ + ((19 << 26) | ((BO) << 21) | ((BI) << 16) | (528 << 1) | ((LINK) & 1)) +#define BUILD_B(TARGET, LINK) \ + ((18 << 26) | (((TARGET) & 0x00FFFFFF) << 2) | ((LINK) & 1)) + +// Pseudo-ops +#define BUILD_LIS(RD,IMM16) BUILD_ADDIS(RD,0,IMM16) +#define BUILD_SLDI(RD,RS,IMM6) BUILD_RLDICR(RD,RS,IMM6,63-IMM6) +#define BUILD_MTCTR(RS) BUILD_MTSPR(RS,9) +#define BUILD_BCTR(LINK) BUILD_BCCTRx(20,0,LINK) + +static void EmitBranchToAt(uint64_t At, uint64_t To, bool isCall, bool is64Bit){ + intptr_t Offset = ((intptr_t)To - (intptr_t)At) >> 2; + unsigned *AtI = (unsigned*)(intptr_t)At; + + if (Offset >= -(1 << 23) && Offset < (1 << 23)) { // In range? + AtI[0] = BUILD_B(Offset, isCall); // b/bl target + } else if (!is64Bit) { + AtI[0] = BUILD_LIS(12, To >> 16); // lis r12, hi16(address) + AtI[1] = BUILD_ORI(12, 12, To); // ori r12, r12, lo16(address) + AtI[2] = BUILD_MTCTR(12); // mtctr r12 + AtI[3] = BUILD_BCTR(isCall); // bctr/bctrl + } else { + AtI[0] = BUILD_LIS(12, To >> 48); // lis r12, hi16(address) + AtI[1] = BUILD_ORI(12, 12, To >> 32); // ori r12, r12, lo16(address) + AtI[2] = BUILD_SLDI(12, 12, 32); // sldi r12, r12, 32 + AtI[3] = BUILD_ORIS(12, 12, To >> 16); // oris r12, r12, hi16(address) + AtI[4] = BUILD_ORI(12, 12, To); // ori r12, r12, lo16(address) + AtI[5] = BUILD_MTCTR(12); // mtctr r12 + AtI[6] = BUILD_BCTR(isCall); // bctr/bctrl + } +} + +extern "C" void PPC32CompilationCallback(); +extern "C" void PPC64CompilationCallback(); + +#if (defined(__POWERPC__) || defined (__ppc__) || defined(_POWER)) && \ + !(defined(__ppc64__) || defined(__FreeBSD__)) +// CompilationCallback stub - We can't use a C function with inline assembly in +// it, because we the prolog/epilog inserted by GCC won't work for us. Instead, +// write our own wrapper, which does things our way, so we have complete control +// over register saving and restoring. +asm( + ".text\n" + ".align 2\n" + ".globl _PPC32CompilationCallback\n" +"_PPC32CompilationCallback:\n" + // Make space for 8 ints r[3-10] and 13 doubles f[1-13] and the + // FIXME: need to save v[0-19] for altivec? + // FIXME: could shrink frame + // Set up a proper stack frame + // FIXME Layout + // PowerPC64 ABI linkage - 24 bytes + // parameters - 32 bytes + // 13 double registers - 104 bytes + // 8 int registers - 32 bytes + "mflr r0\n" + "stw r0, 8(r1)\n" + "stwu r1, -208(r1)\n" + // Save all int arg registers + "stw r10, 204(r1)\n" "stw r9, 200(r1)\n" + "stw r8, 196(r1)\n" "stw r7, 192(r1)\n" + "stw r6, 188(r1)\n" "stw r5, 184(r1)\n" + "stw r4, 180(r1)\n" "stw r3, 176(r1)\n" + // Save all call-clobbered FP regs. + "stfd f13, 168(r1)\n" "stfd f12, 160(r1)\n" + "stfd f11, 152(r1)\n" "stfd f10, 144(r1)\n" + "stfd f9, 136(r1)\n" "stfd f8, 128(r1)\n" + "stfd f7, 120(r1)\n" "stfd f6, 112(r1)\n" + "stfd f5, 104(r1)\n" "stfd f4, 96(r1)\n" + "stfd f3, 88(r1)\n" "stfd f2, 80(r1)\n" + "stfd f1, 72(r1)\n" + // Arguments to Compilation Callback: + // r3 - our lr (address of the call instruction in stub plus 4) + // r4 - stub's lr (address of instruction that called the stub plus 4) + // r5 - is64Bit - always 0. + "mr r3, r0\n" + "lwz r2, 208(r1)\n" // stub's frame + "lwz r4, 8(r2)\n" // stub's lr + "li r5, 0\n" // 0 == 32 bit + "bl _PPCCompilationCallbackC\n" + "mtctr r3\n" + // Restore all int arg registers + "lwz r10, 204(r1)\n" "lwz r9, 200(r1)\n" + "lwz r8, 196(r1)\n" "lwz r7, 192(r1)\n" + "lwz r6, 188(r1)\n" "lwz r5, 184(r1)\n" + "lwz r4, 180(r1)\n" "lwz r3, 176(r1)\n" + // Restore all FP arg registers + "lfd f13, 168(r1)\n" "lfd f12, 160(r1)\n" + "lfd f11, 152(r1)\n" "lfd f10, 144(r1)\n" + "lfd f9, 136(r1)\n" "lfd f8, 128(r1)\n" + "lfd f7, 120(r1)\n" "lfd f6, 112(r1)\n" + "lfd f5, 104(r1)\n" "lfd f4, 96(r1)\n" + "lfd f3, 88(r1)\n" "lfd f2, 80(r1)\n" + "lfd f1, 72(r1)\n" + // Pop 3 frames off the stack and branch to target + "lwz r1, 208(r1)\n" + "lwz r2, 8(r1)\n" + "mtlr r2\n" + "bctr\n" + ); + +#elif defined(__PPC__) && !defined(__ppc64__) +// Linux & FreeBSD / PPC 32 support + +// CompilationCallback stub - We can't use a C function with inline assembly in +// it, because we the prolog/epilog inserted by GCC won't work for us. Instead, +// write our own wrapper, which does things our way, so we have complete control +// over register saving and restoring. +asm( + ".text\n" + ".align 2\n" + ".globl PPC32CompilationCallback\n" +"PPC32CompilationCallback:\n" + // Make space for 8 ints r[3-10] and 8 doubles f[1-8] and the + // FIXME: need to save v[0-19] for altivec? + // FIXME: could shrink frame + // Set up a proper stack frame + // FIXME Layout + // 8 double registers - 64 bytes + // 8 int registers - 32 bytes + "mflr 0\n" + "stw 0, 4(1)\n" + "stwu 1, -104(1)\n" + // Save all int arg registers + "stw 10, 100(1)\n" "stw 9, 96(1)\n" + "stw 8, 92(1)\n" "stw 7, 88(1)\n" + "stw 6, 84(1)\n" "stw 5, 80(1)\n" + "stw 4, 76(1)\n" "stw 3, 72(1)\n" + // Save all call-clobbered FP regs. + "stfd 8, 64(1)\n" + "stfd 7, 56(1)\n" "stfd 6, 48(1)\n" + "stfd 5, 40(1)\n" "stfd 4, 32(1)\n" + "stfd 3, 24(1)\n" "stfd 2, 16(1)\n" + "stfd 1, 8(1)\n" + // Arguments to Compilation Callback: + // r3 - our lr (address of the call instruction in stub plus 4) + // r4 - stub's lr (address of instruction that called the stub plus 4) + // r5 - is64Bit - always 0. + "mr 3, 0\n" + "lwz 5, 104(1)\n" // stub's frame + "lwz 4, 4(5)\n" // stub's lr + "li 5, 0\n" // 0 == 32 bit + "bl PPCCompilationCallbackC\n" + "mtctr 3\n" + // Restore all int arg registers + "lwz 10, 100(1)\n" "lwz 9, 96(1)\n" + "lwz 8, 92(1)\n" "lwz 7, 88(1)\n" + "lwz 6, 84(1)\n" "lwz 5, 80(1)\n" + "lwz 4, 76(1)\n" "lwz 3, 72(1)\n" + // Restore all FP arg registers + "lfd 8, 64(1)\n" + "lfd 7, 56(1)\n" "lfd 6, 48(1)\n" + "lfd 5, 40(1)\n" "lfd 4, 32(1)\n" + "lfd 3, 24(1)\n" "lfd 2, 16(1)\n" + "lfd 1, 8(1)\n" + // Pop 3 frames off the stack and branch to target + "lwz 1, 104(1)\n" + "lwz 0, 4(1)\n" + "mtlr 0\n" + "bctr\n" + ); +#else +void PPC32CompilationCallback() { + llvm_unreachable("This is not a power pc, you can't execute this!"); +} +#endif + +#if (defined(__POWERPC__) || defined (__ppc__) || defined(_POWER)) && \ + defined(__ppc64__) +asm( + ".text\n" + ".align 2\n" + ".globl _PPC64CompilationCallback\n" +"_PPC64CompilationCallback:\n" + // Make space for 8 ints r[3-10] and 13 doubles f[1-13] and the + // FIXME: need to save v[0-19] for altivec? + // Set up a proper stack frame + // Layout + // PowerPC64 ABI linkage - 48 bytes + // parameters - 64 bytes + // 13 double registers - 104 bytes + // 8 int registers - 64 bytes + "mflr r0\n" + "std r0, 16(r1)\n" + "stdu r1, -280(r1)\n" + // Save all int arg registers + "std r10, 272(r1)\n" "std r9, 264(r1)\n" + "std r8, 256(r1)\n" "std r7, 248(r1)\n" + "std r6, 240(r1)\n" "std r5, 232(r1)\n" + "std r4, 224(r1)\n" "std r3, 216(r1)\n" + // Save all call-clobbered FP regs. + "stfd f13, 208(r1)\n" "stfd f12, 200(r1)\n" + "stfd f11, 192(r1)\n" "stfd f10, 184(r1)\n" + "stfd f9, 176(r1)\n" "stfd f8, 168(r1)\n" + "stfd f7, 160(r1)\n" "stfd f6, 152(r1)\n" + "stfd f5, 144(r1)\n" "stfd f4, 136(r1)\n" + "stfd f3, 128(r1)\n" "stfd f2, 120(r1)\n" + "stfd f1, 112(r1)\n" + // Arguments to Compilation Callback: + // r3 - our lr (address of the call instruction in stub plus 4) + // r4 - stub's lr (address of instruction that called the stub plus 4) + // r5 - is64Bit - always 1. + "mr r3, r0\n" + "ld r2, 280(r1)\n" // stub's frame + "ld r4, 16(r2)\n" // stub's lr + "li r5, 1\n" // 1 == 64 bit + "bl _PPCCompilationCallbackC\n" + "mtctr r3\n" + // Restore all int arg registers + "ld r10, 272(r1)\n" "ld r9, 264(r1)\n" + "ld r8, 256(r1)\n" "ld r7, 248(r1)\n" + "ld r6, 240(r1)\n" "ld r5, 232(r1)\n" + "ld r4, 224(r1)\n" "ld r3, 216(r1)\n" + // Restore all FP arg registers + "lfd f13, 208(r1)\n" "lfd f12, 200(r1)\n" + "lfd f11, 192(r1)\n" "lfd f10, 184(r1)\n" + "lfd f9, 176(r1)\n" "lfd f8, 168(r1)\n" + "lfd f7, 160(r1)\n" "lfd f6, 152(r1)\n" + "lfd f5, 144(r1)\n" "lfd f4, 136(r1)\n" + "lfd f3, 128(r1)\n" "lfd f2, 120(r1)\n" + "lfd f1, 112(r1)\n" + // Pop 3 frames off the stack and branch to target + "ld r1, 280(r1)\n" + "ld r2, 16(r1)\n" + "mtlr r2\n" + "bctr\n" + ); +#else +void PPC64CompilationCallback() { + llvm_unreachable("This is not a power pc, you can't execute this!"); +} +#endif + +extern "C" void *PPCCompilationCallbackC(unsigned *StubCallAddrPlus4, + unsigned *OrigCallAddrPlus4, + bool is64Bit) { + // Adjust the pointer to the address of the call instruction in the stub + // emitted by emitFunctionStub, rather than the instruction after it. + unsigned *StubCallAddr = StubCallAddrPlus4 - 1; + unsigned *OrigCallAddr = OrigCallAddrPlus4 - 1; + + void *Target = JITCompilerFunction(StubCallAddr); + + // Check to see if *OrigCallAddr is a 'bl' instruction, and if we can rewrite + // it to branch directly to the destination. If so, rewrite it so it does not + // need to go through the stub anymore. + unsigned OrigCallInst = *OrigCallAddr; + if ((OrigCallInst >> 26) == 18) { // Direct call. + intptr_t Offset = ((intptr_t)Target - (intptr_t)OrigCallAddr) >> 2; + + if (Offset >= -(1 << 23) && Offset < (1 << 23)) { // In range? + // Clear the original target out. + OrigCallInst &= (63 << 26) | 3; + // Fill in the new target. + OrigCallInst |= (Offset & ((1 << 24)-1)) << 2; + // Replace the call. + *OrigCallAddr = OrigCallInst; + } + } + + // Assert that we are coming from a stub that was created with our + // emitFunctionStub. + if ((*StubCallAddr >> 26) == 18) + StubCallAddr -= 3; + else { + assert((*StubCallAddr >> 26) == 19 && "Call in stub is not indirect!"); + StubCallAddr -= is64Bit ? 9 : 6; + } + + // Rewrite the stub with an unconditional branch to the target, for any users + // who took the address of the stub. + EmitBranchToAt((intptr_t)StubCallAddr, (intptr_t)Target, false, is64Bit); + + // Put the address of the target function to call and the address to return to + // after calling the target function in a place that is easy to get on the + // stack after we restore all regs. + return Target; +} + + + +TargetJITInfo::LazyResolverFn +PPCJITInfo::getLazyResolverFunction(JITCompilerFn Fn) { + JITCompilerFunction = Fn; + return is64Bit ? PPC64CompilationCallback : PPC32CompilationCallback; +} + +TargetJITInfo::StubLayout PPCJITInfo::getStubLayout() { + // The stub contains up to 10 4-byte instructions, aligned at 4 bytes: 3 + // instructions to save the caller's address if this is a lazy-compilation + // stub, plus a 1-, 4-, or 7-instruction sequence to load an arbitrary address + // into a register and jump through it. + StubLayout Result = {10*4, 4}; + return Result; +} + +#if (defined(__POWERPC__) || defined (__ppc__) || defined(_POWER)) && \ +defined(__APPLE__) +extern "C" void sys_icache_invalidate(const void *Addr, size_t len); +#endif + +void *PPCJITInfo::emitFunctionStub(const Function* F, void *Fn, + JITCodeEmitter &JCE) { + MachineCodeEmitter::BufferState BS; + // If this is just a call to an external function, emit a branch instead of a + // call. The code is the same except for one bit of the last instruction. + if (Fn != (void*)(intptr_t)PPC32CompilationCallback && + Fn != (void*)(intptr_t)PPC64CompilationCallback) { + void *Addr = (void*)JCE.getCurrentPCValue(); + JCE.emitWordBE(0); + JCE.emitWordBE(0); + JCE.emitWordBE(0); + JCE.emitWordBE(0); + JCE.emitWordBE(0); + JCE.emitWordBE(0); + JCE.emitWordBE(0); + EmitBranchToAt((intptr_t)Addr, (intptr_t)Fn, false, is64Bit); + sys::Memory::InvalidateInstructionCache(Addr, 7*4); + return Addr; + } + + void *Addr = (void*)JCE.getCurrentPCValue(); + if (is64Bit) { + JCE.emitWordBE(0xf821ffb1); // stdu r1,-80(r1) + JCE.emitWordBE(0x7d6802a6); // mflr r11 + JCE.emitWordBE(0xf9610060); // std r11, 96(r1) + } else if (TM.getSubtargetImpl()->isDarwinABI()){ + JCE.emitWordBE(0x9421ffe0); // stwu r1,-32(r1) + JCE.emitWordBE(0x7d6802a6); // mflr r11 + JCE.emitWordBE(0x91610028); // stw r11, 40(r1) + } else { + JCE.emitWordBE(0x9421ffe0); // stwu r1,-32(r1) + JCE.emitWordBE(0x7d6802a6); // mflr r11 + JCE.emitWordBE(0x91610024); // stw r11, 36(r1) + } + intptr_t BranchAddr = (intptr_t)JCE.getCurrentPCValue(); + JCE.emitWordBE(0); + JCE.emitWordBE(0); + JCE.emitWordBE(0); + JCE.emitWordBE(0); + JCE.emitWordBE(0); + JCE.emitWordBE(0); + JCE.emitWordBE(0); + EmitBranchToAt(BranchAddr, (intptr_t)Fn, true, is64Bit); + sys::Memory::InvalidateInstructionCache(Addr, 10*4); + return Addr; +} + + +void PPCJITInfo::relocate(void *Function, MachineRelocation *MR, + unsigned NumRelocs, unsigned char* GOTBase) { + for (unsigned i = 0; i != NumRelocs; ++i, ++MR) { + unsigned *RelocPos = (unsigned*)Function + MR->getMachineCodeOffset()/4; + intptr_t ResultPtr = (intptr_t)MR->getResultPointer(); + switch ((PPC::RelocationType)MR->getRelocationType()) { + default: llvm_unreachable("Unknown relocation type!"); + case PPC::reloc_pcrel_bx: + // PC-relative relocation for b and bl instructions. + ResultPtr = (ResultPtr-(intptr_t)RelocPos) >> 2; + assert(ResultPtr >= -(1 << 23) && ResultPtr < (1 << 23) && + "Relocation out of range!"); + *RelocPos |= (ResultPtr & ((1 << 24)-1)) << 2; + break; + case PPC::reloc_pcrel_bcx: + // PC-relative relocation for BLT,BLE,BEQ,BGE,BGT,BNE, or other + // bcx instructions. + ResultPtr = (ResultPtr-(intptr_t)RelocPos) >> 2; + assert(ResultPtr >= -(1 << 13) && ResultPtr < (1 << 13) && + "Relocation out of range!"); + *RelocPos |= (ResultPtr & ((1 << 14)-1)) << 2; + break; + case PPC::reloc_absolute_high: // high bits of ref -> low 16 of instr + case PPC::reloc_absolute_low: { // low bits of ref -> low 16 of instr + ResultPtr += MR->getConstantVal(); + + // If this is a high-part access, get the high-part. + if (MR->getRelocationType() == PPC::reloc_absolute_high) { + // If the low part will have a carry (really a borrow) from the low + // 16-bits into the high 16, add a bit to borrow from. + if (((int)ResultPtr << 16) < 0) + ResultPtr += 1 << 16; + ResultPtr >>= 16; + } + + // Do the addition then mask, so the addition does not overflow the 16-bit + // immediate section of the instruction. + unsigned LowBits = (*RelocPos + ResultPtr) & 65535; + unsigned HighBits = *RelocPos & ~65535; + *RelocPos = LowBits | HighBits; // Slam into low 16-bits + break; + } + case PPC::reloc_absolute_low_ix: { // low bits of ref -> low 14 of instr + ResultPtr += MR->getConstantVal(); + // Do the addition then mask, so the addition does not overflow the 16-bit + // immediate section of the instruction. + unsigned LowBits = (*RelocPos + ResultPtr) & 0xFFFC; + unsigned HighBits = *RelocPos & 0xFFFF0003; + *RelocPos = LowBits | HighBits; // Slam into low 14-bits. + break; + } + } + } +} + +void PPCJITInfo::replaceMachineCodeForFunction(void *Old, void *New) { + EmitBranchToAt((intptr_t)Old, (intptr_t)New, false, is64Bit); +} diff --git a/libclamav/c++/llvm/lib/Target/PowerPC/PPCJITInfo.h b/libclamav/c++/llvm/lib/Target/PowerPC/PPCJITInfo.h new file mode 100644 index 000000000..47ead59b5 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/PowerPC/PPCJITInfo.h @@ -0,0 +1,49 @@ +//===- PPCJITInfo.h - PowerPC impl. of the JIT interface --------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the PowerPC implementation of the TargetJITInfo class. +// +//===----------------------------------------------------------------------===// + +#ifndef POWERPC_JITINFO_H +#define POWERPC_JITINFO_H + +#include "llvm/Target/TargetJITInfo.h" +#include "llvm/CodeGen/JITCodeEmitter.h" + +namespace llvm { + class PPCTargetMachine; + + class PPCJITInfo : public TargetJITInfo { + protected: + PPCTargetMachine &TM; + bool is64Bit; + public: + PPCJITInfo(PPCTargetMachine &tm, bool tmIs64Bit) : TM(tm) { + useGOT = 0; + is64Bit = tmIs64Bit; + } + + virtual StubLayout getStubLayout(); + virtual void *emitFunctionStub(const Function* F, void *Fn, + JITCodeEmitter &JCE); + virtual LazyResolverFn getLazyResolverFunction(JITCompilerFn); + virtual void relocate(void *Function, MachineRelocation *MR, + unsigned NumRelocs, unsigned char* GOTBase); + + /// replaceMachineCodeForFunction - Make it so that calling the function + /// whose machine code is at OLD turns into a call to NEW, perhaps by + /// overwriting OLD with a branch to NEW. This is used for self-modifying + /// code. + /// + virtual void replaceMachineCodeForFunction(void *Old, void *New); + }; +} + +#endif diff --git a/libclamav/c++/llvm/lib/Target/PowerPC/PPCMCAsmInfo.cpp b/libclamav/c++/llvm/lib/Target/PowerPC/PPCMCAsmInfo.cpp new file mode 100644 index 000000000..c87879b2a --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/PowerPC/PPCMCAsmInfo.cpp @@ -0,0 +1,58 @@ +//===-- PPCMCAsmInfo.cpp - PPC asm properties -------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the declarations of the MCAsmInfoDarwin properties. +// +//===----------------------------------------------------------------------===// + +#include "PPCMCAsmInfo.h" +using namespace llvm; + +PPCMCAsmInfoDarwin::PPCMCAsmInfoDarwin(bool is64Bit) { + PCSymbol = "."; + CommentString = ";"; + ExceptionsType = ExceptionHandling::Dwarf; + + if (!is64Bit) + Data64bitsDirective = 0; // We can't emit a 64-bit unit in PPC32 mode. + AssemblerDialect = 1; // New-Style mnemonics. +} + +PPCLinuxMCAsmInfo::PPCLinuxMCAsmInfo(bool is64Bit) { + CommentString = "#"; + GlobalPrefix = ""; + PrivateGlobalPrefix = ".L"; + UsedDirective = "\t# .no_dead_strip\t"; + WeakRefDirective = "\t.weak\t"; + + // Uses '.section' before '.bss' directive + UsesELFSectionDirectiveForBSS = true; + + // Debug Information + AbsoluteDebugSectionOffsets = true; + SupportsDebugInformation = true; + + PCSymbol = "."; + + // Set up DWARF directives + HasLEB128 = true; // Target asm supports leb128 directives (little-endian) + + // Exceptions handling + if (!is64Bit) + ExceptionsType = ExceptionHandling::Dwarf; + AbsoluteEHSectionOffsets = false; + + ZeroDirective = "\t.space\t"; + SetDirective = "\t.set"; + Data64bitsDirective = is64Bit ? "\t.quad\t" : 0; + AlignmentIsInBytes = false; + LCOMMDirective = "\t.lcomm\t"; + AssemblerDialect = 0; // Old-Style mnemonics. +} + diff --git a/libclamav/c++/llvm/lib/Target/PowerPC/PPCMCAsmInfo.h b/libclamav/c++/llvm/lib/Target/PowerPC/PPCMCAsmInfo.h new file mode 100644 index 000000000..96ae6fbba --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/PowerPC/PPCMCAsmInfo.h @@ -0,0 +1,31 @@ +//=====-- PPCMCAsmInfo.h - PPC asm properties -----------------*- C++ -*--====// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the declaration of the MCAsmInfoDarwin class. +// +//===----------------------------------------------------------------------===// + +#ifndef PPCTARGETASMINFO_H +#define PPCTARGETASMINFO_H + +#include "llvm/MC/MCAsmInfoDarwin.h" + +namespace llvm { + + struct PPCMCAsmInfoDarwin : public MCAsmInfoDarwin { + explicit PPCMCAsmInfoDarwin(bool is64Bit); + }; + + struct PPCLinuxMCAsmInfo : public MCAsmInfo { + explicit PPCLinuxMCAsmInfo(bool is64Bit); + }; + +} // namespace llvm + +#endif diff --git a/libclamav/c++/llvm/lib/Target/PowerPC/PPCMachOWriterInfo.cpp b/libclamav/c++/llvm/lib/Target/PowerPC/PPCMachOWriterInfo.cpp new file mode 100644 index 000000000..4c1445409 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/PowerPC/PPCMachOWriterInfo.cpp @@ -0,0 +1,152 @@ +//===-- PPCMachOWriterInfo.cpp - Mach-O Writer Info for the PowerPC -------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements Mach-O writer information for the PowerPC backend. +// +//===----------------------------------------------------------------------===// + +#include "PPCMachOWriterInfo.h" +#include "PPCRelocations.h" +#include "PPCTargetMachine.h" +#include "llvm/CodeGen/MachORelocation.h" +#include "llvm/Support/OutputBuffer.h" +#include "llvm/Support/ErrorHandling.h" +#include +using namespace llvm; + +PPCMachOWriterInfo::PPCMachOWriterInfo(const PPCTargetMachine &TM) + : TargetMachOWriterInfo(TM.getTargetData()->getPointerSizeInBits() == 64 ? + HDR_CPU_TYPE_POWERPC64 : + HDR_CPU_TYPE_POWERPC, + HDR_CPU_SUBTYPE_POWERPC_ALL) {} +PPCMachOWriterInfo::~PPCMachOWriterInfo() {} + +/// GetTargetRelocation - For the MachineRelocation MR, convert it to one or +/// more PowerPC MachORelocation(s), add the new relocations to the +/// MachOSection, and rewrite the instruction at the section offset if required +/// by that relocation type. +unsigned PPCMachOWriterInfo::GetTargetRelocation(MachineRelocation &MR, + unsigned FromIdx, + unsigned ToAddr, + unsigned ToIdx, + OutputBuffer &RelocOut, + OutputBuffer &SecOut, + bool Scattered, + bool isExtern) const { + unsigned NumRelocs = 0; + uint64_t Addr = 0; + + // Get the address of whatever it is we're relocating, if possible. + if (!isExtern) + Addr = (uintptr_t)MR.getResultPointer() + ToAddr; + + switch ((PPC::RelocationType)MR.getRelocationType()) { + default: llvm_unreachable("Unknown PPC relocation type!"); + case PPC::reloc_absolute_low_ix: + llvm_unreachable("Unhandled PPC relocation type!"); + break; + case PPC::reloc_vanilla: + { + // FIXME: need to handle 64 bit vanilla relocs + MachORelocation VANILLA(MR.getMachineCodeOffset(), ToIdx, + false, 2, isExtern, + PPC_RELOC_VANILLA, + Scattered, (intptr_t)MR.getResultPointer()); + ++NumRelocs; + + if (Scattered) { + RelocOut.outword(VANILLA.getPackedFields()); + RelocOut.outword(VANILLA.getAddress()); + } else { + RelocOut.outword(VANILLA.getAddress()); + RelocOut.outword(VANILLA.getPackedFields()); + } + + intptr_t SymbolOffset; + + if (Scattered) + SymbolOffset = Addr + MR.getConstantVal(); + else + SymbolOffset = Addr; + + printf("vanilla fixup: sec_%x[%x] = %x\n", FromIdx, + unsigned(MR.getMachineCodeOffset()), + unsigned(SymbolOffset)); + SecOut.fixword(SymbolOffset, MR.getMachineCodeOffset()); + } + break; + case PPC::reloc_pcrel_bx: + { + // FIXME: Presumably someday we will need to branch to other, non-extern + // functions too. Need to figure out some way to distinguish between + // target is BB and target is function. + if (isExtern) { + MachORelocation BR24(MR.getMachineCodeOffset(), ToIdx, true, 2, + isExtern, PPC_RELOC_BR24, Scattered, + (intptr_t)MR.getMachineCodeOffset()); + RelocOut.outword(BR24.getAddress()); + RelocOut.outword(BR24.getPackedFields()); + ++NumRelocs; + } + + Addr -= MR.getMachineCodeOffset(); + Addr >>= 2; + Addr &= 0xFFFFFF; + Addr <<= 2; + Addr |= (SecOut[MR.getMachineCodeOffset()] << 24); + Addr |= (SecOut[MR.getMachineCodeOffset()+3] & 0x3); + SecOut.fixword(Addr, MR.getMachineCodeOffset()); + break; + } + case PPC::reloc_pcrel_bcx: + { + Addr -= MR.getMachineCodeOffset(); + Addr &= 0xFFFC; + + SecOut.fixhalf(Addr, MR.getMachineCodeOffset() + 2); + break; + } + case PPC::reloc_absolute_high: + { + MachORelocation HA16(MR.getMachineCodeOffset(), ToIdx, false, 2, + isExtern, PPC_RELOC_HA16); + MachORelocation PAIR(Addr & 0xFFFF, 0xFFFFFF, false, 2, isExtern, + PPC_RELOC_PAIR); + NumRelocs = 2; + + RelocOut.outword(HA16.getRawAddress()); + RelocOut.outword(HA16.getPackedFields()); + RelocOut.outword(PAIR.getRawAddress()); + RelocOut.outword(PAIR.getPackedFields()); + + Addr += 0x8000; + + SecOut.fixhalf(Addr >> 16, MR.getMachineCodeOffset() + 2); + break; + } + case PPC::reloc_absolute_low: + { + MachORelocation LO16(MR.getMachineCodeOffset(), ToIdx, false, 2, + isExtern, PPC_RELOC_LO16); + MachORelocation PAIR(Addr >> 16, 0xFFFFFF, false, 2, isExtern, + PPC_RELOC_PAIR); + NumRelocs = 2; + + RelocOut.outword(LO16.getRawAddress()); + RelocOut.outword(LO16.getPackedFields()); + RelocOut.outword(PAIR.getRawAddress()); + RelocOut.outword(PAIR.getPackedFields()); + + SecOut.fixhalf(Addr, MR.getMachineCodeOffset() + 2); + break; + } + } + + return NumRelocs; +} diff --git a/libclamav/c++/llvm/lib/Target/PowerPC/PPCMachOWriterInfo.h b/libclamav/c++/llvm/lib/Target/PowerPC/PPCMachOWriterInfo.h new file mode 100644 index 000000000..d46334df2 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/PowerPC/PPCMachOWriterInfo.h @@ -0,0 +1,55 @@ +//===-- PPCMachOWriterInfo.h - Mach-O Writer Info for PowerPC ---*- 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 Mach-O writer information for the PowerPC backend. +// +//===----------------------------------------------------------------------===// + +#ifndef PPC_MACHO_WRITER_INFO_H +#define PPC_MACHO_WRITER_INFO_H + +#include "llvm/Target/TargetMachOWriterInfo.h" + +namespace llvm { + + // Forward declarations + class MachineRelocation; + class OutputBuffer; + class PPCTargetMachine; + + class PPCMachOWriterInfo : public TargetMachOWriterInfo { + public: + PPCMachOWriterInfo(const PPCTargetMachine &TM); + virtual ~PPCMachOWriterInfo(); + + virtual unsigned GetTargetRelocation(MachineRelocation &MR, + unsigned FromIdx, + unsigned ToAddr, + unsigned ToIdx, + OutputBuffer &RelocOut, + OutputBuffer &SecOut, + bool Scattered, bool Extern) const; + + // Constants for the relocation r_type field. + // See + enum { + PPC_RELOC_VANILLA, // generic relocation + PPC_RELOC_PAIR, // the second relocation entry of a pair + PPC_RELOC_BR14, // 14 bit branch displacement to word address + PPC_RELOC_BR24, // 24 bit branch displacement to word address + PPC_RELOC_HI16, // a PAIR follows with the low 16 bits + PPC_RELOC_LO16, // a PAIR follows with the high 16 bits + PPC_RELOC_HA16, // a PAIR follows, which is sign extended to 32b + PPC_RELOC_LO14 // LO16 with low 2 bits implicitly zero + }; + }; + +} // end llvm namespace + +#endif // PPC_MACHO_WRITER_INFO_H diff --git a/libclamav/c++/llvm/lib/Target/PowerPC/PPCMachineFunctionInfo.h b/libclamav/c++/llvm/lib/Target/PowerPC/PPCMachineFunctionInfo.h new file mode 100644 index 000000000..b359dd33b --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/PowerPC/PPCMachineFunctionInfo.h @@ -0,0 +1,104 @@ +//===-- PPCMachineFunctionInfo.h - Private data used for PowerPC --*- C++ -*-=// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the PowerPC specific subclass of MachineFunctionInfo. +// +//===----------------------------------------------------------------------===// + +#ifndef PPC_MACHINE_FUNCTION_INFO_H +#define PPC_MACHINE_FUNCTION_INFO_H + +#include "llvm/CodeGen/MachineFunction.h" + +namespace llvm { + +/// PPCFunctionInfo - This class is derived from MachineFunction private +/// PowerPC target-specific information for each MachineFunction. +class PPCFunctionInfo : public MachineFunctionInfo { +private: + /// FramePointerSaveIndex - Frame index of where the old frame pointer is + /// stored. Also used as an anchor for instructions that need to be altered + /// when using frame pointers (dyna_add, dyna_sub.) + int FramePointerSaveIndex; + + /// ReturnAddrSaveIndex - Frame index of where the return address is stored. + /// + int ReturnAddrSaveIndex; + + /// MustSaveLR - Indicates whether LR is defined (or clobbered) in the current + /// function. This is only valid after the initial scan of the function by + /// PEI. + bool MustSaveLR; + + /// SpillsCR - Indicates whether CR is spilled in the current function. + bool SpillsCR; + + /// LRStoreRequired - The bool indicates whether there is some explicit use of + /// the LR/LR8 stack slot that is not obvious from scanning the code. This + /// requires that the code generator produce a store of LR to the stack on + /// entry, even though LR may otherwise apparently not be used. + bool LRStoreRequired; + + /// MinReservedArea - This is the frame size that is at least reserved in a + /// potential caller (parameter+linkage area). + unsigned MinReservedArea; + + /// TailCallSPDelta - Stack pointer delta used when tail calling. Maximum + /// amount the stack pointer is adjusted to make the frame bigger for tail + /// calls. Used for creating an area before the register spill area. + int TailCallSPDelta; + + /// HasFastCall - Does this function contain a fast call. Used to determine + /// how the caller's stack pointer should be calculated (epilog/dynamicalloc). + bool HasFastCall; + +public: + explicit PPCFunctionInfo(MachineFunction &MF) + : FramePointerSaveIndex(0), + ReturnAddrSaveIndex(0), + SpillsCR(false), + LRStoreRequired(false), + MinReservedArea(0), + TailCallSPDelta(0), + HasFastCall(false) {} + + int getFramePointerSaveIndex() const { return FramePointerSaveIndex; } + void setFramePointerSaveIndex(int Idx) { FramePointerSaveIndex = Idx; } + + int getReturnAddrSaveIndex() const { return ReturnAddrSaveIndex; } + void setReturnAddrSaveIndex(int idx) { ReturnAddrSaveIndex = idx; } + + unsigned getMinReservedArea() const { return MinReservedArea; } + void setMinReservedArea(unsigned size) { MinReservedArea = size; } + + int getTailCallSPDelta() const { return TailCallSPDelta; } + void setTailCallSPDelta(int size) { TailCallSPDelta = size; } + + /// MustSaveLR - This is set when the prolog/epilog inserter does its initial + /// scan of the function. It is true if the LR/LR8 register is ever explicitly + /// defined/clobbered in the machine function (e.g. by calls and movpctolr, + /// which is used in PIC generation), or if the LR stack slot is explicitly + /// referenced by builtin_return_address. + void setMustSaveLR(bool U) { MustSaveLR = U; } + bool mustSaveLR() const { return MustSaveLR; } + + void setSpillsCR() { SpillsCR = true; } + bool isCRSpilled() const { return SpillsCR; } + + void setLRStoreRequired() { LRStoreRequired = true; } + bool isLRStoreRequired() const { return LRStoreRequired; } + + void setHasFastCall() { HasFastCall = true; } + bool hasFastCall() const { return HasFastCall;} +}; + +} // end of namespace llvm + + +#endif diff --git a/libclamav/c++/llvm/lib/Target/PowerPC/PPCPerfectShuffle.h b/libclamav/c++/llvm/lib/Target/PowerPC/PPCPerfectShuffle.h new file mode 100644 index 000000000..3164e33fa --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/PowerPC/PPCPerfectShuffle.h @@ -0,0 +1,6586 @@ +//===-- PPCPerfectShuffle.h - Altivec Perfect Shuffle Table ---------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file, which was autogenerated by llvm-PerfectShuffle, contains data +// for the optimal way to build a perfect shuffle without using vperm. +// +//===----------------------------------------------------------------------===// + +// 31 entries have cost 0 +// 292 entries have cost 1 +// 1384 entries have cost 2 +// 3061 entries have cost 3 +// 1733 entries have cost 4 +// 60 entries have cost 5 + +// This table is 6561*4 = 26244 bytes in size. +static const unsigned PerfectShuffleTable[6561+1] = { + 202162278U, // <0,0,0,0>: Cost 1 vspltisw0 LHS + 1140850790U, // <0,0,0,1>: Cost 2 vmrghw <0,0,0,0>, LHS + 2617247181U, // <0,0,0,2>: Cost 3 vsldoi4 <0,0,0,0>, <2,0,3,0> + 2635163787U, // <0,0,0,3>: Cost 3 vsldoi4 <3,0,0,0>, <3,0,0,0> + 1543507254U, // <0,0,0,4>: Cost 2 vsldoi4 <0,0,0,0>, RHS + 2281701705U, // <0,0,0,5>: Cost 3 vmrglw <0,0,0,0>, <0,4,0,5> + 2617250133U, // <0,0,0,6>: Cost 3 vsldoi4 <0,0,0,0>, <6,0,7,0> + 2659054575U, // <0,0,0,7>: Cost 3 vsldoi4 <7,0,0,0>, <7,0,0,0> + 202162278U, // <0,0,0,u>: Cost 1 vspltisw0 LHS + 1141686282U, // <0,0,1,0>: Cost 2 vmrghw LHS, <0,0,1,1> + 67944550U, // <0,0,1,1>: Cost 1 vmrghw LHS, LHS + 1685241958U, // <0,0,1,2>: Cost 2 vsldoi12 <1,2,3,0>, LHS + 2215870716U, // <0,0,1,3>: Cost 3 vmrghw LHS, <0,3,1,0> + 1141727570U, // <0,0,1,4>: Cost 2 vmrghw LHS, <0,4,1,5> + 2215428562U, // <0,0,1,5>: Cost 3 vmrghw LHS, <0,5,6,7> + 2215428589U, // <0,0,1,6>: Cost 3 vmrghw LHS, <0,6,0,7> + 2659062768U, // <0,0,1,7>: Cost 3 vsldoi4 <7,0,0,1>, <7,0,0,1> + 67945117U, // <0,0,1,u>: Cost 1 vmrghw LHS, LHS + 2684356045U, // <0,0,2,0>: Cost 3 vsldoi8 <0,0,0,0>, <2,0,3,0> + 2216009830U, // <0,0,2,1>: Cost 3 vmrghw <0,2,1,2>, LHS + 2216009901U, // <0,0,2,2>: Cost 3 vmrghw <0,2,1,2>, <0,2,1,2> + 2698290853U, // <0,0,2,3>: Cost 3 vsldoi8 <2,3,0,0>, <2,3,0,0> + 3289751890U, // <0,0,2,4>: Cost 4 vmrghw <0,2,1,2>, <0,4,1,5> + 3758098275U, // <0,0,2,5>: Cost 4 vsldoi8 <0,0,0,0>, <2,5,3,1> + 2684356538U, // <0,0,2,6>: Cost 3 vsldoi8 <0,0,0,0>, <2,6,3,7> + 3758098410U, // <0,0,2,7>: Cost 4 vsldoi8 <0,0,0,0>, <2,7,0,1> + 2216010397U, // <0,0,2,u>: Cost 3 vmrghw <0,2,1,2>, LHS + 2702272651U, // <0,0,3,0>: Cost 3 vsldoi8 <3,0,0,0>, <3,0,0,0> + 2216656998U, // <0,0,3,1>: Cost 3 vmrghw <0,3,1,0>, LHS + 3844669704U, // <0,0,3,2>: Cost 4 vsldoi12 <3,2,3,0>, <0,3,2,3> + 2216657148U, // <0,0,3,3>: Cost 3 vmrghw <0,3,1,0>, <0,3,1,0> + 2684357122U, // <0,0,3,4>: Cost 3 vsldoi8 <0,0,0,0>, <3,4,5,6> + 3732820066U, // <0,0,3,5>: Cost 4 vsldoi4 <7,0,0,3>, <5,6,7,0> + 3778005624U, // <0,0,3,6>: Cost 4 vsldoi8 <3,3,0,0>, <3,6,0,7> + 3374713464U, // <0,0,3,7>: Cost 4 vmrglw <3,2,0,3>, <3,6,0,7> + 2216657565U, // <0,0,3,u>: Cost 3 vmrghw <0,3,1,0>, LHS + 2217361408U, // <0,0,4,0>: Cost 3 vmrghw <0,4,1,5>, <0,0,0,0> + 1143619686U, // <0,0,4,1>: Cost 2 vmrghw <0,4,1,5>, LHS + 3291103405U, // <0,0,4,2>: Cost 4 vmrghw <0,4,1,5>, <0,2,1,2> + 3827269988U, // <0,0,4,3>: Cost 4 vsldoi12 <0,3,1,0>, <0,4,3,5> + 1143619922U, // <0,0,4,4>: Cost 2 vmrghw <0,4,1,5>, <0,4,1,5> + 1610616118U, // <0,0,4,5>: Cost 2 vsldoi8 <0,0,0,0>, RHS + 3758099833U, // <0,0,4,6>: Cost 4 vsldoi8 <0,0,0,0>, <4,6,5,2> + 3854107016U, // <0,0,4,7>: Cost 4 vsldoi12 <4,7,5,0>, <0,4,7,5> + 1143620253U, // <0,0,4,u>: Cost 2 vmrghw <0,4,1,5>, LHS + 2284396544U, // <0,0,5,0>: Cost 3 vmrglw <0,4,0,5>, <0,0,0,0> + 2218025062U, // <0,0,5,1>: Cost 3 vmrghw <0,5,1,5>, LHS + 3758100203U, // <0,0,5,2>: Cost 4 vsldoi8 <0,0,0,0>, <5,2,1,3> + 3395966100U, // <0,0,5,3>: Cost 4 vmrglw <6,7,0,5>, <7,2,0,3> + 3804549052U, // <0,0,5,4>: Cost 4 vsldoi8 <7,7,0,0>, <5,4,6,5> + 2302314964U, // <0,0,5,5>: Cost 3 vmrglw <3,4,0,5>, <3,4,0,5> + 2785821138U, // <0,0,5,6>: Cost 3 vsldoi12 <5,6,7,0>, <0,5,6,7> + 3395966428U, // <0,0,5,7>: Cost 4 vmrglw <6,7,0,5>, <7,6,0,7> + 2787148260U, // <0,0,5,u>: Cost 3 vsldoi12 <5,u,7,0>, <0,5,u,7> + 2684358997U, // <0,0,6,0>: Cost 3 vsldoi8 <0,0,0,0>, <6,0,7,0> + 2218631270U, // <0,0,6,1>: Cost 3 vmrghw <0,6,0,7>, LHS + 2684359162U, // <0,0,6,2>: Cost 3 vsldoi8 <0,0,0,0>, <6,2,7,3> + 3758101042U, // <0,0,6,3>: Cost 4 vsldoi8 <0,0,0,0>, <6,3,4,5> + 3732843830U, // <0,0,6,4>: Cost 4 vsldoi4 <7,0,0,6>, RHS + 3758101227U, // <0,0,6,5>: Cost 4 vsldoi8 <0,0,0,0>, <6,5,7,1> + 2684359480U, // <0,0,6,6>: Cost 3 vsldoi8 <0,0,0,0>, <6,6,6,6> + 2724836173U, // <0,0,6,7>: Cost 3 vsldoi8 <6,7,0,0>, <6,7,0,0> + 2725499806U, // <0,0,6,u>: Cost 3 vsldoi8 <6,u,0,0>, <6,u,0,0> + 2726163439U, // <0,0,7,0>: Cost 3 vsldoi8 <7,0,0,0>, <7,0,0,0> + 2219311206U, // <0,0,7,1>: Cost 3 vmrghw <0,7,1,0>, LHS + 3868557900U, // <0,0,7,2>: Cost 4 vsldoi12 <7,2,3,0>, <0,7,2,3> + 3377400112U, // <0,0,7,3>: Cost 4 vmrglw <3,6,0,7>, <3,2,0,3> + 2684360038U, // <0,0,7,4>: Cost 3 vsldoi8 <0,0,0,0>, <7,4,5,6> + 3732852834U, // <0,0,7,5>: Cost 4 vsldoi4 <7,0,0,7>, <5,6,7,0> + 3871507060U, // <0,0,7,6>: Cost 4 vsldoi12 <7,6,7,0>, <0,7,6,7> + 2303658616U, // <0,0,7,7>: Cost 3 vmrglw <3,6,0,7>, <3,6,0,7> + 2726163439U, // <0,0,7,u>: Cost 3 vsldoi8 <7,0,0,0>, <7,0,0,0> + 202162278U, // <0,0,u,0>: Cost 1 vspltisw0 LHS + 72589414U, // <0,0,u,1>: Cost 1 vmrghw LHS, LHS + 1685242525U, // <0,0,u,2>: Cost 2 vsldoi12 <1,2,3,0>, LHS + 2220073212U, // <0,0,u,3>: Cost 3 vmrghw LHS, <0,3,1,0> + 1146331474U, // <0,0,u,4>: Cost 2 vmrghw LHS, <0,4,1,5> + 1610619034U, // <0,0,u,5>: Cost 2 vsldoi8 <0,0,0,0>, RHS + 2785821138U, // <0,0,u,6>: Cost 3 vsldoi12 <5,6,7,0>, <0,5,6,7> + 2659120119U, // <0,0,u,7>: Cost 3 vsldoi4 <7,0,0,u>, <7,0,0,u> + 72589981U, // <0,0,u,u>: Cost 1 vmrghw LHS, LHS + 2698297344U, // <0,1,0,0>: Cost 3 vsldoi8 <2,3,0,1>, <0,0,0,0> + 1624555622U, // <0,1,0,1>: Cost 2 vsldoi8 <2,3,0,1>, LHS + 2758984428U, // <0,1,0,2>: Cost 3 vsldoi12 <1,2,3,0>, <1,0,2,1> + 2635237524U, // <0,1,0,3>: Cost 3 vsldoi4 <3,0,1,0>, <3,0,1,0> + 2693652818U, // <0,1,0,4>: Cost 3 vsldoi8 <1,5,0,1>, <0,4,1,5> + 2281701714U, // <0,1,0,5>: Cost 3 vmrglw <0,0,0,0>, <0,4,1,5> + 2698297846U, // <0,1,0,6>: Cost 3 vsldoi8 <2,3,0,1>, <0,6,1,7> + 2659128312U, // <0,1,0,7>: Cost 3 vsldoi4 <7,0,1,0>, <7,0,1,0> + 1624556189U, // <0,1,0,u>: Cost 2 vsldoi8 <2,3,0,1>, LHS + 1543585802U, // <0,1,1,0>: Cost 2 vsldoi4 <0,0,1,1>, <0,0,1,1> + 1141728052U, // <0,1,1,1>: Cost 2 vmrghw LHS, <1,1,1,1> + 1141728150U, // <0,1,1,2>: Cost 2 vmrghw LHS, <1,2,3,0> + 2295644334U, // <0,1,1,3>: Cost 3 vmrglw <2,3,0,1>, <0,2,1,3> + 1543589174U, // <0,1,1,4>: Cost 2 vsldoi4 <0,0,1,1>, RHS + 2290999634U, // <0,1,1,5>: Cost 3 vmrglw <1,5,0,1>, <0,4,1,5> + 2617332135U, // <0,1,1,6>: Cost 3 vsldoi4 <0,0,1,1>, <6,1,7,1> + 2617332720U, // <0,1,1,7>: Cost 3 vsldoi4 <0,0,1,1>, <7,0,0,1> + 1142171004U, // <0,1,1,u>: Cost 2 vmrghw LHS, <1,u,3,0> + 1561509990U, // <0,1,2,0>: Cost 2 vsldoi4 <3,0,1,2>, LHS + 2623308516U, // <0,1,2,1>: Cost 3 vsldoi4 <1,0,1,2>, <1,0,1,2> + 2698298984U, // <0,1,2,2>: Cost 3 vsldoi8 <2,3,0,1>, <2,2,2,2> + 835584U, // <0,1,2,3>: Cost 0 copy LHS + 1561513270U, // <0,1,2,4>: Cost 2 vsldoi4 <3,0,1,2>, RHS + 2647199304U, // <0,1,2,5>: Cost 3 vsldoi4 <5,0,1,2>, <5,0,1,2> + 2698299322U, // <0,1,2,6>: Cost 3 vsldoi8 <2,3,0,1>, <2,6,3,7> + 1585402874U, // <0,1,2,7>: Cost 2 vsldoi4 <7,0,1,2>, <7,0,1,2> + 835584U, // <0,1,2,u>: Cost 0 copy LHS + 2698299540U, // <0,1,3,0>: Cost 3 vsldoi8 <2,3,0,1>, <3,0,1,0> + 3290399540U, // <0,1,3,1>: Cost 4 vmrghw <0,3,1,0>, <1,1,1,1> + 2698299720U, // <0,1,3,2>: Cost 3 vsldoi8 <2,3,0,1>, <3,2,3,0> + 2698299804U, // <0,1,3,3>: Cost 3 vsldoi8 <2,3,0,1>, <3,3,3,3> + 2698299906U, // <0,1,3,4>: Cost 3 vsldoi8 <2,3,0,1>, <3,4,5,6> + 3832726521U, // <0,1,3,5>: Cost 4 vsldoi12 <1,2,3,0>, <1,3,5,0> + 2724842160U, // <0,1,3,6>: Cost 3 vsldoi8 <6,7,0,1>, <3,6,7,0> + 2706926275U, // <0,1,3,7>: Cost 3 vsldoi8 <3,7,0,1>, <3,7,0,1> + 2698300190U, // <0,1,3,u>: Cost 3 vsldoi8 <2,3,0,1>, <3,u,1,2> + 2635268198U, // <0,1,4,0>: Cost 3 vsldoi4 <3,0,1,4>, LHS + 2217362228U, // <0,1,4,1>: Cost 3 vmrghw <0,4,1,5>, <1,1,1,1> + 2217362326U, // <0,1,4,2>: Cost 3 vmrghw <0,4,1,5>, <1,2,3,0> + 2635270296U, // <0,1,4,3>: Cost 3 vsldoi4 <3,0,1,4>, <3,0,1,4> + 2635271478U, // <0,1,4,4>: Cost 3 vsldoi4 <3,0,1,4>, RHS + 1624558902U, // <0,1,4,5>: Cost 2 vsldoi8 <2,3,0,1>, RHS + 2659160910U, // <0,1,4,6>: Cost 3 vsldoi4 <7,0,1,4>, <6,7,0,1> + 2659161084U, // <0,1,4,7>: Cost 3 vsldoi4 <7,0,1,4>, <7,0,1,4> + 1624559145U, // <0,1,4,u>: Cost 2 vsldoi8 <2,3,0,1>, RHS + 3832726639U, // <0,1,5,0>: Cost 4 vsldoi12 <1,2,3,0>, <1,5,0,1> + 2714889871U, // <0,1,5,1>: Cost 3 vsldoi8 <5,1,0,1>, <5,1,0,1> + 2302314646U, // <0,1,5,2>: Cost 3 vmrglw <3,4,0,5>, <3,0,1,2> + 3834717321U, // <0,1,5,3>: Cost 4 vsldoi12 <1,5,3,0>, <1,5,3,0> + 3832726679U, // <0,1,5,4>: Cost 4 vsldoi12 <1,2,3,0>, <1,5,4,5> + 2717544403U, // <0,1,5,5>: Cost 3 vsldoi8 <5,5,0,1>, <5,5,0,1> + 2718208036U, // <0,1,5,6>: Cost 3 vsldoi8 <5,6,0,1>, <5,6,0,1> + 3792613493U, // <0,1,5,7>: Cost 4 vsldoi8 <5,7,0,1>, <5,7,0,1> + 2719535302U, // <0,1,5,u>: Cost 3 vsldoi8 <5,u,0,1>, <5,u,0,1> + 2659172454U, // <0,1,6,0>: Cost 3 vsldoi4 <7,0,1,6>, LHS + 3832726735U, // <0,1,6,1>: Cost 4 vsldoi12 <1,2,3,0>, <1,6,1,7> + 2724844026U, // <0,1,6,2>: Cost 3 vsldoi8 <6,7,0,1>, <6,2,7,3> + 3775361608U, // <0,1,6,3>: Cost 4 vsldoi8 <2,u,0,1>, <6,3,7,0> + 2659175734U, // <0,1,6,4>: Cost 3 vsldoi4 <7,0,1,6>, RHS + 3832726771U, // <0,1,6,5>: Cost 4 vsldoi12 <1,2,3,0>, <1,6,5,7> + 2724844344U, // <0,1,6,6>: Cost 3 vsldoi8 <6,7,0,1>, <6,6,6,6> + 1651102542U, // <0,1,6,7>: Cost 2 vsldoi8 <6,7,0,1>, <6,7,0,1> + 1651766175U, // <0,1,6,u>: Cost 2 vsldoi8 <6,u,0,1>, <6,u,0,1> + 2724844536U, // <0,1,7,0>: Cost 3 vsldoi8 <6,7,0,1>, <7,0,1,0> + 3377397770U, // <0,1,7,1>: Cost 4 vmrglw <3,6,0,7>, <0,0,1,1> + 2698302636U, // <0,1,7,2>: Cost 3 vsldoi8 <2,3,0,1>, <7,2,3,0> + 2728162531U, // <0,1,7,3>: Cost 3 vsldoi8 <7,3,0,1>, <7,3,0,1> + 2724844902U, // <0,1,7,4>: Cost 3 vsldoi8 <6,7,0,1>, <7,4,5,6> + 3377398098U, // <0,1,7,5>: Cost 4 vmrglw <3,6,0,7>, <0,4,1,5> + 2724845076U, // <0,1,7,6>: Cost 3 vsldoi8 <6,7,0,1>, <7,6,7,0> + 2724845164U, // <0,1,7,7>: Cost 3 vsldoi8 <6,7,0,1>, <7,7,7,7> + 2724845186U, // <0,1,7,u>: Cost 3 vsldoi8 <6,7,0,1>, <7,u,1,2> + 1561559142U, // <0,1,u,0>: Cost 2 vsldoi4 <3,0,1,u>, LHS + 1146331956U, // <0,1,u,1>: Cost 2 vmrghw LHS, <1,1,1,1> + 1146332054U, // <0,1,u,2>: Cost 2 vmrghw LHS, <1,2,3,0> + 835584U, // <0,1,u,3>: Cost 0 copy LHS + 1561562422U, // <0,1,u,4>: Cost 2 vsldoi4 <3,0,1,u>, RHS + 1624561818U, // <0,1,u,5>: Cost 2 vsldoi8 <2,3,0,1>, RHS + 2220074191U, // <0,1,u,6>: Cost 3 vmrghw LHS, <1,6,1,7> + 1585452032U, // <0,1,u,7>: Cost 2 vsldoi4 <7,0,1,u>, <7,0,1,u> + 835584U, // <0,1,u,u>: Cost 0 copy LHS + 2214593997U, // <0,2,0,0>: Cost 3 vmrghw <0,0,0,0>, <2,0,3,0> + 2214675999U, // <0,2,0,1>: Cost 3 vmrghw <0,0,1,1>, <2,1,3,1> + 2214594152U, // <0,2,0,2>: Cost 3 vmrghw <0,0,0,0>, <2,2,2,2> + 1207959654U, // <0,2,0,3>: Cost 2 vmrglw <0,0,0,0>, LHS + 3709054262U, // <0,2,0,4>: Cost 4 vsldoi4 <3,0,2,0>, RHS + 3375350836U, // <0,2,0,5>: Cost 4 vmrglw <3,3,0,0>, <1,4,2,5> + 2214594490U, // <0,2,0,6>: Cost 3 vmrghw <0,0,0,0>, <2,6,3,7> + 3288336362U, // <0,2,0,7>: Cost 4 vmrghw <0,0,0,0>, <2,7,0,1> + 1207959659U, // <0,2,0,u>: Cost 2 vmrglw <0,0,0,0>, LHS + 2215871994U, // <0,2,1,0>: Cost 3 vmrghw LHS, <2,0,u,0> + 2215470623U, // <0,2,1,1>: Cost 3 vmrghw LHS, <2,1,3,1> + 1141728872U, // <0,2,1,2>: Cost 2 vmrghw LHS, <2,2,2,2> + 1141728934U, // <0,2,1,3>: Cost 2 vmrghw LHS, <2,3,0,1> + 2215872323U, // <0,2,1,4>: Cost 3 vmrghw LHS, <2,4,u,5> + 2215872405U, // <0,2,1,5>: Cost 3 vmrghw LHS, <2,5,u,6> + 1141729210U, // <0,2,1,6>: Cost 2 vmrghw LHS, <2,6,3,7> + 2215430122U, // <0,2,1,7>: Cost 3 vmrghw LHS, <2,7,0,1> + 1141729368U, // <0,2,1,u>: Cost 2 vmrghw LHS, <2,u,3,3> + 3289736698U, // <0,2,2,0>: Cost 4 vmrghw <0,2,1,0>, <2,0,u,0> + 3289744927U, // <0,2,2,1>: Cost 4 vmrghw <0,2,1,1>, <2,1,3,1> + 2216011368U, // <0,2,2,2>: Cost 3 vmrghw <0,2,1,2>, <2,2,2,2> + 2216019622U, // <0,2,2,3>: Cost 3 vmrghw <0,2,1,3>, <2,3,0,1> + 3289769795U, // <0,2,2,4>: Cost 4 vmrghw <0,2,1,4>, <2,4,u,5> + 3289778069U, // <0,2,2,5>: Cost 4 vmrghw <0,2,1,5>, <2,5,u,6> + 2216044474U, // <0,2,2,6>: Cost 3 vmrghw <0,2,1,6>, <2,6,3,7> + 3732960259U, // <0,2,2,7>: Cost 4 vsldoi4 <7,0,2,2>, <7,0,2,2> + 2216061016U, // <0,2,2,u>: Cost 3 vmrghw <0,2,1,u>, <2,u,3,3> + 2758985382U, // <0,2,3,0>: Cost 3 vsldoi12 <1,2,3,0>, <2,3,0,1> + 2758985392U, // <0,2,3,1>: Cost 3 vsldoi12 <1,2,3,0>, <2,3,1,2> + 3290400360U, // <0,2,3,2>: Cost 4 vmrghw <0,3,1,0>, <2,2,2,2> + 2758985408U, // <0,2,3,3>: Cost 3 vsldoi12 <1,2,3,0>, <2,3,3,0> + 2758985422U, // <0,2,3,4>: Cost 3 vsldoi12 <1,2,3,0>, <2,3,4,5> + 2785822424U, // <0,2,3,5>: Cost 3 vsldoi12 <5,6,7,0>, <2,3,5,6> + 3290400698U, // <0,2,3,6>: Cost 4 vmrghw <0,3,1,0>, <2,6,3,7> + 2765915876U, // <0,2,3,7>: Cost 3 vsldoi12 <2,3,7,0>, <2,3,7,0> + 2758985453U, // <0,2,3,u>: Cost 3 vsldoi12 <1,2,3,0>, <2,3,u,0> + 3291104762U, // <0,2,4,0>: Cost 4 vmrghw <0,4,1,5>, <2,0,u,0> + 2217362979U, // <0,2,4,1>: Cost 3 vmrghw <0,4,1,5>, <2,1,3,5> + 2217363048U, // <0,2,4,2>: Cost 3 vmrghw <0,4,1,5>, <2,2,2,2> + 2217363110U, // <0,2,4,3>: Cost 3 vmrghw <0,4,1,5>, <2,3,0,1> + 3291105087U, // <0,2,4,4>: Cost 4 vmrghw <0,4,1,5>, <2,4,u,1> + 3291105173U, // <0,2,4,5>: Cost 4 vmrghw <0,4,1,5>, <2,5,u,6> + 2217363386U, // <0,2,4,6>: Cost 3 vmrghw <0,4,1,5>, <2,6,3,7> + 3788639688U, // <0,2,4,7>: Cost 4 vsldoi8 <5,1,0,2>, <4,7,5,0> + 2217363515U, // <0,2,4,u>: Cost 3 vmrghw <0,4,1,5>, <2,u,0,1> + 3376054371U, // <0,2,5,0>: Cost 4 vmrglw <3,4,0,5>, <0,1,2,0> + 3788639888U, // <0,2,5,1>: Cost 4 vsldoi8 <5,1,0,2>, <5,1,0,2> + 3376055912U, // <0,2,5,2>: Cost 4 vmrglw <3,4,0,5>, <2,2,2,2> + 2302312550U, // <0,2,5,3>: Cost 3 vmrglw <3,4,0,5>, LHS + 3376054375U, // <0,2,5,4>: Cost 4 vmrglw <3,4,0,5>, <0,1,2,4> + 3374728244U, // <0,2,5,5>: Cost 4 vmrglw <3,2,0,5>, <1,4,2,5> + 3805229154U, // <0,2,5,6>: Cost 4 vsldoi8 <7,u,0,2>, <5,6,7,0> + 3376055512U, // <0,2,5,7>: Cost 4 vmrglw <3,4,0,5>, <1,6,2,7> + 2302312555U, // <0,2,5,u>: Cost 3 vmrglw <3,4,0,5>, LHS + 3709100134U, // <0,2,6,0>: Cost 4 vsldoi4 <3,0,2,6>, LHS + 3709100950U, // <0,2,6,1>: Cost 4 vsldoi4 <3,0,2,6>, <1,2,3,0> + 3709102010U, // <0,2,6,2>: Cost 4 vsldoi4 <3,0,2,6>, <2,6,3,7> + 2758985658U, // <0,2,6,3>: Cost 3 vsldoi12 <1,2,3,0>, <2,6,3,7> + 3709103414U, // <0,2,6,4>: Cost 4 vsldoi4 <3,0,2,6>, RHS + 3732992098U, // <0,2,6,5>: Cost 4 vsldoi4 <7,0,2,6>, <5,6,7,0> + 3292374970U, // <0,2,6,6>: Cost 4 vmrghw <0,6,0,7>, <2,6,3,7> + 3798594383U, // <0,2,6,7>: Cost 4 vsldoi8 <6,7,0,2>, <6,7,0,2> + 2758985703U, // <0,2,6,u>: Cost 3 vsldoi12 <1,2,3,0>, <2,6,u,7> + 3788641274U, // <0,2,7,0>: Cost 4 vsldoi8 <5,1,0,2>, <7,0,1,2> + 3377398508U, // <0,2,7,1>: Cost 4 vmrglw <3,6,0,7>, <1,0,2,1> + 3377398590U, // <0,2,7,2>: Cost 4 vmrglw <3,6,0,7>, <1,1,2,2> + 2303656038U, // <0,2,7,3>: Cost 3 vmrglw <3,6,0,7>, LHS + 3709111606U, // <0,2,7,4>: Cost 4 vsldoi4 <3,0,2,7>, RHS + 3377398836U, // <0,2,7,5>: Cost 4 vmrglw <3,6,0,7>, <1,4,2,5> + 3803903447U, // <0,2,7,6>: Cost 4 vsldoi8 <7,6,0,2>, <7,6,0,2> + 3293054954U, // <0,2,7,7>: Cost 4 vmrghw <0,7,1,0>, <2,7,0,1> + 2303656043U, // <0,2,7,u>: Cost 3 vmrglw <3,6,0,7>, LHS + 2220074490U, // <0,2,u,0>: Cost 3 vmrghw LHS, <2,0,u,0> + 2220074527U, // <0,2,u,1>: Cost 3 vmrghw LHS, <2,1,3,1> + 1146332776U, // <0,2,u,2>: Cost 2 vmrghw LHS, <2,2,2,2> + 1146332838U, // <0,2,u,3>: Cost 2 vmrghw LHS, <2,3,0,1> + 2220074819U, // <0,2,u,4>: Cost 3 vmrghw LHS, <2,4,u,5> + 2220074901U, // <0,2,u,5>: Cost 3 vmrghw LHS, <2,5,u,6> + 1146333114U, // <0,2,u,6>: Cost 2 vmrghw LHS, <2,6,3,7> + 2220074986U, // <0,2,u,7>: Cost 3 vmrghw LHS, <2,7,0,1> + 1146333243U, // <0,2,u,u>: Cost 2 vmrghw LHS, <2,u,0,1> + 2629410816U, // <0,3,0,0>: Cost 3 vsldoi4 <2,0,3,0>, <0,0,0,0> + 2753530006U, // <0,3,0,1>: Cost 3 vsldoi12 <0,3,1,0>, <3,0,1,2> + 2629412301U, // <0,3,0,2>: Cost 3 vsldoi4 <2,0,3,0>, <2,0,3,0> + 2214594972U, // <0,3,0,3>: Cost 3 vmrghw <0,0,0,0>, <3,3,3,3> + 2758985908U, // <0,3,0,4>: Cost 3 vsldoi12 <1,2,3,0>, <3,0,4,5> + 3733016674U, // <0,3,0,5>: Cost 4 vsldoi4 <7,0,3,0>, <5,6,7,0> + 3777364488U, // <0,3,0,6>: Cost 4 vsldoi8 <3,2,0,3>, <0,6,3,7> + 2281703354U, // <0,3,0,7>: Cost 3 vmrglw <0,0,0,0>, <2,6,3,7> + 2758985941U, // <0,3,0,u>: Cost 3 vsldoi12 <1,2,3,0>, <3,0,u,2> + 1141729430U, // <0,3,1,0>: Cost 2 vmrghw LHS, <3,0,1,2> + 2215471334U, // <0,3,1,1>: Cost 3 vmrghw LHS, <3,1,1,1> + 2215471425U, // <0,3,1,2>: Cost 3 vmrghw LHS, <3,2,2,2> + 1141729692U, // <0,3,1,3>: Cost 2 vmrghw LHS, <3,3,3,3> + 1141729794U, // <0,3,1,4>: Cost 2 vmrghw LHS, <3,4,5,6> + 2215430738U, // <0,3,1,5>: Cost 3 vmrghw LHS, <3,5,5,5> + 2215430776U, // <0,3,1,6>: Cost 3 vmrghw LHS, <3,6,0,7> + 2295646138U, // <0,3,1,7>: Cost 3 vmrglw <2,3,0,1>, <2,6,3,7> + 1141730078U, // <0,3,1,u>: Cost 2 vmrghw LHS, <3,u,1,2> + 2758986032U, // <0,3,2,0>: Cost 3 vsldoi12 <1,2,3,0>, <3,2,0,3> + 3709141910U, // <0,3,2,1>: Cost 4 vsldoi4 <3,0,3,2>, <1,2,3,0> + 3289753921U, // <0,3,2,2>: Cost 4 vmrghw <0,2,1,2>, <3,2,2,2> + 2770929992U, // <0,3,2,3>: Cost 3 vsldoi12 <3,2,3,0>, <3,2,3,0> + 3289754114U, // <0,3,2,4>: Cost 4 vmrghw <0,2,1,2>, <3,4,5,6> + 3362095460U, // <0,3,2,5>: Cost 5 vmrglw <1,1,0,2>, <0,4,3,5> + 3832727910U, // <0,3,2,6>: Cost 4 vsldoi12 <1,2,3,0>, <3,2,6,3> + 3365414842U, // <0,3,2,7>: Cost 4 vmrglw <1,6,0,2>, <2,6,3,7> + 2771298677U, // <0,3,2,u>: Cost 3 vsldoi12 <3,2,u,0>, <3,2,u,0> + 2216659094U, // <0,3,3,0>: Cost 3 vmrghw <0,3,1,0>, <3,0,1,2> + 3290409190U, // <0,3,3,1>: Cost 4 vmrghw <0,3,1,1>, <3,1,1,1> + 2703624496U, // <0,3,3,2>: Cost 3 vsldoi8 <3,2,0,3>, <3,2,0,3> + 2216683932U, // <0,3,3,3>: Cost 3 vmrghw <0,3,1,3>, <3,3,3,3> + 2216692226U, // <0,3,3,4>: Cost 3 vmrghw <0,3,1,4>, <3,4,5,6> + 3733041250U, // <0,3,3,5>: Cost 4 vsldoi4 <7,0,3,3>, <5,6,7,0> + 3832727988U, // <0,3,3,6>: Cost 4 vsldoi12 <1,2,3,0>, <3,3,6,0> + 3374712762U, // <0,3,3,7>: Cost 4 vmrglw <3,2,0,3>, <2,6,3,7> + 2216725278U, // <0,3,3,u>: Cost 3 vmrghw <0,3,1,u>, <3,u,1,2> + 2217363606U, // <0,3,4,0>: Cost 3 vmrghw <0,4,1,5>, <3,0,1,2> + 3291105510U, // <0,3,4,1>: Cost 4 vmrghw <0,4,1,5>, <3,1,1,1> + 3291105601U, // <0,3,4,2>: Cost 4 vmrghw <0,4,1,5>, <3,2,2,2> + 2217363868U, // <0,3,4,3>: Cost 3 vmrghw <0,4,1,5>, <3,3,3,3> + 2217363970U, // <0,3,4,4>: Cost 3 vmrghw <0,4,1,5>, <3,4,5,6> + 2758986242U, // <0,3,4,5>: Cost 3 vsldoi12 <1,2,3,0>, <3,4,5,6> + 3727077685U, // <0,3,4,6>: Cost 4 vsldoi4 <6,0,3,4>, <6,0,3,4> + 3364767674U, // <0,3,4,7>: Cost 4 vmrglw <1,5,0,4>, <2,6,3,7> + 2217364254U, // <0,3,4,u>: Cost 3 vmrghw <0,4,1,5>, <3,u,1,2> + 3832728102U, // <0,3,5,0>: Cost 4 vsldoi12 <1,2,3,0>, <3,5,0,6> + 3405916003U, // <0,3,5,1>: Cost 4 vmrglw , <2,5,3,1> + 3376055840U, // <0,3,5,2>: Cost 4 vmrglw <3,4,0,5>, <2,1,3,2> + 3376055679U, // <0,3,5,3>: Cost 4 vmrglw <3,4,0,5>, <1,u,3,3> + 3376055194U, // <0,3,5,4>: Cost 4 vmrglw <3,4,0,5>, <1,2,3,4> + 3859565138U, // <0,3,5,5>: Cost 4 vsldoi12 <5,6,7,0>, <3,5,5,5> + 2727514210U, // <0,3,5,6>: Cost 3 vsldoi8 <7,2,0,3>, <5,6,7,0> + 3376056250U, // <0,3,5,7>: Cost 4 vmrglw <3,4,0,5>, <2,6,3,7> + 2727514210U, // <0,3,5,u>: Cost 3 vsldoi8 <7,2,0,3>, <5,6,7,0> + 2758986360U, // <0,3,6,0>: Cost 3 vsldoi12 <1,2,3,0>, <3,6,0,7> + 3709174678U, // <0,3,6,1>: Cost 4 vsldoi4 <3,0,3,6>, <1,2,3,0> + 3795284411U, // <0,3,6,2>: Cost 4 vsldoi8 <6,2,0,3>, <6,2,0,3> + 3709175980U, // <0,3,6,3>: Cost 4 vsldoi4 <3,0,3,6>, <3,0,3,6> + 3833096860U, // <0,3,6,4>: Cost 4 vsldoi12 <1,2,u,0>, <3,6,4,7> + 3376728235U, // <0,3,6,5>: Cost 5 vmrglw <3,5,0,6>, <3,0,3,5> + 3859565229U, // <0,3,6,6>: Cost 4 vsldoi12 <5,6,7,0>, <3,6,6,6> + 2773879472U, // <0,3,6,7>: Cost 3 vsldoi12 <3,6,7,0>, <3,6,7,0> + 2758986360U, // <0,3,6,u>: Cost 3 vsldoi12 <1,2,3,0>, <3,6,0,7> + 2303656854U, // <0,3,7,0>: Cost 3 vmrglw <3,6,0,7>, <1,2,3,0> + 3807229018U, // <0,3,7,1>: Cost 4 vsldoi8 , <7,1,2,u> + 2727515284U, // <0,3,7,2>: Cost 3 vsldoi8 <7,2,0,3>, <7,2,0,3> + 3377399410U, // <0,3,7,3>: Cost 4 vmrglw <3,6,0,7>, <2,2,3,3> + 3377398682U, // <0,3,7,4>: Cost 4 vmrglw <3,6,0,7>, <1,2,3,4> + 3801257409U, // <0,3,7,5>: Cost 4 vsldoi8 <7,2,0,3>, <7,5,6,7> + 3377399980U, // <0,3,7,6>: Cost 4 vmrglw <3,6,0,7>, <3,0,3,6> + 3375409082U, // <0,3,7,7>: Cost 4 vmrglw <3,3,0,7>, <2,6,3,7> + 2731497082U, // <0,3,7,u>: Cost 3 vsldoi8 <7,u,0,3>, <7,u,0,3> + 1146333334U, // <0,3,u,0>: Cost 2 vmrghw LHS, <3,0,1,2> + 2220075238U, // <0,3,u,1>: Cost 3 vmrghw LHS, <3,1,1,1> + 2220075329U, // <0,3,u,2>: Cost 3 vmrghw LHS, <3,2,2,2> + 1146333596U, // <0,3,u,3>: Cost 2 vmrghw LHS, <3,3,3,3> + 1146333698U, // <0,3,u,4>: Cost 2 vmrghw LHS, <3,4,5,6> + 2758986566U, // <0,3,u,5>: Cost 3 vsldoi12 <1,2,3,0>, <3,u,5,6> + 2803739472U, // <0,3,u,6>: Cost 3 vsldoi12 , <3,u,6,7> + 2295703482U, // <0,3,u,7>: Cost 3 vmrglw <2,3,0,u>, <2,6,3,7> + 1146333982U, // <0,3,u,u>: Cost 2 vmrghw LHS, <3,u,1,2> + 2214595473U, // <0,4,0,0>: Cost 3 vmrghw <0,0,0,0>, <4,0,5,0> + 2693677158U, // <0,4,0,1>: Cost 3 vsldoi8 <1,5,0,4>, LHS + 3839437689U, // <0,4,0,2>: Cost 4 vsldoi12 <2,3,4,0>, <4,0,2,3> + 3709200559U, // <0,4,0,3>: Cost 4 vsldoi4 <3,0,4,0>, <3,0,4,0> + 2693677394U, // <0,4,0,4>: Cost 3 vsldoi8 <1,5,0,4>, <0,4,1,5> + 1140854070U, // <0,4,0,5>: Cost 2 vmrghw <0,0,0,0>, RHS + 3767419409U, // <0,4,0,6>: Cost 4 vsldoi8 <1,5,0,4>, <0,6,4,7> + 3854109604U, // <0,4,0,7>: Cost 4 vsldoi12 <4,7,5,0>, <4,0,7,1> + 1140854313U, // <0,4,0,u>: Cost 2 vmrghw <0,0,0,0>, RHS + 1141689234U, // <0,4,1,0>: Cost 2 vmrghw LHS, <4,0,5,1> + 2215431114U, // <0,4,1,1>: Cost 3 vmrghw LHS, <4,1,2,3> + 2215431221U, // <0,4,1,2>: Cost 3 vmrghw LHS, <4,2,5,2> + 2635466928U, // <0,4,1,3>: Cost 3 vsldoi4 <3,0,4,1>, <3,0,4,1> + 1141689552U, // <0,4,1,4>: Cost 2 vmrghw LHS, <4,4,4,4> + 67947830U, // <0,4,1,5>: Cost 1 vmrghw LHS, RHS + 2215431545U, // <0,4,1,6>: Cost 3 vmrghw LHS, <4,6,5,2> + 2659357716U, // <0,4,1,7>: Cost 3 vsldoi4 <7,0,4,1>, <7,0,4,1> + 67948073U, // <0,4,1,u>: Cost 1 vmrghw LHS, RHS + 3767420369U, // <0,4,2,0>: Cost 4 vsldoi8 <1,5,0,4>, <2,0,3,4> + 3767420451U, // <0,4,2,1>: Cost 4 vsldoi8 <1,5,0,4>, <2,1,3,5> + 3767420520U, // <0,4,2,2>: Cost 4 vsldoi8 <1,5,0,4>, <2,2,2,2> + 2698323625U, // <0,4,2,3>: Cost 3 vsldoi8 <2,3,0,4>, <2,3,0,4> + 3709218102U, // <0,4,2,4>: Cost 4 vsldoi4 <3,0,4,2>, RHS + 2216013110U, // <0,4,2,5>: Cost 3 vmrghw <0,2,1,2>, RHS + 3767420858U, // <0,4,2,6>: Cost 4 vsldoi8 <1,5,0,4>, <2,6,3,7> + 3774719981U, // <0,4,2,7>: Cost 4 vsldoi8 <2,7,0,4>, <2,7,0,4> + 2216013353U, // <0,4,2,u>: Cost 3 vmrghw <0,2,1,2>, RHS + 3767421078U, // <0,4,3,0>: Cost 4 vsldoi8 <1,5,0,4>, <3,0,1,2> + 3776710880U, // <0,4,3,1>: Cost 4 vsldoi8 <3,1,0,4>, <3,1,0,4> + 3833097325U, // <0,4,3,2>: Cost 5 vsldoi12 <1,2,u,0>, <4,3,2,4> + 3767421340U, // <0,4,3,3>: Cost 4 vsldoi8 <1,5,0,4>, <3,3,3,3> + 3767421442U, // <0,4,3,4>: Cost 4 vsldoi8 <1,5,0,4>, <3,4,5,6> + 2216660278U, // <0,4,3,5>: Cost 3 vmrghw <0,3,1,0>, RHS + 3833097361U, // <0,4,3,6>: Cost 5 vsldoi12 <1,2,u,0>, <4,3,6,4> + 3780692678U, // <0,4,3,7>: Cost 4 vsldoi8 <3,7,0,4>, <3,7,0,4> + 2216660521U, // <0,4,3,u>: Cost 3 vmrghw <0,3,1,0>, RHS + 2617573416U, // <0,4,4,0>: Cost 3 vsldoi4 <0,0,4,4>, <0,0,4,4> + 2217364450U, // <0,4,4,1>: Cost 3 vmrghw <0,4,1,5>, <4,1,5,0> + 3691316771U, // <0,4,4,2>: Cost 4 vsldoi4 <0,0,4,4>, <2,1,3,5> + 3709233331U, // <0,4,4,3>: Cost 4 vsldoi4 <3,0,4,4>, <3,0,4,4> + 2785823952U, // <0,4,4,4>: Cost 3 vsldoi12 <5,6,7,0>, <4,4,4,4> + 1143622966U, // <0,4,4,5>: Cost 2 vmrghw <0,4,1,5>, RHS + 3691319723U, // <0,4,4,6>: Cost 4 vsldoi4 <0,0,4,4>, <6,1,7,5> + 3854109932U, // <0,4,4,7>: Cost 4 vsldoi12 <4,7,5,0>, <4,4,7,5> + 1143623209U, // <0,4,4,u>: Cost 2 vmrghw <0,4,1,5>, RHS + 2635497574U, // <0,4,5,0>: Cost 3 vsldoi4 <3,0,4,5>, LHS + 2635498390U, // <0,4,5,1>: Cost 3 vsldoi4 <3,0,4,5>, <1,2,3,0> + 3709240936U, // <0,4,5,2>: Cost 4 vsldoi4 <3,0,4,5>, <2,2,2,2> + 2635499700U, // <0,4,5,3>: Cost 3 vsldoi4 <3,0,4,5>, <3,0,4,5> + 2635500854U, // <0,4,5,4>: Cost 3 vsldoi4 <3,0,4,5>, RHS + 2785824044U, // <0,4,5,5>: Cost 3 vsldoi12 <5,6,7,0>, <4,5,5,6> + 1685245238U, // <0,4,5,6>: Cost 2 vsldoi12 <1,2,3,0>, RHS + 2659390488U, // <0,4,5,7>: Cost 3 vsldoi4 <7,0,4,5>, <7,0,4,5> + 1685245256U, // <0,4,5,u>: Cost 2 vsldoi12 <1,2,3,0>, RHS + 3839438161U, // <0,4,6,0>: Cost 4 vsldoi12 <2,3,4,0>, <4,6,0,7> + 3798610347U, // <0,4,6,1>: Cost 4 vsldoi8 <6,7,0,4>, <6,1,7,5> + 3798610426U, // <0,4,6,2>: Cost 4 vsldoi8 <6,7,0,4>, <6,2,7,3> + 3795956237U, // <0,4,6,3>: Cost 4 vsldoi8 <6,3,0,4>, <6,3,0,4> + 3733138742U, // <0,4,6,4>: Cost 4 vsldoi4 <7,0,4,6>, RHS + 2218634550U, // <0,4,6,5>: Cost 3 vmrghw <0,6,0,7>, RHS + 3798610744U, // <0,4,6,6>: Cost 4 vsldoi8 <6,7,0,4>, <6,6,6,6> + 2724868945U, // <0,4,6,7>: Cost 3 vsldoi8 <6,7,0,4>, <6,7,0,4> + 2725532578U, // <0,4,6,u>: Cost 3 vsldoi8 <6,u,0,4>, <6,u,0,4> + 3383371465U, // <0,4,7,0>: Cost 4 vmrglw <4,6,0,7>, <2,3,4,0> + 3800601668U, // <0,4,7,1>: Cost 4 vsldoi8 <7,1,0,4>, <7,1,0,4> + 3775386826U, // <0,4,7,2>: Cost 5 vsldoi8 <2,u,0,4>, <7,2,6,3> + 3801928934U, // <0,4,7,3>: Cost 4 vsldoi8 <7,3,0,4>, <7,3,0,4> + 3721202998U, // <0,4,7,4>: Cost 4 vsldoi4 <5,0,4,7>, RHS + 2780368328U, // <0,4,7,5>: Cost 3 vsldoi12 <4,7,5,0>, <4,7,5,0> + 3383372686U, // <0,4,7,6>: Cost 5 vmrglw <4,6,0,7>, <4,0,4,6> + 3854110170U, // <0,4,7,7>: Cost 4 vsldoi12 <4,7,5,0>, <4,7,7,0> + 2780368328U, // <0,4,7,u>: Cost 3 vsldoi12 <4,7,5,0>, <4,7,5,0> + 1146334098U, // <0,4,u,0>: Cost 2 vmrghw LHS, <4,0,5,1> + 2220076002U, // <0,4,u,1>: Cost 3 vmrghw LHS, <4,1,5,0> + 2220076085U, // <0,4,u,2>: Cost 3 vmrghw LHS, <4,2,5,2> + 2635524279U, // <0,4,u,3>: Cost 3 vsldoi4 <3,0,4,u>, <3,0,4,u> + 1146334416U, // <0,4,u,4>: Cost 2 vmrghw LHS, <4,4,4,4> + 72592694U, // <0,4,u,5>: Cost 1 vmrghw LHS, RHS + 1685245481U, // <0,4,u,6>: Cost 2 vsldoi12 <1,2,3,0>, RHS + 2659415067U, // <0,4,u,7>: Cost 3 vsldoi4 <7,0,4,u>, <7,0,4,u> + 72592937U, // <0,4,u,u>: Cost 1 vmrghw LHS, RHS + 2281704337U, // <0,5,0,0>: Cost 3 vmrglw <0,0,0,0>, <4,0,5,0> + 2704965734U, // <0,5,0,1>: Cost 3 vsldoi8 <3,4,0,5>, LHS + 3778707666U, // <0,5,0,2>: Cost 4 vsldoi8 <3,4,0,5>, <0,2,5,3> + 3778707708U, // <0,5,0,3>: Cost 4 vsldoi8 <3,4,0,5>, <0,3,1,0> + 2687050057U, // <0,5,0,4>: Cost 3 vsldoi8 <0,4,0,5>, <0,4,0,5> + 2214596612U, // <0,5,0,5>: Cost 3 vmrghw <0,0,0,0>, <5,5,5,5> + 2785824372U, // <0,5,0,6>: Cost 3 vsldoi12 <5,6,7,0>, <5,0,6,1> + 3854110332U, // <0,5,0,7>: Cost 4 vsldoi12 <4,7,5,0>, <5,0,7,0> + 2704966301U, // <0,5,0,u>: Cost 3 vsldoi8 <3,4,0,5>, LHS + 1567768678U, // <0,5,1,0>: Cost 2 vsldoi4 <4,0,5,1>, LHS + 2312236570U, // <0,5,1,1>: Cost 3 vmrglw <5,1,0,1>, <4,u,5,1> + 2215431915U, // <0,5,1,2>: Cost 3 vmrghw LHS, <5,2,1,3> + 2641512598U, // <0,5,1,3>: Cost 3 vsldoi4 <4,0,5,1>, <3,0,1,2> + 1567771538U, // <0,5,1,4>: Cost 2 vsldoi4 <4,0,5,1>, <4,0,5,1> + 1141690372U, // <0,5,1,5>: Cost 2 vmrghw LHS, <5,5,5,5> + 1141690466U, // <0,5,1,6>: Cost 2 vmrghw LHS, <5,6,7,0> + 2641515514U, // <0,5,1,7>: Cost 3 vsldoi4 <4,0,5,1>, <7,0,1,2> + 1141690615U, // <0,5,1,u>: Cost 2 vmrghw LHS, <5,u,5,5> + 3772736973U, // <0,5,2,0>: Cost 4 vsldoi8 <2,4,0,5>, <2,0,3,0> + 3778709024U, // <0,5,2,1>: Cost 4 vsldoi8 <3,4,0,5>, <2,1,3,2> + 3778709096U, // <0,5,2,2>: Cost 4 vsldoi8 <3,4,0,5>, <2,2,2,2> + 3778709158U, // <0,5,2,3>: Cost 4 vsldoi8 <3,4,0,5>, <2,3,0,1> + 3772737275U, // <0,5,2,4>: Cost 4 vsldoi8 <2,4,0,5>, <2,4,0,5> + 3859566351U, // <0,5,2,5>: Cost 4 vsldoi12 <5,6,7,0>, <5,2,5,3> + 3778709434U, // <0,5,2,6>: Cost 4 vsldoi8 <3,4,0,5>, <2,6,3,7> + 3805251562U, // <0,5,2,7>: Cost 4 vsldoi8 <7,u,0,5>, <2,7,0,1> + 3775391807U, // <0,5,2,u>: Cost 4 vsldoi8 <2,u,0,5>, <2,u,0,5> + 2704967830U, // <0,5,3,0>: Cost 3 vsldoi8 <3,4,0,5>, <3,0,1,2> + 3776719073U, // <0,5,3,1>: Cost 4 vsldoi8 <3,1,0,5>, <3,1,0,5> + 3777382706U, // <0,5,3,2>: Cost 4 vsldoi8 <3,2,0,5>, <3,2,0,5> + 3778709887U, // <0,5,3,3>: Cost 4 vsldoi8 <3,4,0,5>, <3,3,0,1> + 2704968148U, // <0,5,3,4>: Cost 3 vsldoi8 <3,4,0,5>, <3,4,0,5> + 3857428317U, // <0,5,3,5>: Cost 4 vsldoi12 <5,3,5,0>, <5,3,5,0> + 3364096514U, // <0,5,3,6>: Cost 4 vmrglw <1,4,0,3>, <3,4,5,6> + 3780700871U, // <0,5,3,7>: Cost 4 vsldoi8 <3,7,0,5>, <3,7,0,5> + 2707622680U, // <0,5,3,u>: Cost 3 vsldoi8 <3,u,0,5>, <3,u,0,5> + 2728856466U, // <0,5,4,0>: Cost 3 vsldoi8 <7,4,0,5>, <4,0,5,1> + 3697361674U, // <0,5,4,1>: Cost 4 vsldoi4 <1,0,5,4>, <1,0,5,4> + 3697362601U, // <0,5,4,2>: Cost 4 vsldoi4 <1,0,5,4>, <2,3,0,4> + 3364766635U, // <0,5,4,3>: Cost 4 vmrglw <1,5,0,4>, <1,2,5,3> + 2217365428U, // <0,5,4,4>: Cost 3 vmrghw <0,4,1,5>, <5,4,5,6> + 2704969014U, // <0,5,4,5>: Cost 3 vsldoi8 <3,4,0,5>, RHS + 2785824700U, // <0,5,4,6>: Cost 3 vsldoi12 <5,6,7,0>, <5,4,6,5> + 3364766963U, // <0,5,4,7>: Cost 4 vmrglw <1,5,0,4>, <1,6,5,7> + 2704969257U, // <0,5,4,u>: Cost 3 vsldoi8 <3,4,0,5>, RHS + 3846148050U, // <0,5,5,0>: Cost 4 vsldoi12 <3,4,5,0>, <5,5,0,0> + 2326203282U, // <0,5,5,1>: Cost 3 vmrglw <7,4,0,5>, <4,0,5,1> + 3291746027U, // <0,5,5,2>: Cost 4 vmrghw <0,5,1,2>, <5,2,1,3> + 3376054482U, // <0,5,5,3>: Cost 4 vmrglw <3,4,0,5>, <0,2,5,3> + 3790655366U, // <0,5,5,4>: Cost 4 vsldoi8 <5,4,0,5>, <5,4,0,5> + 2785824772U, // <0,5,5,5>: Cost 3 vsldoi12 <5,6,7,0>, <5,5,5,5> + 2724876386U, // <0,5,5,6>: Cost 3 vsldoi8 <6,7,0,5>, <5,6,7,0> + 3858903057U, // <0,5,5,7>: Cost 4 vsldoi12 <5,5,7,0>, <5,5,7,0> + 2736820484U, // <0,5,5,u>: Cost 3 vsldoi8 , <5,u,7,0> + 2659467366U, // <0,5,6,0>: Cost 3 vsldoi4 <7,0,5,6>, LHS + 3859566643U, // <0,5,6,1>: Cost 4 vsldoi12 <5,6,7,0>, <5,6,1,7> + 3798618618U, // <0,5,6,2>: Cost 4 vsldoi8 <6,7,0,5>, <6,2,7,3> + 3852857410U, // <0,5,6,3>: Cost 4 vsldoi12 <4,5,6,0>, <5,6,3,4> + 2659470646U, // <0,5,6,4>: Cost 3 vsldoi4 <7,0,5,6>, RHS + 2659471458U, // <0,5,6,5>: Cost 3 vsldoi4 <7,0,5,6>, <5,6,7,0> + 3832729696U, // <0,5,6,6>: Cost 4 vsldoi12 <1,2,3,0>, <5,6,6,7> + 1712083042U, // <0,5,6,7>: Cost 2 vsldoi12 <5,6,7,0>, <5,6,7,0> + 1712156779U, // <0,5,6,u>: Cost 2 vsldoi12 <5,6,u,0>, <5,6,u,0> + 2731512826U, // <0,5,7,0>: Cost 3 vsldoi8 <7,u,0,5>, <7,0,1,2> + 3859566717U, // <0,5,7,1>: Cost 4 vsldoi12 <5,6,7,0>, <5,7,1,0> + 3798619284U, // <0,5,7,2>: Cost 4 vsldoi8 <6,7,0,5>, <7,2,0,3> + 3778712803U, // <0,5,7,3>: Cost 4 vsldoi8 <3,4,0,5>, <7,3,0,1> + 2728858936U, // <0,5,7,4>: Cost 3 vsldoi8 <7,4,0,5>, <7,4,0,5> + 3859566753U, // <0,5,7,5>: Cost 4 vsldoi12 <5,6,7,0>, <5,7,5,0> + 3377398135U, // <0,5,7,6>: Cost 4 vmrglw <3,6,0,7>, <0,4,5,6> + 3798619686U, // <0,5,7,7>: Cost 4 vsldoi8 <6,7,0,5>, <7,7,0,0> + 2731513468U, // <0,5,7,u>: Cost 3 vsldoi8 <7,u,0,5>, <7,u,0,5> + 1567826022U, // <0,5,u,0>: Cost 2 vsldoi4 <4,0,5,u>, LHS + 2704971566U, // <0,5,u,1>: Cost 3 vsldoi8 <3,4,0,5>, LHS + 2220076779U, // <0,5,u,2>: Cost 3 vmrghw LHS, <5,2,1,3> + 2641569942U, // <0,5,u,3>: Cost 3 vsldoi4 <4,0,5,u>, <3,0,1,2> + 1567828889U, // <0,5,u,4>: Cost 2 vsldoi4 <4,0,5,u>, <4,0,5,u> + 1146335236U, // <0,5,u,5>: Cost 2 vmrghw LHS, <5,5,5,5> + 1146335330U, // <0,5,u,6>: Cost 2 vmrghw LHS, <5,6,7,0> + 1713410308U, // <0,5,u,7>: Cost 2 vsldoi12 <5,u,7,0>, <5,u,7,0> + 1713484045U, // <0,5,u,u>: Cost 2 vsldoi12 <5,u,u,0>, <5,u,u,0> + 2214596949U, // <0,6,0,0>: Cost 3 vmrghw <0,0,0,0>, <6,0,7,0> + 2214678951U, // <0,6,0,1>: Cost 3 vmrghw <0,0,1,1>, <6,1,7,1> + 2214597114U, // <0,6,0,2>: Cost 3 vmrghw <0,0,0,0>, <6,2,7,3> + 3852857653U, // <0,6,0,3>: Cost 4 vsldoi12 <4,5,6,0>, <6,0,3,4> + 3832729919U, // <0,6,0,4>: Cost 4 vsldoi12 <1,2,3,0>, <6,0,4,5> + 3721293427U, // <0,6,0,5>: Cost 4 vsldoi4 <5,0,6,0>, <5,0,6,0> + 2214597432U, // <0,6,0,6>: Cost 3 vmrghw <0,0,0,0>, <6,6,6,6> + 1207962934U, // <0,6,0,7>: Cost 2 vmrglw <0,0,0,0>, RHS + 1207962935U, // <0,6,0,u>: Cost 2 vmrglw <0,0,0,0>, RHS + 2215432481U, // <0,6,1,0>: Cost 3 vmrghw LHS, <6,0,1,2> + 2215432615U, // <0,6,1,1>: Cost 3 vmrghw LHS, <6,1,7,1> + 1141690874U, // <0,6,1,2>: Cost 2 vmrghw LHS, <6,2,7,3> + 2215432754U, // <0,6,1,3>: Cost 3 vmrghw LHS, <6,3,4,5> + 2215432817U, // <0,6,1,4>: Cost 3 vmrghw LHS, <6,4,2,5> + 2215432939U, // <0,6,1,5>: Cost 3 vmrghw LHS, <6,5,7,1> + 1141691192U, // <0,6,1,6>: Cost 2 vmrghw LHS, <6,6,6,6> + 1221905718U, // <0,6,1,7>: Cost 2 vmrglw <2,3,0,1>, RHS + 1221905719U, // <0,6,1,u>: Cost 2 vmrglw <2,3,0,1>, RHS + 3852857787U, // <0,6,2,0>: Cost 4 vsldoi12 <4,5,6,0>, <6,2,0,3> + 3289764265U, // <0,6,2,1>: Cost 4 vmrghw <0,2,1,3>, <6,1,7,3> + 3289690618U, // <0,6,2,2>: Cost 4 vmrghw <0,2,0,3>, <6,2,7,3> + 3862589907U, // <0,6,2,3>: Cost 4 vsldoi12 <6,2,3,0>, <6,2,3,0> + 3733253430U, // <0,6,2,4>: Cost 4 vsldoi4 <7,0,6,2>, RHS + 3733254242U, // <0,6,2,5>: Cost 4 vsldoi4 <7,0,6,2>, <5,6,7,0> + 3777390522U, // <0,6,2,6>: Cost 4 vsldoi8 <3,2,0,6>, <2,6,3,7> + 2785825274U, // <0,6,2,7>: Cost 3 vsldoi12 <5,6,7,0>, <6,2,7,3> + 2785825283U, // <0,6,2,u>: Cost 3 vsldoi12 <5,6,7,0>, <6,2,u,3> + 3777390742U, // <0,6,3,0>: Cost 4 vsldoi8 <3,2,0,6>, <3,0,1,2> + 3863106066U, // <0,6,3,1>: Cost 4 vsldoi12 <6,3,1,0>, <6,3,1,0> + 3777390899U, // <0,6,3,2>: Cost 4 vsldoi8 <3,2,0,6>, <3,2,0,6> + 3290436146U, // <0,6,3,3>: Cost 4 vmrghw <0,3,1,4>, <6,3,4,5> + 3779381762U, // <0,6,3,4>: Cost 4 vsldoi8 <3,5,0,6>, <3,4,5,6> + 3779381798U, // <0,6,3,5>: Cost 4 vsldoi8 <3,5,0,6>, <3,5,0,6> + 3733262920U, // <0,6,3,6>: Cost 4 vsldoi4 <7,0,6,3>, <6,3,7,0> + 2300972342U, // <0,6,3,7>: Cost 3 vmrglw <3,2,0,3>, RHS + 2300972343U, // <0,6,3,u>: Cost 3 vmrglw <3,2,0,3>, RHS + 3802606482U, // <0,6,4,0>: Cost 4 vsldoi8 <7,4,0,6>, <4,0,5,1> + 2217365931U, // <0,6,4,1>: Cost 3 vmrghw <0,4,1,5>, <6,1,7,5> + 2217366010U, // <0,6,4,2>: Cost 3 vmrghw <0,4,1,5>, <6,2,7,3> + 3291107890U, // <0,6,4,3>: Cost 4 vmrghw <0,4,1,5>, <6,3,4,5> + 3291099805U, // <0,6,4,4>: Cost 4 vmrghw <0,4,1,4>, <6,4,7,4> + 3777391926U, // <0,6,4,5>: Cost 4 vsldoi8 <3,2,0,6>, RHS + 2217366328U, // <0,6,4,6>: Cost 3 vmrghw <0,4,1,5>, <6,6,6,6> + 2291027254U, // <0,6,4,7>: Cost 3 vmrglw <1,5,0,4>, RHS + 2291027255U, // <0,6,4,u>: Cost 3 vmrglw <1,5,0,4>, RHS + 3852858033U, // <0,6,5,0>: Cost 4 vsldoi12 <4,5,6,0>, <6,5,0,6> + 3395964532U, // <0,6,5,1>: Cost 4 vmrglw <6,7,0,5>, <5,0,6,1> + 3864507069U, // <0,6,5,2>: Cost 4 vsldoi12 <6,5,2,0>, <6,5,2,0> + 3376056678U, // <0,6,5,3>: Cost 5 vmrglw <3,4,0,5>, <3,2,6,3> + 3721334070U, // <0,6,5,4>: Cost 4 vsldoi4 <5,0,6,5>, RHS + 3395964860U, // <0,6,5,5>: Cost 4 vmrglw <6,7,0,5>, <5,4,6,5> + 3864802017U, // <0,6,5,6>: Cost 4 vsldoi12 <6,5,6,0>, <6,5,6,0> + 2302315830U, // <0,6,5,7>: Cost 3 vmrglw <3,4,0,5>, RHS + 2302315831U, // <0,6,5,u>: Cost 3 vmrglw <3,4,0,5>, RHS + 3852858108U, // <0,6,6,0>: Cost 4 vsldoi12 <4,5,6,0>, <6,6,0,0> + 3398624745U, // <0,6,6,1>: Cost 4 vmrglw <7,2,0,6>, <2,0,6,1> + 2218668538U, // <0,6,6,2>: Cost 3 vmrghw <0,6,1,2>, <6,2,7,3> + 3292418610U, // <0,6,6,3>: Cost 4 vmrghw <0,6,1,3>, <6,3,4,5> + 3733286198U, // <0,6,6,4>: Cost 4 vsldoi4 <7,0,6,6>, RHS + 3797299889U, // <0,6,6,5>: Cost 4 vsldoi8 <6,5,0,6>, <6,5,0,6> + 2785825592U, // <0,6,6,6>: Cost 3 vsldoi12 <5,6,7,0>, <6,6,6,6> + 2785825602U, // <0,6,6,7>: Cost 3 vsldoi12 <5,6,7,0>, <6,6,7,7> + 2785825611U, // <0,6,6,u>: Cost 3 vsldoi12 <5,6,7,0>, <6,6,u,7> + 2785825614U, // <0,6,7,0>: Cost 3 vsldoi12 <5,6,7,0>, <6,7,0,1> + 2758988632U, // <0,6,7,1>: Cost 3 vsldoi12 <1,2,3,0>, <6,7,1,2> + 3377400084U, // <0,6,7,2>: Cost 4 vmrglw <3,6,0,7>, <3,1,6,2> + 2792166248U, // <0,6,7,3>: Cost 3 vsldoi12 <6,7,3,0>, <6,7,3,0> + 2785825654U, // <0,6,7,4>: Cost 3 vsldoi12 <5,6,7,0>, <6,7,4,5> + 2785825664U, // <0,6,7,5>: Cost 3 vsldoi12 <5,6,7,0>, <6,7,5,6> + 3859567493U, // <0,6,7,6>: Cost 4 vsldoi12 <5,6,7,0>, <6,7,6,2> + 2303659318U, // <0,6,7,7>: Cost 3 vmrglw <3,6,0,7>, RHS + 2303659319U, // <0,6,7,u>: Cost 3 vmrglw <3,6,0,7>, RHS + 2785825695U, // <0,6,u,0>: Cost 3 vsldoi12 <5,6,7,0>, <6,u,0,1> + 2220077479U, // <0,6,u,1>: Cost 3 vmrghw LHS, <6,1,7,1> + 1146335738U, // <0,6,u,2>: Cost 2 vmrghw LHS, <6,2,7,3> + 2792829881U, // <0,6,u,3>: Cost 3 vsldoi12 <6,u,3,0>, <6,u,3,0> + 2785825735U, // <0,6,u,4>: Cost 3 vsldoi12 <5,6,7,0>, <6,u,4,5> + 2785825664U, // <0,6,u,5>: Cost 3 vsldoi12 <5,6,7,0>, <6,7,5,6> + 1146336056U, // <0,6,u,6>: Cost 2 vmrghw LHS, <6,6,6,6> + 1221963062U, // <0,6,u,7>: Cost 2 vmrglw <2,3,0,u>, RHS + 1221963063U, // <0,6,u,u>: Cost 2 vmrglw <2,3,0,u>, RHS + 2653593600U, // <0,7,0,0>: Cost 3 vsldoi4 <6,0,7,0>, <0,0,0,0> + 2706309222U, // <0,7,0,1>: Cost 3 vsldoi8 <3,6,0,7>, LHS + 3709421498U, // <0,7,0,2>: Cost 4 vsldoi4 <3,0,7,0>, <2,6,3,7> + 2281705978U, // <0,7,0,3>: Cost 3 vmrglw <0,0,0,0>, <6,2,7,3> + 2785825816U, // <0,7,0,4>: Cost 3 vsldoi12 <5,6,7,0>, <7,0,4,5> + 2785825826U, // <0,7,0,5>: Cost 3 vsldoi12 <5,6,7,0>, <7,0,5,6> + 2653598037U, // <0,7,0,6>: Cost 3 vsldoi4 <6,0,7,0>, <6,0,7,0> + 2214598252U, // <0,7,0,7>: Cost 3 vmrghw <0,0,0,0>, <7,7,7,7> + 2706309789U, // <0,7,0,u>: Cost 3 vsldoi8 <3,6,0,7>, LHS + 1141691386U, // <0,7,1,0>: Cost 2 vmrghw LHS, <7,0,1,2> + 2215433290U, // <0,7,1,1>: Cost 3 vmrghw LHS, <7,1,1,1> + 2706310038U, // <0,7,1,2>: Cost 3 vsldoi8 <3,6,0,7>, <1,2,3,0> + 2322190842U, // <0,7,1,3>: Cost 3 vmrglw <6,7,0,1>, <6,2,7,3> + 1141691750U, // <0,7,1,4>: Cost 2 vmrghw LHS, <7,4,5,6> + 2215433654U, // <0,7,1,5>: Cost 3 vmrghw LHS, <7,5,5,5> + 2653606230U, // <0,7,1,6>: Cost 3 vsldoi4 <6,0,7,1>, <6,0,7,1> + 1141692012U, // <0,7,1,7>: Cost 2 vmrghw LHS, <7,7,7,7> + 1141692034U, // <0,7,1,u>: Cost 2 vmrghw LHS, <7,u,1,2> + 2785825940U, // <0,7,2,0>: Cost 3 vsldoi12 <5,6,7,0>, <7,2,0,3> + 3768108576U, // <0,7,2,1>: Cost 5 vsldoi8 <1,6,0,7>, <2,1,3,2> + 3780052584U, // <0,7,2,2>: Cost 4 vsldoi8 <3,6,0,7>, <2,2,2,2> + 2794820780U, // <0,7,2,3>: Cost 3 vsldoi12 <7,2,3,0>, <7,2,3,0> + 3859641528U, // <0,7,2,4>: Cost 4 vsldoi12 <5,6,u,0>, <7,2,4,3> + 3733327970U, // <0,7,2,5>: Cost 4 vsldoi4 <7,0,7,2>, <5,6,7,0> + 3778062266U, // <0,7,2,6>: Cost 4 vsldoi8 <3,3,0,7>, <2,6,3,7> + 3733328944U, // <0,7,2,7>: Cost 4 vsldoi4 <7,0,7,2>, <7,0,7,2> + 2795189465U, // <0,7,2,u>: Cost 3 vsldoi12 <7,2,u,0>, <7,2,u,0> + 2324861026U, // <0,7,3,0>: Cost 3 vmrglw <7,2,0,3>, <5,6,7,0> + 3780053233U, // <0,7,3,1>: Cost 4 vsldoi8 <3,6,0,7>, <3,1,2,3> + 3780053296U, // <0,7,3,2>: Cost 4 vsldoi8 <3,6,0,7>, <3,2,0,3> + 3778062725U, // <0,7,3,3>: Cost 4 vsldoi8 <3,3,0,7>, <3,3,0,7> + 3780053506U, // <0,7,3,4>: Cost 4 vsldoi8 <3,6,0,7>, <3,4,5,6> + 3803941469U, // <0,7,3,5>: Cost 4 vsldoi8 <7,6,0,7>, <3,5,6,7> + 2706311800U, // <0,7,3,6>: Cost 3 vsldoi8 <3,6,0,7>, <3,6,0,7> + 3398603586U, // <0,7,3,7>: Cost 4 vmrglw <7,2,0,3>, <6,6,7,7> + 2707639066U, // <0,7,3,u>: Cost 3 vsldoi8 <3,u,0,7>, <3,u,0,7> + 2217366522U, // <0,7,4,0>: Cost 3 vmrghw <0,4,1,5>, <7,0,1,2> + 3727369110U, // <0,7,4,1>: Cost 4 vsldoi4 <6,0,7,4>, <1,2,3,0> + 3291108500U, // <0,7,4,2>: Cost 4 vmrghw <0,4,1,5>, <7,2,0,3> + 3727370872U, // <0,7,4,3>: Cost 4 vsldoi4 <6,0,7,4>, <3,6,0,7> + 2217366886U, // <0,7,4,4>: Cost 3 vmrghw <0,4,1,5>, <7,4,5,6> + 2706312502U, // <0,7,4,5>: Cost 3 vsldoi8 <3,6,0,7>, RHS + 3786026321U, // <0,7,4,6>: Cost 4 vsldoi8 <4,6,0,7>, <4,6,0,7> + 2217367148U, // <0,7,4,7>: Cost 3 vmrghw <0,4,1,5>, <7,7,7,7> + 2706312745U, // <0,7,4,u>: Cost 3 vsldoi8 <3,6,0,7>, RHS + 2322223202U, // <0,7,5,0>: Cost 3 vmrglw <6,7,0,5>, <5,6,7,0> + 3399946987U, // <0,7,5,1>: Cost 4 vmrglw <7,4,0,5>, <6,5,7,1> + 3291780244U, // <0,7,5,2>: Cost 4 vmrghw <0,5,1,6>, <7,2,0,3> + 3727378582U, // <0,7,5,3>: Cost 4 vsldoi4 <6,0,7,5>, <3,0,1,2> + 3727379766U, // <0,7,5,4>: Cost 4 vsldoi4 <6,0,7,5>, RHS + 3859568054U, // <0,7,5,5>: Cost 4 vsldoi12 <5,6,7,0>, <7,5,5,5> + 2785826241U, // <0,7,5,6>: Cost 3 vsldoi12 <5,6,7,0>, <7,5,6,7> + 3395965762U, // <0,7,5,7>: Cost 4 vmrglw <6,7,0,5>, <6,6,7,7> + 2787153363U, // <0,7,5,u>: Cost 3 vsldoi12 <5,u,7,0>, <7,5,u,7> + 2785826268U, // <0,7,6,0>: Cost 3 vsldoi12 <5,6,7,0>, <7,6,0,7> + 3780055420U, // <0,7,6,1>: Cost 5 vsldoi8 <3,6,0,7>, <6,1,2,3> + 3859568110U, // <0,7,6,2>: Cost 4 vsldoi12 <5,6,7,0>, <7,6,2,7> + 3874534903U, // <0,7,6,3>: Cost 4 vsldoi12 , <7,6,3,7> + 3859641856U, // <0,7,6,4>: Cost 4 vsldoi12 <5,6,u,0>, <7,6,4,7> + 3733360738U, // <0,7,6,5>: Cost 4 vsldoi4 <7,0,7,6>, <5,6,7,0> + 3859568145U, // <0,7,6,6>: Cost 4 vsldoi12 <5,6,7,0>, <7,6,6,6> + 2797770260U, // <0,7,6,7>: Cost 3 vsldoi12 <7,6,7,0>, <7,6,7,0> + 2797843997U, // <0,7,6,u>: Cost 3 vsldoi12 <7,6,u,0>, <7,6,u,0> + 2785826342U, // <0,7,7,0>: Cost 3 vsldoi12 <5,6,7,0>, <7,7,0,0> + 3727393686U, // <0,7,7,1>: Cost 4 vsldoi4 <6,0,7,7>, <1,2,3,0> + 3868563003U, // <0,7,7,2>: Cost 4 vsldoi12 <7,2,3,0>, <7,7,2,3> + 3377397988U, // <0,7,7,3>: Cost 4 vmrglw <3,6,0,7>, <0,2,7,3> + 2219349350U, // <0,7,7,4>: Cost 3 vmrghw <0,7,1,4>, <7,4,5,6> + 3859568217U, // <0,7,7,5>: Cost 4 vsldoi12 <5,6,7,0>, <7,7,5,6> + 2730202588U, // <0,7,7,6>: Cost 3 vsldoi8 <7,6,0,7>, <7,6,0,7> + 2785826412U, // <0,7,7,7>: Cost 3 vsldoi12 <5,6,7,0>, <7,7,7,7> + 2731529854U, // <0,7,7,u>: Cost 3 vsldoi8 <7,u,0,7>, <7,u,0,7> + 1146336250U, // <0,7,u,0>: Cost 2 vmrghw LHS, <7,0,1,2> + 2706315054U, // <0,7,u,1>: Cost 3 vsldoi8 <3,6,0,7>, LHS + 2653660845U, // <0,7,u,2>: Cost 3 vsldoi4 <6,0,7,u>, <2,3,0,u> + 2322248186U, // <0,7,u,3>: Cost 3 vmrglw <6,7,0,u>, <6,2,7,3> + 1146336614U, // <0,7,u,4>: Cost 2 vmrghw LHS, <7,4,5,6> + 2706315418U, // <0,7,u,5>: Cost 3 vsldoi8 <3,6,0,7>, RHS + 2653663581U, // <0,7,u,6>: Cost 3 vsldoi4 <6,0,7,u>, <6,0,7,u> + 1146336876U, // <0,7,u,7>: Cost 2 vmrghw LHS, <7,7,7,7> + 1146336898U, // <0,7,u,u>: Cost 2 vmrghw LHS, <7,u,1,2> + 202162278U, // <0,u,0,0>: Cost 1 vspltisw0 LHS + 1624612966U, // <0,u,0,1>: Cost 2 vsldoi8 <2,3,0,u>, LHS + 2629780986U, // <0,u,0,2>: Cost 3 vsldoi4 <2,0,u,0>, <2,0,u,0> + 1207959708U, // <0,u,0,3>: Cost 2 vmrglw <0,0,0,0>, LHS + 1544097078U, // <0,u,0,4>: Cost 2 vsldoi4 <0,0,u,0>, RHS + 1140856986U, // <0,u,0,5>: Cost 2 vmrghw <0,0,0,0>, RHS + 2698355253U, // <0,u,0,6>: Cost 3 vsldoi8 <2,3,0,u>, <0,6,u,7> + 1207962952U, // <0,u,0,7>: Cost 2 vmrglw <0,0,0,0>, RHS + 202162278U, // <0,u,0,u>: Cost 1 vspltisw0 LHS + 1142134483U, // <0,u,1,0>: Cost 2 vmrghw LHS, + 67950382U, // <0,u,1,1>: Cost 1 vmrghw LHS, LHS + 1142175624U, // <0,u,1,2>: Cost 2 vmrghw LHS, + 1142175676U, // <0,u,1,3>: Cost 2 vmrghw LHS, + 1142134847U, // <0,u,1,4>: Cost 2 vmrghw LHS, + 67950746U, // <0,u,1,5>: Cost 1 vmrghw LHS, RHS + 1142175952U, // <0,u,1,6>: Cost 2 vmrghw LHS, + 1221905736U, // <0,u,1,7>: Cost 2 vmrglw <2,3,0,1>, RHS + 67950949U, // <0,u,1,u>: Cost 1 vmrghw LHS, LHS + 1562026086U, // <0,u,2,0>: Cost 2 vsldoi4 <3,0,u,2>, LHS + 2216015662U, // <0,u,2,1>: Cost 3 vmrghw <0,2,1,2>, LHS + 2698356328U, // <0,u,2,2>: Cost 3 vsldoi8 <2,3,0,u>, <2,2,2,2> + 835584U, // <0,u,2,3>: Cost 0 copy LHS + 1562029366U, // <0,u,2,4>: Cost 2 vsldoi4 <3,0,u,2>, RHS + 2216016026U, // <0,u,2,5>: Cost 3 vmrghw <0,2,1,2>, RHS + 2698356666U, // <0,u,2,6>: Cost 3 vsldoi8 <2,3,0,u>, <2,6,3,7> + 1585919033U, // <0,u,2,7>: Cost 2 vsldoi4 <7,0,u,2>, <7,0,u,2> + 835584U, // <0,u,2,u>: Cost 0 copy LHS + 2758989756U, // <0,u,3,0>: Cost 3 vsldoi12 <1,2,3,0>, + 2216662830U, // <0,u,3,1>: Cost 3 vmrghw <0,3,1,0>, LHS + 2703665461U, // <0,u,3,2>: Cost 3 vsldoi8 <3,2,0,u>, <3,2,0,u> + 2758989782U, // <0,u,3,3>: Cost 3 vsldoi12 <1,2,3,0>, + 2758989796U, // <0,u,3,4>: Cost 3 vsldoi12 <1,2,3,0>, + 2216663194U, // <0,u,3,5>: Cost 3 vmrghw <0,3,1,0>, RHS + 2706319993U, // <0,u,3,6>: Cost 3 vsldoi8 <3,6,0,u>, <3,6,0,u> + 2300972360U, // <0,u,3,7>: Cost 3 vmrglw <3,2,0,3>, RHS + 2216663397U, // <0,u,3,u>: Cost 3 vmrghw <0,3,1,0>, LHS + 2217367251U, // <0,u,4,0>: Cost 3 vmrghw <0,4,1,5>, + 1143625518U, // <0,u,4,1>: Cost 2 vmrghw <0,4,1,5>, LHS + 2217367432U, // <0,u,4,2>: Cost 3 vmrghw <0,4,1,5>, + 2217367484U, // <0,u,4,3>: Cost 3 vmrghw <0,4,1,5>, + 1143619922U, // <0,u,4,4>: Cost 2 vmrghw <0,4,1,5>, <0,4,1,5> + 1143625882U, // <0,u,4,5>: Cost 2 vmrghw <0,4,1,5>, RHS + 2217367760U, // <0,u,4,6>: Cost 3 vmrghw <0,4,1,5>, + 2291027272U, // <0,u,4,7>: Cost 3 vmrglw <1,5,0,4>, RHS + 1143626085U, // <0,u,4,u>: Cost 2 vmrghw <0,4,1,5>, LHS + 2635792486U, // <0,u,5,0>: Cost 3 vsldoi4 <3,0,u,5>, LHS + 2635793302U, // <0,u,5,1>: Cost 3 vsldoi4 <3,0,u,5>, <1,2,3,0> + 2302314646U, // <0,u,5,2>: Cost 3 vmrglw <3,4,0,5>, <3,0,1,2> + 2635794648U, // <0,u,5,3>: Cost 3 vsldoi4 <3,0,u,5>, <3,0,u,5> + 2635795766U, // <0,u,5,4>: Cost 3 vsldoi4 <3,0,u,5>, RHS + 2717601754U, // <0,u,5,5>: Cost 3 vsldoi8 <5,5,0,u>, <5,5,0,u> + 1685248154U, // <0,u,5,6>: Cost 2 vsldoi12 <1,2,3,0>, RHS + 2302315848U, // <0,u,5,7>: Cost 3 vmrglw <3,4,0,5>, RHS + 1685248172U, // <0,u,5,u>: Cost 2 vsldoi12 <1,2,3,0>, RHS + 2759358645U, // <0,u,6,0>: Cost 3 vsldoi12 <1,2,u,0>, + 2218637102U, // <0,u,6,1>: Cost 3 vmrghw <0,6,0,7>, LHS + 2724901370U, // <0,u,6,2>: Cost 3 vsldoi8 <6,7,0,u>, <6,2,7,3> + 2758990032U, // <0,u,6,3>: Cost 3 vsldoi12 <1,2,3,0>, + 2659691830U, // <0,u,6,4>: Cost 3 vsldoi4 <7,0,u,6>, RHS + 2659471458U, // <0,u,6,5>: Cost 3 vsldoi4 <7,0,5,6>, <5,6,7,0> + 2724901688U, // <0,u,6,6>: Cost 3 vsldoi8 <6,7,0,u>, <6,6,6,6> + 1651159893U, // <0,u,6,7>: Cost 2 vsldoi8 <6,7,0,u>, <6,7,0,u> + 1651823526U, // <0,u,6,u>: Cost 2 vsldoi8 <6,u,0,u>, <6,u,0,u> + 2785827072U, // <0,u,7,0>: Cost 3 vsldoi12 <5,6,7,0>, + 2803964168U, // <0,u,7,1>: Cost 3 vsldoi12 , + 2727556249U, // <0,u,7,2>: Cost 3 vsldoi8 <7,2,0,u>, <7,2,0,u> + 2303656092U, // <0,u,7,3>: Cost 3 vmrglw <3,6,0,7>, LHS + 2785827112U, // <0,u,7,4>: Cost 3 vsldoi12 <5,6,7,0>, + 2785827122U, // <0,u,7,5>: Cost 3 vsldoi12 <5,6,7,0>, + 2730210781U, // <0,u,7,6>: Cost 3 vsldoi8 <7,6,0,u>, <7,6,0,u> + 2303659336U, // <0,u,7,7>: Cost 3 vmrglw <3,6,0,7>, RHS + 2303656097U, // <0,u,7,u>: Cost 3 vmrglw <3,6,0,7>, LHS + 202162278U, // <0,u,u,0>: Cost 1 vspltisw0 LHS + 72595246U, // <0,u,u,1>: Cost 1 vmrghw LHS, LHS + 1146337160U, // <0,u,u,2>: Cost 2 vmrghw LHS, + 835584U, // <0,u,u,3>: Cost 0 copy LHS + 1146337343U, // <0,u,u,4>: Cost 2 vmrghw LHS, + 72595610U, // <0,u,u,5>: Cost 1 vmrghw LHS, RHS + 1146337488U, // <0,u,u,6>: Cost 2 vmrghw LHS, + 1221963080U, // <0,u,u,7>: Cost 2 vmrglw <2,3,0,u>, RHS + 835584U, // <0,u,u,u>: Cost 0 copy LHS + 2756853760U, // <1,0,0,0>: Cost 3 vsldoi12 <0,u,1,1>, <0,0,0,0> + 1677803530U, // <1,0,0,1>: Cost 2 vsldoi12 <0,0,1,1>, <0,0,1,1> + 3759497387U, // <1,0,0,2>: Cost 4 vsldoi8 <0,2,1,0>, <0,2,1,0> + 2686419196U, // <1,0,0,3>: Cost 3 vsldoi8 <0,3,1,0>, <0,3,1,0> + 2751766565U, // <1,0,0,4>: Cost 3 vsldoi12 <0,0,4,1>, <0,0,4,1> + 2687746462U, // <1,0,0,5>: Cost 3 vsldoi8 <0,5,1,0>, <0,5,1,0> + 3776086518U, // <1,0,0,6>: Cost 4 vsldoi8 <3,0,1,0>, <0,6,1,7> + 2689073728U, // <1,0,0,7>: Cost 3 vsldoi8 <0,7,1,0>, <0,7,1,0> + 1678319689U, // <1,0,0,u>: Cost 2 vsldoi12 <0,0,u,1>, <0,0,u,1> + 2287091712U, // <1,0,1,0>: Cost 3 vmrglw <0,u,1,1>, <0,0,0,0> + 1147568230U, // <1,0,1,1>: Cost 2 vmrghw <1,1,1,1>, LHS + 1683112038U, // <1,0,1,2>: Cost 2 vsldoi12 <0,u,1,1>, LHS + 3294970108U, // <1,0,1,3>: Cost 4 vmrghw <1,1,0,0>, <0,3,1,0> + 2623892790U, // <1,0,1,4>: Cost 3 vsldoi4 <1,1,0,1>, RHS + 2647781007U, // <1,0,1,5>: Cost 3 vsldoi4 <5,1,0,1>, <5,1,0,1> + 2791948430U, // <1,0,1,6>: Cost 3 vsldoi12 <6,7,0,1>, <0,1,6,7> + 3721524218U, // <1,0,1,7>: Cost 4 vsldoi4 <5,1,0,1>, <7,0,1,2> + 1683112092U, // <1,0,1,u>: Cost 2 vsldoi12 <0,u,1,1>, LHS + 2222112768U, // <1,0,2,0>: Cost 3 vmrghw <1,2,3,0>, <0,0,0,0> + 1148371046U, // <1,0,2,1>: Cost 2 vmrghw <1,2,3,0>, LHS + 3356862524U, // <1,0,2,2>: Cost 4 vmrglw <0,2,1,2>, <2,u,0,2> + 2702345894U, // <1,0,2,3>: Cost 3 vsldoi8 <3,0,1,0>, <2,3,0,1> + 2222113106U, // <1,0,2,4>: Cost 3 vmrghw <1,2,3,0>, <0,4,1,5> + 2299709908U, // <1,0,2,5>: Cost 3 vmrglw <3,0,1,2>, <3,4,0,5> + 3760162746U, // <1,0,2,6>: Cost 4 vsldoi8 <0,3,1,0>, <2,6,3,7> + 3369470584U, // <1,0,2,7>: Cost 4 vmrglw <2,3,1,2>, <3,6,0,7> + 1148371613U, // <1,0,2,u>: Cost 2 vmrghw <1,2,3,0>, LHS + 2686421142U, // <1,0,3,0>: Cost 3 vsldoi8 <0,3,1,0>, <3,0,1,2> + 2283128486U, // <1,0,3,1>: Cost 3 vmrglw <0,2,1,3>, <2,3,0,1> + 3296305326U, // <1,0,3,2>: Cost 4 vmrghw <1,3,0,1>, <0,2,1,3> + 3760163199U, // <1,0,3,3>: Cost 4 vsldoi8 <0,3,1,0>, <3,3,0,1> + 3760163330U, // <1,0,3,4>: Cost 4 vsldoi8 <0,3,1,0>, <3,4,5,6> + 3779406377U, // <1,0,3,5>: Cost 4 vsldoi8 <3,5,1,0>, <3,5,1,0> + 3865690416U, // <1,0,3,6>: Cost 4 vsldoi12 <6,7,0,1>, <0,3,6,7> + 3366824568U, // <1,0,3,7>: Cost 5 vmrglw <1,u,1,3>, <3,6,0,7> + 2707655452U, // <1,0,3,u>: Cost 3 vsldoi8 <3,u,1,0>, <3,u,1,0> + 2734861202U, // <1,0,4,0>: Cost 3 vsldoi8 , <4,0,5,1> + 2756854098U, // <1,0,4,1>: Cost 3 vsldoi12 <0,u,1,1>, <0,4,1,5> + 3830595931U, // <1,0,4,2>: Cost 5 vsldoi12 <0,u,1,1>, <0,4,2,5> + 3296968960U, // <1,0,4,3>: Cost 4 vmrghw <1,4,0,1>, <0,3,1,4> + 3830595949U, // <1,0,4,4>: Cost 4 vsldoi12 <0,u,1,1>, <0,4,4,5> + 2686422326U, // <1,0,4,5>: Cost 3 vsldoi8 <0,3,1,0>, RHS + 3297378806U, // <1,0,4,6>: Cost 5 vmrghw <1,4,5,6>, <0,6,1,7> + 3810594248U, // <1,0,4,7>: Cost 4 vsldoi8 , <4,7,5,0> + 2686422569U, // <1,0,4,u>: Cost 3 vsldoi8 <0,3,1,0>, RHS + 2284470272U, // <1,0,5,0>: Cost 3 vmrglw <0,4,1,5>, <0,0,0,0> + 2284471974U, // <1,0,5,1>: Cost 3 vmrglw <0,4,1,5>, <2,3,0,1> + 3809267435U, // <1,0,5,2>: Cost 4 vsldoi8 , <5,2,1,3> + 3297968384U, // <1,0,5,3>: Cost 4 vmrghw <1,5,4,6>, <0,3,1,4> + 2284471977U, // <1,0,5,4>: Cost 3 vmrglw <0,4,1,5>, <2,3,0,4> + 3721555603U, // <1,0,5,5>: Cost 4 vsldoi4 <5,1,0,5>, <5,1,0,5> + 3792679010U, // <1,0,5,6>: Cost 4 vsldoi8 <5,7,1,0>, <5,6,7,0> + 3792679037U, // <1,0,5,7>: Cost 4 vsldoi8 <5,7,1,0>, <5,7,1,0> + 2284471981U, // <1,0,5,u>: Cost 3 vmrglw <0,4,1,5>, <2,3,0,u> + 3356893184U, // <1,0,6,0>: Cost 4 vmrglw <0,2,1,6>, <0,0,0,0> + 2224676966U, // <1,0,6,1>: Cost 3 vmrghw <1,6,1,7>, LHS + 3298295985U, // <1,0,6,2>: Cost 4 vmrghw <1,6,0,1>, <0,2,1,6> + 3298345212U, // <1,0,6,3>: Cost 4 vmrghw <1,6,0,7>, <0,3,1,0> + 2224972114U, // <1,0,6,4>: Cost 3 vmrghw <1,6,5,7>, <0,4,1,5> + 3808604907U, // <1,0,6,5>: Cost 4 vsldoi8 , <6,5,7,1> + 3799978808U, // <1,0,6,6>: Cost 4 vsldoi8 <7,0,1,0>, <6,6,6,6> + 2726237006U, // <1,0,6,7>: Cost 3 vsldoi8 <7,0,1,0>, <6,7,0,1> + 2224677522U, // <1,0,6,u>: Cost 3 vmrghw <1,6,1,7>, <0,u,1,1> + 2726237176U, // <1,0,7,0>: Cost 3 vsldoi8 <7,0,1,0>, <7,0,1,0> + 2285815462U, // <1,0,7,1>: Cost 3 vmrglw <0,6,1,7>, <2,3,0,1> + 3805951193U, // <1,0,7,2>: Cost 4 vsldoi8 , <7,2,u,0> + 3807941859U, // <1,0,7,3>: Cost 4 vsldoi8 , <7,3,0,1> + 3799979366U, // <1,0,7,4>: Cost 4 vsldoi8 <7,0,1,0>, <7,4,5,6> + 3803297165U, // <1,0,7,5>: Cost 4 vsldoi8 <7,5,1,0>, <7,5,1,0> + 3799979540U, // <1,0,7,6>: Cost 4 vsldoi8 <7,0,1,0>, <7,6,7,0> + 3799979628U, // <1,0,7,7>: Cost 4 vsldoi8 <7,0,1,0>, <7,7,7,7> + 2731546240U, // <1,0,7,u>: Cost 3 vsldoi8 <7,u,1,0>, <7,u,1,0> + 2284494848U, // <1,0,u,0>: Cost 3 vmrglw <0,4,1,u>, <0,0,0,0> + 1683112594U, // <1,0,u,1>: Cost 2 vsldoi12 <0,u,1,1>, <0,u,1,1> + 1683112605U, // <1,0,u,2>: Cost 2 vsldoi12 <0,u,1,1>, LHS + 2734200772U, // <1,0,u,3>: Cost 3 vsldoi8 , + 2757075629U, // <1,0,u,4>: Cost 3 vsldoi12 <0,u,4,1>, <0,u,4,1> + 2686425242U, // <1,0,u,5>: Cost 3 vsldoi8 <0,3,1,0>, RHS + 2791948430U, // <1,0,u,6>: Cost 3 vsldoi12 <6,7,0,1>, <0,1,6,7> + 2736855304U, // <1,0,u,7>: Cost 3 vsldoi8 , + 1683112659U, // <1,0,u,u>: Cost 2 vsldoi12 <0,u,1,1>, LHS + 1610694666U, // <1,1,0,0>: Cost 2 vsldoi8 <0,0,1,1>, <0,0,1,1> + 1616003174U, // <1,1,0,1>: Cost 2 vsldoi8 <0,u,1,1>, LHS + 2283767958U, // <1,1,0,2>: Cost 3 vmrglw <0,3,1,0>, <3,0,1,2> + 3357507596U, // <1,1,0,3>: Cost 4 vmrglw <0,3,1,0>, <0,0,1,3> + 2689745234U, // <1,1,0,4>: Cost 3 vsldoi8 <0,u,1,1>, <0,4,1,5> + 3357507922U, // <1,1,0,5>: Cost 4 vmrglw <0,3,1,0>, <0,4,1,5> + 3294397647U, // <1,1,0,6>: Cost 4 vmrghw <1,0,1,2>, <1,6,1,7> + 3373433334U, // <1,1,0,7>: Cost 4 vmrglw <3,0,1,0>, <0,6,1,7> + 1616003730U, // <1,1,0,u>: Cost 2 vsldoi8 <0,u,1,1>, <0,u,1,1> + 1550221414U, // <1,1,1,0>: Cost 2 vsldoi4 <1,1,1,1>, LHS + 269271142U, // <1,1,1,1>: Cost 1 vspltisw1 LHS + 2287093910U, // <1,1,1,2>: Cost 3 vmrglw <0,u,1,1>, <3,0,1,2> + 2287092615U, // <1,1,1,3>: Cost 3 vmrglw <0,u,1,1>, <1,2,1,3> + 1550224694U, // <1,1,1,4>: Cost 2 vsldoi4 <1,1,1,1>, RHS + 2287092050U, // <1,1,1,5>: Cost 3 vmrglw <0,u,1,1>, <0,4,1,5> + 2689746127U, // <1,1,1,6>: Cost 3 vsldoi8 <0,u,1,1>, <1,6,1,7> + 2659800138U, // <1,1,1,7>: Cost 3 vsldoi4 <7,1,1,1>, <7,1,1,1> + 269271142U, // <1,1,1,u>: Cost 1 vspltisw1 LHS + 2222113516U, // <1,1,2,0>: Cost 3 vmrghw <1,2,3,0>, <1,0,2,1> + 2756854663U, // <1,1,2,1>: Cost 3 vsldoi12 <0,u,1,1>, <1,2,1,3> + 1148371862U, // <1,1,2,2>: Cost 2 vmrghw <1,2,3,0>, <1,2,3,0> + 2689746598U, // <1,1,2,3>: Cost 3 vsldoi8 <0,u,1,1>, <2,3,0,1> + 2618002742U, // <1,1,2,4>: Cost 3 vsldoi4 <0,1,1,2>, RHS + 2299707730U, // <1,1,2,5>: Cost 3 vmrglw <3,0,1,2>, <0,4,1,5> + 2689746874U, // <1,1,2,6>: Cost 3 vsldoi8 <0,u,1,1>, <2,6,3,7> + 3361506511U, // <1,1,2,7>: Cost 4 vmrglw <1,0,1,2>, <1,6,1,7> + 1148371862U, // <1,1,2,u>: Cost 2 vmrghw <1,2,3,0>, <1,2,3,0> + 2689747094U, // <1,1,3,0>: Cost 3 vsldoi8 <0,u,1,1>, <3,0,1,2> + 2691074278U, // <1,1,3,1>: Cost 3 vsldoi8 <1,1,1,1>, <3,1,1,1> + 3356870806U, // <1,1,3,2>: Cost 4 vmrglw <0,2,1,3>, <3,0,1,2> + 2283126958U, // <1,1,3,3>: Cost 3 vmrglw <0,2,1,3>, <0,2,1,3> + 2689747458U, // <1,1,3,4>: Cost 3 vsldoi8 <0,u,1,1>, <3,4,5,6> + 3356868946U, // <1,1,3,5>: Cost 4 vmrglw <0,2,1,3>, <0,4,1,5> + 3811265144U, // <1,1,3,6>: Cost 4 vsldoi8 , <3,6,0,7> + 3362841807U, // <1,1,3,7>: Cost 4 vmrglw <1,2,1,3>, <1,6,1,7> + 2689747742U, // <1,1,3,u>: Cost 3 vsldoi8 <0,u,1,1>, <3,u,1,2> + 2623987814U, // <1,1,4,0>: Cost 3 vsldoi4 <1,1,1,4>, LHS + 2758181931U, // <1,1,4,1>: Cost 3 vsldoi12 <1,1,1,1>, <1,4,1,5> + 2223408022U, // <1,1,4,2>: Cost 3 vmrghw <1,4,2,5>, <1,2,3,0> + 3697731734U, // <1,1,4,3>: Cost 4 vsldoi4 <1,1,1,4>, <3,0,1,2> + 2283798784U, // <1,1,4,4>: Cost 3 vmrglw <0,3,1,4>, <0,3,1,4> + 1616006454U, // <1,1,4,5>: Cost 2 vsldoi8 <0,u,1,1>, RHS + 3297379535U, // <1,1,4,6>: Cost 4 vmrghw <1,4,5,6>, <1,6,1,7> + 3373466102U, // <1,1,4,7>: Cost 4 vmrglw <3,0,1,4>, <0,6,1,7> + 1616006697U, // <1,1,4,u>: Cost 2 vsldoi8 <0,u,1,1>, RHS + 2760762479U, // <1,1,5,0>: Cost 3 vsldoi12 <1,5,0,1>, <1,5,0,1> + 2284470282U, // <1,1,5,1>: Cost 3 vmrglw <0,4,1,5>, <0,0,1,1> + 2284472470U, // <1,1,5,2>: Cost 3 vmrglw <0,4,1,5>, <3,0,1,2> + 3358212270U, // <1,1,5,3>: Cost 4 vmrglw <0,4,1,5>, <0,2,1,3> + 2284470285U, // <1,1,5,4>: Cost 3 vmrglw <0,4,1,5>, <0,0,1,4> + 1210728786U, // <1,1,5,5>: Cost 2 vmrglw <0,4,1,5>, <0,4,1,5> + 2737524834U, // <1,1,5,6>: Cost 3 vsldoi8 , <5,6,7,0> + 3360867535U, // <1,1,5,7>: Cost 4 vmrglw <0,u,1,5>, <1,6,1,7> + 1210728786U, // <1,1,5,u>: Cost 2 vmrglw <0,4,1,5>, <0,4,1,5> + 3697746022U, // <1,1,6,0>: Cost 4 vsldoi4 <1,1,1,6>, LHS + 2756854991U, // <1,1,6,1>: Cost 3 vsldoi12 <0,u,1,1>, <1,6,1,7> + 2737525242U, // <1,1,6,2>: Cost 3 vsldoi8 , <6,2,7,3> + 3839149281U, // <1,1,6,3>: Cost 4 vsldoi12 <2,3,0,1>, <1,6,3,7> + 3697749302U, // <1,1,6,4>: Cost 4 vsldoi4 <1,1,1,6>, RHS + 3356893522U, // <1,1,6,5>: Cost 4 vmrglw <0,2,1,6>, <0,4,1,5> + 2283151537U, // <1,1,6,6>: Cost 3 vmrglw <0,2,1,6>, <0,2,1,6> + 2791949566U, // <1,1,6,7>: Cost 3 vsldoi12 <6,7,0,1>, <1,6,7,0> + 2792613127U, // <1,1,6,u>: Cost 3 vsldoi12 <6,u,0,1>, <1,6,u,0> + 2737525754U, // <1,1,7,0>: Cost 3 vsldoi8 , <7,0,1,2> + 2291786386U, // <1,1,7,1>: Cost 3 vmrglw <1,6,1,7>, <0,u,1,1> + 3365528292U, // <1,1,7,2>: Cost 4 vmrglw <1,6,1,7>, <1,0,1,2> + 3365528455U, // <1,1,7,3>: Cost 4 vmrglw <1,6,1,7>, <1,2,1,3> + 2737526118U, // <1,1,7,4>: Cost 3 vsldoi8 , <7,4,5,6> + 3365527890U, // <1,1,7,5>: Cost 4 vmrglw <1,6,1,7>, <0,4,1,5> + 3365528377U, // <1,1,7,6>: Cost 4 vmrglw <1,6,1,7>, <1,1,1,6> + 2291786959U, // <1,1,7,7>: Cost 3 vmrglw <1,6,1,7>, <1,6,1,7> + 2737526402U, // <1,1,7,u>: Cost 3 vsldoi8 , <7,u,1,2> + 1550221414U, // <1,1,u,0>: Cost 2 vsldoi4 <1,1,1,1>, LHS + 269271142U, // <1,1,u,1>: Cost 1 vspltisw1 LHS + 1148371862U, // <1,1,u,2>: Cost 2 vmrghw <1,2,3,0>, <1,2,3,0> + 2689750972U, // <1,1,u,3>: Cost 3 vsldoi8 <0,u,1,1>, + 1550224694U, // <1,1,u,4>: Cost 2 vsldoi4 <1,1,1,1>, RHS + 1616009370U, // <1,1,u,5>: Cost 2 vsldoi8 <0,u,1,1>, RHS + 2689751248U, // <1,1,u,6>: Cost 3 vsldoi8 <0,u,1,1>, + 2736863497U, // <1,1,u,7>: Cost 3 vsldoi8 , + 269271142U, // <1,1,u,u>: Cost 1 vspltisw1 LHS + 2702360576U, // <1,2,0,0>: Cost 3 vsldoi8 <3,0,1,2>, <0,0,0,0> + 1628618854U, // <1,2,0,1>: Cost 2 vsldoi8 <3,0,1,2>, LHS + 2685771949U, // <1,2,0,2>: Cost 3 vsldoi8 <0,2,1,2>, <0,2,1,2> + 2283765862U, // <1,2,0,3>: Cost 3 vmrglw <0,3,1,0>, LHS + 2702360914U, // <1,2,0,4>: Cost 3 vsldoi8 <3,0,1,2>, <0,4,1,5> + 3788046813U, // <1,2,0,5>: Cost 4 vsldoi8 <5,0,1,2>, <0,5,u,0> + 2688426481U, // <1,2,0,6>: Cost 3 vsldoi8 <0,6,1,2>, <0,6,1,2> + 2726249024U, // <1,2,0,7>: Cost 3 vsldoi8 <7,0,1,2>, <0,7,1,0> + 1628619421U, // <1,2,0,u>: Cost 2 vsldoi8 <3,0,1,2>, LHS + 2690417380U, // <1,2,1,0>: Cost 3 vsldoi8 <1,0,1,2>, <1,0,1,2> + 2702361396U, // <1,2,1,1>: Cost 3 vsldoi8 <3,0,1,2>, <1,1,1,1> + 2287093352U, // <1,2,1,2>: Cost 3 vmrglw <0,u,1,1>, <2,2,2,2> + 1213349990U, // <1,2,1,3>: Cost 2 vmrglw <0,u,1,1>, LHS + 3764159522U, // <1,2,1,4>: Cost 4 vsldoi8 <1,0,1,2>, <1,4,0,5> + 3295053672U, // <1,2,1,5>: Cost 4 vmrghw <1,1,1,1>, <2,5,3,6> + 2221311930U, // <1,2,1,6>: Cost 3 vmrghw <1,1,1,1>, <2,6,3,7> + 3799991593U, // <1,2,1,7>: Cost 4 vsldoi8 <7,0,1,2>, <1,7,2,7> + 1213349995U, // <1,2,1,u>: Cost 2 vmrglw <0,u,1,1>, LHS + 2624045158U, // <1,2,2,0>: Cost 3 vsldoi4 <1,1,2,2>, LHS + 2702362144U, // <1,2,2,1>: Cost 3 vsldoi8 <3,0,1,2>, <2,1,3,2> + 2283120232U, // <1,2,2,2>: Cost 3 vmrglw <0,2,1,2>, <2,2,2,2> + 1225965670U, // <1,2,2,3>: Cost 2 vmrglw <3,0,1,2>, LHS + 2624048438U, // <1,2,2,4>: Cost 3 vsldoi4 <1,1,2,2>, RHS + 3356860763U, // <1,2,2,5>: Cost 4 vmrglw <0,2,1,2>, <0,4,2,5> + 2222114746U, // <1,2,2,6>: Cost 3 vmrghw <1,2,3,0>, <2,6,3,7> + 2299708632U, // <1,2,2,7>: Cost 3 vmrglw <3,0,1,2>, <1,6,2,7> + 1225965675U, // <1,2,2,u>: Cost 2 vmrglw <3,0,1,2>, LHS + 470597734U, // <1,2,3,0>: Cost 1 vsldoi4 LHS, LHS + 1544340276U, // <1,2,3,1>: Cost 2 vsldoi4 LHS, <1,1,1,1> + 1544341096U, // <1,2,3,2>: Cost 2 vsldoi4 LHS, <2,2,2,2> + 1544341916U, // <1,2,3,3>: Cost 2 vsldoi4 LHS, <3,3,3,3> + 470601014U, // <1,2,3,4>: Cost 1 vsldoi4 LHS, RHS + 1592119300U, // <1,2,3,5>: Cost 2 vsldoi4 LHS, <5,5,5,5> + 1592119802U, // <1,2,3,6>: Cost 2 vsldoi4 LHS, <6,2,7,3> + 1592120314U, // <1,2,3,7>: Cost 2 vsldoi4 LHS, <7,0,1,2> + 470603566U, // <1,2,3,u>: Cost 1 vsldoi4 LHS, LHS + 2708335471U, // <1,2,4,0>: Cost 3 vsldoi8 <4,0,1,2>, <4,0,1,2> + 3838043908U, // <1,2,4,1>: Cost 4 vsldoi12 <2,1,3,1>, <2,4,1,5> + 3357541992U, // <1,2,4,2>: Cost 4 vmrglw <0,3,1,4>, <2,2,2,2> + 2283798630U, // <1,2,4,3>: Cost 3 vmrglw <0,3,1,4>, LHS + 2726251728U, // <1,2,4,4>: Cost 3 vsldoi8 <7,0,1,2>, <4,4,4,4> + 1628622134U, // <1,2,4,5>: Cost 2 vsldoi8 <3,0,1,2>, RHS + 3297077178U, // <1,2,4,6>: Cost 4 vmrghw <1,4,1,5>, <2,6,3,7> + 2726251976U, // <1,2,4,7>: Cost 3 vsldoi8 <7,0,1,2>, <4,7,5,0> + 1628622377U, // <1,2,4,u>: Cost 2 vsldoi8 <3,0,1,2>, RHS + 2714308168U, // <1,2,5,0>: Cost 3 vsldoi8 <5,0,1,2>, <5,0,1,2> + 3297633827U, // <1,2,5,1>: Cost 4 vmrghw <1,5,0,1>, <2,1,3,5> + 2284471912U, // <1,2,5,2>: Cost 3 vmrglw <0,4,1,5>, <2,2,2,2> + 1210728550U, // <1,2,5,3>: Cost 2 vmrglw <0,4,1,5>, LHS + 3776106420U, // <1,2,5,4>: Cost 4 vsldoi8 <3,0,1,2>, <5,4,5,6> + 2726252548U, // <1,2,5,5>: Cost 3 vsldoi8 <7,0,1,2>, <5,5,5,5> + 2726252642U, // <1,2,5,6>: Cost 3 vsldoi8 <7,0,1,2>, <5,6,7,0> + 3799994538U, // <1,2,5,7>: Cost 4 vsldoi8 <7,0,1,2>, <5,7,6,0> + 1210728555U, // <1,2,5,u>: Cost 2 vmrglw <0,4,1,5>, LHS + 2720280865U, // <1,2,6,0>: Cost 3 vsldoi8 <6,0,1,2>, <6,0,1,2> + 2702365096U, // <1,2,6,1>: Cost 3 vsldoi8 <3,0,1,2>, <6,1,7,2> + 2726253050U, // <1,2,6,2>: Cost 3 vsldoi8 <7,0,1,2>, <6,2,7,3> + 2283151462U, // <1,2,6,3>: Cost 3 vmrglw <0,2,1,6>, LHS + 3697823030U, // <1,2,6,4>: Cost 4 vsldoi4 <1,1,2,6>, RHS + 3298715497U, // <1,2,6,5>: Cost 4 vmrghw <1,6,5,7>, <2,5,3,7> + 2726253368U, // <1,2,6,6>: Cost 3 vsldoi8 <7,0,1,2>, <6,6,6,6> + 2724926296U, // <1,2,6,7>: Cost 3 vsldoi8 <6,7,1,2>, <6,7,1,2> + 2283151467U, // <1,2,6,u>: Cost 3 vmrglw <0,2,1,6>, LHS + 1652511738U, // <1,2,7,0>: Cost 2 vsldoi8 <7,0,1,2>, <7,0,1,2> + 3371500916U, // <1,2,7,1>: Cost 4 vmrglw <2,6,1,7>, <1,u,2,1> + 3365529192U, // <1,2,7,2>: Cost 4 vmrglw <1,6,1,7>, <2,2,2,2> + 2291785830U, // <1,2,7,3>: Cost 3 vmrglw <1,6,1,7>, LHS + 2726253926U, // <1,2,7,4>: Cost 3 vsldoi8 <7,0,1,2>, <7,4,5,6> + 3788051845U, // <1,2,7,5>: Cost 4 vsldoi8 <5,0,1,2>, <7,5,0,1> + 3794023894U, // <1,2,7,6>: Cost 4 vsldoi8 <6,0,1,2>, <7,6,0,1> + 2726254119U, // <1,2,7,7>: Cost 3 vsldoi8 <7,0,1,2>, <7,7,0,1> + 1657820802U, // <1,2,7,u>: Cost 2 vsldoi8 <7,u,1,2>, <7,u,1,2> + 470638699U, // <1,2,u,0>: Cost 1 vsldoi4 LHS, LHS + 1544381236U, // <1,2,u,1>: Cost 2 vsldoi4 LHS, <1,1,1,1> + 1544382056U, // <1,2,u,2>: Cost 2 vsldoi4 LHS, <2,2,2,2> + 1544382614U, // <1,2,u,3>: Cost 2 vsldoi4 LHS, <3,0,1,2> + 470641974U, // <1,2,u,4>: Cost 1 vsldoi4 LHS, RHS + 1628625050U, // <1,2,u,5>: Cost 2 vsldoi8 <3,0,1,2>, RHS + 1592160762U, // <1,2,u,6>: Cost 2 vsldoi4 LHS, <6,2,7,3> + 1592161274U, // <1,2,u,7>: Cost 2 vsldoi4 LHS, <7,0,1,2> + 470644526U, // <1,2,u,u>: Cost 1 vsldoi4 LHS, LHS + 2769389708U, // <1,3,0,0>: Cost 3 vsldoi12 <3,0,0,1>, <3,0,0,1> + 2685780070U, // <1,3,0,1>: Cost 3 vsldoi8 <0,2,1,3>, LHS + 2685780142U, // <1,3,0,2>: Cost 3 vsldoi8 <0,2,1,3>, <0,2,1,3> + 2686443775U, // <1,3,0,3>: Cost 3 vsldoi8 <0,3,1,3>, <0,3,1,3> + 2769684656U, // <1,3,0,4>: Cost 3 vsldoi12 <3,0,4,1>, <3,0,4,1> + 3357507940U, // <1,3,0,5>: Cost 4 vmrglw <0,3,1,0>, <0,4,3,5> + 3759522294U, // <1,3,0,6>: Cost 4 vsldoi8 <0,2,1,3>, <0,6,1,7> + 3357509562U, // <1,3,0,7>: Cost 4 vmrglw <0,3,1,0>, <2,6,3,7> + 2685780637U, // <1,3,0,u>: Cost 3 vsldoi8 <0,2,1,3>, LHS + 2287092630U, // <1,3,1,0>: Cost 3 vmrglw <0,u,1,1>, <1,2,3,0> + 2221312230U, // <1,3,1,1>: Cost 3 vmrghw <1,1,1,1>, <3,1,1,1> + 2691752839U, // <1,3,1,2>: Cost 3 vsldoi8 <1,2,1,3>, <1,2,1,3> + 2287093362U, // <1,3,1,3>: Cost 3 vmrglw <0,u,1,1>, <2,2,3,3> + 2287092634U, // <1,3,1,4>: Cost 3 vmrglw <0,u,1,1>, <1,2,3,4> + 3360835107U, // <1,3,1,5>: Cost 4 vmrglw <0,u,1,1>, <2,1,3,5> + 3759523041U, // <1,3,1,6>: Cost 4 vsldoi8 <0,2,1,3>, <1,6,3,7> + 2287093690U, // <1,3,1,7>: Cost 3 vmrglw <0,u,1,1>, <2,6,3,7> + 2287092638U, // <1,3,1,u>: Cost 3 vmrglw <0,u,1,1>, <1,2,3,u> + 2222114966U, // <1,3,2,0>: Cost 3 vmrghw <1,2,3,0>, <3,0,1,2> + 2222115057U, // <1,3,2,1>: Cost 3 vmrghw <1,2,3,0>, <3,1,2,3> + 2630092320U, // <1,3,2,2>: Cost 3 vsldoi4 <2,1,3,2>, <2,1,3,2> + 2685781670U, // <1,3,2,3>: Cost 3 vsldoi8 <0,2,1,3>, <2,3,0,1> + 2222115330U, // <1,3,2,4>: Cost 3 vmrghw <1,2,3,0>, <3,4,5,6> + 3373449572U, // <1,3,2,5>: Cost 4 vmrglw <3,0,1,2>, <0,4,3,5> + 2222115448U, // <1,3,2,6>: Cost 3 vmrghw <1,2,3,0>, <3,6,0,7> + 2299709370U, // <1,3,2,7>: Cost 3 vmrglw <3,0,1,2>, <2,6,3,7> + 2222115614U, // <1,3,2,u>: Cost 3 vmrghw <1,2,3,0>, <3,u,1,2> + 2771380607U, // <1,3,3,0>: Cost 3 vsldoi12 <3,3,0,1>, <3,3,0,1> + 3356874468U, // <1,3,3,1>: Cost 4 vmrglw <0,2,1,3>, + 3759524168U, // <1,3,3,2>: Cost 4 vsldoi8 <0,2,1,3>, <3,2,3,0> + 2283792796U, // <1,3,3,3>: Cost 3 vmrglw <0,3,1,3>, <3,3,3,3> + 3356869530U, // <1,3,3,4>: Cost 4 vmrglw <0,2,1,3>, <1,2,3,4> + 3721760428U, // <1,3,3,5>: Cost 4 vsldoi4 <5,1,3,3>, <5,1,3,3> + 3296496248U, // <1,3,3,6>: Cost 4 vmrghw <1,3,2,6>, <3,6,0,7> + 3356870586U, // <1,3,3,7>: Cost 4 vmrglw <0,2,1,3>, <2,6,3,7> + 2771970503U, // <1,3,3,u>: Cost 3 vsldoi12 <3,3,u,1>, <3,3,u,1> + 2772044240U, // <1,3,4,0>: Cost 3 vsldoi12 <3,4,0,1>, <3,4,0,1> + 3362186135U, // <1,3,4,1>: Cost 4 vmrglw <1,1,1,4>, <1,2,3,1> + 3297151280U, // <1,3,4,2>: Cost 4 vmrghw <1,4,2,5>, <3,2,0,3> + 3357542002U, // <1,3,4,3>: Cost 4 vmrglw <0,3,1,4>, <2,2,3,3> + 3357540626U, // <1,3,4,4>: Cost 4 vmrglw <0,3,1,4>, <0,3,3,4> + 2685783350U, // <1,3,4,5>: Cost 3 vsldoi8 <0,2,1,3>, RHS + 3357546622U, // <1,3,4,6>: Cost 4 vmrglw <0,3,1,4>, + 3357542330U, // <1,3,4,7>: Cost 4 vmrglw <0,3,1,4>, <2,6,3,7> + 2685783593U, // <1,3,4,u>: Cost 3 vsldoi8 <0,2,1,3>, RHS + 2284471190U, // <1,3,5,0>: Cost 3 vmrglw <0,4,1,5>, <1,2,3,0> + 3358213015U, // <1,3,5,1>: Cost 4 vmrglw <0,4,1,5>, <1,2,3,1> + 2630116899U, // <1,3,5,2>: Cost 3 vsldoi4 <2,1,3,5>, <2,1,3,5> + 2284471922U, // <1,3,5,3>: Cost 3 vmrglw <0,4,1,5>, <2,2,3,3> + 2284471194U, // <1,3,5,4>: Cost 3 vmrglw <0,4,1,5>, <1,2,3,4> + 2284471843U, // <1,3,5,5>: Cost 3 vmrglw <0,4,1,5>, <2,1,3,5> + 3358218366U, // <1,3,5,6>: Cost 4 vmrglw <0,4,1,5>, + 2284472250U, // <1,3,5,7>: Cost 3 vmrglw <0,4,1,5>, <2,6,3,7> + 2284471198U, // <1,3,5,u>: Cost 3 vmrglw <0,4,1,5>, <1,2,3,u> + 2224752790U, // <1,3,6,0>: Cost 3 vmrghw <1,6,2,7>, <3,0,1,2> + 3832736385U, // <1,3,6,1>: Cost 4 vsldoi12 <1,2,3,1>, <3,6,1,7> + 3703866916U, // <1,3,6,2>: Cost 4 vsldoi4 <2,1,3,6>, <2,1,3,6> + 3356894834U, // <1,3,6,3>: Cost 4 vmrglw <0,2,1,6>, <2,2,3,3> + 3356894106U, // <1,3,6,4>: Cost 4 vmrglw <0,2,1,6>, <1,2,3,4> + 3356894755U, // <1,3,6,5>: Cost 5 vmrglw <0,2,1,6>, <2,1,3,5> + 3356899130U, // <1,3,6,6>: Cost 4 vmrglw <0,2,1,6>, + 2283153338U, // <1,3,6,7>: Cost 3 vmrglw <0,2,1,6>, <2,6,3,7> + 2283153338U, // <1,3,6,u>: Cost 3 vmrglw <0,2,1,6>, <2,6,3,7> + 2774035139U, // <1,3,7,0>: Cost 3 vsldoi12 <3,7,0,1>, <3,7,0,1> + 3703874767U, // <1,3,7,1>: Cost 4 vsldoi4 <2,1,3,7>, <1,6,1,7> + 3703875109U, // <1,3,7,2>: Cost 4 vsldoi4 <2,1,3,7>, <2,1,3,7> + 3365529202U, // <1,3,7,3>: Cost 4 vmrglw <1,6,1,7>, <2,2,3,3> + 3365528474U, // <1,3,7,4>: Cost 4 vmrglw <1,6,1,7>, <1,2,3,4> + 3789387159U, // <1,3,7,5>: Cost 4 vsldoi8 <5,2,1,3>, <7,5,2,1> + 3865692927U, // <1,3,7,6>: Cost 4 vsldoi12 <6,7,0,1>, <3,7,6,7> + 3363538874U, // <1,3,7,7>: Cost 4 vmrglw <1,3,1,7>, <2,6,3,7> + 2774625035U, // <1,3,7,u>: Cost 3 vsldoi12 <3,7,u,1>, <3,7,u,1> + 2284495766U, // <1,3,u,0>: Cost 3 vmrglw <0,4,1,u>, <1,2,3,0> + 2685785902U, // <1,3,u,1>: Cost 3 vsldoi8 <0,2,1,3>, LHS + 2630141478U, // <1,3,u,2>: Cost 3 vsldoi4 <2,1,3,u>, <2,1,3,u> + 2283169880U, // <1,3,u,3>: Cost 3 vmrglw <0,2,1,u>, <2,u,3,3> + 2284495770U, // <1,3,u,4>: Cost 3 vmrglw <0,4,1,u>, <1,2,3,4> + 2685786266U, // <1,3,u,5>: Cost 3 vsldoi8 <0,2,1,3>, RHS + 2222115448U, // <1,3,u,6>: Cost 3 vmrghw <1,2,3,0>, <3,6,0,7> + 2284496826U, // <1,3,u,7>: Cost 3 vmrglw <0,4,1,u>, <2,6,3,7> + 2685786469U, // <1,3,u,u>: Cost 3 vsldoi8 <0,2,1,3>, LHS + 2684461069U, // <1,4,0,0>: Cost 3 vsldoi8 <0,0,1,4>, <0,0,1,4> + 2686451814U, // <1,4,0,1>: Cost 3 vsldoi8 <0,3,1,4>, LHS + 3759530159U, // <1,4,0,2>: Cost 4 vsldoi8 <0,2,1,4>, <0,2,1,4> + 2686451968U, // <1,4,0,3>: Cost 3 vsldoi8 <0,3,1,4>, <0,3,1,4> + 2684461394U, // <1,4,0,4>: Cost 3 vsldoi8 <0,0,1,4>, <0,4,1,5> + 1701989266U, // <1,4,0,5>: Cost 2 vsldoi12 <4,0,5,1>, <4,0,5,1> + 3776119286U, // <1,4,0,6>: Cost 4 vsldoi8 <3,0,1,4>, <0,6,1,7> + 2689106500U, // <1,4,0,7>: Cost 3 vsldoi8 <0,7,1,4>, <0,7,1,4> + 1702210477U, // <1,4,0,u>: Cost 2 vsldoi12 <4,0,u,1>, <4,0,u,1> + 2221312914U, // <1,4,1,0>: Cost 3 vmrghw <1,1,1,1>, <4,0,5,1> + 2691097399U, // <1,4,1,1>: Cost 3 vsldoi8 <1,1,1,4>, <1,1,1,4> + 3760194454U, // <1,4,1,2>: Cost 4 vsldoi8 <0,3,1,4>, <1,2,3,0> + 3766166489U, // <1,4,1,3>: Cost 4 vsldoi8 <1,3,1,4>, <1,3,1,4> + 2334870736U, // <1,4,1,4>: Cost 3 vmrglw , <4,4,4,4> + 1147571510U, // <1,4,1,5>: Cost 2 vmrghw <1,1,1,1>, RHS + 3760194794U, // <1,4,1,6>: Cost 4 vsldoi8 <0,3,1,4>, <1,6,4,7> + 3867315188U, // <1,4,1,7>: Cost 4 vsldoi12 <7,0,4,1>, <4,1,7,0> + 1147571753U, // <1,4,1,u>: Cost 2 vmrghw <1,1,1,1>, RHS + 2222115730U, // <1,4,2,0>: Cost 3 vmrghw <1,2,3,0>, <4,0,5,1> + 2222115812U, // <1,4,2,1>: Cost 3 vmrghw <1,2,3,0>, <4,1,5,2> + 3760195176U, // <1,4,2,2>: Cost 4 vsldoi8 <0,3,1,4>, <2,2,2,2> + 2702378662U, // <1,4,2,3>: Cost 3 vsldoi8 <3,0,1,4>, <2,3,0,1> + 2323598544U, // <1,4,2,4>: Cost 3 vmrglw <7,0,1,2>, <4,4,4,4> + 1148374326U, // <1,4,2,5>: Cost 2 vmrghw <1,2,3,0>, RHS + 3760195514U, // <1,4,2,6>: Cost 4 vsldoi8 <0,3,1,4>, <2,6,3,7> + 3373451932U, // <1,4,2,7>: Cost 4 vmrglw <3,0,1,2>, <3,6,4,7> + 1148374569U, // <1,4,2,u>: Cost 2 vmrghw <1,2,3,0>, RHS + 2702379160U, // <1,4,3,0>: Cost 3 vsldoi8 <3,0,1,4>, <3,0,1,4> + 3760195840U, // <1,4,3,1>: Cost 4 vsldoi8 <0,3,1,4>, <3,1,4,0> + 3776121160U, // <1,4,3,2>: Cost 4 vsldoi8 <3,0,1,4>, <3,2,3,0> + 3760195996U, // <1,4,3,3>: Cost 4 vsldoi8 <0,3,1,4>, <3,3,3,3> + 2686454274U, // <1,4,3,4>: Cost 3 vsldoi8 <0,3,1,4>, <3,4,5,6> + 3356870350U, // <1,4,3,5>: Cost 4 vmrglw <0,2,1,3>, <2,3,4,5> + 3800009392U, // <1,4,3,6>: Cost 4 vsldoi8 <7,0,1,4>, <3,6,7,0> + 3366824604U, // <1,4,3,7>: Cost 5 vmrglw <1,u,1,3>, <3,6,4,7> + 2707688224U, // <1,4,3,u>: Cost 3 vsldoi8 <3,u,1,4>, <3,u,1,4> + 2775731368U, // <1,4,4,0>: Cost 3 vsldoi12 <4,0,5,1>, <4,4,0,0> + 3830820018U, // <1,4,4,1>: Cost 4 vsldoi12 <0,u,4,1>, <4,4,1,1> + 3691980454U, // <1,4,4,2>: Cost 4 vsldoi4 <0,1,4,4>, <2,3,0,1> + 3357541282U, // <1,4,4,3>: Cost 4 vmrglw <0,3,1,4>, <1,2,4,3> + 2781039824U, // <1,4,4,4>: Cost 3 vsldoi12 <4,u,5,1>, <4,4,4,4> + 2686455094U, // <1,4,4,5>: Cost 3 vsldoi8 <0,3,1,4>, RHS + 3357541528U, // <1,4,4,6>: Cost 4 vmrglw <0,3,1,4>, <1,5,4,6> + 3810627020U, // <1,4,4,7>: Cost 4 vsldoi8 , <4,7,5,4> + 2686455337U, // <1,4,4,u>: Cost 3 vsldoi8 <0,3,1,4>, RHS + 2624217190U, // <1,4,5,0>: Cost 3 vsldoi4 <1,1,4,5>, LHS + 2284470309U, // <1,4,5,1>: Cost 3 vmrglw <0,4,1,5>, <0,0,4,1> + 2618246822U, // <1,4,5,2>: Cost 3 vsldoi4 <0,1,4,5>, <2,3,0,1> + 3358212297U, // <1,4,5,3>: Cost 4 vmrglw <0,4,1,5>, <0,2,4,3> + 2284470312U, // <1,4,5,4>: Cost 3 vmrglw <0,4,1,5>, <0,0,4,4> + 2284470637U, // <1,4,5,5>: Cost 3 vmrglw <0,4,1,5>, <0,4,4,5> + 1683115318U, // <1,4,5,6>: Cost 2 vsldoi12 <0,u,1,1>, RHS + 3721851898U, // <1,4,5,7>: Cost 4 vsldoi4 <5,1,4,5>, <7,0,1,2> + 1683115336U, // <1,4,5,u>: Cost 2 vsldoi12 <0,u,1,1>, RHS + 3794039075U, // <1,4,6,0>: Cost 4 vsldoi8 <6,0,1,4>, <6,0,1,4> + 3830820186U, // <1,4,6,1>: Cost 4 vsldoi12 <0,u,4,1>, <4,6,1,7> + 3800011258U, // <1,4,6,2>: Cost 4 vsldoi8 <7,0,1,4>, <6,2,7,3> + 3807973938U, // <1,4,6,3>: Cost 4 vsldoi8 , <6,3,4,5> + 3298716880U, // <1,4,6,4>: Cost 4 vmrghw <1,6,5,7>, <4,4,4,4> + 2224680246U, // <1,4,6,5>: Cost 3 vmrghw <1,6,1,7>, RHS + 3800011576U, // <1,4,6,6>: Cost 4 vsldoi8 <7,0,1,4>, <6,6,6,6> + 2726269774U, // <1,4,6,7>: Cost 3 vsldoi8 <7,0,1,4>, <6,7,0,1> + 2224680489U, // <1,4,6,u>: Cost 3 vmrghw <1,6,1,7>, RHS + 2726269948U, // <1,4,7,0>: Cost 3 vsldoi8 <7,0,1,4>, <7,0,1,4> + 3383444141U, // <1,4,7,1>: Cost 4 vmrglw <4,6,1,7>, <0,u,4,1> + 3805983961U, // <1,4,7,2>: Cost 4 vsldoi8 , <7,2,u,0> + 3807974667U, // <1,4,7,3>: Cost 4 vsldoi8 , <7,3,4,5> + 2736887142U, // <1,4,7,4>: Cost 3 vsldoi8 , <7,4,5,6> + 3365528403U, // <1,4,7,5>: Cost 4 vmrglw <1,6,1,7>, <1,1,4,5> + 3800012308U, // <1,4,7,6>: Cost 4 vsldoi8 <7,0,1,4>, <7,6,7,0> + 3800012396U, // <1,4,7,7>: Cost 4 vsldoi8 <7,0,1,4>, <7,7,7,7> + 2731579012U, // <1,4,7,u>: Cost 3 vsldoi8 <7,u,1,4>, <7,u,1,4> + 2624241766U, // <1,4,u,0>: Cost 3 vsldoi4 <1,1,4,u>, LHS + 2686457646U, // <1,4,u,1>: Cost 3 vsldoi8 <0,3,1,4>, LHS + 2618271398U, // <1,4,u,2>: Cost 3 vsldoi4 <0,1,4,u>, <2,3,0,1> + 2734233544U, // <1,4,u,3>: Cost 3 vsldoi8 , + 2689775679U, // <1,4,u,4>: Cost 3 vsldoi8 <0,u,1,4>, + 1152355638U, // <1,4,u,5>: Cost 2 vmrghw <1,u,3,0>, RHS + 1683115561U, // <1,4,u,6>: Cost 2 vsldoi12 <0,u,1,1>, RHS + 2736888076U, // <1,4,u,7>: Cost 3 vsldoi8 , + 1683115579U, // <1,4,u,u>: Cost 2 vsldoi12 <0,u,1,1>, RHS + 2687123456U, // <1,5,0,0>: Cost 3 vsldoi8 <0,4,1,5>, <0,0,0,0> + 1613381734U, // <1,5,0,1>: Cost 2 vsldoi8 <0,4,1,5>, LHS + 3759538352U, // <1,5,0,2>: Cost 4 vsldoi8 <0,2,1,5>, <0,2,1,5> + 3760865532U, // <1,5,0,3>: Cost 4 vsldoi8 <0,4,1,5>, <0,3,1,0> + 1613381970U, // <1,5,0,4>: Cost 2 vsldoi8 <0,4,1,5>, <0,4,1,5> + 2687787427U, // <1,5,0,5>: Cost 3 vsldoi8 <0,5,1,5>, <0,5,1,5> + 2781777524U, // <1,5,0,6>: Cost 3 vsldoi12 <5,0,6,1>, <5,0,6,1> + 3733828717U, // <1,5,0,7>: Cost 4 vsldoi4 <7,1,5,0>, <7,1,5,0> + 1613382301U, // <1,5,0,u>: Cost 2 vsldoi8 <0,4,1,5>, LHS + 2781040271U, // <1,5,1,0>: Cost 3 vsldoi12 <4,u,5,1>, <5,1,0,1> + 2687124276U, // <1,5,1,1>: Cost 3 vsldoi8 <0,4,1,5>, <1,1,1,1> + 2687124374U, // <1,5,1,2>: Cost 3 vsldoi8 <0,4,1,5>, <1,2,3,0> + 3760866297U, // <1,5,1,3>: Cost 4 vsldoi8 <0,4,1,5>, <1,3,5,0> + 2693096491U, // <1,5,1,4>: Cost 3 vsldoi8 <1,4,1,5>, <1,4,1,5> + 2687124591U, // <1,5,1,5>: Cost 3 vsldoi8 <0,4,1,5>, <1,5,0,1> + 2687124723U, // <1,5,1,6>: Cost 3 vsldoi8 <0,4,1,5>, <1,6,5,7> + 3360834803U, // <1,5,1,7>: Cost 4 vmrglw <0,u,1,1>, <1,6,5,7> + 2687124860U, // <1,5,1,u>: Cost 3 vsldoi8 <0,4,1,5>, <1,u,3,0> + 2323598792U, // <1,5,2,0>: Cost 3 vmrglw <7,0,1,2>, <4,7,5,0> + 2687125027U, // <1,5,2,1>: Cost 3 vsldoi8 <0,4,1,5>, <2,1,3,5> + 2687125096U, // <1,5,2,2>: Cost 3 vsldoi8 <0,4,1,5>, <2,2,2,2> + 2687125158U, // <1,5,2,3>: Cost 3 vsldoi8 <0,4,1,5>, <2,3,0,1> + 2642185188U, // <1,5,2,4>: Cost 3 vsldoi4 <4,1,5,2>, <4,1,5,2> + 2323598554U, // <1,5,2,5>: Cost 3 vmrglw <7,0,1,2>, <4,4,5,5> + 2687125434U, // <1,5,2,6>: Cost 3 vsldoi8 <0,4,1,5>, <2,6,3,7> + 3373450483U, // <1,5,2,7>: Cost 4 vmrglw <3,0,1,2>, <1,6,5,7> + 2687125563U, // <1,5,2,u>: Cost 3 vsldoi8 <0,4,1,5>, <2,u,0,1> + 2687125654U, // <1,5,3,0>: Cost 3 vsldoi8 <0,4,1,5>, <3,0,1,2> + 2312990234U, // <1,5,3,1>: Cost 3 vmrglw <5,2,1,3>, <4,u,5,1> + 3760867649U, // <1,5,3,2>: Cost 4 vsldoi8 <0,4,1,5>, <3,2,2,2> + 2687125916U, // <1,5,3,3>: Cost 3 vsldoi8 <0,4,1,5>, <3,3,3,3> + 2687126018U, // <1,5,3,4>: Cost 3 vsldoi8 <0,4,1,5>, <3,4,5,6> + 3386731738U, // <1,5,3,5>: Cost 4 vmrglw <5,2,1,3>, <4,4,5,5> + 3356871170U, // <1,5,3,6>: Cost 4 vmrglw <0,2,1,3>, <3,4,5,6> + 3808643779U, // <1,5,3,7>: Cost 4 vsldoi8 , <3,7,0,1> + 2687126302U, // <1,5,3,u>: Cost 3 vsldoi8 <0,4,1,5>, <3,u,1,2> + 2642198630U, // <1,5,4,0>: Cost 3 vsldoi4 <4,1,5,4>, LHS + 2687126498U, // <1,5,4,1>: Cost 3 vsldoi8 <0,4,1,5>, <4,1,5,0> + 3715941923U, // <1,5,4,2>: Cost 4 vsldoi4 <4,1,5,4>, <2,1,3,5> + 3709970701U, // <1,5,4,3>: Cost 4 vsldoi4 <3,1,5,4>, <3,1,5,4> + 2687126736U, // <1,5,4,4>: Cost 3 vsldoi8 <0,4,1,5>, <4,4,4,4> + 1613385014U, // <1,5,4,5>: Cost 2 vsldoi8 <0,4,1,5>, RHS + 2283801090U, // <1,5,4,6>: Cost 3 vmrglw <0,3,1,4>, <3,4,5,6> + 3733861489U, // <1,5,4,7>: Cost 4 vsldoi4 <7,1,5,4>, <7,1,5,4> + 1613385257U, // <1,5,4,u>: Cost 2 vsldoi8 <0,4,1,5>, RHS + 2624290918U, // <1,5,5,0>: Cost 3 vsldoi4 <1,1,5,5>, LHS + 2624291676U, // <1,5,5,1>: Cost 3 vsldoi4 <1,1,5,5>, <1,1,5,5> + 3698034211U, // <1,5,5,2>: Cost 4 vsldoi4 <1,1,5,5>, <2,1,3,5> + 2284471211U, // <1,5,5,3>: Cost 3 vmrglw <0,4,1,5>, <1,2,5,3> + 2624294198U, // <1,5,5,4>: Cost 3 vsldoi4 <1,1,5,5>, RHS + 2284471132U, // <1,5,5,5>: Cost 3 vmrglw <0,4,1,5>, <1,1,5,5> + 2284472834U, // <1,5,5,6>: Cost 3 vmrglw <0,4,1,5>, <3,4,5,6> + 2284471539U, // <1,5,5,7>: Cost 3 vmrglw <0,4,1,5>, <1,6,5,7> + 2284471216U, // <1,5,5,u>: Cost 3 vmrglw <0,4,1,5>, <1,2,5,u> + 2785316900U, // <1,5,6,0>: Cost 3 vsldoi12 <5,6,0,1>, <5,6,0,1> + 2781040691U, // <1,5,6,1>: Cost 3 vsldoi12 <4,u,5,1>, <5,6,1,7> + 2734903802U, // <1,5,6,2>: Cost 3 vsldoi8 , <6,2,7,3> + 3848736834U, // <1,5,6,3>: Cost 4 vsldoi12 <3,u,4,1>, <5,6,3,4> + 3298717620U, // <1,5,6,4>: Cost 4 vmrghw <1,6,5,7>, <5,4,5,6> + 3298717700U, // <1,5,6,5>: Cost 4 vmrghw <1,6,5,7>, <5,5,5,5> + 2734904120U, // <1,5,6,6>: Cost 3 vsldoi8 , <6,6,6,6> + 2781040738U, // <1,5,6,7>: Cost 3 vsldoi12 <4,u,5,1>, <5,6,7,0> + 2781040747U, // <1,5,6,u>: Cost 3 vsldoi12 <4,u,5,1>, <5,6,u,0> + 2734904314U, // <1,5,7,0>: Cost 3 vsldoi8 , <7,0,1,2> + 2315677210U, // <1,5,7,1>: Cost 3 vmrglw <5,6,1,7>, <4,u,5,1> + 3808646292U, // <1,5,7,2>: Cost 4 vsldoi8 , <7,2,0,3> + 3808646371U, // <1,5,7,3>: Cost 4 vsldoi8 , <7,3,0,1> + 2734904678U, // <1,5,7,4>: Cost 3 vsldoi8 , <7,4,5,6> + 3389418714U, // <1,5,7,5>: Cost 4 vmrglw <5,6,1,7>, <4,4,5,5> + 3365528656U, // <1,5,7,6>: Cost 4 vmrglw <1,6,1,7>, <1,4,5,6> + 2734904940U, // <1,5,7,7>: Cost 3 vsldoi8 , <7,7,7,7> + 2734904962U, // <1,5,7,u>: Cost 3 vsldoi8 , <7,u,1,2> + 2687129299U, // <1,5,u,0>: Cost 3 vsldoi8 <0,4,1,5>, + 1613387566U, // <1,5,u,1>: Cost 2 vsldoi8 <0,4,1,5>, LHS + 2687129480U, // <1,5,u,2>: Cost 3 vsldoi8 <0,4,1,5>, + 2687129532U, // <1,5,u,3>: Cost 3 vsldoi8 <0,4,1,5>, + 1661163546U, // <1,5,u,4>: Cost 2 vsldoi8 , + 1613387930U, // <1,5,u,5>: Cost 2 vsldoi8 <0,4,1,5>, RHS + 2687129808U, // <1,5,u,6>: Cost 3 vsldoi8 <0,4,1,5>, + 2781040900U, // <1,5,u,7>: Cost 3 vsldoi12 <4,u,5,1>, <5,u,7,0> + 1613388133U, // <1,5,u,u>: Cost 2 vsldoi8 <0,4,1,5>, LHS + 3759546368U, // <1,6,0,0>: Cost 4 vsldoi8 <0,2,1,6>, <0,0,0,0> + 2685804646U, // <1,6,0,1>: Cost 3 vsldoi8 <0,2,1,6>, LHS + 2685804721U, // <1,6,0,2>: Cost 3 vsldoi8 <0,2,1,6>, <0,2,1,6> + 3861270834U, // <1,6,0,3>: Cost 4 vsldoi12 <6,0,3,1>, <6,0,3,1> + 3759546706U, // <1,6,0,4>: Cost 4 vsldoi8 <0,2,1,6>, <0,4,1,5> + 2687795620U, // <1,6,0,5>: Cost 3 vsldoi8 <0,5,1,6>, <0,5,1,6> + 2688459253U, // <1,6,0,6>: Cost 3 vsldoi8 <0,6,1,6>, <0,6,1,6> + 2283769142U, // <1,6,0,7>: Cost 3 vmrglw <0,3,1,0>, RHS + 2685805213U, // <1,6,0,u>: Cost 3 vsldoi8 <0,2,1,6>, LHS + 3698073702U, // <1,6,1,0>: Cost 4 vsldoi4 <1,1,6,1>, LHS + 3759547188U, // <1,6,1,1>: Cost 4 vsldoi8 <0,2,1,6>, <1,1,1,1> + 2221314554U, // <1,6,1,2>: Cost 3 vmrghw <1,1,1,1>, <6,2,7,3> + 3759547401U, // <1,6,1,3>: Cost 4 vsldoi8 <0,2,1,6>, <1,3,6,7> + 3698076982U, // <1,6,1,4>: Cost 4 vsldoi4 <1,1,6,1>, RHS + 3767510141U, // <1,6,1,5>: Cost 4 vsldoi8 <1,5,1,6>, <1,5,1,6> + 2334872376U, // <1,6,1,6>: Cost 3 vmrglw , <6,6,6,6> + 1213353270U, // <1,6,1,7>: Cost 2 vmrglw <0,u,1,1>, RHS + 1213353271U, // <1,6,1,u>: Cost 2 vmrglw <0,u,1,1>, RHS + 3704053862U, // <1,6,2,0>: Cost 4 vsldoi4 <2,1,6,2>, LHS + 3759547961U, // <1,6,2,1>: Cost 4 vsldoi8 <0,2,1,6>, <2,1,6,0> + 2222117370U, // <1,6,2,2>: Cost 3 vmrghw <1,2,3,0>, <6,2,7,3> + 3759548070U, // <1,6,2,3>: Cost 4 vsldoi8 <0,2,1,6>, <2,3,0,1> + 3704057142U, // <1,6,2,4>: Cost 4 vsldoi4 <2,1,6,2>, RHS + 3373451057U, // <1,6,2,5>: Cost 4 vmrglw <3,0,1,2>, <2,4,6,5> + 2685806522U, // <1,6,2,6>: Cost 3 vsldoi8 <0,2,1,6>, <2,6,3,7> + 1225968950U, // <1,6,2,7>: Cost 2 vmrglw <3,0,1,2>, RHS + 1225968951U, // <1,6,2,u>: Cost 2 vmrglw <3,0,1,2>, RHS + 3759548566U, // <1,6,3,0>: Cost 4 vsldoi8 <0,2,1,6>, <3,0,1,2> + 3842912793U, // <1,6,3,1>: Cost 4 vsldoi12 <2,u,6,1>, <6,3,1,7> + 3759548774U, // <1,6,3,2>: Cost 4 vsldoi8 <0,2,1,6>, <3,2,6,3> + 3759548828U, // <1,6,3,3>: Cost 4 vsldoi8 <0,2,1,6>, <3,3,3,3> + 3759548930U, // <1,6,3,4>: Cost 4 vsldoi8 <0,2,1,6>, <3,4,5,6> + 3809315421U, // <1,6,3,5>: Cost 4 vsldoi8 , <3,5,6,7> + 3386733368U, // <1,6,3,6>: Cost 4 vmrglw <5,2,1,3>, <6,6,6,6> + 2283130166U, // <1,6,3,7>: Cost 3 vmrglw <0,2,1,3>, RHS + 2283130167U, // <1,6,3,u>: Cost 3 vmrglw <0,2,1,3>, RHS + 3704070246U, // <1,6,4,0>: Cost 4 vsldoi4 <2,1,6,4>, LHS + 3862229608U, // <1,6,4,1>: Cost 4 vsldoi12 <6,1,7,1>, <6,4,1,5> + 3704071741U, // <1,6,4,2>: Cost 4 vsldoi4 <2,1,6,4>, <2,1,6,4> + 3721988610U, // <1,6,4,3>: Cost 4 vsldoi4 <5,1,6,4>, <3,4,5,6> + 3704073526U, // <1,6,4,4>: Cost 4 vsldoi4 <2,1,6,4>, RHS + 2685807926U, // <1,6,4,5>: Cost 3 vsldoi8 <0,2,1,6>, RHS + 3865621141U, // <1,6,4,6>: Cost 4 vsldoi12 <6,6,u,1>, <6,4,6,5> + 2283801910U, // <1,6,4,7>: Cost 3 vmrglw <0,3,1,4>, RHS + 2685808169U, // <1,6,4,u>: Cost 3 vsldoi8 <0,2,1,6>, RHS + 3710050406U, // <1,6,5,0>: Cost 4 vsldoi4 <3,1,6,5>, LHS + 3710051571U, // <1,6,5,1>: Cost 4 vsldoi4 <3,1,6,5>, <1,6,5,7> + 3405989597U, // <1,6,5,2>: Cost 4 vmrglw , <2,3,6,2> + 3358214502U, // <1,6,5,3>: Cost 4 vmrglw <0,4,1,5>, <3,2,6,3> + 3710053686U, // <1,6,5,4>: Cost 4 vsldoi4 <3,1,6,5>, RHS + 3721998025U, // <1,6,5,5>: Cost 4 vsldoi4 <5,1,6,5>, <5,1,6,5> + 2332250936U, // <1,6,5,6>: Cost 3 vmrglw , <6,6,6,6> + 1210731830U, // <1,6,5,7>: Cost 2 vmrglw <0,4,1,5>, RHS + 1210731831U, // <1,6,5,u>: Cost 2 vmrglw <0,4,1,5>, RHS + 2791289597U, // <1,6,6,0>: Cost 3 vsldoi12 <6,6,0,1>, <6,6,0,1> + 3698115430U, // <1,6,6,1>: Cost 4 vsldoi4 <1,1,6,6>, <1,1,6,6> + 3698116538U, // <1,6,6,2>: Cost 4 vsldoi4 <1,1,6,6>, <2,6,3,7> + 3356894132U, // <1,6,6,3>: Cost 4 vmrglw <0,2,1,6>, <1,2,6,3> + 3698117942U, // <1,6,6,4>: Cost 4 vsldoi4 <1,1,6,6>, RHS + 3722006218U, // <1,6,6,5>: Cost 4 vsldoi4 <5,1,6,6>, <5,1,6,6> + 2781041464U, // <1,6,6,6>: Cost 3 vsldoi12 <4,u,5,1>, <6,6,6,6> + 2283154742U, // <1,6,6,7>: Cost 3 vmrglw <0,2,1,6>, RHS + 2283154743U, // <1,6,6,u>: Cost 3 vmrglw <0,2,1,6>, RHS + 1718211406U, // <1,6,7,0>: Cost 2 vsldoi12 <6,7,0,1>, <6,7,0,1> + 2792026967U, // <1,6,7,1>: Cost 3 vsldoi12 <6,7,1,1>, <6,7,1,1> + 2765411170U, // <1,6,7,2>: Cost 3 vsldoi12 <2,3,0,1>, <6,7,2,3> + 3854783336U, // <1,6,7,3>: Cost 4 vsldoi12 <4,u,5,1>, <6,7,3,0> + 2781041526U, // <1,6,7,4>: Cost 3 vsldoi12 <4,u,5,1>, <6,7,4,5> + 3365528664U, // <1,6,7,5>: Cost 4 vmrglw <1,6,1,7>, <1,4,6,5> + 2791953290U, // <1,6,7,6>: Cost 3 vsldoi12 <6,7,0,1>, <6,7,6,7> + 2291789110U, // <1,6,7,7>: Cost 3 vmrglw <1,6,1,7>, RHS + 1718801302U, // <1,6,7,u>: Cost 2 vsldoi12 <6,7,u,1>, <6,7,u,1> + 1718875039U, // <1,6,u,0>: Cost 2 vsldoi12 <6,u,0,1>, <6,u,0,1> + 2685810478U, // <1,6,u,1>: Cost 3 vsldoi8 <0,2,1,6>, LHS + 2792764337U, // <1,6,u,2>: Cost 3 vsldoi12 <6,u,2,1>, <6,u,2,1> + 3759552444U, // <1,6,u,3>: Cost 4 vsldoi8 <0,2,1,6>, + 2781041607U, // <1,6,u,4>: Cost 3 vsldoi12 <4,u,5,1>, <6,u,4,5> + 2685810842U, // <1,6,u,5>: Cost 3 vsldoi8 <0,2,1,6>, RHS + 2689792208U, // <1,6,u,6>: Cost 3 vsldoi8 <0,u,1,6>, + 1210756406U, // <1,6,u,7>: Cost 2 vmrglw <0,4,1,u>, RHS + 1210756407U, // <1,6,u,u>: Cost 2 vmrglw <0,4,1,u>, RHS + 2793280496U, // <1,7,0,0>: Cost 3 vsldoi12 <7,0,0,1>, <7,0,0,1> + 2694439014U, // <1,7,0,1>: Cost 3 vsldoi8 <1,6,1,7>, LHS + 3393343912U, // <1,7,0,2>: Cost 4 vmrglw <6,3,1,0>, <6,1,7,2> + 3397325306U, // <1,7,0,3>: Cost 4 vmrglw <7,0,1,0>, <6,2,7,3> + 2793575444U, // <1,7,0,4>: Cost 3 vsldoi12 <7,0,4,1>, <7,0,4,1> + 3722030797U, // <1,7,0,5>: Cost 4 vsldoi4 <5,1,7,0>, <5,1,7,0> + 2688467446U, // <1,7,0,6>: Cost 3 vsldoi8 <0,6,1,7>, <0,6,1,7> + 2689131079U, // <1,7,0,7>: Cost 3 vsldoi8 <0,7,1,7>, <0,7,1,7> + 2694439570U, // <1,7,0,u>: Cost 3 vsldoi8 <1,6,1,7>, <0,u,1,1> + 2654265354U, // <1,7,1,0>: Cost 3 vsldoi4 <6,1,7,1>, <0,0,1,1> + 2794017866U, // <1,7,1,1>: Cost 3 vsldoi12 <7,1,1,1>, <7,1,1,1> + 3768181639U, // <1,7,1,2>: Cost 4 vsldoi8 <1,6,1,7>, <1,2,1,3> + 2334872058U, // <1,7,1,3>: Cost 3 vmrglw , <6,2,7,3> + 2654268726U, // <1,7,1,4>: Cost 3 vsldoi4 <6,1,7,1>, RHS + 3792069797U, // <1,7,1,5>: Cost 4 vsldoi8 <5,6,1,7>, <1,5,6,1> + 2694440143U, // <1,7,1,6>: Cost 3 vsldoi8 <1,6,1,7>, <1,6,1,7> + 2334872386U, // <1,7,1,7>: Cost 3 vmrglw , <6,6,7,7> + 2695767409U, // <1,7,1,u>: Cost 3 vsldoi8 <1,u,1,7>, <1,u,1,7> + 2654273638U, // <1,7,2,0>: Cost 3 vsldoi4 <6,1,7,2>, LHS + 2222117973U, // <1,7,2,1>: Cost 3 vmrghw <1,2,3,0>, <7,1,2,3> + 2299711912U, // <1,7,2,2>: Cost 3 vmrglw <3,0,1,2>, <6,1,7,2> + 2654275734U, // <1,7,2,3>: Cost 3 vsldoi4 <6,1,7,2>, <3,0,1,2> + 2654276918U, // <1,7,2,4>: Cost 3 vsldoi4 <6,1,7,2>, RHS + 3385397675U, // <1,7,2,5>: Cost 4 vmrglw <5,0,1,2>, <6,1,7,5> + 2654278056U, // <1,7,2,6>: Cost 3 vsldoi4 <6,1,7,2>, <6,1,7,2> + 2323599627U, // <1,7,2,7>: Cost 3 vmrglw <7,0,1,2>, <5,u,7,7> + 2654279470U, // <1,7,2,u>: Cost 3 vsldoi4 <6,1,7,2>, LHS + 2795271395U, // <1,7,3,0>: Cost 3 vsldoi12 <7,3,0,1>, <7,3,0,1> + 3768183059U, // <1,7,3,1>: Cost 4 vsldoi8 <1,6,1,7>, <3,1,6,1> + 3728025254U, // <1,7,3,2>: Cost 4 vsldoi4 <6,1,7,3>, <2,3,0,1> + 3768183196U, // <1,7,3,3>: Cost 4 vsldoi8 <1,6,1,7>, <3,3,3,3> + 3768183298U, // <1,7,3,4>: Cost 4 vsldoi8 <1,6,1,7>, <3,4,5,6> + 3792071255U, // <1,7,3,5>: Cost 4 vsldoi8 <5,6,1,7>, <3,5,6,1> + 3780127361U, // <1,7,3,6>: Cost 4 vsldoi8 <3,6,1,7>, <3,6,1,7> + 3847779617U, // <1,7,3,7>: Cost 4 vsldoi12 <3,7,0,1>, <7,3,7,0> + 2795861291U, // <1,7,3,u>: Cost 3 vsldoi12 <7,3,u,1>, <7,3,u,1> + 2795935028U, // <1,7,4,0>: Cost 3 vsldoi12 <7,4,0,1>, <7,4,0,1> + 3728032975U, // <1,7,4,1>: Cost 4 vsldoi4 <6,1,7,4>, <1,6,1,7> + 3839153480U, // <1,7,4,2>: Cost 4 vsldoi12 <2,3,0,1>, <7,4,2,3> + 3397358074U, // <1,7,4,3>: Cost 4 vmrglw <7,0,1,4>, <6,2,7,3> + 3854783835U, // <1,7,4,4>: Cost 4 vsldoi12 <4,u,5,1>, <7,4,4,4> + 2694442294U, // <1,7,4,5>: Cost 3 vsldoi8 <1,6,1,7>, RHS + 3786100058U, // <1,7,4,6>: Cost 4 vsldoi8 <4,6,1,7>, <4,6,1,7> + 3722065254U, // <1,7,4,7>: Cost 4 vsldoi4 <5,1,7,4>, <7,4,5,6> + 2694442537U, // <1,7,4,u>: Cost 3 vsldoi8 <1,6,1,7>, RHS + 2654298214U, // <1,7,5,0>: Cost 3 vsldoi4 <6,1,7,5>, LHS + 3854783893U, // <1,7,5,1>: Cost 4 vsldoi12 <4,u,5,1>, <7,5,1,u> + 3710126010U, // <1,7,5,2>: Cost 4 vsldoi4 <3,1,7,5>, <2,6,3,7> + 2332250618U, // <1,7,5,3>: Cost 3 vmrglw , <6,2,7,3> + 2654301494U, // <1,7,5,4>: Cost 3 vsldoi4 <6,1,7,5>, RHS + 2284474795U, // <1,7,5,5>: Cost 3 vmrglw <0,4,1,5>, <6,1,7,5> + 2718330931U, // <1,7,5,6>: Cost 3 vsldoi8 <5,6,1,7>, <5,6,1,7> + 2332250946U, // <1,7,5,7>: Cost 3 vmrglw , <6,6,7,7> + 2719658197U, // <1,7,5,u>: Cost 3 vsldoi8 <5,u,1,7>, <5,u,1,7> + 2332921954U, // <1,7,6,0>: Cost 3 vmrglw , <5,6,7,0> + 3768185254U, // <1,7,6,1>: Cost 4 vsldoi8 <1,6,1,7>, <6,1,7,0> + 3710134202U, // <1,7,6,2>: Cost 4 vsldoi4 <3,1,7,6>, <2,6,3,7> + 3710134561U, // <1,7,6,3>: Cost 4 vsldoi4 <3,1,7,6>, <3,1,7,6> + 3710135606U, // <1,7,6,4>: Cost 4 vsldoi4 <3,1,7,6>, RHS + 3864884745U, // <1,7,6,5>: Cost 4 vsldoi12 <6,5,7,1>, <7,6,5,7> + 3854784017U, // <1,7,6,6>: Cost 4 vsldoi12 <4,u,5,1>, <7,6,6,6> + 2791953940U, // <1,7,6,7>: Cost 3 vsldoi12 <6,7,0,1>, <7,6,7,0> + 2792617501U, // <1,7,6,u>: Cost 3 vsldoi12 <6,u,0,1>, <7,6,u,0> + 2797925927U, // <1,7,7,0>: Cost 3 vsldoi12 <7,7,0,1>, <7,7,0,1> + 3365528426U, // <1,7,7,1>: Cost 4 vmrglw <1,6,1,7>, <1,1,7,1> + 3728058022U, // <1,7,7,2>: Cost 4 vsldoi4 <6,1,7,7>, <2,3,0,1> + 3365528509U, // <1,7,7,3>: Cost 4 vmrglw <1,6,1,7>, <1,2,7,3> + 3854784079U, // <1,7,7,4>: Cost 4 vsldoi12 <4,u,5,1>, <7,7,4,5> + 3722088148U, // <1,7,7,5>: Cost 4 vsldoi4 <5,1,7,7>, <5,1,7,7> + 3728060845U, // <1,7,7,6>: Cost 4 vsldoi4 <6,1,7,7>, <6,1,7,7> + 2781042284U, // <1,7,7,7>: Cost 3 vsldoi12 <4,u,5,1>, <7,7,7,7> + 2798515823U, // <1,7,7,u>: Cost 3 vsldoi12 <7,7,u,1>, <7,7,u,1> + 2654322705U, // <1,7,u,0>: Cost 3 vsldoi4 <6,1,7,u>, <0,0,1,u> + 2694444846U, // <1,7,u,1>: Cost 3 vsldoi8 <1,6,1,7>, LHS + 2299711912U, // <1,7,u,2>: Cost 3 vmrglw <3,0,1,2>, <6,1,7,2> + 2323649018U, // <1,7,u,3>: Cost 3 vmrglw <7,0,1,u>, <6,2,7,3> + 2654326070U, // <1,7,u,4>: Cost 3 vsldoi4 <6,1,7,u>, RHS + 2694445210U, // <1,7,u,5>: Cost 3 vsldoi8 <1,6,1,7>, RHS + 2654327214U, // <1,7,u,6>: Cost 3 vsldoi4 <6,1,7,u>, <6,1,7,u> + 2323649346U, // <1,7,u,7>: Cost 3 vmrglw <7,0,1,u>, <6,6,7,7> + 2694445413U, // <1,7,u,u>: Cost 3 vsldoi8 <1,6,1,7>, LHS + 1610752017U, // <1,u,0,0>: Cost 2 vsldoi8 <0,0,1,u>, <0,0,1,u> + 1613406310U, // <1,u,0,1>: Cost 2 vsldoi8 <0,4,1,u>, LHS + 2685821107U, // <1,u,0,2>: Cost 3 vsldoi8 <0,2,1,u>, <0,2,1,u> + 2283765916U, // <1,u,0,3>: Cost 3 vmrglw <0,3,1,0>, LHS + 1613406549U, // <1,u,0,4>: Cost 2 vsldoi8 <0,4,1,u>, <0,4,1,u> + 1725880054U, // <1,u,0,5>: Cost 2 vsldoi12 , + 2688475639U, // <1,u,0,6>: Cost 3 vsldoi8 <0,6,1,u>, <0,6,1,u> + 2283769160U, // <1,u,0,7>: Cost 3 vmrglw <0,3,1,0>, RHS + 1613406877U, // <1,u,0,u>: Cost 2 vsldoi8 <0,4,1,u>, LHS + 1550221414U, // <1,u,1,0>: Cost 2 vsldoi4 <1,1,1,1>, LHS + 269271142U, // <1,u,1,1>: Cost 1 vspltisw1 LHS + 1683117870U, // <1,u,1,2>: Cost 2 vsldoi12 <0,u,1,1>, LHS + 1213350044U, // <1,u,1,3>: Cost 2 vmrglw <0,u,1,1>, LHS + 1550224694U, // <1,u,1,4>: Cost 2 vsldoi4 <1,1,1,1>, RHS + 1147574426U, // <1,u,1,5>: Cost 2 vmrghw <1,1,1,1>, RHS + 2687149326U, // <1,u,1,6>: Cost 3 vsldoi8 <0,4,1,u>, <1,6,u,7> + 1213353288U, // <1,u,1,7>: Cost 2 vmrglw <0,u,1,1>, RHS + 269271142U, // <1,u,1,u>: Cost 1 vspltisw1 LHS + 2222118611U, // <1,u,2,0>: Cost 3 vmrghw <1,2,3,0>, + 1148376878U, // <1,u,2,1>: Cost 2 vmrghw <1,2,3,0>, LHS + 1148371862U, // <1,u,2,2>: Cost 2 vmrghw <1,2,3,0>, <1,2,3,0> + 1225965724U, // <1,u,2,3>: Cost 2 vmrglw <3,0,1,2>, LHS + 2222118975U, // <1,u,2,4>: Cost 3 vmrghw <1,2,3,0>, + 1148377242U, // <1,u,2,5>: Cost 2 vmrghw <1,2,3,0>, RHS + 2687150010U, // <1,u,2,6>: Cost 3 vsldoi8 <0,4,1,u>, <2,6,3,7> + 1225968968U, // <1,u,2,7>: Cost 2 vmrglw <3,0,1,2>, RHS + 1148377445U, // <1,u,2,u>: Cost 2 vmrghw <1,2,3,0>, LHS + 471040156U, // <1,u,3,0>: Cost 1 vsldoi4 LHS, LHS + 1544782644U, // <1,u,3,1>: Cost 2 vsldoi4 LHS, <1,1,1,1> + 1544783464U, // <1,u,3,2>: Cost 2 vsldoi4 LHS, <2,2,2,2> + 1544784022U, // <1,u,3,3>: Cost 2 vsldoi4 LHS, <3,0,1,2> + 471043382U, // <1,u,3,4>: Cost 1 vsldoi4 LHS, RHS + 1592561668U, // <1,u,3,5>: Cost 2 vsldoi4 LHS, <5,5,5,5> + 1592562170U, // <1,u,3,6>: Cost 2 vsldoi4 LHS, <6,2,7,3> + 1592562682U, // <1,u,3,7>: Cost 2 vsldoi4 LHS, <7,0,1,2> + 471045934U, // <1,u,3,u>: Cost 1 vsldoi4 LHS, LHS + 2708384629U, // <1,u,4,0>: Cost 3 vsldoi8 <4,0,1,u>, <4,0,1,u> + 2687151101U, // <1,u,4,1>: Cost 3 vsldoi8 <0,4,1,u>, <4,1,u,0> + 2223408022U, // <1,u,4,2>: Cost 3 vmrghw <1,4,2,5>, <1,2,3,0> + 2283798684U, // <1,u,4,3>: Cost 3 vmrglw <0,3,1,4>, LHS + 2642422785U, // <1,u,4,4>: Cost 3 vsldoi4 <4,1,u,4>, <4,1,u,4> + 1613409590U, // <1,u,4,5>: Cost 2 vsldoi8 <0,4,1,u>, RHS + 2283801090U, // <1,u,4,6>: Cost 3 vmrglw <0,3,1,4>, <3,4,5,6> + 2283801928U, // <1,u,4,7>: Cost 3 vmrglw <0,3,1,4>, RHS + 1613409833U, // <1,u,4,u>: Cost 2 vsldoi8 <0,4,1,u>, RHS + 2284471235U, // <1,u,5,0>: Cost 3 vmrglw <0,4,1,5>, <1,2,u,0> + 2284472046U, // <1,u,5,1>: Cost 3 vmrglw <0,4,1,5>, <2,3,u,1> + 2284472533U, // <1,u,5,2>: Cost 3 vmrglw <0,4,1,5>, <3,0,u,2> + 1210728604U, // <1,u,5,3>: Cost 2 vmrglw <0,4,1,5>, LHS + 2284471239U, // <1,u,5,4>: Cost 3 vmrglw <0,4,1,5>, <1,2,u,4> + 1210728786U, // <1,u,5,5>: Cost 2 vmrglw <0,4,1,5>, <0,4,1,5> + 1683118234U, // <1,u,5,6>: Cost 2 vsldoi12 <0,u,1,1>, RHS + 1210731848U, // <1,u,5,7>: Cost 2 vmrglw <0,4,1,5>, RHS + 1210728609U, // <1,u,5,u>: Cost 2 vmrglw <0,4,1,5>, LHS + 2720330023U, // <1,u,6,0>: Cost 3 vsldoi8 <6,0,1,u>, <6,0,1,u> + 2757376190U, // <1,u,6,1>: Cost 3 vsldoi12 <0,u,u,1>, + 2726302202U, // <1,u,6,2>: Cost 3 vsldoi8 <7,0,1,u>, <6,2,7,3> + 2283151516U, // <1,u,6,3>: Cost 3 vmrglw <0,2,1,6>, LHS + 2224972114U, // <1,u,6,4>: Cost 3 vmrghw <1,6,5,7>, <0,4,1,5> + 2224683162U, // <1,u,6,5>: Cost 3 vmrghw <1,6,1,7>, RHS + 2726302520U, // <1,u,6,6>: Cost 3 vsldoi8 <7,0,1,u>, <6,6,6,6> + 2283154760U, // <1,u,6,7>: Cost 3 vmrglw <0,2,1,6>, RHS + 2283151521U, // <1,u,6,u>: Cost 3 vmrglw <0,2,1,6>, LHS + 1652560896U, // <1,u,7,0>: Cost 2 vsldoi8 <7,0,1,u>, <7,0,1,u> + 2333590225U, // <1,u,7,1>: Cost 3 vmrglw , <0,u,u,1> + 2765412628U, // <1,u,7,2>: Cost 3 vsldoi12 <2,3,0,1>, + 2291785884U, // <1,u,7,3>: Cost 3 vmrglw <1,6,1,7>, LHS + 2781042984U, // <1,u,7,4>: Cost 3 vsldoi12 <4,u,5,1>, + 3365527953U, // <1,u,7,5>: Cost 4 vmrglw <1,6,1,7>, <0,4,u,5> + 2791954748U, // <1,u,7,6>: Cost 3 vsldoi12 <6,7,0,1>, + 2291789128U, // <1,u,7,7>: Cost 3 vmrglw <1,6,1,7>, RHS + 1657869960U, // <1,u,7,u>: Cost 2 vsldoi8 <7,u,1,u>, <7,u,1,u> + 471081121U, // <1,u,u,0>: Cost 1 vsldoi4 LHS, LHS + 269271142U, // <1,u,u,1>: Cost 1 vspltisw1 LHS + 1544824424U, // <1,u,u,2>: Cost 2 vsldoi4 LHS, <2,2,2,2> + 1544824982U, // <1,u,u,3>: Cost 2 vsldoi4 LHS, <3,0,1,2> + 471084342U, // <1,u,u,4>: Cost 1 vsldoi4 LHS, RHS + 1613412506U, // <1,u,u,5>: Cost 2 vsldoi8 <0,4,1,u>, RHS + 1683118477U, // <1,u,u,6>: Cost 2 vsldoi12 <0,u,1,1>, RHS + 1210756424U, // <1,u,u,7>: Cost 2 vmrglw <0,4,1,u>, RHS + 471086894U, // <1,u,u,u>: Cost 1 vsldoi4 LHS, LHS + 2226757632U, // <2,0,0,0>: Cost 3 vmrghw <2,0,3,0>, <0,0,0,0> + 2226757734U, // <2,0,0,1>: Cost 3 vmrghw <2,0,3,0>, LHS + 3826622483U, // <2,0,0,2>: Cost 4 vsldoi12 <0,2,1,2>, <0,0,2,1> + 3843211292U, // <2,0,0,3>: Cost 4 vsldoi12 <3,0,1,2>, <0,0,3,1> + 3300499794U, // <2,0,0,4>: Cost 4 vmrghw <2,0,3,0>, <0,4,1,5> + 3356256724U, // <2,0,0,5>: Cost 4 vmrglw <0,1,2,0>, <3,4,0,5> + 3825664056U, // <2,0,0,6>: Cost 4 vsldoi12 <0,0,6,2>, <0,0,6,2> + 3762889289U, // <2,0,0,7>: Cost 4 vsldoi8 <0,7,2,0>, <0,7,2,0> + 2226758301U, // <2,0,0,u>: Cost 3 vmrghw <2,0,3,0>, LHS + 2227429386U, // <2,0,1,0>: Cost 3 vmrghw <2,1,3,1>, <0,0,1,1> + 2227429478U, // <2,0,1,1>: Cost 3 vmrghw <2,1,3,1>, LHS + 1691156582U, // <2,0,1,2>: Cost 2 vsldoi12 <2,2,2,2>, LHS + 2666358997U, // <2,0,1,3>: Cost 3 vsldoi4 , <3,0,u,2> + 2227462482U, // <2,0,1,4>: Cost 3 vmrghw <2,1,3,5>, <0,4,1,5> + 3722186464U, // <2,0,1,5>: Cost 4 vsldoi4 <5,2,0,1>, <5,2,0,1> + 3867099278U, // <2,0,1,6>: Cost 4 vsldoi12 <7,0,1,2>, <0,1,6,7> + 3366881912U, // <2,0,1,7>: Cost 4 vmrglw <1,u,2,1>, <3,6,0,7> + 1691156636U, // <2,0,1,u>: Cost 2 vsldoi12 <2,2,2,2>, LHS + 2228027392U, // <2,0,2,0>: Cost 3 vmrghw <2,2,2,2>, <0,0,0,0> + 1154285670U, // <2,0,2,1>: Cost 2 vmrghw <2,2,2,2>, LHS + 2228027565U, // <2,0,2,2>: Cost 3 vmrghw <2,2,2,2>, <0,2,1,2> + 3301769468U, // <2,0,2,3>: Cost 4 vmrghw <2,2,2,2>, <0,3,1,0> + 2228027730U, // <2,0,2,4>: Cost 3 vmrghw <2,2,2,2>, <0,4,1,5> + 3301769635U, // <2,0,2,5>: Cost 4 vmrghw <2,2,2,2>, <0,5,1,5> + 3780806586U, // <2,0,2,6>: Cost 4 vsldoi8 <3,7,2,0>, <2,6,3,7> + 3368880760U, // <2,0,2,7>: Cost 4 vmrglw <2,2,2,2>, <3,6,0,7> + 1154286237U, // <2,0,2,u>: Cost 2 vmrghw <2,2,2,2>, LHS + 1213440000U, // <2,0,3,0>: Cost 2 vmrglw LHS, <0,0,0,0> + 1213441702U, // <2,0,3,1>: Cost 2 vmrglw LHS, <2,3,0,1> + 2228535470U, // <2,0,3,2>: Cost 3 vmrghw <2,3,0,1>, <0,2,1,3> + 2636515632U, // <2,0,3,3>: Cost 3 vsldoi4 <3,2,0,3>, <3,2,0,3> + 2287182962U, // <2,0,3,4>: Cost 3 vmrglw LHS, <1,5,0,4> + 2660405346U, // <2,0,3,5>: Cost 3 vsldoi4 <7,2,0,3>, <5,6,7,0> + 2228535798U, // <2,0,3,6>: Cost 3 vmrghw <2,3,0,1>, <0,6,1,7> + 2660406420U, // <2,0,3,7>: Cost 3 vsldoi4 <7,2,0,3>, <7,2,0,3> + 1213441709U, // <2,0,3,u>: Cost 2 vmrglw LHS, <2,3,0,u> + 3368894464U, // <2,0,4,0>: Cost 4 vmrglw <2,2,2,4>, <0,0,0,0> + 2764898642U, // <2,0,4,1>: Cost 3 vsldoi12 <2,2,2,2>, <0,4,1,5> + 3826622811U, // <2,0,4,2>: Cost 4 vsldoi12 <0,2,1,2>, <0,4,2,5> + 3843211620U, // <2,0,4,3>: Cost 4 vsldoi12 <3,0,1,2>, <0,4,3,5> + 3838640493U, // <2,0,4,4>: Cost 4 vsldoi12 <2,2,2,2>, <0,4,4,5> + 2732944694U, // <2,0,4,5>: Cost 3 vsldoi8 , RHS + 3797396857U, // <2,0,4,6>: Cost 4 vsldoi8 <6,5,2,0>, <4,6,5,2> + 3867099528U, // <2,0,4,7>: Cost 4 vsldoi12 <7,0,1,2>, <0,4,7,5> + 2764898705U, // <2,0,4,u>: Cost 3 vsldoi12 <2,2,2,2>, <0,4,u,5> + 3364257792U, // <2,0,5,0>: Cost 4 vmrglw <1,4,2,5>, <0,0,0,0> + 2230124646U, // <2,0,5,1>: Cost 3 vmrghw <2,5,3,6>, LHS + 3304235184U, // <2,0,5,2>: Cost 4 vmrghw <2,5,u,6>, <0,2,1,5> + 3364260144U, // <2,0,5,3>: Cost 4 vmrglw <1,4,2,5>, <3,2,0,3> + 3303817554U, // <2,0,5,4>: Cost 4 vmrghw <2,5,3,0>, <0,4,1,5> + 3364260146U, // <2,0,5,5>: Cost 4 vmrglw <1,4,2,5>, <3,2,0,5> + 3867099602U, // <2,0,5,6>: Cost 4 vsldoi12 <7,0,1,2>, <0,5,6,7> + 3364260472U, // <2,0,5,7>: Cost 4 vmrglw <1,4,2,5>, <3,6,0,7> + 2230125213U, // <2,0,5,u>: Cost 3 vmrghw <2,5,3,6>, LHS + 2230796288U, // <2,0,6,0>: Cost 3 vmrghw <2,6,3,7>, <0,0,0,0> + 1157054566U, // <2,0,6,1>: Cost 2 vmrghw <2,6,3,7>, LHS + 2230796465U, // <2,0,6,2>: Cost 3 vmrghw <2,6,3,7>, <0,2,1,6> + 3304538364U, // <2,0,6,3>: Cost 4 vmrghw <2,6,3,7>, <0,3,1,0> + 2230796626U, // <2,0,6,4>: Cost 3 vmrghw <2,6,3,7>, <0,4,1,5> + 3797398205U, // <2,0,6,5>: Cost 4 vsldoi8 <6,5,2,0>, <6,5,2,0> + 3304538614U, // <2,0,6,6>: Cost 4 vmrghw <2,6,3,7>, <0,6,1,7> + 3798725471U, // <2,0,6,7>: Cost 4 vsldoi8 <6,7,2,0>, <6,7,2,0> + 1157055133U, // <2,0,6,u>: Cost 2 vmrghw <2,6,3,7>, LHS + 3371573248U, // <2,0,7,0>: Cost 4 vmrglw <2,6,2,7>, <0,0,0,0> + 2231189606U, // <2,0,7,1>: Cost 3 vmrghw <2,7,0,1>, LHS + 3801380003U, // <2,0,7,2>: Cost 4 vsldoi8 <7,2,2,0>, <7,2,2,0> + 3802043636U, // <2,0,7,3>: Cost 4 vsldoi8 <7,3,2,0>, <7,3,2,0> + 3806688614U, // <2,0,7,4>: Cost 4 vsldoi8 , <7,4,5,6> + 3356317308U, // <2,0,7,5>: Cost 4 vmrglw <0,1,2,7>, <7,u,0,5> + 3804034535U, // <2,0,7,6>: Cost 4 vsldoi8 <7,6,2,0>, <7,6,2,0> + 3806688876U, // <2,0,7,7>: Cost 4 vsldoi8 , <7,7,7,7> + 2231190173U, // <2,0,7,u>: Cost 3 vmrghw <2,7,0,1>, LHS + 1208836096U, // <2,0,u,0>: Cost 2 vmrglw LHS, <0,0,0,0> + 1208837798U, // <2,0,u,1>: Cost 2 vmrglw LHS, <2,3,0,1> + 1691157149U, // <2,0,u,2>: Cost 2 vsldoi12 <2,2,2,2>, LHS + 2636556597U, // <2,0,u,3>: Cost 3 vsldoi4 <3,2,0,u>, <3,2,0,u> + 2282579625U, // <2,0,u,4>: Cost 3 vmrglw LHS, <2,3,0,4> + 2660446306U, // <2,0,u,5>: Cost 3 vsldoi4 <7,2,0,u>, <5,6,7,0> + 2228535798U, // <2,0,u,6>: Cost 3 vmrghw <2,3,0,1>, <0,6,1,7> + 2660447385U, // <2,0,u,7>: Cost 3 vsldoi4 <7,2,0,u>, <7,2,0,u> + 1208837805U, // <2,0,u,u>: Cost 2 vmrglw LHS, <2,3,0,u> + 3692388523U, // <2,1,0,0>: Cost 4 vsldoi4 <0,2,1,0>, <0,2,1,0> + 2757526244U, // <2,1,0,1>: Cost 3 vsldoi12 <1,0,1,2>, <1,0,1,2> + 2330290974U, // <2,1,0,2>: Cost 3 vmrglw , <3,u,1,2> + 3843212020U, // <2,1,0,3>: Cost 4 vsldoi12 <3,0,1,2>, <1,0,3,0> + 3692391734U, // <2,1,0,4>: Cost 4 vsldoi4 <0,2,1,0>, RHS + 3300533362U, // <2,1,0,5>: Cost 4 vmrghw <2,0,3,4>, <1,5,0,4> + 3794084337U, // <2,1,0,6>: Cost 4 vsldoi8 <6,0,2,1>, <0,6,1,2> + 3374170614U, // <2,1,0,7>: Cost 5 vmrglw <3,1,2,0>, <0,6,1,7> + 2758042403U, // <2,1,0,u>: Cost 3 vsldoi12 <1,0,u,2>, <1,0,u,2> + 2690482924U, // <2,1,1,0>: Cost 3 vsldoi8 <1,0,2,1>, <1,0,2,1> + 2764899124U, // <2,1,1,1>: Cost 3 vsldoi12 <2,2,2,2>, <1,1,1,1> + 2695791510U, // <2,1,1,2>: Cost 3 vsldoi8 <1,u,2,1>, <1,2,3,0> + 3362235271U, // <2,1,1,3>: Cost 4 vmrglw <1,1,2,1>, <1,2,1,3> + 3692399926U, // <2,1,1,4>: Cost 4 vsldoi4 <0,2,1,1>, RHS + 3832226649U, // <2,1,1,5>: Cost 4 vsldoi12 <1,1,5,2>, <1,1,5,2> + 3301205235U, // <2,1,1,6>: Cost 4 vmrghw <2,1,3,5>, <1,6,5,7> + 3768870179U, // <2,1,1,7>: Cost 4 vsldoi8 <1,7,2,1>, <1,7,2,1> + 2695791988U, // <2,1,1,u>: Cost 3 vsldoi8 <1,u,2,1>, <1,u,2,1> + 2618663085U, // <2,1,2,0>: Cost 3 vsldoi4 <0,2,1,2>, <0,2,1,2> + 2228028212U, // <2,1,2,1>: Cost 3 vmrghw <2,2,2,2>, <1,1,1,1> + 2618664552U, // <2,1,2,2>: Cost 3 vsldoi4 <0,2,1,2>, <2,2,2,2> + 2759000984U, // <2,1,2,3>: Cost 3 vsldoi12 <1,2,3,2>, <1,2,3,2> + 2618666294U, // <2,1,2,4>: Cost 3 vsldoi4 <0,2,1,2>, RHS + 2295136594U, // <2,1,2,5>: Cost 3 vmrglw <2,2,2,2>, <0,4,1,5> + 3769534376U, // <2,1,2,6>: Cost 4 vsldoi8 <1,u,2,1>, <2,6,1,7> + 2793358266U, // <2,1,2,7>: Cost 3 vsldoi12 <7,0,1,2>, <1,2,7,0> + 2618668846U, // <2,1,2,u>: Cost 3 vsldoi4 <0,2,1,2>, LHS + 2282536969U, // <2,1,3,0>: Cost 3 vmrglw LHS, <0,0,1,0> + 1208795146U, // <2,1,3,1>: Cost 2 vmrglw LHS, <0,0,1,1> + 1213442198U, // <2,1,3,2>: Cost 2 vmrglw LHS, <3,0,1,2> + 2287181998U, // <2,1,3,3>: Cost 3 vmrglw LHS, <0,2,1,3> + 2618674486U, // <2,1,3,4>: Cost 3 vsldoi4 <0,2,1,3>, RHS + 1208795474U, // <2,1,3,5>: Cost 2 vmrglw LHS, <0,4,1,5> + 2287182001U, // <2,1,3,6>: Cost 3 vmrglw LHS, <0,2,1,6> + 2287183055U, // <2,1,3,7>: Cost 3 vmrglw LHS, <1,6,1,7> + 1208795153U, // <2,1,3,u>: Cost 2 vmrglw LHS, <0,0,1,u> + 3692421295U, // <2,1,4,0>: Cost 4 vsldoi4 <0,2,1,4>, <0,2,1,4> + 3838641195U, // <2,1,4,1>: Cost 4 vsldoi12 <2,2,2,2>, <1,4,1,5> + 2330323742U, // <2,1,4,2>: Cost 3 vmrglw , <3,u,1,2> + 3692423318U, // <2,1,4,3>: Cost 5 vsldoi4 <0,2,1,4>, <3,0,1,2> + 3692424502U, // <2,1,4,4>: Cost 4 vsldoi4 <0,2,1,4>, RHS + 2695793974U, // <2,1,4,5>: Cost 3 vsldoi8 <1,u,2,1>, RHS + 3799395705U, // <2,1,4,6>: Cost 4 vsldoi8 <6,u,2,1>, <4,6,5,2> + 3368895695U, // <2,1,4,7>: Cost 5 vmrglw <2,2,2,4>, <1,6,1,7> + 2695794217U, // <2,1,4,u>: Cost 3 vsldoi8 <1,u,2,1>, RHS + 3692429488U, // <2,1,5,0>: Cost 4 vsldoi4 <0,2,1,5>, <0,2,1,5> + 3364257802U, // <2,1,5,1>: Cost 4 vmrglw <1,4,2,5>, <0,0,1,1> + 3692431253U, // <2,1,5,2>: Cost 4 vsldoi4 <0,2,1,5>, <2,5,u,6> + 3692431874U, // <2,1,5,3>: Cost 4 vsldoi4 <0,2,1,5>, <3,4,5,6> + 3692432694U, // <2,1,5,4>: Cost 4 vsldoi4 <0,2,1,5>, RHS + 3364258130U, // <2,1,5,5>: Cost 4 vmrglw <1,4,2,5>, <0,4,1,5> + 3303875827U, // <2,1,5,6>: Cost 4 vmrghw <2,5,3,7>, <1,6,5,7> + 3867100333U, // <2,1,5,7>: Cost 4 vsldoi12 <7,0,1,2>, <1,5,7,0> + 3692435246U, // <2,1,5,u>: Cost 4 vsldoi4 <0,2,1,5>, LHS + 2618695857U, // <2,1,6,0>: Cost 3 vsldoi4 <0,2,1,6>, <0,2,1,6> + 2230797108U, // <2,1,6,1>: Cost 3 vmrghw <2,6,3,7>, <1,1,1,1> + 2618697658U, // <2,1,6,2>: Cost 3 vsldoi4 <0,2,1,6>, <2,6,3,7> + 3692439702U, // <2,1,6,3>: Cost 4 vsldoi4 <0,2,1,6>, <3,0,1,2> + 2618699062U, // <2,1,6,4>: Cost 3 vsldoi4 <0,2,1,6>, RHS + 3364929874U, // <2,1,6,5>: Cost 4 vmrglw <1,5,2,6>, <0,4,1,5> + 3692442424U, // <2,1,6,6>: Cost 4 vsldoi4 <0,2,1,6>, <6,6,6,6> + 3798733664U, // <2,1,6,7>: Cost 4 vsldoi8 <6,7,2,1>, <6,7,2,1> + 2618701614U, // <2,1,6,u>: Cost 3 vsldoi4 <0,2,1,6>, LHS + 3799397370U, // <2,1,7,0>: Cost 4 vsldoi8 <6,u,2,1>, <7,0,1,2> + 3371573258U, // <2,1,7,1>: Cost 4 vmrglw <2,6,2,7>, <0,0,1,1> + 2330351234U, // <2,1,7,2>: Cost 3 vmrglw , <7,u,1,2> + 3799397658U, // <2,1,7,3>: Cost 4 vsldoi8 <6,u,2,1>, <7,3,6,2> + 3799397734U, // <2,1,7,4>: Cost 4 vsldoi8 <6,u,2,1>, <7,4,5,6> + 3371573586U, // <2,1,7,5>: Cost 4 vmrglw <2,6,2,7>, <0,4,1,5> + 3799397870U, // <2,1,7,6>: Cost 4 vsldoi8 <6,u,2,1>, <7,6,2,7> + 3799397956U, // <2,1,7,7>: Cost 4 vsldoi8 <6,u,2,1>, <7,7,3,3> + 2330351234U, // <2,1,7,u>: Cost 3 vmrglw , <7,u,1,2> + 2282577929U, // <2,1,u,0>: Cost 3 vmrglw LHS, <0,0,1,0> + 1208836106U, // <2,1,u,1>: Cost 2 vmrglw LHS, <0,0,1,1> + 1208838294U, // <2,1,u,2>: Cost 2 vmrglw LHS, <3,0,1,2> + 2282578094U, // <2,1,u,3>: Cost 3 vmrglw LHS, <0,2,1,3> + 2282577933U, // <2,1,u,4>: Cost 3 vmrglw LHS, <0,0,1,4> + 1208836434U, // <2,1,u,5>: Cost 2 vmrglw LHS, <0,4,1,5> + 2282578097U, // <2,1,u,6>: Cost 3 vmrglw LHS, <0,2,1,6> + 2287224015U, // <2,1,u,7>: Cost 3 vmrglw LHS, <1,6,1,7> + 1208836113U, // <2,1,u,u>: Cost 2 vmrglw LHS, <0,0,1,u> + 2226759117U, // <2,2,0,0>: Cost 3 vmrghw <2,0,3,0>, <2,0,3,0> + 1624047718U, // <2,2,0,1>: Cost 2 vsldoi8 <2,2,2,2>, LHS + 2697789613U, // <2,2,0,2>: Cost 3 vsldoi8 <2,2,2,2>, <0,2,1,2> + 2226767526U, // <2,2,0,3>: Cost 3 vmrghw <2,0,3,1>, <2,3,0,1> + 2697789778U, // <2,2,0,4>: Cost 3 vsldoi8 <2,2,2,2>, <0,4,1,5> + 3300657000U, // <2,2,0,5>: Cost 4 vmrghw <2,0,5,1>, <2,5,3,6> + 2226988986U, // <2,2,0,6>: Cost 3 vmrghw <2,0,6,1>, <2,6,3,7> + 3734271139U, // <2,2,0,7>: Cost 4 vsldoi4 <7,2,2,0>, <7,2,2,0> + 1624048285U, // <2,2,0,u>: Cost 2 vsldoi8 <2,2,2,2>, LHS + 3831268868U, // <2,2,1,0>: Cost 4 vsldoi12 <1,0,1,2>, <2,1,0,1> + 2293138804U, // <2,2,1,1>: Cost 3 vmrglw <1,u,2,1>, <1,u,2,1> + 2697790358U, // <2,2,1,2>: Cost 3 vsldoi8 <2,2,2,2>, <1,2,3,0> + 2293137510U, // <2,2,1,3>: Cost 3 vmrglw <1,u,2,1>, LHS + 3771532331U, // <2,2,1,4>: Cost 4 vsldoi8 <2,2,2,2>, <1,4,1,5> + 3767551106U, // <2,2,1,5>: Cost 4 vsldoi8 <1,5,2,2>, <1,5,2,2> + 3301173178U, // <2,2,1,6>: Cost 4 vmrghw <2,1,3,1>, <2,6,3,7> + 3372853169U, // <2,2,1,7>: Cost 4 vmrglw <2,u,2,1>, <2,6,2,7> + 2293137515U, // <2,2,1,u>: Cost 3 vmrglw <1,u,2,1>, LHS + 1556938854U, // <2,2,2,0>: Cost 2 vsldoi4 <2,2,2,2>, LHS + 2295137733U, // <2,2,2,1>: Cost 3 vmrglw <2,2,2,2>, <2,0,2,1> + 336380006U, // <2,2,2,2>: Cost 1 vspltisw2 LHS + 1221394534U, // <2,2,2,3>: Cost 2 vmrglw <2,2,2,2>, LHS + 1556942134U, // <2,2,2,4>: Cost 2 vsldoi4 <2,2,2,2>, RHS + 2295138061U, // <2,2,2,5>: Cost 3 vmrglw <2,2,2,2>, <2,4,2,5> + 2228029370U, // <2,2,2,6>: Cost 3 vmrghw <2,2,2,2>, <2,6,3,7> + 2660545701U, // <2,2,2,7>: Cost 3 vsldoi4 <7,2,2,2>, <7,2,2,2> + 336380006U, // <2,2,2,u>: Cost 1 vspltisw2 LHS + 2697791638U, // <2,2,3,0>: Cost 3 vsldoi8 <2,2,2,2>, <3,0,1,2> + 2765489840U, // <2,2,3,1>: Cost 3 vsldoi12 <2,3,1,2>, <2,3,1,2> + 1213441640U, // <2,2,3,2>: Cost 2 vmrglw LHS, <2,2,2,2> + 135053414U, // <2,2,3,3>: Cost 1 vmrglw LHS, LHS + 2697792002U, // <2,2,3,4>: Cost 3 vsldoi8 <2,2,2,2>, <3,4,5,6> + 2330313780U, // <2,2,3,5>: Cost 3 vmrglw LHS, <1,4,2,5> + 2287183549U, // <2,2,3,6>: Cost 3 vmrglw LHS, <2,3,2,6> + 2660553894U, // <2,2,3,7>: Cost 3 vsldoi4 <7,2,2,3>, <7,2,2,3> + 135053419U, // <2,2,3,u>: Cost 1 vmrglw LHS, LHS + 2630697062U, // <2,2,4,0>: Cost 3 vsldoi4 <2,2,2,4>, LHS + 3771534282U, // <2,2,4,1>: Cost 4 vsldoi8 <2,2,2,2>, <4,1,2,3> + 2764900109U, // <2,2,4,2>: Cost 3 vsldoi12 <2,2,2,2>, <2,4,2,5> + 2295152742U, // <2,2,4,3>: Cost 3 vmrglw <2,2,2,4>, LHS + 2295154282U, // <2,2,4,4>: Cost 3 vmrglw <2,2,2,4>, <2,2,2,4> + 1624050998U, // <2,2,4,5>: Cost 2 vsldoi8 <2,2,2,2>, RHS + 2229675962U, // <2,2,4,6>: Cost 3 vmrghw <2,4,6,5>, <2,6,3,7> + 3368896433U, // <2,2,4,7>: Cost 4 vmrglw <2,2,2,4>, <2,6,2,7> + 1624051241U, // <2,2,4,u>: Cost 2 vsldoi8 <2,2,2,2>, RHS + 3771534920U, // <2,2,5,0>: Cost 4 vsldoi8 <2,2,2,2>, <5,0,1,2> + 3364258540U, // <2,2,5,1>: Cost 4 vmrglw <1,4,2,5>, <1,0,2,1> + 2296489576U, // <2,2,5,2>: Cost 3 vmrglw <2,4,2,5>, <2,2,2,2> + 2290516070U, // <2,2,5,3>: Cost 3 vmrglw <1,4,2,5>, LHS + 3771535284U, // <2,2,5,4>: Cost 4 vsldoi8 <2,2,2,2>, <5,4,5,6> + 2290517044U, // <2,2,5,5>: Cost 3 vmrglw <1,4,2,5>, <1,4,2,5> + 2697793634U, // <2,2,5,6>: Cost 3 vsldoi8 <2,2,2,2>, <5,6,7,0> + 3370231729U, // <2,2,5,7>: Cost 4 vmrglw <2,4,2,5>, <2,6,2,7> + 2290516075U, // <2,2,5,u>: Cost 3 vmrglw <1,4,2,5>, LHS + 2230797801U, // <2,2,6,0>: Cost 3 vmrghw <2,6,3,7>, <2,0,6,1> + 3304539679U, // <2,2,6,1>: Cost 4 vmrghw <2,6,3,7>, <2,1,3,1> + 2764900273U, // <2,2,6,2>: Cost 3 vsldoi12 <2,2,2,2>, <2,6,2,7> + 2764900282U, // <2,2,6,3>: Cost 3 vsldoi12 <2,2,2,2>, <2,6,3,7> + 2230798129U, // <2,2,6,4>: Cost 3 vmrghw <2,6,3,7>, <2,4,6,5> + 3304540008U, // <2,2,6,5>: Cost 4 vmrghw <2,6,3,7>, <2,5,3,6> + 1157056442U, // <2,2,6,6>: Cost 2 vmrghw <2,6,3,7>, <2,6,3,7> + 2725000033U, // <2,2,6,7>: Cost 3 vsldoi8 <6,7,2,2>, <6,7,2,2> + 1157056442U, // <2,2,6,u>: Cost 2 vmrghw <2,6,3,7>, <2,6,3,7> + 2793359338U, // <2,2,7,0>: Cost 3 vsldoi12 <7,0,1,2>, <2,7,0,1> + 3371574725U, // <2,2,7,1>: Cost 4 vmrglw <2,6,2,7>, <2,0,2,1> + 2297833064U, // <2,2,7,2>: Cost 3 vmrglw <2,6,2,7>, <2,2,2,2> + 2297831526U, // <2,2,7,3>: Cost 3 vmrglw <2,6,2,7>, LHS + 2697794918U, // <2,2,7,4>: Cost 3 vsldoi8 <2,2,2,2>, <7,4,5,6> + 3371575053U, // <2,2,7,5>: Cost 4 vmrglw <2,6,2,7>, <2,4,2,5> + 3304933297U, // <2,2,7,6>: Cost 4 vmrghw <2,7,0,1>, <2,6,2,7> + 2297833393U, // <2,2,7,7>: Cost 3 vmrglw <2,6,2,7>, <2,6,2,7> + 2297831531U, // <2,2,7,u>: Cost 3 vmrglw <2,6,2,7>, LHS + 1556938854U, // <2,2,u,0>: Cost 2 vsldoi4 <2,2,2,2>, LHS + 1624053550U, // <2,2,u,1>: Cost 2 vsldoi8 <2,2,2,2>, LHS + 336380006U, // <2,2,u,2>: Cost 1 vspltisw2 LHS + 135094374U, // <2,2,u,3>: Cost 1 vmrglw LHS, LHS + 1556942134U, // <2,2,u,4>: Cost 2 vsldoi4 <2,2,2,2>, RHS + 1624053914U, // <2,2,u,5>: Cost 2 vsldoi8 <2,2,2,2>, RHS + 1157056442U, // <2,2,u,6>: Cost 2 vmrghw <2,6,3,7>, <2,6,3,7> + 2660594859U, // <2,2,u,7>: Cost 3 vsldoi4 <7,2,2,u>, <7,2,2,u> + 135094379U, // <2,2,u,u>: Cost 1 vmrglw LHS, LHS + 1611448320U, // <2,3,0,0>: Cost 2 vsldoi8 LHS, <0,0,0,0> + 537706598U, // <2,3,0,1>: Cost 1 vsldoi8 LHS, LHS + 2689835181U, // <2,3,0,2>: Cost 3 vsldoi8 LHS, <0,2,1,2> + 2689835260U, // <2,3,0,3>: Cost 3 vsldoi8 LHS, <0,3,1,0> + 1611448658U, // <2,3,0,4>: Cost 2 vsldoi8 LHS, <0,4,1,5> + 2732966354U, // <2,3,0,5>: Cost 3 vsldoi8 LHS, <0,5,6,7> + 2732966390U, // <2,3,0,6>: Cost 3 vsldoi8 LHS, <0,6,1,7> + 2660603052U, // <2,3,0,7>: Cost 3 vsldoi4 <7,2,3,0>, <7,2,3,0> + 537707165U, // <2,3,0,u>: Cost 1 vsldoi8 LHS, LHS + 2689835748U, // <2,3,1,0>: Cost 3 vsldoi8 LHS, <1,0,1,2> + 1611449140U, // <2,3,1,1>: Cost 2 vsldoi8 LHS, <1,1,1,1> + 1611449238U, // <2,3,1,2>: Cost 2 vsldoi8 LHS, <1,2,3,0> + 3763577805U, // <2,3,1,3>: Cost 4 vsldoi8 LHS, <1,3,0,1> + 2689836112U, // <2,3,1,4>: Cost 3 vsldoi8 LHS, <1,4,5,6> + 2689836143U, // <2,3,1,5>: Cost 3 vsldoi8 LHS, <1,5,0,1> + 2689836239U, // <2,3,1,6>: Cost 3 vsldoi8 LHS, <1,6,1,7> + 3366881210U, // <2,3,1,7>: Cost 4 vmrglw <1,u,2,1>, <2,6,3,7> + 1616094588U, // <2,3,1,u>: Cost 2 vsldoi8 LHS, <1,u,3,0> + 2689836493U, // <2,3,2,0>: Cost 3 vsldoi8 LHS, <2,0,3,0> + 2685191711U, // <2,3,2,1>: Cost 3 vsldoi8 LHS, <2,1,3,1> + 1611449960U, // <2,3,2,2>: Cost 2 vsldoi8 LHS, <2,2,2,2> + 1611450022U, // <2,3,2,3>: Cost 2 vsldoi8 LHS, <2,3,0,1> + 2689836822U, // <2,3,2,4>: Cost 3 vsldoi8 LHS, <2,4,3,5> + 2689836904U, // <2,3,2,5>: Cost 3 vsldoi8 LHS, <2,5,3,6> + 1611450298U, // <2,3,2,6>: Cost 2 vsldoi8 LHS, <2,6,3,7> + 2295138234U, // <2,3,2,7>: Cost 3 vmrglw <2,2,2,2>, <2,6,3,7> + 1611450456U, // <2,3,2,u>: Cost 2 vsldoi8 LHS, <2,u,3,3> + 1213440918U, // <2,3,3,0>: Cost 2 vmrglw LHS, <1,2,3,0> + 2282538527U, // <2,3,3,1>: Cost 3 vmrglw LHS, <2,1,3,1> + 1557022322U, // <2,3,3,2>: Cost 2 vsldoi4 <2,2,3,3>, <2,2,3,3> + 1208796786U, // <2,3,3,3>: Cost 2 vmrglw LHS, <2,2,3,3> + 1213440922U, // <2,3,3,4>: Cost 2 vmrglw LHS, <1,2,3,4> + 2282538531U, // <2,3,3,5>: Cost 3 vmrglw LHS, <2,1,3,5> + 2287188094U, // <2,3,3,6>: Cost 3 vmrglw LHS, + 1213441978U, // <2,3,3,7>: Cost 2 vmrglw LHS, <2,6,3,7> + 1208796791U, // <2,3,3,u>: Cost 2 vmrglw LHS, <2,2,3,u> + 1551056998U, // <2,3,4,0>: Cost 2 vsldoi4 <1,2,3,4>, LHS + 1551057818U, // <2,3,4,1>: Cost 2 vsldoi4 <1,2,3,4>, <1,2,3,4> + 2624800360U, // <2,3,4,2>: Cost 3 vsldoi4 <1,2,3,4>, <2,2,2,2> + 2624800918U, // <2,3,4,3>: Cost 3 vsldoi4 <1,2,3,4>, <3,0,1,2> + 1551060278U, // <2,3,4,4>: Cost 2 vsldoi4 <1,2,3,4>, RHS + 537709878U, // <2,3,4,5>: Cost 1 vsldoi8 LHS, RHS + 2732969337U, // <2,3,4,6>: Cost 3 vsldoi8 LHS, <4,6,5,2> + 2660635824U, // <2,3,4,7>: Cost 3 vsldoi4 <7,2,3,4>, <7,2,3,4> + 537710121U, // <2,3,4,u>: Cost 1 vsldoi8 LHS, RHS + 2689838664U, // <2,3,5,0>: Cost 3 vsldoi8 LHS, <5,0,1,2> + 2732969615U, // <2,3,5,1>: Cost 3 vsldoi8 LHS, <5,1,0,1> + 2732969707U, // <2,3,5,2>: Cost 3 vsldoi8 LHS, <5,2,1,3> + 3763580721U, // <2,3,5,3>: Cost 4 vsldoi8 LHS, <5,3,0,1> + 2689839028U, // <2,3,5,4>: Cost 3 vsldoi8 LHS, <5,4,5,6> + 1659228164U, // <2,3,5,5>: Cost 2 vsldoi8 LHS, <5,5,5,5> + 1659228258U, // <2,3,5,6>: Cost 2 vsldoi8 LHS, <5,6,7,0> + 3364259770U, // <2,3,5,7>: Cost 4 vmrglw <1,4,2,5>, <2,6,3,7> + 1659228420U, // <2,3,5,u>: Cost 2 vsldoi8 LHS, <5,u,7,0> + 2230798486U, // <2,3,6,0>: Cost 3 vmrghw <2,6,3,7>, <3,0,1,2> + 2732970407U, // <2,3,6,1>: Cost 3 vsldoi8 LHS, <6,1,7,1> + 1659228666U, // <2,3,6,2>: Cost 2 vsldoi8 LHS, <6,2,7,3> + 2230798748U, // <2,3,6,3>: Cost 3 vmrghw <2,6,3,7>, <3,3,3,3> + 2230798850U, // <2,3,6,4>: Cost 3 vmrghw <2,6,3,7>, <3,4,5,6> + 2732970731U, // <2,3,6,5>: Cost 3 vsldoi8 LHS, <6,5,7,1> + 1659228984U, // <2,3,6,6>: Cost 2 vsldoi8 LHS, <6,6,6,6> + 1659229006U, // <2,3,6,7>: Cost 2 vsldoi8 LHS, <6,7,0,1> + 1659229087U, // <2,3,6,u>: Cost 2 vsldoi8 LHS, <6,u,0,1> + 1659229178U, // <2,3,7,0>: Cost 2 vsldoi8 LHS, <7,0,1,2> + 2726999125U, // <2,3,7,1>: Cost 3 vsldoi8 <7,1,2,3>, <7,1,2,3> + 2727662758U, // <2,3,7,2>: Cost 3 vsldoi8 <7,2,2,3>, <7,2,2,3> + 2732971235U, // <2,3,7,3>: Cost 3 vsldoi8 LHS, <7,3,0,1> + 1659229542U, // <2,3,7,4>: Cost 2 vsldoi8 LHS, <7,4,5,6> + 2732971446U, // <2,3,7,5>: Cost 3 vsldoi8 LHS, <7,5,5,5> + 2732971484U, // <2,3,7,6>: Cost 3 vsldoi8 LHS, <7,6,0,7> + 1659229804U, // <2,3,7,7>: Cost 2 vsldoi8 LHS, <7,7,7,7> + 1659229826U, // <2,3,7,u>: Cost 2 vsldoi8 LHS, <7,u,1,2> + 1208837014U, // <2,3,u,0>: Cost 2 vmrglw LHS, <1,2,3,0> + 537712430U, // <2,3,u,1>: Cost 1 vsldoi8 LHS, LHS + 1616099205U, // <2,3,u,2>: Cost 2 vsldoi8 LHS, + 1208837746U, // <2,3,u,3>: Cost 2 vmrglw LHS, <2,2,3,3> + 1208837018U, // <2,3,u,4>: Cost 2 vmrglw LHS, <1,2,3,4> + 537712794U, // <2,3,u,5>: Cost 1 vsldoi8 LHS, RHS + 1616099536U, // <2,3,u,6>: Cost 2 vsldoi8 LHS, + 1208838074U, // <2,3,u,7>: Cost 2 vmrglw LHS, <2,6,3,7> + 537712997U, // <2,3,u,u>: Cost 1 vsldoi8 LHS, LHS + 3771547648U, // <2,4,0,0>: Cost 4 vsldoi8 <2,2,2,4>, <0,0,0,0> + 2697805926U, // <2,4,0,1>: Cost 3 vsldoi8 <2,2,2,4>, LHS + 3770884269U, // <2,4,0,2>: Cost 4 vsldoi8 <2,1,2,4>, <0,2,1,2> + 3806716164U, // <2,4,0,3>: Cost 4 vsldoi8 , <0,3,1,u> + 3771547986U, // <2,4,0,4>: Cost 4 vsldoi8 <2,2,2,4>, <0,4,1,5> + 2226761014U, // <2,4,0,5>: Cost 3 vmrghw <2,0,3,0>, RHS + 3853462427U, // <2,4,0,6>: Cost 4 vsldoi12 <4,6,5,2>, <4,0,6,1> + 3867102116U, // <2,4,0,7>: Cost 4 vsldoi12 <7,0,1,2>, <4,0,7,1> + 2226761257U, // <2,4,0,u>: Cost 3 vmrghw <2,0,3,0>, RHS + 3849186231U, // <2,4,1,0>: Cost 4 vsldoi12 <4,0,1,2>, <4,1,0,2> + 3301207010U, // <2,4,1,1>: Cost 4 vmrghw <2,1,3,5>, <4,1,5,0> + 3766240150U, // <2,4,1,2>: Cost 4 vsldoi8 <1,3,2,4>, <1,2,3,0> + 3766240226U, // <2,4,1,3>: Cost 4 vsldoi8 <1,3,2,4>, <1,3,2,4> + 3301207248U, // <2,4,1,4>: Cost 4 vmrghw <2,1,3,5>, <4,4,4,4> + 2227432758U, // <2,4,1,5>: Cost 3 vmrghw <2,1,3,1>, RHS + 3758941400U, // <2,4,1,6>: Cost 4 vsldoi8 <0,1,2,4>, <1,6,2,7> + 3768894758U, // <2,4,1,7>: Cost 4 vsldoi8 <1,7,2,4>, <1,7,2,4> + 2227433001U, // <2,4,1,u>: Cost 3 vmrghw <2,1,3,1>, RHS + 2228030354U, // <2,4,2,0>: Cost 3 vmrghw <2,2,2,2>, <4,0,5,1> + 3770885657U, // <2,4,2,1>: Cost 4 vsldoi8 <2,1,2,4>, <2,1,2,4> + 2697807466U, // <2,4,2,2>: Cost 3 vsldoi8 <2,2,2,4>, <2,2,2,4> + 3368880468U, // <2,4,2,3>: Cost 4 vmrglw <2,2,2,2>, <3,2,4,3> + 2228030672U, // <2,4,2,4>: Cost 3 vmrghw <2,2,2,2>, <4,4,4,4> + 1154288950U, // <2,4,2,5>: Cost 2 vmrghw <2,2,2,2>, RHS + 3771549617U, // <2,4,2,6>: Cost 4 vsldoi8 <2,2,2,4>, <2,6,2,7> + 3368880796U, // <2,4,2,7>: Cost 4 vmrglw <2,2,2,2>, <3,6,4,7> + 1154289193U, // <2,4,2,u>: Cost 2 vmrghw <2,2,2,2>, RHS + 2636808294U, // <2,4,3,0>: Cost 3 vsldoi4 <3,2,4,3>, LHS + 2287181861U, // <2,4,3,1>: Cost 3 vmrglw LHS, <0,0,4,1> + 2228866102U, // <2,4,3,2>: Cost 3 vmrghw <2,3,4,5>, <4,2,5,3> + 2636810580U, // <2,4,3,3>: Cost 3 vsldoi4 <3,2,4,3>, <3,2,4,3> + 1256574160U, // <2,4,3,4>: Cost 2 vmrglw LHS, <4,4,4,4> + 1213441742U, // <2,4,3,5>: Cost 2 vmrglw LHS, <2,3,4,5> + 2228866430U, // <2,4,3,6>: Cost 3 vmrghw <2,3,4,5>, <4,6,5,7> + 2660701368U, // <2,4,3,7>: Cost 3 vsldoi4 <7,2,4,3>, <7,2,4,3> + 1213441745U, // <2,4,3,u>: Cost 2 vmrglw LHS, <2,3,4,u> + 3704586342U, // <2,4,4,0>: Cost 4 vsldoi4 <2,2,4,4>, LHS + 3782831051U, // <2,4,4,1>: Cost 4 vsldoi8 <4,1,2,4>, <4,1,2,4> + 3704587900U, // <2,4,4,2>: Cost 4 vsldoi4 <2,2,4,4>, <2,2,4,4> + 3368896123U, // <2,4,4,3>: Cost 4 vmrglw <2,2,2,4>, <2,2,4,3> + 2793360592U, // <2,4,4,4>: Cost 3 vsldoi12 <7,0,1,2>, <4,4,4,4> + 2697809206U, // <2,4,4,5>: Cost 3 vsldoi8 <2,2,2,4>, RHS + 3303198078U, // <2,4,4,6>: Cost 4 vmrghw <2,4,3,5>, <4,6,5,7> + 3867102444U, // <2,4,4,7>: Cost 4 vsldoi12 <7,0,1,2>, <4,4,7,5> + 2697809449U, // <2,4,4,u>: Cost 3 vsldoi8 <2,2,2,4>, RHS + 2630852710U, // <2,4,5,0>: Cost 3 vsldoi4 <2,2,4,5>, LHS + 2624881572U, // <2,4,5,1>: Cost 3 vsldoi4 <1,2,4,5>, <1,2,4,5> + 2630854269U, // <2,4,5,2>: Cost 3 vsldoi4 <2,2,4,5>, <2,2,4,5> + 2666686677U, // <2,4,5,3>: Cost 3 vsldoi4 , <3,0,u,2> + 2630855990U, // <2,4,5,4>: Cost 3 vsldoi4 <2,2,4,5>, RHS + 2230127926U, // <2,4,5,5>: Cost 3 vmrghw <2,5,3,6>, RHS + 1691159862U, // <2,4,5,6>: Cost 2 vsldoi12 <2,2,2,2>, RHS + 3867102520U, // <2,4,5,7>: Cost 4 vsldoi12 <7,0,1,2>, <4,5,7,0> + 1691159880U, // <2,4,5,u>: Cost 2 vsldoi12 <2,2,2,2>, RHS + 2230799250U, // <2,4,6,0>: Cost 3 vmrghw <2,6,3,7>, <4,0,5,1> + 3304541130U, // <2,4,6,1>: Cost 4 vmrghw <2,6,3,7>, <4,1,2,3> + 2230799417U, // <2,4,6,2>: Cost 3 vmrghw <2,6,3,7>, <4,2,5,6> + 3304541323U, // <2,4,6,3>: Cost 4 vmrghw <2,6,3,7>, <4,3,5,7> + 2230799568U, // <2,4,6,4>: Cost 3 vmrghw <2,6,3,7>, <4,4,4,4> + 1157057846U, // <2,4,6,5>: Cost 2 vmrghw <2,6,3,7>, RHS + 3304541566U, // <2,4,6,6>: Cost 4 vmrghw <2,6,3,7>, <4,6,5,7> + 3798758243U, // <2,4,6,7>: Cost 4 vsldoi8 <6,7,2,4>, <6,7,2,4> + 1157058089U, // <2,4,6,u>: Cost 2 vmrghw <2,6,3,7>, RHS + 3806721018U, // <2,4,7,0>: Cost 4 vsldoi8 , <7,0,1,2> + 3853831590U, // <2,4,7,1>: Cost 4 vsldoi12 <4,7,1,2>, <4,7,1,2> + 3801412775U, // <2,4,7,2>: Cost 4 vsldoi8 <7,2,2,4>, <7,2,2,4> + 3802076408U, // <2,4,7,3>: Cost 4 vsldoi8 <7,3,2,4>, <7,3,2,4> + 3401436368U, // <2,4,7,4>: Cost 4 vmrglw <7,6,2,7>, <4,4,4,4> + 2793360840U, // <2,4,7,5>: Cost 3 vsldoi12 <7,0,1,2>, <4,7,5,0> + 3804067307U, // <2,4,7,6>: Cost 4 vsldoi8 <7,6,2,4>, <7,6,2,4> + 3867102682U, // <2,4,7,7>: Cost 4 vsldoi12 <7,0,1,2>, <4,7,7,0> + 2793360867U, // <2,4,7,u>: Cost 3 vsldoi12 <7,0,1,2>, <4,7,u,0> + 2630877286U, // <2,4,u,0>: Cost 3 vsldoi4 <2,2,4,u>, LHS + 2282580144U, // <2,4,u,1>: Cost 3 vmrglw LHS, <3,0,4,1> + 2630878848U, // <2,4,u,2>: Cost 3 vsldoi4 <2,2,4,u>, <2,2,4,u> + 2636851545U, // <2,4,u,3>: Cost 3 vsldoi4 <3,2,4,u>, <3,2,4,u> + 1256615120U, // <2,4,u,4>: Cost 2 vmrglw LHS, <4,4,4,4> + 1208837838U, // <2,4,u,5>: Cost 2 vmrglw LHS, <2,3,4,5> + 1691160105U, // <2,4,u,6>: Cost 2 vsldoi12 <2,2,2,2>, RHS + 2660742333U, // <2,4,u,7>: Cost 3 vsldoi4 <7,2,4,u>, <7,2,4,u> + 1208837841U, // <2,4,u,u>: Cost 2 vmrglw LHS, <2,3,4,u> + 3766910976U, // <2,5,0,0>: Cost 4 vsldoi8 <1,4,2,5>, <0,0,0,0> + 2693169254U, // <2,5,0,1>: Cost 3 vsldoi8 <1,4,2,5>, LHS + 3760939181U, // <2,5,0,2>: Cost 4 vsldoi8 <0,4,2,5>, <0,2,1,2> + 3843214936U, // <2,5,0,3>: Cost 4 vsldoi12 <3,0,1,2>, <5,0,3,0> + 3760939355U, // <2,5,0,4>: Cost 4 vsldoi8 <0,4,2,5>, <0,4,2,5> + 3867102827U, // <2,5,0,5>: Cost 4 vsldoi12 <7,0,1,2>, <5,0,5,1> + 3867102836U, // <2,5,0,6>: Cost 4 vsldoi12 <7,0,1,2>, <5,0,6,1> + 3867102844U, // <2,5,0,7>: Cost 4 vsldoi12 <7,0,1,2>, <5,0,7,0> + 2693169821U, // <2,5,0,u>: Cost 3 vsldoi8 <1,4,2,5>, LHS + 3766911724U, // <2,5,1,0>: Cost 4 vsldoi8 <1,4,2,5>, <1,0,2,1> + 3766911796U, // <2,5,1,1>: Cost 4 vsldoi8 <1,4,2,5>, <1,1,1,1> + 2693170070U, // <2,5,1,2>: Cost 3 vsldoi8 <1,4,2,5>, <1,2,3,0> + 3384798262U, // <2,5,1,3>: Cost 4 vmrglw <4,u,2,1>, <4,2,5,3> + 2693170228U, // <2,5,1,4>: Cost 3 vsldoi8 <1,4,2,5>, <1,4,2,5> + 3301208068U, // <2,5,1,5>: Cost 4 vmrghw <2,1,3,5>, <5,5,5,5> + 3366879607U, // <2,5,1,6>: Cost 4 vmrglw <1,u,2,1>, <0,4,5,6> + 3867102925U, // <2,5,1,7>: Cost 4 vsldoi12 <7,0,1,2>, <5,1,7,0> + 2695824760U, // <2,5,1,u>: Cost 3 vsldoi8 <1,u,2,5>, <1,u,2,5> + 2642845798U, // <2,5,2,0>: Cost 3 vsldoi4 <4,2,5,2>, LHS + 2295139218U, // <2,5,2,1>: Cost 3 vmrglw <2,2,2,2>, <4,0,5,1> + 2699142760U, // <2,5,2,2>: Cost 3 vsldoi8 <2,4,2,5>, <2,2,2,2> + 3766912678U, // <2,5,2,3>: Cost 4 vsldoi8 <1,4,2,5>, <2,3,0,1> + 2699142925U, // <2,5,2,4>: Cost 3 vsldoi8 <2,4,2,5>, <2,4,2,5> + 2228031492U, // <2,5,2,5>: Cost 3 vmrghw <2,2,2,2>, <5,5,5,5> + 2295138818U, // <2,5,2,6>: Cost 3 vmrglw <2,2,2,2>, <3,4,5,6> + 3368879347U, // <2,5,2,7>: Cost 4 vmrglw <2,2,2,2>, <1,6,5,7> + 2295138820U, // <2,5,2,u>: Cost 3 vmrglw <2,2,2,2>, <3,4,5,u> + 2287184866U, // <2,5,3,0>: Cost 3 vmrglw LHS, <4,1,5,0> + 1256573842U, // <2,5,3,1>: Cost 2 vmrglw LHS, <4,0,5,1> + 2642855630U, // <2,5,3,2>: Cost 3 vsldoi4 <4,2,5,3>, <2,3,4,5> + 2287182763U, // <2,5,3,3>: Cost 3 vmrglw LHS, <1,2,5,3> + 2287184870U, // <2,5,3,4>: Cost 3 vmrglw LHS, <4,1,5,4> + 1256574170U, // <2,5,3,5>: Cost 2 vmrglw LHS, <4,4,5,5> + 1213442562U, // <2,5,3,6>: Cost 2 vmrglw LHS, <3,4,5,6> + 2287183091U, // <2,5,3,7>: Cost 3 vmrglw LHS, <1,6,5,7> + 1213442564U, // <2,5,3,u>: Cost 2 vmrglw LHS, <3,4,5,u> + 3716604006U, // <2,5,4,0>: Cost 4 vsldoi4 <4,2,5,4>, LHS + 3716604822U, // <2,5,4,1>: Cost 4 vsldoi4 <4,2,5,4>, <1,2,3,0> + 3766914099U, // <2,5,4,2>: Cost 4 vsldoi8 <1,4,2,5>, <4,2,5,0> + 3368895403U, // <2,5,4,3>: Cost 5 vmrglw <2,2,2,4>, <1,2,5,3> + 3716607031U, // <2,5,4,4>: Cost 4 vsldoi4 <4,2,5,4>, <4,2,5,4> + 2693172534U, // <2,5,4,5>: Cost 3 vsldoi8 <1,4,2,5>, RHS + 3363588610U, // <2,5,4,6>: Cost 4 vmrglw <1,3,2,4>, <3,4,5,6> + 3368895731U, // <2,5,4,7>: Cost 5 vmrglw <2,2,2,4>, <1,6,5,7> + 2693172777U, // <2,5,4,u>: Cost 3 vsldoi8 <1,4,2,5>, RHS + 3704668262U, // <2,5,5,0>: Cost 4 vsldoi4 <2,2,5,5>, LHS + 3704669078U, // <2,5,5,1>: Cost 4 vsldoi4 <2,2,5,5>, <1,2,3,0> + 3704669830U, // <2,5,5,2>: Cost 4 vsldoi4 <2,2,5,5>, <2,2,5,5> + 3364259460U, // <2,5,5,3>: Cost 4 vmrglw <1,4,2,5>, <2,2,5,3> + 3704671542U, // <2,5,5,4>: Cost 4 vsldoi4 <2,2,5,5>, RHS + 2793361412U, // <2,5,5,5>: Cost 3 vsldoi12 <7,0,1,2>, <5,5,5,5> + 3364258167U, // <2,5,5,6>: Cost 4 vmrglw <1,4,2,5>, <0,4,5,6> + 3867103249U, // <2,5,5,7>: Cost 4 vsldoi12 <7,0,1,2>, <5,5,7,0> + 2793361412U, // <2,5,5,u>: Cost 3 vsldoi12 <7,0,1,2>, <5,5,5,5> + 2642878566U, // <2,5,6,0>: Cost 3 vsldoi4 <4,2,5,6>, LHS + 3386166810U, // <2,5,6,1>: Cost 4 vmrglw <5,1,2,6>, <4,u,5,1> + 2723033594U, // <2,5,6,2>: Cost 3 vsldoi8 <6,4,2,5>, <6,2,7,3> + 3848523842U, // <2,5,6,3>: Cost 4 vsldoi12 <3,u,1,2>, <5,6,3,4> + 2723033713U, // <2,5,6,4>: Cost 3 vsldoi8 <6,4,2,5>, <6,4,2,5> + 2230800388U, // <2,5,6,5>: Cost 3 vmrghw <2,6,3,7>, <5,5,5,5> + 2230800482U, // <2,5,6,6>: Cost 3 vmrghw <2,6,3,7>, <5,6,7,0> + 2785841252U, // <2,5,6,7>: Cost 3 vsldoi12 <5,6,7,2>, <5,6,7,2> + 2785914989U, // <2,5,6,u>: Cost 3 vsldoi12 <5,6,u,2>, <5,6,u,2> + 3796775930U, // <2,5,7,0>: Cost 4 vsldoi8 <6,4,2,5>, <7,0,1,2> + 3800757335U, // <2,5,7,1>: Cost 4 vsldoi8 <7,1,2,5>, <7,1,2,5> + 3853463689U, // <2,5,7,2>: Cost 4 vsldoi12 <4,6,5,2>, <5,7,2,3> + 3796776218U, // <2,5,7,3>: Cost 4 vsldoi8 <6,4,2,5>, <7,3,6,2> + 3796776294U, // <2,5,7,4>: Cost 4 vsldoi8 <6,4,2,5>, <7,4,5,6> + 3803411867U, // <2,5,7,5>: Cost 4 vsldoi8 <7,5,2,5>, <7,5,2,5> + 3371575081U, // <2,5,7,6>: Cost 4 vmrglw <2,6,2,7>, <2,4,5,6> + 3796776516U, // <2,5,7,7>: Cost 4 vsldoi8 <6,4,2,5>, <7,7,3,3> + 3371575083U, // <2,5,7,u>: Cost 4 vmrglw <2,6,2,7>, <2,4,5,u> + 2287225826U, // <2,5,u,0>: Cost 3 vmrglw LHS, <4,1,5,0> + 1256614802U, // <2,5,u,1>: Cost 2 vmrglw LHS, <4,0,5,1> + 2642896590U, // <2,5,u,2>: Cost 3 vsldoi4 <4,2,5,u>, <2,3,4,5> + 2287223723U, // <2,5,u,3>: Cost 3 vmrglw LHS, <1,2,5,3> + 2287225830U, // <2,5,u,4>: Cost 3 vmrglw LHS, <4,1,5,4> + 1256615130U, // <2,5,u,5>: Cost 2 vmrglw LHS, <4,4,5,5> + 1208838658U, // <2,5,u,6>: Cost 2 vmrglw LHS, <3,4,5,6> + 2287224051U, // <2,5,u,7>: Cost 3 vmrglw LHS, <1,6,5,7> + 1208838660U, // <2,5,u,u>: Cost 2 vmrglw LHS, <3,4,5,u> + 3772227584U, // <2,6,0,0>: Cost 4 vsldoi8 <2,3,2,6>, <0,0,0,0> + 2698485862U, // <2,6,0,1>: Cost 3 vsldoi8 <2,3,2,6>, LHS + 3759620282U, // <2,6,0,2>: Cost 4 vsldoi8 <0,2,2,6>, <0,2,2,6> + 3710675299U, // <2,6,0,3>: Cost 4 vsldoi4 <3,2,6,0>, <3,2,6,0> + 3767583058U, // <2,6,0,4>: Cost 4 vsldoi8 <1,5,2,6>, <0,4,1,5> + 3378153265U, // <2,6,0,5>: Cost 5 vmrglw <3,7,2,0>, <2,4,6,5> + 3865186637U, // <2,6,0,6>: Cost 4 vsldoi12 <6,6,2,2>, <6,0,6,1> + 2330291510U, // <2,6,0,7>: Cost 3 vmrglw , RHS + 2698486429U, // <2,6,0,u>: Cost 3 vsldoi8 <2,3,2,6>, LHS + 3734569062U, // <2,6,1,0>: Cost 4 vsldoi4 <7,2,6,1>, LHS + 3764929346U, // <2,6,1,1>: Cost 4 vsldoi8 <1,1,2,6>, <1,1,2,6> + 3772228502U, // <2,6,1,2>: Cost 4 vsldoi8 <2,3,2,6>, <1,2,3,0> + 3734571158U, // <2,6,1,3>: Cost 4 vsldoi4 <7,2,6,1>, <3,0,1,2> + 3734572342U, // <2,6,1,4>: Cost 4 vsldoi4 <7,2,6,1>, RHS + 3767583878U, // <2,6,1,5>: Cost 4 vsldoi8 <1,5,2,6>, <1,5,2,6> + 3768247511U, // <2,6,1,6>: Cost 4 vsldoi8 <1,6,2,6>, <1,6,2,6> + 2293140790U, // <2,6,1,7>: Cost 3 vmrglw <1,u,2,1>, RHS + 2293140791U, // <2,6,1,u>: Cost 3 vmrglw <1,u,2,1>, RHS + 3704717414U, // <2,6,2,0>: Cost 4 vsldoi4 <2,2,6,2>, LHS + 3395424589U, // <2,6,2,1>: Cost 4 vmrglw <6,6,2,2>, <6,0,6,1> + 2228031993U, // <2,6,2,2>: Cost 3 vmrghw <2,2,2,2>, <6,2,7,2> + 2698487485U, // <2,6,2,3>: Cost 3 vsldoi8 <2,3,2,6>, <2,3,2,6> + 3704720694U, // <2,6,2,4>: Cost 4 vsldoi4 <2,2,6,2>, RHS + 3773556575U, // <2,6,2,5>: Cost 4 vsldoi8 <2,5,2,6>, <2,5,2,6> + 2698487738U, // <2,6,2,6>: Cost 3 vsldoi8 <2,3,2,6>, <2,6,3,7> + 1221397814U, // <2,6,2,7>: Cost 2 vmrglw <2,2,2,2>, RHS + 1221397815U, // <2,6,2,u>: Cost 2 vmrglw <2,2,2,2>, RHS + 2636955750U, // <2,6,3,0>: Cost 3 vsldoi4 <3,2,6,3>, LHS + 2330314217U, // <2,6,3,1>: Cost 3 vmrglw LHS, <2,0,6,1> + 2636957626U, // <2,6,3,2>: Cost 3 vsldoi4 <3,2,6,3>, <2,6,3,7> + 2287184230U, // <2,6,3,3>: Cost 3 vmrglw LHS, <3,2,6,3> + 2636959030U, // <2,6,3,4>: Cost 3 vsldoi4 <3,2,6,3>, RHS + 2648903448U, // <2,6,3,5>: Cost 3 vsldoi4 <5,2,6,3>, <5,2,6,3> + 1256575800U, // <2,6,3,6>: Cost 2 vmrglw LHS, <6,6,6,6> + 135056694U, // <2,6,3,7>: Cost 1 vmrglw LHS, RHS + 135056695U, // <2,6,3,u>: Cost 1 vmrglw LHS, RHS + 3710705766U, // <2,6,4,0>: Cost 4 vsldoi4 <3,2,6,4>, LHS + 3698762677U, // <2,6,4,1>: Cost 5 vsldoi4 <1,2,6,4>, <1,2,6,4> + 3710707389U, // <2,6,4,2>: Cost 4 vsldoi4 <3,2,6,4>, <2,3,2,6> + 3710708071U, // <2,6,4,3>: Cost 4 vsldoi4 <3,2,6,4>, <3,2,6,4> + 3710709046U, // <2,6,4,4>: Cost 4 vsldoi4 <3,2,6,4>, RHS + 2698489142U, // <2,6,4,5>: Cost 3 vsldoi8 <2,3,2,6>, RHS + 3796782457U, // <2,6,4,6>: Cost 4 vsldoi8 <6,4,2,6>, <4,6,5,2> + 2295156022U, // <2,6,4,7>: Cost 3 vmrglw <2,2,2,4>, RHS + 2295156023U, // <2,6,4,u>: Cost 3 vmrglw <2,2,2,4>, RHS + 3303870753U, // <2,6,5,0>: Cost 4 vmrghw <2,5,3,6>, <6,0,1,2> + 3788820134U, // <2,6,5,1>: Cost 4 vsldoi8 <5,1,2,6>, <5,1,2,6> + 3779530520U, // <2,6,5,2>: Cost 4 vsldoi8 <3,5,2,6>, <5,2,6,3> + 3303871026U, // <2,6,5,3>: Cost 4 vmrghw <2,5,3,6>, <6,3,4,5> + 3303871117U, // <2,6,5,4>: Cost 4 vmrghw <2,5,3,6>, <6,4,5,6> + 3791474666U, // <2,6,5,5>: Cost 4 vsldoi8 <5,5,2,6>, <5,5,2,6> + 3792138299U, // <2,6,5,6>: Cost 4 vsldoi8 <5,6,2,6>, <5,6,2,6> + 2290519350U, // <2,6,5,7>: Cost 3 vmrglw <1,4,2,5>, RHS + 2290519351U, // <2,6,5,u>: Cost 3 vmrglw <1,4,2,5>, RHS + 2631008358U, // <2,6,6,0>: Cost 3 vsldoi4 <2,2,6,6>, LHS + 3372893673U, // <2,6,6,1>: Cost 4 vmrglw <2,u,2,6>, <2,0,6,1> + 2791445264U, // <2,6,6,2>: Cost 3 vsldoi12 <6,6,2,2>, <6,6,2,2> + 2230800968U, // <2,6,6,3>: Cost 3 vmrghw <2,6,3,7>, <6,3,7,0> + 2631011638U, // <2,6,6,4>: Cost 3 vsldoi4 <2,2,6,6>, RHS + 3372894001U, // <2,6,6,5>: Cost 4 vmrglw <2,u,2,6>, <2,4,6,5> + 2793362232U, // <2,6,6,6>: Cost 3 vsldoi12 <7,0,1,2>, <6,6,6,6> + 2295835958U, // <2,6,6,7>: Cost 3 vmrglw <2,3,2,6>, RHS + 2295835959U, // <2,6,6,u>: Cost 3 vmrglw <2,3,2,6>, RHS + 2793362254U, // <2,6,7,0>: Cost 3 vsldoi12 <7,0,1,2>, <6,7,0,1> + 2792035160U, // <2,6,7,1>: Cost 3 vsldoi12 <6,7,1,2>, <6,7,1,2> + 2792108897U, // <2,6,7,2>: Cost 3 vsldoi12 <6,7,2,2>, <6,7,2,2> + 2769474408U, // <2,6,7,3>: Cost 3 vsldoi12 <3,0,1,2>, <6,7,3,0> + 2793362294U, // <2,6,7,4>: Cost 3 vsldoi12 <7,0,1,2>, <6,7,4,5> + 3371575089U, // <2,6,7,5>: Cost 4 vmrglw <2,6,2,7>, <2,4,6,5> + 2792403845U, // <2,6,7,6>: Cost 3 vsldoi12 <6,7,6,2>, <6,7,6,2> + 2297834806U, // <2,6,7,7>: Cost 3 vmrglw <2,6,2,7>, RHS + 2297834807U, // <2,6,7,u>: Cost 3 vmrglw <2,6,2,7>, RHS + 2636996710U, // <2,6,u,0>: Cost 3 vsldoi4 <3,2,6,u>, LHS + 2698491694U, // <2,6,u,1>: Cost 3 vsldoi8 <2,3,2,6>, LHS + 2636998631U, // <2,6,u,2>: Cost 3 vsldoi4 <3,2,6,u>, <2,6,u,7> + 2282580326U, // <2,6,u,3>: Cost 3 vmrglw LHS, <3,2,6,3> + 2636999990U, // <2,6,u,4>: Cost 3 vsldoi4 <3,2,6,u>, RHS + 2698492058U, // <2,6,u,5>: Cost 3 vsldoi8 <2,3,2,6>, RHS + 1256616760U, // <2,6,u,6>: Cost 2 vmrglw LHS, <6,6,6,6> + 135097654U, // <2,6,u,7>: Cost 1 vmrglw LHS, RHS + 135097655U, // <2,6,u,u>: Cost 1 vmrglw LHS, RHS + 2666864742U, // <2,7,0,0>: Cost 3 vsldoi4 , LHS + 1719620602U, // <2,7,0,1>: Cost 2 vsldoi12 <7,0,1,2>, <7,0,1,2> + 3768254637U, // <2,7,0,2>: Cost 4 vsldoi8 <1,6,2,7>, <0,2,1,2> + 3393417722U, // <2,7,0,3>: Cost 4 vmrglw <6,3,2,0>, <6,2,7,3> + 2666868022U, // <2,7,0,4>: Cost 3 vsldoi4 , RHS + 3867104290U, // <2,7,0,5>: Cost 4 vsldoi12 <7,0,1,2>, <7,0,5,6> + 3728667127U, // <2,7,0,6>: Cost 4 vsldoi4 <6,2,7,0>, <6,2,7,0> + 2666869817U, // <2,7,0,7>: Cost 3 vsldoi4 , <7,0,u,2> + 1720136761U, // <2,7,0,u>: Cost 2 vsldoi12 <7,0,u,2>, <7,0,u,2> + 3728670822U, // <2,7,1,0>: Cost 4 vsldoi4 <6,2,7,1>, LHS + 3774227252U, // <2,7,1,1>: Cost 4 vsldoi8 <2,6,2,7>, <1,1,1,1> + 3774227350U, // <2,7,1,2>: Cost 4 vsldoi8 <2,6,2,7>, <1,2,3,0> + 2323001850U, // <2,7,1,3>: Cost 3 vmrglw <6,u,2,1>, <6,2,7,3> + 3728674102U, // <2,7,1,4>: Cost 4 vsldoi4 <6,2,7,1>, RHS + 3774227567U, // <2,7,1,5>: Cost 5 vsldoi8 <2,6,2,7>, <1,5,0,1> + 2694513880U, // <2,7,1,6>: Cost 3 vsldoi8 <1,6,2,7>, <1,6,2,7> + 3396744002U, // <2,7,1,7>: Cost 4 vmrglw <6,u,2,1>, <6,6,7,7> + 2323001850U, // <2,7,1,u>: Cost 3 vmrglw <6,u,2,1>, <6,2,7,3> + 2654937190U, // <2,7,2,0>: Cost 3 vsldoi4 <6,2,7,2>, LHS + 3728679732U, // <2,7,2,1>: Cost 4 vsldoi4 <6,2,7,2>, <1,1,1,1> + 2700486248U, // <2,7,2,2>: Cost 3 vsldoi8 <2,6,2,7>, <2,2,2,2> + 2321682938U, // <2,7,2,3>: Cost 3 vmrglw <6,6,2,2>, <6,2,7,3> + 2654940470U, // <2,7,2,4>: Cost 3 vsldoi4 <6,2,7,2>, RHS + 3859584196U, // <2,7,2,5>: Cost 4 vsldoi12 <5,6,7,2>, <7,2,5,6> + 2700486577U, // <2,7,2,6>: Cost 3 vsldoi8 <2,6,2,7>, <2,6,2,7> + 2228033132U, // <2,7,2,7>: Cost 3 vmrghw <2,2,2,2>, <7,7,7,7> + 2701813843U, // <2,7,2,u>: Cost 3 vsldoi8 <2,u,2,7>, <2,u,2,7> + 1581203558U, // <2,7,3,0>: Cost 2 vsldoi4 <6,2,7,3>, LHS + 2654946100U, // <2,7,3,1>: Cost 3 vsldoi4 <6,2,7,3>, <1,1,1,1> + 2637031354U, // <2,7,3,2>: Cost 3 vsldoi4 <3,2,7,3>, <2,6,3,7> + 1256575482U, // <2,7,3,3>: Cost 2 vmrglw LHS, <6,2,7,3> + 1581206838U, // <2,7,3,4>: Cost 2 vsldoi4 <6,2,7,3>, RHS + 2654949380U, // <2,7,3,5>: Cost 3 vsldoi4 <6,2,7,3>, <5,5,5,5> + 1581208058U, // <2,7,3,6>: Cost 2 vsldoi4 <6,2,7,3>, <6,2,7,3> + 1256575810U, // <2,7,3,7>: Cost 2 vmrglw LHS, <6,6,7,7> + 1581209390U, // <2,7,3,u>: Cost 2 vsldoi4 <6,2,7,3>, LHS + 3728695398U, // <2,7,4,0>: Cost 4 vsldoi4 <6,2,7,4>, LHS + 3869758782U, // <2,7,4,1>: Cost 4 vsldoi12 <7,4,1,2>, <7,4,1,2> + 3728696936U, // <2,7,4,2>: Cost 4 vsldoi4 <6,2,7,4>, <2,2,2,2> + 3393450490U, // <2,7,4,3>: Cost 4 vmrglw <6,3,2,4>, <6,2,7,3> + 3728698678U, // <2,7,4,4>: Cost 4 vsldoi4 <6,2,7,4>, RHS + 2700487990U, // <2,7,4,5>: Cost 3 vsldoi8 <2,6,2,7>, RHS + 3728699899U, // <2,7,4,6>: Cost 4 vsldoi4 <6,2,7,4>, <6,2,7,4> + 3867104626U, // <2,7,4,7>: Cost 4 vsldoi12 <7,0,1,2>, <7,4,7,0> + 2700488233U, // <2,7,4,u>: Cost 3 vsldoi8 <2,6,2,7>, RHS + 3855160709U, // <2,7,5,0>: Cost 4 vsldoi12 <5,0,1,2>, <7,5,0,1> + 3728704406U, // <2,7,5,1>: Cost 4 vsldoi4 <6,2,7,5>, <1,2,3,0> + 3370233956U, // <2,7,5,2>: Cost 4 vmrglw <2,4,2,5>, <5,6,7,2> + 2320380410U, // <2,7,5,3>: Cost 3 vmrglw <6,4,2,5>, <6,2,7,3> + 3728706870U, // <2,7,5,4>: Cost 4 vsldoi4 <6,2,7,5>, RHS + 3867104694U, // <2,7,5,5>: Cost 4 vsldoi12 <7,0,1,2>, <7,5,5,5> + 3792146492U, // <2,7,5,6>: Cost 4 vsldoi8 <5,6,2,7>, <5,6,2,7> + 3394122562U, // <2,7,5,7>: Cost 4 vmrglw <6,4,2,5>, <6,6,7,7> + 2320380410U, // <2,7,5,u>: Cost 3 vmrglw <6,4,2,5>, <6,2,7,3> + 2230801402U, // <2,7,6,0>: Cost 3 vmrghw <2,6,3,7>, <7,0,1,2> + 3768258984U, // <2,7,6,1>: Cost 4 vsldoi8 <1,6,2,7>, <6,1,7,2> + 2730349050U, // <2,7,6,2>: Cost 3 vsldoi8 <7,6,2,7>, <6,2,7,3> + 3372894575U, // <2,7,6,3>: Cost 4 vmrglw <2,u,2,6>, <3,2,7,3> + 2230801766U, // <2,7,6,4>: Cost 3 vmrghw <2,6,3,7>, <7,4,5,6> + 3304543670U, // <2,7,6,5>: Cost 4 vmrghw <2,6,3,7>, <7,5,5,5> + 3728716285U, // <2,7,6,6>: Cost 4 vsldoi4 <6,2,7,6>, <6,2,7,6> + 2230802028U, // <2,7,6,7>: Cost 3 vmrghw <2,6,3,7>, <7,7,7,7> + 2730349050U, // <2,7,6,u>: Cost 3 vsldoi8 <7,6,2,7>, <6,2,7,3> + 2793362983U, // <2,7,7,0>: Cost 3 vsldoi12 <7,0,1,2>, <7,7,0,1> + 3728721112U, // <2,7,7,1>: Cost 4 vsldoi4 <6,2,7,7>, <1,6,2,7> + 3371574933U, // <2,7,7,2>: Cost 4 vmrglw <2,6,2,7>, <2,2,7,2> + 2327695866U, // <2,7,7,3>: Cost 3 vmrglw <7,6,2,7>, <6,2,7,3> + 3728723254U, // <2,7,7,4>: Cost 4 vsldoi4 <6,2,7,7>, RHS + 3371574855U, // <2,7,7,5>: Cost 5 vmrglw <2,6,2,7>, <2,1,7,5> + 2730350062U, // <2,7,7,6>: Cost 3 vsldoi8 <7,6,2,7>, <7,6,2,7> + 2793363052U, // <2,7,7,7>: Cost 3 vsldoi12 <7,0,1,2>, <7,7,7,7> + 2798671471U, // <2,7,7,u>: Cost 3 vsldoi12 <7,u,1,2>, <7,7,u,1> + 1581244518U, // <2,7,u,0>: Cost 2 vsldoi4 <6,2,7,u>, LHS + 1724929666U, // <2,7,u,1>: Cost 2 vsldoi12 <7,u,1,2>, <7,u,1,2> + 2637072314U, // <2,7,u,2>: Cost 3 vsldoi4 <3,2,7,u>, <2,6,3,7> + 1256616442U, // <2,7,u,3>: Cost 2 vmrglw LHS, <6,2,7,3> + 1581247798U, // <2,7,u,4>: Cost 2 vsldoi4 <6,2,7,u>, RHS + 2700490906U, // <2,7,u,5>: Cost 3 vsldoi8 <2,6,2,7>, RHS + 1581249023U, // <2,7,u,6>: Cost 2 vsldoi4 <6,2,7,u>, <6,2,7,u> + 1256616770U, // <2,7,u,7>: Cost 2 vmrglw LHS, <6,6,7,7> + 1581250350U, // <2,7,u,u>: Cost 2 vsldoi4 <6,2,7,u>, LHS + 1611489280U, // <2,u,0,0>: Cost 2 vsldoi8 LHS, <0,0,0,0> + 537747563U, // <2,u,0,1>: Cost 1 vsldoi8 LHS, LHS + 2685231277U, // <2,u,0,2>: Cost 3 vsldoi8 LHS, <0,2,1,2> + 2685231356U, // <2,u,0,3>: Cost 3 vsldoi8 LHS, <0,3,1,0> + 1611489618U, // <2,u,0,4>: Cost 2 vsldoi8 LHS, <0,4,1,5> + 2226763930U, // <2,u,0,5>: Cost 3 vmrghw <2,0,3,0>, RHS + 2733007350U, // <2,u,0,6>: Cost 3 vsldoi8 LHS, <0,6,1,7> + 2660971737U, // <2,u,0,7>: Cost 3 vsldoi4 <7,2,u,0>, <7,2,u,0> + 537748125U, // <2,u,0,u>: Cost 1 vsldoi8 LHS, LHS + 2689876708U, // <2,u,1,0>: Cost 3 vsldoi8 LHS, <1,0,1,2> + 1611490100U, // <2,u,1,1>: Cost 2 vsldoi8 LHS, <1,1,1,1> + 1611490198U, // <2,u,1,2>: Cost 2 vsldoi8 LHS, <1,2,3,0> + 2293137564U, // <2,u,1,3>: Cost 3 vmrglw <1,u,2,1>, LHS + 2689877072U, // <2,u,1,4>: Cost 3 vsldoi8 LHS, <1,4,5,6> + 2689877103U, // <2,u,1,5>: Cost 3 vsldoi8 LHS, <1,5,0,1> + 2689877199U, // <2,u,1,6>: Cost 3 vsldoi8 LHS, <1,6,1,7> + 2293140808U, // <2,u,1,7>: Cost 3 vmrglw <1,u,2,1>, RHS + 1616135548U, // <2,u,1,u>: Cost 2 vsldoi8 LHS, <1,u,3,0> + 1556938854U, // <2,u,2,0>: Cost 2 vsldoi4 <2,2,2,2>, LHS + 1154291502U, // <2,u,2,1>: Cost 2 vmrghw <2,2,2,2>, LHS + 336380006U, // <2,u,2,2>: Cost 1 vspltisw2 LHS + 1611490982U, // <2,u,2,3>: Cost 2 vsldoi8 LHS, <2,3,0,1> + 1556942134U, // <2,u,2,4>: Cost 2 vsldoi4 <2,2,2,2>, RHS + 1154291866U, // <2,u,2,5>: Cost 2 vmrghw <2,2,2,2>, RHS + 1611491258U, // <2,u,2,6>: Cost 2 vsldoi8 LHS, <2,6,3,7> + 1221397832U, // <2,u,2,7>: Cost 2 vmrglw <2,2,2,2>, RHS + 336380006U, // <2,u,2,u>: Cost 1 vspltisw2 LHS + 1611491478U, // <2,u,3,0>: Cost 2 vsldoi8 LHS, <3,0,1,2> + 1213440073U, // <2,u,3,1>: Cost 2 vmrglw LHS, <0,0,u,1> + 1213442261U, // <2,u,3,2>: Cost 2 vmrglw LHS, <3,0,u,2> + 135053468U, // <2,u,3,3>: Cost 1 vmrglw LHS, LHS + 1611491842U, // <2,u,3,4>: Cost 2 vsldoi8 LHS, <3,4,5,6> + 1213440401U, // <2,u,3,5>: Cost 2 vmrglw LHS, <0,4,u,5> + 1213442589U, // <2,u,3,6>: Cost 2 vmrglw LHS, <3,4,u,6> + 135056712U, // <2,u,3,7>: Cost 1 vmrglw LHS, RHS + 135053473U, // <2,u,3,u>: Cost 1 vmrglw LHS, LHS + 1551425638U, // <2,u,4,0>: Cost 2 vsldoi4 <1,2,u,4>, LHS + 1551426503U, // <2,u,4,1>: Cost 2 vsldoi4 <1,2,u,4>, <1,2,u,4> + 2625169000U, // <2,u,4,2>: Cost 3 vsldoi4 <1,2,u,4>, <2,2,2,2> + 2625169558U, // <2,u,4,3>: Cost 3 vsldoi4 <1,2,u,4>, <3,0,1,2> + 1551428918U, // <2,u,4,4>: Cost 2 vsldoi4 <1,2,u,4>, RHS + 537750838U, // <2,u,4,5>: Cost 1 vsldoi8 LHS, RHS + 2733010297U, // <2,u,4,6>: Cost 3 vsldoi8 LHS, <4,6,5,2> + 2295156040U, // <2,u,4,7>: Cost 3 vmrglw <2,2,2,4>, RHS + 537751081U, // <2,u,4,u>: Cost 1 vsldoi8 LHS, RHS + 2689879624U, // <2,u,5,0>: Cost 3 vsldoi8 LHS, <5,0,1,2> + 2230130478U, // <2,u,5,1>: Cost 3 vmrghw <2,5,3,6>, LHS + 2631149217U, // <2,u,5,2>: Cost 3 vsldoi4 <2,2,u,5>, <2,2,u,5> + 2290516124U, // <2,u,5,3>: Cost 3 vmrglw <1,4,2,5>, LHS + 2689879988U, // <2,u,5,4>: Cost 3 vsldoi8 LHS, <5,4,5,6> + 1659269124U, // <2,u,5,5>: Cost 2 vsldoi8 LHS, <5,5,5,5> + 1691162778U, // <2,u,5,6>: Cost 2 vsldoi12 <2,2,2,2>, RHS + 2290519368U, // <2,u,5,7>: Cost 3 vmrglw <1,4,2,5>, RHS + 1691162796U, // <2,u,5,u>: Cost 2 vsldoi12 <2,2,2,2>, RHS + 2230802131U, // <2,u,6,0>: Cost 3 vmrghw <2,6,3,7>, + 1157060398U, // <2,u,6,1>: Cost 2 vmrghw <2,6,3,7>, LHS + 1659269626U, // <2,u,6,2>: Cost 2 vsldoi8 LHS, <6,2,7,3> + 2764904656U, // <2,u,6,3>: Cost 3 vsldoi12 <2,2,2,2>, + 2230802495U, // <2,u,6,4>: Cost 3 vmrghw <2,6,3,7>, + 1157060762U, // <2,u,6,5>: Cost 2 vmrghw <2,6,3,7>, RHS + 1659269944U, // <2,u,6,6>: Cost 2 vsldoi8 LHS, <6,6,6,6> + 1659269966U, // <2,u,6,7>: Cost 2 vsldoi8 LHS, <6,7,0,1> + 1157060965U, // <2,u,6,u>: Cost 2 vmrghw <2,6,3,7>, LHS + 1659270138U, // <2,u,7,0>: Cost 2 vsldoi8 LHS, <7,0,1,2> + 2727040090U, // <2,u,7,1>: Cost 3 vsldoi8 <7,1,2,u>, <7,1,2,u> + 2727703723U, // <2,u,7,2>: Cost 3 vsldoi8 <7,2,2,u>, <7,2,2,u> + 2297831580U, // <2,u,7,3>: Cost 3 vmrglw <2,6,2,7>, LHS + 1659270502U, // <2,u,7,4>: Cost 2 vsldoi8 LHS, <7,4,5,6> + 2733012406U, // <2,u,7,5>: Cost 3 vsldoi8 LHS, <7,5,5,5> + 2730358255U, // <2,u,7,6>: Cost 3 vsldoi8 <7,6,2,u>, <7,6,2,u> + 1659270764U, // <2,u,7,7>: Cost 2 vsldoi8 LHS, <7,7,7,7> + 1659270786U, // <2,u,7,u>: Cost 2 vsldoi8 LHS, <7,u,1,2> + 1213481923U, // <2,u,u,0>: Cost 2 vmrglw LHS, <1,2,u,0> + 537753390U, // <2,u,u,1>: Cost 1 vsldoi8 LHS, LHS + 336380006U, // <2,u,u,2>: Cost 1 vspltisw2 LHS + 135094428U, // <2,u,u,3>: Cost 1 vmrglw LHS, LHS + 1213481927U, // <2,u,u,4>: Cost 2 vmrglw LHS, <1,2,u,4> + 537753754U, // <2,u,u,5>: Cost 1 vsldoi8 LHS, RHS + 1208838685U, // <2,u,u,6>: Cost 2 vmrglw LHS, <3,4,u,6> + 135097672U, // <2,u,u,7>: Cost 1 vmrglw LHS, RHS + 135094433U, // <2,u,u,u>: Cost 1 vmrglw LHS, LHS + 1678557184U, // <3,0,0,0>: Cost 2 vsldoi12 LHS, <0,0,0,0> + 1678557194U, // <3,0,0,1>: Cost 2 vsldoi12 LHS, <0,0,1,1> + 2631181989U, // <3,0,0,2>: Cost 3 vsldoi4 <2,3,0,0>, <2,3,0,0> + 2289223984U, // <3,0,0,3>: Cost 3 vmrglw <1,2,3,0>, <3,2,0,3> + 2756943909U, // <3,0,0,4>: Cost 3 vsldoi12 LHS, <0,0,4,1> + 3362965729U, // <3,0,0,5>: Cost 4 vmrglw <1,2,3,0>, <3,1,0,5> + 3362966054U, // <3,0,0,6>: Cost 4 vmrglw <1,2,3,0>, <3,5,0,6> + 2289224312U, // <3,0,0,7>: Cost 3 vmrglw <1,2,3,0>, <3,6,0,7> + 1683202121U, // <3,0,0,u>: Cost 2 vsldoi12 LHS, <0,0,u,1> + 1557446758U, // <3,0,1,0>: Cost 2 vsldoi4 <2,3,0,1>, LHS + 2752741467U, // <3,0,1,1>: Cost 3 vsldoi12 LHS, <0,1,1,1> + 604815462U, // <3,0,1,2>: Cost 1 vsldoi12 LHS, LHS + 2631190676U, // <3,0,1,3>: Cost 3 vsldoi4 <2,3,0,1>, <3,0,1,0> + 1557450038U, // <3,0,1,4>: Cost 2 vsldoi4 <2,3,0,1>, RHS + 2667024388U, // <3,0,1,5>: Cost 3 vsldoi4 , <5,5,5,5> + 2800074894U, // <3,0,1,6>: Cost 3 vsldoi12 LHS, <0,1,6,7> + 2661053667U, // <3,0,1,7>: Cost 3 vsldoi4 <7,3,0,1>, <7,3,0,1> + 604815516U, // <3,0,1,u>: Cost 1 vsldoi12 LHS, LHS + 2696521165U, // <3,0,2,0>: Cost 3 vsldoi8 <2,0,3,0>, <2,0,3,0> + 2752741549U, // <3,0,2,1>: Cost 3 vsldoi12 LHS, <0,2,1,2> + 2691876456U, // <3,0,2,2>: Cost 3 vsldoi8 <1,2,3,0>, <2,2,2,2> + 2691876518U, // <3,0,2,3>: Cost 3 vsldoi8 <1,2,3,0>, <2,3,0,1> + 3830685895U, // <3,0,2,4>: Cost 4 vsldoi12 LHS, <0,2,4,1> + 3765618536U, // <3,0,2,5>: Cost 4 vsldoi8 <1,2,3,0>, <2,5,3,6> + 2691876794U, // <3,0,2,6>: Cost 3 vsldoi8 <1,2,3,0>, <2,6,3,7> + 2701166596U, // <3,0,2,7>: Cost 3 vsldoi8 <2,7,3,0>, <2,7,3,0> + 2756944108U, // <3,0,2,u>: Cost 3 vsldoi12 LHS, <0,2,u,2> + 2691877014U, // <3,0,3,0>: Cost 3 vsldoi8 <1,2,3,0>, <3,0,1,2> + 1161003110U, // <3,0,3,1>: Cost 2 vmrghw <3,3,3,3>, LHS + 2691877168U, // <3,0,3,2>: Cost 3 vsldoi8 <1,2,3,0>, <3,2,0,3> + 2691877246U, // <3,0,3,3>: Cost 3 vsldoi8 <1,2,3,0>, <3,3,0,0> + 2691877378U, // <3,0,3,4>: Cost 3 vsldoi8 <1,2,3,0>, <3,4,5,6> + 3765619238U, // <3,0,3,5>: Cost 4 vsldoi8 <1,2,3,0>, <3,5,0,6> + 2691877496U, // <3,0,3,6>: Cost 3 vsldoi8 <1,2,3,0>, <3,6,0,7> + 3368962680U, // <3,0,3,7>: Cost 4 vmrglw <2,2,3,3>, <3,6,0,7> + 1161003677U, // <3,0,3,u>: Cost 2 vmrghw <3,3,3,3>, LHS + 2289254400U, // <3,0,4,0>: Cost 3 vmrglw <1,2,3,4>, <0,0,0,0> + 1678557522U, // <3,0,4,1>: Cost 2 vsldoi12 LHS, <0,4,1,5> + 2631214761U, // <3,0,4,2>: Cost 3 vsldoi4 <2,3,0,4>, <2,3,0,4> + 2235580672U, // <3,0,4,3>: Cost 3 vmrghw <3,4,5,6>, <0,3,1,4> + 2756944237U, // <3,0,4,4>: Cost 3 vsldoi12 LHS, <0,4,4,5> + 1618136374U, // <3,0,4,5>: Cost 2 vsldoi8 <1,2,3,0>, RHS + 3309322742U, // <3,0,4,6>: Cost 4 vmrghw <3,4,5,6>, <0,6,1,7> + 3362998904U, // <3,0,4,7>: Cost 4 vmrglw <1,2,3,4>, <3,6,0,7> + 1683202449U, // <3,0,4,u>: Cost 2 vsldoi12 LHS, <0,4,u,5> + 3765620296U, // <3,0,5,0>: Cost 4 vsldoi8 <1,2,3,0>, <5,0,1,2> + 2752299427U, // <3,0,5,1>: Cost 3 vsldoi12 LHS, <0,5,1,5> + 3789508346U, // <3,0,5,2>: Cost 4 vsldoi8 <5,2,3,0>, <5,2,3,0> + 3403486842U, // <3,0,5,3>: Cost 4 vmrglw , <7,u,0,3> + 3765620660U, // <3,0,5,4>: Cost 4 vsldoi8 <1,2,3,0>, <5,4,5,6> + 2733682692U, // <3,0,5,5>: Cost 3 vsldoi8 , <5,5,5,5> + 2800075218U, // <3,0,5,6>: Cost 3 vsldoi12 LHS, <0,5,6,7> + 3873817044U, // <3,0,5,7>: Cost 4 vsldoi12 LHS, <0,5,7,0> + 2800075234U, // <3,0,5,u>: Cost 3 vsldoi12 LHS, <0,5,u,5> + 2752299501U, // <3,0,6,0>: Cost 3 vsldoi12 LHS, <0,6,0,7> + 2236547174U, // <3,0,6,1>: Cost 3 vmrghw <3,6,0,7>, LHS + 2733683194U, // <3,0,6,2>: Cost 3 vsldoi8 , <6,2,7,3> + 3844473352U, // <3,0,6,3>: Cost 4 vsldoi12 <3,2,0,3>, <0,6,3,7> + 3310289234U, // <3,0,6,4>: Cost 4 vmrghw <3,6,0,7>, <0,4,1,5> + 3873817114U, // <3,0,6,5>: Cost 4 vsldoi12 LHS, <0,6,5,7> + 2733683512U, // <3,0,6,6>: Cost 3 vsldoi8 , <6,6,6,6> + 2725057384U, // <3,0,6,7>: Cost 3 vsldoi8 <6,7,3,0>, <6,7,3,0> + 2236547741U, // <3,0,6,u>: Cost 3 vmrghw <3,6,0,7>, LHS + 2297905152U, // <3,0,7,0>: Cost 3 vmrglw <2,6,3,7>, <0,0,0,0> + 2297906854U, // <3,0,7,1>: Cost 3 vmrglw <2,6,3,7>, <2,3,0,1> + 2727711916U, // <3,0,7,2>: Cost 3 vsldoi8 <7,2,3,0>, <7,2,3,0> + 3371649328U, // <3,0,7,3>: Cost 4 vmrglw <2,6,3,7>, <3,2,0,3> + 2733684070U, // <3,0,7,4>: Cost 3 vsldoi8 , <7,4,5,6> + 3734843490U, // <3,0,7,5>: Cost 4 vsldoi4 <7,3,0,7>, <5,6,7,0> + 3798799895U, // <3,0,7,6>: Cost 4 vsldoi8 <6,7,3,0>, <7,6,7,3> + 2733684332U, // <3,0,7,7>: Cost 3 vsldoi8 , <7,7,7,7> + 2297906861U, // <3,0,7,u>: Cost 3 vmrglw <2,6,3,7>, <2,3,0,u> + 1557504102U, // <3,0,u,0>: Cost 2 vsldoi4 <2,3,0,u>, LHS + 1678557842U, // <3,0,u,1>: Cost 2 vsldoi12 LHS, <0,u,1,1> + 604816029U, // <3,0,u,2>: Cost 1 vsldoi12 LHS, LHS + 2691880892U, // <3,0,u,3>: Cost 3 vsldoi8 <1,2,3,0>, + 1557507382U, // <3,0,u,4>: Cost 2 vsldoi4 <2,3,0,u>, RHS + 1618139290U, // <3,0,u,5>: Cost 2 vsldoi8 <1,2,3,0>, RHS + 2691881168U, // <3,0,u,6>: Cost 3 vsldoi8 <1,2,3,0>, + 2661111018U, // <3,0,u,7>: Cost 3 vsldoi4 <7,3,0,u>, <7,3,0,u> + 604816083U, // <3,0,u,u>: Cost 1 vsldoi12 LHS, LHS + 2619310332U, // <3,1,0,0>: Cost 3 vsldoi4 <0,3,1,0>, <0,3,1,0> + 2756944612U, // <3,1,0,1>: Cost 3 vsldoi12 LHS, <1,0,1,2> + 2289221724U, // <3,1,0,2>: Cost 3 vmrglw <1,2,3,0>, <0,1,1,2> + 2619312278U, // <3,1,0,3>: Cost 3 vsldoi4 <0,3,1,0>, <3,0,1,2> + 2619313462U, // <3,1,0,4>: Cost 3 vsldoi4 <0,3,1,0>, RHS + 2289221970U, // <3,1,0,5>: Cost 3 vmrglw <1,2,3,0>, <0,4,1,5> + 2232599768U, // <3,1,0,6>: Cost 3 vmrghw <3,0,1,2>, <1,6,2,7> + 3362964687U, // <3,1,0,7>: Cost 4 vmrglw <1,2,3,0>, <1,6,1,7> + 2619316014U, // <3,1,0,u>: Cost 3 vsldoi4 <0,3,1,0>, LHS + 2756944683U, // <3,1,1,0>: Cost 3 vsldoi12 LHS, <1,1,0,1> + 1678558004U, // <3,1,1,1>: Cost 2 vsldoi12 LHS, <1,1,1,1> + 2691883927U, // <3,1,1,2>: Cost 3 vsldoi8 <1,2,3,1>, <1,2,3,1> + 3826631496U, // <3,1,1,3>: Cost 4 vsldoi12 <0,2,1,3>, <1,1,3,3> + 2756944723U, // <3,1,1,4>: Cost 3 vsldoi12 LHS, <1,1,4,5> + 2756944732U, // <3,1,1,5>: Cost 3 vsldoi12 LHS, <1,1,5,5> + 3830686561U, // <3,1,1,6>: Cost 4 vsldoi12 LHS, <1,1,6,1> + 3734869228U, // <3,1,1,7>: Cost 4 vsldoi4 <7,3,1,1>, <7,3,1,1> + 1678558004U, // <3,1,1,u>: Cost 2 vsldoi12 LHS, <1,1,1,1> + 2696529358U, // <3,1,2,0>: Cost 3 vsldoi8 <2,0,3,1>, <2,0,3,1> + 2756944775U, // <3,1,2,1>: Cost 3 vsldoi12 LHS, <1,2,1,3> + 2294548630U, // <3,1,2,2>: Cost 3 vmrglw <2,1,3,2>, <3,0,1,2> + 1678558102U, // <3,1,2,3>: Cost 2 vsldoi12 LHS, <1,2,3,0> + 2631273782U, // <3,1,2,4>: Cost 3 vsldoi4 <2,3,1,2>, RHS + 2756944811U, // <3,1,2,5>: Cost 3 vsldoi12 LHS, <1,2,5,3> + 3830686644U, // <3,1,2,6>: Cost 4 vsldoi12 LHS, <1,2,6,3> + 2800075706U, // <3,1,2,7>: Cost 3 vsldoi12 LHS, <1,2,7,0> + 1679000515U, // <3,1,2,u>: Cost 2 vsldoi12 LHS, <1,2,u,0> + 2619334911U, // <3,1,3,0>: Cost 3 vsldoi4 <0,3,1,3>, <0,3,1,3> + 2295218186U, // <3,1,3,1>: Cost 3 vmrglw <2,2,3,3>, <0,0,1,1> + 2293229718U, // <3,1,3,2>: Cost 3 vmrglw <1,u,3,3>, <3,0,1,2> + 2619337116U, // <3,1,3,3>: Cost 3 vsldoi4 <0,3,1,3>, <3,3,3,3> + 2619338038U, // <3,1,3,4>: Cost 3 vsldoi4 <0,3,1,3>, RHS + 2295218514U, // <3,1,3,5>: Cost 3 vmrglw <2,2,3,3>, <0,4,1,5> + 3830686729U, // <3,1,3,6>: Cost 4 vsldoi12 LHS, <1,3,6,7> + 3368961231U, // <3,1,3,7>: Cost 4 vmrglw <2,2,3,3>, <1,6,1,7> + 2619340590U, // <3,1,3,u>: Cost 3 vsldoi4 <0,3,1,3>, LHS + 2619343104U, // <3,1,4,0>: Cost 3 vsldoi4 <0,3,1,4>, <0,3,1,4> + 2289254410U, // <3,1,4,1>: Cost 3 vmrglw <1,2,3,4>, <0,0,1,1> + 2289256598U, // <3,1,4,2>: Cost 3 vmrglw <1,2,3,4>, <3,0,1,2> + 2619345410U, // <3,1,4,3>: Cost 3 vsldoi4 <0,3,1,4>, <3,4,5,6> + 2619346230U, // <3,1,4,4>: Cost 3 vsldoi4 <0,3,1,4>, RHS + 2756944976U, // <3,1,4,5>: Cost 3 vsldoi12 LHS, <1,4,5,6> + 3362996401U, // <3,1,4,6>: Cost 4 vmrglw <1,2,3,4>, <0,2,1,6> + 3362997455U, // <3,1,4,7>: Cost 4 vmrglw <1,2,3,4>, <1,6,1,7> + 2619348782U, // <3,1,4,u>: Cost 3 vsldoi4 <0,3,1,4>, LHS + 2756945007U, // <3,1,5,0>: Cost 3 vsldoi12 LHS, <1,5,0,1> + 3830686840U, // <3,1,5,1>: Cost 4 vsldoi12 LHS, <1,5,1,1> + 3358361750U, // <3,1,5,2>: Cost 4 vmrglw <0,4,3,5>, <3,0,1,2> + 3830686857U, // <3,1,5,3>: Cost 4 vsldoi12 LHS, <1,5,3,0> + 2756945047U, // <3,1,5,4>: Cost 3 vsldoi12 LHS, <1,5,4,5> + 2294571346U, // <3,1,5,5>: Cost 3 vmrglw <2,1,3,5>, <0,4,1,5> + 3806105698U, // <3,1,5,6>: Cost 4 vsldoi8 , <5,6,7,0> + 3873817774U, // <3,1,5,7>: Cost 4 vsldoi12 LHS, <1,5,7,1> + 2756945079U, // <3,1,5,u>: Cost 3 vsldoi12 LHS, <1,5,u,1> + 3830686912U, // <3,1,6,0>: Cost 4 vsldoi12 LHS, <1,6,0,1> + 2756945103U, // <3,1,6,1>: Cost 3 vsldoi12 LHS, <1,6,1,7> + 2236547990U, // <3,1,6,2>: Cost 3 vmrghw <3,6,0,7>, <1,2,3,0> + 3826631905U, // <3,1,6,3>: Cost 4 vsldoi12 <0,2,1,3>, <1,6,3,7> + 3830686952U, // <3,1,6,4>: Cost 4 vsldoi12 LHS, <1,6,4,5> + 2756945139U, // <3,1,6,5>: Cost 3 vsldoi12 LHS, <1,6,5,7> + 3830686972U, // <3,1,6,6>: Cost 4 vsldoi12 LHS, <1,6,6,7> + 2800076030U, // <3,1,6,7>: Cost 3 vsldoi12 LHS, <1,6,7,0> + 2756945166U, // <3,1,6,u>: Cost 3 vsldoi12 LHS, <1,6,u,7> + 3699081318U, // <3,1,7,0>: Cost 4 vsldoi4 <1,3,1,7>, LHS + 2297905162U, // <3,1,7,1>: Cost 3 vmrglw <2,6,3,7>, <0,0,1,1> + 2297907350U, // <3,1,7,2>: Cost 3 vmrglw <2,6,3,7>, <3,0,1,2> + 3365675182U, // <3,1,7,3>: Cost 4 vmrglw <1,6,3,7>, <0,2,1,3> + 3699084598U, // <3,1,7,4>: Cost 4 vsldoi4 <1,3,1,7>, RHS + 2297905490U, // <3,1,7,5>: Cost 3 vmrglw <2,6,3,7>, <0,4,1,5> + 2297905329U, // <3,1,7,6>: Cost 3 vmrglw <2,6,3,7>, <0,2,1,6> + 3368330447U, // <3,1,7,7>: Cost 4 vmrglw <2,1,3,7>, <1,6,1,7> + 2297905169U, // <3,1,7,u>: Cost 3 vmrglw <2,6,3,7>, <0,0,1,u> + 2619375876U, // <3,1,u,0>: Cost 3 vsldoi4 <0,3,1,u>, <0,3,1,u> + 1678558004U, // <3,1,u,1>: Cost 2 vsldoi12 LHS, <1,1,1,1> + 2289289366U, // <3,1,u,2>: Cost 3 vmrglw <1,2,3,u>, <3,0,1,2> + 1679000956U, // <3,1,u,3>: Cost 2 vsldoi12 LHS, <1,u,3,0> + 2619378998U, // <3,1,u,4>: Cost 3 vsldoi4 <0,3,1,u>, RHS + 2756945297U, // <3,1,u,5>: Cost 3 vsldoi12 LHS, <1,u,5,3> + 2297905329U, // <3,1,u,6>: Cost 3 vmrglw <2,6,3,7>, <0,2,1,6> + 2800076192U, // <3,1,u,7>: Cost 3 vsldoi12 LHS, <1,u,7,0> + 1683203497U, // <3,1,u,u>: Cost 2 vsldoi12 LHS, <1,u,u,0> + 3362964203U, // <3,2,0,0>: Cost 4 vmrglw <1,2,3,0>, <1,0,2,0> + 2289222380U, // <3,2,0,1>: Cost 3 vmrglw <1,2,3,0>, <1,0,2,1> + 2289222462U, // <3,2,0,2>: Cost 3 vmrglw <1,2,3,0>, <1,1,2,2> + 1215479910U, // <3,2,0,3>: Cost 2 vmrglw <1,2,3,0>, LHS + 3362964207U, // <3,2,0,4>: Cost 4 vmrglw <1,2,3,0>, <1,0,2,4> + 2289222708U, // <3,2,0,5>: Cost 3 vmrglw <1,2,3,0>, <1,4,2,5> + 2232600506U, // <3,2,0,6>: Cost 3 vmrghw <3,0,1,2>, <2,6,3,7> + 3396142296U, // <3,2,0,7>: Cost 4 vmrglw <6,7,3,0>, <1,6,2,7> + 1215479915U, // <3,2,0,u>: Cost 2 vmrglw <1,2,3,0>, LHS + 3699105894U, // <3,2,1,0>: Cost 4 vsldoi4 <1,3,2,1>, LHS + 3765633844U, // <3,2,1,1>: Cost 4 vsldoi8 <1,2,3,2>, <1,1,1,1> + 2691892120U, // <3,2,1,2>: Cost 3 vsldoi8 <1,2,3,2>, <1,2,3,2> + 2752300575U, // <3,2,1,3>: Cost 3 vsldoi12 LHS, <2,1,3,1> + 3699109174U, // <3,2,1,4>: Cost 4 vsldoi4 <1,3,2,1>, RHS + 3830687280U, // <3,2,1,5>: Cost 5 vsldoi12 LHS, <2,1,5,0> + 3830687289U, // <3,2,1,6>: Cost 4 vsldoi12 LHS, <2,1,6,0> + 3874260548U, // <3,2,1,7>: Cost 4 vsldoi12 LHS, <2,1,7,2> + 2752742988U, // <3,2,1,u>: Cost 3 vsldoi12 LHS, <2,1,u,1> + 2631344230U, // <3,2,2,0>: Cost 3 vsldoi4 <2,3,2,2>, LHS + 2697201184U, // <3,2,2,1>: Cost 3 vsldoi8 <2,1,3,2>, <2,1,3,2> + 1678558824U, // <3,2,2,2>: Cost 2 vsldoi12 LHS, <2,2,2,2> + 1678558834U, // <3,2,2,3>: Cost 2 vsldoi12 LHS, <2,2,3,3> + 2631347510U, // <3,2,2,4>: Cost 3 vsldoi4 <2,3,2,2>, RHS + 3368953613U, // <3,2,2,5>: Cost 4 vmrglw <2,2,3,2>, <2,4,2,5> + 2234304442U, // <3,2,2,6>: Cost 3 vmrghw <3,2,6,3>, <2,6,3,7> + 3368953777U, // <3,2,2,7>: Cost 4 vmrglw <2,2,3,2>, <2,6,2,7> + 1679001247U, // <3,2,2,u>: Cost 2 vsldoi12 LHS, <2,2,u,3> + 1678558886U, // <3,2,3,0>: Cost 2 vsldoi12 LHS, <2,3,0,1> + 2752300719U, // <3,2,3,1>: Cost 3 vsldoi12 LHS, <2,3,1,1> + 2752300729U, // <3,2,3,2>: Cost 3 vsldoi12 LHS, <2,3,2,2> + 1221476454U, // <3,2,3,3>: Cost 2 vmrglw <2,2,3,3>, LHS + 1678558926U, // <3,2,3,4>: Cost 2 vsldoi12 LHS, <2,3,4,5> + 2800076503U, // <3,2,3,5>: Cost 3 vsldoi12 LHS, <2,3,5,5> + 2234746810U, // <3,2,3,6>: Cost 3 vmrghw <3,3,3,3>, <2,6,3,7> + 2800076516U, // <3,2,3,7>: Cost 3 vsldoi12 LHS, <2,3,7,0> + 1678558958U, // <3,2,3,u>: Cost 2 vsldoi12 LHS, <2,3,u,1> + 3699130470U, // <3,2,4,0>: Cost 4 vsldoi4 <1,3,2,4>, LHS + 3362996972U, // <3,2,4,1>: Cost 4 vmrglw <1,2,3,4>, <1,0,2,1> + 2289256040U, // <3,2,4,2>: Cost 3 vmrglw <1,2,3,4>, <2,2,2,2> + 1215512678U, // <3,2,4,3>: Cost 2 vmrglw <1,2,3,4>, LHS + 3362998676U, // <3,2,4,4>: Cost 4 vmrglw <1,2,3,4>, <3,3,2,4> + 2691894582U, // <3,2,4,5>: Cost 3 vsldoi8 <1,2,3,2>, RHS + 2235582394U, // <3,2,4,6>: Cost 3 vmrghw <3,4,5,6>, <2,6,3,7> + 3734967544U, // <3,2,4,7>: Cost 4 vsldoi4 <7,3,2,4>, <7,3,2,4> + 1215512683U, // <3,2,4,u>: Cost 2 vmrglw <1,2,3,4>, LHS + 3705110630U, // <3,2,5,0>: Cost 4 vsldoi4 <2,3,2,5>, LHS + 3368313985U, // <3,2,5,1>: Cost 4 vmrglw <2,1,3,5>, <1,5,2,1> + 3368314472U, // <3,2,5,2>: Cost 4 vmrglw <2,1,3,5>, <2,2,2,2> + 2756945768U, // <3,2,5,3>: Cost 3 vsldoi12 LHS, <2,5,3,6> + 3705113910U, // <3,2,5,4>: Cost 4 vsldoi4 <2,3,2,5>, RHS + 3310061416U, // <3,2,5,5>: Cost 4 vmrghw <3,5,6,6>, <2,5,3,6> + 3310135226U, // <3,2,5,6>: Cost 4 vmrghw <3,5,7,6>, <2,6,3,7> + 3370305457U, // <3,2,5,7>: Cost 5 vmrglw <2,4,3,5>, <2,6,2,7> + 2752743317U, // <3,2,5,u>: Cost 3 vsldoi12 LHS, <2,5,u,6> + 2631376998U, // <3,2,6,0>: Cost 3 vsldoi4 <2,3,2,6>, LHS + 3705119540U, // <3,2,6,1>: Cost 4 vsldoi4 <2,3,2,6>, <1,1,1,1> + 2631378621U, // <3,2,6,2>: Cost 3 vsldoi4 <2,3,2,6>, <2,3,2,6> + 1678559162U, // <3,2,6,3>: Cost 2 vsldoi12 LHS, <2,6,3,7> + 2631380278U, // <3,2,6,4>: Cost 3 vsldoi4 <2,3,2,6>, RHS + 3370976956U, // <3,2,6,5>: Cost 4 vmrglw <2,5,3,6>, <2,3,2,5> + 2237065146U, // <3,2,6,6>: Cost 3 vmrghw <3,6,7,7>, <2,6,3,7> + 3798815594U, // <3,2,6,7>: Cost 4 vsldoi8 <6,7,3,2>, <6,7,3,2> + 1679001575U, // <3,2,6,u>: Cost 2 vsldoi12 LHS, <2,6,u,7> + 2800076778U, // <3,2,7,0>: Cost 3 vsldoi12 LHS, <2,7,0,1> + 3371647724U, // <3,2,7,1>: Cost 4 vmrglw <2,6,3,7>, <1,0,2,1> + 2297906792U, // <3,2,7,2>: Cost 3 vmrglw <2,6,3,7>, <2,2,2,2> + 1224163430U, // <3,2,7,3>: Cost 2 vmrglw <2,6,3,7>, LHS + 3705130294U, // <3,2,7,4>: Cost 4 vsldoi4 <2,3,2,7>, RHS + 3371648052U, // <3,2,7,5>: Cost 4 vmrglw <2,6,3,7>, <1,4,2,5> + 2297906877U, // <3,2,7,6>: Cost 3 vmrglw <2,6,3,7>, <2,3,2,6> + 3371648702U, // <3,2,7,7>: Cost 4 vmrglw <2,6,3,7>, <2,3,2,7> + 1224163435U, // <3,2,7,u>: Cost 2 vmrglw <2,6,3,7>, LHS + 1679001659U, // <3,2,u,0>: Cost 2 vsldoi12 LHS, <2,u,0,1> + 2752743492U, // <3,2,u,1>: Cost 3 vsldoi12 LHS, <2,u,1,1> + 1678558824U, // <3,2,u,2>: Cost 2 vsldoi12 LHS, <2,2,2,2> + 1678559320U, // <3,2,u,3>: Cost 2 vsldoi12 LHS, <2,u,3,3> + 1679001699U, // <3,2,u,4>: Cost 2 vsldoi12 LHS, <2,u,4,5> + 2691897498U, // <3,2,u,5>: Cost 3 vsldoi8 <1,2,3,2>, RHS + 2237908922U, // <3,2,u,6>: Cost 3 vmrghw <3,u,1,2>, <2,6,3,7> + 2800519289U, // <3,2,u,7>: Cost 3 vsldoi12 LHS, <2,u,7,0> + 1679001731U, // <3,2,u,u>: Cost 2 vsldoi12 LHS, <2,u,u,1> + 1215480726U, // <3,3,0,0>: Cost 2 vmrglw <1,2,3,0>, <1,2,3,0> + 1678559382U, // <3,3,0,1>: Cost 2 vsldoi12 LHS, <3,0,1,2> + 2631403200U, // <3,3,0,2>: Cost 3 vsldoi4 <2,3,3,0>, <2,3,3,0> + 2289223282U, // <3,3,0,3>: Cost 3 vmrglw <1,2,3,0>, <2,2,3,3> + 2752301232U, // <3,3,0,4>: Cost 3 vsldoi12 LHS, <3,0,4,1> + 3362965027U, // <3,3,0,5>: Cost 4 vmrglw <1,2,3,0>, <2,1,3,5> + 3362965352U, // <3,3,0,6>: Cost 4 vmrglw <1,2,3,0>, <2,5,3,6> + 2289223610U, // <3,3,0,7>: Cost 3 vmrglw <1,2,3,0>, <2,6,3,7> + 1678559445U, // <3,3,0,u>: Cost 2 vsldoi12 LHS, <3,0,u,2> + 3830687964U, // <3,3,1,0>: Cost 4 vsldoi12 LHS, <3,1,0,0> + 2752301286U, // <3,3,1,1>: Cost 3 vsldoi12 LHS, <3,1,1,1> + 2752301297U, // <3,3,1,2>: Cost 3 vsldoi12 LHS, <3,1,2,3> + 2305157532U, // <3,3,1,3>: Cost 3 vmrglw <3,u,3,1>, <3,3,3,3> + 3830688000U, // <3,3,1,4>: Cost 4 vsldoi12 LHS, <3,1,4,0> + 3830688009U, // <3,3,1,5>: Cost 4 vsldoi12 LHS, <3,1,5,0> + 3830688019U, // <3,3,1,6>: Cost 4 vsldoi12 LHS, <3,1,6,1> + 3362973626U, // <3,3,1,7>: Cost 4 vmrglw <1,2,3,1>, <2,6,3,7> + 2752743719U, // <3,3,1,u>: Cost 3 vsldoi12 LHS, <3,1,u,3> + 2631417958U, // <3,3,2,0>: Cost 3 vsldoi4 <2,3,3,2>, LHS + 3826043193U, // <3,3,2,1>: Cost 4 vsldoi12 LHS, <3,2,1,3> + 1624131186U, // <3,3,2,2>: Cost 2 vsldoi8 <2,2,3,3>, <2,2,3,3> + 2752301384U, // <3,3,2,3>: Cost 3 vsldoi12 LHS, <3,2,3,0> + 2631421238U, // <3,3,2,4>: Cost 3 vsldoi4 <2,3,3,2>, RHS + 3826485602U, // <3,3,2,5>: Cost 4 vsldoi12 LHS, <3,2,5,u> + 2752301414U, // <3,3,2,6>: Cost 3 vsldoi12 LHS, <3,2,6,3> + 2771249519U, // <3,3,2,7>: Cost 3 vsldoi12 <3,2,7,3>, <3,2,7,3> + 1628112984U, // <3,3,2,u>: Cost 2 vsldoi8 <2,u,3,3>, <2,u,3,3> + 1563656294U, // <3,3,3,0>: Cost 2 vsldoi4 <3,3,3,3>, LHS + 2301855911U, // <3,3,3,1>: Cost 3 vmrglw <3,3,3,3>, <3,0,3,1> + 2697873730U, // <3,3,3,2>: Cost 3 vsldoi8 <2,2,3,3>, <3,2,2,3> + 403488870U, // <3,3,3,3>: Cost 1 vspltisw3 LHS + 1563659574U, // <3,3,3,4>: Cost 2 vsldoi4 <3,3,3,3>, RHS + 2301856239U, // <3,3,3,5>: Cost 3 vmrglw <3,3,3,3>, <3,4,3,5> + 2697874067U, // <3,3,3,6>: Cost 3 vsldoi8 <2,2,3,3>, <3,6,3,7> + 2295220154U, // <3,3,3,7>: Cost 3 vmrglw <2,2,3,3>, <2,6,3,7> + 403488870U, // <3,3,3,u>: Cost 1 vspltisw3 LHS + 2289255318U, // <3,3,4,0>: Cost 3 vmrglw <1,2,3,4>, <1,2,3,0> + 2631435162U, // <3,3,4,1>: Cost 3 vsldoi4 <2,3,3,4>, <1,2,3,4> + 2631435972U, // <3,3,4,2>: Cost 3 vsldoi4 <2,3,3,4>, <2,3,3,4> + 2289256050U, // <3,3,4,3>: Cost 3 vmrglw <1,2,3,4>, <2,2,3,3> + 1215513498U, // <3,3,4,4>: Cost 2 vmrglw <1,2,3,4>, <1,2,3,4> + 1679002114U, // <3,3,4,5>: Cost 2 vsldoi12 LHS, <3,4,5,6> + 3362998120U, // <3,3,4,6>: Cost 4 vmrglw <1,2,3,4>, <2,5,3,6> + 2289256378U, // <3,3,4,7>: Cost 3 vmrglw <1,2,3,4>, <2,6,3,7> + 1679002141U, // <3,3,4,u>: Cost 2 vsldoi12 LHS, <3,4,u,6> + 3831130657U, // <3,3,5,0>: Cost 4 vsldoi12 LHS, <3,5,0,1> + 3376277671U, // <3,3,5,1>: Cost 4 vmrglw <3,4,3,5>, <3,0,3,1> + 3771617012U, // <3,3,5,2>: Cost 4 vsldoi8 <2,2,3,3>, <5,2,2,3> + 2302536092U, // <3,3,5,3>: Cost 3 vmrglw <3,4,3,5>, <3,3,3,3> + 3831130697U, // <3,3,5,4>: Cost 4 vsldoi12 LHS, <3,5,4,5> + 2294572579U, // <3,3,5,5>: Cost 3 vmrglw <2,1,3,5>, <2,1,3,5> + 2800519773U, // <3,3,5,6>: Cost 3 vsldoi12 LHS, <3,5,6,7> + 3368314810U, // <3,3,5,7>: Cost 4 vmrglw <2,1,3,5>, <2,6,3,7> + 2800519791U, // <3,3,5,u>: Cost 3 vsldoi12 LHS, <3,5,u,7> + 2800077432U, // <3,3,6,0>: Cost 3 vsldoi12 LHS, <3,6,0,7> + 3310291185U, // <3,3,6,1>: Cost 4 vmrghw <3,6,0,7>, <3,1,2,3> + 2789165706U, // <3,3,6,2>: Cost 3 vsldoi12 <6,2,7,3>, <3,6,2,7> + 2764982931U, // <3,3,6,3>: Cost 3 vsldoi12 <2,2,3,3>, <3,6,3,7> + 2800077468U, // <3,3,6,4>: Cost 3 vsldoi12 LHS, <3,6,4,7> + 3873819301U, // <3,3,6,5>: Cost 4 vsldoi12 LHS, <3,6,5,7> + 2297235304U, // <3,3,6,6>: Cost 3 vmrglw <2,5,3,6>, <2,5,3,6> + 2725081963U, // <3,3,6,7>: Cost 3 vsldoi8 <6,7,3,3>, <6,7,3,3> + 2725745596U, // <3,3,6,u>: Cost 3 vsldoi8 <6,u,3,3>, <6,u,3,3> + 2631458918U, // <3,3,7,0>: Cost 3 vsldoi4 <2,3,3,7>, LHS + 3705201460U, // <3,3,7,1>: Cost 4 vsldoi4 <2,3,3,7>, <1,1,1,1> + 2631460551U, // <3,3,7,2>: Cost 3 vsldoi4 <2,3,3,7>, <2,3,3,7> + 2297906802U, // <3,3,7,3>: Cost 3 vmrglw <2,6,3,7>, <2,2,3,3> + 2631462198U, // <3,3,7,4>: Cost 3 vsldoi4 <2,3,3,7>, RHS + 3371648547U, // <3,3,7,5>: Cost 4 vmrglw <2,6,3,7>, <2,1,3,5> + 3371648548U, // <3,3,7,6>: Cost 4 vmrglw <2,6,3,7>, <2,1,3,6> + 1224165306U, // <3,3,7,7>: Cost 2 vmrglw <2,6,3,7>, <2,6,3,7> + 1224165306U, // <3,3,7,u>: Cost 2 vmrglw <2,6,3,7>, <2,6,3,7> + 1215480726U, // <3,3,u,0>: Cost 2 vmrglw <1,2,3,0>, <1,2,3,0> + 1679002398U, // <3,3,u,1>: Cost 2 vsldoi12 LHS, <3,u,1,2> + 1659967368U, // <3,3,u,2>: Cost 2 vsldoi8 , + 403488870U, // <3,3,u,3>: Cost 1 vspltisw3 LHS + 1563659574U, // <3,3,u,4>: Cost 2 vsldoi4 <3,3,3,3>, RHS + 1679002438U, // <3,3,u,5>: Cost 2 vsldoi12 LHS, <3,u,5,6> + 2756946764U, // <3,3,u,6>: Cost 3 vsldoi12 LHS, <3,u,6,3> + 1224165306U, // <3,3,u,7>: Cost 2 vmrglw <2,6,3,7>, <2,6,3,7> + 403488870U, // <3,3,u,u>: Cost 1 vspltisw3 LHS + 2691907584U, // <3,4,0,0>: Cost 3 vsldoi8 <1,2,3,4>, <0,0,0,0> + 1618165862U, // <3,4,0,1>: Cost 2 vsldoi8 <1,2,3,4>, LHS + 2631476937U, // <3,4,0,2>: Cost 3 vsldoi4 <2,3,4,0>, <2,3,4,0> + 2232601732U, // <3,4,0,3>: Cost 3 vmrghw <3,0,1,2>, <4,3,5,0> + 2691907922U, // <3,4,0,4>: Cost 3 vsldoi8 <1,2,3,4>, <0,4,1,5> + 1158860086U, // <3,4,0,5>: Cost 2 vmrghw <3,0,1,2>, RHS + 3306343806U, // <3,4,0,6>: Cost 4 vmrghw <3,0,1,2>, <4,6,5,7> + 3366947484U, // <3,4,0,7>: Cost 4 vmrglw <1,u,3,0>, <3,6,4,7> + 1618166429U, // <3,4,0,u>: Cost 2 vsldoi8 <1,2,3,4>, LHS + 2631483494U, // <3,4,1,0>: Cost 3 vsldoi4 <2,3,4,1>, LHS + 2691908404U, // <3,4,1,1>: Cost 3 vsldoi8 <1,2,3,4>, <1,1,1,1> + 1618166682U, // <3,4,1,2>: Cost 2 vsldoi8 <1,2,3,4>, <1,2,3,4> + 3765650393U, // <3,4,1,3>: Cost 4 vsldoi8 <1,2,3,4>, <1,3,1,4> + 2631486774U, // <3,4,1,4>: Cost 3 vsldoi4 <2,3,4,1>, RHS + 2756946914U, // <3,4,1,5>: Cost 3 vsldoi12 LHS, <4,1,5,0> + 3765650639U, // <3,4,1,6>: Cost 4 vsldoi8 <1,2,3,4>, <1,6,1,7> + 3735090439U, // <3,4,1,7>: Cost 4 vsldoi4 <7,3,4,1>, <7,3,4,1> + 1622148480U, // <3,4,1,u>: Cost 2 vsldoi8 <1,u,3,4>, <1,u,3,4> + 3765650893U, // <3,4,2,0>: Cost 4 vsldoi8 <1,2,3,4>, <2,0,3,0> + 3831131154U, // <3,4,2,1>: Cost 4 vsldoi12 LHS, <4,2,1,3> + 2691909224U, // <3,4,2,2>: Cost 3 vsldoi8 <1,2,3,4>, <2,2,2,2> + 2691909286U, // <3,4,2,3>: Cost 3 vsldoi8 <1,2,3,4>, <2,3,0,1> + 2699208469U, // <3,4,2,4>: Cost 3 vsldoi8 <2,4,3,4>, <2,4,3,4> + 2233863478U, // <3,4,2,5>: Cost 3 vmrghw <3,2,0,3>, RHS + 2691909562U, // <3,4,2,6>: Cost 3 vsldoi8 <1,2,3,4>, <2,6,3,7> + 2701199368U, // <3,4,2,7>: Cost 3 vsldoi8 <2,7,3,4>, <2,7,3,4> + 2691909691U, // <3,4,2,u>: Cost 3 vsldoi8 <1,2,3,4>, <2,u,0,1> + 2691909782U, // <3,4,3,0>: Cost 3 vsldoi8 <1,2,3,4>, <3,0,1,2> + 3765651686U, // <3,4,3,1>: Cost 4 vsldoi8 <1,2,3,4>, <3,1,1,1> + 2691909972U, // <3,4,3,2>: Cost 3 vsldoi8 <1,2,3,4>, <3,2,4,3> + 2691910044U, // <3,4,3,3>: Cost 3 vsldoi8 <1,2,3,4>, <3,3,3,3> + 2691910096U, // <3,4,3,4>: Cost 3 vsldoi8 <1,2,3,4>, <3,4,0,1> + 1161006390U, // <3,4,3,5>: Cost 2 vmrghw <3,3,3,3>, RHS + 2691910300U, // <3,4,3,6>: Cost 3 vsldoi8 <1,2,3,4>, <3,6,4,7> + 3368962716U, // <3,4,3,7>: Cost 4 vmrglw <2,2,3,3>, <3,6,4,7> + 1161006633U, // <3,4,3,u>: Cost 2 vmrghw <3,3,3,3>, RHS + 2631508070U, // <3,4,4,0>: Cost 3 vsldoi4 <2,3,4,4>, LHS + 2631508890U, // <3,4,4,1>: Cost 3 vsldoi4 <2,3,4,4>, <1,2,3,4> + 2631509709U, // <3,4,4,2>: Cost 3 vsldoi4 <2,3,4,4>, <2,3,4,4> + 2289256788U, // <3,4,4,3>: Cost 3 vmrglw <1,2,3,4>, <3,2,4,3> + 1726336208U, // <3,4,4,4>: Cost 2 vsldoi12 LHS, <4,4,4,4> + 1618169142U, // <3,4,4,5>: Cost 2 vsldoi8 <1,2,3,4>, RHS + 3362998858U, // <3,4,4,6>: Cost 4 vmrglw <1,2,3,4>, <3,5,4,6> + 2289257116U, // <3,4,4,7>: Cost 3 vmrglw <1,2,3,4>, <3,6,4,7> + 1618169385U, // <3,4,4,u>: Cost 2 vsldoi8 <1,2,3,4>, RHS + 1557774438U, // <3,4,5,0>: Cost 2 vsldoi4 <2,3,4,5>, LHS + 2631516980U, // <3,4,5,1>: Cost 3 vsldoi4 <2,3,4,5>, <1,1,1,1> + 1557776078U, // <3,4,5,2>: Cost 2 vsldoi4 <2,3,4,5>, <2,3,4,5> + 2631518358U, // <3,4,5,3>: Cost 3 vsldoi4 <2,3,4,5>, <3,0,1,2> + 1557777718U, // <3,4,5,4>: Cost 2 vsldoi4 <2,3,4,5>, RHS + 2296563406U, // <3,4,5,5>: Cost 3 vmrglw <2,4,3,5>, <2,3,4,5> + 604818742U, // <3,4,5,6>: Cost 1 vsldoi12 LHS, RHS + 2661381387U, // <3,4,5,7>: Cost 3 vsldoi4 <7,3,4,5>, <7,3,4,5> + 604818760U, // <3,4,5,u>: Cost 1 vsldoi12 LHS, RHS + 3705266278U, // <3,4,6,0>: Cost 4 vsldoi4 <2,3,4,6>, LHS + 3831131482U, // <3,4,6,1>: Cost 4 vsldoi12 LHS, <4,6,1,7> + 2733715962U, // <3,4,6,2>: Cost 3 vsldoi8 , <6,2,7,3> + 3844771180U, // <3,4,6,3>: Cost 4 vsldoi12 <3,2,4,3>, <4,6,3,7> + 2800078197U, // <3,4,6,4>: Cost 3 vsldoi12 LHS, <4,6,4,7> + 2236550454U, // <3,4,6,5>: Cost 3 vmrghw <3,6,0,7>, RHS + 2733716280U, // <3,4,6,6>: Cost 3 vsldoi8 , <6,6,6,6> + 2725090156U, // <3,4,6,7>: Cost 3 vsldoi8 <6,7,3,4>, <6,7,3,4> + 2236550697U, // <3,4,6,u>: Cost 3 vmrghw <3,6,0,7>, RHS + 2733716474U, // <3,4,7,0>: Cost 3 vsldoi8 , <7,0,1,2> + 3371647013U, // <3,4,7,1>: Cost 4 vmrglw <2,6,3,7>, <0,0,4,1> + 2727744688U, // <3,4,7,2>: Cost 3 vsldoi8 <7,2,3,4>, <7,2,3,4> + 3371649364U, // <3,4,7,3>: Cost 4 vmrglw <2,6,3,7>, <3,2,4,3> + 2733716838U, // <3,4,7,4>: Cost 3 vsldoi8 , <7,4,5,6> + 2297906894U, // <3,4,7,5>: Cost 3 vmrglw <2,6,3,7>, <2,3,4,5> + 3371647180U, // <3,4,7,6>: Cost 4 vmrglw <2,6,3,7>, <0,2,4,6> + 2733717100U, // <3,4,7,7>: Cost 3 vsldoi8 , <7,7,7,7> + 2297906897U, // <3,4,7,u>: Cost 3 vmrglw <2,6,3,7>, <2,3,4,u> + 1557799014U, // <3,4,u,0>: Cost 2 vsldoi4 <2,3,4,u>, LHS + 1618171694U, // <3,4,u,1>: Cost 2 vsldoi8 <1,2,3,4>, LHS + 1557800657U, // <3,4,u,2>: Cost 2 vsldoi4 <2,3,4,u>, <2,3,4,u> + 2691913660U, // <3,4,u,3>: Cost 3 vsldoi8 <1,2,3,4>, + 1557802294U, // <3,4,u,4>: Cost 2 vsldoi4 <2,3,4,u>, RHS + 1618172058U, // <3,4,u,5>: Cost 2 vsldoi8 <1,2,3,4>, RHS + 604818985U, // <3,4,u,6>: Cost 1 vsldoi12 LHS, RHS + 2661405966U, // <3,4,u,7>: Cost 3 vsldoi4 <7,3,4,u>, <7,3,4,u> + 604819003U, // <3,4,u,u>: Cost 1 vsldoi12 LHS, RHS + 2643492966U, // <3,5,0,0>: Cost 3 vsldoi4 <4,3,5,0>, LHS + 2756947528U, // <3,5,0,1>: Cost 3 vsldoi12 LHS, <5,0,1,2> + 2331029019U, // <3,5,0,2>: Cost 3 vmrglw , <4,u,5,2> + 2643495062U, // <3,5,0,3>: Cost 3 vsldoi4 <4,3,5,0>, <3,0,1,2> + 2756947554U, // <3,5,0,4>: Cost 3 vsldoi12 LHS, <5,0,4,1> + 2800078443U, // <3,5,0,5>: Cost 3 vsldoi12 LHS, <5,0,5,1> + 2289224194U, // <3,5,0,6>: Cost 3 vmrglw <1,2,3,0>, <3,4,5,6> + 3362964723U, // <3,5,0,7>: Cost 4 vmrglw <1,2,3,0>, <1,6,5,7> + 2756947590U, // <3,5,0,u>: Cost 3 vsldoi12 LHS, <5,0,u,1> + 2800078479U, // <3,5,1,0>: Cost 3 vsldoi12 LHS, <5,1,0,1> + 2333027218U, // <3,5,1,1>: Cost 3 vmrglw , <4,0,5,1> + 2691916699U, // <3,5,1,2>: Cost 3 vsldoi8 <1,2,3,5>, <1,2,3,5> + 3832901294U, // <3,5,1,3>: Cost 4 vsldoi12 <1,2,5,3>, <5,1,3,5> + 2800078519U, // <3,5,1,4>: Cost 3 vsldoi12 LHS, <5,1,4,5> + 3830689467U, // <3,5,1,5>: Cost 4 vsldoi12 LHS, <5,1,5,0> + 3830689481U, // <3,5,1,6>: Cost 4 vsldoi12 LHS, <5,1,6,5> + 3873820365U, // <3,5,1,7>: Cost 4 vsldoi12 LHS, <5,1,7,0> + 2800078551U, // <3,5,1,u>: Cost 3 vsldoi12 LHS, <5,1,u,1> + 3770967487U, // <3,5,2,0>: Cost 4 vsldoi8 <2,1,3,5>, <2,0,1,4> + 2697225763U, // <3,5,2,1>: Cost 3 vsldoi8 <2,1,3,5>, <2,1,3,5> + 3830689523U, // <3,5,2,2>: Cost 4 vsldoi12 LHS, <5,2,2,2> + 2699216590U, // <3,5,2,3>: Cost 3 vsldoi8 <2,4,3,5>, <2,3,4,5> + 2699216662U, // <3,5,2,4>: Cost 3 vsldoi8 <2,4,3,5>, <2,4,3,5> + 2783047439U, // <3,5,2,5>: Cost 3 vsldoi12 <5,2,5,3>, <5,2,5,3> + 2783121176U, // <3,5,2,6>: Cost 3 vsldoi12 <5,2,6,3>, <5,2,6,3> + 3856936737U, // <3,5,2,7>: Cost 4 vsldoi12 <5,2,7,3>, <5,2,7,3> + 2701871194U, // <3,5,2,u>: Cost 3 vsldoi8 <2,u,3,5>, <2,u,3,5> + 2643517542U, // <3,5,3,0>: Cost 3 vsldoi4 <4,3,5,3>, LHS + 2331052946U, // <3,5,3,1>: Cost 3 vmrglw , <4,0,5,1> + 3699345010U, // <3,5,3,2>: Cost 4 vsldoi4 <1,3,5,3>, <2,2,3,3> + 2705189276U, // <3,5,3,3>: Cost 3 vsldoi8 <3,4,3,5>, <3,3,3,3> + 2705189359U, // <3,5,3,4>: Cost 3 vsldoi8 <3,4,3,5>, <3,4,3,5> + 2331053274U, // <3,5,3,5>: Cost 3 vmrglw , <4,4,5,5> + 2295220738U, // <3,5,3,6>: Cost 3 vmrglw <2,2,3,3>, <3,4,5,6> + 3368961267U, // <3,5,3,7>: Cost 4 vmrglw <2,2,3,3>, <1,6,5,7> + 2295220740U, // <3,5,3,u>: Cost 3 vmrglw <2,2,3,3>, <3,4,5,u> + 2643525734U, // <3,5,4,0>: Cost 3 vsldoi4 <4,3,5,4>, LHS + 2331061138U, // <3,5,4,1>: Cost 3 vmrglw , <4,0,5,1> + 2235584280U, // <3,5,4,2>: Cost 3 vmrghw <3,4,5,6>, <5,2,6,3> + 2643528194U, // <3,5,4,3>: Cost 3 vsldoi4 <4,3,5,4>, <3,4,5,6> + 2735713498U, // <3,5,4,4>: Cost 3 vsldoi8 , <4,4,5,5> + 2756947892U, // <3,5,4,5>: Cost 3 vsldoi12 LHS, <5,4,5,6> + 2289256962U, // <3,5,4,6>: Cost 3 vmrglw <1,2,3,4>, <3,4,5,6> + 3362997491U, // <3,5,4,7>: Cost 4 vmrglw <1,2,3,4>, <1,6,5,7> + 2756947919U, // <3,5,4,u>: Cost 3 vsldoi12 LHS, <5,4,u,6> + 2800078803U, // <3,5,5,0>: Cost 3 vsldoi12 LHS, <5,5,0,1> + 2800078812U, // <3,5,5,1>: Cost 3 vsldoi12 LHS, <5,5,1,1> + 2631591639U, // <3,5,5,2>: Cost 3 vsldoi4 <2,3,5,5>, <2,3,5,5> + 3832901616U, // <3,5,5,3>: Cost 4 vsldoi12 <1,2,5,3>, <5,5,3,3> + 2800078843U, // <3,5,5,4>: Cost 3 vsldoi12 LHS, <5,5,4,5> + 1726337028U, // <3,5,5,5>: Cost 2 vsldoi12 LHS, <5,5,5,5> + 2800078862U, // <3,5,5,6>: Cost 3 vsldoi12 LHS, <5,5,6,6> + 3368314099U, // <3,5,5,7>: Cost 4 vmrglw <2,1,3,5>, <1,6,5,7> + 1726337028U, // <3,5,5,u>: Cost 2 vsldoi12 LHS, <5,5,5,5> + 2800078884U, // <3,5,6,0>: Cost 3 vsldoi12 LHS, <5,6,0,1> + 2800078899U, // <3,5,6,1>: Cost 3 vsldoi12 LHS, <5,6,1,7> + 2631599832U, // <3,5,6,2>: Cost 3 vsldoi4 <2,3,5,6>, <2,3,5,6> + 2800078914U, // <3,5,6,3>: Cost 3 vsldoi12 LHS, <5,6,3,4> + 2800078924U, // <3,5,6,4>: Cost 3 vsldoi12 LHS, <5,6,4,5> + 2800078935U, // <3,5,6,5>: Cost 3 vsldoi12 LHS, <5,6,5,7> + 2297235970U, // <3,5,6,6>: Cost 3 vmrglw <2,5,3,6>, <3,4,5,6> + 1726337122U, // <3,5,6,7>: Cost 2 vsldoi12 LHS, <5,6,7,0> + 1726337131U, // <3,5,6,u>: Cost 2 vsldoi12 LHS, <5,6,u,0> + 3699376230U, // <3,5,7,0>: Cost 4 vsldoi4 <1,3,5,7>, LHS + 2333739922U, // <3,5,7,1>: Cost 3 vmrglw , <4,0,5,1> + 3699378106U, // <3,5,7,2>: Cost 4 vsldoi4 <1,3,5,7>, <2,6,3,7> + 3371647915U, // <3,5,7,3>: Cost 4 vmrglw <2,6,3,7>, <1,2,5,3> + 3699379510U, // <3,5,7,4>: Cost 4 vsldoi4 <1,3,5,7>, RHS + 2333740250U, // <3,5,7,5>: Cost 3 vmrglw , <4,4,5,5> + 2297907714U, // <3,5,7,6>: Cost 3 vmrglw <2,6,3,7>, <3,4,5,6> + 3370984691U, // <3,5,7,7>: Cost 4 vmrglw <2,5,3,7>, <1,6,5,7> + 2297907716U, // <3,5,7,u>: Cost 3 vmrglw <2,6,3,7>, <3,4,5,u> + 2800079046U, // <3,5,u,0>: Cost 3 vsldoi12 LHS, <5,u,0,1> + 2756948176U, // <3,5,u,1>: Cost 3 vsldoi12 LHS, <5,u,1,2> + 2331029019U, // <3,5,u,2>: Cost 3 vmrglw , <4,u,5,2> + 2800079076U, // <3,5,u,3>: Cost 3 vsldoi12 LHS, <5,u,3,4> + 2800079085U, // <3,5,u,4>: Cost 3 vsldoi12 LHS, <5,u,4,4> + 1726337028U, // <3,5,u,5>: Cost 2 vsldoi12 LHS, <5,5,5,5> + 2289289730U, // <3,5,u,6>: Cost 3 vmrglw <1,2,3,u>, <3,4,5,6> + 1726337284U, // <3,5,u,7>: Cost 2 vsldoi12 LHS, <5,u,7,0> + 1726337293U, // <3,5,u,u>: Cost 2 vsldoi12 LHS, <5,u,u,0> + 3773628416U, // <3,6,0,0>: Cost 4 vsldoi8 <2,5,3,6>, <0,0,0,0> + 2699886694U, // <3,6,0,1>: Cost 3 vsldoi8 <2,5,3,6>, LHS + 2789167401U, // <3,6,0,2>: Cost 3 vsldoi12 <6,2,7,3>, <6,0,2,1> + 3362965862U, // <3,6,0,3>: Cost 4 vmrglw <1,2,3,0>, <3,2,6,3> + 3773628754U, // <3,6,0,4>: Cost 4 vsldoi8 <2,5,3,6>, <0,4,1,5> + 3723284326U, // <3,6,0,5>: Cost 4 vsldoi4 <5,3,6,0>, <5,3,6,0> + 2800079181U, // <3,6,0,6>: Cost 3 vsldoi12 LHS, <6,0,6,1> + 1215483190U, // <3,6,0,7>: Cost 2 vmrglw <1,2,3,0>, RHS + 1215483191U, // <3,6,0,u>: Cost 2 vmrglw <1,2,3,0>, RHS + 3873821032U, // <3,6,1,0>: Cost 4 vsldoi12 LHS, <6,1,0,1> + 3773629236U, // <3,6,1,1>: Cost 4 vsldoi8 <2,5,3,6>, <1,1,1,1> + 2691924892U, // <3,6,1,2>: Cost 3 vsldoi8 <1,2,3,6>, <1,2,3,6> + 3830690184U, // <3,6,1,3>: Cost 5 vsldoi12 LHS, <6,1,3,6> + 3873821072U, // <3,6,1,4>: Cost 4 vsldoi12 LHS, <6,1,4,5> + 3873821082U, // <3,6,1,5>: Cost 4 vsldoi12 LHS, <6,1,5,6> + 3403453240U, // <3,6,1,6>: Cost 4 vmrglw , <6,6,6,6> + 2289233206U, // <3,6,1,7>: Cost 3 vmrglw <1,2,3,1>, RHS + 2289233207U, // <3,6,1,u>: Cost 3 vmrglw <1,2,3,1>, RHS + 2661498982U, // <3,6,2,0>: Cost 3 vsldoi4 <7,3,6,2>, LHS + 3770975780U, // <3,6,2,1>: Cost 4 vsldoi8 <2,1,3,6>, <2,1,3,6> + 2631640797U, // <3,6,2,2>: Cost 3 vsldoi4 <2,3,6,2>, <2,3,6,2> + 3771639485U, // <3,6,2,3>: Cost 4 vsldoi8 <2,2,3,6>, <2,3,2,6> + 2661502262U, // <3,6,2,4>: Cost 3 vsldoi4 <7,3,6,2>, RHS + 2699888488U, // <3,6,2,5>: Cost 3 vsldoi8 <2,5,3,6>, <2,5,3,6> + 2661503482U, // <3,6,2,6>: Cost 3 vsldoi4 <7,3,6,2>, <6,2,7,3> + 1715425786U, // <3,6,2,7>: Cost 2 vsldoi12 <6,2,7,3>, <6,2,7,3> + 1715499523U, // <3,6,2,u>: Cost 2 vsldoi12 <6,2,u,3>, <6,2,u,3> + 3773630614U, // <3,6,3,0>: Cost 4 vsldoi8 <2,5,3,6>, <3,0,1,2> + 3372942825U, // <3,6,3,1>: Cost 4 vmrglw <2,u,3,3>, <2,0,6,1> + 2234749434U, // <3,6,3,2>: Cost 3 vmrghw <3,3,3,3>, <6,2,7,3> + 3368962406U, // <3,6,3,3>: Cost 4 vmrglw <2,2,3,3>, <3,2,6,3> + 2699889154U, // <3,6,3,4>: Cost 3 vsldoi8 <2,5,3,6>, <3,4,5,6> + 3773631068U, // <3,6,3,5>: Cost 4 vsldoi8 <2,5,3,6>, <3,5,6,6> + 2331054904U, // <3,6,3,6>: Cost 3 vmrglw , <6,6,6,6> + 1221479734U, // <3,6,3,7>: Cost 2 vmrglw <2,2,3,3>, RHS + 1221479735U, // <3,6,3,u>: Cost 2 vmrglw <2,2,3,3>, RHS + 2235584801U, // <3,6,4,0>: Cost 3 vmrghw <3,4,5,6>, <6,0,1,2> + 3717342106U, // <3,6,4,1>: Cost 4 vsldoi4 <4,3,6,4>, <1,2,3,4> + 2789167729U, // <3,6,4,2>: Cost 3 vsldoi12 <6,2,7,3>, <6,4,2,5> + 2235585074U, // <3,6,4,3>: Cost 3 vmrghw <3,4,5,6>, <6,3,4,5> + 2235585165U, // <3,6,4,4>: Cost 3 vmrghw <3,4,5,6>, <6,4,5,6> + 2699889974U, // <3,6,4,5>: Cost 3 vsldoi8 <2,5,3,6>, RHS + 2800079509U, // <3,6,4,6>: Cost 3 vsldoi12 LHS, <6,4,6,5> + 1215515958U, // <3,6,4,7>: Cost 2 vmrglw <1,2,3,4>, RHS + 1215515959U, // <3,6,4,u>: Cost 2 vmrglw <1,2,3,4>, RHS + 3873821356U, // <3,6,5,0>: Cost 4 vsldoi12 LHS, <6,5,0,1> + 3372959209U, // <3,6,5,1>: Cost 5 vmrglw <2,u,3,5>, <2,0,6,1> + 3862909629U, // <3,6,5,2>: Cost 4 vsldoi12 <6,2,7,3>, <6,5,2,0> + 3773632358U, // <3,6,5,3>: Cost 4 vsldoi8 <2,5,3,6>, <5,3,6,0> + 3873821396U, // <3,6,5,4>: Cost 4 vsldoi12 LHS, <6,5,4,5> + 3873821405U, // <3,6,5,5>: Cost 4 vsldoi12 LHS, <6,5,5,5> + 3862909672U, // <3,6,5,6>: Cost 4 vsldoi12 <6,2,7,3>, <6,5,6,7> + 2294574390U, // <3,6,5,7>: Cost 3 vmrglw <2,1,3,5>, RHS + 2294574391U, // <3,6,5,u>: Cost 3 vmrglw <2,1,3,5>, RHS + 2800079613U, // <3,6,6,0>: Cost 3 vsldoi12 LHS, <6,6,0,1> + 3873821446U, // <3,6,6,1>: Cost 4 vsldoi12 LHS, <6,6,1,1> + 2789167888U, // <3,6,6,2>: Cost 3 vsldoi12 <6,2,7,3>, <6,6,2,2> + 3844920090U, // <3,6,6,3>: Cost 4 vsldoi12 <3,2,6,3>, <6,6,3,3> + 2800079653U, // <3,6,6,4>: Cost 3 vsldoi12 LHS, <6,6,4,5> + 3723333484U, // <3,6,6,5>: Cost 4 vsldoi4 <5,3,6,6>, <5,3,6,6> + 1726337848U, // <3,6,6,6>: Cost 2 vsldoi12 LHS, <6,6,6,6> + 1726337858U, // <3,6,6,7>: Cost 2 vsldoi12 LHS, <6,6,7,7> + 1726337867U, // <3,6,6,u>: Cost 2 vsldoi12 LHS, <6,6,u,7> + 1726337870U, // <3,6,7,0>: Cost 2 vsldoi12 LHS, <6,7,0,1> + 2297906665U, // <3,6,7,1>: Cost 3 vmrglw <2,6,3,7>, <2,0,6,1> + 2792117090U, // <3,6,7,2>: Cost 3 vsldoi12 <6,7,2,3>, <6,7,2,3> + 2297907558U, // <3,6,7,3>: Cost 3 vmrglw <2,6,3,7>, <3,2,6,3> + 1726337910U, // <3,6,7,4>: Cost 2 vsldoi12 LHS, <6,7,4,5> + 2297906993U, // <3,6,7,5>: Cost 3 vmrglw <2,6,3,7>, <2,4,6,5> + 2297906832U, // <3,6,7,6>: Cost 3 vmrglw <2,6,3,7>, <2,2,6,6> + 1224166710U, // <3,6,7,7>: Cost 2 vmrglw <2,6,3,7>, RHS + 1224166711U, // <3,6,7,u>: Cost 2 vmrglw <2,6,3,7>, RHS + 1726337951U, // <3,6,u,0>: Cost 2 vsldoi12 LHS, <6,u,0,1> + 2699892526U, // <3,6,u,1>: Cost 3 vsldoi8 <2,5,3,6>, LHS + 2789168049U, // <3,6,u,2>: Cost 3 vsldoi12 <6,2,7,3>, <6,u,2,1> + 2792854460U, // <3,6,u,3>: Cost 3 vsldoi12 <6,u,3,3>, <6,u,3,3> + 1726337991U, // <3,6,u,4>: Cost 2 vsldoi12 LHS, <6,u,4,5> + 2699892890U, // <3,6,u,5>: Cost 3 vsldoi8 <2,5,3,6>, RHS + 1726337848U, // <3,6,u,6>: Cost 2 vsldoi12 LHS, <6,6,6,6> + 1215548726U, // <3,6,u,7>: Cost 2 vmrglw <1,2,3,u>, RHS + 1215548727U, // <3,6,u,u>: Cost 2 vmrglw <1,2,3,u>, RHS + 2700558336U, // <3,7,0,0>: Cost 3 vsldoi8 <2,6,3,7>, <0,0,0,0> + 1626816614U, // <3,7,0,1>: Cost 2 vsldoi8 <2,6,3,7>, LHS + 2700558513U, // <3,7,0,2>: Cost 3 vsldoi8 <2,6,3,7>, <0,2,1,6> + 2331030010U, // <3,7,0,3>: Cost 3 vmrglw , <6,2,7,3> + 2700558674U, // <3,7,0,4>: Cost 3 vsldoi8 <2,6,3,7>, <0,4,1,5> + 2800079906U, // <3,7,0,5>: Cost 3 vsldoi12 LHS, <7,0,5,6> + 2655588936U, // <3,7,0,6>: Cost 3 vsldoi4 <6,3,7,0>, <6,3,7,0> + 2800079919U, // <3,7,0,7>: Cost 3 vsldoi12 LHS, <7,0,7,1> + 1626817181U, // <3,7,0,u>: Cost 2 vsldoi8 <2,6,3,7>, LHS + 3774300899U, // <3,7,1,0>: Cost 4 vsldoi8 <2,6,3,7>, <1,0,1,1> + 2700559156U, // <3,7,1,1>: Cost 3 vsldoi8 <2,6,3,7>, <1,1,1,1> + 2700559254U, // <3,7,1,2>: Cost 3 vsldoi8 <2,6,3,7>, <1,2,3,0> + 3774301148U, // <3,7,1,3>: Cost 4 vsldoi8 <2,6,3,7>, <1,3,1,7> + 3774301227U, // <3,7,1,4>: Cost 4 vsldoi8 <2,6,3,7>, <1,4,1,5> + 3774301295U, // <3,7,1,5>: Cost 4 vsldoi8 <2,6,3,7>, <1,5,0,1> + 3768329441U, // <3,7,1,6>: Cost 4 vsldoi8 <1,6,3,7>, <1,6,3,7> + 3403453250U, // <3,7,1,7>: Cost 4 vmrglw , <6,6,7,7> + 2700559740U, // <3,7,1,u>: Cost 3 vsldoi8 <2,6,3,7>, <1,u,3,0> + 2700559849U, // <3,7,2,0>: Cost 3 vsldoi8 <2,6,3,7>, <2,0,6,1> + 3770983973U, // <3,7,2,1>: Cost 4 vsldoi8 <2,1,3,7>, <2,1,3,7> + 2700559976U, // <3,7,2,2>: Cost 3 vsldoi8 <2,6,3,7>, <2,2,2,2> + 2698569415U, // <3,7,2,3>: Cost 3 vsldoi8 <2,3,3,7>, <2,3,3,7> + 2700560177U, // <3,7,2,4>: Cost 3 vsldoi8 <2,6,3,7>, <2,4,6,5> + 3773638505U, // <3,7,2,5>: Cost 4 vsldoi8 <2,5,3,7>, <2,5,3,7> + 1626818490U, // <3,7,2,6>: Cost 2 vsldoi8 <2,6,3,7>, <2,6,3,7> + 2795140307U, // <3,7,2,7>: Cost 3 vsldoi12 <7,2,7,3>, <7,2,7,3> + 1628145756U, // <3,7,2,u>: Cost 2 vsldoi8 <2,u,3,7>, <2,u,3,7> + 2700560534U, // <3,7,3,0>: Cost 3 vsldoi8 <2,6,3,7>, <3,0,1,2> + 3774302438U, // <3,7,3,1>: Cost 4 vsldoi8 <2,6,3,7>, <3,1,1,1> + 2700560742U, // <3,7,3,2>: Cost 3 vsldoi8 <2,6,3,7>, <3,2,6,3> + 2700560796U, // <3,7,3,3>: Cost 3 vsldoi8 <2,6,3,7>, <3,3,3,3> + 2700560898U, // <3,7,3,4>: Cost 3 vsldoi8 <2,6,3,7>, <3,4,5,6> + 3774302821U, // <3,7,3,5>: Cost 4 vsldoi8 <2,6,3,7>, <3,5,7,6> + 2700561079U, // <3,7,3,6>: Cost 3 vsldoi8 <2,6,3,7>, <3,6,7,7> + 2700561091U, // <3,7,3,7>: Cost 3 vsldoi8 <2,6,3,7>, <3,7,0,1> + 2700561182U, // <3,7,3,u>: Cost 3 vsldoi8 <2,6,3,7>, <3,u,1,2> + 2655617126U, // <3,7,4,0>: Cost 3 vsldoi4 <6,3,7,4>, LHS + 3774303178U, // <3,7,4,1>: Cost 4 vsldoi8 <2,6,3,7>, <4,1,2,3> + 2655619002U, // <3,7,4,2>: Cost 3 vsldoi4 <6,3,7,4>, <2,6,3,7> + 2331062778U, // <3,7,4,3>: Cost 3 vmrglw , <6,2,7,3> + 2655620406U, // <3,7,4,4>: Cost 3 vsldoi4 <6,3,7,4>, RHS + 1626819894U, // <3,7,4,5>: Cost 2 vsldoi8 <2,6,3,7>, RHS + 2655621708U, // <3,7,4,6>: Cost 3 vsldoi4 <6,3,7,4>, <6,3,7,4> + 2800080247U, // <3,7,4,7>: Cost 3 vsldoi12 LHS, <7,4,7,5> + 1626820137U, // <3,7,4,u>: Cost 2 vsldoi8 <2,6,3,7>, RHS + 3774303816U, // <3,7,5,0>: Cost 4 vsldoi8 <2,6,3,7>, <5,0,1,2> + 3873822093U, // <3,7,5,1>: Cost 4 vsldoi12 LHS, <7,5,1,0> + 3774303998U, // <3,7,5,2>: Cost 4 vsldoi8 <2,6,3,7>, <5,2,3,4> + 3862910368U, // <3,7,5,3>: Cost 4 vsldoi12 <6,2,7,3>, <7,5,3,1> + 3774304180U, // <3,7,5,4>: Cost 4 vsldoi8 <2,6,3,7>, <5,4,5,6> + 2800080310U, // <3,7,5,5>: Cost 3 vsldoi12 LHS, <7,5,5,5> + 2800080321U, // <3,7,5,6>: Cost 3 vsldoi12 LHS, <7,5,6,7> + 3873822147U, // <3,7,5,7>: Cost 4 vsldoi12 LHS, <7,5,7,0> + 2800080339U, // <3,7,5,u>: Cost 3 vsldoi12 LHS, <7,5,u,7> + 2800080348U, // <3,7,6,0>: Cost 3 vsldoi12 LHS, <7,6,0,7> + 3873822181U, // <3,7,6,1>: Cost 4 vsldoi12 LHS, <7,6,1,7> + 2789168622U, // <3,7,6,2>: Cost 3 vsldoi12 <6,2,7,3>, <7,6,2,7> + 2700563016U, // <3,7,6,3>: Cost 3 vsldoi8 <2,6,3,7>, <6,3,7,0> + 2800080384U, // <3,7,6,4>: Cost 3 vsldoi12 LHS, <7,6,4,7> + 3862910472U, // <3,7,6,5>: Cost 4 vsldoi12 <6,2,7,3>, <7,6,5,6> + 2700563256U, // <3,7,6,6>: Cost 3 vsldoi8 <2,6,3,7>, <6,6,6,6> + 2800080404U, // <3,7,6,7>: Cost 3 vsldoi12 LHS, <7,6,7,0> + 2793149988U, // <3,7,6,u>: Cost 3 vsldoi12 <6,u,7,3>, <7,6,u,7> + 2637725798U, // <3,7,7,0>: Cost 3 vsldoi4 <3,3,7,7>, LHS + 3371649227U, // <3,7,7,1>: Cost 4 vmrglw <2,6,3,7>, <3,0,7,1> + 2637727674U, // <3,7,7,2>: Cost 3 vsldoi4 <3,3,7,7>, <2,6,3,7> + 2297907567U, // <3,7,7,3>: Cost 3 vmrglw <2,6,3,7>, <3,2,7,3> + 2637729078U, // <3,7,7,4>: Cost 3 vsldoi4 <3,3,7,7>, RHS + 3371649312U, // <3,7,7,5>: Cost 4 vmrglw <2,6,3,7>, <3,1,7,5> + 2655646287U, // <3,7,7,6>: Cost 3 vsldoi4 <6,3,7,7>, <6,3,7,7> + 1726338668U, // <3,7,7,7>: Cost 2 vsldoi12 LHS, <7,7,7,7> + 1726338668U, // <3,7,7,u>: Cost 2 vsldoi12 LHS, <7,7,7,7> + 2700564179U, // <3,7,u,0>: Cost 3 vsldoi8 <2,6,3,7>, + 1626822446U, // <3,7,u,1>: Cost 2 vsldoi8 <2,6,3,7>, LHS + 2700564357U, // <3,7,u,2>: Cost 3 vsldoi8 <2,6,3,7>, + 2700564412U, // <3,7,u,3>: Cost 3 vsldoi8 <2,6,3,7>, + 2700564543U, // <3,7,u,4>: Cost 3 vsldoi8 <2,6,3,7>, + 1626822810U, // <3,7,u,5>: Cost 2 vsldoi8 <2,6,3,7>, RHS + 1662654672U, // <3,7,u,6>: Cost 2 vsldoi8 , + 1726338668U, // <3,7,u,7>: Cost 2 vsldoi12 LHS, <7,7,7,7> + 1626823013U, // <3,7,u,u>: Cost 2 vsldoi8 <2,6,3,7>, LHS + 1678557184U, // <3,u,0,0>: Cost 2 vsldoi12 LHS, <0,0,0,0> + 1679005395U, // <3,u,0,1>: Cost 2 vsldoi12 LHS, + 2289221787U, // <3,u,0,2>: Cost 3 vmrglw <1,2,3,0>, <0,1,u,2> + 1215479964U, // <3,u,0,3>: Cost 2 vmrglw <1,2,3,0>, LHS + 2752747245U, // <3,u,0,4>: Cost 3 vsldoi12 LHS, + 1158863002U, // <3,u,0,5>: Cost 2 vmrghw <3,0,1,2>, RHS + 2289224221U, // <3,u,0,6>: Cost 3 vmrglw <1,2,3,0>, <3,4,u,6> + 1215483208U, // <3,u,0,7>: Cost 2 vmrglw <1,2,3,0>, RHS + 1679005458U, // <3,u,0,u>: Cost 2 vsldoi12 LHS, + 1558036582U, // <3,u,1,0>: Cost 2 vsldoi4 <2,3,u,1>, LHS + 1678558004U, // <3,u,1,1>: Cost 2 vsldoi12 LHS, <1,1,1,1> + 604821294U, // <3,u,1,2>: Cost 1 vsldoi12 LHS, LHS + 2752747317U, // <3,u,1,3>: Cost 3 vsldoi12 LHS, + 1558039862U, // <3,u,1,4>: Cost 2 vsldoi4 <2,3,u,1>, RHS + 2756949830U, // <3,u,1,5>: Cost 3 vsldoi12 LHS, + 2800080726U, // <3,u,1,6>: Cost 3 vsldoi12 LHS, + 2289233224U, // <3,u,1,7>: Cost 3 vmrglw <1,2,3,1>, RHS + 604821348U, // <3,u,1,u>: Cost 1 vsldoi12 LHS, LHS + 2696586709U, // <3,u,2,0>: Cost 3 vsldoi8 <2,0,3,u>, <2,0,3,u> + 2757392246U, // <3,u,2,1>: Cost 3 vsldoi12 LHS, + 1624172151U, // <3,u,2,2>: Cost 2 vsldoi8 <2,2,3,u>, <2,2,3,u> + 1679005576U, // <3,u,2,3>: Cost 2 vsldoi12 LHS, + 2631789878U, // <3,u,2,4>: Cost 3 vsldoi4 <2,3,u,2>, RHS + 2699904874U, // <3,u,2,5>: Cost 3 vsldoi8 <2,5,3,u>, <2,5,3,u> + 1626826683U, // <3,u,2,6>: Cost 2 vsldoi8 <2,6,3,u>, <2,6,3,u> + 1726338988U, // <3,u,2,7>: Cost 2 vsldoi12 LHS, + 1683208117U, // <3,u,2,u>: Cost 2 vsldoi12 LHS, + 1679005628U, // <3,u,3,0>: Cost 2 vsldoi12 LHS, + 1161008942U, // <3,u,3,1>: Cost 2 vmrghw <3,3,3,3>, LHS + 2752747471U, // <3,u,3,2>: Cost 3 vsldoi12 LHS, + 403488870U, // <3,u,3,3>: Cost 1 vspltisw3 LHS + 1679005668U, // <3,u,3,4>: Cost 2 vsldoi12 LHS, + 1161009306U, // <3,u,3,5>: Cost 2 vmrghw <3,3,3,3>, RHS + 2691943104U, // <3,u,3,6>: Cost 3 vsldoi8 <1,2,3,u>, <3,6,u,7> + 1221479752U, // <3,u,3,7>: Cost 2 vmrglw <2,2,3,3>, RHS + 403488870U, // <3,u,3,u>: Cost 1 vspltisw3 LHS + 2289255363U, // <3,u,4,0>: Cost 3 vmrglw <1,2,3,4>, <1,2,u,0> + 1161844526U, // <3,u,4,1>: Cost 2 vmrghw <3,4,5,6>, LHS + 2289256661U, // <3,u,4,2>: Cost 3 vmrglw <1,2,3,4>, <3,0,u,2> + 1215512732U, // <3,u,4,3>: Cost 2 vmrglw <1,2,3,4>, LHS + 1215513498U, // <3,u,4,4>: Cost 2 vmrglw <1,2,3,4>, <1,2,3,4> + 1679005759U, // <3,u,4,5>: Cost 2 vsldoi12 LHS, + 2289256989U, // <3,u,4,6>: Cost 3 vmrglw <1,2,3,4>, <3,4,u,6> + 1215515976U, // <3,u,4,7>: Cost 2 vmrglw <1,2,3,4>, RHS + 1679005786U, // <3,u,4,u>: Cost 2 vsldoi12 LHS, + 1558069350U, // <3,u,5,0>: Cost 2 vsldoi4 <2,3,u,5>, LHS + 2631811892U, // <3,u,5,1>: Cost 3 vsldoi4 <2,3,u,5>, <1,1,1,1> + 1558071026U, // <3,u,5,2>: Cost 2 vsldoi4 <2,3,u,5>, <2,3,u,5> + 2752747646U, // <3,u,5,3>: Cost 3 vsldoi12 LHS, + 1558072630U, // <3,u,5,4>: Cost 2 vsldoi4 <2,3,u,5>, RHS + 1726337028U, // <3,u,5,5>: Cost 2 vsldoi12 LHS, <5,5,5,5> + 604821658U, // <3,u,5,6>: Cost 1 vsldoi12 LHS, RHS + 2294574408U, // <3,u,5,7>: Cost 3 vmrglw <2,1,3,5>, RHS + 604821676U, // <3,u,5,u>: Cost 1 vsldoi12 LHS, RHS + 2631819366U, // <3,u,6,0>: Cost 3 vsldoi4 <2,3,u,6>, LHS + 2757392574U, // <3,u,6,1>: Cost 3 vsldoi12 LHS, + 2631821043U, // <3,u,6,2>: Cost 3 vsldoi4 <2,3,u,6>, <2,3,u,6> + 1679005904U, // <3,u,6,3>: Cost 2 vsldoi12 LHS, + 2631822646U, // <3,u,6,4>: Cost 3 vsldoi4 <2,3,u,6>, RHS + 2236553370U, // <3,u,6,5>: Cost 3 vmrghw <3,6,0,7>, RHS + 1726337848U, // <3,u,6,6>: Cost 2 vsldoi12 LHS, <6,6,6,6> + 1726339309U, // <3,u,6,7>: Cost 2 vsldoi12 LHS, + 1683208445U, // <3,u,6,u>: Cost 2 vsldoi12 LHS, + 1726339328U, // <3,u,7,0>: Cost 2 vsldoi12 LHS, + 2297905225U, // <3,u,7,1>: Cost 3 vmrglw <2,6,3,7>, <0,0,u,1> + 2631829236U, // <3,u,7,2>: Cost 3 vsldoi4 <2,3,u,7>, <2,3,u,7> + 1224163484U, // <3,u,7,3>: Cost 2 vmrglw <2,6,3,7>, LHS + 1726339368U, // <3,u,7,4>: Cost 2 vsldoi12 LHS, + 2297905553U, // <3,u,7,5>: Cost 3 vmrglw <2,6,3,7>, <0,4,u,5> + 2297905392U, // <3,u,7,6>: Cost 3 vmrglw <2,6,3,7>, <0,2,u,6> + 1224166728U, // <3,u,7,7>: Cost 2 vmrglw <2,6,3,7>, RHS + 1224163489U, // <3,u,7,u>: Cost 2 vmrglw <2,6,3,7>, LHS + 1683208529U, // <3,u,u,0>: Cost 2 vsldoi12 LHS, + 1679006043U, // <3,u,u,1>: Cost 2 vsldoi12 LHS, + 604821861U, // <3,u,u,2>: Cost 1 vsldoi12 LHS, LHS + 403488870U, // <3,u,u,3>: Cost 1 vspltisw3 LHS + 1683208569U, // <3,u,u,4>: Cost 2 vsldoi12 LHS, + 1679006083U, // <3,u,u,5>: Cost 2 vsldoi12 LHS, + 604821901U, // <3,u,u,6>: Cost 1 vsldoi12 LHS, RHS + 1215548744U, // <3,u,u,7>: Cost 2 vmrglw <1,2,3,u>, RHS + 604821915U, // <3,u,u,u>: Cost 1 vsldoi12 LHS, LHS + 2759016448U, // <4,0,0,0>: Cost 3 vsldoi12 <1,2,3,4>, <0,0,0,0> + 1165115494U, // <4,0,0,1>: Cost 2 vmrghw <4,0,5,1>, LHS + 3717531337U, // <4,0,0,2>: Cost 4 vsldoi4 <4,4,0,0>, <2,3,4,0> + 3369675785U, // <4,0,0,3>: Cost 4 vmrglw <2,3,4,0>, <4,2,0,3> + 2751791144U, // <4,0,0,4>: Cost 3 vsldoi12 <0,0,4,4>, <0,0,4,4> + 2238857630U, // <4,0,0,5>: Cost 3 vmrghw <4,0,5,1>, <0,5,1,0> + 3312591341U, // <4,0,0,6>: Cost 4 vmrghw <4,0,5,0>, <0,6,0,7> + 3369676113U, // <4,0,0,7>: Cost 4 vmrglw <2,3,4,0>, <4,6,0,7> + 1165116061U, // <4,0,0,u>: Cost 2 vmrghw <4,0,5,1>, LHS + 2637824102U, // <4,0,1,0>: Cost 3 vsldoi4 <3,4,0,1>, LHS + 2637824922U, // <4,0,1,1>: Cost 3 vsldoi4 <3,4,0,1>, <1,2,3,4> + 1685274726U, // <4,0,1,2>: Cost 2 vsldoi12 <1,2,3,4>, LHS + 2637826512U, // <4,0,1,3>: Cost 3 vsldoi4 <3,4,0,1>, <3,4,0,1> + 2637827382U, // <4,0,1,4>: Cost 3 vsldoi4 <3,4,0,1>, RHS + 2661716070U, // <4,0,1,5>: Cost 3 vsldoi4 <7,4,0,1>, <5,6,7,4> + 3729486427U, // <4,0,1,6>: Cost 4 vsldoi4 <6,4,0,1>, <6,4,0,1> + 2661717300U, // <4,0,1,7>: Cost 3 vsldoi4 <7,4,0,1>, <7,4,0,1> + 1685274780U, // <4,0,1,u>: Cost 2 vsldoi12 <1,2,3,4>, LHS + 3711574118U, // <4,0,2,0>: Cost 4 vsldoi4 <3,4,0,2>, LHS + 2240200806U, // <4,0,2,1>: Cost 3 vmrghw <4,2,5,3>, LHS + 3771663992U, // <4,0,2,2>: Cost 4 vsldoi8 <2,2,4,0>, <2,2,4,0> + 2698585801U, // <4,0,2,3>: Cost 3 vsldoi8 <2,3,4,0>, <2,3,4,0> + 3373672105U, // <4,0,2,4>: Cost 4 vmrglw <3,0,4,2>, <2,3,0,4> + 3810813795U, // <4,0,2,5>: Cost 4 vsldoi8 , <2,5,3,1> + 3772327866U, // <4,0,2,6>: Cost 4 vsldoi8 <2,3,4,0>, <2,6,3,7> + 3386280568U, // <4,0,2,7>: Cost 5 vmrglw <5,1,4,2>, <3,6,0,7> + 2701903966U, // <4,0,2,u>: Cost 3 vsldoi8 <2,u,4,0>, <2,u,4,0> + 3699638374U, // <4,0,3,0>: Cost 4 vsldoi4 <1,4,0,3>, LHS + 2753560832U, // <4,0,3,1>: Cost 3 vsldoi12 <0,3,1,4>, <0,3,1,4> + 3772328276U, // <4,0,3,2>: Cost 4 vsldoi8 <2,3,4,0>, <3,2,4,3> + 3827302674U, // <4,0,3,3>: Cost 4 vsldoi12 <0,3,1,4>, <0,3,3,4> + 3699641654U, // <4,0,3,4>: Cost 4 vsldoi4 <1,4,0,3>, RHS + 3779627588U, // <4,0,3,5>: Cost 4 vsldoi8 <3,5,4,0>, <3,5,4,0> + 3772328604U, // <4,0,3,6>: Cost 4 vsldoi8 <2,3,4,0>, <3,6,4,7> + 3780954854U, // <4,0,3,7>: Cost 4 vsldoi8 <3,7,4,0>, <3,7,4,0> + 2753560832U, // <4,0,3,u>: Cost 3 vsldoi12 <0,3,1,4>, <0,3,1,4> + 2725129106U, // <4,0,4,0>: Cost 3 vsldoi8 <6,7,4,0>, <4,0,5,1> + 1167720550U, // <4,0,4,1>: Cost 2 vmrghw <4,4,4,4>, LHS + 3839172953U, // <4,0,4,2>: Cost 4 vsldoi12 <2,3,0,4>, <0,4,2,3> + 3772329051U, // <4,0,4,3>: Cost 4 vsldoi8 <2,3,4,0>, <4,3,0,4> + 2241462610U, // <4,0,4,4>: Cost 3 vmrghw <4,4,4,4>, <0,4,1,5> + 2698587446U, // <4,0,4,5>: Cost 3 vsldoi8 <2,3,4,0>, RHS + 3772329297U, // <4,0,4,6>: Cost 4 vsldoi8 <2,3,4,0>, <4,6,0,7> + 3735483703U, // <4,0,4,7>: Cost 4 vsldoi4 <7,4,0,4>, <7,4,0,4> + 1167721117U, // <4,0,4,u>: Cost 2 vmrghw <4,4,4,4>, LHS + 1168556032U, // <4,0,5,0>: Cost 2 vmrghw RHS, <0,0,0,0> + 94814310U, // <4,0,5,1>: Cost 1 vmrghw RHS, LHS + 2242298029U, // <4,0,5,2>: Cost 3 vmrghw RHS, <0,2,1,2> + 2637859284U, // <4,0,5,3>: Cost 3 vsldoi4 <3,4,0,5>, <3,4,0,5> + 1168556370U, // <4,0,5,4>: Cost 2 vmrghw RHS, <0,4,1,5> + 2242306530U, // <4,0,5,5>: Cost 3 vmrghw RHS, <0,5,u,5> + 2242298358U, // <4,0,5,6>: Cost 3 vmrghw RHS, <0,6,1,7> + 2661750072U, // <4,0,5,7>: Cost 3 vsldoi4 <7,4,0,5>, <7,4,0,5> + 94814877U, // <4,0,5,u>: Cost 1 vmrghw RHS, LHS + 3316580362U, // <4,0,6,0>: Cost 4 vmrghw <4,6,5,1>, <0,0,1,1> + 2242846822U, // <4,0,6,1>: Cost 3 vmrghw <4,6,5,2>, LHS + 3798872570U, // <4,0,6,2>: Cost 4 vsldoi8 <6,7,4,0>, <6,2,7,3> + 3796218413U, // <4,0,6,3>: Cost 4 vsldoi8 <6,3,4,0>, <6,3,4,0> + 3834528273U, // <4,0,6,4>: Cost 4 vsldoi12 <1,5,0,4>, <0,6,4,7> + 3798872811U, // <4,0,6,5>: Cost 4 vsldoi8 <6,7,4,0>, <6,5,7,1> + 3316621876U, // <4,0,6,6>: Cost 4 vmrghw <4,6,5,6>, <0,6,u,6> + 2725131121U, // <4,0,6,7>: Cost 3 vsldoi8 <6,7,4,0>, <6,7,4,0> + 2242847389U, // <4,0,6,u>: Cost 3 vmrghw <4,6,5,2>, LHS + 3377692672U, // <4,0,7,0>: Cost 4 vmrglw <3,6,4,7>, <0,0,0,0> + 2243493990U, // <4,0,7,1>: Cost 3 vmrghw <4,7,5,0>, LHS + 3775648970U, // <4,0,7,2>: Cost 5 vsldoi8 <2,u,4,0>, <7,2,6,3> + 3802191110U, // <4,0,7,3>: Cost 4 vsldoi8 <7,3,4,0>, <7,3,4,0> + 3317236050U, // <4,0,7,4>: Cost 4 vmrghw <4,7,5,0>, <0,4,1,5> + 3803518376U, // <4,0,7,5>: Cost 4 vsldoi8 <7,5,4,0>, <7,5,4,0> + 3317236214U, // <4,0,7,6>: Cost 5 vmrghw <4,7,5,0>, <0,6,1,7> + 3798873708U, // <4,0,7,7>: Cost 4 vsldoi8 <6,7,4,0>, <7,7,7,7> + 2243494557U, // <4,0,7,u>: Cost 3 vmrghw <4,7,5,0>, LHS + 1170546688U, // <4,0,u,0>: Cost 2 vmrghw RHS, <0,0,0,0> + 96804966U, // <4,0,u,1>: Cost 1 vmrghw RHS, LHS + 1685275293U, // <4,0,u,2>: Cost 2 vsldoi12 <1,2,3,4>, LHS + 2637883863U, // <4,0,u,3>: Cost 3 vsldoi4 <3,4,0,u>, <3,4,0,u> + 1170547026U, // <4,0,u,4>: Cost 2 vmrghw RHS, <0,4,1,5> + 2698590362U, // <4,0,u,5>: Cost 3 vsldoi8 <2,3,4,0>, RHS + 2244289014U, // <4,0,u,6>: Cost 3 vmrghw RHS, <0,6,1,7> + 2661774651U, // <4,0,u,7>: Cost 3 vsldoi4 <7,4,0,u>, <7,4,0,u> + 96805533U, // <4,0,u,u>: Cost 1 vmrghw RHS, LHS + 2667749478U, // <4,1,0,0>: Cost 3 vsldoi4 , LHS + 2689966182U, // <4,1,0,1>: Cost 3 vsldoi8 <0,u,4,1>, LHS + 2238571418U, // <4,1,0,2>: Cost 3 vmrghw <4,0,1,2>, <1,2,3,4> + 3711633880U, // <4,1,0,3>: Cost 4 vsldoi4 <3,4,1,0>, <3,4,1,0> + 2689966418U, // <4,1,0,4>: Cost 3 vsldoi8 <0,u,4,1>, <0,4,1,5> + 3361046866U, // <4,1,0,5>: Cost 4 vmrglw <0,u,4,0>, <0,4,1,5> + 3741495802U, // <4,1,0,6>: Cost 4 vsldoi4 , <6,2,7,3> + 3741496314U, // <4,1,0,7>: Cost 4 vsldoi4 , <7,0,1,2> + 2689966765U, // <4,1,0,u>: Cost 3 vsldoi8 <0,u,4,1>, <0,u,4,1> + 3764372222U, // <4,1,1,0>: Cost 4 vsldoi8 <1,0,4,1>, <1,0,4,1> + 2758206263U, // <4,1,1,1>: Cost 3 vsldoi12 <1,1,1,4>, <1,1,1,4> + 2698593178U, // <4,1,1,2>: Cost 3 vsldoi8 <2,3,4,1>, <1,2,3,4> + 3361057810U, // <4,1,1,3>: Cost 4 vmrglw <0,u,4,1>, <4,2,1,3> + 3827303250U, // <4,1,1,4>: Cost 4 vsldoi12 <0,3,1,4>, <1,1,4,4> + 2287313234U, // <4,1,1,5>: Cost 3 vmrglw <0,u,4,1>, <0,4,1,5> + 3763709171U, // <4,1,1,6>: Cost 4 vsldoi8 <0,u,4,1>, <1,6,5,7> + 3361058138U, // <4,1,1,7>: Cost 4 vmrglw <0,u,4,1>, <4,6,1,7> + 2239759744U, // <4,1,1,u>: Cost 3 vmrghw <4,1,u,3>, <1,u,3,4> + 2637906022U, // <4,1,2,0>: Cost 3 vsldoi4 <3,4,1,2>, LHS + 2637906842U, // <4,1,2,1>: Cost 3 vsldoi4 <3,4,1,2>, <1,2,3,4> + 3763709544U, // <4,1,2,2>: Cost 4 vsldoi8 <0,u,4,1>, <2,2,2,2> + 1685275546U, // <4,1,2,3>: Cost 2 vsldoi12 <1,2,3,4>, <1,2,3,4> + 2637909302U, // <4,1,2,4>: Cost 3 vsldoi4 <3,4,1,2>, RHS + 3361063250U, // <4,1,2,5>: Cost 4 vmrglw <0,u,4,2>, <0,4,1,5> + 3763709882U, // <4,1,2,6>: Cost 4 vsldoi8 <0,u,4,1>, <2,6,3,7> + 3735541054U, // <4,1,2,7>: Cost 4 vsldoi4 <7,4,1,2>, <7,4,1,2> + 1685644231U, // <4,1,2,u>: Cost 2 vsldoi12 <1,2,u,4>, <1,2,u,4> + 2702575792U, // <4,1,3,0>: Cost 3 vsldoi8 <3,0,4,1>, <3,0,4,1> + 3832759257U, // <4,1,3,1>: Cost 4 vsldoi12 <1,2,3,4>, <1,3,1,4> + 3833349090U, // <4,1,3,2>: Cost 4 vsldoi12 <1,3,2,4>, <1,3,2,4> + 3763710364U, // <4,1,3,3>: Cost 4 vsldoi8 <0,u,4,1>, <3,3,3,3> + 2707884546U, // <4,1,3,4>: Cost 3 vsldoi8 <3,u,4,1>, <3,4,5,6> + 3361071442U, // <4,1,3,5>: Cost 4 vmrglw <0,u,4,3>, <0,4,1,5> + 3772336796U, // <4,1,3,6>: Cost 4 vsldoi8 <2,3,4,1>, <3,6,4,7> + 3775654595U, // <4,1,3,7>: Cost 5 vsldoi8 <2,u,4,1>, <3,7,0,1> + 2707884856U, // <4,1,3,u>: Cost 3 vsldoi8 <3,u,4,1>, <3,u,4,1> + 2667782246U, // <4,1,4,0>: Cost 3 vsldoi4 , LHS + 2241463092U, // <4,1,4,1>: Cost 3 vmrghw <4,4,4,4>, <1,1,1,1> + 2241553306U, // <4,1,4,2>: Cost 3 vmrghw <4,4,5,6>, <1,2,3,4> + 3827303484U, // <4,1,4,3>: Cost 4 vsldoi12 <0,3,1,4>, <1,4,3,4> + 2667785424U, // <4,1,4,4>: Cost 3 vsldoi4 , <4,4,4,4> + 2689969462U, // <4,1,4,5>: Cost 3 vsldoi8 <0,u,4,1>, RHS + 3763711322U, // <4,1,4,6>: Cost 4 vsldoi8 <0,u,4,1>, <4,6,1,7> + 3867116636U, // <4,1,4,7>: Cost 4 vsldoi12 <7,0,1,4>, <1,4,7,0> + 2689969705U, // <4,1,4,u>: Cost 3 vsldoi8 <0,u,4,1>, RHS + 1546273106U, // <4,1,5,0>: Cost 2 vsldoi4 <0,4,1,5>, <0,4,1,5> + 1168556852U, // <4,1,5,1>: Cost 2 vmrghw RHS, <1,1,1,1> + 1168556950U, // <4,1,5,2>: Cost 2 vmrghw RHS, <1,2,3,0> + 2620016790U, // <4,1,5,3>: Cost 3 vsldoi4 <0,4,1,5>, <3,0,1,2> + 1546276150U, // <4,1,5,4>: Cost 2 vsldoi4 <0,4,1,5>, RHS + 2620018692U, // <4,1,5,5>: Cost 3 vsldoi4 <0,4,1,5>, <5,5,5,5> + 2242299087U, // <4,1,5,6>: Cost 3 vmrghw RHS, <1,6,1,7> + 2667795450U, // <4,1,5,7>: Cost 3 vsldoi4 , <7,0,1,2> + 1546278702U, // <4,1,5,u>: Cost 2 vsldoi4 <0,4,1,5>, LHS + 3781628193U, // <4,1,6,0>: Cost 4 vsldoi8 <3,u,4,1>, <6,0,1,2> + 3832759503U, // <4,1,6,1>: Cost 4 vsldoi12 <1,2,3,4>, <1,6,1,7> + 3316261786U, // <4,1,6,2>: Cost 4 vmrghw <4,6,0,7>, <1,2,3,4> + 3781628466U, // <4,1,6,3>: Cost 4 vsldoi8 <3,u,4,1>, <6,3,4,5> + 3827303658U, // <4,1,6,4>: Cost 4 vsldoi12 <0,3,1,4>, <1,6,4,7> + 3361096018U, // <4,1,6,5>: Cost 4 vmrglw <0,u,4,6>, <0,4,1,5> + 3788264248U, // <4,1,6,6>: Cost 4 vsldoi8 <5,0,4,1>, <6,6,6,6> + 3788264270U, // <4,1,6,7>: Cost 4 vsldoi8 <5,0,4,1>, <6,7,0,1> + 3832759566U, // <4,1,6,u>: Cost 4 vsldoi12 <1,2,3,4>, <1,6,u,7> + 2726466580U, // <4,1,7,0>: Cost 3 vsldoi8 <7,0,4,1>, <7,0,4,1> + 3377692682U, // <4,1,7,1>: Cost 4 vmrglw <3,6,4,7>, <0,0,1,1> + 3377694870U, // <4,1,7,2>: Cost 4 vmrglw <3,6,4,7>, <3,0,1,2> + 3802199303U, // <4,1,7,3>: Cost 4 vsldoi8 <7,3,4,1>, <7,3,4,1> + 2731775334U, // <4,1,7,4>: Cost 3 vsldoi8 <7,u,4,1>, <7,4,5,6> + 3377693010U, // <4,1,7,5>: Cost 4 vmrglw <3,6,4,7>, <0,4,1,5> + 3365749804U, // <4,1,7,6>: Cost 5 vmrglw <1,6,4,7>, <1,4,1,6> + 3788265068U, // <4,1,7,7>: Cost 4 vsldoi8 <5,0,4,1>, <7,7,7,7> + 2731775644U, // <4,1,7,u>: Cost 3 vsldoi8 <7,u,4,1>, <7,u,4,1> + 1546297685U, // <4,1,u,0>: Cost 2 vsldoi4 <0,4,1,u>, <0,4,1,u> + 1170547508U, // <4,1,u,1>: Cost 2 vmrghw RHS, <1,1,1,1> + 1170547606U, // <4,1,u,2>: Cost 2 vmrghw RHS, <1,2,3,0> + 1689257344U, // <4,1,u,3>: Cost 2 vsldoi12 <1,u,3,4>, <1,u,3,4> + 1546300726U, // <4,1,u,4>: Cost 2 vsldoi4 <0,4,1,u>, RHS + 2284716370U, // <4,1,u,5>: Cost 3 vmrglw <0,4,4,u>, <0,4,1,5> + 2244289743U, // <4,1,u,6>: Cost 3 vmrghw RHS, <1,6,1,7> + 2667820026U, // <4,1,u,7>: Cost 3 vsldoi4 , <7,0,1,2> + 1546303278U, // <4,1,u,u>: Cost 2 vsldoi4 <0,4,1,u>, LHS + 3729621094U, // <4,2,0,0>: Cost 4 vsldoi4 <6,4,2,0>, LHS + 3763716198U, // <4,2,0,1>: Cost 4 vsldoi8 <0,u,4,2>, LHS + 2238858856U, // <4,2,0,2>: Cost 3 vmrghw <4,0,5,1>, <2,2,2,2> + 2295930982U, // <4,2,0,3>: Cost 3 vmrglw <2,3,4,0>, LHS + 3763716434U, // <4,2,0,4>: Cost 4 vsldoi8 <0,u,4,2>, <0,4,1,5> + 2238859107U, // <4,2,0,5>: Cost 3 vmrghw <4,0,5,1>, <2,5,3,1> + 2238859194U, // <4,2,0,6>: Cost 3 vmrghw <4,0,5,1>, <2,6,3,7> + 3312601066U, // <4,2,0,7>: Cost 4 vmrghw <4,0,5,1>, <2,7,0,1> + 2295930987U, // <4,2,0,u>: Cost 3 vmrglw <2,3,4,0>, LHS + 3699769446U, // <4,2,1,0>: Cost 4 vsldoi4 <1,4,2,1>, LHS + 3313255971U, // <4,2,1,1>: Cost 4 vmrghw <4,1,5,0>, <2,1,3,5> + 3361056360U, // <4,2,1,2>: Cost 4 vmrglw <0,u,4,1>, <2,2,2,2> + 2287312998U, // <4,2,1,3>: Cost 3 vmrglw <0,u,4,1>, LHS + 3788932148U, // <4,2,1,4>: Cost 4 vsldoi8 <5,1,4,2>, <1,4,2,5> + 3313256290U, // <4,2,1,5>: Cost 4 vmrghw <4,1,5,0>, <2,5,3,0> + 3838289469U, // <4,2,1,6>: Cost 4 vsldoi12 <2,1,6,4>, <2,1,6,4> + 3369682865U, // <4,2,1,7>: Cost 5 vmrglw <2,3,4,1>, <2,6,2,7> + 2287313003U, // <4,2,1,u>: Cost 3 vmrglw <0,u,4,1>, LHS + 3838658133U, // <4,2,2,0>: Cost 4 vsldoi12 <2,2,2,4>, <2,2,0,1> + 3711722394U, // <4,2,2,1>: Cost 4 vsldoi4 <3,4,2,2>, <1,2,3,4> + 2759018088U, // <4,2,2,2>: Cost 3 vsldoi12 <1,2,3,4>, <2,2,2,2> + 2759018098U, // <4,2,2,3>: Cost 3 vsldoi12 <1,2,3,4>, <2,2,3,3> + 3838658168U, // <4,2,2,4>: Cost 4 vsldoi12 <2,2,2,4>, <2,2,4,0> + 3369027341U, // <4,2,2,5>: Cost 4 vmrglw <2,2,4,2>, <2,4,2,5> + 2240227258U, // <4,2,2,6>: Cost 3 vmrghw <4,2,5,6>, <2,6,3,7> + 3735614791U, // <4,2,2,7>: Cost 4 vsldoi4 <7,4,2,2>, <7,4,2,2> + 2759018143U, // <4,2,2,u>: Cost 3 vsldoi12 <1,2,3,4>, <2,2,u,3> + 2759018150U, // <4,2,3,0>: Cost 3 vsldoi12 <1,2,3,4>, <2,3,0,1> + 3831948975U, // <4,2,3,1>: Cost 4 vsldoi12 <1,1,1,4>, <2,3,1,1> + 3832759993U, // <4,2,3,2>: Cost 4 vsldoi12 <1,2,3,4>, <2,3,2,2> + 2759018180U, // <4,2,3,3>: Cost 3 vsldoi12 <1,2,3,4>, <2,3,3,4> + 2759018185U, // <4,2,3,4>: Cost 3 vsldoi12 <1,2,3,4>, <2,3,4,0> + 3839542998U, // <4,2,3,5>: Cost 4 vsldoi12 <2,3,5,4>, <2,3,5,4> + 3314640826U, // <4,2,3,6>: Cost 4 vmrghw <4,3,5,7>, <2,6,3,7> + 2765948648U, // <4,2,3,7>: Cost 3 vsldoi12 <2,3,7,4>, <2,3,7,4> + 2759018222U, // <4,2,3,u>: Cost 3 vsldoi12 <1,2,3,4>, <2,3,u,1> + 3838658295U, // <4,2,4,0>: Cost 4 vsldoi12 <2,2,2,4>, <2,4,0,1> + 3315205667U, // <4,2,4,1>: Cost 4 vmrghw <4,4,4,4>, <2,1,3,5> + 2241463912U, // <4,2,4,2>: Cost 3 vmrghw <4,4,4,4>, <2,2,2,2> + 1234829414U, // <4,2,4,3>: Cost 2 vmrglw <4,4,4,4>, LHS + 2241464085U, // <4,2,4,4>: Cost 3 vmrghw <4,4,4,4>, <2,4,3,4> + 2241546087U, // <4,2,4,5>: Cost 3 vmrghw <4,4,5,5>, <2,5,3,5> + 2241464250U, // <4,2,4,6>: Cost 3 vmrghw <4,4,4,4>, <2,6,3,7> + 3741602873U, // <4,2,4,7>: Cost 4 vsldoi4 , <7,0,u,2> + 1234829419U, // <4,2,4,u>: Cost 2 vmrglw <4,4,4,4>, LHS + 2626060390U, // <4,2,5,0>: Cost 3 vsldoi4 <1,4,2,5>, LHS + 2626061364U, // <4,2,5,1>: Cost 3 vsldoi4 <1,4,2,5>, <1,4,2,5> + 1168557672U, // <4,2,5,2>: Cost 2 vmrghw RHS, <2,2,2,2> + 1222230118U, // <4,2,5,3>: Cost 2 vmrglw <2,3,4,5>, LHS + 2626063670U, // <4,2,5,4>: Cost 3 vsldoi4 <1,4,2,5>, RHS + 2242299752U, // <4,2,5,5>: Cost 3 vmrghw RHS, <2,5,3,6> + 1168558010U, // <4,2,5,6>: Cost 2 vmrghw RHS, <2,6,3,7> + 2242299882U, // <4,2,5,7>: Cost 3 vmrghw RHS, <2,7,0,1> + 1222230123U, // <4,2,5,u>: Cost 2 vmrglw <2,3,4,5>, LHS + 3711754342U, // <4,2,6,0>: Cost 4 vsldoi4 <3,4,2,6>, LHS + 3711755162U, // <4,2,6,1>: Cost 4 vsldoi4 <3,4,2,6>, <1,2,3,4> + 3838658481U, // <4,2,6,2>: Cost 4 vsldoi12 <2,2,2,4>, <2,6,2,7> + 2759018426U, // <4,2,6,3>: Cost 3 vsldoi12 <1,2,3,4>, <2,6,3,7> + 3838658499U, // <4,2,6,4>: Cost 4 vsldoi12 <2,2,2,4>, <2,6,4,7> + 3735646310U, // <4,2,6,5>: Cost 4 vsldoi4 <7,4,2,6>, <5,6,7,4> + 3316590522U, // <4,2,6,6>: Cost 4 vmrghw <4,6,5,2>, <2,6,3,7> + 3798889331U, // <4,2,6,7>: Cost 4 vsldoi8 <6,7,4,2>, <6,7,4,2> + 2759018471U, // <4,2,6,u>: Cost 3 vsldoi12 <1,2,3,4>, <2,6,u,7> + 3874564074U, // <4,2,7,0>: Cost 4 vsldoi12 , <2,7,0,1> + 3800880230U, // <4,2,7,1>: Cost 4 vsldoi8 <7,1,4,2>, <7,1,4,2> + 3371722344U, // <4,2,7,2>: Cost 4 vmrglw <2,6,4,7>, <2,2,2,2> + 2303950950U, // <4,2,7,3>: Cost 3 vmrglw <3,6,4,7>, LHS + 3371722346U, // <4,2,7,4>: Cost 4 vmrglw <2,6,4,7>, <2,2,2,4> + 3371722509U, // <4,2,7,5>: Cost 5 vmrglw <2,6,4,7>, <2,4,2,5> + 3317237690U, // <4,2,7,6>: Cost 4 vmrghw <4,7,5,0>, <2,6,3,7> + 3317237738U, // <4,2,7,7>: Cost 4 vmrghw <4,7,5,0>, <2,7,0,1> + 2303950955U, // <4,2,7,u>: Cost 3 vmrglw <3,6,4,7>, LHS + 2759018555U, // <4,2,u,0>: Cost 3 vsldoi12 <1,2,3,4>, <2,u,0,1> + 2626085943U, // <4,2,u,1>: Cost 3 vsldoi4 <1,4,2,u>, <1,4,2,u> + 1170548328U, // <4,2,u,2>: Cost 2 vmrghw RHS, <2,2,2,2> + 1222254694U, // <4,2,u,3>: Cost 2 vmrglw <2,3,4,u>, LHS + 2759018595U, // <4,2,u,4>: Cost 3 vsldoi12 <1,2,3,4>, <2,u,4,5> + 2244290408U, // <4,2,u,5>: Cost 3 vmrghw RHS, <2,5,3,6> + 1170548666U, // <4,2,u,6>: Cost 2 vmrghw RHS, <2,6,3,7> + 2769266813U, // <4,2,u,7>: Cost 3 vsldoi12 <2,u,7,4>, <2,u,7,4> + 1222254699U, // <4,2,u,u>: Cost 2 vmrglw <2,3,4,u>, LHS + 2238859414U, // <4,3,0,0>: Cost 3 vmrghw <4,0,5,1>, <3,0,1,2> + 2759018646U, // <4,3,0,1>: Cost 3 vsldoi12 <1,2,3,4>, <3,0,1,2> + 3312314708U, // <4,3,0,2>: Cost 4 vmrghw <4,0,1,2>, <3,2,4,3> + 2238859676U, // <4,3,0,3>: Cost 3 vmrghw <4,0,5,1>, <3,3,3,3> + 2295931802U, // <4,3,0,4>: Cost 3 vmrglw <2,3,4,0>, <1,2,3,4> + 3735670886U, // <4,3,0,5>: Cost 4 vsldoi4 <7,4,3,0>, <5,6,7,4> + 3312315036U, // <4,3,0,6>: Cost 4 vmrghw <4,0,1,2>, <3,6,4,7> + 3369674682U, // <4,3,0,7>: Cost 4 vmrglw <2,3,4,0>, <2,6,3,7> + 2759018709U, // <4,3,0,u>: Cost 3 vsldoi12 <1,2,3,4>, <3,0,u,2> + 3361055638U, // <4,3,1,0>: Cost 4 vmrglw <0,u,4,1>, <1,2,3,0> + 3831949542U, // <4,3,1,1>: Cost 4 vsldoi12 <1,1,1,4>, <3,1,1,1> + 2703917978U, // <4,3,1,2>: Cost 3 vsldoi8 <3,2,4,3>, <1,2,3,4> + 3361056370U, // <4,3,1,3>: Cost 4 vmrglw <0,u,4,1>, <2,2,3,3> + 2295939994U, // <4,3,1,4>: Cost 3 vmrglw <2,3,4,1>, <1,2,3,4> + 3361056291U, // <4,3,1,5>: Cost 4 vmrglw <0,u,4,1>, <2,1,3,5> + 3378972520U, // <4,3,1,6>: Cost 4 vmrglw <3,u,4,1>, <2,5,3,6> + 3361056698U, // <4,3,1,7>: Cost 4 vmrglw <0,u,4,1>, <2,6,3,7> + 2703917978U, // <4,3,1,u>: Cost 3 vsldoi8 <3,2,4,3>, <1,2,3,4> + 3832760624U, // <4,3,2,0>: Cost 4 vsldoi12 <1,2,3,4>, <3,2,0,3> + 3711796122U, // <4,3,2,1>: Cost 4 vsldoi4 <3,4,3,2>, <1,2,3,4> + 3832760641U, // <4,3,2,2>: Cost 4 vsldoi12 <1,2,3,4>, <3,2,2,2> + 2770962764U, // <4,3,2,3>: Cost 3 vsldoi12 <3,2,3,4>, <3,2,3,4> + 2759018836U, // <4,3,2,4>: Cost 3 vsldoi12 <1,2,3,4>, <3,2,4,3> + 3827304802U, // <4,3,2,5>: Cost 5 vsldoi12 <0,3,1,4>, <3,2,5,u> + 3832760678U, // <4,3,2,6>: Cost 4 vsldoi12 <1,2,3,4>, <3,2,6,3> + 3859597679U, // <4,3,2,7>: Cost 4 vsldoi12 <5,6,7,4>, <3,2,7,3> + 2771331449U, // <4,3,2,u>: Cost 3 vsldoi12 <3,2,u,4>, <3,2,u,4> + 2240841878U, // <4,3,3,0>: Cost 3 vmrghw <4,3,5,0>, <3,0,1,2> + 3776997635U, // <4,3,3,1>: Cost 4 vsldoi8 <3,1,4,3>, <3,1,4,3> + 2703919444U, // <4,3,3,2>: Cost 3 vsldoi8 <3,2,4,3>, <3,2,4,3> + 2759018908U, // <4,3,3,3>: Cost 3 vsldoi12 <1,2,3,4>, <3,3,3,3> + 2759018918U, // <4,3,3,4>: Cost 3 vsldoi12 <1,2,3,4>, <3,3,4,4> + 3386951446U, // <4,3,3,5>: Cost 4 vmrglw <5,2,4,3>, <2,4,3,5> + 3777661596U, // <4,3,3,6>: Cost 4 vsldoi8 <3,2,4,3>, <3,6,4,7> + 3375007674U, // <4,3,3,7>: Cost 4 vmrglw <3,2,4,3>, <2,6,3,7> + 2707901242U, // <4,3,3,u>: Cost 3 vsldoi8 <3,u,4,3>, <3,u,4,3> + 2759018960U, // <4,3,4,0>: Cost 3 vsldoi12 <1,2,3,4>, <3,4,0,1> + 2759018970U, // <4,3,4,1>: Cost 3 vsldoi12 <1,2,3,4>, <3,4,1,2> + 2632099605U, // <4,3,4,2>: Cost 3 vsldoi4 <2,4,3,4>, <2,4,3,4> + 2241464732U, // <4,3,4,3>: Cost 3 vmrghw <4,4,4,4>, <3,3,3,3> + 2759019000U, // <4,3,4,4>: Cost 3 vsldoi12 <1,2,3,4>, <3,4,4,5> + 2753563138U, // <4,3,4,5>: Cost 3 vsldoi12 <0,3,1,4>, <3,4,5,6> + 3777662316U, // <4,3,4,6>: Cost 4 vsldoi8 <3,2,4,3>, <4,6,3,7> + 2308573114U, // <4,3,4,7>: Cost 3 vmrglw <4,4,4,4>, <2,6,3,7> + 2759019032U, // <4,3,4,u>: Cost 3 vsldoi12 <1,2,3,4>, <3,4,u,1> + 1168558230U, // <4,3,5,0>: Cost 2 vmrghw RHS, <3,0,1,2> + 2242300134U, // <4,3,5,1>: Cost 3 vmrghw RHS, <3,1,1,1> + 2632107798U, // <4,3,5,2>: Cost 3 vsldoi4 <2,4,3,5>, <2,4,3,5> + 1168558492U, // <4,3,5,3>: Cost 2 vmrghw RHS, <3,3,3,3> + 1168558594U, // <4,3,5,4>: Cost 2 vmrghw RHS, <3,4,5,6> + 2295973654U, // <4,3,5,5>: Cost 3 vmrglw <2,3,4,5>, <2,4,3,5> + 2242300536U, // <4,3,5,6>: Cost 3 vmrghw RHS, <3,6,0,7> + 2295973818U, // <4,3,5,7>: Cost 3 vmrglw <2,3,4,5>, <2,6,3,7> + 1168558878U, // <4,3,5,u>: Cost 2 vmrghw RHS, <3,u,1,2> + 3832760952U, // <4,3,6,0>: Cost 4 vsldoi12 <1,2,3,4>, <3,6,0,7> + 3711828890U, // <4,3,6,1>: Cost 4 vsldoi4 <3,4,3,6>, <1,2,3,4> + 3316484436U, // <4,3,6,2>: Cost 4 vmrghw <4,6,3,7>, <3,2,4,3> + 3711830512U, // <4,3,6,3>: Cost 4 vsldoi4 <3,4,3,6>, <3,4,3,6> + 2759019164U, // <4,3,6,4>: Cost 3 vsldoi12 <1,2,3,4>, <3,6,4,7> + 3361097251U, // <4,3,6,5>: Cost 5 vmrglw <0,u,4,6>, <2,1,3,5> + 3316624045U, // <4,3,6,6>: Cost 4 vmrghw <4,6,5,6>, <3,6,6,6> + 2773912244U, // <4,3,6,7>: Cost 3 vsldoi12 <3,6,7,4>, <3,6,7,4> + 2759019164U, // <4,3,6,u>: Cost 3 vsldoi12 <1,2,3,4>, <3,6,4,7> + 3377693590U, // <4,3,7,0>: Cost 4 vmrglw <3,6,4,7>, <1,2,3,0> + 3365751680U, // <4,3,7,1>: Cost 5 vmrglw <1,6,4,7>, <4,0,3,1> + 2727810232U, // <4,3,7,2>: Cost 3 vsldoi8 <7,2,4,3>, <7,2,4,3> + 3377694322U, // <4,3,7,3>: Cost 4 vmrglw <3,6,4,7>, <2,2,3,3> + 2303951770U, // <4,3,7,4>: Cost 3 vmrglw <3,6,4,7>, <1,2,3,4> + 3741700198U, // <4,3,7,5>: Cost 4 vsldoi4 , <5,6,7,4> + 3377695216U, // <4,3,7,6>: Cost 4 vmrglw <3,6,4,7>, <3,4,3,6> + 3375703994U, // <4,3,7,7>: Cost 4 vmrglw <3,3,4,7>, <2,6,3,7> + 2731792030U, // <4,3,7,u>: Cost 3 vsldoi8 <7,u,4,3>, <7,u,4,3> + 1170548886U, // <4,3,u,0>: Cost 2 vmrghw RHS, <3,0,1,2> + 2759019294U, // <4,3,u,1>: Cost 3 vsldoi12 <1,2,3,4>, <3,u,1,2> + 2632132377U, // <4,3,u,2>: Cost 3 vsldoi4 <2,4,3,u>, <2,4,3,u> + 1170549148U, // <4,3,u,3>: Cost 2 vmrghw RHS, <3,3,3,3> + 1170549250U, // <4,3,u,4>: Cost 2 vmrghw RHS, <3,4,5,6> + 2759019334U, // <4,3,u,5>: Cost 3 vsldoi12 <1,2,3,4>, <3,u,5,6> + 2244291192U, // <4,3,u,6>: Cost 3 vmrghw RHS, <3,6,0,7> + 2295998394U, // <4,3,u,7>: Cost 3 vmrglw <2,3,4,u>, <2,6,3,7> + 1170549534U, // <4,3,u,u>: Cost 2 vmrghw RHS, <3,u,1,2> + 1165118354U, // <4,4,0,0>: Cost 2 vmrghw <4,0,5,1>, <4,0,5,1> + 1637482598U, // <4,4,0,1>: Cost 2 vsldoi8 <4,4,4,4>, LHS + 3711854285U, // <4,4,0,2>: Cost 4 vsldoi4 <3,4,4,0>, <2,3,4,4> + 3827305344U, // <4,4,0,3>: Cost 4 vsldoi12 <0,3,1,4>, <4,0,3,1> + 2711224658U, // <4,4,0,4>: Cost 3 vsldoi8 <4,4,4,4>, <0,4,1,5> + 1165118774U, // <4,4,0,5>: Cost 2 vmrghw <4,0,5,1>, RHS + 3312602489U, // <4,4,0,6>: Cost 4 vmrghw <4,0,5,1>, <4,6,5,2> + 3369675420U, // <4,4,0,7>: Cost 4 vmrglw <2,3,4,0>, <3,6,4,7> + 1165119017U, // <4,4,0,u>: Cost 2 vmrghw <4,0,5,1>, RHS + 3369682633U, // <4,4,1,0>: Cost 4 vmrglw <2,3,4,1>, <2,3,4,0> + 2287313581U, // <4,4,1,1>: Cost 3 vmrglw <0,u,4,1>, <0,u,4,1> + 2759019466U, // <4,4,1,2>: Cost 3 vsldoi12 <1,2,3,4>, <4,1,2,3> + 3369683284U, // <4,4,1,3>: Cost 4 vmrglw <2,3,4,1>, <3,2,4,3> + 2311204048U, // <4,4,1,4>: Cost 3 vmrglw <4,u,4,1>, <4,4,4,4> + 2239319350U, // <4,4,1,5>: Cost 3 vmrghw <4,1,2,3>, RHS + 3784967411U, // <4,4,1,6>: Cost 4 vsldoi8 <4,4,4,4>, <1,6,5,7> + 3369683612U, // <4,4,1,7>: Cost 4 vmrglw <2,3,4,1>, <3,6,4,7> + 2763000832U, // <4,4,1,u>: Cost 3 vsldoi12 <1,u,3,4>, <4,1,u,3> + 3711869030U, // <4,4,2,0>: Cost 4 vsldoi4 <3,4,4,2>, LHS + 3711869850U, // <4,4,2,1>: Cost 4 vsldoi4 <3,4,4,2>, <1,2,3,4> + 2240203830U, // <4,4,2,2>: Cost 3 vmrghw <4,2,5,3>, <4,2,5,3> + 2698618573U, // <4,4,2,3>: Cost 3 vsldoi8 <2,3,4,4>, <2,3,4,4> + 2711226133U, // <4,4,2,4>: Cost 3 vsldoi8 <4,4,4,4>, <2,4,3,4> + 2240204086U, // <4,4,2,5>: Cost 3 vmrghw <4,2,5,3>, RHS + 2711226298U, // <4,4,2,6>: Cost 3 vsldoi8 <4,4,4,4>, <2,6,3,7> + 3832761416U, // <4,4,2,7>: Cost 4 vsldoi12 <1,2,3,4>, <4,2,7,3> + 2701936738U, // <4,4,2,u>: Cost 3 vsldoi8 <2,u,4,4>, <2,u,4,4> + 2711226518U, // <4,4,3,0>: Cost 3 vsldoi8 <4,4,4,4>, <3,0,1,2> + 3777005828U, // <4,4,3,1>: Cost 4 vsldoi8 <3,1,4,4>, <3,1,4,4> + 3832761453U, // <4,4,3,2>: Cost 4 vsldoi12 <1,2,3,4>, <4,3,2,4> + 2301266260U, // <4,4,3,3>: Cost 3 vmrglw <3,2,4,3>, <3,2,4,3> + 2705254903U, // <4,4,3,4>: Cost 3 vsldoi8 <3,4,4,4>, <3,4,4,4> + 2240843062U, // <4,4,3,5>: Cost 3 vmrghw <4,3,5,0>, RHS + 3832761489U, // <4,4,3,6>: Cost 4 vsldoi12 <1,2,3,4>, <4,3,6,4> + 3375008412U, // <4,4,3,7>: Cost 4 vmrglw <3,2,4,3>, <3,6,4,7> + 2301266260U, // <4,4,3,u>: Cost 3 vmrglw <3,2,4,3>, <3,2,4,3> + 1570373734U, // <4,4,4,0>: Cost 2 vsldoi4 <4,4,4,4>, LHS + 2308574089U, // <4,4,4,1>: Cost 3 vmrglw <4,4,4,4>, <4,0,4,1> + 2644117096U, // <4,4,4,2>: Cost 3 vsldoi4 <4,4,4,4>, <2,2,2,2> + 2638146039U, // <4,4,4,3>: Cost 3 vsldoi4 <3,4,4,4>, <3,4,4,4> + 229035318U, // <4,4,4,4>: Cost 1 vspltisw0 RHS + 1167723830U, // <4,4,4,5>: Cost 2 vmrghw <4,4,4,4>, RHS + 2644120058U, // <4,4,4,6>: Cost 3 vsldoi4 <4,4,4,4>, <6,2,7,3> + 2662036827U, // <4,4,4,7>: Cost 3 vsldoi4 <7,4,4,4>, <7,4,4,4> + 229035318U, // <4,4,4,u>: Cost 1 vspltisw0 RHS + 1168558994U, // <4,4,5,0>: Cost 2 vmrghw RHS, <4,0,5,1> + 2638152602U, // <4,4,5,1>: Cost 3 vsldoi4 <3,4,4,5>, <1,2,3,4> + 2242300981U, // <4,4,5,2>: Cost 3 vmrghw RHS, <4,2,5,2> + 2638154232U, // <4,4,5,3>: Cost 3 vsldoi4 <3,4,4,5>, <3,4,4,5> + 1168559322U, // <4,4,5,4>: Cost 2 vmrghw RHS, <4,4,5,5> + 94817590U, // <4,4,5,5>: Cost 1 vmrghw RHS, RHS + 1685278006U, // <4,4,5,6>: Cost 2 vsldoi12 <1,2,3,4>, RHS + 2242309576U, // <4,4,5,7>: Cost 3 vmrghw RHS, <4,7,5,0> + 94817833U, // <4,4,5,u>: Cost 1 vmrghw RHS, RHS + 3316591506U, // <4,4,6,0>: Cost 4 vmrghw <4,6,5,2>, <4,0,5,1> + 3758428587U, // <4,4,6,1>: Cost 4 vsldoi8 <0,0,4,4>, <6,1,7,5> + 2711228922U, // <4,4,6,2>: Cost 3 vsldoi8 <4,4,4,4>, <6,2,7,3> + 3796251185U, // <4,4,6,3>: Cost 4 vsldoi8 <6,3,4,4>, <6,3,4,4> + 2711229085U, // <4,4,6,4>: Cost 3 vsldoi8 <4,4,4,4>, <6,4,7,4> + 2242850102U, // <4,4,6,5>: Cost 3 vmrghw <4,6,5,2>, RHS + 2242850169U, // <4,4,6,6>: Cost 3 vmrghw <4,6,5,2>, <4,6,5,2> + 2725163893U, // <4,4,6,7>: Cost 3 vsldoi8 <6,7,4,4>, <6,7,4,4> + 2242850345U, // <4,4,6,u>: Cost 3 vmrghw <4,6,5,2>, RHS + 2711229434U, // <4,4,7,0>: Cost 3 vsldoi8 <4,4,4,4>, <7,0,1,2> + 3377694410U, // <4,4,7,1>: Cost 4 vmrglw <3,6,4,7>, <2,3,4,1> + 3868593584U, // <4,4,7,2>: Cost 4 vsldoi12 <7,2,3,4>, <4,7,2,3> + 3377695060U, // <4,4,7,3>: Cost 4 vmrglw <3,6,4,7>, <3,2,4,3> + 2729145691U, // <4,4,7,4>: Cost 3 vsldoi8 <7,4,4,4>, <7,4,4,4> + 2243497270U, // <4,4,7,5>: Cost 3 vmrghw <4,7,5,0>, RHS + 3871542744U, // <4,4,7,6>: Cost 4 vsldoi12 <7,6,7,4>, <4,7,6,7> + 2303953564U, // <4,4,7,7>: Cost 3 vmrglw <3,6,4,7>, <3,6,4,7> + 2243497513U, // <4,4,7,u>: Cost 3 vmrghw <4,7,5,0>, RHS + 1170549650U, // <4,4,u,0>: Cost 2 vmrghw RHS, <4,0,5,1> + 1637488430U, // <4,4,u,1>: Cost 2 vsldoi8 <4,4,4,4>, LHS + 2244291637U, // <4,4,u,2>: Cost 3 vmrghw RHS, <4,2,5,2> + 2638178811U, // <4,4,u,3>: Cost 3 vsldoi4 <3,4,4,u>, <3,4,4,u> + 229035318U, // <4,4,u,4>: Cost 1 vspltisw0 RHS + 96808246U, // <4,4,u,5>: Cost 1 vmrghw RHS, RHS + 1685278249U, // <4,4,u,6>: Cost 2 vsldoi12 <1,2,3,4>, RHS + 2244292040U, // <4,4,u,7>: Cost 3 vmrghw RHS, <4,7,5,0> + 96808489U, // <4,4,u,u>: Cost 1 vmrghw RHS, RHS + 2698625024U, // <4,5,0,0>: Cost 3 vsldoi8 <2,3,4,5>, <0,0,0,0> + 1624883302U, // <4,5,0,1>: Cost 2 vsldoi8 <2,3,4,5>, LHS + 2638186190U, // <4,5,0,2>: Cost 3 vsldoi4 <3,4,5,0>, <2,3,4,5> + 2638187004U, // <4,5,0,3>: Cost 3 vsldoi4 <3,4,5,0>, <3,4,5,0> + 2687345005U, // <4,5,0,4>: Cost 3 vsldoi8 <0,4,4,5>, <0,4,4,5> + 2238861316U, // <4,5,0,5>: Cost 3 vmrghw <4,0,5,1>, <5,5,5,5> + 2662077302U, // <4,5,0,6>: Cost 3 vsldoi4 <7,4,5,0>, <6,7,4,5> + 2662077792U, // <4,5,0,7>: Cost 3 vsldoi4 <7,4,5,0>, <7,4,5,0> + 1624883869U, // <4,5,0,u>: Cost 2 vsldoi8 <2,3,4,5>, LHS + 3361057762U, // <4,5,1,0>: Cost 4 vmrglw <0,u,4,1>, <4,1,5,0> + 2691326803U, // <4,5,1,1>: Cost 3 vsldoi8 <1,1,4,5>, <1,1,4,5> + 2698625942U, // <4,5,1,2>: Cost 3 vsldoi8 <2,3,4,5>, <1,2,3,0> + 3361055659U, // <4,5,1,3>: Cost 4 vmrglw <0,u,4,1>, <1,2,5,3> + 3761087567U, // <4,5,1,4>: Cost 4 vsldoi8 <0,4,4,5>, <1,4,5,5> + 2693981335U, // <4,5,1,5>: Cost 3 vsldoi8 <1,5,4,5>, <1,5,4,5> + 2305231362U, // <4,5,1,6>: Cost 3 vmrglw <3,u,4,1>, <3,4,5,6> + 3361055987U, // <4,5,1,7>: Cost 4 vmrglw <0,u,4,1>, <1,6,5,7> + 2695972234U, // <4,5,1,u>: Cost 3 vsldoi8 <1,u,4,5>, <1,u,4,5> + 2638200934U, // <4,5,2,0>: Cost 3 vsldoi4 <3,4,5,2>, LHS + 3761088035U, // <4,5,2,1>: Cost 4 vsldoi8 <0,4,4,5>, <2,1,3,5> + 2697963133U, // <4,5,2,2>: Cost 3 vsldoi8 <2,2,4,5>, <2,2,4,5> + 1624884942U, // <4,5,2,3>: Cost 2 vsldoi8 <2,3,4,5>, <2,3,4,5> + 2698626838U, // <4,5,2,4>: Cost 3 vsldoi8 <2,3,4,5>, <2,4,3,5> + 3772368744U, // <4,5,2,5>: Cost 4 vsldoi8 <2,3,4,5>, <2,5,3,6> + 2698627002U, // <4,5,2,6>: Cost 3 vsldoi8 <2,3,4,5>, <2,6,3,7> + 3775023122U, // <4,5,2,7>: Cost 4 vsldoi8 <2,7,4,5>, <2,7,4,5> + 1628203107U, // <4,5,2,u>: Cost 2 vsldoi8 <2,u,4,5>, <2,u,4,5> + 2698627222U, // <4,5,3,0>: Cost 3 vsldoi8 <2,3,4,5>, <3,0,1,2> + 3765070057U, // <4,5,3,1>: Cost 4 vsldoi8 <1,1,4,5>, <3,1,1,4> + 2698627404U, // <4,5,3,2>: Cost 3 vsldoi8 <2,3,4,5>, <3,2,3,4> + 2698627484U, // <4,5,3,3>: Cost 3 vsldoi8 <2,3,4,5>, <3,3,3,3> + 2698627580U, // <4,5,3,4>: Cost 3 vsldoi8 <2,3,4,5>, <3,4,5,0> + 3779668553U, // <4,5,3,5>: Cost 4 vsldoi8 <3,5,4,5>, <3,5,4,5> + 2725169844U, // <4,5,3,6>: Cost 3 vsldoi8 <6,7,4,5>, <3,6,7,4> + 2707253995U, // <4,5,3,7>: Cost 3 vsldoi8 <3,7,4,5>, <3,7,4,5> + 2698627870U, // <4,5,3,u>: Cost 3 vsldoi8 <2,3,4,5>, <3,u,1,2> + 2638217318U, // <4,5,4,0>: Cost 3 vsldoi4 <3,4,5,4>, LHS + 2308574098U, // <4,5,4,1>: Cost 3 vmrglw <4,4,4,4>, <4,0,5,1> + 2698628150U, // <4,5,4,2>: Cost 3 vsldoi8 <2,3,4,5>, <4,2,5,3> + 2638219776U, // <4,5,4,3>: Cost 3 vsldoi4 <3,4,5,4>, <3,4,5,4> + 2698628314U, // <4,5,4,4>: Cost 3 vsldoi8 <2,3,4,5>, <4,4,5,5> + 1624886582U, // <4,5,4,5>: Cost 2 vsldoi8 <2,3,4,5>, RHS + 2698628478U, // <4,5,4,6>: Cost 3 vsldoi8 <2,3,4,5>, <4,6,5,7> + 2662110564U, // <4,5,4,7>: Cost 3 vsldoi4 <7,4,5,4>, <7,4,5,4> + 1624886825U, // <4,5,4,u>: Cost 2 vsldoi8 <2,3,4,5>, RHS + 1570455654U, // <4,5,5,0>: Cost 2 vsldoi4 <4,4,5,5>, LHS + 2312564250U, // <4,5,5,1>: Cost 3 vmrglw <5,1,4,5>, <4,u,5,1> + 2644199118U, // <4,5,5,2>: Cost 3 vsldoi4 <4,4,5,5>, <2,3,4,5> + 2295974966U, // <4,5,5,3>: Cost 3 vmrglw <2,3,4,5>, <4,2,5,3> + 1570458842U, // <4,5,5,4>: Cost 2 vsldoi4 <4,4,5,5>, <4,4,5,5> + 1168568324U, // <4,5,5,5>: Cost 2 vmrghw RHS, <5,5,5,5> + 1168568418U, // <4,5,5,6>: Cost 2 vmrghw RHS, <5,6,7,0> + 2295975294U, // <4,5,5,7>: Cost 3 vmrglw <2,3,4,5>, <4,6,5,7> + 1168716036U, // <4,5,5,u>: Cost 2 vmrghw RHS, <5,u,7,0> + 1564491878U, // <4,5,6,0>: Cost 2 vsldoi4 <3,4,5,6>, LHS + 2626290768U, // <4,5,6,1>: Cost 3 vsldoi4 <1,4,5,6>, <1,4,5,6> + 2632263465U, // <4,5,6,2>: Cost 3 vsldoi4 <2,4,5,6>, <2,4,5,6> + 1564494338U, // <4,5,6,3>: Cost 2 vsldoi4 <3,4,5,6>, <3,4,5,6> + 1564495158U, // <4,5,6,4>: Cost 2 vsldoi4 <3,4,5,6>, RHS + 2638237464U, // <4,5,6,5>: Cost 3 vsldoi4 <3,4,5,6>, <5,2,6,3> + 2656154253U, // <4,5,6,6>: Cost 3 vsldoi4 <6,4,5,6>, <6,4,5,6> + 27705344U, // <4,5,6,7>: Cost 0 copy RHS + 27705344U, // <4,5,6,u>: Cost 0 copy RHS + 2725172218U, // <4,5,7,0>: Cost 3 vsldoi8 <6,7,4,5>, <7,0,1,2> + 3859599489U, // <4,5,7,1>: Cost 4 vsldoi12 <5,6,7,4>, <5,7,1,4> + 2698630320U, // <4,5,7,2>: Cost 3 vsldoi8 <2,3,4,5>, <7,2,3,4> + 2728490251U, // <4,5,7,3>: Cost 3 vsldoi8 <7,3,4,5>, <7,3,4,5> + 2725172576U, // <4,5,7,4>: Cost 3 vsldoi8 <6,7,4,5>, <7,4,5,0> + 3317239812U, // <4,5,7,5>: Cost 4 vmrghw <4,7,5,0>, <5,5,5,5> + 2725172760U, // <4,5,7,6>: Cost 3 vsldoi8 <6,7,4,5>, <7,6,7,4> + 2725172844U, // <4,5,7,7>: Cost 3 vsldoi8 <6,7,4,5>, <7,7,7,7> + 2725172866U, // <4,5,7,u>: Cost 3 vsldoi8 <6,7,4,5>, <7,u,1,2> + 1564508262U, // <4,5,u,0>: Cost 2 vsldoi4 <3,4,5,u>, LHS + 1624889134U, // <4,5,u,1>: Cost 2 vsldoi8 <2,3,4,5>, LHS + 2698631045U, // <4,5,u,2>: Cost 3 vsldoi8 <2,3,4,5>, + 1564510724U, // <4,5,u,3>: Cost 2 vsldoi4 <3,4,5,u>, <3,4,5,u> + 1564511542U, // <4,5,u,4>: Cost 2 vsldoi4 <3,4,5,u>, RHS + 1624889498U, // <4,5,u,5>: Cost 2 vsldoi8 <2,3,4,5>, RHS + 1170550882U, // <4,5,u,6>: Cost 2 vmrghw RHS, <5,6,7,0> + 27705344U, // <4,5,u,7>: Cost 0 copy RHS + 27705344U, // <4,5,u,u>: Cost 0 copy RHS + 3312595285U, // <4,6,0,0>: Cost 4 vmrghw <4,0,5,0>, <6,0,7,0> + 3763748966U, // <4,6,0,1>: Cost 4 vsldoi8 <0,u,4,6>, LHS + 2238861818U, // <4,6,0,2>: Cost 3 vmrghw <4,0,5,1>, <6,2,7,3> + 3767730432U, // <4,6,0,3>: Cost 4 vsldoi8 <1,5,4,6>, <0,3,1,4> + 3763749202U, // <4,6,0,4>: Cost 4 vsldoi8 <0,u,4,6>, <0,4,1,5> + 2238862059U, // <4,6,0,5>: Cost 3 vmrghw <4,0,5,1>, <6,5,7,1> + 2238862136U, // <4,6,0,6>: Cost 3 vmrghw <4,0,5,1>, <6,6,6,6> + 2295934262U, // <4,6,0,7>: Cost 3 vmrglw <2,3,4,0>, RHS + 2295934263U, // <4,6,0,u>: Cost 3 vmrglw <2,3,4,0>, RHS + 3378973999U, // <4,6,1,0>: Cost 4 vmrglw <3,u,4,1>, <4,5,6,0> + 3378974648U, // <4,6,1,1>: Cost 4 vmrglw <3,u,4,1>, <5,4,6,1> + 3779675034U, // <4,6,1,2>: Cost 4 vsldoi8 <3,5,4,6>, <1,2,3,4> + 3378974002U, // <4,6,1,3>: Cost 4 vmrglw <3,u,4,1>, <4,5,6,3> + 3378974003U, // <4,6,1,4>: Cost 4 vmrglw <3,u,4,1>, <4,5,6,4> + 3767731352U, // <4,6,1,5>: Cost 4 vsldoi8 <1,5,4,6>, <1,5,4,6> + 3378974734U, // <4,6,1,6>: Cost 4 vmrglw <3,u,4,1>, <5,5,6,6> + 2287316278U, // <4,6,1,7>: Cost 3 vmrglw <0,u,4,1>, RHS + 2287316279U, // <4,6,1,u>: Cost 3 vmrglw <0,u,4,1>, RHS + 3735904358U, // <4,6,2,0>: Cost 4 vsldoi4 <7,4,6,2>, LHS + 3763750435U, // <4,6,2,1>: Cost 5 vsldoi8 <0,u,4,6>, <2,1,3,5> + 3313938937U, // <4,6,2,2>: Cost 4 vmrghw <4,2,5,2>, <6,2,7,2> + 3772376782U, // <4,6,2,3>: Cost 4 vsldoi8 <2,3,4,6>, <2,3,4,5> + 3852890591U, // <4,6,2,4>: Cost 4 vsldoi12 <4,5,6,4>, <6,2,4,3> + 3735908454U, // <4,6,2,5>: Cost 4 vsldoi4 <7,4,6,2>, <5,6,7,4> + 3801573306U, // <4,6,2,6>: Cost 4 vsldoi8 <7,2,4,6>, <2,6,3,7> + 2785858042U, // <4,6,2,7>: Cost 3 vsldoi12 <5,6,7,4>, <6,2,7,3> + 2785858051U, // <4,6,2,u>: Cost 3 vsldoi12 <5,6,7,4>, <6,2,u,3> + 3863065101U, // <4,6,3,0>: Cost 4 vsldoi12 <6,3,0,4>, <6,3,0,4> + 3314586024U, // <4,6,3,1>: Cost 4 vmrghw <4,3,5,0>, <6,1,7,2> + 3863212575U, // <4,6,3,2>: Cost 4 vsldoi12 <6,3,2,4>, <6,3,2,4> + 3863286312U, // <4,6,3,3>: Cost 4 vsldoi12 <6,3,3,4>, <6,3,3,4> + 3767732738U, // <4,6,3,4>: Cost 4 vsldoi8 <1,5,4,6>, <3,4,5,6> + 3779676746U, // <4,6,3,5>: Cost 4 vsldoi8 <3,5,4,6>, <3,5,4,6> + 3398898488U, // <4,6,3,6>: Cost 4 vmrglw <7,2,4,3>, <6,6,6,6> + 2301267254U, // <4,6,3,7>: Cost 3 vmrglw <3,2,4,3>, RHS + 2301267255U, // <4,6,3,u>: Cost 3 vmrglw <3,2,4,3>, RHS + 3852890715U, // <4,6,4,0>: Cost 4 vsldoi12 <4,5,6,4>, <6,4,0,1> + 3315208615U, // <4,6,4,1>: Cost 4 vmrghw <4,4,4,4>, <6,1,7,1> + 2241466874U, // <4,6,4,2>: Cost 3 vmrghw <4,4,4,4>, <6,2,7,3> + 3852890745U, // <4,6,4,3>: Cost 4 vsldoi12 <4,5,6,4>, <6,4,3,4> + 2241467037U, // <4,6,4,4>: Cost 3 vmrghw <4,4,4,4>, <6,4,7,4> + 2241549039U, // <4,6,4,5>: Cost 3 vmrghw <4,4,5,5>, <6,5,7,5> + 2241467192U, // <4,6,4,6>: Cost 3 vmrghw <4,4,4,4>, <6,6,6,6> + 1234832694U, // <4,6,4,7>: Cost 2 vmrglw <4,4,4,4>, RHS + 1234832695U, // <4,6,4,u>: Cost 2 vmrglw <4,4,4,4>, RHS + 2242302241U, // <4,6,5,0>: Cost 3 vmrghw RHS, <6,0,1,2> + 2242310567U, // <4,6,5,1>: Cost 3 vmrghw RHS, <6,1,7,1> + 1168568826U, // <4,6,5,2>: Cost 2 vmrghw RHS, <6,2,7,3> + 2242302514U, // <4,6,5,3>: Cost 3 vmrghw RHS, <6,3,4,5> + 2242302605U, // <4,6,5,4>: Cost 3 vmrghw RHS, <6,4,5,6> + 2242310891U, // <4,6,5,5>: Cost 3 vmrghw RHS, <6,5,7,1> + 1168569144U, // <4,6,5,6>: Cost 2 vmrghw RHS, <6,6,6,6> + 1222233398U, // <4,6,5,7>: Cost 2 vmrglw <2,3,4,5>, RHS + 1222233399U, // <4,6,5,u>: Cost 2 vmrglw <2,3,4,5>, RHS + 3316576545U, // <4,6,6,0>: Cost 4 vmrghw <4,6,5,0>, <6,0,1,2> + 3316584871U, // <4,6,6,1>: Cost 4 vmrghw <4,6,5,1>, <6,1,7,1> + 2242851322U, // <4,6,6,2>: Cost 3 vmrghw <4,6,5,2>, <6,2,7,3> + 3316601394U, // <4,6,6,3>: Cost 4 vmrghw <4,6,5,3>, <6,3,4,5> + 3852890916U, // <4,6,6,4>: Cost 4 vsldoi12 <4,5,6,4>, <6,6,4,4> + 3316617963U, // <4,6,6,5>: Cost 4 vmrghw <4,6,5,5>, <6,5,7,1> + 2242884408U, // <4,6,6,6>: Cost 3 vmrghw <4,6,5,6>, <6,6,6,6> + 2785858370U, // <4,6,6,7>: Cost 3 vsldoi12 <5,6,7,4>, <6,6,7,7> + 2785858379U, // <4,6,6,u>: Cost 3 vsldoi12 <5,6,7,4>, <6,6,u,7> + 2785858382U, // <4,6,7,0>: Cost 3 vsldoi12 <5,6,7,4>, <6,7,0,1> + 3859600215U, // <4,6,7,1>: Cost 4 vsldoi12 <5,6,7,4>, <6,7,1,1> + 3317240314U, // <4,6,7,2>: Cost 4 vmrghw <4,7,5,0>, <6,2,7,3> + 2792199020U, // <4,6,7,3>: Cost 3 vsldoi12 <6,7,3,4>, <6,7,3,4> + 2785858422U, // <4,6,7,4>: Cost 3 vsldoi12 <5,6,7,4>, <6,7,4,5> + 3856651132U, // <4,6,7,5>: Cost 4 vsldoi12 <5,2,3,4>, <6,7,5,2> + 3317240632U, // <4,6,7,6>: Cost 4 vmrghw <4,7,5,0>, <6,6,6,6> + 2303954230U, // <4,6,7,7>: Cost 3 vmrglw <3,6,4,7>, RHS + 2303954231U, // <4,6,7,u>: Cost 3 vmrglw <3,6,4,7>, RHS + 2244292897U, // <4,6,u,0>: Cost 3 vmrghw RHS, <6,0,1,2> + 2244293031U, // <4,6,u,1>: Cost 3 vmrghw RHS, <6,1,7,1> + 1170551290U, // <4,6,u,2>: Cost 2 vmrghw RHS, <6,2,7,3> + 2244293170U, // <4,6,u,3>: Cost 3 vmrghw RHS, <6,3,4,5> + 2244293261U, // <4,6,u,4>: Cost 3 vmrghw RHS, <6,4,5,6> + 2244293355U, // <4,6,u,5>: Cost 3 vmrghw RHS, <6,5,7,1> + 1170551608U, // <4,6,u,6>: Cost 2 vmrghw RHS, <6,6,6,6> + 1222257974U, // <4,6,u,7>: Cost 2 vmrglw <2,3,4,u>, RHS + 1222257975U, // <4,6,u,u>: Cost 2 vmrglw <2,3,4,u>, RHS + 2238862330U, // <4,7,0,0>: Cost 3 vmrghw <4,0,5,1>, <7,0,1,2> + 2706604134U, // <4,7,0,1>: Cost 3 vsldoi8 <3,6,4,7>, LHS + 3312604308U, // <4,7,0,2>: Cost 4 vmrghw <4,0,5,1>, <7,2,0,3> + 3768402176U, // <4,7,0,3>: Cost 4 vsldoi8 <1,6,4,7>, <0,3,1,4> + 2238862648U, // <4,7,0,4>: Cost 3 vmrghw <4,0,5,1>, <7,4,0,5> + 3859600418U, // <4,7,0,5>: Cost 4 vsldoi12 <5,6,7,4>, <7,0,5,6> + 3729994393U, // <4,7,0,6>: Cost 4 vsldoi4 <6,4,7,0>, <6,4,7,0> + 2238862956U, // <4,7,0,7>: Cost 3 vmrghw <4,0,5,1>, <7,7,7,7> + 2706604701U, // <4,7,0,u>: Cost 3 vsldoi8 <3,6,4,7>, LHS + 3385610338U, // <4,7,1,0>: Cost 4 vmrglw <5,0,4,1>, <5,6,7,0> + 3780346676U, // <4,7,1,1>: Cost 4 vsldoi8 <3,6,4,7>, <1,1,1,1> + 2706604954U, // <4,7,1,2>: Cost 3 vsldoi8 <3,6,4,7>, <1,2,3,4> + 3385610746U, // <4,7,1,3>: Cost 4 vmrglw <5,0,4,1>, <6,2,7,3> + 3385610342U, // <4,7,1,4>: Cost 4 vmrglw <5,0,4,1>, <5,6,7,4> + 3385610667U, // <4,7,1,5>: Cost 4 vmrglw <5,0,4,1>, <6,1,7,5> + 3768403178U, // <4,7,1,6>: Cost 4 vsldoi8 <1,6,4,7>, <1,6,4,7> + 3385611074U, // <4,7,1,7>: Cost 4 vmrglw <5,0,4,1>, <6,6,7,7> + 2706604954U, // <4,7,1,u>: Cost 3 vsldoi8 <3,6,4,7>, <1,2,3,4> + 3859600532U, // <4,7,2,0>: Cost 4 vsldoi12 <5,6,7,4>, <7,2,0,3> + 3712091034U, // <4,7,2,1>: Cost 5 vsldoi4 <3,4,7,2>, <1,2,3,4> + 3774375528U, // <4,7,2,2>: Cost 4 vsldoi8 <2,6,4,7>, <2,2,2,2> + 2794853552U, // <4,7,2,3>: Cost 3 vsldoi12 <7,2,3,4>, <7,2,3,4> + 2785858744U, // <4,7,2,4>: Cost 3 vsldoi12 <5,6,7,4>, <7,2,4,3> + 3735982182U, // <4,7,2,5>: Cost 4 vsldoi4 <7,4,7,2>, <5,6,7,4> + 3774375875U, // <4,7,2,6>: Cost 4 vsldoi8 <2,6,4,7>, <2,6,4,7> + 3735983476U, // <4,7,2,7>: Cost 4 vsldoi4 <7,4,7,2>, <7,4,7,2> + 2795222237U, // <4,7,2,u>: Cost 3 vsldoi12 <7,2,u,4>, <7,2,u,4> + 3780348054U, // <4,7,3,0>: Cost 4 vsldoi8 <3,6,4,7>, <3,0,1,2> + 3730015130U, // <4,7,3,1>: Cost 4 vsldoi4 <6,4,7,3>, <1,2,3,4> + 3780348244U, // <4,7,3,2>: Cost 4 vsldoi8 <3,6,4,7>, <3,2,4,3> + 3778357673U, // <4,7,3,3>: Cost 4 vsldoi8 <3,3,4,7>, <3,3,4,7> + 2325155942U, // <4,7,3,4>: Cost 3 vmrglw <7,2,4,3>, <5,6,7,4> + 3779684939U, // <4,7,3,5>: Cost 5 vsldoi8 <3,5,4,7>, <3,5,4,7> + 2706606748U, // <4,7,3,6>: Cost 3 vsldoi8 <3,6,4,7>, <3,6,4,7> + 3398898498U, // <4,7,3,7>: Cost 4 vmrglw <7,2,4,3>, <6,6,7,7> + 2707934014U, // <4,7,3,u>: Cost 3 vsldoi8 <3,u,4,7>, <3,u,4,7> + 2785858868U, // <4,7,4,0>: Cost 3 vsldoi12 <5,6,7,4>, <7,4,0,1> + 3780348874U, // <4,7,4,1>: Cost 4 vsldoi8 <3,6,4,7>, <4,1,2,3> + 3780349000U, // <4,7,4,2>: Cost 4 vsldoi8 <3,6,4,7>, <4,2,7,3> + 2308575738U, // <4,7,4,3>: Cost 3 vmrglw <4,4,4,4>, <6,2,7,3> + 2656283856U, // <4,7,4,4>: Cost 3 vsldoi4 <6,4,7,4>, <4,4,4,4> + 2706607414U, // <4,7,4,5>: Cost 3 vsldoi8 <3,6,4,7>, RHS + 2656285341U, // <4,7,4,6>: Cost 3 vsldoi4 <6,4,7,4>, <6,4,7,4> + 2241468012U, // <4,7,4,7>: Cost 3 vmrghw <4,4,4,4>, <7,7,7,7> + 2706607657U, // <4,7,4,u>: Cost 3 vsldoi8 <3,6,4,7>, RHS + 1168569338U, // <4,7,5,0>: Cost 2 vmrghw RHS, <7,0,1,2> + 2242311242U, // <4,7,5,1>: Cost 3 vmrghw RHS, <7,1,1,1> + 2242303178U, // <4,7,5,2>: Cost 3 vmrghw RHS, <7,2,6,3> + 2242311395U, // <4,7,5,3>: Cost 3 vmrghw RHS, <7,3,0,1> + 1168569702U, // <4,7,5,4>: Cost 2 vmrghw RHS, <7,4,5,6> + 2242311606U, // <4,7,5,5>: Cost 3 vmrghw RHS, <7,5,5,5> + 2242311662U, // <4,7,5,6>: Cost 3 vmrghw RHS, <7,6,2,7> + 1168569964U, // <4,7,5,7>: Cost 2 vmrghw RHS, <7,7,7,7> + 1168569986U, // <4,7,5,u>: Cost 2 vmrghw RHS, <7,u,1,2> + 3316593658U, // <4,7,6,0>: Cost 4 vmrghw <4,6,5,2>, <7,0,1,2> + 3316593738U, // <4,7,6,1>: Cost 5 vmrghw <4,6,5,2>, <7,1,1,1> + 3316634800U, // <4,7,6,2>: Cost 4 vmrghw <4,6,5,7>, <7,2,3,4> + 3386978810U, // <4,7,6,3>: Cost 4 vmrglw <5,2,4,6>, <6,2,7,3> + 2785859072U, // <4,7,6,4>: Cost 3 vsldoi12 <5,6,7,4>, <7,6,4,7> + 3736014950U, // <4,7,6,5>: Cost 4 vsldoi4 <7,4,7,6>, <5,6,7,4> + 3316594158U, // <4,7,6,6>: Cost 4 vmrghw <4,6,5,2>, <7,6,2,7> + 2797803032U, // <4,7,6,7>: Cost 3 vsldoi12 <7,6,7,4>, <7,6,7,4> + 2797876769U, // <4,7,6,u>: Cost 3 vsldoi12 <7,6,u,4>, <7,6,u,4> + 2243499002U, // <4,7,7,0>: Cost 3 vmrghw <4,7,5,0>, <7,0,1,2> + 3718103962U, // <4,7,7,1>: Cost 4 vsldoi4 <4,4,7,7>, <1,2,3,4> + 3317257418U, // <4,7,7,2>: Cost 4 vmrghw <4,7,5,2>, <7,2,6,3> + 3377695816U, // <4,7,7,3>: Cost 4 vmrglw <3,6,4,7>, <4,2,7,3> + 2243532134U, // <4,7,7,4>: Cost 3 vmrghw <4,7,5,4>, <7,4,5,6> + 3317282230U, // <4,7,7,5>: Cost 4 vmrghw <4,7,5,5>, <7,5,5,5> + 2730497536U, // <4,7,7,6>: Cost 3 vsldoi8 <7,6,4,7>, <7,6,4,7> + 2243556972U, // <4,7,7,7>: Cost 3 vmrghw <4,7,5,7>, <7,7,7,7> + 2243565186U, // <4,7,7,u>: Cost 3 vmrghw <4,7,5,u>, <7,u,1,2> + 1170551802U, // <4,7,u,0>: Cost 2 vmrghw RHS, <7,0,1,2> + 2706609966U, // <4,7,u,1>: Cost 3 vsldoi8 <3,6,4,7>, LHS + 2244293797U, // <4,7,u,2>: Cost 3 vmrghw RHS, <7,2,2,2> + 2244293859U, // <4,7,u,3>: Cost 3 vmrghw RHS, <7,3,0,1> + 1170552166U, // <4,7,u,4>: Cost 2 vmrghw RHS, <7,4,5,6> + 2706610330U, // <4,7,u,5>: Cost 3 vsldoi8 <3,6,4,7>, RHS + 2244294126U, // <4,7,u,6>: Cost 3 vmrghw RHS, <7,6,2,7> + 1170552428U, // <4,7,u,7>: Cost 2 vmrghw RHS, <7,7,7,7> + 1170552450U, // <4,7,u,u>: Cost 2 vmrghw RHS, <7,u,1,2> + 1165118354U, // <4,u,0,0>: Cost 2 vmrghw <4,0,5,1>, <4,0,5,1> + 1624907878U, // <4,u,0,1>: Cost 2 vsldoi8 <2,3,4,u>, LHS + 2638407377U, // <4,u,0,2>: Cost 3 vsldoi4 <3,4,u,0>, <2,3,4,u> + 2295931036U, // <4,u,0,3>: Cost 3 vmrglw <2,3,4,0>, LHS + 2687369584U, // <4,u,0,4>: Cost 3 vsldoi8 <0,4,4,u>, <0,4,4,u> + 1165121690U, // <4,u,0,5>: Cost 2 vmrghw <4,0,5,1>, RHS + 2662298489U, // <4,u,0,6>: Cost 3 vsldoi4 <7,4,u,0>, <6,7,4,u> + 2295934280U, // <4,u,0,7>: Cost 3 vmrglw <2,3,4,0>, RHS + 1624908445U, // <4,u,0,u>: Cost 2 vsldoi8 <2,3,4,u>, LHS + 2638413926U, // <4,u,1,0>: Cost 3 vsldoi4 <3,4,u,1>, LHS + 2691351382U, // <4,u,1,1>: Cost 3 vsldoi8 <1,1,4,u>, <1,1,4,u> + 1685280558U, // <4,u,1,2>: Cost 2 vsldoi12 <1,2,3,4>, LHS + 2287313052U, // <4,u,1,3>: Cost 3 vmrglw <0,u,4,1>, LHS + 2299257799U, // <4,u,1,4>: Cost 3 vmrglw <2,u,4,1>, <1,2,u,4> + 2694005914U, // <4,u,1,5>: Cost 3 vsldoi8 <1,5,4,u>, <1,5,4,u> + 2305231362U, // <4,u,1,6>: Cost 3 vmrglw <3,u,4,1>, <3,4,5,6> + 2287316296U, // <4,u,1,7>: Cost 3 vmrglw <0,u,4,1>, RHS + 1685280612U, // <4,u,1,u>: Cost 2 vsldoi12 <1,2,3,4>, LHS + 2638422118U, // <4,u,2,0>: Cost 3 vsldoi4 <3,4,u,2>, LHS + 2240206638U, // <4,u,2,1>: Cost 3 vmrghw <4,2,5,3>, LHS + 2697987712U, // <4,u,2,2>: Cost 3 vsldoi8 <2,2,4,u>, <2,2,4,u> + 1624909521U, // <4,u,2,3>: Cost 2 vsldoi8 <2,3,4,u>, <2,3,4,u> + 2759391121U, // <4,u,2,4>: Cost 3 vsldoi12 <1,2,u,4>, + 2240207002U, // <4,u,2,5>: Cost 3 vmrghw <4,2,5,3>, RHS + 2698651578U, // <4,u,2,6>: Cost 3 vsldoi8 <2,3,4,u>, <2,6,3,7> + 2785859500U, // <4,u,2,7>: Cost 3 vsldoi12 <5,6,7,4>, + 1628227686U, // <4,u,2,u>: Cost 2 vsldoi8 <2,u,4,u>, <2,u,4,u> + 2759022524U, // <4,u,3,0>: Cost 3 vsldoi12 <1,2,3,4>, + 2801342408U, // <4,u,3,1>: Cost 3 vsldoi12 , + 2703960409U, // <4,u,3,2>: Cost 3 vsldoi8 <3,2,4,u>, <3,2,4,u> + 2759022554U, // <4,u,3,3>: Cost 3 vsldoi12 <1,2,3,4>, + 2759022564U, // <4,u,3,4>: Cost 3 vsldoi12 <1,2,3,4>, + 2240845978U, // <4,u,3,5>: Cost 3 vmrghw <4,3,5,0>, RHS + 2706614941U, // <4,u,3,6>: Cost 3 vsldoi8 <3,6,4,u>, <3,6,4,u> + 2301267272U, // <4,u,3,7>: Cost 3 vmrglw <3,2,4,3>, RHS + 2759022596U, // <4,u,3,u>: Cost 3 vsldoi12 <1,2,3,4>, + 1570668646U, // <4,u,4,0>: Cost 2 vsldoi4 <4,4,u,4>, LHS + 1167726382U, // <4,u,4,1>: Cost 2 vmrghw <4,4,4,4>, LHS + 2698652753U, // <4,u,4,2>: Cost 3 vsldoi8 <2,3,4,u>, <4,2,u,3> + 1234829468U, // <4,u,4,3>: Cost 2 vmrglw <4,4,4,4>, LHS + 229035318U, // <4,u,4,4>: Cost 1 vspltisw0 RHS + 1624911158U, // <4,u,4,5>: Cost 2 vsldoi8 <2,3,4,u>, RHS + 2698653081U, // <4,u,4,6>: Cost 3 vsldoi8 <2,3,4,u>, <4,6,u,7> + 1234832712U, // <4,u,4,7>: Cost 2 vmrglw <4,4,4,4>, RHS + 229035318U, // <4,u,4,u>: Cost 1 vspltisw0 RHS + 1168561875U, // <4,u,5,0>: Cost 2 vmrghw RHS, + 94820142U, // <4,u,5,1>: Cost 1 vmrghw RHS, LHS + 1168562053U, // <4,u,5,2>: Cost 2 vmrghw RHS, + 1222230172U, // <4,u,5,3>: Cost 2 vmrglw <2,3,4,5>, LHS + 1168562239U, // <4,u,5,4>: Cost 2 vmrghw RHS, + 94820506U, // <4,u,5,5>: Cost 1 vmrghw RHS, RHS + 1685280922U, // <4,u,5,6>: Cost 2 vsldoi12 <1,2,3,4>, RHS + 1222233416U, // <4,u,5,7>: Cost 2 vmrglw <2,3,4,5>, RHS + 94820709U, // <4,u,5,u>: Cost 1 vmrghw RHS, LHS + 1564713062U, // <4,u,6,0>: Cost 2 vsldoi4 <3,4,u,6>, LHS + 2626511979U, // <4,u,6,1>: Cost 3 vsldoi4 <1,4,u,6>, <1,4,u,6> + 2632484676U, // <4,u,6,2>: Cost 3 vsldoi4 <2,4,u,6>, <2,4,u,6> + 1564715549U, // <4,u,6,3>: Cost 2 vsldoi4 <3,4,u,6>, <3,4,u,6> + 1564716342U, // <4,u,6,4>: Cost 2 vsldoi4 <3,4,u,6>, RHS + 2242853018U, // <4,u,6,5>: Cost 3 vmrghw <4,6,5,2>, RHS + 2656375464U, // <4,u,6,6>: Cost 3 vsldoi4 <6,4,u,6>, <6,4,u,6> + 27705344U, // <4,u,6,7>: Cost 0 copy RHS + 27705344U, // <4,u,6,u>: Cost 0 copy RHS + 2785859840U, // <4,u,7,0>: Cost 3 vsldoi12 <5,6,7,4>, + 2243499822U, // <4,u,7,1>: Cost 3 vmrghw <4,7,5,0>, LHS + 2727851197U, // <4,u,7,2>: Cost 3 vsldoi8 <7,2,4,u>, <7,2,4,u> + 2303951004U, // <4,u,7,3>: Cost 3 vmrglw <3,6,4,7>, LHS + 2785859880U, // <4,u,7,4>: Cost 3 vsldoi12 <5,6,7,4>, + 2243500186U, // <4,u,7,5>: Cost 3 vmrghw <4,7,5,0>, RHS + 2730505729U, // <4,u,7,6>: Cost 3 vsldoi8 <7,6,4,u>, <7,6,4,u> + 2303954248U, // <4,u,7,7>: Cost 3 vmrglw <3,6,4,7>, RHS + 2303951009U, // <4,u,7,u>: Cost 3 vmrglw <3,6,4,7>, LHS + 1564729446U, // <4,u,u,0>: Cost 2 vsldoi4 <3,4,u,u>, LHS + 96810798U, // <4,u,u,1>: Cost 1 vmrghw RHS, LHS + 1685281125U, // <4,u,u,2>: Cost 2 vsldoi12 <1,2,3,4>, LHS + 1222254748U, // <4,u,u,3>: Cost 2 vmrglw <2,3,4,u>, LHS + 229035318U, // <4,u,u,4>: Cost 1 vspltisw0 RHS + 96811162U, // <4,u,u,5>: Cost 1 vmrghw RHS, RHS + 1685281165U, // <4,u,u,6>: Cost 2 vsldoi12 <1,2,3,4>, RHS + 27705344U, // <4,u,u,7>: Cost 0 copy RHS + 27705344U, // <4,u,u,u>: Cost 0 copy RHS + 2754232320U, // <5,0,0,0>: Cost 3 vsldoi12 <0,4,1,5>, <0,0,0,0> + 2754232330U, // <5,0,0,1>: Cost 3 vsldoi12 <0,4,1,5>, <0,0,1,1> + 3718194894U, // <5,0,0,2>: Cost 4 vsldoi4 <4,5,0,0>, <2,3,4,5> + 3376385762U, // <5,0,0,3>: Cost 4 vmrglw <3,4,5,0>, <5,2,0,3> + 2754232357U, // <5,0,0,4>: Cost 3 vsldoi12 <0,4,1,5>, <0,0,4,1> + 3845816370U, // <5,0,0,5>: Cost 4 vsldoi12 <3,4,0,5>, <0,0,5,5> + 3782353389U, // <5,0,0,6>: Cost 4 vsldoi8 <4,0,5,0>, <0,6,0,7> + 3376386090U, // <5,0,0,7>: Cost 4 vmrglw <3,4,5,0>, <5,6,0,7> + 2757402697U, // <5,0,0,u>: Cost 3 vsldoi12 <0,u,u,5>, <0,0,u,1> + 2626543718U, // <5,0,1,0>: Cost 3 vsldoi4 <1,5,0,1>, LHS + 2626544751U, // <5,0,1,1>: Cost 3 vsldoi4 <1,5,0,1>, <1,5,0,1> + 1680490598U, // <5,0,1,2>: Cost 2 vsldoi12 <0,4,1,5>, LHS + 3766428665U, // <5,0,1,3>: Cost 4 vsldoi8 <1,3,5,0>, <1,3,5,0> + 2626546998U, // <5,0,1,4>: Cost 3 vsldoi4 <1,5,0,1>, RHS + 2650435539U, // <5,0,1,5>: Cost 3 vsldoi4 <5,5,0,1>, <5,5,0,1> + 3783017715U, // <5,0,1,6>: Cost 4 vsldoi8 <4,1,5,0>, <1,6,5,7> + 3385019000U, // <5,0,1,7>: Cost 4 vmrglw <4,u,5,1>, <3,6,0,7> + 1680490652U, // <5,0,1,u>: Cost 2 vsldoi12 <0,4,1,5>, LHS + 3376398336U, // <5,0,2,0>: Cost 4 vmrglw <3,4,5,2>, <0,0,0,0> + 2245877862U, // <5,0,2,1>: Cost 3 vmrghw <5,2,1,3>, LHS + 3773064808U, // <5,0,2,2>: Cost 4 vsldoi8 <2,4,5,0>, <2,2,2,2> + 2705295054U, // <5,0,2,3>: Cost 3 vsldoi8 <3,4,5,0>, <2,3,4,5> + 3827974343U, // <5,0,2,4>: Cost 4 vsldoi12 <0,4,1,5>, <0,2,4,1> + 3845816530U, // <5,0,2,5>: Cost 4 vsldoi12 <3,4,0,5>, <0,2,5,3> + 3779037114U, // <5,0,2,6>: Cost 4 vsldoi8 <3,4,5,0>, <2,6,3,7> + 3810887658U, // <5,0,2,7>: Cost 4 vsldoi8 , <2,7,0,1> + 2245878429U, // <5,0,2,u>: Cost 3 vmrghw <5,2,1,3>, LHS + 2710603926U, // <5,0,3,0>: Cost 3 vsldoi8 <4,3,5,0>, <3,0,1,2> + 3827974396U, // <5,0,3,1>: Cost 4 vsldoi12 <0,4,1,5>, <0,3,1,0> + 3779037516U, // <5,0,3,2>: Cost 4 vsldoi8 <3,4,5,0>, <3,2,3,4> + 3779037596U, // <5,0,3,3>: Cost 4 vsldoi8 <3,4,5,0>, <3,3,3,3> + 2705295868U, // <5,0,3,4>: Cost 3 vsldoi8 <3,4,5,0>, <3,4,5,0> + 3379726804U, // <5,0,3,5>: Cost 4 vmrglw <4,0,5,3>, <3,4,0,5> + 3802925748U, // <5,0,3,6>: Cost 4 vsldoi8 <7,4,5,0>, <3,6,7,4> + 3363138168U, // <5,0,3,7>: Cost 5 vmrglw <1,2,5,3>, <3,6,0,7> + 2707950400U, // <5,0,3,u>: Cost 3 vsldoi8 <3,u,5,0>, <3,u,5,0> + 2626568294U, // <5,0,4,0>: Cost 3 vsldoi4 <1,5,0,4>, LHS + 1680490834U, // <5,0,4,1>: Cost 2 vsldoi12 <0,4,1,5>, <0,4,1,5> + 3828048219U, // <5,0,4,2>: Cost 4 vsldoi12 <0,4,2,5>, <0,4,2,5> + 2710604932U, // <5,0,4,3>: Cost 3 vsldoi8 <4,3,5,0>, <4,3,5,0> + 2754232685U, // <5,0,4,4>: Cost 3 vsldoi12 <0,4,1,5>, <0,4,4,5> + 2705296694U, // <5,0,4,5>: Cost 3 vsldoi8 <3,4,5,0>, RHS + 3779038590U, // <5,0,4,6>: Cost 4 vsldoi8 <3,4,5,0>, <4,6,5,7> + 2713259464U, // <5,0,4,7>: Cost 3 vsldoi8 <4,7,5,0>, <4,7,5,0> + 1680490834U, // <5,0,4,u>: Cost 2 vsldoi12 <0,4,1,5>, <0,4,1,5> + 2311307264U, // <5,0,5,0>: Cost 3 vmrglw <4,u,5,5>, <0,0,0,0> + 1174437990U, // <5,0,5,1>: Cost 2 vmrghw <5,5,5,5>, LHS + 3779038946U, // <5,0,5,2>: Cost 4 vsldoi8 <3,4,5,0>, <5,2,0,3> + 3845816752U, // <5,0,5,3>: Cost 4 vsldoi12 <3,4,0,5>, <0,5,3,0> + 2248180050U, // <5,0,5,4>: Cost 3 vmrghw <5,5,5,5>, <0,4,1,5> + 2248180194U, // <5,0,5,5>: Cost 3 vmrghw <5,5,5,5>, <0,5,u,5> + 3779039274U, // <5,0,5,6>: Cost 4 vsldoi8 <3,4,5,0>, <5,6,0,7> + 3385051768U, // <5,0,5,7>: Cost 4 vmrglw <4,u,5,5>, <3,6,0,7> + 1174438557U, // <5,0,5,u>: Cost 2 vmrghw <5,5,5,5>, LHS + 2302689280U, // <5,0,6,0>: Cost 3 vmrglw <3,4,5,6>, <0,0,0,0> + 1175208038U, // <5,0,6,1>: Cost 2 vmrghw <5,6,7,0>, LHS + 3787002362U, // <5,0,6,2>: Cost 4 vsldoi8 <4,7,5,0>, <6,2,7,3> + 3376432160U, // <5,0,6,3>: Cost 4 vmrglw <3,4,5,6>, <1,4,0,3> + 2248950098U, // <5,0,6,4>: Cost 3 vmrghw <5,6,7,0>, <0,4,1,5> + 2248950180U, // <5,0,6,5>: Cost 3 vmrghw <5,6,7,0>, <0,5,1,6> + 3376433702U, // <5,0,6,6>: Cost 4 vmrglw <3,4,5,6>, <3,5,0,6> + 2729186166U, // <5,0,6,7>: Cost 3 vsldoi8 <7,4,5,0>, <6,7,4,5> + 1175208605U, // <5,0,6,u>: Cost 2 vmrghw <5,6,7,0>, LHS + 2713261050U, // <5,0,7,0>: Cost 3 vsldoi8 <4,7,5,0>, <7,0,1,2> + 3365823599U, // <5,0,7,1>: Cost 4 vmrglw <1,6,5,7>, <1,5,0,1> + 3808900317U, // <5,0,7,2>: Cost 4 vsldoi8 , <7,2,u,4> + 3784348899U, // <5,0,7,3>: Cost 4 vsldoi8 <4,3,5,0>, <7,3,0,1> + 2729186656U, // <5,0,7,4>: Cost 3 vsldoi8 <7,4,5,0>, <7,4,5,0> + 3787003268U, // <5,0,7,5>: Cost 4 vsldoi8 <4,7,5,0>, <7,5,0,0> + 3802928664U, // <5,0,7,6>: Cost 4 vsldoi8 <7,4,5,0>, <7,6,7,4> + 3787003431U, // <5,0,7,7>: Cost 4 vsldoi8 <4,7,5,0>, <7,7,0,1> + 2731841188U, // <5,0,7,u>: Cost 3 vsldoi8 <7,u,5,0>, <7,u,5,0> + 2626601062U, // <5,0,u,0>: Cost 3 vsldoi4 <1,5,0,u>, LHS + 1683145366U, // <5,0,u,1>: Cost 2 vsldoi12 <0,u,1,5>, <0,u,1,5> + 1680491165U, // <5,0,u,2>: Cost 2 vsldoi12 <0,4,1,5>, LHS + 2705295054U, // <5,0,u,3>: Cost 3 vsldoi8 <3,4,5,0>, <2,3,4,5> + 2754233005U, // <5,0,u,4>: Cost 3 vsldoi12 <0,4,1,5>, <0,u,4,1> + 2705299610U, // <5,0,u,5>: Cost 3 vsldoi8 <3,4,5,0>, RHS + 3779041488U, // <5,0,u,6>: Cost 4 vsldoi8 <3,4,5,0>, + 2737150252U, // <5,0,u,7>: Cost 3 vsldoi8 , + 1680491219U, // <5,0,u,u>: Cost 2 vsldoi12 <0,4,1,5>, LHS + 2713927680U, // <5,1,0,0>: Cost 3 vsldoi8 <4,u,5,1>, <0,0,0,0> + 1640185958U, // <5,1,0,1>: Cost 2 vsldoi8 <4,u,5,1>, LHS + 2310607866U, // <5,1,0,2>: Cost 3 vmrglw <4,7,5,0>, <7,0,1,2> + 3787669756U, // <5,1,0,3>: Cost 4 vsldoi8 <4,u,5,1>, <0,3,1,0> + 2713928018U, // <5,1,0,4>: Cost 3 vsldoi8 <4,u,5,1>, <0,4,1,5> + 2306621778U, // <5,1,0,5>: Cost 3 vmrglw <4,1,5,0>, <0,4,1,5> + 3787670006U, // <5,1,0,6>: Cost 4 vsldoi8 <4,u,5,1>, <0,6,1,7> + 3736188301U, // <5,1,0,7>: Cost 4 vsldoi4 <7,5,1,0>, <7,5,1,0> + 1640186525U, // <5,1,0,u>: Cost 2 vsldoi8 <4,u,5,1>, LHS + 2650505318U, // <5,1,1,0>: Cost 3 vsldoi4 <5,5,1,1>, LHS + 2754233140U, // <5,1,1,1>: Cost 3 vsldoi12 <0,4,1,5>, <1,1,1,1> + 2311276694U, // <5,1,1,2>: Cost 3 vmrglw <4,u,5,1>, <3,0,1,2> + 2311278315U, // <5,1,1,3>: Cost 3 vmrglw <4,u,5,1>, <5,2,1,3> + 2758435667U, // <5,1,1,4>: Cost 3 vsldoi12 <1,1,4,5>, <1,1,4,5> + 2754233180U, // <5,1,1,5>: Cost 3 vsldoi12 <0,4,1,5>, <1,1,5,5> + 3385016497U, // <5,1,1,6>: Cost 4 vmrglw <4,u,5,1>, <0,2,1,6> + 2311278643U, // <5,1,1,7>: Cost 3 vmrglw <4,u,5,1>, <5,6,1,7> + 2758730615U, // <5,1,1,u>: Cost 3 vsldoi12 <1,1,u,5>, <1,1,u,5> + 3700367462U, // <5,1,2,0>: Cost 4 vsldoi4 <1,5,1,2>, LHS + 3830629255U, // <5,1,2,1>: Cost 4 vsldoi12 <0,u,1,5>, <1,2,1,3> + 2713929320U, // <5,1,2,2>: Cost 3 vsldoi8 <4,u,5,1>, <2,2,2,2> + 2754233238U, // <5,1,2,3>: Cost 3 vsldoi12 <0,4,1,5>, <1,2,3,0> + 2759099300U, // <5,1,2,4>: Cost 3 vsldoi12 <1,2,4,5>, <1,2,4,5> + 2754233259U, // <5,1,2,5>: Cost 3 vsldoi12 <0,4,1,5>, <1,2,5,3> + 2713929658U, // <5,1,2,6>: Cost 3 vsldoi8 <4,u,5,1>, <2,6,3,7> + 3872359354U, // <5,1,2,7>: Cost 4 vsldoi12 <7,u,0,5>, <1,2,7,0> + 2754233283U, // <5,1,2,u>: Cost 3 vsldoi12 <0,4,1,5>, <1,2,u,0> + 2713929878U, // <5,1,3,0>: Cost 3 vsldoi8 <4,u,5,1>, <3,0,1,2> + 3363135498U, // <5,1,3,1>: Cost 4 vmrglw <1,2,5,3>, <0,0,1,1> + 3363137686U, // <5,1,3,2>: Cost 4 vmrglw <1,2,5,3>, <3,0,1,2> + 2713930140U, // <5,1,3,3>: Cost 3 vsldoi8 <4,u,5,1>, <3,3,3,3> + 2713930242U, // <5,1,3,4>: Cost 3 vsldoi8 <4,u,5,1>, <3,4,5,6> + 2289394002U, // <5,1,3,5>: Cost 3 vmrglw <1,2,5,3>, <0,4,1,5> + 3787672184U, // <5,1,3,6>: Cost 4 vsldoi8 <4,u,5,1>, <3,6,0,7> + 3787672259U, // <5,1,3,7>: Cost 4 vsldoi8 <4,u,5,1>, <3,7,0,1> + 2713930526U, // <5,1,3,u>: Cost 3 vsldoi8 <4,u,5,1>, <3,u,1,2> + 1634880402U, // <5,1,4,0>: Cost 2 vsldoi8 <4,0,5,1>, <4,0,5,1> + 2760205355U, // <5,1,4,1>: Cost 3 vsldoi12 <1,4,1,5>, <1,4,1,5> + 2760279092U, // <5,1,4,2>: Cost 3 vsldoi12 <1,4,2,5>, <1,4,2,5> + 3787672708U, // <5,1,4,3>: Cost 4 vsldoi8 <4,u,5,1>, <4,3,5,0> + 2713930960U, // <5,1,4,4>: Cost 3 vsldoi8 <4,u,5,1>, <4,4,4,4> + 1640189238U, // <5,1,4,5>: Cost 2 vsldoi8 <4,u,5,1>, RHS + 3786345848U, // <5,1,4,6>: Cost 4 vsldoi8 <4,6,5,1>, <4,6,5,1> + 3787009481U, // <5,1,4,7>: Cost 4 vsldoi8 <4,7,5,1>, <4,7,5,1> + 1640189466U, // <5,1,4,u>: Cost 2 vsldoi8 <4,u,5,1>, <4,u,5,1> + 2754233455U, // <5,1,5,0>: Cost 3 vsldoi12 <0,4,1,5>, <1,5,0,1> + 2713931407U, // <5,1,5,1>: Cost 3 vsldoi8 <4,u,5,1>, <5,1,0,1> + 2713931499U, // <5,1,5,2>: Cost 3 vsldoi8 <4,u,5,1>, <5,2,1,3> + 3827975305U, // <5,1,5,3>: Cost 4 vsldoi12 <0,4,1,5>, <1,5,3,0> + 2754233495U, // <5,1,5,4>: Cost 3 vsldoi12 <0,4,1,5>, <1,5,4,5> + 2288746834U, // <5,1,5,5>: Cost 3 vmrglw <1,1,5,5>, <0,4,1,5> + 2713931827U, // <5,1,5,6>: Cost 3 vsldoi8 <4,u,5,1>, <5,6,1,7> + 3787673725U, // <5,1,5,7>: Cost 4 vsldoi8 <4,u,5,1>, <5,7,1,0> + 2754233527U, // <5,1,5,u>: Cost 3 vsldoi12 <0,4,1,5>, <1,5,u,1> + 2668462182U, // <5,1,6,0>: Cost 3 vsldoi4 , LHS + 2290746002U, // <5,1,6,1>: Cost 3 vmrglw <1,4,5,6>, <0,u,1,1> + 2302691478U, // <5,1,6,2>: Cost 3 vmrglw <3,4,5,6>, <3,0,1,2> + 3364488071U, // <5,1,6,3>: Cost 4 vmrglw <1,4,5,6>, <1,2,1,3> + 2302689536U, // <5,1,6,4>: Cost 3 vmrglw <3,4,5,6>, <0,3,1,4> + 2754233587U, // <5,1,6,5>: Cost 3 vsldoi12 <0,4,1,5>, <1,6,5,7> + 2713932600U, // <5,1,6,6>: Cost 3 vsldoi8 <4,u,5,1>, <6,6,6,6> + 2713932622U, // <5,1,6,7>: Cost 3 vsldoi8 <4,u,5,1>, <6,7,0,1> + 2302689297U, // <5,1,6,u>: Cost 3 vmrglw <3,4,5,6>, <0,0,1,u> + 2713932794U, // <5,1,7,0>: Cost 3 vsldoi8 <4,u,5,1>, <7,0,1,2> + 3365822474U, // <5,1,7,1>: Cost 4 vmrglw <1,6,5,7>, <0,0,1,1> + 3365824662U, // <5,1,7,2>: Cost 4 vmrglw <1,6,5,7>, <3,0,1,2> + 3787674851U, // <5,1,7,3>: Cost 4 vsldoi8 <4,u,5,1>, <7,3,0,1> + 2713933158U, // <5,1,7,4>: Cost 3 vsldoi8 <4,u,5,1>, <7,4,5,6> + 2292080978U, // <5,1,7,5>: Cost 3 vmrglw <1,6,5,7>, <0,4,1,5> + 3365823613U, // <5,1,7,6>: Cost 4 vmrglw <1,6,5,7>, <1,5,1,6> + 2713933420U, // <5,1,7,7>: Cost 3 vsldoi8 <4,u,5,1>, <7,7,7,7> + 2713933442U, // <5,1,7,u>: Cost 3 vsldoi8 <4,u,5,1>, <7,u,1,2> + 1658771190U, // <5,1,u,0>: Cost 2 vsldoi8 , + 1640191790U, // <5,1,u,1>: Cost 2 vsldoi8 <4,u,5,1>, LHS + 2762933624U, // <5,1,u,2>: Cost 3 vsldoi12 <1,u,2,5>, <1,u,2,5> + 2754233724U, // <5,1,u,3>: Cost 3 vsldoi12 <0,4,1,5>, <1,u,3,0> + 2763081098U, // <5,1,u,4>: Cost 3 vsldoi12 <1,u,4,5>, <1,u,4,5> + 1640192154U, // <5,1,u,5>: Cost 2 vsldoi8 <4,u,5,1>, RHS + 2713934032U, // <5,1,u,6>: Cost 3 vsldoi8 <4,u,5,1>, + 2713934080U, // <5,1,u,7>: Cost 3 vsldoi8 <4,u,5,1>, + 1640192357U, // <5,1,u,u>: Cost 2 vsldoi8 <4,u,5,1>, LHS + 3779051520U, // <5,2,0,0>: Cost 4 vsldoi8 <3,4,5,2>, <0,0,0,0> + 2705309798U, // <5,2,0,1>: Cost 3 vsldoi8 <3,4,5,2>, LHS + 3838813637U, // <5,2,0,2>: Cost 4 vsldoi12 <2,2,4,5>, <2,0,2,1> + 2302640230U, // <5,2,0,3>: Cost 3 vmrglw <3,4,5,0>, LHS + 3765117266U, // <5,2,0,4>: Cost 4 vsldoi8 <1,1,5,2>, <0,4,1,5> + 3381027892U, // <5,2,0,5>: Cost 4 vmrglw <4,2,5,0>, <1,4,2,5> + 3842794985U, // <5,2,0,6>: Cost 4 vsldoi12 <2,u,4,5>, <2,0,6,1> + 3408232554U, // <5,2,0,7>: Cost 4 vmrglw , <0,1,2,7> + 2302640235U, // <5,2,0,u>: Cost 3 vmrglw <3,4,5,0>, LHS + 3700432998U, // <5,2,1,0>: Cost 4 vsldoi4 <1,5,2,1>, LHS + 3765117785U, // <5,2,1,1>: Cost 4 vsldoi8 <1,1,5,2>, <1,1,5,2> + 2311276136U, // <5,2,1,2>: Cost 3 vmrglw <4,u,5,1>, <2,2,2,2> + 1237532774U, // <5,2,1,3>: Cost 2 vmrglw <4,u,5,1>, LHS + 3700436278U, // <5,2,1,4>: Cost 4 vsldoi4 <1,5,2,1>, RHS + 3381036084U, // <5,2,1,5>: Cost 4 vmrglw <4,2,5,1>, <1,4,2,5> + 3385018045U, // <5,2,1,6>: Cost 4 vmrglw <4,u,5,1>, <2,3,2,6> + 3385017560U, // <5,2,1,7>: Cost 4 vmrglw <4,u,5,1>, <1,6,2,7> + 1237532779U, // <5,2,1,u>: Cost 2 vmrglw <4,u,5,1>, LHS + 3700441190U, // <5,2,2,0>: Cost 4 vsldoi4 <1,5,2,2>, LHS + 3700442242U, // <5,2,2,1>: Cost 4 vsldoi4 <1,5,2,2>, <1,5,2,2> + 2754233960U, // <5,2,2,2>: Cost 3 vsldoi12 <0,4,1,5>, <2,2,2,2> + 2754233970U, // <5,2,2,3>: Cost 3 vsldoi12 <0,4,1,5>, <2,2,3,3> + 2765071997U, // <5,2,2,4>: Cost 3 vsldoi12 <2,2,4,5>, <2,2,4,5> + 3834021508U, // <5,2,2,5>: Cost 4 vsldoi12 <1,4,2,5>, <2,2,5,3> + 3842795152U, // <5,2,2,6>: Cost 4 vsldoi12 <2,u,4,5>, <2,2,6,6> + 3376402492U, // <5,2,2,7>: Cost 4 vmrglw <3,4,5,2>, <5,6,2,7> + 2754234015U, // <5,2,2,u>: Cost 3 vsldoi12 <0,4,1,5>, <2,2,u,3> + 2754234022U, // <5,2,3,0>: Cost 3 vsldoi12 <0,4,1,5>, <2,3,0,1> + 3827975855U, // <5,2,3,1>: Cost 4 vsldoi12 <0,4,1,5>, <2,3,1,1> + 2644625102U, // <5,2,3,2>: Cost 3 vsldoi4 <4,5,2,3>, <2,3,4,5> + 2289393766U, // <5,2,3,3>: Cost 3 vmrglw <1,2,5,3>, LHS + 1691993806U, // <5,2,3,4>: Cost 2 vsldoi12 <2,3,4,5>, <2,3,4,5> + 2785052375U, // <5,2,3,5>: Cost 3 vsldoi12 <5,5,5,5>, <2,3,5,5> + 3854812897U, // <5,2,3,6>: Cost 4 vsldoi12 <4,u,5,5>, <2,3,6,6> + 3802942187U, // <5,2,3,7>: Cost 4 vsldoi8 <7,4,5,2>, <3,7,4,5> + 1692288754U, // <5,2,3,u>: Cost 2 vsldoi12 <2,3,u,5>, <2,3,u,5> + 3839846139U, // <5,2,4,0>: Cost 4 vsldoi12 <2,4,0,5>, <2,4,0,5> + 2709294052U, // <5,2,4,1>: Cost 3 vsldoi8 <4,1,5,2>, <4,1,5,2> + 2766251789U, // <5,2,4,2>: Cost 3 vsldoi12 <2,4,2,5>, <2,4,2,5> + 2765735702U, // <5,2,4,3>: Cost 3 vsldoi12 <2,3,4,5>, <2,4,3,5> + 3840141087U, // <5,2,4,4>: Cost 4 vsldoi12 <2,4,4,5>, <2,4,4,5> + 2705313078U, // <5,2,4,5>: Cost 3 vsldoi8 <3,4,5,2>, RHS + 2712612217U, // <5,2,4,6>: Cost 3 vsldoi8 <4,6,5,2>, <4,6,5,2> + 3787017674U, // <5,2,4,7>: Cost 4 vsldoi8 <4,7,5,2>, <4,7,5,2> + 2765735747U, // <5,2,4,u>: Cost 3 vsldoi12 <2,3,4,5>, <2,4,u,5> + 3834021704U, // <5,2,5,0>: Cost 4 vsldoi12 <1,4,2,5>, <2,5,0,1> + 3834021714U, // <5,2,5,1>: Cost 4 vsldoi12 <1,4,2,5>, <2,5,1,2> + 2311308904U, // <5,2,5,2>: Cost 3 vmrglw <4,u,5,5>, <2,2,2,2> + 1237565542U, // <5,2,5,3>: Cost 2 vmrglw <4,u,5,5>, LHS + 3834021744U, // <5,2,5,4>: Cost 4 vsldoi12 <1,4,2,5>, <2,5,4,5> + 3369124916U, // <5,2,5,5>: Cost 4 vmrglw <2,2,5,5>, <1,4,2,5> + 2248181690U, // <5,2,5,6>: Cost 3 vmrghw <5,5,5,5>, <2,6,3,7> + 3786354825U, // <5,2,5,7>: Cost 4 vsldoi8 <4,6,5,2>, <5,7,2,3> + 1237565547U, // <5,2,5,u>: Cost 2 vmrglw <4,u,5,5>, LHS + 3700473958U, // <5,2,6,0>: Cost 4 vsldoi4 <1,5,2,6>, LHS + 3700475014U, // <5,2,6,1>: Cost 4 vsldoi4 <1,5,2,6>, <1,5,2,6> + 2296718952U, // <5,2,6,2>: Cost 3 vmrglw <2,4,5,6>, <2,2,2,2> + 1228947558U, // <5,2,6,3>: Cost 2 vmrglw <3,4,5,6>, LHS + 3700477238U, // <5,2,6,4>: Cost 4 vsldoi4 <1,5,2,6>, RHS + 3834021836U, // <5,2,6,5>: Cost 4 vsldoi12 <1,4,2,5>, <2,6,5,7> + 2248951738U, // <5,2,6,6>: Cost 3 vmrghw <5,6,7,0>, <2,6,3,7> + 3370461105U, // <5,2,6,7>: Cost 4 vmrglw <2,4,5,6>, <2,6,2,7> + 1228947563U, // <5,2,6,u>: Cost 2 vmrglw <3,4,5,6>, LHS + 3786355706U, // <5,2,7,0>: Cost 4 vsldoi8 <4,6,5,2>, <7,0,1,2> + 3783038037U, // <5,2,7,1>: Cost 4 vsldoi8 <4,1,5,2>, <7,1,2,3> + 3365824104U, // <5,2,7,2>: Cost 4 vmrglw <1,6,5,7>, <2,2,2,2> + 2292080742U, // <5,2,7,3>: Cost 3 vmrglw <1,6,5,7>, LHS + 3842131986U, // <5,2,7,4>: Cost 4 vsldoi12 <2,7,4,5>, <2,7,4,5> + 3371795508U, // <5,2,7,5>: Cost 4 vmrglw <2,6,5,7>, <1,4,2,5> + 3786356206U, // <5,2,7,6>: Cost 4 vsldoi8 <4,6,5,2>, <7,6,2,7> + 3786356332U, // <5,2,7,7>: Cost 4 vsldoi8 <4,6,5,2>, <7,7,7,7> + 2292080747U, // <5,2,7,u>: Cost 3 vmrglw <1,6,5,7>, LHS + 2754234427U, // <5,2,u,0>: Cost 3 vsldoi12 <0,4,1,5>, <2,u,0,1> + 2705315630U, // <5,2,u,1>: Cost 3 vsldoi8 <3,4,5,2>, LHS + 2296735336U, // <5,2,u,2>: Cost 3 vmrglw <2,4,5,u>, <2,2,2,2> + 1228963942U, // <5,2,u,3>: Cost 2 vmrglw <3,4,5,u>, LHS + 1695311971U, // <5,2,u,4>: Cost 2 vsldoi12 <2,u,4,5>, <2,u,4,5> + 2705315994U, // <5,2,u,5>: Cost 3 vsldoi8 <3,4,5,2>, RHS + 2769201269U, // <5,2,u,6>: Cost 3 vsldoi12 <2,u,6,5>, <2,u,6,5> + 3370477489U, // <5,2,u,7>: Cost 4 vmrglw <2,4,5,u>, <2,6,2,7> + 1695606919U, // <5,2,u,u>: Cost 2 vsldoi12 <2,u,u,5>, <2,u,u,5> + 3827976331U, // <5,3,0,0>: Cost 4 vsldoi12 <0,4,1,5>, <3,0,0,0> + 2754234518U, // <5,3,0,1>: Cost 3 vsldoi12 <0,4,1,5>, <3,0,1,2> + 3706472290U, // <5,3,0,2>: Cost 4 vsldoi4 <2,5,3,0>, <2,5,3,0> + 3700500630U, // <5,3,0,3>: Cost 4 vsldoi4 <1,5,3,0>, <3,0,1,2> + 2754234544U, // <5,3,0,4>: Cost 3 vsldoi12 <0,4,1,5>, <3,0,4,1> + 3376383766U, // <5,3,0,5>: Cost 4 vmrglw <3,4,5,0>, <2,4,3,5> + 3769770513U, // <5,3,0,6>: Cost 5 vsldoi8 <1,u,5,3>, <0,6,4,7> + 3376383930U, // <5,3,0,7>: Cost 4 vmrglw <3,4,5,0>, <2,6,3,7> + 2754234581U, // <5,3,0,u>: Cost 3 vsldoi12 <0,4,1,5>, <3,0,u,2> + 2311275414U, // <5,3,1,0>: Cost 3 vmrglw <4,u,5,1>, <1,2,3,0> + 2305967971U, // <5,3,1,1>: Cost 3 vmrglw <4,0,5,1>, <2,5,3,1> + 2692047787U, // <5,3,1,2>: Cost 3 vsldoi8 <1,2,5,3>, <1,2,5,3> + 2311276146U, // <5,3,1,3>: Cost 3 vmrglw <4,u,5,1>, <2,2,3,3> + 2311275418U, // <5,3,1,4>: Cost 3 vmrglw <4,u,5,1>, <1,2,3,4> + 3765789807U, // <5,3,1,5>: Cost 4 vsldoi8 <1,2,5,3>, <1,5,0,1> + 3765789939U, // <5,3,1,6>: Cost 4 vsldoi8 <1,2,5,3>, <1,6,5,7> + 2311276474U, // <5,3,1,7>: Cost 3 vmrglw <4,u,5,1>, <2,6,3,7> + 2696029585U, // <5,3,1,u>: Cost 3 vsldoi8 <1,u,5,3>, <1,u,5,3> + 2311288709U, // <5,3,2,0>: Cost 3 vmrglw <4,u,5,2>, + 3765790243U, // <5,3,2,1>: Cost 4 vsldoi8 <1,2,5,3>, <2,1,3,5> + 3827976513U, // <5,3,2,2>: Cost 4 vsldoi12 <0,4,1,5>, <3,2,2,2> + 2765736268U, // <5,3,2,3>: Cost 3 vsldoi12 <2,3,4,5>, <3,2,3,4> + 2246248962U, // <5,3,2,4>: Cost 3 vmrghw <5,2,6,3>, <3,4,5,6> + 3765790563U, // <5,3,2,5>: Cost 4 vsldoi8 <1,2,5,3>, <2,5,3,1> + 3827976550U, // <5,3,2,6>: Cost 4 vsldoi12 <0,4,1,5>, <3,2,6,3> + 3842795887U, // <5,3,2,7>: Cost 4 vsldoi12 <2,u,4,5>, <3,2,7,3> + 2769054073U, // <5,3,2,u>: Cost 3 vsldoi12 <2,u,4,5>, <3,2,u,4> + 3827976575U, // <5,3,3,0>: Cost 4 vsldoi12 <0,4,1,5>, <3,3,0,1> + 3765790963U, // <5,3,3,1>: Cost 4 vsldoi8 <1,2,5,3>, <3,1,2,5> + 3839478162U, // <5,3,3,2>: Cost 4 vsldoi12 <2,3,4,5>, <3,3,2,2> + 2754234780U, // <5,3,3,3>: Cost 3 vsldoi12 <0,4,1,5>, <3,3,3,3> + 2771708327U, // <5,3,3,4>: Cost 3 vsldoi12 <3,3,4,5>, <3,3,4,5> + 3363137059U, // <5,3,3,5>: Cost 4 vmrglw <1,2,5,3>, <2,1,3,5> + 3375081320U, // <5,3,3,6>: Cost 4 vmrglw <3,2,5,3>, <2,5,3,6> + 3363137466U, // <5,3,3,7>: Cost 4 vmrglw <1,2,5,3>, <2,6,3,7> + 2772003275U, // <5,3,3,u>: Cost 3 vsldoi12 <3,3,u,5>, <3,3,u,5> + 2772077012U, // <5,3,4,0>: Cost 3 vsldoi12 <3,4,0,5>, <3,4,0,5> + 3765791714U, // <5,3,4,1>: Cost 4 vsldoi8 <1,2,5,3>, <4,1,5,0> + 2709965878U, // <5,3,4,2>: Cost 3 vsldoi8 <4,2,5,3>, <4,2,5,3> + 2772298223U, // <5,3,4,3>: Cost 3 vsldoi12 <3,4,3,5>, <3,4,3,5> + 2772371960U, // <5,3,4,4>: Cost 3 vsldoi12 <3,4,4,5>, <3,4,4,5> + 2754234882U, // <5,3,4,5>: Cost 3 vsldoi12 <0,4,1,5>, <3,4,5,6> + 3839478282U, // <5,3,4,6>: Cost 4 vsldoi12 <2,3,4,5>, <3,4,6,5> + 3376416698U, // <5,3,4,7>: Cost 4 vmrglw <3,4,5,4>, <2,6,3,7> + 2754234909U, // <5,3,4,u>: Cost 3 vsldoi12 <0,4,1,5>, <3,4,u,6> + 2311308182U, // <5,3,5,0>: Cost 3 vmrglw <4,u,5,5>, <1,2,3,0> + 3765792421U, // <5,3,5,1>: Cost 4 vsldoi8 <1,2,5,3>, <5,1,2,5> + 2715938575U, // <5,3,5,2>: Cost 3 vsldoi8 <5,2,5,3>, <5,2,5,3> + 2311308914U, // <5,3,5,3>: Cost 3 vmrglw <4,u,5,5>, <2,2,3,3> + 2311308186U, // <5,3,5,4>: Cost 3 vmrglw <4,u,5,5>, <1,2,3,4> + 2248182354U, // <5,3,5,5>: Cost 3 vmrghw <5,5,5,5>, <3,5,5,5> + 3765792837U, // <5,3,5,6>: Cost 4 vsldoi8 <1,2,5,3>, <5,6,3,7> + 2311309242U, // <5,3,5,7>: Cost 3 vmrglw <4,u,5,5>, <2,6,3,7> + 2311308190U, // <5,3,5,u>: Cost 3 vmrglw <4,u,5,5>, <1,2,3,u> + 2632777830U, // <5,3,6,0>: Cost 3 vsldoi4 <2,5,3,6>, LHS + 3706520372U, // <5,3,6,1>: Cost 4 vsldoi4 <2,5,3,6>, <1,1,1,1> + 2632779624U, // <5,3,6,2>: Cost 3 vsldoi4 <2,5,3,6>, <2,5,3,6> + 2632780290U, // <5,3,6,3>: Cost 3 vsldoi4 <2,5,3,6>, <3,4,5,6> + 2632781110U, // <5,3,6,4>: Cost 3 vsldoi4 <2,5,3,6>, RHS + 2248952413U, // <5,3,6,5>: Cost 3 vmrghw <5,6,7,0>, <3,5,6,7> + 2302691176U, // <5,3,6,6>: Cost 3 vmrglw <3,4,5,6>, <2,5,3,6> + 2302691258U, // <5,3,6,7>: Cost 3 vmrglw <3,4,5,6>, <2,6,3,7> + 2632783662U, // <5,3,6,u>: Cost 3 vsldoi4 <2,5,3,6>, LHS + 3365823382U, // <5,3,7,0>: Cost 4 vmrglw <1,6,5,7>, <1,2,3,0> + 3706529011U, // <5,3,7,1>: Cost 4 vsldoi4 <2,5,3,7>, <1,6,5,7> + 3706529641U, // <5,3,7,2>: Cost 4 vsldoi4 <2,5,3,7>, <2,5,3,7> + 3365824114U, // <5,3,7,3>: Cost 4 vmrglw <1,6,5,7>, <2,2,3,3> + 2774362859U, // <5,3,7,4>: Cost 3 vsldoi12 <3,7,4,5>, <3,7,4,5> + 3365824035U, // <5,3,7,5>: Cost 4 vmrglw <1,6,5,7>, <2,1,3,5> + 3383740183U, // <5,3,7,6>: Cost 4 vmrglw <4,6,5,7>, <2,4,3,6> + 3363833786U, // <5,3,7,7>: Cost 4 vmrglw <1,3,5,7>, <2,6,3,7> + 2774657807U, // <5,3,7,u>: Cost 3 vsldoi12 <3,7,u,5>, <3,7,u,5> + 2632794214U, // <5,3,u,0>: Cost 3 vsldoi4 <2,5,3,u>, LHS + 2754235166U, // <5,3,u,1>: Cost 3 vsldoi12 <0,4,1,5>, <3,u,1,2> + 2632796010U, // <5,3,u,2>: Cost 3 vsldoi4 <2,5,3,u>, <2,5,3,u> + 2632796676U, // <5,3,u,3>: Cost 3 vsldoi4 <2,5,3,u>, <3,4,5,u> + 2632797494U, // <5,3,u,4>: Cost 3 vsldoi4 <2,5,3,u>, RHS + 2754235206U, // <5,3,u,5>: Cost 3 vsldoi12 <0,4,1,5>, <3,u,5,6> + 2302691176U, // <5,3,u,6>: Cost 3 vmrglw <3,4,5,6>, <2,5,3,6> + 2302707642U, // <5,3,u,7>: Cost 3 vmrglw <3,4,5,u>, <2,6,3,7> + 2754235229U, // <5,3,u,u>: Cost 3 vsldoi12 <0,4,1,5>, <3,u,u,2> + 3765133325U, // <5,4,0,0>: Cost 4 vsldoi8 <1,1,5,4>, <0,0,1,4> + 2705326182U, // <5,4,0,1>: Cost 3 vsldoi8 <3,4,5,4>, LHS + 3718489806U, // <5,4,0,2>: Cost 4 vsldoi4 <4,5,4,0>, <2,3,4,5> + 3718490624U, // <5,4,0,3>: Cost 4 vsldoi4 <4,5,4,0>, <3,4,5,4> + 2709307730U, // <5,4,0,4>: Cost 3 vsldoi8 <4,1,5,4>, <0,4,1,5> + 2302641870U, // <5,4,0,5>: Cost 3 vmrglw <3,4,5,0>, <2,3,4,5> + 3376383695U, // <5,4,0,6>: Cost 5 vmrglw <3,4,5,0>, <2,3,4,6> + 3384351018U, // <5,4,0,7>: Cost 4 vmrglw <4,7,5,0>, + 2705326749U, // <5,4,0,u>: Cost 3 vsldoi8 <3,4,5,4>, LHS + 2305971057U, // <5,4,1,0>: Cost 3 vmrglw <4,0,5,1>, <6,7,4,0> + 3765134171U, // <5,4,1,1>: Cost 4 vsldoi8 <1,1,5,4>, <1,1,5,4> + 3766461338U, // <5,4,1,2>: Cost 4 vsldoi8 <1,3,5,4>, <1,2,3,4> + 3766461437U, // <5,4,1,3>: Cost 4 vsldoi8 <1,3,5,4>, <1,3,5,4> + 2311277776U, // <5,4,1,4>: Cost 3 vmrglw <4,u,5,1>, <4,4,4,4> + 2754235362U, // <5,4,1,5>: Cost 3 vsldoi12 <0,4,1,5>, <4,1,5,0> + 3783050483U, // <5,4,1,6>: Cost 4 vsldoi8 <4,1,5,4>, <1,6,5,7> + 3385019036U, // <5,4,1,7>: Cost 4 vmrglw <4,u,5,1>, <3,6,4,7> + 2311276241U, // <5,4,1,u>: Cost 3 vmrglw <4,u,5,1>, <2,3,4,u> + 3718504550U, // <5,4,2,0>: Cost 4 vsldoi4 <4,5,4,2>, LHS + 3783050787U, // <5,4,2,1>: Cost 4 vsldoi8 <4,1,5,4>, <2,1,3,5> + 3773097576U, // <5,4,2,2>: Cost 4 vsldoi8 <2,4,5,4>, <2,2,2,2> + 2705327822U, // <5,4,2,3>: Cost 3 vsldoi8 <3,4,5,4>, <2,3,4,5> + 3773097767U, // <5,4,2,4>: Cost 4 vsldoi8 <2,4,5,4>, <2,4,5,4> + 2765737014U, // <5,4,2,5>: Cost 3 vsldoi12 <2,3,4,5>, <4,2,5,3> + 3779069882U, // <5,4,2,6>: Cost 4 vsldoi8 <3,4,5,4>, <2,6,3,7> + 3376401052U, // <5,4,2,7>: Cost 5 vmrglw <3,4,5,2>, <3,6,4,7> + 2245881370U, // <5,4,2,u>: Cost 3 vmrghw <5,2,1,3>, <4,u,5,1> + 3779070102U, // <5,4,3,0>: Cost 4 vsldoi8 <3,4,5,4>, <3,0,1,2> + 3363135525U, // <5,4,3,1>: Cost 4 vmrglw <1,2,5,3>, <0,0,4,1> + 3779070284U, // <5,4,3,2>: Cost 4 vsldoi8 <3,4,5,4>, <3,2,3,4> + 3779070364U, // <5,4,3,3>: Cost 4 vsldoi8 <3,4,5,4>, <3,3,3,3> + 2705328640U, // <5,4,3,4>: Cost 3 vsldoi8 <3,4,5,4>, <3,4,5,4> + 2307311310U, // <5,4,3,5>: Cost 3 vmrglw <4,2,5,3>, <2,3,4,5> + 3866021012U, // <5,4,3,6>: Cost 4 vsldoi12 <6,7,4,5>, <4,3,6,7> + 3363138204U, // <5,4,3,7>: Cost 5 vmrglw <1,2,5,3>, <3,6,4,7> + 2707983172U, // <5,4,3,u>: Cost 3 vsldoi8 <3,u,5,4>, <3,u,5,4> + 2708646805U, // <5,4,4,0>: Cost 3 vsldoi8 <4,0,5,4>, <4,0,5,4> + 2709310438U, // <5,4,4,1>: Cost 3 vsldoi8 <4,1,5,4>, <4,1,5,4> + 3779071030U, // <5,4,4,2>: Cost 4 vsldoi8 <3,4,5,4>, <4,2,5,3> + 2710637704U, // <5,4,4,3>: Cost 3 vsldoi8 <4,3,5,4>, <4,3,5,4> + 2754235600U, // <5,4,4,4>: Cost 3 vsldoi12 <0,4,1,5>, <4,4,4,4> + 1704676570U, // <5,4,4,5>: Cost 2 vsldoi12 <4,4,5,5>, <4,4,5,5> + 3779071358U, // <5,4,4,6>: Cost 4 vsldoi8 <3,4,5,4>, <4,6,5,7> + 2713292236U, // <5,4,4,7>: Cost 3 vsldoi8 <4,7,5,4>, <4,7,5,4> + 1704897781U, // <5,4,4,u>: Cost 2 vsldoi12 <4,4,u,5>, <4,4,u,5> + 2626871398U, // <5,4,5,0>: Cost 3 vsldoi4 <1,5,4,5>, LHS + 2626872471U, // <5,4,5,1>: Cost 3 vsldoi4 <1,5,4,5>, <1,5,4,5> + 2765737230U, // <5,4,5,2>: Cost 3 vsldoi12 <2,3,4,5>, <4,5,2,3> + 3700615318U, // <5,4,5,3>: Cost 4 vsldoi4 <1,5,4,5>, <3,0,1,2> + 2626874678U, // <5,4,5,4>: Cost 3 vsldoi4 <1,5,4,5>, RHS + 1174441270U, // <5,4,5,5>: Cost 2 vmrghw <5,5,5,5>, RHS + 1680493878U, // <5,4,5,6>: Cost 2 vsldoi12 <0,4,1,5>, RHS + 3385051804U, // <5,4,5,7>: Cost 4 vmrglw <4,u,5,5>, <3,6,4,7> + 1680493896U, // <5,4,5,u>: Cost 2 vsldoi12 <0,4,1,5>, RHS + 2248952722U, // <5,4,6,0>: Cost 3 vmrghw <5,6,7,0>, <4,0,5,1> + 2302692152U, // <5,4,6,1>: Cost 3 vmrglw <3,4,5,6>, <3,u,4,1> + 3382406107U, // <5,4,6,2>: Cost 4 vmrglw <4,4,5,6>, <4,1,4,2> + 3700623874U, // <5,4,6,3>: Cost 4 vsldoi4 <1,5,4,6>, <3,4,5,6> + 2248953040U, // <5,4,6,4>: Cost 3 vmrghw <5,6,7,0>, <4,4,4,4> + 1175211318U, // <5,4,6,5>: Cost 2 vmrghw <5,6,7,0>, RHS + 3376432280U, // <5,4,6,6>: Cost 4 vmrglw <3,4,5,6>, <1,5,4,6> + 2729218934U, // <5,4,6,7>: Cost 3 vsldoi8 <7,4,5,4>, <6,7,4,5> + 1175211561U, // <5,4,6,u>: Cost 2 vmrghw <5,6,7,0>, RHS + 3787035642U, // <5,4,7,0>: Cost 4 vsldoi8 <4,7,5,4>, <7,0,1,2> + 3365822501U, // <5,4,7,1>: Cost 4 vmrglw <1,6,5,7>, <0,0,4,1> + 3808933085U, // <5,4,7,2>: Cost 4 vsldoi8 , <7,2,u,4> + 3784381707U, // <5,4,7,3>: Cost 4 vsldoi8 <4,3,5,4>, <7,3,4,5> + 2713294182U, // <5,4,7,4>: Cost 3 vsldoi8 <4,7,5,4>, <7,4,5,6> + 2309998286U, // <5,4,7,5>: Cost 3 vmrglw <4,6,5,7>, <2,3,4,5> + 3383740111U, // <5,4,7,6>: Cost 4 vmrglw <4,6,5,7>, <2,3,4,6> + 3787036239U, // <5,4,7,7>: Cost 4 vsldoi8 <4,7,5,4>, <7,7,4,5> + 2731873960U, // <5,4,7,u>: Cost 3 vsldoi8 <7,u,5,4>, <7,u,5,4> + 2626895974U, // <5,4,u,0>: Cost 3 vsldoi4 <1,5,4,u>, LHS + 2626897050U, // <5,4,u,1>: Cost 3 vsldoi4 <1,5,4,u>, <1,5,4,u> + 2644813518U, // <5,4,u,2>: Cost 3 vsldoi4 <4,5,4,u>, <2,3,4,5> + 2705327822U, // <5,4,u,3>: Cost 3 vsldoi8 <3,4,5,4>, <2,3,4,5> + 2626899254U, // <5,4,u,4>: Cost 3 vsldoi4 <1,5,4,u>, RHS + 1707331102U, // <5,4,u,5>: Cost 2 vsldoi12 <4,u,5,5>, <4,u,5,5> + 1680494121U, // <5,4,u,6>: Cost 2 vsldoi12 <0,4,1,5>, RHS + 2737183024U, // <5,4,u,7>: Cost 3 vsldoi8 , + 1680494139U, // <5,4,u,u>: Cost 2 vsldoi12 <0,4,1,5>, RHS + 2302642684U, // <5,5,0,0>: Cost 3 vmrglw <3,4,5,0>, <3,4,5,0> + 1640218726U, // <5,5,0,1>: Cost 2 vsldoi8 <4,u,5,5>, LHS + 3376384510U, // <5,5,0,2>: Cost 4 vmrglw <3,4,5,0>, <3,4,5,2> + 3376385078U, // <5,5,0,3>: Cost 4 vmrglw <3,4,5,0>, <4,2,5,3> + 2754236002U, // <5,5,0,4>: Cost 3 vsldoi12 <0,4,1,5>, <5,0,4,1> + 2717942242U, // <5,5,0,5>: Cost 3 vsldoi8 <5,5,5,5>, <0,5,u,5> + 2244907106U, // <5,5,0,6>: Cost 3 vmrghw <5,0,6,1>, <5,6,7,0> + 3376385406U, // <5,5,0,7>: Cost 4 vmrglw <3,4,5,0>, <4,6,5,7> + 1640219293U, // <5,5,0,u>: Cost 2 vsldoi8 <4,u,5,5>, LHS + 2305969365U, // <5,5,1,0>: Cost 3 vmrglw <4,0,5,1>, <4,4,5,0> + 1237536282U, // <5,5,1,1>: Cost 2 vmrglw <4,u,5,1>, <4,u,5,1> + 2713961366U, // <5,5,1,2>: Cost 3 vsldoi8 <4,u,5,5>, <1,2,3,0> + 3766469630U, // <5,5,1,3>: Cost 4 vsldoi8 <1,3,5,5>, <1,3,5,5> + 2782326455U, // <5,5,1,4>: Cost 3 vsldoi12 <5,1,4,5>, <5,1,4,5> + 2311277786U, // <5,5,1,5>: Cost 3 vmrglw <4,u,5,1>, <4,4,5,5> + 2311277058U, // <5,5,1,6>: Cost 3 vmrglw <4,u,5,1>, <3,4,5,6> + 3385017587U, // <5,5,1,7>: Cost 4 vmrglw <4,u,5,1>, <1,6,5,7> + 1237536282U, // <5,5,1,u>: Cost 2 vmrglw <4,u,5,1>, <4,u,5,1> + 3376400892U, // <5,5,2,0>: Cost 4 vmrglw <3,4,5,2>, <3,4,5,0> + 3827977963U, // <5,5,2,1>: Cost 4 vsldoi12 <0,4,1,5>, <5,2,1,3> + 2302659070U, // <5,5,2,2>: Cost 3 vmrglw <3,4,5,2>, <3,4,5,2> + 2765737726U, // <5,5,2,3>: Cost 3 vsldoi12 <2,3,4,5>, <5,2,3,4> + 3839479558U, // <5,5,2,4>: Cost 4 vsldoi12 <2,3,4,5>, <5,2,4,3> + 2781073167U, // <5,5,2,5>: Cost 3 vsldoi12 <4,u,5,5>, <5,2,5,3> + 2713962426U, // <5,5,2,6>: Cost 3 vsldoi8 <4,u,5,5>, <2,6,3,7> + 3376401790U, // <5,5,2,7>: Cost 4 vmrglw <3,4,5,2>, <4,6,5,7> + 2769055531U, // <5,5,2,u>: Cost 3 vsldoi12 <2,u,4,5>, <5,2,u,4> + 2713962646U, // <5,5,3,0>: Cost 3 vsldoi8 <4,u,5,5>, <3,0,1,2> + 3765143786U, // <5,5,3,1>: Cost 4 vsldoi8 <1,1,5,5>, <3,1,1,5> + 3839479621U, // <5,5,3,2>: Cost 4 vsldoi12 <2,3,4,5>, <5,3,2,3> + 2289394603U, // <5,5,3,3>: Cost 3 vmrglw <1,2,5,3>, <1,2,5,3> + 2713963010U, // <5,5,3,4>: Cost 3 vsldoi8 <4,u,5,5>, <3,4,5,6> + 2313285150U, // <5,5,3,5>: Cost 3 vmrglw <5,2,5,3>, <4,u,5,5> + 3363138050U, // <5,5,3,6>: Cost 4 vmrglw <1,2,5,3>, <3,4,5,6> + 3363136755U, // <5,5,3,7>: Cost 4 vmrglw <1,2,5,3>, <1,6,5,7> + 2713963294U, // <5,5,3,u>: Cost 3 vsldoi8 <4,u,5,5>, <3,u,1,2> + 2713963410U, // <5,5,4,0>: Cost 3 vsldoi8 <4,u,5,5>, <4,0,5,1> + 3827978127U, // <5,5,4,1>: Cost 4 vsldoi12 <0,4,1,5>, <5,4,1,5> + 3839479704U, // <5,5,4,2>: Cost 4 vsldoi12 <2,3,4,5>, <5,4,2,5> + 3376417846U, // <5,5,4,3>: Cost 4 vmrglw <3,4,5,4>, <4,2,5,3> + 1637567706U, // <5,5,4,4>: Cost 2 vsldoi8 <4,4,5,5>, <4,4,5,5> + 1640222006U, // <5,5,4,5>: Cost 2 vsldoi8 <4,u,5,5>, RHS + 2310640998U, // <5,5,4,6>: Cost 3 vmrglw <4,7,5,4>, <7,4,5,6> + 3376418174U, // <5,5,4,7>: Cost 4 vmrglw <3,4,5,4>, <4,6,5,7> + 1640222238U, // <5,5,4,u>: Cost 2 vsldoi8 <4,u,5,5>, <4,u,5,5> + 1577091174U, // <5,5,5,0>: Cost 2 vsldoi4 <5,5,5,5>, LHS + 2311310226U, // <5,5,5,1>: Cost 3 vmrglw <4,u,5,5>, <4,0,5,1> + 2713964303U, // <5,5,5,2>: Cost 3 vsldoi8 <4,u,5,5>, <5,2,5,3> + 2311311119U, // <5,5,5,3>: Cost 3 vmrglw <4,u,5,5>, <5,2,5,3> + 1577094454U, // <5,5,5,4>: Cost 2 vsldoi4 <5,5,5,5>, RHS + 296144182U, // <5,5,5,5>: Cost 1 vspltisw1 RHS + 2311309826U, // <5,5,5,6>: Cost 3 vmrglw <4,u,5,5>, <3,4,5,6> + 2311311447U, // <5,5,5,7>: Cost 3 vmrglw <4,u,5,5>, <5,6,5,7> + 296144182U, // <5,5,5,u>: Cost 1 vspltisw1 RHS + 2248953460U, // <5,5,6,0>: Cost 3 vmrghw <5,6,7,0>, <5,0,6,1> + 2326580114U, // <5,5,6,1>: Cost 3 vmrglw <7,4,5,6>, <4,0,5,1> + 2713965050U, // <5,5,6,2>: Cost 3 vsldoi8 <4,u,5,5>, <6,2,7,3> + 3700697602U, // <5,5,6,3>: Cost 4 vsldoi4 <1,5,5,6>, <3,4,5,6> + 2785644620U, // <5,5,6,4>: Cost 3 vsldoi12 <5,6,4,5>, <5,6,4,5> + 2781073495U, // <5,5,6,5>: Cost 3 vsldoi12 <4,u,5,5>, <5,6,5,7> + 1228950018U, // <5,5,6,6>: Cost 2 vmrglw <3,4,5,6>, <3,4,5,6> + 2713965390U, // <5,5,6,7>: Cost 3 vsldoi8 <4,u,5,5>, <6,7,0,1> + 1228950018U, // <5,5,6,u>: Cost 2 vmrglw <3,4,5,6>, <3,4,5,6> + 2713965562U, // <5,5,7,0>: Cost 3 vsldoi8 <4,u,5,5>, <7,0,1,2> + 3383741330U, // <5,5,7,1>: Cost 4 vmrglw <4,6,5,7>, <4,0,5,1> + 3718620878U, // <5,5,7,2>: Cost 4 vsldoi4 <4,5,5,7>, <2,3,4,5> + 3365823403U, // <5,5,7,3>: Cost 4 vmrglw <1,6,5,7>, <1,2,5,3> + 2713965926U, // <5,5,7,4>: Cost 3 vsldoi8 <4,u,5,5>, <7,4,5,6> + 2717947318U, // <5,5,7,5>: Cost 3 vsldoi8 <5,5,5,5>, <7,5,5,5> + 3365825026U, // <5,5,7,6>: Cost 4 vmrglw <1,6,5,7>, <3,4,5,6> + 2292081907U, // <5,5,7,7>: Cost 3 vmrglw <1,6,5,7>, <1,6,5,7> + 2713966210U, // <5,5,7,u>: Cost 3 vsldoi8 <4,u,5,5>, <7,u,1,2> + 1577091174U, // <5,5,u,0>: Cost 2 vsldoi4 <5,5,5,5>, LHS + 1640224558U, // <5,5,u,1>: Cost 2 vsldoi8 <4,u,5,5>, LHS + 2713966469U, // <5,5,u,2>: Cost 3 vsldoi8 <4,u,5,5>, + 2713966524U, // <5,5,u,3>: Cost 3 vsldoi8 <4,u,5,5>, + 1577094454U, // <5,5,u,4>: Cost 2 vsldoi4 <5,5,5,5>, RHS + 296144182U, // <5,5,u,5>: Cost 1 vspltisw1 RHS + 1228950018U, // <5,5,u,6>: Cost 2 vmrglw <3,4,5,6>, <3,4,5,6> + 2713966848U, // <5,5,u,7>: Cost 3 vsldoi8 <4,u,5,5>, + 296144182U, // <5,5,u,u>: Cost 1 vspltisw1 RHS + 2705342464U, // <5,6,0,0>: Cost 3 vsldoi8 <3,4,5,6>, <0,0,0,0> + 1631600742U, // <5,6,0,1>: Cost 2 vsldoi8 <3,4,5,6>, LHS + 3773112493U, // <5,6,0,2>: Cost 4 vsldoi8 <2,4,5,6>, <0,2,1,2> + 2705342720U, // <5,6,0,3>: Cost 3 vsldoi8 <3,4,5,6>, <0,3,1,4> + 2705342802U, // <5,6,0,4>: Cost 3 vsldoi8 <3,4,5,6>, <0,4,1,5> + 3779084708U, // <5,6,0,5>: Cost 4 vsldoi8 <3,4,5,6>, <0,5,1,6> + 3779084790U, // <5,6,0,6>: Cost 4 vsldoi8 <3,4,5,6>, <0,6,1,7> + 2302643510U, // <5,6,0,7>: Cost 3 vmrglw <3,4,5,0>, RHS + 1631601309U, // <5,6,0,u>: Cost 2 vsldoi8 <3,4,5,6>, LHS + 3767141092U, // <5,6,1,0>: Cost 4 vsldoi8 <1,4,5,6>, <1,0,1,2> + 2705343284U, // <5,6,1,1>: Cost 3 vsldoi8 <3,4,5,6>, <1,1,1,1> + 2705343382U, // <5,6,1,2>: Cost 3 vsldoi8 <3,4,5,6>, <1,2,3,0> + 3779085282U, // <5,6,1,3>: Cost 4 vsldoi8 <3,4,5,6>, <1,3,2,4> + 2693399632U, // <5,6,1,4>: Cost 3 vsldoi8 <1,4,5,6>, <1,4,5,6> + 3767805089U, // <5,6,1,5>: Cost 4 vsldoi8 <1,5,5,6>, <1,5,5,6> + 2311279416U, // <5,6,1,6>: Cost 3 vmrglw <4,u,5,1>, <6,6,6,6> + 1237536054U, // <5,6,1,7>: Cost 2 vmrglw <4,u,5,1>, RHS + 1237536055U, // <5,6,1,u>: Cost 2 vmrglw <4,u,5,1>, RHS + 3773113789U, // <5,6,2,0>: Cost 4 vsldoi8 <2,4,5,6>, <2,0,1,2> + 3779085855U, // <5,6,2,1>: Cost 4 vsldoi8 <3,4,5,6>, <2,1,3,1> + 2699372136U, // <5,6,2,2>: Cost 3 vsldoi8 <2,4,5,6>, <2,2,2,2> + 2705344166U, // <5,6,2,3>: Cost 3 vsldoi8 <3,4,5,6>, <2,3,0,1> + 2699372329U, // <5,6,2,4>: Cost 3 vsldoi8 <2,4,5,6>, <2,4,5,6> + 2705344360U, // <5,6,2,5>: Cost 3 vsldoi8 <3,4,5,6>, <2,5,3,6> + 2705344442U, // <5,6,2,6>: Cost 3 vsldoi8 <3,4,5,6>, <2,6,3,7> + 2302659894U, // <5,6,2,7>: Cost 3 vmrglw <3,4,5,2>, RHS + 2702026861U, // <5,6,2,u>: Cost 3 vsldoi8 <2,u,5,6>, <2,u,5,6> + 2705344662U, // <5,6,3,0>: Cost 3 vsldoi8 <3,4,5,6>, <3,0,1,2> + 3767142661U, // <5,6,3,1>: Cost 4 vsldoi8 <1,4,5,6>, <3,1,4,5> + 3773114689U, // <5,6,3,2>: Cost 4 vsldoi8 <2,4,5,6>, <3,2,2,2> + 2705344924U, // <5,6,3,3>: Cost 3 vsldoi8 <3,4,5,6>, <3,3,3,3> + 1631603202U, // <5,6,3,4>: Cost 2 vsldoi8 <3,4,5,6>, <3,4,5,6> + 3842945597U, // <5,6,3,5>: Cost 4 vsldoi12 <2,u,6,5>, <6,3,5,7> + 3779086962U, // <5,6,3,6>: Cost 4 vsldoi8 <3,4,5,6>, <3,6,0,1> + 2289397046U, // <5,6,3,7>: Cost 3 vmrglw <1,2,5,3>, RHS + 1634257734U, // <5,6,3,u>: Cost 2 vsldoi8 <3,u,5,6>, <3,u,5,6> + 2644926566U, // <5,6,4,0>: Cost 3 vsldoi4 <4,5,6,4>, LHS + 3779087306U, // <5,6,4,1>: Cost 4 vsldoi8 <3,4,5,6>, <4,1,2,3> + 2790142577U, // <5,6,4,2>: Cost 3 vsldoi12 <6,4,2,5>, <6,4,2,5> + 2644929026U, // <5,6,4,3>: Cost 3 vsldoi4 <4,5,6,4>, <3,4,5,6> + 2711317723U, // <5,6,4,4>: Cost 3 vsldoi8 <4,4,5,6>, <4,4,5,6> + 1631604022U, // <5,6,4,5>: Cost 2 vsldoi8 <3,4,5,6>, RHS + 2712644989U, // <5,6,4,6>: Cost 3 vsldoi8 <4,6,5,6>, <4,6,5,6> + 2302676278U, // <5,6,4,7>: Cost 3 vmrglw <3,4,5,4>, RHS + 1631604265U, // <5,6,4,u>: Cost 2 vsldoi8 <3,4,5,6>, RHS + 3842945708U, // <5,6,5,0>: Cost 4 vsldoi12 <2,u,6,5>, <6,5,0,1> + 3767144133U, // <5,6,5,1>: Cost 4 vsldoi8 <1,4,5,6>, <5,1,6,1> + 2705346328U, // <5,6,5,2>: Cost 3 vsldoi8 <3,4,5,6>, <5,2,6,3> + 3779088207U, // <5,6,5,3>: Cost 4 vsldoi8 <3,4,5,6>, <5,3,3,4> + 2717290420U, // <5,6,5,4>: Cost 3 vsldoi8 <5,4,5,6>, <5,4,5,6> + 2705346574U, // <5,6,5,5>: Cost 3 vsldoi8 <3,4,5,6>, <5,5,6,6> + 2705346596U, // <5,6,5,6>: Cost 3 vsldoi8 <3,4,5,6>, <5,6,0,1> + 1237568822U, // <5,6,5,7>: Cost 2 vmrglw <4,u,5,5>, RHS + 1237568823U, // <5,6,5,u>: Cost 2 vmrglw <4,u,5,5>, RHS + 2650914918U, // <5,6,6,0>: Cost 3 vsldoi4 <5,5,6,6>, LHS + 3364490949U, // <5,6,6,1>: Cost 4 vmrglw <1,4,5,6>, <5,1,6,1> + 2248954362U, // <5,6,6,2>: Cost 3 vmrghw <5,6,7,0>, <6,2,7,3> + 2302693144U, // <5,6,6,3>: Cost 3 vmrglw <3,4,5,6>, <5,2,6,3> + 2650918198U, // <5,6,6,4>: Cost 3 vsldoi4 <5,5,6,6>, RHS + 2650918926U, // <5,6,6,5>: Cost 3 vsldoi4 <5,5,6,6>, <5,5,6,6> + 2302693390U, // <5,6,6,6>: Cost 3 vmrglw <3,4,5,6>, <5,5,6,6> + 1228950838U, // <5,6,6,7>: Cost 2 vmrglw <3,4,5,6>, RHS + 1228950839U, // <5,6,6,u>: Cost 2 vmrglw <3,4,5,6>, RHS + 497467494U, // <5,6,7,0>: Cost 1 vsldoi4 RHS, LHS + 1571210036U, // <5,6,7,1>: Cost 2 vsldoi4 RHS, <1,1,1,1> + 1571210856U, // <5,6,7,2>: Cost 2 vsldoi4 RHS, <2,2,2,2> + 1571211414U, // <5,6,7,3>: Cost 2 vsldoi4 RHS, <3,0,1,2> + 497470774U, // <5,6,7,4>: Cost 1 vsldoi4 RHS, RHS + 1571213316U, // <5,6,7,5>: Cost 2 vsldoi4 RHS, <5,5,5,5> + 1571213818U, // <5,6,7,6>: Cost 2 vsldoi4 RHS, <6,2,7,3> + 1571214956U, // <5,6,7,7>: Cost 2 vsldoi4 RHS, <7,7,7,7> + 497473326U, // <5,6,7,u>: Cost 1 vsldoi4 RHS, LHS + 497475686U, // <5,6,u,0>: Cost 1 vsldoi4 RHS, LHS + 1631606574U, // <5,6,u,1>: Cost 2 vsldoi8 <3,4,5,6>, LHS + 1571219048U, // <5,6,u,2>: Cost 2 vsldoi4 RHS, <2,2,2,2> + 1571219606U, // <5,6,u,3>: Cost 2 vsldoi4 RHS, <3,0,1,2> + 497478967U, // <5,6,u,4>: Cost 1 vsldoi4 RHS, RHS + 1631606938U, // <5,6,u,5>: Cost 2 vsldoi8 <3,4,5,6>, RHS + 1571222010U, // <5,6,u,6>: Cost 2 vsldoi4 RHS, <6,2,7,3> + 1228967222U, // <5,6,u,7>: Cost 2 vmrglw <3,4,5,u>, RHS + 497481518U, // <5,6,u,u>: Cost 1 vsldoi4 RHS, LHS + 3768475648U, // <5,7,0,0>: Cost 4 vsldoi8 <1,6,5,7>, <0,0,0,0> + 2694733926U, // <5,7,0,1>: Cost 3 vsldoi8 <1,6,5,7>, LHS + 3718711395U, // <5,7,0,2>: Cost 4 vsldoi4 <4,5,7,0>, <2,u,4,5> + 3384349178U, // <5,7,0,3>: Cost 4 vmrglw <4,7,5,0>, <6,2,7,3> + 2694734162U, // <5,7,0,4>: Cost 3 vsldoi8 <1,6,5,7>, <0,4,1,5> + 3384347884U, // <5,7,0,5>: Cost 4 vmrglw <4,7,5,0>, <4,4,7,5> + 3730658026U, // <5,7,0,6>: Cost 4 vsldoi4 <6,5,7,0>, <6,5,7,0> + 3718714362U, // <5,7,0,7>: Cost 4 vsldoi4 <4,5,7,0>, <7,0,1,2> + 2694734493U, // <5,7,0,u>: Cost 3 vsldoi8 <1,6,5,7>, LHS + 2311278690U, // <5,7,1,0>: Cost 3 vmrglw <4,u,5,1>, <5,6,7,0> + 2305970923U, // <5,7,1,1>: Cost 3 vmrglw <4,0,5,1>, <6,5,7,1> + 3768476566U, // <5,7,1,2>: Cost 4 vsldoi8 <1,6,5,7>, <1,2,3,0> + 2311279098U, // <5,7,1,3>: Cost 3 vmrglw <4,u,5,1>, <6,2,7,3> + 2311278694U, // <5,7,1,4>: Cost 3 vmrglw <4,u,5,1>, <5,6,7,4> + 3768476783U, // <5,7,1,5>: Cost 4 vsldoi8 <1,6,5,7>, <1,5,0,1> + 2694735091U, // <5,7,1,6>: Cost 3 vsldoi8 <1,6,5,7>, <1,6,5,7> + 2311279426U, // <5,7,1,7>: Cost 3 vmrglw <4,u,5,1>, <6,6,7,7> + 2696062357U, // <5,7,1,u>: Cost 3 vsldoi8 <1,u,5,7>, <1,u,5,7> + 3383701602U, // <5,7,2,0>: Cost 4 vmrglw <4,6,5,2>, <5,6,7,0> + 3768477219U, // <5,7,2,1>: Cost 4 vsldoi8 <1,6,5,7>, <2,1,3,5> + 3768477288U, // <5,7,2,2>: Cost 4 vsldoi8 <1,6,5,7>, <2,2,2,2> + 2309960186U, // <5,7,2,3>: Cost 3 vmrglw <4,6,5,2>, <6,2,7,3> + 3383701606U, // <5,7,2,4>: Cost 4 vmrglw <4,6,5,2>, <5,6,7,4> + 3768477545U, // <5,7,2,5>: Cost 4 vsldoi8 <1,6,5,7>, <2,5,3,7> + 3766486970U, // <5,7,2,6>: Cost 4 vsldoi8 <1,3,5,7>, <2,6,3,7> + 3383702338U, // <5,7,2,7>: Cost 4 vmrglw <4,6,5,2>, <6,6,7,7> + 2309960186U, // <5,7,2,u>: Cost 3 vmrglw <4,6,5,2>, <6,2,7,3> + 3768477846U, // <5,7,3,0>: Cost 4 vsldoi8 <1,6,5,7>, <3,0,1,2> + 3768477975U, // <5,7,3,1>: Cost 4 vsldoi8 <1,6,5,7>, <3,1,6,5> + 3786393932U, // <5,7,3,2>: Cost 4 vsldoi8 <4,6,5,7>, <3,2,3,4> + 3768478108U, // <5,7,3,3>: Cost 4 vsldoi8 <1,6,5,7>, <3,3,3,3> + 2795599115U, // <5,7,3,4>: Cost 3 vsldoi12 <7,3,4,5>, <7,3,4,5> + 3385037470U, // <5,7,3,5>: Cost 4 vmrglw <4,u,5,3>, <6,4,7,5> + 3780422309U, // <5,7,3,6>: Cost 4 vsldoi8 <3,6,5,7>, <3,6,5,7> + 3848107301U, // <5,7,3,7>: Cost 4 vsldoi12 <3,7,4,5>, <7,3,7,4> + 2795894063U, // <5,7,3,u>: Cost 3 vsldoi12 <7,3,u,5>, <7,3,u,5> + 2795967800U, // <5,7,4,0>: Cost 3 vsldoi12 <7,4,0,5>, <7,4,0,5> + 3768478690U, // <5,7,4,1>: Cost 4 vsldoi8 <1,6,5,7>, <4,1,5,0> + 3718744163U, // <5,7,4,2>: Cost 4 vsldoi4 <4,5,7,4>, <2,u,4,5> + 3784404107U, // <5,7,4,3>: Cost 4 vsldoi8 <4,3,5,7>, <4,3,5,7> + 2796262748U, // <5,7,4,4>: Cost 3 vsldoi12 <7,4,4,5>, <7,4,4,5> + 2694737206U, // <5,7,4,5>: Cost 3 vsldoi8 <1,6,5,7>, RHS + 2712653182U, // <5,7,4,6>: Cost 3 vsldoi8 <4,6,5,7>, <4,6,5,7> + 2713316815U, // <5,7,4,7>: Cost 3 vsldoi8 <4,7,5,7>, <4,7,5,7> + 2694737449U, // <5,7,4,u>: Cost 3 vsldoi8 <1,6,5,7>, RHS + 2311311458U, // <5,7,5,0>: Cost 3 vmrglw <4,u,5,5>, <5,6,7,0> + 3768479433U, // <5,7,5,1>: Cost 4 vsldoi8 <1,6,5,7>, <5,1,6,5> + 3768479521U, // <5,7,5,2>: Cost 4 vsldoi8 <1,6,5,7>, <5,2,7,3> + 2311311866U, // <5,7,5,3>: Cost 3 vmrglw <4,u,5,5>, <6,2,7,3> + 2311311462U, // <5,7,5,4>: Cost 3 vmrglw <4,u,5,5>, <5,6,7,4> + 2248185270U, // <5,7,5,5>: Cost 3 vmrghw <5,5,5,5>, <7,5,5,5> + 2718625879U, // <5,7,5,6>: Cost 3 vsldoi8 <5,6,5,7>, <5,6,5,7> + 2311312194U, // <5,7,5,7>: Cost 3 vmrglw <4,u,5,5>, <6,6,7,7> + 2311311466U, // <5,7,5,u>: Cost 3 vmrglw <4,u,5,5>, <5,6,7,u> + 2248954874U, // <5,7,6,0>: Cost 3 vmrghw <5,6,7,0>, <7,0,1,2> + 3322696778U, // <5,7,6,1>: Cost 4 vmrghw <5,6,7,0>, <7,1,1,1> + 2248955028U, // <5,7,6,2>: Cost 3 vmrghw <5,6,7,0>, <7,2,0,3> + 2656963074U, // <5,7,6,3>: Cost 3 vsldoi4 <6,5,7,6>, <3,4,5,6> + 2248955238U, // <5,7,6,4>: Cost 3 vmrghw <5,6,7,0>, <7,4,5,6> + 2248955329U, // <5,7,6,5>: Cost 3 vmrghw <5,6,7,0>, <7,5,6,7> + 2656965360U, // <5,7,6,6>: Cost 3 vsldoi4 <6,5,7,6>, <6,5,7,6> + 2248955500U, // <5,7,6,7>: Cost 3 vmrghw <5,6,7,0>, <7,7,7,7> + 2248955522U, // <5,7,6,u>: Cost 3 vmrghw <5,6,7,0>, <7,u,1,2> + 3718766694U, // <5,7,7,0>: Cost 4 vsldoi4 <4,5,7,7>, LHS + 3724739827U, // <5,7,7,1>: Cost 4 vsldoi4 <5,5,7,7>, <1,6,5,7> + 3718768739U, // <5,7,7,2>: Cost 4 vsldoi4 <4,5,7,7>, <2,u,4,5> + 3365826337U, // <5,7,7,3>: Cost 4 vmrglw <1,6,5,7>, <5,2,7,3> + 2798253647U, // <5,7,7,4>: Cost 3 vsldoi12 <7,7,4,5>, <7,7,4,5> + 3365826258U, // <5,7,7,5>: Cost 4 vmrglw <1,6,5,7>, <5,1,7,5> + 3730715377U, // <5,7,7,6>: Cost 4 vsldoi4 <6,5,7,7>, <6,5,7,7> + 2310665836U, // <5,7,7,7>: Cost 3 vmrglw <4,7,5,7>, <7,7,7,7> + 2798548595U, // <5,7,7,u>: Cost 3 vsldoi12 <7,7,u,5>, <7,7,u,5> + 2311336034U, // <5,7,u,0>: Cost 3 vmrglw <4,u,5,u>, <5,6,7,0> + 2694739758U, // <5,7,u,1>: Cost 3 vsldoi8 <1,6,5,7>, LHS + 2248955028U, // <5,7,u,2>: Cost 3 vmrghw <5,6,7,0>, <7,2,0,3> + 2311336442U, // <5,7,u,3>: Cost 3 vmrglw <4,u,5,u>, <6,2,7,3> + 2311336038U, // <5,7,u,4>: Cost 3 vmrglw <4,u,5,u>, <5,6,7,4> + 2694740122U, // <5,7,u,5>: Cost 3 vsldoi8 <1,6,5,7>, RHS + 2656981746U, // <5,7,u,6>: Cost 3 vsldoi4 <6,5,7,u>, <6,5,7,u> + 2311336770U, // <5,7,u,7>: Cost 3 vmrglw <4,u,5,u>, <6,6,7,7> + 2694740325U, // <5,7,u,u>: Cost 3 vsldoi8 <1,6,5,7>, LHS + 2705358848U, // <5,u,0,0>: Cost 3 vsldoi8 <3,4,5,u>, <0,0,0,0> + 1631617126U, // <5,u,0,1>: Cost 2 vsldoi8 <3,4,5,u>, LHS + 2310607866U, // <5,u,0,2>: Cost 3 vmrglw <4,7,5,0>, <7,0,1,2> + 2302640284U, // <5,u,0,3>: Cost 3 vmrglw <3,4,5,0>, LHS + 2754238189U, // <5,u,0,4>: Cost 3 vsldoi12 <0,4,1,5>, + 2305296114U, // <5,u,0,5>: Cost 3 vmrglw <3,u,5,0>, <2,3,u,5> + 2244907106U, // <5,u,0,6>: Cost 3 vmrghw <5,0,6,1>, <5,6,7,0> + 2302643528U, // <5,u,0,7>: Cost 3 vmrglw <3,4,5,0>, RHS + 1631617693U, // <5,u,0,u>: Cost 2 vsldoi8 <3,4,5,u>, LHS + 2627133542U, // <5,u,1,0>: Cost 3 vsldoi4 <1,5,u,1>, LHS + 1237536282U, // <5,u,1,1>: Cost 2 vmrglw <4,u,5,1>, <4,u,5,1> + 1680496430U, // <5,u,1,2>: Cost 2 vsldoi12 <0,4,1,5>, LHS + 1237532828U, // <5,u,1,3>: Cost 2 vmrglw <4,u,5,1>, LHS + 2693416018U, // <5,u,1,4>: Cost 3 vsldoi8 <1,4,5,u>, <1,4,5,u> + 2756892486U, // <5,u,1,5>: Cost 3 vsldoi12 <0,u,1,5>, + 2694743284U, // <5,u,1,6>: Cost 3 vsldoi8 <1,6,5,u>, <1,6,5,u> + 1237536072U, // <5,u,1,7>: Cost 2 vmrglw <4,u,5,1>, RHS + 1680496484U, // <5,u,1,u>: Cost 2 vsldoi12 <0,4,1,5>, LHS + 2311288709U, // <5,u,2,0>: Cost 3 vmrglw <4,u,5,2>, + 2245883694U, // <5,u,2,1>: Cost 3 vmrghw <5,2,1,3>, LHS + 2699388520U, // <5,u,2,2>: Cost 3 vsldoi8 <2,4,5,u>, <2,2,2,2> + 2754238344U, // <5,u,2,3>: Cost 3 vsldoi12 <0,4,1,5>, + 2699388715U, // <5,u,2,4>: Cost 3 vsldoi8 <2,4,5,u>, <2,4,5,u> + 2757408666U, // <5,u,2,5>: Cost 3 vsldoi12 <0,u,u,5>, + 2705360826U, // <5,u,2,6>: Cost 3 vsldoi8 <3,4,5,u>, <2,6,3,7> + 2302659912U, // <5,u,2,7>: Cost 3 vmrglw <3,4,5,2>, RHS + 2754238389U, // <5,u,2,u>: Cost 3 vsldoi12 <0,4,1,5>, + 2754238396U, // <5,u,3,0>: Cost 3 vsldoi12 <0,4,1,5>, + 3827980229U, // <5,u,3,1>: Cost 4 vsldoi12 <0,4,1,5>, + 2644625102U, // <5,u,3,2>: Cost 3 vsldoi4 <4,5,2,3>, <2,3,4,5> + 2289393820U, // <5,u,3,3>: Cost 3 vmrglw <1,2,5,3>, LHS + 1631619588U, // <5,u,3,4>: Cost 2 vsldoi8 <3,4,5,u>, <3,4,5,u> + 2785056749U, // <5,u,3,5>: Cost 3 vsldoi12 <5,5,5,5>, + 3363138077U, // <5,u,3,6>: Cost 4 vmrglw <1,2,5,3>, <3,4,u,6> + 2289397064U, // <5,u,3,7>: Cost 3 vmrglw <1,2,5,3>, RHS + 1634274120U, // <5,u,3,u>: Cost 2 vsldoi8 <3,u,5,u>, <3,u,5,u> + 1634937753U, // <5,u,4,0>: Cost 2 vsldoi8 <4,0,5,u>, <4,0,5,u> + 1728272410U, // <5,u,4,1>: Cost 2 vsldoi12 , + 2710006843U, // <5,u,4,2>: Cost 3 vsldoi8 <4,2,5,u>, <4,2,5,u> + 2765740076U, // <5,u,4,3>: Cost 3 vsldoi12 <2,3,4,5>, + 1637592285U, // <5,u,4,4>: Cost 2 vsldoi8 <4,4,5,u>, <4,4,5,u> + 1631620406U, // <5,u,4,5>: Cost 2 vsldoi8 <3,4,5,u>, RHS + 2712661375U, // <5,u,4,6>: Cost 3 vsldoi8 <4,6,5,u>, <4,6,5,u> + 2302676296U, // <5,u,4,7>: Cost 3 vmrglw <3,4,5,4>, RHS + 1631620649U, // <5,u,4,u>: Cost 2 vsldoi8 <3,4,5,u>, RHS + 1577091174U, // <5,u,5,0>: Cost 2 vsldoi4 <5,5,5,5>, LHS + 1174443822U, // <5,u,5,1>: Cost 2 vmrghw <5,5,5,5>, LHS + 2766035058U, // <5,u,5,2>: Cost 3 vsldoi12 <2,3,u,5>, + 1237565596U, // <5,u,5,3>: Cost 2 vmrglw <4,u,5,5>, LHS + 1577094454U, // <5,u,5,4>: Cost 2 vsldoi4 <5,5,5,5>, RHS + 296144182U, // <5,u,5,5>: Cost 1 vspltisw1 RHS + 1680496794U, // <5,u,5,6>: Cost 2 vsldoi12 <0,4,1,5>, RHS + 1237568840U, // <5,u,5,7>: Cost 2 vmrglw <4,u,5,5>, RHS + 296144182U, // <5,u,5,u>: Cost 1 vspltisw1 RHS + 2633146470U, // <5,u,6,0>: Cost 3 vsldoi4 <2,5,u,6>, LHS + 1175213870U, // <5,u,6,1>: Cost 2 vmrghw <5,6,7,0>, LHS + 2633148309U, // <5,u,6,2>: Cost 3 vsldoi4 <2,5,u,6>, <2,5,u,6> + 1228947612U, // <5,u,6,3>: Cost 2 vmrglw <3,4,5,6>, LHS + 2633149750U, // <5,u,6,4>: Cost 3 vsldoi4 <2,5,u,6>, RHS + 1175214234U, // <5,u,6,5>: Cost 2 vmrghw <5,6,7,0>, RHS + 1228950018U, // <5,u,6,6>: Cost 2 vmrglw <3,4,5,6>, <3,4,5,6> + 1228950856U, // <5,u,6,7>: Cost 2 vmrglw <3,4,5,6>, RHS + 1228947617U, // <5,u,6,u>: Cost 2 vmrglw <3,4,5,6>, LHS + 497614950U, // <5,u,7,0>: Cost 1 vsldoi4 RHS, LHS + 1571357492U, // <5,u,7,1>: Cost 2 vsldoi4 RHS, <1,1,1,1> + 1571358312U, // <5,u,7,2>: Cost 2 vsldoi4 RHS, <2,2,2,2> + 1571358870U, // <5,u,7,3>: Cost 2 vsldoi4 RHS, <3,0,1,2> + 497618248U, // <5,u,7,4>: Cost 1 vsldoi4 RHS, RHS + 1571360772U, // <5,u,7,5>: Cost 2 vsldoi4 RHS, <5,5,5,5> + 1571361274U, // <5,u,7,6>: Cost 2 vsldoi4 RHS, <6,2,7,3> + 1571361786U, // <5,u,7,7>: Cost 2 vsldoi4 RHS, <7,0,1,2> + 497620782U, // <5,u,7,u>: Cost 1 vsldoi4 RHS, LHS + 497623142U, // <5,u,u,0>: Cost 1 vsldoi4 RHS, LHS + 1631622958U, // <5,u,u,1>: Cost 2 vsldoi8 <3,4,5,u>, LHS + 1680496997U, // <5,u,u,2>: Cost 2 vsldoi12 <0,4,1,5>, LHS + 1228963996U, // <5,u,u,3>: Cost 2 vmrglw <3,4,5,u>, LHS + 497626441U, // <5,u,u,4>: Cost 1 vsldoi4 RHS, RHS + 296144182U, // <5,u,u,5>: Cost 1 vspltisw1 RHS + 1680497037U, // <5,u,u,6>: Cost 2 vsldoi12 <0,4,1,5>, RHS + 1228967240U, // <5,u,u,7>: Cost 2 vmrglw <3,4,5,u>, RHS + 497628974U, // <5,u,u,u>: Cost 1 vsldoi4 RHS, LHS + 2772451328U, // <6,0,0,0>: Cost 3 vsldoi12 <3,4,5,6>, <0,0,0,0> + 2772451338U, // <6,0,0,1>: Cost 3 vsldoi12 <3,4,5,6>, <0,0,1,1> + 3771146417U, // <6,0,0,2>: Cost 4 vsldoi8 <2,1,6,0>, <0,2,1,6> + 3383095739U, // <6,0,0,3>: Cost 4 vmrglw <4,5,6,0>, <6,2,0,3> + 3846193189U, // <6,0,0,4>: Cost 4 vsldoi12 <3,4,5,6>, <0,0,4,1> + 3724832803U, // <6,0,0,5>: Cost 4 vsldoi4 <5,6,0,0>, <5,6,0,0> + 3383095985U, // <6,0,0,6>: Cost 4 vmrglw <4,5,6,0>, <6,5,0,6> + 3383096067U, // <6,0,0,7>: Cost 4 vmrglw <4,5,6,0>, <6,6,0,7> + 2772451401U, // <6,0,0,u>: Cost 3 vsldoi12 <3,4,5,6>, <0,0,u,1> + 2651095142U, // <6,0,1,0>: Cost 3 vsldoi4 <5,6,0,1>, LHS + 2251612262U, // <6,0,1,1>: Cost 3 vmrghw <6,1,7,1>, LHS + 1698709606U, // <6,0,1,2>: Cost 2 vsldoi12 <3,4,5,6>, LHS + 2651097602U, // <6,0,1,3>: Cost 3 vsldoi4 <5,6,0,1>, <3,4,5,6> + 2651098422U, // <6,0,1,4>: Cost 3 vsldoi4 <5,6,0,1>, RHS + 2651099172U, // <6,0,1,5>: Cost 3 vsldoi4 <5,6,0,1>, <5,6,0,1> + 2657071869U, // <6,0,1,6>: Cost 3 vsldoi4 <6,6,0,1>, <6,6,0,1> + 3724841978U, // <6,0,1,7>: Cost 4 vsldoi4 <5,6,0,1>, <7,0,1,2> + 1698709660U, // <6,0,1,u>: Cost 2 vsldoi12 <3,4,5,6>, LHS + 2252292096U, // <6,0,2,0>: Cost 3 vmrghw <6,2,7,3>, <0,0,0,0> + 1178550374U, // <6,0,2,1>: Cost 2 vmrghw <6,2,7,3>, LHS + 3826655418U, // <6,0,2,2>: Cost 4 vsldoi12 <0,2,1,6>, <0,2,2,6> + 3777783485U, // <6,0,2,3>: Cost 4 vsldoi8 <3,2,6,0>, <2,3,2,6> + 2252292434U, // <6,0,2,4>: Cost 3 vmrghw <6,2,7,3>, <0,4,1,5> + 3785746280U, // <6,0,2,5>: Cost 4 vsldoi8 <4,5,6,0>, <2,5,3,6> + 2252292593U, // <6,0,2,6>: Cost 3 vmrghw <6,2,7,3>, <0,6,1,2> + 3736794583U, // <6,0,2,7>: Cost 4 vsldoi4 <7,6,0,2>, <7,6,0,2> + 1178550941U, // <6,0,2,u>: Cost 2 vmrghw <6,2,7,3>, LHS + 3375153152U, // <6,0,3,0>: Cost 4 vmrglw <3,2,6,3>, <0,0,0,0> + 2772451584U, // <6,0,3,1>: Cost 3 vsldoi12 <3,4,5,6>, <0,3,1,4> + 3777784163U, // <6,0,3,2>: Cost 4 vsldoi8 <3,2,6,0>, <3,2,6,0> + 3846193426U, // <6,0,3,3>: Cost 4 vsldoi12 <3,4,5,6>, <0,3,3,4> + 2712005122U, // <6,0,3,4>: Cost 3 vsldoi8 <4,5,6,0>, <3,4,5,6> + 3724857382U, // <6,0,3,5>: Cost 4 vsldoi4 <5,6,0,3>, <5,6,0,3> + 3802335864U, // <6,0,3,6>: Cost 4 vsldoi8 <7,3,6,0>, <3,6,0,7> + 3801672410U, // <6,0,3,7>: Cost 4 vsldoi8 <7,2,6,0>, <3,7,2,6> + 2772451647U, // <6,0,3,u>: Cost 3 vsldoi12 <3,4,5,6>, <0,3,u,4> + 3383123968U, // <6,0,4,0>: Cost 4 vmrglw <4,5,6,4>, <0,0,0,0> + 2772451666U, // <6,0,4,1>: Cost 3 vsldoi12 <3,4,5,6>, <0,4,1,5> + 3773803577U, // <6,0,4,2>: Cost 4 vsldoi8 <2,5,6,0>, <4,2,5,6> + 3724864002U, // <6,0,4,3>: Cost 4 vsldoi4 <5,6,0,4>, <3,4,5,6> + 3846193517U, // <6,0,4,4>: Cost 4 vsldoi12 <3,4,5,6>, <0,4,4,5> + 2712005935U, // <6,0,4,5>: Cost 3 vsldoi8 <4,5,6,0>, <4,5,6,0> + 3327009265U, // <6,0,4,6>: Cost 4 vmrghw <6,4,2,5>, <0,6,1,2> + 3383126648U, // <6,0,4,7>: Cost 5 vmrglw <4,5,6,4>, <3,6,0,7> + 2772451729U, // <6,0,4,u>: Cost 3 vsldoi12 <3,4,5,6>, <0,4,u,5> + 3373178880U, // <6,0,5,0>: Cost 4 vmrglw <2,u,6,5>, <0,0,0,0> + 2254266470U, // <6,0,5,1>: Cost 3 vmrghw <6,5,7,1>, LHS + 3785748248U, // <6,0,5,2>: Cost 4 vsldoi8 <4,5,6,0>, <5,2,6,3> + 3790393190U, // <6,0,5,3>: Cost 4 vsldoi8 <5,3,6,0>, <5,3,6,0> + 3328000338U, // <6,0,5,4>: Cost 4 vmrghw <6,5,7,0>, <0,4,1,5> + 3785748494U, // <6,0,5,5>: Cost 4 vsldoi8 <4,5,6,0>, <5,5,6,6> + 3785748516U, // <6,0,5,6>: Cost 4 vsldoi8 <4,5,6,0>, <5,6,0,1> + 3379153528U, // <6,0,5,7>: Cost 4 vmrglw <3,u,6,5>, <3,6,0,7> + 2254267037U, // <6,0,5,u>: Cost 3 vmrghw <6,5,7,1>, LHS + 2254897152U, // <6,0,6,0>: Cost 3 vmrghw <6,6,6,6>, <0,0,0,0> + 1181155430U, // <6,0,6,1>: Cost 2 vmrghw <6,6,6,6>, LHS + 3785748923U, // <6,0,6,2>: Cost 4 vsldoi8 <4,5,6,0>, <6,2,0,3> + 3785749042U, // <6,0,6,3>: Cost 4 vsldoi8 <4,5,6,0>, <6,3,4,5> + 2254897490U, // <6,0,6,4>: Cost 3 vmrghw <6,6,6,6>, <0,4,1,5> + 3785749169U, // <6,0,6,5>: Cost 4 vsldoi8 <4,5,6,0>, <6,5,0,6> + 2724614962U, // <6,0,6,6>: Cost 3 vsldoi8 <6,6,6,0>, <6,6,6,0> + 3787739982U, // <6,0,6,7>: Cost 4 vsldoi8 <4,u,6,0>, <6,7,0,1> + 1181155997U, // <6,0,6,u>: Cost 2 vmrghw <6,6,6,6>, LHS + 1235664896U, // <6,0,7,0>: Cost 2 vmrglw RHS, <0,0,0,0> + 1235666598U, // <6,0,7,1>: Cost 2 vmrglw RHS, <2,3,0,1> + 3712943720U, // <6,0,7,2>: Cost 4 vsldoi4 <3,6,0,7>, <2,2,2,2> + 2639202936U, // <6,0,7,3>: Cost 3 vsldoi4 <3,6,0,7>, <3,6,0,7> + 2639203638U, // <6,0,7,4>: Cost 3 vsldoi4 <3,6,0,7>, RHS + 2309409236U, // <6,0,7,5>: Cost 3 vmrglw RHS, <3,4,0,5> + 3712946517U, // <6,0,7,6>: Cost 4 vsldoi4 <3,6,0,7>, <6,0,7,0> + 2309409400U, // <6,0,7,7>: Cost 3 vmrglw RHS, <3,6,0,7> + 1235666605U, // <6,0,7,u>: Cost 2 vmrglw RHS, <2,3,0,u> + 1235673088U, // <6,0,u,0>: Cost 2 vmrglw RHS, <0,0,0,0> + 1235674790U, // <6,0,u,1>: Cost 2 vmrglw RHS, <2,3,0,1> + 1698710173U, // <6,0,u,2>: Cost 2 vsldoi12 <3,4,5,6>, LHS + 2639211129U, // <6,0,u,3>: Cost 3 vsldoi4 <3,6,0,u>, <3,6,0,u> + 2639211830U, // <6,0,u,4>: Cost 3 vsldoi4 <3,6,0,u>, RHS + 2712008858U, // <6,0,u,5>: Cost 3 vsldoi8 <4,5,6,0>, RHS + 2657129220U, // <6,0,u,6>: Cost 3 vsldoi4 <6,6,0,u>, <6,6,0,u> + 2309417592U, // <6,0,u,7>: Cost 3 vmrglw RHS, <3,6,0,7> + 1698710227U, // <6,0,u,u>: Cost 2 vsldoi12 <3,4,5,6>, LHS + 3775799296U, // <6,1,0,0>: Cost 4 vsldoi8 <2,u,6,1>, <0,0,0,0> + 2702057574U, // <6,1,0,1>: Cost 3 vsldoi8 <2,u,6,1>, LHS + 3373143763U, // <6,1,0,2>: Cost 4 vmrglw <2,u,6,0>, + 3695045122U, // <6,1,0,3>: Cost 4 vsldoi4 <0,6,1,0>, <3,4,5,6> + 3775799634U, // <6,1,0,4>: Cost 4 vsldoi8 <2,u,6,1>, <0,4,1,5> + 3383091538U, // <6,1,0,5>: Cost 4 vmrglw <4,5,6,0>, <0,4,1,5> + 3368493233U, // <6,1,0,6>: Cost 4 vmrglw <2,1,6,0>, <0,2,1,6> + 3362522319U, // <6,1,0,7>: Cost 5 vmrglw <1,1,6,0>, <1,6,1,7> + 2702058141U, // <6,1,0,u>: Cost 3 vsldoi8 <2,u,6,1>, LHS + 3834250027U, // <6,1,1,0>: Cost 4 vsldoi12 <1,4,5,6>, <1,1,0,1> + 2772452148U, // <6,1,1,1>: Cost 3 vsldoi12 <3,4,5,6>, <1,1,1,1> + 3832038210U, // <6,1,1,2>: Cost 4 vsldoi12 <1,1,2,6>, <1,1,2,6> + 3373150660U, // <6,1,1,3>: Cost 4 vmrglw <2,u,6,1>, <6,2,1,3> + 3834250067U, // <6,1,1,4>: Cost 4 vsldoi12 <1,4,5,6>, <1,1,4,5> + 3373146450U, // <6,1,1,5>: Cost 4 vmrglw <2,u,6,1>, <0,4,1,5> + 3826656102U, // <6,1,1,6>: Cost 4 vsldoi12 <0,2,1,6>, <1,1,6,6> + 3362530511U, // <6,1,1,7>: Cost 4 vmrglw <1,1,6,1>, <1,6,1,7> + 2772452148U, // <6,1,1,u>: Cost 3 vsldoi12 <3,4,5,6>, <1,1,1,1> + 2669092966U, // <6,1,2,0>: Cost 3 vsldoi4 , LHS + 2252292916U, // <6,1,2,1>: Cost 3 vmrghw <6,2,7,3>, <1,1,1,1> + 2252293014U, // <6,1,2,2>: Cost 3 vmrghw <6,2,7,3>, <1,2,3,0> + 2772452246U, // <6,1,2,3>: Cost 3 vsldoi12 <3,4,5,6>, <1,2,3,0> + 2669096246U, // <6,1,2,4>: Cost 3 vsldoi4 , RHS + 3846194091U, // <6,1,2,5>: Cost 4 vsldoi12 <3,4,5,6>, <1,2,5,3> + 2702059450U, // <6,1,2,6>: Cost 3 vsldoi8 <2,u,6,1>, <2,6,3,7> + 3870081978U, // <6,1,2,7>: Cost 4 vsldoi12 <7,4,5,6>, <1,2,7,0> + 2702059633U, // <6,1,2,u>: Cost 3 vsldoi8 <2,u,6,1>, <2,u,6,1> + 3775801494U, // <6,1,3,0>: Cost 4 vsldoi8 <2,u,6,1>, <3,0,1,2> + 3777128723U, // <6,1,3,1>: Cost 4 vsldoi8 <3,1,6,1>, <3,1,6,1> + 3775801702U, // <6,1,3,2>: Cost 4 vsldoi8 <2,u,6,1>, <3,2,6,3> + 3775801756U, // <6,1,3,3>: Cost 4 vsldoi8 <2,u,6,1>, <3,3,3,3> + 3775801858U, // <6,1,3,4>: Cost 4 vsldoi8 <2,u,6,1>, <3,4,5,6> + 3375153490U, // <6,1,3,5>: Cost 4 vmrglw <3,2,6,3>, <0,4,1,5> + 3826656265U, // <6,1,3,6>: Cost 4 vsldoi12 <0,2,1,6>, <1,3,6,7> + 3775802051U, // <6,1,3,7>: Cost 4 vsldoi8 <2,u,6,1>, <3,7,0,1> + 3775802142U, // <6,1,3,u>: Cost 4 vsldoi8 <2,u,6,1>, <3,u,1,2> + 3846194206U, // <6,1,4,0>: Cost 4 vsldoi12 <3,4,5,6>, <1,4,0,1> + 3846194219U, // <6,1,4,1>: Cost 4 vsldoi12 <3,4,5,6>, <1,4,1,5> + 3846194228U, // <6,1,4,2>: Cost 4 vsldoi12 <3,4,5,6>, <1,4,2,5> + 3846194236U, // <6,1,4,3>: Cost 4 vsldoi12 <3,4,5,6>, <1,4,3,4> + 3846194246U, // <6,1,4,4>: Cost 4 vsldoi12 <3,4,5,6>, <1,4,4,5> + 2760508496U, // <6,1,4,5>: Cost 3 vsldoi12 <1,4,5,6>, <1,4,5,6> + 3368526001U, // <6,1,4,6>: Cost 4 vmrglw <2,1,6,4>, <0,2,1,6> + 3870082144U, // <6,1,4,7>: Cost 4 vsldoi12 <7,4,5,6>, <1,4,7,4> + 2760729707U, // <6,1,4,u>: Cost 3 vsldoi12 <1,4,u,6>, <1,4,u,6> + 2714668660U, // <6,1,5,0>: Cost 3 vsldoi8 <5,0,6,1>, <5,0,6,1> + 3834619005U, // <6,1,5,1>: Cost 4 vsldoi12 <1,5,1,6>, <1,5,1,6> + 3834692742U, // <6,1,5,2>: Cost 4 vsldoi12 <1,5,2,6>, <1,5,2,6> + 3846194317U, // <6,1,5,3>: Cost 4 vsldoi12 <3,4,5,6>, <1,5,3,4> + 3834840216U, // <6,1,5,4>: Cost 4 vsldoi12 <1,5,4,6>, <1,5,4,6> + 3834913953U, // <6,1,5,5>: Cost 4 vsldoi12 <1,5,5,6>, <1,5,5,6> + 2719977570U, // <6,1,5,6>: Cost 3 vsldoi8 <5,u,6,1>, <5,6,7,0> + 3367208143U, // <6,1,5,7>: Cost 4 vmrglw <1,u,6,5>, <1,6,1,7> + 2719977724U, // <6,1,5,u>: Cost 3 vsldoi8 <5,u,6,1>, <5,u,6,1> + 2669125734U, // <6,1,6,0>: Cost 3 vsldoi4 , LHS + 2254897972U, // <6,1,6,1>: Cost 3 vmrghw <6,6,6,6>, <1,1,1,1> + 2254898070U, // <6,1,6,2>: Cost 3 vmrghw <6,6,6,6>, <1,2,3,0> + 3775803929U, // <6,1,6,3>: Cost 4 vsldoi8 <2,u,6,1>, <6,3,1,7> + 2669129014U, // <6,1,6,4>: Cost 3 vsldoi4 , RHS + 2322006354U, // <6,1,6,5>: Cost 3 vmrglw <6,6,6,6>, <0,4,1,5> + 2725950264U, // <6,1,6,6>: Cost 3 vsldoi8 <6,u,6,1>, <6,6,6,6> + 3793720142U, // <6,1,6,7>: Cost 4 vsldoi8 <5,u,6,1>, <6,7,0,1> + 2254898556U, // <6,1,6,u>: Cost 3 vmrghw <6,6,6,6>, <1,u,3,0> + 2627330150U, // <6,1,7,0>: Cost 3 vsldoi4 <1,6,1,7>, LHS + 1235664906U, // <6,1,7,1>: Cost 2 vmrglw RHS, <0,0,1,1> + 1235667094U, // <6,1,7,2>: Cost 2 vmrglw RHS, <3,0,1,2> + 2309406894U, // <6,1,7,3>: Cost 3 vmrglw RHS, <0,2,1,3> + 2627333430U, // <6,1,7,4>: Cost 3 vsldoi4 <1,6,1,7>, RHS + 1235665234U, // <6,1,7,5>: Cost 2 vmrglw RHS, <0,4,1,5> + 2309406897U, // <6,1,7,6>: Cost 3 vmrglw RHS, <0,2,1,6> + 2309407222U, // <6,1,7,7>: Cost 3 vmrglw RHS, <0,6,1,7> + 1235664913U, // <6,1,7,u>: Cost 2 vmrglw RHS, <0,0,1,u> + 2627338342U, // <6,1,u,0>: Cost 3 vsldoi4 <1,6,1,u>, LHS + 1235673098U, // <6,1,u,1>: Cost 2 vmrglw RHS, <0,0,1,1> + 1235675286U, // <6,1,u,2>: Cost 2 vmrglw RHS, <3,0,1,2> + 2772452732U, // <6,1,u,3>: Cost 3 vsldoi12 <3,4,5,6>, <1,u,3,0> + 2627341622U, // <6,1,u,4>: Cost 3 vsldoi4 <1,6,1,u>, RHS + 1235673426U, // <6,1,u,5>: Cost 2 vmrglw RHS, <0,4,1,5> + 2309415089U, // <6,1,u,6>: Cost 3 vmrglw RHS, <0,2,1,6> + 2309415414U, // <6,1,u,7>: Cost 3 vmrglw RHS, <0,6,1,7> + 1235673105U, // <6,1,u,u>: Cost 2 vmrglw RHS, <0,0,1,u> + 3324683725U, // <6,2,0,0>: Cost 4 vmrghw <6,0,7,0>, <2,0,3,0> + 2725290086U, // <6,2,0,1>: Cost 3 vsldoi8 <6,7,6,2>, LHS + 3771162801U, // <6,2,0,2>: Cost 4 vsldoi8 <2,1,6,2>, <0,2,1,6> + 2309349478U, // <6,2,0,3>: Cost 3 vmrglw <4,5,6,0>, LHS + 3730951478U, // <6,2,0,4>: Cost 4 vsldoi4 <6,6,2,0>, RHS + 3840738784U, // <6,2,0,5>: Cost 4 vsldoi12 <2,5,3,6>, <2,0,5,1> + 3842655721U, // <6,2,0,6>: Cost 4 vsldoi12 <2,u,2,6>, <2,0,6,1> + 3736925671U, // <6,2,0,7>: Cost 4 vsldoi4 <7,6,2,0>, <7,6,2,0> + 2309349483U, // <6,2,0,u>: Cost 3 vmrglw <4,5,6,0>, LHS + 3367840468U, // <6,2,1,0>: Cost 4 vmrglw <2,0,6,1>, <3,7,2,0> + 3325355551U, // <6,2,1,1>: Cost 4 vmrghw <6,1,7,1>, <2,1,3,1> + 3373147752U, // <6,2,1,2>: Cost 4 vmrglw <2,u,6,1>, <2,2,2,2> + 2299404390U, // <6,2,1,3>: Cost 3 vmrglw <2,u,6,1>, LHS + 3701099830U, // <6,2,1,4>: Cost 5 vsldoi4 <1,6,2,1>, RHS + 3767846054U, // <6,2,1,5>: Cost 4 vsldoi8 <1,5,6,2>, <1,5,6,2> + 3826656825U, // <6,2,1,6>: Cost 4 vsldoi12 <0,2,1,6>, <2,1,6,0> + 3373147838U, // <6,2,1,7>: Cost 5 vmrglw <2,u,6,1>, <2,3,2,7> + 2299404395U, // <6,2,1,u>: Cost 3 vmrglw <2,u,6,1>, LHS + 2657222758U, // <6,2,2,0>: Cost 3 vsldoi4 <6,6,2,2>, LHS + 3771164219U, // <6,2,2,1>: Cost 4 vsldoi8 <2,1,6,2>, <2,1,6,2> + 2766481000U, // <6,2,2,2>: Cost 3 vsldoi12 <2,4,5,6>, <2,2,2,2> + 2772452978U, // <6,2,2,3>: Cost 3 vsldoi12 <3,4,5,6>, <2,2,3,3> + 2657226038U, // <6,2,2,4>: Cost 3 vsldoi4 <6,6,2,2>, RHS + 3790407528U, // <6,2,2,5>: Cost 4 vsldoi8 <5,3,6,2>, <2,5,3,6> + 2252294074U, // <6,2,2,6>: Cost 3 vmrghw <6,2,7,3>, <2,6,3,7> + 2252294148U, // <6,2,2,7>: Cost 3 vmrghw <6,2,7,3>, <2,7,3,0> + 2772453023U, // <6,2,2,u>: Cost 3 vsldoi12 <3,4,5,6>, <2,2,u,3> + 2772453030U, // <6,2,3,0>: Cost 3 vsldoi12 <3,4,5,6>, <2,3,0,1> + 3834250930U, // <6,2,3,1>: Cost 4 vsldoi12 <1,4,5,6>, <2,3,1,4> + 2765596349U, // <6,2,3,2>: Cost 3 vsldoi12 <2,3,2,6>, <2,3,2,6> + 2301411430U, // <6,2,3,3>: Cost 3 vmrglw <3,2,6,3>, LHS + 2772453070U, // <6,2,3,4>: Cost 3 vsldoi12 <3,4,5,6>, <2,3,4,5> + 2765817560U, // <6,2,3,5>: Cost 3 vsldoi12 <2,3,5,6>, <2,3,5,6> + 2252933050U, // <6,2,3,6>: Cost 3 vmrghw <6,3,7,0>, <2,6,3,7> + 2796340968U, // <6,2,3,7>: Cost 3 vsldoi12 <7,4,5,6>, <2,3,7,4> + 2766038771U, // <6,2,3,u>: Cost 3 vsldoi12 <2,3,u,6>, <2,3,u,6> + 3725008998U, // <6,2,4,0>: Cost 4 vsldoi4 <5,6,2,4>, LHS + 3368530217U, // <6,2,4,1>: Cost 5 vmrglw <2,1,6,4>, <6,0,2,1> + 3840222989U, // <6,2,4,2>: Cost 4 vsldoi12 <2,4,5,6>, <2,4,2,5> + 2309382246U, // <6,2,4,3>: Cost 3 vmrglw <4,5,6,4>, LHS + 3725012278U, // <6,2,4,4>: Cost 4 vsldoi4 <5,6,2,4>, RHS + 2766481193U, // <6,2,4,5>: Cost 3 vsldoi12 <2,4,5,6>, <2,4,5,6> + 3842656049U, // <6,2,4,6>: Cost 4 vsldoi12 <2,u,2,6>, <2,4,6,5> + 3327010820U, // <6,2,4,7>: Cost 4 vmrghw <6,4,2,5>, <2,7,3,0> + 2766702404U, // <6,2,4,u>: Cost 3 vsldoi12 <2,4,u,6>, <2,4,u,6> + 3713073254U, // <6,2,5,0>: Cost 4 vsldoi4 <3,6,2,5>, LHS + 3789082310U, // <6,2,5,1>: Cost 4 vsldoi8 <5,1,6,2>, <5,1,6,2> + 3840665439U, // <6,2,5,2>: Cost 4 vsldoi12 <2,5,2,6>, <2,5,2,6> + 2766997352U, // <6,2,5,3>: Cost 3 vsldoi12 <2,5,3,6>, <2,5,3,6> + 3713076534U, // <6,2,5,4>: Cost 4 vsldoi4 <3,6,2,5>, RHS + 3791736842U, // <6,2,5,5>: Cost 4 vsldoi8 <5,5,6,2>, <5,5,6,2> + 3373180605U, // <6,2,5,6>: Cost 4 vmrglw <2,u,6,5>, <2,3,2,6> + 3793064108U, // <6,2,5,7>: Cost 4 vsldoi8 <5,7,6,2>, <5,7,6,2> + 2767366037U, // <6,2,5,u>: Cost 3 vsldoi12 <2,5,u,6>, <2,5,u,6> + 3701137510U, // <6,2,6,0>: Cost 4 vsldoi4 <1,6,2,6>, LHS + 3701138647U, // <6,2,6,1>: Cost 4 vsldoi4 <1,6,2,6>, <1,6,2,6> + 2254898792U, // <6,2,6,2>: Cost 3 vmrghw <6,6,6,6>, <2,2,2,2> + 1248264294U, // <6,2,6,3>: Cost 2 vmrglw <6,6,6,6>, LHS + 3701140790U, // <6,2,6,4>: Cost 4 vsldoi4 <1,6,2,6>, RHS + 3725029435U, // <6,2,6,5>: Cost 4 vsldoi4 <5,6,2,6>, <5,6,2,6> + 2254899130U, // <6,2,6,6>: Cost 3 vmrghw <6,6,6,6>, <2,6,3,7> + 2725294981U, // <6,2,6,7>: Cost 3 vsldoi8 <6,7,6,2>, <6,7,6,2> + 1248264299U, // <6,2,6,u>: Cost 2 vmrglw <6,6,6,6>, LHS + 2633375846U, // <6,2,7,0>: Cost 3 vsldoi4 <2,6,2,7>, LHS + 2309407468U, // <6,2,7,1>: Cost 3 vmrglw RHS, <1,0,2,1> + 1235666536U, // <6,2,7,2>: Cost 2 vmrglw RHS, <2,2,2,2> + 161923174U, // <6,2,7,3>: Cost 1 vmrglw RHS, LHS + 2633379126U, // <6,2,7,4>: Cost 3 vsldoi4 <2,6,2,7>, RHS + 2309407796U, // <6,2,7,5>: Cost 3 vmrglw RHS, <1,4,2,5> + 2309408445U, // <6,2,7,6>: Cost 3 vmrglw RHS, <2,3,2,6> + 2309407960U, // <6,2,7,7>: Cost 3 vmrglw RHS, <1,6,2,7> + 161923179U, // <6,2,7,u>: Cost 1 vmrglw RHS, LHS + 2633384038U, // <6,2,u,0>: Cost 3 vsldoi4 <2,6,2,u>, LHS + 2309415660U, // <6,2,u,1>: Cost 3 vmrglw RHS, <1,0,2,1> + 1235674728U, // <6,2,u,2>: Cost 2 vmrglw RHS, <2,2,2,2> + 161931366U, // <6,2,u,3>: Cost 1 vmrglw RHS, LHS + 2633387318U, // <6,2,u,4>: Cost 3 vsldoi4 <2,6,2,u>, RHS + 2769135725U, // <6,2,u,5>: Cost 3 vsldoi12 <2,u,5,6>, <2,u,5,6> + 2309416637U, // <6,2,u,6>: Cost 3 vmrglw RHS, <2,3,2,6> + 2309416152U, // <6,2,u,7>: Cost 3 vmrglw RHS, <1,6,2,7> + 161931371U, // <6,2,u,u>: Cost 1 vmrglw RHS, LHS + 3777806336U, // <6,3,0,0>: Cost 4 vsldoi8 <3,2,6,3>, <0,0,0,0> + 2704064614U, // <6,3,0,1>: Cost 3 vsldoi8 <3,2,6,3>, LHS + 3765862577U, // <6,3,0,2>: Cost 4 vsldoi8 <1,2,6,3>, <0,2,1,6> + 3843393708U, // <6,3,0,3>: Cost 4 vsldoi12 <3,0,3,6>, <3,0,3,6> + 2250516994U, // <6,3,0,4>: Cost 3 vmrghw <6,0,1,2>, <3,4,5,6> + 3725054014U, // <6,3,0,5>: Cost 4 vsldoi4 <5,6,3,0>, <5,6,3,0> + 3383093096U, // <6,3,0,6>: Cost 4 vmrglw <4,5,6,0>, <2,5,3,6> + 3368495034U, // <6,3,0,7>: Cost 4 vmrglw <2,1,6,0>, <2,6,3,7> + 2704065181U, // <6,3,0,u>: Cost 3 vsldoi8 <3,2,6,3>, LHS + 2251622550U, // <6,3,1,0>: Cost 3 vmrghw <6,1,7,2>, <3,0,1,2> + 3777807156U, // <6,3,1,1>: Cost 4 vsldoi8 <3,2,6,3>, <1,1,1,1> + 3765863348U, // <6,3,1,2>: Cost 4 vsldoi8 <1,2,6,3>, <1,2,6,3> + 3373147762U, // <6,3,1,3>: Cost 4 vmrglw <2,u,6,1>, <2,2,3,3> + 3834251525U, // <6,3,1,4>: Cost 4 vsldoi12 <1,4,5,6>, <3,1,4,5> + 3373147683U, // <6,3,1,5>: Cost 5 vmrglw <2,u,6,1>, <2,1,3,5> + 3391727545U, // <6,3,1,6>: Cost 4 vmrglw <6,0,6,1>, <2,6,3,6> + 2299406266U, // <6,3,1,7>: Cost 3 vmrglw <2,u,6,1>, <2,6,3,7> + 2251622550U, // <6,3,1,u>: Cost 3 vmrghw <6,1,7,2>, <3,0,1,2> + 2252294294U, // <6,3,2,0>: Cost 3 vmrghw <6,2,7,3>, <3,0,1,2> + 3326036198U, // <6,3,2,1>: Cost 4 vmrghw <6,2,7,3>, <3,1,1,1> + 3771836045U, // <6,3,2,2>: Cost 4 vsldoi8 <2,2,6,3>, <2,2,6,3> + 2252294556U, // <6,3,2,3>: Cost 3 vmrghw <6,2,7,3>, <3,3,3,3> + 2252294658U, // <6,3,2,4>: Cost 3 vmrghw <6,2,7,3>, <3,4,5,6> + 3840739677U, // <6,3,2,5>: Cost 4 vsldoi12 <2,5,3,6>, <3,2,5,3> + 2704066490U, // <6,3,2,6>: Cost 3 vsldoi8 <3,2,6,3>, <2,6,3,7> + 3368511418U, // <6,3,2,7>: Cost 4 vmrglw <2,1,6,2>, <2,6,3,7> + 2252294942U, // <6,3,2,u>: Cost 3 vmrghw <6,2,7,3>, <3,u,1,2> + 3707158630U, // <6,3,3,0>: Cost 4 vsldoi4 <2,6,3,3>, LHS + 3765864692U, // <6,3,3,1>: Cost 5 vsldoi8 <1,2,6,3>, <3,1,2,6> + 2704066918U, // <6,3,3,2>: Cost 3 vsldoi8 <3,2,6,3>, <3,2,6,3> + 2772453788U, // <6,3,3,3>: Cost 3 vsldoi12 <3,4,5,6>, <3,3,3,3> + 2772453799U, // <6,3,3,4>: Cost 3 vsldoi12 <3,4,5,6>, <3,3,4,5> + 3789752888U, // <6,3,3,5>: Cost 4 vsldoi8 <5,2,6,3>, <3,5,2,6> + 3840739770U, // <6,3,3,6>: Cost 4 vsldoi12 <2,5,3,6>, <3,3,6,6> + 2301413306U, // <6,3,3,7>: Cost 3 vmrglw <3,2,6,3>, <2,6,3,7> + 2775108043U, // <6,3,3,u>: Cost 3 vsldoi12 <3,u,5,6>, <3,3,u,5> + 2651340902U, // <6,3,4,0>: Cost 3 vsldoi4 <5,6,3,4>, LHS + 3846195674U, // <6,3,4,1>: Cost 4 vsldoi12 <3,4,5,6>, <3,4,1,2> + 3845974503U, // <6,3,4,2>: Cost 4 vsldoi12 <3,4,2,6>, <3,4,2,6> + 2651343362U, // <6,3,4,3>: Cost 3 vsldoi4 <5,6,3,4>, <3,4,5,6> + 2651344182U, // <6,3,4,4>: Cost 3 vsldoi4 <5,6,3,4>, RHS + 1698712066U, // <6,3,4,5>: Cost 2 vsldoi12 <3,4,5,6>, <3,4,5,6> + 3383125864U, // <6,3,4,6>: Cost 4 vmrglw <4,5,6,4>, <2,5,3,6> + 3368527802U, // <6,3,4,7>: Cost 4 vmrglw <2,1,6,4>, <2,6,3,7> + 1698933277U, // <6,3,4,u>: Cost 2 vsldoi12 <3,4,u,6>, <3,4,u,6> + 3373179798U, // <6,3,5,0>: Cost 4 vmrglw <2,u,6,5>, <1,2,3,0> + 3707176179U, // <6,3,5,1>: Cost 5 vsldoi4 <2,6,3,5>, <1,6,5,7> + 2716012312U, // <6,3,5,2>: Cost 3 vsldoi8 <5,2,6,3>, <5,2,6,3> + 3373180530U, // <6,3,5,3>: Cost 4 vmrglw <2,u,6,5>, <2,2,3,3> + 2254309890U, // <6,3,5,4>: Cost 3 vmrghw <6,5,7,6>, <3,4,5,6> + 3785773070U, // <6,3,5,5>: Cost 4 vsldoi8 <4,5,6,3>, <5,5,6,6> + 3840739932U, // <6,3,5,6>: Cost 4 vsldoi12 <2,5,3,6>, <3,5,6,6> + 2299439034U, // <6,3,5,7>: Cost 3 vmrglw <2,u,6,5>, <2,6,3,7> + 2719994110U, // <6,3,5,u>: Cost 3 vsldoi8 <5,u,6,3>, <5,u,6,3> + 2254899350U, // <6,3,6,0>: Cost 3 vmrghw <6,6,6,6>, <3,0,1,2> + 3328641254U, // <6,3,6,1>: Cost 4 vmrghw <6,6,6,6>, <3,1,1,1> + 2633443257U, // <6,3,6,2>: Cost 3 vsldoi4 <2,6,3,6>, <2,6,3,6> + 2254899612U, // <6,3,6,3>: Cost 3 vmrghw <6,6,6,6>, <3,3,3,3> + 2254899714U, // <6,3,6,4>: Cost 3 vmrghw <6,6,6,6>, <3,4,5,6> + 3785773772U, // <6,3,6,5>: Cost 4 vsldoi8 <4,5,6,3>, <6,5,3,6> + 2725966648U, // <6,3,6,6>: Cost 3 vsldoi8 <6,u,6,3>, <6,6,6,6> + 2322007994U, // <6,3,6,7>: Cost 3 vmrglw <6,6,6,6>, <2,6,3,7> + 2254899998U, // <6,3,6,u>: Cost 3 vmrghw <6,6,6,6>, <3,u,1,2> + 1559707750U, // <6,3,7,0>: Cost 2 vsldoi4 <2,6,3,7>, LHS + 2633450292U, // <6,3,7,1>: Cost 3 vsldoi4 <2,6,3,7>, <1,1,1,1> + 1559709626U, // <6,3,7,2>: Cost 2 vsldoi4 <2,6,3,7>, <2,6,3,7> + 1235666546U, // <6,3,7,3>: Cost 2 vmrglw RHS, <2,2,3,3> + 1559711030U, // <6,3,7,4>: Cost 2 vsldoi4 <2,6,3,7>, RHS + 2309408291U, // <6,3,7,5>: Cost 3 vmrglw RHS, <2,1,3,5> + 2633454152U, // <6,3,7,6>: Cost 3 vsldoi4 <2,6,3,7>, <6,3,7,0> + 1235666874U, // <6,3,7,7>: Cost 2 vmrglw RHS, <2,6,3,7> + 1559713582U, // <6,3,7,u>: Cost 2 vsldoi4 <2,6,3,7>, LHS + 1559715942U, // <6,3,u,0>: Cost 2 vsldoi4 <2,6,3,u>, LHS + 2633458484U, // <6,3,u,1>: Cost 3 vsldoi4 <2,6,3,u>, <1,1,1,1> + 1559717819U, // <6,3,u,2>: Cost 2 vsldoi4 <2,6,3,u>, <2,6,3,u> + 1235674738U, // <6,3,u,3>: Cost 2 vmrglw RHS, <2,2,3,3> + 1559719222U, // <6,3,u,4>: Cost 2 vsldoi4 <2,6,3,u>, RHS + 1701366598U, // <6,3,u,5>: Cost 2 vsldoi12 <3,u,5,6>, <3,u,5,6> + 2633462353U, // <6,3,u,6>: Cost 3 vsldoi4 <2,6,3,u>, <6,3,u,0> + 1235675066U, // <6,3,u,7>: Cost 2 vmrglw RHS, <2,6,3,7> + 1559721774U, // <6,3,u,u>: Cost 2 vsldoi4 <2,6,3,u>, LHS + 3785777152U, // <6,4,0,0>: Cost 4 vsldoi8 <4,5,6,4>, <0,0,0,0> + 2712035430U, // <6,4,0,1>: Cost 3 vsldoi8 <4,5,6,4>, LHS + 3771179185U, // <6,4,0,2>: Cost 4 vsldoi8 <2,1,6,4>, <0,2,1,6> + 3846196096U, // <6,4,0,3>: Cost 4 vsldoi12 <3,4,5,6>, <4,0,3,1> + 3785777490U, // <6,4,0,4>: Cost 4 vsldoi8 <4,5,6,4>, <0,4,1,5> + 2250517814U, // <6,4,0,5>: Cost 3 vmrghw <6,0,1,2>, RHS + 3324259703U, // <6,4,0,6>: Cost 4 vmrghw <6,0,1,2>, <4,6,5,0> + 3383092458U, // <6,4,0,7>: Cost 5 vmrglw <4,5,6,0>, <1,6,4,7> + 2712035997U, // <6,4,0,u>: Cost 3 vsldoi8 <4,5,6,4>, LHS + 3325356946U, // <6,4,1,0>: Cost 4 vmrghw <6,1,7,1>, <4,0,5,1> + 3785777972U, // <6,4,1,1>: Cost 4 vsldoi8 <4,5,6,4>, <1,1,1,1> + 3846196170U, // <6,4,1,2>: Cost 4 vsldoi12 <3,4,5,6>, <4,1,2,3> + 3325365380U, // <6,4,1,3>: Cost 4 vmrghw <6,1,7,2>, <4,3,5,0> + 3852168155U, // <6,4,1,4>: Cost 4 vsldoi12 <4,4,5,6>, <4,1,4,2> + 2251615542U, // <6,4,1,5>: Cost 3 vmrghw <6,1,7,1>, RHS + 3325357432U, // <6,4,1,6>: Cost 4 vmrghw <6,1,7,1>, <4,6,5,1> + 3870084088U, // <6,4,1,7>: Cost 4 vsldoi12 <7,4,5,6>, <4,1,7,4> + 2251615785U, // <6,4,1,u>: Cost 3 vmrghw <6,1,7,1>, RHS + 2252295058U, // <6,4,2,0>: Cost 3 vmrghw <6,2,7,3>, <4,0,5,1> + 3771180605U, // <6,4,2,1>: Cost 4 vsldoi8 <2,1,6,4>, <2,1,6,4> + 3785778792U, // <6,4,2,2>: Cost 4 vsldoi8 <4,5,6,4>, <2,2,2,2> + 3777816253U, // <6,4,2,3>: Cost 4 vsldoi8 <3,2,6,4>, <2,3,2,6> + 2252295376U, // <6,4,2,4>: Cost 3 vmrghw <6,2,7,3>, <4,4,4,4> + 1178553654U, // <6,4,2,5>: Cost 2 vmrghw <6,2,7,3>, RHS + 2252295545U, // <6,4,2,6>: Cost 3 vmrghw <6,2,7,3>, <4,6,5,2> + 3326037448U, // <6,4,2,7>: Cost 4 vmrghw <6,2,7,3>, <4,7,5,0> + 1178553897U, // <6,4,2,u>: Cost 2 vmrghw <6,2,7,3>, RHS + 3785779350U, // <6,4,3,0>: Cost 4 vsldoi8 <4,5,6,4>, <3,0,1,2> + 3383118648U, // <6,4,3,1>: Cost 4 vmrglw <4,5,6,3>, <3,u,4,1> + 3777816935U, // <6,4,3,2>: Cost 4 vsldoi8 <3,2,6,4>, <3,2,6,4> + 3785779612U, // <6,4,3,3>: Cost 4 vsldoi8 <4,5,6,4>, <3,3,3,3> + 2712037890U, // <6,4,3,4>: Cost 3 vsldoi8 <4,5,6,4>, <3,4,5,6> + 2252754230U, // <6,4,3,5>: Cost 3 vmrghw <6,3,4,5>, RHS + 3784452764U, // <6,4,3,6>: Cost 4 vsldoi8 <4,3,6,4>, <3,6,4,7> + 3801705178U, // <6,4,3,7>: Cost 4 vsldoi8 <7,2,6,4>, <3,7,2,6> + 2252754473U, // <6,4,3,u>: Cost 3 vmrghw <6,3,4,5>, RHS + 3787770770U, // <6,4,4,0>: Cost 4 vsldoi8 <4,u,6,4>, <4,0,5,1> + 3383126840U, // <6,4,4,1>: Cost 4 vmrglw <4,5,6,4>, <3,u,4,1> + 3327380534U, // <6,4,4,2>: Cost 4 vmrghw <6,4,7,5>, <4,2,5,3> + 3784453265U, // <6,4,4,3>: Cost 4 vsldoi8 <4,3,6,4>, <4,3,6,4> + 2253630672U, // <6,4,4,4>: Cost 3 vmrghw <6,4,7,4>, <4,4,4,4> + 2778426587U, // <6,4,4,5>: Cost 3 vsldoi12 <4,4,5,6>, <4,4,5,6> + 3383128789U, // <6,4,4,6>: Cost 4 vmrglw <4,5,6,4>, <6,5,4,6> + 3381799580U, // <6,4,4,7>: Cost 4 vmrglw <4,3,6,4>, <3,6,4,7> + 2778647798U, // <6,4,4,u>: Cost 3 vsldoi12 <4,4,u,6>, <4,4,u,6> + 2651422822U, // <6,4,5,0>: Cost 3 vsldoi4 <5,6,4,5>, LHS + 3701277928U, // <6,4,5,1>: Cost 4 vsldoi4 <1,6,4,5>, <1,6,4,5> + 3701278650U, // <6,4,5,2>: Cost 4 vsldoi4 <1,6,4,5>, <2,6,3,7> + 2651425282U, // <6,4,5,3>: Cost 3 vsldoi4 <5,6,4,5>, <3,4,5,6> + 2651426102U, // <6,4,5,4>: Cost 3 vsldoi4 <5,6,4,5>, RHS + 2651426892U, // <6,4,5,5>: Cost 3 vsldoi4 <5,6,4,5>, <5,6,4,5> + 1698712886U, // <6,4,5,6>: Cost 2 vsldoi12 <3,4,5,6>, RHS + 3725169658U, // <6,4,5,7>: Cost 4 vsldoi4 <5,6,4,5>, <7,0,1,2> + 1698712904U, // <6,4,5,u>: Cost 2 vsldoi12 <3,4,5,6>, RHS + 2254900114U, // <6,4,6,0>: Cost 3 vmrghw <6,6,6,6>, <4,0,5,1> + 3389115192U, // <6,4,6,1>: Cost 4 vmrglw <5,5,6,6>, <3,u,4,1> + 3785781727U, // <6,4,6,2>: Cost 4 vsldoi8 <4,5,6,4>, <6,2,4,3> + 3785781810U, // <6,4,6,3>: Cost 4 vsldoi8 <4,5,6,4>, <6,3,4,5> + 2254900432U, // <6,4,6,4>: Cost 3 vmrghw <6,6,6,6>, <4,4,4,4> + 1181158710U, // <6,4,6,5>: Cost 2 vmrghw <6,6,6,6>, RHS + 2254900605U, // <6,4,6,6>: Cost 3 vmrghw <6,6,6,6>, <4,6,5,6> + 3787772750U, // <6,4,6,7>: Cost 4 vsldoi8 <4,u,6,4>, <6,7,0,1> + 1181158953U, // <6,4,6,u>: Cost 2 vmrghw <6,6,6,6>, RHS + 2639495270U, // <6,4,7,0>: Cost 3 vsldoi4 <3,6,4,7>, LHS + 2639496090U, // <6,4,7,1>: Cost 3 vsldoi4 <3,6,4,7>, <1,2,3,4> + 3707267011U, // <6,4,7,2>: Cost 4 vsldoi4 <2,6,4,7>, <2,6,4,7> + 2639497884U, // <6,4,7,3>: Cost 3 vsldoi4 <3,6,4,7>, <3,6,4,7> + 1237658832U, // <6,4,7,4>: Cost 2 vmrglw RHS, <4,4,4,4> + 1235666638U, // <6,4,7,5>: Cost 2 vmrglw RHS, <2,3,4,5> + 3713241753U, // <6,4,7,6>: Cost 4 vsldoi4 <3,6,4,7>, <6,4,7,0> + 2309409436U, // <6,4,7,7>: Cost 3 vmrglw RHS, <3,6,4,7> + 1235666641U, // <6,4,7,u>: Cost 2 vmrglw RHS, <2,3,4,u> + 2639503462U, // <6,4,u,0>: Cost 3 vsldoi4 <3,6,4,u>, LHS + 2639504282U, // <6,4,u,1>: Cost 3 vsldoi4 <3,6,4,u>, <1,2,3,4> + 3701303226U, // <6,4,u,2>: Cost 4 vsldoi4 <1,6,4,u>, <2,6,3,7> + 2639506077U, // <6,4,u,3>: Cost 3 vsldoi4 <3,6,4,u>, <3,6,4,u> + 1235676368U, // <6,4,u,4>: Cost 2 vmrglw RHS, <4,4,4,4> + 1235674830U, // <6,4,u,5>: Cost 2 vmrglw RHS, <2,3,4,5> + 1698713129U, // <6,4,u,6>: Cost 2 vsldoi12 <3,4,5,6>, RHS + 2309417628U, // <6,4,u,7>: Cost 3 vmrglw RHS, <3,6,4,7> + 1698713147U, // <6,4,u,u>: Cost 2 vsldoi12 <3,4,5,6>, RHS + 3775832064U, // <6,5,0,0>: Cost 4 vsldoi8 <2,u,6,5>, <0,0,0,0> + 2702090342U, // <6,5,0,1>: Cost 3 vsldoi8 <2,u,6,5>, LHS + 3775832241U, // <6,5,0,2>: Cost 4 vsldoi8 <2,u,6,5>, <0,2,1,6> + 3719227906U, // <6,5,0,3>: Cost 4 vsldoi4 <4,6,5,0>, <3,4,5,6> + 3775832402U, // <6,5,0,4>: Cost 4 vsldoi8 <2,u,6,5>, <0,4,1,5> + 3385085146U, // <6,5,0,5>: Cost 4 vmrglw <4,u,6,0>, <4,4,5,5> + 2309351938U, // <6,5,0,6>: Cost 3 vmrglw <4,5,6,0>, <3,4,5,6> + 3376459134U, // <6,5,0,7>: Cost 5 vmrglw <3,4,6,0>, <4,6,5,7> + 2702090909U, // <6,5,0,u>: Cost 3 vsldoi8 <2,u,6,5>, LHS + 3719233546U, // <6,5,1,0>: Cost 4 vsldoi4 <4,6,5,1>, <0,0,1,1> + 3775832884U, // <6,5,1,1>: Cost 4 vsldoi8 <2,u,6,5>, <1,1,1,1> + 3775832982U, // <6,5,1,2>: Cost 4 vsldoi8 <2,u,6,5>, <1,2,3,0> + 3846196909U, // <6,5,1,3>: Cost 4 vsldoi12 <3,4,5,6>, <5,1,3,4> + 3719236984U, // <6,5,1,4>: Cost 4 vsldoi4 <4,6,5,1>, <4,6,5,1> + 3856150209U, // <6,5,1,5>: Cost 4 vsldoi12 <5,1,5,6>, <5,1,5,6> + 3834252997U, // <6,5,1,6>: Cost 4 vsldoi12 <1,4,5,6>, <5,1,6,1> + 3870084817U, // <6,5,1,7>: Cost 4 vsldoi12 <7,4,5,6>, <5,1,7,4> + 3769861532U, // <6,5,1,u>: Cost 4 vsldoi8 <1,u,6,5>, <1,u,6,5> + 2645500006U, // <6,5,2,0>: Cost 3 vsldoi4 <4,6,5,2>, LHS + 3719242548U, // <6,5,2,1>: Cost 4 vsldoi4 <4,6,5,2>, <1,1,1,1> + 3775833704U, // <6,5,2,2>: Cost 4 vsldoi8 <2,u,6,5>, <2,2,2,2> + 3775833766U, // <6,5,2,3>: Cost 4 vsldoi8 <2,u,6,5>, <2,3,0,1> + 2645503353U, // <6,5,2,4>: Cost 3 vsldoi4 <4,6,5,2>, <4,6,5,2> + 2252296196U, // <6,5,2,5>: Cost 3 vmrghw <6,2,7,3>, <5,5,5,5> + 2702092218U, // <6,5,2,6>: Cost 3 vsldoi8 <2,u,6,5>, <2,6,3,7> + 3719246842U, // <6,5,2,7>: Cost 4 vsldoi4 <4,6,5,2>, <7,0,1,2> + 2702092405U, // <6,5,2,u>: Cost 3 vsldoi8 <2,u,6,5>, <2,u,6,5> + 3775834262U, // <6,5,3,0>: Cost 4 vsldoi8 <2,u,6,5>, <3,0,1,2> + 3777161495U, // <6,5,3,1>: Cost 4 vsldoi8 <3,1,6,5>, <3,1,6,5> + 3775834470U, // <6,5,3,2>: Cost 4 vsldoi8 <2,u,6,5>, <3,2,6,3> + 3775834524U, // <6,5,3,3>: Cost 4 vsldoi8 <2,u,6,5>, <3,3,3,3> + 3775834626U, // <6,5,3,4>: Cost 4 vsldoi8 <2,u,6,5>, <3,4,5,6> + 3385109722U, // <6,5,3,5>: Cost 4 vmrglw <4,u,6,3>, <4,4,5,5> + 2309376514U, // <6,5,3,6>: Cost 3 vmrglw <4,5,6,3>, <3,4,5,6> + 3775834819U, // <6,5,3,7>: Cost 4 vsldoi8 <2,u,6,5>, <3,7,0,1> + 2309376514U, // <6,5,3,u>: Cost 3 vmrglw <4,5,6,3>, <3,4,5,6> + 3719258214U, // <6,5,4,0>: Cost 4 vsldoi4 <4,6,5,4>, LHS + 3385117586U, // <6,5,4,1>: Cost 4 vmrglw <4,u,6,4>, <4,0,5,1> + 3327242008U, // <6,5,4,2>: Cost 4 vmrghw <6,4,5,6>, <5,2,6,3> + 3719260674U, // <6,5,4,3>: Cost 4 vsldoi4 <4,6,5,4>, <3,4,5,6> + 3719261563U, // <6,5,4,4>: Cost 4 vsldoi4 <4,6,5,4>, <4,6,5,4> + 2702093622U, // <6,5,4,5>: Cost 3 vsldoi8 <2,u,6,5>, RHS + 2309384706U, // <6,5,4,6>: Cost 3 vmrglw <4,5,6,4>, <3,4,5,6> + 3870085060U, // <6,5,4,7>: Cost 4 vsldoi12 <7,4,5,6>, <5,4,7,4> + 2702093865U, // <6,5,4,u>: Cost 3 vsldoi8 <2,u,6,5>, RHS + 3719266406U, // <6,5,5,0>: Cost 4 vsldoi4 <4,6,5,5>, LHS + 3789106889U, // <6,5,5,1>: Cost 4 vsldoi8 <5,1,6,5>, <5,1,6,5> + 3785789208U, // <6,5,5,2>: Cost 4 vsldoi8 <4,5,6,5>, <5,2,6,3> + 3373183950U, // <6,5,5,3>: Cost 4 vmrglw <2,u,6,5>, <6,u,5,3> + 2717355964U, // <6,5,5,4>: Cost 3 vsldoi8 <5,4,6,5>, <5,4,6,5> + 2791772164U, // <6,5,5,5>: Cost 3 vsldoi12 <6,6,6,6>, <5,5,5,5> + 2772455438U, // <6,5,5,6>: Cost 3 vsldoi12 <3,4,5,6>, <5,5,6,6> + 3373183549U, // <6,5,5,7>: Cost 4 vmrglw <2,u,6,5>, <6,3,5,7> + 2720010496U, // <6,5,5,u>: Cost 3 vsldoi8 <5,u,6,5>, <5,u,6,5> + 2772455460U, // <6,5,6,0>: Cost 3 vsldoi12 <3,4,5,6>, <5,6,0,1> + 2322008978U, // <6,5,6,1>: Cost 3 vmrglw <6,6,6,6>, <4,0,5,1> + 3840225335U, // <6,5,6,2>: Cost 4 vsldoi12 <2,4,5,6>, <5,6,2,2> + 2772455490U, // <6,5,6,3>: Cost 3 vsldoi12 <3,4,5,6>, <5,6,3,4> + 2772455500U, // <6,5,6,4>: Cost 3 vsldoi12 <3,4,5,6>, <5,6,4,5> + 2254901252U, // <6,5,6,5>: Cost 3 vmrghw <6,6,6,6>, <5,5,5,5> + 2772455520U, // <6,5,6,6>: Cost 3 vsldoi12 <3,4,5,6>, <5,6,6,7> + 2785874024U, // <6,5,6,7>: Cost 3 vsldoi12 <5,6,7,6>, <5,6,7,6> + 2772455532U, // <6,5,6,u>: Cost 3 vsldoi12 <3,4,5,6>, <5,6,u,1> + 2627625062U, // <6,5,7,0>: Cost 3 vsldoi4 <1,6,5,7>, LHS + 1235667858U, // <6,5,7,1>: Cost 2 vmrglw RHS, <4,0,5,1> + 2309409278U, // <6,5,7,2>: Cost 3 vmrglw RHS, <3,4,5,2> + 2309407659U, // <6,5,7,3>: Cost 3 vmrglw RHS, <1,2,5,3> + 2627628342U, // <6,5,7,4>: Cost 3 vsldoi4 <1,6,5,7>, RHS + 1235668186U, // <6,5,7,5>: Cost 2 vmrglw RHS, <4,4,5,5> + 1235667458U, // <6,5,7,6>: Cost 2 vmrglw RHS, <3,4,5,6> + 2309407987U, // <6,5,7,7>: Cost 3 vmrglw RHS, <1,6,5,7> + 1235667460U, // <6,5,7,u>: Cost 2 vmrglw RHS, <3,4,5,u> + 2627633254U, // <6,5,u,0>: Cost 3 vsldoi4 <1,6,5,u>, LHS + 1235676050U, // <6,5,u,1>: Cost 2 vmrglw RHS, <4,0,5,1> + 2309417470U, // <6,5,u,2>: Cost 3 vmrglw RHS, <3,4,5,2> + 2309415851U, // <6,5,u,3>: Cost 3 vmrglw RHS, <1,2,5,3> + 2627636534U, // <6,5,u,4>: Cost 3 vsldoi4 <1,6,5,u>, RHS + 1235676378U, // <6,5,u,5>: Cost 2 vmrglw RHS, <4,4,5,5> + 1235675650U, // <6,5,u,6>: Cost 2 vmrglw RHS, <3,4,5,6> + 2309416179U, // <6,5,u,7>: Cost 3 vmrglw RHS, <1,6,5,7> + 1235675652U, // <6,5,u,u>: Cost 2 vmrglw RHS, <3,4,5,u> + 2309352751U, // <6,6,0,0>: Cost 3 vmrglw <4,5,6,0>, <4,5,6,0> + 1650917478U, // <6,6,0,1>: Cost 2 vsldoi8 <6,6,6,6>, LHS + 2250584570U, // <6,6,0,2>: Cost 3 vmrghw <6,0,2,1>, <6,2,7,3> + 3846197554U, // <6,6,0,3>: Cost 4 vsldoi12 <3,4,5,6>, <6,0,3,1> + 2724659538U, // <6,6,0,4>: Cost 3 vsldoi8 <6,6,6,6>, <0,4,1,5> + 3725275225U, // <6,6,0,5>: Cost 4 vsldoi4 <5,6,6,0>, <5,6,6,0> + 2791772493U, // <6,6,0,6>: Cost 3 vsldoi12 <6,6,6,6>, <6,0,6,1> + 2309352758U, // <6,6,0,7>: Cost 3 vmrglw <4,5,6,0>, RHS + 1650918045U, // <6,6,0,u>: Cost 2 vsldoi8 <6,6,6,6>, LHS + 3325358368U, // <6,6,1,0>: Cost 4 vmrghw <6,1,7,1>, <6,0,1,1> + 2299406449U, // <6,6,1,1>: Cost 3 vmrglw <2,u,6,1>, <2,u,6,1> + 2724660118U, // <6,6,1,2>: Cost 3 vsldoi8 <6,6,6,6>, <1,2,3,0> + 3373148518U, // <6,6,1,3>: Cost 4 vmrglw <2,u,6,1>, <3,2,6,3> + 3834253712U, // <6,6,1,4>: Cost 4 vsldoi12 <1,4,5,6>, <6,1,4,5> + 3373147953U, // <6,6,1,5>: Cost 4 vmrglw <2,u,6,1>, <2,4,6,5> + 2323297080U, // <6,6,1,6>: Cost 3 vmrglw <6,u,6,1>, <6,6,6,6> + 2299407670U, // <6,6,1,7>: Cost 3 vmrglw <2,u,6,1>, RHS + 2299407671U, // <6,6,1,u>: Cost 3 vmrglw <2,u,6,1>, RHS + 2252296489U, // <6,6,2,0>: Cost 3 vmrghw <6,2,7,3>, <6,0,2,1> + 3326038394U, // <6,6,2,1>: Cost 4 vmrghw <6,2,7,3>, <6,1,2,1> + 1178554874U, // <6,6,2,2>: Cost 2 vmrghw <6,2,7,3>, <6,2,7,3> + 2724660902U, // <6,6,2,3>: Cost 3 vsldoi8 <6,6,6,6>, <2,3,0,1> + 2252296817U, // <6,6,2,4>: Cost 3 vmrghw <6,2,7,3>, <6,4,2,5> + 3840741864U, // <6,6,2,5>: Cost 4 vsldoi12 <2,5,3,6>, <6,2,5,3> + 2252296976U, // <6,6,2,6>: Cost 3 vmrghw <6,2,7,3>, <6,6,2,2> + 2785874426U, // <6,6,2,7>: Cost 3 vsldoi12 <5,6,7,6>, <6,2,7,3> + 1178554874U, // <6,6,2,u>: Cost 2 vmrghw <6,2,7,3>, <6,2,7,3> + 2724661398U, // <6,6,3,0>: Cost 3 vsldoi8 <6,6,6,6>, <3,0,1,2> + 3375154665U, // <6,6,3,1>: Cost 4 vmrglw <3,2,6,3>, <2,0,6,1> + 3375154909U, // <6,6,3,2>: Cost 4 vmrglw <3,2,6,3>, <2,3,6,2> + 2301413734U, // <6,6,3,3>: Cost 3 vmrglw <3,2,6,3>, <3,2,6,3> + 2772455986U, // <6,6,3,4>: Cost 3 vsldoi12 <3,4,5,6>, <6,3,4,5> + 3375154993U, // <6,6,3,5>: Cost 4 vmrglw <3,2,6,3>, <2,4,6,5> + 2323313464U, // <6,6,3,6>: Cost 3 vmrglw <6,u,6,3>, <6,6,6,6> + 2301414710U, // <6,6,3,7>: Cost 3 vmrglw <3,2,6,3>, RHS + 2301414711U, // <6,6,3,u>: Cost 3 vmrglw <3,2,6,3>, RHS + 2724662162U, // <6,6,4,0>: Cost 3 vsldoi8 <6,6,6,6>, <4,0,5,1> + 3326939559U, // <6,6,4,1>: Cost 4 vmrghw <6,4,1,5>, <6,1,7,1> + 2253271546U, // <6,6,4,2>: Cost 3 vmrghw <6,4,2,5>, <6,2,7,3> + 3383127346U, // <6,6,4,3>: Cost 4 vmrglw <4,5,6,4>, <4,5,6,3> + 2309385523U, // <6,6,4,4>: Cost 3 vmrglw <4,5,6,4>, <4,5,6,4> + 1650920758U, // <6,6,4,5>: Cost 2 vsldoi8 <6,6,6,6>, RHS + 2724662653U, // <6,6,4,6>: Cost 3 vsldoi8 <6,6,6,6>, <4,6,5,6> + 2309385526U, // <6,6,4,7>: Cost 3 vmrglw <4,5,6,4>, RHS + 1650921001U, // <6,6,4,u>: Cost 2 vsldoi8 <6,6,6,6>, RHS + 3725312102U, // <6,6,5,0>: Cost 4 vsldoi4 <5,6,6,5>, LHS + 3373180393U, // <6,6,5,1>: Cost 4 vmrglw <2,u,6,5>, <2,0,6,1> + 3791769368U, // <6,6,5,2>: Cost 4 vsldoi8 <5,5,6,6>, <5,2,6,3> + 3373181286U, // <6,6,5,3>: Cost 4 vmrglw <2,u,6,5>, <3,2,6,3> + 3725315382U, // <6,6,5,4>: Cost 4 vsldoi4 <5,6,6,5>, RHS + 2299439221U, // <6,6,5,5>: Cost 3 vmrglw <2,u,6,5>, <2,u,6,5> + 2724663394U, // <6,6,5,6>: Cost 3 vsldoi8 <6,6,6,6>, <5,6,7,0> + 2299440438U, // <6,6,5,7>: Cost 3 vmrglw <2,u,6,5>, RHS + 2299440439U, // <6,6,5,u>: Cost 3 vmrglw <2,u,6,5>, RHS + 1583808614U, // <6,6,6,0>: Cost 2 vsldoi4 <6,6,6,6>, LHS + 2322010445U, // <6,6,6,1>: Cost 3 vmrglw <6,6,6,6>, <6,0,6,1> + 2254574074U, // <6,6,6,2>: Cost 3 vmrghw <6,6,2,2>, <6,2,7,3> + 2322010609U, // <6,6,6,3>: Cost 3 vmrglw <6,6,6,6>, <6,2,6,3> + 1583811894U, // <6,6,6,4>: Cost 2 vsldoi4 <6,6,6,6>, RHS + 2322010773U, // <6,6,6,5>: Cost 3 vmrglw <6,6,6,6>, <6,4,6,5> + 363253046U, // <6,6,6,6>: Cost 1 vspltisw2 RHS + 1248267574U, // <6,6,6,7>: Cost 2 vmrglw <6,6,6,6>, RHS + 363253046U, // <6,6,6,u>: Cost 1 vspltisw2 RHS + 2309410095U, // <6,6,7,0>: Cost 3 vmrglw RHS, <4,5,6,0> + 2309408233U, // <6,6,7,1>: Cost 3 vmrglw RHS, <2,0,6,1> + 2311402373U, // <6,6,7,2>: Cost 3 vmrglw RHS, <6,7,6,2> + 2309409126U, // <6,6,7,3>: Cost 3 vmrglw RHS, <3,2,6,3> + 2309410099U, // <6,6,7,4>: Cost 3 vmrglw RHS, <4,5,6,4> + 2309408561U, // <6,6,7,5>: Cost 3 vmrglw RHS, <2,4,6,5> + 1237660472U, // <6,6,7,6>: Cost 2 vmrglw RHS, <6,6,6,6> + 161926454U, // <6,6,7,7>: Cost 1 vmrglw RHS, RHS + 161926455U, // <6,6,7,u>: Cost 1 vmrglw RHS, RHS + 1583808614U, // <6,6,u,0>: Cost 2 vsldoi4 <6,6,6,6>, LHS + 1650923310U, // <6,6,u,1>: Cost 2 vsldoi8 <6,6,6,6>, LHS + 1178554874U, // <6,6,u,2>: Cost 2 vmrghw <6,2,7,3>, <6,2,7,3> + 2309417318U, // <6,6,u,3>: Cost 3 vmrglw RHS, <3,2,6,3> + 1583811894U, // <6,6,u,4>: Cost 2 vsldoi4 <6,6,6,6>, RHS + 1650923674U, // <6,6,u,5>: Cost 2 vsldoi8 <6,6,6,6>, RHS + 363253046U, // <6,6,u,6>: Cost 1 vspltisw2 RHS + 161934646U, // <6,6,u,7>: Cost 1 vmrglw RHS, RHS + 161934647U, // <6,6,u,u>: Cost 1 vmrglw RHS, RHS + 1638318080U, // <6,7,0,0>: Cost 2 vsldoi8 RHS, <0,0,0,0> + 564576358U, // <6,7,0,1>: Cost 1 vsldoi8 RHS, LHS + 2712060077U, // <6,7,0,2>: Cost 3 vsldoi8 RHS, <0,2,1,2> + 2712060156U, // <6,7,0,3>: Cost 3 vsldoi8 RHS, <0,3,1,0> + 1638318418U, // <6,7,0,4>: Cost 2 vsldoi8 RHS, <0,4,1,5> + 1577865314U, // <6,7,0,5>: Cost 2 vsldoi4 <5,6,7,0>, <5,6,7,0> + 2712060406U, // <6,7,0,6>: Cost 3 vsldoi8 RHS, <0,6,1,7> + 2651608058U, // <6,7,0,7>: Cost 3 vsldoi4 <5,6,7,0>, <7,0,1,2> + 564576925U, // <6,7,0,u>: Cost 1 vsldoi8 RHS, LHS + 2712060643U, // <6,7,1,0>: Cost 3 vsldoi8 RHS, <1,0,1,1> + 1638318900U, // <6,7,1,1>: Cost 2 vsldoi8 RHS, <1,1,1,1> + 1638318998U, // <6,7,1,2>: Cost 2 vsldoi8 RHS, <1,2,3,0> + 3766559753U, // <6,7,1,3>: Cost 4 vsldoi8 <1,3,6,7>, <1,3,6,7> + 2712060971U, // <6,7,1,4>: Cost 3 vsldoi8 RHS, <1,4,1,5> + 2712061039U, // <6,7,1,5>: Cost 3 vsldoi8 RHS, <1,5,0,1> + 2712061135U, // <6,7,1,6>: Cost 3 vsldoi8 RHS, <1,6,1,7> + 3373148612U, // <6,7,1,7>: Cost 4 vmrglw <2,u,6,1>, <3,3,7,7> + 1638319484U, // <6,7,1,u>: Cost 2 vsldoi8 RHS, <1,u,3,0> + 2712061373U, // <6,7,2,0>: Cost 3 vsldoi8 RHS, <2,0,1,2> + 2712061471U, // <6,7,2,1>: Cost 3 vsldoi8 RHS, <2,1,3,1> + 1638319720U, // <6,7,2,2>: Cost 2 vsldoi8 RHS, <2,2,2,2> + 1638319782U, // <6,7,2,3>: Cost 2 vsldoi8 RHS, <2,3,0,1> + 2712061709U, // <6,7,2,4>: Cost 3 vsldoi8 RHS, <2,4,2,5> + 2712061800U, // <6,7,2,5>: Cost 3 vsldoi8 RHS, <2,5,3,6> + 1638320058U, // <6,7,2,6>: Cost 2 vsldoi8 RHS, <2,6,3,7> + 2252297836U, // <6,7,2,7>: Cost 3 vmrghw <6,2,7,3>, <7,7,7,7> + 1638320187U, // <6,7,2,u>: Cost 2 vsldoi8 RHS, <2,u,0,1> + 1638320278U, // <6,7,3,0>: Cost 2 vsldoi8 RHS, <3,0,1,2> + 2712062182U, // <6,7,3,1>: Cost 3 vsldoi8 RHS, <3,1,1,1> + 2712062256U, // <6,7,3,2>: Cost 3 vsldoi8 RHS, <3,2,0,3> + 1638320540U, // <6,7,3,3>: Cost 2 vsldoi8 RHS, <3,3,3,3> + 1638320642U, // <6,7,3,4>: Cost 2 vsldoi8 RHS, <3,4,5,6> + 2712062546U, // <6,7,3,5>: Cost 3 vsldoi8 RHS, <3,5,5,5> + 2712062584U, // <6,7,3,6>: Cost 3 vsldoi8 RHS, <3,6,0,7> + 2712062659U, // <6,7,3,7>: Cost 3 vsldoi8 RHS, <3,7,0,1> + 1638320926U, // <6,7,3,u>: Cost 2 vsldoi8 RHS, <3,u,1,2> + 1638321042U, // <6,7,4,0>: Cost 2 vsldoi8 RHS, <4,0,5,1> + 2712062922U, // <6,7,4,1>: Cost 3 vsldoi8 RHS, <4,1,2,3> + 2712063029U, // <6,7,4,2>: Cost 3 vsldoi8 RHS, <4,2,5,2> + 2712063108U, // <6,7,4,3>: Cost 3 vsldoi8 RHS, <4,3,5,0> + 1638321360U, // <6,7,4,4>: Cost 2 vsldoi8 RHS, <4,4,4,4> + 564579638U, // <6,7,4,5>: Cost 1 vsldoi8 RHS, RHS + 2712063357U, // <6,7,4,6>: Cost 3 vsldoi8 RHS, <4,6,5,6> + 2712063439U, // <6,7,4,7>: Cost 3 vsldoi8 RHS, <4,7,5,7> + 564579881U, // <6,7,4,u>: Cost 1 vsldoi8 RHS, RHS + 2712063560U, // <6,7,5,0>: Cost 3 vsldoi8 RHS, <5,0,1,2> + 2714054287U, // <6,7,5,1>: Cost 3 vsldoi8 RHS, <5,1,0,1> + 2712063742U, // <6,7,5,2>: Cost 3 vsldoi8 RHS, <5,2,3,4> + 3373181295U, // <6,7,5,3>: Cost 4 vmrglw <2,u,6,5>, <3,2,7,3> + 2712063924U, // <6,7,5,4>: Cost 3 vsldoi8 RHS, <5,4,5,6> + 1638322180U, // <6,7,5,5>: Cost 2 vsldoi8 RHS, <5,5,5,5> + 1638322274U, // <6,7,5,6>: Cost 2 vsldoi8 RHS, <5,6,7,0> + 3373181380U, // <6,7,5,7>: Cost 4 vmrglw <2,u,6,5>, <3,3,7,7> + 1640313092U, // <6,7,5,u>: Cost 2 vsldoi8 RHS, <5,u,7,0> + 2712064289U, // <6,7,6,0>: Cost 3 vsldoi8 RHS, <6,0,1,2> + 2712064423U, // <6,7,6,1>: Cost 3 vsldoi8 RHS, <6,1,7,1> + 1638322682U, // <6,7,6,2>: Cost 2 vsldoi8 RHS, <6,2,7,3> + 2712064562U, // <6,7,6,3>: Cost 3 vsldoi8 RHS, <6,3,4,5> + 2712064653U, // <6,7,6,4>: Cost 3 vsldoi8 RHS, <6,4,5,6> + 2712064747U, // <6,7,6,5>: Cost 3 vsldoi8 RHS, <6,5,7,1> + 1638323000U, // <6,7,6,6>: Cost 2 vsldoi8 RHS, <6,6,6,6> + 1638323022U, // <6,7,6,7>: Cost 2 vsldoi8 RHS, <6,7,0,1> + 1638323168U, // <6,7,6,u>: Cost 2 vsldoi8 RHS, <6,u,7,3> + 1237659746U, // <6,7,7,0>: Cost 2 vmrglw RHS, <5,6,7,0> + 2309411158U, // <6,7,7,1>: Cost 3 vmrglw RHS, <6,0,7,1> + 2639718330U, // <6,7,7,2>: Cost 3 vsldoi4 <3,6,7,7>, <2,6,3,7> + 1235669498U, // <6,7,7,3>: Cost 2 vmrglw RHS, <6,2,7,3> + 1237659750U, // <6,7,7,4>: Cost 2 vmrglw RHS, <5,6,7,4> + 2309411243U, // <6,7,7,5>: Cost 3 vmrglw RHS, <6,1,7,5> + 1583895362U, // <6,7,7,6>: Cost 2 vsldoi4 <6,6,7,7>, <6,6,7,7> + 1235669826U, // <6,7,7,7>: Cost 2 vmrglw RHS, <6,6,7,7> + 1235669503U, // <6,7,7,u>: Cost 2 vmrglw RHS, <6,2,7,u> + 1638323923U, // <6,7,u,0>: Cost 2 vsldoi8 RHS, + 564582190U, // <6,7,u,1>: Cost 1 vsldoi8 RHS, LHS + 1638324101U, // <6,7,u,2>: Cost 2 vsldoi8 RHS, + 1638324156U, // <6,7,u,3>: Cost 2 vsldoi8 RHS, + 1638324287U, // <6,7,u,4>: Cost 2 vsldoi8 RHS, + 564582554U, // <6,7,u,5>: Cost 1 vsldoi8 RHS, RHS + 1638324432U, // <6,7,u,6>: Cost 2 vsldoi8 RHS, + 1235678018U, // <6,7,u,7>: Cost 2 vmrglw RHS, <6,6,7,7> + 564582757U, // <6,7,u,u>: Cost 1 vsldoi8 RHS, LHS + 1638326272U, // <6,u,0,0>: Cost 2 vsldoi8 RHS, <0,0,0,0> + 564584550U, // <6,u,0,1>: Cost 1 vsldoi8 RHS, LHS + 2712068269U, // <6,u,0,2>: Cost 3 vsldoi8 RHS, <0,2,1,2> + 2309349532U, // <6,u,0,3>: Cost 3 vmrglw <4,5,6,0>, LHS + 1638326610U, // <6,u,0,4>: Cost 2 vsldoi8 RHS, <0,4,1,5> + 1577939051U, // <6,u,0,5>: Cost 2 vsldoi4 <5,6,u,0>, <5,6,u,0> + 2712068598U, // <6,u,0,6>: Cost 3 vsldoi8 RHS, <0,6,1,7> + 2309352776U, // <6,u,0,7>: Cost 3 vmrglw <4,5,6,0>, RHS + 564585117U, // <6,u,0,u>: Cost 1 vsldoi8 RHS, LHS + 2712068835U, // <6,u,1,0>: Cost 3 vsldoi8 RHS, <1,0,1,1> + 1638327092U, // <6,u,1,1>: Cost 2 vsldoi8 RHS, <1,1,1,1> + 1698715438U, // <6,u,1,2>: Cost 2 vsldoi12 <3,4,5,6>, LHS + 2299404444U, // <6,u,1,3>: Cost 3 vmrglw <2,u,6,1>, LHS + 2712069163U, // <6,u,1,4>: Cost 3 vsldoi8 RHS, <1,4,1,5> + 2712069231U, // <6,u,1,5>: Cost 3 vsldoi8 RHS, <1,5,0,1> + 2712069327U, // <6,u,1,6>: Cost 3 vsldoi8 RHS, <1,6,1,7> + 2299407688U, // <6,u,1,7>: Cost 3 vmrglw <2,u,6,1>, RHS + 1698715492U, // <6,u,1,u>: Cost 2 vsldoi12 <3,4,5,6>, LHS + 2712069565U, // <6,u,2,0>: Cost 3 vsldoi8 RHS, <2,0,1,2> + 1178556206U, // <6,u,2,1>: Cost 2 vmrghw <6,2,7,3>, LHS + 1638327912U, // <6,u,2,2>: Cost 2 vsldoi8 RHS, <2,2,2,2> + 1638327974U, // <6,u,2,3>: Cost 2 vsldoi8 RHS, <2,3,0,1> + 2712069901U, // <6,u,2,4>: Cost 3 vsldoi8 RHS, <2,4,2,5> + 1178556570U, // <6,u,2,5>: Cost 2 vmrghw <6,2,7,3>, RHS + 1638328250U, // <6,u,2,6>: Cost 2 vsldoi8 RHS, <2,6,3,7> + 2252298496U, // <6,u,2,7>: Cost 3 vmrghw <6,2,7,3>, + 1638328379U, // <6,u,2,u>: Cost 2 vsldoi8 RHS, <2,u,0,1> + 1638328470U, // <6,u,3,0>: Cost 2 vsldoi8 RHS, <3,0,1,2> + 2712070374U, // <6,u,3,1>: Cost 3 vsldoi8 RHS, <3,1,1,1> + 2704107883U, // <6,u,3,2>: Cost 3 vsldoi8 <3,2,6,u>, <3,2,6,u> + 1638328732U, // <6,u,3,3>: Cost 2 vsldoi8 RHS, <3,3,3,3> + 1638328834U, // <6,u,3,4>: Cost 2 vsldoi8 RHS, <3,4,5,6> + 2712070738U, // <6,u,3,5>: Cost 3 vsldoi8 RHS, <3,5,5,5> + 2712070776U, // <6,u,3,6>: Cost 3 vsldoi8 RHS, <3,6,0,7> + 2301414728U, // <6,u,3,7>: Cost 3 vmrglw <3,2,6,3>, RHS + 1638329118U, // <6,u,3,u>: Cost 2 vsldoi8 RHS, <3,u,1,2> + 1638329234U, // <6,u,4,0>: Cost 2 vsldoi8 RHS, <4,0,5,1> + 2712071114U, // <6,u,4,1>: Cost 3 vsldoi8 RHS, <4,1,2,3> + 2712071221U, // <6,u,4,2>: Cost 3 vsldoi8 RHS, <4,2,5,2> + 2309382300U, // <6,u,4,3>: Cost 3 vmrglw <4,5,6,4>, LHS + 1638329552U, // <6,u,4,4>: Cost 2 vsldoi8 RHS, <4,4,4,4> + 564587831U, // <6,u,4,5>: Cost 1 vsldoi8 RHS, RHS + 2712071545U, // <6,u,4,6>: Cost 3 vsldoi8 RHS, <4,6,5,2> + 2309385544U, // <6,u,4,7>: Cost 3 vmrglw <4,5,6,4>, RHS + 564588073U, // <6,u,4,u>: Cost 1 vsldoi8 RHS, RHS + 2712071752U, // <6,u,5,0>: Cost 3 vsldoi8 RHS, <5,0,1,2> + 2714062479U, // <6,u,5,1>: Cost 3 vsldoi8 RHS, <5,1,0,1> + 2712071934U, // <6,u,5,2>: Cost 3 vsldoi8 RHS, <5,2,3,4> + 2299437212U, // <6,u,5,3>: Cost 3 vmrglw <2,u,6,5>, LHS + 2712072116U, // <6,u,5,4>: Cost 3 vsldoi8 RHS, <5,4,5,6> + 1638330372U, // <6,u,5,5>: Cost 2 vsldoi8 RHS, <5,5,5,5> + 1698715802U, // <6,u,5,6>: Cost 2 vsldoi12 <3,4,5,6>, RHS + 2299440456U, // <6,u,5,7>: Cost 3 vmrglw <2,u,6,5>, RHS + 1698715820U, // <6,u,5,u>: Cost 2 vsldoi12 <3,4,5,6>, RHS + 1583808614U, // <6,u,6,0>: Cost 2 vsldoi4 <6,6,6,6>, LHS + 1181161262U, // <6,u,6,1>: Cost 2 vmrghw <6,6,6,6>, LHS + 1638330874U, // <6,u,6,2>: Cost 2 vsldoi8 RHS, <6,2,7,3> + 1248264348U, // <6,u,6,3>: Cost 2 vmrglw <6,6,6,6>, LHS + 1583811894U, // <6,u,6,4>: Cost 2 vsldoi4 <6,6,6,6>, RHS + 1181161626U, // <6,u,6,5>: Cost 2 vmrghw <6,6,6,6>, RHS + 363253046U, // <6,u,6,6>: Cost 1 vspltisw2 RHS + 1638331214U, // <6,u,6,7>: Cost 2 vsldoi8 RHS, <6,7,0,1> + 363253046U, // <6,u,6,u>: Cost 1 vspltisw2 RHS + 1560076390U, // <6,u,7,0>: Cost 2 vsldoi4 <2,6,u,7>, LHS + 1235664969U, // <6,u,7,1>: Cost 2 vmrglw RHS, <0,0,u,1> + 1560078311U, // <6,u,7,2>: Cost 2 vsldoi4 <2,6,u,7>, <2,6,u,7> + 161923228U, // <6,u,7,3>: Cost 1 vmrglw RHS, LHS + 1560079670U, // <6,u,7,4>: Cost 2 vsldoi4 <2,6,u,7>, RHS + 1235665297U, // <6,u,7,5>: Cost 2 vmrglw RHS, <0,4,u,5> + 1235667485U, // <6,u,7,6>: Cost 2 vmrglw RHS, <3,4,u,6> + 161926472U, // <6,u,7,7>: Cost 1 vmrglw RHS, RHS + 161923233U, // <6,u,7,u>: Cost 1 vmrglw RHS, LHS + 1560084582U, // <6,u,u,0>: Cost 2 vsldoi4 <2,6,u,u>, LHS + 564590382U, // <6,u,u,1>: Cost 1 vsldoi8 RHS, LHS + 1560086504U, // <6,u,u,2>: Cost 2 vsldoi4 <2,6,u,u>, <2,6,u,u> + 161931420U, // <6,u,u,3>: Cost 1 vmrglw RHS, LHS + 1560087862U, // <6,u,u,4>: Cost 2 vsldoi4 <2,6,u,u>, RHS + 564590746U, // <6,u,u,5>: Cost 1 vsldoi8 RHS, RHS + 363253046U, // <6,u,u,6>: Cost 1 vspltisw2 RHS + 161934664U, // <6,u,u,7>: Cost 1 vmrglw RHS, RHS + 161931425U, // <6,u,u,u>: Cost 1 vmrglw RHS, LHS + 1705426944U, // <7,0,0,0>: Cost 2 vsldoi12 RHS, <0,0,0,0> + 1705426954U, // <7,0,0,1>: Cost 2 vsldoi12 RHS, <0,0,1,1> + 3713550266U, // <7,0,0,2>: Cost 4 vsldoi4 <3,7,0,0>, <2,6,3,7> + 2316063892U, // <7,0,0,3>: Cost 3 vmrglw <5,6,7,0>, <7,2,0,3> + 2779168805U, // <7,0,0,4>: Cost 3 vsldoi12 RHS, <0,0,4,1> + 2663698530U, // <7,0,0,5>: Cost 3 vsldoi4 <7,7,0,0>, <5,6,7,0> + 2657727309U, // <7,0,0,6>: Cost 3 vsldoi4 <6,7,0,0>, <6,7,0,0> + 2316064220U, // <7,0,0,7>: Cost 3 vmrglw <5,6,7,0>, <7,6,0,7> + 1705427017U, // <7,0,0,u>: Cost 2 vsldoi12 RHS, <0,0,u,1> + 1583988838U, // <7,0,1,0>: Cost 2 vsldoi4 <6,7,0,1>, LHS + 2779168859U, // <7,0,1,1>: Cost 3 vsldoi12 RHS, <0,1,1,1> + 631685222U, // <7,0,1,2>: Cost 1 vsldoi12 RHS, LHS + 2639817411U, // <7,0,1,3>: Cost 3 vsldoi4 <3,7,0,1>, <3,7,0,1> + 1583992118U, // <7,0,1,4>: Cost 2 vsldoi4 <6,7,0,1>, RHS + 2657734660U, // <7,0,1,5>: Cost 3 vsldoi4 <6,7,0,1>, <5,5,5,5> + 1583993678U, // <7,0,1,6>: Cost 2 vsldoi4 <6,7,0,1>, <6,7,0,1> + 2657735672U, // <7,0,1,7>: Cost 3 vsldoi4 <6,7,0,1>, <7,0,1,0> + 631685276U, // <7,0,1,u>: Cost 1 vsldoi12 RHS, LHS + 2779168933U, // <7,0,2,0>: Cost 3 vsldoi12 RHS, <0,2,0,3> + 2767667377U, // <7,0,2,1>: Cost 3 vsldoi12 <2,6,3,7>, <0,2,1,6> + 2718713448U, // <7,0,2,2>: Cost 3 vsldoi8 <5,6,7,0>, <2,2,2,2> + 2718713510U, // <7,0,2,3>: Cost 3 vsldoi8 <5,6,7,0>, <2,3,0,1> + 3841409228U, // <7,0,2,4>: Cost 4 vsldoi12 <2,6,3,7>, <0,2,4,6> + 3852910802U, // <7,0,2,5>: Cost 4 vsldoi12 RHS, <0,2,5,3> + 2718713786U, // <7,0,2,6>: Cost 3 vsldoi8 <5,6,7,0>, <2,6,3,7> + 3847160036U, // <7,0,2,7>: Cost 4 vsldoi12 <3,6,0,7>, <0,2,7,3> + 2767667440U, // <7,0,2,u>: Cost 3 vsldoi12 <2,6,3,7>, <0,2,u,6> + 2718714006U, // <7,0,3,0>: Cost 3 vsldoi8 <5,6,7,0>, <3,0,1,2> + 2779169020U, // <7,0,3,1>: Cost 3 vsldoi12 RHS, <0,3,1,0> + 3852910853U, // <7,0,3,2>: Cost 4 vsldoi12 RHS, <0,3,2,0> + 2718714268U, // <7,0,3,3>: Cost 3 vsldoi8 <5,6,7,0>, <3,3,3,3> + 2718714370U, // <7,0,3,4>: Cost 3 vsldoi8 <5,6,7,0>, <3,4,5,6> + 2718714461U, // <7,0,3,5>: Cost 3 vsldoi8 <5,6,7,0>, <3,5,6,7> + 2706770608U, // <7,0,3,6>: Cost 3 vsldoi8 <3,6,7,0>, <3,6,7,0> + 3847160114U, // <7,0,3,7>: Cost 4 vsldoi12 <3,6,0,7>, <0,3,7,0> + 2779169083U, // <7,0,3,u>: Cost 3 vsldoi12 RHS, <0,3,u,0> + 2718714770U, // <7,0,4,0>: Cost 3 vsldoi8 <5,6,7,0>, <4,0,5,1> + 1705427282U, // <7,0,4,1>: Cost 2 vsldoi12 RHS, <0,4,1,5> + 3713583034U, // <7,0,4,2>: Cost 4 vsldoi4 <3,7,0,4>, <2,6,3,7> + 3713583814U, // <7,0,4,3>: Cost 4 vsldoi4 <3,7,0,4>, <3,7,0,4> + 2779169133U, // <7,0,4,4>: Cost 3 vsldoi12 RHS, <0,4,4,5> + 1644973366U, // <7,0,4,5>: Cost 2 vsldoi8 <5,6,7,0>, RHS + 2657760081U, // <7,0,4,6>: Cost 3 vsldoi4 <6,7,0,4>, <6,7,0,4> + 2259468868U, // <7,0,4,7>: Cost 3 vmrghw <7,4,5,6>, <0,7,1,4> + 1705427345U, // <7,0,4,u>: Cost 2 vsldoi12 RHS, <0,4,u,5> + 2718715508U, // <7,0,5,0>: Cost 3 vsldoi8 <5,6,7,0>, <5,0,6,1> + 2260123750U, // <7,0,5,1>: Cost 3 vmrghw <7,5,5,5>, LHS + 3792457451U, // <7,0,5,2>: Cost 4 vsldoi8 <5,6,7,0>, <5,2,1,3> + 3852911024U, // <7,0,5,3>: Cost 4 vsldoi12 RHS, <0,5,3,0> + 2718715836U, // <7,0,5,4>: Cost 3 vsldoi8 <5,6,7,0>, <5,4,6,5> + 2718715908U, // <7,0,5,5>: Cost 3 vsldoi8 <5,6,7,0>, <5,5,5,5> + 1644974178U, // <7,0,5,6>: Cost 2 vsldoi8 <5,6,7,0>, <5,6,7,0> + 3792457853U, // <7,0,5,7>: Cost 4 vsldoi8 <5,6,7,0>, <5,7,1,0> + 1646301444U, // <7,0,5,u>: Cost 2 vsldoi8 <5,u,7,0>, <5,u,7,0> + 2720706901U, // <7,0,6,0>: Cost 3 vsldoi8 <6,0,7,0>, <6,0,7,0> + 2779169270U, // <7,0,6,1>: Cost 3 vsldoi12 RHS, <0,6,1,7> + 2718716410U, // <7,0,6,2>: Cost 3 vsldoi8 <5,6,7,0>, <6,2,7,3> + 2722697800U, // <7,0,6,3>: Cost 3 vsldoi8 <6,3,7,0>, <6,3,7,0> + 3852911121U, // <7,0,6,4>: Cost 4 vsldoi12 RHS, <0,6,4,7> + 3852911130U, // <7,0,6,5>: Cost 4 vsldoi12 RHS, <0,6,5,7> + 2718716728U, // <7,0,6,6>: Cost 3 vsldoi8 <5,6,7,0>, <6,6,6,6> + 2718716750U, // <7,0,6,7>: Cost 3 vsldoi8 <5,6,7,0>, <6,7,0,1> + 2779169333U, // <7,0,6,u>: Cost 3 vsldoi12 RHS, <0,6,u,7> + 2718716922U, // <7,0,7,0>: Cost 3 vsldoi8 <5,6,7,0>, <7,0,1,2> + 1187872870U, // <7,0,7,1>: Cost 2 vmrghw <7,7,7,7>, LHS + 2718717076U, // <7,0,7,2>: Cost 3 vsldoi8 <5,6,7,0>, <7,2,0,3> + 3847160408U, // <7,0,7,3>: Cost 4 vsldoi12 <3,6,0,7>, <0,7,3,6> + 2718717286U, // <7,0,7,4>: Cost 3 vsldoi8 <5,6,7,0>, <7,4,5,6> + 2718717377U, // <7,0,7,5>: Cost 3 vsldoi8 <5,6,7,0>, <7,5,6,7> + 2718717404U, // <7,0,7,6>: Cost 3 vsldoi8 <5,6,7,0>, <7,6,0,7> + 2718717478U, // <7,0,7,7>: Cost 3 vsldoi8 <5,6,7,0>, <7,7,0,0> + 1187873437U, // <7,0,7,u>: Cost 2 vmrghw <7,7,7,7>, LHS + 1584046182U, // <7,0,u,0>: Cost 2 vsldoi4 <6,7,0,u>, LHS + 1705427602U, // <7,0,u,1>: Cost 2 vsldoi12 RHS, <0,u,1,1> + 631685789U, // <7,0,u,2>: Cost 1 vsldoi12 RHS, LHS + 2639874762U, // <7,0,u,3>: Cost 3 vsldoi4 <3,7,0,u>, <3,7,0,u> + 1584049462U, // <7,0,u,4>: Cost 2 vsldoi4 <6,7,0,u>, RHS + 1644976282U, // <7,0,u,5>: Cost 2 vsldoi8 <5,6,7,0>, RHS + 1584051029U, // <7,0,u,6>: Cost 2 vsldoi4 <6,7,0,u>, <6,7,0,u> + 2718718208U, // <7,0,u,7>: Cost 3 vsldoi8 <5,6,7,0>, + 631685843U, // <7,0,u,u>: Cost 1 vsldoi12 RHS, LHS + 2721374218U, // <7,1,0,0>: Cost 3 vsldoi8 <6,1,7,1>, <0,0,1,1> + 2779169507U, // <7,1,0,1>: Cost 3 vsldoi12 RHS, <1,0,1,1> + 2779169516U, // <7,1,0,2>: Cost 3 vsldoi12 RHS, <1,0,2,1> + 3852911348U, // <7,1,0,3>: Cost 4 vsldoi12 RHS, <1,0,3,0> + 2669743414U, // <7,1,0,4>: Cost 3 vsldoi4 , RHS + 2316058962U, // <7,1,0,5>: Cost 3 vmrglw <5,6,7,0>, <0,4,1,5> + 2316059044U, // <7,1,0,6>: Cost 3 vmrglw <5,6,7,0>, <0,5,1,6> + 2669745146U, // <7,1,0,7>: Cost 3 vsldoi4 , <7,0,1,2> + 2779169570U, // <7,1,0,u>: Cost 3 vsldoi12 RHS, <1,0,u,1> + 2779169579U, // <7,1,1,0>: Cost 3 vsldoi12 RHS, <1,1,0,1> + 1705427764U, // <7,1,1,1>: Cost 2 vsldoi12 RHS, <1,1,1,1> + 2779169598U, // <7,1,1,2>: Cost 3 vsldoi12 RHS, <1,1,2,2> + 3713632972U, // <7,1,1,3>: Cost 4 vsldoi4 <3,7,1,1>, <3,7,1,1> + 2779169619U, // <7,1,1,4>: Cost 3 vsldoi12 RHS, <1,1,4,5> + 2779169628U, // <7,1,1,5>: Cost 3 vsldoi12 RHS, <1,1,5,5> + 2657809239U, // <7,1,1,6>: Cost 3 vsldoi4 <6,7,1,1>, <6,7,1,1> + 3835290474U, // <7,1,1,7>: Cost 4 vsldoi12 <1,6,1,7>, <1,1,7,1> + 1705427764U, // <7,1,1,u>: Cost 2 vsldoi12 RHS, <1,1,1,1> + 2779169660U, // <7,1,2,0>: Cost 3 vsldoi12 RHS, <1,2,0,1> + 2779169671U, // <7,1,2,1>: Cost 3 vsldoi12 RHS, <1,2,1,3> + 2779169680U, // <7,1,2,2>: Cost 3 vsldoi12 RHS, <1,2,2,3> + 1705427862U, // <7,1,2,3>: Cost 2 vsldoi12 RHS, <1,2,3,0> + 2779169700U, // <7,1,2,4>: Cost 3 vsldoi12 RHS, <1,2,4,5> + 2779169707U, // <7,1,2,5>: Cost 3 vsldoi12 RHS, <1,2,5,3> + 2657817432U, // <7,1,2,6>: Cost 3 vsldoi4 <6,7,1,2>, <6,7,1,2> + 2803057594U, // <7,1,2,7>: Cost 3 vsldoi12 RHS, <1,2,7,0> + 1705427907U, // <7,1,2,u>: Cost 2 vsldoi12 RHS, <1,2,u,0> + 3776538827U, // <7,1,3,0>: Cost 4 vsldoi8 <3,0,7,1>, <3,0,7,1> + 2319400970U, // <7,1,3,1>: Cost 3 vmrglw <6,2,7,3>, <0,0,1,1> + 2316085398U, // <7,1,3,2>: Cost 3 vmrglw <5,6,7,3>, <3,0,1,2> + 3852911591U, // <7,1,3,3>: Cost 4 vsldoi12 RHS, <1,3,3,0> + 3852911600U, // <7,1,3,4>: Cost 4 vsldoi12 RHS, <1,3,4,0> + 2319401298U, // <7,1,3,5>: Cost 3 vmrglw <6,2,7,3>, <0,4,1,5> + 3833668617U, // <7,1,3,6>: Cost 4 vsldoi12 <1,3,6,7>, <1,3,6,7> + 3367265487U, // <7,1,3,7>: Cost 4 vmrglw <1,u,7,3>, <1,6,1,7> + 2319400977U, // <7,1,3,u>: Cost 3 vmrglw <6,2,7,3>, <0,0,1,u> + 2724031378U, // <7,1,4,0>: Cost 3 vsldoi8 <6,5,7,1>, <4,0,5,1> + 2779169835U, // <7,1,4,1>: Cost 3 vsldoi12 RHS, <1,4,1,5> + 2779169844U, // <7,1,4,2>: Cost 3 vsldoi12 RHS, <1,4,2,5> + 3852911672U, // <7,1,4,3>: Cost 4 vsldoi12 RHS, <1,4,3,0> + 2669776182U, // <7,1,4,4>: Cost 3 vsldoi4 , RHS + 2779169872U, // <7,1,4,5>: Cost 3 vsldoi12 RHS, <1,4,5,6> + 3835290712U, // <7,1,4,6>: Cost 4 vsldoi12 <1,6,1,7>, <1,4,6,5> + 2669778278U, // <7,1,4,7>: Cost 3 vsldoi4 , <7,4,5,6> + 2779169898U, // <7,1,4,u>: Cost 3 vsldoi12 RHS, <1,4,u,5> + 2779169903U, // <7,1,5,0>: Cost 3 vsldoi12 RHS, <1,5,0,1> + 3835585661U, // <7,1,5,1>: Cost 4 vsldoi12 <1,6,5,7>, <1,5,1,6> + 3841410182U, // <7,1,5,2>: Cost 4 vsldoi12 <2,6,3,7>, <1,5,2,6> + 3852911753U, // <7,1,5,3>: Cost 4 vsldoi12 RHS, <1,5,3,0> + 2779169943U, // <7,1,5,4>: Cost 3 vsldoi12 RHS, <1,5,4,5> + 2318754130U, // <7,1,5,5>: Cost 3 vmrglw <6,1,7,5>, <0,4,1,5> + 2718724195U, // <7,1,5,6>: Cost 3 vsldoi8 <5,6,7,1>, <5,6,7,1> + 3859178670U, // <7,1,5,7>: Cost 4 vsldoi12 <5,6,1,7>, <1,5,7,1> + 2779169975U, // <7,1,5,u>: Cost 3 vsldoi12 RHS, <1,5,u,1> + 2720715094U, // <7,1,6,0>: Cost 3 vsldoi8 <6,0,7,1>, <6,0,7,1> + 2761549007U, // <7,1,6,1>: Cost 3 vsldoi12 <1,6,1,7>, <1,6,1,7> + 2779170008U, // <7,1,6,2>: Cost 3 vsldoi12 RHS, <1,6,2,7> + 3835438305U, // <7,1,6,3>: Cost 4 vsldoi12 <1,6,3,7>, <1,6,3,7> + 3835512042U, // <7,1,6,4>: Cost 4 vsldoi12 <1,6,4,7>, <1,6,4,7> + 2761843955U, // <7,1,6,5>: Cost 3 vsldoi12 <1,6,5,7>, <1,6,5,7> + 3835659516U, // <7,1,6,6>: Cost 4 vsldoi12 <1,6,6,7>, <1,6,6,7> + 2803057918U, // <7,1,6,7>: Cost 3 vsldoi12 RHS, <1,6,7,0> + 2762065166U, // <7,1,6,u>: Cost 3 vsldoi12 <1,6,u,7>, <1,6,u,7> + 2669797478U, // <7,1,7,0>: Cost 3 vsldoi4 , LHS + 2322087946U, // <7,1,7,1>: Cost 3 vmrglw <6,6,7,7>, <0,0,1,1> + 2317448186U, // <7,1,7,2>: Cost 3 vmrglw <5,u,7,7>, <7,0,1,2> + 3395829934U, // <7,1,7,3>: Cost 4 vmrglw <6,6,7,7>, <0,2,1,3> + 2669800758U, // <7,1,7,4>: Cost 3 vsldoi4 , RHS + 2322088274U, // <7,1,7,5>: Cost 3 vmrglw <6,6,7,7>, <0,4,1,5> + 3375923377U, // <7,1,7,6>: Cost 4 vmrglw <3,3,7,7>, <0,2,1,6> + 2731996780U, // <7,1,7,7>: Cost 3 vsldoi8 <7,u,7,1>, <7,7,7,7> + 2322087953U, // <7,1,7,u>: Cost 3 vmrglw <6,6,7,7>, <0,0,1,u> + 2779170146U, // <7,1,u,0>: Cost 3 vsldoi12 RHS, <1,u,0,1> + 1705427764U, // <7,1,u,1>: Cost 2 vsldoi12 RHS, <1,1,1,1> + 2779170164U, // <7,1,u,2>: Cost 3 vsldoi12 RHS, <1,u,2,1> + 1705428348U, // <7,1,u,3>: Cost 2 vsldoi12 RHS, <1,u,3,0> + 2779170186U, // <7,1,u,4>: Cost 3 vsldoi12 RHS, <1,u,4,5> + 2763171221U, // <7,1,u,5>: Cost 3 vsldoi12 <1,u,5,7>, <1,u,5,7> + 2657866590U, // <7,1,u,6>: Cost 3 vsldoi4 <6,7,1,u>, <6,7,1,u> + 2803058080U, // <7,1,u,7>: Cost 3 vsldoi12 RHS, <1,u,7,0> + 1705428393U, // <7,1,u,u>: Cost 2 vsldoi12 RHS, <1,u,u,0> + 3713695846U, // <7,2,0,0>: Cost 4 vsldoi4 <3,7,2,0>, LHS + 2779170237U, // <7,2,0,1>: Cost 3 vsldoi12 RHS, <2,0,1,2> + 2779170245U, // <7,2,0,2>: Cost 3 vsldoi12 RHS, <2,0,2,1> + 1242316902U, // <7,2,0,3>: Cost 2 vmrglw <5,6,7,0>, LHS + 3713699126U, // <7,2,0,4>: Cost 4 vsldoi4 <3,7,2,0>, RHS + 3852912096U, // <7,2,0,5>: Cost 4 vsldoi12 RHS, <2,0,5,1> + 2767668713U, // <7,2,0,6>: Cost 3 vsldoi12 <2,6,3,7>, <2,0,6,1> + 2256488426U, // <7,2,0,7>: Cost 3 vmrghw <7,0,1,2>, <2,7,0,1> + 1242316907U, // <7,2,0,u>: Cost 2 vmrglw <5,6,7,0>, LHS + 3852912132U, // <7,2,1,0>: Cost 4 vsldoi12 RHS, <2,1,0,1> + 3852912141U, // <7,2,1,1>: Cost 4 vsldoi12 RHS, <2,1,1,1> + 3852912149U, // <7,2,1,2>: Cost 4 vsldoi12 RHS, <2,1,2,0> + 2779170335U, // <7,2,1,3>: Cost 3 vsldoi12 RHS, <2,1,3,1> + 3852912172U, // <7,2,1,4>: Cost 4 vsldoi12 RHS, <2,1,4,5> + 3840747062U, // <7,2,1,5>: Cost 5 vsldoi12 <2,5,3,7>, <2,1,5,6> + 3841410617U, // <7,2,1,6>: Cost 4 vsldoi12 <2,6,3,7>, <2,1,6,0> + 3795125538U, // <7,2,1,7>: Cost 4 vsldoi8 <6,1,7,2>, <1,7,2,0> + 2779170380U, // <7,2,1,u>: Cost 3 vsldoi12 RHS, <2,1,u,1> + 2779170389U, // <7,2,2,0>: Cost 3 vsldoi12 RHS, <2,2,0,1> + 3852912222U, // <7,2,2,1>: Cost 4 vsldoi12 RHS, <2,2,1,1> + 1705428584U, // <7,2,2,2>: Cost 2 vsldoi12 RHS, <2,2,2,2> + 1705428594U, // <7,2,2,3>: Cost 2 vsldoi12 RHS, <2,2,3,3> + 2779170429U, // <7,2,2,4>: Cost 3 vsldoi12 RHS, <2,2,4,5> + 3852912259U, // <7,2,2,5>: Cost 4 vsldoi12 RHS, <2,2,5,2> + 2767668880U, // <7,2,2,6>: Cost 3 vsldoi12 <2,6,3,7>, <2,2,6,6> + 3841336981U, // <7,2,2,7>: Cost 4 vsldoi12 <2,6,2,7>, <2,2,7,2> + 1705428639U, // <7,2,2,u>: Cost 2 vsldoi12 RHS, <2,2,u,3> + 1705428646U, // <7,2,3,0>: Cost 2 vsldoi12 RHS, <2,3,0,1> + 2779170479U, // <7,2,3,1>: Cost 3 vsldoi12 RHS, <2,3,1,1> + 2767668925U, // <7,2,3,2>: Cost 3 vsldoi12 <2,6,3,7>, <2,3,2,6> + 1245659238U, // <7,2,3,3>: Cost 2 vmrglw <6,2,7,3>, LHS + 1705428686U, // <7,2,3,4>: Cost 2 vsldoi12 RHS, <2,3,4,5> + 2779170519U, // <7,2,3,5>: Cost 3 vsldoi12 RHS, <2,3,5,5> + 2657899362U, // <7,2,3,6>: Cost 3 vsldoi4 <6,7,2,3>, <6,7,2,3> + 2319406574U, // <7,2,3,7>: Cost 3 vmrglw <6,2,7,3>, <7,6,2,7> + 1705428718U, // <7,2,3,u>: Cost 2 vsldoi12 RHS, <2,3,u,1> + 3713728614U, // <7,2,4,0>: Cost 4 vsldoi4 <3,7,2,4>, LHS + 3852912388U, // <7,2,4,1>: Cost 4 vsldoi12 RHS, <2,4,1,5> + 2779170573U, // <7,2,4,2>: Cost 3 vsldoi12 RHS, <2,4,2,5> + 1242349670U, // <7,2,4,3>: Cost 2 vmrglw <5,6,7,4>, LHS + 3713731894U, // <7,2,4,4>: Cost 4 vsldoi4 <3,7,2,4>, RHS + 2779170601U, // <7,2,4,5>: Cost 3 vsldoi12 RHS, <2,4,5,6> + 2767669041U, // <7,2,4,6>: Cost 3 vsldoi12 <2,6,3,7>, <2,4,6,5> + 3389834456U, // <7,2,4,7>: Cost 4 vmrglw <5,6,7,4>, <1,6,2,7> + 1242349675U, // <7,2,4,u>: Cost 2 vmrglw <5,6,7,4>, LHS + 3852912456U, // <7,2,5,0>: Cost 4 vsldoi12 RHS, <2,5,0,1> + 3852912466U, // <7,2,5,1>: Cost 4 vsldoi12 RHS, <2,5,1,2> + 3852912475U, // <7,2,5,2>: Cost 4 vsldoi12 RHS, <2,5,2,2> + 2779170664U, // <7,2,5,3>: Cost 3 vsldoi12 RHS, <2,5,3,6> + 3852912496U, // <7,2,5,4>: Cost 4 vsldoi12 RHS, <2,5,4,5> + 3792474116U, // <7,2,5,5>: Cost 4 vsldoi8 <5,6,7,2>, <5,5,5,5> + 2718732388U, // <7,2,5,6>: Cost 3 vsldoi8 <5,6,7,2>, <5,6,7,2> + 3841337228U, // <7,2,5,7>: Cost 5 vsldoi12 <2,6,2,7>, <2,5,7,6> + 2779170709U, // <7,2,5,u>: Cost 3 vsldoi12 RHS, <2,5,u,6> + 2640003174U, // <7,2,6,0>: Cost 3 vsldoi4 <3,7,2,6>, LHS + 2721386920U, // <7,2,6,1>: Cost 3 vsldoi8 <6,1,7,2>, <6,1,7,2> + 2767595441U, // <7,2,6,2>: Cost 3 vsldoi12 <2,6,2,7>, <2,6,2,7> + 1693927354U, // <7,2,6,3>: Cost 2 vsldoi12 <2,6,3,7>, <2,6,3,7> + 2640006454U, // <7,2,6,4>: Cost 3 vsldoi4 <3,7,2,6>, RHS + 3841558476U, // <7,2,6,5>: Cost 4 vsldoi12 <2,6,5,7>, <2,6,5,7> + 2657923941U, // <7,2,6,6>: Cost 3 vsldoi4 <6,7,2,6>, <6,7,2,6> + 3841337310U, // <7,2,6,7>: Cost 4 vsldoi12 <2,6,2,7>, <2,6,7,7> + 1694296039U, // <7,2,6,u>: Cost 2 vsldoi12 <2,6,u,7>, <2,6,u,7> + 2803058666U, // <7,2,7,0>: Cost 3 vsldoi12 RHS, <2,7,0,1> + 3852912632U, // <7,2,7,1>: Cost 4 vsldoi12 RHS, <2,7,1,6> + 2322089576U, // <7,2,7,2>: Cost 3 vmrglw <6,6,7,7>, <2,2,2,2> + 1248346214U, // <7,2,7,3>: Cost 2 vmrglw <6,6,7,7>, LHS + 3841337362U, // <7,2,7,4>: Cost 4 vsldoi12 <2,6,2,7>, <2,7,4,5> + 3395830836U, // <7,2,7,5>: Cost 4 vmrglw <6,6,7,7>, <1,4,2,5> + 2261616570U, // <7,2,7,6>: Cost 3 vmrghw <7,7,7,7>, <2,6,3,7> + 3371943857U, // <7,2,7,7>: Cost 4 vmrglw <2,6,7,7>, <2,6,2,7> + 1248346219U, // <7,2,7,u>: Cost 2 vmrglw <6,6,7,7>, LHS + 1705429051U, // <7,2,u,0>: Cost 2 vsldoi12 RHS, <2,u,0,1> + 2779170884U, // <7,2,u,1>: Cost 3 vsldoi12 RHS, <2,u,1,1> + 1705428584U, // <7,2,u,2>: Cost 2 vsldoi12 RHS, <2,2,2,2> + 1695254620U, // <7,2,u,3>: Cost 2 vsldoi12 <2,u,3,7>, <2,u,3,7> + 1705429091U, // <7,2,u,4>: Cost 2 vsldoi12 RHS, <2,u,4,5> + 2779170924U, // <7,2,u,5>: Cost 3 vsldoi12 RHS, <2,u,5,5> + 2767669361U, // <7,2,u,6>: Cost 3 vsldoi12 <2,6,3,7>, <2,u,6,1> + 2803058809U, // <7,2,u,7>: Cost 3 vsldoi12 RHS, <2,u,7,0> + 1695623305U, // <7,2,u,u>: Cost 2 vsldoi12 <2,u,u,7>, <2,u,u,7> + 2779170955U, // <7,3,0,0>: Cost 3 vsldoi12 RHS, <3,0,0,0> + 1705429142U, // <7,3,0,1>: Cost 2 vsldoi12 RHS, <3,0,1,2> + 2634057732U, // <7,3,0,2>: Cost 3 vsldoi4 <2,7,3,0>, <2,7,3,0> + 2779170983U, // <7,3,0,3>: Cost 3 vsldoi12 RHS, <3,0,3,1> + 2779170992U, // <7,3,0,4>: Cost 3 vsldoi12 RHS, <3,0,4,1> + 3852912829U, // <7,3,0,5>: Cost 4 vsldoi12 RHS, <3,0,5,5> + 2657948520U, // <7,3,0,6>: Cost 3 vsldoi4 <6,7,3,0>, <6,7,3,0> + 2316060602U, // <7,3,0,7>: Cost 3 vmrglw <5,6,7,0>, <2,6,3,7> + 1705429205U, // <7,3,0,u>: Cost 2 vsldoi12 RHS, <3,0,u,2> + 3852912860U, // <7,3,1,0>: Cost 4 vsldoi12 RHS, <3,1,0,0> + 2779171046U, // <7,3,1,1>: Cost 3 vsldoi12 RHS, <3,1,1,1> + 2779171057U, // <7,3,1,2>: Cost 3 vsldoi12 RHS, <3,1,2,3> + 3852912887U, // <7,3,1,3>: Cost 4 vsldoi12 RHS, <3,1,3,0> + 3852912896U, // <7,3,1,4>: Cost 4 vsldoi12 RHS, <3,1,4,0> + 3852912905U, // <7,3,1,5>: Cost 4 vsldoi12 RHS, <3,1,5,0> + 3835291923U, // <7,3,1,6>: Cost 4 vsldoi12 <1,6,1,7>, <3,1,6,1> + 3841411356U, // <7,3,1,7>: Cost 4 vsldoi12 <2,6,3,7>, <3,1,7,1> + 2779171111U, // <7,3,1,u>: Cost 3 vsldoi12 RHS, <3,1,u,3> + 2779171120U, // <7,3,2,0>: Cost 3 vsldoi12 RHS, <3,2,0,3> + 3852912952U, // <7,3,2,1>: Cost 4 vsldoi12 RHS, <3,2,1,2> + 2779171137U, // <7,3,2,2>: Cost 3 vsldoi12 RHS, <3,2,2,2> + 2779171144U, // <7,3,2,3>: Cost 3 vsldoi12 RHS, <3,2,3,0> + 2779171156U, // <7,3,2,4>: Cost 3 vsldoi12 RHS, <3,2,4,3> + 3852912989U, // <7,3,2,5>: Cost 4 vsldoi12 RHS, <3,2,5,3> + 2767669606U, // <7,3,2,6>: Cost 3 vsldoi12 <2,6,3,7>, <3,2,6,3> + 2767669615U, // <7,3,2,7>: Cost 3 vsldoi12 <2,6,3,7>, <3,2,7,3> + 2779171189U, // <7,3,2,u>: Cost 3 vsldoi12 RHS, <3,2,u,0> + 2779171198U, // <7,3,3,0>: Cost 3 vsldoi12 RHS, <3,3,0,0> + 3852913032U, // <7,3,3,1>: Cost 4 vsldoi12 RHS, <3,3,1,1> + 2704140655U, // <7,3,3,2>: Cost 3 vsldoi8 <3,2,7,3>, <3,2,7,3> + 1705429404U, // <7,3,3,3>: Cost 2 vsldoi12 RHS, <3,3,3,3> + 2779171238U, // <7,3,3,4>: Cost 3 vsldoi12 RHS, <3,3,4,4> + 3852913070U, // <7,3,3,5>: Cost 4 vsldoi12 RHS, <3,3,5,3> + 2657973099U, // <7,3,3,6>: Cost 3 vsldoi4 <6,7,3,3>, <6,7,3,3> + 2767669700U, // <7,3,3,7>: Cost 3 vsldoi12 <2,6,3,7>, <3,3,7,7> + 1705429404U, // <7,3,3,u>: Cost 2 vsldoi12 RHS, <3,3,3,3> + 2779171280U, // <7,3,4,0>: Cost 3 vsldoi12 RHS, <3,4,0,1> + 2779171290U, // <7,3,4,1>: Cost 3 vsldoi12 RHS, <3,4,1,2> + 2634090504U, // <7,3,4,2>: Cost 3 vsldoi4 <2,7,3,4>, <2,7,3,4> + 2779171311U, // <7,3,4,3>: Cost 3 vsldoi12 RHS, <3,4,3,5> + 2779171319U, // <7,3,4,4>: Cost 3 vsldoi12 RHS, <3,4,4,4> + 1705429506U, // <7,3,4,5>: Cost 2 vsldoi12 RHS, <3,4,5,6> + 2722057593U, // <7,3,4,6>: Cost 3 vsldoi8 <6,2,7,3>, <4,6,5,2> + 2316093370U, // <7,3,4,7>: Cost 3 vmrglw <5,6,7,4>, <2,6,3,7> + 1705429533U, // <7,3,4,u>: Cost 2 vsldoi12 RHS, <3,4,u,6> + 3852913185U, // <7,3,5,0>: Cost 4 vsldoi12 RHS, <3,5,0,1> + 3795799695U, // <7,3,5,1>: Cost 4 vsldoi8 <6,2,7,3>, <5,1,0,1> + 3852913203U, // <7,3,5,2>: Cost 4 vsldoi12 RHS, <3,5,2,1> + 3852913214U, // <7,3,5,3>: Cost 4 vsldoi12 RHS, <3,5,3,3> + 3852913225U, // <7,3,5,4>: Cost 4 vsldoi12 RHS, <3,5,4,5> + 2779171410U, // <7,3,5,5>: Cost 3 vsldoi12 RHS, <3,5,5,5> + 2718740581U, // <7,3,5,6>: Cost 3 vsldoi8 <5,6,7,3>, <5,6,7,3> + 3841411685U, // <7,3,5,7>: Cost 4 vsldoi12 <2,6,3,7>, <3,5,7,6> + 2720067847U, // <7,3,5,u>: Cost 3 vsldoi8 <5,u,7,3>, <5,u,7,3> + 2773420664U, // <7,3,6,0>: Cost 3 vsldoi12 <3,6,0,7>, <3,6,0,7> + 3847236225U, // <7,3,6,1>: Cost 4 vsldoi12 <3,6,1,7>, <3,6,1,7> + 1648316922U, // <7,3,6,2>: Cost 2 vsldoi8 <6,2,7,3>, <6,2,7,3> + 2773641875U, // <7,3,6,3>: Cost 3 vsldoi12 <3,6,3,7>, <3,6,3,7> + 2773715612U, // <7,3,6,4>: Cost 3 vsldoi12 <3,6,4,7>, <3,6,4,7> + 3847531173U, // <7,3,6,5>: Cost 4 vsldoi12 <3,6,5,7>, <3,6,5,7> + 2722059024U, // <7,3,6,6>: Cost 3 vsldoi8 <6,2,7,3>, <6,6,2,2> + 2767669943U, // <7,3,6,7>: Cost 3 vsldoi12 <2,6,3,7>, <3,6,7,7> + 1652298720U, // <7,3,6,u>: Cost 2 vsldoi8 <6,u,7,3>, <6,u,7,3> + 2767669955U, // <7,3,7,0>: Cost 3 vsldoi12 <2,6,3,7>, <3,7,0,1> + 3841411788U, // <7,3,7,1>: Cost 4 vsldoi12 <2,6,3,7>, <3,7,1,1> + 2767669978U, // <7,3,7,2>: Cost 3 vsldoi12 <2,6,3,7>, <3,7,2,6> + 2722059546U, // <7,3,7,3>: Cost 3 vsldoi8 <6,2,7,3>, <7,3,6,2> + 2767669995U, // <7,3,7,4>: Cost 3 vsldoi12 <2,6,3,7>, <3,7,4,5> + 3852913396U, // <7,3,7,5>: Cost 4 vsldoi12 RHS, <3,7,5,5> + 2722059758U, // <7,3,7,6>: Cost 3 vsldoi8 <6,2,7,3>, <7,6,2,7> + 2302183354U, // <7,3,7,7>: Cost 3 vmrglw <3,3,7,7>, <2,6,3,7> + 2767670027U, // <7,3,7,u>: Cost 3 vsldoi12 <2,6,3,7>, <3,7,u,1> + 2774747930U, // <7,3,u,0>: Cost 3 vsldoi12 <3,u,0,7>, <3,u,0,7> + 1705429790U, // <7,3,u,1>: Cost 2 vsldoi12 RHS, <3,u,1,2> + 1660262316U, // <7,3,u,2>: Cost 2 vsldoi8 , + 1705429404U, // <7,3,u,3>: Cost 2 vsldoi12 RHS, <3,3,3,3> + 2775042878U, // <7,3,u,4>: Cost 3 vsldoi12 <3,u,4,7>, <3,u,4,7> + 1705429830U, // <7,3,u,5>: Cost 2 vsldoi12 RHS, <3,u,5,6> + 2779171660U, // <7,3,u,6>: Cost 3 vsldoi12 RHS, <3,u,6,3> + 2767670101U, // <7,3,u,7>: Cost 3 vsldoi12 <2,6,3,7>, <3,u,7,3> + 1705429853U, // <7,3,u,u>: Cost 2 vsldoi12 RHS, <3,u,u,2> + 2718744576U, // <7,4,0,0>: Cost 3 vsldoi8 <5,6,7,4>, <0,0,0,0> + 1645002854U, // <7,4,0,1>: Cost 2 vsldoi8 <5,6,7,4>, LHS + 3852913527U, // <7,4,0,2>: Cost 4 vsldoi12 RHS, <4,0,2,1> + 3852913536U, // <7,4,0,3>: Cost 4 vsldoi12 RHS, <4,0,3,1> + 2316061904U, // <7,4,0,4>: Cost 3 vmrglw <5,6,7,0>, <4,4,4,4> + 1705429906U, // <7,4,0,5>: Cost 2 vsldoi12 RHS, <4,0,5,1> + 2658022257U, // <7,4,0,6>: Cost 3 vsldoi4 <6,7,4,0>, <6,7,4,0> + 2256489928U, // <7,4,0,7>: Cost 3 vmrghw <7,0,1,2>, <4,7,5,0> + 1707420589U, // <7,4,0,u>: Cost 2 vsldoi12 RHS, <4,0,u,1> + 3852913590U, // <7,4,1,0>: Cost 4 vsldoi12 RHS, <4,1,0,1> + 2718745396U, // <7,4,1,1>: Cost 3 vsldoi8 <5,6,7,4>, <1,1,1,1> + 2779171786U, // <7,4,1,2>: Cost 3 vsldoi12 RHS, <4,1,2,3> + 3852913616U, // <7,4,1,3>: Cost 4 vsldoi12 RHS, <4,1,3,0> + 3852913627U, // <7,4,1,4>: Cost 4 vsldoi12 RHS, <4,1,4,2> + 2779171810U, // <7,4,1,5>: Cost 3 vsldoi12 RHS, <4,1,5,0> + 3792487631U, // <7,4,1,6>: Cost 4 vsldoi8 <5,6,7,4>, <1,6,1,7> + 3394456220U, // <7,4,1,7>: Cost 4 vmrglw <6,4,7,1>, <3,6,4,7> + 2779171837U, // <7,4,1,u>: Cost 3 vsldoi12 RHS, <4,1,u,0> + 3852913673U, // <7,4,2,0>: Cost 4 vsldoi12 RHS, <4,2,0,3> + 3852913682U, // <7,4,2,1>: Cost 4 vsldoi12 RHS, <4,2,1,3> + 2718746216U, // <7,4,2,2>: Cost 3 vsldoi8 <5,6,7,4>, <2,2,2,2> + 2718746278U, // <7,4,2,3>: Cost 3 vsldoi8 <5,6,7,4>, <2,3,0,1> + 2779171885U, // <7,4,2,4>: Cost 3 vsldoi12 RHS, <4,2,4,3> + 2779171893U, // <7,4,2,5>: Cost 3 vsldoi12 RHS, <4,2,5,2> + 2718746554U, // <7,4,2,6>: Cost 3 vsldoi8 <5,6,7,4>, <2,6,3,7> + 3847457864U, // <7,4,2,7>: Cost 4 vsldoi12 <3,6,4,7>, <4,2,7,3> + 2779171921U, // <7,4,2,u>: Cost 3 vsldoi12 RHS, <4,2,u,3> + 2718746774U, // <7,4,3,0>: Cost 3 vsldoi8 <5,6,7,4>, <3,0,1,2> + 3852913762U, // <7,4,3,1>: Cost 4 vsldoi12 RHS, <4,3,1,2> + 3852913772U, // <7,4,3,2>: Cost 4 vsldoi12 RHS, <4,3,2,3> + 2718747036U, // <7,4,3,3>: Cost 3 vsldoi8 <5,6,7,4>, <3,3,3,3> + 2718747138U, // <7,4,3,4>: Cost 3 vsldoi8 <5,6,7,4>, <3,4,5,6> + 2779171972U, // <7,4,3,5>: Cost 3 vsldoi12 RHS, <4,3,5,0> + 2706803380U, // <7,4,3,6>: Cost 3 vsldoi8 <3,6,7,4>, <3,6,7,4> + 3847457946U, // <7,4,3,7>: Cost 4 vsldoi12 <3,6,4,7>, <4,3,7,4> + 2781162655U, // <7,4,3,u>: Cost 3 vsldoi12 RHS, <4,3,u,0> + 2718747538U, // <7,4,4,0>: Cost 3 vsldoi8 <5,6,7,4>, <4,0,5,1> + 3852913842U, // <7,4,4,1>: Cost 4 vsldoi12 RHS, <4,4,1,1> + 3852913852U, // <7,4,4,2>: Cost 4 vsldoi12 RHS, <4,4,2,2> + 2316096696U, // <7,4,4,3>: Cost 3 vmrglw <5,6,7,4>, <7,2,4,3> + 1705430224U, // <7,4,4,4>: Cost 2 vsldoi12 RHS, <4,4,4,4> + 1705430234U, // <7,4,4,5>: Cost 2 vsldoi12 RHS, <4,4,5,5> + 2658055029U, // <7,4,4,6>: Cost 3 vsldoi4 <6,7,4,4>, <6,7,4,4> + 2316097024U, // <7,4,4,7>: Cost 3 vmrglw <5,6,7,4>, <7,6,4,7> + 1707420917U, // <7,4,4,u>: Cost 2 vsldoi12 RHS, <4,4,u,5> + 1584316518U, // <7,4,5,0>: Cost 2 vsldoi4 <6,7,4,5>, LHS + 2658059060U, // <7,4,5,1>: Cost 3 vsldoi4 <6,7,4,5>, <1,1,1,1> + 2640144314U, // <7,4,5,2>: Cost 3 vsldoi4 <3,7,4,5>, <2,6,3,7> + 2640145131U, // <7,4,5,3>: Cost 3 vsldoi4 <3,7,4,5>, <3,7,4,5> + 1584319798U, // <7,4,5,4>: Cost 2 vsldoi4 <6,7,4,5>, RHS + 2779172134U, // <7,4,5,5>: Cost 3 vsldoi12 RHS, <4,5,5,0> + 631688502U, // <7,4,5,6>: Cost 1 vsldoi12 RHS, RHS + 2658063354U, // <7,4,5,7>: Cost 3 vsldoi4 <6,7,4,5>, <7,0,1,2> + 631688520U, // <7,4,5,u>: Cost 1 vsldoi12 RHS, RHS + 3852914001U, // <7,4,6,0>: Cost 4 vsldoi12 RHS, <4,6,0,7> + 3852914010U, // <7,4,6,1>: Cost 4 vsldoi12 RHS, <4,6,1,7> + 2718749178U, // <7,4,6,2>: Cost 3 vsldoi8 <5,6,7,4>, <6,2,7,3> + 2722730572U, // <7,4,6,3>: Cost 3 vsldoi8 <6,3,7,4>, <6,3,7,4> + 2723394205U, // <7,4,6,4>: Cost 3 vsldoi8 <6,4,7,4>, <6,4,7,4> + 2779172221U, // <7,4,6,5>: Cost 3 vsldoi12 RHS, <4,6,5,6> + 2718749496U, // <7,4,6,6>: Cost 3 vsldoi8 <5,6,7,4>, <6,6,6,6> + 2718749518U, // <7,4,6,7>: Cost 3 vsldoi8 <5,6,7,4>, <6,7,0,1> + 2779172249U, // <7,4,6,u>: Cost 3 vsldoi12 RHS, <4,6,u,7> + 2718749690U, // <7,4,7,0>: Cost 3 vsldoi8 <5,6,7,4>, <7,0,1,2> + 3847458214U, // <7,4,7,1>: Cost 4 vsldoi12 <3,6,4,7>, <4,7,1,2> + 2718749880U, // <7,4,7,2>: Cost 3 vsldoi8 <5,6,7,4>, <7,2,4,3> + 3847458236U, // <7,4,7,3>: Cost 4 vsldoi12 <3,6,4,7>, <4,7,3,6> + 2718750004U, // <7,4,7,4>: Cost 3 vsldoi8 <5,6,7,4>, <7,4,0,1> + 1187876150U, // <7,4,7,5>: Cost 2 vmrghw <7,7,7,7>, RHS + 2718750208U, // <7,4,7,6>: Cost 3 vsldoi8 <5,6,7,4>, <7,6,4,7> + 2718750286U, // <7,4,7,7>: Cost 3 vsldoi8 <5,6,7,4>, <7,7,4,4> + 1187876393U, // <7,4,7,u>: Cost 2 vmrghw <7,7,7,7>, RHS + 1584341094U, // <7,4,u,0>: Cost 2 vsldoi4 <6,7,4,u>, LHS + 1645008686U, // <7,4,u,1>: Cost 2 vsldoi8 <5,6,7,4>, LHS + 2640168890U, // <7,4,u,2>: Cost 3 vsldoi4 <3,7,4,u>, <2,6,3,7> + 2640169710U, // <7,4,u,3>: Cost 3 vsldoi4 <3,7,4,u>, <3,7,4,u> + 1584344374U, // <7,4,u,4>: Cost 2 vsldoi4 <6,7,4,u>, RHS + 1705430554U, // <7,4,u,5>: Cost 2 vsldoi12 RHS, <4,u,5,1> + 631688745U, // <7,4,u,6>: Cost 1 vsldoi12 RHS, RHS + 2718750976U, // <7,4,u,7>: Cost 3 vsldoi8 <5,6,7,4>, + 631688763U, // <7,4,u,u>: Cost 1 vsldoi12 RHS, RHS + 2646147174U, // <7,5,0,0>: Cost 3 vsldoi4 <4,7,5,0>, LHS + 2779172424U, // <7,5,0,1>: Cost 3 vsldoi12 RHS, <5,0,1,2> + 3852914258U, // <7,5,0,2>: Cost 4 vsldoi12 RHS, <5,0,2,3> + 3852914268U, // <7,5,0,3>: Cost 4 vsldoi12 RHS, <5,0,3,4> + 2779172450U, // <7,5,0,4>: Cost 3 vsldoi12 RHS, <5,0,4,1> + 2316061914U, // <7,5,0,5>: Cost 3 vmrglw <5,6,7,0>, <4,4,5,5> + 2316061186U, // <7,5,0,6>: Cost 3 vmrglw <5,6,7,0>, <3,4,5,6> + 2646152186U, // <7,5,0,7>: Cost 3 vsldoi4 <4,7,5,0>, <7,0,1,2> + 2779172486U, // <7,5,0,u>: Cost 3 vsldoi12 RHS, <5,0,u,1> + 2781163151U, // <7,5,1,0>: Cost 3 vsldoi12 RHS, <5,1,0,1> + 2321378194U, // <7,5,1,1>: Cost 3 vmrglw <6,5,7,1>, <4,0,5,1> + 3852914339U, // <7,5,1,2>: Cost 4 vsldoi12 RHS, <5,1,2,3> + 3852914350U, // <7,5,1,3>: Cost 4 vsldoi12 RHS, <5,1,3,5> + 2781163191U, // <7,5,1,4>: Cost 3 vsldoi12 RHS, <5,1,4,5> + 3852914363U, // <7,5,1,5>: Cost 4 vsldoi12 RHS, <5,1,5,0> + 3835588297U, // <7,5,1,6>: Cost 4 vsldoi12 <1,6,5,7>, <5,1,6,5> + 3835588306U, // <7,5,1,7>: Cost 4 vsldoi12 <1,6,5,7>, <5,1,7,5> + 2781163223U, // <7,5,1,u>: Cost 3 vsldoi12 RHS, <5,1,u,1> + 3852914400U, // <7,5,2,0>: Cost 4 vsldoi12 RHS, <5,2,0,1> + 2781163243U, // <7,5,2,1>: Cost 3 vsldoi12 RHS, <5,2,1,3> + 3852914419U, // <7,5,2,2>: Cost 4 vsldoi12 RHS, <5,2,2,2> + 2779172606U, // <7,5,2,3>: Cost 3 vsldoi12 RHS, <5,2,3,4> + 3780552497U, // <7,5,2,4>: Cost 4 vsldoi8 <3,6,7,5>, <2,4,6,5> + 2781163279U, // <7,5,2,5>: Cost 3 vsldoi12 RHS, <5,2,5,3> + 2779172632U, // <7,5,2,6>: Cost 3 vsldoi12 RHS, <5,2,6,3> + 3835588385U, // <7,5,2,7>: Cost 4 vsldoi12 <1,6,5,7>, <5,2,7,3> + 2779172650U, // <7,5,2,u>: Cost 3 vsldoi12 RHS, <5,2,u,3> + 3852914481U, // <7,5,3,0>: Cost 4 vsldoi12 RHS, <5,3,0,1> + 2319403922U, // <7,5,3,1>: Cost 3 vmrglw <6,2,7,3>, <4,0,5,1> + 2319404409U, // <7,5,3,2>: Cost 3 vmrglw <6,2,7,3>, <4,6,5,2> + 3852914510U, // <7,5,3,3>: Cost 4 vsldoi12 RHS, <5,3,3,3> + 3779226131U, // <7,5,3,4>: Cost 4 vsldoi8 <3,4,7,5>, <3,4,7,5> + 2319404250U, // <7,5,3,5>: Cost 3 vmrglw <6,2,7,3>, <4,4,5,5> + 2319403522U, // <7,5,3,6>: Cost 3 vmrglw <6,2,7,3>, <3,4,5,6> + 3852914547U, // <7,5,3,7>: Cost 4 vsldoi12 RHS, <5,3,7,4> + 2319403524U, // <7,5,3,u>: Cost 3 vmrglw <6,2,7,3>, <3,4,5,u> + 2646179942U, // <7,5,4,0>: Cost 3 vsldoi4 <4,7,5,4>, LHS + 2316094354U, // <7,5,4,1>: Cost 3 vmrglw <5,6,7,4>, <4,0,5,1> + 3852914582U, // <7,5,4,2>: Cost 4 vsldoi12 RHS, <5,4,2,3> + 3852914592U, // <7,5,4,3>: Cost 4 vsldoi12 RHS, <5,4,3,4> + 2646183372U, // <7,5,4,4>: Cost 3 vsldoi4 <4,7,5,4>, <4,7,5,4> + 2779172788U, // <7,5,4,5>: Cost 3 vsldoi12 RHS, <5,4,5,6> + 2316093954U, // <7,5,4,6>: Cost 3 vmrglw <5,6,7,4>, <3,4,5,6> + 2646185318U, // <7,5,4,7>: Cost 3 vsldoi4 <4,7,5,4>, <7,4,5,6> + 2779172815U, // <7,5,4,u>: Cost 3 vsldoi12 RHS, <5,4,u,6> + 2781163475U, // <7,5,5,0>: Cost 3 vsldoi12 RHS, <5,5,0,1> + 2781163484U, // <7,5,5,1>: Cost 3 vsldoi12 RHS, <5,5,1,1> + 3852914662U, // <7,5,5,2>: Cost 4 vsldoi12 RHS, <5,5,2,2> + 3852914672U, // <7,5,5,3>: Cost 4 vsldoi12 RHS, <5,5,3,3> + 2781163515U, // <7,5,5,4>: Cost 3 vsldoi12 RHS, <5,5,4,5> + 1705431044U, // <7,5,5,5>: Cost 2 vsldoi12 RHS, <5,5,5,5> + 2779172878U, // <7,5,5,6>: Cost 3 vsldoi12 RHS, <5,5,6,6> + 3835588632U, // <7,5,5,7>: Cost 4 vsldoi12 <1,6,5,7>, <5,5,7,7> + 1705431044U, // <7,5,5,u>: Cost 2 vsldoi12 RHS, <5,5,5,5> + 2779172900U, // <7,5,6,0>: Cost 3 vsldoi12 RHS, <5,6,0,1> + 2781163571U, // <7,5,6,1>: Cost 3 vsldoi12 RHS, <5,6,1,7> + 3852914743U, // <7,5,6,2>: Cost 4 vsldoi12 RHS, <5,6,2,2> + 2779172930U, // <7,5,6,3>: Cost 3 vsldoi12 RHS, <5,6,3,4> + 2779172940U, // <7,5,6,4>: Cost 3 vsldoi12 RHS, <5,6,4,5> + 2781163607U, // <7,5,6,5>: Cost 3 vsldoi12 RHS, <5,6,5,7> + 2779172960U, // <7,5,6,6>: Cost 3 vsldoi12 RHS, <5,6,6,7> + 1705431138U, // <7,5,6,7>: Cost 2 vsldoi12 RHS, <5,6,7,0> + 1705578603U, // <7,5,6,u>: Cost 2 vsldoi12 RHS, <5,6,u,0> + 2646204518U, // <7,5,7,0>: Cost 3 vsldoi4 <4,7,5,7>, LHS + 2322090898U, // <7,5,7,1>: Cost 3 vmrglw <6,6,7,7>, <4,0,5,1> + 3719947880U, // <7,5,7,2>: Cost 4 vsldoi4 <4,7,5,7>, <2,2,2,2> + 3719948438U, // <7,5,7,3>: Cost 4 vsldoi4 <4,7,5,7>, <3,0,1,2> + 2646207951U, // <7,5,7,4>: Cost 3 vsldoi4 <4,7,5,7>, <4,7,5,7> + 2322091226U, // <7,5,7,5>: Cost 3 vmrglw <6,6,7,7>, <4,4,5,5> + 2322090498U, // <7,5,7,6>: Cost 3 vmrglw <6,6,7,7>, <3,4,5,6> + 2646210156U, // <7,5,7,7>: Cost 3 vsldoi4 <4,7,5,7>, <7,7,7,7> + 2646210350U, // <7,5,7,u>: Cost 3 vsldoi4 <4,7,5,7>, LHS + 2779173062U, // <7,5,u,0>: Cost 3 vsldoi12 RHS, <5,u,0,1> + 2779173072U, // <7,5,u,1>: Cost 3 vsldoi12 RHS, <5,u,1,2> + 2319404409U, // <7,5,u,2>: Cost 3 vmrglw <6,2,7,3>, <4,6,5,2> + 2779173092U, // <7,5,u,3>: Cost 3 vsldoi12 RHS, <5,u,3,4> + 2779173101U, // <7,5,u,4>: Cost 3 vsldoi12 RHS, <5,u,4,4> + 1705431044U, // <7,5,u,5>: Cost 2 vsldoi12 RHS, <5,5,5,5> + 2779173118U, // <7,5,u,6>: Cost 3 vsldoi12 RHS, <5,u,6,3> + 1705578756U, // <7,5,u,7>: Cost 2 vsldoi12 RHS, <5,u,7,0> + 1707421965U, // <7,5,u,u>: Cost 2 vsldoi12 RHS, <5,u,u,0> + 3852914966U, // <7,6,0,0>: Cost 4 vsldoi12 RHS, <6,0,0,0> + 2779173153U, // <7,6,0,1>: Cost 3 vsldoi12 RHS, <6,0,1,2> + 2256491002U, // <7,6,0,2>: Cost 3 vmrghw <7,0,1,2>, <6,2,7,3> + 3852914994U, // <7,6,0,3>: Cost 4 vsldoi12 RHS, <6,0,3,1> + 3852915003U, // <7,6,0,4>: Cost 4 vsldoi12 RHS, <6,0,4,1> + 2316062652U, // <7,6,0,5>: Cost 3 vmrglw <5,6,7,0>, <5,4,6,5> + 2316063544U, // <7,6,0,6>: Cost 3 vmrglw <5,6,7,0>, <6,6,6,6> + 1242320182U, // <7,6,0,7>: Cost 2 vmrglw <5,6,7,0>, RHS + 1242320183U, // <7,6,0,u>: Cost 2 vmrglw <5,6,7,0>, RHS + 3852915048U, // <7,6,1,0>: Cost 4 vsldoi12 RHS, <6,1,0,1> + 3377866217U, // <7,6,1,1>: Cost 4 vmrglw <3,6,7,1>, <2,0,6,1> + 3852915068U, // <7,6,1,2>: Cost 4 vsldoi12 RHS, <6,1,2,3> + 3833672072U, // <7,6,1,3>: Cost 5 vsldoi12 <1,3,6,7>, <6,1,3,6> + 3852915088U, // <7,6,1,4>: Cost 4 vsldoi12 RHS, <6,1,4,5> + 3395122056U, // <7,6,1,5>: Cost 4 vmrglw <6,5,7,1>, <6,7,6,5> + 3389813560U, // <7,6,1,6>: Cost 4 vmrglw <5,6,7,1>, <6,6,6,6> + 2779173287U, // <7,6,1,7>: Cost 3 vsldoi12 RHS, <6,1,7,1> + 2779320752U, // <7,6,1,u>: Cost 3 vsldoi12 RHS, <6,1,u,1> + 2658181222U, // <7,6,2,0>: Cost 3 vsldoi4 <6,7,6,2>, LHS + 3852915140U, // <7,6,2,1>: Cost 4 vsldoi12 RHS, <6,2,1,3> + 2257973754U, // <7,6,2,2>: Cost 3 vmrghw <7,2,3,3>, <6,2,7,3> + 3841413589U, // <7,6,2,3>: Cost 4 vsldoi12 <2,6,3,7>, <6,2,3,2> + 2658184502U, // <7,6,2,4>: Cost 3 vsldoi4 <6,7,6,2>, RHS + 3852915176U, // <7,6,2,5>: Cost 4 vsldoi12 RHS, <6,2,5,3> + 2658186117U, // <7,6,2,6>: Cost 3 vsldoi4 <6,7,6,2>, <6,7,6,2> + 1705431546U, // <7,6,2,7>: Cost 2 vsldoi12 RHS, <6,2,7,3> + 1705579011U, // <7,6,2,u>: Cost 2 vsldoi12 RHS, <6,2,u,3> + 3714015334U, // <7,6,3,0>: Cost 4 vsldoi4 <3,7,6,3>, LHS + 3777243425U, // <7,6,3,1>: Cost 4 vsldoi8 <3,1,7,6>, <3,1,7,6> + 2319405957U, // <7,6,3,2>: Cost 3 vmrglw <6,2,7,3>, <6,7,6,2> + 3375229286U, // <7,6,3,3>: Cost 4 vmrglw <3,2,7,3>, <3,2,6,3> + 2779173426U, // <7,6,3,4>: Cost 3 vsldoi12 RHS, <6,3,4,5> + 3375228721U, // <7,6,3,5>: Cost 4 vmrglw <3,2,7,3>, <2,4,6,5> + 2319405880U, // <7,6,3,6>: Cost 3 vmrglw <6,2,7,3>, <6,6,6,6> + 1245662518U, // <7,6,3,7>: Cost 2 vmrglw <6,2,7,3>, RHS + 1245662519U, // <7,6,3,u>: Cost 2 vmrglw <6,2,7,3>, RHS + 3852915291U, // <7,6,4,0>: Cost 4 vsldoi12 RHS, <6,4,0,1> + 3389834729U, // <7,6,4,1>: Cost 4 vmrglw <5,6,7,4>, <2,0,6,1> + 2259472890U, // <7,6,4,2>: Cost 3 vmrghw <7,4,5,6>, <6,2,7,3> + 3852915321U, // <7,6,4,3>: Cost 4 vsldoi12 RHS, <6,4,3,4> + 3852915330U, // <7,6,4,4>: Cost 4 vsldoi12 RHS, <6,4,4,4> + 2779173517U, // <7,6,4,5>: Cost 3 vsldoi12 RHS, <6,4,5,6> + 2316096312U, // <7,6,4,6>: Cost 3 vmrglw <5,6,7,4>, <6,6,6,6> + 1242352950U, // <7,6,4,7>: Cost 2 vmrglw <5,6,7,4>, RHS + 1242352951U, // <7,6,4,u>: Cost 2 vmrglw <5,6,7,4>, RHS + 3852915372U, // <7,6,5,0>: Cost 4 vsldoi12 RHS, <6,5,0,1> + 3835294392U, // <7,6,5,1>: Cost 5 vsldoi12 <1,6,1,7>, <6,5,1,4> + 3852915395U, // <7,6,5,2>: Cost 4 vsldoi12 RHS, <6,5,2,6> + 3852915404U, // <7,6,5,3>: Cost 4 vsldoi12 RHS, <6,5,3,6> + 3852915412U, // <7,6,5,4>: Cost 4 vsldoi12 RHS, <6,5,4,5> + 3377899313U, // <7,6,5,5>: Cost 4 vmrglw <3,6,7,5>, <2,4,6,5> + 2718765160U, // <7,6,5,6>: Cost 3 vsldoi8 <5,6,7,6>, <5,6,7,6> + 2779173611U, // <7,6,5,7>: Cost 3 vsldoi12 RHS, <6,5,7,1> + 2779321076U, // <7,6,5,u>: Cost 3 vsldoi12 RHS, <6,5,u,1> + 2658213990U, // <7,6,6,0>: Cost 3 vsldoi4 <6,7,6,6>, LHS + 3852915462U, // <7,6,6,1>: Cost 4 vsldoi12 RHS, <6,6,1,1> + 2718765562U, // <7,6,6,2>: Cost 3 vsldoi8 <5,6,7,6>, <6,2,7,3> + 3714042622U, // <7,6,6,3>: Cost 4 vsldoi4 <3,7,6,6>, <3,7,6,6> + 2658217270U, // <7,6,6,4>: Cost 3 vsldoi4 <6,7,6,6>, RHS + 2724074224U, // <7,6,6,5>: Cost 3 vsldoi8 <6,5,7,6>, <6,5,7,6> + 1705431864U, // <7,6,6,6>: Cost 2 vsldoi12 RHS, <6,6,6,6> + 1705431874U, // <7,6,6,7>: Cost 2 vsldoi12 RHS, <6,6,7,7> + 1705579339U, // <7,6,6,u>: Cost 2 vsldoi12 RHS, <6,6,u,7> + 1705431886U, // <7,6,7,0>: Cost 2 vsldoi12 RHS, <6,7,0,1> + 2779173719U, // <7,6,7,1>: Cost 3 vsldoi12 RHS, <6,7,1,1> + 2779173729U, // <7,6,7,2>: Cost 3 vsldoi12 RHS, <6,7,2,2> + 2779173736U, // <7,6,7,3>: Cost 3 vsldoi12 RHS, <6,7,3,0> + 1705431926U, // <7,6,7,4>: Cost 2 vsldoi12 RHS, <6,7,4,5> + 2779173759U, // <7,6,7,5>: Cost 3 vsldoi12 RHS, <6,7,5,5> + 2779173765U, // <7,6,7,6>: Cost 3 vsldoi12 RHS, <6,7,6,2> + 1248349494U, // <7,6,7,7>: Cost 2 vmrglw <6,6,7,7>, RHS + 1705431958U, // <7,6,7,u>: Cost 2 vsldoi12 RHS, <6,7,u,1> + 1705579423U, // <7,6,u,0>: Cost 2 vsldoi12 RHS, <6,u,0,1> + 2779173801U, // <7,6,u,1>: Cost 3 vsldoi12 RHS, <6,u,1,2> + 2779321266U, // <7,6,u,2>: Cost 3 vsldoi12 RHS, <6,u,2,2> + 2779321273U, // <7,6,u,3>: Cost 3 vsldoi12 RHS, <6,u,3,0> + 1705579463U, // <7,6,u,4>: Cost 2 vsldoi12 RHS, <6,u,4,5> + 2779173841U, // <7,6,u,5>: Cost 3 vsldoi12 RHS, <6,u,5,6> + 1705431864U, // <7,6,u,6>: Cost 2 vsldoi12 RHS, <6,6,6,6> + 1705432032U, // <7,6,u,7>: Cost 2 vsldoi12 RHS, <6,u,7,3> + 1705579495U, // <7,6,u,u>: Cost 2 vsldoi12 RHS, <6,u,u,1> + 1242320994U, // <7,7,0,0>: Cost 2 vmrglw <5,6,7,0>, <5,6,7,0> + 1705432058U, // <7,7,0,1>: Cost 2 vsldoi12 RHS, <7,0,1,2> + 3841414146U, // <7,7,0,2>: Cost 4 vsldoi12 <2,6,3,7>, <7,0,2,1> + 2316063226U, // <7,7,0,3>: Cost 3 vmrglw <5,6,7,0>, <6,2,7,3> + 2779173908U, // <7,7,0,4>: Cost 3 vsldoi12 RHS, <7,0,4,1> + 2658242658U, // <7,7,0,5>: Cost 3 vsldoi4 <6,7,7,0>, <5,6,7,0> + 2658243468U, // <7,7,0,6>: Cost 3 vsldoi4 <6,7,7,0>, <6,7,7,0> + 2316063554U, // <7,7,0,7>: Cost 3 vmrglw <5,6,7,0>, <6,6,7,7> + 1705432121U, // <7,7,0,u>: Cost 2 vsldoi12 RHS, <7,0,u,2> + 3852915777U, // <7,7,1,0>: Cost 4 vsldoi12 RHS, <7,1,0,1> + 2779173962U, // <7,7,1,1>: Cost 3 vsldoi12 RHS, <7,1,1,1> + 2779173973U, // <7,7,1,2>: Cost 3 vsldoi12 RHS, <7,1,2,3> + 3389813242U, // <7,7,1,3>: Cost 4 vmrglw <5,6,7,1>, <6,2,7,3> + 3852915813U, // <7,7,1,4>: Cost 4 vsldoi12 RHS, <7,1,4,1> + 3852915821U, // <7,7,1,5>: Cost 4 vsldoi12 RHS, <7,1,5,0> + 3835294839U, // <7,7,1,6>: Cost 4 vsldoi12 <1,6,1,7>, <7,1,6,1> + 2329343596U, // <7,7,1,7>: Cost 3 vmrglw <7,u,7,1>, <7,7,7,7> + 2779174027U, // <7,7,1,u>: Cost 3 vsldoi12 RHS, <7,1,u,3> + 2803061908U, // <7,7,2,0>: Cost 3 vsldoi12 RHS, <7,2,0,3> + 3852915869U, // <7,7,2,1>: Cost 4 vsldoi12 RHS, <7,2,1,3> + 2779174053U, // <7,7,2,2>: Cost 3 vsldoi12 RHS, <7,2,2,2> + 2779174060U, // <7,7,2,3>: Cost 3 vsldoi12 RHS, <7,2,3,0> + 2803061944U, // <7,7,2,4>: Cost 3 vsldoi12 RHS, <7,2,4,3> + 3852915905U, // <7,7,2,5>: Cost 4 vsldoi12 RHS, <7,2,5,3> + 2767672522U, // <7,7,2,6>: Cost 3 vsldoi12 <2,6,3,7>, <7,2,6,3> + 2791855315U, // <7,7,2,7>: Cost 3 vsldoi12 <6,6,7,7>, <7,2,7,3> + 2768999644U, // <7,7,2,u>: Cost 3 vsldoi12 <2,u,3,7>, <7,2,u,3> + 2779174115U, // <7,7,3,0>: Cost 3 vsldoi12 RHS, <7,3,0,1> + 3852915948U, // <7,7,3,1>: Cost 4 vsldoi12 RHS, <7,3,1,1> + 3841414394U, // <7,7,3,2>: Cost 4 vsldoi12 <2,6,3,7>, <7,3,2,6> + 1245663738U, // <7,7,3,3>: Cost 2 vmrglw <6,2,7,3>, <6,2,7,3> + 2779174155U, // <7,7,3,4>: Cost 3 vsldoi12 RHS, <7,3,4,5> + 3852915988U, // <7,7,3,5>: Cost 4 vsldoi12 RHS, <7,3,5,5> + 2706827959U, // <7,7,3,6>: Cost 3 vsldoi8 <3,6,7,7>, <3,6,7,7> + 2319405890U, // <7,7,3,7>: Cost 3 vmrglw <6,2,7,3>, <6,6,7,7> + 1245663738U, // <7,7,3,u>: Cost 2 vmrglw <6,2,7,3>, <6,2,7,3> + 2779174200U, // <7,7,4,0>: Cost 3 vsldoi12 RHS, <7,4,0,5> + 3852916030U, // <7,7,4,1>: Cost 4 vsldoi12 RHS, <7,4,1,2> + 3714099130U, // <7,7,4,2>: Cost 4 vsldoi4 <3,7,7,4>, <2,6,3,7> + 2316095994U, // <7,7,4,3>: Cost 3 vmrglw <5,6,7,4>, <6,2,7,3> + 1242353766U, // <7,7,4,4>: Cost 2 vmrglw <5,6,7,4>, <5,6,7,4> + 1705432422U, // <7,7,4,5>: Cost 2 vsldoi12 RHS, <7,4,5,6> + 2658276240U, // <7,7,4,6>: Cost 3 vsldoi4 <6,7,7,4>, <6,7,7,4> + 2316096322U, // <7,7,4,7>: Cost 3 vmrglw <5,6,7,4>, <6,6,7,7> + 1705432449U, // <7,7,4,u>: Cost 2 vsldoi12 RHS, <7,4,u,6> + 3852916101U, // <7,7,5,0>: Cost 4 vsldoi12 RHS, <7,5,0,1> + 3854906765U, // <7,7,5,1>: Cost 4 vsldoi12 RHS, <7,5,1,0> + 3852916121U, // <7,7,5,2>: Cost 4 vsldoi12 RHS, <7,5,2,3> + 3389846010U, // <7,7,5,3>: Cost 4 vmrglw <5,6,7,5>, <6,2,7,3> + 3852916141U, // <7,7,5,4>: Cost 4 vsldoi12 RHS, <7,5,4,5> + 2779174326U, // <7,7,5,5>: Cost 3 vsldoi12 RHS, <7,5,5,5> + 2779174337U, // <7,7,5,6>: Cost 3 vsldoi12 RHS, <7,5,6,7> + 2329376364U, // <7,7,5,7>: Cost 3 vmrglw <7,u,7,5>, <7,7,7,7> + 2779321811U, // <7,7,5,u>: Cost 3 vsldoi12 RHS, <7,5,u,7> + 2658287718U, // <7,7,6,0>: Cost 3 vsldoi4 <6,7,7,6>, LHS + 3852916197U, // <7,7,6,1>: Cost 4 vsldoi12 RHS, <7,6,1,7> + 2779174382U, // <7,7,6,2>: Cost 3 vsldoi12 RHS, <7,6,2,7> + 2316112378U, // <7,7,6,3>: Cost 3 vmrglw <5,6,7,6>, <6,2,7,3> + 2658290998U, // <7,7,6,4>: Cost 3 vsldoi4 <6,7,7,6>, RHS + 3852916233U, // <7,7,6,5>: Cost 4 vsldoi12 RHS, <7,6,5,7> + 1651004226U, // <7,7,6,6>: Cost 2 vsldoi8 <6,6,7,7>, <6,6,7,7> + 2779174420U, // <7,7,6,7>: Cost 3 vsldoi12 RHS, <7,6,7,0> + 1652331492U, // <7,7,6,u>: Cost 2 vsldoi8 <6,u,7,7>, <6,u,7,7> + 1590526054U, // <7,7,7,0>: Cost 2 vsldoi4 <7,7,7,7>, LHS + 2328728623U, // <7,7,7,1>: Cost 3 vmrglw <7,7,7,7>, <7,0,7,1> + 2724746451U, // <7,7,7,2>: Cost 3 vsldoi8 <6,6,7,7>, <7,2,7,3> + 2322092538U, // <7,7,7,3>: Cost 3 vmrglw <6,6,7,7>, <6,2,7,3> + 1590529334U, // <7,7,7,4>: Cost 2 vsldoi4 <7,7,7,7>, RHS + 2328728951U, // <7,7,7,5>: Cost 3 vmrglw <7,7,7,7>, <7,4,7,5> + 2724746770U, // <7,7,7,6>: Cost 3 vsldoi8 <6,6,7,7>, <7,6,6,7> + 430361910U, // <7,7,7,7>: Cost 1 vspltisw3 RHS + 430361910U, // <7,7,7,u>: Cost 1 vspltisw3 RHS + 1242320994U, // <7,7,u,0>: Cost 2 vmrglw <5,6,7,0>, <5,6,7,0> + 1705580162U, // <7,7,u,1>: Cost 2 vsldoi12 RHS, <7,u,1,2> + 2779321996U, // <7,7,u,2>: Cost 3 vsldoi12 RHS, <7,u,2,3> + 1245663738U, // <7,7,u,3>: Cost 2 vmrglw <6,2,7,3>, <6,2,7,3> + 1242353766U, // <7,7,u,4>: Cost 2 vmrglw <5,6,7,4>, <5,6,7,4> + 1705580202U, // <7,7,u,5>: Cost 2 vsldoi12 RHS, <7,u,5,6> + 1662949620U, // <7,7,u,6>: Cost 2 vsldoi8 , + 430361910U, // <7,7,u,7>: Cost 1 vspltisw3 RHS + 430361910U, // <7,7,u,u>: Cost 1 vspltisw3 RHS + 1705426944U, // <7,u,0,0>: Cost 2 vsldoi12 RHS, <0,0,0,0> + 1705432787U, // <7,u,0,1>: Cost 2 vsldoi12 RHS, + 2316060885U, // <7,u,0,2>: Cost 3 vmrglw <5,6,7,0>, <3,0,u,2> + 1242316956U, // <7,u,0,3>: Cost 2 vmrglw <5,6,7,0>, LHS + 2779174637U, // <7,u,0,4>: Cost 3 vsldoi12 RHS, + 1182750874U, // <7,u,0,5>: Cost 2 vmrghw <7,0,1,2>, RHS + 2316061213U, // <7,u,0,6>: Cost 3 vmrglw <5,6,7,0>, <3,4,u,6> + 1242320200U, // <7,u,0,7>: Cost 2 vmrglw <5,6,7,0>, RHS + 1705432850U, // <7,u,0,u>: Cost 2 vsldoi12 RHS, + 1584578662U, // <7,u,1,0>: Cost 2 vsldoi4 <6,7,u,1>, LHS + 1705427764U, // <7,u,1,1>: Cost 2 vsldoi12 RHS, <1,1,1,1> + 631691054U, // <7,u,1,2>: Cost 1 vsldoi12 RHS, LHS + 2640407307U, // <7,u,1,3>: Cost 3 vsldoi4 <3,7,u,1>, <3,7,u,1> + 1584581942U, // <7,u,1,4>: Cost 2 vsldoi4 <6,7,u,1>, RHS + 2779174726U, // <7,u,1,5>: Cost 3 vsldoi12 RHS, + 1584583574U, // <7,u,1,6>: Cost 2 vsldoi4 <6,7,u,1>, <6,7,u,1> + 2779322201U, // <7,u,1,7>: Cost 3 vsldoi12 RHS, + 631691108U, // <7,u,1,u>: Cost 1 vsldoi12 RHS, LHS + 2779174763U, // <7,u,2,0>: Cost 3 vsldoi12 RHS, + 2779174774U, // <7,u,2,1>: Cost 3 vsldoi12 RHS, + 1705428584U, // <7,u,2,2>: Cost 2 vsldoi12 RHS, <2,2,2,2> + 1705432965U, // <7,u,2,3>: Cost 2 vsldoi12 RHS, + 2779174801U, // <7,u,2,4>: Cost 3 vsldoi12 RHS, + 2779174810U, // <7,u,2,5>: Cost 3 vsldoi12 RHS, + 2767673251U, // <7,u,2,6>: Cost 3 vsldoi12 <2,6,3,7>, + 1705580460U, // <7,u,2,7>: Cost 2 vsldoi12 RHS, + 1705433010U, // <7,u,2,u>: Cost 2 vsldoi12 RHS, + 1705433020U, // <7,u,3,0>: Cost 2 vsldoi12 RHS, + 2779174853U, // <7,u,3,1>: Cost 3 vsldoi12 RHS, + 2767673299U, // <7,u,3,2>: Cost 3 vsldoi12 <2,6,3,7>, + 1245659292U, // <7,u,3,3>: Cost 2 vmrglw <6,2,7,3>, LHS + 1705433060U, // <7,u,3,4>: Cost 2 vsldoi12 RHS, + 2779174893U, // <7,u,3,5>: Cost 3 vsldoi12 RHS, + 2706836152U, // <7,u,3,6>: Cost 3 vsldoi8 <3,6,7,u>, <3,6,7,u> + 1245662536U, // <7,u,3,7>: Cost 2 vmrglw <6,2,7,3>, RHS + 1705433092U, // <7,u,3,u>: Cost 2 vsldoi12 RHS, + 2779174925U, // <7,u,4,0>: Cost 3 vsldoi12 RHS, + 1185732398U, // <7,u,4,1>: Cost 2 vmrghw <7,4,5,6>, LHS + 2316093653U, // <7,u,4,2>: Cost 3 vmrglw <5,6,7,4>, <3,0,u,2> + 1242349724U, // <7,u,4,3>: Cost 2 vmrglw <5,6,7,4>, LHS + 1705430224U, // <7,u,4,4>: Cost 2 vsldoi12 RHS, <4,4,4,4> + 1705433151U, // <7,u,4,5>: Cost 2 vsldoi12 RHS, + 2316093981U, // <7,u,4,6>: Cost 3 vmrglw <5,6,7,4>, <3,4,u,6> + 1242352968U, // <7,u,4,7>: Cost 2 vmrglw <5,6,7,4>, RHS + 1705433178U, // <7,u,4,u>: Cost 2 vsldoi12 RHS, + 1584611430U, // <7,u,5,0>: Cost 2 vsldoi4 <6,7,u,5>, LHS + 2781165670U, // <7,u,5,1>: Cost 3 vsldoi12 RHS, + 2640439226U, // <7,u,5,2>: Cost 3 vsldoi4 <3,7,u,5>, <2,6,3,7> + 2640440079U, // <7,u,5,3>: Cost 3 vsldoi4 <3,7,u,5>, <3,7,u,5> + 1584614710U, // <7,u,5,4>: Cost 2 vsldoi4 <6,7,u,5>, RHS + 1705431044U, // <7,u,5,5>: Cost 2 vsldoi12 RHS, <5,5,5,5> + 631691418U, // <7,u,5,6>: Cost 1 vsldoi12 RHS, RHS + 2779322525U, // <7,u,5,7>: Cost 3 vsldoi12 RHS, + 631691436U, // <7,u,5,u>: Cost 1 vsldoi12 RHS, RHS + 2779175087U, // <7,u,6,0>: Cost 3 vsldoi12 RHS, + 2779175102U, // <7,u,6,1>: Cost 3 vsldoi12 RHS, + 1648357887U, // <7,u,6,2>: Cost 2 vsldoi8 <6,2,7,u>, <6,2,7,u> + 1705433296U, // <7,u,6,3>: Cost 2 vsldoi12 RHS, + 2779175127U, // <7,u,6,4>: Cost 3 vsldoi12 RHS, + 2779175138U, // <7,u,6,5>: Cost 3 vsldoi12 RHS, + 1651012419U, // <7,u,6,6>: Cost 2 vsldoi8 <6,6,7,u>, <6,6,7,u> + 1705580788U, // <7,u,6,7>: Cost 2 vsldoi12 RHS, + 1705433341U, // <7,u,6,u>: Cost 2 vsldoi12 RHS, + 1705580800U, // <7,u,7,0>: Cost 2 vsldoi12 RHS, + 1187878702U, // <7,u,7,1>: Cost 2 vmrghw <7,7,7,7>, LHS + 2768042263U, // <7,u,7,2>: Cost 3 vsldoi12 <2,6,u,7>, + 1248346268U, // <7,u,7,3>: Cost 2 vmrglw <6,6,7,7>, LHS + 1705580840U, // <7,u,7,4>: Cost 2 vsldoi12 RHS, + 1187879066U, // <7,u,7,5>: Cost 2 vmrghw <7,7,7,7>, RHS + 2779322679U, // <7,u,7,6>: Cost 3 vsldoi12 RHS, + 430361910U, // <7,u,7,7>: Cost 1 vspltisw3 RHS + 430361910U, // <7,u,7,u>: Cost 1 vspltisw3 RHS + 1705433425U, // <7,u,u,0>: Cost 2 vsldoi12 RHS, + 1705433435U, // <7,u,u,1>: Cost 2 vsldoi12 RHS, + 631691621U, // <7,u,u,2>: Cost 1 vsldoi12 RHS, LHS + 1705433451U, // <7,u,u,3>: Cost 2 vsldoi12 RHS, + 1705433465U, // <7,u,u,4>: Cost 2 vsldoi12 RHS, + 1705433475U, // <7,u,u,5>: Cost 2 vsldoi12 RHS, + 631691661U, // <7,u,u,6>: Cost 1 vsldoi12 RHS, RHS + 430361910U, // <7,u,u,7>: Cost 1 vspltisw3 RHS + 631691675U, // <7,u,u,u>: Cost 1 vsldoi12 RHS, LHS + 202162278U, // : Cost 1 vspltisw0 LHS + 1678598154U, // : Cost 2 vsldoi12 LHS, <0,0,1,1> + 2634500154U, // : Cost 3 vsldoi4 <2,u,0,0>, <2,u,0,0> + 2289596269U, // : Cost 3 vmrglw <1,2,u,0>, + 1548815670U, // : Cost 2 vsldoi4 <0,u,0,0>, RHS + 2663698530U, // : Cost 3 vsldoi4 <7,7,0,0>, <5,6,7,0> + 2658390942U, // : Cost 3 vsldoi4 <6,u,0,0>, <6,u,0,0> + 2289596597U, // : Cost 3 vmrglw <1,2,u,0>, + 202162278U, // : Cost 1 vspltisw0 LHS + 1560764518U, // : Cost 2 vsldoi4 <2,u,0,1>, LHS + 115720294U, // : Cost 1 vmrghw LHS, LHS + 604856427U, // : Cost 1 vsldoi12 LHS, LHS + 2634508438U, // : Cost 3 vsldoi4 <2,u,0,1>, <3,0,1,2> + 1560767798U, // : Cost 2 vsldoi4 <2,u,0,1>, RHS + 2652426438U, // : Cost 3 vsldoi4 <5,u,0,1>, <5,u,0,1> + 1584657311U, // : Cost 2 vsldoi4 <6,u,0,1>, <6,u,0,1> + 2658399226U, // : Cost 3 vsldoi4 <6,u,0,1>, <7,0,1,2> + 604856476U, // : Cost 1 vsldoi12 LHS, LHS + 2696889850U, // : Cost 3 vsldoi8 <2,0,u,0>, <2,0,u,0> + 1190174822U, // : Cost 2 vmrghw , LHS + 2692245096U, // : Cost 3 vsldoi8 <1,2,u,0>, <2,2,2,2> + 2692245158U, // : Cost 3 vsldoi8 <1,2,u,0>, <2,3,0,1> + 2263916882U, // : Cost 3 vmrghw , <0,4,1,5> + 2299709908U, // : Cost 3 vmrglw <3,0,1,2>, <3,4,0,5> + 2692245434U, // : Cost 3 vsldoi8 <1,2,u,0>, <2,6,3,7> + 2701535281U, // : Cost 3 vsldoi8 <2,7,u,0>, <2,7,u,0> + 1190175389U, // : Cost 2 vmrghw , LHS + 1209237504U, // : Cost 2 vmrglw LHS, <0,0,0,0> + 1209239206U, // : Cost 2 vmrglw LHS, <2,3,0,1> + 2704189813U, // : Cost 3 vsldoi8 <3,2,u,0>, <3,2,u,0> + 2692245916U, // : Cost 3 vsldoi8 <1,2,u,0>, <3,3,3,3> + 2282981033U, // : Cost 3 vmrglw LHS, <2,3,0,4> + 2664386658U, // : Cost 3 vsldoi4 <7,u,0,3>, <5,6,7,0> + 2691877496U, // : Cost 3 vsldoi8 <1,2,3,0>, <3,6,0,7> + 2664388218U, // : Cost 3 vsldoi4 <7,u,0,3>, <7,u,0,3> + 1209239213U, // : Cost 2 vmrglw LHS, <2,3,0,u> + 2289623040U, // : Cost 3 vmrglw <1,2,u,4>, <0,0,0,0> + 1678598482U, // : Cost 2 vsldoi12 LHS, <0,4,1,5> + 2634532926U, // : Cost 3 vsldoi4 <2,u,0,4>, <2,u,0,4> + 2235580672U, // : Cost 3 vmrghw <3,4,5,6>, <0,3,1,4> + 1143619922U, // : Cost 2 vmrghw <0,4,1,5>, <0,4,1,5> + 1618505014U, // : Cost 2 vsldoi8 <1,2,u,0>, RHS + 2658423714U, // : Cost 3 vsldoi4 <6,u,0,4>, <6,u,0,4> + 2713259464U, // : Cost 3 vsldoi8 <4,7,5,0>, <4,7,5,0> + 1683243409U, // : Cost 2 vsldoi12 LHS, <0,4,u,5> + 1192443904U, // : Cost 2 vmrghw RHS, <0,0,0,0> + 118702182U, // : Cost 1 vmrghw RHS, LHS + 2266185901U, // : Cost 3 vmrghw RHS, <0,2,1,2> + 2640513816U, // : Cost 3 vsldoi4 <3,u,0,5>, <3,u,0,5> + 1192444242U, // : Cost 2 vmrghw RHS, <0,4,1,5> + 2718789636U, // : Cost 3 vsldoi8 <5,6,u,0>, <5,5,5,5> + 1645047915U, // : Cost 2 vsldoi8 <5,6,u,0>, <5,6,u,0> + 2664404604U, // : Cost 3 vsldoi4 <7,u,0,5>, <7,u,0,5> + 118702749U, // : Cost 1 vmrghw RHS, LHS + 2302910464U, // : Cost 3 vmrglw <3,4,u,6>, <0,0,0,0> + 1192886374U, // : Cost 2 vmrghw , LHS + 2718790138U, // : Cost 3 vsldoi8 <5,6,u,0>, <6,2,7,3> + 2722771537U, // : Cost 3 vsldoi8 <6,3,u,0>, <6,3,u,0> + 2266628434U, // : Cost 3 vmrghw , <0,4,1,5> + 2248950180U, // : Cost 3 vmrghw <5,6,7,0>, <0,5,1,6> + 2718790456U, // : Cost 3 vsldoi8 <5,6,u,0>, <6,6,6,6> + 2718790478U, // : Cost 3 vsldoi8 <5,6,u,0>, <6,7,0,1> + 1192886941U, // : Cost 2 vmrghw , LHS + 1235812352U, // : Cost 2 vmrglw RHS, <0,0,0,0> + 1235814054U, // : Cost 2 vmrglw RHS, <2,3,0,1> + 2728080601U, // : Cost 3 vsldoi8 <7,2,u,0>, <7,2,u,0> + 2640530202U, // : Cost 3 vsldoi4 <3,u,0,7>, <3,u,0,7> + 2640530742U, // : Cost 3 vsldoi4 <3,u,0,7>, RHS + 2309556692U, // : Cost 3 vmrglw RHS, <3,4,0,5> + 2730735133U, // : Cost 3 vsldoi8 <7,6,u,0>, <7,6,u,0> + 2309556856U, // : Cost 3 vmrglw RHS, <3,6,0,7> + 1235814061U, // : Cost 2 vmrglw RHS, <2,3,0,u> + 202162278U, // : Cost 1 vspltisw0 LHS + 120365158U, // : Cost 1 vmrghw LHS, LHS + 604856989U, // : Cost 1 vsldoi12 LHS, LHS + 2692249532U, // : Cost 3 vsldoi8 <1,2,u,0>, + 1560825142U, // : Cost 2 vsldoi4 <2,u,0,u>, RHS + 1618507930U, // : Cost 2 vsldoi8 <1,2,u,0>, RHS + 1584714662U, // : Cost 2 vsldoi4 <6,u,0,u>, <6,u,0,u> + 2309565048U, // : Cost 3 vmrglw RHS, <3,6,0,7> + 604857043U, // : Cost 1 vsldoi12 LHS, LHS + 1611210825U, // : Cost 2 vsldoi8 <0,0,u,1>, <0,0,u,1> + 1616519270U, // : Cost 2 vsldoi8 <0,u,u,1>, LHS + 2287605459U, // : Cost 3 vmrglw <0,u,u,0>, + 2640546588U, // : Cost 3 vsldoi4 <3,u,1,0>, <3,u,1,0> + 2622631222U, // : Cost 3 vsldoi4 <0,u,1,0>, RHS + 2289590610U, // : Cost 3 vmrglw <1,2,u,0>, <0,4,1,5> + 2664436630U, // : Cost 3 vsldoi4 <7,u,1,0>, <6,7,u,1> + 2664437376U, // : Cost 3 vsldoi4 <7,u,1,0>, <7,u,1,0> + 1616519889U, // : Cost 2 vsldoi8 <0,u,u,1>, <0,u,u,1> + 1548894866U, // : Cost 2 vsldoi4 <0,u,1,1>, <0,u,1,1> + 269271142U, // : Cost 1 vspltisw1 LHS + 1189462934U, // : Cost 2 vmrghw LHS, <1,2,3,0> + 2622638230U, // : Cost 3 vsldoi4 <0,u,1,1>, <3,0,1,2> + 1548897590U, // : Cost 2 vsldoi4 <0,u,1,1>, RHS + 2756985692U, // : Cost 3 vsldoi12 LHS, <1,1,5,5> + 2658472872U, // : Cost 3 vsldoi4 <6,u,1,1>, <6,u,1,1> + 2287614142U, // : Cost 3 vmrglw <0,u,u,1>, + 269271142U, // : Cost 1 vspltisw1 LHS + 1566818406U, // : Cost 2 vsldoi4 <3,u,1,2>, LHS + 2756985735U, // : Cost 3 vsldoi12 LHS, <1,2,1,3> + 1148371862U, // : Cost 2 vmrghw <1,2,3,0>, <1,2,3,0> + 835584U, // : Cost 0 copy LHS + 1566821686U, // : Cost 2 vsldoi4 <3,u,1,2>, RHS + 2756985771U, // : Cost 3 vsldoi12 LHS, <1,2,5,3> + 2690262970U, // : Cost 3 vsldoi8 <0,u,u,1>, <2,6,3,7> + 1590711938U, // : Cost 2 vsldoi4 <7,u,1,2>, <7,u,1,2> + 835584U, // : Cost 0 copy LHS + 2282979337U, // : Cost 3 vmrglw LHS, <0,0,1,0> + 1209237514U, // : Cost 2 vmrglw LHS, <0,0,1,1> + 1209239702U, // : Cost 2 vmrglw LHS, <3,0,1,2> + 2282979502U, // : Cost 3 vmrglw LHS, <0,2,1,3> + 2282979341U, // : Cost 3 vmrglw LHS, <0,0,1,4> + 1209237842U, // : Cost 2 vmrglw LHS, <0,4,1,5> + 2282979505U, // : Cost 3 vmrglw LHS, <0,2,1,6> + 2287625423U, // : Cost 3 vmrglw LHS, <1,6,1,7> + 1209237521U, // : Cost 2 vmrglw LHS, <0,0,1,u> + 1635101613U, // : Cost 2 vsldoi8 <4,0,u,1>, <4,0,u,1> + 2289623050U, // : Cost 3 vmrglw <1,2,u,4>, <0,0,1,1> + 2289625238U, // : Cost 3 vmrglw <1,2,u,4>, <3,0,1,2> + 2640579360U, // : Cost 3 vsldoi4 <3,u,1,4>, <3,u,1,4> + 2622663990U, // : Cost 3 vsldoi4 <0,u,1,4>, RHS + 1616522550U, // : Cost 2 vsldoi8 <0,u,u,1>, RHS + 2664469398U, // : Cost 3 vsldoi4 <7,u,1,4>, <6,7,u,1> + 2664470148U, // : Cost 3 vsldoi4 <7,u,1,4>, <7,u,1,4> + 1616522793U, // : Cost 2 vsldoi8 <0,u,u,1>, RHS + 1548927638U, // : Cost 2 vsldoi4 <0,u,1,5>, <0,u,1,5> + 1192444724U, // : Cost 2 vmrghw RHS, <1,1,1,1> + 1192444822U, // : Cost 2 vmrghw RHS, <1,2,3,0> + 2622670998U, // : Cost 3 vsldoi4 <0,u,1,5>, <3,0,1,2> + 1548930358U, // : Cost 2 vsldoi4 <0,u,1,5>, RHS + 1210728786U, // : Cost 2 vmrglw <0,4,1,5>, <0,4,1,5> + 2714153058U, // : Cost 3 vsldoi8 <4,u,u,1>, <5,6,7,0> + 2670449658U, // : Cost 3 vsldoi4 , <7,0,1,2> + 1548932910U, // : Cost 2 vsldoi4 <0,u,1,5>, LHS + 2622677655U, // : Cost 3 vsldoi4 <0,u,1,6>, <0,u,1,6> + 2756986063U, // : Cost 3 vsldoi12 LHS, <1,6,1,7> + 2302912662U, // : Cost 3 vmrglw <3,4,u,6>, <3,0,1,2> + 3696421014U, // : Cost 4 vsldoi4 <0,u,1,6>, <3,0,1,2> + 2622680374U, // : Cost 3 vsldoi4 <0,u,1,6>, RHS + 2756986099U, // : Cost 3 vsldoi12 LHS, <1,6,5,7> + 2714153784U, // : Cost 3 vsldoi8 <4,u,u,1>, <6,6,6,6> + 1651692438U, // : Cost 2 vsldoi8 <6,7,u,1>, <6,7,u,1> + 1652356071U, // : Cost 2 vsldoi8 <6,u,u,1>, <6,u,u,1> + 2628657254U, // : Cost 3 vsldoi4 <1,u,1,7>, LHS + 1235812362U, // : Cost 2 vmrglw RHS, <0,0,1,1> + 1235814550U, // : Cost 2 vmrglw RHS, <3,0,1,2> + 2309554350U, // : Cost 3 vmrglw RHS, <0,2,1,3> + 2628660534U, // : Cost 3 vsldoi4 <1,u,1,7>, RHS + 1235812690U, // : Cost 2 vmrglw RHS, <0,4,1,5> + 2309554353U, // : Cost 3 vmrglw RHS, <0,2,1,6> + 2309554678U, // : Cost 3 vmrglw RHS, <0,6,1,7> + 1235812369U, // : Cost 2 vmrglw RHS, <0,0,1,u> + 1548952217U, // : Cost 2 vsldoi4 <0,u,1,u>, <0,u,1,u> + 269271142U, // : Cost 1 vspltisw1 LHS + 1209280662U, // : Cost 2 vmrglw LHS, <3,0,1,2> + 835584U, // : Cost 0 copy LHS + 1548954934U, // : Cost 2 vsldoi4 <0,u,1,u>, RHS + 1209278802U, // : Cost 2 vmrglw LHS, <0,4,1,5> + 2283020465U, // : Cost 3 vmrglw LHS, <0,2,1,6> + 1590761096U, // : Cost 2 vsldoi4 <7,u,1,u>, <7,u,1,u> + 835584U, // : Cost 0 copy LHS + 2702876672U, // : Cost 3 vsldoi8 <3,0,u,2>, <0,0,0,0> + 1629134950U, // : Cost 2 vsldoi8 <3,0,u,2>, LHS + 2289591912U, // : Cost 3 vmrglw <1,2,u,0>, <2,2,2,2> + 1215848550U, // : Cost 2 vmrglw <1,2,u,0>, LHS + 2702877010U, // : Cost 3 vsldoi8 <3,0,u,2>, <0,4,1,5> + 2289222708U, // : Cost 3 vmrglw <1,2,3,0>, <1,4,2,5> + 2779178473U, // : Cost 3 vsldoi12 RHS, <2,0,6,1> + 2726249024U, // : Cost 3 vsldoi8 <7,0,1,2>, <0,7,1,0> + 1215848555U, // : Cost 2 vmrglw <1,2,u,0>, LHS + 2690933539U, // : Cost 3 vsldoi8 <1,0,u,2>, <1,0,u,2> + 2628683124U, // : Cost 3 vsldoi4 <1,u,2,1>, <1,u,2,1> + 1189463656U, // : Cost 2 vmrghw LHS, <2,2,2,2> + 1213866086U, // : Cost 2 vmrglw <0,u,u,1>, LHS + 2628685110U, // : Cost 3 vsldoi4 <1,u,2,1>, RHS + 2263205736U, // : Cost 3 vmrghw LHS, <2,5,3,6> + 1189463994U, // : Cost 2 vmrghw LHS, <2,6,3,7> + 2263205866U, // : Cost 3 vmrghw LHS, <2,7,0,1> + 1213866091U, // : Cost 2 vmrglw <0,u,u,1>, LHS + 1556938854U, // : Cost 2 vsldoi4 <2,2,2,2>, LHS + 2697569869U, // : Cost 3 vsldoi8 <2,1,u,2>, <2,1,u,2> + 336380006U, // : Cost 1 vspltisw2 LHS + 1678599794U, // : Cost 2 vsldoi12 LHS, <2,2,3,3> + 1556942134U, // : Cost 2 vsldoi4 <2,2,2,2>, RHS + 2295138061U, // : Cost 3 vmrglw <2,2,2,2>, <2,4,2,5> + 2702878650U, // : Cost 3 vsldoi8 <3,0,u,2>, <2,6,3,7> + 2300229831U, // : Cost 3 vmrglw <3,0,u,2>, + 336380006U, // : Cost 1 vspltisw2 LHS + 475243165U, // : Cost 1 vsldoi4 LHS, LHS + 1548985140U, // : Cost 2 vsldoi4 LHS, <1,1,1,1> + 1209239144U, // : Cost 2 vmrglw LHS, <2,2,2,2> + 135495782U, // : Cost 1 vmrglw LHS, LHS + 475245878U, // : Cost 1 vsldoi4 LHS, RHS + 1596764164U, // : Cost 2 vsldoi4 LHS, <5,5,5,5> + 1596764666U, // : Cost 2 vsldoi4 LHS, <6,2,7,3> + 1596765178U, // : Cost 2 vsldoi4 LHS, <7,0,1,2> + 135495787U, // : Cost 1 vmrglw LHS, LHS + 2708851630U, // : Cost 3 vsldoi8 <4,0,u,2>, <4,0,u,2> + 2217362979U, // : Cost 3 vmrghw <0,4,1,5>, <2,1,3,5> + 2289624680U, // : Cost 3 vmrglw <1,2,u,4>, <2,2,2,2> + 1215881318U, // : Cost 2 vmrglw <1,2,u,4>, LHS + 2726767824U, // : Cost 3 vsldoi8 <7,0,u,2>, <4,4,4,4> + 1629138230U, // : Cost 2 vsldoi8 <3,0,u,2>, RHS + 2779178801U, // : Cost 3 vsldoi12 RHS, <2,4,6,5> + 2726251976U, // : Cost 3 vsldoi8 <7,0,1,2>, <4,7,5,0> + 1215881323U, // : Cost 2 vmrglw <1,2,u,4>, LHS + 2628714598U, // : Cost 3 vsldoi4 <1,u,2,5>, LHS + 2628715896U, // : Cost 3 vsldoi4 <1,u,2,5>, <1,u,2,5> + 1192445544U, // : Cost 2 vmrghw RHS, <2,2,2,2> + 1213898854U, // : Cost 2 vmrglw <0,u,u,5>, LHS + 2628717878U, // : Cost 3 vsldoi4 <1,u,2,5>, RHS + 2726768644U, // : Cost 3 vsldoi8 <7,0,u,2>, <5,5,5,5> + 1192445882U, // : Cost 2 vmrghw RHS, <2,6,3,7> + 2266187754U, // : Cost 3 vmrghw RHS, <2,7,0,1> + 1213898859U, // : Cost 2 vmrglw <0,u,u,5>, LHS + 2634694758U, // : Cost 3 vsldoi4 <2,u,2,6>, LHS + 2721460657U, // : Cost 3 vsldoi8 <6,1,u,2>, <6,1,u,2> + 2296940136U, // : Cost 3 vmrglw <2,4,u,6>, <2,2,2,2> + 1678600122U, // : Cost 2 vsldoi12 LHS, <2,6,3,7> + 2634698038U, // : Cost 3 vsldoi4 <2,u,2,6>, RHS + 3370682125U, // : Cost 4 vmrglw <2,4,u,6>, <2,4,2,5> + 1157056442U, // : Cost 2 vmrghw <2,6,3,7>, <2,6,3,7> + 2725442455U, // : Cost 3 vsldoi8 <6,7,u,2>, <6,7,u,2> + 1678600167U, // : Cost 2 vsldoi12 LHS, <2,6,u,7> + 1653027897U, // : Cost 2 vsldoi8 <7,0,u,2>, <7,0,u,2> + 2309554924U, // : Cost 3 vmrglw RHS, <1,0,2,1> + 1235813992U, // : Cost 2 vmrglw RHS, <2,2,2,2> + 162070630U, // : Cost 1 vmrglw RHS, LHS + 2634706230U, // : Cost 3 vsldoi4 <2,u,2,7>, RHS + 2309555252U, // : Cost 3 vmrglw RHS, <1,4,2,5> + 2309555901U, // : Cost 3 vmrglw RHS, <2,3,2,6> + 2309555416U, // : Cost 3 vmrglw RHS, <1,6,2,7> + 162070635U, // : Cost 1 vmrglw RHS, LHS + 475284130U, // : Cost 1 vsldoi4 LHS, LHS + 1549026100U, // : Cost 2 vsldoi4 LHS, <1,1,1,1> + 336380006U, // : Cost 1 vspltisw2 LHS + 135536742U, // : Cost 1 vmrglw LHS, LHS + 475286838U, // : Cost 1 vsldoi4 LHS, RHS + 1629141146U, // : Cost 2 vsldoi8 <3,0,u,2>, RHS + 1194108858U, // : Cost 2 vmrghw LHS, <2,6,3,7> + 1596806138U, // : Cost 2 vsldoi4 LHS, <7,0,1,2> + 135536747U, // : Cost 1 vmrglw LHS, LHS + 1611890688U, // : Cost 2 vsldoi8 LHS, <0,0,0,0> + 538149020U, // : Cost 1 vsldoi8 LHS, LHS + 2685632685U, // : Cost 3 vsldoi8 LHS, <0,2,1,2> + 2685632764U, // : Cost 3 vsldoi8 LHS, <0,3,1,0> + 1611891026U, // : Cost 2 vsldoi8 LHS, <0,4,1,5> + 2733408722U, // : Cost 3 vsldoi8 LHS, <0,5,6,7> + 2658612153U, // : Cost 3 vsldoi4 <6,u,3,0>, <6,u,3,0> + 2289592250U, // : Cost 3 vmrglw <1,2,u,0>, <2,6,3,7> + 538149533U, // : Cost 1 vsldoi8 LHS, LHS + 1189464214U, // : Cost 2 vmrghw LHS, <3,0,1,2> + 1611891508U, // : Cost 2 vsldoi8 LHS, <1,1,1,1> + 1611891606U, // : Cost 2 vsldoi8 LHS, <1,2,3,0> + 1189464476U, // : Cost 2 vmrghw LHS, <3,3,3,3> + 1189464578U, // : Cost 2 vmrghw LHS, <3,4,5,6> + 2690278511U, // : Cost 3 vsldoi8 LHS, <1,5,0,1> + 2690278607U, // : Cost 3 vsldoi8 LHS, <1,6,1,7> + 2287609786U, // : Cost 3 vmrglw <0,u,u,1>, <2,6,3,7> + 1611892092U, // : Cost 2 vsldoi8 LHS, <1,u,3,0> + 2685634042U, // : Cost 3 vsldoi8 LHS, <2,0,u,0> + 2685634079U, // : Cost 3 vsldoi8 LHS, <2,1,3,1> + 1611892328U, // : Cost 2 vsldoi8 LHS, <2,2,2,2> + 1611892390U, // : Cost 2 vsldoi8 LHS, <2,3,0,1> + 2685634371U, // : Cost 3 vsldoi8 LHS, <2,4,u,5> + 2685634453U, // : Cost 3 vsldoi8 LHS, <2,5,u,6> + 1611892666U, // : Cost 2 vsldoi8 LHS, <2,6,3,7> + 2300225466U, // : Cost 3 vmrglw <3,0,u,2>, <2,6,3,7> + 1611892795U, // : Cost 2 vsldoi8 LHS, <2,u,0,1> + 1209238422U, // : Cost 2 vmrglw LHS, <1,2,3,0> + 2282980247U, // : Cost 3 vmrglw LHS, <1,2,3,1> + 1561004120U, // : Cost 2 vsldoi4 <2,u,3,3>, <2,u,3,3> + 403488870U, // : Cost 1 vspltisw3 LHS + 1209238426U, // : Cost 2 vmrglw LHS, <1,2,3,4> + 2282980899U, // : Cost 3 vmrglw LHS, <2,1,3,5> + 2282985598U, // : Cost 3 vmrglw LHS, + 1209239482U, // : Cost 2 vmrglw LHS, <2,6,3,7> + 403488870U, // : Cost 1 vspltisw3 LHS + 1555038310U, // : Cost 2 vsldoi4 <1,u,3,4>, LHS + 1555039616U, // : Cost 2 vsldoi4 <1,u,3,4>, <1,u,3,4> + 2628781672U, // : Cost 3 vsldoi4 <1,u,3,4>, <2,2,2,2> + 2289624690U, // : Cost 3 vmrglw <1,2,u,4>, <2,2,3,3> + 1555041590U, // : Cost 2 vsldoi4 <1,u,3,4>, RHS + 538152246U, // : Cost 1 vsldoi8 LHS, RHS + 2658644925U, // : Cost 3 vsldoi4 <6,u,3,4>, <6,u,3,4> + 2289625018U, // : Cost 3 vmrglw <1,2,u,4>, <2,6,3,7> + 538152489U, // : Cost 1 vsldoi8 LHS, RHS + 1192446102U, // : Cost 2 vmrghw RHS, <3,0,1,2> + 2733411983U, // : Cost 3 vsldoi8 LHS, <5,1,0,1> + 2634762330U, // : Cost 3 vsldoi4 <2,u,3,5>, <2,u,3,5> + 1192446364U, // : Cost 2 vmrghw RHS, <3,3,3,3> + 1192446466U, // : Cost 2 vmrghw RHS, <3,4,5,6> + 1659670532U, // : Cost 2 vsldoi8 LHS, <5,5,5,5> + 1659670626U, // : Cost 2 vsldoi8 LHS, <5,6,7,0> + 2287642554U, // : Cost 3 vmrglw <0,u,u,5>, <2,6,3,7> + 1659670788U, // : Cost 2 vsldoi8 LHS, <5,u,7,0> + 2634768486U, // : Cost 3 vsldoi4 <2,u,3,6>, LHS + 2733412775U, // : Cost 3 vsldoi8 LHS, <6,1,7,1> + 1648390659U, // : Cost 2 vsldoi8 <6,2,u,3>, <6,2,u,3> + 2634770973U, // : Cost 3 vsldoi4 <2,u,3,6>, <3,4,u,6> + 2634771766U, // : Cost 3 vsldoi4 <2,u,3,6>, RHS + 2733413099U, // : Cost 3 vsldoi8 LHS, <6,5,7,1> + 1659671352U, // : Cost 2 vsldoi8 LHS, <6,6,6,6> + 1659671374U, // : Cost 2 vsldoi8 LHS, <6,7,0,1> + 1652372457U, // : Cost 2 vsldoi8 <6,u,u,3>, <6,u,u,3> + 1561034854U, // : Cost 2 vsldoi4 <2,u,3,7>, LHS + 2634777396U, // : Cost 3 vsldoi4 <2,u,3,7>, <1,1,1,1> + 1561036892U, // : Cost 2 vsldoi4 <2,u,3,7>, <2,u,3,7> + 1235814002U, // : Cost 2 vmrglw RHS, <2,2,3,3> + 1561038134U, // : Cost 2 vsldoi4 <2,u,3,7>, RHS + 2309555747U, // : Cost 3 vmrglw RHS, <2,1,3,5> + 2309556072U, // : Cost 3 vmrglw RHS, <2,5,3,6> + 1235814330U, // : Cost 2 vmrglw RHS, <2,6,3,7> + 1561040686U, // : Cost 2 vsldoi4 <2,u,3,7>, LHS + 1611896531U, // : Cost 2 vsldoi8 LHS, + 538154798U, // : Cost 1 vsldoi8 LHS, LHS + 1611896712U, // : Cost 2 vsldoi8 LHS, + 403488870U, // : Cost 1 vspltisw3 LHS + 1611896895U, // : Cost 2 vsldoi8 LHS, + 538155162U, // : Cost 1 vsldoi8 LHS, RHS + 1611897040U, // : Cost 2 vsldoi8 LHS, + 1209280442U, // : Cost 2 vmrglw LHS, <2,6,3,7> + 538155365U, // : Cost 1 vsldoi8 LHS, LHS + 1165118354U, // : Cost 2 vmrghw <4,0,5,1>, <4,0,5,1> + 1618534502U, // : Cost 2 vsldoi8 <1,2,u,4>, LHS + 2634795102U, // : Cost 3 vsldoi4 <2,u,4,0>, <2,u,4,0> + 2686451968U, // : Cost 3 vsldoi8 <0,3,1,4>, <0,3,1,4> + 2692276562U, // : Cost 3 vsldoi8 <1,2,u,4>, <0,4,1,5> + 1705438098U, // : Cost 2 vsldoi12 RHS, <4,0,5,1> + 2658685890U, // : Cost 3 vsldoi4 <6,u,4,0>, <6,u,4,0> + 2256489928U, // : Cost 3 vmrghw <7,0,1,2>, <4,7,5,0> + 1618535069U, // : Cost 2 vsldoi8 <1,2,u,4>, LHS + 1189464978U, // : Cost 2 vmrghw LHS, <4,0,5,1> + 2692277044U, // : Cost 3 vsldoi8 <1,2,u,4>, <1,1,1,1> + 1618535367U, // : Cost 2 vsldoi8 <1,2,u,4>, <1,2,u,4> + 2640775992U, // : Cost 3 vsldoi4 <3,u,4,1>, <3,u,4,1> + 1189465296U, // : Cost 2 vmrghw LHS, <4,4,4,4> + 115723574U, // : Cost 1 vmrghw LHS, RHS + 2263207289U, // : Cost 3 vmrghw LHS, <4,6,5,2> + 2664666780U, // : Cost 3 vsldoi4 <7,u,4,1>, <7,u,4,1> + 115723817U, // : Cost 1 vmrghw LHS, RHS + 2263919506U, // : Cost 3 vmrghw , <4,0,5,1> + 2222115812U, // : Cost 3 vmrghw <1,2,3,0>, <4,1,5,2> + 2692277864U, // : Cost 3 vsldoi8 <1,2,u,4>, <2,2,2,2> + 2692277926U, // : Cost 3 vsldoi8 <1,2,u,4>, <2,3,0,1> + 2324114640U, // : Cost 3 vmrglw <7,0,u,2>, <4,4,4,4> + 1190178102U, // : Cost 2 vmrghw , RHS + 2692278202U, // : Cost 3 vsldoi8 <1,2,u,4>, <2,6,3,7> + 2701568053U, // : Cost 3 vsldoi8 <2,7,u,4>, <2,7,u,4> + 1190178345U, // : Cost 2 vmrghw , RHS + 2692278422U, // : Cost 3 vsldoi8 <1,2,u,4>, <3,0,1,2> + 2282981552U, // : Cost 3 vmrglw LHS, <3,0,4,1> + 2704222585U, // : Cost 3 vsldoi8 <3,2,u,4>, <3,2,u,4> + 2692278684U, // : Cost 3 vsldoi8 <1,2,u,4>, <3,3,3,3> + 1257016528U, // : Cost 2 vmrglw LHS, <4,4,4,4> + 1209239246U, // : Cost 2 vmrglw LHS, <2,3,4,5> + 2691910300U, // : Cost 3 vsldoi8 <1,2,3,4>, <3,6,4,7> + 2664683166U, // : Cost 3 vsldoi4 <7,u,4,3>, <7,u,4,3> + 1209239249U, // : Cost 2 vmrglw LHS, <2,3,4,u> + 1573027942U, // : Cost 2 vsldoi4 <4,u,4,4>, LHS + 2634826695U, // : Cost 3 vsldoi4 <2,u,4,4>, <1,2,u,4> + 2634827874U, // : Cost 3 vsldoi4 <2,u,4,4>, <2,u,4,4> + 2289629073U, // : Cost 3 vmrglw <1,2,u,4>, + 229035318U, // : Cost 1 vspltisw0 RHS + 1618537782U, // : Cost 2 vsldoi8 <1,2,u,4>, RHS + 2658718662U, // : Cost 3 vsldoi4 <6,u,4,4>, <6,u,4,4> + 2289629401U, // : Cost 3 vmrglw <1,2,u,4>, + 229035318U, // : Cost 1 vspltisw0 RHS + 1561092198U, // : Cost 2 vsldoi4 <2,u,4,5>, LHS + 2628863370U, // : Cost 3 vsldoi4 <1,u,4,5>, <1,u,4,5> + 1561094243U, // : Cost 2 vsldoi4 <2,u,4,5>, <2,u,4,5> + 2634836118U, // : Cost 3 vsldoi4 <2,u,4,5>, <3,0,1,2> + 1561095478U, // : Cost 2 vsldoi4 <2,u,4,5>, RHS + 118705462U, // : Cost 1 vmrghw RHS, RHS + 604859702U, // : Cost 1 vsldoi12 LHS, RHS + 2658726906U, // : Cost 3 vsldoi4 <6,u,4,5>, <7,0,1,2> + 604859720U, // : Cost 1 vsldoi12 LHS, RHS + 2266631058U, // : Cost 3 vmrghw , <4,0,5,1> + 2302692152U, // : Cost 3 vmrglw <3,4,5,6>, <3,u,4,1> + 2718822906U, // : Cost 3 vsldoi8 <5,6,u,4>, <6,2,7,3> + 2722804309U, // : Cost 3 vsldoi8 <6,3,u,4>, <6,3,u,4> + 2723467942U, // : Cost 3 vsldoi8 <6,4,u,4>, <6,4,u,4> + 1192889654U, // : Cost 2 vmrghw , RHS + 2718823224U, // : Cost 3 vsldoi8 <5,6,u,4>, <6,6,6,6> + 2718823246U, // : Cost 3 vsldoi8 <5,6,u,4>, <6,7,0,1> + 1192889897U, // : Cost 2 vmrghw , RHS + 2640822374U, // : Cost 3 vsldoi4 <3,u,4,7>, LHS + 2640823194U, // : Cost 3 vsldoi4 <3,u,4,7>, <1,2,3,4> + 2728113373U, // : Cost 3 vsldoi8 <7,2,u,4>, <7,2,u,4> + 2640825150U, // : Cost 3 vsldoi4 <3,u,4,7>, <3,u,4,7> + 1235815632U, // : Cost 2 vmrglw RHS, <4,4,4,4> + 1235814094U, // : Cost 2 vmrglw RHS, <2,3,4,5> + 2730767905U, // : Cost 3 vsldoi8 <7,6,u,4>, <7,6,u,4> + 2309556892U, // : Cost 3 vmrglw RHS, <3,6,4,7> + 1235814097U, // : Cost 2 vmrglw RHS, <2,3,4,u> + 1561116774U, // : Cost 2 vsldoi4 <2,u,4,u>, LHS + 1618540334U, // : Cost 2 vsldoi8 <1,2,u,4>, LHS + 1561118822U, // : Cost 2 vsldoi4 <2,u,4,u>, <2,u,4,u> + 2692282300U, // : Cost 3 vsldoi8 <1,2,u,4>, + 229035318U, // : Cost 1 vspltisw0 RHS + 120368438U, // : Cost 1 vmrghw LHS, RHS + 604859945U, // : Cost 1 vsldoi12 LHS, RHS + 2309565084U, // : Cost 3 vmrglw RHS, <3,6,4,7> + 604859963U, // : Cost 1 vsldoi12 LHS, RHS + 2690293760U, // : Cost 3 vsldoi8 <0,u,u,5>, <0,0,0,0> + 1616552038U, // : Cost 2 vsldoi8 <0,u,u,5>, LHS + 2640840434U, // : Cost 3 vsldoi4 <3,u,5,0>, <2,3,u,5> + 2640841536U, // : Cost 3 vsldoi4 <3,u,5,0>, <3,u,5,0> + 1613381970U, // : Cost 2 vsldoi8 <0,4,1,5>, <0,4,1,5> + 2316135642U, // : Cost 3 vmrglw <5,6,u,0>, <4,4,5,5> + 2289592834U, // : Cost 3 vmrglw <1,2,u,0>, <3,4,5,6> + 2664732324U, // : Cost 3 vsldoi4 <7,u,5,0>, <7,u,5,0> + 1616552661U, // : Cost 2 vsldoi8 <0,u,u,5>, <0,u,u,5> + 1573077094U, // : Cost 2 vsldoi4 <4,u,5,1>, LHS + 1237536282U, // : Cost 2 vmrglw <4,u,5,1>, <4,u,5,1> + 2690294678U, // : Cost 3 vsldoi8 <0,u,u,5>, <1,2,3,0> + 2646821014U, // : Cost 3 vsldoi4 <4,u,5,1>, <3,0,1,2> + 1573080602U, // : Cost 2 vsldoi4 <4,u,5,1>, <4,u,5,1> + 1189466116U, // : Cost 2 vmrghw LHS, <5,5,5,5> + 1189466210U, // : Cost 2 vmrghw LHS, <5,6,7,0> + 2646823930U, // : Cost 3 vsldoi4 <4,u,5,1>, <7,0,1,2> + 1573082926U, // : Cost 2 vsldoi4 <4,u,5,1>, LHS + 2640855142U, // : Cost 3 vsldoi4 <3,u,5,2>, LHS + 2697594448U, // : Cost 3 vsldoi8 <2,1,u,5>, <2,1,u,5> + 2690295400U, // : Cost 3 vsldoi8 <0,u,u,5>, <2,2,2,2> + 1625179890U, // : Cost 2 vsldoi8 <2,3,u,5>, <2,3,u,5> + 2699585347U, // : Cost 3 vsldoi8 <2,4,u,5>, <2,4,u,5> + 2781171471U, // : Cost 3 vsldoi12 RHS, <5,2,5,3> + 2690295738U, // : Cost 3 vsldoi8 <0,u,u,5>, <2,6,3,7> + 3775318070U, // : Cost 4 vsldoi8 <2,7,u,5>, <2,7,u,5> + 1628498055U, // : Cost 2 vsldoi8 <2,u,u,5>, <2,u,u,5> + 2287627234U, // : Cost 3 vmrglw LHS, <4,1,5,0> + 1257016210U, // : Cost 2 vmrglw LHS, <4,0,5,1> + 2646836942U, // : Cost 3 vsldoi4 <4,u,5,3>, <2,3,4,5> + 2287625131U, // : Cost 3 vmrglw LHS, <1,2,5,3> + 2287627238U, // : Cost 3 vmrglw LHS, <4,1,5,4> + 1257016538U, // : Cost 2 vmrglw LHS, <4,4,5,5> + 1209240066U, // : Cost 2 vmrglw LHS, <3,4,5,6> + 2287625459U, // : Cost 3 vmrglw LHS, <1,6,5,7> + 1209240068U, // : Cost 2 vmrglw LHS, <3,4,5,u> + 2640871526U, // : Cost 3 vsldoi4 <3,u,5,4>, LHS + 2316168082U, // : Cost 3 vmrglw <5,6,u,4>, <4,0,5,1> + 2640873202U, // : Cost 3 vsldoi4 <3,u,5,4>, <2,3,u,5> + 2640874308U, // : Cost 3 vsldoi4 <3,u,5,4>, <3,u,5,4> + 1637788917U, // : Cost 2 vsldoi8 <4,4,u,5>, <4,4,u,5> + 1616555318U, // : Cost 2 vsldoi8 <0,u,u,5>, RHS + 2287638591U, // : Cost 3 vmrglw <0,u,u,4>, + 2664765096U, // : Cost 3 vsldoi4 <7,u,5,4>, <7,u,5,4> + 1616555561U, // : Cost 2 vsldoi8 <0,u,u,5>, RHS + 1573109862U, // : Cost 2 vsldoi4 <4,u,5,5>, LHS + 2646852404U, // : Cost 3 vsldoi4 <4,u,5,5>, <1,1,1,1> + 2646853224U, // : Cost 3 vsldoi4 <4,u,5,5>, <2,2,2,2> + 2287646618U, // : Cost 3 vmrglw <0,u,u,5>, + 1573113374U, // : Cost 2 vsldoi4 <4,u,5,5>, <4,u,5,5> + 296144182U, // : Cost 1 vspltisw1 RHS + 1192448098U, // : Cost 2 vmrghw RHS, <5,6,7,0> + 2287646946U, // : Cost 3 vmrglw <0,u,u,5>, + 296144182U, // : Cost 1 vspltisw1 RHS + 1567146086U, // : Cost 2 vsldoi4 <3,u,5,6>, LHS + 2628945300U, // : Cost 3 vsldoi4 <1,u,5,6>, <1,u,5,6> + 2634917997U, // : Cost 3 vsldoi4 <2,u,5,6>, <2,u,5,6> + 1567148870U, // : Cost 2 vsldoi4 <3,u,5,6>, <3,u,5,6> + 1567149366U, // : Cost 2 vsldoi4 <3,u,5,6>, RHS + 2781171799U, // : Cost 3 vsldoi12 RHS, <5,6,5,7> + 1228950018U, // : Cost 2 vmrglw <3,4,5,6>, <3,4,5,6> + 27705344U, // : Cost 0 copy RHS + 27705344U, // : Cost 0 copy RHS + 2628952166U, // : Cost 3 vsldoi4 <1,u,5,7>, LHS + 1235815314U, // : Cost 2 vmrglw RHS, <4,0,5,1> + 2309556734U, // : Cost 3 vmrglw RHS, <3,4,5,2> + 2309555115U, // : Cost 3 vmrglw RHS, <1,2,5,3> + 2628955446U, // : Cost 3 vsldoi4 <1,u,5,7>, RHS + 1235815642U, // : Cost 2 vmrglw RHS, <4,4,5,5> + 1235814914U, // : Cost 2 vmrglw RHS, <3,4,5,6> + 2309555443U, // : Cost 3 vmrglw RHS, <1,6,5,7> + 1235814916U, // : Cost 2 vmrglw RHS, <3,4,5,u> + 1567162470U, // : Cost 2 vsldoi4 <3,u,5,u>, LHS + 1616557870U, // : Cost 2 vsldoi8 <0,u,u,5>, LHS + 2690299781U, // : Cost 3 vsldoi8 <0,u,u,5>, + 1567165256U, // : Cost 2 vsldoi4 <3,u,5,u>, <3,u,5,u> + 1567165750U, // : Cost 2 vsldoi4 <3,u,5,u>, RHS + 296144182U, // : Cost 1 vspltisw1 RHS + 1209281026U, // : Cost 2 vmrglw LHS, <3,4,5,6> + 27705344U, // : Cost 0 copy RHS + 27705344U, // : Cost 0 copy RHS + 2705563648U, // : Cost 3 vsldoi8 <3,4,u,6>, <0,0,0,0> + 1631821926U, // : Cost 2 vsldoi8 <3,4,u,6>, LHS + 2262462970U, // : Cost 3 vmrghw , <6,2,7,3> + 2646886941U, // : Cost 3 vsldoi4 <4,u,6,0>, <3,4,u,6> + 2705563986U, // : Cost 3 vsldoi8 <3,4,u,6>, <0,4,1,5> + 2316062652U, // : Cost 3 vmrglw <5,6,7,0>, <5,4,6,5> + 2316137272U, // : Cost 3 vmrglw <5,6,u,0>, <6,6,6,6> + 1215851830U, // : Cost 2 vmrglw <1,2,u,0>, RHS + 1215851831U, // : Cost 2 vmrglw <1,2,u,0>, RHS + 2634948710U, // : Cost 3 vsldoi4 <2,u,6,1>, LHS + 2705564468U, // : Cost 3 vsldoi8 <3,4,u,6>, <1,1,1,1> + 1189466618U, // : Cost 2 vmrghw LHS, <6,2,7,3> + 2263208498U, // : Cost 3 vmrghw LHS, <6,3,4,5> + 2693620843U, // : Cost 3 vsldoi8 <1,4,u,6>, <1,4,u,6> + 2652868860U, // : Cost 3 vsldoi4 <5,u,6,1>, <5,u,6,1> + 1189466936U, // : Cost 2 vmrghw LHS, <6,6,6,6> + 1213869366U, // : Cost 2 vmrglw <0,u,u,1>, RHS + 1213869367U, // : Cost 2 vmrglw <0,u,u,1>, RHS + 2658844774U, // : Cost 3 vsldoi4 <6,u,6,2>, LHS + 3771344465U, // : Cost 4 vsldoi8 <2,1,u,6>, <2,1,u,6> + 1178554874U, // : Cost 2 vmrghw <6,2,7,3>, <6,2,7,3> + 2698929907U, // : Cost 3 vsldoi8 <2,3,u,6>, <2,3,u,6> + 2699593540U, // : Cost 3 vsldoi8 <2,4,u,6>, <2,4,u,6> + 2700257173U, // : Cost 3 vsldoi8 <2,5,u,6>, <2,5,u,6> + 2705565626U, // : Cost 3 vsldoi8 <3,4,u,6>, <2,6,3,7> + 1226485046U, // : Cost 2 vmrglw <3,0,u,2>, RHS + 1226485047U, // : Cost 2 vmrglw <3,0,u,2>, RHS + 2705565846U, // : Cost 3 vsldoi8 <3,4,u,6>, <3,0,1,2> + 2330756585U, // : Cost 3 vmrglw LHS, <2,0,6,1> + 2330756829U, // : Cost 3 vmrglw LHS, <2,3,6,2> + 2282981734U, // : Cost 3 vmrglw LHS, <3,2,6,3> + 1631824413U, // : Cost 2 vsldoi8 <3,4,u,6>, <3,4,u,6> + 2652885246U, // : Cost 3 vsldoi4 <5,u,6,3>, <5,u,6,3> + 1257018168U, // : Cost 2 vmrglw LHS, <6,6,6,6> + 135499062U, // : Cost 1 vmrglw LHS, RHS + 135499063U, // : Cost 1 vmrglw LHS, RHS + 2646917222U, // : Cost 3 vsldoi4 <4,u,6,4>, LHS + 2217365931U, // : Cost 3 vmrghw <0,4,1,5>, <6,1,7,5> + 2790167156U, // : Cost 3 vsldoi12 <6,4,2,u>, <6,4,2,u> + 2646919709U, // : Cost 3 vsldoi4 <4,u,6,4>, <3,4,u,6> + 2711538934U, // : Cost 3 vsldoi8 <4,4,u,6>, <4,4,u,6> + 1631825206U, // : Cost 2 vsldoi8 <3,4,u,6>, RHS + 2316170040U, // : Cost 3 vmrglw <5,6,u,4>, <6,6,6,6> + 1215884598U, // : Cost 2 vmrglw <1,2,u,4>, RHS + 1215884599U, // : Cost 2 vmrglw <1,2,u,4>, RHS + 2634981478U, // : Cost 3 vsldoi4 <2,u,6,5>, LHS + 2266190247U, // : Cost 3 vmrghw RHS, <6,1,7,1> + 1192448506U, // : Cost 2 vmrghw RHS, <6,2,7,3> + 2266190386U, // : Cost 3 vmrghw RHS, <6,3,4,5> + 2634984758U, // : Cost 3 vsldoi4 <2,u,6,5>, RHS + 2652901632U, // : Cost 3 vsldoi4 <5,u,6,5>, <5,u,6,5> + 1192448824U, // : Cost 2 vmrghw RHS, <6,6,6,6> + 1213902134U, // : Cost 2 vmrglw <0,u,u,5>, RHS + 1213902135U, // : Cost 2 vmrglw <0,u,u,5>, RHS + 1583808614U, // : Cost 2 vsldoi4 <6,6,6,6>, LHS + 2322010445U, // : Cost 3 vmrglw <6,6,6,6>, <6,0,6,1> + 2718839290U, // : Cost 3 vsldoi8 <5,6,u,6>, <6,2,7,3> + 2670823965U, // : Cost 3 vsldoi4 , <3,4,u,6> + 1583811894U, // : Cost 2 vsldoi4 <6,6,6,6>, RHS + 2724147961U, // : Cost 3 vsldoi8 <6,5,u,6>, <6,5,u,6> + 363253046U, // : Cost 1 vspltisw2 RHS + 1229172022U, // : Cost 2 vmrglw <3,4,u,6>, RHS + 363253046U, // : Cost 1 vspltisw2 RHS + 499458150U, // : Cost 1 vsldoi4 RHS, LHS + 1573200692U, // : Cost 2 vsldoi4 RHS, <1,1,1,1> + 1573201512U, // : Cost 2 vsldoi4 RHS, <2,2,2,2> + 1573202070U, // : Cost 2 vsldoi4 RHS, <3,0,1,2> + 499461673U, // : Cost 1 vsldoi4 RHS, RHS + 1573203972U, // : Cost 2 vsldoi4 RHS, <5,5,5,5> + 1235817272U, // : Cost 2 vmrglw RHS, <6,6,6,6> + 162073910U, // : Cost 1 vmrglw RHS, RHS + 162073911U, // : Cost 1 vmrglw RHS, RHS + 499466342U, // : Cost 1 vsldoi4 RHS, LHS + 1631827758U, // : Cost 2 vsldoi8 <3,4,u,6>, LHS + 1573209704U, // : Cost 2 vsldoi4 RHS, <2,2,2,2> + 1573210262U, // : Cost 2 vsldoi4 RHS, <3,0,1,2> + 499469866U, // : Cost 1 vsldoi4 RHS, RHS + 1631828122U, // : Cost 2 vsldoi8 <3,4,u,6>, RHS + 363253046U, // : Cost 1 vspltisw2 RHS + 135540022U, // : Cost 1 vmrglw LHS, RHS + 135540023U, // : Cost 1 vmrglw LHS, RHS + 1638465536U, // : Cost 2 vsldoi8 RHS, <0,0,0,0> + 564723814U, // : Cost 1 vsldoi8 RHS, LHS + 2712207533U, // : Cost 3 vsldoi8 RHS, <0,2,1,2> + 2712207612U, // : Cost 3 vsldoi8 RHS, <0,3,1,0> + 1638465874U, // : Cost 2 vsldoi8 RHS, <0,4,1,5> + 1579192580U, // : Cost 2 vsldoi4 <5,u,7,0>, <5,u,7,0> + 2712207862U, // : Cost 3 vsldoi8 RHS, <0,6,1,7> + 2316137282U, // : Cost 3 vmrglw <5,6,u,0>, <6,6,7,7> + 564724381U, // : Cost 1 vsldoi8 RHS, LHS + 1189467130U, // : Cost 2 vmrghw LHS, <7,0,1,2> + 1638466356U, // : Cost 2 vsldoi8 RHS, <1,1,1,1> + 1638466454U, // : Cost 2 vsldoi8 RHS, <1,2,3,0> + 2311500282U, // : Cost 3 vmrglw <4,u,u,1>, <6,2,7,3> + 1189467494U, // : Cost 2 vmrghw LHS, <7,4,5,6> + 2712208495U, // : Cost 3 vsldoi8 RHS, <1,5,0,1> + 2694956302U, // : Cost 3 vsldoi8 <1,6,u,7>, <1,6,u,7> + 1189467756U, // : Cost 2 vmrghw LHS, <7,7,7,7> + 1638466940U, // : Cost 2 vsldoi8 RHS, <1,u,3,0> + 2712208829U, // : Cost 3 vsldoi8 RHS, <2,0,1,2> + 2712208927U, // : Cost 3 vsldoi8 RHS, <2,1,3,1> + 1638467176U, // : Cost 2 vsldoi8 RHS, <2,2,2,2> + 1638467238U, // : Cost 2 vsldoi8 RHS, <2,3,0,1> + 2712209165U, // : Cost 3 vsldoi8 RHS, <2,4,2,5> + 2712209256U, // : Cost 3 vsldoi8 RHS, <2,5,3,6> + 1627187175U, // : Cost 2 vsldoi8 <2,6,u,7>, <2,6,u,7> + 2324116290U, // : Cost 3 vmrglw <7,0,u,2>, <6,6,7,7> + 1628514441U, // : Cost 2 vsldoi8 <2,u,u,7>, <2,u,u,7> + 1638467734U, // : Cost 2 vsldoi8 RHS, <3,0,1,2> + 2712209638U, // : Cost 3 vsldoi8 RHS, <3,1,1,1> + 2700929387U, // : Cost 3 vsldoi8 <2,6,u,7>, <3,2,6,u> + 1638467996U, // : Cost 2 vsldoi8 RHS, <3,3,3,3> + 1638468098U, // : Cost 2 vsldoi8 RHS, <3,4,5,6> + 2712210002U, // : Cost 3 vsldoi8 RHS, <3,5,5,5> + 1585189856U, // : Cost 2 vsldoi4 <6,u,7,3>, <6,u,7,3> + 1257018178U, // : Cost 2 vmrglw LHS, <6,6,7,7> + 1638468382U, // : Cost 2 vsldoi8 RHS, <3,u,1,2> + 1638468498U, // : Cost 2 vsldoi8 RHS, <4,0,5,1> + 2712210378U, // : Cost 3 vsldoi8 RHS, <4,1,2,3> + 2712210485U, // : Cost 3 vsldoi8 RHS, <4,2,5,2> + 2712210564U, // : Cost 3 vsldoi8 RHS, <4,3,5,0> + 1638468816U, // : Cost 2 vsldoi8 RHS, <4,4,4,4> + 564727112U, // : Cost 1 vsldoi8 RHS, RHS + 2712210809U, // : Cost 3 vsldoi8 RHS, <4,6,5,2> + 2712210888U, // : Cost 3 vsldoi8 RHS, <4,7,5,0> + 564727337U, // : Cost 1 vsldoi8 RHS, RHS + 1192449018U, // : Cost 2 vmrghw RHS, <7,0,1,2> + 2714201743U, // : Cost 3 vsldoi8 RHS, <5,1,0,1> + 2712211198U, // : Cost 3 vsldoi8 RHS, <5,2,3,4> + 2311533050U, // : Cost 3 vmrglw <4,u,u,5>, <6,2,7,3> + 1192449382U, // : Cost 2 vmrghw RHS, <7,4,5,6> + 1638469636U, // : Cost 2 vsldoi8 RHS, <5,5,5,5> + 1638469730U, // : Cost 2 vsldoi8 RHS, <5,6,7,0> + 1192449644U, // : Cost 2 vmrghw RHS, <7,7,7,7> + 1638469892U, // : Cost 2 vsldoi8 RHS, <5,u,7,0> + 2712211745U, // : Cost 3 vsldoi8 RHS, <6,0,1,2> + 2712211879U, // : Cost 3 vsldoi8 RHS, <6,1,7,1> + 1638470138U, // : Cost 2 vsldoi8 RHS, <6,2,7,3> + 2712212018U, // : Cost 3 vsldoi8 RHS, <6,3,4,5> + 2712212109U, // : Cost 3 vsldoi8 RHS, <6,4,5,6> + 2712212203U, // : Cost 3 vsldoi8 RHS, <6,5,7,1> + 1638470456U, // : Cost 2 vsldoi8 RHS, <6,6,6,6> + 1638470478U, // : Cost 2 vsldoi8 RHS, <6,7,0,1> + 1638470559U, // : Cost 2 vsldoi8 RHS, <6,u,0,1> + 1235816546U, // : Cost 2 vmrglw RHS, <5,6,7,0> + 2309558371U, // : Cost 3 vmrglw RHS, <5,6,7,1> + 2641045434U, // : Cost 3 vsldoi4 <3,u,7,7>, <2,6,3,7> + 1235816954U, // : Cost 2 vmrglw RHS, <6,2,7,3> + 1235816550U, // : Cost 2 vmrglw RHS, <5,6,7,4> + 2309558375U, // : Cost 3 vmrglw RHS, <5,6,7,5> + 1585222628U, // : Cost 2 vsldoi4 <6,u,7,7>, <6,u,7,7> + 430361910U, // : Cost 1 vspltisw3 RHS + 430361910U, // : Cost 1 vspltisw3 RHS + 1638471379U, // : Cost 2 vsldoi8 RHS, + 564729646U, // : Cost 1 vsldoi8 RHS, LHS + 1638471557U, // : Cost 2 vsldoi8 RHS, + 1638471612U, // : Cost 2 vsldoi8 RHS, + 1638471743U, // : Cost 2 vsldoi8 RHS, + 564730010U, // : Cost 1 vsldoi8 RHS, RHS + 1638471888U, // : Cost 2 vsldoi8 RHS, + 430361910U, // : Cost 1 vspltisw3 RHS + 564730213U, // : Cost 1 vsldoi8 RHS, LHS + 202162278U, // : Cost 1 vspltisw0 LHS + 538189985U, // : Cost 1 vsldoi8 LHS, LHS + 2685673645U, // : Cost 3 vsldoi8 LHS, <0,2,1,2> + 1215848604U, // : Cost 2 vmrglw <1,2,u,0>, LHS + 1611931986U, // : Cost 2 vsldoi8 LHS, <0,4,1,5> + 1579266317U, // : Cost 2 vsldoi4 <5,u,u,0>, <5,u,u,0> + 2289592861U, // : Cost 3 vmrglw <1,2,u,0>, <3,4,u,6> + 1215851848U, // : Cost 2 vmrglw <1,2,u,0>, RHS + 538190493U, // : Cost 1 vsldoi8 LHS, LHS + 1549411025U, // : Cost 2 vsldoi4 <0,u,u,1>, <0,u,u,1> + 115726126U, // : Cost 1 vmrghw LHS, LHS + 604862254U, // : Cost 1 vsldoi12 LHS, LHS + 1213866140U, // : Cost 2 vmrglw <0,u,u,1>, LHS + 1549413686U, // : Cost 2 vsldoi4 <0,u,u,1>, RHS + 115726490U, // : Cost 1 vmrghw LHS, RHS + 1585247207U, // : Cost 2 vsldoi4 <6,u,u,1>, <6,u,u,1> + 1213869384U, // : Cost 2 vmrglw <0,u,u,1>, RHS + 604862308U, // : Cost 1 vsldoi12 LHS, LHS + 1567334502U, // : Cost 2 vsldoi4 <3,u,u,2>, LHS + 1190180654U, // : Cost 2 vmrghw , LHS + 336380006U, // : Cost 1 vspltisw2 LHS + 835584U, // : Cost 0 copy LHS + 1567337782U, // : Cost 2 vsldoi4 <3,u,u,2>, RHS + 1190181018U, // : Cost 2 vmrghw , RHS + 1611933626U, // : Cost 2 vsldoi8 LHS, <2,6,3,7> + 1226485064U, // : Cost 2 vmrglw <3,0,u,2>, RHS + 835584U, // : Cost 0 copy LHS + 475685587U, // : Cost 1 vsldoi4 LHS, LHS + 1209239278U, // : Cost 2 vmrglw LHS, <2,3,u,1> + 1209239765U, // : Cost 2 vmrglw LHS, <3,0,u,2> + 135495836U, // : Cost 1 vmrglw LHS, LHS + 475688246U, // : Cost 1 vsldoi4 LHS, RHS + 1209239282U, // : Cost 2 vmrglw LHS, <2,3,u,5> + 1209240093U, // : Cost 2 vmrglw LHS, <3,4,u,6> + 135499080U, // : Cost 1 vmrglw LHS, RHS + 135495841U, // : Cost 1 vmrglw LHS, LHS + 1555406950U, // : Cost 2 vsldoi4 <1,u,u,4>, LHS + 1555408301U, // : Cost 2 vsldoi4 <1,u,u,4>, <1,u,u,4> + 2289625301U, // : Cost 3 vmrglw <1,2,u,4>, <3,0,u,2> + 1215881372U, // : Cost 2 vmrglw <1,2,u,4>, LHS + 229035318U, // : Cost 1 vspltisw0 RHS + 538193206U, // : Cost 1 vsldoi8 LHS, RHS + 2289625629U, // : Cost 3 vmrglw <1,2,u,4>, <3,4,u,6> + 1215884616U, // : Cost 2 vmrglw <1,2,u,4>, RHS + 538193449U, // : Cost 1 vsldoi8 LHS, RHS + 1549443797U, // : Cost 2 vsldoi4 <0,u,u,5>, <0,u,u,5> + 118708014U, // : Cost 1 vmrghw RHS, LHS + 1561389191U, // : Cost 2 vsldoi4 <2,u,u,5>, <2,u,u,5> + 1213898908U, // : Cost 2 vmrglw <0,u,u,5>, LHS + 1549446454U, // : Cost 2 vsldoi4 <0,u,u,5>, RHS + 118708378U, // : Cost 1 vmrghw RHS, RHS + 604862618U, // : Cost 1 vsldoi12 LHS, RHS + 1213902152U, // : Cost 2 vmrglw <0,u,u,5>, RHS + 604862636U, // : Cost 1 vsldoi12 LHS, RHS + 1567367270U, // : Cost 2 vsldoi4 <3,u,u,6>, LHS + 1192892206U, // : Cost 2 vmrghw , LHS + 1638478330U, // : Cost 2 vsldoi8 RHS, <6,2,7,3> + 1679046864U, // : Cost 2 vsldoi12 LHS, + 1567370550U, // : Cost 2 vsldoi4 <3,u,u,6>, RHS + 1192892570U, // : Cost 2 vmrghw , RHS + 363253046U, // : Cost 1 vspltisw2 RHS + 27705344U, // : Cost 0 copy RHS + 27705344U, // : Cost 0 copy RHS + 499605606U, // : Cost 1 vsldoi4 RHS, LHS + 1235812425U, // : Cost 2 vmrglw RHS, <0,0,u,1> + 1561405577U, // : Cost 2 vsldoi4 <2,u,u,7>, <2,u,u,7> + 162070684U, // : Cost 1 vmrglw RHS, LHS + 499609147U, // : Cost 1 vsldoi4 RHS, RHS + 1235812753U, // : Cost 2 vmrglw RHS, <0,4,u,5> + 1235814941U, // : Cost 2 vmrglw RHS, <3,4,u,6> + 162073928U, // : Cost 1 vmrglw RHS, RHS + 162070689U, // : Cost 1 vmrglw RHS, LHS + 475726552U, // : Cost 1 vsldoi4 LHS, LHS + 538195758U, // : Cost 1 vsldoi8 LHS, LHS + 604862821U, // : Cost 1 vsldoi12 LHS, LHS + 835584U, // : Cost 0 copy LHS + 475729206U, // : Cost 1 vsldoi4 LHS, RHS + 538196122U, // : Cost 1 vsldoi8 LHS, RHS + 604862861U, // : Cost 1 vsldoi12 LHS, RHS + 27705344U, // : Cost 0 copy RHS + 835584U, // : Cost 0 copy LHS + 0 +}; diff --git a/libclamav/c++/llvm/lib/Target/PowerPC/PPCPredicates.cpp b/libclamav/c++/llvm/lib/Target/PowerPC/PPCPredicates.cpp new file mode 100644 index 000000000..12bb0a143 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/PowerPC/PPCPredicates.cpp @@ -0,0 +1,31 @@ +//===-- PPCPredicates.cpp - PPC Branch Predicate Information --------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the PowerPC branch predicates. +// +//===----------------------------------------------------------------------===// + +#include "PPCPredicates.h" +#include "llvm/Support/ErrorHandling.h" +#include +using namespace llvm; + +PPC::Predicate PPC::InvertPredicate(PPC::Predicate Opcode) { + switch (Opcode) { + default: llvm_unreachable("Unknown PPC branch opcode!"); + case PPC::PRED_EQ: return PPC::PRED_NE; + case PPC::PRED_NE: return PPC::PRED_EQ; + case PPC::PRED_LT: return PPC::PRED_GE; + case PPC::PRED_GE: return PPC::PRED_LT; + case PPC::PRED_GT: return PPC::PRED_LE; + case PPC::PRED_LE: return PPC::PRED_GT; + case PPC::PRED_NU: return PPC::PRED_UN; + case PPC::PRED_UN: return PPC::PRED_NU; + } +} diff --git a/libclamav/c++/llvm/lib/Target/PowerPC/PPCPredicates.h b/libclamav/c++/llvm/lib/Target/PowerPC/PPCPredicates.h new file mode 100644 index 000000000..b2c831579 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/PowerPC/PPCPredicates.h @@ -0,0 +1,39 @@ +//===-- PPCPredicates.h - PPC Branch Predicate Information ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file describes the PowerPC branch predicates. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TARGET_POWERPC_PPCPREDICATES_H +#define LLVM_TARGET_POWERPC_PPCPREDICATES_H + +#include "PPC.h" + +namespace llvm { +namespace PPC { + /// Predicate - These are "(BI << 5) | BO" for various predicates. + enum Predicate { + PRED_ALWAYS = (0 << 5) | 20, + PRED_LT = (0 << 5) | 12, + PRED_LE = (1 << 5) | 4, + PRED_EQ = (2 << 5) | 12, + PRED_GE = (0 << 5) | 4, + PRED_GT = (1 << 5) | 12, + PRED_NE = (2 << 5) | 4, + PRED_UN = (3 << 5) | 12, + PRED_NU = (3 << 5) | 4 + }; + + /// Invert the specified predicate. != -> ==, < -> >=. + Predicate InvertPredicate(Predicate Opcode); +} +} + +#endif diff --git a/libclamav/c++/llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp b/libclamav/c++/llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp new file mode 100644 index 000000000..0c3c8eb64 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp @@ -0,0 +1,1745 @@ +//===- PPCRegisterInfo.cpp - PowerPC Register Information -------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the PowerPC implementation of the TargetRegisterInfo +// class. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "reginfo" +#include "PPC.h" +#include "PPCInstrBuilder.h" +#include "PPCMachineFunctionInfo.h" +#include "PPCRegisterInfo.h" +#include "PPCFrameInfo.h" +#include "PPCSubtarget.h" +#include "llvm/CallingConv.h" +#include "llvm/Constants.h" +#include "llvm/Function.h" +#include "llvm/Type.h" +#include "llvm/CodeGen/ValueTypes.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineLocation.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/RegisterScavenging.h" +#include "llvm/Target/TargetFrameInfo.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetOptions.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/ADT/BitVector.h" +#include "llvm/ADT/STLExtras.h" +#include +using namespace llvm; + +// FIXME This disables some code that aligns the stack to a boundary +// bigger than the default (16 bytes on Darwin) when there is a stack local +// of greater alignment. This does not currently work, because the delta +// between old and new stack pointers is added to offsets that reference +// incoming parameters after the prolog is generated, and the code that +// does that doesn't handle a variable delta. You don't want to do that +// anyway; a better approach is to reserve another register that retains +// to the incoming stack pointer, and reference parameters relative to that. +#define ALIGN_STACK 0 + +// FIXME (64-bit): Eventually enable by default. +cl::opt EnablePPC32RS("enable-ppc32-regscavenger", + cl::init(false), + cl::desc("Enable PPC32 register scavenger"), + cl::Hidden); +cl::opt EnablePPC64RS("enable-ppc64-regscavenger", + cl::init(false), + cl::desc("Enable PPC64 register scavenger"), + cl::Hidden); +#define EnableRegisterScavenging \ + ((EnablePPC32RS && !Subtarget.isPPC64()) || \ + (EnablePPC64RS && Subtarget.isPPC64())) + +// FIXME (64-bit): Should be inlined. +bool +PPCRegisterInfo::requiresRegisterScavenging(const MachineFunction &) const { + return EnableRegisterScavenging; +} + +/// getRegisterNumbering - Given the enum value for some register, e.g. +/// PPC::F14, return the number that it corresponds to (e.g. 14). +unsigned PPCRegisterInfo::getRegisterNumbering(unsigned RegEnum) { + using namespace PPC; + switch (RegEnum) { + case 0: return 0; + case R0 : case X0 : case F0 : case V0 : case CR0: case CR0LT: return 0; + case R1 : case X1 : case F1 : case V1 : case CR1: case CR0GT: return 1; + case R2 : case X2 : case F2 : case V2 : case CR2: case CR0EQ: return 2; + case R3 : case X3 : case F3 : case V3 : case CR3: case CR0UN: return 3; + case R4 : case X4 : case F4 : case V4 : case CR4: case CR1LT: return 4; + case R5 : case X5 : case F5 : case V5 : case CR5: case CR1GT: return 5; + case R6 : case X6 : case F6 : case V6 : case CR6: case CR1EQ: return 6; + case R7 : case X7 : case F7 : case V7 : case CR7: case CR1UN: return 7; + case R8 : case X8 : case F8 : case V8 : case CR2LT: return 8; + case R9 : case X9 : case F9 : case V9 : case CR2GT: return 9; + case R10: case X10: case F10: case V10: case CR2EQ: return 10; + case R11: case X11: case F11: case V11: case CR2UN: return 11; + case R12: case X12: case F12: case V12: case CR3LT: return 12; + case R13: case X13: case F13: case V13: case CR3GT: return 13; + case R14: case X14: case F14: case V14: case CR3EQ: return 14; + case R15: case X15: case F15: case V15: case CR3UN: return 15; + case R16: case X16: case F16: case V16: case CR4LT: return 16; + case R17: case X17: case F17: case V17: case CR4GT: return 17; + case R18: case X18: case F18: case V18: case CR4EQ: return 18; + case R19: case X19: case F19: case V19: case CR4UN: return 19; + case R20: case X20: case F20: case V20: case CR5LT: return 20; + case R21: case X21: case F21: case V21: case CR5GT: return 21; + case R22: case X22: case F22: case V22: case CR5EQ: return 22; + case R23: case X23: case F23: case V23: case CR5UN: return 23; + case R24: case X24: case F24: case V24: case CR6LT: return 24; + case R25: case X25: case F25: case V25: case CR6GT: return 25; + case R26: case X26: case F26: case V26: case CR6EQ: return 26; + case R27: case X27: case F27: case V27: case CR6UN: return 27; + case R28: case X28: case F28: case V28: case CR7LT: return 28; + case R29: case X29: case F29: case V29: case CR7GT: return 29; + case R30: case X30: case F30: case V30: case CR7EQ: return 30; + case R31: case X31: case F31: case V31: case CR7UN: return 31; + default: + llvm_unreachable("Unhandled reg in PPCRegisterInfo::getRegisterNumbering!"); + } +} + +PPCRegisterInfo::PPCRegisterInfo(const PPCSubtarget &ST, + const TargetInstrInfo &tii) + : PPCGenRegisterInfo(PPC::ADJCALLSTACKDOWN, PPC::ADJCALLSTACKUP), + Subtarget(ST), TII(tii) { + ImmToIdxMap[PPC::LD] = PPC::LDX; ImmToIdxMap[PPC::STD] = PPC::STDX; + ImmToIdxMap[PPC::LBZ] = PPC::LBZX; ImmToIdxMap[PPC::STB] = PPC::STBX; + ImmToIdxMap[PPC::LHZ] = PPC::LHZX; ImmToIdxMap[PPC::LHA] = PPC::LHAX; + ImmToIdxMap[PPC::LWZ] = PPC::LWZX; ImmToIdxMap[PPC::LWA] = PPC::LWAX; + ImmToIdxMap[PPC::LFS] = PPC::LFSX; ImmToIdxMap[PPC::LFD] = PPC::LFDX; + ImmToIdxMap[PPC::STH] = PPC::STHX; ImmToIdxMap[PPC::STW] = PPC::STWX; + ImmToIdxMap[PPC::STFS] = PPC::STFSX; ImmToIdxMap[PPC::STFD] = PPC::STFDX; + ImmToIdxMap[PPC::ADDI] = PPC::ADD4; + + // 64-bit + ImmToIdxMap[PPC::LHA8] = PPC::LHAX8; ImmToIdxMap[PPC::LBZ8] = PPC::LBZX8; + ImmToIdxMap[PPC::LHZ8] = PPC::LHZX8; ImmToIdxMap[PPC::LWZ8] = PPC::LWZX8; + ImmToIdxMap[PPC::STB8] = PPC::STBX8; ImmToIdxMap[PPC::STH8] = PPC::STHX8; + ImmToIdxMap[PPC::STW8] = PPC::STWX8; ImmToIdxMap[PPC::STDU] = PPC::STDUX; + ImmToIdxMap[PPC::ADDI8] = PPC::ADD8; ImmToIdxMap[PPC::STD_32] = PPC::STDX_32; +} + +/// getPointerRegClass - Return the register class to use to hold pointers. +/// This is used for addressing modes. +const TargetRegisterClass * +PPCRegisterInfo::getPointerRegClass(unsigned Kind) const { + if (Subtarget.isPPC64()) + return &PPC::G8RCRegClass; + return &PPC::GPRCRegClass; +} + +const unsigned* +PPCRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const { + // 32-bit Darwin calling convention. + static const unsigned Darwin32_CalleeSavedRegs[] = { + PPC::R13, PPC::R14, PPC::R15, + PPC::R16, PPC::R17, PPC::R18, PPC::R19, + PPC::R20, PPC::R21, PPC::R22, PPC::R23, + PPC::R24, PPC::R25, PPC::R26, PPC::R27, + PPC::R28, PPC::R29, PPC::R30, PPC::R31, + + PPC::F14, PPC::F15, PPC::F16, PPC::F17, + PPC::F18, PPC::F19, PPC::F20, PPC::F21, + PPC::F22, PPC::F23, PPC::F24, PPC::F25, + PPC::F26, PPC::F27, PPC::F28, PPC::F29, + PPC::F30, PPC::F31, + + PPC::CR2, PPC::CR3, PPC::CR4, + PPC::V20, PPC::V21, PPC::V22, PPC::V23, + PPC::V24, PPC::V25, PPC::V26, PPC::V27, + PPC::V28, PPC::V29, PPC::V30, PPC::V31, + + PPC::CR2LT, PPC::CR2GT, PPC::CR2EQ, PPC::CR2UN, + PPC::CR3LT, PPC::CR3GT, PPC::CR3EQ, PPC::CR3UN, + PPC::CR4LT, PPC::CR4GT, PPC::CR4EQ, PPC::CR4UN, + + PPC::LR, 0 + }; + + // 32-bit SVR4 calling convention. + static const unsigned SVR4_CalleeSavedRegs[] = { + PPC::R14, PPC::R15, + PPC::R16, PPC::R17, PPC::R18, PPC::R19, + PPC::R20, PPC::R21, PPC::R22, PPC::R23, + PPC::R24, PPC::R25, PPC::R26, PPC::R27, + PPC::R28, PPC::R29, PPC::R30, PPC::R31, + + PPC::F14, PPC::F15, PPC::F16, PPC::F17, + PPC::F18, PPC::F19, PPC::F20, PPC::F21, + PPC::F22, PPC::F23, PPC::F24, PPC::F25, + PPC::F26, PPC::F27, PPC::F28, PPC::F29, + PPC::F30, PPC::F31, + + PPC::CR2, PPC::CR3, PPC::CR4, + + PPC::VRSAVE, + + PPC::V20, PPC::V21, PPC::V22, PPC::V23, + PPC::V24, PPC::V25, PPC::V26, PPC::V27, + PPC::V28, PPC::V29, PPC::V30, PPC::V31, + + PPC::CR2LT, PPC::CR2GT, PPC::CR2EQ, PPC::CR2UN, + PPC::CR3LT, PPC::CR3GT, PPC::CR3EQ, PPC::CR3UN, + PPC::CR4LT, PPC::CR4GT, PPC::CR4EQ, PPC::CR4UN, + + 0 + }; + // 64-bit Darwin calling convention. + static const unsigned Darwin64_CalleeSavedRegs[] = { + PPC::X14, PPC::X15, + PPC::X16, PPC::X17, PPC::X18, PPC::X19, + PPC::X20, PPC::X21, PPC::X22, PPC::X23, + PPC::X24, PPC::X25, PPC::X26, PPC::X27, + PPC::X28, PPC::X29, PPC::X30, PPC::X31, + + PPC::F14, PPC::F15, PPC::F16, PPC::F17, + PPC::F18, PPC::F19, PPC::F20, PPC::F21, + PPC::F22, PPC::F23, PPC::F24, PPC::F25, + PPC::F26, PPC::F27, PPC::F28, PPC::F29, + PPC::F30, PPC::F31, + + PPC::CR2, PPC::CR3, PPC::CR4, + PPC::V20, PPC::V21, PPC::V22, PPC::V23, + PPC::V24, PPC::V25, PPC::V26, PPC::V27, + PPC::V28, PPC::V29, PPC::V30, PPC::V31, + + PPC::CR2LT, PPC::CR2GT, PPC::CR2EQ, PPC::CR2UN, + PPC::CR3LT, PPC::CR3GT, PPC::CR3EQ, PPC::CR3UN, + PPC::CR4LT, PPC::CR4GT, PPC::CR4EQ, PPC::CR4UN, + + PPC::LR8, 0 + }; + + // 64-bit SVR4 calling convention. + static const unsigned SVR4_64_CalleeSavedRegs[] = { + PPC::X14, PPC::X15, + PPC::X16, PPC::X17, PPC::X18, PPC::X19, + PPC::X20, PPC::X21, PPC::X22, PPC::X23, + PPC::X24, PPC::X25, PPC::X26, PPC::X27, + PPC::X28, PPC::X29, PPC::X30, PPC::X31, + + PPC::F14, PPC::F15, PPC::F16, PPC::F17, + PPC::F18, PPC::F19, PPC::F20, PPC::F21, + PPC::F22, PPC::F23, PPC::F24, PPC::F25, + PPC::F26, PPC::F27, PPC::F28, PPC::F29, + PPC::F30, PPC::F31, + + PPC::CR2, PPC::CR3, PPC::CR4, + + PPC::VRSAVE, + + PPC::V20, PPC::V21, PPC::V22, PPC::V23, + PPC::V24, PPC::V25, PPC::V26, PPC::V27, + PPC::V28, PPC::V29, PPC::V30, PPC::V31, + + PPC::CR2LT, PPC::CR2GT, PPC::CR2EQ, PPC::CR2UN, + PPC::CR3LT, PPC::CR3GT, PPC::CR3EQ, PPC::CR3UN, + PPC::CR4LT, PPC::CR4GT, PPC::CR4EQ, PPC::CR4UN, + + 0 + }; + + if (Subtarget.isDarwinABI()) + return Subtarget.isPPC64() ? Darwin64_CalleeSavedRegs : + Darwin32_CalleeSavedRegs; + + return Subtarget.isPPC64() ? SVR4_64_CalleeSavedRegs : SVR4_CalleeSavedRegs; +} + +const TargetRegisterClass* const* +PPCRegisterInfo::getCalleeSavedRegClasses(const MachineFunction *MF) const { + // 32-bit Darwin calling convention. + static const TargetRegisterClass * const Darwin32_CalleeSavedRegClasses[] = { + &PPC::GPRCRegClass,&PPC::GPRCRegClass,&PPC::GPRCRegClass, + &PPC::GPRCRegClass,&PPC::GPRCRegClass,&PPC::GPRCRegClass,&PPC::GPRCRegClass, + &PPC::GPRCRegClass,&PPC::GPRCRegClass,&PPC::GPRCRegClass,&PPC::GPRCRegClass, + &PPC::GPRCRegClass,&PPC::GPRCRegClass,&PPC::GPRCRegClass,&PPC::GPRCRegClass, + &PPC::GPRCRegClass,&PPC::GPRCRegClass,&PPC::GPRCRegClass,&PPC::GPRCRegClass, + + &PPC::F8RCRegClass,&PPC::F8RCRegClass,&PPC::F8RCRegClass,&PPC::F8RCRegClass, + &PPC::F8RCRegClass,&PPC::F8RCRegClass,&PPC::F8RCRegClass,&PPC::F8RCRegClass, + &PPC::F8RCRegClass,&PPC::F8RCRegClass,&PPC::F8RCRegClass,&PPC::F8RCRegClass, + &PPC::F8RCRegClass,&PPC::F8RCRegClass,&PPC::F8RCRegClass,&PPC::F8RCRegClass, + &PPC::F8RCRegClass,&PPC::F8RCRegClass, + + &PPC::CRRCRegClass,&PPC::CRRCRegClass,&PPC::CRRCRegClass, + + &PPC::VRRCRegClass,&PPC::VRRCRegClass,&PPC::VRRCRegClass,&PPC::VRRCRegClass, + &PPC::VRRCRegClass,&PPC::VRRCRegClass,&PPC::VRRCRegClass,&PPC::VRRCRegClass, + &PPC::VRRCRegClass,&PPC::VRRCRegClass,&PPC::VRRCRegClass,&PPC::VRRCRegClass, + + &PPC::CRBITRCRegClass,&PPC::CRBITRCRegClass,&PPC::CRBITRCRegClass, + &PPC::CRBITRCRegClass, + &PPC::CRBITRCRegClass,&PPC::CRBITRCRegClass,&PPC::CRBITRCRegClass, + &PPC::CRBITRCRegClass, + &PPC::CRBITRCRegClass,&PPC::CRBITRCRegClass,&PPC::CRBITRCRegClass, + &PPC::CRBITRCRegClass, + + &PPC::GPRCRegClass, 0 + }; + + // 32-bit SVR4 calling convention. + static const TargetRegisterClass * const SVR4_CalleeSavedRegClasses[] = { + &PPC::GPRCRegClass,&PPC::GPRCRegClass, + &PPC::GPRCRegClass,&PPC::GPRCRegClass,&PPC::GPRCRegClass,&PPC::GPRCRegClass, + &PPC::GPRCRegClass,&PPC::GPRCRegClass,&PPC::GPRCRegClass,&PPC::GPRCRegClass, + &PPC::GPRCRegClass,&PPC::GPRCRegClass,&PPC::GPRCRegClass,&PPC::GPRCRegClass, + &PPC::GPRCRegClass,&PPC::GPRCRegClass,&PPC::GPRCRegClass,&PPC::GPRCRegClass, + + &PPC::F8RCRegClass,&PPC::F8RCRegClass,&PPC::F8RCRegClass,&PPC::F8RCRegClass, + &PPC::F8RCRegClass,&PPC::F8RCRegClass,&PPC::F8RCRegClass,&PPC::F8RCRegClass, + &PPC::F8RCRegClass,&PPC::F8RCRegClass,&PPC::F8RCRegClass,&PPC::F8RCRegClass, + &PPC::F8RCRegClass,&PPC::F8RCRegClass,&PPC::F8RCRegClass,&PPC::F8RCRegClass, + &PPC::F8RCRegClass,&PPC::F8RCRegClass, + + &PPC::CRRCRegClass,&PPC::CRRCRegClass,&PPC::CRRCRegClass, + + &PPC::VRSAVERCRegClass, + + &PPC::VRRCRegClass,&PPC::VRRCRegClass,&PPC::VRRCRegClass,&PPC::VRRCRegClass, + &PPC::VRRCRegClass,&PPC::VRRCRegClass,&PPC::VRRCRegClass,&PPC::VRRCRegClass, + &PPC::VRRCRegClass,&PPC::VRRCRegClass,&PPC::VRRCRegClass,&PPC::VRRCRegClass, + + &PPC::CRBITRCRegClass,&PPC::CRBITRCRegClass,&PPC::CRBITRCRegClass, + &PPC::CRBITRCRegClass, + &PPC::CRBITRCRegClass,&PPC::CRBITRCRegClass,&PPC::CRBITRCRegClass, + &PPC::CRBITRCRegClass, + &PPC::CRBITRCRegClass,&PPC::CRBITRCRegClass,&PPC::CRBITRCRegClass, + &PPC::CRBITRCRegClass, + + 0 + }; + + // 64-bit Darwin calling convention. + static const TargetRegisterClass * const Darwin64_CalleeSavedRegClasses[] = { + &PPC::G8RCRegClass,&PPC::G8RCRegClass, + &PPC::G8RCRegClass,&PPC::G8RCRegClass,&PPC::G8RCRegClass,&PPC::G8RCRegClass, + &PPC::G8RCRegClass,&PPC::G8RCRegClass,&PPC::G8RCRegClass,&PPC::G8RCRegClass, + &PPC::G8RCRegClass,&PPC::G8RCRegClass,&PPC::G8RCRegClass,&PPC::G8RCRegClass, + &PPC::G8RCRegClass,&PPC::G8RCRegClass,&PPC::G8RCRegClass,&PPC::G8RCRegClass, + + &PPC::F8RCRegClass,&PPC::F8RCRegClass,&PPC::F8RCRegClass,&PPC::F8RCRegClass, + &PPC::F8RCRegClass,&PPC::F8RCRegClass,&PPC::F8RCRegClass,&PPC::F8RCRegClass, + &PPC::F8RCRegClass,&PPC::F8RCRegClass,&PPC::F8RCRegClass,&PPC::F8RCRegClass, + &PPC::F8RCRegClass,&PPC::F8RCRegClass,&PPC::F8RCRegClass,&PPC::F8RCRegClass, + &PPC::F8RCRegClass,&PPC::F8RCRegClass, + + &PPC::CRRCRegClass,&PPC::CRRCRegClass,&PPC::CRRCRegClass, + + &PPC::VRRCRegClass,&PPC::VRRCRegClass,&PPC::VRRCRegClass,&PPC::VRRCRegClass, + &PPC::VRRCRegClass,&PPC::VRRCRegClass,&PPC::VRRCRegClass,&PPC::VRRCRegClass, + &PPC::VRRCRegClass,&PPC::VRRCRegClass,&PPC::VRRCRegClass,&PPC::VRRCRegClass, + + &PPC::CRBITRCRegClass,&PPC::CRBITRCRegClass,&PPC::CRBITRCRegClass, + &PPC::CRBITRCRegClass, + &PPC::CRBITRCRegClass,&PPC::CRBITRCRegClass,&PPC::CRBITRCRegClass, + &PPC::CRBITRCRegClass, + &PPC::CRBITRCRegClass,&PPC::CRBITRCRegClass,&PPC::CRBITRCRegClass, + &PPC::CRBITRCRegClass, + + &PPC::G8RCRegClass, 0 + }; + + // 64-bit SVR4 calling convention. + static const TargetRegisterClass * const SVR4_64_CalleeSavedRegClasses[] = { + &PPC::G8RCRegClass,&PPC::G8RCRegClass, + &PPC::G8RCRegClass,&PPC::G8RCRegClass,&PPC::G8RCRegClass,&PPC::G8RCRegClass, + &PPC::G8RCRegClass,&PPC::G8RCRegClass,&PPC::G8RCRegClass,&PPC::G8RCRegClass, + &PPC::G8RCRegClass,&PPC::G8RCRegClass,&PPC::G8RCRegClass,&PPC::G8RCRegClass, + &PPC::G8RCRegClass,&PPC::G8RCRegClass,&PPC::G8RCRegClass,&PPC::G8RCRegClass, + + &PPC::F8RCRegClass,&PPC::F8RCRegClass,&PPC::F8RCRegClass,&PPC::F8RCRegClass, + &PPC::F8RCRegClass,&PPC::F8RCRegClass,&PPC::F8RCRegClass,&PPC::F8RCRegClass, + &PPC::F8RCRegClass,&PPC::F8RCRegClass,&PPC::F8RCRegClass,&PPC::F8RCRegClass, + &PPC::F8RCRegClass,&PPC::F8RCRegClass,&PPC::F8RCRegClass,&PPC::F8RCRegClass, + &PPC::F8RCRegClass,&PPC::F8RCRegClass, + + &PPC::CRRCRegClass,&PPC::CRRCRegClass,&PPC::CRRCRegClass, + + &PPC::VRSAVERCRegClass, + + &PPC::VRRCRegClass,&PPC::VRRCRegClass,&PPC::VRRCRegClass,&PPC::VRRCRegClass, + &PPC::VRRCRegClass,&PPC::VRRCRegClass,&PPC::VRRCRegClass,&PPC::VRRCRegClass, + &PPC::VRRCRegClass,&PPC::VRRCRegClass,&PPC::VRRCRegClass,&PPC::VRRCRegClass, + + &PPC::CRBITRCRegClass,&PPC::CRBITRCRegClass,&PPC::CRBITRCRegClass, + &PPC::CRBITRCRegClass, + &PPC::CRBITRCRegClass,&PPC::CRBITRCRegClass,&PPC::CRBITRCRegClass, + &PPC::CRBITRCRegClass, + &PPC::CRBITRCRegClass,&PPC::CRBITRCRegClass,&PPC::CRBITRCRegClass, + &PPC::CRBITRCRegClass, + + 0 + }; + + if (Subtarget.isDarwinABI()) + return Subtarget.isPPC64() ? Darwin64_CalleeSavedRegClasses : + Darwin32_CalleeSavedRegClasses; + + return Subtarget.isPPC64() ? SVR4_64_CalleeSavedRegClasses + : SVR4_CalleeSavedRegClasses; +} + +// needsFP - Return true if the specified function should have a dedicated frame +// pointer register. This is true if the function has variable sized allocas or +// if frame pointer elimination is disabled. +// +static bool needsFP(const MachineFunction &MF) { + const MachineFrameInfo *MFI = MF.getFrameInfo(); + return NoFramePointerElim || MFI->hasVarSizedObjects() || + (PerformTailCallOpt && MF.getInfo()->hasFastCall()); +} + +static bool spillsCR(const MachineFunction &MF) { + const PPCFunctionInfo *FuncInfo = MF.getInfo(); + return FuncInfo->isCRSpilled(); +} + +BitVector PPCRegisterInfo::getReservedRegs(const MachineFunction &MF) const { + BitVector Reserved(getNumRegs()); + Reserved.set(PPC::R0); + Reserved.set(PPC::R1); + Reserved.set(PPC::LR); + Reserved.set(PPC::LR8); + Reserved.set(PPC::RM); + + // The SVR4 ABI reserves r2 and r13 + if (Subtarget.isSVR4ABI()) { + Reserved.set(PPC::R2); // System-reserved register + Reserved.set(PPC::R13); // Small Data Area pointer register + } + + // On PPC64, r13 is the thread pointer. Never allocate this register. + // Note that this is over conservative, as it also prevents allocation of R31 + // when the FP is not needed. + if (Subtarget.isPPC64()) { + Reserved.set(PPC::R13); + Reserved.set(PPC::R31); + + if (!EnableRegisterScavenging) + Reserved.set(PPC::R0); // FIXME (64-bit): Remove + + Reserved.set(PPC::X0); + Reserved.set(PPC::X1); + Reserved.set(PPC::X13); + Reserved.set(PPC::X31); + + // The 64-bit SVR4 ABI reserves r2 for the TOC pointer. + if (Subtarget.isSVR4ABI()) { + Reserved.set(PPC::X2); + } + } + + if (needsFP(MF)) + Reserved.set(PPC::R31); + + return Reserved; +} + +//===----------------------------------------------------------------------===// +// Stack Frame Processing methods +//===----------------------------------------------------------------------===// + +// hasFP - Return true if the specified function actually has a dedicated frame +// pointer register. This is true if the function needs a frame pointer and has +// a non-zero stack size. +bool PPCRegisterInfo::hasFP(const MachineFunction &MF) const { + const MachineFrameInfo *MFI = MF.getFrameInfo(); + return MFI->getStackSize() && needsFP(MF); +} + +/// MustSaveLR - Return true if this function requires that we save the LR +/// register onto the stack in the prolog and restore it in the epilog of the +/// function. +static bool MustSaveLR(const MachineFunction &MF, unsigned LR) { + const PPCFunctionInfo *MFI = MF.getInfo(); + + // We need a save/restore of LR if there is any def of LR (which is + // defined by calls, including the PIC setup sequence), or if there is + // some use of the LR stack slot (e.g. for builtin_return_address). + // (LR comes in 32 and 64 bit versions.) + MachineRegisterInfo::def_iterator RI = MF.getRegInfo().def_begin(LR); + return RI !=MF.getRegInfo().def_end() || MFI->isLRStoreRequired(); +} + + + +void PPCRegisterInfo:: +eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, + MachineBasicBlock::iterator I) const { + if (PerformTailCallOpt && I->getOpcode() == PPC::ADJCALLSTACKUP) { + // Add (actually subtract) back the amount the callee popped on return. + if (int CalleeAmt = I->getOperand(1).getImm()) { + bool is64Bit = Subtarget.isPPC64(); + CalleeAmt *= -1; + unsigned StackReg = is64Bit ? PPC::X1 : PPC::R1; + unsigned TmpReg = is64Bit ? PPC::X0 : PPC::R0; + unsigned ADDIInstr = is64Bit ? PPC::ADDI8 : PPC::ADDI; + unsigned ADDInstr = is64Bit ? PPC::ADD8 : PPC::ADD4; + unsigned LISInstr = is64Bit ? PPC::LIS8 : PPC::LIS; + unsigned ORIInstr = is64Bit ? PPC::ORI8 : PPC::ORI; + MachineInstr *MI = I; + DebugLoc dl = MI->getDebugLoc(); + + if (isInt16(CalleeAmt)) { + BuildMI(MBB, I, dl, TII.get(ADDIInstr), StackReg).addReg(StackReg). + addImm(CalleeAmt); + } else { + MachineBasicBlock::iterator MBBI = I; + BuildMI(MBB, MBBI, dl, TII.get(LISInstr), TmpReg) + .addImm(CalleeAmt >> 16); + BuildMI(MBB, MBBI, dl, TII.get(ORIInstr), TmpReg) + .addReg(TmpReg, RegState::Kill) + .addImm(CalleeAmt & 0xFFFF); + BuildMI(MBB, MBBI, dl, TII.get(ADDInstr)) + .addReg(StackReg) + .addReg(StackReg) + .addReg(TmpReg); + } + } + } + // Simply discard ADJCALLSTACKDOWN, ADJCALLSTACKUP instructions. + MBB.erase(I); +} + +/// findScratchRegister - Find a 'free' PPC register. Try for a call-clobbered +/// register first and then a spilled callee-saved register if that fails. +static +unsigned findScratchRegister(MachineBasicBlock::iterator II, RegScavenger *RS, + const TargetRegisterClass *RC, int SPAdj) { + assert(RS && "Register scavenging must be on"); + unsigned Reg = RS->FindUnusedReg(RC); + // FIXME: move ARM callee-saved reg scan to target independent code, then + // search for already spilled CS register here. + if (Reg == 0) + Reg = RS->scavengeRegister(RC, II, SPAdj); + return Reg; +} + +/// lowerDynamicAlloc - Generate the code for allocating an object in the +/// current frame. The sequence of code with be in the general form +/// +/// addi R0, SP, \#frameSize ; get the address of the previous frame +/// stwxu R0, SP, Rnegsize ; add and update the SP with the negated size +/// addi Rnew, SP, \#maxCalFrameSize ; get the top of the allocation +/// +void PPCRegisterInfo::lowerDynamicAlloc(MachineBasicBlock::iterator II, + int SPAdj, RegScavenger *RS) const { + // Get the instruction. + MachineInstr &MI = *II; + // Get the instruction's basic block. + MachineBasicBlock &MBB = *MI.getParent(); + // Get the basic block's function. + MachineFunction &MF = *MBB.getParent(); + // Get the frame info. + MachineFrameInfo *MFI = MF.getFrameInfo(); + // Determine whether 64-bit pointers are used. + bool LP64 = Subtarget.isPPC64(); + DebugLoc dl = MI.getDebugLoc(); + + // Get the maximum call stack size. + unsigned maxCallFrameSize = MFI->getMaxCallFrameSize(); + // Get the total frame size. + unsigned FrameSize = MFI->getStackSize(); + + // Get stack alignments. + unsigned TargetAlign = MF.getTarget().getFrameInfo()->getStackAlignment(); + unsigned MaxAlign = MFI->getMaxAlignment(); + assert(MaxAlign <= TargetAlign && + "Dynamic alloca with large aligns not supported"); + + // Determine the previous frame's address. If FrameSize can't be + // represented as 16 bits or we need special alignment, then we load the + // previous frame's address from 0(SP). Why not do an addis of the hi? + // Because R0 is our only safe tmp register and addi/addis treat R0 as zero. + // Constructing the constant and adding would take 3 instructions. + // Fortunately, a frame greater than 32K is rare. + const TargetRegisterClass *G8RC = &PPC::G8RCRegClass; + const TargetRegisterClass *GPRC = &PPC::GPRCRegClass; + const TargetRegisterClass *RC = LP64 ? G8RC : GPRC; + + // FIXME (64-bit): Use "findScratchRegister" + unsigned Reg; + if (EnableRegisterScavenging) + Reg = findScratchRegister(II, RS, RC, SPAdj); + else + Reg = PPC::R0; + + if (MaxAlign < TargetAlign && isInt16(FrameSize)) { + BuildMI(MBB, II, dl, TII.get(PPC::ADDI), Reg) + .addReg(PPC::R31) + .addImm(FrameSize); + } else if (LP64) { + if (EnableRegisterScavenging) // FIXME (64-bit): Use "true" part. + BuildMI(MBB, II, dl, TII.get(PPC::LD), Reg) + .addImm(0) + .addReg(PPC::X1); + else + BuildMI(MBB, II, dl, TII.get(PPC::LD), PPC::X0) + .addImm(0) + .addReg(PPC::X1); + } else { + BuildMI(MBB, II, dl, TII.get(PPC::LWZ), Reg) + .addImm(0) + .addReg(PPC::R1); + } + + // Grow the stack and update the stack pointer link, then determine the + // address of new allocated space. + if (LP64) { + if (EnableRegisterScavenging) // FIXME (64-bit): Use "true" part. + BuildMI(MBB, II, dl, TII.get(PPC::STDUX)) + .addReg(Reg, RegState::Kill) + .addReg(PPC::X1) + .addReg(MI.getOperand(1).getReg()); + else + BuildMI(MBB, II, dl, TII.get(PPC::STDUX)) + .addReg(PPC::X0, RegState::Kill) + .addReg(PPC::X1) + .addReg(MI.getOperand(1).getReg()); + + if (!MI.getOperand(1).isKill()) + BuildMI(MBB, II, dl, TII.get(PPC::ADDI8), MI.getOperand(0).getReg()) + .addReg(PPC::X1) + .addImm(maxCallFrameSize); + else + // Implicitly kill the register. + BuildMI(MBB, II, dl, TII.get(PPC::ADDI8), MI.getOperand(0).getReg()) + .addReg(PPC::X1) + .addImm(maxCallFrameSize) + .addReg(MI.getOperand(1).getReg(), RegState::ImplicitKill); + } else { + BuildMI(MBB, II, dl, TII.get(PPC::STWUX)) + .addReg(Reg, RegState::Kill) + .addReg(PPC::R1) + .addReg(MI.getOperand(1).getReg()); + + if (!MI.getOperand(1).isKill()) + BuildMI(MBB, II, dl, TII.get(PPC::ADDI), MI.getOperand(0).getReg()) + .addReg(PPC::R1) + .addImm(maxCallFrameSize); + else + // Implicitly kill the register. + BuildMI(MBB, II, dl, TII.get(PPC::ADDI), MI.getOperand(0).getReg()) + .addReg(PPC::R1) + .addImm(maxCallFrameSize) + .addReg(MI.getOperand(1).getReg(), RegState::ImplicitKill); + } + + // Discard the DYNALLOC instruction. + MBB.erase(II); +} + +/// lowerCRSpilling - Generate the code for spilling a CR register. Instead of +/// reserving a whole register (R0), we scrounge for one here. This generates +/// code like this: +/// +/// mfcr rA ; Move the conditional register into GPR rA. +/// rlwinm rA, rA, SB, 0, 31 ; Shift the bits left so they are in CR0's slot. +/// stw rA, FI ; Store rA to the frame. +/// +void PPCRegisterInfo::lowerCRSpilling(MachineBasicBlock::iterator II, + unsigned FrameIndex, int SPAdj, + RegScavenger *RS) const { + // Get the instruction. + MachineInstr &MI = *II; // ; SPILL_CR , , + // Get the instruction's basic block. + MachineBasicBlock &MBB = *MI.getParent(); + DebugLoc dl = MI.getDebugLoc(); + + const TargetRegisterClass *G8RC = &PPC::G8RCRegClass; + const TargetRegisterClass *GPRC = &PPC::GPRCRegClass; + const TargetRegisterClass *RC = Subtarget.isPPC64() ? G8RC : GPRC; + unsigned Reg = findScratchRegister(II, RS, RC, SPAdj); + + // We need to store the CR in the low 4-bits of the saved value. First, issue + // an MFCR to save all of the CRBits. Add an implicit kill of the CR. + if (!MI.getOperand(0).isKill()) + BuildMI(MBB, II, dl, TII.get(PPC::MFCR), Reg); + else + // Implicitly kill the CR register. + BuildMI(MBB, II, dl, TII.get(PPC::MFCR), Reg) + .addReg(MI.getOperand(0).getReg(), RegState::ImplicitKill); + + // If the saved register wasn't CR0, shift the bits left so that they are in + // CR0's slot. + unsigned SrcReg = MI.getOperand(0).getReg(); + if (SrcReg != PPC::CR0) + // rlwinm rA, rA, ShiftBits, 0, 31. + BuildMI(MBB, II, dl, TII.get(PPC::RLWINM), Reg) + .addReg(Reg, RegState::Kill) + .addImm(PPCRegisterInfo::getRegisterNumbering(SrcReg) * 4) + .addImm(0) + .addImm(31); + + addFrameReference(BuildMI(MBB, II, dl, TII.get(PPC::STW)) + .addReg(Reg, getKillRegState(MI.getOperand(1).getImm())), + FrameIndex); + + // Discard the pseudo instruction. + MBB.erase(II); +} + +unsigned +PPCRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, + int SPAdj, int *Value, + RegScavenger *RS) const { + assert(SPAdj == 0 && "Unexpected"); + + // Get the instruction. + MachineInstr &MI = *II; + // Get the instruction's basic block. + MachineBasicBlock &MBB = *MI.getParent(); + // Get the basic block's function. + MachineFunction &MF = *MBB.getParent(); + // Get the frame info. + MachineFrameInfo *MFI = MF.getFrameInfo(); + DebugLoc dl = MI.getDebugLoc(); + + // Find out which operand is the frame index. + unsigned FIOperandNo = 0; + while (!MI.getOperand(FIOperandNo).isFI()) { + ++FIOperandNo; + assert(FIOperandNo != MI.getNumOperands() && + "Instr doesn't have FrameIndex operand!"); + } + // Take into account whether it's an add or mem instruction + unsigned OffsetOperandNo = (FIOperandNo == 2) ? 1 : 2; + if (MI.getOpcode() == TargetInstrInfo::INLINEASM) + OffsetOperandNo = FIOperandNo-1; + + // Get the frame index. + int FrameIndex = MI.getOperand(FIOperandNo).getIndex(); + + // Get the frame pointer save index. Users of this index are primarily + // DYNALLOC instructions. + PPCFunctionInfo *FI = MF.getInfo(); + int FPSI = FI->getFramePointerSaveIndex(); + // Get the instruction opcode. + unsigned OpC = MI.getOpcode(); + + // Special case for dynamic alloca. + if (FPSI && FrameIndex == FPSI && + (OpC == PPC::DYNALLOC || OpC == PPC::DYNALLOC8)) { + lowerDynamicAlloc(II, SPAdj, RS); + return 0; + } + + // Special case for pseudo-op SPILL_CR. + if (EnableRegisterScavenging) // FIXME (64-bit): Enable by default. + if (OpC == PPC::SPILL_CR) { + lowerCRSpilling(II, FrameIndex, SPAdj, RS); + return 0; + } + + // Replace the FrameIndex with base register with GPR1 (SP) or GPR31 (FP). + MI.getOperand(FIOperandNo).ChangeToRegister(hasFP(MF) ? PPC::R31 : PPC::R1, + false); + + // Figure out if the offset in the instruction is shifted right two bits. This + // is true for instructions like "STD", which the machine implicitly adds two + // low zeros to. + bool isIXAddr = false; + switch (OpC) { + case PPC::LWA: + case PPC::LD: + case PPC::STD: + case PPC::STD_32: + isIXAddr = true; + break; + } + + // Now add the frame object offset to the offset from r1. + int Offset = MFI->getObjectOffset(FrameIndex); + if (!isIXAddr) + Offset += MI.getOperand(OffsetOperandNo).getImm(); + else + Offset += MI.getOperand(OffsetOperandNo).getImm() << 2; + + // If we're not using a Frame Pointer that has been set to the value of the + // SP before having the stack size subtracted from it, then add the stack size + // to Offset to get the correct offset. + Offset += MFI->getStackSize(); + + // If we can, encode the offset directly into the instruction. If this is a + // normal PPC "ri" instruction, any 16-bit value can be safely encoded. If + // this is a PPC64 "ix" instruction, only a 16-bit value with the low two bits + // clear can be encoded. This is extremely uncommon, because normally you + // only "std" to a stack slot that is at least 4-byte aligned, but it can + // happen in invalid code. + if (isInt16(Offset) && (!isIXAddr || (Offset & 3) == 0)) { + if (isIXAddr) + Offset >>= 2; // The actual encoded value has the low two bits zero. + MI.getOperand(OffsetOperandNo).ChangeToImmediate(Offset); + return 0; + } + + // The offset doesn't fit into a single register, scavenge one to build the + // offset in. + // FIXME: figure out what SPAdj is doing here. + + // FIXME (64-bit): Use "findScratchRegister". + unsigned SReg; + if (EnableRegisterScavenging) + SReg = findScratchRegister(II, RS, &PPC::GPRCRegClass, SPAdj); + else + SReg = PPC::R0; + + // Insert a set of rA with the full offset value before the ld, st, or add + BuildMI(MBB, II, dl, TII.get(PPC::LIS), SReg) + .addImm(Offset >> 16); + BuildMI(MBB, II, dl, TII.get(PPC::ORI), SReg) + .addReg(SReg, RegState::Kill) + .addImm(Offset); + + // Convert into indexed form of the instruction: + // + // sth 0:rA, 1:imm 2:(rB) ==> sthx 0:rA, 2:rB, 1:r0 + // addi 0:rA 1:rB, 2, imm ==> add 0:rA, 1:rB, 2:r0 + unsigned OperandBase; + + if (OpC != TargetInstrInfo::INLINEASM) { + assert(ImmToIdxMap.count(OpC) && + "No indexed form of load or store available!"); + unsigned NewOpcode = ImmToIdxMap.find(OpC)->second; + MI.setDesc(TII.get(NewOpcode)); + OperandBase = 1; + } else { + OperandBase = OffsetOperandNo; + } + + unsigned StackReg = MI.getOperand(FIOperandNo).getReg(); + MI.getOperand(OperandBase).ChangeToRegister(StackReg, false); + MI.getOperand(OperandBase + 1).ChangeToRegister(SReg, false); + return 0; +} + +/// VRRegNo - Map from a numbered VR register to its enum value. +/// +static const unsigned short VRRegNo[] = { + PPC::V0 , PPC::V1 , PPC::V2 , PPC::V3 , PPC::V4 , PPC::V5 , PPC::V6 , PPC::V7 , + PPC::V8 , PPC::V9 , PPC::V10, PPC::V11, PPC::V12, PPC::V13, PPC::V14, PPC::V15, + PPC::V16, PPC::V17, PPC::V18, PPC::V19, PPC::V20, PPC::V21, PPC::V22, PPC::V23, + PPC::V24, PPC::V25, PPC::V26, PPC::V27, PPC::V28, PPC::V29, PPC::V30, PPC::V31 +}; + +/// RemoveVRSaveCode - We have found that this function does not need any code +/// to manipulate the VRSAVE register, even though it uses vector registers. +/// This can happen when the only registers used are known to be live in or out +/// of the function. Remove all of the VRSAVE related code from the function. +static void RemoveVRSaveCode(MachineInstr *MI) { + MachineBasicBlock *Entry = MI->getParent(); + MachineFunction *MF = Entry->getParent(); + + // We know that the MTVRSAVE instruction immediately follows MI. Remove it. + MachineBasicBlock::iterator MBBI = MI; + ++MBBI; + assert(MBBI != Entry->end() && MBBI->getOpcode() == PPC::MTVRSAVE); + MBBI->eraseFromParent(); + + bool RemovedAllMTVRSAVEs = true; + // See if we can find and remove the MTVRSAVE instruction from all of the + // epilog blocks. + for (MachineFunction::iterator I = MF->begin(), E = MF->end(); I != E; ++I) { + // If last instruction is a return instruction, add an epilogue + if (!I->empty() && I->back().getDesc().isReturn()) { + bool FoundIt = false; + for (MBBI = I->end(); MBBI != I->begin(); ) { + --MBBI; + if (MBBI->getOpcode() == PPC::MTVRSAVE) { + MBBI->eraseFromParent(); // remove it. + FoundIt = true; + break; + } + } + RemovedAllMTVRSAVEs &= FoundIt; + } + } + + // If we found and removed all MTVRSAVE instructions, remove the read of + // VRSAVE as well. + if (RemovedAllMTVRSAVEs) { + MBBI = MI; + assert(MBBI != Entry->begin() && "UPDATE_VRSAVE is first instr in block?"); + --MBBI; + assert(MBBI->getOpcode() == PPC::MFVRSAVE && "VRSAVE instrs wandered?"); + MBBI->eraseFromParent(); + } + + // Finally, nuke the UPDATE_VRSAVE. + MI->eraseFromParent(); +} + +// HandleVRSaveUpdate - MI is the UPDATE_VRSAVE instruction introduced by the +// instruction selector. Based on the vector registers that have been used, +// transform this into the appropriate ORI instruction. +static void HandleVRSaveUpdate(MachineInstr *MI, const TargetInstrInfo &TII) { + MachineFunction *MF = MI->getParent()->getParent(); + DebugLoc dl = MI->getDebugLoc(); + + unsigned UsedRegMask = 0; + for (unsigned i = 0; i != 32; ++i) + if (MF->getRegInfo().isPhysRegUsed(VRRegNo[i])) + UsedRegMask |= 1 << (31-i); + + // Live in and live out values already must be in the mask, so don't bother + // marking them. + for (MachineRegisterInfo::livein_iterator + I = MF->getRegInfo().livein_begin(), + E = MF->getRegInfo().livein_end(); I != E; ++I) { + unsigned RegNo = PPCRegisterInfo::getRegisterNumbering(I->first); + if (VRRegNo[RegNo] == I->first) // If this really is a vector reg. + UsedRegMask &= ~(1 << (31-RegNo)); // Doesn't need to be marked. + } + for (MachineRegisterInfo::liveout_iterator + I = MF->getRegInfo().liveout_begin(), + E = MF->getRegInfo().liveout_end(); I != E; ++I) { + unsigned RegNo = PPCRegisterInfo::getRegisterNumbering(*I); + if (VRRegNo[RegNo] == *I) // If this really is a vector reg. + UsedRegMask &= ~(1 << (31-RegNo)); // Doesn't need to be marked. + } + + // If no registers are used, turn this into a copy. + if (UsedRegMask == 0) { + // Remove all VRSAVE code. + RemoveVRSaveCode(MI); + return; + } + + unsigned SrcReg = MI->getOperand(1).getReg(); + unsigned DstReg = MI->getOperand(0).getReg(); + + if ((UsedRegMask & 0xFFFF) == UsedRegMask) { + if (DstReg != SrcReg) + BuildMI(*MI->getParent(), MI, dl, TII.get(PPC::ORI), DstReg) + .addReg(SrcReg) + .addImm(UsedRegMask); + else + BuildMI(*MI->getParent(), MI, dl, TII.get(PPC::ORI), DstReg) + .addReg(SrcReg, RegState::Kill) + .addImm(UsedRegMask); + } else if ((UsedRegMask & 0xFFFF0000) == UsedRegMask) { + if (DstReg != SrcReg) + BuildMI(*MI->getParent(), MI, dl, TII.get(PPC::ORIS), DstReg) + .addReg(SrcReg) + .addImm(UsedRegMask >> 16); + else + BuildMI(*MI->getParent(), MI, dl, TII.get(PPC::ORIS), DstReg) + .addReg(SrcReg, RegState::Kill) + .addImm(UsedRegMask >> 16); + } else { + if (DstReg != SrcReg) + BuildMI(*MI->getParent(), MI, dl, TII.get(PPC::ORIS), DstReg) + .addReg(SrcReg) + .addImm(UsedRegMask >> 16); + else + BuildMI(*MI->getParent(), MI, dl, TII.get(PPC::ORIS), DstReg) + .addReg(SrcReg, RegState::Kill) + .addImm(UsedRegMask >> 16); + + BuildMI(*MI->getParent(), MI, dl, TII.get(PPC::ORI), DstReg) + .addReg(DstReg, RegState::Kill) + .addImm(UsedRegMask & 0xFFFF); + } + + // Remove the old UPDATE_VRSAVE instruction. + MI->eraseFromParent(); +} + +/// determineFrameLayout - Determine the size of the frame and maximum call +/// frame size. +void PPCRegisterInfo::determineFrameLayout(MachineFunction &MF) const { + MachineFrameInfo *MFI = MF.getFrameInfo(); + + // Get the number of bytes to allocate from the FrameInfo + unsigned FrameSize = MFI->getStackSize(); + + // Get the alignments provided by the target, and the maximum alignment + // (if any) of the fixed frame objects. + unsigned MaxAlign = MFI->getMaxAlignment(); + unsigned TargetAlign = MF.getTarget().getFrameInfo()->getStackAlignment(); + unsigned AlignMask = TargetAlign - 1; // + + // If we are a leaf function, and use up to 224 bytes of stack space, + // don't have a frame pointer, calls, or dynamic alloca then we do not need + // to adjust the stack pointer (we fit in the Red Zone). + bool DisableRedZone = MF.getFunction()->hasFnAttr(Attribute::NoRedZone); + // FIXME SVR4 The 32-bit SVR4 ABI has no red zone. + if (!DisableRedZone && + FrameSize <= 224 && // Fits in red zone. + !MFI->hasVarSizedObjects() && // No dynamic alloca. + !MFI->hasCalls() && // No calls. + (!ALIGN_STACK || MaxAlign <= TargetAlign)) { // No special alignment. + // No need for frame + MFI->setStackSize(0); + return; + } + + // Get the maximum call frame size of all the calls. + unsigned maxCallFrameSize = MFI->getMaxCallFrameSize(); + + // Maximum call frame needs to be at least big enough for linkage and 8 args. + unsigned minCallFrameSize = + PPCFrameInfo::getMinCallFrameSize(Subtarget.isPPC64(), + Subtarget.isDarwinABI()); + maxCallFrameSize = std::max(maxCallFrameSize, minCallFrameSize); + + // If we have dynamic alloca then maxCallFrameSize needs to be aligned so + // that allocations will be aligned. + if (MFI->hasVarSizedObjects()) + maxCallFrameSize = (maxCallFrameSize + AlignMask) & ~AlignMask; + + // Update maximum call frame size. + MFI->setMaxCallFrameSize(maxCallFrameSize); + + // Include call frame size in total. + FrameSize += maxCallFrameSize; + + // Make sure the frame is aligned. + FrameSize = (FrameSize + AlignMask) & ~AlignMask; + + // Update frame info. + MFI->setStackSize(FrameSize); +} + +void +PPCRegisterInfo::processFunctionBeforeCalleeSavedScan(MachineFunction &MF, + RegScavenger *RS) const { + // Save and clear the LR state. + PPCFunctionInfo *FI = MF.getInfo(); + unsigned LR = getRARegister(); + FI->setMustSaveLR(MustSaveLR(MF, LR)); + MF.getRegInfo().setPhysRegUnused(LR); + + // Save R31 if necessary + int FPSI = FI->getFramePointerSaveIndex(); + bool isPPC64 = Subtarget.isPPC64(); + bool isDarwinABI = Subtarget.isDarwinABI(); + MachineFrameInfo *MFI = MF.getFrameInfo(); + + // If the frame pointer save index hasn't been defined yet. + if (!FPSI && needsFP(MF)) { + // Find out what the fix offset of the frame pointer save area. + int FPOffset = PPCFrameInfo::getFramePointerSaveOffset(isPPC64, + isDarwinABI); + // Allocate the frame index for frame pointer save area. + FPSI = MF.getFrameInfo()->CreateFixedObject(isPPC64? 8 : 4, FPOffset, + true, false); + // Save the result. + FI->setFramePointerSaveIndex(FPSI); + } + + // Reserve stack space to move the linkage area to in case of a tail call. + int TCSPDelta = 0; + if (PerformTailCallOpt && (TCSPDelta = FI->getTailCallSPDelta()) < 0) { + MF.getFrameInfo()->CreateFixedObject(-1 * TCSPDelta, TCSPDelta, + true, false); + } + + // Reserve a slot closest to SP or frame pointer if we have a dynalloc or + // a large stack, which will require scavenging a register to materialize a + // large offset. + // FIXME: this doesn't actually check stack size, so is a bit pessimistic + // FIXME: doesn't detect whether or not we need to spill vXX, which requires + // r0 for now. + + if (EnableRegisterScavenging) // FIXME (64-bit): Enable. + if (needsFP(MF) || spillsCR(MF)) { + const TargetRegisterClass *GPRC = &PPC::GPRCRegClass; + const TargetRegisterClass *G8RC = &PPC::G8RCRegClass; + const TargetRegisterClass *RC = isPPC64 ? G8RC : GPRC; + RS->setScavengingFrameIndex(MFI->CreateStackObject(RC->getSize(), + RC->getAlignment(), + false)); + } +} + +void +PPCRegisterInfo::processFunctionBeforeFrameFinalized(MachineFunction &MF) + const { + // Early exit if not using the SVR4 ABI. + if (!Subtarget.isSVR4ABI()) { + return; + } + + // Get callee saved register information. + MachineFrameInfo *FFI = MF.getFrameInfo(); + const std::vector &CSI = FFI->getCalleeSavedInfo(); + + // Early exit if no callee saved registers are modified! + if (CSI.empty() && !needsFP(MF)) { + return; + } + + unsigned MinGPR = PPC::R31; + unsigned MinG8R = PPC::X31; + unsigned MinFPR = PPC::F31; + unsigned MinVR = PPC::V31; + + bool HasGPSaveArea = false; + bool HasG8SaveArea = false; + bool HasFPSaveArea = false; + bool HasCRSaveArea = false; + bool HasVRSAVESaveArea = false; + bool HasVRSaveArea = false; + + SmallVector GPRegs; + SmallVector G8Regs; + SmallVector FPRegs; + SmallVector VRegs; + + for (unsigned i = 0, e = CSI.size(); i != e; ++i) { + unsigned Reg = CSI[i].getReg(); + const TargetRegisterClass *RC = CSI[i].getRegClass(); + + if (RC == PPC::GPRCRegisterClass) { + HasGPSaveArea = true; + + GPRegs.push_back(CSI[i]); + + if (Reg < MinGPR) { + MinGPR = Reg; + } + } else if (RC == PPC::G8RCRegisterClass) { + HasG8SaveArea = true; + + G8Regs.push_back(CSI[i]); + + if (Reg < MinG8R) { + MinG8R = Reg; + } + } else if (RC == PPC::F8RCRegisterClass) { + HasFPSaveArea = true; + + FPRegs.push_back(CSI[i]); + + if (Reg < MinFPR) { + MinFPR = Reg; + } +// FIXME SVR4: Disable CR save area for now. + } else if ( RC == PPC::CRBITRCRegisterClass + || RC == PPC::CRRCRegisterClass) { +// HasCRSaveArea = true; + } else if (RC == PPC::VRSAVERCRegisterClass) { + HasVRSAVESaveArea = true; + } else if (RC == PPC::VRRCRegisterClass) { + HasVRSaveArea = true; + + VRegs.push_back(CSI[i]); + + if (Reg < MinVR) { + MinVR = Reg; + } + } else { + llvm_unreachable("Unknown RegisterClass!"); + } + } + + PPCFunctionInfo *PFI = MF.getInfo(); + + int64_t LowerBound = 0; + + // Take into account stack space reserved for tail calls. + int TCSPDelta = 0; + if (PerformTailCallOpt && (TCSPDelta = PFI->getTailCallSPDelta()) < 0) { + LowerBound = TCSPDelta; + } + + // The Floating-point register save area is right below the back chain word + // of the previous stack frame. + if (HasFPSaveArea) { + for (unsigned i = 0, e = FPRegs.size(); i != e; ++i) { + int FI = FPRegs[i].getFrameIdx(); + + FFI->setObjectOffset(FI, LowerBound + FFI->getObjectOffset(FI)); + } + + LowerBound -= (31 - getRegisterNumbering(MinFPR) + 1) * 8; + } + + // Check whether the frame pointer register is allocated. If so, make sure it + // is spilled to the correct offset. + if (needsFP(MF)) { + HasGPSaveArea = true; + + int FI = PFI->getFramePointerSaveIndex(); + assert(FI && "No Frame Pointer Save Slot!"); + + FFI->setObjectOffset(FI, LowerBound + FFI->getObjectOffset(FI)); + } + + // General register save area starts right below the Floating-point + // register save area. + if (HasGPSaveArea || HasG8SaveArea) { + // Move general register save area spill slots down, taking into account + // the size of the Floating-point register save area. + for (unsigned i = 0, e = GPRegs.size(); i != e; ++i) { + int FI = GPRegs[i].getFrameIdx(); + + FFI->setObjectOffset(FI, LowerBound + FFI->getObjectOffset(FI)); + } + + // Move general register save area spill slots down, taking into account + // the size of the Floating-point register save area. + for (unsigned i = 0, e = G8Regs.size(); i != e; ++i) { + int FI = G8Regs[i].getFrameIdx(); + + FFI->setObjectOffset(FI, LowerBound + FFI->getObjectOffset(FI)); + } + + unsigned MinReg = std::min(getRegisterNumbering(MinGPR), + getRegisterNumbering(MinG8R)); + + if (Subtarget.isPPC64()) { + LowerBound -= (31 - MinReg + 1) * 8; + } else { + LowerBound -= (31 - MinReg + 1) * 4; + } + } + + // The CR save area is below the general register save area. + if (HasCRSaveArea) { + // FIXME SVR4: Is it actually possible to have multiple elements in CSI + // which have the CR/CRBIT register class? + // Adjust the frame index of the CR spill slot. + for (unsigned i = 0, e = CSI.size(); i != e; ++i) { + const TargetRegisterClass *RC = CSI[i].getRegClass(); + + if (RC == PPC::CRBITRCRegisterClass || RC == PPC::CRRCRegisterClass) { + int FI = CSI[i].getFrameIdx(); + + FFI->setObjectOffset(FI, LowerBound + FFI->getObjectOffset(FI)); + } + } + + LowerBound -= 4; // The CR save area is always 4 bytes long. + } + + if (HasVRSAVESaveArea) { + // FIXME SVR4: Is it actually possible to have multiple elements in CSI + // which have the VRSAVE register class? + // Adjust the frame index of the VRSAVE spill slot. + for (unsigned i = 0, e = CSI.size(); i != e; ++i) { + const TargetRegisterClass *RC = CSI[i].getRegClass(); + + if (RC == PPC::VRSAVERCRegisterClass) { + int FI = CSI[i].getFrameIdx(); + + FFI->setObjectOffset(FI, LowerBound + FFI->getObjectOffset(FI)); + } + } + + LowerBound -= 4; // The VRSAVE save area is always 4 bytes long. + } + + if (HasVRSaveArea) { + // Insert alignment padding, we need 16-byte alignment. + LowerBound = (LowerBound - 15) & ~(15); + + for (unsigned i = 0, e = VRegs.size(); i != e; ++i) { + int FI = VRegs[i].getFrameIdx(); + + FFI->setObjectOffset(FI, LowerBound + FFI->getObjectOffset(FI)); + } + } +} + +void +PPCRegisterInfo::emitPrologue(MachineFunction &MF) const { + MachineBasicBlock &MBB = MF.front(); // Prolog goes in entry BB + MachineBasicBlock::iterator MBBI = MBB.begin(); + MachineFrameInfo *MFI = MF.getFrameInfo(); + MachineModuleInfo *MMI = MFI->getMachineModuleInfo(); + DebugLoc dl = DebugLoc::getUnknownLoc(); + bool needsFrameMoves = (MMI && MMI->hasDebugInfo()) || + !MF.getFunction()->doesNotThrow() || + UnwindTablesMandatory; + + // Prepare for frame info. + unsigned FrameLabelId = 0; + + // Scan the prolog, looking for an UPDATE_VRSAVE instruction. If we find it, + // process it. + for (unsigned i = 0; MBBI != MBB.end(); ++i, ++MBBI) { + if (MBBI->getOpcode() == PPC::UPDATE_VRSAVE) { + HandleVRSaveUpdate(MBBI, TII); + break; + } + } + + // Move MBBI back to the beginning of the function. + MBBI = MBB.begin(); + + // Work out frame sizes. + determineFrameLayout(MF); + unsigned FrameSize = MFI->getStackSize(); + + int NegFrameSize = -FrameSize; + + // Get processor type. + bool isPPC64 = Subtarget.isPPC64(); + // Get operating system + bool isDarwinABI = Subtarget.isDarwinABI(); + // Check if the link register (LR) must be saved. + PPCFunctionInfo *FI = MF.getInfo(); + bool MustSaveLR = FI->mustSaveLR(); + // Do we have a frame pointer for this function? + bool HasFP = hasFP(MF) && FrameSize; + + int LROffset = PPCFrameInfo::getReturnSaveOffset(isPPC64, isDarwinABI); + + int FPOffset = 0; + if (HasFP) { + if (Subtarget.isSVR4ABI()) { + MachineFrameInfo *FFI = MF.getFrameInfo(); + int FPIndex = FI->getFramePointerSaveIndex(); + assert(FPIndex && "No Frame Pointer Save Slot!"); + FPOffset = FFI->getObjectOffset(FPIndex); + } else { + FPOffset = PPCFrameInfo::getFramePointerSaveOffset(isPPC64, isDarwinABI); + } + } + + if (isPPC64) { + if (MustSaveLR) + BuildMI(MBB, MBBI, dl, TII.get(PPC::MFLR8), PPC::X0); + + if (HasFP) + BuildMI(MBB, MBBI, dl, TII.get(PPC::STD)) + .addReg(PPC::X31) + .addImm(FPOffset/4) + .addReg(PPC::X1); + + if (MustSaveLR) + BuildMI(MBB, MBBI, dl, TII.get(PPC::STD)) + .addReg(PPC::X0) + .addImm(LROffset / 4) + .addReg(PPC::X1); + } else { + if (MustSaveLR) + BuildMI(MBB, MBBI, dl, TII.get(PPC::MFLR), PPC::R0); + + if (HasFP) + BuildMI(MBB, MBBI, dl, TII.get(PPC::STW)) + .addReg(PPC::R31) + .addImm(FPOffset) + .addReg(PPC::R1); + + if (MustSaveLR) + BuildMI(MBB, MBBI, dl, TII.get(PPC::STW)) + .addReg(PPC::R0) + .addImm(LROffset) + .addReg(PPC::R1); + } + + // Skip if a leaf routine. + if (!FrameSize) return; + + // Get stack alignments. + unsigned TargetAlign = MF.getTarget().getFrameInfo()->getStackAlignment(); + unsigned MaxAlign = MFI->getMaxAlignment(); + + // Adjust stack pointer: r1 += NegFrameSize. + // If there is a preferred stack alignment, align R1 now + if (!isPPC64) { + // PPC32. + if (ALIGN_STACK && MaxAlign > TargetAlign) { + assert(isPowerOf2_32(MaxAlign)&&isInt16(MaxAlign)&&"Invalid alignment!"); + assert(isInt16(NegFrameSize) && "Unhandled stack size and alignment!"); + + BuildMI(MBB, MBBI, dl, TII.get(PPC::RLWINM), PPC::R0) + .addReg(PPC::R1) + .addImm(0) + .addImm(32 - Log2_32(MaxAlign)) + .addImm(31); + BuildMI(MBB, MBBI, dl, TII.get(PPC::SUBFIC) ,PPC::R0) + .addReg(PPC::R0, RegState::Kill) + .addImm(NegFrameSize); + BuildMI(MBB, MBBI, dl, TII.get(PPC::STWUX)) + .addReg(PPC::R1) + .addReg(PPC::R1) + .addReg(PPC::R0); + } else if (isInt16(NegFrameSize)) { + BuildMI(MBB, MBBI, dl, TII.get(PPC::STWU), PPC::R1) + .addReg(PPC::R1) + .addImm(NegFrameSize) + .addReg(PPC::R1); + } else { + BuildMI(MBB, MBBI, dl, TII.get(PPC::LIS), PPC::R0) + .addImm(NegFrameSize >> 16); + BuildMI(MBB, MBBI, dl, TII.get(PPC::ORI), PPC::R0) + .addReg(PPC::R0, RegState::Kill) + .addImm(NegFrameSize & 0xFFFF); + BuildMI(MBB, MBBI, dl, TII.get(PPC::STWUX)) + .addReg(PPC::R1) + .addReg(PPC::R1) + .addReg(PPC::R0); + } + } else { // PPC64. + if (ALIGN_STACK && MaxAlign > TargetAlign) { + assert(isPowerOf2_32(MaxAlign)&&isInt16(MaxAlign)&&"Invalid alignment!"); + assert(isInt16(NegFrameSize) && "Unhandled stack size and alignment!"); + + BuildMI(MBB, MBBI, dl, TII.get(PPC::RLDICL), PPC::X0) + .addReg(PPC::X1) + .addImm(0) + .addImm(64 - Log2_32(MaxAlign)); + BuildMI(MBB, MBBI, dl, TII.get(PPC::SUBFIC8), PPC::X0) + .addReg(PPC::X0) + .addImm(NegFrameSize); + BuildMI(MBB, MBBI, dl, TII.get(PPC::STDUX)) + .addReg(PPC::X1) + .addReg(PPC::X1) + .addReg(PPC::X0); + } else if (isInt16(NegFrameSize)) { + BuildMI(MBB, MBBI, dl, TII.get(PPC::STDU), PPC::X1) + .addReg(PPC::X1) + .addImm(NegFrameSize / 4) + .addReg(PPC::X1); + } else { + BuildMI(MBB, MBBI, dl, TII.get(PPC::LIS8), PPC::X0) + .addImm(NegFrameSize >> 16); + BuildMI(MBB, MBBI, dl, TII.get(PPC::ORI8), PPC::X0) + .addReg(PPC::X0, RegState::Kill) + .addImm(NegFrameSize & 0xFFFF); + BuildMI(MBB, MBBI, dl, TII.get(PPC::STDUX)) + .addReg(PPC::X1) + .addReg(PPC::X1) + .addReg(PPC::X0); + } + } + + std::vector &Moves = MMI->getFrameMoves(); + + // Add the "machine moves" for the instructions we generated above, but in + // reverse order. + if (needsFrameMoves) { + // Mark effective beginning of when frame pointer becomes valid. + FrameLabelId = MMI->NextLabelID(); + BuildMI(MBB, MBBI, dl, TII.get(PPC::DBG_LABEL)).addImm(FrameLabelId); + + // Show update of SP. + if (NegFrameSize) { + MachineLocation SPDst(MachineLocation::VirtualFP); + MachineLocation SPSrc(MachineLocation::VirtualFP, NegFrameSize); + Moves.push_back(MachineMove(FrameLabelId, SPDst, SPSrc)); + } else { + MachineLocation SP(isPPC64 ? PPC::X31 : PPC::R31); + Moves.push_back(MachineMove(FrameLabelId, SP, SP)); + } + + if (HasFP) { + MachineLocation FPDst(MachineLocation::VirtualFP, FPOffset); + MachineLocation FPSrc(isPPC64 ? PPC::X31 : PPC::R31); + Moves.push_back(MachineMove(FrameLabelId, FPDst, FPSrc)); + } + + if (MustSaveLR) { + MachineLocation LRDst(MachineLocation::VirtualFP, LROffset); + MachineLocation LRSrc(isPPC64 ? PPC::LR8 : PPC::LR); + Moves.push_back(MachineMove(FrameLabelId, LRDst, LRSrc)); + } + } + + unsigned ReadyLabelId = 0; + + // If there is a frame pointer, copy R1 into R31 + if (HasFP) { + if (!isPPC64) { + BuildMI(MBB, MBBI, dl, TII.get(PPC::OR), PPC::R31) + .addReg(PPC::R1) + .addReg(PPC::R1); + } else { + BuildMI(MBB, MBBI, dl, TII.get(PPC::OR8), PPC::X31) + .addReg(PPC::X1) + .addReg(PPC::X1); + } + + if (needsFrameMoves) { + ReadyLabelId = MMI->NextLabelID(); + + // Mark effective beginning of when frame pointer is ready. + BuildMI(MBB, MBBI, dl, TII.get(PPC::DBG_LABEL)).addImm(ReadyLabelId); + + MachineLocation FPDst(HasFP ? (isPPC64 ? PPC::X31 : PPC::R31) : + (isPPC64 ? PPC::X1 : PPC::R1)); + MachineLocation FPSrc(MachineLocation::VirtualFP); + Moves.push_back(MachineMove(ReadyLabelId, FPDst, FPSrc)); + } + } + + if (needsFrameMoves) { + unsigned LabelId = HasFP ? ReadyLabelId : FrameLabelId; + + // Add callee saved registers to move list. + const std::vector &CSI = MFI->getCalleeSavedInfo(); + for (unsigned I = 0, E = CSI.size(); I != E; ++I) { + int Offset = MFI->getObjectOffset(CSI[I].getFrameIdx()); + unsigned Reg = CSI[I].getReg(); + if (Reg == PPC::LR || Reg == PPC::LR8 || Reg == PPC::RM) continue; + MachineLocation CSDst(MachineLocation::VirtualFP, Offset); + MachineLocation CSSrc(Reg); + Moves.push_back(MachineMove(LabelId, CSDst, CSSrc)); + } + } +} + +void PPCRegisterInfo::emitEpilogue(MachineFunction &MF, + MachineBasicBlock &MBB) const { + MachineBasicBlock::iterator MBBI = prior(MBB.end()); + unsigned RetOpcode = MBBI->getOpcode(); + DebugLoc dl = DebugLoc::getUnknownLoc(); + + assert( (RetOpcode == PPC::BLR || + RetOpcode == PPC::TCRETURNri || + RetOpcode == PPC::TCRETURNdi || + RetOpcode == PPC::TCRETURNai || + RetOpcode == PPC::TCRETURNri8 || + RetOpcode == PPC::TCRETURNdi8 || + RetOpcode == PPC::TCRETURNai8) && + "Can only insert epilog into returning blocks"); + + // Get alignment info so we know how to restore r1 + const MachineFrameInfo *MFI = MF.getFrameInfo(); + unsigned TargetAlign = MF.getTarget().getFrameInfo()->getStackAlignment(); + unsigned MaxAlign = MFI->getMaxAlignment(); + + // Get the number of bytes allocated from the FrameInfo. + int FrameSize = MFI->getStackSize(); + + // Get processor type. + bool isPPC64 = Subtarget.isPPC64(); + // Get operating system + bool isDarwinABI = Subtarget.isDarwinABI(); + // Check if the link register (LR) has been saved. + PPCFunctionInfo *FI = MF.getInfo(); + bool MustSaveLR = FI->mustSaveLR(); + // Do we have a frame pointer for this function? + bool HasFP = hasFP(MF) && FrameSize; + + int LROffset = PPCFrameInfo::getReturnSaveOffset(isPPC64, isDarwinABI); + + int FPOffset = 0; + if (HasFP) { + if (Subtarget.isSVR4ABI()) { + MachineFrameInfo *FFI = MF.getFrameInfo(); + int FPIndex = FI->getFramePointerSaveIndex(); + assert(FPIndex && "No Frame Pointer Save Slot!"); + FPOffset = FFI->getObjectOffset(FPIndex); + } else { + FPOffset = PPCFrameInfo::getFramePointerSaveOffset(isPPC64, isDarwinABI); + } + } + + bool UsesTCRet = RetOpcode == PPC::TCRETURNri || + RetOpcode == PPC::TCRETURNdi || + RetOpcode == PPC::TCRETURNai || + RetOpcode == PPC::TCRETURNri8 || + RetOpcode == PPC::TCRETURNdi8 || + RetOpcode == PPC::TCRETURNai8; + + if (UsesTCRet) { + int MaxTCRetDelta = FI->getTailCallSPDelta(); + MachineOperand &StackAdjust = MBBI->getOperand(1); + assert(StackAdjust.isImm() && "Expecting immediate value."); + // Adjust stack pointer. + int StackAdj = StackAdjust.getImm(); + int Delta = StackAdj - MaxTCRetDelta; + assert((Delta >= 0) && "Delta must be positive"); + if (MaxTCRetDelta>0) + FrameSize += (StackAdj +Delta); + else + FrameSize += StackAdj; + } + + if (FrameSize) { + // The loaded (or persistent) stack pointer value is offset by the 'stwu' + // on entry to the function. Add this offset back now. + if (!isPPC64) { + // If this function contained a fastcc call and PerformTailCallOpt is + // enabled (=> hasFastCall()==true) the fastcc call might contain a tail + // call which invalidates the stack pointer value in SP(0). So we use the + // value of R31 in this case. + if (FI->hasFastCall() && isInt16(FrameSize)) { + assert(hasFP(MF) && "Expecting a valid the frame pointer."); + BuildMI(MBB, MBBI, dl, TII.get(PPC::ADDI), PPC::R1) + .addReg(PPC::R31).addImm(FrameSize); + } else if(FI->hasFastCall()) { + BuildMI(MBB, MBBI, dl, TII.get(PPC::LIS), PPC::R0) + .addImm(FrameSize >> 16); + BuildMI(MBB, MBBI, dl, TII.get(PPC::ORI), PPC::R0) + .addReg(PPC::R0, RegState::Kill) + .addImm(FrameSize & 0xFFFF); + BuildMI(MBB, MBBI, dl, TII.get(PPC::ADD4)) + .addReg(PPC::R1) + .addReg(PPC::R31) + .addReg(PPC::R0); + } else if (isInt16(FrameSize) && + (!ALIGN_STACK || TargetAlign >= MaxAlign) && + !MFI->hasVarSizedObjects()) { + BuildMI(MBB, MBBI, dl, TII.get(PPC::ADDI), PPC::R1) + .addReg(PPC::R1).addImm(FrameSize); + } else { + BuildMI(MBB, MBBI, dl, TII.get(PPC::LWZ),PPC::R1) + .addImm(0).addReg(PPC::R1); + } + } else { + if (FI->hasFastCall() && isInt16(FrameSize)) { + assert(hasFP(MF) && "Expecting a valid the frame pointer."); + BuildMI(MBB, MBBI, dl, TII.get(PPC::ADDI8), PPC::X1) + .addReg(PPC::X31).addImm(FrameSize); + } else if(FI->hasFastCall()) { + BuildMI(MBB, MBBI, dl, TII.get(PPC::LIS8), PPC::X0) + .addImm(FrameSize >> 16); + BuildMI(MBB, MBBI, dl, TII.get(PPC::ORI8), PPC::X0) + .addReg(PPC::X0, RegState::Kill) + .addImm(FrameSize & 0xFFFF); + BuildMI(MBB, MBBI, dl, TII.get(PPC::ADD8)) + .addReg(PPC::X1) + .addReg(PPC::X31) + .addReg(PPC::X0); + } else if (isInt16(FrameSize) && TargetAlign >= MaxAlign && + !MFI->hasVarSizedObjects()) { + BuildMI(MBB, MBBI, dl, TII.get(PPC::ADDI8), PPC::X1) + .addReg(PPC::X1).addImm(FrameSize); + } else { + BuildMI(MBB, MBBI, dl, TII.get(PPC::LD), PPC::X1) + .addImm(0).addReg(PPC::X1); + } + } + } + + if (isPPC64) { + if (MustSaveLR) + BuildMI(MBB, MBBI, dl, TII.get(PPC::LD), PPC::X0) + .addImm(LROffset/4).addReg(PPC::X1); + + if (HasFP) + BuildMI(MBB, MBBI, dl, TII.get(PPC::LD), PPC::X31) + .addImm(FPOffset/4).addReg(PPC::X1); + + if (MustSaveLR) + BuildMI(MBB, MBBI, dl, TII.get(PPC::MTLR8)).addReg(PPC::X0); + } else { + if (MustSaveLR) + BuildMI(MBB, MBBI, dl, TII.get(PPC::LWZ), PPC::R0) + .addImm(LROffset).addReg(PPC::R1); + + if (HasFP) + BuildMI(MBB, MBBI, dl, TII.get(PPC::LWZ), PPC::R31) + .addImm(FPOffset).addReg(PPC::R1); + + if (MustSaveLR) + BuildMI(MBB, MBBI, dl, TII.get(PPC::MTLR)).addReg(PPC::R0); + } + + // Callee pop calling convention. Pop parameter/linkage area. Used for tail + // call optimization + if (PerformTailCallOpt && RetOpcode == PPC::BLR && + MF.getFunction()->getCallingConv() == CallingConv::Fast) { + PPCFunctionInfo *FI = MF.getInfo(); + unsigned CallerAllocatedAmt = FI->getMinReservedArea(); + unsigned StackReg = isPPC64 ? PPC::X1 : PPC::R1; + unsigned FPReg = isPPC64 ? PPC::X31 : PPC::R31; + unsigned TmpReg = isPPC64 ? PPC::X0 : PPC::R0; + unsigned ADDIInstr = isPPC64 ? PPC::ADDI8 : PPC::ADDI; + unsigned ADDInstr = isPPC64 ? PPC::ADD8 : PPC::ADD4; + unsigned LISInstr = isPPC64 ? PPC::LIS8 : PPC::LIS; + unsigned ORIInstr = isPPC64 ? PPC::ORI8 : PPC::ORI; + + if (CallerAllocatedAmt && isInt16(CallerAllocatedAmt)) { + BuildMI(MBB, MBBI, dl, TII.get(ADDIInstr), StackReg) + .addReg(StackReg).addImm(CallerAllocatedAmt); + } else { + BuildMI(MBB, MBBI, dl, TII.get(LISInstr), TmpReg) + .addImm(CallerAllocatedAmt >> 16); + BuildMI(MBB, MBBI, dl, TII.get(ORIInstr), TmpReg) + .addReg(TmpReg, RegState::Kill) + .addImm(CallerAllocatedAmt & 0xFFFF); + BuildMI(MBB, MBBI, dl, TII.get(ADDInstr)) + .addReg(StackReg) + .addReg(FPReg) + .addReg(TmpReg); + } + } else if (RetOpcode == PPC::TCRETURNdi) { + MBBI = prior(MBB.end()); + MachineOperand &JumpTarget = MBBI->getOperand(0); + BuildMI(MBB, MBBI, dl, TII.get(PPC::TAILB)). + addGlobalAddress(JumpTarget.getGlobal(), JumpTarget.getOffset()); + } else if (RetOpcode == PPC::TCRETURNri) { + MBBI = prior(MBB.end()); + assert(MBBI->getOperand(0).isReg() && "Expecting register operand."); + BuildMI(MBB, MBBI, dl, TII.get(PPC::TAILBCTR)); + } else if (RetOpcode == PPC::TCRETURNai) { + MBBI = prior(MBB.end()); + MachineOperand &JumpTarget = MBBI->getOperand(0); + BuildMI(MBB, MBBI, dl, TII.get(PPC::TAILBA)).addImm(JumpTarget.getImm()); + } else if (RetOpcode == PPC::TCRETURNdi8) { + MBBI = prior(MBB.end()); + MachineOperand &JumpTarget = MBBI->getOperand(0); + BuildMI(MBB, MBBI, dl, TII.get(PPC::TAILB8)). + addGlobalAddress(JumpTarget.getGlobal(), JumpTarget.getOffset()); + } else if (RetOpcode == PPC::TCRETURNri8) { + MBBI = prior(MBB.end()); + assert(MBBI->getOperand(0).isReg() && "Expecting register operand."); + BuildMI(MBB, MBBI, dl, TII.get(PPC::TAILBCTR8)); + } else if (RetOpcode == PPC::TCRETURNai8) { + MBBI = prior(MBB.end()); + MachineOperand &JumpTarget = MBBI->getOperand(0); + BuildMI(MBB, MBBI, dl, TII.get(PPC::TAILBA8)).addImm(JumpTarget.getImm()); + } +} + +unsigned PPCRegisterInfo::getRARegister() const { + return !Subtarget.isPPC64() ? PPC::LR : PPC::LR8; +} + +unsigned PPCRegisterInfo::getFrameRegister(const MachineFunction &MF) const { + if (!Subtarget.isPPC64()) + return hasFP(MF) ? PPC::R31 : PPC::R1; + else + return hasFP(MF) ? PPC::X31 : PPC::X1; +} + +void PPCRegisterInfo::getInitialFrameState(std::vector &Moves) + const { + // Initial state of the frame pointer is R1. + MachineLocation Dst(MachineLocation::VirtualFP); + MachineLocation Src(PPC::R1, 0); + Moves.push_back(MachineMove(0, Dst, Src)); +} + +unsigned PPCRegisterInfo::getEHExceptionRegister() const { + return !Subtarget.isPPC64() ? PPC::R3 : PPC::X3; +} + +unsigned PPCRegisterInfo::getEHHandlerRegister() const { + return !Subtarget.isPPC64() ? PPC::R4 : PPC::X4; +} + +int PPCRegisterInfo::getDwarfRegNum(unsigned RegNum, bool isEH) const { + // FIXME: Most probably dwarf numbers differs for Linux and Darwin + return PPCGenRegisterInfo::getDwarfRegNumFull(RegNum, 0); +} + +#include "PPCGenRegisterInfo.inc" + diff --git a/libclamav/c++/llvm/lib/Target/PowerPC/PPCRegisterInfo.h b/libclamav/c++/llvm/lib/Target/PowerPC/PPCRegisterInfo.h new file mode 100644 index 000000000..3aeed80e0 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/PowerPC/PPCRegisterInfo.h @@ -0,0 +1,98 @@ +//===- PPCRegisterInfo.h - PowerPC Register Information Impl -----*- C++ -*-==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the PowerPC implementation of the TargetRegisterInfo +// class. +// +//===----------------------------------------------------------------------===// + +#ifndef POWERPC32_REGISTERINFO_H +#define POWERPC32_REGISTERINFO_H + +#include "PPC.h" +#include "PPCGenRegisterInfo.h.inc" +#include + +namespace llvm { +class PPCSubtarget; +class TargetInstrInfo; +class Type; + +class PPCRegisterInfo : public PPCGenRegisterInfo { + std::map ImmToIdxMap; + const PPCSubtarget &Subtarget; + const TargetInstrInfo &TII; +public: + PPCRegisterInfo(const PPCSubtarget &SubTarget, const TargetInstrInfo &tii); + + /// getRegisterNumbering - Given the enum value for some register, e.g. + /// PPC::F14, return the number that it corresponds to (e.g. 14). + static unsigned getRegisterNumbering(unsigned RegEnum); + + /// getPointerRegClass - Return the register class to use to hold pointers. + /// This is used for addressing modes. + virtual const TargetRegisterClass *getPointerRegClass(unsigned Kind=0) const; + + /// Code Generation virtual methods... + const unsigned *getCalleeSavedRegs(const MachineFunction* MF = 0) const; + + const TargetRegisterClass* const* + getCalleeSavedRegClasses(const MachineFunction *MF = 0) const; + + BitVector getReservedRegs(const MachineFunction &MF) const; + + /// targetHandlesStackFrameRounding - Returns true if the target is + /// responsible for rounding up the stack frame (probably at emitPrologue + /// time). + bool targetHandlesStackFrameRounding() const { return true; } + + /// requiresRegisterScavenging - We require a register scavenger. + /// FIXME (64-bit): Should be inlined. + bool requiresRegisterScavenging(const MachineFunction &MF) const; + + bool hasFP(const MachineFunction &MF) const; + + void eliminateCallFramePseudoInstr(MachineFunction &MF, + MachineBasicBlock &MBB, + MachineBasicBlock::iterator I) const; + + void lowerDynamicAlloc(MachineBasicBlock::iterator II, + int SPAdj, RegScavenger *RS) const; + void lowerCRSpilling(MachineBasicBlock::iterator II, unsigned FrameIndex, + int SPAdj, RegScavenger *RS) const; + unsigned eliminateFrameIndex(MachineBasicBlock::iterator II, + int SPAdj, int *Value = NULL, + RegScavenger *RS = NULL) const; + + /// determineFrameLayout - Determine the size of the frame and maximum call + /// frame size. + void determineFrameLayout(MachineFunction &MF) const; + + void processFunctionBeforeCalleeSavedScan(MachineFunction &MF, + RegScavenger *RS = NULL) const; + void processFunctionBeforeFrameFinalized(MachineFunction &MF) const; + + void emitPrologue(MachineFunction &MF) const; + void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const; + + // Debug information queries. + unsigned getRARegister() const; + unsigned getFrameRegister(const MachineFunction &MF) const; + void getInitialFrameState(std::vector &Moves) const; + + // Exception handling queries. + unsigned getEHExceptionRegister() const; + unsigned getEHHandlerRegister() const; + + int getDwarfRegNum(unsigned RegNum, bool isEH) const; +}; + +} // end namespace llvm + +#endif diff --git a/libclamav/c++/llvm/lib/Target/PowerPC/PPCRegisterInfo.td b/libclamav/c++/llvm/lib/Target/PowerPC/PPCRegisterInfo.td new file mode 100644 index 000000000..049e893e8 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/PowerPC/PPCRegisterInfo.td @@ -0,0 +1,387 @@ +//===- PPCRegisterInfo.td - The PowerPC Register File ------*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// +//===----------------------------------------------------------------------===// + +class PPCReg : Register { + let Namespace = "PPC"; +} + +// We identify all our registers with a 5-bit ID, for consistency's sake. + +// GPR - One of the 32 32-bit general-purpose registers +class GPR num, string n> : PPCReg { + field bits<5> Num = num; +} + +// GP8 - One of the 32 64-bit general-purpose registers +class GP8 : PPCReg { + field bits<5> Num = SubReg.Num; + let SubRegs = [SubReg]; +} + +// SPR - One of the 32-bit special-purpose registers +class SPR num, string n> : PPCReg { + field bits<10> Num = num; +} + +// FPR - One of the 32 64-bit floating-point registers +class FPR num, string n> : PPCReg { + field bits<5> Num = num; +} + +// VR - One of the 32 128-bit vector registers +class VR num, string n> : PPCReg { + field bits<5> Num = num; +} + +// CR - One of the 8 4-bit condition registers +class CR num, string n, list subregs> : PPCReg { + field bits<3> Num = num; + let SubRegs = subregs; +} + +// CRBIT - One of the 32 1-bit condition register fields +class CRBIT num, string n> : PPCReg { + field bits<5> Num = num; +} + + +// General-purpose registers +def R0 : GPR< 0, "r0">, DwarfRegNum<[0]>; +def R1 : GPR< 1, "r1">, DwarfRegNum<[1]>; +def R2 : GPR< 2, "r2">, DwarfRegNum<[2]>; +def R3 : GPR< 3, "r3">, DwarfRegNum<[3]>; +def R4 : GPR< 4, "r4">, DwarfRegNum<[4]>; +def R5 : GPR< 5, "r5">, DwarfRegNum<[5]>; +def R6 : GPR< 6, "r6">, DwarfRegNum<[6]>; +def R7 : GPR< 7, "r7">, DwarfRegNum<[7]>; +def R8 : GPR< 8, "r8">, DwarfRegNum<[8]>; +def R9 : GPR< 9, "r9">, DwarfRegNum<[9]>; +def R10 : GPR<10, "r10">, DwarfRegNum<[10]>; +def R11 : GPR<11, "r11">, DwarfRegNum<[11]>; +def R12 : GPR<12, "r12">, DwarfRegNum<[12]>; +def R13 : GPR<13, "r13">, DwarfRegNum<[13]>; +def R14 : GPR<14, "r14">, DwarfRegNum<[14]>; +def R15 : GPR<15, "r15">, DwarfRegNum<[15]>; +def R16 : GPR<16, "r16">, DwarfRegNum<[16]>; +def R17 : GPR<17, "r17">, DwarfRegNum<[17]>; +def R18 : GPR<18, "r18">, DwarfRegNum<[18]>; +def R19 : GPR<19, "r19">, DwarfRegNum<[19]>; +def R20 : GPR<20, "r20">, DwarfRegNum<[20]>; +def R21 : GPR<21, "r21">, DwarfRegNum<[21]>; +def R22 : GPR<22, "r22">, DwarfRegNum<[22]>; +def R23 : GPR<23, "r23">, DwarfRegNum<[23]>; +def R24 : GPR<24, "r24">, DwarfRegNum<[24]>; +def R25 : GPR<25, "r25">, DwarfRegNum<[25]>; +def R26 : GPR<26, "r26">, DwarfRegNum<[26]>; +def R27 : GPR<27, "r27">, DwarfRegNum<[27]>; +def R28 : GPR<28, "r28">, DwarfRegNum<[28]>; +def R29 : GPR<29, "r29">, DwarfRegNum<[29]>; +def R30 : GPR<30, "r30">, DwarfRegNum<[30]>; +def R31 : GPR<31, "r31">, DwarfRegNum<[31]>; + +// 64-bit General-purpose registers +def X0 : GP8< R0, "r0">, DwarfRegNum<[0]>; +def X1 : GP8< R1, "r1">, DwarfRegNum<[1]>; +def X2 : GP8< R2, "r2">, DwarfRegNum<[2]>; +def X3 : GP8< R3, "r3">, DwarfRegNum<[3]>; +def X4 : GP8< R4, "r4">, DwarfRegNum<[4]>; +def X5 : GP8< R5, "r5">, DwarfRegNum<[5]>; +def X6 : GP8< R6, "r6">, DwarfRegNum<[6]>; +def X7 : GP8< R7, "r7">, DwarfRegNum<[7]>; +def X8 : GP8< R8, "r8">, DwarfRegNum<[8]>; +def X9 : GP8< R9, "r9">, DwarfRegNum<[9]>; +def X10 : GP8, DwarfRegNum<[10]>; +def X11 : GP8, DwarfRegNum<[11]>; +def X12 : GP8, DwarfRegNum<[12]>; +def X13 : GP8, DwarfRegNum<[13]>; +def X14 : GP8, DwarfRegNum<[14]>; +def X15 : GP8, DwarfRegNum<[15]>; +def X16 : GP8, DwarfRegNum<[16]>; +def X17 : GP8, DwarfRegNum<[17]>; +def X18 : GP8, DwarfRegNum<[18]>; +def X19 : GP8, DwarfRegNum<[19]>; +def X20 : GP8, DwarfRegNum<[20]>; +def X21 : GP8, DwarfRegNum<[21]>; +def X22 : GP8, DwarfRegNum<[22]>; +def X23 : GP8, DwarfRegNum<[23]>; +def X24 : GP8, DwarfRegNum<[24]>; +def X25 : GP8, DwarfRegNum<[25]>; +def X26 : GP8, DwarfRegNum<[26]>; +def X27 : GP8, DwarfRegNum<[27]>; +def X28 : GP8, DwarfRegNum<[28]>; +def X29 : GP8, DwarfRegNum<[29]>; +def X30 : GP8, DwarfRegNum<[30]>; +def X31 : GP8, DwarfRegNum<[31]>; + +// Floating-point registers +def F0 : FPR< 0, "f0">, DwarfRegNum<[32]>; +def F1 : FPR< 1, "f1">, DwarfRegNum<[33]>; +def F2 : FPR< 2, "f2">, DwarfRegNum<[34]>; +def F3 : FPR< 3, "f3">, DwarfRegNum<[35]>; +def F4 : FPR< 4, "f4">, DwarfRegNum<[36]>; +def F5 : FPR< 5, "f5">, DwarfRegNum<[37]>; +def F6 : FPR< 6, "f6">, DwarfRegNum<[38]>; +def F7 : FPR< 7, "f7">, DwarfRegNum<[39]>; +def F8 : FPR< 8, "f8">, DwarfRegNum<[40]>; +def F9 : FPR< 9, "f9">, DwarfRegNum<[41]>; +def F10 : FPR<10, "f10">, DwarfRegNum<[42]>; +def F11 : FPR<11, "f11">, DwarfRegNum<[43]>; +def F12 : FPR<12, "f12">, DwarfRegNum<[44]>; +def F13 : FPR<13, "f13">, DwarfRegNum<[45]>; +def F14 : FPR<14, "f14">, DwarfRegNum<[46]>; +def F15 : FPR<15, "f15">, DwarfRegNum<[47]>; +def F16 : FPR<16, "f16">, DwarfRegNum<[48]>; +def F17 : FPR<17, "f17">, DwarfRegNum<[49]>; +def F18 : FPR<18, "f18">, DwarfRegNum<[50]>; +def F19 : FPR<19, "f19">, DwarfRegNum<[51]>; +def F20 : FPR<20, "f20">, DwarfRegNum<[52]>; +def F21 : FPR<21, "f21">, DwarfRegNum<[53]>; +def F22 : FPR<22, "f22">, DwarfRegNum<[54]>; +def F23 : FPR<23, "f23">, DwarfRegNum<[55]>; +def F24 : FPR<24, "f24">, DwarfRegNum<[56]>; +def F25 : FPR<25, "f25">, DwarfRegNum<[57]>; +def F26 : FPR<26, "f26">, DwarfRegNum<[58]>; +def F27 : FPR<27, "f27">, DwarfRegNum<[59]>; +def F28 : FPR<28, "f28">, DwarfRegNum<[60]>; +def F29 : FPR<29, "f29">, DwarfRegNum<[61]>; +def F30 : FPR<30, "f30">, DwarfRegNum<[62]>; +def F31 : FPR<31, "f31">, DwarfRegNum<[63]>; + +// Vector registers +def V0 : VR< 0, "v0">, DwarfRegNum<[77]>; +def V1 : VR< 1, "v1">, DwarfRegNum<[78]>; +def V2 : VR< 2, "v2">, DwarfRegNum<[79]>; +def V3 : VR< 3, "v3">, DwarfRegNum<[80]>; +def V4 : VR< 4, "v4">, DwarfRegNum<[81]>; +def V5 : VR< 5, "v5">, DwarfRegNum<[82]>; +def V6 : VR< 6, "v6">, DwarfRegNum<[83]>; +def V7 : VR< 7, "v7">, DwarfRegNum<[84]>; +def V8 : VR< 8, "v8">, DwarfRegNum<[85]>; +def V9 : VR< 9, "v9">, DwarfRegNum<[86]>; +def V10 : VR<10, "v10">, DwarfRegNum<[87]>; +def V11 : VR<11, "v11">, DwarfRegNum<[88]>; +def V12 : VR<12, "v12">, DwarfRegNum<[89]>; +def V13 : VR<13, "v13">, DwarfRegNum<[90]>; +def V14 : VR<14, "v14">, DwarfRegNum<[91]>; +def V15 : VR<15, "v15">, DwarfRegNum<[92]>; +def V16 : VR<16, "v16">, DwarfRegNum<[93]>; +def V17 : VR<17, "v17">, DwarfRegNum<[94]>; +def V18 : VR<18, "v18">, DwarfRegNum<[95]>; +def V19 : VR<19, "v19">, DwarfRegNum<[96]>; +def V20 : VR<20, "v20">, DwarfRegNum<[97]>; +def V21 : VR<21, "v21">, DwarfRegNum<[98]>; +def V22 : VR<22, "v22">, DwarfRegNum<[99]>; +def V23 : VR<23, "v23">, DwarfRegNum<[100]>; +def V24 : VR<24, "v24">, DwarfRegNum<[101]>; +def V25 : VR<25, "v25">, DwarfRegNum<[102]>; +def V26 : VR<26, "v26">, DwarfRegNum<[103]>; +def V27 : VR<27, "v27">, DwarfRegNum<[104]>; +def V28 : VR<28, "v28">, DwarfRegNum<[105]>; +def V29 : VR<29, "v29">, DwarfRegNum<[106]>; +def V30 : VR<30, "v30">, DwarfRegNum<[107]>; +def V31 : VR<31, "v31">, DwarfRegNum<[108]>; + +// Condition register bits +def CR0LT : CRBIT< 0, "0">, DwarfRegNum<[0]>; +def CR0GT : CRBIT< 1, "1">, DwarfRegNum<[0]>; +def CR0EQ : CRBIT< 2, "2">, DwarfRegNum<[0]>; +def CR0UN : CRBIT< 3, "3">, DwarfRegNum<[0]>; +def CR1LT : CRBIT< 4, "4">, DwarfRegNum<[0]>; +def CR1GT : CRBIT< 5, "5">, DwarfRegNum<[0]>; +def CR1EQ : CRBIT< 6, "6">, DwarfRegNum<[0]>; +def CR1UN : CRBIT< 7, "7">, DwarfRegNum<[0]>; +def CR2LT : CRBIT< 8, "8">, DwarfRegNum<[0]>; +def CR2GT : CRBIT< 9, "9">, DwarfRegNum<[0]>; +def CR2EQ : CRBIT<10, "10">, DwarfRegNum<[0]>; +def CR2UN : CRBIT<11, "11">, DwarfRegNum<[0]>; +def CR3LT : CRBIT<12, "12">, DwarfRegNum<[0]>; +def CR3GT : CRBIT<13, "13">, DwarfRegNum<[0]>; +def CR3EQ : CRBIT<14, "14">, DwarfRegNum<[0]>; +def CR3UN : CRBIT<15, "15">, DwarfRegNum<[0]>; +def CR4LT : CRBIT<16, "16">, DwarfRegNum<[0]>; +def CR4GT : CRBIT<17, "17">, DwarfRegNum<[0]>; +def CR4EQ : CRBIT<18, "18">, DwarfRegNum<[0]>; +def CR4UN : CRBIT<19, "19">, DwarfRegNum<[0]>; +def CR5LT : CRBIT<20, "20">, DwarfRegNum<[0]>; +def CR5GT : CRBIT<21, "21">, DwarfRegNum<[0]>; +def CR5EQ : CRBIT<22, "22">, DwarfRegNum<[0]>; +def CR5UN : CRBIT<23, "23">, DwarfRegNum<[0]>; +def CR6LT : CRBIT<24, "24">, DwarfRegNum<[0]>; +def CR6GT : CRBIT<25, "25">, DwarfRegNum<[0]>; +def CR6EQ : CRBIT<26, "26">, DwarfRegNum<[0]>; +def CR6UN : CRBIT<27, "27">, DwarfRegNum<[0]>; +def CR7LT : CRBIT<28, "28">, DwarfRegNum<[0]>; +def CR7GT : CRBIT<29, "29">, DwarfRegNum<[0]>; +def CR7EQ : CRBIT<30, "30">, DwarfRegNum<[0]>; +def CR7UN : CRBIT<31, "31">, DwarfRegNum<[0]>; + +// Condition registers +def CR0 : CR<0, "cr0", [CR0LT, CR0GT, CR0EQ, CR0UN]>, DwarfRegNum<[68]>; +def CR1 : CR<1, "cr1", [CR1LT, CR1GT, CR1EQ, CR1UN]>, DwarfRegNum<[69]>; +def CR2 : CR<2, "cr2", [CR2LT, CR2GT, CR2EQ, CR2UN]>, DwarfRegNum<[70]>; +def CR3 : CR<3, "cr3", [CR3LT, CR3GT, CR3EQ, CR3UN]>, DwarfRegNum<[71]>; +def CR4 : CR<4, "cr4", [CR4LT, CR4GT, CR4EQ, CR4UN]>, DwarfRegNum<[72]>; +def CR5 : CR<5, "cr5", [CR5LT, CR5GT, CR5EQ, CR5UN]>, DwarfRegNum<[73]>; +def CR6 : CR<6, "cr6", [CR6LT, CR6GT, CR6EQ, CR6UN]>, DwarfRegNum<[74]>; +def CR7 : CR<7, "cr7", [CR7LT, CR7GT, CR7EQ, CR7UN]>, DwarfRegNum<[75]>; + +def : SubRegSet<1, [CR0, CR1, CR2, CR3, CR4, CR5, CR6, CR7], + [CR0LT, CR1LT, CR2LT, CR3LT, CR4LT, CR5LT, CR6LT, CR7LT]>; +def : SubRegSet<2, [CR0, CR1, CR2, CR3, CR4, CR5, CR6, CR7], + [CR0GT, CR1GT, CR2GT, CR3GT, CR4GT, CR5GT, CR6GT, CR7GT]>; +def : SubRegSet<3, [CR0, CR1, CR2, CR3, CR4, CR5, CR6, CR7], + [CR0EQ, CR1EQ, CR2EQ, CR3EQ, CR4EQ, CR5EQ, CR6EQ, CR7EQ]>; +def : SubRegSet<4, [CR0, CR1, CR2, CR3, CR4, CR5, CR6, CR7], + [CR0UN, CR1UN, CR2UN, CR3UN, CR4UN, CR5UN, CR6UN, CR7UN]>; + +// Link register +def LR : SPR<8, "lr">, DwarfRegNum<[65]>; +//let Aliases = [LR] in +def LR8 : SPR<8, "lr">, DwarfRegNum<[65]>; + +// Count register +def CTR : SPR<9, "ctr">, DwarfRegNum<[66]>; +def CTR8 : SPR<9, "ctr">, DwarfRegNum<[66]>; + +// VRsave register +def VRSAVE: SPR<256, "VRsave">, DwarfRegNum<[107]>; + +// Carry bit. In the architecture this is really bit 0 of the XER register +// (which really is SPR register 1); this is the only bit interesting to a +// compiler. +def CARRY: SPR<1, "ca">, DwarfRegNum<[0]>; + +// FP rounding mode: bits 30 and 31 of the FP status and control register +// This is not allocated as a normal register; it appears only in +// Uses and Defs. The ABI says it needs to be preserved by a function, +// but this is not achieved by saving and restoring it as with +// most registers, it has to be done in code; to make this work all the +// return and call instructions are described as Uses of RM, so instructions +// that do nothing but change RM will not get deleted. +// Also, in the architecture it is not really a SPR; 512 is arbitrary. +def RM: SPR<512, "**ROUNDING MODE**">, DwarfRegNum<[0]>; + +/// Register classes +// Allocate volatiles first +// then nonvolatiles in reverse order since stmw/lmw save from rN to r31 +def GPRC : RegisterClass<"PPC", [i32], 32, + [R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, + R30, R29, R28, R27, R26, R25, R24, R23, R22, R21, R20, R19, R18, R17, + R16, R15, R14, R13, R31, R0, R1, LR]> +{ + let MethodProtos = [{ + iterator allocation_order_begin(const MachineFunction &MF) const; + iterator allocation_order_end(const MachineFunction &MF) const; + }]; + let MethodBodies = [{ + GPRCClass::iterator + GPRCClass::allocation_order_begin(const MachineFunction &MF) const { + // 32-bit SVR4 ABI: r2 is reserved for the OS. + // 64-bit SVR4 ABI: r2 is reserved for the TOC pointer. + if (!MF.getTarget().getSubtarget().isDarwin()) + return begin()+1; + + return begin(); + } + GPRCClass::iterator + GPRCClass::allocation_order_end(const MachineFunction &MF) const { + // On PPC64, r13 is the thread pointer. Never allocate this register. + // Note that this is overconservative, as it also prevents allocation of + // R31 when the FP is not needed. + // When using the 32-bit SVR4 ABI, r13 is reserved for the Small Data Area + // pointer. + const PPCSubtarget &Subtarget + = MF.getTarget().getSubtarget(); + + if (Subtarget.isPPC64() || Subtarget.isSVR4ABI()) + return end()-5; // don't allocate R13, R31, R0, R1, LR + + if (needsFP(MF)) + return end()-4; // don't allocate R31, R0, R1, LR + else + return end()-3; // don't allocate R0, R1, LR + } + }]; +} +def G8RC : RegisterClass<"PPC", [i64], 64, + [X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, + X30, X29, X28, X27, X26, X25, X24, X23, X22, X21, X20, X19, X18, X17, + X16, X15, X14, X31, X13, X0, X1, LR8]> +{ + let MethodProtos = [{ + iterator allocation_order_begin(const MachineFunction &MF) const; + iterator allocation_order_end(const MachineFunction &MF) const; + }]; + let MethodBodies = [{ + G8RCClass::iterator + G8RCClass::allocation_order_begin(const MachineFunction &MF) const { + // 64-bit SVR4 ABI: r2 is reserved for the TOC pointer. + if (!MF.getTarget().getSubtarget().isDarwin()) + return begin()+1; + + return begin(); + } + G8RCClass::iterator + G8RCClass::allocation_order_end(const MachineFunction &MF) const { + if (needsFP(MF)) + return end()-5; + else + return end()-4; + } + }]; +} + +// Allocate volatiles first, then non-volatiles in reverse order. With the SVR4 +// ABI the size of the Floating-point register save area is determined by the +// allocated non-volatile register with the lowest register number, as FP +// register N is spilled to offset 8 * (32 - N) below the back chain word of the +// previous stack frame. By allocating non-volatiles in reverse order we make +// sure that the Floating-point register save area is always as small as +// possible because there aren't any unused spill slots. +def F8RC : RegisterClass<"PPC", [f64], 64, [F0, F1, F2, F3, F4, F5, F6, F7, + F8, F9, F10, F11, F12, F13, F31, F30, F29, F28, F27, F26, F25, F24, F23, + F22, F21, F20, F19, F18, F17, F16, F15, F14]>; +def F4RC : RegisterClass<"PPC", [f32], 32, [F0, F1, F2, F3, F4, F5, F6, F7, + F8, F9, F10, F11, F12, F13, F31, F30, F29, F28, F27, F26, F25, F24, F23, + F22, F21, F20, F19, F18, F17, F16, F15, F14]>; + +def VRRC : RegisterClass<"PPC", [v16i8,v8i16,v4i32,v4f32], 128, + [V2, V3, V4, V5, V0, V1, + V6, V7, V8, V9, V10, V11, V12, V13, V14, V15, V16, V17, V18, V19, V31, V30, + V29, V28, V27, V26, V25, V24, V23, V22, V21, V20]>; + +def CRBITRC : RegisterClass<"PPC", [i32], 32, + [CR0LT, CR0GT, CR0EQ, CR0UN, + CR1LT, CR1GT, CR1EQ, CR1UN, + CR2LT, CR2GT, CR2EQ, CR2UN, + CR3LT, CR3GT, CR3EQ, CR3UN, + CR4LT, CR4GT, CR4EQ, CR4UN, + CR5LT, CR5GT, CR5EQ, CR5UN, + CR6LT, CR6GT, CR6EQ, CR6UN, + CR7LT, CR7GT, CR7EQ, CR7UN + ]> +{ + let CopyCost = -1; +} + +def CRRC : RegisterClass<"PPC", [i32], 32, [CR0, CR1, CR5, CR6, CR7, CR2, + CR3, CR4]> +{ + let SubRegClassList = [CRBITRC, CRBITRC, CRBITRC, CRBITRC]; +} + +def CTRRC : RegisterClass<"PPC", [i32], 32, [CTR]>; +def CTRRC8 : RegisterClass<"PPC", [i64], 64, [CTR8]>; +def VRSAVERC : RegisterClass<"PPC", [i32], 32, [VRSAVE]>; +def CARRYRC : RegisterClass<"PPC", [i32], 32, [CARRY]> { + let CopyCost = -1; +} diff --git a/libclamav/c++/llvm/lib/Target/PowerPC/PPCRelocations.h b/libclamav/c++/llvm/lib/Target/PowerPC/PPCRelocations.h new file mode 100644 index 000000000..a33e7e033 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/PowerPC/PPCRelocations.h @@ -0,0 +1,56 @@ +//===- PPCRelocations.h - PPC32 Code Relocations ----------------*- 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 the PowerPC 32-bit target-specific relocation types. +// +//===----------------------------------------------------------------------===// + +#ifndef PPC32RELOCATIONS_H +#define PPC32RELOCATIONS_H + +#include "llvm/CodeGen/MachineRelocation.h" + +// Hack to rid us of a PPC pre-processor symbol which is erroneously +// defined in a PowerPC header file (bug in Linux/PPC) +#ifdef PPC +#undef PPC +#endif + +namespace llvm { + namespace PPC { + enum RelocationType { + // reloc_vanilla - A standard relocation, where the address of the + // relocated object completely overwrites the address of the relocation. + reloc_vanilla, + + // reloc_pcrel_bx - PC relative relocation, for the b or bl instructions. + reloc_pcrel_bx, + + // reloc_pcrel_bcx - PC relative relocation, for BLT,BLE,BEQ,BGE,BGT,BNE, + // and other bcx instructions. + reloc_pcrel_bcx, + + // reloc_absolute_high - Absolute relocation, for the loadhi instruction + // (which is really addis). Add the high 16-bits of the specified global + // address into the low 16-bits of the instruction. + reloc_absolute_high, + + // reloc_absolute_low - Absolute relocation, for the la instruction (which + // is really an addi). Add the low 16-bits of the specified global + // address into the low 16-bits of the instruction. + reloc_absolute_low, + + // reloc_absolute_low_ix - Absolute relocation for the 64-bit load/store + // instruction which have two implicit zero bits. + reloc_absolute_low_ix + }; + } +} + +#endif diff --git a/libclamav/c++/llvm/lib/Target/PowerPC/PPCSchedule.td b/libclamav/c++/llvm/lib/Target/PowerPC/PPCSchedule.td new file mode 100644 index 000000000..d589414c0 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/PowerPC/PPCSchedule.td @@ -0,0 +1,508 @@ +//===- PPCSchedule.td - PowerPC Scheduling Definitions -----*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// Functional units across PowerPC chips sets +// +def BPU : FuncUnit; // Branch unit +def SLU : FuncUnit; // Store/load unit +def SRU : FuncUnit; // special register unit +def IU1 : FuncUnit; // integer unit 1 (simple) +def IU2 : FuncUnit; // integer unit 2 (complex) +def IU3 : FuncUnit; // integer unit 3 (7450 simple) +def IU4 : FuncUnit; // integer unit 4 (7450 simple) +def FPU1 : FuncUnit; // floating point unit 1 +def FPU2 : FuncUnit; // floating point unit 2 +def VPU : FuncUnit; // vector permutation unit +def VIU1 : FuncUnit; // vector integer unit 1 (simple) +def VIU2 : FuncUnit; // vector integer unit 2 (complex) +def VFPU : FuncUnit; // vector floating point unit + + +//===----------------------------------------------------------------------===// +// Instruction Itinerary classes used for PowerPC +// +def IntGeneral : InstrItinClass; +def IntCompare : InstrItinClass; +def IntDivD : InstrItinClass; +def IntDivW : InstrItinClass; +def IntMFFS : InstrItinClass; +def IntMFVSCR : InstrItinClass; +def IntMTFSB0 : InstrItinClass; +def IntMTSRD : InstrItinClass; +def IntMulHD : InstrItinClass; +def IntMulHW : InstrItinClass; +def IntMulHWU : InstrItinClass; +def IntMulLI : InstrItinClass; +def IntRFID : InstrItinClass; +def IntRotateD : InstrItinClass; +def IntRotate : InstrItinClass; +def IntShift : InstrItinClass; +def IntTrapD : InstrItinClass; +def IntTrapW : InstrItinClass; +def BrB : InstrItinClass; +def BrCR : InstrItinClass; +def BrMCR : InstrItinClass; +def BrMCRX : InstrItinClass; +def LdStDCBA : InstrItinClass; +def LdStDCBF : InstrItinClass; +def LdStDCBI : InstrItinClass; +def LdStGeneral : InstrItinClass; +def LdStDSS : InstrItinClass; +def LdStICBI : InstrItinClass; +def LdStUX : InstrItinClass; +def LdStLD : InstrItinClass; +def LdStLDARX : InstrItinClass; +def LdStLFD : InstrItinClass; +def LdStLFDU : InstrItinClass; +def LdStLHA : InstrItinClass; +def LdStLMW : InstrItinClass; +def LdStLVecX : InstrItinClass; +def LdStLWA : InstrItinClass; +def LdStLWARX : InstrItinClass; +def LdStSLBIA : InstrItinClass; +def LdStSLBIE : InstrItinClass; +def LdStSTD : InstrItinClass; +def LdStSTDCX : InstrItinClass; +def LdStSTVEBX : InstrItinClass; +def LdStSTWCX : InstrItinClass; +def LdStSync : InstrItinClass; +def SprISYNC : InstrItinClass; +def SprMFSR : InstrItinClass; +def SprMTMSR : InstrItinClass; +def SprMTSR : InstrItinClass; +def SprTLBSYNC : InstrItinClass; +def SprMFCR : InstrItinClass; +def SprMFMSR : InstrItinClass; +def SprMFSPR : InstrItinClass; +def SprMFTB : InstrItinClass; +def SprMTSPR : InstrItinClass; +def SprMTSRIN : InstrItinClass; +def SprRFI : InstrItinClass; +def SprSC : InstrItinClass; +def FPGeneral : InstrItinClass; +def FPCompare : InstrItinClass; +def FPDivD : InstrItinClass; +def FPDivS : InstrItinClass; +def FPFused : InstrItinClass; +def FPRes : InstrItinClass; +def FPSqrt : InstrItinClass; +def VecGeneral : InstrItinClass; +def VecFP : InstrItinClass; +def VecFPCompare : InstrItinClass; +def VecComplex : InstrItinClass; +def VecPerm : InstrItinClass; +def VecFPRound : InstrItinClass; +def VecVSL : InstrItinClass; +def VecVSR : InstrItinClass; + +//===----------------------------------------------------------------------===// +// Processor instruction itineraries. + +include "PPCScheduleG3.td" +include "PPCScheduleG4.td" +include "PPCScheduleG4Plus.td" +include "PPCScheduleG5.td" + +//===----------------------------------------------------------------------===// +// Instruction to itinerary class map - When add new opcodes to the supported +// set, refer to the following table to determine which itinerary class the +// opcode belongs. +// +// opcode itinerary class +// ====== =============== +// add IntGeneral +// addc IntGeneral +// adde IntGeneral +// addi IntGeneral +// addic IntGeneral +// addic. IntGeneral +// addis IntGeneral +// addme IntGeneral +// addze IntGeneral +// and IntGeneral +// andc IntGeneral +// andi. IntGeneral +// andis. IntGeneral +// b BrB +// bc BrB +// bcctr BrB +// bclr BrB +// cmp IntCompare +// cmpi IntCompare +// cmpl IntCompare +// cmpli IntCompare +// cntlzd IntRotateD +// cntlzw IntGeneral +// crand BrCR +// crandc BrCR +// creqv BrCR +// crnand BrCR +// crnor BrCR +// cror BrCR +// crorc BrCR +// crxor BrCR +// dcba LdStDCBA +// dcbf LdStDCBF +// dcbi LdStDCBI +// dcbst LdStDCBF +// dcbt LdStGeneral +// dcbtst LdStGeneral +// dcbz LdStDCBF +// divd IntDivD +// divdu IntDivD +// divw IntDivW +// divwu IntDivW +// dss LdStDSS +// dst LdStDSS +// dstst LdStDSS +// eciwx LdStGeneral +// ecowx LdStGeneral +// eieio LdStGeneral +// eqv IntGeneral +// extsb IntGeneral +// extsh IntGeneral +// extsw IntRotateD +// fabs FPGeneral +// fadd FPGeneral +// fadds FPGeneral +// fcfid FPGeneral +// fcmpo FPCompare +// fcmpu FPCompare +// fctid FPGeneral +// fctidz FPGeneral +// fctiw FPGeneral +// fctiwz FPGeneral +// fdiv FPDivD +// fdivs FPDivS +// fmadd FPFused +// fmadds FPGeneral +// fmr FPGeneral +// fmsub FPFused +// fmsubs FPGeneral +// fmul FPFused +// fmuls FPGeneral +// fnabs FPGeneral +// fneg FPGeneral +// fnmadd FPFused +// fnmadds FPGeneral +// fnmsub FPFused +// fnmsubs FPGeneral +// fres FPRes +// frsp FPGeneral +// frsqrte FPGeneral +// fsel FPGeneral +// fsqrt FPSqrt +// fsqrts FPSqrt +// fsub FPGeneral +// fsubs FPGeneral +// icbi LdStICBI +// isync SprISYNC +// lbz LdStGeneral +// lbzu LdStGeneral +// lbzux LdStUX +// lbzx LdStGeneral +// ld LdStLD +// ldarx LdStLDARX +// ldu LdStLD +// ldux LdStLD +// ldx LdStLD +// lfd LdStLFD +// lfdu LdStLFDU +// lfdux LdStLFDU +// lfdx LdStLFDU +// lfs LdStLFDU +// lfsu LdStLFDU +// lfsux LdStLFDU +// lfsx LdStLFDU +// lha LdStLHA +// lhau LdStLHA +// lhaux LdStLHA +// lhax LdStLHA +// lhbrx LdStGeneral +// lhz LdStGeneral +// lhzu LdStGeneral +// lhzux LdStUX +// lhzx LdStGeneral +// lmw LdStLMW +// lswi LdStLMW +// lswx LdStLMW +// lvebx LdStLVecX +// lvehx LdStLVecX +// lvewx LdStLVecX +// lvsl LdStLVecX +// lvsr LdStLVecX +// lvx LdStLVecX +// lvxl LdStLVecX +// lwa LdStLWA +// lwarx LdStLWARX +// lwaux LdStLHA +// lwax LdStLHA +// lwbrx LdStGeneral +// lwz LdStGeneral +// lwzu LdStGeneral +// lwzux LdStUX +// lwzx LdStGeneral +// mcrf BrMCR +// mcrfs FPGeneral +// mcrxr BrMCRX +// mfcr SprMFCR +// mffs IntMFFS +// mfmsr SprMFMSR +// mfspr SprMFSPR +// mfsr SprMFSR +// mfsrin SprMFSR +// mftb SprMFTB +// mfvscr IntMFVSCR +// mtcrf BrMCRX +// mtfsb0 IntMTFSB0 +// mtfsb1 IntMTFSB0 +// mtfsf IntMTFSB0 +// mtfsfi IntMTFSB0 +// mtmsr SprMTMSR +// mtmsrd LdStLD +// mtspr SprMTSPR +// mtsr SprMTSR +// mtsrd IntMTSRD +// mtsrdin IntMTSRD +// mtsrin SprMTSRIN +// mtvscr IntMFVSCR +// mulhd IntMulHD +// mulhdu IntMulHD +// mulhw IntMulHW +// mulhwu IntMulHWU +// mulld IntMulHD +// mulli IntMulLI +// mullw IntMulHW +// nand IntGeneral +// neg IntGeneral +// nor IntGeneral +// or IntGeneral +// orc IntGeneral +// ori IntGeneral +// oris IntGeneral +// rfi SprRFI +// rfid IntRFID +// rldcl IntRotateD +// rldcr IntRotateD +// rldic IntRotateD +// rldicl IntRotateD +// rldicr IntRotateD +// rldimi IntRotateD +// rlwimi IntRotate +// rlwinm IntGeneral +// rlwnm IntGeneral +// sc SprSC +// slbia LdStSLBIA +// slbie LdStSLBIE +// sld IntRotateD +// slw IntGeneral +// srad IntRotateD +// sradi IntRotateD +// sraw IntShift +// srawi IntShift +// srd IntRotateD +// srw IntGeneral +// stb LdStGeneral +// stbu LdStGeneral +// stbux LdStGeneral +// stbx LdStGeneral +// std LdStSTD +// stdcx. LdStSTDCX +// stdu LdStSTD +// stdux LdStSTD +// stdx LdStSTD +// stfd LdStUX +// stfdu LdStUX +// stfdux LdStUX +// stfdx LdStUX +// stfiwx LdStUX +// stfs LdStUX +// stfsu LdStUX +// stfsux LdStUX +// stfsx LdStUX +// sth LdStGeneral +// sthbrx LdStGeneral +// sthu LdStGeneral +// sthux LdStGeneral +// sthx LdStGeneral +// stmw LdStLMW +// stswi LdStLMW +// stswx LdStLMW +// stvebx LdStSTVEBX +// stvehx LdStSTVEBX +// stvewx LdStSTVEBX +// stvx LdStSTVEBX +// stvxl LdStSTVEBX +// stw LdStGeneral +// stwbrx LdStGeneral +// stwcx. LdStSTWCX +// stwu LdStGeneral +// stwux LdStGeneral +// stwx LdStGeneral +// subf IntGeneral +// subfc IntGeneral +// subfe IntGeneral +// subfic IntGeneral +// subfme IntGeneral +// subfze IntGeneral +// sync LdStSync +// td IntTrapD +// tdi IntTrapD +// tlbia LdStSLBIA +// tlbie LdStDCBF +// tlbsync SprTLBSYNC +// tw IntTrapW +// twi IntTrapW +// vaddcuw VecGeneral +// vaddfp VecFP +// vaddsbs VecGeneral +// vaddshs VecGeneral +// vaddsws VecGeneral +// vaddubm VecGeneral +// vaddubs VecGeneral +// vadduhm VecGeneral +// vadduhs VecGeneral +// vadduwm VecGeneral +// vadduws VecGeneral +// vand VecGeneral +// vandc VecGeneral +// vavgsb VecGeneral +// vavgsh VecGeneral +// vavgsw VecGeneral +// vavgub VecGeneral +// vavguh VecGeneral +// vavguw VecGeneral +// vcfsx VecFP +// vcfux VecFP +// vcmpbfp VecFPCompare +// vcmpeqfp VecFPCompare +// vcmpequb VecGeneral +// vcmpequh VecGeneral +// vcmpequw VecGeneral +// vcmpgefp VecFPCompare +// vcmpgtfp VecFPCompare +// vcmpgtsb VecGeneral +// vcmpgtsh VecGeneral +// vcmpgtsw VecGeneral +// vcmpgtub VecGeneral +// vcmpgtuh VecGeneral +// vcmpgtuw VecGeneral +// vctsxs VecFP +// vctuxs VecFP +// vexptefp VecFP +// vlogefp VecFP +// vmaddfp VecFP +// vmaxfp VecFPCompare +// vmaxsb VecGeneral +// vmaxsh VecGeneral +// vmaxsw VecGeneral +// vmaxub VecGeneral +// vmaxuh VecGeneral +// vmaxuw VecGeneral +// vmhaddshs VecComplex +// vmhraddshs VecComplex +// vminfp VecFPCompare +// vminsb VecGeneral +// vminsh VecGeneral +// vminsw VecGeneral +// vminub VecGeneral +// vminuh VecGeneral +// vminuw VecGeneral +// vmladduhm VecComplex +// vmrghb VecPerm +// vmrghh VecPerm +// vmrghw VecPerm +// vmrglb VecPerm +// vmrglh VecPerm +// vmrglw VecPerm +// vmsubfp VecFP +// vmsummbm VecComplex +// vmsumshm VecComplex +// vmsumshs VecComplex +// vmsumubm VecComplex +// vmsumuhm VecComplex +// vmsumuhs VecComplex +// vmulesb VecComplex +// vmulesh VecComplex +// vmuleub VecComplex +// vmuleuh VecComplex +// vmulosb VecComplex +// vmulosh VecComplex +// vmuloub VecComplex +// vmulouh VecComplex +// vnor VecGeneral +// vor VecGeneral +// vperm VecPerm +// vpkpx VecPerm +// vpkshss VecPerm +// vpkshus VecPerm +// vpkswss VecPerm +// vpkswus VecPerm +// vpkuhum VecPerm +// vpkuhus VecPerm +// vpkuwum VecPerm +// vpkuwus VecPerm +// vrefp VecFPRound +// vrfim VecFPRound +// vrfin VecFPRound +// vrfip VecFPRound +// vrfiz VecFPRound +// vrlb VecGeneral +// vrlh VecGeneral +// vrlw VecGeneral +// vrsqrtefp VecFP +// vsel VecGeneral +// vsl VecVSL +// vslb VecGeneral +// vsldoi VecPerm +// vslh VecGeneral +// vslo VecPerm +// vslw VecGeneral +// vspltb VecPerm +// vsplth VecPerm +// vspltisb VecPerm +// vspltish VecPerm +// vspltisw VecPerm +// vspltw VecPerm +// vsr VecVSR +// vsrab VecGeneral +// vsrah VecGeneral +// vsraw VecGeneral +// vsrb VecGeneral +// vsrh VecGeneral +// vsro VecPerm +// vsrw VecGeneral +// vsubcuw VecGeneral +// vsubfp VecFP +// vsubsbs VecGeneral +// vsubshs VecGeneral +// vsubsws VecGeneral +// vsububm VecGeneral +// vsububs VecGeneral +// vsubuhm VecGeneral +// vsubuhs VecGeneral +// vsubuwm VecGeneral +// vsubuws VecGeneral +// vsum2sws VecComplex +// vsum4sbs VecComplex +// vsum4shs VecComplex +// vsum4ubs VecComplex +// vsumsws VecComplex +// vupkhpx VecPerm +// vupkhsb VecPerm +// vupkhsh VecPerm +// vupklpx VecPerm +// vupklsb VecPerm +// vupklsh VecPerm +// vxor VecGeneral +// xor IntGeneral +// xori IntGeneral +// xoris IntGeneral +// diff --git a/libclamav/c++/llvm/lib/Target/PowerPC/PPCScheduleG3.td b/libclamav/c++/llvm/lib/Target/PowerPC/PPCScheduleG3.td new file mode 100644 index 000000000..f72194d6d --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/PowerPC/PPCScheduleG3.td @@ -0,0 +1,63 @@ +//===- PPCScheduleG3.td - PPC G3 Scheduling Definitions ----*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the itinerary class data for the G3 (750) processor. +// +//===----------------------------------------------------------------------===// + + +def G3Itineraries : ProcessorItineraries<[ + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]> +]>; diff --git a/libclamav/c++/llvm/lib/Target/PowerPC/PPCScheduleG4.td b/libclamav/c++/llvm/lib/Target/PowerPC/PPCScheduleG4.td new file mode 100644 index 000000000..92ed20f17 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/PowerPC/PPCScheduleG4.td @@ -0,0 +1,73 @@ +//===- PPCScheduleG4.td - PPC G4 Scheduling Definitions ----*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the itinerary class data for the G4 (7400) processor. +// +//===----------------------------------------------------------------------===// + +def G4Itineraries : ProcessorItineraries<[ + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]> +]>; diff --git a/libclamav/c++/llvm/lib/Target/PowerPC/PPCScheduleG4Plus.td b/libclamav/c++/llvm/lib/Target/PowerPC/PPCScheduleG4Plus.td new file mode 100644 index 000000000..7474ba494 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/PowerPC/PPCScheduleG4Plus.td @@ -0,0 +1,76 @@ +//===- PPCScheduleG4Plus.td - PPC G4+ Scheduling Defs. -----*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the itinerary class data for the G4+ (7450) processor. +// +//===----------------------------------------------------------------------===// + +def G4PlusItineraries : ProcessorItineraries<[ + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]> +]>; diff --git a/libclamav/c++/llvm/lib/Target/PowerPC/PPCScheduleG5.td b/libclamav/c++/llvm/lib/Target/PowerPC/PPCScheduleG5.td new file mode 100644 index 000000000..d28214715 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/PowerPC/PPCScheduleG5.td @@ -0,0 +1,83 @@ +//===- PPCScheduleG5.td - PPC G5 Scheduling Definitions ----*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the itinerary class data for the G5 (970) processor. +// +//===----------------------------------------------------------------------===// + +def G5Itineraries : ProcessorItineraries<[ + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, // needs work + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, // needs work + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]> +]>; diff --git a/libclamav/c++/llvm/lib/Target/PowerPC/PPCSubtarget.cpp b/libclamav/c++/llvm/lib/Target/PowerPC/PPCSubtarget.cpp new file mode 100644 index 000000000..f75e78145 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/PowerPC/PPCSubtarget.cpp @@ -0,0 +1,138 @@ +//===- PowerPCSubtarget.cpp - PPC Subtarget Information -------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the PPC specific subclass of TargetSubtarget. +// +//===----------------------------------------------------------------------===// + +#include "PPCSubtarget.h" +#include "PPC.h" +#include "llvm/GlobalValue.h" +#include "llvm/Target/TargetMachine.h" +#include "PPCGenSubtarget.inc" +#include +using namespace llvm; + +#if defined(__APPLE__) +#include +#include +#include +#include + +/// GetCurrentPowerPCFeatures - Returns the current CPUs features. +static const char *GetCurrentPowerPCCPU() { + host_basic_info_data_t hostInfo; + mach_msg_type_number_t infoCount; + + infoCount = HOST_BASIC_INFO_COUNT; + host_info(mach_host_self(), HOST_BASIC_INFO, (host_info_t)&hostInfo, + &infoCount); + + if (hostInfo.cpu_type != CPU_TYPE_POWERPC) return "generic"; + + switch(hostInfo.cpu_subtype) { + case CPU_SUBTYPE_POWERPC_601: return "601"; + case CPU_SUBTYPE_POWERPC_602: return "602"; + case CPU_SUBTYPE_POWERPC_603: return "603"; + case CPU_SUBTYPE_POWERPC_603e: return "603e"; + case CPU_SUBTYPE_POWERPC_603ev: return "603ev"; + case CPU_SUBTYPE_POWERPC_604: return "604"; + case CPU_SUBTYPE_POWERPC_604e: return "604e"; + case CPU_SUBTYPE_POWERPC_620: return "620"; + case CPU_SUBTYPE_POWERPC_750: return "750"; + case CPU_SUBTYPE_POWERPC_7400: return "7400"; + case CPU_SUBTYPE_POWERPC_7450: return "7450"; + case CPU_SUBTYPE_POWERPC_970: return "970"; + default: ; + } + + return "generic"; +} +#endif + + +PPCSubtarget::PPCSubtarget(const std::string &TT, const std::string &FS, + bool is64Bit) + : StackAlignment(16) + , DarwinDirective(PPC::DIR_NONE) + , IsGigaProcessor(false) + , Has64BitSupport(false) + , Use64BitRegs(false) + , IsPPC64(is64Bit) + , HasAltivec(false) + , HasFSQRT(false) + , HasSTFIWX(false) + , HasLazyResolverStubs(false) + , DarwinVers(0) { + + // Determine default and user specified characteristics + std::string CPU = "generic"; +#if defined(__APPLE__) + CPU = GetCurrentPowerPCCPU(); +#endif + + // Parse features string. + ParseSubtargetFeatures(FS, CPU); + + // If we are generating code for ppc64, verify that options make sense. + if (is64Bit) { + Has64BitSupport = true; + // Silently force 64-bit register use on ppc64. + Use64BitRegs = true; + } + + // If the user requested use of 64-bit regs, but the cpu selected doesn't + // support it, ignore. + if (use64BitRegs() && !has64BitSupport()) + Use64BitRegs = false; + + // Set the boolean corresponding to the current target triple, or the default + // if one cannot be determined, to true. + if (TT.length() > 7) { + // Determine which version of darwin this is. + size_t DarwinPos = TT.find("-darwin"); + if (DarwinPos != std::string::npos) { + if (isdigit(TT[DarwinPos+7])) + DarwinVers = atoi(&TT[DarwinPos+7]); + else + DarwinVers = 8; // Minimum supported darwin is Tiger. + } + } + + // Set up darwin-specific properties. + if (isDarwin()) + HasLazyResolverStubs = true; +} + +/// SetJITMode - This is called to inform the subtarget info that we are +/// producing code for the JIT. +void PPCSubtarget::SetJITMode() { + // JIT mode doesn't want lazy resolver stubs, it knows exactly where + // everything is. This matters for PPC64, which codegens in PIC mode without + // stubs. + HasLazyResolverStubs = false; +} + + +/// hasLazyResolverStub - Return true if accesses to the specified global have +/// to go through a dyld lazy resolution stub. This means that an extra load +/// is required to get the address of the global. +bool PPCSubtarget::hasLazyResolverStub(const GlobalValue *GV, + const TargetMachine &TM) const { + // We never hae stubs if HasLazyResolverStubs=false or if in static mode. + if (!HasLazyResolverStubs || TM.getRelocationModel() == Reloc::Static) + return false; + // If symbol visibility is hidden, the extra load is not needed if + // the symbol is definitely defined in the current translation unit. + bool isDecl = GV->isDeclaration() && !GV->hasNotBeenReadFromBitcode(); + if (GV->hasHiddenVisibility() && !isDecl && !GV->hasCommonLinkage()) + return false; + return GV->hasWeakLinkage() || GV->hasLinkOnceLinkage() || + GV->hasCommonLinkage() || isDecl; +} diff --git a/libclamav/c++/llvm/lib/Target/PowerPC/PPCSubtarget.h b/libclamav/c++/llvm/lib/Target/PowerPC/PPCSubtarget.h new file mode 100644 index 000000000..75fcf6238 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/PowerPC/PPCSubtarget.h @@ -0,0 +1,147 @@ +//=====-- PPCSubtarget.h - Define Subtarget for the PPC -------*- C++ -*--====// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the PowerPC specific subclass of TargetSubtarget. +// +//===----------------------------------------------------------------------===// + +#ifndef POWERPCSUBTARGET_H +#define POWERPCSUBTARGET_H + +#include "llvm/Target/TargetInstrItineraries.h" +#include "llvm/Target/TargetSubtarget.h" + +#include + +// GCC #defines PPC on Linux but we use it as our namespace name +#undef PPC + +namespace llvm { + +namespace PPC { + // -m directive values. + enum { + DIR_NONE, + DIR_32, + DIR_601, + DIR_602, + DIR_603, + DIR_7400, + DIR_750, + DIR_970, + DIR_64 + }; +} + +class GlobalValue; +class TargetMachine; + +class PPCSubtarget : public TargetSubtarget { +protected: + /// stackAlignment - The minimum alignment known to hold of the stack frame on + /// entry to the function and which must be maintained by every function. + unsigned StackAlignment; + + /// Selected instruction itineraries (one entry per itinerary class.) + InstrItineraryData InstrItins; + + /// Which cpu directive was used. + unsigned DarwinDirective; + + /// Used by the ISel to turn in optimizations for POWER4-derived architectures + bool IsGigaProcessor; + bool Has64BitSupport; + bool Use64BitRegs; + bool IsPPC64; + bool HasAltivec; + bool HasFSQRT; + bool HasSTFIWX; + bool HasLazyResolverStubs; + + /// DarwinVers - Nonzero if this is a darwin platform. Otherwise, the numeric + /// version of the platform, e.g. 8 = 10.4 (Tiger), 9 = 10.5 (Leopard), etc. + unsigned char DarwinVers; // Is any darwin-ppc platform. +public: + /// This constructor initializes the data members to match that + /// of the specified triple. + /// + PPCSubtarget(const std::string &TT, const std::string &FS, bool is64Bit); + + /// ParseSubtargetFeatures - Parses features string setting specified + /// subtarget options. Definition of function is auto generated by tblgen. + std::string ParseSubtargetFeatures(const std::string &FS, + const std::string &CPU); + + + /// SetJITMode - This is called to inform the subtarget info that we are + /// producing code for the JIT. + void SetJITMode(); + + /// getStackAlignment - Returns the minimum alignment known to hold of the + /// stack frame on entry to the function and which must be maintained by every + /// function for this subtarget. + unsigned getStackAlignment() const { return StackAlignment; } + + /// getDarwinDirective - Returns the -m directive specified for the cpu. + /// + unsigned getDarwinDirective() const { return DarwinDirective; } + + /// getInstrItins - Return the instruction itineraies based on subtarget + /// selection. + const InstrItineraryData &getInstrItineraryData() const { return InstrItins; } + + /// getTargetDataString - Return the pointer size and type alignment + /// properties of this subtarget. + const char *getTargetDataString() const { + // Note, the alignment values for f64 and i64 on ppc64 in Darwin + // documentation are wrong; these are correct (i.e. "what gcc does"). + return isPPC64() ? "E-p:64:64-f64:64:64-i64:64:64-f128:64:128-n32:64" + : "E-p:32:32-f64:32:64-i64:32:64-f128:64:128-n32"; + } + + /// isPPC64 - Return true if we are generating code for 64-bit pointer mode. + /// + bool isPPC64() const { return IsPPC64; } + + /// has64BitSupport - Return true if the selected CPU supports 64-bit + /// instructions, regardless of whether we are in 32-bit or 64-bit mode. + bool has64BitSupport() const { return Has64BitSupport; } + + /// use64BitRegs - Return true if in 64-bit mode or if we should use 64-bit + /// registers in 32-bit mode when possible. This can only true if + /// has64BitSupport() returns true. + bool use64BitRegs() const { return Use64BitRegs; } + + /// hasLazyResolverStub - Return true if accesses to the specified global have + /// to go through a dyld lazy resolution stub. This means that an extra load + /// is required to get the address of the global. + bool hasLazyResolverStub(const GlobalValue *GV, + const TargetMachine &TM) const; + + // Specific obvious features. + bool hasFSQRT() const { return HasFSQRT; } + bool hasSTFIWX() const { return HasSTFIWX; } + bool hasAltivec() const { return HasAltivec; } + bool isGigaProcessor() const { return IsGigaProcessor; } + + /// isDarwin - True if this is any darwin platform. + bool isDarwin() const { return DarwinVers != 0; } + /// isDarwin - True if this is darwin9 (leopard, 10.5) or above. + bool isDarwin9() const { return DarwinVers >= 9; } + + /// getDarwinVers - Return the darwin version number, 8 = tiger, 9 = leopard. + unsigned getDarwinVers() const { return DarwinVers; } + + bool isDarwinABI() const { return isDarwin(); } + bool isSVR4ABI() const { return !isDarwin(); } + +}; +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/lib/Target/PowerPC/PPCTargetMachine.cpp b/libclamav/c++/llvm/lib/Target/PowerPC/PPCTargetMachine.cpp new file mode 100644 index 000000000..8079c6e9c --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/PowerPC/PPCTargetMachine.cpp @@ -0,0 +1,197 @@ +//===-- PPCTargetMachine.cpp - Define TargetMachine for PowerPC -----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Top-level implementation for the PowerPC target. +// +//===----------------------------------------------------------------------===// + +#include "PPC.h" +#include "PPCMCAsmInfo.h" +#include "PPCTargetMachine.h" +#include "llvm/PassManager.h" +#include "llvm/Target/TargetOptions.h" +#include "llvm/Target/TargetRegistry.h" +#include "llvm/Support/FormattedStream.h" +using namespace llvm; + +static const MCAsmInfo *createMCAsmInfo(const Target &T, StringRef TT) { + Triple TheTriple(TT); + bool isPPC64 = TheTriple.getArch() == Triple::ppc64; + if (TheTriple.getOS() == Triple::Darwin) + return new PPCMCAsmInfoDarwin(isPPC64); + return new PPCLinuxMCAsmInfo(isPPC64); + +} + +extern "C" void LLVMInitializePowerPCTarget() { + // Register the targets + RegisterTargetMachine A(ThePPC32Target); + RegisterTargetMachine B(ThePPC64Target); + + RegisterAsmInfoFn C(ThePPC32Target, createMCAsmInfo); + RegisterAsmInfoFn D(ThePPC64Target, createMCAsmInfo); +} + + +PPCTargetMachine::PPCTargetMachine(const Target &T, const std::string &TT, + const std::string &FS, bool is64Bit) + : LLVMTargetMachine(T, TT), + Subtarget(TT, FS, is64Bit), + DataLayout(Subtarget.getTargetDataString()), InstrInfo(*this), + FrameInfo(*this, is64Bit), JITInfo(*this, is64Bit), TLInfo(*this), + InstrItins(Subtarget.getInstrItineraryData()), MachOWriterInfo(*this) { + + if (getRelocationModel() == Reloc::Default) { + if (Subtarget.isDarwin()) + setRelocationModel(Reloc::DynamicNoPIC); + else + setRelocationModel(Reloc::Static); + } +} + +/// Override this for PowerPC. Tail merging happily breaks up instruction issue +/// groups, which typically degrades performance. +bool PPCTargetMachine::getEnableTailMergeDefault() const { return false; } + +PPC32TargetMachine::PPC32TargetMachine(const Target &T, const std::string &TT, + const std::string &FS) + : PPCTargetMachine(T, TT, FS, false) { +} + + +PPC64TargetMachine::PPC64TargetMachine(const Target &T, const std::string &TT, + const std::string &FS) + : PPCTargetMachine(T, TT, FS, true) { +} + + +//===----------------------------------------------------------------------===// +// Pass Pipeline Configuration +//===----------------------------------------------------------------------===// + +bool PPCTargetMachine::addInstSelector(PassManagerBase &PM, + CodeGenOpt::Level OptLevel) { + // Install an instruction selector. + PM.add(createPPCISelDag(*this)); + return false; +} + +bool PPCTargetMachine::addPreEmitPass(PassManagerBase &PM, + CodeGenOpt::Level OptLevel) { + // Must run branch selection immediately preceding the asm printer. + PM.add(createPPCBranchSelectionPass()); + return false; +} + +bool PPCTargetMachine::addCodeEmitter(PassManagerBase &PM, + CodeGenOpt::Level OptLevel, + MachineCodeEmitter &MCE) { + // The JIT should use the static relocation model in ppc32 mode, PIC in ppc64. + // FIXME: This should be moved to TargetJITInfo!! + if (Subtarget.isPPC64()) { + // We use PIC codegen in ppc64 mode, because otherwise we'd have to use many + // instructions to materialize arbitrary global variable + function + + // constant pool addresses. + setRelocationModel(Reloc::PIC_); + // Temporary workaround for the inability of PPC64 JIT to handle jump + // tables. + DisableJumpTables = true; + } else { + setRelocationModel(Reloc::Static); + } + + // Inform the subtarget that we are in JIT mode. FIXME: does this break macho + // writing? + Subtarget.SetJITMode(); + + // Machine code emitter pass for PowerPC. + PM.add(createPPCCodeEmitterPass(*this, MCE)); + + return false; +} + +bool PPCTargetMachine::addCodeEmitter(PassManagerBase &PM, + CodeGenOpt::Level OptLevel, + JITCodeEmitter &JCE) { + // The JIT should use the static relocation model in ppc32 mode, PIC in ppc64. + // FIXME: This should be moved to TargetJITInfo!! + if (Subtarget.isPPC64()) { + // We use PIC codegen in ppc64 mode, because otherwise we'd have to use many + // instructions to materialize arbitrary global variable + function + + // constant pool addresses. + setRelocationModel(Reloc::PIC_); + // Temporary workaround for the inability of PPC64 JIT to handle jump + // tables. + DisableJumpTables = true; + } else { + setRelocationModel(Reloc::Static); + } + + // Inform the subtarget that we are in JIT mode. FIXME: does this break macho + // writing? + Subtarget.SetJITMode(); + + // Machine code emitter pass for PowerPC. + PM.add(createPPCJITCodeEmitterPass(*this, JCE)); + + return false; +} + +bool PPCTargetMachine::addCodeEmitter(PassManagerBase &PM, + CodeGenOpt::Level OptLevel, + ObjectCodeEmitter &OCE) { + // The JIT should use the static relocation model in ppc32 mode, PIC in ppc64. + // FIXME: This should be moved to TargetJITInfo!! + if (Subtarget.isPPC64()) { + // We use PIC codegen in ppc64 mode, because otherwise we'd have to use many + // instructions to materialize arbitrary global variable + function + + // constant pool addresses. + setRelocationModel(Reloc::PIC_); + // Temporary workaround for the inability of PPC64 JIT to handle jump + // tables. + DisableJumpTables = true; + } else { + setRelocationModel(Reloc::Static); + } + + // Inform the subtarget that we are in JIT mode. FIXME: does this break macho + // writing? + Subtarget.SetJITMode(); + + // Machine code emitter pass for PowerPC. + PM.add(createPPCObjectCodeEmitterPass(*this, OCE)); + + return false; +} + +bool PPCTargetMachine::addSimpleCodeEmitter(PassManagerBase &PM, + CodeGenOpt::Level OptLevel, + MachineCodeEmitter &MCE) { + // Machine code emitter pass for PowerPC. + PM.add(createPPCCodeEmitterPass(*this, MCE)); + return false; +} + +bool PPCTargetMachine::addSimpleCodeEmitter(PassManagerBase &PM, + CodeGenOpt::Level OptLevel, + JITCodeEmitter &JCE) { + // Machine code emitter pass for PowerPC. + PM.add(createPPCJITCodeEmitterPass(*this, JCE)); + return false; +} + +bool PPCTargetMachine::addSimpleCodeEmitter(PassManagerBase &PM, + CodeGenOpt::Level OptLevel, + ObjectCodeEmitter &OCE) { + // Machine code emitter pass for PowerPC. + PM.add(createPPCObjectCodeEmitterPass(*this, OCE)); + return false; +} + + diff --git a/libclamav/c++/llvm/lib/Target/PowerPC/PPCTargetMachine.h b/libclamav/c++/llvm/lib/Target/PowerPC/PPCTargetMachine.h new file mode 100644 index 000000000..3399ac891 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/PowerPC/PPCTargetMachine.h @@ -0,0 +1,104 @@ +//===-- PPCTargetMachine.h - Define TargetMachine for PowerPC -----*- C++ -*-=// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the PowerPC specific subclass of TargetMachine. +// +//===----------------------------------------------------------------------===// + +#ifndef PPC_TARGETMACHINE_H +#define PPC_TARGETMACHINE_H + +#include "PPCFrameInfo.h" +#include "PPCSubtarget.h" +#include "PPCJITInfo.h" +#include "PPCInstrInfo.h" +#include "PPCISelLowering.h" +#include "PPCMachOWriterInfo.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetData.h" + +namespace llvm { +class PassManager; +class GlobalValue; + +/// PPCTargetMachine - Common code between 32-bit and 64-bit PowerPC targets. +/// +class PPCTargetMachine : public LLVMTargetMachine { + PPCSubtarget Subtarget; + const TargetData DataLayout; // Calculates type size & alignment + PPCInstrInfo InstrInfo; + PPCFrameInfo FrameInfo; + PPCJITInfo JITInfo; + PPCTargetLowering TLInfo; + InstrItineraryData InstrItins; + PPCMachOWriterInfo MachOWriterInfo; + +public: + PPCTargetMachine(const Target &T, const std::string &TT, + const std::string &FS, bool is64Bit); + + virtual const PPCInstrInfo *getInstrInfo() const { return &InstrInfo; } + virtual const PPCFrameInfo *getFrameInfo() const { return &FrameInfo; } + virtual PPCJITInfo *getJITInfo() { return &JITInfo; } + virtual PPCTargetLowering *getTargetLowering() const { + return const_cast(&TLInfo); + } + virtual const PPCRegisterInfo *getRegisterInfo() const { + return &InstrInfo.getRegisterInfo(); + } + + virtual const TargetData *getTargetData() const { return &DataLayout; } + virtual const PPCSubtarget *getSubtargetImpl() const { return &Subtarget; } + virtual const InstrItineraryData getInstrItineraryData() const { + return InstrItins; + } + virtual const PPCMachOWriterInfo *getMachOWriterInfo() const { + return &MachOWriterInfo; + } + + // Pass Pipeline Configuration + virtual bool addInstSelector(PassManagerBase &PM, CodeGenOpt::Level OptLevel); + virtual bool addPreEmitPass(PassManagerBase &PM, CodeGenOpt::Level OptLevel); + virtual bool addCodeEmitter(PassManagerBase &PM, CodeGenOpt::Level OptLevel, + MachineCodeEmitter &MCE); + virtual bool addCodeEmitter(PassManagerBase &PM, CodeGenOpt::Level OptLevel, + JITCodeEmitter &JCE); + virtual bool addCodeEmitter(PassManagerBase &PM, CodeGenOpt::Level OptLevel, + ObjectCodeEmitter &OCE); + virtual bool addSimpleCodeEmitter(PassManagerBase &PM, + CodeGenOpt::Level OptLevel, + MachineCodeEmitter &MCE); + virtual bool addSimpleCodeEmitter(PassManagerBase &PM, + CodeGenOpt::Level OptLevel, + JITCodeEmitter &JCE); + virtual bool addSimpleCodeEmitter(PassManagerBase &PM, + CodeGenOpt::Level OptLevel, + ObjectCodeEmitter &OCE); + virtual bool getEnableTailMergeDefault() const; +}; + +/// PPC32TargetMachine - PowerPC 32-bit target machine. +/// +class PPC32TargetMachine : public PPCTargetMachine { +public: + PPC32TargetMachine(const Target &T, const std::string &TT, + const std::string &FS); +}; + +/// PPC64TargetMachine - PowerPC 64-bit target machine. +/// +class PPC64TargetMachine : public PPCTargetMachine { +public: + PPC64TargetMachine(const Target &T, const std::string &TT, + const std::string &FS); +}; + +} // end namespace llvm + +#endif diff --git a/libclamav/c++/llvm/lib/Target/PowerPC/README.txt b/libclamav/c++/llvm/lib/Target/PowerPC/README.txt new file mode 100644 index 000000000..f5e50fc80 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/PowerPC/README.txt @@ -0,0 +1,809 @@ +//===- README.txt - Notes for improving PowerPC-specific code gen ---------===// + +TODO: +* gpr0 allocation +* implement do-loop -> bdnz transform +* lmw/stmw pass a la arm load store optimizer for prolog/epilog + +===-------------------------------------------------------------------------=== + +Support 'update' load/store instructions. These are cracked on the G5, but are +still a codesize win. + +With preinc enabled, this: + +long *%test4(long *%X, long *%dest) { + %Y = getelementptr long* %X, int 4 + %A = load long* %Y + store long %A, long* %dest + ret long* %Y +} + +compiles to: + +_test4: + mr r2, r3 + lwzu r5, 32(r2) + lwz r3, 36(r3) + stw r5, 0(r4) + stw r3, 4(r4) + mr r3, r2 + blr + +with -sched=list-burr, I get: + +_test4: + lwz r2, 36(r3) + lwzu r5, 32(r3) + stw r2, 4(r4) + stw r5, 0(r4) + blr + +===-------------------------------------------------------------------------=== + +We compile the hottest inner loop of viterbi to: + + li r6, 0 + b LBB1_84 ;bb432.i +LBB1_83: ;bb420.i + lbzx r8, r5, r7 + addi r6, r7, 1 + stbx r8, r4, r7 +LBB1_84: ;bb432.i + mr r7, r6 + cmplwi cr0, r7, 143 + bne cr0, LBB1_83 ;bb420.i + +The CBE manages to produce: + + li r0, 143 + mtctr r0 +loop: + lbzx r2, r2, r11 + stbx r0, r2, r9 + addi r2, r2, 1 + bdz later + b loop + +This could be much better (bdnz instead of bdz) but it still beats us. If we +produced this with bdnz, the loop would be a single dispatch group. + +===-------------------------------------------------------------------------=== + +Compile: + +void foo(int *P) { + if (P) *P = 0; +} + +into: + +_foo: + cmpwi cr0,r3,0 + beqlr cr0 + li r0,0 + stw r0,0(r3) + blr + +This is effectively a simple form of predication. + +===-------------------------------------------------------------------------=== + +Lump the constant pool for each function into ONE pic object, and reference +pieces of it as offsets from the start. For functions like this (contrived +to have lots of constants obviously): + +double X(double Y) { return (Y*1.23 + 4.512)*2.34 + 14.38; } + +We generate: + +_X: + lis r2, ha16(.CPI_X_0) + lfd f0, lo16(.CPI_X_0)(r2) + lis r2, ha16(.CPI_X_1) + lfd f2, lo16(.CPI_X_1)(r2) + fmadd f0, f1, f0, f2 + lis r2, ha16(.CPI_X_2) + lfd f1, lo16(.CPI_X_2)(r2) + lis r2, ha16(.CPI_X_3) + lfd f2, lo16(.CPI_X_3)(r2) + fmadd f1, f0, f1, f2 + blr + +It would be better to materialize .CPI_X into a register, then use immediates +off of the register to avoid the lis's. This is even more important in PIC +mode. + +Note that this (and the static variable version) is discussed here for GCC: +http://gcc.gnu.org/ml/gcc-patches/2006-02/msg00133.html + +Here's another example (the sgn function): +double testf(double a) { + return a == 0.0 ? 0.0 : (a > 0.0 ? 1.0 : -1.0); +} + +it produces a BB like this: +LBB1_1: ; cond_true + lis r2, ha16(LCPI1_0) + lfs f0, lo16(LCPI1_0)(r2) + lis r2, ha16(LCPI1_1) + lis r3, ha16(LCPI1_2) + lfs f2, lo16(LCPI1_2)(r3) + lfs f3, lo16(LCPI1_1)(r2) + fsub f0, f0, f1 + fsel f1, f0, f2, f3 + blr + +===-------------------------------------------------------------------------=== + +PIC Code Gen IPO optimization: + +Squish small scalar globals together into a single global struct, allowing the +address of the struct to be CSE'd, avoiding PIC accesses (also reduces the size +of the GOT on targets with one). + +Note that this is discussed here for GCC: +http://gcc.gnu.org/ml/gcc-patches/2006-02/msg00133.html + +===-------------------------------------------------------------------------=== + +Implement Newton-Rhapson method for improving estimate instructions to the +correct accuracy, and implementing divide as multiply by reciprocal when it has +more than one use. Itanium would want this too. + +===-------------------------------------------------------------------------=== + +Compile offsets from allocas: + +int *%test() { + %X = alloca { int, int } + %Y = getelementptr {int,int}* %X, int 0, uint 1 + ret int* %Y +} + +into a single add, not two: + +_test: + addi r2, r1, -8 + addi r3, r2, 4 + blr + +--> important for C++. + +===-------------------------------------------------------------------------=== + +No loads or stores of the constants should be needed: + +struct foo { double X, Y; }; +void xxx(struct foo F); +void bar() { struct foo R = { 1.0, 2.0 }; xxx(R); } + +===-------------------------------------------------------------------------=== + +Darwin Stub removal: + +We still generate calls to foo$stub, and stubs, on Darwin. This is not +necessary when building with the Leopard (10.5) or later linker, as stubs are +generated by ld when necessary. Parameterizing this based on the deployment +target (-mmacosx-version-min) is probably enough. x86-32 does this right, see +its logic. + +===-------------------------------------------------------------------------=== + +Darwin Stub LICM optimization: + +Loops like this: + + for (...) bar(); + +Have to go through an indirect stub if bar is external or linkonce. It would +be better to compile it as: + + fp = &bar; + for (...) fp(); + +which only computes the address of bar once (instead of each time through the +stub). This is Darwin specific and would have to be done in the code generator. +Probably not a win on x86. + +===-------------------------------------------------------------------------=== + +Simple IPO for argument passing, change: + void foo(int X, double Y, int Z) -> void foo(int X, int Z, double Y) + +the Darwin ABI specifies that any integer arguments in the first 32 bytes worth +of arguments get assigned to r3 through r10. That is, if you have a function +foo(int, double, int) you get r3, f1, r6, since the 64 bit double ate up the +argument bytes for r4 and r5. The trick then would be to shuffle the argument +order for functions we can internalize so that the maximum number of +integers/pointers get passed in regs before you see any of the fp arguments. + +Instead of implementing this, it would actually probably be easier to just +implement a PPC fastcc, where we could do whatever we wanted to the CC, +including having this work sanely. + +===-------------------------------------------------------------------------=== + +Fix Darwin FP-In-Integer Registers ABI + +Darwin passes doubles in structures in integer registers, which is very very +bad. Add something like a BIT_CONVERT to LLVM, then do an i-p transformation +that percolates these things out of functions. + +Check out how horrible this is: +http://gcc.gnu.org/ml/gcc/2005-10/msg01036.html + +This is an extension of "interprocedural CC unmunging" that can't be done with +just fastcc. + +===-------------------------------------------------------------------------=== + +Compile this: + +int foo(int a) { + int b = (a < 8); + if (b) { + return b * 3; // ignore the fact that this is always 3. + } else { + return 2; + } +} + +into something not this: + +_foo: +1) cmpwi cr7, r3, 8 + mfcr r2, 1 + rlwinm r2, r2, 29, 31, 31 +1) cmpwi cr0, r3, 7 + bgt cr0, LBB1_2 ; UnifiedReturnBlock +LBB1_1: ; then + rlwinm r2, r2, 0, 31, 31 + mulli r3, r2, 3 + blr +LBB1_2: ; UnifiedReturnBlock + li r3, 2 + blr + +In particular, the two compares (marked 1) could be shared by reversing one. +This could be done in the dag combiner, by swapping a BR_CC when a SETCC of the +same operands (but backwards) exists. In this case, this wouldn't save us +anything though, because the compares still wouldn't be shared. + +===-------------------------------------------------------------------------=== + +We should custom expand setcc instead of pretending that we have it. That +would allow us to expose the access of the crbit after the mfcr, allowing +that access to be trivially folded into other ops. A simple example: + +int foo(int a, int b) { return (a < b) << 4; } + +compiles into: + +_foo: + cmpw cr7, r3, r4 + mfcr r2, 1 + rlwinm r2, r2, 29, 31, 31 + slwi r3, r2, 4 + blr + +===-------------------------------------------------------------------------=== + +Fold add and sub with constant into non-extern, non-weak addresses so this: + +static int a; +void bar(int b) { a = b; } +void foo(unsigned char *c) { + *c = a; +} + +So that + +_foo: + lis r2, ha16(_a) + la r2, lo16(_a)(r2) + lbz r2, 3(r2) + stb r2, 0(r3) + blr + +Becomes + +_foo: + lis r2, ha16(_a+3) + lbz r2, lo16(_a+3)(r2) + stb r2, 0(r3) + blr + +===-------------------------------------------------------------------------=== + +We generate really bad code for this: + +int f(signed char *a, _Bool b, _Bool c) { + signed char t = 0; + if (b) t = *a; + if (c) *a = t; +} + +===-------------------------------------------------------------------------=== + +This: +int test(unsigned *P) { return *P >> 24; } + +Should compile to: + +_test: + lbz r3,0(r3) + blr + +not: + +_test: + lwz r2, 0(r3) + srwi r3, r2, 24 + blr + +===-------------------------------------------------------------------------=== + +On the G5, logical CR operations are more expensive in their three +address form: ops that read/write the same register are half as expensive as +those that read from two registers that are different from their destination. + +We should model this with two separate instructions. The isel should generate +the "two address" form of the instructions. When the register allocator +detects that it needs to insert a copy due to the two-addresness of the CR +logical op, it will invoke PPCInstrInfo::convertToThreeAddress. At this point +we can convert to the "three address" instruction, to save code space. + +This only matters when we start generating cr logical ops. + +===-------------------------------------------------------------------------=== + +We should compile these two functions to the same thing: + +#include +void f(int a, int b, int *P) { + *P = (a-b)>=0?(a-b):(b-a); +} +void g(int a, int b, int *P) { + *P = abs(a-b); +} + +Further, they should compile to something better than: + +_g: + subf r2, r4, r3 + subfic r3, r2, 0 + cmpwi cr0, r2, -1 + bgt cr0, LBB2_2 ; entry +LBB2_1: ; entry + mr r2, r3 +LBB2_2: ; entry + stw r2, 0(r5) + blr + +GCC produces: + +_g: + subf r4,r4,r3 + srawi r2,r4,31 + xor r0,r2,r4 + subf r0,r2,r0 + stw r0,0(r5) + blr + +... which is much nicer. + +This theoretically may help improve twolf slightly (used in dimbox.c:142?). + +===-------------------------------------------------------------------------=== + +int foo(int N, int ***W, int **TK, int X) { + int t, i; + + for (t = 0; t < N; ++t) + for (i = 0; i < 4; ++i) + W[t / X][i][t % X] = TK[i][t]; + + return 5; +} + +We generate relatively atrocious code for this loop compared to gcc. + +We could also strength reduce the rem and the div: +http://www.lcs.mit.edu/pubs/pdf/MIT-LCS-TM-600.pdf + +===-------------------------------------------------------------------------=== + +float foo(float X) { return (int)(X); } + +Currently produces: + +_foo: + fctiwz f0, f1 + stfd f0, -8(r1) + lwz r2, -4(r1) + extsw r2, r2 + std r2, -16(r1) + lfd f0, -16(r1) + fcfid f0, f0 + frsp f1, f0 + blr + +We could use a target dag combine to turn the lwz/extsw into an lwa when the +lwz has a single use. Since LWA is cracked anyway, this would be a codesize +win only. + +===-------------------------------------------------------------------------=== + +We generate ugly code for this: + +void func(unsigned int *ret, float dx, float dy, float dz, float dw) { + unsigned code = 0; + if(dx < -dw) code |= 1; + if(dx > dw) code |= 2; + if(dy < -dw) code |= 4; + if(dy > dw) code |= 8; + if(dz < -dw) code |= 16; + if(dz > dw) code |= 32; + *ret = code; +} + +===-------------------------------------------------------------------------=== + +Complete the signed i32 to FP conversion code using 64-bit registers +transformation, good for PI. See PPCISelLowering.cpp, this comment: + + // FIXME: disable this lowered code. This generates 64-bit register values, + // and we don't model the fact that the top part is clobbered by calls. We + // need to flag these together so that the value isn't live across a call. + //setOperationAction(ISD::SINT_TO_FP, MVT::i32, Custom); + +Also, if the registers are spilled to the stack, we have to ensure that all +64-bits of them are save/restored, otherwise we will miscompile the code. It +sounds like we need to get the 64-bit register classes going. + +===-------------------------------------------------------------------------=== + +%struct.B = type { i8, [3 x i8] } + +define void @bar(%struct.B* %b) { +entry: + %tmp = bitcast %struct.B* %b to i32* ; [#uses=1] + %tmp = load i32* %tmp ; [#uses=1] + %tmp3 = bitcast %struct.B* %b to i32* ; [#uses=1] + %tmp4 = load i32* %tmp3 ; [#uses=1] + %tmp8 = bitcast %struct.B* %b to i32* ; [#uses=2] + %tmp9 = load i32* %tmp8 ; [#uses=1] + %tmp4.mask17 = shl i32 %tmp4, i8 1 ; [#uses=1] + %tmp1415 = and i32 %tmp4.mask17, 2147483648 ; [#uses=1] + %tmp.masked = and i32 %tmp, 2147483648 ; [#uses=1] + %tmp11 = or i32 %tmp1415, %tmp.masked ; [#uses=1] + %tmp12 = and i32 %tmp9, 2147483647 ; [#uses=1] + %tmp13 = or i32 %tmp12, %tmp11 ; [#uses=1] + store i32 %tmp13, i32* %tmp8 + ret void +} + +We emit: + +_foo: + lwz r2, 0(r3) + slwi r4, r2, 1 + or r4, r4, r2 + rlwimi r2, r4, 0, 0, 0 + stw r2, 0(r3) + blr + +We could collapse a bunch of those ORs and ANDs and generate the following +equivalent code: + +_foo: + lwz r2, 0(r3) + rlwinm r4, r2, 1, 0, 0 + or r2, r2, r4 + stw r2, 0(r3) + blr + +===-------------------------------------------------------------------------=== + +We compile: + +unsigned test6(unsigned x) { + return ((x & 0x00FF0000) >> 16) | ((x & 0x000000FF) << 16); +} + +into: + +_test6: + lis r2, 255 + rlwinm r3, r3, 16, 0, 31 + ori r2, r2, 255 + and r3, r3, r2 + blr + +GCC gets it down to: + +_test6: + rlwinm r0,r3,16,8,15 + rlwinm r3,r3,16,24,31 + or r3,r3,r0 + blr + + +===-------------------------------------------------------------------------=== + +Consider a function like this: + +float foo(float X) { return X + 1234.4123f; } + +The FP constant ends up in the constant pool, so we need to get the LR register. + This ends up producing code like this: + +_foo: +.LBB_foo_0: ; entry + mflr r11 +*** stw r11, 8(r1) + bl "L00000$pb" +"L00000$pb": + mflr r2 + addis r2, r2, ha16(.CPI_foo_0-"L00000$pb") + lfs f0, lo16(.CPI_foo_0-"L00000$pb")(r2) + fadds f1, f1, f0 +*** lwz r11, 8(r1) + mtlr r11 + blr + +This is functional, but there is no reason to spill the LR register all the way +to the stack (the two marked instrs): spilling it to a GPR is quite enough. + +Implementing this will require some codegen improvements. Nate writes: + +"So basically what we need to support the "no stack frame save and restore" is a +generalization of the LR optimization to "callee-save regs". + +Currently, we have LR marked as a callee-save reg. The register allocator sees +that it's callee save, and spills it directly to the stack. + +Ideally, something like this would happen: + +LR would be in a separate register class from the GPRs. The class of LR would be +marked "unspillable". When the register allocator came across an unspillable +reg, it would ask "what is the best class to copy this into that I *can* spill" +If it gets a class back, which it will in this case (the gprs), it grabs a free +register of that class. If it is then later necessary to spill that reg, so be +it. + +===-------------------------------------------------------------------------=== + +We compile this: +int test(_Bool X) { + return X ? 524288 : 0; +} + +to: +_test: + cmplwi cr0, r3, 0 + lis r2, 8 + li r3, 0 + beq cr0, LBB1_2 ;entry +LBB1_1: ;entry + mr r3, r2 +LBB1_2: ;entry + blr + +instead of: +_test: + addic r2,r3,-1 + subfe r0,r2,r3 + slwi r3,r0,19 + blr + +This sort of thing occurs a lot due to globalopt. + +===-------------------------------------------------------------------------=== + +We currently compile 32-bit bswap: + +declare i32 @llvm.bswap.i32(i32 %A) +define i32 @test(i32 %A) { + %B = call i32 @llvm.bswap.i32(i32 %A) + ret i32 %B +} + +to: + +_test: + rlwinm r2, r3, 24, 16, 23 + slwi r4, r3, 24 + rlwimi r2, r3, 8, 24, 31 + rlwimi r4, r3, 8, 8, 15 + rlwimi r4, r2, 0, 16, 31 + mr r3, r4 + blr + +it would be more efficient to produce: + +_foo: mr r0,r3 + rlwinm r3,r3,8,0xffffffff + rlwimi r3,r0,24,0,7 + rlwimi r3,r0,24,16,23 + blr + +===-------------------------------------------------------------------------=== + +test/CodeGen/PowerPC/2007-03-24-cntlzd.ll compiles to: + +__ZNK4llvm5APInt17countLeadingZerosEv: + ld r2, 0(r3) + cntlzd r2, r2 + or r2, r2, r2 <<-- silly. + addi r3, r2, -64 + blr + +The dead or is a 'truncate' from 64- to 32-bits. + +===-------------------------------------------------------------------------=== + +We generate horrible ppc code for this: + +#define N 2000000 +double a[N],c[N]; +void simpleloop() { + int j; + for (j=0; j + inline std::pair full_add(unsigned a, unsigned b) + { return std::make_pair(a + b, a + b < a); } + bool no_overflow(unsigned a, unsigned b) + { return !full_add(a, b).second; } + +Should compile to: + +__Z11no_overflowjj: + add r4,r3,r4 + subfc r3,r3,r4 + li r3,0 + adde r3,r3,r3 + blr + +(or better) not: + +__Z11no_overflowjj: + add r2, r4, r3 + cmplw cr7, r2, r3 + mfcr r2 + rlwinm r2, r2, 29, 31, 31 + xori r3, r2, 1 + blr + +//===---------------------------------------------------------------------===// + +We compile some FP comparisons into an mfcr with two rlwinms and an or. For +example: +#include +int test(double x, double y) { return islessequal(x, y);} +int test2(double x, double y) { return islessgreater(x, y);} +int test3(double x, double y) { return !islessequal(x, y);} + +Compiles into (all three are similar, but the bits differ): + +_test: + fcmpu cr7, f1, f2 + mfcr r2 + rlwinm r3, r2, 29, 31, 31 + rlwinm r2, r2, 31, 31, 31 + or r3, r2, r3 + blr + +GCC compiles this into: + + _test: + fcmpu cr7,f1,f2 + cror 30,28,30 + mfcr r3 + rlwinm r3,r3,31,1 + blr + +which is more efficient and can use mfocr. See PR642 for some more context. + +//===---------------------------------------------------------------------===// + +void foo(float *data, float d) { + long i; + for (i = 0; i < 8000; i++) + data[i] = d; +} +void foo2(float *data, float d) { + long i; + data--; + for (i = 0; i < 8000; i++) { + data[1] = d; + data++; + } +} + +These compile to: + +_foo: + li r2, 0 +LBB1_1: ; bb + addi r4, r2, 4 + stfsx f1, r3, r2 + cmplwi cr0, r4, 32000 + mr r2, r4 + bne cr0, LBB1_1 ; bb + blr +_foo2: + li r2, 0 +LBB2_1: ; bb + addi r4, r2, 4 + stfsx f1, r3, r2 + cmplwi cr0, r4, 32000 + mr r2, r4 + bne cr0, LBB2_1 ; bb + blr + +The 'mr' could be eliminated to folding the add into the cmp better. + +//===---------------------------------------------------------------------===// +Codegen for the following (low-probability) case deteriorated considerably +when the correctness fixes for unordered comparisons went in (PR 642, 58871). +It should be possible to recover the code quality described in the comments. + +; RUN: llvm-as < %s | llc -march=ppc32 | grep or | count 3 +; This should produce one 'or' or 'cror' instruction per function. + +; RUN: llvm-as < %s | llc -march=ppc32 | grep mfcr | count 3 +; PR2964 + +define i32 @test(double %x, double %y) nounwind { +entry: + %tmp3 = fcmp ole double %x, %y ; [#uses=1] + %tmp345 = zext i1 %tmp3 to i32 ; [#uses=1] + ret i32 %tmp345 +} + +define i32 @test2(double %x, double %y) nounwind { +entry: + %tmp3 = fcmp one double %x, %y ; [#uses=1] + %tmp345 = zext i1 %tmp3 to i32 ; [#uses=1] + ret i32 %tmp345 +} + +define i32 @test3(double %x, double %y) nounwind { +entry: + %tmp3 = fcmp ugt double %x, %y ; [#uses=1] + %tmp34 = zext i1 %tmp3 to i32 ; [#uses=1] + ret i32 %tmp34 +} +//===----------------------------------------------------------------------===// +; RUN: llvm-as < %s | llc -march=ppc32 | not grep fneg + +; This could generate FSEL with appropriate flags (FSEL is not IEEE-safe, and +; should not be generated except with -enable-finite-only-fp-math or the like). +; With the correctness fixes for PR642 (58871) LowerSELECT_CC would need to +; recognize a more elaborate tree than a simple SETxx. + +define double @test_FNEG_sel(double %A, double %B, double %C) { + %D = sub double -0.000000e+00, %A ; [#uses=1] + %Cond = fcmp ugt double %D, -0.000000e+00 ; [#uses=1] + %E = select i1 %Cond, double %B, double %C ; [#uses=1] + ret double %E +} + diff --git a/libclamav/c++/llvm/lib/Target/PowerPC/README_ALTIVEC.txt b/libclamav/c++/llvm/lib/Target/PowerPC/README_ALTIVEC.txt new file mode 100644 index 000000000..1e4c6fb98 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/PowerPC/README_ALTIVEC.txt @@ -0,0 +1,211 @@ +//===- README_ALTIVEC.txt - Notes for improving Altivec code gen ----------===// + +Implement PPCInstrInfo::isLoadFromStackSlot/isStoreToStackSlot for vector +registers, to generate better spill code. + +//===----------------------------------------------------------------------===// + +The first should be a single lvx from the constant pool, the second should be +a xor/stvx: + +void foo(void) { + int x[8] __attribute__((aligned(128))) = { 1, 1, 1, 17, 1, 1, 1, 1 }; + bar (x); +} + +#include +void foo(void) { + int x[8] __attribute__((aligned(128))); + memset (x, 0, sizeof (x)); + bar (x); +} + +//===----------------------------------------------------------------------===// + +Altivec: Codegen'ing MUL with vector FMADD should add -0.0, not 0.0: +http://gcc.gnu.org/bugzilla/show_bug.cgi?id=8763 + +When -ffast-math is on, we can use 0.0. + +//===----------------------------------------------------------------------===// + + Consider this: + v4f32 Vector; + v4f32 Vector2 = { Vector.X, Vector.X, Vector.X, Vector.X }; + +Since we know that "Vector" is 16-byte aligned and we know the element offset +of ".X", we should change the load into a lve*x instruction, instead of doing +a load/store/lve*x sequence. + +//===----------------------------------------------------------------------===// + +For functions that use altivec AND have calls, we are VRSAVE'ing all call +clobbered regs. + +//===----------------------------------------------------------------------===// + +Implement passing vectors by value into calls and receiving them as arguments. + +//===----------------------------------------------------------------------===// + +GCC apparently tries to codegen { C1, C2, Variable, C3 } as a constant pool load +of C1/C2/C3, then a load and vperm of Variable. + +//===----------------------------------------------------------------------===// + +We need a way to teach tblgen that some operands of an intrinsic are required to +be constants. The verifier should enforce this constraint. + +//===----------------------------------------------------------------------===// + +We currently codegen SCALAR_TO_VECTOR as a store of the scalar to a 16-byte +aligned stack slot, followed by a load/vperm. We should probably just store it +to a scalar stack slot, then use lvsl/vperm to load it. If the value is already +in memory this is a big win. + +//===----------------------------------------------------------------------===// + +extract_vector_elt of an arbitrary constant vector can be done with the +following instructions: + +vTemp = vec_splat(v0,2); // 2 is the element the src is in. +vec_ste(&destloc,0,vTemp); + +We can do an arbitrary non-constant value by using lvsr/perm/ste. + +//===----------------------------------------------------------------------===// + +If we want to tie instruction selection into the scheduler, we can do some +constant formation with different instructions. For example, we can generate +"vsplti -1" with "vcmpequw R,R" and 1,1,1,1 with "vsubcuw R,R", and 0,0,0,0 with +"vsplti 0" or "vxor", each of which use different execution units, thus could +help scheduling. + +This is probably only reasonable for a post-pass scheduler. + +//===----------------------------------------------------------------------===// + +For this function: + +void test(vector float *A, vector float *B) { + vector float C = (vector float)vec_cmpeq(*A, *B); + if (!vec_any_eq(*A, *B)) + *B = (vector float){0,0,0,0}; + *A = C; +} + +we get the following basic block: + + ... + lvx v2, 0, r4 + lvx v3, 0, r3 + vcmpeqfp v4, v3, v2 + vcmpeqfp. v2, v3, v2 + bne cr6, LBB1_2 ; cond_next + +The vcmpeqfp/vcmpeqfp. instructions currently cannot be merged when the +vcmpeqfp. result is used by a branch. This can be improved. + +//===----------------------------------------------------------------------===// + +The code generated for this is truly aweful: + +vector float test(float a, float b) { + return (vector float){ 0.0, a, 0.0, 0.0}; +} + +LCPI1_0: ; float + .space 4 + .text + .globl _test + .align 4 +_test: + mfspr r2, 256 + oris r3, r2, 4096 + mtspr 256, r3 + lis r3, ha16(LCPI1_0) + addi r4, r1, -32 + stfs f1, -16(r1) + addi r5, r1, -16 + lfs f0, lo16(LCPI1_0)(r3) + stfs f0, -32(r1) + lvx v2, 0, r4 + lvx v3, 0, r5 + vmrghw v3, v3, v2 + vspltw v2, v2, 0 + vmrghw v2, v2, v3 + mtspr 256, r2 + blr + +//===----------------------------------------------------------------------===// + +int foo(vector float *x, vector float *y) { + if (vec_all_eq(*x,*y)) return 3245; + else return 12; +} + +A predicate compare being used in a select_cc should have the same peephole +applied to it as a predicate compare used by a br_cc. There should be no +mfcr here: + +_foo: + mfspr r2, 256 + oris r5, r2, 12288 + mtspr 256, r5 + li r5, 12 + li r6, 3245 + lvx v2, 0, r4 + lvx v3, 0, r3 + vcmpeqfp. v2, v3, v2 + mfcr r3, 2 + rlwinm r3, r3, 25, 31, 31 + cmpwi cr0, r3, 0 + bne cr0, LBB1_2 ; entry +LBB1_1: ; entry + mr r6, r5 +LBB1_2: ; entry + mr r3, r6 + mtspr 256, r2 + blr + +//===----------------------------------------------------------------------===// + +CodeGen/PowerPC/vec_constants.ll has an and operation that should be +codegen'd to andc. The issue is that the 'all ones' build vector is +SelectNodeTo'd a VSPLTISB instruction node before the and/xor is selected +which prevents the vnot pattern from matching. + + +//===----------------------------------------------------------------------===// + +An alternative to the store/store/load approach for illegal insert element +lowering would be: + +1. store element to any ol' slot +2. lvx the slot +3. lvsl 0; splat index; vcmpeq to generate a select mask +4. lvsl slot + x; vperm to rotate result into correct slot +5. vsel result together. + +//===----------------------------------------------------------------------===// + +Should codegen branches on vec_any/vec_all to avoid mfcr. Two examples: + +#include + int f(vector float a, vector float b) + { + int aa = 0; + if (vec_all_ge(a, b)) + aa |= 0x1; + if (vec_any_ge(a,b)) + aa |= 0x2; + return aa; +} + +vector float f(vector float a, vector float b) { + if (vec_any_eq(a, b)) + return a; + else + return b; +} + diff --git a/libclamav/c++/llvm/lib/Target/PowerPC/TargetInfo/CMakeLists.txt b/libclamav/c++/llvm/lib/Target/PowerPC/TargetInfo/CMakeLists.txt new file mode 100644 index 000000000..058d599a4 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/PowerPC/TargetInfo/CMakeLists.txt @@ -0,0 +1,7 @@ +include_directories( ${CMAKE_CURRENT_BINARY_DIR}/.. ${CMAKE_CURRENT_SOURCE_DIR}/.. ) + +add_llvm_library(LLVMPowerPCInfo + PowerPCTargetInfo.cpp + ) + +add_dependencies(LLVMPowerPCInfo PowerPCCodeGenTable_gen) diff --git a/libclamav/c++/llvm/lib/Target/PowerPC/TargetInfo/Makefile b/libclamav/c++/llvm/lib/Target/PowerPC/TargetInfo/Makefile new file mode 100644 index 000000000..a101aa4a4 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/PowerPC/TargetInfo/Makefile @@ -0,0 +1,15 @@ +##===- lib/Target/PowerPC/TargetInfo/Makefile --------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## +LEVEL = ../../../.. +LIBRARYNAME = LLVMPowerPCInfo + +# Hack: we need to include 'main' target directory to grab private headers +CPPFLAGS = -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. + +include $(LEVEL)/Makefile.common diff --git a/libclamav/c++/llvm/lib/Target/PowerPC/TargetInfo/PowerPCTargetInfo.cpp b/libclamav/c++/llvm/lib/Target/PowerPC/TargetInfo/PowerPCTargetInfo.cpp new file mode 100644 index 000000000..ad607d0ad --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/PowerPC/TargetInfo/PowerPCTargetInfo.cpp @@ -0,0 +1,23 @@ +//===-- PowerPCTargetInfo.cpp - PowerPC Target Implementation -------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "PPC.h" +#include "llvm/Module.h" +#include "llvm/Target/TargetRegistry.h" +using namespace llvm; + +Target llvm::ThePPC32Target, llvm::ThePPC64Target; + +extern "C" void LLVMInitializePowerPCTargetInfo() { + RegisterTarget + X(ThePPC32Target, "ppc32", "PowerPC 32"); + + RegisterTarget + Y(ThePPC64Target, "ppc64", "PowerPC 64"); +} diff --git a/libclamav/c++/llvm/lib/Target/README.txt b/libclamav/c++/llvm/lib/Target/README.txt new file mode 100644 index 000000000..e7a55a07c --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/README.txt @@ -0,0 +1,1684 @@ +Target Independent Opportunities: + +//===---------------------------------------------------------------------===// + +With the recent changes to make the implicit def/use set explicit in +machineinstrs, we should change the target descriptions for 'call' instructions +so that the .td files don't list all the call-clobbered registers as implicit +defs. Instead, these should be added by the code generator (e.g. on the dag). + +This has a number of uses: + +1. PPC32/64 and X86 32/64 can avoid having multiple copies of call instructions + for their different impdef sets. +2. Targets with multiple calling convs (e.g. x86) which have different clobber + sets don't need copies of call instructions. +3. 'Interprocedural register allocation' can be done to reduce the clobber sets + of calls. + +//===---------------------------------------------------------------------===// + +Make the PPC branch selector target independant + +//===---------------------------------------------------------------------===// + +Get the C front-end to expand hypot(x,y) -> llvm.sqrt(x*x+y*y) when errno and +precision don't matter (ffastmath). Misc/mandel will like this. :) This isn't +safe in general, even on darwin. See the libm implementation of hypot for +examples (which special case when x/y are exactly zero to get signed zeros etc +right). + +//===---------------------------------------------------------------------===// + +Solve this DAG isel folding deficiency: + +int X, Y; + +void fn1(void) +{ + X = X | (Y << 3); +} + +compiles to + +fn1: + movl Y, %eax + shll $3, %eax + orl X, %eax + movl %eax, X + ret + +The problem is the store's chain operand is not the load X but rather +a TokenFactor of the load X and load Y, which prevents the folding. + +There are two ways to fix this: + +1. The dag combiner can start using alias analysis to realize that y/x + don't alias, making the store to X not dependent on the load from Y. +2. The generated isel could be made smarter in the case it can't + disambiguate the pointers. + +Number 1 is the preferred solution. + +This has been "fixed" by a TableGen hack. But that is a short term workaround +which will be removed once the proper fix is made. + +//===---------------------------------------------------------------------===// + +On targets with expensive 64-bit multiply, we could LSR this: + +for (i = ...; ++i) { + x = 1ULL << i; + +into: + long long tmp = 1; + for (i = ...; ++i, tmp+=tmp) + x = tmp; + +This would be a win on ppc32, but not x86 or ppc64. + +//===---------------------------------------------------------------------===// + +Shrink: (setlt (loadi32 P), 0) -> (setlt (loadi8 Phi), 0) + +//===---------------------------------------------------------------------===// + +Reassociate should turn: X*X*X*X -> t=(X*X) (t*t) to eliminate a multiply. + +//===---------------------------------------------------------------------===// + +Interesting? testcase for add/shift/mul reassoc: + +int bar(int x, int y) { + return x*x*x+y+x*x*x*x*x*y*y*y*y; +} +int foo(int z, int n) { + return bar(z, n) + bar(2*z, 2*n); +} + +Reassociate should handle the example in GCC PR16157. + +//===---------------------------------------------------------------------===// + +These two functions should generate the same code on big-endian systems: + +int g(int *j,int *l) { return memcmp(j,l,4); } +int h(int *j, int *l) { return *j - *l; } + +this could be done in SelectionDAGISel.cpp, along with other special cases, +for 1,2,4,8 bytes. + +//===---------------------------------------------------------------------===// + +It would be nice to revert this patch: +http://lists.cs.uiuc.edu/pipermail/llvm-commits/Week-of-Mon-20060213/031986.html + +And teach the dag combiner enough to simplify the code expanded before +legalize. It seems plausible that this knowledge would let it simplify other +stuff too. + +//===---------------------------------------------------------------------===// + +For vector types, TargetData.cpp::getTypeInfo() returns alignment that is equal +to the type size. It works but can be overly conservative as the alignment of +specific vector types are target dependent. + +//===---------------------------------------------------------------------===// + +We should produce an unaligned load from code like this: + +v4sf example(float *P) { + return (v4sf){P[0], P[1], P[2], P[3] }; +} + +//===---------------------------------------------------------------------===// + +Add support for conditional increments, and other related patterns. Instead +of: + + movl 136(%esp), %eax + cmpl $0, %eax + je LBB16_2 #cond_next +LBB16_1: #cond_true + incl _foo +LBB16_2: #cond_next + +emit: + movl _foo, %eax + cmpl $1, %edi + sbbl $-1, %eax + movl %eax, _foo + +//===---------------------------------------------------------------------===// + +Combine: a = sin(x), b = cos(x) into a,b = sincos(x). + +Expand these to calls of sin/cos and stores: + double sincos(double x, double *sin, double *cos); + float sincosf(float x, float *sin, float *cos); + long double sincosl(long double x, long double *sin, long double *cos); + +Doing so could allow SROA of the destination pointers. See also: +http://gcc.gnu.org/bugzilla/show_bug.cgi?id=17687 + +This is now easily doable with MRVs. We could even make an intrinsic for this +if anyone cared enough about sincos. + +//===---------------------------------------------------------------------===// + +Turn this into a single byte store with no load (the other 3 bytes are +unmodified): + +define void @test(i32* %P) { + %tmp = load i32* %P + %tmp14 = or i32 %tmp, 3305111552 + %tmp15 = and i32 %tmp14, 3321888767 + store i32 %tmp15, i32* %P + ret void +} + +//===---------------------------------------------------------------------===// + +dag/inst combine "clz(x)>>5 -> x==0" for 32-bit x. + +Compile: + +int bar(int x) +{ + int t = __builtin_clz(x); + return -(t>>5); +} + +to: + +_bar: addic r3,r3,-1 + subfe r3,r3,r3 + blr + +//===---------------------------------------------------------------------===// + +quantum_sigma_x in 462.libquantum contains the following loop: + + for(i=0; isize; i++) + { + /* Flip the target bit of each basis state */ + reg->node[i].state ^= ((MAX_UNSIGNED) 1 << target); + } + +Where MAX_UNSIGNED/state is a 64-bit int. On a 32-bit platform it would be just +so cool to turn it into something like: + + long long Res = ((MAX_UNSIGNED) 1 << target); + if (target < 32) { + for(i=0; isize; i++) + reg->node[i].state ^= Res & 0xFFFFFFFFULL; + } else { + for(i=0; isize; i++) + reg->node[i].state ^= Res & 0xFFFFFFFF00000000ULL + } + +... which would only do one 32-bit XOR per loop iteration instead of two. + +It would also be nice to recognize the reg->size doesn't alias reg->node[i], but +this requires TBAA. + +//===---------------------------------------------------------------------===// + +This should be optimized to one 'and' and one 'or', from PR4216: + +define i32 @test_bitfield(i32 %bf.prev.low) nounwind ssp { +entry: + %bf.prev.lo.cleared10 = or i32 %bf.prev.low, 32962 ; [#uses=1] + %0 = and i32 %bf.prev.low, -65536 ; [#uses=1] + %1 = and i32 %bf.prev.lo.cleared10, 40186 ; [#uses=1] + %2 = or i32 %1, %0 ; [#uses=1] + ret i32 %2 +} + +//===---------------------------------------------------------------------===// + +This isn't recognized as bswap by instcombine (yes, it really is bswap): + +unsigned long reverse(unsigned v) { + unsigned t; + t = v ^ ((v << 16) | (v >> 16)); + t &= ~0xff0000; + v = (v << 24) | (v >> 8); + return v ^ (t >> 8); +} + +//===---------------------------------------------------------------------===// + +These idioms should be recognized as popcount (see PR1488): + +unsigned countbits_slow(unsigned v) { + unsigned c; + for (c = 0; v; v >>= 1) + c += v & 1; + return c; +} +unsigned countbits_fast(unsigned v){ + unsigned c; + for (c = 0; v; c++) + v &= v - 1; // clear the least significant bit set + return c; +} + +BITBOARD = unsigned long long +int PopCnt(register BITBOARD a) { + register int c=0; + while(a) { + c++; + a &= a - 1; + } + return c; +} +unsigned int popcount(unsigned int input) { + unsigned int count = 0; + for (unsigned int i = 0; i < 4 * 8; i++) + count += (input >> i) & i; + return count; +} + +This is a form of idiom recognition for loops, the same thing that could be +useful for recognizing memset/memcpy. + +//===---------------------------------------------------------------------===// + +These should turn into single 16-bit (unaligned?) loads on little/big endian +processors. + +unsigned short read_16_le(const unsigned char *adr) { + return adr[0] | (adr[1] << 8); +} +unsigned short read_16_be(const unsigned char *adr) { + return (adr[0] << 8) | adr[1]; +} + +//===---------------------------------------------------------------------===// + +-instcombine should handle this transform: + icmp pred (sdiv X / C1 ), C2 +when X, C1, and C2 are unsigned. Similarly for udiv and signed operands. + +Currently InstCombine avoids this transform but will do it when the signs of +the operands and the sign of the divide match. See the FIXME in +InstructionCombining.cpp in the visitSetCondInst method after the switch case +for Instruction::UDiv (around line 4447) for more details. + +The SingleSource/Benchmarks/Shootout-C++/hash and hash2 tests have examples of +this construct. + +//===---------------------------------------------------------------------===// + +viterbi speeds up *significantly* if the various "history" related copy loops +are turned into memcpy calls at the source level. We need a "loops to memcpy" +pass. + +//===---------------------------------------------------------------------===// + +Consider: + +typedef unsigned U32; +typedef unsigned long long U64; +int test (U32 *inst, U64 *regs) { + U64 effective_addr2; + U32 temp = *inst; + int r1 = (temp >> 20) & 0xf; + int b2 = (temp >> 16) & 0xf; + effective_addr2 = temp & 0xfff; + if (b2) effective_addr2 += regs[b2]; + b2 = (temp >> 12) & 0xf; + if (b2) effective_addr2 += regs[b2]; + effective_addr2 &= regs[4]; + if ((effective_addr2 & 3) == 0) + return 1; + return 0; +} + +Note that only the low 2 bits of effective_addr2 are used. On 32-bit systems, +we don't eliminate the computation of the top half of effective_addr2 because +we don't have whole-function selection dags. On x86, this means we use one +extra register for the function when effective_addr2 is declared as U64 than +when it is declared U32. + +PHI Slicing could be extended to do this. + +//===---------------------------------------------------------------------===// + +LSR should know what GPR types a target has from TargetData. This code: + +volatile short X, Y; // globals + +void foo(int N) { + int i; + for (i = 0; i < N; i++) { X = i; Y = i*4; } +} + +produces two near identical IV's (after promotion) on PPC/ARM: + +LBB1_2: + ldr r3, LCPI1_0 + ldr r3, [r3] + strh r2, [r3] + ldr r3, LCPI1_1 + ldr r3, [r3] + strh r1, [r3] + add r1, r1, #4 + add r2, r2, #1 <- [0,+,1] + sub r0, r0, #1 <- [0,-,1] + cmp r0, #0 + bne LBB1_2 + +LSR should reuse the "+" IV for the exit test. + +//===---------------------------------------------------------------------===// + +Tail call elim should be more aggressive, checking to see if the call is +followed by an uncond branch to an exit block. + +; This testcase is due to tail-duplication not wanting to copy the return +; instruction into the terminating blocks because there was other code +; optimized out of the function after the taildup happened. +; RUN: llvm-as < %s | opt -tailcallelim | llvm-dis | not grep call + +define i32 @t4(i32 %a) { +entry: + %tmp.1 = and i32 %a, 1 ; [#uses=1] + %tmp.2 = icmp ne i32 %tmp.1, 0 ; [#uses=1] + br i1 %tmp.2, label %then.0, label %else.0 + +then.0: ; preds = %entry + %tmp.5 = add i32 %a, -1 ; [#uses=1] + %tmp.3 = call i32 @t4( i32 %tmp.5 ) ; [#uses=1] + br label %return + +else.0: ; preds = %entry + %tmp.7 = icmp ne i32 %a, 0 ; [#uses=1] + br i1 %tmp.7, label %then.1, label %return + +then.1: ; preds = %else.0 + %tmp.11 = add i32 %a, -2 ; [#uses=1] + %tmp.9 = call i32 @t4( i32 %tmp.11 ) ; [#uses=1] + br label %return + +return: ; preds = %then.1, %else.0, %then.0 + %result.0 = phi i32 [ 0, %else.0 ], [ %tmp.3, %then.0 ], + [ %tmp.9, %then.1 ] + ret i32 %result.0 +} + +//===---------------------------------------------------------------------===// + +Tail recursion elimination should handle: + +int pow2m1(int n) { + if (n == 0) + return 0; + return 2 * pow2m1 (n - 1) + 1; +} + +Also, multiplies can be turned into SHL's, so they should be handled as if +they were associative. "return foo() << 1" can be tail recursion eliminated. + +//===---------------------------------------------------------------------===// + +Argument promotion should promote arguments for recursive functions, like +this: + +; RUN: llvm-as < %s | opt -argpromotion | llvm-dis | grep x.val + +define internal i32 @foo(i32* %x) { +entry: + %tmp = load i32* %x ; [#uses=0] + %tmp.foo = call i32 @foo( i32* %x ) ; [#uses=1] + ret i32 %tmp.foo +} + +define i32 @bar(i32* %x) { +entry: + %tmp3 = call i32 @foo( i32* %x ) ; [#uses=1] + ret i32 %tmp3 +} + +//===---------------------------------------------------------------------===// + +We should investigate an instruction sinking pass. Consider this silly +example in pic mode: + +#include +void foo(int x) { + assert(x); + //... +} + +we compile this to: +_foo: + subl $28, %esp + call "L1$pb" +"L1$pb": + popl %eax + cmpl $0, 32(%esp) + je LBB1_2 # cond_true +LBB1_1: # return + # ... + addl $28, %esp + ret +LBB1_2: # cond_true +... + +The PIC base computation (call+popl) is only used on one path through the +code, but is currently always computed in the entry block. It would be +better to sink the picbase computation down into the block for the +assertion, as it is the only one that uses it. This happens for a lot of +code with early outs. + +Another example is loads of arguments, which are usually emitted into the +entry block on targets like x86. If not used in all paths through a +function, they should be sunk into the ones that do. + +In this case, whole-function-isel would also handle this. + +//===---------------------------------------------------------------------===// + +Investigate lowering of sparse switch statements into perfect hash tables: +http://burtleburtle.net/bob/hash/perfect.html + +//===---------------------------------------------------------------------===// + +We should turn things like "load+fabs+store" and "load+fneg+store" into the +corresponding integer operations. On a yonah, this loop: + +double a[256]; +void foo() { + int i, b; + for (b = 0; b < 10000000; b++) + for (i = 0; i < 256; i++) + a[i] = -a[i]; +} + +is twice as slow as this loop: + +long long a[256]; +void foo() { + int i, b; + for (b = 0; b < 10000000; b++) + for (i = 0; i < 256; i++) + a[i] ^= (1ULL << 63); +} + +and I suspect other processors are similar. On X86 in particular this is a +big win because doing this with integers allows the use of read/modify/write +instructions. + +//===---------------------------------------------------------------------===// + +DAG Combiner should try to combine small loads into larger loads when +profitable. For example, we compile this C++ example: + +struct THotKey { short Key; bool Control; bool Shift; bool Alt; }; +extern THotKey m_HotKey; +THotKey GetHotKey () { return m_HotKey; } + +into (-O3 -fno-exceptions -static -fomit-frame-pointer): + +__Z9GetHotKeyv: + pushl %esi + movl 8(%esp), %eax + movb _m_HotKey+3, %cl + movb _m_HotKey+4, %dl + movb _m_HotKey+2, %ch + movw _m_HotKey, %si + movw %si, (%eax) + movb %ch, 2(%eax) + movb %cl, 3(%eax) + movb %dl, 4(%eax) + popl %esi + ret $4 + +GCC produces: + +__Z9GetHotKeyv: + movl _m_HotKey, %edx + movl 4(%esp), %eax + movl %edx, (%eax) + movzwl _m_HotKey+4, %edx + movw %dx, 4(%eax) + ret $4 + +The LLVM IR contains the needed alignment info, so we should be able to +merge the loads and stores into 4-byte loads: + + %struct.THotKey = type { i16, i8, i8, i8 } +define void @_Z9GetHotKeyv(%struct.THotKey* sret %agg.result) nounwind { +... + %tmp2 = load i16* getelementptr (@m_HotKey, i32 0, i32 0), align 8 + %tmp5 = load i8* getelementptr (@m_HotKey, i32 0, i32 1), align 2 + %tmp8 = load i8* getelementptr (@m_HotKey, i32 0, i32 2), align 1 + %tmp11 = load i8* getelementptr (@m_HotKey, i32 0, i32 3), align 2 + +Alternatively, we should use a small amount of base-offset alias analysis +to make it so the scheduler doesn't need to hold all the loads in regs at +once. + +//===---------------------------------------------------------------------===// + +We should add an FRINT node to the DAG to model targets that have legal +implementations of ceil/floor/rint. + +//===---------------------------------------------------------------------===// + +Consider: + +int test() { + long long input[8] = {1,1,1,1,1,1,1,1}; + foo(input); +} + +We currently compile this into a memcpy from a global array since the +initializer is fairly large and not memset'able. This is good, but the memcpy +gets lowered to load/stores in the code generator. This is also ok, except +that the codegen lowering for memcpy doesn't handle the case when the source +is a constant global. This gives us atrocious code like this: + + call "L1$pb" +"L1$pb": + popl %eax + movl _C.0.1444-"L1$pb"+32(%eax), %ecx + movl %ecx, 40(%esp) + movl _C.0.1444-"L1$pb"+20(%eax), %ecx + movl %ecx, 28(%esp) + movl _C.0.1444-"L1$pb"+36(%eax), %ecx + movl %ecx, 44(%esp) + movl _C.0.1444-"L1$pb"+44(%eax), %ecx + movl %ecx, 52(%esp) + movl _C.0.1444-"L1$pb"+40(%eax), %ecx + movl %ecx, 48(%esp) + movl _C.0.1444-"L1$pb"+12(%eax), %ecx + movl %ecx, 20(%esp) + movl _C.0.1444-"L1$pb"+4(%eax), %ecx +... + +instead of: + movl $1, 16(%esp) + movl $0, 20(%esp) + movl $1, 24(%esp) + movl $0, 28(%esp) + movl $1, 32(%esp) + movl $0, 36(%esp) + ... + +//===---------------------------------------------------------------------===// + +http://llvm.org/PR717: + +The following code should compile into "ret int undef". Instead, LLVM +produces "ret int 0": + +int f() { + int x = 4; + int y; + if (x == 3) y = 0; + return y; +} + +//===---------------------------------------------------------------------===// + +The loop unroller should partially unroll loops (instead of peeling them) +when code growth isn't too bad and when an unroll count allows simplification +of some code within the loop. One trivial example is: + +#include +int main() { + int nRet = 17; + int nLoop; + for ( nLoop = 0; nLoop < 1000; nLoop++ ) { + if ( nLoop & 1 ) + nRet += 2; + else + nRet -= 1; + } + return nRet; +} + +Unrolling by 2 would eliminate the '&1' in both copies, leading to a net +reduction in code size. The resultant code would then also be suitable for +exit value computation. + +//===---------------------------------------------------------------------===// + +We miss a bunch of rotate opportunities on various targets, including ppc, x86, +etc. On X86, we miss a bunch of 'rotate by variable' cases because the rotate +matching code in dag combine doesn't look through truncates aggressively +enough. Here are some testcases reduces from GCC PR17886: + +unsigned long long f(unsigned long long x, int y) { + return (x << y) | (x >> 64-y); +} +unsigned f2(unsigned x, int y){ + return (x << y) | (x >> 32-y); +} +unsigned long long f3(unsigned long long x){ + int y = 9; + return (x << y) | (x >> 64-y); +} +unsigned f4(unsigned x){ + int y = 10; + return (x << y) | (x >> 32-y); +} +unsigned long long f5(unsigned long long x, unsigned long long y) { + return (x << 8) | ((y >> 48) & 0xffull); +} +unsigned long long f6(unsigned long long x, unsigned long long y, int z) { + switch(z) { + case 1: + return (x << 8) | ((y >> 48) & 0xffull); + case 2: + return (x << 16) | ((y >> 40) & 0xffffull); + case 3: + return (x << 24) | ((y >> 32) & 0xffffffull); + case 4: + return (x << 32) | ((y >> 24) & 0xffffffffull); + default: + return (x << 40) | ((y >> 16) & 0xffffffffffull); + } +} + +On X86-64, we only handle f2/f3/f4 right. On x86-32, a few of these +generate truly horrible code, instead of using shld and friends. On +ARM, we end up with calls to L___lshrdi3/L___ashldi3 in f, which is +badness. PPC64 misses f, f5 and f6. CellSPU aborts in isel. + +//===---------------------------------------------------------------------===// + +We do a number of simplifications in simplify libcalls to strength reduce +standard library functions, but we don't currently merge them together. For +example, it is useful to merge memcpy(a,b,strlen(b)) -> strcpy. This can only +be done safely if "b" isn't modified between the strlen and memcpy of course. + +//===---------------------------------------------------------------------===// + +Reassociate should turn things like: + +int factorial(int X) { + return X*X*X*X*X*X*X*X; +} + +into llvm.powi calls, allowing the code generator to produce balanced +multiplication trees. + +//===---------------------------------------------------------------------===// + +We generate a horrible libcall for llvm.powi. For example, we compile: + +#include +double f(double a) { return std::pow(a, 4); } + +into: + +__Z1fd: + subl $12, %esp + movsd 16(%esp), %xmm0 + movsd %xmm0, (%esp) + movl $4, 8(%esp) + call L___powidf2$stub + addl $12, %esp + ret + +GCC produces: + +__Z1fd: + subl $12, %esp + movsd 16(%esp), %xmm0 + mulsd %xmm0, %xmm0 + mulsd %xmm0, %xmm0 + movsd %xmm0, (%esp) + fldl (%esp) + addl $12, %esp + ret + +//===---------------------------------------------------------------------===// + +We compile this program: (from GCC PR11680) +http://gcc.gnu.org/bugzilla/attachment.cgi?id=4487 + +Into code that runs the same speed in fast/slow modes, but both modes run 2x +slower than when compile with GCC (either 4.0 or 4.2): + +$ llvm-g++ perf.cpp -O3 -fno-exceptions +$ time ./a.out fast +1.821u 0.003s 0:01.82 100.0% 0+0k 0+0io 0pf+0w + +$ g++ perf.cpp -O3 -fno-exceptions +$ time ./a.out fast +0.821u 0.001s 0:00.82 100.0% 0+0k 0+0io 0pf+0w + +It looks like we are making the same inlining decisions, so this may be raw +codegen badness or something else (haven't investigated). + +//===---------------------------------------------------------------------===// + +We miss some instcombines for stuff like this: +void bar (void); +void foo (unsigned int a) { + /* This one is equivalent to a >= (3 << 2). */ + if ((a >> 2) >= 3) + bar (); +} + +A few other related ones are in GCC PR14753. + +//===---------------------------------------------------------------------===// + +Divisibility by constant can be simplified (according to GCC PR12849) from +being a mulhi to being a mul lo (cheaper). Testcase: + +void bar(unsigned n) { + if (n % 3 == 0) + true(); +} + +I think this basically amounts to a dag combine to simplify comparisons against +multiply hi's into a comparison against the mullo. + +//===---------------------------------------------------------------------===// + +Better mod/ref analysis for scanf would allow us to eliminate the vtable and a +bunch of other stuff from this example (see PR1604): + +#include +struct test { + int val; + virtual ~test() {} +}; + +int main() { + test t; + std::scanf("%d", &t.val); + std::printf("%d\n", t.val); +} + +//===---------------------------------------------------------------------===// + +Instcombine will merge comparisons like (x >= 10) && (x < 20) by producing (x - +10) u< 10, but only when the comparisons have matching sign. + +This could be converted with a similiar technique. (PR1941) + +define i1 @test(i8 %x) { + %A = icmp uge i8 %x, 5 + %B = icmp slt i8 %x, 20 + %C = and i1 %A, %B + ret i1 %C +} + +//===---------------------------------------------------------------------===// + +These functions perform the same computation, but produce different assembly. + +define i8 @select(i8 %x) readnone nounwind { + %A = icmp ult i8 %x, 250 + %B = select i1 %A, i8 0, i8 1 + ret i8 %B +} + +define i8 @addshr(i8 %x) readnone nounwind { + %A = zext i8 %x to i9 + %B = add i9 %A, 6 ;; 256 - 250 == 6 + %C = lshr i9 %B, 8 + %D = trunc i9 %C to i8 + ret i8 %D +} + +//===---------------------------------------------------------------------===// + +From gcc bug 24696: +int +f (unsigned long a, unsigned long b, unsigned long c) +{ + return ((a & (c - 1)) != 0) || ((b & (c - 1)) != 0); +} +int +f (unsigned long a, unsigned long b, unsigned long c) +{ + return ((a & (c - 1)) != 0) | ((b & (c - 1)) != 0); +} +Both should combine to ((a|b) & (c-1)) != 0. Currently not optimized with +"clang -emit-llvm-bc | opt -std-compile-opts". + +//===---------------------------------------------------------------------===// + +From GCC Bug 20192: +#define PMD_MASK (~((1UL << 23) - 1)) +void clear_pmd_range(unsigned long start, unsigned long end) +{ + if (!(start & ~PMD_MASK) && !(end & ~PMD_MASK)) + f(); +} +The expression should optimize to something like +"!((start|end)&~PMD_MASK). Currently not optimized with "clang +-emit-llvm-bc | opt -std-compile-opts". + +//===---------------------------------------------------------------------===// + +From GCC Bug 15241: +unsigned int +foo (unsigned int a, unsigned int b) +{ + if (a <= 7 && b <= 7) + baz (); +} +Should combine to "(a|b) <= 7". Currently not optimized with "clang +-emit-llvm-bc | opt -std-compile-opts". + +//===---------------------------------------------------------------------===// + +From GCC Bug 3756: +int +pn (int n) +{ + return (n >= 0 ? 1 : -1); +} +Should combine to (n >> 31) | 1. Currently not optimized with "clang +-emit-llvm-bc | opt -std-compile-opts | llc". + +//===---------------------------------------------------------------------===// + +From GCC Bug 28685: +int test(int a, int b) +{ + int lt = a < b; + int eq = a == b; + + return (lt || eq); +} +Should combine to "a <= b". Currently not optimized with "clang +-emit-llvm-bc | opt -std-compile-opts | llc". + +//===---------------------------------------------------------------------===// + +void a(int variable) +{ + if (variable == 4 || variable == 6) + bar(); +} +This should optimize to "if ((variable | 2) == 6)". Currently not +optimized with "clang -emit-llvm-bc | opt -std-compile-opts | llc". + +//===---------------------------------------------------------------------===// + +unsigned int f(unsigned int i, unsigned int n) {++i; if (i == n) ++i; return +i;} +unsigned int f2(unsigned int i, unsigned int n) {++i; i += i == n; return i;} +These should combine to the same thing. Currently, the first function +produces better code on X86. + +//===---------------------------------------------------------------------===// + +From GCC Bug 15784: +#define abs(x) x>0?x:-x +int f(int x, int y) +{ + return (abs(x)) >= 0; +} +This should optimize to x == INT_MIN. (With -fwrapv.) Currently not +optimized with "clang -emit-llvm-bc | opt -std-compile-opts". + +//===---------------------------------------------------------------------===// + +From GCC Bug 14753: +void +rotate_cst (unsigned int a) +{ + a = (a << 10) | (a >> 22); + if (a == 123) + bar (); +} +void +minus_cst (unsigned int a) +{ + unsigned int tem; + + tem = 20 - a; + if (tem == 5) + bar (); +} +void +mask_gt (unsigned int a) +{ + /* This is equivalent to a > 15. */ + if ((a & ~7) > 8) + bar (); +} +void +rshift_gt (unsigned int a) +{ + /* This is equivalent to a > 23. */ + if ((a >> 2) > 5) + bar (); +} +All should simplify to a single comparison. All of these are +currently not optimized with "clang -emit-llvm-bc | opt +-std-compile-opts". + +//===---------------------------------------------------------------------===// + +From GCC Bug 32605: +int c(int* x) {return (char*)x+2 == (char*)x;} +Should combine to 0. Currently not optimized with "clang +-emit-llvm-bc | opt -std-compile-opts" (although llc can optimize it). + +//===---------------------------------------------------------------------===// + +int a(unsigned char* b) {return *b > 99;} +There's an unnecessary zext in the generated code with "clang +-emit-llvm-bc | opt -std-compile-opts". + +//===---------------------------------------------------------------------===// + +int a(unsigned b) {return ((b << 31) | (b << 30)) >> 31;} +Should be combined to "((b >> 1) | b) & 1". Currently not optimized +with "clang -emit-llvm-bc | opt -std-compile-opts". + +//===---------------------------------------------------------------------===// + +unsigned a(unsigned x, unsigned y) { return x | (y & 1) | (y & 2);} +Should combine to "x | (y & 3)". Currently not optimized with "clang +-emit-llvm-bc | opt -std-compile-opts". + +//===---------------------------------------------------------------------===// + +unsigned a(unsigned a) {return ((a | 1) & 3) | (a & -4);} +Should combine to "a | 1". Currently not optimized with "clang +-emit-llvm-bc | opt -std-compile-opts". + +//===---------------------------------------------------------------------===// + +int a(int a, int b, int c) {return (~a & c) | ((c|a) & b);} +Should fold to "(~a & c) | (a & b)". Currently not optimized with +"clang -emit-llvm-bc | opt -std-compile-opts". + +//===---------------------------------------------------------------------===// + +int a(int a,int b) {return (~(a|b))|a;} +Should fold to "a|~b". Currently not optimized with "clang +-emit-llvm-bc | opt -std-compile-opts". + +//===---------------------------------------------------------------------===// + +int a(int a, int b) {return (a&&b) || (a&&!b);} +Should fold to "a". Currently not optimized with "clang -emit-llvm-bc +| opt -std-compile-opts". + +//===---------------------------------------------------------------------===// + +int a(int a, int b, int c) {return (a&&b) || (!a&&c);} +Should fold to "a ? b : c", or at least something sane. Currently not +optimized with "clang -emit-llvm-bc | opt -std-compile-opts". + +//===---------------------------------------------------------------------===// + +int a(int a, int b, int c) {return (a&&b) || (a&&c) || (a&&b&&c);} +Should fold to a && (b || c). Currently not optimized with "clang +-emit-llvm-bc | opt -std-compile-opts". + +//===---------------------------------------------------------------------===// + +int a(int x) {return x | ((x & 8) ^ 8);} +Should combine to x | 8. Currently not optimized with "clang +-emit-llvm-bc | opt -std-compile-opts". + +//===---------------------------------------------------------------------===// + +int a(int x) {return x ^ ((x & 8) ^ 8);} +Should also combine to x | 8. Currently not optimized with "clang +-emit-llvm-bc | opt -std-compile-opts". + +//===---------------------------------------------------------------------===// + +int a(int x) {return (x & 8) == 0 ? -1 : -9;} +Should combine to (x | -9) ^ 8. Currently not optimized with "clang +-emit-llvm-bc | opt -std-compile-opts". + +//===---------------------------------------------------------------------===// + +int a(int x) {return (x & 8) == 0 ? -9 : -1;} +Should combine to x | -9. Currently not optimized with "clang +-emit-llvm-bc | opt -std-compile-opts". + +//===---------------------------------------------------------------------===// + +int a(int x) {return ((x | -9) ^ 8) & x;} +Should combine to x & -9. Currently not optimized with "clang +-emit-llvm-bc | opt -std-compile-opts". + +//===---------------------------------------------------------------------===// + +unsigned a(unsigned a) {return a * 0x11111111 >> 28 & 1;} +Should combine to "a * 0x88888888 >> 31". Currently not optimized +with "clang -emit-llvm-bc | opt -std-compile-opts". + +//===---------------------------------------------------------------------===// + +unsigned a(char* x) {if ((*x & 32) == 0) return b();} +There's an unnecessary zext in the generated code with "clang +-emit-llvm-bc | opt -std-compile-opts". + +//===---------------------------------------------------------------------===// + +unsigned a(unsigned long long x) {return 40 * (x >> 1);} +Should combine to "20 * (((unsigned)x) & -2)". Currently not +optimized with "clang -emit-llvm-bc | opt -std-compile-opts". + +//===---------------------------------------------------------------------===// + +This was noticed in the entryblock for grokdeclarator in 403.gcc: + + %tmp = icmp eq i32 %decl_context, 4 + %decl_context_addr.0 = select i1 %tmp, i32 3, i32 %decl_context + %tmp1 = icmp eq i32 %decl_context_addr.0, 1 + %decl_context_addr.1 = select i1 %tmp1, i32 0, i32 %decl_context_addr.0 + +tmp1 should be simplified to something like: + (!tmp || decl_context == 1) + +This allows recursive simplifications, tmp1 is used all over the place in +the function, e.g. by: + + %tmp23 = icmp eq i32 %decl_context_addr.1, 0 ; [#uses=1] + %tmp24 = xor i1 %tmp1, true ; [#uses=1] + %or.cond8 = and i1 %tmp23, %tmp24 ; [#uses=1] + +later. + +//===---------------------------------------------------------------------===// + +Store sinking: This code: + +void f (int n, int *cond, int *res) { + int i; + *res = 0; + for (i = 0; i < n; i++) + if (*cond) + *res ^= 234; /* (*) */ +} + +On this function GVN hoists the fully redundant value of *res, but nothing +moves the store out. This gives us this code: + +bb: ; preds = %bb2, %entry + %.rle = phi i32 [ 0, %entry ], [ %.rle6, %bb2 ] + %i.05 = phi i32 [ 0, %entry ], [ %indvar.next, %bb2 ] + %1 = load i32* %cond, align 4 + %2 = icmp eq i32 %1, 0 + br i1 %2, label %bb2, label %bb1 + +bb1: ; preds = %bb + %3 = xor i32 %.rle, 234 + store i32 %3, i32* %res, align 4 + br label %bb2 + +bb2: ; preds = %bb, %bb1 + %.rle6 = phi i32 [ %3, %bb1 ], [ %.rle, %bb ] + %indvar.next = add i32 %i.05, 1 + %exitcond = icmp eq i32 %indvar.next, %n + br i1 %exitcond, label %return, label %bb + +DSE should sink partially dead stores to get the store out of the loop. + +Here's another partial dead case: +http://gcc.gnu.org/bugzilla/show_bug.cgi?id=12395 + +//===---------------------------------------------------------------------===// + +Scalar PRE hoists the mul in the common block up to the else: + +int test (int a, int b, int c, int g) { + int d, e; + if (a) + d = b * c; + else + d = b - c; + e = b * c + g; + return d + e; +} + +It would be better to do the mul once to reduce codesize above the if. +This is GCC PR38204. + +//===---------------------------------------------------------------------===// + +GCC PR37810 is an interesting case where we should sink load/store reload +into the if block and outside the loop, so we don't reload/store it on the +non-call path. + +for () { + *P += 1; + if () + call(); + else + ... +-> +tmp = *P +for () { + tmp += 1; + if () { + *P = tmp; + call(); + tmp = *P; + } else ... +} +*P = tmp; + +We now hoist the reload after the call (Transforms/GVN/lpre-call-wrap.ll), but +we don't sink the store. We need partially dead store sinking. + +//===---------------------------------------------------------------------===// + +[PHI TRANSLATE GEPs] + +GCC PR37166: Sinking of loads prevents SROA'ing the "g" struct on the stack +leading to excess stack traffic. This could be handled by GVN with some crazy +symbolic phi translation. The code we get looks like (g is on the stack): + +bb2: ; preds = %bb1 +.. + %9 = getelementptr %struct.f* %g, i32 0, i32 0 + store i32 %8, i32* %9, align bel %bb3 + +bb3: ; preds = %bb1, %bb2, %bb + %c_addr.0 = phi %struct.f* [ %g, %bb2 ], [ %c, %bb ], [ %c, %bb1 ] + %b_addr.0 = phi %struct.f* [ %b, %bb2 ], [ %g, %bb ], [ %b, %bb1 ] + %10 = getelementptr %struct.f* %c_addr.0, i32 0, i32 0 + %11 = load i32* %10, align 4 + +%11 is fully redundant, an in BB2 it should have the value %8. + +GCC PR33344 is a similar case. + + +//===---------------------------------------------------------------------===// + +There are many load PRE testcases in testsuite/gcc.dg/tree-ssa/loadpre* in the +GCC testsuite. There are many pre testcases as ssa-pre-*.c + +//===---------------------------------------------------------------------===// + +There are some interesting cases in testsuite/gcc.dg/tree-ssa/pred-comm* in the +GCC testsuite. For example, predcom-1.c is: + + for (i = 2; i < 1000; i++) + fib[i] = (fib[i-1] + fib[i - 2]) & 0xffff; + +which compiles into: + +bb1: ; preds = %bb1, %bb1.thread + %indvar = phi i32 [ 0, %bb1.thread ], [ %0, %bb1 ] + %i.0.reg2mem.0 = add i32 %indvar, 2 + %0 = add i32 %indvar, 1 ; [#uses=3] + %1 = getelementptr [1000 x i32]* @fib, i32 0, i32 %0 + %2 = load i32* %1, align 4 ; [#uses=1] + %3 = getelementptr [1000 x i32]* @fib, i32 0, i32 %indvar + %4 = load i32* %3, align 4 ; [#uses=1] + %5 = add i32 %4, %2 ; [#uses=1] + %6 = and i32 %5, 65535 ; [#uses=1] + %7 = getelementptr [1000 x i32]* @fib, i32 0, i32 %i.0.reg2mem.0 + store i32 %6, i32* %7, align 4 + %exitcond = icmp eq i32 %0, 998 ; [#uses=1] + br i1 %exitcond, label %return, label %bb1 + +This is basically: + LOAD fib[i+1] + LOAD fib[i] + STORE fib[i+2] + +instead of handling this as a loop or other xform, all we'd need to do is teach +load PRE to phi translate the %0 add (i+1) into the predecessor as (i'+1+1) = +(i'+2) (where i' is the previous iteration of i). This would find the store +which feeds it. + +predcom-2.c is apparently the same as predcom-1.c +predcom-3.c is very similar but needs loads feeding each other instead of +store->load. +predcom-4.c seems the same as the rest. + + +//===---------------------------------------------------------------------===// + +Other simple load PRE cases: +http://gcc.gnu.org/bugzilla/show_bug.cgi?id=35287 [LPRE crit edge splitting] + +http://gcc.gnu.org/bugzilla/show_bug.cgi?id=34677 (licm does this, LPRE crit edge) + llvm-gcc t2.c -S -o - -O0 -emit-llvm | llvm-as | opt -mem2reg -simplifycfg -gvn | llvm-dis + +//===---------------------------------------------------------------------===// + +Type based alias analysis: +http://gcc.gnu.org/bugzilla/show_bug.cgi?id=14705 + +//===---------------------------------------------------------------------===// + +A/B get pinned to the stack because we turn an if/then into a select instead +of PRE'ing the load/store. This may be fixable in instcombine: +http://gcc.gnu.org/bugzilla/show_bug.cgi?id=37892 + +struct X { int i; }; +int foo (int x) { + struct X a; + struct X b; + struct X *p; + a.i = 1; + b.i = 2; + if (x) + p = &a; + else + p = &b; + return p->i; +} + +//===---------------------------------------------------------------------===// + +Interesting missed case because of control flow flattening (should be 2 loads): +http://gcc.gnu.org/bugzilla/show_bug.cgi?id=26629 +With: llvm-gcc t2.c -S -o - -O0 -emit-llvm | llvm-as | + opt -mem2reg -gvn -instcombine | llvm-dis +we miss it because we need 1) GEP PHI TRAN, 2) CRIT EDGE 3) MULTIPLE DIFFERENT +VALS PRODUCED BY ONE BLOCK OVER DIFFERENT PATHS + +//===---------------------------------------------------------------------===// + +http://gcc.gnu.org/bugzilla/show_bug.cgi?id=19633 +We could eliminate the branch condition here, loading from null is undefined: + +struct S { int w, x, y, z; }; +struct T { int r; struct S s; }; +void bar (struct S, int); +void foo (int a, struct T b) +{ + struct S *c = 0; + if (a) + c = &b.s; + bar (*c, a); +} + +//===---------------------------------------------------------------------===// + +simplifylibcalls should do several optimizations for strspn/strcspn: + +strcspn(x, "") -> strlen(x) +strcspn("", x) -> 0 +strspn("", x) -> 0 +strspn(x, "") -> strlen(x) +strspn(x, "a") -> strchr(x, 'a')-x + +strcspn(x, "a") -> inlined loop for up to 3 letters (similarly for strspn): + +size_t __strcspn_c3 (__const char *__s, int __reject1, int __reject2, + int __reject3) { + register size_t __result = 0; + while (__s[__result] != '\0' && __s[__result] != __reject1 && + __s[__result] != __reject2 && __s[__result] != __reject3) + ++__result; + return __result; +} + +This should turn into a switch on the character. See PR3253 for some notes on +codegen. + +456.hmmer apparently uses strcspn and strspn a lot. 471.omnetpp uses strspn. + +//===---------------------------------------------------------------------===// + +"gas" uses this idiom: + else if (strchr ("+-/*%|&^:[]()~", *intel_parser.op_string)) +.. + else if (strchr ("<>", *intel_parser.op_string) + +Those should be turned into a switch. + +//===---------------------------------------------------------------------===// + +252.eon contains this interesting code: + + %3072 = getelementptr [100 x i8]* %tempString, i32 0, i32 0 + %3073 = call i8* @strcpy(i8* %3072, i8* %3071) nounwind + %strlen = call i32 @strlen(i8* %3072) ; uses = 1 + %endptr = getelementptr [100 x i8]* %tempString, i32 0, i32 %strlen + call void @llvm.memcpy.i32(i8* %endptr, + i8* getelementptr ([5 x i8]* @"\01LC42", i32 0, i32 0), i32 5, i32 1) + %3074 = call i32 @strlen(i8* %endptr) nounwind readonly + +This is interesting for a couple reasons. First, in this: + + %3073 = call i8* @strcpy(i8* %3072, i8* %3071) nounwind + %strlen = call i32 @strlen(i8* %3072) + +The strlen could be replaced with: %strlen = sub %3072, %3073, because the +strcpy call returns a pointer to the end of the string. Based on that, the +endptr GEP just becomes equal to 3073, which eliminates a strlen call and GEP. + +Second, the memcpy+strlen strlen can be replaced with: + + %3074 = call i32 @strlen([5 x i8]* @"\01LC42") nounwind readonly + +Because the destination was just copied into the specified memory buffer. This, +in turn, can be constant folded to "4". + +In other code, it contains: + + %endptr6978 = bitcast i8* %endptr69 to i32* + store i32 7107374, i32* %endptr6978, align 1 + %3167 = call i32 @strlen(i8* %endptr69) nounwind readonly + +Which could also be constant folded. Whatever is producing this should probably +be fixed to leave this as a memcpy from a string. + +Further, eon also has an interesting partially redundant strlen call: + +bb8: ; preds = %_ZN18eonImageCalculatorC1Ev.exit + %682 = getelementptr i8** %argv, i32 6 ; [#uses=2] + %683 = load i8** %682, align 4 ; [#uses=4] + %684 = load i8* %683, align 1 ; [#uses=1] + %685 = icmp eq i8 %684, 0 ; [#uses=1] + br i1 %685, label %bb10, label %bb9 + +bb9: ; preds = %bb8 + %686 = call i32 @strlen(i8* %683) nounwind readonly + %687 = icmp ugt i32 %686, 254 ; [#uses=1] + br i1 %687, label %bb10, label %bb11 + +bb10: ; preds = %bb9, %bb8 + %688 = call i32 @strlen(i8* %683) nounwind readonly + +This could be eliminated by doing the strlen once in bb8, saving code size and +improving perf on the bb8->9->10 path. + +//===---------------------------------------------------------------------===// + +I see an interesting fully redundant call to strlen left in 186.crafty:InputMove +which looks like: + %movetext11 = getelementptr [128 x i8]* %movetext, i32 0, i32 0 + + +bb62: ; preds = %bb55, %bb53 + %promote.0 = phi i32 [ %169, %bb55 ], [ 0, %bb53 ] + %171 = call i32 @strlen(i8* %movetext11) nounwind readonly align 1 + %172 = add i32 %171, -1 ; [#uses=1] + %173 = getelementptr [128 x i8]* %movetext, i32 0, i32 %172 + +... no stores ... + br i1 %or.cond, label %bb65, label %bb72 + +bb65: ; preds = %bb62 + store i8 0, i8* %173, align 1 + br label %bb72 + +bb72: ; preds = %bb65, %bb62 + %trank.1 = phi i32 [ %176, %bb65 ], [ -1, %bb62 ] + %177 = call i32 @strlen(i8* %movetext11) nounwind readonly align 1 + +Note that on the bb62->bb72 path, that the %177 strlen call is partially +redundant with the %171 call. At worst, we could shove the %177 strlen call +up into the bb65 block moving it out of the bb62->bb72 path. However, note +that bb65 stores to the string, zeroing out the last byte. This means that on +that path the value of %177 is actually just %171-1. A sub is cheaper than a +strlen! + +This pattern repeats several times, basically doing: + + A = strlen(P); + P[A-1] = 0; + B = strlen(P); + where it is "obvious" that B = A-1. + +//===---------------------------------------------------------------------===// + +186.crafty contains this interesting pattern: + +%77 = call i8* @strstr(i8* getelementptr ([6 x i8]* @"\01LC5", i32 0, i32 0), + i8* %30) +%phitmp648 = icmp eq i8* %77, getelementptr ([6 x i8]* @"\01LC5", i32 0, i32 0) +br i1 %phitmp648, label %bb70, label %bb76 + +bb70: ; preds = %OptionMatch.exit91, %bb69 + %78 = call i32 @strlen(i8* %30) nounwind readonly align 1 ; [#uses=1] + +This is basically: + cststr = "abcdef"; + if (strstr(cststr, P) == cststr) { + x = strlen(P); + ... + +The strstr call would be significantly cheaper written as: + +cststr = "abcdef"; +if (memcmp(P, str, strlen(P))) + x = strlen(P); + +This is memcmp+strlen instead of strstr. This also makes the strlen fully +redundant. + +//===---------------------------------------------------------------------===// + +186.crafty also contains this code: + +%1906 = call i32 @strlen(i8* getelementptr ([32 x i8]* @pgn_event, i32 0,i32 0)) +%1907 = getelementptr [32 x i8]* @pgn_event, i32 0, i32 %1906 +%1908 = call i8* @strcpy(i8* %1907, i8* %1905) nounwind align 1 +%1909 = call i32 @strlen(i8* getelementptr ([32 x i8]* @pgn_event, i32 0,i32 0)) +%1910 = getelementptr [32 x i8]* @pgn_event, i32 0, i32 %1909 + +The last strlen is computable as 1908-@pgn_event, which means 1910=1908. + +//===---------------------------------------------------------------------===// + +186.crafty has this interesting pattern with the "out.4543" variable: + +call void @llvm.memcpy.i32( + i8* getelementptr ([10 x i8]* @out.4543, i32 0, i32 0), + i8* getelementptr ([7 x i8]* @"\01LC28700", i32 0, i32 0), i32 7, i32 1) +%101 = call@printf(i8* ... @out.4543, i32 0, i32 0)) nounwind + +It is basically doing: + + memcpy(globalarray, "string"); + printf(..., globalarray); + +Anyway, by knowing that printf just reads the memory and forward substituting +the string directly into the printf, this eliminates reads from globalarray. +Since this pattern occurs frequently in crafty (due to the "DisplayTime" and +other similar functions) there are many stores to "out". Once all the printfs +stop using "out", all that is left is the memcpy's into it. This should allow +globalopt to remove the "stored only" global. + +//===---------------------------------------------------------------------===// + +This code: + +define inreg i32 @foo(i8* inreg %p) nounwind { + %tmp0 = load i8* %p + %tmp1 = ashr i8 %tmp0, 5 + %tmp2 = sext i8 %tmp1 to i32 + ret i32 %tmp2 +} + +could be dagcombine'd to a sign-extending load with a shift. +For example, on x86 this currently gets this: + + movb (%eax), %al + sarb $5, %al + movsbl %al, %eax + +while it could get this: + + movsbl (%eax), %eax + sarl $5, %eax + +//===---------------------------------------------------------------------===// + +GCC PR31029: + +int test(int x) { return 1-x == x; } // --> return false +int test2(int x) { return 2-x == x; } // --> return x == 1 ? + +Always foldable for odd constants, what is the rule for even? + +//===---------------------------------------------------------------------===// + +PR 3381: GEP to field of size 0 inside a struct could be turned into GEP +for next field in struct (which is at same address). + +For example: store of float into { {{}}, float } could be turned into a store to +the float directly. + +//===---------------------------------------------------------------------===// + +#include +double foo(double a) { return sin(a); } + +This compiles into this on x86-64 Linux: +foo: + subq $8, %rsp + call sin + addq $8, %rsp + ret +vs: + +foo: + jmp sin + +//===---------------------------------------------------------------------===// + +The arg promotion pass should make use of nocapture to make its alias analysis +stuff much more precise. + +//===---------------------------------------------------------------------===// + +The following functions should be optimized to use a select instead of a +branch (from gcc PR40072): + +char char_int(int m) {if(m>7) return 0; return m;} +int int_char(char m) {if(m>7) return 0; return m;} + +//===---------------------------------------------------------------------===// + +int func(int a, int b) { if (a & 0x80) b |= 0x80; else b &= ~0x80; return b; } + +Generates this: + +define i32 @func(i32 %a, i32 %b) nounwind readnone ssp { +entry: + %0 = and i32 %a, 128 ; [#uses=1] + %1 = icmp eq i32 %0, 0 ; [#uses=1] + %2 = or i32 %b, 128 ; [#uses=1] + %3 = and i32 %b, -129 ; [#uses=1] + %b_addr.0 = select i1 %1, i32 %3, i32 %2 ; [#uses=1] + ret i32 %b_addr.0 +} + +However, it's functionally equivalent to: + + b = (b & ~0x80) | (a & 0x80); + +Which generates this: + +define i32 @func(i32 %a, i32 %b) nounwind readnone ssp { +entry: + %0 = and i32 %b, -129 ; [#uses=1] + %1 = and i32 %a, 128 ; [#uses=1] + %2 = or i32 %0, %1 ; [#uses=1] + ret i32 %2 +} + +This can be generalized for other forms: + + b = (b & ~0x80) | (a & 0x40) << 1; + +//===---------------------------------------------------------------------===// + +These two functions produce different code. They shouldn't: + +#include + +uint8_t p1(uint8_t b, uint8_t a) { + b = (b & ~0xc0) | (a & 0xc0); + return (b); +} + +uint8_t p2(uint8_t b, uint8_t a) { + b = (b & ~0x40) | (a & 0x40); + b = (b & ~0x80) | (a & 0x80); + return (b); +} + +define zeroext i8 @p1(i8 zeroext %b, i8 zeroext %a) nounwind readnone ssp { +entry: + %0 = and i8 %b, 63 ; [#uses=1] + %1 = and i8 %a, -64 ; [#uses=1] + %2 = or i8 %1, %0 ; [#uses=1] + ret i8 %2 +} + +define zeroext i8 @p2(i8 zeroext %b, i8 zeroext %a) nounwind readnone ssp { +entry: + %0 = and i8 %b, 63 ; [#uses=1] + %.masked = and i8 %a, 64 ; [#uses=1] + %1 = and i8 %a, -128 ; [#uses=1] + %2 = or i8 %1, %0 ; [#uses=1] + %3 = or i8 %2, %.masked ; [#uses=1] + ret i8 %3 +} + +//===---------------------------------------------------------------------===// + +IPSCCP does not currently propagate argument dependent constants through +functions where it does not not all of the callers. This includes functions +with normal external linkage as well as templates, C99 inline functions etc. +Specifically, it does nothing to: + +define i32 @test(i32 %x, i32 %y, i32 %z) nounwind { +entry: + %0 = add nsw i32 %y, %z + %1 = mul i32 %0, %x + %2 = mul i32 %y, %z + %3 = add nsw i32 %1, %2 + ret i32 %3 +} + +define i32 @test2() nounwind { +entry: + %0 = call i32 @test(i32 1, i32 2, i32 4) nounwind + ret i32 %0 +} + +It would be interesting extend IPSCCP to be able to handle simple cases like +this, where all of the arguments to a call are constant. Because IPSCCP runs +before inlining, trivial templates and inline functions are not yet inlined. +The results for a function + set of constant arguments should be memoized in a +map. + +//===---------------------------------------------------------------------===// + +The libcall constant folding stuff should be moved out of SimplifyLibcalls into +libanalysis' constantfolding logic. This would allow IPSCCP to be able to +handle simple things like this: + +static int foo(const char *X) { return strlen(X); } +int bar() { return foo("abcd"); } + +//===---------------------------------------------------------------------===// + +InstCombine should use SimplifyDemandedBits to remove the or instruction: + +define i1 @test(i8 %x, i8 %y) { + %A = or i8 %x, 1 + %B = icmp ugt i8 %A, 3 + ret i1 %B +} + +Currently instcombine calls SimplifyDemandedBits with either all bits or just +the sign bit, if the comparison is obviously a sign test. In this case, we only +need all but the bottom two bits from %A, and if we gave that mask to SDB it +would delete the or instruction for us. + +//===---------------------------------------------------------------------===// diff --git a/libclamav/c++/llvm/lib/Target/SubtargetFeature.cpp b/libclamav/c++/llvm/lib/Target/SubtargetFeature.cpp new file mode 100644 index 000000000..590574ef3 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/SubtargetFeature.cpp @@ -0,0 +1,386 @@ +//===- SubtargetFeature.cpp - CPU characteristics Implementation ----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the SubtargetFeature interface. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Target/SubtargetFeature.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/ADT/StringExtras.h" +#include +#include +#include +using namespace llvm; + +//===----------------------------------------------------------------------===// +// Static Helper Functions +//===----------------------------------------------------------------------===// + +/// hasFlag - Determine if a feature has a flag; '+' or '-' +/// +static inline bool hasFlag(const std::string &Feature) { + assert(!Feature.empty() && "Empty string"); + // Get first character + char Ch = Feature[0]; + // Check if first character is '+' or '-' flag + return Ch == '+' || Ch =='-'; +} + +/// StripFlag - Return string stripped of flag. +/// +static inline std::string StripFlag(const std::string &Feature) { + return hasFlag(Feature) ? Feature.substr(1) : Feature; +} + +/// isEnabled - Return true if enable flag; '+'. +/// +static inline bool isEnabled(const std::string &Feature) { + assert(!Feature.empty() && "Empty string"); + // Get first character + char Ch = Feature[0]; + // Check if first character is '+' for enabled + return Ch == '+'; +} + +/// PrependFlag - Return a string with a prepended flag; '+' or '-'. +/// +static inline std::string PrependFlag(const std::string &Feature, + bool IsEnabled) { + assert(!Feature.empty() && "Empty string"); + if (hasFlag(Feature)) return Feature; + return std::string(IsEnabled ? "+" : "-") + Feature; +} + +/// Split - Splits a string of comma separated items in to a vector of strings. +/// +static void Split(std::vector &V, const std::string &S) { + // Start at beginning of string. + size_t Pos = 0; + while (true) { + // Find the next comma + size_t Comma = S.find(',', Pos); + // If no comma found then the the rest of the string is used + if (Comma == std::string::npos) { + // Add string to vector + V.push_back(S.substr(Pos)); + break; + } + // Otherwise add substring to vector + V.push_back(S.substr(Pos, Comma - Pos)); + // Advance to next item + Pos = Comma + 1; + } +} + +/// Join a vector of strings to a string with a comma separating each element. +/// +static std::string Join(const std::vector &V) { + // Start with empty string. + std::string Result; + // If the vector is not empty + if (!V.empty()) { + // Start with the CPU feature + Result = V[0]; + // For each successive feature + for (size_t i = 1; i < V.size(); i++) { + // Add a comma + Result += ","; + // Add the feature + Result += V[i]; + } + } + // Return the features string + return Result; +} + +/// Adding features. +void SubtargetFeatures::AddFeature(const std::string &String, + bool IsEnabled) { + // Don't add empty features + if (!String.empty()) { + // Convert to lowercase, prepend flag and add to vector + Features.push_back(PrependFlag(LowercaseString(String), IsEnabled)); + } +} + +/// Find KV in array using binary search. +template const T *Find(const std::string &S, const T *A, size_t L) { + // Make the lower bound element we're looking for + T KV; + KV.Key = S.c_str(); + // Determine the end of the array + const T *Hi = A + L; + // Binary search the array + const T *F = std::lower_bound(A, Hi, KV); + // If not found then return NULL + if (F == Hi || std::string(F->Key) != S) return NULL; + // Return the found array item + return F; +} + +/// getLongestEntryLength - Return the length of the longest entry in the table. +/// +static size_t getLongestEntryLength(const SubtargetFeatureKV *Table, + size_t Size) { + size_t MaxLen = 0; + for (size_t i = 0; i < Size; i++) + MaxLen = std::max(MaxLen, std::strlen(Table[i].Key)); + return MaxLen; +} + +/// Display help for feature choices. +/// +static void Help(const SubtargetFeatureKV *CPUTable, size_t CPUTableSize, + const SubtargetFeatureKV *FeatTable, size_t FeatTableSize) { + // Determine the length of the longest CPU and Feature entries. + unsigned MaxCPULen = getLongestEntryLength(CPUTable, CPUTableSize); + unsigned MaxFeatLen = getLongestEntryLength(FeatTable, FeatTableSize); + + // Print the CPU table. + errs() << "Available CPUs for this target:\n\n"; + for (size_t i = 0; i != CPUTableSize; i++) + errs() << " " << CPUTable[i].Key + << std::string(MaxCPULen - std::strlen(CPUTable[i].Key), ' ') + << " - " << CPUTable[i].Desc << ".\n"; + errs() << "\n"; + + // Print the Feature table. + errs() << "Available features for this target:\n\n"; + for (size_t i = 0; i != FeatTableSize; i++) + errs() << " " << FeatTable[i].Key + << std::string(MaxFeatLen - std::strlen(FeatTable[i].Key), ' ') + << " - " << FeatTable[i].Desc << ".\n"; + errs() << "\n"; + + errs() << "Use +feature to enable a feature, or -feature to disable it.\n" + << "For example, llc -mcpu=mycpu -mattr=+feature1,-feature2\n"; + exit(1); +} + +//===----------------------------------------------------------------------===// +// SubtargetFeatures Implementation +//===----------------------------------------------------------------------===// + +SubtargetFeatures::SubtargetFeatures(const std::string &Initial) { + // Break up string into separate features + Split(Features, Initial); +} + + +std::string SubtargetFeatures::getString() const { + return Join(Features); +} +void SubtargetFeatures::setString(const std::string &Initial) { + // Throw out old features + Features.clear(); + // Break up string into separate features + Split(Features, LowercaseString(Initial)); +} + + +/// setCPU - Set the CPU string. Replaces previous setting. Setting to "" +/// clears CPU. +void SubtargetFeatures::setCPU(const std::string &String) { + Features[0] = LowercaseString(String); +} + + +/// setCPUIfNone - Setting CPU string only if no string is set. +/// +void SubtargetFeatures::setCPUIfNone(const std::string &String) { + if (Features[0].empty()) setCPU(String); +} + +/// getCPU - Returns current CPU. +/// +const std::string & SubtargetFeatures::getCPU() const { + return Features[0]; +} + + +/// SetImpliedBits - For each feature that is (transitively) implied by this +/// feature, set it. +/// +static +void SetImpliedBits(uint32_t &Bits, const SubtargetFeatureKV *FeatureEntry, + const SubtargetFeatureKV *FeatureTable, + size_t FeatureTableSize) { + for (size_t i = 0; i < FeatureTableSize; ++i) { + const SubtargetFeatureKV &FE = FeatureTable[i]; + + if (FeatureEntry->Value == FE.Value) continue; + + if (FeatureEntry->Implies & FE.Value) { + Bits |= FE.Value; + SetImpliedBits(Bits, &FE, FeatureTable, FeatureTableSize); + } + } +} + +/// ClearImpliedBits - For each feature that (transitively) implies this +/// feature, clear it. +/// +static +void ClearImpliedBits(uint32_t &Bits, const SubtargetFeatureKV *FeatureEntry, + const SubtargetFeatureKV *FeatureTable, + size_t FeatureTableSize) { + for (size_t i = 0; i < FeatureTableSize; ++i) { + const SubtargetFeatureKV &FE = FeatureTable[i]; + + if (FeatureEntry->Value == FE.Value) continue; + + if (FE.Implies & FeatureEntry->Value) { + Bits &= ~FE.Value; + ClearImpliedBits(Bits, &FE, FeatureTable, FeatureTableSize); + } + } +} + +/// getBits - Get feature bits. +/// +uint32_t SubtargetFeatures::getBits(const SubtargetFeatureKV *CPUTable, + size_t CPUTableSize, + const SubtargetFeatureKV *FeatureTable, + size_t FeatureTableSize) { + assert(CPUTable && "missing CPU table"); + assert(FeatureTable && "missing features table"); +#ifndef NDEBUG + for (size_t i = 1; i < CPUTableSize; i++) { + assert(strcmp(CPUTable[i - 1].Key, CPUTable[i].Key) < 0 && + "CPU table is not sorted"); + } + for (size_t i = 1; i < FeatureTableSize; i++) { + assert(strcmp(FeatureTable[i - 1].Key, FeatureTable[i].Key) < 0 && + "CPU features table is not sorted"); + } +#endif + uint32_t Bits = 0; // Resulting bits + + // Check if help is needed + if (Features[0] == "help") + Help(CPUTable, CPUTableSize, FeatureTable, FeatureTableSize); + + // Find CPU entry + const SubtargetFeatureKV *CPUEntry = + Find(Features[0], CPUTable, CPUTableSize); + // If there is a match + if (CPUEntry) { + // Set base feature bits + Bits = CPUEntry->Value; + + // Set the feature implied by this CPU feature, if any. + for (size_t i = 0; i < FeatureTableSize; ++i) { + const SubtargetFeatureKV &FE = FeatureTable[i]; + if (CPUEntry->Value & FE.Value) + SetImpliedBits(Bits, &FE, FeatureTable, FeatureTableSize); + } + } else { + errs() << "'" << Features[0] + << "' is not a recognized processor for this target" + << " (ignoring processor)\n"; + } + // Iterate through each feature + for (size_t i = 1; i < Features.size(); i++) { + const std::string &Feature = Features[i]; + + // Check for help + if (Feature == "+help") + Help(CPUTable, CPUTableSize, FeatureTable, FeatureTableSize); + + // Find feature in table. + const SubtargetFeatureKV *FeatureEntry = + Find(StripFlag(Feature), FeatureTable, FeatureTableSize); + // If there is a match + if (FeatureEntry) { + // Enable/disable feature in bits + if (isEnabled(Feature)) { + Bits |= FeatureEntry->Value; + + // For each feature that this implies, set it. + SetImpliedBits(Bits, FeatureEntry, FeatureTable, FeatureTableSize); + } else { + Bits &= ~FeatureEntry->Value; + + // For each feature that implies this, clear it. + ClearImpliedBits(Bits, FeatureEntry, FeatureTable, FeatureTableSize); + } + } else { + errs() << "'" << Feature + << "' is not a recognized feature for this target" + << " (ignoring feature)\n"; + } + } + + return Bits; +} + +/// Get info pointer +void *SubtargetFeatures::getInfo(const SubtargetInfoKV *Table, + size_t TableSize) { + assert(Table && "missing table"); +#ifndef NDEBUG + for (size_t i = 1; i < TableSize; i++) { + assert(strcmp(Table[i - 1].Key, Table[i].Key) < 0 && "Table is not sorted"); + } +#endif + + // Find entry + const SubtargetInfoKV *Entry = Find(Features[0], Table, TableSize); + + if (Entry) { + return Entry->Value; + } else { + errs() << "'" << Features[0] + << "' is not a recognized processor for this target" + << " (ignoring processor)\n"; + return NULL; + } +} + +/// print - Print feature string. +/// +void SubtargetFeatures::print(raw_ostream &OS) const { + for (size_t i = 0, e = Features.size(); i != e; ++i) + OS << Features[i] << " "; + OS << "\n"; +} + +/// dump - Dump feature info. +/// +void SubtargetFeatures::dump() const { + print(errs()); +} + +/// getDefaultSubtargetFeatures - Return a string listing +/// the features associated with the target triple. +/// +/// FIXME: This is an inelegant way of specifying the features of a +/// subtarget. It would be better if we could encode this information +/// into the IR. See . +/// +std::string SubtargetFeatures::getDefaultSubtargetFeatures( + const Triple& Triple) { + switch (Triple.getVendor()) { + case Triple::Apple: + switch (Triple.getArch()) { + case Triple::ppc: // powerpc-apple-* + return std::string("altivec"); + case Triple::ppc64: // powerpc64-apple-* + return std::string("64bit,altivec"); + default: + break; + } + break; + default: + break; + } + + return std::string(""); +} diff --git a/libclamav/c++/llvm/lib/Target/Target.cpp b/libclamav/c++/llvm/lib/Target/Target.cpp new file mode 100644 index 000000000..cc6be9fa7 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/Target.cpp @@ -0,0 +1,94 @@ +//===-- Target.cpp --------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the C bindings for libLLVMTarget.a, which implements +// target information. +// +//===----------------------------------------------------------------------===// + +#include "llvm-c/Target.h" +#include "llvm/PassManager.h" +#include "llvm/Target/TargetData.h" +#include + +using namespace llvm; + +LLVMTargetDataRef LLVMCreateTargetData(const char *StringRep) { + return wrap(new TargetData(StringRep)); +} + +void LLVMAddTargetData(LLVMTargetDataRef TD, LLVMPassManagerRef PM) { + unwrap(PM)->add(new TargetData(*unwrap(TD))); +} + +char *LLVMCopyStringRepOfTargetData(LLVMTargetDataRef TD) { + std::string StringRep = unwrap(TD)->getStringRepresentation(); + return strdup(StringRep.c_str()); +} + +LLVMByteOrdering LLVMByteOrder(LLVMTargetDataRef TD) { + return unwrap(TD)->isLittleEndian(); +} + +unsigned LLVMPointerSize(LLVMTargetDataRef TD) { + return unwrap(TD)->getPointerSize(); +} + +LLVMTypeRef LLVMIntPtrType(LLVMTargetDataRef TD) { + return wrap(unwrap(TD)->getIntPtrType(getGlobalContext())); +} + +unsigned long long LLVMSizeOfTypeInBits(LLVMTargetDataRef TD, LLVMTypeRef Ty) { + return unwrap(TD)->getTypeSizeInBits(unwrap(Ty)); +} + +unsigned long long LLVMStoreSizeOfType(LLVMTargetDataRef TD, LLVMTypeRef Ty) { + return unwrap(TD)->getTypeStoreSize(unwrap(Ty)); +} + +unsigned long long LLVMABISizeOfType(LLVMTargetDataRef TD, LLVMTypeRef Ty) { + return unwrap(TD)->getTypeAllocSize(unwrap(Ty)); +} + +unsigned LLVMABIAlignmentOfType(LLVMTargetDataRef TD, LLVMTypeRef Ty) { + return unwrap(TD)->getABITypeAlignment(unwrap(Ty)); +} + +unsigned LLVMCallFrameAlignmentOfType(LLVMTargetDataRef TD, LLVMTypeRef Ty) { + return unwrap(TD)->getCallFrameTypeAlignment(unwrap(Ty)); +} + +unsigned LLVMPreferredAlignmentOfType(LLVMTargetDataRef TD, LLVMTypeRef Ty) { + return unwrap(TD)->getPrefTypeAlignment(unwrap(Ty)); +} + +unsigned LLVMPreferredAlignmentOfGlobal(LLVMTargetDataRef TD, + LLVMValueRef GlobalVar) { + return unwrap(TD)->getPreferredAlignment(unwrap(GlobalVar)); +} + +unsigned LLVMElementAtOffset(LLVMTargetDataRef TD, LLVMTypeRef StructTy, + unsigned long long Offset) { + const StructType *STy = unwrap(StructTy); + return unwrap(TD)->getStructLayout(STy)->getElementContainingOffset(Offset); +} + +unsigned long long LLVMOffsetOfElement(LLVMTargetDataRef TD, LLVMTypeRef StructTy, + unsigned Element) { + const StructType *STy = unwrap(StructTy); + return unwrap(TD)->getStructLayout(STy)->getElementOffset(Element); +} + +void LLVMInvalidateStructLayout(LLVMTargetDataRef TD, LLVMTypeRef StructTy) { + unwrap(TD)->InvalidateStructLayoutInfo(unwrap(StructTy)); +} + +void LLVMDisposeTargetData(LLVMTargetDataRef TD) { + delete unwrap(TD); +} diff --git a/libclamav/c++/llvm/lib/Target/TargetData.cpp b/libclamav/c++/llvm/lib/Target/TargetData.cpp new file mode 100644 index 000000000..fc71bc3ab --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/TargetData.cpp @@ -0,0 +1,682 @@ +//===-- TargetData.cpp - Data size & alignment routines --------------------==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines target properties related to datatype size/offset/alignment +// information. +// +// This structure should be created once, filled in if the defaults are not +// correct and then passed around by const&. None of the members functions +// require modification to the object. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Target/TargetData.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Module.h" +#include "llvm/Support/GetElementPtrTypeIterator.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/Support/ManagedStatic.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/System/Mutex.h" +#include "llvm/ADT/DenseMap.h" +#include +#include +using namespace llvm; + +// Handle the Pass registration stuff necessary to use TargetData's. + +// Register the default SparcV9 implementation... +static RegisterPass X("targetdata", "Target Data Layout", false, + true); +char TargetData::ID = 0; + +//===----------------------------------------------------------------------===// +// Support for StructLayout +//===----------------------------------------------------------------------===// + +StructLayout::StructLayout(const StructType *ST, const TargetData &TD) { + StructAlignment = 0; + StructSize = 0; + NumElements = ST->getNumElements(); + + // Loop over each of the elements, placing them in memory. + for (unsigned i = 0, e = NumElements; i != e; ++i) { + const Type *Ty = ST->getElementType(i); + unsigned TyAlign = ST->isPacked() ? 1 : TD.getABITypeAlignment(Ty); + + // Add padding if necessary to align the data element properly. + if ((StructSize & (TyAlign-1)) != 0) + StructSize = TargetData::RoundUpAlignment(StructSize, TyAlign); + + // Keep track of maximum alignment constraint. + StructAlignment = std::max(TyAlign, StructAlignment); + + MemberOffsets[i] = StructSize; + StructSize += TD.getTypeAllocSize(Ty); // Consume space for this data item + } + + // Empty structures have alignment of 1 byte. + if (StructAlignment == 0) StructAlignment = 1; + + // Add padding to the end of the struct so that it could be put in an array + // and all array elements would be aligned correctly. + if ((StructSize & (StructAlignment-1)) != 0) + StructSize = TargetData::RoundUpAlignment(StructSize, StructAlignment); +} + + +/// getElementContainingOffset - Given a valid offset into the structure, +/// return the structure index that contains it. +unsigned StructLayout::getElementContainingOffset(uint64_t Offset) const { + const uint64_t *SI = + std::upper_bound(&MemberOffsets[0], &MemberOffsets[NumElements], Offset); + assert(SI != &MemberOffsets[0] && "Offset not in structure type!"); + --SI; + assert(*SI <= Offset && "upper_bound didn't work"); + assert((SI == &MemberOffsets[0] || *(SI-1) <= Offset) && + (SI+1 == &MemberOffsets[NumElements] || *(SI+1) > Offset) && + "Upper bound didn't work!"); + + // Multiple fields can have the same offset if any of them are zero sized. + // For example, in { i32, [0 x i32], i32 }, searching for offset 4 will stop + // at the i32 element, because it is the last element at that offset. This is + // the right one to return, because anything after it will have a higher + // offset, implying that this element is non-empty. + return SI-&MemberOffsets[0]; +} + +//===----------------------------------------------------------------------===// +// TargetAlignElem, TargetAlign support +//===----------------------------------------------------------------------===// + +TargetAlignElem +TargetAlignElem::get(AlignTypeEnum align_type, unsigned char abi_align, + unsigned char pref_align, uint32_t bit_width) { + assert(abi_align <= pref_align && "Preferred alignment worse than ABI!"); + TargetAlignElem retval; + retval.AlignType = align_type; + retval.ABIAlign = abi_align; + retval.PrefAlign = pref_align; + retval.TypeBitWidth = bit_width; + return retval; +} + +bool +TargetAlignElem::operator==(const TargetAlignElem &rhs) const { + return (AlignType == rhs.AlignType + && ABIAlign == rhs.ABIAlign + && PrefAlign == rhs.PrefAlign + && TypeBitWidth == rhs.TypeBitWidth); +} + +std::ostream & +TargetAlignElem::dump(std::ostream &os) const { + return os << AlignType + << TypeBitWidth + << ":" << (int) (ABIAlign * 8) + << ":" << (int) (PrefAlign * 8); +} + +const TargetAlignElem TargetData::InvalidAlignmentElem = + TargetAlignElem::get((AlignTypeEnum) -1, 0, 0, 0); + +//===----------------------------------------------------------------------===// +// TargetData Class Implementation +//===----------------------------------------------------------------------===// + +/// getInt - Get an integer ignoring errors. +static unsigned getInt(StringRef R) { + unsigned Result = 0; + R.getAsInteger(10, Result); + return Result; +} + +void TargetData::init(StringRef Desc) { + LayoutMap = 0; + LittleEndian = false; + PointerMemSize = 8; + PointerABIAlign = 8; + PointerPrefAlign = PointerABIAlign; + + // Default alignments + setAlignment(INTEGER_ALIGN, 1, 1, 1); // i1 + setAlignment(INTEGER_ALIGN, 1, 1, 8); // i8 + setAlignment(INTEGER_ALIGN, 2, 2, 16); // i16 + setAlignment(INTEGER_ALIGN, 4, 4, 32); // i32 + setAlignment(INTEGER_ALIGN, 4, 8, 64); // i64 + setAlignment(FLOAT_ALIGN, 4, 4, 32); // float + setAlignment(FLOAT_ALIGN, 8, 8, 64); // double + setAlignment(VECTOR_ALIGN, 8, 8, 64); // v2i32, v1i64, ... + setAlignment(VECTOR_ALIGN, 16, 16, 128); // v16i8, v8i16, v4i32, ... + setAlignment(AGGREGATE_ALIGN, 0, 8, 0); // struct + + while (!Desc.empty()) { + std::pair Split = Desc.split('-'); + StringRef Token = Split.first; + Desc = Split.second; + + if (Token.empty()) + continue; + + Split = Token.split(':'); + StringRef Specifier = Split.first; + Token = Split.second; + + assert(!Specifier.empty() && "Can't be empty here"); + + switch (Specifier[0]) { + case 'E': + LittleEndian = false; + break; + case 'e': + LittleEndian = true; + break; + case 'p': + Split = Token.split(':'); + PointerMemSize = getInt(Split.first) / 8; + Split = Split.second.split(':'); + PointerABIAlign = getInt(Split.first) / 8; + Split = Split.second.split(':'); + PointerPrefAlign = getInt(Split.first) / 8; + if (PointerPrefAlign == 0) + PointerPrefAlign = PointerABIAlign; + break; + case 'i': + case 'v': + case 'f': + case 'a': + case 's': { + AlignTypeEnum AlignType; + switch (Specifier[0]) { + default: + case 'i': AlignType = INTEGER_ALIGN; break; + case 'v': AlignType = VECTOR_ALIGN; break; + case 'f': AlignType = FLOAT_ALIGN; break; + case 'a': AlignType = AGGREGATE_ALIGN; break; + case 's': AlignType = STACK_ALIGN; break; + } + unsigned Size = getInt(Specifier.substr(1)); + Split = Token.split(':'); + unsigned char ABIAlign = getInt(Split.first) / 8; + + Split = Split.second.split(':'); + unsigned char PrefAlign = getInt(Split.first) / 8; + if (PrefAlign == 0) + PrefAlign = ABIAlign; + setAlignment(AlignType, ABIAlign, PrefAlign, Size); + break; + } + case 'n': // Native integer types. + Specifier = Specifier.substr(1); + do { + if (unsigned Width = getInt(Specifier)) + LegalIntWidths.push_back(Width); + Split = Token.split(':'); + Specifier = Split.first; + Token = Split.second; + } while (!Specifier.empty() || !Token.empty()); + break; + + default: + break; + } + } +} + +/// Default ctor. +/// +/// @note This has to exist, because this is a pass, but it should never be +/// used. +TargetData::TargetData() : ImmutablePass(&ID) { + llvm_report_error("Bad TargetData ctor used. " + "Tool did not specify a TargetData to use?"); +} + +TargetData::TargetData(const Module *M) + : ImmutablePass(&ID) { + init(M->getDataLayout()); +} + +void +TargetData::setAlignment(AlignTypeEnum align_type, unsigned char abi_align, + unsigned char pref_align, uint32_t bit_width) { + assert(abi_align <= pref_align && "Preferred alignment worse than ABI!"); + for (unsigned i = 0, e = Alignments.size(); i != e; ++i) { + if (Alignments[i].AlignType == align_type && + Alignments[i].TypeBitWidth == bit_width) { + // Update the abi, preferred alignments. + Alignments[i].ABIAlign = abi_align; + Alignments[i].PrefAlign = pref_align; + return; + } + } + + Alignments.push_back(TargetAlignElem::get(align_type, abi_align, + pref_align, bit_width)); +} + +/// getAlignmentInfo - Return the alignment (either ABI if ABIInfo = true or +/// preferred if ABIInfo = false) the target wants for the specified datatype. +unsigned TargetData::getAlignmentInfo(AlignTypeEnum AlignType, + uint32_t BitWidth, bool ABIInfo, + const Type *Ty) const { + // Check to see if we have an exact match and remember the best match we see. + int BestMatchIdx = -1; + int LargestInt = -1; + for (unsigned i = 0, e = Alignments.size(); i != e; ++i) { + if (Alignments[i].AlignType == AlignType && + Alignments[i].TypeBitWidth == BitWidth) + return ABIInfo ? Alignments[i].ABIAlign : Alignments[i].PrefAlign; + + // The best match so far depends on what we're looking for. + if (AlignType == VECTOR_ALIGN && Alignments[i].AlignType == VECTOR_ALIGN) { + // If this is a specification for a smaller vector type, we will fall back + // to it. This happens because <128 x double> can be implemented in terms + // of 64 <2 x double>. + if (Alignments[i].TypeBitWidth < BitWidth) { + // Verify that we pick the biggest of the fallbacks. + if (BestMatchIdx == -1 || + Alignments[BestMatchIdx].TypeBitWidth < Alignments[i].TypeBitWidth) + BestMatchIdx = i; + } + } else if (AlignType == INTEGER_ALIGN && + Alignments[i].AlignType == INTEGER_ALIGN) { + // The "best match" for integers is the smallest size that is larger than + // the BitWidth requested. + if (Alignments[i].TypeBitWidth > BitWidth && (BestMatchIdx == -1 || + Alignments[i].TypeBitWidth < Alignments[BestMatchIdx].TypeBitWidth)) + BestMatchIdx = i; + // However, if there isn't one that's larger, then we must use the + // largest one we have (see below) + if (LargestInt == -1 || + Alignments[i].TypeBitWidth > Alignments[LargestInt].TypeBitWidth) + LargestInt = i; + } + } + + // Okay, we didn't find an exact solution. Fall back here depending on what + // is being looked for. + if (BestMatchIdx == -1) { + // If we didn't find an integer alignment, fall back on most conservative. + if (AlignType == INTEGER_ALIGN) { + BestMatchIdx = LargestInt; + } else { + assert(AlignType == VECTOR_ALIGN && "Unknown alignment type!"); + + // If we didn't find a vector size that is smaller or equal to this type, + // then we will end up scalarizing this to its element type. Just return + // the alignment of the element. + return getAlignment(cast(Ty)->getElementType(), ABIInfo); + } + } + + // Since we got a "best match" index, just return it. + return ABIInfo ? Alignments[BestMatchIdx].ABIAlign + : Alignments[BestMatchIdx].PrefAlign; +} + +typedef DenseMap LayoutInfoTy; + +namespace llvm { + +class StructLayoutMap : public AbstractTypeUser { + LayoutInfoTy LayoutInfo; + + /// refineAbstractType - The callback method invoked when an abstract type is + /// resolved to another type. An object must override this method to update + /// its internal state to reference NewType instead of OldType. + /// + virtual void refineAbstractType(const DerivedType *OldTy, + const Type *) { + const StructType *STy = dyn_cast(OldTy); + if (!STy) { + OldTy->removeAbstractTypeUser(this); + return; + } + + StructLayout *SL = LayoutInfo[STy]; + if (SL) { + SL->~StructLayout(); + free(SL); + LayoutInfo[STy] = NULL; + } + + OldTy->removeAbstractTypeUser(this); + } + + /// typeBecameConcrete - The other case which AbstractTypeUsers must be aware + /// of is when a type makes the transition from being abstract (where it has + /// clients on its AbstractTypeUsers list) to concrete (where it does not). + /// This method notifies ATU's when this occurs for a type. + /// + virtual void typeBecameConcrete(const DerivedType *AbsTy) { + const StructType *STy = dyn_cast(AbsTy); + if (!STy) { + AbsTy->removeAbstractTypeUser(this); + return; + } + + StructLayout *SL = LayoutInfo[STy]; + if (SL) { + SL->~StructLayout(); + free(SL); + LayoutInfo[STy] = NULL; + } + + AbsTy->removeAbstractTypeUser(this); + } + + bool insert(const Type *Ty) { + if (Ty->isAbstract()) + Ty->addAbstractTypeUser(this); + return true; + } + +public: + virtual ~StructLayoutMap() { + // Remove any layouts. + for (LayoutInfoTy::iterator + I = LayoutInfo.begin(), E = LayoutInfo.end(); I != E; ++I) + if (StructLayout *SL = I->second) { + SL->~StructLayout(); + free(SL); + } + } + + inline LayoutInfoTy::iterator begin() { + return LayoutInfo.begin(); + } + inline LayoutInfoTy::iterator end() { + return LayoutInfo.end(); + } + inline LayoutInfoTy::const_iterator begin() const { + return LayoutInfo.begin(); + } + inline LayoutInfoTy::const_iterator end() const { + return LayoutInfo.end(); + } + + LayoutInfoTy::iterator find(const StructType *&Val) { + return LayoutInfo.find(Val); + } + LayoutInfoTy::const_iterator find(const StructType *&Val) const { + return LayoutInfo.find(Val); + } + + bool erase(const StructType *&Val) { + return LayoutInfo.erase(Val); + } + bool erase(LayoutInfoTy::iterator I) { + return LayoutInfo.erase(I); + } + + StructLayout *&operator[](const Type *Key) { + const StructType *STy = dyn_cast(Key); + assert(STy && "Trying to access the struct layout map with a non-struct!"); + insert(STy); + return LayoutInfo[STy]; + } + + // for debugging... + virtual void dump() const {} +}; + +} // end namespace llvm + +TargetData::~TargetData() { + delete LayoutMap; +} + +const StructLayout *TargetData::getStructLayout(const StructType *Ty) const { + if (!LayoutMap) + LayoutMap = new StructLayoutMap(); + + StructLayout *&SL = (*LayoutMap)[Ty]; + if (SL) return SL; + + // Otherwise, create the struct layout. Because it is variable length, we + // malloc it, then use placement new. + int NumElts = Ty->getNumElements(); + StructLayout *L = + (StructLayout *)malloc(sizeof(StructLayout)+(NumElts-1) * sizeof(uint64_t)); + + // Set SL before calling StructLayout's ctor. The ctor could cause other + // entries to be added to TheMap, invalidating our reference. + SL = L; + + new (L) StructLayout(Ty, *this); + return L; +} + +/// InvalidateStructLayoutInfo - TargetData speculatively caches StructLayout +/// objects. If a TargetData object is alive when types are being refined and +/// removed, this method must be called whenever a StructType is removed to +/// avoid a dangling pointer in this cache. +void TargetData::InvalidateStructLayoutInfo(const StructType *Ty) const { + if (!LayoutMap) return; // No cache. + + DenseMap::iterator I = LayoutMap->find(Ty); + if (I == LayoutMap->end()) return; + + I->second->~StructLayout(); + free(I->second); + LayoutMap->erase(I); +} + + +std::string TargetData::getStringRepresentation() const { + std::string Result; + raw_string_ostream OS(Result); + + OS << (LittleEndian ? "e" : "E") + << "-p:" << PointerMemSize*8 << ':' << PointerABIAlign*8 + << ':' << PointerPrefAlign*8; + for (unsigned i = 0, e = Alignments.size(); i != e; ++i) { + const TargetAlignElem &AI = Alignments[i]; + OS << '-' << (char)AI.AlignType << AI.TypeBitWidth << ':' + << AI.ABIAlign*8 << ':' << AI.PrefAlign*8; + } + + if (!LegalIntWidths.empty()) { + OS << "-n" << (unsigned)LegalIntWidths[0]; + + for (unsigned i = 1, e = LegalIntWidths.size(); i != e; ++i) + OS << ':' << (unsigned)LegalIntWidths[i]; + } + return OS.str(); +} + + +uint64_t TargetData::getTypeSizeInBits(const Type *Ty) const { + assert(Ty->isSized() && "Cannot getTypeInfo() on a type that is unsized!"); + switch (Ty->getTypeID()) { + case Type::LabelTyID: + case Type::PointerTyID: + return getPointerSizeInBits(); + case Type::ArrayTyID: { + const ArrayType *ATy = cast(Ty); + return getTypeAllocSizeInBits(ATy->getElementType())*ATy->getNumElements(); + } + case Type::StructTyID: + // Get the layout annotation... which is lazily created on demand. + return getStructLayout(cast(Ty))->getSizeInBits(); + case Type::IntegerTyID: + return cast(Ty)->getBitWidth(); + case Type::VoidTyID: + return 8; + case Type::FloatTyID: + return 32; + case Type::DoubleTyID: + return 64; + case Type::PPC_FP128TyID: + case Type::FP128TyID: + return 128; + // In memory objects this is always aligned to a higher boundary, but + // only 80 bits contain information. + case Type::X86_FP80TyID: + return 80; + case Type::VectorTyID: + return cast(Ty)->getBitWidth(); + default: + llvm_unreachable("TargetData::getTypeSizeInBits(): Unsupported type"); + break; + } + return 0; +} + +/*! + \param abi_or_pref Flag that determines which alignment is returned. true + returns the ABI alignment, false returns the preferred alignment. + \param Ty The underlying type for which alignment is determined. + + Get the ABI (\a abi_or_pref == true) or preferred alignment (\a abi_or_pref + == false) for the requested type \a Ty. + */ +unsigned char TargetData::getAlignment(const Type *Ty, bool abi_or_pref) const { + int AlignType = -1; + + assert(Ty->isSized() && "Cannot getTypeInfo() on a type that is unsized!"); + switch (Ty->getTypeID()) { + // Early escape for the non-numeric types. + case Type::LabelTyID: + case Type::PointerTyID: + return (abi_or_pref + ? getPointerABIAlignment() + : getPointerPrefAlignment()); + case Type::ArrayTyID: + return getAlignment(cast(Ty)->getElementType(), abi_or_pref); + + case Type::StructTyID: { + // Packed structure types always have an ABI alignment of one. + if (cast(Ty)->isPacked() && abi_or_pref) + return 1; + + // Get the layout annotation... which is lazily created on demand. + const StructLayout *Layout = getStructLayout(cast(Ty)); + unsigned Align = getAlignmentInfo(AGGREGATE_ALIGN, 0, abi_or_pref, Ty); + return std::max(Align, (unsigned)Layout->getAlignment()); + } + case Type::IntegerTyID: + case Type::VoidTyID: + AlignType = INTEGER_ALIGN; + break; + case Type::FloatTyID: + case Type::DoubleTyID: + // PPC_FP128TyID and FP128TyID have different data contents, but the + // same size and alignment, so they look the same here. + case Type::PPC_FP128TyID: + case Type::FP128TyID: + case Type::X86_FP80TyID: + AlignType = FLOAT_ALIGN; + break; + case Type::VectorTyID: + AlignType = VECTOR_ALIGN; + break; + default: + llvm_unreachable("Bad type for getAlignment!!!"); + break; + } + + return getAlignmentInfo((AlignTypeEnum)AlignType, getTypeSizeInBits(Ty), + abi_or_pref, Ty); +} + +unsigned char TargetData::getABITypeAlignment(const Type *Ty) const { + return getAlignment(Ty, true); +} + +unsigned char TargetData::getCallFrameTypeAlignment(const Type *Ty) const { + for (unsigned i = 0, e = Alignments.size(); i != e; ++i) + if (Alignments[i].AlignType == STACK_ALIGN) + return Alignments[i].ABIAlign; + + return getABITypeAlignment(Ty); +} + +unsigned char TargetData::getPrefTypeAlignment(const Type *Ty) const { + return getAlignment(Ty, false); +} + +unsigned char TargetData::getPreferredTypeAlignmentShift(const Type *Ty) const { + unsigned Align = (unsigned) getPrefTypeAlignment(Ty); + assert(!(Align & (Align-1)) && "Alignment is not a power of two!"); + return Log2_32(Align); +} + +/// getIntPtrType - Return an unsigned integer type that is the same size or +/// greater to the host pointer size. +const IntegerType *TargetData::getIntPtrType(LLVMContext &C) const { + return IntegerType::get(C, getPointerSizeInBits()); +} + + +uint64_t TargetData::getIndexedOffset(const Type *ptrTy, Value* const* Indices, + unsigned NumIndices) const { + const Type *Ty = ptrTy; + assert(isa(Ty) && "Illegal argument for getIndexedOffset()"); + uint64_t Result = 0; + + generic_gep_type_iterator + TI = gep_type_begin(ptrTy, Indices, Indices+NumIndices); + for (unsigned CurIDX = 0; CurIDX != NumIndices; ++CurIDX, ++TI) { + if (const StructType *STy = dyn_cast(*TI)) { + assert(Indices[CurIDX]->getType() == + Type::getInt32Ty(ptrTy->getContext()) && + "Illegal struct idx"); + unsigned FieldNo = cast(Indices[CurIDX])->getZExtValue(); + + // Get structure layout information... + const StructLayout *Layout = getStructLayout(STy); + + // Add in the offset, as calculated by the structure layout info... + Result += Layout->getElementOffset(FieldNo); + + // Update Ty to refer to current element + Ty = STy->getElementType(FieldNo); + } else { + // Update Ty to refer to current element + Ty = cast(Ty)->getElementType(); + + // Get the array index and the size of each array element. + int64_t arrayIdx = cast(Indices[CurIDX])->getSExtValue(); + Result += arrayIdx * (int64_t)getTypeAllocSize(Ty); + } + } + + return Result; +} + +/// getPreferredAlignment - Return the preferred alignment of the specified +/// global. This includes an explicitly requested alignment (if the global +/// has one). +unsigned TargetData::getPreferredAlignment(const GlobalVariable *GV) const { + const Type *ElemType = GV->getType()->getElementType(); + unsigned Alignment = getPrefTypeAlignment(ElemType); + if (GV->getAlignment() > Alignment) + Alignment = GV->getAlignment(); + + if (GV->hasInitializer()) { + if (Alignment < 16) { + // If the global is not external, see if it is large. If so, give it a + // larger alignment. + if (getTypeSizeInBits(ElemType) > 128) + Alignment = 16; // 16-byte alignment. + } + } + return Alignment; +} + +/// getPreferredAlignmentLog - Return the preferred alignment of the +/// specified global, returned in log form. This includes an explicitly +/// requested alignment (if the global has one). +unsigned TargetData::getPreferredAlignmentLog(const GlobalVariable *GV) const { + return Log2_32(getPreferredAlignment(GV)); +} diff --git a/libclamav/c++/llvm/lib/Target/TargetELFWriterInfo.cpp b/libclamav/c++/llvm/lib/Target/TargetELFWriterInfo.cpp new file mode 100644 index 000000000..3631b3501 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/TargetELFWriterInfo.cpp @@ -0,0 +1,26 @@ +//===-- lib/Target/TargetELFWriterInfo.cpp - ELF Writer Info --0-*- 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 the TargetELFWriterInfo class. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Function.h" +#include "llvm/Target/TargetELFWriterInfo.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetMachine.h" +using namespace llvm; + +TargetELFWriterInfo::TargetELFWriterInfo(TargetMachine &tm) : TM(tm) { + is64Bit = TM.getTargetData()->getPointerSizeInBits() == 64; + isLittleEndian = TM.getTargetData()->isLittleEndian(); +} + +TargetELFWriterInfo::~TargetELFWriterInfo() {} + diff --git a/libclamav/c++/llvm/lib/Target/TargetFrameInfo.cpp b/libclamav/c++/llvm/lib/Target/TargetFrameInfo.cpp new file mode 100644 index 000000000..873d60a1b --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/TargetFrameInfo.cpp @@ -0,0 +1,19 @@ +//===-- TargetFrameInfo.cpp - Implement machine frame interface -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Implements the layout of a stack frame on the target machine. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Target/TargetFrameInfo.h" +#include +using namespace llvm; + +TargetFrameInfo::~TargetFrameInfo() { +} diff --git a/libclamav/c++/llvm/lib/Target/TargetInstrInfo.cpp b/libclamav/c++/llvm/lib/Target/TargetInstrInfo.cpp new file mode 100644 index 000000000..094a57edb --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/TargetInstrInfo.cpp @@ -0,0 +1,95 @@ +//===-- TargetInstrInfo.cpp - Target Instruction Information --------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the TargetInstrInfo class. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Support/ErrorHandling.h" +using namespace llvm; + +//===----------------------------------------------------------------------===// +// TargetOperandInfo +//===----------------------------------------------------------------------===// + +/// getRegClass - Get the register class for the operand, handling resolution +/// of "symbolic" pointer register classes etc. If this is not a register +/// operand, this returns null. +const TargetRegisterClass * +TargetOperandInfo::getRegClass(const TargetRegisterInfo *TRI) const { + if (isLookupPtrRegClass()) + return TRI->getPointerRegClass(RegClass); + return TRI->getRegClass(RegClass); +} + +//===----------------------------------------------------------------------===// +// TargetInstrInfo +//===----------------------------------------------------------------------===// + +TargetInstrInfo::TargetInstrInfo(const TargetInstrDesc* Desc, + unsigned numOpcodes) + : Descriptors(Desc), NumOpcodes(numOpcodes) { +} + +TargetInstrInfo::~TargetInstrInfo() { +} + +/// insertNoop - Insert a noop into the instruction stream at the specified +/// point. +void TargetInstrInfo::insertNoop(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI) const { + llvm_unreachable("Target didn't implement insertNoop!"); +} + + +bool TargetInstrInfo::isUnpredicatedTerminator(const MachineInstr *MI) const { + const TargetInstrDesc &TID = MI->getDesc(); + if (!TID.isTerminator()) return false; + + // Conditional branch is a special case. + if (TID.isBranch() && !TID.isBarrier()) + return true; + if (!TID.isPredicable()) + return true; + return !isPredicated(MI); +} + + +/// Measure the specified inline asm to determine an approximation of its +/// length. +/// Comments (which run till the next SeparatorChar or newline) do not +/// count as an instruction. +/// Any other non-whitespace text is considered an instruction, with +/// multiple instructions separated by SeparatorChar or newlines. +/// Variable-length instructions are not handled here; this function +/// may be overloaded in the target code to do that. +unsigned TargetInstrInfo::getInlineAsmLength(const char *Str, + const MCAsmInfo &MAI) const { + + + // Count the number of instructions in the asm. + bool atInsnStart = true; + unsigned Length = 0; + for (; *Str; ++Str) { + if (*Str == '\n' || *Str == MAI.getSeparatorChar()) + atInsnStart = true; + if (atInsnStart && !isspace(*Str)) { + Length += MAI.getMaxInstLength(); + atInsnStart = false; + } + if (atInsnStart && strncmp(Str, MAI.getCommentString(), + strlen(MAI.getCommentString())) == 0) + atInsnStart = false; + } + + return Length; +} diff --git a/libclamav/c++/llvm/lib/Target/TargetIntrinsicInfo.cpp b/libclamav/c++/llvm/lib/Target/TargetIntrinsicInfo.cpp new file mode 100644 index 000000000..e049a1d3b --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/TargetIntrinsicInfo.cpp @@ -0,0 +1,30 @@ +//===-- TargetIntrinsicInfo.cpp - Target Instruction Information ----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the TargetIntrinsicInfo class. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Target/TargetIntrinsicInfo.h" +#include "llvm/Function.h" +#include "llvm/ADT/StringMap.h" +using namespace llvm; + +TargetIntrinsicInfo::TargetIntrinsicInfo() { +} + +TargetIntrinsicInfo::~TargetIntrinsicInfo() { +} + +unsigned TargetIntrinsicInfo::getIntrinsicID(Function *F) const { + const ValueName *ValName = F->getValueName(); + if (!ValName) + return 0; + return lookupName(ValName->getKeyData(), ValName->getKeyLength()); +} diff --git a/libclamav/c++/llvm/lib/Target/TargetLoweringObjectFile.cpp b/libclamav/c++/llvm/lib/Target/TargetLoweringObjectFile.cpp new file mode 100644 index 000000000..f887523c5 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/TargetLoweringObjectFile.cpp @@ -0,0 +1,1090 @@ +//===-- llvm/Target/TargetLoweringObjectFile.cpp - Object File Info -------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements classes used to handle lowerings specific to common +// object file formats. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Target/TargetLoweringObjectFile.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Function.h" +#include "llvm/GlobalVariable.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCSectionMachO.h" +#include "llvm/MC/MCSectionELF.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetOptions.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/Mangler.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringExtras.h" +using namespace llvm; + +//===----------------------------------------------------------------------===// +// Generic Code +//===----------------------------------------------------------------------===// + +TargetLoweringObjectFile::TargetLoweringObjectFile() : Ctx(0) { + TextSection = 0; + DataSection = 0; + BSSSection = 0; + ReadOnlySection = 0; + StaticCtorSection = 0; + StaticDtorSection = 0; + LSDASection = 0; + EHFrameSection = 0; + + DwarfAbbrevSection = 0; + DwarfInfoSection = 0; + DwarfLineSection = 0; + DwarfFrameSection = 0; + DwarfPubNamesSection = 0; + DwarfPubTypesSection = 0; + DwarfDebugInlineSection = 0; + DwarfStrSection = 0; + DwarfLocSection = 0; + DwarfARangesSection = 0; + DwarfRangesSection = 0; + DwarfMacroInfoSection = 0; +} + +TargetLoweringObjectFile::~TargetLoweringObjectFile() { +} + +static bool isSuitableForBSS(const GlobalVariable *GV) { + Constant *C = GV->getInitializer(); + + // Must have zero initializer. + if (!C->isNullValue()) + return false; + + // Leave constant zeros in readonly constant sections, so they can be shared. + if (GV->isConstant()) + return false; + + // If the global has an explicit section specified, don't put it in BSS. + if (!GV->getSection().empty()) + return false; + + // If -nozero-initialized-in-bss is specified, don't ever use BSS. + if (NoZerosInBSS) + return false; + + // Otherwise, put it in BSS! + return true; +} + +/// IsNullTerminatedString - Return true if the specified constant (which is +/// known to have a type that is an array of 1/2/4 byte elements) ends with a +/// nul value and contains no other nuls in it. +static bool IsNullTerminatedString(const Constant *C) { + const ArrayType *ATy = cast(C->getType()); + + // First check: is we have constant array of i8 terminated with zero + if (const ConstantArray *CVA = dyn_cast(C)) { + if (ATy->getNumElements() == 0) return false; + + ConstantInt *Null = + dyn_cast(CVA->getOperand(ATy->getNumElements()-1)); + if (Null == 0 || Null->getZExtValue() != 0) + return false; // Not null terminated. + + // Verify that the null doesn't occur anywhere else in the string. + for (unsigned i = 0, e = ATy->getNumElements()-1; i != e; ++i) + // Reject constantexpr elements etc. + if (!isa(CVA->getOperand(i)) || + CVA->getOperand(i) == Null) + return false; + return true; + } + + // Another possibility: [1 x i8] zeroinitializer + if (isa(C)) + return ATy->getNumElements() == 1; + + return false; +} + +/// getKindForGlobal - This is a top-level target-independent classifier for +/// a global variable. Given an global variable and information from TM, it +/// classifies the global in a variety of ways that make various target +/// implementations simpler. The target implementation is free to ignore this +/// extra info of course. +SectionKind TargetLoweringObjectFile::getKindForGlobal(const GlobalValue *GV, + const TargetMachine &TM){ + assert(!GV->isDeclaration() && !GV->hasAvailableExternallyLinkage() && + "Can only be used for global definitions"); + + Reloc::Model ReloModel = TM.getRelocationModel(); + + // Early exit - functions should be always in text sections. + const GlobalVariable *GVar = dyn_cast(GV); + if (GVar == 0) + return SectionKind::getText(); + + // Handle thread-local data first. + if (GVar->isThreadLocal()) { + if (isSuitableForBSS(GVar)) + return SectionKind::getThreadBSS(); + return SectionKind::getThreadData(); + } + + // Variable can be easily put to BSS section. + if (isSuitableForBSS(GVar)) + return SectionKind::getBSS(); + + Constant *C = GVar->getInitializer(); + + // If the global is marked constant, we can put it into a mergable section, + // a mergable string section, or general .data if it contains relocations. + if (GVar->isConstant()) { + // If the initializer for the global contains something that requires a + // relocation, then we may have to drop this into a wriable data section + // even though it is marked const. + switch (C->getRelocationInfo()) { + default: assert(0 && "unknown relocation info kind"); + case Constant::NoRelocation: + // If initializer is a null-terminated string, put it in a "cstring" + // section of the right width. + if (const ArrayType *ATy = dyn_cast(C->getType())) { + if (const IntegerType *ITy = + dyn_cast(ATy->getElementType())) { + if ((ITy->getBitWidth() == 8 || ITy->getBitWidth() == 16 || + ITy->getBitWidth() == 32) && + IsNullTerminatedString(C)) { + if (ITy->getBitWidth() == 8) + return SectionKind::getMergeable1ByteCString(); + if (ITy->getBitWidth() == 16) + return SectionKind::getMergeable2ByteCString(); + + assert(ITy->getBitWidth() == 32 && "Unknown width"); + return SectionKind::getMergeable4ByteCString(); + } + } + } + + // Otherwise, just drop it into a mergable constant section. If we have + // a section for this size, use it, otherwise use the arbitrary sized + // mergable section. + switch (TM.getTargetData()->getTypeAllocSize(C->getType())) { + case 4: return SectionKind::getMergeableConst4(); + case 8: return SectionKind::getMergeableConst8(); + case 16: return SectionKind::getMergeableConst16(); + default: return SectionKind::getMergeableConst(); + } + + case Constant::LocalRelocation: + // In static relocation model, the linker will resolve all addresses, so + // the relocation entries will actually be constants by the time the app + // starts up. However, we can't put this into a mergable section, because + // the linker doesn't take relocations into consideration when it tries to + // merge entries in the section. + if (ReloModel == Reloc::Static) + return SectionKind::getReadOnly(); + + // Otherwise, the dynamic linker needs to fix it up, put it in the + // writable data.rel.local section. + return SectionKind::getReadOnlyWithRelLocal(); + + case Constant::GlobalRelocations: + // In static relocation model, the linker will resolve all addresses, so + // the relocation entries will actually be constants by the time the app + // starts up. However, we can't put this into a mergable section, because + // the linker doesn't take relocations into consideration when it tries to + // merge entries in the section. + if (ReloModel == Reloc::Static) + return SectionKind::getReadOnly(); + + // Otherwise, the dynamic linker needs to fix it up, put it in the + // writable data.rel section. + return SectionKind::getReadOnlyWithRel(); + } + } + + // Okay, this isn't a constant. If the initializer for the global is going + // to require a runtime relocation by the dynamic linker, put it into a more + // specific section to improve startup time of the app. This coalesces these + // globals together onto fewer pages, improving the locality of the dynamic + // linker. + if (ReloModel == Reloc::Static) + return SectionKind::getDataNoRel(); + + switch (C->getRelocationInfo()) { + default: assert(0 && "unknown relocation info kind"); + case Constant::NoRelocation: + return SectionKind::getDataNoRel(); + case Constant::LocalRelocation: + return SectionKind::getDataRelLocal(); + case Constant::GlobalRelocations: + return SectionKind::getDataRel(); + } +} + +/// SectionForGlobal - This method computes the appropriate section to emit +/// the specified global variable or function definition. This should not +/// be passed external (or available externally) globals. +const MCSection *TargetLoweringObjectFile:: +SectionForGlobal(const GlobalValue *GV, SectionKind Kind, Mangler *Mang, + const TargetMachine &TM) const { + // Select section name. + if (GV->hasSection()) + return getExplicitSectionGlobal(GV, Kind, Mang, TM); + + + // Use default section depending on the 'type' of global + return SelectSectionForGlobal(GV, Kind, Mang, TM); +} + + +// Lame default implementation. Calculate the section name for global. +const MCSection * +TargetLoweringObjectFile::SelectSectionForGlobal(const GlobalValue *GV, + SectionKind Kind, + Mangler *Mang, + const TargetMachine &TM) const{ + assert(!Kind.isThreadLocal() && "Doesn't support TLS"); + + if (Kind.isText()) + return getTextSection(); + + if (Kind.isBSS() && BSSSection != 0) + return BSSSection; + + if (Kind.isReadOnly() && ReadOnlySection != 0) + return ReadOnlySection; + + return getDataSection(); +} + +/// getSectionForConstant - Given a mergable constant with the +/// specified size and relocation information, return a section that it +/// should be placed in. +const MCSection * +TargetLoweringObjectFile::getSectionForConstant(SectionKind Kind) const { + if (Kind.isReadOnly() && ReadOnlySection != 0) + return ReadOnlySection; + + return DataSection; +} + +/// getSymbolForDwarfGlobalReference - Return an MCExpr to use for a +/// pc-relative reference to the specified global variable from exception +/// handling information. In addition to the symbol, this returns +/// by-reference: +/// +/// IsIndirect - True if the returned symbol is actually a stub that contains +/// the address of the symbol, false if the symbol is the global itself. +/// +/// IsPCRel - True if the symbol reference is already pc-relative, false if +/// the caller needs to subtract off the address of the reference from the +/// symbol. +/// +const MCExpr *TargetLoweringObjectFile:: +getSymbolForDwarfGlobalReference(const GlobalValue *GV, Mangler *Mang, + MachineModuleInfo *MMI, + bool &IsIndirect, bool &IsPCRel) const { + // The generic implementation of this just returns a direct reference to the + // symbol. + IsIndirect = false; + IsPCRel = false; + + SmallString<128> Name; + Mang->getNameWithPrefix(Name, GV, false); + return MCSymbolRefExpr::Create(Name.str(), getContext()); +} + + +//===----------------------------------------------------------------------===// +// ELF +//===----------------------------------------------------------------------===// +typedef StringMap ELFUniqueMapTy; + +TargetLoweringObjectFileELF::~TargetLoweringObjectFileELF() { + // If we have the section uniquing map, free it. + delete (ELFUniqueMapTy*)UniquingMap; +} + +const MCSection *TargetLoweringObjectFileELF:: +getELFSection(StringRef Section, unsigned Type, unsigned Flags, + SectionKind Kind, bool IsExplicit) const { + if (UniquingMap == 0) + UniquingMap = new ELFUniqueMapTy(); + ELFUniqueMapTy &Map = *(ELFUniqueMapTy*)UniquingMap; + + // Do the lookup, if we have a hit, return it. + const MCSectionELF *&Entry = Map[Section]; + if (Entry) return Entry; + + return Entry = MCSectionELF::Create(Section, Type, Flags, Kind, IsExplicit, + getContext()); +} + +void TargetLoweringObjectFileELF::Initialize(MCContext &Ctx, + const TargetMachine &TM) { + if (UniquingMap != 0) + ((ELFUniqueMapTy*)UniquingMap)->clear(); + TargetLoweringObjectFile::Initialize(Ctx, TM); + + BSSSection = + getELFSection(".bss", MCSectionELF::SHT_NOBITS, + MCSectionELF::SHF_WRITE | MCSectionELF::SHF_ALLOC, + SectionKind::getBSS()); + + TextSection = + getELFSection(".text", MCSectionELF::SHT_PROGBITS, + MCSectionELF::SHF_EXECINSTR | MCSectionELF::SHF_ALLOC, + SectionKind::getText()); + + DataSection = + getELFSection(".data", MCSectionELF::SHT_PROGBITS, + MCSectionELF::SHF_WRITE | MCSectionELF::SHF_ALLOC, + SectionKind::getDataRel()); + + ReadOnlySection = + getELFSection(".rodata", MCSectionELF::SHT_PROGBITS, + MCSectionELF::SHF_ALLOC, + SectionKind::getReadOnly()); + + TLSDataSection = + getELFSection(".tdata", MCSectionELF::SHT_PROGBITS, + MCSectionELF::SHF_ALLOC | MCSectionELF::SHF_TLS | + MCSectionELF::SHF_WRITE, SectionKind::getThreadData()); + + TLSBSSSection = + getELFSection(".tbss", MCSectionELF::SHT_NOBITS, + MCSectionELF::SHF_ALLOC | MCSectionELF::SHF_TLS | + MCSectionELF::SHF_WRITE, SectionKind::getThreadBSS()); + + DataRelSection = + getELFSection(".data.rel", MCSectionELF::SHT_PROGBITS, + MCSectionELF::SHF_ALLOC | MCSectionELF::SHF_WRITE, + SectionKind::getDataRel()); + + DataRelLocalSection = + getELFSection(".data.rel.local", MCSectionELF::SHT_PROGBITS, + MCSectionELF::SHF_ALLOC | MCSectionELF::SHF_WRITE, + SectionKind::getDataRelLocal()); + + DataRelROSection = + getELFSection(".data.rel.ro", MCSectionELF::SHT_PROGBITS, + MCSectionELF::SHF_ALLOC | MCSectionELF::SHF_WRITE, + SectionKind::getReadOnlyWithRel()); + + DataRelROLocalSection = + getELFSection(".data.rel.ro.local", MCSectionELF::SHT_PROGBITS, + MCSectionELF::SHF_ALLOC | MCSectionELF::SHF_WRITE, + SectionKind::getReadOnlyWithRelLocal()); + + MergeableConst4Section = + getELFSection(".rodata.cst4", MCSectionELF::SHT_PROGBITS, + MCSectionELF::SHF_ALLOC | MCSectionELF::SHF_MERGE, + SectionKind::getMergeableConst4()); + + MergeableConst8Section = + getELFSection(".rodata.cst8", MCSectionELF::SHT_PROGBITS, + MCSectionELF::SHF_ALLOC | MCSectionELF::SHF_MERGE, + SectionKind::getMergeableConst8()); + + MergeableConst16Section = + getELFSection(".rodata.cst16", MCSectionELF::SHT_PROGBITS, + MCSectionELF::SHF_ALLOC | MCSectionELF::SHF_MERGE, + SectionKind::getMergeableConst16()); + + StaticCtorSection = + getELFSection(".ctors", MCSectionELF::SHT_PROGBITS, + MCSectionELF::SHF_ALLOC | MCSectionELF::SHF_WRITE, + SectionKind::getDataRel()); + + StaticDtorSection = + getELFSection(".dtors", MCSectionELF::SHT_PROGBITS, + MCSectionELF::SHF_ALLOC | MCSectionELF::SHF_WRITE, + SectionKind::getDataRel()); + + // Exception Handling Sections. + + // FIXME: We're emitting LSDA info into a readonly section on ELF, even though + // it contains relocatable pointers. In PIC mode, this is probably a big + // runtime hit for C++ apps. Either the contents of the LSDA need to be + // adjusted or this should be a data section. + LSDASection = + getELFSection(".gcc_except_table", MCSectionELF::SHT_PROGBITS, + MCSectionELF::SHF_ALLOC, SectionKind::getReadOnly()); + EHFrameSection = + getELFSection(".eh_frame", MCSectionELF::SHT_PROGBITS, + MCSectionELF::SHF_ALLOC | MCSectionELF::SHF_WRITE, + SectionKind::getDataRel()); + + // Debug Info Sections. + DwarfAbbrevSection = + getELFSection(".debug_abbrev", MCSectionELF::SHT_PROGBITS, 0, + SectionKind::getMetadata()); + DwarfInfoSection = + getELFSection(".debug_info", MCSectionELF::SHT_PROGBITS, 0, + SectionKind::getMetadata()); + DwarfLineSection = + getELFSection(".debug_line", MCSectionELF::SHT_PROGBITS, 0, + SectionKind::getMetadata()); + DwarfFrameSection = + getELFSection(".debug_frame", MCSectionELF::SHT_PROGBITS, 0, + SectionKind::getMetadata()); + DwarfPubNamesSection = + getELFSection(".debug_pubnames", MCSectionELF::SHT_PROGBITS, 0, + SectionKind::getMetadata()); + DwarfPubTypesSection = + getELFSection(".debug_pubtypes", MCSectionELF::SHT_PROGBITS, 0, + SectionKind::getMetadata()); + DwarfStrSection = + getELFSection(".debug_str", MCSectionELF::SHT_PROGBITS, 0, + SectionKind::getMetadata()); + DwarfLocSection = + getELFSection(".debug_loc", MCSectionELF::SHT_PROGBITS, 0, + SectionKind::getMetadata()); + DwarfARangesSection = + getELFSection(".debug_aranges", MCSectionELF::SHT_PROGBITS, 0, + SectionKind::getMetadata()); + DwarfRangesSection = + getELFSection(".debug_ranges", MCSectionELF::SHT_PROGBITS, 0, + SectionKind::getMetadata()); + DwarfMacroInfoSection = + getELFSection(".debug_macinfo", MCSectionELF::SHT_PROGBITS, 0, + SectionKind::getMetadata()); +} + + +static SectionKind +getELFKindForNamedSection(const char *Name, SectionKind K) { + if (Name[0] != '.') return K; + + // Some lame default implementation based on some magic section names. + if (strcmp(Name, ".bss") == 0 || + strncmp(Name, ".bss.", 5) == 0 || + strncmp(Name, ".gnu.linkonce.b.", 16) == 0 || + strncmp(Name, ".llvm.linkonce.b.", 17) == 0 || + strcmp(Name, ".sbss") == 0 || + strncmp(Name, ".sbss.", 6) == 0 || + strncmp(Name, ".gnu.linkonce.sb.", 17) == 0 || + strncmp(Name, ".llvm.linkonce.sb.", 18) == 0) + return SectionKind::getBSS(); + + if (strcmp(Name, ".tdata") == 0 || + strncmp(Name, ".tdata.", 7) == 0 || + strncmp(Name, ".gnu.linkonce.td.", 17) == 0 || + strncmp(Name, ".llvm.linkonce.td.", 18) == 0) + return SectionKind::getThreadData(); + + if (strcmp(Name, ".tbss") == 0 || + strncmp(Name, ".tbss.", 6) == 0 || + strncmp(Name, ".gnu.linkonce.tb.", 17) == 0 || + strncmp(Name, ".llvm.linkonce.tb.", 18) == 0) + return SectionKind::getThreadBSS(); + + return K; +} + + +static unsigned +getELFSectionType(const char *Name, SectionKind K) { + + if (strcmp(Name, ".init_array") == 0) + return MCSectionELF::SHT_INIT_ARRAY; + + if (strcmp(Name, ".fini_array") == 0) + return MCSectionELF::SHT_FINI_ARRAY; + + if (strcmp(Name, ".preinit_array") == 0) + return MCSectionELF::SHT_PREINIT_ARRAY; + + if (K.isBSS() || K.isThreadBSS()) + return MCSectionELF::SHT_NOBITS; + + return MCSectionELF::SHT_PROGBITS; +} + + +static unsigned +getELFSectionFlags(SectionKind K) { + unsigned Flags = 0; + + if (!K.isMetadata()) + Flags |= MCSectionELF::SHF_ALLOC; + + if (K.isText()) + Flags |= MCSectionELF::SHF_EXECINSTR; + + if (K.isWriteable()) + Flags |= MCSectionELF::SHF_WRITE; + + if (K.isThreadLocal()) + Flags |= MCSectionELF::SHF_TLS; + + // K.isMergeableConst() is left out to honour PR4650 + if (K.isMergeableCString() || K.isMergeableConst4() || + K.isMergeableConst8() || K.isMergeableConst16()) + Flags |= MCSectionELF::SHF_MERGE; + + if (K.isMergeableCString()) + Flags |= MCSectionELF::SHF_STRINGS; + + return Flags; +} + + +const MCSection *TargetLoweringObjectFileELF:: +getExplicitSectionGlobal(const GlobalValue *GV, SectionKind Kind, + Mangler *Mang, const TargetMachine &TM) const { + const char *SectionName = GV->getSection().c_str(); + + // Infer section flags from the section name if we can. + Kind = getELFKindForNamedSection(SectionName, Kind); + + return getELFSection(SectionName, + getELFSectionType(SectionName, Kind), + getELFSectionFlags(Kind), Kind, true); +} + +static const char *getSectionPrefixForUniqueGlobal(SectionKind Kind) { + if (Kind.isText()) return ".gnu.linkonce.t."; + if (Kind.isReadOnly()) return ".gnu.linkonce.r."; + + if (Kind.isThreadData()) return ".gnu.linkonce.td."; + if (Kind.isThreadBSS()) return ".gnu.linkonce.tb."; + + if (Kind.isBSS()) return ".gnu.linkonce.b."; + if (Kind.isDataNoRel()) return ".gnu.linkonce.d."; + if (Kind.isDataRelLocal()) return ".gnu.linkonce.d.rel.local."; + if (Kind.isDataRel()) return ".gnu.linkonce.d.rel."; + if (Kind.isReadOnlyWithRelLocal()) return ".gnu.linkonce.d.rel.ro.local."; + + assert(Kind.isReadOnlyWithRel() && "Unknown section kind"); + return ".gnu.linkonce.d.rel.ro."; +} + +const MCSection *TargetLoweringObjectFileELF:: +SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind, + Mangler *Mang, const TargetMachine &TM) const { + + // If this global is linkonce/weak and the target handles this by emitting it + // into a 'uniqued' section name, create and return the section now. + if (GV->isWeakForLinker()) { + const char *Prefix = getSectionPrefixForUniqueGlobal(Kind); + std::string Name = Mang->makeNameProper(GV->getNameStr()); + + return getELFSection((Prefix+Name).c_str(), + getELFSectionType((Prefix+Name).c_str(), Kind), + getELFSectionFlags(Kind), + Kind); + } + + if (Kind.isText()) return TextSection; + + if (Kind.isMergeable1ByteCString() || + Kind.isMergeable2ByteCString() || + Kind.isMergeable4ByteCString()) { + + // We also need alignment here. + // FIXME: this is getting the alignment of the character, not the + // alignment of the global! + unsigned Align = + TM.getTargetData()->getPreferredAlignment(cast(GV)); + + const char *SizeSpec = ".rodata.str1."; + if (Kind.isMergeable2ByteCString()) + SizeSpec = ".rodata.str2."; + else if (Kind.isMergeable4ByteCString()) + SizeSpec = ".rodata.str4."; + else + assert(Kind.isMergeable1ByteCString() && "unknown string width"); + + + std::string Name = SizeSpec + utostr(Align); + return getELFSection(Name.c_str(), MCSectionELF::SHT_PROGBITS, + MCSectionELF::SHF_ALLOC | + MCSectionELF::SHF_MERGE | + MCSectionELF::SHF_STRINGS, + Kind); + } + + if (Kind.isMergeableConst()) { + if (Kind.isMergeableConst4() && MergeableConst4Section) + return MergeableConst4Section; + if (Kind.isMergeableConst8() && MergeableConst8Section) + return MergeableConst8Section; + if (Kind.isMergeableConst16() && MergeableConst16Section) + return MergeableConst16Section; + return ReadOnlySection; // .const + } + + if (Kind.isReadOnly()) return ReadOnlySection; + + if (Kind.isThreadData()) return TLSDataSection; + if (Kind.isThreadBSS()) return TLSBSSSection; + + if (Kind.isBSS()) return BSSSection; + + if (Kind.isDataNoRel()) return DataSection; + if (Kind.isDataRelLocal()) return DataRelLocalSection; + if (Kind.isDataRel()) return DataRelSection; + if (Kind.isReadOnlyWithRelLocal()) return DataRelROLocalSection; + + assert(Kind.isReadOnlyWithRel() && "Unknown section kind"); + return DataRelROSection; +} + +/// getSectionForConstant - Given a mergeable constant with the +/// specified size and relocation information, return a section that it +/// should be placed in. +const MCSection *TargetLoweringObjectFileELF:: +getSectionForConstant(SectionKind Kind) const { + if (Kind.isMergeableConst4() && MergeableConst4Section) + return MergeableConst4Section; + if (Kind.isMergeableConst8() && MergeableConst8Section) + return MergeableConst8Section; + if (Kind.isMergeableConst16() && MergeableConst16Section) + return MergeableConst16Section; + if (Kind.isReadOnly()) + return ReadOnlySection; + + if (Kind.isReadOnlyWithRelLocal()) return DataRelROLocalSection; + assert(Kind.isReadOnlyWithRel() && "Unknown section kind"); + return DataRelROSection; +} + +//===----------------------------------------------------------------------===// +// MachO +//===----------------------------------------------------------------------===// + +typedef StringMap MachOUniqueMapTy; + +TargetLoweringObjectFileMachO::~TargetLoweringObjectFileMachO() { + // If we have the MachO uniquing map, free it. + delete (MachOUniqueMapTy*)UniquingMap; +} + + +const MCSectionMachO *TargetLoweringObjectFileMachO:: +getMachOSection(StringRef Segment, StringRef Section, + unsigned TypeAndAttributes, + unsigned Reserved2, SectionKind Kind) const { + // We unique sections by their segment/section pair. The returned section + // may not have the same flags as the requested section, if so this should be + // diagnosed by the client as an error. + + // Create the map if it doesn't already exist. + if (UniquingMap == 0) + UniquingMap = new MachOUniqueMapTy(); + MachOUniqueMapTy &Map = *(MachOUniqueMapTy*)UniquingMap; + + // Form the name to look up. + SmallString<64> Name; + Name += Segment; + Name.push_back(','); + Name += Section; + + // Do the lookup, if we have a hit, return it. + const MCSectionMachO *&Entry = Map[Name.str()]; + if (Entry) return Entry; + + // Otherwise, return a new section. + return Entry = MCSectionMachO::Create(Segment, Section, TypeAndAttributes, + Reserved2, Kind, getContext()); +} + + +void TargetLoweringObjectFileMachO::Initialize(MCContext &Ctx, + const TargetMachine &TM) { + if (UniquingMap != 0) + ((MachOUniqueMapTy*)UniquingMap)->clear(); + TargetLoweringObjectFile::Initialize(Ctx, TM); + + TextSection // .text + = getMachOSection("__TEXT", "__text", + MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS, + SectionKind::getText()); + DataSection // .data + = getMachOSection("__DATA", "__data", 0, SectionKind::getDataRel()); + + CStringSection // .cstring + = getMachOSection("__TEXT", "__cstring", MCSectionMachO::S_CSTRING_LITERALS, + SectionKind::getMergeable1ByteCString()); + UStringSection + = getMachOSection("__TEXT","__ustring", 0, + SectionKind::getMergeable2ByteCString()); + FourByteConstantSection // .literal4 + = getMachOSection("__TEXT", "__literal4", MCSectionMachO::S_4BYTE_LITERALS, + SectionKind::getMergeableConst4()); + EightByteConstantSection // .literal8 + = getMachOSection("__TEXT", "__literal8", MCSectionMachO::S_8BYTE_LITERALS, + SectionKind::getMergeableConst8()); + + // ld_classic doesn't support .literal16 in 32-bit mode, and ld64 falls back + // to using it in -static mode. + SixteenByteConstantSection = 0; + if (TM.getRelocationModel() != Reloc::Static && + TM.getTargetData()->getPointerSize() == 32) + SixteenByteConstantSection = // .literal16 + getMachOSection("__TEXT", "__literal16",MCSectionMachO::S_16BYTE_LITERALS, + SectionKind::getMergeableConst16()); + + ReadOnlySection // .const + = getMachOSection("__TEXT", "__const", 0, SectionKind::getReadOnly()); + + TextCoalSection + = getMachOSection("__TEXT", "__textcoal_nt", + MCSectionMachO::S_COALESCED | + MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS, + SectionKind::getText()); + ConstTextCoalSection + = getMachOSection("__TEXT", "__const_coal", MCSectionMachO::S_COALESCED, + SectionKind::getText()); + ConstDataCoalSection + = getMachOSection("__DATA","__const_coal", MCSectionMachO::S_COALESCED, + SectionKind::getText()); + ConstDataSection // .const_data + = getMachOSection("__DATA", "__const", 0, + SectionKind::getReadOnlyWithRel()); + DataCoalSection + = getMachOSection("__DATA","__datacoal_nt", MCSectionMachO::S_COALESCED, + SectionKind::getDataRel()); + + + LazySymbolPointerSection + = getMachOSection("__DATA", "__la_symbol_ptr", + MCSectionMachO::S_LAZY_SYMBOL_POINTERS, + SectionKind::getMetadata()); + NonLazySymbolPointerSection + = getMachOSection("__DATA", "__nl_symbol_ptr", + MCSectionMachO::S_NON_LAZY_SYMBOL_POINTERS, + SectionKind::getMetadata()); + + if (TM.getRelocationModel() == Reloc::Static) { + StaticCtorSection + = getMachOSection("__TEXT", "__constructor", 0,SectionKind::getDataRel()); + StaticDtorSection + = getMachOSection("__TEXT", "__destructor", 0, SectionKind::getDataRel()); + } else { + StaticCtorSection + = getMachOSection("__DATA", "__mod_init_func", + MCSectionMachO::S_MOD_INIT_FUNC_POINTERS, + SectionKind::getDataRel()); + StaticDtorSection + = getMachOSection("__DATA", "__mod_term_func", + MCSectionMachO::S_MOD_TERM_FUNC_POINTERS, + SectionKind::getDataRel()); + } + + // Exception Handling. + LSDASection = getMachOSection("__DATA", "__gcc_except_tab", 0, + SectionKind::getDataRel()); + EHFrameSection = + getMachOSection("__TEXT", "__eh_frame", + MCSectionMachO::S_COALESCED | + MCSectionMachO::S_ATTR_NO_TOC | + MCSectionMachO::S_ATTR_STRIP_STATIC_SYMS | + MCSectionMachO::S_ATTR_LIVE_SUPPORT, + SectionKind::getReadOnly()); + + // Debug Information. + DwarfAbbrevSection = + getMachOSection("__DWARF", "__debug_abbrev", MCSectionMachO::S_ATTR_DEBUG, + SectionKind::getMetadata()); + DwarfInfoSection = + getMachOSection("__DWARF", "__debug_info", MCSectionMachO::S_ATTR_DEBUG, + SectionKind::getMetadata()); + DwarfLineSection = + getMachOSection("__DWARF", "__debug_line", MCSectionMachO::S_ATTR_DEBUG, + SectionKind::getMetadata()); + DwarfFrameSection = + getMachOSection("__DWARF", "__debug_frame", MCSectionMachO::S_ATTR_DEBUG, + SectionKind::getMetadata()); + DwarfPubNamesSection = + getMachOSection("__DWARF", "__debug_pubnames", MCSectionMachO::S_ATTR_DEBUG, + SectionKind::getMetadata()); + DwarfPubTypesSection = + getMachOSection("__DWARF", "__debug_pubtypes", MCSectionMachO::S_ATTR_DEBUG, + SectionKind::getMetadata()); + DwarfStrSection = + getMachOSection("__DWARF", "__debug_str", MCSectionMachO::S_ATTR_DEBUG, + SectionKind::getMetadata()); + DwarfLocSection = + getMachOSection("__DWARF", "__debug_loc", MCSectionMachO::S_ATTR_DEBUG, + SectionKind::getMetadata()); + DwarfARangesSection = + getMachOSection("__DWARF", "__debug_aranges", MCSectionMachO::S_ATTR_DEBUG, + SectionKind::getMetadata()); + DwarfRangesSection = + getMachOSection("__DWARF", "__debug_ranges", MCSectionMachO::S_ATTR_DEBUG, + SectionKind::getMetadata()); + DwarfMacroInfoSection = + getMachOSection("__DWARF", "__debug_macinfo", MCSectionMachO::S_ATTR_DEBUG, + SectionKind::getMetadata()); + DwarfDebugInlineSection = + getMachOSection("__DWARF", "__debug_inlined", MCSectionMachO::S_ATTR_DEBUG, + SectionKind::getMetadata()); +} + +const MCSection *TargetLoweringObjectFileMachO:: +getExplicitSectionGlobal(const GlobalValue *GV, SectionKind Kind, + Mangler *Mang, const TargetMachine &TM) const { + // Parse the section specifier and create it if valid. + StringRef Segment, Section; + unsigned TAA, StubSize; + std::string ErrorCode = + MCSectionMachO::ParseSectionSpecifier(GV->getSection(), Segment, Section, + TAA, StubSize); + if (!ErrorCode.empty()) { + // If invalid, report the error with llvm_report_error. + llvm_report_error("Global variable '" + GV->getNameStr() + + "' has an invalid section specifier '" + GV->getSection()+ + "': " + ErrorCode + "."); + // Fall back to dropping it into the data section. + return DataSection; + } + + // Get the section. + const MCSectionMachO *S = + getMachOSection(Segment, Section, TAA, StubSize, Kind); + + // Okay, now that we got the section, verify that the TAA & StubSize agree. + // If the user declared multiple globals with different section flags, we need + // to reject it here. + if (S->getTypeAndAttributes() != TAA || S->getStubSize() != StubSize) { + // If invalid, report the error with llvm_report_error. + llvm_report_error("Global variable '" + GV->getNameStr() + + "' section type or attributes does not match previous" + " section specifier"); + } + + return S; +} + +const MCSection *TargetLoweringObjectFileMachO:: +SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind, + Mangler *Mang, const TargetMachine &TM) const { + assert(!Kind.isThreadLocal() && "Darwin doesn't support TLS"); + + if (Kind.isText()) + return GV->isWeakForLinker() ? TextCoalSection : TextSection; + + // If this is weak/linkonce, put this in a coalescable section, either in text + // or data depending on if it is writable. + if (GV->isWeakForLinker()) { + if (Kind.isReadOnly()) + return ConstTextCoalSection; + return DataCoalSection; + } + + // FIXME: Alignment check should be handled by section classifier. + if (Kind.isMergeable1ByteCString() || + Kind.isMergeable2ByteCString()) { + if (TM.getTargetData()->getPreferredAlignment( + cast(GV)) < 32) { + if (Kind.isMergeable1ByteCString()) + return CStringSection; + assert(Kind.isMergeable2ByteCString()); + return UStringSection; + } + } + + if (Kind.isMergeableConst()) { + if (Kind.isMergeableConst4()) + return FourByteConstantSection; + if (Kind.isMergeableConst8()) + return EightByteConstantSection; + if (Kind.isMergeableConst16() && SixteenByteConstantSection) + return SixteenByteConstantSection; + } + + // Otherwise, if it is readonly, but not something we can specially optimize, + // just drop it in .const. + if (Kind.isReadOnly()) + return ReadOnlySection; + + // If this is marked const, put it into a const section. But if the dynamic + // linker needs to write to it, put it in the data segment. + if (Kind.isReadOnlyWithRel()) + return ConstDataSection; + + // Otherwise, just drop the variable in the normal data section. + return DataSection; +} + +const MCSection * +TargetLoweringObjectFileMachO::getSectionForConstant(SectionKind Kind) const { + // If this constant requires a relocation, we have to put it in the data + // segment, not in the text segment. + if (Kind.isDataRel()) + return ConstDataSection; + + if (Kind.isMergeableConst4()) + return FourByteConstantSection; + if (Kind.isMergeableConst8()) + return EightByteConstantSection; + if (Kind.isMergeableConst16() && SixteenByteConstantSection) + return SixteenByteConstantSection; + return ReadOnlySection; // .const +} + +/// shouldEmitUsedDirectiveFor - This hook allows targets to selectively decide +/// not to emit the UsedDirective for some symbols in llvm.used. +// FIXME: REMOVE this (rdar://7071300) +bool TargetLoweringObjectFileMachO:: +shouldEmitUsedDirectiveFor(const GlobalValue *GV, Mangler *Mang) const { + /// On Darwin, internally linked data beginning with "L" or "l" does not have + /// the directive emitted (this occurs in ObjC metadata). + if (!GV) return false; + + // Check whether the mangled name has the "Private" or "LinkerPrivate" prefix. + if (GV->hasLocalLinkage() && !isa(GV)) { + // FIXME: ObjC metadata is currently emitted as internal symbols that have + // \1L and \0l prefixes on them. Fix them to be Private/LinkerPrivate and + // this horrible hack can go away. + const std::string &Name = Mang->getMangledName(GV); + if (Name[0] == 'L' || Name[0] == 'l') + return false; + } + + return true; +} + +const MCExpr *TargetLoweringObjectFileMachO:: +getSymbolForDwarfGlobalReference(const GlobalValue *GV, Mangler *Mang, + MachineModuleInfo *MMI, + bool &IsIndirect, bool &IsPCRel) const { + // The mach-o version of this method defaults to returning a stub reference. + IsIndirect = true; + IsPCRel = false; + + SmallString<128> Name; + Mang->getNameWithPrefix(Name, GV, true); + Name += "$non_lazy_ptr"; + return MCSymbolRefExpr::Create(Name.str(), getContext()); +} + + +//===----------------------------------------------------------------------===// +// COFF +//===----------------------------------------------------------------------===// + +typedef StringMap COFFUniqueMapTy; + +TargetLoweringObjectFileCOFF::~TargetLoweringObjectFileCOFF() { + delete (COFFUniqueMapTy*)UniquingMap; +} + + +const MCSection *TargetLoweringObjectFileCOFF:: +getCOFFSection(const char *Name, bool isDirective, SectionKind Kind) const { + // Create the map if it doesn't already exist. + if (UniquingMap == 0) + UniquingMap = new MachOUniqueMapTy(); + COFFUniqueMapTy &Map = *(COFFUniqueMapTy*)UniquingMap; + + // Do the lookup, if we have a hit, return it. + const MCSectionCOFF *&Entry = Map[Name]; + if (Entry) return Entry; + + return Entry = MCSectionCOFF::Create(Name, isDirective, Kind, getContext()); +} + +void TargetLoweringObjectFileCOFF::Initialize(MCContext &Ctx, + const TargetMachine &TM) { + if (UniquingMap != 0) + ((COFFUniqueMapTy*)UniquingMap)->clear(); + TargetLoweringObjectFile::Initialize(Ctx, TM); + TextSection = getCOFFSection("\t.text", true, SectionKind::getText()); + DataSection = getCOFFSection("\t.data", true, SectionKind::getDataRel()); + StaticCtorSection = + getCOFFSection(".ctors", false, SectionKind::getDataRel()); + StaticDtorSection = + getCOFFSection(".dtors", false, SectionKind::getDataRel()); + + // FIXME: We're emitting LSDA info into a readonly section on COFF, even + // though it contains relocatable pointers. In PIC mode, this is probably a + // big runtime hit for C++ apps. Either the contents of the LSDA need to be + // adjusted or this should be a data section. + LSDASection = + getCOFFSection(".gcc_except_table", false, SectionKind::getReadOnly()); + EHFrameSection = + getCOFFSection(".eh_frame", false, SectionKind::getDataRel()); + + // Debug info. + // FIXME: Don't use 'directive' mode here. + DwarfAbbrevSection = + getCOFFSection("\t.section\t.debug_abbrev,\"dr\"", + true, SectionKind::getMetadata()); + DwarfInfoSection = + getCOFFSection("\t.section\t.debug_info,\"dr\"", + true, SectionKind::getMetadata()); + DwarfLineSection = + getCOFFSection("\t.section\t.debug_line,\"dr\"", + true, SectionKind::getMetadata()); + DwarfFrameSection = + getCOFFSection("\t.section\t.debug_frame,\"dr\"", + true, SectionKind::getMetadata()); + DwarfPubNamesSection = + getCOFFSection("\t.section\t.debug_pubnames,\"dr\"", + true, SectionKind::getMetadata()); + DwarfPubTypesSection = + getCOFFSection("\t.section\t.debug_pubtypes,\"dr\"", + true, SectionKind::getMetadata()); + DwarfStrSection = + getCOFFSection("\t.section\t.debug_str,\"dr\"", + true, SectionKind::getMetadata()); + DwarfLocSection = + getCOFFSection("\t.section\t.debug_loc,\"dr\"", + true, SectionKind::getMetadata()); + DwarfARangesSection = + getCOFFSection("\t.section\t.debug_aranges,\"dr\"", + true, SectionKind::getMetadata()); + DwarfRangesSection = + getCOFFSection("\t.section\t.debug_ranges,\"dr\"", + true, SectionKind::getMetadata()); + DwarfMacroInfoSection = + getCOFFSection("\t.section\t.debug_macinfo,\"dr\"", + true, SectionKind::getMetadata()); +} + +const MCSection *TargetLoweringObjectFileCOFF:: +getExplicitSectionGlobal(const GlobalValue *GV, SectionKind Kind, + Mangler *Mang, const TargetMachine &TM) const { + return getCOFFSection(GV->getSection().c_str(), false, Kind); +} + +static const char *getCOFFSectionPrefixForUniqueGlobal(SectionKind Kind) { + if (Kind.isText()) + return ".text$linkonce"; + if (Kind.isWriteable()) + return ".data$linkonce"; + return ".rdata$linkonce"; +} + + +const MCSection *TargetLoweringObjectFileCOFF:: +SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind, + Mangler *Mang, const TargetMachine &TM) const { + assert(!Kind.isThreadLocal() && "Doesn't support TLS"); + + // If this global is linkonce/weak and the target handles this by emitting it + // into a 'uniqued' section name, create and return the section now. + if (GV->isWeakForLinker()) { + const char *Prefix = getCOFFSectionPrefixForUniqueGlobal(Kind); + std::string Name = Mang->makeNameProper(GV->getNameStr()); + return getCOFFSection((Prefix+Name).c_str(), false, Kind); + } + + if (Kind.isText()) + return getTextSection(); + + return getDataSection(); +} + diff --git a/libclamav/c++/llvm/lib/Target/TargetMachOWriterInfo.cpp b/libclamav/c++/llvm/lib/Target/TargetMachOWriterInfo.cpp new file mode 100644 index 000000000..d60811981 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/TargetMachOWriterInfo.cpp @@ -0,0 +1,25 @@ +//===-- llvm/Target/TargetMachOWriterInfo.h - MachO Writer 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 defines the TargetMachOWriterInfo class. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Target/TargetMachOWriterInfo.h" +#include "llvm/CodeGen/MachineRelocation.h" +using namespace llvm; + +TargetMachOWriterInfo::~TargetMachOWriterInfo() {} + +MachineRelocation +TargetMachOWriterInfo::GetJTRelocation(unsigned Offset, + MachineBasicBlock *MBB) const { + // FIXME: do something about PIC + return MachineRelocation::getBB(Offset, MachineRelocation::VANILLA, MBB); +} diff --git a/libclamav/c++/llvm/lib/Target/TargetMachine.cpp b/libclamav/c++/llvm/lib/Target/TargetMachine.cpp new file mode 100644 index 000000000..fec59b5e2 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/TargetMachine.cpp @@ -0,0 +1,265 @@ +//===-- TargetMachine.cpp - General Target Information ---------------------==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file describes the general parts of a Target machine. +// +//===----------------------------------------------------------------------===// + +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetOptions.h" +#include "llvm/Support/CommandLine.h" +using namespace llvm; + +//--------------------------------------------------------------------------- +// Command-line options that tend to be useful on more than one back-end. +// + +namespace llvm { + bool LessPreciseFPMADOption; + bool PrintMachineCode; + bool NoFramePointerElim; + bool NoExcessFPPrecision; + bool UnsafeFPMath; + bool FiniteOnlyFPMathOption; + bool HonorSignDependentRoundingFPMathOption; + bool UseSoftFloat; + FloatABI::ABIType FloatABIType; + bool NoImplicitFloat; + bool NoZerosInBSS; + bool DwarfExceptionHandling; + bool SjLjExceptionHandling; + bool JITEmitDebugInfo; + bool JITEmitDebugInfoToDisk; + bool UnwindTablesMandatory; + Reloc::Model RelocationModel; + CodeModel::Model CMModel; + bool PerformTailCallOpt; + unsigned StackAlignment; + bool RealignStack; + bool DisableJumpTables; + bool StrongPHIElim; + bool AsmVerbosityDefault(false); +} + +static cl::opt +PrintCode("print-machineinstrs", + cl::desc("Print generated machine code"), + cl::location(PrintMachineCode), cl::init(false)); +static cl::opt +DisableFPElim("disable-fp-elim", + cl::desc("Disable frame pointer elimination optimization"), + cl::location(NoFramePointerElim), + cl::init(false)); +static cl::opt +DisableExcessPrecision("disable-excess-fp-precision", + cl::desc("Disable optimizations that may increase FP precision"), + cl::location(NoExcessFPPrecision), + cl::init(false)); +static cl::opt +EnableFPMAD("enable-fp-mad", + cl::desc("Enable less precise MAD instructions to be generated"), + cl::location(LessPreciseFPMADOption), + cl::init(false)); +static cl::opt +EnableUnsafeFPMath("enable-unsafe-fp-math", + cl::desc("Enable optimizations that may decrease FP precision"), + cl::location(UnsafeFPMath), + cl::init(false)); +static cl::opt +EnableFiniteOnlyFPMath("enable-finite-only-fp-math", + cl::desc("Enable optimizations that assumes non- NaNs / +-Infs"), + cl::location(FiniteOnlyFPMathOption), + cl::init(false)); +static cl::opt +EnableHonorSignDependentRoundingFPMath("enable-sign-dependent-rounding-fp-math", + cl::Hidden, + cl::desc("Force codegen to assume rounding mode can change dynamically"), + cl::location(HonorSignDependentRoundingFPMathOption), + cl::init(false)); +static cl::opt +GenerateSoftFloatCalls("soft-float", + cl::desc("Generate software floating point library calls"), + cl::location(UseSoftFloat), + cl::init(false)); +static cl::opt +FloatABIForCalls("float-abi", + cl::desc("Choose float ABI type"), + cl::location(FloatABIType), + cl::init(FloatABI::Default), + cl::values( + clEnumValN(FloatABI::Default, "default", + "Target default float ABI type"), + clEnumValN(FloatABI::Soft, "soft", + "Soft float ABI (implied by -soft-float)"), + clEnumValN(FloatABI::Hard, "hard", + "Hard float ABI (uses FP registers)"), + clEnumValEnd)); +static cl::opt +DontPlaceZerosInBSS("nozero-initialized-in-bss", + cl::desc("Don't place zero-initialized symbols into bss section"), + cl::location(NoZerosInBSS), + cl::init(false)); +static cl::opt +EnableDwarfExceptionHandling("enable-eh", + cl::desc("Emit DWARF exception handling (default if target supports)"), + cl::location(DwarfExceptionHandling), + cl::init(false)); +static cl::opt +EnableSjLjExceptionHandling("enable-sjlj-eh", + cl::desc("Emit SJLJ exception handling (default if target supports)"), + cl::location(SjLjExceptionHandling), + cl::init(false)); +// In debug builds, make this default to true. +#ifdef NDEBUG +#define EMIT_DEBUG false +#else +#define EMIT_DEBUG true +#endif +static cl::opt +EmitJitDebugInfo("jit-emit-debug", + cl::desc("Emit debug information to debugger"), + cl::location(JITEmitDebugInfo), + cl::init(EMIT_DEBUG)); +#undef EMIT_DEBUG +static cl::opt +EmitJitDebugInfoToDisk("jit-emit-debug-to-disk", + cl::Hidden, + cl::desc("Emit debug info objfiles to disk"), + cl::location(JITEmitDebugInfoToDisk), + cl::init(false)); +static cl::opt +EnableUnwindTables("unwind-tables", + cl::desc("Generate unwinding tables for all functions"), + cl::location(UnwindTablesMandatory), + cl::init(false)); + +static cl::opt +DefRelocationModel("relocation-model", + cl::desc("Choose relocation model"), + cl::location(RelocationModel), + cl::init(Reloc::Default), + cl::values( + clEnumValN(Reloc::Default, "default", + "Target default relocation model"), + clEnumValN(Reloc::Static, "static", + "Non-relocatable code"), + clEnumValN(Reloc::PIC_, "pic", + "Fully relocatable, position independent code"), + clEnumValN(Reloc::DynamicNoPIC, "dynamic-no-pic", + "Relocatable external references, non-relocatable code"), + clEnumValEnd)); +static cl::opt +DefCodeModel("code-model", + cl::desc("Choose code model"), + cl::location(CMModel), + cl::init(CodeModel::Default), + cl::values( + clEnumValN(CodeModel::Default, "default", + "Target default code model"), + clEnumValN(CodeModel::Small, "small", + "Small code model"), + clEnumValN(CodeModel::Kernel, "kernel", + "Kernel code model"), + clEnumValN(CodeModel::Medium, "medium", + "Medium code model"), + clEnumValN(CodeModel::Large, "large", + "Large code model"), + clEnumValEnd)); +static cl::opt +EnablePerformTailCallOpt("tailcallopt", + cl::desc("Turn on tail call optimization."), + cl::location(PerformTailCallOpt), + cl::init(false)); +static cl::opt +OverrideStackAlignment("stack-alignment", + cl::desc("Override default stack alignment"), + cl::location(StackAlignment), + cl::init(0)); +static cl::opt +EnableRealignStack("realign-stack", + cl::desc("Realign stack if needed"), + cl::location(RealignStack), + cl::init(true)); +static cl::opt +DisableSwitchTables(cl::Hidden, "disable-jump-tables", + cl::desc("Do not generate jump tables."), + cl::location(DisableJumpTables), + cl::init(false)); +static cl::opt +EnableStrongPHIElim(cl::Hidden, "strong-phi-elim", + cl::desc("Use strong PHI elimination."), + cl::location(StrongPHIElim), + cl::init(false)); + +//--------------------------------------------------------------------------- +// TargetMachine Class +// + +TargetMachine::TargetMachine(const Target &T) + : TheTarget(T), AsmInfo(0) { + // Typically it will be subtargets that will adjust FloatABIType from Default + // to Soft or Hard. + if (UseSoftFloat) + FloatABIType = FloatABI::Soft; +} + +TargetMachine::~TargetMachine() { + delete AsmInfo; +} + +/// getRelocationModel - Returns the code generation relocation model. The +/// choices are static, PIC, and dynamic-no-pic, and target default. +Reloc::Model TargetMachine::getRelocationModel() { + return RelocationModel; +} + +/// setRelocationModel - Sets the code generation relocation model. +void TargetMachine::setRelocationModel(Reloc::Model Model) { + RelocationModel = Model; +} + +/// getCodeModel - Returns the code model. The choices are small, kernel, +/// medium, large, and target default. +CodeModel::Model TargetMachine::getCodeModel() { + return CMModel; +} + +/// setCodeModel - Sets the code model. +void TargetMachine::setCodeModel(CodeModel::Model Model) { + CMModel = Model; +} + +bool TargetMachine::getAsmVerbosityDefault() { + return AsmVerbosityDefault; +} + +void TargetMachine::setAsmVerbosityDefault(bool V) { + AsmVerbosityDefault = V; +} + +namespace llvm { + /// LessPreciseFPMAD - This flag return true when -enable-fp-mad option + /// is specified on the command line. When this flag is off(default), the + /// code generator is not allowed to generate mad (multiply add) if the + /// result is "less precise" than doing those operations individually. + bool LessPreciseFPMAD() { return UnsafeFPMath || LessPreciseFPMADOption; } + + /// FiniteOnlyFPMath - This returns true when the -enable-finite-only-fp-math + /// option is specified on the command line. If this returns false (default), + /// the code generator is not allowed to assume that FP arithmetic arguments + /// and results are never NaNs or +-Infs. + bool FiniteOnlyFPMath() { return UnsafeFPMath || FiniteOnlyFPMathOption; } + + /// HonorSignDependentRoundingFPMath - Return true if the codegen must assume + /// that the rounding mode of the FPU can change from its default. + bool HonorSignDependentRoundingFPMath() { + return !UnsafeFPMath && HonorSignDependentRoundingFPMathOption; + } +} diff --git a/libclamav/c++/llvm/lib/Target/TargetRegisterInfo.cpp b/libclamav/c++/llvm/lib/Target/TargetRegisterInfo.cpp new file mode 100644 index 000000000..fac67e2e1 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/TargetRegisterInfo.cpp @@ -0,0 +1,144 @@ +//===- TargetRegisterInfo.cpp - Target Register Information Implementation ===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the TargetRegisterInfo interface. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Target/TargetFrameInfo.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/ADT/BitVector.h" + +using namespace llvm; + +TargetRegisterInfo::TargetRegisterInfo(const TargetRegisterDesc *D, unsigned NR, + regclass_iterator RCB, regclass_iterator RCE, + int CFSO, int CFDO, + const unsigned* subregs, const unsigned subregsize, + const unsigned* superregs, const unsigned superregsize, + const unsigned* aliases, const unsigned aliasessize) + : SubregHash(subregs), SubregHashSize(subregsize), + SuperregHash(superregs), SuperregHashSize(superregsize), + AliasesHash(aliases), AliasesHashSize(aliasessize), + Desc(D), NumRegs(NR), RegClassBegin(RCB), RegClassEnd(RCE) { + assert(NumRegs < FirstVirtualRegister && + "Target has too many physical registers!"); + + CallFrameSetupOpcode = CFSO; + CallFrameDestroyOpcode = CFDO; +} + +TargetRegisterInfo::~TargetRegisterInfo() {} + +/// getPhysicalRegisterRegClass - Returns the Register Class of a physical +/// register of the given type. If type is EVT::Other, then just return any +/// register class the register belongs to. +const TargetRegisterClass * +TargetRegisterInfo::getPhysicalRegisterRegClass(unsigned reg, EVT VT) const { + assert(isPhysicalRegister(reg) && "reg must be a physical register"); + + // Pick the most super register class of the right type that contains + // this physreg. + const TargetRegisterClass* BestRC = 0; + for (regclass_iterator I = regclass_begin(), E = regclass_end(); I != E; ++I){ + const TargetRegisterClass* RC = *I; + if ((VT == MVT::Other || RC->hasType(VT)) && RC->contains(reg) && + (!BestRC || BestRC->hasSuperClass(RC))) + BestRC = RC; + } + + assert(BestRC && "Couldn't find the register class"); + return BestRC; +} + +/// getAllocatableSetForRC - Toggle the bits that represent allocatable +/// registers for the specific register class. +static void getAllocatableSetForRC(const MachineFunction &MF, + const TargetRegisterClass *RC, BitVector &R){ + for (TargetRegisterClass::iterator I = RC->allocation_order_begin(MF), + E = RC->allocation_order_end(MF); I != E; ++I) + R.set(*I); +} + +BitVector TargetRegisterInfo::getAllocatableSet(const MachineFunction &MF, + const TargetRegisterClass *RC) const { + BitVector Allocatable(NumRegs); + if (RC) { + getAllocatableSetForRC(MF, RC, Allocatable); + return Allocatable; + } + + for (TargetRegisterInfo::regclass_iterator I = regclass_begin(), + E = regclass_end(); I != E; ++I) + getAllocatableSetForRC(MF, *I, Allocatable); + return Allocatable; +} + +/// getFrameIndexOffset - Returns the displacement from the frame register to +/// the stack frame of the specified index. This is the default implementation +/// which is overridden for some targets. +int TargetRegisterInfo::getFrameIndexOffset(MachineFunction &MF, int FI) const { + const TargetFrameInfo &TFI = *MF.getTarget().getFrameInfo(); + MachineFrameInfo *MFI = MF.getFrameInfo(); + return MFI->getObjectOffset(FI) + MFI->getStackSize() - + TFI.getOffsetOfLocalArea() + MFI->getOffsetAdjustment(); +} + +/// getInitialFrameState - Returns a list of machine moves that are assumed +/// on entry to a function. +void +TargetRegisterInfo::getInitialFrameState(std::vector &Moves) const { + // Default is to do nothing. +} + +const TargetRegisterClass * +llvm::getCommonSubClass(const TargetRegisterClass *A, + const TargetRegisterClass *B) { + // First take care of the trivial cases + if (A == B) + return A; + if (!A || !B) + return 0; + + // If B is a subclass of A, it will be handled in the loop below + if (B->hasSubClass(A)) + return A; + + const TargetRegisterClass *Best = 0; + for (TargetRegisterClass::sc_iterator I = A->subclasses_begin(); + const TargetRegisterClass *X = *I; ++I) { + if (X == B) + return B; // B is a subclass of A + + // X must be a common subclass of A and B + if (!B->hasSubClass(X)) + continue; + + // A superclass is definitely better. + if (!Best || Best->hasSuperClass(X)) { + Best = X; + continue; + } + + // A subclass is definitely worse + if (Best->hasSubClass(X)) + continue; + + // Best and *I have no super/sub class relation - pick the larger class, or + // the smaller spill size. + int nb = std::distance(Best->begin(), Best->end()); + int ni = std::distance(X->begin(), X->end()); + if (ni>nb || (ni==nb && X->getSize() < Best->getSize())) + Best = X; + } + return Best; +} diff --git a/libclamav/c++/llvm/lib/Target/TargetSubtarget.cpp b/libclamav/c++/llvm/lib/Target/TargetSubtarget.cpp new file mode 100644 index 000000000..edb76f971 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/TargetSubtarget.cpp @@ -0,0 +1,33 @@ +//===-- TargetSubtarget.cpp - General Target Information -------------------==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file describes the general parts of a Subtarget. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Target/TargetSubtarget.h" +#include "llvm/ADT/SmallVector.h" +using namespace llvm; + +//--------------------------------------------------------------------------- +// TargetSubtarget Class +// +TargetSubtarget::TargetSubtarget() {} + +TargetSubtarget::~TargetSubtarget() {} + +bool TargetSubtarget::enablePostRAScheduler( + CodeGenOpt::Level OptLevel, + AntiDepBreakMode& Mode, + RegClassVector& CriticalPathRCs) const { + Mode = ANTIDEP_NONE; + CriticalPathRCs.clear(); + return false; +} + diff --git a/libclamav/c++/llvm/lib/Target/X86/AsmParser/CMakeLists.txt b/libclamav/c++/llvm/lib/Target/X86/AsmParser/CMakeLists.txt new file mode 100644 index 000000000..034d5aba8 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/X86/AsmParser/CMakeLists.txt @@ -0,0 +1,6 @@ +include_directories( ${CMAKE_CURRENT_BINARY_DIR}/.. ${CMAKE_CURRENT_SOURCE_DIR}/.. ) + +add_llvm_library(LLVMX86AsmParser + X86AsmParser.cpp + ) +add_dependencies(LLVMX86AsmParser X86CodeGenTable_gen) diff --git a/libclamav/c++/llvm/lib/Target/X86/AsmParser/Makefile b/libclamav/c++/llvm/lib/Target/X86/AsmParser/Makefile new file mode 100644 index 000000000..25fb0a283 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/X86/AsmParser/Makefile @@ -0,0 +1,15 @@ +##===- lib/Target/X86/AsmParser/Makefile -------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## +LEVEL = ../../../.. +LIBRARYNAME = LLVMX86AsmParser + +# Hack: we need to include 'main' x86 target directory to grab private headers +CPPFLAGS = -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. + +include $(LEVEL)/Makefile.common diff --git a/libclamav/c++/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp b/libclamav/c++/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp new file mode 100644 index 000000000..c357b4d0d --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp @@ -0,0 +1,479 @@ +//===-- X86AsmParser.cpp - Parse X86 assembly to MCInst instructions ------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "X86.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/Twine.h" +#include "llvm/MC/MCAsmLexer.h" +#include "llvm/MC/MCAsmParser.h" +#include "llvm/MC/MCStreamer.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCInst.h" +#include "llvm/Support/SourceMgr.h" +#include "llvm/Target/TargetRegistry.h" +#include "llvm/Target/TargetAsmParser.h" +using namespace llvm; + +namespace { +struct X86Operand; + +class X86ATTAsmParser : public TargetAsmParser { + MCAsmParser &Parser; + +private: + MCAsmParser &getParser() const { return Parser; } + + MCAsmLexer &getLexer() const { return Parser.getLexer(); } + + void Warning(SMLoc L, const Twine &Msg) { Parser.Warning(L, Msg); } + + bool Error(SMLoc L, const Twine &Msg) { return Parser.Error(L, Msg); } + + bool ParseRegister(X86Operand &Op); + + bool ParseOperand(X86Operand &Op); + + bool ParseMemOperand(X86Operand &Op); + + bool ParseDirectiveWord(unsigned Size, SMLoc L); + + /// @name Auto-generated Match Functions + /// { + + bool MatchInstruction(SmallVectorImpl &Operands, + MCInst &Inst); + + /// MatchRegisterName - Match the given string to a register name, or 0 if + /// there is no match. + unsigned MatchRegisterName(const StringRef &Name); + + /// } + +public: + X86ATTAsmParser(const Target &T, MCAsmParser &_Parser) + : TargetAsmParser(T), Parser(_Parser) {} + + virtual bool ParseInstruction(const StringRef &Name, MCInst &Inst); + + virtual bool ParseDirective(AsmToken DirectiveID); +}; + +} // end anonymous namespace + + +namespace { + +/// X86Operand - Instances of this class represent a parsed X86 machine +/// instruction. +struct X86Operand { + enum { + Token, + Register, + Immediate, + Memory + } Kind; + + union { + struct { + const char *Data; + unsigned Length; + } Tok; + + struct { + unsigned RegNo; + } Reg; + + struct { + const MCExpr *Val; + } Imm; + + struct { + unsigned SegReg; + const MCExpr *Disp; + unsigned BaseReg; + unsigned IndexReg; + unsigned Scale; + } Mem; + }; + + StringRef getToken() const { + assert(Kind == Token && "Invalid access!"); + return StringRef(Tok.Data, Tok.Length); + } + + unsigned getReg() const { + assert(Kind == Register && "Invalid access!"); + return Reg.RegNo; + } + + const MCExpr *getImm() const { + assert(Kind == Immediate && "Invalid access!"); + return Imm.Val; + } + + const MCExpr *getMemDisp() const { + assert(Kind == Memory && "Invalid access!"); + return Mem.Disp; + } + unsigned getMemSegReg() const { + assert(Kind == Memory && "Invalid access!"); + return Mem.SegReg; + } + unsigned getMemBaseReg() const { + assert(Kind == Memory && "Invalid access!"); + return Mem.BaseReg; + } + unsigned getMemIndexReg() const { + assert(Kind == Memory && "Invalid access!"); + return Mem.IndexReg; + } + unsigned getMemScale() const { + assert(Kind == Memory && "Invalid access!"); + return Mem.Scale; + } + + bool isToken() const {return Kind == Token; } + + bool isImm() const { return Kind == Immediate; } + + bool isImmSExt8() const { + // Accept immediates which fit in 8 bits when sign extended, and + // non-absolute immediates. + if (!isImm()) + return false; + + if (const MCConstantExpr *CE = dyn_cast(getImm())) { + int64_t Value = CE->getValue(); + return Value == (int64_t) (int8_t) Value; + } + + return true; + } + + bool isMem() const { return Kind == Memory; } + + bool isReg() const { return Kind == Register; } + + void addRegOperands(MCInst &Inst, unsigned N) const { + assert(N == 1 && "Invalid number of operands!"); + Inst.addOperand(MCOperand::CreateReg(getReg())); + } + + void addImmOperands(MCInst &Inst, unsigned N) const { + assert(N == 1 && "Invalid number of operands!"); + Inst.addOperand(MCOperand::CreateExpr(getImm())); + } + + void addImmSExt8Operands(MCInst &Inst, unsigned N) const { + // FIXME: Support user customization of the render method. + assert(N == 1 && "Invalid number of operands!"); + Inst.addOperand(MCOperand::CreateExpr(getImm())); + } + + void addMemOperands(MCInst &Inst, unsigned N) const { + assert((N == 4 || N == 5) && "Invalid number of operands!"); + + Inst.addOperand(MCOperand::CreateReg(getMemBaseReg())); + Inst.addOperand(MCOperand::CreateImm(getMemScale())); + Inst.addOperand(MCOperand::CreateReg(getMemIndexReg())); + Inst.addOperand(MCOperand::CreateExpr(getMemDisp())); + + // FIXME: What a hack. + if (N == 5) + Inst.addOperand(MCOperand::CreateReg(getMemSegReg())); + } + + static X86Operand CreateToken(StringRef Str) { + X86Operand Res; + Res.Kind = Token; + Res.Tok.Data = Str.data(); + Res.Tok.Length = Str.size(); + return Res; + } + + static X86Operand CreateReg(unsigned RegNo) { + X86Operand Res; + Res.Kind = Register; + Res.Reg.RegNo = RegNo; + return Res; + } + + static X86Operand CreateImm(const MCExpr *Val) { + X86Operand Res; + Res.Kind = Immediate; + Res.Imm.Val = Val; + return Res; + } + + static X86Operand CreateMem(unsigned SegReg, const MCExpr *Disp, + unsigned BaseReg, unsigned IndexReg, + unsigned Scale) { + // We should never just have a displacement, that would be an immediate. + assert((SegReg || BaseReg || IndexReg) && "Invalid memory operand!"); + + // The scale should always be one of {1,2,4,8}. + assert(((Scale == 1 || Scale == 2 || Scale == 4 || Scale == 8)) && + "Invalid scale!"); + X86Operand Res; + Res.Kind = Memory; + Res.Mem.SegReg = SegReg; + Res.Mem.Disp = Disp; + Res.Mem.BaseReg = BaseReg; + Res.Mem.IndexReg = IndexReg; + Res.Mem.Scale = Scale; + return Res; + } +}; + +} // end anonymous namespace. + + +bool X86ATTAsmParser::ParseRegister(X86Operand &Op) { + const AsmToken &TokPercent = getLexer().getTok(); + (void)TokPercent; // Avoid warning when assertions are disabled. + assert(TokPercent.is(AsmToken::Percent) && "Invalid token kind!"); + getLexer().Lex(); // Eat percent token. + + const AsmToken &Tok = getLexer().getTok(); + if (Tok.isNot(AsmToken::Identifier)) + return Error(Tok.getLoc(), "invalid register name"); + + // FIXME: Validate register for the current architecture; we have to do + // validation later, so maybe there is no need for this here. + unsigned RegNo; + + RegNo = MatchRegisterName(Tok.getString()); + if (RegNo == 0) + return Error(Tok.getLoc(), "invalid register name"); + + Op = X86Operand::CreateReg(RegNo); + getLexer().Lex(); // Eat identifier token. + + return false; +} + +bool X86ATTAsmParser::ParseOperand(X86Operand &Op) { + switch (getLexer().getKind()) { + default: + return ParseMemOperand(Op); + case AsmToken::Percent: + // FIXME: if a segment register, this could either be just the seg reg, or + // the start of a memory operand. + return ParseRegister(Op); + case AsmToken::Dollar: { + // $42 -> immediate. + getLexer().Lex(); + const MCExpr *Val; + if (getParser().ParseExpression(Val)) + return true; + Op = X86Operand::CreateImm(Val); + return false; + } + } +} + +/// ParseMemOperand: segment: disp(basereg, indexreg, scale) +bool X86ATTAsmParser::ParseMemOperand(X86Operand &Op) { + // FIXME: If SegReg ':' (e.g. %gs:), eat and remember. + unsigned SegReg = 0; + + // We have to disambiguate a parenthesized expression "(4+5)" from the start + // of a memory operand with a missing displacement "(%ebx)" or "(,%eax)". The + // only way to do this without lookahead is to eat the ( and see what is after + // it. + const MCExpr *Disp = MCConstantExpr::Create(0, getParser().getContext()); + if (getLexer().isNot(AsmToken::LParen)) { + if (getParser().ParseExpression(Disp)) return true; + + // After parsing the base expression we could either have a parenthesized + // memory address or not. If not, return now. If so, eat the (. + if (getLexer().isNot(AsmToken::LParen)) { + // Unless we have a segment register, treat this as an immediate. + if (SegReg) + Op = X86Operand::CreateMem(SegReg, Disp, 0, 0, 1); + else + Op = X86Operand::CreateImm(Disp); + return false; + } + + // Eat the '('. + getLexer().Lex(); + } else { + // Okay, we have a '('. We don't know if this is an expression or not, but + // so we have to eat the ( to see beyond it. + getLexer().Lex(); // Eat the '('. + + if (getLexer().is(AsmToken::Percent) || getLexer().is(AsmToken::Comma)) { + // Nothing to do here, fall into the code below with the '(' part of the + // memory operand consumed. + } else { + // It must be an parenthesized expression, parse it now. + if (getParser().ParseParenExpression(Disp)) + return true; + + // After parsing the base expression we could either have a parenthesized + // memory address or not. If not, return now. If so, eat the (. + if (getLexer().isNot(AsmToken::LParen)) { + // Unless we have a segment register, treat this as an immediate. + if (SegReg) + Op = X86Operand::CreateMem(SegReg, Disp, 0, 0, 1); + else + Op = X86Operand::CreateImm(Disp); + return false; + } + + // Eat the '('. + getLexer().Lex(); + } + } + + // If we reached here, then we just ate the ( of the memory operand. Process + // the rest of the memory operand. + unsigned BaseReg = 0, IndexReg = 0, Scale = 1; + + if (getLexer().is(AsmToken::Percent)) { + if (ParseRegister(Op)) + return true; + BaseReg = Op.getReg(); + } + + if (getLexer().is(AsmToken::Comma)) { + getLexer().Lex(); // Eat the comma. + + // Following the comma we should have either an index register, or a scale + // value. We don't support the later form, but we want to parse it + // correctly. + // + // Not that even though it would be completely consistent to support syntax + // like "1(%eax,,1)", the assembler doesn't. + if (getLexer().is(AsmToken::Percent)) { + if (ParseRegister(Op)) + return true; + IndexReg = Op.getReg(); + + if (getLexer().isNot(AsmToken::RParen)) { + // Parse the scale amount: + // ::= ',' [scale-expression] + if (getLexer().isNot(AsmToken::Comma)) + return true; + getLexer().Lex(); // Eat the comma. + + if (getLexer().isNot(AsmToken::RParen)) { + SMLoc Loc = getLexer().getTok().getLoc(); + + int64_t ScaleVal; + if (getParser().ParseAbsoluteExpression(ScaleVal)) + return true; + + // Validate the scale amount. + if (ScaleVal != 1 && ScaleVal != 2 && ScaleVal != 4 && ScaleVal != 8) + return Error(Loc, "scale factor in address must be 1, 2, 4 or 8"); + Scale = (unsigned)ScaleVal; + } + } + } else if (getLexer().isNot(AsmToken::RParen)) { + // Otherwise we have the unsupported form of a scale amount without an + // index. + SMLoc Loc = getLexer().getTok().getLoc(); + + int64_t Value; + if (getParser().ParseAbsoluteExpression(Value)) + return true; + + return Error(Loc, "cannot have scale factor without index register"); + } + } + + // Ok, we've eaten the memory operand, verify we have a ')' and eat it too. + if (getLexer().isNot(AsmToken::RParen)) + return Error(getLexer().getTok().getLoc(), + "unexpected token in memory operand"); + getLexer().Lex(); // Eat the ')'. + + Op = X86Operand::CreateMem(SegReg, Disp, BaseReg, IndexReg, Scale); + return false; +} + +bool X86ATTAsmParser::ParseInstruction(const StringRef &Name, MCInst &Inst) { + SmallVector Operands; + + Operands.push_back(X86Operand::CreateToken(Name)); + + SMLoc Loc = getLexer().getTok().getLoc(); + if (getLexer().isNot(AsmToken::EndOfStatement)) { + + // Parse '*' modifier. + if (getLexer().is(AsmToken::Star)) { + getLexer().Lex(); // Eat the star. + Operands.push_back(X86Operand::CreateToken("*")); + } + + // Read the first operand. + Operands.push_back(X86Operand()); + if (ParseOperand(Operands.back())) + return true; + + while (getLexer().is(AsmToken::Comma)) { + getLexer().Lex(); // Eat the comma. + + // Parse and remember the operand. + Operands.push_back(X86Operand()); + if (ParseOperand(Operands.back())) + return true; + } + } + + if (!MatchInstruction(Operands, Inst)) + return false; + + // FIXME: We should give nicer diagnostics about the exact failure. + + Error(Loc, "unrecognized instruction"); + return true; +} + +bool X86ATTAsmParser::ParseDirective(AsmToken DirectiveID) { + StringRef IDVal = DirectiveID.getIdentifier(); + if (IDVal == ".word") + return ParseDirectiveWord(2, DirectiveID.getLoc()); + return true; +} + +/// ParseDirectiveWord +/// ::= .word [ expression (, expression)* ] +bool X86ATTAsmParser::ParseDirectiveWord(unsigned Size, SMLoc L) { + if (getLexer().isNot(AsmToken::EndOfStatement)) { + for (;;) { + const MCExpr *Value; + if (getParser().ParseExpression(Value)) + return true; + + getParser().getStreamer().EmitValue(Value, Size); + + if (getLexer().is(AsmToken::EndOfStatement)) + break; + + // FIXME: Improve diagnostic. + if (getLexer().isNot(AsmToken::Comma)) + return Error(L, "unexpected token in directive"); + getLexer().Lex(); + } + } + + getLexer().Lex(); + return false; +} + +// Force static initialization. +extern "C" void LLVMInitializeX86AsmParser() { + RegisterAsmParser X(TheX86_32Target); + RegisterAsmParser Y(TheX86_64Target); +} + +#include "X86GenAsmMatcher.inc" diff --git a/libclamav/c++/llvm/lib/Target/X86/AsmPrinter/CMakeLists.txt b/libclamav/c++/llvm/lib/Target/X86/AsmPrinter/CMakeLists.txt new file mode 100644 index 000000000..b70a587ec --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/X86/AsmPrinter/CMakeLists.txt @@ -0,0 +1,9 @@ +include_directories( ${CMAKE_CURRENT_BINARY_DIR}/.. ${CMAKE_CURRENT_SOURCE_DIR}/.. ) + +add_llvm_library(LLVMX86AsmPrinter + X86ATTInstPrinter.cpp + X86AsmPrinter.cpp + X86IntelInstPrinter.cpp + X86MCInstLower.cpp + ) +add_dependencies(LLVMX86AsmPrinter X86CodeGenTable_gen) diff --git a/libclamav/c++/llvm/lib/Target/X86/AsmPrinter/Makefile b/libclamav/c++/llvm/lib/Target/X86/AsmPrinter/Makefile new file mode 100644 index 000000000..2368761ac --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/X86/AsmPrinter/Makefile @@ -0,0 +1,15 @@ +##===- lib/Target/X86/AsmPrinter/Makefile ------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## +LEVEL = ../../../.. +LIBRARYNAME = LLVMX86AsmPrinter + +# Hack: we need to include 'main' x86 target directory to grab private headers +CPPFLAGS = -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. + +include $(LEVEL)/Makefile.common diff --git a/libclamav/c++/llvm/lib/Target/X86/AsmPrinter/X86ATTInstPrinter.cpp b/libclamav/c++/llvm/lib/Target/X86/AsmPrinter/X86ATTInstPrinter.cpp new file mode 100644 index 000000000..8ec5b6219 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/X86/AsmPrinter/X86ATTInstPrinter.cpp @@ -0,0 +1,111 @@ +//===-- X86ATTInstPrinter.cpp - AT&T assembly instruction printing --------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file includes code for rendering MCInst instances as AT&T-style +// assembly. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "asm-printer" +#include "X86ATTInstPrinter.h" +#include "llvm/MC/MCInst.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/FormattedStream.h" +#include "X86GenInstrNames.inc" +using namespace llvm; + +// Include the auto-generated portion of the assembly writer. +#define MachineInstr MCInst +#define NO_ASM_WRITER_BOILERPLATE +#include "X86GenAsmWriter.inc" +#undef MachineInstr + +void X86ATTInstPrinter::printInst(const MCInst *MI) { printInstruction(MI); } + +void X86ATTInstPrinter::printSSECC(const MCInst *MI, unsigned Op) { + switch (MI->getOperand(Op).getImm()) { + default: llvm_unreachable("Invalid ssecc argument!"); + case 0: O << "eq"; break; + case 1: O << "lt"; break; + case 2: O << "le"; break; + case 3: O << "unord"; break; + case 4: O << "neq"; break; + case 5: O << "nlt"; break; + case 6: O << "nle"; break; + case 7: O << "ord"; break; + } +} + +/// print_pcrel_imm - This is used to print an immediate value that ends up +/// being encoded as a pc-relative value. These print slightly differently, for +/// example, a $ is not emitted. +void X86ATTInstPrinter::print_pcrel_imm(const MCInst *MI, unsigned OpNo) { + const MCOperand &Op = MI->getOperand(OpNo); + if (Op.isImm()) + O << Op.getImm(); + else { + assert(Op.isExpr() && "unknown pcrel immediate operand"); + Op.getExpr()->print(O, &MAI); + } +} + +void X86ATTInstPrinter::printOperand(const MCInst *MI, unsigned OpNo) { + + const MCOperand &Op = MI->getOperand(OpNo); + if (Op.isReg()) { + O << '%' << getRegisterName(Op.getReg()); + } else if (Op.isImm()) { + O << '$' << Op.getImm(); + } else { + assert(Op.isExpr() && "unknown operand kind in printOperand"); + O << '$'; + Op.getExpr()->print(O, &MAI); + } +} + +void X86ATTInstPrinter::printLeaMemReference(const MCInst *MI, unsigned Op) { + const MCOperand &BaseReg = MI->getOperand(Op); + const MCOperand &IndexReg = MI->getOperand(Op+2); + const MCOperand &DispSpec = MI->getOperand(Op+3); + + if (DispSpec.isImm()) { + int64_t DispVal = DispSpec.getImm(); + if (DispVal || (!IndexReg.getReg() && !BaseReg.getReg())) + O << DispVal; + } else { + assert(DispSpec.isExpr() && "non-immediate displacement for LEA?"); + DispSpec.getExpr()->print(O, &MAI); + } + + if (IndexReg.getReg() || BaseReg.getReg()) { + O << '('; + if (BaseReg.getReg()) + printOperand(MI, Op); + + if (IndexReg.getReg()) { + O << ','; + printOperand(MI, Op+2); + unsigned ScaleVal = MI->getOperand(Op+1).getImm(); + if (ScaleVal != 1) + O << ',' << ScaleVal; + } + O << ')'; + } +} + +void X86ATTInstPrinter::printMemReference(const MCInst *MI, unsigned Op) { + // If this has a segment register, print it. + if (MI->getOperand(Op+4).getReg()) { + printOperand(MI, Op+4); + O << ':'; + } + printLeaMemReference(MI, Op); +} diff --git a/libclamav/c++/llvm/lib/Target/X86/AsmPrinter/X86ATTInstPrinter.h b/libclamav/c++/llvm/lib/Target/X86/AsmPrinter/X86ATTInstPrinter.h new file mode 100644 index 000000000..3180618d1 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/X86/AsmPrinter/X86ATTInstPrinter.h @@ -0,0 +1,85 @@ +//===-- X86ATTInstPrinter.h - Convert X86 MCInst to assembly syntax -------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This class prints an X86 MCInst to AT&T style .s file syntax. +// +//===----------------------------------------------------------------------===// + +#ifndef X86_ATT_INST_PRINTER_H +#define X86_ATT_INST_PRINTER_H + +#include "llvm/MC/MCInstPrinter.h" + +namespace llvm { + class MCOperand; + +class X86ATTInstPrinter : public MCInstPrinter { +public: + X86ATTInstPrinter(raw_ostream &O, const MCAsmInfo &MAI) + : MCInstPrinter(O, MAI) {} + + + virtual void printInst(const MCInst *MI); + + // Autogenerated by tblgen. + void printInstruction(const MCInst *MI); + static const char *getRegisterName(unsigned RegNo); + + + void printOperand(const MCInst *MI, unsigned OpNo); + void printMemReference(const MCInst *MI, unsigned Op); + void printLeaMemReference(const MCInst *MI, unsigned Op); + void printSSECC(const MCInst *MI, unsigned Op); + void print_pcrel_imm(const MCInst *MI, unsigned OpNo); + + void printopaquemem(const MCInst *MI, unsigned OpNo) { + printMemReference(MI, OpNo); + } + + void printi8mem(const MCInst *MI, unsigned OpNo) { + printMemReference(MI, OpNo); + } + void printi16mem(const MCInst *MI, unsigned OpNo) { + printMemReference(MI, OpNo); + } + void printi32mem(const MCInst *MI, unsigned OpNo) { + printMemReference(MI, OpNo); + } + void printi64mem(const MCInst *MI, unsigned OpNo) { + printMemReference(MI, OpNo); + } + void printi128mem(const MCInst *MI, unsigned OpNo) { + printMemReference(MI, OpNo); + } + void printf32mem(const MCInst *MI, unsigned OpNo) { + printMemReference(MI, OpNo); + } + void printf64mem(const MCInst *MI, unsigned OpNo) { + printMemReference(MI, OpNo); + } + void printf80mem(const MCInst *MI, unsigned OpNo) { + printMemReference(MI, OpNo); + } + void printf128mem(const MCInst *MI, unsigned OpNo) { + printMemReference(MI, OpNo); + } + void printlea32mem(const MCInst *MI, unsigned OpNo) { + printLeaMemReference(MI, OpNo); + } + void printlea64mem(const MCInst *MI, unsigned OpNo) { + printLeaMemReference(MI, OpNo); + } + void printlea64_32mem(const MCInst *MI, unsigned OpNo) { + printLeaMemReference(MI, OpNo); + } +}; + +} + +#endif diff --git a/libclamav/c++/llvm/lib/Target/X86/AsmPrinter/X86AsmPrinter.cpp b/libclamav/c++/llvm/lib/Target/X86/AsmPrinter/X86AsmPrinter.cpp new file mode 100644 index 000000000..b88063f9c --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/X86/AsmPrinter/X86AsmPrinter.cpp @@ -0,0 +1,949 @@ +//===-- X86AsmPrinter.cpp - Convert X86 LLVM code to AT&T assembly --------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains a printer that converts from our internal representation +// of machine-dependent LLVM code to AT&T format assembly +// language. This printer is the output mechanism used by `llc'. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "asm-printer" +#include "X86AsmPrinter.h" +#include "X86ATTInstPrinter.h" +#include "X86IntelInstPrinter.h" +#include "X86MCInstLower.h" +#include "X86.h" +#include "X86COFF.h" +#include "X86COFFMachineModuleInfo.h" +#include "X86MachineFunctionInfo.h" +#include "X86TargetMachine.h" +#include "llvm/CallingConv.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Module.h" +#include "llvm/Type.h" +#include "llvm/Assembly/Writer.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCSectionMachO.h" +#include "llvm/MC/MCStreamer.h" +#include "llvm/MC/MCSymbol.h" +#include "llvm/CodeGen/MachineJumpTableInfo.h" +#include "llvm/CodeGen/MachineModuleInfoImpls.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/FormattedStream.h" +#include "llvm/Support/Mangler.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/Target/TargetLoweringObjectFile.h" +#include "llvm/Target/TargetOptions.h" +#include "llvm/Target/TargetRegistry.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/Statistic.h" +using namespace llvm; + +STATISTIC(EmittedInsts, "Number of machine instrs printed"); + +//===----------------------------------------------------------------------===// +// Primitive Helper Functions. +//===----------------------------------------------------------------------===// + +void X86AsmPrinter::printMCInst(const MCInst *MI) { + if (MAI->getAssemblerDialect() == 0) + X86ATTInstPrinter(O, *MAI).printInstruction(MI); + else + X86IntelInstPrinter(O, *MAI).printInstruction(MI); +} + +void X86AsmPrinter::PrintPICBaseSymbol() const { + // FIXME: Gross const cast hack. + X86AsmPrinter *AP = const_cast(this); + X86MCInstLower(OutContext, 0, *AP).GetPICBaseSymbol()->print(O, MAI); +} + +void X86AsmPrinter::emitFunctionHeader(const MachineFunction &MF) { + unsigned FnAlign = MF.getAlignment(); + const Function *F = MF.getFunction(); + + if (Subtarget->isTargetCygMing()) { + X86COFFMachineModuleInfo &COFFMMI = + MMI->getObjFileInfo(); + COFFMMI.DecorateCygMingName(CurrentFnName, F, *TM.getTargetData()); + } + + OutStreamer.SwitchSection(getObjFileLowering().SectionForGlobal(F, Mang, TM)); + EmitAlignment(FnAlign, F); + + switch (F->getLinkage()) { + default: llvm_unreachable("Unknown linkage type!"); + case Function::InternalLinkage: // Symbols default to internal. + case Function::PrivateLinkage: + break; + case Function::DLLExportLinkage: + case Function::ExternalLinkage: + O << "\t.globl\t" << CurrentFnName << '\n'; + break; + case Function::LinkerPrivateLinkage: + case Function::LinkOnceAnyLinkage: + case Function::LinkOnceODRLinkage: + case Function::WeakAnyLinkage: + case Function::WeakODRLinkage: + if (Subtarget->isTargetDarwin()) { + O << "\t.globl\t" << CurrentFnName << '\n'; + O << MAI->getWeakDefDirective() << CurrentFnName << '\n'; + } else if (Subtarget->isTargetCygMing()) { + O << "\t.globl\t" << CurrentFnName << "\n" + "\t.linkonce discard\n"; + } else { + O << "\t.weak\t" << CurrentFnName << '\n'; + } + break; + } + + printVisibility(CurrentFnName, F->getVisibility()); + + if (Subtarget->isTargetELF()) + O << "\t.type\t" << CurrentFnName << ",@function\n"; + else if (Subtarget->isTargetCygMing()) { + O << "\t.def\t " << CurrentFnName + << ";\t.scl\t" << + (F->hasInternalLinkage() ? COFF::C_STAT : COFF::C_EXT) + << ";\t.type\t" << (COFF::DT_FCN << COFF::N_BTSHFT) + << ";\t.endef\n"; + } + + O << CurrentFnName << ':'; + if (VerboseAsm) { + O.PadToColumn(MAI->getCommentColumn()); + O << MAI->getCommentString() << ' '; + WriteAsOperand(O, F, /*PrintType=*/false, F->getParent()); + } + O << '\n'; + + // Add some workaround for linkonce linkage on Cygwin\MinGW + if (Subtarget->isTargetCygMing() && + (F->hasLinkOnceLinkage() || F->hasWeakLinkage())) + O << "Lllvm$workaround$fake$stub$" << CurrentFnName << ":\n"; +} + +/// runOnMachineFunction - This uses the printMachineInstruction() +/// method to print assembly for each instruction. +/// +bool X86AsmPrinter::runOnMachineFunction(MachineFunction &MF) { + const Function *F = MF.getFunction(); + this->MF = &MF; + CallingConv::ID CC = F->getCallingConv(); + + SetupMachineFunction(MF); + O << "\n\n"; + + if (Subtarget->isTargetCOFF()) { + X86COFFMachineModuleInfo &COFFMMI = + MMI->getObjFileInfo(); + + // Populate function information map. Don't want to populate + // non-stdcall or non-fastcall functions' information right now. + if (CC == CallingConv::X86_StdCall || CC == CallingConv::X86_FastCall) + COFFMMI.AddFunctionInfo(F, *MF.getInfo()); + } + + // Print out constants referenced by the function + EmitConstantPool(MF.getConstantPool()); + + // Print the 'header' of function + emitFunctionHeader(MF); + + // Emit pre-function debug and/or EH information. + if (MAI->doesSupportDebugInformation() || MAI->doesSupportExceptionHandling()) + DW->BeginFunction(&MF); + + // Print out code for the function. + bool hasAnyRealCode = false; + for (MachineFunction::const_iterator I = MF.begin(), E = MF.end(); + I != E; ++I) { + // Print a label for the basic block. + EmitBasicBlockStart(I); + for (MachineBasicBlock::const_iterator II = I->begin(), IE = I->end(); + II != IE; ++II) { + // Print the assembly for the instruction. + if (!II->isLabel()) + hasAnyRealCode = true; + printMachineInstruction(II); + } + } + + if (Subtarget->isTargetDarwin() && !hasAnyRealCode) { + // If the function is empty, then we need to emit *something*. Otherwise, + // the function's label might be associated with something that it wasn't + // meant to be associated with. We emit a noop in this situation. + // We are assuming inline asms are code. + O << "\tnop\n"; + } + + if (MAI->hasDotTypeDotSizeDirective()) + O << "\t.size\t" << CurrentFnName << ", .-" << CurrentFnName << '\n'; + + // Emit post-function debug information. + if (MAI->doesSupportDebugInformation() || MAI->doesSupportExceptionHandling()) + DW->EndFunction(&MF); + + // Print out jump tables referenced by the function. + EmitJumpTableInfo(MF.getJumpTableInfo(), MF); + + // We didn't modify anything. + return false; +} + +/// printSymbolOperand - Print a raw symbol reference operand. This handles +/// jump tables, constant pools, global address and external symbols, all of +/// which print to a label with various suffixes for relocation types etc. +void X86AsmPrinter::printSymbolOperand(const MachineOperand &MO) { + switch (MO.getType()) { + default: llvm_unreachable("unknown symbol type!"); + case MachineOperand::MO_JumpTableIndex: + O << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() << '_' + << MO.getIndex(); + break; + case MachineOperand::MO_ConstantPoolIndex: + O << MAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << '_' + << MO.getIndex(); + printOffset(MO.getOffset()); + break; + case MachineOperand::MO_GlobalAddress: { + const GlobalValue *GV = MO.getGlobal(); + + const char *Suffix = ""; + if (MO.getTargetFlags() == X86II::MO_DARWIN_STUB) + Suffix = "$stub"; + else if (MO.getTargetFlags() == X86II::MO_DARWIN_NONLAZY || + MO.getTargetFlags() == X86II::MO_DARWIN_NONLAZY_PIC_BASE || + MO.getTargetFlags() == X86II::MO_DARWIN_HIDDEN_NONLAZY_PIC_BASE) + Suffix = "$non_lazy_ptr"; + + std::string Name = Mang->getMangledName(GV, Suffix, Suffix[0] != '\0'); + if (Subtarget->isTargetCygMing()) { + X86COFFMachineModuleInfo &COFFMMI = + MMI->getObjFileInfo(); + COFFMMI.DecorateCygMingName(Name, GV, *TM.getTargetData()); + } + + // Handle dllimport linkage. + if (MO.getTargetFlags() == X86II::MO_DLLIMPORT) + Name = "__imp_" + Name; + + if (MO.getTargetFlags() == X86II::MO_DARWIN_NONLAZY || + MO.getTargetFlags() == X86II::MO_DARWIN_NONLAZY_PIC_BASE) { + SmallString<128> NameStr; + Mang->getNameWithPrefix(NameStr, GV, true); + NameStr += "$non_lazy_ptr"; + MCSymbol *Sym = OutContext.GetOrCreateSymbol(NameStr.str()); + + const MCSymbol *&StubSym = + MMI->getObjFileInfo().getGVStubEntry(Sym); + if (StubSym == 0) { + NameStr.clear(); + Mang->getNameWithPrefix(NameStr, GV, false); + StubSym = OutContext.GetOrCreateSymbol(NameStr.str()); + } + } else if (MO.getTargetFlags() == X86II::MO_DARWIN_HIDDEN_NONLAZY_PIC_BASE){ + SmallString<128> NameStr; + Mang->getNameWithPrefix(NameStr, GV, true); + NameStr += "$non_lazy_ptr"; + MCSymbol *Sym = OutContext.GetOrCreateSymbol(NameStr.str()); + const MCSymbol *&StubSym = + MMI->getObjFileInfo().getHiddenGVStubEntry(Sym); + if (StubSym == 0) { + NameStr.clear(); + Mang->getNameWithPrefix(NameStr, GV, false); + StubSym = OutContext.GetOrCreateSymbol(NameStr.str()); + } + } else if (MO.getTargetFlags() == X86II::MO_DARWIN_STUB) { + SmallString<128> NameStr; + Mang->getNameWithPrefix(NameStr, GV, true); + NameStr += "$stub"; + MCSymbol *Sym = OutContext.GetOrCreateSymbol(NameStr.str()); + const MCSymbol *&StubSym = + MMI->getObjFileInfo().getFnStubEntry(Sym); + if (StubSym == 0) { + NameStr.clear(); + Mang->getNameWithPrefix(NameStr, GV, false); + StubSym = OutContext.GetOrCreateSymbol(NameStr.str()); + } + } + + // If the name begins with a dollar-sign, enclose it in parens. We do this + // to avoid having it look like an integer immediate to the assembler. + if (Name[0] == '$') + O << '(' << Name << ')'; + else + O << Name; + + printOffset(MO.getOffset()); + break; + } + case MachineOperand::MO_ExternalSymbol: { + std::string Name = Mang->makeNameProper(MO.getSymbolName()); + if (MO.getTargetFlags() == X86II::MO_DARWIN_STUB) { + Name += "$stub"; + MCSymbol *Sym = OutContext.GetOrCreateSymbol(StringRef(Name)); + const MCSymbol *&StubSym = + MMI->getObjFileInfo().getFnStubEntry(Sym); + if (StubSym == 0) { + Name.erase(Name.end()-5, Name.end()); + StubSym = OutContext.GetOrCreateSymbol(StringRef(Name)); + } + } + + // If the name begins with a dollar-sign, enclose it in parens. We do this + // to avoid having it look like an integer immediate to the assembler. + if (Name[0] == '$') + O << '(' << Name << ')'; + else + O << Name; + break; + } + } + + switch (MO.getTargetFlags()) { + default: + llvm_unreachable("Unknown target flag on GV operand"); + case X86II::MO_NO_FLAG: // No flag. + break; + case X86II::MO_DARWIN_NONLAZY: + case X86II::MO_DLLIMPORT: + case X86II::MO_DARWIN_STUB: + // These affect the name of the symbol, not any suffix. + break; + case X86II::MO_GOT_ABSOLUTE_ADDRESS: + O << " + [.-"; + PrintPICBaseSymbol(); + O << ']'; + break; + case X86II::MO_PIC_BASE_OFFSET: + case X86II::MO_DARWIN_NONLAZY_PIC_BASE: + case X86II::MO_DARWIN_HIDDEN_NONLAZY_PIC_BASE: + O << '-'; + PrintPICBaseSymbol(); + break; + case X86II::MO_TLSGD: O << "@TLSGD"; break; + case X86II::MO_GOTTPOFF: O << "@GOTTPOFF"; break; + case X86II::MO_INDNTPOFF: O << "@INDNTPOFF"; break; + case X86II::MO_TPOFF: O << "@TPOFF"; break; + case X86II::MO_NTPOFF: O << "@NTPOFF"; break; + case X86II::MO_GOTPCREL: O << "@GOTPCREL"; break; + case X86II::MO_GOT: O << "@GOT"; break; + case X86II::MO_GOTOFF: O << "@GOTOFF"; break; + case X86II::MO_PLT: O << "@PLT"; break; + } +} + +/// print_pcrel_imm - This is used to print an immediate value that ends up +/// being encoded as a pc-relative value. These print slightly differently, for +/// example, a $ is not emitted. +void X86AsmPrinter::print_pcrel_imm(const MachineInstr *MI, unsigned OpNo) { + const MachineOperand &MO = MI->getOperand(OpNo); + switch (MO.getType()) { + default: llvm_unreachable("Unknown pcrel immediate operand"); + case MachineOperand::MO_Immediate: + O << MO.getImm(); + return; + case MachineOperand::MO_MachineBasicBlock: + GetMBBSymbol(MO.getMBB()->getNumber())->print(O, MAI); + return; + case MachineOperand::MO_GlobalAddress: + case MachineOperand::MO_ExternalSymbol: + printSymbolOperand(MO); + return; + } +} + + +void X86AsmPrinter::printOperand(const MachineInstr *MI, unsigned OpNo, + const char *Modifier) { + const MachineOperand &MO = MI->getOperand(OpNo); + switch (MO.getType()) { + default: llvm_unreachable("unknown operand type!"); + case MachineOperand::MO_Register: { + O << '%'; + unsigned Reg = MO.getReg(); + if (Modifier && strncmp(Modifier, "subreg", strlen("subreg")) == 0) { + EVT VT = (strcmp(Modifier+6,"64") == 0) ? + MVT::i64 : ((strcmp(Modifier+6, "32") == 0) ? MVT::i32 : + ((strcmp(Modifier+6,"16") == 0) ? MVT::i16 : MVT::i8)); + Reg = getX86SubSuperRegister(Reg, VT); + } + O << X86ATTInstPrinter::getRegisterName(Reg); + return; + } + + case MachineOperand::MO_Immediate: + O << '$' << MO.getImm(); + return; + + case MachineOperand::MO_JumpTableIndex: + case MachineOperand::MO_ConstantPoolIndex: + case MachineOperand::MO_GlobalAddress: + case MachineOperand::MO_ExternalSymbol: { + O << '$'; + printSymbolOperand(MO); + break; + } + } +} + +void X86AsmPrinter::printSSECC(const MachineInstr *MI, unsigned Op) { + unsigned char value = MI->getOperand(Op).getImm(); + assert(value <= 7 && "Invalid ssecc argument!"); + switch (value) { + case 0: O << "eq"; break; + case 1: O << "lt"; break; + case 2: O << "le"; break; + case 3: O << "unord"; break; + case 4: O << "neq"; break; + case 5: O << "nlt"; break; + case 6: O << "nle"; break; + case 7: O << "ord"; break; + } +} + +void X86AsmPrinter::printLeaMemReference(const MachineInstr *MI, unsigned Op, + const char *Modifier) { + const MachineOperand &BaseReg = MI->getOperand(Op); + const MachineOperand &IndexReg = MI->getOperand(Op+2); + const MachineOperand &DispSpec = MI->getOperand(Op+3); + + // If we really don't want to print out (rip), don't. + bool HasBaseReg = BaseReg.getReg() != 0; + if (HasBaseReg && Modifier && !strcmp(Modifier, "no-rip") && + BaseReg.getReg() == X86::RIP) + HasBaseReg = false; + + // HasParenPart - True if we will print out the () part of the mem ref. + bool HasParenPart = IndexReg.getReg() || HasBaseReg; + + if (DispSpec.isImm()) { + int DispVal = DispSpec.getImm(); + if (DispVal || !HasParenPart) + O << DispVal; + } else { + assert(DispSpec.isGlobal() || DispSpec.isCPI() || + DispSpec.isJTI() || DispSpec.isSymbol()); + printSymbolOperand(MI->getOperand(Op+3)); + } + + if (HasParenPart) { + assert(IndexReg.getReg() != X86::ESP && + "X86 doesn't allow scaling by ESP"); + + O << '('; + if (HasBaseReg) + printOperand(MI, Op, Modifier); + + if (IndexReg.getReg()) { + O << ','; + printOperand(MI, Op+2, Modifier); + unsigned ScaleVal = MI->getOperand(Op+1).getImm(); + if (ScaleVal != 1) + O << ',' << ScaleVal; + } + O << ')'; + } +} + +void X86AsmPrinter::printMemReference(const MachineInstr *MI, unsigned Op, + const char *Modifier) { + assert(isMem(MI, Op) && "Invalid memory reference!"); + const MachineOperand &Segment = MI->getOperand(Op+4); + if (Segment.getReg()) { + printOperand(MI, Op+4, Modifier); + O << ':'; + } + printLeaMemReference(MI, Op, Modifier); +} + +void X86AsmPrinter::printPICJumpTableSetLabel(unsigned uid, + const MachineBasicBlock *MBB) const { + if (!MAI->getSetDirective()) + return; + + // We don't need .set machinery if we have GOT-style relocations + if (Subtarget->isPICStyleGOT()) + return; + + O << MAI->getSetDirective() << ' ' << MAI->getPrivateGlobalPrefix() + << getFunctionNumber() << '_' << uid << "_set_" << MBB->getNumber() << ','; + + GetMBBSymbol(MBB->getNumber())->print(O, MAI); + + if (Subtarget->isPICStyleRIPRel()) + O << '-' << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() + << '_' << uid << '\n'; + else { + O << '-'; + PrintPICBaseSymbol(); + O << '\n'; + } +} + + +void X86AsmPrinter::printPICLabel(const MachineInstr *MI, unsigned Op) { + PrintPICBaseSymbol(); + O << '\n'; + PrintPICBaseSymbol(); + O << ':'; +} + +void X86AsmPrinter::printPICJumpTableEntry(const MachineJumpTableInfo *MJTI, + const MachineBasicBlock *MBB, + unsigned uid) const { + const char *JTEntryDirective = MJTI->getEntrySize() == 4 ? + MAI->getData32bitsDirective() : MAI->getData64bitsDirective(); + + O << JTEntryDirective << ' '; + + if (Subtarget->isPICStyleRIPRel() || Subtarget->isPICStyleStubPIC()) { + O << MAI->getPrivateGlobalPrefix() << getFunctionNumber() + << '_' << uid << "_set_" << MBB->getNumber(); + } else if (Subtarget->isPICStyleGOT()) { + GetMBBSymbol(MBB->getNumber())->print(O, MAI); + O << "@GOTOFF"; + } else + GetMBBSymbol(MBB->getNumber())->print(O, MAI); +} + +bool X86AsmPrinter::printAsmMRegister(const MachineOperand &MO, char Mode) { + unsigned Reg = MO.getReg(); + switch (Mode) { + default: return true; // Unknown mode. + case 'b': // Print QImode register + Reg = getX86SubSuperRegister(Reg, MVT::i8); + break; + case 'h': // Print QImode high register + Reg = getX86SubSuperRegister(Reg, MVT::i8, true); + break; + case 'w': // Print HImode register + Reg = getX86SubSuperRegister(Reg, MVT::i16); + break; + case 'k': // Print SImode register + Reg = getX86SubSuperRegister(Reg, MVT::i32); + break; + case 'q': // Print DImode register + Reg = getX86SubSuperRegister(Reg, MVT::i64); + break; + } + + O << '%' << X86ATTInstPrinter::getRegisterName(Reg); + return false; +} + +/// PrintAsmOperand - Print out an operand for an inline asm expression. +/// +bool X86AsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, + unsigned AsmVariant, + const char *ExtraCode) { + // Does this asm operand have a single letter operand modifier? + if (ExtraCode && ExtraCode[0]) { + if (ExtraCode[1] != 0) return true; // Unknown modifier. + + const MachineOperand &MO = MI->getOperand(OpNo); + + switch (ExtraCode[0]) { + default: return true; // Unknown modifier. + case 'a': // This is an address. Currently only 'i' and 'r' are expected. + if (MO.isImm()) { + O << MO.getImm(); + return false; + } + if (MO.isGlobal() || MO.isCPI() || MO.isJTI() || MO.isSymbol()) { + printSymbolOperand(MO); + return false; + } + if (MO.isReg()) { + O << '('; + printOperand(MI, OpNo); + O << ')'; + return false; + } + return true; + + case 'c': // Don't print "$" before a global var name or constant. + if (MO.isImm()) + O << MO.getImm(); + else if (MO.isGlobal() || MO.isCPI() || MO.isJTI() || MO.isSymbol()) + printSymbolOperand(MO); + else + printOperand(MI, OpNo); + return false; + + case 'A': // Print '*' before a register (it must be a register) + if (MO.isReg()) { + O << '*'; + printOperand(MI, OpNo); + return false; + } + return true; + + case 'b': // Print QImode register + case 'h': // Print QImode high register + case 'w': // Print HImode register + case 'k': // Print SImode register + case 'q': // Print DImode register + if (MO.isReg()) + return printAsmMRegister(MO, ExtraCode[0]); + printOperand(MI, OpNo); + return false; + + case 'P': // This is the operand of a call, treat specially. + print_pcrel_imm(MI, OpNo); + return false; + + case 'n': // Negate the immediate or print a '-' before the operand. + // Note: this is a temporary solution. It should be handled target + // independently as part of the 'MC' work. + if (MO.isImm()) { + O << -MO.getImm(); + return false; + } + O << '-'; + } + } + + printOperand(MI, OpNo); + return false; +} + +bool X86AsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, + unsigned OpNo, unsigned AsmVariant, + const char *ExtraCode) { + if (ExtraCode && ExtraCode[0]) { + if (ExtraCode[1] != 0) return true; // Unknown modifier. + + switch (ExtraCode[0]) { + default: return true; // Unknown modifier. + case 'b': // Print QImode register + case 'h': // Print QImode high register + case 'w': // Print HImode register + case 'k': // Print SImode register + case 'q': // Print SImode register + // These only apply to registers, ignore on mem. + break; + case 'P': // Don't print @PLT, but do print as memory. + printMemReference(MI, OpNo, "no-rip"); + return false; + } + } + printMemReference(MI, OpNo); + return false; +} + + + +/// printMachineInstruction -- Print out a single X86 LLVM instruction MI in +/// AT&T syntax to the current output stream. +/// +void X86AsmPrinter::printMachineInstruction(const MachineInstr *MI) { + ++EmittedInsts; + + processDebugLoc(MI, true); + + printInstructionThroughMCStreamer(MI); + + if (VerboseAsm) + EmitComments(*MI); + O << '\n'; + + processDebugLoc(MI, false); +} + +void X86AsmPrinter::PrintGlobalVariable(const GlobalVariable* GVar) { + if (!GVar->hasInitializer()) + return; // External global require no code + + // Check to see if this is a special global used by LLVM, if so, emit it. + if (EmitSpecialLLVMGlobal(GVar)) { + if (Subtarget->isTargetDarwin() && + TM.getRelocationModel() == Reloc::Static) { + if (GVar->getName() == "llvm.global_ctors") + O << ".reference .constructors_used\n"; + else if (GVar->getName() == "llvm.global_dtors") + O << ".reference .destructors_used\n"; + } + return; + } + + const TargetData *TD = TM.getTargetData(); + + std::string name = Mang->getMangledName(GVar); + Constant *C = GVar->getInitializer(); + const Type *Type = C->getType(); + unsigned Size = TD->getTypeAllocSize(Type); + unsigned Align = TD->getPreferredAlignmentLog(GVar); + + printVisibility(name, GVar->getVisibility()); + + if (Subtarget->isTargetELF()) + O << "\t.type\t" << name << ",@object\n"; + + + SectionKind GVKind = TargetLoweringObjectFile::getKindForGlobal(GVar, TM); + const MCSection *TheSection = + getObjFileLowering().SectionForGlobal(GVar, GVKind, Mang, TM); + OutStreamer.SwitchSection(TheSection); + + // FIXME: get this stuff from section kind flags. + if (C->isNullValue() && !GVar->hasSection() && + // Don't put things that should go in the cstring section into "comm". + !TheSection->getKind().isMergeableCString()) { + if (GVar->hasExternalLinkage()) { + if (const char *Directive = MAI->getZeroFillDirective()) { + O << "\t.globl " << name << '\n'; + O << Directive << "__DATA, __common, " << name << ", " + << Size << ", " << Align << '\n'; + return; + } + } + + if (!GVar->isThreadLocal() && + (GVar->hasLocalLinkage() || GVar->isWeakForLinker())) { + if (Size == 0) Size = 1; // .comm Foo, 0 is undefined, avoid it. + + if (MAI->getLCOMMDirective() != NULL) { + if (GVar->hasLocalLinkage()) { + O << MAI->getLCOMMDirective() << name << ',' << Size; + if (Subtarget->isTargetDarwin()) + O << ',' << Align; + } else if (Subtarget->isTargetDarwin() && !GVar->hasCommonLinkage()) { + O << "\t.globl " << name << '\n' + << MAI->getWeakDefDirective() << name << '\n'; + EmitAlignment(Align, GVar); + O << name << ":"; + if (VerboseAsm) { + O.PadToColumn(MAI->getCommentColumn()); + O << MAI->getCommentString() << ' '; + WriteAsOperand(O, GVar, /*PrintType=*/false, GVar->getParent()); + } + O << '\n'; + EmitGlobalConstant(C); + return; + } else { + O << MAI->getCOMMDirective() << name << ',' << Size; + if (MAI->getCOMMDirectiveTakesAlignment()) + O << ',' << (MAI->getAlignmentIsInBytes() ? (1 << Align) : Align); + } + } else { + if (!Subtarget->isTargetCygMing()) { + if (GVar->hasLocalLinkage()) + O << "\t.local\t" << name << '\n'; + } + O << MAI->getCOMMDirective() << name << ',' << Size; + if (MAI->getCOMMDirectiveTakesAlignment()) + O << ',' << (MAI->getAlignmentIsInBytes() ? (1 << Align) : Align); + } + if (VerboseAsm) { + O.PadToColumn(MAI->getCommentColumn()); + O << MAI->getCommentString() << ' '; + WriteAsOperand(O, GVar, /*PrintType=*/false, GVar->getParent()); + } + O << '\n'; + return; + } + } + + switch (GVar->getLinkage()) { + case GlobalValue::CommonLinkage: + case GlobalValue::LinkOnceAnyLinkage: + case GlobalValue::LinkOnceODRLinkage: + case GlobalValue::WeakAnyLinkage: + case GlobalValue::WeakODRLinkage: + case GlobalValue::LinkerPrivateLinkage: + if (Subtarget->isTargetDarwin()) { + O << "\t.globl " << name << '\n' + << MAI->getWeakDefDirective() << name << '\n'; + } else if (Subtarget->isTargetCygMing()) { + O << "\t.globl\t" << name << "\n" + "\t.linkonce same_size\n"; + } else { + O << "\t.weak\t" << name << '\n'; + } + break; + case GlobalValue::DLLExportLinkage: + case GlobalValue::AppendingLinkage: + // FIXME: appending linkage variables should go into a section of + // their name or something. For now, just emit them as external. + case GlobalValue::ExternalLinkage: + // If external or appending, declare as a global symbol + O << "\t.globl " << name << '\n'; + // FALL THROUGH + case GlobalValue::PrivateLinkage: + case GlobalValue::InternalLinkage: + break; + default: + llvm_unreachable("Unknown linkage type!"); + } + + EmitAlignment(Align, GVar); + O << name << ":"; + if (VerboseAsm){ + O.PadToColumn(MAI->getCommentColumn()); + O << MAI->getCommentString() << ' '; + WriteAsOperand(O, GVar, /*PrintType=*/false, GVar->getParent()); + } + O << '\n'; + + EmitGlobalConstant(C); + + if (MAI->hasDotTypeDotSizeDirective()) + O << "\t.size\t" << name << ", " << Size << '\n'; +} + +void X86AsmPrinter::EmitEndOfAsmFile(Module &M) { + if (Subtarget->isTargetDarwin()) { + // All darwin targets use mach-o. + TargetLoweringObjectFileMachO &TLOFMacho = + static_cast(getObjFileLowering()); + + MachineModuleInfoMachO &MMIMacho = + MMI->getObjFileInfo(); + + // Output stubs for dynamically-linked functions. + MachineModuleInfoMachO::SymbolListTy Stubs; + + Stubs = MMIMacho.GetFnStubList(); + if (!Stubs.empty()) { + const MCSection *TheSection = + TLOFMacho.getMachOSection("__IMPORT", "__jump_table", + MCSectionMachO::S_SYMBOL_STUBS | + MCSectionMachO::S_ATTR_SELF_MODIFYING_CODE | + MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS, + 5, SectionKind::getMetadata()); + OutStreamer.SwitchSection(TheSection); + + for (unsigned i = 0, e = Stubs.size(); i != e; ++i) { + Stubs[i].first->print(O, MAI); + O << ":\n" << "\t.indirect_symbol "; + // Get the MCSymbol without the $stub suffix. + Stubs[i].second->print(O, MAI); + O << "\n\thlt ; hlt ; hlt ; hlt ; hlt\n"; + } + O << '\n'; + + Stubs.clear(); + } + + // Output stubs for external and common global variables. + Stubs = MMIMacho.GetGVStubList(); + if (!Stubs.empty()) { + const MCSection *TheSection = + TLOFMacho.getMachOSection("__IMPORT", "__pointers", + MCSectionMachO::S_NON_LAZY_SYMBOL_POINTERS, + SectionKind::getMetadata()); + OutStreamer.SwitchSection(TheSection); + + for (unsigned i = 0, e = Stubs.size(); i != e; ++i) { + Stubs[i].first->print(O, MAI); + O << ":\n\t.indirect_symbol "; + Stubs[i].second->print(O, MAI); + O << "\n\t.long\t0\n"; + } + Stubs.clear(); + } + + Stubs = MMIMacho.GetHiddenGVStubList(); + if (!Stubs.empty()) { + OutStreamer.SwitchSection(getObjFileLowering().getDataSection()); + EmitAlignment(2); + + for (unsigned i = 0, e = Stubs.size(); i != e; ++i) { + Stubs[i].first->print(O, MAI); + O << ":\n" << MAI->getData32bitsDirective(); + Stubs[i].second->print(O, MAI); + O << '\n'; + } + Stubs.clear(); + } + + // Funny Darwin hack: This flag tells the linker that no global symbols + // contain code that falls through to other global symbols (e.g. the obvious + // implementation of multiple entry points). If this doesn't occur, the + // linker can safely perform dead code stripping. Since LLVM never + // generates code that does this, it is always safe to set. + OutStreamer.EmitAssemblerFlag(MCStreamer::SubsectionsViaSymbols); + } + + if (Subtarget->isTargetCOFF()) { + X86COFFMachineModuleInfo &COFFMMI = + MMI->getObjFileInfo(); + + // Emit type information for external functions + for (X86COFFMachineModuleInfo::stub_iterator I = COFFMMI.stub_begin(), + E = COFFMMI.stub_end(); I != E; ++I) { + O << "\t.def\t " << I->getKeyData() + << ";\t.scl\t" << COFF::C_EXT + << ";\t.type\t" << (COFF::DT_FCN << COFF::N_BTSHFT) + << ";\t.endef\n"; + } + + if (Subtarget->isTargetCygMing()) { + // Necessary for dllexport support + std::vector DLLExportedFns, DLLExportedGlobals; + + TargetLoweringObjectFileCOFF &TLOFCOFF = + static_cast(getObjFileLowering()); + + for (Module::const_iterator I = M.begin(), E = M.end(); I != E; ++I) + if (I->hasDLLExportLinkage()) { + std::string Name = Mang->getMangledName(I); + COFFMMI.DecorateCygMingName(Name, I, *TM.getTargetData()); + DLLExportedFns.push_back(Name); + } + + for (Module::const_global_iterator I = M.global_begin(), + E = M.global_end(); I != E; ++I) + if (I->hasDLLExportLinkage()) { + std::string Name = Mang->getMangledName(I); + COFFMMI.DecorateCygMingName(Name, I, *TM.getTargetData()); + DLLExportedGlobals.push_back(Mang->getMangledName(I)); + } + + // Output linker support code for dllexported globals on windows. + if (!DLLExportedGlobals.empty() || !DLLExportedFns.empty()) { + OutStreamer.SwitchSection(TLOFCOFF.getCOFFSection(".section .drectve", + true, + SectionKind::getMetadata())); + for (unsigned i = 0, e = DLLExportedGlobals.size(); i != e; ++i) + O << "\t.ascii \" -export:" << DLLExportedGlobals[i] << ",data\"\n"; + + for (unsigned i = 0, e = DLLExportedFns.size(); i != e; ++i) + O << "\t.ascii \" -export:" << DLLExportedFns[i] << "\"\n"; + } + } + } +} + + +//===----------------------------------------------------------------------===// +// Target Registry Stuff +//===----------------------------------------------------------------------===// + +static MCInstPrinter *createX86MCInstPrinter(const Target &T, + unsigned SyntaxVariant, + const MCAsmInfo &MAI, + raw_ostream &O) { + if (SyntaxVariant == 0) + return new X86ATTInstPrinter(O, MAI); + if (SyntaxVariant == 1) + return new X86IntelInstPrinter(O, MAI); + return 0; +} + +// Force static initialization. +extern "C" void LLVMInitializeX86AsmPrinter() { + RegisterAsmPrinter X(TheX86_32Target); + RegisterAsmPrinter Y(TheX86_64Target); + + TargetRegistry::RegisterMCInstPrinter(TheX86_32Target,createX86MCInstPrinter); + TargetRegistry::RegisterMCInstPrinter(TheX86_64Target,createX86MCInstPrinter); +} diff --git a/libclamav/c++/llvm/lib/Target/X86/AsmPrinter/X86AsmPrinter.h b/libclamav/c++/llvm/lib/Target/X86/AsmPrinter/X86AsmPrinter.h new file mode 100644 index 000000000..0351829b0 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/X86/AsmPrinter/X86AsmPrinter.h @@ -0,0 +1,150 @@ +//===-- X86AsmPrinter.h - Convert X86 LLVM code to assembly -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// AT&T assembly code printer class. +// +//===----------------------------------------------------------------------===// + +#ifndef X86ASMPRINTER_H +#define X86ASMPRINTER_H + +#include "../X86.h" +#include "../X86MachineFunctionInfo.h" +#include "../X86TargetMachine.h" +#include "llvm/ADT/StringSet.h" +#include "llvm/CodeGen/AsmPrinter.h" +#include "llvm/CodeGen/DwarfWriter.h" +#include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/CodeGen/ValueTypes.h" +#include "llvm/Support/Compiler.h" + +namespace llvm { + +class MachineJumpTableInfo; +class MCContext; +class MCInst; +class MCStreamer; +class MCSymbol; + +class VISIBILITY_HIDDEN X86AsmPrinter : public AsmPrinter { + const X86Subtarget *Subtarget; + public: + explicit X86AsmPrinter(formatted_raw_ostream &O, TargetMachine &TM, + const MCAsmInfo *T, bool V) + : AsmPrinter(O, TM, T, V) { + Subtarget = &TM.getSubtarget(); + } + + virtual const char *getPassName() const { + return "X86 AT&T-Style Assembly Printer"; + } + + const X86Subtarget &getSubtarget() const { return *Subtarget; } + + void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + AU.addRequired(); + AU.addRequired(); + AsmPrinter::getAnalysisUsage(AU); + } + + + virtual void EmitEndOfAsmFile(Module &M); + + void printInstructionThroughMCStreamer(const MachineInstr *MI); + + + void printMCInst(const MCInst *MI); + + void printSymbolOperand(const MachineOperand &MO); + + + + // These methods are used by the tablegen'erated instruction printer. + void printOperand(const MachineInstr *MI, unsigned OpNo, + const char *Modifier = 0); + void print_pcrel_imm(const MachineInstr *MI, unsigned OpNo); + + void printopaquemem(const MachineInstr *MI, unsigned OpNo) { + printMemReference(MI, OpNo); + } + + void printi8mem(const MachineInstr *MI, unsigned OpNo) { + printMemReference(MI, OpNo); + } + void printi16mem(const MachineInstr *MI, unsigned OpNo) { + printMemReference(MI, OpNo); + } + void printi32mem(const MachineInstr *MI, unsigned OpNo) { + printMemReference(MI, OpNo); + } + void printi64mem(const MachineInstr *MI, unsigned OpNo) { + printMemReference(MI, OpNo); + } + void printi128mem(const MachineInstr *MI, unsigned OpNo) { + printMemReference(MI, OpNo); + } + void printf32mem(const MachineInstr *MI, unsigned OpNo) { + printMemReference(MI, OpNo); + } + void printf64mem(const MachineInstr *MI, unsigned OpNo) { + printMemReference(MI, OpNo); + } + void printf80mem(const MachineInstr *MI, unsigned OpNo) { + printMemReference(MI, OpNo); + } + void printf128mem(const MachineInstr *MI, unsigned OpNo) { + printMemReference(MI, OpNo); + } + void printlea32mem(const MachineInstr *MI, unsigned OpNo) { + printLeaMemReference(MI, OpNo); + } + void printlea64mem(const MachineInstr *MI, unsigned OpNo) { + printLeaMemReference(MI, OpNo); + } + void printlea64_32mem(const MachineInstr *MI, unsigned OpNo) { + printLeaMemReference(MI, OpNo, "subreg64"); + } + + bool printAsmMRegister(const MachineOperand &MO, char Mode); + bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, + unsigned AsmVariant, const char *ExtraCode); + bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo, + unsigned AsmVariant, const char *ExtraCode); + + void printMachineInstruction(const MachineInstr *MI); + void printSSECC(const MachineInstr *MI, unsigned Op); + void printMemReference(const MachineInstr *MI, unsigned Op, + const char *Modifier=NULL); + void printLeaMemReference(const MachineInstr *MI, unsigned Op, + const char *Modifier=NULL); + void printPICJumpTableSetLabel(unsigned uid, + const MachineBasicBlock *MBB) const; + void printPICJumpTableSetLabel(unsigned uid, unsigned uid2, + const MachineBasicBlock *MBB) const { + AsmPrinter::printPICJumpTableSetLabel(uid, uid2, MBB); + } + void printPICJumpTableEntry(const MachineJumpTableInfo *MJTI, + const MachineBasicBlock *MBB, + unsigned uid) const; + + void printPICLabel(const MachineInstr *MI, unsigned Op); + void PrintGlobalVariable(const GlobalVariable* GVar); + + void PrintPICBaseSymbol() const; + + bool runOnMachineFunction(MachineFunction &F); + + void emitFunctionHeader(const MachineFunction &MF); + +}; + +} // end namespace llvm + +#endif diff --git a/libclamav/c++/llvm/lib/Target/X86/AsmPrinter/X86IntelInstPrinter.cpp b/libclamav/c++/llvm/lib/Target/X86/AsmPrinter/X86IntelInstPrinter.cpp new file mode 100644 index 000000000..fde590235 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/X86/AsmPrinter/X86IntelInstPrinter.cpp @@ -0,0 +1,131 @@ +//===-- X86IntelInstPrinter.cpp - AT&T assembly instruction printing ------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file includes code for rendering MCInst instances as AT&T-style +// assembly. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "asm-printer" +#include "X86IntelInstPrinter.h" +#include "llvm/MC/MCInst.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/FormattedStream.h" +#include "X86GenInstrNames.inc" +using namespace llvm; + +// Include the auto-generated portion of the assembly writer. +#define MachineInstr MCInst +#define NO_ASM_WRITER_BOILERPLATE +#include "X86GenAsmWriter1.inc" +#undef MachineInstr + +void X86IntelInstPrinter::printInst(const MCInst *MI) { printInstruction(MI); } + +void X86IntelInstPrinter::printSSECC(const MCInst *MI, unsigned Op) { + switch (MI->getOperand(Op).getImm()) { + default: llvm_unreachable("Invalid ssecc argument!"); + case 0: O << "eq"; break; + case 1: O << "lt"; break; + case 2: O << "le"; break; + case 3: O << "unord"; break; + case 4: O << "neq"; break; + case 5: O << "nlt"; break; + case 6: O << "nle"; break; + case 7: O << "ord"; break; + } +} + +/// print_pcrel_imm - This is used to print an immediate value that ends up +/// being encoded as a pc-relative value. +void X86IntelInstPrinter::print_pcrel_imm(const MCInst *MI, unsigned OpNo) { + const MCOperand &Op = MI->getOperand(OpNo); + if (Op.isImm()) + O << Op.getImm(); + else { + assert(Op.isExpr() && "unknown pcrel immediate operand"); + Op.getExpr()->print(O, &MAI); + } +} + +static void PrintRegName(raw_ostream &O, StringRef RegName) { + for (unsigned i = 0, e = RegName.size(); i != e; ++i) + O << (char)toupper(RegName[i]); +} + +void X86IntelInstPrinter::printOperand(const MCInst *MI, unsigned OpNo, + const char *Modifier) { + assert(Modifier == 0 && "Modifiers should not be used"); + + const MCOperand &Op = MI->getOperand(OpNo); + if (Op.isReg()) { + PrintRegName(O, getRegisterName(Op.getReg())); + } else if (Op.isImm()) { + O << Op.getImm(); + } else { + assert(Op.isExpr() && "unknown operand kind in printOperand"); + Op.getExpr()->print(O, &MAI); + } +} + +void X86IntelInstPrinter::printLeaMemReference(const MCInst *MI, unsigned Op) { + const MCOperand &BaseReg = MI->getOperand(Op); + unsigned ScaleVal = MI->getOperand(Op+1).getImm(); + const MCOperand &IndexReg = MI->getOperand(Op+2); + const MCOperand &DispSpec = MI->getOperand(Op+3); + + O << '['; + + bool NeedPlus = false; + if (BaseReg.getReg()) { + printOperand(MI, Op); + NeedPlus = true; + } + + if (IndexReg.getReg()) { + if (NeedPlus) O << " + "; + if (ScaleVal != 1) + O << ScaleVal << '*'; + printOperand(MI, Op+2); + NeedPlus = true; + } + + + if (!DispSpec.isImm()) { + if (NeedPlus) O << " + "; + assert(DispSpec.isExpr() && "non-immediate displacement for LEA?"); + DispSpec.getExpr()->print(O, &MAI); + } else { + int64_t DispVal = DispSpec.getImm(); + if (DispVal || (!IndexReg.getReg() && !BaseReg.getReg())) { + if (NeedPlus) { + if (DispVal > 0) + O << " + "; + else { + O << " - "; + DispVal = -DispVal; + } + } + O << DispVal; + } + } + + O << ']'; +} + +void X86IntelInstPrinter::printMemReference(const MCInst *MI, unsigned Op) { + // If this has a segment register, print it. + if (MI->getOperand(Op+4).getReg()) { + printOperand(MI, Op+4); + O << ':'; + } + printLeaMemReference(MI, Op); +} diff --git a/libclamav/c++/llvm/lib/Target/X86/AsmPrinter/X86IntelInstPrinter.h b/libclamav/c++/llvm/lib/Target/X86/AsmPrinter/X86IntelInstPrinter.h new file mode 100644 index 000000000..1976177eb --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/X86/AsmPrinter/X86IntelInstPrinter.h @@ -0,0 +1,99 @@ +//===-- X86IntelInstPrinter.h - Convert X86 MCInst to assembly syntax -----===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This class prints an X86 MCInst to intel style .s file syntax. +// +//===----------------------------------------------------------------------===// + +#ifndef X86_INTEL_INST_PRINTER_H +#define X86_INTEL_INST_PRINTER_H + +#include "llvm/MC/MCInstPrinter.h" +#include "llvm/Support/raw_ostream.h" + +namespace llvm { + class MCOperand; + +class X86IntelInstPrinter : public MCInstPrinter { +public: + X86IntelInstPrinter(raw_ostream &O, const MCAsmInfo &MAI) + : MCInstPrinter(O, MAI) {} + + virtual void printInst(const MCInst *MI); + + // Autogenerated by tblgen. + void printInstruction(const MCInst *MI); + static const char *getRegisterName(unsigned RegNo); + + + void printOperand(const MCInst *MI, unsigned OpNo, + const char *Modifier = 0); + void printMemReference(const MCInst *MI, unsigned Op); + void printLeaMemReference(const MCInst *MI, unsigned Op); + void printSSECC(const MCInst *MI, unsigned Op); + void print_pcrel_imm(const MCInst *MI, unsigned OpNo); + + void printopaquemem(const MCInst *MI, unsigned OpNo) { + O << "OPAQUE PTR "; + printMemReference(MI, OpNo); + } + + void printi8mem(const MCInst *MI, unsigned OpNo) { + O << "BYTE PTR "; + printMemReference(MI, OpNo); + } + void printi16mem(const MCInst *MI, unsigned OpNo) { + O << "WORD PTR "; + printMemReference(MI, OpNo); + } + void printi32mem(const MCInst *MI, unsigned OpNo) { + O << "DWORD PTR "; + printMemReference(MI, OpNo); + } + void printi64mem(const MCInst *MI, unsigned OpNo) { + O << "QWORD PTR "; + printMemReference(MI, OpNo); + } + void printi128mem(const MCInst *MI, unsigned OpNo) { + O << "XMMWORD PTR "; + printMemReference(MI, OpNo); + } + void printf32mem(const MCInst *MI, unsigned OpNo) { + O << "DWORD PTR "; + printMemReference(MI, OpNo); + } + void printf64mem(const MCInst *MI, unsigned OpNo) { + O << "QWORD PTR "; + printMemReference(MI, OpNo); + } + void printf80mem(const MCInst *MI, unsigned OpNo) { + O << "XWORD PTR "; + printMemReference(MI, OpNo); + } + void printf128mem(const MCInst *MI, unsigned OpNo) { + O << "XMMWORD PTR "; + printMemReference(MI, OpNo); + } + void printlea32mem(const MCInst *MI, unsigned OpNo) { + O << "DWORD PTR "; + printLeaMemReference(MI, OpNo); + } + void printlea64mem(const MCInst *MI, unsigned OpNo) { + O << "QWORD PTR "; + printLeaMemReference(MI, OpNo); + } + void printlea64_32mem(const MCInst *MI, unsigned OpNo) { + O << "QWORD PTR "; + printLeaMemReference(MI, OpNo); + } +}; + +} + +#endif diff --git a/libclamav/c++/llvm/lib/Target/X86/AsmPrinter/X86MCInstLower.cpp b/libclamav/c++/llvm/lib/Target/X86/AsmPrinter/X86MCInstLower.cpp new file mode 100644 index 000000000..38c0c2847 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/X86/AsmPrinter/X86MCInstLower.cpp @@ -0,0 +1,500 @@ +//===-- X86MCInstLower.cpp - Convert X86 MachineInstr to an MCInst --------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains code to lower X86 MachineInstrs to their corresponding +// MCInst records. +// +//===----------------------------------------------------------------------===// + +#include "X86MCInstLower.h" +#include "X86AsmPrinter.h" +#include "X86MCAsmInfo.h" +#include "X86COFFMachineModuleInfo.h" +#include "llvm/CodeGen/MachineModuleInfoImpls.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCInst.h" +#include "llvm/MC/MCStreamer.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/FormattedStream.h" +#include "llvm/Support/Mangler.h" +#include "llvm/ADT/SmallString.h" +using namespace llvm; + + +const X86Subtarget &X86MCInstLower::getSubtarget() const { + return AsmPrinter.getSubtarget(); +} + +MachineModuleInfoMachO &X86MCInstLower::getMachOMMI() const { + assert(getSubtarget().isTargetDarwin() &&"Can only get MachO info on darwin"); + return AsmPrinter.MMI->getObjFileInfo(); +} + + +MCSymbol *X86MCInstLower::GetPICBaseSymbol() const { + return Ctx.GetOrCreateSymbol(Twine(AsmPrinter.MAI->getPrivateGlobalPrefix())+ + Twine(AsmPrinter.getFunctionNumber())+"$pb"); +} + +/// LowerGlobalAddressOperand - Lower an MO_GlobalAddress operand to an +/// MCOperand. +MCSymbol *X86MCInstLower:: +GetGlobalAddressSymbol(const MachineOperand &MO) const { + const GlobalValue *GV = MO.getGlobal(); + + bool isImplicitlyPrivate = false; + if (MO.getTargetFlags() == X86II::MO_DARWIN_STUB || + MO.getTargetFlags() == X86II::MO_DARWIN_NONLAZY || + MO.getTargetFlags() == X86II::MO_DARWIN_NONLAZY_PIC_BASE || + MO.getTargetFlags() == X86II::MO_DARWIN_HIDDEN_NONLAZY_PIC_BASE) + isImplicitlyPrivate = true; + + SmallString<128> Name; + Mang->getNameWithPrefix(Name, GV, isImplicitlyPrivate); + + if (getSubtarget().isTargetCygMing()) { + X86COFFMachineModuleInfo &COFFMMI = + AsmPrinter.MMI->getObjFileInfo(); + COFFMMI.DecorateCygMingName(Name, GV, *AsmPrinter.TM.getTargetData()); + } + + switch (MO.getTargetFlags()) { + default: llvm_unreachable("Unknown target flag on GV operand"); + case X86II::MO_NO_FLAG: // No flag. + case X86II::MO_PIC_BASE_OFFSET: // Doesn't modify symbol name. + break; + case X86II::MO_DLLIMPORT: { + // Handle dllimport linkage. + const char *Prefix = "__imp_"; + Name.insert(Name.begin(), Prefix, Prefix+strlen(Prefix)); + break; + } + case X86II::MO_DARWIN_NONLAZY: + case X86II::MO_DARWIN_NONLAZY_PIC_BASE: { + Name += "$non_lazy_ptr"; + MCSymbol *Sym = Ctx.GetOrCreateSymbol(Name.str()); + + const MCSymbol *&StubSym = getMachOMMI().getGVStubEntry(Sym); + if (StubSym == 0) { + Name.clear(); + Mang->getNameWithPrefix(Name, GV, false); + StubSym = Ctx.GetOrCreateSymbol(Name.str()); + } + return Sym; + } + case X86II::MO_DARWIN_HIDDEN_NONLAZY_PIC_BASE: { + Name += "$non_lazy_ptr"; + MCSymbol *Sym = Ctx.GetOrCreateSymbol(Name.str()); + const MCSymbol *&StubSym = getMachOMMI().getHiddenGVStubEntry(Sym); + if (StubSym == 0) { + Name.clear(); + Mang->getNameWithPrefix(Name, GV, false); + StubSym = Ctx.GetOrCreateSymbol(Name.str()); + } + return Sym; + } + case X86II::MO_DARWIN_STUB: { + Name += "$stub"; + MCSymbol *Sym = Ctx.GetOrCreateSymbol(Name.str()); + const MCSymbol *&StubSym = getMachOMMI().getFnStubEntry(Sym); + if (StubSym == 0) { + Name.clear(); + Mang->getNameWithPrefix(Name, GV, false); + StubSym = Ctx.GetOrCreateSymbol(Name.str()); + } + return Sym; + } + // FIXME: These probably should be a modifier on the symbol or something?? + case X86II::MO_TLSGD: Name += "@TLSGD"; break; + case X86II::MO_GOTTPOFF: Name += "@GOTTPOFF"; break; + case X86II::MO_INDNTPOFF: Name += "@INDNTPOFF"; break; + case X86II::MO_TPOFF: Name += "@TPOFF"; break; + case X86II::MO_NTPOFF: Name += "@NTPOFF"; break; + case X86II::MO_GOTPCREL: Name += "@GOTPCREL"; break; + case X86II::MO_GOT: Name += "@GOT"; break; + case X86II::MO_GOTOFF: Name += "@GOTOFF"; break; + case X86II::MO_PLT: Name += "@PLT"; break; + } + + return Ctx.GetOrCreateSymbol(Name.str()); +} + +MCSymbol *X86MCInstLower:: +GetExternalSymbolSymbol(const MachineOperand &MO) const { + SmallString<128> Name; + Name += AsmPrinter.MAI->getGlobalPrefix(); + Name += MO.getSymbolName(); + + switch (MO.getTargetFlags()) { + default: llvm_unreachable("Unknown target flag on GV operand"); + case X86II::MO_NO_FLAG: // No flag. + case X86II::MO_GOT_ABSOLUTE_ADDRESS: // Doesn't modify symbol name. + case X86II::MO_PIC_BASE_OFFSET: // Doesn't modify symbol name. + break; + case X86II::MO_DLLIMPORT: { + // Handle dllimport linkage. + const char *Prefix = "__imp_"; + Name.insert(Name.begin(), Prefix, Prefix+strlen(Prefix)); + break; + } + case X86II::MO_DARWIN_STUB: { + Name += "$stub"; + MCSymbol *Sym = Ctx.GetOrCreateSymbol(Name.str()); + const MCSymbol *&StubSym = getMachOMMI().getFnStubEntry(Sym); + + if (StubSym == 0) { + Name.erase(Name.end()-5, Name.end()); + StubSym = Ctx.GetOrCreateSymbol(Name.str()); + } + return Sym; + } + // FIXME: These probably should be a modifier on the symbol or something?? + case X86II::MO_TLSGD: Name += "@TLSGD"; break; + case X86II::MO_GOTTPOFF: Name += "@GOTTPOFF"; break; + case X86II::MO_INDNTPOFF: Name += "@INDNTPOFF"; break; + case X86II::MO_TPOFF: Name += "@TPOFF"; break; + case X86II::MO_NTPOFF: Name += "@NTPOFF"; break; + case X86II::MO_GOTPCREL: Name += "@GOTPCREL"; break; + case X86II::MO_GOT: Name += "@GOT"; break; + case X86II::MO_GOTOFF: Name += "@GOTOFF"; break; + case X86II::MO_PLT: Name += "@PLT"; break; + } + + return Ctx.GetOrCreateSymbol(Name.str()); +} + +MCSymbol *X86MCInstLower::GetJumpTableSymbol(const MachineOperand &MO) const { + SmallString<256> Name; + raw_svector_ostream(Name) << AsmPrinter.MAI->getPrivateGlobalPrefix() << "JTI" + << AsmPrinter.getFunctionNumber() << '_' << MO.getIndex(); + + switch (MO.getTargetFlags()) { + default: + llvm_unreachable("Unknown target flag on GV operand"); + case X86II::MO_NO_FLAG: // No flag. + case X86II::MO_PIC_BASE_OFFSET: + case X86II::MO_DARWIN_NONLAZY_PIC_BASE: + case X86II::MO_DARWIN_HIDDEN_NONLAZY_PIC_BASE: + break; + // FIXME: These probably should be a modifier on the symbol or something?? + case X86II::MO_TLSGD: Name += "@TLSGD"; break; + case X86II::MO_GOTTPOFF: Name += "@GOTTPOFF"; break; + case X86II::MO_INDNTPOFF: Name += "@INDNTPOFF"; break; + case X86II::MO_TPOFF: Name += "@TPOFF"; break; + case X86II::MO_NTPOFF: Name += "@NTPOFF"; break; + case X86II::MO_GOTPCREL: Name += "@GOTPCREL"; break; + case X86II::MO_GOT: Name += "@GOT"; break; + case X86II::MO_GOTOFF: Name += "@GOTOFF"; break; + case X86II::MO_PLT: Name += "@PLT"; break; + } + + // Create a symbol for the name. + return Ctx.GetOrCreateSymbol(Name.str()); +} + + +MCSymbol *X86MCInstLower:: +GetConstantPoolIndexSymbol(const MachineOperand &MO) const { + SmallString<256> Name; + raw_svector_ostream(Name) << AsmPrinter.MAI->getPrivateGlobalPrefix() << "CPI" + << AsmPrinter.getFunctionNumber() << '_' << MO.getIndex(); + + switch (MO.getTargetFlags()) { + default: + llvm_unreachable("Unknown target flag on GV operand"); + case X86II::MO_NO_FLAG: // No flag. + case X86II::MO_PIC_BASE_OFFSET: + case X86II::MO_DARWIN_NONLAZY_PIC_BASE: + case X86II::MO_DARWIN_HIDDEN_NONLAZY_PIC_BASE: + break; + // FIXME: These probably should be a modifier on the symbol or something?? + case X86II::MO_TLSGD: Name += "@TLSGD"; break; + case X86II::MO_GOTTPOFF: Name += "@GOTTPOFF"; break; + case X86II::MO_INDNTPOFF: Name += "@INDNTPOFF"; break; + case X86II::MO_TPOFF: Name += "@TPOFF"; break; + case X86II::MO_NTPOFF: Name += "@NTPOFF"; break; + case X86II::MO_GOTPCREL: Name += "@GOTPCREL"; break; + case X86II::MO_GOT: Name += "@GOT"; break; + case X86II::MO_GOTOFF: Name += "@GOTOFF"; break; + case X86II::MO_PLT: Name += "@PLT"; break; + } + + // Create a symbol for the name. + return Ctx.GetOrCreateSymbol(Name.str()); +} + +MCSymbol *X86MCInstLower:: +GetBlockAddressSymbol(const MachineOperand &MO) const { + const char *Suffix = ""; + switch (MO.getTargetFlags()) { + default: llvm_unreachable("Unknown target flag on BA operand"); + case X86II::MO_NO_FLAG: break; // No flag. + case X86II::MO_PIC_BASE_OFFSET: break; // Doesn't modify symbol name. + case X86II::MO_GOTOFF: Suffix = "@GOTOFF"; break; + } + + return AsmPrinter.GetBlockAddressSymbol(MO.getBlockAddress(), Suffix); +} + +MCOperand X86MCInstLower::LowerSymbolOperand(const MachineOperand &MO, + MCSymbol *Sym) const { + // FIXME: We would like an efficient form for this, so we don't have to do a + // lot of extra uniquing. + const MCExpr *Expr = MCSymbolRefExpr::Create(Sym, Ctx); + + switch (MO.getTargetFlags()) { + default: llvm_unreachable("Unknown target flag on GV operand"); + case X86II::MO_NO_FLAG: // No flag. + + // These affect the name of the symbol, not any suffix. + case X86II::MO_DARWIN_NONLAZY: + case X86II::MO_DLLIMPORT: + case X86II::MO_DARWIN_STUB: + case X86II::MO_TLSGD: + case X86II::MO_GOTTPOFF: + case X86II::MO_INDNTPOFF: + case X86II::MO_TPOFF: + case X86II::MO_NTPOFF: + case X86II::MO_GOTPCREL: + case X86II::MO_GOT: + case X86II::MO_GOTOFF: + case X86II::MO_PLT: + break; + case X86II::MO_PIC_BASE_OFFSET: + case X86II::MO_DARWIN_NONLAZY_PIC_BASE: + case X86II::MO_DARWIN_HIDDEN_NONLAZY_PIC_BASE: + // Subtract the pic base. + Expr = MCBinaryExpr::CreateSub(Expr, + MCSymbolRefExpr::Create(GetPICBaseSymbol(), Ctx), + Ctx); + break; + } + + if (!MO.isJTI() && MO.getOffset()) + Expr = MCBinaryExpr::CreateAdd(Expr, + MCConstantExpr::Create(MO.getOffset(), Ctx), + Ctx); + return MCOperand::CreateExpr(Expr); +} + + + +static void lower_subreg32(MCInst *MI, unsigned OpNo) { + // Convert registers in the addr mode according to subreg32. + unsigned Reg = MI->getOperand(OpNo).getReg(); + if (Reg != 0) + MI->getOperand(OpNo).setReg(getX86SubSuperRegister(Reg, MVT::i32)); +} + +static void lower_lea64_32mem(MCInst *MI, unsigned OpNo) { + // Convert registers in the addr mode according to subreg64. + for (unsigned i = 0; i != 4; ++i) { + if (!MI->getOperand(OpNo+i).isReg()) continue; + + unsigned Reg = MI->getOperand(OpNo+i).getReg(); + if (Reg == 0) continue; + + MI->getOperand(OpNo+i).setReg(getX86SubSuperRegister(Reg, MVT::i64)); + } +} + + + +void X86MCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const { + OutMI.setOpcode(MI->getOpcode()); + + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + const MachineOperand &MO = MI->getOperand(i); + + MCOperand MCOp; + switch (MO.getType()) { + default: + MI->dump(); + llvm_unreachable("unknown operand type"); + case MachineOperand::MO_Register: + // Ignore all implicit register operands. + if (MO.isImplicit()) continue; + MCOp = MCOperand::CreateReg(MO.getReg()); + break; + case MachineOperand::MO_Immediate: + MCOp = MCOperand::CreateImm(MO.getImm()); + break; + case MachineOperand::MO_MachineBasicBlock: + MCOp = MCOperand::CreateExpr(MCSymbolRefExpr::Create( + AsmPrinter.GetMBBSymbol(MO.getMBB()->getNumber()), Ctx)); + break; + case MachineOperand::MO_GlobalAddress: + MCOp = LowerSymbolOperand(MO, GetGlobalAddressSymbol(MO)); + break; + case MachineOperand::MO_ExternalSymbol: + MCOp = LowerSymbolOperand(MO, GetExternalSymbolSymbol(MO)); + break; + case MachineOperand::MO_JumpTableIndex: + MCOp = LowerSymbolOperand(MO, GetJumpTableSymbol(MO)); + break; + case MachineOperand::MO_ConstantPoolIndex: + MCOp = LowerSymbolOperand(MO, GetConstantPoolIndexSymbol(MO)); + break; + case MachineOperand::MO_BlockAddress: + MCOp = LowerSymbolOperand(MO, GetBlockAddressSymbol(MO)); + break; + } + + OutMI.addOperand(MCOp); + } + + // Handle a few special cases to eliminate operand modifiers. + switch (OutMI.getOpcode()) { + case X86::LEA64_32r: // Handle 'subreg rewriting' for the lea64_32mem operand. + lower_lea64_32mem(&OutMI, 1); + break; + case X86::MOV16r0: + OutMI.setOpcode(X86::MOV32r0); + lower_subreg32(&OutMI, 0); + break; + case X86::MOVZX16rr8: + OutMI.setOpcode(X86::MOVZX32rr8); + lower_subreg32(&OutMI, 0); + break; + case X86::MOVZX16rm8: + OutMI.setOpcode(X86::MOVZX32rm8); + lower_subreg32(&OutMI, 0); + break; + case X86::MOVSX16rr8: + OutMI.setOpcode(X86::MOVSX32rr8); + lower_subreg32(&OutMI, 0); + break; + case X86::MOVSX16rm8: + OutMI.setOpcode(X86::MOVSX32rm8); + lower_subreg32(&OutMI, 0); + break; + case X86::MOVZX64rr32: + OutMI.setOpcode(X86::MOV32rr); + lower_subreg32(&OutMI, 0); + break; + case X86::MOVZX64rm32: + OutMI.setOpcode(X86::MOV32rm); + lower_subreg32(&OutMI, 0); + break; + case X86::MOV64ri64i32: + OutMI.setOpcode(X86::MOV32ri); + lower_subreg32(&OutMI, 0); + break; + case X86::MOVZX64rr8: + OutMI.setOpcode(X86::MOVZX32rr8); + lower_subreg32(&OutMI, 0); + break; + case X86::MOVZX64rm8: + OutMI.setOpcode(X86::MOVZX32rm8); + lower_subreg32(&OutMI, 0); + break; + case X86::MOVZX64rr16: + OutMI.setOpcode(X86::MOVZX32rr16); + lower_subreg32(&OutMI, 0); + break; + case X86::MOVZX64rm16: + OutMI.setOpcode(X86::MOVZX32rm16); + lower_subreg32(&OutMI, 0); + break; + } +} + + + +void X86AsmPrinter::printInstructionThroughMCStreamer(const MachineInstr *MI) { + X86MCInstLower MCInstLowering(OutContext, Mang, *this); + switch (MI->getOpcode()) { + case TargetInstrInfo::DBG_LABEL: + case TargetInstrInfo::EH_LABEL: + case TargetInstrInfo::GC_LABEL: + printLabel(MI); + return; + case TargetInstrInfo::INLINEASM: + printInlineAsm(MI); + return; + case TargetInstrInfo::IMPLICIT_DEF: + printImplicitDef(MI); + return; + case TargetInstrInfo::KILL: + printKill(MI); + return; + case X86::MOVPC32r: { + MCInst TmpInst; + // This is a pseudo op for a two instruction sequence with a label, which + // looks like: + // call "L1$pb" + // "L1$pb": + // popl %esi + + // Emit the call. + MCSymbol *PICBase = MCInstLowering.GetPICBaseSymbol(); + TmpInst.setOpcode(X86::CALLpcrel32); + // FIXME: We would like an efficient form for this, so we don't have to do a + // lot of extra uniquing. + TmpInst.addOperand(MCOperand::CreateExpr(MCSymbolRefExpr::Create(PICBase, + OutContext))); + printMCInst(&TmpInst); + O << '\n'; + + // Emit the label. + OutStreamer.EmitLabel(PICBase); + + // popl $reg + TmpInst.setOpcode(X86::POP32r); + TmpInst.getOperand(0) = MCOperand::CreateReg(MI->getOperand(0).getReg()); + printMCInst(&TmpInst); + return; + } + + case X86::ADD32ri: { + // Lower the MO_GOT_ABSOLUTE_ADDRESS form of ADD32ri. + if (MI->getOperand(2).getTargetFlags() != X86II::MO_GOT_ABSOLUTE_ADDRESS) + break; + + // Okay, we have something like: + // EAX = ADD32ri EAX, MO_GOT_ABSOLUTE_ADDRESS(@MYGLOBAL) + + // For this, we want to print something like: + // MYGLOBAL + (. - PICBASE) + // However, we can't generate a ".", so just emit a new label here and refer + // to it. We know that this operand flag occurs at most once per function. + const char *Prefix = MAI->getPrivateGlobalPrefix(); + MCSymbol *DotSym = OutContext.GetOrCreateSymbol(Twine(Prefix)+"picbaseref"+ + Twine(getFunctionNumber())); + OutStreamer.EmitLabel(DotSym); + + // Now that we have emitted the label, lower the complex operand expression. + MCSymbol *OpSym = MCInstLowering.GetExternalSymbolSymbol(MI->getOperand(2)); + + const MCExpr *DotExpr = MCSymbolRefExpr::Create(DotSym, OutContext); + const MCExpr *PICBase = + MCSymbolRefExpr::Create(MCInstLowering.GetPICBaseSymbol(), OutContext); + DotExpr = MCBinaryExpr::CreateSub(DotExpr, PICBase, OutContext); + + DotExpr = MCBinaryExpr::CreateAdd(MCSymbolRefExpr::Create(OpSym,OutContext), + DotExpr, OutContext); + + MCInst TmpInst; + TmpInst.setOpcode(X86::ADD32ri); + TmpInst.addOperand(MCOperand::CreateReg(MI->getOperand(0).getReg())); + TmpInst.addOperand(MCOperand::CreateReg(MI->getOperand(1).getReg())); + TmpInst.addOperand(MCOperand::CreateExpr(DotExpr)); + printMCInst(&TmpInst); + return; + } + } + + MCInst TmpInst; + MCInstLowering.Lower(MI, TmpInst); + + + printMCInst(&TmpInst); +} + diff --git a/libclamav/c++/llvm/lib/Target/X86/AsmPrinter/X86MCInstLower.h b/libclamav/c++/llvm/lib/Target/X86/AsmPrinter/X86MCInstLower.h new file mode 100644 index 000000000..94f8bfcc9 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/X86/AsmPrinter/X86MCInstLower.h @@ -0,0 +1,55 @@ +//===-- X86MCInstLower.h - Lower MachineInstr to MCInst -------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef X86_MCINSTLOWER_H +#define X86_MCINSTLOWER_H + +#include "llvm/Support/Compiler.h" + +namespace llvm { + class MCContext; + class MCInst; + class MCOperand; + class MCSymbol; + class MachineInstr; + class MachineModuleInfoMachO; + class MachineOperand; + class Mangler; + class X86AsmPrinter; + class X86Subtarget; + +/// X86MCInstLower - This class is used to lower an MachineInstr into an MCInst. +class VISIBILITY_HIDDEN X86MCInstLower { + MCContext &Ctx; + Mangler *Mang; + X86AsmPrinter &AsmPrinter; + + const X86Subtarget &getSubtarget() const; +public: + X86MCInstLower(MCContext &ctx, Mangler *mang, X86AsmPrinter &asmprinter) + : Ctx(ctx), Mang(mang), AsmPrinter(asmprinter) {} + + void Lower(const MachineInstr *MI, MCInst &OutMI) const; + + MCSymbol *GetPICBaseSymbol() const; + + MCSymbol *GetGlobalAddressSymbol(const MachineOperand &MO) const; + MCSymbol *GetExternalSymbolSymbol(const MachineOperand &MO) const; + MCSymbol *GetJumpTableSymbol(const MachineOperand &MO) const; + MCSymbol *GetConstantPoolIndexSymbol(const MachineOperand &MO) const; + MCSymbol *GetBlockAddressSymbol(const MachineOperand &MO) const; + MCOperand LowerSymbolOperand(const MachineOperand &MO, MCSymbol *Sym) const; + +private: + MachineModuleInfoMachO &getMachOMMI() const; +}; + +} + +#endif diff --git a/libclamav/c++/llvm/lib/Target/X86/CMakeLists.txt b/libclamav/c++/llvm/lib/Target/X86/CMakeLists.txt new file mode 100644 index 000000000..3ad65fbed --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/X86/CMakeLists.txt @@ -0,0 +1,41 @@ +set(LLVM_TARGET_DEFINITIONS X86.td) + +tablegen(X86GenRegisterInfo.h.inc -gen-register-desc-header) +tablegen(X86GenRegisterNames.inc -gen-register-enums) +tablegen(X86GenRegisterInfo.inc -gen-register-desc) +tablegen(X86GenInstrNames.inc -gen-instr-enums) +tablegen(X86GenInstrInfo.inc -gen-instr-desc) +tablegen(X86GenAsmWriter.inc -gen-asm-writer) +tablegen(X86GenAsmWriter1.inc -gen-asm-writer -asmwriternum=1) +tablegen(X86GenAsmMatcher.inc -gen-asm-matcher) +tablegen(X86GenDAGISel.inc -gen-dag-isel) +tablegen(X86GenFastISel.inc -gen-fast-isel) +tablegen(X86GenCallingConv.inc -gen-callingconv) +tablegen(X86GenSubtarget.inc -gen-subtarget) + +set(sources + X86CodeEmitter.cpp + X86COFFMachineModuleInfo.cpp + X86ELFWriterInfo.cpp + X86FloatingPoint.cpp + X86FloatingPointRegKill.cpp + X86ISelDAGToDAG.cpp + X86ISelLowering.cpp + X86InstrInfo.cpp + X86JITInfo.cpp + X86MCAsmInfo.cpp + X86RegisterInfo.cpp + X86Subtarget.cpp + X86TargetMachine.cpp + X86TargetObjectFile.cpp + X86FastISel.cpp + ) + +if( CMAKE_CL_64 ) + enable_language(ASM_MASM) + set(sources ${sources} X86CompilationCallback_Win64.asm) +endif() + +add_llvm_target(X86CodeGen ${sources}) + +target_link_libraries (LLVMX86CodeGen LLVMSelectionDAG) diff --git a/libclamav/c++/llvm/lib/Target/X86/Disassembler/CMakeLists.txt b/libclamav/c++/llvm/lib/Target/X86/Disassembler/CMakeLists.txt new file mode 100644 index 000000000..b329e897b --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/X86/Disassembler/CMakeLists.txt @@ -0,0 +1,6 @@ +include_directories( ${CMAKE_CURRENT_BINARY_DIR}/.. ${CMAKE_CURRENT_SOURCE_DIR}/.. ) + +add_llvm_library(LLVMX86Disassembler + X86Disassembler.cpp + ) +add_dependencies(LLVMX86Disassembler X86CodeGenTable_gen) diff --git a/libclamav/c++/llvm/lib/Target/X86/Disassembler/X86Disassembler.cpp b/libclamav/c++/llvm/lib/Target/X86/Disassembler/X86Disassembler.cpp new file mode 100644 index 000000000..2ebbc9bdb --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/X86/Disassembler/X86Disassembler.cpp @@ -0,0 +1,29 @@ +//===- X86Disassembler.cpp - Disassembler for x86 and x86_64 ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/MC/MCDisassembler.h" +#include "llvm/Target/TargetRegistry.h" +#include "X86.h" +using namespace llvm; + +static const MCDisassembler *createX86_32Disassembler(const Target &T) { + return 0; +} + +static const MCDisassembler *createX86_64Disassembler(const Target &T) { + return 0; +} + +extern "C" void LLVMInitializeX86Disassembler() { + // Register the disassembler. + TargetRegistry::RegisterMCDisassembler(TheX86_32Target, + createX86_32Disassembler); + TargetRegistry::RegisterMCDisassembler(TheX86_64Target, + createX86_64Disassembler); +} diff --git a/libclamav/c++/llvm/lib/Target/X86/Makefile b/libclamav/c++/llvm/lib/Target/X86/Makefile new file mode 100644 index 000000000..b311a6ed8 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/X86/Makefile @@ -0,0 +1,23 @@ +##===- lib/Target/X86/Makefile -----------------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## +LEVEL = ../../.. +LIBRARYNAME = LLVMX86CodeGen +TARGET = X86 + +# Make sure that tblgen is run, first thing. +BUILT_SOURCES = X86GenRegisterInfo.h.inc X86GenRegisterNames.inc \ + X86GenRegisterInfo.inc X86GenInstrNames.inc \ + X86GenInstrInfo.inc X86GenAsmWriter.inc X86GenAsmMatcher.inc \ + X86GenAsmWriter1.inc X86GenDAGISel.inc \ + X86GenFastISel.inc \ + X86GenCallingConv.inc X86GenSubtarget.inc + +DIRS = AsmPrinter AsmParser Disassembler TargetInfo + +include $(LEVEL)/Makefile.common diff --git a/libclamav/c++/llvm/lib/Target/X86/README-FPStack.txt b/libclamav/c++/llvm/lib/Target/X86/README-FPStack.txt new file mode 100644 index 000000000..be28e8b39 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/X86/README-FPStack.txt @@ -0,0 +1,85 @@ +//===---------------------------------------------------------------------===// +// Random ideas for the X86 backend: FP stack related stuff +//===---------------------------------------------------------------------===// + +//===---------------------------------------------------------------------===// + +Some targets (e.g. athlons) prefer freep to fstp ST(0): +http://gcc.gnu.org/ml/gcc-patches/2004-04/msg00659.html + +//===---------------------------------------------------------------------===// + +This should use fiadd on chips where it is profitable: +double foo(double P, int *I) { return P+*I; } + +We have fiadd patterns now but the followings have the same cost and +complexity. We need a way to specify the later is more profitable. + +def FpADD32m : FpI<(ops RFP:$dst, RFP:$src1, f32mem:$src2), OneArgFPRW, + [(set RFP:$dst, (fadd RFP:$src1, + (extloadf64f32 addr:$src2)))]>; + // ST(0) = ST(0) + [mem32] + +def FpIADD32m : FpI<(ops RFP:$dst, RFP:$src1, i32mem:$src2), OneArgFPRW, + [(set RFP:$dst, (fadd RFP:$src1, + (X86fild addr:$src2, i32)))]>; + // ST(0) = ST(0) + [mem32int] + +//===---------------------------------------------------------------------===// + +The FP stackifier needs to be global. Also, it should handle simple permutates +to reduce number of shuffle instructions, e.g. turning: + +fld P -> fld Q +fld Q fld P +fxch + +or: + +fxch -> fucomi +fucomi jl X +jg X + +Ideas: +http://gcc.gnu.org/ml/gcc-patches/2004-11/msg02410.html + + +//===---------------------------------------------------------------------===// + +Add a target specific hook to DAG combiner to handle SINT_TO_FP and +FP_TO_SINT when the source operand is already in memory. + +//===---------------------------------------------------------------------===// + +Open code rint,floor,ceil,trunc: +http://gcc.gnu.org/ml/gcc-patches/2004-08/msg02006.html +http://gcc.gnu.org/ml/gcc-patches/2004-08/msg02011.html + +Opencode the sincos[f] libcall. + +//===---------------------------------------------------------------------===// + +None of the FPStack instructions are handled in +X86RegisterInfo::foldMemoryOperand, which prevents the spiller from +folding spill code into the instructions. + +//===---------------------------------------------------------------------===// + +Currently the x86 codegen isn't very good at mixing SSE and FPStack +code: + +unsigned int foo(double x) { return x; } + +foo: + subl $20, %esp + movsd 24(%esp), %xmm0 + movsd %xmm0, 8(%esp) + fldl 8(%esp) + fisttpll (%esp) + movl (%esp), %eax + addl $20, %esp + ret + +This just requires being smarter when custom expanding fptoui. + +//===---------------------------------------------------------------------===// diff --git a/libclamav/c++/llvm/lib/Target/X86/README-MMX.txt b/libclamav/c++/llvm/lib/Target/X86/README-MMX.txt new file mode 100644 index 000000000..a6c8616b6 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/X86/README-MMX.txt @@ -0,0 +1,71 @@ +//===---------------------------------------------------------------------===// +// Random ideas for the X86 backend: MMX-specific stuff. +//===---------------------------------------------------------------------===// + +//===---------------------------------------------------------------------===// + +This: + +#include + +__v2si qux(int A) { + return (__v2si){ 0, A }; +} + +is compiled into: + +_qux: + subl $28, %esp + movl 32(%esp), %eax + movd %eax, %mm0 + movq %mm0, (%esp) + movl (%esp), %eax + movl %eax, 20(%esp) + movq %mm0, 8(%esp) + movl 12(%esp), %eax + movl %eax, 16(%esp) + movq 16(%esp), %mm0 + addl $28, %esp + ret + +Yuck! + +GCC gives us: + +_qux: + subl $12, %esp + movl 16(%esp), %eax + movl 20(%esp), %edx + movl $0, (%eax) + movl %edx, 4(%eax) + addl $12, %esp + ret $4 + +//===---------------------------------------------------------------------===// + +We generate crappy code for this: + +__m64 t() { + return _mm_cvtsi32_si64(1); +} + +_t: + subl $12, %esp + movl $1, %eax + movd %eax, %mm0 + movq %mm0, (%esp) + movl (%esp), %eax + movl 4(%esp), %edx + addl $12, %esp + ret + +The extra stack traffic is covered in the previous entry. But the other reason +is we are not smart about materializing constants in MMX registers. With -m64 + + movl $1, %eax + movd %eax, %mm0 + movd %mm0, %rax + ret + +We should be using a constantpool load instead: + movq LC0(%rip), %rax diff --git a/libclamav/c++/llvm/lib/Target/X86/README-SSE.txt b/libclamav/c++/llvm/lib/Target/X86/README-SSE.txt new file mode 100644 index 000000000..71ad51c79 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/X86/README-SSE.txt @@ -0,0 +1,918 @@ +//===---------------------------------------------------------------------===// +// Random ideas for the X86 backend: SSE-specific stuff. +//===---------------------------------------------------------------------===// + +- Consider eliminating the unaligned SSE load intrinsics, replacing them with + unaligned LLVM load instructions. + +//===---------------------------------------------------------------------===// + +Expand libm rounding functions inline: Significant speedups possible. +http://gcc.gnu.org/ml/gcc-patches/2006-10/msg00909.html + +//===---------------------------------------------------------------------===// + +When compiled with unsafemath enabled, "main" should enable SSE DAZ mode and +other fast SSE modes. + +//===---------------------------------------------------------------------===// + +Think about doing i64 math in SSE regs on x86-32. + +//===---------------------------------------------------------------------===// + +This testcase should have no SSE instructions in it, and only one load from +a constant pool: + +double %test3(bool %B) { + %C = select bool %B, double 123.412, double 523.01123123 + ret double %C +} + +Currently, the select is being lowered, which prevents the dag combiner from +turning 'select (load CPI1), (load CPI2)' -> 'load (select CPI1, CPI2)' + +The pattern isel got this one right. + +//===---------------------------------------------------------------------===// + +SSE doesn't have [mem] op= reg instructions. If we have an SSE instruction +like this: + + X += y + +and the register allocator decides to spill X, it is cheaper to emit this as: + +Y += [xslot] +store Y -> [xslot] + +than as: + +tmp = [xslot] +tmp += y +store tmp -> [xslot] + +..and this uses one fewer register (so this should be done at load folding +time, not at spiller time). *Note* however that this can only be done +if Y is dead. Here's a testcase: + +@.str_3 = external global [15 x i8] +declare void @printf(i32, ...) +define void @main() { +build_tree.exit: + br label %no_exit.i7 + +no_exit.i7: ; preds = %no_exit.i7, %build_tree.exit + %tmp.0.1.0.i9 = phi double [ 0.000000e+00, %build_tree.exit ], + [ %tmp.34.i18, %no_exit.i7 ] + %tmp.0.0.0.i10 = phi double [ 0.000000e+00, %build_tree.exit ], + [ %tmp.28.i16, %no_exit.i7 ] + %tmp.28.i16 = add double %tmp.0.0.0.i10, 0.000000e+00 + %tmp.34.i18 = add double %tmp.0.1.0.i9, 0.000000e+00 + br i1 false, label %Compute_Tree.exit23, label %no_exit.i7 + +Compute_Tree.exit23: ; preds = %no_exit.i7 + tail call void (i32, ...)* @printf( i32 0 ) + store double %tmp.34.i18, double* null + ret void +} + +We currently emit: + +.BBmain_1: + xorpd %XMM1, %XMM1 + addsd %XMM0, %XMM1 +*** movsd %XMM2, QWORD PTR [%ESP + 8] +*** addsd %XMM2, %XMM1 +*** movsd QWORD PTR [%ESP + 8], %XMM2 + jmp .BBmain_1 # no_exit.i7 + +This is a bugpoint reduced testcase, which is why the testcase doesn't make +much sense (e.g. its an infinite loop). :) + +//===---------------------------------------------------------------------===// + +SSE should implement 'select_cc' using 'emulated conditional moves' that use +pcmp/pand/pandn/por to do a selection instead of a conditional branch: + +double %X(double %Y, double %Z, double %A, double %B) { + %C = setlt double %A, %B + %z = add double %Z, 0.0 ;; select operand is not a load + %D = select bool %C, double %Y, double %z + ret double %D +} + +We currently emit: + +_X: + subl $12, %esp + xorpd %xmm0, %xmm0 + addsd 24(%esp), %xmm0 + movsd 32(%esp), %xmm1 + movsd 16(%esp), %xmm2 + ucomisd 40(%esp), %xmm1 + jb LBB_X_2 +LBB_X_1: + movsd %xmm0, %xmm2 +LBB_X_2: + movsd %xmm2, (%esp) + fldl (%esp) + addl $12, %esp + ret + +//===---------------------------------------------------------------------===// + +It's not clear whether we should use pxor or xorps / xorpd to clear XMM +registers. The choice may depend on subtarget information. We should do some +more experiments on different x86 machines. + +//===---------------------------------------------------------------------===// + +Lower memcpy / memset to a series of SSE 128 bit move instructions when it's +feasible. + +//===---------------------------------------------------------------------===// + +Codegen: + if (copysign(1.0, x) == copysign(1.0, y)) +into: + if (x^y & mask) +when using SSE. + +//===---------------------------------------------------------------------===// + +Use movhps to update upper 64-bits of a v4sf value. Also movlps on lower half +of a v4sf value. + +//===---------------------------------------------------------------------===// + +Better codegen for vector_shuffles like this { x, 0, 0, 0 } or { x, 0, x, 0}. +Perhaps use pxor / xorp* to clear a XMM register first? + +//===---------------------------------------------------------------------===// + +How to decide when to use the "floating point version" of logical ops? Here are +some code fragments: + + movaps LCPI5_5, %xmm2 + divps %xmm1, %xmm2 + mulps %xmm2, %xmm3 + mulps 8656(%ecx), %xmm3 + addps 8672(%ecx), %xmm3 + andps LCPI5_6, %xmm2 + andps LCPI5_1, %xmm3 + por %xmm2, %xmm3 + movdqa %xmm3, (%edi) + + movaps LCPI5_5, %xmm1 + divps %xmm0, %xmm1 + mulps %xmm1, %xmm3 + mulps 8656(%ecx), %xmm3 + addps 8672(%ecx), %xmm3 + andps LCPI5_6, %xmm1 + andps LCPI5_1, %xmm3 + orps %xmm1, %xmm3 + movaps %xmm3, 112(%esp) + movaps %xmm3, (%ebx) + +Due to some minor source change, the later case ended up using orps and movaps +instead of por and movdqa. Does it matter? + +//===---------------------------------------------------------------------===// + +X86RegisterInfo::copyRegToReg() returns X86::MOVAPSrr for VR128. Is it possible +to choose between movaps, movapd, and movdqa based on types of source and +destination? + +How about andps, andpd, and pand? Do we really care about the type of the packed +elements? If not, why not always use the "ps" variants which are likely to be +shorter. + +//===---------------------------------------------------------------------===// + +External test Nurbs exposed some problems. Look for +__ZN15Nurbs_SSE_Cubic17TessellateSurfaceE, bb cond_next140. This is what icc +emits: + + movaps (%edx), %xmm2 #59.21 + movaps (%edx), %xmm5 #60.21 + movaps (%edx), %xmm4 #61.21 + movaps (%edx), %xmm3 #62.21 + movl 40(%ecx), %ebp #69.49 + shufps $0, %xmm2, %xmm5 #60.21 + movl 100(%esp), %ebx #69.20 + movl (%ebx), %edi #69.20 + imull %ebp, %edi #69.49 + addl (%eax), %edi #70.33 + shufps $85, %xmm2, %xmm4 #61.21 + shufps $170, %xmm2, %xmm3 #62.21 + shufps $255, %xmm2, %xmm2 #63.21 + lea (%ebp,%ebp,2), %ebx #69.49 + negl %ebx #69.49 + lea -3(%edi,%ebx), %ebx #70.33 + shll $4, %ebx #68.37 + addl 32(%ecx), %ebx #68.37 + testb $15, %bl #91.13 + jne L_B1.24 # Prob 5% #91.13 + +This is the llvm code after instruction scheduling: + +cond_next140 (0xa910740, LLVM BB @0xa90beb0): + %reg1078 = MOV32ri -3 + %reg1079 = ADD32rm %reg1078, %reg1068, 1, %NOREG, 0 + %reg1037 = MOV32rm %reg1024, 1, %NOREG, 40 + %reg1080 = IMUL32rr %reg1079, %reg1037 + %reg1081 = MOV32rm %reg1058, 1, %NOREG, 0 + %reg1038 = LEA32r %reg1081, 1, %reg1080, -3 + %reg1036 = MOV32rm %reg1024, 1, %NOREG, 32 + %reg1082 = SHL32ri %reg1038, 4 + %reg1039 = ADD32rr %reg1036, %reg1082 + %reg1083 = MOVAPSrm %reg1059, 1, %NOREG, 0 + %reg1034 = SHUFPSrr %reg1083, %reg1083, 170 + %reg1032 = SHUFPSrr %reg1083, %reg1083, 0 + %reg1035 = SHUFPSrr %reg1083, %reg1083, 255 + %reg1033 = SHUFPSrr %reg1083, %reg1083, 85 + %reg1040 = MOV32rr %reg1039 + %reg1084 = AND32ri8 %reg1039, 15 + CMP32ri8 %reg1084, 0 + JE mbb + +Still ok. After register allocation: + +cond_next140 (0xa910740, LLVM BB @0xa90beb0): + %EAX = MOV32ri -3 + %EDX = MOV32rm , 1, %NOREG, 0 + ADD32rm %EAX, %EDX, 1, %NOREG, 0 + %EDX = MOV32rm , 1, %NOREG, 0 + %EDX = MOV32rm %EDX, 1, %NOREG, 40 + IMUL32rr %EAX, %EDX + %ESI = MOV32rm , 1, %NOREG, 0 + %ESI = MOV32rm %ESI, 1, %NOREG, 0 + MOV32mr , 1, %NOREG, 0, %ESI + %EAX = LEA32r %ESI, 1, %EAX, -3 + %ESI = MOV32rm , 1, %NOREG, 0 + %ESI = MOV32rm %ESI, 1, %NOREG, 32 + %EDI = MOV32rr %EAX + SHL32ri %EDI, 4 + ADD32rr %EDI, %ESI + %XMM0 = MOVAPSrm %ECX, 1, %NOREG, 0 + %XMM1 = MOVAPSrr %XMM0 + SHUFPSrr %XMM1, %XMM1, 170 + %XMM2 = MOVAPSrr %XMM0 + SHUFPSrr %XMM2, %XMM2, 0 + %XMM3 = MOVAPSrr %XMM0 + SHUFPSrr %XMM3, %XMM3, 255 + SHUFPSrr %XMM0, %XMM0, 85 + %EBX = MOV32rr %EDI + AND32ri8 %EBX, 15 + CMP32ri8 %EBX, 0 + JE mbb + +This looks really bad. The problem is shufps is a destructive opcode. Since it +appears as operand two in more than one shufps ops. It resulted in a number of +copies. Note icc also suffers from the same problem. Either the instruction +selector should select pshufd or The register allocator can made the two-address +to three-address transformation. + +It also exposes some other problems. See MOV32ri -3 and the spills. + +//===---------------------------------------------------------------------===// + +http://gcc.gnu.org/bugzilla/show_bug.cgi?id=25500 + +LLVM is producing bad code. + +LBB_main_4: # cond_true44 + addps %xmm1, %xmm2 + subps %xmm3, %xmm2 + movaps (%ecx), %xmm4 + movaps %xmm2, %xmm1 + addps %xmm4, %xmm1 + addl $16, %ecx + incl %edx + cmpl $262144, %edx + movaps %xmm3, %xmm2 + movaps %xmm4, %xmm3 + jne LBB_main_4 # cond_true44 + +There are two problems. 1) No need to two loop induction variables. We can +compare against 262144 * 16. 2) Known register coalescer issue. We should +be able eliminate one of the movaps: + + addps %xmm2, %xmm1 <=== Commute! + subps %xmm3, %xmm1 + movaps (%ecx), %xmm4 + movaps %xmm1, %xmm1 <=== Eliminate! + addps %xmm4, %xmm1 + addl $16, %ecx + incl %edx + cmpl $262144, %edx + movaps %xmm3, %xmm2 + movaps %xmm4, %xmm3 + jne LBB_main_4 # cond_true44 + +//===---------------------------------------------------------------------===// + +Consider: + +__m128 test(float a) { + return _mm_set_ps(0.0, 0.0, 0.0, a*a); +} + +This compiles into: + +movss 4(%esp), %xmm1 +mulss %xmm1, %xmm1 +xorps %xmm0, %xmm0 +movss %xmm1, %xmm0 +ret + +Because mulss doesn't modify the top 3 elements, the top elements of +xmm1 are already zero'd. We could compile this to: + +movss 4(%esp), %xmm0 +mulss %xmm0, %xmm0 +ret + +//===---------------------------------------------------------------------===// + +Here's a sick and twisted idea. Consider code like this: + +__m128 test(__m128 a) { + float b = *(float*)&A; + ... + return _mm_set_ps(0.0, 0.0, 0.0, b); +} + +This might compile to this code: + +movaps c(%esp), %xmm1 +xorps %xmm0, %xmm0 +movss %xmm1, %xmm0 +ret + +Now consider if the ... code caused xmm1 to get spilled. This might produce +this code: + +movaps c(%esp), %xmm1 +movaps %xmm1, c2(%esp) +... + +xorps %xmm0, %xmm0 +movaps c2(%esp), %xmm1 +movss %xmm1, %xmm0 +ret + +However, since the reload is only used by these instructions, we could +"fold" it into the uses, producing something like this: + +movaps c(%esp), %xmm1 +movaps %xmm1, c2(%esp) +... + +movss c2(%esp), %xmm0 +ret + +... saving two instructions. + +The basic idea is that a reload from a spill slot, can, if only one 4-byte +chunk is used, bring in 3 zeros the the one element instead of 4 elements. +This can be used to simplify a variety of shuffle operations, where the +elements are fixed zeros. + +//===---------------------------------------------------------------------===// + +__m128d test1( __m128d A, __m128d B) { + return _mm_shuffle_pd(A, B, 0x3); +} + +compiles to + +shufpd $3, %xmm1, %xmm0 + +Perhaps it's better to use unpckhpd instead? + +unpckhpd %xmm1, %xmm0 + +Don't know if unpckhpd is faster. But it is shorter. + +//===---------------------------------------------------------------------===// + +This code generates ugly code, probably due to costs being off or something: + +define void @test(float* %P, <4 x float>* %P2 ) { + %xFloat0.688 = load float* %P + %tmp = load <4 x float>* %P2 + %inFloat3.713 = insertelement <4 x float> %tmp, float 0.0, i32 3 + store <4 x float> %inFloat3.713, <4 x float>* %P2 + ret void +} + +Generates: + +_test: + movl 8(%esp), %eax + movaps (%eax), %xmm0 + pxor %xmm1, %xmm1 + movaps %xmm0, %xmm2 + shufps $50, %xmm1, %xmm2 + shufps $132, %xmm2, %xmm0 + movaps %xmm0, (%eax) + ret + +Would it be better to generate: + +_test: + movl 8(%esp), %ecx + movaps (%ecx), %xmm0 + xor %eax, %eax + pinsrw $6, %eax, %xmm0 + pinsrw $7, %eax, %xmm0 + movaps %xmm0, (%ecx) + ret + +? + +//===---------------------------------------------------------------------===// + +Some useful information in the Apple Altivec / SSE Migration Guide: + +http://developer.apple.com/documentation/Performance/Conceptual/ +Accelerate_sse_migration/index.html + +e.g. SSE select using and, andnot, or. Various SSE compare translations. + +//===---------------------------------------------------------------------===// + +Add hooks to commute some CMPP operations. + +//===---------------------------------------------------------------------===// + +Apply the same transformation that merged four float into a single 128-bit load +to loads from constant pool. + +//===---------------------------------------------------------------------===// + +Floating point max / min are commutable when -enable-unsafe-fp-path is +specified. We should turn int_x86_sse_max_ss and X86ISD::FMIN etc. into other +nodes which are selected to max / min instructions that are marked commutable. + +//===---------------------------------------------------------------------===// + +We should materialize vector constants like "all ones" and "signbit" with +code like: + + cmpeqps xmm1, xmm1 ; xmm1 = all-ones + +and: + cmpeqps xmm1, xmm1 ; xmm1 = all-ones + psrlq xmm1, 31 ; xmm1 = all 100000000000... + +instead of using a load from the constant pool. The later is important for +ABS/NEG/copysign etc. + +//===---------------------------------------------------------------------===// + +These functions: + +#include +__m128i a; +void x(unsigned short n) { + a = _mm_slli_epi32 (a, n); +} +void y(unsigned n) { + a = _mm_slli_epi32 (a, n); +} + +compile to ( -O3 -static -fomit-frame-pointer): +_x: + movzwl 4(%esp), %eax + movd %eax, %xmm0 + movaps _a, %xmm1 + pslld %xmm0, %xmm1 + movaps %xmm1, _a + ret +_y: + movd 4(%esp), %xmm0 + movaps _a, %xmm1 + pslld %xmm0, %xmm1 + movaps %xmm1, _a + ret + +"y" looks good, but "x" does silly movzwl stuff around into a GPR. It seems +like movd would be sufficient in both cases as the value is already zero +extended in the 32-bit stack slot IIRC. For signed short, it should also be +save, as a really-signed value would be undefined for pslld. + + +//===---------------------------------------------------------------------===// + +#include +int t1(double d) { return signbit(d); } + +This currently compiles to: + subl $12, %esp + movsd 16(%esp), %xmm0 + movsd %xmm0, (%esp) + movl 4(%esp), %eax + shrl $31, %eax + addl $12, %esp + ret + +We should use movmskp{s|d} instead. + +//===---------------------------------------------------------------------===// + +CodeGen/X86/vec_align.ll tests whether we can turn 4 scalar loads into a single +(aligned) vector load. This functionality has a couple of problems. + +1. The code to infer alignment from loads of globals is in the X86 backend, + not the dag combiner. This is because dagcombine2 needs to be able to see + through the X86ISD::Wrapper node, which DAGCombine can't really do. +2. The code for turning 4 x load into a single vector load is target + independent and should be moved to the dag combiner. +3. The code for turning 4 x load into a vector load can only handle a direct + load from a global or a direct load from the stack. It should be generalized + to handle any load from P, P+4, P+8, P+12, where P can be anything. +4. The alignment inference code cannot handle loads from globals in non-static + mode because it doesn't look through the extra dyld stub load. If you try + vec_align.ll without -relocation-model=static, you'll see what I mean. + +//===---------------------------------------------------------------------===// + +We should lower store(fneg(load p), q) into an integer load+xor+store, which +eliminates a constant pool load. For example, consider: + +define i64 @ccosf(float %z.0, float %z.1) nounwind readonly { +entry: + %tmp6 = sub float -0.000000e+00, %z.1 ; [#uses=1] + %tmp20 = tail call i64 @ccoshf( float %tmp6, float %z.0 ) nounwind readonly + ret i64 %tmp20 +} + +This currently compiles to: + +LCPI1_0: # <4 x float> + .long 2147483648 # float -0 + .long 2147483648 # float -0 + .long 2147483648 # float -0 + .long 2147483648 # float -0 +_ccosf: + subl $12, %esp + movss 16(%esp), %xmm0 + movss %xmm0, 4(%esp) + movss 20(%esp), %xmm0 + xorps LCPI1_0, %xmm0 + movss %xmm0, (%esp) + call L_ccoshf$stub + addl $12, %esp + ret + +Note the load into xmm0, then xor (to negate), then store. In PIC mode, +this code computes the pic base and does two loads to do the constant pool +load, so the improvement is much bigger. + +The tricky part about this xform is that the argument load/store isn't exposed +until post-legalize, and at that point, the fneg has been custom expanded into +an X86 fxor. This means that we need to handle this case in the x86 backend +instead of in target independent code. + +//===---------------------------------------------------------------------===// + +Non-SSE4 insert into 16 x i8 is atrociously bad. + +//===---------------------------------------------------------------------===// + +<2 x i64> extract is substantially worse than <2 x f64>, even if the destination +is memory. + +//===---------------------------------------------------------------------===// + +SSE4 extract-to-mem ops aren't being pattern matched because of the AssertZext +sitting between the truncate and the extract. + +//===---------------------------------------------------------------------===// + +INSERTPS can match any insert (extract, imm1), imm2 for 4 x float, and insert +any number of 0.0 simultaneously. Currently we only use it for simple +insertions. + +See comments in LowerINSERT_VECTOR_ELT_SSE4. + +//===---------------------------------------------------------------------===// + +On a random note, SSE2 should declare insert/extract of 2 x f64 as legal, not +Custom. All combinations of insert/extract reg-reg, reg-mem, and mem-reg are +legal, it'll just take a few extra patterns written in the .td file. + +Note: this is not a code quality issue; the custom lowered code happens to be +right, but we shouldn't have to custom lower anything. This is probably related +to <2 x i64> ops being so bad. + +//===---------------------------------------------------------------------===// + +'select' on vectors and scalars could be a whole lot better. We currently +lower them to conditional branches. On x86-64 for example, we compile this: + +double test(double a, double b, double c, double d) { return a + +typedef short vSInt16 __attribute__ ((__vector_size__ (16))); + +static const vSInt16 a = {- 22725, - 12873, - 22725, - 12873, - 22725, - 12873, +- 22725, - 12873};; + +vSInt16 madd(vSInt16 b) +{ + return _mm_madd_epi16(a, b); +} + +Generated code (x86-32, linux): +madd: + pushl %ebp + movl %esp, %ebp + andl $-16, %esp + movaps .LCPI1_0, %xmm1 + pmaddwd %xmm1, %xmm0 + movl %ebp, %esp + popl %ebp + ret + +//===---------------------------------------------------------------------===// + +Consider: +#include +__m128 foo2 (float x) { + return _mm_set_ps (0, 0, x, 0); +} + +In x86-32 mode, we generate this spiffy code: + +_foo2: + movss 4(%esp), %xmm0 + pshufd $81, %xmm0, %xmm0 + ret + +in x86-64 mode, we generate this code, which could be better: + +_foo2: + xorps %xmm1, %xmm1 + movss %xmm0, %xmm1 + pshufd $81, %xmm1, %xmm0 + ret + +In sse4 mode, we could use insertps to make both better. + +Here's another testcase that could use insertps [mem]: + +#include +extern float x2, x3; +__m128 foo1 (float x1, float x4) { + return _mm_set_ps (x2, x1, x3, x4); +} + +gcc mainline compiles it to: + +foo1: + insertps $0x10, x2(%rip), %xmm0 + insertps $0x10, x3(%rip), %xmm1 + movaps %xmm1, %xmm2 + movlhps %xmm0, %xmm2 + movaps %xmm2, %xmm0 + ret + +//===---------------------------------------------------------------------===// + +We compile vector multiply-by-constant into poor code: + +define <4 x i32> @f(<4 x i32> %i) nounwind { + %A = mul <4 x i32> %i, < i32 10, i32 10, i32 10, i32 10 > + ret <4 x i32> %A +} + +On targets without SSE4.1, this compiles into: + +LCPI1_0: ## <4 x i32> + .long 10 + .long 10 + .long 10 + .long 10 + .text + .align 4,0x90 + .globl _f +_f: + pshufd $3, %xmm0, %xmm1 + movd %xmm1, %eax + imull LCPI1_0+12, %eax + movd %eax, %xmm1 + pshufd $1, %xmm0, %xmm2 + movd %xmm2, %eax + imull LCPI1_0+4, %eax + movd %eax, %xmm2 + punpckldq %xmm1, %xmm2 + movd %xmm0, %eax + imull LCPI1_0, %eax + movd %eax, %xmm1 + movhlps %xmm0, %xmm0 + movd %xmm0, %eax + imull LCPI1_0+8, %eax + movd %eax, %xmm0 + punpckldq %xmm0, %xmm1 + movaps %xmm1, %xmm0 + punpckldq %xmm2, %xmm0 + ret + +It would be better to synthesize integer vector multiplication by constants +using shifts and adds, pslld and paddd here. And even on targets with SSE4.1, +simple cases such as multiplication by powers of two would be better as +vector shifts than as multiplications. + +//===---------------------------------------------------------------------===// + +We compile this: + +__m128i +foo2 (char x) +{ + return _mm_set_epi8 (1, 0, 0, 0, 0, 0, 0, 0, 0, x, 0, 1, 0, 0, 0, 0); +} + +into: + movl $1, %eax + xorps %xmm0, %xmm0 + pinsrw $2, %eax, %xmm0 + movzbl 4(%esp), %eax + pinsrw $3, %eax, %xmm0 + movl $256, %eax + pinsrw $7, %eax, %xmm0 + ret + + +gcc-4.2: + subl $12, %esp + movzbl 16(%esp), %eax + movdqa LC0, %xmm0 + pinsrw $3, %eax, %xmm0 + addl $12, %esp + ret + .const + .align 4 +LC0: + .word 0 + .word 0 + .word 1 + .word 0 + .word 0 + .word 0 + .word 0 + .word 256 + +With SSE4, it should be + movdqa .LC0(%rip), %xmm0 + pinsrb $6, %edi, %xmm0 + +//===---------------------------------------------------------------------===// + +We should transform a shuffle of two vectors of constants into a single vector +of constants. Also, insertelement of a constant into a vector of constants +should also result in a vector of constants. e.g. 2008-06-25-VecISelBug.ll. + +We compiled it to something horrible: + + .align 4 +LCPI1_1: ## float + .long 1065353216 ## float 1 + .const + + .align 4 +LCPI1_0: ## <4 x float> + .space 4 + .long 1065353216 ## float 1 + .space 4 + .long 1065353216 ## float 1 + .text + .align 4,0x90 + .globl _t +_t: + xorps %xmm0, %xmm0 + movhps LCPI1_0, %xmm0 + movss LCPI1_1, %xmm1 + movaps %xmm0, %xmm2 + shufps $2, %xmm1, %xmm2 + shufps $132, %xmm2, %xmm0 + movaps %xmm0, 0 + +//===---------------------------------------------------------------------===// +rdar://5907648 + +This function: + +float foo(unsigned char x) { + return x; +} + +compiles to (x86-32): + +define float @foo(i8 zeroext %x) nounwind { + %tmp12 = uitofp i8 %x to float ; [#uses=1] + ret float %tmp12 +} + +compiles to: + +_foo: + subl $4, %esp + movzbl 8(%esp), %eax + cvtsi2ss %eax, %xmm0 + movss %xmm0, (%esp) + flds (%esp) + addl $4, %esp + ret + +We should be able to use: + cvtsi2ss 8($esp), %xmm0 +since we know the stack slot is already zext'd. + +//===---------------------------------------------------------------------===// + +Consider using movlps instead of movsd to implement (scalar_to_vector (loadf64)) +when code size is critical. movlps is slower than movsd on core2 but it's one +byte shorter. + +//===---------------------------------------------------------------------===// + +We should use a dynamic programming based approach to tell when using FPStack +operations is cheaper than SSE. SciMark montecarlo contains code like this +for example: + +double MonteCarlo_num_flops(int Num_samples) { + return ((double) Num_samples)* 4.0; +} + +In fpstack mode, this compiles into: + +LCPI1_0: + .long 1082130432 ## float 4.000000e+00 +_MonteCarlo_num_flops: + subl $4, %esp + movl 8(%esp), %eax + movl %eax, (%esp) + fildl (%esp) + fmuls LCPI1_0 + addl $4, %esp + ret + +in SSE mode, it compiles into significantly slower code: + +_MonteCarlo_num_flops: + subl $12, %esp + cvtsi2sd 16(%esp), %xmm0 + mulsd LCPI1_0, %xmm0 + movsd %xmm0, (%esp) + fldl (%esp) + addl $12, %esp + ret + +There are also other cases in scimark where using fpstack is better, it is +cheaper to do fld1 than load from a constant pool for example, so +"load, add 1.0, store" is better done in the fp stack, etc. + +//===---------------------------------------------------------------------===// diff --git a/libclamav/c++/llvm/lib/Target/X86/README-UNIMPLEMENTED.txt b/libclamav/c++/llvm/lib/Target/X86/README-UNIMPLEMENTED.txt new file mode 100644 index 000000000..69dc8ee1a --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/X86/README-UNIMPLEMENTED.txt @@ -0,0 +1,14 @@ +//===---------------------------------------------------------------------===// +// Testcases that crash the X86 backend because they aren't implemented +//===---------------------------------------------------------------------===// + +These are cases we know the X86 backend doesn't handle. Patches are welcome +and appreciated, because no one has signed up to implemented these yet. +Implementing these would allow elimination of the corresponding intrinsics, +which would be great. + +1) vector shifts +2) vector comparisons +3) vector fp<->int conversions: PR2683, PR2684, PR2685, PR2686, PR2688 +4) bitcasts from vectors to scalars: PR2804 + diff --git a/libclamav/c++/llvm/lib/Target/X86/README-X86-64.txt b/libclamav/c++/llvm/lib/Target/X86/README-X86-64.txt new file mode 100644 index 000000000..e8f7c5d6d --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/X86/README-X86-64.txt @@ -0,0 +1,300 @@ +//===- README_X86_64.txt - Notes for X86-64 code gen ----------------------===// + +Implement different PIC models? Right now we only support Mac OS X with small +PIC code model. + +//===---------------------------------------------------------------------===// + +For this: + +extern void xx(void); +void bar(void) { + xx(); +} + +gcc compiles to: + +.globl _bar +_bar: + jmp _xx + +We need to do the tailcall optimization as well. + +//===---------------------------------------------------------------------===// + +AMD64 Optimization Manual 8.2 has some nice information about optimizing integer +multiplication by a constant. How much of it applies to Intel's X86-64 +implementation? There are definite trade-offs to consider: latency vs. register +pressure vs. code size. + +//===---------------------------------------------------------------------===// + +Are we better off using branches instead of cmove to implement FP to +unsigned i64? + +_conv: + ucomiss LC0(%rip), %xmm0 + cvttss2siq %xmm0, %rdx + jb L3 + subss LC0(%rip), %xmm0 + movabsq $-9223372036854775808, %rax + cvttss2siq %xmm0, %rdx + xorq %rax, %rdx +L3: + movq %rdx, %rax + ret + +instead of + +_conv: + movss LCPI1_0(%rip), %xmm1 + cvttss2siq %xmm0, %rcx + movaps %xmm0, %xmm2 + subss %xmm1, %xmm2 + cvttss2siq %xmm2, %rax + movabsq $-9223372036854775808, %rdx + xorq %rdx, %rax + ucomiss %xmm1, %xmm0 + cmovb %rcx, %rax + ret + +Seems like the jb branch has high likelyhood of being taken. It would have +saved a few instructions. + +//===---------------------------------------------------------------------===// + +Poor codegen: + +int X[2]; +int b; +void test(void) { + memset(X, b, 2*sizeof(X[0])); +} + +llc: + movq _b@GOTPCREL(%rip), %rax + movzbq (%rax), %rax + movq %rax, %rcx + shlq $8, %rcx + orq %rax, %rcx + movq %rcx, %rax + shlq $16, %rax + orq %rcx, %rax + movq %rax, %rcx + shlq $32, %rcx + movq _X@GOTPCREL(%rip), %rdx + orq %rax, %rcx + movq %rcx, (%rdx) + ret + +gcc: + movq _b@GOTPCREL(%rip), %rax + movabsq $72340172838076673, %rdx + movzbq (%rax), %rax + imulq %rdx, %rax + movq _X@GOTPCREL(%rip), %rdx + movq %rax, (%rdx) + ret + +//===---------------------------------------------------------------------===// + +Vararg function prologue can be further optimized. Currently all XMM registers +are stored into register save area. Most of them can be eliminated since the +upper bound of the number of XMM registers used are passed in %al. gcc produces +something like the following: + + movzbl %al, %edx + leaq 0(,%rdx,4), %rax + leaq 4+L2(%rip), %rdx + leaq 239(%rsp), %rax + jmp *%rdx + movaps %xmm7, -15(%rax) + movaps %xmm6, -31(%rax) + movaps %xmm5, -47(%rax) + movaps %xmm4, -63(%rax) + movaps %xmm3, -79(%rax) + movaps %xmm2, -95(%rax) + movaps %xmm1, -111(%rax) + movaps %xmm0, -127(%rax) +L2: + +It jumps over the movaps that do not need to be stored. Hard to see this being +significant as it added 5 instruciton (including a indirect branch) to avoid +executing 0 to 8 stores in the function prologue. + +Perhaps we can optimize for the common case where no XMM registers are used for +parameter passing. i.e. is %al == 0 jump over all stores. Or in the case of a +leaf function where we can determine that no XMM input parameter is need, avoid +emitting the stores at all. + +//===---------------------------------------------------------------------===// + +AMD64 has a complex calling convention for aggregate passing by value: + +1. If the size of an object is larger than two eightbytes, or in C++, is a non- + POD structure or union type, or contains unaligned fields, it has class + MEMORY. +2. Both eightbytes get initialized to class NO_CLASS. +3. Each field of an object is classified recursively so that always two fields + are considered. The resulting class is calculated according to the classes + of the fields in the eightbyte: + (a) If both classes are equal, this is the resulting class. + (b) If one of the classes is NO_CLASS, the resulting class is the other + class. + (c) If one of the classes is MEMORY, the result is the MEMORY class. + (d) If one of the classes is INTEGER, the result is the INTEGER. + (e) If one of the classes is X87, X87UP, COMPLEX_X87 class, MEMORY is used as + class. + (f) Otherwise class SSE is used. +4. Then a post merger cleanup is done: + (a) If one of the classes is MEMORY, the whole argument is passed in memory. + (b) If SSEUP is not preceeded by SSE, it is converted to SSE. + +Currently llvm frontend does not handle this correctly. + +Problem 1: + typedef struct { int i; double d; } QuadWordS; +It is currently passed in two i64 integer registers. However, gcc compiled +callee expects the second element 'd' to be passed in XMM0. + +Problem 2: + typedef struct { int32_t i; float j; double d; } QuadWordS; +The size of the first two fields == i64 so they will be combined and passed in +a integer register RDI. The third field is still passed in XMM0. + +Problem 3: + typedef struct { int64_t i; int8_t j; int64_t d; } S; + void test(S s) +The size of this aggregate is greater than two i64 so it should be passed in +memory. Currently llvm breaks this down and passed it in three integer +registers. + +Problem 4: +Taking problem 3 one step ahead where a function expects a aggregate value +in memory followed by more parameter(s) passed in register(s). + void test(S s, int b) + +LLVM IR does not allow parameter passing by aggregates, therefore it must break +the aggregates value (in problem 3 and 4) into a number of scalar values: + void %test(long %s.i, byte %s.j, long %s.d); + +However, if the backend were to lower this code literally it would pass the 3 +values in integer registers. To force it be passed in memory, the frontend +should change the function signiture to: + void %test(long %undef1, long %undef2, long %undef3, long %undef4, + long %undef5, long %undef6, + long %s.i, byte %s.j, long %s.d); +And the callee would look something like this: + call void %test( undef, undef, undef, undef, undef, undef, + %tmp.s.i, %tmp.s.j, %tmp.s.d ); +The first 6 undef parameters would exhaust the 6 integer registers used for +parameter passing. The following three integer values would then be forced into +memory. + +For problem 4, the parameter 'd' would be moved to the front of the parameter +list so it will be passed in register: + void %test(int %d, + long %undef1, long %undef2, long %undef3, long %undef4, + long %undef5, long %undef6, + long %s.i, byte %s.j, long %s.d); + +//===---------------------------------------------------------------------===// + +Right now the asm printer assumes GlobalAddress are accessed via RIP relative +addressing. Therefore, it is not possible to generate this: + movabsq $__ZTV10polynomialIdE+16, %rax + +That is ok for now since we currently only support small model. So the above +is selected as + leaq __ZTV10polynomialIdE+16(%rip), %rax + +This is probably slightly slower but is much shorter than movabsq. However, if +we were to support medium or larger code models, we need to use the movabs +instruction. We should probably introduce something like AbsoluteAddress to +distinguish it from GlobalAddress so the asm printer and JIT code emitter can +do the right thing. + +//===---------------------------------------------------------------------===// + +It's not possible to reference AH, BH, CH, and DH registers in an instruction +requiring REX prefix. However, divb and mulb both produce results in AH. If isel +emits a CopyFromReg which gets turned into a movb and that can be allocated a +r8b - r15b. + +To get around this, isel emits a CopyFromReg from AX and then right shift it +down by 8 and truncate it. It's not pretty but it works. We need some register +allocation magic to make the hack go away (e.g. putting additional constraints +on the result of the movb). + +//===---------------------------------------------------------------------===// + +The x86-64 ABI for hidden-argument struct returns requires that the +incoming value of %rdi be copied into %rax by the callee upon return. + +The idea is that it saves callers from having to remember this value, +which would often require a callee-saved register. Callees usually +need to keep this value live for most of their body anyway, so it +doesn't add a significant burden on them. + +We currently implement this in codegen, however this is suboptimal +because it means that it would be quite awkward to implement the +optimization for callers. + +A better implementation would be to relax the LLVM IR rules for sret +arguments to allow a function with an sret argument to have a non-void +return type, and to have the front-end to set up the sret argument value +as the return value of the function. The front-end could more easily +emit uses of the returned struct value to be in terms of the function's +lowered return value, and it would free non-C frontends from a +complication only required by a C-based ABI. + +//===---------------------------------------------------------------------===// + +We get a redundant zero extension for code like this: + +int mask[1000]; +int foo(unsigned x) { + if (x < 10) + x = x * 45; + else + x = x * 78; + return mask[x]; +} + +_foo: +LBB1_0: ## entry + cmpl $9, %edi + jbe LBB1_3 ## bb +LBB1_1: ## bb1 + imull $78, %edi, %eax +LBB1_2: ## bb2 + movl %eax, %eax <---- + movq _mask@GOTPCREL(%rip), %rcx + movl (%rcx,%rax,4), %eax + ret +LBB1_3: ## bb + imull $45, %edi, %eax + jmp LBB1_2 ## bb2 + +Before regalloc, we have: + + %reg1025 = IMUL32rri8 %reg1024, 45, %EFLAGS + JMP mbb + Successors according to CFG: 0x203afb0 (#3) + +bb1: 0x203af60, LLVM BB @0x1e02310, ID#2: + Predecessors according to CFG: 0x203aec0 (#0) + %reg1026 = IMUL32rri8 %reg1024, 78, %EFLAGS + Successors according to CFG: 0x203afb0 (#3) + +bb2: 0x203afb0, LLVM BB @0x1e02340, ID#3: + Predecessors according to CFG: 0x203af10 (#1) 0x203af60 (#2) + %reg1027 = PHI %reg1025, mbb, + %reg1026, mbb + %reg1029 = MOVZX64rr32 %reg1027 + +so we'd have to know that IMUL32rri8 leaves the high word zero extended and to +be able to recognize the zero extend. This could also presumably be implemented +if we have whole-function selectiondags. + +//===---------------------------------------------------------------------===// diff --git a/libclamav/c++/llvm/lib/Target/X86/README.txt b/libclamav/c++/llvm/lib/Target/X86/README.txt new file mode 100644 index 000000000..9b7aab801 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/X86/README.txt @@ -0,0 +1,1956 @@ +//===---------------------------------------------------------------------===// +// Random ideas for the X86 backend. +//===---------------------------------------------------------------------===// + +We should add support for the "movbe" instruction, which does a byte-swapping +copy (3-addr bswap + memory support?) This is available on Atom processors. + +//===---------------------------------------------------------------------===// + +CodeGen/X86/lea-3.ll:test3 should be a single LEA, not a shift/move. The X86 +backend knows how to three-addressify this shift, but it appears the register +allocator isn't even asking it to do so in this case. We should investigate +why this isn't happening, it could have significant impact on other important +cases for X86 as well. + +//===---------------------------------------------------------------------===// + +This should be one DIV/IDIV instruction, not a libcall: + +unsigned test(unsigned long long X, unsigned Y) { + return X/Y; +} + +This can be done trivially with a custom legalizer. What about overflow +though? http://gcc.gnu.org/bugzilla/show_bug.cgi?id=14224 + +//===---------------------------------------------------------------------===// + +Improvements to the multiply -> shift/add algorithm: +http://gcc.gnu.org/ml/gcc-patches/2004-08/msg01590.html + +//===---------------------------------------------------------------------===// + +Improve code like this (occurs fairly frequently, e.g. in LLVM): +long long foo(int x) { return 1LL << x; } + +http://gcc.gnu.org/ml/gcc-patches/2004-09/msg01109.html +http://gcc.gnu.org/ml/gcc-patches/2004-09/msg01128.html +http://gcc.gnu.org/ml/gcc-patches/2004-09/msg01136.html + +Another useful one would be ~0ULL >> X and ~0ULL << X. + +One better solution for 1LL << x is: + xorl %eax, %eax + xorl %edx, %edx + testb $32, %cl + sete %al + setne %dl + sall %cl, %eax + sall %cl, %edx + +But that requires good 8-bit subreg support. + +Also, this might be better. It's an extra shift, but it's one instruction +shorter, and doesn't stress 8-bit subreg support. +(From http://gcc.gnu.org/ml/gcc-patches/2004-09/msg01148.html, +but without the unnecessary and.) + movl %ecx, %eax + shrl $5, %eax + movl %eax, %edx + xorl $1, %edx + sall %cl, %eax + sall %cl. %edx + +64-bit shifts (in general) expand to really bad code. Instead of using +cmovs, we should expand to a conditional branch like GCC produces. + +//===---------------------------------------------------------------------===// + +Compile this: +_Bool f(_Bool a) { return a!=1; } + +into: + movzbl %dil, %eax + xorl $1, %eax + ret + +(Although note that this isn't a legal way to express the code that llvm-gcc +currently generates for that function.) + +//===---------------------------------------------------------------------===// + +Some isel ideas: + +1. Dynamic programming based approach when compile time if not an + issue. +2. Code duplication (addressing mode) during isel. +3. Other ideas from "Register-Sensitive Selection, Duplication, and + Sequencing of Instructions". +4. Scheduling for reduced register pressure. E.g. "Minimum Register + Instruction Sequence Problem: Revisiting Optimal Code Generation for DAGs" + and other related papers. + http://citeseer.ist.psu.edu/govindarajan01minimum.html + +//===---------------------------------------------------------------------===// + +Should we promote i16 to i32 to avoid partial register update stalls? + +//===---------------------------------------------------------------------===// + +Leave any_extend as pseudo instruction and hint to register +allocator. Delay codegen until post register allocation. +Note. any_extend is now turned into an INSERT_SUBREG. We still need to teach +the coalescer how to deal with it though. + +//===---------------------------------------------------------------------===// + +It appears icc use push for parameter passing. Need to investigate. + +//===---------------------------------------------------------------------===// + +Only use inc/neg/not instructions on processors where they are faster than +add/sub/xor. They are slower on the P4 due to only updating some processor +flags. + +//===---------------------------------------------------------------------===// + +The instruction selector sometimes misses folding a load into a compare. The +pattern is written as (cmp reg, (load p)). Because the compare isn't +commutative, it is not matched with the load on both sides. The dag combiner +should be made smart enough to cannonicalize the load into the RHS of a compare +when it can invert the result of the compare for free. + +//===---------------------------------------------------------------------===// + +How about intrinsics? An example is: + *res = _mm_mulhi_epu16(*A, _mm_mul_epu32(*B, *C)); + +compiles to + pmuludq (%eax), %xmm0 + movl 8(%esp), %eax + movdqa (%eax), %xmm1 + pmulhuw %xmm0, %xmm1 + +The transformation probably requires a X86 specific pass or a DAG combiner +target specific hook. + +//===---------------------------------------------------------------------===// + +In many cases, LLVM generates code like this: + +_test: + movl 8(%esp), %eax + cmpl %eax, 4(%esp) + setl %al + movzbl %al, %eax + ret + +on some processors (which ones?), it is more efficient to do this: + +_test: + movl 8(%esp), %ebx + xor %eax, %eax + cmpl %ebx, 4(%esp) + setl %al + ret + +Doing this correctly is tricky though, as the xor clobbers the flags. + +//===---------------------------------------------------------------------===// + +We should generate bts/btr/etc instructions on targets where they are cheap or +when codesize is important. e.g., for: + +void setbit(int *target, int bit) { + *target |= (1 << bit); +} +void clearbit(int *target, int bit) { + *target &= ~(1 << bit); +} + +//===---------------------------------------------------------------------===// + +Instead of the following for memset char*, 1, 10: + + movl $16843009, 4(%edx) + movl $16843009, (%edx) + movw $257, 8(%edx) + +It might be better to generate + + movl $16843009, %eax + movl %eax, 4(%edx) + movl %eax, (%edx) + movw al, 8(%edx) + +when we can spare a register. It reduces code size. + +//===---------------------------------------------------------------------===// + +Evaluate what the best way to codegen sdiv X, (2^C) is. For X/8, we currently +get this: + +define i32 @test1(i32 %X) { + %Y = sdiv i32 %X, 8 + ret i32 %Y +} + +_test1: + movl 4(%esp), %eax + movl %eax, %ecx + sarl $31, %ecx + shrl $29, %ecx + addl %ecx, %eax + sarl $3, %eax + ret + +GCC knows several different ways to codegen it, one of which is this: + +_test1: + movl 4(%esp), %eax + cmpl $-1, %eax + leal 7(%eax), %ecx + cmovle %ecx, %eax + sarl $3, %eax + ret + +which is probably slower, but it's interesting at least :) + +//===---------------------------------------------------------------------===// + +We are currently lowering large (1MB+) memmove/memcpy to rep/stosl and rep/movsl +We should leave these as libcalls for everything over a much lower threshold, +since libc is hand tuned for medium and large mem ops (avoiding RFO for large +stores, TLB preheating, etc) + +//===---------------------------------------------------------------------===// + +Optimize this into something reasonable: + x * copysign(1.0, y) * copysign(1.0, z) + +//===---------------------------------------------------------------------===// + +Optimize copysign(x, *y) to use an integer load from y. + +//===---------------------------------------------------------------------===// + +The following tests perform worse with LSR: + +lambda, siod, optimizer-eval, ackermann, hash2, nestedloop, strcat, and Treesor. + +//===---------------------------------------------------------------------===// + +Teach the coalescer to coalesce vregs of different register classes. e.g. FR32 / +FR64 to VR128. + +//===---------------------------------------------------------------------===// + +Adding to the list of cmp / test poor codegen issues: + +int test(__m128 *A, __m128 *B) { + if (_mm_comige_ss(*A, *B)) + return 3; + else + return 4; +} + +_test: + movl 8(%esp), %eax + movaps (%eax), %xmm0 + movl 4(%esp), %eax + movaps (%eax), %xmm1 + comiss %xmm0, %xmm1 + setae %al + movzbl %al, %ecx + movl $3, %eax + movl $4, %edx + cmpl $0, %ecx + cmove %edx, %eax + ret + +Note the setae, movzbl, cmpl, cmove can be replaced with a single cmovae. There +are a number of issues. 1) We are introducing a setcc between the result of the +intrisic call and select. 2) The intrinsic is expected to produce a i32 value +so a any extend (which becomes a zero extend) is added. + +We probably need some kind of target DAG combine hook to fix this. + +//===---------------------------------------------------------------------===// + +We generate significantly worse code for this than GCC: +http://gcc.gnu.org/bugzilla/show_bug.cgi?id=21150 +http://gcc.gnu.org/bugzilla/attachment.cgi?id=8701 + +There is also one case we do worse on PPC. + +//===---------------------------------------------------------------------===// + +For this: + +int test(int a) +{ + return a * 3; +} + +We currently emits + imull $3, 4(%esp), %eax + +Perhaps this is what we really should generate is? Is imull three or four +cycles? Note: ICC generates this: + movl 4(%esp), %eax + leal (%eax,%eax,2), %eax + +The current instruction priority is based on pattern complexity. The former is +more "complex" because it folds a load so the latter will not be emitted. + +Perhaps we should use AddedComplexity to give LEA32r a higher priority? We +should always try to match LEA first since the LEA matching code does some +estimate to determine whether the match is profitable. + +However, if we care more about code size, then imull is better. It's two bytes +shorter than movl + leal. + +On a Pentium M, both variants have the same characteristics with regard +to throughput; however, the multiplication has a latency of four cycles, as +opposed to two cycles for the movl+lea variant. + +//===---------------------------------------------------------------------===// + +__builtin_ffs codegen is messy. + +int ffs_(unsigned X) { return __builtin_ffs(X); } + +llvm produces: +ffs_: + movl 4(%esp), %ecx + bsfl %ecx, %eax + movl $32, %edx + cmove %edx, %eax + incl %eax + xorl %edx, %edx + testl %ecx, %ecx + cmove %edx, %eax + ret + +vs gcc: + +_ffs_: + movl $-1, %edx + bsfl 4(%esp), %eax + cmove %edx, %eax + addl $1, %eax + ret + +Another example of __builtin_ffs (use predsimplify to eliminate a select): + +int foo (unsigned long j) { + if (j) + return __builtin_ffs (j) - 1; + else + return 0; +} + +//===---------------------------------------------------------------------===// + +It appears gcc place string data with linkonce linkage in +.section __TEXT,__const_coal,coalesced instead of +.section __DATA,__const_coal,coalesced. +Take a look at darwin.h, there are other Darwin assembler directives that we +do not make use of. + +//===---------------------------------------------------------------------===// + +define i32 @foo(i32* %a, i32 %t) { +entry: + br label %cond_true + +cond_true: ; preds = %cond_true, %entry + %x.0.0 = phi i32 [ 0, %entry ], [ %tmp9, %cond_true ] ; [#uses=3] + %t_addr.0.0 = phi i32 [ %t, %entry ], [ %tmp7, %cond_true ] ; [#uses=1] + %tmp2 = getelementptr i32* %a, i32 %x.0.0 ; [#uses=1] + %tmp3 = load i32* %tmp2 ; [#uses=1] + %tmp5 = add i32 %t_addr.0.0, %x.0.0 ; [#uses=1] + %tmp7 = add i32 %tmp5, %tmp3 ; [#uses=2] + %tmp9 = add i32 %x.0.0, 1 ; [#uses=2] + %tmp = icmp sgt i32 %tmp9, 39 ; [#uses=1] + br i1 %tmp, label %bb12, label %cond_true + +bb12: ; preds = %cond_true + ret i32 %tmp7 +} +is pessimized by -loop-reduce and -indvars + +//===---------------------------------------------------------------------===// + +u32 to float conversion improvement: + +float uint32_2_float( unsigned u ) { + float fl = (int) (u & 0xffff); + float fh = (int) (u >> 16); + fh *= 0x1.0p16f; + return fh + fl; +} + +00000000 subl $0x04,%esp +00000003 movl 0x08(%esp,1),%eax +00000007 movl %eax,%ecx +00000009 shrl $0x10,%ecx +0000000c cvtsi2ss %ecx,%xmm0 +00000010 andl $0x0000ffff,%eax +00000015 cvtsi2ss %eax,%xmm1 +00000019 mulss 0x00000078,%xmm0 +00000021 addss %xmm1,%xmm0 +00000025 movss %xmm0,(%esp,1) +0000002a flds (%esp,1) +0000002d addl $0x04,%esp +00000030 ret + +//===---------------------------------------------------------------------===// + +When using fastcc abi, align stack slot of argument of type double on 8 byte +boundary to improve performance. + +//===---------------------------------------------------------------------===// + +Codegen: + +int f(int a, int b) { + if (a == 4 || a == 6) + b++; + return b; +} + + +as: + +or eax, 2 +cmp eax, 6 +jz label + +//===---------------------------------------------------------------------===// + +GCC's ix86_expand_int_movcc function (in i386.c) has a ton of interesting +simplifications for integer "x cmp y ? a : b". For example, instead of: + +int G; +void f(int X, int Y) { + G = X < 0 ? 14 : 13; +} + +compiling to: + +_f: + movl $14, %eax + movl $13, %ecx + movl 4(%esp), %edx + testl %edx, %edx + cmovl %eax, %ecx + movl %ecx, _G + ret + +it could be: +_f: + movl 4(%esp), %eax + sarl $31, %eax + notl %eax + addl $14, %eax + movl %eax, _G + ret + +etc. + +Another is: +int usesbb(unsigned int a, unsigned int b) { + return (a < b ? -1 : 0); +} +to: +_usesbb: + movl 8(%esp), %eax + cmpl %eax, 4(%esp) + sbbl %eax, %eax + ret + +instead of: +_usesbb: + xorl %eax, %eax + movl 8(%esp), %ecx + cmpl %ecx, 4(%esp) + movl $4294967295, %ecx + cmovb %ecx, %eax + ret + +//===---------------------------------------------------------------------===// + +Consider the expansion of: + +define i32 @test3(i32 %X) { + %tmp1 = urem i32 %X, 255 + ret i32 %tmp1 +} + +Currently it compiles to: + +... + movl $2155905153, %ecx + movl 8(%esp), %esi + movl %esi, %eax + mull %ecx +... + +This could be "reassociated" into: + + movl $2155905153, %eax + movl 8(%esp), %ecx + mull %ecx + +to avoid the copy. In fact, the existing two-address stuff would do this +except that mul isn't a commutative 2-addr instruction. I guess this has +to be done at isel time based on the #uses to mul? + +//===---------------------------------------------------------------------===// + +Make sure the instruction which starts a loop does not cross a cacheline +boundary. This requires knowning the exact length of each machine instruction. +That is somewhat complicated, but doable. Example 256.bzip2: + +In the new trace, the hot loop has an instruction which crosses a cacheline +boundary. In addition to potential cache misses, this can't help decoding as I +imagine there has to be some kind of complicated decoder reset and realignment +to grab the bytes from the next cacheline. + +532 532 0x3cfc movb (1809(%esp, %esi), %bl <<<--- spans 2 64 byte lines +942 942 0x3d03 movl %dh, (1809(%esp, %esi) +937 937 0x3d0a incl %esi +3 3 0x3d0b cmpb %bl, %dl +27 27 0x3d0d jnz 0x000062db + +//===---------------------------------------------------------------------===// + +In c99 mode, the preprocessor doesn't like assembly comments like #TRUNCATE. + +//===---------------------------------------------------------------------===// + +This could be a single 16-bit load. + +int f(char *p) { + if ((p[0] == 1) & (p[1] == 2)) return 1; + return 0; +} + +//===---------------------------------------------------------------------===// + +We should inline lrintf and probably other libc functions. + +//===---------------------------------------------------------------------===// + +Start using the flags more. For example, compile: + +int add_zf(int *x, int y, int a, int b) { + if ((*x += y) == 0) + return a; + else + return b; +} + +to: + addl %esi, (%rdi) + movl %edx, %eax + cmovne %ecx, %eax + ret +instead of: + +_add_zf: + addl (%rdi), %esi + movl %esi, (%rdi) + testl %esi, %esi + cmove %edx, %ecx + movl %ecx, %eax + ret + +and: + +int add_zf(int *x, int y, int a, int b) { + if ((*x + y) < 0) + return a; + else + return b; +} + +to: + +add_zf: + addl (%rdi), %esi + movl %edx, %eax + cmovns %ecx, %eax + ret + +instead of: + +_add_zf: + addl (%rdi), %esi + testl %esi, %esi + cmovs %edx, %ecx + movl %ecx, %eax + ret + +//===---------------------------------------------------------------------===// + +These two functions have identical effects: + +unsigned int f(unsigned int i, unsigned int n) {++i; if (i == n) ++i; return i;} +unsigned int f2(unsigned int i, unsigned int n) {++i; i += i == n; return i;} + +We currently compile them to: + +_f: + movl 4(%esp), %eax + movl %eax, %ecx + incl %ecx + movl 8(%esp), %edx + cmpl %edx, %ecx + jne LBB1_2 #UnifiedReturnBlock +LBB1_1: #cond_true + addl $2, %eax + ret +LBB1_2: #UnifiedReturnBlock + movl %ecx, %eax + ret +_f2: + movl 4(%esp), %eax + movl %eax, %ecx + incl %ecx + cmpl 8(%esp), %ecx + sete %cl + movzbl %cl, %ecx + leal 1(%ecx,%eax), %eax + ret + +both of which are inferior to GCC's: + +_f: + movl 4(%esp), %edx + leal 1(%edx), %eax + addl $2, %edx + cmpl 8(%esp), %eax + cmove %edx, %eax + ret +_f2: + movl 4(%esp), %eax + addl $1, %eax + xorl %edx, %edx + cmpl 8(%esp), %eax + sete %dl + addl %edx, %eax + ret + +//===---------------------------------------------------------------------===// + +This code: + +void test(int X) { + if (X) abort(); +} + +is currently compiled to: + +_test: + subl $12, %esp + cmpl $0, 16(%esp) + jne LBB1_1 + addl $12, %esp + ret +LBB1_1: + call L_abort$stub + +It would be better to produce: + +_test: + subl $12, %esp + cmpl $0, 16(%esp) + jne L_abort$stub + addl $12, %esp + ret + +This can be applied to any no-return function call that takes no arguments etc. +Alternatively, the stack save/restore logic could be shrink-wrapped, producing +something like this: + +_test: + cmpl $0, 4(%esp) + jne LBB1_1 + ret +LBB1_1: + subl $12, %esp + call L_abort$stub + +Both are useful in different situations. Finally, it could be shrink-wrapped +and tail called, like this: + +_test: + cmpl $0, 4(%esp) + jne LBB1_1 + ret +LBB1_1: + pop %eax # realign stack. + call L_abort$stub + +Though this probably isn't worth it. + +//===---------------------------------------------------------------------===// + +We need to teach the codegen to convert two-address INC instructions to LEA +when the flags are dead (likewise dec). For example, on X86-64, compile: + +int foo(int A, int B) { + return A+1; +} + +to: + +_foo: + leal 1(%edi), %eax + ret + +instead of: + +_foo: + incl %edi + movl %edi, %eax + ret + +Another example is: + +;; X's live range extends beyond the shift, so the register allocator +;; cannot coalesce it with Y. Because of this, a copy needs to be +;; emitted before the shift to save the register value before it is +;; clobbered. However, this copy is not needed if the register +;; allocator turns the shift into an LEA. This also occurs for ADD. + +; Check that the shift gets turned into an LEA. +; RUN: llvm-as < %s | llc -march=x86 -x86-asm-syntax=intel | \ +; RUN: not grep {mov E.X, E.X} + +@G = external global i32 ; [#uses=3] + +define i32 @test1(i32 %X, i32 %Y) { + %Z = add i32 %X, %Y ; [#uses=1] + volatile store i32 %Y, i32* @G + volatile store i32 %Z, i32* @G + ret i32 %X +} + +define i32 @test2(i32 %X) { + %Z = add i32 %X, 1 ; [#uses=1] + volatile store i32 %Z, i32* @G + ret i32 %X +} + +//===---------------------------------------------------------------------===// + +Sometimes it is better to codegen subtractions from a constant (e.g. 7-x) with +a neg instead of a sub instruction. Consider: + +int test(char X) { return 7-X; } + +we currently produce: +_test: + movl $7, %eax + movsbl 4(%esp), %ecx + subl %ecx, %eax + ret + +We would use one fewer register if codegen'd as: + + movsbl 4(%esp), %eax + neg %eax + add $7, %eax + ret + +Note that this isn't beneficial if the load can be folded into the sub. In +this case, we want a sub: + +int test(int X) { return 7-X; } +_test: + movl $7, %eax + subl 4(%esp), %eax + ret + +//===---------------------------------------------------------------------===// + +Leaf functions that require one 4-byte spill slot have a prolog like this: + +_foo: + pushl %esi + subl $4, %esp +... +and an epilog like this: + addl $4, %esp + popl %esi + ret + +It would be smaller, and potentially faster, to push eax on entry and to +pop into a dummy register instead of using addl/subl of esp. Just don't pop +into any return registers :) + +//===---------------------------------------------------------------------===// + +The X86 backend should fold (branch (or (setcc, setcc))) into multiple +branches. We generate really poor code for: + +double testf(double a) { + return a == 0.0 ? 0.0 : (a > 0.0 ? 1.0 : -1.0); +} + +For example, the entry BB is: + +_testf: + subl $20, %esp + pxor %xmm0, %xmm0 + movsd 24(%esp), %xmm1 + ucomisd %xmm0, %xmm1 + setnp %al + sete %cl + testb %cl, %al + jne LBB1_5 # UnifiedReturnBlock +LBB1_1: # cond_true + + +it would be better to replace the last four instructions with: + + jp LBB1_1 + je LBB1_5 +LBB1_1: + +We also codegen the inner ?: into a diamond: + + cvtss2sd LCPI1_0(%rip), %xmm2 + cvtss2sd LCPI1_1(%rip), %xmm3 + ucomisd %xmm1, %xmm0 + ja LBB1_3 # cond_true +LBB1_2: # cond_true + movapd %xmm3, %xmm2 +LBB1_3: # cond_true + movapd %xmm2, %xmm0 + ret + +We should sink the load into xmm3 into the LBB1_2 block. This should +be pretty easy, and will nuke all the copies. + +//===---------------------------------------------------------------------===// + +This: + #include + inline std::pair full_add(unsigned a, unsigned b) + { return std::make_pair(a + b, a + b < a); } + bool no_overflow(unsigned a, unsigned b) + { return !full_add(a, b).second; } + +Should compile to: + + + _Z11no_overflowjj: + addl %edi, %esi + setae %al + ret + +FIXME: That code looks wrong; bool return is normally defined as zext. + +on x86-64, not: + +__Z11no_overflowjj: + addl %edi, %esi + cmpl %edi, %esi + setae %al + movzbl %al, %eax + ret + + +//===---------------------------------------------------------------------===// + +Re-materialize MOV32r0 etc. with xor instead of changing them to moves if the +condition register is dead. xor reg reg is shorter than mov reg, #0. + +//===---------------------------------------------------------------------===// + +The following code: + +bb114.preheader: ; preds = %cond_next94 + %tmp231232 = sext i16 %tmp62 to i32 ; [#uses=1] + %tmp233 = sub i32 32, %tmp231232 ; [#uses=1] + %tmp245246 = sext i16 %tmp65 to i32 ; [#uses=1] + %tmp252253 = sext i16 %tmp68 to i32 ; [#uses=1] + %tmp254 = sub i32 32, %tmp252253 ; [#uses=1] + %tmp553554 = bitcast i16* %tmp37 to i8* ; [#uses=2] + %tmp583584 = sext i16 %tmp98 to i32 ; [#uses=1] + %tmp585 = sub i32 32, %tmp583584 ; [#uses=1] + %tmp614615 = sext i16 %tmp101 to i32 ; [#uses=1] + %tmp621622 = sext i16 %tmp104 to i32 ; [#uses=1] + %tmp623 = sub i32 32, %tmp621622 ; [#uses=1] + br label %bb114 + +produces: + +LBB3_5: # bb114.preheader + movswl -68(%ebp), %eax + movl $32, %ecx + movl %ecx, -80(%ebp) + subl %eax, -80(%ebp) + movswl -52(%ebp), %eax + movl %ecx, -84(%ebp) + subl %eax, -84(%ebp) + movswl -70(%ebp), %eax + movl %ecx, -88(%ebp) + subl %eax, -88(%ebp) + movswl -50(%ebp), %eax + subl %eax, %ecx + movl %ecx, -76(%ebp) + movswl -42(%ebp), %eax + movl %eax, -92(%ebp) + movswl -66(%ebp), %eax + movl %eax, -96(%ebp) + movw $0, -98(%ebp) + +This appears to be bad because the RA is not folding the store to the stack +slot into the movl. The above instructions could be: + movl $32, -80(%ebp) +... + movl $32, -84(%ebp) +... +This seems like a cross between remat and spill folding. + +This has redundant subtractions of %eax from a stack slot. However, %ecx doesn't +change, so we could simply subtract %eax from %ecx first and then use %ecx (or +vice-versa). + +//===---------------------------------------------------------------------===// + +This code: + + %tmp659 = icmp slt i16 %tmp654, 0 ; [#uses=1] + br i1 %tmp659, label %cond_true662, label %cond_next715 + +produces this: + + testw %cx, %cx + movswl %cx, %esi + jns LBB4_109 # cond_next715 + +Shark tells us that using %cx in the testw instruction is sub-optimal. It +suggests using the 32-bit register (which is what ICC uses). + +//===---------------------------------------------------------------------===// + +We compile this: + +void compare (long long foo) { + if (foo < 4294967297LL) + abort(); +} + +to: + +compare: + subl $4, %esp + cmpl $0, 8(%esp) + setne %al + movzbw %al, %ax + cmpl $1, 12(%esp) + setg %cl + movzbw %cl, %cx + cmove %ax, %cx + testb $1, %cl + jne .LBB1_2 # UnifiedReturnBlock +.LBB1_1: # ifthen + call abort +.LBB1_2: # UnifiedReturnBlock + addl $4, %esp + ret + +(also really horrible code on ppc). This is due to the expand code for 64-bit +compares. GCC produces multiple branches, which is much nicer: + +compare: + subl $12, %esp + movl 20(%esp), %edx + movl 16(%esp), %eax + decl %edx + jle .L7 +.L5: + addl $12, %esp + ret + .p2align 4,,7 +.L7: + jl .L4 + cmpl $0, %eax + .p2align 4,,8 + ja .L5 +.L4: + .p2align 4,,9 + call abort + +//===---------------------------------------------------------------------===// + +Tail call optimization improvements: Tail call optimization currently +pushes all arguments on the top of the stack (their normal place for +non-tail call optimized calls) that source from the callers arguments +or that source from a virtual register (also possibly sourcing from +callers arguments). +This is done to prevent overwriting of parameters (see example +below) that might be used later. + +example: + +int callee(int32, int64); +int caller(int32 arg1, int32 arg2) { + int64 local = arg2 * 2; + return callee(arg2, (int64)local); +} + +[arg1] [!arg2 no longer valid since we moved local onto it] +[arg2] -> [(int64) +[RETADDR] local ] + +Moving arg1 onto the stack slot of callee function would overwrite +arg2 of the caller. + +Possible optimizations: + + + - Analyse the actual parameters of the callee to see which would + overwrite a caller parameter which is used by the callee and only + push them onto the top of the stack. + + int callee (int32 arg1, int32 arg2); + int caller (int32 arg1, int32 arg2) { + return callee(arg1,arg2); + } + + Here we don't need to write any variables to the top of the stack + since they don't overwrite each other. + + int callee (int32 arg1, int32 arg2); + int caller (int32 arg1, int32 arg2) { + return callee(arg2,arg1); + } + + Here we need to push the arguments because they overwrite each + other. + +//===---------------------------------------------------------------------===// + +main () +{ + int i = 0; + unsigned long int z = 0; + + do { + z -= 0x00004000; + i++; + if (i > 0x00040000) + abort (); + } while (z > 0); + exit (0); +} + +gcc compiles this to: + +_main: + subl $28, %esp + xorl %eax, %eax + jmp L2 +L3: + cmpl $262144, %eax + je L10 +L2: + addl $1, %eax + cmpl $262145, %eax + jne L3 + call L_abort$stub +L10: + movl $0, (%esp) + call L_exit$stub + +llvm: + +_main: + subl $12, %esp + movl $1, %eax + movl $16384, %ecx +LBB1_1: # bb + cmpl $262145, %eax + jge LBB1_4 # cond_true +LBB1_2: # cond_next + incl %eax + addl $4294950912, %ecx + cmpl $16384, %ecx + jne LBB1_1 # bb +LBB1_3: # bb11 + xorl %eax, %eax + addl $12, %esp + ret +LBB1_4: # cond_true + call L_abort$stub + +1. LSR should rewrite the first cmp with induction variable %ecx. +2. DAG combiner should fold + leal 1(%eax), %edx + cmpl $262145, %edx + => + cmpl $262144, %eax + +//===---------------------------------------------------------------------===// + +define i64 @test(double %X) { + %Y = fptosi double %X to i64 + ret i64 %Y +} + +compiles to: + +_test: + subl $20, %esp + movsd 24(%esp), %xmm0 + movsd %xmm0, 8(%esp) + fldl 8(%esp) + fisttpll (%esp) + movl 4(%esp), %edx + movl (%esp), %eax + addl $20, %esp + #FP_REG_KILL + ret + +This should just fldl directly from the input stack slot. + +//===---------------------------------------------------------------------===// + +This code: +int foo (int x) { return (x & 65535) | 255; } + +Should compile into: + +_foo: + movzwl 4(%esp), %eax + orl $255, %eax + ret + +instead of: +_foo: + movl $255, %eax + orl 4(%esp), %eax + andl $65535, %eax + ret + +//===---------------------------------------------------------------------===// + +We're codegen'ing multiply of long longs inefficiently: + +unsigned long long LLM(unsigned long long arg1, unsigned long long arg2) { + return arg1 * arg2; +} + +We compile to (fomit-frame-pointer): + +_LLM: + pushl %esi + movl 8(%esp), %ecx + movl 16(%esp), %esi + movl %esi, %eax + mull %ecx + imull 12(%esp), %esi + addl %edx, %esi + imull 20(%esp), %ecx + movl %esi, %edx + addl %ecx, %edx + popl %esi + ret + +This looks like a scheduling deficiency and lack of remat of the load from +the argument area. ICC apparently produces: + + movl 8(%esp), %ecx + imull 12(%esp), %ecx + movl 16(%esp), %eax + imull 4(%esp), %eax + addl %eax, %ecx + movl 4(%esp), %eax + mull 12(%esp) + addl %ecx, %edx + ret + +Note that it remat'd loads from 4(esp) and 12(esp). See this GCC PR: +http://gcc.gnu.org/bugzilla/show_bug.cgi?id=17236 + +//===---------------------------------------------------------------------===// + +We can fold a store into "zeroing a reg". Instead of: + +xorl %eax, %eax +movl %eax, 124(%esp) + +we should get: + +movl $0, 124(%esp) + +if the flags of the xor are dead. + +Likewise, we isel "x<<1" into "add reg,reg". If reg is spilled, this should +be folded into: shl [mem], 1 + +//===---------------------------------------------------------------------===// + +This testcase misses a read/modify/write opportunity (from PR1425): + +void vertical_decompose97iH1(int *b0, int *b1, int *b2, int width){ + int i; + for(i=0; i>0; +} + +We compile it down to: + +LBB1_2: # bb + movl (%esi,%edi,4), %ebx + addl (%ecx,%edi,4), %ebx + addl (%edx,%edi,4), %ebx + movl %ebx, (%ecx,%edi,4) + incl %edi + cmpl %eax, %edi + jne LBB1_2 # bb + +the inner loop should add to the memory location (%ecx,%edi,4), saving +a mov. Something like: + + movl (%esi,%edi,4), %ebx + addl (%edx,%edi,4), %ebx + addl %ebx, (%ecx,%edi,4) + +Here is another interesting example: + +void vertical_compose97iH1(int *b0, int *b1, int *b2, int width){ + int i; + for(i=0; i>0; +} + +We miss the r/m/w opportunity here by using 2 subs instead of an add+sub[mem]: + +LBB9_2: # bb + movl (%ecx,%edi,4), %ebx + subl (%esi,%edi,4), %ebx + subl (%edx,%edi,4), %ebx + movl %ebx, (%ecx,%edi,4) + incl %edi + cmpl %eax, %edi + jne LBB9_2 # bb + +Additionally, LSR should rewrite the exit condition of these loops to use +a stride-4 IV, would would allow all the scales in the loop to go away. +This would result in smaller code and more efficient microops. + +//===---------------------------------------------------------------------===// + +In SSE mode, we turn abs and neg into a load from the constant pool plus a xor +or and instruction, for example: + + xorpd LCPI1_0, %xmm2 + +However, if xmm2 gets spilled, we end up with really ugly code like this: + + movsd (%esp), %xmm0 + xorpd LCPI1_0, %xmm0 + movsd %xmm0, (%esp) + +Since we 'know' that this is a 'neg', we can actually "fold" the spill into +the neg/abs instruction, turning it into an *integer* operation, like this: + + xorl 2147483648, [mem+4] ## 2147483648 = (1 << 31) + +you could also use xorb, but xorl is less likely to lead to a partial register +stall. Here is a contrived testcase: + +double a, b, c; +void test(double *P) { + double X = *P; + a = X; + bar(); + X = -X; + b = X; + bar(); + c = X; +} + +//===---------------------------------------------------------------------===// + +handling llvm.memory.barrier on pre SSE2 cpus + +should generate: +lock ; mov %esp, %esp + +//===---------------------------------------------------------------------===// + +The generated code on x86 for checking for signed overflow on a multiply the +obvious way is much longer than it needs to be. + +int x(int a, int b) { + long long prod = (long long)a*b; + return prod > 0x7FFFFFFF || prod < (-0x7FFFFFFF-1); +} + +See PR2053 for more details. + +//===---------------------------------------------------------------------===// + +We should investigate using cdq/ctld (effect: edx = sar eax, 31) +more aggressively; it should cost the same as a move+shift on any modern +processor, but it's a lot shorter. Downside is that it puts more +pressure on register allocation because it has fixed operands. + +Example: +int abs(int x) {return x < 0 ? -x : x;} + +gcc compiles this to the following when using march/mtune=pentium2/3/4/m/etc.: +abs: + movl 4(%esp), %eax + cltd + xorl %edx, %eax + subl %edx, %eax + ret + +//===---------------------------------------------------------------------===// + +Consider: +int test(unsigned long a, unsigned long b) { return -(a < b); } + +We currently compile this to: + +define i32 @test(i32 %a, i32 %b) nounwind { + %tmp3 = icmp ult i32 %a, %b ; [#uses=1] + %tmp34 = zext i1 %tmp3 to i32 ; [#uses=1] + %tmp5 = sub i32 0, %tmp34 ; [#uses=1] + ret i32 %tmp5 +} + +and + +_test: + movl 8(%esp), %eax + cmpl %eax, 4(%esp) + setb %al + movzbl %al, %eax + negl %eax + ret + +Several deficiencies here. First, we should instcombine zext+neg into sext: + +define i32 @test2(i32 %a, i32 %b) nounwind { + %tmp3 = icmp ult i32 %a, %b ; [#uses=1] + %tmp34 = sext i1 %tmp3 to i32 ; [#uses=1] + ret i32 %tmp34 +} + +However, before we can do that, we have to fix the bad codegen that we get for +sext from bool: + +_test2: + movl 8(%esp), %eax + cmpl %eax, 4(%esp) + setb %al + movzbl %al, %eax + shll $31, %eax + sarl $31, %eax + ret + +This code should be at least as good as the code above. Once this is fixed, we +can optimize this specific case even more to: + + movl 8(%esp), %eax + xorl %ecx, %ecx + cmpl %eax, 4(%esp) + sbbl %ecx, %ecx + +//===---------------------------------------------------------------------===// + +Take the following code (from +http://gcc.gnu.org/bugzilla/show_bug.cgi?id=16541): + +extern unsigned char first_one[65536]; +int FirstOnet(unsigned long long arg1) +{ + if (arg1 >> 48) + return (first_one[arg1 >> 48]); + return 0; +} + + +The following code is currently generated: +FirstOnet: + movl 8(%esp), %eax + cmpl $65536, %eax + movl 4(%esp), %ecx + jb .LBB1_2 # UnifiedReturnBlock +.LBB1_1: # ifthen + shrl $16, %eax + movzbl first_one(%eax), %eax + ret +.LBB1_2: # UnifiedReturnBlock + xorl %eax, %eax + ret + +There are a few possible improvements here: +1. We should be able to eliminate the dead load into %ecx +2. We could change the "movl 8(%esp), %eax" into + "movzwl 10(%esp), %eax"; this lets us change the cmpl + into a testl, which is shorter, and eliminate the shift. + +We could also in theory eliminate the branch by using a conditional +for the address of the load, but that seems unlikely to be worthwhile +in general. + +//===---------------------------------------------------------------------===// + +We compile this function: + +define i32 @foo(i32 %a, i32 %b, i32 %c, i8 zeroext %d) nounwind { +entry: + %tmp2 = icmp eq i8 %d, 0 ; [#uses=1] + br i1 %tmp2, label %bb7, label %bb + +bb: ; preds = %entry + %tmp6 = add i32 %b, %a ; [#uses=1] + ret i32 %tmp6 + +bb7: ; preds = %entry + %tmp10 = sub i32 %a, %c ; [#uses=1] + ret i32 %tmp10 +} + +to: + +_foo: + cmpb $0, 16(%esp) + movl 12(%esp), %ecx + movl 8(%esp), %eax + movl 4(%esp), %edx + je LBB1_2 # bb7 +LBB1_1: # bb + addl %edx, %eax + ret +LBB1_2: # bb7 + movl %edx, %eax + subl %ecx, %eax + ret + +The coalescer could coalesce "edx" with "eax" to avoid the movl in LBB1_2 +if it commuted the addl in LBB1_1. + +//===---------------------------------------------------------------------===// + +See rdar://4653682. + +From flops: + +LBB1_15: # bb310 + cvtss2sd LCPI1_0, %xmm1 + addsd %xmm1, %xmm0 + movsd 176(%esp), %xmm2 + mulsd %xmm0, %xmm2 + movapd %xmm2, %xmm3 + mulsd %xmm3, %xmm3 + movapd %xmm3, %xmm4 + mulsd LCPI1_23, %xmm4 + addsd LCPI1_24, %xmm4 + mulsd %xmm3, %xmm4 + addsd LCPI1_25, %xmm4 + mulsd %xmm3, %xmm4 + addsd LCPI1_26, %xmm4 + mulsd %xmm3, %xmm4 + addsd LCPI1_27, %xmm4 + mulsd %xmm3, %xmm4 + addsd LCPI1_28, %xmm4 + mulsd %xmm3, %xmm4 + addsd %xmm1, %xmm4 + mulsd %xmm2, %xmm4 + movsd 152(%esp), %xmm1 + addsd %xmm4, %xmm1 + movsd %xmm1, 152(%esp) + incl %eax + cmpl %eax, %esi + jge LBB1_15 # bb310 +LBB1_16: # bb358.loopexit + movsd 152(%esp), %xmm0 + addsd %xmm0, %xmm0 + addsd LCPI1_22, %xmm0 + movsd %xmm0, 152(%esp) + +Rather than spilling the result of the last addsd in the loop, we should have +insert a copy to split the interval (one for the duration of the loop, one +extending to the fall through). The register pressure in the loop isn't high +enough to warrant the spill. + +Also check why xmm7 is not used at all in the function. + +//===---------------------------------------------------------------------===// + +Legalize loses track of the fact that bools are always zero extended when in +memory. This causes us to compile abort_gzip (from 164.gzip) from: + +target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128" +target triple = "i386-apple-darwin8" +@in_exit.4870.b = internal global i1 false ; [#uses=2] +define fastcc void @abort_gzip() noreturn nounwind { +entry: + %tmp.b.i = load i1* @in_exit.4870.b ; [#uses=1] + br i1 %tmp.b.i, label %bb.i, label %bb4.i +bb.i: ; preds = %entry + tail call void @exit( i32 1 ) noreturn nounwind + unreachable +bb4.i: ; preds = %entry + store i1 true, i1* @in_exit.4870.b + tail call void @exit( i32 1 ) noreturn nounwind + unreachable +} +declare void @exit(i32) noreturn nounwind + +into: + +_abort_gzip: + subl $12, %esp + movb _in_exit.4870.b, %al + notb %al + testb $1, %al + jne LBB1_2 ## bb4.i +LBB1_1: ## bb.i + ... + +//===---------------------------------------------------------------------===// + +We compile: + +int test(int x, int y) { + return x-y-1; +} + +into (-m64): + +_test: + decl %edi + movl %edi, %eax + subl %esi, %eax + ret + +it would be better to codegen as: x+~y (notl+addl) + +//===---------------------------------------------------------------------===// + +This code: + +int foo(const char *str,...) +{ + __builtin_va_list a; int x; + __builtin_va_start(a,str); x = __builtin_va_arg(a,int); __builtin_va_end(a); + return x; +} + +gets compiled into this on x86-64: + subq $200, %rsp + movaps %xmm7, 160(%rsp) + movaps %xmm6, 144(%rsp) + movaps %xmm5, 128(%rsp) + movaps %xmm4, 112(%rsp) + movaps %xmm3, 96(%rsp) + movaps %xmm2, 80(%rsp) + movaps %xmm1, 64(%rsp) + movaps %xmm0, 48(%rsp) + movq %r9, 40(%rsp) + movq %r8, 32(%rsp) + movq %rcx, 24(%rsp) + movq %rdx, 16(%rsp) + movq %rsi, 8(%rsp) + leaq (%rsp), %rax + movq %rax, 192(%rsp) + leaq 208(%rsp), %rax + movq %rax, 184(%rsp) + movl $48, 180(%rsp) + movl $8, 176(%rsp) + movl 176(%rsp), %eax + cmpl $47, %eax + jbe .LBB1_3 # bb +.LBB1_1: # bb3 + movq 184(%rsp), %rcx + leaq 8(%rcx), %rax + movq %rax, 184(%rsp) +.LBB1_2: # bb4 + movl (%rcx), %eax + addq $200, %rsp + ret +.LBB1_3: # bb + movl %eax, %ecx + addl $8, %eax + addq 192(%rsp), %rcx + movl %eax, 176(%rsp) + jmp .LBB1_2 # bb4 + +gcc 4.3 generates: + subq $96, %rsp +.LCFI0: + leaq 104(%rsp), %rax + movq %rsi, -80(%rsp) + movl $8, -120(%rsp) + movq %rax, -112(%rsp) + leaq -88(%rsp), %rax + movq %rax, -104(%rsp) + movl $8, %eax + cmpl $48, %eax + jb .L6 + movq -112(%rsp), %rdx + movl (%rdx), %eax + addq $96, %rsp + ret + .p2align 4,,10 + .p2align 3 +.L6: + mov %eax, %edx + addq -104(%rsp), %rdx + addl $8, %eax + movl %eax, -120(%rsp) + movl (%rdx), %eax + addq $96, %rsp + ret + +and it gets compiled into this on x86: + pushl %ebp + movl %esp, %ebp + subl $4, %esp + leal 12(%ebp), %eax + movl %eax, -4(%ebp) + leal 16(%ebp), %eax + movl %eax, -4(%ebp) + movl 12(%ebp), %eax + addl $4, %esp + popl %ebp + ret + +gcc 4.3 generates: + pushl %ebp + movl %esp, %ebp + movl 12(%ebp), %eax + popl %ebp + ret + +//===---------------------------------------------------------------------===// + +Teach tblgen not to check bitconvert source type in some cases. This allows us +to consolidate the following patterns in X86InstrMMX.td: + +def : Pat<(v2i32 (bitconvert (i64 (vector_extract (v2i64 VR128:$src), + (iPTR 0))))), + (v2i32 (MMX_MOVDQ2Qrr VR128:$src))>; +def : Pat<(v4i16 (bitconvert (i64 (vector_extract (v2i64 VR128:$src), + (iPTR 0))))), + (v4i16 (MMX_MOVDQ2Qrr VR128:$src))>; +def : Pat<(v8i8 (bitconvert (i64 (vector_extract (v2i64 VR128:$src), + (iPTR 0))))), + (v8i8 (MMX_MOVDQ2Qrr VR128:$src))>; + +There are other cases in various td files. + +//===---------------------------------------------------------------------===// + +Take something like the following on x86-32: +unsigned a(unsigned long long x, unsigned y) {return x % y;} + +We currently generate a libcall, but we really shouldn't: the expansion is +shorter and likely faster than the libcall. The expected code is something +like the following: + + movl 12(%ebp), %eax + movl 16(%ebp), %ecx + xorl %edx, %edx + divl %ecx + movl 8(%ebp), %eax + divl %ecx + movl %edx, %eax + ret + +A similar code sequence works for division. + +//===---------------------------------------------------------------------===// + +These should compile to the same code, but the later codegen's to useless +instructions on X86. This may be a trivial dag combine (GCC PR7061): + +struct s1 { unsigned char a, b; }; +unsigned long f1(struct s1 x) { + return x.a + x.b; +} +struct s2 { unsigned a: 8, b: 8; }; +unsigned long f2(struct s2 x) { + return x.a + x.b; +} + +//===---------------------------------------------------------------------===// + +We currently compile this: + +define i32 @func1(i32 %v1, i32 %v2) nounwind { +entry: + %t = call {i32, i1} @llvm.sadd.with.overflow.i32(i32 %v1, i32 %v2) + %sum = extractvalue {i32, i1} %t, 0 + %obit = extractvalue {i32, i1} %t, 1 + br i1 %obit, label %overflow, label %normal +normal: + ret i32 %sum +overflow: + call void @llvm.trap() + unreachable +} +declare {i32, i1} @llvm.sadd.with.overflow.i32(i32, i32) +declare void @llvm.trap() + +to: + +_func1: + movl 4(%esp), %eax + addl 8(%esp), %eax + jo LBB1_2 ## overflow +LBB1_1: ## normal + ret +LBB1_2: ## overflow + ud2 + +it would be nice to produce "into" someday. + +//===---------------------------------------------------------------------===// + +This code: + +void vec_mpys1(int y[], const int x[], int scaler) { +int i; +for (i = 0; i < 150; i++) + y[i] += (((long long)scaler * (long long)x[i]) >> 31); +} + +Compiles to this loop with GCC 3.x: + +.L5: + movl %ebx, %eax + imull (%edi,%ecx,4) + shrdl $31, %edx, %eax + addl %eax, (%esi,%ecx,4) + incl %ecx + cmpl $149, %ecx + jle .L5 + +llvm-gcc compiles it to the much uglier: + +LBB1_1: ## bb1 + movl 24(%esp), %eax + movl (%eax,%edi,4), %ebx + movl %ebx, %ebp + imull %esi, %ebp + movl %ebx, %eax + mull %ecx + addl %ebp, %edx + sarl $31, %ebx + imull %ecx, %ebx + addl %edx, %ebx + shldl $1, %eax, %ebx + movl 20(%esp), %eax + addl %ebx, (%eax,%edi,4) + incl %edi + cmpl $150, %edi + jne LBB1_1 ## bb1 + +//===---------------------------------------------------------------------===// + +Test instructions can be eliminated by using EFLAGS values from arithmetic +instructions. This is currently not done for mul, and, or, xor, neg, shl, +sra, srl, shld, shrd, atomic ops, and others. It is also currently not done +for read-modify-write instructions. It is also current not done if the +OF or CF flags are needed. + +The shift operators have the complication that when the shift count is +zero, EFLAGS is not set, so they can only subsume a test instruction if +the shift count is known to be non-zero. Also, using the EFLAGS value +from a shift is apparently very slow on some x86 implementations. + +In read-modify-write instructions, the root node in the isel match is +the store, and isel has no way for the use of the EFLAGS result of the +arithmetic to be remapped to the new node. + +Add and subtract instructions set OF on signed overflow and CF on unsiged +overflow, while test instructions always clear OF and CF. In order to +replace a test with an add or subtract in a situation where OF or CF is +needed, codegen must be able to prove that the operation cannot see +signed or unsigned overflow, respectively. + +//===---------------------------------------------------------------------===// + +memcpy/memmove do not lower to SSE copies when possible. A silly example is: +define <16 x float> @foo(<16 x float> %A) nounwind { + %tmp = alloca <16 x float>, align 16 + %tmp2 = alloca <16 x float>, align 16 + store <16 x float> %A, <16 x float>* %tmp + %s = bitcast <16 x float>* %tmp to i8* + %s2 = bitcast <16 x float>* %tmp2 to i8* + call void @llvm.memcpy.i64(i8* %s, i8* %s2, i64 64, i32 16) + %R = load <16 x float>* %tmp2 + ret <16 x float> %R +} + +declare void @llvm.memcpy.i64(i8* nocapture, i8* nocapture, i64, i32) nounwind + +which compiles to: + +_foo: + subl $140, %esp + movaps %xmm3, 112(%esp) + movaps %xmm2, 96(%esp) + movaps %xmm1, 80(%esp) + movaps %xmm0, 64(%esp) + movl 60(%esp), %eax + movl %eax, 124(%esp) + movl 56(%esp), %eax + movl %eax, 120(%esp) + movl 52(%esp), %eax + + movaps (%esp), %xmm0 + movaps 16(%esp), %xmm1 + movaps 32(%esp), %xmm2 + movaps 48(%esp), %xmm3 + addl $140, %esp + ret + +On Nehalem, it may even be cheaper to just use movups when unaligned than to +fall back to lower-granularity chunks. + +//===---------------------------------------------------------------------===// + +Implement processor-specific optimizations for parity with GCC on these +processors. GCC does two optimizations: + +1. ix86_pad_returns inserts a noop before ret instructions if immediately + preceeded by a conditional branch or is the target of a jump. +2. ix86_avoid_jump_misspredicts inserts noops in cases where a 16-byte block of + code contains more than 3 branches. + +The first one is done for all AMDs, Core2, and "Generic" +The second one is done for: Atom, Pentium Pro, all AMDs, Pentium 4, Nocona, + Core 2, and "Generic" + +//===---------------------------------------------------------------------===// + +Testcase: +int a(int x) { return (x & 127) > 31; } + +Current output: + movl 4(%esp), %eax + andl $127, %eax + cmpl $31, %eax + seta %al + movzbl %al, %eax + ret + +Ideal output: + xorl %eax, %eax + testl $96, 4(%esp) + setne %al + ret + +This should definitely be done in instcombine, canonicalizing the range +condition into a != condition. We get this IR: + +define i32 @a(i32 %x) nounwind readnone { +entry: + %0 = and i32 %x, 127 ; [#uses=1] + %1 = icmp ugt i32 %0, 31 ; [#uses=1] + %2 = zext i1 %1 to i32 ; [#uses=1] + ret i32 %2 +} + +Instcombine prefers to strength reduce relational comparisons to equality +comparisons when possible, this should be another case of that. This could +be handled pretty easily in InstCombiner::visitICmpInstWithInstAndIntCst, but it +looks like InstCombiner::visitICmpInstWithInstAndIntCst should really already +be redesigned to use ComputeMaskedBits and friends. + + +//===---------------------------------------------------------------------===// +Testcase: +int x(int a) { return (a&0xf0)>>4; } + +Current output: + movl 4(%esp), %eax + shrl $4, %eax + andl $15, %eax + ret + +Ideal output: + movzbl 4(%esp), %eax + shrl $4, %eax + ret + +//===---------------------------------------------------------------------===// + +Testcase: +int x(int a) { return (a & 0x80) ? 0x100 : 0; } +int y(int a) { return (a & 0x80) *2; } + +Current: + testl $128, 4(%esp) + setne %al + movzbl %al, %eax + shll $8, %eax + ret + +Better: + movl 4(%esp), %eax + addl %eax, %eax + andl $256, %eax + ret + +This is another general instcombine transformation that is profitable on all +targets. In LLVM IR, these functions look like this: + +define i32 @x(i32 %a) nounwind readnone { +entry: + %0 = and i32 %a, 128 + %1 = icmp eq i32 %0, 0 + %iftmp.0.0 = select i1 %1, i32 0, i32 256 + ret i32 %iftmp.0.0 +} + +define i32 @y(i32 %a) nounwind readnone { +entry: + %0 = shl i32 %a, 1 + %1 = and i32 %0, 256 + ret i32 %1 +} + +Replacing an icmp+select with a shift should always be considered profitable in +instcombine. + +//===---------------------------------------------------------------------===// + +Re-implement atomic builtins __sync_add_and_fetch() and __sync_sub_and_fetch +properly. + +When the return value is not used (i.e. only care about the value in the +memory), x86 does not have to use add to implement these. Instead, it can use +add, sub, inc, dec instructions with the "lock" prefix. + +This is currently implemented using a bit of instruction selection trick. The +issue is the target independent pattern produces one output and a chain and we +want to map it into one that just output a chain. The current trick is to select +it into a MERGE_VALUES with the first definition being an implicit_def. The +proper solution is to add new ISD opcodes for the no-output variant. DAG +combiner can then transform the node before it gets to target node selection. + +Problem #2 is we are adding a whole bunch of x86 atomic instructions when in +fact these instructions are identical to the non-lock versions. We need a way to +add target specific information to target nodes and have this information +carried over to machine instructions. Asm printer (or JIT) can use this +information to add the "lock" prefix. + +//===---------------------------------------------------------------------===// diff --git a/libclamav/c++/llvm/lib/Target/X86/TargetInfo/CMakeLists.txt b/libclamav/c++/llvm/lib/Target/X86/TargetInfo/CMakeLists.txt new file mode 100644 index 000000000..90be9f58c --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/X86/TargetInfo/CMakeLists.txt @@ -0,0 +1,7 @@ +include_directories( ${CMAKE_CURRENT_BINARY_DIR}/.. ${CMAKE_CURRENT_SOURCE_DIR}/.. ) + +add_llvm_library(LLVMX86Info + X86TargetInfo.cpp + ) + +add_dependencies(LLVMX86Info X86CodeGenTable_gen) diff --git a/libclamav/c++/llvm/lib/Target/X86/TargetInfo/Makefile b/libclamav/c++/llvm/lib/Target/X86/TargetInfo/Makefile new file mode 100644 index 000000000..6677d4bdf --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/X86/TargetInfo/Makefile @@ -0,0 +1,15 @@ +##===- lib/Target/X86/TargetInfo/Makefile ------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## +LEVEL = ../../../.. +LIBRARYNAME = LLVMX86Info + +# Hack: we need to include 'main' target directory to grab private headers +CPPFLAGS = -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. + +include $(LEVEL)/Makefile.common diff --git a/libclamav/c++/llvm/lib/Target/X86/TargetInfo/X86TargetInfo.cpp b/libclamav/c++/llvm/lib/Target/X86/TargetInfo/X86TargetInfo.cpp new file mode 100644 index 000000000..08d4d84f8 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/X86/TargetInfo/X86TargetInfo.cpp @@ -0,0 +1,23 @@ +//===-- X86TargetInfo.cpp - X86 Target Implementation ---------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "X86.h" +#include "llvm/Module.h" +#include "llvm/Target/TargetRegistry.h" +using namespace llvm; + +Target llvm::TheX86_32Target, llvm::TheX86_64Target; + +extern "C" void LLVMInitializeX86TargetInfo() { + RegisterTarget + X(TheX86_32Target, "x86", "32-bit X86: Pentium-Pro and above"); + + RegisterTarget + Y(TheX86_64Target, "x86-64", "64-bit X86: EM64T and AMD64"); +} diff --git a/libclamav/c++/llvm/lib/Target/X86/X86.h b/libclamav/c++/llvm/lib/Target/X86/X86.h new file mode 100644 index 000000000..a1671185a --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/X86/X86.h @@ -0,0 +1,83 @@ +//===-- X86.h - Top-level interface for X86 representation ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the entry points for global functions defined in the x86 +// target library, as used by the LLVM JIT. +// +//===----------------------------------------------------------------------===// + +#ifndef TARGET_X86_H +#define TARGET_X86_H + +#include "llvm/Target/TargetMachine.h" + +namespace llvm { + +class X86TargetMachine; +class FunctionPass; +class MachineCodeEmitter; +class MCCodeEmitter; +class JITCodeEmitter; +class Target; +class formatted_raw_ostream; + +/// createX86ISelDag - This pass converts a legalized DAG into a +/// X86-specific DAG, ready for instruction scheduling. +/// +FunctionPass *createX86ISelDag(X86TargetMachine &TM, + CodeGenOpt::Level OptLevel); + +/// createX86FloatingPointStackifierPass - This function returns a pass which +/// converts floating point register references and pseudo instructions into +/// floating point stack references and physical instructions. +/// +FunctionPass *createX86FloatingPointStackifierPass(); + +/// createX87FPRegKillInserterPass - This function returns a pass which +/// inserts FP_REG_KILL instructions where needed. +/// +FunctionPass *createX87FPRegKillInserterPass(); + +/// createX86CodeEmitterPass - Return a pass that emits the collected X86 code +/// to the specified MCE object. + +FunctionPass *createX86CodeEmitterPass(X86TargetMachine &TM, + MachineCodeEmitter &MCE); +FunctionPass *createX86JITCodeEmitterPass(X86TargetMachine &TM, + JITCodeEmitter &JCE); +FunctionPass *createX86ObjectCodeEmitterPass(X86TargetMachine &TM, + ObjectCodeEmitter &OCE); + +MCCodeEmitter *createX86MCCodeEmitter(const Target &, TargetMachine &TM); + +/// createX86EmitCodeToMemory - Returns a pass that converts a register +/// allocated function into raw machine code in a dynamically +/// allocated chunk of memory. +/// +FunctionPass *createEmitX86CodeToMemory(); + +/// createX86MaxStackAlignmentCalculatorPass - This function returns a pass +/// which calculates maximal stack alignment required for function +/// +FunctionPass *createX86MaxStackAlignmentCalculatorPass(); + +extern Target TheX86_32Target, TheX86_64Target; + +} // End llvm namespace + +// Defines symbolic names for X86 registers. This defines a mapping from +// register name to register number. +// +#include "X86GenRegisterNames.inc" + +// Defines symbolic names for the X86 instructions. +// +#include "X86GenInstrNames.inc" + +#endif diff --git a/libclamav/c++/llvm/lib/Target/X86/X86.td b/libclamav/c++/llvm/lib/Target/X86/X86.td new file mode 100644 index 000000000..da467fe6a --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/X86/X86.td @@ -0,0 +1,216 @@ +//===- X86.td - Target definition file for the Intel X86 ---*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This is a target description file for the Intel i386 architecture, refered to +// here as the "X86" architecture. +// +//===----------------------------------------------------------------------===// + +// Get the target-independent interfaces which we are implementing... +// +include "llvm/Target/Target.td" + +//===----------------------------------------------------------------------===// +// X86 Subtarget features. +//===----------------------------------------------------------------------===// + +def FeatureCMOV : SubtargetFeature<"cmov","HasCMov", "true", + "Enable conditional move instructions">; + +def FeatureMMX : SubtargetFeature<"mmx","X86SSELevel", "MMX", + "Enable MMX instructions">; +def FeatureSSE1 : SubtargetFeature<"sse", "X86SSELevel", "SSE1", + "Enable SSE instructions", + // SSE codegen depends on cmovs, and all + // SSE1+ processors support them. + [FeatureMMX, FeatureCMOV]>; +def FeatureSSE2 : SubtargetFeature<"sse2", "X86SSELevel", "SSE2", + "Enable SSE2 instructions", + [FeatureSSE1]>; +def FeatureSSE3 : SubtargetFeature<"sse3", "X86SSELevel", "SSE3", + "Enable SSE3 instructions", + [FeatureSSE2]>; +def FeatureSSSE3 : SubtargetFeature<"ssse3", "X86SSELevel", "SSSE3", + "Enable SSSE3 instructions", + [FeatureSSE3]>; +def FeatureSSE41 : SubtargetFeature<"sse41", "X86SSELevel", "SSE41", + "Enable SSE 4.1 instructions", + [FeatureSSSE3]>; +def FeatureSSE42 : SubtargetFeature<"sse42", "X86SSELevel", "SSE42", + "Enable SSE 4.2 instructions", + [FeatureSSE41]>; +def Feature3DNow : SubtargetFeature<"3dnow", "X863DNowLevel", "ThreeDNow", + "Enable 3DNow! instructions">; +def Feature3DNowA : SubtargetFeature<"3dnowa", "X863DNowLevel", "ThreeDNowA", + "Enable 3DNow! Athlon instructions", + [Feature3DNow]>; +// All x86-64 hardware has SSE2, but we don't mark SSE2 as an implied +// feature, because SSE2 can be disabled (e.g. for compiling OS kernels) +// without disabling 64-bit mode. +def Feature64Bit : SubtargetFeature<"64bit", "HasX86_64", "true", + "Support 64-bit instructions">; +def FeatureSlowBTMem : SubtargetFeature<"slow-bt-mem", "IsBTMemSlow", "true", + "Bit testing of memory is slow">; +def FeatureSSE4A : SubtargetFeature<"sse4a", "HasSSE4A", "true", + "Support SSE 4a instructions">; + +def FeatureAVX : SubtargetFeature<"avx", "HasAVX", "true", + "Enable AVX instructions">; +def FeatureFMA3 : SubtargetFeature<"fma3", "HasFMA3", "true", + "Enable three-operand fused multiple-add">; +def FeatureFMA4 : SubtargetFeature<"fma4", "HasFMA4", "true", + "Enable four-operand fused multiple-add">; + +//===----------------------------------------------------------------------===// +// X86 processors supported. +//===----------------------------------------------------------------------===// + +class Proc Features> + : Processor; + +def : Proc<"generic", []>; +def : Proc<"i386", []>; +def : Proc<"i486", []>; +def : Proc<"i586", []>; +def : Proc<"pentium", []>; +def : Proc<"pentium-mmx", [FeatureMMX]>; +def : Proc<"i686", []>; +def : Proc<"pentiumpro", [FeatureCMOV]>; +def : Proc<"pentium2", [FeatureMMX, FeatureCMOV]>; +def : Proc<"pentium3", [FeatureSSE1]>; +def : Proc<"pentium-m", [FeatureSSE2, FeatureSlowBTMem]>; +def : Proc<"pentium4", [FeatureSSE2]>; +def : Proc<"x86-64", [FeatureSSE2, Feature64Bit, FeatureSlowBTMem]>; +def : Proc<"yonah", [FeatureSSE3, FeatureSlowBTMem]>; +def : Proc<"prescott", [FeatureSSE3, FeatureSlowBTMem]>; +def : Proc<"nocona", [FeatureSSE3, Feature64Bit, FeatureSlowBTMem]>; +def : Proc<"core2", [FeatureSSSE3, Feature64Bit, FeatureSlowBTMem]>; +def : Proc<"penryn", [FeatureSSE41, Feature64Bit, FeatureSlowBTMem]>; +def : Proc<"atom", [FeatureSSE3, Feature64Bit, FeatureSlowBTMem]>; +def : Proc<"corei7", [FeatureSSE42, Feature64Bit, FeatureSlowBTMem]>; +def : Proc<"nehalem", [FeatureSSE42, Feature64Bit, FeatureSlowBTMem]>; +// Sandy Bridge does not have FMA +def : Proc<"sandybridge", [FeatureSSE42, FeatureAVX, Feature64Bit]>; + +def : Proc<"k6", [FeatureMMX]>; +def : Proc<"k6-2", [FeatureMMX, Feature3DNow]>; +def : Proc<"k6-3", [FeatureMMX, Feature3DNow]>; +def : Proc<"athlon", [FeatureMMX, Feature3DNowA, FeatureSlowBTMem]>; +def : Proc<"athlon-tbird", [FeatureMMX, Feature3DNowA, FeatureSlowBTMem]>; +def : Proc<"athlon-4", [FeatureSSE1, Feature3DNowA, FeatureSlowBTMem]>; +def : Proc<"athlon-xp", [FeatureSSE1, Feature3DNowA, FeatureSlowBTMem]>; +def : Proc<"athlon-mp", [FeatureSSE1, Feature3DNowA, FeatureSlowBTMem]>; +def : Proc<"k8", [FeatureSSE2, Feature3DNowA, Feature64Bit, + FeatureSlowBTMem]>; +def : Proc<"opteron", [FeatureSSE2, Feature3DNowA, Feature64Bit, + FeatureSlowBTMem]>; +def : Proc<"athlon64", [FeatureSSE2, Feature3DNowA, Feature64Bit, + FeatureSlowBTMem]>; +def : Proc<"athlon-fx", [FeatureSSE2, Feature3DNowA, Feature64Bit, + FeatureSlowBTMem]>; +def : Proc<"k8-sse3", [FeatureSSE3, Feature3DNowA, Feature64Bit, + FeatureSlowBTMem]>; +def : Proc<"opteron-sse3", [FeatureSSE3, Feature3DNowA, Feature64Bit, + FeatureSlowBTMem]>; +def : Proc<"athlon64-sse3", [FeatureSSE3, Feature3DNowA, Feature64Bit, + FeatureSlowBTMem]>; +def : Proc<"amdfam10", [FeatureSSE3, FeatureSSE4A, + Feature3DNowA, Feature64Bit, FeatureSlowBTMem]>; +def : Proc<"barcelona", [FeatureSSE3, FeatureSSE4A, + Feature3DNowA, Feature64Bit, FeatureSlowBTMem]>; +def : Proc<"istanbul", [Feature3DNowA, Feature64Bit, FeatureSSE4A, + Feature3DNowA]>; +def : Proc<"shanghai", [Feature3DNowA, Feature64Bit, FeatureSSE4A, + Feature3DNowA]>; + +def : Proc<"winchip-c6", [FeatureMMX]>; +def : Proc<"winchip2", [FeatureMMX, Feature3DNow]>; +def : Proc<"c3", [FeatureMMX, Feature3DNow]>; +def : Proc<"c3-2", [FeatureSSE1]>; + +//===----------------------------------------------------------------------===// +// Register File Description +//===----------------------------------------------------------------------===// + +include "X86RegisterInfo.td" + +//===----------------------------------------------------------------------===// +// Instruction Descriptions +//===----------------------------------------------------------------------===// + +include "X86InstrInfo.td" + +def X86InstrInfo : InstrInfo { + + // Define how we want to layout our TargetSpecific information field... This + // should be kept up-to-date with the fields in the X86InstrInfo.h file. + let TSFlagsFields = ["FormBits", + "hasOpSizePrefix", + "hasAdSizePrefix", + "Prefix", + "hasREX_WPrefix", + "ImmTypeBits", + "FPFormBits", + "hasLockPrefix", + "SegOvrBits", + "Opcode"]; + let TSFlagsShifts = [0, + 6, + 7, + 8, + 12, + 13, + 16, + 19, + 20, + 24]; +} + +//===----------------------------------------------------------------------===// +// Calling Conventions +//===----------------------------------------------------------------------===// + +include "X86CallingConv.td" + + +//===----------------------------------------------------------------------===// +// Assembly Printers +//===----------------------------------------------------------------------===// + +// Currently the X86 assembly parser only supports ATT syntax. +def ATTAsmParser : AsmParser { + string AsmParserClassName = "ATTAsmParser"; + int Variant = 0; + + // Discard comments in assembly strings. + string CommentDelimiter = "#"; + + // Recognize hard coded registers. + string RegisterPrefix = "%"; +} + +// The X86 target supports two different syntaxes for emitting machine code. +// This is controlled by the -x86-asm-syntax={att|intel} +def ATTAsmWriter : AsmWriter { + string AsmWriterClassName = "ATTInstPrinter"; + int Variant = 0; +} +def IntelAsmWriter : AsmWriter { + string AsmWriterClassName = "IntelInstPrinter"; + int Variant = 1; +} + +def X86 : Target { + // Information about the instructions... + let InstructionSet = X86InstrInfo; + + let AssemblyParsers = [ATTAsmParser]; + + let AssemblyWriters = [ATTAsmWriter, IntelAsmWriter]; +} diff --git a/libclamav/c++/llvm/lib/Target/X86/X86COFF.h b/libclamav/c++/llvm/lib/Target/X86/X86COFF.h new file mode 100644 index 000000000..0a8e4e6ac --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/X86/X86COFF.h @@ -0,0 +1,95 @@ +//===--- X86COFF.h - Some definitions from COFF documentations ------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file just defines some symbols found in COFF documentation. They are +// used to emit function type information for COFF targets (Cygwin/Mingw32). +// +//===----------------------------------------------------------------------===// + +#ifndef X86COFF_H +#define X86COFF_H + +namespace COFF +{ +/// Storage class tells where and what the symbol represents +enum StorageClass { + C_EFCN = -1, ///< Physical end of function + C_NULL = 0, ///< No symbol + C_AUTO = 1, ///< External definition + C_EXT = 2, ///< External symbol + C_STAT = 3, ///< Static + C_REG = 4, ///< Register variable + C_EXTDEF = 5, ///< External definition + C_LABEL = 6, ///< Label + C_ULABEL = 7, ///< Undefined label + C_MOS = 8, ///< Member of structure + C_ARG = 9, ///< Function argument + C_STRTAG = 10, ///< Structure tag + C_MOU = 11, ///< Member of union + C_UNTAG = 12, ///< Union tag + C_TPDEF = 13, ///< Type definition + C_USTATIC = 14, ///< Undefined static + C_ENTAG = 15, ///< Enumeration tag + C_MOE = 16, ///< Member of enumeration + C_REGPARM = 17, ///< Register parameter + C_FIELD = 18, ///< Bit field + + C_BLOCK = 100, ///< ".bb" or ".eb" - beginning or end of block + C_FCN = 101, ///< ".bf" or ".ef" - beginning or end of function + C_EOS = 102, ///< End of structure + C_FILE = 103, ///< File name + C_LINE = 104, ///< Line number, reformatted as symbol + C_ALIAS = 105, ///< Duplicate tag + C_HIDDEN = 106 ///< External symbol in dmert public lib +}; + +/// The type of the symbol. This is made up of a base type and a derived type. +/// For example, pointer to int is "pointer to T" and "int" +enum SymbolType { + T_NULL = 0, ///< No type info + T_ARG = 1, ///< Void function argument (only used by compiler) + T_VOID = 1, ///< The same as above. Just named differently in some specs. + T_CHAR = 2, ///< Character + T_SHORT = 3, ///< Short integer + T_INT = 4, ///< Integer + T_LONG = 5, ///< Long integer + T_FLOAT = 6, ///< Floating point + T_DOUBLE = 7, ///< Double word + T_STRUCT = 8, ///< Structure + T_UNION = 9, ///< Union + T_ENUM = 10, ///< Enumeration + T_MOE = 11, ///< Member of enumeration + T_UCHAR = 12, ///< Unsigned character + T_USHORT = 13, ///< Unsigned short + T_UINT = 14, ///< Unsigned integer + T_ULONG = 15 ///< Unsigned long +}; + +/// Derived type of symbol +enum SymbolDerivedType { + DT_NON = 0, ///< No derived type + DT_PTR = 1, ///< Pointer to T + DT_FCN = 2, ///< Function returning T + DT_ARY = 3 ///< Array of T +}; + +/// Masks for extracting parts of type +enum SymbolTypeMasks { + N_BTMASK = 017, ///< Mask for base type + N_TMASK = 060 ///< Mask for derived type +}; + +/// Offsets of parts of type +enum Shifts { + N_BTSHFT = 4 ///< Type is formed as (base + derived << N_BTSHIFT) +}; + +} + +#endif // X86COFF_H diff --git a/libclamav/c++/llvm/lib/Target/X86/X86COFFMachineModuleInfo.cpp b/libclamav/c++/llvm/lib/Target/X86/X86COFFMachineModuleInfo.cpp new file mode 100644 index 000000000..01c4fcfa1 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/X86/X86COFFMachineModuleInfo.cpp @@ -0,0 +1,123 @@ +//===-- llvm/CodeGen/X86COFFMachineModuleInfo.cpp -------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This is an MMI implementation for X86 COFF (windows) targets. +// +//===----------------------------------------------------------------------===// + +#include "X86COFFMachineModuleInfo.h" +#include "X86MachineFunctionInfo.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Function.h" +#include "llvm/Target/TargetData.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +X86COFFMachineModuleInfo::X86COFFMachineModuleInfo(const MachineModuleInfo &) { +} +X86COFFMachineModuleInfo::~X86COFFMachineModuleInfo() { + +} + +void X86COFFMachineModuleInfo::AddFunctionInfo(const Function *F, + const X86MachineFunctionInfo &Val) { + FunctionInfoMap[F] = Val; +} + + + +static X86MachineFunctionInfo calculateFunctionInfo(const Function *F, + const TargetData &TD) { + X86MachineFunctionInfo Info; + uint64_t Size = 0; + + switch (F->getCallingConv()) { + case CallingConv::X86_StdCall: + Info.setDecorationStyle(StdCall); + break; + case CallingConv::X86_FastCall: + Info.setDecorationStyle(FastCall); + break; + default: + return Info; + } + + unsigned argNum = 1; + for (Function::const_arg_iterator AI = F->arg_begin(), AE = F->arg_end(); + AI != AE; ++AI, ++argNum) { + const Type* Ty = AI->getType(); + + // 'Dereference' type in case of byval parameter attribute + if (F->paramHasAttr(argNum, Attribute::ByVal)) + Ty = cast(Ty)->getElementType(); + + // Size should be aligned to DWORD boundary + Size += ((TD.getTypeAllocSize(Ty) + 3)/4)*4; + } + + // We're not supporting tooooo huge arguments :) + Info.setBytesToPopOnReturn((unsigned int)Size); + return Info; +} + + +/// DecorateCygMingName - Query FunctionInfoMap and use this information for +/// various name decorations for Cygwin and MingW. +void X86COFFMachineModuleInfo::DecorateCygMingName(SmallVectorImpl &Name, + const GlobalValue *GV, + const TargetData &TD) { + const Function *F = dyn_cast(GV); + if (!F) return; + + // Save function name for later type emission. + if (F->isDeclaration()) + CygMingStubs.insert(StringRef(Name.data(), Name.size())); + + // We don't want to decorate non-stdcall or non-fastcall functions right now + CallingConv::ID CC = F->getCallingConv(); + if (CC != CallingConv::X86_StdCall && CC != CallingConv::X86_FastCall) + return; + + const X86MachineFunctionInfo *Info; + + FMFInfoMap::const_iterator info_item = FunctionInfoMap.find(F); + if (info_item == FunctionInfoMap.end()) { + // Calculate apropriate function info and populate map + FunctionInfoMap[F] = calculateFunctionInfo(F, TD); + Info = &FunctionInfoMap[F]; + } else { + Info = &info_item->second; + } + + if (Info->getDecorationStyle() == None) return; + const FunctionType *FT = F->getFunctionType(); + + // "Pure" variadic functions do not receive @0 suffix. + if (!FT->isVarArg() || FT->getNumParams() == 0 || + (FT->getNumParams() == 1 && F->hasStructRetAttr())) + raw_svector_ostream(Name) << '@' << Info->getBytesToPopOnReturn(); + + if (Info->getDecorationStyle() == FastCall) { + if (Name[0] == '_') + Name[0] = '@'; + else + Name.insert(Name.begin(), '@'); + } +} + +/// DecorateCygMingName - Query FunctionInfoMap and use this information for +/// various name decorations for Cygwin and MingW. +void X86COFFMachineModuleInfo::DecorateCygMingName(std::string &Name, + const GlobalValue *GV, + const TargetData &TD) { + SmallString<128> NameStr(Name.begin(), Name.end()); + DecorateCygMingName(NameStr, GV, TD); + Name.assign(NameStr.begin(), NameStr.end()); +} diff --git a/libclamav/c++/llvm/lib/Target/X86/X86COFFMachineModuleInfo.h b/libclamav/c++/llvm/lib/Target/X86/X86COFFMachineModuleInfo.h new file mode 100644 index 000000000..afd552563 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/X86/X86COFFMachineModuleInfo.h @@ -0,0 +1,67 @@ +//===-- llvm/CodeGen/X86COFFMachineModuleInfo.h -----------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This is an MMI implementation for X86 COFF (windows) targets. +// +//===----------------------------------------------------------------------===// + +#ifndef X86COFF_MACHINEMODULEINFO_H +#define X86COFF_MACHINEMODULEINFO_H + +#include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/ADT/StringSet.h" + +namespace llvm { + class X86MachineFunctionInfo; + class TargetData; + +/// X86COFFMachineModuleInfo - This is a MachineModuleInfoImpl implementation +/// for X86 COFF targets. +class X86COFFMachineModuleInfo : public MachineModuleInfoImpl { + StringSet<> CygMingStubs; + + // We have to propagate some information about MachineFunction to + // AsmPrinter. It's ok, when we're printing the function, since we have + // access to MachineFunction and can get the appropriate MachineFunctionInfo. + // Unfortunately, this is not possible when we're printing reference to + // Function (e.g. calling it and so on). Even more, there is no way to get the + // corresponding MachineFunctions: it can even be not created at all. That's + // why we should use additional structure, when we're collecting all necessary + // information. + // + // This structure is using e.g. for name decoration for stdcall & fastcall'ed + // function, since we have to use arguments' size for decoration. + typedef std::map FMFInfoMap; + FMFInfoMap FunctionInfoMap; + +public: + X86COFFMachineModuleInfo(const MachineModuleInfo &); + ~X86COFFMachineModuleInfo(); + + + void DecorateCygMingName(std::string &Name, const GlobalValue *GV, + const TargetData &TD); + void DecorateCygMingName(SmallVectorImpl &Name, const GlobalValue *GV, + const TargetData &TD); + + void AddFunctionInfo(const Function *F, const X86MachineFunctionInfo &Val); + + + typedef StringSet<>::const_iterator stub_iterator; + stub_iterator stub_begin() const { return CygMingStubs.begin(); } + stub_iterator stub_end() const { return CygMingStubs.end(); } + + +}; + + + +} // end namespace llvm + +#endif diff --git a/libclamav/c++/llvm/lib/Target/X86/X86CallingConv.td b/libclamav/c++/llvm/lib/Target/X86/X86CallingConv.td new file mode 100644 index 000000000..d77f0390b --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/X86/X86CallingConv.td @@ -0,0 +1,315 @@ +//===- X86CallingConv.td - Calling Conventions X86 32/64 ---*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This describes the calling conventions for the X86-32 and X86-64 +// architectures. +// +//===----------------------------------------------------------------------===// + +/// CCIfSubtarget - Match if the current subtarget has a feature F. +class CCIfSubtarget + : CCIf().", F), A>; + +//===----------------------------------------------------------------------===// +// Return Value Calling Conventions +//===----------------------------------------------------------------------===// + +// Return-value conventions common to all X86 CC's. +def RetCC_X86Common : CallingConv<[ + // Scalar values are returned in AX first, then DX. For i8, the ABI + // requires the values to be in AL and AH, however this code uses AL and DL + // instead. This is because using AH for the second register conflicts with + // the way LLVM does multiple return values -- a return of {i16,i8} would end + // up in AX and AH, which overlap. Front-ends wishing to conform to the ABI + // for functions that return two i8 values are currently expected to pack the + // values into an i16 (which uses AX, and thus AL:AH). + CCIfType<[i8] , CCAssignToReg<[AL, DL]>>, + CCIfType<[i16], CCAssignToReg<[AX, DX]>>, + CCIfType<[i32], CCAssignToReg<[EAX, EDX]>>, + CCIfType<[i64], CCAssignToReg<[RAX, RDX]>>, + + // Vector types are returned in XMM0 and XMM1, when they fit. XMMM2 and XMM3 + // can only be used by ABI non-compliant code. If the target doesn't have XMM + // registers, it won't have vector types. + CCIfType<[v16i8, v8i16, v4i32, v2i64, v4f32, v2f64], + CCAssignToReg<[XMM0,XMM1,XMM2,XMM3]>>, + + // MMX vector types are always returned in MM0. If the target doesn't have + // MM0, it doesn't support these vector types. + CCIfType<[v8i8, v4i16, v2i32, v1i64, v2f32], CCAssignToReg<[MM0]>>, + + // Long double types are always returned in ST0 (even with SSE). + CCIfType<[f80], CCAssignToReg<[ST0, ST1]>> +]>; + +// X86-32 C return-value convention. +def RetCC_X86_32_C : CallingConv<[ + // The X86-32 calling convention returns FP values in ST0, unless marked + // with "inreg" (used here to distinguish one kind of reg from another, + // weirdly; this is really the sse-regparm calling convention) in which + // case they use XMM0, otherwise it is the same as the common X86 calling + // conv. + CCIfInReg>>>, + CCIfType<[f32,f64], CCAssignToReg<[ST0, ST1]>>, + CCDelegateTo +]>; + +// X86-32 FastCC return-value convention. +def RetCC_X86_32_Fast : CallingConv<[ + // The X86-32 fastcc returns 1, 2, or 3 FP values in XMM0-2 if the target has + // SSE2, otherwise it is the the C calling conventions. + // This can happen when a float, 2 x float, or 3 x float vector is split by + // target lowering, and is returned in 1-3 sse regs. + CCIfType<[f32], CCIfSubtarget<"hasSSE2()", CCAssignToReg<[XMM0,XMM1,XMM2]>>>, + CCIfType<[f64], CCIfSubtarget<"hasSSE2()", CCAssignToReg<[XMM0,XMM1,XMM2]>>>, + CCDelegateTo +]>; + +// X86-64 C return-value convention. +def RetCC_X86_64_C : CallingConv<[ + // The X86-64 calling convention always returns FP values in XMM0. + CCIfType<[f32], CCAssignToReg<[XMM0, XMM1]>>, + CCIfType<[f64], CCAssignToReg<[XMM0, XMM1]>>, + + // MMX vector types are always returned in XMM0 except for v1i64 which is + // returned in RAX. This disagrees with ABI documentation but is bug + // compatible with gcc. + CCIfType<[v1i64], CCAssignToReg<[RAX]>>, + CCIfType<[v8i8, v4i16, v2i32, v2f32], CCAssignToReg<[XMM0, XMM1]>>, + CCDelegateTo +]>; + +// X86-Win64 C return-value convention. +def RetCC_X86_Win64_C : CallingConv<[ + // The X86-Win64 calling convention always returns __m64 values in RAX. + CCIfType<[v8i8, v4i16, v2i32, v1i64], CCBitConvertToType>, + + // And FP in XMM0 only. + CCIfType<[f32], CCAssignToReg<[XMM0]>>, + CCIfType<[f64], CCAssignToReg<[XMM0]>>, + + // Otherwise, everything is the same as 'normal' X86-64 C CC. + CCDelegateTo +]>; + + +// This is the root return-value convention for the X86-32 backend. +def RetCC_X86_32 : CallingConv<[ + // If FastCC, use RetCC_X86_32_Fast. + CCIfCC<"CallingConv::Fast", CCDelegateTo>, + // Otherwise, use RetCC_X86_32_C. + CCDelegateTo +]>; + +// This is the root return-value convention for the X86-64 backend. +def RetCC_X86_64 : CallingConv<[ + // Mingw64 and native Win64 use Win64 CC + CCIfSubtarget<"isTargetWin64()", CCDelegateTo>, + + // Otherwise, drop to normal X86-64 CC + CCDelegateTo +]>; + +// This is the return-value convention used for the entire X86 backend. +def RetCC_X86 : CallingConv<[ + CCIfSubtarget<"is64Bit()", CCDelegateTo>, + CCDelegateTo +]>; + +//===----------------------------------------------------------------------===// +// X86-64 Argument Calling Conventions +//===----------------------------------------------------------------------===// + +def CC_X86_64_C : CallingConv<[ + // Handles byval parameters. + CCIfByVal>, + + // Promote i8/i16 arguments to i32. + CCIfType<[i8, i16], CCPromoteToType>, + + // The 'nest' parameter, if any, is passed in R10. + CCIfNest>, + + // The first 6 v1i64 vector arguments are passed in GPRs on Darwin. + CCIfType<[v1i64], + CCIfSubtarget<"isTargetDarwin()", + CCBitConvertToType>>, + + // The first 6 integer arguments are passed in integer registers. + CCIfType<[i32], CCAssignToReg<[EDI, ESI, EDX, ECX, R8D, R9D]>>, + CCIfType<[i64], CCAssignToReg<[RDI, RSI, RDX, RCX, R8 , R9 ]>>, + + // The first 8 MMX (except for v1i64) vector arguments are passed in XMM + // registers on Darwin. + CCIfType<[v8i8, v4i16, v2i32, v2f32], + CCIfSubtarget<"isTargetDarwin()", + CCIfSubtarget<"hasSSE2()", + CCPromoteToType>>>, + + // The first 8 FP/Vector arguments are passed in XMM registers. + CCIfType<[f32, f64, v16i8, v8i16, v4i32, v2i64, v4f32, v2f64], + CCIfSubtarget<"hasSSE1()", + CCAssignToReg<[XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6, XMM7]>>>, + + // Integer/FP values get stored in stack slots that are 8 bytes in size and + // 8-byte aligned if there are no more registers to hold them. + CCIfType<[i32, i64, f32, f64], CCAssignToStack<8, 8>>, + + // Long doubles get stack slots whose size and alignment depends on the + // subtarget. + CCIfType<[f80], CCAssignToStack<0, 0>>, + + // Vectors get 16-byte stack slots that are 16-byte aligned. + CCIfType<[v16i8, v8i16, v4i32, v2i64, v4f32, v2f64], CCAssignToStack<16, 16>>, + + // __m64 vectors get 8-byte stack slots that are 8-byte aligned. + CCIfType<[v8i8, v4i16, v2i32, v1i64, v2f32], CCAssignToStack<8, 8>> +]>; + +// Calling convention used on Win64 +def CC_X86_Win64_C : CallingConv<[ + // FIXME: Handle byval stuff. + // FIXME: Handle varargs. + + // Promote i8/i16 arguments to i32. + CCIfType<[i8, i16], CCPromoteToType>, + + // The 'nest' parameter, if any, is passed in R10. + CCIfNest>, + + // 128 bit vectors are passed by pointer + CCIfType<[v16i8, v8i16, v4i32, v2i64, v4f32, v2f64], CCPassIndirect>, + + // The first 4 MMX vector arguments are passed in GPRs. + CCIfType<[v8i8, v4i16, v2i32, v1i64, v2f32], + CCBitConvertToType>, + + // The first 4 integer arguments are passed in integer registers. + CCIfType<[i32], CCAssignToRegWithShadow<[ECX , EDX , R8D , R9D ], + [XMM0, XMM1, XMM2, XMM3]>>, + CCIfType<[i64], CCAssignToRegWithShadow<[RCX , RDX , R8 , R9 ], + [XMM0, XMM1, XMM2, XMM3]>>, + + // The first 4 FP/Vector arguments are passed in XMM registers. + CCIfType<[f32, f64, v16i8, v8i16, v4i32, v2i64, v4f32, v2f64], + CCAssignToRegWithShadow<[XMM0, XMM1, XMM2, XMM3], + [RCX , RDX , R8 , R9 ]>>, + + // Integer/FP values get stored in stack slots that are 8 bytes in size and + // 8-byte aligned if there are no more registers to hold them. + CCIfType<[i32, i64, f32, f64], CCAssignToStack<8, 8>>, + + // Long doubles get stack slots whose size and alignment depends on the + // subtarget. + CCIfType<[f80], CCAssignToStack<0, 0>>, + + // __m64 vectors get 8-byte stack slots that are 8-byte aligned. + CCIfType<[v8i8, v4i16, v2i32, v1i64], CCAssignToStack<8, 8>> +]>; + +//===----------------------------------------------------------------------===// +// X86 C Calling Convention +//===----------------------------------------------------------------------===// + +/// CC_X86_32_Common - In all X86-32 calling conventions, extra integers and FP +/// values are spilled on the stack, and the first 4 vector values go in XMM +/// regs. +def CC_X86_32_Common : CallingConv<[ + // Handles byval parameters. + CCIfByVal>, + + // The first 3 float or double arguments, if marked 'inreg' and if the call + // is not a vararg call and if SSE2 is available, are passed in SSE registers. + CCIfNotVarArg>>>>, + + // The first 3 __m64 (except for v1i64) vector arguments are passed in mmx + // registers if the call is not a vararg call. + CCIfNotVarArg>>, + + // Integer/Float values get stored in stack slots that are 4 bytes in + // size and 4-byte aligned. + CCIfType<[i32, f32], CCAssignToStack<4, 4>>, + + // Doubles get 8-byte slots that are 4-byte aligned. + CCIfType<[f64], CCAssignToStack<8, 4>>, + + // Long doubles get slots whose size depends on the subtarget. + CCIfType<[f80], CCAssignToStack<0, 4>>, + + // The first 4 SSE vector arguments are passed in XMM registers. + CCIfNotVarArg>>, + + // Other SSE vectors get 16-byte stack slots that are 16-byte aligned. + CCIfType<[v16i8, v8i16, v4i32, v2i64, v4f32, v2f64], CCAssignToStack<16, 16>>, + + // __m64 vectors get 8-byte stack slots that are 4-byte aligned. They are + // passed in the parameter area. + CCIfType<[v8i8, v4i16, v2i32, v1i64], CCAssignToStack<8, 4>>]>; + +def CC_X86_32_C : CallingConv<[ + // Promote i8/i16 arguments to i32. + CCIfType<[i8, i16], CCPromoteToType>, + + // The 'nest' parameter, if any, is passed in ECX. + CCIfNest>, + + // The first 3 integer arguments, if marked 'inreg' and if the call is not + // a vararg call, are passed in integer registers. + CCIfNotVarArg>>>, + + // Otherwise, same as everything else. + CCDelegateTo +]>; + +def CC_X86_32_FastCall : CallingConv<[ + // Promote i8/i16 arguments to i32. + CCIfType<[i8, i16], CCPromoteToType>, + + // The 'nest' parameter, if any, is passed in EAX. + CCIfNest>, + + // The first 2 integer arguments are passed in ECX/EDX + CCIfType<[i32], CCAssignToReg<[ECX, EDX]>>, + + // Otherwise, same as everything else. + CCDelegateTo +]>; + +def CC_X86_32_FastCC : CallingConv<[ + // Handles byval parameters. Note that we can't rely on the delegation + // to CC_X86_32_Common for this because that happens after code that + // puts arguments in registers. + CCIfByVal>, + + // Promote i8/i16 arguments to i32. + CCIfType<[i8, i16], CCPromoteToType>, + + // The 'nest' parameter, if any, is passed in EAX. + CCIfNest>, + + // The first 2 integer arguments are passed in ECX/EDX + CCIfType<[i32], CCAssignToReg<[ECX, EDX]>>, + + // The first 3 float or double arguments, if the call is not a vararg + // call and if SSE2 is available, are passed in SSE registers. + CCIfNotVarArg>>>, + + // Doubles get 8-byte slots that are 8-byte aligned. + CCIfType<[f64], CCAssignToStack<8, 8>>, + + // Otherwise, same as everything else. + CCDelegateTo +]>; diff --git a/libclamav/c++/llvm/lib/Target/X86/X86CodeEmitter.cpp b/libclamav/c++/llvm/lib/Target/X86/X86CodeEmitter.cpp new file mode 100644 index 000000000..4892e1746 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/X86/X86CodeEmitter.cpp @@ -0,0 +1,1105 @@ +//===-- X86/X86CodeEmitter.cpp - Convert X86 code to machine code ---------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the pass that transforms the X86 machine instructions into +// relocatable machine code. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "x86-emitter" +#include "X86InstrInfo.h" +#include "X86JITInfo.h" +#include "X86Subtarget.h" +#include "X86TargetMachine.h" +#include "X86Relocations.h" +#include "X86.h" +#include "llvm/LLVMContext.h" +#include "llvm/PassManager.h" +#include "llvm/CodeGen/MachineCodeEmitter.h" +#include "llvm/CodeGen/JITCodeEmitter.h" +#include "llvm/CodeGen/ObjectCodeEmitter.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/Function.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/MC/MCCodeEmitter.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCInst.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Target/TargetOptions.h" +using namespace llvm; + +STATISTIC(NumEmitted, "Number of machine instructions emitted"); + +namespace { + template + class Emitter : public MachineFunctionPass { + const X86InstrInfo *II; + const TargetData *TD; + X86TargetMachine &TM; + CodeEmitter &MCE; + intptr_t PICBaseOffset; + bool Is64BitMode; + bool IsPIC; + public: + static char ID; + explicit Emitter(X86TargetMachine &tm, CodeEmitter &mce) + : MachineFunctionPass(&ID), II(0), TD(0), TM(tm), + MCE(mce), PICBaseOffset(0), Is64BitMode(false), + IsPIC(TM.getRelocationModel() == Reloc::PIC_) {} + Emitter(X86TargetMachine &tm, CodeEmitter &mce, + const X86InstrInfo &ii, const TargetData &td, bool is64) + : MachineFunctionPass(&ID), II(&ii), TD(&td), TM(tm), + MCE(mce), PICBaseOffset(0), Is64BitMode(is64), + IsPIC(TM.getRelocationModel() == Reloc::PIC_) {} + + bool runOnMachineFunction(MachineFunction &MF); + + virtual const char *getPassName() const { + return "X86 Machine Code Emitter"; + } + + void emitInstruction(const MachineInstr &MI, + const TargetInstrDesc *Desc); + + void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + AU.addRequired(); + MachineFunctionPass::getAnalysisUsage(AU); + } + + private: + void emitPCRelativeBlockAddress(MachineBasicBlock *MBB); + void emitGlobalAddress(GlobalValue *GV, unsigned Reloc, + intptr_t Disp = 0, intptr_t PCAdj = 0, + bool Indirect = false); + void emitExternalSymbolAddress(const char *ES, unsigned Reloc); + void emitConstPoolAddress(unsigned CPI, unsigned Reloc, intptr_t Disp = 0, + intptr_t PCAdj = 0); + void emitJumpTableAddress(unsigned JTI, unsigned Reloc, + intptr_t PCAdj = 0); + + void emitDisplacementField(const MachineOperand *RelocOp, int DispVal, + intptr_t Adj = 0, bool IsPCRel = true); + + void emitRegModRMByte(unsigned ModRMReg, unsigned RegOpcodeField); + void emitRegModRMByte(unsigned RegOpcodeField); + void emitSIBByte(unsigned SS, unsigned Index, unsigned Base); + void emitConstant(uint64_t Val, unsigned Size); + + void emitMemModRMByte(const MachineInstr &MI, + unsigned Op, unsigned RegOpcodeField, + intptr_t PCAdj = 0); + + unsigned getX86RegNum(unsigned RegNo) const; + }; + +template + char Emitter::ID = 0; +} // end anonymous namespace. + +/// createX86CodeEmitterPass - Return a pass that emits the collected X86 code +/// to the specified templated MachineCodeEmitter object. + +FunctionPass *llvm::createX86CodeEmitterPass(X86TargetMachine &TM, + MachineCodeEmitter &MCE) { + return new Emitter(TM, MCE); +} +FunctionPass *llvm::createX86JITCodeEmitterPass(X86TargetMachine &TM, + JITCodeEmitter &JCE) { + return new Emitter(TM, JCE); +} +FunctionPass *llvm::createX86ObjectCodeEmitterPass(X86TargetMachine &TM, + ObjectCodeEmitter &OCE) { + return new Emitter(TM, OCE); +} + +template +bool Emitter::runOnMachineFunction(MachineFunction &MF) { + + MCE.setModuleInfo(&getAnalysis()); + + II = TM.getInstrInfo(); + TD = TM.getTargetData(); + Is64BitMode = TM.getSubtarget().is64Bit(); + IsPIC = TM.getRelocationModel() == Reloc::PIC_; + + do { + DEBUG(errs() << "JITTing function '" + << MF.getFunction()->getName() << "'\n"); + MCE.startFunction(MF); + for (MachineFunction::iterator MBB = MF.begin(), E = MF.end(); + MBB != E; ++MBB) { + MCE.StartMachineBasicBlock(MBB); + for (MachineBasicBlock::const_iterator I = MBB->begin(), E = MBB->end(); + I != E; ++I) { + const TargetInstrDesc &Desc = I->getDesc(); + emitInstruction(*I, &Desc); + // MOVPC32r is basically a call plus a pop instruction. + if (Desc.getOpcode() == X86::MOVPC32r) + emitInstruction(*I, &II->get(X86::POP32r)); + NumEmitted++; // Keep track of the # of mi's emitted + } + } + } while (MCE.finishFunction(MF)); + + return false; +} + +/// emitPCRelativeBlockAddress - This method keeps track of the information +/// necessary to resolve the address of this block later and emits a dummy +/// value. +/// +template +void Emitter::emitPCRelativeBlockAddress(MachineBasicBlock *MBB) { + // Remember where this reference was and where it is to so we can + // deal with it later. + MCE.addRelocation(MachineRelocation::getBB(MCE.getCurrentPCOffset(), + X86::reloc_pcrel_word, MBB)); + MCE.emitWordLE(0); +} + +/// emitGlobalAddress - Emit the specified address to the code stream assuming +/// this is part of a "take the address of a global" instruction. +/// +template +void Emitter::emitGlobalAddress(GlobalValue *GV, unsigned Reloc, + intptr_t Disp /* = 0 */, + intptr_t PCAdj /* = 0 */, + bool Indirect /* = false */) { + intptr_t RelocCST = Disp; + if (Reloc == X86::reloc_picrel_word) + RelocCST = PICBaseOffset; + else if (Reloc == X86::reloc_pcrel_word) + RelocCST = PCAdj; + MachineRelocation MR = Indirect + ? MachineRelocation::getIndirectSymbol(MCE.getCurrentPCOffset(), Reloc, + GV, RelocCST, false) + : MachineRelocation::getGV(MCE.getCurrentPCOffset(), Reloc, + GV, RelocCST, false); + MCE.addRelocation(MR); + // The relocated value will be added to the displacement + if (Reloc == X86::reloc_absolute_dword) + MCE.emitDWordLE(Disp); + else + MCE.emitWordLE((int32_t)Disp); +} + +/// emitExternalSymbolAddress - Arrange for the address of an external symbol to +/// be emitted to the current location in the function, and allow it to be PC +/// relative. +template +void Emitter::emitExternalSymbolAddress(const char *ES, + unsigned Reloc) { + intptr_t RelocCST = (Reloc == X86::reloc_picrel_word) ? PICBaseOffset : 0; + MCE.addRelocation(MachineRelocation::getExtSym(MCE.getCurrentPCOffset(), + Reloc, ES, RelocCST)); + if (Reloc == X86::reloc_absolute_dword) + MCE.emitDWordLE(0); + else + MCE.emitWordLE(0); +} + +/// emitConstPoolAddress - Arrange for the address of an constant pool +/// to be emitted to the current location in the function, and allow it to be PC +/// relative. +template +void Emitter::emitConstPoolAddress(unsigned CPI, unsigned Reloc, + intptr_t Disp /* = 0 */, + intptr_t PCAdj /* = 0 */) { + intptr_t RelocCST = 0; + if (Reloc == X86::reloc_picrel_word) + RelocCST = PICBaseOffset; + else if (Reloc == X86::reloc_pcrel_word) + RelocCST = PCAdj; + MCE.addRelocation(MachineRelocation::getConstPool(MCE.getCurrentPCOffset(), + Reloc, CPI, RelocCST)); + // The relocated value will be added to the displacement + if (Reloc == X86::reloc_absolute_dword) + MCE.emitDWordLE(Disp); + else + MCE.emitWordLE((int32_t)Disp); +} + +/// emitJumpTableAddress - Arrange for the address of a jump table to +/// be emitted to the current location in the function, and allow it to be PC +/// relative. +template +void Emitter::emitJumpTableAddress(unsigned JTI, unsigned Reloc, + intptr_t PCAdj /* = 0 */) { + intptr_t RelocCST = 0; + if (Reloc == X86::reloc_picrel_word) + RelocCST = PICBaseOffset; + else if (Reloc == X86::reloc_pcrel_word) + RelocCST = PCAdj; + MCE.addRelocation(MachineRelocation::getJumpTable(MCE.getCurrentPCOffset(), + Reloc, JTI, RelocCST)); + // The relocated value will be added to the displacement + if (Reloc == X86::reloc_absolute_dword) + MCE.emitDWordLE(0); + else + MCE.emitWordLE(0); +} + +template +unsigned Emitter::getX86RegNum(unsigned RegNo) const { + return II->getRegisterInfo().getX86RegNum(RegNo); +} + +inline static unsigned char ModRMByte(unsigned Mod, unsigned RegOpcode, + unsigned RM) { + assert(Mod < 4 && RegOpcode < 8 && RM < 8 && "ModRM Fields out of range!"); + return RM | (RegOpcode << 3) | (Mod << 6); +} + +template +void Emitter::emitRegModRMByte(unsigned ModRMReg, + unsigned RegOpcodeFld){ + MCE.emitByte(ModRMByte(3, RegOpcodeFld, getX86RegNum(ModRMReg))); +} + +template +void Emitter::emitRegModRMByte(unsigned RegOpcodeFld) { + MCE.emitByte(ModRMByte(3, RegOpcodeFld, 0)); +} + +template +void Emitter::emitSIBByte(unsigned SS, + unsigned Index, + unsigned Base) { + // SIB byte is in the same format as the ModRMByte... + MCE.emitByte(ModRMByte(SS, Index, Base)); +} + +template +void Emitter::emitConstant(uint64_t Val, unsigned Size) { + // Output the constant in little endian byte order... + for (unsigned i = 0; i != Size; ++i) { + MCE.emitByte(Val & 255); + Val >>= 8; + } +} + +/// isDisp8 - Return true if this signed displacement fits in a 8-bit +/// sign-extended field. +static bool isDisp8(int Value) { + return Value == (signed char)Value; +} + +static bool gvNeedsNonLazyPtr(const MachineOperand &GVOp, + const TargetMachine &TM) { + // For Darwin-64, simulate the linktime GOT by using the same non-lazy-pointer + // mechanism as 32-bit mode. + if (TM.getSubtarget().is64Bit() && + !TM.getSubtarget().isTargetDarwin()) + return false; + + // Return true if this is a reference to a stub containing the address of the + // global, not the global itself. + return isGlobalStubReference(GVOp.getTargetFlags()); +} + +template +void Emitter::emitDisplacementField(const MachineOperand *RelocOp, + int DispVal, + intptr_t Adj /* = 0 */, + bool IsPCRel /* = true */) { + // If this is a simple integer displacement that doesn't require a relocation, + // emit it now. + if (!RelocOp) { + emitConstant(DispVal, 4); + return; + } + + // Otherwise, this is something that requires a relocation. Emit it as such + // now. + unsigned RelocType = Is64BitMode ? + (IsPCRel ? X86::reloc_pcrel_word : X86::reloc_absolute_word_sext) + : (IsPIC ? X86::reloc_picrel_word : X86::reloc_absolute_word); + if (RelocOp->isGlobal()) { + // In 64-bit static small code model, we could potentially emit absolute. + // But it's probably not beneficial. If the MCE supports using RIP directly + // do it, otherwise fallback to absolute (this is determined by IsPCRel). + // 89 05 00 00 00 00 mov %eax,0(%rip) # PC-relative + // 89 04 25 00 00 00 00 mov %eax,0x0 # Absolute + bool Indirect = gvNeedsNonLazyPtr(*RelocOp, TM); + emitGlobalAddress(RelocOp->getGlobal(), RelocType, RelocOp->getOffset(), + Adj, Indirect); + } else if (RelocOp->isSymbol()) { + emitExternalSymbolAddress(RelocOp->getSymbolName(), RelocType); + } else if (RelocOp->isCPI()) { + emitConstPoolAddress(RelocOp->getIndex(), RelocType, + RelocOp->getOffset(), Adj); + } else { + assert(RelocOp->isJTI() && "Unexpected machine operand!"); + emitJumpTableAddress(RelocOp->getIndex(), RelocType, Adj); + } +} + +template +void Emitter::emitMemModRMByte(const MachineInstr &MI, + unsigned Op,unsigned RegOpcodeField, + intptr_t PCAdj) { + const MachineOperand &Op3 = MI.getOperand(Op+3); + int DispVal = 0; + const MachineOperand *DispForReloc = 0; + + // Figure out what sort of displacement we have to handle here. + if (Op3.isGlobal()) { + DispForReloc = &Op3; + } else if (Op3.isSymbol()) { + DispForReloc = &Op3; + } else if (Op3.isCPI()) { + if (!MCE.earlyResolveAddresses() || Is64BitMode || IsPIC) { + DispForReloc = &Op3; + } else { + DispVal += MCE.getConstantPoolEntryAddress(Op3.getIndex()); + DispVal += Op3.getOffset(); + } + } else if (Op3.isJTI()) { + if (!MCE.earlyResolveAddresses() || Is64BitMode || IsPIC) { + DispForReloc = &Op3; + } else { + DispVal += MCE.getJumpTableEntryAddress(Op3.getIndex()); + } + } else { + DispVal = Op3.getImm(); + } + + const MachineOperand &Base = MI.getOperand(Op); + const MachineOperand &Scale = MI.getOperand(Op+1); + const MachineOperand &IndexReg = MI.getOperand(Op+2); + + unsigned BaseReg = Base.getReg(); + + // Indicate that the displacement will use an pcrel or absolute reference + // by default. MCEs able to resolve addresses on-the-fly use pcrel by default + // while others, unless explicit asked to use RIP, use absolute references. + bool IsPCRel = MCE.earlyResolveAddresses() ? true : false; + + // Is a SIB byte needed? + // If no BaseReg, issue a RIP relative instruction only if the MCE can + // resolve addresses on-the-fly, otherwise use SIB (Intel Manual 2A, table + // 2-7) and absolute references. + if ((!Is64BitMode || DispForReloc || BaseReg != 0) && + IndexReg.getReg() == 0 && + ((BaseReg == 0 && MCE.earlyResolveAddresses()) || BaseReg == X86::RIP || + (BaseReg != 0 && getX86RegNum(BaseReg) != N86::ESP))) { + if (BaseReg == 0 || BaseReg == X86::RIP) { // Just a displacement? + // Emit special case [disp32] encoding + MCE.emitByte(ModRMByte(0, RegOpcodeField, 5)); + emitDisplacementField(DispForReloc, DispVal, PCAdj, true); + } else { + unsigned BaseRegNo = getX86RegNum(BaseReg); + if (!DispForReloc && DispVal == 0 && BaseRegNo != N86::EBP) { + // Emit simple indirect register encoding... [EAX] f.e. + MCE.emitByte(ModRMByte(0, RegOpcodeField, BaseRegNo)); + } else if (!DispForReloc && isDisp8(DispVal)) { + // Emit the disp8 encoding... [REG+disp8] + MCE.emitByte(ModRMByte(1, RegOpcodeField, BaseRegNo)); + emitConstant(DispVal, 1); + } else { + // Emit the most general non-SIB encoding: [REG+disp32] + MCE.emitByte(ModRMByte(2, RegOpcodeField, BaseRegNo)); + emitDisplacementField(DispForReloc, DispVal, PCAdj, IsPCRel); + } + } + + } else { // We need a SIB byte, so start by outputting the ModR/M byte first + assert(IndexReg.getReg() != X86::ESP && + IndexReg.getReg() != X86::RSP && "Cannot use ESP as index reg!"); + + bool ForceDisp32 = false; + bool ForceDisp8 = false; + if (BaseReg == 0) { + // If there is no base register, we emit the special case SIB byte with + // MOD=0, BASE=5, to JUST get the index, scale, and displacement. + MCE.emitByte(ModRMByte(0, RegOpcodeField, 4)); + ForceDisp32 = true; + } else if (DispForReloc) { + // Emit the normal disp32 encoding. + MCE.emitByte(ModRMByte(2, RegOpcodeField, 4)); + ForceDisp32 = true; + } else if (DispVal == 0 && getX86RegNum(BaseReg) != N86::EBP) { + // Emit no displacement ModR/M byte + MCE.emitByte(ModRMByte(0, RegOpcodeField, 4)); + } else if (isDisp8(DispVal)) { + // Emit the disp8 encoding... + MCE.emitByte(ModRMByte(1, RegOpcodeField, 4)); + ForceDisp8 = true; // Make sure to force 8 bit disp if Base=EBP + } else { + // Emit the normal disp32 encoding... + MCE.emitByte(ModRMByte(2, RegOpcodeField, 4)); + } + + // Calculate what the SS field value should be... + static const unsigned SSTable[] = { ~0, 0, 1, ~0, 2, ~0, ~0, ~0, 3 }; + unsigned SS = SSTable[Scale.getImm()]; + + if (BaseReg == 0) { + // Handle the SIB byte for the case where there is no base, see Intel + // Manual 2A, table 2-7. The displacement has already been output. + unsigned IndexRegNo; + if (IndexReg.getReg()) + IndexRegNo = getX86RegNum(IndexReg.getReg()); + else // Examples: [ESP+1*+4] or [scaled idx]+disp32 (MOD=0,BASE=5) + IndexRegNo = 4; + emitSIBByte(SS, IndexRegNo, 5); + } else { + unsigned BaseRegNo = getX86RegNum(BaseReg); + unsigned IndexRegNo; + if (IndexReg.getReg()) + IndexRegNo = getX86RegNum(IndexReg.getReg()); + else + IndexRegNo = 4; // For example [ESP+1*+4] + emitSIBByte(SS, IndexRegNo, BaseRegNo); + } + + // Do we need to output a displacement? + if (ForceDisp8) { + emitConstant(DispVal, 1); + } else if (DispVal != 0 || ForceDisp32) { + emitDisplacementField(DispForReloc, DispVal, PCAdj, IsPCRel); + } + } +} + +template +void Emitter::emitInstruction(const MachineInstr &MI, + const TargetInstrDesc *Desc) { + DEBUG(errs() << MI); + + MCE.processDebugLoc(MI.getDebugLoc(), true); + + unsigned Opcode = Desc->Opcode; + + // Emit the lock opcode prefix as needed. + if (Desc->TSFlags & X86II::LOCK) + MCE.emitByte(0xF0); + + // Emit segment override opcode prefix as needed. + switch (Desc->TSFlags & X86II::SegOvrMask) { + case X86II::FS: + MCE.emitByte(0x64); + break; + case X86II::GS: + MCE.emitByte(0x65); + break; + default: llvm_unreachable("Invalid segment!"); + case 0: break; // No segment override! + } + + // Emit the repeat opcode prefix as needed. + if ((Desc->TSFlags & X86II::Op0Mask) == X86II::REP) + MCE.emitByte(0xF3); + + // Emit the operand size opcode prefix as needed. + if (Desc->TSFlags & X86II::OpSize) + MCE.emitByte(0x66); + + // Emit the address size opcode prefix as needed. + if (Desc->TSFlags & X86II::AdSize) + MCE.emitByte(0x67); + + bool Need0FPrefix = false; + switch (Desc->TSFlags & X86II::Op0Mask) { + case X86II::TB: // Two-byte opcode prefix + case X86II::T8: // 0F 38 + case X86II::TA: // 0F 3A + Need0FPrefix = true; + break; + case X86II::TF: // F2 0F 38 + MCE.emitByte(0xF2); + Need0FPrefix = true; + break; + case X86II::REP: break; // already handled. + case X86II::XS: // F3 0F + MCE.emitByte(0xF3); + Need0FPrefix = true; + break; + case X86II::XD: // F2 0F + MCE.emitByte(0xF2); + Need0FPrefix = true; + break; + case X86II::D8: case X86II::D9: case X86II::DA: case X86II::DB: + case X86II::DC: case X86II::DD: case X86II::DE: case X86II::DF: + MCE.emitByte(0xD8+ + (((Desc->TSFlags & X86II::Op0Mask)-X86II::D8) + >> X86II::Op0Shift)); + break; // Two-byte opcode prefix + default: llvm_unreachable("Invalid prefix!"); + case 0: break; // No prefix! + } + + // Handle REX prefix. + if (Is64BitMode) { + if (unsigned REX = X86InstrInfo::determineREX(MI)) + MCE.emitByte(0x40 | REX); + } + + // 0x0F escape code must be emitted just before the opcode. + if (Need0FPrefix) + MCE.emitByte(0x0F); + + switch (Desc->TSFlags & X86II::Op0Mask) { + case X86II::TF: // F2 0F 38 + case X86II::T8: // 0F 38 + MCE.emitByte(0x38); + break; + case X86II::TA: // 0F 3A + MCE.emitByte(0x3A); + break; + } + + // If this is a two-address instruction, skip one of the register operands. + unsigned NumOps = Desc->getNumOperands(); + unsigned CurOp = 0; + if (NumOps > 1 && Desc->getOperandConstraint(1, TOI::TIED_TO) != -1) + ++CurOp; + else if (NumOps > 2 && Desc->getOperandConstraint(NumOps-1, TOI::TIED_TO)== 0) + // Skip the last source operand that is tied_to the dest reg. e.g. LXADD32 + --NumOps; + + unsigned char BaseOpcode = II->getBaseOpcodeFor(Desc); + switch (Desc->TSFlags & X86II::FormMask) { + default: + llvm_unreachable("Unknown FormMask value in X86 MachineCodeEmitter!"); + case X86II::Pseudo: + // Remember the current PC offset, this is the PIC relocation + // base address. + switch (Opcode) { + default: + llvm_unreachable("psuedo instructions should be removed before code" + " emission"); + break; + case TargetInstrInfo::INLINEASM: + // We allow inline assembler nodes with empty bodies - they can + // implicitly define registers, which is ok for JIT. + if (MI.getOperand(0).getSymbolName()[0]) + llvm_report_error("JIT does not support inline asm!"); + break; + case TargetInstrInfo::DBG_LABEL: + case TargetInstrInfo::EH_LABEL: + case TargetInstrInfo::GC_LABEL: + MCE.emitLabel(MI.getOperand(0).getImm()); + break; + case TargetInstrInfo::IMPLICIT_DEF: + case TargetInstrInfo::KILL: + case X86::FP_REG_KILL: + break; + case X86::MOVPC32r: { + // This emits the "call" portion of this pseudo instruction. + MCE.emitByte(BaseOpcode); + emitConstant(0, X86InstrInfo::sizeOfImm(Desc)); + // Remember PIC base. + PICBaseOffset = (intptr_t) MCE.getCurrentPCOffset(); + X86JITInfo *JTI = TM.getJITInfo(); + JTI->setPICBase(MCE.getCurrentPCValue()); + break; + } + } + CurOp = NumOps; + break; + case X86II::RawFrm: { + MCE.emitByte(BaseOpcode); + + if (CurOp == NumOps) + break; + + const MachineOperand &MO = MI.getOperand(CurOp++); + + DEBUG(errs() << "RawFrm CurOp " << CurOp << "\n"); + DEBUG(errs() << "isMBB " << MO.isMBB() << "\n"); + DEBUG(errs() << "isGlobal " << MO.isGlobal() << "\n"); + DEBUG(errs() << "isSymbol " << MO.isSymbol() << "\n"); + DEBUG(errs() << "isImm " << MO.isImm() << "\n"); + + if (MO.isMBB()) { + emitPCRelativeBlockAddress(MO.getMBB()); + break; + } + + if (MO.isGlobal()) { + emitGlobalAddress(MO.getGlobal(), X86::reloc_pcrel_word, + MO.getOffset(), 0); + break; + } + + if (MO.isSymbol()) { + emitExternalSymbolAddress(MO.getSymbolName(), X86::reloc_pcrel_word); + break; + } + + assert(MO.isImm() && "Unknown RawFrm operand!"); + if (Opcode == X86::CALLpcrel32 || Opcode == X86::CALL64pcrel32) { + // Fix up immediate operand for pc relative calls. + intptr_t Imm = (intptr_t)MO.getImm(); + Imm = Imm - MCE.getCurrentPCValue() - 4; + emitConstant(Imm, X86InstrInfo::sizeOfImm(Desc)); + } else + emitConstant(MO.getImm(), X86InstrInfo::sizeOfImm(Desc)); + break; + } + + case X86II::AddRegFrm: { + MCE.emitByte(BaseOpcode + getX86RegNum(MI.getOperand(CurOp++).getReg())); + + if (CurOp == NumOps) + break; + + const MachineOperand &MO1 = MI.getOperand(CurOp++); + unsigned Size = X86InstrInfo::sizeOfImm(Desc); + if (MO1.isImm()) { + emitConstant(MO1.getImm(), Size); + break; + } + + unsigned rt = Is64BitMode ? X86::reloc_pcrel_word + : (IsPIC ? X86::reloc_picrel_word : X86::reloc_absolute_word); + if (Opcode == X86::MOV64ri64i32) + rt = X86::reloc_absolute_word; // FIXME: add X86II flag? + // This should not occur on Darwin for relocatable objects. + if (Opcode == X86::MOV64ri) + rt = X86::reloc_absolute_dword; // FIXME: add X86II flag? + if (MO1.isGlobal()) { + bool Indirect = gvNeedsNonLazyPtr(MO1, TM); + emitGlobalAddress(MO1.getGlobal(), rt, MO1.getOffset(), 0, + Indirect); + } else if (MO1.isSymbol()) + emitExternalSymbolAddress(MO1.getSymbolName(), rt); + else if (MO1.isCPI()) + emitConstPoolAddress(MO1.getIndex(), rt); + else if (MO1.isJTI()) + emitJumpTableAddress(MO1.getIndex(), rt); + break; + } + + case X86II::MRMDestReg: { + MCE.emitByte(BaseOpcode); + emitRegModRMByte(MI.getOperand(CurOp).getReg(), + getX86RegNum(MI.getOperand(CurOp+1).getReg())); + CurOp += 2; + if (CurOp != NumOps) + emitConstant(MI.getOperand(CurOp++).getImm(), + X86InstrInfo::sizeOfImm(Desc)); + break; + } + case X86II::MRMDestMem: { + MCE.emitByte(BaseOpcode); + emitMemModRMByte(MI, CurOp, + getX86RegNum(MI.getOperand(CurOp + X86AddrNumOperands) + .getReg())); + CurOp += X86AddrNumOperands + 1; + if (CurOp != NumOps) + emitConstant(MI.getOperand(CurOp++).getImm(), + X86InstrInfo::sizeOfImm(Desc)); + break; + } + + case X86II::MRMSrcReg: + MCE.emitByte(BaseOpcode); + emitRegModRMByte(MI.getOperand(CurOp+1).getReg(), + getX86RegNum(MI.getOperand(CurOp).getReg())); + CurOp += 2; + if (CurOp != NumOps) + emitConstant(MI.getOperand(CurOp++).getImm(), + X86InstrInfo::sizeOfImm(Desc)); + break; + + case X86II::MRMSrcMem: { + // FIXME: Maybe lea should have its own form? + int AddrOperands; + if (Opcode == X86::LEA64r || Opcode == X86::LEA64_32r || + Opcode == X86::LEA16r || Opcode == X86::LEA32r) + AddrOperands = X86AddrNumOperands - 1; // No segment register + else + AddrOperands = X86AddrNumOperands; + + intptr_t PCAdj = (CurOp + AddrOperands + 1 != NumOps) ? + X86InstrInfo::sizeOfImm(Desc) : 0; + + MCE.emitByte(BaseOpcode); + emitMemModRMByte(MI, CurOp+1, getX86RegNum(MI.getOperand(CurOp).getReg()), + PCAdj); + CurOp += AddrOperands + 1; + if (CurOp != NumOps) + emitConstant(MI.getOperand(CurOp++).getImm(), + X86InstrInfo::sizeOfImm(Desc)); + break; + } + + case X86II::MRM0r: case X86II::MRM1r: + case X86II::MRM2r: case X86II::MRM3r: + case X86II::MRM4r: case X86II::MRM5r: + case X86II::MRM6r: case X86II::MRM7r: { + MCE.emitByte(BaseOpcode); + + // Special handling of lfence, mfence, monitor, and mwait. + if (Desc->getOpcode() == X86::LFENCE || + Desc->getOpcode() == X86::MFENCE || + Desc->getOpcode() == X86::MONITOR || + Desc->getOpcode() == X86::MWAIT) { + emitRegModRMByte((Desc->TSFlags & X86II::FormMask)-X86II::MRM0r); + + switch (Desc->getOpcode()) { + default: break; + case X86::MONITOR: + MCE.emitByte(0xC8); + break; + case X86::MWAIT: + MCE.emitByte(0xC9); + break; + } + } else { + emitRegModRMByte(MI.getOperand(CurOp++).getReg(), + (Desc->TSFlags & X86II::FormMask)-X86II::MRM0r); + } + + if (CurOp == NumOps) + break; + + const MachineOperand &MO1 = MI.getOperand(CurOp++); + unsigned Size = X86InstrInfo::sizeOfImm(Desc); + if (MO1.isImm()) { + emitConstant(MO1.getImm(), Size); + break; + } + + unsigned rt = Is64BitMode ? X86::reloc_pcrel_word + : (IsPIC ? X86::reloc_picrel_word : X86::reloc_absolute_word); + if (Opcode == X86::MOV64ri32) + rt = X86::reloc_absolute_word_sext; // FIXME: add X86II flag? + if (MO1.isGlobal()) { + bool Indirect = gvNeedsNonLazyPtr(MO1, TM); + emitGlobalAddress(MO1.getGlobal(), rt, MO1.getOffset(), 0, + Indirect); + } else if (MO1.isSymbol()) + emitExternalSymbolAddress(MO1.getSymbolName(), rt); + else if (MO1.isCPI()) + emitConstPoolAddress(MO1.getIndex(), rt); + else if (MO1.isJTI()) + emitJumpTableAddress(MO1.getIndex(), rt); + break; + } + + case X86II::MRM0m: case X86II::MRM1m: + case X86II::MRM2m: case X86II::MRM3m: + case X86II::MRM4m: case X86II::MRM5m: + case X86II::MRM6m: case X86II::MRM7m: { + intptr_t PCAdj = (CurOp + X86AddrNumOperands != NumOps) ? + (MI.getOperand(CurOp+X86AddrNumOperands).isImm() ? + X86InstrInfo::sizeOfImm(Desc) : 4) : 0; + + MCE.emitByte(BaseOpcode); + emitMemModRMByte(MI, CurOp, (Desc->TSFlags & X86II::FormMask)-X86II::MRM0m, + PCAdj); + CurOp += X86AddrNumOperands; + + if (CurOp == NumOps) + break; + + const MachineOperand &MO = MI.getOperand(CurOp++); + unsigned Size = X86InstrInfo::sizeOfImm(Desc); + if (MO.isImm()) { + emitConstant(MO.getImm(), Size); + break; + } + + unsigned rt = Is64BitMode ? X86::reloc_pcrel_word + : (IsPIC ? X86::reloc_picrel_word : X86::reloc_absolute_word); + if (Opcode == X86::MOV64mi32) + rt = X86::reloc_absolute_word_sext; // FIXME: add X86II flag? + if (MO.isGlobal()) { + bool Indirect = gvNeedsNonLazyPtr(MO, TM); + emitGlobalAddress(MO.getGlobal(), rt, MO.getOffset(), 0, + Indirect); + } else if (MO.isSymbol()) + emitExternalSymbolAddress(MO.getSymbolName(), rt); + else if (MO.isCPI()) + emitConstPoolAddress(MO.getIndex(), rt); + else if (MO.isJTI()) + emitJumpTableAddress(MO.getIndex(), rt); + break; + } + + case X86II::MRMInitReg: + MCE.emitByte(BaseOpcode); + // Duplicate register, used by things like MOV8r0 (aka xor reg,reg). + emitRegModRMByte(MI.getOperand(CurOp).getReg(), + getX86RegNum(MI.getOperand(CurOp).getReg())); + ++CurOp; + break; + } + + if (!Desc->isVariadic() && CurOp != NumOps) { +#ifndef NDEBUG + errs() << "Cannot encode all operands of: " << MI << "\n"; +#endif + llvm_unreachable(0); + } + + MCE.processDebugLoc(MI.getDebugLoc(), false); +} + +// Adapt the Emitter / CodeEmitter interfaces to MCCodeEmitter. +// +// FIXME: This is a total hack designed to allow work on llvm-mc to proceed +// without being blocked on various cleanups needed to support a clean interface +// to instruction encoding. +// +// Look away! + +#include "llvm/DerivedTypes.h" + +namespace { +class MCSingleInstructionCodeEmitter : public MachineCodeEmitter { + uint8_t Data[256]; + +public: + MCSingleInstructionCodeEmitter() { reset(); } + + void reset() { + BufferBegin = Data; + BufferEnd = array_endof(Data); + CurBufferPtr = Data; + } + + StringRef str() { + return StringRef(reinterpret_cast(BufferBegin), + CurBufferPtr - BufferBegin); + } + + virtual void startFunction(MachineFunction &F) {} + virtual bool finishFunction(MachineFunction &F) { return false; } + virtual void emitLabel(uint64_t LabelID) {} + virtual void StartMachineBasicBlock(MachineBasicBlock *MBB) {} + virtual bool earlyResolveAddresses() const { return false; } + virtual void addRelocation(const MachineRelocation &MR) { } + virtual uintptr_t getConstantPoolEntryAddress(unsigned Index) const { + return 0; + } + virtual uintptr_t getJumpTableEntryAddress(unsigned Index) const { + return 0; + } + virtual uintptr_t getMachineBasicBlockAddress(MachineBasicBlock *MBB) const { + return 0; + } + virtual uintptr_t getLabelAddress(uint64_t LabelID) const { + return 0; + } + virtual void setModuleInfo(MachineModuleInfo* Info) {} +}; + +class X86MCCodeEmitter : public MCCodeEmitter { + X86MCCodeEmitter(const X86MCCodeEmitter &); // DO NOT IMPLEMENT + void operator=(const X86MCCodeEmitter &); // DO NOT IMPLEMENT + +private: + X86TargetMachine &TM; + llvm::Function *DummyF; + TargetData *DummyTD; + mutable llvm::MachineFunction *DummyMF; + llvm::MachineBasicBlock *DummyMBB; + + MCSingleInstructionCodeEmitter *InstrEmitter; + Emitter *Emit; + +public: + X86MCCodeEmitter(X86TargetMachine &_TM) : TM(_TM) { + // Verily, thou shouldst avert thine eyes. + const llvm::FunctionType *FTy = + FunctionType::get(llvm::Type::getVoidTy(getGlobalContext()), false); + DummyF = Function::Create(FTy, GlobalValue::InternalLinkage); + DummyTD = new TargetData(""); + DummyMF = new MachineFunction(DummyF, TM); + DummyMBB = DummyMF->CreateMachineBasicBlock(); + + InstrEmitter = new MCSingleInstructionCodeEmitter(); + Emit = new Emitter(TM, *InstrEmitter, + *TM.getInstrInfo(), + *DummyTD, false); + } + ~X86MCCodeEmitter() { + delete Emit; + delete InstrEmitter; + delete DummyMF; + delete DummyF; + } + + bool AddRegToInstr(const MCInst &MI, MachineInstr *Instr, + unsigned Start) const { + if (Start + 1 > MI.getNumOperands()) + return false; + + const MCOperand &Op = MI.getOperand(Start); + if (!Op.isReg()) return false; + + Instr->addOperand(MachineOperand::CreateReg(Op.getReg(), false)); + return true; + } + + bool AddImmToInstr(const MCInst &MI, MachineInstr *Instr, + unsigned Start) const { + if (Start + 1 > MI.getNumOperands()) + return false; + + const MCOperand &Op = MI.getOperand(Start); + if (Op.isImm()) { + Instr->addOperand(MachineOperand::CreateImm(Op.getImm())); + return true; + } + if (!Op.isExpr()) + return false; + + const MCExpr *Expr = Op.getExpr(); + if (const MCConstantExpr *CE = dyn_cast(Expr)) { + Instr->addOperand(MachineOperand::CreateImm(CE->getValue())); + return true; + } + + // FIXME: Relocation / fixup. + Instr->addOperand(MachineOperand::CreateImm(0)); + return true; + } + + bool AddLMemToInstr(const MCInst &MI, MachineInstr *Instr, + unsigned Start) const { + return (AddRegToInstr(MI, Instr, Start + 0) && + AddImmToInstr(MI, Instr, Start + 1) && + AddRegToInstr(MI, Instr, Start + 2) && + AddImmToInstr(MI, Instr, Start + 3)); + } + + bool AddMemToInstr(const MCInst &MI, MachineInstr *Instr, + unsigned Start) const { + return (AddRegToInstr(MI, Instr, Start + 0) && + AddImmToInstr(MI, Instr, Start + 1) && + AddRegToInstr(MI, Instr, Start + 2) && + AddImmToInstr(MI, Instr, Start + 3) && + AddRegToInstr(MI, Instr, Start + 4)); + } + + void EncodeInstruction(const MCInst &MI, raw_ostream &OS) const { + // Don't look yet! + + // Convert the MCInst to a MachineInstr so we can (ab)use the regular + // emitter. + const X86InstrInfo &II = *TM.getInstrInfo(); + const TargetInstrDesc &Desc = II.get(MI.getOpcode()); + MachineInstr *Instr = DummyMF->CreateMachineInstr(Desc, DebugLoc()); + DummyMBB->push_back(Instr); + + unsigned Opcode = MI.getOpcode(); + unsigned NumOps = MI.getNumOperands(); + unsigned CurOp = 0; + if (NumOps > 1 && Desc.getOperandConstraint(1, TOI::TIED_TO) != -1) { + Instr->addOperand(MachineOperand::CreateReg(0, false)); + ++CurOp; + } else if (NumOps > 2 && + Desc.getOperandConstraint(NumOps-1, TOI::TIED_TO)== 0) + // Skip the last source operand that is tied_to the dest reg. e.g. LXADD32 + --NumOps; + + bool OK = true; + switch (Desc.TSFlags & X86II::FormMask) { + case X86II::MRMDestReg: + case X86II::MRMSrcReg: + // Matching doesn't fill this in completely, we have to choose operand 0 + // for a tied register. + OK &= AddRegToInstr(MI, Instr, 0); CurOp++; + OK &= AddRegToInstr(MI, Instr, CurOp++); + if (CurOp < NumOps) + OK &= AddImmToInstr(MI, Instr, CurOp); + break; + + case X86II::RawFrm: + if (CurOp < NumOps) { + // Hack to make branches work. + if (!(Desc.TSFlags & X86II::ImmMask) && + MI.getOperand(0).isExpr() && + isa(MI.getOperand(0).getExpr())) + Instr->addOperand(MachineOperand::CreateMBB(DummyMBB)); + else + OK &= AddImmToInstr(MI, Instr, CurOp); + } + break; + + case X86II::AddRegFrm: + OK &= AddRegToInstr(MI, Instr, CurOp++); + if (CurOp < NumOps) + OK &= AddImmToInstr(MI, Instr, CurOp); + break; + + case X86II::MRM0r: case X86II::MRM1r: + case X86II::MRM2r: case X86II::MRM3r: + case X86II::MRM4r: case X86II::MRM5r: + case X86II::MRM6r: case X86II::MRM7r: + // Matching doesn't fill this in completely, we have to choose operand 0 + // for a tied register. + OK &= AddRegToInstr(MI, Instr, 0); CurOp++; + if (CurOp < NumOps) + OK &= AddImmToInstr(MI, Instr, CurOp); + break; + + case X86II::MRM0m: case X86II::MRM1m: + case X86II::MRM2m: case X86II::MRM3m: + case X86II::MRM4m: case X86II::MRM5m: + case X86II::MRM6m: case X86II::MRM7m: + OK &= AddMemToInstr(MI, Instr, CurOp); CurOp += 5; + if (CurOp < NumOps) + OK &= AddImmToInstr(MI, Instr, CurOp); + break; + + case X86II::MRMSrcMem: + OK &= AddRegToInstr(MI, Instr, CurOp++); + if (Opcode == X86::LEA64r || Opcode == X86::LEA64_32r || + Opcode == X86::LEA16r || Opcode == X86::LEA32r) + OK &= AddLMemToInstr(MI, Instr, CurOp); + else + OK &= AddMemToInstr(MI, Instr, CurOp); + break; + + case X86II::MRMDestMem: + OK &= AddMemToInstr(MI, Instr, CurOp); CurOp += 5; + OK &= AddRegToInstr(MI, Instr, CurOp); + break; + + default: + case X86II::MRMInitReg: + case X86II::Pseudo: + OK = false; + break; + } + + if (!OK) { + errs() << "couldn't convert inst '"; + MI.dump(); + errs() << "' to machine instr:\n"; + Instr->dump(); + } + + InstrEmitter->reset(); + if (OK) + Emit->emitInstruction(*Instr, &Desc); + OS << InstrEmitter->str(); + + Instr->eraseFromParent(); + } +}; +} + +// Ok, now you can look. +MCCodeEmitter *llvm::createX86MCCodeEmitter(const Target &, + TargetMachine &TM) { + return new X86MCCodeEmitter(static_cast(TM)); +} diff --git a/libclamav/c++/llvm/lib/Target/X86/X86CompilationCallback_Win64.asm b/libclamav/c++/llvm/lib/Target/X86/X86CompilationCallback_Win64.asm new file mode 100644 index 000000000..f321778db --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/X86/X86CompilationCallback_Win64.asm @@ -0,0 +1,68 @@ +;;===-- X86CompilationCallback_Win64.asm - Implement Win64 JIT callback ---=== +;; +;; The LLVM Compiler Infrastructure +;; +;; This file is distributed under the University of Illinois Open Source +;; License. See LICENSE.TXT for details. +;; +;;===----------------------------------------------------------------------=== +;; +;; This file implements the JIT interfaces for the X86 target. +;; +;;===----------------------------------------------------------------------=== + +extrn X86CompilationCallback2: PROC + +.code +X86CompilationCallback proc + push rbp + + ; Save RSP. + mov rbp, rsp + + ; Save all int arg registers + ; WARNING: We cannot use register spill area - we're generating stubs by hands! + push rcx + push rdx + push r8 + push r9 + + ; Align stack on 16-byte boundary. + and rsp, -16 + + ; Save all XMM arg registers. Also allocate reg spill area. + sub rsp, 96 + movaps [rsp +32], xmm0 + movaps [rsp+16+32], xmm1 + movaps [rsp+32+32], xmm2 + movaps [rsp+48+32], xmm3 + + ; JIT callee + + ; Pass prev frame and return address. + mov rcx, rbp + mov rdx, qword ptr [rbp+8] + call X86CompilationCallback2 + + ; Restore all XMM arg registers. + movaps xmm3, [rsp+48+32] + movaps xmm2, [rsp+32+32] + movaps xmm1, [rsp+16+32] + movaps xmm0, [rsp +32] + + ; Restore RSP. + mov rsp, rbp + + ; Restore all int arg registers + sub rsp, 32 + pop r9 + pop r8 + pop rdx + pop rcx + + ; Restore RBP. + pop rbp + ret +X86CompilationCallback endp + +End diff --git a/libclamav/c++/llvm/lib/Target/X86/X86ELFWriterInfo.cpp b/libclamav/c++/llvm/lib/Target/X86/X86ELFWriterInfo.cpp new file mode 100644 index 000000000..1597d2b31 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/X86/X86ELFWriterInfo.cpp @@ -0,0 +1,153 @@ +//===-- X86ELFWriterInfo.cpp - ELF Writer Info for the X86 backend --------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements ELF writer information for the X86 backend. +// +//===----------------------------------------------------------------------===// + +#include "X86ELFWriterInfo.h" +#include "X86Relocations.h" +#include "llvm/Function.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetMachine.h" + +using namespace llvm; + +//===----------------------------------------------------------------------===// +// Implementation of the X86ELFWriterInfo class +//===----------------------------------------------------------------------===// + +X86ELFWriterInfo::X86ELFWriterInfo(TargetMachine &TM) + : TargetELFWriterInfo(TM) { + bool is64Bit = TM.getTargetData()->getPointerSizeInBits() == 64; + EMachine = is64Bit ? EM_X86_64 : EM_386; + } + +X86ELFWriterInfo::~X86ELFWriterInfo() {} + +unsigned X86ELFWriterInfo::getRelocationType(unsigned MachineRelTy) const { + if (is64Bit) { + switch(MachineRelTy) { + case X86::reloc_pcrel_word: + return R_X86_64_PC32; + case X86::reloc_absolute_word: + return R_X86_64_32; + case X86::reloc_absolute_word_sext: + return R_X86_64_32S; + case X86::reloc_absolute_dword: + return R_X86_64_64; + case X86::reloc_picrel_word: + default: + llvm_unreachable("unknown x86_64 machine relocation type"); + } + } else { + switch(MachineRelTy) { + case X86::reloc_pcrel_word: + return R_386_PC32; + case X86::reloc_absolute_word: + return R_386_32; + case X86::reloc_absolute_word_sext: + case X86::reloc_absolute_dword: + case X86::reloc_picrel_word: + default: + llvm_unreachable("unknown x86 machine relocation type"); + } + } + return 0; +} + +long int X86ELFWriterInfo::getDefaultAddendForRelTy(unsigned RelTy, + long int Modifier) const { + if (is64Bit) { + switch(RelTy) { + case R_X86_64_PC32: return Modifier - 4; + case R_X86_64_32: + case R_X86_64_32S: + case R_X86_64_64: + return Modifier; + default: + llvm_unreachable("unknown x86_64 relocation type"); + } + } else { + switch(RelTy) { + case R_386_PC32: return Modifier - 4; + case R_386_32: return Modifier; + default: + llvm_unreachable("unknown x86 relocation type"); + } + } + return 0; +} + +unsigned X86ELFWriterInfo::getRelocationTySize(unsigned RelTy) const { + if (is64Bit) { + switch(RelTy) { + case R_X86_64_PC32: + case R_X86_64_32: + case R_X86_64_32S: + return 32; + case R_X86_64_64: + return 64; + default: + llvm_unreachable("unknown x86_64 relocation type"); + } + } else { + switch(RelTy) { + case R_386_PC32: + case R_386_32: + return 32; + default: + llvm_unreachable("unknown x86 relocation type"); + } + } + return 0; +} + +bool X86ELFWriterInfo::isPCRelativeRel(unsigned RelTy) const { + if (is64Bit) { + switch(RelTy) { + case R_X86_64_PC32: + return true; + case R_X86_64_32: + case R_X86_64_32S: + case R_X86_64_64: + return false; + default: + llvm_unreachable("unknown x86_64 relocation type"); + } + } else { + switch(RelTy) { + case R_386_PC32: + return true; + case R_386_32: + return false; + default: + llvm_unreachable("unknown x86 relocation type"); + } + } + return 0; +} + +unsigned X86ELFWriterInfo::getAbsoluteLabelMachineRelTy() const { + return is64Bit ? + X86::reloc_absolute_dword : X86::reloc_absolute_word; +} + +long int X86ELFWriterInfo::computeRelocation(unsigned SymOffset, + unsigned RelOffset, + unsigned RelTy) const { + + if (RelTy == R_X86_64_PC32 || RelTy == R_386_PC32) + return SymOffset - (RelOffset + 4); + else + assert("computeRelocation unknown for this relocation type"); + + return 0; +} diff --git a/libclamav/c++/llvm/lib/Target/X86/X86ELFWriterInfo.h b/libclamav/c++/llvm/lib/Target/X86/X86ELFWriterInfo.h new file mode 100644 index 000000000..342e6e627 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/X86/X86ELFWriterInfo.h @@ -0,0 +1,76 @@ +//===-- X86ELFWriterInfo.h - ELF Writer Info for X86 ------------*- 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 ELF writer information for the X86 backend. +// +//===----------------------------------------------------------------------===// + +#ifndef X86_ELF_WRITER_INFO_H +#define X86_ELF_WRITER_INFO_H + +#include "llvm/Target/TargetELFWriterInfo.h" + +namespace llvm { + + class X86ELFWriterInfo : public TargetELFWriterInfo { + + // ELF Relocation types for X86 + enum X86RelocationType { + R_386_NONE = 0, + R_386_32 = 1, + R_386_PC32 = 2 + }; + + // ELF Relocation types for X86_64 + enum X86_64RelocationType { + R_X86_64_NONE = 0, + R_X86_64_64 = 1, + R_X86_64_PC32 = 2, + R_X86_64_32 = 10, + R_X86_64_32S = 11, + R_X86_64_PC64 = 24 + }; + + public: + X86ELFWriterInfo(TargetMachine &TM); + virtual ~X86ELFWriterInfo(); + + /// getRelocationType - Returns the target specific ELF Relocation type. + /// 'MachineRelTy' contains the object code independent relocation type + virtual unsigned getRelocationType(unsigned MachineRelTy) const; + + /// hasRelocationAddend - True if the target uses an addend in the + /// ELF relocation entry. + virtual bool hasRelocationAddend() const { return is64Bit ? true : false; } + + /// getDefaultAddendForRelTy - Gets the default addend value for a + /// relocation entry based on the target ELF relocation type. + virtual long int getDefaultAddendForRelTy(unsigned RelTy, + long int Modifier = 0) const; + + /// getRelTySize - Returns the size of relocatable field in bits + virtual unsigned getRelocationTySize(unsigned RelTy) const; + + /// isPCRelativeRel - True if the relocation type is pc relative + virtual bool isPCRelativeRel(unsigned RelTy) const; + + /// getJumpTableRelocationTy - Returns the machine relocation type used + /// to reference a jumptable. + virtual unsigned getAbsoluteLabelMachineRelTy() const; + + /// computeRelocation - Some relocatable fields could be relocated + /// directly, avoiding the relocation symbol emission, compute the + /// final relocation value for this symbol. + virtual long int computeRelocation(unsigned SymOffset, unsigned RelOffset, + unsigned RelTy) const; + }; + +} // end llvm namespace + +#endif // X86_ELF_WRITER_INFO_H diff --git a/libclamav/c++/llvm/lib/Target/X86/X86FastISel.cpp b/libclamav/c++/llvm/lib/Target/X86/X86FastISel.cpp new file mode 100644 index 000000000..431c120f8 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/X86/X86FastISel.cpp @@ -0,0 +1,1702 @@ +//===-- X86FastISel.cpp - X86 FastISel implementation ---------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the X86-specific support for the FastISel class. Much +// of the target-specific code is generated by tablegen in the file +// X86GenFastISel.inc, which is #included here. +// +//===----------------------------------------------------------------------===// + +#include "X86.h" +#include "X86InstrBuilder.h" +#include "X86ISelLowering.h" +#include "X86RegisterInfo.h" +#include "X86Subtarget.h" +#include "X86TargetMachine.h" +#include "llvm/CallingConv.h" +#include "llvm/DerivedTypes.h" +#include "llvm/GlobalVariable.h" +#include "llvm/Instructions.h" +#include "llvm/IntrinsicInst.h" +#include "llvm/CodeGen/FastISel.h" +#include "llvm/CodeGen/MachineConstantPool.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/Support/CallSite.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/GetElementPtrTypeIterator.h" +#include "llvm/Target/TargetOptions.h" +using namespace llvm; + +namespace { + +class X86FastISel : public FastISel { + /// Subtarget - Keep a pointer to the X86Subtarget around so that we can + /// make the right decision when generating code for different targets. + const X86Subtarget *Subtarget; + + /// StackPtr - Register used as the stack pointer. + /// + unsigned StackPtr; + + /// X86ScalarSSEf32, X86ScalarSSEf64 - Select between SSE or x87 + /// floating point ops. + /// When SSE is available, use it for f32 operations. + /// When SSE2 is available, use it for f64 operations. + bool X86ScalarSSEf64; + bool X86ScalarSSEf32; + +public: + explicit X86FastISel(MachineFunction &mf, + MachineModuleInfo *mmi, + DwarfWriter *dw, + DenseMap &vm, + DenseMap &bm, + DenseMap &am +#ifndef NDEBUG + , SmallSet &cil +#endif + ) + : FastISel(mf, mmi, dw, vm, bm, am +#ifndef NDEBUG + , cil +#endif + ) { + Subtarget = &TM.getSubtarget(); + StackPtr = Subtarget->is64Bit() ? X86::RSP : X86::ESP; + X86ScalarSSEf64 = Subtarget->hasSSE2(); + X86ScalarSSEf32 = Subtarget->hasSSE1(); + } + + virtual bool TargetSelectInstruction(Instruction *I); + +#include "X86GenFastISel.inc" + +private: + bool X86FastEmitCompare(Value *LHS, Value *RHS, EVT VT); + + bool X86FastEmitLoad(EVT VT, const X86AddressMode &AM, unsigned &RR); + + bool X86FastEmitStore(EVT VT, Value *Val, + const X86AddressMode &AM); + bool X86FastEmitStore(EVT VT, unsigned Val, + const X86AddressMode &AM); + + bool X86FastEmitExtend(ISD::NodeType Opc, EVT DstVT, unsigned Src, EVT SrcVT, + unsigned &ResultReg); + + bool X86SelectAddress(Value *V, X86AddressMode &AM); + bool X86SelectCallAddress(Value *V, X86AddressMode &AM); + + bool X86SelectLoad(Instruction *I); + + bool X86SelectStore(Instruction *I); + + bool X86SelectCmp(Instruction *I); + + bool X86SelectZExt(Instruction *I); + + bool X86SelectBranch(Instruction *I); + + bool X86SelectShift(Instruction *I); + + bool X86SelectSelect(Instruction *I); + + bool X86SelectTrunc(Instruction *I); + + bool X86SelectFPExt(Instruction *I); + bool X86SelectFPTrunc(Instruction *I); + + bool X86SelectExtractValue(Instruction *I); + + bool X86VisitIntrinsicCall(IntrinsicInst &I); + bool X86SelectCall(Instruction *I); + + CCAssignFn *CCAssignFnForCall(CallingConv::ID CC, bool isTailCall = false); + + const X86InstrInfo *getInstrInfo() const { + return getTargetMachine()->getInstrInfo(); + } + const X86TargetMachine *getTargetMachine() const { + return static_cast(&TM); + } + + unsigned TargetMaterializeConstant(Constant *C); + + unsigned TargetMaterializeAlloca(AllocaInst *C); + + /// isScalarFPTypeInSSEReg - Return true if the specified scalar FP type is + /// computed in an SSE register, not on the X87 floating point stack. + bool isScalarFPTypeInSSEReg(EVT VT) const { + return (VT == MVT::f64 && X86ScalarSSEf64) || // f64 is when SSE2 + (VT == MVT::f32 && X86ScalarSSEf32); // f32 is when SSE1 + } + + bool isTypeLegal(const Type *Ty, EVT &VT, bool AllowI1 = false); +}; + +} // end anonymous namespace. + +bool X86FastISel::isTypeLegal(const Type *Ty, EVT &VT, bool AllowI1) { + VT = TLI.getValueType(Ty, /*HandleUnknown=*/true); + if (VT == MVT::Other || !VT.isSimple()) + // Unhandled type. Halt "fast" selection and bail. + return false; + + // For now, require SSE/SSE2 for performing floating-point operations, + // since x87 requires additional work. + if (VT == MVT::f64 && !X86ScalarSSEf64) + return false; + if (VT == MVT::f32 && !X86ScalarSSEf32) + return false; + // Similarly, no f80 support yet. + if (VT == MVT::f80) + return false; + // We only handle legal types. For example, on x86-32 the instruction + // selector contains all of the 64-bit instructions from x86-64, + // under the assumption that i64 won't be used if the target doesn't + // support it. + return (AllowI1 && VT == MVT::i1) || TLI.isTypeLegal(VT); +} + +#include "X86GenCallingConv.inc" + +/// CCAssignFnForCall - Selects the correct CCAssignFn for a given calling +/// convention. +CCAssignFn *X86FastISel::CCAssignFnForCall(CallingConv::ID CC, + bool isTaillCall) { + if (Subtarget->is64Bit()) { + if (Subtarget->isTargetWin64()) + return CC_X86_Win64_C; + else + return CC_X86_64_C; + } + + if (CC == CallingConv::X86_FastCall) + return CC_X86_32_FastCall; + else if (CC == CallingConv::Fast) + return CC_X86_32_FastCC; + else + return CC_X86_32_C; +} + +/// X86FastEmitLoad - Emit a machine instruction to load a value of type VT. +/// The address is either pre-computed, i.e. Ptr, or a GlobalAddress, i.e. GV. +/// Return true and the result register by reference if it is possible. +bool X86FastISel::X86FastEmitLoad(EVT VT, const X86AddressMode &AM, + unsigned &ResultReg) { + // Get opcode and regclass of the output for the given load instruction. + unsigned Opc = 0; + const TargetRegisterClass *RC = NULL; + switch (VT.getSimpleVT().SimpleTy) { + default: return false; + case MVT::i1: + case MVT::i8: + Opc = X86::MOV8rm; + RC = X86::GR8RegisterClass; + break; + case MVT::i16: + Opc = X86::MOV16rm; + RC = X86::GR16RegisterClass; + break; + case MVT::i32: + Opc = X86::MOV32rm; + RC = X86::GR32RegisterClass; + break; + case MVT::i64: + // Must be in x86-64 mode. + Opc = X86::MOV64rm; + RC = X86::GR64RegisterClass; + break; + case MVT::f32: + if (Subtarget->hasSSE1()) { + Opc = X86::MOVSSrm; + RC = X86::FR32RegisterClass; + } else { + Opc = X86::LD_Fp32m; + RC = X86::RFP32RegisterClass; + } + break; + case MVT::f64: + if (Subtarget->hasSSE2()) { + Opc = X86::MOVSDrm; + RC = X86::FR64RegisterClass; + } else { + Opc = X86::LD_Fp64m; + RC = X86::RFP64RegisterClass; + } + break; + case MVT::f80: + // No f80 support yet. + return false; + } + + ResultReg = createResultReg(RC); + addFullAddress(BuildMI(MBB, DL, TII.get(Opc), ResultReg), AM); + return true; +} + +/// X86FastEmitStore - Emit a machine instruction to store a value Val of +/// type VT. The address is either pre-computed, consisted of a base ptr, Ptr +/// and a displacement offset, or a GlobalAddress, +/// i.e. V. Return true if it is possible. +bool +X86FastISel::X86FastEmitStore(EVT VT, unsigned Val, + const X86AddressMode &AM) { + // Get opcode and regclass of the output for the given store instruction. + unsigned Opc = 0; + switch (VT.getSimpleVT().SimpleTy) { + case MVT::f80: // No f80 support yet. + default: return false; + case MVT::i1: { + // Mask out all but lowest bit. + unsigned AndResult = createResultReg(X86::GR8RegisterClass); + BuildMI(MBB, DL, + TII.get(X86::AND8ri), AndResult).addReg(Val).addImm(1); + Val = AndResult; + } + // FALLTHROUGH, handling i1 as i8. + case MVT::i8: Opc = X86::MOV8mr; break; + case MVT::i16: Opc = X86::MOV16mr; break; + case MVT::i32: Opc = X86::MOV32mr; break; + case MVT::i64: Opc = X86::MOV64mr; break; // Must be in x86-64 mode. + case MVT::f32: + Opc = Subtarget->hasSSE1() ? X86::MOVSSmr : X86::ST_Fp32m; + break; + case MVT::f64: + Opc = Subtarget->hasSSE2() ? X86::MOVSDmr : X86::ST_Fp64m; + break; + } + + addFullAddress(BuildMI(MBB, DL, TII.get(Opc)), AM).addReg(Val); + return true; +} + +bool X86FastISel::X86FastEmitStore(EVT VT, Value *Val, + const X86AddressMode &AM) { + // Handle 'null' like i32/i64 0. + if (isa(Val)) + Val = Constant::getNullValue(TD.getIntPtrType(Val->getContext())); + + // If this is a store of a simple constant, fold the constant into the store. + if (ConstantInt *CI = dyn_cast(Val)) { + unsigned Opc = 0; + bool Signed = true; + switch (VT.getSimpleVT().SimpleTy) { + default: break; + case MVT::i1: Signed = false; // FALLTHROUGH to handle as i8. + case MVT::i8: Opc = X86::MOV8mi; break; + case MVT::i16: Opc = X86::MOV16mi; break; + case MVT::i32: Opc = X86::MOV32mi; break; + case MVT::i64: + // Must be a 32-bit sign extended value. + if ((int)CI->getSExtValue() == CI->getSExtValue()) + Opc = X86::MOV64mi32; + break; + } + + if (Opc) { + addFullAddress(BuildMI(MBB, DL, TII.get(Opc)), AM) + .addImm(Signed ? CI->getSExtValue() : + CI->getZExtValue()); + return true; + } + } + + unsigned ValReg = getRegForValue(Val); + if (ValReg == 0) + return false; + + return X86FastEmitStore(VT, ValReg, AM); +} + +/// X86FastEmitExtend - Emit a machine instruction to extend a value Src of +/// type SrcVT to type DstVT using the specified extension opcode Opc (e.g. +/// ISD::SIGN_EXTEND). +bool X86FastISel::X86FastEmitExtend(ISD::NodeType Opc, EVT DstVT, + unsigned Src, EVT SrcVT, + unsigned &ResultReg) { + unsigned RR = FastEmit_r(SrcVT.getSimpleVT(), DstVT.getSimpleVT(), Opc, Src); + + if (RR != 0) { + ResultReg = RR; + return true; + } else + return false; +} + +/// X86SelectAddress - Attempt to fill in an address from the given value. +/// +bool X86FastISel::X86SelectAddress(Value *V, X86AddressMode &AM) { + User *U = NULL; + unsigned Opcode = Instruction::UserOp1; + if (Instruction *I = dyn_cast(V)) { + Opcode = I->getOpcode(); + U = I; + } else if (ConstantExpr *C = dyn_cast(V)) { + Opcode = C->getOpcode(); + U = C; + } + + switch (Opcode) { + default: break; + case Instruction::BitCast: + // Look past bitcasts. + return X86SelectAddress(U->getOperand(0), AM); + + case Instruction::IntToPtr: + // Look past no-op inttoptrs. + if (TLI.getValueType(U->getOperand(0)->getType()) == TLI.getPointerTy()) + return X86SelectAddress(U->getOperand(0), AM); + break; + + case Instruction::PtrToInt: + // Look past no-op ptrtoints. + if (TLI.getValueType(U->getType()) == TLI.getPointerTy()) + return X86SelectAddress(U->getOperand(0), AM); + break; + + case Instruction::Alloca: { + // Do static allocas. + const AllocaInst *A = cast(V); + DenseMap::iterator SI = StaticAllocaMap.find(A); + if (SI != StaticAllocaMap.end()) { + AM.BaseType = X86AddressMode::FrameIndexBase; + AM.Base.FrameIndex = SI->second; + return true; + } + break; + } + + case Instruction::Add: { + // Adds of constants are common and easy enough. + if (ConstantInt *CI = dyn_cast(U->getOperand(1))) { + uint64_t Disp = (int32_t)AM.Disp + (uint64_t)CI->getSExtValue(); + // They have to fit in the 32-bit signed displacement field though. + if (isInt32(Disp)) { + AM.Disp = (uint32_t)Disp; + return X86SelectAddress(U->getOperand(0), AM); + } + } + break; + } + + case Instruction::GetElementPtr: { + // Pattern-match simple GEPs. + uint64_t Disp = (int32_t)AM.Disp; + unsigned IndexReg = AM.IndexReg; + unsigned Scale = AM.Scale; + gep_type_iterator GTI = gep_type_begin(U); + // Iterate through the indices, folding what we can. Constants can be + // folded, and one dynamic index can be handled, if the scale is supported. + for (User::op_iterator i = U->op_begin() + 1, e = U->op_end(); + i != e; ++i, ++GTI) { + Value *Op = *i; + if (const StructType *STy = dyn_cast(*GTI)) { + const StructLayout *SL = TD.getStructLayout(STy); + unsigned Idx = cast(Op)->getZExtValue(); + Disp += SL->getElementOffset(Idx); + } else { + uint64_t S = TD.getTypeAllocSize(GTI.getIndexedType()); + if (ConstantInt *CI = dyn_cast(Op)) { + // Constant-offset addressing. + Disp += CI->getSExtValue() * S; + } else if (IndexReg == 0 && + (!AM.GV || !Subtarget->isPICStyleRIPRel()) && + (S == 1 || S == 2 || S == 4 || S == 8)) { + // Scaled-index addressing. + Scale = S; + IndexReg = getRegForGEPIndex(Op); + if (IndexReg == 0) + return false; + } else + // Unsupported. + goto unsupported_gep; + } + } + // Check for displacement overflow. + if (!isInt32(Disp)) + break; + // Ok, the GEP indices were covered by constant-offset and scaled-index + // addressing. Update the address state and move on to examining the base. + AM.IndexReg = IndexReg; + AM.Scale = Scale; + AM.Disp = (uint32_t)Disp; + return X86SelectAddress(U->getOperand(0), AM); + unsupported_gep: + // Ok, the GEP indices weren't all covered. + break; + } + } + + // Handle constant address. + if (GlobalValue *GV = dyn_cast(V)) { + // Can't handle alternate code models yet. + if (TM.getCodeModel() != CodeModel::Small) + return false; + + // RIP-relative addresses can't have additional register operands. + if (Subtarget->isPICStyleRIPRel() && + (AM.Base.Reg != 0 || AM.IndexReg != 0)) + return false; + + // Can't handle TLS yet. + if (GlobalVariable *GVar = dyn_cast(GV)) + if (GVar->isThreadLocal()) + return false; + + // Okay, we've committed to selecting this global. Set up the basic address. + AM.GV = GV; + + // Allow the subtarget to classify the global. + unsigned char GVFlags = Subtarget->ClassifyGlobalReference(GV, TM); + + // If this reference is relative to the pic base, set it now. + if (isGlobalRelativeToPICBase(GVFlags)) { + // FIXME: How do we know Base.Reg is free?? + AM.Base.Reg = getInstrInfo()->getGlobalBaseReg(&MF); + } + + // Unless the ABI requires an extra load, return a direct reference to + // the global. + if (!isGlobalStubReference(GVFlags)) { + if (Subtarget->isPICStyleRIPRel()) { + // Use rip-relative addressing if we can. Above we verified that the + // base and index registers are unused. + assert(AM.Base.Reg == 0 && AM.IndexReg == 0); + AM.Base.Reg = X86::RIP; + } + AM.GVOpFlags = GVFlags; + return true; + } + + // Ok, we need to do a load from a stub. If we've already loaded from this + // stub, reuse the loaded pointer, otherwise emit the load now. + DenseMap::iterator I = LocalValueMap.find(V); + unsigned LoadReg; + if (I != LocalValueMap.end() && I->second != 0) { + LoadReg = I->second; + } else { + // Issue load from stub. + unsigned Opc = 0; + const TargetRegisterClass *RC = NULL; + X86AddressMode StubAM; + StubAM.Base.Reg = AM.Base.Reg; + StubAM.GV = GV; + StubAM.GVOpFlags = GVFlags; + + if (TLI.getPointerTy() == MVT::i64) { + Opc = X86::MOV64rm; + RC = X86::GR64RegisterClass; + + if (Subtarget->isPICStyleRIPRel()) + StubAM.Base.Reg = X86::RIP; + } else { + Opc = X86::MOV32rm; + RC = X86::GR32RegisterClass; + } + + LoadReg = createResultReg(RC); + addFullAddress(BuildMI(MBB, DL, TII.get(Opc), LoadReg), StubAM); + + // Prevent loading GV stub multiple times in same MBB. + LocalValueMap[V] = LoadReg; + } + + // Now construct the final address. Note that the Disp, Scale, + // and Index values may already be set here. + AM.Base.Reg = LoadReg; + AM.GV = 0; + return true; + } + + // If all else fails, try to materialize the value in a register. + if (!AM.GV || !Subtarget->isPICStyleRIPRel()) { + if (AM.Base.Reg == 0) { + AM.Base.Reg = getRegForValue(V); + return AM.Base.Reg != 0; + } + if (AM.IndexReg == 0) { + assert(AM.Scale == 1 && "Scale with no index!"); + AM.IndexReg = getRegForValue(V); + return AM.IndexReg != 0; + } + } + + return false; +} + +/// X86SelectCallAddress - Attempt to fill in an address from the given value. +/// +bool X86FastISel::X86SelectCallAddress(Value *V, X86AddressMode &AM) { + User *U = NULL; + unsigned Opcode = Instruction::UserOp1; + if (Instruction *I = dyn_cast(V)) { + Opcode = I->getOpcode(); + U = I; + } else if (ConstantExpr *C = dyn_cast(V)) { + Opcode = C->getOpcode(); + U = C; + } + + switch (Opcode) { + default: break; + case Instruction::BitCast: + // Look past bitcasts. + return X86SelectCallAddress(U->getOperand(0), AM); + + case Instruction::IntToPtr: + // Look past no-op inttoptrs. + if (TLI.getValueType(U->getOperand(0)->getType()) == TLI.getPointerTy()) + return X86SelectCallAddress(U->getOperand(0), AM); + break; + + case Instruction::PtrToInt: + // Look past no-op ptrtoints. + if (TLI.getValueType(U->getType()) == TLI.getPointerTy()) + return X86SelectCallAddress(U->getOperand(0), AM); + break; + } + + // Handle constant address. + if (GlobalValue *GV = dyn_cast(V)) { + // Can't handle alternate code models yet. + if (TM.getCodeModel() != CodeModel::Small) + return false; + + // RIP-relative addresses can't have additional register operands. + if (Subtarget->isPICStyleRIPRel() && + (AM.Base.Reg != 0 || AM.IndexReg != 0)) + return false; + + // Can't handle TLS or DLLImport. + if (GlobalVariable *GVar = dyn_cast(GV)) + if (GVar->isThreadLocal() || GVar->hasDLLImportLinkage()) + return false; + + // Okay, we've committed to selecting this global. Set up the basic address. + AM.GV = GV; + + // No ABI requires an extra load for anything other than DLLImport, which + // we rejected above. Return a direct reference to the global. + if (Subtarget->isPICStyleRIPRel()) { + // Use rip-relative addressing if we can. Above we verified that the + // base and index registers are unused. + assert(AM.Base.Reg == 0 && AM.IndexReg == 0); + AM.Base.Reg = X86::RIP; + } else if (Subtarget->isPICStyleStubPIC()) { + AM.GVOpFlags = X86II::MO_PIC_BASE_OFFSET; + } else if (Subtarget->isPICStyleGOT()) { + AM.GVOpFlags = X86II::MO_GOTOFF; + } + + return true; + } + + // If all else fails, try to materialize the value in a register. + if (!AM.GV || !Subtarget->isPICStyleRIPRel()) { + if (AM.Base.Reg == 0) { + AM.Base.Reg = getRegForValue(V); + return AM.Base.Reg != 0; + } + if (AM.IndexReg == 0) { + assert(AM.Scale == 1 && "Scale with no index!"); + AM.IndexReg = getRegForValue(V); + return AM.IndexReg != 0; + } + } + + return false; +} + + +/// X86SelectStore - Select and emit code to implement store instructions. +bool X86FastISel::X86SelectStore(Instruction* I) { + EVT VT; + if (!isTypeLegal(I->getOperand(0)->getType(), VT, /*AllowI1=*/true)) + return false; + + X86AddressMode AM; + if (!X86SelectAddress(I->getOperand(1), AM)) + return false; + + return X86FastEmitStore(VT, I->getOperand(0), AM); +} + +/// X86SelectLoad - Select and emit code to implement load instructions. +/// +bool X86FastISel::X86SelectLoad(Instruction *I) { + EVT VT; + if (!isTypeLegal(I->getType(), VT, /*AllowI1=*/true)) + return false; + + X86AddressMode AM; + if (!X86SelectAddress(I->getOperand(0), AM)) + return false; + + unsigned ResultReg = 0; + if (X86FastEmitLoad(VT, AM, ResultReg)) { + UpdateValueMap(I, ResultReg); + return true; + } + return false; +} + +static unsigned X86ChooseCmpOpcode(EVT VT) { + switch (VT.getSimpleVT().SimpleTy) { + default: return 0; + case MVT::i8: return X86::CMP8rr; + case MVT::i16: return X86::CMP16rr; + case MVT::i32: return X86::CMP32rr; + case MVT::i64: return X86::CMP64rr; + case MVT::f32: return X86::UCOMISSrr; + case MVT::f64: return X86::UCOMISDrr; + } +} + +/// X86ChooseCmpImmediateOpcode - If we have a comparison with RHS as the RHS +/// of the comparison, return an opcode that works for the compare (e.g. +/// CMP32ri) otherwise return 0. +static unsigned X86ChooseCmpImmediateOpcode(EVT VT, ConstantInt *RHSC) { + switch (VT.getSimpleVT().SimpleTy) { + // Otherwise, we can't fold the immediate into this comparison. + default: return 0; + case MVT::i8: return X86::CMP8ri; + case MVT::i16: return X86::CMP16ri; + case MVT::i32: return X86::CMP32ri; + case MVT::i64: + // 64-bit comparisons are only valid if the immediate fits in a 32-bit sext + // field. + if ((int)RHSC->getSExtValue() == RHSC->getSExtValue()) + return X86::CMP64ri32; + return 0; + } +} + +bool X86FastISel::X86FastEmitCompare(Value *Op0, Value *Op1, EVT VT) { + unsigned Op0Reg = getRegForValue(Op0); + if (Op0Reg == 0) return false; + + // Handle 'null' like i32/i64 0. + if (isa(Op1)) + Op1 = Constant::getNullValue(TD.getIntPtrType(Op0->getContext())); + + // We have two options: compare with register or immediate. If the RHS of + // the compare is an immediate that we can fold into this compare, use + // CMPri, otherwise use CMPrr. + if (ConstantInt *Op1C = dyn_cast(Op1)) { + if (unsigned CompareImmOpc = X86ChooseCmpImmediateOpcode(VT, Op1C)) { + BuildMI(MBB, DL, TII.get(CompareImmOpc)).addReg(Op0Reg) + .addImm(Op1C->getSExtValue()); + return true; + } + } + + unsigned CompareOpc = X86ChooseCmpOpcode(VT); + if (CompareOpc == 0) return false; + + unsigned Op1Reg = getRegForValue(Op1); + if (Op1Reg == 0) return false; + BuildMI(MBB, DL, TII.get(CompareOpc)).addReg(Op0Reg).addReg(Op1Reg); + + return true; +} + +bool X86FastISel::X86SelectCmp(Instruction *I) { + CmpInst *CI = cast(I); + + EVT VT; + if (!isTypeLegal(I->getOperand(0)->getType(), VT)) + return false; + + unsigned ResultReg = createResultReg(&X86::GR8RegClass); + unsigned SetCCOpc; + bool SwapArgs; // false -> compare Op0, Op1. true -> compare Op1, Op0. + switch (CI->getPredicate()) { + case CmpInst::FCMP_OEQ: { + if (!X86FastEmitCompare(CI->getOperand(0), CI->getOperand(1), VT)) + return false; + + unsigned EReg = createResultReg(&X86::GR8RegClass); + unsigned NPReg = createResultReg(&X86::GR8RegClass); + BuildMI(MBB, DL, TII.get(X86::SETEr), EReg); + BuildMI(MBB, DL, TII.get(X86::SETNPr), NPReg); + BuildMI(MBB, DL, + TII.get(X86::AND8rr), ResultReg).addReg(NPReg).addReg(EReg); + UpdateValueMap(I, ResultReg); + return true; + } + case CmpInst::FCMP_UNE: { + if (!X86FastEmitCompare(CI->getOperand(0), CI->getOperand(1), VT)) + return false; + + unsigned NEReg = createResultReg(&X86::GR8RegClass); + unsigned PReg = createResultReg(&X86::GR8RegClass); + BuildMI(MBB, DL, TII.get(X86::SETNEr), NEReg); + BuildMI(MBB, DL, TII.get(X86::SETPr), PReg); + BuildMI(MBB, DL, TII.get(X86::OR8rr), ResultReg).addReg(PReg).addReg(NEReg); + UpdateValueMap(I, ResultReg); + return true; + } + case CmpInst::FCMP_OGT: SwapArgs = false; SetCCOpc = X86::SETAr; break; + case CmpInst::FCMP_OGE: SwapArgs = false; SetCCOpc = X86::SETAEr; break; + case CmpInst::FCMP_OLT: SwapArgs = true; SetCCOpc = X86::SETAr; break; + case CmpInst::FCMP_OLE: SwapArgs = true; SetCCOpc = X86::SETAEr; break; + case CmpInst::FCMP_ONE: SwapArgs = false; SetCCOpc = X86::SETNEr; break; + case CmpInst::FCMP_ORD: SwapArgs = false; SetCCOpc = X86::SETNPr; break; + case CmpInst::FCMP_UNO: SwapArgs = false; SetCCOpc = X86::SETPr; break; + case CmpInst::FCMP_UEQ: SwapArgs = false; SetCCOpc = X86::SETEr; break; + case CmpInst::FCMP_UGT: SwapArgs = true; SetCCOpc = X86::SETBr; break; + case CmpInst::FCMP_UGE: SwapArgs = true; SetCCOpc = X86::SETBEr; break; + case CmpInst::FCMP_ULT: SwapArgs = false; SetCCOpc = X86::SETBr; break; + case CmpInst::FCMP_ULE: SwapArgs = false; SetCCOpc = X86::SETBEr; break; + + case CmpInst::ICMP_EQ: SwapArgs = false; SetCCOpc = X86::SETEr; break; + case CmpInst::ICMP_NE: SwapArgs = false; SetCCOpc = X86::SETNEr; break; + case CmpInst::ICMP_UGT: SwapArgs = false; SetCCOpc = X86::SETAr; break; + case CmpInst::ICMP_UGE: SwapArgs = false; SetCCOpc = X86::SETAEr; break; + case CmpInst::ICMP_ULT: SwapArgs = false; SetCCOpc = X86::SETBr; break; + case CmpInst::ICMP_ULE: SwapArgs = false; SetCCOpc = X86::SETBEr; break; + case CmpInst::ICMP_SGT: SwapArgs = false; SetCCOpc = X86::SETGr; break; + case CmpInst::ICMP_SGE: SwapArgs = false; SetCCOpc = X86::SETGEr; break; + case CmpInst::ICMP_SLT: SwapArgs = false; SetCCOpc = X86::SETLr; break; + case CmpInst::ICMP_SLE: SwapArgs = false; SetCCOpc = X86::SETLEr; break; + default: + return false; + } + + Value *Op0 = CI->getOperand(0), *Op1 = CI->getOperand(1); + if (SwapArgs) + std::swap(Op0, Op1); + + // Emit a compare of Op0/Op1. + if (!X86FastEmitCompare(Op0, Op1, VT)) + return false; + + BuildMI(MBB, DL, TII.get(SetCCOpc), ResultReg); + UpdateValueMap(I, ResultReg); + return true; +} + +bool X86FastISel::X86SelectZExt(Instruction *I) { + // Handle zero-extension from i1 to i8, which is common. + if (I->getType() == Type::getInt8Ty(I->getContext()) && + I->getOperand(0)->getType() == Type::getInt1Ty(I->getContext())) { + unsigned ResultReg = getRegForValue(I->getOperand(0)); + if (ResultReg == 0) return false; + // Set the high bits to zero. + ResultReg = FastEmitZExtFromI1(MVT::i8, ResultReg); + if (ResultReg == 0) return false; + UpdateValueMap(I, ResultReg); + return true; + } + + return false; +} + + +bool X86FastISel::X86SelectBranch(Instruction *I) { + // Unconditional branches are selected by tablegen-generated code. + // Handle a conditional branch. + BranchInst *BI = cast(I); + MachineBasicBlock *TrueMBB = MBBMap[BI->getSuccessor(0)]; + MachineBasicBlock *FalseMBB = MBBMap[BI->getSuccessor(1)]; + + // Fold the common case of a conditional branch with a comparison. + if (CmpInst *CI = dyn_cast(BI->getCondition())) { + if (CI->hasOneUse()) { + EVT VT = TLI.getValueType(CI->getOperand(0)->getType()); + + // Try to take advantage of fallthrough opportunities. + CmpInst::Predicate Predicate = CI->getPredicate(); + if (MBB->isLayoutSuccessor(TrueMBB)) { + std::swap(TrueMBB, FalseMBB); + Predicate = CmpInst::getInversePredicate(Predicate); + } + + bool SwapArgs; // false -> compare Op0, Op1. true -> compare Op1, Op0. + unsigned BranchOpc; // Opcode to jump on, e.g. "X86::JA" + + switch (Predicate) { + case CmpInst::FCMP_OEQ: + std::swap(TrueMBB, FalseMBB); + Predicate = CmpInst::FCMP_UNE; + // FALL THROUGH + case CmpInst::FCMP_UNE: SwapArgs = false; BranchOpc = X86::JNE; break; + case CmpInst::FCMP_OGT: SwapArgs = false; BranchOpc = X86::JA; break; + case CmpInst::FCMP_OGE: SwapArgs = false; BranchOpc = X86::JAE; break; + case CmpInst::FCMP_OLT: SwapArgs = true; BranchOpc = X86::JA; break; + case CmpInst::FCMP_OLE: SwapArgs = true; BranchOpc = X86::JAE; break; + case CmpInst::FCMP_ONE: SwapArgs = false; BranchOpc = X86::JNE; break; + case CmpInst::FCMP_ORD: SwapArgs = false; BranchOpc = X86::JNP; break; + case CmpInst::FCMP_UNO: SwapArgs = false; BranchOpc = X86::JP; break; + case CmpInst::FCMP_UEQ: SwapArgs = false; BranchOpc = X86::JE; break; + case CmpInst::FCMP_UGT: SwapArgs = true; BranchOpc = X86::JB; break; + case CmpInst::FCMP_UGE: SwapArgs = true; BranchOpc = X86::JBE; break; + case CmpInst::FCMP_ULT: SwapArgs = false; BranchOpc = X86::JB; break; + case CmpInst::FCMP_ULE: SwapArgs = false; BranchOpc = X86::JBE; break; + + case CmpInst::ICMP_EQ: SwapArgs = false; BranchOpc = X86::JE; break; + case CmpInst::ICMP_NE: SwapArgs = false; BranchOpc = X86::JNE; break; + case CmpInst::ICMP_UGT: SwapArgs = false; BranchOpc = X86::JA; break; + case CmpInst::ICMP_UGE: SwapArgs = false; BranchOpc = X86::JAE; break; + case CmpInst::ICMP_ULT: SwapArgs = false; BranchOpc = X86::JB; break; + case CmpInst::ICMP_ULE: SwapArgs = false; BranchOpc = X86::JBE; break; + case CmpInst::ICMP_SGT: SwapArgs = false; BranchOpc = X86::JG; break; + case CmpInst::ICMP_SGE: SwapArgs = false; BranchOpc = X86::JGE; break; + case CmpInst::ICMP_SLT: SwapArgs = false; BranchOpc = X86::JL; break; + case CmpInst::ICMP_SLE: SwapArgs = false; BranchOpc = X86::JLE; break; + default: + return false; + } + + Value *Op0 = CI->getOperand(0), *Op1 = CI->getOperand(1); + if (SwapArgs) + std::swap(Op0, Op1); + + // Emit a compare of the LHS and RHS, setting the flags. + if (!X86FastEmitCompare(Op0, Op1, VT)) + return false; + + BuildMI(MBB, DL, TII.get(BranchOpc)).addMBB(TrueMBB); + + if (Predicate == CmpInst::FCMP_UNE) { + // X86 requires a second branch to handle UNE (and OEQ, + // which is mapped to UNE above). + BuildMI(MBB, DL, TII.get(X86::JP)).addMBB(TrueMBB); + } + + FastEmitBranch(FalseMBB); + MBB->addSuccessor(TrueMBB); + return true; + } + } else if (ExtractValueInst *EI = + dyn_cast(BI->getCondition())) { + // Check to see if the branch instruction is from an "arithmetic with + // overflow" intrinsic. The main way these intrinsics are used is: + // + // %t = call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 %v1, i32 %v2) + // %sum = extractvalue { i32, i1 } %t, 0 + // %obit = extractvalue { i32, i1 } %t, 1 + // br i1 %obit, label %overflow, label %normal + // + // The %sum and %obit are converted in an ADD and a SETO/SETB before + // reaching the branch. Therefore, we search backwards through the MBB + // looking for the SETO/SETB instruction. If an instruction modifies the + // EFLAGS register before we reach the SETO/SETB instruction, then we can't + // convert the branch into a JO/JB instruction. + if (IntrinsicInst *CI = dyn_cast(EI->getAggregateOperand())){ + if (CI->getIntrinsicID() == Intrinsic::sadd_with_overflow || + CI->getIntrinsicID() == Intrinsic::uadd_with_overflow) { + const MachineInstr *SetMI = 0; + unsigned Reg = lookUpRegForValue(EI); + + for (MachineBasicBlock::const_reverse_iterator + RI = MBB->rbegin(), RE = MBB->rend(); RI != RE; ++RI) { + const MachineInstr &MI = *RI; + + if (MI.modifiesRegister(Reg)) { + unsigned Src, Dst, SrcSR, DstSR; + + if (getInstrInfo()->isMoveInstr(MI, Src, Dst, SrcSR, DstSR)) { + Reg = Src; + continue; + } + + SetMI = &MI; + break; + } + + const TargetInstrDesc &TID = MI.getDesc(); + if (TID.hasUnmodeledSideEffects() || + TID.hasImplicitDefOfPhysReg(X86::EFLAGS)) + break; + } + + if (SetMI) { + unsigned OpCode = SetMI->getOpcode(); + + if (OpCode == X86::SETOr || OpCode == X86::SETBr) { + BuildMI(MBB, DL, TII.get(OpCode == X86::SETOr ? X86::JO : X86::JB)) + .addMBB(TrueMBB); + FastEmitBranch(FalseMBB); + MBB->addSuccessor(TrueMBB); + return true; + } + } + } + } + } + + // Otherwise do a clumsy setcc and re-test it. + unsigned OpReg = getRegForValue(BI->getCondition()); + if (OpReg == 0) return false; + + BuildMI(MBB, DL, TII.get(X86::TEST8rr)).addReg(OpReg).addReg(OpReg); + BuildMI(MBB, DL, TII.get(X86::JNE)).addMBB(TrueMBB); + FastEmitBranch(FalseMBB); + MBB->addSuccessor(TrueMBB); + return true; +} + +bool X86FastISel::X86SelectShift(Instruction *I) { + unsigned CReg = 0, OpReg = 0, OpImm = 0; + const TargetRegisterClass *RC = NULL; + if (I->getType() == Type::getInt8Ty(I->getContext())) { + CReg = X86::CL; + RC = &X86::GR8RegClass; + switch (I->getOpcode()) { + case Instruction::LShr: OpReg = X86::SHR8rCL; OpImm = X86::SHR8ri; break; + case Instruction::AShr: OpReg = X86::SAR8rCL; OpImm = X86::SAR8ri; break; + case Instruction::Shl: OpReg = X86::SHL8rCL; OpImm = X86::SHL8ri; break; + default: return false; + } + } else if (I->getType() == Type::getInt16Ty(I->getContext())) { + CReg = X86::CX; + RC = &X86::GR16RegClass; + switch (I->getOpcode()) { + case Instruction::LShr: OpReg = X86::SHR16rCL; OpImm = X86::SHR16ri; break; + case Instruction::AShr: OpReg = X86::SAR16rCL; OpImm = X86::SAR16ri; break; + case Instruction::Shl: OpReg = X86::SHL16rCL; OpImm = X86::SHL16ri; break; + default: return false; + } + } else if (I->getType() == Type::getInt32Ty(I->getContext())) { + CReg = X86::ECX; + RC = &X86::GR32RegClass; + switch (I->getOpcode()) { + case Instruction::LShr: OpReg = X86::SHR32rCL; OpImm = X86::SHR32ri; break; + case Instruction::AShr: OpReg = X86::SAR32rCL; OpImm = X86::SAR32ri; break; + case Instruction::Shl: OpReg = X86::SHL32rCL; OpImm = X86::SHL32ri; break; + default: return false; + } + } else if (I->getType() == Type::getInt64Ty(I->getContext())) { + CReg = X86::RCX; + RC = &X86::GR64RegClass; + switch (I->getOpcode()) { + case Instruction::LShr: OpReg = X86::SHR64rCL; OpImm = X86::SHR64ri; break; + case Instruction::AShr: OpReg = X86::SAR64rCL; OpImm = X86::SAR64ri; break; + case Instruction::Shl: OpReg = X86::SHL64rCL; OpImm = X86::SHL64ri; break; + default: return false; + } + } else { + return false; + } + + EVT VT = TLI.getValueType(I->getType(), /*HandleUnknown=*/true); + if (VT == MVT::Other || !isTypeLegal(I->getType(), VT)) + return false; + + unsigned Op0Reg = getRegForValue(I->getOperand(0)); + if (Op0Reg == 0) return false; + + // Fold immediate in shl(x,3). + if (ConstantInt *CI = dyn_cast(I->getOperand(1))) { + unsigned ResultReg = createResultReg(RC); + BuildMI(MBB, DL, TII.get(OpImm), + ResultReg).addReg(Op0Reg).addImm(CI->getZExtValue() & 0xff); + UpdateValueMap(I, ResultReg); + return true; + } + + unsigned Op1Reg = getRegForValue(I->getOperand(1)); + if (Op1Reg == 0) return false; + TII.copyRegToReg(*MBB, MBB->end(), CReg, Op1Reg, RC, RC); + + // The shift instruction uses X86::CL. If we defined a super-register + // of X86::CL, emit an EXTRACT_SUBREG to precisely describe what + // we're doing here. + if (CReg != X86::CL) + BuildMI(MBB, DL, TII.get(TargetInstrInfo::EXTRACT_SUBREG), X86::CL) + .addReg(CReg).addImm(X86::SUBREG_8BIT); + + unsigned ResultReg = createResultReg(RC); + BuildMI(MBB, DL, TII.get(OpReg), ResultReg).addReg(Op0Reg); + UpdateValueMap(I, ResultReg); + return true; +} + +bool X86FastISel::X86SelectSelect(Instruction *I) { + EVT VT = TLI.getValueType(I->getType(), /*HandleUnknown=*/true); + if (VT == MVT::Other || !isTypeLegal(I->getType(), VT)) + return false; + + unsigned Opc = 0; + const TargetRegisterClass *RC = NULL; + if (VT.getSimpleVT() == MVT::i16) { + Opc = X86::CMOVE16rr; + RC = &X86::GR16RegClass; + } else if (VT.getSimpleVT() == MVT::i32) { + Opc = X86::CMOVE32rr; + RC = &X86::GR32RegClass; + } else if (VT.getSimpleVT() == MVT::i64) { + Opc = X86::CMOVE64rr; + RC = &X86::GR64RegClass; + } else { + return false; + } + + unsigned Op0Reg = getRegForValue(I->getOperand(0)); + if (Op0Reg == 0) return false; + unsigned Op1Reg = getRegForValue(I->getOperand(1)); + if (Op1Reg == 0) return false; + unsigned Op2Reg = getRegForValue(I->getOperand(2)); + if (Op2Reg == 0) return false; + + BuildMI(MBB, DL, TII.get(X86::TEST8rr)).addReg(Op0Reg).addReg(Op0Reg); + unsigned ResultReg = createResultReg(RC); + BuildMI(MBB, DL, TII.get(Opc), ResultReg).addReg(Op1Reg).addReg(Op2Reg); + UpdateValueMap(I, ResultReg); + return true; +} + +bool X86FastISel::X86SelectFPExt(Instruction *I) { + // fpext from float to double. + if (Subtarget->hasSSE2() && + I->getType()->isDoubleTy()) { + Value *V = I->getOperand(0); + if (V->getType()->isFloatTy()) { + unsigned OpReg = getRegForValue(V); + if (OpReg == 0) return false; + unsigned ResultReg = createResultReg(X86::FR64RegisterClass); + BuildMI(MBB, DL, TII.get(X86::CVTSS2SDrr), ResultReg).addReg(OpReg); + UpdateValueMap(I, ResultReg); + return true; + } + } + + return false; +} + +bool X86FastISel::X86SelectFPTrunc(Instruction *I) { + if (Subtarget->hasSSE2()) { + if (I->getType()->isFloatTy()) { + Value *V = I->getOperand(0); + if (V->getType()->isDoubleTy()) { + unsigned OpReg = getRegForValue(V); + if (OpReg == 0) return false; + unsigned ResultReg = createResultReg(X86::FR32RegisterClass); + BuildMI(MBB, DL, TII.get(X86::CVTSD2SSrr), ResultReg).addReg(OpReg); + UpdateValueMap(I, ResultReg); + return true; + } + } + } + + return false; +} + +bool X86FastISel::X86SelectTrunc(Instruction *I) { + if (Subtarget->is64Bit()) + // All other cases should be handled by the tblgen generated code. + return false; + EVT SrcVT = TLI.getValueType(I->getOperand(0)->getType()); + EVT DstVT = TLI.getValueType(I->getType()); + + // This code only handles truncation to byte right now. + if (DstVT != MVT::i8 && DstVT != MVT::i1) + // All other cases should be handled by the tblgen generated code. + return false; + if (SrcVT != MVT::i16 && SrcVT != MVT::i32) + // All other cases should be handled by the tblgen generated code. + return false; + + unsigned InputReg = getRegForValue(I->getOperand(0)); + if (!InputReg) + // Unhandled operand. Halt "fast" selection and bail. + return false; + + // First issue a copy to GR16_ABCD or GR32_ABCD. + unsigned CopyOpc = (SrcVT == MVT::i16) ? X86::MOV16rr : X86::MOV32rr; + const TargetRegisterClass *CopyRC = (SrcVT == MVT::i16) + ? X86::GR16_ABCDRegisterClass : X86::GR32_ABCDRegisterClass; + unsigned CopyReg = createResultReg(CopyRC); + BuildMI(MBB, DL, TII.get(CopyOpc), CopyReg).addReg(InputReg); + + // Then issue an extract_subreg. + unsigned ResultReg = FastEmitInst_extractsubreg(MVT::i8, + CopyReg, X86::SUBREG_8BIT); + if (!ResultReg) + return false; + + UpdateValueMap(I, ResultReg); + return true; +} + +bool X86FastISel::X86SelectExtractValue(Instruction *I) { + ExtractValueInst *EI = cast(I); + Value *Agg = EI->getAggregateOperand(); + + if (IntrinsicInst *CI = dyn_cast(Agg)) { + switch (CI->getIntrinsicID()) { + default: break; + case Intrinsic::sadd_with_overflow: + case Intrinsic::uadd_with_overflow: + // Cheat a little. We know that the registers for "add" and "seto" are + // allocated sequentially. However, we only keep track of the register + // for "add" in the value map. Use extractvalue's index to get the + // correct register for "seto". + UpdateValueMap(I, lookUpRegForValue(Agg) + *EI->idx_begin()); + return true; + } + } + + return false; +} + +bool X86FastISel::X86VisitIntrinsicCall(IntrinsicInst &I) { + // FIXME: Handle more intrinsics. + switch (I.getIntrinsicID()) { + default: return false; + case Intrinsic::sadd_with_overflow: + case Intrinsic::uadd_with_overflow: { + // Replace "add with overflow" intrinsics with an "add" instruction followed + // by a seto/setc instruction. Later on, when the "extractvalue" + // instructions are encountered, we use the fact that two registers were + // created sequentially to get the correct registers for the "sum" and the + // "overflow bit". + const Function *Callee = I.getCalledFunction(); + const Type *RetTy = + cast(Callee->getReturnType())->getTypeAtIndex(unsigned(0)); + + EVT VT; + if (!isTypeLegal(RetTy, VT)) + return false; + + Value *Op1 = I.getOperand(1); + Value *Op2 = I.getOperand(2); + unsigned Reg1 = getRegForValue(Op1); + unsigned Reg2 = getRegForValue(Op2); + + if (Reg1 == 0 || Reg2 == 0) + // FIXME: Handle values *not* in registers. + return false; + + unsigned OpC = 0; + if (VT == MVT::i32) + OpC = X86::ADD32rr; + else if (VT == MVT::i64) + OpC = X86::ADD64rr; + else + return false; + + unsigned ResultReg = createResultReg(TLI.getRegClassFor(VT)); + BuildMI(MBB, DL, TII.get(OpC), ResultReg).addReg(Reg1).addReg(Reg2); + unsigned DestReg1 = UpdateValueMap(&I, ResultReg); + + // If the add with overflow is an intra-block value then we just want to + // create temporaries for it like normal. If it is a cross-block value then + // UpdateValueMap will return the cross-block register used. Since we + // *really* want the value to be live in the register pair known by + // UpdateValueMap, we have to use DestReg1+1 as the destination register in + // the cross block case. In the non-cross-block case, we should just make + // another register for the value. + if (DestReg1 != ResultReg) + ResultReg = DestReg1+1; + else + ResultReg = createResultReg(TLI.getRegClassFor(MVT::i8)); + + unsigned Opc = X86::SETBr; + if (I.getIntrinsicID() == Intrinsic::sadd_with_overflow) + Opc = X86::SETOr; + BuildMI(MBB, DL, TII.get(Opc), ResultReg); + return true; + } + } +} + +bool X86FastISel::X86SelectCall(Instruction *I) { + CallInst *CI = cast(I); + Value *Callee = I->getOperand(0); + + // Can't handle inline asm yet. + if (isa(Callee)) + return false; + + // Handle intrinsic calls. + if (IntrinsicInst *II = dyn_cast(CI)) + return X86VisitIntrinsicCall(*II); + + // Handle only C and fastcc calling conventions for now. + CallSite CS(CI); + CallingConv::ID CC = CS.getCallingConv(); + if (CC != CallingConv::C && + CC != CallingConv::Fast && + CC != CallingConv::X86_FastCall) + return false; + + // On X86, -tailcallopt changes the fastcc ABI. FastISel doesn't + // handle this for now. + if (CC == CallingConv::Fast && PerformTailCallOpt) + return false; + + // Let SDISel handle vararg functions. + const PointerType *PT = cast(CS.getCalledValue()->getType()); + const FunctionType *FTy = cast(PT->getElementType()); + if (FTy->isVarArg()) + return false; + + // Handle *simple* calls for now. + const Type *RetTy = CS.getType(); + EVT RetVT; + if (RetTy->isVoidTy()) + RetVT = MVT::isVoid; + else if (!isTypeLegal(RetTy, RetVT, true)) + return false; + + // Materialize callee address in a register. FIXME: GV address can be + // handled with a CALLpcrel32 instead. + X86AddressMode CalleeAM; + if (!X86SelectCallAddress(Callee, CalleeAM)) + return false; + unsigned CalleeOp = 0; + GlobalValue *GV = 0; + if (CalleeAM.GV != 0) { + GV = CalleeAM.GV; + } else if (CalleeAM.Base.Reg != 0) { + CalleeOp = CalleeAM.Base.Reg; + } else + return false; + + // Allow calls which produce i1 results. + bool AndToI1 = false; + if (RetVT == MVT::i1) { + RetVT = MVT::i8; + AndToI1 = true; + } + + // Deal with call operands first. + SmallVector ArgVals; + SmallVector Args; + SmallVector ArgVTs; + SmallVector ArgFlags; + Args.reserve(CS.arg_size()); + ArgVals.reserve(CS.arg_size()); + ArgVTs.reserve(CS.arg_size()); + ArgFlags.reserve(CS.arg_size()); + for (CallSite::arg_iterator i = CS.arg_begin(), e = CS.arg_end(); + i != e; ++i) { + unsigned Arg = getRegForValue(*i); + if (Arg == 0) + return false; + ISD::ArgFlagsTy Flags; + unsigned AttrInd = i - CS.arg_begin() + 1; + if (CS.paramHasAttr(AttrInd, Attribute::SExt)) + Flags.setSExt(); + if (CS.paramHasAttr(AttrInd, Attribute::ZExt)) + Flags.setZExt(); + + // FIXME: Only handle *easy* calls for now. + if (CS.paramHasAttr(AttrInd, Attribute::InReg) || + CS.paramHasAttr(AttrInd, Attribute::StructRet) || + CS.paramHasAttr(AttrInd, Attribute::Nest) || + CS.paramHasAttr(AttrInd, Attribute::ByVal)) + return false; + + const Type *ArgTy = (*i)->getType(); + EVT ArgVT; + if (!isTypeLegal(ArgTy, ArgVT)) + return false; + unsigned OriginalAlignment = TD.getABITypeAlignment(ArgTy); + Flags.setOrigAlign(OriginalAlignment); + + Args.push_back(Arg); + ArgVals.push_back(*i); + ArgVTs.push_back(ArgVT); + ArgFlags.push_back(Flags); + } + + // Analyze operands of the call, assigning locations to each operand. + SmallVector ArgLocs; + CCState CCInfo(CC, false, TM, ArgLocs, I->getParent()->getContext()); + CCInfo.AnalyzeCallOperands(ArgVTs, ArgFlags, CCAssignFnForCall(CC)); + + // Get a count of how many bytes are to be pushed on the stack. + unsigned NumBytes = CCInfo.getNextStackOffset(); + + // Issue CALLSEQ_START + unsigned AdjStackDown = TM.getRegisterInfo()->getCallFrameSetupOpcode(); + BuildMI(MBB, DL, TII.get(AdjStackDown)).addImm(NumBytes); + + // Process argument: walk the register/memloc assignments, inserting + // copies / loads. + SmallVector RegArgs; + for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { + CCValAssign &VA = ArgLocs[i]; + unsigned Arg = Args[VA.getValNo()]; + EVT ArgVT = ArgVTs[VA.getValNo()]; + + // Promote the value if needed. + switch (VA.getLocInfo()) { + default: llvm_unreachable("Unknown loc info!"); + case CCValAssign::Full: break; + case CCValAssign::SExt: { + bool Emitted = X86FastEmitExtend(ISD::SIGN_EXTEND, VA.getLocVT(), + Arg, ArgVT, Arg); + assert(Emitted && "Failed to emit a sext!"); Emitted=Emitted; + Emitted = true; + ArgVT = VA.getLocVT(); + break; + } + case CCValAssign::ZExt: { + bool Emitted = X86FastEmitExtend(ISD::ZERO_EXTEND, VA.getLocVT(), + Arg, ArgVT, Arg); + assert(Emitted && "Failed to emit a zext!"); Emitted=Emitted; + Emitted = true; + ArgVT = VA.getLocVT(); + break; + } + case CCValAssign::AExt: { + bool Emitted = X86FastEmitExtend(ISD::ANY_EXTEND, VA.getLocVT(), + Arg, ArgVT, Arg); + if (!Emitted) + Emitted = X86FastEmitExtend(ISD::ZERO_EXTEND, VA.getLocVT(), + Arg, ArgVT, Arg); + if (!Emitted) + Emitted = X86FastEmitExtend(ISD::SIGN_EXTEND, VA.getLocVT(), + Arg, ArgVT, Arg); + + assert(Emitted && "Failed to emit a aext!"); Emitted=Emitted; + ArgVT = VA.getLocVT(); + break; + } + case CCValAssign::BCvt: { + unsigned BC = FastEmit_r(ArgVT.getSimpleVT(), VA.getLocVT().getSimpleVT(), + ISD::BIT_CONVERT, Arg); + assert(BC != 0 && "Failed to emit a bitcast!"); + Arg = BC; + ArgVT = VA.getLocVT(); + break; + } + } + + if (VA.isRegLoc()) { + TargetRegisterClass* RC = TLI.getRegClassFor(ArgVT); + bool Emitted = TII.copyRegToReg(*MBB, MBB->end(), VA.getLocReg(), + Arg, RC, RC); + assert(Emitted && "Failed to emit a copy instruction!"); Emitted=Emitted; + Emitted = true; + RegArgs.push_back(VA.getLocReg()); + } else { + unsigned LocMemOffset = VA.getLocMemOffset(); + X86AddressMode AM; + AM.Base.Reg = StackPtr; + AM.Disp = LocMemOffset; + Value *ArgVal = ArgVals[VA.getValNo()]; + + // If this is a really simple value, emit this with the Value* version of + // X86FastEmitStore. If it isn't simple, we don't want to do this, as it + // can cause us to reevaluate the argument. + if (isa(ArgVal) || isa(ArgVal)) + X86FastEmitStore(ArgVT, ArgVal, AM); + else + X86FastEmitStore(ArgVT, Arg, AM); + } + } + + // ELF / PIC requires GOT in the EBX register before function calls via PLT + // GOT pointer. + if (Subtarget->isPICStyleGOT()) { + TargetRegisterClass *RC = X86::GR32RegisterClass; + unsigned Base = getInstrInfo()->getGlobalBaseReg(&MF); + bool Emitted = TII.copyRegToReg(*MBB, MBB->end(), X86::EBX, Base, RC, RC); + assert(Emitted && "Failed to emit a copy instruction!"); Emitted=Emitted; + Emitted = true; + } + + // Issue the call. + MachineInstrBuilder MIB; + if (CalleeOp) { + // Register-indirect call. + unsigned CallOpc = Subtarget->is64Bit() ? X86::CALL64r : X86::CALL32r; + MIB = BuildMI(MBB, DL, TII.get(CallOpc)).addReg(CalleeOp); + + } else { + // Direct call. + assert(GV && "Not a direct call"); + unsigned CallOpc = + Subtarget->is64Bit() ? X86::CALL64pcrel32 : X86::CALLpcrel32; + + // See if we need any target-specific flags on the GV operand. + unsigned char OpFlags = 0; + + // On ELF targets, in both X86-64 and X86-32 mode, direct calls to + // external symbols most go through the PLT in PIC mode. If the symbol + // has hidden or protected visibility, or if it is static or local, then + // we don't need to use the PLT - we can directly call it. + if (Subtarget->isTargetELF() && + TM.getRelocationModel() == Reloc::PIC_ && + GV->hasDefaultVisibility() && !GV->hasLocalLinkage()) { + OpFlags = X86II::MO_PLT; + } else if (Subtarget->isPICStyleStubAny() && + (GV->isDeclaration() || GV->isWeakForLinker()) && + Subtarget->getDarwinVers() < 9) { + // PC-relative references to external symbols should go through $stub, + // unless we're building with the leopard linker or later, which + // automatically synthesizes these stubs. + OpFlags = X86II::MO_DARWIN_STUB; + } + + + MIB = BuildMI(MBB, DL, TII.get(CallOpc)).addGlobalAddress(GV, 0, OpFlags); + } + + // Add an implicit use GOT pointer in EBX. + if (Subtarget->isPICStyleGOT()) + MIB.addReg(X86::EBX); + + // Add implicit physical register uses to the call. + for (unsigned i = 0, e = RegArgs.size(); i != e; ++i) + MIB.addReg(RegArgs[i]); + + // Issue CALLSEQ_END + unsigned AdjStackUp = TM.getRegisterInfo()->getCallFrameDestroyOpcode(); + BuildMI(MBB, DL, TII.get(AdjStackUp)).addImm(NumBytes).addImm(0); + + // Now handle call return value (if any). + if (RetVT.getSimpleVT().SimpleTy != MVT::isVoid) { + SmallVector RVLocs; + CCState CCInfo(CC, false, TM, RVLocs, I->getParent()->getContext()); + CCInfo.AnalyzeCallResult(RetVT, RetCC_X86); + + // Copy all of the result registers out of their specified physreg. + assert(RVLocs.size() == 1 && "Can't handle multi-value calls!"); + EVT CopyVT = RVLocs[0].getValVT(); + TargetRegisterClass* DstRC = TLI.getRegClassFor(CopyVT); + TargetRegisterClass *SrcRC = DstRC; + + // If this is a call to a function that returns an fp value on the x87 fp + // stack, but where we prefer to use the value in xmm registers, copy it + // out as F80 and use a truncate to move it from fp stack reg to xmm reg. + if ((RVLocs[0].getLocReg() == X86::ST0 || + RVLocs[0].getLocReg() == X86::ST1) && + isScalarFPTypeInSSEReg(RVLocs[0].getValVT())) { + CopyVT = MVT::f80; + SrcRC = X86::RSTRegisterClass; + DstRC = X86::RFP80RegisterClass; + } + + unsigned ResultReg = createResultReg(DstRC); + bool Emitted = TII.copyRegToReg(*MBB, MBB->end(), ResultReg, + RVLocs[0].getLocReg(), DstRC, SrcRC); + assert(Emitted && "Failed to emit a copy instruction!"); Emitted=Emitted; + Emitted = true; + if (CopyVT != RVLocs[0].getValVT()) { + // Round the F80 the right size, which also moves to the appropriate xmm + // register. This is accomplished by storing the F80 value in memory and + // then loading it back. Ewww... + EVT ResVT = RVLocs[0].getValVT(); + unsigned Opc = ResVT == MVT::f32 ? X86::ST_Fp80m32 : X86::ST_Fp80m64; + unsigned MemSize = ResVT.getSizeInBits()/8; + int FI = MFI.CreateStackObject(MemSize, MemSize, false); + addFrameReference(BuildMI(MBB, DL, TII.get(Opc)), FI).addReg(ResultReg); + DstRC = ResVT == MVT::f32 + ? X86::FR32RegisterClass : X86::FR64RegisterClass; + Opc = ResVT == MVT::f32 ? X86::MOVSSrm : X86::MOVSDrm; + ResultReg = createResultReg(DstRC); + addFrameReference(BuildMI(MBB, DL, TII.get(Opc), ResultReg), FI); + } + + if (AndToI1) { + // Mask out all but lowest bit for some call which produces an i1. + unsigned AndResult = createResultReg(X86::GR8RegisterClass); + BuildMI(MBB, DL, + TII.get(X86::AND8ri), AndResult).addReg(ResultReg).addImm(1); + ResultReg = AndResult; + } + + UpdateValueMap(I, ResultReg); + } + + return true; +} + + +bool +X86FastISel::TargetSelectInstruction(Instruction *I) { + switch (I->getOpcode()) { + default: break; + case Instruction::Load: + return X86SelectLoad(I); + case Instruction::Store: + return X86SelectStore(I); + case Instruction::ICmp: + case Instruction::FCmp: + return X86SelectCmp(I); + case Instruction::ZExt: + return X86SelectZExt(I); + case Instruction::Br: + return X86SelectBranch(I); + case Instruction::Call: + return X86SelectCall(I); + case Instruction::LShr: + case Instruction::AShr: + case Instruction::Shl: + return X86SelectShift(I); + case Instruction::Select: + return X86SelectSelect(I); + case Instruction::Trunc: + return X86SelectTrunc(I); + case Instruction::FPExt: + return X86SelectFPExt(I); + case Instruction::FPTrunc: + return X86SelectFPTrunc(I); + case Instruction::ExtractValue: + return X86SelectExtractValue(I); + case Instruction::IntToPtr: // Deliberate fall-through. + case Instruction::PtrToInt: { + EVT SrcVT = TLI.getValueType(I->getOperand(0)->getType()); + EVT DstVT = TLI.getValueType(I->getType()); + if (DstVT.bitsGT(SrcVT)) + return X86SelectZExt(I); + if (DstVT.bitsLT(SrcVT)) + return X86SelectTrunc(I); + unsigned Reg = getRegForValue(I->getOperand(0)); + if (Reg == 0) return false; + UpdateValueMap(I, Reg); + return true; + } + } + + return false; +} + +unsigned X86FastISel::TargetMaterializeConstant(Constant *C) { + EVT VT; + if (!isTypeLegal(C->getType(), VT)) + return false; + + // Get opcode and regclass of the output for the given load instruction. + unsigned Opc = 0; + const TargetRegisterClass *RC = NULL; + switch (VT.getSimpleVT().SimpleTy) { + default: return false; + case MVT::i8: + Opc = X86::MOV8rm; + RC = X86::GR8RegisterClass; + break; + case MVT::i16: + Opc = X86::MOV16rm; + RC = X86::GR16RegisterClass; + break; + case MVT::i32: + Opc = X86::MOV32rm; + RC = X86::GR32RegisterClass; + break; + case MVT::i64: + // Must be in x86-64 mode. + Opc = X86::MOV64rm; + RC = X86::GR64RegisterClass; + break; + case MVT::f32: + if (Subtarget->hasSSE1()) { + Opc = X86::MOVSSrm; + RC = X86::FR32RegisterClass; + } else { + Opc = X86::LD_Fp32m; + RC = X86::RFP32RegisterClass; + } + break; + case MVT::f64: + if (Subtarget->hasSSE2()) { + Opc = X86::MOVSDrm; + RC = X86::FR64RegisterClass; + } else { + Opc = X86::LD_Fp64m; + RC = X86::RFP64RegisterClass; + } + break; + case MVT::f80: + // No f80 support yet. + return false; + } + + // Materialize addresses with LEA instructions. + if (isa(C)) { + X86AddressMode AM; + if (X86SelectAddress(C, AM)) { + if (TLI.getPointerTy() == MVT::i32) + Opc = X86::LEA32r; + else + Opc = X86::LEA64r; + unsigned ResultReg = createResultReg(RC); + addLeaAddress(BuildMI(MBB, DL, TII.get(Opc), ResultReg), AM); + return ResultReg; + } + return 0; + } + + // MachineConstantPool wants an explicit alignment. + unsigned Align = TD.getPrefTypeAlignment(C->getType()); + if (Align == 0) { + // Alignment of vector types. FIXME! + Align = TD.getTypeAllocSize(C->getType()); + } + + // x86-32 PIC requires a PIC base register for constant pools. + unsigned PICBase = 0; + unsigned char OpFlag = 0; + if (Subtarget->isPICStyleStubPIC()) { // Not dynamic-no-pic + OpFlag = X86II::MO_PIC_BASE_OFFSET; + PICBase = getInstrInfo()->getGlobalBaseReg(&MF); + } else if (Subtarget->isPICStyleGOT()) { + OpFlag = X86II::MO_GOTOFF; + PICBase = getInstrInfo()->getGlobalBaseReg(&MF); + } else if (Subtarget->isPICStyleRIPRel() && + TM.getCodeModel() == CodeModel::Small) { + PICBase = X86::RIP; + } + + // Create the load from the constant pool. + unsigned MCPOffset = MCP.getConstantPoolIndex(C, Align); + unsigned ResultReg = createResultReg(RC); + addConstantPoolReference(BuildMI(MBB, DL, TII.get(Opc), ResultReg), + MCPOffset, PICBase, OpFlag); + + return ResultReg; +} + +unsigned X86FastISel::TargetMaterializeAlloca(AllocaInst *C) { + // Fail on dynamic allocas. At this point, getRegForValue has already + // checked its CSE maps, so if we're here trying to handle a dynamic + // alloca, we're not going to succeed. X86SelectAddress has a + // check for dynamic allocas, because it's called directly from + // various places, but TargetMaterializeAlloca also needs a check + // in order to avoid recursion between getRegForValue, + // X86SelectAddrss, and TargetMaterializeAlloca. + if (!StaticAllocaMap.count(C)) + return 0; + + X86AddressMode AM; + if (!X86SelectAddress(C, AM)) + return 0; + unsigned Opc = Subtarget->is64Bit() ? X86::LEA64r : X86::LEA32r; + TargetRegisterClass* RC = TLI.getRegClassFor(TLI.getPointerTy()); + unsigned ResultReg = createResultReg(RC); + addLeaAddress(BuildMI(MBB, DL, TII.get(Opc), ResultReg), AM); + return ResultReg; +} + +namespace llvm { + llvm::FastISel *X86::createFastISel(MachineFunction &mf, + MachineModuleInfo *mmi, + DwarfWriter *dw, + DenseMap &vm, + DenseMap &bm, + DenseMap &am +#ifndef NDEBUG + , SmallSet &cil +#endif + ) { + return new X86FastISel(mf, mmi, dw, vm, bm, am +#ifndef NDEBUG + , cil +#endif + ); + } +} diff --git a/libclamav/c++/llvm/lib/Target/X86/X86FloatingPoint.cpp b/libclamav/c++/llvm/lib/Target/X86/X86FloatingPoint.cpp new file mode 100644 index 000000000..a2fe9b095 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/X86/X86FloatingPoint.cpp @@ -0,0 +1,1207 @@ +//===-- X86FloatingPoint.cpp - Floating point Reg -> Stack converter ------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the pass which converts floating point instructions from +// virtual registers into register stack instructions. This pass uses live +// variable information to indicate where the FPn registers are used and their +// lifetimes. +// +// This pass is hampered by the lack of decent CFG manipulation routines for +// machine code. In particular, this wants to be able to split critical edges +// as necessary, traverse the machine basic block CFG in depth-first order, and +// allow there to be multiple machine basic blocks for each LLVM basicblock +// (needed for critical edge splitting). +// +// In particular, this pass currently barfs on critical edges. Because of this, +// it requires the instruction selector to insert FP_REG_KILL instructions on +// the exits of any basic block that has critical edges going from it, or which +// branch to a critical basic block. +// +// FIXME: this is not implemented yet. The stackifier pass only works on local +// basic blocks. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "x86-codegen" +#include "X86.h" +#include "X86InstrInfo.h" +#include "llvm/ADT/DepthFirstIterator.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetMachine.h" +#include +using namespace llvm; + +STATISTIC(NumFXCH, "Number of fxch instructions inserted"); +STATISTIC(NumFP , "Number of floating point instructions"); + +namespace { + struct FPS : public MachineFunctionPass { + static char ID; + FPS() : MachineFunctionPass(&ID) {} + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesCFG(); + AU.addPreservedID(MachineLoopInfoID); + AU.addPreservedID(MachineDominatorsID); + MachineFunctionPass::getAnalysisUsage(AU); + } + + virtual bool runOnMachineFunction(MachineFunction &MF); + + virtual const char *getPassName() const { return "X86 FP Stackifier"; } + + private: + const TargetInstrInfo *TII; // Machine instruction info. + MachineBasicBlock *MBB; // Current basic block + unsigned Stack[8]; // FP Registers in each stack slot... + unsigned RegMap[8]; // Track which stack slot contains each register + unsigned StackTop; // The current top of the FP stack. + + void dumpStack() const { + errs() << "Stack contents:"; + for (unsigned i = 0; i != StackTop; ++i) { + errs() << " FP" << Stack[i]; + assert(RegMap[Stack[i]] == i && "Stack[] doesn't match RegMap[]!"); + } + errs() << "\n"; + } + private: + /// isStackEmpty - Return true if the FP stack is empty. + bool isStackEmpty() const { + return StackTop == 0; + } + + // getSlot - Return the stack slot number a particular register number is + // in. + unsigned getSlot(unsigned RegNo) const { + assert(RegNo < 8 && "Regno out of range!"); + return RegMap[RegNo]; + } + + // getStackEntry - Return the X86::FP register in register ST(i). + unsigned getStackEntry(unsigned STi) const { + assert(STi < StackTop && "Access past stack top!"); + return Stack[StackTop-1-STi]; + } + + // getSTReg - Return the X86::ST(i) register which contains the specified + // FP register. + unsigned getSTReg(unsigned RegNo) const { + return StackTop - 1 - getSlot(RegNo) + llvm::X86::ST0; + } + + // pushReg - Push the specified FP register onto the stack. + void pushReg(unsigned Reg) { + assert(Reg < 8 && "Register number out of range!"); + assert(StackTop < 8 && "Stack overflow!"); + Stack[StackTop] = Reg; + RegMap[Reg] = StackTop++; + } + + bool isAtTop(unsigned RegNo) const { return getSlot(RegNo) == StackTop-1; } + void moveToTop(unsigned RegNo, MachineBasicBlock::iterator I) { + MachineInstr *MI = I; + DebugLoc dl = MI->getDebugLoc(); + if (isAtTop(RegNo)) return; + + unsigned STReg = getSTReg(RegNo); + unsigned RegOnTop = getStackEntry(0); + + // Swap the slots the regs are in. + std::swap(RegMap[RegNo], RegMap[RegOnTop]); + + // Swap stack slot contents. + assert(RegMap[RegOnTop] < StackTop); + std::swap(Stack[RegMap[RegOnTop]], Stack[StackTop-1]); + + // Emit an fxch to update the runtime processors version of the state. + BuildMI(*MBB, I, dl, TII->get(X86::XCH_F)).addReg(STReg); + NumFXCH++; + } + + void duplicateToTop(unsigned RegNo, unsigned AsReg, MachineInstr *I) { + DebugLoc dl = I->getDebugLoc(); + unsigned STReg = getSTReg(RegNo); + pushReg(AsReg); // New register on top of stack + + BuildMI(*MBB, I, dl, TII->get(X86::LD_Frr)).addReg(STReg); + } + + // popStackAfter - Pop the current value off of the top of the FP stack + // after the specified instruction. + void popStackAfter(MachineBasicBlock::iterator &I); + + // freeStackSlotAfter - Free the specified register from the register stack, + // so that it is no longer in a register. If the register is currently at + // the top of the stack, we just pop the current instruction, otherwise we + // store the current top-of-stack into the specified slot, then pop the top + // of stack. + void freeStackSlotAfter(MachineBasicBlock::iterator &I, unsigned Reg); + + bool processBasicBlock(MachineFunction &MF, MachineBasicBlock &MBB); + + void handleZeroArgFP(MachineBasicBlock::iterator &I); + void handleOneArgFP(MachineBasicBlock::iterator &I); + void handleOneArgFPRW(MachineBasicBlock::iterator &I); + void handleTwoArgFP(MachineBasicBlock::iterator &I); + void handleCompareFP(MachineBasicBlock::iterator &I); + void handleCondMovFP(MachineBasicBlock::iterator &I); + void handleSpecialFP(MachineBasicBlock::iterator &I); + }; + char FPS::ID = 0; +} + +FunctionPass *llvm::createX86FloatingPointStackifierPass() { return new FPS(); } + +/// getFPReg - Return the X86::FPx register number for the specified operand. +/// For example, this returns 3 for X86::FP3. +static unsigned getFPReg(const MachineOperand &MO) { + assert(MO.isReg() && "Expected an FP register!"); + unsigned Reg = MO.getReg(); + assert(Reg >= X86::FP0 && Reg <= X86::FP6 && "Expected FP register!"); + return Reg - X86::FP0; +} + + +/// runOnMachineFunction - Loop over all of the basic blocks, transforming FP +/// register references into FP stack references. +/// +bool FPS::runOnMachineFunction(MachineFunction &MF) { + // We only need to run this pass if there are any FP registers used in this + // function. If it is all integer, there is nothing for us to do! + bool FPIsUsed = false; + + assert(X86::FP6 == X86::FP0+6 && "Register enums aren't sorted right!"); + for (unsigned i = 0; i <= 6; ++i) + if (MF.getRegInfo().isPhysRegUsed(X86::FP0+i)) { + FPIsUsed = true; + break; + } + + // Early exit. + if (!FPIsUsed) return false; + + TII = MF.getTarget().getInstrInfo(); + StackTop = 0; + + // Process the function in depth first order so that we process at least one + // of the predecessors for every reachable block in the function. + SmallPtrSet Processed; + MachineBasicBlock *Entry = MF.begin(); + + bool Changed = false; + for (df_ext_iterator > + I = df_ext_begin(Entry, Processed), E = df_ext_end(Entry, Processed); + I != E; ++I) + Changed |= processBasicBlock(MF, **I); + + // Process any unreachable blocks in arbitrary order now. + if (MF.size() == Processed.size()) + return Changed; + + for (MachineFunction::iterator BB = MF.begin(), E = MF.end(); BB != E; ++BB) + if (Processed.insert(BB)) + Changed |= processBasicBlock(MF, *BB); + + return Changed; +} + +/// processBasicBlock - Loop over all of the instructions in the basic block, +/// transforming FP instructions into their stack form. +/// +bool FPS::processBasicBlock(MachineFunction &MF, MachineBasicBlock &BB) { + bool Changed = false; + MBB = &BB; + + for (MachineBasicBlock::iterator I = BB.begin(); I != BB.end(); ++I) { + MachineInstr *MI = I; + unsigned Flags = MI->getDesc().TSFlags; + + unsigned FPInstClass = Flags & X86II::FPTypeMask; + if (MI->getOpcode() == TargetInstrInfo::INLINEASM) + FPInstClass = X86II::SpecialFP; + + if (FPInstClass == X86II::NotFP) + continue; // Efficiently ignore non-fp insts! + + MachineInstr *PrevMI = 0; + if (I != BB.begin()) + PrevMI = prior(I); + + ++NumFP; // Keep track of # of pseudo instrs + DEBUG(errs() << "\nFPInst:\t" << *MI); + + // Get dead variables list now because the MI pointer may be deleted as part + // of processing! + SmallVector DeadRegs; + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + const MachineOperand &MO = MI->getOperand(i); + if (MO.isReg() && MO.isDead()) + DeadRegs.push_back(MO.getReg()); + } + + switch (FPInstClass) { + case X86II::ZeroArgFP: handleZeroArgFP(I); break; + case X86II::OneArgFP: handleOneArgFP(I); break; // fstp ST(0) + case X86II::OneArgFPRW: handleOneArgFPRW(I); break; // ST(0) = fsqrt(ST(0)) + case X86II::TwoArgFP: handleTwoArgFP(I); break; + case X86II::CompareFP: handleCompareFP(I); break; + case X86II::CondMovFP: handleCondMovFP(I); break; + case X86II::SpecialFP: handleSpecialFP(I); break; + default: llvm_unreachable("Unknown FP Type!"); + } + + // Check to see if any of the values defined by this instruction are dead + // after definition. If so, pop them. + for (unsigned i = 0, e = DeadRegs.size(); i != e; ++i) { + unsigned Reg = DeadRegs[i]; + if (Reg >= X86::FP0 && Reg <= X86::FP6) { + DEBUG(errs() << "Register FP#" << Reg-X86::FP0 << " is dead!\n"); + freeStackSlotAfter(I, Reg-X86::FP0); + } + } + + // Print out all of the instructions expanded to if -debug + DEBUG( + MachineBasicBlock::iterator PrevI(PrevMI); + if (I == PrevI) { + errs() << "Just deleted pseudo instruction\n"; + } else { + MachineBasicBlock::iterator Start = I; + // Rewind to first instruction newly inserted. + while (Start != BB.begin() && prior(Start) != PrevI) --Start; + errs() << "Inserted instructions:\n\t"; + Start->print(errs(), &MF.getTarget()); + while (++Start != next(I)) {} + } + dumpStack(); + ); + + Changed = true; + } + + assert(isStackEmpty() && "Stack not empty at end of basic block?"); + return Changed; +} + +//===----------------------------------------------------------------------===// +// Efficient Lookup Table Support +//===----------------------------------------------------------------------===// + +namespace { + struct TableEntry { + unsigned from; + unsigned to; + bool operator<(const TableEntry &TE) const { return from < TE.from; } + friend bool operator<(const TableEntry &TE, unsigned V) { + return TE.from < V; + } + friend bool operator<(unsigned V, const TableEntry &TE) { + return V < TE.from; + } + }; +} + +#ifndef NDEBUG +static bool TableIsSorted(const TableEntry *Table, unsigned NumEntries) { + for (unsigned i = 0; i != NumEntries-1; ++i) + if (!(Table[i] < Table[i+1])) return false; + return true; +} +#endif + +static int Lookup(const TableEntry *Table, unsigned N, unsigned Opcode) { + const TableEntry *I = std::lower_bound(Table, Table+N, Opcode); + if (I != Table+N && I->from == Opcode) + return I->to; + return -1; +} + +#ifdef NDEBUG +#define ASSERT_SORTED(TABLE) +#else +#define ASSERT_SORTED(TABLE) \ + { static bool TABLE##Checked = false; \ + if (!TABLE##Checked) { \ + assert(TableIsSorted(TABLE, array_lengthof(TABLE)) && \ + "All lookup tables must be sorted for efficient access!"); \ + TABLE##Checked = true; \ + } \ + } +#endif + +//===----------------------------------------------------------------------===// +// Register File -> Register Stack Mapping Methods +//===----------------------------------------------------------------------===// + +// OpcodeTable - Sorted map of register instructions to their stack version. +// The first element is an register file pseudo instruction, the second is the +// concrete X86 instruction which uses the register stack. +// +static const TableEntry OpcodeTable[] = { + { X86::ABS_Fp32 , X86::ABS_F }, + { X86::ABS_Fp64 , X86::ABS_F }, + { X86::ABS_Fp80 , X86::ABS_F }, + { X86::ADD_Fp32m , X86::ADD_F32m }, + { X86::ADD_Fp64m , X86::ADD_F64m }, + { X86::ADD_Fp64m32 , X86::ADD_F32m }, + { X86::ADD_Fp80m32 , X86::ADD_F32m }, + { X86::ADD_Fp80m64 , X86::ADD_F64m }, + { X86::ADD_FpI16m32 , X86::ADD_FI16m }, + { X86::ADD_FpI16m64 , X86::ADD_FI16m }, + { X86::ADD_FpI16m80 , X86::ADD_FI16m }, + { X86::ADD_FpI32m32 , X86::ADD_FI32m }, + { X86::ADD_FpI32m64 , X86::ADD_FI32m }, + { X86::ADD_FpI32m80 , X86::ADD_FI32m }, + { X86::CHS_Fp32 , X86::CHS_F }, + { X86::CHS_Fp64 , X86::CHS_F }, + { X86::CHS_Fp80 , X86::CHS_F }, + { X86::CMOVBE_Fp32 , X86::CMOVBE_F }, + { X86::CMOVBE_Fp64 , X86::CMOVBE_F }, + { X86::CMOVBE_Fp80 , X86::CMOVBE_F }, + { X86::CMOVB_Fp32 , X86::CMOVB_F }, + { X86::CMOVB_Fp64 , X86::CMOVB_F }, + { X86::CMOVB_Fp80 , X86::CMOVB_F }, + { X86::CMOVE_Fp32 , X86::CMOVE_F }, + { X86::CMOVE_Fp64 , X86::CMOVE_F }, + { X86::CMOVE_Fp80 , X86::CMOVE_F }, + { X86::CMOVNBE_Fp32 , X86::CMOVNBE_F }, + { X86::CMOVNBE_Fp64 , X86::CMOVNBE_F }, + { X86::CMOVNBE_Fp80 , X86::CMOVNBE_F }, + { X86::CMOVNB_Fp32 , X86::CMOVNB_F }, + { X86::CMOVNB_Fp64 , X86::CMOVNB_F }, + { X86::CMOVNB_Fp80 , X86::CMOVNB_F }, + { X86::CMOVNE_Fp32 , X86::CMOVNE_F }, + { X86::CMOVNE_Fp64 , X86::CMOVNE_F }, + { X86::CMOVNE_Fp80 , X86::CMOVNE_F }, + { X86::CMOVNP_Fp32 , X86::CMOVNP_F }, + { X86::CMOVNP_Fp64 , X86::CMOVNP_F }, + { X86::CMOVNP_Fp80 , X86::CMOVNP_F }, + { X86::CMOVP_Fp32 , X86::CMOVP_F }, + { X86::CMOVP_Fp64 , X86::CMOVP_F }, + { X86::CMOVP_Fp80 , X86::CMOVP_F }, + { X86::COS_Fp32 , X86::COS_F }, + { X86::COS_Fp64 , X86::COS_F }, + { X86::COS_Fp80 , X86::COS_F }, + { X86::DIVR_Fp32m , X86::DIVR_F32m }, + { X86::DIVR_Fp64m , X86::DIVR_F64m }, + { X86::DIVR_Fp64m32 , X86::DIVR_F32m }, + { X86::DIVR_Fp80m32 , X86::DIVR_F32m }, + { X86::DIVR_Fp80m64 , X86::DIVR_F64m }, + { X86::DIVR_FpI16m32, X86::DIVR_FI16m}, + { X86::DIVR_FpI16m64, X86::DIVR_FI16m}, + { X86::DIVR_FpI16m80, X86::DIVR_FI16m}, + { X86::DIVR_FpI32m32, X86::DIVR_FI32m}, + { X86::DIVR_FpI32m64, X86::DIVR_FI32m}, + { X86::DIVR_FpI32m80, X86::DIVR_FI32m}, + { X86::DIV_Fp32m , X86::DIV_F32m }, + { X86::DIV_Fp64m , X86::DIV_F64m }, + { X86::DIV_Fp64m32 , X86::DIV_F32m }, + { X86::DIV_Fp80m32 , X86::DIV_F32m }, + { X86::DIV_Fp80m64 , X86::DIV_F64m }, + { X86::DIV_FpI16m32 , X86::DIV_FI16m }, + { X86::DIV_FpI16m64 , X86::DIV_FI16m }, + { X86::DIV_FpI16m80 , X86::DIV_FI16m }, + { X86::DIV_FpI32m32 , X86::DIV_FI32m }, + { X86::DIV_FpI32m64 , X86::DIV_FI32m }, + { X86::DIV_FpI32m80 , X86::DIV_FI32m }, + { X86::ILD_Fp16m32 , X86::ILD_F16m }, + { X86::ILD_Fp16m64 , X86::ILD_F16m }, + { X86::ILD_Fp16m80 , X86::ILD_F16m }, + { X86::ILD_Fp32m32 , X86::ILD_F32m }, + { X86::ILD_Fp32m64 , X86::ILD_F32m }, + { X86::ILD_Fp32m80 , X86::ILD_F32m }, + { X86::ILD_Fp64m32 , X86::ILD_F64m }, + { X86::ILD_Fp64m64 , X86::ILD_F64m }, + { X86::ILD_Fp64m80 , X86::ILD_F64m }, + { X86::ISTT_Fp16m32 , X86::ISTT_FP16m}, + { X86::ISTT_Fp16m64 , X86::ISTT_FP16m}, + { X86::ISTT_Fp16m80 , X86::ISTT_FP16m}, + { X86::ISTT_Fp32m32 , X86::ISTT_FP32m}, + { X86::ISTT_Fp32m64 , X86::ISTT_FP32m}, + { X86::ISTT_Fp32m80 , X86::ISTT_FP32m}, + { X86::ISTT_Fp64m32 , X86::ISTT_FP64m}, + { X86::ISTT_Fp64m64 , X86::ISTT_FP64m}, + { X86::ISTT_Fp64m80 , X86::ISTT_FP64m}, + { X86::IST_Fp16m32 , X86::IST_F16m }, + { X86::IST_Fp16m64 , X86::IST_F16m }, + { X86::IST_Fp16m80 , X86::IST_F16m }, + { X86::IST_Fp32m32 , X86::IST_F32m }, + { X86::IST_Fp32m64 , X86::IST_F32m }, + { X86::IST_Fp32m80 , X86::IST_F32m }, + { X86::IST_Fp64m32 , X86::IST_FP64m }, + { X86::IST_Fp64m64 , X86::IST_FP64m }, + { X86::IST_Fp64m80 , X86::IST_FP64m }, + { X86::LD_Fp032 , X86::LD_F0 }, + { X86::LD_Fp064 , X86::LD_F0 }, + { X86::LD_Fp080 , X86::LD_F0 }, + { X86::LD_Fp132 , X86::LD_F1 }, + { X86::LD_Fp164 , X86::LD_F1 }, + { X86::LD_Fp180 , X86::LD_F1 }, + { X86::LD_Fp32m , X86::LD_F32m }, + { X86::LD_Fp32m64 , X86::LD_F32m }, + { X86::LD_Fp32m80 , X86::LD_F32m }, + { X86::LD_Fp64m , X86::LD_F64m }, + { X86::LD_Fp64m80 , X86::LD_F64m }, + { X86::LD_Fp80m , X86::LD_F80m }, + { X86::MUL_Fp32m , X86::MUL_F32m }, + { X86::MUL_Fp64m , X86::MUL_F64m }, + { X86::MUL_Fp64m32 , X86::MUL_F32m }, + { X86::MUL_Fp80m32 , X86::MUL_F32m }, + { X86::MUL_Fp80m64 , X86::MUL_F64m }, + { X86::MUL_FpI16m32 , X86::MUL_FI16m }, + { X86::MUL_FpI16m64 , X86::MUL_FI16m }, + { X86::MUL_FpI16m80 , X86::MUL_FI16m }, + { X86::MUL_FpI32m32 , X86::MUL_FI32m }, + { X86::MUL_FpI32m64 , X86::MUL_FI32m }, + { X86::MUL_FpI32m80 , X86::MUL_FI32m }, + { X86::SIN_Fp32 , X86::SIN_F }, + { X86::SIN_Fp64 , X86::SIN_F }, + { X86::SIN_Fp80 , X86::SIN_F }, + { X86::SQRT_Fp32 , X86::SQRT_F }, + { X86::SQRT_Fp64 , X86::SQRT_F }, + { X86::SQRT_Fp80 , X86::SQRT_F }, + { X86::ST_Fp32m , X86::ST_F32m }, + { X86::ST_Fp64m , X86::ST_F64m }, + { X86::ST_Fp64m32 , X86::ST_F32m }, + { X86::ST_Fp80m32 , X86::ST_F32m }, + { X86::ST_Fp80m64 , X86::ST_F64m }, + { X86::ST_FpP80m , X86::ST_FP80m }, + { X86::SUBR_Fp32m , X86::SUBR_F32m }, + { X86::SUBR_Fp64m , X86::SUBR_F64m }, + { X86::SUBR_Fp64m32 , X86::SUBR_F32m }, + { X86::SUBR_Fp80m32 , X86::SUBR_F32m }, + { X86::SUBR_Fp80m64 , X86::SUBR_F64m }, + { X86::SUBR_FpI16m32, X86::SUBR_FI16m}, + { X86::SUBR_FpI16m64, X86::SUBR_FI16m}, + { X86::SUBR_FpI16m80, X86::SUBR_FI16m}, + { X86::SUBR_FpI32m32, X86::SUBR_FI32m}, + { X86::SUBR_FpI32m64, X86::SUBR_FI32m}, + { X86::SUBR_FpI32m80, X86::SUBR_FI32m}, + { X86::SUB_Fp32m , X86::SUB_F32m }, + { X86::SUB_Fp64m , X86::SUB_F64m }, + { X86::SUB_Fp64m32 , X86::SUB_F32m }, + { X86::SUB_Fp80m32 , X86::SUB_F32m }, + { X86::SUB_Fp80m64 , X86::SUB_F64m }, + { X86::SUB_FpI16m32 , X86::SUB_FI16m }, + { X86::SUB_FpI16m64 , X86::SUB_FI16m }, + { X86::SUB_FpI16m80 , X86::SUB_FI16m }, + { X86::SUB_FpI32m32 , X86::SUB_FI32m }, + { X86::SUB_FpI32m64 , X86::SUB_FI32m }, + { X86::SUB_FpI32m80 , X86::SUB_FI32m }, + { X86::TST_Fp32 , X86::TST_F }, + { X86::TST_Fp64 , X86::TST_F }, + { X86::TST_Fp80 , X86::TST_F }, + { X86::UCOM_FpIr32 , X86::UCOM_FIr }, + { X86::UCOM_FpIr64 , X86::UCOM_FIr }, + { X86::UCOM_FpIr80 , X86::UCOM_FIr }, + { X86::UCOM_Fpr32 , X86::UCOM_Fr }, + { X86::UCOM_Fpr64 , X86::UCOM_Fr }, + { X86::UCOM_Fpr80 , X86::UCOM_Fr }, +}; + +static unsigned getConcreteOpcode(unsigned Opcode) { + ASSERT_SORTED(OpcodeTable); + int Opc = Lookup(OpcodeTable, array_lengthof(OpcodeTable), Opcode); + assert(Opc != -1 && "FP Stack instruction not in OpcodeTable!"); + return Opc; +} + +//===----------------------------------------------------------------------===// +// Helper Methods +//===----------------------------------------------------------------------===// + +// PopTable - Sorted map of instructions to their popping version. The first +// element is an instruction, the second is the version which pops. +// +static const TableEntry PopTable[] = { + { X86::ADD_FrST0 , X86::ADD_FPrST0 }, + + { X86::DIVR_FrST0, X86::DIVR_FPrST0 }, + { X86::DIV_FrST0 , X86::DIV_FPrST0 }, + + { X86::IST_F16m , X86::IST_FP16m }, + { X86::IST_F32m , X86::IST_FP32m }, + + { X86::MUL_FrST0 , X86::MUL_FPrST0 }, + + { X86::ST_F32m , X86::ST_FP32m }, + { X86::ST_F64m , X86::ST_FP64m }, + { X86::ST_Frr , X86::ST_FPrr }, + + { X86::SUBR_FrST0, X86::SUBR_FPrST0 }, + { X86::SUB_FrST0 , X86::SUB_FPrST0 }, + + { X86::UCOM_FIr , X86::UCOM_FIPr }, + + { X86::UCOM_FPr , X86::UCOM_FPPr }, + { X86::UCOM_Fr , X86::UCOM_FPr }, +}; + +/// popStackAfter - Pop the current value off of the top of the FP stack after +/// the specified instruction. This attempts to be sneaky and combine the pop +/// into the instruction itself if possible. The iterator is left pointing to +/// the last instruction, be it a new pop instruction inserted, or the old +/// instruction if it was modified in place. +/// +void FPS::popStackAfter(MachineBasicBlock::iterator &I) { + MachineInstr* MI = I; + DebugLoc dl = MI->getDebugLoc(); + ASSERT_SORTED(PopTable); + assert(StackTop > 0 && "Cannot pop empty stack!"); + RegMap[Stack[--StackTop]] = ~0; // Update state + + // Check to see if there is a popping version of this instruction... + int Opcode = Lookup(PopTable, array_lengthof(PopTable), I->getOpcode()); + if (Opcode != -1) { + I->setDesc(TII->get(Opcode)); + if (Opcode == X86::UCOM_FPPr) + I->RemoveOperand(0); + } else { // Insert an explicit pop + I = BuildMI(*MBB, ++I, dl, TII->get(X86::ST_FPrr)).addReg(X86::ST0); + } +} + +/// freeStackSlotAfter - Free the specified register from the register stack, so +/// that it is no longer in a register. If the register is currently at the top +/// of the stack, we just pop the current instruction, otherwise we store the +/// current top-of-stack into the specified slot, then pop the top of stack. +void FPS::freeStackSlotAfter(MachineBasicBlock::iterator &I, unsigned FPRegNo) { + if (getStackEntry(0) == FPRegNo) { // already at the top of stack? easy. + popStackAfter(I); + return; + } + + // Otherwise, store the top of stack into the dead slot, killing the operand + // without having to add in an explicit xchg then pop. + // + unsigned STReg = getSTReg(FPRegNo); + unsigned OldSlot = getSlot(FPRegNo); + unsigned TopReg = Stack[StackTop-1]; + Stack[OldSlot] = TopReg; + RegMap[TopReg] = OldSlot; + RegMap[FPRegNo] = ~0; + Stack[--StackTop] = ~0; + MachineInstr *MI = I; + DebugLoc dl = MI->getDebugLoc(); + I = BuildMI(*MBB, ++I, dl, TII->get(X86::ST_FPrr)).addReg(STReg); +} + + +//===----------------------------------------------------------------------===// +// Instruction transformation implementation +//===----------------------------------------------------------------------===// + +/// handleZeroArgFP - ST(0) = fld0 ST(0) = flds +/// +void FPS::handleZeroArgFP(MachineBasicBlock::iterator &I) { + MachineInstr *MI = I; + unsigned DestReg = getFPReg(MI->getOperand(0)); + + // Change from the pseudo instruction to the concrete instruction. + MI->RemoveOperand(0); // Remove the explicit ST(0) operand + MI->setDesc(TII->get(getConcreteOpcode(MI->getOpcode()))); + + // Result gets pushed on the stack. + pushReg(DestReg); +} + +/// handleOneArgFP - fst , ST(0) +/// +void FPS::handleOneArgFP(MachineBasicBlock::iterator &I) { + MachineInstr *MI = I; + unsigned NumOps = MI->getDesc().getNumOperands(); + assert((NumOps == X86AddrNumOperands + 1 || NumOps == 1) && + "Can only handle fst* & ftst instructions!"); + + // Is this the last use of the source register? + unsigned Reg = getFPReg(MI->getOperand(NumOps-1)); + bool KillsSrc = MI->killsRegister(X86::FP0+Reg); + + // FISTP64m is strange because there isn't a non-popping versions. + // If we have one _and_ we don't want to pop the operand, duplicate the value + // on the stack instead of moving it. This ensure that popping the value is + // always ok. + // Ditto FISTTP16m, FISTTP32m, FISTTP64m, ST_FpP80m. + // + if (!KillsSrc && + (MI->getOpcode() == X86::IST_Fp64m32 || + MI->getOpcode() == X86::ISTT_Fp16m32 || + MI->getOpcode() == X86::ISTT_Fp32m32 || + MI->getOpcode() == X86::ISTT_Fp64m32 || + MI->getOpcode() == X86::IST_Fp64m64 || + MI->getOpcode() == X86::ISTT_Fp16m64 || + MI->getOpcode() == X86::ISTT_Fp32m64 || + MI->getOpcode() == X86::ISTT_Fp64m64 || + MI->getOpcode() == X86::IST_Fp64m80 || + MI->getOpcode() == X86::ISTT_Fp16m80 || + MI->getOpcode() == X86::ISTT_Fp32m80 || + MI->getOpcode() == X86::ISTT_Fp64m80 || + MI->getOpcode() == X86::ST_FpP80m)) { + duplicateToTop(Reg, 7 /*temp register*/, I); + } else { + moveToTop(Reg, I); // Move to the top of the stack... + } + + // Convert from the pseudo instruction to the concrete instruction. + MI->RemoveOperand(NumOps-1); // Remove explicit ST(0) operand + MI->setDesc(TII->get(getConcreteOpcode(MI->getOpcode()))); + + if (MI->getOpcode() == X86::IST_FP64m || + MI->getOpcode() == X86::ISTT_FP16m || + MI->getOpcode() == X86::ISTT_FP32m || + MI->getOpcode() == X86::ISTT_FP64m || + MI->getOpcode() == X86::ST_FP80m) { + assert(StackTop > 0 && "Stack empty??"); + --StackTop; + } else if (KillsSrc) { // Last use of operand? + popStackAfter(I); + } +} + + +/// handleOneArgFPRW: Handle instructions that read from the top of stack and +/// replace the value with a newly computed value. These instructions may have +/// non-fp operands after their FP operands. +/// +/// Examples: +/// R1 = fchs R2 +/// R1 = fadd R2, [mem] +/// +void FPS::handleOneArgFPRW(MachineBasicBlock::iterator &I) { + MachineInstr *MI = I; +#ifndef NDEBUG + unsigned NumOps = MI->getDesc().getNumOperands(); + assert(NumOps >= 2 && "FPRW instructions must have 2 ops!!"); +#endif + + // Is this the last use of the source register? + unsigned Reg = getFPReg(MI->getOperand(1)); + bool KillsSrc = MI->killsRegister(X86::FP0+Reg); + + if (KillsSrc) { + // If this is the last use of the source register, just make sure it's on + // the top of the stack. + moveToTop(Reg, I); + assert(StackTop > 0 && "Stack cannot be empty!"); + --StackTop; + pushReg(getFPReg(MI->getOperand(0))); + } else { + // If this is not the last use of the source register, _copy_ it to the top + // of the stack. + duplicateToTop(Reg, getFPReg(MI->getOperand(0)), I); + } + + // Change from the pseudo instruction to the concrete instruction. + MI->RemoveOperand(1); // Drop the source operand. + MI->RemoveOperand(0); // Drop the destination operand. + MI->setDesc(TII->get(getConcreteOpcode(MI->getOpcode()))); +} + + +//===----------------------------------------------------------------------===// +// Define tables of various ways to map pseudo instructions +// + +// ForwardST0Table - Map: A = B op C into: ST(0) = ST(0) op ST(i) +static const TableEntry ForwardST0Table[] = { + { X86::ADD_Fp32 , X86::ADD_FST0r }, + { X86::ADD_Fp64 , X86::ADD_FST0r }, + { X86::ADD_Fp80 , X86::ADD_FST0r }, + { X86::DIV_Fp32 , X86::DIV_FST0r }, + { X86::DIV_Fp64 , X86::DIV_FST0r }, + { X86::DIV_Fp80 , X86::DIV_FST0r }, + { X86::MUL_Fp32 , X86::MUL_FST0r }, + { X86::MUL_Fp64 , X86::MUL_FST0r }, + { X86::MUL_Fp80 , X86::MUL_FST0r }, + { X86::SUB_Fp32 , X86::SUB_FST0r }, + { X86::SUB_Fp64 , X86::SUB_FST0r }, + { X86::SUB_Fp80 , X86::SUB_FST0r }, +}; + +// ReverseST0Table - Map: A = B op C into: ST(0) = ST(i) op ST(0) +static const TableEntry ReverseST0Table[] = { + { X86::ADD_Fp32 , X86::ADD_FST0r }, // commutative + { X86::ADD_Fp64 , X86::ADD_FST0r }, // commutative + { X86::ADD_Fp80 , X86::ADD_FST0r }, // commutative + { X86::DIV_Fp32 , X86::DIVR_FST0r }, + { X86::DIV_Fp64 , X86::DIVR_FST0r }, + { X86::DIV_Fp80 , X86::DIVR_FST0r }, + { X86::MUL_Fp32 , X86::MUL_FST0r }, // commutative + { X86::MUL_Fp64 , X86::MUL_FST0r }, // commutative + { X86::MUL_Fp80 , X86::MUL_FST0r }, // commutative + { X86::SUB_Fp32 , X86::SUBR_FST0r }, + { X86::SUB_Fp64 , X86::SUBR_FST0r }, + { X86::SUB_Fp80 , X86::SUBR_FST0r }, +}; + +// ForwardSTiTable - Map: A = B op C into: ST(i) = ST(0) op ST(i) +static const TableEntry ForwardSTiTable[] = { + { X86::ADD_Fp32 , X86::ADD_FrST0 }, // commutative + { X86::ADD_Fp64 , X86::ADD_FrST0 }, // commutative + { X86::ADD_Fp80 , X86::ADD_FrST0 }, // commutative + { X86::DIV_Fp32 , X86::DIVR_FrST0 }, + { X86::DIV_Fp64 , X86::DIVR_FrST0 }, + { X86::DIV_Fp80 , X86::DIVR_FrST0 }, + { X86::MUL_Fp32 , X86::MUL_FrST0 }, // commutative + { X86::MUL_Fp64 , X86::MUL_FrST0 }, // commutative + { X86::MUL_Fp80 , X86::MUL_FrST0 }, // commutative + { X86::SUB_Fp32 , X86::SUBR_FrST0 }, + { X86::SUB_Fp64 , X86::SUBR_FrST0 }, + { X86::SUB_Fp80 , X86::SUBR_FrST0 }, +}; + +// ReverseSTiTable - Map: A = B op C into: ST(i) = ST(i) op ST(0) +static const TableEntry ReverseSTiTable[] = { + { X86::ADD_Fp32 , X86::ADD_FrST0 }, + { X86::ADD_Fp64 , X86::ADD_FrST0 }, + { X86::ADD_Fp80 , X86::ADD_FrST0 }, + { X86::DIV_Fp32 , X86::DIV_FrST0 }, + { X86::DIV_Fp64 , X86::DIV_FrST0 }, + { X86::DIV_Fp80 , X86::DIV_FrST0 }, + { X86::MUL_Fp32 , X86::MUL_FrST0 }, + { X86::MUL_Fp64 , X86::MUL_FrST0 }, + { X86::MUL_Fp80 , X86::MUL_FrST0 }, + { X86::SUB_Fp32 , X86::SUB_FrST0 }, + { X86::SUB_Fp64 , X86::SUB_FrST0 }, + { X86::SUB_Fp80 , X86::SUB_FrST0 }, +}; + + +/// handleTwoArgFP - Handle instructions like FADD and friends which are virtual +/// instructions which need to be simplified and possibly transformed. +/// +/// Result: ST(0) = fsub ST(0), ST(i) +/// ST(i) = fsub ST(0), ST(i) +/// ST(0) = fsubr ST(0), ST(i) +/// ST(i) = fsubr ST(0), ST(i) +/// +void FPS::handleTwoArgFP(MachineBasicBlock::iterator &I) { + ASSERT_SORTED(ForwardST0Table); ASSERT_SORTED(ReverseST0Table); + ASSERT_SORTED(ForwardSTiTable); ASSERT_SORTED(ReverseSTiTable); + MachineInstr *MI = I; + + unsigned NumOperands = MI->getDesc().getNumOperands(); + assert(NumOperands == 3 && "Illegal TwoArgFP instruction!"); + unsigned Dest = getFPReg(MI->getOperand(0)); + unsigned Op0 = getFPReg(MI->getOperand(NumOperands-2)); + unsigned Op1 = getFPReg(MI->getOperand(NumOperands-1)); + bool KillsOp0 = MI->killsRegister(X86::FP0+Op0); + bool KillsOp1 = MI->killsRegister(X86::FP0+Op1); + DebugLoc dl = MI->getDebugLoc(); + + unsigned TOS = getStackEntry(0); + + // One of our operands must be on the top of the stack. If neither is yet, we + // need to move one. + if (Op0 != TOS && Op1 != TOS) { // No operand at TOS? + // We can choose to move either operand to the top of the stack. If one of + // the operands is killed by this instruction, we want that one so that we + // can update right on top of the old version. + if (KillsOp0) { + moveToTop(Op0, I); // Move dead operand to TOS. + TOS = Op0; + } else if (KillsOp1) { + moveToTop(Op1, I); + TOS = Op1; + } else { + // All of the operands are live after this instruction executes, so we + // cannot update on top of any operand. Because of this, we must + // duplicate one of the stack elements to the top. It doesn't matter + // which one we pick. + // + duplicateToTop(Op0, Dest, I); + Op0 = TOS = Dest; + KillsOp0 = true; + } + } else if (!KillsOp0 && !KillsOp1) { + // If we DO have one of our operands at the top of the stack, but we don't + // have a dead operand, we must duplicate one of the operands to a new slot + // on the stack. + duplicateToTop(Op0, Dest, I); + Op0 = TOS = Dest; + KillsOp0 = true; + } + + // Now we know that one of our operands is on the top of the stack, and at + // least one of our operands is killed by this instruction. + assert((TOS == Op0 || TOS == Op1) && (KillsOp0 || KillsOp1) && + "Stack conditions not set up right!"); + + // We decide which form to use based on what is on the top of the stack, and + // which operand is killed by this instruction. + const TableEntry *InstTable; + bool isForward = TOS == Op0; + bool updateST0 = (TOS == Op0 && !KillsOp1) || (TOS == Op1 && !KillsOp0); + if (updateST0) { + if (isForward) + InstTable = ForwardST0Table; + else + InstTable = ReverseST0Table; + } else { + if (isForward) + InstTable = ForwardSTiTable; + else + InstTable = ReverseSTiTable; + } + + int Opcode = Lookup(InstTable, array_lengthof(ForwardST0Table), + MI->getOpcode()); + assert(Opcode != -1 && "Unknown TwoArgFP pseudo instruction!"); + + // NotTOS - The register which is not on the top of stack... + unsigned NotTOS = (TOS == Op0) ? Op1 : Op0; + + // Replace the old instruction with a new instruction + MBB->remove(I++); + I = BuildMI(*MBB, I, dl, TII->get(Opcode)).addReg(getSTReg(NotTOS)); + + // If both operands are killed, pop one off of the stack in addition to + // overwriting the other one. + if (KillsOp0 && KillsOp1 && Op0 != Op1) { + assert(!updateST0 && "Should have updated other operand!"); + popStackAfter(I); // Pop the top of stack + } + + // Update stack information so that we know the destination register is now on + // the stack. + unsigned UpdatedSlot = getSlot(updateST0 ? TOS : NotTOS); + assert(UpdatedSlot < StackTop && Dest < 7); + Stack[UpdatedSlot] = Dest; + RegMap[Dest] = UpdatedSlot; + MBB->getParent()->DeleteMachineInstr(MI); // Remove the old instruction +} + +/// handleCompareFP - Handle FUCOM and FUCOMI instructions, which have two FP +/// register arguments and no explicit destinations. +/// +void FPS::handleCompareFP(MachineBasicBlock::iterator &I) { + ASSERT_SORTED(ForwardST0Table); ASSERT_SORTED(ReverseST0Table); + ASSERT_SORTED(ForwardSTiTable); ASSERT_SORTED(ReverseSTiTable); + MachineInstr *MI = I; + + unsigned NumOperands = MI->getDesc().getNumOperands(); + assert(NumOperands == 2 && "Illegal FUCOM* instruction!"); + unsigned Op0 = getFPReg(MI->getOperand(NumOperands-2)); + unsigned Op1 = getFPReg(MI->getOperand(NumOperands-1)); + bool KillsOp0 = MI->killsRegister(X86::FP0+Op0); + bool KillsOp1 = MI->killsRegister(X86::FP0+Op1); + + // Make sure the first operand is on the top of stack, the other one can be + // anywhere. + moveToTop(Op0, I); + + // Change from the pseudo instruction to the concrete instruction. + MI->getOperand(0).setReg(getSTReg(Op1)); + MI->RemoveOperand(1); + MI->setDesc(TII->get(getConcreteOpcode(MI->getOpcode()))); + + // If any of the operands are killed by this instruction, free them. + if (KillsOp0) freeStackSlotAfter(I, Op0); + if (KillsOp1 && Op0 != Op1) freeStackSlotAfter(I, Op1); +} + +/// handleCondMovFP - Handle two address conditional move instructions. These +/// instructions move a st(i) register to st(0) iff a condition is true. These +/// instructions require that the first operand is at the top of the stack, but +/// otherwise don't modify the stack at all. +void FPS::handleCondMovFP(MachineBasicBlock::iterator &I) { + MachineInstr *MI = I; + + unsigned Op0 = getFPReg(MI->getOperand(0)); + unsigned Op1 = getFPReg(MI->getOperand(2)); + bool KillsOp1 = MI->killsRegister(X86::FP0+Op1); + + // The first operand *must* be on the top of the stack. + moveToTop(Op0, I); + + // Change the second operand to the stack register that the operand is in. + // Change from the pseudo instruction to the concrete instruction. + MI->RemoveOperand(0); + MI->RemoveOperand(1); + MI->getOperand(0).setReg(getSTReg(Op1)); + MI->setDesc(TII->get(getConcreteOpcode(MI->getOpcode()))); + + // If we kill the second operand, make sure to pop it from the stack. + if (Op0 != Op1 && KillsOp1) { + // Get this value off of the register stack. + freeStackSlotAfter(I, Op1); + } +} + + +/// handleSpecialFP - Handle special instructions which behave unlike other +/// floating point instructions. This is primarily intended for use by pseudo +/// instructions. +/// +void FPS::handleSpecialFP(MachineBasicBlock::iterator &I) { + MachineInstr *MI = I; + DebugLoc dl = MI->getDebugLoc(); + switch (MI->getOpcode()) { + default: llvm_unreachable("Unknown SpecialFP instruction!"); + case X86::FpGET_ST0_32:// Appears immediately after a call returning FP type! + case X86::FpGET_ST0_64:// Appears immediately after a call returning FP type! + case X86::FpGET_ST0_80:// Appears immediately after a call returning FP type! + assert(StackTop == 0 && "Stack should be empty after a call!"); + pushReg(getFPReg(MI->getOperand(0))); + break; + case X86::FpGET_ST1_32:// Appears immediately after a call returning FP type! + case X86::FpGET_ST1_64:// Appears immediately after a call returning FP type! + case X86::FpGET_ST1_80:{// Appears immediately after a call returning FP type! + // FpGET_ST1 should occur right after a FpGET_ST0 for a call or inline asm. + // The pattern we expect is: + // CALL + // FP1 = FpGET_ST0 + // FP4 = FpGET_ST1 + // + // At this point, we've pushed FP1 on the top of stack, so it should be + // present if it isn't dead. If it was dead, we already emitted a pop to + // remove it from the stack and StackTop = 0. + + // Push FP4 as top of stack next. + pushReg(getFPReg(MI->getOperand(0))); + + // If StackTop was 0 before we pushed our operand, then ST(0) must have been + // dead. In this case, the ST(1) value is the only thing that is live, so + // it should be on the TOS (after the pop that was emitted) and is. Just + // continue in this case. + if (StackTop == 1) + break; + + // Because pushReg just pushed ST(1) as TOS, we now have to swap the two top + // elements so that our accounting is correct. + unsigned RegOnTop = getStackEntry(0); + unsigned RegNo = getStackEntry(1); + + // Swap the slots the regs are in. + std::swap(RegMap[RegNo], RegMap[RegOnTop]); + + // Swap stack slot contents. + assert(RegMap[RegOnTop] < StackTop); + std::swap(Stack[RegMap[RegOnTop]], Stack[StackTop-1]); + break; + } + case X86::FpSET_ST0_32: + case X86::FpSET_ST0_64: + case X86::FpSET_ST0_80: { + unsigned Op0 = getFPReg(MI->getOperand(0)); + + // FpSET_ST0_80 is generated by copyRegToReg for both function return + // and inline assembly with the "st" constrain. In the latter case, + // it is possible for ST(0) to be alive after this instruction. + if (!MI->killsRegister(X86::FP0 + Op0)) { + // Duplicate Op0 + duplicateToTop(0, 7 /*temp register*/, I); + } else { + moveToTop(Op0, I); + } + --StackTop; // "Forget" we have something on the top of stack! + break; + } + case X86::FpSET_ST1_32: + case X86::FpSET_ST1_64: + case X86::FpSET_ST1_80: + // StackTop can be 1 if a FpSET_ST0_* was before this. Exchange them. + if (StackTop == 1) { + BuildMI(*MBB, I, dl, TII->get(X86::XCH_F)).addReg(X86::ST1); + NumFXCH++; + StackTop = 0; + break; + } + assert(StackTop == 2 && "Stack should have two element on it to return!"); + --StackTop; // "Forget" we have something on the top of stack! + break; + case X86::MOV_Fp3232: + case X86::MOV_Fp3264: + case X86::MOV_Fp6432: + case X86::MOV_Fp6464: + case X86::MOV_Fp3280: + case X86::MOV_Fp6480: + case X86::MOV_Fp8032: + case X86::MOV_Fp8064: + case X86::MOV_Fp8080: { + const MachineOperand &MO1 = MI->getOperand(1); + unsigned SrcReg = getFPReg(MO1); + + const MachineOperand &MO0 = MI->getOperand(0); + // These can be created due to inline asm. Two address pass can introduce + // copies from RFP registers to virtual registers. + if (MO0.getReg() == X86::ST0 && SrcReg == 0) { + assert(MO1.isKill()); + // Treat %ST0 = MOV_Fp8080 %FP0 + // like FpSET_ST0_80 %FP0, %ST0 + assert((StackTop == 1 || StackTop == 2) + && "Stack should have one or two element on it to return!"); + --StackTop; // "Forget" we have something on the top of stack! + break; + } else if (MO0.getReg() == X86::ST1 && SrcReg == 1) { + assert(MO1.isKill()); + // Treat %ST1 = MOV_Fp8080 %FP1 + // like FpSET_ST1_80 %FP0, %ST1 + // StackTop can be 1 if a FpSET_ST0_* was before this. Exchange them. + if (StackTop == 1) { + BuildMI(*MBB, I, dl, TII->get(X86::XCH_F)).addReg(X86::ST1); + NumFXCH++; + StackTop = 0; + break; + } + assert(StackTop == 2 && "Stack should have two element on it to return!"); + --StackTop; // "Forget" we have something on the top of stack! + break; + } + + unsigned DestReg = getFPReg(MO0); + if (MI->killsRegister(X86::FP0+SrcReg)) { + // If the input operand is killed, we can just change the owner of the + // incoming stack slot into the result. + unsigned Slot = getSlot(SrcReg); + assert(Slot < 7 && DestReg < 7 && "FpMOV operands invalid!"); + Stack[Slot] = DestReg; + RegMap[DestReg] = Slot; + + } else { + // For FMOV we just duplicate the specified value to a new stack slot. + // This could be made better, but would require substantial changes. + duplicateToTop(SrcReg, DestReg, I); + } + } + break; + case TargetInstrInfo::INLINEASM: { + // The inline asm MachineInstr currently only *uses* FP registers for the + // 'f' constraint. These should be turned into the current ST(x) register + // in the machine instr. Also, any kills should be explicitly popped after + // the inline asm. + unsigned Kills[7]; + unsigned NumKills = 0; + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + MachineOperand &Op = MI->getOperand(i); + if (!Op.isReg() || Op.getReg() < X86::FP0 || Op.getReg() > X86::FP6) + continue; + assert(Op.isUse() && "Only handle inline asm uses right now"); + + unsigned FPReg = getFPReg(Op); + Op.setReg(getSTReg(FPReg)); + + // If we kill this operand, make sure to pop it from the stack after the + // asm. We just remember it for now, and pop them all off at the end in + // a batch. + if (Op.isKill()) + Kills[NumKills++] = FPReg; + } + + // If this asm kills any FP registers (is the last use of them) we must + // explicitly emit pop instructions for them. Do this now after the asm has + // executed so that the ST(x) numbers are not off (which would happen if we + // did this inline with operand rewriting). + // + // Note: this might be a non-optimal pop sequence. We might be able to do + // better by trying to pop in stack order or something. + MachineBasicBlock::iterator InsertPt = MI; + while (NumKills) + freeStackSlotAfter(InsertPt, Kills[--NumKills]); + + // Don't delete the inline asm! + return; + } + + case X86::RET: + case X86::RETI: + // If RET has an FP register use operand, pass the first one in ST(0) and + // the second one in ST(1). + if (isStackEmpty()) return; // Quick check to see if any are possible. + + // Find the register operands. + unsigned FirstFPRegOp = ~0U, SecondFPRegOp = ~0U; + + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + MachineOperand &Op = MI->getOperand(i); + if (!Op.isReg() || Op.getReg() < X86::FP0 || Op.getReg() > X86::FP6) + continue; + // FP Register uses must be kills unless there are two uses of the same + // register, in which case only one will be a kill. + assert(Op.isUse() && + (Op.isKill() || // Marked kill. + getFPReg(Op) == FirstFPRegOp || // Second instance. + MI->killsRegister(Op.getReg())) && // Later use is marked kill. + "Ret only defs operands, and values aren't live beyond it"); + + if (FirstFPRegOp == ~0U) + FirstFPRegOp = getFPReg(Op); + else { + assert(SecondFPRegOp == ~0U && "More than two fp operands!"); + SecondFPRegOp = getFPReg(Op); + } + + // Remove the operand so that later passes don't see it. + MI->RemoveOperand(i); + --i, --e; + } + + // There are only four possibilities here: + // 1) we are returning a single FP value. In this case, it has to be in + // ST(0) already, so just declare success by removing the value from the + // FP Stack. + if (SecondFPRegOp == ~0U) { + // Assert that the top of stack contains the right FP register. + assert(StackTop == 1 && FirstFPRegOp == getStackEntry(0) && + "Top of stack not the right register for RET!"); + + // Ok, everything is good, mark the value as not being on the stack + // anymore so that our assertion about the stack being empty at end of + // block doesn't fire. + StackTop = 0; + return; + } + + // Otherwise, we are returning two values: + // 2) If returning the same value for both, we only have one thing in the FP + // stack. Consider: RET FP1, FP1 + if (StackTop == 1) { + assert(FirstFPRegOp == SecondFPRegOp && FirstFPRegOp == getStackEntry(0)&& + "Stack misconfiguration for RET!"); + + // Duplicate the TOS so that we return it twice. Just pick some other FPx + // register to hold it. + unsigned NewReg = (FirstFPRegOp+1)%7; + duplicateToTop(FirstFPRegOp, NewReg, MI); + FirstFPRegOp = NewReg; + } + + /// Okay we know we have two different FPx operands now: + assert(StackTop == 2 && "Must have two values live!"); + + /// 3) If SecondFPRegOp is currently in ST(0) and FirstFPRegOp is currently + /// in ST(1). In this case, emit an fxch. + if (getStackEntry(0) == SecondFPRegOp) { + assert(getStackEntry(1) == FirstFPRegOp && "Unknown regs live"); + moveToTop(FirstFPRegOp, MI); + } + + /// 4) Finally, FirstFPRegOp must be in ST(0) and SecondFPRegOp must be in + /// ST(1). Just remove both from our understanding of the stack and return. + assert(getStackEntry(0) == FirstFPRegOp && "Unknown regs live"); + assert(getStackEntry(1) == SecondFPRegOp && "Unknown regs live"); + StackTop = 0; + return; + } + + I = MBB->erase(I); // Remove the pseudo instruction + --I; +} diff --git a/libclamav/c++/llvm/lib/Target/X86/X86FloatingPointRegKill.cpp b/libclamav/c++/llvm/lib/Target/X86/X86FloatingPointRegKill.cpp new file mode 100644 index 000000000..34a004534 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/X86/X86FloatingPointRegKill.cpp @@ -0,0 +1,140 @@ +//===-- X86FloatingPoint.cpp - FP_REG_KILL inserter -----------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the pass which inserts FP_REG_KILL instructions. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "x86-codegen" +#include "X86.h" +#include "X86InstrInfo.h" +#include "X86Subtarget.h" +#include "llvm/Instructions.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/CFG.h" +#include "llvm/ADT/Statistic.h" +using namespace llvm; + +STATISTIC(NumFPKill, "Number of FP_REG_KILL instructions added"); + +namespace { + struct FPRegKiller : public MachineFunctionPass { + static char ID; + FPRegKiller() : MachineFunctionPass(&ID) {} + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesCFG(); + AU.addPreservedID(MachineLoopInfoID); + AU.addPreservedID(MachineDominatorsID); + MachineFunctionPass::getAnalysisUsage(AU); + } + + virtual bool runOnMachineFunction(MachineFunction &MF); + + virtual const char *getPassName() const { return "X86 FP_REG_KILL inserter"; } + }; + char FPRegKiller::ID = 0; +} + +FunctionPass *llvm::createX87FPRegKillInserterPass() { return new FPRegKiller(); } + +bool FPRegKiller::runOnMachineFunction(MachineFunction &MF) { + // If we are emitting FP stack code, scan the basic block to determine if this + // block defines any FP values. If so, put an FP_REG_KILL instruction before + // the terminator of the block. + + // Note that FP stack instructions are used in all modes for long double, + // so we always need to do this check. + // Also note that it's possible for an FP stack register to be live across + // an instruction that produces multiple basic blocks (SSE CMOV) so we + // must check all the generated basic blocks. + + // Scan all of the machine instructions in these MBBs, checking for FP + // stores. (RFP32 and RFP64 will not exist in SSE mode, but RFP80 might.) + + // Fast-path: If nothing is using the x87 registers, we don't need to do + // any scanning. + MachineRegisterInfo &MRI = MF.getRegInfo(); + if (MRI.getRegClassVirtRegs(X86::RFP80RegisterClass).empty() && + MRI.getRegClassVirtRegs(X86::RFP64RegisterClass).empty() && + MRI.getRegClassVirtRegs(X86::RFP32RegisterClass).empty()) + return false; + + bool Changed = false; + const X86Subtarget &Subtarget = MF.getTarget().getSubtarget(); + MachineFunction::iterator MBBI = MF.begin(); + MachineFunction::iterator EndMBB = MF.end(); + for (; MBBI != EndMBB; ++MBBI) { + MachineBasicBlock *MBB = MBBI; + + // If this block returns, ignore it. We don't want to insert an FP_REG_KILL + // before the return. + if (!MBB->empty()) { + MachineBasicBlock::iterator EndI = MBB->end(); + --EndI; + if (EndI->getDesc().isReturn()) + continue; + } + + bool ContainsFPCode = false; + for (MachineBasicBlock::iterator I = MBB->begin(), E = MBB->end(); + !ContainsFPCode && I != E; ++I) { + if (I->getNumOperands() != 0 && I->getOperand(0).isReg()) { + const TargetRegisterClass *clas; + for (unsigned op = 0, e = I->getNumOperands(); op != e; ++op) { + if (I->getOperand(op).isReg() && I->getOperand(op).isDef() && + TargetRegisterInfo::isVirtualRegister(I->getOperand(op).getReg()) && + ((clas = MRI.getRegClass(I->getOperand(op).getReg())) == + X86::RFP32RegisterClass || + clas == X86::RFP64RegisterClass || + clas == X86::RFP80RegisterClass)) { + ContainsFPCode = true; + break; + } + } + } + } + // Check PHI nodes in successor blocks. These PHI's will be lowered to have + // a copy of the input value in this block. In SSE mode, we only care about + // 80-bit values. + if (!ContainsFPCode) { + // Final check, check LLVM BB's that are successors to the LLVM BB + // corresponding to BB for FP PHI nodes. + const BasicBlock *LLVMBB = MBB->getBasicBlock(); + const PHINode *PN; + for (succ_const_iterator SI = succ_begin(LLVMBB), E = succ_end(LLVMBB); + !ContainsFPCode && SI != E; ++SI) { + for (BasicBlock::const_iterator II = SI->begin(); + (PN = dyn_cast(II)); ++II) { + if (PN->getType()==Type::getX86_FP80Ty(LLVMBB->getContext()) || + (!Subtarget.hasSSE1() && PN->getType()->isFloatingPoint()) || + (!Subtarget.hasSSE2() && + PN->getType()==Type::getDoubleTy(LLVMBB->getContext()))) { + ContainsFPCode = true; + break; + } + } + } + } + // Finally, if we found any FP code, emit the FP_REG_KILL instruction. + if (ContainsFPCode) { + BuildMI(*MBB, MBBI->getFirstTerminator(), DebugLoc::getUnknownLoc(), + MF.getTarget().getInstrInfo()->get(X86::FP_REG_KILL)); + ++NumFPKill; + Changed = true; + } + } + + return Changed; +} diff --git a/libclamav/c++/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp b/libclamav/c++/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp new file mode 100644 index 000000000..a9a78be3e --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp @@ -0,0 +1,2195 @@ +//===- X86ISelDAGToDAG.cpp - A DAG pattern matching inst selector for X86 -===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines a DAG pattern matching instruction selector for X86, +// converting from a legalized dag to a X86 dag. +// +//===----------------------------------------------------------------------===// + +// Force NDEBUG on in any optimized build on Darwin. +// +// FIXME: This is a huge hack, to work around ridiculously awful compile times +// on this file with gcc-4.2 on Darwin, in Release mode. +#if (!defined(__llvm__) && defined(__APPLE__) && \ + defined(__OPTIMIZE__) && !defined(NDEBUG)) +#define NDEBUG +#endif + +#define DEBUG_TYPE "x86-isel" +#include "X86.h" +#include "X86InstrBuilder.h" +#include "X86ISelLowering.h" +#include "X86MachineFunctionInfo.h" +#include "X86RegisterInfo.h" +#include "X86Subtarget.h" +#include "X86TargetMachine.h" +#include "llvm/GlobalValue.h" +#include "llvm/Instructions.h" +#include "llvm/Intrinsics.h" +#include "llvm/Support/CFG.h" +#include "llvm/Type.h" +#include "llvm/CodeGen/MachineConstantPool.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/SelectionDAGISel.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetOptions.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/Statistic.h" +using namespace llvm; + +#include "llvm/Support/CommandLine.h" +static cl::opt AvoidDupAddrCompute("x86-avoid-dup-address", cl::Hidden); + +STATISTIC(NumLoadMoved, "Number of loads moved below TokenFactor"); + +//===----------------------------------------------------------------------===// +// Pattern Matcher Implementation +//===----------------------------------------------------------------------===// + +namespace { + /// X86ISelAddressMode - This corresponds to X86AddressMode, but uses + /// SDValue's instead of register numbers for the leaves of the matched + /// tree. + struct X86ISelAddressMode { + enum { + RegBase, + FrameIndexBase + } BaseType; + + struct { // This is really a union, discriminated by BaseType! + SDValue Reg; + int FrameIndex; + } Base; + + unsigned Scale; + SDValue IndexReg; + int32_t Disp; + SDValue Segment; + GlobalValue *GV; + Constant *CP; + BlockAddress *BlockAddr; + const char *ES; + int JT; + unsigned Align; // CP alignment. + unsigned char SymbolFlags; // X86II::MO_* + + X86ISelAddressMode() + : BaseType(RegBase), Scale(1), IndexReg(), Disp(0), + Segment(), GV(0), CP(0), BlockAddr(0), ES(0), JT(-1), Align(0), + SymbolFlags(X86II::MO_NO_FLAG) { + } + + bool hasSymbolicDisplacement() const { + return GV != 0 || CP != 0 || ES != 0 || JT != -1 || BlockAddr != 0; + } + + bool hasBaseOrIndexReg() const { + return IndexReg.getNode() != 0 || Base.Reg.getNode() != 0; + } + + /// isRIPRelative - Return true if this addressing mode is already RIP + /// relative. + bool isRIPRelative() const { + if (BaseType != RegBase) return false; + if (RegisterSDNode *RegNode = + dyn_cast_or_null(Base.Reg.getNode())) + return RegNode->getReg() == X86::RIP; + return false; + } + + void setBaseReg(SDValue Reg) { + BaseType = RegBase; + Base.Reg = Reg; + } + + void dump() { + errs() << "X86ISelAddressMode " << this << '\n'; + errs() << "Base.Reg "; + if (Base.Reg.getNode() != 0) + Base.Reg.getNode()->dump(); + else + errs() << "nul"; + errs() << " Base.FrameIndex " << Base.FrameIndex << '\n' + << " Scale" << Scale << '\n' + << "IndexReg "; + if (IndexReg.getNode() != 0) + IndexReg.getNode()->dump(); + else + errs() << "nul"; + errs() << " Disp " << Disp << '\n' + << "GV "; + if (GV) + GV->dump(); + else + errs() << "nul"; + errs() << " CP "; + if (CP) + CP->dump(); + else + errs() << "nul"; + errs() << '\n' + << "ES "; + if (ES) + errs() << ES; + else + errs() << "nul"; + errs() << " JT" << JT << " Align" << Align << '\n'; + } + }; +} + +namespace { + //===--------------------------------------------------------------------===// + /// ISel - X86 specific code to select X86 machine instructions for + /// SelectionDAG operations. + /// + class X86DAGToDAGISel : public SelectionDAGISel { + /// X86Lowering - This object fully describes how to lower LLVM code to an + /// X86-specific SelectionDAG. + X86TargetLowering &X86Lowering; + + /// Subtarget - Keep a pointer to the X86Subtarget around so that we can + /// make the right decision when generating code for different targets. + const X86Subtarget *Subtarget; + + /// OptForSize - If true, selector should try to optimize for code size + /// instead of performance. + bool OptForSize; + + public: + explicit X86DAGToDAGISel(X86TargetMachine &tm, CodeGenOpt::Level OptLevel) + : SelectionDAGISel(tm, OptLevel), + X86Lowering(*tm.getTargetLowering()), + Subtarget(&tm.getSubtarget()), + OptForSize(false) {} + + virtual const char *getPassName() const { + return "X86 DAG->DAG Instruction Selection"; + } + + /// InstructionSelect - This callback is invoked by + /// SelectionDAGISel when it has created a SelectionDAG for us to codegen. + virtual void InstructionSelect(); + + virtual void EmitFunctionEntryCode(Function &Fn, MachineFunction &MF); + + virtual + bool IsLegalAndProfitableToFold(SDNode *N, SDNode *U, SDNode *Root) const; + +// Include the pieces autogenerated from the target description. +#include "X86GenDAGISel.inc" + + private: + SDNode *Select(SDValue N); + SDNode *SelectAtomic64(SDNode *Node, unsigned Opc); + SDNode *SelectAtomicLoadAdd(SDNode *Node, EVT NVT); + + bool MatchSegmentBaseAddress(SDValue N, X86ISelAddressMode &AM); + bool MatchLoad(SDValue N, X86ISelAddressMode &AM); + bool MatchWrapper(SDValue N, X86ISelAddressMode &AM); + bool MatchAddress(SDValue N, X86ISelAddressMode &AM); + bool MatchAddressRecursively(SDValue N, X86ISelAddressMode &AM, + unsigned Depth); + bool MatchAddressBase(SDValue N, X86ISelAddressMode &AM); + bool SelectAddr(SDValue Op, SDValue N, SDValue &Base, + SDValue &Scale, SDValue &Index, SDValue &Disp, + SDValue &Segment); + bool SelectLEAAddr(SDValue Op, SDValue N, SDValue &Base, + SDValue &Scale, SDValue &Index, SDValue &Disp); + bool SelectTLSADDRAddr(SDValue Op, SDValue N, SDValue &Base, + SDValue &Scale, SDValue &Index, SDValue &Disp); + bool SelectScalarSSELoad(SDValue Op, SDValue Pred, + SDValue N, SDValue &Base, SDValue &Scale, + SDValue &Index, SDValue &Disp, + SDValue &Segment, + SDValue &InChain, SDValue &OutChain); + bool TryFoldLoad(SDValue P, SDValue N, + SDValue &Base, SDValue &Scale, + SDValue &Index, SDValue &Disp, + SDValue &Segment); + void PreprocessForRMW(); + void PreprocessForFPConvert(); + + /// SelectInlineAsmMemoryOperand - Implement addressing mode selection for + /// inline asm expressions. + virtual bool SelectInlineAsmMemoryOperand(const SDValue &Op, + char ConstraintCode, + std::vector &OutOps); + + void EmitSpecialCodeForMain(MachineBasicBlock *BB, MachineFrameInfo *MFI); + + inline void getAddressOperands(X86ISelAddressMode &AM, SDValue &Base, + SDValue &Scale, SDValue &Index, + SDValue &Disp, SDValue &Segment) { + Base = (AM.BaseType == X86ISelAddressMode::FrameIndexBase) ? + CurDAG->getTargetFrameIndex(AM.Base.FrameIndex, TLI.getPointerTy()) : + AM.Base.Reg; + Scale = getI8Imm(AM.Scale); + Index = AM.IndexReg; + // These are 32-bit even in 64-bit mode since RIP relative offset + // is 32-bit. + if (AM.GV) + Disp = CurDAG->getTargetGlobalAddress(AM.GV, MVT::i32, AM.Disp, + AM.SymbolFlags); + else if (AM.CP) + Disp = CurDAG->getTargetConstantPool(AM.CP, MVT::i32, + AM.Align, AM.Disp, AM.SymbolFlags); + else if (AM.ES) + Disp = CurDAG->getTargetExternalSymbol(AM.ES, MVT::i32, AM.SymbolFlags); + else if (AM.JT != -1) + Disp = CurDAG->getTargetJumpTable(AM.JT, MVT::i32, AM.SymbolFlags); + else if (AM.BlockAddr) + Disp = CurDAG->getBlockAddress(AM.BlockAddr, MVT::i32, + true, AM.SymbolFlags); + else + Disp = CurDAG->getTargetConstant(AM.Disp, MVT::i32); + + if (AM.Segment.getNode()) + Segment = AM.Segment; + else + Segment = CurDAG->getRegister(0, MVT::i32); + } + + /// getI8Imm - Return a target constant with the specified value, of type + /// i8. + inline SDValue getI8Imm(unsigned Imm) { + return CurDAG->getTargetConstant(Imm, MVT::i8); + } + + /// getI16Imm - Return a target constant with the specified value, of type + /// i16. + inline SDValue getI16Imm(unsigned Imm) { + return CurDAG->getTargetConstant(Imm, MVT::i16); + } + + /// getI32Imm - Return a target constant with the specified value, of type + /// i32. + inline SDValue getI32Imm(unsigned Imm) { + return CurDAG->getTargetConstant(Imm, MVT::i32); + } + + /// getGlobalBaseReg - Return an SDNode that returns the value of + /// the global base register. Output instructions required to + /// initialize the global base register, if necessary. + /// + SDNode *getGlobalBaseReg(); + + /// getTargetMachine - Return a reference to the TargetMachine, casted + /// to the target-specific type. + const X86TargetMachine &getTargetMachine() { + return static_cast(TM); + } + + /// getInstrInfo - Return a reference to the TargetInstrInfo, casted + /// to the target-specific type. + const X86InstrInfo *getInstrInfo() { + return getTargetMachine().getInstrInfo(); + } + +#ifndef NDEBUG + unsigned Indent; +#endif + }; +} + + +bool X86DAGToDAGISel::IsLegalAndProfitableToFold(SDNode *N, SDNode *U, + SDNode *Root) const { + if (OptLevel == CodeGenOpt::None) return false; + + if (U == Root) + switch (U->getOpcode()) { + default: break; + case ISD::ADD: + case ISD::ADDC: + case ISD::ADDE: + case ISD::AND: + case ISD::OR: + case ISD::XOR: { + SDValue Op1 = U->getOperand(1); + + // If the other operand is a 8-bit immediate we should fold the immediate + // instead. This reduces code size. + // e.g. + // movl 4(%esp), %eax + // addl $4, %eax + // vs. + // movl $4, %eax + // addl 4(%esp), %eax + // The former is 2 bytes shorter. In case where the increment is 1, then + // the saving can be 4 bytes (by using incl %eax). + if (ConstantSDNode *Imm = dyn_cast(Op1)) + if (Imm->getAPIntValue().isSignedIntN(8)) + return false; + + // If the other operand is a TLS address, we should fold it instead. + // This produces + // movl %gs:0, %eax + // leal i@NTPOFF(%eax), %eax + // instead of + // movl $i@NTPOFF, %eax + // addl %gs:0, %eax + // if the block also has an access to a second TLS address this will save + // a load. + // FIXME: This is probably also true for non TLS addresses. + if (Op1.getOpcode() == X86ISD::Wrapper) { + SDValue Val = Op1.getOperand(0); + if (Val.getOpcode() == ISD::TargetGlobalTLSAddress) + return false; + } + } + } + + // Proceed to 'generic' cycle finder code + return SelectionDAGISel::IsLegalAndProfitableToFold(N, U, Root); +} + +/// MoveBelowTokenFactor - Replace TokenFactor operand with load's chain operand +/// and move load below the TokenFactor. Replace store's chain operand with +/// load's chain result. +static void MoveBelowTokenFactor(SelectionDAG *CurDAG, SDValue Load, + SDValue Store, SDValue TF) { + SmallVector Ops; + for (unsigned i = 0, e = TF.getNode()->getNumOperands(); i != e; ++i) + if (Load.getNode() == TF.getOperand(i).getNode()) + Ops.push_back(Load.getOperand(0)); + else + Ops.push_back(TF.getOperand(i)); + SDValue NewTF = CurDAG->UpdateNodeOperands(TF, &Ops[0], Ops.size()); + SDValue NewLoad = CurDAG->UpdateNodeOperands(Load, NewTF, + Load.getOperand(1), + Load.getOperand(2)); + CurDAG->UpdateNodeOperands(Store, NewLoad.getValue(1), Store.getOperand(1), + Store.getOperand(2), Store.getOperand(3)); +} + +/// isRMWLoad - Return true if N is a load that's part of RMW sub-DAG. The +/// chain produced by the load must only be used by the store's chain operand, +/// otherwise this may produce a cycle in the DAG. +/// +static bool isRMWLoad(SDValue N, SDValue Chain, SDValue Address, + SDValue &Load) { + if (N.getOpcode() == ISD::BIT_CONVERT) + N = N.getOperand(0); + + LoadSDNode *LD = dyn_cast(N); + if (!LD || LD->isVolatile()) + return false; + if (LD->getAddressingMode() != ISD::UNINDEXED) + return false; + + ISD::LoadExtType ExtType = LD->getExtensionType(); + if (ExtType != ISD::NON_EXTLOAD && ExtType != ISD::EXTLOAD) + return false; + + if (N.hasOneUse() && + LD->hasNUsesOfValue(1, 1) && + N.getOperand(1) == Address && + LD->isOperandOf(Chain.getNode())) { + Load = N; + return true; + } + return false; +} + +/// MoveBelowCallSeqStart - Replace CALLSEQ_START operand with load's chain +/// operand and move load below the call's chain operand. +static void MoveBelowCallSeqStart(SelectionDAG *CurDAG, SDValue Load, + SDValue Call, SDValue CallSeqStart) { + SmallVector Ops; + SDValue Chain = CallSeqStart.getOperand(0); + if (Chain.getNode() == Load.getNode()) + Ops.push_back(Load.getOperand(0)); + else { + assert(Chain.getOpcode() == ISD::TokenFactor && + "Unexpected CallSeqStart chain operand"); + for (unsigned i = 0, e = Chain.getNumOperands(); i != e; ++i) + if (Chain.getOperand(i).getNode() == Load.getNode()) + Ops.push_back(Load.getOperand(0)); + else + Ops.push_back(Chain.getOperand(i)); + SDValue NewChain = + CurDAG->getNode(ISD::TokenFactor, Load.getDebugLoc(), + MVT::Other, &Ops[0], Ops.size()); + Ops.clear(); + Ops.push_back(NewChain); + } + for (unsigned i = 1, e = CallSeqStart.getNumOperands(); i != e; ++i) + Ops.push_back(CallSeqStart.getOperand(i)); + CurDAG->UpdateNodeOperands(CallSeqStart, &Ops[0], Ops.size()); + CurDAG->UpdateNodeOperands(Load, Call.getOperand(0), + Load.getOperand(1), Load.getOperand(2)); + Ops.clear(); + Ops.push_back(SDValue(Load.getNode(), 1)); + for (unsigned i = 1, e = Call.getNode()->getNumOperands(); i != e; ++i) + Ops.push_back(Call.getOperand(i)); + CurDAG->UpdateNodeOperands(Call, &Ops[0], Ops.size()); +} + +/// isCalleeLoad - Return true if call address is a load and it can be +/// moved below CALLSEQ_START and the chains leading up to the call. +/// Return the CALLSEQ_START by reference as a second output. +static bool isCalleeLoad(SDValue Callee, SDValue &Chain) { + if (Callee.getNode() == Chain.getNode() || !Callee.hasOneUse()) + return false; + LoadSDNode *LD = dyn_cast(Callee.getNode()); + if (!LD || + LD->isVolatile() || + LD->getAddressingMode() != ISD::UNINDEXED || + LD->getExtensionType() != ISD::NON_EXTLOAD) + return false; + + // Now let's find the callseq_start. + while (Chain.getOpcode() != ISD::CALLSEQ_START) { + if (!Chain.hasOneUse()) + return false; + Chain = Chain.getOperand(0); + } + + if (Chain.getOperand(0).getNode() == Callee.getNode()) + return true; + if (Chain.getOperand(0).getOpcode() == ISD::TokenFactor && + Callee.getValue(1).isOperandOf(Chain.getOperand(0).getNode()) && + Callee.getValue(1).hasOneUse()) + return true; + return false; +} + + +/// PreprocessForRMW - Preprocess the DAG to make instruction selection better. +/// This is only run if not in -O0 mode. +/// This allows the instruction selector to pick more read-modify-write +/// instructions. This is a common case: +/// +/// [Load chain] +/// ^ +/// | +/// [Load] +/// ^ ^ +/// | | +/// / \- +/// / | +/// [TokenFactor] [Op] +/// ^ ^ +/// | | +/// \ / +/// \ / +/// [Store] +/// +/// The fact the store's chain operand != load's chain will prevent the +/// (store (op (load))) instruction from being selected. We can transform it to: +/// +/// [Load chain] +/// ^ +/// | +/// [TokenFactor] +/// ^ +/// | +/// [Load] +/// ^ ^ +/// | | +/// | \- +/// | | +/// | [Op] +/// | ^ +/// | | +/// \ / +/// \ / +/// [Store] +void X86DAGToDAGISel::PreprocessForRMW() { + for (SelectionDAG::allnodes_iterator I = CurDAG->allnodes_begin(), + E = CurDAG->allnodes_end(); I != E; ++I) { + if (I->getOpcode() == X86ISD::CALL) { + /// Also try moving call address load from outside callseq_start to just + /// before the call to allow it to be folded. + /// + /// [Load chain] + /// ^ + /// | + /// [Load] + /// ^ ^ + /// | | + /// / \-- + /// / | + ///[CALLSEQ_START] | + /// ^ | + /// | | + /// [LOAD/C2Reg] | + /// | | + /// \ / + /// \ / + /// [CALL] + SDValue Chain = I->getOperand(0); + SDValue Load = I->getOperand(1); + if (!isCalleeLoad(Load, Chain)) + continue; + MoveBelowCallSeqStart(CurDAG, Load, SDValue(I, 0), Chain); + ++NumLoadMoved; + continue; + } + + if (!ISD::isNON_TRUNCStore(I)) + continue; + SDValue Chain = I->getOperand(0); + + if (Chain.getNode()->getOpcode() != ISD::TokenFactor) + continue; + + SDValue N1 = I->getOperand(1); + SDValue N2 = I->getOperand(2); + if ((N1.getValueType().isFloatingPoint() && + !N1.getValueType().isVector()) || + !N1.hasOneUse()) + continue; + + bool RModW = false; + SDValue Load; + unsigned Opcode = N1.getNode()->getOpcode(); + switch (Opcode) { + case ISD::ADD: + case ISD::MUL: + case ISD::AND: + case ISD::OR: + case ISD::XOR: + case ISD::ADDC: + case ISD::ADDE: + case ISD::VECTOR_SHUFFLE: { + SDValue N10 = N1.getOperand(0); + SDValue N11 = N1.getOperand(1); + RModW = isRMWLoad(N10, Chain, N2, Load); + if (!RModW) + RModW = isRMWLoad(N11, Chain, N2, Load); + break; + } + case ISD::SUB: + case ISD::SHL: + case ISD::SRA: + case ISD::SRL: + case ISD::ROTL: + case ISD::ROTR: + case ISD::SUBC: + case ISD::SUBE: + case X86ISD::SHLD: + case X86ISD::SHRD: { + SDValue N10 = N1.getOperand(0); + RModW = isRMWLoad(N10, Chain, N2, Load); + break; + } + } + + if (RModW) { + MoveBelowTokenFactor(CurDAG, Load, SDValue(I, 0), Chain); + ++NumLoadMoved; + } + } +} + + +/// PreprocessForFPConvert - Walk over the dag lowering fpround and fpextend +/// nodes that target the FP stack to be store and load to the stack. This is a +/// gross hack. We would like to simply mark these as being illegal, but when +/// we do that, legalize produces these when it expands calls, then expands +/// these in the same legalize pass. We would like dag combine to be able to +/// hack on these between the call expansion and the node legalization. As such +/// this pass basically does "really late" legalization of these inline with the +/// X86 isel pass. +void X86DAGToDAGISel::PreprocessForFPConvert() { + for (SelectionDAG::allnodes_iterator I = CurDAG->allnodes_begin(), + E = CurDAG->allnodes_end(); I != E; ) { + SDNode *N = I++; // Preincrement iterator to avoid invalidation issues. + if (N->getOpcode() != ISD::FP_ROUND && N->getOpcode() != ISD::FP_EXTEND) + continue; + + // If the source and destination are SSE registers, then this is a legal + // conversion that should not be lowered. + EVT SrcVT = N->getOperand(0).getValueType(); + EVT DstVT = N->getValueType(0); + bool SrcIsSSE = X86Lowering.isScalarFPTypeInSSEReg(SrcVT); + bool DstIsSSE = X86Lowering.isScalarFPTypeInSSEReg(DstVT); + if (SrcIsSSE && DstIsSSE) + continue; + + if (!SrcIsSSE && !DstIsSSE) { + // If this is an FPStack extension, it is a noop. + if (N->getOpcode() == ISD::FP_EXTEND) + continue; + // If this is a value-preserving FPStack truncation, it is a noop. + if (N->getConstantOperandVal(1)) + continue; + } + + // Here we could have an FP stack truncation or an FPStack <-> SSE convert. + // FPStack has extload and truncstore. SSE can fold direct loads into other + // operations. Based on this, decide what we want to do. + EVT MemVT; + if (N->getOpcode() == ISD::FP_ROUND) + MemVT = DstVT; // FP_ROUND must use DstVT, we can't do a 'trunc load'. + else + MemVT = SrcIsSSE ? SrcVT : DstVT; + + SDValue MemTmp = CurDAG->CreateStackTemporary(MemVT); + DebugLoc dl = N->getDebugLoc(); + + // FIXME: optimize the case where the src/dest is a load or store? + SDValue Store = CurDAG->getTruncStore(CurDAG->getEntryNode(), dl, + N->getOperand(0), + MemTmp, NULL, 0, MemVT); + SDValue Result = CurDAG->getExtLoad(ISD::EXTLOAD, dl, DstVT, Store, MemTmp, + NULL, 0, MemVT); + + // We're about to replace all uses of the FP_ROUND/FP_EXTEND with the + // extload we created. This will cause general havok on the dag because + // anything below the conversion could be folded into other existing nodes. + // To avoid invalidating 'I', back it up to the convert node. + --I; + CurDAG->ReplaceAllUsesOfValueWith(SDValue(N, 0), Result); + + // Now that we did that, the node is dead. Increment the iterator to the + // next node to process, then delete N. + ++I; + CurDAG->DeleteNode(N); + } +} + +/// InstructionSelectBasicBlock - This callback is invoked by SelectionDAGISel +/// when it has created a SelectionDAG for us to codegen. +void X86DAGToDAGISel::InstructionSelect() { + const Function *F = MF->getFunction(); + OptForSize = F->hasFnAttr(Attribute::OptimizeForSize); + + if (OptLevel != CodeGenOpt::None) + PreprocessForRMW(); + + // FIXME: This should only happen when not compiled with -O0. + PreprocessForFPConvert(); + + // Codegen the basic block. +#ifndef NDEBUG + DEBUG(errs() << "===== Instruction selection begins:\n"); + Indent = 0; +#endif + SelectRoot(*CurDAG); +#ifndef NDEBUG + DEBUG(errs() << "===== Instruction selection ends:\n"); +#endif + + CurDAG->RemoveDeadNodes(); +} + +/// EmitSpecialCodeForMain - Emit any code that needs to be executed only in +/// the main function. +void X86DAGToDAGISel::EmitSpecialCodeForMain(MachineBasicBlock *BB, + MachineFrameInfo *MFI) { + const TargetInstrInfo *TII = TM.getInstrInfo(); + if (Subtarget->isTargetCygMing()) + BuildMI(BB, DebugLoc::getUnknownLoc(), + TII->get(X86::CALLpcrel32)).addExternalSymbol("__main"); +} + +void X86DAGToDAGISel::EmitFunctionEntryCode(Function &Fn, MachineFunction &MF) { + // If this is main, emit special code for main. + MachineBasicBlock *BB = MF.begin(); + if (Fn.hasExternalLinkage() && Fn.getName() == "main") + EmitSpecialCodeForMain(BB, MF.getFrameInfo()); +} + + +bool X86DAGToDAGISel::MatchSegmentBaseAddress(SDValue N, + X86ISelAddressMode &AM) { + assert(N.getOpcode() == X86ISD::SegmentBaseAddress); + SDValue Segment = N.getOperand(0); + + if (AM.Segment.getNode() == 0) { + AM.Segment = Segment; + return false; + } + + return true; +} + +bool X86DAGToDAGISel::MatchLoad(SDValue N, X86ISelAddressMode &AM) { + // This optimization is valid because the GNU TLS model defines that + // gs:0 (or fs:0 on X86-64) contains its own address. + // For more information see http://people.redhat.com/drepper/tls.pdf + + SDValue Address = N.getOperand(1); + if (Address.getOpcode() == X86ISD::SegmentBaseAddress && + !MatchSegmentBaseAddress (Address, AM)) + return false; + + return true; +} + +/// MatchWrapper - Try to match X86ISD::Wrapper and X86ISD::WrapperRIP nodes +/// into an addressing mode. These wrap things that will resolve down into a +/// symbol reference. If no match is possible, this returns true, otherwise it +/// returns false. +bool X86DAGToDAGISel::MatchWrapper(SDValue N, X86ISelAddressMode &AM) { + // If the addressing mode already has a symbol as the displacement, we can + // never match another symbol. + if (AM.hasSymbolicDisplacement()) + return true; + + SDValue N0 = N.getOperand(0); + CodeModel::Model M = TM.getCodeModel(); + + // Handle X86-64 rip-relative addresses. We check this before checking direct + // folding because RIP is preferable to non-RIP accesses. + if (Subtarget->is64Bit() && + // Under X86-64 non-small code model, GV (and friends) are 64-bits, so + // they cannot be folded into immediate fields. + // FIXME: This can be improved for kernel and other models? + (M == CodeModel::Small || M == CodeModel::Kernel) && + // Base and index reg must be 0 in order to use %rip as base and lowering + // must allow RIP. + !AM.hasBaseOrIndexReg() && N.getOpcode() == X86ISD::WrapperRIP) { + if (GlobalAddressSDNode *G = dyn_cast(N0)) { + int64_t Offset = AM.Disp + G->getOffset(); + if (!X86::isOffsetSuitableForCodeModel(Offset, M)) return true; + AM.GV = G->getGlobal(); + AM.Disp = Offset; + AM.SymbolFlags = G->getTargetFlags(); + } else if (ConstantPoolSDNode *CP = dyn_cast(N0)) { + int64_t Offset = AM.Disp + CP->getOffset(); + if (!X86::isOffsetSuitableForCodeModel(Offset, M)) return true; + AM.CP = CP->getConstVal(); + AM.Align = CP->getAlignment(); + AM.Disp = Offset; + AM.SymbolFlags = CP->getTargetFlags(); + } else if (ExternalSymbolSDNode *S = dyn_cast(N0)) { + AM.ES = S->getSymbol(); + AM.SymbolFlags = S->getTargetFlags(); + } else if (JumpTableSDNode *J = dyn_cast(N0)) { + AM.JT = J->getIndex(); + AM.SymbolFlags = J->getTargetFlags(); + } else { + AM.BlockAddr = cast(N0)->getBlockAddress(); + AM.SymbolFlags = cast(N0)->getTargetFlags(); + } + + if (N.getOpcode() == X86ISD::WrapperRIP) + AM.setBaseReg(CurDAG->getRegister(X86::RIP, MVT::i64)); + return false; + } + + // Handle the case when globals fit in our immediate field: This is true for + // X86-32 always and X86-64 when in -static -mcmodel=small mode. In 64-bit + // mode, this results in a non-RIP-relative computation. + if (!Subtarget->is64Bit() || + ((M == CodeModel::Small || M == CodeModel::Kernel) && + TM.getRelocationModel() == Reloc::Static)) { + if (GlobalAddressSDNode *G = dyn_cast(N0)) { + AM.GV = G->getGlobal(); + AM.Disp += G->getOffset(); + AM.SymbolFlags = G->getTargetFlags(); + } else if (ConstantPoolSDNode *CP = dyn_cast(N0)) { + AM.CP = CP->getConstVal(); + AM.Align = CP->getAlignment(); + AM.Disp += CP->getOffset(); + AM.SymbolFlags = CP->getTargetFlags(); + } else if (ExternalSymbolSDNode *S = dyn_cast(N0)) { + AM.ES = S->getSymbol(); + AM.SymbolFlags = S->getTargetFlags(); + } else if (JumpTableSDNode *J = dyn_cast(N0)) { + AM.JT = J->getIndex(); + AM.SymbolFlags = J->getTargetFlags(); + } else { + AM.BlockAddr = cast(N0)->getBlockAddress(); + AM.SymbolFlags = cast(N0)->getTargetFlags(); + } + return false; + } + + return true; +} + +/// MatchAddress - Add the specified node to the specified addressing mode, +/// returning true if it cannot be done. This just pattern matches for the +/// addressing mode. +bool X86DAGToDAGISel::MatchAddress(SDValue N, X86ISelAddressMode &AM) { + if (MatchAddressRecursively(N, AM, 0)) + return true; + + // Post-processing: Convert lea(,%reg,2) to lea(%reg,%reg), which has + // a smaller encoding and avoids a scaled-index. + if (AM.Scale == 2 && + AM.BaseType == X86ISelAddressMode::RegBase && + AM.Base.Reg.getNode() == 0) { + AM.Base.Reg = AM.IndexReg; + AM.Scale = 1; + } + + // Post-processing: Convert foo to foo(%rip), even in non-PIC mode, + // because it has a smaller encoding. + // TODO: Which other code models can use this? + if (TM.getCodeModel() == CodeModel::Small && + Subtarget->is64Bit() && + AM.Scale == 1 && + AM.BaseType == X86ISelAddressMode::RegBase && + AM.Base.Reg.getNode() == 0 && + AM.IndexReg.getNode() == 0 && + AM.SymbolFlags == X86II::MO_NO_FLAG && + AM.hasSymbolicDisplacement()) + AM.Base.Reg = CurDAG->getRegister(X86::RIP, MVT::i64); + + return false; +} + +bool X86DAGToDAGISel::MatchAddressRecursively(SDValue N, X86ISelAddressMode &AM, + unsigned Depth) { + bool is64Bit = Subtarget->is64Bit(); + DebugLoc dl = N.getDebugLoc(); + DEBUG({ + errs() << "MatchAddress: "; + AM.dump(); + }); + // Limit recursion. + if (Depth > 5) + return MatchAddressBase(N, AM); + + CodeModel::Model M = TM.getCodeModel(); + + // If this is already a %rip relative address, we can only merge immediates + // into it. Instead of handling this in every case, we handle it here. + // RIP relative addressing: %rip + 32-bit displacement! + if (AM.isRIPRelative()) { + // FIXME: JumpTable and ExternalSymbol address currently don't like + // displacements. It isn't very important, but this should be fixed for + // consistency. + if (!AM.ES && AM.JT != -1) return true; + + if (ConstantSDNode *Cst = dyn_cast(N)) { + int64_t Val = AM.Disp + Cst->getSExtValue(); + if (X86::isOffsetSuitableForCodeModel(Val, M, + AM.hasSymbolicDisplacement())) { + AM.Disp = Val; + return false; + } + } + return true; + } + + switch (N.getOpcode()) { + default: break; + case ISD::Constant: { + uint64_t Val = cast(N)->getSExtValue(); + if (!is64Bit || + X86::isOffsetSuitableForCodeModel(AM.Disp + Val, M, + AM.hasSymbolicDisplacement())) { + AM.Disp += Val; + return false; + } + break; + } + + case X86ISD::SegmentBaseAddress: + if (!MatchSegmentBaseAddress(N, AM)) + return false; + break; + + case X86ISD::Wrapper: + case X86ISD::WrapperRIP: + if (!MatchWrapper(N, AM)) + return false; + break; + + case ISD::LOAD: + if (!MatchLoad(N, AM)) + return false; + break; + + case ISD::FrameIndex: + if (AM.BaseType == X86ISelAddressMode::RegBase + && AM.Base.Reg.getNode() == 0) { + AM.BaseType = X86ISelAddressMode::FrameIndexBase; + AM.Base.FrameIndex = cast(N)->getIndex(); + return false; + } + break; + + case ISD::SHL: + if (AM.IndexReg.getNode() != 0 || AM.Scale != 1) + break; + + if (ConstantSDNode + *CN = dyn_cast(N.getNode()->getOperand(1))) { + unsigned Val = CN->getZExtValue(); + // Note that we handle x<<1 as (,x,2) rather than (x,x) here so + // that the base operand remains free for further matching. If + // the base doesn't end up getting used, a post-processing step + // in MatchAddress turns (,x,2) into (x,x), which is cheaper. + if (Val == 1 || Val == 2 || Val == 3) { + AM.Scale = 1 << Val; + SDValue ShVal = N.getNode()->getOperand(0); + + // Okay, we know that we have a scale by now. However, if the scaled + // value is an add of something and a constant, we can fold the + // constant into the disp field here. + if (ShVal.getNode()->getOpcode() == ISD::ADD && ShVal.hasOneUse() && + isa(ShVal.getNode()->getOperand(1))) { + AM.IndexReg = ShVal.getNode()->getOperand(0); + ConstantSDNode *AddVal = + cast(ShVal.getNode()->getOperand(1)); + uint64_t Disp = AM.Disp + (AddVal->getSExtValue() << Val); + if (!is64Bit || + X86::isOffsetSuitableForCodeModel(Disp, M, + AM.hasSymbolicDisplacement())) + AM.Disp = Disp; + else + AM.IndexReg = ShVal; + } else { + AM.IndexReg = ShVal; + } + return false; + } + break; + } + + case ISD::SMUL_LOHI: + case ISD::UMUL_LOHI: + // A mul_lohi where we need the low part can be folded as a plain multiply. + if (N.getResNo() != 0) break; + // FALL THROUGH + case ISD::MUL: + case X86ISD::MUL_IMM: + // X*[3,5,9] -> X+X*[2,4,8] + if (AM.BaseType == X86ISelAddressMode::RegBase && + AM.Base.Reg.getNode() == 0 && + AM.IndexReg.getNode() == 0) { + if (ConstantSDNode + *CN = dyn_cast(N.getNode()->getOperand(1))) + if (CN->getZExtValue() == 3 || CN->getZExtValue() == 5 || + CN->getZExtValue() == 9) { + AM.Scale = unsigned(CN->getZExtValue())-1; + + SDValue MulVal = N.getNode()->getOperand(0); + SDValue Reg; + + // Okay, we know that we have a scale by now. However, if the scaled + // value is an add of something and a constant, we can fold the + // constant into the disp field here. + if (MulVal.getNode()->getOpcode() == ISD::ADD && MulVal.hasOneUse() && + isa(MulVal.getNode()->getOperand(1))) { + Reg = MulVal.getNode()->getOperand(0); + ConstantSDNode *AddVal = + cast(MulVal.getNode()->getOperand(1)); + uint64_t Disp = AM.Disp + AddVal->getSExtValue() * + CN->getZExtValue(); + if (!is64Bit || + X86::isOffsetSuitableForCodeModel(Disp, M, + AM.hasSymbolicDisplacement())) + AM.Disp = Disp; + else + Reg = N.getNode()->getOperand(0); + } else { + Reg = N.getNode()->getOperand(0); + } + + AM.IndexReg = AM.Base.Reg = Reg; + return false; + } + } + break; + + case ISD::SUB: { + // Given A-B, if A can be completely folded into the address and + // the index field with the index field unused, use -B as the index. + // This is a win if a has multiple parts that can be folded into + // the address. Also, this saves a mov if the base register has + // other uses, since it avoids a two-address sub instruction, however + // it costs an additional mov if the index register has other uses. + + // Test if the LHS of the sub can be folded. + X86ISelAddressMode Backup = AM; + if (MatchAddressRecursively(N.getNode()->getOperand(0), AM, Depth+1)) { + AM = Backup; + break; + } + // Test if the index field is free for use. + if (AM.IndexReg.getNode() || AM.isRIPRelative()) { + AM = Backup; + break; + } + int Cost = 0; + SDValue RHS = N.getNode()->getOperand(1); + // If the RHS involves a register with multiple uses, this + // transformation incurs an extra mov, due to the neg instruction + // clobbering its operand. + if (!RHS.getNode()->hasOneUse() || + RHS.getNode()->getOpcode() == ISD::CopyFromReg || + RHS.getNode()->getOpcode() == ISD::TRUNCATE || + RHS.getNode()->getOpcode() == ISD::ANY_EXTEND || + (RHS.getNode()->getOpcode() == ISD::ZERO_EXTEND && + RHS.getNode()->getOperand(0).getValueType() == MVT::i32)) + ++Cost; + // If the base is a register with multiple uses, this + // transformation may save a mov. + if ((AM.BaseType == X86ISelAddressMode::RegBase && + AM.Base.Reg.getNode() && + !AM.Base.Reg.getNode()->hasOneUse()) || + AM.BaseType == X86ISelAddressMode::FrameIndexBase) + --Cost; + // If the folded LHS was interesting, this transformation saves + // address arithmetic. + if ((AM.hasSymbolicDisplacement() && !Backup.hasSymbolicDisplacement()) + + ((AM.Disp != 0) && (Backup.Disp == 0)) + + (AM.Segment.getNode() && !Backup.Segment.getNode()) >= 2) + --Cost; + // If it doesn't look like it may be an overall win, don't do it. + if (Cost >= 0) { + AM = Backup; + break; + } + + // Ok, the transformation is legal and appears profitable. Go for it. + SDValue Zero = CurDAG->getConstant(0, N.getValueType()); + SDValue Neg = CurDAG->getNode(ISD::SUB, dl, N.getValueType(), Zero, RHS); + AM.IndexReg = Neg; + AM.Scale = 1; + + // Insert the new nodes into the topological ordering. + if (Zero.getNode()->getNodeId() == -1 || + Zero.getNode()->getNodeId() > N.getNode()->getNodeId()) { + CurDAG->RepositionNode(N.getNode(), Zero.getNode()); + Zero.getNode()->setNodeId(N.getNode()->getNodeId()); + } + if (Neg.getNode()->getNodeId() == -1 || + Neg.getNode()->getNodeId() > N.getNode()->getNodeId()) { + CurDAG->RepositionNode(N.getNode(), Neg.getNode()); + Neg.getNode()->setNodeId(N.getNode()->getNodeId()); + } + return false; + } + + case ISD::ADD: { + X86ISelAddressMode Backup = AM; + if (!MatchAddressRecursively(N.getNode()->getOperand(0), AM, Depth+1) && + !MatchAddressRecursively(N.getNode()->getOperand(1), AM, Depth+1)) + return false; + AM = Backup; + if (!MatchAddressRecursively(N.getNode()->getOperand(1), AM, Depth+1) && + !MatchAddressRecursively(N.getNode()->getOperand(0), AM, Depth+1)) + return false; + AM = Backup; + + // If we couldn't fold both operands into the address at the same time, + // see if we can just put each operand into a register and fold at least + // the add. + if (AM.BaseType == X86ISelAddressMode::RegBase && + !AM.Base.Reg.getNode() && + !AM.IndexReg.getNode()) { + AM.Base.Reg = N.getNode()->getOperand(0); + AM.IndexReg = N.getNode()->getOperand(1); + AM.Scale = 1; + return false; + } + break; + } + + case ISD::OR: + // Handle "X | C" as "X + C" iff X is known to have C bits clear. + if (ConstantSDNode *CN = dyn_cast(N.getOperand(1))) { + X86ISelAddressMode Backup = AM; + uint64_t Offset = CN->getSExtValue(); + // Start with the LHS as an addr mode. + if (!MatchAddressRecursively(N.getOperand(0), AM, Depth+1) && + // Address could not have picked a GV address for the displacement. + AM.GV == NULL && + // On x86-64, the resultant disp must fit in 32-bits. + (!is64Bit || + X86::isOffsetSuitableForCodeModel(AM.Disp + Offset, M, + AM.hasSymbolicDisplacement())) && + // Check to see if the LHS & C is zero. + CurDAG->MaskedValueIsZero(N.getOperand(0), CN->getAPIntValue())) { + AM.Disp += Offset; + return false; + } + AM = Backup; + } + break; + + case ISD::AND: { + // Perform some heroic transforms on an and of a constant-count shift + // with a constant to enable use of the scaled offset field. + + SDValue Shift = N.getOperand(0); + if (Shift.getNumOperands() != 2) break; + + // Scale must not be used already. + if (AM.IndexReg.getNode() != 0 || AM.Scale != 1) break; + + SDValue X = Shift.getOperand(0); + ConstantSDNode *C2 = dyn_cast(N.getOperand(1)); + ConstantSDNode *C1 = dyn_cast(Shift.getOperand(1)); + if (!C1 || !C2) break; + + // Handle "(X >> (8-C1)) & C2" as "(X >> 8) & 0xff)" if safe. This + // allows us to convert the shift and and into an h-register extract and + // a scaled index. + if (Shift.getOpcode() == ISD::SRL && Shift.hasOneUse()) { + unsigned ScaleLog = 8 - C1->getZExtValue(); + if (ScaleLog > 0 && ScaleLog < 4 && + C2->getZExtValue() == (UINT64_C(0xff) << ScaleLog)) { + SDValue Eight = CurDAG->getConstant(8, MVT::i8); + SDValue Mask = CurDAG->getConstant(0xff, N.getValueType()); + SDValue Srl = CurDAG->getNode(ISD::SRL, dl, N.getValueType(), + X, Eight); + SDValue And = CurDAG->getNode(ISD::AND, dl, N.getValueType(), + Srl, Mask); + SDValue ShlCount = CurDAG->getConstant(ScaleLog, MVT::i8); + SDValue Shl = CurDAG->getNode(ISD::SHL, dl, N.getValueType(), + And, ShlCount); + + // Insert the new nodes into the topological ordering. + if (Eight.getNode()->getNodeId() == -1 || + Eight.getNode()->getNodeId() > X.getNode()->getNodeId()) { + CurDAG->RepositionNode(X.getNode(), Eight.getNode()); + Eight.getNode()->setNodeId(X.getNode()->getNodeId()); + } + if (Mask.getNode()->getNodeId() == -1 || + Mask.getNode()->getNodeId() > X.getNode()->getNodeId()) { + CurDAG->RepositionNode(X.getNode(), Mask.getNode()); + Mask.getNode()->setNodeId(X.getNode()->getNodeId()); + } + if (Srl.getNode()->getNodeId() == -1 || + Srl.getNode()->getNodeId() > Shift.getNode()->getNodeId()) { + CurDAG->RepositionNode(Shift.getNode(), Srl.getNode()); + Srl.getNode()->setNodeId(Shift.getNode()->getNodeId()); + } + if (And.getNode()->getNodeId() == -1 || + And.getNode()->getNodeId() > N.getNode()->getNodeId()) { + CurDAG->RepositionNode(N.getNode(), And.getNode()); + And.getNode()->setNodeId(N.getNode()->getNodeId()); + } + if (ShlCount.getNode()->getNodeId() == -1 || + ShlCount.getNode()->getNodeId() > X.getNode()->getNodeId()) { + CurDAG->RepositionNode(X.getNode(), ShlCount.getNode()); + ShlCount.getNode()->setNodeId(N.getNode()->getNodeId()); + } + if (Shl.getNode()->getNodeId() == -1 || + Shl.getNode()->getNodeId() > N.getNode()->getNodeId()) { + CurDAG->RepositionNode(N.getNode(), Shl.getNode()); + Shl.getNode()->setNodeId(N.getNode()->getNodeId()); + } + CurDAG->ReplaceAllUsesWith(N, Shl); + AM.IndexReg = And; + AM.Scale = (1 << ScaleLog); + return false; + } + } + + // Handle "(X << C1) & C2" as "(X & (C2>>C1)) << C1" if safe and if this + // allows us to fold the shift into this addressing mode. + if (Shift.getOpcode() != ISD::SHL) break; + + // Not likely to be profitable if either the AND or SHIFT node has more + // than one use (unless all uses are for address computation). Besides, + // isel mechanism requires their node ids to be reused. + if (!N.hasOneUse() || !Shift.hasOneUse()) + break; + + // Verify that the shift amount is something we can fold. + unsigned ShiftCst = C1->getZExtValue(); + if (ShiftCst != 1 && ShiftCst != 2 && ShiftCst != 3) + break; + + // Get the new AND mask, this folds to a constant. + SDValue NewANDMask = CurDAG->getNode(ISD::SRL, dl, N.getValueType(), + SDValue(C2, 0), SDValue(C1, 0)); + SDValue NewAND = CurDAG->getNode(ISD::AND, dl, N.getValueType(), X, + NewANDMask); + SDValue NewSHIFT = CurDAG->getNode(ISD::SHL, dl, N.getValueType(), + NewAND, SDValue(C1, 0)); + + // Insert the new nodes into the topological ordering. + if (C1->getNodeId() > X.getNode()->getNodeId()) { + CurDAG->RepositionNode(X.getNode(), C1); + C1->setNodeId(X.getNode()->getNodeId()); + } + if (NewANDMask.getNode()->getNodeId() == -1 || + NewANDMask.getNode()->getNodeId() > X.getNode()->getNodeId()) { + CurDAG->RepositionNode(X.getNode(), NewANDMask.getNode()); + NewANDMask.getNode()->setNodeId(X.getNode()->getNodeId()); + } + if (NewAND.getNode()->getNodeId() == -1 || + NewAND.getNode()->getNodeId() > Shift.getNode()->getNodeId()) { + CurDAG->RepositionNode(Shift.getNode(), NewAND.getNode()); + NewAND.getNode()->setNodeId(Shift.getNode()->getNodeId()); + } + if (NewSHIFT.getNode()->getNodeId() == -1 || + NewSHIFT.getNode()->getNodeId() > N.getNode()->getNodeId()) { + CurDAG->RepositionNode(N.getNode(), NewSHIFT.getNode()); + NewSHIFT.getNode()->setNodeId(N.getNode()->getNodeId()); + } + + CurDAG->ReplaceAllUsesWith(N, NewSHIFT); + + AM.Scale = 1 << ShiftCst; + AM.IndexReg = NewAND; + return false; + } + } + + return MatchAddressBase(N, AM); +} + +/// MatchAddressBase - Helper for MatchAddress. Add the specified node to the +/// specified addressing mode without any further recursion. +bool X86DAGToDAGISel::MatchAddressBase(SDValue N, X86ISelAddressMode &AM) { + // Is the base register already occupied? + if (AM.BaseType != X86ISelAddressMode::RegBase || AM.Base.Reg.getNode()) { + // If so, check to see if the scale index register is set. + if (AM.IndexReg.getNode() == 0) { + AM.IndexReg = N; + AM.Scale = 1; + return false; + } + + // Otherwise, we cannot select it. + return true; + } + + // Default, generate it as a register. + AM.BaseType = X86ISelAddressMode::RegBase; + AM.Base.Reg = N; + return false; +} + +/// SelectAddr - returns true if it is able pattern match an addressing mode. +/// It returns the operands which make up the maximal addressing mode it can +/// match by reference. +bool X86DAGToDAGISel::SelectAddr(SDValue Op, SDValue N, SDValue &Base, + SDValue &Scale, SDValue &Index, + SDValue &Disp, SDValue &Segment) { + X86ISelAddressMode AM; + bool Done = false; + if (AvoidDupAddrCompute && !N.hasOneUse()) { + unsigned Opcode = N.getOpcode(); + if (Opcode != ISD::Constant && Opcode != ISD::FrameIndex && + Opcode != X86ISD::Wrapper && Opcode != X86ISD::WrapperRIP) { + // If we are able to fold N into addressing mode, then we'll allow it even + // if N has multiple uses. In general, addressing computation is used as + // addresses by all of its uses. But watch out for CopyToReg uses, that + // means the address computation is liveout. It will be computed by a LEA + // so we want to avoid computing the address twice. + for (SDNode::use_iterator UI = N.getNode()->use_begin(), + UE = N.getNode()->use_end(); UI != UE; ++UI) { + if (UI->getOpcode() == ISD::CopyToReg) { + MatchAddressBase(N, AM); + Done = true; + break; + } + } + } + } + + if (!Done && MatchAddress(N, AM)) + return false; + + EVT VT = N.getValueType(); + if (AM.BaseType == X86ISelAddressMode::RegBase) { + if (!AM.Base.Reg.getNode()) + AM.Base.Reg = CurDAG->getRegister(0, VT); + } + + if (!AM.IndexReg.getNode()) + AM.IndexReg = CurDAG->getRegister(0, VT); + + getAddressOperands(AM, Base, Scale, Index, Disp, Segment); + return true; +} + +/// SelectScalarSSELoad - Match a scalar SSE load. In particular, we want to +/// match a load whose top elements are either undef or zeros. The load flavor +/// is derived from the type of N, which is either v4f32 or v2f64. +bool X86DAGToDAGISel::SelectScalarSSELoad(SDValue Op, SDValue Pred, + SDValue N, SDValue &Base, + SDValue &Scale, SDValue &Index, + SDValue &Disp, SDValue &Segment, + SDValue &InChain, + SDValue &OutChain) { + if (N.getOpcode() == ISD::SCALAR_TO_VECTOR) { + InChain = N.getOperand(0).getValue(1); + if (ISD::isNON_EXTLoad(InChain.getNode()) && + InChain.getValue(0).hasOneUse() && + N.hasOneUse() && + IsLegalAndProfitableToFold(N.getNode(), Pred.getNode(), Op.getNode())) { + LoadSDNode *LD = cast(InChain); + if (!SelectAddr(Op, LD->getBasePtr(), Base, Scale, Index, Disp, Segment)) + return false; + OutChain = LD->getChain(); + return true; + } + } + + // Also handle the case where we explicitly require zeros in the top + // elements. This is a vector shuffle from the zero vector. + if (N.getOpcode() == X86ISD::VZEXT_MOVL && N.getNode()->hasOneUse() && + // Check to see if the top elements are all zeros (or bitcast of zeros). + N.getOperand(0).getOpcode() == ISD::SCALAR_TO_VECTOR && + N.getOperand(0).getNode()->hasOneUse() && + ISD::isNON_EXTLoad(N.getOperand(0).getOperand(0).getNode()) && + N.getOperand(0).getOperand(0).hasOneUse()) { + // Okay, this is a zero extending load. Fold it. + LoadSDNode *LD = cast(N.getOperand(0).getOperand(0)); + if (!SelectAddr(Op, LD->getBasePtr(), Base, Scale, Index, Disp, Segment)) + return false; + OutChain = LD->getChain(); + InChain = SDValue(LD, 1); + return true; + } + return false; +} + + +/// SelectLEAAddr - it calls SelectAddr and determines if the maximal addressing +/// mode it matches can be cost effectively emitted as an LEA instruction. +bool X86DAGToDAGISel::SelectLEAAddr(SDValue Op, SDValue N, + SDValue &Base, SDValue &Scale, + SDValue &Index, SDValue &Disp) { + X86ISelAddressMode AM; + + // Set AM.Segment to prevent MatchAddress from using one. LEA doesn't support + // segments. + SDValue Copy = AM.Segment; + SDValue T = CurDAG->getRegister(0, MVT::i32); + AM.Segment = T; + if (MatchAddress(N, AM)) + return false; + assert (T == AM.Segment); + AM.Segment = Copy; + + EVT VT = N.getValueType(); + unsigned Complexity = 0; + if (AM.BaseType == X86ISelAddressMode::RegBase) + if (AM.Base.Reg.getNode()) + Complexity = 1; + else + AM.Base.Reg = CurDAG->getRegister(0, VT); + else if (AM.BaseType == X86ISelAddressMode::FrameIndexBase) + Complexity = 4; + + if (AM.IndexReg.getNode()) + Complexity++; + else + AM.IndexReg = CurDAG->getRegister(0, VT); + + // Don't match just leal(,%reg,2). It's cheaper to do addl %reg, %reg, or with + // a simple shift. + if (AM.Scale > 1) + Complexity++; + + // FIXME: We are artificially lowering the criteria to turn ADD %reg, $GA + // to a LEA. This is determined with some expermentation but is by no means + // optimal (especially for code size consideration). LEA is nice because of + // its three-address nature. Tweak the cost function again when we can run + // convertToThreeAddress() at register allocation time. + if (AM.hasSymbolicDisplacement()) { + // For X86-64, we should always use lea to materialize RIP relative + // addresses. + if (Subtarget->is64Bit()) + Complexity = 4; + else + Complexity += 2; + } + + if (AM.Disp && (AM.Base.Reg.getNode() || AM.IndexReg.getNode())) + Complexity++; + + // If it isn't worth using an LEA, reject it. + if (Complexity <= 2) + return false; + + SDValue Segment; + getAddressOperands(AM, Base, Scale, Index, Disp, Segment); + return true; +} + +/// SelectTLSADDRAddr - This is only run on TargetGlobalTLSAddress nodes. +bool X86DAGToDAGISel::SelectTLSADDRAddr(SDValue Op, SDValue N, SDValue &Base, + SDValue &Scale, SDValue &Index, + SDValue &Disp) { + assert(Op.getOpcode() == X86ISD::TLSADDR); + assert(N.getOpcode() == ISD::TargetGlobalTLSAddress); + const GlobalAddressSDNode *GA = cast(N); + + X86ISelAddressMode AM; + AM.GV = GA->getGlobal(); + AM.Disp += GA->getOffset(); + AM.Base.Reg = CurDAG->getRegister(0, N.getValueType()); + AM.SymbolFlags = GA->getTargetFlags(); + + if (N.getValueType() == MVT::i32) { + AM.Scale = 1; + AM.IndexReg = CurDAG->getRegister(X86::EBX, MVT::i32); + } else { + AM.IndexReg = CurDAG->getRegister(0, MVT::i64); + } + + SDValue Segment; + getAddressOperands(AM, Base, Scale, Index, Disp, Segment); + return true; +} + + +bool X86DAGToDAGISel::TryFoldLoad(SDValue P, SDValue N, + SDValue &Base, SDValue &Scale, + SDValue &Index, SDValue &Disp, + SDValue &Segment) { + if (ISD::isNON_EXTLoad(N.getNode()) && + N.hasOneUse() && + IsLegalAndProfitableToFold(N.getNode(), P.getNode(), P.getNode())) + return SelectAddr(P, N.getOperand(1), Base, Scale, Index, Disp, Segment); + return false; +} + +/// getGlobalBaseReg - Return an SDNode that returns the value of +/// the global base register. Output instructions required to +/// initialize the global base register, if necessary. +/// +SDNode *X86DAGToDAGISel::getGlobalBaseReg() { + unsigned GlobalBaseReg = getInstrInfo()->getGlobalBaseReg(MF); + return CurDAG->getRegister(GlobalBaseReg, TLI.getPointerTy()).getNode(); +} + +static SDNode *FindCallStartFromCall(SDNode *Node) { + if (Node->getOpcode() == ISD::CALLSEQ_START) return Node; + assert(Node->getOperand(0).getValueType() == MVT::Other && + "Node doesn't have a token chain argument!"); + return FindCallStartFromCall(Node->getOperand(0).getNode()); +} + +SDNode *X86DAGToDAGISel::SelectAtomic64(SDNode *Node, unsigned Opc) { + SDValue Chain = Node->getOperand(0); + SDValue In1 = Node->getOperand(1); + SDValue In2L = Node->getOperand(2); + SDValue In2H = Node->getOperand(3); + SDValue Tmp0, Tmp1, Tmp2, Tmp3, Tmp4; + if (!SelectAddr(In1, In1, Tmp0, Tmp1, Tmp2, Tmp3, Tmp4)) + return NULL; + MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1); + MemOp[0] = cast(Node)->getMemOperand(); + const SDValue Ops[] = { Tmp0, Tmp1, Tmp2, Tmp3, Tmp4, In2L, In2H, Chain}; + SDNode *ResNode = CurDAG->getMachineNode(Opc, Node->getDebugLoc(), + MVT::i32, MVT::i32, MVT::Other, Ops, + array_lengthof(Ops)); + cast(ResNode)->setMemRefs(MemOp, MemOp + 1); + return ResNode; +} + +SDNode *X86DAGToDAGISel::SelectAtomicLoadAdd(SDNode *Node, EVT NVT) { + if (Node->hasAnyUseOfValue(0)) + return 0; + + // Optimize common patterns for __sync_add_and_fetch and + // __sync_sub_and_fetch where the result is not used. This allows us + // to use "lock" version of add, sub, inc, dec instructions. + // FIXME: Do not use special instructions but instead add the "lock" + // prefix to the target node somehow. The extra information will then be + // transferred to machine instruction and it denotes the prefix. + SDValue Chain = Node->getOperand(0); + SDValue Ptr = Node->getOperand(1); + SDValue Val = Node->getOperand(2); + SDValue Tmp0, Tmp1, Tmp2, Tmp3, Tmp4; + if (!SelectAddr(Ptr, Ptr, Tmp0, Tmp1, Tmp2, Tmp3, Tmp4)) + return 0; + + bool isInc = false, isDec = false, isSub = false, isCN = false; + ConstantSDNode *CN = dyn_cast(Val); + if (CN) { + isCN = true; + int64_t CNVal = CN->getSExtValue(); + if (CNVal == 1) + isInc = true; + else if (CNVal == -1) + isDec = true; + else if (CNVal >= 0) + Val = CurDAG->getTargetConstant(CNVal, NVT); + else { + isSub = true; + Val = CurDAG->getTargetConstant(-CNVal, NVT); + } + } else if (Val.hasOneUse() && + Val.getOpcode() == ISD::SUB && + X86::isZeroNode(Val.getOperand(0))) { + isSub = true; + Val = Val.getOperand(1); + } + + unsigned Opc = 0; + switch (NVT.getSimpleVT().SimpleTy) { + default: return 0; + case MVT::i8: + if (isInc) + Opc = X86::LOCK_INC8m; + else if (isDec) + Opc = X86::LOCK_DEC8m; + else if (isSub) { + if (isCN) + Opc = X86::LOCK_SUB8mi; + else + Opc = X86::LOCK_SUB8mr; + } else { + if (isCN) + Opc = X86::LOCK_ADD8mi; + else + Opc = X86::LOCK_ADD8mr; + } + break; + case MVT::i16: + if (isInc) + Opc = X86::LOCK_INC16m; + else if (isDec) + Opc = X86::LOCK_DEC16m; + else if (isSub) { + if (isCN) { + if (Predicate_i16immSExt8(Val.getNode())) + Opc = X86::LOCK_SUB16mi8; + else + Opc = X86::LOCK_SUB16mi; + } else + Opc = X86::LOCK_SUB16mr; + } else { + if (isCN) { + if (Predicate_i16immSExt8(Val.getNode())) + Opc = X86::LOCK_ADD16mi8; + else + Opc = X86::LOCK_ADD16mi; + } else + Opc = X86::LOCK_ADD16mr; + } + break; + case MVT::i32: + if (isInc) + Opc = X86::LOCK_INC32m; + else if (isDec) + Opc = X86::LOCK_DEC32m; + else if (isSub) { + if (isCN) { + if (Predicate_i32immSExt8(Val.getNode())) + Opc = X86::LOCK_SUB32mi8; + else + Opc = X86::LOCK_SUB32mi; + } else + Opc = X86::LOCK_SUB32mr; + } else { + if (isCN) { + if (Predicate_i32immSExt8(Val.getNode())) + Opc = X86::LOCK_ADD32mi8; + else + Opc = X86::LOCK_ADD32mi; + } else + Opc = X86::LOCK_ADD32mr; + } + break; + case MVT::i64: + if (isInc) + Opc = X86::LOCK_INC64m; + else if (isDec) + Opc = X86::LOCK_DEC64m; + else if (isSub) { + Opc = X86::LOCK_SUB64mr; + if (isCN) { + if (Predicate_i64immSExt8(Val.getNode())) + Opc = X86::LOCK_SUB64mi8; + else if (Predicate_i64immSExt32(Val.getNode())) + Opc = X86::LOCK_SUB64mi32; + } + } else { + Opc = X86::LOCK_ADD64mr; + if (isCN) { + if (Predicate_i64immSExt8(Val.getNode())) + Opc = X86::LOCK_ADD64mi8; + else if (Predicate_i64immSExt32(Val.getNode())) + Opc = X86::LOCK_ADD64mi32; + } + } + break; + } + + DebugLoc dl = Node->getDebugLoc(); + SDValue Undef = SDValue(CurDAG->getMachineNode(TargetInstrInfo::IMPLICIT_DEF, + dl, NVT), 0); + MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1); + MemOp[0] = cast(Node)->getMemOperand(); + if (isInc || isDec) { + SDValue Ops[] = { Tmp0, Tmp1, Tmp2, Tmp3, Tmp4, Chain }; + SDValue Ret = SDValue(CurDAG->getMachineNode(Opc, dl, MVT::Other, Ops, 6), 0); + cast(Ret)->setMemRefs(MemOp, MemOp + 1); + SDValue RetVals[] = { Undef, Ret }; + return CurDAG->getMergeValues(RetVals, 2, dl).getNode(); + } else { + SDValue Ops[] = { Tmp0, Tmp1, Tmp2, Tmp3, Tmp4, Val, Chain }; + SDValue Ret = SDValue(CurDAG->getMachineNode(Opc, dl, MVT::Other, Ops, 7), 0); + cast(Ret)->setMemRefs(MemOp, MemOp + 1); + SDValue RetVals[] = { Undef, Ret }; + return CurDAG->getMergeValues(RetVals, 2, dl).getNode(); + } +} + +/// HasNoSignedComparisonUses - Test whether the given X86ISD::CMP node has +/// any uses which require the SF or OF bits to be accurate. +static bool HasNoSignedComparisonUses(SDNode *N) { + // Examine each user of the node. + for (SDNode::use_iterator UI = N->use_begin(), + UE = N->use_end(); UI != UE; ++UI) { + // Only examine CopyToReg uses. + if (UI->getOpcode() != ISD::CopyToReg) + return false; + // Only examine CopyToReg uses that copy to EFLAGS. + if (cast(UI->getOperand(1))->getReg() != + X86::EFLAGS) + return false; + // Examine each user of the CopyToReg use. + for (SDNode::use_iterator FlagUI = UI->use_begin(), + FlagUE = UI->use_end(); FlagUI != FlagUE; ++FlagUI) { + // Only examine the Flag result. + if (FlagUI.getUse().getResNo() != 1) continue; + // Anything unusual: assume conservatively. + if (!FlagUI->isMachineOpcode()) return false; + // Examine the opcode of the user. + switch (FlagUI->getMachineOpcode()) { + // These comparisons don't treat the most significant bit specially. + case X86::SETAr: case X86::SETAEr: case X86::SETBr: case X86::SETBEr: + case X86::SETEr: case X86::SETNEr: case X86::SETPr: case X86::SETNPr: + case X86::SETAm: case X86::SETAEm: case X86::SETBm: case X86::SETBEm: + case X86::SETEm: case X86::SETNEm: case X86::SETPm: case X86::SETNPm: + case X86::JA: case X86::JAE: case X86::JB: case X86::JBE: + case X86::JE: case X86::JNE: case X86::JP: case X86::JNP: + case X86::CMOVA16rr: case X86::CMOVA16rm: + case X86::CMOVA32rr: case X86::CMOVA32rm: + case X86::CMOVA64rr: case X86::CMOVA64rm: + case X86::CMOVAE16rr: case X86::CMOVAE16rm: + case X86::CMOVAE32rr: case X86::CMOVAE32rm: + case X86::CMOVAE64rr: case X86::CMOVAE64rm: + case X86::CMOVB16rr: case X86::CMOVB16rm: + case X86::CMOVB32rr: case X86::CMOVB32rm: + case X86::CMOVB64rr: case X86::CMOVB64rm: + case X86::CMOVBE16rr: case X86::CMOVBE16rm: + case X86::CMOVBE32rr: case X86::CMOVBE32rm: + case X86::CMOVBE64rr: case X86::CMOVBE64rm: + case X86::CMOVE16rr: case X86::CMOVE16rm: + case X86::CMOVE32rr: case X86::CMOVE32rm: + case X86::CMOVE64rr: case X86::CMOVE64rm: + case X86::CMOVNE16rr: case X86::CMOVNE16rm: + case X86::CMOVNE32rr: case X86::CMOVNE32rm: + case X86::CMOVNE64rr: case X86::CMOVNE64rm: + case X86::CMOVNP16rr: case X86::CMOVNP16rm: + case X86::CMOVNP32rr: case X86::CMOVNP32rm: + case X86::CMOVNP64rr: case X86::CMOVNP64rm: + case X86::CMOVP16rr: case X86::CMOVP16rm: + case X86::CMOVP32rr: case X86::CMOVP32rm: + case X86::CMOVP64rr: case X86::CMOVP64rm: + continue; + // Anything else: assume conservatively. + default: return false; + } + } + } + return true; +} + +SDNode *X86DAGToDAGISel::Select(SDValue N) { + SDNode *Node = N.getNode(); + EVT NVT = Node->getValueType(0); + unsigned Opc, MOpc; + unsigned Opcode = Node->getOpcode(); + DebugLoc dl = Node->getDebugLoc(); + +#ifndef NDEBUG + DEBUG({ + errs() << std::string(Indent, ' ') << "Selecting: "; + Node->dump(CurDAG); + errs() << '\n'; + }); + Indent += 2; +#endif + + if (Node->isMachineOpcode()) { +#ifndef NDEBUG + DEBUG({ + errs() << std::string(Indent-2, ' ') << "== "; + Node->dump(CurDAG); + errs() << '\n'; + }); + Indent -= 2; +#endif + return NULL; // Already selected. + } + + switch (Opcode) { + default: break; + case X86ISD::GlobalBaseReg: + return getGlobalBaseReg(); + + case X86ISD::ATOMOR64_DAG: + return SelectAtomic64(Node, X86::ATOMOR6432); + case X86ISD::ATOMXOR64_DAG: + return SelectAtomic64(Node, X86::ATOMXOR6432); + case X86ISD::ATOMADD64_DAG: + return SelectAtomic64(Node, X86::ATOMADD6432); + case X86ISD::ATOMSUB64_DAG: + return SelectAtomic64(Node, X86::ATOMSUB6432); + case X86ISD::ATOMNAND64_DAG: + return SelectAtomic64(Node, X86::ATOMNAND6432); + case X86ISD::ATOMAND64_DAG: + return SelectAtomic64(Node, X86::ATOMAND6432); + case X86ISD::ATOMSWAP64_DAG: + return SelectAtomic64(Node, X86::ATOMSWAP6432); + + case ISD::ATOMIC_LOAD_ADD: { + SDNode *RetVal = SelectAtomicLoadAdd(Node, NVT); + if (RetVal) + return RetVal; + break; + } + + case ISD::SMUL_LOHI: + case ISD::UMUL_LOHI: { + SDValue N0 = Node->getOperand(0); + SDValue N1 = Node->getOperand(1); + + bool isSigned = Opcode == ISD::SMUL_LOHI; + if (!isSigned) { + switch (NVT.getSimpleVT().SimpleTy) { + default: llvm_unreachable("Unsupported VT!"); + case MVT::i8: Opc = X86::MUL8r; MOpc = X86::MUL8m; break; + case MVT::i16: Opc = X86::MUL16r; MOpc = X86::MUL16m; break; + case MVT::i32: Opc = X86::MUL32r; MOpc = X86::MUL32m; break; + case MVT::i64: Opc = X86::MUL64r; MOpc = X86::MUL64m; break; + } + } else { + switch (NVT.getSimpleVT().SimpleTy) { + default: llvm_unreachable("Unsupported VT!"); + case MVT::i8: Opc = X86::IMUL8r; MOpc = X86::IMUL8m; break; + case MVT::i16: Opc = X86::IMUL16r; MOpc = X86::IMUL16m; break; + case MVT::i32: Opc = X86::IMUL32r; MOpc = X86::IMUL32m; break; + case MVT::i64: Opc = X86::IMUL64r; MOpc = X86::IMUL64m; break; + } + } + + unsigned LoReg, HiReg; + switch (NVT.getSimpleVT().SimpleTy) { + default: llvm_unreachable("Unsupported VT!"); + case MVT::i8: LoReg = X86::AL; HiReg = X86::AH; break; + case MVT::i16: LoReg = X86::AX; HiReg = X86::DX; break; + case MVT::i32: LoReg = X86::EAX; HiReg = X86::EDX; break; + case MVT::i64: LoReg = X86::RAX; HiReg = X86::RDX; break; + } + + SDValue Tmp0, Tmp1, Tmp2, Tmp3, Tmp4; + bool foldedLoad = TryFoldLoad(N, N1, Tmp0, Tmp1, Tmp2, Tmp3, Tmp4); + // Multiply is commmutative. + if (!foldedLoad) { + foldedLoad = TryFoldLoad(N, N0, Tmp0, Tmp1, Tmp2, Tmp3, Tmp4); + if (foldedLoad) + std::swap(N0, N1); + } + + SDValue InFlag = CurDAG->getCopyToReg(CurDAG->getEntryNode(), dl, LoReg, + N0, SDValue()).getValue(1); + + if (foldedLoad) { + SDValue Ops[] = { Tmp0, Tmp1, Tmp2, Tmp3, Tmp4, N1.getOperand(0), + InFlag }; + SDNode *CNode = + CurDAG->getMachineNode(MOpc, dl, MVT::Other, MVT::Flag, Ops, + array_lengthof(Ops)); + InFlag = SDValue(CNode, 1); + // Update the chain. + ReplaceUses(N1.getValue(1), SDValue(CNode, 0)); + } else { + InFlag = + SDValue(CurDAG->getMachineNode(Opc, dl, MVT::Flag, N1, InFlag), 0); + } + + // Copy the low half of the result, if it is needed. + if (!N.getValue(0).use_empty()) { + SDValue Result = CurDAG->getCopyFromReg(CurDAG->getEntryNode(), dl, + LoReg, NVT, InFlag); + InFlag = Result.getValue(2); + ReplaceUses(N.getValue(0), Result); +#ifndef NDEBUG + DEBUG({ + errs() << std::string(Indent-2, ' ') << "=> "; + Result.getNode()->dump(CurDAG); + errs() << '\n'; + }); +#endif + } + // Copy the high half of the result, if it is needed. + if (!N.getValue(1).use_empty()) { + SDValue Result; + if (HiReg == X86::AH && Subtarget->is64Bit()) { + // Prevent use of AH in a REX instruction by referencing AX instead. + // Shift it down 8 bits. + Result = CurDAG->getCopyFromReg(CurDAG->getEntryNode(), dl, + X86::AX, MVT::i16, InFlag); + InFlag = Result.getValue(2); + Result = SDValue(CurDAG->getMachineNode(X86::SHR16ri, dl, MVT::i16, + Result, + CurDAG->getTargetConstant(8, MVT::i8)), 0); + // Then truncate it down to i8. + Result = CurDAG->getTargetExtractSubreg(X86::SUBREG_8BIT, dl, + MVT::i8, Result); + } else { + Result = CurDAG->getCopyFromReg(CurDAG->getEntryNode(), dl, + HiReg, NVT, InFlag); + InFlag = Result.getValue(2); + } + ReplaceUses(N.getValue(1), Result); +#ifndef NDEBUG + DEBUG({ + errs() << std::string(Indent-2, ' ') << "=> "; + Result.getNode()->dump(CurDAG); + errs() << '\n'; + }); +#endif + } + +#ifndef NDEBUG + Indent -= 2; +#endif + + return NULL; + } + + case ISD::SDIVREM: + case ISD::UDIVREM: { + SDValue N0 = Node->getOperand(0); + SDValue N1 = Node->getOperand(1); + + bool isSigned = Opcode == ISD::SDIVREM; + if (!isSigned) { + switch (NVT.getSimpleVT().SimpleTy) { + default: llvm_unreachable("Unsupported VT!"); + case MVT::i8: Opc = X86::DIV8r; MOpc = X86::DIV8m; break; + case MVT::i16: Opc = X86::DIV16r; MOpc = X86::DIV16m; break; + case MVT::i32: Opc = X86::DIV32r; MOpc = X86::DIV32m; break; + case MVT::i64: Opc = X86::DIV64r; MOpc = X86::DIV64m; break; + } + } else { + switch (NVT.getSimpleVT().SimpleTy) { + default: llvm_unreachable("Unsupported VT!"); + case MVT::i8: Opc = X86::IDIV8r; MOpc = X86::IDIV8m; break; + case MVT::i16: Opc = X86::IDIV16r; MOpc = X86::IDIV16m; break; + case MVT::i32: Opc = X86::IDIV32r; MOpc = X86::IDIV32m; break; + case MVT::i64: Opc = X86::IDIV64r; MOpc = X86::IDIV64m; break; + } + } + + unsigned LoReg, HiReg; + unsigned ClrOpcode, SExtOpcode; + switch (NVT.getSimpleVT().SimpleTy) { + default: llvm_unreachable("Unsupported VT!"); + case MVT::i8: + LoReg = X86::AL; HiReg = X86::AH; + ClrOpcode = 0; + SExtOpcode = X86::CBW; + break; + case MVT::i16: + LoReg = X86::AX; HiReg = X86::DX; + ClrOpcode = X86::MOV16r0; + SExtOpcode = X86::CWD; + break; + case MVT::i32: + LoReg = X86::EAX; HiReg = X86::EDX; + ClrOpcode = X86::MOV32r0; + SExtOpcode = X86::CDQ; + break; + case MVT::i64: + LoReg = X86::RAX; HiReg = X86::RDX; + ClrOpcode = ~0U; // NOT USED. + SExtOpcode = X86::CQO; + break; + } + + SDValue Tmp0, Tmp1, Tmp2, Tmp3, Tmp4; + bool foldedLoad = TryFoldLoad(N, N1, Tmp0, Tmp1, Tmp2, Tmp3, Tmp4); + bool signBitIsZero = CurDAG->SignBitIsZero(N0); + + SDValue InFlag; + if (NVT == MVT::i8 && (!isSigned || signBitIsZero)) { + // Special case for div8, just use a move with zero extension to AX to + // clear the upper 8 bits (AH). + SDValue Tmp0, Tmp1, Tmp2, Tmp3, Tmp4, Move, Chain; + if (TryFoldLoad(N, N0, Tmp0, Tmp1, Tmp2, Tmp3, Tmp4)) { + SDValue Ops[] = { Tmp0, Tmp1, Tmp2, Tmp3, Tmp4, N0.getOperand(0) }; + Move = + SDValue(CurDAG->getMachineNode(X86::MOVZX16rm8, dl, MVT::i16, + MVT::Other, Ops, + array_lengthof(Ops)), 0); + Chain = Move.getValue(1); + ReplaceUses(N0.getValue(1), Chain); + } else { + Move = + SDValue(CurDAG->getMachineNode(X86::MOVZX16rr8, dl, MVT::i16, N0),0); + Chain = CurDAG->getEntryNode(); + } + Chain = CurDAG->getCopyToReg(Chain, dl, X86::AX, Move, SDValue()); + InFlag = Chain.getValue(1); + } else { + InFlag = + CurDAG->getCopyToReg(CurDAG->getEntryNode(), dl, + LoReg, N0, SDValue()).getValue(1); + if (isSigned && !signBitIsZero) { + // Sign extend the low part into the high part. + InFlag = + SDValue(CurDAG->getMachineNode(SExtOpcode, dl, MVT::Flag, InFlag),0); + } else { + // Zero out the high part, effectively zero extending the input. + SDValue ClrNode; + + if (NVT.getSimpleVT() == MVT::i64) { + ClrNode = SDValue(CurDAG->getMachineNode(X86::MOV32r0, dl, MVT::i32), + 0); + // We just did a 32-bit clear, insert it into a 64-bit register to + // clear the whole 64-bit reg. + SDValue Zero = CurDAG->getTargetConstant(0, MVT::i64); + SDValue SubRegNo = + CurDAG->getTargetConstant(X86::SUBREG_32BIT, MVT::i32); + ClrNode = + SDValue(CurDAG->getMachineNode(TargetInstrInfo::SUBREG_TO_REG, dl, + MVT::i64, Zero, ClrNode, SubRegNo), + 0); + } else { + ClrNode = SDValue(CurDAG->getMachineNode(ClrOpcode, dl, NVT), 0); + } + + InFlag = CurDAG->getCopyToReg(CurDAG->getEntryNode(), dl, HiReg, + ClrNode, InFlag).getValue(1); + } + } + + if (foldedLoad) { + SDValue Ops[] = { Tmp0, Tmp1, Tmp2, Tmp3, Tmp4, N1.getOperand(0), + InFlag }; + SDNode *CNode = + CurDAG->getMachineNode(MOpc, dl, MVT::Other, MVT::Flag, Ops, + array_lengthof(Ops)); + InFlag = SDValue(CNode, 1); + // Update the chain. + ReplaceUses(N1.getValue(1), SDValue(CNode, 0)); + } else { + InFlag = + SDValue(CurDAG->getMachineNode(Opc, dl, MVT::Flag, N1, InFlag), 0); + } + + // Copy the division (low) result, if it is needed. + if (!N.getValue(0).use_empty()) { + SDValue Result = CurDAG->getCopyFromReg(CurDAG->getEntryNode(), dl, + LoReg, NVT, InFlag); + InFlag = Result.getValue(2); + ReplaceUses(N.getValue(0), Result); +#ifndef NDEBUG + DEBUG({ + errs() << std::string(Indent-2, ' ') << "=> "; + Result.getNode()->dump(CurDAG); + errs() << '\n'; + }); +#endif + } + // Copy the remainder (high) result, if it is needed. + if (!N.getValue(1).use_empty()) { + SDValue Result; + if (HiReg == X86::AH && Subtarget->is64Bit()) { + // Prevent use of AH in a REX instruction by referencing AX instead. + // Shift it down 8 bits. + Result = CurDAG->getCopyFromReg(CurDAG->getEntryNode(), dl, + X86::AX, MVT::i16, InFlag); + InFlag = Result.getValue(2); + Result = SDValue(CurDAG->getMachineNode(X86::SHR16ri, dl, MVT::i16, + Result, + CurDAG->getTargetConstant(8, MVT::i8)), + 0); + // Then truncate it down to i8. + Result = CurDAG->getTargetExtractSubreg(X86::SUBREG_8BIT, dl, + MVT::i8, Result); + } else { + Result = CurDAG->getCopyFromReg(CurDAG->getEntryNode(), dl, + HiReg, NVT, InFlag); + InFlag = Result.getValue(2); + } + ReplaceUses(N.getValue(1), Result); +#ifndef NDEBUG + DEBUG({ + errs() << std::string(Indent-2, ' ') << "=> "; + Result.getNode()->dump(CurDAG); + errs() << '\n'; + }); +#endif + } + +#ifndef NDEBUG + Indent -= 2; +#endif + + return NULL; + } + + case X86ISD::CMP: { + SDValue N0 = Node->getOperand(0); + SDValue N1 = Node->getOperand(1); + + // Look for (X86cmp (and $op, $imm), 0) and see if we can convert it to + // use a smaller encoding. + if (N0.getNode()->getOpcode() == ISD::AND && N0.getNode()->hasOneUse() && + N0.getValueType() != MVT::i8 && + X86::isZeroNode(N1)) { + ConstantSDNode *C = dyn_cast(N0.getNode()->getOperand(1)); + if (!C) break; + + // For example, convert "testl %eax, $8" to "testb %al, $8" + if ((C->getZExtValue() & ~UINT64_C(0xff)) == 0 && + (!(C->getZExtValue() & 0x80) || + HasNoSignedComparisonUses(Node))) { + SDValue Imm = CurDAG->getTargetConstant(C->getZExtValue(), MVT::i8); + SDValue Reg = N0.getNode()->getOperand(0); + + // On x86-32, only the ABCD registers have 8-bit subregisters. + if (!Subtarget->is64Bit()) { + TargetRegisterClass *TRC = 0; + switch (N0.getValueType().getSimpleVT().SimpleTy) { + case MVT::i32: TRC = &X86::GR32_ABCDRegClass; break; + case MVT::i16: TRC = &X86::GR16_ABCDRegClass; break; + default: llvm_unreachable("Unsupported TEST operand type!"); + } + SDValue RC = CurDAG->getTargetConstant(TRC->getID(), MVT::i32); + Reg = SDValue(CurDAG->getMachineNode(X86::COPY_TO_REGCLASS, dl, + Reg.getValueType(), Reg, RC), 0); + } + + // Extract the l-register. + SDValue Subreg = CurDAG->getTargetExtractSubreg(X86::SUBREG_8BIT, dl, + MVT::i8, Reg); + + // Emit a testb. + return CurDAG->getMachineNode(X86::TEST8ri, dl, MVT::i32, Subreg, Imm); + } + + // For example, "testl %eax, $2048" to "testb %ah, $8". + if ((C->getZExtValue() & ~UINT64_C(0xff00)) == 0 && + (!(C->getZExtValue() & 0x8000) || + HasNoSignedComparisonUses(Node))) { + // Shift the immediate right by 8 bits. + SDValue ShiftedImm = CurDAG->getTargetConstant(C->getZExtValue() >> 8, + MVT::i8); + SDValue Reg = N0.getNode()->getOperand(0); + + // Put the value in an ABCD register. + TargetRegisterClass *TRC = 0; + switch (N0.getValueType().getSimpleVT().SimpleTy) { + case MVT::i64: TRC = &X86::GR64_ABCDRegClass; break; + case MVT::i32: TRC = &X86::GR32_ABCDRegClass; break; + case MVT::i16: TRC = &X86::GR16_ABCDRegClass; break; + default: llvm_unreachable("Unsupported TEST operand type!"); + } + SDValue RC = CurDAG->getTargetConstant(TRC->getID(), MVT::i32); + Reg = SDValue(CurDAG->getMachineNode(X86::COPY_TO_REGCLASS, dl, + Reg.getValueType(), Reg, RC), 0); + + // Extract the h-register. + SDValue Subreg = CurDAG->getTargetExtractSubreg(X86::SUBREG_8BIT_HI, dl, + MVT::i8, Reg); + + // Emit a testb. No special NOREX tricks are needed since there's + // only one GPR operand! + return CurDAG->getMachineNode(X86::TEST8ri, dl, MVT::i32, + Subreg, ShiftedImm); + } + + // For example, "testl %eax, $32776" to "testw %ax, $32776". + if ((C->getZExtValue() & ~UINT64_C(0xffff)) == 0 && + N0.getValueType() != MVT::i16 && + (!(C->getZExtValue() & 0x8000) || + HasNoSignedComparisonUses(Node))) { + SDValue Imm = CurDAG->getTargetConstant(C->getZExtValue(), MVT::i16); + SDValue Reg = N0.getNode()->getOperand(0); + + // Extract the 16-bit subregister. + SDValue Subreg = CurDAG->getTargetExtractSubreg(X86::SUBREG_16BIT, dl, + MVT::i16, Reg); + + // Emit a testw. + return CurDAG->getMachineNode(X86::TEST16ri, dl, MVT::i32, Subreg, Imm); + } + + // For example, "testq %rax, $268468232" to "testl %eax, $268468232". + if ((C->getZExtValue() & ~UINT64_C(0xffffffff)) == 0 && + N0.getValueType() == MVT::i64 && + (!(C->getZExtValue() & 0x80000000) || + HasNoSignedComparisonUses(Node))) { + SDValue Imm = CurDAG->getTargetConstant(C->getZExtValue(), MVT::i32); + SDValue Reg = N0.getNode()->getOperand(0); + + // Extract the 32-bit subregister. + SDValue Subreg = CurDAG->getTargetExtractSubreg(X86::SUBREG_32BIT, dl, + MVT::i32, Reg); + + // Emit a testl. + return CurDAG->getMachineNode(X86::TEST32ri, dl, MVT::i32, Subreg, Imm); + } + } + break; + } + } + + SDNode *ResNode = SelectCode(N); + +#ifndef NDEBUG + DEBUG({ + errs() << std::string(Indent-2, ' ') << "=> "; + if (ResNode == NULL || ResNode == N.getNode()) + N.getNode()->dump(CurDAG); + else + ResNode->dump(CurDAG); + errs() << '\n'; + }); + Indent -= 2; +#endif + + return ResNode; +} + +bool X86DAGToDAGISel:: +SelectInlineAsmMemoryOperand(const SDValue &Op, char ConstraintCode, + std::vector &OutOps) { + SDValue Op0, Op1, Op2, Op3, Op4; + switch (ConstraintCode) { + case 'o': // offsetable ?? + case 'v': // not offsetable ?? + default: return true; + case 'm': // memory + if (!SelectAddr(Op, Op, Op0, Op1, Op2, Op3, Op4)) + return true; + break; + } + + OutOps.push_back(Op0); + OutOps.push_back(Op1); + OutOps.push_back(Op2); + OutOps.push_back(Op3); + OutOps.push_back(Op4); + return false; +} + +/// createX86ISelDag - This pass converts a legalized DAG into a +/// X86-specific DAG, ready for instruction scheduling. +/// +FunctionPass *llvm::createX86ISelDag(X86TargetMachine &TM, + llvm::CodeGenOpt::Level OptLevel) { + return new X86DAGToDAGISel(TM, OptLevel); +} diff --git a/libclamav/c++/llvm/lib/Target/X86/X86ISelLowering.cpp b/libclamav/c++/llvm/lib/Target/X86/X86ISelLowering.cpp new file mode 100644 index 000000000..8567ca47b --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/X86/X86ISelLowering.cpp @@ -0,0 +1,9755 @@ +//===-- X86ISelLowering.cpp - X86 DAG Lowering Implementation -------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the interfaces that X86 uses to lower LLVM code into a +// selection DAG. +// +//===----------------------------------------------------------------------===// + +#include "X86.h" +#include "X86InstrBuilder.h" +#include "X86ISelLowering.h" +#include "X86TargetMachine.h" +#include "X86TargetObjectFile.h" +#include "llvm/CallingConv.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/GlobalAlias.h" +#include "llvm/GlobalVariable.h" +#include "llvm/Function.h" +#include "llvm/Instructions.h" +#include "llvm/Intrinsics.h" +#include "llvm/LLVMContext.h" +#include "llvm/ADT/BitVector.h" +#include "llvm/ADT/VectorExtras.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/PseudoSourceValue.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Target/TargetOptions.h" +#include "llvm/ADT/SmallSet.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +static cl::opt +DisableMMX("disable-mmx", cl::Hidden, cl::desc("Disable use of MMX")); + +// Disable16Bit - 16-bit operations typically have a larger encoding than +// corresponding 32-bit instructions, and 16-bit code is slow on some +// processors. This is an experimental flag to disable 16-bit operations +// (which forces them to be Legalized to 32-bit operations). +static cl::opt +Disable16Bit("disable-16bit", cl::Hidden, + cl::desc("Disable use of 16-bit instructions")); + +// Forward declarations. +static SDValue getMOVL(SelectionDAG &DAG, DebugLoc dl, EVT VT, SDValue V1, + SDValue V2); + +static TargetLoweringObjectFile *createTLOF(X86TargetMachine &TM) { + switch (TM.getSubtarget().TargetType) { + default: llvm_unreachable("unknown subtarget type"); + case X86Subtarget::isDarwin: + if (TM.getSubtarget().is64Bit()) + return new X8664_MachoTargetObjectFile(); + return new X8632_MachoTargetObjectFile(); + case X86Subtarget::isELF: + return new TargetLoweringObjectFileELF(); + case X86Subtarget::isMingw: + case X86Subtarget::isCygwin: + case X86Subtarget::isWindows: + return new TargetLoweringObjectFileCOFF(); + } + +} + +X86TargetLowering::X86TargetLowering(X86TargetMachine &TM) + : TargetLowering(TM, createTLOF(TM)) { + Subtarget = &TM.getSubtarget(); + X86ScalarSSEf64 = Subtarget->hasSSE2(); + X86ScalarSSEf32 = Subtarget->hasSSE1(); + X86StackPtr = Subtarget->is64Bit() ? X86::RSP : X86::ESP; + + RegInfo = TM.getRegisterInfo(); + TD = getTargetData(); + + // Set up the TargetLowering object. + + // X86 is weird, it always uses i8 for shift amounts and setcc results. + setShiftAmountType(MVT::i8); + setBooleanContents(ZeroOrOneBooleanContent); + setSchedulingPreference(SchedulingForRegPressure); + setStackPointerRegisterToSaveRestore(X86StackPtr); + + if (Subtarget->isTargetDarwin()) { + // Darwin should use _setjmp/_longjmp instead of setjmp/longjmp. + setUseUnderscoreSetJmp(false); + setUseUnderscoreLongJmp(false); + } else if (Subtarget->isTargetMingw()) { + // MS runtime is weird: it exports _setjmp, but longjmp! + setUseUnderscoreSetJmp(true); + setUseUnderscoreLongJmp(false); + } else { + setUseUnderscoreSetJmp(true); + setUseUnderscoreLongJmp(true); + } + + // Set up the register classes. + addRegisterClass(MVT::i8, X86::GR8RegisterClass); + if (!Disable16Bit) + addRegisterClass(MVT::i16, X86::GR16RegisterClass); + addRegisterClass(MVT::i32, X86::GR32RegisterClass); + if (Subtarget->is64Bit()) + addRegisterClass(MVT::i64, X86::GR64RegisterClass); + + setLoadExtAction(ISD::SEXTLOAD, MVT::i1, Promote); + + // We don't accept any truncstore of integer registers. + setTruncStoreAction(MVT::i64, MVT::i32, Expand); + if (!Disable16Bit) + setTruncStoreAction(MVT::i64, MVT::i16, Expand); + setTruncStoreAction(MVT::i64, MVT::i8 , Expand); + if (!Disable16Bit) + setTruncStoreAction(MVT::i32, MVT::i16, Expand); + setTruncStoreAction(MVT::i32, MVT::i8 , Expand); + setTruncStoreAction(MVT::i16, MVT::i8, Expand); + + // SETOEQ and SETUNE require checking two conditions. + setCondCodeAction(ISD::SETOEQ, MVT::f32, Expand); + setCondCodeAction(ISD::SETOEQ, MVT::f64, Expand); + setCondCodeAction(ISD::SETOEQ, MVT::f80, Expand); + setCondCodeAction(ISD::SETUNE, MVT::f32, Expand); + setCondCodeAction(ISD::SETUNE, MVT::f64, Expand); + setCondCodeAction(ISD::SETUNE, MVT::f80, Expand); + + // Promote all UINT_TO_FP to larger SINT_TO_FP's, as X86 doesn't have this + // operation. + setOperationAction(ISD::UINT_TO_FP , MVT::i1 , Promote); + setOperationAction(ISD::UINT_TO_FP , MVT::i8 , Promote); + setOperationAction(ISD::UINT_TO_FP , MVT::i16 , Promote); + + if (Subtarget->is64Bit()) { + setOperationAction(ISD::UINT_TO_FP , MVT::i32 , Promote); + setOperationAction(ISD::UINT_TO_FP , MVT::i64 , Expand); + } else if (!UseSoftFloat) { + if (X86ScalarSSEf64) { + // We have an impenetrably clever algorithm for ui64->double only. + setOperationAction(ISD::UINT_TO_FP , MVT::i64 , Custom); + } + // We have an algorithm for SSE2, and we turn this into a 64-bit + // FILD for other targets. + setOperationAction(ISD::UINT_TO_FP , MVT::i32 , Custom); + } + + // Promote i1/i8 SINT_TO_FP to larger SINT_TO_FP's, as X86 doesn't have + // this operation. + setOperationAction(ISD::SINT_TO_FP , MVT::i1 , Promote); + setOperationAction(ISD::SINT_TO_FP , MVT::i8 , Promote); + + if (!UseSoftFloat) { + // SSE has no i16 to fp conversion, only i32 + if (X86ScalarSSEf32) { + setOperationAction(ISD::SINT_TO_FP , MVT::i16 , Promote); + // f32 and f64 cases are Legal, f80 case is not + setOperationAction(ISD::SINT_TO_FP , MVT::i32 , Custom); + } else { + setOperationAction(ISD::SINT_TO_FP , MVT::i16 , Custom); + setOperationAction(ISD::SINT_TO_FP , MVT::i32 , Custom); + } + } else { + setOperationAction(ISD::SINT_TO_FP , MVT::i16 , Promote); + setOperationAction(ISD::SINT_TO_FP , MVT::i32 , Promote); + } + + // In 32-bit mode these are custom lowered. In 64-bit mode F32 and F64 + // are Legal, f80 is custom lowered. + setOperationAction(ISD::FP_TO_SINT , MVT::i64 , Custom); + setOperationAction(ISD::SINT_TO_FP , MVT::i64 , Custom); + + // Promote i1/i8 FP_TO_SINT to larger FP_TO_SINTS's, as X86 doesn't have + // this operation. + setOperationAction(ISD::FP_TO_SINT , MVT::i1 , Promote); + setOperationAction(ISD::FP_TO_SINT , MVT::i8 , Promote); + + if (X86ScalarSSEf32) { + setOperationAction(ISD::FP_TO_SINT , MVT::i16 , Promote); + // f32 and f64 cases are Legal, f80 case is not + setOperationAction(ISD::FP_TO_SINT , MVT::i32 , Custom); + } else { + setOperationAction(ISD::FP_TO_SINT , MVT::i16 , Custom); + setOperationAction(ISD::FP_TO_SINT , MVT::i32 , Custom); + } + + // Handle FP_TO_UINT by promoting the destination to a larger signed + // conversion. + setOperationAction(ISD::FP_TO_UINT , MVT::i1 , Promote); + setOperationAction(ISD::FP_TO_UINT , MVT::i8 , Promote); + setOperationAction(ISD::FP_TO_UINT , MVT::i16 , Promote); + + if (Subtarget->is64Bit()) { + setOperationAction(ISD::FP_TO_UINT , MVT::i64 , Expand); + setOperationAction(ISD::FP_TO_UINT , MVT::i32 , Promote); + } else if (!UseSoftFloat) { + if (X86ScalarSSEf32 && !Subtarget->hasSSE3()) + // Expand FP_TO_UINT into a select. + // FIXME: We would like to use a Custom expander here eventually to do + // the optimal thing for SSE vs. the default expansion in the legalizer. + setOperationAction(ISD::FP_TO_UINT , MVT::i32 , Expand); + else + // With SSE3 we can use fisttpll to convert to a signed i64; without + // SSE, we're stuck with a fistpll. + setOperationAction(ISD::FP_TO_UINT , MVT::i32 , Custom); + } + + // TODO: when we have SSE, these could be more efficient, by using movd/movq. + if (!X86ScalarSSEf64) { + setOperationAction(ISD::BIT_CONVERT , MVT::f32 , Expand); + setOperationAction(ISD::BIT_CONVERT , MVT::i32 , Expand); + } + + // Scalar integer divide and remainder are lowered to use operations that + // produce two results, to match the available instructions. This exposes + // the two-result form to trivial CSE, which is able to combine x/y and x%y + // into a single instruction. + // + // Scalar integer multiply-high is also lowered to use two-result + // operations, to match the available instructions. However, plain multiply + // (low) operations are left as Legal, as there are single-result + // instructions for this in x86. Using the two-result multiply instructions + // when both high and low results are needed must be arranged by dagcombine. + setOperationAction(ISD::MULHS , MVT::i8 , Expand); + setOperationAction(ISD::MULHU , MVT::i8 , Expand); + setOperationAction(ISD::SDIV , MVT::i8 , Expand); + setOperationAction(ISD::UDIV , MVT::i8 , Expand); + setOperationAction(ISD::SREM , MVT::i8 , Expand); + setOperationAction(ISD::UREM , MVT::i8 , Expand); + setOperationAction(ISD::MULHS , MVT::i16 , Expand); + setOperationAction(ISD::MULHU , MVT::i16 , Expand); + setOperationAction(ISD::SDIV , MVT::i16 , Expand); + setOperationAction(ISD::UDIV , MVT::i16 , Expand); + setOperationAction(ISD::SREM , MVT::i16 , Expand); + setOperationAction(ISD::UREM , MVT::i16 , Expand); + setOperationAction(ISD::MULHS , MVT::i32 , Expand); + setOperationAction(ISD::MULHU , MVT::i32 , Expand); + setOperationAction(ISD::SDIV , MVT::i32 , Expand); + setOperationAction(ISD::UDIV , MVT::i32 , Expand); + setOperationAction(ISD::SREM , MVT::i32 , Expand); + setOperationAction(ISD::UREM , MVT::i32 , Expand); + setOperationAction(ISD::MULHS , MVT::i64 , Expand); + setOperationAction(ISD::MULHU , MVT::i64 , Expand); + setOperationAction(ISD::SDIV , MVT::i64 , Expand); + setOperationAction(ISD::UDIV , MVT::i64 , Expand); + setOperationAction(ISD::SREM , MVT::i64 , Expand); + setOperationAction(ISD::UREM , MVT::i64 , Expand); + + setOperationAction(ISD::BR_JT , MVT::Other, Expand); + setOperationAction(ISD::BRCOND , MVT::Other, Custom); + setOperationAction(ISD::BR_CC , MVT::Other, Expand); + setOperationAction(ISD::SELECT_CC , MVT::Other, Expand); + if (Subtarget->is64Bit()) + setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i32, Legal); + setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i16 , Legal); + setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i8 , Legal); + setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1 , Expand); + setOperationAction(ISD::FP_ROUND_INREG , MVT::f32 , Expand); + setOperationAction(ISD::FREM , MVT::f32 , Expand); + setOperationAction(ISD::FREM , MVT::f64 , Expand); + setOperationAction(ISD::FREM , MVT::f80 , Expand); + setOperationAction(ISD::FLT_ROUNDS_ , MVT::i32 , Custom); + + setOperationAction(ISD::CTPOP , MVT::i8 , Expand); + setOperationAction(ISD::CTTZ , MVT::i8 , Custom); + setOperationAction(ISD::CTLZ , MVT::i8 , Custom); + setOperationAction(ISD::CTPOP , MVT::i16 , Expand); + if (Disable16Bit) { + setOperationAction(ISD::CTTZ , MVT::i16 , Expand); + setOperationAction(ISD::CTLZ , MVT::i16 , Expand); + } else { + setOperationAction(ISD::CTTZ , MVT::i16 , Custom); + setOperationAction(ISD::CTLZ , MVT::i16 , Custom); + } + setOperationAction(ISD::CTPOP , MVT::i32 , Expand); + setOperationAction(ISD::CTTZ , MVT::i32 , Custom); + setOperationAction(ISD::CTLZ , MVT::i32 , Custom); + if (Subtarget->is64Bit()) { + setOperationAction(ISD::CTPOP , MVT::i64 , Expand); + setOperationAction(ISD::CTTZ , MVT::i64 , Custom); + setOperationAction(ISD::CTLZ , MVT::i64 , Custom); + } + + setOperationAction(ISD::READCYCLECOUNTER , MVT::i64 , Custom); + setOperationAction(ISD::BSWAP , MVT::i16 , Expand); + + // These should be promoted to a larger select which is supported. + setOperationAction(ISD::SELECT , MVT::i1 , Promote); + // X86 wants to expand cmov itself. + setOperationAction(ISD::SELECT , MVT::i8 , Custom); + if (Disable16Bit) + setOperationAction(ISD::SELECT , MVT::i16 , Expand); + else + setOperationAction(ISD::SELECT , MVT::i16 , Custom); + setOperationAction(ISD::SELECT , MVT::i32 , Custom); + setOperationAction(ISD::SELECT , MVT::f32 , Custom); + setOperationAction(ISD::SELECT , MVT::f64 , Custom); + setOperationAction(ISD::SELECT , MVT::f80 , Custom); + setOperationAction(ISD::SETCC , MVT::i8 , Custom); + if (Disable16Bit) + setOperationAction(ISD::SETCC , MVT::i16 , Expand); + else + setOperationAction(ISD::SETCC , MVT::i16 , Custom); + setOperationAction(ISD::SETCC , MVT::i32 , Custom); + setOperationAction(ISD::SETCC , MVT::f32 , Custom); + setOperationAction(ISD::SETCC , MVT::f64 , Custom); + setOperationAction(ISD::SETCC , MVT::f80 , Custom); + if (Subtarget->is64Bit()) { + setOperationAction(ISD::SELECT , MVT::i64 , Custom); + setOperationAction(ISD::SETCC , MVT::i64 , Custom); + } + setOperationAction(ISD::EH_RETURN , MVT::Other, Custom); + + // Darwin ABI issue. + setOperationAction(ISD::ConstantPool , MVT::i32 , Custom); + setOperationAction(ISD::JumpTable , MVT::i32 , Custom); + setOperationAction(ISD::GlobalAddress , MVT::i32 , Custom); + setOperationAction(ISD::GlobalTLSAddress, MVT::i32 , Custom); + if (Subtarget->is64Bit()) + setOperationAction(ISD::GlobalTLSAddress, MVT::i64, Custom); + setOperationAction(ISD::ExternalSymbol , MVT::i32 , Custom); + setOperationAction(ISD::BlockAddress , MVT::i32 , Custom); + if (Subtarget->is64Bit()) { + setOperationAction(ISD::ConstantPool , MVT::i64 , Custom); + setOperationAction(ISD::JumpTable , MVT::i64 , Custom); + setOperationAction(ISD::GlobalAddress , MVT::i64 , Custom); + setOperationAction(ISD::ExternalSymbol, MVT::i64 , Custom); + setOperationAction(ISD::BlockAddress , MVT::i64 , Custom); + } + // 64-bit addm sub, shl, sra, srl (iff 32-bit x86) + setOperationAction(ISD::SHL_PARTS , MVT::i32 , Custom); + setOperationAction(ISD::SRA_PARTS , MVT::i32 , Custom); + setOperationAction(ISD::SRL_PARTS , MVT::i32 , Custom); + if (Subtarget->is64Bit()) { + setOperationAction(ISD::SHL_PARTS , MVT::i64 , Custom); + setOperationAction(ISD::SRA_PARTS , MVT::i64 , Custom); + setOperationAction(ISD::SRL_PARTS , MVT::i64 , Custom); + } + + if (Subtarget->hasSSE1()) + setOperationAction(ISD::PREFETCH , MVT::Other, Legal); + + if (!Subtarget->hasSSE2()) + setOperationAction(ISD::MEMBARRIER , MVT::Other, Expand); + + // Expand certain atomics + setOperationAction(ISD::ATOMIC_CMP_SWAP, MVT::i8, Custom); + setOperationAction(ISD::ATOMIC_CMP_SWAP, MVT::i16, Custom); + setOperationAction(ISD::ATOMIC_CMP_SWAP, MVT::i32, Custom); + setOperationAction(ISD::ATOMIC_CMP_SWAP, MVT::i64, Custom); + + setOperationAction(ISD::ATOMIC_LOAD_SUB, MVT::i8, Custom); + setOperationAction(ISD::ATOMIC_LOAD_SUB, MVT::i16, Custom); + setOperationAction(ISD::ATOMIC_LOAD_SUB, MVT::i32, Custom); + setOperationAction(ISD::ATOMIC_LOAD_SUB, MVT::i64, Custom); + + if (!Subtarget->is64Bit()) { + setOperationAction(ISD::ATOMIC_LOAD_ADD, MVT::i64, Custom); + setOperationAction(ISD::ATOMIC_LOAD_SUB, MVT::i64, Custom); + setOperationAction(ISD::ATOMIC_LOAD_AND, MVT::i64, Custom); + setOperationAction(ISD::ATOMIC_LOAD_OR, MVT::i64, Custom); + setOperationAction(ISD::ATOMIC_LOAD_XOR, MVT::i64, Custom); + setOperationAction(ISD::ATOMIC_LOAD_NAND, MVT::i64, Custom); + setOperationAction(ISD::ATOMIC_SWAP, MVT::i64, Custom); + } + + // FIXME - use subtarget debug flags + if (!Subtarget->isTargetDarwin() && + !Subtarget->isTargetELF() && + !Subtarget->isTargetCygMing()) { + setOperationAction(ISD::EH_LABEL, MVT::Other, Expand); + } + + setOperationAction(ISD::EXCEPTIONADDR, MVT::i64, Expand); + setOperationAction(ISD::EHSELECTION, MVT::i64, Expand); + setOperationAction(ISD::EXCEPTIONADDR, MVT::i32, Expand); + setOperationAction(ISD::EHSELECTION, MVT::i32, Expand); + if (Subtarget->is64Bit()) { + setExceptionPointerRegister(X86::RAX); + setExceptionSelectorRegister(X86::RDX); + } else { + setExceptionPointerRegister(X86::EAX); + setExceptionSelectorRegister(X86::EDX); + } + setOperationAction(ISD::FRAME_TO_ARGS_OFFSET, MVT::i32, Custom); + setOperationAction(ISD::FRAME_TO_ARGS_OFFSET, MVT::i64, Custom); + + setOperationAction(ISD::TRAMPOLINE, MVT::Other, Custom); + + setOperationAction(ISD::TRAP, MVT::Other, Legal); + + // VASTART needs to be custom lowered to use the VarArgsFrameIndex + setOperationAction(ISD::VASTART , MVT::Other, Custom); + setOperationAction(ISD::VAEND , MVT::Other, Expand); + if (Subtarget->is64Bit()) { + setOperationAction(ISD::VAARG , MVT::Other, Custom); + setOperationAction(ISD::VACOPY , MVT::Other, Custom); + } else { + setOperationAction(ISD::VAARG , MVT::Other, Expand); + setOperationAction(ISD::VACOPY , MVT::Other, Expand); + } + + setOperationAction(ISD::STACKSAVE, MVT::Other, Expand); + setOperationAction(ISD::STACKRESTORE, MVT::Other, Expand); + if (Subtarget->is64Bit()) + setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i64, Expand); + if (Subtarget->isTargetCygMing()) + setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32, Custom); + else + setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32, Expand); + + if (!UseSoftFloat && X86ScalarSSEf64) { + // f32 and f64 use SSE. + // Set up the FP register classes. + addRegisterClass(MVT::f32, X86::FR32RegisterClass); + addRegisterClass(MVT::f64, X86::FR64RegisterClass); + + // Use ANDPD to simulate FABS. + setOperationAction(ISD::FABS , MVT::f64, Custom); + setOperationAction(ISD::FABS , MVT::f32, Custom); + + // Use XORP to simulate FNEG. + setOperationAction(ISD::FNEG , MVT::f64, Custom); + setOperationAction(ISD::FNEG , MVT::f32, Custom); + + // Use ANDPD and ORPD to simulate FCOPYSIGN. + setOperationAction(ISD::FCOPYSIGN, MVT::f64, Custom); + setOperationAction(ISD::FCOPYSIGN, MVT::f32, Custom); + + // We don't support sin/cos/fmod + setOperationAction(ISD::FSIN , MVT::f64, Expand); + setOperationAction(ISD::FCOS , MVT::f64, Expand); + setOperationAction(ISD::FSIN , MVT::f32, Expand); + setOperationAction(ISD::FCOS , MVT::f32, Expand); + + // Expand FP immediates into loads from the stack, except for the special + // cases we handle. + addLegalFPImmediate(APFloat(+0.0)); // xorpd + addLegalFPImmediate(APFloat(+0.0f)); // xorps + } else if (!UseSoftFloat && X86ScalarSSEf32) { + // Use SSE for f32, x87 for f64. + // Set up the FP register classes. + addRegisterClass(MVT::f32, X86::FR32RegisterClass); + addRegisterClass(MVT::f64, X86::RFP64RegisterClass); + + // Use ANDPS to simulate FABS. + setOperationAction(ISD::FABS , MVT::f32, Custom); + + // Use XORP to simulate FNEG. + setOperationAction(ISD::FNEG , MVT::f32, Custom); + + setOperationAction(ISD::UNDEF, MVT::f64, Expand); + + // Use ANDPS and ORPS to simulate FCOPYSIGN. + setOperationAction(ISD::FCOPYSIGN, MVT::f64, Expand); + setOperationAction(ISD::FCOPYSIGN, MVT::f32, Custom); + + // We don't support sin/cos/fmod + setOperationAction(ISD::FSIN , MVT::f32, Expand); + setOperationAction(ISD::FCOS , MVT::f32, Expand); + + // Special cases we handle for FP constants. + addLegalFPImmediate(APFloat(+0.0f)); // xorps + addLegalFPImmediate(APFloat(+0.0)); // FLD0 + addLegalFPImmediate(APFloat(+1.0)); // FLD1 + addLegalFPImmediate(APFloat(-0.0)); // FLD0/FCHS + addLegalFPImmediate(APFloat(-1.0)); // FLD1/FCHS + + if (!UnsafeFPMath) { + setOperationAction(ISD::FSIN , MVT::f64 , Expand); + setOperationAction(ISD::FCOS , MVT::f64 , Expand); + } + } else if (!UseSoftFloat) { + // f32 and f64 in x87. + // Set up the FP register classes. + addRegisterClass(MVT::f64, X86::RFP64RegisterClass); + addRegisterClass(MVT::f32, X86::RFP32RegisterClass); + + setOperationAction(ISD::UNDEF, MVT::f64, Expand); + setOperationAction(ISD::UNDEF, MVT::f32, Expand); + setOperationAction(ISD::FCOPYSIGN, MVT::f64, Expand); + setOperationAction(ISD::FCOPYSIGN, MVT::f32, Expand); + + if (!UnsafeFPMath) { + setOperationAction(ISD::FSIN , MVT::f64 , Expand); + setOperationAction(ISD::FCOS , MVT::f64 , Expand); + } + addLegalFPImmediate(APFloat(+0.0)); // FLD0 + addLegalFPImmediate(APFloat(+1.0)); // FLD1 + addLegalFPImmediate(APFloat(-0.0)); // FLD0/FCHS + addLegalFPImmediate(APFloat(-1.0)); // FLD1/FCHS + addLegalFPImmediate(APFloat(+0.0f)); // FLD0 + addLegalFPImmediate(APFloat(+1.0f)); // FLD1 + addLegalFPImmediate(APFloat(-0.0f)); // FLD0/FCHS + addLegalFPImmediate(APFloat(-1.0f)); // FLD1/FCHS + } + + // Long double always uses X87. + if (!UseSoftFloat) { + addRegisterClass(MVT::f80, X86::RFP80RegisterClass); + setOperationAction(ISD::UNDEF, MVT::f80, Expand); + setOperationAction(ISD::FCOPYSIGN, MVT::f80, Expand); + { + bool ignored; + APFloat TmpFlt(+0.0); + TmpFlt.convert(APFloat::x87DoubleExtended, APFloat::rmNearestTiesToEven, + &ignored); + addLegalFPImmediate(TmpFlt); // FLD0 + TmpFlt.changeSign(); + addLegalFPImmediate(TmpFlt); // FLD0/FCHS + APFloat TmpFlt2(+1.0); + TmpFlt2.convert(APFloat::x87DoubleExtended, APFloat::rmNearestTiesToEven, + &ignored); + addLegalFPImmediate(TmpFlt2); // FLD1 + TmpFlt2.changeSign(); + addLegalFPImmediate(TmpFlt2); // FLD1/FCHS + } + + if (!UnsafeFPMath) { + setOperationAction(ISD::FSIN , MVT::f80 , Expand); + setOperationAction(ISD::FCOS , MVT::f80 , Expand); + } + } + + // Always use a library call for pow. + setOperationAction(ISD::FPOW , MVT::f32 , Expand); + setOperationAction(ISD::FPOW , MVT::f64 , Expand); + setOperationAction(ISD::FPOW , MVT::f80 , Expand); + + setOperationAction(ISD::FLOG, MVT::f80, Expand); + setOperationAction(ISD::FLOG2, MVT::f80, Expand); + setOperationAction(ISD::FLOG10, MVT::f80, Expand); + setOperationAction(ISD::FEXP, MVT::f80, Expand); + setOperationAction(ISD::FEXP2, MVT::f80, Expand); + + // First set operation action for all vector types to either promote + // (for widening) or expand (for scalarization). Then we will selectively + // turn on ones that can be effectively codegen'd. + for (unsigned VT = (unsigned)MVT::FIRST_VECTOR_VALUETYPE; + VT <= (unsigned)MVT::LAST_VECTOR_VALUETYPE; ++VT) { + setOperationAction(ISD::ADD , (MVT::SimpleValueType)VT, Expand); + setOperationAction(ISD::SUB , (MVT::SimpleValueType)VT, Expand); + setOperationAction(ISD::FADD, (MVT::SimpleValueType)VT, Expand); + setOperationAction(ISD::FNEG, (MVT::SimpleValueType)VT, Expand); + setOperationAction(ISD::FSUB, (MVT::SimpleValueType)VT, Expand); + setOperationAction(ISD::MUL , (MVT::SimpleValueType)VT, Expand); + setOperationAction(ISD::FMUL, (MVT::SimpleValueType)VT, Expand); + setOperationAction(ISD::SDIV, (MVT::SimpleValueType)VT, Expand); + setOperationAction(ISD::UDIV, (MVT::SimpleValueType)VT, Expand); + setOperationAction(ISD::FDIV, (MVT::SimpleValueType)VT, Expand); + setOperationAction(ISD::SREM, (MVT::SimpleValueType)VT, Expand); + setOperationAction(ISD::UREM, (MVT::SimpleValueType)VT, Expand); + setOperationAction(ISD::LOAD, (MVT::SimpleValueType)VT, Expand); + setOperationAction(ISD::VECTOR_SHUFFLE, (MVT::SimpleValueType)VT, Expand); + setOperationAction(ISD::EXTRACT_VECTOR_ELT,(MVT::SimpleValueType)VT,Expand); + setOperationAction(ISD::EXTRACT_SUBVECTOR,(MVT::SimpleValueType)VT,Expand); + setOperationAction(ISD::INSERT_VECTOR_ELT,(MVT::SimpleValueType)VT, Expand); + setOperationAction(ISD::FABS, (MVT::SimpleValueType)VT, Expand); + setOperationAction(ISD::FSIN, (MVT::SimpleValueType)VT, Expand); + setOperationAction(ISD::FCOS, (MVT::SimpleValueType)VT, Expand); + setOperationAction(ISD::FREM, (MVT::SimpleValueType)VT, Expand); + setOperationAction(ISD::FPOWI, (MVT::SimpleValueType)VT, Expand); + setOperationAction(ISD::FSQRT, (MVT::SimpleValueType)VT, Expand); + setOperationAction(ISD::FCOPYSIGN, (MVT::SimpleValueType)VT, Expand); + setOperationAction(ISD::SMUL_LOHI, (MVT::SimpleValueType)VT, Expand); + setOperationAction(ISD::UMUL_LOHI, (MVT::SimpleValueType)VT, Expand); + setOperationAction(ISD::SDIVREM, (MVT::SimpleValueType)VT, Expand); + setOperationAction(ISD::UDIVREM, (MVT::SimpleValueType)VT, Expand); + setOperationAction(ISD::FPOW, (MVT::SimpleValueType)VT, Expand); + setOperationAction(ISD::CTPOP, (MVT::SimpleValueType)VT, Expand); + setOperationAction(ISD::CTTZ, (MVT::SimpleValueType)VT, Expand); + setOperationAction(ISD::CTLZ, (MVT::SimpleValueType)VT, Expand); + setOperationAction(ISD::SHL, (MVT::SimpleValueType)VT, Expand); + setOperationAction(ISD::SRA, (MVT::SimpleValueType)VT, Expand); + setOperationAction(ISD::SRL, (MVT::SimpleValueType)VT, Expand); + setOperationAction(ISD::ROTL, (MVT::SimpleValueType)VT, Expand); + setOperationAction(ISD::ROTR, (MVT::SimpleValueType)VT, Expand); + setOperationAction(ISD::BSWAP, (MVT::SimpleValueType)VT, Expand); + setOperationAction(ISD::VSETCC, (MVT::SimpleValueType)VT, Expand); + setOperationAction(ISD::FLOG, (MVT::SimpleValueType)VT, Expand); + setOperationAction(ISD::FLOG2, (MVT::SimpleValueType)VT, Expand); + setOperationAction(ISD::FLOG10, (MVT::SimpleValueType)VT, Expand); + setOperationAction(ISD::FEXP, (MVT::SimpleValueType)VT, Expand); + setOperationAction(ISD::FEXP2, (MVT::SimpleValueType)VT, Expand); + setOperationAction(ISD::FP_TO_UINT, (MVT::SimpleValueType)VT, Expand); + setOperationAction(ISD::FP_TO_SINT, (MVT::SimpleValueType)VT, Expand); + setOperationAction(ISD::UINT_TO_FP, (MVT::SimpleValueType)VT, Expand); + setOperationAction(ISD::SINT_TO_FP, (MVT::SimpleValueType)VT, Expand); + } + + // FIXME: In order to prevent SSE instructions being expanded to MMX ones + // with -msoft-float, disable use of MMX as well. + if (!UseSoftFloat && !DisableMMX && Subtarget->hasMMX()) { + addRegisterClass(MVT::v8i8, X86::VR64RegisterClass); + addRegisterClass(MVT::v4i16, X86::VR64RegisterClass); + addRegisterClass(MVT::v2i32, X86::VR64RegisterClass); + addRegisterClass(MVT::v2f32, X86::VR64RegisterClass); + addRegisterClass(MVT::v1i64, X86::VR64RegisterClass); + + setOperationAction(ISD::ADD, MVT::v8i8, Legal); + setOperationAction(ISD::ADD, MVT::v4i16, Legal); + setOperationAction(ISD::ADD, MVT::v2i32, Legal); + setOperationAction(ISD::ADD, MVT::v1i64, Legal); + + setOperationAction(ISD::SUB, MVT::v8i8, Legal); + setOperationAction(ISD::SUB, MVT::v4i16, Legal); + setOperationAction(ISD::SUB, MVT::v2i32, Legal); + setOperationAction(ISD::SUB, MVT::v1i64, Legal); + + setOperationAction(ISD::MULHS, MVT::v4i16, Legal); + setOperationAction(ISD::MUL, MVT::v4i16, Legal); + + setOperationAction(ISD::AND, MVT::v8i8, Promote); + AddPromotedToType (ISD::AND, MVT::v8i8, MVT::v1i64); + setOperationAction(ISD::AND, MVT::v4i16, Promote); + AddPromotedToType (ISD::AND, MVT::v4i16, MVT::v1i64); + setOperationAction(ISD::AND, MVT::v2i32, Promote); + AddPromotedToType (ISD::AND, MVT::v2i32, MVT::v1i64); + setOperationAction(ISD::AND, MVT::v1i64, Legal); + + setOperationAction(ISD::OR, MVT::v8i8, Promote); + AddPromotedToType (ISD::OR, MVT::v8i8, MVT::v1i64); + setOperationAction(ISD::OR, MVT::v4i16, Promote); + AddPromotedToType (ISD::OR, MVT::v4i16, MVT::v1i64); + setOperationAction(ISD::OR, MVT::v2i32, Promote); + AddPromotedToType (ISD::OR, MVT::v2i32, MVT::v1i64); + setOperationAction(ISD::OR, MVT::v1i64, Legal); + + setOperationAction(ISD::XOR, MVT::v8i8, Promote); + AddPromotedToType (ISD::XOR, MVT::v8i8, MVT::v1i64); + setOperationAction(ISD::XOR, MVT::v4i16, Promote); + AddPromotedToType (ISD::XOR, MVT::v4i16, MVT::v1i64); + setOperationAction(ISD::XOR, MVT::v2i32, Promote); + AddPromotedToType (ISD::XOR, MVT::v2i32, MVT::v1i64); + setOperationAction(ISD::XOR, MVT::v1i64, Legal); + + setOperationAction(ISD::LOAD, MVT::v8i8, Promote); + AddPromotedToType (ISD::LOAD, MVT::v8i8, MVT::v1i64); + setOperationAction(ISD::LOAD, MVT::v4i16, Promote); + AddPromotedToType (ISD::LOAD, MVT::v4i16, MVT::v1i64); + setOperationAction(ISD::LOAD, MVT::v2i32, Promote); + AddPromotedToType (ISD::LOAD, MVT::v2i32, MVT::v1i64); + setOperationAction(ISD::LOAD, MVT::v2f32, Promote); + AddPromotedToType (ISD::LOAD, MVT::v2f32, MVT::v1i64); + setOperationAction(ISD::LOAD, MVT::v1i64, Legal); + + setOperationAction(ISD::BUILD_VECTOR, MVT::v8i8, Custom); + setOperationAction(ISD::BUILD_VECTOR, MVT::v4i16, Custom); + setOperationAction(ISD::BUILD_VECTOR, MVT::v2i32, Custom); + setOperationAction(ISD::BUILD_VECTOR, MVT::v2f32, Custom); + setOperationAction(ISD::BUILD_VECTOR, MVT::v1i64, Custom); + + setOperationAction(ISD::VECTOR_SHUFFLE, MVT::v8i8, Custom); + setOperationAction(ISD::VECTOR_SHUFFLE, MVT::v4i16, Custom); + setOperationAction(ISD::VECTOR_SHUFFLE, MVT::v2i32, Custom); + setOperationAction(ISD::VECTOR_SHUFFLE, MVT::v1i64, Custom); + + setOperationAction(ISD::SCALAR_TO_VECTOR, MVT::v2f32, Custom); + setOperationAction(ISD::SCALAR_TO_VECTOR, MVT::v8i8, Custom); + setOperationAction(ISD::SCALAR_TO_VECTOR, MVT::v4i16, Custom); + setOperationAction(ISD::SCALAR_TO_VECTOR, MVT::v1i64, Custom); + + setOperationAction(ISD::INSERT_VECTOR_ELT, MVT::v4i16, Custom); + + setTruncStoreAction(MVT::v8i16, MVT::v8i8, Expand); + setOperationAction(ISD::TRUNCATE, MVT::v8i8, Expand); + setOperationAction(ISD::SELECT, MVT::v8i8, Promote); + setOperationAction(ISD::SELECT, MVT::v4i16, Promote); + setOperationAction(ISD::SELECT, MVT::v2i32, Promote); + setOperationAction(ISD::SELECT, MVT::v1i64, Custom); + setOperationAction(ISD::VSETCC, MVT::v8i8, Custom); + setOperationAction(ISD::VSETCC, MVT::v4i16, Custom); + setOperationAction(ISD::VSETCC, MVT::v2i32, Custom); + } + + if (!UseSoftFloat && Subtarget->hasSSE1()) { + addRegisterClass(MVT::v4f32, X86::VR128RegisterClass); + + setOperationAction(ISD::FADD, MVT::v4f32, Legal); + setOperationAction(ISD::FSUB, MVT::v4f32, Legal); + setOperationAction(ISD::FMUL, MVT::v4f32, Legal); + setOperationAction(ISD::FDIV, MVT::v4f32, Legal); + setOperationAction(ISD::FSQRT, MVT::v4f32, Legal); + setOperationAction(ISD::FNEG, MVT::v4f32, Custom); + setOperationAction(ISD::LOAD, MVT::v4f32, Legal); + setOperationAction(ISD::BUILD_VECTOR, MVT::v4f32, Custom); + setOperationAction(ISD::VECTOR_SHUFFLE, MVT::v4f32, Custom); + setOperationAction(ISD::EXTRACT_VECTOR_ELT, MVT::v4f32, Custom); + setOperationAction(ISD::SELECT, MVT::v4f32, Custom); + setOperationAction(ISD::VSETCC, MVT::v4f32, Custom); + } + + if (!UseSoftFloat && Subtarget->hasSSE2()) { + addRegisterClass(MVT::v2f64, X86::VR128RegisterClass); + + // FIXME: Unfortunately -soft-float and -no-implicit-float means XMM + // registers cannot be used even for integer operations. + addRegisterClass(MVT::v16i8, X86::VR128RegisterClass); + addRegisterClass(MVT::v8i16, X86::VR128RegisterClass); + addRegisterClass(MVT::v4i32, X86::VR128RegisterClass); + addRegisterClass(MVT::v2i64, X86::VR128RegisterClass); + + setOperationAction(ISD::ADD, MVT::v16i8, Legal); + setOperationAction(ISD::ADD, MVT::v8i16, Legal); + setOperationAction(ISD::ADD, MVT::v4i32, Legal); + setOperationAction(ISD::ADD, MVT::v2i64, Legal); + setOperationAction(ISD::MUL, MVT::v2i64, Custom); + setOperationAction(ISD::SUB, MVT::v16i8, Legal); + setOperationAction(ISD::SUB, MVT::v8i16, Legal); + setOperationAction(ISD::SUB, MVT::v4i32, Legal); + setOperationAction(ISD::SUB, MVT::v2i64, Legal); + setOperationAction(ISD::MUL, MVT::v8i16, Legal); + setOperationAction(ISD::FADD, MVT::v2f64, Legal); + setOperationAction(ISD::FSUB, MVT::v2f64, Legal); + setOperationAction(ISD::FMUL, MVT::v2f64, Legal); + setOperationAction(ISD::FDIV, MVT::v2f64, Legal); + setOperationAction(ISD::FSQRT, MVT::v2f64, Legal); + setOperationAction(ISD::FNEG, MVT::v2f64, Custom); + + setOperationAction(ISD::VSETCC, MVT::v2f64, Custom); + setOperationAction(ISD::VSETCC, MVT::v16i8, Custom); + setOperationAction(ISD::VSETCC, MVT::v8i16, Custom); + setOperationAction(ISD::VSETCC, MVT::v4i32, Custom); + + setOperationAction(ISD::SCALAR_TO_VECTOR, MVT::v16i8, Custom); + setOperationAction(ISD::SCALAR_TO_VECTOR, MVT::v8i16, Custom); + setOperationAction(ISD::INSERT_VECTOR_ELT, MVT::v8i16, Custom); + setOperationAction(ISD::INSERT_VECTOR_ELT, MVT::v4i32, Custom); + setOperationAction(ISD::INSERT_VECTOR_ELT, MVT::v4f32, Custom); + + // Custom lower build_vector, vector_shuffle, and extract_vector_elt. + for (unsigned i = (unsigned)MVT::v16i8; i != (unsigned)MVT::v2i64; ++i) { + EVT VT = (MVT::SimpleValueType)i; + // Do not attempt to custom lower non-power-of-2 vectors + if (!isPowerOf2_32(VT.getVectorNumElements())) + continue; + // Do not attempt to custom lower non-128-bit vectors + if (!VT.is128BitVector()) + continue; + setOperationAction(ISD::BUILD_VECTOR, + VT.getSimpleVT().SimpleTy, Custom); + setOperationAction(ISD::VECTOR_SHUFFLE, + VT.getSimpleVT().SimpleTy, Custom); + setOperationAction(ISD::EXTRACT_VECTOR_ELT, + VT.getSimpleVT().SimpleTy, Custom); + } + + setOperationAction(ISD::BUILD_VECTOR, MVT::v2f64, Custom); + setOperationAction(ISD::BUILD_VECTOR, MVT::v2i64, Custom); + setOperationAction(ISD::VECTOR_SHUFFLE, MVT::v2f64, Custom); + setOperationAction(ISD::VECTOR_SHUFFLE, MVT::v2i64, Custom); + setOperationAction(ISD::INSERT_VECTOR_ELT, MVT::v2f64, Custom); + setOperationAction(ISD::EXTRACT_VECTOR_ELT, MVT::v2f64, Custom); + + if (Subtarget->is64Bit()) { + setOperationAction(ISD::INSERT_VECTOR_ELT, MVT::v2i64, Custom); + setOperationAction(ISD::EXTRACT_VECTOR_ELT, MVT::v2i64, Custom); + } + + // Promote v16i8, v8i16, v4i32 load, select, and, or, xor to v2i64. + for (unsigned i = (unsigned)MVT::v16i8; i != (unsigned)MVT::v2i64; i++) { + MVT::SimpleValueType SVT = (MVT::SimpleValueType)i; + EVT VT = SVT; + + // Do not attempt to promote non-128-bit vectors + if (!VT.is128BitVector()) { + continue; + } + setOperationAction(ISD::AND, SVT, Promote); + AddPromotedToType (ISD::AND, SVT, MVT::v2i64); + setOperationAction(ISD::OR, SVT, Promote); + AddPromotedToType (ISD::OR, SVT, MVT::v2i64); + setOperationAction(ISD::XOR, SVT, Promote); + AddPromotedToType (ISD::XOR, SVT, MVT::v2i64); + setOperationAction(ISD::LOAD, SVT, Promote); + AddPromotedToType (ISD::LOAD, SVT, MVT::v2i64); + setOperationAction(ISD::SELECT, SVT, Promote); + AddPromotedToType (ISD::SELECT, SVT, MVT::v2i64); + } + + setTruncStoreAction(MVT::f64, MVT::f32, Expand); + + // Custom lower v2i64 and v2f64 selects. + setOperationAction(ISD::LOAD, MVT::v2f64, Legal); + setOperationAction(ISD::LOAD, MVT::v2i64, Legal); + setOperationAction(ISD::SELECT, MVT::v2f64, Custom); + setOperationAction(ISD::SELECT, MVT::v2i64, Custom); + + setOperationAction(ISD::FP_TO_SINT, MVT::v4i32, Legal); + setOperationAction(ISD::SINT_TO_FP, MVT::v4i32, Legal); + if (!DisableMMX && Subtarget->hasMMX()) { + setOperationAction(ISD::FP_TO_SINT, MVT::v2i32, Custom); + setOperationAction(ISD::SINT_TO_FP, MVT::v2i32, Custom); + } + } + + if (Subtarget->hasSSE41()) { + // FIXME: Do we need to handle scalar-to-vector here? + setOperationAction(ISD::MUL, MVT::v4i32, Legal); + + // i8 and i16 vectors are custom , because the source register and source + // source memory operand types are not the same width. f32 vectors are + // custom since the immediate controlling the insert encodes additional + // information. + setOperationAction(ISD::INSERT_VECTOR_ELT, MVT::v16i8, Custom); + setOperationAction(ISD::INSERT_VECTOR_ELT, MVT::v8i16, Custom); + setOperationAction(ISD::INSERT_VECTOR_ELT, MVT::v4i32, Custom); + setOperationAction(ISD::INSERT_VECTOR_ELT, MVT::v4f32, Custom); + + setOperationAction(ISD::EXTRACT_VECTOR_ELT, MVT::v16i8, Custom); + setOperationAction(ISD::EXTRACT_VECTOR_ELT, MVT::v8i16, Custom); + setOperationAction(ISD::EXTRACT_VECTOR_ELT, MVT::v4i32, Custom); + setOperationAction(ISD::EXTRACT_VECTOR_ELT, MVT::v4f32, Custom); + + if (Subtarget->is64Bit()) { + setOperationAction(ISD::INSERT_VECTOR_ELT, MVT::v2i64, Legal); + setOperationAction(ISD::EXTRACT_VECTOR_ELT, MVT::v2i64, Legal); + } + } + + if (Subtarget->hasSSE42()) { + setOperationAction(ISD::VSETCC, MVT::v2i64, Custom); + } + + if (!UseSoftFloat && Subtarget->hasAVX()) { + addRegisterClass(MVT::v8f32, X86::VR256RegisterClass); + addRegisterClass(MVT::v4f64, X86::VR256RegisterClass); + addRegisterClass(MVT::v8i32, X86::VR256RegisterClass); + addRegisterClass(MVT::v4i64, X86::VR256RegisterClass); + + setOperationAction(ISD::LOAD, MVT::v8f32, Legal); + setOperationAction(ISD::LOAD, MVT::v8i32, Legal); + setOperationAction(ISD::LOAD, MVT::v4f64, Legal); + setOperationAction(ISD::LOAD, MVT::v4i64, Legal); + setOperationAction(ISD::FADD, MVT::v8f32, Legal); + setOperationAction(ISD::FSUB, MVT::v8f32, Legal); + setOperationAction(ISD::FMUL, MVT::v8f32, Legal); + setOperationAction(ISD::FDIV, MVT::v8f32, Legal); + setOperationAction(ISD::FSQRT, MVT::v8f32, Legal); + setOperationAction(ISD::FNEG, MVT::v8f32, Custom); + //setOperationAction(ISD::BUILD_VECTOR, MVT::v8f32, Custom); + //setOperationAction(ISD::VECTOR_SHUFFLE, MVT::v8f32, Custom); + //setOperationAction(ISD::EXTRACT_VECTOR_ELT, MVT::v8f32, Custom); + //setOperationAction(ISD::SELECT, MVT::v8f32, Custom); + //setOperationAction(ISD::VSETCC, MVT::v8f32, Custom); + + // Operations to consider commented out -v16i16 v32i8 + //setOperationAction(ISD::ADD, MVT::v16i16, Legal); + setOperationAction(ISD::ADD, MVT::v8i32, Custom); + setOperationAction(ISD::ADD, MVT::v4i64, Custom); + //setOperationAction(ISD::SUB, MVT::v32i8, Legal); + //setOperationAction(ISD::SUB, MVT::v16i16, Legal); + setOperationAction(ISD::SUB, MVT::v8i32, Custom); + setOperationAction(ISD::SUB, MVT::v4i64, Custom); + //setOperationAction(ISD::MUL, MVT::v16i16, Legal); + setOperationAction(ISD::FADD, MVT::v4f64, Legal); + setOperationAction(ISD::FSUB, MVT::v4f64, Legal); + setOperationAction(ISD::FMUL, MVT::v4f64, Legal); + setOperationAction(ISD::FDIV, MVT::v4f64, Legal); + setOperationAction(ISD::FSQRT, MVT::v4f64, Legal); + setOperationAction(ISD::FNEG, MVT::v4f64, Custom); + + setOperationAction(ISD::VSETCC, MVT::v4f64, Custom); + // setOperationAction(ISD::VSETCC, MVT::v32i8, Custom); + // setOperationAction(ISD::VSETCC, MVT::v16i16, Custom); + setOperationAction(ISD::VSETCC, MVT::v8i32, Custom); + + // setOperationAction(ISD::SCALAR_TO_VECTOR, MVT::v32i8, Custom); + // setOperationAction(ISD::SCALAR_TO_VECTOR, MVT::v16i16, Custom); + // setOperationAction(ISD::INSERT_VECTOR_ELT, MVT::v16i16, Custom); + setOperationAction(ISD::INSERT_VECTOR_ELT, MVT::v8i32, Custom); + setOperationAction(ISD::INSERT_VECTOR_ELT, MVT::v8f32, Custom); + + setOperationAction(ISD::BUILD_VECTOR, MVT::v4f64, Custom); + setOperationAction(ISD::BUILD_VECTOR, MVT::v4i64, Custom); + setOperationAction(ISD::VECTOR_SHUFFLE, MVT::v4f64, Custom); + setOperationAction(ISD::VECTOR_SHUFFLE, MVT::v4i64, Custom); + setOperationAction(ISD::INSERT_VECTOR_ELT, MVT::v4f64, Custom); + setOperationAction(ISD::EXTRACT_VECTOR_ELT, MVT::v4f64, Custom); + +#if 0 + // Not sure we want to do this since there are no 256-bit integer + // operations in AVX + + // Custom lower build_vector, vector_shuffle, and extract_vector_elt. + // This includes 256-bit vectors + for (unsigned i = (unsigned)MVT::v16i8; i != (unsigned)MVT::v4i64; ++i) { + EVT VT = (MVT::SimpleValueType)i; + + // Do not attempt to custom lower non-power-of-2 vectors + if (!isPowerOf2_32(VT.getVectorNumElements())) + continue; + + setOperationAction(ISD::BUILD_VECTOR, VT, Custom); + setOperationAction(ISD::VECTOR_SHUFFLE, VT, Custom); + setOperationAction(ISD::EXTRACT_VECTOR_ELT, VT, Custom); + } + + if (Subtarget->is64Bit()) { + setOperationAction(ISD::INSERT_VECTOR_ELT, MVT::v4i64, Custom); + setOperationAction(ISD::EXTRACT_VECTOR_ELT, MVT::v4i64, Custom); + } +#endif + +#if 0 + // Not sure we want to do this since there are no 256-bit integer + // operations in AVX + + // Promote v32i8, v16i16, v8i32 load, select, and, or, xor to v4i64. + // Including 256-bit vectors + for (unsigned i = (unsigned)MVT::v16i8; i != (unsigned)MVT::v4i64; i++) { + EVT VT = (MVT::SimpleValueType)i; + + if (!VT.is256BitVector()) { + continue; + } + setOperationAction(ISD::AND, VT, Promote); + AddPromotedToType (ISD::AND, VT, MVT::v4i64); + setOperationAction(ISD::OR, VT, Promote); + AddPromotedToType (ISD::OR, VT, MVT::v4i64); + setOperationAction(ISD::XOR, VT, Promote); + AddPromotedToType (ISD::XOR, VT, MVT::v4i64); + setOperationAction(ISD::LOAD, VT, Promote); + AddPromotedToType (ISD::LOAD, VT, MVT::v4i64); + setOperationAction(ISD::SELECT, VT, Promote); + AddPromotedToType (ISD::SELECT, VT, MVT::v4i64); + } + + setTruncStoreAction(MVT::f64, MVT::f32, Expand); +#endif + } + + // We want to custom lower some of our intrinsics. + setOperationAction(ISD::INTRINSIC_WO_CHAIN, MVT::Other, Custom); + + // Add/Sub/Mul with overflow operations are custom lowered. + setOperationAction(ISD::SADDO, MVT::i32, Custom); + setOperationAction(ISD::SADDO, MVT::i64, Custom); + setOperationAction(ISD::UADDO, MVT::i32, Custom); + setOperationAction(ISD::UADDO, MVT::i64, Custom); + setOperationAction(ISD::SSUBO, MVT::i32, Custom); + setOperationAction(ISD::SSUBO, MVT::i64, Custom); + setOperationAction(ISD::USUBO, MVT::i32, Custom); + setOperationAction(ISD::USUBO, MVT::i64, Custom); + setOperationAction(ISD::SMULO, MVT::i32, Custom); + setOperationAction(ISD::SMULO, MVT::i64, Custom); + + if (!Subtarget->is64Bit()) { + // These libcalls are not available in 32-bit. + setLibcallName(RTLIB::SHL_I128, 0); + setLibcallName(RTLIB::SRL_I128, 0); + setLibcallName(RTLIB::SRA_I128, 0); + } + + // We have target-specific dag combine patterns for the following nodes: + setTargetDAGCombine(ISD::VECTOR_SHUFFLE); + setTargetDAGCombine(ISD::BUILD_VECTOR); + setTargetDAGCombine(ISD::SELECT); + setTargetDAGCombine(ISD::SHL); + setTargetDAGCombine(ISD::SRA); + setTargetDAGCombine(ISD::SRL); + setTargetDAGCombine(ISD::STORE); + setTargetDAGCombine(ISD::MEMBARRIER); + if (Subtarget->is64Bit()) + setTargetDAGCombine(ISD::MUL); + + computeRegisterProperties(); + + // FIXME: These should be based on subtarget info. Plus, the values should + // be smaller when we are in optimizing for size mode. + maxStoresPerMemset = 16; // For @llvm.memset -> sequence of stores + maxStoresPerMemcpy = 16; // For @llvm.memcpy -> sequence of stores + maxStoresPerMemmove = 3; // For @llvm.memmove -> sequence of stores + setPrefLoopAlignment(16); + benefitFromCodePlacementOpt = true; +} + + +MVT::SimpleValueType X86TargetLowering::getSetCCResultType(EVT VT) const { + return MVT::i8; +} + + +/// getMaxByValAlign - Helper for getByValTypeAlignment to determine +/// the desired ByVal argument alignment. +static void getMaxByValAlign(const Type *Ty, unsigned &MaxAlign) { + if (MaxAlign == 16) + return; + if (const VectorType *VTy = dyn_cast(Ty)) { + if (VTy->getBitWidth() == 128) + MaxAlign = 16; + } else if (const ArrayType *ATy = dyn_cast(Ty)) { + unsigned EltAlign = 0; + getMaxByValAlign(ATy->getElementType(), EltAlign); + if (EltAlign > MaxAlign) + MaxAlign = EltAlign; + } else if (const StructType *STy = dyn_cast(Ty)) { + for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) { + unsigned EltAlign = 0; + getMaxByValAlign(STy->getElementType(i), EltAlign); + if (EltAlign > MaxAlign) + MaxAlign = EltAlign; + if (MaxAlign == 16) + break; + } + } + return; +} + +/// getByValTypeAlignment - Return the desired alignment for ByVal aggregate +/// function arguments in the caller parameter area. For X86, aggregates +/// that contain SSE vectors are placed at 16-byte boundaries while the rest +/// are at 4-byte boundaries. +unsigned X86TargetLowering::getByValTypeAlignment(const Type *Ty) const { + if (Subtarget->is64Bit()) { + // Max of 8 and alignment of type. + unsigned TyAlign = TD->getABITypeAlignment(Ty); + if (TyAlign > 8) + return TyAlign; + return 8; + } + + unsigned Align = 4; + if (Subtarget->hasSSE1()) + getMaxByValAlign(Ty, Align); + return Align; +} + +/// getOptimalMemOpType - Returns the target specific optimal type for load +/// and store operations as a result of memset, memcpy, and memmove +/// lowering. It returns MVT::iAny if SelectionDAG should be responsible for +/// determining it. +EVT +X86TargetLowering::getOptimalMemOpType(uint64_t Size, unsigned Align, + bool isSrcConst, bool isSrcStr, + SelectionDAG &DAG) const { + // FIXME: This turns off use of xmm stores for memset/memcpy on targets like + // linux. This is because the stack realignment code can't handle certain + // cases like PR2962. This should be removed when PR2962 is fixed. + const Function *F = DAG.getMachineFunction().getFunction(); + bool NoImplicitFloatOps = F->hasFnAttr(Attribute::NoImplicitFloat); + if (!NoImplicitFloatOps && Subtarget->getStackAlignment() >= 16) { + if ((isSrcConst || isSrcStr) && Subtarget->hasSSE2() && Size >= 16) + return MVT::v4i32; + if ((isSrcConst || isSrcStr) && Subtarget->hasSSE1() && Size >= 16) + return MVT::v4f32; + } + if (Subtarget->is64Bit() && Size >= 8) + return MVT::i64; + return MVT::i32; +} + +/// getPICJumpTableRelocaBase - Returns relocation base for the given PIC +/// jumptable. +SDValue X86TargetLowering::getPICJumpTableRelocBase(SDValue Table, + SelectionDAG &DAG) const { + if (usesGlobalOffsetTable()) + return DAG.getGLOBAL_OFFSET_TABLE(getPointerTy()); + if (!Subtarget->is64Bit()) + // This doesn't have DebugLoc associated with it, but is not really the + // same as a Register. + return DAG.getNode(X86ISD::GlobalBaseReg, DebugLoc::getUnknownLoc(), + getPointerTy()); + return Table; +} + +/// getFunctionAlignment - Return the Log2 alignment of this function. +unsigned X86TargetLowering::getFunctionAlignment(const Function *F) const { + return F->hasFnAttr(Attribute::OptimizeForSize) ? 0 : 4; +} + +//===----------------------------------------------------------------------===// +// Return Value Calling Convention Implementation +//===----------------------------------------------------------------------===// + +#include "X86GenCallingConv.inc" + +bool +X86TargetLowering::CanLowerReturn(CallingConv::ID CallConv, bool isVarArg, + const SmallVectorImpl &OutTys, + const SmallVectorImpl &ArgsFlags, + SelectionDAG &DAG) { + SmallVector RVLocs; + CCState CCInfo(CallConv, isVarArg, getTargetMachine(), + RVLocs, *DAG.getContext()); + return CCInfo.CheckReturn(OutTys, ArgsFlags, RetCC_X86); +} + +SDValue +X86TargetLowering::LowerReturn(SDValue Chain, + CallingConv::ID CallConv, bool isVarArg, + const SmallVectorImpl &Outs, + DebugLoc dl, SelectionDAG &DAG) { + + SmallVector RVLocs; + CCState CCInfo(CallConv, isVarArg, getTargetMachine(), + RVLocs, *DAG.getContext()); + CCInfo.AnalyzeReturn(Outs, RetCC_X86); + + // If this is the first return lowered for this function, add the regs to the + // liveout set for the function. + if (DAG.getMachineFunction().getRegInfo().liveout_empty()) { + for (unsigned i = 0; i != RVLocs.size(); ++i) + if (RVLocs[i].isRegLoc()) + DAG.getMachineFunction().getRegInfo().addLiveOut(RVLocs[i].getLocReg()); + } + + SDValue Flag; + + SmallVector RetOps; + RetOps.push_back(Chain); // Operand #0 = Chain (updated below) + // Operand #1 = Bytes To Pop + RetOps.push_back(DAG.getTargetConstant(getBytesToPopOnReturn(), MVT::i16)); + + // Copy the result values into the output registers. + for (unsigned i = 0; i != RVLocs.size(); ++i) { + CCValAssign &VA = RVLocs[i]; + assert(VA.isRegLoc() && "Can only return in registers!"); + SDValue ValToCopy = Outs[i].Val; + + // Returns in ST0/ST1 are handled specially: these are pushed as operands to + // the RET instruction and handled by the FP Stackifier. + if (VA.getLocReg() == X86::ST0 || + VA.getLocReg() == X86::ST1) { + // If this is a copy from an xmm register to ST(0), use an FPExtend to + // change the value to the FP stack register class. + if (isScalarFPTypeInSSEReg(VA.getValVT())) + ValToCopy = DAG.getNode(ISD::FP_EXTEND, dl, MVT::f80, ValToCopy); + RetOps.push_back(ValToCopy); + // Don't emit a copytoreg. + continue; + } + + // 64-bit vector (MMX) values are returned in XMM0 / XMM1 except for v1i64 + // which is returned in RAX / RDX. + if (Subtarget->is64Bit()) { + EVT ValVT = ValToCopy.getValueType(); + if (ValVT.isVector() && ValVT.getSizeInBits() == 64) { + ValToCopy = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::i64, ValToCopy); + if (VA.getLocReg() == X86::XMM0 || VA.getLocReg() == X86::XMM1) + ValToCopy = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, MVT::v2i64, ValToCopy); + } + } + + Chain = DAG.getCopyToReg(Chain, dl, VA.getLocReg(), ValToCopy, Flag); + Flag = Chain.getValue(1); + } + + // The x86-64 ABI for returning structs by value requires that we copy + // the sret argument into %rax for the return. We saved the argument into + // a virtual register in the entry block, so now we copy the value out + // and into %rax. + if (Subtarget->is64Bit() && + DAG.getMachineFunction().getFunction()->hasStructRetAttr()) { + MachineFunction &MF = DAG.getMachineFunction(); + X86MachineFunctionInfo *FuncInfo = MF.getInfo(); + unsigned Reg = FuncInfo->getSRetReturnReg(); + if (!Reg) { + Reg = MF.getRegInfo().createVirtualRegister(getRegClassFor(MVT::i64)); + FuncInfo->setSRetReturnReg(Reg); + } + SDValue Val = DAG.getCopyFromReg(Chain, dl, Reg, getPointerTy()); + + Chain = DAG.getCopyToReg(Chain, dl, X86::RAX, Val, Flag); + Flag = Chain.getValue(1); + + // RAX now acts like a return value. + MF.getRegInfo().addLiveOut(X86::RAX); + } + + RetOps[0] = Chain; // Update chain. + + // Add the flag if we have it. + if (Flag.getNode()) + RetOps.push_back(Flag); + + return DAG.getNode(X86ISD::RET_FLAG, dl, + MVT::Other, &RetOps[0], RetOps.size()); +} + +/// LowerCallResult - Lower the result values of a call into the +/// appropriate copies out of appropriate physical registers. +/// +SDValue +X86TargetLowering::LowerCallResult(SDValue Chain, SDValue InFlag, + CallingConv::ID CallConv, bool isVarArg, + const SmallVectorImpl &Ins, + DebugLoc dl, SelectionDAG &DAG, + SmallVectorImpl &InVals) { + + // Assign locations to each value returned by this call. + SmallVector RVLocs; + bool Is64Bit = Subtarget->is64Bit(); + CCState CCInfo(CallConv, isVarArg, getTargetMachine(), + RVLocs, *DAG.getContext()); + CCInfo.AnalyzeCallResult(Ins, RetCC_X86); + + // Copy all of the result registers out of their specified physreg. + for (unsigned i = 0; i != RVLocs.size(); ++i) { + CCValAssign &VA = RVLocs[i]; + EVT CopyVT = VA.getValVT(); + + // If this is x86-64, and we disabled SSE, we can't return FP values + if ((CopyVT == MVT::f32 || CopyVT == MVT::f64) && + ((Is64Bit || Ins[i].Flags.isInReg()) && !Subtarget->hasSSE1())) { + llvm_report_error("SSE register return with SSE disabled"); + } + + // If this is a call to a function that returns an fp value on the floating + // point stack, but where we prefer to use the value in xmm registers, copy + // it out as F80 and use a truncate to move it from fp stack reg to xmm reg. + if ((VA.getLocReg() == X86::ST0 || + VA.getLocReg() == X86::ST1) && + isScalarFPTypeInSSEReg(VA.getValVT())) { + CopyVT = MVT::f80; + } + + SDValue Val; + if (Is64Bit && CopyVT.isVector() && CopyVT.getSizeInBits() == 64) { + // For x86-64, MMX values are returned in XMM0 / XMM1 except for v1i64. + if (VA.getLocReg() == X86::XMM0 || VA.getLocReg() == X86::XMM1) { + Chain = DAG.getCopyFromReg(Chain, dl, VA.getLocReg(), + MVT::v2i64, InFlag).getValue(1); + Val = Chain.getValue(0); + Val = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, MVT::i64, + Val, DAG.getConstant(0, MVT::i64)); + } else { + Chain = DAG.getCopyFromReg(Chain, dl, VA.getLocReg(), + MVT::i64, InFlag).getValue(1); + Val = Chain.getValue(0); + } + Val = DAG.getNode(ISD::BIT_CONVERT, dl, CopyVT, Val); + } else { + Chain = DAG.getCopyFromReg(Chain, dl, VA.getLocReg(), + CopyVT, InFlag).getValue(1); + Val = Chain.getValue(0); + } + InFlag = Chain.getValue(2); + + if (CopyVT != VA.getValVT()) { + // Round the F80 the right size, which also moves to the appropriate xmm + // register. + Val = DAG.getNode(ISD::FP_ROUND, dl, VA.getValVT(), Val, + // This truncation won't change the value. + DAG.getIntPtrConstant(1)); + } + + InVals.push_back(Val); + } + + return Chain; +} + + +//===----------------------------------------------------------------------===// +// C & StdCall & Fast Calling Convention implementation +//===----------------------------------------------------------------------===// +// StdCall calling convention seems to be standard for many Windows' API +// routines and around. It differs from C calling convention just a little: +// callee should clean up the stack, not caller. Symbols should be also +// decorated in some fancy way :) It doesn't support any vector arguments. +// For info on fast calling convention see Fast Calling Convention (tail call) +// implementation LowerX86_32FastCCCallTo. + +/// CallIsStructReturn - Determines whether a call uses struct return +/// semantics. +static bool CallIsStructReturn(const SmallVectorImpl &Outs) { + if (Outs.empty()) + return false; + + return Outs[0].Flags.isSRet(); +} + +/// ArgsAreStructReturn - Determines whether a function uses struct +/// return semantics. +static bool +ArgsAreStructReturn(const SmallVectorImpl &Ins) { + if (Ins.empty()) + return false; + + return Ins[0].Flags.isSRet(); +} + +/// IsCalleePop - Determines whether the callee is required to pop its +/// own arguments. Callee pop is necessary to support tail calls. +bool X86TargetLowering::IsCalleePop(bool IsVarArg, CallingConv::ID CallingConv){ + if (IsVarArg) + return false; + + switch (CallingConv) { + default: + return false; + case CallingConv::X86_StdCall: + return !Subtarget->is64Bit(); + case CallingConv::X86_FastCall: + return !Subtarget->is64Bit(); + case CallingConv::Fast: + return PerformTailCallOpt; + } +} + +/// CCAssignFnForNode - Selects the correct CCAssignFn for a the +/// given CallingConvention value. +CCAssignFn *X86TargetLowering::CCAssignFnForNode(CallingConv::ID CC) const { + if (Subtarget->is64Bit()) { + if (Subtarget->isTargetWin64()) + return CC_X86_Win64_C; + else + return CC_X86_64_C; + } + + if (CC == CallingConv::X86_FastCall) + return CC_X86_32_FastCall; + else if (CC == CallingConv::Fast) + return CC_X86_32_FastCC; + else + return CC_X86_32_C; +} + +/// NameDecorationForCallConv - Selects the appropriate decoration to +/// apply to a MachineFunction containing a given calling convention. +NameDecorationStyle +X86TargetLowering::NameDecorationForCallConv(CallingConv::ID CallConv) { + if (CallConv == CallingConv::X86_FastCall) + return FastCall; + else if (CallConv == CallingConv::X86_StdCall) + return StdCall; + return None; +} + + +/// CreateCopyOfByValArgument - Make a copy of an aggregate at address specified +/// by "Src" to address "Dst" with size and alignment information specified by +/// the specific parameter attribute. The copy will be passed as a byval +/// function parameter. +static SDValue +CreateCopyOfByValArgument(SDValue Src, SDValue Dst, SDValue Chain, + ISD::ArgFlagsTy Flags, SelectionDAG &DAG, + DebugLoc dl) { + SDValue SizeNode = DAG.getConstant(Flags.getByValSize(), MVT::i32); + return DAG.getMemcpy(Chain, dl, Dst, Src, SizeNode, Flags.getByValAlign(), + /*AlwaysInline=*/true, NULL, 0, NULL, 0); +} + +SDValue +X86TargetLowering::LowerMemArgument(SDValue Chain, + CallingConv::ID CallConv, + const SmallVectorImpl &Ins, + DebugLoc dl, SelectionDAG &DAG, + const CCValAssign &VA, + MachineFrameInfo *MFI, + unsigned i) { + + // Create the nodes corresponding to a load from this parameter slot. + ISD::ArgFlagsTy Flags = Ins[i].Flags; + bool AlwaysUseMutable = (CallConv==CallingConv::Fast) && PerformTailCallOpt; + bool isImmutable = !AlwaysUseMutable && !Flags.isByVal(); + EVT ValVT; + + // If value is passed by pointer we have address passed instead of the value + // itself. + if (VA.getLocInfo() == CCValAssign::Indirect) + ValVT = VA.getLocVT(); + else + ValVT = VA.getValVT(); + + // FIXME: For now, all byval parameter objects are marked mutable. This can be + // changed with more analysis. + // In case of tail call optimization mark all arguments mutable. Since they + // could be overwritten by lowering of arguments in case of a tail call. + int FI = MFI->CreateFixedObject(ValVT.getSizeInBits()/8, + VA.getLocMemOffset(), isImmutable, false); + SDValue FIN = DAG.getFrameIndex(FI, getPointerTy()); + if (Flags.isByVal()) + return FIN; + return DAG.getLoad(ValVT, dl, Chain, FIN, + PseudoSourceValue::getFixedStack(FI), 0); +} + +SDValue +X86TargetLowering::LowerFormalArguments(SDValue Chain, + CallingConv::ID CallConv, + bool isVarArg, + const SmallVectorImpl &Ins, + DebugLoc dl, + SelectionDAG &DAG, + SmallVectorImpl &InVals) { + + MachineFunction &MF = DAG.getMachineFunction(); + X86MachineFunctionInfo *FuncInfo = MF.getInfo(); + + const Function* Fn = MF.getFunction(); + if (Fn->hasExternalLinkage() && + Subtarget->isTargetCygMing() && + Fn->getName() == "main") + FuncInfo->setForceFramePointer(true); + + // Decorate the function name. + FuncInfo->setDecorationStyle(NameDecorationForCallConv(CallConv)); + + MachineFrameInfo *MFI = MF.getFrameInfo(); + bool Is64Bit = Subtarget->is64Bit(); + bool IsWin64 = Subtarget->isTargetWin64(); + + assert(!(isVarArg && CallConv == CallingConv::Fast) && + "Var args not supported with calling convention fastcc"); + + // Assign locations to all of the incoming arguments. + SmallVector ArgLocs; + CCState CCInfo(CallConv, isVarArg, getTargetMachine(), + ArgLocs, *DAG.getContext()); + CCInfo.AnalyzeFormalArguments(Ins, CCAssignFnForNode(CallConv)); + + unsigned LastVal = ~0U; + SDValue ArgValue; + for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { + CCValAssign &VA = ArgLocs[i]; + // TODO: If an arg is passed in two places (e.g. reg and stack), skip later + // places. + assert(VA.getValNo() != LastVal && + "Don't support value assigned to multiple locs yet"); + LastVal = VA.getValNo(); + + if (VA.isRegLoc()) { + EVT RegVT = VA.getLocVT(); + TargetRegisterClass *RC = NULL; + if (RegVT == MVT::i32) + RC = X86::GR32RegisterClass; + else if (Is64Bit && RegVT == MVT::i64) + RC = X86::GR64RegisterClass; + else if (RegVT == MVT::f32) + RC = X86::FR32RegisterClass; + else if (RegVT == MVT::f64) + RC = X86::FR64RegisterClass; + else if (RegVT.isVector() && RegVT.getSizeInBits() == 128) + RC = X86::VR128RegisterClass; + else if (RegVT.isVector() && RegVT.getSizeInBits() == 64) + RC = X86::VR64RegisterClass; + else + llvm_unreachable("Unknown argument type!"); + + unsigned Reg = MF.addLiveIn(VA.getLocReg(), RC); + ArgValue = DAG.getCopyFromReg(Chain, dl, Reg, RegVT); + + // If this is an 8 or 16-bit value, it is really passed promoted to 32 + // bits. Insert an assert[sz]ext to capture this, then truncate to the + // right size. + if (VA.getLocInfo() == CCValAssign::SExt) + ArgValue = DAG.getNode(ISD::AssertSext, dl, RegVT, ArgValue, + DAG.getValueType(VA.getValVT())); + else if (VA.getLocInfo() == CCValAssign::ZExt) + ArgValue = DAG.getNode(ISD::AssertZext, dl, RegVT, ArgValue, + DAG.getValueType(VA.getValVT())); + else if (VA.getLocInfo() == CCValAssign::BCvt) + ArgValue = DAG.getNode(ISD::BIT_CONVERT, dl, VA.getValVT(), ArgValue); + + if (VA.isExtInLoc()) { + // Handle MMX values passed in XMM regs. + if (RegVT.isVector()) { + ArgValue = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, MVT::i64, + ArgValue, DAG.getConstant(0, MVT::i64)); + ArgValue = DAG.getNode(ISD::BIT_CONVERT, dl, VA.getValVT(), ArgValue); + } else + ArgValue = DAG.getNode(ISD::TRUNCATE, dl, VA.getValVT(), ArgValue); + } + } else { + assert(VA.isMemLoc()); + ArgValue = LowerMemArgument(Chain, CallConv, Ins, dl, DAG, VA, MFI, i); + } + + // If value is passed via pointer - do a load. + if (VA.getLocInfo() == CCValAssign::Indirect) + ArgValue = DAG.getLoad(VA.getValVT(), dl, Chain, ArgValue, NULL, 0); + + InVals.push_back(ArgValue); + } + + // The x86-64 ABI for returning structs by value requires that we copy + // the sret argument into %rax for the return. Save the argument into + // a virtual register so that we can access it from the return points. + if (Is64Bit && MF.getFunction()->hasStructRetAttr()) { + X86MachineFunctionInfo *FuncInfo = MF.getInfo(); + unsigned Reg = FuncInfo->getSRetReturnReg(); + if (!Reg) { + Reg = MF.getRegInfo().createVirtualRegister(getRegClassFor(MVT::i64)); + FuncInfo->setSRetReturnReg(Reg); + } + SDValue Copy = DAG.getCopyToReg(DAG.getEntryNode(), dl, Reg, InVals[0]); + Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Copy, Chain); + } + + unsigned StackSize = CCInfo.getNextStackOffset(); + // align stack specially for tail calls + if (PerformTailCallOpt && CallConv == CallingConv::Fast) + StackSize = GetAlignedArgumentStackSize(StackSize, DAG); + + // If the function takes variable number of arguments, make a frame index for + // the start of the first vararg value... for expansion of llvm.va_start. + if (isVarArg) { + if (Is64Bit || CallConv != CallingConv::X86_FastCall) { + VarArgsFrameIndex = MFI->CreateFixedObject(1, StackSize, true, false); + } + if (Is64Bit) { + unsigned TotalNumIntRegs = 0, TotalNumXMMRegs = 0; + + // FIXME: We should really autogenerate these arrays + static const unsigned GPR64ArgRegsWin64[] = { + X86::RCX, X86::RDX, X86::R8, X86::R9 + }; + static const unsigned XMMArgRegsWin64[] = { + X86::XMM0, X86::XMM1, X86::XMM2, X86::XMM3 + }; + static const unsigned GPR64ArgRegs64Bit[] = { + X86::RDI, X86::RSI, X86::RDX, X86::RCX, X86::R8, X86::R9 + }; + static const unsigned XMMArgRegs64Bit[] = { + X86::XMM0, X86::XMM1, X86::XMM2, X86::XMM3, + X86::XMM4, X86::XMM5, X86::XMM6, X86::XMM7 + }; + const unsigned *GPR64ArgRegs, *XMMArgRegs; + + if (IsWin64) { + TotalNumIntRegs = 4; TotalNumXMMRegs = 4; + GPR64ArgRegs = GPR64ArgRegsWin64; + XMMArgRegs = XMMArgRegsWin64; + } else { + TotalNumIntRegs = 6; TotalNumXMMRegs = 8; + GPR64ArgRegs = GPR64ArgRegs64Bit; + XMMArgRegs = XMMArgRegs64Bit; + } + unsigned NumIntRegs = CCInfo.getFirstUnallocated(GPR64ArgRegs, + TotalNumIntRegs); + unsigned NumXMMRegs = CCInfo.getFirstUnallocated(XMMArgRegs, + TotalNumXMMRegs); + + bool NoImplicitFloatOps = Fn->hasFnAttr(Attribute::NoImplicitFloat); + assert(!(NumXMMRegs && !Subtarget->hasSSE1()) && + "SSE register cannot be used when SSE is disabled!"); + assert(!(NumXMMRegs && UseSoftFloat && NoImplicitFloatOps) && + "SSE register cannot be used when SSE is disabled!"); + if (UseSoftFloat || NoImplicitFloatOps || !Subtarget->hasSSE1()) + // Kernel mode asks for SSE to be disabled, so don't push them + // on the stack. + TotalNumXMMRegs = 0; + + // For X86-64, if there are vararg parameters that are passed via + // registers, then we must store them to their spots on the stack so they + // may be loaded by deferencing the result of va_next. + VarArgsGPOffset = NumIntRegs * 8; + VarArgsFPOffset = TotalNumIntRegs * 8 + NumXMMRegs * 16; + RegSaveFrameIndex = MFI->CreateStackObject(TotalNumIntRegs * 8 + + TotalNumXMMRegs * 16, 16, + false); + + // Store the integer parameter registers. + SmallVector MemOps; + SDValue RSFIN = DAG.getFrameIndex(RegSaveFrameIndex, getPointerTy()); + unsigned Offset = VarArgsGPOffset; + for (; NumIntRegs != TotalNumIntRegs; ++NumIntRegs) { + SDValue FIN = DAG.getNode(ISD::ADD, dl, getPointerTy(), RSFIN, + DAG.getIntPtrConstant(Offset)); + unsigned VReg = MF.addLiveIn(GPR64ArgRegs[NumIntRegs], + X86::GR64RegisterClass); + SDValue Val = DAG.getCopyFromReg(Chain, dl, VReg, MVT::i64); + SDValue Store = + DAG.getStore(Val.getValue(1), dl, Val, FIN, + PseudoSourceValue::getFixedStack(RegSaveFrameIndex), + Offset); + MemOps.push_back(Store); + Offset += 8; + } + + if (TotalNumXMMRegs != 0 && NumXMMRegs != TotalNumXMMRegs) { + // Now store the XMM (fp + vector) parameter registers. + SmallVector SaveXMMOps; + SaveXMMOps.push_back(Chain); + + unsigned AL = MF.addLiveIn(X86::AL, X86::GR8RegisterClass); + SDValue ALVal = DAG.getCopyFromReg(DAG.getEntryNode(), dl, AL, MVT::i8); + SaveXMMOps.push_back(ALVal); + + SaveXMMOps.push_back(DAG.getIntPtrConstant(RegSaveFrameIndex)); + SaveXMMOps.push_back(DAG.getIntPtrConstant(VarArgsFPOffset)); + + for (; NumXMMRegs != TotalNumXMMRegs; ++NumXMMRegs) { + unsigned VReg = MF.addLiveIn(XMMArgRegs[NumXMMRegs], + X86::VR128RegisterClass); + SDValue Val = DAG.getCopyFromReg(Chain, dl, VReg, MVT::v4f32); + SaveXMMOps.push_back(Val); + } + MemOps.push_back(DAG.getNode(X86ISD::VASTART_SAVE_XMM_REGS, dl, + MVT::Other, + &SaveXMMOps[0], SaveXMMOps.size())); + } + + if (!MemOps.empty()) + Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, + &MemOps[0], MemOps.size()); + } + } + + // Some CCs need callee pop. + if (IsCalleePop(isVarArg, CallConv)) { + BytesToPopOnReturn = StackSize; // Callee pops everything. + BytesCallerReserves = 0; + } else { + BytesToPopOnReturn = 0; // Callee pops nothing. + // If this is an sret function, the return should pop the hidden pointer. + if (!Is64Bit && CallConv != CallingConv::Fast && ArgsAreStructReturn(Ins)) + BytesToPopOnReturn = 4; + BytesCallerReserves = StackSize; + } + + if (!Is64Bit) { + RegSaveFrameIndex = 0xAAAAAAA; // RegSaveFrameIndex is X86-64 only. + if (CallConv == CallingConv::X86_FastCall) + VarArgsFrameIndex = 0xAAAAAAA; // fastcc functions can't have varargs. + } + + FuncInfo->setBytesToPopOnReturn(BytesToPopOnReturn); + + return Chain; +} + +SDValue +X86TargetLowering::LowerMemOpCallTo(SDValue Chain, + SDValue StackPtr, SDValue Arg, + DebugLoc dl, SelectionDAG &DAG, + const CCValAssign &VA, + ISD::ArgFlagsTy Flags) { + const unsigned FirstStackArgOffset = (Subtarget->isTargetWin64() ? 32 : 0); + unsigned LocMemOffset = FirstStackArgOffset + VA.getLocMemOffset(); + SDValue PtrOff = DAG.getIntPtrConstant(LocMemOffset); + PtrOff = DAG.getNode(ISD::ADD, dl, getPointerTy(), StackPtr, PtrOff); + if (Flags.isByVal()) { + return CreateCopyOfByValArgument(Arg, PtrOff, Chain, Flags, DAG, dl); + } + return DAG.getStore(Chain, dl, Arg, PtrOff, + PseudoSourceValue::getStack(), LocMemOffset); +} + +/// EmitTailCallLoadRetAddr - Emit a load of return address if tail call +/// optimization is performed and it is required. +SDValue +X86TargetLowering::EmitTailCallLoadRetAddr(SelectionDAG &DAG, + SDValue &OutRetAddr, + SDValue Chain, + bool IsTailCall, + bool Is64Bit, + int FPDiff, + DebugLoc dl) { + if (!IsTailCall || FPDiff==0) return Chain; + + // Adjust the Return address stack slot. + EVT VT = getPointerTy(); + OutRetAddr = getReturnAddressFrameIndex(DAG); + + // Load the "old" Return address. + OutRetAddr = DAG.getLoad(VT, dl, Chain, OutRetAddr, NULL, 0); + return SDValue(OutRetAddr.getNode(), 1); +} + +/// EmitTailCallStoreRetAddr - Emit a store of the return adress if tail call +/// optimization is performed and it is required (FPDiff!=0). +static SDValue +EmitTailCallStoreRetAddr(SelectionDAG & DAG, MachineFunction &MF, + SDValue Chain, SDValue RetAddrFrIdx, + bool Is64Bit, int FPDiff, DebugLoc dl) { + // Store the return address to the appropriate stack slot. + if (!FPDiff) return Chain; + // Calculate the new stack slot for the return address. + int SlotSize = Is64Bit ? 8 : 4; + int NewReturnAddrFI = + MF.getFrameInfo()->CreateFixedObject(SlotSize, FPDiff-SlotSize, + true, false); + EVT VT = Is64Bit ? MVT::i64 : MVT::i32; + SDValue NewRetAddrFrIdx = DAG.getFrameIndex(NewReturnAddrFI, VT); + Chain = DAG.getStore(Chain, dl, RetAddrFrIdx, NewRetAddrFrIdx, + PseudoSourceValue::getFixedStack(NewReturnAddrFI), 0); + return Chain; +} + +SDValue +X86TargetLowering::LowerCall(SDValue Chain, SDValue Callee, + CallingConv::ID CallConv, bool isVarArg, + bool isTailCall, + const SmallVectorImpl &Outs, + const SmallVectorImpl &Ins, + DebugLoc dl, SelectionDAG &DAG, + SmallVectorImpl &InVals) { + + MachineFunction &MF = DAG.getMachineFunction(); + bool Is64Bit = Subtarget->is64Bit(); + bool IsStructRet = CallIsStructReturn(Outs); + + assert((!isTailCall || + (CallConv == CallingConv::Fast && PerformTailCallOpt)) && + "IsEligibleForTailCallOptimization missed a case!"); + assert(!(isVarArg && CallConv == CallingConv::Fast) && + "Var args not supported with calling convention fastcc"); + + // Analyze operands of the call, assigning locations to each operand. + SmallVector ArgLocs; + CCState CCInfo(CallConv, isVarArg, getTargetMachine(), + ArgLocs, *DAG.getContext()); + CCInfo.AnalyzeCallOperands(Outs, CCAssignFnForNode(CallConv)); + + // Get a count of how many bytes are to be pushed on the stack. + unsigned NumBytes = CCInfo.getNextStackOffset(); + if (PerformTailCallOpt && CallConv == CallingConv::Fast) + NumBytes = GetAlignedArgumentStackSize(NumBytes, DAG); + + int FPDiff = 0; + if (isTailCall) { + // Lower arguments at fp - stackoffset + fpdiff. + unsigned NumBytesCallerPushed = + MF.getInfo()->getBytesToPopOnReturn(); + FPDiff = NumBytesCallerPushed - NumBytes; + + // Set the delta of movement of the returnaddr stackslot. + // But only set if delta is greater than previous delta. + if (FPDiff < (MF.getInfo()->getTCReturnAddrDelta())) + MF.getInfo()->setTCReturnAddrDelta(FPDiff); + } + + Chain = DAG.getCALLSEQ_START(Chain, DAG.getIntPtrConstant(NumBytes, true)); + + SDValue RetAddrFrIdx; + // Load return adress for tail calls. + Chain = EmitTailCallLoadRetAddr(DAG, RetAddrFrIdx, Chain, isTailCall, Is64Bit, + FPDiff, dl); + + SmallVector, 8> RegsToPass; + SmallVector MemOpChains; + SDValue StackPtr; + + // Walk the register/memloc assignments, inserting copies/loads. In the case + // of tail call optimization arguments are handle later. + for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { + CCValAssign &VA = ArgLocs[i]; + EVT RegVT = VA.getLocVT(); + SDValue Arg = Outs[i].Val; + ISD::ArgFlagsTy Flags = Outs[i].Flags; + bool isByVal = Flags.isByVal(); + + // Promote the value if needed. + switch (VA.getLocInfo()) { + default: llvm_unreachable("Unknown loc info!"); + case CCValAssign::Full: break; + case CCValAssign::SExt: + Arg = DAG.getNode(ISD::SIGN_EXTEND, dl, RegVT, Arg); + break; + case CCValAssign::ZExt: + Arg = DAG.getNode(ISD::ZERO_EXTEND, dl, RegVT, Arg); + break; + case CCValAssign::AExt: + if (RegVT.isVector() && RegVT.getSizeInBits() == 128) { + // Special case: passing MMX values in XMM registers. + Arg = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::i64, Arg); + Arg = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, MVT::v2i64, Arg); + Arg = getMOVL(DAG, dl, MVT::v2i64, DAG.getUNDEF(MVT::v2i64), Arg); + } else + Arg = DAG.getNode(ISD::ANY_EXTEND, dl, RegVT, Arg); + break; + case CCValAssign::BCvt: + Arg = DAG.getNode(ISD::BIT_CONVERT, dl, RegVT, Arg); + break; + case CCValAssign::Indirect: { + // Store the argument. + SDValue SpillSlot = DAG.CreateStackTemporary(VA.getValVT()); + int FI = cast(SpillSlot)->getIndex(); + Chain = DAG.getStore(Chain, dl, Arg, SpillSlot, + PseudoSourceValue::getFixedStack(FI), 0); + Arg = SpillSlot; + break; + } + } + + if (VA.isRegLoc()) { + RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg)); + } else { + if (!isTailCall || (isTailCall && isByVal)) { + assert(VA.isMemLoc()); + if (StackPtr.getNode() == 0) + StackPtr = DAG.getCopyFromReg(Chain, dl, X86StackPtr, getPointerTy()); + + MemOpChains.push_back(LowerMemOpCallTo(Chain, StackPtr, Arg, + dl, DAG, VA, Flags)); + } + } + } + + if (!MemOpChains.empty()) + Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, + &MemOpChains[0], MemOpChains.size()); + + // Build a sequence of copy-to-reg nodes chained together with token chain + // and flag operands which copy the outgoing args into registers. + SDValue InFlag; + // Tail call byval lowering might overwrite argument registers so in case of + // tail call optimization the copies to registers are lowered later. + if (!isTailCall) + for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) { + Chain = DAG.getCopyToReg(Chain, dl, RegsToPass[i].first, + RegsToPass[i].second, InFlag); + InFlag = Chain.getValue(1); + } + + + if (Subtarget->isPICStyleGOT()) { + // ELF / PIC requires GOT in the EBX register before function calls via PLT + // GOT pointer. + if (!isTailCall) { + Chain = DAG.getCopyToReg(Chain, dl, X86::EBX, + DAG.getNode(X86ISD::GlobalBaseReg, + DebugLoc::getUnknownLoc(), + getPointerTy()), + InFlag); + InFlag = Chain.getValue(1); + } else { + // If we are tail calling and generating PIC/GOT style code load the + // address of the callee into ECX. The value in ecx is used as target of + // the tail jump. This is done to circumvent the ebx/callee-saved problem + // for tail calls on PIC/GOT architectures. Normally we would just put the + // address of GOT into ebx and then call target@PLT. But for tail calls + // ebx would be restored (since ebx is callee saved) before jumping to the + // target@PLT. + + // Note: The actual moving to ECX is done further down. + GlobalAddressSDNode *G = dyn_cast(Callee); + if (G && !G->getGlobal()->hasHiddenVisibility() && + !G->getGlobal()->hasProtectedVisibility()) + Callee = LowerGlobalAddress(Callee, DAG); + else if (isa(Callee)) + Callee = LowerExternalSymbol(Callee, DAG); + } + } + + if (Is64Bit && isVarArg) { + // From AMD64 ABI document: + // For calls that may call functions that use varargs or stdargs + // (prototype-less calls or calls to functions containing ellipsis (...) in + // the declaration) %al is used as hidden argument to specify the number + // of SSE registers used. The contents of %al do not need to match exactly + // the number of registers, but must be an ubound on the number of SSE + // registers used and is in the range 0 - 8 inclusive. + + // FIXME: Verify this on Win64 + // Count the number of XMM registers allocated. + static const unsigned XMMArgRegs[] = { + X86::XMM0, X86::XMM1, X86::XMM2, X86::XMM3, + X86::XMM4, X86::XMM5, X86::XMM6, X86::XMM7 + }; + unsigned NumXMMRegs = CCInfo.getFirstUnallocated(XMMArgRegs, 8); + assert((Subtarget->hasSSE1() || !NumXMMRegs) + && "SSE registers cannot be used when SSE is disabled"); + + Chain = DAG.getCopyToReg(Chain, dl, X86::AL, + DAG.getConstant(NumXMMRegs, MVT::i8), InFlag); + InFlag = Chain.getValue(1); + } + + + // For tail calls lower the arguments to the 'real' stack slot. + if (isTailCall) { + // Force all the incoming stack arguments to be loaded from the stack + // before any new outgoing arguments are stored to the stack, because the + // outgoing stack slots may alias the incoming argument stack slots, and + // the alias isn't otherwise explicit. This is slightly more conservative + // than necessary, because it means that each store effectively depends + // on every argument instead of just those arguments it would clobber. + SDValue ArgChain = DAG.getStackArgumentTokenFactor(Chain); + + SmallVector MemOpChains2; + SDValue FIN; + int FI = 0; + // Do not flag preceeding copytoreg stuff together with the following stuff. + InFlag = SDValue(); + for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { + CCValAssign &VA = ArgLocs[i]; + if (!VA.isRegLoc()) { + assert(VA.isMemLoc()); + SDValue Arg = Outs[i].Val; + ISD::ArgFlagsTy Flags = Outs[i].Flags; + // Create frame index. + int32_t Offset = VA.getLocMemOffset()+FPDiff; + uint32_t OpSize = (VA.getLocVT().getSizeInBits()+7)/8; + FI = MF.getFrameInfo()->CreateFixedObject(OpSize, Offset, true, false); + FIN = DAG.getFrameIndex(FI, getPointerTy()); + + if (Flags.isByVal()) { + // Copy relative to framepointer. + SDValue Source = DAG.getIntPtrConstant(VA.getLocMemOffset()); + if (StackPtr.getNode() == 0) + StackPtr = DAG.getCopyFromReg(Chain, dl, X86StackPtr, + getPointerTy()); + Source = DAG.getNode(ISD::ADD, dl, getPointerTy(), StackPtr, Source); + + MemOpChains2.push_back(CreateCopyOfByValArgument(Source, FIN, + ArgChain, + Flags, DAG, dl)); + } else { + // Store relative to framepointer. + MemOpChains2.push_back( + DAG.getStore(ArgChain, dl, Arg, FIN, + PseudoSourceValue::getFixedStack(FI), 0)); + } + } + } + + if (!MemOpChains2.empty()) + Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, + &MemOpChains2[0], MemOpChains2.size()); + + // Copy arguments to their registers. + for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) { + Chain = DAG.getCopyToReg(Chain, dl, RegsToPass[i].first, + RegsToPass[i].second, InFlag); + InFlag = Chain.getValue(1); + } + InFlag =SDValue(); + + // Store the return address to the appropriate stack slot. + Chain = EmitTailCallStoreRetAddr(DAG, MF, Chain, RetAddrFrIdx, Is64Bit, + FPDiff, dl); + } + + bool WasGlobalOrExternal = false; + if (getTargetMachine().getCodeModel() == CodeModel::Large) { + assert(Is64Bit && "Large code model is only legal in 64-bit mode."); + // In the 64-bit large code model, we have to make all calls + // through a register, since the call instruction's 32-bit + // pc-relative offset may not be large enough to hold the whole + // address. + } else if (GlobalAddressSDNode *G = dyn_cast(Callee)) { + WasGlobalOrExternal = true; + // If the callee is a GlobalAddress node (quite common, every direct call + // is) turn it into a TargetGlobalAddress node so that legalize doesn't hack + // it. + + // We should use extra load for direct calls to dllimported functions in + // non-JIT mode. + GlobalValue *GV = G->getGlobal(); + if (!GV->hasDLLImportLinkage()) { + unsigned char OpFlags = 0; + + // On ELF targets, in both X86-64 and X86-32 mode, direct calls to + // external symbols most go through the PLT in PIC mode. If the symbol + // has hidden or protected visibility, or if it is static or local, then + // we don't need to use the PLT - we can directly call it. + if (Subtarget->isTargetELF() && + getTargetMachine().getRelocationModel() == Reloc::PIC_ && + GV->hasDefaultVisibility() && !GV->hasLocalLinkage()) { + OpFlags = X86II::MO_PLT; + } else if (Subtarget->isPICStyleStubAny() && + (GV->isDeclaration() || GV->isWeakForLinker()) && + Subtarget->getDarwinVers() < 9) { + // PC-relative references to external symbols should go through $stub, + // unless we're building with the leopard linker or later, which + // automatically synthesizes these stubs. + OpFlags = X86II::MO_DARWIN_STUB; + } + + Callee = DAG.getTargetGlobalAddress(GV, getPointerTy(), + G->getOffset(), OpFlags); + } + } else if (ExternalSymbolSDNode *S = dyn_cast(Callee)) { + WasGlobalOrExternal = true; + unsigned char OpFlags = 0; + + // On ELF targets, in either X86-64 or X86-32 mode, direct calls to external + // symbols should go through the PLT. + if (Subtarget->isTargetELF() && + getTargetMachine().getRelocationModel() == Reloc::PIC_) { + OpFlags = X86II::MO_PLT; + } else if (Subtarget->isPICStyleStubAny() && + Subtarget->getDarwinVers() < 9) { + // PC-relative references to external symbols should go through $stub, + // unless we're building with the leopard linker or later, which + // automatically synthesizes these stubs. + OpFlags = X86II::MO_DARWIN_STUB; + } + + Callee = DAG.getTargetExternalSymbol(S->getSymbol(), getPointerTy(), + OpFlags); + } + + if (isTailCall && !WasGlobalOrExternal) { + unsigned Opc = Is64Bit ? X86::R11 : X86::EAX; + + Chain = DAG.getCopyToReg(Chain, dl, + DAG.getRegister(Opc, getPointerTy()), + Callee,InFlag); + Callee = DAG.getRegister(Opc, getPointerTy()); + // Add register as live out. + MF.getRegInfo().addLiveOut(Opc); + } + + // Returns a chain & a flag for retval copy to use. + SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Flag); + SmallVector Ops; + + if (isTailCall) { + Chain = DAG.getCALLSEQ_END(Chain, DAG.getIntPtrConstant(NumBytes, true), + DAG.getIntPtrConstant(0, true), InFlag); + InFlag = Chain.getValue(1); + } + + Ops.push_back(Chain); + Ops.push_back(Callee); + + if (isTailCall) + Ops.push_back(DAG.getConstant(FPDiff, MVT::i32)); + + // Add argument registers to the end of the list so that they are known live + // into the call. + for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) + Ops.push_back(DAG.getRegister(RegsToPass[i].first, + RegsToPass[i].second.getValueType())); + + // Add an implicit use GOT pointer in EBX. + if (!isTailCall && Subtarget->isPICStyleGOT()) + Ops.push_back(DAG.getRegister(X86::EBX, getPointerTy())); + + // Add an implicit use of AL for x86 vararg functions. + if (Is64Bit && isVarArg) + Ops.push_back(DAG.getRegister(X86::AL, MVT::i8)); + + if (InFlag.getNode()) + Ops.push_back(InFlag); + + if (isTailCall) { + // If this is the first return lowered for this function, add the regs + // to the liveout set for the function. + if (MF.getRegInfo().liveout_empty()) { + SmallVector RVLocs; + CCState CCInfo(CallConv, isVarArg, getTargetMachine(), RVLocs, + *DAG.getContext()); + CCInfo.AnalyzeCallResult(Ins, RetCC_X86); + for (unsigned i = 0; i != RVLocs.size(); ++i) + if (RVLocs[i].isRegLoc()) + MF.getRegInfo().addLiveOut(RVLocs[i].getLocReg()); + } + + assert(((Callee.getOpcode() == ISD::Register && + (cast(Callee)->getReg() == X86::EAX || + cast(Callee)->getReg() == X86::R9)) || + Callee.getOpcode() == ISD::TargetExternalSymbol || + Callee.getOpcode() == ISD::TargetGlobalAddress) && + "Expecting an global address, external symbol, or register"); + + return DAG.getNode(X86ISD::TC_RETURN, dl, + NodeTys, &Ops[0], Ops.size()); + } + + Chain = DAG.getNode(X86ISD::CALL, dl, NodeTys, &Ops[0], Ops.size()); + InFlag = Chain.getValue(1); + + // Create the CALLSEQ_END node. + unsigned NumBytesForCalleeToPush; + if (IsCalleePop(isVarArg, CallConv)) + NumBytesForCalleeToPush = NumBytes; // Callee pops everything + else if (!Is64Bit && CallConv != CallingConv::Fast && IsStructRet) + // If this is is a call to a struct-return function, the callee + // pops the hidden struct pointer, so we have to push it back. + // This is common for Darwin/X86, Linux & Mingw32 targets. + NumBytesForCalleeToPush = 4; + else + NumBytesForCalleeToPush = 0; // Callee pops nothing. + + // Returns a flag for retval copy to use. + Chain = DAG.getCALLSEQ_END(Chain, + DAG.getIntPtrConstant(NumBytes, true), + DAG.getIntPtrConstant(NumBytesForCalleeToPush, + true), + InFlag); + InFlag = Chain.getValue(1); + + // Handle result values, copying them out of physregs into vregs that we + // return. + return LowerCallResult(Chain, InFlag, CallConv, isVarArg, + Ins, dl, DAG, InVals); +} + + +//===----------------------------------------------------------------------===// +// Fast Calling Convention (tail call) implementation +//===----------------------------------------------------------------------===// + +// Like std call, callee cleans arguments, convention except that ECX is +// reserved for storing the tail called function address. Only 2 registers are +// free for argument passing (inreg). Tail call optimization is performed +// provided: +// * tailcallopt is enabled +// * caller/callee are fastcc +// On X86_64 architecture with GOT-style position independent code only local +// (within module) calls are supported at the moment. +// To keep the stack aligned according to platform abi the function +// GetAlignedArgumentStackSize ensures that argument delta is always multiples +// of stack alignment. (Dynamic linkers need this - darwin's dyld for example) +// If a tail called function callee has more arguments than the caller the +// caller needs to make sure that there is room to move the RETADDR to. This is +// achieved by reserving an area the size of the argument delta right after the +// original REtADDR, but before the saved framepointer or the spilled registers +// e.g. caller(arg1, arg2) calls callee(arg1, arg2,arg3,arg4) +// stack layout: +// arg1 +// arg2 +// RETADDR +// [ new RETADDR +// move area ] +// (possible EBP) +// ESI +// EDI +// local1 .. + +/// GetAlignedArgumentStackSize - Make the stack size align e.g 16n + 12 aligned +/// for a 16 byte align requirement. +unsigned X86TargetLowering::GetAlignedArgumentStackSize(unsigned StackSize, + SelectionDAG& DAG) { + MachineFunction &MF = DAG.getMachineFunction(); + const TargetMachine &TM = MF.getTarget(); + const TargetFrameInfo &TFI = *TM.getFrameInfo(); + unsigned StackAlignment = TFI.getStackAlignment(); + uint64_t AlignMask = StackAlignment - 1; + int64_t Offset = StackSize; + uint64_t SlotSize = TD->getPointerSize(); + if ( (Offset & AlignMask) <= (StackAlignment - SlotSize) ) { + // Number smaller than 12 so just add the difference. + Offset += ((StackAlignment - SlotSize) - (Offset & AlignMask)); + } else { + // Mask out lower bits, add stackalignment once plus the 12 bytes. + Offset = ((~AlignMask) & Offset) + StackAlignment + + (StackAlignment-SlotSize); + } + return Offset; +} + +/// IsEligibleForTailCallOptimization - Check whether the call is eligible +/// for tail call optimization. Targets which want to do tail call +/// optimization should implement this function. +bool +X86TargetLowering::IsEligibleForTailCallOptimization(SDValue Callee, + CallingConv::ID CalleeCC, + bool isVarArg, + const SmallVectorImpl &Ins, + SelectionDAG& DAG) const { + MachineFunction &MF = DAG.getMachineFunction(); + CallingConv::ID CallerCC = MF.getFunction()->getCallingConv(); + return CalleeCC == CallingConv::Fast && CallerCC == CalleeCC; +} + +FastISel * +X86TargetLowering::createFastISel(MachineFunction &mf, + MachineModuleInfo *mmo, + DwarfWriter *dw, + DenseMap &vm, + DenseMap &bm, + DenseMap &am +#ifndef NDEBUG + , SmallSet &cil +#endif + ) { + return X86::createFastISel(mf, mmo, dw, vm, bm, am +#ifndef NDEBUG + , cil +#endif + ); +} + + +//===----------------------------------------------------------------------===// +// Other Lowering Hooks +//===----------------------------------------------------------------------===// + + +SDValue X86TargetLowering::getReturnAddressFrameIndex(SelectionDAG &DAG) { + MachineFunction &MF = DAG.getMachineFunction(); + X86MachineFunctionInfo *FuncInfo = MF.getInfo(); + int ReturnAddrIndex = FuncInfo->getRAIndex(); + + if (ReturnAddrIndex == 0) { + // Set up a frame object for the return address. + uint64_t SlotSize = TD->getPointerSize(); + ReturnAddrIndex = MF.getFrameInfo()->CreateFixedObject(SlotSize, -SlotSize, + true, false); + FuncInfo->setRAIndex(ReturnAddrIndex); + } + + return DAG.getFrameIndex(ReturnAddrIndex, getPointerTy()); +} + + +bool X86::isOffsetSuitableForCodeModel(int64_t Offset, CodeModel::Model M, + bool hasSymbolicDisplacement) { + // Offset should fit into 32 bit immediate field. + if (!isInt32(Offset)) + return false; + + // If we don't have a symbolic displacement - we don't have any extra + // restrictions. + if (!hasSymbolicDisplacement) + return true; + + // FIXME: Some tweaks might be needed for medium code model. + if (M != CodeModel::Small && M != CodeModel::Kernel) + return false; + + // For small code model we assume that latest object is 16MB before end of 31 + // bits boundary. We may also accept pretty large negative constants knowing + // that all objects are in the positive half of address space. + if (M == CodeModel::Small && Offset < 16*1024*1024) + return true; + + // For kernel code model we know that all object resist in the negative half + // of 32bits address space. We may not accept negative offsets, since they may + // be just off and we may accept pretty large positive ones. + if (M == CodeModel::Kernel && Offset > 0) + return true; + + return false; +} + +/// TranslateX86CC - do a one to one translation of a ISD::CondCode to the X86 +/// specific condition code, returning the condition code and the LHS/RHS of the +/// comparison to make. +static unsigned TranslateX86CC(ISD::CondCode SetCCOpcode, bool isFP, + SDValue &LHS, SDValue &RHS, SelectionDAG &DAG) { + if (!isFP) { + if (ConstantSDNode *RHSC = dyn_cast(RHS)) { + if (SetCCOpcode == ISD::SETGT && RHSC->isAllOnesValue()) { + // X > -1 -> X == 0, jump !sign. + RHS = DAG.getConstant(0, RHS.getValueType()); + return X86::COND_NS; + } else if (SetCCOpcode == ISD::SETLT && RHSC->isNullValue()) { + // X < 0 -> X == 0, jump on sign. + return X86::COND_S; + } else if (SetCCOpcode == ISD::SETLT && RHSC->getZExtValue() == 1) { + // X < 1 -> X <= 0 + RHS = DAG.getConstant(0, RHS.getValueType()); + return X86::COND_LE; + } + } + + switch (SetCCOpcode) { + default: llvm_unreachable("Invalid integer condition!"); + case ISD::SETEQ: return X86::COND_E; + case ISD::SETGT: return X86::COND_G; + case ISD::SETGE: return X86::COND_GE; + case ISD::SETLT: return X86::COND_L; + case ISD::SETLE: return X86::COND_LE; + case ISD::SETNE: return X86::COND_NE; + case ISD::SETULT: return X86::COND_B; + case ISD::SETUGT: return X86::COND_A; + case ISD::SETULE: return X86::COND_BE; + case ISD::SETUGE: return X86::COND_AE; + } + } + + // First determine if it is required or is profitable to flip the operands. + + // If LHS is a foldable load, but RHS is not, flip the condition. + if ((ISD::isNON_EXTLoad(LHS.getNode()) && LHS.hasOneUse()) && + !(ISD::isNON_EXTLoad(RHS.getNode()) && RHS.hasOneUse())) { + SetCCOpcode = getSetCCSwappedOperands(SetCCOpcode); + std::swap(LHS, RHS); + } + + switch (SetCCOpcode) { + default: break; + case ISD::SETOLT: + case ISD::SETOLE: + case ISD::SETUGT: + case ISD::SETUGE: + std::swap(LHS, RHS); + break; + } + + // On a floating point condition, the flags are set as follows: + // ZF PF CF op + // 0 | 0 | 0 | X > Y + // 0 | 0 | 1 | X < Y + // 1 | 0 | 0 | X == Y + // 1 | 1 | 1 | unordered + switch (SetCCOpcode) { + default: llvm_unreachable("Condcode should be pre-legalized away"); + case ISD::SETUEQ: + case ISD::SETEQ: return X86::COND_E; + case ISD::SETOLT: // flipped + case ISD::SETOGT: + case ISD::SETGT: return X86::COND_A; + case ISD::SETOLE: // flipped + case ISD::SETOGE: + case ISD::SETGE: return X86::COND_AE; + case ISD::SETUGT: // flipped + case ISD::SETULT: + case ISD::SETLT: return X86::COND_B; + case ISD::SETUGE: // flipped + case ISD::SETULE: + case ISD::SETLE: return X86::COND_BE; + case ISD::SETONE: + case ISD::SETNE: return X86::COND_NE; + case ISD::SETUO: return X86::COND_P; + case ISD::SETO: return X86::COND_NP; + case ISD::SETOEQ: + case ISD::SETUNE: return X86::COND_INVALID; + } +} + +/// hasFPCMov - is there a floating point cmov for the specific X86 condition +/// code. Current x86 isa includes the following FP cmov instructions: +/// fcmovb, fcomvbe, fcomve, fcmovu, fcmovae, fcmova, fcmovne, fcmovnu. +static bool hasFPCMov(unsigned X86CC) { + switch (X86CC) { + default: + return false; + case X86::COND_B: + case X86::COND_BE: + case X86::COND_E: + case X86::COND_P: + case X86::COND_A: + case X86::COND_AE: + case X86::COND_NE: + case X86::COND_NP: + return true; + } +} + +/// isFPImmLegal - Returns true if the target can instruction select the +/// specified FP immediate natively. If false, the legalizer will +/// materialize the FP immediate as a load from a constant pool. +bool X86TargetLowering::isFPImmLegal(const APFloat &Imm, EVT VT) const { + for (unsigned i = 0, e = LegalFPImmediates.size(); i != e; ++i) { + if (Imm.bitwiseIsEqual(LegalFPImmediates[i])) + return true; + } + return false; +} + +/// isUndefOrInRange - Return true if Val is undef or if its value falls within +/// the specified range (L, H]. +static bool isUndefOrInRange(int Val, int Low, int Hi) { + return (Val < 0) || (Val >= Low && Val < Hi); +} + +/// isUndefOrEqual - Val is either less than zero (undef) or equal to the +/// specified value. +static bool isUndefOrEqual(int Val, int CmpVal) { + if (Val < 0 || Val == CmpVal) + return true; + return false; +} + +/// isPSHUFDMask - Return true if the node specifies a shuffle of elements that +/// is suitable for input to PSHUFD or PSHUFW. That is, it doesn't reference +/// the second operand. +static bool isPSHUFDMask(const SmallVectorImpl &Mask, EVT VT) { + if (VT == MVT::v4f32 || VT == MVT::v4i32 || VT == MVT::v4i16) + return (Mask[0] < 4 && Mask[1] < 4 && Mask[2] < 4 && Mask[3] < 4); + if (VT == MVT::v2f64 || VT == MVT::v2i64) + return (Mask[0] < 2 && Mask[1] < 2); + return false; +} + +bool X86::isPSHUFDMask(ShuffleVectorSDNode *N) { + SmallVector M; + N->getMask(M); + return ::isPSHUFDMask(M, N->getValueType(0)); +} + +/// isPSHUFHWMask - Return true if the node specifies a shuffle of elements that +/// is suitable for input to PSHUFHW. +static bool isPSHUFHWMask(const SmallVectorImpl &Mask, EVT VT) { + if (VT != MVT::v8i16) + return false; + + // Lower quadword copied in order or undef. + for (int i = 0; i != 4; ++i) + if (Mask[i] >= 0 && Mask[i] != i) + return false; + + // Upper quadword shuffled. + for (int i = 4; i != 8; ++i) + if (Mask[i] >= 0 && (Mask[i] < 4 || Mask[i] > 7)) + return false; + + return true; +} + +bool X86::isPSHUFHWMask(ShuffleVectorSDNode *N) { + SmallVector M; + N->getMask(M); + return ::isPSHUFHWMask(M, N->getValueType(0)); +} + +/// isPSHUFLWMask - Return true if the node specifies a shuffle of elements that +/// is suitable for input to PSHUFLW. +static bool isPSHUFLWMask(const SmallVectorImpl &Mask, EVT VT) { + if (VT != MVT::v8i16) + return false; + + // Upper quadword copied in order. + for (int i = 4; i != 8; ++i) + if (Mask[i] >= 0 && Mask[i] != i) + return false; + + // Lower quadword shuffled. + for (int i = 0; i != 4; ++i) + if (Mask[i] >= 4) + return false; + + return true; +} + +bool X86::isPSHUFLWMask(ShuffleVectorSDNode *N) { + SmallVector M; + N->getMask(M); + return ::isPSHUFLWMask(M, N->getValueType(0)); +} + +/// isPALIGNRMask - Return true if the node specifies a shuffle of elements that +/// is suitable for input to PALIGNR. +static bool isPALIGNRMask(const SmallVectorImpl &Mask, EVT VT, + bool hasSSSE3) { + int i, e = VT.getVectorNumElements(); + + // Do not handle v2i64 / v2f64 shuffles with palignr. + if (e < 4 || !hasSSSE3) + return false; + + for (i = 0; i != e; ++i) + if (Mask[i] >= 0) + break; + + // All undef, not a palignr. + if (i == e) + return false; + + // Determine if it's ok to perform a palignr with only the LHS, since we + // don't have access to the actual shuffle elements to see if RHS is undef. + bool Unary = Mask[i] < (int)e; + bool NeedsUnary = false; + + int s = Mask[i] - i; + + // Check the rest of the elements to see if they are consecutive. + for (++i; i != e; ++i) { + int m = Mask[i]; + if (m < 0) + continue; + + Unary = Unary && (m < (int)e); + NeedsUnary = NeedsUnary || (m < s); + + if (NeedsUnary && !Unary) + return false; + if (Unary && m != ((s+i) & (e-1))) + return false; + if (!Unary && m != (s+i)) + return false; + } + return true; +} + +bool X86::isPALIGNRMask(ShuffleVectorSDNode *N) { + SmallVector M; + N->getMask(M); + return ::isPALIGNRMask(M, N->getValueType(0), true); +} + +/// isSHUFPMask - Return true if the specified VECTOR_SHUFFLE operand +/// specifies a shuffle of elements that is suitable for input to SHUFP*. +static bool isSHUFPMask(const SmallVectorImpl &Mask, EVT VT) { + int NumElems = VT.getVectorNumElements(); + if (NumElems != 2 && NumElems != 4) + return false; + + int Half = NumElems / 2; + for (int i = 0; i < Half; ++i) + if (!isUndefOrInRange(Mask[i], 0, NumElems)) + return false; + for (int i = Half; i < NumElems; ++i) + if (!isUndefOrInRange(Mask[i], NumElems, NumElems*2)) + return false; + + return true; +} + +bool X86::isSHUFPMask(ShuffleVectorSDNode *N) { + SmallVector M; + N->getMask(M); + return ::isSHUFPMask(M, N->getValueType(0)); +} + +/// isCommutedSHUFP - Returns true if the shuffle mask is exactly +/// the reverse of what x86 shuffles want. x86 shuffles requires the lower +/// half elements to come from vector 1 (which would equal the dest.) and +/// the upper half to come from vector 2. +static bool isCommutedSHUFPMask(const SmallVectorImpl &Mask, EVT VT) { + int NumElems = VT.getVectorNumElements(); + + if (NumElems != 2 && NumElems != 4) + return false; + + int Half = NumElems / 2; + for (int i = 0; i < Half; ++i) + if (!isUndefOrInRange(Mask[i], NumElems, NumElems*2)) + return false; + for (int i = Half; i < NumElems; ++i) + if (!isUndefOrInRange(Mask[i], 0, NumElems)) + return false; + return true; +} + +static bool isCommutedSHUFP(ShuffleVectorSDNode *N) { + SmallVector M; + N->getMask(M); + return isCommutedSHUFPMask(M, N->getValueType(0)); +} + +/// isMOVHLPSMask - Return true if the specified VECTOR_SHUFFLE operand +/// specifies a shuffle of elements that is suitable for input to MOVHLPS. +bool X86::isMOVHLPSMask(ShuffleVectorSDNode *N) { + if (N->getValueType(0).getVectorNumElements() != 4) + return false; + + // Expect bit0 == 6, bit1 == 7, bit2 == 2, bit3 == 3 + return isUndefOrEqual(N->getMaskElt(0), 6) && + isUndefOrEqual(N->getMaskElt(1), 7) && + isUndefOrEqual(N->getMaskElt(2), 2) && + isUndefOrEqual(N->getMaskElt(3), 3); +} + +/// isMOVHLPS_v_undef_Mask - Special case of isMOVHLPSMask for canonical form +/// of vector_shuffle v, v, <2, 3, 2, 3>, i.e. vector_shuffle v, undef, +/// <2, 3, 2, 3> +bool X86::isMOVHLPS_v_undef_Mask(ShuffleVectorSDNode *N) { + unsigned NumElems = N->getValueType(0).getVectorNumElements(); + + if (NumElems != 4) + return false; + + return isUndefOrEqual(N->getMaskElt(0), 2) && + isUndefOrEqual(N->getMaskElt(1), 3) && + isUndefOrEqual(N->getMaskElt(2), 2) && + isUndefOrEqual(N->getMaskElt(3), 3); +} + +/// isMOVLPMask - Return true if the specified VECTOR_SHUFFLE operand +/// specifies a shuffle of elements that is suitable for input to MOVLP{S|D}. +bool X86::isMOVLPMask(ShuffleVectorSDNode *N) { + unsigned NumElems = N->getValueType(0).getVectorNumElements(); + + if (NumElems != 2 && NumElems != 4) + return false; + + for (unsigned i = 0; i < NumElems/2; ++i) + if (!isUndefOrEqual(N->getMaskElt(i), i + NumElems)) + return false; + + for (unsigned i = NumElems/2; i < NumElems; ++i) + if (!isUndefOrEqual(N->getMaskElt(i), i)) + return false; + + return true; +} + +/// isMOVLHPSMask - Return true if the specified VECTOR_SHUFFLE operand +/// specifies a shuffle of elements that is suitable for input to MOVLHPS. +bool X86::isMOVLHPSMask(ShuffleVectorSDNode *N) { + unsigned NumElems = N->getValueType(0).getVectorNumElements(); + + if (NumElems != 2 && NumElems != 4) + return false; + + for (unsigned i = 0; i < NumElems/2; ++i) + if (!isUndefOrEqual(N->getMaskElt(i), i)) + return false; + + for (unsigned i = 0; i < NumElems/2; ++i) + if (!isUndefOrEqual(N->getMaskElt(i + NumElems/2), i + NumElems)) + return false; + + return true; +} + +/// isUNPCKLMask - Return true if the specified VECTOR_SHUFFLE operand +/// specifies a shuffle of elements that is suitable for input to UNPCKL. +static bool isUNPCKLMask(const SmallVectorImpl &Mask, EVT VT, + bool V2IsSplat = false) { + int NumElts = VT.getVectorNumElements(); + if (NumElts != 2 && NumElts != 4 && NumElts != 8 && NumElts != 16) + return false; + + for (int i = 0, j = 0; i != NumElts; i += 2, ++j) { + int BitI = Mask[i]; + int BitI1 = Mask[i+1]; + if (!isUndefOrEqual(BitI, j)) + return false; + if (V2IsSplat) { + if (!isUndefOrEqual(BitI1, NumElts)) + return false; + } else { + if (!isUndefOrEqual(BitI1, j + NumElts)) + return false; + } + } + return true; +} + +bool X86::isUNPCKLMask(ShuffleVectorSDNode *N, bool V2IsSplat) { + SmallVector M; + N->getMask(M); + return ::isUNPCKLMask(M, N->getValueType(0), V2IsSplat); +} + +/// isUNPCKHMask - Return true if the specified VECTOR_SHUFFLE operand +/// specifies a shuffle of elements that is suitable for input to UNPCKH. +static bool isUNPCKHMask(const SmallVectorImpl &Mask, EVT VT, + bool V2IsSplat = false) { + int NumElts = VT.getVectorNumElements(); + if (NumElts != 2 && NumElts != 4 && NumElts != 8 && NumElts != 16) + return false; + + for (int i = 0, j = 0; i != NumElts; i += 2, ++j) { + int BitI = Mask[i]; + int BitI1 = Mask[i+1]; + if (!isUndefOrEqual(BitI, j + NumElts/2)) + return false; + if (V2IsSplat) { + if (isUndefOrEqual(BitI1, NumElts)) + return false; + } else { + if (!isUndefOrEqual(BitI1, j + NumElts/2 + NumElts)) + return false; + } + } + return true; +} + +bool X86::isUNPCKHMask(ShuffleVectorSDNode *N, bool V2IsSplat) { + SmallVector M; + N->getMask(M); + return ::isUNPCKHMask(M, N->getValueType(0), V2IsSplat); +} + +/// isUNPCKL_v_undef_Mask - Special case of isUNPCKLMask for canonical form +/// of vector_shuffle v, v, <0, 4, 1, 5>, i.e. vector_shuffle v, undef, +/// <0, 0, 1, 1> +static bool isUNPCKL_v_undef_Mask(const SmallVectorImpl &Mask, EVT VT) { + int NumElems = VT.getVectorNumElements(); + if (NumElems != 2 && NumElems != 4 && NumElems != 8 && NumElems != 16) + return false; + + for (int i = 0, j = 0; i != NumElems; i += 2, ++j) { + int BitI = Mask[i]; + int BitI1 = Mask[i+1]; + if (!isUndefOrEqual(BitI, j)) + return false; + if (!isUndefOrEqual(BitI1, j)) + return false; + } + return true; +} + +bool X86::isUNPCKL_v_undef_Mask(ShuffleVectorSDNode *N) { + SmallVector M; + N->getMask(M); + return ::isUNPCKL_v_undef_Mask(M, N->getValueType(0)); +} + +/// isUNPCKH_v_undef_Mask - Special case of isUNPCKHMask for canonical form +/// of vector_shuffle v, v, <2, 6, 3, 7>, i.e. vector_shuffle v, undef, +/// <2, 2, 3, 3> +static bool isUNPCKH_v_undef_Mask(const SmallVectorImpl &Mask, EVT VT) { + int NumElems = VT.getVectorNumElements(); + if (NumElems != 2 && NumElems != 4 && NumElems != 8 && NumElems != 16) + return false; + + for (int i = 0, j = NumElems / 2; i != NumElems; i += 2, ++j) { + int BitI = Mask[i]; + int BitI1 = Mask[i+1]; + if (!isUndefOrEqual(BitI, j)) + return false; + if (!isUndefOrEqual(BitI1, j)) + return false; + } + return true; +} + +bool X86::isUNPCKH_v_undef_Mask(ShuffleVectorSDNode *N) { + SmallVector M; + N->getMask(M); + return ::isUNPCKH_v_undef_Mask(M, N->getValueType(0)); +} + +/// isMOVLMask - Return true if the specified VECTOR_SHUFFLE operand +/// specifies a shuffle of elements that is suitable for input to MOVSS, +/// MOVSD, and MOVD, i.e. setting the lowest element. +static bool isMOVLMask(const SmallVectorImpl &Mask, EVT VT) { + if (VT.getVectorElementType().getSizeInBits() < 32) + return false; + + int NumElts = VT.getVectorNumElements(); + + if (!isUndefOrEqual(Mask[0], NumElts)) + return false; + + for (int i = 1; i < NumElts; ++i) + if (!isUndefOrEqual(Mask[i], i)) + return false; + + return true; +} + +bool X86::isMOVLMask(ShuffleVectorSDNode *N) { + SmallVector M; + N->getMask(M); + return ::isMOVLMask(M, N->getValueType(0)); +} + +/// isCommutedMOVL - Returns true if the shuffle mask is except the reverse +/// of what x86 movss want. X86 movs requires the lowest element to be lowest +/// element of vector 2 and the other elements to come from vector 1 in order. +static bool isCommutedMOVLMask(const SmallVectorImpl &Mask, EVT VT, + bool V2IsSplat = false, bool V2IsUndef = false) { + int NumOps = VT.getVectorNumElements(); + if (NumOps != 2 && NumOps != 4 && NumOps != 8 && NumOps != 16) + return false; + + if (!isUndefOrEqual(Mask[0], 0)) + return false; + + for (int i = 1; i < NumOps; ++i) + if (!(isUndefOrEqual(Mask[i], i+NumOps) || + (V2IsUndef && isUndefOrInRange(Mask[i], NumOps, NumOps*2)) || + (V2IsSplat && isUndefOrEqual(Mask[i], NumOps)))) + return false; + + return true; +} + +static bool isCommutedMOVL(ShuffleVectorSDNode *N, bool V2IsSplat = false, + bool V2IsUndef = false) { + SmallVector M; + N->getMask(M); + return isCommutedMOVLMask(M, N->getValueType(0), V2IsSplat, V2IsUndef); +} + +/// isMOVSHDUPMask - Return true if the specified VECTOR_SHUFFLE operand +/// specifies a shuffle of elements that is suitable for input to MOVSHDUP. +bool X86::isMOVSHDUPMask(ShuffleVectorSDNode *N) { + if (N->getValueType(0).getVectorNumElements() != 4) + return false; + + // Expect 1, 1, 3, 3 + for (unsigned i = 0; i < 2; ++i) { + int Elt = N->getMaskElt(i); + if (Elt >= 0 && Elt != 1) + return false; + } + + bool HasHi = false; + for (unsigned i = 2; i < 4; ++i) { + int Elt = N->getMaskElt(i); + if (Elt >= 0 && Elt != 3) + return false; + if (Elt == 3) + HasHi = true; + } + // Don't use movshdup if it can be done with a shufps. + // FIXME: verify that matching u, u, 3, 3 is what we want. + return HasHi; +} + +/// isMOVSLDUPMask - Return true if the specified VECTOR_SHUFFLE operand +/// specifies a shuffle of elements that is suitable for input to MOVSLDUP. +bool X86::isMOVSLDUPMask(ShuffleVectorSDNode *N) { + if (N->getValueType(0).getVectorNumElements() != 4) + return false; + + // Expect 0, 0, 2, 2 + for (unsigned i = 0; i < 2; ++i) + if (N->getMaskElt(i) > 0) + return false; + + bool HasHi = false; + for (unsigned i = 2; i < 4; ++i) { + int Elt = N->getMaskElt(i); + if (Elt >= 0 && Elt != 2) + return false; + if (Elt == 2) + HasHi = true; + } + // Don't use movsldup if it can be done with a shufps. + return HasHi; +} + +/// isMOVDDUPMask - Return true if the specified VECTOR_SHUFFLE operand +/// specifies a shuffle of elements that is suitable for input to MOVDDUP. +bool X86::isMOVDDUPMask(ShuffleVectorSDNode *N) { + int e = N->getValueType(0).getVectorNumElements() / 2; + + for (int i = 0; i < e; ++i) + if (!isUndefOrEqual(N->getMaskElt(i), i)) + return false; + for (int i = 0; i < e; ++i) + if (!isUndefOrEqual(N->getMaskElt(e+i), i)) + return false; + return true; +} + +/// getShuffleSHUFImmediate - Return the appropriate immediate to shuffle +/// the specified VECTOR_SHUFFLE mask with PSHUF* and SHUFP* instructions. +unsigned X86::getShuffleSHUFImmediate(SDNode *N) { + ShuffleVectorSDNode *SVOp = cast(N); + int NumOperands = SVOp->getValueType(0).getVectorNumElements(); + + unsigned Shift = (NumOperands == 4) ? 2 : 1; + unsigned Mask = 0; + for (int i = 0; i < NumOperands; ++i) { + int Val = SVOp->getMaskElt(NumOperands-i-1); + if (Val < 0) Val = 0; + if (Val >= NumOperands) Val -= NumOperands; + Mask |= Val; + if (i != NumOperands - 1) + Mask <<= Shift; + } + return Mask; +} + +/// getShufflePSHUFHWImmediate - Return the appropriate immediate to shuffle +/// the specified VECTOR_SHUFFLE mask with the PSHUFHW instruction. +unsigned X86::getShufflePSHUFHWImmediate(SDNode *N) { + ShuffleVectorSDNode *SVOp = cast(N); + unsigned Mask = 0; + // 8 nodes, but we only care about the last 4. + for (unsigned i = 7; i >= 4; --i) { + int Val = SVOp->getMaskElt(i); + if (Val >= 0) + Mask |= (Val - 4); + if (i != 4) + Mask <<= 2; + } + return Mask; +} + +/// getShufflePSHUFLWImmediate - Return the appropriate immediate to shuffle +/// the specified VECTOR_SHUFFLE mask with the PSHUFLW instruction. +unsigned X86::getShufflePSHUFLWImmediate(SDNode *N) { + ShuffleVectorSDNode *SVOp = cast(N); + unsigned Mask = 0; + // 8 nodes, but we only care about the first 4. + for (int i = 3; i >= 0; --i) { + int Val = SVOp->getMaskElt(i); + if (Val >= 0) + Mask |= Val; + if (i != 0) + Mask <<= 2; + } + return Mask; +} + +/// getShufflePALIGNRImmediate - Return the appropriate immediate to shuffle +/// the specified VECTOR_SHUFFLE mask with the PALIGNR instruction. +unsigned X86::getShufflePALIGNRImmediate(SDNode *N) { + ShuffleVectorSDNode *SVOp = cast(N); + EVT VVT = N->getValueType(0); + unsigned EltSize = VVT.getVectorElementType().getSizeInBits() >> 3; + int Val = 0; + + unsigned i, e; + for (i = 0, e = VVT.getVectorNumElements(); i != e; ++i) { + Val = SVOp->getMaskElt(i); + if (Val >= 0) + break; + } + return (Val - i) * EltSize; +} + +/// isZeroNode - Returns true if Elt is a constant zero or a floating point +/// constant +0.0. +bool X86::isZeroNode(SDValue Elt) { + return ((isa(Elt) && + cast(Elt)->getZExtValue() == 0) || + (isa(Elt) && + cast(Elt)->getValueAPF().isPosZero())); +} + +/// CommuteVectorShuffle - Swap vector_shuffle operands as well as values in +/// their permute mask. +static SDValue CommuteVectorShuffle(ShuffleVectorSDNode *SVOp, + SelectionDAG &DAG) { + EVT VT = SVOp->getValueType(0); + unsigned NumElems = VT.getVectorNumElements(); + SmallVector MaskVec; + + for (unsigned i = 0; i != NumElems; ++i) { + int idx = SVOp->getMaskElt(i); + if (idx < 0) + MaskVec.push_back(idx); + else if (idx < (int)NumElems) + MaskVec.push_back(idx + NumElems); + else + MaskVec.push_back(idx - NumElems); + } + return DAG.getVectorShuffle(VT, SVOp->getDebugLoc(), SVOp->getOperand(1), + SVOp->getOperand(0), &MaskVec[0]); +} + +/// CommuteVectorShuffleMask - Change values in a shuffle permute mask assuming +/// the two vector operands have swapped position. +static void CommuteVectorShuffleMask(SmallVectorImpl &Mask, EVT VT) { + unsigned NumElems = VT.getVectorNumElements(); + for (unsigned i = 0; i != NumElems; ++i) { + int idx = Mask[i]; + if (idx < 0) + continue; + else if (idx < (int)NumElems) + Mask[i] = idx + NumElems; + else + Mask[i] = idx - NumElems; + } +} + +/// ShouldXformToMOVHLPS - Return true if the node should be transformed to +/// match movhlps. The lower half elements should come from upper half of +/// V1 (and in order), and the upper half elements should come from the upper +/// half of V2 (and in order). +static bool ShouldXformToMOVHLPS(ShuffleVectorSDNode *Op) { + if (Op->getValueType(0).getVectorNumElements() != 4) + return false; + for (unsigned i = 0, e = 2; i != e; ++i) + if (!isUndefOrEqual(Op->getMaskElt(i), i+2)) + return false; + for (unsigned i = 2; i != 4; ++i) + if (!isUndefOrEqual(Op->getMaskElt(i), i+4)) + return false; + return true; +} + +/// isScalarLoadToVector - Returns true if the node is a scalar load that +/// is promoted to a vector. It also returns the LoadSDNode by reference if +/// required. +static bool isScalarLoadToVector(SDNode *N, LoadSDNode **LD = NULL) { + if (N->getOpcode() != ISD::SCALAR_TO_VECTOR) + return false; + N = N->getOperand(0).getNode(); + if (!ISD::isNON_EXTLoad(N)) + return false; + if (LD) + *LD = cast(N); + return true; +} + +/// ShouldXformToMOVLP{S|D} - Return true if the node should be transformed to +/// match movlp{s|d}. The lower half elements should come from lower half of +/// V1 (and in order), and the upper half elements should come from the upper +/// half of V2 (and in order). And since V1 will become the source of the +/// MOVLP, it must be either a vector load or a scalar load to vector. +static bool ShouldXformToMOVLP(SDNode *V1, SDNode *V2, + ShuffleVectorSDNode *Op) { + if (!ISD::isNON_EXTLoad(V1) && !isScalarLoadToVector(V1)) + return false; + // Is V2 is a vector load, don't do this transformation. We will try to use + // load folding shufps op. + if (ISD::isNON_EXTLoad(V2)) + return false; + + unsigned NumElems = Op->getValueType(0).getVectorNumElements(); + + if (NumElems != 2 && NumElems != 4) + return false; + for (unsigned i = 0, e = NumElems/2; i != e; ++i) + if (!isUndefOrEqual(Op->getMaskElt(i), i)) + return false; + for (unsigned i = NumElems/2; i != NumElems; ++i) + if (!isUndefOrEqual(Op->getMaskElt(i), i+NumElems)) + return false; + return true; +} + +/// isSplatVector - Returns true if N is a BUILD_VECTOR node whose elements are +/// all the same. +static bool isSplatVector(SDNode *N) { + if (N->getOpcode() != ISD::BUILD_VECTOR) + return false; + + SDValue SplatValue = N->getOperand(0); + for (unsigned i = 1, e = N->getNumOperands(); i != e; ++i) + if (N->getOperand(i) != SplatValue) + return false; + return true; +} + +/// isZeroShuffle - Returns true if N is a VECTOR_SHUFFLE that can be resolved +/// to an zero vector. +/// FIXME: move to dag combiner / method on ShuffleVectorSDNode +static bool isZeroShuffle(ShuffleVectorSDNode *N) { + SDValue V1 = N->getOperand(0); + SDValue V2 = N->getOperand(1); + unsigned NumElems = N->getValueType(0).getVectorNumElements(); + for (unsigned i = 0; i != NumElems; ++i) { + int Idx = N->getMaskElt(i); + if (Idx >= (int)NumElems) { + unsigned Opc = V2.getOpcode(); + if (Opc == ISD::UNDEF || ISD::isBuildVectorAllZeros(V2.getNode())) + continue; + if (Opc != ISD::BUILD_VECTOR || + !X86::isZeroNode(V2.getOperand(Idx-NumElems))) + return false; + } else if (Idx >= 0) { + unsigned Opc = V1.getOpcode(); + if (Opc == ISD::UNDEF || ISD::isBuildVectorAllZeros(V1.getNode())) + continue; + if (Opc != ISD::BUILD_VECTOR || + !X86::isZeroNode(V1.getOperand(Idx))) + return false; + } + } + return true; +} + +/// getZeroVector - Returns a vector of specified type with all zero elements. +/// +static SDValue getZeroVector(EVT VT, bool HasSSE2, SelectionDAG &DAG, + DebugLoc dl) { + assert(VT.isVector() && "Expected a vector type"); + + // Always build zero vectors as <4 x i32> or <2 x i32> bitcasted to their dest + // type. This ensures they get CSE'd. + SDValue Vec; + if (VT.getSizeInBits() == 64) { // MMX + SDValue Cst = DAG.getTargetConstant(0, MVT::i32); + Vec = DAG.getNode(ISD::BUILD_VECTOR, dl, MVT::v2i32, Cst, Cst); + } else if (HasSSE2) { // SSE2 + SDValue Cst = DAG.getTargetConstant(0, MVT::i32); + Vec = DAG.getNode(ISD::BUILD_VECTOR, dl, MVT::v4i32, Cst, Cst, Cst, Cst); + } else { // SSE1 + SDValue Cst = DAG.getTargetConstantFP(+0.0, MVT::f32); + Vec = DAG.getNode(ISD::BUILD_VECTOR, dl, MVT::v4f32, Cst, Cst, Cst, Cst); + } + return DAG.getNode(ISD::BIT_CONVERT, dl, VT, Vec); +} + +/// getOnesVector - Returns a vector of specified type with all bits set. +/// +static SDValue getOnesVector(EVT VT, SelectionDAG &DAG, DebugLoc dl) { + assert(VT.isVector() && "Expected a vector type"); + + // Always build ones vectors as <4 x i32> or <2 x i32> bitcasted to their dest + // type. This ensures they get CSE'd. + SDValue Cst = DAG.getTargetConstant(~0U, MVT::i32); + SDValue Vec; + if (VT.getSizeInBits() == 64) // MMX + Vec = DAG.getNode(ISD::BUILD_VECTOR, dl, MVT::v2i32, Cst, Cst); + else // SSE + Vec = DAG.getNode(ISD::BUILD_VECTOR, dl, MVT::v4i32, Cst, Cst, Cst, Cst); + return DAG.getNode(ISD::BIT_CONVERT, dl, VT, Vec); +} + + +/// NormalizeMask - V2 is a splat, modify the mask (if needed) so all elements +/// that point to V2 points to its first element. +static SDValue NormalizeMask(ShuffleVectorSDNode *SVOp, SelectionDAG &DAG) { + EVT VT = SVOp->getValueType(0); + unsigned NumElems = VT.getVectorNumElements(); + + bool Changed = false; + SmallVector MaskVec; + SVOp->getMask(MaskVec); + + for (unsigned i = 0; i != NumElems; ++i) { + if (MaskVec[i] > (int)NumElems) { + MaskVec[i] = NumElems; + Changed = true; + } + } + if (Changed) + return DAG.getVectorShuffle(VT, SVOp->getDebugLoc(), SVOp->getOperand(0), + SVOp->getOperand(1), &MaskVec[0]); + return SDValue(SVOp, 0); +} + +/// getMOVLMask - Returns a vector_shuffle mask for an movs{s|d}, movd +/// operation of specified width. +static SDValue getMOVL(SelectionDAG &DAG, DebugLoc dl, EVT VT, SDValue V1, + SDValue V2) { + unsigned NumElems = VT.getVectorNumElements(); + SmallVector Mask; + Mask.push_back(NumElems); + for (unsigned i = 1; i != NumElems; ++i) + Mask.push_back(i); + return DAG.getVectorShuffle(VT, dl, V1, V2, &Mask[0]); +} + +/// getUnpackl - Returns a vector_shuffle node for an unpackl operation. +static SDValue getUnpackl(SelectionDAG &DAG, DebugLoc dl, EVT VT, SDValue V1, + SDValue V2) { + unsigned NumElems = VT.getVectorNumElements(); + SmallVector Mask; + for (unsigned i = 0, e = NumElems/2; i != e; ++i) { + Mask.push_back(i); + Mask.push_back(i + NumElems); + } + return DAG.getVectorShuffle(VT, dl, V1, V2, &Mask[0]); +} + +/// getUnpackhMask - Returns a vector_shuffle node for an unpackh operation. +static SDValue getUnpackh(SelectionDAG &DAG, DebugLoc dl, EVT VT, SDValue V1, + SDValue V2) { + unsigned NumElems = VT.getVectorNumElements(); + unsigned Half = NumElems/2; + SmallVector Mask; + for (unsigned i = 0; i != Half; ++i) { + Mask.push_back(i + Half); + Mask.push_back(i + NumElems + Half); + } + return DAG.getVectorShuffle(VT, dl, V1, V2, &Mask[0]); +} + +/// PromoteSplat - Promote a splat of v4f32, v8i16 or v16i8 to v4i32. +static SDValue PromoteSplat(ShuffleVectorSDNode *SV, SelectionDAG &DAG, + bool HasSSE2) { + if (SV->getValueType(0).getVectorNumElements() <= 4) + return SDValue(SV, 0); + + EVT PVT = MVT::v4f32; + EVT VT = SV->getValueType(0); + DebugLoc dl = SV->getDebugLoc(); + SDValue V1 = SV->getOperand(0); + int NumElems = VT.getVectorNumElements(); + int EltNo = SV->getSplatIndex(); + + // unpack elements to the correct location + while (NumElems > 4) { + if (EltNo < NumElems/2) { + V1 = getUnpackl(DAG, dl, VT, V1, V1); + } else { + V1 = getUnpackh(DAG, dl, VT, V1, V1); + EltNo -= NumElems/2; + } + NumElems >>= 1; + } + + // Perform the splat. + int SplatMask[4] = { EltNo, EltNo, EltNo, EltNo }; + V1 = DAG.getNode(ISD::BIT_CONVERT, dl, PVT, V1); + V1 = DAG.getVectorShuffle(PVT, dl, V1, DAG.getUNDEF(PVT), &SplatMask[0]); + return DAG.getNode(ISD::BIT_CONVERT, dl, VT, V1); +} + +/// getShuffleVectorZeroOrUndef - Return a vector_shuffle of the specified +/// vector of zero or undef vector. This produces a shuffle where the low +/// element of V2 is swizzled into the zero/undef vector, landing at element +/// Idx. This produces a shuffle mask like 4,1,2,3 (idx=0) or 0,1,2,4 (idx=3). +static SDValue getShuffleVectorZeroOrUndef(SDValue V2, unsigned Idx, + bool isZero, bool HasSSE2, + SelectionDAG &DAG) { + EVT VT = V2.getValueType(); + SDValue V1 = isZero + ? getZeroVector(VT, HasSSE2, DAG, V2.getDebugLoc()) : DAG.getUNDEF(VT); + unsigned NumElems = VT.getVectorNumElements(); + SmallVector MaskVec; + for (unsigned i = 0; i != NumElems; ++i) + // If this is the insertion idx, put the low elt of V2 here. + MaskVec.push_back(i == Idx ? NumElems : i); + return DAG.getVectorShuffle(VT, V2.getDebugLoc(), V1, V2, &MaskVec[0]); +} + +/// getNumOfConsecutiveZeros - Return the number of elements in a result of +/// a shuffle that is zero. +static +unsigned getNumOfConsecutiveZeros(ShuffleVectorSDNode *SVOp, int NumElems, + bool Low, SelectionDAG &DAG) { + unsigned NumZeros = 0; + for (int i = 0; i < NumElems; ++i) { + unsigned Index = Low ? i : NumElems-i-1; + int Idx = SVOp->getMaskElt(Index); + if (Idx < 0) { + ++NumZeros; + continue; + } + SDValue Elt = DAG.getShuffleScalarElt(SVOp, Index); + if (Elt.getNode() && X86::isZeroNode(Elt)) + ++NumZeros; + else + break; + } + return NumZeros; +} + +/// isVectorShift - Returns true if the shuffle can be implemented as a +/// logical left or right shift of a vector. +/// FIXME: split into pslldqi, psrldqi, palignr variants. +static bool isVectorShift(ShuffleVectorSDNode *SVOp, SelectionDAG &DAG, + bool &isLeft, SDValue &ShVal, unsigned &ShAmt) { + int NumElems = SVOp->getValueType(0).getVectorNumElements(); + + isLeft = true; + unsigned NumZeros = getNumOfConsecutiveZeros(SVOp, NumElems, true, DAG); + if (!NumZeros) { + isLeft = false; + NumZeros = getNumOfConsecutiveZeros(SVOp, NumElems, false, DAG); + if (!NumZeros) + return false; + } + bool SeenV1 = false; + bool SeenV2 = false; + for (int i = NumZeros; i < NumElems; ++i) { + int Val = isLeft ? (i - NumZeros) : i; + int Idx = SVOp->getMaskElt(isLeft ? i : (i - NumZeros)); + if (Idx < 0) + continue; + if (Idx < NumElems) + SeenV1 = true; + else { + Idx -= NumElems; + SeenV2 = true; + } + if (Idx != Val) + return false; + } + if (SeenV1 && SeenV2) + return false; + + ShVal = SeenV1 ? SVOp->getOperand(0) : SVOp->getOperand(1); + ShAmt = NumZeros; + return true; +} + + +/// LowerBuildVectorv16i8 - Custom lower build_vector of v16i8. +/// +static SDValue LowerBuildVectorv16i8(SDValue Op, unsigned NonZeros, + unsigned NumNonZero, unsigned NumZero, + SelectionDAG &DAG, TargetLowering &TLI) { + if (NumNonZero > 8) + return SDValue(); + + DebugLoc dl = Op.getDebugLoc(); + SDValue V(0, 0); + bool First = true; + for (unsigned i = 0; i < 16; ++i) { + bool ThisIsNonZero = (NonZeros & (1 << i)) != 0; + if (ThisIsNonZero && First) { + if (NumZero) + V = getZeroVector(MVT::v8i16, true, DAG, dl); + else + V = DAG.getUNDEF(MVT::v8i16); + First = false; + } + + if ((i & 1) != 0) { + SDValue ThisElt(0, 0), LastElt(0, 0); + bool LastIsNonZero = (NonZeros & (1 << (i-1))) != 0; + if (LastIsNonZero) { + LastElt = DAG.getNode(ISD::ZERO_EXTEND, dl, + MVT::i16, Op.getOperand(i-1)); + } + if (ThisIsNonZero) { + ThisElt = DAG.getNode(ISD::ZERO_EXTEND, dl, MVT::i16, Op.getOperand(i)); + ThisElt = DAG.getNode(ISD::SHL, dl, MVT::i16, + ThisElt, DAG.getConstant(8, MVT::i8)); + if (LastIsNonZero) + ThisElt = DAG.getNode(ISD::OR, dl, MVT::i16, ThisElt, LastElt); + } else + ThisElt = LastElt; + + if (ThisElt.getNode()) + V = DAG.getNode(ISD::INSERT_VECTOR_ELT, dl, MVT::v8i16, V, ThisElt, + DAG.getIntPtrConstant(i/2)); + } + } + + return DAG.getNode(ISD::BIT_CONVERT, dl, MVT::v16i8, V); +} + +/// LowerBuildVectorv8i16 - Custom lower build_vector of v8i16. +/// +static SDValue LowerBuildVectorv8i16(SDValue Op, unsigned NonZeros, + unsigned NumNonZero, unsigned NumZero, + SelectionDAG &DAG, TargetLowering &TLI) { + if (NumNonZero > 4) + return SDValue(); + + DebugLoc dl = Op.getDebugLoc(); + SDValue V(0, 0); + bool First = true; + for (unsigned i = 0; i < 8; ++i) { + bool isNonZero = (NonZeros & (1 << i)) != 0; + if (isNonZero) { + if (First) { + if (NumZero) + V = getZeroVector(MVT::v8i16, true, DAG, dl); + else + V = DAG.getUNDEF(MVT::v8i16); + First = false; + } + V = DAG.getNode(ISD::INSERT_VECTOR_ELT, dl, + MVT::v8i16, V, Op.getOperand(i), + DAG.getIntPtrConstant(i)); + } + } + + return V; +} + +/// getVShift - Return a vector logical shift node. +/// +static SDValue getVShift(bool isLeft, EVT VT, SDValue SrcOp, + unsigned NumBits, SelectionDAG &DAG, + const TargetLowering &TLI, DebugLoc dl) { + bool isMMX = VT.getSizeInBits() == 64; + EVT ShVT = isMMX ? MVT::v1i64 : MVT::v2i64; + unsigned Opc = isLeft ? X86ISD::VSHL : X86ISD::VSRL; + SrcOp = DAG.getNode(ISD::BIT_CONVERT, dl, ShVT, SrcOp); + return DAG.getNode(ISD::BIT_CONVERT, dl, VT, + DAG.getNode(Opc, dl, ShVT, SrcOp, + DAG.getConstant(NumBits, TLI.getShiftAmountTy()))); +} + +SDValue +X86TargetLowering::LowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG) { + DebugLoc dl = Op.getDebugLoc(); + // All zero's are handled with pxor, all one's are handled with pcmpeqd. + if (ISD::isBuildVectorAllZeros(Op.getNode()) + || ISD::isBuildVectorAllOnes(Op.getNode())) { + // Canonicalize this to either <4 x i32> or <2 x i32> (SSE vs MMX) to + // 1) ensure the zero vectors are CSE'd, and 2) ensure that i64 scalars are + // eliminated on x86-32 hosts. + if (Op.getValueType() == MVT::v4i32 || Op.getValueType() == MVT::v2i32) + return Op; + + if (ISD::isBuildVectorAllOnes(Op.getNode())) + return getOnesVector(Op.getValueType(), DAG, dl); + return getZeroVector(Op.getValueType(), Subtarget->hasSSE2(), DAG, dl); + } + + EVT VT = Op.getValueType(); + EVT ExtVT = VT.getVectorElementType(); + unsigned EVTBits = ExtVT.getSizeInBits(); + + unsigned NumElems = Op.getNumOperands(); + unsigned NumZero = 0; + unsigned NumNonZero = 0; + unsigned NonZeros = 0; + bool IsAllConstants = true; + SmallSet Values; + for (unsigned i = 0; i < NumElems; ++i) { + SDValue Elt = Op.getOperand(i); + if (Elt.getOpcode() == ISD::UNDEF) + continue; + Values.insert(Elt); + if (Elt.getOpcode() != ISD::Constant && + Elt.getOpcode() != ISD::ConstantFP) + IsAllConstants = false; + if (X86::isZeroNode(Elt)) + NumZero++; + else { + NonZeros |= (1 << i); + NumNonZero++; + } + } + + if (NumNonZero == 0) { + // All undef vector. Return an UNDEF. All zero vectors were handled above. + return DAG.getUNDEF(VT); + } + + // Special case for single non-zero, non-undef, element. + if (NumNonZero == 1) { + unsigned Idx = CountTrailingZeros_32(NonZeros); + SDValue Item = Op.getOperand(Idx); + + // If this is an insertion of an i64 value on x86-32, and if the top bits of + // the value are obviously zero, truncate the value to i32 and do the + // insertion that way. Only do this if the value is non-constant or if the + // value is a constant being inserted into element 0. It is cheaper to do + // a constant pool load than it is to do a movd + shuffle. + if (ExtVT == MVT::i64 && !Subtarget->is64Bit() && + (!IsAllConstants || Idx == 0)) { + if (DAG.MaskedValueIsZero(Item, APInt::getBitsSet(64, 32, 64))) { + // Handle MMX and SSE both. + EVT VecVT = VT == MVT::v2i64 ? MVT::v4i32 : MVT::v2i32; + unsigned VecElts = VT == MVT::v2i64 ? 4 : 2; + + // Truncate the value (which may itself be a constant) to i32, and + // convert it to a vector with movd (S2V+shuffle to zero extend). + Item = DAG.getNode(ISD::TRUNCATE, dl, MVT::i32, Item); + Item = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, VecVT, Item); + Item = getShuffleVectorZeroOrUndef(Item, 0, true, + Subtarget->hasSSE2(), DAG); + + // Now we have our 32-bit value zero extended in the low element of + // a vector. If Idx != 0, swizzle it into place. + if (Idx != 0) { + SmallVector Mask; + Mask.push_back(Idx); + for (unsigned i = 1; i != VecElts; ++i) + Mask.push_back(i); + Item = DAG.getVectorShuffle(VecVT, dl, Item, + DAG.getUNDEF(Item.getValueType()), + &Mask[0]); + } + return DAG.getNode(ISD::BIT_CONVERT, dl, Op.getValueType(), Item); + } + } + + // If we have a constant or non-constant insertion into the low element of + // a vector, we can do this with SCALAR_TO_VECTOR + shuffle of zero into + // the rest of the elements. This will be matched as movd/movq/movss/movsd + // depending on what the source datatype is. + if (Idx == 0) { + if (NumZero == 0) { + return DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, VT, Item); + } else if (ExtVT == MVT::i32 || ExtVT == MVT::f32 || ExtVT == MVT::f64 || + (ExtVT == MVT::i64 && Subtarget->is64Bit())) { + Item = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, VT, Item); + // Turn it into a MOVL (i.e. movss, movsd, or movd) to a zero vector. + return getShuffleVectorZeroOrUndef(Item, 0, true, Subtarget->hasSSE2(), + DAG); + } else if (ExtVT == MVT::i16 || ExtVT == MVT::i8) { + Item = DAG.getNode(ISD::ZERO_EXTEND, dl, MVT::i32, Item); + EVT MiddleVT = VT.getSizeInBits() == 64 ? MVT::v2i32 : MVT::v4i32; + Item = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, MiddleVT, Item); + Item = getShuffleVectorZeroOrUndef(Item, 0, true, + Subtarget->hasSSE2(), DAG); + return DAG.getNode(ISD::BIT_CONVERT, dl, VT, Item); + } + } + + // Is it a vector logical left shift? + if (NumElems == 2 && Idx == 1 && + X86::isZeroNode(Op.getOperand(0)) && + !X86::isZeroNode(Op.getOperand(1))) { + unsigned NumBits = VT.getSizeInBits(); + return getVShift(true, VT, + DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, + VT, Op.getOperand(1)), + NumBits/2, DAG, *this, dl); + } + + if (IsAllConstants) // Otherwise, it's better to do a constpool load. + return SDValue(); + + // Otherwise, if this is a vector with i32 or f32 elements, and the element + // is a non-constant being inserted into an element other than the low one, + // we can't use a constant pool load. Instead, use SCALAR_TO_VECTOR (aka + // movd/movss) to move this into the low element, then shuffle it into + // place. + if (EVTBits == 32) { + Item = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, VT, Item); + + // Turn it into a shuffle of zero and zero-extended scalar to vector. + Item = getShuffleVectorZeroOrUndef(Item, 0, NumZero > 0, + Subtarget->hasSSE2(), DAG); + SmallVector MaskVec; + for (unsigned i = 0; i < NumElems; i++) + MaskVec.push_back(i == Idx ? 0 : 1); + return DAG.getVectorShuffle(VT, dl, Item, DAG.getUNDEF(VT), &MaskVec[0]); + } + } + + // Splat is obviously ok. Let legalizer expand it to a shuffle. + if (Values.size() == 1) + return SDValue(); + + // A vector full of immediates; various special cases are already + // handled, so this is best done with a single constant-pool load. + if (IsAllConstants) + return SDValue(); + + // Let legalizer expand 2-wide build_vectors. + if (EVTBits == 64) { + if (NumNonZero == 1) { + // One half is zero or undef. + unsigned Idx = CountTrailingZeros_32(NonZeros); + SDValue V2 = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, VT, + Op.getOperand(Idx)); + return getShuffleVectorZeroOrUndef(V2, Idx, true, + Subtarget->hasSSE2(), DAG); + } + return SDValue(); + } + + // If element VT is < 32 bits, convert it to inserts into a zero vector. + if (EVTBits == 8 && NumElems == 16) { + SDValue V = LowerBuildVectorv16i8(Op, NonZeros,NumNonZero,NumZero, DAG, + *this); + if (V.getNode()) return V; + } + + if (EVTBits == 16 && NumElems == 8) { + SDValue V = LowerBuildVectorv8i16(Op, NonZeros,NumNonZero,NumZero, DAG, + *this); + if (V.getNode()) return V; + } + + // If element VT is == 32 bits, turn it into a number of shuffles. + SmallVector V; + V.resize(NumElems); + if (NumElems == 4 && NumZero > 0) { + for (unsigned i = 0; i < 4; ++i) { + bool isZero = !(NonZeros & (1 << i)); + if (isZero) + V[i] = getZeroVector(VT, Subtarget->hasSSE2(), DAG, dl); + else + V[i] = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, VT, Op.getOperand(i)); + } + + for (unsigned i = 0; i < 2; ++i) { + switch ((NonZeros & (0x3 << i*2)) >> (i*2)) { + default: break; + case 0: + V[i] = V[i*2]; // Must be a zero vector. + break; + case 1: + V[i] = getMOVL(DAG, dl, VT, V[i*2+1], V[i*2]); + break; + case 2: + V[i] = getMOVL(DAG, dl, VT, V[i*2], V[i*2+1]); + break; + case 3: + V[i] = getUnpackl(DAG, dl, VT, V[i*2], V[i*2+1]); + break; + } + } + + SmallVector MaskVec; + bool Reverse = (NonZeros & 0x3) == 2; + for (unsigned i = 0; i < 2; ++i) + MaskVec.push_back(Reverse ? 1-i : i); + Reverse = ((NonZeros & (0x3 << 2)) >> 2) == 2; + for (unsigned i = 0; i < 2; ++i) + MaskVec.push_back(Reverse ? 1-i+NumElems : i+NumElems); + return DAG.getVectorShuffle(VT, dl, V[0], V[1], &MaskVec[0]); + } + + if (Values.size() > 2) { + // If we have SSE 4.1, Expand into a number of inserts unless the number of + // values to be inserted is equal to the number of elements, in which case + // use the unpack code below in the hopes of matching the consecutive elts + // load merge pattern for shuffles. + // FIXME: We could probably just check that here directly. + if (Values.size() < NumElems && VT.getSizeInBits() == 128 && + getSubtarget()->hasSSE41()) { + V[0] = DAG.getUNDEF(VT); + for (unsigned i = 0; i < NumElems; ++i) + if (Op.getOperand(i).getOpcode() != ISD::UNDEF) + V[0] = DAG.getNode(ISD::INSERT_VECTOR_ELT, dl, VT, V[0], + Op.getOperand(i), DAG.getIntPtrConstant(i)); + return V[0]; + } + // Expand into a number of unpckl*. + // e.g. for v4f32 + // Step 1: unpcklps 0, 2 ==> X: + // : unpcklps 1, 3 ==> Y: + // Step 2: unpcklps X, Y ==> <3, 2, 1, 0> + for (unsigned i = 0; i < NumElems; ++i) + V[i] = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, VT, Op.getOperand(i)); + NumElems >>= 1; + while (NumElems != 0) { + for (unsigned i = 0; i < NumElems; ++i) + V[i] = getUnpackl(DAG, dl, VT, V[i], V[i + NumElems]); + NumElems >>= 1; + } + return V[0]; + } + + return SDValue(); +} + +// v8i16 shuffles - Prefer shuffles in the following order: +// 1. [all] pshuflw, pshufhw, optional move +// 2. [ssse3] 1 x pshufb +// 3. [ssse3] 2 x pshufb + 1 x por +// 4. [all] mov + pshuflw + pshufhw + N x (pextrw + pinsrw) +static +SDValue LowerVECTOR_SHUFFLEv8i16(ShuffleVectorSDNode *SVOp, + SelectionDAG &DAG, X86TargetLowering &TLI) { + SDValue V1 = SVOp->getOperand(0); + SDValue V2 = SVOp->getOperand(1); + DebugLoc dl = SVOp->getDebugLoc(); + SmallVector MaskVals; + + // Determine if more than 1 of the words in each of the low and high quadwords + // of the result come from the same quadword of one of the two inputs. Undef + // mask values count as coming from any quadword, for better codegen. + SmallVector LoQuad(4); + SmallVector HiQuad(4); + BitVector InputQuads(4); + for (unsigned i = 0; i < 8; ++i) { + SmallVectorImpl &Quad = i < 4 ? LoQuad : HiQuad; + int EltIdx = SVOp->getMaskElt(i); + MaskVals.push_back(EltIdx); + if (EltIdx < 0) { + ++Quad[0]; + ++Quad[1]; + ++Quad[2]; + ++Quad[3]; + continue; + } + ++Quad[EltIdx / 4]; + InputQuads.set(EltIdx / 4); + } + + int BestLoQuad = -1; + unsigned MaxQuad = 1; + for (unsigned i = 0; i < 4; ++i) { + if (LoQuad[i] > MaxQuad) { + BestLoQuad = i; + MaxQuad = LoQuad[i]; + } + } + + int BestHiQuad = -1; + MaxQuad = 1; + for (unsigned i = 0; i < 4; ++i) { + if (HiQuad[i] > MaxQuad) { + BestHiQuad = i; + MaxQuad = HiQuad[i]; + } + } + + // For SSSE3, If all 8 words of the result come from only 1 quadword of each + // of the two input vectors, shuffle them into one input vector so only a + // single pshufb instruction is necessary. If There are more than 2 input + // quads, disable the next transformation since it does not help SSSE3. + bool V1Used = InputQuads[0] || InputQuads[1]; + bool V2Used = InputQuads[2] || InputQuads[3]; + if (TLI.getSubtarget()->hasSSSE3()) { + if (InputQuads.count() == 2 && V1Used && V2Used) { + BestLoQuad = InputQuads.find_first(); + BestHiQuad = InputQuads.find_next(BestLoQuad); + } + if (InputQuads.count() > 2) { + BestLoQuad = -1; + BestHiQuad = -1; + } + } + + // If BestLoQuad or BestHiQuad are set, shuffle the quads together and update + // the shuffle mask. If a quad is scored as -1, that means that it contains + // words from all 4 input quadwords. + SDValue NewV; + if (BestLoQuad >= 0 || BestHiQuad >= 0) { + SmallVector MaskV; + MaskV.push_back(BestLoQuad < 0 ? 0 : BestLoQuad); + MaskV.push_back(BestHiQuad < 0 ? 1 : BestHiQuad); + NewV = DAG.getVectorShuffle(MVT::v2i64, dl, + DAG.getNode(ISD::BIT_CONVERT, dl, MVT::v2i64, V1), + DAG.getNode(ISD::BIT_CONVERT, dl, MVT::v2i64, V2), &MaskV[0]); + NewV = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::v8i16, NewV); + + // Rewrite the MaskVals and assign NewV to V1 if NewV now contains all the + // source words for the shuffle, to aid later transformations. + bool AllWordsInNewV = true; + bool InOrder[2] = { true, true }; + for (unsigned i = 0; i != 8; ++i) { + int idx = MaskVals[i]; + if (idx != (int)i) + InOrder[i/4] = false; + if (idx < 0 || (idx/4) == BestLoQuad || (idx/4) == BestHiQuad) + continue; + AllWordsInNewV = false; + break; + } + + bool pshuflw = AllWordsInNewV, pshufhw = AllWordsInNewV; + if (AllWordsInNewV) { + for (int i = 0; i != 8; ++i) { + int idx = MaskVals[i]; + if (idx < 0) + continue; + idx = MaskVals[i] = (idx / 4) == BestLoQuad ? (idx & 3) : (idx & 3) + 4; + if ((idx != i) && idx < 4) + pshufhw = false; + if ((idx != i) && idx > 3) + pshuflw = false; + } + V1 = NewV; + V2Used = false; + BestLoQuad = 0; + BestHiQuad = 1; + } + + // If we've eliminated the use of V2, and the new mask is a pshuflw or + // pshufhw, that's as cheap as it gets. Return the new shuffle. + if ((pshufhw && InOrder[0]) || (pshuflw && InOrder[1])) { + return DAG.getVectorShuffle(MVT::v8i16, dl, NewV, + DAG.getUNDEF(MVT::v8i16), &MaskVals[0]); + } + } + + // If we have SSSE3, and all words of the result are from 1 input vector, + // case 2 is generated, otherwise case 3 is generated. If no SSSE3 + // is present, fall back to case 4. + if (TLI.getSubtarget()->hasSSSE3()) { + SmallVector pshufbMask; + + // If we have elements from both input vectors, set the high bit of the + // shuffle mask element to zero out elements that come from V2 in the V1 + // mask, and elements that come from V1 in the V2 mask, so that the two + // results can be OR'd together. + bool TwoInputs = V1Used && V2Used; + for (unsigned i = 0; i != 8; ++i) { + int EltIdx = MaskVals[i] * 2; + if (TwoInputs && (EltIdx >= 16)) { + pshufbMask.push_back(DAG.getConstant(0x80, MVT::i8)); + pshufbMask.push_back(DAG.getConstant(0x80, MVT::i8)); + continue; + } + pshufbMask.push_back(DAG.getConstant(EltIdx, MVT::i8)); + pshufbMask.push_back(DAG.getConstant(EltIdx+1, MVT::i8)); + } + V1 = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::v16i8, V1); + V1 = DAG.getNode(X86ISD::PSHUFB, dl, MVT::v16i8, V1, + DAG.getNode(ISD::BUILD_VECTOR, dl, + MVT::v16i8, &pshufbMask[0], 16)); + if (!TwoInputs) + return DAG.getNode(ISD::BIT_CONVERT, dl, MVT::v8i16, V1); + + // Calculate the shuffle mask for the second input, shuffle it, and + // OR it with the first shuffled input. + pshufbMask.clear(); + for (unsigned i = 0; i != 8; ++i) { + int EltIdx = MaskVals[i] * 2; + if (EltIdx < 16) { + pshufbMask.push_back(DAG.getConstant(0x80, MVT::i8)); + pshufbMask.push_back(DAG.getConstant(0x80, MVT::i8)); + continue; + } + pshufbMask.push_back(DAG.getConstant(EltIdx - 16, MVT::i8)); + pshufbMask.push_back(DAG.getConstant(EltIdx - 15, MVT::i8)); + } + V2 = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::v16i8, V2); + V2 = DAG.getNode(X86ISD::PSHUFB, dl, MVT::v16i8, V2, + DAG.getNode(ISD::BUILD_VECTOR, dl, + MVT::v16i8, &pshufbMask[0], 16)); + V1 = DAG.getNode(ISD::OR, dl, MVT::v16i8, V1, V2); + return DAG.getNode(ISD::BIT_CONVERT, dl, MVT::v8i16, V1); + } + + // If BestLoQuad >= 0, generate a pshuflw to put the low elements in order, + // and update MaskVals with new element order. + BitVector InOrder(8); + if (BestLoQuad >= 0) { + SmallVector MaskV; + for (int i = 0; i != 4; ++i) { + int idx = MaskVals[i]; + if (idx < 0) { + MaskV.push_back(-1); + InOrder.set(i); + } else if ((idx / 4) == BestLoQuad) { + MaskV.push_back(idx & 3); + InOrder.set(i); + } else { + MaskV.push_back(-1); + } + } + for (unsigned i = 4; i != 8; ++i) + MaskV.push_back(i); + NewV = DAG.getVectorShuffle(MVT::v8i16, dl, NewV, DAG.getUNDEF(MVT::v8i16), + &MaskV[0]); + } + + // If BestHi >= 0, generate a pshufhw to put the high elements in order, + // and update MaskVals with the new element order. + if (BestHiQuad >= 0) { + SmallVector MaskV; + for (unsigned i = 0; i != 4; ++i) + MaskV.push_back(i); + for (unsigned i = 4; i != 8; ++i) { + int idx = MaskVals[i]; + if (idx < 0) { + MaskV.push_back(-1); + InOrder.set(i); + } else if ((idx / 4) == BestHiQuad) { + MaskV.push_back((idx & 3) + 4); + InOrder.set(i); + } else { + MaskV.push_back(-1); + } + } + NewV = DAG.getVectorShuffle(MVT::v8i16, dl, NewV, DAG.getUNDEF(MVT::v8i16), + &MaskV[0]); + } + + // In case BestHi & BestLo were both -1, which means each quadword has a word + // from each of the four input quadwords, calculate the InOrder bitvector now + // before falling through to the insert/extract cleanup. + if (BestLoQuad == -1 && BestHiQuad == -1) { + NewV = V1; + for (int i = 0; i != 8; ++i) + if (MaskVals[i] < 0 || MaskVals[i] == i) + InOrder.set(i); + } + + // The other elements are put in the right place using pextrw and pinsrw. + for (unsigned i = 0; i != 8; ++i) { + if (InOrder[i]) + continue; + int EltIdx = MaskVals[i]; + if (EltIdx < 0) + continue; + SDValue ExtOp = (EltIdx < 8) + ? DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, MVT::i16, V1, + DAG.getIntPtrConstant(EltIdx)) + : DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, MVT::i16, V2, + DAG.getIntPtrConstant(EltIdx - 8)); + NewV = DAG.getNode(ISD::INSERT_VECTOR_ELT, dl, MVT::v8i16, NewV, ExtOp, + DAG.getIntPtrConstant(i)); + } + return NewV; +} + +// v16i8 shuffles - Prefer shuffles in the following order: +// 1. [ssse3] 1 x pshufb +// 2. [ssse3] 2 x pshufb + 1 x por +// 3. [all] v8i16 shuffle + N x pextrw + rotate + pinsrw +static +SDValue LowerVECTOR_SHUFFLEv16i8(ShuffleVectorSDNode *SVOp, + SelectionDAG &DAG, X86TargetLowering &TLI) { + SDValue V1 = SVOp->getOperand(0); + SDValue V2 = SVOp->getOperand(1); + DebugLoc dl = SVOp->getDebugLoc(); + SmallVector MaskVals; + SVOp->getMask(MaskVals); + + // If we have SSSE3, case 1 is generated when all result bytes come from + // one of the inputs. Otherwise, case 2 is generated. If no SSSE3 is + // present, fall back to case 3. + // FIXME: kill V2Only once shuffles are canonizalized by getNode. + bool V1Only = true; + bool V2Only = true; + for (unsigned i = 0; i < 16; ++i) { + int EltIdx = MaskVals[i]; + if (EltIdx < 0) + continue; + if (EltIdx < 16) + V2Only = false; + else + V1Only = false; + } + + // If SSSE3, use 1 pshufb instruction per vector with elements in the result. + if (TLI.getSubtarget()->hasSSSE3()) { + SmallVector pshufbMask; + + // If all result elements are from one input vector, then only translate + // undef mask values to 0x80 (zero out result) in the pshufb mask. + // + // Otherwise, we have elements from both input vectors, and must zero out + // elements that come from V2 in the first mask, and V1 in the second mask + // so that we can OR them together. + bool TwoInputs = !(V1Only || V2Only); + for (unsigned i = 0; i != 16; ++i) { + int EltIdx = MaskVals[i]; + if (EltIdx < 0 || (TwoInputs && EltIdx >= 16)) { + pshufbMask.push_back(DAG.getConstant(0x80, MVT::i8)); + continue; + } + pshufbMask.push_back(DAG.getConstant(EltIdx, MVT::i8)); + } + // If all the elements are from V2, assign it to V1 and return after + // building the first pshufb. + if (V2Only) + V1 = V2; + V1 = DAG.getNode(X86ISD::PSHUFB, dl, MVT::v16i8, V1, + DAG.getNode(ISD::BUILD_VECTOR, dl, + MVT::v16i8, &pshufbMask[0], 16)); + if (!TwoInputs) + return V1; + + // Calculate the shuffle mask for the second input, shuffle it, and + // OR it with the first shuffled input. + pshufbMask.clear(); + for (unsigned i = 0; i != 16; ++i) { + int EltIdx = MaskVals[i]; + if (EltIdx < 16) { + pshufbMask.push_back(DAG.getConstant(0x80, MVT::i8)); + continue; + } + pshufbMask.push_back(DAG.getConstant(EltIdx - 16, MVT::i8)); + } + V2 = DAG.getNode(X86ISD::PSHUFB, dl, MVT::v16i8, V2, + DAG.getNode(ISD::BUILD_VECTOR, dl, + MVT::v16i8, &pshufbMask[0], 16)); + return DAG.getNode(ISD::OR, dl, MVT::v16i8, V1, V2); + } + + // No SSSE3 - Calculate in place words and then fix all out of place words + // With 0-16 extracts & inserts. Worst case is 16 bytes out of order from + // the 16 different words that comprise the two doublequadword input vectors. + V1 = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::v8i16, V1); + V2 = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::v8i16, V2); + SDValue NewV = V2Only ? V2 : V1; + for (int i = 0; i != 8; ++i) { + int Elt0 = MaskVals[i*2]; + int Elt1 = MaskVals[i*2+1]; + + // This word of the result is all undef, skip it. + if (Elt0 < 0 && Elt1 < 0) + continue; + + // This word of the result is already in the correct place, skip it. + if (V1Only && (Elt0 == i*2) && (Elt1 == i*2+1)) + continue; + if (V2Only && (Elt0 == i*2+16) && (Elt1 == i*2+17)) + continue; + + SDValue Elt0Src = Elt0 < 16 ? V1 : V2; + SDValue Elt1Src = Elt1 < 16 ? V1 : V2; + SDValue InsElt; + + // If Elt0 and Elt1 are defined, are consecutive, and can be load + // using a single extract together, load it and store it. + if ((Elt0 >= 0) && ((Elt0 + 1) == Elt1) && ((Elt0 & 1) == 0)) { + InsElt = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, MVT::i16, Elt1Src, + DAG.getIntPtrConstant(Elt1 / 2)); + NewV = DAG.getNode(ISD::INSERT_VECTOR_ELT, dl, MVT::v8i16, NewV, InsElt, + DAG.getIntPtrConstant(i)); + continue; + } + + // If Elt1 is defined, extract it from the appropriate source. If the + // source byte is not also odd, shift the extracted word left 8 bits + // otherwise clear the bottom 8 bits if we need to do an or. + if (Elt1 >= 0) { + InsElt = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, MVT::i16, Elt1Src, + DAG.getIntPtrConstant(Elt1 / 2)); + if ((Elt1 & 1) == 0) + InsElt = DAG.getNode(ISD::SHL, dl, MVT::i16, InsElt, + DAG.getConstant(8, TLI.getShiftAmountTy())); + else if (Elt0 >= 0) + InsElt = DAG.getNode(ISD::AND, dl, MVT::i16, InsElt, + DAG.getConstant(0xFF00, MVT::i16)); + } + // If Elt0 is defined, extract it from the appropriate source. If the + // source byte is not also even, shift the extracted word right 8 bits. If + // Elt1 was also defined, OR the extracted values together before + // inserting them in the result. + if (Elt0 >= 0) { + SDValue InsElt0 = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, MVT::i16, + Elt0Src, DAG.getIntPtrConstant(Elt0 / 2)); + if ((Elt0 & 1) != 0) + InsElt0 = DAG.getNode(ISD::SRL, dl, MVT::i16, InsElt0, + DAG.getConstant(8, TLI.getShiftAmountTy())); + else if (Elt1 >= 0) + InsElt0 = DAG.getNode(ISD::AND, dl, MVT::i16, InsElt0, + DAG.getConstant(0x00FF, MVT::i16)); + InsElt = Elt1 >= 0 ? DAG.getNode(ISD::OR, dl, MVT::i16, InsElt, InsElt0) + : InsElt0; + } + NewV = DAG.getNode(ISD::INSERT_VECTOR_ELT, dl, MVT::v8i16, NewV, InsElt, + DAG.getIntPtrConstant(i)); + } + return DAG.getNode(ISD::BIT_CONVERT, dl, MVT::v16i8, NewV); +} + +/// RewriteAsNarrowerShuffle - Try rewriting v8i16 and v16i8 shuffles as 4 wide +/// ones, or rewriting v4i32 / v2f32 as 2 wide ones if possible. This can be +/// done when every pair / quad of shuffle mask elements point to elements in +/// the right sequence. e.g. +/// vector_shuffle <>, <>, < 3, 4, | 10, 11, | 0, 1, | 14, 15> +static +SDValue RewriteAsNarrowerShuffle(ShuffleVectorSDNode *SVOp, + SelectionDAG &DAG, + TargetLowering &TLI, DebugLoc dl) { + EVT VT = SVOp->getValueType(0); + SDValue V1 = SVOp->getOperand(0); + SDValue V2 = SVOp->getOperand(1); + unsigned NumElems = VT.getVectorNumElements(); + unsigned NewWidth = (NumElems == 4) ? 2 : 4; + EVT MaskVT = MVT::getIntVectorWithNumElements(NewWidth); + EVT MaskEltVT = MaskVT.getVectorElementType(); + EVT NewVT = MaskVT; + switch (VT.getSimpleVT().SimpleTy) { + default: assert(false && "Unexpected!"); + case MVT::v4f32: NewVT = MVT::v2f64; break; + case MVT::v4i32: NewVT = MVT::v2i64; break; + case MVT::v8i16: NewVT = MVT::v4i32; break; + case MVT::v16i8: NewVT = MVT::v4i32; break; + } + + if (NewWidth == 2) { + if (VT.isInteger()) + NewVT = MVT::v2i64; + else + NewVT = MVT::v2f64; + } + int Scale = NumElems / NewWidth; + SmallVector MaskVec; + for (unsigned i = 0; i < NumElems; i += Scale) { + int StartIdx = -1; + for (int j = 0; j < Scale; ++j) { + int EltIdx = SVOp->getMaskElt(i+j); + if (EltIdx < 0) + continue; + if (StartIdx == -1) + StartIdx = EltIdx - (EltIdx % Scale); + if (EltIdx != StartIdx + j) + return SDValue(); + } + if (StartIdx == -1) + MaskVec.push_back(-1); + else + MaskVec.push_back(StartIdx / Scale); + } + + V1 = DAG.getNode(ISD::BIT_CONVERT, dl, NewVT, V1); + V2 = DAG.getNode(ISD::BIT_CONVERT, dl, NewVT, V2); + return DAG.getVectorShuffle(NewVT, dl, V1, V2, &MaskVec[0]); +} + +/// getVZextMovL - Return a zero-extending vector move low node. +/// +static SDValue getVZextMovL(EVT VT, EVT OpVT, + SDValue SrcOp, SelectionDAG &DAG, + const X86Subtarget *Subtarget, DebugLoc dl) { + if (VT == MVT::v2f64 || VT == MVT::v4f32) { + LoadSDNode *LD = NULL; + if (!isScalarLoadToVector(SrcOp.getNode(), &LD)) + LD = dyn_cast(SrcOp); + if (!LD) { + // movssrr and movsdrr do not clear top bits. Try to use movd, movq + // instead. + MVT ExtVT = (OpVT == MVT::v2f64) ? MVT::i64 : MVT::i32; + if ((ExtVT.SimpleTy != MVT::i64 || Subtarget->is64Bit()) && + SrcOp.getOpcode() == ISD::SCALAR_TO_VECTOR && + SrcOp.getOperand(0).getOpcode() == ISD::BIT_CONVERT && + SrcOp.getOperand(0).getOperand(0).getValueType() == ExtVT) { + // PR2108 + OpVT = (OpVT == MVT::v2f64) ? MVT::v2i64 : MVT::v4i32; + return DAG.getNode(ISD::BIT_CONVERT, dl, VT, + DAG.getNode(X86ISD::VZEXT_MOVL, dl, OpVT, + DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, + OpVT, + SrcOp.getOperand(0) + .getOperand(0)))); + } + } + } + + return DAG.getNode(ISD::BIT_CONVERT, dl, VT, + DAG.getNode(X86ISD::VZEXT_MOVL, dl, OpVT, + DAG.getNode(ISD::BIT_CONVERT, dl, + OpVT, SrcOp))); +} + +/// LowerVECTOR_SHUFFLE_4wide - Handle all 4 wide cases with a number of +/// shuffles. +static SDValue +LowerVECTOR_SHUFFLE_4wide(ShuffleVectorSDNode *SVOp, SelectionDAG &DAG) { + SDValue V1 = SVOp->getOperand(0); + SDValue V2 = SVOp->getOperand(1); + DebugLoc dl = SVOp->getDebugLoc(); + EVT VT = SVOp->getValueType(0); + + SmallVector, 8> Locs; + Locs.resize(4); + SmallVector Mask1(4U, -1); + SmallVector PermMask; + SVOp->getMask(PermMask); + + unsigned NumHi = 0; + unsigned NumLo = 0; + for (unsigned i = 0; i != 4; ++i) { + int Idx = PermMask[i]; + if (Idx < 0) { + Locs[i] = std::make_pair(-1, -1); + } else { + assert(Idx < 8 && "Invalid VECTOR_SHUFFLE index!"); + if (Idx < 4) { + Locs[i] = std::make_pair(0, NumLo); + Mask1[NumLo] = Idx; + NumLo++; + } else { + Locs[i] = std::make_pair(1, NumHi); + if (2+NumHi < 4) + Mask1[2+NumHi] = Idx; + NumHi++; + } + } + } + + if (NumLo <= 2 && NumHi <= 2) { + // If no more than two elements come from either vector. This can be + // implemented with two shuffles. First shuffle gather the elements. + // The second shuffle, which takes the first shuffle as both of its + // vector operands, put the elements into the right order. + V1 = DAG.getVectorShuffle(VT, dl, V1, V2, &Mask1[0]); + + SmallVector Mask2(4U, -1); + + for (unsigned i = 0; i != 4; ++i) { + if (Locs[i].first == -1) + continue; + else { + unsigned Idx = (i < 2) ? 0 : 4; + Idx += Locs[i].first * 2 + Locs[i].second; + Mask2[i] = Idx; + } + } + + return DAG.getVectorShuffle(VT, dl, V1, V1, &Mask2[0]); + } else if (NumLo == 3 || NumHi == 3) { + // Otherwise, we must have three elements from one vector, call it X, and + // one element from the other, call it Y. First, use a shufps to build an + // intermediate vector with the one element from Y and the element from X + // that will be in the same half in the final destination (the indexes don't + // matter). Then, use a shufps to build the final vector, taking the half + // containing the element from Y from the intermediate, and the other half + // from X. + if (NumHi == 3) { + // Normalize it so the 3 elements come from V1. + CommuteVectorShuffleMask(PermMask, VT); + std::swap(V1, V2); + } + + // Find the element from V2. + unsigned HiIndex; + for (HiIndex = 0; HiIndex < 3; ++HiIndex) { + int Val = PermMask[HiIndex]; + if (Val < 0) + continue; + if (Val >= 4) + break; + } + + Mask1[0] = PermMask[HiIndex]; + Mask1[1] = -1; + Mask1[2] = PermMask[HiIndex^1]; + Mask1[3] = -1; + V2 = DAG.getVectorShuffle(VT, dl, V1, V2, &Mask1[0]); + + if (HiIndex >= 2) { + Mask1[0] = PermMask[0]; + Mask1[1] = PermMask[1]; + Mask1[2] = HiIndex & 1 ? 6 : 4; + Mask1[3] = HiIndex & 1 ? 4 : 6; + return DAG.getVectorShuffle(VT, dl, V1, V2, &Mask1[0]); + } else { + Mask1[0] = HiIndex & 1 ? 2 : 0; + Mask1[1] = HiIndex & 1 ? 0 : 2; + Mask1[2] = PermMask[2]; + Mask1[3] = PermMask[3]; + if (Mask1[2] >= 0) + Mask1[2] += 4; + if (Mask1[3] >= 0) + Mask1[3] += 4; + return DAG.getVectorShuffle(VT, dl, V2, V1, &Mask1[0]); + } + } + + // Break it into (shuffle shuffle_hi, shuffle_lo). + Locs.clear(); + SmallVector LoMask(4U, -1); + SmallVector HiMask(4U, -1); + + SmallVector *MaskPtr = &LoMask; + unsigned MaskIdx = 0; + unsigned LoIdx = 0; + unsigned HiIdx = 2; + for (unsigned i = 0; i != 4; ++i) { + if (i == 2) { + MaskPtr = &HiMask; + MaskIdx = 1; + LoIdx = 0; + HiIdx = 2; + } + int Idx = PermMask[i]; + if (Idx < 0) { + Locs[i] = std::make_pair(-1, -1); + } else if (Idx < 4) { + Locs[i] = std::make_pair(MaskIdx, LoIdx); + (*MaskPtr)[LoIdx] = Idx; + LoIdx++; + } else { + Locs[i] = std::make_pair(MaskIdx, HiIdx); + (*MaskPtr)[HiIdx] = Idx; + HiIdx++; + } + } + + SDValue LoShuffle = DAG.getVectorShuffle(VT, dl, V1, V2, &LoMask[0]); + SDValue HiShuffle = DAG.getVectorShuffle(VT, dl, V1, V2, &HiMask[0]); + SmallVector MaskOps; + for (unsigned i = 0; i != 4; ++i) { + if (Locs[i].first == -1) { + MaskOps.push_back(-1); + } else { + unsigned Idx = Locs[i].first * 4 + Locs[i].second; + MaskOps.push_back(Idx); + } + } + return DAG.getVectorShuffle(VT, dl, LoShuffle, HiShuffle, &MaskOps[0]); +} + +SDValue +X86TargetLowering::LowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG) { + ShuffleVectorSDNode *SVOp = cast(Op); + SDValue V1 = Op.getOperand(0); + SDValue V2 = Op.getOperand(1); + EVT VT = Op.getValueType(); + DebugLoc dl = Op.getDebugLoc(); + unsigned NumElems = VT.getVectorNumElements(); + bool isMMX = VT.getSizeInBits() == 64; + bool V1IsUndef = V1.getOpcode() == ISD::UNDEF; + bool V2IsUndef = V2.getOpcode() == ISD::UNDEF; + bool V1IsSplat = false; + bool V2IsSplat = false; + + if (isZeroShuffle(SVOp)) + return getZeroVector(VT, Subtarget->hasSSE2(), DAG, dl); + + // Promote splats to v4f32. + if (SVOp->isSplat()) { + if (isMMX || NumElems < 4) + return Op; + return PromoteSplat(SVOp, DAG, Subtarget->hasSSE2()); + } + + // If the shuffle can be profitably rewritten as a narrower shuffle, then + // do it! + if (VT == MVT::v8i16 || VT == MVT::v16i8) { + SDValue NewOp = RewriteAsNarrowerShuffle(SVOp, DAG, *this, dl); + if (NewOp.getNode()) + return DAG.getNode(ISD::BIT_CONVERT, dl, VT, + LowerVECTOR_SHUFFLE(NewOp, DAG)); + } else if ((VT == MVT::v4i32 || (VT == MVT::v4f32 && Subtarget->hasSSE2()))) { + // FIXME: Figure out a cleaner way to do this. + // Try to make use of movq to zero out the top part. + if (ISD::isBuildVectorAllZeros(V2.getNode())) { + SDValue NewOp = RewriteAsNarrowerShuffle(SVOp, DAG, *this, dl); + if (NewOp.getNode()) { + if (isCommutedMOVL(cast(NewOp), true, false)) + return getVZextMovL(VT, NewOp.getValueType(), NewOp.getOperand(0), + DAG, Subtarget, dl); + } + } else if (ISD::isBuildVectorAllZeros(V1.getNode())) { + SDValue NewOp = RewriteAsNarrowerShuffle(SVOp, DAG, *this, dl); + if (NewOp.getNode() && X86::isMOVLMask(cast(NewOp))) + return getVZextMovL(VT, NewOp.getValueType(), NewOp.getOperand(1), + DAG, Subtarget, dl); + } + } + + if (X86::isPSHUFDMask(SVOp)) + return Op; + + // Check if this can be converted into a logical shift. + bool isLeft = false; + unsigned ShAmt = 0; + SDValue ShVal; + bool isShift = getSubtarget()->hasSSE2() && + isVectorShift(SVOp, DAG, isLeft, ShVal, ShAmt); + if (isShift && ShVal.hasOneUse()) { + // If the shifted value has multiple uses, it may be cheaper to use + // v_set0 + movlhps or movhlps, etc. + EVT EltVT = VT.getVectorElementType(); + ShAmt *= EltVT.getSizeInBits(); + return getVShift(isLeft, VT, ShVal, ShAmt, DAG, *this, dl); + } + + if (X86::isMOVLMask(SVOp)) { + if (V1IsUndef) + return V2; + if (ISD::isBuildVectorAllZeros(V1.getNode())) + return getVZextMovL(VT, VT, V2, DAG, Subtarget, dl); + if (!isMMX) + return Op; + } + + // FIXME: fold these into legal mask. + if (!isMMX && (X86::isMOVSHDUPMask(SVOp) || + X86::isMOVSLDUPMask(SVOp) || + X86::isMOVHLPSMask(SVOp) || + X86::isMOVLHPSMask(SVOp) || + X86::isMOVLPMask(SVOp))) + return Op; + + if (ShouldXformToMOVHLPS(SVOp) || + ShouldXformToMOVLP(V1.getNode(), V2.getNode(), SVOp)) + return CommuteVectorShuffle(SVOp, DAG); + + if (isShift) { + // No better options. Use a vshl / vsrl. + EVT EltVT = VT.getVectorElementType(); + ShAmt *= EltVT.getSizeInBits(); + return getVShift(isLeft, VT, ShVal, ShAmt, DAG, *this, dl); + } + + bool Commuted = false; + // FIXME: This should also accept a bitcast of a splat? Be careful, not + // 1,1,1,1 -> v8i16 though. + V1IsSplat = isSplatVector(V1.getNode()); + V2IsSplat = isSplatVector(V2.getNode()); + + // Canonicalize the splat or undef, if present, to be on the RHS. + if ((V1IsSplat || V1IsUndef) && !(V2IsSplat || V2IsUndef)) { + Op = CommuteVectorShuffle(SVOp, DAG); + SVOp = cast(Op); + V1 = SVOp->getOperand(0); + V2 = SVOp->getOperand(1); + std::swap(V1IsSplat, V2IsSplat); + std::swap(V1IsUndef, V2IsUndef); + Commuted = true; + } + + if (isCommutedMOVL(SVOp, V2IsSplat, V2IsUndef)) { + // Shuffling low element of v1 into undef, just return v1. + if (V2IsUndef) + return V1; + // If V2 is a splat, the mask may be malformed such as <4,3,3,3>, which + // the instruction selector will not match, so get a canonical MOVL with + // swapped operands to undo the commute. + return getMOVL(DAG, dl, VT, V2, V1); + } + + if (X86::isUNPCKL_v_undef_Mask(SVOp) || + X86::isUNPCKH_v_undef_Mask(SVOp) || + X86::isUNPCKLMask(SVOp) || + X86::isUNPCKHMask(SVOp)) + return Op; + + if (V2IsSplat) { + // Normalize mask so all entries that point to V2 points to its first + // element then try to match unpck{h|l} again. If match, return a + // new vector_shuffle with the corrected mask. + SDValue NewMask = NormalizeMask(SVOp, DAG); + ShuffleVectorSDNode *NSVOp = cast(NewMask); + if (NSVOp != SVOp) { + if (X86::isUNPCKLMask(NSVOp, true)) { + return NewMask; + } else if (X86::isUNPCKHMask(NSVOp, true)) { + return NewMask; + } + } + } + + if (Commuted) { + // Commute is back and try unpck* again. + // FIXME: this seems wrong. + SDValue NewOp = CommuteVectorShuffle(SVOp, DAG); + ShuffleVectorSDNode *NewSVOp = cast(NewOp); + if (X86::isUNPCKL_v_undef_Mask(NewSVOp) || + X86::isUNPCKH_v_undef_Mask(NewSVOp) || + X86::isUNPCKLMask(NewSVOp) || + X86::isUNPCKHMask(NewSVOp)) + return NewOp; + } + + // FIXME: for mmx, bitcast v2i32 to v4i16 for shuffle. + + // Normalize the node to match x86 shuffle ops if needed + if (!isMMX && V2.getOpcode() != ISD::UNDEF && isCommutedSHUFP(SVOp)) + return CommuteVectorShuffle(SVOp, DAG); + + // Check for legal shuffle and return? + SmallVector PermMask; + SVOp->getMask(PermMask); + if (isShuffleMaskLegal(PermMask, VT)) + return Op; + + // Handle v8i16 specifically since SSE can do byte extraction and insertion. + if (VT == MVT::v8i16) { + SDValue NewOp = LowerVECTOR_SHUFFLEv8i16(SVOp, DAG, *this); + if (NewOp.getNode()) + return NewOp; + } + + if (VT == MVT::v16i8) { + SDValue NewOp = LowerVECTOR_SHUFFLEv16i8(SVOp, DAG, *this); + if (NewOp.getNode()) + return NewOp; + } + + // Handle all 4 wide cases with a number of shuffles except for MMX. + if (NumElems == 4 && !isMMX) + return LowerVECTOR_SHUFFLE_4wide(SVOp, DAG); + + return SDValue(); +} + +SDValue +X86TargetLowering::LowerEXTRACT_VECTOR_ELT_SSE4(SDValue Op, + SelectionDAG &DAG) { + EVT VT = Op.getValueType(); + DebugLoc dl = Op.getDebugLoc(); + if (VT.getSizeInBits() == 8) { + SDValue Extract = DAG.getNode(X86ISD::PEXTRB, dl, MVT::i32, + Op.getOperand(0), Op.getOperand(1)); + SDValue Assert = DAG.getNode(ISD::AssertZext, dl, MVT::i32, Extract, + DAG.getValueType(VT)); + return DAG.getNode(ISD::TRUNCATE, dl, VT, Assert); + } else if (VT.getSizeInBits() == 16) { + unsigned Idx = cast(Op.getOperand(1))->getZExtValue(); + // If Idx is 0, it's cheaper to do a move instead of a pextrw. + if (Idx == 0) + return DAG.getNode(ISD::TRUNCATE, dl, MVT::i16, + DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, MVT::i32, + DAG.getNode(ISD::BIT_CONVERT, dl, + MVT::v4i32, + Op.getOperand(0)), + Op.getOperand(1))); + SDValue Extract = DAG.getNode(X86ISD::PEXTRW, dl, MVT::i32, + Op.getOperand(0), Op.getOperand(1)); + SDValue Assert = DAG.getNode(ISD::AssertZext, dl, MVT::i32, Extract, + DAG.getValueType(VT)); + return DAG.getNode(ISD::TRUNCATE, dl, VT, Assert); + } else if (VT == MVT::f32) { + // EXTRACTPS outputs to a GPR32 register which will require a movd to copy + // the result back to FR32 register. It's only worth matching if the + // result has a single use which is a store or a bitcast to i32. And in + // the case of a store, it's not worth it if the index is a constant 0, + // because a MOVSSmr can be used instead, which is smaller and faster. + if (!Op.hasOneUse()) + return SDValue(); + SDNode *User = *Op.getNode()->use_begin(); + if ((User->getOpcode() != ISD::STORE || + (isa(Op.getOperand(1)) && + cast(Op.getOperand(1))->isNullValue())) && + (User->getOpcode() != ISD::BIT_CONVERT || + User->getValueType(0) != MVT::i32)) + return SDValue(); + SDValue Extract = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, MVT::i32, + DAG.getNode(ISD::BIT_CONVERT, dl, MVT::v4i32, + Op.getOperand(0)), + Op.getOperand(1)); + return DAG.getNode(ISD::BIT_CONVERT, dl, MVT::f32, Extract); + } else if (VT == MVT::i32) { + // ExtractPS works with constant index. + if (isa(Op.getOperand(1))) + return Op; + } + return SDValue(); +} + + +SDValue +X86TargetLowering::LowerEXTRACT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) { + if (!isa(Op.getOperand(1))) + return SDValue(); + + if (Subtarget->hasSSE41()) { + SDValue Res = LowerEXTRACT_VECTOR_ELT_SSE4(Op, DAG); + if (Res.getNode()) + return Res; + } + + EVT VT = Op.getValueType(); + DebugLoc dl = Op.getDebugLoc(); + // TODO: handle v16i8. + if (VT.getSizeInBits() == 16) { + SDValue Vec = Op.getOperand(0); + unsigned Idx = cast(Op.getOperand(1))->getZExtValue(); + if (Idx == 0) + return DAG.getNode(ISD::TRUNCATE, dl, MVT::i16, + DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, MVT::i32, + DAG.getNode(ISD::BIT_CONVERT, dl, + MVT::v4i32, Vec), + Op.getOperand(1))); + // Transform it so it match pextrw which produces a 32-bit result. + EVT EltVT = (MVT::SimpleValueType)(VT.getSimpleVT().SimpleTy+1); + SDValue Extract = DAG.getNode(X86ISD::PEXTRW, dl, EltVT, + Op.getOperand(0), Op.getOperand(1)); + SDValue Assert = DAG.getNode(ISD::AssertZext, dl, EltVT, Extract, + DAG.getValueType(VT)); + return DAG.getNode(ISD::TRUNCATE, dl, VT, Assert); + } else if (VT.getSizeInBits() == 32) { + unsigned Idx = cast(Op.getOperand(1))->getZExtValue(); + if (Idx == 0) + return Op; + + // SHUFPS the element to the lowest double word, then movss. + int Mask[4] = { Idx, -1, -1, -1 }; + EVT VVT = Op.getOperand(0).getValueType(); + SDValue Vec = DAG.getVectorShuffle(VVT, dl, Op.getOperand(0), + DAG.getUNDEF(VVT), Mask); + return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, VT, Vec, + DAG.getIntPtrConstant(0)); + } else if (VT.getSizeInBits() == 64) { + // FIXME: .td only matches this for <2 x f64>, not <2 x i64> on 32b + // FIXME: seems like this should be unnecessary if mov{h,l}pd were taught + // to match extract_elt for f64. + unsigned Idx = cast(Op.getOperand(1))->getZExtValue(); + if (Idx == 0) + return Op; + + // UNPCKHPD the element to the lowest double word, then movsd. + // Note if the lower 64 bits of the result of the UNPCKHPD is then stored + // to a f64mem, the whole operation is folded into a single MOVHPDmr. + int Mask[2] = { 1, -1 }; + EVT VVT = Op.getOperand(0).getValueType(); + SDValue Vec = DAG.getVectorShuffle(VVT, dl, Op.getOperand(0), + DAG.getUNDEF(VVT), Mask); + return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, VT, Vec, + DAG.getIntPtrConstant(0)); + } + + return SDValue(); +} + +SDValue +X86TargetLowering::LowerINSERT_VECTOR_ELT_SSE4(SDValue Op, SelectionDAG &DAG){ + EVT VT = Op.getValueType(); + EVT EltVT = VT.getVectorElementType(); + DebugLoc dl = Op.getDebugLoc(); + + SDValue N0 = Op.getOperand(0); + SDValue N1 = Op.getOperand(1); + SDValue N2 = Op.getOperand(2); + + if ((EltVT.getSizeInBits() == 8 || EltVT.getSizeInBits() == 16) && + isa(N2)) { + unsigned Opc = (EltVT.getSizeInBits() == 8) ? X86ISD::PINSRB + : X86ISD::PINSRW; + // Transform it so it match pinsr{b,w} which expects a GR32 as its second + // argument. + if (N1.getValueType() != MVT::i32) + N1 = DAG.getNode(ISD::ANY_EXTEND, dl, MVT::i32, N1); + if (N2.getValueType() != MVT::i32) + N2 = DAG.getIntPtrConstant(cast(N2)->getZExtValue()); + return DAG.getNode(Opc, dl, VT, N0, N1, N2); + } else if (EltVT == MVT::f32 && isa(N2)) { + // Bits [7:6] of the constant are the source select. This will always be + // zero here. The DAG Combiner may combine an extract_elt index into these + // bits. For example (insert (extract, 3), 2) could be matched by putting + // the '3' into bits [7:6] of X86ISD::INSERTPS. + // Bits [5:4] of the constant are the destination select. This is the + // value of the incoming immediate. + // Bits [3:0] of the constant are the zero mask. The DAG Combiner may + // combine either bitwise AND or insert of float 0.0 to set these bits. + N2 = DAG.getIntPtrConstant(cast(N2)->getZExtValue() << 4); + // Create this as a scalar to vector.. + N1 = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, MVT::v4f32, N1); + return DAG.getNode(X86ISD::INSERTPS, dl, VT, N0, N1, N2); + } else if (EltVT == MVT::i32 && isa(N2)) { + // PINSR* works with constant index. + return Op; + } + return SDValue(); +} + +SDValue +X86TargetLowering::LowerINSERT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) { + EVT VT = Op.getValueType(); + EVT EltVT = VT.getVectorElementType(); + + if (Subtarget->hasSSE41()) + return LowerINSERT_VECTOR_ELT_SSE4(Op, DAG); + + if (EltVT == MVT::i8) + return SDValue(); + + DebugLoc dl = Op.getDebugLoc(); + SDValue N0 = Op.getOperand(0); + SDValue N1 = Op.getOperand(1); + SDValue N2 = Op.getOperand(2); + + if (EltVT.getSizeInBits() == 16 && isa(N2)) { + // Transform it so it match pinsrw which expects a 16-bit value in a GR32 + // as its second argument. + if (N1.getValueType() != MVT::i32) + N1 = DAG.getNode(ISD::ANY_EXTEND, dl, MVT::i32, N1); + if (N2.getValueType() != MVT::i32) + N2 = DAG.getIntPtrConstant(cast(N2)->getZExtValue()); + return DAG.getNode(X86ISD::PINSRW, dl, VT, N0, N1, N2); + } + return SDValue(); +} + +SDValue +X86TargetLowering::LowerSCALAR_TO_VECTOR(SDValue Op, SelectionDAG &DAG) { + DebugLoc dl = Op.getDebugLoc(); + if (Op.getValueType() == MVT::v2f32) + return DAG.getNode(ISD::BIT_CONVERT, dl, MVT::v2f32, + DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, MVT::v2i32, + DAG.getNode(ISD::BIT_CONVERT, dl, MVT::i32, + Op.getOperand(0)))); + + if (Op.getValueType() == MVT::v1i64 && Op.getOperand(0).getValueType() == MVT::i64) + return DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, MVT::v1i64, Op.getOperand(0)); + + SDValue AnyExt = DAG.getNode(ISD::ANY_EXTEND, dl, MVT::i32, Op.getOperand(0)); + EVT VT = MVT::v2i32; + switch (Op.getValueType().getSimpleVT().SimpleTy) { + default: break; + case MVT::v16i8: + case MVT::v8i16: + VT = MVT::v4i32; + break; + } + return DAG.getNode(ISD::BIT_CONVERT, dl, Op.getValueType(), + DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, VT, AnyExt)); +} + +// ConstantPool, JumpTable, GlobalAddress, and ExternalSymbol are lowered as +// their target countpart wrapped in the X86ISD::Wrapper node. Suppose N is +// one of the above mentioned nodes. It has to be wrapped because otherwise +// Select(N) returns N. So the raw TargetGlobalAddress nodes, etc. can only +// be used to form addressing mode. These wrapped nodes will be selected +// into MOV32ri. +SDValue +X86TargetLowering::LowerConstantPool(SDValue Op, SelectionDAG &DAG) { + ConstantPoolSDNode *CP = cast(Op); + + // In PIC mode (unless we're in RIPRel PIC mode) we add an offset to the + // global base reg. + unsigned char OpFlag = 0; + unsigned WrapperKind = X86ISD::Wrapper; + CodeModel::Model M = getTargetMachine().getCodeModel(); + + if (Subtarget->isPICStyleRIPRel() && + (M == CodeModel::Small || M == CodeModel::Kernel)) + WrapperKind = X86ISD::WrapperRIP; + else if (Subtarget->isPICStyleGOT()) + OpFlag = X86II::MO_GOTOFF; + else if (Subtarget->isPICStyleStubPIC()) + OpFlag = X86II::MO_PIC_BASE_OFFSET; + + SDValue Result = DAG.getTargetConstantPool(CP->getConstVal(), getPointerTy(), + CP->getAlignment(), + CP->getOffset(), OpFlag); + DebugLoc DL = CP->getDebugLoc(); + Result = DAG.getNode(WrapperKind, DL, getPointerTy(), Result); + // With PIC, the address is actually $g + Offset. + if (OpFlag) { + Result = DAG.getNode(ISD::ADD, DL, getPointerTy(), + DAG.getNode(X86ISD::GlobalBaseReg, + DebugLoc::getUnknownLoc(), getPointerTy()), + Result); + } + + return Result; +} + +SDValue X86TargetLowering::LowerJumpTable(SDValue Op, SelectionDAG &DAG) { + JumpTableSDNode *JT = cast(Op); + + // In PIC mode (unless we're in RIPRel PIC mode) we add an offset to the + // global base reg. + unsigned char OpFlag = 0; + unsigned WrapperKind = X86ISD::Wrapper; + CodeModel::Model M = getTargetMachine().getCodeModel(); + + if (Subtarget->isPICStyleRIPRel() && + (M == CodeModel::Small || M == CodeModel::Kernel)) + WrapperKind = X86ISD::WrapperRIP; + else if (Subtarget->isPICStyleGOT()) + OpFlag = X86II::MO_GOTOFF; + else if (Subtarget->isPICStyleStubPIC()) + OpFlag = X86II::MO_PIC_BASE_OFFSET; + + SDValue Result = DAG.getTargetJumpTable(JT->getIndex(), getPointerTy(), + OpFlag); + DebugLoc DL = JT->getDebugLoc(); + Result = DAG.getNode(WrapperKind, DL, getPointerTy(), Result); + + // With PIC, the address is actually $g + Offset. + if (OpFlag) { + Result = DAG.getNode(ISD::ADD, DL, getPointerTy(), + DAG.getNode(X86ISD::GlobalBaseReg, + DebugLoc::getUnknownLoc(), getPointerTy()), + Result); + } + + return Result; +} + +SDValue +X86TargetLowering::LowerExternalSymbol(SDValue Op, SelectionDAG &DAG) { + const char *Sym = cast(Op)->getSymbol(); + + // In PIC mode (unless we're in RIPRel PIC mode) we add an offset to the + // global base reg. + unsigned char OpFlag = 0; + unsigned WrapperKind = X86ISD::Wrapper; + CodeModel::Model M = getTargetMachine().getCodeModel(); + + if (Subtarget->isPICStyleRIPRel() && + (M == CodeModel::Small || M == CodeModel::Kernel)) + WrapperKind = X86ISD::WrapperRIP; + else if (Subtarget->isPICStyleGOT()) + OpFlag = X86II::MO_GOTOFF; + else if (Subtarget->isPICStyleStubPIC()) + OpFlag = X86II::MO_PIC_BASE_OFFSET; + + SDValue Result = DAG.getTargetExternalSymbol(Sym, getPointerTy(), OpFlag); + + DebugLoc DL = Op.getDebugLoc(); + Result = DAG.getNode(WrapperKind, DL, getPointerTy(), Result); + + + // With PIC, the address is actually $g + Offset. + if (getTargetMachine().getRelocationModel() == Reloc::PIC_ && + !Subtarget->is64Bit()) { + Result = DAG.getNode(ISD::ADD, DL, getPointerTy(), + DAG.getNode(X86ISD::GlobalBaseReg, + DebugLoc::getUnknownLoc(), + getPointerTy()), + Result); + } + + return Result; +} + +SDValue +X86TargetLowering::LowerBlockAddress(SDValue Op, SelectionDAG &DAG) { + // Create the TargetBlockAddressAddress node. + unsigned char OpFlags = + Subtarget->ClassifyBlockAddressReference(); + CodeModel::Model M = getTargetMachine().getCodeModel(); + BlockAddress *BA = cast(Op)->getBlockAddress(); + DebugLoc dl = Op.getDebugLoc(); + SDValue Result = DAG.getBlockAddress(BA, getPointerTy(), + /*isTarget=*/true, OpFlags); + + if (Subtarget->isPICStyleRIPRel() && + (M == CodeModel::Small || M == CodeModel::Kernel)) + Result = DAG.getNode(X86ISD::WrapperRIP, dl, getPointerTy(), Result); + else + Result = DAG.getNode(X86ISD::Wrapper, dl, getPointerTy(), Result); + + // With PIC, the address is actually $g + Offset. + if (isGlobalRelativeToPICBase(OpFlags)) { + Result = DAG.getNode(ISD::ADD, dl, getPointerTy(), + DAG.getNode(X86ISD::GlobalBaseReg, dl, getPointerTy()), + Result); + } + + return Result; +} + +SDValue +X86TargetLowering::LowerGlobalAddress(const GlobalValue *GV, DebugLoc dl, + int64_t Offset, + SelectionDAG &DAG) const { + // Create the TargetGlobalAddress node, folding in the constant + // offset if it is legal. + unsigned char OpFlags = + Subtarget->ClassifyGlobalReference(GV, getTargetMachine()); + CodeModel::Model M = getTargetMachine().getCodeModel(); + SDValue Result; + if (OpFlags == X86II::MO_NO_FLAG && + X86::isOffsetSuitableForCodeModel(Offset, M)) { + // A direct static reference to a global. + Result = DAG.getTargetGlobalAddress(GV, getPointerTy(), Offset); + Offset = 0; + } else { + Result = DAG.getTargetGlobalAddress(GV, getPointerTy(), 0, OpFlags); + } + + if (Subtarget->isPICStyleRIPRel() && + (M == CodeModel::Small || M == CodeModel::Kernel)) + Result = DAG.getNode(X86ISD::WrapperRIP, dl, getPointerTy(), Result); + else + Result = DAG.getNode(X86ISD::Wrapper, dl, getPointerTy(), Result); + + // With PIC, the address is actually $g + Offset. + if (isGlobalRelativeToPICBase(OpFlags)) { + Result = DAG.getNode(ISD::ADD, dl, getPointerTy(), + DAG.getNode(X86ISD::GlobalBaseReg, dl, getPointerTy()), + Result); + } + + // For globals that require a load from a stub to get the address, emit the + // load. + if (isGlobalStubReference(OpFlags)) + Result = DAG.getLoad(getPointerTy(), dl, DAG.getEntryNode(), Result, + PseudoSourceValue::getGOT(), 0); + + // If there was a non-zero offset that we didn't fold, create an explicit + // addition for it. + if (Offset != 0) + Result = DAG.getNode(ISD::ADD, dl, getPointerTy(), Result, + DAG.getConstant(Offset, getPointerTy())); + + return Result; +} + +SDValue +X86TargetLowering::LowerGlobalAddress(SDValue Op, SelectionDAG &DAG) { + const GlobalValue *GV = cast(Op)->getGlobal(); + int64_t Offset = cast(Op)->getOffset(); + return LowerGlobalAddress(GV, Op.getDebugLoc(), Offset, DAG); +} + +static SDValue +GetTLSADDR(SelectionDAG &DAG, SDValue Chain, GlobalAddressSDNode *GA, + SDValue *InFlag, const EVT PtrVT, unsigned ReturnReg, + unsigned char OperandFlags) { + SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Flag); + DebugLoc dl = GA->getDebugLoc(); + SDValue TGA = DAG.getTargetGlobalAddress(GA->getGlobal(), + GA->getValueType(0), + GA->getOffset(), + OperandFlags); + if (InFlag) { + SDValue Ops[] = { Chain, TGA, *InFlag }; + Chain = DAG.getNode(X86ISD::TLSADDR, dl, NodeTys, Ops, 3); + } else { + SDValue Ops[] = { Chain, TGA }; + Chain = DAG.getNode(X86ISD::TLSADDR, dl, NodeTys, Ops, 2); + } + SDValue Flag = Chain.getValue(1); + return DAG.getCopyFromReg(Chain, dl, ReturnReg, PtrVT, Flag); +} + +// Lower ISD::GlobalTLSAddress using the "general dynamic" model, 32 bit +static SDValue +LowerToTLSGeneralDynamicModel32(GlobalAddressSDNode *GA, SelectionDAG &DAG, + const EVT PtrVT) { + SDValue InFlag; + DebugLoc dl = GA->getDebugLoc(); // ? function entry point might be better + SDValue Chain = DAG.getCopyToReg(DAG.getEntryNode(), dl, X86::EBX, + DAG.getNode(X86ISD::GlobalBaseReg, + DebugLoc::getUnknownLoc(), + PtrVT), InFlag); + InFlag = Chain.getValue(1); + + return GetTLSADDR(DAG, Chain, GA, &InFlag, PtrVT, X86::EAX, X86II::MO_TLSGD); +} + +// Lower ISD::GlobalTLSAddress using the "general dynamic" model, 64 bit +static SDValue +LowerToTLSGeneralDynamicModel64(GlobalAddressSDNode *GA, SelectionDAG &DAG, + const EVT PtrVT) { + return GetTLSADDR(DAG, DAG.getEntryNode(), GA, NULL, PtrVT, + X86::RAX, X86II::MO_TLSGD); +} + +// Lower ISD::GlobalTLSAddress using the "initial exec" (for no-pic) or +// "local exec" model. +static SDValue LowerToTLSExecModel(GlobalAddressSDNode *GA, SelectionDAG &DAG, + const EVT PtrVT, TLSModel::Model model, + bool is64Bit) { + DebugLoc dl = GA->getDebugLoc(); + // Get the Thread Pointer + SDValue Base = DAG.getNode(X86ISD::SegmentBaseAddress, + DebugLoc::getUnknownLoc(), PtrVT, + DAG.getRegister(is64Bit? X86::FS : X86::GS, + MVT::i32)); + + SDValue ThreadPointer = DAG.getLoad(PtrVT, dl, DAG.getEntryNode(), Base, + NULL, 0); + + unsigned char OperandFlags = 0; + // Most TLS accesses are not RIP relative, even on x86-64. One exception is + // initialexec. + unsigned WrapperKind = X86ISD::Wrapper; + if (model == TLSModel::LocalExec) { + OperandFlags = is64Bit ? X86II::MO_TPOFF : X86II::MO_NTPOFF; + } else if (is64Bit) { + assert(model == TLSModel::InitialExec); + OperandFlags = X86II::MO_GOTTPOFF; + WrapperKind = X86ISD::WrapperRIP; + } else { + assert(model == TLSModel::InitialExec); + OperandFlags = X86II::MO_INDNTPOFF; + } + + // emit "addl x@ntpoff,%eax" (local exec) or "addl x@indntpoff,%eax" (initial + // exec) + SDValue TGA = DAG.getTargetGlobalAddress(GA->getGlobal(), GA->getValueType(0), + GA->getOffset(), OperandFlags); + SDValue Offset = DAG.getNode(WrapperKind, dl, PtrVT, TGA); + + if (model == TLSModel::InitialExec) + Offset = DAG.getLoad(PtrVT, dl, DAG.getEntryNode(), Offset, + PseudoSourceValue::getGOT(), 0); + + // The address of the thread local variable is the add of the thread + // pointer with the offset of the variable. + return DAG.getNode(ISD::ADD, dl, PtrVT, ThreadPointer, Offset); +} + +SDValue +X86TargetLowering::LowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) { + // TODO: implement the "local dynamic" model + // TODO: implement the "initial exec"model for pic executables + assert(Subtarget->isTargetELF() && + "TLS not implemented for non-ELF targets"); + GlobalAddressSDNode *GA = cast(Op); + const GlobalValue *GV = GA->getGlobal(); + + // If GV is an alias then use the aliasee for determining + // thread-localness. + if (const GlobalAlias *GA = dyn_cast(GV)) + GV = GA->resolveAliasedGlobal(false); + + TLSModel::Model model = getTLSModel(GV, + getTargetMachine().getRelocationModel()); + + switch (model) { + case TLSModel::GeneralDynamic: + case TLSModel::LocalDynamic: // not implemented + if (Subtarget->is64Bit()) + return LowerToTLSGeneralDynamicModel64(GA, DAG, getPointerTy()); + return LowerToTLSGeneralDynamicModel32(GA, DAG, getPointerTy()); + + case TLSModel::InitialExec: + case TLSModel::LocalExec: + return LowerToTLSExecModel(GA, DAG, getPointerTy(), model, + Subtarget->is64Bit()); + } + + llvm_unreachable("Unreachable"); + return SDValue(); +} + + +/// LowerShift - Lower SRA_PARTS and friends, which return two i32 values and +/// take a 2 x i32 value to shift plus a shift amount. +SDValue X86TargetLowering::LowerShift(SDValue Op, SelectionDAG &DAG) { + assert(Op.getNumOperands() == 3 && "Not a double-shift!"); + EVT VT = Op.getValueType(); + unsigned VTBits = VT.getSizeInBits(); + DebugLoc dl = Op.getDebugLoc(); + bool isSRA = Op.getOpcode() == ISD::SRA_PARTS; + SDValue ShOpLo = Op.getOperand(0); + SDValue ShOpHi = Op.getOperand(1); + SDValue ShAmt = Op.getOperand(2); + SDValue Tmp1 = isSRA ? DAG.getNode(ISD::SRA, dl, VT, ShOpHi, + DAG.getConstant(VTBits - 1, MVT::i8)) + : DAG.getConstant(0, VT); + + SDValue Tmp2, Tmp3; + if (Op.getOpcode() == ISD::SHL_PARTS) { + Tmp2 = DAG.getNode(X86ISD::SHLD, dl, VT, ShOpHi, ShOpLo, ShAmt); + Tmp3 = DAG.getNode(ISD::SHL, dl, VT, ShOpLo, ShAmt); + } else { + Tmp2 = DAG.getNode(X86ISD::SHRD, dl, VT, ShOpLo, ShOpHi, ShAmt); + Tmp3 = DAG.getNode(isSRA ? ISD::SRA : ISD::SRL, dl, VT, ShOpHi, ShAmt); + } + + SDValue AndNode = DAG.getNode(ISD::AND, dl, MVT::i8, ShAmt, + DAG.getConstant(VTBits, MVT::i8)); + SDValue Cond = DAG.getNode(X86ISD::CMP, dl, VT, + AndNode, DAG.getConstant(0, MVT::i8)); + + SDValue Hi, Lo; + SDValue CC = DAG.getConstant(X86::COND_NE, MVT::i8); + SDValue Ops0[4] = { Tmp2, Tmp3, CC, Cond }; + SDValue Ops1[4] = { Tmp3, Tmp1, CC, Cond }; + + if (Op.getOpcode() == ISD::SHL_PARTS) { + Hi = DAG.getNode(X86ISD::CMOV, dl, VT, Ops0, 4); + Lo = DAG.getNode(X86ISD::CMOV, dl, VT, Ops1, 4); + } else { + Lo = DAG.getNode(X86ISD::CMOV, dl, VT, Ops0, 4); + Hi = DAG.getNode(X86ISD::CMOV, dl, VT, Ops1, 4); + } + + SDValue Ops[2] = { Lo, Hi }; + return DAG.getMergeValues(Ops, 2, dl); +} + +SDValue X86TargetLowering::LowerSINT_TO_FP(SDValue Op, SelectionDAG &DAG) { + EVT SrcVT = Op.getOperand(0).getValueType(); + + if (SrcVT.isVector()) { + if (SrcVT == MVT::v2i32 && Op.getValueType() == MVT::v2f64) { + return Op; + } + return SDValue(); + } + + assert(SrcVT.getSimpleVT() <= MVT::i64 && SrcVT.getSimpleVT() >= MVT::i16 && + "Unknown SINT_TO_FP to lower!"); + + // These are really Legal; return the operand so the caller accepts it as + // Legal. + if (SrcVT == MVT::i32 && isScalarFPTypeInSSEReg(Op.getValueType())) + return Op; + if (SrcVT == MVT::i64 && isScalarFPTypeInSSEReg(Op.getValueType()) && + Subtarget->is64Bit()) { + return Op; + } + + DebugLoc dl = Op.getDebugLoc(); + unsigned Size = SrcVT.getSizeInBits()/8; + MachineFunction &MF = DAG.getMachineFunction(); + int SSFI = MF.getFrameInfo()->CreateStackObject(Size, Size, false); + SDValue StackSlot = DAG.getFrameIndex(SSFI, getPointerTy()); + SDValue Chain = DAG.getStore(DAG.getEntryNode(), dl, Op.getOperand(0), + StackSlot, + PseudoSourceValue::getFixedStack(SSFI), 0); + return BuildFILD(Op, SrcVT, Chain, StackSlot, DAG); +} + +SDValue X86TargetLowering::BuildFILD(SDValue Op, EVT SrcVT, SDValue Chain, + SDValue StackSlot, + SelectionDAG &DAG) { + // Build the FILD + DebugLoc dl = Op.getDebugLoc(); + SDVTList Tys; + bool useSSE = isScalarFPTypeInSSEReg(Op.getValueType()); + if (useSSE) + Tys = DAG.getVTList(MVT::f64, MVT::Other, MVT::Flag); + else + Tys = DAG.getVTList(Op.getValueType(), MVT::Other); + SmallVector Ops; + Ops.push_back(Chain); + Ops.push_back(StackSlot); + Ops.push_back(DAG.getValueType(SrcVT)); + SDValue Result = DAG.getNode(useSSE ? X86ISD::FILD_FLAG : X86ISD::FILD, dl, + Tys, &Ops[0], Ops.size()); + + if (useSSE) { + Chain = Result.getValue(1); + SDValue InFlag = Result.getValue(2); + + // FIXME: Currently the FST is flagged to the FILD_FLAG. This + // shouldn't be necessary except that RFP cannot be live across + // multiple blocks. When stackifier is fixed, they can be uncoupled. + MachineFunction &MF = DAG.getMachineFunction(); + int SSFI = MF.getFrameInfo()->CreateStackObject(8, 8, false); + SDValue StackSlot = DAG.getFrameIndex(SSFI, getPointerTy()); + Tys = DAG.getVTList(MVT::Other); + SmallVector Ops; + Ops.push_back(Chain); + Ops.push_back(Result); + Ops.push_back(StackSlot); + Ops.push_back(DAG.getValueType(Op.getValueType())); + Ops.push_back(InFlag); + Chain = DAG.getNode(X86ISD::FST, dl, Tys, &Ops[0], Ops.size()); + Result = DAG.getLoad(Op.getValueType(), dl, Chain, StackSlot, + PseudoSourceValue::getFixedStack(SSFI), 0); + } + + return Result; +} + +// LowerUINT_TO_FP_i64 - 64-bit unsigned integer to double expansion. +SDValue X86TargetLowering::LowerUINT_TO_FP_i64(SDValue Op, SelectionDAG &DAG) { + // This algorithm is not obvious. Here it is in C code, more or less: + /* + double uint64_to_double( uint32_t hi, uint32_t lo ) { + static const __m128i exp = { 0x4330000045300000ULL, 0 }; + static const __m128d bias = { 0x1.0p84, 0x1.0p52 }; + + // Copy ints to xmm registers. + __m128i xh = _mm_cvtsi32_si128( hi ); + __m128i xl = _mm_cvtsi32_si128( lo ); + + // Combine into low half of a single xmm register. + __m128i x = _mm_unpacklo_epi32( xh, xl ); + __m128d d; + double sd; + + // Merge in appropriate exponents to give the integer bits the right + // magnitude. + x = _mm_unpacklo_epi32( x, exp ); + + // Subtract away the biases to deal with the IEEE-754 double precision + // implicit 1. + d = _mm_sub_pd( (__m128d) x, bias ); + + // All conversions up to here are exact. The correctly rounded result is + // calculated using the current rounding mode using the following + // horizontal add. + d = _mm_add_sd( d, _mm_unpackhi_pd( d, d ) ); + _mm_store_sd( &sd, d ); // Because we are returning doubles in XMM, this + // store doesn't really need to be here (except + // maybe to zero the other double) + return sd; + } + */ + + DebugLoc dl = Op.getDebugLoc(); + LLVMContext *Context = DAG.getContext(); + + // Build some magic constants. + std::vector CV0; + CV0.push_back(ConstantInt::get(*Context, APInt(32, 0x45300000))); + CV0.push_back(ConstantInt::get(*Context, APInt(32, 0x43300000))); + CV0.push_back(ConstantInt::get(*Context, APInt(32, 0))); + CV0.push_back(ConstantInt::get(*Context, APInt(32, 0))); + Constant *C0 = ConstantVector::get(CV0); + SDValue CPIdx0 = DAG.getConstantPool(C0, getPointerTy(), 16); + + std::vector CV1; + CV1.push_back( + ConstantFP::get(*Context, APFloat(APInt(64, 0x4530000000000000ULL)))); + CV1.push_back( + ConstantFP::get(*Context, APFloat(APInt(64, 0x4330000000000000ULL)))); + Constant *C1 = ConstantVector::get(CV1); + SDValue CPIdx1 = DAG.getConstantPool(C1, getPointerTy(), 16); + + SDValue XR1 = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, MVT::v4i32, + DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, + Op.getOperand(0), + DAG.getIntPtrConstant(1))); + SDValue XR2 = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, MVT::v4i32, + DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, + Op.getOperand(0), + DAG.getIntPtrConstant(0))); + SDValue Unpck1 = getUnpackl(DAG, dl, MVT::v4i32, XR1, XR2); + SDValue CLod0 = DAG.getLoad(MVT::v4i32, dl, DAG.getEntryNode(), CPIdx0, + PseudoSourceValue::getConstantPool(), 0, + false, 16); + SDValue Unpck2 = getUnpackl(DAG, dl, MVT::v4i32, Unpck1, CLod0); + SDValue XR2F = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::v2f64, Unpck2); + SDValue CLod1 = DAG.getLoad(MVT::v2f64, dl, CLod0.getValue(1), CPIdx1, + PseudoSourceValue::getConstantPool(), 0, + false, 16); + SDValue Sub = DAG.getNode(ISD::FSUB, dl, MVT::v2f64, XR2F, CLod1); + + // Add the halves; easiest way is to swap them into another reg first. + int ShufMask[2] = { 1, -1 }; + SDValue Shuf = DAG.getVectorShuffle(MVT::v2f64, dl, Sub, + DAG.getUNDEF(MVT::v2f64), ShufMask); + SDValue Add = DAG.getNode(ISD::FADD, dl, MVT::v2f64, Shuf, Sub); + return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, MVT::f64, Add, + DAG.getIntPtrConstant(0)); +} + +// LowerUINT_TO_FP_i32 - 32-bit unsigned integer to float expansion. +SDValue X86TargetLowering::LowerUINT_TO_FP_i32(SDValue Op, SelectionDAG &DAG) { + DebugLoc dl = Op.getDebugLoc(); + // FP constant to bias correct the final result. + SDValue Bias = DAG.getConstantFP(BitsToDouble(0x4330000000000000ULL), + MVT::f64); + + // Load the 32-bit value into an XMM register. + SDValue Load = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, MVT::v4i32, + DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, + Op.getOperand(0), + DAG.getIntPtrConstant(0))); + + Load = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, MVT::f64, + DAG.getNode(ISD::BIT_CONVERT, dl, MVT::v2f64, Load), + DAG.getIntPtrConstant(0)); + + // Or the load with the bias. + SDValue Or = DAG.getNode(ISD::OR, dl, MVT::v2i64, + DAG.getNode(ISD::BIT_CONVERT, dl, MVT::v2i64, + DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, + MVT::v2f64, Load)), + DAG.getNode(ISD::BIT_CONVERT, dl, MVT::v2i64, + DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, + MVT::v2f64, Bias))); + Or = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, MVT::f64, + DAG.getNode(ISD::BIT_CONVERT, dl, MVT::v2f64, Or), + DAG.getIntPtrConstant(0)); + + // Subtract the bias. + SDValue Sub = DAG.getNode(ISD::FSUB, dl, MVT::f64, Or, Bias); + + // Handle final rounding. + EVT DestVT = Op.getValueType(); + + if (DestVT.bitsLT(MVT::f64)) { + return DAG.getNode(ISD::FP_ROUND, dl, DestVT, Sub, + DAG.getIntPtrConstant(0)); + } else if (DestVT.bitsGT(MVT::f64)) { + return DAG.getNode(ISD::FP_EXTEND, dl, DestVT, Sub); + } + + // Handle final rounding. + return Sub; +} + +SDValue X86TargetLowering::LowerUINT_TO_FP(SDValue Op, SelectionDAG &DAG) { + SDValue N0 = Op.getOperand(0); + DebugLoc dl = Op.getDebugLoc(); + + // Now not UINT_TO_FP is legal (it's marked custom), dag combiner won't + // optimize it to a SINT_TO_FP when the sign bit is known zero. Perform + // the optimization here. + if (DAG.SignBitIsZero(N0)) + return DAG.getNode(ISD::SINT_TO_FP, dl, Op.getValueType(), N0); + + EVT SrcVT = N0.getValueType(); + if (SrcVT == MVT::i64) { + // We only handle SSE2 f64 target here; caller can expand the rest. + if (Op.getValueType() != MVT::f64 || !X86ScalarSSEf64) + return SDValue(); + + return LowerUINT_TO_FP_i64(Op, DAG); + } else if (SrcVT == MVT::i32 && X86ScalarSSEf64) { + return LowerUINT_TO_FP_i32(Op, DAG); + } + + assert(SrcVT == MVT::i32 && "Unknown UINT_TO_FP to lower!"); + + // Make a 64-bit buffer, and use it to build an FILD. + SDValue StackSlot = DAG.CreateStackTemporary(MVT::i64); + SDValue WordOff = DAG.getConstant(4, getPointerTy()); + SDValue OffsetSlot = DAG.getNode(ISD::ADD, dl, + getPointerTy(), StackSlot, WordOff); + SDValue Store1 = DAG.getStore(DAG.getEntryNode(), dl, Op.getOperand(0), + StackSlot, NULL, 0); + SDValue Store2 = DAG.getStore(Store1, dl, DAG.getConstant(0, MVT::i32), + OffsetSlot, NULL, 0); + return BuildFILD(Op, MVT::i64, Store2, StackSlot, DAG); +} + +std::pair X86TargetLowering:: +FP_TO_INTHelper(SDValue Op, SelectionDAG &DAG, bool IsSigned) { + DebugLoc dl = Op.getDebugLoc(); + + EVT DstTy = Op.getValueType(); + + if (!IsSigned) { + assert(DstTy == MVT::i32 && "Unexpected FP_TO_UINT"); + DstTy = MVT::i64; + } + + assert(DstTy.getSimpleVT() <= MVT::i64 && + DstTy.getSimpleVT() >= MVT::i16 && + "Unknown FP_TO_SINT to lower!"); + + // These are really Legal. + if (DstTy == MVT::i32 && + isScalarFPTypeInSSEReg(Op.getOperand(0).getValueType())) + return std::make_pair(SDValue(), SDValue()); + if (Subtarget->is64Bit() && + DstTy == MVT::i64 && + isScalarFPTypeInSSEReg(Op.getOperand(0).getValueType())) + return std::make_pair(SDValue(), SDValue()); + + // We lower FP->sint64 into FISTP64, followed by a load, all to a temporary + // stack slot. + MachineFunction &MF = DAG.getMachineFunction(); + unsigned MemSize = DstTy.getSizeInBits()/8; + int SSFI = MF.getFrameInfo()->CreateStackObject(MemSize, MemSize, false); + SDValue StackSlot = DAG.getFrameIndex(SSFI, getPointerTy()); + + unsigned Opc; + switch (DstTy.getSimpleVT().SimpleTy) { + default: llvm_unreachable("Invalid FP_TO_SINT to lower!"); + case MVT::i16: Opc = X86ISD::FP_TO_INT16_IN_MEM; break; + case MVT::i32: Opc = X86ISD::FP_TO_INT32_IN_MEM; break; + case MVT::i64: Opc = X86ISD::FP_TO_INT64_IN_MEM; break; + } + + SDValue Chain = DAG.getEntryNode(); + SDValue Value = Op.getOperand(0); + if (isScalarFPTypeInSSEReg(Op.getOperand(0).getValueType())) { + assert(DstTy == MVT::i64 && "Invalid FP_TO_SINT to lower!"); + Chain = DAG.getStore(Chain, dl, Value, StackSlot, + PseudoSourceValue::getFixedStack(SSFI), 0); + SDVTList Tys = DAG.getVTList(Op.getOperand(0).getValueType(), MVT::Other); + SDValue Ops[] = { + Chain, StackSlot, DAG.getValueType(Op.getOperand(0).getValueType()) + }; + Value = DAG.getNode(X86ISD::FLD, dl, Tys, Ops, 3); + Chain = Value.getValue(1); + SSFI = MF.getFrameInfo()->CreateStackObject(MemSize, MemSize, false); + StackSlot = DAG.getFrameIndex(SSFI, getPointerTy()); + } + + // Build the FP_TO_INT*_IN_MEM + SDValue Ops[] = { Chain, Value, StackSlot }; + SDValue FIST = DAG.getNode(Opc, dl, MVT::Other, Ops, 3); + + return std::make_pair(FIST, StackSlot); +} + +SDValue X86TargetLowering::LowerFP_TO_SINT(SDValue Op, SelectionDAG &DAG) { + if (Op.getValueType().isVector()) { + if (Op.getValueType() == MVT::v2i32 && + Op.getOperand(0).getValueType() == MVT::v2f64) { + return Op; + } + return SDValue(); + } + + std::pair Vals = FP_TO_INTHelper(Op, DAG, true); + SDValue FIST = Vals.first, StackSlot = Vals.second; + // If FP_TO_INTHelper failed, the node is actually supposed to be Legal. + if (FIST.getNode() == 0) return Op; + + // Load the result. + return DAG.getLoad(Op.getValueType(), Op.getDebugLoc(), + FIST, StackSlot, NULL, 0); +} + +SDValue X86TargetLowering::LowerFP_TO_UINT(SDValue Op, SelectionDAG &DAG) { + std::pair Vals = FP_TO_INTHelper(Op, DAG, false); + SDValue FIST = Vals.first, StackSlot = Vals.second; + assert(FIST.getNode() && "Unexpected failure"); + + // Load the result. + return DAG.getLoad(Op.getValueType(), Op.getDebugLoc(), + FIST, StackSlot, NULL, 0); +} + +SDValue X86TargetLowering::LowerFABS(SDValue Op, SelectionDAG &DAG) { + LLVMContext *Context = DAG.getContext(); + DebugLoc dl = Op.getDebugLoc(); + EVT VT = Op.getValueType(); + EVT EltVT = VT; + if (VT.isVector()) + EltVT = VT.getVectorElementType(); + std::vector CV; + if (EltVT == MVT::f64) { + Constant *C = ConstantFP::get(*Context, APFloat(APInt(64, ~(1ULL << 63)))); + CV.push_back(C); + CV.push_back(C); + } else { + Constant *C = ConstantFP::get(*Context, APFloat(APInt(32, ~(1U << 31)))); + CV.push_back(C); + CV.push_back(C); + CV.push_back(C); + CV.push_back(C); + } + Constant *C = ConstantVector::get(CV); + SDValue CPIdx = DAG.getConstantPool(C, getPointerTy(), 16); + SDValue Mask = DAG.getLoad(VT, dl, DAG.getEntryNode(), CPIdx, + PseudoSourceValue::getConstantPool(), 0, + false, 16); + return DAG.getNode(X86ISD::FAND, dl, VT, Op.getOperand(0), Mask); +} + +SDValue X86TargetLowering::LowerFNEG(SDValue Op, SelectionDAG &DAG) { + LLVMContext *Context = DAG.getContext(); + DebugLoc dl = Op.getDebugLoc(); + EVT VT = Op.getValueType(); + EVT EltVT = VT; + if (VT.isVector()) + EltVT = VT.getVectorElementType(); + std::vector CV; + if (EltVT == MVT::f64) { + Constant *C = ConstantFP::get(*Context, APFloat(APInt(64, 1ULL << 63))); + CV.push_back(C); + CV.push_back(C); + } else { + Constant *C = ConstantFP::get(*Context, APFloat(APInt(32, 1U << 31))); + CV.push_back(C); + CV.push_back(C); + CV.push_back(C); + CV.push_back(C); + } + Constant *C = ConstantVector::get(CV); + SDValue CPIdx = DAG.getConstantPool(C, getPointerTy(), 16); + SDValue Mask = DAG.getLoad(VT, dl, DAG.getEntryNode(), CPIdx, + PseudoSourceValue::getConstantPool(), 0, + false, 16); + if (VT.isVector()) { + return DAG.getNode(ISD::BIT_CONVERT, dl, VT, + DAG.getNode(ISD::XOR, dl, MVT::v2i64, + DAG.getNode(ISD::BIT_CONVERT, dl, MVT::v2i64, + Op.getOperand(0)), + DAG.getNode(ISD::BIT_CONVERT, dl, MVT::v2i64, Mask))); + } else { + return DAG.getNode(X86ISD::FXOR, dl, VT, Op.getOperand(0), Mask); + } +} + +SDValue X86TargetLowering::LowerFCOPYSIGN(SDValue Op, SelectionDAG &DAG) { + LLVMContext *Context = DAG.getContext(); + SDValue Op0 = Op.getOperand(0); + SDValue Op1 = Op.getOperand(1); + DebugLoc dl = Op.getDebugLoc(); + EVT VT = Op.getValueType(); + EVT SrcVT = Op1.getValueType(); + + // If second operand is smaller, extend it first. + if (SrcVT.bitsLT(VT)) { + Op1 = DAG.getNode(ISD::FP_EXTEND, dl, VT, Op1); + SrcVT = VT; + } + // And if it is bigger, shrink it first. + if (SrcVT.bitsGT(VT)) { + Op1 = DAG.getNode(ISD::FP_ROUND, dl, VT, Op1, DAG.getIntPtrConstant(1)); + SrcVT = VT; + } + + // At this point the operands and the result should have the same + // type, and that won't be f80 since that is not custom lowered. + + // First get the sign bit of second operand. + std::vector CV; + if (SrcVT == MVT::f64) { + CV.push_back(ConstantFP::get(*Context, APFloat(APInt(64, 1ULL << 63)))); + CV.push_back(ConstantFP::get(*Context, APFloat(APInt(64, 0)))); + } else { + CV.push_back(ConstantFP::get(*Context, APFloat(APInt(32, 1U << 31)))); + CV.push_back(ConstantFP::get(*Context, APFloat(APInt(32, 0)))); + CV.push_back(ConstantFP::get(*Context, APFloat(APInt(32, 0)))); + CV.push_back(ConstantFP::get(*Context, APFloat(APInt(32, 0)))); + } + Constant *C = ConstantVector::get(CV); + SDValue CPIdx = DAG.getConstantPool(C, getPointerTy(), 16); + SDValue Mask1 = DAG.getLoad(SrcVT, dl, DAG.getEntryNode(), CPIdx, + PseudoSourceValue::getConstantPool(), 0, + false, 16); + SDValue SignBit = DAG.getNode(X86ISD::FAND, dl, SrcVT, Op1, Mask1); + + // Shift sign bit right or left if the two operands have different types. + if (SrcVT.bitsGT(VT)) { + // Op0 is MVT::f32, Op1 is MVT::f64. + SignBit = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, MVT::v2f64, SignBit); + SignBit = DAG.getNode(X86ISD::FSRL, dl, MVT::v2f64, SignBit, + DAG.getConstant(32, MVT::i32)); + SignBit = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::v4f32, SignBit); + SignBit = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, MVT::f32, SignBit, + DAG.getIntPtrConstant(0)); + } + + // Clear first operand sign bit. + CV.clear(); + if (VT == MVT::f64) { + CV.push_back(ConstantFP::get(*Context, APFloat(APInt(64, ~(1ULL << 63))))); + CV.push_back(ConstantFP::get(*Context, APFloat(APInt(64, 0)))); + } else { + CV.push_back(ConstantFP::get(*Context, APFloat(APInt(32, ~(1U << 31))))); + CV.push_back(ConstantFP::get(*Context, APFloat(APInt(32, 0)))); + CV.push_back(ConstantFP::get(*Context, APFloat(APInt(32, 0)))); + CV.push_back(ConstantFP::get(*Context, APFloat(APInt(32, 0)))); + } + C = ConstantVector::get(CV); + CPIdx = DAG.getConstantPool(C, getPointerTy(), 16); + SDValue Mask2 = DAG.getLoad(VT, dl, DAG.getEntryNode(), CPIdx, + PseudoSourceValue::getConstantPool(), 0, + false, 16); + SDValue Val = DAG.getNode(X86ISD::FAND, dl, VT, Op0, Mask2); + + // Or the value with the sign bit. + return DAG.getNode(X86ISD::FOR, dl, VT, Val, SignBit); +} + +/// Emit nodes that will be selected as "test Op0,Op0", or something +/// equivalent. +SDValue X86TargetLowering::EmitTest(SDValue Op, unsigned X86CC, + SelectionDAG &DAG) { + DebugLoc dl = Op.getDebugLoc(); + + // CF and OF aren't always set the way we want. Determine which + // of these we need. + bool NeedCF = false; + bool NeedOF = false; + switch (X86CC) { + case X86::COND_A: case X86::COND_AE: + case X86::COND_B: case X86::COND_BE: + NeedCF = true; + break; + case X86::COND_G: case X86::COND_GE: + case X86::COND_L: case X86::COND_LE: + case X86::COND_O: case X86::COND_NO: + NeedOF = true; + break; + default: break; + } + + // See if we can use the EFLAGS value from the operand instead of + // doing a separate TEST. TEST always sets OF and CF to 0, so unless + // we prove that the arithmetic won't overflow, we can't use OF or CF. + if (Op.getResNo() == 0 && !NeedOF && !NeedCF) { + unsigned Opcode = 0; + unsigned NumOperands = 0; + switch (Op.getNode()->getOpcode()) { + case ISD::ADD: + // Due to an isel shortcoming, be conservative if this add is likely to + // be selected as part of a load-modify-store instruction. When the root + // node in a match is a store, isel doesn't know how to remap non-chain + // non-flag uses of other nodes in the match, such as the ADD in this + // case. This leads to the ADD being left around and reselected, with + // the result being two adds in the output. + for (SDNode::use_iterator UI = Op.getNode()->use_begin(), + UE = Op.getNode()->use_end(); UI != UE; ++UI) + if (UI->getOpcode() == ISD::STORE) + goto default_case; + if (ConstantSDNode *C = + dyn_cast(Op.getNode()->getOperand(1))) { + // An add of one will be selected as an INC. + if (C->getAPIntValue() == 1) { + Opcode = X86ISD::INC; + NumOperands = 1; + break; + } + // An add of negative one (subtract of one) will be selected as a DEC. + if (C->getAPIntValue().isAllOnesValue()) { + Opcode = X86ISD::DEC; + NumOperands = 1; + break; + } + } + // Otherwise use a regular EFLAGS-setting add. + Opcode = X86ISD::ADD; + NumOperands = 2; + break; + case ISD::AND: { + // If the primary and result isn't used, don't bother using X86ISD::AND, + // because a TEST instruction will be better. + bool NonFlagUse = false; + for (SDNode::use_iterator UI = Op.getNode()->use_begin(), + UE = Op.getNode()->use_end(); UI != UE; ++UI) + if (UI->getOpcode() != ISD::BRCOND && + UI->getOpcode() != ISD::SELECT && + UI->getOpcode() != ISD::SETCC) { + NonFlagUse = true; + break; + } + if (!NonFlagUse) + break; + } + // FALL THROUGH + case ISD::SUB: + case ISD::OR: + case ISD::XOR: + // Due to the ISEL shortcoming noted above, be conservative if this op is + // likely to be selected as part of a load-modify-store instruction. + for (SDNode::use_iterator UI = Op.getNode()->use_begin(), + UE = Op.getNode()->use_end(); UI != UE; ++UI) + if (UI->getOpcode() == ISD::STORE) + goto default_case; + // Otherwise use a regular EFLAGS-setting instruction. + switch (Op.getNode()->getOpcode()) { + case ISD::SUB: Opcode = X86ISD::SUB; break; + case ISD::OR: Opcode = X86ISD::OR; break; + case ISD::XOR: Opcode = X86ISD::XOR; break; + case ISD::AND: Opcode = X86ISD::AND; break; + default: llvm_unreachable("unexpected operator!"); + } + NumOperands = 2; + break; + case X86ISD::ADD: + case X86ISD::SUB: + case X86ISD::INC: + case X86ISD::DEC: + case X86ISD::OR: + case X86ISD::XOR: + case X86ISD::AND: + return SDValue(Op.getNode(), 1); + default: + default_case: + break; + } + if (Opcode != 0) { + SDVTList VTs = DAG.getVTList(Op.getValueType(), MVT::i32); + SmallVector Ops; + for (unsigned i = 0; i != NumOperands; ++i) + Ops.push_back(Op.getOperand(i)); + SDValue New = DAG.getNode(Opcode, dl, VTs, &Ops[0], NumOperands); + DAG.ReplaceAllUsesWith(Op, New); + return SDValue(New.getNode(), 1); + } + } + + // Otherwise just emit a CMP with 0, which is the TEST pattern. + return DAG.getNode(X86ISD::CMP, dl, MVT::i32, Op, + DAG.getConstant(0, Op.getValueType())); +} + +/// Emit nodes that will be selected as "cmp Op0,Op1", or something +/// equivalent. +SDValue X86TargetLowering::EmitCmp(SDValue Op0, SDValue Op1, unsigned X86CC, + SelectionDAG &DAG) { + if (ConstantSDNode *C = dyn_cast(Op1)) + if (C->getAPIntValue() == 0) + return EmitTest(Op0, X86CC, DAG); + + DebugLoc dl = Op0.getDebugLoc(); + return DAG.getNode(X86ISD::CMP, dl, MVT::i32, Op0, Op1); +} + +SDValue X86TargetLowering::LowerSETCC(SDValue Op, SelectionDAG &DAG) { + assert(Op.getValueType() == MVT::i8 && "SetCC type must be 8-bit integer"); + SDValue Op0 = Op.getOperand(0); + SDValue Op1 = Op.getOperand(1); + DebugLoc dl = Op.getDebugLoc(); + ISD::CondCode CC = cast(Op.getOperand(2))->get(); + + // Lower (X & (1 << N)) == 0 to BT(X, N). + // Lower ((X >>u N) & 1) != 0 to BT(X, N). + // Lower ((X >>s N) & 1) != 0 to BT(X, N). + if (Op0.getOpcode() == ISD::AND && + Op0.hasOneUse() && + Op1.getOpcode() == ISD::Constant && + cast(Op1)->getZExtValue() == 0 && + (CC == ISD::SETEQ || CC == ISD::SETNE)) { + SDValue LHS, RHS; + if (Op0.getOperand(1).getOpcode() == ISD::SHL) { + if (ConstantSDNode *Op010C = + dyn_cast(Op0.getOperand(1).getOperand(0))) + if (Op010C->getZExtValue() == 1) { + LHS = Op0.getOperand(0); + RHS = Op0.getOperand(1).getOperand(1); + } + } else if (Op0.getOperand(0).getOpcode() == ISD::SHL) { + if (ConstantSDNode *Op000C = + dyn_cast(Op0.getOperand(0).getOperand(0))) + if (Op000C->getZExtValue() == 1) { + LHS = Op0.getOperand(1); + RHS = Op0.getOperand(0).getOperand(1); + } + } else if (Op0.getOperand(1).getOpcode() == ISD::Constant) { + ConstantSDNode *AndRHS = cast(Op0.getOperand(1)); + SDValue AndLHS = Op0.getOperand(0); + if (AndRHS->getZExtValue() == 1 && AndLHS.getOpcode() == ISD::SRL) { + LHS = AndLHS.getOperand(0); + RHS = AndLHS.getOperand(1); + } + } + + if (LHS.getNode()) { + // If LHS is i8, promote it to i16 with any_extend. There is no i8 BT + // instruction. Since the shift amount is in-range-or-undefined, we know + // that doing a bittest on the i16 value is ok. We extend to i32 because + // the encoding for the i16 version is larger than the i32 version. + if (LHS.getValueType() == MVT::i8) + LHS = DAG.getNode(ISD::ANY_EXTEND, dl, MVT::i32, LHS); + + // If the operand types disagree, extend the shift amount to match. Since + // BT ignores high bits (like shifts) we can use anyextend. + if (LHS.getValueType() != RHS.getValueType()) + RHS = DAG.getNode(ISD::ANY_EXTEND, dl, LHS.getValueType(), RHS); + + SDValue BT = DAG.getNode(X86ISD::BT, dl, MVT::i32, LHS, RHS); + unsigned Cond = CC == ISD::SETEQ ? X86::COND_AE : X86::COND_B; + return DAG.getNode(X86ISD::SETCC, dl, MVT::i8, + DAG.getConstant(Cond, MVT::i8), BT); + } + } + + bool isFP = Op.getOperand(1).getValueType().isFloatingPoint(); + unsigned X86CC = TranslateX86CC(CC, isFP, Op0, Op1, DAG); + if (X86CC == X86::COND_INVALID) + return SDValue(); + + SDValue Cond = EmitCmp(Op0, Op1, X86CC, DAG); + return DAG.getNode(X86ISD::SETCC, dl, MVT::i8, + DAG.getConstant(X86CC, MVT::i8), Cond); +} + +SDValue X86TargetLowering::LowerVSETCC(SDValue Op, SelectionDAG &DAG) { + SDValue Cond; + SDValue Op0 = Op.getOperand(0); + SDValue Op1 = Op.getOperand(1); + SDValue CC = Op.getOperand(2); + EVT VT = Op.getValueType(); + ISD::CondCode SetCCOpcode = cast(CC)->get(); + bool isFP = Op.getOperand(1).getValueType().isFloatingPoint(); + DebugLoc dl = Op.getDebugLoc(); + + if (isFP) { + unsigned SSECC = 8; + EVT VT0 = Op0.getValueType(); + assert(VT0 == MVT::v4f32 || VT0 == MVT::v2f64); + unsigned Opc = VT0 == MVT::v4f32 ? X86ISD::CMPPS : X86ISD::CMPPD; + bool Swap = false; + + switch (SetCCOpcode) { + default: break; + case ISD::SETOEQ: + case ISD::SETEQ: SSECC = 0; break; + case ISD::SETOGT: + case ISD::SETGT: Swap = true; // Fallthrough + case ISD::SETLT: + case ISD::SETOLT: SSECC = 1; break; + case ISD::SETOGE: + case ISD::SETGE: Swap = true; // Fallthrough + case ISD::SETLE: + case ISD::SETOLE: SSECC = 2; break; + case ISD::SETUO: SSECC = 3; break; + case ISD::SETUNE: + case ISD::SETNE: SSECC = 4; break; + case ISD::SETULE: Swap = true; + case ISD::SETUGE: SSECC = 5; break; + case ISD::SETULT: Swap = true; + case ISD::SETUGT: SSECC = 6; break; + case ISD::SETO: SSECC = 7; break; + } + if (Swap) + std::swap(Op0, Op1); + + // In the two special cases we can't handle, emit two comparisons. + if (SSECC == 8) { + if (SetCCOpcode == ISD::SETUEQ) { + SDValue UNORD, EQ; + UNORD = DAG.getNode(Opc, dl, VT, Op0, Op1, DAG.getConstant(3, MVT::i8)); + EQ = DAG.getNode(Opc, dl, VT, Op0, Op1, DAG.getConstant(0, MVT::i8)); + return DAG.getNode(ISD::OR, dl, VT, UNORD, EQ); + } + else if (SetCCOpcode == ISD::SETONE) { + SDValue ORD, NEQ; + ORD = DAG.getNode(Opc, dl, VT, Op0, Op1, DAG.getConstant(7, MVT::i8)); + NEQ = DAG.getNode(Opc, dl, VT, Op0, Op1, DAG.getConstant(4, MVT::i8)); + return DAG.getNode(ISD::AND, dl, VT, ORD, NEQ); + } + llvm_unreachable("Illegal FP comparison"); + } + // Handle all other FP comparisons here. + return DAG.getNode(Opc, dl, VT, Op0, Op1, DAG.getConstant(SSECC, MVT::i8)); + } + + // We are handling one of the integer comparisons here. Since SSE only has + // GT and EQ comparisons for integer, swapping operands and multiple + // operations may be required for some comparisons. + unsigned Opc = 0, EQOpc = 0, GTOpc = 0; + bool Swap = false, Invert = false, FlipSigns = false; + + switch (VT.getSimpleVT().SimpleTy) { + default: break; + case MVT::v8i8: + case MVT::v16i8: EQOpc = X86ISD::PCMPEQB; GTOpc = X86ISD::PCMPGTB; break; + case MVT::v4i16: + case MVT::v8i16: EQOpc = X86ISD::PCMPEQW; GTOpc = X86ISD::PCMPGTW; break; + case MVT::v2i32: + case MVT::v4i32: EQOpc = X86ISD::PCMPEQD; GTOpc = X86ISD::PCMPGTD; break; + case MVT::v2i64: EQOpc = X86ISD::PCMPEQQ; GTOpc = X86ISD::PCMPGTQ; break; + } + + switch (SetCCOpcode) { + default: break; + case ISD::SETNE: Invert = true; + case ISD::SETEQ: Opc = EQOpc; break; + case ISD::SETLT: Swap = true; + case ISD::SETGT: Opc = GTOpc; break; + case ISD::SETGE: Swap = true; + case ISD::SETLE: Opc = GTOpc; Invert = true; break; + case ISD::SETULT: Swap = true; + case ISD::SETUGT: Opc = GTOpc; FlipSigns = true; break; + case ISD::SETUGE: Swap = true; + case ISD::SETULE: Opc = GTOpc; FlipSigns = true; Invert = true; break; + } + if (Swap) + std::swap(Op0, Op1); + + // Since SSE has no unsigned integer comparisons, we need to flip the sign + // bits of the inputs before performing those operations. + if (FlipSigns) { + EVT EltVT = VT.getVectorElementType(); + SDValue SignBit = DAG.getConstant(APInt::getSignBit(EltVT.getSizeInBits()), + EltVT); + std::vector SignBits(VT.getVectorNumElements(), SignBit); + SDValue SignVec = DAG.getNode(ISD::BUILD_VECTOR, dl, VT, &SignBits[0], + SignBits.size()); + Op0 = DAG.getNode(ISD::XOR, dl, VT, Op0, SignVec); + Op1 = DAG.getNode(ISD::XOR, dl, VT, Op1, SignVec); + } + + SDValue Result = DAG.getNode(Opc, dl, VT, Op0, Op1); + + // If the logical-not of the result is required, perform that now. + if (Invert) + Result = DAG.getNOT(dl, Result, VT); + + return Result; +} + +// isX86LogicalCmp - Return true if opcode is a X86 logical comparison. +static bool isX86LogicalCmp(SDValue Op) { + unsigned Opc = Op.getNode()->getOpcode(); + if (Opc == X86ISD::CMP || Opc == X86ISD::COMI || Opc == X86ISD::UCOMI) + return true; + if (Op.getResNo() == 1 && + (Opc == X86ISD::ADD || + Opc == X86ISD::SUB || + Opc == X86ISD::SMUL || + Opc == X86ISD::UMUL || + Opc == X86ISD::INC || + Opc == X86ISD::DEC || + Opc == X86ISD::OR || + Opc == X86ISD::XOR || + Opc == X86ISD::AND)) + return true; + + return false; +} + +SDValue X86TargetLowering::LowerSELECT(SDValue Op, SelectionDAG &DAG) { + bool addTest = true; + SDValue Cond = Op.getOperand(0); + DebugLoc dl = Op.getDebugLoc(); + SDValue CC; + + if (Cond.getOpcode() == ISD::SETCC) { + SDValue NewCond = LowerSETCC(Cond, DAG); + if (NewCond.getNode()) + Cond = NewCond; + } + + // If condition flag is set by a X86ISD::CMP, then use it as the condition + // setting operand in place of the X86ISD::SETCC. + if (Cond.getOpcode() == X86ISD::SETCC) { + CC = Cond.getOperand(0); + + SDValue Cmp = Cond.getOperand(1); + unsigned Opc = Cmp.getOpcode(); + EVT VT = Op.getValueType(); + + bool IllegalFPCMov = false; + if (VT.isFloatingPoint() && !VT.isVector() && + !isScalarFPTypeInSSEReg(VT)) // FPStack? + IllegalFPCMov = !hasFPCMov(cast(CC)->getSExtValue()); + + if ((isX86LogicalCmp(Cmp) && !IllegalFPCMov) || + Opc == X86ISD::BT) { // FIXME + Cond = Cmp; + addTest = false; + } + } + + if (addTest) { + CC = DAG.getConstant(X86::COND_NE, MVT::i8); + Cond = EmitTest(Cond, X86::COND_NE, DAG); + } + + SDVTList VTs = DAG.getVTList(Op.getValueType(), MVT::Flag); + SmallVector Ops; + // X86ISD::CMOV means set the result (which is operand 1) to the RHS if + // condition is true. + Ops.push_back(Op.getOperand(2)); + Ops.push_back(Op.getOperand(1)); + Ops.push_back(CC); + Ops.push_back(Cond); + return DAG.getNode(X86ISD::CMOV, dl, VTs, &Ops[0], Ops.size()); +} + +// isAndOrOfSingleUseSetCCs - Return true if node is an ISD::AND or +// ISD::OR of two X86ISD::SETCC nodes each of which has no other use apart +// from the AND / OR. +static bool isAndOrOfSetCCs(SDValue Op, unsigned &Opc) { + Opc = Op.getOpcode(); + if (Opc != ISD::OR && Opc != ISD::AND) + return false; + return (Op.getOperand(0).getOpcode() == X86ISD::SETCC && + Op.getOperand(0).hasOneUse() && + Op.getOperand(1).getOpcode() == X86ISD::SETCC && + Op.getOperand(1).hasOneUse()); +} + +// isXor1OfSetCC - Return true if node is an ISD::XOR of a X86ISD::SETCC and +// 1 and that the SETCC node has a single use. +static bool isXor1OfSetCC(SDValue Op) { + if (Op.getOpcode() != ISD::XOR) + return false; + ConstantSDNode *N1C = dyn_cast(Op.getOperand(1)); + if (N1C && N1C->getAPIntValue() == 1) { + return Op.getOperand(0).getOpcode() == X86ISD::SETCC && + Op.getOperand(0).hasOneUse(); + } + return false; +} + +SDValue X86TargetLowering::LowerBRCOND(SDValue Op, SelectionDAG &DAG) { + bool addTest = true; + SDValue Chain = Op.getOperand(0); + SDValue Cond = Op.getOperand(1); + SDValue Dest = Op.getOperand(2); + DebugLoc dl = Op.getDebugLoc(); + SDValue CC; + + if (Cond.getOpcode() == ISD::SETCC) { + SDValue NewCond = LowerSETCC(Cond, DAG); + if (NewCond.getNode()) + Cond = NewCond; + } +#if 0 + // FIXME: LowerXALUO doesn't handle these!! + else if (Cond.getOpcode() == X86ISD::ADD || + Cond.getOpcode() == X86ISD::SUB || + Cond.getOpcode() == X86ISD::SMUL || + Cond.getOpcode() == X86ISD::UMUL) + Cond = LowerXALUO(Cond, DAG); +#endif + + // If condition flag is set by a X86ISD::CMP, then use it as the condition + // setting operand in place of the X86ISD::SETCC. + if (Cond.getOpcode() == X86ISD::SETCC) { + CC = Cond.getOperand(0); + + SDValue Cmp = Cond.getOperand(1); + unsigned Opc = Cmp.getOpcode(); + // FIXME: WHY THE SPECIAL CASING OF LogicalCmp?? + if (isX86LogicalCmp(Cmp) || Opc == X86ISD::BT) { + Cond = Cmp; + addTest = false; + } else { + switch (cast(CC)->getZExtValue()) { + default: break; + case X86::COND_O: + case X86::COND_B: + // These can only come from an arithmetic instruction with overflow, + // e.g. SADDO, UADDO. + Cond = Cond.getNode()->getOperand(1); + addTest = false; + break; + } + } + } else { + unsigned CondOpc; + if (Cond.hasOneUse() && isAndOrOfSetCCs(Cond, CondOpc)) { + SDValue Cmp = Cond.getOperand(0).getOperand(1); + if (CondOpc == ISD::OR) { + // Also, recognize the pattern generated by an FCMP_UNE. We can emit + // two branches instead of an explicit OR instruction with a + // separate test. + if (Cmp == Cond.getOperand(1).getOperand(1) && + isX86LogicalCmp(Cmp)) { + CC = Cond.getOperand(0).getOperand(0); + Chain = DAG.getNode(X86ISD::BRCOND, dl, Op.getValueType(), + Chain, Dest, CC, Cmp); + CC = Cond.getOperand(1).getOperand(0); + Cond = Cmp; + addTest = false; + } + } else { // ISD::AND + // Also, recognize the pattern generated by an FCMP_OEQ. We can emit + // two branches instead of an explicit AND instruction with a + // separate test. However, we only do this if this block doesn't + // have a fall-through edge, because this requires an explicit + // jmp when the condition is false. + if (Cmp == Cond.getOperand(1).getOperand(1) && + isX86LogicalCmp(Cmp) && + Op.getNode()->hasOneUse()) { + X86::CondCode CCode = + (X86::CondCode)Cond.getOperand(0).getConstantOperandVal(0); + CCode = X86::GetOppositeBranchCondition(CCode); + CC = DAG.getConstant(CCode, MVT::i8); + SDValue User = SDValue(*Op.getNode()->use_begin(), 0); + // Look for an unconditional branch following this conditional branch. + // We need this because we need to reverse the successors in order + // to implement FCMP_OEQ. + if (User.getOpcode() == ISD::BR) { + SDValue FalseBB = User.getOperand(1); + SDValue NewBR = + DAG.UpdateNodeOperands(User, User.getOperand(0), Dest); + assert(NewBR == User); + Dest = FalseBB; + + Chain = DAG.getNode(X86ISD::BRCOND, dl, Op.getValueType(), + Chain, Dest, CC, Cmp); + X86::CondCode CCode = + (X86::CondCode)Cond.getOperand(1).getConstantOperandVal(0); + CCode = X86::GetOppositeBranchCondition(CCode); + CC = DAG.getConstant(CCode, MVT::i8); + Cond = Cmp; + addTest = false; + } + } + } + } else if (Cond.hasOneUse() && isXor1OfSetCC(Cond)) { + // Recognize for xorb (setcc), 1 patterns. The xor inverts the condition. + // It should be transformed during dag combiner except when the condition + // is set by a arithmetics with overflow node. + X86::CondCode CCode = + (X86::CondCode)Cond.getOperand(0).getConstantOperandVal(0); + CCode = X86::GetOppositeBranchCondition(CCode); + CC = DAG.getConstant(CCode, MVT::i8); + Cond = Cond.getOperand(0).getOperand(1); + addTest = false; + } + } + + if (addTest) { + CC = DAG.getConstant(X86::COND_NE, MVT::i8); + Cond = EmitTest(Cond, X86::COND_NE, DAG); + } + return DAG.getNode(X86ISD::BRCOND, dl, Op.getValueType(), + Chain, Dest, CC, Cond); +} + + +// Lower dynamic stack allocation to _alloca call for Cygwin/Mingw targets. +// Calls to _alloca is needed to probe the stack when allocating more than 4k +// bytes in one go. Touching the stack at 4K increments is necessary to ensure +// that the guard pages used by the OS virtual memory manager are allocated in +// correct sequence. +SDValue +X86TargetLowering::LowerDYNAMIC_STACKALLOC(SDValue Op, + SelectionDAG &DAG) { + assert(Subtarget->isTargetCygMing() && + "This should be used only on Cygwin/Mingw targets"); + DebugLoc dl = Op.getDebugLoc(); + + // Get the inputs. + SDValue Chain = Op.getOperand(0); + SDValue Size = Op.getOperand(1); + // FIXME: Ensure alignment here + + SDValue Flag; + + EVT IntPtr = getPointerTy(); + EVT SPTy = Subtarget->is64Bit() ? MVT::i64 : MVT::i32; + + Chain = DAG.getCALLSEQ_START(Chain, DAG.getIntPtrConstant(0, true)); + + Chain = DAG.getCopyToReg(Chain, dl, X86::EAX, Size, Flag); + Flag = Chain.getValue(1); + + SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Flag); + SDValue Ops[] = { Chain, + DAG.getTargetExternalSymbol("_alloca", IntPtr), + DAG.getRegister(X86::EAX, IntPtr), + DAG.getRegister(X86StackPtr, SPTy), + Flag }; + Chain = DAG.getNode(X86ISD::CALL, dl, NodeTys, Ops, 5); + Flag = Chain.getValue(1); + + Chain = DAG.getCALLSEQ_END(Chain, + DAG.getIntPtrConstant(0, true), + DAG.getIntPtrConstant(0, true), + Flag); + + Chain = DAG.getCopyFromReg(Chain, dl, X86StackPtr, SPTy).getValue(1); + + SDValue Ops1[2] = { Chain.getValue(0), Chain }; + return DAG.getMergeValues(Ops1, 2, dl); +} + +SDValue +X86TargetLowering::EmitTargetCodeForMemset(SelectionDAG &DAG, DebugLoc dl, + SDValue Chain, + SDValue Dst, SDValue Src, + SDValue Size, unsigned Align, + const Value *DstSV, + uint64_t DstSVOff) { + ConstantSDNode *ConstantSize = dyn_cast(Size); + + // If not DWORD aligned or size is more than the threshold, call the library. + // The libc version is likely to be faster for these cases. It can use the + // address value and run time information about the CPU. + if ((Align & 3) != 0 || + !ConstantSize || + ConstantSize->getZExtValue() > + getSubtarget()->getMaxInlineSizeThreshold()) { + SDValue InFlag(0, 0); + + // Check to see if there is a specialized entry-point for memory zeroing. + ConstantSDNode *V = dyn_cast(Src); + + if (const char *bzeroEntry = V && + V->isNullValue() ? Subtarget->getBZeroEntry() : 0) { + EVT IntPtr = getPointerTy(); + const Type *IntPtrTy = TD->getIntPtrType(*DAG.getContext()); + TargetLowering::ArgListTy Args; + TargetLowering::ArgListEntry Entry; + Entry.Node = Dst; + Entry.Ty = IntPtrTy; + Args.push_back(Entry); + Entry.Node = Size; + Args.push_back(Entry); + std::pair CallResult = + LowerCallTo(Chain, Type::getVoidTy(*DAG.getContext()), + false, false, false, false, + 0, CallingConv::C, false, /*isReturnValueUsed=*/false, + DAG.getExternalSymbol(bzeroEntry, IntPtr), Args, DAG, dl); + return CallResult.second; + } + + // Otherwise have the target-independent code call memset. + return SDValue(); + } + + uint64_t SizeVal = ConstantSize->getZExtValue(); + SDValue InFlag(0, 0); + EVT AVT; + SDValue Count; + ConstantSDNode *ValC = dyn_cast(Src); + unsigned BytesLeft = 0; + bool TwoRepStos = false; + if (ValC) { + unsigned ValReg; + uint64_t Val = ValC->getZExtValue() & 255; + + // If the value is a constant, then we can potentially use larger sets. + switch (Align & 3) { + case 2: // WORD aligned + AVT = MVT::i16; + ValReg = X86::AX; + Val = (Val << 8) | Val; + break; + case 0: // DWORD aligned + AVT = MVT::i32; + ValReg = X86::EAX; + Val = (Val << 8) | Val; + Val = (Val << 16) | Val; + if (Subtarget->is64Bit() && ((Align & 0x7) == 0)) { // QWORD aligned + AVT = MVT::i64; + ValReg = X86::RAX; + Val = (Val << 32) | Val; + } + break; + default: // Byte aligned + AVT = MVT::i8; + ValReg = X86::AL; + Count = DAG.getIntPtrConstant(SizeVal); + break; + } + + if (AVT.bitsGT(MVT::i8)) { + unsigned UBytes = AVT.getSizeInBits() / 8; + Count = DAG.getIntPtrConstant(SizeVal / UBytes); + BytesLeft = SizeVal % UBytes; + } + + Chain = DAG.getCopyToReg(Chain, dl, ValReg, DAG.getConstant(Val, AVT), + InFlag); + InFlag = Chain.getValue(1); + } else { + AVT = MVT::i8; + Count = DAG.getIntPtrConstant(SizeVal); + Chain = DAG.getCopyToReg(Chain, dl, X86::AL, Src, InFlag); + InFlag = Chain.getValue(1); + } + + Chain = DAG.getCopyToReg(Chain, dl, Subtarget->is64Bit() ? X86::RCX : + X86::ECX, + Count, InFlag); + InFlag = Chain.getValue(1); + Chain = DAG.getCopyToReg(Chain, dl, Subtarget->is64Bit() ? X86::RDI : + X86::EDI, + Dst, InFlag); + InFlag = Chain.getValue(1); + + SDVTList Tys = DAG.getVTList(MVT::Other, MVT::Flag); + SmallVector Ops; + Ops.push_back(Chain); + Ops.push_back(DAG.getValueType(AVT)); + Ops.push_back(InFlag); + Chain = DAG.getNode(X86ISD::REP_STOS, dl, Tys, &Ops[0], Ops.size()); + + if (TwoRepStos) { + InFlag = Chain.getValue(1); + Count = Size; + EVT CVT = Count.getValueType(); + SDValue Left = DAG.getNode(ISD::AND, dl, CVT, Count, + DAG.getConstant((AVT == MVT::i64) ? 7 : 3, CVT)); + Chain = DAG.getCopyToReg(Chain, dl, (CVT == MVT::i64) ? X86::RCX : + X86::ECX, + Left, InFlag); + InFlag = Chain.getValue(1); + Tys = DAG.getVTList(MVT::Other, MVT::Flag); + Ops.clear(); + Ops.push_back(Chain); + Ops.push_back(DAG.getValueType(MVT::i8)); + Ops.push_back(InFlag); + Chain = DAG.getNode(X86ISD::REP_STOS, dl, Tys, &Ops[0], Ops.size()); + } else if (BytesLeft) { + // Handle the last 1 - 7 bytes. + unsigned Offset = SizeVal - BytesLeft; + EVT AddrVT = Dst.getValueType(); + EVT SizeVT = Size.getValueType(); + + Chain = DAG.getMemset(Chain, dl, + DAG.getNode(ISD::ADD, dl, AddrVT, Dst, + DAG.getConstant(Offset, AddrVT)), + Src, + DAG.getConstant(BytesLeft, SizeVT), + Align, DstSV, DstSVOff + Offset); + } + + // TODO: Use a Tokenfactor, as in memcpy, instead of a single chain. + return Chain; +} + +SDValue +X86TargetLowering::EmitTargetCodeForMemcpy(SelectionDAG &DAG, DebugLoc dl, + SDValue Chain, SDValue Dst, SDValue Src, + SDValue Size, unsigned Align, + bool AlwaysInline, + const Value *DstSV, uint64_t DstSVOff, + const Value *SrcSV, uint64_t SrcSVOff) { + // This requires the copy size to be a constant, preferrably + // within a subtarget-specific limit. + ConstantSDNode *ConstantSize = dyn_cast(Size); + if (!ConstantSize) + return SDValue(); + uint64_t SizeVal = ConstantSize->getZExtValue(); + if (!AlwaysInline && SizeVal > getSubtarget()->getMaxInlineSizeThreshold()) + return SDValue(); + + /// If not DWORD aligned, call the library. + if ((Align & 3) != 0) + return SDValue(); + + // DWORD aligned + EVT AVT = MVT::i32; + if (Subtarget->is64Bit() && ((Align & 0x7) == 0)) // QWORD aligned + AVT = MVT::i64; + + unsigned UBytes = AVT.getSizeInBits() / 8; + unsigned CountVal = SizeVal / UBytes; + SDValue Count = DAG.getIntPtrConstant(CountVal); + unsigned BytesLeft = SizeVal % UBytes; + + SDValue InFlag(0, 0); + Chain = DAG.getCopyToReg(Chain, dl, Subtarget->is64Bit() ? X86::RCX : + X86::ECX, + Count, InFlag); + InFlag = Chain.getValue(1); + Chain = DAG.getCopyToReg(Chain, dl, Subtarget->is64Bit() ? X86::RDI : + X86::EDI, + Dst, InFlag); + InFlag = Chain.getValue(1); + Chain = DAG.getCopyToReg(Chain, dl, Subtarget->is64Bit() ? X86::RSI : + X86::ESI, + Src, InFlag); + InFlag = Chain.getValue(1); + + SDVTList Tys = DAG.getVTList(MVT::Other, MVT::Flag); + SmallVector Ops; + Ops.push_back(Chain); + Ops.push_back(DAG.getValueType(AVT)); + Ops.push_back(InFlag); + SDValue RepMovs = DAG.getNode(X86ISD::REP_MOVS, dl, Tys, &Ops[0], Ops.size()); + + SmallVector Results; + Results.push_back(RepMovs); + if (BytesLeft) { + // Handle the last 1 - 7 bytes. + unsigned Offset = SizeVal - BytesLeft; + EVT DstVT = Dst.getValueType(); + EVT SrcVT = Src.getValueType(); + EVT SizeVT = Size.getValueType(); + Results.push_back(DAG.getMemcpy(Chain, dl, + DAG.getNode(ISD::ADD, dl, DstVT, Dst, + DAG.getConstant(Offset, DstVT)), + DAG.getNode(ISD::ADD, dl, SrcVT, Src, + DAG.getConstant(Offset, SrcVT)), + DAG.getConstant(BytesLeft, SizeVT), + Align, AlwaysInline, + DstSV, DstSVOff + Offset, + SrcSV, SrcSVOff + Offset)); + } + + return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, + &Results[0], Results.size()); +} + +SDValue X86TargetLowering::LowerVASTART(SDValue Op, SelectionDAG &DAG) { + const Value *SV = cast(Op.getOperand(2))->getValue(); + DebugLoc dl = Op.getDebugLoc(); + + if (!Subtarget->is64Bit()) { + // vastart just stores the address of the VarArgsFrameIndex slot into the + // memory location argument. + SDValue FR = DAG.getFrameIndex(VarArgsFrameIndex, getPointerTy()); + return DAG.getStore(Op.getOperand(0), dl, FR, Op.getOperand(1), SV, 0); + } + + // __va_list_tag: + // gp_offset (0 - 6 * 8) + // fp_offset (48 - 48 + 8 * 16) + // overflow_arg_area (point to parameters coming in memory). + // reg_save_area + SmallVector MemOps; + SDValue FIN = Op.getOperand(1); + // Store gp_offset + SDValue Store = DAG.getStore(Op.getOperand(0), dl, + DAG.getConstant(VarArgsGPOffset, MVT::i32), + FIN, SV, 0); + MemOps.push_back(Store); + + // Store fp_offset + FIN = DAG.getNode(ISD::ADD, dl, getPointerTy(), + FIN, DAG.getIntPtrConstant(4)); + Store = DAG.getStore(Op.getOperand(0), dl, + DAG.getConstant(VarArgsFPOffset, MVT::i32), + FIN, SV, 0); + MemOps.push_back(Store); + + // Store ptr to overflow_arg_area + FIN = DAG.getNode(ISD::ADD, dl, getPointerTy(), + FIN, DAG.getIntPtrConstant(4)); + SDValue OVFIN = DAG.getFrameIndex(VarArgsFrameIndex, getPointerTy()); + Store = DAG.getStore(Op.getOperand(0), dl, OVFIN, FIN, SV, 0); + MemOps.push_back(Store); + + // Store ptr to reg_save_area. + FIN = DAG.getNode(ISD::ADD, dl, getPointerTy(), + FIN, DAG.getIntPtrConstant(8)); + SDValue RSFIN = DAG.getFrameIndex(RegSaveFrameIndex, getPointerTy()); + Store = DAG.getStore(Op.getOperand(0), dl, RSFIN, FIN, SV, 0); + MemOps.push_back(Store); + return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, + &MemOps[0], MemOps.size()); +} + +SDValue X86TargetLowering::LowerVAARG(SDValue Op, SelectionDAG &DAG) { + // X86-64 va_list is a struct { i32, i32, i8*, i8* }. + assert(Subtarget->is64Bit() && "This code only handles 64-bit va_arg!"); + SDValue Chain = Op.getOperand(0); + SDValue SrcPtr = Op.getOperand(1); + SDValue SrcSV = Op.getOperand(2); + + llvm_report_error("VAArgInst is not yet implemented for x86-64!"); + return SDValue(); +} + +SDValue X86TargetLowering::LowerVACOPY(SDValue Op, SelectionDAG &DAG) { + // X86-64 va_list is a struct { i32, i32, i8*, i8* }. + assert(Subtarget->is64Bit() && "This code only handles 64-bit va_copy!"); + SDValue Chain = Op.getOperand(0); + SDValue DstPtr = Op.getOperand(1); + SDValue SrcPtr = Op.getOperand(2); + const Value *DstSV = cast(Op.getOperand(3))->getValue(); + const Value *SrcSV = cast(Op.getOperand(4))->getValue(); + DebugLoc dl = Op.getDebugLoc(); + + return DAG.getMemcpy(Chain, dl, DstPtr, SrcPtr, + DAG.getIntPtrConstant(24), 8, false, + DstSV, 0, SrcSV, 0); +} + +SDValue +X86TargetLowering::LowerINTRINSIC_WO_CHAIN(SDValue Op, SelectionDAG &DAG) { + DebugLoc dl = Op.getDebugLoc(); + unsigned IntNo = cast(Op.getOperand(0))->getZExtValue(); + switch (IntNo) { + default: return SDValue(); // Don't custom lower most intrinsics. + // Comparison intrinsics. + case Intrinsic::x86_sse_comieq_ss: + case Intrinsic::x86_sse_comilt_ss: + case Intrinsic::x86_sse_comile_ss: + case Intrinsic::x86_sse_comigt_ss: + case Intrinsic::x86_sse_comige_ss: + case Intrinsic::x86_sse_comineq_ss: + case Intrinsic::x86_sse_ucomieq_ss: + case Intrinsic::x86_sse_ucomilt_ss: + case Intrinsic::x86_sse_ucomile_ss: + case Intrinsic::x86_sse_ucomigt_ss: + case Intrinsic::x86_sse_ucomige_ss: + case Intrinsic::x86_sse_ucomineq_ss: + case Intrinsic::x86_sse2_comieq_sd: + case Intrinsic::x86_sse2_comilt_sd: + case Intrinsic::x86_sse2_comile_sd: + case Intrinsic::x86_sse2_comigt_sd: + case Intrinsic::x86_sse2_comige_sd: + case Intrinsic::x86_sse2_comineq_sd: + case Intrinsic::x86_sse2_ucomieq_sd: + case Intrinsic::x86_sse2_ucomilt_sd: + case Intrinsic::x86_sse2_ucomile_sd: + case Intrinsic::x86_sse2_ucomigt_sd: + case Intrinsic::x86_sse2_ucomige_sd: + case Intrinsic::x86_sse2_ucomineq_sd: { + unsigned Opc = 0; + ISD::CondCode CC = ISD::SETCC_INVALID; + switch (IntNo) { + default: break; + case Intrinsic::x86_sse_comieq_ss: + case Intrinsic::x86_sse2_comieq_sd: + Opc = X86ISD::COMI; + CC = ISD::SETEQ; + break; + case Intrinsic::x86_sse_comilt_ss: + case Intrinsic::x86_sse2_comilt_sd: + Opc = X86ISD::COMI; + CC = ISD::SETLT; + break; + case Intrinsic::x86_sse_comile_ss: + case Intrinsic::x86_sse2_comile_sd: + Opc = X86ISD::COMI; + CC = ISD::SETLE; + break; + case Intrinsic::x86_sse_comigt_ss: + case Intrinsic::x86_sse2_comigt_sd: + Opc = X86ISD::COMI; + CC = ISD::SETGT; + break; + case Intrinsic::x86_sse_comige_ss: + case Intrinsic::x86_sse2_comige_sd: + Opc = X86ISD::COMI; + CC = ISD::SETGE; + break; + case Intrinsic::x86_sse_comineq_ss: + case Intrinsic::x86_sse2_comineq_sd: + Opc = X86ISD::COMI; + CC = ISD::SETNE; + break; + case Intrinsic::x86_sse_ucomieq_ss: + case Intrinsic::x86_sse2_ucomieq_sd: + Opc = X86ISD::UCOMI; + CC = ISD::SETEQ; + break; + case Intrinsic::x86_sse_ucomilt_ss: + case Intrinsic::x86_sse2_ucomilt_sd: + Opc = X86ISD::UCOMI; + CC = ISD::SETLT; + break; + case Intrinsic::x86_sse_ucomile_ss: + case Intrinsic::x86_sse2_ucomile_sd: + Opc = X86ISD::UCOMI; + CC = ISD::SETLE; + break; + case Intrinsic::x86_sse_ucomigt_ss: + case Intrinsic::x86_sse2_ucomigt_sd: + Opc = X86ISD::UCOMI; + CC = ISD::SETGT; + break; + case Intrinsic::x86_sse_ucomige_ss: + case Intrinsic::x86_sse2_ucomige_sd: + Opc = X86ISD::UCOMI; + CC = ISD::SETGE; + break; + case Intrinsic::x86_sse_ucomineq_ss: + case Intrinsic::x86_sse2_ucomineq_sd: + Opc = X86ISD::UCOMI; + CC = ISD::SETNE; + break; + } + + SDValue LHS = Op.getOperand(1); + SDValue RHS = Op.getOperand(2); + unsigned X86CC = TranslateX86CC(CC, true, LHS, RHS, DAG); + assert(X86CC != X86::COND_INVALID && "Unexpected illegal condition!"); + SDValue Cond = DAG.getNode(Opc, dl, MVT::i32, LHS, RHS); + SDValue SetCC = DAG.getNode(X86ISD::SETCC, dl, MVT::i8, + DAG.getConstant(X86CC, MVT::i8), Cond); + return DAG.getNode(ISD::ZERO_EXTEND, dl, MVT::i32, SetCC); + } + // ptest intrinsics. The intrinsic these come from are designed to return + // an integer value, not just an instruction so lower it to the ptest + // pattern and a setcc for the result. + case Intrinsic::x86_sse41_ptestz: + case Intrinsic::x86_sse41_ptestc: + case Intrinsic::x86_sse41_ptestnzc:{ + unsigned X86CC = 0; + switch (IntNo) { + default: llvm_unreachable("Bad fallthrough in Intrinsic lowering."); + case Intrinsic::x86_sse41_ptestz: + // ZF = 1 + X86CC = X86::COND_E; + break; + case Intrinsic::x86_sse41_ptestc: + // CF = 1 + X86CC = X86::COND_B; + break; + case Intrinsic::x86_sse41_ptestnzc: + // ZF and CF = 0 + X86CC = X86::COND_A; + break; + } + + SDValue LHS = Op.getOperand(1); + SDValue RHS = Op.getOperand(2); + SDValue Test = DAG.getNode(X86ISD::PTEST, dl, MVT::i32, LHS, RHS); + SDValue CC = DAG.getConstant(X86CC, MVT::i8); + SDValue SetCC = DAG.getNode(X86ISD::SETCC, dl, MVT::i8, CC, Test); + return DAG.getNode(ISD::ZERO_EXTEND, dl, MVT::i32, SetCC); + } + + // Fix vector shift instructions where the last operand is a non-immediate + // i32 value. + case Intrinsic::x86_sse2_pslli_w: + case Intrinsic::x86_sse2_pslli_d: + case Intrinsic::x86_sse2_pslli_q: + case Intrinsic::x86_sse2_psrli_w: + case Intrinsic::x86_sse2_psrli_d: + case Intrinsic::x86_sse2_psrli_q: + case Intrinsic::x86_sse2_psrai_w: + case Intrinsic::x86_sse2_psrai_d: + case Intrinsic::x86_mmx_pslli_w: + case Intrinsic::x86_mmx_pslli_d: + case Intrinsic::x86_mmx_pslli_q: + case Intrinsic::x86_mmx_psrli_w: + case Intrinsic::x86_mmx_psrli_d: + case Intrinsic::x86_mmx_psrli_q: + case Intrinsic::x86_mmx_psrai_w: + case Intrinsic::x86_mmx_psrai_d: { + SDValue ShAmt = Op.getOperand(2); + if (isa(ShAmt)) + return SDValue(); + + unsigned NewIntNo = 0; + EVT ShAmtVT = MVT::v4i32; + switch (IntNo) { + case Intrinsic::x86_sse2_pslli_w: + NewIntNo = Intrinsic::x86_sse2_psll_w; + break; + case Intrinsic::x86_sse2_pslli_d: + NewIntNo = Intrinsic::x86_sse2_psll_d; + break; + case Intrinsic::x86_sse2_pslli_q: + NewIntNo = Intrinsic::x86_sse2_psll_q; + break; + case Intrinsic::x86_sse2_psrli_w: + NewIntNo = Intrinsic::x86_sse2_psrl_w; + break; + case Intrinsic::x86_sse2_psrli_d: + NewIntNo = Intrinsic::x86_sse2_psrl_d; + break; + case Intrinsic::x86_sse2_psrli_q: + NewIntNo = Intrinsic::x86_sse2_psrl_q; + break; + case Intrinsic::x86_sse2_psrai_w: + NewIntNo = Intrinsic::x86_sse2_psra_w; + break; + case Intrinsic::x86_sse2_psrai_d: + NewIntNo = Intrinsic::x86_sse2_psra_d; + break; + default: { + ShAmtVT = MVT::v2i32; + switch (IntNo) { + case Intrinsic::x86_mmx_pslli_w: + NewIntNo = Intrinsic::x86_mmx_psll_w; + break; + case Intrinsic::x86_mmx_pslli_d: + NewIntNo = Intrinsic::x86_mmx_psll_d; + break; + case Intrinsic::x86_mmx_pslli_q: + NewIntNo = Intrinsic::x86_mmx_psll_q; + break; + case Intrinsic::x86_mmx_psrli_w: + NewIntNo = Intrinsic::x86_mmx_psrl_w; + break; + case Intrinsic::x86_mmx_psrli_d: + NewIntNo = Intrinsic::x86_mmx_psrl_d; + break; + case Intrinsic::x86_mmx_psrli_q: + NewIntNo = Intrinsic::x86_mmx_psrl_q; + break; + case Intrinsic::x86_mmx_psrai_w: + NewIntNo = Intrinsic::x86_mmx_psra_w; + break; + case Intrinsic::x86_mmx_psrai_d: + NewIntNo = Intrinsic::x86_mmx_psra_d; + break; + default: llvm_unreachable("Impossible intrinsic"); // Can't reach here. + } + break; + } + } + + // The vector shift intrinsics with scalars uses 32b shift amounts but + // the sse2/mmx shift instructions reads 64 bits. Set the upper 32 bits + // to be zero. + SDValue ShOps[4]; + ShOps[0] = ShAmt; + ShOps[1] = DAG.getConstant(0, MVT::i32); + if (ShAmtVT == MVT::v4i32) { + ShOps[2] = DAG.getUNDEF(MVT::i32); + ShOps[3] = DAG.getUNDEF(MVT::i32); + ShAmt = DAG.getNode(ISD::BUILD_VECTOR, dl, ShAmtVT, &ShOps[0], 4); + } else { + ShAmt = DAG.getNode(ISD::BUILD_VECTOR, dl, ShAmtVT, &ShOps[0], 2); + } + + EVT VT = Op.getValueType(); + ShAmt = DAG.getNode(ISD::BIT_CONVERT, dl, VT, ShAmt); + return DAG.getNode(ISD::INTRINSIC_WO_CHAIN, dl, VT, + DAG.getConstant(NewIntNo, MVT::i32), + Op.getOperand(1), ShAmt); + } + } +} + +SDValue X86TargetLowering::LowerRETURNADDR(SDValue Op, SelectionDAG &DAG) { + unsigned Depth = cast(Op.getOperand(0))->getZExtValue(); + DebugLoc dl = Op.getDebugLoc(); + + if (Depth > 0) { + SDValue FrameAddr = LowerFRAMEADDR(Op, DAG); + SDValue Offset = + DAG.getConstant(TD->getPointerSize(), + Subtarget->is64Bit() ? MVT::i64 : MVT::i32); + return DAG.getLoad(getPointerTy(), dl, DAG.getEntryNode(), + DAG.getNode(ISD::ADD, dl, getPointerTy(), + FrameAddr, Offset), + NULL, 0); + } + + // Just load the return address. + SDValue RetAddrFI = getReturnAddressFrameIndex(DAG); + return DAG.getLoad(getPointerTy(), dl, DAG.getEntryNode(), + RetAddrFI, NULL, 0); +} + +SDValue X86TargetLowering::LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) { + MachineFrameInfo *MFI = DAG.getMachineFunction().getFrameInfo(); + MFI->setFrameAddressIsTaken(true); + EVT VT = Op.getValueType(); + DebugLoc dl = Op.getDebugLoc(); // FIXME probably not meaningful + unsigned Depth = cast(Op.getOperand(0))->getZExtValue(); + unsigned FrameReg = Subtarget->is64Bit() ? X86::RBP : X86::EBP; + SDValue FrameAddr = DAG.getCopyFromReg(DAG.getEntryNode(), dl, FrameReg, VT); + while (Depth--) + FrameAddr = DAG.getLoad(VT, dl, DAG.getEntryNode(), FrameAddr, NULL, 0); + return FrameAddr; +} + +SDValue X86TargetLowering::LowerFRAME_TO_ARGS_OFFSET(SDValue Op, + SelectionDAG &DAG) { + return DAG.getIntPtrConstant(2*TD->getPointerSize()); +} + +SDValue X86TargetLowering::LowerEH_RETURN(SDValue Op, SelectionDAG &DAG) +{ + MachineFunction &MF = DAG.getMachineFunction(); + SDValue Chain = Op.getOperand(0); + SDValue Offset = Op.getOperand(1); + SDValue Handler = Op.getOperand(2); + DebugLoc dl = Op.getDebugLoc(); + + SDValue Frame = DAG.getRegister(Subtarget->is64Bit() ? X86::RBP : X86::EBP, + getPointerTy()); + unsigned StoreAddrReg = (Subtarget->is64Bit() ? X86::RCX : X86::ECX); + + SDValue StoreAddr = DAG.getNode(ISD::SUB, dl, getPointerTy(), Frame, + DAG.getIntPtrConstant(-TD->getPointerSize())); + StoreAddr = DAG.getNode(ISD::ADD, dl, getPointerTy(), StoreAddr, Offset); + Chain = DAG.getStore(Chain, dl, Handler, StoreAddr, NULL, 0); + Chain = DAG.getCopyToReg(Chain, dl, StoreAddrReg, StoreAddr); + MF.getRegInfo().addLiveOut(StoreAddrReg); + + return DAG.getNode(X86ISD::EH_RETURN, dl, + MVT::Other, + Chain, DAG.getRegister(StoreAddrReg, getPointerTy())); +} + +SDValue X86TargetLowering::LowerTRAMPOLINE(SDValue Op, + SelectionDAG &DAG) { + SDValue Root = Op.getOperand(0); + SDValue Trmp = Op.getOperand(1); // trampoline + SDValue FPtr = Op.getOperand(2); // nested function + SDValue Nest = Op.getOperand(3); // 'nest' parameter value + DebugLoc dl = Op.getDebugLoc(); + + const Value *TrmpAddr = cast(Op.getOperand(4))->getValue(); + + const X86InstrInfo *TII = + ((X86TargetMachine&)getTargetMachine()).getInstrInfo(); + + if (Subtarget->is64Bit()) { + SDValue OutChains[6]; + + // Large code-model. + + const unsigned char JMP64r = TII->getBaseOpcodeFor(X86::JMP64r); + const unsigned char MOV64ri = TII->getBaseOpcodeFor(X86::MOV64ri); + + const unsigned char N86R10 = RegInfo->getX86RegNum(X86::R10); + const unsigned char N86R11 = RegInfo->getX86RegNum(X86::R11); + + const unsigned char REX_WB = 0x40 | 0x08 | 0x01; // REX prefix + + // Load the pointer to the nested function into R11. + unsigned OpCode = ((MOV64ri | N86R11) << 8) | REX_WB; // movabsq r11 + SDValue Addr = Trmp; + OutChains[0] = DAG.getStore(Root, dl, DAG.getConstant(OpCode, MVT::i16), + Addr, TrmpAddr, 0); + + Addr = DAG.getNode(ISD::ADD, dl, MVT::i64, Trmp, + DAG.getConstant(2, MVT::i64)); + OutChains[1] = DAG.getStore(Root, dl, FPtr, Addr, TrmpAddr, 2, false, 2); + + // Load the 'nest' parameter value into R10. + // R10 is specified in X86CallingConv.td + OpCode = ((MOV64ri | N86R10) << 8) | REX_WB; // movabsq r10 + Addr = DAG.getNode(ISD::ADD, dl, MVT::i64, Trmp, + DAG.getConstant(10, MVT::i64)); + OutChains[2] = DAG.getStore(Root, dl, DAG.getConstant(OpCode, MVT::i16), + Addr, TrmpAddr, 10); + + Addr = DAG.getNode(ISD::ADD, dl, MVT::i64, Trmp, + DAG.getConstant(12, MVT::i64)); + OutChains[3] = DAG.getStore(Root, dl, Nest, Addr, TrmpAddr, 12, false, 2); + + // Jump to the nested function. + OpCode = (JMP64r << 8) | REX_WB; // jmpq *... + Addr = DAG.getNode(ISD::ADD, dl, MVT::i64, Trmp, + DAG.getConstant(20, MVT::i64)); + OutChains[4] = DAG.getStore(Root, dl, DAG.getConstant(OpCode, MVT::i16), + Addr, TrmpAddr, 20); + + unsigned char ModRM = N86R11 | (4 << 3) | (3 << 6); // ...r11 + Addr = DAG.getNode(ISD::ADD, dl, MVT::i64, Trmp, + DAG.getConstant(22, MVT::i64)); + OutChains[5] = DAG.getStore(Root, dl, DAG.getConstant(ModRM, MVT::i8), Addr, + TrmpAddr, 22); + + SDValue Ops[] = + { Trmp, DAG.getNode(ISD::TokenFactor, dl, MVT::Other, OutChains, 6) }; + return DAG.getMergeValues(Ops, 2, dl); + } else { + const Function *Func = + cast(cast(Op.getOperand(5))->getValue()); + CallingConv::ID CC = Func->getCallingConv(); + unsigned NestReg; + + switch (CC) { + default: + llvm_unreachable("Unsupported calling convention"); + case CallingConv::C: + case CallingConv::X86_StdCall: { + // Pass 'nest' parameter in ECX. + // Must be kept in sync with X86CallingConv.td + NestReg = X86::ECX; + + // Check that ECX wasn't needed by an 'inreg' parameter. + const FunctionType *FTy = Func->getFunctionType(); + const AttrListPtr &Attrs = Func->getAttributes(); + + if (!Attrs.isEmpty() && !Func->isVarArg()) { + unsigned InRegCount = 0; + unsigned Idx = 1; + + for (FunctionType::param_iterator I = FTy->param_begin(), + E = FTy->param_end(); I != E; ++I, ++Idx) + if (Attrs.paramHasAttr(Idx, Attribute::InReg)) + // FIXME: should only count parameters that are lowered to integers. + InRegCount += (TD->getTypeSizeInBits(*I) + 31) / 32; + + if (InRegCount > 2) { + llvm_report_error("Nest register in use - reduce number of inreg parameters!"); + } + } + break; + } + case CallingConv::X86_FastCall: + case CallingConv::Fast: + // Pass 'nest' parameter in EAX. + // Must be kept in sync with X86CallingConv.td + NestReg = X86::EAX; + break; + } + + SDValue OutChains[4]; + SDValue Addr, Disp; + + Addr = DAG.getNode(ISD::ADD, dl, MVT::i32, Trmp, + DAG.getConstant(10, MVT::i32)); + Disp = DAG.getNode(ISD::SUB, dl, MVT::i32, FPtr, Addr); + + const unsigned char MOV32ri = TII->getBaseOpcodeFor(X86::MOV32ri); + const unsigned char N86Reg = RegInfo->getX86RegNum(NestReg); + OutChains[0] = DAG.getStore(Root, dl, + DAG.getConstant(MOV32ri|N86Reg, MVT::i8), + Trmp, TrmpAddr, 0); + + Addr = DAG.getNode(ISD::ADD, dl, MVT::i32, Trmp, + DAG.getConstant(1, MVT::i32)); + OutChains[1] = DAG.getStore(Root, dl, Nest, Addr, TrmpAddr, 1, false, 1); + + const unsigned char JMP = TII->getBaseOpcodeFor(X86::JMP); + Addr = DAG.getNode(ISD::ADD, dl, MVT::i32, Trmp, + DAG.getConstant(5, MVT::i32)); + OutChains[2] = DAG.getStore(Root, dl, DAG.getConstant(JMP, MVT::i8), Addr, + TrmpAddr, 5, false, 1); + + Addr = DAG.getNode(ISD::ADD, dl, MVT::i32, Trmp, + DAG.getConstant(6, MVT::i32)); + OutChains[3] = DAG.getStore(Root, dl, Disp, Addr, TrmpAddr, 6, false, 1); + + SDValue Ops[] = + { Trmp, DAG.getNode(ISD::TokenFactor, dl, MVT::Other, OutChains, 4) }; + return DAG.getMergeValues(Ops, 2, dl); + } +} + +SDValue X86TargetLowering::LowerFLT_ROUNDS_(SDValue Op, SelectionDAG &DAG) { + /* + The rounding mode is in bits 11:10 of FPSR, and has the following + settings: + 00 Round to nearest + 01 Round to -inf + 10 Round to +inf + 11 Round to 0 + + FLT_ROUNDS, on the other hand, expects the following: + -1 Undefined + 0 Round to 0 + 1 Round to nearest + 2 Round to +inf + 3 Round to -inf + + To perform the conversion, we do: + (((((FPSR & 0x800) >> 11) | ((FPSR & 0x400) >> 9)) + 1) & 3) + */ + + MachineFunction &MF = DAG.getMachineFunction(); + const TargetMachine &TM = MF.getTarget(); + const TargetFrameInfo &TFI = *TM.getFrameInfo(); + unsigned StackAlignment = TFI.getStackAlignment(); + EVT VT = Op.getValueType(); + DebugLoc dl = Op.getDebugLoc(); + + // Save FP Control Word to stack slot + int SSFI = MF.getFrameInfo()->CreateStackObject(2, StackAlignment, false); + SDValue StackSlot = DAG.getFrameIndex(SSFI, getPointerTy()); + + SDValue Chain = DAG.getNode(X86ISD::FNSTCW16m, dl, MVT::Other, + DAG.getEntryNode(), StackSlot); + + // Load FP Control Word from stack slot + SDValue CWD = DAG.getLoad(MVT::i16, dl, Chain, StackSlot, NULL, 0); + + // Transform as necessary + SDValue CWD1 = + DAG.getNode(ISD::SRL, dl, MVT::i16, + DAG.getNode(ISD::AND, dl, MVT::i16, + CWD, DAG.getConstant(0x800, MVT::i16)), + DAG.getConstant(11, MVT::i8)); + SDValue CWD2 = + DAG.getNode(ISD::SRL, dl, MVT::i16, + DAG.getNode(ISD::AND, dl, MVT::i16, + CWD, DAG.getConstant(0x400, MVT::i16)), + DAG.getConstant(9, MVT::i8)); + + SDValue RetVal = + DAG.getNode(ISD::AND, dl, MVT::i16, + DAG.getNode(ISD::ADD, dl, MVT::i16, + DAG.getNode(ISD::OR, dl, MVT::i16, CWD1, CWD2), + DAG.getConstant(1, MVT::i16)), + DAG.getConstant(3, MVT::i16)); + + + return DAG.getNode((VT.getSizeInBits() < 16 ? + ISD::TRUNCATE : ISD::ZERO_EXTEND), dl, VT, RetVal); +} + +SDValue X86TargetLowering::LowerCTLZ(SDValue Op, SelectionDAG &DAG) { + EVT VT = Op.getValueType(); + EVT OpVT = VT; + unsigned NumBits = VT.getSizeInBits(); + DebugLoc dl = Op.getDebugLoc(); + + Op = Op.getOperand(0); + if (VT == MVT::i8) { + // Zero extend to i32 since there is not an i8 bsr. + OpVT = MVT::i32; + Op = DAG.getNode(ISD::ZERO_EXTEND, dl, OpVT, Op); + } + + // Issue a bsr (scan bits in reverse) which also sets EFLAGS. + SDVTList VTs = DAG.getVTList(OpVT, MVT::i32); + Op = DAG.getNode(X86ISD::BSR, dl, VTs, Op); + + // If src is zero (i.e. bsr sets ZF), returns NumBits. + SmallVector Ops; + Ops.push_back(Op); + Ops.push_back(DAG.getConstant(NumBits+NumBits-1, OpVT)); + Ops.push_back(DAG.getConstant(X86::COND_E, MVT::i8)); + Ops.push_back(Op.getValue(1)); + Op = DAG.getNode(X86ISD::CMOV, dl, OpVT, &Ops[0], 4); + + // Finally xor with NumBits-1. + Op = DAG.getNode(ISD::XOR, dl, OpVT, Op, DAG.getConstant(NumBits-1, OpVT)); + + if (VT == MVT::i8) + Op = DAG.getNode(ISD::TRUNCATE, dl, MVT::i8, Op); + return Op; +} + +SDValue X86TargetLowering::LowerCTTZ(SDValue Op, SelectionDAG &DAG) { + EVT VT = Op.getValueType(); + EVT OpVT = VT; + unsigned NumBits = VT.getSizeInBits(); + DebugLoc dl = Op.getDebugLoc(); + + Op = Op.getOperand(0); + if (VT == MVT::i8) { + OpVT = MVT::i32; + Op = DAG.getNode(ISD::ZERO_EXTEND, dl, OpVT, Op); + } + + // Issue a bsf (scan bits forward) which also sets EFLAGS. + SDVTList VTs = DAG.getVTList(OpVT, MVT::i32); + Op = DAG.getNode(X86ISD::BSF, dl, VTs, Op); + + // If src is zero (i.e. bsf sets ZF), returns NumBits. + SmallVector Ops; + Ops.push_back(Op); + Ops.push_back(DAG.getConstant(NumBits, OpVT)); + Ops.push_back(DAG.getConstant(X86::COND_E, MVT::i8)); + Ops.push_back(Op.getValue(1)); + Op = DAG.getNode(X86ISD::CMOV, dl, OpVT, &Ops[0], 4); + + if (VT == MVT::i8) + Op = DAG.getNode(ISD::TRUNCATE, dl, MVT::i8, Op); + return Op; +} + +SDValue X86TargetLowering::LowerMUL_V2I64(SDValue Op, SelectionDAG &DAG) { + EVT VT = Op.getValueType(); + assert(VT == MVT::v2i64 && "Only know how to lower V2I64 multiply"); + DebugLoc dl = Op.getDebugLoc(); + + // ulong2 Ahi = __builtin_ia32_psrlqi128( a, 32); + // ulong2 Bhi = __builtin_ia32_psrlqi128( b, 32); + // ulong2 AloBlo = __builtin_ia32_pmuludq128( a, b ); + // ulong2 AloBhi = __builtin_ia32_pmuludq128( a, Bhi ); + // ulong2 AhiBlo = __builtin_ia32_pmuludq128( Ahi, b ); + // + // AloBhi = __builtin_ia32_psllqi128( AloBhi, 32 ); + // AhiBlo = __builtin_ia32_psllqi128( AhiBlo, 32 ); + // return AloBlo + AloBhi + AhiBlo; + + SDValue A = Op.getOperand(0); + SDValue B = Op.getOperand(1); + + SDValue Ahi = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, dl, VT, + DAG.getConstant(Intrinsic::x86_sse2_psrli_q, MVT::i32), + A, DAG.getConstant(32, MVT::i32)); + SDValue Bhi = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, dl, VT, + DAG.getConstant(Intrinsic::x86_sse2_psrli_q, MVT::i32), + B, DAG.getConstant(32, MVT::i32)); + SDValue AloBlo = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, dl, VT, + DAG.getConstant(Intrinsic::x86_sse2_pmulu_dq, MVT::i32), + A, B); + SDValue AloBhi = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, dl, VT, + DAG.getConstant(Intrinsic::x86_sse2_pmulu_dq, MVT::i32), + A, Bhi); + SDValue AhiBlo = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, dl, VT, + DAG.getConstant(Intrinsic::x86_sse2_pmulu_dq, MVT::i32), + Ahi, B); + AloBhi = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, dl, VT, + DAG.getConstant(Intrinsic::x86_sse2_pslli_q, MVT::i32), + AloBhi, DAG.getConstant(32, MVT::i32)); + AhiBlo = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, dl, VT, + DAG.getConstant(Intrinsic::x86_sse2_pslli_q, MVT::i32), + AhiBlo, DAG.getConstant(32, MVT::i32)); + SDValue Res = DAG.getNode(ISD::ADD, dl, VT, AloBlo, AloBhi); + Res = DAG.getNode(ISD::ADD, dl, VT, Res, AhiBlo); + return Res; +} + + +SDValue X86TargetLowering::LowerXALUO(SDValue Op, SelectionDAG &DAG) { + // Lower the "add/sub/mul with overflow" instruction into a regular ins plus + // a "setcc" instruction that checks the overflow flag. The "brcond" lowering + // looks for this combo and may remove the "setcc" instruction if the "setcc" + // has only one use. + SDNode *N = Op.getNode(); + SDValue LHS = N->getOperand(0); + SDValue RHS = N->getOperand(1); + unsigned BaseOp = 0; + unsigned Cond = 0; + DebugLoc dl = Op.getDebugLoc(); + + switch (Op.getOpcode()) { + default: llvm_unreachable("Unknown ovf instruction!"); + case ISD::SADDO: + // A subtract of one will be selected as a INC. Note that INC doesn't + // set CF, so we can't do this for UADDO. + if (ConstantSDNode *C = dyn_cast(Op)) + if (C->getAPIntValue() == 1) { + BaseOp = X86ISD::INC; + Cond = X86::COND_O; + break; + } + BaseOp = X86ISD::ADD; + Cond = X86::COND_O; + break; + case ISD::UADDO: + BaseOp = X86ISD::ADD; + Cond = X86::COND_B; + break; + case ISD::SSUBO: + // A subtract of one will be selected as a DEC. Note that DEC doesn't + // set CF, so we can't do this for USUBO. + if (ConstantSDNode *C = dyn_cast(Op)) + if (C->getAPIntValue() == 1) { + BaseOp = X86ISD::DEC; + Cond = X86::COND_O; + break; + } + BaseOp = X86ISD::SUB; + Cond = X86::COND_O; + break; + case ISD::USUBO: + BaseOp = X86ISD::SUB; + Cond = X86::COND_B; + break; + case ISD::SMULO: + BaseOp = X86ISD::SMUL; + Cond = X86::COND_O; + break; + case ISD::UMULO: + BaseOp = X86ISD::UMUL; + Cond = X86::COND_B; + break; + } + + // Also sets EFLAGS. + SDVTList VTs = DAG.getVTList(N->getValueType(0), MVT::i32); + SDValue Sum = DAG.getNode(BaseOp, dl, VTs, LHS, RHS); + + SDValue SetCC = + DAG.getNode(X86ISD::SETCC, dl, N->getValueType(1), + DAG.getConstant(Cond, MVT::i32), SDValue(Sum.getNode(), 1)); + + DAG.ReplaceAllUsesOfValueWith(SDValue(N, 1), SetCC); + return Sum; +} + +SDValue X86TargetLowering::LowerCMP_SWAP(SDValue Op, SelectionDAG &DAG) { + EVT T = Op.getValueType(); + DebugLoc dl = Op.getDebugLoc(); + unsigned Reg = 0; + unsigned size = 0; + switch(T.getSimpleVT().SimpleTy) { + default: + assert(false && "Invalid value type!"); + case MVT::i8: Reg = X86::AL; size = 1; break; + case MVT::i16: Reg = X86::AX; size = 2; break; + case MVT::i32: Reg = X86::EAX; size = 4; break; + case MVT::i64: + assert(Subtarget->is64Bit() && "Node not type legal!"); + Reg = X86::RAX; size = 8; + break; + } + SDValue cpIn = DAG.getCopyToReg(Op.getOperand(0), dl, Reg, + Op.getOperand(2), SDValue()); + SDValue Ops[] = { cpIn.getValue(0), + Op.getOperand(1), + Op.getOperand(3), + DAG.getTargetConstant(size, MVT::i8), + cpIn.getValue(1) }; + SDVTList Tys = DAG.getVTList(MVT::Other, MVT::Flag); + SDValue Result = DAG.getNode(X86ISD::LCMPXCHG_DAG, dl, Tys, Ops, 5); + SDValue cpOut = + DAG.getCopyFromReg(Result.getValue(0), dl, Reg, T, Result.getValue(1)); + return cpOut; +} + +SDValue X86TargetLowering::LowerREADCYCLECOUNTER(SDValue Op, + SelectionDAG &DAG) { + assert(Subtarget->is64Bit() && "Result not type legalized?"); + SDVTList Tys = DAG.getVTList(MVT::Other, MVT::Flag); + SDValue TheChain = Op.getOperand(0); + DebugLoc dl = Op.getDebugLoc(); + SDValue rd = DAG.getNode(X86ISD::RDTSC_DAG, dl, Tys, &TheChain, 1); + SDValue rax = DAG.getCopyFromReg(rd, dl, X86::RAX, MVT::i64, rd.getValue(1)); + SDValue rdx = DAG.getCopyFromReg(rax.getValue(1), dl, X86::RDX, MVT::i64, + rax.getValue(2)); + SDValue Tmp = DAG.getNode(ISD::SHL, dl, MVT::i64, rdx, + DAG.getConstant(32, MVT::i8)); + SDValue Ops[] = { + DAG.getNode(ISD::OR, dl, MVT::i64, rax, Tmp), + rdx.getValue(1) + }; + return DAG.getMergeValues(Ops, 2, dl); +} + +SDValue X86TargetLowering::LowerLOAD_SUB(SDValue Op, SelectionDAG &DAG) { + SDNode *Node = Op.getNode(); + DebugLoc dl = Node->getDebugLoc(); + EVT T = Node->getValueType(0); + SDValue negOp = DAG.getNode(ISD::SUB, dl, T, + DAG.getConstant(0, T), Node->getOperand(2)); + return DAG.getAtomic(ISD::ATOMIC_LOAD_ADD, dl, + cast(Node)->getMemoryVT(), + Node->getOperand(0), + Node->getOperand(1), negOp, + cast(Node)->getSrcValue(), + cast(Node)->getAlignment()); +} + +/// LowerOperation - Provide custom lowering hooks for some operations. +/// +SDValue X86TargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) { + switch (Op.getOpcode()) { + default: llvm_unreachable("Should not custom lower this!"); + case ISD::ATOMIC_CMP_SWAP: return LowerCMP_SWAP(Op,DAG); + case ISD::ATOMIC_LOAD_SUB: return LowerLOAD_SUB(Op,DAG); + case ISD::BUILD_VECTOR: return LowerBUILD_VECTOR(Op, DAG); + case ISD::VECTOR_SHUFFLE: return LowerVECTOR_SHUFFLE(Op, DAG); + case ISD::EXTRACT_VECTOR_ELT: return LowerEXTRACT_VECTOR_ELT(Op, DAG); + case ISD::INSERT_VECTOR_ELT: return LowerINSERT_VECTOR_ELT(Op, DAG); + case ISD::SCALAR_TO_VECTOR: return LowerSCALAR_TO_VECTOR(Op, DAG); + case ISD::ConstantPool: return LowerConstantPool(Op, DAG); + case ISD::GlobalAddress: return LowerGlobalAddress(Op, DAG); + case ISD::GlobalTLSAddress: return LowerGlobalTLSAddress(Op, DAG); + case ISD::ExternalSymbol: return LowerExternalSymbol(Op, DAG); + case ISD::BlockAddress: return LowerBlockAddress(Op, DAG); + case ISD::SHL_PARTS: + case ISD::SRA_PARTS: + case ISD::SRL_PARTS: return LowerShift(Op, DAG); + case ISD::SINT_TO_FP: return LowerSINT_TO_FP(Op, DAG); + case ISD::UINT_TO_FP: return LowerUINT_TO_FP(Op, DAG); + case ISD::FP_TO_SINT: return LowerFP_TO_SINT(Op, DAG); + case ISD::FP_TO_UINT: return LowerFP_TO_UINT(Op, DAG); + case ISD::FABS: return LowerFABS(Op, DAG); + case ISD::FNEG: return LowerFNEG(Op, DAG); + case ISD::FCOPYSIGN: return LowerFCOPYSIGN(Op, DAG); + case ISD::SETCC: return LowerSETCC(Op, DAG); + case ISD::VSETCC: return LowerVSETCC(Op, DAG); + case ISD::SELECT: return LowerSELECT(Op, DAG); + case ISD::BRCOND: return LowerBRCOND(Op, DAG); + case ISD::JumpTable: return LowerJumpTable(Op, DAG); + case ISD::VASTART: return LowerVASTART(Op, DAG); + case ISD::VAARG: return LowerVAARG(Op, DAG); + case ISD::VACOPY: return LowerVACOPY(Op, DAG); + case ISD::INTRINSIC_WO_CHAIN: return LowerINTRINSIC_WO_CHAIN(Op, DAG); + case ISD::RETURNADDR: return LowerRETURNADDR(Op, DAG); + case ISD::FRAMEADDR: return LowerFRAMEADDR(Op, DAG); + case ISD::FRAME_TO_ARGS_OFFSET: + return LowerFRAME_TO_ARGS_OFFSET(Op, DAG); + case ISD::DYNAMIC_STACKALLOC: return LowerDYNAMIC_STACKALLOC(Op, DAG); + case ISD::EH_RETURN: return LowerEH_RETURN(Op, DAG); + case ISD::TRAMPOLINE: return LowerTRAMPOLINE(Op, DAG); + case ISD::FLT_ROUNDS_: return LowerFLT_ROUNDS_(Op, DAG); + case ISD::CTLZ: return LowerCTLZ(Op, DAG); + case ISD::CTTZ: return LowerCTTZ(Op, DAG); + case ISD::MUL: return LowerMUL_V2I64(Op, DAG); + case ISD::SADDO: + case ISD::UADDO: + case ISD::SSUBO: + case ISD::USUBO: + case ISD::SMULO: + case ISD::UMULO: return LowerXALUO(Op, DAG); + case ISD::READCYCLECOUNTER: return LowerREADCYCLECOUNTER(Op, DAG); + } +} + +void X86TargetLowering:: +ReplaceATOMIC_BINARY_64(SDNode *Node, SmallVectorImpl&Results, + SelectionDAG &DAG, unsigned NewOp) { + EVT T = Node->getValueType(0); + DebugLoc dl = Node->getDebugLoc(); + assert (T == MVT::i64 && "Only know how to expand i64 atomics"); + + SDValue Chain = Node->getOperand(0); + SDValue In1 = Node->getOperand(1); + SDValue In2L = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, + Node->getOperand(2), DAG.getIntPtrConstant(0)); + SDValue In2H = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, + Node->getOperand(2), DAG.getIntPtrConstant(1)); + SDValue Ops[] = { Chain, In1, In2L, In2H }; + SDVTList Tys = DAG.getVTList(MVT::i32, MVT::i32, MVT::Other); + SDValue Result = + DAG.getMemIntrinsicNode(NewOp, dl, Tys, Ops, 4, MVT::i64, + cast(Node)->getMemOperand()); + SDValue OpsF[] = { Result.getValue(0), Result.getValue(1)}; + Results.push_back(DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i64, OpsF, 2)); + Results.push_back(Result.getValue(2)); +} + +/// ReplaceNodeResults - Replace a node with an illegal result type +/// with a new node built out of custom code. +void X86TargetLowering::ReplaceNodeResults(SDNode *N, + SmallVectorImpl&Results, + SelectionDAG &DAG) { + DebugLoc dl = N->getDebugLoc(); + switch (N->getOpcode()) { + default: + assert(false && "Do not know how to custom type legalize this operation!"); + return; + case ISD::FP_TO_SINT: { + std::pair Vals = + FP_TO_INTHelper(SDValue(N, 0), DAG, true); + SDValue FIST = Vals.first, StackSlot = Vals.second; + if (FIST.getNode() != 0) { + EVT VT = N->getValueType(0); + // Return a load from the stack slot. + Results.push_back(DAG.getLoad(VT, dl, FIST, StackSlot, NULL, 0)); + } + return; + } + case ISD::READCYCLECOUNTER: { + SDVTList Tys = DAG.getVTList(MVT::Other, MVT::Flag); + SDValue TheChain = N->getOperand(0); + SDValue rd = DAG.getNode(X86ISD::RDTSC_DAG, dl, Tys, &TheChain, 1); + SDValue eax = DAG.getCopyFromReg(rd, dl, X86::EAX, MVT::i32, + rd.getValue(1)); + SDValue edx = DAG.getCopyFromReg(eax.getValue(1), dl, X86::EDX, MVT::i32, + eax.getValue(2)); + // Use a buildpair to merge the two 32-bit values into a 64-bit one. + SDValue Ops[] = { eax, edx }; + Results.push_back(DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i64, Ops, 2)); + Results.push_back(edx.getValue(1)); + return; + } + case ISD::ATOMIC_CMP_SWAP: { + EVT T = N->getValueType(0); + assert (T == MVT::i64 && "Only know how to expand i64 Cmp and Swap"); + SDValue cpInL, cpInH; + cpInL = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, N->getOperand(2), + DAG.getConstant(0, MVT::i32)); + cpInH = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, N->getOperand(2), + DAG.getConstant(1, MVT::i32)); + cpInL = DAG.getCopyToReg(N->getOperand(0), dl, X86::EAX, cpInL, SDValue()); + cpInH = DAG.getCopyToReg(cpInL.getValue(0), dl, X86::EDX, cpInH, + cpInL.getValue(1)); + SDValue swapInL, swapInH; + swapInL = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, N->getOperand(3), + DAG.getConstant(0, MVT::i32)); + swapInH = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, N->getOperand(3), + DAG.getConstant(1, MVT::i32)); + swapInL = DAG.getCopyToReg(cpInH.getValue(0), dl, X86::EBX, swapInL, + cpInH.getValue(1)); + swapInH = DAG.getCopyToReg(swapInL.getValue(0), dl, X86::ECX, swapInH, + swapInL.getValue(1)); + SDValue Ops[] = { swapInH.getValue(0), + N->getOperand(1), + swapInH.getValue(1) }; + SDVTList Tys = DAG.getVTList(MVT::Other, MVT::Flag); + SDValue Result = DAG.getNode(X86ISD::LCMPXCHG8_DAG, dl, Tys, Ops, 3); + SDValue cpOutL = DAG.getCopyFromReg(Result.getValue(0), dl, X86::EAX, + MVT::i32, Result.getValue(1)); + SDValue cpOutH = DAG.getCopyFromReg(cpOutL.getValue(1), dl, X86::EDX, + MVT::i32, cpOutL.getValue(2)); + SDValue OpsF[] = { cpOutL.getValue(0), cpOutH.getValue(0)}; + Results.push_back(DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i64, OpsF, 2)); + Results.push_back(cpOutH.getValue(1)); + return; + } + case ISD::ATOMIC_LOAD_ADD: + ReplaceATOMIC_BINARY_64(N, Results, DAG, X86ISD::ATOMADD64_DAG); + return; + case ISD::ATOMIC_LOAD_AND: + ReplaceATOMIC_BINARY_64(N, Results, DAG, X86ISD::ATOMAND64_DAG); + return; + case ISD::ATOMIC_LOAD_NAND: + ReplaceATOMIC_BINARY_64(N, Results, DAG, X86ISD::ATOMNAND64_DAG); + return; + case ISD::ATOMIC_LOAD_OR: + ReplaceATOMIC_BINARY_64(N, Results, DAG, X86ISD::ATOMOR64_DAG); + return; + case ISD::ATOMIC_LOAD_SUB: + ReplaceATOMIC_BINARY_64(N, Results, DAG, X86ISD::ATOMSUB64_DAG); + return; + case ISD::ATOMIC_LOAD_XOR: + ReplaceATOMIC_BINARY_64(N, Results, DAG, X86ISD::ATOMXOR64_DAG); + return; + case ISD::ATOMIC_SWAP: + ReplaceATOMIC_BINARY_64(N, Results, DAG, X86ISD::ATOMSWAP64_DAG); + return; + } +} + +const char *X86TargetLowering::getTargetNodeName(unsigned Opcode) const { + switch (Opcode) { + default: return NULL; + case X86ISD::BSF: return "X86ISD::BSF"; + case X86ISD::BSR: return "X86ISD::BSR"; + case X86ISD::SHLD: return "X86ISD::SHLD"; + case X86ISD::SHRD: return "X86ISD::SHRD"; + case X86ISD::FAND: return "X86ISD::FAND"; + case X86ISD::FOR: return "X86ISD::FOR"; + case X86ISD::FXOR: return "X86ISD::FXOR"; + case X86ISD::FSRL: return "X86ISD::FSRL"; + case X86ISD::FILD: return "X86ISD::FILD"; + case X86ISD::FILD_FLAG: return "X86ISD::FILD_FLAG"; + case X86ISD::FP_TO_INT16_IN_MEM: return "X86ISD::FP_TO_INT16_IN_MEM"; + case X86ISD::FP_TO_INT32_IN_MEM: return "X86ISD::FP_TO_INT32_IN_MEM"; + case X86ISD::FP_TO_INT64_IN_MEM: return "X86ISD::FP_TO_INT64_IN_MEM"; + case X86ISD::FLD: return "X86ISD::FLD"; + case X86ISD::FST: return "X86ISD::FST"; + case X86ISD::CALL: return "X86ISD::CALL"; + case X86ISD::RDTSC_DAG: return "X86ISD::RDTSC_DAG"; + case X86ISD::BT: return "X86ISD::BT"; + case X86ISD::CMP: return "X86ISD::CMP"; + case X86ISD::COMI: return "X86ISD::COMI"; + case X86ISD::UCOMI: return "X86ISD::UCOMI"; + case X86ISD::SETCC: return "X86ISD::SETCC"; + case X86ISD::CMOV: return "X86ISD::CMOV"; + case X86ISD::BRCOND: return "X86ISD::BRCOND"; + case X86ISD::RET_FLAG: return "X86ISD::RET_FLAG"; + case X86ISD::REP_STOS: return "X86ISD::REP_STOS"; + case X86ISD::REP_MOVS: return "X86ISD::REP_MOVS"; + case X86ISD::GlobalBaseReg: return "X86ISD::GlobalBaseReg"; + case X86ISD::Wrapper: return "X86ISD::Wrapper"; + case X86ISD::WrapperRIP: return "X86ISD::WrapperRIP"; + case X86ISD::PEXTRB: return "X86ISD::PEXTRB"; + case X86ISD::PEXTRW: return "X86ISD::PEXTRW"; + case X86ISD::INSERTPS: return "X86ISD::INSERTPS"; + case X86ISD::PINSRB: return "X86ISD::PINSRB"; + case X86ISD::PINSRW: return "X86ISD::PINSRW"; + case X86ISD::PSHUFB: return "X86ISD::PSHUFB"; + case X86ISD::FMAX: return "X86ISD::FMAX"; + case X86ISD::FMIN: return "X86ISD::FMIN"; + case X86ISD::FRSQRT: return "X86ISD::FRSQRT"; + case X86ISD::FRCP: return "X86ISD::FRCP"; + case X86ISD::TLSADDR: return "X86ISD::TLSADDR"; + case X86ISD::SegmentBaseAddress: return "X86ISD::SegmentBaseAddress"; + case X86ISD::EH_RETURN: return "X86ISD::EH_RETURN"; + case X86ISD::TC_RETURN: return "X86ISD::TC_RETURN"; + case X86ISD::FNSTCW16m: return "X86ISD::FNSTCW16m"; + case X86ISD::LCMPXCHG_DAG: return "X86ISD::LCMPXCHG_DAG"; + case X86ISD::LCMPXCHG8_DAG: return "X86ISD::LCMPXCHG8_DAG"; + case X86ISD::ATOMADD64_DAG: return "X86ISD::ATOMADD64_DAG"; + case X86ISD::ATOMSUB64_DAG: return "X86ISD::ATOMSUB64_DAG"; + case X86ISD::ATOMOR64_DAG: return "X86ISD::ATOMOR64_DAG"; + case X86ISD::ATOMXOR64_DAG: return "X86ISD::ATOMXOR64_DAG"; + case X86ISD::ATOMAND64_DAG: return "X86ISD::ATOMAND64_DAG"; + case X86ISD::ATOMNAND64_DAG: return "X86ISD::ATOMNAND64_DAG"; + case X86ISD::VZEXT_MOVL: return "X86ISD::VZEXT_MOVL"; + case X86ISD::VZEXT_LOAD: return "X86ISD::VZEXT_LOAD"; + case X86ISD::VSHL: return "X86ISD::VSHL"; + case X86ISD::VSRL: return "X86ISD::VSRL"; + case X86ISD::CMPPD: return "X86ISD::CMPPD"; + case X86ISD::CMPPS: return "X86ISD::CMPPS"; + case X86ISD::PCMPEQB: return "X86ISD::PCMPEQB"; + case X86ISD::PCMPEQW: return "X86ISD::PCMPEQW"; + case X86ISD::PCMPEQD: return "X86ISD::PCMPEQD"; + case X86ISD::PCMPEQQ: return "X86ISD::PCMPEQQ"; + case X86ISD::PCMPGTB: return "X86ISD::PCMPGTB"; + case X86ISD::PCMPGTW: return "X86ISD::PCMPGTW"; + case X86ISD::PCMPGTD: return "X86ISD::PCMPGTD"; + case X86ISD::PCMPGTQ: return "X86ISD::PCMPGTQ"; + case X86ISD::ADD: return "X86ISD::ADD"; + case X86ISD::SUB: return "X86ISD::SUB"; + case X86ISD::SMUL: return "X86ISD::SMUL"; + case X86ISD::UMUL: return "X86ISD::UMUL"; + case X86ISD::INC: return "X86ISD::INC"; + case X86ISD::DEC: return "X86ISD::DEC"; + case X86ISD::OR: return "X86ISD::OR"; + case X86ISD::XOR: return "X86ISD::XOR"; + case X86ISD::AND: return "X86ISD::AND"; + case X86ISD::MUL_IMM: return "X86ISD::MUL_IMM"; + case X86ISD::PTEST: return "X86ISD::PTEST"; + case X86ISD::VASTART_SAVE_XMM_REGS: return "X86ISD::VASTART_SAVE_XMM_REGS"; + } +} + +// isLegalAddressingMode - Return true if the addressing mode represented +// by AM is legal for this target, for a load/store of the specified type. +bool X86TargetLowering::isLegalAddressingMode(const AddrMode &AM, + const Type *Ty) const { + // X86 supports extremely general addressing modes. + CodeModel::Model M = getTargetMachine().getCodeModel(); + + // X86 allows a sign-extended 32-bit immediate field as a displacement. + if (!X86::isOffsetSuitableForCodeModel(AM.BaseOffs, M, AM.BaseGV != NULL)) + return false; + + if (AM.BaseGV) { + unsigned GVFlags = + Subtarget->ClassifyGlobalReference(AM.BaseGV, getTargetMachine()); + + // If a reference to this global requires an extra load, we can't fold it. + if (isGlobalStubReference(GVFlags)) + return false; + + // If BaseGV requires a register for the PIC base, we cannot also have a + // BaseReg specified. + if (AM.HasBaseReg && isGlobalRelativeToPICBase(GVFlags)) + return false; + + // If lower 4G is not available, then we must use rip-relative addressing. + if (Subtarget->is64Bit() && (AM.BaseOffs || AM.Scale > 1)) + return false; + } + + switch (AM.Scale) { + case 0: + case 1: + case 2: + case 4: + case 8: + // These scales always work. + break; + case 3: + case 5: + case 9: + // These scales are formed with basereg+scalereg. Only accept if there is + // no basereg yet. + if (AM.HasBaseReg) + return false; + break; + default: // Other stuff never works. + return false; + } + + return true; +} + + +bool X86TargetLowering::isTruncateFree(const Type *Ty1, const Type *Ty2) const { + if (!Ty1->isInteger() || !Ty2->isInteger()) + return false; + unsigned NumBits1 = Ty1->getPrimitiveSizeInBits(); + unsigned NumBits2 = Ty2->getPrimitiveSizeInBits(); + if (NumBits1 <= NumBits2) + return false; + return Subtarget->is64Bit() || NumBits1 < 64; +} + +bool X86TargetLowering::isTruncateFree(EVT VT1, EVT VT2) const { + if (!VT1.isInteger() || !VT2.isInteger()) + return false; + unsigned NumBits1 = VT1.getSizeInBits(); + unsigned NumBits2 = VT2.getSizeInBits(); + if (NumBits1 <= NumBits2) + return false; + return Subtarget->is64Bit() || NumBits1 < 64; +} + +bool X86TargetLowering::isZExtFree(const Type *Ty1, const Type *Ty2) const { + // x86-64 implicitly zero-extends 32-bit results in 64-bit registers. + return Ty1 == Type::getInt32Ty(Ty1->getContext()) && + Ty2 == Type::getInt64Ty(Ty1->getContext()) && Subtarget->is64Bit(); +} + +bool X86TargetLowering::isZExtFree(EVT VT1, EVT VT2) const { + // x86-64 implicitly zero-extends 32-bit results in 64-bit registers. + return VT1 == MVT::i32 && VT2 == MVT::i64 && Subtarget->is64Bit(); +} + +bool X86TargetLowering::isNarrowingProfitable(EVT VT1, EVT VT2) const { + // i16 instructions are longer (0x66 prefix) and potentially slower. + return !(VT1 == MVT::i32 && VT2 == MVT::i16); +} + +/// isShuffleMaskLegal - Targets can use this to indicate that they only +/// support *some* VECTOR_SHUFFLE operations, those with specific masks. +/// By default, if a target supports the VECTOR_SHUFFLE node, all mask values +/// are assumed to be legal. +bool +X86TargetLowering::isShuffleMaskLegal(const SmallVectorImpl &M, + EVT VT) const { + // Only do shuffles on 128-bit vector types for now. + if (VT.getSizeInBits() == 64) + return false; + + // FIXME: pshufb, blends, shifts. + return (VT.getVectorNumElements() == 2 || + ShuffleVectorSDNode::isSplatMask(&M[0], VT) || + isMOVLMask(M, VT) || + isSHUFPMask(M, VT) || + isPSHUFDMask(M, VT) || + isPSHUFHWMask(M, VT) || + isPSHUFLWMask(M, VT) || + isPALIGNRMask(M, VT, Subtarget->hasSSSE3()) || + isUNPCKLMask(M, VT) || + isUNPCKHMask(M, VT) || + isUNPCKL_v_undef_Mask(M, VT) || + isUNPCKH_v_undef_Mask(M, VT)); +} + +bool +X86TargetLowering::isVectorClearMaskLegal(const SmallVectorImpl &Mask, + EVT VT) const { + unsigned NumElts = VT.getVectorNumElements(); + // FIXME: This collection of masks seems suspect. + if (NumElts == 2) + return true; + if (NumElts == 4 && VT.getSizeInBits() == 128) { + return (isMOVLMask(Mask, VT) || + isCommutedMOVLMask(Mask, VT, true) || + isSHUFPMask(Mask, VT) || + isCommutedSHUFPMask(Mask, VT)); + } + return false; +} + +//===----------------------------------------------------------------------===// +// X86 Scheduler Hooks +//===----------------------------------------------------------------------===// + +// private utility function +MachineBasicBlock * +X86TargetLowering::EmitAtomicBitwiseWithCustomInserter(MachineInstr *bInstr, + MachineBasicBlock *MBB, + unsigned regOpc, + unsigned immOpc, + unsigned LoadOpc, + unsigned CXchgOpc, + unsigned copyOpc, + unsigned notOpc, + unsigned EAXreg, + TargetRegisterClass *RC, + bool invSrc) const { + // For the atomic bitwise operator, we generate + // thisMBB: + // newMBB: + // ld t1 = [bitinstr.addr] + // op t2 = t1, [bitinstr.val] + // mov EAX = t1 + // lcs dest = [bitinstr.addr], t2 [EAX is implicit] + // bz newMBB + // fallthrough -->nextMBB + const TargetInstrInfo *TII = getTargetMachine().getInstrInfo(); + const BasicBlock *LLVM_BB = MBB->getBasicBlock(); + MachineFunction::iterator MBBIter = MBB; + ++MBBIter; + + /// First build the CFG + MachineFunction *F = MBB->getParent(); + MachineBasicBlock *thisMBB = MBB; + MachineBasicBlock *newMBB = F->CreateMachineBasicBlock(LLVM_BB); + MachineBasicBlock *nextMBB = F->CreateMachineBasicBlock(LLVM_BB); + F->insert(MBBIter, newMBB); + F->insert(MBBIter, nextMBB); + + // Move all successors to thisMBB to nextMBB + nextMBB->transferSuccessors(thisMBB); + + // Update thisMBB to fall through to newMBB + thisMBB->addSuccessor(newMBB); + + // newMBB jumps to itself and fall through to nextMBB + newMBB->addSuccessor(nextMBB); + newMBB->addSuccessor(newMBB); + + // Insert instructions into newMBB based on incoming instruction + assert(bInstr->getNumOperands() < X86AddrNumOperands + 4 && + "unexpected number of operands"); + DebugLoc dl = bInstr->getDebugLoc(); + MachineOperand& destOper = bInstr->getOperand(0); + MachineOperand* argOpers[2 + X86AddrNumOperands]; + int numArgs = bInstr->getNumOperands() - 1; + for (int i=0; i < numArgs; ++i) + argOpers[i] = &bInstr->getOperand(i+1); + + // x86 address has 4 operands: base, index, scale, and displacement + int lastAddrIndx = X86AddrNumOperands - 1; // [0,3] + int valArgIndx = lastAddrIndx + 1; + + unsigned t1 = F->getRegInfo().createVirtualRegister(RC); + MachineInstrBuilder MIB = BuildMI(newMBB, dl, TII->get(LoadOpc), t1); + for (int i=0; i <= lastAddrIndx; ++i) + (*MIB).addOperand(*argOpers[i]); + + unsigned tt = F->getRegInfo().createVirtualRegister(RC); + if (invSrc) { + MIB = BuildMI(newMBB, dl, TII->get(notOpc), tt).addReg(t1); + } + else + tt = t1; + + unsigned t2 = F->getRegInfo().createVirtualRegister(RC); + assert((argOpers[valArgIndx]->isReg() || + argOpers[valArgIndx]->isImm()) && + "invalid operand"); + if (argOpers[valArgIndx]->isReg()) + MIB = BuildMI(newMBB, dl, TII->get(regOpc), t2); + else + MIB = BuildMI(newMBB, dl, TII->get(immOpc), t2); + MIB.addReg(tt); + (*MIB).addOperand(*argOpers[valArgIndx]); + + MIB = BuildMI(newMBB, dl, TII->get(copyOpc), EAXreg); + MIB.addReg(t1); + + MIB = BuildMI(newMBB, dl, TII->get(CXchgOpc)); + for (int i=0; i <= lastAddrIndx; ++i) + (*MIB).addOperand(*argOpers[i]); + MIB.addReg(t2); + assert(bInstr->hasOneMemOperand() && "Unexpected number of memoperand"); + (*MIB).setMemRefs(bInstr->memoperands_begin(), + bInstr->memoperands_end()); + + MIB = BuildMI(newMBB, dl, TII->get(copyOpc), destOper.getReg()); + MIB.addReg(EAXreg); + + // insert branch + BuildMI(newMBB, dl, TII->get(X86::JNE)).addMBB(newMBB); + + F->DeleteMachineInstr(bInstr); // The pseudo instruction is gone now. + return nextMBB; +} + +// private utility function: 64 bit atomics on 32 bit host. +MachineBasicBlock * +X86TargetLowering::EmitAtomicBit6432WithCustomInserter(MachineInstr *bInstr, + MachineBasicBlock *MBB, + unsigned regOpcL, + unsigned regOpcH, + unsigned immOpcL, + unsigned immOpcH, + bool invSrc) const { + // For the atomic bitwise operator, we generate + // thisMBB (instructions are in pairs, except cmpxchg8b) + // ld t1,t2 = [bitinstr.addr] + // newMBB: + // out1, out2 = phi (thisMBB, t1/t2) (newMBB, t3/t4) + // op t5, t6 <- out1, out2, [bitinstr.val] + // (for SWAP, substitute: mov t5, t6 <- [bitinstr.val]) + // mov ECX, EBX <- t5, t6 + // mov EAX, EDX <- t1, t2 + // cmpxchg8b [bitinstr.addr] [EAX, EDX, EBX, ECX implicit] + // mov t3, t4 <- EAX, EDX + // bz newMBB + // result in out1, out2 + // fallthrough -->nextMBB + + const TargetRegisterClass *RC = X86::GR32RegisterClass; + const unsigned LoadOpc = X86::MOV32rm; + const unsigned copyOpc = X86::MOV32rr; + const unsigned NotOpc = X86::NOT32r; + const TargetInstrInfo *TII = getTargetMachine().getInstrInfo(); + const BasicBlock *LLVM_BB = MBB->getBasicBlock(); + MachineFunction::iterator MBBIter = MBB; + ++MBBIter; + + /// First build the CFG + MachineFunction *F = MBB->getParent(); + MachineBasicBlock *thisMBB = MBB; + MachineBasicBlock *newMBB = F->CreateMachineBasicBlock(LLVM_BB); + MachineBasicBlock *nextMBB = F->CreateMachineBasicBlock(LLVM_BB); + F->insert(MBBIter, newMBB); + F->insert(MBBIter, nextMBB); + + // Move all successors to thisMBB to nextMBB + nextMBB->transferSuccessors(thisMBB); + + // Update thisMBB to fall through to newMBB + thisMBB->addSuccessor(newMBB); + + // newMBB jumps to itself and fall through to nextMBB + newMBB->addSuccessor(nextMBB); + newMBB->addSuccessor(newMBB); + + DebugLoc dl = bInstr->getDebugLoc(); + // Insert instructions into newMBB based on incoming instruction + // There are 8 "real" operands plus 9 implicit def/uses, ignored here. + assert(bInstr->getNumOperands() < X86AddrNumOperands + 14 && + "unexpected number of operands"); + MachineOperand& dest1Oper = bInstr->getOperand(0); + MachineOperand& dest2Oper = bInstr->getOperand(1); + MachineOperand* argOpers[2 + X86AddrNumOperands]; + for (int i=0; i < 2 + X86AddrNumOperands; ++i) + argOpers[i] = &bInstr->getOperand(i+2); + + // x86 address has 4 operands: base, index, scale, and displacement + int lastAddrIndx = X86AddrNumOperands - 1; // [0,3] + + unsigned t1 = F->getRegInfo().createVirtualRegister(RC); + MachineInstrBuilder MIB = BuildMI(thisMBB, dl, TII->get(LoadOpc), t1); + for (int i=0; i <= lastAddrIndx; ++i) + (*MIB).addOperand(*argOpers[i]); + unsigned t2 = F->getRegInfo().createVirtualRegister(RC); + MIB = BuildMI(thisMBB, dl, TII->get(LoadOpc), t2); + // add 4 to displacement. + for (int i=0; i <= lastAddrIndx-2; ++i) + (*MIB).addOperand(*argOpers[i]); + MachineOperand newOp3 = *(argOpers[3]); + if (newOp3.isImm()) + newOp3.setImm(newOp3.getImm()+4); + else + newOp3.setOffset(newOp3.getOffset()+4); + (*MIB).addOperand(newOp3); + (*MIB).addOperand(*argOpers[lastAddrIndx]); + + // t3/4 are defined later, at the bottom of the loop + unsigned t3 = F->getRegInfo().createVirtualRegister(RC); + unsigned t4 = F->getRegInfo().createVirtualRegister(RC); + BuildMI(newMBB, dl, TII->get(X86::PHI), dest1Oper.getReg()) + .addReg(t1).addMBB(thisMBB).addReg(t3).addMBB(newMBB); + BuildMI(newMBB, dl, TII->get(X86::PHI), dest2Oper.getReg()) + .addReg(t2).addMBB(thisMBB).addReg(t4).addMBB(newMBB); + + unsigned tt1 = F->getRegInfo().createVirtualRegister(RC); + unsigned tt2 = F->getRegInfo().createVirtualRegister(RC); + if (invSrc) { + MIB = BuildMI(newMBB, dl, TII->get(NotOpc), tt1).addReg(t1); + MIB = BuildMI(newMBB, dl, TII->get(NotOpc), tt2).addReg(t2); + } else { + tt1 = t1; + tt2 = t2; + } + + int valArgIndx = lastAddrIndx + 1; + assert((argOpers[valArgIndx]->isReg() || + argOpers[valArgIndx]->isImm()) && + "invalid operand"); + unsigned t5 = F->getRegInfo().createVirtualRegister(RC); + unsigned t6 = F->getRegInfo().createVirtualRegister(RC); + if (argOpers[valArgIndx]->isReg()) + MIB = BuildMI(newMBB, dl, TII->get(regOpcL), t5); + else + MIB = BuildMI(newMBB, dl, TII->get(immOpcL), t5); + if (regOpcL != X86::MOV32rr) + MIB.addReg(tt1); + (*MIB).addOperand(*argOpers[valArgIndx]); + assert(argOpers[valArgIndx + 1]->isReg() == + argOpers[valArgIndx]->isReg()); + assert(argOpers[valArgIndx + 1]->isImm() == + argOpers[valArgIndx]->isImm()); + if (argOpers[valArgIndx + 1]->isReg()) + MIB = BuildMI(newMBB, dl, TII->get(regOpcH), t6); + else + MIB = BuildMI(newMBB, dl, TII->get(immOpcH), t6); + if (regOpcH != X86::MOV32rr) + MIB.addReg(tt2); + (*MIB).addOperand(*argOpers[valArgIndx + 1]); + + MIB = BuildMI(newMBB, dl, TII->get(copyOpc), X86::EAX); + MIB.addReg(t1); + MIB = BuildMI(newMBB, dl, TII->get(copyOpc), X86::EDX); + MIB.addReg(t2); + + MIB = BuildMI(newMBB, dl, TII->get(copyOpc), X86::EBX); + MIB.addReg(t5); + MIB = BuildMI(newMBB, dl, TII->get(copyOpc), X86::ECX); + MIB.addReg(t6); + + MIB = BuildMI(newMBB, dl, TII->get(X86::LCMPXCHG8B)); + for (int i=0; i <= lastAddrIndx; ++i) + (*MIB).addOperand(*argOpers[i]); + + assert(bInstr->hasOneMemOperand() && "Unexpected number of memoperand"); + (*MIB).setMemRefs(bInstr->memoperands_begin(), + bInstr->memoperands_end()); + + MIB = BuildMI(newMBB, dl, TII->get(copyOpc), t3); + MIB.addReg(X86::EAX); + MIB = BuildMI(newMBB, dl, TII->get(copyOpc), t4); + MIB.addReg(X86::EDX); + + // insert branch + BuildMI(newMBB, dl, TII->get(X86::JNE)).addMBB(newMBB); + + F->DeleteMachineInstr(bInstr); // The pseudo instruction is gone now. + return nextMBB; +} + +// private utility function +MachineBasicBlock * +X86TargetLowering::EmitAtomicMinMaxWithCustomInserter(MachineInstr *mInstr, + MachineBasicBlock *MBB, + unsigned cmovOpc) const { + // For the atomic min/max operator, we generate + // thisMBB: + // newMBB: + // ld t1 = [min/max.addr] + // mov t2 = [min/max.val] + // cmp t1, t2 + // cmov[cond] t2 = t1 + // mov EAX = t1 + // lcs dest = [bitinstr.addr], t2 [EAX is implicit] + // bz newMBB + // fallthrough -->nextMBB + // + const TargetInstrInfo *TII = getTargetMachine().getInstrInfo(); + const BasicBlock *LLVM_BB = MBB->getBasicBlock(); + MachineFunction::iterator MBBIter = MBB; + ++MBBIter; + + /// First build the CFG + MachineFunction *F = MBB->getParent(); + MachineBasicBlock *thisMBB = MBB; + MachineBasicBlock *newMBB = F->CreateMachineBasicBlock(LLVM_BB); + MachineBasicBlock *nextMBB = F->CreateMachineBasicBlock(LLVM_BB); + F->insert(MBBIter, newMBB); + F->insert(MBBIter, nextMBB); + + // Move all successors of thisMBB to nextMBB + nextMBB->transferSuccessors(thisMBB); + + // Update thisMBB to fall through to newMBB + thisMBB->addSuccessor(newMBB); + + // newMBB jumps to newMBB and fall through to nextMBB + newMBB->addSuccessor(nextMBB); + newMBB->addSuccessor(newMBB); + + DebugLoc dl = mInstr->getDebugLoc(); + // Insert instructions into newMBB based on incoming instruction + assert(mInstr->getNumOperands() < X86AddrNumOperands + 4 && + "unexpected number of operands"); + MachineOperand& destOper = mInstr->getOperand(0); + MachineOperand* argOpers[2 + X86AddrNumOperands]; + int numArgs = mInstr->getNumOperands() - 1; + for (int i=0; i < numArgs; ++i) + argOpers[i] = &mInstr->getOperand(i+1); + + // x86 address has 4 operands: base, index, scale, and displacement + int lastAddrIndx = X86AddrNumOperands - 1; // [0,3] + int valArgIndx = lastAddrIndx + 1; + + unsigned t1 = F->getRegInfo().createVirtualRegister(X86::GR32RegisterClass); + MachineInstrBuilder MIB = BuildMI(newMBB, dl, TII->get(X86::MOV32rm), t1); + for (int i=0; i <= lastAddrIndx; ++i) + (*MIB).addOperand(*argOpers[i]); + + // We only support register and immediate values + assert((argOpers[valArgIndx]->isReg() || + argOpers[valArgIndx]->isImm()) && + "invalid operand"); + + unsigned t2 = F->getRegInfo().createVirtualRegister(X86::GR32RegisterClass); + if (argOpers[valArgIndx]->isReg()) + MIB = BuildMI(newMBB, dl, TII->get(X86::MOV32rr), t2); + else + MIB = BuildMI(newMBB, dl, TII->get(X86::MOV32rr), t2); + (*MIB).addOperand(*argOpers[valArgIndx]); + + MIB = BuildMI(newMBB, dl, TII->get(X86::MOV32rr), X86::EAX); + MIB.addReg(t1); + + MIB = BuildMI(newMBB, dl, TII->get(X86::CMP32rr)); + MIB.addReg(t1); + MIB.addReg(t2); + + // Generate movc + unsigned t3 = F->getRegInfo().createVirtualRegister(X86::GR32RegisterClass); + MIB = BuildMI(newMBB, dl, TII->get(cmovOpc),t3); + MIB.addReg(t2); + MIB.addReg(t1); + + // Cmp and exchange if none has modified the memory location + MIB = BuildMI(newMBB, dl, TII->get(X86::LCMPXCHG32)); + for (int i=0; i <= lastAddrIndx; ++i) + (*MIB).addOperand(*argOpers[i]); + MIB.addReg(t3); + assert(mInstr->hasOneMemOperand() && "Unexpected number of memoperand"); + (*MIB).setMemRefs(mInstr->memoperands_begin(), + mInstr->memoperands_end()); + + MIB = BuildMI(newMBB, dl, TII->get(X86::MOV32rr), destOper.getReg()); + MIB.addReg(X86::EAX); + + // insert branch + BuildMI(newMBB, dl, TII->get(X86::JNE)).addMBB(newMBB); + + F->DeleteMachineInstr(mInstr); // The pseudo instruction is gone now. + return nextMBB; +} + +// FIXME: When we get size specific XMM0 registers, i.e. XMM0_V16I8 +// all of this code can be replaced with that in the .td file. +MachineBasicBlock * +X86TargetLowering::EmitPCMP(MachineInstr *MI, MachineBasicBlock *BB, + unsigned numArgs, bool memArg) const { + + MachineFunction *F = BB->getParent(); + DebugLoc dl = MI->getDebugLoc(); + const TargetInstrInfo *TII = getTargetMachine().getInstrInfo(); + + unsigned Opc; + if (memArg) + Opc = numArgs == 3 ? X86::PCMPISTRM128rm : X86::PCMPESTRM128rm; + else + Opc = numArgs == 3 ? X86::PCMPISTRM128rr : X86::PCMPESTRM128rr; + + MachineInstrBuilder MIB = BuildMI(BB, dl, TII->get(Opc)); + + for (unsigned i = 0; i < numArgs; ++i) { + MachineOperand &Op = MI->getOperand(i+1); + + if (!(Op.isReg() && Op.isImplicit())) + MIB.addOperand(Op); + } + + BuildMI(BB, dl, TII->get(X86::MOVAPSrr), MI->getOperand(0).getReg()) + .addReg(X86::XMM0); + + F->DeleteMachineInstr(MI); + + return BB; +} + +MachineBasicBlock * +X86TargetLowering::EmitVAStartSaveXMMRegsWithCustomInserter( + MachineInstr *MI, + MachineBasicBlock *MBB) const { + // Emit code to save XMM registers to the stack. The ABI says that the + // number of registers to save is given in %al, so it's theoretically + // possible to do an indirect jump trick to avoid saving all of them, + // however this code takes a simpler approach and just executes all + // of the stores if %al is non-zero. It's less code, and it's probably + // easier on the hardware branch predictor, and stores aren't all that + // expensive anyway. + + // Create the new basic blocks. One block contains all the XMM stores, + // and one block is the final destination regardless of whether any + // stores were performed. + const BasicBlock *LLVM_BB = MBB->getBasicBlock(); + MachineFunction *F = MBB->getParent(); + MachineFunction::iterator MBBIter = MBB; + ++MBBIter; + MachineBasicBlock *XMMSaveMBB = F->CreateMachineBasicBlock(LLVM_BB); + MachineBasicBlock *EndMBB = F->CreateMachineBasicBlock(LLVM_BB); + F->insert(MBBIter, XMMSaveMBB); + F->insert(MBBIter, EndMBB); + + // Set up the CFG. + // Move any original successors of MBB to the end block. + EndMBB->transferSuccessors(MBB); + // The original block will now fall through to the XMM save block. + MBB->addSuccessor(XMMSaveMBB); + // The XMMSaveMBB will fall through to the end block. + XMMSaveMBB->addSuccessor(EndMBB); + + // Now add the instructions. + const TargetInstrInfo *TII = getTargetMachine().getInstrInfo(); + DebugLoc DL = MI->getDebugLoc(); + + unsigned CountReg = MI->getOperand(0).getReg(); + int64_t RegSaveFrameIndex = MI->getOperand(1).getImm(); + int64_t VarArgsFPOffset = MI->getOperand(2).getImm(); + + if (!Subtarget->isTargetWin64()) { + // If %al is 0, branch around the XMM save block. + BuildMI(MBB, DL, TII->get(X86::TEST8rr)).addReg(CountReg).addReg(CountReg); + BuildMI(MBB, DL, TII->get(X86::JE)).addMBB(EndMBB); + MBB->addSuccessor(EndMBB); + } + + // In the XMM save block, save all the XMM argument registers. + for (int i = 3, e = MI->getNumOperands(); i != e; ++i) { + int64_t Offset = (i - 3) * 16 + VarArgsFPOffset; + MachineMemOperand *MMO = + F->getMachineMemOperand( + PseudoSourceValue::getFixedStack(RegSaveFrameIndex), + MachineMemOperand::MOStore, Offset, + /*Size=*/16, /*Align=*/16); + BuildMI(XMMSaveMBB, DL, TII->get(X86::MOVAPSmr)) + .addFrameIndex(RegSaveFrameIndex) + .addImm(/*Scale=*/1) + .addReg(/*IndexReg=*/0) + .addImm(/*Disp=*/Offset) + .addReg(/*Segment=*/0) + .addReg(MI->getOperand(i).getReg()) + .addMemOperand(MMO); + } + + F->DeleteMachineInstr(MI); // The pseudo instruction is gone now. + + return EndMBB; +} + +MachineBasicBlock * +X86TargetLowering::EmitLoweredSelect(MachineInstr *MI, + MachineBasicBlock *BB, + DenseMap *EM) const { + const TargetInstrInfo *TII = getTargetMachine().getInstrInfo(); + DebugLoc DL = MI->getDebugLoc(); + + // To "insert" a SELECT_CC instruction, we actually have to insert the + // diamond control-flow pattern. The incoming instruction knows the + // destination vreg to set, the condition code register to branch on, the + // true/false values to select between, and a branch opcode to use. + const BasicBlock *LLVM_BB = BB->getBasicBlock(); + MachineFunction::iterator It = BB; + ++It; + + // thisMBB: + // ... + // TrueVal = ... + // cmpTY ccX, r1, r2 + // bCC copy1MBB + // fallthrough --> copy0MBB + MachineBasicBlock *thisMBB = BB; + MachineFunction *F = BB->getParent(); + MachineBasicBlock *copy0MBB = F->CreateMachineBasicBlock(LLVM_BB); + MachineBasicBlock *sinkMBB = F->CreateMachineBasicBlock(LLVM_BB); + unsigned Opc = + X86::GetCondBranchFromCond((X86::CondCode)MI->getOperand(3).getImm()); + BuildMI(BB, DL, TII->get(Opc)).addMBB(sinkMBB); + F->insert(It, copy0MBB); + F->insert(It, sinkMBB); + // Update machine-CFG edges by first adding all successors of the current + // block to the new block which will contain the Phi node for the select. + // Also inform sdisel of the edge changes. + for (MachineBasicBlock::succ_iterator I = BB->succ_begin(), + E = BB->succ_end(); I != E; ++I) { + EM->insert(std::make_pair(*I, sinkMBB)); + sinkMBB->addSuccessor(*I); + } + // Next, remove all successors of the current block, and add the true + // and fallthrough blocks as its successors. + while (!BB->succ_empty()) + BB->removeSuccessor(BB->succ_begin()); + // Add the true and fallthrough blocks as its successors. + BB->addSuccessor(copy0MBB); + BB->addSuccessor(sinkMBB); + + // copy0MBB: + // %FalseValue = ... + // # fallthrough to sinkMBB + BB = copy0MBB; + + // Update machine-CFG edges + BB->addSuccessor(sinkMBB); + + // sinkMBB: + // %Result = phi [ %FalseValue, copy0MBB ], [ %TrueValue, thisMBB ] + // ... + BB = sinkMBB; + BuildMI(BB, DL, TII->get(X86::PHI), MI->getOperand(0).getReg()) + .addReg(MI->getOperand(1).getReg()).addMBB(copy0MBB) + .addReg(MI->getOperand(2).getReg()).addMBB(thisMBB); + + F->DeleteMachineInstr(MI); // The pseudo instruction is gone now. + return BB; +} + + +MachineBasicBlock * +X86TargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI, + MachineBasicBlock *BB, + DenseMap *EM) const { + switch (MI->getOpcode()) { + default: assert(false && "Unexpected instr type to insert"); + case X86::CMOV_GR8: + case X86::CMOV_V1I64: + case X86::CMOV_FR32: + case X86::CMOV_FR64: + case X86::CMOV_V4F32: + case X86::CMOV_V2F64: + case X86::CMOV_V2I64: + return EmitLoweredSelect(MI, BB, EM); + + case X86::FP32_TO_INT16_IN_MEM: + case X86::FP32_TO_INT32_IN_MEM: + case X86::FP32_TO_INT64_IN_MEM: + case X86::FP64_TO_INT16_IN_MEM: + case X86::FP64_TO_INT32_IN_MEM: + case X86::FP64_TO_INT64_IN_MEM: + case X86::FP80_TO_INT16_IN_MEM: + case X86::FP80_TO_INT32_IN_MEM: + case X86::FP80_TO_INT64_IN_MEM: { + const TargetInstrInfo *TII = getTargetMachine().getInstrInfo(); + DebugLoc DL = MI->getDebugLoc(); + + // Change the floating point control register to use "round towards zero" + // mode when truncating to an integer value. + MachineFunction *F = BB->getParent(); + int CWFrameIdx = F->getFrameInfo()->CreateStackObject(2, 2, false); + addFrameReference(BuildMI(BB, DL, TII->get(X86::FNSTCW16m)), CWFrameIdx); + + // Load the old value of the high byte of the control word... + unsigned OldCW = + F->getRegInfo().createVirtualRegister(X86::GR16RegisterClass); + addFrameReference(BuildMI(BB, DL, TII->get(X86::MOV16rm), OldCW), + CWFrameIdx); + + // Set the high part to be round to zero... + addFrameReference(BuildMI(BB, DL, TII->get(X86::MOV16mi)), CWFrameIdx) + .addImm(0xC7F); + + // Reload the modified control word now... + addFrameReference(BuildMI(BB, DL, TII->get(X86::FLDCW16m)), CWFrameIdx); + + // Restore the memory image of control word to original value + addFrameReference(BuildMI(BB, DL, TII->get(X86::MOV16mr)), CWFrameIdx) + .addReg(OldCW); + + // Get the X86 opcode to use. + unsigned Opc; + switch (MI->getOpcode()) { + default: llvm_unreachable("illegal opcode!"); + case X86::FP32_TO_INT16_IN_MEM: Opc = X86::IST_Fp16m32; break; + case X86::FP32_TO_INT32_IN_MEM: Opc = X86::IST_Fp32m32; break; + case X86::FP32_TO_INT64_IN_MEM: Opc = X86::IST_Fp64m32; break; + case X86::FP64_TO_INT16_IN_MEM: Opc = X86::IST_Fp16m64; break; + case X86::FP64_TO_INT32_IN_MEM: Opc = X86::IST_Fp32m64; break; + case X86::FP64_TO_INT64_IN_MEM: Opc = X86::IST_Fp64m64; break; + case X86::FP80_TO_INT16_IN_MEM: Opc = X86::IST_Fp16m80; break; + case X86::FP80_TO_INT32_IN_MEM: Opc = X86::IST_Fp32m80; break; + case X86::FP80_TO_INT64_IN_MEM: Opc = X86::IST_Fp64m80; break; + } + + X86AddressMode AM; + MachineOperand &Op = MI->getOperand(0); + if (Op.isReg()) { + AM.BaseType = X86AddressMode::RegBase; + AM.Base.Reg = Op.getReg(); + } else { + AM.BaseType = X86AddressMode::FrameIndexBase; + AM.Base.FrameIndex = Op.getIndex(); + } + Op = MI->getOperand(1); + if (Op.isImm()) + AM.Scale = Op.getImm(); + Op = MI->getOperand(2); + if (Op.isImm()) + AM.IndexReg = Op.getImm(); + Op = MI->getOperand(3); + if (Op.isGlobal()) { + AM.GV = Op.getGlobal(); + } else { + AM.Disp = Op.getImm(); + } + addFullAddress(BuildMI(BB, DL, TII->get(Opc)), AM) + .addReg(MI->getOperand(X86AddrNumOperands).getReg()); + + // Reload the original control word now. + addFrameReference(BuildMI(BB, DL, TII->get(X86::FLDCW16m)), CWFrameIdx); + + F->DeleteMachineInstr(MI); // The pseudo instruction is gone now. + return BB; + } + // String/text processing lowering. + case X86::PCMPISTRM128REG: + return EmitPCMP(MI, BB, 3, false /* in-mem */); + case X86::PCMPISTRM128MEM: + return EmitPCMP(MI, BB, 3, true /* in-mem */); + case X86::PCMPESTRM128REG: + return EmitPCMP(MI, BB, 5, false /* in mem */); + case X86::PCMPESTRM128MEM: + return EmitPCMP(MI, BB, 5, true /* in mem */); + + // Atomic Lowering. + case X86::ATOMAND32: + return EmitAtomicBitwiseWithCustomInserter(MI, BB, X86::AND32rr, + X86::AND32ri, X86::MOV32rm, + X86::LCMPXCHG32, X86::MOV32rr, + X86::NOT32r, X86::EAX, + X86::GR32RegisterClass); + case X86::ATOMOR32: + return EmitAtomicBitwiseWithCustomInserter(MI, BB, X86::OR32rr, + X86::OR32ri, X86::MOV32rm, + X86::LCMPXCHG32, X86::MOV32rr, + X86::NOT32r, X86::EAX, + X86::GR32RegisterClass); + case X86::ATOMXOR32: + return EmitAtomicBitwiseWithCustomInserter(MI, BB, X86::XOR32rr, + X86::XOR32ri, X86::MOV32rm, + X86::LCMPXCHG32, X86::MOV32rr, + X86::NOT32r, X86::EAX, + X86::GR32RegisterClass); + case X86::ATOMNAND32: + return EmitAtomicBitwiseWithCustomInserter(MI, BB, X86::AND32rr, + X86::AND32ri, X86::MOV32rm, + X86::LCMPXCHG32, X86::MOV32rr, + X86::NOT32r, X86::EAX, + X86::GR32RegisterClass, true); + case X86::ATOMMIN32: + return EmitAtomicMinMaxWithCustomInserter(MI, BB, X86::CMOVL32rr); + case X86::ATOMMAX32: + return EmitAtomicMinMaxWithCustomInserter(MI, BB, X86::CMOVG32rr); + case X86::ATOMUMIN32: + return EmitAtomicMinMaxWithCustomInserter(MI, BB, X86::CMOVB32rr); + case X86::ATOMUMAX32: + return EmitAtomicMinMaxWithCustomInserter(MI, BB, X86::CMOVA32rr); + + case X86::ATOMAND16: + return EmitAtomicBitwiseWithCustomInserter(MI, BB, X86::AND16rr, + X86::AND16ri, X86::MOV16rm, + X86::LCMPXCHG16, X86::MOV16rr, + X86::NOT16r, X86::AX, + X86::GR16RegisterClass); + case X86::ATOMOR16: + return EmitAtomicBitwiseWithCustomInserter(MI, BB, X86::OR16rr, + X86::OR16ri, X86::MOV16rm, + X86::LCMPXCHG16, X86::MOV16rr, + X86::NOT16r, X86::AX, + X86::GR16RegisterClass); + case X86::ATOMXOR16: + return EmitAtomicBitwiseWithCustomInserter(MI, BB, X86::XOR16rr, + X86::XOR16ri, X86::MOV16rm, + X86::LCMPXCHG16, X86::MOV16rr, + X86::NOT16r, X86::AX, + X86::GR16RegisterClass); + case X86::ATOMNAND16: + return EmitAtomicBitwiseWithCustomInserter(MI, BB, X86::AND16rr, + X86::AND16ri, X86::MOV16rm, + X86::LCMPXCHG16, X86::MOV16rr, + X86::NOT16r, X86::AX, + X86::GR16RegisterClass, true); + case X86::ATOMMIN16: + return EmitAtomicMinMaxWithCustomInserter(MI, BB, X86::CMOVL16rr); + case X86::ATOMMAX16: + return EmitAtomicMinMaxWithCustomInserter(MI, BB, X86::CMOVG16rr); + case X86::ATOMUMIN16: + return EmitAtomicMinMaxWithCustomInserter(MI, BB, X86::CMOVB16rr); + case X86::ATOMUMAX16: + return EmitAtomicMinMaxWithCustomInserter(MI, BB, X86::CMOVA16rr); + + case X86::ATOMAND8: + return EmitAtomicBitwiseWithCustomInserter(MI, BB, X86::AND8rr, + X86::AND8ri, X86::MOV8rm, + X86::LCMPXCHG8, X86::MOV8rr, + X86::NOT8r, X86::AL, + X86::GR8RegisterClass); + case X86::ATOMOR8: + return EmitAtomicBitwiseWithCustomInserter(MI, BB, X86::OR8rr, + X86::OR8ri, X86::MOV8rm, + X86::LCMPXCHG8, X86::MOV8rr, + X86::NOT8r, X86::AL, + X86::GR8RegisterClass); + case X86::ATOMXOR8: + return EmitAtomicBitwiseWithCustomInserter(MI, BB, X86::XOR8rr, + X86::XOR8ri, X86::MOV8rm, + X86::LCMPXCHG8, X86::MOV8rr, + X86::NOT8r, X86::AL, + X86::GR8RegisterClass); + case X86::ATOMNAND8: + return EmitAtomicBitwiseWithCustomInserter(MI, BB, X86::AND8rr, + X86::AND8ri, X86::MOV8rm, + X86::LCMPXCHG8, X86::MOV8rr, + X86::NOT8r, X86::AL, + X86::GR8RegisterClass, true); + // FIXME: There are no CMOV8 instructions; MIN/MAX need some other way. + // This group is for 64-bit host. + case X86::ATOMAND64: + return EmitAtomicBitwiseWithCustomInserter(MI, BB, X86::AND64rr, + X86::AND64ri32, X86::MOV64rm, + X86::LCMPXCHG64, X86::MOV64rr, + X86::NOT64r, X86::RAX, + X86::GR64RegisterClass); + case X86::ATOMOR64: + return EmitAtomicBitwiseWithCustomInserter(MI, BB, X86::OR64rr, + X86::OR64ri32, X86::MOV64rm, + X86::LCMPXCHG64, X86::MOV64rr, + X86::NOT64r, X86::RAX, + X86::GR64RegisterClass); + case X86::ATOMXOR64: + return EmitAtomicBitwiseWithCustomInserter(MI, BB, X86::XOR64rr, + X86::XOR64ri32, X86::MOV64rm, + X86::LCMPXCHG64, X86::MOV64rr, + X86::NOT64r, X86::RAX, + X86::GR64RegisterClass); + case X86::ATOMNAND64: + return EmitAtomicBitwiseWithCustomInserter(MI, BB, X86::AND64rr, + X86::AND64ri32, X86::MOV64rm, + X86::LCMPXCHG64, X86::MOV64rr, + X86::NOT64r, X86::RAX, + X86::GR64RegisterClass, true); + case X86::ATOMMIN64: + return EmitAtomicMinMaxWithCustomInserter(MI, BB, X86::CMOVL64rr); + case X86::ATOMMAX64: + return EmitAtomicMinMaxWithCustomInserter(MI, BB, X86::CMOVG64rr); + case X86::ATOMUMIN64: + return EmitAtomicMinMaxWithCustomInserter(MI, BB, X86::CMOVB64rr); + case X86::ATOMUMAX64: + return EmitAtomicMinMaxWithCustomInserter(MI, BB, X86::CMOVA64rr); + + // This group does 64-bit operations on a 32-bit host. + case X86::ATOMAND6432: + return EmitAtomicBit6432WithCustomInserter(MI, BB, + X86::AND32rr, X86::AND32rr, + X86::AND32ri, X86::AND32ri, + false); + case X86::ATOMOR6432: + return EmitAtomicBit6432WithCustomInserter(MI, BB, + X86::OR32rr, X86::OR32rr, + X86::OR32ri, X86::OR32ri, + false); + case X86::ATOMXOR6432: + return EmitAtomicBit6432WithCustomInserter(MI, BB, + X86::XOR32rr, X86::XOR32rr, + X86::XOR32ri, X86::XOR32ri, + false); + case X86::ATOMNAND6432: + return EmitAtomicBit6432WithCustomInserter(MI, BB, + X86::AND32rr, X86::AND32rr, + X86::AND32ri, X86::AND32ri, + true); + case X86::ATOMADD6432: + return EmitAtomicBit6432WithCustomInserter(MI, BB, + X86::ADD32rr, X86::ADC32rr, + X86::ADD32ri, X86::ADC32ri, + false); + case X86::ATOMSUB6432: + return EmitAtomicBit6432WithCustomInserter(MI, BB, + X86::SUB32rr, X86::SBB32rr, + X86::SUB32ri, X86::SBB32ri, + false); + case X86::ATOMSWAP6432: + return EmitAtomicBit6432WithCustomInserter(MI, BB, + X86::MOV32rr, X86::MOV32rr, + X86::MOV32ri, X86::MOV32ri, + false); + case X86::VASTART_SAVE_XMM_REGS: + return EmitVAStartSaveXMMRegsWithCustomInserter(MI, BB); + } +} + +//===----------------------------------------------------------------------===// +// X86 Optimization Hooks +//===----------------------------------------------------------------------===// + +void X86TargetLowering::computeMaskedBitsForTargetNode(const SDValue Op, + const APInt &Mask, + APInt &KnownZero, + APInt &KnownOne, + const SelectionDAG &DAG, + unsigned Depth) const { + unsigned Opc = Op.getOpcode(); + assert((Opc >= ISD::BUILTIN_OP_END || + Opc == ISD::INTRINSIC_WO_CHAIN || + Opc == ISD::INTRINSIC_W_CHAIN || + Opc == ISD::INTRINSIC_VOID) && + "Should use MaskedValueIsZero if you don't know whether Op" + " is a target node!"); + + KnownZero = KnownOne = APInt(Mask.getBitWidth(), 0); // Don't know anything. + switch (Opc) { + default: break; + case X86ISD::ADD: + case X86ISD::SUB: + case X86ISD::SMUL: + case X86ISD::UMUL: + case X86ISD::INC: + case X86ISD::DEC: + case X86ISD::OR: + case X86ISD::XOR: + case X86ISD::AND: + // These nodes' second result is a boolean. + if (Op.getResNo() == 0) + break; + // Fallthrough + case X86ISD::SETCC: + KnownZero |= APInt::getHighBitsSet(Mask.getBitWidth(), + Mask.getBitWidth() - 1); + break; + } +} + +/// isGAPlusOffset - Returns true (and the GlobalValue and the offset) if the +/// node is a GlobalAddress + offset. +bool X86TargetLowering::isGAPlusOffset(SDNode *N, + GlobalValue* &GA, int64_t &Offset) const{ + if (N->getOpcode() == X86ISD::Wrapper) { + if (isa(N->getOperand(0))) { + GA = cast(N->getOperand(0))->getGlobal(); + Offset = cast(N->getOperand(0))->getOffset(); + return true; + } + } + return TargetLowering::isGAPlusOffset(N, GA, Offset); +} + +static bool isBaseAlignmentOfN(unsigned N, SDNode *Base, + const TargetLowering &TLI) { + GlobalValue *GV; + int64_t Offset = 0; + if (TLI.isGAPlusOffset(Base, GV, Offset)) + return (GV->getAlignment() >= N && (Offset % N) == 0); + // DAG combine handles the stack object case. + return false; +} + +static bool EltsFromConsecutiveLoads(ShuffleVectorSDNode *N, unsigned NumElems, + EVT EltVT, LoadSDNode *&LDBase, + unsigned &LastLoadedElt, + SelectionDAG &DAG, MachineFrameInfo *MFI, + const TargetLowering &TLI) { + LDBase = NULL; + LastLoadedElt = -1U; + for (unsigned i = 0; i < NumElems; ++i) { + if (N->getMaskElt(i) < 0) { + if (!LDBase) + return false; + continue; + } + + SDValue Elt = DAG.getShuffleScalarElt(N, i); + if (!Elt.getNode() || + (Elt.getOpcode() != ISD::UNDEF && !ISD::isNON_EXTLoad(Elt.getNode()))) + return false; + if (!LDBase) { + if (Elt.getNode()->getOpcode() == ISD::UNDEF) + return false; + LDBase = cast(Elt.getNode()); + LastLoadedElt = i; + continue; + } + if (Elt.getOpcode() == ISD::UNDEF) + continue; + + LoadSDNode *LD = cast(Elt); + if (!TLI.isConsecutiveLoad(LD, LDBase, EltVT.getSizeInBits()/8, i, MFI)) + return false; + LastLoadedElt = i; + } + return true; +} + +/// PerformShuffleCombine - Combine a vector_shuffle that is equal to +/// build_vector load1, load2, load3, load4, <0, 1, 2, 3> into a 128-bit load +/// if the load addresses are consecutive, non-overlapping, and in the right +/// order. In the case of v2i64, it will see if it can rewrite the +/// shuffle to be an appropriate build vector so it can take advantage of +// performBuildVectorCombine. +static SDValue PerformShuffleCombine(SDNode *N, SelectionDAG &DAG, + const TargetLowering &TLI) { + DebugLoc dl = N->getDebugLoc(); + EVT VT = N->getValueType(0); + EVT EltVT = VT.getVectorElementType(); + ShuffleVectorSDNode *SVN = cast(N); + unsigned NumElems = VT.getVectorNumElements(); + + if (VT.getSizeInBits() != 128) + return SDValue(); + + // Try to combine a vector_shuffle into a 128-bit load. + MachineFrameInfo *MFI = DAG.getMachineFunction().getFrameInfo(); + LoadSDNode *LD = NULL; + unsigned LastLoadedElt; + if (!EltsFromConsecutiveLoads(SVN, NumElems, EltVT, LD, LastLoadedElt, DAG, + MFI, TLI)) + return SDValue(); + + if (LastLoadedElt == NumElems - 1) { + if (isBaseAlignmentOfN(16, LD->getBasePtr().getNode(), TLI)) + return DAG.getLoad(VT, dl, LD->getChain(), LD->getBasePtr(), + LD->getSrcValue(), LD->getSrcValueOffset(), + LD->isVolatile()); + return DAG.getLoad(VT, dl, LD->getChain(), LD->getBasePtr(), + LD->getSrcValue(), LD->getSrcValueOffset(), + LD->isVolatile(), LD->getAlignment()); + } else if (NumElems == 4 && LastLoadedElt == 1) { + SDVTList Tys = DAG.getVTList(MVT::v2i64, MVT::Other); + SDValue Ops[] = { LD->getChain(), LD->getBasePtr() }; + SDValue ResNode = DAG.getNode(X86ISD::VZEXT_LOAD, dl, Tys, Ops, 2); + return DAG.getNode(ISD::BIT_CONVERT, dl, VT, ResNode); + } + return SDValue(); +} + +/// PerformSELECTCombine - Do target-specific dag combines on SELECT nodes. +static SDValue PerformSELECTCombine(SDNode *N, SelectionDAG &DAG, + const X86Subtarget *Subtarget) { + DebugLoc DL = N->getDebugLoc(); + SDValue Cond = N->getOperand(0); + // Get the LHS/RHS of the select. + SDValue LHS = N->getOperand(1); + SDValue RHS = N->getOperand(2); + + // If we have SSE[12] support, try to form min/max nodes. SSE min/max + // instructions have the peculiarity that if either operand is a NaN, + // they chose what we call the RHS operand (and as such are not symmetric). + // It happens that this matches the semantics of the common C idiom + // xhasSSE2() && + (LHS.getValueType() == MVT::f32 || LHS.getValueType() == MVT::f64) && + Cond.getOpcode() == ISD::SETCC) { + ISD::CondCode CC = cast(Cond.getOperand(2))->get(); + + unsigned Opcode = 0; + // Check for x CC y ? x : y. + if (LHS == Cond.getOperand(0) && RHS == Cond.getOperand(1)) { + switch (CC) { + default: break; + case ISD::SETULT: + // This can be a min if we can prove that at least one of the operands + // is not a nan. + if (!FiniteOnlyFPMath()) { + if (DAG.isKnownNeverNaN(RHS)) { + // Put the potential NaN in the RHS so that SSE will preserve it. + std::swap(LHS, RHS); + } else if (!DAG.isKnownNeverNaN(LHS)) + break; + } + Opcode = X86ISD::FMIN; + break; + case ISD::SETOLE: + // This can be a min if we can prove that at least one of the operands + // is not a nan. + if (!FiniteOnlyFPMath()) { + if (DAG.isKnownNeverNaN(LHS)) { + // Put the potential NaN in the RHS so that SSE will preserve it. + std::swap(LHS, RHS); + } else if (!DAG.isKnownNeverNaN(RHS)) + break; + } + Opcode = X86ISD::FMIN; + break; + case ISD::SETULE: + // This can be a min, but if either operand is a NaN we need it to + // preserve the original LHS. + std::swap(LHS, RHS); + case ISD::SETOLT: + case ISD::SETLT: + case ISD::SETLE: + Opcode = X86ISD::FMIN; + break; + + case ISD::SETOGE: + // This can be a max if we can prove that at least one of the operands + // is not a nan. + if (!FiniteOnlyFPMath()) { + if (DAG.isKnownNeverNaN(LHS)) { + // Put the potential NaN in the RHS so that SSE will preserve it. + std::swap(LHS, RHS); + } else if (!DAG.isKnownNeverNaN(RHS)) + break; + } + Opcode = X86ISD::FMAX; + break; + case ISD::SETUGT: + // This can be a max if we can prove that at least one of the operands + // is not a nan. + if (!FiniteOnlyFPMath()) { + if (DAG.isKnownNeverNaN(RHS)) { + // Put the potential NaN in the RHS so that SSE will preserve it. + std::swap(LHS, RHS); + } else if (!DAG.isKnownNeverNaN(LHS)) + break; + } + Opcode = X86ISD::FMAX; + break; + case ISD::SETUGE: + // This can be a max, but if either operand is a NaN we need it to + // preserve the original LHS. + std::swap(LHS, RHS); + case ISD::SETOGT: + case ISD::SETGT: + case ISD::SETGE: + Opcode = X86ISD::FMAX; + break; + } + // Check for x CC y ? y : x -- a min/max with reversed arms. + } else if (LHS == Cond.getOperand(1) && RHS == Cond.getOperand(0)) { + switch (CC) { + default: break; + case ISD::SETOGE: + // This can be a min if we can prove that at least one of the operands + // is not a nan. + if (!FiniteOnlyFPMath()) { + if (DAG.isKnownNeverNaN(RHS)) { + // Put the potential NaN in the RHS so that SSE will preserve it. + std::swap(LHS, RHS); + } else if (!DAG.isKnownNeverNaN(LHS)) + break; + } + Opcode = X86ISD::FMIN; + break; + case ISD::SETUGT: + // This can be a min if we can prove that at least one of the operands + // is not a nan. + if (!FiniteOnlyFPMath()) { + if (DAG.isKnownNeverNaN(LHS)) { + // Put the potential NaN in the RHS so that SSE will preserve it. + std::swap(LHS, RHS); + } else if (!DAG.isKnownNeverNaN(RHS)) + break; + } + Opcode = X86ISD::FMIN; + break; + case ISD::SETUGE: + // This can be a min, but if either operand is a NaN we need it to + // preserve the original LHS. + std::swap(LHS, RHS); + case ISD::SETOGT: + case ISD::SETGT: + case ISD::SETGE: + Opcode = X86ISD::FMIN; + break; + + case ISD::SETULT: + // This can be a max if we can prove that at least one of the operands + // is not a nan. + if (!FiniteOnlyFPMath()) { + if (DAG.isKnownNeverNaN(LHS)) { + // Put the potential NaN in the RHS so that SSE will preserve it. + std::swap(LHS, RHS); + } else if (!DAG.isKnownNeverNaN(RHS)) + break; + } + Opcode = X86ISD::FMAX; + break; + case ISD::SETOLE: + // This can be a max if we can prove that at least one of the operands + // is not a nan. + if (!FiniteOnlyFPMath()) { + if (DAG.isKnownNeverNaN(RHS)) { + // Put the potential NaN in the RHS so that SSE will preserve it. + std::swap(LHS, RHS); + } else if (!DAG.isKnownNeverNaN(LHS)) + break; + } + Opcode = X86ISD::FMAX; + break; + case ISD::SETULE: + // This can be a max, but if either operand is a NaN we need it to + // preserve the original LHS. + std::swap(LHS, RHS); + case ISD::SETOLT: + case ISD::SETLT: + case ISD::SETLE: + Opcode = X86ISD::FMAX; + break; + } + } + + if (Opcode) + return DAG.getNode(Opcode, DL, N->getValueType(0), LHS, RHS); + } + + // If this is a select between two integer constants, try to do some + // optimizations. + if (ConstantSDNode *TrueC = dyn_cast(LHS)) { + if (ConstantSDNode *FalseC = dyn_cast(RHS)) + // Don't do this for crazy integer types. + if (DAG.getTargetLoweringInfo().isTypeLegal(LHS.getValueType())) { + // If this is efficiently invertible, canonicalize the LHSC/RHSC values + // so that TrueC (the true value) is larger than FalseC. + bool NeedsCondInvert = false; + + if (TrueC->getAPIntValue().ult(FalseC->getAPIntValue()) && + // Efficiently invertible. + (Cond.getOpcode() == ISD::SETCC || // setcc -> invertible. + (Cond.getOpcode() == ISD::XOR && // xor(X, C) -> invertible. + isa(Cond.getOperand(1))))) { + NeedsCondInvert = true; + std::swap(TrueC, FalseC); + } + + // Optimize C ? 8 : 0 -> zext(C) << 3. Likewise for any pow2/0. + if (FalseC->getAPIntValue() == 0 && + TrueC->getAPIntValue().isPowerOf2()) { + if (NeedsCondInvert) // Invert the condition if needed. + Cond = DAG.getNode(ISD::XOR, DL, Cond.getValueType(), Cond, + DAG.getConstant(1, Cond.getValueType())); + + // Zero extend the condition if needed. + Cond = DAG.getNode(ISD::ZERO_EXTEND, DL, LHS.getValueType(), Cond); + + unsigned ShAmt = TrueC->getAPIntValue().logBase2(); + return DAG.getNode(ISD::SHL, DL, LHS.getValueType(), Cond, + DAG.getConstant(ShAmt, MVT::i8)); + } + + // Optimize Cond ? cst+1 : cst -> zext(setcc(C)+cst. + if (FalseC->getAPIntValue()+1 == TrueC->getAPIntValue()) { + if (NeedsCondInvert) // Invert the condition if needed. + Cond = DAG.getNode(ISD::XOR, DL, Cond.getValueType(), Cond, + DAG.getConstant(1, Cond.getValueType())); + + // Zero extend the condition if needed. + Cond = DAG.getNode(ISD::ZERO_EXTEND, DL, + FalseC->getValueType(0), Cond); + return DAG.getNode(ISD::ADD, DL, Cond.getValueType(), Cond, + SDValue(FalseC, 0)); + } + + // Optimize cases that will turn into an LEA instruction. This requires + // an i32 or i64 and an efficient multiplier (1, 2, 3, 4, 5, 8, 9). + if (N->getValueType(0) == MVT::i32 || N->getValueType(0) == MVT::i64) { + uint64_t Diff = TrueC->getZExtValue()-FalseC->getZExtValue(); + if (N->getValueType(0) == MVT::i32) Diff = (unsigned)Diff; + + bool isFastMultiplier = false; + if (Diff < 10) { + switch ((unsigned char)Diff) { + default: break; + case 1: // result = add base, cond + case 2: // result = lea base( , cond*2) + case 3: // result = lea base(cond, cond*2) + case 4: // result = lea base( , cond*4) + case 5: // result = lea base(cond, cond*4) + case 8: // result = lea base( , cond*8) + case 9: // result = lea base(cond, cond*8) + isFastMultiplier = true; + break; + } + } + + if (isFastMultiplier) { + APInt Diff = TrueC->getAPIntValue()-FalseC->getAPIntValue(); + if (NeedsCondInvert) // Invert the condition if needed. + Cond = DAG.getNode(ISD::XOR, DL, Cond.getValueType(), Cond, + DAG.getConstant(1, Cond.getValueType())); + + // Zero extend the condition if needed. + Cond = DAG.getNode(ISD::ZERO_EXTEND, DL, FalseC->getValueType(0), + Cond); + // Scale the condition by the difference. + if (Diff != 1) + Cond = DAG.getNode(ISD::MUL, DL, Cond.getValueType(), Cond, + DAG.getConstant(Diff, Cond.getValueType())); + + // Add the base if non-zero. + if (FalseC->getAPIntValue() != 0) + Cond = DAG.getNode(ISD::ADD, DL, Cond.getValueType(), Cond, + SDValue(FalseC, 0)); + return Cond; + } + } + } + } + + return SDValue(); +} + +/// Optimize X86ISD::CMOV [LHS, RHS, CONDCODE (e.g. X86::COND_NE), CONDVAL] +static SDValue PerformCMOVCombine(SDNode *N, SelectionDAG &DAG, + TargetLowering::DAGCombinerInfo &DCI) { + DebugLoc DL = N->getDebugLoc(); + + // If the flag operand isn't dead, don't touch this CMOV. + if (N->getNumValues() == 2 && !SDValue(N, 1).use_empty()) + return SDValue(); + + // If this is a select between two integer constants, try to do some + // optimizations. Note that the operands are ordered the opposite of SELECT + // operands. + if (ConstantSDNode *TrueC = dyn_cast(N->getOperand(1))) { + if (ConstantSDNode *FalseC = dyn_cast(N->getOperand(0))) { + // Canonicalize the TrueC/FalseC values so that TrueC (the true value) is + // larger than FalseC (the false value). + X86::CondCode CC = (X86::CondCode)N->getConstantOperandVal(2); + + if (TrueC->getAPIntValue().ult(FalseC->getAPIntValue())) { + CC = X86::GetOppositeBranchCondition(CC); + std::swap(TrueC, FalseC); + } + + // Optimize C ? 8 : 0 -> zext(setcc(C)) << 3. Likewise for any pow2/0. + // This is efficient for any integer data type (including i8/i16) and + // shift amount. + if (FalseC->getAPIntValue() == 0 && TrueC->getAPIntValue().isPowerOf2()) { + SDValue Cond = N->getOperand(3); + Cond = DAG.getNode(X86ISD::SETCC, DL, MVT::i8, + DAG.getConstant(CC, MVT::i8), Cond); + + // Zero extend the condition if needed. + Cond = DAG.getNode(ISD::ZERO_EXTEND, DL, TrueC->getValueType(0), Cond); + + unsigned ShAmt = TrueC->getAPIntValue().logBase2(); + Cond = DAG.getNode(ISD::SHL, DL, Cond.getValueType(), Cond, + DAG.getConstant(ShAmt, MVT::i8)); + if (N->getNumValues() == 2) // Dead flag value? + return DCI.CombineTo(N, Cond, SDValue()); + return Cond; + } + + // Optimize Cond ? cst+1 : cst -> zext(setcc(C)+cst. This is efficient + // for any integer data type, including i8/i16. + if (FalseC->getAPIntValue()+1 == TrueC->getAPIntValue()) { + SDValue Cond = N->getOperand(3); + Cond = DAG.getNode(X86ISD::SETCC, DL, MVT::i8, + DAG.getConstant(CC, MVT::i8), Cond); + + // Zero extend the condition if needed. + Cond = DAG.getNode(ISD::ZERO_EXTEND, DL, + FalseC->getValueType(0), Cond); + Cond = DAG.getNode(ISD::ADD, DL, Cond.getValueType(), Cond, + SDValue(FalseC, 0)); + + if (N->getNumValues() == 2) // Dead flag value? + return DCI.CombineTo(N, Cond, SDValue()); + return Cond; + } + + // Optimize cases that will turn into an LEA instruction. This requires + // an i32 or i64 and an efficient multiplier (1, 2, 3, 4, 5, 8, 9). + if (N->getValueType(0) == MVT::i32 || N->getValueType(0) == MVT::i64) { + uint64_t Diff = TrueC->getZExtValue()-FalseC->getZExtValue(); + if (N->getValueType(0) == MVT::i32) Diff = (unsigned)Diff; + + bool isFastMultiplier = false; + if (Diff < 10) { + switch ((unsigned char)Diff) { + default: break; + case 1: // result = add base, cond + case 2: // result = lea base( , cond*2) + case 3: // result = lea base(cond, cond*2) + case 4: // result = lea base( , cond*4) + case 5: // result = lea base(cond, cond*4) + case 8: // result = lea base( , cond*8) + case 9: // result = lea base(cond, cond*8) + isFastMultiplier = true; + break; + } + } + + if (isFastMultiplier) { + APInt Diff = TrueC->getAPIntValue()-FalseC->getAPIntValue(); + SDValue Cond = N->getOperand(3); + Cond = DAG.getNode(X86ISD::SETCC, DL, MVT::i8, + DAG.getConstant(CC, MVT::i8), Cond); + // Zero extend the condition if needed. + Cond = DAG.getNode(ISD::ZERO_EXTEND, DL, FalseC->getValueType(0), + Cond); + // Scale the condition by the difference. + if (Diff != 1) + Cond = DAG.getNode(ISD::MUL, DL, Cond.getValueType(), Cond, + DAG.getConstant(Diff, Cond.getValueType())); + + // Add the base if non-zero. + if (FalseC->getAPIntValue() != 0) + Cond = DAG.getNode(ISD::ADD, DL, Cond.getValueType(), Cond, + SDValue(FalseC, 0)); + if (N->getNumValues() == 2) // Dead flag value? + return DCI.CombineTo(N, Cond, SDValue()); + return Cond; + } + } + } + } + return SDValue(); +} + + +/// PerformMulCombine - Optimize a single multiply with constant into two +/// in order to implement it with two cheaper instructions, e.g. +/// LEA + SHL, LEA + LEA. +static SDValue PerformMulCombine(SDNode *N, SelectionDAG &DAG, + TargetLowering::DAGCombinerInfo &DCI) { + if (DAG.getMachineFunction(). + getFunction()->hasFnAttr(Attribute::OptimizeForSize)) + return SDValue(); + + if (DCI.isBeforeLegalize() || DCI.isCalledByLegalizer()) + return SDValue(); + + EVT VT = N->getValueType(0); + if (VT != MVT::i64) + return SDValue(); + + ConstantSDNode *C = dyn_cast(N->getOperand(1)); + if (!C) + return SDValue(); + uint64_t MulAmt = C->getZExtValue(); + if (isPowerOf2_64(MulAmt) || MulAmt == 3 || MulAmt == 5 || MulAmt == 9) + return SDValue(); + + uint64_t MulAmt1 = 0; + uint64_t MulAmt2 = 0; + if ((MulAmt % 9) == 0) { + MulAmt1 = 9; + MulAmt2 = MulAmt / 9; + } else if ((MulAmt % 5) == 0) { + MulAmt1 = 5; + MulAmt2 = MulAmt / 5; + } else if ((MulAmt % 3) == 0) { + MulAmt1 = 3; + MulAmt2 = MulAmt / 3; + } + if (MulAmt2 && + (isPowerOf2_64(MulAmt2) || MulAmt2 == 3 || MulAmt2 == 5 || MulAmt2 == 9)){ + DebugLoc DL = N->getDebugLoc(); + + if (isPowerOf2_64(MulAmt2) && + !(N->hasOneUse() && N->use_begin()->getOpcode() == ISD::ADD)) + // If second multiplifer is pow2, issue it first. We want the multiply by + // 3, 5, or 9 to be folded into the addressing mode unless the lone use + // is an add. + std::swap(MulAmt1, MulAmt2); + + SDValue NewMul; + if (isPowerOf2_64(MulAmt1)) + NewMul = DAG.getNode(ISD::SHL, DL, VT, N->getOperand(0), + DAG.getConstant(Log2_64(MulAmt1), MVT::i8)); + else + NewMul = DAG.getNode(X86ISD::MUL_IMM, DL, VT, N->getOperand(0), + DAG.getConstant(MulAmt1, VT)); + + if (isPowerOf2_64(MulAmt2)) + NewMul = DAG.getNode(ISD::SHL, DL, VT, NewMul, + DAG.getConstant(Log2_64(MulAmt2), MVT::i8)); + else + NewMul = DAG.getNode(X86ISD::MUL_IMM, DL, VT, NewMul, + DAG.getConstant(MulAmt2, VT)); + + // Do not add new nodes to DAG combiner worklist. + DCI.CombineTo(N, NewMul, false); + } + return SDValue(); +} + + +/// PerformShiftCombine - Transforms vector shift nodes to use vector shifts +/// when possible. +static SDValue PerformShiftCombine(SDNode* N, SelectionDAG &DAG, + const X86Subtarget *Subtarget) { + // On X86 with SSE2 support, we can transform this to a vector shift if + // all elements are shifted by the same amount. We can't do this in legalize + // because the a constant vector is typically transformed to a constant pool + // so we have no knowledge of the shift amount. + if (!Subtarget->hasSSE2()) + return SDValue(); + + EVT VT = N->getValueType(0); + if (VT != MVT::v2i64 && VT != MVT::v4i32 && VT != MVT::v8i16) + return SDValue(); + + SDValue ShAmtOp = N->getOperand(1); + EVT EltVT = VT.getVectorElementType(); + DebugLoc DL = N->getDebugLoc(); + SDValue BaseShAmt = SDValue(); + if (ShAmtOp.getOpcode() == ISD::BUILD_VECTOR) { + unsigned NumElts = VT.getVectorNumElements(); + unsigned i = 0; + for (; i != NumElts; ++i) { + SDValue Arg = ShAmtOp.getOperand(i); + if (Arg.getOpcode() == ISD::UNDEF) continue; + BaseShAmt = Arg; + break; + } + for (; i != NumElts; ++i) { + SDValue Arg = ShAmtOp.getOperand(i); + if (Arg.getOpcode() == ISD::UNDEF) continue; + if (Arg != BaseShAmt) { + return SDValue(); + } + } + } else if (ShAmtOp.getOpcode() == ISD::VECTOR_SHUFFLE && + cast(ShAmtOp)->isSplat()) { + SDValue InVec = ShAmtOp.getOperand(0); + if (InVec.getOpcode() == ISD::BUILD_VECTOR) { + unsigned NumElts = InVec.getValueType().getVectorNumElements(); + unsigned i = 0; + for (; i != NumElts; ++i) { + SDValue Arg = InVec.getOperand(i); + if (Arg.getOpcode() == ISD::UNDEF) continue; + BaseShAmt = Arg; + break; + } + } else if (InVec.getOpcode() == ISD::INSERT_VECTOR_ELT) { + if (ConstantSDNode *C = dyn_cast(InVec.getOperand(2))) { + unsigned SplatIdx = cast(ShAmtOp)->getSplatIndex(); + if (C->getZExtValue() == SplatIdx) + BaseShAmt = InVec.getOperand(1); + } + } + if (BaseShAmt.getNode() == 0) + BaseShAmt = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, EltVT, ShAmtOp, + DAG.getIntPtrConstant(0)); + } else + return SDValue(); + + // The shift amount is an i32. + if (EltVT.bitsGT(MVT::i32)) + BaseShAmt = DAG.getNode(ISD::TRUNCATE, DL, MVT::i32, BaseShAmt); + else if (EltVT.bitsLT(MVT::i32)) + BaseShAmt = DAG.getNode(ISD::ZERO_EXTEND, DL, MVT::i32, BaseShAmt); + + // The shift amount is identical so we can do a vector shift. + SDValue ValOp = N->getOperand(0); + switch (N->getOpcode()) { + default: + llvm_unreachable("Unknown shift opcode!"); + break; + case ISD::SHL: + if (VT == MVT::v2i64) + return DAG.getNode(ISD::INTRINSIC_WO_CHAIN, DL, VT, + DAG.getConstant(Intrinsic::x86_sse2_pslli_q, MVT::i32), + ValOp, BaseShAmt); + if (VT == MVT::v4i32) + return DAG.getNode(ISD::INTRINSIC_WO_CHAIN, DL, VT, + DAG.getConstant(Intrinsic::x86_sse2_pslli_d, MVT::i32), + ValOp, BaseShAmt); + if (VT == MVT::v8i16) + return DAG.getNode(ISD::INTRINSIC_WO_CHAIN, DL, VT, + DAG.getConstant(Intrinsic::x86_sse2_pslli_w, MVT::i32), + ValOp, BaseShAmt); + break; + case ISD::SRA: + if (VT == MVT::v4i32) + return DAG.getNode(ISD::INTRINSIC_WO_CHAIN, DL, VT, + DAG.getConstant(Intrinsic::x86_sse2_psrai_d, MVT::i32), + ValOp, BaseShAmt); + if (VT == MVT::v8i16) + return DAG.getNode(ISD::INTRINSIC_WO_CHAIN, DL, VT, + DAG.getConstant(Intrinsic::x86_sse2_psrai_w, MVT::i32), + ValOp, BaseShAmt); + break; + case ISD::SRL: + if (VT == MVT::v2i64) + return DAG.getNode(ISD::INTRINSIC_WO_CHAIN, DL, VT, + DAG.getConstant(Intrinsic::x86_sse2_psrli_q, MVT::i32), + ValOp, BaseShAmt); + if (VT == MVT::v4i32) + return DAG.getNode(ISD::INTRINSIC_WO_CHAIN, DL, VT, + DAG.getConstant(Intrinsic::x86_sse2_psrli_d, MVT::i32), + ValOp, BaseShAmt); + if (VT == MVT::v8i16) + return DAG.getNode(ISD::INTRINSIC_WO_CHAIN, DL, VT, + DAG.getConstant(Intrinsic::x86_sse2_psrli_w, MVT::i32), + ValOp, BaseShAmt); + break; + } + return SDValue(); +} + +/// PerformSTORECombine - Do target-specific dag combines on STORE nodes. +static SDValue PerformSTORECombine(SDNode *N, SelectionDAG &DAG, + const X86Subtarget *Subtarget) { + // Turn load->store of MMX types into GPR load/stores. This avoids clobbering + // the FP state in cases where an emms may be missing. + // A preferable solution to the general problem is to figure out the right + // places to insert EMMS. This qualifies as a quick hack. + + // Similarly, turn load->store of i64 into double load/stores in 32-bit mode. + StoreSDNode *St = cast(N); + EVT VT = St->getValue().getValueType(); + if (VT.getSizeInBits() != 64) + return SDValue(); + + const Function *F = DAG.getMachineFunction().getFunction(); + bool NoImplicitFloatOps = F->hasFnAttr(Attribute::NoImplicitFloat); + bool F64IsLegal = !UseSoftFloat && !NoImplicitFloatOps + && Subtarget->hasSSE2(); + if ((VT.isVector() || + (VT == MVT::i64 && F64IsLegal && !Subtarget->is64Bit())) && + isa(St->getValue()) && + !cast(St->getValue())->isVolatile() && + St->getChain().hasOneUse() && !St->isVolatile()) { + SDNode* LdVal = St->getValue().getNode(); + LoadSDNode *Ld = 0; + int TokenFactorIndex = -1; + SmallVector Ops; + SDNode* ChainVal = St->getChain().getNode(); + // Must be a store of a load. We currently handle two cases: the load + // is a direct child, and it's under an intervening TokenFactor. It is + // possible to dig deeper under nested TokenFactors. + if (ChainVal == LdVal) + Ld = cast(St->getChain()); + else if (St->getValue().hasOneUse() && + ChainVal->getOpcode() == ISD::TokenFactor) { + for (unsigned i=0, e = ChainVal->getNumOperands(); i != e; ++i) { + if (ChainVal->getOperand(i).getNode() == LdVal) { + TokenFactorIndex = i; + Ld = cast(St->getValue()); + } else + Ops.push_back(ChainVal->getOperand(i)); + } + } + + if (!Ld || !ISD::isNormalLoad(Ld)) + return SDValue(); + + // If this is not the MMX case, i.e. we are just turning i64 load/store + // into f64 load/store, avoid the transformation if there are multiple + // uses of the loaded value. + if (!VT.isVector() && !Ld->hasNUsesOfValue(1, 0)) + return SDValue(); + + DebugLoc LdDL = Ld->getDebugLoc(); + DebugLoc StDL = N->getDebugLoc(); + // If we are a 64-bit capable x86, lower to a single movq load/store pair. + // Otherwise, if it's legal to use f64 SSE instructions, use f64 load/store + // pair instead. + if (Subtarget->is64Bit() || F64IsLegal) { + EVT LdVT = Subtarget->is64Bit() ? MVT::i64 : MVT::f64; + SDValue NewLd = DAG.getLoad(LdVT, LdDL, Ld->getChain(), + Ld->getBasePtr(), Ld->getSrcValue(), + Ld->getSrcValueOffset(), Ld->isVolatile(), + Ld->getAlignment()); + SDValue NewChain = NewLd.getValue(1); + if (TokenFactorIndex != -1) { + Ops.push_back(NewChain); + NewChain = DAG.getNode(ISD::TokenFactor, LdDL, MVT::Other, &Ops[0], + Ops.size()); + } + return DAG.getStore(NewChain, StDL, NewLd, St->getBasePtr(), + St->getSrcValue(), St->getSrcValueOffset(), + St->isVolatile(), St->getAlignment()); + } + + // Otherwise, lower to two pairs of 32-bit loads / stores. + SDValue LoAddr = Ld->getBasePtr(); + SDValue HiAddr = DAG.getNode(ISD::ADD, LdDL, MVT::i32, LoAddr, + DAG.getConstant(4, MVT::i32)); + + SDValue LoLd = DAG.getLoad(MVT::i32, LdDL, Ld->getChain(), LoAddr, + Ld->getSrcValue(), Ld->getSrcValueOffset(), + Ld->isVolatile(), Ld->getAlignment()); + SDValue HiLd = DAG.getLoad(MVT::i32, LdDL, Ld->getChain(), HiAddr, + Ld->getSrcValue(), Ld->getSrcValueOffset()+4, + Ld->isVolatile(), + MinAlign(Ld->getAlignment(), 4)); + + SDValue NewChain = LoLd.getValue(1); + if (TokenFactorIndex != -1) { + Ops.push_back(LoLd); + Ops.push_back(HiLd); + NewChain = DAG.getNode(ISD::TokenFactor, LdDL, MVT::Other, &Ops[0], + Ops.size()); + } + + LoAddr = St->getBasePtr(); + HiAddr = DAG.getNode(ISD::ADD, StDL, MVT::i32, LoAddr, + DAG.getConstant(4, MVT::i32)); + + SDValue LoSt = DAG.getStore(NewChain, StDL, LoLd, LoAddr, + St->getSrcValue(), St->getSrcValueOffset(), + St->isVolatile(), St->getAlignment()); + SDValue HiSt = DAG.getStore(NewChain, StDL, HiLd, HiAddr, + St->getSrcValue(), + St->getSrcValueOffset() + 4, + St->isVolatile(), + MinAlign(St->getAlignment(), 4)); + return DAG.getNode(ISD::TokenFactor, StDL, MVT::Other, LoSt, HiSt); + } + return SDValue(); +} + +/// PerformFORCombine - Do target-specific dag combines on X86ISD::FOR and +/// X86ISD::FXOR nodes. +static SDValue PerformFORCombine(SDNode *N, SelectionDAG &DAG) { + assert(N->getOpcode() == X86ISD::FOR || N->getOpcode() == X86ISD::FXOR); + // F[X]OR(0.0, x) -> x + // F[X]OR(x, 0.0) -> x + if (ConstantFPSDNode *C = dyn_cast(N->getOperand(0))) + if (C->getValueAPF().isPosZero()) + return N->getOperand(1); + if (ConstantFPSDNode *C = dyn_cast(N->getOperand(1))) + if (C->getValueAPF().isPosZero()) + return N->getOperand(0); + return SDValue(); +} + +/// PerformFANDCombine - Do target-specific dag combines on X86ISD::FAND nodes. +static SDValue PerformFANDCombine(SDNode *N, SelectionDAG &DAG) { + // FAND(0.0, x) -> 0.0 + // FAND(x, 0.0) -> 0.0 + if (ConstantFPSDNode *C = dyn_cast(N->getOperand(0))) + if (C->getValueAPF().isPosZero()) + return N->getOperand(0); + if (ConstantFPSDNode *C = dyn_cast(N->getOperand(1))) + if (C->getValueAPF().isPosZero()) + return N->getOperand(1); + return SDValue(); +} + +static SDValue PerformBTCombine(SDNode *N, + SelectionDAG &DAG, + TargetLowering::DAGCombinerInfo &DCI) { + // BT ignores high bits in the bit index operand. + SDValue Op1 = N->getOperand(1); + if (Op1.hasOneUse()) { + unsigned BitWidth = Op1.getValueSizeInBits(); + APInt DemandedMask = APInt::getLowBitsSet(BitWidth, Log2_32(BitWidth)); + APInt KnownZero, KnownOne; + TargetLowering::TargetLoweringOpt TLO(DAG); + TargetLowering &TLI = DAG.getTargetLoweringInfo(); + if (TLO.ShrinkDemandedConstant(Op1, DemandedMask) || + TLI.SimplifyDemandedBits(Op1, DemandedMask, KnownZero, KnownOne, TLO)) + DCI.CommitTargetLoweringOpt(TLO); + } + return SDValue(); +} + +static SDValue PerformVZEXT_MOVLCombine(SDNode *N, SelectionDAG &DAG) { + SDValue Op = N->getOperand(0); + if (Op.getOpcode() == ISD::BIT_CONVERT) + Op = Op.getOperand(0); + EVT VT = N->getValueType(0), OpVT = Op.getValueType(); + if (Op.getOpcode() == X86ISD::VZEXT_LOAD && + VT.getVectorElementType().getSizeInBits() == + OpVT.getVectorElementType().getSizeInBits()) { + return DAG.getNode(ISD::BIT_CONVERT, N->getDebugLoc(), VT, Op); + } + return SDValue(); +} + +// On X86 and X86-64, atomic operations are lowered to locked instructions. +// Locked instructions, in turn, have implicit fence semantics (all memory +// operations are flushed before issuing the locked instruction, and the +// are not buffered), so we can fold away the common pattern of +// fence-atomic-fence. +static SDValue PerformMEMBARRIERCombine(SDNode* N, SelectionDAG &DAG) { + SDValue atomic = N->getOperand(0); + switch (atomic.getOpcode()) { + case ISD::ATOMIC_CMP_SWAP: + case ISD::ATOMIC_SWAP: + case ISD::ATOMIC_LOAD_ADD: + case ISD::ATOMIC_LOAD_SUB: + case ISD::ATOMIC_LOAD_AND: + case ISD::ATOMIC_LOAD_OR: + case ISD::ATOMIC_LOAD_XOR: + case ISD::ATOMIC_LOAD_NAND: + case ISD::ATOMIC_LOAD_MIN: + case ISD::ATOMIC_LOAD_MAX: + case ISD::ATOMIC_LOAD_UMIN: + case ISD::ATOMIC_LOAD_UMAX: + break; + default: + return SDValue(); + } + + SDValue fence = atomic.getOperand(0); + if (fence.getOpcode() != ISD::MEMBARRIER) + return SDValue(); + + switch (atomic.getOpcode()) { + case ISD::ATOMIC_CMP_SWAP: + return DAG.UpdateNodeOperands(atomic, fence.getOperand(0), + atomic.getOperand(1), atomic.getOperand(2), + atomic.getOperand(3)); + case ISD::ATOMIC_SWAP: + case ISD::ATOMIC_LOAD_ADD: + case ISD::ATOMIC_LOAD_SUB: + case ISD::ATOMIC_LOAD_AND: + case ISD::ATOMIC_LOAD_OR: + case ISD::ATOMIC_LOAD_XOR: + case ISD::ATOMIC_LOAD_NAND: + case ISD::ATOMIC_LOAD_MIN: + case ISD::ATOMIC_LOAD_MAX: + case ISD::ATOMIC_LOAD_UMIN: + case ISD::ATOMIC_LOAD_UMAX: + return DAG.UpdateNodeOperands(atomic, fence.getOperand(0), + atomic.getOperand(1), atomic.getOperand(2)); + default: + return SDValue(); + } +} + +SDValue X86TargetLowering::PerformDAGCombine(SDNode *N, + DAGCombinerInfo &DCI) const { + SelectionDAG &DAG = DCI.DAG; + switch (N->getOpcode()) { + default: break; + case ISD::VECTOR_SHUFFLE: return PerformShuffleCombine(N, DAG, *this); + case ISD::SELECT: return PerformSELECTCombine(N, DAG, Subtarget); + case X86ISD::CMOV: return PerformCMOVCombine(N, DAG, DCI); + case ISD::MUL: return PerformMulCombine(N, DAG, DCI); + case ISD::SHL: + case ISD::SRA: + case ISD::SRL: return PerformShiftCombine(N, DAG, Subtarget); + case ISD::STORE: return PerformSTORECombine(N, DAG, Subtarget); + case X86ISD::FXOR: + case X86ISD::FOR: return PerformFORCombine(N, DAG); + case X86ISD::FAND: return PerformFANDCombine(N, DAG); + case X86ISD::BT: return PerformBTCombine(N, DAG, DCI); + case X86ISD::VZEXT_MOVL: return PerformVZEXT_MOVLCombine(N, DAG); + case ISD::MEMBARRIER: return PerformMEMBARRIERCombine(N, DAG); + } + + return SDValue(); +} + +//===----------------------------------------------------------------------===// +// X86 Inline Assembly Support +//===----------------------------------------------------------------------===// + +static bool LowerToBSwap(CallInst *CI) { + // FIXME: this should verify that we are targetting a 486 or better. If not, + // we will turn this bswap into something that will be lowered to logical ops + // instead of emitting the bswap asm. For now, we don't support 486 or lower + // so don't worry about this. + + // Verify this is a simple bswap. + if (CI->getNumOperands() != 2 || + CI->getType() != CI->getOperand(1)->getType() || + !CI->getType()->isInteger()) + return false; + + const IntegerType *Ty = dyn_cast(CI->getType()); + if (!Ty || Ty->getBitWidth() % 16 != 0) + return false; + + // Okay, we can do this xform, do so now. + const Type *Tys[] = { Ty }; + Module *M = CI->getParent()->getParent()->getParent(); + Constant *Int = Intrinsic::getDeclaration(M, Intrinsic::bswap, Tys, 1); + + Value *Op = CI->getOperand(1); + Op = CallInst::Create(Int, Op, CI->getName(), CI); + + CI->replaceAllUsesWith(Op); + CI->eraseFromParent(); + return true; +} + +bool X86TargetLowering::ExpandInlineAsm(CallInst *CI) const { + InlineAsm *IA = cast(CI->getCalledValue()); + std::vector Constraints = IA->ParseConstraints(); + + std::string AsmStr = IA->getAsmString(); + + // TODO: should remove alternatives from the asmstring: "foo {a|b}" -> "foo a" + std::vector AsmPieces; + SplitString(AsmStr, AsmPieces, "\n"); // ; as separator? + + switch (AsmPieces.size()) { + default: return false; + case 1: + AsmStr = AsmPieces[0]; + AsmPieces.clear(); + SplitString(AsmStr, AsmPieces, " \t"); // Split with whitespace. + + // bswap $0 + if (AsmPieces.size() == 2 && + (AsmPieces[0] == "bswap" || + AsmPieces[0] == "bswapq" || + AsmPieces[0] == "bswapl") && + (AsmPieces[1] == "$0" || + AsmPieces[1] == "${0:q}")) { + // No need to check constraints, nothing other than the equivalent of + // "=r,0" would be valid here. + return LowerToBSwap(CI); + } + // rorw $$8, ${0:w} --> llvm.bswap.i16 + if (CI->getType() == Type::getInt16Ty(CI->getContext()) && + AsmPieces.size() == 3 && + AsmPieces[0] == "rorw" && + AsmPieces[1] == "$$8," && + AsmPieces[2] == "${0:w}" && + IA->getConstraintString() == "=r,0,~{dirflag},~{fpsr},~{flags},~{cc}") { + return LowerToBSwap(CI); + } + break; + case 3: + if (CI->getType() == Type::getInt64Ty(CI->getContext()) && + Constraints.size() >= 2 && + Constraints[0].Codes.size() == 1 && Constraints[0].Codes[0] == "A" && + Constraints[1].Codes.size() == 1 && Constraints[1].Codes[0] == "0") { + // bswap %eax / bswap %edx / xchgl %eax, %edx -> llvm.bswap.i64 + std::vector Words; + SplitString(AsmPieces[0], Words, " \t"); + if (Words.size() == 2 && Words[0] == "bswap" && Words[1] == "%eax") { + Words.clear(); + SplitString(AsmPieces[1], Words, " \t"); + if (Words.size() == 2 && Words[0] == "bswap" && Words[1] == "%edx") { + Words.clear(); + SplitString(AsmPieces[2], Words, " \t,"); + if (Words.size() == 3 && Words[0] == "xchgl" && Words[1] == "%eax" && + Words[2] == "%edx") { + return LowerToBSwap(CI); + } + } + } + } + break; + } + return false; +} + + + +/// getConstraintType - Given a constraint letter, return the type of +/// constraint it is for this target. +X86TargetLowering::ConstraintType +X86TargetLowering::getConstraintType(const std::string &Constraint) const { + if (Constraint.size() == 1) { + switch (Constraint[0]) { + case 'A': + return C_Register; + case 'f': + case 'r': + case 'R': + case 'l': + case 'q': + case 'Q': + case 'x': + case 'y': + case 'Y': + return C_RegisterClass; + case 'e': + case 'Z': + return C_Other; + default: + break; + } + } + return TargetLowering::getConstraintType(Constraint); +} + +/// LowerXConstraint - try to replace an X constraint, which matches anything, +/// with another that has more specific requirements based on the type of the +/// corresponding operand. +const char *X86TargetLowering:: +LowerXConstraint(EVT ConstraintVT) const { + // FP X constraints get lowered to SSE1/2 registers if available, otherwise + // 'f' like normal targets. + if (ConstraintVT.isFloatingPoint()) { + if (Subtarget->hasSSE2()) + return "Y"; + if (Subtarget->hasSSE1()) + return "x"; + } + + return TargetLowering::LowerXConstraint(ConstraintVT); +} + +/// LowerAsmOperandForConstraint - Lower the specified operand into the Ops +/// vector. If it is invalid, don't add anything to Ops. +void X86TargetLowering::LowerAsmOperandForConstraint(SDValue Op, + char Constraint, + bool hasMemory, + std::vector&Ops, + SelectionDAG &DAG) const { + SDValue Result(0, 0); + + switch (Constraint) { + default: break; + case 'I': + if (ConstantSDNode *C = dyn_cast(Op)) { + if (C->getZExtValue() <= 31) { + Result = DAG.getTargetConstant(C->getZExtValue(), Op.getValueType()); + break; + } + } + return; + case 'J': + if (ConstantSDNode *C = dyn_cast(Op)) { + if (C->getZExtValue() <= 63) { + Result = DAG.getTargetConstant(C->getZExtValue(), Op.getValueType()); + break; + } + } + return; + case 'K': + if (ConstantSDNode *C = dyn_cast(Op)) { + if ((int8_t)C->getSExtValue() == C->getSExtValue()) { + Result = DAG.getTargetConstant(C->getZExtValue(), Op.getValueType()); + break; + } + } + return; + case 'N': + if (ConstantSDNode *C = dyn_cast(Op)) { + if (C->getZExtValue() <= 255) { + Result = DAG.getTargetConstant(C->getZExtValue(), Op.getValueType()); + break; + } + } + return; + case 'e': { + // 32-bit signed value + if (ConstantSDNode *C = dyn_cast(Op)) { + const ConstantInt *CI = C->getConstantIntValue(); + if (CI->isValueValidForType(Type::getInt32Ty(*DAG.getContext()), + C->getSExtValue())) { + // Widen to 64 bits here to get it sign extended. + Result = DAG.getTargetConstant(C->getSExtValue(), MVT::i64); + break; + } + // FIXME gcc accepts some relocatable values here too, but only in certain + // memory models; it's complicated. + } + return; + } + case 'Z': { + // 32-bit unsigned value + if (ConstantSDNode *C = dyn_cast(Op)) { + const ConstantInt *CI = C->getConstantIntValue(); + if (CI->isValueValidForType(Type::getInt32Ty(*DAG.getContext()), + C->getZExtValue())) { + Result = DAG.getTargetConstant(C->getZExtValue(), Op.getValueType()); + break; + } + } + // FIXME gcc accepts some relocatable values here too, but only in certain + // memory models; it's complicated. + return; + } + case 'i': { + // Literal immediates are always ok. + if (ConstantSDNode *CST = dyn_cast(Op)) { + // Widen to 64 bits here to get it sign extended. + Result = DAG.getTargetConstant(CST->getSExtValue(), MVT::i64); + break; + } + + // If we are in non-pic codegen mode, we allow the address of a global (with + // an optional displacement) to be used with 'i'. + GlobalAddressSDNode *GA = 0; + int64_t Offset = 0; + + // Match either (GA), (GA+C), (GA+C1+C2), etc. + while (1) { + if ((GA = dyn_cast(Op))) { + Offset += GA->getOffset(); + break; + } else if (Op.getOpcode() == ISD::ADD) { + if (ConstantSDNode *C = dyn_cast(Op.getOperand(1))) { + Offset += C->getZExtValue(); + Op = Op.getOperand(0); + continue; + } + } else if (Op.getOpcode() == ISD::SUB) { + if (ConstantSDNode *C = dyn_cast(Op.getOperand(1))) { + Offset += -C->getZExtValue(); + Op = Op.getOperand(0); + continue; + } + } + + // Otherwise, this isn't something we can handle, reject it. + return; + } + + GlobalValue *GV = GA->getGlobal(); + // If we require an extra load to get this address, as in PIC mode, we + // can't accept it. + if (isGlobalStubReference(Subtarget->ClassifyGlobalReference(GV, + getTargetMachine()))) + return; + + if (hasMemory) + Op = LowerGlobalAddress(GV, Op.getDebugLoc(), Offset, DAG); + else + Op = DAG.getTargetGlobalAddress(GV, GA->getValueType(0), Offset); + Result = Op; + break; + } + } + + if (Result.getNode()) { + Ops.push_back(Result); + return; + } + return TargetLowering::LowerAsmOperandForConstraint(Op, Constraint, hasMemory, + Ops, DAG); +} + +std::vector X86TargetLowering:: +getRegClassForInlineAsmConstraint(const std::string &Constraint, + EVT VT) const { + if (Constraint.size() == 1) { + // FIXME: not handling fp-stack yet! + switch (Constraint[0]) { // GCC X86 Constraint Letters + default: break; // Unknown constraint letter + case 'q': // GENERAL_REGS in 64-bit mode, Q_REGS in 32-bit mode. + if (Subtarget->is64Bit()) { + if (VT == MVT::i32) + return make_vector(X86::EAX, X86::EDX, X86::ECX, X86::EBX, + X86::ESI, X86::EDI, X86::R8D, X86::R9D, + X86::R10D,X86::R11D,X86::R12D, + X86::R13D,X86::R14D,X86::R15D, + X86::EBP, X86::ESP, 0); + else if (VT == MVT::i16) + return make_vector(X86::AX, X86::DX, X86::CX, X86::BX, + X86::SI, X86::DI, X86::R8W,X86::R9W, + X86::R10W,X86::R11W,X86::R12W, + X86::R13W,X86::R14W,X86::R15W, + X86::BP, X86::SP, 0); + else if (VT == MVT::i8) + return make_vector(X86::AL, X86::DL, X86::CL, X86::BL, + X86::SIL, X86::DIL, X86::R8B,X86::R9B, + X86::R10B,X86::R11B,X86::R12B, + X86::R13B,X86::R14B,X86::R15B, + X86::BPL, X86::SPL, 0); + + else if (VT == MVT::i64) + return make_vector(X86::RAX, X86::RDX, X86::RCX, X86::RBX, + X86::RSI, X86::RDI, X86::R8, X86::R9, + X86::R10, X86::R11, X86::R12, + X86::R13, X86::R14, X86::R15, + X86::RBP, X86::RSP, 0); + + break; + } + // 32-bit fallthrough + case 'Q': // Q_REGS + if (VT == MVT::i32) + return make_vector(X86::EAX, X86::EDX, X86::ECX, X86::EBX, 0); + else if (VT == MVT::i16) + return make_vector(X86::AX, X86::DX, X86::CX, X86::BX, 0); + else if (VT == MVT::i8) + return make_vector(X86::AL, X86::DL, X86::CL, X86::BL, 0); + else if (VT == MVT::i64) + return make_vector(X86::RAX, X86::RDX, X86::RCX, X86::RBX, 0); + break; + } + } + + return std::vector(); +} + +std::pair +X86TargetLowering::getRegForInlineAsmConstraint(const std::string &Constraint, + EVT VT) const { + // First, see if this is a constraint that directly corresponds to an LLVM + // register class. + if (Constraint.size() == 1) { + // GCC Constraint Letters + switch (Constraint[0]) { + default: break; + case 'r': // GENERAL_REGS + case 'l': // INDEX_REGS + if (VT == MVT::i8) + return std::make_pair(0U, X86::GR8RegisterClass); + if (VT == MVT::i16) + return std::make_pair(0U, X86::GR16RegisterClass); + if (VT == MVT::i32 || !Subtarget->is64Bit()) + return std::make_pair(0U, X86::GR32RegisterClass); + return std::make_pair(0U, X86::GR64RegisterClass); + case 'R': // LEGACY_REGS + if (VT == MVT::i8) + return std::make_pair(0U, X86::GR8_NOREXRegisterClass); + if (VT == MVT::i16) + return std::make_pair(0U, X86::GR16_NOREXRegisterClass); + if (VT == MVT::i32 || !Subtarget->is64Bit()) + return std::make_pair(0U, X86::GR32_NOREXRegisterClass); + return std::make_pair(0U, X86::GR64_NOREXRegisterClass); + case 'f': // FP Stack registers. + // If SSE is enabled for this VT, use f80 to ensure the isel moves the + // value to the correct fpstack register class. + if (VT == MVT::f32 && !isScalarFPTypeInSSEReg(VT)) + return std::make_pair(0U, X86::RFP32RegisterClass); + if (VT == MVT::f64 && !isScalarFPTypeInSSEReg(VT)) + return std::make_pair(0U, X86::RFP64RegisterClass); + return std::make_pair(0U, X86::RFP80RegisterClass); + case 'y': // MMX_REGS if MMX allowed. + if (!Subtarget->hasMMX()) break; + return std::make_pair(0U, X86::VR64RegisterClass); + case 'Y': // SSE_REGS if SSE2 allowed + if (!Subtarget->hasSSE2()) break; + // FALL THROUGH. + case 'x': // SSE_REGS if SSE1 allowed + if (!Subtarget->hasSSE1()) break; + + switch (VT.getSimpleVT().SimpleTy) { + default: break; + // Scalar SSE types. + case MVT::f32: + case MVT::i32: + return std::make_pair(0U, X86::FR32RegisterClass); + case MVT::f64: + case MVT::i64: + return std::make_pair(0U, X86::FR64RegisterClass); + // Vector types. + case MVT::v16i8: + case MVT::v8i16: + case MVT::v4i32: + case MVT::v2i64: + case MVT::v4f32: + case MVT::v2f64: + return std::make_pair(0U, X86::VR128RegisterClass); + } + break; + } + } + + // Use the default implementation in TargetLowering to convert the register + // constraint into a member of a register class. + std::pair Res; + Res = TargetLowering::getRegForInlineAsmConstraint(Constraint, VT); + + // Not found as a standard register? + if (Res.second == 0) { + // Map st(0) -> st(7) -> ST0 + if (Constraint.size() == 7 && Constraint[0] == '{' && + tolower(Constraint[1]) == 's' && + tolower(Constraint[2]) == 't' && + Constraint[3] == '(' && + (Constraint[4] >= '0' && Constraint[4] <= '7') && + Constraint[5] == ')' && + Constraint[6] == '}') { + + Res.first = X86::ST0+Constraint[4]-'0'; + Res.second = X86::RFP80RegisterClass; + return Res; + } + + // GCC allows "st(0)" to be called just plain "st". + if (StringRef("{st}").equals_lower(Constraint)) { + Res.first = X86::ST0; + Res.second = X86::RFP80RegisterClass; + return Res; + } + + // flags -> EFLAGS + if (StringRef("{flags}").equals_lower(Constraint)) { + Res.first = X86::EFLAGS; + Res.second = X86::CCRRegisterClass; + return Res; + } + + // 'A' means EAX + EDX. + if (Constraint == "A") { + Res.first = X86::EAX; + Res.second = X86::GR32_ADRegisterClass; + return Res; + } + return Res; + } + + // Otherwise, check to see if this is a register class of the wrong value + // type. For example, we want to map "{ax},i32" -> {eax}, we don't want it to + // turn into {ax},{dx}. + if (Res.second->hasType(VT)) + return Res; // Correct type already, nothing to do. + + // All of the single-register GCC register classes map their values onto + // 16-bit register pieces "ax","dx","cx","bx","si","di","bp","sp". If we + // really want an 8-bit or 32-bit register, map to the appropriate register + // class and return the appropriate register. + if (Res.second == X86::GR16RegisterClass) { + if (VT == MVT::i8) { + unsigned DestReg = 0; + switch (Res.first) { + default: break; + case X86::AX: DestReg = X86::AL; break; + case X86::DX: DestReg = X86::DL; break; + case X86::CX: DestReg = X86::CL; break; + case X86::BX: DestReg = X86::BL; break; + } + if (DestReg) { + Res.first = DestReg; + Res.second = X86::GR8RegisterClass; + } + } else if (VT == MVT::i32) { + unsigned DestReg = 0; + switch (Res.first) { + default: break; + case X86::AX: DestReg = X86::EAX; break; + case X86::DX: DestReg = X86::EDX; break; + case X86::CX: DestReg = X86::ECX; break; + case X86::BX: DestReg = X86::EBX; break; + case X86::SI: DestReg = X86::ESI; break; + case X86::DI: DestReg = X86::EDI; break; + case X86::BP: DestReg = X86::EBP; break; + case X86::SP: DestReg = X86::ESP; break; + } + if (DestReg) { + Res.first = DestReg; + Res.second = X86::GR32RegisterClass; + } + } else if (VT == MVT::i64) { + unsigned DestReg = 0; + switch (Res.first) { + default: break; + case X86::AX: DestReg = X86::RAX; break; + case X86::DX: DestReg = X86::RDX; break; + case X86::CX: DestReg = X86::RCX; break; + case X86::BX: DestReg = X86::RBX; break; + case X86::SI: DestReg = X86::RSI; break; + case X86::DI: DestReg = X86::RDI; break; + case X86::BP: DestReg = X86::RBP; break; + case X86::SP: DestReg = X86::RSP; break; + } + if (DestReg) { + Res.first = DestReg; + Res.second = X86::GR64RegisterClass; + } + } + } else if (Res.second == X86::FR32RegisterClass || + Res.second == X86::FR64RegisterClass || + Res.second == X86::VR128RegisterClass) { + // Handle references to XMM physical registers that got mapped into the + // wrong class. This can happen with constraints like {xmm0} where the + // target independent register mapper will just pick the first match it can + // find, ignoring the required type. + if (VT == MVT::f32) + Res.second = X86::FR32RegisterClass; + else if (VT == MVT::f64) + Res.second = X86::FR64RegisterClass; + else if (X86::VR128RegisterClass->hasType(VT)) + Res.second = X86::VR128RegisterClass; + } + + return Res; +} + +//===----------------------------------------------------------------------===// +// X86 Widen vector type +//===----------------------------------------------------------------------===// + +/// getWidenVectorType: given a vector type, returns the type to widen +/// to (e.g., v7i8 to v8i8). If the vector type is legal, it returns itself. +/// If there is no vector type that we want to widen to, returns MVT::Other +/// When and where to widen is target dependent based on the cost of +/// scalarizing vs using the wider vector type. + +EVT X86TargetLowering::getWidenVectorType(EVT VT) const { + assert(VT.isVector()); + if (isTypeLegal(VT)) + return VT; + + // TODO: In computeRegisterProperty, we can compute the list of legal vector + // type based on element type. This would speed up our search (though + // it may not be worth it since the size of the list is relatively + // small). + EVT EltVT = VT.getVectorElementType(); + unsigned NElts = VT.getVectorNumElements(); + + // On X86, it make sense to widen any vector wider than 1 + if (NElts <= 1) + return MVT::Other; + + for (unsigned nVT = MVT::FIRST_VECTOR_VALUETYPE; + nVT <= MVT::LAST_VECTOR_VALUETYPE; ++nVT) { + EVT SVT = (MVT::SimpleValueType)nVT; + + if (isTypeLegal(SVT) && + SVT.getVectorElementType() == EltVT && + SVT.getVectorNumElements() > NElts) + return SVT; + } + return MVT::Other; +} diff --git a/libclamav/c++/llvm/lib/Target/X86/X86ISelLowering.h b/libclamav/c++/llvm/lib/Target/X86/X86ISelLowering.h new file mode 100644 index 000000000..7b4ab62fd --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/X86/X86ISelLowering.h @@ -0,0 +1,796 @@ +//===-- X86ISelLowering.h - X86 DAG Lowering Interface ----------*- 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 the interfaces that X86 uses to lower LLVM code into a +// selection DAG. +// +//===----------------------------------------------------------------------===// + +#ifndef X86ISELLOWERING_H +#define X86ISELLOWERING_H + +#include "X86Subtarget.h" +#include "X86RegisterInfo.h" +#include "X86MachineFunctionInfo.h" +#include "llvm/Target/TargetLowering.h" +#include "llvm/CodeGen/FastISel.h" +#include "llvm/CodeGen/SelectionDAG.h" +#include "llvm/CodeGen/CallingConvLower.h" + +namespace llvm { + namespace X86ISD { + // X86 Specific DAG Nodes + enum NodeType { + // Start the numbering where the builtin ops leave off. + FIRST_NUMBER = ISD::BUILTIN_OP_END, + + /// BSF - Bit scan forward. + /// BSR - Bit scan reverse. + BSF, + BSR, + + /// SHLD, SHRD - Double shift instructions. These correspond to + /// X86::SHLDxx and X86::SHRDxx instructions. + SHLD, + SHRD, + + /// FAND - Bitwise logical AND of floating point values. This corresponds + /// to X86::ANDPS or X86::ANDPD. + FAND, + + /// FOR - Bitwise logical OR of floating point values. This corresponds + /// to X86::ORPS or X86::ORPD. + FOR, + + /// FXOR - Bitwise logical XOR of floating point values. This corresponds + /// to X86::XORPS or X86::XORPD. + FXOR, + + /// FSRL - Bitwise logical right shift of floating point values. These + /// corresponds to X86::PSRLDQ. + FSRL, + + /// FILD, FILD_FLAG - This instruction implements SINT_TO_FP with the + /// integer source in memory and FP reg result. This corresponds to the + /// X86::FILD*m instructions. It has three inputs (token chain, address, + /// and source type) and two outputs (FP value and token chain). FILD_FLAG + /// also produces a flag). + FILD, + FILD_FLAG, + + /// FP_TO_INT*_IN_MEM - This instruction implements FP_TO_SINT with the + /// integer destination in memory and a FP reg source. This corresponds + /// to the X86::FIST*m instructions and the rounding mode change stuff. It + /// has two inputs (token chain and address) and two outputs (int value + /// and token chain). + FP_TO_INT16_IN_MEM, + FP_TO_INT32_IN_MEM, + FP_TO_INT64_IN_MEM, + + /// FLD - This instruction implements an extending load to FP stack slots. + /// This corresponds to the X86::FLD32m / X86::FLD64m. It takes a chain + /// operand, ptr to load from, and a ValueType node indicating the type + /// to load to. + FLD, + + /// FST - This instruction implements a truncating store to FP stack + /// slots. This corresponds to the X86::FST32m / X86::FST64m. It takes a + /// chain operand, value to store, address, and a ValueType to store it + /// as. + FST, + + /// CALL - These operations represent an abstract X86 call + /// instruction, which includes a bunch of information. In particular the + /// operands of these node are: + /// + /// #0 - The incoming token chain + /// #1 - The callee + /// #2 - The number of arg bytes the caller pushes on the stack. + /// #3 - The number of arg bytes the callee pops off the stack. + /// #4 - The value to pass in AL/AX/EAX (optional) + /// #5 - The value to pass in DL/DX/EDX (optional) + /// + /// The result values of these nodes are: + /// + /// #0 - The outgoing token chain + /// #1 - The first register result value (optional) + /// #2 - The second register result value (optional) + /// + CALL, + + /// RDTSC_DAG - This operation implements the lowering for + /// readcyclecounter + RDTSC_DAG, + + /// X86 compare and logical compare instructions. + CMP, COMI, UCOMI, + + /// X86 bit-test instructions. + BT, + + /// X86 SetCC. Operand 0 is condition code, and operand 1 is the flag + /// operand produced by a CMP instruction. + SETCC, + + /// X86 conditional moves. Operand 0 and operand 1 are the two values + /// to select from. Operand 2 is the condition code, and operand 3 is the + /// flag operand produced by a CMP or TEST instruction. It also writes a + /// flag result. + CMOV, + + /// X86 conditional branches. Operand 0 is the chain operand, operand 1 + /// is the block to branch if condition is true, operand 2 is the + /// condition code, and operand 3 is the flag operand produced by a CMP + /// or TEST instruction. + BRCOND, + + /// Return with a flag operand. Operand 0 is the chain operand, operand + /// 1 is the number of bytes of stack to pop. + RET_FLAG, + + /// REP_STOS - Repeat fill, corresponds to X86::REP_STOSx. + REP_STOS, + + /// REP_MOVS - Repeat move, corresponds to X86::REP_MOVSx. + REP_MOVS, + + /// GlobalBaseReg - On Darwin, this node represents the result of the popl + /// at function entry, used for PIC code. + GlobalBaseReg, + + /// Wrapper - A wrapper node for TargetConstantPool, + /// TargetExternalSymbol, and TargetGlobalAddress. + Wrapper, + + /// WrapperRIP - Special wrapper used under X86-64 PIC mode for RIP + /// relative displacements. + WrapperRIP, + + /// PEXTRB - Extract an 8-bit value from a vector and zero extend it to + /// i32, corresponds to X86::PEXTRB. + PEXTRB, + + /// PEXTRW - Extract a 16-bit value from a vector and zero extend it to + /// i32, corresponds to X86::PEXTRW. + PEXTRW, + + /// INSERTPS - Insert any element of a 4 x float vector into any element + /// of a destination 4 x floatvector. + INSERTPS, + + /// PINSRB - Insert the lower 8-bits of a 32-bit value to a vector, + /// corresponds to X86::PINSRB. + PINSRB, + + /// PINSRW - Insert the lower 16-bits of a 32-bit value to a vector, + /// corresponds to X86::PINSRW. + PINSRW, + + /// PSHUFB - Shuffle 16 8-bit values within a vector. + PSHUFB, + + /// FMAX, FMIN - Floating point max and min. + /// + FMAX, FMIN, + + /// FRSQRT, FRCP - Floating point reciprocal-sqrt and reciprocal + /// approximation. Note that these typically require refinement + /// in order to obtain suitable precision. + FRSQRT, FRCP, + + // TLSADDR - Thread Local Storage. + TLSADDR, + + // SegmentBaseAddress - The address segment:0 + SegmentBaseAddress, + + // EH_RETURN - Exception Handling helpers. + EH_RETURN, + + /// TC_RETURN - Tail call return. + /// operand #0 chain + /// operand #1 callee (register or absolute) + /// operand #2 stack adjustment + /// operand #3 optional in flag + TC_RETURN, + + // LCMPXCHG_DAG, LCMPXCHG8_DAG - Compare and swap. + LCMPXCHG_DAG, + LCMPXCHG8_DAG, + + // FNSTCW16m - Store FP control world into i16 memory. + FNSTCW16m, + + // VZEXT_MOVL - Vector move low and zero extend. + VZEXT_MOVL, + + // VZEXT_LOAD - Load, scalar_to_vector, and zero extend. + VZEXT_LOAD, + + // VSHL, VSRL - Vector logical left / right shift. + VSHL, VSRL, + + // CMPPD, CMPPS - Vector double/float comparison. + // CMPPD, CMPPS - Vector double/float comparison. + CMPPD, CMPPS, + + // PCMP* - Vector integer comparisons. + PCMPEQB, PCMPEQW, PCMPEQD, PCMPEQQ, + PCMPGTB, PCMPGTW, PCMPGTD, PCMPGTQ, + + // ADD, SUB, SMUL, UMUL, etc. - Arithmetic operations with FLAGS results. + ADD, SUB, SMUL, UMUL, + INC, DEC, OR, XOR, AND, + + // MUL_IMM - X86 specific multiply by immediate. + MUL_IMM, + + // PTEST - Vector bitwise comparisons + PTEST, + + // VASTART_SAVE_XMM_REGS - Save xmm argument registers to the stack, + // according to %al. An operator is needed so that this can be expanded + // with control flow. + VASTART_SAVE_XMM_REGS, + + // ATOMADD64_DAG, ATOMSUB64_DAG, ATOMOR64_DAG, ATOMAND64_DAG, + // ATOMXOR64_DAG, ATOMNAND64_DAG, ATOMSWAP64_DAG - + // Atomic 64-bit binary operations. + ATOMADD64_DAG = ISD::FIRST_TARGET_MEMORY_OPCODE, + ATOMSUB64_DAG, + ATOMOR64_DAG, + ATOMXOR64_DAG, + ATOMAND64_DAG, + ATOMNAND64_DAG, + ATOMSWAP64_DAG + }; + } + + /// Define some predicates that are used for node matching. + namespace X86 { + /// isPSHUFDMask - Return true if the specified VECTOR_SHUFFLE operand + /// specifies a shuffle of elements that is suitable for input to PSHUFD. + bool isPSHUFDMask(ShuffleVectorSDNode *N); + + /// isPSHUFHWMask - Return true if the specified VECTOR_SHUFFLE operand + /// specifies a shuffle of elements that is suitable for input to PSHUFD. + bool isPSHUFHWMask(ShuffleVectorSDNode *N); + + /// isPSHUFLWMask - Return true if the specified VECTOR_SHUFFLE operand + /// specifies a shuffle of elements that is suitable for input to PSHUFD. + bool isPSHUFLWMask(ShuffleVectorSDNode *N); + + /// isSHUFPMask - Return true if the specified VECTOR_SHUFFLE operand + /// specifies a shuffle of elements that is suitable for input to SHUFP*. + bool isSHUFPMask(ShuffleVectorSDNode *N); + + /// isMOVHLPSMask - Return true if the specified VECTOR_SHUFFLE operand + /// specifies a shuffle of elements that is suitable for input to MOVHLPS. + bool isMOVHLPSMask(ShuffleVectorSDNode *N); + + /// isMOVHLPS_v_undef_Mask - Special case of isMOVHLPSMask for canonical form + /// of vector_shuffle v, v, <2, 3, 2, 3>, i.e. vector_shuffle v, undef, + /// <2, 3, 2, 3> + bool isMOVHLPS_v_undef_Mask(ShuffleVectorSDNode *N); + + /// isMOVLPMask - Return true if the specified VECTOR_SHUFFLE operand + /// specifies a shuffle of elements that is suitable for MOVLP{S|D}. + bool isMOVLPMask(ShuffleVectorSDNode *N); + + /// isMOVHPMask - Return true if the specified VECTOR_SHUFFLE operand + /// specifies a shuffle of elements that is suitable for MOVHP{S|D}. + /// as well as MOVLHPS. + bool isMOVLHPSMask(ShuffleVectorSDNode *N); + + /// isUNPCKLMask - Return true if the specified VECTOR_SHUFFLE operand + /// specifies a shuffle of elements that is suitable for input to UNPCKL. + bool isUNPCKLMask(ShuffleVectorSDNode *N, bool V2IsSplat = false); + + /// isUNPCKHMask - Return true if the specified VECTOR_SHUFFLE operand + /// specifies a shuffle of elements that is suitable for input to UNPCKH. + bool isUNPCKHMask(ShuffleVectorSDNode *N, bool V2IsSplat = false); + + /// isUNPCKL_v_undef_Mask - Special case of isUNPCKLMask for canonical form + /// of vector_shuffle v, v, <0, 4, 1, 5>, i.e. vector_shuffle v, undef, + /// <0, 0, 1, 1> + bool isUNPCKL_v_undef_Mask(ShuffleVectorSDNode *N); + + /// isUNPCKH_v_undef_Mask - Special case of isUNPCKHMask for canonical form + /// of vector_shuffle v, v, <2, 6, 3, 7>, i.e. vector_shuffle v, undef, + /// <2, 2, 3, 3> + bool isUNPCKH_v_undef_Mask(ShuffleVectorSDNode *N); + + /// isMOVLMask - Return true if the specified VECTOR_SHUFFLE operand + /// specifies a shuffle of elements that is suitable for input to MOVSS, + /// MOVSD, and MOVD, i.e. setting the lowest element. + bool isMOVLMask(ShuffleVectorSDNode *N); + + /// isMOVSHDUPMask - Return true if the specified VECTOR_SHUFFLE operand + /// specifies a shuffle of elements that is suitable for input to MOVSHDUP. + bool isMOVSHDUPMask(ShuffleVectorSDNode *N); + + /// isMOVSLDUPMask - Return true if the specified VECTOR_SHUFFLE operand + /// specifies a shuffle of elements that is suitable for input to MOVSLDUP. + bool isMOVSLDUPMask(ShuffleVectorSDNode *N); + + /// isMOVDDUPMask - Return true if the specified VECTOR_SHUFFLE operand + /// specifies a shuffle of elements that is suitable for input to MOVDDUP. + bool isMOVDDUPMask(ShuffleVectorSDNode *N); + + /// isPALIGNRMask - Return true if the specified VECTOR_SHUFFLE operand + /// specifies a shuffle of elements that is suitable for input to PALIGNR. + bool isPALIGNRMask(ShuffleVectorSDNode *N); + + /// getShuffleSHUFImmediate - Return the appropriate immediate to shuffle + /// the specified isShuffleMask VECTOR_SHUFFLE mask with PSHUF* and SHUFP* + /// instructions. + unsigned getShuffleSHUFImmediate(SDNode *N); + + /// getShufflePSHUFHWImmediate - Return the appropriate immediate to shuffle + /// the specified VECTOR_SHUFFLE mask with PSHUFHW instruction. + unsigned getShufflePSHUFHWImmediate(SDNode *N); + + /// getShufflePSHUFLWImmediate - Return the appropriate immediate to shuffle + /// the specified VECTOR_SHUFFLE mask with PSHUFLW instruction. + unsigned getShufflePSHUFLWImmediate(SDNode *N); + + /// getShufflePALIGNRImmediate - Return the appropriate immediate to shuffle + /// the specified VECTOR_SHUFFLE mask with the PALIGNR instruction. + unsigned getShufflePALIGNRImmediate(SDNode *N); + + /// isZeroNode - Returns true if Elt is a constant zero or a floating point + /// constant +0.0. + bool isZeroNode(SDValue Elt); + + /// isOffsetSuitableForCodeModel - Returns true of the given offset can be + /// fit into displacement field of the instruction. + bool isOffsetSuitableForCodeModel(int64_t Offset, CodeModel::Model M, + bool hasSymbolicDisplacement = true); + } + + //===--------------------------------------------------------------------===// + // X86TargetLowering - X86 Implementation of the TargetLowering interface + class X86TargetLowering : public TargetLowering { + int VarArgsFrameIndex; // FrameIndex for start of varargs area. + int RegSaveFrameIndex; // X86-64 vararg func register save area. + unsigned VarArgsGPOffset; // X86-64 vararg func int reg offset. + unsigned VarArgsFPOffset; // X86-64 vararg func fp reg offset. + int BytesToPopOnReturn; // Number of arg bytes ret should pop. + int BytesCallerReserves; // Number of arg bytes caller makes. + + public: + explicit X86TargetLowering(X86TargetMachine &TM); + + /// getPICJumpTableRelocaBase - Returns relocation base for the given PIC + /// jumptable. + SDValue getPICJumpTableRelocBase(SDValue Table, + SelectionDAG &DAG) const; + + // Return the number of bytes that a function should pop when it returns (in + // addition to the space used by the return address). + // + unsigned getBytesToPopOnReturn() const { return BytesToPopOnReturn; } + + // Return the number of bytes that the caller reserves for arguments passed + // to this function. + unsigned getBytesCallerReserves() const { return BytesCallerReserves; } + + /// getStackPtrReg - Return the stack pointer register we are using: either + /// ESP or RSP. + unsigned getStackPtrReg() const { return X86StackPtr; } + + /// getByValTypeAlignment - Return the desired alignment for ByVal aggregate + /// function arguments in the caller parameter area. For X86, aggregates + /// that contains are placed at 16-byte boundaries while the rest are at + /// 4-byte boundaries. + virtual unsigned getByValTypeAlignment(const Type *Ty) const; + + /// getOptimalMemOpType - Returns the target specific optimal type for load + /// and store operations as a result of memset, memcpy, and memmove + /// lowering. It returns EVT::iAny if SelectionDAG should be responsible for + /// determining it. + virtual EVT getOptimalMemOpType(uint64_t Size, unsigned Align, + bool isSrcConst, bool isSrcStr, + SelectionDAG &DAG) const; + + /// allowsUnalignedMemoryAccesses - Returns true if the target allows + /// unaligned memory accesses. of the specified type. + virtual bool allowsUnalignedMemoryAccesses(EVT VT) const { + return true; + } + + /// LowerOperation - Provide custom lowering hooks for some operations. + /// + virtual SDValue LowerOperation(SDValue Op, SelectionDAG &DAG); + + /// ReplaceNodeResults - Replace the results of node with an illegal result + /// type with new values built out of custom code. + /// + virtual void ReplaceNodeResults(SDNode *N, SmallVectorImpl&Results, + SelectionDAG &DAG); + + + virtual SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const; + + virtual MachineBasicBlock *EmitInstrWithCustomInserter(MachineInstr *MI, + MachineBasicBlock *MBB, + DenseMap *EM) const; + + + /// getTargetNodeName - This method returns the name of a target specific + /// DAG node. + virtual const char *getTargetNodeName(unsigned Opcode) const; + + /// getSetCCResultType - Return the ISD::SETCC ValueType + virtual MVT::SimpleValueType getSetCCResultType(EVT VT) const; + + /// computeMaskedBitsForTargetNode - Determine which of the bits specified + /// in Mask are known to be either zero or one and return them in the + /// KnownZero/KnownOne bitsets. + virtual void computeMaskedBitsForTargetNode(const SDValue Op, + const APInt &Mask, + APInt &KnownZero, + APInt &KnownOne, + const SelectionDAG &DAG, + unsigned Depth = 0) const; + + virtual bool + isGAPlusOffset(SDNode *N, GlobalValue* &GA, int64_t &Offset) const; + + SDValue getReturnAddressFrameIndex(SelectionDAG &DAG); + + virtual bool ExpandInlineAsm(CallInst *CI) const; + + ConstraintType getConstraintType(const std::string &Constraint) const; + + std::vector + getRegClassForInlineAsmConstraint(const std::string &Constraint, + EVT VT) const; + + virtual const char *LowerXConstraint(EVT ConstraintVT) const; + + /// LowerAsmOperandForConstraint - Lower the specified operand into the Ops + /// vector. If it is invalid, don't add anything to Ops. If hasMemory is + /// true it means one of the asm constraint of the inline asm instruction + /// being processed is 'm'. + virtual void LowerAsmOperandForConstraint(SDValue Op, + char ConstraintLetter, + bool hasMemory, + std::vector &Ops, + SelectionDAG &DAG) const; + + /// getRegForInlineAsmConstraint - Given a physical register constraint + /// (e.g. {edx}), return the register number and the register class for the + /// register. This should only be used for C_Register constraints. On + /// error, this returns a register number of 0. + std::pair + getRegForInlineAsmConstraint(const std::string &Constraint, + EVT VT) const; + + /// isLegalAddressingMode - Return true if the addressing mode represented + /// by AM is legal for this target, for a load/store of the specified type. + virtual bool isLegalAddressingMode(const AddrMode &AM, const Type *Ty)const; + + /// isTruncateFree - Return true if it's free to truncate a value of + /// type Ty1 to type Ty2. e.g. On x86 it's free to truncate a i32 value in + /// register EAX to i16 by referencing its sub-register AX. + virtual bool isTruncateFree(const Type *Ty1, const Type *Ty2) const; + virtual bool isTruncateFree(EVT VT1, EVT VT2) const; + + /// isZExtFree - Return true if any actual instruction that defines a + /// value of type Ty1 implicit zero-extends the value to Ty2 in the result + /// register. This does not necessarily include registers defined in + /// unknown ways, such as incoming arguments, or copies from unknown + /// virtual registers. Also, if isTruncateFree(Ty2, Ty1) is true, this + /// does not necessarily apply to truncate instructions. e.g. on x86-64, + /// all instructions that define 32-bit values implicit zero-extend the + /// result out to 64 bits. + virtual bool isZExtFree(const Type *Ty1, const Type *Ty2) const; + virtual bool isZExtFree(EVT VT1, EVT VT2) const; + + /// isNarrowingProfitable - Return true if it's profitable to narrow + /// operations of type VT1 to VT2. e.g. on x86, it's profitable to narrow + /// from i32 to i8 but not from i32 to i16. + virtual bool isNarrowingProfitable(EVT VT1, EVT VT2) const; + + /// isFPImmLegal - Returns true if the target can instruction select the + /// specified FP immediate natively. If false, the legalizer will + /// materialize the FP immediate as a load from a constant pool. + virtual bool isFPImmLegal(const APFloat &Imm, EVT VT) const; + + /// isShuffleMaskLegal - Targets can use this to indicate that they only + /// support *some* VECTOR_SHUFFLE operations, those with specific masks. + /// By default, if a target supports the VECTOR_SHUFFLE node, all mask + /// values are assumed to be legal. + virtual bool isShuffleMaskLegal(const SmallVectorImpl &Mask, + EVT VT) const; + + /// isVectorClearMaskLegal - Similar to isShuffleMaskLegal. This is + /// used by Targets can use this to indicate if there is a suitable + /// VECTOR_SHUFFLE that can be used to replace a VAND with a constant + /// pool entry. + virtual bool isVectorClearMaskLegal(const SmallVectorImpl &Mask, + EVT VT) const; + + /// ShouldShrinkFPConstant - If true, then instruction selection should + /// seek to shrink the FP constant of the specified type to a smaller type + /// in order to save space and / or reduce runtime. + virtual bool ShouldShrinkFPConstant(EVT VT) const { + // Don't shrink FP constpool if SSE2 is available since cvtss2sd is more + // expensive than a straight movsd. On the other hand, it's important to + // shrink long double fp constant since fldt is very slow. + return !X86ScalarSSEf64 || VT == MVT::f80; + } + + /// IsEligibleForTailCallOptimization - Check whether the call is eligible + /// for tail call optimization. Targets which want to do tail call + /// optimization should implement this function. + virtual bool + IsEligibleForTailCallOptimization(SDValue Callee, + CallingConv::ID CalleeCC, + bool isVarArg, + const SmallVectorImpl &Ins, + SelectionDAG& DAG) const; + + virtual const X86Subtarget* getSubtarget() { + return Subtarget; + } + + /// isScalarFPTypeInSSEReg - Return true if the specified scalar FP type is + /// computed in an SSE register, not on the X87 floating point stack. + bool isScalarFPTypeInSSEReg(EVT VT) const { + return (VT == MVT::f64 && X86ScalarSSEf64) || // f64 is when SSE2 + (VT == MVT::f32 && X86ScalarSSEf32); // f32 is when SSE1 + } + + /// getWidenVectorType: given a vector type, returns the type to widen + /// to (e.g., v7i8 to v8i8). If the vector type is legal, it returns itself. + /// If there is no vector type that we want to widen to, returns EVT::Other + /// When and were to widen is target dependent based on the cost of + /// scalarizing vs using the wider vector type. + virtual EVT getWidenVectorType(EVT VT) const; + + /// createFastISel - This method returns a target specific FastISel object, + /// or null if the target does not support "fast" ISel. + virtual FastISel * + createFastISel(MachineFunction &mf, + MachineModuleInfo *mmi, DwarfWriter *dw, + DenseMap &, + DenseMap &, + DenseMap & +#ifndef NDEBUG + , SmallSet & +#endif + ); + + /// getFunctionAlignment - Return the Log2 alignment of this function. + virtual unsigned getFunctionAlignment(const Function *F) const; + + private: + /// Subtarget - Keep a pointer to the X86Subtarget around so that we can + /// make the right decision when generating code for different targets. + const X86Subtarget *Subtarget; + const X86RegisterInfo *RegInfo; + const TargetData *TD; + + /// X86StackPtr - X86 physical register used as stack ptr. + unsigned X86StackPtr; + + /// X86ScalarSSEf32, X86ScalarSSEf64 - Select between SSE or x87 + /// floating point ops. + /// When SSE is available, use it for f32 operations. + /// When SSE2 is available, use it for f64 operations. + bool X86ScalarSSEf32; + bool X86ScalarSSEf64; + + /// LegalFPImmediates - A list of legal fp immediates. + std::vector LegalFPImmediates; + + /// addLegalFPImmediate - Indicate that this x86 target can instruction + /// select the specified FP immediate natively. + void addLegalFPImmediate(const APFloat& Imm) { + LegalFPImmediates.push_back(Imm); + } + + SDValue LowerCallResult(SDValue Chain, SDValue InFlag, + CallingConv::ID CallConv, bool isVarArg, + const SmallVectorImpl &Ins, + DebugLoc dl, SelectionDAG &DAG, + SmallVectorImpl &InVals); + SDValue LowerMemArgument(SDValue Chain, + CallingConv::ID CallConv, + const SmallVectorImpl &ArgInfo, + DebugLoc dl, SelectionDAG &DAG, + const CCValAssign &VA, MachineFrameInfo *MFI, + unsigned i); + SDValue LowerMemOpCallTo(SDValue Chain, SDValue StackPtr, SDValue Arg, + DebugLoc dl, SelectionDAG &DAG, + const CCValAssign &VA, + ISD::ArgFlagsTy Flags); + + // Call lowering helpers. + bool IsCalleePop(bool isVarArg, CallingConv::ID CallConv); + SDValue EmitTailCallLoadRetAddr(SelectionDAG &DAG, SDValue &OutRetAddr, + SDValue Chain, bool IsTailCall, bool Is64Bit, + int FPDiff, DebugLoc dl); + + CCAssignFn *CCAssignFnForNode(CallingConv::ID CallConv) const; + NameDecorationStyle NameDecorationForCallConv(CallingConv::ID CallConv); + unsigned GetAlignedArgumentStackSize(unsigned StackSize, SelectionDAG &DAG); + + std::pair FP_TO_INTHelper(SDValue Op, SelectionDAG &DAG, + bool isSigned); + + SDValue LowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG); + SDValue LowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG); + SDValue LowerEXTRACT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG); + SDValue LowerEXTRACT_VECTOR_ELT_SSE4(SDValue Op, SelectionDAG &DAG); + SDValue LowerINSERT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG); + SDValue LowerINSERT_VECTOR_ELT_SSE4(SDValue Op, SelectionDAG &DAG); + SDValue LowerSCALAR_TO_VECTOR(SDValue Op, SelectionDAG &DAG); + SDValue LowerConstantPool(SDValue Op, SelectionDAG &DAG); + SDValue LowerBlockAddress(SDValue Op, SelectionDAG &DAG); + SDValue LowerGlobalAddress(const GlobalValue *GV, DebugLoc dl, + int64_t Offset, SelectionDAG &DAG) const; + SDValue LowerGlobalAddress(SDValue Op, SelectionDAG &DAG); + SDValue LowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG); + SDValue LowerExternalSymbol(SDValue Op, SelectionDAG &DAG); + SDValue LowerShift(SDValue Op, SelectionDAG &DAG); + SDValue BuildFILD(SDValue Op, EVT SrcVT, SDValue Chain, SDValue StackSlot, + SelectionDAG &DAG); + SDValue LowerSINT_TO_FP(SDValue Op, SelectionDAG &DAG); + SDValue LowerUINT_TO_FP(SDValue Op, SelectionDAG &DAG); + SDValue LowerUINT_TO_FP_i64(SDValue Op, SelectionDAG &DAG); + SDValue LowerUINT_TO_FP_i32(SDValue Op, SelectionDAG &DAG); + SDValue LowerFP_TO_SINT(SDValue Op, SelectionDAG &DAG); + SDValue LowerFP_TO_UINT(SDValue Op, SelectionDAG &DAG); + SDValue LowerFABS(SDValue Op, SelectionDAG &DAG); + SDValue LowerFNEG(SDValue Op, SelectionDAG &DAG); + SDValue LowerFCOPYSIGN(SDValue Op, SelectionDAG &DAG); + SDValue LowerSETCC(SDValue Op, SelectionDAG &DAG); + SDValue LowerVSETCC(SDValue Op, SelectionDAG &DAG); + SDValue LowerSELECT(SDValue Op, SelectionDAG &DAG); + SDValue LowerBRCOND(SDValue Op, SelectionDAG &DAG); + SDValue LowerMEMSET(SDValue Op, SelectionDAG &DAG); + SDValue LowerJumpTable(SDValue Op, SelectionDAG &DAG); + SDValue LowerDYNAMIC_STACKALLOC(SDValue Op, SelectionDAG &DAG); + SDValue LowerVASTART(SDValue Op, SelectionDAG &DAG); + SDValue LowerVAARG(SDValue Op, SelectionDAG &DAG); + SDValue LowerVACOPY(SDValue Op, SelectionDAG &DAG); + SDValue LowerINTRINSIC_WO_CHAIN(SDValue Op, SelectionDAG &DAG); + SDValue LowerRETURNADDR(SDValue Op, SelectionDAG &DAG); + SDValue LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG); + SDValue LowerFRAME_TO_ARGS_OFFSET(SDValue Op, SelectionDAG &DAG); + SDValue LowerEH_RETURN(SDValue Op, SelectionDAG &DAG); + SDValue LowerTRAMPOLINE(SDValue Op, SelectionDAG &DAG); + SDValue LowerFLT_ROUNDS_(SDValue Op, SelectionDAG &DAG); + SDValue LowerCTLZ(SDValue Op, SelectionDAG &DAG); + SDValue LowerCTTZ(SDValue Op, SelectionDAG &DAG); + SDValue LowerMUL_V2I64(SDValue Op, SelectionDAG &DAG); + SDValue LowerXALUO(SDValue Op, SelectionDAG &DAG); + + SDValue LowerCMP_SWAP(SDValue Op, SelectionDAG &DAG); + SDValue LowerLOAD_SUB(SDValue Op, SelectionDAG &DAG); + SDValue LowerREADCYCLECOUNTER(SDValue Op, SelectionDAG &DAG); + + virtual SDValue + LowerFormalArguments(SDValue Chain, + CallingConv::ID CallConv, bool isVarArg, + const SmallVectorImpl &Ins, + DebugLoc dl, SelectionDAG &DAG, + SmallVectorImpl &InVals); + virtual SDValue + LowerCall(SDValue Chain, SDValue Callee, + CallingConv::ID CallConv, bool isVarArg, bool isTailCall, + const SmallVectorImpl &Outs, + const SmallVectorImpl &Ins, + DebugLoc dl, SelectionDAG &DAG, + SmallVectorImpl &InVals); + + virtual SDValue + LowerReturn(SDValue Chain, + CallingConv::ID CallConv, bool isVarArg, + const SmallVectorImpl &Outs, + DebugLoc dl, SelectionDAG &DAG); + + virtual bool + CanLowerReturn(CallingConv::ID CallConv, bool isVarArg, + const SmallVectorImpl &OutTys, + const SmallVectorImpl &ArgsFlags, + SelectionDAG &DAG); + + void ReplaceATOMIC_BINARY_64(SDNode *N, SmallVectorImpl &Results, + SelectionDAG &DAG, unsigned NewOp); + + SDValue EmitTargetCodeForMemset(SelectionDAG &DAG, DebugLoc dl, + SDValue Chain, + SDValue Dst, SDValue Src, + SDValue Size, unsigned Align, + const Value *DstSV, uint64_t DstSVOff); + SDValue EmitTargetCodeForMemcpy(SelectionDAG &DAG, DebugLoc dl, + SDValue Chain, + SDValue Dst, SDValue Src, + SDValue Size, unsigned Align, + bool AlwaysInline, + const Value *DstSV, uint64_t DstSVOff, + const Value *SrcSV, uint64_t SrcSVOff); + + /// Utility function to emit string processing sse4.2 instructions + /// that return in xmm0. + /// This takes the instruction to expand, the associated machine basic + /// block, the number of args, and whether or not the second arg is + /// in memory or not. + MachineBasicBlock *EmitPCMP(MachineInstr *BInstr, MachineBasicBlock *BB, + unsigned argNum, bool inMem) const; + + /// Utility function to emit atomic bitwise operations (and, or, xor). + /// It takes the bitwise instruction to expand, the associated machine basic + /// block, and the associated X86 opcodes for reg/reg and reg/imm. + MachineBasicBlock *EmitAtomicBitwiseWithCustomInserter( + MachineInstr *BInstr, + MachineBasicBlock *BB, + unsigned regOpc, + unsigned immOpc, + unsigned loadOpc, + unsigned cxchgOpc, + unsigned copyOpc, + unsigned notOpc, + unsigned EAXreg, + TargetRegisterClass *RC, + bool invSrc = false) const; + + MachineBasicBlock *EmitAtomicBit6432WithCustomInserter( + MachineInstr *BInstr, + MachineBasicBlock *BB, + unsigned regOpcL, + unsigned regOpcH, + unsigned immOpcL, + unsigned immOpcH, + bool invSrc = false) const; + + /// Utility function to emit atomic min and max. It takes the min/max + /// instruction to expand, the associated basic block, and the associated + /// cmov opcode for moving the min or max value. + MachineBasicBlock *EmitAtomicMinMaxWithCustomInserter(MachineInstr *BInstr, + MachineBasicBlock *BB, + unsigned cmovOpc) const; + + /// Utility function to emit the xmm reg save portion of va_start. + MachineBasicBlock *EmitVAStartSaveXMMRegsWithCustomInserter( + MachineInstr *BInstr, + MachineBasicBlock *BB) const; + + MachineBasicBlock *EmitLoweredSelect(MachineInstr *I, + MachineBasicBlock *BB, + DenseMap *EM) const; + + /// Emit nodes that will be selected as "test Op0,Op0", or something + /// equivalent, for use with the given x86 condition code. + SDValue EmitTest(SDValue Op0, unsigned X86CC, SelectionDAG &DAG); + + /// Emit nodes that will be selected as "cmp Op0,Op1", or something + /// equivalent, for use with the given x86 condition code. + SDValue EmitCmp(SDValue Op0, SDValue Op1, unsigned X86CC, + SelectionDAG &DAG); + }; + + namespace X86 { + FastISel *createFastISel(MachineFunction &mf, + MachineModuleInfo *mmi, DwarfWriter *dw, + DenseMap &, + DenseMap &, + DenseMap & +#ifndef NDEBUG + , SmallSet & +#endif + ); + } +} + +#endif // X86ISELLOWERING_H diff --git a/libclamav/c++/llvm/lib/Target/X86/X86Instr64bit.td b/libclamav/c++/llvm/lib/Target/X86/X86Instr64bit.td new file mode 100644 index 000000000..a01534b70 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/X86/X86Instr64bit.td @@ -0,0 +1,2266 @@ +//====- X86Instr64bit.td - Describe X86-64 Instructions ----*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file describes the X86-64 instruction set, defining the instructions, +// and properties of the instructions which are needed for code generation, +// machine code emission, and analysis. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// Operand Definitions. +// + +// 64-bits but only 32 bits are significant. +def i64i32imm : Operand; + +// 64-bits but only 32 bits are significant, and those bits are treated as being +// pc relative. +def i64i32imm_pcrel : Operand { + let PrintMethod = "print_pcrel_imm"; +} + + +// 64-bits but only 8 bits are significant. +def i64i8imm : Operand { + let ParserMatchClass = ImmSExt8AsmOperand; +} + +def lea64mem : Operand { + let PrintMethod = "printlea64mem"; + let MIOperandInfo = (ops GR64, i8imm, GR64_NOSP, i32imm); + let ParserMatchClass = X86MemAsmOperand; +} + +def lea64_32mem : Operand { + let PrintMethod = "printlea64_32mem"; + let AsmOperandLowerMethod = "lower_lea64_32mem"; + let MIOperandInfo = (ops GR32, i8imm, GR32_NOSP, i32imm); + let ParserMatchClass = X86MemAsmOperand; +} + +//===----------------------------------------------------------------------===// +// Complex Pattern Definitions. +// +def lea64addr : ComplexPattern; + +def tls64addr : ComplexPattern; + +//===----------------------------------------------------------------------===// +// Pattern fragments. +// + +def i64immSExt8 : PatLeaf<(i64 imm), [{ + // i64immSExt8 predicate - True if the 64-bit immediate fits in a 8-bit + // sign extended field. + return (int64_t)N->getZExtValue() == (int8_t)N->getZExtValue(); +}]>; + +def i64immSExt32 : PatLeaf<(i64 imm), [{ + // i64immSExt32 predicate - True if the 64-bit immediate fits in a 32-bit + // sign extended field. + return (int64_t)N->getZExtValue() == (int32_t)N->getZExtValue(); +}]>; + +def i64immZExt32 : PatLeaf<(i64 imm), [{ + // i64immZExt32 predicate - True if the 64-bit immediate fits in a 32-bit + // unsignedsign extended field. + return (uint64_t)N->getZExtValue() == (uint32_t)N->getZExtValue(); +}]>; + +def sextloadi64i8 : PatFrag<(ops node:$ptr), (i64 (sextloadi8 node:$ptr))>; +def sextloadi64i16 : PatFrag<(ops node:$ptr), (i64 (sextloadi16 node:$ptr))>; +def sextloadi64i32 : PatFrag<(ops node:$ptr), (i64 (sextloadi32 node:$ptr))>; + +def zextloadi64i1 : PatFrag<(ops node:$ptr), (i64 (zextloadi1 node:$ptr))>; +def zextloadi64i8 : PatFrag<(ops node:$ptr), (i64 (zextloadi8 node:$ptr))>; +def zextloadi64i16 : PatFrag<(ops node:$ptr), (i64 (zextloadi16 node:$ptr))>; +def zextloadi64i32 : PatFrag<(ops node:$ptr), (i64 (zextloadi32 node:$ptr))>; + +def extloadi64i1 : PatFrag<(ops node:$ptr), (i64 (extloadi1 node:$ptr))>; +def extloadi64i8 : PatFrag<(ops node:$ptr), (i64 (extloadi8 node:$ptr))>; +def extloadi64i16 : PatFrag<(ops node:$ptr), (i64 (extloadi16 node:$ptr))>; +def extloadi64i32 : PatFrag<(ops node:$ptr), (i64 (extloadi32 node:$ptr))>; + +//===----------------------------------------------------------------------===// +// Instruction list... +// + +// ADJCALLSTACKDOWN/UP implicitly use/def RSP because they may be expanded into +// a stack adjustment and the codegen must know that they may modify the stack +// pointer before prolog-epilog rewriting occurs. +// Pessimistically assume ADJCALLSTACKDOWN / ADJCALLSTACKUP will become +// sub / add which can clobber EFLAGS. +let Defs = [RSP, EFLAGS], Uses = [RSP] in { +def ADJCALLSTACKDOWN64 : I<0, Pseudo, (outs), (ins i32imm:$amt), + "#ADJCALLSTACKDOWN", + [(X86callseq_start timm:$amt)]>, + Requires<[In64BitMode]>; +def ADJCALLSTACKUP64 : I<0, Pseudo, (outs), (ins i32imm:$amt1, i32imm:$amt2), + "#ADJCALLSTACKUP", + [(X86callseq_end timm:$amt1, timm:$amt2)]>, + Requires<[In64BitMode]>; +} + +//===----------------------------------------------------------------------===// +// Call Instructions... +// +let isCall = 1 in + // All calls clobber the non-callee saved registers. RSP is marked as + // a use to prevent stack-pointer assignments that appear immediately + // before calls from potentially appearing dead. Uses for argument + // registers are added manually. + let Defs = [RAX, RCX, RDX, RSI, RDI, R8, R9, R10, R11, + FP0, FP1, FP2, FP3, FP4, FP5, FP6, ST0, ST1, + MM0, MM1, MM2, MM3, MM4, MM5, MM6, MM7, + XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6, XMM7, + XMM8, XMM9, XMM10, XMM11, XMM12, XMM13, XMM14, XMM15, EFLAGS], + Uses = [RSP] in { + + // NOTE: this pattern doesn't match "X86call imm", because we do not know + // that the offset between an arbitrary immediate and the call will fit in + // the 32-bit pcrel field that we have. + def CALL64pcrel32 : Ii32<0xE8, RawFrm, + (outs), (ins i64i32imm_pcrel:$dst, variable_ops), + "call\t$dst", []>, + Requires<[In64BitMode, NotWin64]>; + def CALL64r : I<0xFF, MRM2r, (outs), (ins GR64:$dst, variable_ops), + "call\t{*}$dst", [(X86call GR64:$dst)]>, + Requires<[NotWin64]>; + def CALL64m : I<0xFF, MRM2m, (outs), (ins i64mem:$dst, variable_ops), + "call\t{*}$dst", [(X86call (loadi64 addr:$dst))]>, + Requires<[NotWin64]>; + + def FARCALL64 : RI<0xFF, MRM3m, (outs), (ins opaque80mem:$dst), + "lcall{q}\t{*}$dst", []>; + } + + // FIXME: We need to teach codegen about single list of call-clobbered registers. +let isCall = 1 in + // All calls clobber the non-callee saved registers. RSP is marked as + // a use to prevent stack-pointer assignments that appear immediately + // before calls from potentially appearing dead. Uses for argument + // registers are added manually. + let Defs = [RAX, RCX, RDX, R8, R9, R10, R11, + FP0, FP1, FP2, FP3, FP4, FP5, FP6, ST0, ST1, + MM0, MM1, MM2, MM3, MM4, MM5, MM6, MM7, + XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, EFLAGS], + Uses = [RSP] in { + def WINCALL64pcrel32 : I<0xE8, RawFrm, + (outs), (ins i64i32imm_pcrel:$dst, variable_ops), + "call\t$dst", []>, + Requires<[IsWin64]>; + def WINCALL64r : I<0xFF, MRM2r, (outs), (ins GR64:$dst, variable_ops), + "call\t{*}$dst", + [(X86call GR64:$dst)]>, Requires<[IsWin64]>; + def WINCALL64m : I<0xFF, MRM2m, (outs), (ins i64mem:$dst, variable_ops), + "call\t{*}$dst", + [(X86call (loadi64 addr:$dst))]>, Requires<[IsWin64]>; + } + + +let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1 in +def TCRETURNdi64 : I<0, Pseudo, (outs), (ins i64imm:$dst, i32imm:$offset, + variable_ops), + "#TC_RETURN $dst $offset", + []>; + +let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1 in +def TCRETURNri64 : I<0, Pseudo, (outs), (ins GR64:$dst, i32imm:$offset, + variable_ops), + "#TC_RETURN $dst $offset", + []>; + + +let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1 in + def TAILJMPr64 : I<0xFF, MRM4r, (outs), (ins GR64:$dst), + "jmp{q}\t{*}$dst # TAILCALL", + []>; + +// Branches +let isBranch = 1, isTerminator = 1, isBarrier = 1, isIndirectBranch = 1 in { + def JMP64r : I<0xFF, MRM4r, (outs), (ins GR64:$dst), "jmp{q}\t{*}$dst", + [(brind GR64:$dst)]>; + def JMP64m : I<0xFF, MRM4m, (outs), (ins i64mem:$dst), "jmp{q}\t{*}$dst", + [(brind (loadi64 addr:$dst))]>; + def FARJMP64 : RI<0xFF, MRM5m, (outs), (ins opaque80mem:$dst), + "ljmp{q}\t{*}$dst", []>; +} + +//===----------------------------------------------------------------------===// +// EH Pseudo Instructions +// +let isTerminator = 1, isReturn = 1, isBarrier = 1, + hasCtrlDep = 1 in { +def EH_RETURN64 : I<0xC3, RawFrm, (outs), (ins GR64:$addr), + "ret\t#eh_return, addr: $addr", + [(X86ehret GR64:$addr)]>; + +} + +//===----------------------------------------------------------------------===// +// Miscellaneous Instructions... +// +let Defs = [RBP,RSP], Uses = [RBP,RSP], mayLoad = 1, neverHasSideEffects = 1 in +def LEAVE64 : I<0xC9, RawFrm, + (outs), (ins), "leave", []>; +let Defs = [RSP], Uses = [RSP], neverHasSideEffects=1 in { +let mayLoad = 1 in { +def POP64r : I<0x58, AddRegFrm, + (outs GR64:$reg), (ins), "pop{q}\t$reg", []>; +def POP64rmr: I<0x8F, MRM0r, (outs GR64:$reg), (ins), "pop{q}\t$reg", []>; +def POP64rmm: I<0x8F, MRM0m, (outs i64mem:$dst), (ins), "pop{q}\t$dst", []>; +} +let mayStore = 1 in { +def PUSH64r : I<0x50, AddRegFrm, + (outs), (ins GR64:$reg), "push{q}\t$reg", []>; +def PUSH64rmr: I<0xFF, MRM6r, (outs), (ins GR64:$reg), "push{q}\t$reg", []>; +def PUSH64rmm: I<0xFF, MRM6m, (outs), (ins i64mem:$src), "push{q}\t$src", []>; +} +} + +let Defs = [RSP], Uses = [RSP], neverHasSideEffects = 1, mayStore = 1 in { +def PUSH64i8 : Ii8<0x6a, RawFrm, (outs), (ins i8imm:$imm), + "push{q}\t$imm", []>; +def PUSH64i16 : Ii16<0x68, RawFrm, (outs), (ins i16imm:$imm), + "push{q}\t$imm", []>; +def PUSH64i32 : Ii32<0x68, RawFrm, (outs), (ins i32imm:$imm), + "push{q}\t$imm", []>; +} + +let Defs = [RSP, EFLAGS], Uses = [RSP], mayLoad = 1 in +def POPFQ : I<0x9D, RawFrm, (outs), (ins), "popf", []>, REX_W; +let Defs = [RSP], Uses = [RSP, EFLAGS], mayStore = 1 in +def PUSHFQ : I<0x9C, RawFrm, (outs), (ins), "pushf", []>; + +def LEA64_32r : I<0x8D, MRMSrcMem, + (outs GR32:$dst), (ins lea64_32mem:$src), + "lea{l}\t{$src|$dst}, {$dst|$src}", + [(set GR32:$dst, lea32addr:$src)]>, Requires<[In64BitMode]>; + +let isReMaterializable = 1 in +def LEA64r : RI<0x8D, MRMSrcMem, (outs GR64:$dst), (ins lea64mem:$src), + "lea{q}\t{$src|$dst}, {$dst|$src}", + [(set GR64:$dst, lea64addr:$src)]>; + +let isTwoAddress = 1 in +def BSWAP64r : RI<0xC8, AddRegFrm, (outs GR64:$dst), (ins GR64:$src), + "bswap{q}\t$dst", + [(set GR64:$dst, (bswap GR64:$src))]>, TB; + +// Bit scan instructions. +let Defs = [EFLAGS] in { +def BSF64rr : RI<0xBC, MRMSrcReg, (outs GR64:$dst), (ins GR64:$src), + "bsf{q}\t{$src, $dst|$dst, $src}", + [(set GR64:$dst, (X86bsf GR64:$src)), (implicit EFLAGS)]>, TB; +def BSF64rm : RI<0xBC, MRMSrcMem, (outs GR64:$dst), (ins i64mem:$src), + "bsf{q}\t{$src, $dst|$dst, $src}", + [(set GR64:$dst, (X86bsf (loadi64 addr:$src))), + (implicit EFLAGS)]>, TB; + +def BSR64rr : RI<0xBD, MRMSrcReg, (outs GR64:$dst), (ins GR64:$src), + "bsr{q}\t{$src, $dst|$dst, $src}", + [(set GR64:$dst, (X86bsr GR64:$src)), (implicit EFLAGS)]>, TB; +def BSR64rm : RI<0xBD, MRMSrcMem, (outs GR64:$dst), (ins i64mem:$src), + "bsr{q}\t{$src, $dst|$dst, $src}", + [(set GR64:$dst, (X86bsr (loadi64 addr:$src))), + (implicit EFLAGS)]>, TB; +} // Defs = [EFLAGS] + +// Repeat string ops +let Defs = [RCX,RDI,RSI], Uses = [RCX,RDI,RSI] in +def REP_MOVSQ : RI<0xA5, RawFrm, (outs), (ins), "{rep;movsq|rep movsq}", + [(X86rep_movs i64)]>, REP; +let Defs = [RCX,RDI], Uses = [RAX,RCX,RDI] in +def REP_STOSQ : RI<0xAB, RawFrm, (outs), (ins), "{rep;stosq|rep stosq}", + [(X86rep_stos i64)]>, REP; + +def SCAS64 : RI<0xAF, RawFrm, (outs), (ins), "scas{q}", []>; + +def CMPS64 : RI<0xA7, RawFrm, (outs), (ins), "cmps{q}", []>; + +// Fast system-call instructions +def SYSEXIT64 : RI<0x35, RawFrm, + (outs), (ins), "sysexit", []>, TB; + +//===----------------------------------------------------------------------===// +// Move Instructions... +// + +let neverHasSideEffects = 1 in +def MOV64rr : RI<0x89, MRMDestReg, (outs GR64:$dst), (ins GR64:$src), + "mov{q}\t{$src, $dst|$dst, $src}", []>; + +let isReMaterializable = 1, isAsCheapAsAMove = 1 in { +def MOV64ri : RIi64<0xB8, AddRegFrm, (outs GR64:$dst), (ins i64imm:$src), + "movabs{q}\t{$src, $dst|$dst, $src}", + [(set GR64:$dst, imm:$src)]>; +def MOV64ri32 : RIi32<0xC7, MRM0r, (outs GR64:$dst), (ins i64i32imm:$src), + "mov{q}\t{$src, $dst|$dst, $src}", + [(set GR64:$dst, i64immSExt32:$src)]>; +} + +let canFoldAsLoad = 1, isReMaterializable = 1, mayHaveSideEffects = 1 in +def MOV64rm : RI<0x8B, MRMSrcMem, (outs GR64:$dst), (ins i64mem:$src), + "mov{q}\t{$src, $dst|$dst, $src}", + [(set GR64:$dst, (load addr:$src))]>; + +def MOV64mr : RI<0x89, MRMDestMem, (outs), (ins i64mem:$dst, GR64:$src), + "mov{q}\t{$src, $dst|$dst, $src}", + [(store GR64:$src, addr:$dst)]>; +def MOV64mi32 : RIi32<0xC7, MRM0m, (outs), (ins i64mem:$dst, i64i32imm:$src), + "mov{q}\t{$src, $dst|$dst, $src}", + [(store i64immSExt32:$src, addr:$dst)]>; + +def MOV64o8a : RIi8<0xA0, RawFrm, (outs), (ins i8imm:$src), + "mov{q}\t{$src, %rax|%rax, $src}", []>; +def MOV64o32a : RIi32<0xA1, RawFrm, (outs), (ins i32imm:$src), + "mov{q}\t{$src, %rax|%rax, $src}", []>; +def MOV64ao8 : RIi8<0xA2, RawFrm, (outs i8imm:$dst), (ins), + "mov{q}\t{%rax, $dst|$dst, %rax}", []>; +def MOV64ao32 : RIi32<0xA3, RawFrm, (outs i32imm:$dst), (ins), + "mov{q}\t{%rax, $dst|$dst, %rax}", []>; + +// Moves to and from segment registers +def MOV64rs : RI<0x8C, MRMDestReg, (outs GR64:$dst), (ins SEGMENT_REG:$src), + "mov{w}\t{$src, $dst|$dst, $src}", []>; +def MOV64ms : RI<0x8C, MRMDestMem, (outs i64mem:$dst), (ins SEGMENT_REG:$src), + "mov{w}\t{$src, $dst|$dst, $src}", []>; +def MOV64sr : RI<0x8E, MRMSrcReg, (outs SEGMENT_REG:$dst), (ins GR64:$src), + "mov{w}\t{$src, $dst|$dst, $src}", []>; +def MOV64sm : RI<0x8E, MRMSrcMem, (outs SEGMENT_REG:$dst), (ins i64mem:$src), + "mov{w}\t{$src, $dst|$dst, $src}", []>; + +// Sign/Zero extenders + +// MOVSX64rr8 always has a REX prefix and it has an 8-bit register +// operand, which makes it a rare instruction with an 8-bit register +// operand that can never access an h register. If support for h registers +// were generalized, this would require a special register class. +def MOVSX64rr8 : RI<0xBE, MRMSrcReg, (outs GR64:$dst), (ins GR8 :$src), + "movs{bq|x}\t{$src, $dst|$dst, $src}", + [(set GR64:$dst, (sext GR8:$src))]>, TB; +def MOVSX64rm8 : RI<0xBE, MRMSrcMem, (outs GR64:$dst), (ins i8mem :$src), + "movs{bq|x}\t{$src, $dst|$dst, $src}", + [(set GR64:$dst, (sextloadi64i8 addr:$src))]>, TB; +def MOVSX64rr16: RI<0xBF, MRMSrcReg, (outs GR64:$dst), (ins GR16:$src), + "movs{wq|x}\t{$src, $dst|$dst, $src}", + [(set GR64:$dst, (sext GR16:$src))]>, TB; +def MOVSX64rm16: RI<0xBF, MRMSrcMem, (outs GR64:$dst), (ins i16mem:$src), + "movs{wq|x}\t{$src, $dst|$dst, $src}", + [(set GR64:$dst, (sextloadi64i16 addr:$src))]>, TB; +def MOVSX64rr32: RI<0x63, MRMSrcReg, (outs GR64:$dst), (ins GR32:$src), + "movs{lq|xd}\t{$src, $dst|$dst, $src}", + [(set GR64:$dst, (sext GR32:$src))]>; +def MOVSX64rm32: RI<0x63, MRMSrcMem, (outs GR64:$dst), (ins i32mem:$src), + "movs{lq|xd}\t{$src, $dst|$dst, $src}", + [(set GR64:$dst, (sextloadi64i32 addr:$src))]>; + +// Use movzbl instead of movzbq when the destination is a register; it's +// equivalent due to implicit zero-extending, and it has a smaller encoding. +def MOVZX64rr8 : I<0xB6, MRMSrcReg, (outs GR64:$dst), (ins GR8 :$src), + "", [(set GR64:$dst, (zext GR8:$src))]>, TB; +def MOVZX64rm8 : I<0xB6, MRMSrcMem, (outs GR64:$dst), (ins i8mem :$src), + "", [(set GR64:$dst, (zextloadi64i8 addr:$src))]>, TB; +// Use movzwl instead of movzwq when the destination is a register; it's +// equivalent due to implicit zero-extending, and it has a smaller encoding. +def MOVZX64rr16: I<0xB7, MRMSrcReg, (outs GR64:$dst), (ins GR16:$src), + "", [(set GR64:$dst, (zext GR16:$src))]>, TB; +def MOVZX64rm16: I<0xB7, MRMSrcMem, (outs GR64:$dst), (ins i16mem:$src), + "", [(set GR64:$dst, (zextloadi64i16 addr:$src))]>, TB; + +// There's no movzlq instruction, but movl can be used for this purpose, using +// implicit zero-extension. The preferred way to do 32-bit-to-64-bit zero +// extension on x86-64 is to use a SUBREG_TO_REG to utilize implicit +// zero-extension, however this isn't possible when the 32-bit value is +// defined by a truncate or is copied from something where the high bits aren't +// necessarily all zero. In such cases, we fall back to these explicit zext +// instructions. +def MOVZX64rr32 : I<0x89, MRMDestReg, (outs GR64:$dst), (ins GR32:$src), + "", [(set GR64:$dst, (zext GR32:$src))]>; +def MOVZX64rm32 : I<0x8B, MRMSrcMem, (outs GR64:$dst), (ins i32mem:$src), + "", [(set GR64:$dst, (zextloadi64i32 addr:$src))]>; + +// Any instruction that defines a 32-bit result leaves the high half of the +// register. Truncate can be lowered to EXTRACT_SUBREG. CopyFromReg may +// be copying from a truncate. And x86's cmov doesn't do anything if the +// condition is false. But any other 32-bit operation will zero-extend +// up to 64 bits. +def def32 : PatLeaf<(i32 GR32:$src), [{ + return N->getOpcode() != ISD::TRUNCATE && + N->getOpcode() != TargetInstrInfo::EXTRACT_SUBREG && + N->getOpcode() != ISD::CopyFromReg && + N->getOpcode() != X86ISD::CMOV; +}]>; + +// In the case of a 32-bit def that is known to implicitly zero-extend, +// we can use a SUBREG_TO_REG. +def : Pat<(i64 (zext def32:$src)), + (SUBREG_TO_REG (i64 0), GR32:$src, x86_subreg_32bit)>; + +let neverHasSideEffects = 1 in { + let Defs = [RAX], Uses = [EAX] in + def CDQE : RI<0x98, RawFrm, (outs), (ins), + "{cltq|cdqe}", []>; // RAX = signext(EAX) + + let Defs = [RAX,RDX], Uses = [RAX] in + def CQO : RI<0x99, RawFrm, (outs), (ins), + "{cqto|cqo}", []>; // RDX:RAX = signext(RAX) +} + +//===----------------------------------------------------------------------===// +// Arithmetic Instructions... +// + +let Defs = [EFLAGS] in { + +def ADD64i32 : RI<0x05, RawFrm, (outs), (ins i32imm:$src), + "add{q}\t{$src, %rax|%rax, $src}", []>; + +let isTwoAddress = 1 in { +let isConvertibleToThreeAddress = 1 in { +let isCommutable = 1 in +// Register-Register Addition +def ADD64rr : RI<0x01, MRMDestReg, (outs GR64:$dst), (ins GR64:$src1, GR64:$src2), + "add{q}\t{$src2, $dst|$dst, $src2}", + [(set GR64:$dst, (add GR64:$src1, GR64:$src2)), + (implicit EFLAGS)]>; + +// Register-Integer Addition +def ADD64ri8 : RIi8<0x83, MRM0r, (outs GR64:$dst), (ins GR64:$src1, i64i8imm:$src2), + "add{q}\t{$src2, $dst|$dst, $src2}", + [(set GR64:$dst, (add GR64:$src1, i64immSExt8:$src2)), + (implicit EFLAGS)]>; +def ADD64ri32 : RIi32<0x81, MRM0r, (outs GR64:$dst), (ins GR64:$src1, i64i32imm:$src2), + "add{q}\t{$src2, $dst|$dst, $src2}", + [(set GR64:$dst, (add GR64:$src1, i64immSExt32:$src2)), + (implicit EFLAGS)]>; +} // isConvertibleToThreeAddress + +// Register-Memory Addition +def ADD64rm : RI<0x03, MRMSrcMem, (outs GR64:$dst), (ins GR64:$src1, i64mem:$src2), + "add{q}\t{$src2, $dst|$dst, $src2}", + [(set GR64:$dst, (add GR64:$src1, (load addr:$src2))), + (implicit EFLAGS)]>; + +// Register-Register Addition - Equivalent to the normal rr form (ADD64rr), but +// differently encoded. +def ADD64mrmrr : RI<0x03, MRMSrcReg, (outs GR64:$dst), (ins GR64:$src1, GR64:$src2), + "add{l}\t{$src2, $dst|$dst, $src2}", []>; + +} // isTwoAddress + +// Memory-Register Addition +def ADD64mr : RI<0x01, MRMDestMem, (outs), (ins i64mem:$dst, GR64:$src2), + "add{q}\t{$src2, $dst|$dst, $src2}", + [(store (add (load addr:$dst), GR64:$src2), addr:$dst), + (implicit EFLAGS)]>; +def ADD64mi8 : RIi8<0x83, MRM0m, (outs), (ins i64mem:$dst, i64i8imm :$src2), + "add{q}\t{$src2, $dst|$dst, $src2}", + [(store (add (load addr:$dst), i64immSExt8:$src2), addr:$dst), + (implicit EFLAGS)]>; +def ADD64mi32 : RIi32<0x81, MRM0m, (outs), (ins i64mem:$dst, i64i32imm :$src2), + "add{q}\t{$src2, $dst|$dst, $src2}", + [(store (add (load addr:$dst), i64immSExt32:$src2), addr:$dst), + (implicit EFLAGS)]>; + +let Uses = [EFLAGS] in { + +def ADC64i32 : RI<0x15, RawFrm, (outs), (ins i32imm:$src), + "adc{q}\t{$src, %rax|%rax, $src}", []>; + +let isTwoAddress = 1 in { +let isCommutable = 1 in +def ADC64rr : RI<0x11, MRMDestReg, (outs GR64:$dst), (ins GR64:$src1, GR64:$src2), + "adc{q}\t{$src2, $dst|$dst, $src2}", + [(set GR64:$dst, (adde GR64:$src1, GR64:$src2))]>; + +def ADC64rm : RI<0x13, MRMSrcMem , (outs GR64:$dst), (ins GR64:$src1, i64mem:$src2), + "adc{q}\t{$src2, $dst|$dst, $src2}", + [(set GR64:$dst, (adde GR64:$src1, (load addr:$src2)))]>; + +def ADC64ri8 : RIi8<0x83, MRM2r, (outs GR64:$dst), (ins GR64:$src1, i64i8imm:$src2), + "adc{q}\t{$src2, $dst|$dst, $src2}", + [(set GR64:$dst, (adde GR64:$src1, i64immSExt8:$src2))]>; +def ADC64ri32 : RIi32<0x81, MRM2r, (outs GR64:$dst), (ins GR64:$src1, i64i32imm:$src2), + "adc{q}\t{$src2, $dst|$dst, $src2}", + [(set GR64:$dst, (adde GR64:$src1, i64immSExt32:$src2))]>; +} // isTwoAddress + +def ADC64mr : RI<0x11, MRMDestMem, (outs), (ins i64mem:$dst, GR64:$src2), + "adc{q}\t{$src2, $dst|$dst, $src2}", + [(store (adde (load addr:$dst), GR64:$src2), addr:$dst)]>; +def ADC64mi8 : RIi8<0x83, MRM2m, (outs), (ins i64mem:$dst, i64i8imm :$src2), + "adc{q}\t{$src2, $dst|$dst, $src2}", + [(store (adde (load addr:$dst), i64immSExt8:$src2), addr:$dst)]>; +def ADC64mi32 : RIi32<0x81, MRM2m, (outs), (ins i64mem:$dst, i64i32imm:$src2), + "adc{q}\t{$src2, $dst|$dst, $src2}", + [(store (adde (load addr:$dst), i64immSExt8:$src2), addr:$dst)]>; +} // Uses = [EFLAGS] + +let isTwoAddress = 1 in { +// Register-Register Subtraction +def SUB64rr : RI<0x29, MRMDestReg, (outs GR64:$dst), (ins GR64:$src1, GR64:$src2), + "sub{q}\t{$src2, $dst|$dst, $src2}", + [(set GR64:$dst, (sub GR64:$src1, GR64:$src2)), + (implicit EFLAGS)]>; + +// Register-Memory Subtraction +def SUB64rm : RI<0x2B, MRMSrcMem, (outs GR64:$dst), (ins GR64:$src1, i64mem:$src2), + "sub{q}\t{$src2, $dst|$dst, $src2}", + [(set GR64:$dst, (sub GR64:$src1, (load addr:$src2))), + (implicit EFLAGS)]>; + +// Register-Integer Subtraction +def SUB64ri8 : RIi8<0x83, MRM5r, (outs GR64:$dst), + (ins GR64:$src1, i64i8imm:$src2), + "sub{q}\t{$src2, $dst|$dst, $src2}", + [(set GR64:$dst, (sub GR64:$src1, i64immSExt8:$src2)), + (implicit EFLAGS)]>; +def SUB64ri32 : RIi32<0x81, MRM5r, (outs GR64:$dst), + (ins GR64:$src1, i64i32imm:$src2), + "sub{q}\t{$src2, $dst|$dst, $src2}", + [(set GR64:$dst, (sub GR64:$src1, i64immSExt32:$src2)), + (implicit EFLAGS)]>; +} // isTwoAddress + +def SUB64i32 : RI<0x2D, RawFrm, (outs), (ins i32imm:$src), + "sub{q}\t{$src, %rax|%rax, $src}", []>; + +// Memory-Register Subtraction +def SUB64mr : RI<0x29, MRMDestMem, (outs), (ins i64mem:$dst, GR64:$src2), + "sub{q}\t{$src2, $dst|$dst, $src2}", + [(store (sub (load addr:$dst), GR64:$src2), addr:$dst), + (implicit EFLAGS)]>; + +// Memory-Integer Subtraction +def SUB64mi8 : RIi8<0x83, MRM5m, (outs), (ins i64mem:$dst, i64i8imm :$src2), + "sub{q}\t{$src2, $dst|$dst, $src2}", + [(store (sub (load addr:$dst), i64immSExt8:$src2), + addr:$dst), + (implicit EFLAGS)]>; +def SUB64mi32 : RIi32<0x81, MRM5m, (outs), (ins i64mem:$dst, i64i32imm:$src2), + "sub{q}\t{$src2, $dst|$dst, $src2}", + [(store (sub (load addr:$dst), i64immSExt32:$src2), + addr:$dst), + (implicit EFLAGS)]>; + +let Uses = [EFLAGS] in { +let isTwoAddress = 1 in { +def SBB64rr : RI<0x19, MRMDestReg, (outs GR64:$dst), (ins GR64:$src1, GR64:$src2), + "sbb{q}\t{$src2, $dst|$dst, $src2}", + [(set GR64:$dst, (sube GR64:$src1, GR64:$src2))]>; + +def SBB64rm : RI<0x1B, MRMSrcMem, (outs GR64:$dst), (ins GR64:$src1, i64mem:$src2), + "sbb{q}\t{$src2, $dst|$dst, $src2}", + [(set GR64:$dst, (sube GR64:$src1, (load addr:$src2)))]>; + +def SBB64ri8 : RIi8<0x83, MRM3r, (outs GR64:$dst), (ins GR64:$src1, i64i8imm:$src2), + "sbb{q}\t{$src2, $dst|$dst, $src2}", + [(set GR64:$dst, (sube GR64:$src1, i64immSExt8:$src2))]>; +def SBB64ri32 : RIi32<0x81, MRM3r, (outs GR64:$dst), (ins GR64:$src1, i64i32imm:$src2), + "sbb{q}\t{$src2, $dst|$dst, $src2}", + [(set GR64:$dst, (sube GR64:$src1, i64immSExt32:$src2))]>; +} // isTwoAddress + +def SBB64i32 : RI<0x1D, RawFrm, (outs), (ins i32imm:$src), + "sbb{q}\t{$src, %rax|%rax, $src}", []>; + +def SBB64mr : RI<0x19, MRMDestMem, (outs), (ins i64mem:$dst, GR64:$src2), + "sbb{q}\t{$src2, $dst|$dst, $src2}", + [(store (sube (load addr:$dst), GR64:$src2), addr:$dst)]>; +def SBB64mi8 : RIi8<0x83, MRM3m, (outs), (ins i64mem:$dst, i64i8imm :$src2), + "sbb{q}\t{$src2, $dst|$dst, $src2}", + [(store (sube (load addr:$dst), i64immSExt8:$src2), addr:$dst)]>; +def SBB64mi32 : RIi32<0x81, MRM3m, (outs), (ins i64mem:$dst, i64i32imm:$src2), + "sbb{q}\t{$src2, $dst|$dst, $src2}", + [(store (sube (load addr:$dst), i64immSExt32:$src2), addr:$dst)]>; +} // Uses = [EFLAGS] +} // Defs = [EFLAGS] + +// Unsigned multiplication +let Defs = [RAX,RDX,EFLAGS], Uses = [RAX], neverHasSideEffects = 1 in { +def MUL64r : RI<0xF7, MRM4r, (outs), (ins GR64:$src), + "mul{q}\t$src", []>; // RAX,RDX = RAX*GR64 +let mayLoad = 1 in +def MUL64m : RI<0xF7, MRM4m, (outs), (ins i64mem:$src), + "mul{q}\t$src", []>; // RAX,RDX = RAX*[mem64] + +// Signed multiplication +def IMUL64r : RI<0xF7, MRM5r, (outs), (ins GR64:$src), + "imul{q}\t$src", []>; // RAX,RDX = RAX*GR64 +let mayLoad = 1 in +def IMUL64m : RI<0xF7, MRM5m, (outs), (ins i64mem:$src), + "imul{q}\t$src", []>; // RAX,RDX = RAX*[mem64] +} + +let Defs = [EFLAGS] in { +let isTwoAddress = 1 in { +let isCommutable = 1 in +// Register-Register Signed Integer Multiplication +def IMUL64rr : RI<0xAF, MRMSrcReg, (outs GR64:$dst), + (ins GR64:$src1, GR64:$src2), + "imul{q}\t{$src2, $dst|$dst, $src2}", + [(set GR64:$dst, (mul GR64:$src1, GR64:$src2)), + (implicit EFLAGS)]>, TB; + +// Register-Memory Signed Integer Multiplication +def IMUL64rm : RI<0xAF, MRMSrcMem, (outs GR64:$dst), + (ins GR64:$src1, i64mem:$src2), + "imul{q}\t{$src2, $dst|$dst, $src2}", + [(set GR64:$dst, (mul GR64:$src1, (load addr:$src2))), + (implicit EFLAGS)]>, TB; +} // isTwoAddress + +// Suprisingly enough, these are not two address instructions! + +// Register-Integer Signed Integer Multiplication +def IMUL64rri8 : RIi8<0x6B, MRMSrcReg, // GR64 = GR64*I8 + (outs GR64:$dst), (ins GR64:$src1, i64i8imm:$src2), + "imul{q}\t{$src2, $src1, $dst|$dst, $src1, $src2}", + [(set GR64:$dst, (mul GR64:$src1, i64immSExt8:$src2)), + (implicit EFLAGS)]>; +def IMUL64rri32 : RIi32<0x69, MRMSrcReg, // GR64 = GR64*I32 + (outs GR64:$dst), (ins GR64:$src1, i64i32imm:$src2), + "imul{q}\t{$src2, $src1, $dst|$dst, $src1, $src2}", + [(set GR64:$dst, (mul GR64:$src1, i64immSExt32:$src2)), + (implicit EFLAGS)]>; + +// Memory-Integer Signed Integer Multiplication +def IMUL64rmi8 : RIi8<0x6B, MRMSrcMem, // GR64 = [mem64]*I8 + (outs GR64:$dst), (ins i64mem:$src1, i64i8imm: $src2), + "imul{q}\t{$src2, $src1, $dst|$dst, $src1, $src2}", + [(set GR64:$dst, (mul (load addr:$src1), + i64immSExt8:$src2)), + (implicit EFLAGS)]>; +def IMUL64rmi32 : RIi32<0x69, MRMSrcMem, // GR64 = [mem64]*I32 + (outs GR64:$dst), (ins i64mem:$src1, i64i32imm:$src2), + "imul{q}\t{$src2, $src1, $dst|$dst, $src1, $src2}", + [(set GR64:$dst, (mul (load addr:$src1), + i64immSExt32:$src2)), + (implicit EFLAGS)]>; +} // Defs = [EFLAGS] + +// Unsigned division / remainder +let Defs = [RAX,RDX,EFLAGS], Uses = [RAX,RDX] in { +def DIV64r : RI<0xF7, MRM6r, (outs), (ins GR64:$src), // RDX:RAX/r64 = RAX,RDX + "div{q}\t$src", []>; +// Signed division / remainder +def IDIV64r: RI<0xF7, MRM7r, (outs), (ins GR64:$src), // RDX:RAX/r64 = RAX,RDX + "idiv{q}\t$src", []>; +let mayLoad = 1 in { +def DIV64m : RI<0xF7, MRM6m, (outs), (ins i64mem:$src), // RDX:RAX/[mem64] = RAX,RDX + "div{q}\t$src", []>; +def IDIV64m: RI<0xF7, MRM7m, (outs), (ins i64mem:$src), // RDX:RAX/[mem64] = RAX,RDX + "idiv{q}\t$src", []>; +} +} + +// Unary instructions +let Defs = [EFLAGS], CodeSize = 2 in { +let isTwoAddress = 1 in +def NEG64r : RI<0xF7, MRM3r, (outs GR64:$dst), (ins GR64:$src), "neg{q}\t$dst", + [(set GR64:$dst, (ineg GR64:$src)), + (implicit EFLAGS)]>; +def NEG64m : RI<0xF7, MRM3m, (outs), (ins i64mem:$dst), "neg{q}\t$dst", + [(store (ineg (loadi64 addr:$dst)), addr:$dst), + (implicit EFLAGS)]>; + +let isTwoAddress = 1, isConvertibleToThreeAddress = 1 in +def INC64r : RI<0xFF, MRM0r, (outs GR64:$dst), (ins GR64:$src), "inc{q}\t$dst", + [(set GR64:$dst, (add GR64:$src, 1)), + (implicit EFLAGS)]>; +def INC64m : RI<0xFF, MRM0m, (outs), (ins i64mem:$dst), "inc{q}\t$dst", + [(store (add (loadi64 addr:$dst), 1), addr:$dst), + (implicit EFLAGS)]>; + +let isTwoAddress = 1, isConvertibleToThreeAddress = 1 in +def DEC64r : RI<0xFF, MRM1r, (outs GR64:$dst), (ins GR64:$src), "dec{q}\t$dst", + [(set GR64:$dst, (add GR64:$src, -1)), + (implicit EFLAGS)]>; +def DEC64m : RI<0xFF, MRM1m, (outs), (ins i64mem:$dst), "dec{q}\t$dst", + [(store (add (loadi64 addr:$dst), -1), addr:$dst), + (implicit EFLAGS)]>; + +// In 64-bit mode, single byte INC and DEC cannot be encoded. +let isTwoAddress = 1, isConvertibleToThreeAddress = 1 in { +// Can transform into LEA. +def INC64_16r : I<0xFF, MRM0r, (outs GR16:$dst), (ins GR16:$src), "inc{w}\t$dst", + [(set GR16:$dst, (add GR16:$src, 1)), + (implicit EFLAGS)]>, + OpSize, Requires<[In64BitMode]>; +def INC64_32r : I<0xFF, MRM0r, (outs GR32:$dst), (ins GR32:$src), "inc{l}\t$dst", + [(set GR32:$dst, (add GR32:$src, 1)), + (implicit EFLAGS)]>, + Requires<[In64BitMode]>; +def DEC64_16r : I<0xFF, MRM1r, (outs GR16:$dst), (ins GR16:$src), "dec{w}\t$dst", + [(set GR16:$dst, (add GR16:$src, -1)), + (implicit EFLAGS)]>, + OpSize, Requires<[In64BitMode]>; +def DEC64_32r : I<0xFF, MRM1r, (outs GR32:$dst), (ins GR32:$src), "dec{l}\t$dst", + [(set GR32:$dst, (add GR32:$src, -1)), + (implicit EFLAGS)]>, + Requires<[In64BitMode]>; +} // isConvertibleToThreeAddress + +// These are duplicates of their 32-bit counterparts. Only needed so X86 knows +// how to unfold them. +let isTwoAddress = 0, CodeSize = 2 in { + def INC64_16m : I<0xFF, MRM0m, (outs), (ins i16mem:$dst), "inc{w}\t$dst", + [(store (add (loadi16 addr:$dst), 1), addr:$dst), + (implicit EFLAGS)]>, + OpSize, Requires<[In64BitMode]>; + def INC64_32m : I<0xFF, MRM0m, (outs), (ins i32mem:$dst), "inc{l}\t$dst", + [(store (add (loadi32 addr:$dst), 1), addr:$dst), + (implicit EFLAGS)]>, + Requires<[In64BitMode]>; + def DEC64_16m : I<0xFF, MRM1m, (outs), (ins i16mem:$dst), "dec{w}\t$dst", + [(store (add (loadi16 addr:$dst), -1), addr:$dst), + (implicit EFLAGS)]>, + OpSize, Requires<[In64BitMode]>; + def DEC64_32m : I<0xFF, MRM1m, (outs), (ins i32mem:$dst), "dec{l}\t$dst", + [(store (add (loadi32 addr:$dst), -1), addr:$dst), + (implicit EFLAGS)]>, + Requires<[In64BitMode]>; +} +} // Defs = [EFLAGS], CodeSize + + +let Defs = [EFLAGS] in { +// Shift instructions +let isTwoAddress = 1 in { +let Uses = [CL] in +def SHL64rCL : RI<0xD3, MRM4r, (outs GR64:$dst), (ins GR64:$src), + "shl{q}\t{%cl, $dst|$dst, %CL}", + [(set GR64:$dst, (shl GR64:$src, CL))]>; +let isConvertibleToThreeAddress = 1 in // Can transform into LEA. +def SHL64ri : RIi8<0xC1, MRM4r, (outs GR64:$dst), (ins GR64:$src1, i8imm:$src2), + "shl{q}\t{$src2, $dst|$dst, $src2}", + [(set GR64:$dst, (shl GR64:$src1, (i8 imm:$src2)))]>; +// NOTE: We don't include patterns for shifts of a register by one, because +// 'add reg,reg' is cheaper. +def SHL64r1 : RI<0xD1, MRM4r, (outs GR64:$dst), (ins GR64:$src1), + "shr{q}\t$dst", []>; +} // isTwoAddress + +let Uses = [CL] in +def SHL64mCL : RI<0xD3, MRM4m, (outs), (ins i64mem:$dst), + "shl{q}\t{%cl, $dst|$dst, %CL}", + [(store (shl (loadi64 addr:$dst), CL), addr:$dst)]>; +def SHL64mi : RIi8<0xC1, MRM4m, (outs), (ins i64mem:$dst, i8imm:$src), + "shl{q}\t{$src, $dst|$dst, $src}", + [(store (shl (loadi64 addr:$dst), (i8 imm:$src)), addr:$dst)]>; +def SHL64m1 : RI<0xD1, MRM4m, (outs), (ins i64mem:$dst), + "shl{q}\t$dst", + [(store (shl (loadi64 addr:$dst), (i8 1)), addr:$dst)]>; + +let isTwoAddress = 1 in { +let Uses = [CL] in +def SHR64rCL : RI<0xD3, MRM5r, (outs GR64:$dst), (ins GR64:$src), + "shr{q}\t{%cl, $dst|$dst, %CL}", + [(set GR64:$dst, (srl GR64:$src, CL))]>; +def SHR64ri : RIi8<0xC1, MRM5r, (outs GR64:$dst), (ins GR64:$src1, i8imm:$src2), + "shr{q}\t{$src2, $dst|$dst, $src2}", + [(set GR64:$dst, (srl GR64:$src1, (i8 imm:$src2)))]>; +def SHR64r1 : RI<0xD1, MRM5r, (outs GR64:$dst), (ins GR64:$src1), + "shr{q}\t$dst", + [(set GR64:$dst, (srl GR64:$src1, (i8 1)))]>; +} // isTwoAddress + +let Uses = [CL] in +def SHR64mCL : RI<0xD3, MRM5m, (outs), (ins i64mem:$dst), + "shr{q}\t{%cl, $dst|$dst, %CL}", + [(store (srl (loadi64 addr:$dst), CL), addr:$dst)]>; +def SHR64mi : RIi8<0xC1, MRM5m, (outs), (ins i64mem:$dst, i8imm:$src), + "shr{q}\t{$src, $dst|$dst, $src}", + [(store (srl (loadi64 addr:$dst), (i8 imm:$src)), addr:$dst)]>; +def SHR64m1 : RI<0xD1, MRM5m, (outs), (ins i64mem:$dst), + "shr{q}\t$dst", + [(store (srl (loadi64 addr:$dst), (i8 1)), addr:$dst)]>; + +let isTwoAddress = 1 in { +let Uses = [CL] in +def SAR64rCL : RI<0xD3, MRM7r, (outs GR64:$dst), (ins GR64:$src), + "sar{q}\t{%cl, $dst|$dst, %CL}", + [(set GR64:$dst, (sra GR64:$src, CL))]>; +def SAR64ri : RIi8<0xC1, MRM7r, (outs GR64:$dst), (ins GR64:$src1, i8imm:$src2), + "sar{q}\t{$src2, $dst|$dst, $src2}", + [(set GR64:$dst, (sra GR64:$src1, (i8 imm:$src2)))]>; +def SAR64r1 : RI<0xD1, MRM7r, (outs GR64:$dst), (ins GR64:$src1), + "sar{q}\t$dst", + [(set GR64:$dst, (sra GR64:$src1, (i8 1)))]>; +} // isTwoAddress + +let Uses = [CL] in +def SAR64mCL : RI<0xD3, MRM7m, (outs), (ins i64mem:$dst), + "sar{q}\t{%cl, $dst|$dst, %CL}", + [(store (sra (loadi64 addr:$dst), CL), addr:$dst)]>; +def SAR64mi : RIi8<0xC1, MRM7m, (outs), (ins i64mem:$dst, i8imm:$src), + "sar{q}\t{$src, $dst|$dst, $src}", + [(store (sra (loadi64 addr:$dst), (i8 imm:$src)), addr:$dst)]>; +def SAR64m1 : RI<0xD1, MRM7m, (outs), (ins i64mem:$dst), + "sar{q}\t$dst", + [(store (sra (loadi64 addr:$dst), (i8 1)), addr:$dst)]>; + +// Rotate instructions + +let isTwoAddress = 1 in { +def RCL64r1 : RI<0xD1, MRM2r, (outs GR64:$dst), (ins GR64:$src), + "rcl{q}\t{1, $dst|$dst, 1}", []>; +def RCL64m1 : RI<0xD1, MRM2m, (outs i64mem:$dst), (ins i64mem:$src), + "rcl{q}\t{1, $dst|$dst, 1}", []>; +let Uses = [CL] in { +def RCL64rCL : RI<0xD3, MRM2r, (outs GR64:$dst), (ins GR64:$src), + "rcl{q}\t{%cl, $dst|$dst, CL}", []>; +def RCL64mCL : RI<0xD3, MRM2m, (outs i64mem:$dst), (ins i64mem:$src), + "rcl{q}\t{%cl, $dst|$dst, CL}", []>; +} +def RCL64ri : RIi8<0xC1, MRM2r, (outs GR64:$dst), (ins GR64:$src, i8imm:$cnt), + "rcl{q}\t{$cnt, $dst|$dst, $cnt}", []>; +def RCL64mi : RIi8<0xC1, MRM2m, (outs i64mem:$dst), (ins i64mem:$src, i8imm:$cnt), + "rcl{q}\t{$cnt, $dst|$dst, $cnt}", []>; + +def RCR64r1 : RI<0xD1, MRM3r, (outs GR64:$dst), (ins GR64:$src), + "rcr{q}\t{1, $dst|$dst, 1}", []>; +def RCR64m1 : RI<0xD1, MRM3m, (outs i64mem:$dst), (ins i64mem:$src), + "rcr{q}\t{1, $dst|$dst, 1}", []>; +let Uses = [CL] in { +def RCR64rCL : RI<0xD3, MRM3r, (outs GR64:$dst), (ins GR64:$src), + "rcr{q}\t{%cl, $dst|$dst, CL}", []>; +def RCR64mCL : RI<0xD3, MRM3m, (outs i64mem:$dst), (ins i64mem:$src), + "rcr{q}\t{%cl, $dst|$dst, CL}", []>; +} +def RCR64ri : RIi8<0xC1, MRM3r, (outs GR64:$dst), (ins GR64:$src, i8imm:$cnt), + "rcr{q}\t{$cnt, $dst|$dst, $cnt}", []>; +def RCR64mi : RIi8<0xC1, MRM3m, (outs i64mem:$dst), (ins i64mem:$src, i8imm:$cnt), + "rcr{q}\t{$cnt, $dst|$dst, $cnt}", []>; +} + +let isTwoAddress = 1 in { +let Uses = [CL] in +def ROL64rCL : RI<0xD3, MRM0r, (outs GR64:$dst), (ins GR64:$src), + "rol{q}\t{%cl, $dst|$dst, %CL}", + [(set GR64:$dst, (rotl GR64:$src, CL))]>; +def ROL64ri : RIi8<0xC1, MRM0r, (outs GR64:$dst), (ins GR64:$src1, i8imm:$src2), + "rol{q}\t{$src2, $dst|$dst, $src2}", + [(set GR64:$dst, (rotl GR64:$src1, (i8 imm:$src2)))]>; +def ROL64r1 : RI<0xD1, MRM0r, (outs GR64:$dst), (ins GR64:$src1), + "rol{q}\t$dst", + [(set GR64:$dst, (rotl GR64:$src1, (i8 1)))]>; +} // isTwoAddress + +let Uses = [CL] in +def ROL64mCL : I<0xD3, MRM0m, (outs), (ins i64mem:$dst), + "rol{q}\t{%cl, $dst|$dst, %CL}", + [(store (rotl (loadi64 addr:$dst), CL), addr:$dst)]>; +def ROL64mi : RIi8<0xC1, MRM0m, (outs), (ins i64mem:$dst, i8imm:$src), + "rol{q}\t{$src, $dst|$dst, $src}", + [(store (rotl (loadi64 addr:$dst), (i8 imm:$src)), addr:$dst)]>; +def ROL64m1 : RI<0xD1, MRM0m, (outs), (ins i64mem:$dst), + "rol{q}\t$dst", + [(store (rotl (loadi64 addr:$dst), (i8 1)), addr:$dst)]>; + +let isTwoAddress = 1 in { +let Uses = [CL] in +def ROR64rCL : RI<0xD3, MRM1r, (outs GR64:$dst), (ins GR64:$src), + "ror{q}\t{%cl, $dst|$dst, %CL}", + [(set GR64:$dst, (rotr GR64:$src, CL))]>; +def ROR64ri : RIi8<0xC1, MRM1r, (outs GR64:$dst), (ins GR64:$src1, i8imm:$src2), + "ror{q}\t{$src2, $dst|$dst, $src2}", + [(set GR64:$dst, (rotr GR64:$src1, (i8 imm:$src2)))]>; +def ROR64r1 : RI<0xD1, MRM1r, (outs GR64:$dst), (ins GR64:$src1), + "ror{q}\t$dst", + [(set GR64:$dst, (rotr GR64:$src1, (i8 1)))]>; +} // isTwoAddress + +let Uses = [CL] in +def ROR64mCL : RI<0xD3, MRM1m, (outs), (ins i64mem:$dst), + "ror{q}\t{%cl, $dst|$dst, %CL}", + [(store (rotr (loadi64 addr:$dst), CL), addr:$dst)]>; +def ROR64mi : RIi8<0xC1, MRM1m, (outs), (ins i64mem:$dst, i8imm:$src), + "ror{q}\t{$src, $dst|$dst, $src}", + [(store (rotr (loadi64 addr:$dst), (i8 imm:$src)), addr:$dst)]>; +def ROR64m1 : RI<0xD1, MRM1m, (outs), (ins i64mem:$dst), + "ror{q}\t$dst", + [(store (rotr (loadi64 addr:$dst), (i8 1)), addr:$dst)]>; + +// Double shift instructions (generalizations of rotate) +let isTwoAddress = 1 in { +let Uses = [CL] in { +def SHLD64rrCL : RI<0xA5, MRMDestReg, (outs GR64:$dst), (ins GR64:$src1, GR64:$src2), + "shld{q}\t{%cl, $src2, $dst|$dst, $src2, %CL}", + [(set GR64:$dst, (X86shld GR64:$src1, GR64:$src2, CL))]>, TB; +def SHRD64rrCL : RI<0xAD, MRMDestReg, (outs GR64:$dst), (ins GR64:$src1, GR64:$src2), + "shrd{q}\t{%cl, $src2, $dst|$dst, $src2, %CL}", + [(set GR64:$dst, (X86shrd GR64:$src1, GR64:$src2, CL))]>, TB; +} + +let isCommutable = 1 in { // FIXME: Update X86InstrInfo::commuteInstruction +def SHLD64rri8 : RIi8<0xA4, MRMDestReg, + (outs GR64:$dst), (ins GR64:$src1, GR64:$src2, i8imm:$src3), + "shld{q}\t{$src3, $src2, $dst|$dst, $src2, $src3}", + [(set GR64:$dst, (X86shld GR64:$src1, GR64:$src2, + (i8 imm:$src3)))]>, + TB; +def SHRD64rri8 : RIi8<0xAC, MRMDestReg, + (outs GR64:$dst), (ins GR64:$src1, GR64:$src2, i8imm:$src3), + "shrd{q}\t{$src3, $src2, $dst|$dst, $src2, $src3}", + [(set GR64:$dst, (X86shrd GR64:$src1, GR64:$src2, + (i8 imm:$src3)))]>, + TB; +} // isCommutable +} // isTwoAddress + +let Uses = [CL] in { +def SHLD64mrCL : RI<0xA5, MRMDestMem, (outs), (ins i64mem:$dst, GR64:$src2), + "shld{q}\t{%cl, $src2, $dst|$dst, $src2, %CL}", + [(store (X86shld (loadi64 addr:$dst), GR64:$src2, CL), + addr:$dst)]>, TB; +def SHRD64mrCL : RI<0xAD, MRMDestMem, (outs), (ins i64mem:$dst, GR64:$src2), + "shrd{q}\t{%cl, $src2, $dst|$dst, $src2, %CL}", + [(store (X86shrd (loadi64 addr:$dst), GR64:$src2, CL), + addr:$dst)]>, TB; +} +def SHLD64mri8 : RIi8<0xA4, MRMDestMem, + (outs), (ins i64mem:$dst, GR64:$src2, i8imm:$src3), + "shld{q}\t{$src3, $src2, $dst|$dst, $src2, $src3}", + [(store (X86shld (loadi64 addr:$dst), GR64:$src2, + (i8 imm:$src3)), addr:$dst)]>, + TB; +def SHRD64mri8 : RIi8<0xAC, MRMDestMem, + (outs), (ins i64mem:$dst, GR64:$src2, i8imm:$src3), + "shrd{q}\t{$src3, $src2, $dst|$dst, $src2, $src3}", + [(store (X86shrd (loadi64 addr:$dst), GR64:$src2, + (i8 imm:$src3)), addr:$dst)]>, + TB; +} // Defs = [EFLAGS] + +//===----------------------------------------------------------------------===// +// Logical Instructions... +// + +let isTwoAddress = 1 , AddedComplexity = 15 in +def NOT64r : RI<0xF7, MRM2r, (outs GR64:$dst), (ins GR64:$src), "not{q}\t$dst", + [(set GR64:$dst, (not GR64:$src))]>; +def NOT64m : RI<0xF7, MRM2m, (outs), (ins i64mem:$dst), "not{q}\t$dst", + [(store (not (loadi64 addr:$dst)), addr:$dst)]>; + +let Defs = [EFLAGS] in { +def AND64i32 : RI<0x25, RawFrm, (outs), (ins i32imm:$src), + "and{q}\t{$src, %rax|%rax, $src}", []>; + +let isTwoAddress = 1 in { +let isCommutable = 1 in +def AND64rr : RI<0x21, MRMDestReg, + (outs GR64:$dst), (ins GR64:$src1, GR64:$src2), + "and{q}\t{$src2, $dst|$dst, $src2}", + [(set GR64:$dst, (and GR64:$src1, GR64:$src2)), + (implicit EFLAGS)]>; +def AND64rm : RI<0x23, MRMSrcMem, + (outs GR64:$dst), (ins GR64:$src1, i64mem:$src2), + "and{q}\t{$src2, $dst|$dst, $src2}", + [(set GR64:$dst, (and GR64:$src1, (load addr:$src2))), + (implicit EFLAGS)]>; +def AND64ri8 : RIi8<0x83, MRM4r, + (outs GR64:$dst), (ins GR64:$src1, i64i8imm:$src2), + "and{q}\t{$src2, $dst|$dst, $src2}", + [(set GR64:$dst, (and GR64:$src1, i64immSExt8:$src2)), + (implicit EFLAGS)]>; +def AND64ri32 : RIi32<0x81, MRM4r, + (outs GR64:$dst), (ins GR64:$src1, i64i32imm:$src2), + "and{q}\t{$src2, $dst|$dst, $src2}", + [(set GR64:$dst, (and GR64:$src1, i64immSExt32:$src2)), + (implicit EFLAGS)]>; +} // isTwoAddress + +def AND64mr : RI<0x21, MRMDestMem, + (outs), (ins i64mem:$dst, GR64:$src), + "and{q}\t{$src, $dst|$dst, $src}", + [(store (and (load addr:$dst), GR64:$src), addr:$dst), + (implicit EFLAGS)]>; +def AND64mi8 : RIi8<0x83, MRM4m, + (outs), (ins i64mem:$dst, i64i8imm :$src), + "and{q}\t{$src, $dst|$dst, $src}", + [(store (and (load addr:$dst), i64immSExt8:$src), addr:$dst), + (implicit EFLAGS)]>; +def AND64mi32 : RIi32<0x81, MRM4m, + (outs), (ins i64mem:$dst, i64i32imm:$src), + "and{q}\t{$src, $dst|$dst, $src}", + [(store (and (loadi64 addr:$dst), i64immSExt32:$src), addr:$dst), + (implicit EFLAGS)]>; + +let isTwoAddress = 1 in { +let isCommutable = 1 in +def OR64rr : RI<0x09, MRMDestReg, (outs GR64:$dst), (ins GR64:$src1, GR64:$src2), + "or{q}\t{$src2, $dst|$dst, $src2}", + [(set GR64:$dst, (or GR64:$src1, GR64:$src2)), + (implicit EFLAGS)]>; +def OR64rm : RI<0x0B, MRMSrcMem , (outs GR64:$dst), (ins GR64:$src1, i64mem:$src2), + "or{q}\t{$src2, $dst|$dst, $src2}", + [(set GR64:$dst, (or GR64:$src1, (load addr:$src2))), + (implicit EFLAGS)]>; +def OR64ri8 : RIi8<0x83, MRM1r, (outs GR64:$dst), (ins GR64:$src1, i64i8imm:$src2), + "or{q}\t{$src2, $dst|$dst, $src2}", + [(set GR64:$dst, (or GR64:$src1, i64immSExt8:$src2)), + (implicit EFLAGS)]>; +def OR64ri32 : RIi32<0x81, MRM1r, (outs GR64:$dst), (ins GR64:$src1, i64i32imm:$src2), + "or{q}\t{$src2, $dst|$dst, $src2}", + [(set GR64:$dst, (or GR64:$src1, i64immSExt32:$src2)), + (implicit EFLAGS)]>; +} // isTwoAddress + +def OR64mr : RI<0x09, MRMDestMem, (outs), (ins i64mem:$dst, GR64:$src), + "or{q}\t{$src, $dst|$dst, $src}", + [(store (or (load addr:$dst), GR64:$src), addr:$dst), + (implicit EFLAGS)]>; +def OR64mi8 : RIi8<0x83, MRM1m, (outs), (ins i64mem:$dst, i64i8imm:$src), + "or{q}\t{$src, $dst|$dst, $src}", + [(store (or (load addr:$dst), i64immSExt8:$src), addr:$dst), + (implicit EFLAGS)]>; +def OR64mi32 : RIi32<0x81, MRM1m, (outs), (ins i64mem:$dst, i64i32imm:$src), + "or{q}\t{$src, $dst|$dst, $src}", + [(store (or (loadi64 addr:$dst), i64immSExt32:$src), addr:$dst), + (implicit EFLAGS)]>; + +def OR64i32 : RIi32<0x0D, RawFrm, (outs), (ins i32imm:$src), + "or{q}\t{$src, %rax|%rax, $src}", []>; + +let isTwoAddress = 1 in { +let isCommutable = 1 in +def XOR64rr : RI<0x31, MRMDestReg, (outs GR64:$dst), (ins GR64:$src1, GR64:$src2), + "xor{q}\t{$src2, $dst|$dst, $src2}", + [(set GR64:$dst, (xor GR64:$src1, GR64:$src2)), + (implicit EFLAGS)]>; +def XOR64rm : RI<0x33, MRMSrcMem, (outs GR64:$dst), (ins GR64:$src1, i64mem:$src2), + "xor{q}\t{$src2, $dst|$dst, $src2}", + [(set GR64:$dst, (xor GR64:$src1, (load addr:$src2))), + (implicit EFLAGS)]>; +def XOR64ri8 : RIi8<0x83, MRM6r, (outs GR64:$dst), (ins GR64:$src1, i64i8imm:$src2), + "xor{q}\t{$src2, $dst|$dst, $src2}", + [(set GR64:$dst, (xor GR64:$src1, i64immSExt8:$src2)), + (implicit EFLAGS)]>; +def XOR64ri32 : RIi32<0x81, MRM6r, + (outs GR64:$dst), (ins GR64:$src1, i64i32imm:$src2), + "xor{q}\t{$src2, $dst|$dst, $src2}", + [(set GR64:$dst, (xor GR64:$src1, i64immSExt32:$src2)), + (implicit EFLAGS)]>; +} // isTwoAddress + +def XOR64mr : RI<0x31, MRMDestMem, (outs), (ins i64mem:$dst, GR64:$src), + "xor{q}\t{$src, $dst|$dst, $src}", + [(store (xor (load addr:$dst), GR64:$src), addr:$dst), + (implicit EFLAGS)]>; +def XOR64mi8 : RIi8<0x83, MRM6m, (outs), (ins i64mem:$dst, i64i8imm :$src), + "xor{q}\t{$src, $dst|$dst, $src}", + [(store (xor (load addr:$dst), i64immSExt8:$src), addr:$dst), + (implicit EFLAGS)]>; +def XOR64mi32 : RIi32<0x81, MRM6m, (outs), (ins i64mem:$dst, i64i32imm:$src), + "xor{q}\t{$src, $dst|$dst, $src}", + [(store (xor (loadi64 addr:$dst), i64immSExt32:$src), addr:$dst), + (implicit EFLAGS)]>; + +def XOR64i32 : RIi32<0x35, RawFrm, (outs), (ins i32imm:$src), + "xor{q}\t{$src, %rax|%rax, $src}", []>; + +} // Defs = [EFLAGS] + +//===----------------------------------------------------------------------===// +// Comparison Instructions... +// + +// Integer comparison +let Defs = [EFLAGS] in { +def TEST64i32 : RI<0xa9, RawFrm, (outs), (ins i32imm:$src), + "test{q}\t{$src, %rax|%rax, $src}", []>; +let isCommutable = 1 in +def TEST64rr : RI<0x85, MRMDestReg, (outs), (ins GR64:$src1, GR64:$src2), + "test{q}\t{$src2, $src1|$src1, $src2}", + [(X86cmp (and GR64:$src1, GR64:$src2), 0), + (implicit EFLAGS)]>; +def TEST64rm : RI<0x85, MRMSrcMem, (outs), (ins GR64:$src1, i64mem:$src2), + "test{q}\t{$src2, $src1|$src1, $src2}", + [(X86cmp (and GR64:$src1, (loadi64 addr:$src2)), 0), + (implicit EFLAGS)]>; +def TEST64ri32 : RIi32<0xF7, MRM0r, (outs), + (ins GR64:$src1, i64i32imm:$src2), + "test{q}\t{$src2, $src1|$src1, $src2}", + [(X86cmp (and GR64:$src1, i64immSExt32:$src2), 0), + (implicit EFLAGS)]>; +def TEST64mi32 : RIi32<0xF7, MRM0m, (outs), + (ins i64mem:$src1, i64i32imm:$src2), + "test{q}\t{$src2, $src1|$src1, $src2}", + [(X86cmp (and (loadi64 addr:$src1), i64immSExt32:$src2), 0), + (implicit EFLAGS)]>; + + +def CMP64i32 : RI<0x3D, RawFrm, (outs), (ins i32imm:$src), + "cmp{q}\t{$src, %rax|%rax, $src}", []>; +def CMP64rr : RI<0x39, MRMDestReg, (outs), (ins GR64:$src1, GR64:$src2), + "cmp{q}\t{$src2, $src1|$src1, $src2}", + [(X86cmp GR64:$src1, GR64:$src2), + (implicit EFLAGS)]>; +def CMP64mrmrr : RI<0x3B, MRMSrcReg, (outs), (ins GR64:$src1, GR64:$src2), + "cmp{q}\t{$src2, $src1|$src1, $src2}", []>; +def CMP64mr : RI<0x39, MRMDestMem, (outs), (ins i64mem:$src1, GR64:$src2), + "cmp{q}\t{$src2, $src1|$src1, $src2}", + [(X86cmp (loadi64 addr:$src1), GR64:$src2), + (implicit EFLAGS)]>; +def CMP64rm : RI<0x3B, MRMSrcMem, (outs), (ins GR64:$src1, i64mem:$src2), + "cmp{q}\t{$src2, $src1|$src1, $src2}", + [(X86cmp GR64:$src1, (loadi64 addr:$src2)), + (implicit EFLAGS)]>; +def CMP64ri8 : RIi8<0x83, MRM7r, (outs), (ins GR64:$src1, i64i8imm:$src2), + "cmp{q}\t{$src2, $src1|$src1, $src2}", + [(X86cmp GR64:$src1, i64immSExt8:$src2), + (implicit EFLAGS)]>; +def CMP64ri32 : RIi32<0x81, MRM7r, (outs), (ins GR64:$src1, i64i32imm:$src2), + "cmp{q}\t{$src2, $src1|$src1, $src2}", + [(X86cmp GR64:$src1, i64immSExt32:$src2), + (implicit EFLAGS)]>; +def CMP64mi8 : RIi8<0x83, MRM7m, (outs), (ins i64mem:$src1, i64i8imm:$src2), + "cmp{q}\t{$src2, $src1|$src1, $src2}", + [(X86cmp (loadi64 addr:$src1), i64immSExt8:$src2), + (implicit EFLAGS)]>; +def CMP64mi32 : RIi32<0x81, MRM7m, (outs), + (ins i64mem:$src1, i64i32imm:$src2), + "cmp{q}\t{$src2, $src1|$src1, $src2}", + [(X86cmp (loadi64 addr:$src1), i64immSExt32:$src2), + (implicit EFLAGS)]>; +} // Defs = [EFLAGS] + +// Bit tests. +// TODO: BTC, BTR, and BTS +let Defs = [EFLAGS] in { +def BT64rr : RI<0xA3, MRMDestReg, (outs), (ins GR64:$src1, GR64:$src2), + "bt{q}\t{$src2, $src1|$src1, $src2}", + [(X86bt GR64:$src1, GR64:$src2), + (implicit EFLAGS)]>, TB; + +// Unlike with the register+register form, the memory+register form of the +// bt instruction does not ignore the high bits of the index. From ISel's +// perspective, this is pretty bizarre. Disable these instructions for now. +//def BT64mr : RI<0xA3, MRMDestMem, (outs), (ins i64mem:$src1, GR64:$src2), +// "bt{q}\t{$src2, $src1|$src1, $src2}", +// [(X86bt (loadi64 addr:$src1), GR64:$src2), +// (implicit EFLAGS)]>, TB; + +def BT64ri8 : Ii8<0xBA, MRM4r, (outs), (ins GR64:$src1, i64i8imm:$src2), + "bt{q}\t{$src2, $src1|$src1, $src2}", + [(X86bt GR64:$src1, i64immSExt8:$src2), + (implicit EFLAGS)]>, TB; +// Note that these instructions don't need FastBTMem because that +// only applies when the other operand is in a register. When it's +// an immediate, bt is still fast. +def BT64mi8 : Ii8<0xBA, MRM4m, (outs), (ins i64mem:$src1, i64i8imm:$src2), + "bt{q}\t{$src2, $src1|$src1, $src2}", + [(X86bt (loadi64 addr:$src1), i64immSExt8:$src2), + (implicit EFLAGS)]>, TB; +} // Defs = [EFLAGS] + +// Conditional moves +let Uses = [EFLAGS], isTwoAddress = 1 in { +let isCommutable = 1 in { +def CMOVB64rr : RI<0x42, MRMSrcReg, // if , TB; +def CMOVAE64rr: RI<0x43, MRMSrcReg, // if >=u, GR64 = GR64 + (outs GR64:$dst), (ins GR64:$src1, GR64:$src2), + "cmovae\t{$src2, $dst|$dst, $src2}", + [(set GR64:$dst, (X86cmov GR64:$src1, GR64:$src2, + X86_COND_AE, EFLAGS))]>, TB; +def CMOVE64rr : RI<0x44, MRMSrcReg, // if ==, GR64 = GR64 + (outs GR64:$dst), (ins GR64:$src1, GR64:$src2), + "cmove\t{$src2, $dst|$dst, $src2}", + [(set GR64:$dst, (X86cmov GR64:$src1, GR64:$src2, + X86_COND_E, EFLAGS))]>, TB; +def CMOVNE64rr: RI<0x45, MRMSrcReg, // if !=, GR64 = GR64 + (outs GR64:$dst), (ins GR64:$src1, GR64:$src2), + "cmovne\t{$src2, $dst|$dst, $src2}", + [(set GR64:$dst, (X86cmov GR64:$src1, GR64:$src2, + X86_COND_NE, EFLAGS))]>, TB; +def CMOVBE64rr: RI<0x46, MRMSrcReg, // if <=u, GR64 = GR64 + (outs GR64:$dst), (ins GR64:$src1, GR64:$src2), + "cmovbe\t{$src2, $dst|$dst, $src2}", + [(set GR64:$dst, (X86cmov GR64:$src1, GR64:$src2, + X86_COND_BE, EFLAGS))]>, TB; +def CMOVA64rr : RI<0x47, MRMSrcReg, // if >u, GR64 = GR64 + (outs GR64:$dst), (ins GR64:$src1, GR64:$src2), + "cmova\t{$src2, $dst|$dst, $src2}", + [(set GR64:$dst, (X86cmov GR64:$src1, GR64:$src2, + X86_COND_A, EFLAGS))]>, TB; +def CMOVL64rr : RI<0x4C, MRMSrcReg, // if , TB; +def CMOVGE64rr: RI<0x4D, MRMSrcReg, // if >=s, GR64 = GR64 + (outs GR64:$dst), (ins GR64:$src1, GR64:$src2), + "cmovge\t{$src2, $dst|$dst, $src2}", + [(set GR64:$dst, (X86cmov GR64:$src1, GR64:$src2, + X86_COND_GE, EFLAGS))]>, TB; +def CMOVLE64rr: RI<0x4E, MRMSrcReg, // if <=s, GR64 = GR64 + (outs GR64:$dst), (ins GR64:$src1, GR64:$src2), + "cmovle\t{$src2, $dst|$dst, $src2}", + [(set GR64:$dst, (X86cmov GR64:$src1, GR64:$src2, + X86_COND_LE, EFLAGS))]>, TB; +def CMOVG64rr : RI<0x4F, MRMSrcReg, // if >s, GR64 = GR64 + (outs GR64:$dst), (ins GR64:$src1, GR64:$src2), + "cmovg\t{$src2, $dst|$dst, $src2}", + [(set GR64:$dst, (X86cmov GR64:$src1, GR64:$src2, + X86_COND_G, EFLAGS))]>, TB; +def CMOVS64rr : RI<0x48, MRMSrcReg, // if signed, GR64 = GR64 + (outs GR64:$dst), (ins GR64:$src1, GR64:$src2), + "cmovs\t{$src2, $dst|$dst, $src2}", + [(set GR64:$dst, (X86cmov GR64:$src1, GR64:$src2, + X86_COND_S, EFLAGS))]>, TB; +def CMOVNS64rr: RI<0x49, MRMSrcReg, // if !signed, GR64 = GR64 + (outs GR64:$dst), (ins GR64:$src1, GR64:$src2), + "cmovns\t{$src2, $dst|$dst, $src2}", + [(set GR64:$dst, (X86cmov GR64:$src1, GR64:$src2, + X86_COND_NS, EFLAGS))]>, TB; +def CMOVP64rr : RI<0x4A, MRMSrcReg, // if parity, GR64 = GR64 + (outs GR64:$dst), (ins GR64:$src1, GR64:$src2), + "cmovp\t{$src2, $dst|$dst, $src2}", + [(set GR64:$dst, (X86cmov GR64:$src1, GR64:$src2, + X86_COND_P, EFLAGS))]>, TB; +def CMOVNP64rr : RI<0x4B, MRMSrcReg, // if !parity, GR64 = GR64 + (outs GR64:$dst), (ins GR64:$src1, GR64:$src2), + "cmovnp\t{$src2, $dst|$dst, $src2}", + [(set GR64:$dst, (X86cmov GR64:$src1, GR64:$src2, + X86_COND_NP, EFLAGS))]>, TB; +def CMOVO64rr : RI<0x40, MRMSrcReg, // if overflow, GR64 = GR64 + (outs GR64:$dst), (ins GR64:$src1, GR64:$src2), + "cmovo\t{$src2, $dst|$dst, $src2}", + [(set GR64:$dst, (X86cmov GR64:$src1, GR64:$src2, + X86_COND_O, EFLAGS))]>, TB; +def CMOVNO64rr : RI<0x41, MRMSrcReg, // if !overflow, GR64 = GR64 + (outs GR64:$dst), (ins GR64:$src1, GR64:$src2), + "cmovno\t{$src2, $dst|$dst, $src2}", + [(set GR64:$dst, (X86cmov GR64:$src1, GR64:$src2, + X86_COND_NO, EFLAGS))]>, TB; +} // isCommutable = 1 + +def CMOVB64rm : RI<0x42, MRMSrcMem, // if , TB; +def CMOVAE64rm: RI<0x43, MRMSrcMem, // if >=u, GR64 = [mem64] + (outs GR64:$dst), (ins GR64:$src1, i64mem:$src2), + "cmovae\t{$src2, $dst|$dst, $src2}", + [(set GR64:$dst, (X86cmov GR64:$src1, (loadi64 addr:$src2), + X86_COND_AE, EFLAGS))]>, TB; +def CMOVE64rm : RI<0x44, MRMSrcMem, // if ==, GR64 = [mem64] + (outs GR64:$dst), (ins GR64:$src1, i64mem:$src2), + "cmove\t{$src2, $dst|$dst, $src2}", + [(set GR64:$dst, (X86cmov GR64:$src1, (loadi64 addr:$src2), + X86_COND_E, EFLAGS))]>, TB; +def CMOVNE64rm: RI<0x45, MRMSrcMem, // if !=, GR64 = [mem64] + (outs GR64:$dst), (ins GR64:$src1, i64mem:$src2), + "cmovne\t{$src2, $dst|$dst, $src2}", + [(set GR64:$dst, (X86cmov GR64:$src1, (loadi64 addr:$src2), + X86_COND_NE, EFLAGS))]>, TB; +def CMOVBE64rm: RI<0x46, MRMSrcMem, // if <=u, GR64 = [mem64] + (outs GR64:$dst), (ins GR64:$src1, i64mem:$src2), + "cmovbe\t{$src2, $dst|$dst, $src2}", + [(set GR64:$dst, (X86cmov GR64:$src1, (loadi64 addr:$src2), + X86_COND_BE, EFLAGS))]>, TB; +def CMOVA64rm : RI<0x47, MRMSrcMem, // if >u, GR64 = [mem64] + (outs GR64:$dst), (ins GR64:$src1, i64mem:$src2), + "cmova\t{$src2, $dst|$dst, $src2}", + [(set GR64:$dst, (X86cmov GR64:$src1, (loadi64 addr:$src2), + X86_COND_A, EFLAGS))]>, TB; +def CMOVL64rm : RI<0x4C, MRMSrcMem, // if , TB; +def CMOVGE64rm: RI<0x4D, MRMSrcMem, // if >=s, GR64 = [mem64] + (outs GR64:$dst), (ins GR64:$src1, i64mem:$src2), + "cmovge\t{$src2, $dst|$dst, $src2}", + [(set GR64:$dst, (X86cmov GR64:$src1, (loadi64 addr:$src2), + X86_COND_GE, EFLAGS))]>, TB; +def CMOVLE64rm: RI<0x4E, MRMSrcMem, // if <=s, GR64 = [mem64] + (outs GR64:$dst), (ins GR64:$src1, i64mem:$src2), + "cmovle\t{$src2, $dst|$dst, $src2}", + [(set GR64:$dst, (X86cmov GR64:$src1, (loadi64 addr:$src2), + X86_COND_LE, EFLAGS))]>, TB; +def CMOVG64rm : RI<0x4F, MRMSrcMem, // if >s, GR64 = [mem64] + (outs GR64:$dst), (ins GR64:$src1, i64mem:$src2), + "cmovg\t{$src2, $dst|$dst, $src2}", + [(set GR64:$dst, (X86cmov GR64:$src1, (loadi64 addr:$src2), + X86_COND_G, EFLAGS))]>, TB; +def CMOVS64rm : RI<0x48, MRMSrcMem, // if signed, GR64 = [mem64] + (outs GR64:$dst), (ins GR64:$src1, i64mem:$src2), + "cmovs\t{$src2, $dst|$dst, $src2}", + [(set GR64:$dst, (X86cmov GR64:$src1, (loadi64 addr:$src2), + X86_COND_S, EFLAGS))]>, TB; +def CMOVNS64rm: RI<0x49, MRMSrcMem, // if !signed, GR64 = [mem64] + (outs GR64:$dst), (ins GR64:$src1, i64mem:$src2), + "cmovns\t{$src2, $dst|$dst, $src2}", + [(set GR64:$dst, (X86cmov GR64:$src1, (loadi64 addr:$src2), + X86_COND_NS, EFLAGS))]>, TB; +def CMOVP64rm : RI<0x4A, MRMSrcMem, // if parity, GR64 = [mem64] + (outs GR64:$dst), (ins GR64:$src1, i64mem:$src2), + "cmovp\t{$src2, $dst|$dst, $src2}", + [(set GR64:$dst, (X86cmov GR64:$src1, (loadi64 addr:$src2), + X86_COND_P, EFLAGS))]>, TB; +def CMOVNP64rm : RI<0x4B, MRMSrcMem, // if !parity, GR64 = [mem64] + (outs GR64:$dst), (ins GR64:$src1, i64mem:$src2), + "cmovnp\t{$src2, $dst|$dst, $src2}", + [(set GR64:$dst, (X86cmov GR64:$src1, (loadi64 addr:$src2), + X86_COND_NP, EFLAGS))]>, TB; +def CMOVO64rm : RI<0x40, MRMSrcMem, // if overflow, GR64 = [mem64] + (outs GR64:$dst), (ins GR64:$src1, i64mem:$src2), + "cmovo\t{$src2, $dst|$dst, $src2}", + [(set GR64:$dst, (X86cmov GR64:$src1, (loadi64 addr:$src2), + X86_COND_O, EFLAGS))]>, TB; +def CMOVNO64rm : RI<0x41, MRMSrcMem, // if !overflow, GR64 = [mem64] + (outs GR64:$dst), (ins GR64:$src1, i64mem:$src2), + "cmovno\t{$src2, $dst|$dst, $src2}", + [(set GR64:$dst, (X86cmov GR64:$src1, (loadi64 addr:$src2), + X86_COND_NO, EFLAGS))]>, TB; +} // isTwoAddress + +//===----------------------------------------------------------------------===// +// Conversion Instructions... +// + +// f64 -> signed i64 +def Int_CVTSD2SI64rr: RSDI<0x2D, MRMSrcReg, (outs GR64:$dst), (ins VR128:$src), + "cvtsd2si{q}\t{$src, $dst|$dst, $src}", + [(set GR64:$dst, + (int_x86_sse2_cvtsd2si64 VR128:$src))]>; +def Int_CVTSD2SI64rm: RSDI<0x2D, MRMSrcMem, (outs GR64:$dst), (ins f128mem:$src), + "cvtsd2si{q}\t{$src, $dst|$dst, $src}", + [(set GR64:$dst, (int_x86_sse2_cvtsd2si64 + (load addr:$src)))]>; +def CVTTSD2SI64rr: RSDI<0x2C, MRMSrcReg, (outs GR64:$dst), (ins FR64:$src), + "cvttsd2si{q}\t{$src, $dst|$dst, $src}", + [(set GR64:$dst, (fp_to_sint FR64:$src))]>; +def CVTTSD2SI64rm: RSDI<0x2C, MRMSrcMem, (outs GR64:$dst), (ins f64mem:$src), + "cvttsd2si{q}\t{$src, $dst|$dst, $src}", + [(set GR64:$dst, (fp_to_sint (loadf64 addr:$src)))]>; +def Int_CVTTSD2SI64rr: RSDI<0x2C, MRMSrcReg, (outs GR64:$dst), (ins VR128:$src), + "cvttsd2si{q}\t{$src, $dst|$dst, $src}", + [(set GR64:$dst, + (int_x86_sse2_cvttsd2si64 VR128:$src))]>; +def Int_CVTTSD2SI64rm: RSDI<0x2C, MRMSrcMem, (outs GR64:$dst), (ins f128mem:$src), + "cvttsd2si{q}\t{$src, $dst|$dst, $src}", + [(set GR64:$dst, + (int_x86_sse2_cvttsd2si64 + (load addr:$src)))]>; + +// Signed i64 -> f64 +def CVTSI2SD64rr: RSDI<0x2A, MRMSrcReg, (outs FR64:$dst), (ins GR64:$src), + "cvtsi2sd{q}\t{$src, $dst|$dst, $src}", + [(set FR64:$dst, (sint_to_fp GR64:$src))]>; +def CVTSI2SD64rm: RSDI<0x2A, MRMSrcMem, (outs FR64:$dst), (ins i64mem:$src), + "cvtsi2sd{q}\t{$src, $dst|$dst, $src}", + [(set FR64:$dst, (sint_to_fp (loadi64 addr:$src)))]>; + +let isTwoAddress = 1 in { +def Int_CVTSI2SD64rr: RSDI<0x2A, MRMSrcReg, + (outs VR128:$dst), (ins VR128:$src1, GR64:$src2), + "cvtsi2sd{q}\t{$src2, $dst|$dst, $src2}", + [(set VR128:$dst, + (int_x86_sse2_cvtsi642sd VR128:$src1, + GR64:$src2))]>; +def Int_CVTSI2SD64rm: RSDI<0x2A, MRMSrcMem, + (outs VR128:$dst), (ins VR128:$src1, i64mem:$src2), + "cvtsi2sd{q}\t{$src2, $dst|$dst, $src2}", + [(set VR128:$dst, + (int_x86_sse2_cvtsi642sd VR128:$src1, + (loadi64 addr:$src2)))]>; +} // isTwoAddress + +// Signed i64 -> f32 +def CVTSI2SS64rr: RSSI<0x2A, MRMSrcReg, (outs FR32:$dst), (ins GR64:$src), + "cvtsi2ss{q}\t{$src, $dst|$dst, $src}", + [(set FR32:$dst, (sint_to_fp GR64:$src))]>; +def CVTSI2SS64rm: RSSI<0x2A, MRMSrcMem, (outs FR32:$dst), (ins i64mem:$src), + "cvtsi2ss{q}\t{$src, $dst|$dst, $src}", + [(set FR32:$dst, (sint_to_fp (loadi64 addr:$src)))]>; + +let isTwoAddress = 1 in { + def Int_CVTSI2SS64rr : RSSI<0x2A, MRMSrcReg, + (outs VR128:$dst), (ins VR128:$src1, GR64:$src2), + "cvtsi2ss{q}\t{$src2, $dst|$dst, $src2}", + [(set VR128:$dst, + (int_x86_sse_cvtsi642ss VR128:$src1, + GR64:$src2))]>; + def Int_CVTSI2SS64rm : RSSI<0x2A, MRMSrcMem, + (outs VR128:$dst), (ins VR128:$src1, i64mem:$src2), + "cvtsi2ss{q}\t{$src2, $dst|$dst, $src2}", + [(set VR128:$dst, + (int_x86_sse_cvtsi642ss VR128:$src1, + (loadi64 addr:$src2)))]>; +} + +// f32 -> signed i64 +def Int_CVTSS2SI64rr: RSSI<0x2D, MRMSrcReg, (outs GR64:$dst), (ins VR128:$src), + "cvtss2si{q}\t{$src, $dst|$dst, $src}", + [(set GR64:$dst, + (int_x86_sse_cvtss2si64 VR128:$src))]>; +def Int_CVTSS2SI64rm: RSSI<0x2D, MRMSrcMem, (outs GR64:$dst), (ins f32mem:$src), + "cvtss2si{q}\t{$src, $dst|$dst, $src}", + [(set GR64:$dst, (int_x86_sse_cvtss2si64 + (load addr:$src)))]>; +def CVTTSS2SI64rr: RSSI<0x2C, MRMSrcReg, (outs GR64:$dst), (ins FR32:$src), + "cvttss2si{q}\t{$src, $dst|$dst, $src}", + [(set GR64:$dst, (fp_to_sint FR32:$src))]>; +def CVTTSS2SI64rm: RSSI<0x2C, MRMSrcMem, (outs GR64:$dst), (ins f32mem:$src), + "cvttss2si{q}\t{$src, $dst|$dst, $src}", + [(set GR64:$dst, (fp_to_sint (loadf32 addr:$src)))]>; +def Int_CVTTSS2SI64rr: RSSI<0x2C, MRMSrcReg, (outs GR64:$dst), (ins VR128:$src), + "cvttss2si{q}\t{$src, $dst|$dst, $src}", + [(set GR64:$dst, + (int_x86_sse_cvttss2si64 VR128:$src))]>; +def Int_CVTTSS2SI64rm: RSSI<0x2C, MRMSrcMem, (outs GR64:$dst), (ins f32mem:$src), + "cvttss2si{q}\t{$src, $dst|$dst, $src}", + [(set GR64:$dst, + (int_x86_sse_cvttss2si64 (load addr:$src)))]>; + +//===----------------------------------------------------------------------===// +// Alias Instructions +//===----------------------------------------------------------------------===// + +// Alias instructions that map movr0 to xor. Use xorl instead of xorq; it's +// equivalent due to implicit zero-extending, and it sometimes has a smaller +// encoding. +// FIXME: AddedComplexity gives this a higher priority than MOV64ri32. Remove +// when we have a better way to specify isel priority. +let AddedComplexity = 1 in +def : Pat<(i64 0), + (SUBREG_TO_REG (i64 0), (MOV32r0), x86_subreg_32bit)>; + + +// Materialize i64 constant where top 32-bits are zero. +let AddedComplexity = 1, isReMaterializable = 1, isAsCheapAsAMove = 1 in +def MOV64ri64i32 : Ii32<0xB8, AddRegFrm, (outs GR64:$dst), (ins i64i32imm:$src), + "", [(set GR64:$dst, i64immZExt32:$src)]>; + +//===----------------------------------------------------------------------===// +// Thread Local Storage Instructions +//===----------------------------------------------------------------------===// + +// All calls clobber the non-callee saved registers. RSP is marked as +// a use to prevent stack-pointer assignments that appear immediately +// before calls from potentially appearing dead. +let Defs = [RAX, RCX, RDX, RSI, RDI, R8, R9, R10, R11, + FP0, FP1, FP2, FP3, FP4, FP5, FP6, ST0, ST1, + MM0, MM1, MM2, MM3, MM4, MM5, MM6, MM7, + XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6, XMM7, + XMM8, XMM9, XMM10, XMM11, XMM12, XMM13, XMM14, XMM15, EFLAGS], + Uses = [RSP] in +def TLS_addr64 : I<0, Pseudo, (outs), (ins lea64mem:$sym), + ".byte\t0x66; " + "leaq\t$sym(%rip), %rdi; " + ".word\t0x6666; " + "rex64; " + "call\t__tls_get_addr@PLT", + [(X86tlsaddr tls64addr:$sym)]>, + Requires<[In64BitMode]>; + +let AddedComplexity = 5, isCodeGenOnly = 1 in +def MOV64GSrm : RI<0x8B, MRMSrcMem, (outs GR64:$dst), (ins i64mem:$src), + "movq\t%gs:$src, $dst", + [(set GR64:$dst, (gsload addr:$src))]>, SegGS; + +let AddedComplexity = 5, isCodeGenOnly = 1 in +def MOV64FSrm : RI<0x8B, MRMSrcMem, (outs GR64:$dst), (ins i64mem:$src), + "movq\t%fs:$src, $dst", + [(set GR64:$dst, (fsload addr:$src))]>, SegFS; + +//===----------------------------------------------------------------------===// +// Atomic Instructions +//===----------------------------------------------------------------------===// + +let Defs = [RAX, EFLAGS], Uses = [RAX] in { +def LCMPXCHG64 : RI<0xB1, MRMDestMem, (outs), (ins i64mem:$ptr, GR64:$swap), + "lock\n\t" + "cmpxchgq\t$swap,$ptr", + [(X86cas addr:$ptr, GR64:$swap, 8)]>, TB, LOCK; +} + +let Constraints = "$val = $dst" in { +let Defs = [EFLAGS] in +def LXADD64 : RI<0xC1, MRMSrcMem, (outs GR64:$dst), (ins i64mem:$ptr,GR64:$val), + "lock\n\t" + "xadd\t$val, $ptr", + [(set GR64:$dst, (atomic_load_add_64 addr:$ptr, GR64:$val))]>, + TB, LOCK; + +def XCHG64rm : RI<0x87, MRMSrcMem, (outs GR64:$dst), (ins i64mem:$ptr,GR64:$val), + "xchg\t$val, $ptr", + [(set GR64:$dst, (atomic_swap_64 addr:$ptr, GR64:$val))]>; +} + +// Optimized codegen when the non-memory output is not used. +let Defs = [EFLAGS] in { +// FIXME: Use normal add / sub instructions and add lock prefix dynamically. +def LOCK_ADD64mr : RI<0x03, MRMDestMem, (outs), (ins i64mem:$dst, GR64:$src2), + "lock\n\t" + "add{q}\t{$src2, $dst|$dst, $src2}", []>, LOCK; +def LOCK_ADD64mi8 : RIi8<0x83, MRM0m, (outs), + (ins i64mem:$dst, i64i8imm :$src2), + "lock\n\t" + "add{q}\t{$src2, $dst|$dst, $src2}", []>, LOCK; +def LOCK_ADD64mi32 : RIi32<0x81, MRM0m, (outs), + (ins i64mem:$dst, i64i32imm :$src2), + "lock\n\t" + "add{q}\t{$src2, $dst|$dst, $src2}", []>, LOCK; +def LOCK_SUB64mr : RI<0x29, MRMDestMem, (outs), (ins i64mem:$dst, GR64:$src2), + "lock\n\t" + "sub{q}\t{$src2, $dst|$dst, $src2}", []>, LOCK; +def LOCK_SUB64mi8 : RIi8<0x83, MRM5m, (outs), + (ins i64mem:$dst, i64i8imm :$src2), + "lock\n\t" + "sub{q}\t{$src2, $dst|$dst, $src2}", []>, LOCK; +def LOCK_SUB64mi32 : RIi32<0x81, MRM5m, (outs), + (ins i64mem:$dst, i64i32imm:$src2), + "lock\n\t" + "sub{q}\t{$src2, $dst|$dst, $src2}", []>, LOCK; +def LOCK_INC64m : RI<0xFF, MRM0m, (outs), (ins i64mem:$dst), + "lock\n\t" + "inc{q}\t$dst", []>, LOCK; +def LOCK_DEC64m : RI<0xFF, MRM1m, (outs), (ins i64mem:$dst), + "lock\n\t" + "dec{q}\t$dst", []>, LOCK; +} +// Atomic exchange, and, or, xor +let Constraints = "$val = $dst", Defs = [EFLAGS], + usesCustomInserter = 1 in { +def ATOMAND64 : I<0, Pseudo, (outs GR64:$dst),(ins i64mem:$ptr, GR64:$val), + "#ATOMAND64 PSEUDO!", + [(set GR64:$dst, (atomic_load_and_64 addr:$ptr, GR64:$val))]>; +def ATOMOR64 : I<0, Pseudo, (outs GR64:$dst),(ins i64mem:$ptr, GR64:$val), + "#ATOMOR64 PSEUDO!", + [(set GR64:$dst, (atomic_load_or_64 addr:$ptr, GR64:$val))]>; +def ATOMXOR64 : I<0, Pseudo,(outs GR64:$dst),(ins i64mem:$ptr, GR64:$val), + "#ATOMXOR64 PSEUDO!", + [(set GR64:$dst, (atomic_load_xor_64 addr:$ptr, GR64:$val))]>; +def ATOMNAND64 : I<0, Pseudo,(outs GR64:$dst),(ins i64mem:$ptr, GR64:$val), + "#ATOMNAND64 PSEUDO!", + [(set GR64:$dst, (atomic_load_nand_64 addr:$ptr, GR64:$val))]>; +def ATOMMIN64: I<0, Pseudo, (outs GR64:$dst), (ins i64mem:$ptr, GR64:$val), + "#ATOMMIN64 PSEUDO!", + [(set GR64:$dst, (atomic_load_min_64 addr:$ptr, GR64:$val))]>; +def ATOMMAX64: I<0, Pseudo, (outs GR64:$dst),(ins i64mem:$ptr, GR64:$val), + "#ATOMMAX64 PSEUDO!", + [(set GR64:$dst, (atomic_load_max_64 addr:$ptr, GR64:$val))]>; +def ATOMUMIN64: I<0, Pseudo, (outs GR64:$dst),(ins i64mem:$ptr, GR64:$val), + "#ATOMUMIN64 PSEUDO!", + [(set GR64:$dst, (atomic_load_umin_64 addr:$ptr, GR64:$val))]>; +def ATOMUMAX64: I<0, Pseudo, (outs GR64:$dst),(ins i64mem:$ptr, GR64:$val), + "#ATOMUMAX64 PSEUDO!", + [(set GR64:$dst, (atomic_load_umax_64 addr:$ptr, GR64:$val))]>; +} + +// Segmentation support instructions + +// i16mem operand in LAR64rm and GR32 operand in LAR32rr is not a typo. +def LAR64rm : RI<0x02, MRMSrcMem, (outs GR64:$dst), (ins i16mem:$src), + "lar{q}\t{$src, $dst|$dst, $src}", []>, TB; +def LAR64rr : RI<0x02, MRMSrcReg, (outs GR64:$dst), (ins GR32:$src), + "lar{q}\t{$src, $dst|$dst, $src}", []>, TB; + +// String manipulation instructions + +def LODSQ : RI<0xAD, RawFrm, (outs), (ins), "lodsq", []>; + +//===----------------------------------------------------------------------===// +// Non-Instruction Patterns +//===----------------------------------------------------------------------===// + +// ConstantPool GlobalAddress, ExternalSymbol, and JumpTable when not in small +// code model mode, should use 'movabs'. FIXME: This is really a hack, the +// 'movabs' predicate should handle this sort of thing. +def : Pat<(i64 (X86Wrapper tconstpool :$dst)), + (MOV64ri tconstpool :$dst)>, Requires<[FarData]>; +def : Pat<(i64 (X86Wrapper tjumptable :$dst)), + (MOV64ri tjumptable :$dst)>, Requires<[FarData]>; +def : Pat<(i64 (X86Wrapper tglobaladdr :$dst)), + (MOV64ri tglobaladdr :$dst)>, Requires<[FarData]>; +def : Pat<(i64 (X86Wrapper texternalsym:$dst)), + (MOV64ri texternalsym:$dst)>, Requires<[FarData]>; +def : Pat<(i64 (X86Wrapper tblockaddress:$dst)), + (MOV64ri tblockaddress:$dst)>, Requires<[FarData]>; + +// In static codegen with small code model, we can get the address of a label +// into a register with 'movl'. FIXME: This is a hack, the 'imm' predicate of +// the MOV64ri64i32 should accept these. +def : Pat<(i64 (X86Wrapper tconstpool :$dst)), + (MOV64ri64i32 tconstpool :$dst)>, Requires<[SmallCode]>; +def : Pat<(i64 (X86Wrapper tjumptable :$dst)), + (MOV64ri64i32 tjumptable :$dst)>, Requires<[SmallCode]>; +def : Pat<(i64 (X86Wrapper tglobaladdr :$dst)), + (MOV64ri64i32 tglobaladdr :$dst)>, Requires<[SmallCode]>; +def : Pat<(i64 (X86Wrapper texternalsym:$dst)), + (MOV64ri64i32 texternalsym:$dst)>, Requires<[SmallCode]>; +def : Pat<(i64 (X86Wrapper tblockaddress:$dst)), + (MOV64ri64i32 tblockaddress:$dst)>, Requires<[SmallCode]>; + +// In kernel code model, we can get the address of a label +// into a register with 'movq'. FIXME: This is a hack, the 'imm' predicate of +// the MOV64ri32 should accept these. +def : Pat<(i64 (X86Wrapper tconstpool :$dst)), + (MOV64ri32 tconstpool :$dst)>, Requires<[KernelCode]>; +def : Pat<(i64 (X86Wrapper tjumptable :$dst)), + (MOV64ri32 tjumptable :$dst)>, Requires<[KernelCode]>; +def : Pat<(i64 (X86Wrapper tglobaladdr :$dst)), + (MOV64ri32 tglobaladdr :$dst)>, Requires<[KernelCode]>; +def : Pat<(i64 (X86Wrapper texternalsym:$dst)), + (MOV64ri32 texternalsym:$dst)>, Requires<[KernelCode]>; +def : Pat<(i64 (X86Wrapper tblockaddress:$dst)), + (MOV64ri32 tblockaddress:$dst)>, Requires<[KernelCode]>; + +// If we have small model and -static mode, it is safe to store global addresses +// directly as immediates. FIXME: This is really a hack, the 'imm' predicate +// for MOV64mi32 should handle this sort of thing. +def : Pat<(store (i64 (X86Wrapper tconstpool:$src)), addr:$dst), + (MOV64mi32 addr:$dst, tconstpool:$src)>, + Requires<[NearData, IsStatic]>; +def : Pat<(store (i64 (X86Wrapper tjumptable:$src)), addr:$dst), + (MOV64mi32 addr:$dst, tjumptable:$src)>, + Requires<[NearData, IsStatic]>; +def : Pat<(store (i64 (X86Wrapper tglobaladdr:$src)), addr:$dst), + (MOV64mi32 addr:$dst, tglobaladdr:$src)>, + Requires<[NearData, IsStatic]>; +def : Pat<(store (i64 (X86Wrapper texternalsym:$src)), addr:$dst), + (MOV64mi32 addr:$dst, texternalsym:$src)>, + Requires<[NearData, IsStatic]>; +def : Pat<(store (i64 (X86Wrapper tblockaddress:$src)), addr:$dst), + (MOV64mi32 addr:$dst, tblockaddress:$src)>, + Requires<[NearData, IsStatic]>; + +// Calls +// Direct PC relative function call for small code model. 32-bit displacement +// sign extended to 64-bit. +def : Pat<(X86call (i64 tglobaladdr:$dst)), + (CALL64pcrel32 tglobaladdr:$dst)>, Requires<[NotWin64]>; +def : Pat<(X86call (i64 texternalsym:$dst)), + (CALL64pcrel32 texternalsym:$dst)>, Requires<[NotWin64]>; + +def : Pat<(X86call (i64 tglobaladdr:$dst)), + (WINCALL64pcrel32 tglobaladdr:$dst)>, Requires<[IsWin64]>; +def : Pat<(X86call (i64 texternalsym:$dst)), + (WINCALL64pcrel32 texternalsym:$dst)>, Requires<[IsWin64]>; + +// tailcall stuff +def : Pat<(X86tcret GR64:$dst, imm:$off), + (TCRETURNri64 GR64:$dst, imm:$off)>; + +def : Pat<(X86tcret (i64 tglobaladdr:$dst), imm:$off), + (TCRETURNdi64 texternalsym:$dst, imm:$off)>; + +def : Pat<(X86tcret (i64 texternalsym:$dst), imm:$off), + (TCRETURNdi64 texternalsym:$dst, imm:$off)>; + +// Comparisons. + +// TEST R,R is smaller than CMP R,0 +def : Pat<(parallel (X86cmp GR64:$src1, 0), (implicit EFLAGS)), + (TEST64rr GR64:$src1, GR64:$src1)>; + +// Conditional moves with folded loads with operands swapped and conditions +// inverted. +def : Pat<(X86cmov (loadi64 addr:$src1), GR64:$src2, X86_COND_B, EFLAGS), + (CMOVAE64rm GR64:$src2, addr:$src1)>; +def : Pat<(X86cmov (loadi64 addr:$src1), GR64:$src2, X86_COND_AE, EFLAGS), + (CMOVB64rm GR64:$src2, addr:$src1)>; +def : Pat<(X86cmov (loadi64 addr:$src1), GR64:$src2, X86_COND_E, EFLAGS), + (CMOVNE64rm GR64:$src2, addr:$src1)>; +def : Pat<(X86cmov (loadi64 addr:$src1), GR64:$src2, X86_COND_NE, EFLAGS), + (CMOVE64rm GR64:$src2, addr:$src1)>; +def : Pat<(X86cmov (loadi64 addr:$src1), GR64:$src2, X86_COND_BE, EFLAGS), + (CMOVA64rm GR64:$src2, addr:$src1)>; +def : Pat<(X86cmov (loadi64 addr:$src1), GR64:$src2, X86_COND_A, EFLAGS), + (CMOVBE64rm GR64:$src2, addr:$src1)>; +def : Pat<(X86cmov (loadi64 addr:$src1), GR64:$src2, X86_COND_L, EFLAGS), + (CMOVGE64rm GR64:$src2, addr:$src1)>; +def : Pat<(X86cmov (loadi64 addr:$src1), GR64:$src2, X86_COND_GE, EFLAGS), + (CMOVL64rm GR64:$src2, addr:$src1)>; +def : Pat<(X86cmov (loadi64 addr:$src1), GR64:$src2, X86_COND_LE, EFLAGS), + (CMOVG64rm GR64:$src2, addr:$src1)>; +def : Pat<(X86cmov (loadi64 addr:$src1), GR64:$src2, X86_COND_G, EFLAGS), + (CMOVLE64rm GR64:$src2, addr:$src1)>; +def : Pat<(X86cmov (loadi64 addr:$src1), GR64:$src2, X86_COND_P, EFLAGS), + (CMOVNP64rm GR64:$src2, addr:$src1)>; +def : Pat<(X86cmov (loadi64 addr:$src1), GR64:$src2, X86_COND_NP, EFLAGS), + (CMOVP64rm GR64:$src2, addr:$src1)>; +def : Pat<(X86cmov (loadi64 addr:$src1), GR64:$src2, X86_COND_S, EFLAGS), + (CMOVNS64rm GR64:$src2, addr:$src1)>; +def : Pat<(X86cmov (loadi64 addr:$src1), GR64:$src2, X86_COND_NS, EFLAGS), + (CMOVS64rm GR64:$src2, addr:$src1)>; +def : Pat<(X86cmov (loadi64 addr:$src1), GR64:$src2, X86_COND_O, EFLAGS), + (CMOVNO64rm GR64:$src2, addr:$src1)>; +def : Pat<(X86cmov (loadi64 addr:$src1), GR64:$src2, X86_COND_NO, EFLAGS), + (CMOVO64rm GR64:$src2, addr:$src1)>; + +// zextload bool -> zextload byte +def : Pat<(zextloadi64i1 addr:$src), (MOVZX64rm8 addr:$src)>; + +// extload +// When extloading from 16-bit and smaller memory locations into 64-bit registers, +// use zero-extending loads so that the entire 64-bit register is defined, avoiding +// partial-register updates. +def : Pat<(extloadi64i1 addr:$src), (MOVZX64rm8 addr:$src)>; +def : Pat<(extloadi64i8 addr:$src), (MOVZX64rm8 addr:$src)>; +def : Pat<(extloadi64i16 addr:$src), (MOVZX64rm16 addr:$src)>; +// For other extloads, use subregs, since the high contents of the register are +// defined after an extload. +def : Pat<(extloadi64i32 addr:$src), + (SUBREG_TO_REG (i64 0), (MOV32rm addr:$src), + x86_subreg_32bit)>; + +// anyext. Define these to do an explicit zero-extend to +// avoid partial-register updates. +def : Pat<(i64 (anyext GR8 :$src)), (MOVZX64rr8 GR8 :$src)>; +def : Pat<(i64 (anyext GR16:$src)), (MOVZX64rr16 GR16 :$src)>; +def : Pat<(i64 (anyext GR32:$src)), + (SUBREG_TO_REG (i64 0), GR32:$src, x86_subreg_32bit)>; + +//===----------------------------------------------------------------------===// +// Some peepholes +//===----------------------------------------------------------------------===// + +// Odd encoding trick: -128 fits into an 8-bit immediate field while +// +128 doesn't, so in this special case use a sub instead of an add. +def : Pat<(add GR64:$src1, 128), + (SUB64ri8 GR64:$src1, -128)>; +def : Pat<(store (add (loadi64 addr:$dst), 128), addr:$dst), + (SUB64mi8 addr:$dst, -128)>; + +// The same trick applies for 32-bit immediate fields in 64-bit +// instructions. +def : Pat<(add GR64:$src1, 0x0000000080000000), + (SUB64ri32 GR64:$src1, 0xffffffff80000000)>; +def : Pat<(store (add (loadi64 addr:$dst), 0x00000000800000000), addr:$dst), + (SUB64mi32 addr:$dst, 0xffffffff80000000)>; + +// r & (2^32-1) ==> movz +def : Pat<(and GR64:$src, 0x00000000FFFFFFFF), + (MOVZX64rr32 (EXTRACT_SUBREG GR64:$src, x86_subreg_32bit))>; +// r & (2^16-1) ==> movz +def : Pat<(and GR64:$src, 0xffff), + (MOVZX64rr16 (i16 (EXTRACT_SUBREG GR64:$src, x86_subreg_16bit)))>; +// r & (2^8-1) ==> movz +def : Pat<(and GR64:$src, 0xff), + (MOVZX64rr8 (i8 (EXTRACT_SUBREG GR64:$src, x86_subreg_8bit)))>; +// r & (2^8-1) ==> movz +def : Pat<(and GR32:$src1, 0xff), + (MOVZX32rr8 (EXTRACT_SUBREG GR32:$src1, x86_subreg_8bit))>, + Requires<[In64BitMode]>; +// r & (2^8-1) ==> movz +def : Pat<(and GR16:$src1, 0xff), + (MOVZX16rr8 (i8 (EXTRACT_SUBREG GR16:$src1, x86_subreg_8bit)))>, + Requires<[In64BitMode]>; + +// sext_inreg patterns +def : Pat<(sext_inreg GR64:$src, i32), + (MOVSX64rr32 (EXTRACT_SUBREG GR64:$src, x86_subreg_32bit))>; +def : Pat<(sext_inreg GR64:$src, i16), + (MOVSX64rr16 (EXTRACT_SUBREG GR64:$src, x86_subreg_16bit))>; +def : Pat<(sext_inreg GR64:$src, i8), + (MOVSX64rr8 (EXTRACT_SUBREG GR64:$src, x86_subreg_8bit))>; +def : Pat<(sext_inreg GR32:$src, i8), + (MOVSX32rr8 (EXTRACT_SUBREG GR32:$src, x86_subreg_8bit))>, + Requires<[In64BitMode]>; +def : Pat<(sext_inreg GR16:$src, i8), + (MOVSX16rr8 (i8 (EXTRACT_SUBREG GR16:$src, x86_subreg_8bit)))>, + Requires<[In64BitMode]>; + +// trunc patterns +def : Pat<(i32 (trunc GR64:$src)), + (EXTRACT_SUBREG GR64:$src, x86_subreg_32bit)>; +def : Pat<(i16 (trunc GR64:$src)), + (EXTRACT_SUBREG GR64:$src, x86_subreg_16bit)>; +def : Pat<(i8 (trunc GR64:$src)), + (EXTRACT_SUBREG GR64:$src, x86_subreg_8bit)>; +def : Pat<(i8 (trunc GR32:$src)), + (EXTRACT_SUBREG GR32:$src, x86_subreg_8bit)>, + Requires<[In64BitMode]>; +def : Pat<(i8 (trunc GR16:$src)), + (EXTRACT_SUBREG GR16:$src, x86_subreg_8bit)>, + Requires<[In64BitMode]>; + +// h-register tricks. +// For now, be conservative on x86-64 and use an h-register extract only if the +// value is immediately zero-extended or stored, which are somewhat common +// cases. This uses a bunch of code to prevent a register requiring a REX prefix +// from being allocated in the same instruction as the h register, as there's +// currently no way to describe this requirement to the register allocator. + +// h-register extract and zero-extend. +def : Pat<(and (srl_su GR64:$src, (i8 8)), (i64 255)), + (SUBREG_TO_REG + (i64 0), + (MOVZX32_NOREXrr8 + (EXTRACT_SUBREG (i64 (COPY_TO_REGCLASS GR64:$src, GR64_ABCD)), + x86_subreg_8bit_hi)), + x86_subreg_32bit)>; +def : Pat<(and (srl_su GR32:$src, (i8 8)), (i32 255)), + (MOVZX32_NOREXrr8 + (EXTRACT_SUBREG (i32 (COPY_TO_REGCLASS GR32:$src, GR32_ABCD)), + x86_subreg_8bit_hi))>, + Requires<[In64BitMode]>; +def : Pat<(srl_su GR16:$src, (i8 8)), + (EXTRACT_SUBREG + (MOVZX32_NOREXrr8 + (EXTRACT_SUBREG (i16 (COPY_TO_REGCLASS GR16:$src, GR16_ABCD)), + x86_subreg_8bit_hi)), + x86_subreg_16bit)>, + Requires<[In64BitMode]>; +def : Pat<(i32 (zext (srl_su GR16:$src, (i8 8)))), + (MOVZX32_NOREXrr8 + (EXTRACT_SUBREG (i16 (COPY_TO_REGCLASS GR16:$src, GR16_ABCD)), + x86_subreg_8bit_hi))>, + Requires<[In64BitMode]>; +def : Pat<(i32 (anyext (srl_su GR16:$src, (i8 8)))), + (MOVZX32_NOREXrr8 + (EXTRACT_SUBREG (i16 (COPY_TO_REGCLASS GR16:$src, GR16_ABCD)), + x86_subreg_8bit_hi))>, + Requires<[In64BitMode]>; +def : Pat<(i64 (zext (srl_su GR16:$src, (i8 8)))), + (SUBREG_TO_REG + (i64 0), + (MOVZX32_NOREXrr8 + (EXTRACT_SUBREG (i16 (COPY_TO_REGCLASS GR16:$src, GR16_ABCD)), + x86_subreg_8bit_hi)), + x86_subreg_32bit)>; +def : Pat<(i64 (anyext (srl_su GR16:$src, (i8 8)))), + (SUBREG_TO_REG + (i64 0), + (MOVZX32_NOREXrr8 + (EXTRACT_SUBREG (i16 (COPY_TO_REGCLASS GR16:$src, GR16_ABCD)), + x86_subreg_8bit_hi)), + x86_subreg_32bit)>; + +// h-register extract and store. +def : Pat<(store (i8 (trunc_su (srl_su GR64:$src, (i8 8)))), addr:$dst), + (MOV8mr_NOREX + addr:$dst, + (EXTRACT_SUBREG (i64 (COPY_TO_REGCLASS GR64:$src, GR64_ABCD)), + x86_subreg_8bit_hi))>; +def : Pat<(store (i8 (trunc_su (srl_su GR32:$src, (i8 8)))), addr:$dst), + (MOV8mr_NOREX + addr:$dst, + (EXTRACT_SUBREG (i32 (COPY_TO_REGCLASS GR32:$src, GR32_ABCD)), + x86_subreg_8bit_hi))>, + Requires<[In64BitMode]>; +def : Pat<(store (i8 (trunc_su (srl_su GR16:$src, (i8 8)))), addr:$dst), + (MOV8mr_NOREX + addr:$dst, + (EXTRACT_SUBREG (i16 (COPY_TO_REGCLASS GR16:$src, GR16_ABCD)), + x86_subreg_8bit_hi))>, + Requires<[In64BitMode]>; + +// (shl x, 1) ==> (add x, x) +def : Pat<(shl GR64:$src1, (i8 1)), (ADD64rr GR64:$src1, GR64:$src1)>; + +// (shl x (and y, 63)) ==> (shl x, y) +def : Pat<(shl GR64:$src1, (and CL:$amt, 63)), + (SHL64rCL GR64:$src1)>; +def : Pat<(store (shl (loadi64 addr:$dst), (and CL:$amt, 63)), addr:$dst), + (SHL64mCL addr:$dst)>; + +def : Pat<(srl GR64:$src1, (and CL:$amt, 63)), + (SHR64rCL GR64:$src1)>; +def : Pat<(store (srl (loadi64 addr:$dst), (and CL:$amt, 63)), addr:$dst), + (SHR64mCL addr:$dst)>; + +def : Pat<(sra GR64:$src1, (and CL:$amt, 63)), + (SAR64rCL GR64:$src1)>; +def : Pat<(store (sra (loadi64 addr:$dst), (and CL:$amt, 63)), addr:$dst), + (SAR64mCL addr:$dst)>; + +// (or (x >> c) | (y << (64 - c))) ==> (shrd64 x, y, c) +def : Pat<(or (srl GR64:$src1, CL:$amt), + (shl GR64:$src2, (sub 64, CL:$amt))), + (SHRD64rrCL GR64:$src1, GR64:$src2)>; + +def : Pat<(store (or (srl (loadi64 addr:$dst), CL:$amt), + (shl GR64:$src2, (sub 64, CL:$amt))), addr:$dst), + (SHRD64mrCL addr:$dst, GR64:$src2)>; + +def : Pat<(or (srl GR64:$src1, (i8 (trunc RCX:$amt))), + (shl GR64:$src2, (i8 (trunc (sub 64, RCX:$amt))))), + (SHRD64rrCL GR64:$src1, GR64:$src2)>; + +def : Pat<(store (or (srl (loadi64 addr:$dst), (i8 (trunc RCX:$amt))), + (shl GR64:$src2, (i8 (trunc (sub 64, RCX:$amt))))), + addr:$dst), + (SHRD64mrCL addr:$dst, GR64:$src2)>; + +def : Pat<(shrd GR64:$src1, (i8 imm:$amt1), GR64:$src2, (i8 imm:$amt2)), + (SHRD64rri8 GR64:$src1, GR64:$src2, (i8 imm:$amt1))>; + +def : Pat<(store (shrd (loadi64 addr:$dst), (i8 imm:$amt1), + GR64:$src2, (i8 imm:$amt2)), addr:$dst), + (SHRD64mri8 addr:$dst, GR64:$src2, (i8 imm:$amt1))>; + +// (or (x << c) | (y >> (64 - c))) ==> (shld64 x, y, c) +def : Pat<(or (shl GR64:$src1, CL:$amt), + (srl GR64:$src2, (sub 64, CL:$amt))), + (SHLD64rrCL GR64:$src1, GR64:$src2)>; + +def : Pat<(store (or (shl (loadi64 addr:$dst), CL:$amt), + (srl GR64:$src2, (sub 64, CL:$amt))), addr:$dst), + (SHLD64mrCL addr:$dst, GR64:$src2)>; + +def : Pat<(or (shl GR64:$src1, (i8 (trunc RCX:$amt))), + (srl GR64:$src2, (i8 (trunc (sub 64, RCX:$amt))))), + (SHLD64rrCL GR64:$src1, GR64:$src2)>; + +def : Pat<(store (or (shl (loadi64 addr:$dst), (i8 (trunc RCX:$amt))), + (srl GR64:$src2, (i8 (trunc (sub 64, RCX:$amt))))), + addr:$dst), + (SHLD64mrCL addr:$dst, GR64:$src2)>; + +def : Pat<(shld GR64:$src1, (i8 imm:$amt1), GR64:$src2, (i8 imm:$amt2)), + (SHLD64rri8 GR64:$src1, GR64:$src2, (i8 imm:$amt1))>; + +def : Pat<(store (shld (loadi64 addr:$dst), (i8 imm:$amt1), + GR64:$src2, (i8 imm:$amt2)), addr:$dst), + (SHLD64mri8 addr:$dst, GR64:$src2, (i8 imm:$amt1))>; + +// X86 specific add which produces a flag. +def : Pat<(addc GR64:$src1, GR64:$src2), + (ADD64rr GR64:$src1, GR64:$src2)>; +def : Pat<(addc GR64:$src1, (load addr:$src2)), + (ADD64rm GR64:$src1, addr:$src2)>; +def : Pat<(addc GR64:$src1, i64immSExt8:$src2), + (ADD64ri8 GR64:$src1, i64immSExt8:$src2)>; +def : Pat<(addc GR64:$src1, i64immSExt32:$src2), + (ADD64ri32 GR64:$src1, imm:$src2)>; + +def : Pat<(subc GR64:$src1, GR64:$src2), + (SUB64rr GR64:$src1, GR64:$src2)>; +def : Pat<(subc GR64:$src1, (load addr:$src2)), + (SUB64rm GR64:$src1, addr:$src2)>; +def : Pat<(subc GR64:$src1, i64immSExt8:$src2), + (SUB64ri8 GR64:$src1, i64immSExt8:$src2)>; +def : Pat<(subc GR64:$src1, imm:$src2), + (SUB64ri32 GR64:$src1, i64immSExt32:$src2)>; + +//===----------------------------------------------------------------------===// +// EFLAGS-defining Patterns +//===----------------------------------------------------------------------===// + +// Register-Register Addition with EFLAGS result +def : Pat<(parallel (X86add_flag GR64:$src1, GR64:$src2), + (implicit EFLAGS)), + (ADD64rr GR64:$src1, GR64:$src2)>; + +// Register-Integer Addition with EFLAGS result +def : Pat<(parallel (X86add_flag GR64:$src1, i64immSExt8:$src2), + (implicit EFLAGS)), + (ADD64ri8 GR64:$src1, i64immSExt8:$src2)>; +def : Pat<(parallel (X86add_flag GR64:$src1, i64immSExt32:$src2), + (implicit EFLAGS)), + (ADD64ri32 GR64:$src1, i64immSExt32:$src2)>; + +// Register-Memory Addition with EFLAGS result +def : Pat<(parallel (X86add_flag GR64:$src1, (loadi64 addr:$src2)), + (implicit EFLAGS)), + (ADD64rm GR64:$src1, addr:$src2)>; + +// Memory-Register Addition with EFLAGS result +def : Pat<(parallel (store (X86add_flag (loadi64 addr:$dst), GR64:$src2), + addr:$dst), + (implicit EFLAGS)), + (ADD64mr addr:$dst, GR64:$src2)>; +def : Pat<(parallel (store (X86add_flag (loadi64 addr:$dst), i64immSExt8:$src2), + addr:$dst), + (implicit EFLAGS)), + (ADD64mi8 addr:$dst, i64immSExt8:$src2)>; +def : Pat<(parallel (store (X86add_flag (loadi64 addr:$dst), i64immSExt32:$src2), + addr:$dst), + (implicit EFLAGS)), + (ADD64mi32 addr:$dst, i64immSExt32:$src2)>; + +// Register-Register Subtraction with EFLAGS result +def : Pat<(parallel (X86sub_flag GR64:$src1, GR64:$src2), + (implicit EFLAGS)), + (SUB64rr GR64:$src1, GR64:$src2)>; + +// Register-Memory Subtraction with EFLAGS result +def : Pat<(parallel (X86sub_flag GR64:$src1, (loadi64 addr:$src2)), + (implicit EFLAGS)), + (SUB64rm GR64:$src1, addr:$src2)>; + +// Register-Integer Subtraction with EFLAGS result +def : Pat<(parallel (X86sub_flag GR64:$src1, i64immSExt8:$src2), + (implicit EFLAGS)), + (SUB64ri8 GR64:$src1, i64immSExt8:$src2)>; +def : Pat<(parallel (X86sub_flag GR64:$src1, i64immSExt32:$src2), + (implicit EFLAGS)), + (SUB64ri32 GR64:$src1, i64immSExt32:$src2)>; + +// Memory-Register Subtraction with EFLAGS result +def : Pat<(parallel (store (X86sub_flag (loadi64 addr:$dst), GR64:$src2), + addr:$dst), + (implicit EFLAGS)), + (SUB64mr addr:$dst, GR64:$src2)>; + +// Memory-Integer Subtraction with EFLAGS result +def : Pat<(parallel (store (X86sub_flag (loadi64 addr:$dst), i64immSExt8:$src2), + addr:$dst), + (implicit EFLAGS)), + (SUB64mi8 addr:$dst, i64immSExt8:$src2)>; +def : Pat<(parallel (store (X86sub_flag (loadi64 addr:$dst), i64immSExt32:$src2), + addr:$dst), + (implicit EFLAGS)), + (SUB64mi32 addr:$dst, i64immSExt32:$src2)>; + +// Register-Register Signed Integer Multiplication with EFLAGS result +def : Pat<(parallel (X86smul_flag GR64:$src1, GR64:$src2), + (implicit EFLAGS)), + (IMUL64rr GR64:$src1, GR64:$src2)>; + +// Register-Memory Signed Integer Multiplication with EFLAGS result +def : Pat<(parallel (X86smul_flag GR64:$src1, (loadi64 addr:$src2)), + (implicit EFLAGS)), + (IMUL64rm GR64:$src1, addr:$src2)>; + +// Register-Integer Signed Integer Multiplication with EFLAGS result +def : Pat<(parallel (X86smul_flag GR64:$src1, i64immSExt8:$src2), + (implicit EFLAGS)), + (IMUL64rri8 GR64:$src1, i64immSExt8:$src2)>; +def : Pat<(parallel (X86smul_flag GR64:$src1, i64immSExt32:$src2), + (implicit EFLAGS)), + (IMUL64rri32 GR64:$src1, i64immSExt32:$src2)>; + +// Memory-Integer Signed Integer Multiplication with EFLAGS result +def : Pat<(parallel (X86smul_flag (loadi64 addr:$src1), i64immSExt8:$src2), + (implicit EFLAGS)), + (IMUL64rmi8 addr:$src1, i64immSExt8:$src2)>; +def : Pat<(parallel (X86smul_flag (loadi64 addr:$src1), i64immSExt32:$src2), + (implicit EFLAGS)), + (IMUL64rmi32 addr:$src1, i64immSExt32:$src2)>; + +// INC and DEC with EFLAGS result. Note that these do not set CF. +def : Pat<(parallel (X86inc_flag GR16:$src), (implicit EFLAGS)), + (INC64_16r GR16:$src)>, Requires<[In64BitMode]>; +def : Pat<(parallel (store (i16 (X86inc_flag (loadi16 addr:$dst))), addr:$dst), + (implicit EFLAGS)), + (INC64_16m addr:$dst)>, Requires<[In64BitMode]>; +def : Pat<(parallel (X86dec_flag GR16:$src), (implicit EFLAGS)), + (DEC64_16r GR16:$src)>, Requires<[In64BitMode]>; +def : Pat<(parallel (store (i16 (X86dec_flag (loadi16 addr:$dst))), addr:$dst), + (implicit EFLAGS)), + (DEC64_16m addr:$dst)>, Requires<[In64BitMode]>; + +def : Pat<(parallel (X86inc_flag GR32:$src), (implicit EFLAGS)), + (INC64_32r GR32:$src)>, Requires<[In64BitMode]>; +def : Pat<(parallel (store (i32 (X86inc_flag (loadi32 addr:$dst))), addr:$dst), + (implicit EFLAGS)), + (INC64_32m addr:$dst)>, Requires<[In64BitMode]>; +def : Pat<(parallel (X86dec_flag GR32:$src), (implicit EFLAGS)), + (DEC64_32r GR32:$src)>, Requires<[In64BitMode]>; +def : Pat<(parallel (store (i32 (X86dec_flag (loadi32 addr:$dst))), addr:$dst), + (implicit EFLAGS)), + (DEC64_32m addr:$dst)>, Requires<[In64BitMode]>; + +def : Pat<(parallel (X86inc_flag GR64:$src), (implicit EFLAGS)), + (INC64r GR64:$src)>; +def : Pat<(parallel (store (i64 (X86inc_flag (loadi64 addr:$dst))), addr:$dst), + (implicit EFLAGS)), + (INC64m addr:$dst)>; +def : Pat<(parallel (X86dec_flag GR64:$src), (implicit EFLAGS)), + (DEC64r GR64:$src)>; +def : Pat<(parallel (store (i64 (X86dec_flag (loadi64 addr:$dst))), addr:$dst), + (implicit EFLAGS)), + (DEC64m addr:$dst)>; + +// Register-Register Logical Or with EFLAGS result +def : Pat<(parallel (X86or_flag GR64:$src1, GR64:$src2), + (implicit EFLAGS)), + (OR64rr GR64:$src1, GR64:$src2)>; + +// Register-Integer Logical Or with EFLAGS result +def : Pat<(parallel (X86or_flag GR64:$src1, i64immSExt8:$src2), + (implicit EFLAGS)), + (OR64ri8 GR64:$src1, i64immSExt8:$src2)>; +def : Pat<(parallel (X86or_flag GR64:$src1, i64immSExt32:$src2), + (implicit EFLAGS)), + (OR64ri32 GR64:$src1, i64immSExt32:$src2)>; + +// Register-Memory Logical Or with EFLAGS result +def : Pat<(parallel (X86or_flag GR64:$src1, (loadi64 addr:$src2)), + (implicit EFLAGS)), + (OR64rm GR64:$src1, addr:$src2)>; + +// Memory-Register Logical Or with EFLAGS result +def : Pat<(parallel (store (X86or_flag (loadi64 addr:$dst), GR64:$src2), + addr:$dst), + (implicit EFLAGS)), + (OR64mr addr:$dst, GR64:$src2)>; +def : Pat<(parallel (store (X86or_flag (loadi64 addr:$dst), i64immSExt8:$src2), + addr:$dst), + (implicit EFLAGS)), + (OR64mi8 addr:$dst, i64immSExt8:$src2)>; +def : Pat<(parallel (store (X86or_flag (loadi64 addr:$dst), i64immSExt32:$src2), + addr:$dst), + (implicit EFLAGS)), + (OR64mi32 addr:$dst, i64immSExt32:$src2)>; + +// Register-Register Logical XOr with EFLAGS result +def : Pat<(parallel (X86xor_flag GR64:$src1, GR64:$src2), + (implicit EFLAGS)), + (XOR64rr GR64:$src1, GR64:$src2)>; + +// Register-Integer Logical XOr with EFLAGS result +def : Pat<(parallel (X86xor_flag GR64:$src1, i64immSExt8:$src2), + (implicit EFLAGS)), + (XOR64ri8 GR64:$src1, i64immSExt8:$src2)>; +def : Pat<(parallel (X86xor_flag GR64:$src1, i64immSExt32:$src2), + (implicit EFLAGS)), + (XOR64ri32 GR64:$src1, i64immSExt32:$src2)>; + +// Register-Memory Logical XOr with EFLAGS result +def : Pat<(parallel (X86xor_flag GR64:$src1, (loadi64 addr:$src2)), + (implicit EFLAGS)), + (XOR64rm GR64:$src1, addr:$src2)>; + +// Memory-Register Logical XOr with EFLAGS result +def : Pat<(parallel (store (X86xor_flag (loadi64 addr:$dst), GR64:$src2), + addr:$dst), + (implicit EFLAGS)), + (XOR64mr addr:$dst, GR64:$src2)>; +def : Pat<(parallel (store (X86xor_flag (loadi64 addr:$dst), i64immSExt8:$src2), + addr:$dst), + (implicit EFLAGS)), + (XOR64mi8 addr:$dst, i64immSExt8:$src2)>; +def : Pat<(parallel (store (X86xor_flag (loadi64 addr:$dst), i64immSExt32:$src2), + addr:$dst), + (implicit EFLAGS)), + (XOR64mi32 addr:$dst, i64immSExt32:$src2)>; + +// Register-Register Logical And with EFLAGS result +def : Pat<(parallel (X86and_flag GR64:$src1, GR64:$src2), + (implicit EFLAGS)), + (AND64rr GR64:$src1, GR64:$src2)>; + +// Register-Integer Logical And with EFLAGS result +def : Pat<(parallel (X86and_flag GR64:$src1, i64immSExt8:$src2), + (implicit EFLAGS)), + (AND64ri8 GR64:$src1, i64immSExt8:$src2)>; +def : Pat<(parallel (X86and_flag GR64:$src1, i64immSExt32:$src2), + (implicit EFLAGS)), + (AND64ri32 GR64:$src1, i64immSExt32:$src2)>; + +// Register-Memory Logical And with EFLAGS result +def : Pat<(parallel (X86and_flag GR64:$src1, (loadi64 addr:$src2)), + (implicit EFLAGS)), + (AND64rm GR64:$src1, addr:$src2)>; + +// Memory-Register Logical And with EFLAGS result +def : Pat<(parallel (store (X86and_flag (loadi64 addr:$dst), GR64:$src2), + addr:$dst), + (implicit EFLAGS)), + (AND64mr addr:$dst, GR64:$src2)>; +def : Pat<(parallel (store (X86and_flag (loadi64 addr:$dst), i64immSExt8:$src2), + addr:$dst), + (implicit EFLAGS)), + (AND64mi8 addr:$dst, i64immSExt8:$src2)>; +def : Pat<(parallel (store (X86and_flag (loadi64 addr:$dst), i64immSExt32:$src2), + addr:$dst), + (implicit EFLAGS)), + (AND64mi32 addr:$dst, i64immSExt32:$src2)>; + +//===----------------------------------------------------------------------===// +// X86-64 SSE Instructions +//===----------------------------------------------------------------------===// + +// Move instructions... + +def MOV64toPQIrr : RPDI<0x6E, MRMSrcReg, (outs VR128:$dst), (ins GR64:$src), + "mov{d|q}\t{$src, $dst|$dst, $src}", + [(set VR128:$dst, + (v2i64 (scalar_to_vector GR64:$src)))]>; +def MOVPQIto64rr : RPDI<0x7E, MRMDestReg, (outs GR64:$dst), (ins VR128:$src), + "mov{d|q}\t{$src, $dst|$dst, $src}", + [(set GR64:$dst, (vector_extract (v2i64 VR128:$src), + (iPTR 0)))]>; + +def MOV64toSDrr : RPDI<0x6E, MRMSrcReg, (outs FR64:$dst), (ins GR64:$src), + "mov{d|q}\t{$src, $dst|$dst, $src}", + [(set FR64:$dst, (bitconvert GR64:$src))]>; +def MOV64toSDrm : RPDI<0x6E, MRMSrcMem, (outs FR64:$dst), (ins i64mem:$src), + "movq\t{$src, $dst|$dst, $src}", + [(set FR64:$dst, (bitconvert (loadi64 addr:$src)))]>; + +def MOVSDto64rr : RPDI<0x7E, MRMDestReg, (outs GR64:$dst), (ins FR64:$src), + "mov{d|q}\t{$src, $dst|$dst, $src}", + [(set GR64:$dst, (bitconvert FR64:$src))]>; +def MOVSDto64mr : RPDI<0x7E, MRMDestMem, (outs), (ins i64mem:$dst, FR64:$src), + "movq\t{$src, $dst|$dst, $src}", + [(store (i64 (bitconvert FR64:$src)), addr:$dst)]>; + +//===----------------------------------------------------------------------===// +// X86-64 SSE4.1 Instructions +//===----------------------------------------------------------------------===// + +/// SS41I_extract32 - SSE 4.1 extract 32 bits to int reg or memory destination +multiclass SS41I_extract64 opc, string OpcodeStr> { + def rr : SS4AIi8, OpSize, REX_W; + def mr : SS4AIi8, OpSize, REX_W; +} + +defm PEXTRQ : SS41I_extract64<0x16, "pextrq">; + +let isTwoAddress = 1 in { + multiclass SS41I_insert64 opc, string OpcodeStr> { + def rr : SS4AIi8, + OpSize, REX_W; + def rm : SS4AIi8, OpSize, REX_W; + } +} + +defm PINSRQ : SS41I_insert64<0x22, "pinsrq">; + +// -disable-16bit support. +def : Pat<(truncstorei16 (i64 imm:$src), addr:$dst), + (MOV16mi addr:$dst, imm:$src)>; +def : Pat<(truncstorei16 GR64:$src, addr:$dst), + (MOV16mr addr:$dst, (EXTRACT_SUBREG GR64:$src, x86_subreg_16bit))>; +def : Pat<(i64 (sextloadi16 addr:$dst)), + (MOVSX64rm16 addr:$dst)>; +def : Pat<(i64 (zextloadi16 addr:$dst)), + (MOVZX64rm16 addr:$dst)>; +def : Pat<(i64 (extloadi16 addr:$dst)), + (MOVZX64rm16 addr:$dst)>; diff --git a/libclamav/c++/llvm/lib/Target/X86/X86InstrBuilder.h b/libclamav/c++/llvm/lib/Target/X86/X86InstrBuilder.h new file mode 100644 index 000000000..c475b56d1 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/X86/X86InstrBuilder.h @@ -0,0 +1,172 @@ +//===-- X86InstrBuilder.h - Functions to aid building x86 insts -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file exposes functions that may be used with BuildMI from the +// MachineInstrBuilder.h file to handle X86'isms in a clean way. +// +// The BuildMem function may be used with the BuildMI function to add entire +// memory references in a single, typed, function call. X86 memory references +// can be very complex expressions (described in the README), so wrapping them +// up behind an easier to use interface makes sense. Descriptions of the +// functions are included below. +// +// For reference, the order of operands for memory references is: +// (Operand), Base, Scale, Index, Displacement. +// +//===----------------------------------------------------------------------===// + +#ifndef X86INSTRBUILDER_H +#define X86INSTRBUILDER_H + +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineMemOperand.h" +#include "llvm/CodeGen/PseudoSourceValue.h" + +namespace llvm { + +/// X86AddressMode - This struct holds a generalized full x86 address mode. +/// The base register can be a frame index, which will eventually be replaced +/// with BP or SP and Disp being offsetted accordingly. The displacement may +/// also include the offset of a global value. +struct X86AddressMode { + enum { + RegBase, + FrameIndexBase + } BaseType; + + union { + unsigned Reg; + int FrameIndex; + } Base; + + unsigned Scale; + unsigned IndexReg; + int Disp; + GlobalValue *GV; + unsigned GVOpFlags; + + X86AddressMode() + : BaseType(RegBase), Scale(1), IndexReg(0), Disp(0), GV(0), GVOpFlags(0) { + Base.Reg = 0; + } +}; + +/// addDirectMem - This function is used to add a direct memory reference to the +/// current instruction -- that is, a dereference of an address in a register, +/// with no scale, index or displacement. An example is: DWORD PTR [EAX]. +/// +static inline const MachineInstrBuilder & +addDirectMem(const MachineInstrBuilder &MIB, unsigned Reg) { + // Because memory references are always represented with four + // values, this adds: Reg, [1, NoReg, 0] to the instruction. + return MIB.addReg(Reg).addImm(1).addReg(0).addImm(0); +} + +static inline const MachineInstrBuilder & +addLeaOffset(const MachineInstrBuilder &MIB, int Offset) { + return MIB.addImm(1).addReg(0).addImm(Offset); +} + +static inline const MachineInstrBuilder & +addOffset(const MachineInstrBuilder &MIB, int Offset) { + return addLeaOffset(MIB, Offset).addReg(0); +} + +/// addRegOffset - This function is used to add a memory reference of the form +/// [Reg + Offset], i.e., one with no scale or index, but with a +/// displacement. An example is: DWORD PTR [EAX + 4]. +/// +static inline const MachineInstrBuilder & +addRegOffset(const MachineInstrBuilder &MIB, + unsigned Reg, bool isKill, int Offset) { + return addOffset(MIB.addReg(Reg, getKillRegState(isKill)), Offset); +} + +static inline const MachineInstrBuilder & +addLeaRegOffset(const MachineInstrBuilder &MIB, + unsigned Reg, bool isKill, int Offset) { + return addLeaOffset(MIB.addReg(Reg, getKillRegState(isKill)), Offset); +} + +/// addRegReg - This function is used to add a memory reference of the form: +/// [Reg + Reg]. +static inline const MachineInstrBuilder &addRegReg(const MachineInstrBuilder &MIB, + unsigned Reg1, bool isKill1, + unsigned Reg2, bool isKill2) { + return MIB.addReg(Reg1, getKillRegState(isKill1)).addImm(1) + .addReg(Reg2, getKillRegState(isKill2)).addImm(0); +} + +static inline const MachineInstrBuilder & +addLeaAddress(const MachineInstrBuilder &MIB, const X86AddressMode &AM) { + assert (AM.Scale == 1 || AM.Scale == 2 || AM.Scale == 4 || AM.Scale == 8); + + if (AM.BaseType == X86AddressMode::RegBase) + MIB.addReg(AM.Base.Reg); + else if (AM.BaseType == X86AddressMode::FrameIndexBase) + MIB.addFrameIndex(AM.Base.FrameIndex); + else + assert (0); + MIB.addImm(AM.Scale).addReg(AM.IndexReg); + if (AM.GV) + return MIB.addGlobalAddress(AM.GV, AM.Disp, AM.GVOpFlags); + else + return MIB.addImm(AM.Disp); +} + +static inline const MachineInstrBuilder & +addFullAddress(const MachineInstrBuilder &MIB, + const X86AddressMode &AM) { + return addLeaAddress(MIB, AM).addReg(0); +} + +/// addFrameReference - This function is used to add a reference to the base of +/// an abstract object on the stack frame of the current function. This +/// reference has base register as the FrameIndex offset until it is resolved. +/// This allows a constant offset to be specified as well... +/// +static inline const MachineInstrBuilder & +addFrameReference(const MachineInstrBuilder &MIB, int FI, int Offset = 0) { + MachineInstr *MI = MIB; + MachineFunction &MF = *MI->getParent()->getParent(); + MachineFrameInfo &MFI = *MF.getFrameInfo(); + const TargetInstrDesc &TID = MI->getDesc(); + unsigned Flags = 0; + if (TID.mayLoad()) + Flags |= MachineMemOperand::MOLoad; + if (TID.mayStore()) + Flags |= MachineMemOperand::MOStore; + MachineMemOperand *MMO = + MF.getMachineMemOperand(PseudoSourceValue::getFixedStack(FI), + Flags, Offset, + MFI.getObjectSize(FI), + MFI.getObjectAlignment(FI)); + return addOffset(MIB.addFrameIndex(FI), Offset) + .addMemOperand(MMO); +} + +/// addConstantPoolReference - This function is used to add a reference to the +/// base of a constant value spilled to the per-function constant pool. The +/// reference uses the abstract ConstantPoolIndex which is retained until +/// either machine code emission or assembly output. In PIC mode on x86-32, +/// the GlobalBaseReg parameter can be used to make this a +/// GlobalBaseReg-relative reference. +/// +static inline const MachineInstrBuilder & +addConstantPoolReference(const MachineInstrBuilder &MIB, unsigned CPI, + unsigned GlobalBaseReg, unsigned char OpFlags) { + //FIXME: factor this + return MIB.addReg(GlobalBaseReg).addImm(1).addReg(0) + .addConstantPoolIndex(CPI, 0, OpFlags).addReg(0); +} + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/lib/Target/X86/X86InstrFPStack.td b/libclamav/c++/llvm/lib/Target/X86/X86InstrFPStack.td new file mode 100644 index 000000000..b0b0409ad --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/X86/X86InstrFPStack.td @@ -0,0 +1,622 @@ +//==- X86InstrFPStack.td - Describe the X86 Instruction Set --*- tablegen -*-=// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file describes the X86 x87 FPU instruction set, defining the +// instructions, and properties of the instructions which are needed for code +// generation, machine code emission, and analysis. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// FPStack specific DAG Nodes. +//===----------------------------------------------------------------------===// + +def SDTX86FpGet2 : SDTypeProfile<2, 0, [SDTCisVT<0, f80>, + SDTCisVT<1, f80>]>; +def SDTX86Fld : SDTypeProfile<1, 2, [SDTCisFP<0>, + SDTCisPtrTy<1>, + SDTCisVT<2, OtherVT>]>; +def SDTX86Fst : SDTypeProfile<0, 3, [SDTCisFP<0>, + SDTCisPtrTy<1>, + SDTCisVT<2, OtherVT>]>; +def SDTX86Fild : SDTypeProfile<1, 2, [SDTCisFP<0>, SDTCisPtrTy<1>, + SDTCisVT<2, OtherVT>]>; +def SDTX86FpToIMem : SDTypeProfile<0, 2, [SDTCisFP<0>, SDTCisPtrTy<1>]>; + +def SDTX86CwdStore : SDTypeProfile<0, 1, [SDTCisPtrTy<0>]>; + +def X86fld : SDNode<"X86ISD::FLD", SDTX86Fld, + [SDNPHasChain, SDNPMayLoad]>; +def X86fst : SDNode<"X86ISD::FST", SDTX86Fst, + [SDNPHasChain, SDNPInFlag, SDNPMayStore]>; +def X86fild : SDNode<"X86ISD::FILD", SDTX86Fild, + [SDNPHasChain, SDNPMayLoad]>; +def X86fildflag : SDNode<"X86ISD::FILD_FLAG", SDTX86Fild, + [SDNPHasChain, SDNPOutFlag, SDNPMayLoad]>; +def X86fp_to_i16mem : SDNode<"X86ISD::FP_TO_INT16_IN_MEM", SDTX86FpToIMem, + [SDNPHasChain, SDNPMayStore]>; +def X86fp_to_i32mem : SDNode<"X86ISD::FP_TO_INT32_IN_MEM", SDTX86FpToIMem, + [SDNPHasChain, SDNPMayStore]>; +def X86fp_to_i64mem : SDNode<"X86ISD::FP_TO_INT64_IN_MEM", SDTX86FpToIMem, + [SDNPHasChain, SDNPMayStore]>; +def X86fp_cwd_get16 : SDNode<"X86ISD::FNSTCW16m", SDTX86CwdStore, + [SDNPHasChain, SDNPMayStore, SDNPSideEffect]>; + +//===----------------------------------------------------------------------===// +// FPStack pattern fragments +//===----------------------------------------------------------------------===// + +def fpimm0 : PatLeaf<(fpimm), [{ + return N->isExactlyValue(+0.0); +}]>; + +def fpimmneg0 : PatLeaf<(fpimm), [{ + return N->isExactlyValue(-0.0); +}]>; + +def fpimm1 : PatLeaf<(fpimm), [{ + return N->isExactlyValue(+1.0); +}]>; + +def fpimmneg1 : PatLeaf<(fpimm), [{ + return N->isExactlyValue(-1.0); +}]>; + +// Some 'special' instructions +let usesCustomInserter = 1 in { // Expanded after instruction selection. + def FP32_TO_INT16_IN_MEM : I<0, Pseudo, + (outs), (ins i16mem:$dst, RFP32:$src), + "##FP32_TO_INT16_IN_MEM PSEUDO!", + [(X86fp_to_i16mem RFP32:$src, addr:$dst)]>; + def FP32_TO_INT32_IN_MEM : I<0, Pseudo, + (outs), (ins i32mem:$dst, RFP32:$src), + "##FP32_TO_INT32_IN_MEM PSEUDO!", + [(X86fp_to_i32mem RFP32:$src, addr:$dst)]>; + def FP32_TO_INT64_IN_MEM : I<0, Pseudo, + (outs), (ins i64mem:$dst, RFP32:$src), + "##FP32_TO_INT64_IN_MEM PSEUDO!", + [(X86fp_to_i64mem RFP32:$src, addr:$dst)]>; + def FP64_TO_INT16_IN_MEM : I<0, Pseudo, + (outs), (ins i16mem:$dst, RFP64:$src), + "##FP64_TO_INT16_IN_MEM PSEUDO!", + [(X86fp_to_i16mem RFP64:$src, addr:$dst)]>; + def FP64_TO_INT32_IN_MEM : I<0, Pseudo, + (outs), (ins i32mem:$dst, RFP64:$src), + "##FP64_TO_INT32_IN_MEM PSEUDO!", + [(X86fp_to_i32mem RFP64:$src, addr:$dst)]>; + def FP64_TO_INT64_IN_MEM : I<0, Pseudo, + (outs), (ins i64mem:$dst, RFP64:$src), + "##FP64_TO_INT64_IN_MEM PSEUDO!", + [(X86fp_to_i64mem RFP64:$src, addr:$dst)]>; + def FP80_TO_INT16_IN_MEM : I<0, Pseudo, + (outs), (ins i16mem:$dst, RFP80:$src), + "##FP80_TO_INT16_IN_MEM PSEUDO!", + [(X86fp_to_i16mem RFP80:$src, addr:$dst)]>; + def FP80_TO_INT32_IN_MEM : I<0, Pseudo, + (outs), (ins i32mem:$dst, RFP80:$src), + "##FP80_TO_INT32_IN_MEM PSEUDO!", + [(X86fp_to_i32mem RFP80:$src, addr:$dst)]>; + def FP80_TO_INT64_IN_MEM : I<0, Pseudo, + (outs), (ins i64mem:$dst, RFP80:$src), + "##FP80_TO_INT64_IN_MEM PSEUDO!", + [(X86fp_to_i64mem RFP80:$src, addr:$dst)]>; +} + +let isTerminator = 1 in + let Defs = [FP0, FP1, FP2, FP3, FP4, FP5, FP6] in + def FP_REG_KILL : I<0, Pseudo, (outs), (ins), "##FP_REG_KILL", []>; + +// All FP Stack operations are represented with four instructions here. The +// first three instructions, generated by the instruction selector, use "RFP32" +// "RFP64" or "RFP80" registers: traditional register files to reference 32-bit, +// 64-bit or 80-bit floating point values. These sizes apply to the values, +// not the registers, which are always 80 bits; RFP32, RFP64 and RFP80 can be +// copied to each other without losing information. These instructions are all +// pseudo instructions and use the "_Fp" suffix. +// In some cases there are additional variants with a mixture of different +// register sizes. +// The second instruction is defined with FPI, which is the actual instruction +// emitted by the assembler. These use "RST" registers, although frequently +// the actual register(s) used are implicit. These are always 80 bits. +// The FP stackifier pass converts one to the other after register allocation +// occurs. +// +// Note that the FpI instruction should have instruction selection info (e.g. +// a pattern) and the FPI instruction should have emission info (e.g. opcode +// encoding and asm printing info). + +// Pseudo Instructions for FP stack return values. +def FpGET_ST0_32 : FpI_<(outs RFP32:$dst), (ins), SpecialFP, []>; // FPR = ST(0) +def FpGET_ST0_64 : FpI_<(outs RFP64:$dst), (ins), SpecialFP, []>; // FPR = ST(0) +def FpGET_ST0_80 : FpI_<(outs RFP80:$dst), (ins), SpecialFP, []>; // FPR = ST(0) + +// FpGET_ST1* should only be issued *after* an FpGET_ST0* has been issued when +// there are two values live out on the stack from a call or inlineasm. This +// magic is handled by the stackifier. It is not valid to emit FpGET_ST1* and +// then FpGET_ST0*. In addition, it is invalid for any FP-using operations to +// occur between them. +def FpGET_ST1_32 : FpI_<(outs RFP32:$dst), (ins), SpecialFP, []>; // FPR = ST(1) +def FpGET_ST1_64 : FpI_<(outs RFP64:$dst), (ins), SpecialFP, []>; // FPR = ST(1) +def FpGET_ST1_80 : FpI_<(outs RFP80:$dst), (ins), SpecialFP, []>; // FPR = ST(1) + +let Defs = [ST0] in { +def FpSET_ST0_32 : FpI_<(outs), (ins RFP32:$src), SpecialFP, []>; // ST(0) = FPR +def FpSET_ST0_64 : FpI_<(outs), (ins RFP64:$src), SpecialFP, []>; // ST(0) = FPR +def FpSET_ST0_80 : FpI_<(outs), (ins RFP80:$src), SpecialFP, []>; // ST(0) = FPR +} + +let Defs = [ST1] in { +def FpSET_ST1_32 : FpI_<(outs), (ins RFP32:$src), SpecialFP, []>; // ST(1) = FPR +def FpSET_ST1_64 : FpI_<(outs), (ins RFP64:$src), SpecialFP, []>; // ST(1) = FPR +def FpSET_ST1_80 : FpI_<(outs), (ins RFP80:$src), SpecialFP, []>; // ST(1) = FPR +} + +// FpIf32, FpIf64 - Floating Point Psuedo Instruction template. +// f32 instructions can use SSE1 and are predicated on FPStackf32 == !SSE1. +// f64 instructions can use SSE2 and are predicated on FPStackf64 == !SSE2. +// f80 instructions cannot use SSE and use neither of these. +class FpIf32 pattern> : + FpI_, Requires<[FPStackf32]>; +class FpIf64 pattern> : + FpI_, Requires<[FPStackf64]>; + +// Register copies. Just copies, the shortening ones do not truncate. +let neverHasSideEffects = 1 in { + def MOV_Fp3232 : FpIf32<(outs RFP32:$dst), (ins RFP32:$src), SpecialFP, []>; + def MOV_Fp3264 : FpIf32<(outs RFP64:$dst), (ins RFP32:$src), SpecialFP, []>; + def MOV_Fp6432 : FpIf32<(outs RFP32:$dst), (ins RFP64:$src), SpecialFP, []>; + def MOV_Fp6464 : FpIf64<(outs RFP64:$dst), (ins RFP64:$src), SpecialFP, []>; + def MOV_Fp8032 : FpIf32<(outs RFP32:$dst), (ins RFP80:$src), SpecialFP, []>; + def MOV_Fp3280 : FpIf32<(outs RFP80:$dst), (ins RFP32:$src), SpecialFP, []>; + def MOV_Fp8064 : FpIf64<(outs RFP64:$dst), (ins RFP80:$src), SpecialFP, []>; + def MOV_Fp6480 : FpIf64<(outs RFP80:$dst), (ins RFP64:$src), SpecialFP, []>; + def MOV_Fp8080 : FpI_ <(outs RFP80:$dst), (ins RFP80:$src), SpecialFP, []>; +} + +// Factoring for arithmetic. +multiclass FPBinary_rr { +// Register op register -> register +// These are separated out because they have no reversed form. +def _Fp32 : FpIf32<(outs RFP32:$dst), (ins RFP32:$src1, RFP32:$src2), TwoArgFP, + [(set RFP32:$dst, (OpNode RFP32:$src1, RFP32:$src2))]>; +def _Fp64 : FpIf64<(outs RFP64:$dst), (ins RFP64:$src1, RFP64:$src2), TwoArgFP, + [(set RFP64:$dst, (OpNode RFP64:$src1, RFP64:$src2))]>; +def _Fp80 : FpI_<(outs RFP80:$dst), (ins RFP80:$src1, RFP80:$src2), TwoArgFP, + [(set RFP80:$dst, (OpNode RFP80:$src1, RFP80:$src2))]>; +} +// The FopST0 series are not included here because of the irregularities +// in where the 'r' goes in assembly output. +// These instructions cannot address 80-bit memory. +multiclass FPBinary { +// ST(0) = ST(0) + [mem] +def _Fp32m : FpIf32<(outs RFP32:$dst), (ins RFP32:$src1, f32mem:$src2), OneArgFPRW, + [(set RFP32:$dst, + (OpNode RFP32:$src1, (loadf32 addr:$src2)))]>; +def _Fp64m : FpIf64<(outs RFP64:$dst), (ins RFP64:$src1, f64mem:$src2), OneArgFPRW, + [(set RFP64:$dst, + (OpNode RFP64:$src1, (loadf64 addr:$src2)))]>; +def _Fp64m32: FpIf64<(outs RFP64:$dst), (ins RFP64:$src1, f32mem:$src2), OneArgFPRW, + [(set RFP64:$dst, + (OpNode RFP64:$src1, (f64 (extloadf32 addr:$src2))))]>; +def _Fp80m32: FpI_<(outs RFP80:$dst), (ins RFP80:$src1, f32mem:$src2), OneArgFPRW, + [(set RFP80:$dst, + (OpNode RFP80:$src1, (f80 (extloadf32 addr:$src2))))]>; +def _Fp80m64: FpI_<(outs RFP80:$dst), (ins RFP80:$src1, f64mem:$src2), OneArgFPRW, + [(set RFP80:$dst, + (OpNode RFP80:$src1, (f80 (extloadf64 addr:$src2))))]>; +def _F32m : FPI<0xD8, fp, (outs), (ins f32mem:$src), + !strconcat("f", !strconcat(asmstring, "{s}\t$src"))> { let mayLoad = 1; } +def _F64m : FPI<0xDC, fp, (outs), (ins f64mem:$src), + !strconcat("f", !strconcat(asmstring, "{l}\t$src"))> { let mayLoad = 1; } +// ST(0) = ST(0) + [memint] +def _FpI16m32 : FpIf32<(outs RFP32:$dst), (ins RFP32:$src1, i16mem:$src2), OneArgFPRW, + [(set RFP32:$dst, (OpNode RFP32:$src1, + (X86fild addr:$src2, i16)))]>; +def _FpI32m32 : FpIf32<(outs RFP32:$dst), (ins RFP32:$src1, i32mem:$src2), OneArgFPRW, + [(set RFP32:$dst, (OpNode RFP32:$src1, + (X86fild addr:$src2, i32)))]>; +def _FpI16m64 : FpIf64<(outs RFP64:$dst), (ins RFP64:$src1, i16mem:$src2), OneArgFPRW, + [(set RFP64:$dst, (OpNode RFP64:$src1, + (X86fild addr:$src2, i16)))]>; +def _FpI32m64 : FpIf64<(outs RFP64:$dst), (ins RFP64:$src1, i32mem:$src2), OneArgFPRW, + [(set RFP64:$dst, (OpNode RFP64:$src1, + (X86fild addr:$src2, i32)))]>; +def _FpI16m80 : FpI_<(outs RFP80:$dst), (ins RFP80:$src1, i16mem:$src2), OneArgFPRW, + [(set RFP80:$dst, (OpNode RFP80:$src1, + (X86fild addr:$src2, i16)))]>; +def _FpI32m80 : FpI_<(outs RFP80:$dst), (ins RFP80:$src1, i32mem:$src2), OneArgFPRW, + [(set RFP80:$dst, (OpNode RFP80:$src1, + (X86fild addr:$src2, i32)))]>; +def _FI16m : FPI<0xDE, fp, (outs), (ins i16mem:$src), + !strconcat("fi", !strconcat(asmstring, "{s}\t$src"))> { let mayLoad = 1; } +def _FI32m : FPI<0xDA, fp, (outs), (ins i32mem:$src), + !strconcat("fi", !strconcat(asmstring, "{l}\t$src"))> { let mayLoad = 1; } +} + +defm ADD : FPBinary_rr; +defm SUB : FPBinary_rr; +defm MUL : FPBinary_rr; +defm DIV : FPBinary_rr; +defm ADD : FPBinary; +defm SUB : FPBinary; +defm SUBR: FPBinary; +defm MUL : FPBinary; +defm DIV : FPBinary; +defm DIVR: FPBinary; + +class FPST0rInst o, string asm> + : FPI, D8; +class FPrST0Inst o, string asm> + : FPI, DC; +class FPrST0PInst o, string asm> + : FPI, DE; + +// NOTE: GAS and apparently all other AT&T style assemblers have a broken notion +// of some of the 'reverse' forms of the fsub and fdiv instructions. As such, +// we have to put some 'r's in and take them out of weird places. +def ADD_FST0r : FPST0rInst <0xC0, "fadd\t$op">; +def ADD_FrST0 : FPrST0Inst <0xC0, "fadd\t{%st(0), $op|$op, %ST(0)}">; +def ADD_FPrST0 : FPrST0PInst<0xC0, "faddp\t$op">; +def SUBR_FST0r : FPST0rInst <0xE8, "fsubr\t$op">; +def SUB_FrST0 : FPrST0Inst <0xE8, "fsub{r}\t{%st(0), $op|$op, %ST(0)}">; +def SUB_FPrST0 : FPrST0PInst<0xE8, "fsub{r}p\t$op">; +def SUB_FST0r : FPST0rInst <0xE0, "fsub\t$op">; +def SUBR_FrST0 : FPrST0Inst <0xE0, "fsub{|r}\t{%st(0), $op|$op, %ST(0)}">; +def SUBR_FPrST0 : FPrST0PInst<0xE0, "fsub{|r}p\t$op">; +def MUL_FST0r : FPST0rInst <0xC8, "fmul\t$op">; +def MUL_FrST0 : FPrST0Inst <0xC8, "fmul\t{%st(0), $op|$op, %ST(0)}">; +def MUL_FPrST0 : FPrST0PInst<0xC8, "fmulp\t$op">; +def DIVR_FST0r : FPST0rInst <0xF8, "fdivr\t$op">; +def DIV_FrST0 : FPrST0Inst <0xF8, "fdiv{r}\t{%st(0), $op|$op, %ST(0)}">; +def DIV_FPrST0 : FPrST0PInst<0xF8, "fdiv{r}p\t$op">; +def DIV_FST0r : FPST0rInst <0xF0, "fdiv\t$op">; +def DIVR_FrST0 : FPrST0Inst <0xF0, "fdiv{|r}\t{%st(0), $op|$op, %ST(0)}">; +def DIVR_FPrST0 : FPrST0PInst<0xF0, "fdiv{|r}p\t$op">; + +// Unary operations. +multiclass FPUnary opcode, string asmstring> { +def _Fp32 : FpIf32<(outs RFP32:$dst), (ins RFP32:$src), OneArgFPRW, + [(set RFP32:$dst, (OpNode RFP32:$src))]>; +def _Fp64 : FpIf64<(outs RFP64:$dst), (ins RFP64:$src), OneArgFPRW, + [(set RFP64:$dst, (OpNode RFP64:$src))]>; +def _Fp80 : FpI_<(outs RFP80:$dst), (ins RFP80:$src), OneArgFPRW, + [(set RFP80:$dst, (OpNode RFP80:$src))]>; +def _F : FPI, D9; +} + +defm CHS : FPUnary; +defm ABS : FPUnary; +defm SQRT: FPUnary; +defm SIN : FPUnary; +defm COS : FPUnary; + +let neverHasSideEffects = 1 in { +def TST_Fp32 : FpIf32<(outs), (ins RFP32:$src), OneArgFP, []>; +def TST_Fp64 : FpIf64<(outs), (ins RFP64:$src), OneArgFP, []>; +def TST_Fp80 : FpI_<(outs), (ins RFP80:$src), OneArgFP, []>; +} +def TST_F : FPI<0xE4, RawFrm, (outs), (ins), "ftst">, D9; + +// Versions of FP instructions that take a single memory operand. Added for the +// disassembler; remove as they are included with patterns elsewhere. +def FCOM32m : FPI<0xD8, MRM2m, (outs), (ins f32mem:$src), "fcom\t$src">; +def FCOMP32m : FPI<0xD8, MRM3m, (outs), (ins f32mem:$src), "fcomp\t$src">; + +def FLDENVm : FPI<0xD9, MRM4m, (outs), (ins f32mem:$src), "fldenv\t$src">; +def FSTENVm : FPI<0xD9, MRM6m, (outs f32mem:$dst), (ins), "fstenv\t$dst">; + +def FICOM32m : FPI<0xDA, MRM2m, (outs), (ins i32mem:$src), "ficom{l}\t$src">; +def FICOMP32m: FPI<0xDA, MRM3m, (outs), (ins i32mem:$src), "ficomp{l}\t$src">; + +def FCOM64m : FPI<0xDC, MRM2m, (outs), (ins f64mem:$src), "fcom\t$src">; +def FCOMP64m : FPI<0xDC, MRM3m, (outs), (ins f64mem:$src), "fcomp\t$src">; + +def FISTTP32m: FPI<0xDD, MRM1m, (outs i32mem:$dst), (ins), "fisttp{l}\t$dst">; +def FRSTORm : FPI<0xDD, MRM4m, (outs f32mem:$dst), (ins), "frstor\t$dst">; +def FSAVEm : FPI<0xDD, MRM6m, (outs f32mem:$dst), (ins), "fsave\t$dst">; +def FSTSWm : FPI<0xDD, MRM7m, (outs f32mem:$dst), (ins), "fstsw\t$dst">; + +def FICOM16m : FPI<0xDE, MRM2m, (outs), (ins i16mem:$src), "ficom{w}\t$src">; +def FICOMP16m: FPI<0xDE, MRM3m, (outs), (ins i16mem:$src), "ficomp{w}\t$src">; + +def FBLDm : FPI<0xDF, MRM4m, (outs), (ins f32mem:$src), "fbld\t$src">; +def FBSTPm : FPI<0xDF, MRM6m, (outs f32mem:$dst), (ins), "fbstp\t$dst">; + +// Floating point cmovs. +multiclass FPCMov { + def _Fp32 : FpIf32<(outs RFP32:$dst), (ins RFP32:$src1, RFP32:$src2), + CondMovFP, + [(set RFP32:$dst, (X86cmov RFP32:$src1, RFP32:$src2, + cc, EFLAGS))]>; + def _Fp64 : FpIf64<(outs RFP64:$dst), (ins RFP64:$src1, RFP64:$src2), + CondMovFP, + [(set RFP64:$dst, (X86cmov RFP64:$src1, RFP64:$src2, + cc, EFLAGS))]>; + def _Fp80 : FpI_<(outs RFP80:$dst), (ins RFP80:$src1, RFP80:$src2), + CondMovFP, + [(set RFP80:$dst, (X86cmov RFP80:$src1, RFP80:$src2, + cc, EFLAGS))]>; +} +let Uses = [EFLAGS], isTwoAddress = 1 in { +defm CMOVB : FPCMov; +defm CMOVBE : FPCMov; +defm CMOVE : FPCMov; +defm CMOVP : FPCMov; +defm CMOVNB : FPCMov; +defm CMOVNBE: FPCMov; +defm CMOVNE : FPCMov; +defm CMOVNP : FPCMov; +} + +// These are not factored because there's no clean way to pass DA/DB. +def CMOVB_F : FPI<0xC0, AddRegFrm, (outs RST:$op), (ins), + "fcmovb\t{$op, %st(0)|%ST(0), $op}">, DA; +def CMOVBE_F : FPI<0xD0, AddRegFrm, (outs RST:$op), (ins), + "fcmovbe\t{$op, %st(0)|%ST(0), $op}">, DA; +def CMOVE_F : FPI<0xC8, AddRegFrm, (outs RST:$op), (ins), + "fcmove\t{$op, %st(0)|%ST(0), $op}">, DA; +def CMOVP_F : FPI<0xD8, AddRegFrm, (outs RST:$op), (ins), + "fcmovu\t {$op, %st(0)|%ST(0), $op}">, DA; +def CMOVNB_F : FPI<0xC0, AddRegFrm, (outs RST:$op), (ins), + "fcmovnb\t{$op, %st(0)|%ST(0), $op}">, DB; +def CMOVNBE_F: FPI<0xD0, AddRegFrm, (outs RST:$op), (ins), + "fcmovnbe\t{$op, %st(0)|%ST(0), $op}">, DB; +def CMOVNE_F : FPI<0xC8, AddRegFrm, (outs RST:$op), (ins), + "fcmovne\t{$op, %st(0)|%ST(0), $op}">, DB; +def CMOVNP_F : FPI<0xD8, AddRegFrm, (outs RST:$op), (ins), + "fcmovnu\t{$op, %st(0)|%ST(0), $op}">, DB; + +// Floating point loads & stores. +let canFoldAsLoad = 1 in { +def LD_Fp32m : FpIf32<(outs RFP32:$dst), (ins f32mem:$src), ZeroArgFP, + [(set RFP32:$dst, (loadf32 addr:$src))]>; +let isReMaterializable = 1, mayHaveSideEffects = 1 in + def LD_Fp64m : FpIf64<(outs RFP64:$dst), (ins f64mem:$src), ZeroArgFP, + [(set RFP64:$dst, (loadf64 addr:$src))]>; +def LD_Fp80m : FpI_<(outs RFP80:$dst), (ins f80mem:$src), ZeroArgFP, + [(set RFP80:$dst, (loadf80 addr:$src))]>; +} +def LD_Fp32m64 : FpIf64<(outs RFP64:$dst), (ins f32mem:$src), ZeroArgFP, + [(set RFP64:$dst, (f64 (extloadf32 addr:$src)))]>; +def LD_Fp64m80 : FpI_<(outs RFP80:$dst), (ins f64mem:$src), ZeroArgFP, + [(set RFP80:$dst, (f80 (extloadf64 addr:$src)))]>; +def LD_Fp32m80 : FpI_<(outs RFP80:$dst), (ins f32mem:$src), ZeroArgFP, + [(set RFP80:$dst, (f80 (extloadf32 addr:$src)))]>; +def ILD_Fp16m32: FpIf32<(outs RFP32:$dst), (ins i16mem:$src), ZeroArgFP, + [(set RFP32:$dst, (X86fild addr:$src, i16))]>; +def ILD_Fp32m32: FpIf32<(outs RFP32:$dst), (ins i32mem:$src), ZeroArgFP, + [(set RFP32:$dst, (X86fild addr:$src, i32))]>; +def ILD_Fp64m32: FpIf32<(outs RFP32:$dst), (ins i64mem:$src), ZeroArgFP, + [(set RFP32:$dst, (X86fild addr:$src, i64))]>; +def ILD_Fp16m64: FpIf64<(outs RFP64:$dst), (ins i16mem:$src), ZeroArgFP, + [(set RFP64:$dst, (X86fild addr:$src, i16))]>; +def ILD_Fp32m64: FpIf64<(outs RFP64:$dst), (ins i32mem:$src), ZeroArgFP, + [(set RFP64:$dst, (X86fild addr:$src, i32))]>; +def ILD_Fp64m64: FpIf64<(outs RFP64:$dst), (ins i64mem:$src), ZeroArgFP, + [(set RFP64:$dst, (X86fild addr:$src, i64))]>; +def ILD_Fp16m80: FpI_<(outs RFP80:$dst), (ins i16mem:$src), ZeroArgFP, + [(set RFP80:$dst, (X86fild addr:$src, i16))]>; +def ILD_Fp32m80: FpI_<(outs RFP80:$dst), (ins i32mem:$src), ZeroArgFP, + [(set RFP80:$dst, (X86fild addr:$src, i32))]>; +def ILD_Fp64m80: FpI_<(outs RFP80:$dst), (ins i64mem:$src), ZeroArgFP, + [(set RFP80:$dst, (X86fild addr:$src, i64))]>; + +def ST_Fp32m : FpIf32<(outs), (ins f32mem:$op, RFP32:$src), OneArgFP, + [(store RFP32:$src, addr:$op)]>; +def ST_Fp64m32 : FpIf64<(outs), (ins f32mem:$op, RFP64:$src), OneArgFP, + [(truncstoref32 RFP64:$src, addr:$op)]>; +def ST_Fp64m : FpIf64<(outs), (ins f64mem:$op, RFP64:$src), OneArgFP, + [(store RFP64:$src, addr:$op)]>; +def ST_Fp80m32 : FpI_<(outs), (ins f32mem:$op, RFP80:$src), OneArgFP, + [(truncstoref32 RFP80:$src, addr:$op)]>; +def ST_Fp80m64 : FpI_<(outs), (ins f64mem:$op, RFP80:$src), OneArgFP, + [(truncstoref64 RFP80:$src, addr:$op)]>; +// FST does not support 80-bit memory target; FSTP must be used. + +let mayStore = 1, neverHasSideEffects = 1 in { +def ST_FpP32m : FpIf32<(outs), (ins f32mem:$op, RFP32:$src), OneArgFP, []>; +def ST_FpP64m32 : FpIf64<(outs), (ins f32mem:$op, RFP64:$src), OneArgFP, []>; +def ST_FpP64m : FpIf64<(outs), (ins f64mem:$op, RFP64:$src), OneArgFP, []>; +def ST_FpP80m32 : FpI_<(outs), (ins f32mem:$op, RFP80:$src), OneArgFP, []>; +def ST_FpP80m64 : FpI_<(outs), (ins f64mem:$op, RFP80:$src), OneArgFP, []>; +} +def ST_FpP80m : FpI_<(outs), (ins f80mem:$op, RFP80:$src), OneArgFP, + [(store RFP80:$src, addr:$op)]>; +let mayStore = 1, neverHasSideEffects = 1 in { +def IST_Fp16m32 : FpIf32<(outs), (ins i16mem:$op, RFP32:$src), OneArgFP, []>; +def IST_Fp32m32 : FpIf32<(outs), (ins i32mem:$op, RFP32:$src), OneArgFP, []>; +def IST_Fp64m32 : FpIf32<(outs), (ins i64mem:$op, RFP32:$src), OneArgFP, []>; +def IST_Fp16m64 : FpIf64<(outs), (ins i16mem:$op, RFP64:$src), OneArgFP, []>; +def IST_Fp32m64 : FpIf64<(outs), (ins i32mem:$op, RFP64:$src), OneArgFP, []>; +def IST_Fp64m64 : FpIf64<(outs), (ins i64mem:$op, RFP64:$src), OneArgFP, []>; +def IST_Fp16m80 : FpI_<(outs), (ins i16mem:$op, RFP80:$src), OneArgFP, []>; +def IST_Fp32m80 : FpI_<(outs), (ins i32mem:$op, RFP80:$src), OneArgFP, []>; +def IST_Fp64m80 : FpI_<(outs), (ins i64mem:$op, RFP80:$src), OneArgFP, []>; +} + +let mayLoad = 1 in { +def LD_F32m : FPI<0xD9, MRM0m, (outs), (ins f32mem:$src), "fld{s}\t$src">; +def LD_F64m : FPI<0xDD, MRM0m, (outs), (ins f64mem:$src), "fld{l}\t$src">; +def LD_F80m : FPI<0xDB, MRM5m, (outs), (ins f80mem:$src), "fld{t}\t$src">; +def ILD_F16m : FPI<0xDF, MRM0m, (outs), (ins i16mem:$src), "fild{s}\t$src">; +def ILD_F32m : FPI<0xDB, MRM0m, (outs), (ins i32mem:$src), "fild{l}\t$src">; +def ILD_F64m : FPI<0xDF, MRM5m, (outs), (ins i64mem:$src), "fild{ll}\t$src">; +} +let mayStore = 1 in { +def ST_F32m : FPI<0xD9, MRM2m, (outs), (ins f32mem:$dst), "fst{s}\t$dst">; +def ST_F64m : FPI<0xDD, MRM2m, (outs), (ins f64mem:$dst), "fst{l}\t$dst">; +def ST_FP32m : FPI<0xD9, MRM3m, (outs), (ins f32mem:$dst), "fstp{s}\t$dst">; +def ST_FP64m : FPI<0xDD, MRM3m, (outs), (ins f64mem:$dst), "fstp{l}\t$dst">; +def ST_FP80m : FPI<0xDB, MRM7m, (outs), (ins f80mem:$dst), "fstp{t}\t$dst">; +def IST_F16m : FPI<0xDF, MRM2m, (outs), (ins i16mem:$dst), "fist{s}\t$dst">; +def IST_F32m : FPI<0xDB, MRM2m, (outs), (ins i32mem:$dst), "fist{l}\t$dst">; +def IST_FP16m : FPI<0xDF, MRM3m, (outs), (ins i16mem:$dst), "fistp{s}\t$dst">; +def IST_FP32m : FPI<0xDB, MRM3m, (outs), (ins i32mem:$dst), "fistp{l}\t$dst">; +def IST_FP64m : FPI<0xDF, MRM7m, (outs), (ins i64mem:$dst), "fistp{ll}\t$dst">; +} + +// FISTTP requires SSE3 even though it's a FPStack op. +def ISTT_Fp16m32 : FpI_<(outs), (ins i16mem:$op, RFP32:$src), OneArgFP, + [(X86fp_to_i16mem RFP32:$src, addr:$op)]>, + Requires<[HasSSE3]>; +def ISTT_Fp32m32 : FpI_<(outs), (ins i32mem:$op, RFP32:$src), OneArgFP, + [(X86fp_to_i32mem RFP32:$src, addr:$op)]>, + Requires<[HasSSE3]>; +def ISTT_Fp64m32 : FpI_<(outs), (ins i64mem:$op, RFP32:$src), OneArgFP, + [(X86fp_to_i64mem RFP32:$src, addr:$op)]>, + Requires<[HasSSE3]>; +def ISTT_Fp16m64 : FpI_<(outs), (ins i16mem:$op, RFP64:$src), OneArgFP, + [(X86fp_to_i16mem RFP64:$src, addr:$op)]>, + Requires<[HasSSE3]>; +def ISTT_Fp32m64 : FpI_<(outs), (ins i32mem:$op, RFP64:$src), OneArgFP, + [(X86fp_to_i32mem RFP64:$src, addr:$op)]>, + Requires<[HasSSE3]>; +def ISTT_Fp64m64 : FpI_<(outs), (ins i64mem:$op, RFP64:$src), OneArgFP, + [(X86fp_to_i64mem RFP64:$src, addr:$op)]>, + Requires<[HasSSE3]>; +def ISTT_Fp16m80 : FpI_<(outs), (ins i16mem:$op, RFP80:$src), OneArgFP, + [(X86fp_to_i16mem RFP80:$src, addr:$op)]>, + Requires<[HasSSE3]>; +def ISTT_Fp32m80 : FpI_<(outs), (ins i32mem:$op, RFP80:$src), OneArgFP, + [(X86fp_to_i32mem RFP80:$src, addr:$op)]>, + Requires<[HasSSE3]>; +def ISTT_Fp64m80 : FpI_<(outs), (ins i64mem:$op, RFP80:$src), OneArgFP, + [(X86fp_to_i64mem RFP80:$src, addr:$op)]>, + Requires<[HasSSE3]>; + +let mayStore = 1 in { +def ISTT_FP16m : FPI<0xDF, MRM1m, (outs), (ins i16mem:$dst), "fisttp{s}\t$dst">; +def ISTT_FP32m : FPI<0xDB, MRM1m, (outs), (ins i32mem:$dst), "fisttp{l}\t$dst">; +def ISTT_FP64m : FPI<0xDD, MRM1m, (outs), (ins i64mem:$dst), "fisttp{ll}\t$dst">; +} + +// FP Stack manipulation instructions. +def LD_Frr : FPI<0xC0, AddRegFrm, (outs), (ins RST:$op), "fld\t$op">, D9; +def ST_Frr : FPI<0xD0, AddRegFrm, (outs), (ins RST:$op), "fst\t$op">, DD; +def ST_FPrr : FPI<0xD8, AddRegFrm, (outs), (ins RST:$op), "fstp\t$op">, DD; +def XCH_F : FPI<0xC8, AddRegFrm, (outs), (ins RST:$op), "fxch\t$op">, D9; + +// Floating point constant loads. +let isReMaterializable = 1 in { +def LD_Fp032 : FpIf32<(outs RFP32:$dst), (ins), ZeroArgFP, + [(set RFP32:$dst, fpimm0)]>; +def LD_Fp132 : FpIf32<(outs RFP32:$dst), (ins), ZeroArgFP, + [(set RFP32:$dst, fpimm1)]>; +def LD_Fp064 : FpIf64<(outs RFP64:$dst), (ins), ZeroArgFP, + [(set RFP64:$dst, fpimm0)]>; +def LD_Fp164 : FpIf64<(outs RFP64:$dst), (ins), ZeroArgFP, + [(set RFP64:$dst, fpimm1)]>; +def LD_Fp080 : FpI_<(outs RFP80:$dst), (ins), ZeroArgFP, + [(set RFP80:$dst, fpimm0)]>; +def LD_Fp180 : FpI_<(outs RFP80:$dst), (ins), ZeroArgFP, + [(set RFP80:$dst, fpimm1)]>; +} + +def LD_F0 : FPI<0xEE, RawFrm, (outs), (ins), "fldz">, D9; +def LD_F1 : FPI<0xE8, RawFrm, (outs), (ins), "fld1">, D9; + + +// Floating point compares. +let Defs = [EFLAGS] in { +def UCOM_Fpr32 : FpIf32<(outs), (ins RFP32:$lhs, RFP32:$rhs), CompareFP, + []>; // FPSW = cmp ST(0) with ST(i) +def UCOM_Fpr64 : FpIf64<(outs), (ins RFP64:$lhs, RFP64:$rhs), CompareFP, + []>; // FPSW = cmp ST(0) with ST(i) +def UCOM_Fpr80 : FpI_ <(outs), (ins RFP80:$lhs, RFP80:$rhs), CompareFP, + []>; // FPSW = cmp ST(0) with ST(i) + +def UCOM_FpIr32: FpIf32<(outs), (ins RFP32:$lhs, RFP32:$rhs), CompareFP, + [(X86cmp RFP32:$lhs, RFP32:$rhs), + (implicit EFLAGS)]>; // CC = ST(0) cmp ST(i) +def UCOM_FpIr64: FpIf64<(outs), (ins RFP64:$lhs, RFP64:$rhs), CompareFP, + [(X86cmp RFP64:$lhs, RFP64:$rhs), + (implicit EFLAGS)]>; // CC = ST(0) cmp ST(i) +def UCOM_FpIr80: FpI_<(outs), (ins RFP80:$lhs, RFP80:$rhs), CompareFP, + [(X86cmp RFP80:$lhs, RFP80:$rhs), + (implicit EFLAGS)]>; // CC = ST(0) cmp ST(i) +} + +let Defs = [EFLAGS], Uses = [ST0] in { +def UCOM_Fr : FPI<0xE0, AddRegFrm, // FPSW = cmp ST(0) with ST(i) + (outs), (ins RST:$reg), + "fucom\t$reg">, DD; +def UCOM_FPr : FPI<0xE8, AddRegFrm, // FPSW = cmp ST(0) with ST(i), pop + (outs), (ins RST:$reg), + "fucomp\t$reg">, DD; +def UCOM_FPPr : FPI<0xE9, RawFrm, // cmp ST(0) with ST(1), pop, pop + (outs), (ins), + "fucompp">, DA; + +def UCOM_FIr : FPI<0xE8, AddRegFrm, // CC = cmp ST(0) with ST(i) + (outs), (ins RST:$reg), + "fucomi\t{$reg, %st(0)|%ST(0), $reg}">, DB; +def UCOM_FIPr : FPI<0xE8, AddRegFrm, // CC = cmp ST(0) with ST(i), pop + (outs), (ins RST:$reg), + "fucomip\t{$reg, %st(0)|%ST(0), $reg}">, DF; +} + +// Floating point flag ops. +let Defs = [AX] in +def FNSTSW8r : I<0xE0, RawFrm, // AX = fp flags + (outs), (ins), "fnstsw", []>, DF; + +def FNSTCW16m : I<0xD9, MRM7m, // [mem16] = X87 control world + (outs), (ins i16mem:$dst), "fnstcw\t$dst", + [(X86fp_cwd_get16 addr:$dst)]>; + +let mayLoad = 1 in +def FLDCW16m : I<0xD9, MRM5m, // X87 control world = [mem16] + (outs), (ins i16mem:$dst), "fldcw\t$dst", []>; + +//===----------------------------------------------------------------------===// +// Non-Instruction Patterns +//===----------------------------------------------------------------------===// + +// Required for RET of f32 / f64 / f80 values. +def : Pat<(X86fld addr:$src, f32), (LD_Fp32m addr:$src)>; +def : Pat<(X86fld addr:$src, f64), (LD_Fp64m addr:$src)>; +def : Pat<(X86fld addr:$src, f80), (LD_Fp80m addr:$src)>; + +// Required for CALL which return f32 / f64 / f80 values. +def : Pat<(X86fst RFP32:$src, addr:$op, f32), (ST_Fp32m addr:$op, RFP32:$src)>; +def : Pat<(X86fst RFP64:$src, addr:$op, f32), (ST_Fp64m32 addr:$op, RFP64:$src)>; +def : Pat<(X86fst RFP64:$src, addr:$op, f64), (ST_Fp64m addr:$op, RFP64:$src)>; +def : Pat<(X86fst RFP80:$src, addr:$op, f32), (ST_Fp80m32 addr:$op, RFP80:$src)>; +def : Pat<(X86fst RFP80:$src, addr:$op, f64), (ST_Fp80m64 addr:$op, RFP80:$src)>; +def : Pat<(X86fst RFP80:$src, addr:$op, f80), (ST_FpP80m addr:$op, RFP80:$src)>; + +// Floating point constant -0.0 and -1.0 +def : Pat<(f32 fpimmneg0), (CHS_Fp32 (LD_Fp032))>, Requires<[FPStackf32]>; +def : Pat<(f32 fpimmneg1), (CHS_Fp32 (LD_Fp132))>, Requires<[FPStackf32]>; +def : Pat<(f64 fpimmneg0), (CHS_Fp64 (LD_Fp064))>, Requires<[FPStackf64]>; +def : Pat<(f64 fpimmneg1), (CHS_Fp64 (LD_Fp164))>, Requires<[FPStackf64]>; +def : Pat<(f80 fpimmneg0), (CHS_Fp80 (LD_Fp080))>; +def : Pat<(f80 fpimmneg1), (CHS_Fp80 (LD_Fp180))>; + +// Used to conv. i64 to f64 since there isn't a SSE version. +def : Pat<(X86fildflag addr:$src, i64), (ILD_Fp64m64 addr:$src)>; + +// FP extensions map onto simple pseudo-value conversions if they are to/from +// the FP stack. +def : Pat<(f64 (fextend RFP32:$src)), (MOV_Fp3264 RFP32:$src)>, + Requires<[FPStackf32]>; +def : Pat<(f80 (fextend RFP32:$src)), (MOV_Fp3280 RFP32:$src)>, + Requires<[FPStackf32]>; +def : Pat<(f80 (fextend RFP64:$src)), (MOV_Fp6480 RFP64:$src)>, + Requires<[FPStackf64]>; + +// FP truncations map onto simple pseudo-value conversions if they are to/from +// the FP stack. We have validated that only value-preserving truncations make +// it through isel. +def : Pat<(f32 (fround RFP64:$src)), (MOV_Fp6432 RFP64:$src)>, + Requires<[FPStackf32]>; +def : Pat<(f32 (fround RFP80:$src)), (MOV_Fp8032 RFP80:$src)>, + Requires<[FPStackf32]>; +def : Pat<(f64 (fround RFP80:$src)), (MOV_Fp8064 RFP80:$src)>, + Requires<[FPStackf64]>; diff --git a/libclamav/c++/llvm/lib/Target/X86/X86InstrFormats.td b/libclamav/c++/llvm/lib/Target/X86/X86InstrFormats.td new file mode 100644 index 000000000..2f14bb0d9 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/X86/X86InstrFormats.td @@ -0,0 +1,313 @@ +//===- X86InstrFormats.td - X86 Instruction Formats --------*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// X86 Instruction Format Definitions. +// + +// Format specifies the encoding used by the instruction. This is part of the +// ad-hoc solution used to emit machine instruction encodings by our machine +// code emitter. +class Format val> { + bits<6> Value = val; +} + +def Pseudo : Format<0>; def RawFrm : Format<1>; +def AddRegFrm : Format<2>; def MRMDestReg : Format<3>; +def MRMDestMem : Format<4>; def MRMSrcReg : Format<5>; +def MRMSrcMem : Format<6>; +def MRM0r : Format<16>; def MRM1r : Format<17>; def MRM2r : Format<18>; +def MRM3r : Format<19>; def MRM4r : Format<20>; def MRM5r : Format<21>; +def MRM6r : Format<22>; def MRM7r : Format<23>; +def MRM0m : Format<24>; def MRM1m : Format<25>; def MRM2m : Format<26>; +def MRM3m : Format<27>; def MRM4m : Format<28>; def MRM5m : Format<29>; +def MRM6m : Format<30>; def MRM7m : Format<31>; +def MRMInitReg : Format<32>; + + +// ImmType - This specifies the immediate type used by an instruction. This is +// part of the ad-hoc solution used to emit machine instruction encodings by our +// machine code emitter. +class ImmType val> { + bits<3> Value = val; +} +def NoImm : ImmType<0>; +def Imm8 : ImmType<1>; +def Imm16 : ImmType<2>; +def Imm32 : ImmType<3>; +def Imm64 : ImmType<4>; + +// FPFormat - This specifies what form this FP instruction has. This is used by +// the Floating-Point stackifier pass. +class FPFormat val> { + bits<3> Value = val; +} +def NotFP : FPFormat<0>; +def ZeroArgFP : FPFormat<1>; +def OneArgFP : FPFormat<2>; +def OneArgFPRW : FPFormat<3>; +def TwoArgFP : FPFormat<4>; +def CompareFP : FPFormat<5>; +def CondMovFP : FPFormat<6>; +def SpecialFP : FPFormat<7>; + +// Prefix byte classes which are used to indicate to the ad-hoc machine code +// emitter that various prefix bytes are required. +class OpSize { bit hasOpSizePrefix = 1; } +class AdSize { bit hasAdSizePrefix = 1; } +class REX_W { bit hasREX_WPrefix = 1; } +class LOCK { bit hasLockPrefix = 1; } +class SegFS { bits<2> SegOvrBits = 1; } +class SegGS { bits<2> SegOvrBits = 2; } +class TB { bits<4> Prefix = 1; } +class REP { bits<4> Prefix = 2; } +class D8 { bits<4> Prefix = 3; } +class D9 { bits<4> Prefix = 4; } +class DA { bits<4> Prefix = 5; } +class DB { bits<4> Prefix = 6; } +class DC { bits<4> Prefix = 7; } +class DD { bits<4> Prefix = 8; } +class DE { bits<4> Prefix = 9; } +class DF { bits<4> Prefix = 10; } +class XD { bits<4> Prefix = 11; } +class XS { bits<4> Prefix = 12; } +class T8 { bits<4> Prefix = 13; } +class TA { bits<4> Prefix = 14; } +class TF { bits<4> Prefix = 15; } + +class X86Inst opcod, Format f, ImmType i, dag outs, dag ins, + string AsmStr> + : Instruction { + let Namespace = "X86"; + + bits<8> Opcode = opcod; + Format Form = f; + bits<6> FormBits = Form.Value; + ImmType ImmT = i; + bits<3> ImmTypeBits = ImmT.Value; + + dag OutOperandList = outs; + dag InOperandList = ins; + string AsmString = AsmStr; + + // + // Attributes specific to X86 instructions... + // + bit hasOpSizePrefix = 0; // Does this inst have a 0x66 prefix? + bit hasAdSizePrefix = 0; // Does this inst have a 0x67 prefix? + + bits<4> Prefix = 0; // Which prefix byte does this inst have? + bit hasREX_WPrefix = 0; // Does this inst requires the REX.W prefix? + FPFormat FPForm; // What flavor of FP instruction is this? + bits<3> FPFormBits = 0; + bit hasLockPrefix = 0; // Does this inst have a 0xF0 prefix? + bits<2> SegOvrBits = 0; // Segment override prefix. +} + +class I o, Format f, dag outs, dag ins, string asm, list pattern> + : X86Inst { + let Pattern = pattern; + let CodeSize = 3; +} +class Ii8 o, Format f, dag outs, dag ins, string asm, list pattern> + : X86Inst { + let Pattern = pattern; + let CodeSize = 3; +} +class Ii16 o, Format f, dag outs, dag ins, string asm, list pattern> + : X86Inst { + let Pattern = pattern; + let CodeSize = 3; +} +class Ii32 o, Format f, dag outs, dag ins, string asm, list pattern> + : X86Inst { + let Pattern = pattern; + let CodeSize = 3; +} + +// FPStack Instruction Templates: +// FPI - Floating Point Instruction template. +class FPI o, Format F, dag outs, dag ins, string asm> + : I {} + +// FpI_ - Floating Point Psuedo Instruction template. Not Predicated. +class FpI_ pattern> + : X86Inst<0, Pseudo, NoImm, outs, ins, ""> { + let FPForm = fp; let FPFormBits = FPForm.Value; + let Pattern = pattern; +} + +// Templates for instructions that use a 16- or 32-bit segmented address as +// their only operand: lcall (FAR CALL) and ljmp (FAR JMP) +// +// Iseg16 - 16-bit segment selector, 16-bit offset +// Iseg32 - 16-bit segment selector, 32-bit offset + +class Iseg16 o, Format f, dag outs, dag ins, string asm, + list pattern> : X86Inst { + let Pattern = pattern; + let CodeSize = 3; +} + +class Iseg32 o, Format f, dag outs, dag ins, string asm, + list pattern> : X86Inst { + let Pattern = pattern; + let CodeSize = 3; +} + +// SSE1 Instruction Templates: +// +// SSI - SSE1 instructions with XS prefix. +// PSI - SSE1 instructions with TB prefix. +// PSIi8 - SSE1 instructions with ImmT == Imm8 and TB prefix. + +class SSI o, Format F, dag outs, dag ins, string asm, list pattern> + : I, XS, Requires<[HasSSE1]>; +class SSIi8 o, Format F, dag outs, dag ins, string asm, list pattern> + : Ii8, XS, Requires<[HasSSE1]>; +class PSI o, Format F, dag outs, dag ins, string asm, list pattern> + : I, TB, Requires<[HasSSE1]>; +class PSIi8 o, Format F, dag outs, dag ins, string asm, + list pattern> + : Ii8, TB, Requires<[HasSSE1]>; + +// SSE2 Instruction Templates: +// +// SDI - SSE2 instructions with XD prefix. +// SDIi8 - SSE2 instructions with ImmT == Imm8 and XD prefix. +// SSDIi8 - SSE2 instructions with ImmT == Imm8 and XS prefix. +// PDI - SSE2 instructions with TB and OpSize prefixes. +// PDIi8 - SSE2 instructions with ImmT == Imm8 and TB and OpSize prefixes. + +class SDI o, Format F, dag outs, dag ins, string asm, list pattern> + : I, XD, Requires<[HasSSE2]>; +class SDIi8 o, Format F, dag outs, dag ins, string asm, + list pattern> + : Ii8, XD, Requires<[HasSSE2]>; +class SSDIi8 o, Format F, dag outs, dag ins, string asm, + list pattern> + : Ii8, XS, Requires<[HasSSE2]>; +class PDI o, Format F, dag outs, dag ins, string asm, list pattern> + : I, TB, OpSize, Requires<[HasSSE2]>; +class PDIi8 o, Format F, dag outs, dag ins, string asm, + list pattern> + : Ii8, TB, OpSize, Requires<[HasSSE2]>; + +// SSE3 Instruction Templates: +// +// S3I - SSE3 instructions with TB and OpSize prefixes. +// S3SI - SSE3 instructions with XS prefix. +// S3DI - SSE3 instructions with XD prefix. + +class S3SI o, Format F, dag outs, dag ins, string asm, list pattern> + : I, XS, Requires<[HasSSE3]>; +class S3DI o, Format F, dag outs, dag ins, string asm, list pattern> + : I, XD, Requires<[HasSSE3]>; +class S3I o, Format F, dag outs, dag ins, string asm, list pattern> + : I, TB, OpSize, Requires<[HasSSE3]>; + + +// SSSE3 Instruction Templates: +// +// SS38I - SSSE3 instructions with T8 prefix. +// SS3AI - SSSE3 instructions with TA prefix. +// +// Note: SSSE3 instructions have 64-bit and 128-bit versions. The 64-bit version +// uses the MMX registers. We put those instructions here because they better +// fit into the SSSE3 instruction category rather than the MMX category. + +class SS38I o, Format F, dag outs, dag ins, string asm, + list pattern> + : Ii8, T8, Requires<[HasSSSE3]>; +class SS3AI o, Format F, dag outs, dag ins, string asm, + list pattern> + : Ii8, TA, Requires<[HasSSSE3]>; + +// SSE4.1 Instruction Templates: +// +// SS48I - SSE 4.1 instructions with T8 prefix. +// SS41AIi8 - SSE 4.1 instructions with TA prefix and ImmT == Imm8. +// +class SS48I o, Format F, dag outs, dag ins, string asm, + list pattern> + : I, T8, Requires<[HasSSE41]>; +class SS4AIi8 o, Format F, dag outs, dag ins, string asm, + list pattern> + : Ii8, TA, Requires<[HasSSE41]>; + +// SSE4.2 Instruction Templates: +// +// SS428I - SSE 4.2 instructions with T8 prefix. +class SS428I o, Format F, dag outs, dag ins, string asm, + list pattern> + : I, T8, Requires<[HasSSE42]>; + +// SS42FI - SSE 4.2 instructions with TF prefix. +class SS42FI o, Format F, dag outs, dag ins, string asm, + list pattern> + : I, TF, Requires<[HasSSE42]>; + +// SS42AI = SSE 4.2 instructions with TA prefix +class SS42AI o, Format F, dag outs, dag ins, string asm, + list pattern> + : I, TA, Requires<[HasSSE42]>; + +// X86-64 Instruction templates... +// + +class RI o, Format F, dag outs, dag ins, string asm, list pattern> + : I, REX_W; +class RIi8 o, Format F, dag outs, dag ins, string asm, + list pattern> + : Ii8, REX_W; +class RIi32 o, Format F, dag outs, dag ins, string asm, + list pattern> + : Ii32, REX_W; + +class RIi64 o, Format f, dag outs, dag ins, string asm, + list pattern> + : X86Inst, REX_W { + let Pattern = pattern; + let CodeSize = 3; +} + +class RSSI o, Format F, dag outs, dag ins, string asm, + list pattern> + : SSI, REX_W; +class RSDI o, Format F, dag outs, dag ins, string asm, + list pattern> + : SDI, REX_W; +class RPDI o, Format F, dag outs, dag ins, string asm, + list pattern> + : PDI, REX_W; + +// MMX Instruction templates +// + +// MMXI - MMX instructions with TB prefix. +// MMXI64 - MMX instructions with TB prefix valid only in 64 bit mode. +// MMX2I - MMX / SSE2 instructions with TB and OpSize prefixes. +// MMXIi8 - MMX instructions with ImmT == Imm8 and TB prefix. +// MMXIi8 - MMX instructions with ImmT == Imm8 and TB prefix. +// MMXID - MMX instructions with XD prefix. +// MMXIS - MMX instructions with XS prefix. +class MMXI o, Format F, dag outs, dag ins, string asm, list pattern> + : I, TB, Requires<[HasMMX]>; +class MMXI64 o, Format F, dag outs, dag ins, string asm, list pattern> + : I, TB, Requires<[HasMMX,In64BitMode]>; +class MMXRI o, Format F, dag outs, dag ins, string asm, list pattern> + : I, TB, REX_W, Requires<[HasMMX]>; +class MMX2I o, Format F, dag outs, dag ins, string asm, list pattern> + : I, TB, OpSize, Requires<[HasMMX]>; +class MMXIi8 o, Format F, dag outs, dag ins, string asm, list pattern> + : Ii8, TB, Requires<[HasMMX]>; +class MMXID o, Format F, dag outs, dag ins, string asm, list pattern> + : Ii8, XD, Requires<[HasMMX]>; +class MMXIS o, Format F, dag outs, dag ins, string asm, list pattern> + : Ii8, XS, Requires<[HasMMX]>; diff --git a/libclamav/c++/llvm/lib/Target/X86/X86InstrInfo.cpp b/libclamav/c++/llvm/lib/Target/X86/X86InstrInfo.cpp new file mode 100644 index 000000000..a37013d25 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/X86/X86InstrInfo.cpp @@ -0,0 +1,3380 @@ +//===- X86InstrInfo.cpp - X86 Instruction Information -----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the X86 implementation of the TargetInstrInfo class. +// +//===----------------------------------------------------------------------===// + +#include "X86InstrInfo.h" +#include "X86.h" +#include "X86GenInstrInfo.inc" +#include "X86InstrBuilder.h" +#include "X86MachineFunctionInfo.h" +#include "X86Subtarget.h" +#include "X86TargetMachine.h" +#include "llvm/DerivedTypes.h" +#include "llvm/LLVMContext.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/CodeGen/MachineConstantPool.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/LiveVariables.h" +#include "llvm/CodeGen/PseudoSourceValue.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Target/TargetOptions.h" +#include "llvm/MC/MCAsmInfo.h" + +#include + +using namespace llvm; + +static cl::opt +NoFusing("disable-spill-fusing", + cl::desc("Disable fusing of spill code into instructions")); +static cl::opt +PrintFailedFusing("print-failed-fuse-candidates", + cl::desc("Print instructions that the allocator wants to" + " fuse, but the X86 backend currently can't"), + cl::Hidden); +static cl::opt +ReMatPICStubLoad("remat-pic-stub-load", + cl::desc("Re-materialize load from stub in PIC mode"), + cl::init(false), cl::Hidden); + +X86InstrInfo::X86InstrInfo(X86TargetMachine &tm) + : TargetInstrInfoImpl(X86Insts, array_lengthof(X86Insts)), + TM(tm), RI(tm, *this) { + SmallVector AmbEntries; + static const unsigned OpTbl2Addr[][2] = { + { X86::ADC32ri, X86::ADC32mi }, + { X86::ADC32ri8, X86::ADC32mi8 }, + { X86::ADC32rr, X86::ADC32mr }, + { X86::ADC64ri32, X86::ADC64mi32 }, + { X86::ADC64ri8, X86::ADC64mi8 }, + { X86::ADC64rr, X86::ADC64mr }, + { X86::ADD16ri, X86::ADD16mi }, + { X86::ADD16ri8, X86::ADD16mi8 }, + { X86::ADD16rr, X86::ADD16mr }, + { X86::ADD32ri, X86::ADD32mi }, + { X86::ADD32ri8, X86::ADD32mi8 }, + { X86::ADD32rr, X86::ADD32mr }, + { X86::ADD64ri32, X86::ADD64mi32 }, + { X86::ADD64ri8, X86::ADD64mi8 }, + { X86::ADD64rr, X86::ADD64mr }, + { X86::ADD8ri, X86::ADD8mi }, + { X86::ADD8rr, X86::ADD8mr }, + { X86::AND16ri, X86::AND16mi }, + { X86::AND16ri8, X86::AND16mi8 }, + { X86::AND16rr, X86::AND16mr }, + { X86::AND32ri, X86::AND32mi }, + { X86::AND32ri8, X86::AND32mi8 }, + { X86::AND32rr, X86::AND32mr }, + { X86::AND64ri32, X86::AND64mi32 }, + { X86::AND64ri8, X86::AND64mi8 }, + { X86::AND64rr, X86::AND64mr }, + { X86::AND8ri, X86::AND8mi }, + { X86::AND8rr, X86::AND8mr }, + { X86::DEC16r, X86::DEC16m }, + { X86::DEC32r, X86::DEC32m }, + { X86::DEC64_16r, X86::DEC64_16m }, + { X86::DEC64_32r, X86::DEC64_32m }, + { X86::DEC64r, X86::DEC64m }, + { X86::DEC8r, X86::DEC8m }, + { X86::INC16r, X86::INC16m }, + { X86::INC32r, X86::INC32m }, + { X86::INC64_16r, X86::INC64_16m }, + { X86::INC64_32r, X86::INC64_32m }, + { X86::INC64r, X86::INC64m }, + { X86::INC8r, X86::INC8m }, + { X86::NEG16r, X86::NEG16m }, + { X86::NEG32r, X86::NEG32m }, + { X86::NEG64r, X86::NEG64m }, + { X86::NEG8r, X86::NEG8m }, + { X86::NOT16r, X86::NOT16m }, + { X86::NOT32r, X86::NOT32m }, + { X86::NOT64r, X86::NOT64m }, + { X86::NOT8r, X86::NOT8m }, + { X86::OR16ri, X86::OR16mi }, + { X86::OR16ri8, X86::OR16mi8 }, + { X86::OR16rr, X86::OR16mr }, + { X86::OR32ri, X86::OR32mi }, + { X86::OR32ri8, X86::OR32mi8 }, + { X86::OR32rr, X86::OR32mr }, + { X86::OR64ri32, X86::OR64mi32 }, + { X86::OR64ri8, X86::OR64mi8 }, + { X86::OR64rr, X86::OR64mr }, + { X86::OR8ri, X86::OR8mi }, + { X86::OR8rr, X86::OR8mr }, + { X86::ROL16r1, X86::ROL16m1 }, + { X86::ROL16rCL, X86::ROL16mCL }, + { X86::ROL16ri, X86::ROL16mi }, + { X86::ROL32r1, X86::ROL32m1 }, + { X86::ROL32rCL, X86::ROL32mCL }, + { X86::ROL32ri, X86::ROL32mi }, + { X86::ROL64r1, X86::ROL64m1 }, + { X86::ROL64rCL, X86::ROL64mCL }, + { X86::ROL64ri, X86::ROL64mi }, + { X86::ROL8r1, X86::ROL8m1 }, + { X86::ROL8rCL, X86::ROL8mCL }, + { X86::ROL8ri, X86::ROL8mi }, + { X86::ROR16r1, X86::ROR16m1 }, + { X86::ROR16rCL, X86::ROR16mCL }, + { X86::ROR16ri, X86::ROR16mi }, + { X86::ROR32r1, X86::ROR32m1 }, + { X86::ROR32rCL, X86::ROR32mCL }, + { X86::ROR32ri, X86::ROR32mi }, + { X86::ROR64r1, X86::ROR64m1 }, + { X86::ROR64rCL, X86::ROR64mCL }, + { X86::ROR64ri, X86::ROR64mi }, + { X86::ROR8r1, X86::ROR8m1 }, + { X86::ROR8rCL, X86::ROR8mCL }, + { X86::ROR8ri, X86::ROR8mi }, + { X86::SAR16r1, X86::SAR16m1 }, + { X86::SAR16rCL, X86::SAR16mCL }, + { X86::SAR16ri, X86::SAR16mi }, + { X86::SAR32r1, X86::SAR32m1 }, + { X86::SAR32rCL, X86::SAR32mCL }, + { X86::SAR32ri, X86::SAR32mi }, + { X86::SAR64r1, X86::SAR64m1 }, + { X86::SAR64rCL, X86::SAR64mCL }, + { X86::SAR64ri, X86::SAR64mi }, + { X86::SAR8r1, X86::SAR8m1 }, + { X86::SAR8rCL, X86::SAR8mCL }, + { X86::SAR8ri, X86::SAR8mi }, + { X86::SBB32ri, X86::SBB32mi }, + { X86::SBB32ri8, X86::SBB32mi8 }, + { X86::SBB32rr, X86::SBB32mr }, + { X86::SBB64ri32, X86::SBB64mi32 }, + { X86::SBB64ri8, X86::SBB64mi8 }, + { X86::SBB64rr, X86::SBB64mr }, + { X86::SHL16rCL, X86::SHL16mCL }, + { X86::SHL16ri, X86::SHL16mi }, + { X86::SHL32rCL, X86::SHL32mCL }, + { X86::SHL32ri, X86::SHL32mi }, + { X86::SHL64rCL, X86::SHL64mCL }, + { X86::SHL64ri, X86::SHL64mi }, + { X86::SHL8rCL, X86::SHL8mCL }, + { X86::SHL8ri, X86::SHL8mi }, + { X86::SHLD16rrCL, X86::SHLD16mrCL }, + { X86::SHLD16rri8, X86::SHLD16mri8 }, + { X86::SHLD32rrCL, X86::SHLD32mrCL }, + { X86::SHLD32rri8, X86::SHLD32mri8 }, + { X86::SHLD64rrCL, X86::SHLD64mrCL }, + { X86::SHLD64rri8, X86::SHLD64mri8 }, + { X86::SHR16r1, X86::SHR16m1 }, + { X86::SHR16rCL, X86::SHR16mCL }, + { X86::SHR16ri, X86::SHR16mi }, + { X86::SHR32r1, X86::SHR32m1 }, + { X86::SHR32rCL, X86::SHR32mCL }, + { X86::SHR32ri, X86::SHR32mi }, + { X86::SHR64r1, X86::SHR64m1 }, + { X86::SHR64rCL, X86::SHR64mCL }, + { X86::SHR64ri, X86::SHR64mi }, + { X86::SHR8r1, X86::SHR8m1 }, + { X86::SHR8rCL, X86::SHR8mCL }, + { X86::SHR8ri, X86::SHR8mi }, + { X86::SHRD16rrCL, X86::SHRD16mrCL }, + { X86::SHRD16rri8, X86::SHRD16mri8 }, + { X86::SHRD32rrCL, X86::SHRD32mrCL }, + { X86::SHRD32rri8, X86::SHRD32mri8 }, + { X86::SHRD64rrCL, X86::SHRD64mrCL }, + { X86::SHRD64rri8, X86::SHRD64mri8 }, + { X86::SUB16ri, X86::SUB16mi }, + { X86::SUB16ri8, X86::SUB16mi8 }, + { X86::SUB16rr, X86::SUB16mr }, + { X86::SUB32ri, X86::SUB32mi }, + { X86::SUB32ri8, X86::SUB32mi8 }, + { X86::SUB32rr, X86::SUB32mr }, + { X86::SUB64ri32, X86::SUB64mi32 }, + { X86::SUB64ri8, X86::SUB64mi8 }, + { X86::SUB64rr, X86::SUB64mr }, + { X86::SUB8ri, X86::SUB8mi }, + { X86::SUB8rr, X86::SUB8mr }, + { X86::XOR16ri, X86::XOR16mi }, + { X86::XOR16ri8, X86::XOR16mi8 }, + { X86::XOR16rr, X86::XOR16mr }, + { X86::XOR32ri, X86::XOR32mi }, + { X86::XOR32ri8, X86::XOR32mi8 }, + { X86::XOR32rr, X86::XOR32mr }, + { X86::XOR64ri32, X86::XOR64mi32 }, + { X86::XOR64ri8, X86::XOR64mi8 }, + { X86::XOR64rr, X86::XOR64mr }, + { X86::XOR8ri, X86::XOR8mi }, + { X86::XOR8rr, X86::XOR8mr } + }; + + for (unsigned i = 0, e = array_lengthof(OpTbl2Addr); i != e; ++i) { + unsigned RegOp = OpTbl2Addr[i][0]; + unsigned MemOp = OpTbl2Addr[i][1]; + if (!RegOp2MemOpTable2Addr.insert(std::make_pair((unsigned*)RegOp, + std::make_pair(MemOp,0))).second) + assert(false && "Duplicated entries?"); + // Index 0, folded load and store, no alignment requirement. + unsigned AuxInfo = 0 | (1 << 4) | (1 << 5); + if (!MemOp2RegOpTable.insert(std::make_pair((unsigned*)MemOp, + std::make_pair(RegOp, + AuxInfo))).second) + AmbEntries.push_back(MemOp); + } + + // If the third value is 1, then it's folding either a load or a store. + static const unsigned OpTbl0[][4] = { + { X86::BT16ri8, X86::BT16mi8, 1, 0 }, + { X86::BT32ri8, X86::BT32mi8, 1, 0 }, + { X86::BT64ri8, X86::BT64mi8, 1, 0 }, + { X86::CALL32r, X86::CALL32m, 1, 0 }, + { X86::CALL64r, X86::CALL64m, 1, 0 }, + { X86::CMP16ri, X86::CMP16mi, 1, 0 }, + { X86::CMP16ri8, X86::CMP16mi8, 1, 0 }, + { X86::CMP16rr, X86::CMP16mr, 1, 0 }, + { X86::CMP32ri, X86::CMP32mi, 1, 0 }, + { X86::CMP32ri8, X86::CMP32mi8, 1, 0 }, + { X86::CMP32rr, X86::CMP32mr, 1, 0 }, + { X86::CMP64ri32, X86::CMP64mi32, 1, 0 }, + { X86::CMP64ri8, X86::CMP64mi8, 1, 0 }, + { X86::CMP64rr, X86::CMP64mr, 1, 0 }, + { X86::CMP8ri, X86::CMP8mi, 1, 0 }, + { X86::CMP8rr, X86::CMP8mr, 1, 0 }, + { X86::DIV16r, X86::DIV16m, 1, 0 }, + { X86::DIV32r, X86::DIV32m, 1, 0 }, + { X86::DIV64r, X86::DIV64m, 1, 0 }, + { X86::DIV8r, X86::DIV8m, 1, 0 }, + { X86::EXTRACTPSrr, X86::EXTRACTPSmr, 0, 16 }, + { X86::FsMOVAPDrr, X86::MOVSDmr, 0, 0 }, + { X86::FsMOVAPSrr, X86::MOVSSmr, 0, 0 }, + { X86::IDIV16r, X86::IDIV16m, 1, 0 }, + { X86::IDIV32r, X86::IDIV32m, 1, 0 }, + { X86::IDIV64r, X86::IDIV64m, 1, 0 }, + { X86::IDIV8r, X86::IDIV8m, 1, 0 }, + { X86::IMUL16r, X86::IMUL16m, 1, 0 }, + { X86::IMUL32r, X86::IMUL32m, 1, 0 }, + { X86::IMUL64r, X86::IMUL64m, 1, 0 }, + { X86::IMUL8r, X86::IMUL8m, 1, 0 }, + { X86::JMP32r, X86::JMP32m, 1, 0 }, + { X86::JMP64r, X86::JMP64m, 1, 0 }, + { X86::MOV16ri, X86::MOV16mi, 0, 0 }, + { X86::MOV16rr, X86::MOV16mr, 0, 0 }, + { X86::MOV32ri, X86::MOV32mi, 0, 0 }, + { X86::MOV32rr, X86::MOV32mr, 0, 0 }, + { X86::MOV64ri32, X86::MOV64mi32, 0, 0 }, + { X86::MOV64rr, X86::MOV64mr, 0, 0 }, + { X86::MOV8ri, X86::MOV8mi, 0, 0 }, + { X86::MOV8rr, X86::MOV8mr, 0, 0 }, + { X86::MOV8rr_NOREX, X86::MOV8mr_NOREX, 0, 0 }, + { X86::MOVAPDrr, X86::MOVAPDmr, 0, 16 }, + { X86::MOVAPSrr, X86::MOVAPSmr, 0, 16 }, + { X86::MOVDQArr, X86::MOVDQAmr, 0, 16 }, + { X86::MOVPDI2DIrr, X86::MOVPDI2DImr, 0, 0 }, + { X86::MOVPQIto64rr,X86::MOVPQI2QImr, 0, 0 }, + { X86::MOVPS2SSrr, X86::MOVPS2SSmr, 0, 0 }, + { X86::MOVSDrr, X86::MOVSDmr, 0, 0 }, + { X86::MOVSDto64rr, X86::MOVSDto64mr, 0, 0 }, + { X86::MOVSS2DIrr, X86::MOVSS2DImr, 0, 0 }, + { X86::MOVSSrr, X86::MOVSSmr, 0, 0 }, + { X86::MOVUPDrr, X86::MOVUPDmr, 0, 0 }, + { X86::MOVUPSrr, X86::MOVUPSmr, 0, 0 }, + { X86::MUL16r, X86::MUL16m, 1, 0 }, + { X86::MUL32r, X86::MUL32m, 1, 0 }, + { X86::MUL64r, X86::MUL64m, 1, 0 }, + { X86::MUL8r, X86::MUL8m, 1, 0 }, + { X86::SETAEr, X86::SETAEm, 0, 0 }, + { X86::SETAr, X86::SETAm, 0, 0 }, + { X86::SETBEr, X86::SETBEm, 0, 0 }, + { X86::SETBr, X86::SETBm, 0, 0 }, + { X86::SETEr, X86::SETEm, 0, 0 }, + { X86::SETGEr, X86::SETGEm, 0, 0 }, + { X86::SETGr, X86::SETGm, 0, 0 }, + { X86::SETLEr, X86::SETLEm, 0, 0 }, + { X86::SETLr, X86::SETLm, 0, 0 }, + { X86::SETNEr, X86::SETNEm, 0, 0 }, + { X86::SETNOr, X86::SETNOm, 0, 0 }, + { X86::SETNPr, X86::SETNPm, 0, 0 }, + { X86::SETNSr, X86::SETNSm, 0, 0 }, + { X86::SETOr, X86::SETOm, 0, 0 }, + { X86::SETPr, X86::SETPm, 0, 0 }, + { X86::SETSr, X86::SETSm, 0, 0 }, + { X86::TAILJMPr, X86::TAILJMPm, 1, 0 }, + { X86::TEST16ri, X86::TEST16mi, 1, 0 }, + { X86::TEST32ri, X86::TEST32mi, 1, 0 }, + { X86::TEST64ri32, X86::TEST64mi32, 1, 0 }, + { X86::TEST8ri, X86::TEST8mi, 1, 0 } + }; + + for (unsigned i = 0, e = array_lengthof(OpTbl0); i != e; ++i) { + unsigned RegOp = OpTbl0[i][0]; + unsigned MemOp = OpTbl0[i][1]; + unsigned Align = OpTbl0[i][3]; + if (!RegOp2MemOpTable0.insert(std::make_pair((unsigned*)RegOp, + std::make_pair(MemOp,Align))).second) + assert(false && "Duplicated entries?"); + unsigned FoldedLoad = OpTbl0[i][2]; + // Index 0, folded load or store. + unsigned AuxInfo = 0 | (FoldedLoad << 4) | ((FoldedLoad^1) << 5); + if (RegOp != X86::FsMOVAPDrr && RegOp != X86::FsMOVAPSrr) + if (!MemOp2RegOpTable.insert(std::make_pair((unsigned*)MemOp, + std::make_pair(RegOp, AuxInfo))).second) + AmbEntries.push_back(MemOp); + } + + static const unsigned OpTbl1[][3] = { + { X86::CMP16rr, X86::CMP16rm, 0 }, + { X86::CMP32rr, X86::CMP32rm, 0 }, + { X86::CMP64rr, X86::CMP64rm, 0 }, + { X86::CMP8rr, X86::CMP8rm, 0 }, + { X86::CVTSD2SSrr, X86::CVTSD2SSrm, 0 }, + { X86::CVTSI2SD64rr, X86::CVTSI2SD64rm, 0 }, + { X86::CVTSI2SDrr, X86::CVTSI2SDrm, 0 }, + { X86::CVTSI2SS64rr, X86::CVTSI2SS64rm, 0 }, + { X86::CVTSI2SSrr, X86::CVTSI2SSrm, 0 }, + { X86::CVTSS2SDrr, X86::CVTSS2SDrm, 0 }, + { X86::CVTTSD2SI64rr, X86::CVTTSD2SI64rm, 0 }, + { X86::CVTTSD2SIrr, X86::CVTTSD2SIrm, 0 }, + { X86::CVTTSS2SI64rr, X86::CVTTSS2SI64rm, 0 }, + { X86::CVTTSS2SIrr, X86::CVTTSS2SIrm, 0 }, + { X86::FsMOVAPDrr, X86::MOVSDrm, 0 }, + { X86::FsMOVAPSrr, X86::MOVSSrm, 0 }, + { X86::IMUL16rri, X86::IMUL16rmi, 0 }, + { X86::IMUL16rri8, X86::IMUL16rmi8, 0 }, + { X86::IMUL32rri, X86::IMUL32rmi, 0 }, + { X86::IMUL32rri8, X86::IMUL32rmi8, 0 }, + { X86::IMUL64rri32, X86::IMUL64rmi32, 0 }, + { X86::IMUL64rri8, X86::IMUL64rmi8, 0 }, + { X86::Int_CMPSDrr, X86::Int_CMPSDrm, 0 }, + { X86::Int_CMPSSrr, X86::Int_CMPSSrm, 0 }, + { X86::Int_COMISDrr, X86::Int_COMISDrm, 0 }, + { X86::Int_COMISSrr, X86::Int_COMISSrm, 0 }, + { X86::Int_CVTDQ2PDrr, X86::Int_CVTDQ2PDrm, 16 }, + { X86::Int_CVTDQ2PSrr, X86::Int_CVTDQ2PSrm, 16 }, + { X86::Int_CVTPD2DQrr, X86::Int_CVTPD2DQrm, 16 }, + { X86::Int_CVTPD2PSrr, X86::Int_CVTPD2PSrm, 16 }, + { X86::Int_CVTPS2DQrr, X86::Int_CVTPS2DQrm, 16 }, + { X86::Int_CVTPS2PDrr, X86::Int_CVTPS2PDrm, 0 }, + { X86::Int_CVTSD2SI64rr,X86::Int_CVTSD2SI64rm, 0 }, + { X86::Int_CVTSD2SIrr, X86::Int_CVTSD2SIrm, 0 }, + { X86::Int_CVTSD2SSrr, X86::Int_CVTSD2SSrm, 0 }, + { X86::Int_CVTSI2SD64rr,X86::Int_CVTSI2SD64rm, 0 }, + { X86::Int_CVTSI2SDrr, X86::Int_CVTSI2SDrm, 0 }, + { X86::Int_CVTSI2SS64rr,X86::Int_CVTSI2SS64rm, 0 }, + { X86::Int_CVTSI2SSrr, X86::Int_CVTSI2SSrm, 0 }, + { X86::Int_CVTSS2SDrr, X86::Int_CVTSS2SDrm, 0 }, + { X86::Int_CVTSS2SI64rr,X86::Int_CVTSS2SI64rm, 0 }, + { X86::Int_CVTSS2SIrr, X86::Int_CVTSS2SIrm, 0 }, + { X86::Int_CVTTPD2DQrr, X86::Int_CVTTPD2DQrm, 16 }, + { X86::Int_CVTTPS2DQrr, X86::Int_CVTTPS2DQrm, 16 }, + { X86::Int_CVTTSD2SI64rr,X86::Int_CVTTSD2SI64rm, 0 }, + { X86::Int_CVTTSD2SIrr, X86::Int_CVTTSD2SIrm, 0 }, + { X86::Int_CVTTSS2SI64rr,X86::Int_CVTTSS2SI64rm, 0 }, + { X86::Int_CVTTSS2SIrr, X86::Int_CVTTSS2SIrm, 0 }, + { X86::Int_UCOMISDrr, X86::Int_UCOMISDrm, 0 }, + { X86::Int_UCOMISSrr, X86::Int_UCOMISSrm, 0 }, + { X86::MOV16rr, X86::MOV16rm, 0 }, + { X86::MOV32rr, X86::MOV32rm, 0 }, + { X86::MOV64rr, X86::MOV64rm, 0 }, + { X86::MOV64toPQIrr, X86::MOVQI2PQIrm, 0 }, + { X86::MOV64toSDrr, X86::MOV64toSDrm, 0 }, + { X86::MOV8rr, X86::MOV8rm, 0 }, + { X86::MOVAPDrr, X86::MOVAPDrm, 16 }, + { X86::MOVAPSrr, X86::MOVAPSrm, 16 }, + { X86::MOVDDUPrr, X86::MOVDDUPrm, 0 }, + { X86::MOVDI2PDIrr, X86::MOVDI2PDIrm, 0 }, + { X86::MOVDI2SSrr, X86::MOVDI2SSrm, 0 }, + { X86::MOVDQArr, X86::MOVDQArm, 16 }, + { X86::MOVSD2PDrr, X86::MOVSD2PDrm, 0 }, + { X86::MOVSDrr, X86::MOVSDrm, 0 }, + { X86::MOVSHDUPrr, X86::MOVSHDUPrm, 16 }, + { X86::MOVSLDUPrr, X86::MOVSLDUPrm, 16 }, + { X86::MOVSS2PSrr, X86::MOVSS2PSrm, 0 }, + { X86::MOVSSrr, X86::MOVSSrm, 0 }, + { X86::MOVSX16rr8, X86::MOVSX16rm8, 0 }, + { X86::MOVSX32rr16, X86::MOVSX32rm16, 0 }, + { X86::MOVSX32rr8, X86::MOVSX32rm8, 0 }, + { X86::MOVSX64rr16, X86::MOVSX64rm16, 0 }, + { X86::MOVSX64rr32, X86::MOVSX64rm32, 0 }, + { X86::MOVSX64rr8, X86::MOVSX64rm8, 0 }, + { X86::MOVUPDrr, X86::MOVUPDrm, 16 }, + { X86::MOVUPSrr, X86::MOVUPSrm, 16 }, + { X86::MOVZDI2PDIrr, X86::MOVZDI2PDIrm, 0 }, + { X86::MOVZQI2PQIrr, X86::MOVZQI2PQIrm, 0 }, + { X86::MOVZPQILo2PQIrr, X86::MOVZPQILo2PQIrm, 16 }, + { X86::MOVZX16rr8, X86::MOVZX16rm8, 0 }, + { X86::MOVZX32rr16, X86::MOVZX32rm16, 0 }, + { X86::MOVZX32_NOREXrr8, X86::MOVZX32_NOREXrm8, 0 }, + { X86::MOVZX32rr8, X86::MOVZX32rm8, 0 }, + { X86::MOVZX64rr16, X86::MOVZX64rm16, 0 }, + { X86::MOVZX64rr32, X86::MOVZX64rm32, 0 }, + { X86::MOVZX64rr8, X86::MOVZX64rm8, 0 }, + { X86::PSHUFDri, X86::PSHUFDmi, 16 }, + { X86::PSHUFHWri, X86::PSHUFHWmi, 16 }, + { X86::PSHUFLWri, X86::PSHUFLWmi, 16 }, + { X86::RCPPSr, X86::RCPPSm, 16 }, + { X86::RCPPSr_Int, X86::RCPPSm_Int, 16 }, + { X86::RSQRTPSr, X86::RSQRTPSm, 16 }, + { X86::RSQRTPSr_Int, X86::RSQRTPSm_Int, 16 }, + { X86::RSQRTSSr, X86::RSQRTSSm, 0 }, + { X86::RSQRTSSr_Int, X86::RSQRTSSm_Int, 0 }, + { X86::SQRTPDr, X86::SQRTPDm, 16 }, + { X86::SQRTPDr_Int, X86::SQRTPDm_Int, 16 }, + { X86::SQRTPSr, X86::SQRTPSm, 16 }, + { X86::SQRTPSr_Int, X86::SQRTPSm_Int, 16 }, + { X86::SQRTSDr, X86::SQRTSDm, 0 }, + { X86::SQRTSDr_Int, X86::SQRTSDm_Int, 0 }, + { X86::SQRTSSr, X86::SQRTSSm, 0 }, + { X86::SQRTSSr_Int, X86::SQRTSSm_Int, 0 }, + { X86::TEST16rr, X86::TEST16rm, 0 }, + { X86::TEST32rr, X86::TEST32rm, 0 }, + { X86::TEST64rr, X86::TEST64rm, 0 }, + { X86::TEST8rr, X86::TEST8rm, 0 }, + // FIXME: TEST*rr EAX,EAX ---> CMP [mem], 0 + { X86::UCOMISDrr, X86::UCOMISDrm, 0 }, + { X86::UCOMISSrr, X86::UCOMISSrm, 0 } + }; + + for (unsigned i = 0, e = array_lengthof(OpTbl1); i != e; ++i) { + unsigned RegOp = OpTbl1[i][0]; + unsigned MemOp = OpTbl1[i][1]; + unsigned Align = OpTbl1[i][2]; + if (!RegOp2MemOpTable1.insert(std::make_pair((unsigned*)RegOp, + std::make_pair(MemOp,Align))).second) + assert(false && "Duplicated entries?"); + // Index 1, folded load + unsigned AuxInfo = 1 | (1 << 4); + if (RegOp != X86::FsMOVAPDrr && RegOp != X86::FsMOVAPSrr) + if (!MemOp2RegOpTable.insert(std::make_pair((unsigned*)MemOp, + std::make_pair(RegOp, AuxInfo))).second) + AmbEntries.push_back(MemOp); + } + + static const unsigned OpTbl2[][3] = { + { X86::ADC32rr, X86::ADC32rm, 0 }, + { X86::ADC64rr, X86::ADC64rm, 0 }, + { X86::ADD16rr, X86::ADD16rm, 0 }, + { X86::ADD32rr, X86::ADD32rm, 0 }, + { X86::ADD64rr, X86::ADD64rm, 0 }, + { X86::ADD8rr, X86::ADD8rm, 0 }, + { X86::ADDPDrr, X86::ADDPDrm, 16 }, + { X86::ADDPSrr, X86::ADDPSrm, 16 }, + { X86::ADDSDrr, X86::ADDSDrm, 0 }, + { X86::ADDSSrr, X86::ADDSSrm, 0 }, + { X86::ADDSUBPDrr, X86::ADDSUBPDrm, 16 }, + { X86::ADDSUBPSrr, X86::ADDSUBPSrm, 16 }, + { X86::AND16rr, X86::AND16rm, 0 }, + { X86::AND32rr, X86::AND32rm, 0 }, + { X86::AND64rr, X86::AND64rm, 0 }, + { X86::AND8rr, X86::AND8rm, 0 }, + { X86::ANDNPDrr, X86::ANDNPDrm, 16 }, + { X86::ANDNPSrr, X86::ANDNPSrm, 16 }, + { X86::ANDPDrr, X86::ANDPDrm, 16 }, + { X86::ANDPSrr, X86::ANDPSrm, 16 }, + { X86::CMOVA16rr, X86::CMOVA16rm, 0 }, + { X86::CMOVA32rr, X86::CMOVA32rm, 0 }, + { X86::CMOVA64rr, X86::CMOVA64rm, 0 }, + { X86::CMOVAE16rr, X86::CMOVAE16rm, 0 }, + { X86::CMOVAE32rr, X86::CMOVAE32rm, 0 }, + { X86::CMOVAE64rr, X86::CMOVAE64rm, 0 }, + { X86::CMOVB16rr, X86::CMOVB16rm, 0 }, + { X86::CMOVB32rr, X86::CMOVB32rm, 0 }, + { X86::CMOVB64rr, X86::CMOVB64rm, 0 }, + { X86::CMOVBE16rr, X86::CMOVBE16rm, 0 }, + { X86::CMOVBE32rr, X86::CMOVBE32rm, 0 }, + { X86::CMOVBE64rr, X86::CMOVBE64rm, 0 }, + { X86::CMOVE16rr, X86::CMOVE16rm, 0 }, + { X86::CMOVE32rr, X86::CMOVE32rm, 0 }, + { X86::CMOVE64rr, X86::CMOVE64rm, 0 }, + { X86::CMOVG16rr, X86::CMOVG16rm, 0 }, + { X86::CMOVG32rr, X86::CMOVG32rm, 0 }, + { X86::CMOVG64rr, X86::CMOVG64rm, 0 }, + { X86::CMOVGE16rr, X86::CMOVGE16rm, 0 }, + { X86::CMOVGE32rr, X86::CMOVGE32rm, 0 }, + { X86::CMOVGE64rr, X86::CMOVGE64rm, 0 }, + { X86::CMOVL16rr, X86::CMOVL16rm, 0 }, + { X86::CMOVL32rr, X86::CMOVL32rm, 0 }, + { X86::CMOVL64rr, X86::CMOVL64rm, 0 }, + { X86::CMOVLE16rr, X86::CMOVLE16rm, 0 }, + { X86::CMOVLE32rr, X86::CMOVLE32rm, 0 }, + { X86::CMOVLE64rr, X86::CMOVLE64rm, 0 }, + { X86::CMOVNE16rr, X86::CMOVNE16rm, 0 }, + { X86::CMOVNE32rr, X86::CMOVNE32rm, 0 }, + { X86::CMOVNE64rr, X86::CMOVNE64rm, 0 }, + { X86::CMOVNO16rr, X86::CMOVNO16rm, 0 }, + { X86::CMOVNO32rr, X86::CMOVNO32rm, 0 }, + { X86::CMOVNO64rr, X86::CMOVNO64rm, 0 }, + { X86::CMOVNP16rr, X86::CMOVNP16rm, 0 }, + { X86::CMOVNP32rr, X86::CMOVNP32rm, 0 }, + { X86::CMOVNP64rr, X86::CMOVNP64rm, 0 }, + { X86::CMOVNS16rr, X86::CMOVNS16rm, 0 }, + { X86::CMOVNS32rr, X86::CMOVNS32rm, 0 }, + { X86::CMOVNS64rr, X86::CMOVNS64rm, 0 }, + { X86::CMOVO16rr, X86::CMOVO16rm, 0 }, + { X86::CMOVO32rr, X86::CMOVO32rm, 0 }, + { X86::CMOVO64rr, X86::CMOVO64rm, 0 }, + { X86::CMOVP16rr, X86::CMOVP16rm, 0 }, + { X86::CMOVP32rr, X86::CMOVP32rm, 0 }, + { X86::CMOVP64rr, X86::CMOVP64rm, 0 }, + { X86::CMOVS16rr, X86::CMOVS16rm, 0 }, + { X86::CMOVS32rr, X86::CMOVS32rm, 0 }, + { X86::CMOVS64rr, X86::CMOVS64rm, 0 }, + { X86::CMPPDrri, X86::CMPPDrmi, 16 }, + { X86::CMPPSrri, X86::CMPPSrmi, 16 }, + { X86::CMPSDrr, X86::CMPSDrm, 0 }, + { X86::CMPSSrr, X86::CMPSSrm, 0 }, + { X86::DIVPDrr, X86::DIVPDrm, 16 }, + { X86::DIVPSrr, X86::DIVPSrm, 16 }, + { X86::DIVSDrr, X86::DIVSDrm, 0 }, + { X86::DIVSSrr, X86::DIVSSrm, 0 }, + { X86::FsANDNPDrr, X86::FsANDNPDrm, 16 }, + { X86::FsANDNPSrr, X86::FsANDNPSrm, 16 }, + { X86::FsANDPDrr, X86::FsANDPDrm, 16 }, + { X86::FsANDPSrr, X86::FsANDPSrm, 16 }, + { X86::FsORPDrr, X86::FsORPDrm, 16 }, + { X86::FsORPSrr, X86::FsORPSrm, 16 }, + { X86::FsXORPDrr, X86::FsXORPDrm, 16 }, + { X86::FsXORPSrr, X86::FsXORPSrm, 16 }, + { X86::HADDPDrr, X86::HADDPDrm, 16 }, + { X86::HADDPSrr, X86::HADDPSrm, 16 }, + { X86::HSUBPDrr, X86::HSUBPDrm, 16 }, + { X86::HSUBPSrr, X86::HSUBPSrm, 16 }, + { X86::IMUL16rr, X86::IMUL16rm, 0 }, + { X86::IMUL32rr, X86::IMUL32rm, 0 }, + { X86::IMUL64rr, X86::IMUL64rm, 0 }, + { X86::MAXPDrr, X86::MAXPDrm, 16 }, + { X86::MAXPDrr_Int, X86::MAXPDrm_Int, 16 }, + { X86::MAXPSrr, X86::MAXPSrm, 16 }, + { X86::MAXPSrr_Int, X86::MAXPSrm_Int, 16 }, + { X86::MAXSDrr, X86::MAXSDrm, 0 }, + { X86::MAXSDrr_Int, X86::MAXSDrm_Int, 0 }, + { X86::MAXSSrr, X86::MAXSSrm, 0 }, + { X86::MAXSSrr_Int, X86::MAXSSrm_Int, 0 }, + { X86::MINPDrr, X86::MINPDrm, 16 }, + { X86::MINPDrr_Int, X86::MINPDrm_Int, 16 }, + { X86::MINPSrr, X86::MINPSrm, 16 }, + { X86::MINPSrr_Int, X86::MINPSrm_Int, 16 }, + { X86::MINSDrr, X86::MINSDrm, 0 }, + { X86::MINSDrr_Int, X86::MINSDrm_Int, 0 }, + { X86::MINSSrr, X86::MINSSrm, 0 }, + { X86::MINSSrr_Int, X86::MINSSrm_Int, 0 }, + { X86::MULPDrr, X86::MULPDrm, 16 }, + { X86::MULPSrr, X86::MULPSrm, 16 }, + { X86::MULSDrr, X86::MULSDrm, 0 }, + { X86::MULSSrr, X86::MULSSrm, 0 }, + { X86::OR16rr, X86::OR16rm, 0 }, + { X86::OR32rr, X86::OR32rm, 0 }, + { X86::OR64rr, X86::OR64rm, 0 }, + { X86::OR8rr, X86::OR8rm, 0 }, + { X86::ORPDrr, X86::ORPDrm, 16 }, + { X86::ORPSrr, X86::ORPSrm, 16 }, + { X86::PACKSSDWrr, X86::PACKSSDWrm, 16 }, + { X86::PACKSSWBrr, X86::PACKSSWBrm, 16 }, + { X86::PACKUSWBrr, X86::PACKUSWBrm, 16 }, + { X86::PADDBrr, X86::PADDBrm, 16 }, + { X86::PADDDrr, X86::PADDDrm, 16 }, + { X86::PADDQrr, X86::PADDQrm, 16 }, + { X86::PADDSBrr, X86::PADDSBrm, 16 }, + { X86::PADDSWrr, X86::PADDSWrm, 16 }, + { X86::PADDWrr, X86::PADDWrm, 16 }, + { X86::PANDNrr, X86::PANDNrm, 16 }, + { X86::PANDrr, X86::PANDrm, 16 }, + { X86::PAVGBrr, X86::PAVGBrm, 16 }, + { X86::PAVGWrr, X86::PAVGWrm, 16 }, + { X86::PCMPEQBrr, X86::PCMPEQBrm, 16 }, + { X86::PCMPEQDrr, X86::PCMPEQDrm, 16 }, + { X86::PCMPEQWrr, X86::PCMPEQWrm, 16 }, + { X86::PCMPGTBrr, X86::PCMPGTBrm, 16 }, + { X86::PCMPGTDrr, X86::PCMPGTDrm, 16 }, + { X86::PCMPGTWrr, X86::PCMPGTWrm, 16 }, + { X86::PINSRWrri, X86::PINSRWrmi, 16 }, + { X86::PMADDWDrr, X86::PMADDWDrm, 16 }, + { X86::PMAXSWrr, X86::PMAXSWrm, 16 }, + { X86::PMAXUBrr, X86::PMAXUBrm, 16 }, + { X86::PMINSWrr, X86::PMINSWrm, 16 }, + { X86::PMINUBrr, X86::PMINUBrm, 16 }, + { X86::PMULDQrr, X86::PMULDQrm, 16 }, + { X86::PMULHUWrr, X86::PMULHUWrm, 16 }, + { X86::PMULHWrr, X86::PMULHWrm, 16 }, + { X86::PMULLDrr, X86::PMULLDrm, 16 }, + { X86::PMULLDrr_int, X86::PMULLDrm_int, 16 }, + { X86::PMULLWrr, X86::PMULLWrm, 16 }, + { X86::PMULUDQrr, X86::PMULUDQrm, 16 }, + { X86::PORrr, X86::PORrm, 16 }, + { X86::PSADBWrr, X86::PSADBWrm, 16 }, + { X86::PSLLDrr, X86::PSLLDrm, 16 }, + { X86::PSLLQrr, X86::PSLLQrm, 16 }, + { X86::PSLLWrr, X86::PSLLWrm, 16 }, + { X86::PSRADrr, X86::PSRADrm, 16 }, + { X86::PSRAWrr, X86::PSRAWrm, 16 }, + { X86::PSRLDrr, X86::PSRLDrm, 16 }, + { X86::PSRLQrr, X86::PSRLQrm, 16 }, + { X86::PSRLWrr, X86::PSRLWrm, 16 }, + { X86::PSUBBrr, X86::PSUBBrm, 16 }, + { X86::PSUBDrr, X86::PSUBDrm, 16 }, + { X86::PSUBSBrr, X86::PSUBSBrm, 16 }, + { X86::PSUBSWrr, X86::PSUBSWrm, 16 }, + { X86::PSUBWrr, X86::PSUBWrm, 16 }, + { X86::PUNPCKHBWrr, X86::PUNPCKHBWrm, 16 }, + { X86::PUNPCKHDQrr, X86::PUNPCKHDQrm, 16 }, + { X86::PUNPCKHQDQrr, X86::PUNPCKHQDQrm, 16 }, + { X86::PUNPCKHWDrr, X86::PUNPCKHWDrm, 16 }, + { X86::PUNPCKLBWrr, X86::PUNPCKLBWrm, 16 }, + { X86::PUNPCKLDQrr, X86::PUNPCKLDQrm, 16 }, + { X86::PUNPCKLQDQrr, X86::PUNPCKLQDQrm, 16 }, + { X86::PUNPCKLWDrr, X86::PUNPCKLWDrm, 16 }, + { X86::PXORrr, X86::PXORrm, 16 }, + { X86::SBB32rr, X86::SBB32rm, 0 }, + { X86::SBB64rr, X86::SBB64rm, 0 }, + { X86::SHUFPDrri, X86::SHUFPDrmi, 16 }, + { X86::SHUFPSrri, X86::SHUFPSrmi, 16 }, + { X86::SUB16rr, X86::SUB16rm, 0 }, + { X86::SUB32rr, X86::SUB32rm, 0 }, + { X86::SUB64rr, X86::SUB64rm, 0 }, + { X86::SUB8rr, X86::SUB8rm, 0 }, + { X86::SUBPDrr, X86::SUBPDrm, 16 }, + { X86::SUBPSrr, X86::SUBPSrm, 16 }, + { X86::SUBSDrr, X86::SUBSDrm, 0 }, + { X86::SUBSSrr, X86::SUBSSrm, 0 }, + // FIXME: TEST*rr -> swapped operand of TEST*mr. + { X86::UNPCKHPDrr, X86::UNPCKHPDrm, 16 }, + { X86::UNPCKHPSrr, X86::UNPCKHPSrm, 16 }, + { X86::UNPCKLPDrr, X86::UNPCKLPDrm, 16 }, + { X86::UNPCKLPSrr, X86::UNPCKLPSrm, 16 }, + { X86::XOR16rr, X86::XOR16rm, 0 }, + { X86::XOR32rr, X86::XOR32rm, 0 }, + { X86::XOR64rr, X86::XOR64rm, 0 }, + { X86::XOR8rr, X86::XOR8rm, 0 }, + { X86::XORPDrr, X86::XORPDrm, 16 }, + { X86::XORPSrr, X86::XORPSrm, 16 } + }; + + for (unsigned i = 0, e = array_lengthof(OpTbl2); i != e; ++i) { + unsigned RegOp = OpTbl2[i][0]; + unsigned MemOp = OpTbl2[i][1]; + unsigned Align = OpTbl2[i][2]; + if (!RegOp2MemOpTable2.insert(std::make_pair((unsigned*)RegOp, + std::make_pair(MemOp,Align))).second) + assert(false && "Duplicated entries?"); + // Index 2, folded load + unsigned AuxInfo = 2 | (1 << 4); + if (!MemOp2RegOpTable.insert(std::make_pair((unsigned*)MemOp, + std::make_pair(RegOp, AuxInfo))).second) + AmbEntries.push_back(MemOp); + } + + // Remove ambiguous entries. + assert(AmbEntries.empty() && "Duplicated entries in unfolding maps?"); +} + +bool X86InstrInfo::isMoveInstr(const MachineInstr& MI, + unsigned &SrcReg, unsigned &DstReg, + unsigned &SrcSubIdx, unsigned &DstSubIdx) const { + switch (MI.getOpcode()) { + default: + return false; + case X86::MOV8rr: + case X86::MOV8rr_NOREX: + case X86::MOV16rr: + case X86::MOV32rr: + case X86::MOV64rr: + case X86::MOVSSrr: + case X86::MOVSDrr: + + // FP Stack register class copies + case X86::MOV_Fp3232: case X86::MOV_Fp6464: case X86::MOV_Fp8080: + case X86::MOV_Fp3264: case X86::MOV_Fp3280: + case X86::MOV_Fp6432: case X86::MOV_Fp8032: + + case X86::FsMOVAPSrr: + case X86::FsMOVAPDrr: + case X86::MOVAPSrr: + case X86::MOVAPDrr: + case X86::MOVDQArr: + case X86::MOVSS2PSrr: + case X86::MOVSD2PDrr: + case X86::MOVPS2SSrr: + case X86::MOVPD2SDrr: + case X86::MMX_MOVQ64rr: + assert(MI.getNumOperands() >= 2 && + MI.getOperand(0).isReg() && + MI.getOperand(1).isReg() && + "invalid register-register move instruction"); + SrcReg = MI.getOperand(1).getReg(); + DstReg = MI.getOperand(0).getReg(); + SrcSubIdx = MI.getOperand(1).getSubReg(); + DstSubIdx = MI.getOperand(0).getSubReg(); + return true; + } +} + +/// isFrameOperand - Return true and the FrameIndex if the specified +/// operand and follow operands form a reference to the stack frame. +bool X86InstrInfo::isFrameOperand(const MachineInstr *MI, unsigned int Op, + int &FrameIndex) const { + if (MI->getOperand(Op).isFI() && MI->getOperand(Op+1).isImm() && + MI->getOperand(Op+2).isReg() && MI->getOperand(Op+3).isImm() && + MI->getOperand(Op+1).getImm() == 1 && + MI->getOperand(Op+2).getReg() == 0 && + MI->getOperand(Op+3).getImm() == 0) { + FrameIndex = MI->getOperand(Op).getIndex(); + return true; + } + return false; +} + +static bool isFrameLoadOpcode(int Opcode) { + switch (Opcode) { + default: break; + case X86::MOV8rm: + case X86::MOV16rm: + case X86::MOV32rm: + case X86::MOV64rm: + case X86::LD_Fp64m: + case X86::MOVSSrm: + case X86::MOVSDrm: + case X86::MOVAPSrm: + case X86::MOVAPDrm: + case X86::MOVDQArm: + case X86::MMX_MOVD64rm: + case X86::MMX_MOVQ64rm: + return true; + break; + } + return false; +} + +static bool isFrameStoreOpcode(int Opcode) { + switch (Opcode) { + default: break; + case X86::MOV8mr: + case X86::MOV16mr: + case X86::MOV32mr: + case X86::MOV64mr: + case X86::ST_FpP64m: + case X86::MOVSSmr: + case X86::MOVSDmr: + case X86::MOVAPSmr: + case X86::MOVAPDmr: + case X86::MOVDQAmr: + case X86::MMX_MOVD64mr: + case X86::MMX_MOVQ64mr: + case X86::MMX_MOVNTQmr: + return true; + } + return false; +} + +unsigned X86InstrInfo::isLoadFromStackSlot(const MachineInstr *MI, + int &FrameIndex) const { + if (isFrameLoadOpcode(MI->getOpcode())) + if (isFrameOperand(MI, 1, FrameIndex)) + return MI->getOperand(0).getReg(); + return 0; +} + +unsigned X86InstrInfo::isLoadFromStackSlotPostFE(const MachineInstr *MI, + int &FrameIndex) const { + if (isFrameLoadOpcode(MI->getOpcode())) { + unsigned Reg; + if ((Reg = isLoadFromStackSlot(MI, FrameIndex))) + return Reg; + // Check for post-frame index elimination operations + return hasLoadFromStackSlot(MI, FrameIndex); + } + return 0; +} + +bool X86InstrInfo::hasLoadFromStackSlot(const MachineInstr *MI, + int &FrameIndex) const { + for (MachineInstr::mmo_iterator o = MI->memoperands_begin(), + oe = MI->memoperands_end(); + o != oe; + ++o) { + if ((*o)->isLoad() && (*o)->getValue()) + if (const FixedStackPseudoSourceValue *Value = + dyn_cast((*o)->getValue())) { + FrameIndex = Value->getFrameIndex(); + return true; + } + } + return false; +} + +unsigned X86InstrInfo::isStoreToStackSlot(const MachineInstr *MI, + int &FrameIndex) const { + if (isFrameStoreOpcode(MI->getOpcode())) + if (isFrameOperand(MI, 0, FrameIndex)) + return MI->getOperand(X86AddrNumOperands).getReg(); + return 0; +} + +unsigned X86InstrInfo::isStoreToStackSlotPostFE(const MachineInstr *MI, + int &FrameIndex) const { + if (isFrameStoreOpcode(MI->getOpcode())) { + unsigned Reg; + if ((Reg = isStoreToStackSlot(MI, FrameIndex))) + return Reg; + // Check for post-frame index elimination operations + return hasStoreToStackSlot(MI, FrameIndex); + } + return 0; +} + +bool X86InstrInfo::hasStoreToStackSlot(const MachineInstr *MI, + int &FrameIndex) const { + for (MachineInstr::mmo_iterator o = MI->memoperands_begin(), + oe = MI->memoperands_end(); + o != oe; + ++o) { + if ((*o)->isStore() && (*o)->getValue()) + if (const FixedStackPseudoSourceValue *Value = + dyn_cast((*o)->getValue())) { + FrameIndex = Value->getFrameIndex(); + return true; + } + } + return false; +} + +/// regIsPICBase - Return true if register is PIC base (i.e.g defined by +/// X86::MOVPC32r. +static bool regIsPICBase(unsigned BaseReg, const MachineRegisterInfo &MRI) { + bool isPICBase = false; + for (MachineRegisterInfo::def_iterator I = MRI.def_begin(BaseReg), + E = MRI.def_end(); I != E; ++I) { + MachineInstr *DefMI = I.getOperand().getParent(); + if (DefMI->getOpcode() != X86::MOVPC32r) + return false; + assert(!isPICBase && "More than one PIC base?"); + isPICBase = true; + } + return isPICBase; +} + +bool +X86InstrInfo::isReallyTriviallyReMaterializable(const MachineInstr *MI, + AliasAnalysis *AA) const { + switch (MI->getOpcode()) { + default: break; + case X86::MOV8rm: + case X86::MOV16rm: + case X86::MOV32rm: + case X86::MOV64rm: + case X86::LD_Fp64m: + case X86::MOVSSrm: + case X86::MOVSDrm: + case X86::MOVAPSrm: + case X86::MOVUPSrm: + case X86::MOVUPSrm_Int: + case X86::MOVAPDrm: + case X86::MOVDQArm: + case X86::MMX_MOVD64rm: + case X86::MMX_MOVQ64rm: + case X86::FsMOVAPSrm: + case X86::FsMOVAPDrm: { + // Loads from constant pools are trivially rematerializable. + if (MI->getOperand(1).isReg() && + MI->getOperand(2).isImm() && + MI->getOperand(3).isReg() && MI->getOperand(3).getReg() == 0 && + MI->isInvariantLoad(AA)) { + unsigned BaseReg = MI->getOperand(1).getReg(); + if (BaseReg == 0 || BaseReg == X86::RIP) + return true; + // Allow re-materialization of PIC load. + if (!ReMatPICStubLoad && MI->getOperand(4).isGlobal()) + return false; + const MachineFunction &MF = *MI->getParent()->getParent(); + const MachineRegisterInfo &MRI = MF.getRegInfo(); + bool isPICBase = false; + for (MachineRegisterInfo::def_iterator I = MRI.def_begin(BaseReg), + E = MRI.def_end(); I != E; ++I) { + MachineInstr *DefMI = I.getOperand().getParent(); + if (DefMI->getOpcode() != X86::MOVPC32r) + return false; + assert(!isPICBase && "More than one PIC base?"); + isPICBase = true; + } + return isPICBase; + } + return false; + } + + case X86::LEA32r: + case X86::LEA64r: { + if (MI->getOperand(2).isImm() && + MI->getOperand(3).isReg() && MI->getOperand(3).getReg() == 0 && + !MI->getOperand(4).isReg()) { + // lea fi#, lea GV, etc. are all rematerializable. + if (!MI->getOperand(1).isReg()) + return true; + unsigned BaseReg = MI->getOperand(1).getReg(); + if (BaseReg == 0) + return true; + // Allow re-materialization of lea PICBase + x. + const MachineFunction &MF = *MI->getParent()->getParent(); + const MachineRegisterInfo &MRI = MF.getRegInfo(); + return regIsPICBase(BaseReg, MRI); + } + return false; + } + } + + // All other instructions marked M_REMATERIALIZABLE are always trivially + // rematerializable. + return true; +} + +/// isSafeToClobberEFLAGS - Return true if it's safe insert an instruction that +/// would clobber the EFLAGS condition register. Note the result may be +/// conservative. If it cannot definitely determine the safety after visiting +/// a few instructions in each direction it assumes it's not safe. +static bool isSafeToClobberEFLAGS(MachineBasicBlock &MBB, + MachineBasicBlock::iterator I) { + // It's always safe to clobber EFLAGS at the end of a block. + if (I == MBB.end()) + return true; + + // For compile time consideration, if we are not able to determine the + // safety after visiting 4 instructions in each direction, we will assume + // it's not safe. + MachineBasicBlock::iterator Iter = I; + for (unsigned i = 0; i < 4; ++i) { + bool SeenDef = false; + for (unsigned j = 0, e = Iter->getNumOperands(); j != e; ++j) { + MachineOperand &MO = Iter->getOperand(j); + if (!MO.isReg()) + continue; + if (MO.getReg() == X86::EFLAGS) { + if (MO.isUse()) + return false; + SeenDef = true; + } + } + + if (SeenDef) + // This instruction defines EFLAGS, no need to look any further. + return true; + ++Iter; + + // If we make it to the end of the block, it's safe to clobber EFLAGS. + if (Iter == MBB.end()) + return true; + } + + Iter = I; + for (unsigned i = 0; i < 4; ++i) { + // If we make it to the beginning of the block, it's safe to clobber + // EFLAGS iff EFLAGS is not live-in. + if (Iter == MBB.begin()) + return !MBB.isLiveIn(X86::EFLAGS); + + --Iter; + bool SawKill = false; + for (unsigned j = 0, e = Iter->getNumOperands(); j != e; ++j) { + MachineOperand &MO = Iter->getOperand(j); + if (MO.isReg() && MO.getReg() == X86::EFLAGS) { + if (MO.isDef()) return MO.isDead(); + if (MO.isKill()) SawKill = true; + } + } + + if (SawKill) + // This instruction kills EFLAGS and doesn't redefine it, so + // there's no need to look further. + return true; + } + + // Conservative answer. + return false; +} + +void X86InstrInfo::reMaterialize(MachineBasicBlock &MBB, + MachineBasicBlock::iterator I, + unsigned DestReg, unsigned SubIdx, + const MachineInstr *Orig, + const TargetRegisterInfo *TRI) const { + DebugLoc DL = DebugLoc::getUnknownLoc(); + if (I != MBB.end()) DL = I->getDebugLoc(); + + if (SubIdx && TargetRegisterInfo::isPhysicalRegister(DestReg)) { + DestReg = TRI->getSubReg(DestReg, SubIdx); + SubIdx = 0; + } + + // MOV32r0 etc. are implemented with xor which clobbers condition code. + // Re-materialize them as movri instructions to avoid side effects. + bool Clone = true; + unsigned Opc = Orig->getOpcode(); + switch (Opc) { + default: break; + case X86::MOV8r0: + case X86::MOV16r0: + case X86::MOV32r0: { + if (!isSafeToClobberEFLAGS(MBB, I)) { + switch (Opc) { + default: break; + case X86::MOV8r0: Opc = X86::MOV8ri; break; + case X86::MOV16r0: Opc = X86::MOV16ri; break; + case X86::MOV32r0: Opc = X86::MOV32ri; break; + } + Clone = false; + } + break; + } + } + + if (Clone) { + MachineInstr *MI = MBB.getParent()->CloneMachineInstr(Orig); + MI->getOperand(0).setReg(DestReg); + MBB.insert(I, MI); + } else { + BuildMI(MBB, I, DL, get(Opc), DestReg).addImm(0); + } + + MachineInstr *NewMI = prior(I); + NewMI->getOperand(0).setSubReg(SubIdx); +} + +/// hasLiveCondCodeDef - True if MI has a condition code def, e.g. EFLAGS, that +/// is not marked dead. +static bool hasLiveCondCodeDef(MachineInstr *MI) { + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + MachineOperand &MO = MI->getOperand(i); + if (MO.isReg() && MO.isDef() && + MO.getReg() == X86::EFLAGS && !MO.isDead()) { + return true; + } + } + return false; +} + +/// convertToThreeAddress - This method must be implemented by targets that +/// set the M_CONVERTIBLE_TO_3_ADDR flag. When this flag is set, the target +/// may be able to convert a two-address instruction into a true +/// three-address instruction on demand. This allows the X86 target (for +/// example) to convert ADD and SHL instructions into LEA instructions if they +/// would require register copies due to two-addressness. +/// +/// This method returns a null pointer if the transformation cannot be +/// performed, otherwise it returns the new instruction. +/// +MachineInstr * +X86InstrInfo::convertToThreeAddress(MachineFunction::iterator &MFI, + MachineBasicBlock::iterator &MBBI, + LiveVariables *LV) const { + MachineInstr *MI = MBBI; + MachineFunction &MF = *MI->getParent()->getParent(); + // All instructions input are two-addr instructions. Get the known operands. + unsigned Dest = MI->getOperand(0).getReg(); + unsigned Src = MI->getOperand(1).getReg(); + bool isDead = MI->getOperand(0).isDead(); + bool isKill = MI->getOperand(1).isKill(); + + MachineInstr *NewMI = NULL; + // FIXME: 16-bit LEA's are really slow on Athlons, but not bad on P4's. When + // we have better subtarget support, enable the 16-bit LEA generation here. + bool DisableLEA16 = true; + + unsigned MIOpc = MI->getOpcode(); + switch (MIOpc) { + case X86::SHUFPSrri: { + assert(MI->getNumOperands() == 4 && "Unknown shufps instruction!"); + if (!TM.getSubtarget().hasSSE2()) return 0; + + unsigned B = MI->getOperand(1).getReg(); + unsigned C = MI->getOperand(2).getReg(); + if (B != C) return 0; + unsigned A = MI->getOperand(0).getReg(); + unsigned M = MI->getOperand(3).getImm(); + NewMI = BuildMI(MF, MI->getDebugLoc(), get(X86::PSHUFDri)) + .addReg(A, RegState::Define | getDeadRegState(isDead)) + .addReg(B, getKillRegState(isKill)).addImm(M); + break; + } + case X86::SHL64ri: { + assert(MI->getNumOperands() >= 3 && "Unknown shift instruction!"); + // NOTE: LEA doesn't produce flags like shift does, but LLVM never uses + // the flags produced by a shift yet, so this is safe. + unsigned ShAmt = MI->getOperand(2).getImm(); + if (ShAmt == 0 || ShAmt >= 4) return 0; + + NewMI = BuildMI(MF, MI->getDebugLoc(), get(X86::LEA64r)) + .addReg(Dest, RegState::Define | getDeadRegState(isDead)) + .addReg(0).addImm(1 << ShAmt) + .addReg(Src, getKillRegState(isKill)) + .addImm(0); + break; + } + case X86::SHL32ri: { + assert(MI->getNumOperands() >= 3 && "Unknown shift instruction!"); + // NOTE: LEA doesn't produce flags like shift does, but LLVM never uses + // the flags produced by a shift yet, so this is safe. + unsigned ShAmt = MI->getOperand(2).getImm(); + if (ShAmt == 0 || ShAmt >= 4) return 0; + + unsigned Opc = TM.getSubtarget().is64Bit() ? + X86::LEA64_32r : X86::LEA32r; + NewMI = BuildMI(MF, MI->getDebugLoc(), get(Opc)) + .addReg(Dest, RegState::Define | getDeadRegState(isDead)) + .addReg(0).addImm(1 << ShAmt) + .addReg(Src, getKillRegState(isKill)).addImm(0); + break; + } + case X86::SHL16ri: { + assert(MI->getNumOperands() >= 3 && "Unknown shift instruction!"); + // NOTE: LEA doesn't produce flags like shift does, but LLVM never uses + // the flags produced by a shift yet, so this is safe. + unsigned ShAmt = MI->getOperand(2).getImm(); + if (ShAmt == 0 || ShAmt >= 4) return 0; + + if (DisableLEA16) { + // If 16-bit LEA is disabled, use 32-bit LEA via subregisters. + MachineRegisterInfo &RegInfo = MFI->getParent()->getRegInfo(); + unsigned Opc = TM.getSubtarget().is64Bit() + ? X86::LEA64_32r : X86::LEA32r; + unsigned leaInReg = RegInfo.createVirtualRegister(&X86::GR32RegClass); + unsigned leaOutReg = RegInfo.createVirtualRegister(&X86::GR32RegClass); + + // Build and insert into an implicit UNDEF value. This is OK because + // well be shifting and then extracting the lower 16-bits. + BuildMI(*MFI, MBBI, MI->getDebugLoc(), get(X86::IMPLICIT_DEF), leaInReg); + MachineInstr *InsMI = + BuildMI(*MFI, MBBI, MI->getDebugLoc(), get(X86::INSERT_SUBREG),leaInReg) + .addReg(leaInReg) + .addReg(Src, getKillRegState(isKill)) + .addImm(X86::SUBREG_16BIT); + + NewMI = BuildMI(*MFI, MBBI, MI->getDebugLoc(), get(Opc), leaOutReg) + .addReg(0).addImm(1 << ShAmt) + .addReg(leaInReg, RegState::Kill) + .addImm(0); + + MachineInstr *ExtMI = + BuildMI(*MFI, MBBI, MI->getDebugLoc(), get(X86::EXTRACT_SUBREG)) + .addReg(Dest, RegState::Define | getDeadRegState(isDead)) + .addReg(leaOutReg, RegState::Kill) + .addImm(X86::SUBREG_16BIT); + + if (LV) { + // Update live variables + LV->getVarInfo(leaInReg).Kills.push_back(NewMI); + LV->getVarInfo(leaOutReg).Kills.push_back(ExtMI); + if (isKill) + LV->replaceKillInstruction(Src, MI, InsMI); + if (isDead) + LV->replaceKillInstruction(Dest, MI, ExtMI); + } + return ExtMI; + } else { + NewMI = BuildMI(MF, MI->getDebugLoc(), get(X86::LEA16r)) + .addReg(Dest, RegState::Define | getDeadRegState(isDead)) + .addReg(0).addImm(1 << ShAmt) + .addReg(Src, getKillRegState(isKill)) + .addImm(0); + } + break; + } + default: { + // The following opcodes also sets the condition code register(s). Only + // convert them to equivalent lea if the condition code register def's + // are dead! + if (hasLiveCondCodeDef(MI)) + return 0; + + bool is64Bit = TM.getSubtarget().is64Bit(); + switch (MIOpc) { + default: return 0; + case X86::INC64r: + case X86::INC32r: + case X86::INC64_32r: { + assert(MI->getNumOperands() >= 2 && "Unknown inc instruction!"); + unsigned Opc = MIOpc == X86::INC64r ? X86::LEA64r + : (is64Bit ? X86::LEA64_32r : X86::LEA32r); + NewMI = addLeaRegOffset(BuildMI(MF, MI->getDebugLoc(), get(Opc)) + .addReg(Dest, RegState::Define | + getDeadRegState(isDead)), + Src, isKill, 1); + break; + } + case X86::INC16r: + case X86::INC64_16r: + if (DisableLEA16) return 0; + assert(MI->getNumOperands() >= 2 && "Unknown inc instruction!"); + NewMI = addRegOffset(BuildMI(MF, MI->getDebugLoc(), get(X86::LEA16r)) + .addReg(Dest, RegState::Define | + getDeadRegState(isDead)), + Src, isKill, 1); + break; + case X86::DEC64r: + case X86::DEC32r: + case X86::DEC64_32r: { + assert(MI->getNumOperands() >= 2 && "Unknown dec instruction!"); + unsigned Opc = MIOpc == X86::DEC64r ? X86::LEA64r + : (is64Bit ? X86::LEA64_32r : X86::LEA32r); + NewMI = addLeaRegOffset(BuildMI(MF, MI->getDebugLoc(), get(Opc)) + .addReg(Dest, RegState::Define | + getDeadRegState(isDead)), + Src, isKill, -1); + break; + } + case X86::DEC16r: + case X86::DEC64_16r: + if (DisableLEA16) return 0; + assert(MI->getNumOperands() >= 2 && "Unknown dec instruction!"); + NewMI = addRegOffset(BuildMI(MF, MI->getDebugLoc(), get(X86::LEA16r)) + .addReg(Dest, RegState::Define | + getDeadRegState(isDead)), + Src, isKill, -1); + break; + case X86::ADD64rr: + case X86::ADD32rr: { + assert(MI->getNumOperands() >= 3 && "Unknown add instruction!"); + unsigned Opc = MIOpc == X86::ADD64rr ? X86::LEA64r + : (is64Bit ? X86::LEA64_32r : X86::LEA32r); + unsigned Src2 = MI->getOperand(2).getReg(); + bool isKill2 = MI->getOperand(2).isKill(); + NewMI = addRegReg(BuildMI(MF, MI->getDebugLoc(), get(Opc)) + .addReg(Dest, RegState::Define | + getDeadRegState(isDead)), + Src, isKill, Src2, isKill2); + if (LV && isKill2) + LV->replaceKillInstruction(Src2, MI, NewMI); + break; + } + case X86::ADD16rr: { + if (DisableLEA16) return 0; + assert(MI->getNumOperands() >= 3 && "Unknown add instruction!"); + unsigned Src2 = MI->getOperand(2).getReg(); + bool isKill2 = MI->getOperand(2).isKill(); + NewMI = addRegReg(BuildMI(MF, MI->getDebugLoc(), get(X86::LEA16r)) + .addReg(Dest, RegState::Define | + getDeadRegState(isDead)), + Src, isKill, Src2, isKill2); + if (LV && isKill2) + LV->replaceKillInstruction(Src2, MI, NewMI); + break; + } + case X86::ADD64ri32: + case X86::ADD64ri8: + assert(MI->getNumOperands() >= 3 && "Unknown add instruction!"); + if (MI->getOperand(2).isImm()) + NewMI = addLeaRegOffset(BuildMI(MF, MI->getDebugLoc(), get(X86::LEA64r)) + .addReg(Dest, RegState::Define | + getDeadRegState(isDead)), + Src, isKill, MI->getOperand(2).getImm()); + break; + case X86::ADD32ri: + case X86::ADD32ri8: + assert(MI->getNumOperands() >= 3 && "Unknown add instruction!"); + if (MI->getOperand(2).isImm()) { + unsigned Opc = is64Bit ? X86::LEA64_32r : X86::LEA32r; + NewMI = addLeaRegOffset(BuildMI(MF, MI->getDebugLoc(), get(Opc)) + .addReg(Dest, RegState::Define | + getDeadRegState(isDead)), + Src, isKill, MI->getOperand(2).getImm()); + } + break; + case X86::ADD16ri: + case X86::ADD16ri8: + if (DisableLEA16) return 0; + assert(MI->getNumOperands() >= 3 && "Unknown add instruction!"); + if (MI->getOperand(2).isImm()) + NewMI = addRegOffset(BuildMI(MF, MI->getDebugLoc(), get(X86::LEA16r)) + .addReg(Dest, RegState::Define | + getDeadRegState(isDead)), + Src, isKill, MI->getOperand(2).getImm()); + break; + case X86::SHL16ri: + if (DisableLEA16) return 0; + case X86::SHL32ri: + case X86::SHL64ri: { + assert(MI->getNumOperands() >= 3 && MI->getOperand(2).isImm() && + "Unknown shl instruction!"); + unsigned ShAmt = MI->getOperand(2).getImm(); + if (ShAmt == 1 || ShAmt == 2 || ShAmt == 3) { + X86AddressMode AM; + AM.Scale = 1 << ShAmt; + AM.IndexReg = Src; + unsigned Opc = MIOpc == X86::SHL64ri ? X86::LEA64r + : (MIOpc == X86::SHL32ri + ? (is64Bit ? X86::LEA64_32r : X86::LEA32r) : X86::LEA16r); + NewMI = addFullAddress(BuildMI(MF, MI->getDebugLoc(), get(Opc)) + .addReg(Dest, RegState::Define | + getDeadRegState(isDead)), AM); + if (isKill) + NewMI->getOperand(3).setIsKill(true); + } + break; + } + } + } + } + + if (!NewMI) return 0; + + if (LV) { // Update live variables + if (isKill) + LV->replaceKillInstruction(Src, MI, NewMI); + if (isDead) + LV->replaceKillInstruction(Dest, MI, NewMI); + } + + MFI->insert(MBBI, NewMI); // Insert the new inst + return NewMI; +} + +/// commuteInstruction - We have a few instructions that must be hacked on to +/// commute them. +/// +MachineInstr * +X86InstrInfo::commuteInstruction(MachineInstr *MI, bool NewMI) const { + switch (MI->getOpcode()) { + case X86::SHRD16rri8: // A = SHRD16rri8 B, C, I -> A = SHLD16rri8 C, B, (16-I) + case X86::SHLD16rri8: // A = SHLD16rri8 B, C, I -> A = SHRD16rri8 C, B, (16-I) + case X86::SHRD32rri8: // A = SHRD32rri8 B, C, I -> A = SHLD32rri8 C, B, (32-I) + case X86::SHLD32rri8: // A = SHLD32rri8 B, C, I -> A = SHRD32rri8 C, B, (32-I) + case X86::SHRD64rri8: // A = SHRD64rri8 B, C, I -> A = SHLD64rri8 C, B, (64-I) + case X86::SHLD64rri8:{// A = SHLD64rri8 B, C, I -> A = SHRD64rri8 C, B, (64-I) + unsigned Opc; + unsigned Size; + switch (MI->getOpcode()) { + default: llvm_unreachable("Unreachable!"); + case X86::SHRD16rri8: Size = 16; Opc = X86::SHLD16rri8; break; + case X86::SHLD16rri8: Size = 16; Opc = X86::SHRD16rri8; break; + case X86::SHRD32rri8: Size = 32; Opc = X86::SHLD32rri8; break; + case X86::SHLD32rri8: Size = 32; Opc = X86::SHRD32rri8; break; + case X86::SHRD64rri8: Size = 64; Opc = X86::SHLD64rri8; break; + case X86::SHLD64rri8: Size = 64; Opc = X86::SHRD64rri8; break; + } + unsigned Amt = MI->getOperand(3).getImm(); + if (NewMI) { + MachineFunction &MF = *MI->getParent()->getParent(); + MI = MF.CloneMachineInstr(MI); + NewMI = false; + } + MI->setDesc(get(Opc)); + MI->getOperand(3).setImm(Size-Amt); + return TargetInstrInfoImpl::commuteInstruction(MI, NewMI); + } + case X86::CMOVB16rr: + case X86::CMOVB32rr: + case X86::CMOVB64rr: + case X86::CMOVAE16rr: + case X86::CMOVAE32rr: + case X86::CMOVAE64rr: + case X86::CMOVE16rr: + case X86::CMOVE32rr: + case X86::CMOVE64rr: + case X86::CMOVNE16rr: + case X86::CMOVNE32rr: + case X86::CMOVNE64rr: + case X86::CMOVBE16rr: + case X86::CMOVBE32rr: + case X86::CMOVBE64rr: + case X86::CMOVA16rr: + case X86::CMOVA32rr: + case X86::CMOVA64rr: + case X86::CMOVL16rr: + case X86::CMOVL32rr: + case X86::CMOVL64rr: + case X86::CMOVGE16rr: + case X86::CMOVGE32rr: + case X86::CMOVGE64rr: + case X86::CMOVLE16rr: + case X86::CMOVLE32rr: + case X86::CMOVLE64rr: + case X86::CMOVG16rr: + case X86::CMOVG32rr: + case X86::CMOVG64rr: + case X86::CMOVS16rr: + case X86::CMOVS32rr: + case X86::CMOVS64rr: + case X86::CMOVNS16rr: + case X86::CMOVNS32rr: + case X86::CMOVNS64rr: + case X86::CMOVP16rr: + case X86::CMOVP32rr: + case X86::CMOVP64rr: + case X86::CMOVNP16rr: + case X86::CMOVNP32rr: + case X86::CMOVNP64rr: + case X86::CMOVO16rr: + case X86::CMOVO32rr: + case X86::CMOVO64rr: + case X86::CMOVNO16rr: + case X86::CMOVNO32rr: + case X86::CMOVNO64rr: { + unsigned Opc = 0; + switch (MI->getOpcode()) { + default: break; + case X86::CMOVB16rr: Opc = X86::CMOVAE16rr; break; + case X86::CMOVB32rr: Opc = X86::CMOVAE32rr; break; + case X86::CMOVB64rr: Opc = X86::CMOVAE64rr; break; + case X86::CMOVAE16rr: Opc = X86::CMOVB16rr; break; + case X86::CMOVAE32rr: Opc = X86::CMOVB32rr; break; + case X86::CMOVAE64rr: Opc = X86::CMOVB64rr; break; + case X86::CMOVE16rr: Opc = X86::CMOVNE16rr; break; + case X86::CMOVE32rr: Opc = X86::CMOVNE32rr; break; + case X86::CMOVE64rr: Opc = X86::CMOVNE64rr; break; + case X86::CMOVNE16rr: Opc = X86::CMOVE16rr; break; + case X86::CMOVNE32rr: Opc = X86::CMOVE32rr; break; + case X86::CMOVNE64rr: Opc = X86::CMOVE64rr; break; + case X86::CMOVBE16rr: Opc = X86::CMOVA16rr; break; + case X86::CMOVBE32rr: Opc = X86::CMOVA32rr; break; + case X86::CMOVBE64rr: Opc = X86::CMOVA64rr; break; + case X86::CMOVA16rr: Opc = X86::CMOVBE16rr; break; + case X86::CMOVA32rr: Opc = X86::CMOVBE32rr; break; + case X86::CMOVA64rr: Opc = X86::CMOVBE64rr; break; + case X86::CMOVL16rr: Opc = X86::CMOVGE16rr; break; + case X86::CMOVL32rr: Opc = X86::CMOVGE32rr; break; + case X86::CMOVL64rr: Opc = X86::CMOVGE64rr; break; + case X86::CMOVGE16rr: Opc = X86::CMOVL16rr; break; + case X86::CMOVGE32rr: Opc = X86::CMOVL32rr; break; + case X86::CMOVGE64rr: Opc = X86::CMOVL64rr; break; + case X86::CMOVLE16rr: Opc = X86::CMOVG16rr; break; + case X86::CMOVLE32rr: Opc = X86::CMOVG32rr; break; + case X86::CMOVLE64rr: Opc = X86::CMOVG64rr; break; + case X86::CMOVG16rr: Opc = X86::CMOVLE16rr; break; + case X86::CMOVG32rr: Opc = X86::CMOVLE32rr; break; + case X86::CMOVG64rr: Opc = X86::CMOVLE64rr; break; + case X86::CMOVS16rr: Opc = X86::CMOVNS16rr; break; + case X86::CMOVS32rr: Opc = X86::CMOVNS32rr; break; + case X86::CMOVS64rr: Opc = X86::CMOVNS64rr; break; + case X86::CMOVNS16rr: Opc = X86::CMOVS16rr; break; + case X86::CMOVNS32rr: Opc = X86::CMOVS32rr; break; + case X86::CMOVNS64rr: Opc = X86::CMOVS64rr; break; + case X86::CMOVP16rr: Opc = X86::CMOVNP16rr; break; + case X86::CMOVP32rr: Opc = X86::CMOVNP32rr; break; + case X86::CMOVP64rr: Opc = X86::CMOVNP64rr; break; + case X86::CMOVNP16rr: Opc = X86::CMOVP16rr; break; + case X86::CMOVNP32rr: Opc = X86::CMOVP32rr; break; + case X86::CMOVNP64rr: Opc = X86::CMOVP64rr; break; + case X86::CMOVO16rr: Opc = X86::CMOVNO16rr; break; + case X86::CMOVO32rr: Opc = X86::CMOVNO32rr; break; + case X86::CMOVO64rr: Opc = X86::CMOVNO64rr; break; + case X86::CMOVNO16rr: Opc = X86::CMOVO16rr; break; + case X86::CMOVNO32rr: Opc = X86::CMOVO32rr; break; + case X86::CMOVNO64rr: Opc = X86::CMOVO64rr; break; + } + if (NewMI) { + MachineFunction &MF = *MI->getParent()->getParent(); + MI = MF.CloneMachineInstr(MI); + NewMI = false; + } + MI->setDesc(get(Opc)); + // Fallthrough intended. + } + default: + return TargetInstrInfoImpl::commuteInstruction(MI, NewMI); + } +} + +static X86::CondCode GetCondFromBranchOpc(unsigned BrOpc) { + switch (BrOpc) { + default: return X86::COND_INVALID; + case X86::JE: return X86::COND_E; + case X86::JNE: return X86::COND_NE; + case X86::JL: return X86::COND_L; + case X86::JLE: return X86::COND_LE; + case X86::JG: return X86::COND_G; + case X86::JGE: return X86::COND_GE; + case X86::JB: return X86::COND_B; + case X86::JBE: return X86::COND_BE; + case X86::JA: return X86::COND_A; + case X86::JAE: return X86::COND_AE; + case X86::JS: return X86::COND_S; + case X86::JNS: return X86::COND_NS; + case X86::JP: return X86::COND_P; + case X86::JNP: return X86::COND_NP; + case X86::JO: return X86::COND_O; + case X86::JNO: return X86::COND_NO; + } +} + +unsigned X86::GetCondBranchFromCond(X86::CondCode CC) { + switch (CC) { + default: llvm_unreachable("Illegal condition code!"); + case X86::COND_E: return X86::JE; + case X86::COND_NE: return X86::JNE; + case X86::COND_L: return X86::JL; + case X86::COND_LE: return X86::JLE; + case X86::COND_G: return X86::JG; + case X86::COND_GE: return X86::JGE; + case X86::COND_B: return X86::JB; + case X86::COND_BE: return X86::JBE; + case X86::COND_A: return X86::JA; + case X86::COND_AE: return X86::JAE; + case X86::COND_S: return X86::JS; + case X86::COND_NS: return X86::JNS; + case X86::COND_P: return X86::JP; + case X86::COND_NP: return X86::JNP; + case X86::COND_O: return X86::JO; + case X86::COND_NO: return X86::JNO; + } +} + +/// GetOppositeBranchCondition - Return the inverse of the specified condition, +/// e.g. turning COND_E to COND_NE. +X86::CondCode X86::GetOppositeBranchCondition(X86::CondCode CC) { + switch (CC) { + default: llvm_unreachable("Illegal condition code!"); + case X86::COND_E: return X86::COND_NE; + case X86::COND_NE: return X86::COND_E; + case X86::COND_L: return X86::COND_GE; + case X86::COND_LE: return X86::COND_G; + case X86::COND_G: return X86::COND_LE; + case X86::COND_GE: return X86::COND_L; + case X86::COND_B: return X86::COND_AE; + case X86::COND_BE: return X86::COND_A; + case X86::COND_A: return X86::COND_BE; + case X86::COND_AE: return X86::COND_B; + case X86::COND_S: return X86::COND_NS; + case X86::COND_NS: return X86::COND_S; + case X86::COND_P: return X86::COND_NP; + case X86::COND_NP: return X86::COND_P; + case X86::COND_O: return X86::COND_NO; + case X86::COND_NO: return X86::COND_O; + } +} + +bool X86InstrInfo::isUnpredicatedTerminator(const MachineInstr *MI) const { + const TargetInstrDesc &TID = MI->getDesc(); + if (!TID.isTerminator()) return false; + + // Conditional branch is a special case. + if (TID.isBranch() && !TID.isBarrier()) + return true; + if (!TID.isPredicable()) + return true; + return !isPredicated(MI); +} + +// For purposes of branch analysis do not count FP_REG_KILL as a terminator. +static bool isBrAnalysisUnpredicatedTerminator(const MachineInstr *MI, + const X86InstrInfo &TII) { + if (MI->getOpcode() == X86::FP_REG_KILL) + return false; + return TII.isUnpredicatedTerminator(MI); +} + +bool X86InstrInfo::AnalyzeBranch(MachineBasicBlock &MBB, + MachineBasicBlock *&TBB, + MachineBasicBlock *&FBB, + SmallVectorImpl &Cond, + bool AllowModify) const { + // Start from the bottom of the block and work up, examining the + // terminator instructions. + MachineBasicBlock::iterator I = MBB.end(); + while (I != MBB.begin()) { + --I; + // Working from the bottom, when we see a non-terminator + // instruction, we're done. + if (!isBrAnalysisUnpredicatedTerminator(I, *this)) + break; + // A terminator that isn't a branch can't easily be handled + // by this analysis. + if (!I->getDesc().isBranch()) + return true; + // Handle unconditional branches. + if (I->getOpcode() == X86::JMP) { + if (!AllowModify) { + TBB = I->getOperand(0).getMBB(); + continue; + } + + // If the block has any instructions after a JMP, delete them. + while (next(I) != MBB.end()) + next(I)->eraseFromParent(); + Cond.clear(); + FBB = 0; + // Delete the JMP if it's equivalent to a fall-through. + if (MBB.isLayoutSuccessor(I->getOperand(0).getMBB())) { + TBB = 0; + I->eraseFromParent(); + I = MBB.end(); + continue; + } + // TBB is used to indicate the unconditinal destination. + TBB = I->getOperand(0).getMBB(); + continue; + } + // Handle conditional branches. + X86::CondCode BranchCode = GetCondFromBranchOpc(I->getOpcode()); + if (BranchCode == X86::COND_INVALID) + return true; // Can't handle indirect branch. + // Working from the bottom, handle the first conditional branch. + if (Cond.empty()) { + FBB = TBB; + TBB = I->getOperand(0).getMBB(); + Cond.push_back(MachineOperand::CreateImm(BranchCode)); + continue; + } + // Handle subsequent conditional branches. Only handle the case + // where all conditional branches branch to the same destination + // and their condition opcodes fit one of the special + // multi-branch idioms. + assert(Cond.size() == 1); + assert(TBB); + // Only handle the case where all conditional branches branch to + // the same destination. + if (TBB != I->getOperand(0).getMBB()) + return true; + X86::CondCode OldBranchCode = (X86::CondCode)Cond[0].getImm(); + // If the conditions are the same, we can leave them alone. + if (OldBranchCode == BranchCode) + continue; + // If they differ, see if they fit one of the known patterns. + // Theoretically we could handle more patterns here, but + // we shouldn't expect to see them if instruction selection + // has done a reasonable job. + if ((OldBranchCode == X86::COND_NP && + BranchCode == X86::COND_E) || + (OldBranchCode == X86::COND_E && + BranchCode == X86::COND_NP)) + BranchCode = X86::COND_NP_OR_E; + else if ((OldBranchCode == X86::COND_P && + BranchCode == X86::COND_NE) || + (OldBranchCode == X86::COND_NE && + BranchCode == X86::COND_P)) + BranchCode = X86::COND_NE_OR_P; + else + return true; + // Update the MachineOperand. + Cond[0].setImm(BranchCode); + } + + return false; +} + +unsigned X86InstrInfo::RemoveBranch(MachineBasicBlock &MBB) const { + MachineBasicBlock::iterator I = MBB.end(); + unsigned Count = 0; + + while (I != MBB.begin()) { + --I; + if (I->getOpcode() != X86::JMP && + GetCondFromBranchOpc(I->getOpcode()) == X86::COND_INVALID) + break; + // Remove the branch. + I->eraseFromParent(); + I = MBB.end(); + ++Count; + } + + return Count; +} + +unsigned +X86InstrInfo::InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, + MachineBasicBlock *FBB, + const SmallVectorImpl &Cond) const { + // FIXME this should probably have a DebugLoc operand + DebugLoc dl = DebugLoc::getUnknownLoc(); + // Shouldn't be a fall through. + assert(TBB && "InsertBranch must not be told to insert a fallthrough"); + assert((Cond.size() == 1 || Cond.size() == 0) && + "X86 branch conditions have one component!"); + + if (Cond.empty()) { + // Unconditional branch? + assert(!FBB && "Unconditional branch with multiple successors!"); + BuildMI(&MBB, dl, get(X86::JMP)).addMBB(TBB); + return 1; + } + + // Conditional branch. + unsigned Count = 0; + X86::CondCode CC = (X86::CondCode)Cond[0].getImm(); + switch (CC) { + case X86::COND_NP_OR_E: + // Synthesize NP_OR_E with two branches. + BuildMI(&MBB, dl, get(X86::JNP)).addMBB(TBB); + ++Count; + BuildMI(&MBB, dl, get(X86::JE)).addMBB(TBB); + ++Count; + break; + case X86::COND_NE_OR_P: + // Synthesize NE_OR_P with two branches. + BuildMI(&MBB, dl, get(X86::JNE)).addMBB(TBB); + ++Count; + BuildMI(&MBB, dl, get(X86::JP)).addMBB(TBB); + ++Count; + break; + default: { + unsigned Opc = GetCondBranchFromCond(CC); + BuildMI(&MBB, dl, get(Opc)).addMBB(TBB); + ++Count; + } + } + if (FBB) { + // Two-way Conditional branch. Insert the second branch. + BuildMI(&MBB, dl, get(X86::JMP)).addMBB(FBB); + ++Count; + } + return Count; +} + +/// isHReg - Test if the given register is a physical h register. +static bool isHReg(unsigned Reg) { + return X86::GR8_ABCD_HRegClass.contains(Reg); +} + +bool X86InstrInfo::copyRegToReg(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + unsigned DestReg, unsigned SrcReg, + const TargetRegisterClass *DestRC, + const TargetRegisterClass *SrcRC) const { + DebugLoc DL = DebugLoc::getUnknownLoc(); + if (MI != MBB.end()) DL = MI->getDebugLoc(); + + // Determine if DstRC and SrcRC have a common superclass in common. + const TargetRegisterClass *CommonRC = DestRC; + if (DestRC == SrcRC) + /* Source and destination have the same register class. */; + else if (CommonRC->hasSuperClass(SrcRC)) + CommonRC = SrcRC; + else if (!DestRC->hasSubClass(SrcRC)) { + // Neither of GR64_NOREX or GR64_NOSP is a superclass of the other, + // but we want to copy then as GR64. Similarly, for GR32_NOREX and + // GR32_NOSP, copy as GR32. + if (SrcRC->hasSuperClass(&X86::GR64RegClass) && + DestRC->hasSuperClass(&X86::GR64RegClass)) + CommonRC = &X86::GR64RegClass; + else if (SrcRC->hasSuperClass(&X86::GR32RegClass) && + DestRC->hasSuperClass(&X86::GR32RegClass)) + CommonRC = &X86::GR32RegClass; + else + CommonRC = 0; + } + + if (CommonRC) { + unsigned Opc; + if (CommonRC == &X86::GR64RegClass || CommonRC == &X86::GR64_NOSPRegClass) { + Opc = X86::MOV64rr; + } else if (CommonRC == &X86::GR32RegClass || + CommonRC == &X86::GR32_NOSPRegClass) { + Opc = X86::MOV32rr; + } else if (CommonRC == &X86::GR16RegClass) { + Opc = X86::MOV16rr; + } else if (CommonRC == &X86::GR8RegClass) { + // Copying to or from a physical H register on x86-64 requires a NOREX + // move. Otherwise use a normal move. + if ((isHReg(DestReg) || isHReg(SrcReg)) && + TM.getSubtarget().is64Bit()) + Opc = X86::MOV8rr_NOREX; + else + Opc = X86::MOV8rr; + } else if (CommonRC == &X86::GR64_ABCDRegClass) { + Opc = X86::MOV64rr; + } else if (CommonRC == &X86::GR32_ABCDRegClass) { + Opc = X86::MOV32rr; + } else if (CommonRC == &X86::GR16_ABCDRegClass) { + Opc = X86::MOV16rr; + } else if (CommonRC == &X86::GR8_ABCD_LRegClass) { + Opc = X86::MOV8rr; + } else if (CommonRC == &X86::GR8_ABCD_HRegClass) { + if (TM.getSubtarget().is64Bit()) + Opc = X86::MOV8rr_NOREX; + else + Opc = X86::MOV8rr; + } else if (CommonRC == &X86::GR64_NOREXRegClass || + CommonRC == &X86::GR64_NOREX_NOSPRegClass) { + Opc = X86::MOV64rr; + } else if (CommonRC == &X86::GR32_NOREXRegClass) { + Opc = X86::MOV32rr; + } else if (CommonRC == &X86::GR16_NOREXRegClass) { + Opc = X86::MOV16rr; + } else if (CommonRC == &X86::GR8_NOREXRegClass) { + Opc = X86::MOV8rr; + } else if (CommonRC == &X86::RFP32RegClass) { + Opc = X86::MOV_Fp3232; + } else if (CommonRC == &X86::RFP64RegClass || CommonRC == &X86::RSTRegClass) { + Opc = X86::MOV_Fp6464; + } else if (CommonRC == &X86::RFP80RegClass) { + Opc = X86::MOV_Fp8080; + } else if (CommonRC == &X86::FR32RegClass) { + Opc = X86::FsMOVAPSrr; + } else if (CommonRC == &X86::FR64RegClass) { + Opc = X86::FsMOVAPDrr; + } else if (CommonRC == &X86::VR128RegClass) { + Opc = X86::MOVAPSrr; + } else if (CommonRC == &X86::VR64RegClass) { + Opc = X86::MMX_MOVQ64rr; + } else { + return false; + } + BuildMI(MBB, MI, DL, get(Opc), DestReg).addReg(SrcReg); + return true; + } + + // Moving EFLAGS to / from another register requires a push and a pop. + if (SrcRC == &X86::CCRRegClass) { + if (SrcReg != X86::EFLAGS) + return false; + if (DestRC == &X86::GR64RegClass || DestRC == &X86::GR64_NOSPRegClass) { + BuildMI(MBB, MI, DL, get(X86::PUSHFQ)); + BuildMI(MBB, MI, DL, get(X86::POP64r), DestReg); + return true; + } else if (DestRC == &X86::GR32RegClass || + DestRC == &X86::GR32_NOSPRegClass) { + BuildMI(MBB, MI, DL, get(X86::PUSHFD)); + BuildMI(MBB, MI, DL, get(X86::POP32r), DestReg); + return true; + } + } else if (DestRC == &X86::CCRRegClass) { + if (DestReg != X86::EFLAGS) + return false; + if (SrcRC == &X86::GR64RegClass || DestRC == &X86::GR64_NOSPRegClass) { + BuildMI(MBB, MI, DL, get(X86::PUSH64r)).addReg(SrcReg); + BuildMI(MBB, MI, DL, get(X86::POPFQ)); + return true; + } else if (SrcRC == &X86::GR32RegClass || + DestRC == &X86::GR32_NOSPRegClass) { + BuildMI(MBB, MI, DL, get(X86::PUSH32r)).addReg(SrcReg); + BuildMI(MBB, MI, DL, get(X86::POPFD)); + return true; + } + } + + // Moving from ST(0) turns into FpGET_ST0_32 etc. + if (SrcRC == &X86::RSTRegClass) { + // Copying from ST(0)/ST(1). + if (SrcReg != X86::ST0 && SrcReg != X86::ST1) + // Can only copy from ST(0)/ST(1) right now + return false; + bool isST0 = SrcReg == X86::ST0; + unsigned Opc; + if (DestRC == &X86::RFP32RegClass) + Opc = isST0 ? X86::FpGET_ST0_32 : X86::FpGET_ST1_32; + else if (DestRC == &X86::RFP64RegClass) + Opc = isST0 ? X86::FpGET_ST0_64 : X86::FpGET_ST1_64; + else { + if (DestRC != &X86::RFP80RegClass) + return false; + Opc = isST0 ? X86::FpGET_ST0_80 : X86::FpGET_ST1_80; + } + BuildMI(MBB, MI, DL, get(Opc), DestReg); + return true; + } + + // Moving to ST(0) turns into FpSET_ST0_32 etc. + if (DestRC == &X86::RSTRegClass) { + // Copying to ST(0) / ST(1). + if (DestReg != X86::ST0 && DestReg != X86::ST1) + // Can only copy to TOS right now + return false; + bool isST0 = DestReg == X86::ST0; + unsigned Opc; + if (SrcRC == &X86::RFP32RegClass) + Opc = isST0 ? X86::FpSET_ST0_32 : X86::FpSET_ST1_32; + else if (SrcRC == &X86::RFP64RegClass) + Opc = isST0 ? X86::FpSET_ST0_64 : X86::FpSET_ST1_64; + else { + if (SrcRC != &X86::RFP80RegClass) + return false; + Opc = isST0 ? X86::FpSET_ST0_80 : X86::FpSET_ST1_80; + } + BuildMI(MBB, MI, DL, get(Opc)).addReg(SrcReg); + return true; + } + + // Not yet supported! + return false; +} + +static unsigned getStoreRegOpcode(unsigned SrcReg, + const TargetRegisterClass *RC, + bool isStackAligned, + TargetMachine &TM) { + unsigned Opc = 0; + if (RC == &X86::GR64RegClass || RC == &X86::GR64_NOSPRegClass) { + Opc = X86::MOV64mr; + } else if (RC == &X86::GR32RegClass || RC == &X86::GR32_NOSPRegClass) { + Opc = X86::MOV32mr; + } else if (RC == &X86::GR16RegClass) { + Opc = X86::MOV16mr; + } else if (RC == &X86::GR8RegClass) { + // Copying to or from a physical H register on x86-64 requires a NOREX + // move. Otherwise use a normal move. + if (isHReg(SrcReg) && + TM.getSubtarget().is64Bit()) + Opc = X86::MOV8mr_NOREX; + else + Opc = X86::MOV8mr; + } else if (RC == &X86::GR64_ABCDRegClass) { + Opc = X86::MOV64mr; + } else if (RC == &X86::GR32_ABCDRegClass) { + Opc = X86::MOV32mr; + } else if (RC == &X86::GR16_ABCDRegClass) { + Opc = X86::MOV16mr; + } else if (RC == &X86::GR8_ABCD_LRegClass) { + Opc = X86::MOV8mr; + } else if (RC == &X86::GR8_ABCD_HRegClass) { + if (TM.getSubtarget().is64Bit()) + Opc = X86::MOV8mr_NOREX; + else + Opc = X86::MOV8mr; + } else if (RC == &X86::GR64_NOREXRegClass || + RC == &X86::GR64_NOREX_NOSPRegClass) { + Opc = X86::MOV64mr; + } else if (RC == &X86::GR32_NOREXRegClass) { + Opc = X86::MOV32mr; + } else if (RC == &X86::GR16_NOREXRegClass) { + Opc = X86::MOV16mr; + } else if (RC == &X86::GR8_NOREXRegClass) { + Opc = X86::MOV8mr; + } else if (RC == &X86::RFP80RegClass) { + Opc = X86::ST_FpP80m; // pops + } else if (RC == &X86::RFP64RegClass) { + Opc = X86::ST_Fp64m; + } else if (RC == &X86::RFP32RegClass) { + Opc = X86::ST_Fp32m; + } else if (RC == &X86::FR32RegClass) { + Opc = X86::MOVSSmr; + } else if (RC == &X86::FR64RegClass) { + Opc = X86::MOVSDmr; + } else if (RC == &X86::VR128RegClass) { + // If stack is realigned we can use aligned stores. + Opc = isStackAligned ? X86::MOVAPSmr : X86::MOVUPSmr; + } else if (RC == &X86::VR64RegClass) { + Opc = X86::MMX_MOVQ64mr; + } else { + llvm_unreachable("Unknown regclass"); + } + + return Opc; +} + +void X86InstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + unsigned SrcReg, bool isKill, int FrameIdx, + const TargetRegisterClass *RC) const { + const MachineFunction &MF = *MBB.getParent(); + bool isAligned = (RI.getStackAlignment() >= 16) || + RI.needsStackRealignment(MF); + unsigned Opc = getStoreRegOpcode(SrcReg, RC, isAligned, TM); + DebugLoc DL = DebugLoc::getUnknownLoc(); + if (MI != MBB.end()) DL = MI->getDebugLoc(); + addFrameReference(BuildMI(MBB, MI, DL, get(Opc)), FrameIdx) + .addReg(SrcReg, getKillRegState(isKill)); +} + +void X86InstrInfo::storeRegToAddr(MachineFunction &MF, unsigned SrcReg, + bool isKill, + SmallVectorImpl &Addr, + const TargetRegisterClass *RC, + MachineInstr::mmo_iterator MMOBegin, + MachineInstr::mmo_iterator MMOEnd, + SmallVectorImpl &NewMIs) const { + bool isAligned = (*MMOBegin)->getAlignment() >= 16; + unsigned Opc = getStoreRegOpcode(SrcReg, RC, isAligned, TM); + DebugLoc DL = DebugLoc::getUnknownLoc(); + MachineInstrBuilder MIB = BuildMI(MF, DL, get(Opc)); + for (unsigned i = 0, e = Addr.size(); i != e; ++i) + MIB.addOperand(Addr[i]); + MIB.addReg(SrcReg, getKillRegState(isKill)); + (*MIB).setMemRefs(MMOBegin, MMOEnd); + NewMIs.push_back(MIB); +} + +static unsigned getLoadRegOpcode(unsigned DestReg, + const TargetRegisterClass *RC, + bool isStackAligned, + const TargetMachine &TM) { + unsigned Opc = 0; + if (RC == &X86::GR64RegClass || RC == &X86::GR64_NOSPRegClass) { + Opc = X86::MOV64rm; + } else if (RC == &X86::GR32RegClass || RC == &X86::GR32_NOSPRegClass) { + Opc = X86::MOV32rm; + } else if (RC == &X86::GR16RegClass) { + Opc = X86::MOV16rm; + } else if (RC == &X86::GR8RegClass) { + // Copying to or from a physical H register on x86-64 requires a NOREX + // move. Otherwise use a normal move. + if (isHReg(DestReg) && + TM.getSubtarget().is64Bit()) + Opc = X86::MOV8rm_NOREX; + else + Opc = X86::MOV8rm; + } else if (RC == &X86::GR64_ABCDRegClass) { + Opc = X86::MOV64rm; + } else if (RC == &X86::GR32_ABCDRegClass) { + Opc = X86::MOV32rm; + } else if (RC == &X86::GR16_ABCDRegClass) { + Opc = X86::MOV16rm; + } else if (RC == &X86::GR8_ABCD_LRegClass) { + Opc = X86::MOV8rm; + } else if (RC == &X86::GR8_ABCD_HRegClass) { + if (TM.getSubtarget().is64Bit()) + Opc = X86::MOV8rm_NOREX; + else + Opc = X86::MOV8rm; + } else if (RC == &X86::GR64_NOREXRegClass || + RC == &X86::GR64_NOREX_NOSPRegClass) { + Opc = X86::MOV64rm; + } else if (RC == &X86::GR32_NOREXRegClass) { + Opc = X86::MOV32rm; + } else if (RC == &X86::GR16_NOREXRegClass) { + Opc = X86::MOV16rm; + } else if (RC == &X86::GR8_NOREXRegClass) { + Opc = X86::MOV8rm; + } else if (RC == &X86::RFP80RegClass) { + Opc = X86::LD_Fp80m; + } else if (RC == &X86::RFP64RegClass) { + Opc = X86::LD_Fp64m; + } else if (RC == &X86::RFP32RegClass) { + Opc = X86::LD_Fp32m; + } else if (RC == &X86::FR32RegClass) { + Opc = X86::MOVSSrm; + } else if (RC == &X86::FR64RegClass) { + Opc = X86::MOVSDrm; + } else if (RC == &X86::VR128RegClass) { + // If stack is realigned we can use aligned loads. + Opc = isStackAligned ? X86::MOVAPSrm : X86::MOVUPSrm; + } else if (RC == &X86::VR64RegClass) { + Opc = X86::MMX_MOVQ64rm; + } else { + llvm_unreachable("Unknown regclass"); + } + + return Opc; +} + +void X86InstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + unsigned DestReg, int FrameIdx, + const TargetRegisterClass *RC) const{ + const MachineFunction &MF = *MBB.getParent(); + bool isAligned = (RI.getStackAlignment() >= 16) || + RI.needsStackRealignment(MF); + unsigned Opc = getLoadRegOpcode(DestReg, RC, isAligned, TM); + DebugLoc DL = DebugLoc::getUnknownLoc(); + if (MI != MBB.end()) DL = MI->getDebugLoc(); + addFrameReference(BuildMI(MBB, MI, DL, get(Opc), DestReg), FrameIdx); +} + +void X86InstrInfo::loadRegFromAddr(MachineFunction &MF, unsigned DestReg, + SmallVectorImpl &Addr, + const TargetRegisterClass *RC, + MachineInstr::mmo_iterator MMOBegin, + MachineInstr::mmo_iterator MMOEnd, + SmallVectorImpl &NewMIs) const { + bool isAligned = (*MMOBegin)->getAlignment() >= 16; + unsigned Opc = getLoadRegOpcode(DestReg, RC, isAligned, TM); + DebugLoc DL = DebugLoc::getUnknownLoc(); + MachineInstrBuilder MIB = BuildMI(MF, DL, get(Opc), DestReg); + for (unsigned i = 0, e = Addr.size(); i != e; ++i) + MIB.addOperand(Addr[i]); + (*MIB).setMemRefs(MMOBegin, MMOEnd); + NewMIs.push_back(MIB); +} + +bool X86InstrInfo::spillCalleeSavedRegisters(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + const std::vector &CSI) const { + if (CSI.empty()) + return false; + + DebugLoc DL = DebugLoc::getUnknownLoc(); + if (MI != MBB.end()) DL = MI->getDebugLoc(); + + bool is64Bit = TM.getSubtarget().is64Bit(); + bool isWin64 = TM.getSubtarget().isTargetWin64(); + unsigned SlotSize = is64Bit ? 8 : 4; + + MachineFunction &MF = *MBB.getParent(); + unsigned FPReg = RI.getFrameRegister(MF); + X86MachineFunctionInfo *X86FI = MF.getInfo(); + unsigned CalleeFrameSize = 0; + + unsigned Opc = is64Bit ? X86::PUSH64r : X86::PUSH32r; + for (unsigned i = CSI.size(); i != 0; --i) { + unsigned Reg = CSI[i-1].getReg(); + const TargetRegisterClass *RegClass = CSI[i-1].getRegClass(); + // Add the callee-saved register as live-in. It's killed at the spill. + MBB.addLiveIn(Reg); + if (Reg == FPReg) + // X86RegisterInfo::emitPrologue will handle spilling of frame register. + continue; + if (RegClass != &X86::VR128RegClass && !isWin64) { + CalleeFrameSize += SlotSize; + BuildMI(MBB, MI, DL, get(Opc)).addReg(Reg, RegState::Kill); + } else { + storeRegToStackSlot(MBB, MI, Reg, true, CSI[i-1].getFrameIdx(), RegClass); + } + } + + X86FI->setCalleeSavedFrameSize(CalleeFrameSize); + return true; +} + +bool X86InstrInfo::restoreCalleeSavedRegisters(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + const std::vector &CSI) const { + if (CSI.empty()) + return false; + + DebugLoc DL = DebugLoc::getUnknownLoc(); + if (MI != MBB.end()) DL = MI->getDebugLoc(); + + MachineFunction &MF = *MBB.getParent(); + unsigned FPReg = RI.getFrameRegister(MF); + bool is64Bit = TM.getSubtarget().is64Bit(); + bool isWin64 = TM.getSubtarget().isTargetWin64(); + unsigned Opc = is64Bit ? X86::POP64r : X86::POP32r; + for (unsigned i = 0, e = CSI.size(); i != e; ++i) { + unsigned Reg = CSI[i].getReg(); + if (Reg == FPReg) + // X86RegisterInfo::emitEpilogue will handle restoring of frame register. + continue; + const TargetRegisterClass *RegClass = CSI[i].getRegClass(); + if (RegClass != &X86::VR128RegClass && !isWin64) { + BuildMI(MBB, MI, DL, get(Opc), Reg); + } else { + loadRegFromStackSlot(MBB, MI, Reg, CSI[i].getFrameIdx(), RegClass); + } + } + return true; +} + +static MachineInstr *FuseTwoAddrInst(MachineFunction &MF, unsigned Opcode, + const SmallVectorImpl &MOs, + MachineInstr *MI, + const TargetInstrInfo &TII) { + // Create the base instruction with the memory operand as the first part. + MachineInstr *NewMI = MF.CreateMachineInstr(TII.get(Opcode), + MI->getDebugLoc(), true); + MachineInstrBuilder MIB(NewMI); + unsigned NumAddrOps = MOs.size(); + for (unsigned i = 0; i != NumAddrOps; ++i) + MIB.addOperand(MOs[i]); + if (NumAddrOps < 4) // FrameIndex only + addOffset(MIB, 0); + + // Loop over the rest of the ri operands, converting them over. + unsigned NumOps = MI->getDesc().getNumOperands()-2; + for (unsigned i = 0; i != NumOps; ++i) { + MachineOperand &MO = MI->getOperand(i+2); + MIB.addOperand(MO); + } + for (unsigned i = NumOps+2, e = MI->getNumOperands(); i != e; ++i) { + MachineOperand &MO = MI->getOperand(i); + MIB.addOperand(MO); + } + return MIB; +} + +static MachineInstr *FuseInst(MachineFunction &MF, + unsigned Opcode, unsigned OpNo, + const SmallVectorImpl &MOs, + MachineInstr *MI, const TargetInstrInfo &TII) { + MachineInstr *NewMI = MF.CreateMachineInstr(TII.get(Opcode), + MI->getDebugLoc(), true); + MachineInstrBuilder MIB(NewMI); + + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + MachineOperand &MO = MI->getOperand(i); + if (i == OpNo) { + assert(MO.isReg() && "Expected to fold into reg operand!"); + unsigned NumAddrOps = MOs.size(); + for (unsigned i = 0; i != NumAddrOps; ++i) + MIB.addOperand(MOs[i]); + if (NumAddrOps < 4) // FrameIndex only + addOffset(MIB, 0); + } else { + MIB.addOperand(MO); + } + } + return MIB; +} + +static MachineInstr *MakeM0Inst(const TargetInstrInfo &TII, unsigned Opcode, + const SmallVectorImpl &MOs, + MachineInstr *MI) { + MachineFunction &MF = *MI->getParent()->getParent(); + MachineInstrBuilder MIB = BuildMI(MF, MI->getDebugLoc(), TII.get(Opcode)); + + unsigned NumAddrOps = MOs.size(); + for (unsigned i = 0; i != NumAddrOps; ++i) + MIB.addOperand(MOs[i]); + if (NumAddrOps < 4) // FrameIndex only + addOffset(MIB, 0); + return MIB.addImm(0); +} + +MachineInstr* +X86InstrInfo::foldMemoryOperandImpl(MachineFunction &MF, + MachineInstr *MI, unsigned i, + const SmallVectorImpl &MOs, + unsigned Size, unsigned Align) const { + const DenseMap > *OpcodeTablePtr=NULL; + bool isTwoAddrFold = false; + unsigned NumOps = MI->getDesc().getNumOperands(); + bool isTwoAddr = NumOps > 1 && + MI->getDesc().getOperandConstraint(1, TOI::TIED_TO) != -1; + + MachineInstr *NewMI = NULL; + // Folding a memory location into the two-address part of a two-address + // instruction is different than folding it other places. It requires + // replacing the *two* registers with the memory location. + if (isTwoAddr && NumOps >= 2 && i < 2 && + MI->getOperand(0).isReg() && + MI->getOperand(1).isReg() && + MI->getOperand(0).getReg() == MI->getOperand(1).getReg()) { + OpcodeTablePtr = &RegOp2MemOpTable2Addr; + isTwoAddrFold = true; + } else if (i == 0) { // If operand 0 + if (MI->getOpcode() == X86::MOV16r0) + NewMI = MakeM0Inst(*this, X86::MOV16mi, MOs, MI); + else if (MI->getOpcode() == X86::MOV32r0) + NewMI = MakeM0Inst(*this, X86::MOV32mi, MOs, MI); + else if (MI->getOpcode() == X86::MOV8r0) + NewMI = MakeM0Inst(*this, X86::MOV8mi, MOs, MI); + if (NewMI) + return NewMI; + + OpcodeTablePtr = &RegOp2MemOpTable0; + } else if (i == 1) { + OpcodeTablePtr = &RegOp2MemOpTable1; + } else if (i == 2) { + OpcodeTablePtr = &RegOp2MemOpTable2; + } + + // If table selected... + if (OpcodeTablePtr) { + // Find the Opcode to fuse + DenseMap >::const_iterator I = + OpcodeTablePtr->find((unsigned*)MI->getOpcode()); + if (I != OpcodeTablePtr->end()) { + unsigned Opcode = I->second.first; + unsigned MinAlign = I->second.second; + if (Align < MinAlign) + return NULL; + bool NarrowToMOV32rm = false; + if (Size) { + unsigned RCSize = MI->getDesc().OpInfo[i].getRegClass(&RI)->getSize(); + if (Size < RCSize) { + // Check if it's safe to fold the load. If the size of the object is + // narrower than the load width, then it's not. + if (Opcode != X86::MOV64rm || RCSize != 8 || Size != 4) + return NULL; + // If this is a 64-bit load, but the spill slot is 32, then we can do + // a 32-bit load which is implicitly zero-extended. This likely is due + // to liveintervalanalysis remat'ing a load from stack slot. + if (MI->getOperand(0).getSubReg() || MI->getOperand(1).getSubReg()) + return NULL; + Opcode = X86::MOV32rm; + NarrowToMOV32rm = true; + } + } + + if (isTwoAddrFold) + NewMI = FuseTwoAddrInst(MF, Opcode, MOs, MI, *this); + else + NewMI = FuseInst(MF, Opcode, i, MOs, MI, *this); + + if (NarrowToMOV32rm) { + // If this is the special case where we use a MOV32rm to load a 32-bit + // value and zero-extend the top bits. Change the destination register + // to a 32-bit one. + unsigned DstReg = NewMI->getOperand(0).getReg(); + if (TargetRegisterInfo::isPhysicalRegister(DstReg)) + NewMI->getOperand(0).setReg(RI.getSubReg(DstReg, + 4/*x86_subreg_32bit*/)); + else + NewMI->getOperand(0).setSubReg(4/*x86_subreg_32bit*/); + } + return NewMI; + } + } + + // No fusion + if (PrintFailedFusing) + errs() << "We failed to fuse operand " << i << " in " << *MI; + return NULL; +} + + +MachineInstr* X86InstrInfo::foldMemoryOperandImpl(MachineFunction &MF, + MachineInstr *MI, + const SmallVectorImpl &Ops, + int FrameIndex) const { + // Check switch flag + if (NoFusing) return NULL; + + const MachineFrameInfo *MFI = MF.getFrameInfo(); + unsigned Size = MFI->getObjectSize(FrameIndex); + unsigned Alignment = MFI->getObjectAlignment(FrameIndex); + if (Ops.size() == 2 && Ops[0] == 0 && Ops[1] == 1) { + unsigned NewOpc = 0; + unsigned RCSize = 0; + switch (MI->getOpcode()) { + default: return NULL; + case X86::TEST8rr: NewOpc = X86::CMP8ri; RCSize = 1; break; + case X86::TEST16rr: NewOpc = X86::CMP16ri; RCSize = 2; break; + case X86::TEST32rr: NewOpc = X86::CMP32ri; RCSize = 4; break; + case X86::TEST64rr: NewOpc = X86::CMP64ri32; RCSize = 8; break; + } + // Check if it's safe to fold the load. If the size of the object is + // narrower than the load width, then it's not. + if (Size < RCSize) + return NULL; + // Change to CMPXXri r, 0 first. + MI->setDesc(get(NewOpc)); + MI->getOperand(1).ChangeToImmediate(0); + } else if (Ops.size() != 1) + return NULL; + + SmallVector MOs; + MOs.push_back(MachineOperand::CreateFI(FrameIndex)); + return foldMemoryOperandImpl(MF, MI, Ops[0], MOs, Size, Alignment); +} + +MachineInstr* X86InstrInfo::foldMemoryOperandImpl(MachineFunction &MF, + MachineInstr *MI, + const SmallVectorImpl &Ops, + MachineInstr *LoadMI) const { + // Check switch flag + if (NoFusing) return NULL; + + // Determine the alignment of the load. + unsigned Alignment = 0; + if (LoadMI->hasOneMemOperand()) + Alignment = (*LoadMI->memoperands_begin())->getAlignment(); + else + switch (LoadMI->getOpcode()) { + case X86::V_SET0: + case X86::V_SETALLONES: + Alignment = 16; + break; + case X86::FsFLD0SD: + Alignment = 8; + break; + case X86::FsFLD0SS: + Alignment = 4; + break; + default: + llvm_unreachable("Don't know how to fold this instruction!"); + } + if (Ops.size() == 2 && Ops[0] == 0 && Ops[1] == 1) { + unsigned NewOpc = 0; + switch (MI->getOpcode()) { + default: return NULL; + case X86::TEST8rr: NewOpc = X86::CMP8ri; break; + case X86::TEST16rr: NewOpc = X86::CMP16ri; break; + case X86::TEST32rr: NewOpc = X86::CMP32ri; break; + case X86::TEST64rr: NewOpc = X86::CMP64ri32; break; + } + // Change to CMPXXri r, 0 first. + MI->setDesc(get(NewOpc)); + MI->getOperand(1).ChangeToImmediate(0); + } else if (Ops.size() != 1) + return NULL; + + SmallVector MOs; + switch (LoadMI->getOpcode()) { + case X86::V_SET0: + case X86::V_SETALLONES: + case X86::FsFLD0SD: + case X86::FsFLD0SS: { + // Folding a V_SET0 or V_SETALLONES as a load, to ease register pressure. + // Create a constant-pool entry and operands to load from it. + + // x86-32 PIC requires a PIC base register for constant pools. + unsigned PICBase = 0; + if (TM.getRelocationModel() == Reloc::PIC_) { + if (TM.getSubtarget().is64Bit()) + PICBase = X86::RIP; + else + // FIXME: PICBase = TM.getInstrInfo()->getGlobalBaseReg(&MF); + // This doesn't work for several reasons. + // 1. GlobalBaseReg may have been spilled. + // 2. It may not be live at MI. + return NULL; + } + + // Create a constant-pool entry. + MachineConstantPool &MCP = *MF.getConstantPool(); + const Type *Ty; + if (LoadMI->getOpcode() == X86::FsFLD0SS) + Ty = Type::getFloatTy(MF.getFunction()->getContext()); + else if (LoadMI->getOpcode() == X86::FsFLD0SD) + Ty = Type::getDoubleTy(MF.getFunction()->getContext()); + else + Ty = VectorType::get(Type::getInt32Ty(MF.getFunction()->getContext()), 4); + Constant *C = LoadMI->getOpcode() == X86::V_SETALLONES ? + Constant::getAllOnesValue(Ty) : + Constant::getNullValue(Ty); + unsigned CPI = MCP.getConstantPoolIndex(C, Alignment); + + // Create operands to load from the constant pool entry. + MOs.push_back(MachineOperand::CreateReg(PICBase, false)); + MOs.push_back(MachineOperand::CreateImm(1)); + MOs.push_back(MachineOperand::CreateReg(0, false)); + MOs.push_back(MachineOperand::CreateCPI(CPI, 0)); + MOs.push_back(MachineOperand::CreateReg(0, false)); + break; + } + default: { + // Folding a normal load. Just copy the load's address operands. + unsigned NumOps = LoadMI->getDesc().getNumOperands(); + for (unsigned i = NumOps - X86AddrNumOperands; i != NumOps; ++i) + MOs.push_back(LoadMI->getOperand(i)); + break; + } + } + return foldMemoryOperandImpl(MF, MI, Ops[0], MOs, 0, Alignment); +} + + +bool X86InstrInfo::canFoldMemoryOperand(const MachineInstr *MI, + const SmallVectorImpl &Ops) const { + // Check switch flag + if (NoFusing) return 0; + + if (Ops.size() == 2 && Ops[0] == 0 && Ops[1] == 1) { + switch (MI->getOpcode()) { + default: return false; + case X86::TEST8rr: + case X86::TEST16rr: + case X86::TEST32rr: + case X86::TEST64rr: + return true; + } + } + + if (Ops.size() != 1) + return false; + + unsigned OpNum = Ops[0]; + unsigned Opc = MI->getOpcode(); + unsigned NumOps = MI->getDesc().getNumOperands(); + bool isTwoAddr = NumOps > 1 && + MI->getDesc().getOperandConstraint(1, TOI::TIED_TO) != -1; + + // Folding a memory location into the two-address part of a two-address + // instruction is different than folding it other places. It requires + // replacing the *two* registers with the memory location. + const DenseMap > *OpcodeTablePtr=NULL; + if (isTwoAddr && NumOps >= 2 && OpNum < 2) { + OpcodeTablePtr = &RegOp2MemOpTable2Addr; + } else if (OpNum == 0) { // If operand 0 + switch (Opc) { + case X86::MOV8r0: + case X86::MOV16r0: + case X86::MOV32r0: + return true; + default: break; + } + OpcodeTablePtr = &RegOp2MemOpTable0; + } else if (OpNum == 1) { + OpcodeTablePtr = &RegOp2MemOpTable1; + } else if (OpNum == 2) { + OpcodeTablePtr = &RegOp2MemOpTable2; + } + + if (OpcodeTablePtr) { + // Find the Opcode to fuse + DenseMap >::const_iterator I = + OpcodeTablePtr->find((unsigned*)Opc); + if (I != OpcodeTablePtr->end()) + return true; + } + return false; +} + +bool X86InstrInfo::unfoldMemoryOperand(MachineFunction &MF, MachineInstr *MI, + unsigned Reg, bool UnfoldLoad, bool UnfoldStore, + SmallVectorImpl &NewMIs) const { + DenseMap >::const_iterator I = + MemOp2RegOpTable.find((unsigned*)MI->getOpcode()); + if (I == MemOp2RegOpTable.end()) + return false; + DebugLoc dl = MI->getDebugLoc(); + unsigned Opc = I->second.first; + unsigned Index = I->second.second & 0xf; + bool FoldedLoad = I->second.second & (1 << 4); + bool FoldedStore = I->second.second & (1 << 5); + if (UnfoldLoad && !FoldedLoad) + return false; + UnfoldLoad &= FoldedLoad; + if (UnfoldStore && !FoldedStore) + return false; + UnfoldStore &= FoldedStore; + + const TargetInstrDesc &TID = get(Opc); + const TargetOperandInfo &TOI = TID.OpInfo[Index]; + const TargetRegisterClass *RC = TOI.getRegClass(&RI); + SmallVector AddrOps; + SmallVector BeforeOps; + SmallVector AfterOps; + SmallVector ImpOps; + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + MachineOperand &Op = MI->getOperand(i); + if (i >= Index && i < Index + X86AddrNumOperands) + AddrOps.push_back(Op); + else if (Op.isReg() && Op.isImplicit()) + ImpOps.push_back(Op); + else if (i < Index) + BeforeOps.push_back(Op); + else if (i > Index) + AfterOps.push_back(Op); + } + + // Emit the load instruction. + if (UnfoldLoad) { + std::pair MMOs = + MF.extractLoadMemRefs(MI->memoperands_begin(), + MI->memoperands_end()); + loadRegFromAddr(MF, Reg, AddrOps, RC, MMOs.first, MMOs.second, NewMIs); + if (UnfoldStore) { + // Address operands cannot be marked isKill. + for (unsigned i = 1; i != 1 + X86AddrNumOperands; ++i) { + MachineOperand &MO = NewMIs[0]->getOperand(i); + if (MO.isReg()) + MO.setIsKill(false); + } + } + } + + // Emit the data processing instruction. + MachineInstr *DataMI = MF.CreateMachineInstr(TID, MI->getDebugLoc(), true); + MachineInstrBuilder MIB(DataMI); + + if (FoldedStore) + MIB.addReg(Reg, RegState::Define); + for (unsigned i = 0, e = BeforeOps.size(); i != e; ++i) + MIB.addOperand(BeforeOps[i]); + if (FoldedLoad) + MIB.addReg(Reg); + for (unsigned i = 0, e = AfterOps.size(); i != e; ++i) + MIB.addOperand(AfterOps[i]); + for (unsigned i = 0, e = ImpOps.size(); i != e; ++i) { + MachineOperand &MO = ImpOps[i]; + MIB.addReg(MO.getReg(), + getDefRegState(MO.isDef()) | + RegState::Implicit | + getKillRegState(MO.isKill()) | + getDeadRegState(MO.isDead()) | + getUndefRegState(MO.isUndef())); + } + // Change CMP32ri r, 0 back to TEST32rr r, r, etc. + unsigned NewOpc = 0; + switch (DataMI->getOpcode()) { + default: break; + case X86::CMP64ri32: + case X86::CMP32ri: + case X86::CMP16ri: + case X86::CMP8ri: { + MachineOperand &MO0 = DataMI->getOperand(0); + MachineOperand &MO1 = DataMI->getOperand(1); + if (MO1.getImm() == 0) { + switch (DataMI->getOpcode()) { + default: break; + case X86::CMP64ri32: NewOpc = X86::TEST64rr; break; + case X86::CMP32ri: NewOpc = X86::TEST32rr; break; + case X86::CMP16ri: NewOpc = X86::TEST16rr; break; + case X86::CMP8ri: NewOpc = X86::TEST8rr; break; + } + DataMI->setDesc(get(NewOpc)); + MO1.ChangeToRegister(MO0.getReg(), false); + } + } + } + NewMIs.push_back(DataMI); + + // Emit the store instruction. + if (UnfoldStore) { + const TargetRegisterClass *DstRC = TID.OpInfo[0].getRegClass(&RI); + std::pair MMOs = + MF.extractStoreMemRefs(MI->memoperands_begin(), + MI->memoperands_end()); + storeRegToAddr(MF, Reg, true, AddrOps, DstRC, MMOs.first, MMOs.second, NewMIs); + } + + return true; +} + +bool +X86InstrInfo::unfoldMemoryOperand(SelectionDAG &DAG, SDNode *N, + SmallVectorImpl &NewNodes) const { + if (!N->isMachineOpcode()) + return false; + + DenseMap >::const_iterator I = + MemOp2RegOpTable.find((unsigned*)N->getMachineOpcode()); + if (I == MemOp2RegOpTable.end()) + return false; + unsigned Opc = I->second.first; + unsigned Index = I->second.second & 0xf; + bool FoldedLoad = I->second.second & (1 << 4); + bool FoldedStore = I->second.second & (1 << 5); + const TargetInstrDesc &TID = get(Opc); + const TargetRegisterClass *RC = TID.OpInfo[Index].getRegClass(&RI); + unsigned NumDefs = TID.NumDefs; + std::vector AddrOps; + std::vector BeforeOps; + std::vector AfterOps; + DebugLoc dl = N->getDebugLoc(); + unsigned NumOps = N->getNumOperands(); + for (unsigned i = 0; i != NumOps-1; ++i) { + SDValue Op = N->getOperand(i); + if (i >= Index-NumDefs && i < Index-NumDefs + X86AddrNumOperands) + AddrOps.push_back(Op); + else if (i < Index-NumDefs) + BeforeOps.push_back(Op); + else if (i > Index-NumDefs) + AfterOps.push_back(Op); + } + SDValue Chain = N->getOperand(NumOps-1); + AddrOps.push_back(Chain); + + // Emit the load instruction. + SDNode *Load = 0; + MachineFunction &MF = DAG.getMachineFunction(); + if (FoldedLoad) { + EVT VT = *RC->vt_begin(); + std::pair MMOs = + MF.extractLoadMemRefs(cast(N)->memoperands_begin(), + cast(N)->memoperands_end()); + bool isAligned = (*MMOs.first)->getAlignment() >= 16; + Load = DAG.getMachineNode(getLoadRegOpcode(0, RC, isAligned, TM), dl, + VT, MVT::Other, &AddrOps[0], AddrOps.size()); + NewNodes.push_back(Load); + + // Preserve memory reference information. + cast(Load)->setMemRefs(MMOs.first, MMOs.second); + } + + // Emit the data processing instruction. + std::vector VTs; + const TargetRegisterClass *DstRC = 0; + if (TID.getNumDefs() > 0) { + DstRC = TID.OpInfo[0].getRegClass(&RI); + VTs.push_back(*DstRC->vt_begin()); + } + for (unsigned i = 0, e = N->getNumValues(); i != e; ++i) { + EVT VT = N->getValueType(i); + if (VT != MVT::Other && i >= (unsigned)TID.getNumDefs()) + VTs.push_back(VT); + } + if (Load) + BeforeOps.push_back(SDValue(Load, 0)); + std::copy(AfterOps.begin(), AfterOps.end(), std::back_inserter(BeforeOps)); + SDNode *NewNode= DAG.getMachineNode(Opc, dl, VTs, &BeforeOps[0], + BeforeOps.size()); + NewNodes.push_back(NewNode); + + // Emit the store instruction. + if (FoldedStore) { + AddrOps.pop_back(); + AddrOps.push_back(SDValue(NewNode, 0)); + AddrOps.push_back(Chain); + std::pair MMOs = + MF.extractStoreMemRefs(cast(N)->memoperands_begin(), + cast(N)->memoperands_end()); + bool isAligned = (*MMOs.first)->getAlignment() >= 16; + SDNode *Store = DAG.getMachineNode(getStoreRegOpcode(0, DstRC, + isAligned, TM), + dl, MVT::Other, + &AddrOps[0], AddrOps.size()); + NewNodes.push_back(Store); + + // Preserve memory reference information. + cast(Load)->setMemRefs(MMOs.first, MMOs.second); + } + + return true; +} + +unsigned X86InstrInfo::getOpcodeAfterMemoryUnfold(unsigned Opc, + bool UnfoldLoad, bool UnfoldStore, + unsigned *LoadRegIndex) const { + DenseMap >::const_iterator I = + MemOp2RegOpTable.find((unsigned*)Opc); + if (I == MemOp2RegOpTable.end()) + return 0; + bool FoldedLoad = I->second.second & (1 << 4); + bool FoldedStore = I->second.second & (1 << 5); + if (UnfoldLoad && !FoldedLoad) + return 0; + if (UnfoldStore && !FoldedStore) + return 0; + if (LoadRegIndex) + *LoadRegIndex = I->second.second & 0xf; + return I->second.first; +} + +bool X86InstrInfo::BlockHasNoFallThrough(const MachineBasicBlock &MBB) const { + if (MBB.empty()) return false; + + switch (MBB.back().getOpcode()) { + case X86::TCRETURNri: + case X86::TCRETURNdi: + case X86::RET: // Return. + case X86::RETI: + case X86::TAILJMPd: + case X86::TAILJMPr: + case X86::TAILJMPm: + case X86::JMP: // Uncond branch. + case X86::JMP32r: // Indirect branch. + case X86::JMP64r: // Indirect branch (64-bit). + case X86::JMP32m: // Indirect branch through mem. + case X86::JMP64m: // Indirect branch through mem (64-bit). + return true; + default: return false; + } +} + +bool X86InstrInfo:: +ReverseBranchCondition(SmallVectorImpl &Cond) const { + assert(Cond.size() == 1 && "Invalid X86 branch condition!"); + X86::CondCode CC = static_cast(Cond[0].getImm()); + if (CC == X86::COND_NE_OR_P || CC == X86::COND_NP_OR_E) + return true; + Cond[0].setImm(GetOppositeBranchCondition(CC)); + return false; +} + +bool X86InstrInfo:: +isSafeToMoveRegClassDefs(const TargetRegisterClass *RC) const { + // FIXME: Return false for x87 stack register classes for now. We can't + // allow any loads of these registers before FpGet_ST0_80. + return !(RC == &X86::CCRRegClass || RC == &X86::RFP32RegClass || + RC == &X86::RFP64RegClass || RC == &X86::RFP80RegClass); +} + +unsigned X86InstrInfo::sizeOfImm(const TargetInstrDesc *Desc) { + switch (Desc->TSFlags & X86II::ImmMask) { + case X86II::Imm8: return 1; + case X86II::Imm16: return 2; + case X86II::Imm32: return 4; + case X86II::Imm64: return 8; + default: llvm_unreachable("Immediate size not set!"); + return 0; + } +} + +/// isX86_64ExtendedReg - Is the MachineOperand a x86-64 extended register? +/// e.g. r8, xmm8, etc. +bool X86InstrInfo::isX86_64ExtendedReg(const MachineOperand &MO) { + if (!MO.isReg()) return false; + switch (MO.getReg()) { + default: break; + case X86::R8: case X86::R9: case X86::R10: case X86::R11: + case X86::R12: case X86::R13: case X86::R14: case X86::R15: + case X86::R8D: case X86::R9D: case X86::R10D: case X86::R11D: + case X86::R12D: case X86::R13D: case X86::R14D: case X86::R15D: + case X86::R8W: case X86::R9W: case X86::R10W: case X86::R11W: + case X86::R12W: case X86::R13W: case X86::R14W: case X86::R15W: + case X86::R8B: case X86::R9B: case X86::R10B: case X86::R11B: + case X86::R12B: case X86::R13B: case X86::R14B: case X86::R15B: + case X86::XMM8: case X86::XMM9: case X86::XMM10: case X86::XMM11: + case X86::XMM12: case X86::XMM13: case X86::XMM14: case X86::XMM15: + return true; + } + return false; +} + + +/// determineREX - Determine if the MachineInstr has to be encoded with a X86-64 +/// REX prefix which specifies 1) 64-bit instructions, 2) non-default operand +/// size, and 3) use of X86-64 extended registers. +unsigned X86InstrInfo::determineREX(const MachineInstr &MI) { + unsigned REX = 0; + const TargetInstrDesc &Desc = MI.getDesc(); + + // Pseudo instructions do not need REX prefix byte. + if ((Desc.TSFlags & X86II::FormMask) == X86II::Pseudo) + return 0; + if (Desc.TSFlags & X86II::REX_W) + REX |= 1 << 3; + + unsigned NumOps = Desc.getNumOperands(); + if (NumOps) { + bool isTwoAddr = NumOps > 1 && + Desc.getOperandConstraint(1, TOI::TIED_TO) != -1; + + // If it accesses SPL, BPL, SIL, or DIL, then it requires a 0x40 REX prefix. + unsigned i = isTwoAddr ? 1 : 0; + for (unsigned e = NumOps; i != e; ++i) { + const MachineOperand& MO = MI.getOperand(i); + if (MO.isReg()) { + unsigned Reg = MO.getReg(); + if (isX86_64NonExtLowByteReg(Reg)) + REX |= 0x40; + } + } + + switch (Desc.TSFlags & X86II::FormMask) { + case X86II::MRMInitReg: + if (isX86_64ExtendedReg(MI.getOperand(0))) + REX |= (1 << 0) | (1 << 2); + break; + case X86II::MRMSrcReg: { + if (isX86_64ExtendedReg(MI.getOperand(0))) + REX |= 1 << 2; + i = isTwoAddr ? 2 : 1; + for (unsigned e = NumOps; i != e; ++i) { + const MachineOperand& MO = MI.getOperand(i); + if (isX86_64ExtendedReg(MO)) + REX |= 1 << 0; + } + break; + } + case X86II::MRMSrcMem: { + if (isX86_64ExtendedReg(MI.getOperand(0))) + REX |= 1 << 2; + unsigned Bit = 0; + i = isTwoAddr ? 2 : 1; + for (; i != NumOps; ++i) { + const MachineOperand& MO = MI.getOperand(i); + if (MO.isReg()) { + if (isX86_64ExtendedReg(MO)) + REX |= 1 << Bit; + Bit++; + } + } + break; + } + case X86II::MRM0m: case X86II::MRM1m: + case X86II::MRM2m: case X86II::MRM3m: + case X86II::MRM4m: case X86II::MRM5m: + case X86II::MRM6m: case X86II::MRM7m: + case X86II::MRMDestMem: { + unsigned e = (isTwoAddr ? X86AddrNumOperands+1 : X86AddrNumOperands); + i = isTwoAddr ? 1 : 0; + if (NumOps > e && isX86_64ExtendedReg(MI.getOperand(e))) + REX |= 1 << 2; + unsigned Bit = 0; + for (; i != e; ++i) { + const MachineOperand& MO = MI.getOperand(i); + if (MO.isReg()) { + if (isX86_64ExtendedReg(MO)) + REX |= 1 << Bit; + Bit++; + } + } + break; + } + default: { + if (isX86_64ExtendedReg(MI.getOperand(0))) + REX |= 1 << 0; + i = isTwoAddr ? 2 : 1; + for (unsigned e = NumOps; i != e; ++i) { + const MachineOperand& MO = MI.getOperand(i); + if (isX86_64ExtendedReg(MO)) + REX |= 1 << 2; + } + break; + } + } + } + return REX; +} + +/// sizePCRelativeBlockAddress - This method returns the size of a PC +/// relative block address instruction +/// +static unsigned sizePCRelativeBlockAddress() { + return 4; +} + +/// sizeGlobalAddress - Give the size of the emission of this global address +/// +static unsigned sizeGlobalAddress(bool dword) { + return dword ? 8 : 4; +} + +/// sizeConstPoolAddress - Give the size of the emission of this constant +/// pool address +/// +static unsigned sizeConstPoolAddress(bool dword) { + return dword ? 8 : 4; +} + +/// sizeExternalSymbolAddress - Give the size of the emission of this external +/// symbol +/// +static unsigned sizeExternalSymbolAddress(bool dword) { + return dword ? 8 : 4; +} + +/// sizeJumpTableAddress - Give the size of the emission of this jump +/// table address +/// +static unsigned sizeJumpTableAddress(bool dword) { + return dword ? 8 : 4; +} + +static unsigned sizeConstant(unsigned Size) { + return Size; +} + +static unsigned sizeRegModRMByte(){ + return 1; +} + +static unsigned sizeSIBByte(){ + return 1; +} + +static unsigned getDisplacementFieldSize(const MachineOperand *RelocOp) { + unsigned FinalSize = 0; + // If this is a simple integer displacement that doesn't require a relocation. + if (!RelocOp) { + FinalSize += sizeConstant(4); + return FinalSize; + } + + // Otherwise, this is something that requires a relocation. + if (RelocOp->isGlobal()) { + FinalSize += sizeGlobalAddress(false); + } else if (RelocOp->isCPI()) { + FinalSize += sizeConstPoolAddress(false); + } else if (RelocOp->isJTI()) { + FinalSize += sizeJumpTableAddress(false); + } else { + llvm_unreachable("Unknown value to relocate!"); + } + return FinalSize; +} + +static unsigned getMemModRMByteSize(const MachineInstr &MI, unsigned Op, + bool IsPIC, bool Is64BitMode) { + const MachineOperand &Op3 = MI.getOperand(Op+3); + int DispVal = 0; + const MachineOperand *DispForReloc = 0; + unsigned FinalSize = 0; + + // Figure out what sort of displacement we have to handle here. + if (Op3.isGlobal()) { + DispForReloc = &Op3; + } else if (Op3.isCPI()) { + if (Is64BitMode || IsPIC) { + DispForReloc = &Op3; + } else { + DispVal = 1; + } + } else if (Op3.isJTI()) { + if (Is64BitMode || IsPIC) { + DispForReloc = &Op3; + } else { + DispVal = 1; + } + } else { + DispVal = 1; + } + + const MachineOperand &Base = MI.getOperand(Op); + const MachineOperand &IndexReg = MI.getOperand(Op+2); + + unsigned BaseReg = Base.getReg(); + + // Is a SIB byte needed? + if ((!Is64BitMode || DispForReloc || BaseReg != 0) && + IndexReg.getReg() == 0 && + (BaseReg == 0 || X86RegisterInfo::getX86RegNum(BaseReg) != N86::ESP)) { + if (BaseReg == 0) { // Just a displacement? + // Emit special case [disp32] encoding + ++FinalSize; + FinalSize += getDisplacementFieldSize(DispForReloc); + } else { + unsigned BaseRegNo = X86RegisterInfo::getX86RegNum(BaseReg); + if (!DispForReloc && DispVal == 0 && BaseRegNo != N86::EBP) { + // Emit simple indirect register encoding... [EAX] f.e. + ++FinalSize; + // Be pessimistic and assume it's a disp32, not a disp8 + } else { + // Emit the most general non-SIB encoding: [REG+disp32] + ++FinalSize; + FinalSize += getDisplacementFieldSize(DispForReloc); + } + } + + } else { // We need a SIB byte, so start by outputting the ModR/M byte first + assert(IndexReg.getReg() != X86::ESP && + IndexReg.getReg() != X86::RSP && "Cannot use ESP as index reg!"); + + bool ForceDisp32 = false; + if (BaseReg == 0 || DispForReloc) { + // Emit the normal disp32 encoding. + ++FinalSize; + ForceDisp32 = true; + } else { + ++FinalSize; + } + + FinalSize += sizeSIBByte(); + + // Do we need to output a displacement? + if (DispVal != 0 || ForceDisp32) { + FinalSize += getDisplacementFieldSize(DispForReloc); + } + } + return FinalSize; +} + + +static unsigned GetInstSizeWithDesc(const MachineInstr &MI, + const TargetInstrDesc *Desc, + bool IsPIC, bool Is64BitMode) { + + unsigned Opcode = Desc->Opcode; + unsigned FinalSize = 0; + + // Emit the lock opcode prefix as needed. + if (Desc->TSFlags & X86II::LOCK) ++FinalSize; + + // Emit segment override opcode prefix as needed. + switch (Desc->TSFlags & X86II::SegOvrMask) { + case X86II::FS: + case X86II::GS: + ++FinalSize; + break; + default: llvm_unreachable("Invalid segment!"); + case 0: break; // No segment override! + } + + // Emit the repeat opcode prefix as needed. + if ((Desc->TSFlags & X86II::Op0Mask) == X86II::REP) ++FinalSize; + + // Emit the operand size opcode prefix as needed. + if (Desc->TSFlags & X86II::OpSize) ++FinalSize; + + // Emit the address size opcode prefix as needed. + if (Desc->TSFlags & X86II::AdSize) ++FinalSize; + + bool Need0FPrefix = false; + switch (Desc->TSFlags & X86II::Op0Mask) { + case X86II::TB: // Two-byte opcode prefix + case X86II::T8: // 0F 38 + case X86II::TA: // 0F 3A + Need0FPrefix = true; + break; + case X86II::TF: // F2 0F 38 + ++FinalSize; + Need0FPrefix = true; + break; + case X86II::REP: break; // already handled. + case X86II::XS: // F3 0F + ++FinalSize; + Need0FPrefix = true; + break; + case X86II::XD: // F2 0F + ++FinalSize; + Need0FPrefix = true; + break; + case X86II::D8: case X86II::D9: case X86II::DA: case X86II::DB: + case X86II::DC: case X86II::DD: case X86II::DE: case X86II::DF: + ++FinalSize; + break; // Two-byte opcode prefix + default: llvm_unreachable("Invalid prefix!"); + case 0: break; // No prefix! + } + + if (Is64BitMode) { + // REX prefix + unsigned REX = X86InstrInfo::determineREX(MI); + if (REX) + ++FinalSize; + } + + // 0x0F escape code must be emitted just before the opcode. + if (Need0FPrefix) + ++FinalSize; + + switch (Desc->TSFlags & X86II::Op0Mask) { + case X86II::T8: // 0F 38 + ++FinalSize; + break; + case X86II::TA: // 0F 3A + ++FinalSize; + break; + case X86II::TF: // F2 0F 38 + ++FinalSize; + break; + } + + // If this is a two-address instruction, skip one of the register operands. + unsigned NumOps = Desc->getNumOperands(); + unsigned CurOp = 0; + if (NumOps > 1 && Desc->getOperandConstraint(1, TOI::TIED_TO) != -1) + CurOp++; + else if (NumOps > 2 && Desc->getOperandConstraint(NumOps-1, TOI::TIED_TO)== 0) + // Skip the last source operand that is tied_to the dest reg. e.g. LXADD32 + --NumOps; + + switch (Desc->TSFlags & X86II::FormMask) { + default: llvm_unreachable("Unknown FormMask value in X86 MachineCodeEmitter!"); + case X86II::Pseudo: + // Remember the current PC offset, this is the PIC relocation + // base address. + switch (Opcode) { + default: + break; + case TargetInstrInfo::INLINEASM: { + const MachineFunction *MF = MI.getParent()->getParent(); + const TargetInstrInfo &TII = *MF->getTarget().getInstrInfo(); + FinalSize += TII.getInlineAsmLength(MI.getOperand(0).getSymbolName(), + *MF->getTarget().getMCAsmInfo()); + break; + } + case TargetInstrInfo::DBG_LABEL: + case TargetInstrInfo::EH_LABEL: + break; + case TargetInstrInfo::IMPLICIT_DEF: + case TargetInstrInfo::KILL: + case X86::FP_REG_KILL: + break; + case X86::MOVPC32r: { + // This emits the "call" portion of this pseudo instruction. + ++FinalSize; + FinalSize += sizeConstant(X86InstrInfo::sizeOfImm(Desc)); + break; + } + } + CurOp = NumOps; + break; + case X86II::RawFrm: + ++FinalSize; + + if (CurOp != NumOps) { + const MachineOperand &MO = MI.getOperand(CurOp++); + if (MO.isMBB()) { + FinalSize += sizePCRelativeBlockAddress(); + } else if (MO.isGlobal()) { + FinalSize += sizeGlobalAddress(false); + } else if (MO.isSymbol()) { + FinalSize += sizeExternalSymbolAddress(false); + } else if (MO.isImm()) { + FinalSize += sizeConstant(X86InstrInfo::sizeOfImm(Desc)); + } else { + llvm_unreachable("Unknown RawFrm operand!"); + } + } + break; + + case X86II::AddRegFrm: + ++FinalSize; + ++CurOp; + + if (CurOp != NumOps) { + const MachineOperand &MO1 = MI.getOperand(CurOp++); + unsigned Size = X86InstrInfo::sizeOfImm(Desc); + if (MO1.isImm()) + FinalSize += sizeConstant(Size); + else { + bool dword = false; + if (Opcode == X86::MOV64ri) + dword = true; + if (MO1.isGlobal()) { + FinalSize += sizeGlobalAddress(dword); + } else if (MO1.isSymbol()) + FinalSize += sizeExternalSymbolAddress(dword); + else if (MO1.isCPI()) + FinalSize += sizeConstPoolAddress(dword); + else if (MO1.isJTI()) + FinalSize += sizeJumpTableAddress(dword); + } + } + break; + + case X86II::MRMDestReg: { + ++FinalSize; + FinalSize += sizeRegModRMByte(); + CurOp += 2; + if (CurOp != NumOps) { + ++CurOp; + FinalSize += sizeConstant(X86InstrInfo::sizeOfImm(Desc)); + } + break; + } + case X86II::MRMDestMem: { + ++FinalSize; + FinalSize += getMemModRMByteSize(MI, CurOp, IsPIC, Is64BitMode); + CurOp += X86AddrNumOperands + 1; + if (CurOp != NumOps) { + ++CurOp; + FinalSize += sizeConstant(X86InstrInfo::sizeOfImm(Desc)); + } + break; + } + + case X86II::MRMSrcReg: + ++FinalSize; + FinalSize += sizeRegModRMByte(); + CurOp += 2; + if (CurOp != NumOps) { + ++CurOp; + FinalSize += sizeConstant(X86InstrInfo::sizeOfImm(Desc)); + } + break; + + case X86II::MRMSrcMem: { + int AddrOperands; + if (Opcode == X86::LEA64r || Opcode == X86::LEA64_32r || + Opcode == X86::LEA16r || Opcode == X86::LEA32r) + AddrOperands = X86AddrNumOperands - 1; // No segment register + else + AddrOperands = X86AddrNumOperands; + + ++FinalSize; + FinalSize += getMemModRMByteSize(MI, CurOp+1, IsPIC, Is64BitMode); + CurOp += AddrOperands + 1; + if (CurOp != NumOps) { + ++CurOp; + FinalSize += sizeConstant(X86InstrInfo::sizeOfImm(Desc)); + } + break; + } + + case X86II::MRM0r: case X86II::MRM1r: + case X86II::MRM2r: case X86II::MRM3r: + case X86II::MRM4r: case X86II::MRM5r: + case X86II::MRM6r: case X86II::MRM7r: + ++FinalSize; + if (Desc->getOpcode() == X86::LFENCE || + Desc->getOpcode() == X86::MFENCE) { + // Special handling of lfence and mfence; + FinalSize += sizeRegModRMByte(); + } else if (Desc->getOpcode() == X86::MONITOR || + Desc->getOpcode() == X86::MWAIT) { + // Special handling of monitor and mwait. + FinalSize += sizeRegModRMByte() + 1; // +1 for the opcode. + } else { + ++CurOp; + FinalSize += sizeRegModRMByte(); + } + + if (CurOp != NumOps) { + const MachineOperand &MO1 = MI.getOperand(CurOp++); + unsigned Size = X86InstrInfo::sizeOfImm(Desc); + if (MO1.isImm()) + FinalSize += sizeConstant(Size); + else { + bool dword = false; + if (Opcode == X86::MOV64ri32) + dword = true; + if (MO1.isGlobal()) { + FinalSize += sizeGlobalAddress(dword); + } else if (MO1.isSymbol()) + FinalSize += sizeExternalSymbolAddress(dword); + else if (MO1.isCPI()) + FinalSize += sizeConstPoolAddress(dword); + else if (MO1.isJTI()) + FinalSize += sizeJumpTableAddress(dword); + } + } + break; + + case X86II::MRM0m: case X86II::MRM1m: + case X86II::MRM2m: case X86II::MRM3m: + case X86II::MRM4m: case X86II::MRM5m: + case X86II::MRM6m: case X86II::MRM7m: { + + ++FinalSize; + FinalSize += getMemModRMByteSize(MI, CurOp, IsPIC, Is64BitMode); + CurOp += X86AddrNumOperands; + + if (CurOp != NumOps) { + const MachineOperand &MO = MI.getOperand(CurOp++); + unsigned Size = X86InstrInfo::sizeOfImm(Desc); + if (MO.isImm()) + FinalSize += sizeConstant(Size); + else { + bool dword = false; + if (Opcode == X86::MOV64mi32) + dword = true; + if (MO.isGlobal()) { + FinalSize += sizeGlobalAddress(dword); + } else if (MO.isSymbol()) + FinalSize += sizeExternalSymbolAddress(dword); + else if (MO.isCPI()) + FinalSize += sizeConstPoolAddress(dword); + else if (MO.isJTI()) + FinalSize += sizeJumpTableAddress(dword); + } + } + break; + } + + case X86II::MRMInitReg: + ++FinalSize; + // Duplicate register, used by things like MOV8r0 (aka xor reg,reg). + FinalSize += sizeRegModRMByte(); + ++CurOp; + break; + } + + if (!Desc->isVariadic() && CurOp != NumOps) { + std::string msg; + raw_string_ostream Msg(msg); + Msg << "Cannot determine size: " << MI; + llvm_report_error(Msg.str()); + } + + + return FinalSize; +} + + +unsigned X86InstrInfo::GetInstSizeInBytes(const MachineInstr *MI) const { + const TargetInstrDesc &Desc = MI->getDesc(); + bool IsPIC = TM.getRelocationModel() == Reloc::PIC_; + bool Is64BitMode = TM.getSubtargetImpl()->is64Bit(); + unsigned Size = GetInstSizeWithDesc(*MI, &Desc, IsPIC, Is64BitMode); + if (Desc.getOpcode() == X86::MOVPC32r) + Size += GetInstSizeWithDesc(*MI, &get(X86::POP32r), IsPIC, Is64BitMode); + return Size; +} + +/// getGlobalBaseReg - Return a virtual register initialized with the +/// the global base register value. Output instructions required to +/// initialize the register in the function entry block, if necessary. +/// +unsigned X86InstrInfo::getGlobalBaseReg(MachineFunction *MF) const { + assert(!TM.getSubtarget().is64Bit() && + "X86-64 PIC uses RIP relative addressing"); + + X86MachineFunctionInfo *X86FI = MF->getInfo(); + unsigned GlobalBaseReg = X86FI->getGlobalBaseReg(); + if (GlobalBaseReg != 0) + return GlobalBaseReg; + + // Insert the set of GlobalBaseReg into the first MBB of the function + MachineBasicBlock &FirstMBB = MF->front(); + MachineBasicBlock::iterator MBBI = FirstMBB.begin(); + DebugLoc DL = DebugLoc::getUnknownLoc(); + if (MBBI != FirstMBB.end()) DL = MBBI->getDebugLoc(); + MachineRegisterInfo &RegInfo = MF->getRegInfo(); + unsigned PC = RegInfo.createVirtualRegister(X86::GR32RegisterClass); + + const TargetInstrInfo *TII = TM.getInstrInfo(); + // Operand of MovePCtoStack is completely ignored by asm printer. It's + // only used in JIT code emission as displacement to pc. + BuildMI(FirstMBB, MBBI, DL, TII->get(X86::MOVPC32r), PC).addImm(0); + + // If we're using vanilla 'GOT' PIC style, we should use relative addressing + // not to pc, but to _GLOBAL_OFFSET_TABLE_ external. + if (TM.getSubtarget().isPICStyleGOT()) { + GlobalBaseReg = RegInfo.createVirtualRegister(X86::GR32RegisterClass); + // Generate addl $__GLOBAL_OFFSET_TABLE_ + [.-piclabel], %some_register + BuildMI(FirstMBB, MBBI, DL, TII->get(X86::ADD32ri), GlobalBaseReg) + .addReg(PC).addExternalSymbol("_GLOBAL_OFFSET_TABLE_", + X86II::MO_GOT_ABSOLUTE_ADDRESS); + } else { + GlobalBaseReg = PC; + } + + X86FI->setGlobalBaseReg(GlobalBaseReg); + return GlobalBaseReg; +} diff --git a/libclamav/c++/llvm/lib/Target/X86/X86InstrInfo.h b/libclamav/c++/llvm/lib/Target/X86/X86InstrInfo.h new file mode 100644 index 000000000..3d4c2f695 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/X86/X86InstrInfo.h @@ -0,0 +1,652 @@ +//===- X86InstrInfo.h - X86 Instruction Information ------------*- C++ -*- ===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the X86 implementation of the TargetInstrInfo class. +// +//===----------------------------------------------------------------------===// + +#ifndef X86INSTRUCTIONINFO_H +#define X86INSTRUCTIONINFO_H + +#include "llvm/Target/TargetInstrInfo.h" +#include "X86.h" +#include "X86RegisterInfo.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/Target/TargetRegisterInfo.h" + +namespace llvm { + class X86RegisterInfo; + class X86TargetMachine; + +namespace X86 { + // X86 specific condition code. These correspond to X86_*_COND in + // X86InstrInfo.td. They must be kept in synch. + enum CondCode { + COND_A = 0, + COND_AE = 1, + COND_B = 2, + COND_BE = 3, + COND_E = 4, + COND_G = 5, + COND_GE = 6, + COND_L = 7, + COND_LE = 8, + COND_NE = 9, + COND_NO = 10, + COND_NP = 11, + COND_NS = 12, + COND_O = 13, + COND_P = 14, + COND_S = 15, + + // Artificial condition codes. These are used by AnalyzeBranch + // to indicate a block terminated with two conditional branches to + // the same location. This occurs in code using FCMP_OEQ or FCMP_UNE, + // which can't be represented on x86 with a single condition. These + // are never used in MachineInstrs. + COND_NE_OR_P, + COND_NP_OR_E, + + COND_INVALID + }; + + // Turn condition code into conditional branch opcode. + unsigned GetCondBranchFromCond(CondCode CC); + + /// GetOppositeBranchCondition - Return the inverse of the specified cond, + /// e.g. turning COND_E to COND_NE. + CondCode GetOppositeBranchCondition(X86::CondCode CC); + +} + +/// X86II - This namespace holds all of the target specific flags that +/// instruction info tracks. +/// +namespace X86II { + /// Target Operand Flag enum. + enum TOF { + //===------------------------------------------------------------------===// + // X86 Specific MachineOperand flags. + + MO_NO_FLAG, + + /// MO_GOT_ABSOLUTE_ADDRESS - On a symbol operand, this represents a + /// relocation of: + /// SYMBOL_LABEL + [. - PICBASELABEL] + MO_GOT_ABSOLUTE_ADDRESS, + + /// MO_PIC_BASE_OFFSET - On a symbol operand this indicates that the + /// immediate should get the value of the symbol minus the PIC base label: + /// SYMBOL_LABEL - PICBASELABEL + MO_PIC_BASE_OFFSET, + + /// MO_GOT - On a symbol operand this indicates that the immediate is the + /// offset to the GOT entry for the symbol name from the base of the GOT. + /// + /// See the X86-64 ELF ABI supplement for more details. + /// SYMBOL_LABEL @GOT + MO_GOT, + + /// MO_GOTOFF - On a symbol operand this indicates that the immediate is + /// the offset to the location of the symbol name from the base of the GOT. + /// + /// See the X86-64 ELF ABI supplement for more details. + /// SYMBOL_LABEL @GOTOFF + MO_GOTOFF, + + /// MO_GOTPCREL - On a symbol operand this indicates that the immediate is + /// offset to the GOT entry for the symbol name from the current code + /// location. + /// + /// See the X86-64 ELF ABI supplement for more details. + /// SYMBOL_LABEL @GOTPCREL + MO_GOTPCREL, + + /// MO_PLT - On a symbol operand this indicates that the immediate is + /// offset to the PLT entry of symbol name from the current code location. + /// + /// See the X86-64 ELF ABI supplement for more details. + /// SYMBOL_LABEL @PLT + MO_PLT, + + /// MO_TLSGD - On a symbol operand this indicates that the immediate is + /// some TLS offset. + /// + /// See 'ELF Handling for Thread-Local Storage' for more details. + /// SYMBOL_LABEL @TLSGD + MO_TLSGD, + + /// MO_GOTTPOFF - On a symbol operand this indicates that the immediate is + /// some TLS offset. + /// + /// See 'ELF Handling for Thread-Local Storage' for more details. + /// SYMBOL_LABEL @GOTTPOFF + MO_GOTTPOFF, + + /// MO_INDNTPOFF - On a symbol operand this indicates that the immediate is + /// some TLS offset. + /// + /// See 'ELF Handling for Thread-Local Storage' for more details. + /// SYMBOL_LABEL @INDNTPOFF + MO_INDNTPOFF, + + /// MO_TPOFF - On a symbol operand this indicates that the immediate is + /// some TLS offset. + /// + /// See 'ELF Handling for Thread-Local Storage' for more details. + /// SYMBOL_LABEL @TPOFF + MO_TPOFF, + + /// MO_NTPOFF - On a symbol operand this indicates that the immediate is + /// some TLS offset. + /// + /// See 'ELF Handling for Thread-Local Storage' for more details. + /// SYMBOL_LABEL @NTPOFF + MO_NTPOFF, + + /// MO_DLLIMPORT - On a symbol operand "FOO", this indicates that the + /// reference is actually to the "__imp_FOO" symbol. This is used for + /// dllimport linkage on windows. + MO_DLLIMPORT, + + /// MO_DARWIN_STUB - On a symbol operand "FOO", this indicates that the + /// reference is actually to the "FOO$stub" symbol. This is used for calls + /// and jumps to external functions on Tiger and before. + MO_DARWIN_STUB, + + /// MO_DARWIN_NONLAZY - On a symbol operand "FOO", this indicates that the + /// reference is actually to the "FOO$non_lazy_ptr" symbol, which is a + /// non-PIC-base-relative reference to a non-hidden dyld lazy pointer stub. + MO_DARWIN_NONLAZY, + + /// MO_DARWIN_NONLAZY_PIC_BASE - On a symbol operand "FOO", this indicates + /// that the reference is actually to "FOO$non_lazy_ptr - PICBASE", which is + /// a PIC-base-relative reference to a non-hidden dyld lazy pointer stub. + MO_DARWIN_NONLAZY_PIC_BASE, + + /// MO_DARWIN_HIDDEN_NONLAZY_PIC_BASE - On a symbol operand "FOO", this + /// indicates that the reference is actually to "FOO$non_lazy_ptr -PICBASE", + /// which is a PIC-base-relative reference to a hidden dyld lazy pointer + /// stub. + MO_DARWIN_HIDDEN_NONLAZY_PIC_BASE + }; +} + +/// isGlobalStubReference - Return true if the specified TargetFlag operand is +/// a reference to a stub for a global, not the global itself. +inline static bool isGlobalStubReference(unsigned char TargetFlag) { + switch (TargetFlag) { + case X86II::MO_DLLIMPORT: // dllimport stub. + case X86II::MO_GOTPCREL: // rip-relative GOT reference. + case X86II::MO_GOT: // normal GOT reference. + case X86II::MO_DARWIN_NONLAZY_PIC_BASE: // Normal $non_lazy_ptr ref. + case X86II::MO_DARWIN_NONLAZY: // Normal $non_lazy_ptr ref. + case X86II::MO_DARWIN_HIDDEN_NONLAZY_PIC_BASE: // Hidden $non_lazy_ptr ref. + return true; + default: + return false; + } +} + +/// isGlobalRelativeToPICBase - Return true if the specified global value +/// reference is relative to a 32-bit PIC base (X86ISD::GlobalBaseReg). If this +/// is true, the addressing mode has the PIC base register added in (e.g. EBX). +inline static bool isGlobalRelativeToPICBase(unsigned char TargetFlag) { + switch (TargetFlag) { + case X86II::MO_GOTOFF: // isPICStyleGOT: local global. + case X86II::MO_GOT: // isPICStyleGOT: other global. + case X86II::MO_PIC_BASE_OFFSET: // Darwin local global. + case X86II::MO_DARWIN_NONLAZY_PIC_BASE: // Darwin/32 external global. + case X86II::MO_DARWIN_HIDDEN_NONLAZY_PIC_BASE: // Darwin/32 hidden global. + return true; + default: + return false; + } +} + +/// X86II - This namespace holds all of the target specific flags that +/// instruction info tracks. +/// +namespace X86II { + enum { + //===------------------------------------------------------------------===// + // Instruction encodings. These are the standard/most common forms for X86 + // instructions. + // + + // PseudoFrm - This represents an instruction that is a pseudo instruction + // or one that has not been implemented yet. It is illegal to code generate + // it, but tolerated for intermediate implementation stages. + Pseudo = 0, + + /// Raw - This form is for instructions that don't have any operands, so + /// they are just a fixed opcode value, like 'leave'. + RawFrm = 1, + + /// AddRegFrm - This form is used for instructions like 'push r32' that have + /// their one register operand added to their opcode. + AddRegFrm = 2, + + /// MRMDestReg - This form is used for instructions that use the Mod/RM byte + /// to specify a destination, which in this case is a register. + /// + MRMDestReg = 3, + + /// MRMDestMem - This form is used for instructions that use the Mod/RM byte + /// to specify a destination, which in this case is memory. + /// + MRMDestMem = 4, + + /// MRMSrcReg - This form is used for instructions that use the Mod/RM byte + /// to specify a source, which in this case is a register. + /// + MRMSrcReg = 5, + + /// MRMSrcMem - This form is used for instructions that use the Mod/RM byte + /// to specify a source, which in this case is memory. + /// + MRMSrcMem = 6, + + /// MRM[0-7][rm] - These forms are used to represent instructions that use + /// a Mod/RM byte, and use the middle field to hold extended opcode + /// information. In the intel manual these are represented as /0, /1, ... + /// + + // First, instructions that operate on a register r/m operand... + MRM0r = 16, MRM1r = 17, MRM2r = 18, MRM3r = 19, // Format /0 /1 /2 /3 + MRM4r = 20, MRM5r = 21, MRM6r = 22, MRM7r = 23, // Format /4 /5 /6 /7 + + // Next, instructions that operate on a memory r/m operand... + MRM0m = 24, MRM1m = 25, MRM2m = 26, MRM3m = 27, // Format /0 /1 /2 /3 + MRM4m = 28, MRM5m = 29, MRM6m = 30, MRM7m = 31, // Format /4 /5 /6 /7 + + // MRMInitReg - This form is used for instructions whose source and + // destinations are the same register. + MRMInitReg = 32, + + FormMask = 63, + + //===------------------------------------------------------------------===// + // Actual flags... + + // OpSize - Set if this instruction requires an operand size prefix (0x66), + // which most often indicates that the instruction operates on 16 bit data + // instead of 32 bit data. + OpSize = 1 << 6, + + // AsSize - Set if this instruction requires an operand size prefix (0x67), + // which most often indicates that the instruction address 16 bit address + // instead of 32 bit address (or 32 bit address in 64 bit mode). + AdSize = 1 << 7, + + //===------------------------------------------------------------------===// + // Op0Mask - There are several prefix bytes that are used to form two byte + // opcodes. These are currently 0x0F, 0xF3, and 0xD8-0xDF. This mask is + // used to obtain the setting of this field. If no bits in this field is + // set, there is no prefix byte for obtaining a multibyte opcode. + // + Op0Shift = 8, + Op0Mask = 0xF << Op0Shift, + + // TB - TwoByte - Set if this instruction has a two byte opcode, which + // starts with a 0x0F byte before the real opcode. + TB = 1 << Op0Shift, + + // REP - The 0xF3 prefix byte indicating repetition of the following + // instruction. + REP = 2 << Op0Shift, + + // D8-DF - These escape opcodes are used by the floating point unit. These + // values must remain sequential. + D8 = 3 << Op0Shift, D9 = 4 << Op0Shift, + DA = 5 << Op0Shift, DB = 6 << Op0Shift, + DC = 7 << Op0Shift, DD = 8 << Op0Shift, + DE = 9 << Op0Shift, DF = 10 << Op0Shift, + + // XS, XD - These prefix codes are for single and double precision scalar + // floating point operations performed in the SSE registers. + XD = 11 << Op0Shift, XS = 12 << Op0Shift, + + // T8, TA - Prefix after the 0x0F prefix. + T8 = 13 << Op0Shift, TA = 14 << Op0Shift, + + // TF - Prefix before and after 0x0F + TF = 15 << Op0Shift, + + //===------------------------------------------------------------------===// + // REX_W - REX prefixes are instruction prefixes used in 64-bit mode. + // They are used to specify GPRs and SSE registers, 64-bit operand size, + // etc. We only cares about REX.W and REX.R bits and only the former is + // statically determined. + // + REXShift = 12, + REX_W = 1 << REXShift, + + //===------------------------------------------------------------------===// + // This three-bit field describes the size of an immediate operand. Zero is + // unused so that we can tell if we forgot to set a value. + ImmShift = 13, + ImmMask = 7 << ImmShift, + Imm8 = 1 << ImmShift, + Imm16 = 2 << ImmShift, + Imm32 = 3 << ImmShift, + Imm64 = 4 << ImmShift, + + //===------------------------------------------------------------------===// + // FP Instruction Classification... Zero is non-fp instruction. + + // FPTypeMask - Mask for all of the FP types... + FPTypeShift = 16, + FPTypeMask = 7 << FPTypeShift, + + // NotFP - The default, set for instructions that do not use FP registers. + NotFP = 0 << FPTypeShift, + + // ZeroArgFP - 0 arg FP instruction which implicitly pushes ST(0), f.e. fld0 + ZeroArgFP = 1 << FPTypeShift, + + // OneArgFP - 1 arg FP instructions which implicitly read ST(0), such as fst + OneArgFP = 2 << FPTypeShift, + + // OneArgFPRW - 1 arg FP instruction which implicitly read ST(0) and write a + // result back to ST(0). For example, fcos, fsqrt, etc. + // + OneArgFPRW = 3 << FPTypeShift, + + // TwoArgFP - 2 arg FP instructions which implicitly read ST(0), and an + // explicit argument, storing the result to either ST(0) or the implicit + // argument. For example: fadd, fsub, fmul, etc... + TwoArgFP = 4 << FPTypeShift, + + // CompareFP - 2 arg FP instructions which implicitly read ST(0) and an + // explicit argument, but have no destination. Example: fucom, fucomi, ... + CompareFP = 5 << FPTypeShift, + + // CondMovFP - "2 operand" floating point conditional move instructions. + CondMovFP = 6 << FPTypeShift, + + // SpecialFP - Special instruction forms. Dispatch by opcode explicitly. + SpecialFP = 7 << FPTypeShift, + + // Lock prefix + LOCKShift = 19, + LOCK = 1 << LOCKShift, + + // Segment override prefixes. Currently we just need ability to address + // stuff in gs and fs segments. + SegOvrShift = 20, + SegOvrMask = 3 << SegOvrShift, + FS = 1 << SegOvrShift, + GS = 2 << SegOvrShift, + + // Bits 22 -> 23 are unused + OpcodeShift = 24, + OpcodeMask = 0xFF << OpcodeShift + }; +} + +const int X86AddrNumOperands = 5; + +inline static bool isScale(const MachineOperand &MO) { + return MO.isImm() && + (MO.getImm() == 1 || MO.getImm() == 2 || + MO.getImm() == 4 || MO.getImm() == 8); +} + +inline static bool isLeaMem(const MachineInstr *MI, unsigned Op) { + if (MI->getOperand(Op).isFI()) return true; + return Op+4 <= MI->getNumOperands() && + MI->getOperand(Op ).isReg() && isScale(MI->getOperand(Op+1)) && + MI->getOperand(Op+2).isReg() && + (MI->getOperand(Op+3).isImm() || + MI->getOperand(Op+3).isGlobal() || + MI->getOperand(Op+3).isCPI() || + MI->getOperand(Op+3).isJTI()); +} + +inline static bool isMem(const MachineInstr *MI, unsigned Op) { + if (MI->getOperand(Op).isFI()) return true; + return Op+5 <= MI->getNumOperands() && + MI->getOperand(Op+4).isReg() && + isLeaMem(MI, Op); +} + +class X86InstrInfo : public TargetInstrInfoImpl { + X86TargetMachine &TM; + const X86RegisterInfo RI; + + /// RegOp2MemOpTable2Addr, RegOp2MemOpTable0, RegOp2MemOpTable1, + /// RegOp2MemOpTable2 - Load / store folding opcode maps. + /// + DenseMap > RegOp2MemOpTable2Addr; + DenseMap > RegOp2MemOpTable0; + DenseMap > RegOp2MemOpTable1; + DenseMap > RegOp2MemOpTable2; + + /// MemOp2RegOpTable - Load / store unfolding opcode map. + /// + DenseMap > MemOp2RegOpTable; + +public: + explicit X86InstrInfo(X86TargetMachine &tm); + + /// getRegisterInfo - TargetInstrInfo is a superset of MRegister info. As + /// such, whenever a client has an instance of instruction info, it should + /// always be able to get register info as well (through this method). + /// + virtual const X86RegisterInfo &getRegisterInfo() const { return RI; } + + /// Return true if the instruction is a register to register move and return + /// the source and dest operands and their sub-register indices by reference. + virtual bool isMoveInstr(const MachineInstr &MI, + unsigned &SrcReg, unsigned &DstReg, + unsigned &SrcSubIdx, unsigned &DstSubIdx) const; + + unsigned isLoadFromStackSlot(const MachineInstr *MI, int &FrameIndex) const; + /// isLoadFromStackSlotPostFE - Check for post-frame ptr elimination + /// stack locations as well. This uses a heuristic so it isn't + /// reliable for correctness. + unsigned isLoadFromStackSlotPostFE(const MachineInstr *MI, + int &FrameIndex) const; + + /// hasLoadFromStackSlot - If the specified machine instruction has + /// a load from a stack slot, return true along with the FrameIndex + /// of the loaded stack slot. If not, return false. Unlike + /// isLoadFromStackSlot, this returns true for any instructions that + /// loads from the stack. This is a hint only and may not catch all + /// cases. + bool hasLoadFromStackSlot(const MachineInstr *MI, int &FrameIndex) const; + + unsigned isStoreToStackSlot(const MachineInstr *MI, int &FrameIndex) const; + /// isStoreToStackSlotPostFE - Check for post-frame ptr elimination + /// stack locations as well. This uses a heuristic so it isn't + /// reliable for correctness. + unsigned isStoreToStackSlotPostFE(const MachineInstr *MI, + int &FrameIndex) const; + + /// hasStoreToStackSlot - If the specified machine instruction has a + /// store to a stack slot, return true along with the FrameIndex of + /// the loaded stack slot. If not, return false. Unlike + /// isStoreToStackSlot, this returns true for any instructions that + /// loads from the stack. This is a hint only and may not catch all + /// cases. + bool hasStoreToStackSlot(const MachineInstr *MI, int &FrameIndex) const; + + bool isReallyTriviallyReMaterializable(const MachineInstr *MI, + AliasAnalysis *AA) const; + void reMaterialize(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, + unsigned DestReg, unsigned SubIdx, + const MachineInstr *Orig, + const TargetRegisterInfo *TRI) const; + + /// convertToThreeAddress - This method must be implemented by targets that + /// set the M_CONVERTIBLE_TO_3_ADDR flag. When this flag is set, the target + /// may be able to convert a two-address instruction into a true + /// three-address instruction on demand. This allows the X86 target (for + /// example) to convert ADD and SHL instructions into LEA instructions if they + /// would require register copies due to two-addressness. + /// + /// This method returns a null pointer if the transformation cannot be + /// performed, otherwise it returns the new instruction. + /// + virtual MachineInstr *convertToThreeAddress(MachineFunction::iterator &MFI, + MachineBasicBlock::iterator &MBBI, + LiveVariables *LV) const; + + /// commuteInstruction - We have a few instructions that must be hacked on to + /// commute them. + /// + virtual MachineInstr *commuteInstruction(MachineInstr *MI, bool NewMI) const; + + // Branch analysis. + virtual bool isUnpredicatedTerminator(const MachineInstr* MI) const; + virtual bool AnalyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, + MachineBasicBlock *&FBB, + SmallVectorImpl &Cond, + bool AllowModify) const; + virtual unsigned RemoveBranch(MachineBasicBlock &MBB) const; + virtual unsigned InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, + MachineBasicBlock *FBB, + const SmallVectorImpl &Cond) const; + virtual bool copyRegToReg(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + unsigned DestReg, unsigned SrcReg, + const TargetRegisterClass *DestRC, + const TargetRegisterClass *SrcRC) const; + virtual void storeRegToStackSlot(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + unsigned SrcReg, bool isKill, int FrameIndex, + const TargetRegisterClass *RC) const; + + virtual void storeRegToAddr(MachineFunction &MF, unsigned SrcReg, bool isKill, + SmallVectorImpl &Addr, + const TargetRegisterClass *RC, + MachineInstr::mmo_iterator MMOBegin, + MachineInstr::mmo_iterator MMOEnd, + SmallVectorImpl &NewMIs) const; + + virtual void loadRegFromStackSlot(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + unsigned DestReg, int FrameIndex, + const TargetRegisterClass *RC) const; + + virtual void loadRegFromAddr(MachineFunction &MF, unsigned DestReg, + SmallVectorImpl &Addr, + const TargetRegisterClass *RC, + MachineInstr::mmo_iterator MMOBegin, + MachineInstr::mmo_iterator MMOEnd, + SmallVectorImpl &NewMIs) const; + + virtual bool spillCalleeSavedRegisters(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + const std::vector &CSI) const; + + virtual bool restoreCalleeSavedRegisters(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + const std::vector &CSI) const; + + /// foldMemoryOperand - If this target supports it, fold a load or store of + /// the specified stack slot into the specified machine instruction for the + /// specified operand(s). If this is possible, the target should perform the + /// folding and return true, otherwise it should return false. If it folds + /// the instruction, it is likely that the MachineInstruction the iterator + /// references has been changed. + virtual MachineInstr* foldMemoryOperandImpl(MachineFunction &MF, + MachineInstr* MI, + const SmallVectorImpl &Ops, + int FrameIndex) const; + + /// foldMemoryOperand - Same as the previous version except it allows folding + /// of any load and store from / to any address, not just from a specific + /// stack slot. + virtual MachineInstr* foldMemoryOperandImpl(MachineFunction &MF, + MachineInstr* MI, + const SmallVectorImpl &Ops, + MachineInstr* LoadMI) const; + + /// canFoldMemoryOperand - Returns true if the specified load / store is + /// folding is possible. + virtual bool canFoldMemoryOperand(const MachineInstr*, + const SmallVectorImpl &) const; + + /// unfoldMemoryOperand - Separate a single instruction which folded a load or + /// a store or a load and a store into two or more instruction. If this is + /// possible, returns true as well as the new instructions by reference. + virtual bool unfoldMemoryOperand(MachineFunction &MF, MachineInstr *MI, + unsigned Reg, bool UnfoldLoad, bool UnfoldStore, + SmallVectorImpl &NewMIs) const; + + virtual bool unfoldMemoryOperand(SelectionDAG &DAG, SDNode *N, + SmallVectorImpl &NewNodes) const; + + /// getOpcodeAfterMemoryUnfold - Returns the opcode of the would be new + /// instruction after load / store are unfolded from an instruction of the + /// specified opcode. It returns zero if the specified unfolding is not + /// possible. If LoadRegIndex is non-null, it is filled in with the operand + /// index of the operand which will hold the register holding the loaded + /// value. + virtual unsigned getOpcodeAfterMemoryUnfold(unsigned Opc, + bool UnfoldLoad, bool UnfoldStore, + unsigned *LoadRegIndex = 0) const; + + virtual bool BlockHasNoFallThrough(const MachineBasicBlock &MBB) const; + virtual + bool ReverseBranchCondition(SmallVectorImpl &Cond) const; + + /// isSafeToMoveRegClassDefs - Return true if it's safe to move a machine + /// instruction that defines the specified register class. + bool isSafeToMoveRegClassDefs(const TargetRegisterClass *RC) const; + + // getBaseOpcodeFor - This function returns the "base" X86 opcode for the + // specified machine instruction. + // + unsigned char getBaseOpcodeFor(const TargetInstrDesc *TID) const { + return TID->TSFlags >> X86II::OpcodeShift; + } + unsigned char getBaseOpcodeFor(unsigned Opcode) const { + return getBaseOpcodeFor(&get(Opcode)); + } + + static bool isX86_64NonExtLowByteReg(unsigned reg) { + return (reg == X86::SPL || reg == X86::BPL || + reg == X86::SIL || reg == X86::DIL); + } + + static unsigned sizeOfImm(const TargetInstrDesc *Desc); + static bool isX86_64ExtendedReg(const MachineOperand &MO); + static unsigned determineREX(const MachineInstr &MI); + + /// GetInstSize - Returns the size of the specified MachineInstr. + /// + virtual unsigned GetInstSizeInBytes(const MachineInstr *MI) const; + + /// getGlobalBaseReg - Return a virtual register initialized with the + /// the global base register value. Output instructions required to + /// initialize the register in the function entry block, if necessary. + /// + unsigned getGlobalBaseReg(MachineFunction *MF) const; + + virtual bool isProfitableToDuplicateIndirectBranch() const { return true; } + +private: + MachineInstr* foldMemoryOperandImpl(MachineFunction &MF, + MachineInstr* MI, + unsigned OpNum, + const SmallVectorImpl &MOs, + unsigned Size, unsigned Alignment) const; + + /// isFrameOperand - Return true and the FrameIndex if the specified + /// operand and follow operands form a reference to the stack frame. + bool isFrameOperand(const MachineInstr *MI, unsigned int Op, + int &FrameIndex) const; +}; + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/lib/Target/X86/X86InstrInfo.td b/libclamav/c++/llvm/lib/Target/X86/X86InstrInfo.td new file mode 100644 index 000000000..1cf552940 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/X86/X86InstrInfo.td @@ -0,0 +1,4676 @@ +//===- X86InstrInfo.td - Describe the X86 Instruction Set --*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file describes the X86 instruction set, defining the instructions, and +// properties of the instructions which are needed for code generation, machine +// code emission, and analysis. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// X86 specific DAG Nodes. +// + +def SDTIntShiftDOp: SDTypeProfile<1, 3, + [SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>, + SDTCisInt<0>, SDTCisInt<3>]>; + +def SDTX86CmpTest : SDTypeProfile<0, 2, [SDTCisSameAs<0, 1>]>; + +def SDTX86Cmov : SDTypeProfile<1, 4, + [SDTCisSameAs<0, 1>, SDTCisSameAs<1, 2>, + SDTCisVT<3, i8>, SDTCisVT<4, i32>]>; + +// Unary and binary operator instructions that set EFLAGS as a side-effect. +def SDTUnaryArithWithFlags : SDTypeProfile<1, 1, + [SDTCisInt<0>]>; +def SDTBinaryArithWithFlags : SDTypeProfile<1, 2, + [SDTCisSameAs<0, 1>, + SDTCisSameAs<0, 2>, + SDTCisInt<0>]>; +def SDTX86BrCond : SDTypeProfile<0, 3, + [SDTCisVT<0, OtherVT>, + SDTCisVT<1, i8>, SDTCisVT<2, i32>]>; + +def SDTX86SetCC : SDTypeProfile<1, 2, + [SDTCisVT<0, i8>, + SDTCisVT<1, i8>, SDTCisVT<2, i32>]>; + +def SDTX86cas : SDTypeProfile<0, 3, [SDTCisPtrTy<0>, SDTCisInt<1>, + SDTCisVT<2, i8>]>; +def SDTX86cas8 : SDTypeProfile<0, 1, [SDTCisPtrTy<0>]>; + +def SDTX86atomicBinary : SDTypeProfile<2, 3, [SDTCisInt<0>, SDTCisInt<1>, + SDTCisPtrTy<2>, SDTCisInt<3>,SDTCisInt<4>]>; +def SDTX86Ret : SDTypeProfile<0, -1, [SDTCisVT<0, i16>]>; + +def SDT_X86CallSeqStart : SDCallSeqStart<[SDTCisVT<0, i32>]>; +def SDT_X86CallSeqEnd : SDCallSeqEnd<[SDTCisVT<0, i32>, + SDTCisVT<1, i32>]>; + +def SDT_X86Call : SDTypeProfile<0, -1, [SDTCisVT<0, iPTR>]>; + +def SDT_X86VASTART_SAVE_XMM_REGS : SDTypeProfile<0, -1, [SDTCisVT<0, i8>, + SDTCisVT<1, iPTR>, + SDTCisVT<2, iPTR>]>; + +def SDTX86RepStr : SDTypeProfile<0, 1, [SDTCisVT<0, OtherVT>]>; + +def SDTX86RdTsc : SDTypeProfile<0, 0, []>; + +def SDTX86Wrapper : SDTypeProfile<1, 1, [SDTCisSameAs<0, 1>, SDTCisPtrTy<0>]>; + +def SDT_X86TLSADDR : SDTypeProfile<0, 1, [SDTCisInt<0>]>; + +def SDT_X86SegmentBaseAddress : SDTypeProfile<1, 1, [SDTCisPtrTy<0>]>; + +def SDT_X86EHRET : SDTypeProfile<0, 1, [SDTCisInt<0>]>; + +def SDT_X86TCRET : SDTypeProfile<0, 2, [SDTCisPtrTy<0>, SDTCisVT<1, i32>]>; + +def X86bsf : SDNode<"X86ISD::BSF", SDTIntUnaryOp>; +def X86bsr : SDNode<"X86ISD::BSR", SDTIntUnaryOp>; +def X86shld : SDNode<"X86ISD::SHLD", SDTIntShiftDOp>; +def X86shrd : SDNode<"X86ISD::SHRD", SDTIntShiftDOp>; + +def X86cmp : SDNode<"X86ISD::CMP" , SDTX86CmpTest>; + +def X86bt : SDNode<"X86ISD::BT", SDTX86CmpTest>; + +def X86cmov : SDNode<"X86ISD::CMOV", SDTX86Cmov>; +def X86brcond : SDNode<"X86ISD::BRCOND", SDTX86BrCond, + [SDNPHasChain]>; +def X86setcc : SDNode<"X86ISD::SETCC", SDTX86SetCC>; + +def X86cas : SDNode<"X86ISD::LCMPXCHG_DAG", SDTX86cas, + [SDNPHasChain, SDNPInFlag, SDNPOutFlag, SDNPMayStore, + SDNPMayLoad]>; +def X86cas8 : SDNode<"X86ISD::LCMPXCHG8_DAG", SDTX86cas8, + [SDNPHasChain, SDNPInFlag, SDNPOutFlag, SDNPMayStore, + SDNPMayLoad]>; +def X86AtomAdd64 : SDNode<"X86ISD::ATOMADD64_DAG", SDTX86atomicBinary, + [SDNPHasChain, SDNPMayStore, + SDNPMayLoad, SDNPMemOperand]>; +def X86AtomSub64 : SDNode<"X86ISD::ATOMSUB64_DAG", SDTX86atomicBinary, + [SDNPHasChain, SDNPMayStore, + SDNPMayLoad, SDNPMemOperand]>; +def X86AtomOr64 : SDNode<"X86ISD::ATOMOR64_DAG", SDTX86atomicBinary, + [SDNPHasChain, SDNPMayStore, + SDNPMayLoad, SDNPMemOperand]>; +def X86AtomXor64 : SDNode<"X86ISD::ATOMXOR64_DAG", SDTX86atomicBinary, + [SDNPHasChain, SDNPMayStore, + SDNPMayLoad, SDNPMemOperand]>; +def X86AtomAnd64 : SDNode<"X86ISD::ATOMAND64_DAG", SDTX86atomicBinary, + [SDNPHasChain, SDNPMayStore, + SDNPMayLoad, SDNPMemOperand]>; +def X86AtomNand64 : SDNode<"X86ISD::ATOMNAND64_DAG", SDTX86atomicBinary, + [SDNPHasChain, SDNPMayStore, + SDNPMayLoad, SDNPMemOperand]>; +def X86AtomSwap64 : SDNode<"X86ISD::ATOMSWAP64_DAG", SDTX86atomicBinary, + [SDNPHasChain, SDNPMayStore, + SDNPMayLoad, SDNPMemOperand]>; +def X86retflag : SDNode<"X86ISD::RET_FLAG", SDTX86Ret, + [SDNPHasChain, SDNPOptInFlag]>; + +def X86vastart_save_xmm_regs : + SDNode<"X86ISD::VASTART_SAVE_XMM_REGS", + SDT_X86VASTART_SAVE_XMM_REGS, + [SDNPHasChain]>; + +def X86callseq_start : + SDNode<"ISD::CALLSEQ_START", SDT_X86CallSeqStart, + [SDNPHasChain, SDNPOutFlag]>; +def X86callseq_end : + SDNode<"ISD::CALLSEQ_END", SDT_X86CallSeqEnd, + [SDNPHasChain, SDNPOptInFlag, SDNPOutFlag]>; + +def X86call : SDNode<"X86ISD::CALL", SDT_X86Call, + [SDNPHasChain, SDNPOutFlag, SDNPOptInFlag]>; + +def X86rep_stos: SDNode<"X86ISD::REP_STOS", SDTX86RepStr, + [SDNPHasChain, SDNPInFlag, SDNPOutFlag, SDNPMayStore]>; +def X86rep_movs: SDNode<"X86ISD::REP_MOVS", SDTX86RepStr, + [SDNPHasChain, SDNPInFlag, SDNPOutFlag, SDNPMayStore, + SDNPMayLoad]>; + +def X86rdtsc : SDNode<"X86ISD::RDTSC_DAG",SDTX86RdTsc, + [SDNPHasChain, SDNPOutFlag, SDNPSideEffect]>; + +def X86Wrapper : SDNode<"X86ISD::Wrapper", SDTX86Wrapper>; +def X86WrapperRIP : SDNode<"X86ISD::WrapperRIP", SDTX86Wrapper>; + +def X86tlsaddr : SDNode<"X86ISD::TLSADDR", SDT_X86TLSADDR, + [SDNPHasChain, SDNPOptInFlag, SDNPOutFlag]>; +def X86SegmentBaseAddress : SDNode<"X86ISD::SegmentBaseAddress", + SDT_X86SegmentBaseAddress, []>; + +def X86ehret : SDNode<"X86ISD::EH_RETURN", SDT_X86EHRET, + [SDNPHasChain]>; + +def X86tcret : SDNode<"X86ISD::TC_RETURN", SDT_X86TCRET, + [SDNPHasChain, SDNPOptInFlag]>; + +def X86add_flag : SDNode<"X86ISD::ADD", SDTBinaryArithWithFlags>; +def X86sub_flag : SDNode<"X86ISD::SUB", SDTBinaryArithWithFlags>; +def X86smul_flag : SDNode<"X86ISD::SMUL", SDTBinaryArithWithFlags>; +def X86umul_flag : SDNode<"X86ISD::UMUL", SDTUnaryArithWithFlags>; +def X86inc_flag : SDNode<"X86ISD::INC", SDTUnaryArithWithFlags>; +def X86dec_flag : SDNode<"X86ISD::DEC", SDTUnaryArithWithFlags>; +def X86or_flag : SDNode<"X86ISD::OR", SDTBinaryArithWithFlags>; +def X86xor_flag : SDNode<"X86ISD::XOR", SDTBinaryArithWithFlags>; +def X86and_flag : SDNode<"X86ISD::AND", SDTBinaryArithWithFlags>; + +def X86mul_imm : SDNode<"X86ISD::MUL_IMM", SDTIntBinOp>; + +//===----------------------------------------------------------------------===// +// X86 Operand Definitions. +// + +def i32imm_pcrel : Operand { + let PrintMethod = "print_pcrel_imm"; +} + +// A version of ptr_rc which excludes SP, ESP, and RSP. This is used for +// the index operand of an address, to conform to x86 encoding restrictions. +def ptr_rc_nosp : PointerLikeRegClass<1>; + +// *mem - Operand definitions for the funky X86 addressing mode operands. +// +def X86MemAsmOperand : AsmOperandClass { + let Name = "Mem"; + let SuperClass = ?; +} +class X86MemOperand : Operand { + let PrintMethod = printMethod; + let MIOperandInfo = (ops ptr_rc, i8imm, ptr_rc_nosp, i32imm, i8imm); + let ParserMatchClass = X86MemAsmOperand; +} + +def opaque32mem : X86MemOperand<"printopaquemem">; +def opaque48mem : X86MemOperand<"printopaquemem">; +def opaque80mem : X86MemOperand<"printopaquemem">; + +def i8mem : X86MemOperand<"printi8mem">; +def i16mem : X86MemOperand<"printi16mem">; +def i32mem : X86MemOperand<"printi32mem">; +def i64mem : X86MemOperand<"printi64mem">; +def i128mem : X86MemOperand<"printi128mem">; +//def i256mem : X86MemOperand<"printi256mem">; +def f32mem : X86MemOperand<"printf32mem">; +def f64mem : X86MemOperand<"printf64mem">; +def f80mem : X86MemOperand<"printf80mem">; +def f128mem : X86MemOperand<"printf128mem">; +//def f256mem : X86MemOperand<"printf256mem">; + +// A version of i8mem for use on x86-64 that uses GR64_NOREX instead of +// plain GR64, so that it doesn't potentially require a REX prefix. +def i8mem_NOREX : Operand { + let PrintMethod = "printi8mem"; + let MIOperandInfo = (ops GR64_NOREX, i8imm, GR64_NOREX_NOSP, i32imm, i8imm); + let ParserMatchClass = X86MemAsmOperand; +} + +def lea32mem : Operand { + let PrintMethod = "printlea32mem"; + let MIOperandInfo = (ops GR32, i8imm, GR32_NOSP, i32imm); + let ParserMatchClass = X86MemAsmOperand; +} + +def SSECC : Operand { + let PrintMethod = "printSSECC"; +} + +def ImmSExt8AsmOperand : AsmOperandClass { + let Name = "ImmSExt8"; + let SuperClass = ImmAsmOperand; +} + +// A couple of more descriptive operand definitions. +// 16-bits but only 8 bits are significant. +def i16i8imm : Operand { + let ParserMatchClass = ImmSExt8AsmOperand; +} +// 32-bits but only 8 bits are significant. +def i32i8imm : Operand { + let ParserMatchClass = ImmSExt8AsmOperand; +} + +// Branch targets have OtherVT type and print as pc-relative values. +def brtarget : Operand { + let PrintMethod = "print_pcrel_imm"; +} + +def brtarget8 : Operand { + let PrintMethod = "print_pcrel_imm"; +} + +//===----------------------------------------------------------------------===// +// X86 Complex Pattern Definitions. +// + +// Define X86 specific addressing mode. +def addr : ComplexPattern; +def lea32addr : ComplexPattern; +def tls32addr : ComplexPattern; + +//===----------------------------------------------------------------------===// +// X86 Instruction Predicate Definitions. +def HasMMX : Predicate<"Subtarget->hasMMX()">; +def HasSSE1 : Predicate<"Subtarget->hasSSE1()">; +def HasSSE2 : Predicate<"Subtarget->hasSSE2()">; +def HasSSE3 : Predicate<"Subtarget->hasSSE3()">; +def HasSSSE3 : Predicate<"Subtarget->hasSSSE3()">; +def HasSSE41 : Predicate<"Subtarget->hasSSE41()">; +def HasSSE42 : Predicate<"Subtarget->hasSSE42()">; +def HasSSE4A : Predicate<"Subtarget->hasSSE4A()">; +def HasAVX : Predicate<"Subtarget->hasAVX()">; +def HasFMA3 : Predicate<"Subtarget->hasFMA3()">; +def HasFMA4 : Predicate<"Subtarget->hasFMA4()">; +def FPStackf32 : Predicate<"!Subtarget->hasSSE1()">; +def FPStackf64 : Predicate<"!Subtarget->hasSSE2()">; +def In32BitMode : Predicate<"!Subtarget->is64Bit()">; +def In64BitMode : Predicate<"Subtarget->is64Bit()">; +def IsWin64 : Predicate<"Subtarget->isTargetWin64()">; +def NotWin64 : Predicate<"!Subtarget->isTargetWin64()">; +def SmallCode : Predicate<"TM.getCodeModel() == CodeModel::Small">; +def KernelCode : Predicate<"TM.getCodeModel() == CodeModel::Kernel">; +def FarData : Predicate<"TM.getCodeModel() != CodeModel::Small &&" + "TM.getCodeModel() != CodeModel::Kernel">; +def NearData : Predicate<"TM.getCodeModel() == CodeModel::Small ||" + "TM.getCodeModel() == CodeModel::Kernel">; +def IsStatic : Predicate<"TM.getRelocationModel() == Reloc::Static">; +def OptForSpeed : Predicate<"!OptForSize">; +def FastBTMem : Predicate<"!Subtarget->isBTMemSlow()">; +def CallImmAddr : Predicate<"Subtarget->IsLegalToCallImmediateAddr(TM)">; + +//===----------------------------------------------------------------------===// +// X86 Instruction Format Definitions. +// + +include "X86InstrFormats.td" + +//===----------------------------------------------------------------------===// +// Pattern fragments... +// + +// X86 specific condition code. These correspond to CondCode in +// X86InstrInfo.h. They must be kept in synch. +def X86_COND_A : PatLeaf<(i8 0)>; // alt. COND_NBE +def X86_COND_AE : PatLeaf<(i8 1)>; // alt. COND_NC +def X86_COND_B : PatLeaf<(i8 2)>; // alt. COND_C +def X86_COND_BE : PatLeaf<(i8 3)>; // alt. COND_NA +def X86_COND_E : PatLeaf<(i8 4)>; // alt. COND_Z +def X86_COND_G : PatLeaf<(i8 5)>; // alt. COND_NLE +def X86_COND_GE : PatLeaf<(i8 6)>; // alt. COND_NL +def X86_COND_L : PatLeaf<(i8 7)>; // alt. COND_NGE +def X86_COND_LE : PatLeaf<(i8 8)>; // alt. COND_NG +def X86_COND_NE : PatLeaf<(i8 9)>; // alt. COND_NZ +def X86_COND_NO : PatLeaf<(i8 10)>; +def X86_COND_NP : PatLeaf<(i8 11)>; // alt. COND_PO +def X86_COND_NS : PatLeaf<(i8 12)>; +def X86_COND_O : PatLeaf<(i8 13)>; +def X86_COND_P : PatLeaf<(i8 14)>; // alt. COND_PE +def X86_COND_S : PatLeaf<(i8 15)>; + +def i16immSExt8 : PatLeaf<(i16 imm), [{ + // i16immSExt8 predicate - True if the 16-bit immediate fits in a 8-bit + // sign extended field. + return (int16_t)N->getZExtValue() == (int8_t)N->getZExtValue(); +}]>; + +def i32immSExt8 : PatLeaf<(i32 imm), [{ + // i32immSExt8 predicate - True if the 32-bit immediate fits in a 8-bit + // sign extended field. + return (int32_t)N->getZExtValue() == (int8_t)N->getZExtValue(); +}]>; + +// Helper fragments for loads. +// It's always safe to treat a anyext i16 load as a i32 load if the i16 is +// known to be 32-bit aligned or better. Ditto for i8 to i16. +def loadi16 : PatFrag<(ops node:$ptr), (i16 (unindexedload node:$ptr)), [{ + LoadSDNode *LD = cast(N); + if (const Value *Src = LD->getSrcValue()) + if (const PointerType *PT = dyn_cast(Src->getType())) + if (PT->getAddressSpace() > 255) + return false; + ISD::LoadExtType ExtType = LD->getExtensionType(); + if (ExtType == ISD::NON_EXTLOAD) + return true; + if (ExtType == ISD::EXTLOAD) + return LD->getAlignment() >= 2 && !LD->isVolatile(); + return false; +}]>; + +def loadi16_anyext : PatFrag<(ops node:$ptr), (i32 (unindexedload node:$ptr)), [{ + LoadSDNode *LD = cast(N); + if (const Value *Src = LD->getSrcValue()) + if (const PointerType *PT = dyn_cast(Src->getType())) + if (PT->getAddressSpace() > 255) + return false; + ISD::LoadExtType ExtType = LD->getExtensionType(); + if (ExtType == ISD::EXTLOAD) + return LD->getAlignment() >= 2 && !LD->isVolatile(); + return false; +}]>; + +def loadi32 : PatFrag<(ops node:$ptr), (i32 (unindexedload node:$ptr)), [{ + LoadSDNode *LD = cast(N); + if (const Value *Src = LD->getSrcValue()) + if (const PointerType *PT = dyn_cast(Src->getType())) + if (PT->getAddressSpace() > 255) + return false; + ISD::LoadExtType ExtType = LD->getExtensionType(); + if (ExtType == ISD::NON_EXTLOAD) + return true; + if (ExtType == ISD::EXTLOAD) + return LD->getAlignment() >= 4 && !LD->isVolatile(); + return false; +}]>; + +def nvloadi32 : PatFrag<(ops node:$ptr), (i32 (unindexedload node:$ptr)), [{ + LoadSDNode *LD = cast(N); + if (const Value *Src = LD->getSrcValue()) + if (const PointerType *PT = dyn_cast(Src->getType())) + if (PT->getAddressSpace() > 255) + return false; + if (LD->isVolatile()) + return false; + ISD::LoadExtType ExtType = LD->getExtensionType(); + if (ExtType == ISD::NON_EXTLOAD) + return true; + if (ExtType == ISD::EXTLOAD) + return LD->getAlignment() >= 4; + return false; +}]>; + +def gsload : PatFrag<(ops node:$ptr), (load node:$ptr), [{ + if (const Value *Src = cast(N)->getSrcValue()) + if (const PointerType *PT = dyn_cast(Src->getType())) + return PT->getAddressSpace() == 256; + return false; +}]>; + +def fsload : PatFrag<(ops node:$ptr), (load node:$ptr), [{ + if (const Value *Src = cast(N)->getSrcValue()) + if (const PointerType *PT = dyn_cast(Src->getType())) + return PT->getAddressSpace() == 257; + return false; +}]>; + +def loadi8 : PatFrag<(ops node:$ptr), (i8 (load node:$ptr)), [{ + if (const Value *Src = cast(N)->getSrcValue()) + if (const PointerType *PT = dyn_cast(Src->getType())) + if (PT->getAddressSpace() > 255) + return false; + return true; +}]>; +def loadi64 : PatFrag<(ops node:$ptr), (i64 (load node:$ptr)), [{ + if (const Value *Src = cast(N)->getSrcValue()) + if (const PointerType *PT = dyn_cast(Src->getType())) + if (PT->getAddressSpace() > 255) + return false; + return true; +}]>; + +def loadf32 : PatFrag<(ops node:$ptr), (f32 (load node:$ptr)), [{ + if (const Value *Src = cast(N)->getSrcValue()) + if (const PointerType *PT = dyn_cast(Src->getType())) + if (PT->getAddressSpace() > 255) + return false; + return true; +}]>; +def loadf64 : PatFrag<(ops node:$ptr), (f64 (load node:$ptr)), [{ + if (const Value *Src = cast(N)->getSrcValue()) + if (const PointerType *PT = dyn_cast(Src->getType())) + if (PT->getAddressSpace() > 255) + return false; + return true; +}]>; +def loadf80 : PatFrag<(ops node:$ptr), (f80 (load node:$ptr)), [{ + if (const Value *Src = cast(N)->getSrcValue()) + if (const PointerType *PT = dyn_cast(Src->getType())) + if (PT->getAddressSpace() > 255) + return false; + return true; +}]>; + +def sextloadi16i8 : PatFrag<(ops node:$ptr), (i16 (sextloadi8 node:$ptr))>; +def sextloadi32i8 : PatFrag<(ops node:$ptr), (i32 (sextloadi8 node:$ptr))>; +def sextloadi32i16 : PatFrag<(ops node:$ptr), (i32 (sextloadi16 node:$ptr))>; + +def zextloadi8i1 : PatFrag<(ops node:$ptr), (i8 (zextloadi1 node:$ptr))>; +def zextloadi16i1 : PatFrag<(ops node:$ptr), (i16 (zextloadi1 node:$ptr))>; +def zextloadi32i1 : PatFrag<(ops node:$ptr), (i32 (zextloadi1 node:$ptr))>; +def zextloadi16i8 : PatFrag<(ops node:$ptr), (i16 (zextloadi8 node:$ptr))>; +def zextloadi32i8 : PatFrag<(ops node:$ptr), (i32 (zextloadi8 node:$ptr))>; +def zextloadi32i16 : PatFrag<(ops node:$ptr), (i32 (zextloadi16 node:$ptr))>; + +def extloadi8i1 : PatFrag<(ops node:$ptr), (i8 (extloadi1 node:$ptr))>; +def extloadi16i1 : PatFrag<(ops node:$ptr), (i16 (extloadi1 node:$ptr))>; +def extloadi32i1 : PatFrag<(ops node:$ptr), (i32 (extloadi1 node:$ptr))>; +def extloadi16i8 : PatFrag<(ops node:$ptr), (i16 (extloadi8 node:$ptr))>; +def extloadi32i8 : PatFrag<(ops node:$ptr), (i32 (extloadi8 node:$ptr))>; +def extloadi32i16 : PatFrag<(ops node:$ptr), (i32 (extloadi16 node:$ptr))>; + + +// An 'and' node with a single use. +def and_su : PatFrag<(ops node:$lhs, node:$rhs), (and node:$lhs, node:$rhs), [{ + return N->hasOneUse(); +}]>; +// An 'srl' node with a single use. +def srl_su : PatFrag<(ops node:$lhs, node:$rhs), (srl node:$lhs, node:$rhs), [{ + return N->hasOneUse(); +}]>; +// An 'trunc' node with a single use. +def trunc_su : PatFrag<(ops node:$src), (trunc node:$src), [{ + return N->hasOneUse(); +}]>; + +// 'shld' and 'shrd' instruction patterns. Note that even though these have +// the srl and shl in their patterns, the C++ code must still check for them, +// because predicates are tested before children nodes are explored. + +def shrd : PatFrag<(ops node:$src1, node:$amt1, node:$src2, node:$amt2), + (or (srl node:$src1, node:$amt1), + (shl node:$src2, node:$amt2)), [{ + assert(N->getOpcode() == ISD::OR); + return N->getOperand(0).getOpcode() == ISD::SRL && + N->getOperand(1).getOpcode() == ISD::SHL && + isa(N->getOperand(0).getOperand(1)) && + isa(N->getOperand(1).getOperand(1)) && + N->getOperand(0).getConstantOperandVal(1) == + N->getValueSizeInBits(0) - N->getOperand(1).getConstantOperandVal(1); +}]>; + +def shld : PatFrag<(ops node:$src1, node:$amt1, node:$src2, node:$amt2), + (or (shl node:$src1, node:$amt1), + (srl node:$src2, node:$amt2)), [{ + assert(N->getOpcode() == ISD::OR); + return N->getOperand(0).getOpcode() == ISD::SHL && + N->getOperand(1).getOpcode() == ISD::SRL && + isa(N->getOperand(0).getOperand(1)) && + isa(N->getOperand(1).getOperand(1)) && + N->getOperand(0).getConstantOperandVal(1) == + N->getValueSizeInBits(0) - N->getOperand(1).getConstantOperandVal(1); +}]>; + +//===----------------------------------------------------------------------===// +// Instruction list... +// + +// ADJCALLSTACKDOWN/UP implicitly use/def ESP because they may be expanded into +// a stack adjustment and the codegen must know that they may modify the stack +// pointer before prolog-epilog rewriting occurs. +// Pessimistically assume ADJCALLSTACKDOWN / ADJCALLSTACKUP will become +// sub / add which can clobber EFLAGS. +let Defs = [ESP, EFLAGS], Uses = [ESP] in { +def ADJCALLSTACKDOWN32 : I<0, Pseudo, (outs), (ins i32imm:$amt), + "#ADJCALLSTACKDOWN", + [(X86callseq_start timm:$amt)]>, + Requires<[In32BitMode]>; +def ADJCALLSTACKUP32 : I<0, Pseudo, (outs), (ins i32imm:$amt1, i32imm:$amt2), + "#ADJCALLSTACKUP", + [(X86callseq_end timm:$amt1, timm:$amt2)]>, + Requires<[In32BitMode]>; +} + +// x86-64 va_start lowering magic. +let usesCustomInserter = 1 in +def VASTART_SAVE_XMM_REGS : I<0, Pseudo, + (outs), + (ins GR8:$al, + i64imm:$regsavefi, i64imm:$offset, + variable_ops), + "#VASTART_SAVE_XMM_REGS $al, $regsavefi, $offset", + [(X86vastart_save_xmm_regs GR8:$al, + imm:$regsavefi, + imm:$offset)]>; + +// Nop +let neverHasSideEffects = 1 in { + def NOOP : I<0x90, RawFrm, (outs), (ins), "nop", []>; + def NOOPL : I<0x1f, MRM0m, (outs), (ins i32mem:$zero), + "nopl\t$zero", []>, TB; +} + +// Trap +def INT3 : I<0xcc, RawFrm, (outs), (ins), "int\t3", []>; +def INT : I<0xcd, RawFrm, (outs), (ins i8imm:$trap), "int\t$trap", []>; + +// PIC base construction. This expands to code that looks like this: +// call $next_inst +// popl %destreg" +let neverHasSideEffects = 1, isNotDuplicable = 1, Uses = [ESP] in + def MOVPC32r : Ii32<0xE8, Pseudo, (outs GR32:$reg), (ins i32imm:$label), + "", []>; + +//===----------------------------------------------------------------------===// +// Control Flow Instructions... +// + +// Return instructions. +let isTerminator = 1, isReturn = 1, isBarrier = 1, + hasCtrlDep = 1, FPForm = SpecialFP, FPFormBits = SpecialFP.Value in { + def RET : I <0xC3, RawFrm, (outs), (ins variable_ops), + "ret", + [(X86retflag 0)]>; + def RETI : Ii16<0xC2, RawFrm, (outs), (ins i16imm:$amt, variable_ops), + "ret\t$amt", + [(X86retflag timm:$amt)]>; + def LRET : I <0xCB, RawFrm, (outs), (ins), + "lret", []>; + def LRETI : Ii16<0xCA, RawFrm, (outs), (ins i16imm:$amt), + "lret\t$amt", []>; +} + +// All branches are RawFrm, Void, Branch, and Terminators +let isBranch = 1, isTerminator = 1 in + class IBr opcode, dag ins, string asm, list pattern> : + I; + +let isBranch = 1, isBarrier = 1 in { + def JMP : IBr<0xE9, (ins brtarget:$dst), "jmp\t$dst", [(br bb:$dst)]>; + def JMP8 : IBr<0xEB, (ins brtarget8:$dst), "jmp\t$dst", []>; +} + +// Indirect branches +let isBranch = 1, isTerminator = 1, isBarrier = 1, isIndirectBranch = 1 in { + def JMP32r : I<0xFF, MRM4r, (outs), (ins GR32:$dst), "jmp{l}\t{*}$dst", + [(brind GR32:$dst)]>; + def JMP32m : I<0xFF, MRM4m, (outs), (ins i32mem:$dst), "jmp{l}\t{*}$dst", + [(brind (loadi32 addr:$dst))]>; + + def FARJMP16i : Iseg16<0xEA, RawFrm, (outs), + (ins i16imm:$seg, i16imm:$off), + "ljmp{w}\t$seg, $off", []>, OpSize; + def FARJMP32i : Iseg32<0xEA, RawFrm, (outs), + (ins i16imm:$seg, i32imm:$off), + "ljmp{l}\t$seg, $off", []>; + + def FARJMP16m : I<0xFF, MRM5m, (outs), (ins opaque32mem:$dst), + "ljmp{w}\t{*}$dst", []>, OpSize; + def FARJMP32m : I<0xFF, MRM5m, (outs), (ins opaque48mem:$dst), + "ljmp{l}\t{*}$dst", []>; +} + +// Conditional branches +let Uses = [EFLAGS] in { +// Short conditional jumps +def JO8 : IBr<0x70, (ins brtarget8:$dst), "jo\t$dst", []>; +def JNO8 : IBr<0x71, (ins brtarget8:$dst), "jno\t$dst", []>; +def JB8 : IBr<0x72, (ins brtarget8:$dst), "jb\t$dst", []>; +def JAE8 : IBr<0x73, (ins brtarget8:$dst), "jae\t$dst", []>; +def JE8 : IBr<0x74, (ins brtarget8:$dst), "je\t$dst", []>; +def JNE8 : IBr<0x75, (ins brtarget8:$dst), "jne\t$dst", []>; +def JBE8 : IBr<0x76, (ins brtarget8:$dst), "jbe\t$dst", []>; +def JA8 : IBr<0x77, (ins brtarget8:$dst), "ja\t$dst", []>; +def JS8 : IBr<0x78, (ins brtarget8:$dst), "js\t$dst", []>; +def JNS8 : IBr<0x79, (ins brtarget8:$dst), "jns\t$dst", []>; +def JP8 : IBr<0x7A, (ins brtarget8:$dst), "jp\t$dst", []>; +def JNP8 : IBr<0x7B, (ins brtarget8:$dst), "jnp\t$dst", []>; +def JL8 : IBr<0x7C, (ins brtarget8:$dst), "jl\t$dst", []>; +def JGE8 : IBr<0x7D, (ins brtarget8:$dst), "jge\t$dst", []>; +def JLE8 : IBr<0x7E, (ins brtarget8:$dst), "jle\t$dst", []>; +def JG8 : IBr<0x7F, (ins brtarget8:$dst), "jg\t$dst", []>; + +def JCXZ8 : IBr<0xE3, (ins brtarget8:$dst), "jcxz\t$dst", []>; + +def JE : IBr<0x84, (ins brtarget:$dst), "je\t$dst", + [(X86brcond bb:$dst, X86_COND_E, EFLAGS)]>, TB; +def JNE : IBr<0x85, (ins brtarget:$dst), "jne\t$dst", + [(X86brcond bb:$dst, X86_COND_NE, EFLAGS)]>, TB; +def JL : IBr<0x8C, (ins brtarget:$dst), "jl\t$dst", + [(X86brcond bb:$dst, X86_COND_L, EFLAGS)]>, TB; +def JLE : IBr<0x8E, (ins brtarget:$dst), "jle\t$dst", + [(X86brcond bb:$dst, X86_COND_LE, EFLAGS)]>, TB; +def JG : IBr<0x8F, (ins brtarget:$dst), "jg\t$dst", + [(X86brcond bb:$dst, X86_COND_G, EFLAGS)]>, TB; +def JGE : IBr<0x8D, (ins brtarget:$dst), "jge\t$dst", + [(X86brcond bb:$dst, X86_COND_GE, EFLAGS)]>, TB; + +def JB : IBr<0x82, (ins brtarget:$dst), "jb\t$dst", + [(X86brcond bb:$dst, X86_COND_B, EFLAGS)]>, TB; +def JBE : IBr<0x86, (ins brtarget:$dst), "jbe\t$dst", + [(X86brcond bb:$dst, X86_COND_BE, EFLAGS)]>, TB; +def JA : IBr<0x87, (ins brtarget:$dst), "ja\t$dst", + [(X86brcond bb:$dst, X86_COND_A, EFLAGS)]>, TB; +def JAE : IBr<0x83, (ins brtarget:$dst), "jae\t$dst", + [(X86brcond bb:$dst, X86_COND_AE, EFLAGS)]>, TB; + +def JS : IBr<0x88, (ins brtarget:$dst), "js\t$dst", + [(X86brcond bb:$dst, X86_COND_S, EFLAGS)]>, TB; +def JNS : IBr<0x89, (ins brtarget:$dst), "jns\t$dst", + [(X86brcond bb:$dst, X86_COND_NS, EFLAGS)]>, TB; +def JP : IBr<0x8A, (ins brtarget:$dst), "jp\t$dst", + [(X86brcond bb:$dst, X86_COND_P, EFLAGS)]>, TB; +def JNP : IBr<0x8B, (ins brtarget:$dst), "jnp\t$dst", + [(X86brcond bb:$dst, X86_COND_NP, EFLAGS)]>, TB; +def JO : IBr<0x80, (ins brtarget:$dst), "jo\t$dst", + [(X86brcond bb:$dst, X86_COND_O, EFLAGS)]>, TB; +def JNO : IBr<0x81, (ins brtarget:$dst), "jno\t$dst", + [(X86brcond bb:$dst, X86_COND_NO, EFLAGS)]>, TB; +} // Uses = [EFLAGS] + +// Loop instructions + +def LOOP : I<0xE2, RawFrm, (ins brtarget8:$dst), (outs), "loop\t$dst", []>; +def LOOPE : I<0xE1, RawFrm, (ins brtarget8:$dst), (outs), "loope\t$dst", []>; +def LOOPNE : I<0xE0, RawFrm, (ins brtarget8:$dst), (outs), "loopne\t$dst", []>; + +//===----------------------------------------------------------------------===// +// Call Instructions... +// +let isCall = 1 in + // All calls clobber the non-callee saved registers. ESP is marked as + // a use to prevent stack-pointer assignments that appear immediately + // before calls from potentially appearing dead. Uses for argument + // registers are added manually. + let Defs = [EAX, ECX, EDX, FP0, FP1, FP2, FP3, FP4, FP5, FP6, ST0, + MM0, MM1, MM2, MM3, MM4, MM5, MM6, MM7, + XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6, XMM7, + XMM8, XMM9, XMM10, XMM11, XMM12, XMM13, XMM14, XMM15, EFLAGS], + Uses = [ESP] in { + def CALLpcrel32 : Ii32<0xE8, RawFrm, + (outs), (ins i32imm_pcrel:$dst,variable_ops), + "call\t$dst", []>; + def CALL32r : I<0xFF, MRM2r, (outs), (ins GR32:$dst, variable_ops), + "call\t{*}$dst", [(X86call GR32:$dst)]>; + def CALL32m : I<0xFF, MRM2m, (outs), (ins i32mem:$dst, variable_ops), + "call\t{*}$dst", [(X86call (loadi32 addr:$dst))]>; + + def FARCALL16i : Iseg16<0x9A, RawFrm, (outs), + (ins i16imm:$seg, i16imm:$off), + "lcall{w}\t$seg, $off", []>, OpSize; + def FARCALL32i : Iseg32<0x9A, RawFrm, (outs), + (ins i16imm:$seg, i32imm:$off), + "lcall{l}\t$seg, $off", []>; + + def FARCALL16m : I<0xFF, MRM3m, (outs), (ins opaque32mem:$dst), + "lcall{w}\t{*}$dst", []>, OpSize; + def FARCALL32m : I<0xFF, MRM3m, (outs), (ins opaque48mem:$dst), + "lcall{l}\t{*}$dst", []>; + } + +// Constructing a stack frame. + +def ENTER : I<0xC8, RawFrm, (outs), (ins i16imm:$len, i8imm:$lvl), + "enter\t$len, $lvl", []>; + +// Tail call stuff. + +let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1 in +def TCRETURNdi : I<0, Pseudo, (outs), (ins i32imm:$dst, i32imm:$offset, variable_ops), + "#TC_RETURN $dst $offset", + []>; + +let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1 in +def TCRETURNri : I<0, Pseudo, (outs), (ins GR32:$dst, i32imm:$offset, variable_ops), + "#TC_RETURN $dst $offset", + []>; + +let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1 in + + def TAILJMPd : IBr<0xE9, (ins i32imm_pcrel:$dst), "jmp\t$dst # TAILCALL", + []>; +let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1 in + def TAILJMPr : I<0xFF, MRM4r, (outs), (ins GR32:$dst), "jmp{l}\t{*}$dst # TAILCALL", + []>; +let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1 in + def TAILJMPm : I<0xFF, MRM4m, (outs), (ins i32mem:$dst), + "jmp\t{*}$dst # TAILCALL", []>; + +//===----------------------------------------------------------------------===// +// Miscellaneous Instructions... +// +let Defs = [EBP, ESP], Uses = [EBP, ESP], mayLoad = 1, neverHasSideEffects=1 in +def LEAVE : I<0xC9, RawFrm, + (outs), (ins), "leave", []>; + +let Defs = [ESP], Uses = [ESP], neverHasSideEffects=1 in { +let mayLoad = 1 in { +def POP16r : I<0x58, AddRegFrm, (outs GR16:$reg), (ins), "pop{w}\t$reg", []>, + OpSize; +def POP32r : I<0x58, AddRegFrm, (outs GR32:$reg), (ins), "pop{l}\t$reg", []>; +def POP16rmr: I<0x8F, MRM0r, (outs GR16:$reg), (ins), "pop{w}\t$reg", []>, + OpSize; +def POP16rmm: I<0x8F, MRM0m, (outs i16mem:$dst), (ins), "pop{w}\t$dst", []>, + OpSize; +def POP32rmr: I<0x8F, MRM0r, (outs GR32:$reg), (ins), "pop{l}\t$reg", []>; +def POP32rmm: I<0x8F, MRM0m, (outs i32mem:$dst), (ins), "pop{l}\t$dst", []>; +} + +let mayStore = 1 in { +def PUSH16r : I<0x50, AddRegFrm, (outs), (ins GR16:$reg), "push{w}\t$reg",[]>, + OpSize; +def PUSH32r : I<0x50, AddRegFrm, (outs), (ins GR32:$reg), "push{l}\t$reg",[]>; +def PUSH16rmr: I<0xFF, MRM6r, (outs), (ins GR16:$reg), "push{w}\t$reg",[]>, + OpSize; +def PUSH16rmm: I<0xFF, MRM6m, (outs), (ins i16mem:$src), "push{w}\t$src",[]>, + OpSize; +def PUSH32rmr: I<0xFF, MRM6r, (outs), (ins GR32:$reg), "push{l}\t$reg",[]>; +def PUSH32rmm: I<0xFF, MRM6m, (outs), (ins i32mem:$src), "push{l}\t$src",[]>; +} +} + +let Defs = [ESP], Uses = [ESP], neverHasSideEffects = 1, mayStore = 1 in { +def PUSH32i8 : Ii8<0x6a, RawFrm, (outs), (ins i8imm:$imm), + "push{l}\t$imm", []>; +def PUSH32i16 : Ii16<0x68, RawFrm, (outs), (ins i16imm:$imm), + "push{l}\t$imm", []>; +def PUSH32i32 : Ii32<0x68, RawFrm, (outs), (ins i32imm:$imm), + "push{l}\t$imm", []>; +} + +let Defs = [ESP, EFLAGS], Uses = [ESP], mayLoad = 1, neverHasSideEffects=1 in +def POPFD : I<0x9D, RawFrm, (outs), (ins), "popf", []>; +let Defs = [ESP], Uses = [ESP, EFLAGS], mayStore = 1, neverHasSideEffects=1 in +def PUSHFD : I<0x9C, RawFrm, (outs), (ins), "pushf", []>; + +let isTwoAddress = 1 in // GR32 = bswap GR32 + def BSWAP32r : I<0xC8, AddRegFrm, + (outs GR32:$dst), (ins GR32:$src), + "bswap{l}\t$dst", + [(set GR32:$dst, (bswap GR32:$src))]>, TB; + + +// Bit scan instructions. +let Defs = [EFLAGS] in { +def BSF16rr : I<0xBC, MRMSrcReg, (outs GR16:$dst), (ins GR16:$src), + "bsf{w}\t{$src, $dst|$dst, $src}", + [(set GR16:$dst, (X86bsf GR16:$src)), (implicit EFLAGS)]>, TB; +def BSF16rm : I<0xBC, MRMSrcMem, (outs GR16:$dst), (ins i16mem:$src), + "bsf{w}\t{$src, $dst|$dst, $src}", + [(set GR16:$dst, (X86bsf (loadi16 addr:$src))), + (implicit EFLAGS)]>, TB; +def BSF32rr : I<0xBC, MRMSrcReg, (outs GR32:$dst), (ins GR32:$src), + "bsf{l}\t{$src, $dst|$dst, $src}", + [(set GR32:$dst, (X86bsf GR32:$src)), (implicit EFLAGS)]>, TB; +def BSF32rm : I<0xBC, MRMSrcMem, (outs GR32:$dst), (ins i32mem:$src), + "bsf{l}\t{$src, $dst|$dst, $src}", + [(set GR32:$dst, (X86bsf (loadi32 addr:$src))), + (implicit EFLAGS)]>, TB; + +def BSR16rr : I<0xBD, MRMSrcReg, (outs GR16:$dst), (ins GR16:$src), + "bsr{w}\t{$src, $dst|$dst, $src}", + [(set GR16:$dst, (X86bsr GR16:$src)), (implicit EFLAGS)]>, TB; +def BSR16rm : I<0xBD, MRMSrcMem, (outs GR16:$dst), (ins i16mem:$src), + "bsr{w}\t{$src, $dst|$dst, $src}", + [(set GR16:$dst, (X86bsr (loadi16 addr:$src))), + (implicit EFLAGS)]>, TB; +def BSR32rr : I<0xBD, MRMSrcReg, (outs GR32:$dst), (ins GR32:$src), + "bsr{l}\t{$src, $dst|$dst, $src}", + [(set GR32:$dst, (X86bsr GR32:$src)), (implicit EFLAGS)]>, TB; +def BSR32rm : I<0xBD, MRMSrcMem, (outs GR32:$dst), (ins i32mem:$src), + "bsr{l}\t{$src, $dst|$dst, $src}", + [(set GR32:$dst, (X86bsr (loadi32 addr:$src))), + (implicit EFLAGS)]>, TB; +} // Defs = [EFLAGS] + +let neverHasSideEffects = 1 in +def LEA16r : I<0x8D, MRMSrcMem, + (outs GR16:$dst), (ins i32mem:$src), + "lea{w}\t{$src|$dst}, {$dst|$src}", []>, OpSize; +let isReMaterializable = 1 in +def LEA32r : I<0x8D, MRMSrcMem, + (outs GR32:$dst), (ins lea32mem:$src), + "lea{l}\t{$src|$dst}, {$dst|$src}", + [(set GR32:$dst, lea32addr:$src)]>, Requires<[In32BitMode]>; + +let Defs = [ECX,EDI,ESI], Uses = [ECX,EDI,ESI] in { +def REP_MOVSB : I<0xA4, RawFrm, (outs), (ins), "{rep;movsb|rep movsb}", + [(X86rep_movs i8)]>, REP; +def REP_MOVSW : I<0xA5, RawFrm, (outs), (ins), "{rep;movsw|rep movsw}", + [(X86rep_movs i16)]>, REP, OpSize; +def REP_MOVSD : I<0xA5, RawFrm, (outs), (ins), "{rep;movsl|rep movsd}", + [(X86rep_movs i32)]>, REP; +} + +let Defs = [ECX,EDI], Uses = [AL,ECX,EDI] in +def REP_STOSB : I<0xAA, RawFrm, (outs), (ins), "{rep;stosb|rep stosb}", + [(X86rep_stos i8)]>, REP; +let Defs = [ECX,EDI], Uses = [AX,ECX,EDI] in +def REP_STOSW : I<0xAB, RawFrm, (outs), (ins), "{rep;stosw|rep stosw}", + [(X86rep_stos i16)]>, REP, OpSize; +let Defs = [ECX,EDI], Uses = [EAX,ECX,EDI] in +def REP_STOSD : I<0xAB, RawFrm, (outs), (ins), "{rep;stosl|rep stosd}", + [(X86rep_stos i32)]>, REP; + +def SCAS8 : I<0xAE, RawFrm, (outs), (ins), "scas{b}", []>; +def SCAS16 : I<0xAF, RawFrm, (outs), (ins), "scas{w}", []>, OpSize; +def SCAS32 : I<0xAF, RawFrm, (outs), (ins), "scas{l}", []>; + +def CMPS8 : I<0xA6, RawFrm, (outs), (ins), "cmps{b}", []>; +def CMPS16 : I<0xA7, RawFrm, (outs), (ins), "cmps{w}", []>, OpSize; +def CMPS32 : I<0xA7, RawFrm, (outs), (ins), "cmps{l}", []>; + +let Defs = [RAX, RDX] in +def RDTSC : I<0x31, RawFrm, (outs), (ins), "rdtsc", [(X86rdtsc)]>, + TB; + +let isBarrier = 1, hasCtrlDep = 1 in { +def TRAP : I<0x0B, RawFrm, (outs), (ins), "ud2", [(trap)]>, TB; +} + +def SYSCALL : I<0x05, RawFrm, + (outs), (ins), "syscall", []>, TB; +def SYSRET : I<0x07, RawFrm, + (outs), (ins), "sysret", []>, TB; +def SYSENTER : I<0x34, RawFrm, + (outs), (ins), "sysenter", []>, TB; +def SYSEXIT : I<0x35, RawFrm, + (outs), (ins), "sysexit", []>, TB; + +def WAIT : I<0x9B, RawFrm, (outs), (ins), "wait", []>; + + +//===----------------------------------------------------------------------===// +// Input/Output Instructions... +// +let Defs = [AL], Uses = [DX] in +def IN8rr : I<0xEC, RawFrm, (outs), (ins), + "in{b}\t{%dx, %al|%AL, %DX}", []>; +let Defs = [AX], Uses = [DX] in +def IN16rr : I<0xED, RawFrm, (outs), (ins), + "in{w}\t{%dx, %ax|%AX, %DX}", []>, OpSize; +let Defs = [EAX], Uses = [DX] in +def IN32rr : I<0xED, RawFrm, (outs), (ins), + "in{l}\t{%dx, %eax|%EAX, %DX}", []>; + +let Defs = [AL] in +def IN8ri : Ii8<0xE4, RawFrm, (outs), (ins i16i8imm:$port), + "in{b}\t{$port, %al|%AL, $port}", []>; +let Defs = [AX] in +def IN16ri : Ii8<0xE5, RawFrm, (outs), (ins i16i8imm:$port), + "in{w}\t{$port, %ax|%AX, $port}", []>, OpSize; +let Defs = [EAX] in +def IN32ri : Ii8<0xE5, RawFrm, (outs), (ins i16i8imm:$port), + "in{l}\t{$port, %eax|%EAX, $port}", []>; + +let Uses = [DX, AL] in +def OUT8rr : I<0xEE, RawFrm, (outs), (ins), + "out{b}\t{%al, %dx|%DX, %AL}", []>; +let Uses = [DX, AX] in +def OUT16rr : I<0xEF, RawFrm, (outs), (ins), + "out{w}\t{%ax, %dx|%DX, %AX}", []>, OpSize; +let Uses = [DX, EAX] in +def OUT32rr : I<0xEF, RawFrm, (outs), (ins), + "out{l}\t{%eax, %dx|%DX, %EAX}", []>; + +let Uses = [AL] in +def OUT8ir : Ii8<0xE6, RawFrm, (outs), (ins i16i8imm:$port), + "out{b}\t{%al, $port|$port, %AL}", []>; +let Uses = [AX] in +def OUT16ir : Ii8<0xE7, RawFrm, (outs), (ins i16i8imm:$port), + "out{w}\t{%ax, $port|$port, %AX}", []>, OpSize; +let Uses = [EAX] in +def OUT32ir : Ii8<0xE7, RawFrm, (outs), (ins i16i8imm:$port), + "out{l}\t{%eax, $port|$port, %EAX}", []>; + +//===----------------------------------------------------------------------===// +// Move Instructions... +// +let neverHasSideEffects = 1 in { +def MOV8rr : I<0x88, MRMDestReg, (outs GR8 :$dst), (ins GR8 :$src), + "mov{b}\t{$src, $dst|$dst, $src}", []>; +def MOV16rr : I<0x89, MRMDestReg, (outs GR16:$dst), (ins GR16:$src), + "mov{w}\t{$src, $dst|$dst, $src}", []>, OpSize; +def MOV32rr : I<0x89, MRMDestReg, (outs GR32:$dst), (ins GR32:$src), + "mov{l}\t{$src, $dst|$dst, $src}", []>; +} +let isReMaterializable = 1, isAsCheapAsAMove = 1 in { +def MOV8ri : Ii8 <0xB0, AddRegFrm, (outs GR8 :$dst), (ins i8imm :$src), + "mov{b}\t{$src, $dst|$dst, $src}", + [(set GR8:$dst, imm:$src)]>; +def MOV16ri : Ii16<0xB8, AddRegFrm, (outs GR16:$dst), (ins i16imm:$src), + "mov{w}\t{$src, $dst|$dst, $src}", + [(set GR16:$dst, imm:$src)]>, OpSize; +def MOV32ri : Ii32<0xB8, AddRegFrm, (outs GR32:$dst), (ins i32imm:$src), + "mov{l}\t{$src, $dst|$dst, $src}", + [(set GR32:$dst, imm:$src)]>; +} +def MOV8mi : Ii8 <0xC6, MRM0m, (outs), (ins i8mem :$dst, i8imm :$src), + "mov{b}\t{$src, $dst|$dst, $src}", + [(store (i8 imm:$src), addr:$dst)]>; +def MOV16mi : Ii16<0xC7, MRM0m, (outs), (ins i16mem:$dst, i16imm:$src), + "mov{w}\t{$src, $dst|$dst, $src}", + [(store (i16 imm:$src), addr:$dst)]>, OpSize; +def MOV32mi : Ii32<0xC7, MRM0m, (outs), (ins i32mem:$dst, i32imm:$src), + "mov{l}\t{$src, $dst|$dst, $src}", + [(store (i32 imm:$src), addr:$dst)]>; + +def MOV8o8a : Ii8 <0xA0, RawFrm, (outs), (ins i8imm:$src), + "mov{b}\t{$src, %al|%al, $src}", []>; +def MOV16o16a : Ii16 <0xA1, RawFrm, (outs), (ins i16imm:$src), + "mov{w}\t{$src, %ax|%ax, $src}", []>, OpSize; +def MOV32o32a : Ii32 <0xA1, RawFrm, (outs), (ins i32imm:$src), + "mov{l}\t{$src, %eax|%eax, $src}", []>; + +def MOV8ao8 : Ii8 <0xA2, RawFrm, (outs i8imm:$dst), (ins), + "mov{b}\t{%al, $dst|$dst, %al}", []>; +def MOV16ao16 : Ii16 <0xA3, RawFrm, (outs i16imm:$dst), (ins), + "mov{w}\t{%ax, $dst|$dst, %ax}", []>, OpSize; +def MOV32ao32 : Ii32 <0xA3, RawFrm, (outs i32imm:$dst), (ins), + "mov{l}\t{%eax, $dst|$dst, %eax}", []>; + +// Moves to and from segment registers +def MOV16rs : I<0x8C, MRMDestReg, (outs GR16:$dst), (ins SEGMENT_REG:$src), + "mov{w}\t{$src, $dst|$dst, $src}", []>; +def MOV16ms : I<0x8C, MRMDestMem, (outs i16mem:$dst), (ins SEGMENT_REG:$src), + "mov{w}\t{$src, $dst|$dst, $src}", []>; +def MOV16sr : I<0x8E, MRMSrcReg, (outs SEGMENT_REG:$dst), (ins GR16:$src), + "mov{w}\t{$src, $dst|$dst, $src}", []>; +def MOV16sm : I<0x8E, MRMSrcMem, (outs SEGMENT_REG:$dst), (ins i16mem:$src), + "mov{w}\t{$src, $dst|$dst, $src}", []>; + +let canFoldAsLoad = 1, isReMaterializable = 1, mayHaveSideEffects = 1 in { +def MOV8rm : I<0x8A, MRMSrcMem, (outs GR8 :$dst), (ins i8mem :$src), + "mov{b}\t{$src, $dst|$dst, $src}", + [(set GR8:$dst, (loadi8 addr:$src))]>; +def MOV16rm : I<0x8B, MRMSrcMem, (outs GR16:$dst), (ins i16mem:$src), + "mov{w}\t{$src, $dst|$dst, $src}", + [(set GR16:$dst, (loadi16 addr:$src))]>, OpSize; +def MOV32rm : I<0x8B, MRMSrcMem, (outs GR32:$dst), (ins i32mem:$src), + "mov{l}\t{$src, $dst|$dst, $src}", + [(set GR32:$dst, (loadi32 addr:$src))]>; +} + +def MOV8mr : I<0x88, MRMDestMem, (outs), (ins i8mem :$dst, GR8 :$src), + "mov{b}\t{$src, $dst|$dst, $src}", + [(store GR8:$src, addr:$dst)]>; +def MOV16mr : I<0x89, MRMDestMem, (outs), (ins i16mem:$dst, GR16:$src), + "mov{w}\t{$src, $dst|$dst, $src}", + [(store GR16:$src, addr:$dst)]>, OpSize; +def MOV32mr : I<0x89, MRMDestMem, (outs), (ins i32mem:$dst, GR32:$src), + "mov{l}\t{$src, $dst|$dst, $src}", + [(store GR32:$src, addr:$dst)]>; + +// Versions of MOV8rr, MOV8mr, and MOV8rm that use i8mem_NOREX and GR8_NOREX so +// that they can be used for copying and storing h registers, which can't be +// encoded when a REX prefix is present. +let neverHasSideEffects = 1 in +def MOV8rr_NOREX : I<0x88, MRMDestReg, + (outs GR8_NOREX:$dst), (ins GR8_NOREX:$src), + "mov{b}\t{$src, $dst|$dst, $src} # NOREX", []>; +let mayStore = 1 in +def MOV8mr_NOREX : I<0x88, MRMDestMem, + (outs), (ins i8mem_NOREX:$dst, GR8_NOREX:$src), + "mov{b}\t{$src, $dst|$dst, $src} # NOREX", []>; +let mayLoad = 1, + canFoldAsLoad = 1, isReMaterializable = 1, mayHaveSideEffects = 1 in +def MOV8rm_NOREX : I<0x8A, MRMSrcMem, + (outs GR8_NOREX:$dst), (ins i8mem_NOREX:$src), + "mov{b}\t{$src, $dst|$dst, $src} # NOREX", []>; + +//===----------------------------------------------------------------------===// +// Fixed-Register Multiplication and Division Instructions... +// + +// Extra precision multiplication +let Defs = [AL,AH,EFLAGS], Uses = [AL] in +def MUL8r : I<0xF6, MRM4r, (outs), (ins GR8:$src), "mul{b}\t$src", + // FIXME: Used for 8-bit mul, ignore result upper 8 bits. + // This probably ought to be moved to a def : Pat<> if the + // syntax can be accepted. + [(set AL, (mul AL, GR8:$src)), + (implicit EFLAGS)]>; // AL,AH = AL*GR8 + +let Defs = [AX,DX,EFLAGS], Uses = [AX], neverHasSideEffects = 1 in +def MUL16r : I<0xF7, MRM4r, (outs), (ins GR16:$src), + "mul{w}\t$src", + []>, OpSize; // AX,DX = AX*GR16 + +let Defs = [EAX,EDX,EFLAGS], Uses = [EAX], neverHasSideEffects = 1 in +def MUL32r : I<0xF7, MRM4r, (outs), (ins GR32:$src), + "mul{l}\t$src", + []>; // EAX,EDX = EAX*GR32 + +let Defs = [AL,AH,EFLAGS], Uses = [AL] in +def MUL8m : I<0xF6, MRM4m, (outs), (ins i8mem :$src), + "mul{b}\t$src", + // FIXME: Used for 8-bit mul, ignore result upper 8 bits. + // This probably ought to be moved to a def : Pat<> if the + // syntax can be accepted. + [(set AL, (mul AL, (loadi8 addr:$src))), + (implicit EFLAGS)]>; // AL,AH = AL*[mem8] + +let mayLoad = 1, neverHasSideEffects = 1 in { +let Defs = [AX,DX,EFLAGS], Uses = [AX] in +def MUL16m : I<0xF7, MRM4m, (outs), (ins i16mem:$src), + "mul{w}\t$src", + []>, OpSize; // AX,DX = AX*[mem16] + +let Defs = [EAX,EDX,EFLAGS], Uses = [EAX] in +def MUL32m : I<0xF7, MRM4m, (outs), (ins i32mem:$src), + "mul{l}\t$src", + []>; // EAX,EDX = EAX*[mem32] +} + +let neverHasSideEffects = 1 in { +let Defs = [AL,AH,EFLAGS], Uses = [AL] in +def IMUL8r : I<0xF6, MRM5r, (outs), (ins GR8:$src), "imul{b}\t$src", []>; + // AL,AH = AL*GR8 +let Defs = [AX,DX,EFLAGS], Uses = [AX] in +def IMUL16r : I<0xF7, MRM5r, (outs), (ins GR16:$src), "imul{w}\t$src", []>, + OpSize; // AX,DX = AX*GR16 +let Defs = [EAX,EDX,EFLAGS], Uses = [EAX] in +def IMUL32r : I<0xF7, MRM5r, (outs), (ins GR32:$src), "imul{l}\t$src", []>; + // EAX,EDX = EAX*GR32 +let mayLoad = 1 in { +let Defs = [AL,AH,EFLAGS], Uses = [AL] in +def IMUL8m : I<0xF6, MRM5m, (outs), (ins i8mem :$src), + "imul{b}\t$src", []>; // AL,AH = AL*[mem8] +let Defs = [AX,DX,EFLAGS], Uses = [AX] in +def IMUL16m : I<0xF7, MRM5m, (outs), (ins i16mem:$src), + "imul{w}\t$src", []>, OpSize; // AX,DX = AX*[mem16] +let Defs = [EAX,EDX], Uses = [EAX] in +def IMUL32m : I<0xF7, MRM5m, (outs), (ins i32mem:$src), + "imul{l}\t$src", []>; // EAX,EDX = EAX*[mem32] +} +} // neverHasSideEffects + +// unsigned division/remainder +let Defs = [AL,AH,EFLAGS], Uses = [AX] in +def DIV8r : I<0xF6, MRM6r, (outs), (ins GR8:$src), // AX/r8 = AL,AH + "div{b}\t$src", []>; +let Defs = [AX,DX,EFLAGS], Uses = [AX,DX] in +def DIV16r : I<0xF7, MRM6r, (outs), (ins GR16:$src), // DX:AX/r16 = AX,DX + "div{w}\t$src", []>, OpSize; +let Defs = [EAX,EDX,EFLAGS], Uses = [EAX,EDX] in +def DIV32r : I<0xF7, MRM6r, (outs), (ins GR32:$src), // EDX:EAX/r32 = EAX,EDX + "div{l}\t$src", []>; +let mayLoad = 1 in { +let Defs = [AL,AH,EFLAGS], Uses = [AX] in +def DIV8m : I<0xF6, MRM6m, (outs), (ins i8mem:$src), // AX/[mem8] = AL,AH + "div{b}\t$src", []>; +let Defs = [AX,DX,EFLAGS], Uses = [AX,DX] in +def DIV16m : I<0xF7, MRM6m, (outs), (ins i16mem:$src), // DX:AX/[mem16] = AX,DX + "div{w}\t$src", []>, OpSize; +let Defs = [EAX,EDX,EFLAGS], Uses = [EAX,EDX] in +def DIV32m : I<0xF7, MRM6m, (outs), (ins i32mem:$src), // EDX:EAX/[mem32] = EAX,EDX + "div{l}\t$src", []>; +} + +// Signed division/remainder. +let Defs = [AL,AH,EFLAGS], Uses = [AX] in +def IDIV8r : I<0xF6, MRM7r, (outs), (ins GR8:$src), // AX/r8 = AL,AH + "idiv{b}\t$src", []>; +let Defs = [AX,DX,EFLAGS], Uses = [AX,DX] in +def IDIV16r: I<0xF7, MRM7r, (outs), (ins GR16:$src), // DX:AX/r16 = AX,DX + "idiv{w}\t$src", []>, OpSize; +let Defs = [EAX,EDX,EFLAGS], Uses = [EAX,EDX] in +def IDIV32r: I<0xF7, MRM7r, (outs), (ins GR32:$src), // EDX:EAX/r32 = EAX,EDX + "idiv{l}\t$src", []>; +let mayLoad = 1, mayLoad = 1 in { +let Defs = [AL,AH,EFLAGS], Uses = [AX] in +def IDIV8m : I<0xF6, MRM7m, (outs), (ins i8mem:$src), // AX/[mem8] = AL,AH + "idiv{b}\t$src", []>; +let Defs = [AX,DX,EFLAGS], Uses = [AX,DX] in +def IDIV16m: I<0xF7, MRM7m, (outs), (ins i16mem:$src), // DX:AX/[mem16] = AX,DX + "idiv{w}\t$src", []>, OpSize; +let Defs = [EAX,EDX,EFLAGS], Uses = [EAX,EDX] in +def IDIV32m: I<0xF7, MRM7m, (outs), (ins i32mem:$src), // EDX:EAX/[mem32] = EAX,EDX + "idiv{l}\t$src", []>; +} + +//===----------------------------------------------------------------------===// +// Two address Instructions. +// +let isTwoAddress = 1 in { + +// Conditional moves +let Uses = [EFLAGS] in { + +// X86 doesn't have 8-bit conditional moves. Use a customInserter to +// emit control flow. An alternative to this is to mark i8 SELECT as Promote, +// however that requires promoting the operands, and can induce additional +// i8 register pressure. Note that CMOV_GR8 is conservatively considered to +// clobber EFLAGS, because if one of the operands is zero, the expansion +// could involve an xor. +let usesCustomInserter = 1, isTwoAddress = 0, Defs = [EFLAGS] in +def CMOV_GR8 : I<0, Pseudo, + (outs GR8:$dst), (ins GR8:$src1, GR8:$src2, i8imm:$cond), + "#CMOV_GR8 PSEUDO!", + [(set GR8:$dst, (X86cmov GR8:$src1, GR8:$src2, + imm:$cond, EFLAGS))]>; + +let isCommutable = 1 in { +def CMOVB16rr : I<0x42, MRMSrcReg, // if , + TB, OpSize; +def CMOVB32rr : I<0x42, MRMSrcReg, // if , + TB; +def CMOVAE16rr: I<0x43, MRMSrcReg, // if >=u, GR16 = GR16 + (outs GR16:$dst), (ins GR16:$src1, GR16:$src2), + "cmovae\t{$src2, $dst|$dst, $src2}", + [(set GR16:$dst, (X86cmov GR16:$src1, GR16:$src2, + X86_COND_AE, EFLAGS))]>, + TB, OpSize; +def CMOVAE32rr: I<0x43, MRMSrcReg, // if >=u, GR32 = GR32 + (outs GR32:$dst), (ins GR32:$src1, GR32:$src2), + "cmovae\t{$src2, $dst|$dst, $src2}", + [(set GR32:$dst, (X86cmov GR32:$src1, GR32:$src2, + X86_COND_AE, EFLAGS))]>, + TB; +def CMOVE16rr : I<0x44, MRMSrcReg, // if ==, GR16 = GR16 + (outs GR16:$dst), (ins GR16:$src1, GR16:$src2), + "cmove\t{$src2, $dst|$dst, $src2}", + [(set GR16:$dst, (X86cmov GR16:$src1, GR16:$src2, + X86_COND_E, EFLAGS))]>, + TB, OpSize; +def CMOVE32rr : I<0x44, MRMSrcReg, // if ==, GR32 = GR32 + (outs GR32:$dst), (ins GR32:$src1, GR32:$src2), + "cmove\t{$src2, $dst|$dst, $src2}", + [(set GR32:$dst, (X86cmov GR32:$src1, GR32:$src2, + X86_COND_E, EFLAGS))]>, + TB; +def CMOVNE16rr: I<0x45, MRMSrcReg, // if !=, GR16 = GR16 + (outs GR16:$dst), (ins GR16:$src1, GR16:$src2), + "cmovne\t{$src2, $dst|$dst, $src2}", + [(set GR16:$dst, (X86cmov GR16:$src1, GR16:$src2, + X86_COND_NE, EFLAGS))]>, + TB, OpSize; +def CMOVNE32rr: I<0x45, MRMSrcReg, // if !=, GR32 = GR32 + (outs GR32:$dst), (ins GR32:$src1, GR32:$src2), + "cmovne\t{$src2, $dst|$dst, $src2}", + [(set GR32:$dst, (X86cmov GR32:$src1, GR32:$src2, + X86_COND_NE, EFLAGS))]>, + TB; +def CMOVBE16rr: I<0x46, MRMSrcReg, // if <=u, GR16 = GR16 + (outs GR16:$dst), (ins GR16:$src1, GR16:$src2), + "cmovbe\t{$src2, $dst|$dst, $src2}", + [(set GR16:$dst, (X86cmov GR16:$src1, GR16:$src2, + X86_COND_BE, EFLAGS))]>, + TB, OpSize; +def CMOVBE32rr: I<0x46, MRMSrcReg, // if <=u, GR32 = GR32 + (outs GR32:$dst), (ins GR32:$src1, GR32:$src2), + "cmovbe\t{$src2, $dst|$dst, $src2}", + [(set GR32:$dst, (X86cmov GR32:$src1, GR32:$src2, + X86_COND_BE, EFLAGS))]>, + TB; +def CMOVA16rr : I<0x47, MRMSrcReg, // if >u, GR16 = GR16 + (outs GR16:$dst), (ins GR16:$src1, GR16:$src2), + "cmova\t{$src2, $dst|$dst, $src2}", + [(set GR16:$dst, (X86cmov GR16:$src1, GR16:$src2, + X86_COND_A, EFLAGS))]>, + TB, OpSize; +def CMOVA32rr : I<0x47, MRMSrcReg, // if >u, GR32 = GR32 + (outs GR32:$dst), (ins GR32:$src1, GR32:$src2), + "cmova\t{$src2, $dst|$dst, $src2}", + [(set GR32:$dst, (X86cmov GR32:$src1, GR32:$src2, + X86_COND_A, EFLAGS))]>, + TB; +def CMOVL16rr : I<0x4C, MRMSrcReg, // if , + TB, OpSize; +def CMOVL32rr : I<0x4C, MRMSrcReg, // if , + TB; +def CMOVGE16rr: I<0x4D, MRMSrcReg, // if >=s, GR16 = GR16 + (outs GR16:$dst), (ins GR16:$src1, GR16:$src2), + "cmovge\t{$src2, $dst|$dst, $src2}", + [(set GR16:$dst, (X86cmov GR16:$src1, GR16:$src2, + X86_COND_GE, EFLAGS))]>, + TB, OpSize; +def CMOVGE32rr: I<0x4D, MRMSrcReg, // if >=s, GR32 = GR32 + (outs GR32:$dst), (ins GR32:$src1, GR32:$src2), + "cmovge\t{$src2, $dst|$dst, $src2}", + [(set GR32:$dst, (X86cmov GR32:$src1, GR32:$src2, + X86_COND_GE, EFLAGS))]>, + TB; +def CMOVLE16rr: I<0x4E, MRMSrcReg, // if <=s, GR16 = GR16 + (outs GR16:$dst), (ins GR16:$src1, GR16:$src2), + "cmovle\t{$src2, $dst|$dst, $src2}", + [(set GR16:$dst, (X86cmov GR16:$src1, GR16:$src2, + X86_COND_LE, EFLAGS))]>, + TB, OpSize; +def CMOVLE32rr: I<0x4E, MRMSrcReg, // if <=s, GR32 = GR32 + (outs GR32:$dst), (ins GR32:$src1, GR32:$src2), + "cmovle\t{$src2, $dst|$dst, $src2}", + [(set GR32:$dst, (X86cmov GR32:$src1, GR32:$src2, + X86_COND_LE, EFLAGS))]>, + TB; +def CMOVG16rr : I<0x4F, MRMSrcReg, // if >s, GR16 = GR16 + (outs GR16:$dst), (ins GR16:$src1, GR16:$src2), + "cmovg\t{$src2, $dst|$dst, $src2}", + [(set GR16:$dst, (X86cmov GR16:$src1, GR16:$src2, + X86_COND_G, EFLAGS))]>, + TB, OpSize; +def CMOVG32rr : I<0x4F, MRMSrcReg, // if >s, GR32 = GR32 + (outs GR32:$dst), (ins GR32:$src1, GR32:$src2), + "cmovg\t{$src2, $dst|$dst, $src2}", + [(set GR32:$dst, (X86cmov GR32:$src1, GR32:$src2, + X86_COND_G, EFLAGS))]>, + TB; +def CMOVS16rr : I<0x48, MRMSrcReg, // if signed, GR16 = GR16 + (outs GR16:$dst), (ins GR16:$src1, GR16:$src2), + "cmovs\t{$src2, $dst|$dst, $src2}", + [(set GR16:$dst, (X86cmov GR16:$src1, GR16:$src2, + X86_COND_S, EFLAGS))]>, + TB, OpSize; +def CMOVS32rr : I<0x48, MRMSrcReg, // if signed, GR32 = GR32 + (outs GR32:$dst), (ins GR32:$src1, GR32:$src2), + "cmovs\t{$src2, $dst|$dst, $src2}", + [(set GR32:$dst, (X86cmov GR32:$src1, GR32:$src2, + X86_COND_S, EFLAGS))]>, + TB; +def CMOVNS16rr: I<0x49, MRMSrcReg, // if !signed, GR16 = GR16 + (outs GR16:$dst), (ins GR16:$src1, GR16:$src2), + "cmovns\t{$src2, $dst|$dst, $src2}", + [(set GR16:$dst, (X86cmov GR16:$src1, GR16:$src2, + X86_COND_NS, EFLAGS))]>, + TB, OpSize; +def CMOVNS32rr: I<0x49, MRMSrcReg, // if !signed, GR32 = GR32 + (outs GR32:$dst), (ins GR32:$src1, GR32:$src2), + "cmovns\t{$src2, $dst|$dst, $src2}", + [(set GR32:$dst, (X86cmov GR32:$src1, GR32:$src2, + X86_COND_NS, EFLAGS))]>, + TB; +def CMOVP16rr : I<0x4A, MRMSrcReg, // if parity, GR16 = GR16 + (outs GR16:$dst), (ins GR16:$src1, GR16:$src2), + "cmovp\t{$src2, $dst|$dst, $src2}", + [(set GR16:$dst, (X86cmov GR16:$src1, GR16:$src2, + X86_COND_P, EFLAGS))]>, + TB, OpSize; +def CMOVP32rr : I<0x4A, MRMSrcReg, // if parity, GR32 = GR32 + (outs GR32:$dst), (ins GR32:$src1, GR32:$src2), + "cmovp\t{$src2, $dst|$dst, $src2}", + [(set GR32:$dst, (X86cmov GR32:$src1, GR32:$src2, + X86_COND_P, EFLAGS))]>, + TB; +def CMOVNP16rr : I<0x4B, MRMSrcReg, // if !parity, GR16 = GR16 + (outs GR16:$dst), (ins GR16:$src1, GR16:$src2), + "cmovnp\t{$src2, $dst|$dst, $src2}", + [(set GR16:$dst, (X86cmov GR16:$src1, GR16:$src2, + X86_COND_NP, EFLAGS))]>, + TB, OpSize; +def CMOVNP32rr : I<0x4B, MRMSrcReg, // if !parity, GR32 = GR32 + (outs GR32:$dst), (ins GR32:$src1, GR32:$src2), + "cmovnp\t{$src2, $dst|$dst, $src2}", + [(set GR32:$dst, (X86cmov GR32:$src1, GR32:$src2, + X86_COND_NP, EFLAGS))]>, + TB; +def CMOVO16rr : I<0x40, MRMSrcReg, // if overflow, GR16 = GR16 + (outs GR16:$dst), (ins GR16:$src1, GR16:$src2), + "cmovo\t{$src2, $dst|$dst, $src2}", + [(set GR16:$dst, (X86cmov GR16:$src1, GR16:$src2, + X86_COND_O, EFLAGS))]>, + TB, OpSize; +def CMOVO32rr : I<0x40, MRMSrcReg, // if overflow, GR32 = GR32 + (outs GR32:$dst), (ins GR32:$src1, GR32:$src2), + "cmovo\t{$src2, $dst|$dst, $src2}", + [(set GR32:$dst, (X86cmov GR32:$src1, GR32:$src2, + X86_COND_O, EFLAGS))]>, + TB; +def CMOVNO16rr : I<0x41, MRMSrcReg, // if !overflow, GR16 = GR16 + (outs GR16:$dst), (ins GR16:$src1, GR16:$src2), + "cmovno\t{$src2, $dst|$dst, $src2}", + [(set GR16:$dst, (X86cmov GR16:$src1, GR16:$src2, + X86_COND_NO, EFLAGS))]>, + TB, OpSize; +def CMOVNO32rr : I<0x41, MRMSrcReg, // if !overflow, GR32 = GR32 + (outs GR32:$dst), (ins GR32:$src1, GR32:$src2), + "cmovno\t{$src2, $dst|$dst, $src2}", + [(set GR32:$dst, (X86cmov GR32:$src1, GR32:$src2, + X86_COND_NO, EFLAGS))]>, + TB; +} // isCommutable = 1 + +def CMOVB16rm : I<0x42, MRMSrcMem, // if , + TB, OpSize; +def CMOVB32rm : I<0x42, MRMSrcMem, // if , + TB; +def CMOVAE16rm: I<0x43, MRMSrcMem, // if >=u, GR16 = [mem16] + (outs GR16:$dst), (ins GR16:$src1, i16mem:$src2), + "cmovae\t{$src2, $dst|$dst, $src2}", + [(set GR16:$dst, (X86cmov GR16:$src1, (loadi16 addr:$src2), + X86_COND_AE, EFLAGS))]>, + TB, OpSize; +def CMOVAE32rm: I<0x43, MRMSrcMem, // if >=u, GR32 = [mem32] + (outs GR32:$dst), (ins GR32:$src1, i32mem:$src2), + "cmovae\t{$src2, $dst|$dst, $src2}", + [(set GR32:$dst, (X86cmov GR32:$src1, (loadi32 addr:$src2), + X86_COND_AE, EFLAGS))]>, + TB; +def CMOVE16rm : I<0x44, MRMSrcMem, // if ==, GR16 = [mem16] + (outs GR16:$dst), (ins GR16:$src1, i16mem:$src2), + "cmove\t{$src2, $dst|$dst, $src2}", + [(set GR16:$dst, (X86cmov GR16:$src1, (loadi16 addr:$src2), + X86_COND_E, EFLAGS))]>, + TB, OpSize; +def CMOVE32rm : I<0x44, MRMSrcMem, // if ==, GR32 = [mem32] + (outs GR32:$dst), (ins GR32:$src1, i32mem:$src2), + "cmove\t{$src2, $dst|$dst, $src2}", + [(set GR32:$dst, (X86cmov GR32:$src1, (loadi32 addr:$src2), + X86_COND_E, EFLAGS))]>, + TB; +def CMOVNE16rm: I<0x45, MRMSrcMem, // if !=, GR16 = [mem16] + (outs GR16:$dst), (ins GR16:$src1, i16mem:$src2), + "cmovne\t{$src2, $dst|$dst, $src2}", + [(set GR16:$dst, (X86cmov GR16:$src1, (loadi16 addr:$src2), + X86_COND_NE, EFLAGS))]>, + TB, OpSize; +def CMOVNE32rm: I<0x45, MRMSrcMem, // if !=, GR32 = [mem32] + (outs GR32:$dst), (ins GR32:$src1, i32mem:$src2), + "cmovne\t{$src2, $dst|$dst, $src2}", + [(set GR32:$dst, (X86cmov GR32:$src1, (loadi32 addr:$src2), + X86_COND_NE, EFLAGS))]>, + TB; +def CMOVBE16rm: I<0x46, MRMSrcMem, // if <=u, GR16 = [mem16] + (outs GR16:$dst), (ins GR16:$src1, i16mem:$src2), + "cmovbe\t{$src2, $dst|$dst, $src2}", + [(set GR16:$dst, (X86cmov GR16:$src1, (loadi16 addr:$src2), + X86_COND_BE, EFLAGS))]>, + TB, OpSize; +def CMOVBE32rm: I<0x46, MRMSrcMem, // if <=u, GR32 = [mem32] + (outs GR32:$dst), (ins GR32:$src1, i32mem:$src2), + "cmovbe\t{$src2, $dst|$dst, $src2}", + [(set GR32:$dst, (X86cmov GR32:$src1, (loadi32 addr:$src2), + X86_COND_BE, EFLAGS))]>, + TB; +def CMOVA16rm : I<0x47, MRMSrcMem, // if >u, GR16 = [mem16] + (outs GR16:$dst), (ins GR16:$src1, i16mem:$src2), + "cmova\t{$src2, $dst|$dst, $src2}", + [(set GR16:$dst, (X86cmov GR16:$src1, (loadi16 addr:$src2), + X86_COND_A, EFLAGS))]>, + TB, OpSize; +def CMOVA32rm : I<0x47, MRMSrcMem, // if >u, GR32 = [mem32] + (outs GR32:$dst), (ins GR32:$src1, i32mem:$src2), + "cmova\t{$src2, $dst|$dst, $src2}", + [(set GR32:$dst, (X86cmov GR32:$src1, (loadi32 addr:$src2), + X86_COND_A, EFLAGS))]>, + TB; +def CMOVL16rm : I<0x4C, MRMSrcMem, // if , + TB, OpSize; +def CMOVL32rm : I<0x4C, MRMSrcMem, // if , + TB; +def CMOVGE16rm: I<0x4D, MRMSrcMem, // if >=s, GR16 = [mem16] + (outs GR16:$dst), (ins GR16:$src1, i16mem:$src2), + "cmovge\t{$src2, $dst|$dst, $src2}", + [(set GR16:$dst, (X86cmov GR16:$src1, (loadi16 addr:$src2), + X86_COND_GE, EFLAGS))]>, + TB, OpSize; +def CMOVGE32rm: I<0x4D, MRMSrcMem, // if >=s, GR32 = [mem32] + (outs GR32:$dst), (ins GR32:$src1, i32mem:$src2), + "cmovge\t{$src2, $dst|$dst, $src2}", + [(set GR32:$dst, (X86cmov GR32:$src1, (loadi32 addr:$src2), + X86_COND_GE, EFLAGS))]>, + TB; +def CMOVLE16rm: I<0x4E, MRMSrcMem, // if <=s, GR16 = [mem16] + (outs GR16:$dst), (ins GR16:$src1, i16mem:$src2), + "cmovle\t{$src2, $dst|$dst, $src2}", + [(set GR16:$dst, (X86cmov GR16:$src1, (loadi16 addr:$src2), + X86_COND_LE, EFLAGS))]>, + TB, OpSize; +def CMOVLE32rm: I<0x4E, MRMSrcMem, // if <=s, GR32 = [mem32] + (outs GR32:$dst), (ins GR32:$src1, i32mem:$src2), + "cmovle\t{$src2, $dst|$dst, $src2}", + [(set GR32:$dst, (X86cmov GR32:$src1, (loadi32 addr:$src2), + X86_COND_LE, EFLAGS))]>, + TB; +def CMOVG16rm : I<0x4F, MRMSrcMem, // if >s, GR16 = [mem16] + (outs GR16:$dst), (ins GR16:$src1, i16mem:$src2), + "cmovg\t{$src2, $dst|$dst, $src2}", + [(set GR16:$dst, (X86cmov GR16:$src1, (loadi16 addr:$src2), + X86_COND_G, EFLAGS))]>, + TB, OpSize; +def CMOVG32rm : I<0x4F, MRMSrcMem, // if >s, GR32 = [mem32] + (outs GR32:$dst), (ins GR32:$src1, i32mem:$src2), + "cmovg\t{$src2, $dst|$dst, $src2}", + [(set GR32:$dst, (X86cmov GR32:$src1, (loadi32 addr:$src2), + X86_COND_G, EFLAGS))]>, + TB; +def CMOVS16rm : I<0x48, MRMSrcMem, // if signed, GR16 = [mem16] + (outs GR16:$dst), (ins GR16:$src1, i16mem:$src2), + "cmovs\t{$src2, $dst|$dst, $src2}", + [(set GR16:$dst, (X86cmov GR16:$src1, (loadi16 addr:$src2), + X86_COND_S, EFLAGS))]>, + TB, OpSize; +def CMOVS32rm : I<0x48, MRMSrcMem, // if signed, GR32 = [mem32] + (outs GR32:$dst), (ins GR32:$src1, i32mem:$src2), + "cmovs\t{$src2, $dst|$dst, $src2}", + [(set GR32:$dst, (X86cmov GR32:$src1, (loadi32 addr:$src2), + X86_COND_S, EFLAGS))]>, + TB; +def CMOVNS16rm: I<0x49, MRMSrcMem, // if !signed, GR16 = [mem16] + (outs GR16:$dst), (ins GR16:$src1, i16mem:$src2), + "cmovns\t{$src2, $dst|$dst, $src2}", + [(set GR16:$dst, (X86cmov GR16:$src1, (loadi16 addr:$src2), + X86_COND_NS, EFLAGS))]>, + TB, OpSize; +def CMOVNS32rm: I<0x49, MRMSrcMem, // if !signed, GR32 = [mem32] + (outs GR32:$dst), (ins GR32:$src1, i32mem:$src2), + "cmovns\t{$src2, $dst|$dst, $src2}", + [(set GR32:$dst, (X86cmov GR32:$src1, (loadi32 addr:$src2), + X86_COND_NS, EFLAGS))]>, + TB; +def CMOVP16rm : I<0x4A, MRMSrcMem, // if parity, GR16 = [mem16] + (outs GR16:$dst), (ins GR16:$src1, i16mem:$src2), + "cmovp\t{$src2, $dst|$dst, $src2}", + [(set GR16:$dst, (X86cmov GR16:$src1, (loadi16 addr:$src2), + X86_COND_P, EFLAGS))]>, + TB, OpSize; +def CMOVP32rm : I<0x4A, MRMSrcMem, // if parity, GR32 = [mem32] + (outs GR32:$dst), (ins GR32:$src1, i32mem:$src2), + "cmovp\t{$src2, $dst|$dst, $src2}", + [(set GR32:$dst, (X86cmov GR32:$src1, (loadi32 addr:$src2), + X86_COND_P, EFLAGS))]>, + TB; +def CMOVNP16rm : I<0x4B, MRMSrcMem, // if !parity, GR16 = [mem16] + (outs GR16:$dst), (ins GR16:$src1, i16mem:$src2), + "cmovnp\t{$src2, $dst|$dst, $src2}", + [(set GR16:$dst, (X86cmov GR16:$src1, (loadi16 addr:$src2), + X86_COND_NP, EFLAGS))]>, + TB, OpSize; +def CMOVNP32rm : I<0x4B, MRMSrcMem, // if !parity, GR32 = [mem32] + (outs GR32:$dst), (ins GR32:$src1, i32mem:$src2), + "cmovnp\t{$src2, $dst|$dst, $src2}", + [(set GR32:$dst, (X86cmov GR32:$src1, (loadi32 addr:$src2), + X86_COND_NP, EFLAGS))]>, + TB; +def CMOVO16rm : I<0x40, MRMSrcMem, // if overflow, GR16 = [mem16] + (outs GR16:$dst), (ins GR16:$src1, i16mem:$src2), + "cmovo\t{$src2, $dst|$dst, $src2}", + [(set GR16:$dst, (X86cmov GR16:$src1, (loadi16 addr:$src2), + X86_COND_O, EFLAGS))]>, + TB, OpSize; +def CMOVO32rm : I<0x40, MRMSrcMem, // if overflow, GR32 = [mem32] + (outs GR32:$dst), (ins GR32:$src1, i32mem:$src2), + "cmovo\t{$src2, $dst|$dst, $src2}", + [(set GR32:$dst, (X86cmov GR32:$src1, (loadi32 addr:$src2), + X86_COND_O, EFLAGS))]>, + TB; +def CMOVNO16rm : I<0x41, MRMSrcMem, // if !overflow, GR16 = [mem16] + (outs GR16:$dst), (ins GR16:$src1, i16mem:$src2), + "cmovno\t{$src2, $dst|$dst, $src2}", + [(set GR16:$dst, (X86cmov GR16:$src1, (loadi16 addr:$src2), + X86_COND_NO, EFLAGS))]>, + TB, OpSize; +def CMOVNO32rm : I<0x41, MRMSrcMem, // if !overflow, GR32 = [mem32] + (outs GR32:$dst), (ins GR32:$src1, i32mem:$src2), + "cmovno\t{$src2, $dst|$dst, $src2}", + [(set GR32:$dst, (X86cmov GR32:$src1, (loadi32 addr:$src2), + X86_COND_NO, EFLAGS))]>, + TB; +} // Uses = [EFLAGS] + + +// unary instructions +let CodeSize = 2 in { +let Defs = [EFLAGS] in { +def NEG8r : I<0xF6, MRM3r, (outs GR8 :$dst), (ins GR8 :$src), "neg{b}\t$dst", + [(set GR8:$dst, (ineg GR8:$src)), + (implicit EFLAGS)]>; +def NEG16r : I<0xF7, MRM3r, (outs GR16:$dst), (ins GR16:$src), "neg{w}\t$dst", + [(set GR16:$dst, (ineg GR16:$src)), + (implicit EFLAGS)]>, OpSize; +def NEG32r : I<0xF7, MRM3r, (outs GR32:$dst), (ins GR32:$src), "neg{l}\t$dst", + [(set GR32:$dst, (ineg GR32:$src)), + (implicit EFLAGS)]>; +let isTwoAddress = 0 in { + def NEG8m : I<0xF6, MRM3m, (outs), (ins i8mem :$dst), "neg{b}\t$dst", + [(store (ineg (loadi8 addr:$dst)), addr:$dst), + (implicit EFLAGS)]>; + def NEG16m : I<0xF7, MRM3m, (outs), (ins i16mem:$dst), "neg{w}\t$dst", + [(store (ineg (loadi16 addr:$dst)), addr:$dst), + (implicit EFLAGS)]>, OpSize; + def NEG32m : I<0xF7, MRM3m, (outs), (ins i32mem:$dst), "neg{l}\t$dst", + [(store (ineg (loadi32 addr:$dst)), addr:$dst), + (implicit EFLAGS)]>; +} +} // Defs = [EFLAGS] + +// Match xor -1 to not. Favors these over a move imm + xor to save code size. +let AddedComplexity = 15 in { +def NOT8r : I<0xF6, MRM2r, (outs GR8 :$dst), (ins GR8 :$src), "not{b}\t$dst", + [(set GR8:$dst, (not GR8:$src))]>; +def NOT16r : I<0xF7, MRM2r, (outs GR16:$dst), (ins GR16:$src), "not{w}\t$dst", + [(set GR16:$dst, (not GR16:$src))]>, OpSize; +def NOT32r : I<0xF7, MRM2r, (outs GR32:$dst), (ins GR32:$src), "not{l}\t$dst", + [(set GR32:$dst, (not GR32:$src))]>; +} +let isTwoAddress = 0 in { + def NOT8m : I<0xF6, MRM2m, (outs), (ins i8mem :$dst), "not{b}\t$dst", + [(store (not (loadi8 addr:$dst)), addr:$dst)]>; + def NOT16m : I<0xF7, MRM2m, (outs), (ins i16mem:$dst), "not{w}\t$dst", + [(store (not (loadi16 addr:$dst)), addr:$dst)]>, OpSize; + def NOT32m : I<0xF7, MRM2m, (outs), (ins i32mem:$dst), "not{l}\t$dst", + [(store (not (loadi32 addr:$dst)), addr:$dst)]>; +} +} // CodeSize + +// TODO: inc/dec is slow for P4, but fast for Pentium-M. +let Defs = [EFLAGS] in { +let CodeSize = 2 in +def INC8r : I<0xFE, MRM0r, (outs GR8 :$dst), (ins GR8 :$src), "inc{b}\t$dst", + [(set GR8:$dst, (add GR8:$src, 1)), + (implicit EFLAGS)]>; +let isConvertibleToThreeAddress = 1, CodeSize = 1 in { // Can xform into LEA. +def INC16r : I<0x40, AddRegFrm, (outs GR16:$dst), (ins GR16:$src), "inc{w}\t$dst", + [(set GR16:$dst, (add GR16:$src, 1)), + (implicit EFLAGS)]>, + OpSize, Requires<[In32BitMode]>; +def INC32r : I<0x40, AddRegFrm, (outs GR32:$dst), (ins GR32:$src), "inc{l}\t$dst", + [(set GR32:$dst, (add GR32:$src, 1)), + (implicit EFLAGS)]>, Requires<[In32BitMode]>; +} +let isTwoAddress = 0, CodeSize = 2 in { + def INC8m : I<0xFE, MRM0m, (outs), (ins i8mem :$dst), "inc{b}\t$dst", + [(store (add (loadi8 addr:$dst), 1), addr:$dst), + (implicit EFLAGS)]>; + def INC16m : I<0xFF, MRM0m, (outs), (ins i16mem:$dst), "inc{w}\t$dst", + [(store (add (loadi16 addr:$dst), 1), addr:$dst), + (implicit EFLAGS)]>, + OpSize, Requires<[In32BitMode]>; + def INC32m : I<0xFF, MRM0m, (outs), (ins i32mem:$dst), "inc{l}\t$dst", + [(store (add (loadi32 addr:$dst), 1), addr:$dst), + (implicit EFLAGS)]>, + Requires<[In32BitMode]>; +} + +let CodeSize = 2 in +def DEC8r : I<0xFE, MRM1r, (outs GR8 :$dst), (ins GR8 :$src), "dec{b}\t$dst", + [(set GR8:$dst, (add GR8:$src, -1)), + (implicit EFLAGS)]>; +let isConvertibleToThreeAddress = 1, CodeSize = 1 in { // Can xform into LEA. +def DEC16r : I<0x48, AddRegFrm, (outs GR16:$dst), (ins GR16:$src), "dec{w}\t$dst", + [(set GR16:$dst, (add GR16:$src, -1)), + (implicit EFLAGS)]>, + OpSize, Requires<[In32BitMode]>; +def DEC32r : I<0x48, AddRegFrm, (outs GR32:$dst), (ins GR32:$src), "dec{l}\t$dst", + [(set GR32:$dst, (add GR32:$src, -1)), + (implicit EFLAGS)]>, Requires<[In32BitMode]>; +} + +let isTwoAddress = 0, CodeSize = 2 in { + def DEC8m : I<0xFE, MRM1m, (outs), (ins i8mem :$dst), "dec{b}\t$dst", + [(store (add (loadi8 addr:$dst), -1), addr:$dst), + (implicit EFLAGS)]>; + def DEC16m : I<0xFF, MRM1m, (outs), (ins i16mem:$dst), "dec{w}\t$dst", + [(store (add (loadi16 addr:$dst), -1), addr:$dst), + (implicit EFLAGS)]>, + OpSize, Requires<[In32BitMode]>; + def DEC32m : I<0xFF, MRM1m, (outs), (ins i32mem:$dst), "dec{l}\t$dst", + [(store (add (loadi32 addr:$dst), -1), addr:$dst), + (implicit EFLAGS)]>, + Requires<[In32BitMode]>; +} +} // Defs = [EFLAGS] + +// Logical operators... +let Defs = [EFLAGS] in { +let isCommutable = 1 in { // X = AND Y, Z --> X = AND Z, Y +def AND8rr : I<0x20, MRMDestReg, + (outs GR8 :$dst), (ins GR8 :$src1, GR8 :$src2), + "and{b}\t{$src2, $dst|$dst, $src2}", + [(set GR8:$dst, (and GR8:$src1, GR8:$src2)), + (implicit EFLAGS)]>; +def AND16rr : I<0x21, MRMDestReg, + (outs GR16:$dst), (ins GR16:$src1, GR16:$src2), + "and{w}\t{$src2, $dst|$dst, $src2}", + [(set GR16:$dst, (and GR16:$src1, GR16:$src2)), + (implicit EFLAGS)]>, OpSize; +def AND32rr : I<0x21, MRMDestReg, + (outs GR32:$dst), (ins GR32:$src1, GR32:$src2), + "and{l}\t{$src2, $dst|$dst, $src2}", + [(set GR32:$dst, (and GR32:$src1, GR32:$src2)), + (implicit EFLAGS)]>; +} + +def AND8rm : I<0x22, MRMSrcMem, + (outs GR8 :$dst), (ins GR8 :$src1, i8mem :$src2), + "and{b}\t{$src2, $dst|$dst, $src2}", + [(set GR8:$dst, (and GR8:$src1, (loadi8 addr:$src2))), + (implicit EFLAGS)]>; +def AND16rm : I<0x23, MRMSrcMem, + (outs GR16:$dst), (ins GR16:$src1, i16mem:$src2), + "and{w}\t{$src2, $dst|$dst, $src2}", + [(set GR16:$dst, (and GR16:$src1, (loadi16 addr:$src2))), + (implicit EFLAGS)]>, OpSize; +def AND32rm : I<0x23, MRMSrcMem, + (outs GR32:$dst), (ins GR32:$src1, i32mem:$src2), + "and{l}\t{$src2, $dst|$dst, $src2}", + [(set GR32:$dst, (and GR32:$src1, (loadi32 addr:$src2))), + (implicit EFLAGS)]>; + +def AND8ri : Ii8<0x80, MRM4r, + (outs GR8 :$dst), (ins GR8 :$src1, i8imm :$src2), + "and{b}\t{$src2, $dst|$dst, $src2}", + [(set GR8:$dst, (and GR8:$src1, imm:$src2)), + (implicit EFLAGS)]>; +def AND16ri : Ii16<0x81, MRM4r, + (outs GR16:$dst), (ins GR16:$src1, i16imm:$src2), + "and{w}\t{$src2, $dst|$dst, $src2}", + [(set GR16:$dst, (and GR16:$src1, imm:$src2)), + (implicit EFLAGS)]>, OpSize; +def AND32ri : Ii32<0x81, MRM4r, + (outs GR32:$dst), (ins GR32:$src1, i32imm:$src2), + "and{l}\t{$src2, $dst|$dst, $src2}", + [(set GR32:$dst, (and GR32:$src1, imm:$src2)), + (implicit EFLAGS)]>; +def AND16ri8 : Ii8<0x83, MRM4r, + (outs GR16:$dst), (ins GR16:$src1, i16i8imm:$src2), + "and{w}\t{$src2, $dst|$dst, $src2}", + [(set GR16:$dst, (and GR16:$src1, i16immSExt8:$src2)), + (implicit EFLAGS)]>, + OpSize; +def AND32ri8 : Ii8<0x83, MRM4r, + (outs GR32:$dst), (ins GR32:$src1, i32i8imm:$src2), + "and{l}\t{$src2, $dst|$dst, $src2}", + [(set GR32:$dst, (and GR32:$src1, i32immSExt8:$src2)), + (implicit EFLAGS)]>; + +let isTwoAddress = 0 in { + def AND8mr : I<0x20, MRMDestMem, + (outs), (ins i8mem :$dst, GR8 :$src), + "and{b}\t{$src, $dst|$dst, $src}", + [(store (and (load addr:$dst), GR8:$src), addr:$dst), + (implicit EFLAGS)]>; + def AND16mr : I<0x21, MRMDestMem, + (outs), (ins i16mem:$dst, GR16:$src), + "and{w}\t{$src, $dst|$dst, $src}", + [(store (and (load addr:$dst), GR16:$src), addr:$dst), + (implicit EFLAGS)]>, + OpSize; + def AND32mr : I<0x21, MRMDestMem, + (outs), (ins i32mem:$dst, GR32:$src), + "and{l}\t{$src, $dst|$dst, $src}", + [(store (and (load addr:$dst), GR32:$src), addr:$dst), + (implicit EFLAGS)]>; + def AND8mi : Ii8<0x80, MRM4m, + (outs), (ins i8mem :$dst, i8imm :$src), + "and{b}\t{$src, $dst|$dst, $src}", + [(store (and (loadi8 addr:$dst), imm:$src), addr:$dst), + (implicit EFLAGS)]>; + def AND16mi : Ii16<0x81, MRM4m, + (outs), (ins i16mem:$dst, i16imm:$src), + "and{w}\t{$src, $dst|$dst, $src}", + [(store (and (loadi16 addr:$dst), imm:$src), addr:$dst), + (implicit EFLAGS)]>, + OpSize; + def AND32mi : Ii32<0x81, MRM4m, + (outs), (ins i32mem:$dst, i32imm:$src), + "and{l}\t{$src, $dst|$dst, $src}", + [(store (and (loadi32 addr:$dst), imm:$src), addr:$dst), + (implicit EFLAGS)]>; + def AND16mi8 : Ii8<0x83, MRM4m, + (outs), (ins i16mem:$dst, i16i8imm :$src), + "and{w}\t{$src, $dst|$dst, $src}", + [(store (and (load addr:$dst), i16immSExt8:$src), addr:$dst), + (implicit EFLAGS)]>, + OpSize; + def AND32mi8 : Ii8<0x83, MRM4m, + (outs), (ins i32mem:$dst, i32i8imm :$src), + "and{l}\t{$src, $dst|$dst, $src}", + [(store (and (load addr:$dst), i32immSExt8:$src), addr:$dst), + (implicit EFLAGS)]>; + + def AND8i8 : Ii8<0x24, RawFrm, (outs), (ins i8imm:$src), + "and{b}\t{$src, %al|%al, $src}", []>; + def AND16i16 : Ii16<0x25, RawFrm, (outs), (ins i16imm:$src), + "and{w}\t{$src, %ax|%ax, $src}", []>, OpSize; + def AND32i32 : Ii32<0x25, RawFrm, (outs), (ins i32imm:$src), + "and{l}\t{$src, %eax|%eax, $src}", []>; + +} + + +let isCommutable = 1 in { // X = OR Y, Z --> X = OR Z, Y +def OR8rr : I<0x08, MRMDestReg, (outs GR8 :$dst), (ins GR8 :$src1, GR8 :$src2), + "or{b}\t{$src2, $dst|$dst, $src2}", + [(set GR8:$dst, (or GR8:$src1, GR8:$src2)), + (implicit EFLAGS)]>; +def OR16rr : I<0x09, MRMDestReg, (outs GR16:$dst), (ins GR16:$src1, GR16:$src2), + "or{w}\t{$src2, $dst|$dst, $src2}", + [(set GR16:$dst, (or GR16:$src1, GR16:$src2)), + (implicit EFLAGS)]>, OpSize; +def OR32rr : I<0x09, MRMDestReg, (outs GR32:$dst), (ins GR32:$src1, GR32:$src2), + "or{l}\t{$src2, $dst|$dst, $src2}", + [(set GR32:$dst, (or GR32:$src1, GR32:$src2)), + (implicit EFLAGS)]>; +} +def OR8rm : I<0x0A, MRMSrcMem , (outs GR8 :$dst), (ins GR8 :$src1, i8mem :$src2), + "or{b}\t{$src2, $dst|$dst, $src2}", + [(set GR8:$dst, (or GR8:$src1, (load addr:$src2))), + (implicit EFLAGS)]>; +def OR16rm : I<0x0B, MRMSrcMem , (outs GR16:$dst), (ins GR16:$src1, i16mem:$src2), + "or{w}\t{$src2, $dst|$dst, $src2}", + [(set GR16:$dst, (or GR16:$src1, (load addr:$src2))), + (implicit EFLAGS)]>, OpSize; +def OR32rm : I<0x0B, MRMSrcMem , (outs GR32:$dst), (ins GR32:$src1, i32mem:$src2), + "or{l}\t{$src2, $dst|$dst, $src2}", + [(set GR32:$dst, (or GR32:$src1, (load addr:$src2))), + (implicit EFLAGS)]>; + +def OR8ri : Ii8 <0x80, MRM1r, (outs GR8 :$dst), (ins GR8 :$src1, i8imm:$src2), + "or{b}\t{$src2, $dst|$dst, $src2}", + [(set GR8:$dst, (or GR8:$src1, imm:$src2)), + (implicit EFLAGS)]>; +def OR16ri : Ii16<0x81, MRM1r, (outs GR16:$dst), (ins GR16:$src1, i16imm:$src2), + "or{w}\t{$src2, $dst|$dst, $src2}", + [(set GR16:$dst, (or GR16:$src1, imm:$src2)), + (implicit EFLAGS)]>, OpSize; +def OR32ri : Ii32<0x81, MRM1r, (outs GR32:$dst), (ins GR32:$src1, i32imm:$src2), + "or{l}\t{$src2, $dst|$dst, $src2}", + [(set GR32:$dst, (or GR32:$src1, imm:$src2)), + (implicit EFLAGS)]>; + +def OR16ri8 : Ii8<0x83, MRM1r, (outs GR16:$dst), (ins GR16:$src1, i16i8imm:$src2), + "or{w}\t{$src2, $dst|$dst, $src2}", + [(set GR16:$dst, (or GR16:$src1, i16immSExt8:$src2)), + (implicit EFLAGS)]>, OpSize; +def OR32ri8 : Ii8<0x83, MRM1r, (outs GR32:$dst), (ins GR32:$src1, i32i8imm:$src2), + "or{l}\t{$src2, $dst|$dst, $src2}", + [(set GR32:$dst, (or GR32:$src1, i32immSExt8:$src2)), + (implicit EFLAGS)]>; +let isTwoAddress = 0 in { + def OR8mr : I<0x08, MRMDestMem, (outs), (ins i8mem:$dst, GR8:$src), + "or{b}\t{$src, $dst|$dst, $src}", + [(store (or (load addr:$dst), GR8:$src), addr:$dst), + (implicit EFLAGS)]>; + def OR16mr : I<0x09, MRMDestMem, (outs), (ins i16mem:$dst, GR16:$src), + "or{w}\t{$src, $dst|$dst, $src}", + [(store (or (load addr:$dst), GR16:$src), addr:$dst), + (implicit EFLAGS)]>, OpSize; + def OR32mr : I<0x09, MRMDestMem, (outs), (ins i32mem:$dst, GR32:$src), + "or{l}\t{$src, $dst|$dst, $src}", + [(store (or (load addr:$dst), GR32:$src), addr:$dst), + (implicit EFLAGS)]>; + def OR8mi : Ii8<0x80, MRM1m, (outs), (ins i8mem :$dst, i8imm:$src), + "or{b}\t{$src, $dst|$dst, $src}", + [(store (or (loadi8 addr:$dst), imm:$src), addr:$dst), + (implicit EFLAGS)]>; + def OR16mi : Ii16<0x81, MRM1m, (outs), (ins i16mem:$dst, i16imm:$src), + "or{w}\t{$src, $dst|$dst, $src}", + [(store (or (loadi16 addr:$dst), imm:$src), addr:$dst), + (implicit EFLAGS)]>, + OpSize; + def OR32mi : Ii32<0x81, MRM1m, (outs), (ins i32mem:$dst, i32imm:$src), + "or{l}\t{$src, $dst|$dst, $src}", + [(store (or (loadi32 addr:$dst), imm:$src), addr:$dst), + (implicit EFLAGS)]>; + def OR16mi8 : Ii8<0x83, MRM1m, (outs), (ins i16mem:$dst, i16i8imm:$src), + "or{w}\t{$src, $dst|$dst, $src}", + [(store (or (load addr:$dst), i16immSExt8:$src), addr:$dst), + (implicit EFLAGS)]>, + OpSize; + def OR32mi8 : Ii8<0x83, MRM1m, (outs), (ins i32mem:$dst, i32i8imm:$src), + "or{l}\t{$src, $dst|$dst, $src}", + [(store (or (load addr:$dst), i32immSExt8:$src), addr:$dst), + (implicit EFLAGS)]>; + + def OR8i8 : Ii8 <0x0C, RawFrm, (outs), (ins i8imm:$src), + "or{b}\t{$src, %al|%al, $src}", []>; + def OR16i16 : Ii16 <0x0D, RawFrm, (outs), (ins i16imm:$src), + "or{w}\t{$src, %ax|%ax, $src}", []>, OpSize; + def OR32i32 : Ii32 <0x0D, RawFrm, (outs), (ins i32imm:$src), + "or{l}\t{$src, %eax|%eax, $src}", []>; +} // isTwoAddress = 0 + + +let isCommutable = 1 in { // X = XOR Y, Z --> X = XOR Z, Y + def XOR8rr : I<0x30, MRMDestReg, + (outs GR8 :$dst), (ins GR8 :$src1, GR8 :$src2), + "xor{b}\t{$src2, $dst|$dst, $src2}", + [(set GR8:$dst, (xor GR8:$src1, GR8:$src2)), + (implicit EFLAGS)]>; + def XOR16rr : I<0x31, MRMDestReg, + (outs GR16:$dst), (ins GR16:$src1, GR16:$src2), + "xor{w}\t{$src2, $dst|$dst, $src2}", + [(set GR16:$dst, (xor GR16:$src1, GR16:$src2)), + (implicit EFLAGS)]>, OpSize; + def XOR32rr : I<0x31, MRMDestReg, + (outs GR32:$dst), (ins GR32:$src1, GR32:$src2), + "xor{l}\t{$src2, $dst|$dst, $src2}", + [(set GR32:$dst, (xor GR32:$src1, GR32:$src2)), + (implicit EFLAGS)]>; +} // isCommutable = 1 + +def XOR8rm : I<0x32, MRMSrcMem , + (outs GR8 :$dst), (ins GR8:$src1, i8mem :$src2), + "xor{b}\t{$src2, $dst|$dst, $src2}", + [(set GR8:$dst, (xor GR8:$src1, (load addr:$src2))), + (implicit EFLAGS)]>; +def XOR16rm : I<0x33, MRMSrcMem , + (outs GR16:$dst), (ins GR16:$src1, i16mem:$src2), + "xor{w}\t{$src2, $dst|$dst, $src2}", + [(set GR16:$dst, (xor GR16:$src1, (load addr:$src2))), + (implicit EFLAGS)]>, + OpSize; +def XOR32rm : I<0x33, MRMSrcMem , + (outs GR32:$dst), (ins GR32:$src1, i32mem:$src2), + "xor{l}\t{$src2, $dst|$dst, $src2}", + [(set GR32:$dst, (xor GR32:$src1, (load addr:$src2))), + (implicit EFLAGS)]>; + +def XOR8ri : Ii8<0x80, MRM6r, + (outs GR8:$dst), (ins GR8:$src1, i8imm:$src2), + "xor{b}\t{$src2, $dst|$dst, $src2}", + [(set GR8:$dst, (xor GR8:$src1, imm:$src2)), + (implicit EFLAGS)]>; +def XOR16ri : Ii16<0x81, MRM6r, + (outs GR16:$dst), (ins GR16:$src1, i16imm:$src2), + "xor{w}\t{$src2, $dst|$dst, $src2}", + [(set GR16:$dst, (xor GR16:$src1, imm:$src2)), + (implicit EFLAGS)]>, OpSize; +def XOR32ri : Ii32<0x81, MRM6r, + (outs GR32:$dst), (ins GR32:$src1, i32imm:$src2), + "xor{l}\t{$src2, $dst|$dst, $src2}", + [(set GR32:$dst, (xor GR32:$src1, imm:$src2)), + (implicit EFLAGS)]>; +def XOR16ri8 : Ii8<0x83, MRM6r, + (outs GR16:$dst), (ins GR16:$src1, i16i8imm:$src2), + "xor{w}\t{$src2, $dst|$dst, $src2}", + [(set GR16:$dst, (xor GR16:$src1, i16immSExt8:$src2)), + (implicit EFLAGS)]>, + OpSize; +def XOR32ri8 : Ii8<0x83, MRM6r, + (outs GR32:$dst), (ins GR32:$src1, i32i8imm:$src2), + "xor{l}\t{$src2, $dst|$dst, $src2}", + [(set GR32:$dst, (xor GR32:$src1, i32immSExt8:$src2)), + (implicit EFLAGS)]>; + +let isTwoAddress = 0 in { + def XOR8mr : I<0x30, MRMDestMem, + (outs), (ins i8mem :$dst, GR8 :$src), + "xor{b}\t{$src, $dst|$dst, $src}", + [(store (xor (load addr:$dst), GR8:$src), addr:$dst), + (implicit EFLAGS)]>; + def XOR16mr : I<0x31, MRMDestMem, + (outs), (ins i16mem:$dst, GR16:$src), + "xor{w}\t{$src, $dst|$dst, $src}", + [(store (xor (load addr:$dst), GR16:$src), addr:$dst), + (implicit EFLAGS)]>, + OpSize; + def XOR32mr : I<0x31, MRMDestMem, + (outs), (ins i32mem:$dst, GR32:$src), + "xor{l}\t{$src, $dst|$dst, $src}", + [(store (xor (load addr:$dst), GR32:$src), addr:$dst), + (implicit EFLAGS)]>; + def XOR8mi : Ii8<0x80, MRM6m, + (outs), (ins i8mem :$dst, i8imm :$src), + "xor{b}\t{$src, $dst|$dst, $src}", + [(store (xor (loadi8 addr:$dst), imm:$src), addr:$dst), + (implicit EFLAGS)]>; + def XOR16mi : Ii16<0x81, MRM6m, + (outs), (ins i16mem:$dst, i16imm:$src), + "xor{w}\t{$src, $dst|$dst, $src}", + [(store (xor (loadi16 addr:$dst), imm:$src), addr:$dst), + (implicit EFLAGS)]>, + OpSize; + def XOR32mi : Ii32<0x81, MRM6m, + (outs), (ins i32mem:$dst, i32imm:$src), + "xor{l}\t{$src, $dst|$dst, $src}", + [(store (xor (loadi32 addr:$dst), imm:$src), addr:$dst), + (implicit EFLAGS)]>; + def XOR16mi8 : Ii8<0x83, MRM6m, + (outs), (ins i16mem:$dst, i16i8imm :$src), + "xor{w}\t{$src, $dst|$dst, $src}", + [(store (xor (load addr:$dst), i16immSExt8:$src), addr:$dst), + (implicit EFLAGS)]>, + OpSize; + def XOR32mi8 : Ii8<0x83, MRM6m, + (outs), (ins i32mem:$dst, i32i8imm :$src), + "xor{l}\t{$src, $dst|$dst, $src}", + [(store (xor (load addr:$dst), i32immSExt8:$src), addr:$dst), + (implicit EFLAGS)]>; + + def XOR8i8 : Ii8 <0x34, RawFrm, (outs), (ins i8imm:$src), + "xor{b}\t{$src, %al|%al, $src}", []>; + def XOR16i16 : Ii16 <0x35, RawFrm, (outs), (ins i16imm:$src), + "xor{w}\t{$src, %ax|%ax, $src}", []>, OpSize; + def XOR32i32 : Ii32 <0x35, RawFrm, (outs), (ins i32imm:$src), + "xor{l}\t{$src, %eax|%eax, $src}", []>; +} // isTwoAddress = 0 +} // Defs = [EFLAGS] + +// Shift instructions +let Defs = [EFLAGS] in { +let Uses = [CL] in { +def SHL8rCL : I<0xD2, MRM4r, (outs GR8 :$dst), (ins GR8 :$src), + "shl{b}\t{%cl, $dst|$dst, CL}", + [(set GR8:$dst, (shl GR8:$src, CL))]>; +def SHL16rCL : I<0xD3, MRM4r, (outs GR16:$dst), (ins GR16:$src), + "shl{w}\t{%cl, $dst|$dst, CL}", + [(set GR16:$dst, (shl GR16:$src, CL))]>, OpSize; +def SHL32rCL : I<0xD3, MRM4r, (outs GR32:$dst), (ins GR32:$src), + "shl{l}\t{%cl, $dst|$dst, CL}", + [(set GR32:$dst, (shl GR32:$src, CL))]>; +} // Uses = [CL] + +def SHL8ri : Ii8<0xC0, MRM4r, (outs GR8 :$dst), (ins GR8 :$src1, i8imm:$src2), + "shl{b}\t{$src2, $dst|$dst, $src2}", + [(set GR8:$dst, (shl GR8:$src1, (i8 imm:$src2)))]>; +let isConvertibleToThreeAddress = 1 in { // Can transform into LEA. +def SHL16ri : Ii8<0xC1, MRM4r, (outs GR16:$dst), (ins GR16:$src1, i8imm:$src2), + "shl{w}\t{$src2, $dst|$dst, $src2}", + [(set GR16:$dst, (shl GR16:$src1, (i8 imm:$src2)))]>, OpSize; +def SHL32ri : Ii8<0xC1, MRM4r, (outs GR32:$dst), (ins GR32:$src1, i8imm:$src2), + "shl{l}\t{$src2, $dst|$dst, $src2}", + [(set GR32:$dst, (shl GR32:$src1, (i8 imm:$src2)))]>; + +// NOTE: We don't include patterns for shifts of a register by one, because +// 'add reg,reg' is cheaper. + +def SHL8r1 : I<0xD0, MRM4r, (outs GR8:$dst), (ins GR8:$src1), + "shl{b}\t$dst", []>; +def SHL16r1 : I<0xD1, MRM4r, (outs GR16:$dst), (ins GR16:$src1), + "shl{w}\t$dst", []>, OpSize; +def SHL32r1 : I<0xD1, MRM4r, (outs GR32:$dst), (ins GR32:$src1), + "shl{l}\t$dst", []>; + +} // isConvertibleToThreeAddress = 1 + +let isTwoAddress = 0 in { + let Uses = [CL] in { + def SHL8mCL : I<0xD2, MRM4m, (outs), (ins i8mem :$dst), + "shl{b}\t{%cl, $dst|$dst, CL}", + [(store (shl (loadi8 addr:$dst), CL), addr:$dst)]>; + def SHL16mCL : I<0xD3, MRM4m, (outs), (ins i16mem:$dst), + "shl{w}\t{%cl, $dst|$dst, CL}", + [(store (shl (loadi16 addr:$dst), CL), addr:$dst)]>, OpSize; + def SHL32mCL : I<0xD3, MRM4m, (outs), (ins i32mem:$dst), + "shl{l}\t{%cl, $dst|$dst, CL}", + [(store (shl (loadi32 addr:$dst), CL), addr:$dst)]>; + } + def SHL8mi : Ii8<0xC0, MRM4m, (outs), (ins i8mem :$dst, i8imm:$src), + "shl{b}\t{$src, $dst|$dst, $src}", + [(store (shl (loadi8 addr:$dst), (i8 imm:$src)), addr:$dst)]>; + def SHL16mi : Ii8<0xC1, MRM4m, (outs), (ins i16mem:$dst, i8imm:$src), + "shl{w}\t{$src, $dst|$dst, $src}", + [(store (shl (loadi16 addr:$dst), (i8 imm:$src)), addr:$dst)]>, + OpSize; + def SHL32mi : Ii8<0xC1, MRM4m, (outs), (ins i32mem:$dst, i8imm:$src), + "shl{l}\t{$src, $dst|$dst, $src}", + [(store (shl (loadi32 addr:$dst), (i8 imm:$src)), addr:$dst)]>; + + // Shift by 1 + def SHL8m1 : I<0xD0, MRM4m, (outs), (ins i8mem :$dst), + "shl{b}\t$dst", + [(store (shl (loadi8 addr:$dst), (i8 1)), addr:$dst)]>; + def SHL16m1 : I<0xD1, MRM4m, (outs), (ins i16mem:$dst), + "shl{w}\t$dst", + [(store (shl (loadi16 addr:$dst), (i8 1)), addr:$dst)]>, + OpSize; + def SHL32m1 : I<0xD1, MRM4m, (outs), (ins i32mem:$dst), + "shl{l}\t$dst", + [(store (shl (loadi32 addr:$dst), (i8 1)), addr:$dst)]>; +} + +let Uses = [CL] in { +def SHR8rCL : I<0xD2, MRM5r, (outs GR8 :$dst), (ins GR8 :$src), + "shr{b}\t{%cl, $dst|$dst, CL}", + [(set GR8:$dst, (srl GR8:$src, CL))]>; +def SHR16rCL : I<0xD3, MRM5r, (outs GR16:$dst), (ins GR16:$src), + "shr{w}\t{%cl, $dst|$dst, CL}", + [(set GR16:$dst, (srl GR16:$src, CL))]>, OpSize; +def SHR32rCL : I<0xD3, MRM5r, (outs GR32:$dst), (ins GR32:$src), + "shr{l}\t{%cl, $dst|$dst, CL}", + [(set GR32:$dst, (srl GR32:$src, CL))]>; +} + +def SHR8ri : Ii8<0xC0, MRM5r, (outs GR8:$dst), (ins GR8:$src1, i8imm:$src2), + "shr{b}\t{$src2, $dst|$dst, $src2}", + [(set GR8:$dst, (srl GR8:$src1, (i8 imm:$src2)))]>; +def SHR16ri : Ii8<0xC1, MRM5r, (outs GR16:$dst), (ins GR16:$src1, i8imm:$src2), + "shr{w}\t{$src2, $dst|$dst, $src2}", + [(set GR16:$dst, (srl GR16:$src1, (i8 imm:$src2)))]>, OpSize; +def SHR32ri : Ii8<0xC1, MRM5r, (outs GR32:$dst), (ins GR32:$src1, i8imm:$src2), + "shr{l}\t{$src2, $dst|$dst, $src2}", + [(set GR32:$dst, (srl GR32:$src1, (i8 imm:$src2)))]>; + +// Shift by 1 +def SHR8r1 : I<0xD0, MRM5r, (outs GR8:$dst), (ins GR8:$src1), + "shr{b}\t$dst", + [(set GR8:$dst, (srl GR8:$src1, (i8 1)))]>; +def SHR16r1 : I<0xD1, MRM5r, (outs GR16:$dst), (ins GR16:$src1), + "shr{w}\t$dst", + [(set GR16:$dst, (srl GR16:$src1, (i8 1)))]>, OpSize; +def SHR32r1 : I<0xD1, MRM5r, (outs GR32:$dst), (ins GR32:$src1), + "shr{l}\t$dst", + [(set GR32:$dst, (srl GR32:$src1, (i8 1)))]>; + +let isTwoAddress = 0 in { + let Uses = [CL] in { + def SHR8mCL : I<0xD2, MRM5m, (outs), (ins i8mem :$dst), + "shr{b}\t{%cl, $dst|$dst, CL}", + [(store (srl (loadi8 addr:$dst), CL), addr:$dst)]>; + def SHR16mCL : I<0xD3, MRM5m, (outs), (ins i16mem:$dst), + "shr{w}\t{%cl, $dst|$dst, CL}", + [(store (srl (loadi16 addr:$dst), CL), addr:$dst)]>, + OpSize; + def SHR32mCL : I<0xD3, MRM5m, (outs), (ins i32mem:$dst), + "shr{l}\t{%cl, $dst|$dst, CL}", + [(store (srl (loadi32 addr:$dst), CL), addr:$dst)]>; + } + def SHR8mi : Ii8<0xC0, MRM5m, (outs), (ins i8mem :$dst, i8imm:$src), + "shr{b}\t{$src, $dst|$dst, $src}", + [(store (srl (loadi8 addr:$dst), (i8 imm:$src)), addr:$dst)]>; + def SHR16mi : Ii8<0xC1, MRM5m, (outs), (ins i16mem:$dst, i8imm:$src), + "shr{w}\t{$src, $dst|$dst, $src}", + [(store (srl (loadi16 addr:$dst), (i8 imm:$src)), addr:$dst)]>, + OpSize; + def SHR32mi : Ii8<0xC1, MRM5m, (outs), (ins i32mem:$dst, i8imm:$src), + "shr{l}\t{$src, $dst|$dst, $src}", + [(store (srl (loadi32 addr:$dst), (i8 imm:$src)), addr:$dst)]>; + + // Shift by 1 + def SHR8m1 : I<0xD0, MRM5m, (outs), (ins i8mem :$dst), + "shr{b}\t$dst", + [(store (srl (loadi8 addr:$dst), (i8 1)), addr:$dst)]>; + def SHR16m1 : I<0xD1, MRM5m, (outs), (ins i16mem:$dst), + "shr{w}\t$dst", + [(store (srl (loadi16 addr:$dst), (i8 1)), addr:$dst)]>,OpSize; + def SHR32m1 : I<0xD1, MRM5m, (outs), (ins i32mem:$dst), + "shr{l}\t$dst", + [(store (srl (loadi32 addr:$dst), (i8 1)), addr:$dst)]>; +} + +let Uses = [CL] in { +def SAR8rCL : I<0xD2, MRM7r, (outs GR8 :$dst), (ins GR8 :$src), + "sar{b}\t{%cl, $dst|$dst, CL}", + [(set GR8:$dst, (sra GR8:$src, CL))]>; +def SAR16rCL : I<0xD3, MRM7r, (outs GR16:$dst), (ins GR16:$src), + "sar{w}\t{%cl, $dst|$dst, CL}", + [(set GR16:$dst, (sra GR16:$src, CL))]>, OpSize; +def SAR32rCL : I<0xD3, MRM7r, (outs GR32:$dst), (ins GR32:$src), + "sar{l}\t{%cl, $dst|$dst, CL}", + [(set GR32:$dst, (sra GR32:$src, CL))]>; +} + +def SAR8ri : Ii8<0xC0, MRM7r, (outs GR8 :$dst), (ins GR8 :$src1, i8imm:$src2), + "sar{b}\t{$src2, $dst|$dst, $src2}", + [(set GR8:$dst, (sra GR8:$src1, (i8 imm:$src2)))]>; +def SAR16ri : Ii8<0xC1, MRM7r, (outs GR16:$dst), (ins GR16:$src1, i8imm:$src2), + "sar{w}\t{$src2, $dst|$dst, $src2}", + [(set GR16:$dst, (sra GR16:$src1, (i8 imm:$src2)))]>, + OpSize; +def SAR32ri : Ii8<0xC1, MRM7r, (outs GR32:$dst), (ins GR32:$src1, i8imm:$src2), + "sar{l}\t{$src2, $dst|$dst, $src2}", + [(set GR32:$dst, (sra GR32:$src1, (i8 imm:$src2)))]>; + +// Shift by 1 +def SAR8r1 : I<0xD0, MRM7r, (outs GR8 :$dst), (ins GR8 :$src1), + "sar{b}\t$dst", + [(set GR8:$dst, (sra GR8:$src1, (i8 1)))]>; +def SAR16r1 : I<0xD1, MRM7r, (outs GR16:$dst), (ins GR16:$src1), + "sar{w}\t$dst", + [(set GR16:$dst, (sra GR16:$src1, (i8 1)))]>, OpSize; +def SAR32r1 : I<0xD1, MRM7r, (outs GR32:$dst), (ins GR32:$src1), + "sar{l}\t$dst", + [(set GR32:$dst, (sra GR32:$src1, (i8 1)))]>; + +let isTwoAddress = 0 in { + let Uses = [CL] in { + def SAR8mCL : I<0xD2, MRM7m, (outs), (ins i8mem :$dst), + "sar{b}\t{%cl, $dst|$dst, CL}", + [(store (sra (loadi8 addr:$dst), CL), addr:$dst)]>; + def SAR16mCL : I<0xD3, MRM7m, (outs), (ins i16mem:$dst), + "sar{w}\t{%cl, $dst|$dst, CL}", + [(store (sra (loadi16 addr:$dst), CL), addr:$dst)]>, OpSize; + def SAR32mCL : I<0xD3, MRM7m, (outs), (ins i32mem:$dst), + "sar{l}\t{%cl, $dst|$dst, CL}", + [(store (sra (loadi32 addr:$dst), CL), addr:$dst)]>; + } + def SAR8mi : Ii8<0xC0, MRM7m, (outs), (ins i8mem :$dst, i8imm:$src), + "sar{b}\t{$src, $dst|$dst, $src}", + [(store (sra (loadi8 addr:$dst), (i8 imm:$src)), addr:$dst)]>; + def SAR16mi : Ii8<0xC1, MRM7m, (outs), (ins i16mem:$dst, i8imm:$src), + "sar{w}\t{$src, $dst|$dst, $src}", + [(store (sra (loadi16 addr:$dst), (i8 imm:$src)), addr:$dst)]>, + OpSize; + def SAR32mi : Ii8<0xC1, MRM7m, (outs), (ins i32mem:$dst, i8imm:$src), + "sar{l}\t{$src, $dst|$dst, $src}", + [(store (sra (loadi32 addr:$dst), (i8 imm:$src)), addr:$dst)]>; + + // Shift by 1 + def SAR8m1 : I<0xD0, MRM7m, (outs), (ins i8mem :$dst), + "sar{b}\t$dst", + [(store (sra (loadi8 addr:$dst), (i8 1)), addr:$dst)]>; + def SAR16m1 : I<0xD1, MRM7m, (outs), (ins i16mem:$dst), + "sar{w}\t$dst", + [(store (sra (loadi16 addr:$dst), (i8 1)), addr:$dst)]>, + OpSize; + def SAR32m1 : I<0xD1, MRM7m, (outs), (ins i32mem:$dst), + "sar{l}\t$dst", + [(store (sra (loadi32 addr:$dst), (i8 1)), addr:$dst)]>; +} + +// Rotate instructions + +def RCL8r1 : I<0xD0, MRM2r, (outs GR8:$dst), (ins GR8:$src), + "rcl{b}\t{1, $dst|$dst, 1}", []>; +def RCL8m1 : I<0xD0, MRM2m, (outs i8mem:$dst), (ins i8mem:$src), + "rcl{b}\t{1, $dst|$dst, 1}", []>; +let Uses = [CL] in { +def RCL8rCL : I<0xD2, MRM2r, (outs GR8:$dst), (ins GR8:$src), + "rcl{b}\t{%cl, $dst|$dst, CL}", []>; +def RCL8mCL : I<0xD2, MRM2m, (outs i8mem:$dst), (ins i8mem:$src), + "rcl{b}\t{%cl, $dst|$dst, CL}", []>; +} +def RCL8ri : Ii8<0xC0, MRM2r, (outs GR8:$dst), (ins GR8:$src, i8imm:$cnt), + "rcl{b}\t{$cnt, $dst|$dst, $cnt}", []>; +def RCL8mi : Ii8<0xC0, MRM2m, (outs i8mem:$dst), (ins i8mem:$src, i8imm:$cnt), + "rcl{b}\t{$cnt, $dst|$dst, $cnt}", []>; + +def RCL16r1 : I<0xD1, MRM2r, (outs GR16:$dst), (ins GR16:$src), + "rcl{w}\t{1, $dst|$dst, 1}", []>, OpSize; +def RCL16m1 : I<0xD1, MRM2m, (outs i16mem:$dst), (ins i16mem:$src), + "rcl{w}\t{1, $dst|$dst, 1}", []>, OpSize; +let Uses = [CL] in { +def RCL16rCL : I<0xD3, MRM2r, (outs GR16:$dst), (ins GR16:$src), + "rcl{w}\t{%cl, $dst|$dst, CL}", []>, OpSize; +def RCL16mCL : I<0xD3, MRM2m, (outs i16mem:$dst), (ins i16mem:$src), + "rcl{w}\t{%cl, $dst|$dst, CL}", []>, OpSize; +} +def RCL16ri : Ii8<0xC1, MRM2r, (outs GR16:$dst), (ins GR16:$src, i8imm:$cnt), + "rcl{w}\t{$cnt, $dst|$dst, $cnt}", []>, OpSize; +def RCL16mi : Ii8<0xC1, MRM2m, (outs i16mem:$dst), (ins i16mem:$src, i8imm:$cnt), + "rcl{w}\t{$cnt, $dst|$dst, $cnt}", []>, OpSize; + +def RCL32r1 : I<0xD1, MRM2r, (outs GR32:$dst), (ins GR32:$src), + "rcl{l}\t{1, $dst|$dst, 1}", []>; +def RCL32m1 : I<0xD1, MRM2m, (outs i32mem:$dst), (ins i32mem:$src), + "rcl{l}\t{1, $dst|$dst, 1}", []>; +let Uses = [CL] in { +def RCL32rCL : I<0xD3, MRM2r, (outs GR32:$dst), (ins GR32:$src), + "rcl{l}\t{%cl, $dst|$dst, CL}", []>; +def RCL32mCL : I<0xD3, MRM2m, (outs i32mem:$dst), (ins i32mem:$src), + "rcl{l}\t{%cl, $dst|$dst, CL}", []>; +} +def RCL32ri : Ii8<0xC1, MRM2r, (outs GR32:$dst), (ins GR32:$src, i8imm:$cnt), + "rcl{l}\t{$cnt, $dst|$dst, $cnt}", []>; +def RCL32mi : Ii8<0xC1, MRM2m, (outs i32mem:$dst), (ins i32mem:$src, i8imm:$cnt), + "rcl{l}\t{$cnt, $dst|$dst, $cnt}", []>; + +def RCR8r1 : I<0xD0, MRM3r, (outs GR8:$dst), (ins GR8:$src), + "rcr{b}\t{1, $dst|$dst, 1}", []>; +def RCR8m1 : I<0xD0, MRM3m, (outs i8mem:$dst), (ins i8mem:$src), + "rcr{b}\t{1, $dst|$dst, 1}", []>; +let Uses = [CL] in { +def RCR8rCL : I<0xD2, MRM3r, (outs GR8:$dst), (ins GR8:$src), + "rcr{b}\t{%cl, $dst|$dst, CL}", []>; +def RCR8mCL : I<0xD2, MRM3m, (outs i8mem:$dst), (ins i8mem:$src), + "rcr{b}\t{%cl, $dst|$dst, CL}", []>; +} +def RCR8ri : Ii8<0xC0, MRM3r, (outs GR8:$dst), (ins GR8:$src, i8imm:$cnt), + "rcr{b}\t{$cnt, $dst|$dst, $cnt}", []>; +def RCR8mi : Ii8<0xC0, MRM3m, (outs i8mem:$dst), (ins i8mem:$src, i8imm:$cnt), + "rcr{b}\t{$cnt, $dst|$dst, $cnt}", []>; + +def RCR16r1 : I<0xD1, MRM3r, (outs GR16:$dst), (ins GR16:$src), + "rcr{w}\t{1, $dst|$dst, 1}", []>, OpSize; +def RCR16m1 : I<0xD1, MRM3m, (outs i16mem:$dst), (ins i16mem:$src), + "rcr{w}\t{1, $dst|$dst, 1}", []>, OpSize; +let Uses = [CL] in { +def RCR16rCL : I<0xD3, MRM3r, (outs GR16:$dst), (ins GR16:$src), + "rcr{w}\t{%cl, $dst|$dst, CL}", []>, OpSize; +def RCR16mCL : I<0xD3, MRM3m, (outs i16mem:$dst), (ins i16mem:$src), + "rcr{w}\t{%cl, $dst|$dst, CL}", []>, OpSize; +} +def RCR16ri : Ii8<0xC1, MRM3r, (outs GR16:$dst), (ins GR16:$src, i8imm:$cnt), + "rcr{w}\t{$cnt, $dst|$dst, $cnt}", []>, OpSize; +def RCR16mi : Ii8<0xC1, MRM3m, (outs i16mem:$dst), (ins i16mem:$src, i8imm:$cnt), + "rcr{w}\t{$cnt, $dst|$dst, $cnt}", []>, OpSize; + +def RCR32r1 : I<0xD1, MRM3r, (outs GR32:$dst), (ins GR32:$src), + "rcr{l}\t{1, $dst|$dst, 1}", []>; +def RCR32m1 : I<0xD1, MRM3m, (outs i32mem:$dst), (ins i32mem:$src), + "rcr{l}\t{1, $dst|$dst, 1}", []>; +let Uses = [CL] in { +def RCR32rCL : I<0xD3, MRM3r, (outs GR32:$dst), (ins GR32:$src), + "rcr{l}\t{%cl, $dst|$dst, CL}", []>; +def RCR32mCL : I<0xD3, MRM3m, (outs i32mem:$dst), (ins i32mem:$src), + "rcr{l}\t{%cl, $dst|$dst, CL}", []>; +} +def RCR32ri : Ii8<0xC1, MRM3r, (outs GR32:$dst), (ins GR32:$src, i8imm:$cnt), + "rcr{l}\t{$cnt, $dst|$dst, $cnt}", []>; +def RCR32mi : Ii8<0xC1, MRM3m, (outs i32mem:$dst), (ins i32mem:$src, i8imm:$cnt), + "rcr{l}\t{$cnt, $dst|$dst, $cnt}", []>; + +// FIXME: provide shorter instructions when imm8 == 1 +let Uses = [CL] in { +def ROL8rCL : I<0xD2, MRM0r, (outs GR8 :$dst), (ins GR8 :$src), + "rol{b}\t{%cl, $dst|$dst, CL}", + [(set GR8:$dst, (rotl GR8:$src, CL))]>; +def ROL16rCL : I<0xD3, MRM0r, (outs GR16:$dst), (ins GR16:$src), + "rol{w}\t{%cl, $dst|$dst, CL}", + [(set GR16:$dst, (rotl GR16:$src, CL))]>, OpSize; +def ROL32rCL : I<0xD3, MRM0r, (outs GR32:$dst), (ins GR32:$src), + "rol{l}\t{%cl, $dst|$dst, CL}", + [(set GR32:$dst, (rotl GR32:$src, CL))]>; +} + +def ROL8ri : Ii8<0xC0, MRM0r, (outs GR8 :$dst), (ins GR8 :$src1, i8imm:$src2), + "rol{b}\t{$src2, $dst|$dst, $src2}", + [(set GR8:$dst, (rotl GR8:$src1, (i8 imm:$src2)))]>; +def ROL16ri : Ii8<0xC1, MRM0r, (outs GR16:$dst), (ins GR16:$src1, i8imm:$src2), + "rol{w}\t{$src2, $dst|$dst, $src2}", + [(set GR16:$dst, (rotl GR16:$src1, (i8 imm:$src2)))]>, OpSize; +def ROL32ri : Ii8<0xC1, MRM0r, (outs GR32:$dst), (ins GR32:$src1, i8imm:$src2), + "rol{l}\t{$src2, $dst|$dst, $src2}", + [(set GR32:$dst, (rotl GR32:$src1, (i8 imm:$src2)))]>; + +// Rotate by 1 +def ROL8r1 : I<0xD0, MRM0r, (outs GR8 :$dst), (ins GR8 :$src1), + "rol{b}\t$dst", + [(set GR8:$dst, (rotl GR8:$src1, (i8 1)))]>; +def ROL16r1 : I<0xD1, MRM0r, (outs GR16:$dst), (ins GR16:$src1), + "rol{w}\t$dst", + [(set GR16:$dst, (rotl GR16:$src1, (i8 1)))]>, OpSize; +def ROL32r1 : I<0xD1, MRM0r, (outs GR32:$dst), (ins GR32:$src1), + "rol{l}\t$dst", + [(set GR32:$dst, (rotl GR32:$src1, (i8 1)))]>; + +let isTwoAddress = 0 in { + let Uses = [CL] in { + def ROL8mCL : I<0xD2, MRM0m, (outs), (ins i8mem :$dst), + "rol{b}\t{%cl, $dst|$dst, CL}", + [(store (rotl (loadi8 addr:$dst), CL), addr:$dst)]>; + def ROL16mCL : I<0xD3, MRM0m, (outs), (ins i16mem:$dst), + "rol{w}\t{%cl, $dst|$dst, CL}", + [(store (rotl (loadi16 addr:$dst), CL), addr:$dst)]>, OpSize; + def ROL32mCL : I<0xD3, MRM0m, (outs), (ins i32mem:$dst), + "rol{l}\t{%cl, $dst|$dst, CL}", + [(store (rotl (loadi32 addr:$dst), CL), addr:$dst)]>; + } + def ROL8mi : Ii8<0xC0, MRM0m, (outs), (ins i8mem :$dst, i8imm:$src), + "rol{b}\t{$src, $dst|$dst, $src}", + [(store (rotl (loadi8 addr:$dst), (i8 imm:$src)), addr:$dst)]>; + def ROL16mi : Ii8<0xC1, MRM0m, (outs), (ins i16mem:$dst, i8imm:$src), + "rol{w}\t{$src, $dst|$dst, $src}", + [(store (rotl (loadi16 addr:$dst), (i8 imm:$src)), addr:$dst)]>, + OpSize; + def ROL32mi : Ii8<0xC1, MRM0m, (outs), (ins i32mem:$dst, i8imm:$src), + "rol{l}\t{$src, $dst|$dst, $src}", + [(store (rotl (loadi32 addr:$dst), (i8 imm:$src)), addr:$dst)]>; + + // Rotate by 1 + def ROL8m1 : I<0xD0, MRM0m, (outs), (ins i8mem :$dst), + "rol{b}\t$dst", + [(store (rotl (loadi8 addr:$dst), (i8 1)), addr:$dst)]>; + def ROL16m1 : I<0xD1, MRM0m, (outs), (ins i16mem:$dst), + "rol{w}\t$dst", + [(store (rotl (loadi16 addr:$dst), (i8 1)), addr:$dst)]>, + OpSize; + def ROL32m1 : I<0xD1, MRM0m, (outs), (ins i32mem:$dst), + "rol{l}\t$dst", + [(store (rotl (loadi32 addr:$dst), (i8 1)), addr:$dst)]>; +} + +let Uses = [CL] in { +def ROR8rCL : I<0xD2, MRM1r, (outs GR8 :$dst), (ins GR8 :$src), + "ror{b}\t{%cl, $dst|$dst, CL}", + [(set GR8:$dst, (rotr GR8:$src, CL))]>; +def ROR16rCL : I<0xD3, MRM1r, (outs GR16:$dst), (ins GR16:$src), + "ror{w}\t{%cl, $dst|$dst, CL}", + [(set GR16:$dst, (rotr GR16:$src, CL))]>, OpSize; +def ROR32rCL : I<0xD3, MRM1r, (outs GR32:$dst), (ins GR32:$src), + "ror{l}\t{%cl, $dst|$dst, CL}", + [(set GR32:$dst, (rotr GR32:$src, CL))]>; +} + +def ROR8ri : Ii8<0xC0, MRM1r, (outs GR8 :$dst), (ins GR8 :$src1, i8imm:$src2), + "ror{b}\t{$src2, $dst|$dst, $src2}", + [(set GR8:$dst, (rotr GR8:$src1, (i8 imm:$src2)))]>; +def ROR16ri : Ii8<0xC1, MRM1r, (outs GR16:$dst), (ins GR16:$src1, i8imm:$src2), + "ror{w}\t{$src2, $dst|$dst, $src2}", + [(set GR16:$dst, (rotr GR16:$src1, (i8 imm:$src2)))]>, OpSize; +def ROR32ri : Ii8<0xC1, MRM1r, (outs GR32:$dst), (ins GR32:$src1, i8imm:$src2), + "ror{l}\t{$src2, $dst|$dst, $src2}", + [(set GR32:$dst, (rotr GR32:$src1, (i8 imm:$src2)))]>; + +// Rotate by 1 +def ROR8r1 : I<0xD0, MRM1r, (outs GR8 :$dst), (ins GR8 :$src1), + "ror{b}\t$dst", + [(set GR8:$dst, (rotr GR8:$src1, (i8 1)))]>; +def ROR16r1 : I<0xD1, MRM1r, (outs GR16:$dst), (ins GR16:$src1), + "ror{w}\t$dst", + [(set GR16:$dst, (rotr GR16:$src1, (i8 1)))]>, OpSize; +def ROR32r1 : I<0xD1, MRM1r, (outs GR32:$dst), (ins GR32:$src1), + "ror{l}\t$dst", + [(set GR32:$dst, (rotr GR32:$src1, (i8 1)))]>; + +let isTwoAddress = 0 in { + let Uses = [CL] in { + def ROR8mCL : I<0xD2, MRM1m, (outs), (ins i8mem :$dst), + "ror{b}\t{%cl, $dst|$dst, CL}", + [(store (rotr (loadi8 addr:$dst), CL), addr:$dst)]>; + def ROR16mCL : I<0xD3, MRM1m, (outs), (ins i16mem:$dst), + "ror{w}\t{%cl, $dst|$dst, CL}", + [(store (rotr (loadi16 addr:$dst), CL), addr:$dst)]>, OpSize; + def ROR32mCL : I<0xD3, MRM1m, (outs), (ins i32mem:$dst), + "ror{l}\t{%cl, $dst|$dst, CL}", + [(store (rotr (loadi32 addr:$dst), CL), addr:$dst)]>; + } + def ROR8mi : Ii8<0xC0, MRM1m, (outs), (ins i8mem :$dst, i8imm:$src), + "ror{b}\t{$src, $dst|$dst, $src}", + [(store (rotr (loadi8 addr:$dst), (i8 imm:$src)), addr:$dst)]>; + def ROR16mi : Ii8<0xC1, MRM1m, (outs), (ins i16mem:$dst, i8imm:$src), + "ror{w}\t{$src, $dst|$dst, $src}", + [(store (rotr (loadi16 addr:$dst), (i8 imm:$src)), addr:$dst)]>, + OpSize; + def ROR32mi : Ii8<0xC1, MRM1m, (outs), (ins i32mem:$dst, i8imm:$src), + "ror{l}\t{$src, $dst|$dst, $src}", + [(store (rotr (loadi32 addr:$dst), (i8 imm:$src)), addr:$dst)]>; + + // Rotate by 1 + def ROR8m1 : I<0xD0, MRM1m, (outs), (ins i8mem :$dst), + "ror{b}\t$dst", + [(store (rotr (loadi8 addr:$dst), (i8 1)), addr:$dst)]>; + def ROR16m1 : I<0xD1, MRM1m, (outs), (ins i16mem:$dst), + "ror{w}\t$dst", + [(store (rotr (loadi16 addr:$dst), (i8 1)), addr:$dst)]>, + OpSize; + def ROR32m1 : I<0xD1, MRM1m, (outs), (ins i32mem:$dst), + "ror{l}\t$dst", + [(store (rotr (loadi32 addr:$dst), (i8 1)), addr:$dst)]>; +} + + + +// Double shift instructions (generalizations of rotate) +let Uses = [CL] in { +def SHLD32rrCL : I<0xA5, MRMDestReg, (outs GR32:$dst), (ins GR32:$src1, GR32:$src2), + "shld{l}\t{%cl, $src2, $dst|$dst, $src2, CL}", + [(set GR32:$dst, (X86shld GR32:$src1, GR32:$src2, CL))]>, TB; +def SHRD32rrCL : I<0xAD, MRMDestReg, (outs GR32:$dst), (ins GR32:$src1, GR32:$src2), + "shrd{l}\t{%cl, $src2, $dst|$dst, $src2, CL}", + [(set GR32:$dst, (X86shrd GR32:$src1, GR32:$src2, CL))]>, TB; +def SHLD16rrCL : I<0xA5, MRMDestReg, (outs GR16:$dst), (ins GR16:$src1, GR16:$src2), + "shld{w}\t{%cl, $src2, $dst|$dst, $src2, CL}", + [(set GR16:$dst, (X86shld GR16:$src1, GR16:$src2, CL))]>, + TB, OpSize; +def SHRD16rrCL : I<0xAD, MRMDestReg, (outs GR16:$dst), (ins GR16:$src1, GR16:$src2), + "shrd{w}\t{%cl, $src2, $dst|$dst, $src2, CL}", + [(set GR16:$dst, (X86shrd GR16:$src1, GR16:$src2, CL))]>, + TB, OpSize; +} + +let isCommutable = 1 in { // These instructions commute to each other. +def SHLD32rri8 : Ii8<0xA4, MRMDestReg, + (outs GR32:$dst), (ins GR32:$src1, GR32:$src2, i8imm:$src3), + "shld{l}\t{$src3, $src2, $dst|$dst, $src2, $src3}", + [(set GR32:$dst, (X86shld GR32:$src1, GR32:$src2, + (i8 imm:$src3)))]>, + TB; +def SHRD32rri8 : Ii8<0xAC, MRMDestReg, + (outs GR32:$dst), (ins GR32:$src1, GR32:$src2, i8imm:$src3), + "shrd{l}\t{$src3, $src2, $dst|$dst, $src2, $src3}", + [(set GR32:$dst, (X86shrd GR32:$src1, GR32:$src2, + (i8 imm:$src3)))]>, + TB; +def SHLD16rri8 : Ii8<0xA4, MRMDestReg, + (outs GR16:$dst), (ins GR16:$src1, GR16:$src2, i8imm:$src3), + "shld{w}\t{$src3, $src2, $dst|$dst, $src2, $src3}", + [(set GR16:$dst, (X86shld GR16:$src1, GR16:$src2, + (i8 imm:$src3)))]>, + TB, OpSize; +def SHRD16rri8 : Ii8<0xAC, MRMDestReg, + (outs GR16:$dst), (ins GR16:$src1, GR16:$src2, i8imm:$src3), + "shrd{w}\t{$src3, $src2, $dst|$dst, $src2, $src3}", + [(set GR16:$dst, (X86shrd GR16:$src1, GR16:$src2, + (i8 imm:$src3)))]>, + TB, OpSize; +} + +let isTwoAddress = 0 in { + let Uses = [CL] in { + def SHLD32mrCL : I<0xA5, MRMDestMem, (outs), (ins i32mem:$dst, GR32:$src2), + "shld{l}\t{%cl, $src2, $dst|$dst, $src2, CL}", + [(store (X86shld (loadi32 addr:$dst), GR32:$src2, CL), + addr:$dst)]>, TB; + def SHRD32mrCL : I<0xAD, MRMDestMem, (outs), (ins i32mem:$dst, GR32:$src2), + "shrd{l}\t{%cl, $src2, $dst|$dst, $src2, CL}", + [(store (X86shrd (loadi32 addr:$dst), GR32:$src2, CL), + addr:$dst)]>, TB; + } + def SHLD32mri8 : Ii8<0xA4, MRMDestMem, + (outs), (ins i32mem:$dst, GR32:$src2, i8imm:$src3), + "shld{l}\t{$src3, $src2, $dst|$dst, $src2, $src3}", + [(store (X86shld (loadi32 addr:$dst), GR32:$src2, + (i8 imm:$src3)), addr:$dst)]>, + TB; + def SHRD32mri8 : Ii8<0xAC, MRMDestMem, + (outs), (ins i32mem:$dst, GR32:$src2, i8imm:$src3), + "shrd{l}\t{$src3, $src2, $dst|$dst, $src2, $src3}", + [(store (X86shrd (loadi32 addr:$dst), GR32:$src2, + (i8 imm:$src3)), addr:$dst)]>, + TB; + + let Uses = [CL] in { + def SHLD16mrCL : I<0xA5, MRMDestMem, (outs), (ins i16mem:$dst, GR16:$src2), + "shld{w}\t{%cl, $src2, $dst|$dst, $src2, CL}", + [(store (X86shld (loadi16 addr:$dst), GR16:$src2, CL), + addr:$dst)]>, TB, OpSize; + def SHRD16mrCL : I<0xAD, MRMDestMem, (outs), (ins i16mem:$dst, GR16:$src2), + "shrd{w}\t{%cl, $src2, $dst|$dst, $src2, CL}", + [(store (X86shrd (loadi16 addr:$dst), GR16:$src2, CL), + addr:$dst)]>, TB, OpSize; + } + def SHLD16mri8 : Ii8<0xA4, MRMDestMem, + (outs), (ins i16mem:$dst, GR16:$src2, i8imm:$src3), + "shld{w}\t{$src3, $src2, $dst|$dst, $src2, $src3}", + [(store (X86shld (loadi16 addr:$dst), GR16:$src2, + (i8 imm:$src3)), addr:$dst)]>, + TB, OpSize; + def SHRD16mri8 : Ii8<0xAC, MRMDestMem, + (outs), (ins i16mem:$dst, GR16:$src2, i8imm:$src3), + "shrd{w}\t{$src3, $src2, $dst|$dst, $src2, $src3}", + [(store (X86shrd (loadi16 addr:$dst), GR16:$src2, + (i8 imm:$src3)), addr:$dst)]>, + TB, OpSize; +} +} // Defs = [EFLAGS] + + +// Arithmetic. +let Defs = [EFLAGS] in { +let isCommutable = 1 in { // X = ADD Y, Z --> X = ADD Z, Y +// Register-Register Addition +def ADD8rr : I<0x00, MRMDestReg, (outs GR8 :$dst), + (ins GR8 :$src1, GR8 :$src2), + "add{b}\t{$src2, $dst|$dst, $src2}", + [(set GR8:$dst, (add GR8:$src1, GR8:$src2)), + (implicit EFLAGS)]>; + +let isConvertibleToThreeAddress = 1 in { // Can transform into LEA. +// Register-Register Addition +def ADD16rr : I<0x01, MRMDestReg, (outs GR16:$dst), + (ins GR16:$src1, GR16:$src2), + "add{w}\t{$src2, $dst|$dst, $src2}", + [(set GR16:$dst, (add GR16:$src1, GR16:$src2)), + (implicit EFLAGS)]>, OpSize; +def ADD32rr : I<0x01, MRMDestReg, (outs GR32:$dst), + (ins GR32:$src1, GR32:$src2), + "add{l}\t{$src2, $dst|$dst, $src2}", + [(set GR32:$dst, (add GR32:$src1, GR32:$src2)), + (implicit EFLAGS)]>; +} // end isConvertibleToThreeAddress +} // end isCommutable + +// Register-Memory Addition +def ADD8rm : I<0x02, MRMSrcMem, (outs GR8 :$dst), + (ins GR8 :$src1, i8mem :$src2), + "add{b}\t{$src2, $dst|$dst, $src2}", + [(set GR8:$dst, (add GR8:$src1, (load addr:$src2))), + (implicit EFLAGS)]>; +def ADD16rm : I<0x03, MRMSrcMem, (outs GR16:$dst), + (ins GR16:$src1, i16mem:$src2), + "add{w}\t{$src2, $dst|$dst, $src2}", + [(set GR16:$dst, (add GR16:$src1, (load addr:$src2))), + (implicit EFLAGS)]>, OpSize; +def ADD32rm : I<0x03, MRMSrcMem, (outs GR32:$dst), + (ins GR32:$src1, i32mem:$src2), + "add{l}\t{$src2, $dst|$dst, $src2}", + [(set GR32:$dst, (add GR32:$src1, (load addr:$src2))), + (implicit EFLAGS)]>; + +// Register-Register Addition - Equivalent to the normal rr forms (ADD8rr, +// ADD16rr, and ADD32rr), but differently encoded. +def ADD8mrmrr: I<0x02, MRMSrcReg, (outs GR8:$dst), (ins GR8:$src1, GR8:$src2), + "add{b}\t{$src2, $dst|$dst, $src2}", []>; +def ADD16mrmrr: I<0x03, MRMSrcReg,(outs GR16:$dst),(ins GR16:$src1, GR16:$src2), + "add{w}\t{$src2, $dst|$dst, $src2}", []>, OpSize; +def ADD32mrmrr: I<0x03, MRMSrcReg,(outs GR16:$dst),(ins GR16:$src1, GR16:$src2), + "add{l}\t{$src2, $dst|$dst, $src2}", []>; + +// Register-Integer Addition +def ADD8ri : Ii8<0x80, MRM0r, (outs GR8:$dst), (ins GR8:$src1, i8imm:$src2), + "add{b}\t{$src2, $dst|$dst, $src2}", + [(set GR8:$dst, (add GR8:$src1, imm:$src2)), + (implicit EFLAGS)]>; + +let isConvertibleToThreeAddress = 1 in { // Can transform into LEA. +// Register-Integer Addition +def ADD16ri : Ii16<0x81, MRM0r, (outs GR16:$dst), + (ins GR16:$src1, i16imm:$src2), + "add{w}\t{$src2, $dst|$dst, $src2}", + [(set GR16:$dst, (add GR16:$src1, imm:$src2)), + (implicit EFLAGS)]>, OpSize; +def ADD32ri : Ii32<0x81, MRM0r, (outs GR32:$dst), + (ins GR32:$src1, i32imm:$src2), + "add{l}\t{$src2, $dst|$dst, $src2}", + [(set GR32:$dst, (add GR32:$src1, imm:$src2)), + (implicit EFLAGS)]>; +def ADD16ri8 : Ii8<0x83, MRM0r, (outs GR16:$dst), + (ins GR16:$src1, i16i8imm:$src2), + "add{w}\t{$src2, $dst|$dst, $src2}", + [(set GR16:$dst, (add GR16:$src1, i16immSExt8:$src2)), + (implicit EFLAGS)]>, OpSize; +def ADD32ri8 : Ii8<0x83, MRM0r, (outs GR32:$dst), + (ins GR32:$src1, i32i8imm:$src2), + "add{l}\t{$src2, $dst|$dst, $src2}", + [(set GR32:$dst, (add GR32:$src1, i32immSExt8:$src2)), + (implicit EFLAGS)]>; +} + +let isTwoAddress = 0 in { + // Memory-Register Addition + def ADD8mr : I<0x00, MRMDestMem, (outs), (ins i8mem:$dst, GR8:$src2), + "add{b}\t{$src2, $dst|$dst, $src2}", + [(store (add (load addr:$dst), GR8:$src2), addr:$dst), + (implicit EFLAGS)]>; + def ADD16mr : I<0x01, MRMDestMem, (outs), (ins i16mem:$dst, GR16:$src2), + "add{w}\t{$src2, $dst|$dst, $src2}", + [(store (add (load addr:$dst), GR16:$src2), addr:$dst), + (implicit EFLAGS)]>, OpSize; + def ADD32mr : I<0x01, MRMDestMem, (outs), (ins i32mem:$dst, GR32:$src2), + "add{l}\t{$src2, $dst|$dst, $src2}", + [(store (add (load addr:$dst), GR32:$src2), addr:$dst), + (implicit EFLAGS)]>; + def ADD8mi : Ii8<0x80, MRM0m, (outs), (ins i8mem :$dst, i8imm :$src2), + "add{b}\t{$src2, $dst|$dst, $src2}", + [(store (add (loadi8 addr:$dst), imm:$src2), addr:$dst), + (implicit EFLAGS)]>; + def ADD16mi : Ii16<0x81, MRM0m, (outs), (ins i16mem:$dst, i16imm:$src2), + "add{w}\t{$src2, $dst|$dst, $src2}", + [(store (add (loadi16 addr:$dst), imm:$src2), addr:$dst), + (implicit EFLAGS)]>, OpSize; + def ADD32mi : Ii32<0x81, MRM0m, (outs), (ins i32mem:$dst, i32imm:$src2), + "add{l}\t{$src2, $dst|$dst, $src2}", + [(store (add (loadi32 addr:$dst), imm:$src2), addr:$dst), + (implicit EFLAGS)]>; + def ADD16mi8 : Ii8<0x83, MRM0m, (outs), (ins i16mem:$dst, i16i8imm :$src2), + "add{w}\t{$src2, $dst|$dst, $src2}", + [(store (add (load addr:$dst), i16immSExt8:$src2), + addr:$dst), + (implicit EFLAGS)]>, OpSize; + def ADD32mi8 : Ii8<0x83, MRM0m, (outs), (ins i32mem:$dst, i32i8imm :$src2), + "add{l}\t{$src2, $dst|$dst, $src2}", + [(store (add (load addr:$dst), i32immSExt8:$src2), + addr:$dst), + (implicit EFLAGS)]>; + + // addition to rAX + def ADD8i8 : Ii8<0x04, RawFrm, (outs), (ins i8imm:$src), + "add{b}\t{$src, %al|%al, $src}", []>; + def ADD16i16 : Ii16<0x05, RawFrm, (outs), (ins i16imm:$src), + "add{w}\t{$src, %ax|%ax, $src}", []>, OpSize; + def ADD32i32 : Ii32<0x05, RawFrm, (outs), (ins i32imm:$src), + "add{l}\t{$src, %eax|%eax, $src}", []>; +} + +let Uses = [EFLAGS] in { +let isCommutable = 1 in { // X = ADC Y, Z --> X = ADC Z, Y +def ADC8rr : I<0x10, MRMDestReg, (outs GR8:$dst), (ins GR8:$src1, GR8:$src2), + "adc{b}\t{$src2, $dst|$dst, $src2}", + [(set GR8:$dst, (adde GR8:$src1, GR8:$src2))]>; +def ADC16rr : I<0x11, MRMDestReg, (outs GR16:$dst), + (ins GR16:$src1, GR16:$src2), + "adc{w}\t{$src2, $dst|$dst, $src2}", + [(set GR16:$dst, (adde GR16:$src1, GR16:$src2))]>, OpSize; +def ADC32rr : I<0x11, MRMDestReg, (outs GR32:$dst), + (ins GR32:$src1, GR32:$src2), + "adc{l}\t{$src2, $dst|$dst, $src2}", + [(set GR32:$dst, (adde GR32:$src1, GR32:$src2))]>; +} +def ADC8rm : I<0x12, MRMSrcMem , (outs GR8:$dst), + (ins GR8:$src1, i8mem:$src2), + "adc{b}\t{$src2, $dst|$dst, $src2}", + [(set GR8:$dst, (adde GR8:$src1, (load addr:$src2)))]>; +def ADC16rm : I<0x13, MRMSrcMem , (outs GR16:$dst), + (ins GR16:$src1, i16mem:$src2), + "adc{w}\t{$src2, $dst|$dst, $src2}", + [(set GR16:$dst, (adde GR16:$src1, (load addr:$src2)))]>, + OpSize; +def ADC32rm : I<0x13, MRMSrcMem , (outs GR32:$dst), + (ins GR32:$src1, i32mem:$src2), + "adc{l}\t{$src2, $dst|$dst, $src2}", + [(set GR32:$dst, (adde GR32:$src1, (load addr:$src2)))]>; +def ADC8ri : Ii8<0x80, MRM2r, (outs GR8:$dst), (ins GR8:$src1, i8imm:$src2), + "adc{b}\t{$src2, $dst|$dst, $src2}", + [(set GR8:$dst, (adde GR8:$src1, imm:$src2))]>; +def ADC16ri : Ii16<0x81, MRM2r, (outs GR16:$dst), + (ins GR16:$src1, i16imm:$src2), + "adc{w}\t{$src2, $dst|$dst, $src2}", + [(set GR16:$dst, (adde GR16:$src1, imm:$src2))]>, OpSize; +def ADC16ri8 : Ii8<0x83, MRM2r, (outs GR16:$dst), + (ins GR16:$src1, i16i8imm:$src2), + "adc{w}\t{$src2, $dst|$dst, $src2}", + [(set GR16:$dst, (adde GR16:$src1, i16immSExt8:$src2))]>, + OpSize; +def ADC32ri : Ii32<0x81, MRM2r, (outs GR32:$dst), + (ins GR32:$src1, i32imm:$src2), + "adc{l}\t{$src2, $dst|$dst, $src2}", + [(set GR32:$dst, (adde GR32:$src1, imm:$src2))]>; +def ADC32ri8 : Ii8<0x83, MRM2r, (outs GR32:$dst), + (ins GR32:$src1, i32i8imm:$src2), + "adc{l}\t{$src2, $dst|$dst, $src2}", + [(set GR32:$dst, (adde GR32:$src1, i32immSExt8:$src2))]>; + +let isTwoAddress = 0 in { + def ADC8mr : I<0x10, MRMDestMem, (outs), (ins i8mem:$dst, GR8:$src2), + "adc{b}\t{$src2, $dst|$dst, $src2}", + [(store (adde (load addr:$dst), GR8:$src2), addr:$dst)]>; + def ADC16mr : I<0x11, MRMDestMem, (outs), (ins i16mem:$dst, GR16:$src2), + "adc{w}\t{$src2, $dst|$dst, $src2}", + [(store (adde (load addr:$dst), GR16:$src2), addr:$dst)]>, + OpSize; + def ADC32mr : I<0x11, MRMDestMem, (outs), (ins i32mem:$dst, GR32:$src2), + "adc{l}\t{$src2, $dst|$dst, $src2}", + [(store (adde (load addr:$dst), GR32:$src2), addr:$dst)]>; + def ADC8mi : Ii8<0x80, MRM2m, (outs), (ins i8mem:$dst, i8imm:$src2), + "adc{b}\t{$src2, $dst|$dst, $src2}", + [(store (adde (loadi8 addr:$dst), imm:$src2), addr:$dst)]>; + def ADC16mi : Ii16<0x81, MRM2m, (outs), (ins i16mem:$dst, i16imm:$src2), + "adc{w}\t{$src2, $dst|$dst, $src2}", + [(store (adde (loadi16 addr:$dst), imm:$src2), addr:$dst)]>, + OpSize; + def ADC16mi8 : Ii8<0x83, MRM2m, (outs), (ins i16mem:$dst, i16i8imm :$src2), + "adc{w}\t{$src2, $dst|$dst, $src2}", + [(store (adde (load addr:$dst), i16immSExt8:$src2), addr:$dst)]>, + OpSize; + def ADC32mi : Ii32<0x81, MRM2m, (outs), (ins i32mem:$dst, i32imm:$src2), + "adc{l}\t{$src2, $dst|$dst, $src2}", + [(store (adde (loadi32 addr:$dst), imm:$src2), addr:$dst)]>; + def ADC32mi8 : Ii8<0x83, MRM2m, (outs), (ins i32mem:$dst, i32i8imm :$src2), + "adc{l}\t{$src2, $dst|$dst, $src2}", + [(store (adde (load addr:$dst), i32immSExt8:$src2), addr:$dst)]>; + + def ADC8i8 : Ii8<0x14, RawFrm, (outs), (ins i8imm:$src), + "adc{b}\t{$src, %al|%al, $src}", []>; + def ADC16i16 : Ii16<0x15, RawFrm, (outs), (ins i16imm:$src), + "adc{w}\t{$src, %ax|%ax, $src}", []>, OpSize; + def ADC32i32 : Ii32<0x15, RawFrm, (outs), (ins i32imm:$src), + "adc{l}\t{$src, %eax|%eax, $src}", []>; +} +} // Uses = [EFLAGS] + +// Register-Register Subtraction +def SUB8rr : I<0x28, MRMDestReg, (outs GR8:$dst), (ins GR8:$src1, GR8:$src2), + "sub{b}\t{$src2, $dst|$dst, $src2}", + [(set GR8:$dst, (sub GR8:$src1, GR8:$src2)), + (implicit EFLAGS)]>; +def SUB16rr : I<0x29, MRMDestReg, (outs GR16:$dst), (ins GR16:$src1,GR16:$src2), + "sub{w}\t{$src2, $dst|$dst, $src2}", + [(set GR16:$dst, (sub GR16:$src1, GR16:$src2)), + (implicit EFLAGS)]>, OpSize; +def SUB32rr : I<0x29, MRMDestReg, (outs GR32:$dst), (ins GR32:$src1,GR32:$src2), + "sub{l}\t{$src2, $dst|$dst, $src2}", + [(set GR32:$dst, (sub GR32:$src1, GR32:$src2)), + (implicit EFLAGS)]>; + +// Register-Memory Subtraction +def SUB8rm : I<0x2A, MRMSrcMem, (outs GR8 :$dst), + (ins GR8 :$src1, i8mem :$src2), + "sub{b}\t{$src2, $dst|$dst, $src2}", + [(set GR8:$dst, (sub GR8:$src1, (load addr:$src2))), + (implicit EFLAGS)]>; +def SUB16rm : I<0x2B, MRMSrcMem, (outs GR16:$dst), + (ins GR16:$src1, i16mem:$src2), + "sub{w}\t{$src2, $dst|$dst, $src2}", + [(set GR16:$dst, (sub GR16:$src1, (load addr:$src2))), + (implicit EFLAGS)]>, OpSize; +def SUB32rm : I<0x2B, MRMSrcMem, (outs GR32:$dst), + (ins GR32:$src1, i32mem:$src2), + "sub{l}\t{$src2, $dst|$dst, $src2}", + [(set GR32:$dst, (sub GR32:$src1, (load addr:$src2))), + (implicit EFLAGS)]>; + +// Register-Integer Subtraction +def SUB8ri : Ii8 <0x80, MRM5r, (outs GR8:$dst), + (ins GR8:$src1, i8imm:$src2), + "sub{b}\t{$src2, $dst|$dst, $src2}", + [(set GR8:$dst, (sub GR8:$src1, imm:$src2)), + (implicit EFLAGS)]>; +def SUB16ri : Ii16<0x81, MRM5r, (outs GR16:$dst), + (ins GR16:$src1, i16imm:$src2), + "sub{w}\t{$src2, $dst|$dst, $src2}", + [(set GR16:$dst, (sub GR16:$src1, imm:$src2)), + (implicit EFLAGS)]>, OpSize; +def SUB32ri : Ii32<0x81, MRM5r, (outs GR32:$dst), + (ins GR32:$src1, i32imm:$src2), + "sub{l}\t{$src2, $dst|$dst, $src2}", + [(set GR32:$dst, (sub GR32:$src1, imm:$src2)), + (implicit EFLAGS)]>; +def SUB16ri8 : Ii8<0x83, MRM5r, (outs GR16:$dst), + (ins GR16:$src1, i16i8imm:$src2), + "sub{w}\t{$src2, $dst|$dst, $src2}", + [(set GR16:$dst, (sub GR16:$src1, i16immSExt8:$src2)), + (implicit EFLAGS)]>, OpSize; +def SUB32ri8 : Ii8<0x83, MRM5r, (outs GR32:$dst), + (ins GR32:$src1, i32i8imm:$src2), + "sub{l}\t{$src2, $dst|$dst, $src2}", + [(set GR32:$dst, (sub GR32:$src1, i32immSExt8:$src2)), + (implicit EFLAGS)]>; + +let isTwoAddress = 0 in { + // Memory-Register Subtraction + def SUB8mr : I<0x28, MRMDestMem, (outs), (ins i8mem :$dst, GR8 :$src2), + "sub{b}\t{$src2, $dst|$dst, $src2}", + [(store (sub (load addr:$dst), GR8:$src2), addr:$dst), + (implicit EFLAGS)]>; + def SUB16mr : I<0x29, MRMDestMem, (outs), (ins i16mem:$dst, GR16:$src2), + "sub{w}\t{$src2, $dst|$dst, $src2}", + [(store (sub (load addr:$dst), GR16:$src2), addr:$dst), + (implicit EFLAGS)]>, OpSize; + def SUB32mr : I<0x29, MRMDestMem, (outs), (ins i32mem:$dst, GR32:$src2), + "sub{l}\t{$src2, $dst|$dst, $src2}", + [(store (sub (load addr:$dst), GR32:$src2), addr:$dst), + (implicit EFLAGS)]>; + + // Memory-Integer Subtraction + def SUB8mi : Ii8<0x80, MRM5m, (outs), (ins i8mem :$dst, i8imm:$src2), + "sub{b}\t{$src2, $dst|$dst, $src2}", + [(store (sub (loadi8 addr:$dst), imm:$src2), addr:$dst), + (implicit EFLAGS)]>; + def SUB16mi : Ii16<0x81, MRM5m, (outs), (ins i16mem:$dst, i16imm:$src2), + "sub{w}\t{$src2, $dst|$dst, $src2}", + [(store (sub (loadi16 addr:$dst), imm:$src2),addr:$dst), + (implicit EFLAGS)]>, OpSize; + def SUB32mi : Ii32<0x81, MRM5m, (outs), (ins i32mem:$dst, i32imm:$src2), + "sub{l}\t{$src2, $dst|$dst, $src2}", + [(store (sub (loadi32 addr:$dst), imm:$src2),addr:$dst), + (implicit EFLAGS)]>; + def SUB16mi8 : Ii8<0x83, MRM5m, (outs), (ins i16mem:$dst, i16i8imm :$src2), + "sub{w}\t{$src2, $dst|$dst, $src2}", + [(store (sub (load addr:$dst), i16immSExt8:$src2), + addr:$dst), + (implicit EFLAGS)]>, OpSize; + def SUB32mi8 : Ii8<0x83, MRM5m, (outs), (ins i32mem:$dst, i32i8imm :$src2), + "sub{l}\t{$src2, $dst|$dst, $src2}", + [(store (sub (load addr:$dst), i32immSExt8:$src2), + addr:$dst), + (implicit EFLAGS)]>; + + def SUB8i8 : Ii8<0x2C, RawFrm, (outs), (ins i8imm:$src), + "sub{b}\t{$src, %al|%al, $src}", []>; + def SUB16i16 : Ii16<0x2D, RawFrm, (outs), (ins i16imm:$src), + "sub{w}\t{$src, %ax|%ax, $src}", []>, OpSize; + def SUB32i32 : Ii32<0x2D, RawFrm, (outs), (ins i32imm:$src), + "sub{l}\t{$src, %eax|%eax, $src}", []>; +} + +let Uses = [EFLAGS] in { +def SBB8rr : I<0x18, MRMDestReg, (outs GR8:$dst), + (ins GR8:$src1, GR8:$src2), + "sbb{b}\t{$src2, $dst|$dst, $src2}", + [(set GR8:$dst, (sube GR8:$src1, GR8:$src2))]>; +def SBB16rr : I<0x19, MRMDestReg, (outs GR16:$dst), + (ins GR16:$src1, GR16:$src2), + "sbb{w}\t{$src2, $dst|$dst, $src2}", + [(set GR16:$dst, (sube GR16:$src1, GR16:$src2))]>, OpSize; +def SBB32rr : I<0x19, MRMDestReg, (outs GR32:$dst), + (ins GR32:$src1, GR32:$src2), + "sbb{l}\t{$src2, $dst|$dst, $src2}", + [(set GR32:$dst, (sube GR32:$src1, GR32:$src2))]>; + +let isTwoAddress = 0 in { + def SBB8mr : I<0x18, MRMDestMem, (outs), (ins i8mem:$dst, GR8:$src2), + "sbb{b}\t{$src2, $dst|$dst, $src2}", + [(store (sube (load addr:$dst), GR8:$src2), addr:$dst)]>; + def SBB16mr : I<0x19, MRMDestMem, (outs), (ins i16mem:$dst, GR16:$src2), + "sbb{w}\t{$src2, $dst|$dst, $src2}", + [(store (sube (load addr:$dst), GR16:$src2), addr:$dst)]>, + OpSize; + def SBB32mr : I<0x19, MRMDestMem, (outs), (ins i32mem:$dst, GR32:$src2), + "sbb{l}\t{$src2, $dst|$dst, $src2}", + [(store (sube (load addr:$dst), GR32:$src2), addr:$dst)]>; + def SBB8mi : Ii32<0x80, MRM3m, (outs), (ins i8mem:$dst, i8imm:$src2), + "sbb{b}\t{$src2, $dst|$dst, $src2}", + [(store (sube (loadi8 addr:$dst), imm:$src2), addr:$dst)]>; + def SBB16mi : Ii16<0x81, MRM3m, (outs), (ins i16mem:$dst, i16imm:$src2), + "sbb{w}\t{$src2, $dst|$dst, $src2}", + [(store (sube (loadi16 addr:$dst), imm:$src2), addr:$dst)]>, + OpSize; + def SBB16mi8 : Ii8<0x83, MRM3m, (outs), (ins i16mem:$dst, i16i8imm :$src2), + "sbb{w}\t{$src2, $dst|$dst, $src2}", + [(store (sube (load addr:$dst), i16immSExt8:$src2), addr:$dst)]>, + OpSize; + def SBB32mi : Ii32<0x81, MRM3m, (outs), (ins i32mem:$dst, i32imm:$src2), + "sbb{l}\t{$src2, $dst|$dst, $src2}", + [(store (sube (loadi32 addr:$dst), imm:$src2), addr:$dst)]>; + def SBB32mi8 : Ii8<0x83, MRM3m, (outs), (ins i32mem:$dst, i32i8imm :$src2), + "sbb{l}\t{$src2, $dst|$dst, $src2}", + [(store (sube (load addr:$dst), i32immSExt8:$src2), addr:$dst)]>; + + def SBB8i8 : Ii8<0x1C, RawFrm, (outs), (ins i8imm:$src), + "sbb{b}\t{$src, %al|%al, $src}", []>; + def SBB16i16 : Ii16<0x1D, RawFrm, (outs), (ins i16imm:$src), + "sbb{w}\t{$src, %ax|%ax, $src}", []>, OpSize; + def SBB32i32 : Ii32<0x1D, RawFrm, (outs), (ins i32imm:$src), + "sbb{l}\t{$src, %eax|%eax, $src}", []>; +} +def SBB8rm : I<0x1A, MRMSrcMem, (outs GR8:$dst), (ins GR8:$src1, i8mem:$src2), + "sbb{b}\t{$src2, $dst|$dst, $src2}", + [(set GR8:$dst, (sube GR8:$src1, (load addr:$src2)))]>; +def SBB16rm : I<0x1B, MRMSrcMem, (outs GR16:$dst), + (ins GR16:$src1, i16mem:$src2), + "sbb{w}\t{$src2, $dst|$dst, $src2}", + [(set GR16:$dst, (sube GR16:$src1, (load addr:$src2)))]>, + OpSize; +def SBB32rm : I<0x1B, MRMSrcMem, (outs GR32:$dst), + (ins GR32:$src1, i32mem:$src2), + "sbb{l}\t{$src2, $dst|$dst, $src2}", + [(set GR32:$dst, (sube GR32:$src1, (load addr:$src2)))]>; +def SBB8ri : Ii8<0x80, MRM3r, (outs GR8:$dst), (ins GR8:$src1, i8imm:$src2), + "sbb{b}\t{$src2, $dst|$dst, $src2}", + [(set GR8:$dst, (sube GR8:$src1, imm:$src2))]>; +def SBB16ri : Ii16<0x81, MRM3r, (outs GR16:$dst), + (ins GR16:$src1, i16imm:$src2), + "sbb{w}\t{$src2, $dst|$dst, $src2}", + [(set GR16:$dst, (sube GR16:$src1, imm:$src2))]>, OpSize; +def SBB16ri8 : Ii8<0x83, MRM3r, (outs GR16:$dst), + (ins GR16:$src1, i16i8imm:$src2), + "sbb{w}\t{$src2, $dst|$dst, $src2}", + [(set GR16:$dst, (sube GR16:$src1, i16immSExt8:$src2))]>, + OpSize; +def SBB32ri : Ii32<0x81, MRM3r, (outs GR32:$dst), + (ins GR32:$src1, i32imm:$src2), + "sbb{l}\t{$src2, $dst|$dst, $src2}", + [(set GR32:$dst, (sube GR32:$src1, imm:$src2))]>; +def SBB32ri8 : Ii8<0x83, MRM3r, (outs GR32:$dst), + (ins GR32:$src1, i32i8imm:$src2), + "sbb{l}\t{$src2, $dst|$dst, $src2}", + [(set GR32:$dst, (sube GR32:$src1, i32immSExt8:$src2))]>; +} // Uses = [EFLAGS] +} // Defs = [EFLAGS] + +let Defs = [EFLAGS] in { +let isCommutable = 1 in { // X = IMUL Y, Z --> X = IMUL Z, Y +// Register-Register Signed Integer Multiply +def IMUL16rr : I<0xAF, MRMSrcReg, (outs GR16:$dst), (ins GR16:$src1,GR16:$src2), + "imul{w}\t{$src2, $dst|$dst, $src2}", + [(set GR16:$dst, (mul GR16:$src1, GR16:$src2)), + (implicit EFLAGS)]>, TB, OpSize; +def IMUL32rr : I<0xAF, MRMSrcReg, (outs GR32:$dst), (ins GR32:$src1,GR32:$src2), + "imul{l}\t{$src2, $dst|$dst, $src2}", + [(set GR32:$dst, (mul GR32:$src1, GR32:$src2)), + (implicit EFLAGS)]>, TB; +} + +// Register-Memory Signed Integer Multiply +def IMUL16rm : I<0xAF, MRMSrcMem, (outs GR16:$dst), + (ins GR16:$src1, i16mem:$src2), + "imul{w}\t{$src2, $dst|$dst, $src2}", + [(set GR16:$dst, (mul GR16:$src1, (load addr:$src2))), + (implicit EFLAGS)]>, TB, OpSize; +def IMUL32rm : I<0xAF, MRMSrcMem, (outs GR32:$dst), (ins GR32:$src1, i32mem:$src2), + "imul{l}\t{$src2, $dst|$dst, $src2}", + [(set GR32:$dst, (mul GR32:$src1, (load addr:$src2))), + (implicit EFLAGS)]>, TB; +} // Defs = [EFLAGS] +} // end Two Address instructions + +// Suprisingly enough, these are not two address instructions! +let Defs = [EFLAGS] in { +// Register-Integer Signed Integer Multiply +def IMUL16rri : Ii16<0x69, MRMSrcReg, // GR16 = GR16*I16 + (outs GR16:$dst), (ins GR16:$src1, i16imm:$src2), + "imul{w}\t{$src2, $src1, $dst|$dst, $src1, $src2}", + [(set GR16:$dst, (mul GR16:$src1, imm:$src2)), + (implicit EFLAGS)]>, OpSize; +def IMUL32rri : Ii32<0x69, MRMSrcReg, // GR32 = GR32*I32 + (outs GR32:$dst), (ins GR32:$src1, i32imm:$src2), + "imul{l}\t{$src2, $src1, $dst|$dst, $src1, $src2}", + [(set GR32:$dst, (mul GR32:$src1, imm:$src2)), + (implicit EFLAGS)]>; +def IMUL16rri8 : Ii8<0x6B, MRMSrcReg, // GR16 = GR16*I8 + (outs GR16:$dst), (ins GR16:$src1, i16i8imm:$src2), + "imul{w}\t{$src2, $src1, $dst|$dst, $src1, $src2}", + [(set GR16:$dst, (mul GR16:$src1, i16immSExt8:$src2)), + (implicit EFLAGS)]>, OpSize; +def IMUL32rri8 : Ii8<0x6B, MRMSrcReg, // GR32 = GR32*I8 + (outs GR32:$dst), (ins GR32:$src1, i32i8imm:$src2), + "imul{l}\t{$src2, $src1, $dst|$dst, $src1, $src2}", + [(set GR32:$dst, (mul GR32:$src1, i32immSExt8:$src2)), + (implicit EFLAGS)]>; + +// Memory-Integer Signed Integer Multiply +def IMUL16rmi : Ii16<0x69, MRMSrcMem, // GR16 = [mem16]*I16 + (outs GR16:$dst), (ins i16mem:$src1, i16imm:$src2), + "imul{w}\t{$src2, $src1, $dst|$dst, $src1, $src2}", + [(set GR16:$dst, (mul (load addr:$src1), imm:$src2)), + (implicit EFLAGS)]>, OpSize; +def IMUL32rmi : Ii32<0x69, MRMSrcMem, // GR32 = [mem32]*I32 + (outs GR32:$dst), (ins i32mem:$src1, i32imm:$src2), + "imul{l}\t{$src2, $src1, $dst|$dst, $src1, $src2}", + [(set GR32:$dst, (mul (load addr:$src1), imm:$src2)), + (implicit EFLAGS)]>; +def IMUL16rmi8 : Ii8<0x6B, MRMSrcMem, // GR16 = [mem16]*I8 + (outs GR16:$dst), (ins i16mem:$src1, i16i8imm :$src2), + "imul{w}\t{$src2, $src1, $dst|$dst, $src1, $src2}", + [(set GR16:$dst, (mul (load addr:$src1), + i16immSExt8:$src2)), + (implicit EFLAGS)]>, OpSize; +def IMUL32rmi8 : Ii8<0x6B, MRMSrcMem, // GR32 = [mem32]*I8 + (outs GR32:$dst), (ins i32mem:$src1, i32i8imm: $src2), + "imul{l}\t{$src2, $src1, $dst|$dst, $src1, $src2}", + [(set GR32:$dst, (mul (load addr:$src1), + i32immSExt8:$src2)), + (implicit EFLAGS)]>; +} // Defs = [EFLAGS] + +//===----------------------------------------------------------------------===// +// Test instructions are just like AND, except they don't generate a result. +// +let Defs = [EFLAGS] in { +let isCommutable = 1 in { // TEST X, Y --> TEST Y, X +def TEST8rr : I<0x84, MRMDestReg, (outs), (ins GR8:$src1, GR8:$src2), + "test{b}\t{$src2, $src1|$src1, $src2}", + [(X86cmp (and_su GR8:$src1, GR8:$src2), 0), + (implicit EFLAGS)]>; +def TEST16rr : I<0x85, MRMDestReg, (outs), (ins GR16:$src1, GR16:$src2), + "test{w}\t{$src2, $src1|$src1, $src2}", + [(X86cmp (and_su GR16:$src1, GR16:$src2), 0), + (implicit EFLAGS)]>, + OpSize; +def TEST32rr : I<0x85, MRMDestReg, (outs), (ins GR32:$src1, GR32:$src2), + "test{l}\t{$src2, $src1|$src1, $src2}", + [(X86cmp (and_su GR32:$src1, GR32:$src2), 0), + (implicit EFLAGS)]>; +} + +def TEST8i8 : Ii8<0xA8, RawFrm, (outs), (ins i8imm:$src), + "test{b}\t{$src, %al|%al, $src}", []>; +def TEST16i16 : Ii16<0xA9, RawFrm, (outs), (ins i16imm:$src), + "test{w}\t{$src, %ax|%ax, $src}", []>, OpSize; +def TEST32i32 : Ii32<0xA9, RawFrm, (outs), (ins i32imm:$src), + "test{l}\t{$src, %eax|%eax, $src}", []>; + +def TEST8rm : I<0x84, MRMSrcMem, (outs), (ins GR8 :$src1, i8mem :$src2), + "test{b}\t{$src2, $src1|$src1, $src2}", + [(X86cmp (and GR8:$src1, (loadi8 addr:$src2)), 0), + (implicit EFLAGS)]>; +def TEST16rm : I<0x85, MRMSrcMem, (outs), (ins GR16:$src1, i16mem:$src2), + "test{w}\t{$src2, $src1|$src1, $src2}", + [(X86cmp (and GR16:$src1, (loadi16 addr:$src2)), 0), + (implicit EFLAGS)]>, OpSize; +def TEST32rm : I<0x85, MRMSrcMem, (outs), (ins GR32:$src1, i32mem:$src2), + "test{l}\t{$src2, $src1|$src1, $src2}", + [(X86cmp (and GR32:$src1, (loadi32 addr:$src2)), 0), + (implicit EFLAGS)]>; + +def TEST8ri : Ii8 <0xF6, MRM0r, // flags = GR8 & imm8 + (outs), (ins GR8:$src1, i8imm:$src2), + "test{b}\t{$src2, $src1|$src1, $src2}", + [(X86cmp (and_su GR8:$src1, imm:$src2), 0), + (implicit EFLAGS)]>; +def TEST16ri : Ii16<0xF7, MRM0r, // flags = GR16 & imm16 + (outs), (ins GR16:$src1, i16imm:$src2), + "test{w}\t{$src2, $src1|$src1, $src2}", + [(X86cmp (and_su GR16:$src1, imm:$src2), 0), + (implicit EFLAGS)]>, OpSize; +def TEST32ri : Ii32<0xF7, MRM0r, // flags = GR32 & imm32 + (outs), (ins GR32:$src1, i32imm:$src2), + "test{l}\t{$src2, $src1|$src1, $src2}", + [(X86cmp (and_su GR32:$src1, imm:$src2), 0), + (implicit EFLAGS)]>; + +def TEST8mi : Ii8 <0xF6, MRM0m, // flags = [mem8] & imm8 + (outs), (ins i8mem:$src1, i8imm:$src2), + "test{b}\t{$src2, $src1|$src1, $src2}", + [(X86cmp (and (loadi8 addr:$src1), imm:$src2), 0), + (implicit EFLAGS)]>; +def TEST16mi : Ii16<0xF7, MRM0m, // flags = [mem16] & imm16 + (outs), (ins i16mem:$src1, i16imm:$src2), + "test{w}\t{$src2, $src1|$src1, $src2}", + [(X86cmp (and (loadi16 addr:$src1), imm:$src2), 0), + (implicit EFLAGS)]>, OpSize; +def TEST32mi : Ii32<0xF7, MRM0m, // flags = [mem32] & imm32 + (outs), (ins i32mem:$src1, i32imm:$src2), + "test{l}\t{$src2, $src1|$src1, $src2}", + [(X86cmp (and (loadi32 addr:$src1), imm:$src2), 0), + (implicit EFLAGS)]>; +} // Defs = [EFLAGS] + + +// Condition code ops, incl. set if equal/not equal/... +let Defs = [EFLAGS], Uses = [AH], neverHasSideEffects = 1 in +def SAHF : I<0x9E, RawFrm, (outs), (ins), "sahf", []>; // flags = AH +let Defs = [AH], Uses = [EFLAGS], neverHasSideEffects = 1 in +def LAHF : I<0x9F, RawFrm, (outs), (ins), "lahf", []>; // AH = flags + +let Uses = [EFLAGS] in { +def SETEr : I<0x94, MRM0r, + (outs GR8 :$dst), (ins), + "sete\t$dst", + [(set GR8:$dst, (X86setcc X86_COND_E, EFLAGS))]>, + TB; // GR8 = == +def SETEm : I<0x94, MRM0m, + (outs), (ins i8mem:$dst), + "sete\t$dst", + [(store (X86setcc X86_COND_E, EFLAGS), addr:$dst)]>, + TB; // [mem8] = == + +def SETNEr : I<0x95, MRM0r, + (outs GR8 :$dst), (ins), + "setne\t$dst", + [(set GR8:$dst, (X86setcc X86_COND_NE, EFLAGS))]>, + TB; // GR8 = != +def SETNEm : I<0x95, MRM0m, + (outs), (ins i8mem:$dst), + "setne\t$dst", + [(store (X86setcc X86_COND_NE, EFLAGS), addr:$dst)]>, + TB; // [mem8] = != + +def SETLr : I<0x9C, MRM0r, + (outs GR8 :$dst), (ins), + "setl\t$dst", + [(set GR8:$dst, (X86setcc X86_COND_L, EFLAGS))]>, + TB; // GR8 = < signed +def SETLm : I<0x9C, MRM0m, + (outs), (ins i8mem:$dst), + "setl\t$dst", + [(store (X86setcc X86_COND_L, EFLAGS), addr:$dst)]>, + TB; // [mem8] = < signed + +def SETGEr : I<0x9D, MRM0r, + (outs GR8 :$dst), (ins), + "setge\t$dst", + [(set GR8:$dst, (X86setcc X86_COND_GE, EFLAGS))]>, + TB; // GR8 = >= signed +def SETGEm : I<0x9D, MRM0m, + (outs), (ins i8mem:$dst), + "setge\t$dst", + [(store (X86setcc X86_COND_GE, EFLAGS), addr:$dst)]>, + TB; // [mem8] = >= signed + +def SETLEr : I<0x9E, MRM0r, + (outs GR8 :$dst), (ins), + "setle\t$dst", + [(set GR8:$dst, (X86setcc X86_COND_LE, EFLAGS))]>, + TB; // GR8 = <= signed +def SETLEm : I<0x9E, MRM0m, + (outs), (ins i8mem:$dst), + "setle\t$dst", + [(store (X86setcc X86_COND_LE, EFLAGS), addr:$dst)]>, + TB; // [mem8] = <= signed + +def SETGr : I<0x9F, MRM0r, + (outs GR8 :$dst), (ins), + "setg\t$dst", + [(set GR8:$dst, (X86setcc X86_COND_G, EFLAGS))]>, + TB; // GR8 = > signed +def SETGm : I<0x9F, MRM0m, + (outs), (ins i8mem:$dst), + "setg\t$dst", + [(store (X86setcc X86_COND_G, EFLAGS), addr:$dst)]>, + TB; // [mem8] = > signed + +def SETBr : I<0x92, MRM0r, + (outs GR8 :$dst), (ins), + "setb\t$dst", + [(set GR8:$dst, (X86setcc X86_COND_B, EFLAGS))]>, + TB; // GR8 = < unsign +def SETBm : I<0x92, MRM0m, + (outs), (ins i8mem:$dst), + "setb\t$dst", + [(store (X86setcc X86_COND_B, EFLAGS), addr:$dst)]>, + TB; // [mem8] = < unsign + +def SETAEr : I<0x93, MRM0r, + (outs GR8 :$dst), (ins), + "setae\t$dst", + [(set GR8:$dst, (X86setcc X86_COND_AE, EFLAGS))]>, + TB; // GR8 = >= unsign +def SETAEm : I<0x93, MRM0m, + (outs), (ins i8mem:$dst), + "setae\t$dst", + [(store (X86setcc X86_COND_AE, EFLAGS), addr:$dst)]>, + TB; // [mem8] = >= unsign + +def SETBEr : I<0x96, MRM0r, + (outs GR8 :$dst), (ins), + "setbe\t$dst", + [(set GR8:$dst, (X86setcc X86_COND_BE, EFLAGS))]>, + TB; // GR8 = <= unsign +def SETBEm : I<0x96, MRM0m, + (outs), (ins i8mem:$dst), + "setbe\t$dst", + [(store (X86setcc X86_COND_BE, EFLAGS), addr:$dst)]>, + TB; // [mem8] = <= unsign + +def SETAr : I<0x97, MRM0r, + (outs GR8 :$dst), (ins), + "seta\t$dst", + [(set GR8:$dst, (X86setcc X86_COND_A, EFLAGS))]>, + TB; // GR8 = > signed +def SETAm : I<0x97, MRM0m, + (outs), (ins i8mem:$dst), + "seta\t$dst", + [(store (X86setcc X86_COND_A, EFLAGS), addr:$dst)]>, + TB; // [mem8] = > signed + +def SETSr : I<0x98, MRM0r, + (outs GR8 :$dst), (ins), + "sets\t$dst", + [(set GR8:$dst, (X86setcc X86_COND_S, EFLAGS))]>, + TB; // GR8 = +def SETSm : I<0x98, MRM0m, + (outs), (ins i8mem:$dst), + "sets\t$dst", + [(store (X86setcc X86_COND_S, EFLAGS), addr:$dst)]>, + TB; // [mem8] = +def SETNSr : I<0x99, MRM0r, + (outs GR8 :$dst), (ins), + "setns\t$dst", + [(set GR8:$dst, (X86setcc X86_COND_NS, EFLAGS))]>, + TB; // GR8 = ! +def SETNSm : I<0x99, MRM0m, + (outs), (ins i8mem:$dst), + "setns\t$dst", + [(store (X86setcc X86_COND_NS, EFLAGS), addr:$dst)]>, + TB; // [mem8] = ! + +def SETPr : I<0x9A, MRM0r, + (outs GR8 :$dst), (ins), + "setp\t$dst", + [(set GR8:$dst, (X86setcc X86_COND_P, EFLAGS))]>, + TB; // GR8 = parity +def SETPm : I<0x9A, MRM0m, + (outs), (ins i8mem:$dst), + "setp\t$dst", + [(store (X86setcc X86_COND_P, EFLAGS), addr:$dst)]>, + TB; // [mem8] = parity +def SETNPr : I<0x9B, MRM0r, + (outs GR8 :$dst), (ins), + "setnp\t$dst", + [(set GR8:$dst, (X86setcc X86_COND_NP, EFLAGS))]>, + TB; // GR8 = not parity +def SETNPm : I<0x9B, MRM0m, + (outs), (ins i8mem:$dst), + "setnp\t$dst", + [(store (X86setcc X86_COND_NP, EFLAGS), addr:$dst)]>, + TB; // [mem8] = not parity + +def SETOr : I<0x90, MRM0r, + (outs GR8 :$dst), (ins), + "seto\t$dst", + [(set GR8:$dst, (X86setcc X86_COND_O, EFLAGS))]>, + TB; // GR8 = overflow +def SETOm : I<0x90, MRM0m, + (outs), (ins i8mem:$dst), + "seto\t$dst", + [(store (X86setcc X86_COND_O, EFLAGS), addr:$dst)]>, + TB; // [mem8] = overflow +def SETNOr : I<0x91, MRM0r, + (outs GR8 :$dst), (ins), + "setno\t$dst", + [(set GR8:$dst, (X86setcc X86_COND_NO, EFLAGS))]>, + TB; // GR8 = not overflow +def SETNOm : I<0x91, MRM0m, + (outs), (ins i8mem:$dst), + "setno\t$dst", + [(store (X86setcc X86_COND_NO, EFLAGS), addr:$dst)]>, + TB; // [mem8] = not overflow +} // Uses = [EFLAGS] + + +// Integer comparisons +let Defs = [EFLAGS] in { +def CMP8i8 : Ii8<0x3C, RawFrm, (outs), (ins i8imm:$src), + "cmp{b}\t{$src, %al|%al, $src}", []>; +def CMP16i16 : Ii16<0x3D, RawFrm, (outs), (ins i16imm:$src), + "cmp{w}\t{$src, %ax|%ax, $src}", []>, OpSize; +def CMP32i32 : Ii32<0x3D, RawFrm, (outs), (ins i32imm:$src), + "cmp{l}\t{$src, %eax|%eax, $src}", []>; + +def CMP8rr : I<0x38, MRMDestReg, + (outs), (ins GR8 :$src1, GR8 :$src2), + "cmp{b}\t{$src2, $src1|$src1, $src2}", + [(X86cmp GR8:$src1, GR8:$src2), (implicit EFLAGS)]>; +def CMP16rr : I<0x39, MRMDestReg, + (outs), (ins GR16:$src1, GR16:$src2), + "cmp{w}\t{$src2, $src1|$src1, $src2}", + [(X86cmp GR16:$src1, GR16:$src2), (implicit EFLAGS)]>, OpSize; +def CMP32rr : I<0x39, MRMDestReg, + (outs), (ins GR32:$src1, GR32:$src2), + "cmp{l}\t{$src2, $src1|$src1, $src2}", + [(X86cmp GR32:$src1, GR32:$src2), (implicit EFLAGS)]>; +def CMP8mr : I<0x38, MRMDestMem, + (outs), (ins i8mem :$src1, GR8 :$src2), + "cmp{b}\t{$src2, $src1|$src1, $src2}", + [(X86cmp (loadi8 addr:$src1), GR8:$src2), + (implicit EFLAGS)]>; +def CMP16mr : I<0x39, MRMDestMem, + (outs), (ins i16mem:$src1, GR16:$src2), + "cmp{w}\t{$src2, $src1|$src1, $src2}", + [(X86cmp (loadi16 addr:$src1), GR16:$src2), + (implicit EFLAGS)]>, OpSize; +def CMP32mr : I<0x39, MRMDestMem, + (outs), (ins i32mem:$src1, GR32:$src2), + "cmp{l}\t{$src2, $src1|$src1, $src2}", + [(X86cmp (loadi32 addr:$src1), GR32:$src2), + (implicit EFLAGS)]>; +def CMP8rm : I<0x3A, MRMSrcMem, + (outs), (ins GR8 :$src1, i8mem :$src2), + "cmp{b}\t{$src2, $src1|$src1, $src2}", + [(X86cmp GR8:$src1, (loadi8 addr:$src2)), + (implicit EFLAGS)]>; +def CMP16rm : I<0x3B, MRMSrcMem, + (outs), (ins GR16:$src1, i16mem:$src2), + "cmp{w}\t{$src2, $src1|$src1, $src2}", + [(X86cmp GR16:$src1, (loadi16 addr:$src2)), + (implicit EFLAGS)]>, OpSize; +def CMP32rm : I<0x3B, MRMSrcMem, + (outs), (ins GR32:$src1, i32mem:$src2), + "cmp{l}\t{$src2, $src1|$src1, $src2}", + [(X86cmp GR32:$src1, (loadi32 addr:$src2)), + (implicit EFLAGS)]>; +def CMP8mrmrr : I<0x3A, MRMSrcReg, (outs), (ins GR8:$src1, GR8:$src2), + "cmp{b}\t{$src2, $src1|$src1, $src2}", []>; +def CMP16mrmrr : I<0x3B, MRMSrcReg, (outs), (ins GR16:$src1, GR16:$src2), + "cmp{w}\t{$src2, $src1|$src1, $src2}", []>, OpSize; +def CMP32mrmrr : I<0x3B, MRMSrcReg, (outs), (ins GR32:$src1, GR32:$src2), + "cmp{l}\t{$src2, $src1|$src1, $src2}", []>; +def CMP8ri : Ii8<0x80, MRM7r, + (outs), (ins GR8:$src1, i8imm:$src2), + "cmp{b}\t{$src2, $src1|$src1, $src2}", + [(X86cmp GR8:$src1, imm:$src2), (implicit EFLAGS)]>; +def CMP16ri : Ii16<0x81, MRM7r, + (outs), (ins GR16:$src1, i16imm:$src2), + "cmp{w}\t{$src2, $src1|$src1, $src2}", + [(X86cmp GR16:$src1, imm:$src2), + (implicit EFLAGS)]>, OpSize; +def CMP32ri : Ii32<0x81, MRM7r, + (outs), (ins GR32:$src1, i32imm:$src2), + "cmp{l}\t{$src2, $src1|$src1, $src2}", + [(X86cmp GR32:$src1, imm:$src2), (implicit EFLAGS)]>; +def CMP8mi : Ii8 <0x80, MRM7m, + (outs), (ins i8mem :$src1, i8imm :$src2), + "cmp{b}\t{$src2, $src1|$src1, $src2}", + [(X86cmp (loadi8 addr:$src1), imm:$src2), + (implicit EFLAGS)]>; +def CMP16mi : Ii16<0x81, MRM7m, + (outs), (ins i16mem:$src1, i16imm:$src2), + "cmp{w}\t{$src2, $src1|$src1, $src2}", + [(X86cmp (loadi16 addr:$src1), imm:$src2), + (implicit EFLAGS)]>, OpSize; +def CMP32mi : Ii32<0x81, MRM7m, + (outs), (ins i32mem:$src1, i32imm:$src2), + "cmp{l}\t{$src2, $src1|$src1, $src2}", + [(X86cmp (loadi32 addr:$src1), imm:$src2), + (implicit EFLAGS)]>; +def CMP16ri8 : Ii8<0x83, MRM7r, + (outs), (ins GR16:$src1, i16i8imm:$src2), + "cmp{w}\t{$src2, $src1|$src1, $src2}", + [(X86cmp GR16:$src1, i16immSExt8:$src2), + (implicit EFLAGS)]>, OpSize; +def CMP16mi8 : Ii8<0x83, MRM7m, + (outs), (ins i16mem:$src1, i16i8imm:$src2), + "cmp{w}\t{$src2, $src1|$src1, $src2}", + [(X86cmp (loadi16 addr:$src1), i16immSExt8:$src2), + (implicit EFLAGS)]>, OpSize; +def CMP32mi8 : Ii8<0x83, MRM7m, + (outs), (ins i32mem:$src1, i32i8imm:$src2), + "cmp{l}\t{$src2, $src1|$src1, $src2}", + [(X86cmp (loadi32 addr:$src1), i32immSExt8:$src2), + (implicit EFLAGS)]>; +def CMP32ri8 : Ii8<0x83, MRM7r, + (outs), (ins GR32:$src1, i32i8imm:$src2), + "cmp{l}\t{$src2, $src1|$src1, $src2}", + [(X86cmp GR32:$src1, i32immSExt8:$src2), + (implicit EFLAGS)]>; +} // Defs = [EFLAGS] + +// Bit tests. +// TODO: BTC, BTR, and BTS +let Defs = [EFLAGS] in { +def BT16rr : I<0xA3, MRMDestReg, (outs), (ins GR16:$src1, GR16:$src2), + "bt{w}\t{$src2, $src1|$src1, $src2}", + [(X86bt GR16:$src1, GR16:$src2), + (implicit EFLAGS)]>, OpSize, TB; +def BT32rr : I<0xA3, MRMDestReg, (outs), (ins GR32:$src1, GR32:$src2), + "bt{l}\t{$src2, $src1|$src1, $src2}", + [(X86bt GR32:$src1, GR32:$src2), + (implicit EFLAGS)]>, TB; + +// Unlike with the register+register form, the memory+register form of the +// bt instruction does not ignore the high bits of the index. From ISel's +// perspective, this is pretty bizarre. Disable these instructions for now. +//def BT16mr : I<0xA3, MRMDestMem, (outs), (ins i16mem:$src1, GR16:$src2), +// "bt{w}\t{$src2, $src1|$src1, $src2}", +// [(X86bt (loadi16 addr:$src1), GR16:$src2), +// (implicit EFLAGS)]>, OpSize, TB, Requires<[FastBTMem]>; +//def BT32mr : I<0xA3, MRMDestMem, (outs), (ins i32mem:$src1, GR32:$src2), +// "bt{l}\t{$src2, $src1|$src1, $src2}", +// [(X86bt (loadi32 addr:$src1), GR32:$src2), +// (implicit EFLAGS)]>, TB, Requires<[FastBTMem]>; + +def BT16ri8 : Ii8<0xBA, MRM4r, (outs), (ins GR16:$src1, i16i8imm:$src2), + "bt{w}\t{$src2, $src1|$src1, $src2}", + [(X86bt GR16:$src1, i16immSExt8:$src2), + (implicit EFLAGS)]>, OpSize, TB; +def BT32ri8 : Ii8<0xBA, MRM4r, (outs), (ins GR32:$src1, i32i8imm:$src2), + "bt{l}\t{$src2, $src1|$src1, $src2}", + [(X86bt GR32:$src1, i32immSExt8:$src2), + (implicit EFLAGS)]>, TB; +// Note that these instructions don't need FastBTMem because that +// only applies when the other operand is in a register. When it's +// an immediate, bt is still fast. +def BT16mi8 : Ii8<0xBA, MRM4m, (outs), (ins i16mem:$src1, i16i8imm:$src2), + "bt{w}\t{$src2, $src1|$src1, $src2}", + [(X86bt (loadi16 addr:$src1), i16immSExt8:$src2), + (implicit EFLAGS)]>, OpSize, TB; +def BT32mi8 : Ii8<0xBA, MRM4m, (outs), (ins i32mem:$src1, i32i8imm:$src2), + "bt{l}\t{$src2, $src1|$src1, $src2}", + [(X86bt (loadi32 addr:$src1), i32immSExt8:$src2), + (implicit EFLAGS)]>, TB; +} // Defs = [EFLAGS] + +// Sign/Zero extenders +// Use movsbl intead of movsbw; we don't care about the high 16 bits +// of the register here. This has a smaller encoding and avoids a +// partial-register update. +def MOVSX16rr8 : I<0xBE, MRMSrcReg, (outs GR16:$dst), (ins GR8 :$src), + "", [(set GR16:$dst, (sext GR8:$src))]>, TB; +def MOVSX16rm8 : I<0xBE, MRMSrcMem, (outs GR16:$dst), (ins i8mem :$src), + "", [(set GR16:$dst, (sextloadi16i8 addr:$src))]>, TB; +def MOVSX32rr8 : I<0xBE, MRMSrcReg, (outs GR32:$dst), (ins GR8 :$src), + "movs{bl|x}\t{$src, $dst|$dst, $src}", + [(set GR32:$dst, (sext GR8:$src))]>, TB; +def MOVSX32rm8 : I<0xBE, MRMSrcMem, (outs GR32:$dst), (ins i8mem :$src), + "movs{bl|x}\t{$src, $dst|$dst, $src}", + [(set GR32:$dst, (sextloadi32i8 addr:$src))]>, TB; +def MOVSX32rr16: I<0xBF, MRMSrcReg, (outs GR32:$dst), (ins GR16:$src), + "movs{wl|x}\t{$src, $dst|$dst, $src}", + [(set GR32:$dst, (sext GR16:$src))]>, TB; +def MOVSX32rm16: I<0xBF, MRMSrcMem, (outs GR32:$dst), (ins i16mem:$src), + "movs{wl|x}\t{$src, $dst|$dst, $src}", + [(set GR32:$dst, (sextloadi32i16 addr:$src))]>, TB; + +// Use movzbl intead of movzbw; we don't care about the high 16 bits +// of the register here. This has a smaller encoding and avoids a +// partial-register update. +def MOVZX16rr8 : I<0xB6, MRMSrcReg, (outs GR16:$dst), (ins GR8 :$src), + "", [(set GR16:$dst, (zext GR8:$src))]>, TB; +def MOVZX16rm8 : I<0xB6, MRMSrcMem, (outs GR16:$dst), (ins i8mem :$src), + "", [(set GR16:$dst, (zextloadi16i8 addr:$src))]>, TB; +def MOVZX32rr8 : I<0xB6, MRMSrcReg, (outs GR32:$dst), (ins GR8 :$src), + "movz{bl|x}\t{$src, $dst|$dst, $src}", + [(set GR32:$dst, (zext GR8:$src))]>, TB; +def MOVZX32rm8 : I<0xB6, MRMSrcMem, (outs GR32:$dst), (ins i8mem :$src), + "movz{bl|x}\t{$src, $dst|$dst, $src}", + [(set GR32:$dst, (zextloadi32i8 addr:$src))]>, TB; +def MOVZX32rr16: I<0xB7, MRMSrcReg, (outs GR32:$dst), (ins GR16:$src), + "movz{wl|x}\t{$src, $dst|$dst, $src}", + [(set GR32:$dst, (zext GR16:$src))]>, TB; +def MOVZX32rm16: I<0xB7, MRMSrcMem, (outs GR32:$dst), (ins i16mem:$src), + "movz{wl|x}\t{$src, $dst|$dst, $src}", + [(set GR32:$dst, (zextloadi32i16 addr:$src))]>, TB; + +// These are the same as the regular regular MOVZX32rr8 and MOVZX32rm8 +// except that they use GR32_NOREX for the output operand register class +// instead of GR32. This allows them to operate on h registers on x86-64. +def MOVZX32_NOREXrr8 : I<0xB6, MRMSrcReg, + (outs GR32_NOREX:$dst), (ins GR8:$src), + "movz{bl|x}\t{$src, $dst|$dst, $src} # NOREX", + []>, TB; +let mayLoad = 1 in +def MOVZX32_NOREXrm8 : I<0xB6, MRMSrcMem, + (outs GR32_NOREX:$dst), (ins i8mem:$src), + "movz{bl|x}\t{$src, $dst|$dst, $src} # NOREX", + []>, TB; + +let neverHasSideEffects = 1 in { + let Defs = [AX], Uses = [AL] in + def CBW : I<0x98, RawFrm, (outs), (ins), + "{cbtw|cbw}", []>, OpSize; // AX = signext(AL) + let Defs = [EAX], Uses = [AX] in + def CWDE : I<0x98, RawFrm, (outs), (ins), + "{cwtl|cwde}", []>; // EAX = signext(AX) + + let Defs = [AX,DX], Uses = [AX] in + def CWD : I<0x99, RawFrm, (outs), (ins), + "{cwtd|cwd}", []>, OpSize; // DX:AX = signext(AX) + let Defs = [EAX,EDX], Uses = [EAX] in + def CDQ : I<0x99, RawFrm, (outs), (ins), + "{cltd|cdq}", []>; // EDX:EAX = signext(EAX) +} + +//===----------------------------------------------------------------------===// +// Alias Instructions +//===----------------------------------------------------------------------===// + +// Alias instructions that map movr0 to xor. +// FIXME: remove when we can teach regalloc that xor reg, reg is ok. +let Defs = [EFLAGS], isReMaterializable = 1, isAsCheapAsAMove = 1, + isCodeGenOnly = 1 in { +def MOV8r0 : I<0x30, MRMInitReg, (outs GR8 :$dst), (ins), + "xor{b}\t$dst, $dst", + [(set GR8:$dst, 0)]>; +// Use xorl instead of xorw since we don't care about the high 16 bits, +// it's smaller, and it avoids a partial-register update. +def MOV16r0 : I<0x31, MRMInitReg, (outs GR16:$dst), (ins), + "", [(set GR16:$dst, 0)]>; +def MOV32r0 : I<0x31, MRMInitReg, (outs GR32:$dst), (ins), + "xor{l}\t$dst, $dst", + [(set GR32:$dst, 0)]>; +} + +//===----------------------------------------------------------------------===// +// Thread Local Storage Instructions +// + +// All calls clobber the non-callee saved registers. ESP is marked as +// a use to prevent stack-pointer assignments that appear immediately +// before calls from potentially appearing dead. +let Defs = [EAX, ECX, EDX, FP0, FP1, FP2, FP3, FP4, FP5, FP6, ST0, + MM0, MM1, MM2, MM3, MM4, MM5, MM6, MM7, + XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6, XMM7, + XMM8, XMM9, XMM10, XMM11, XMM12, XMM13, XMM14, XMM15, EFLAGS], + Uses = [ESP] in +def TLS_addr32 : I<0, Pseudo, (outs), (ins lea32mem:$sym), + "leal\t$sym, %eax; " + "call\t___tls_get_addr@PLT", + [(X86tlsaddr tls32addr:$sym)]>, + Requires<[In32BitMode]>; + +let AddedComplexity = 5, isCodeGenOnly = 1 in +def GS_MOV32rm : I<0x8B, MRMSrcMem, (outs GR32:$dst), (ins i32mem:$src), + "movl\t%gs:$src, $dst", + [(set GR32:$dst, (gsload addr:$src))]>, SegGS; + +let AddedComplexity = 5, isCodeGenOnly = 1 in +def FS_MOV32rm : I<0x8B, MRMSrcMem, (outs GR32:$dst), (ins i32mem:$src), + "movl\t%fs:$src, $dst", + [(set GR32:$dst, (fsload addr:$src))]>, SegFS; + +//===----------------------------------------------------------------------===// +// EH Pseudo Instructions +// +let isTerminator = 1, isReturn = 1, isBarrier = 1, + hasCtrlDep = 1, isCodeGenOnly = 1 in { +def EH_RETURN : I<0xC3, RawFrm, (outs), (ins GR32:$addr), + "ret\t#eh_return, addr: $addr", + [(X86ehret GR32:$addr)]>; + +} + +//===----------------------------------------------------------------------===// +// Atomic support +// + +// Atomic swap. These are just normal xchg instructions. But since a memory +// operand is referenced, the atomicity is ensured. +let Constraints = "$val = $dst" in { +def XCHG32rm : I<0x87, MRMSrcMem, (outs GR32:$dst), (ins i32mem:$ptr, GR32:$val), + "xchg{l}\t{$val, $ptr|$ptr, $val}", + [(set GR32:$dst, (atomic_swap_32 addr:$ptr, GR32:$val))]>; +def XCHG16rm : I<0x87, MRMSrcMem, (outs GR16:$dst), (ins i16mem:$ptr, GR16:$val), + "xchg{w}\t{$val, $ptr|$ptr, $val}", + [(set GR16:$dst, (atomic_swap_16 addr:$ptr, GR16:$val))]>, + OpSize; +def XCHG8rm : I<0x86, MRMSrcMem, (outs GR8:$dst), (ins i8mem:$ptr, GR8:$val), + "xchg{b}\t{$val, $ptr|$ptr, $val}", + [(set GR8:$dst, (atomic_swap_8 addr:$ptr, GR8:$val))]>; +} + +// Atomic compare and swap. +let Defs = [EAX, EFLAGS], Uses = [EAX] in { +def LCMPXCHG32 : I<0xB1, MRMDestMem, (outs), (ins i32mem:$ptr, GR32:$swap), + "lock\n\t" + "cmpxchg{l}\t{$swap, $ptr|$ptr, $swap}", + [(X86cas addr:$ptr, GR32:$swap, 4)]>, TB, LOCK; +} +let Defs = [EAX, EDX, EFLAGS], Uses = [EAX, EBX, ECX, EDX] in { +def LCMPXCHG8B : I<0xC7, MRM1m, (outs), (ins i32mem:$ptr), + "lock\n\t" + "cmpxchg8b\t$ptr", + [(X86cas8 addr:$ptr)]>, TB, LOCK; +} + +let Defs = [AX, EFLAGS], Uses = [AX] in { +def LCMPXCHG16 : I<0xB1, MRMDestMem, (outs), (ins i16mem:$ptr, GR16:$swap), + "lock\n\t" + "cmpxchg{w}\t{$swap, $ptr|$ptr, $swap}", + [(X86cas addr:$ptr, GR16:$swap, 2)]>, TB, OpSize, LOCK; +} +let Defs = [AL, EFLAGS], Uses = [AL] in { +def LCMPXCHG8 : I<0xB0, MRMDestMem, (outs), (ins i8mem:$ptr, GR8:$swap), + "lock\n\t" + "cmpxchg{b}\t{$swap, $ptr|$ptr, $swap}", + [(X86cas addr:$ptr, GR8:$swap, 1)]>, TB, LOCK; +} + +// Atomic exchange and add +let Constraints = "$val = $dst", Defs = [EFLAGS] in { +def LXADD32 : I<0xC1, MRMSrcMem, (outs GR32:$dst), (ins i32mem:$ptr, GR32:$val), + "lock\n\t" + "xadd{l}\t{$val, $ptr|$ptr, $val}", + [(set GR32:$dst, (atomic_load_add_32 addr:$ptr, GR32:$val))]>, + TB, LOCK; +def LXADD16 : I<0xC1, MRMSrcMem, (outs GR16:$dst), (ins i16mem:$ptr, GR16:$val), + "lock\n\t" + "xadd{w}\t{$val, $ptr|$ptr, $val}", + [(set GR16:$dst, (atomic_load_add_16 addr:$ptr, GR16:$val))]>, + TB, OpSize, LOCK; +def LXADD8 : I<0xC0, MRMSrcMem, (outs GR8:$dst), (ins i8mem:$ptr, GR8:$val), + "lock\n\t" + "xadd{b}\t{$val, $ptr|$ptr, $val}", + [(set GR8:$dst, (atomic_load_add_8 addr:$ptr, GR8:$val))]>, + TB, LOCK; +} + +// Optimized codegen when the non-memory output is not used. +// FIXME: Use normal add / sub instructions and add lock prefix dynamically. +let Defs = [EFLAGS] in { +def LOCK_ADD8mr : I<0x00, MRMDestMem, (outs), (ins i8mem:$dst, GR8:$src2), + "lock\n\t" + "add{b}\t{$src2, $dst|$dst, $src2}", []>, LOCK; +def LOCK_ADD16mr : I<0x01, MRMDestMem, (outs), (ins i16mem:$dst, GR16:$src2), + "lock\n\t" + "add{w}\t{$src2, $dst|$dst, $src2}", []>, OpSize, LOCK; +def LOCK_ADD32mr : I<0x01, MRMDestMem, (outs), (ins i32mem:$dst, GR32:$src2), + "lock\n\t" + "add{l}\t{$src2, $dst|$dst, $src2}", []>, LOCK; +def LOCK_ADD8mi : Ii8<0x80, MRM0m, (outs), (ins i8mem :$dst, i8imm :$src2), + "lock\n\t" + "add{b}\t{$src2, $dst|$dst, $src2}", []>, LOCK; +def LOCK_ADD16mi : Ii16<0x81, MRM0m, (outs), (ins i16mem:$dst, i16imm:$src2), + "lock\n\t" + "add{w}\t{$src2, $dst|$dst, $src2}", []>, LOCK; +def LOCK_ADD32mi : Ii32<0x81, MRM0m, (outs), (ins i32mem:$dst, i32imm:$src2), + "lock\n\t" + "add{l}\t{$src2, $dst|$dst, $src2}", []>, LOCK; +def LOCK_ADD16mi8 : Ii8<0x83, MRM0m, (outs), (ins i16mem:$dst, i16i8imm :$src2), + "lock\n\t" + "add{w}\t{$src2, $dst|$dst, $src2}", []>, OpSize, LOCK; +def LOCK_ADD32mi8 : Ii8<0x83, MRM0m, (outs), (ins i32mem:$dst, i32i8imm :$src2), + "lock\n\t" + "add{l}\t{$src2, $dst|$dst, $src2}", []>, LOCK; + +def LOCK_INC8m : I<0xFE, MRM0m, (outs), (ins i8mem :$dst), + "lock\n\t" + "inc{b}\t$dst", []>, LOCK; +def LOCK_INC16m : I<0xFF, MRM0m, (outs), (ins i16mem:$dst), + "lock\n\t" + "inc{w}\t$dst", []>, OpSize, LOCK; +def LOCK_INC32m : I<0xFF, MRM0m, (outs), (ins i32mem:$dst), + "lock\n\t" + "inc{l}\t$dst", []>, LOCK; + +def LOCK_SUB8mr : I<0x28, MRMDestMem, (outs), (ins i8mem :$dst, GR8 :$src2), + "lock\n\t" + "sub{b}\t{$src2, $dst|$dst, $src2}", []>, LOCK; +def LOCK_SUB16mr : I<0x29, MRMDestMem, (outs), (ins i16mem:$dst, GR16:$src2), + "lock\n\t" + "sub{w}\t{$src2, $dst|$dst, $src2}", []>, OpSize, LOCK; +def LOCK_SUB32mr : I<0x29, MRMDestMem, (outs), (ins i32mem:$dst, GR32:$src2), + "lock\n\t" + "sub{l}\t{$src2, $dst|$dst, $src2}", []>, LOCK; +def LOCK_SUB8mi : Ii8<0x80, MRM5m, (outs), (ins i8mem :$dst, i8imm:$src2), + "lock\n\t" + "sub{b}\t{$src2, $dst|$dst, $src2}", []>, LOCK; +def LOCK_SUB16mi : Ii16<0x81, MRM5m, (outs), (ins i16mem:$dst, i16imm:$src2), + "lock\n\t" + "sub{w}\t{$src2, $dst|$dst, $src2}", []>, OpSize, LOCK; +def LOCK_SUB32mi : Ii32<0x81, MRM5m, (outs), (ins i32mem:$dst, i32imm:$src2), + "lock\n\t" + "sub{l}\t{$src2, $dst|$dst, $src2}", []>, LOCK; +def LOCK_SUB16mi8 : Ii8<0x83, MRM5m, (outs), (ins i16mem:$dst, i16i8imm :$src2), + "lock\n\t" + "sub{w}\t{$src2, $dst|$dst, $src2}", []>, OpSize, LOCK; +def LOCK_SUB32mi8 : Ii8<0x83, MRM5m, (outs), (ins i32mem:$dst, i32i8imm :$src2), + "lock\n\t" + "sub{l}\t{$src2, $dst|$dst, $src2}", []>, LOCK; + +def LOCK_DEC8m : I<0xFE, MRM1m, (outs), (ins i8mem :$dst), + "lock\n\t" + "dec{b}\t$dst", []>, LOCK; +def LOCK_DEC16m : I<0xFF, MRM1m, (outs), (ins i16mem:$dst), + "lock\n\t" + "dec{w}\t$dst", []>, OpSize, LOCK; +def LOCK_DEC32m : I<0xFF, MRM1m, (outs), (ins i32mem:$dst), + "lock\n\t" + "dec{l}\t$dst", []>, LOCK; +} + +// Atomic exchange, and, or, xor +let Constraints = "$val = $dst", Defs = [EFLAGS], + usesCustomInserter = 1 in { +def ATOMAND32 : I<0, Pseudo, (outs GR32:$dst),(ins i32mem:$ptr, GR32:$val), + "#ATOMAND32 PSEUDO!", + [(set GR32:$dst, (atomic_load_and_32 addr:$ptr, GR32:$val))]>; +def ATOMOR32 : I<0, Pseudo, (outs GR32:$dst),(ins i32mem:$ptr, GR32:$val), + "#ATOMOR32 PSEUDO!", + [(set GR32:$dst, (atomic_load_or_32 addr:$ptr, GR32:$val))]>; +def ATOMXOR32 : I<0, Pseudo,(outs GR32:$dst),(ins i32mem:$ptr, GR32:$val), + "#ATOMXOR32 PSEUDO!", + [(set GR32:$dst, (atomic_load_xor_32 addr:$ptr, GR32:$val))]>; +def ATOMNAND32 : I<0, Pseudo,(outs GR32:$dst),(ins i32mem:$ptr, GR32:$val), + "#ATOMNAND32 PSEUDO!", + [(set GR32:$dst, (atomic_load_nand_32 addr:$ptr, GR32:$val))]>; +def ATOMMIN32: I<0, Pseudo, (outs GR32:$dst), (ins i32mem:$ptr, GR32:$val), + "#ATOMMIN32 PSEUDO!", + [(set GR32:$dst, (atomic_load_min_32 addr:$ptr, GR32:$val))]>; +def ATOMMAX32: I<0, Pseudo, (outs GR32:$dst),(ins i32mem:$ptr, GR32:$val), + "#ATOMMAX32 PSEUDO!", + [(set GR32:$dst, (atomic_load_max_32 addr:$ptr, GR32:$val))]>; +def ATOMUMIN32: I<0, Pseudo, (outs GR32:$dst),(ins i32mem:$ptr, GR32:$val), + "#ATOMUMIN32 PSEUDO!", + [(set GR32:$dst, (atomic_load_umin_32 addr:$ptr, GR32:$val))]>; +def ATOMUMAX32: I<0, Pseudo, (outs GR32:$dst),(ins i32mem:$ptr, GR32:$val), + "#ATOMUMAX32 PSEUDO!", + [(set GR32:$dst, (atomic_load_umax_32 addr:$ptr, GR32:$val))]>; + +def ATOMAND16 : I<0, Pseudo, (outs GR16:$dst),(ins i16mem:$ptr, GR16:$val), + "#ATOMAND16 PSEUDO!", + [(set GR16:$dst, (atomic_load_and_16 addr:$ptr, GR16:$val))]>; +def ATOMOR16 : I<0, Pseudo, (outs GR16:$dst),(ins i16mem:$ptr, GR16:$val), + "#ATOMOR16 PSEUDO!", + [(set GR16:$dst, (atomic_load_or_16 addr:$ptr, GR16:$val))]>; +def ATOMXOR16 : I<0, Pseudo,(outs GR16:$dst),(ins i16mem:$ptr, GR16:$val), + "#ATOMXOR16 PSEUDO!", + [(set GR16:$dst, (atomic_load_xor_16 addr:$ptr, GR16:$val))]>; +def ATOMNAND16 : I<0, Pseudo,(outs GR16:$dst),(ins i16mem:$ptr, GR16:$val), + "#ATOMNAND16 PSEUDO!", + [(set GR16:$dst, (atomic_load_nand_16 addr:$ptr, GR16:$val))]>; +def ATOMMIN16: I<0, Pseudo, (outs GR16:$dst), (ins i16mem:$ptr, GR16:$val), + "#ATOMMIN16 PSEUDO!", + [(set GR16:$dst, (atomic_load_min_16 addr:$ptr, GR16:$val))]>; +def ATOMMAX16: I<0, Pseudo, (outs GR16:$dst),(ins i16mem:$ptr, GR16:$val), + "#ATOMMAX16 PSEUDO!", + [(set GR16:$dst, (atomic_load_max_16 addr:$ptr, GR16:$val))]>; +def ATOMUMIN16: I<0, Pseudo, (outs GR16:$dst),(ins i16mem:$ptr, GR16:$val), + "#ATOMUMIN16 PSEUDO!", + [(set GR16:$dst, (atomic_load_umin_16 addr:$ptr, GR16:$val))]>; +def ATOMUMAX16: I<0, Pseudo, (outs GR16:$dst),(ins i16mem:$ptr, GR16:$val), + "#ATOMUMAX16 PSEUDO!", + [(set GR16:$dst, (atomic_load_umax_16 addr:$ptr, GR16:$val))]>; + +def ATOMAND8 : I<0, Pseudo, (outs GR8:$dst),(ins i8mem:$ptr, GR8:$val), + "#ATOMAND8 PSEUDO!", + [(set GR8:$dst, (atomic_load_and_8 addr:$ptr, GR8:$val))]>; +def ATOMOR8 : I<0, Pseudo, (outs GR8:$dst),(ins i8mem:$ptr, GR8:$val), + "#ATOMOR8 PSEUDO!", + [(set GR8:$dst, (atomic_load_or_8 addr:$ptr, GR8:$val))]>; +def ATOMXOR8 : I<0, Pseudo,(outs GR8:$dst),(ins i8mem:$ptr, GR8:$val), + "#ATOMXOR8 PSEUDO!", + [(set GR8:$dst, (atomic_load_xor_8 addr:$ptr, GR8:$val))]>; +def ATOMNAND8 : I<0, Pseudo,(outs GR8:$dst),(ins i8mem:$ptr, GR8:$val), + "#ATOMNAND8 PSEUDO!", + [(set GR8:$dst, (atomic_load_nand_8 addr:$ptr, GR8:$val))]>; +} + +let Constraints = "$val1 = $dst1, $val2 = $dst2", + Defs = [EFLAGS, EAX, EBX, ECX, EDX], + Uses = [EAX, EBX, ECX, EDX], + mayLoad = 1, mayStore = 1, + usesCustomInserter = 1 in { +def ATOMAND6432 : I<0, Pseudo, (outs GR32:$dst1, GR32:$dst2), + (ins i64mem:$ptr, GR32:$val1, GR32:$val2), + "#ATOMAND6432 PSEUDO!", []>; +def ATOMOR6432 : I<0, Pseudo, (outs GR32:$dst1, GR32:$dst2), + (ins i64mem:$ptr, GR32:$val1, GR32:$val2), + "#ATOMOR6432 PSEUDO!", []>; +def ATOMXOR6432 : I<0, Pseudo, (outs GR32:$dst1, GR32:$dst2), + (ins i64mem:$ptr, GR32:$val1, GR32:$val2), + "#ATOMXOR6432 PSEUDO!", []>; +def ATOMNAND6432 : I<0, Pseudo, (outs GR32:$dst1, GR32:$dst2), + (ins i64mem:$ptr, GR32:$val1, GR32:$val2), + "#ATOMNAND6432 PSEUDO!", []>; +def ATOMADD6432 : I<0, Pseudo, (outs GR32:$dst1, GR32:$dst2), + (ins i64mem:$ptr, GR32:$val1, GR32:$val2), + "#ATOMADD6432 PSEUDO!", []>; +def ATOMSUB6432 : I<0, Pseudo, (outs GR32:$dst1, GR32:$dst2), + (ins i64mem:$ptr, GR32:$val1, GR32:$val2), + "#ATOMSUB6432 PSEUDO!", []>; +def ATOMSWAP6432 : I<0, Pseudo, (outs GR32:$dst1, GR32:$dst2), + (ins i64mem:$ptr, GR32:$val1, GR32:$val2), + "#ATOMSWAP6432 PSEUDO!", []>; +} + +// Segmentation support instructions. + +def LAR16rm : I<0x02, MRMSrcMem, (outs GR16:$dst), (ins i16mem:$src), + "lar{w}\t{$src, $dst|$dst, $src}", []>, TB, OpSize; +def LAR16rr : I<0x02, MRMSrcReg, (outs GR16:$dst), (ins GR16:$src), + "lar{w}\t{$src, $dst|$dst, $src}", []>, TB, OpSize; + +// i16mem operand in LAR32rm and GR32 operand in LAR32rr is not a typo. +def LAR32rm : I<0x02, MRMSrcMem, (outs GR32:$dst), (ins i16mem:$src), + "lar{l}\t{$src, $dst|$dst, $src}", []>, TB; +def LAR32rr : I<0x02, MRMSrcReg, (outs GR32:$dst), (ins GR32:$src), + "lar{l}\t{$src, $dst|$dst, $src}", []>, TB; + +// String manipulation instructions + +def LODSB : I<0xAC, RawFrm, (outs), (ins), "lodsb", []>; +def LODSW : I<0xAD, RawFrm, (outs), (ins), "lodsw", []>, OpSize; +def LODSD : I<0xAD, RawFrm, (outs), (ins), "lodsd", []>; + +//===----------------------------------------------------------------------===// +// Non-Instruction Patterns +//===----------------------------------------------------------------------===// + +// ConstantPool GlobalAddress, ExternalSymbol, and JumpTable +def : Pat<(i32 (X86Wrapper tconstpool :$dst)), (MOV32ri tconstpool :$dst)>; +def : Pat<(i32 (X86Wrapper tjumptable :$dst)), (MOV32ri tjumptable :$dst)>; +def : Pat<(i32 (X86Wrapper tglobaltlsaddr:$dst)),(MOV32ri tglobaltlsaddr:$dst)>; +def : Pat<(i32 (X86Wrapper tglobaladdr :$dst)), (MOV32ri tglobaladdr :$dst)>; +def : Pat<(i32 (X86Wrapper texternalsym:$dst)), (MOV32ri texternalsym:$dst)>; +def : Pat<(i32 (X86Wrapper tblockaddress:$dst)), (MOV32ri tblockaddress:$dst)>; + +def : Pat<(add GR32:$src1, (X86Wrapper tconstpool:$src2)), + (ADD32ri GR32:$src1, tconstpool:$src2)>; +def : Pat<(add GR32:$src1, (X86Wrapper tjumptable:$src2)), + (ADD32ri GR32:$src1, tjumptable:$src2)>; +def : Pat<(add GR32:$src1, (X86Wrapper tglobaladdr :$src2)), + (ADD32ri GR32:$src1, tglobaladdr:$src2)>; +def : Pat<(add GR32:$src1, (X86Wrapper texternalsym:$src2)), + (ADD32ri GR32:$src1, texternalsym:$src2)>; +def : Pat<(add GR32:$src1, (X86Wrapper tblockaddress:$src2)), + (ADD32ri GR32:$src1, tblockaddress:$src2)>; + +def : Pat<(store (i32 (X86Wrapper tglobaladdr:$src)), addr:$dst), + (MOV32mi addr:$dst, tglobaladdr:$src)>; +def : Pat<(store (i32 (X86Wrapper texternalsym:$src)), addr:$dst), + (MOV32mi addr:$dst, texternalsym:$src)>; +def : Pat<(store (i32 (X86Wrapper tblockaddress:$src)), addr:$dst), + (MOV32mi addr:$dst, tblockaddress:$src)>; + +// Calls +// tailcall stuff +def : Pat<(X86tcret GR32:$dst, imm:$off), + (TCRETURNri GR32:$dst, imm:$off)>; + +def : Pat<(X86tcret (i32 tglobaladdr:$dst), imm:$off), + (TCRETURNdi texternalsym:$dst, imm:$off)>; + +def : Pat<(X86tcret (i32 texternalsym:$dst), imm:$off), + (TCRETURNdi texternalsym:$dst, imm:$off)>; + +// Normal calls, with various flavors of addresses. +def : Pat<(X86call (i32 tglobaladdr:$dst)), + (CALLpcrel32 tglobaladdr:$dst)>; +def : Pat<(X86call (i32 texternalsym:$dst)), + (CALLpcrel32 texternalsym:$dst)>; +def : Pat<(X86call (i32 imm:$dst)), + (CALLpcrel32 imm:$dst)>, Requires<[CallImmAddr]>; + +// X86 specific add which produces a flag. +def : Pat<(addc GR32:$src1, GR32:$src2), + (ADD32rr GR32:$src1, GR32:$src2)>; +def : Pat<(addc GR32:$src1, (load addr:$src2)), + (ADD32rm GR32:$src1, addr:$src2)>; +def : Pat<(addc GR32:$src1, imm:$src2), + (ADD32ri GR32:$src1, imm:$src2)>; +def : Pat<(addc GR32:$src1, i32immSExt8:$src2), + (ADD32ri8 GR32:$src1, i32immSExt8:$src2)>; + +def : Pat<(subc GR32:$src1, GR32:$src2), + (SUB32rr GR32:$src1, GR32:$src2)>; +def : Pat<(subc GR32:$src1, (load addr:$src2)), + (SUB32rm GR32:$src1, addr:$src2)>; +def : Pat<(subc GR32:$src1, imm:$src2), + (SUB32ri GR32:$src1, imm:$src2)>; +def : Pat<(subc GR32:$src1, i32immSExt8:$src2), + (SUB32ri8 GR32:$src1, i32immSExt8:$src2)>; + +// Comparisons. + +// TEST R,R is smaller than CMP R,0 +def : Pat<(parallel (X86cmp GR8:$src1, 0), (implicit EFLAGS)), + (TEST8rr GR8:$src1, GR8:$src1)>; +def : Pat<(parallel (X86cmp GR16:$src1, 0), (implicit EFLAGS)), + (TEST16rr GR16:$src1, GR16:$src1)>; +def : Pat<(parallel (X86cmp GR32:$src1, 0), (implicit EFLAGS)), + (TEST32rr GR32:$src1, GR32:$src1)>; + +// Conditional moves with folded loads with operands swapped and conditions +// inverted. +def : Pat<(X86cmov (loadi16 addr:$src1), GR16:$src2, X86_COND_B, EFLAGS), + (CMOVAE16rm GR16:$src2, addr:$src1)>; +def : Pat<(X86cmov (loadi32 addr:$src1), GR32:$src2, X86_COND_B, EFLAGS), + (CMOVAE32rm GR32:$src2, addr:$src1)>; +def : Pat<(X86cmov (loadi16 addr:$src1), GR16:$src2, X86_COND_AE, EFLAGS), + (CMOVB16rm GR16:$src2, addr:$src1)>; +def : Pat<(X86cmov (loadi32 addr:$src1), GR32:$src2, X86_COND_AE, EFLAGS), + (CMOVB32rm GR32:$src2, addr:$src1)>; +def : Pat<(X86cmov (loadi16 addr:$src1), GR16:$src2, X86_COND_E, EFLAGS), + (CMOVNE16rm GR16:$src2, addr:$src1)>; +def : Pat<(X86cmov (loadi32 addr:$src1), GR32:$src2, X86_COND_E, EFLAGS), + (CMOVNE32rm GR32:$src2, addr:$src1)>; +def : Pat<(X86cmov (loadi16 addr:$src1), GR16:$src2, X86_COND_NE, EFLAGS), + (CMOVE16rm GR16:$src2, addr:$src1)>; +def : Pat<(X86cmov (loadi32 addr:$src1), GR32:$src2, X86_COND_NE, EFLAGS), + (CMOVE32rm GR32:$src2, addr:$src1)>; +def : Pat<(X86cmov (loadi16 addr:$src1), GR16:$src2, X86_COND_BE, EFLAGS), + (CMOVA16rm GR16:$src2, addr:$src1)>; +def : Pat<(X86cmov (loadi32 addr:$src1), GR32:$src2, X86_COND_BE, EFLAGS), + (CMOVA32rm GR32:$src2, addr:$src1)>; +def : Pat<(X86cmov (loadi16 addr:$src1), GR16:$src2, X86_COND_A, EFLAGS), + (CMOVBE16rm GR16:$src2, addr:$src1)>; +def : Pat<(X86cmov (loadi32 addr:$src1), GR32:$src2, X86_COND_A, EFLAGS), + (CMOVBE32rm GR32:$src2, addr:$src1)>; +def : Pat<(X86cmov (loadi16 addr:$src1), GR16:$src2, X86_COND_L, EFLAGS), + (CMOVGE16rm GR16:$src2, addr:$src1)>; +def : Pat<(X86cmov (loadi32 addr:$src1), GR32:$src2, X86_COND_L, EFLAGS), + (CMOVGE32rm GR32:$src2, addr:$src1)>; +def : Pat<(X86cmov (loadi16 addr:$src1), GR16:$src2, X86_COND_GE, EFLAGS), + (CMOVL16rm GR16:$src2, addr:$src1)>; +def : Pat<(X86cmov (loadi32 addr:$src1), GR32:$src2, X86_COND_GE, EFLAGS), + (CMOVL32rm GR32:$src2, addr:$src1)>; +def : Pat<(X86cmov (loadi16 addr:$src1), GR16:$src2, X86_COND_LE, EFLAGS), + (CMOVG16rm GR16:$src2, addr:$src1)>; +def : Pat<(X86cmov (loadi32 addr:$src1), GR32:$src2, X86_COND_LE, EFLAGS), + (CMOVG32rm GR32:$src2, addr:$src1)>; +def : Pat<(X86cmov (loadi16 addr:$src1), GR16:$src2, X86_COND_G, EFLAGS), + (CMOVLE16rm GR16:$src2, addr:$src1)>; +def : Pat<(X86cmov (loadi32 addr:$src1), GR32:$src2, X86_COND_G, EFLAGS), + (CMOVLE32rm GR32:$src2, addr:$src1)>; +def : Pat<(X86cmov (loadi16 addr:$src1), GR16:$src2, X86_COND_P, EFLAGS), + (CMOVNP16rm GR16:$src2, addr:$src1)>; +def : Pat<(X86cmov (loadi32 addr:$src1), GR32:$src2, X86_COND_P, EFLAGS), + (CMOVNP32rm GR32:$src2, addr:$src1)>; +def : Pat<(X86cmov (loadi16 addr:$src1), GR16:$src2, X86_COND_NP, EFLAGS), + (CMOVP16rm GR16:$src2, addr:$src1)>; +def : Pat<(X86cmov (loadi32 addr:$src1), GR32:$src2, X86_COND_NP, EFLAGS), + (CMOVP32rm GR32:$src2, addr:$src1)>; +def : Pat<(X86cmov (loadi16 addr:$src1), GR16:$src2, X86_COND_S, EFLAGS), + (CMOVNS16rm GR16:$src2, addr:$src1)>; +def : Pat<(X86cmov (loadi32 addr:$src1), GR32:$src2, X86_COND_S, EFLAGS), + (CMOVNS32rm GR32:$src2, addr:$src1)>; +def : Pat<(X86cmov (loadi16 addr:$src1), GR16:$src2, X86_COND_NS, EFLAGS), + (CMOVS16rm GR16:$src2, addr:$src1)>; +def : Pat<(X86cmov (loadi32 addr:$src1), GR32:$src2, X86_COND_NS, EFLAGS), + (CMOVS32rm GR32:$src2, addr:$src1)>; +def : Pat<(X86cmov (loadi16 addr:$src1), GR16:$src2, X86_COND_O, EFLAGS), + (CMOVNO16rm GR16:$src2, addr:$src1)>; +def : Pat<(X86cmov (loadi32 addr:$src1), GR32:$src2, X86_COND_O, EFLAGS), + (CMOVNO32rm GR32:$src2, addr:$src1)>; +def : Pat<(X86cmov (loadi16 addr:$src1), GR16:$src2, X86_COND_NO, EFLAGS), + (CMOVO16rm GR16:$src2, addr:$src1)>; +def : Pat<(X86cmov (loadi32 addr:$src1), GR32:$src2, X86_COND_NO, EFLAGS), + (CMOVO32rm GR32:$src2, addr:$src1)>; + +// zextload bool -> zextload byte +def : Pat<(zextloadi8i1 addr:$src), (MOV8rm addr:$src)>; +def : Pat<(zextloadi16i1 addr:$src), (MOVZX16rm8 addr:$src)>; +def : Pat<(zextloadi32i1 addr:$src), (MOVZX32rm8 addr:$src)>; + +// extload bool -> extload byte +def : Pat<(extloadi8i1 addr:$src), (MOV8rm addr:$src)>; +def : Pat<(extloadi16i1 addr:$src), (MOVZX16rm8 addr:$src)>; +def : Pat<(extloadi32i1 addr:$src), (MOVZX32rm8 addr:$src)>; +def : Pat<(extloadi16i8 addr:$src), (MOVZX16rm8 addr:$src)>; +def : Pat<(extloadi32i8 addr:$src), (MOVZX32rm8 addr:$src)>; +def : Pat<(extloadi32i16 addr:$src), (MOVZX32rm16 addr:$src)>; + +// anyext. Define these to do an explicit zero-extend to +// avoid partial-register updates. +def : Pat<(i16 (anyext GR8 :$src)), (MOVZX16rr8 GR8 :$src)>; +def : Pat<(i32 (anyext GR8 :$src)), (MOVZX32rr8 GR8 :$src)>; +def : Pat<(i32 (anyext GR16:$src)), (MOVZX32rr16 GR16:$src)>; + +// (and (i32 load), 255) -> (zextload i8) +def : Pat<(i32 (and (nvloadi32 addr:$src), (i32 255))), + (MOVZX32rm8 addr:$src)>; +def : Pat<(i32 (and (nvloadi32 addr:$src), (i32 65535))), + (MOVZX32rm16 addr:$src)>; + +//===----------------------------------------------------------------------===// +// Some peepholes +//===----------------------------------------------------------------------===// + +// Odd encoding trick: -128 fits into an 8-bit immediate field while +// +128 doesn't, so in this special case use a sub instead of an add. +def : Pat<(add GR16:$src1, 128), + (SUB16ri8 GR16:$src1, -128)>; +def : Pat<(store (add (loadi16 addr:$dst), 128), addr:$dst), + (SUB16mi8 addr:$dst, -128)>; +def : Pat<(add GR32:$src1, 128), + (SUB32ri8 GR32:$src1, -128)>; +def : Pat<(store (add (loadi32 addr:$dst), 128), addr:$dst), + (SUB32mi8 addr:$dst, -128)>; + +// r & (2^16-1) ==> movz +def : Pat<(and GR32:$src1, 0xffff), + (MOVZX32rr16 (EXTRACT_SUBREG GR32:$src1, x86_subreg_16bit))>; +// r & (2^8-1) ==> movz +def : Pat<(and GR32:$src1, 0xff), + (MOVZX32rr8 (EXTRACT_SUBREG (i32 (COPY_TO_REGCLASS GR32:$src1, + GR32_ABCD)), + x86_subreg_8bit))>, + Requires<[In32BitMode]>; +// r & (2^8-1) ==> movz +def : Pat<(and GR16:$src1, 0xff), + (MOVZX16rr8 (EXTRACT_SUBREG (i16 (COPY_TO_REGCLASS GR16:$src1, + GR16_ABCD)), + x86_subreg_8bit))>, + Requires<[In32BitMode]>; + +// sext_inreg patterns +def : Pat<(sext_inreg GR32:$src, i16), + (MOVSX32rr16 (EXTRACT_SUBREG GR32:$src, x86_subreg_16bit))>; +def : Pat<(sext_inreg GR32:$src, i8), + (MOVSX32rr8 (EXTRACT_SUBREG (i32 (COPY_TO_REGCLASS GR32:$src, + GR32_ABCD)), + x86_subreg_8bit))>, + Requires<[In32BitMode]>; +def : Pat<(sext_inreg GR16:$src, i8), + (MOVSX16rr8 (EXTRACT_SUBREG (i16 (COPY_TO_REGCLASS GR16:$src, + GR16_ABCD)), + x86_subreg_8bit))>, + Requires<[In32BitMode]>; + +// trunc patterns +def : Pat<(i16 (trunc GR32:$src)), + (EXTRACT_SUBREG GR32:$src, x86_subreg_16bit)>; +def : Pat<(i8 (trunc GR32:$src)), + (EXTRACT_SUBREG (i32 (COPY_TO_REGCLASS GR32:$src, GR32_ABCD)), + x86_subreg_8bit)>, + Requires<[In32BitMode]>; +def : Pat<(i8 (trunc GR16:$src)), + (EXTRACT_SUBREG (i16 (COPY_TO_REGCLASS GR16:$src, GR16_ABCD)), + x86_subreg_8bit)>, + Requires<[In32BitMode]>; + +// h-register tricks +def : Pat<(i8 (trunc (srl_su GR16:$src, (i8 8)))), + (EXTRACT_SUBREG (i32 (COPY_TO_REGCLASS GR16:$src, GR16_ABCD)), + x86_subreg_8bit_hi)>, + Requires<[In32BitMode]>; +def : Pat<(i8 (trunc (srl_su GR32:$src, (i8 8)))), + (EXTRACT_SUBREG (i16 (COPY_TO_REGCLASS GR32:$src, GR32_ABCD)), + x86_subreg_8bit_hi)>, + Requires<[In32BitMode]>; +def : Pat<(srl_su GR16:$src, (i8 8)), + (EXTRACT_SUBREG + (MOVZX32rr8 + (EXTRACT_SUBREG (i16 (COPY_TO_REGCLASS GR16:$src, GR16_ABCD)), + x86_subreg_8bit_hi)), + x86_subreg_16bit)>, + Requires<[In32BitMode]>; +def : Pat<(i32 (zext (srl_su GR16:$src, (i8 8)))), + (MOVZX32rr8 (EXTRACT_SUBREG (i16 (COPY_TO_REGCLASS GR16:$src, GR16_ABCD)), + x86_subreg_8bit_hi))>, + Requires<[In32BitMode]>; +def : Pat<(i32 (anyext (srl_su GR16:$src, (i8 8)))), + (MOVZX32rr8 (EXTRACT_SUBREG (i16 (COPY_TO_REGCLASS GR16:$src, GR16_ABCD)), + x86_subreg_8bit_hi))>, + Requires<[In32BitMode]>; +def : Pat<(and (srl_su GR32:$src, (i8 8)), (i32 255)), + (MOVZX32rr8 (EXTRACT_SUBREG (i32 (COPY_TO_REGCLASS GR32:$src, GR32_ABCD)), + x86_subreg_8bit_hi))>, + Requires<[In32BitMode]>; + +// (shl x, 1) ==> (add x, x) +def : Pat<(shl GR8 :$src1, (i8 1)), (ADD8rr GR8 :$src1, GR8 :$src1)>; +def : Pat<(shl GR16:$src1, (i8 1)), (ADD16rr GR16:$src1, GR16:$src1)>; +def : Pat<(shl GR32:$src1, (i8 1)), (ADD32rr GR32:$src1, GR32:$src1)>; + +// (shl x (and y, 31)) ==> (shl x, y) +def : Pat<(shl GR8:$src1, (and CL:$amt, 31)), + (SHL8rCL GR8:$src1)>; +def : Pat<(shl GR16:$src1, (and CL:$amt, 31)), + (SHL16rCL GR16:$src1)>; +def : Pat<(shl GR32:$src1, (and CL:$amt, 31)), + (SHL32rCL GR32:$src1)>; +def : Pat<(store (shl (loadi8 addr:$dst), (and CL:$amt, 31)), addr:$dst), + (SHL8mCL addr:$dst)>; +def : Pat<(store (shl (loadi16 addr:$dst), (and CL:$amt, 31)), addr:$dst), + (SHL16mCL addr:$dst)>; +def : Pat<(store (shl (loadi32 addr:$dst), (and CL:$amt, 31)), addr:$dst), + (SHL32mCL addr:$dst)>; + +def : Pat<(srl GR8:$src1, (and CL:$amt, 31)), + (SHR8rCL GR8:$src1)>; +def : Pat<(srl GR16:$src1, (and CL:$amt, 31)), + (SHR16rCL GR16:$src1)>; +def : Pat<(srl GR32:$src1, (and CL:$amt, 31)), + (SHR32rCL GR32:$src1)>; +def : Pat<(store (srl (loadi8 addr:$dst), (and CL:$amt, 31)), addr:$dst), + (SHR8mCL addr:$dst)>; +def : Pat<(store (srl (loadi16 addr:$dst), (and CL:$amt, 31)), addr:$dst), + (SHR16mCL addr:$dst)>; +def : Pat<(store (srl (loadi32 addr:$dst), (and CL:$amt, 31)), addr:$dst), + (SHR32mCL addr:$dst)>; + +def : Pat<(sra GR8:$src1, (and CL:$amt, 31)), + (SAR8rCL GR8:$src1)>; +def : Pat<(sra GR16:$src1, (and CL:$amt, 31)), + (SAR16rCL GR16:$src1)>; +def : Pat<(sra GR32:$src1, (and CL:$amt, 31)), + (SAR32rCL GR32:$src1)>; +def : Pat<(store (sra (loadi8 addr:$dst), (and CL:$amt, 31)), addr:$dst), + (SAR8mCL addr:$dst)>; +def : Pat<(store (sra (loadi16 addr:$dst), (and CL:$amt, 31)), addr:$dst), + (SAR16mCL addr:$dst)>; +def : Pat<(store (sra (loadi32 addr:$dst), (and CL:$amt, 31)), addr:$dst), + (SAR32mCL addr:$dst)>; + +// (or (x >> c) | (y << (32 - c))) ==> (shrd32 x, y, c) +def : Pat<(or (srl GR32:$src1, CL:$amt), + (shl GR32:$src2, (sub 32, CL:$amt))), + (SHRD32rrCL GR32:$src1, GR32:$src2)>; + +def : Pat<(store (or (srl (loadi32 addr:$dst), CL:$amt), + (shl GR32:$src2, (sub 32, CL:$amt))), addr:$dst), + (SHRD32mrCL addr:$dst, GR32:$src2)>; + +def : Pat<(or (srl GR32:$src1, (i8 (trunc ECX:$amt))), + (shl GR32:$src2, (i8 (trunc (sub 32, ECX:$amt))))), + (SHRD32rrCL GR32:$src1, GR32:$src2)>; + +def : Pat<(store (or (srl (loadi32 addr:$dst), (i8 (trunc ECX:$amt))), + (shl GR32:$src2, (i8 (trunc (sub 32, ECX:$amt))))), + addr:$dst), + (SHRD32mrCL addr:$dst, GR32:$src2)>; + +def : Pat<(shrd GR32:$src1, (i8 imm:$amt1), GR32:$src2, (i8 imm:$amt2)), + (SHRD32rri8 GR32:$src1, GR32:$src2, (i8 imm:$amt1))>; + +def : Pat<(store (shrd (loadi32 addr:$dst), (i8 imm:$amt1), + GR32:$src2, (i8 imm:$amt2)), addr:$dst), + (SHRD32mri8 addr:$dst, GR32:$src2, (i8 imm:$amt1))>; + +// (or (x << c) | (y >> (32 - c))) ==> (shld32 x, y, c) +def : Pat<(or (shl GR32:$src1, CL:$amt), + (srl GR32:$src2, (sub 32, CL:$amt))), + (SHLD32rrCL GR32:$src1, GR32:$src2)>; + +def : Pat<(store (or (shl (loadi32 addr:$dst), CL:$amt), + (srl GR32:$src2, (sub 32, CL:$amt))), addr:$dst), + (SHLD32mrCL addr:$dst, GR32:$src2)>; + +def : Pat<(or (shl GR32:$src1, (i8 (trunc ECX:$amt))), + (srl GR32:$src2, (i8 (trunc (sub 32, ECX:$amt))))), + (SHLD32rrCL GR32:$src1, GR32:$src2)>; + +def : Pat<(store (or (shl (loadi32 addr:$dst), (i8 (trunc ECX:$amt))), + (srl GR32:$src2, (i8 (trunc (sub 32, ECX:$amt))))), + addr:$dst), + (SHLD32mrCL addr:$dst, GR32:$src2)>; + +def : Pat<(shld GR32:$src1, (i8 imm:$amt1), GR32:$src2, (i8 imm:$amt2)), + (SHLD32rri8 GR32:$src1, GR32:$src2, (i8 imm:$amt1))>; + +def : Pat<(store (shld (loadi32 addr:$dst), (i8 imm:$amt1), + GR32:$src2, (i8 imm:$amt2)), addr:$dst), + (SHLD32mri8 addr:$dst, GR32:$src2, (i8 imm:$amt1))>; + +// (or (x >> c) | (y << (16 - c))) ==> (shrd16 x, y, c) +def : Pat<(or (srl GR16:$src1, CL:$amt), + (shl GR16:$src2, (sub 16, CL:$amt))), + (SHRD16rrCL GR16:$src1, GR16:$src2)>; + +def : Pat<(store (or (srl (loadi16 addr:$dst), CL:$amt), + (shl GR16:$src2, (sub 16, CL:$amt))), addr:$dst), + (SHRD16mrCL addr:$dst, GR16:$src2)>; + +def : Pat<(or (srl GR16:$src1, (i8 (trunc CX:$amt))), + (shl GR16:$src2, (i8 (trunc (sub 16, CX:$amt))))), + (SHRD16rrCL GR16:$src1, GR16:$src2)>; + +def : Pat<(store (or (srl (loadi16 addr:$dst), (i8 (trunc CX:$amt))), + (shl GR16:$src2, (i8 (trunc (sub 16, CX:$amt))))), + addr:$dst), + (SHRD16mrCL addr:$dst, GR16:$src2)>; + +def : Pat<(shrd GR16:$src1, (i8 imm:$amt1), GR16:$src2, (i8 imm:$amt2)), + (SHRD16rri8 GR16:$src1, GR16:$src2, (i8 imm:$amt1))>; + +def : Pat<(store (shrd (loadi16 addr:$dst), (i8 imm:$amt1), + GR16:$src2, (i8 imm:$amt2)), addr:$dst), + (SHRD16mri8 addr:$dst, GR16:$src2, (i8 imm:$amt1))>; + +// (or (x << c) | (y >> (16 - c))) ==> (shld16 x, y, c) +def : Pat<(or (shl GR16:$src1, CL:$amt), + (srl GR16:$src2, (sub 16, CL:$amt))), + (SHLD16rrCL GR16:$src1, GR16:$src2)>; + +def : Pat<(store (or (shl (loadi16 addr:$dst), CL:$amt), + (srl GR16:$src2, (sub 16, CL:$amt))), addr:$dst), + (SHLD16mrCL addr:$dst, GR16:$src2)>; + +def : Pat<(or (shl GR16:$src1, (i8 (trunc CX:$amt))), + (srl GR16:$src2, (i8 (trunc (sub 16, CX:$amt))))), + (SHLD16rrCL GR16:$src1, GR16:$src2)>; + +def : Pat<(store (or (shl (loadi16 addr:$dst), (i8 (trunc CX:$amt))), + (srl GR16:$src2, (i8 (trunc (sub 16, CX:$amt))))), + addr:$dst), + (SHLD16mrCL addr:$dst, GR16:$src2)>; + +def : Pat<(shld GR16:$src1, (i8 imm:$amt1), GR16:$src2, (i8 imm:$amt2)), + (SHLD16rri8 GR16:$src1, GR16:$src2, (i8 imm:$amt1))>; + +def : Pat<(store (shld (loadi16 addr:$dst), (i8 imm:$amt1), + GR16:$src2, (i8 imm:$amt2)), addr:$dst), + (SHLD16mri8 addr:$dst, GR16:$src2, (i8 imm:$amt1))>; + +//===----------------------------------------------------------------------===// +// EFLAGS-defining Patterns +//===----------------------------------------------------------------------===// + +// Register-Register Addition with EFLAGS result +def : Pat<(parallel (X86add_flag GR8:$src1, GR8:$src2), + (implicit EFLAGS)), + (ADD8rr GR8:$src1, GR8:$src2)>; +def : Pat<(parallel (X86add_flag GR16:$src1, GR16:$src2), + (implicit EFLAGS)), + (ADD16rr GR16:$src1, GR16:$src2)>; +def : Pat<(parallel (X86add_flag GR32:$src1, GR32:$src2), + (implicit EFLAGS)), + (ADD32rr GR32:$src1, GR32:$src2)>; + +// Register-Memory Addition with EFLAGS result +def : Pat<(parallel (X86add_flag GR8:$src1, (loadi8 addr:$src2)), + (implicit EFLAGS)), + (ADD8rm GR8:$src1, addr:$src2)>; +def : Pat<(parallel (X86add_flag GR16:$src1, (loadi16 addr:$src2)), + (implicit EFLAGS)), + (ADD16rm GR16:$src1, addr:$src2)>; +def : Pat<(parallel (X86add_flag GR32:$src1, (loadi32 addr:$src2)), + (implicit EFLAGS)), + (ADD32rm GR32:$src1, addr:$src2)>; + +// Register-Integer Addition with EFLAGS result +def : Pat<(parallel (X86add_flag GR8:$src1, imm:$src2), + (implicit EFLAGS)), + (ADD8ri GR8:$src1, imm:$src2)>; +def : Pat<(parallel (X86add_flag GR16:$src1, imm:$src2), + (implicit EFLAGS)), + (ADD16ri GR16:$src1, imm:$src2)>; +def : Pat<(parallel (X86add_flag GR32:$src1, imm:$src2), + (implicit EFLAGS)), + (ADD32ri GR32:$src1, imm:$src2)>; +def : Pat<(parallel (X86add_flag GR16:$src1, i16immSExt8:$src2), + (implicit EFLAGS)), + (ADD16ri8 GR16:$src1, i16immSExt8:$src2)>; +def : Pat<(parallel (X86add_flag GR32:$src1, i32immSExt8:$src2), + (implicit EFLAGS)), + (ADD32ri8 GR32:$src1, i32immSExt8:$src2)>; + +// Memory-Register Addition with EFLAGS result +def : Pat<(parallel (store (X86add_flag (loadi8 addr:$dst), GR8:$src2), + addr:$dst), + (implicit EFLAGS)), + (ADD8mr addr:$dst, GR8:$src2)>; +def : Pat<(parallel (store (X86add_flag (loadi16 addr:$dst), GR16:$src2), + addr:$dst), + (implicit EFLAGS)), + (ADD16mr addr:$dst, GR16:$src2)>; +def : Pat<(parallel (store (X86add_flag (loadi32 addr:$dst), GR32:$src2), + addr:$dst), + (implicit EFLAGS)), + (ADD32mr addr:$dst, GR32:$src2)>; + +// Memory-Integer Addition with EFLAGS result +def : Pat<(parallel (store (X86add_flag (loadi8 addr:$dst), imm:$src2), + addr:$dst), + (implicit EFLAGS)), + (ADD8mi addr:$dst, imm:$src2)>; +def : Pat<(parallel (store (X86add_flag (loadi16 addr:$dst), imm:$src2), + addr:$dst), + (implicit EFLAGS)), + (ADD16mi addr:$dst, imm:$src2)>; +def : Pat<(parallel (store (X86add_flag (loadi32 addr:$dst), imm:$src2), + addr:$dst), + (implicit EFLAGS)), + (ADD32mi addr:$dst, imm:$src2)>; +def : Pat<(parallel (store (X86add_flag (loadi16 addr:$dst), i16immSExt8:$src2), + addr:$dst), + (implicit EFLAGS)), + (ADD16mi8 addr:$dst, i16immSExt8:$src2)>; +def : Pat<(parallel (store (X86add_flag (loadi32 addr:$dst), i32immSExt8:$src2), + addr:$dst), + (implicit EFLAGS)), + (ADD32mi8 addr:$dst, i32immSExt8:$src2)>; + +// Register-Register Subtraction with EFLAGS result +def : Pat<(parallel (X86sub_flag GR8:$src1, GR8:$src2), + (implicit EFLAGS)), + (SUB8rr GR8:$src1, GR8:$src2)>; +def : Pat<(parallel (X86sub_flag GR16:$src1, GR16:$src2), + (implicit EFLAGS)), + (SUB16rr GR16:$src1, GR16:$src2)>; +def : Pat<(parallel (X86sub_flag GR32:$src1, GR32:$src2), + (implicit EFLAGS)), + (SUB32rr GR32:$src1, GR32:$src2)>; + +// Register-Memory Subtraction with EFLAGS result +def : Pat<(parallel (X86sub_flag GR8:$src1, (loadi8 addr:$src2)), + (implicit EFLAGS)), + (SUB8rm GR8:$src1, addr:$src2)>; +def : Pat<(parallel (X86sub_flag GR16:$src1, (loadi16 addr:$src2)), + (implicit EFLAGS)), + (SUB16rm GR16:$src1, addr:$src2)>; +def : Pat<(parallel (X86sub_flag GR32:$src1, (loadi32 addr:$src2)), + (implicit EFLAGS)), + (SUB32rm GR32:$src1, addr:$src2)>; + +// Register-Integer Subtraction with EFLAGS result +def : Pat<(parallel (X86sub_flag GR8:$src1, imm:$src2), + (implicit EFLAGS)), + (SUB8ri GR8:$src1, imm:$src2)>; +def : Pat<(parallel (X86sub_flag GR16:$src1, imm:$src2), + (implicit EFLAGS)), + (SUB16ri GR16:$src1, imm:$src2)>; +def : Pat<(parallel (X86sub_flag GR32:$src1, imm:$src2), + (implicit EFLAGS)), + (SUB32ri GR32:$src1, imm:$src2)>; +def : Pat<(parallel (X86sub_flag GR16:$src1, i16immSExt8:$src2), + (implicit EFLAGS)), + (SUB16ri8 GR16:$src1, i16immSExt8:$src2)>; +def : Pat<(parallel (X86sub_flag GR32:$src1, i32immSExt8:$src2), + (implicit EFLAGS)), + (SUB32ri8 GR32:$src1, i32immSExt8:$src2)>; + +// Memory-Register Subtraction with EFLAGS result +def : Pat<(parallel (store (X86sub_flag (loadi8 addr:$dst), GR8:$src2), + addr:$dst), + (implicit EFLAGS)), + (SUB8mr addr:$dst, GR8:$src2)>; +def : Pat<(parallel (store (X86sub_flag (loadi16 addr:$dst), GR16:$src2), + addr:$dst), + (implicit EFLAGS)), + (SUB16mr addr:$dst, GR16:$src2)>; +def : Pat<(parallel (store (X86sub_flag (loadi32 addr:$dst), GR32:$src2), + addr:$dst), + (implicit EFLAGS)), + (SUB32mr addr:$dst, GR32:$src2)>; + +// Memory-Integer Subtraction with EFLAGS result +def : Pat<(parallel (store (X86sub_flag (loadi8 addr:$dst), imm:$src2), + addr:$dst), + (implicit EFLAGS)), + (SUB8mi addr:$dst, imm:$src2)>; +def : Pat<(parallel (store (X86sub_flag (loadi16 addr:$dst), imm:$src2), + addr:$dst), + (implicit EFLAGS)), + (SUB16mi addr:$dst, imm:$src2)>; +def : Pat<(parallel (store (X86sub_flag (loadi32 addr:$dst), imm:$src2), + addr:$dst), + (implicit EFLAGS)), + (SUB32mi addr:$dst, imm:$src2)>; +def : Pat<(parallel (store (X86sub_flag (loadi16 addr:$dst), i16immSExt8:$src2), + addr:$dst), + (implicit EFLAGS)), + (SUB16mi8 addr:$dst, i16immSExt8:$src2)>; +def : Pat<(parallel (store (X86sub_flag (loadi32 addr:$dst), i32immSExt8:$src2), + addr:$dst), + (implicit EFLAGS)), + (SUB32mi8 addr:$dst, i32immSExt8:$src2)>; + + +// Register-Register Signed Integer Multiply with EFLAGS result +def : Pat<(parallel (X86smul_flag GR16:$src1, GR16:$src2), + (implicit EFLAGS)), + (IMUL16rr GR16:$src1, GR16:$src2)>; +def : Pat<(parallel (X86smul_flag GR32:$src1, GR32:$src2), + (implicit EFLAGS)), + (IMUL32rr GR32:$src1, GR32:$src2)>; + +// Register-Memory Signed Integer Multiply with EFLAGS result +def : Pat<(parallel (X86smul_flag GR16:$src1, (loadi16 addr:$src2)), + (implicit EFLAGS)), + (IMUL16rm GR16:$src1, addr:$src2)>; +def : Pat<(parallel (X86smul_flag GR32:$src1, (loadi32 addr:$src2)), + (implicit EFLAGS)), + (IMUL32rm GR32:$src1, addr:$src2)>; + +// Register-Integer Signed Integer Multiply with EFLAGS result +def : Pat<(parallel (X86smul_flag GR16:$src1, imm:$src2), + (implicit EFLAGS)), + (IMUL16rri GR16:$src1, imm:$src2)>; +def : Pat<(parallel (X86smul_flag GR32:$src1, imm:$src2), + (implicit EFLAGS)), + (IMUL32rri GR32:$src1, imm:$src2)>; +def : Pat<(parallel (X86smul_flag GR16:$src1, i16immSExt8:$src2), + (implicit EFLAGS)), + (IMUL16rri8 GR16:$src1, i16immSExt8:$src2)>; +def : Pat<(parallel (X86smul_flag GR32:$src1, i32immSExt8:$src2), + (implicit EFLAGS)), + (IMUL32rri8 GR32:$src1, i32immSExt8:$src2)>; + +// Memory-Integer Signed Integer Multiply with EFLAGS result +def : Pat<(parallel (X86smul_flag (loadi16 addr:$src1), imm:$src2), + (implicit EFLAGS)), + (IMUL16rmi addr:$src1, imm:$src2)>; +def : Pat<(parallel (X86smul_flag (loadi32 addr:$src1), imm:$src2), + (implicit EFLAGS)), + (IMUL32rmi addr:$src1, imm:$src2)>; +def : Pat<(parallel (X86smul_flag (loadi16 addr:$src1), i16immSExt8:$src2), + (implicit EFLAGS)), + (IMUL16rmi8 addr:$src1, i16immSExt8:$src2)>; +def : Pat<(parallel (X86smul_flag (loadi32 addr:$src1), i32immSExt8:$src2), + (implicit EFLAGS)), + (IMUL32rmi8 addr:$src1, i32immSExt8:$src2)>; + +// Optimize multiply by 2 with EFLAGS result. +let AddedComplexity = 2 in { +def : Pat<(parallel (X86smul_flag GR16:$src1, 2), + (implicit EFLAGS)), + (ADD16rr GR16:$src1, GR16:$src1)>; + +def : Pat<(parallel (X86smul_flag GR32:$src1, 2), + (implicit EFLAGS)), + (ADD32rr GR32:$src1, GR32:$src1)>; +} + +// INC and DEC with EFLAGS result. Note that these do not set CF. +def : Pat<(parallel (X86inc_flag GR8:$src), (implicit EFLAGS)), + (INC8r GR8:$src)>; +def : Pat<(parallel (store (i8 (X86inc_flag (loadi8 addr:$dst))), addr:$dst), + (implicit EFLAGS)), + (INC8m addr:$dst)>; +def : Pat<(parallel (X86dec_flag GR8:$src), (implicit EFLAGS)), + (DEC8r GR8:$src)>; +def : Pat<(parallel (store (i8 (X86dec_flag (loadi8 addr:$dst))), addr:$dst), + (implicit EFLAGS)), + (DEC8m addr:$dst)>; + +def : Pat<(parallel (X86inc_flag GR16:$src), (implicit EFLAGS)), + (INC16r GR16:$src)>, Requires<[In32BitMode]>; +def : Pat<(parallel (store (i16 (X86inc_flag (loadi16 addr:$dst))), addr:$dst), + (implicit EFLAGS)), + (INC16m addr:$dst)>, Requires<[In32BitMode]>; +def : Pat<(parallel (X86dec_flag GR16:$src), (implicit EFLAGS)), + (DEC16r GR16:$src)>, Requires<[In32BitMode]>; +def : Pat<(parallel (store (i16 (X86dec_flag (loadi16 addr:$dst))), addr:$dst), + (implicit EFLAGS)), + (DEC16m addr:$dst)>, Requires<[In32BitMode]>; + +def : Pat<(parallel (X86inc_flag GR32:$src), (implicit EFLAGS)), + (INC32r GR32:$src)>, Requires<[In32BitMode]>; +def : Pat<(parallel (store (i32 (X86inc_flag (loadi32 addr:$dst))), addr:$dst), + (implicit EFLAGS)), + (INC32m addr:$dst)>, Requires<[In32BitMode]>; +def : Pat<(parallel (X86dec_flag GR32:$src), (implicit EFLAGS)), + (DEC32r GR32:$src)>, Requires<[In32BitMode]>; +def : Pat<(parallel (store (i32 (X86dec_flag (loadi32 addr:$dst))), addr:$dst), + (implicit EFLAGS)), + (DEC32m addr:$dst)>, Requires<[In32BitMode]>; + +// Register-Register Or with EFLAGS result +def : Pat<(parallel (X86or_flag GR8:$src1, GR8:$src2), + (implicit EFLAGS)), + (OR8rr GR8:$src1, GR8:$src2)>; +def : Pat<(parallel (X86or_flag GR16:$src1, GR16:$src2), + (implicit EFLAGS)), + (OR16rr GR16:$src1, GR16:$src2)>; +def : Pat<(parallel (X86or_flag GR32:$src1, GR32:$src2), + (implicit EFLAGS)), + (OR32rr GR32:$src1, GR32:$src2)>; + +// Register-Memory Or with EFLAGS result +def : Pat<(parallel (X86or_flag GR8:$src1, (loadi8 addr:$src2)), + (implicit EFLAGS)), + (OR8rm GR8:$src1, addr:$src2)>; +def : Pat<(parallel (X86or_flag GR16:$src1, (loadi16 addr:$src2)), + (implicit EFLAGS)), + (OR16rm GR16:$src1, addr:$src2)>; +def : Pat<(parallel (X86or_flag GR32:$src1, (loadi32 addr:$src2)), + (implicit EFLAGS)), + (OR32rm GR32:$src1, addr:$src2)>; + +// Register-Integer Or with EFLAGS result +def : Pat<(parallel (X86or_flag GR8:$src1, imm:$src2), + (implicit EFLAGS)), + (OR8ri GR8:$src1, imm:$src2)>; +def : Pat<(parallel (X86or_flag GR16:$src1, imm:$src2), + (implicit EFLAGS)), + (OR16ri GR16:$src1, imm:$src2)>; +def : Pat<(parallel (X86or_flag GR32:$src1, imm:$src2), + (implicit EFLAGS)), + (OR32ri GR32:$src1, imm:$src2)>; +def : Pat<(parallel (X86or_flag GR16:$src1, i16immSExt8:$src2), + (implicit EFLAGS)), + (OR16ri8 GR16:$src1, i16immSExt8:$src2)>; +def : Pat<(parallel (X86or_flag GR32:$src1, i32immSExt8:$src2), + (implicit EFLAGS)), + (OR32ri8 GR32:$src1, i32immSExt8:$src2)>; + +// Memory-Register Or with EFLAGS result +def : Pat<(parallel (store (X86or_flag (loadi8 addr:$dst), GR8:$src2), + addr:$dst), + (implicit EFLAGS)), + (OR8mr addr:$dst, GR8:$src2)>; +def : Pat<(parallel (store (X86or_flag (loadi16 addr:$dst), GR16:$src2), + addr:$dst), + (implicit EFLAGS)), + (OR16mr addr:$dst, GR16:$src2)>; +def : Pat<(parallel (store (X86or_flag (loadi32 addr:$dst), GR32:$src2), + addr:$dst), + (implicit EFLAGS)), + (OR32mr addr:$dst, GR32:$src2)>; + +// Memory-Integer Or with EFLAGS result +def : Pat<(parallel (store (X86or_flag (loadi8 addr:$dst), imm:$src2), + addr:$dst), + (implicit EFLAGS)), + (OR8mi addr:$dst, imm:$src2)>; +def : Pat<(parallel (store (X86or_flag (loadi16 addr:$dst), imm:$src2), + addr:$dst), + (implicit EFLAGS)), + (OR16mi addr:$dst, imm:$src2)>; +def : Pat<(parallel (store (X86or_flag (loadi32 addr:$dst), imm:$src2), + addr:$dst), + (implicit EFLAGS)), + (OR32mi addr:$dst, imm:$src2)>; +def : Pat<(parallel (store (X86or_flag (loadi16 addr:$dst), i16immSExt8:$src2), + addr:$dst), + (implicit EFLAGS)), + (OR16mi8 addr:$dst, i16immSExt8:$src2)>; +def : Pat<(parallel (store (X86or_flag (loadi32 addr:$dst), i32immSExt8:$src2), + addr:$dst), + (implicit EFLAGS)), + (OR32mi8 addr:$dst, i32immSExt8:$src2)>; + +// Register-Register XOr with EFLAGS result +def : Pat<(parallel (X86xor_flag GR8:$src1, GR8:$src2), + (implicit EFLAGS)), + (XOR8rr GR8:$src1, GR8:$src2)>; +def : Pat<(parallel (X86xor_flag GR16:$src1, GR16:$src2), + (implicit EFLAGS)), + (XOR16rr GR16:$src1, GR16:$src2)>; +def : Pat<(parallel (X86xor_flag GR32:$src1, GR32:$src2), + (implicit EFLAGS)), + (XOR32rr GR32:$src1, GR32:$src2)>; + +// Register-Memory XOr with EFLAGS result +def : Pat<(parallel (X86xor_flag GR8:$src1, (loadi8 addr:$src2)), + (implicit EFLAGS)), + (XOR8rm GR8:$src1, addr:$src2)>; +def : Pat<(parallel (X86xor_flag GR16:$src1, (loadi16 addr:$src2)), + (implicit EFLAGS)), + (XOR16rm GR16:$src1, addr:$src2)>; +def : Pat<(parallel (X86xor_flag GR32:$src1, (loadi32 addr:$src2)), + (implicit EFLAGS)), + (XOR32rm GR32:$src1, addr:$src2)>; + +// Register-Integer XOr with EFLAGS result +def : Pat<(parallel (X86xor_flag GR8:$src1, imm:$src2), + (implicit EFLAGS)), + (XOR8ri GR8:$src1, imm:$src2)>; +def : Pat<(parallel (X86xor_flag GR16:$src1, imm:$src2), + (implicit EFLAGS)), + (XOR16ri GR16:$src1, imm:$src2)>; +def : Pat<(parallel (X86xor_flag GR32:$src1, imm:$src2), + (implicit EFLAGS)), + (XOR32ri GR32:$src1, imm:$src2)>; +def : Pat<(parallel (X86xor_flag GR16:$src1, i16immSExt8:$src2), + (implicit EFLAGS)), + (XOR16ri8 GR16:$src1, i16immSExt8:$src2)>; +def : Pat<(parallel (X86xor_flag GR32:$src1, i32immSExt8:$src2), + (implicit EFLAGS)), + (XOR32ri8 GR32:$src1, i32immSExt8:$src2)>; + +// Memory-Register XOr with EFLAGS result +def : Pat<(parallel (store (X86xor_flag (loadi8 addr:$dst), GR8:$src2), + addr:$dst), + (implicit EFLAGS)), + (XOR8mr addr:$dst, GR8:$src2)>; +def : Pat<(parallel (store (X86xor_flag (loadi16 addr:$dst), GR16:$src2), + addr:$dst), + (implicit EFLAGS)), + (XOR16mr addr:$dst, GR16:$src2)>; +def : Pat<(parallel (store (X86xor_flag (loadi32 addr:$dst), GR32:$src2), + addr:$dst), + (implicit EFLAGS)), + (XOR32mr addr:$dst, GR32:$src2)>; + +// Memory-Integer XOr with EFLAGS result +def : Pat<(parallel (store (X86xor_flag (loadi8 addr:$dst), imm:$src2), + addr:$dst), + (implicit EFLAGS)), + (XOR8mi addr:$dst, imm:$src2)>; +def : Pat<(parallel (store (X86xor_flag (loadi16 addr:$dst), imm:$src2), + addr:$dst), + (implicit EFLAGS)), + (XOR16mi addr:$dst, imm:$src2)>; +def : Pat<(parallel (store (X86xor_flag (loadi32 addr:$dst), imm:$src2), + addr:$dst), + (implicit EFLAGS)), + (XOR32mi addr:$dst, imm:$src2)>; +def : Pat<(parallel (store (X86xor_flag (loadi16 addr:$dst), i16immSExt8:$src2), + addr:$dst), + (implicit EFLAGS)), + (XOR16mi8 addr:$dst, i16immSExt8:$src2)>; +def : Pat<(parallel (store (X86xor_flag (loadi32 addr:$dst), i32immSExt8:$src2), + addr:$dst), + (implicit EFLAGS)), + (XOR32mi8 addr:$dst, i32immSExt8:$src2)>; + +// Register-Register And with EFLAGS result +def : Pat<(parallel (X86and_flag GR8:$src1, GR8:$src2), + (implicit EFLAGS)), + (AND8rr GR8:$src1, GR8:$src2)>; +def : Pat<(parallel (X86and_flag GR16:$src1, GR16:$src2), + (implicit EFLAGS)), + (AND16rr GR16:$src1, GR16:$src2)>; +def : Pat<(parallel (X86and_flag GR32:$src1, GR32:$src2), + (implicit EFLAGS)), + (AND32rr GR32:$src1, GR32:$src2)>; + +// Register-Memory And with EFLAGS result +def : Pat<(parallel (X86and_flag GR8:$src1, (loadi8 addr:$src2)), + (implicit EFLAGS)), + (AND8rm GR8:$src1, addr:$src2)>; +def : Pat<(parallel (X86and_flag GR16:$src1, (loadi16 addr:$src2)), + (implicit EFLAGS)), + (AND16rm GR16:$src1, addr:$src2)>; +def : Pat<(parallel (X86and_flag GR32:$src1, (loadi32 addr:$src2)), + (implicit EFLAGS)), + (AND32rm GR32:$src1, addr:$src2)>; + +// Register-Integer And with EFLAGS result +def : Pat<(parallel (X86and_flag GR8:$src1, imm:$src2), + (implicit EFLAGS)), + (AND8ri GR8:$src1, imm:$src2)>; +def : Pat<(parallel (X86and_flag GR16:$src1, imm:$src2), + (implicit EFLAGS)), + (AND16ri GR16:$src1, imm:$src2)>; +def : Pat<(parallel (X86and_flag GR32:$src1, imm:$src2), + (implicit EFLAGS)), + (AND32ri GR32:$src1, imm:$src2)>; +def : Pat<(parallel (X86and_flag GR16:$src1, i16immSExt8:$src2), + (implicit EFLAGS)), + (AND16ri8 GR16:$src1, i16immSExt8:$src2)>; +def : Pat<(parallel (X86and_flag GR32:$src1, i32immSExt8:$src2), + (implicit EFLAGS)), + (AND32ri8 GR32:$src1, i32immSExt8:$src2)>; + +// Memory-Register And with EFLAGS result +def : Pat<(parallel (store (X86and_flag (loadi8 addr:$dst), GR8:$src2), + addr:$dst), + (implicit EFLAGS)), + (AND8mr addr:$dst, GR8:$src2)>; +def : Pat<(parallel (store (X86and_flag (loadi16 addr:$dst), GR16:$src2), + addr:$dst), + (implicit EFLAGS)), + (AND16mr addr:$dst, GR16:$src2)>; +def : Pat<(parallel (store (X86and_flag (loadi32 addr:$dst), GR32:$src2), + addr:$dst), + (implicit EFLAGS)), + (AND32mr addr:$dst, GR32:$src2)>; + +// Memory-Integer And with EFLAGS result +def : Pat<(parallel (store (X86and_flag (loadi8 addr:$dst), imm:$src2), + addr:$dst), + (implicit EFLAGS)), + (AND8mi addr:$dst, imm:$src2)>; +def : Pat<(parallel (store (X86and_flag (loadi16 addr:$dst), imm:$src2), + addr:$dst), + (implicit EFLAGS)), + (AND16mi addr:$dst, imm:$src2)>; +def : Pat<(parallel (store (X86and_flag (loadi32 addr:$dst), imm:$src2), + addr:$dst), + (implicit EFLAGS)), + (AND32mi addr:$dst, imm:$src2)>; +def : Pat<(parallel (store (X86and_flag (loadi16 addr:$dst), i16immSExt8:$src2), + addr:$dst), + (implicit EFLAGS)), + (AND16mi8 addr:$dst, i16immSExt8:$src2)>; +def : Pat<(parallel (store (X86and_flag (loadi32 addr:$dst), i32immSExt8:$src2), + addr:$dst), + (implicit EFLAGS)), + (AND32mi8 addr:$dst, i32immSExt8:$src2)>; + +// -disable-16bit support. +def : Pat<(truncstorei16 (i32 imm:$src), addr:$dst), + (MOV16mi addr:$dst, imm:$src)>; +def : Pat<(truncstorei16 GR32:$src, addr:$dst), + (MOV16mr addr:$dst, (EXTRACT_SUBREG GR32:$src, x86_subreg_16bit))>; +def : Pat<(i32 (sextloadi16 addr:$dst)), + (MOVSX32rm16 addr:$dst)>; +def : Pat<(i32 (zextloadi16 addr:$dst)), + (MOVZX32rm16 addr:$dst)>; +def : Pat<(i32 (extloadi16 addr:$dst)), + (MOVZX32rm16 addr:$dst)>; + +//===----------------------------------------------------------------------===// +// Floating Point Stack Support +//===----------------------------------------------------------------------===// + +include "X86InstrFPStack.td" + +//===----------------------------------------------------------------------===// +// X86-64 Support +//===----------------------------------------------------------------------===// + +include "X86Instr64bit.td" + +//===----------------------------------------------------------------------===// +// XMM Floating point support (requires SSE / SSE2) +//===----------------------------------------------------------------------===// + +include "X86InstrSSE.td" + +//===----------------------------------------------------------------------===// +// MMX and XMM Packed Integer support (requires MMX, SSE, and SSE2) +//===----------------------------------------------------------------------===// + +include "X86InstrMMX.td" diff --git a/libclamav/c++/llvm/lib/Target/X86/X86InstrMMX.td b/libclamav/c++/llvm/lib/Target/X86/X86InstrMMX.td new file mode 100644 index 000000000..500785b99 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/X86/X86InstrMMX.td @@ -0,0 +1,718 @@ +//====- X86InstrMMX.td - Describe the X86 Instruction Set --*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file describes the X86 MMX instruction set, defining the instructions, +// and properties of the instructions which are needed for code generation, +// machine code emission, and analysis. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// MMX Pattern Fragments +//===----------------------------------------------------------------------===// + +def load_mmx : PatFrag<(ops node:$ptr), (v1i64 (load node:$ptr))>; + +def bc_v8i8 : PatFrag<(ops node:$in), (v8i8 (bitconvert node:$in))>; +def bc_v4i16 : PatFrag<(ops node:$in), (v4i16 (bitconvert node:$in))>; +def bc_v2i32 : PatFrag<(ops node:$in), (v2i32 (bitconvert node:$in))>; +def bc_v1i64 : PatFrag<(ops node:$in), (v1i64 (bitconvert node:$in))>; + +//===----------------------------------------------------------------------===// +// MMX Masks +//===----------------------------------------------------------------------===// + +// MMX_SHUFFLE_get_shuf_imm xform function: convert vector_shuffle mask to +// PSHUFW imm. +def MMX_SHUFFLE_get_shuf_imm : SDNodeXForm; + +// Patterns for: vector_shuffle v1, v2, <2, 6, 3, 7, ...> +def mmx_unpckh : PatFrag<(ops node:$lhs, node:$rhs), + (vector_shuffle node:$lhs, node:$rhs), [{ + return X86::isUNPCKHMask(cast(N)); +}]>; + +// Patterns for: vector_shuffle v1, v2, <0, 4, 2, 5, ...> +def mmx_unpckl : PatFrag<(ops node:$lhs, node:$rhs), + (vector_shuffle node:$lhs, node:$rhs), [{ + return X86::isUNPCKLMask(cast(N)); +}]>; + +// Patterns for: vector_shuffle v1, , <0, 0, 1, 1, ...> +def mmx_unpckh_undef : PatFrag<(ops node:$lhs, node:$rhs), + (vector_shuffle node:$lhs, node:$rhs), [{ + return X86::isUNPCKH_v_undef_Mask(cast(N)); +}]>; + +// Patterns for: vector_shuffle v1, , <2, 2, 3, 3, ...> +def mmx_unpckl_undef : PatFrag<(ops node:$lhs, node:$rhs), + (vector_shuffle node:$lhs, node:$rhs), [{ + return X86::isUNPCKL_v_undef_Mask(cast(N)); +}]>; + +def mmx_pshufw : PatFrag<(ops node:$lhs, node:$rhs), + (vector_shuffle node:$lhs, node:$rhs), [{ + return X86::isPSHUFDMask(cast(N)); +}], MMX_SHUFFLE_get_shuf_imm>; + +//===----------------------------------------------------------------------===// +// MMX Multiclasses +//===----------------------------------------------------------------------===// + +let Constraints = "$src1 = $dst" in { + // MMXI_binop_rm - Simple MMX binary operator. + multiclass MMXI_binop_rm opc, string OpcodeStr, SDNode OpNode, + ValueType OpVT, bit Commutable = 0> { + def rr : MMXI { + let isCommutable = Commutable; + } + def rm : MMXI; + } + + multiclass MMXI_binop_rm_int opc, string OpcodeStr, Intrinsic IntId, + bit Commutable = 0> { + def rr : MMXI { + let isCommutable = Commutable; + } + def rm : MMXI; + } + + // MMXI_binop_rm_v1i64 - Simple MMX binary operator whose type is v1i64. + // + // FIXME: we could eliminate this and use MMXI_binop_rm instead if tblgen knew + // to collapse (bitconvert VT to VT) into its operand. + // + multiclass MMXI_binop_rm_v1i64 opc, string OpcodeStr, SDNode OpNode, + bit Commutable = 0> { + def rr : MMXI { + let isCommutable = Commutable; + } + def rm : MMXI; + } + + multiclass MMXI_binop_rmi_int opc, bits<8> opc2, Format ImmForm, + string OpcodeStr, Intrinsic IntId, + Intrinsic IntId2> { + def rr : MMXI; + def rm : MMXI; + def ri : MMXIi8; + } +} + +//===----------------------------------------------------------------------===// +// MMX EMMS & FEMMS Instructions +//===----------------------------------------------------------------------===// + +def MMX_EMMS : MMXI<0x77, RawFrm, (outs), (ins), "emms", + [(int_x86_mmx_emms)]>; +def MMX_FEMMS : MMXI<0x0E, RawFrm, (outs), (ins), "femms", + [(int_x86_mmx_femms)]>; + +//===----------------------------------------------------------------------===// +// MMX Scalar Instructions +//===----------------------------------------------------------------------===// + +// Data Transfer Instructions +def MMX_MOVD64rr : MMXI<0x6E, MRMSrcReg, (outs VR64:$dst), (ins GR32:$src), + "movd\t{$src, $dst|$dst, $src}", + [(set VR64:$dst, + (v2i32 (scalar_to_vector GR32:$src)))]>; +let canFoldAsLoad = 1, isReMaterializable = 1 in +def MMX_MOVD64rm : MMXI<0x6E, MRMSrcMem, (outs VR64:$dst), (ins i32mem:$src), + "movd\t{$src, $dst|$dst, $src}", + [(set VR64:$dst, + (v2i32 (scalar_to_vector (loadi32 addr:$src))))]>; +let mayStore = 1 in +def MMX_MOVD64mr : MMXI<0x7E, MRMDestMem, (outs), (ins i32mem:$dst, VR64:$src), + "movd\t{$src, $dst|$dst, $src}", []>; + +let neverHasSideEffects = 1 in +def MMX_MOVD64to64rr : MMXRI<0x6E, MRMSrcReg, (outs VR64:$dst), (ins GR64:$src), + "movd\t{$src, $dst|$dst, $src}", + []>; + +let neverHasSideEffects = 1 in +// These are 64 bit moves, but since the OS X assembler doesn't +// recognize a register-register movq, we write them as +// movd. +def MMX_MOVD64from64rr : MMXRI<0x7E, MRMDestReg, + (outs GR64:$dst), (ins VR64:$src), + "movd\t{$src, $dst|$dst, $src}", []>; +def MMX_MOVD64rrv164 : MMXI<0x6E, MRMSrcReg, (outs VR64:$dst), (ins GR64:$src), + "movd\t{$src, $dst|$dst, $src}", + [(set VR64:$dst, + (v1i64 (scalar_to_vector GR64:$src)))]>; + +let neverHasSideEffects = 1 in +def MMX_MOVQ64rr : MMXI<0x6F, MRMSrcReg, (outs VR64:$dst), (ins VR64:$src), + "movq\t{$src, $dst|$dst, $src}", []>; +let canFoldAsLoad = 1, isReMaterializable = 1, mayHaveSideEffects = 1 in +def MMX_MOVQ64rm : MMXI<0x6F, MRMSrcMem, (outs VR64:$dst), (ins i64mem:$src), + "movq\t{$src, $dst|$dst, $src}", + [(set VR64:$dst, (load_mmx addr:$src))]>; +def MMX_MOVQ64mr : MMXI<0x7F, MRMDestMem, (outs), (ins i64mem:$dst, VR64:$src), + "movq\t{$src, $dst|$dst, $src}", + [(store (v1i64 VR64:$src), addr:$dst)]>; + +def MMX_MOVDQ2Qrr : SDIi8<0xD6, MRMSrcReg, (outs VR64:$dst), (ins VR128:$src), + "movdq2q\t{$src, $dst|$dst, $src}", + [(set VR64:$dst, + (v1i64 (bitconvert + (i64 (vector_extract (v2i64 VR128:$src), + (iPTR 0))))))]>; + +def MMX_MOVQ2DQrr : SSDIi8<0xD6, MRMSrcReg, (outs VR128:$dst), (ins VR64:$src), + "movq2dq\t{$src, $dst|$dst, $src}", + [(set VR128:$dst, + (movl immAllZerosV, + (v2i64 (scalar_to_vector (i64 (bitconvert VR64:$src))))))]>; + +let neverHasSideEffects = 1 in +def MMX_MOVQ2FR64rr: SSDIi8<0xD6, MRMSrcReg, (outs FR64:$dst), (ins VR64:$src), + "movq2dq\t{$src, $dst|$dst, $src}", []>; + +def MMX_MOVNTQmr : MMXI<0xE7, MRMDestMem, (outs), (ins i64mem:$dst, VR64:$src), + "movntq\t{$src, $dst|$dst, $src}", + [(int_x86_mmx_movnt_dq addr:$dst, VR64:$src)]>; + +let AddedComplexity = 15 in +// movd to MMX register zero-extends +def MMX_MOVZDI2PDIrr : MMXI<0x6E, MRMSrcReg, (outs VR64:$dst), (ins GR32:$src), + "movd\t{$src, $dst|$dst, $src}", + [(set VR64:$dst, + (v2i32 (X86vzmovl (v2i32 (scalar_to_vector GR32:$src)))))]>; +let AddedComplexity = 20 in +def MMX_MOVZDI2PDIrm : MMXI<0x6E, MRMSrcMem, (outs VR64:$dst), + (ins i32mem:$src), + "movd\t{$src, $dst|$dst, $src}", + [(set VR64:$dst, + (v2i32 (X86vzmovl (v2i32 + (scalar_to_vector (loadi32 addr:$src))))))]>; + +// Arithmetic Instructions + +// -- Addition +defm MMX_PADDB : MMXI_binop_rm<0xFC, "paddb", add, v8i8, 1>; +defm MMX_PADDW : MMXI_binop_rm<0xFD, "paddw", add, v4i16, 1>; +defm MMX_PADDD : MMXI_binop_rm<0xFE, "paddd", add, v2i32, 1>; +defm MMX_PADDQ : MMXI_binop_rm<0xD4, "paddq", add, v1i64, 1>; + +defm MMX_PADDSB : MMXI_binop_rm_int<0xEC, "paddsb" , int_x86_mmx_padds_b, 1>; +defm MMX_PADDSW : MMXI_binop_rm_int<0xED, "paddsw" , int_x86_mmx_padds_w, 1>; + +defm MMX_PADDUSB : MMXI_binop_rm_int<0xDC, "paddusb", int_x86_mmx_paddus_b, 1>; +defm MMX_PADDUSW : MMXI_binop_rm_int<0xDD, "paddusw", int_x86_mmx_paddus_w, 1>; + +// -- Subtraction +defm MMX_PSUBB : MMXI_binop_rm<0xF8, "psubb", sub, v8i8>; +defm MMX_PSUBW : MMXI_binop_rm<0xF9, "psubw", sub, v4i16>; +defm MMX_PSUBD : MMXI_binop_rm<0xFA, "psubd", sub, v2i32>; +defm MMX_PSUBQ : MMXI_binop_rm<0xFB, "psubq", sub, v1i64>; + +defm MMX_PSUBSB : MMXI_binop_rm_int<0xE8, "psubsb" , int_x86_mmx_psubs_b>; +defm MMX_PSUBSW : MMXI_binop_rm_int<0xE9, "psubsw" , int_x86_mmx_psubs_w>; + +defm MMX_PSUBUSB : MMXI_binop_rm_int<0xD8, "psubusb", int_x86_mmx_psubus_b>; +defm MMX_PSUBUSW : MMXI_binop_rm_int<0xD9, "psubusw", int_x86_mmx_psubus_w>; + +// -- Multiplication +defm MMX_PMULLW : MMXI_binop_rm<0xD5, "pmullw", mul, v4i16, 1>; + +defm MMX_PMULHW : MMXI_binop_rm_int<0xE5, "pmulhw", int_x86_mmx_pmulh_w, 1>; +defm MMX_PMULHUW : MMXI_binop_rm_int<0xE4, "pmulhuw", int_x86_mmx_pmulhu_w, 1>; +defm MMX_PMULUDQ : MMXI_binop_rm_int<0xF4, "pmuludq", int_x86_mmx_pmulu_dq, 1>; + +// -- Miscellanea +defm MMX_PMADDWD : MMXI_binop_rm_int<0xF5, "pmaddwd", int_x86_mmx_pmadd_wd, 1>; + +defm MMX_PAVGB : MMXI_binop_rm_int<0xE0, "pavgb", int_x86_mmx_pavg_b, 1>; +defm MMX_PAVGW : MMXI_binop_rm_int<0xE3, "pavgw", int_x86_mmx_pavg_w, 1>; + +defm MMX_PMINUB : MMXI_binop_rm_int<0xDA, "pminub", int_x86_mmx_pminu_b, 1>; +defm MMX_PMINSW : MMXI_binop_rm_int<0xEA, "pminsw", int_x86_mmx_pmins_w, 1>; + +defm MMX_PMAXUB : MMXI_binop_rm_int<0xDE, "pmaxub", int_x86_mmx_pmaxu_b, 1>; +defm MMX_PMAXSW : MMXI_binop_rm_int<0xEE, "pmaxsw", int_x86_mmx_pmaxs_w, 1>; + +defm MMX_PSADBW : MMXI_binop_rm_int<0xF6, "psadbw", int_x86_mmx_psad_bw, 1>; + +// Logical Instructions +defm MMX_PAND : MMXI_binop_rm_v1i64<0xDB, "pand", and, 1>; +defm MMX_POR : MMXI_binop_rm_v1i64<0xEB, "por" , or, 1>; +defm MMX_PXOR : MMXI_binop_rm_v1i64<0xEF, "pxor", xor, 1>; + +let Constraints = "$src1 = $dst" in { + def MMX_PANDNrr : MMXI<0xDF, MRMSrcReg, + (outs VR64:$dst), (ins VR64:$src1, VR64:$src2), + "pandn\t{$src2, $dst|$dst, $src2}", + [(set VR64:$dst, (v1i64 (and (vnot VR64:$src1), + VR64:$src2)))]>; + def MMX_PANDNrm : MMXI<0xDF, MRMSrcMem, + (outs VR64:$dst), (ins VR64:$src1, i64mem:$src2), + "pandn\t{$src2, $dst|$dst, $src2}", + [(set VR64:$dst, (v1i64 (and (vnot VR64:$src1), + (load addr:$src2))))]>; +} + +// Shift Instructions +defm MMX_PSRLW : MMXI_binop_rmi_int<0xD1, 0x71, MRM2r, "psrlw", + int_x86_mmx_psrl_w, int_x86_mmx_psrli_w>; +defm MMX_PSRLD : MMXI_binop_rmi_int<0xD2, 0x72, MRM2r, "psrld", + int_x86_mmx_psrl_d, int_x86_mmx_psrli_d>; +defm MMX_PSRLQ : MMXI_binop_rmi_int<0xD3, 0x73, MRM2r, "psrlq", + int_x86_mmx_psrl_q, int_x86_mmx_psrli_q>; + +defm MMX_PSLLW : MMXI_binop_rmi_int<0xF1, 0x71, MRM6r, "psllw", + int_x86_mmx_psll_w, int_x86_mmx_pslli_w>; +defm MMX_PSLLD : MMXI_binop_rmi_int<0xF2, 0x72, MRM6r, "pslld", + int_x86_mmx_psll_d, int_x86_mmx_pslli_d>; +defm MMX_PSLLQ : MMXI_binop_rmi_int<0xF3, 0x73, MRM6r, "psllq", + int_x86_mmx_psll_q, int_x86_mmx_pslli_q>; + +defm MMX_PSRAW : MMXI_binop_rmi_int<0xE1, 0x71, MRM4r, "psraw", + int_x86_mmx_psra_w, int_x86_mmx_psrai_w>; +defm MMX_PSRAD : MMXI_binop_rmi_int<0xE2, 0x72, MRM4r, "psrad", + int_x86_mmx_psra_d, int_x86_mmx_psrai_d>; + +// Shift up / down and insert zero's. +def : Pat<(v1i64 (X86vshl VR64:$src, (i8 imm:$amt))), + (v1i64 (MMX_PSLLQri VR64:$src, imm:$amt))>; +def : Pat<(v1i64 (X86vshr VR64:$src, (i8 imm:$amt))), + (v1i64 (MMX_PSRLQri VR64:$src, imm:$amt))>; + +// Comparison Instructions +defm MMX_PCMPEQB : MMXI_binop_rm_int<0x74, "pcmpeqb", int_x86_mmx_pcmpeq_b>; +defm MMX_PCMPEQW : MMXI_binop_rm_int<0x75, "pcmpeqw", int_x86_mmx_pcmpeq_w>; +defm MMX_PCMPEQD : MMXI_binop_rm_int<0x76, "pcmpeqd", int_x86_mmx_pcmpeq_d>; + +defm MMX_PCMPGTB : MMXI_binop_rm_int<0x64, "pcmpgtb", int_x86_mmx_pcmpgt_b>; +defm MMX_PCMPGTW : MMXI_binop_rm_int<0x65, "pcmpgtw", int_x86_mmx_pcmpgt_w>; +defm MMX_PCMPGTD : MMXI_binop_rm_int<0x66, "pcmpgtd", int_x86_mmx_pcmpgt_d>; + +// Conversion Instructions + +// -- Unpack Instructions +let Constraints = "$src1 = $dst" in { + // Unpack High Packed Data Instructions + def MMX_PUNPCKHBWrr : MMXI<0x68, MRMSrcReg, + (outs VR64:$dst), (ins VR64:$src1, VR64:$src2), + "punpckhbw\t{$src2, $dst|$dst, $src2}", + [(set VR64:$dst, + (v8i8 (mmx_unpckh VR64:$src1, VR64:$src2)))]>; + def MMX_PUNPCKHBWrm : MMXI<0x68, MRMSrcMem, + (outs VR64:$dst), (ins VR64:$src1, i64mem:$src2), + "punpckhbw\t{$src2, $dst|$dst, $src2}", + [(set VR64:$dst, + (v8i8 (mmx_unpckh VR64:$src1, + (bc_v8i8 (load_mmx addr:$src2)))))]>; + + def MMX_PUNPCKHWDrr : MMXI<0x69, MRMSrcReg, + (outs VR64:$dst), (ins VR64:$src1, VR64:$src2), + "punpckhwd\t{$src2, $dst|$dst, $src2}", + [(set VR64:$dst, + (v4i16 (mmx_unpckh VR64:$src1, VR64:$src2)))]>; + def MMX_PUNPCKHWDrm : MMXI<0x69, MRMSrcMem, + (outs VR64:$dst), (ins VR64:$src1, i64mem:$src2), + "punpckhwd\t{$src2, $dst|$dst, $src2}", + [(set VR64:$dst, + (v4i16 (mmx_unpckh VR64:$src1, + (bc_v4i16 (load_mmx addr:$src2)))))]>; + + def MMX_PUNPCKHDQrr : MMXI<0x6A, MRMSrcReg, + (outs VR64:$dst), (ins VR64:$src1, VR64:$src2), + "punpckhdq\t{$src2, $dst|$dst, $src2}", + [(set VR64:$dst, + (v2i32 (mmx_unpckh VR64:$src1, VR64:$src2)))]>; + def MMX_PUNPCKHDQrm : MMXI<0x6A, MRMSrcMem, + (outs VR64:$dst), (ins VR64:$src1, i64mem:$src2), + "punpckhdq\t{$src2, $dst|$dst, $src2}", + [(set VR64:$dst, + (v2i32 (mmx_unpckh VR64:$src1, + (bc_v2i32 (load_mmx addr:$src2)))))]>; + + // Unpack Low Packed Data Instructions + def MMX_PUNPCKLBWrr : MMXI<0x60, MRMSrcReg, + (outs VR64:$dst), (ins VR64:$src1, VR64:$src2), + "punpcklbw\t{$src2, $dst|$dst, $src2}", + [(set VR64:$dst, + (v8i8 (mmx_unpckl VR64:$src1, VR64:$src2)))]>; + def MMX_PUNPCKLBWrm : MMXI<0x60, MRMSrcMem, + (outs VR64:$dst), (ins VR64:$src1, i64mem:$src2), + "punpcklbw\t{$src2, $dst|$dst, $src2}", + [(set VR64:$dst, + (v8i8 (mmx_unpckl VR64:$src1, + (bc_v8i8 (load_mmx addr:$src2)))))]>; + + def MMX_PUNPCKLWDrr : MMXI<0x61, MRMSrcReg, + (outs VR64:$dst), (ins VR64:$src1, VR64:$src2), + "punpcklwd\t{$src2, $dst|$dst, $src2}", + [(set VR64:$dst, + (v4i16 (mmx_unpckl VR64:$src1, VR64:$src2)))]>; + def MMX_PUNPCKLWDrm : MMXI<0x61, MRMSrcMem, + (outs VR64:$dst), (ins VR64:$src1, i64mem:$src2), + "punpcklwd\t{$src2, $dst|$dst, $src2}", + [(set VR64:$dst, + (v4i16 (mmx_unpckl VR64:$src1, + (bc_v4i16 (load_mmx addr:$src2)))))]>; + + def MMX_PUNPCKLDQrr : MMXI<0x62, MRMSrcReg, + (outs VR64:$dst), (ins VR64:$src1, VR64:$src2), + "punpckldq\t{$src2, $dst|$dst, $src2}", + [(set VR64:$dst, + (v2i32 (mmx_unpckl VR64:$src1, VR64:$src2)))]>; + def MMX_PUNPCKLDQrm : MMXI<0x62, MRMSrcMem, + (outs VR64:$dst), (ins VR64:$src1, i64mem:$src2), + "punpckldq\t{$src2, $dst|$dst, $src2}", + [(set VR64:$dst, + (v2i32 (mmx_unpckl VR64:$src1, + (bc_v2i32 (load_mmx addr:$src2)))))]>; +} + +// -- Pack Instructions +defm MMX_PACKSSWB : MMXI_binop_rm_int<0x63, "packsswb", int_x86_mmx_packsswb>; +defm MMX_PACKSSDW : MMXI_binop_rm_int<0x6B, "packssdw", int_x86_mmx_packssdw>; +defm MMX_PACKUSWB : MMXI_binop_rm_int<0x67, "packuswb", int_x86_mmx_packuswb>; + +// -- Shuffle Instructions +def MMX_PSHUFWri : MMXIi8<0x70, MRMSrcReg, + (outs VR64:$dst), (ins VR64:$src1, i8imm:$src2), + "pshufw\t{$src2, $src1, $dst|$dst, $src1, $src2}", + [(set VR64:$dst, + (v4i16 (mmx_pshufw:$src2 VR64:$src1, (undef))))]>; +def MMX_PSHUFWmi : MMXIi8<0x70, MRMSrcMem, + (outs VR64:$dst), (ins i64mem:$src1, i8imm:$src2), + "pshufw\t{$src2, $src1, $dst|$dst, $src1, $src2}", + [(set VR64:$dst, + (mmx_pshufw:$src2 (bc_v4i16 (load_mmx addr:$src1)), + (undef)))]>; + +// -- Conversion Instructions +let neverHasSideEffects = 1 in { +def MMX_CVTPD2PIrr : MMX2I<0x2D, MRMSrcReg, (outs VR64:$dst), (ins VR128:$src), + "cvtpd2pi\t{$src, $dst|$dst, $src}", []>; +let mayLoad = 1 in +def MMX_CVTPD2PIrm : MMX2I<0x2D, MRMSrcMem, (outs VR64:$dst), + (ins f128mem:$src), + "cvtpd2pi\t{$src, $dst|$dst, $src}", []>; + +def MMX_CVTPI2PDrr : MMX2I<0x2A, MRMSrcReg, (outs VR128:$dst), (ins VR64:$src), + "cvtpi2pd\t{$src, $dst|$dst, $src}", []>; +let mayLoad = 1 in +def MMX_CVTPI2PDrm : MMX2I<0x2A, MRMSrcMem, (outs VR128:$dst), + (ins i64mem:$src), + "cvtpi2pd\t{$src, $dst|$dst, $src}", []>; + +def MMX_CVTPI2PSrr : MMXI<0x2A, MRMSrcReg, (outs VR128:$dst), (ins VR64:$src), + "cvtpi2ps\t{$src, $dst|$dst, $src}", []>; +let mayLoad = 1 in +def MMX_CVTPI2PSrm : MMXI<0x2A, MRMSrcMem, (outs VR128:$dst), + (ins i64mem:$src), + "cvtpi2ps\t{$src, $dst|$dst, $src}", []>; + +def MMX_CVTPS2PIrr : MMXI<0x2D, MRMSrcReg, (outs VR64:$dst), (ins VR128:$src), + "cvtps2pi\t{$src, $dst|$dst, $src}", []>; +let mayLoad = 1 in +def MMX_CVTPS2PIrm : MMXI<0x2D, MRMSrcMem, (outs VR64:$dst), (ins f64mem:$src), + "cvtps2pi\t{$src, $dst|$dst, $src}", []>; + +def MMX_CVTTPD2PIrr : MMX2I<0x2C, MRMSrcReg, (outs VR64:$dst), (ins VR128:$src), + "cvttpd2pi\t{$src, $dst|$dst, $src}", []>; +let mayLoad = 1 in +def MMX_CVTTPD2PIrm : MMX2I<0x2C, MRMSrcMem, (outs VR64:$dst), + (ins f128mem:$src), + "cvttpd2pi\t{$src, $dst|$dst, $src}", []>; + +def MMX_CVTTPS2PIrr : MMXI<0x2C, MRMSrcReg, (outs VR64:$dst), (ins VR128:$src), + "cvttps2pi\t{$src, $dst|$dst, $src}", []>; +let mayLoad = 1 in +def MMX_CVTTPS2PIrm : MMXI<0x2C, MRMSrcMem, (outs VR64:$dst), (ins f64mem:$src), + "cvttps2pi\t{$src, $dst|$dst, $src}", []>; +} // end neverHasSideEffects + + +// Extract / Insert +def MMX_X86pextrw : SDNode<"X86ISD::PEXTRW", SDTypeProfile<1, 2, []>, []>; +def MMX_X86pinsrw : SDNode<"X86ISD::PINSRW", SDTypeProfile<1, 3, []>, []>; + +def MMX_PEXTRWri : MMXIi8<0xC5, MRMSrcReg, + (outs GR32:$dst), (ins VR64:$src1, i16i8imm:$src2), + "pextrw\t{$src2, $src1, $dst|$dst, $src1, $src2}", + [(set GR32:$dst, (MMX_X86pextrw (v4i16 VR64:$src1), + (iPTR imm:$src2)))]>; +let Constraints = "$src1 = $dst" in { + def MMX_PINSRWrri : MMXIi8<0xC4, MRMSrcReg, + (outs VR64:$dst), (ins VR64:$src1, GR32:$src2, + i16i8imm:$src3), + "pinsrw\t{$src3, $src2, $dst|$dst, $src2, $src3}", + [(set VR64:$dst, (v4i16 (MMX_X86pinsrw (v4i16 VR64:$src1), + GR32:$src2,(iPTR imm:$src3))))]>; + def MMX_PINSRWrmi : MMXIi8<0xC4, MRMSrcMem, + (outs VR64:$dst), (ins VR64:$src1, i16mem:$src2, + i16i8imm:$src3), + "pinsrw\t{$src3, $src2, $dst|$dst, $src2, $src3}", + [(set VR64:$dst, + (v4i16 (MMX_X86pinsrw (v4i16 VR64:$src1), + (i32 (anyext (loadi16 addr:$src2))), + (iPTR imm:$src3))))]>; +} + +// Mask creation +def MMX_PMOVMSKBrr : MMXI<0xD7, MRMSrcReg, (outs GR32:$dst), (ins VR64:$src), + "pmovmskb\t{$src, $dst|$dst, $src}", + [(set GR32:$dst, (int_x86_mmx_pmovmskb VR64:$src))]>; + +// Misc. +let Uses = [EDI] in +def MMX_MASKMOVQ : MMXI<0xF7, MRMSrcReg, (outs), (ins VR64:$src, VR64:$mask), + "maskmovq\t{$mask, $src|$src, $mask}", + [(int_x86_mmx_maskmovq VR64:$src, VR64:$mask, EDI)]>; +let Uses = [RDI] in +def MMX_MASKMOVQ64: MMXI64<0xF7, MRMSrcReg, (outs), (ins VR64:$src, VR64:$mask), + "maskmovq\t{$mask, $src|$src, $mask}", + [(int_x86_mmx_maskmovq VR64:$src, VR64:$mask, RDI)]>; + +//===----------------------------------------------------------------------===// +// Alias Instructions +//===----------------------------------------------------------------------===// + +// Alias instructions that map zero vector to pxor. +let isReMaterializable = 1, isCodeGenOnly = 1 in { + def MMX_V_SET0 : MMXI<0xEF, MRMInitReg, (outs VR64:$dst), (ins), + "pxor\t$dst, $dst", + [(set VR64:$dst, (v2i32 immAllZerosV))]>; + def MMX_V_SETALLONES : MMXI<0x76, MRMInitReg, (outs VR64:$dst), (ins), + "pcmpeqd\t$dst, $dst", + [(set VR64:$dst, (v2i32 immAllOnesV))]>; +} + +let Predicates = [HasMMX] in { + def : Pat<(v1i64 immAllZerosV), (MMX_V_SET0)>; + def : Pat<(v4i16 immAllZerosV), (MMX_V_SET0)>; + def : Pat<(v8i8 immAllZerosV), (MMX_V_SET0)>; +} + +//===----------------------------------------------------------------------===// +// Non-Instruction Patterns +//===----------------------------------------------------------------------===// + +// Store 64-bit integer vector values. +def : Pat<(store (v8i8 VR64:$src), addr:$dst), + (MMX_MOVQ64mr addr:$dst, VR64:$src)>; +def : Pat<(store (v4i16 VR64:$src), addr:$dst), + (MMX_MOVQ64mr addr:$dst, VR64:$src)>; +def : Pat<(store (v2i32 VR64:$src), addr:$dst), + (MMX_MOVQ64mr addr:$dst, VR64:$src)>; +def : Pat<(store (v2f32 VR64:$src), addr:$dst), + (MMX_MOVQ64mr addr:$dst, VR64:$src)>; +def : Pat<(store (v1i64 VR64:$src), addr:$dst), + (MMX_MOVQ64mr addr:$dst, VR64:$src)>; + +// Bit convert. +def : Pat<(v8i8 (bitconvert (v1i64 VR64:$src))), (v8i8 VR64:$src)>; +def : Pat<(v8i8 (bitconvert (v2i32 VR64:$src))), (v8i8 VR64:$src)>; +def : Pat<(v8i8 (bitconvert (v2f32 VR64:$src))), (v8i8 VR64:$src)>; +def : Pat<(v8i8 (bitconvert (v4i16 VR64:$src))), (v8i8 VR64:$src)>; +def : Pat<(v4i16 (bitconvert (v1i64 VR64:$src))), (v4i16 VR64:$src)>; +def : Pat<(v4i16 (bitconvert (v2i32 VR64:$src))), (v4i16 VR64:$src)>; +def : Pat<(v4i16 (bitconvert (v2f32 VR64:$src))), (v4i16 VR64:$src)>; +def : Pat<(v4i16 (bitconvert (v8i8 VR64:$src))), (v4i16 VR64:$src)>; +def : Pat<(v2i32 (bitconvert (v1i64 VR64:$src))), (v2i32 VR64:$src)>; +def : Pat<(v2i32 (bitconvert (v2f32 VR64:$src))), (v2i32 VR64:$src)>; +def : Pat<(v2i32 (bitconvert (v4i16 VR64:$src))), (v2i32 VR64:$src)>; +def : Pat<(v2i32 (bitconvert (v8i8 VR64:$src))), (v2i32 VR64:$src)>; +def : Pat<(v2f32 (bitconvert (v1i64 VR64:$src))), (v2f32 VR64:$src)>; +def : Pat<(v2f32 (bitconvert (v2i32 VR64:$src))), (v2f32 VR64:$src)>; +def : Pat<(v2f32 (bitconvert (v4i16 VR64:$src))), (v2f32 VR64:$src)>; +def : Pat<(v2f32 (bitconvert (v8i8 VR64:$src))), (v2f32 VR64:$src)>; +def : Pat<(v1i64 (bitconvert (v2i32 VR64:$src))), (v1i64 VR64:$src)>; +def : Pat<(v1i64 (bitconvert (v2f32 VR64:$src))), (v1i64 VR64:$src)>; +def : Pat<(v1i64 (bitconvert (v4i16 VR64:$src))), (v1i64 VR64:$src)>; +def : Pat<(v1i64 (bitconvert (v8i8 VR64:$src))), (v1i64 VR64:$src)>; + +// 64-bit bit convert. +def : Pat<(v1i64 (bitconvert (i64 GR64:$src))), + (MMX_MOVD64to64rr GR64:$src)>; +def : Pat<(v2i32 (bitconvert (i64 GR64:$src))), + (MMX_MOVD64to64rr GR64:$src)>; +def : Pat<(v2f32 (bitconvert (i64 GR64:$src))), + (MMX_MOVD64to64rr GR64:$src)>; +def : Pat<(v4i16 (bitconvert (i64 GR64:$src))), + (MMX_MOVD64to64rr GR64:$src)>; +def : Pat<(v8i8 (bitconvert (i64 GR64:$src))), + (MMX_MOVD64to64rr GR64:$src)>; +def : Pat<(i64 (bitconvert (v1i64 VR64:$src))), + (MMX_MOVD64from64rr VR64:$src)>; +def : Pat<(i64 (bitconvert (v2i32 VR64:$src))), + (MMX_MOVD64from64rr VR64:$src)>; +def : Pat<(i64 (bitconvert (v2f32 VR64:$src))), + (MMX_MOVD64from64rr VR64:$src)>; +def : Pat<(i64 (bitconvert (v4i16 VR64:$src))), + (MMX_MOVD64from64rr VR64:$src)>; +def : Pat<(i64 (bitconvert (v8i8 VR64:$src))), + (MMX_MOVD64from64rr VR64:$src)>; +def : Pat<(f64 (bitconvert (v1i64 VR64:$src))), + (MMX_MOVQ2FR64rr VR64:$src)>; +def : Pat<(f64 (bitconvert (v2i32 VR64:$src))), + (MMX_MOVQ2FR64rr VR64:$src)>; +def : Pat<(f64 (bitconvert (v4i16 VR64:$src))), + (MMX_MOVQ2FR64rr VR64:$src)>; +def : Pat<(f64 (bitconvert (v8i8 VR64:$src))), + (MMX_MOVQ2FR64rr VR64:$src)>; + +let AddedComplexity = 20 in { + def : Pat<(v2i32 (X86vzmovl (bc_v2i32 (load_mmx addr:$src)))), + (MMX_MOVZDI2PDIrm addr:$src)>; +} + +// Clear top half. +let AddedComplexity = 15 in { + def : Pat<(v2i32 (X86vzmovl VR64:$src)), + (MMX_PUNPCKLDQrr VR64:$src, (MMX_V_SET0))>; +} + +// Patterns to perform canonical versions of vector shuffling. +let AddedComplexity = 10 in { + def : Pat<(v8i8 (mmx_unpckl_undef VR64:$src, (undef))), + (MMX_PUNPCKLBWrr VR64:$src, VR64:$src)>; + def : Pat<(v4i16 (mmx_unpckl_undef VR64:$src, (undef))), + (MMX_PUNPCKLWDrr VR64:$src, VR64:$src)>; + def : Pat<(v2i32 (mmx_unpckl_undef VR64:$src, (undef))), + (MMX_PUNPCKLDQrr VR64:$src, VR64:$src)>; +} + +let AddedComplexity = 10 in { + def : Pat<(v8i8 (mmx_unpckh_undef VR64:$src, (undef))), + (MMX_PUNPCKHBWrr VR64:$src, VR64:$src)>; + def : Pat<(v4i16 (mmx_unpckh_undef VR64:$src, (undef))), + (MMX_PUNPCKHWDrr VR64:$src, VR64:$src)>; + def : Pat<(v2i32 (mmx_unpckh_undef VR64:$src, (undef))), + (MMX_PUNPCKHDQrr VR64:$src, VR64:$src)>; +} + +// Patterns to perform vector shuffling with a zeroed out vector. +let AddedComplexity = 20 in { + def : Pat<(bc_v2i32 (mmx_unpckl immAllZerosV, + (v2i32 (scalar_to_vector (load_mmx addr:$src))))), + (MMX_PUNPCKLDQrm VR64:$src, VR64:$src)>; +} + +// Some special case PANDN patterns. +// FIXME: Get rid of these. +def : Pat<(v1i64 (and (xor VR64:$src1, (bc_v1i64 (v2i32 immAllOnesV))), + VR64:$src2)), + (MMX_PANDNrr VR64:$src1, VR64:$src2)>; +def : Pat<(v1i64 (and (xor VR64:$src1, (bc_v1i64 (v4i16 immAllOnesV_bc))), + VR64:$src2)), + (MMX_PANDNrr VR64:$src1, VR64:$src2)>; +def : Pat<(v1i64 (and (xor VR64:$src1, (bc_v1i64 (v8i8 immAllOnesV_bc))), + VR64:$src2)), + (MMX_PANDNrr VR64:$src1, VR64:$src2)>; + +def : Pat<(v1i64 (and (xor VR64:$src1, (bc_v1i64 (v2i32 immAllOnesV))), + (load addr:$src2))), + (MMX_PANDNrm VR64:$src1, addr:$src2)>; +def : Pat<(v1i64 (and (xor VR64:$src1, (bc_v1i64 (v4i16 immAllOnesV_bc))), + (load addr:$src2))), + (MMX_PANDNrm VR64:$src1, addr:$src2)>; +def : Pat<(v1i64 (and (xor VR64:$src1, (bc_v1i64 (v8i8 immAllOnesV_bc))), + (load addr:$src2))), + (MMX_PANDNrm VR64:$src1, addr:$src2)>; + +// Move MMX to lower 64-bit of XMM +def : Pat<(v2i64 (scalar_to_vector (i64 (bitconvert (v8i8 VR64:$src))))), + (v2i64 (MMX_MOVQ2DQrr VR64:$src))>; +def : Pat<(v2i64 (scalar_to_vector (i64 (bitconvert (v4i16 VR64:$src))))), + (v2i64 (MMX_MOVQ2DQrr VR64:$src))>; +def : Pat<(v2i64 (scalar_to_vector (i64 (bitconvert (v2i32 VR64:$src))))), + (v2i64 (MMX_MOVQ2DQrr VR64:$src))>; +def : Pat<(v2i64 (scalar_to_vector (i64 (bitconvert (v1i64 VR64:$src))))), + (v2i64 (MMX_MOVQ2DQrr VR64:$src))>; + +// Move lower 64-bit of XMM to MMX. +def : Pat<(v2i32 (bitconvert (i64 (vector_extract (v2i64 VR128:$src), + (iPTR 0))))), + (v2i32 (MMX_MOVDQ2Qrr VR128:$src))>; +def : Pat<(v4i16 (bitconvert (i64 (vector_extract (v2i64 VR128:$src), + (iPTR 0))))), + (v4i16 (MMX_MOVDQ2Qrr VR128:$src))>; +def : Pat<(v8i8 (bitconvert (i64 (vector_extract (v2i64 VR128:$src), + (iPTR 0))))), + (v8i8 (MMX_MOVDQ2Qrr VR128:$src))>; + +// Patterns for vector comparisons +def : Pat<(v8i8 (X86pcmpeqb VR64:$src1, VR64:$src2)), + (MMX_PCMPEQBrr VR64:$src1, VR64:$src2)>; +def : Pat<(v8i8 (X86pcmpeqb VR64:$src1, (bitconvert (load_mmx addr:$src2)))), + (MMX_PCMPEQBrm VR64:$src1, addr:$src2)>; +def : Pat<(v4i16 (X86pcmpeqw VR64:$src1, VR64:$src2)), + (MMX_PCMPEQWrr VR64:$src1, VR64:$src2)>; +def : Pat<(v4i16 (X86pcmpeqw VR64:$src1, (bitconvert (load_mmx addr:$src2)))), + (MMX_PCMPEQWrm VR64:$src1, addr:$src2)>; +def : Pat<(v2i32 (X86pcmpeqd VR64:$src1, VR64:$src2)), + (MMX_PCMPEQDrr VR64:$src1, VR64:$src2)>; +def : Pat<(v2i32 (X86pcmpeqd VR64:$src1, (bitconvert (load_mmx addr:$src2)))), + (MMX_PCMPEQDrm VR64:$src1, addr:$src2)>; + +def : Pat<(v8i8 (X86pcmpgtb VR64:$src1, VR64:$src2)), + (MMX_PCMPGTBrr VR64:$src1, VR64:$src2)>; +def : Pat<(v8i8 (X86pcmpgtb VR64:$src1, (bitconvert (load_mmx addr:$src2)))), + (MMX_PCMPGTBrm VR64:$src1, addr:$src2)>; +def : Pat<(v4i16 (X86pcmpgtw VR64:$src1, VR64:$src2)), + (MMX_PCMPGTWrr VR64:$src1, VR64:$src2)>; +def : Pat<(v4i16 (X86pcmpgtw VR64:$src1, (bitconvert (load_mmx addr:$src2)))), + (MMX_PCMPGTWrm VR64:$src1, addr:$src2)>; +def : Pat<(v2i32 (X86pcmpgtd VR64:$src1, VR64:$src2)), + (MMX_PCMPGTDrr VR64:$src1, VR64:$src2)>; +def : Pat<(v2i32 (X86pcmpgtd VR64:$src1, (bitconvert (load_mmx addr:$src2)))), + (MMX_PCMPGTDrm VR64:$src1, addr:$src2)>; + +// CMOV* - Used to implement the SELECT DAG operation. Expanded after +// instruction selection into a branch sequence. +let Uses = [EFLAGS], usesCustomInserter = 1 in { + def CMOV_V1I64 : I<0, Pseudo, + (outs VR64:$dst), (ins VR64:$t, VR64:$f, i8imm:$cond), + "#CMOV_V1I64 PSEUDO!", + [(set VR64:$dst, + (v1i64 (X86cmov VR64:$t, VR64:$f, imm:$cond, + EFLAGS)))]>; +} diff --git a/libclamav/c++/llvm/lib/Target/X86/X86InstrSSE.td b/libclamav/c++/llvm/lib/Target/X86/X86InstrSSE.td new file mode 100644 index 000000000..dfdd4ce36 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/X86/X86InstrSSE.td @@ -0,0 +1,3896 @@ +//====- X86InstrSSE.td - Describe the X86 Instruction Set --*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file describes the X86 SSE instruction set, defining the instructions, +// and properties of the instructions which are needed for code generation, +// machine code emission, and analysis. +// +//===----------------------------------------------------------------------===// + + +//===----------------------------------------------------------------------===// +// SSE specific DAG Nodes. +//===----------------------------------------------------------------------===// + +def SDTX86FPShiftOp : SDTypeProfile<1, 2, [ SDTCisSameAs<0, 1>, + SDTCisFP<0>, SDTCisInt<2> ]>; +def SDTX86VFCMP : SDTypeProfile<1, 3, [SDTCisInt<0>, SDTCisSameAs<1, 2>, + SDTCisFP<1>, SDTCisVT<3, i8>]>; + +def X86fmin : SDNode<"X86ISD::FMIN", SDTFPBinOp>; +def X86fmax : SDNode<"X86ISD::FMAX", SDTFPBinOp>; +def X86fand : SDNode<"X86ISD::FAND", SDTFPBinOp, + [SDNPCommutative, SDNPAssociative]>; +def X86for : SDNode<"X86ISD::FOR", SDTFPBinOp, + [SDNPCommutative, SDNPAssociative]>; +def X86fxor : SDNode<"X86ISD::FXOR", SDTFPBinOp, + [SDNPCommutative, SDNPAssociative]>; +def X86frsqrt : SDNode<"X86ISD::FRSQRT", SDTFPUnaryOp>; +def X86frcp : SDNode<"X86ISD::FRCP", SDTFPUnaryOp>; +def X86fsrl : SDNode<"X86ISD::FSRL", SDTX86FPShiftOp>; +def X86comi : SDNode<"X86ISD::COMI", SDTX86CmpTest>; +def X86ucomi : SDNode<"X86ISD::UCOMI", SDTX86CmpTest>; +def X86pshufb : SDNode<"X86ISD::PSHUFB", + SDTypeProfile<1, 2, [SDTCisVT<0, v16i8>, SDTCisSameAs<0,1>, + SDTCisSameAs<0,2>]>>; +def X86pextrb : SDNode<"X86ISD::PEXTRB", + SDTypeProfile<1, 2, [SDTCisVT<0, i32>, SDTCisPtrTy<2>]>>; +def X86pextrw : SDNode<"X86ISD::PEXTRW", + SDTypeProfile<1, 2, [SDTCisVT<0, i32>, SDTCisPtrTy<2>]>>; +def X86pinsrb : SDNode<"X86ISD::PINSRB", + SDTypeProfile<1, 3, [SDTCisVT<0, v16i8>, SDTCisSameAs<0,1>, + SDTCisVT<2, i32>, SDTCisPtrTy<3>]>>; +def X86pinsrw : SDNode<"X86ISD::PINSRW", + SDTypeProfile<1, 3, [SDTCisVT<0, v8i16>, SDTCisSameAs<0,1>, + SDTCisVT<2, i32>, SDTCisPtrTy<3>]>>; +def X86insrtps : SDNode<"X86ISD::INSERTPS", + SDTypeProfile<1, 3, [SDTCisVT<0, v4f32>, SDTCisSameAs<0,1>, + SDTCisVT<2, v4f32>, SDTCisPtrTy<3>]>>; +def X86vzmovl : SDNode<"X86ISD::VZEXT_MOVL", + SDTypeProfile<1, 1, [SDTCisSameAs<0,1>]>>; +def X86vzload : SDNode<"X86ISD::VZEXT_LOAD", SDTLoad, + [SDNPHasChain, SDNPMayLoad]>; +def X86vshl : SDNode<"X86ISD::VSHL", SDTIntShiftOp>; +def X86vshr : SDNode<"X86ISD::VSRL", SDTIntShiftOp>; +def X86cmpps : SDNode<"X86ISD::CMPPS", SDTX86VFCMP>; +def X86cmppd : SDNode<"X86ISD::CMPPD", SDTX86VFCMP>; +def X86pcmpeqb : SDNode<"X86ISD::PCMPEQB", SDTIntBinOp, [SDNPCommutative]>; +def X86pcmpeqw : SDNode<"X86ISD::PCMPEQW", SDTIntBinOp, [SDNPCommutative]>; +def X86pcmpeqd : SDNode<"X86ISD::PCMPEQD", SDTIntBinOp, [SDNPCommutative]>; +def X86pcmpeqq : SDNode<"X86ISD::PCMPEQQ", SDTIntBinOp, [SDNPCommutative]>; +def X86pcmpgtb : SDNode<"X86ISD::PCMPGTB", SDTIntBinOp>; +def X86pcmpgtw : SDNode<"X86ISD::PCMPGTW", SDTIntBinOp>; +def X86pcmpgtd : SDNode<"X86ISD::PCMPGTD", SDTIntBinOp>; +def X86pcmpgtq : SDNode<"X86ISD::PCMPGTQ", SDTIntBinOp>; + +def SDTX86CmpPTest : SDTypeProfile<0, 2, [SDTCisVT<0, v4f32>, + SDTCisVT<1, v4f32>]>; +def X86ptest : SDNode<"X86ISD::PTEST", SDTX86CmpPTest>; + +//===----------------------------------------------------------------------===// +// SSE Complex Patterns +//===----------------------------------------------------------------------===// + +// These are 'extloads' from a scalar to the low element of a vector, zeroing +// the top elements. These are used for the SSE 'ss' and 'sd' instruction +// forms. +def sse_load_f32 : ComplexPattern; +def sse_load_f64 : ComplexPattern; + +def ssmem : Operand { + let PrintMethod = "printf32mem"; + let MIOperandInfo = (ops ptr_rc, i8imm, ptr_rc_nosp, i32imm, i8imm); + let ParserMatchClass = X86MemAsmOperand; +} +def sdmem : Operand { + let PrintMethod = "printf64mem"; + let MIOperandInfo = (ops ptr_rc, i8imm, ptr_rc_nosp, i32imm, i8imm); + let ParserMatchClass = X86MemAsmOperand; +} + +//===----------------------------------------------------------------------===// +// SSE pattern fragments +//===----------------------------------------------------------------------===// + +def loadv4f32 : PatFrag<(ops node:$ptr), (v4f32 (load node:$ptr))>; +def loadv2f64 : PatFrag<(ops node:$ptr), (v2f64 (load node:$ptr))>; +def loadv4i32 : PatFrag<(ops node:$ptr), (v4i32 (load node:$ptr))>; +def loadv2i64 : PatFrag<(ops node:$ptr), (v2i64 (load node:$ptr))>; + +// Like 'store', but always requires vector alignment. +def alignedstore : PatFrag<(ops node:$val, node:$ptr), + (store node:$val, node:$ptr), [{ + return cast(N)->getAlignment() >= 16; +}]>; + +// Like 'load', but always requires vector alignment. +def alignedload : PatFrag<(ops node:$ptr), (load node:$ptr), [{ + return cast(N)->getAlignment() >= 16; +}]>; + +def alignedloadfsf32 : PatFrag<(ops node:$ptr), (f32 (alignedload node:$ptr))>; +def alignedloadfsf64 : PatFrag<(ops node:$ptr), (f64 (alignedload node:$ptr))>; +def alignedloadv4f32 : PatFrag<(ops node:$ptr), (v4f32 (alignedload node:$ptr))>; +def alignedloadv2f64 : PatFrag<(ops node:$ptr), (v2f64 (alignedload node:$ptr))>; +def alignedloadv4i32 : PatFrag<(ops node:$ptr), (v4i32 (alignedload node:$ptr))>; +def alignedloadv2i64 : PatFrag<(ops node:$ptr), (v2i64 (alignedload node:$ptr))>; + +// Like 'load', but uses special alignment checks suitable for use in +// memory operands in most SSE instructions, which are required to +// be naturally aligned on some targets but not on others. +// FIXME: Actually implement support for targets that don't require the +// alignment. This probably wants a subtarget predicate. +def memop : PatFrag<(ops node:$ptr), (load node:$ptr), [{ + return cast(N)->getAlignment() >= 16; +}]>; + +def memopfsf32 : PatFrag<(ops node:$ptr), (f32 (memop node:$ptr))>; +def memopfsf64 : PatFrag<(ops node:$ptr), (f64 (memop node:$ptr))>; +def memopv4f32 : PatFrag<(ops node:$ptr), (v4f32 (memop node:$ptr))>; +def memopv2f64 : PatFrag<(ops node:$ptr), (v2f64 (memop node:$ptr))>; +def memopv4i32 : PatFrag<(ops node:$ptr), (v4i32 (memop node:$ptr))>; +def memopv2i64 : PatFrag<(ops node:$ptr), (v2i64 (memop node:$ptr))>; +def memopv16i8 : PatFrag<(ops node:$ptr), (v16i8 (memop node:$ptr))>; + +// SSSE3 uses MMX registers for some instructions. They aren't aligned on a +// 16-byte boundary. +// FIXME: 8 byte alignment for mmx reads is not required +def memop64 : PatFrag<(ops node:$ptr), (load node:$ptr), [{ + return cast(N)->getAlignment() >= 8; +}]>; + +def memopv8i8 : PatFrag<(ops node:$ptr), (v8i8 (memop64 node:$ptr))>; +def memopv4i16 : PatFrag<(ops node:$ptr), (v4i16 (memop64 node:$ptr))>; +def memopv8i16 : PatFrag<(ops node:$ptr), (v8i16 (memop64 node:$ptr))>; +def memopv2i32 : PatFrag<(ops node:$ptr), (v2i32 (memop64 node:$ptr))>; + +def bc_v4f32 : PatFrag<(ops node:$in), (v4f32 (bitconvert node:$in))>; +def bc_v2f64 : PatFrag<(ops node:$in), (v2f64 (bitconvert node:$in))>; +def bc_v16i8 : PatFrag<(ops node:$in), (v16i8 (bitconvert node:$in))>; +def bc_v8i16 : PatFrag<(ops node:$in), (v8i16 (bitconvert node:$in))>; +def bc_v4i32 : PatFrag<(ops node:$in), (v4i32 (bitconvert node:$in))>; +def bc_v2i64 : PatFrag<(ops node:$in), (v2i64 (bitconvert node:$in))>; + +def vzmovl_v2i64 : PatFrag<(ops node:$src), + (bitconvert (v2i64 (X86vzmovl + (v2i64 (scalar_to_vector (loadi64 node:$src))))))>; +def vzmovl_v4i32 : PatFrag<(ops node:$src), + (bitconvert (v4i32 (X86vzmovl + (v4i32 (scalar_to_vector (loadi32 node:$src))))))>; + +def vzload_v2i64 : PatFrag<(ops node:$src), + (bitconvert (v2i64 (X86vzload node:$src)))>; + + +def fp32imm0 : PatLeaf<(f32 fpimm), [{ + return N->isExactlyValue(+0.0); +}]>; + +// BYTE_imm - Transform bit immediates into byte immediates. +def BYTE_imm : SDNodeXForm> 3 + return getI32Imm(N->getZExtValue() >> 3); +}]>; + +// SHUFFLE_get_shuf_imm xform function: convert vector_shuffle mask to PSHUF*, +// SHUFP* etc. imm. +def SHUFFLE_get_shuf_imm : SDNodeXForm; + +// SHUFFLE_get_pshufhw_imm xform function: convert vector_shuffle mask to +// PSHUFHW imm. +def SHUFFLE_get_pshufhw_imm : SDNodeXForm; + +// SHUFFLE_get_pshuflw_imm xform function: convert vector_shuffle mask to +// PSHUFLW imm. +def SHUFFLE_get_pshuflw_imm : SDNodeXForm; + +// SHUFFLE_get_palign_imm xform function: convert vector_shuffle mask to +// a PALIGNR imm. +def SHUFFLE_get_palign_imm : SDNodeXForm; + +def splat_lo : PatFrag<(ops node:$lhs, node:$rhs), + (vector_shuffle node:$lhs, node:$rhs), [{ + ShuffleVectorSDNode *SVOp = cast(N); + return SVOp->isSplat() && SVOp->getSplatIndex() == 0; +}]>; + +def movddup : PatFrag<(ops node:$lhs, node:$rhs), + (vector_shuffle node:$lhs, node:$rhs), [{ + return X86::isMOVDDUPMask(cast(N)); +}]>; + +def movhlps : PatFrag<(ops node:$lhs, node:$rhs), + (vector_shuffle node:$lhs, node:$rhs), [{ + return X86::isMOVHLPSMask(cast(N)); +}]>; + +def movhlps_undef : PatFrag<(ops node:$lhs, node:$rhs), + (vector_shuffle node:$lhs, node:$rhs), [{ + return X86::isMOVHLPS_v_undef_Mask(cast(N)); +}]>; + +def movlhps : PatFrag<(ops node:$lhs, node:$rhs), + (vector_shuffle node:$lhs, node:$rhs), [{ + return X86::isMOVLHPSMask(cast(N)); +}]>; + +def movlp : PatFrag<(ops node:$lhs, node:$rhs), + (vector_shuffle node:$lhs, node:$rhs), [{ + return X86::isMOVLPMask(cast(N)); +}]>; + +def movl : PatFrag<(ops node:$lhs, node:$rhs), + (vector_shuffle node:$lhs, node:$rhs), [{ + return X86::isMOVLMask(cast(N)); +}]>; + +def movshdup : PatFrag<(ops node:$lhs, node:$rhs), + (vector_shuffle node:$lhs, node:$rhs), [{ + return X86::isMOVSHDUPMask(cast(N)); +}]>; + +def movsldup : PatFrag<(ops node:$lhs, node:$rhs), + (vector_shuffle node:$lhs, node:$rhs), [{ + return X86::isMOVSLDUPMask(cast(N)); +}]>; + +def unpckl : PatFrag<(ops node:$lhs, node:$rhs), + (vector_shuffle node:$lhs, node:$rhs), [{ + return X86::isUNPCKLMask(cast(N)); +}]>; + +def unpckh : PatFrag<(ops node:$lhs, node:$rhs), + (vector_shuffle node:$lhs, node:$rhs), [{ + return X86::isUNPCKHMask(cast(N)); +}]>; + +def unpckl_undef : PatFrag<(ops node:$lhs, node:$rhs), + (vector_shuffle node:$lhs, node:$rhs), [{ + return X86::isUNPCKL_v_undef_Mask(cast(N)); +}]>; + +def unpckh_undef : PatFrag<(ops node:$lhs, node:$rhs), + (vector_shuffle node:$lhs, node:$rhs), [{ + return X86::isUNPCKH_v_undef_Mask(cast(N)); +}]>; + +def pshufd : PatFrag<(ops node:$lhs, node:$rhs), + (vector_shuffle node:$lhs, node:$rhs), [{ + return X86::isPSHUFDMask(cast(N)); +}], SHUFFLE_get_shuf_imm>; + +def shufp : PatFrag<(ops node:$lhs, node:$rhs), + (vector_shuffle node:$lhs, node:$rhs), [{ + return X86::isSHUFPMask(cast(N)); +}], SHUFFLE_get_shuf_imm>; + +def pshufhw : PatFrag<(ops node:$lhs, node:$rhs), + (vector_shuffle node:$lhs, node:$rhs), [{ + return X86::isPSHUFHWMask(cast(N)); +}], SHUFFLE_get_pshufhw_imm>; + +def pshuflw : PatFrag<(ops node:$lhs, node:$rhs), + (vector_shuffle node:$lhs, node:$rhs), [{ + return X86::isPSHUFLWMask(cast(N)); +}], SHUFFLE_get_pshuflw_imm>; + +def palign : PatFrag<(ops node:$lhs, node:$rhs), + (vector_shuffle node:$lhs, node:$rhs), [{ + return X86::isPALIGNRMask(cast(N)); +}], SHUFFLE_get_palign_imm>; + +//===----------------------------------------------------------------------===// +// SSE scalar FP Instructions +//===----------------------------------------------------------------------===// + +// CMOV* - Used to implement the SSE SELECT DAG operation. Expanded after +// instruction selection into a branch sequence. +let Uses = [EFLAGS], usesCustomInserter = 1 in { + def CMOV_FR32 : I<0, Pseudo, + (outs FR32:$dst), (ins FR32:$t, FR32:$f, i8imm:$cond), + "#CMOV_FR32 PSEUDO!", + [(set FR32:$dst, (X86cmov FR32:$t, FR32:$f, imm:$cond, + EFLAGS))]>; + def CMOV_FR64 : I<0, Pseudo, + (outs FR64:$dst), (ins FR64:$t, FR64:$f, i8imm:$cond), + "#CMOV_FR64 PSEUDO!", + [(set FR64:$dst, (X86cmov FR64:$t, FR64:$f, imm:$cond, + EFLAGS))]>; + def CMOV_V4F32 : I<0, Pseudo, + (outs VR128:$dst), (ins VR128:$t, VR128:$f, i8imm:$cond), + "#CMOV_V4F32 PSEUDO!", + [(set VR128:$dst, + (v4f32 (X86cmov VR128:$t, VR128:$f, imm:$cond, + EFLAGS)))]>; + def CMOV_V2F64 : I<0, Pseudo, + (outs VR128:$dst), (ins VR128:$t, VR128:$f, i8imm:$cond), + "#CMOV_V2F64 PSEUDO!", + [(set VR128:$dst, + (v2f64 (X86cmov VR128:$t, VR128:$f, imm:$cond, + EFLAGS)))]>; + def CMOV_V2I64 : I<0, Pseudo, + (outs VR128:$dst), (ins VR128:$t, VR128:$f, i8imm:$cond), + "#CMOV_V2I64 PSEUDO!", + [(set VR128:$dst, + (v2i64 (X86cmov VR128:$t, VR128:$f, imm:$cond, + EFLAGS)))]>; +} + +//===----------------------------------------------------------------------===// +// SSE1 Instructions +//===----------------------------------------------------------------------===// + +// Move Instructions +let neverHasSideEffects = 1 in +def MOVSSrr : SSI<0x10, MRMSrcReg, (outs FR32:$dst), (ins FR32:$src), + "movss\t{$src, $dst|$dst, $src}", []>; +let canFoldAsLoad = 1, isReMaterializable = 1, mayHaveSideEffects = 1 in +def MOVSSrm : SSI<0x10, MRMSrcMem, (outs FR32:$dst), (ins f32mem:$src), + "movss\t{$src, $dst|$dst, $src}", + [(set FR32:$dst, (loadf32 addr:$src))]>; +def MOVSSmr : SSI<0x11, MRMDestMem, (outs), (ins f32mem:$dst, FR32:$src), + "movss\t{$src, $dst|$dst, $src}", + [(store FR32:$src, addr:$dst)]>; + +// Conversion instructions +def CVTTSS2SIrr : SSI<0x2C, MRMSrcReg, (outs GR32:$dst), (ins FR32:$src), + "cvttss2si\t{$src, $dst|$dst, $src}", + [(set GR32:$dst, (fp_to_sint FR32:$src))]>; +def CVTTSS2SIrm : SSI<0x2C, MRMSrcMem, (outs GR32:$dst), (ins f32mem:$src), + "cvttss2si\t{$src, $dst|$dst, $src}", + [(set GR32:$dst, (fp_to_sint (loadf32 addr:$src)))]>; +def CVTSI2SSrr : SSI<0x2A, MRMSrcReg, (outs FR32:$dst), (ins GR32:$src), + "cvtsi2ss\t{$src, $dst|$dst, $src}", + [(set FR32:$dst, (sint_to_fp GR32:$src))]>; +def CVTSI2SSrm : SSI<0x2A, MRMSrcMem, (outs FR32:$dst), (ins i32mem:$src), + "cvtsi2ss\t{$src, $dst|$dst, $src}", + [(set FR32:$dst, (sint_to_fp (loadi32 addr:$src)))]>; + +// Match intrinsics which expect XMM operand(s). +def Int_CVTSS2SIrr : SSI<0x2D, MRMSrcReg, (outs GR32:$dst), (ins VR128:$src), + "cvtss2si\t{$src, $dst|$dst, $src}", + [(set GR32:$dst, (int_x86_sse_cvtss2si VR128:$src))]>; +def Int_CVTSS2SIrm : SSI<0x2D, MRMSrcMem, (outs GR32:$dst), (ins f32mem:$src), + "cvtss2si\t{$src, $dst|$dst, $src}", + [(set GR32:$dst, (int_x86_sse_cvtss2si + (load addr:$src)))]>; + +// Match intrinisics which expect MM and XMM operand(s). +def Int_CVTPS2PIrr : PSI<0x2D, MRMSrcReg, (outs VR64:$dst), (ins VR128:$src), + "cvtps2pi\t{$src, $dst|$dst, $src}", + [(set VR64:$dst, (int_x86_sse_cvtps2pi VR128:$src))]>; +def Int_CVTPS2PIrm : PSI<0x2D, MRMSrcMem, (outs VR64:$dst), (ins f64mem:$src), + "cvtps2pi\t{$src, $dst|$dst, $src}", + [(set VR64:$dst, (int_x86_sse_cvtps2pi + (load addr:$src)))]>; +def Int_CVTTPS2PIrr: PSI<0x2C, MRMSrcReg, (outs VR64:$dst), (ins VR128:$src), + "cvttps2pi\t{$src, $dst|$dst, $src}", + [(set VR64:$dst, (int_x86_sse_cvttps2pi VR128:$src))]>; +def Int_CVTTPS2PIrm: PSI<0x2C, MRMSrcMem, (outs VR64:$dst), (ins f64mem:$src), + "cvttps2pi\t{$src, $dst|$dst, $src}", + [(set VR64:$dst, (int_x86_sse_cvttps2pi + (load addr:$src)))]>; +let Constraints = "$src1 = $dst" in { + def Int_CVTPI2PSrr : PSI<0x2A, MRMSrcReg, + (outs VR128:$dst), (ins VR128:$src1, VR64:$src2), + "cvtpi2ps\t{$src2, $dst|$dst, $src2}", + [(set VR128:$dst, (int_x86_sse_cvtpi2ps VR128:$src1, + VR64:$src2))]>; + def Int_CVTPI2PSrm : PSI<0x2A, MRMSrcMem, + (outs VR128:$dst), (ins VR128:$src1, i64mem:$src2), + "cvtpi2ps\t{$src2, $dst|$dst, $src2}", + [(set VR128:$dst, (int_x86_sse_cvtpi2ps VR128:$src1, + (load addr:$src2)))]>; +} + +// Aliases for intrinsics +def Int_CVTTSS2SIrr : SSI<0x2C, MRMSrcReg, (outs GR32:$dst), (ins VR128:$src), + "cvttss2si\t{$src, $dst|$dst, $src}", + [(set GR32:$dst, + (int_x86_sse_cvttss2si VR128:$src))]>; +def Int_CVTTSS2SIrm : SSI<0x2C, MRMSrcMem, (outs GR32:$dst), (ins f32mem:$src), + "cvttss2si\t{$src, $dst|$dst, $src}", + [(set GR32:$dst, + (int_x86_sse_cvttss2si(load addr:$src)))]>; + +let Constraints = "$src1 = $dst" in { + def Int_CVTSI2SSrr : SSI<0x2A, MRMSrcReg, + (outs VR128:$dst), (ins VR128:$src1, GR32:$src2), + "cvtsi2ss\t{$src2, $dst|$dst, $src2}", + [(set VR128:$dst, (int_x86_sse_cvtsi2ss VR128:$src1, + GR32:$src2))]>; + def Int_CVTSI2SSrm : SSI<0x2A, MRMSrcMem, + (outs VR128:$dst), (ins VR128:$src1, i32mem:$src2), + "cvtsi2ss\t{$src2, $dst|$dst, $src2}", + [(set VR128:$dst, (int_x86_sse_cvtsi2ss VR128:$src1, + (loadi32 addr:$src2)))]>; +} + +// Comparison instructions +let Constraints = "$src1 = $dst", neverHasSideEffects = 1 in { + def CMPSSrr : SSIi8<0xC2, MRMSrcReg, + (outs FR32:$dst), (ins FR32:$src1, FR32:$src, SSECC:$cc), + "cmp${cc}ss\t{$src, $dst|$dst, $src}", []>; +let mayLoad = 1 in + def CMPSSrm : SSIi8<0xC2, MRMSrcMem, + (outs FR32:$dst), (ins FR32:$src1, f32mem:$src, SSECC:$cc), + "cmp${cc}ss\t{$src, $dst|$dst, $src}", []>; +} + +let Defs = [EFLAGS] in { +def UCOMISSrr: PSI<0x2E, MRMSrcReg, (outs), (ins FR32:$src1, FR32:$src2), + "ucomiss\t{$src2, $src1|$src1, $src2}", + [(X86cmp FR32:$src1, FR32:$src2), (implicit EFLAGS)]>; +def UCOMISSrm: PSI<0x2E, MRMSrcMem, (outs), (ins FR32:$src1, f32mem:$src2), + "ucomiss\t{$src2, $src1|$src1, $src2}", + [(X86cmp FR32:$src1, (loadf32 addr:$src2)), + (implicit EFLAGS)]>; +} // Defs = [EFLAGS] + +// Aliases to match intrinsics which expect XMM operand(s). +let Constraints = "$src1 = $dst" in { + def Int_CMPSSrr : SSIi8<0xC2, MRMSrcReg, + (outs VR128:$dst), (ins VR128:$src1, VR128:$src, + SSECC:$cc), + "cmp${cc}ss\t{$src, $dst|$dst, $src}", + [(set VR128:$dst, (int_x86_sse_cmp_ss VR128:$src1, + VR128:$src, imm:$cc))]>; + def Int_CMPSSrm : SSIi8<0xC2, MRMSrcMem, + (outs VR128:$dst), (ins VR128:$src1, f32mem:$src, + SSECC:$cc), + "cmp${cc}ss\t{$src, $dst|$dst, $src}", + [(set VR128:$dst, (int_x86_sse_cmp_ss VR128:$src1, + (load addr:$src), imm:$cc))]>; +} + +let Defs = [EFLAGS] in { +def Int_UCOMISSrr: PSI<0x2E, MRMSrcReg, (outs), (ins VR128:$src1, VR128:$src2), + "ucomiss\t{$src2, $src1|$src1, $src2}", + [(X86ucomi (v4f32 VR128:$src1), VR128:$src2), + (implicit EFLAGS)]>; +def Int_UCOMISSrm: PSI<0x2E, MRMSrcMem, (outs),(ins VR128:$src1, f128mem:$src2), + "ucomiss\t{$src2, $src1|$src1, $src2}", + [(X86ucomi (v4f32 VR128:$src1), (load addr:$src2)), + (implicit EFLAGS)]>; + +def Int_COMISSrr: PSI<0x2F, MRMSrcReg, (outs), (ins VR128:$src1, VR128:$src2), + "comiss\t{$src2, $src1|$src1, $src2}", + [(X86comi (v4f32 VR128:$src1), VR128:$src2), + (implicit EFLAGS)]>; +def Int_COMISSrm: PSI<0x2F, MRMSrcMem, (outs), (ins VR128:$src1, f128mem:$src2), + "comiss\t{$src2, $src1|$src1, $src2}", + [(X86comi (v4f32 VR128:$src1), (load addr:$src2)), + (implicit EFLAGS)]>; +} // Defs = [EFLAGS] + +// Aliases of packed SSE1 instructions for scalar use. These all have names +// that start with 'Fs'. + +// Alias instructions that map fld0 to pxor for sse. +let isReMaterializable = 1, isAsCheapAsAMove = 1, isCodeGenOnly = 1, + canFoldAsLoad = 1 in +def FsFLD0SS : I<0xEF, MRMInitReg, (outs FR32:$dst), (ins), + "pxor\t$dst, $dst", [(set FR32:$dst, fp32imm0)]>, + Requires<[HasSSE1]>, TB, OpSize; + +// Alias instruction to do FR32 reg-to-reg copy using movaps. Upper bits are +// disregarded. +let neverHasSideEffects = 1 in +def FsMOVAPSrr : PSI<0x28, MRMSrcReg, (outs FR32:$dst), (ins FR32:$src), + "movaps\t{$src, $dst|$dst, $src}", []>; + +// Alias instruction to load FR32 from f128mem using movaps. Upper bits are +// disregarded. +let canFoldAsLoad = 1, isReMaterializable = 1, mayHaveSideEffects = 1 in +def FsMOVAPSrm : PSI<0x28, MRMSrcMem, (outs FR32:$dst), (ins f128mem:$src), + "movaps\t{$src, $dst|$dst, $src}", + [(set FR32:$dst, (alignedloadfsf32 addr:$src))]>; + +// Alias bitwise logical operations using SSE logical ops on packed FP values. +let Constraints = "$src1 = $dst" in { +let isCommutable = 1 in { + def FsANDPSrr : PSI<0x54, MRMSrcReg, (outs FR32:$dst), + (ins FR32:$src1, FR32:$src2), + "andps\t{$src2, $dst|$dst, $src2}", + [(set FR32:$dst, (X86fand FR32:$src1, FR32:$src2))]>; + def FsORPSrr : PSI<0x56, MRMSrcReg, (outs FR32:$dst), + (ins FR32:$src1, FR32:$src2), + "orps\t{$src2, $dst|$dst, $src2}", + [(set FR32:$dst, (X86for FR32:$src1, FR32:$src2))]>; + def FsXORPSrr : PSI<0x57, MRMSrcReg, (outs FR32:$dst), + (ins FR32:$src1, FR32:$src2), + "xorps\t{$src2, $dst|$dst, $src2}", + [(set FR32:$dst, (X86fxor FR32:$src1, FR32:$src2))]>; +} + +def FsANDPSrm : PSI<0x54, MRMSrcMem, (outs FR32:$dst), + (ins FR32:$src1, f128mem:$src2), + "andps\t{$src2, $dst|$dst, $src2}", + [(set FR32:$dst, (X86fand FR32:$src1, + (memopfsf32 addr:$src2)))]>; +def FsORPSrm : PSI<0x56, MRMSrcMem, (outs FR32:$dst), + (ins FR32:$src1, f128mem:$src2), + "orps\t{$src2, $dst|$dst, $src2}", + [(set FR32:$dst, (X86for FR32:$src1, + (memopfsf32 addr:$src2)))]>; +def FsXORPSrm : PSI<0x57, MRMSrcMem, (outs FR32:$dst), + (ins FR32:$src1, f128mem:$src2), + "xorps\t{$src2, $dst|$dst, $src2}", + [(set FR32:$dst, (X86fxor FR32:$src1, + (memopfsf32 addr:$src2)))]>; + +let neverHasSideEffects = 1 in { +def FsANDNPSrr : PSI<0x55, MRMSrcReg, + (outs FR32:$dst), (ins FR32:$src1, FR32:$src2), + "andnps\t{$src2, $dst|$dst, $src2}", []>; +let mayLoad = 1 in +def FsANDNPSrm : PSI<0x55, MRMSrcMem, + (outs FR32:$dst), (ins FR32:$src1, f128mem:$src2), + "andnps\t{$src2, $dst|$dst, $src2}", []>; +} +} + +/// basic_sse1_fp_binop_rm - SSE1 binops come in both scalar and vector forms. +/// +/// In addition, we also have a special variant of the scalar form here to +/// represent the associated intrinsic operation. This form is unlike the +/// plain scalar form, in that it takes an entire vector (instead of a scalar) +/// and leaves the top elements unmodified (therefore these cannot be commuted). +/// +/// These three forms can each be reg+reg or reg+mem, so there are a total of +/// six "instructions". +/// +let Constraints = "$src1 = $dst" in { +multiclass basic_sse1_fp_binop_rm opc, string OpcodeStr, + SDNode OpNode, Intrinsic F32Int, + bit Commutable = 0> { + // Scalar operation, reg+reg. + def SSrr : SSI { + let isCommutable = Commutable; + } + + // Scalar operation, reg+mem. + def SSrm : SSI; + + // Vector operation, reg+reg. + def PSrr : PSI { + let isCommutable = Commutable; + } + + // Vector operation, reg+mem. + def PSrm : PSI; + + // Intrinsic operation, reg+reg. + def SSrr_Int : SSI; + + // Intrinsic operation, reg+mem. + def SSrm_Int : SSI; +} +} + +// Arithmetic instructions +defm ADD : basic_sse1_fp_binop_rm<0x58, "add", fadd, int_x86_sse_add_ss, 1>; +defm MUL : basic_sse1_fp_binop_rm<0x59, "mul", fmul, int_x86_sse_mul_ss, 1>; +defm SUB : basic_sse1_fp_binop_rm<0x5C, "sub", fsub, int_x86_sse_sub_ss>; +defm DIV : basic_sse1_fp_binop_rm<0x5E, "div", fdiv, int_x86_sse_div_ss>; + +/// sse1_fp_binop_rm - Other SSE1 binops +/// +/// This multiclass is like basic_sse1_fp_binop_rm, with the addition of +/// instructions for a full-vector intrinsic form. Operations that map +/// onto C operators don't use this form since they just use the plain +/// vector form instead of having a separate vector intrinsic form. +/// +/// This provides a total of eight "instructions". +/// +let Constraints = "$src1 = $dst" in { +multiclass sse1_fp_binop_rm opc, string OpcodeStr, + SDNode OpNode, + Intrinsic F32Int, + Intrinsic V4F32Int, + bit Commutable = 0> { + + // Scalar operation, reg+reg. + def SSrr : SSI { + let isCommutable = Commutable; + } + + // Scalar operation, reg+mem. + def SSrm : SSI; + + // Vector operation, reg+reg. + def PSrr : PSI { + let isCommutable = Commutable; + } + + // Vector operation, reg+mem. + def PSrm : PSI; + + // Intrinsic operation, reg+reg. + def SSrr_Int : SSI { + let isCommutable = Commutable; + } + + // Intrinsic operation, reg+mem. + def SSrm_Int : SSI; + + // Vector intrinsic operation, reg+reg. + def PSrr_Int : PSI { + let isCommutable = Commutable; + } + + // Vector intrinsic operation, reg+mem. + def PSrm_Int : PSI; +} +} + +defm MAX : sse1_fp_binop_rm<0x5F, "max", X86fmax, + int_x86_sse_max_ss, int_x86_sse_max_ps>; +defm MIN : sse1_fp_binop_rm<0x5D, "min", X86fmin, + int_x86_sse_min_ss, int_x86_sse_min_ps>; + +//===----------------------------------------------------------------------===// +// SSE packed FP Instructions + +// Move Instructions +let neverHasSideEffects = 1 in +def MOVAPSrr : PSI<0x28, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src), + "movaps\t{$src, $dst|$dst, $src}", []>; +let canFoldAsLoad = 1, isReMaterializable = 1, mayHaveSideEffects = 1 in +def MOVAPSrm : PSI<0x28, MRMSrcMem, (outs VR128:$dst), (ins f128mem:$src), + "movaps\t{$src, $dst|$dst, $src}", + [(set VR128:$dst, (alignedloadv4f32 addr:$src))]>; + +def MOVAPSmr : PSI<0x29, MRMDestMem, (outs), (ins f128mem:$dst, VR128:$src), + "movaps\t{$src, $dst|$dst, $src}", + [(alignedstore (v4f32 VR128:$src), addr:$dst)]>; + +let neverHasSideEffects = 1 in +def MOVUPSrr : PSI<0x10, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src), + "movups\t{$src, $dst|$dst, $src}", []>; +let canFoldAsLoad = 1, isReMaterializable = 1, mayHaveSideEffects = 1 in +def MOVUPSrm : PSI<0x10, MRMSrcMem, (outs VR128:$dst), (ins f128mem:$src), + "movups\t{$src, $dst|$dst, $src}", + [(set VR128:$dst, (loadv4f32 addr:$src))]>; +def MOVUPSmr : PSI<0x11, MRMDestMem, (outs), (ins f128mem:$dst, VR128:$src), + "movups\t{$src, $dst|$dst, $src}", + [(store (v4f32 VR128:$src), addr:$dst)]>; + +// Intrinsic forms of MOVUPS load and store +let canFoldAsLoad = 1, isReMaterializable = 1, mayHaveSideEffects = 1 in +def MOVUPSrm_Int : PSI<0x10, MRMSrcMem, (outs VR128:$dst), (ins f128mem:$src), + "movups\t{$src, $dst|$dst, $src}", + [(set VR128:$dst, (int_x86_sse_loadu_ps addr:$src))]>; +def MOVUPSmr_Int : PSI<0x11, MRMDestMem, (outs), (ins f128mem:$dst, VR128:$src), + "movups\t{$src, $dst|$dst, $src}", + [(int_x86_sse_storeu_ps addr:$dst, VR128:$src)]>; + +let Constraints = "$src1 = $dst" in { + let AddedComplexity = 20 in { + def MOVLPSrm : PSI<0x12, MRMSrcMem, + (outs VR128:$dst), (ins VR128:$src1, f64mem:$src2), + "movlps\t{$src2, $dst|$dst, $src2}", + [(set VR128:$dst, + (movlp VR128:$src1, + (bc_v4f32 (v2f64 (scalar_to_vector (loadf64 addr:$src2))))))]>; + def MOVHPSrm : PSI<0x16, MRMSrcMem, + (outs VR128:$dst), (ins VR128:$src1, f64mem:$src2), + "movhps\t{$src2, $dst|$dst, $src2}", + [(set VR128:$dst, + (movlhps VR128:$src1, + (bc_v4f32 (v2f64 (scalar_to_vector (loadf64 addr:$src2))))))]>; + } // AddedComplexity +} // Constraints = "$src1 = $dst" + + +def MOVLPSmr : PSI<0x13, MRMDestMem, (outs), (ins f64mem:$dst, VR128:$src), + "movlps\t{$src, $dst|$dst, $src}", + [(store (f64 (vector_extract (bc_v2f64 (v4f32 VR128:$src)), + (iPTR 0))), addr:$dst)]>; + +// v2f64 extract element 1 is always custom lowered to unpack high to low +// and extract element 0 so the non-store version isn't too horrible. +def MOVHPSmr : PSI<0x17, MRMDestMem, (outs), (ins f64mem:$dst, VR128:$src), + "movhps\t{$src, $dst|$dst, $src}", + [(store (f64 (vector_extract + (unpckh (bc_v2f64 (v4f32 VR128:$src)), + (undef)), (iPTR 0))), addr:$dst)]>; + +let Constraints = "$src1 = $dst" in { +let AddedComplexity = 20 in { +def MOVLHPSrr : PSI<0x16, MRMSrcReg, (outs VR128:$dst), + (ins VR128:$src1, VR128:$src2), + "movlhps\t{$src2, $dst|$dst, $src2}", + [(set VR128:$dst, + (v4f32 (movlhps VR128:$src1, VR128:$src2)))]>; + +def MOVHLPSrr : PSI<0x12, MRMSrcReg, (outs VR128:$dst), + (ins VR128:$src1, VR128:$src2), + "movhlps\t{$src2, $dst|$dst, $src2}", + [(set VR128:$dst, + (v4f32 (movhlps VR128:$src1, VR128:$src2)))]>; +} // AddedComplexity +} // Constraints = "$src1 = $dst" + +let AddedComplexity = 20 in { +def : Pat<(v4f32 (movddup VR128:$src, (undef))), + (MOVLHPSrr VR128:$src, VR128:$src)>, Requires<[HasSSE1]>; +def : Pat<(v2i64 (movddup VR128:$src, (undef))), + (MOVLHPSrr VR128:$src, VR128:$src)>, Requires<[HasSSE1]>; +} + + + +// Arithmetic + +/// sse1_fp_unop_rm - SSE1 unops come in both scalar and vector forms. +/// +/// In addition, we also have a special variant of the scalar form here to +/// represent the associated intrinsic operation. This form is unlike the +/// plain scalar form, in that it takes an entire vector (instead of a +/// scalar) and leaves the top elements undefined. +/// +/// And, we have a special variant form for a full-vector intrinsic form. +/// +/// These four forms can each have a reg or a mem operand, so there are a +/// total of eight "instructions". +/// +multiclass sse1_fp_unop_rm opc, string OpcodeStr, + SDNode OpNode, + Intrinsic F32Int, + Intrinsic V4F32Int, + bit Commutable = 0> { + // Scalar operation, reg. + def SSr : SSI { + let isCommutable = Commutable; + } + + // Scalar operation, mem. + def SSm : SSI; + + // Vector operation, reg. + def PSr : PSI { + let isCommutable = Commutable; + } + + // Vector operation, mem. + def PSm : PSI; + + // Intrinsic operation, reg. + def SSr_Int : SSI { + let isCommutable = Commutable; + } + + // Intrinsic operation, mem. + def SSm_Int : SSI; + + // Vector intrinsic operation, reg + def PSr_Int : PSI { + let isCommutable = Commutable; + } + + // Vector intrinsic operation, mem + def PSm_Int : PSI; +} + +// Square root. +defm SQRT : sse1_fp_unop_rm<0x51, "sqrt", fsqrt, + int_x86_sse_sqrt_ss, int_x86_sse_sqrt_ps>; + +// Reciprocal approximations. Note that these typically require refinement +// in order to obtain suitable precision. +defm RSQRT : sse1_fp_unop_rm<0x52, "rsqrt", X86frsqrt, + int_x86_sse_rsqrt_ss, int_x86_sse_rsqrt_ps>; +defm RCP : sse1_fp_unop_rm<0x53, "rcp", X86frcp, + int_x86_sse_rcp_ss, int_x86_sse_rcp_ps>; + +// Logical +let Constraints = "$src1 = $dst" in { + let isCommutable = 1 in { + def ANDPSrr : PSI<0x54, MRMSrcReg, + (outs VR128:$dst), (ins VR128:$src1, VR128:$src2), + "andps\t{$src2, $dst|$dst, $src2}", + [(set VR128:$dst, (v2i64 + (and VR128:$src1, VR128:$src2)))]>; + def ORPSrr : PSI<0x56, MRMSrcReg, + (outs VR128:$dst), (ins VR128:$src1, VR128:$src2), + "orps\t{$src2, $dst|$dst, $src2}", + [(set VR128:$dst, (v2i64 + (or VR128:$src1, VR128:$src2)))]>; + def XORPSrr : PSI<0x57, MRMSrcReg, + (outs VR128:$dst), (ins VR128:$src1, VR128:$src2), + "xorps\t{$src2, $dst|$dst, $src2}", + [(set VR128:$dst, (v2i64 + (xor VR128:$src1, VR128:$src2)))]>; + } + + def ANDPSrm : PSI<0x54, MRMSrcMem, + (outs VR128:$dst), (ins VR128:$src1, f128mem:$src2), + "andps\t{$src2, $dst|$dst, $src2}", + [(set VR128:$dst, (and (bc_v2i64 (v4f32 VR128:$src1)), + (memopv2i64 addr:$src2)))]>; + def ORPSrm : PSI<0x56, MRMSrcMem, + (outs VR128:$dst), (ins VR128:$src1, f128mem:$src2), + "orps\t{$src2, $dst|$dst, $src2}", + [(set VR128:$dst, (or (bc_v2i64 (v4f32 VR128:$src1)), + (memopv2i64 addr:$src2)))]>; + def XORPSrm : PSI<0x57, MRMSrcMem, + (outs VR128:$dst), (ins VR128:$src1, f128mem:$src2), + "xorps\t{$src2, $dst|$dst, $src2}", + [(set VR128:$dst, (xor (bc_v2i64 (v4f32 VR128:$src1)), + (memopv2i64 addr:$src2)))]>; + def ANDNPSrr : PSI<0x55, MRMSrcReg, + (outs VR128:$dst), (ins VR128:$src1, VR128:$src2), + "andnps\t{$src2, $dst|$dst, $src2}", + [(set VR128:$dst, + (v2i64 (and (xor VR128:$src1, + (bc_v2i64 (v4i32 immAllOnesV))), + VR128:$src2)))]>; + def ANDNPSrm : PSI<0x55, MRMSrcMem, + (outs VR128:$dst), (ins VR128:$src1,f128mem:$src2), + "andnps\t{$src2, $dst|$dst, $src2}", + [(set VR128:$dst, + (v2i64 (and (xor (bc_v2i64 (v4f32 VR128:$src1)), + (bc_v2i64 (v4i32 immAllOnesV))), + (memopv2i64 addr:$src2))))]>; +} + +let Constraints = "$src1 = $dst" in { + def CMPPSrri : PSIi8<0xC2, MRMSrcReg, + (outs VR128:$dst), (ins VR128:$src1, VR128:$src, SSECC:$cc), + "cmp${cc}ps\t{$src, $dst|$dst, $src}", + [(set VR128:$dst, (int_x86_sse_cmp_ps VR128:$src1, + VR128:$src, imm:$cc))]>; + def CMPPSrmi : PSIi8<0xC2, MRMSrcMem, + (outs VR128:$dst), (ins VR128:$src1, f128mem:$src, SSECC:$cc), + "cmp${cc}ps\t{$src, $dst|$dst, $src}", + [(set VR128:$dst, (int_x86_sse_cmp_ps VR128:$src1, + (memop addr:$src), imm:$cc))]>; +} +def : Pat<(v4i32 (X86cmpps (v4f32 VR128:$src1), VR128:$src2, imm:$cc)), + (CMPPSrri VR128:$src1, VR128:$src2, imm:$cc)>; +def : Pat<(v4i32 (X86cmpps (v4f32 VR128:$src1), (memop addr:$src2), imm:$cc)), + (CMPPSrmi VR128:$src1, addr:$src2, imm:$cc)>; + +// Shuffle and unpack instructions +let Constraints = "$src1 = $dst" in { + let isConvertibleToThreeAddress = 1 in // Convert to pshufd + def SHUFPSrri : PSIi8<0xC6, MRMSrcReg, + (outs VR128:$dst), (ins VR128:$src1, + VR128:$src2, i8imm:$src3), + "shufps\t{$src3, $src2, $dst|$dst, $src2, $src3}", + [(set VR128:$dst, + (v4f32 (shufp:$src3 VR128:$src1, VR128:$src2)))]>; + def SHUFPSrmi : PSIi8<0xC6, MRMSrcMem, + (outs VR128:$dst), (ins VR128:$src1, + f128mem:$src2, i8imm:$src3), + "shufps\t{$src3, $src2, $dst|$dst, $src2, $src3}", + [(set VR128:$dst, + (v4f32 (shufp:$src3 + VR128:$src1, (memopv4f32 addr:$src2))))]>; + + let AddedComplexity = 10 in { + def UNPCKHPSrr : PSI<0x15, MRMSrcReg, + (outs VR128:$dst), (ins VR128:$src1, VR128:$src2), + "unpckhps\t{$src2, $dst|$dst, $src2}", + [(set VR128:$dst, + (v4f32 (unpckh VR128:$src1, VR128:$src2)))]>; + def UNPCKHPSrm : PSI<0x15, MRMSrcMem, + (outs VR128:$dst), (ins VR128:$src1, f128mem:$src2), + "unpckhps\t{$src2, $dst|$dst, $src2}", + [(set VR128:$dst, + (v4f32 (unpckh VR128:$src1, + (memopv4f32 addr:$src2))))]>; + + def UNPCKLPSrr : PSI<0x14, MRMSrcReg, + (outs VR128:$dst), (ins VR128:$src1, VR128:$src2), + "unpcklps\t{$src2, $dst|$dst, $src2}", + [(set VR128:$dst, + (v4f32 (unpckl VR128:$src1, VR128:$src2)))]>; + def UNPCKLPSrm : PSI<0x14, MRMSrcMem, + (outs VR128:$dst), (ins VR128:$src1, f128mem:$src2), + "unpcklps\t{$src2, $dst|$dst, $src2}", + [(set VR128:$dst, + (unpckl VR128:$src1, (memopv4f32 addr:$src2)))]>; + } // AddedComplexity +} // Constraints = "$src1 = $dst" + +// Mask creation +def MOVMSKPSrr : PSI<0x50, MRMSrcReg, (outs GR32:$dst), (ins VR128:$src), + "movmskps\t{$src, $dst|$dst, $src}", + [(set GR32:$dst, (int_x86_sse_movmsk_ps VR128:$src))]>; +def MOVMSKPDrr : PDI<0x50, MRMSrcReg, (outs GR32:$dst), (ins VR128:$src), + "movmskpd\t{$src, $dst|$dst, $src}", + [(set GR32:$dst, (int_x86_sse2_movmsk_pd VR128:$src))]>; + +// Prefetch intrinsic. +def PREFETCHT0 : PSI<0x18, MRM1m, (outs), (ins i8mem:$src), + "prefetcht0\t$src", [(prefetch addr:$src, imm, (i32 3))]>; +def PREFETCHT1 : PSI<0x18, MRM2m, (outs), (ins i8mem:$src), + "prefetcht1\t$src", [(prefetch addr:$src, imm, (i32 2))]>; +def PREFETCHT2 : PSI<0x18, MRM3m, (outs), (ins i8mem:$src), + "prefetcht2\t$src", [(prefetch addr:$src, imm, (i32 1))]>; +def PREFETCHNTA : PSI<0x18, MRM0m, (outs), (ins i8mem:$src), + "prefetchnta\t$src", [(prefetch addr:$src, imm, (i32 0))]>; + +// Non-temporal stores +def MOVNTPSmr : PSI<0x2B, MRMDestMem, (outs), (ins i128mem:$dst, VR128:$src), + "movntps\t{$src, $dst|$dst, $src}", + [(int_x86_sse_movnt_ps addr:$dst, VR128:$src)]>; + +// Load, store, and memory fence +def SFENCE : PSI<0xAE, MRM7r, (outs), (ins), "sfence", [(int_x86_sse_sfence)]>; + +// MXCSR register +def LDMXCSR : PSI<0xAE, MRM2m, (outs), (ins i32mem:$src), + "ldmxcsr\t$src", [(int_x86_sse_ldmxcsr addr:$src)]>; +def STMXCSR : PSI<0xAE, MRM3m, (outs), (ins i32mem:$dst), + "stmxcsr\t$dst", [(int_x86_sse_stmxcsr addr:$dst)]>; + +// Alias instructions that map zero vector to pxor / xorp* for sse. +// We set canFoldAsLoad because this can be converted to a constant-pool +// load of an all-zeros value if folding it would be beneficial. +let isReMaterializable = 1, isAsCheapAsAMove = 1, canFoldAsLoad = 1, + isCodeGenOnly = 1 in +def V_SET0 : PSI<0x57, MRMInitReg, (outs VR128:$dst), (ins), + "xorps\t$dst, $dst", + [(set VR128:$dst, (v4i32 immAllZerosV))]>; + +let Predicates = [HasSSE1] in { + def : Pat<(v2i64 immAllZerosV), (V_SET0)>; + def : Pat<(v8i16 immAllZerosV), (V_SET0)>; + def : Pat<(v16i8 immAllZerosV), (V_SET0)>; + def : Pat<(v2f64 immAllZerosV), (V_SET0)>; + def : Pat<(v4f32 immAllZerosV), (V_SET0)>; +} + +// FR32 to 128-bit vector conversion. +let isAsCheapAsAMove = 1 in +def MOVSS2PSrr : SSI<0x10, MRMSrcReg, (outs VR128:$dst), (ins FR32:$src), + "movss\t{$src, $dst|$dst, $src}", + [(set VR128:$dst, + (v4f32 (scalar_to_vector FR32:$src)))]>; +def MOVSS2PSrm : SSI<0x10, MRMSrcMem, (outs VR128:$dst), (ins f32mem:$src), + "movss\t{$src, $dst|$dst, $src}", + [(set VR128:$dst, + (v4f32 (scalar_to_vector (loadf32 addr:$src))))]>; + +// FIXME: may not be able to eliminate this movss with coalescing the src and +// dest register classes are different. We really want to write this pattern +// like this: +// def : Pat<(f32 (vector_extract (v4f32 VR128:$src), (iPTR 0))), +// (f32 FR32:$src)>; +let isAsCheapAsAMove = 1 in +def MOVPS2SSrr : SSI<0x10, MRMSrcReg, (outs FR32:$dst), (ins VR128:$src), + "movss\t{$src, $dst|$dst, $src}", + [(set FR32:$dst, (vector_extract (v4f32 VR128:$src), + (iPTR 0)))]>; +def MOVPS2SSmr : SSI<0x11, MRMDestMem, (outs), (ins f32mem:$dst, VR128:$src), + "movss\t{$src, $dst|$dst, $src}", + [(store (f32 (vector_extract (v4f32 VR128:$src), + (iPTR 0))), addr:$dst)]>; + + +// Move to lower bits of a VR128, leaving upper bits alone. +// Three operand (but two address) aliases. +let Constraints = "$src1 = $dst" in { +let neverHasSideEffects = 1 in + def MOVLSS2PSrr : SSI<0x10, MRMSrcReg, + (outs VR128:$dst), (ins VR128:$src1, FR32:$src2), + "movss\t{$src2, $dst|$dst, $src2}", []>; + + let AddedComplexity = 15 in + def MOVLPSrr : SSI<0x10, MRMSrcReg, + (outs VR128:$dst), (ins VR128:$src1, VR128:$src2), + "movss\t{$src2, $dst|$dst, $src2}", + [(set VR128:$dst, + (v4f32 (movl VR128:$src1, VR128:$src2)))]>; +} + +// Move to lower bits of a VR128 and zeroing upper bits. +// Loading from memory automatically zeroing upper bits. +let AddedComplexity = 20 in +def MOVZSS2PSrm : SSI<0x10, MRMSrcMem, (outs VR128:$dst), (ins f32mem:$src), + "movss\t{$src, $dst|$dst, $src}", + [(set VR128:$dst, (v4f32 (X86vzmovl (v4f32 (scalar_to_vector + (loadf32 addr:$src))))))]>; + +def : Pat<(v4f32 (X86vzmovl (loadv4f32 addr:$src))), + (MOVZSS2PSrm addr:$src)>; + +//===---------------------------------------------------------------------===// +// SSE2 Instructions +//===---------------------------------------------------------------------===// + +// Move Instructions +let neverHasSideEffects = 1 in +def MOVSDrr : SDI<0x10, MRMSrcReg, (outs FR64:$dst), (ins FR64:$src), + "movsd\t{$src, $dst|$dst, $src}", []>; +let canFoldAsLoad = 1, isReMaterializable = 1, mayHaveSideEffects = 1 in +def MOVSDrm : SDI<0x10, MRMSrcMem, (outs FR64:$dst), (ins f64mem:$src), + "movsd\t{$src, $dst|$dst, $src}", + [(set FR64:$dst, (loadf64 addr:$src))]>; +def MOVSDmr : SDI<0x11, MRMDestMem, (outs), (ins f64mem:$dst, FR64:$src), + "movsd\t{$src, $dst|$dst, $src}", + [(store FR64:$src, addr:$dst)]>; + +// Conversion instructions +def CVTTSD2SIrr : SDI<0x2C, MRMSrcReg, (outs GR32:$dst), (ins FR64:$src), + "cvttsd2si\t{$src, $dst|$dst, $src}", + [(set GR32:$dst, (fp_to_sint FR64:$src))]>; +def CVTTSD2SIrm : SDI<0x2C, MRMSrcMem, (outs GR32:$dst), (ins f64mem:$src), + "cvttsd2si\t{$src, $dst|$dst, $src}", + [(set GR32:$dst, (fp_to_sint (loadf64 addr:$src)))]>; +def CVTSD2SSrr : SDI<0x5A, MRMSrcReg, (outs FR32:$dst), (ins FR64:$src), + "cvtsd2ss\t{$src, $dst|$dst, $src}", + [(set FR32:$dst, (fround FR64:$src))]>; +def CVTSD2SSrm : SDI<0x5A, MRMSrcMem, (outs FR32:$dst), (ins f64mem:$src), + "cvtsd2ss\t{$src, $dst|$dst, $src}", + [(set FR32:$dst, (fround (loadf64 addr:$src)))]>; +def CVTSI2SDrr : SDI<0x2A, MRMSrcReg, (outs FR64:$dst), (ins GR32:$src), + "cvtsi2sd\t{$src, $dst|$dst, $src}", + [(set FR64:$dst, (sint_to_fp GR32:$src))]>; +def CVTSI2SDrm : SDI<0x2A, MRMSrcMem, (outs FR64:$dst), (ins i32mem:$src), + "cvtsi2sd\t{$src, $dst|$dst, $src}", + [(set FR64:$dst, (sint_to_fp (loadi32 addr:$src)))]>; + +def CVTPD2DQrm : S3DI<0xE6, MRMSrcMem, (outs VR128:$dst), (ins f128mem:$src), + "cvtpd2dq\t{$src, $dst|$dst, $src}", []>; +def CVTPD2DQrr : S3DI<0xE6, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src), + "cvtpd2dq\t{$src, $dst|$dst, $src}", []>; +def CVTDQ2PDrm : S3SI<0xE6, MRMSrcMem, (outs VR128:$dst), (ins f128mem:$src), + "cvtdq2pd\t{$src, $dst|$dst, $src}", []>; +def CVTDQ2PDrr : S3SI<0xE6, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src), + "cvtdq2pd\t{$src, $dst|$dst, $src}", []>; +def CVTPS2DQrr : PDI<0x5B, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src), + "cvtps2dq\t{$src, $dst|$dst, $src}", []>; +def CVTPS2DQrm : PDI<0x5B, MRMSrcMem, (outs VR128:$dst), (ins f128mem:$src), + "cvtps2dq\t{$src, $dst|$dst, $src}", []>; +def CVTDQ2PSrr : PSI<0x5B, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src), + "cvtdq2ps\t{$src, $dst|$dst, $src}", []>; +def CVTDQ2PSrm : PSI<0x5B, MRMSrcMem, (outs VR128:$dst), (ins f128mem:$src), + "cvtdq2ps\t{$src, $dst|$dst, $src}", []>; +def COMISDrr: PDI<0x2F, MRMSrcReg, (outs), (ins VR128:$src1, VR128:$src2), + "comisd\t{$src2, $src1|$src1, $src2}", []>; +def COMISDrm: PDI<0x2F, MRMSrcMem, (outs), (ins VR128:$src1, f128mem:$src2), + "comisd\t{$src2, $src1|$src1, $src2}", []>; + +// SSE2 instructions with XS prefix +def CVTSS2SDrr : I<0x5A, MRMSrcReg, (outs FR64:$dst), (ins FR32:$src), + "cvtss2sd\t{$src, $dst|$dst, $src}", + [(set FR64:$dst, (fextend FR32:$src))]>, XS, + Requires<[HasSSE2]>; +def CVTSS2SDrm : I<0x5A, MRMSrcMem, (outs FR64:$dst), (ins f32mem:$src), + "cvtss2sd\t{$src, $dst|$dst, $src}", + [(set FR64:$dst, (extloadf32 addr:$src))]>, XS, + Requires<[HasSSE2]>; + +// Match intrinsics which expect XMM operand(s). +def Int_CVTSD2SIrr : SDI<0x2D, MRMSrcReg, (outs GR32:$dst), (ins VR128:$src), + "cvtsd2si\t{$src, $dst|$dst, $src}", + [(set GR32:$dst, (int_x86_sse2_cvtsd2si VR128:$src))]>; +def Int_CVTSD2SIrm : SDI<0x2D, MRMSrcMem, (outs GR32:$dst), (ins f128mem:$src), + "cvtsd2si\t{$src, $dst|$dst, $src}", + [(set GR32:$dst, (int_x86_sse2_cvtsd2si + (load addr:$src)))]>; + +// Match intrinisics which expect MM and XMM operand(s). +def Int_CVTPD2PIrr : PDI<0x2D, MRMSrcReg, (outs VR64:$dst), (ins VR128:$src), + "cvtpd2pi\t{$src, $dst|$dst, $src}", + [(set VR64:$dst, (int_x86_sse_cvtpd2pi VR128:$src))]>; +def Int_CVTPD2PIrm : PDI<0x2D, MRMSrcMem, (outs VR64:$dst), (ins f128mem:$src), + "cvtpd2pi\t{$src, $dst|$dst, $src}", + [(set VR64:$dst, (int_x86_sse_cvtpd2pi + (memop addr:$src)))]>; +def Int_CVTTPD2PIrr: PDI<0x2C, MRMSrcReg, (outs VR64:$dst), (ins VR128:$src), + "cvttpd2pi\t{$src, $dst|$dst, $src}", + [(set VR64:$dst, (int_x86_sse_cvttpd2pi VR128:$src))]>; +def Int_CVTTPD2PIrm: PDI<0x2C, MRMSrcMem, (outs VR64:$dst), (ins f128mem:$src), + "cvttpd2pi\t{$src, $dst|$dst, $src}", + [(set VR64:$dst, (int_x86_sse_cvttpd2pi + (memop addr:$src)))]>; +def Int_CVTPI2PDrr : PDI<0x2A, MRMSrcReg, (outs VR128:$dst), (ins VR64:$src), + "cvtpi2pd\t{$src, $dst|$dst, $src}", + [(set VR128:$dst, (int_x86_sse_cvtpi2pd VR64:$src))]>; +def Int_CVTPI2PDrm : PDI<0x2A, MRMSrcMem, (outs VR128:$dst), (ins i64mem:$src), + "cvtpi2pd\t{$src, $dst|$dst, $src}", + [(set VR128:$dst, (int_x86_sse_cvtpi2pd + (load addr:$src)))]>; + +// Aliases for intrinsics +def Int_CVTTSD2SIrr : SDI<0x2C, MRMSrcReg, (outs GR32:$dst), (ins VR128:$src), + "cvttsd2si\t{$src, $dst|$dst, $src}", + [(set GR32:$dst, + (int_x86_sse2_cvttsd2si VR128:$src))]>; +def Int_CVTTSD2SIrm : SDI<0x2C, MRMSrcMem, (outs GR32:$dst), (ins f128mem:$src), + "cvttsd2si\t{$src, $dst|$dst, $src}", + [(set GR32:$dst, (int_x86_sse2_cvttsd2si + (load addr:$src)))]>; + +// Comparison instructions +let Constraints = "$src1 = $dst", neverHasSideEffects = 1 in { + def CMPSDrr : SDIi8<0xC2, MRMSrcReg, + (outs FR64:$dst), (ins FR64:$src1, FR64:$src, SSECC:$cc), + "cmp${cc}sd\t{$src, $dst|$dst, $src}", []>; +let mayLoad = 1 in + def CMPSDrm : SDIi8<0xC2, MRMSrcMem, + (outs FR64:$dst), (ins FR64:$src1, f64mem:$src, SSECC:$cc), + "cmp${cc}sd\t{$src, $dst|$dst, $src}", []>; +} + +let Defs = [EFLAGS] in { +def UCOMISDrr: PDI<0x2E, MRMSrcReg, (outs), (ins FR64:$src1, FR64:$src2), + "ucomisd\t{$src2, $src1|$src1, $src2}", + [(X86cmp FR64:$src1, FR64:$src2), (implicit EFLAGS)]>; +def UCOMISDrm: PDI<0x2E, MRMSrcMem, (outs), (ins FR64:$src1, f64mem:$src2), + "ucomisd\t{$src2, $src1|$src1, $src2}", + [(X86cmp FR64:$src1, (loadf64 addr:$src2)), + (implicit EFLAGS)]>; +} // Defs = [EFLAGS] + +// Aliases to match intrinsics which expect XMM operand(s). +let Constraints = "$src1 = $dst" in { + def Int_CMPSDrr : SDIi8<0xC2, MRMSrcReg, + (outs VR128:$dst), (ins VR128:$src1, VR128:$src, + SSECC:$cc), + "cmp${cc}sd\t{$src, $dst|$dst, $src}", + [(set VR128:$dst, (int_x86_sse2_cmp_sd VR128:$src1, + VR128:$src, imm:$cc))]>; + def Int_CMPSDrm : SDIi8<0xC2, MRMSrcMem, + (outs VR128:$dst), (ins VR128:$src1, f64mem:$src, + SSECC:$cc), + "cmp${cc}sd\t{$src, $dst|$dst, $src}", + [(set VR128:$dst, (int_x86_sse2_cmp_sd VR128:$src1, + (load addr:$src), imm:$cc))]>; +} + +let Defs = [EFLAGS] in { +def Int_UCOMISDrr: PDI<0x2E, MRMSrcReg, (outs), (ins VR128:$src1, VR128:$src2), + "ucomisd\t{$src2, $src1|$src1, $src2}", + [(X86ucomi (v2f64 VR128:$src1), (v2f64 VR128:$src2)), + (implicit EFLAGS)]>; +def Int_UCOMISDrm: PDI<0x2E, MRMSrcMem, (outs),(ins VR128:$src1, f128mem:$src2), + "ucomisd\t{$src2, $src1|$src1, $src2}", + [(X86ucomi (v2f64 VR128:$src1), (load addr:$src2)), + (implicit EFLAGS)]>; + +def Int_COMISDrr: PDI<0x2F, MRMSrcReg, (outs), (ins VR128:$src1, VR128:$src2), + "comisd\t{$src2, $src1|$src1, $src2}", + [(X86comi (v2f64 VR128:$src1), (v2f64 VR128:$src2)), + (implicit EFLAGS)]>; +def Int_COMISDrm: PDI<0x2F, MRMSrcMem, (outs), (ins VR128:$src1, f128mem:$src2), + "comisd\t{$src2, $src1|$src1, $src2}", + [(X86comi (v2f64 VR128:$src1), (load addr:$src2)), + (implicit EFLAGS)]>; +} // Defs = [EFLAGS] + +// Aliases of packed SSE2 instructions for scalar use. These all have names +// that start with 'Fs'. + +// Alias instructions that map fld0 to pxor for sse. +let isReMaterializable = 1, isAsCheapAsAMove = 1, isCodeGenOnly = 1, + canFoldAsLoad = 1 in +def FsFLD0SD : I<0xEF, MRMInitReg, (outs FR64:$dst), (ins), + "pxor\t$dst, $dst", [(set FR64:$dst, fpimm0)]>, + Requires<[HasSSE2]>, TB, OpSize; + +// Alias instruction to do FR64 reg-to-reg copy using movapd. Upper bits are +// disregarded. +let neverHasSideEffects = 1 in +def FsMOVAPDrr : PDI<0x28, MRMSrcReg, (outs FR64:$dst), (ins FR64:$src), + "movapd\t{$src, $dst|$dst, $src}", []>; + +// Alias instruction to load FR64 from f128mem using movapd. Upper bits are +// disregarded. +let canFoldAsLoad = 1, isReMaterializable = 1, mayHaveSideEffects = 1 in +def FsMOVAPDrm : PDI<0x28, MRMSrcMem, (outs FR64:$dst), (ins f128mem:$src), + "movapd\t{$src, $dst|$dst, $src}", + [(set FR64:$dst, (alignedloadfsf64 addr:$src))]>; + +// Alias bitwise logical operations using SSE logical ops on packed FP values. +let Constraints = "$src1 = $dst" in { +let isCommutable = 1 in { + def FsANDPDrr : PDI<0x54, MRMSrcReg, (outs FR64:$dst), + (ins FR64:$src1, FR64:$src2), + "andpd\t{$src2, $dst|$dst, $src2}", + [(set FR64:$dst, (X86fand FR64:$src1, FR64:$src2))]>; + def FsORPDrr : PDI<0x56, MRMSrcReg, (outs FR64:$dst), + (ins FR64:$src1, FR64:$src2), + "orpd\t{$src2, $dst|$dst, $src2}", + [(set FR64:$dst, (X86for FR64:$src1, FR64:$src2))]>; + def FsXORPDrr : PDI<0x57, MRMSrcReg, (outs FR64:$dst), + (ins FR64:$src1, FR64:$src2), + "xorpd\t{$src2, $dst|$dst, $src2}", + [(set FR64:$dst, (X86fxor FR64:$src1, FR64:$src2))]>; +} + +def FsANDPDrm : PDI<0x54, MRMSrcMem, (outs FR64:$dst), + (ins FR64:$src1, f128mem:$src2), + "andpd\t{$src2, $dst|$dst, $src2}", + [(set FR64:$dst, (X86fand FR64:$src1, + (memopfsf64 addr:$src2)))]>; +def FsORPDrm : PDI<0x56, MRMSrcMem, (outs FR64:$dst), + (ins FR64:$src1, f128mem:$src2), + "orpd\t{$src2, $dst|$dst, $src2}", + [(set FR64:$dst, (X86for FR64:$src1, + (memopfsf64 addr:$src2)))]>; +def FsXORPDrm : PDI<0x57, MRMSrcMem, (outs FR64:$dst), + (ins FR64:$src1, f128mem:$src2), + "xorpd\t{$src2, $dst|$dst, $src2}", + [(set FR64:$dst, (X86fxor FR64:$src1, + (memopfsf64 addr:$src2)))]>; + +let neverHasSideEffects = 1 in { +def FsANDNPDrr : PDI<0x55, MRMSrcReg, + (outs FR64:$dst), (ins FR64:$src1, FR64:$src2), + "andnpd\t{$src2, $dst|$dst, $src2}", []>; +let mayLoad = 1 in +def FsANDNPDrm : PDI<0x55, MRMSrcMem, + (outs FR64:$dst), (ins FR64:$src1, f128mem:$src2), + "andnpd\t{$src2, $dst|$dst, $src2}", []>; +} +} + +/// basic_sse2_fp_binop_rm - SSE2 binops come in both scalar and vector forms. +/// +/// In addition, we also have a special variant of the scalar form here to +/// represent the associated intrinsic operation. This form is unlike the +/// plain scalar form, in that it takes an entire vector (instead of a scalar) +/// and leaves the top elements unmodified (therefore these cannot be commuted). +/// +/// These three forms can each be reg+reg or reg+mem, so there are a total of +/// six "instructions". +/// +let Constraints = "$src1 = $dst" in { +multiclass basic_sse2_fp_binop_rm opc, string OpcodeStr, + SDNode OpNode, Intrinsic F64Int, + bit Commutable = 0> { + // Scalar operation, reg+reg. + def SDrr : SDI { + let isCommutable = Commutable; + } + + // Scalar operation, reg+mem. + def SDrm : SDI; + + // Vector operation, reg+reg. + def PDrr : PDI { + let isCommutable = Commutable; + } + + // Vector operation, reg+mem. + def PDrm : PDI; + + // Intrinsic operation, reg+reg. + def SDrr_Int : SDI; + + // Intrinsic operation, reg+mem. + def SDrm_Int : SDI; +} +} + +// Arithmetic instructions +defm ADD : basic_sse2_fp_binop_rm<0x58, "add", fadd, int_x86_sse2_add_sd, 1>; +defm MUL : basic_sse2_fp_binop_rm<0x59, "mul", fmul, int_x86_sse2_mul_sd, 1>; +defm SUB : basic_sse2_fp_binop_rm<0x5C, "sub", fsub, int_x86_sse2_sub_sd>; +defm DIV : basic_sse2_fp_binop_rm<0x5E, "div", fdiv, int_x86_sse2_div_sd>; + +/// sse2_fp_binop_rm - Other SSE2 binops +/// +/// This multiclass is like basic_sse2_fp_binop_rm, with the addition of +/// instructions for a full-vector intrinsic form. Operations that map +/// onto C operators don't use this form since they just use the plain +/// vector form instead of having a separate vector intrinsic form. +/// +/// This provides a total of eight "instructions". +/// +let Constraints = "$src1 = $dst" in { +multiclass sse2_fp_binop_rm opc, string OpcodeStr, + SDNode OpNode, + Intrinsic F64Int, + Intrinsic V2F64Int, + bit Commutable = 0> { + + // Scalar operation, reg+reg. + def SDrr : SDI { + let isCommutable = Commutable; + } + + // Scalar operation, reg+mem. + def SDrm : SDI; + + // Vector operation, reg+reg. + def PDrr : PDI { + let isCommutable = Commutable; + } + + // Vector operation, reg+mem. + def PDrm : PDI; + + // Intrinsic operation, reg+reg. + def SDrr_Int : SDI { + let isCommutable = Commutable; + } + + // Intrinsic operation, reg+mem. + def SDrm_Int : SDI; + + // Vector intrinsic operation, reg+reg. + def PDrr_Int : PDI { + let isCommutable = Commutable; + } + + // Vector intrinsic operation, reg+mem. + def PDrm_Int : PDI; +} +} + +defm MAX : sse2_fp_binop_rm<0x5F, "max", X86fmax, + int_x86_sse2_max_sd, int_x86_sse2_max_pd>; +defm MIN : sse2_fp_binop_rm<0x5D, "min", X86fmin, + int_x86_sse2_min_sd, int_x86_sse2_min_pd>; + +//===---------------------------------------------------------------------===// +// SSE packed FP Instructions + +// Move Instructions +let neverHasSideEffects = 1 in +def MOVAPDrr : PDI<0x28, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src), + "movapd\t{$src, $dst|$dst, $src}", []>; +let canFoldAsLoad = 1, isReMaterializable = 1, mayHaveSideEffects = 1 in +def MOVAPDrm : PDI<0x28, MRMSrcMem, (outs VR128:$dst), (ins f128mem:$src), + "movapd\t{$src, $dst|$dst, $src}", + [(set VR128:$dst, (alignedloadv2f64 addr:$src))]>; + +def MOVAPDmr : PDI<0x29, MRMDestMem, (outs), (ins f128mem:$dst, VR128:$src), + "movapd\t{$src, $dst|$dst, $src}", + [(alignedstore (v2f64 VR128:$src), addr:$dst)]>; + +let neverHasSideEffects = 1 in +def MOVUPDrr : PDI<0x10, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src), + "movupd\t{$src, $dst|$dst, $src}", []>; +let canFoldAsLoad = 1 in +def MOVUPDrm : PDI<0x10, MRMSrcMem, (outs VR128:$dst), (ins f128mem:$src), + "movupd\t{$src, $dst|$dst, $src}", + [(set VR128:$dst, (loadv2f64 addr:$src))]>; +def MOVUPDmr : PDI<0x11, MRMDestMem, (outs), (ins f128mem:$dst, VR128:$src), + "movupd\t{$src, $dst|$dst, $src}", + [(store (v2f64 VR128:$src), addr:$dst)]>; + +// Intrinsic forms of MOVUPD load and store +def MOVUPDrm_Int : PDI<0x10, MRMSrcMem, (outs VR128:$dst), (ins f128mem:$src), + "movupd\t{$src, $dst|$dst, $src}", + [(set VR128:$dst, (int_x86_sse2_loadu_pd addr:$src))]>; +def MOVUPDmr_Int : PDI<0x11, MRMDestMem, (outs), (ins f128mem:$dst, VR128:$src), + "movupd\t{$src, $dst|$dst, $src}", + [(int_x86_sse2_storeu_pd addr:$dst, VR128:$src)]>; + +let Constraints = "$src1 = $dst" in { + let AddedComplexity = 20 in { + def MOVLPDrm : PDI<0x12, MRMSrcMem, + (outs VR128:$dst), (ins VR128:$src1, f64mem:$src2), + "movlpd\t{$src2, $dst|$dst, $src2}", + [(set VR128:$dst, + (v2f64 (movlp VR128:$src1, + (scalar_to_vector (loadf64 addr:$src2)))))]>; + def MOVHPDrm : PDI<0x16, MRMSrcMem, + (outs VR128:$dst), (ins VR128:$src1, f64mem:$src2), + "movhpd\t{$src2, $dst|$dst, $src2}", + [(set VR128:$dst, + (v2f64 (movlhps VR128:$src1, + (scalar_to_vector (loadf64 addr:$src2)))))]>; + } // AddedComplexity +} // Constraints = "$src1 = $dst" + +def MOVLPDmr : PDI<0x13, MRMDestMem, (outs), (ins f64mem:$dst, VR128:$src), + "movlpd\t{$src, $dst|$dst, $src}", + [(store (f64 (vector_extract (v2f64 VR128:$src), + (iPTR 0))), addr:$dst)]>; + +// v2f64 extract element 1 is always custom lowered to unpack high to low +// and extract element 0 so the non-store version isn't too horrible. +def MOVHPDmr : PDI<0x17, MRMDestMem, (outs), (ins f64mem:$dst, VR128:$src), + "movhpd\t{$src, $dst|$dst, $src}", + [(store (f64 (vector_extract + (v2f64 (unpckh VR128:$src, (undef))), + (iPTR 0))), addr:$dst)]>; + +// SSE2 instructions without OpSize prefix +def Int_CVTDQ2PSrr : I<0x5B, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src), + "cvtdq2ps\t{$src, $dst|$dst, $src}", + [(set VR128:$dst, (int_x86_sse2_cvtdq2ps VR128:$src))]>, + TB, Requires<[HasSSE2]>; +def Int_CVTDQ2PSrm : I<0x5B, MRMSrcMem, (outs VR128:$dst), (ins i128mem:$src), + "cvtdq2ps\t{$src, $dst|$dst, $src}", + [(set VR128:$dst, (int_x86_sse2_cvtdq2ps + (bitconvert (memopv2i64 addr:$src))))]>, + TB, Requires<[HasSSE2]>; + +// SSE2 instructions with XS prefix +def Int_CVTDQ2PDrr : I<0xE6, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src), + "cvtdq2pd\t{$src, $dst|$dst, $src}", + [(set VR128:$dst, (int_x86_sse2_cvtdq2pd VR128:$src))]>, + XS, Requires<[HasSSE2]>; +def Int_CVTDQ2PDrm : I<0xE6, MRMSrcMem, (outs VR128:$dst), (ins i64mem:$src), + "cvtdq2pd\t{$src, $dst|$dst, $src}", + [(set VR128:$dst, (int_x86_sse2_cvtdq2pd + (bitconvert (memopv2i64 addr:$src))))]>, + XS, Requires<[HasSSE2]>; + +def Int_CVTPS2DQrr : PDI<0x5B, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src), + "cvtps2dq\t{$src, $dst|$dst, $src}", + [(set VR128:$dst, (int_x86_sse2_cvtps2dq VR128:$src))]>; +def Int_CVTPS2DQrm : PDI<0x5B, MRMSrcMem, (outs VR128:$dst), (ins f128mem:$src), + "cvtps2dq\t{$src, $dst|$dst, $src}", + [(set VR128:$dst, (int_x86_sse2_cvtps2dq + (memop addr:$src)))]>; +// SSE2 packed instructions with XS prefix +def Int_CVTTPS2DQrr : I<0x5B, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src), + "cvttps2dq\t{$src, $dst|$dst, $src}", + [(set VR128:$dst, (int_x86_sse2_cvttps2dq VR128:$src))]>, + XS, Requires<[HasSSE2]>; +def Int_CVTTPS2DQrm : I<0x5B, MRMSrcMem, (outs VR128:$dst), (ins f128mem:$src), + "cvttps2dq\t{$src, $dst|$dst, $src}", + [(set VR128:$dst, (int_x86_sse2_cvttps2dq + (memop addr:$src)))]>, + XS, Requires<[HasSSE2]>; + +// SSE2 packed instructions with XD prefix +def Int_CVTPD2DQrr : I<0xE6, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src), + "cvtpd2dq\t{$src, $dst|$dst, $src}", + [(set VR128:$dst, (int_x86_sse2_cvtpd2dq VR128:$src))]>, + XD, Requires<[HasSSE2]>; +def Int_CVTPD2DQrm : I<0xE6, MRMSrcMem, (outs VR128:$dst), (ins f128mem:$src), + "cvtpd2dq\t{$src, $dst|$dst, $src}", + [(set VR128:$dst, (int_x86_sse2_cvtpd2dq + (memop addr:$src)))]>, + XD, Requires<[HasSSE2]>; + +def Int_CVTTPD2DQrr : PDI<0xE6, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src), + "cvttpd2dq\t{$src, $dst|$dst, $src}", + [(set VR128:$dst, (int_x86_sse2_cvttpd2dq VR128:$src))]>; +def Int_CVTTPD2DQrm : PDI<0xE6, MRMSrcMem, (outs VR128:$dst),(ins f128mem:$src), + "cvttpd2dq\t{$src, $dst|$dst, $src}", + [(set VR128:$dst, (int_x86_sse2_cvttpd2dq + (memop addr:$src)))]>; + +// SSE2 instructions without OpSize prefix +def Int_CVTPS2PDrr : I<0x5A, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src), + "cvtps2pd\t{$src, $dst|$dst, $src}", + [(set VR128:$dst, (int_x86_sse2_cvtps2pd VR128:$src))]>, + TB, Requires<[HasSSE2]>; +def Int_CVTPS2PDrm : I<0x5A, MRMSrcMem, (outs VR128:$dst), (ins f64mem:$src), + "cvtps2pd\t{$src, $dst|$dst, $src}", + [(set VR128:$dst, (int_x86_sse2_cvtps2pd + (load addr:$src)))]>, + TB, Requires<[HasSSE2]>; + +def Int_CVTPD2PSrr : PDI<0x5A, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src), + "cvtpd2ps\t{$src, $dst|$dst, $src}", + [(set VR128:$dst, (int_x86_sse2_cvtpd2ps VR128:$src))]>; +def Int_CVTPD2PSrm : PDI<0x5A, MRMSrcMem, (outs VR128:$dst), (ins f128mem:$src), + "cvtpd2ps\t{$src, $dst|$dst, $src}", + [(set VR128:$dst, (int_x86_sse2_cvtpd2ps + (memop addr:$src)))]>; + +// Match intrinsics which expect XMM operand(s). +// Aliases for intrinsics +let Constraints = "$src1 = $dst" in { +def Int_CVTSI2SDrr: SDI<0x2A, MRMSrcReg, + (outs VR128:$dst), (ins VR128:$src1, GR32:$src2), + "cvtsi2sd\t{$src2, $dst|$dst, $src2}", + [(set VR128:$dst, (int_x86_sse2_cvtsi2sd VR128:$src1, + GR32:$src2))]>; +def Int_CVTSI2SDrm: SDI<0x2A, MRMSrcMem, + (outs VR128:$dst), (ins VR128:$src1, i32mem:$src2), + "cvtsi2sd\t{$src2, $dst|$dst, $src2}", + [(set VR128:$dst, (int_x86_sse2_cvtsi2sd VR128:$src1, + (loadi32 addr:$src2)))]>; +def Int_CVTSD2SSrr: SDI<0x5A, MRMSrcReg, + (outs VR128:$dst), (ins VR128:$src1, VR128:$src2), + "cvtsd2ss\t{$src2, $dst|$dst, $src2}", + [(set VR128:$dst, (int_x86_sse2_cvtsd2ss VR128:$src1, + VR128:$src2))]>; +def Int_CVTSD2SSrm: SDI<0x5A, MRMSrcMem, + (outs VR128:$dst), (ins VR128:$src1, f64mem:$src2), + "cvtsd2ss\t{$src2, $dst|$dst, $src2}", + [(set VR128:$dst, (int_x86_sse2_cvtsd2ss VR128:$src1, + (load addr:$src2)))]>; +def Int_CVTSS2SDrr: I<0x5A, MRMSrcReg, + (outs VR128:$dst), (ins VR128:$src1, VR128:$src2), + "cvtss2sd\t{$src2, $dst|$dst, $src2}", + [(set VR128:$dst, (int_x86_sse2_cvtss2sd VR128:$src1, + VR128:$src2))]>, XS, + Requires<[HasSSE2]>; +def Int_CVTSS2SDrm: I<0x5A, MRMSrcMem, + (outs VR128:$dst), (ins VR128:$src1, f32mem:$src2), + "cvtss2sd\t{$src2, $dst|$dst, $src2}", + [(set VR128:$dst, (int_x86_sse2_cvtss2sd VR128:$src1, + (load addr:$src2)))]>, XS, + Requires<[HasSSE2]>; +} + +// Arithmetic + +/// sse2_fp_unop_rm - SSE2 unops come in both scalar and vector forms. +/// +/// In addition, we also have a special variant of the scalar form here to +/// represent the associated intrinsic operation. This form is unlike the +/// plain scalar form, in that it takes an entire vector (instead of a +/// scalar) and leaves the top elements undefined. +/// +/// And, we have a special variant form for a full-vector intrinsic form. +/// +/// These four forms can each have a reg or a mem operand, so there are a +/// total of eight "instructions". +/// +multiclass sse2_fp_unop_rm opc, string OpcodeStr, + SDNode OpNode, + Intrinsic F64Int, + Intrinsic V2F64Int, + bit Commutable = 0> { + // Scalar operation, reg. + def SDr : SDI { + let isCommutable = Commutable; + } + + // Scalar operation, mem. + def SDm : SDI; + + // Vector operation, reg. + def PDr : PDI { + let isCommutable = Commutable; + } + + // Vector operation, mem. + def PDm : PDI; + + // Intrinsic operation, reg. + def SDr_Int : SDI { + let isCommutable = Commutable; + } + + // Intrinsic operation, mem. + def SDm_Int : SDI; + + // Vector intrinsic operation, reg + def PDr_Int : PDI { + let isCommutable = Commutable; + } + + // Vector intrinsic operation, mem + def PDm_Int : PDI; +} + +// Square root. +defm SQRT : sse2_fp_unop_rm<0x51, "sqrt", fsqrt, + int_x86_sse2_sqrt_sd, int_x86_sse2_sqrt_pd>; + +// There is no f64 version of the reciprocal approximation instructions. + +// Logical +let Constraints = "$src1 = $dst" in { + let isCommutable = 1 in { + def ANDPDrr : PDI<0x54, MRMSrcReg, + (outs VR128:$dst), (ins VR128:$src1, VR128:$src2), + "andpd\t{$src2, $dst|$dst, $src2}", + [(set VR128:$dst, + (and (bc_v2i64 (v2f64 VR128:$src1)), + (bc_v2i64 (v2f64 VR128:$src2))))]>; + def ORPDrr : PDI<0x56, MRMSrcReg, + (outs VR128:$dst), (ins VR128:$src1, VR128:$src2), + "orpd\t{$src2, $dst|$dst, $src2}", + [(set VR128:$dst, + (or (bc_v2i64 (v2f64 VR128:$src1)), + (bc_v2i64 (v2f64 VR128:$src2))))]>; + def XORPDrr : PDI<0x57, MRMSrcReg, + (outs VR128:$dst), (ins VR128:$src1, VR128:$src2), + "xorpd\t{$src2, $dst|$dst, $src2}", + [(set VR128:$dst, + (xor (bc_v2i64 (v2f64 VR128:$src1)), + (bc_v2i64 (v2f64 VR128:$src2))))]>; + } + + def ANDPDrm : PDI<0x54, MRMSrcMem, + (outs VR128:$dst), (ins VR128:$src1, f128mem:$src2), + "andpd\t{$src2, $dst|$dst, $src2}", + [(set VR128:$dst, + (and (bc_v2i64 (v2f64 VR128:$src1)), + (memopv2i64 addr:$src2)))]>; + def ORPDrm : PDI<0x56, MRMSrcMem, + (outs VR128:$dst), (ins VR128:$src1, f128mem:$src2), + "orpd\t{$src2, $dst|$dst, $src2}", + [(set VR128:$dst, + (or (bc_v2i64 (v2f64 VR128:$src1)), + (memopv2i64 addr:$src2)))]>; + def XORPDrm : PDI<0x57, MRMSrcMem, + (outs VR128:$dst), (ins VR128:$src1, f128mem:$src2), + "xorpd\t{$src2, $dst|$dst, $src2}", + [(set VR128:$dst, + (xor (bc_v2i64 (v2f64 VR128:$src1)), + (memopv2i64 addr:$src2)))]>; + def ANDNPDrr : PDI<0x55, MRMSrcReg, + (outs VR128:$dst), (ins VR128:$src1, VR128:$src2), + "andnpd\t{$src2, $dst|$dst, $src2}", + [(set VR128:$dst, + (and (vnot (bc_v2i64 (v2f64 VR128:$src1))), + (bc_v2i64 (v2f64 VR128:$src2))))]>; + def ANDNPDrm : PDI<0x55, MRMSrcMem, + (outs VR128:$dst), (ins VR128:$src1,f128mem:$src2), + "andnpd\t{$src2, $dst|$dst, $src2}", + [(set VR128:$dst, + (and (vnot (bc_v2i64 (v2f64 VR128:$src1))), + (memopv2i64 addr:$src2)))]>; +} + +let Constraints = "$src1 = $dst" in { + def CMPPDrri : PDIi8<0xC2, MRMSrcReg, + (outs VR128:$dst), (ins VR128:$src1, VR128:$src, SSECC:$cc), + "cmp${cc}pd\t{$src, $dst|$dst, $src}", + [(set VR128:$dst, (int_x86_sse2_cmp_pd VR128:$src1, + VR128:$src, imm:$cc))]>; + def CMPPDrmi : PDIi8<0xC2, MRMSrcMem, + (outs VR128:$dst), (ins VR128:$src1, f128mem:$src, SSECC:$cc), + "cmp${cc}pd\t{$src, $dst|$dst, $src}", + [(set VR128:$dst, (int_x86_sse2_cmp_pd VR128:$src1, + (memop addr:$src), imm:$cc))]>; +} +def : Pat<(v2i64 (X86cmppd (v2f64 VR128:$src1), VR128:$src2, imm:$cc)), + (CMPPDrri VR128:$src1, VR128:$src2, imm:$cc)>; +def : Pat<(v2i64 (X86cmppd (v2f64 VR128:$src1), (memop addr:$src2), imm:$cc)), + (CMPPDrmi VR128:$src1, addr:$src2, imm:$cc)>; + +// Shuffle and unpack instructions +let Constraints = "$src1 = $dst" in { + def SHUFPDrri : PDIi8<0xC6, MRMSrcReg, + (outs VR128:$dst), (ins VR128:$src1, VR128:$src2, i8imm:$src3), + "shufpd\t{$src3, $src2, $dst|$dst, $src2, $src3}", + [(set VR128:$dst, + (v2f64 (shufp:$src3 VR128:$src1, VR128:$src2)))]>; + def SHUFPDrmi : PDIi8<0xC6, MRMSrcMem, + (outs VR128:$dst), (ins VR128:$src1, + f128mem:$src2, i8imm:$src3), + "shufpd\t{$src3, $src2, $dst|$dst, $src2, $src3}", + [(set VR128:$dst, + (v2f64 (shufp:$src3 + VR128:$src1, (memopv2f64 addr:$src2))))]>; + + let AddedComplexity = 10 in { + def UNPCKHPDrr : PDI<0x15, MRMSrcReg, + (outs VR128:$dst), (ins VR128:$src1, VR128:$src2), + "unpckhpd\t{$src2, $dst|$dst, $src2}", + [(set VR128:$dst, + (v2f64 (unpckh VR128:$src1, VR128:$src2)))]>; + def UNPCKHPDrm : PDI<0x15, MRMSrcMem, + (outs VR128:$dst), (ins VR128:$src1, f128mem:$src2), + "unpckhpd\t{$src2, $dst|$dst, $src2}", + [(set VR128:$dst, + (v2f64 (unpckh VR128:$src1, + (memopv2f64 addr:$src2))))]>; + + def UNPCKLPDrr : PDI<0x14, MRMSrcReg, + (outs VR128:$dst), (ins VR128:$src1, VR128:$src2), + "unpcklpd\t{$src2, $dst|$dst, $src2}", + [(set VR128:$dst, + (v2f64 (unpckl VR128:$src1, VR128:$src2)))]>; + def UNPCKLPDrm : PDI<0x14, MRMSrcMem, + (outs VR128:$dst), (ins VR128:$src1, f128mem:$src2), + "unpcklpd\t{$src2, $dst|$dst, $src2}", + [(set VR128:$dst, + (unpckl VR128:$src1, (memopv2f64 addr:$src2)))]>; + } // AddedComplexity +} // Constraints = "$src1 = $dst" + + +//===---------------------------------------------------------------------===// +// SSE integer instructions + +// Move Instructions +let neverHasSideEffects = 1 in +def MOVDQArr : PDI<0x6F, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src), + "movdqa\t{$src, $dst|$dst, $src}", []>; +let canFoldAsLoad = 1, mayLoad = 1 in +def MOVDQArm : PDI<0x6F, MRMSrcMem, (outs VR128:$dst), (ins i128mem:$src), + "movdqa\t{$src, $dst|$dst, $src}", + [/*(set VR128:$dst, (alignedloadv2i64 addr:$src))*/]>; +let mayStore = 1 in +def MOVDQAmr : PDI<0x7F, MRMDestMem, (outs), (ins i128mem:$dst, VR128:$src), + "movdqa\t{$src, $dst|$dst, $src}", + [/*(alignedstore (v2i64 VR128:$src), addr:$dst)*/]>; +let canFoldAsLoad = 1, mayLoad = 1 in +def MOVDQUrm : I<0x6F, MRMSrcMem, (outs VR128:$dst), (ins i128mem:$src), + "movdqu\t{$src, $dst|$dst, $src}", + [/*(set VR128:$dst, (loadv2i64 addr:$src))*/]>, + XS, Requires<[HasSSE2]>; +let mayStore = 1 in +def MOVDQUmr : I<0x7F, MRMDestMem, (outs), (ins i128mem:$dst, VR128:$src), + "movdqu\t{$src, $dst|$dst, $src}", + [/*(store (v2i64 VR128:$src), addr:$dst)*/]>, + XS, Requires<[HasSSE2]>; + +// Intrinsic forms of MOVDQU load and store +let canFoldAsLoad = 1 in +def MOVDQUrm_Int : I<0x6F, MRMSrcMem, (outs VR128:$dst), (ins i128mem:$src), + "movdqu\t{$src, $dst|$dst, $src}", + [(set VR128:$dst, (int_x86_sse2_loadu_dq addr:$src))]>, + XS, Requires<[HasSSE2]>; +def MOVDQUmr_Int : I<0x7F, MRMDestMem, (outs), (ins i128mem:$dst, VR128:$src), + "movdqu\t{$src, $dst|$dst, $src}", + [(int_x86_sse2_storeu_dq addr:$dst, VR128:$src)]>, + XS, Requires<[HasSSE2]>; + +let Constraints = "$src1 = $dst" in { + +multiclass PDI_binop_rm_int opc, string OpcodeStr, Intrinsic IntId, + bit Commutable = 0> { + def rr : PDI { + let isCommutable = Commutable; + } + def rm : PDI; +} + +multiclass PDI_binop_rmi_int opc, bits<8> opc2, Format ImmForm, + string OpcodeStr, + Intrinsic IntId, Intrinsic IntId2> { + def rr : PDI; + def rm : PDI; + def ri : PDIi8; +} + +/// PDI_binop_rm - Simple SSE2 binary operator. +multiclass PDI_binop_rm opc, string OpcodeStr, SDNode OpNode, + ValueType OpVT, bit Commutable = 0> { + def rr : PDI { + let isCommutable = Commutable; + } + def rm : PDI; +} + +/// PDI_binop_rm_v2i64 - Simple SSE2 binary operator whose type is v2i64. +/// +/// FIXME: we could eliminate this and use PDI_binop_rm instead if tblgen knew +/// to collapse (bitconvert VT to VT) into its operand. +/// +multiclass PDI_binop_rm_v2i64 opc, string OpcodeStr, SDNode OpNode, + bit Commutable = 0> { + def rr : PDI { + let isCommutable = Commutable; + } + def rm : PDI; +} + +} // Constraints = "$src1 = $dst" + +// 128-bit Integer Arithmetic + +defm PADDB : PDI_binop_rm<0xFC, "paddb", add, v16i8, 1>; +defm PADDW : PDI_binop_rm<0xFD, "paddw", add, v8i16, 1>; +defm PADDD : PDI_binop_rm<0xFE, "paddd", add, v4i32, 1>; +defm PADDQ : PDI_binop_rm_v2i64<0xD4, "paddq", add, 1>; + +defm PADDSB : PDI_binop_rm_int<0xEC, "paddsb" , int_x86_sse2_padds_b, 1>; +defm PADDSW : PDI_binop_rm_int<0xED, "paddsw" , int_x86_sse2_padds_w, 1>; +defm PADDUSB : PDI_binop_rm_int<0xDC, "paddusb", int_x86_sse2_paddus_b, 1>; +defm PADDUSW : PDI_binop_rm_int<0xDD, "paddusw", int_x86_sse2_paddus_w, 1>; + +defm PSUBB : PDI_binop_rm<0xF8, "psubb", sub, v16i8>; +defm PSUBW : PDI_binop_rm<0xF9, "psubw", sub, v8i16>; +defm PSUBD : PDI_binop_rm<0xFA, "psubd", sub, v4i32>; +defm PSUBQ : PDI_binop_rm_v2i64<0xFB, "psubq", sub>; + +defm PSUBSB : PDI_binop_rm_int<0xE8, "psubsb" , int_x86_sse2_psubs_b>; +defm PSUBSW : PDI_binop_rm_int<0xE9, "psubsw" , int_x86_sse2_psubs_w>; +defm PSUBUSB : PDI_binop_rm_int<0xD8, "psubusb", int_x86_sse2_psubus_b>; +defm PSUBUSW : PDI_binop_rm_int<0xD9, "psubusw", int_x86_sse2_psubus_w>; + +defm PMULLW : PDI_binop_rm<0xD5, "pmullw", mul, v8i16, 1>; + +defm PMULHUW : PDI_binop_rm_int<0xE4, "pmulhuw", int_x86_sse2_pmulhu_w, 1>; +defm PMULHW : PDI_binop_rm_int<0xE5, "pmulhw" , int_x86_sse2_pmulh_w , 1>; +defm PMULUDQ : PDI_binop_rm_int<0xF4, "pmuludq", int_x86_sse2_pmulu_dq, 1>; + +defm PMADDWD : PDI_binop_rm_int<0xF5, "pmaddwd", int_x86_sse2_pmadd_wd, 1>; + +defm PAVGB : PDI_binop_rm_int<0xE0, "pavgb", int_x86_sse2_pavg_b, 1>; +defm PAVGW : PDI_binop_rm_int<0xE3, "pavgw", int_x86_sse2_pavg_w, 1>; + + +defm PMINUB : PDI_binop_rm_int<0xDA, "pminub", int_x86_sse2_pminu_b, 1>; +defm PMINSW : PDI_binop_rm_int<0xEA, "pminsw", int_x86_sse2_pmins_w, 1>; +defm PMAXUB : PDI_binop_rm_int<0xDE, "pmaxub", int_x86_sse2_pmaxu_b, 1>; +defm PMAXSW : PDI_binop_rm_int<0xEE, "pmaxsw", int_x86_sse2_pmaxs_w, 1>; +defm PSADBW : PDI_binop_rm_int<0xF6, "psadbw", int_x86_sse2_psad_bw, 1>; + + +defm PSLLW : PDI_binop_rmi_int<0xF1, 0x71, MRM6r, "psllw", + int_x86_sse2_psll_w, int_x86_sse2_pslli_w>; +defm PSLLD : PDI_binop_rmi_int<0xF2, 0x72, MRM6r, "pslld", + int_x86_sse2_psll_d, int_x86_sse2_pslli_d>; +defm PSLLQ : PDI_binop_rmi_int<0xF3, 0x73, MRM6r, "psllq", + int_x86_sse2_psll_q, int_x86_sse2_pslli_q>; + +defm PSRLW : PDI_binop_rmi_int<0xD1, 0x71, MRM2r, "psrlw", + int_x86_sse2_psrl_w, int_x86_sse2_psrli_w>; +defm PSRLD : PDI_binop_rmi_int<0xD2, 0x72, MRM2r, "psrld", + int_x86_sse2_psrl_d, int_x86_sse2_psrli_d>; +defm PSRLQ : PDI_binop_rmi_int<0xD3, 0x73, MRM2r, "psrlq", + int_x86_sse2_psrl_q, int_x86_sse2_psrli_q>; + +defm PSRAW : PDI_binop_rmi_int<0xE1, 0x71, MRM4r, "psraw", + int_x86_sse2_psra_w, int_x86_sse2_psrai_w>; +defm PSRAD : PDI_binop_rmi_int<0xE2, 0x72, MRM4r, "psrad", + int_x86_sse2_psra_d, int_x86_sse2_psrai_d>; + +// 128-bit logical shifts. +let Constraints = "$src1 = $dst", neverHasSideEffects = 1 in { + def PSLLDQri : PDIi8<0x73, MRM7r, + (outs VR128:$dst), (ins VR128:$src1, i32i8imm:$src2), + "pslldq\t{$src2, $dst|$dst, $src2}", []>; + def PSRLDQri : PDIi8<0x73, MRM3r, + (outs VR128:$dst), (ins VR128:$src1, i32i8imm:$src2), + "psrldq\t{$src2, $dst|$dst, $src2}", []>; + // PSRADQri doesn't exist in SSE[1-3]. +} + +let Predicates = [HasSSE2] in { + def : Pat<(int_x86_sse2_psll_dq VR128:$src1, imm:$src2), + (v2i64 (PSLLDQri VR128:$src1, (BYTE_imm imm:$src2)))>; + def : Pat<(int_x86_sse2_psrl_dq VR128:$src1, imm:$src2), + (v2i64 (PSRLDQri VR128:$src1, (BYTE_imm imm:$src2)))>; + def : Pat<(int_x86_sse2_psll_dq_bs VR128:$src1, imm:$src2), + (v2i64 (PSLLDQri VR128:$src1, imm:$src2))>; + def : Pat<(int_x86_sse2_psrl_dq_bs VR128:$src1, imm:$src2), + (v2i64 (PSRLDQri VR128:$src1, imm:$src2))>; + def : Pat<(v2f64 (X86fsrl VR128:$src1, i32immSExt8:$src2)), + (v2f64 (PSRLDQri VR128:$src1, (BYTE_imm imm:$src2)))>; + + // Shift up / down and insert zero's. + def : Pat<(v2i64 (X86vshl VR128:$src, (i8 imm:$amt))), + (v2i64 (PSLLDQri VR128:$src, (BYTE_imm imm:$amt)))>; + def : Pat<(v2i64 (X86vshr VR128:$src, (i8 imm:$amt))), + (v2i64 (PSRLDQri VR128:$src, (BYTE_imm imm:$amt)))>; +} + +// Logical +defm PAND : PDI_binop_rm_v2i64<0xDB, "pand", and, 1>; +defm POR : PDI_binop_rm_v2i64<0xEB, "por" , or , 1>; +defm PXOR : PDI_binop_rm_v2i64<0xEF, "pxor", xor, 1>; + +let Constraints = "$src1 = $dst" in { + def PANDNrr : PDI<0xDF, MRMSrcReg, + (outs VR128:$dst), (ins VR128:$src1, VR128:$src2), + "pandn\t{$src2, $dst|$dst, $src2}", + [(set VR128:$dst, (v2i64 (and (vnot VR128:$src1), + VR128:$src2)))]>; + + def PANDNrm : PDI<0xDF, MRMSrcMem, + (outs VR128:$dst), (ins VR128:$src1, i128mem:$src2), + "pandn\t{$src2, $dst|$dst, $src2}", + [(set VR128:$dst, (v2i64 (and (vnot VR128:$src1), + (memopv2i64 addr:$src2))))]>; +} + +// SSE2 Integer comparison +defm PCMPEQB : PDI_binop_rm_int<0x74, "pcmpeqb", int_x86_sse2_pcmpeq_b>; +defm PCMPEQW : PDI_binop_rm_int<0x75, "pcmpeqw", int_x86_sse2_pcmpeq_w>; +defm PCMPEQD : PDI_binop_rm_int<0x76, "pcmpeqd", int_x86_sse2_pcmpeq_d>; +defm PCMPGTB : PDI_binop_rm_int<0x64, "pcmpgtb", int_x86_sse2_pcmpgt_b>; +defm PCMPGTW : PDI_binop_rm_int<0x65, "pcmpgtw", int_x86_sse2_pcmpgt_w>; +defm PCMPGTD : PDI_binop_rm_int<0x66, "pcmpgtd", int_x86_sse2_pcmpgt_d>; + +def : Pat<(v16i8 (X86pcmpeqb VR128:$src1, VR128:$src2)), + (PCMPEQBrr VR128:$src1, VR128:$src2)>; +def : Pat<(v16i8 (X86pcmpeqb VR128:$src1, (memop addr:$src2))), + (PCMPEQBrm VR128:$src1, addr:$src2)>; +def : Pat<(v8i16 (X86pcmpeqw VR128:$src1, VR128:$src2)), + (PCMPEQWrr VR128:$src1, VR128:$src2)>; +def : Pat<(v8i16 (X86pcmpeqw VR128:$src1, (memop addr:$src2))), + (PCMPEQWrm VR128:$src1, addr:$src2)>; +def : Pat<(v4i32 (X86pcmpeqd VR128:$src1, VR128:$src2)), + (PCMPEQDrr VR128:$src1, VR128:$src2)>; +def : Pat<(v4i32 (X86pcmpeqd VR128:$src1, (memop addr:$src2))), + (PCMPEQDrm VR128:$src1, addr:$src2)>; + +def : Pat<(v16i8 (X86pcmpgtb VR128:$src1, VR128:$src2)), + (PCMPGTBrr VR128:$src1, VR128:$src2)>; +def : Pat<(v16i8 (X86pcmpgtb VR128:$src1, (memop addr:$src2))), + (PCMPGTBrm VR128:$src1, addr:$src2)>; +def : Pat<(v8i16 (X86pcmpgtw VR128:$src1, VR128:$src2)), + (PCMPGTWrr VR128:$src1, VR128:$src2)>; +def : Pat<(v8i16 (X86pcmpgtw VR128:$src1, (memop addr:$src2))), + (PCMPGTWrm VR128:$src1, addr:$src2)>; +def : Pat<(v4i32 (X86pcmpgtd VR128:$src1, VR128:$src2)), + (PCMPGTDrr VR128:$src1, VR128:$src2)>; +def : Pat<(v4i32 (X86pcmpgtd VR128:$src1, (memop addr:$src2))), + (PCMPGTDrm VR128:$src1, addr:$src2)>; + + +// Pack instructions +defm PACKSSWB : PDI_binop_rm_int<0x63, "packsswb", int_x86_sse2_packsswb_128>; +defm PACKSSDW : PDI_binop_rm_int<0x6B, "packssdw", int_x86_sse2_packssdw_128>; +defm PACKUSWB : PDI_binop_rm_int<0x67, "packuswb", int_x86_sse2_packuswb_128>; + +// Shuffle and unpack instructions +let AddedComplexity = 5 in { +def PSHUFDri : PDIi8<0x70, MRMSrcReg, + (outs VR128:$dst), (ins VR128:$src1, i8imm:$src2), + "pshufd\t{$src2, $src1, $dst|$dst, $src1, $src2}", + [(set VR128:$dst, (v4i32 (pshufd:$src2 + VR128:$src1, (undef))))]>; +def PSHUFDmi : PDIi8<0x70, MRMSrcMem, + (outs VR128:$dst), (ins i128mem:$src1, i8imm:$src2), + "pshufd\t{$src2, $src1, $dst|$dst, $src1, $src2}", + [(set VR128:$dst, (v4i32 (pshufd:$src2 + (bc_v4i32(memopv2i64 addr:$src1)), + (undef))))]>; +} + +// SSE2 with ImmT == Imm8 and XS prefix. +def PSHUFHWri : Ii8<0x70, MRMSrcReg, + (outs VR128:$dst), (ins VR128:$src1, i8imm:$src2), + "pshufhw\t{$src2, $src1, $dst|$dst, $src1, $src2}", + [(set VR128:$dst, (v8i16 (pshufhw:$src2 VR128:$src1, + (undef))))]>, + XS, Requires<[HasSSE2]>; +def PSHUFHWmi : Ii8<0x70, MRMSrcMem, + (outs VR128:$dst), (ins i128mem:$src1, i8imm:$src2), + "pshufhw\t{$src2, $src1, $dst|$dst, $src1, $src2}", + [(set VR128:$dst, (v8i16 (pshufhw:$src2 + (bc_v8i16 (memopv2i64 addr:$src1)), + (undef))))]>, + XS, Requires<[HasSSE2]>; + +// SSE2 with ImmT == Imm8 and XD prefix. +def PSHUFLWri : Ii8<0x70, MRMSrcReg, + (outs VR128:$dst), (ins VR128:$src1, i8imm:$src2), + "pshuflw\t{$src2, $src1, $dst|$dst, $src1, $src2}", + [(set VR128:$dst, (v8i16 (pshuflw:$src2 VR128:$src1, + (undef))))]>, + XD, Requires<[HasSSE2]>; +def PSHUFLWmi : Ii8<0x70, MRMSrcMem, + (outs VR128:$dst), (ins i128mem:$src1, i8imm:$src2), + "pshuflw\t{$src2, $src1, $dst|$dst, $src1, $src2}", + [(set VR128:$dst, (v8i16 (pshuflw:$src2 + (bc_v8i16 (memopv2i64 addr:$src1)), + (undef))))]>, + XD, Requires<[HasSSE2]>; + + +let Constraints = "$src1 = $dst" in { + def PUNPCKLBWrr : PDI<0x60, MRMSrcReg, + (outs VR128:$dst), (ins VR128:$src1, VR128:$src2), + "punpcklbw\t{$src2, $dst|$dst, $src2}", + [(set VR128:$dst, + (v16i8 (unpckl VR128:$src1, VR128:$src2)))]>; + def PUNPCKLBWrm : PDI<0x60, MRMSrcMem, + (outs VR128:$dst), (ins VR128:$src1, i128mem:$src2), + "punpcklbw\t{$src2, $dst|$dst, $src2}", + [(set VR128:$dst, + (unpckl VR128:$src1, + (bc_v16i8 (memopv2i64 addr:$src2))))]>; + def PUNPCKLWDrr : PDI<0x61, MRMSrcReg, + (outs VR128:$dst), (ins VR128:$src1, VR128:$src2), + "punpcklwd\t{$src2, $dst|$dst, $src2}", + [(set VR128:$dst, + (v8i16 (unpckl VR128:$src1, VR128:$src2)))]>; + def PUNPCKLWDrm : PDI<0x61, MRMSrcMem, + (outs VR128:$dst), (ins VR128:$src1, i128mem:$src2), + "punpcklwd\t{$src2, $dst|$dst, $src2}", + [(set VR128:$dst, + (unpckl VR128:$src1, + (bc_v8i16 (memopv2i64 addr:$src2))))]>; + def PUNPCKLDQrr : PDI<0x62, MRMSrcReg, + (outs VR128:$dst), (ins VR128:$src1, VR128:$src2), + "punpckldq\t{$src2, $dst|$dst, $src2}", + [(set VR128:$dst, + (v4i32 (unpckl VR128:$src1, VR128:$src2)))]>; + def PUNPCKLDQrm : PDI<0x62, MRMSrcMem, + (outs VR128:$dst), (ins VR128:$src1, i128mem:$src2), + "punpckldq\t{$src2, $dst|$dst, $src2}", + [(set VR128:$dst, + (unpckl VR128:$src1, + (bc_v4i32 (memopv2i64 addr:$src2))))]>; + def PUNPCKLQDQrr : PDI<0x6C, MRMSrcReg, + (outs VR128:$dst), (ins VR128:$src1, VR128:$src2), + "punpcklqdq\t{$src2, $dst|$dst, $src2}", + [(set VR128:$dst, + (v2i64 (unpckl VR128:$src1, VR128:$src2)))]>; + def PUNPCKLQDQrm : PDI<0x6C, MRMSrcMem, + (outs VR128:$dst), (ins VR128:$src1, i128mem:$src2), + "punpcklqdq\t{$src2, $dst|$dst, $src2}", + [(set VR128:$dst, + (v2i64 (unpckl VR128:$src1, + (memopv2i64 addr:$src2))))]>; + + def PUNPCKHBWrr : PDI<0x68, MRMSrcReg, + (outs VR128:$dst), (ins VR128:$src1, VR128:$src2), + "punpckhbw\t{$src2, $dst|$dst, $src2}", + [(set VR128:$dst, + (v16i8 (unpckh VR128:$src1, VR128:$src2)))]>; + def PUNPCKHBWrm : PDI<0x68, MRMSrcMem, + (outs VR128:$dst), (ins VR128:$src1, i128mem:$src2), + "punpckhbw\t{$src2, $dst|$dst, $src2}", + [(set VR128:$dst, + (unpckh VR128:$src1, + (bc_v16i8 (memopv2i64 addr:$src2))))]>; + def PUNPCKHWDrr : PDI<0x69, MRMSrcReg, + (outs VR128:$dst), (ins VR128:$src1, VR128:$src2), + "punpckhwd\t{$src2, $dst|$dst, $src2}", + [(set VR128:$dst, + (v8i16 (unpckh VR128:$src1, VR128:$src2)))]>; + def PUNPCKHWDrm : PDI<0x69, MRMSrcMem, + (outs VR128:$dst), (ins VR128:$src1, i128mem:$src2), + "punpckhwd\t{$src2, $dst|$dst, $src2}", + [(set VR128:$dst, + (unpckh VR128:$src1, + (bc_v8i16 (memopv2i64 addr:$src2))))]>; + def PUNPCKHDQrr : PDI<0x6A, MRMSrcReg, + (outs VR128:$dst), (ins VR128:$src1, VR128:$src2), + "punpckhdq\t{$src2, $dst|$dst, $src2}", + [(set VR128:$dst, + (v4i32 (unpckh VR128:$src1, VR128:$src2)))]>; + def PUNPCKHDQrm : PDI<0x6A, MRMSrcMem, + (outs VR128:$dst), (ins VR128:$src1, i128mem:$src2), + "punpckhdq\t{$src2, $dst|$dst, $src2}", + [(set VR128:$dst, + (unpckh VR128:$src1, + (bc_v4i32 (memopv2i64 addr:$src2))))]>; + def PUNPCKHQDQrr : PDI<0x6D, MRMSrcReg, + (outs VR128:$dst), (ins VR128:$src1, VR128:$src2), + "punpckhqdq\t{$src2, $dst|$dst, $src2}", + [(set VR128:$dst, + (v2i64 (unpckh VR128:$src1, VR128:$src2)))]>; + def PUNPCKHQDQrm : PDI<0x6D, MRMSrcMem, + (outs VR128:$dst), (ins VR128:$src1, i128mem:$src2), + "punpckhqdq\t{$src2, $dst|$dst, $src2}", + [(set VR128:$dst, + (v2i64 (unpckh VR128:$src1, + (memopv2i64 addr:$src2))))]>; +} + +// Extract / Insert +def PEXTRWri : PDIi8<0xC5, MRMSrcReg, + (outs GR32:$dst), (ins VR128:$src1, i32i8imm:$src2), + "pextrw\t{$src2, $src1, $dst|$dst, $src1, $src2}", + [(set GR32:$dst, (X86pextrw (v8i16 VR128:$src1), + imm:$src2))]>; +let Constraints = "$src1 = $dst" in { + def PINSRWrri : PDIi8<0xC4, MRMSrcReg, + (outs VR128:$dst), (ins VR128:$src1, + GR32:$src2, i32i8imm:$src3), + "pinsrw\t{$src3, $src2, $dst|$dst, $src2, $src3}", + [(set VR128:$dst, + (X86pinsrw VR128:$src1, GR32:$src2, imm:$src3))]>; + def PINSRWrmi : PDIi8<0xC4, MRMSrcMem, + (outs VR128:$dst), (ins VR128:$src1, + i16mem:$src2, i32i8imm:$src3), + "pinsrw\t{$src3, $src2, $dst|$dst, $src2, $src3}", + [(set VR128:$dst, + (X86pinsrw VR128:$src1, (extloadi16 addr:$src2), + imm:$src3))]>; +} + +// Mask creation +def PMOVMSKBrr : PDI<0xD7, MRMSrcReg, (outs GR32:$dst), (ins VR128:$src), + "pmovmskb\t{$src, $dst|$dst, $src}", + [(set GR32:$dst, (int_x86_sse2_pmovmskb_128 VR128:$src))]>; + +// Conditional store +let Uses = [EDI] in +def MASKMOVDQU : PDI<0xF7, MRMSrcReg, (outs), (ins VR128:$src, VR128:$mask), + "maskmovdqu\t{$mask, $src|$src, $mask}", + [(int_x86_sse2_maskmov_dqu VR128:$src, VR128:$mask, EDI)]>; + +let Uses = [RDI] in +def MASKMOVDQU64 : PDI<0xF7, MRMSrcReg, (outs), (ins VR128:$src, VR128:$mask), + "maskmovdqu\t{$mask, $src|$src, $mask}", + [(int_x86_sse2_maskmov_dqu VR128:$src, VR128:$mask, RDI)]>; + +// Non-temporal stores +def MOVNTPDmr : PDI<0x2B, MRMDestMem, (outs), (ins i128mem:$dst, VR128:$src), + "movntpd\t{$src, $dst|$dst, $src}", + [(int_x86_sse2_movnt_pd addr:$dst, VR128:$src)]>; +def MOVNTDQmr : PDI<0xE7, MRMDestMem, (outs), (ins f128mem:$dst, VR128:$src), + "movntdq\t{$src, $dst|$dst, $src}", + [(int_x86_sse2_movnt_dq addr:$dst, VR128:$src)]>; +def MOVNTImr : I<0xC3, MRMDestMem, (outs), (ins i32mem:$dst, GR32:$src), + "movnti\t{$src, $dst|$dst, $src}", + [(int_x86_sse2_movnt_i addr:$dst, GR32:$src)]>, + TB, Requires<[HasSSE2]>; + +// Flush cache +def CLFLUSH : I<0xAE, MRM7m, (outs), (ins i8mem:$src), + "clflush\t$src", [(int_x86_sse2_clflush addr:$src)]>, + TB, Requires<[HasSSE2]>; + +// Load, store, and memory fence +def LFENCE : I<0xAE, MRM5r, (outs), (ins), + "lfence", [(int_x86_sse2_lfence)]>, TB, Requires<[HasSSE2]>; +def MFENCE : I<0xAE, MRM6r, (outs), (ins), + "mfence", [(int_x86_sse2_mfence)]>, TB, Requires<[HasSSE2]>; + +//TODO: custom lower this so as to never even generate the noop +def : Pat<(membarrier (i8 imm:$ll), (i8 imm:$ls), (i8 imm:$sl), (i8 imm:$ss), + (i8 0)), (NOOP)>; +def : Pat<(membarrier (i8 0), (i8 0), (i8 0), (i8 1), (i8 1)), (SFENCE)>; +def : Pat<(membarrier (i8 1), (i8 0), (i8 0), (i8 0), (i8 1)), (LFENCE)>; +def : Pat<(membarrier (i8 imm:$ll), (i8 imm:$ls), (i8 imm:$sl), (i8 imm:$ss), + (i8 1)), (MFENCE)>; + +// Alias instructions that map zero vector to pxor / xorp* for sse. +// We set canFoldAsLoad because this can be converted to a constant-pool +// load of an all-ones value if folding it would be beneficial. +let isReMaterializable = 1, isAsCheapAsAMove = 1, canFoldAsLoad = 1, + isCodeGenOnly = 1 in + def V_SETALLONES : PDI<0x76, MRMInitReg, (outs VR128:$dst), (ins), + "pcmpeqd\t$dst, $dst", + [(set VR128:$dst, (v4i32 immAllOnesV))]>; + +// FR64 to 128-bit vector conversion. +let isAsCheapAsAMove = 1 in +def MOVSD2PDrr : SDI<0x10, MRMSrcReg, (outs VR128:$dst), (ins FR64:$src), + "movsd\t{$src, $dst|$dst, $src}", + [(set VR128:$dst, + (v2f64 (scalar_to_vector FR64:$src)))]>; +def MOVSD2PDrm : SDI<0x10, MRMSrcMem, (outs VR128:$dst), (ins f64mem:$src), + "movsd\t{$src, $dst|$dst, $src}", + [(set VR128:$dst, + (v2f64 (scalar_to_vector (loadf64 addr:$src))))]>; + +def MOVDI2PDIrr : PDI<0x6E, MRMSrcReg, (outs VR128:$dst), (ins GR32:$src), + "movd\t{$src, $dst|$dst, $src}", + [(set VR128:$dst, + (v4i32 (scalar_to_vector GR32:$src)))]>; +def MOVDI2PDIrm : PDI<0x6E, MRMSrcMem, (outs VR128:$dst), (ins i32mem:$src), + "movd\t{$src, $dst|$dst, $src}", + [(set VR128:$dst, + (v4i32 (scalar_to_vector (loadi32 addr:$src))))]>; + +def MOVDI2SSrr : PDI<0x6E, MRMSrcReg, (outs FR32:$dst), (ins GR32:$src), + "movd\t{$src, $dst|$dst, $src}", + [(set FR32:$dst, (bitconvert GR32:$src))]>; + +def MOVDI2SSrm : PDI<0x6E, MRMSrcMem, (outs FR32:$dst), (ins i32mem:$src), + "movd\t{$src, $dst|$dst, $src}", + [(set FR32:$dst, (bitconvert (loadi32 addr:$src)))]>; + +// SSE2 instructions with XS prefix +def MOVQI2PQIrm : I<0x7E, MRMSrcMem, (outs VR128:$dst), (ins i64mem:$src), + "movq\t{$src, $dst|$dst, $src}", + [(set VR128:$dst, + (v2i64 (scalar_to_vector (loadi64 addr:$src))))]>, XS, + Requires<[HasSSE2]>; +def MOVPQI2QImr : PDI<0xD6, MRMDestMem, (outs), (ins i64mem:$dst, VR128:$src), + "movq\t{$src, $dst|$dst, $src}", + [(store (i64 (vector_extract (v2i64 VR128:$src), + (iPTR 0))), addr:$dst)]>; + +// FIXME: may not be able to eliminate this movss with coalescing the src and +// dest register classes are different. We really want to write this pattern +// like this: +// def : Pat<(f32 (vector_extract (v4f32 VR128:$src), (iPTR 0))), +// (f32 FR32:$src)>; +let isAsCheapAsAMove = 1 in +def MOVPD2SDrr : SDI<0x10, MRMSrcReg, (outs FR64:$dst), (ins VR128:$src), + "movsd\t{$src, $dst|$dst, $src}", + [(set FR64:$dst, (vector_extract (v2f64 VR128:$src), + (iPTR 0)))]>; +def MOVPD2SDmr : SDI<0x11, MRMDestMem, (outs), (ins f64mem:$dst, VR128:$src), + "movsd\t{$src, $dst|$dst, $src}", + [(store (f64 (vector_extract (v2f64 VR128:$src), + (iPTR 0))), addr:$dst)]>; +def MOVPDI2DIrr : PDI<0x7E, MRMDestReg, (outs GR32:$dst), (ins VR128:$src), + "movd\t{$src, $dst|$dst, $src}", + [(set GR32:$dst, (vector_extract (v4i32 VR128:$src), + (iPTR 0)))]>; +def MOVPDI2DImr : PDI<0x7E, MRMDestMem, (outs), (ins i32mem:$dst, VR128:$src), + "movd\t{$src, $dst|$dst, $src}", + [(store (i32 (vector_extract (v4i32 VR128:$src), + (iPTR 0))), addr:$dst)]>; + +def MOVSS2DIrr : PDI<0x7E, MRMDestReg, (outs GR32:$dst), (ins FR32:$src), + "movd\t{$src, $dst|$dst, $src}", + [(set GR32:$dst, (bitconvert FR32:$src))]>; +def MOVSS2DImr : PDI<0x7E, MRMDestMem, (outs), (ins i32mem:$dst, FR32:$src), + "movd\t{$src, $dst|$dst, $src}", + [(store (i32 (bitconvert FR32:$src)), addr:$dst)]>; + + +// Move to lower bits of a VR128, leaving upper bits alone. +// Three operand (but two address) aliases. +let Constraints = "$src1 = $dst" in { + let neverHasSideEffects = 1 in + def MOVLSD2PDrr : SDI<0x10, MRMSrcReg, + (outs VR128:$dst), (ins VR128:$src1, FR64:$src2), + "movsd\t{$src2, $dst|$dst, $src2}", []>; + + let AddedComplexity = 15 in + def MOVLPDrr : SDI<0x10, MRMSrcReg, + (outs VR128:$dst), (ins VR128:$src1, VR128:$src2), + "movsd\t{$src2, $dst|$dst, $src2}", + [(set VR128:$dst, + (v2f64 (movl VR128:$src1, VR128:$src2)))]>; +} + +// Store / copy lower 64-bits of a XMM register. +def MOVLQ128mr : PDI<0xD6, MRMDestMem, (outs), (ins i64mem:$dst, VR128:$src), + "movq\t{$src, $dst|$dst, $src}", + [(int_x86_sse2_storel_dq addr:$dst, VR128:$src)]>; + +// Move to lower bits of a VR128 and zeroing upper bits. +// Loading from memory automatically zeroing upper bits. +let AddedComplexity = 20 in { +def MOVZSD2PDrm : SDI<0x10, MRMSrcMem, (outs VR128:$dst), (ins f64mem:$src), + "movsd\t{$src, $dst|$dst, $src}", + [(set VR128:$dst, + (v2f64 (X86vzmovl (v2f64 (scalar_to_vector + (loadf64 addr:$src))))))]>; + +def : Pat<(v2f64 (X86vzmovl (loadv2f64 addr:$src))), + (MOVZSD2PDrm addr:$src)>; +def : Pat<(v2f64 (X86vzmovl (bc_v2f64 (loadv4f32 addr:$src)))), + (MOVZSD2PDrm addr:$src)>; +def : Pat<(v2f64 (X86vzload addr:$src)), (MOVZSD2PDrm addr:$src)>; +} + +// movd / movq to XMM register zero-extends +let AddedComplexity = 15 in { +def MOVZDI2PDIrr : PDI<0x6E, MRMSrcReg, (outs VR128:$dst), (ins GR32:$src), + "movd\t{$src, $dst|$dst, $src}", + [(set VR128:$dst, (v4i32 (X86vzmovl + (v4i32 (scalar_to_vector GR32:$src)))))]>; +// This is X86-64 only. +def MOVZQI2PQIrr : RPDI<0x6E, MRMSrcReg, (outs VR128:$dst), (ins GR64:$src), + "mov{d|q}\t{$src, $dst|$dst, $src}", + [(set VR128:$dst, (v2i64 (X86vzmovl + (v2i64 (scalar_to_vector GR64:$src)))))]>; +} + +let AddedComplexity = 20 in { +def MOVZDI2PDIrm : PDI<0x6E, MRMSrcMem, (outs VR128:$dst), (ins i32mem:$src), + "movd\t{$src, $dst|$dst, $src}", + [(set VR128:$dst, + (v4i32 (X86vzmovl (v4i32 (scalar_to_vector + (loadi32 addr:$src))))))]>; + +def : Pat<(v4i32 (X86vzmovl (loadv4i32 addr:$src))), + (MOVZDI2PDIrm addr:$src)>; +def : Pat<(v4i32 (X86vzmovl (bc_v4i32 (loadv4f32 addr:$src)))), + (MOVZDI2PDIrm addr:$src)>; +def : Pat<(v4i32 (X86vzmovl (bc_v4i32 (loadv2i64 addr:$src)))), + (MOVZDI2PDIrm addr:$src)>; + +def MOVZQI2PQIrm : I<0x7E, MRMSrcMem, (outs VR128:$dst), (ins i64mem:$src), + "movq\t{$src, $dst|$dst, $src}", + [(set VR128:$dst, + (v2i64 (X86vzmovl (v2i64 (scalar_to_vector + (loadi64 addr:$src))))))]>, XS, + Requires<[HasSSE2]>; + +def : Pat<(v2i64 (X86vzmovl (loadv2i64 addr:$src))), + (MOVZQI2PQIrm addr:$src)>; +def : Pat<(v2i64 (X86vzmovl (bc_v2i64 (loadv4f32 addr:$src)))), + (MOVZQI2PQIrm addr:$src)>; +def : Pat<(v2i64 (X86vzload addr:$src)), (MOVZQI2PQIrm addr:$src)>; +} + +// Moving from XMM to XMM and clear upper 64 bits. Note, there is a bug in +// IA32 document. movq xmm1, xmm2 does clear the high bits. +let AddedComplexity = 15 in +def MOVZPQILo2PQIrr : I<0x7E, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src), + "movq\t{$src, $dst|$dst, $src}", + [(set VR128:$dst, (v2i64 (X86vzmovl (v2i64 VR128:$src))))]>, + XS, Requires<[HasSSE2]>; + +let AddedComplexity = 20 in { +def MOVZPQILo2PQIrm : I<0x7E, MRMSrcMem, (outs VR128:$dst), (ins i128mem:$src), + "movq\t{$src, $dst|$dst, $src}", + [(set VR128:$dst, (v2i64 (X86vzmovl + (loadv2i64 addr:$src))))]>, + XS, Requires<[HasSSE2]>; + +def : Pat<(v2i64 (X86vzmovl (bc_v2i64 (loadv4i32 addr:$src)))), + (MOVZPQILo2PQIrm addr:$src)>; +} + +//===---------------------------------------------------------------------===// +// SSE3 Instructions +//===---------------------------------------------------------------------===// + +// Move Instructions +def MOVSHDUPrr : S3SI<0x16, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src), + "movshdup\t{$src, $dst|$dst, $src}", + [(set VR128:$dst, (v4f32 (movshdup + VR128:$src, (undef))))]>; +def MOVSHDUPrm : S3SI<0x16, MRMSrcMem, (outs VR128:$dst), (ins f128mem:$src), + "movshdup\t{$src, $dst|$dst, $src}", + [(set VR128:$dst, (movshdup + (memopv4f32 addr:$src), (undef)))]>; + +def MOVSLDUPrr : S3SI<0x12, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src), + "movsldup\t{$src, $dst|$dst, $src}", + [(set VR128:$dst, (v4f32 (movsldup + VR128:$src, (undef))))]>; +def MOVSLDUPrm : S3SI<0x12, MRMSrcMem, (outs VR128:$dst), (ins f128mem:$src), + "movsldup\t{$src, $dst|$dst, $src}", + [(set VR128:$dst, (movsldup + (memopv4f32 addr:$src), (undef)))]>; + +def MOVDDUPrr : S3DI<0x12, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src), + "movddup\t{$src, $dst|$dst, $src}", + [(set VR128:$dst,(v2f64 (movddup VR128:$src, (undef))))]>; +def MOVDDUPrm : S3DI<0x12, MRMSrcMem, (outs VR128:$dst), (ins f64mem:$src), + "movddup\t{$src, $dst|$dst, $src}", + [(set VR128:$dst, + (v2f64 (movddup (scalar_to_vector (loadf64 addr:$src)), + (undef))))]>; + +def : Pat<(movddup (bc_v2f64 (v2i64 (scalar_to_vector (loadi64 addr:$src)))), + (undef)), + (MOVDDUPrm addr:$src)>, Requires<[HasSSE3]>; + +let AddedComplexity = 5 in { +def : Pat<(movddup (memopv2f64 addr:$src), (undef)), + (MOVDDUPrm addr:$src)>, Requires<[HasSSE3]>; +def : Pat<(movddup (bc_v4f32 (memopv2f64 addr:$src)), (undef)), + (MOVDDUPrm addr:$src)>, Requires<[HasSSE3]>; +def : Pat<(movddup (memopv2i64 addr:$src), (undef)), + (MOVDDUPrm addr:$src)>, Requires<[HasSSE3]>; +def : Pat<(movddup (bc_v4i32 (memopv2i64 addr:$src)), (undef)), + (MOVDDUPrm addr:$src)>, Requires<[HasSSE3]>; +} + +// Arithmetic +let Constraints = "$src1 = $dst" in { + def ADDSUBPSrr : S3DI<0xD0, MRMSrcReg, + (outs VR128:$dst), (ins VR128:$src1, VR128:$src2), + "addsubps\t{$src2, $dst|$dst, $src2}", + [(set VR128:$dst, (int_x86_sse3_addsub_ps VR128:$src1, + VR128:$src2))]>; + def ADDSUBPSrm : S3DI<0xD0, MRMSrcMem, + (outs VR128:$dst), (ins VR128:$src1, f128mem:$src2), + "addsubps\t{$src2, $dst|$dst, $src2}", + [(set VR128:$dst, (int_x86_sse3_addsub_ps VR128:$src1, + (memop addr:$src2)))]>; + def ADDSUBPDrr : S3I<0xD0, MRMSrcReg, + (outs VR128:$dst), (ins VR128:$src1, VR128:$src2), + "addsubpd\t{$src2, $dst|$dst, $src2}", + [(set VR128:$dst, (int_x86_sse3_addsub_pd VR128:$src1, + VR128:$src2))]>; + def ADDSUBPDrm : S3I<0xD0, MRMSrcMem, + (outs VR128:$dst), (ins VR128:$src1, f128mem:$src2), + "addsubpd\t{$src2, $dst|$dst, $src2}", + [(set VR128:$dst, (int_x86_sse3_addsub_pd VR128:$src1, + (memop addr:$src2)))]>; +} + +def LDDQUrm : S3DI<0xF0, MRMSrcMem, (outs VR128:$dst), (ins i128mem:$src), + "lddqu\t{$src, $dst|$dst, $src}", + [(set VR128:$dst, (int_x86_sse3_ldu_dq addr:$src))]>; + +// Horizontal ops +class S3D_Intrr o, string OpcodeStr, Intrinsic IntId> + : S3DI; +class S3D_Intrm o, string OpcodeStr, Intrinsic IntId> + : S3DI; +class S3_Intrr o, string OpcodeStr, Intrinsic IntId> + : S3I; +class S3_Intrm o, string OpcodeStr, Intrinsic IntId> + : S3I; + +let Constraints = "$src1 = $dst" in { + def HADDPSrr : S3D_Intrr<0x7C, "haddps", int_x86_sse3_hadd_ps>; + def HADDPSrm : S3D_Intrm<0x7C, "haddps", int_x86_sse3_hadd_ps>; + def HADDPDrr : S3_Intrr <0x7C, "haddpd", int_x86_sse3_hadd_pd>; + def HADDPDrm : S3_Intrm <0x7C, "haddpd", int_x86_sse3_hadd_pd>; + def HSUBPSrr : S3D_Intrr<0x7D, "hsubps", int_x86_sse3_hsub_ps>; + def HSUBPSrm : S3D_Intrm<0x7D, "hsubps", int_x86_sse3_hsub_ps>; + def HSUBPDrr : S3_Intrr <0x7D, "hsubpd", int_x86_sse3_hsub_pd>; + def HSUBPDrm : S3_Intrm <0x7D, "hsubpd", int_x86_sse3_hsub_pd>; +} + +// Thread synchronization +def MONITOR : I<0x01, MRM1r, (outs), (ins), "monitor", + [(int_x86_sse3_monitor EAX, ECX, EDX)]>,TB, Requires<[HasSSE3]>; +def MWAIT : I<0x01, MRM1r, (outs), (ins), "mwait", + [(int_x86_sse3_mwait ECX, EAX)]>, TB, Requires<[HasSSE3]>; + +// vector_shuffle v1, <1, 1, 3, 3> +let AddedComplexity = 15 in +def : Pat<(v4i32 (movshdup VR128:$src, (undef))), + (MOVSHDUPrr VR128:$src)>, Requires<[HasSSE3]>; +let AddedComplexity = 20 in +def : Pat<(v4i32 (movshdup (bc_v4i32 (memopv2i64 addr:$src)), (undef))), + (MOVSHDUPrm addr:$src)>, Requires<[HasSSE3]>; + +// vector_shuffle v1, <0, 0, 2, 2> +let AddedComplexity = 15 in + def : Pat<(v4i32 (movsldup VR128:$src, (undef))), + (MOVSLDUPrr VR128:$src)>, Requires<[HasSSE3]>; +let AddedComplexity = 20 in + def : Pat<(v4i32 (movsldup (bc_v4i32 (memopv2i64 addr:$src)), (undef))), + (MOVSLDUPrm addr:$src)>, Requires<[HasSSE3]>; + +//===---------------------------------------------------------------------===// +// SSSE3 Instructions +//===---------------------------------------------------------------------===// + +/// SS3I_unop_rm_int_8 - Simple SSSE3 unary operator whose type is v*i8. +multiclass SS3I_unop_rm_int_8 opc, string OpcodeStr, + Intrinsic IntId64, Intrinsic IntId128> { + def rr64 : SS38I; + + def rm64 : SS38I; + + def rr128 : SS38I, + OpSize; + + def rm128 : SS38I, OpSize; +} + +/// SS3I_unop_rm_int_16 - Simple SSSE3 unary operator whose type is v*i16. +multiclass SS3I_unop_rm_int_16 opc, string OpcodeStr, + Intrinsic IntId64, Intrinsic IntId128> { + def rr64 : SS38I; + + def rm64 : SS38I; + + def rr128 : SS38I, + OpSize; + + def rm128 : SS38I, OpSize; +} + +/// SS3I_unop_rm_int_32 - Simple SSSE3 unary operator whose type is v*i32. +multiclass SS3I_unop_rm_int_32 opc, string OpcodeStr, + Intrinsic IntId64, Intrinsic IntId128> { + def rr64 : SS38I; + + def rm64 : SS38I; + + def rr128 : SS38I, + OpSize; + + def rm128 : SS38I, OpSize; +} + +defm PABSB : SS3I_unop_rm_int_8 <0x1C, "pabsb", + int_x86_ssse3_pabs_b, + int_x86_ssse3_pabs_b_128>; +defm PABSW : SS3I_unop_rm_int_16<0x1D, "pabsw", + int_x86_ssse3_pabs_w, + int_x86_ssse3_pabs_w_128>; +defm PABSD : SS3I_unop_rm_int_32<0x1E, "pabsd", + int_x86_ssse3_pabs_d, + int_x86_ssse3_pabs_d_128>; + +/// SS3I_binop_rm_int_8 - Simple SSSE3 binary operator whose type is v*i8. +let Constraints = "$src1 = $dst" in { + multiclass SS3I_binop_rm_int_8 opc, string OpcodeStr, + Intrinsic IntId64, Intrinsic IntId128, + bit Commutable = 0> { + def rr64 : SS38I { + let isCommutable = Commutable; + } + def rm64 : SS38I; + + def rr128 : SS38I, + OpSize { + let isCommutable = Commutable; + } + def rm128 : SS38I, OpSize; + } +} + +/// SS3I_binop_rm_int_16 - Simple SSSE3 binary operator whose type is v*i16. +let Constraints = "$src1 = $dst" in { + multiclass SS3I_binop_rm_int_16 opc, string OpcodeStr, + Intrinsic IntId64, Intrinsic IntId128, + bit Commutable = 0> { + def rr64 : SS38I { + let isCommutable = Commutable; + } + def rm64 : SS38I; + + def rr128 : SS38I, + OpSize { + let isCommutable = Commutable; + } + def rm128 : SS38I, OpSize; + } +} + +/// SS3I_binop_rm_int_32 - Simple SSSE3 binary operator whose type is v*i32. +let Constraints = "$src1 = $dst" in { + multiclass SS3I_binop_rm_int_32 opc, string OpcodeStr, + Intrinsic IntId64, Intrinsic IntId128, + bit Commutable = 0> { + def rr64 : SS38I { + let isCommutable = Commutable; + } + def rm64 : SS38I; + + def rr128 : SS38I, + OpSize { + let isCommutable = Commutable; + } + def rm128 : SS38I, OpSize; + } +} + +defm PHADDW : SS3I_binop_rm_int_16<0x01, "phaddw", + int_x86_ssse3_phadd_w, + int_x86_ssse3_phadd_w_128>; +defm PHADDD : SS3I_binop_rm_int_32<0x02, "phaddd", + int_x86_ssse3_phadd_d, + int_x86_ssse3_phadd_d_128>; +defm PHADDSW : SS3I_binop_rm_int_16<0x03, "phaddsw", + int_x86_ssse3_phadd_sw, + int_x86_ssse3_phadd_sw_128>; +defm PHSUBW : SS3I_binop_rm_int_16<0x05, "phsubw", + int_x86_ssse3_phsub_w, + int_x86_ssse3_phsub_w_128>; +defm PHSUBD : SS3I_binop_rm_int_32<0x06, "phsubd", + int_x86_ssse3_phsub_d, + int_x86_ssse3_phsub_d_128>; +defm PHSUBSW : SS3I_binop_rm_int_16<0x07, "phsubsw", + int_x86_ssse3_phsub_sw, + int_x86_ssse3_phsub_sw_128>; +defm PMADDUBSW : SS3I_binop_rm_int_8 <0x04, "pmaddubsw", + int_x86_ssse3_pmadd_ub_sw, + int_x86_ssse3_pmadd_ub_sw_128>; +defm PMULHRSW : SS3I_binop_rm_int_16<0x0B, "pmulhrsw", + int_x86_ssse3_pmul_hr_sw, + int_x86_ssse3_pmul_hr_sw_128, 1>; +defm PSHUFB : SS3I_binop_rm_int_8 <0x00, "pshufb", + int_x86_ssse3_pshuf_b, + int_x86_ssse3_pshuf_b_128>; +defm PSIGNB : SS3I_binop_rm_int_8 <0x08, "psignb", + int_x86_ssse3_psign_b, + int_x86_ssse3_psign_b_128>; +defm PSIGNW : SS3I_binop_rm_int_16<0x09, "psignw", + int_x86_ssse3_psign_w, + int_x86_ssse3_psign_w_128>; +defm PSIGND : SS3I_binop_rm_int_32<0x0A, "psignd", + int_x86_ssse3_psign_d, + int_x86_ssse3_psign_d_128>; + +let Constraints = "$src1 = $dst" in { + def PALIGNR64rr : SS3AI<0x0F, MRMSrcReg, (outs VR64:$dst), + (ins VR64:$src1, VR64:$src2, i8imm:$src3), + "palignr\t{$src3, $src2, $dst|$dst, $src2, $src3}", + []>; + def PALIGNR64rm : SS3AI<0x0F, MRMSrcMem, (outs VR64:$dst), + (ins VR64:$src1, i64mem:$src2, i8imm:$src3), + "palignr\t{$src3, $src2, $dst|$dst, $src2, $src3}", + []>; + + def PALIGNR128rr : SS3AI<0x0F, MRMSrcReg, (outs VR128:$dst), + (ins VR128:$src1, VR128:$src2, i8imm:$src3), + "palignr\t{$src3, $src2, $dst|$dst, $src2, $src3}", + []>, OpSize; + def PALIGNR128rm : SS3AI<0x0F, MRMSrcMem, (outs VR128:$dst), + (ins VR128:$src1, i128mem:$src2, i8imm:$src3), + "palignr\t{$src3, $src2, $dst|$dst, $src2, $src3}", + []>, OpSize; +} + +// palignr patterns. +def : Pat<(int_x86_ssse3_palign_r VR64:$src1, VR64:$src2, (i8 imm:$src3)), + (PALIGNR64rr VR64:$src1, VR64:$src2, (BYTE_imm imm:$src3))>, + Requires<[HasSSSE3]>; +def : Pat<(int_x86_ssse3_palign_r VR64:$src1, + (memop64 addr:$src2), + (i8 imm:$src3)), + (PALIGNR64rm VR64:$src1, addr:$src2, (BYTE_imm imm:$src3))>, + Requires<[HasSSSE3]>; + +def : Pat<(int_x86_ssse3_palign_r_128 VR128:$src1, VR128:$src2, (i8 imm:$src3)), + (PALIGNR128rr VR128:$src1, VR128:$src2, (BYTE_imm imm:$src3))>, + Requires<[HasSSSE3]>; +def : Pat<(int_x86_ssse3_palign_r_128 VR128:$src1, + (memopv2i64 addr:$src2), + (i8 imm:$src3)), + (PALIGNR128rm VR128:$src1, addr:$src2, (BYTE_imm imm:$src3))>, + Requires<[HasSSSE3]>; + +let AddedComplexity = 5 in { +def : Pat<(v4i32 (palign:$src3 VR128:$src1, VR128:$src2)), + (PALIGNR128rr VR128:$src2, VR128:$src1, + (SHUFFLE_get_palign_imm VR128:$src3))>, + Requires<[HasSSSE3]>; +def : Pat<(v4f32 (palign:$src3 VR128:$src1, VR128:$src2)), + (PALIGNR128rr VR128:$src2, VR128:$src1, + (SHUFFLE_get_palign_imm VR128:$src3))>, + Requires<[HasSSSE3]>; +def : Pat<(v8i16 (palign:$src3 VR128:$src1, VR128:$src2)), + (PALIGNR128rr VR128:$src2, VR128:$src1, + (SHUFFLE_get_palign_imm VR128:$src3))>, + Requires<[HasSSSE3]>; +def : Pat<(v16i8 (palign:$src3 VR128:$src1, VR128:$src2)), + (PALIGNR128rr VR128:$src2, VR128:$src1, + (SHUFFLE_get_palign_imm VR128:$src3))>, + Requires<[HasSSSE3]>; +} + +def : Pat<(X86pshufb VR128:$src, VR128:$mask), + (PSHUFBrr128 VR128:$src, VR128:$mask)>, Requires<[HasSSSE3]>; +def : Pat<(X86pshufb VR128:$src, (bc_v16i8 (memopv2i64 addr:$mask))), + (PSHUFBrm128 VR128:$src, addr:$mask)>, Requires<[HasSSSE3]>; + +//===---------------------------------------------------------------------===// +// Non-Instruction Patterns +//===---------------------------------------------------------------------===// + +// extload f32 -> f64. This matches load+fextend because we have a hack in +// the isel (PreprocessForFPConvert) that can introduce loads after dag +// combine. +// Since these loads aren't folded into the fextend, we have to match it +// explicitly here. +let Predicates = [HasSSE2] in + def : Pat<(fextend (loadf32 addr:$src)), + (CVTSS2SDrm addr:$src)>; + +// bit_convert +let Predicates = [HasSSE2] in { + def : Pat<(v2i64 (bitconvert (v4i32 VR128:$src))), (v2i64 VR128:$src)>; + def : Pat<(v2i64 (bitconvert (v8i16 VR128:$src))), (v2i64 VR128:$src)>; + def : Pat<(v2i64 (bitconvert (v16i8 VR128:$src))), (v2i64 VR128:$src)>; + def : Pat<(v2i64 (bitconvert (v2f64 VR128:$src))), (v2i64 VR128:$src)>; + def : Pat<(v2i64 (bitconvert (v4f32 VR128:$src))), (v2i64 VR128:$src)>; + def : Pat<(v4i32 (bitconvert (v2i64 VR128:$src))), (v4i32 VR128:$src)>; + def : Pat<(v4i32 (bitconvert (v8i16 VR128:$src))), (v4i32 VR128:$src)>; + def : Pat<(v4i32 (bitconvert (v16i8 VR128:$src))), (v4i32 VR128:$src)>; + def : Pat<(v4i32 (bitconvert (v2f64 VR128:$src))), (v4i32 VR128:$src)>; + def : Pat<(v4i32 (bitconvert (v4f32 VR128:$src))), (v4i32 VR128:$src)>; + def : Pat<(v8i16 (bitconvert (v2i64 VR128:$src))), (v8i16 VR128:$src)>; + def : Pat<(v8i16 (bitconvert (v4i32 VR128:$src))), (v8i16 VR128:$src)>; + def : Pat<(v8i16 (bitconvert (v16i8 VR128:$src))), (v8i16 VR128:$src)>; + def : Pat<(v8i16 (bitconvert (v2f64 VR128:$src))), (v8i16 VR128:$src)>; + def : Pat<(v8i16 (bitconvert (v4f32 VR128:$src))), (v8i16 VR128:$src)>; + def : Pat<(v16i8 (bitconvert (v2i64 VR128:$src))), (v16i8 VR128:$src)>; + def : Pat<(v16i8 (bitconvert (v4i32 VR128:$src))), (v16i8 VR128:$src)>; + def : Pat<(v16i8 (bitconvert (v8i16 VR128:$src))), (v16i8 VR128:$src)>; + def : Pat<(v16i8 (bitconvert (v2f64 VR128:$src))), (v16i8 VR128:$src)>; + def : Pat<(v16i8 (bitconvert (v4f32 VR128:$src))), (v16i8 VR128:$src)>; + def : Pat<(v4f32 (bitconvert (v2i64 VR128:$src))), (v4f32 VR128:$src)>; + def : Pat<(v4f32 (bitconvert (v4i32 VR128:$src))), (v4f32 VR128:$src)>; + def : Pat<(v4f32 (bitconvert (v8i16 VR128:$src))), (v4f32 VR128:$src)>; + def : Pat<(v4f32 (bitconvert (v16i8 VR128:$src))), (v4f32 VR128:$src)>; + def : Pat<(v4f32 (bitconvert (v2f64 VR128:$src))), (v4f32 VR128:$src)>; + def : Pat<(v2f64 (bitconvert (v2i64 VR128:$src))), (v2f64 VR128:$src)>; + def : Pat<(v2f64 (bitconvert (v4i32 VR128:$src))), (v2f64 VR128:$src)>; + def : Pat<(v2f64 (bitconvert (v8i16 VR128:$src))), (v2f64 VR128:$src)>; + def : Pat<(v2f64 (bitconvert (v16i8 VR128:$src))), (v2f64 VR128:$src)>; + def : Pat<(v2f64 (bitconvert (v4f32 VR128:$src))), (v2f64 VR128:$src)>; +} + +// Move scalar to XMM zero-extended +// movd to XMM register zero-extends +let AddedComplexity = 15 in { +// Zeroing a VR128 then do a MOVS{S|D} to the lower bits. +def : Pat<(v2f64 (X86vzmovl (v2f64 (scalar_to_vector FR64:$src)))), + (MOVLSD2PDrr (V_SET0), FR64:$src)>, Requires<[HasSSE2]>; +def : Pat<(v4f32 (X86vzmovl (v4f32 (scalar_to_vector FR32:$src)))), + (MOVLSS2PSrr (V_SET0), FR32:$src)>, Requires<[HasSSE1]>; +def : Pat<(v4f32 (X86vzmovl (v4f32 VR128:$src))), + (MOVLPSrr (V_SET0), VR128:$src)>, Requires<[HasSSE1]>; +def : Pat<(v4i32 (X86vzmovl (v4i32 VR128:$src))), + (MOVLPSrr (V_SET0), VR128:$src)>, Requires<[HasSSE1]>; +} + +// Splat v2f64 / v2i64 +let AddedComplexity = 10 in { +def : Pat<(splat_lo (v2f64 VR128:$src), (undef)), + (UNPCKLPDrr VR128:$src, VR128:$src)>, Requires<[HasSSE2]>; +def : Pat<(unpckh (v2f64 VR128:$src), (undef)), + (UNPCKHPDrr VR128:$src, VR128:$src)>, Requires<[HasSSE2]>; +def : Pat<(splat_lo (v2i64 VR128:$src), (undef)), + (PUNPCKLQDQrr VR128:$src, VR128:$src)>, Requires<[HasSSE2]>; +def : Pat<(unpckh (v2i64 VR128:$src), (undef)), + (PUNPCKHQDQrr VR128:$src, VR128:$src)>, Requires<[HasSSE2]>; +} + +// Special unary SHUFPSrri case. +def : Pat<(v4f32 (pshufd:$src3 VR128:$src1, (undef))), + (SHUFPSrri VR128:$src1, VR128:$src1, + (SHUFFLE_get_shuf_imm VR128:$src3))>, + Requires<[HasSSE1]>; +let AddedComplexity = 5 in +def : Pat<(v4f32 (pshufd:$src2 VR128:$src1, (undef))), + (PSHUFDri VR128:$src1, (SHUFFLE_get_shuf_imm VR128:$src2))>, + Requires<[HasSSE2]>; +// Special unary SHUFPDrri case. +def : Pat<(v2i64 (pshufd:$src3 VR128:$src1, (undef))), + (SHUFPDrri VR128:$src1, VR128:$src1, + (SHUFFLE_get_shuf_imm VR128:$src3))>, + Requires<[HasSSE2]>; +// Special unary SHUFPDrri case. +def : Pat<(v2f64 (pshufd:$src3 VR128:$src1, (undef))), + (SHUFPDrri VR128:$src1, VR128:$src1, + (SHUFFLE_get_shuf_imm VR128:$src3))>, + Requires<[HasSSE2]>; +// Unary v4f32 shuffle with PSHUF* in order to fold a load. +def : Pat<(pshufd:$src2 (bc_v4i32 (memopv4f32 addr:$src1)), (undef)), + (PSHUFDmi addr:$src1, (SHUFFLE_get_shuf_imm VR128:$src2))>, + Requires<[HasSSE2]>; + +// Special binary v4i32 shuffle cases with SHUFPS. +def : Pat<(v4i32 (shufp:$src3 VR128:$src1, (v4i32 VR128:$src2))), + (SHUFPSrri VR128:$src1, VR128:$src2, + (SHUFFLE_get_shuf_imm VR128:$src3))>, + Requires<[HasSSE2]>; +def : Pat<(v4i32 (shufp:$src3 VR128:$src1, (bc_v4i32 (memopv2i64 addr:$src2)))), + (SHUFPSrmi VR128:$src1, addr:$src2, + (SHUFFLE_get_shuf_imm VR128:$src3))>, + Requires<[HasSSE2]>; +// Special binary v2i64 shuffle cases using SHUFPDrri. +def : Pat<(v2i64 (shufp:$src3 VR128:$src1, VR128:$src2)), + (SHUFPDrri VR128:$src1, VR128:$src2, + (SHUFFLE_get_shuf_imm VR128:$src3))>, + Requires<[HasSSE2]>; + +// vector_shuffle v1, , <0, 0, 1, 1, ...> +let AddedComplexity = 15 in { +def : Pat<(v4i32 (unpckl_undef:$src2 VR128:$src, (undef))), + (PSHUFDri VR128:$src, (SHUFFLE_get_shuf_imm VR128:$src2))>, + Requires<[OptForSpeed, HasSSE2]>; +def : Pat<(v4f32 (unpckl_undef:$src2 VR128:$src, (undef))), + (PSHUFDri VR128:$src, (SHUFFLE_get_shuf_imm VR128:$src2))>, + Requires<[OptForSpeed, HasSSE2]>; +} +let AddedComplexity = 10 in { +def : Pat<(v4f32 (unpckl_undef VR128:$src, (undef))), + (UNPCKLPSrr VR128:$src, VR128:$src)>, Requires<[HasSSE1]>; +def : Pat<(v16i8 (unpckl_undef VR128:$src, (undef))), + (PUNPCKLBWrr VR128:$src, VR128:$src)>, Requires<[HasSSE2]>; +def : Pat<(v8i16 (unpckl_undef VR128:$src, (undef))), + (PUNPCKLWDrr VR128:$src, VR128:$src)>, Requires<[HasSSE2]>; +def : Pat<(v4i32 (unpckl_undef VR128:$src, (undef))), + (PUNPCKLDQrr VR128:$src, VR128:$src)>, Requires<[HasSSE2]>; +} + +// vector_shuffle v1, , <2, 2, 3, 3, ...> +let AddedComplexity = 15 in { +def : Pat<(v4i32 (unpckh_undef:$src2 VR128:$src, (undef))), + (PSHUFDri VR128:$src, (SHUFFLE_get_shuf_imm VR128:$src2))>, + Requires<[OptForSpeed, HasSSE2]>; +def : Pat<(v4f32 (unpckh_undef:$src2 VR128:$src, (undef))), + (PSHUFDri VR128:$src, (SHUFFLE_get_shuf_imm VR128:$src2))>, + Requires<[OptForSpeed, HasSSE2]>; +} +let AddedComplexity = 10 in { +def : Pat<(v4f32 (unpckh_undef VR128:$src, (undef))), + (UNPCKHPSrr VR128:$src, VR128:$src)>, Requires<[HasSSE1]>; +def : Pat<(v16i8 (unpckh_undef VR128:$src, (undef))), + (PUNPCKHBWrr VR128:$src, VR128:$src)>, Requires<[HasSSE2]>; +def : Pat<(v8i16 (unpckh_undef VR128:$src, (undef))), + (PUNPCKHWDrr VR128:$src, VR128:$src)>, Requires<[HasSSE2]>; +def : Pat<(v4i32 (unpckh_undef VR128:$src, (undef))), + (PUNPCKHDQrr VR128:$src, VR128:$src)>, Requires<[HasSSE2]>; +} + +let AddedComplexity = 20 in { +// vector_shuffle v1, v2 <0, 1, 4, 5> using MOVLHPS +def : Pat<(v4i32 (movlhps VR128:$src1, VR128:$src2)), + (MOVLHPSrr VR128:$src1, VR128:$src2)>; + +// vector_shuffle v1, v2 <6, 7, 2, 3> using MOVHLPS +def : Pat<(v4i32 (movhlps VR128:$src1, VR128:$src2)), + (MOVHLPSrr VR128:$src1, VR128:$src2)>; + +// vector_shuffle v1, undef <2, ?, ?, ?> using MOVHLPS +def : Pat<(v4f32 (movhlps_undef VR128:$src1, (undef))), + (MOVHLPSrr VR128:$src1, VR128:$src1)>; +def : Pat<(v4i32 (movhlps_undef VR128:$src1, (undef))), + (MOVHLPSrr VR128:$src1, VR128:$src1)>; +} + +let AddedComplexity = 20 in { +// vector_shuffle v1, (load v2) <4, 5, 2, 3> using MOVLPS +def : Pat<(v4f32 (movlp VR128:$src1, (load addr:$src2))), + (MOVLPSrm VR128:$src1, addr:$src2)>, Requires<[HasSSE1]>; +def : Pat<(v2f64 (movlp VR128:$src1, (load addr:$src2))), + (MOVLPDrm VR128:$src1, addr:$src2)>, Requires<[HasSSE2]>; +def : Pat<(v4i32 (movlp VR128:$src1, (load addr:$src2))), + (MOVLPSrm VR128:$src1, addr:$src2)>, Requires<[HasSSE2]>; +def : Pat<(v2i64 (movlp VR128:$src1, (load addr:$src2))), + (MOVLPDrm VR128:$src1, addr:$src2)>, Requires<[HasSSE2]>; +} + +// (store (vector_shuffle (load addr), v2, <4, 5, 2, 3>), addr) using MOVLPS +def : Pat<(store (v4f32 (movlp (load addr:$src1), VR128:$src2)), addr:$src1), + (MOVLPSmr addr:$src1, VR128:$src2)>, Requires<[HasSSE1]>; +def : Pat<(store (v2f64 (movlp (load addr:$src1), VR128:$src2)), addr:$src1), + (MOVLPDmr addr:$src1, VR128:$src2)>, Requires<[HasSSE2]>; +def : Pat<(store (v4i32 (movlp (bc_v4i32 (loadv2i64 addr:$src1)), VR128:$src2)), + addr:$src1), + (MOVLPSmr addr:$src1, VR128:$src2)>, Requires<[HasSSE1]>; +def : Pat<(store (v2i64 (movlp (load addr:$src1), VR128:$src2)), addr:$src1), + (MOVLPDmr addr:$src1, VR128:$src2)>, Requires<[HasSSE2]>; + +let AddedComplexity = 15 in { +// Setting the lowest element in the vector. +def : Pat<(v4i32 (movl VR128:$src1, VR128:$src2)), + (MOVLPSrr VR128:$src1, VR128:$src2)>, Requires<[HasSSE2]>; +def : Pat<(v2i64 (movl VR128:$src1, VR128:$src2)), + (MOVLPDrr VR128:$src1, VR128:$src2)>, Requires<[HasSSE2]>; + +// vector_shuffle v1, v2 <4, 5, 2, 3> using MOVLPDrr (movsd) +def : Pat<(v4f32 (movlp VR128:$src1, VR128:$src2)), + (MOVLPDrr VR128:$src1, VR128:$src2)>, Requires<[HasSSE2]>; +def : Pat<(v4i32 (movlp VR128:$src1, VR128:$src2)), + (MOVLPDrr VR128:$src1, VR128:$src2)>, Requires<[HasSSE2]>; +} + +// vector_shuffle v1, v2 <4, 5, 2, 3> using SHUFPSrri (we prefer movsd, but +// fall back to this for SSE1) +def : Pat<(v4f32 (movlp:$src3 VR128:$src1, (v4f32 VR128:$src2))), + (SHUFPSrri VR128:$src2, VR128:$src1, + (SHUFFLE_get_shuf_imm VR128:$src3))>, Requires<[HasSSE1]>; + +// Set lowest element and zero upper elements. +let AddedComplexity = 15 in +def : Pat<(v2f64 (movl immAllZerosV_bc, VR128:$src)), + (MOVZPQILo2PQIrr VR128:$src)>, Requires<[HasSSE2]>; +def : Pat<(v2f64 (X86vzmovl (v2f64 VR128:$src))), + (MOVZPQILo2PQIrr VR128:$src)>, Requires<[HasSSE2]>; + +// Some special case pandn patterns. +def : Pat<(v2i64 (and (xor VR128:$src1, (bc_v2i64 (v4i32 immAllOnesV))), + VR128:$src2)), + (PANDNrr VR128:$src1, VR128:$src2)>, Requires<[HasSSE2]>; +def : Pat<(v2i64 (and (xor VR128:$src1, (bc_v2i64 (v8i16 immAllOnesV))), + VR128:$src2)), + (PANDNrr VR128:$src1, VR128:$src2)>, Requires<[HasSSE2]>; +def : Pat<(v2i64 (and (xor VR128:$src1, (bc_v2i64 (v16i8 immAllOnesV))), + VR128:$src2)), + (PANDNrr VR128:$src1, VR128:$src2)>, Requires<[HasSSE2]>; + +def : Pat<(v2i64 (and (xor VR128:$src1, (bc_v2i64 (v4i32 immAllOnesV))), + (memop addr:$src2))), + (PANDNrm VR128:$src1, addr:$src2)>, Requires<[HasSSE2]>; +def : Pat<(v2i64 (and (xor VR128:$src1, (bc_v2i64 (v8i16 immAllOnesV))), + (memop addr:$src2))), + (PANDNrm VR128:$src1, addr:$src2)>, Requires<[HasSSE2]>; +def : Pat<(v2i64 (and (xor VR128:$src1, (bc_v2i64 (v16i8 immAllOnesV))), + (memop addr:$src2))), + (PANDNrm VR128:$src1, addr:$src2)>, Requires<[HasSSE2]>; + +// vector -> vector casts +def : Pat<(v4f32 (sint_to_fp (v4i32 VR128:$src))), + (Int_CVTDQ2PSrr VR128:$src)>, Requires<[HasSSE2]>; +def : Pat<(v4i32 (fp_to_sint (v4f32 VR128:$src))), + (Int_CVTTPS2DQrr VR128:$src)>, Requires<[HasSSE2]>; +def : Pat<(v2f64 (sint_to_fp (v2i32 VR64:$src))), + (Int_CVTPI2PDrr VR64:$src)>, Requires<[HasSSE2]>; +def : Pat<(v2i32 (fp_to_sint (v2f64 VR128:$src))), + (Int_CVTTPD2PIrr VR128:$src)>, Requires<[HasSSE2]>; + +// Use movaps / movups for SSE integer load / store (one byte shorter). +def : Pat<(alignedloadv4i32 addr:$src), + (MOVAPSrm addr:$src)>, Requires<[HasSSE1]>; +def : Pat<(loadv4i32 addr:$src), + (MOVUPSrm addr:$src)>, Requires<[HasSSE1]>; +def : Pat<(alignedloadv2i64 addr:$src), + (MOVAPSrm addr:$src)>, Requires<[HasSSE2]>; +def : Pat<(loadv2i64 addr:$src), + (MOVUPSrm addr:$src)>, Requires<[HasSSE2]>; + +def : Pat<(alignedstore (v2i64 VR128:$src), addr:$dst), + (MOVAPSmr addr:$dst, VR128:$src)>, Requires<[HasSSE2]>; +def : Pat<(alignedstore (v4i32 VR128:$src), addr:$dst), + (MOVAPSmr addr:$dst, VR128:$src)>, Requires<[HasSSE2]>; +def : Pat<(alignedstore (v8i16 VR128:$src), addr:$dst), + (MOVAPSmr addr:$dst, VR128:$src)>, Requires<[HasSSE2]>; +def : Pat<(alignedstore (v16i8 VR128:$src), addr:$dst), + (MOVAPSmr addr:$dst, VR128:$src)>, Requires<[HasSSE2]>; +def : Pat<(store (v2i64 VR128:$src), addr:$dst), + (MOVUPSmr addr:$dst, VR128:$src)>, Requires<[HasSSE2]>; +def : Pat<(store (v4i32 VR128:$src), addr:$dst), + (MOVUPSmr addr:$dst, VR128:$src)>, Requires<[HasSSE2]>; +def : Pat<(store (v8i16 VR128:$src), addr:$dst), + (MOVUPSmr addr:$dst, VR128:$src)>, Requires<[HasSSE2]>; +def : Pat<(store (v16i8 VR128:$src), addr:$dst), + (MOVUPSmr addr:$dst, VR128:$src)>, Requires<[HasSSE2]>; + +//===----------------------------------------------------------------------===// +// SSE4.1 Instructions +//===----------------------------------------------------------------------===// + +multiclass sse41_fp_unop_rm opcps, bits<8> opcpd, + string OpcodeStr, + Intrinsic V4F32Int, + Intrinsic V2F64Int> { + // Intrinsic operation, reg. + // Vector intrinsic operation, reg + def PSr_Int : SS4AIi8, + OpSize; + + // Vector intrinsic operation, mem + def PSm_Int : SS4AIi8, + OpSize; + + // Vector intrinsic operation, reg + def PDr_Int : SS4AIi8, + OpSize; + + // Vector intrinsic operation, mem + def PDm_Int : SS4AIi8, + OpSize; +} + +let Constraints = "$src1 = $dst" in { +multiclass sse41_fp_binop_rm opcss, bits<8> opcsd, + string OpcodeStr, + Intrinsic F32Int, + Intrinsic F64Int> { + // Intrinsic operation, reg. + def SSr_Int : SS4AIi8, + OpSize; + + // Intrinsic operation, mem. + def SSm_Int : SS4AIi8, + OpSize; + + // Intrinsic operation, reg. + def SDr_Int : SS4AIi8, + OpSize; + + // Intrinsic operation, mem. + def SDm_Int : SS4AIi8, + OpSize; +} +} + +// FP round - roundss, roundps, roundsd, roundpd +defm ROUND : sse41_fp_unop_rm<0x08, 0x09, "round", + int_x86_sse41_round_ps, int_x86_sse41_round_pd>; +defm ROUND : sse41_fp_binop_rm<0x0A, 0x0B, "round", + int_x86_sse41_round_ss, int_x86_sse41_round_sd>; + +// SS41I_unop_rm_int_v16 - SSE 4.1 unary operator whose type is v8i16. +multiclass SS41I_unop_rm_int_v16 opc, string OpcodeStr, + Intrinsic IntId128> { + def rr128 : SS48I, OpSize; + def rm128 : SS48I, OpSize; +} + +defm PHMINPOSUW : SS41I_unop_rm_int_v16 <0x41, "phminposuw", + int_x86_sse41_phminposuw>; + +/// SS41I_binop_rm_int - Simple SSE 4.1 binary operator +let Constraints = "$src1 = $dst" in { + multiclass SS41I_binop_rm_int opc, string OpcodeStr, + Intrinsic IntId128, bit Commutable = 0> { + def rr : SS48I, + OpSize { + let isCommutable = Commutable; + } + def rm : SS48I, OpSize; + } +} + +defm PCMPEQQ : SS41I_binop_rm_int<0x29, "pcmpeqq", + int_x86_sse41_pcmpeqq, 1>; +defm PACKUSDW : SS41I_binop_rm_int<0x2B, "packusdw", + int_x86_sse41_packusdw, 0>; +defm PMINSB : SS41I_binop_rm_int<0x38, "pminsb", + int_x86_sse41_pminsb, 1>; +defm PMINSD : SS41I_binop_rm_int<0x39, "pminsd", + int_x86_sse41_pminsd, 1>; +defm PMINUD : SS41I_binop_rm_int<0x3B, "pminud", + int_x86_sse41_pminud, 1>; +defm PMINUW : SS41I_binop_rm_int<0x3A, "pminuw", + int_x86_sse41_pminuw, 1>; +defm PMAXSB : SS41I_binop_rm_int<0x3C, "pmaxsb", + int_x86_sse41_pmaxsb, 1>; +defm PMAXSD : SS41I_binop_rm_int<0x3D, "pmaxsd", + int_x86_sse41_pmaxsd, 1>; +defm PMAXUD : SS41I_binop_rm_int<0x3F, "pmaxud", + int_x86_sse41_pmaxud, 1>; +defm PMAXUW : SS41I_binop_rm_int<0x3E, "pmaxuw", + int_x86_sse41_pmaxuw, 1>; + +defm PMULDQ : SS41I_binop_rm_int<0x28, "pmuldq", int_x86_sse41_pmuldq, 1>; + +def : Pat<(v2i64 (X86pcmpeqq VR128:$src1, VR128:$src2)), + (PCMPEQQrr VR128:$src1, VR128:$src2)>; +def : Pat<(v2i64 (X86pcmpeqq VR128:$src1, (memop addr:$src2))), + (PCMPEQQrm VR128:$src1, addr:$src2)>; + +/// SS41I_binop_rm_int - Simple SSE 4.1 binary operator +let Constraints = "$src1 = $dst" in { + multiclass SS41I_binop_patint opc, string OpcodeStr, ValueType OpVT, + SDNode OpNode, Intrinsic IntId128, + bit Commutable = 0> { + def rr : SS48I, OpSize { + let isCommutable = Commutable; + } + def rr_int : SS48I, + OpSize { + let isCommutable = Commutable; + } + def rm : SS48I, OpSize; + def rm_int : SS48I, + OpSize; + } +} +defm PMULLD : SS41I_binop_patint<0x40, "pmulld", v4i32, mul, + int_x86_sse41_pmulld, 1>; + +/// SS41I_binop_rmi_int - SSE 4.1 binary operator with 8-bit immediate +let Constraints = "$src1 = $dst" in { + multiclass SS41I_binop_rmi_int opc, string OpcodeStr, + Intrinsic IntId128, bit Commutable = 0> { + def rri : SS4AIi8, + OpSize { + let isCommutable = Commutable; + } + def rmi : SS4AIi8, + OpSize; + } +} + +defm BLENDPS : SS41I_binop_rmi_int<0x0C, "blendps", + int_x86_sse41_blendps, 0>; +defm BLENDPD : SS41I_binop_rmi_int<0x0D, "blendpd", + int_x86_sse41_blendpd, 0>; +defm PBLENDW : SS41I_binop_rmi_int<0x0E, "pblendw", + int_x86_sse41_pblendw, 0>; +defm DPPS : SS41I_binop_rmi_int<0x40, "dpps", + int_x86_sse41_dpps, 1>; +defm DPPD : SS41I_binop_rmi_int<0x41, "dppd", + int_x86_sse41_dppd, 1>; +defm MPSADBW : SS41I_binop_rmi_int<0x42, "mpsadbw", + int_x86_sse41_mpsadbw, 1>; + + +/// SS41I_ternary_int - SSE 4.1 ternary operator +let Uses = [XMM0], Constraints = "$src1 = $dst" in { + multiclass SS41I_ternary_int opc, string OpcodeStr, Intrinsic IntId> { + def rr0 : SS48I, + OpSize; + + def rm0 : SS48I, OpSize; + } +} + +defm BLENDVPD : SS41I_ternary_int<0x15, "blendvpd", int_x86_sse41_blendvpd>; +defm BLENDVPS : SS41I_ternary_int<0x14, "blendvps", int_x86_sse41_blendvps>; +defm PBLENDVB : SS41I_ternary_int<0x10, "pblendvb", int_x86_sse41_pblendvb>; + + +multiclass SS41I_binop_rm_int8 opc, string OpcodeStr, Intrinsic IntId> { + def rr : SS48I, OpSize; + + def rm : SS48I, + OpSize; +} + +defm PMOVSXBW : SS41I_binop_rm_int8<0x20, "pmovsxbw", int_x86_sse41_pmovsxbw>; +defm PMOVSXWD : SS41I_binop_rm_int8<0x23, "pmovsxwd", int_x86_sse41_pmovsxwd>; +defm PMOVSXDQ : SS41I_binop_rm_int8<0x25, "pmovsxdq", int_x86_sse41_pmovsxdq>; +defm PMOVZXBW : SS41I_binop_rm_int8<0x30, "pmovzxbw", int_x86_sse41_pmovzxbw>; +defm PMOVZXWD : SS41I_binop_rm_int8<0x33, "pmovzxwd", int_x86_sse41_pmovzxwd>; +defm PMOVZXDQ : SS41I_binop_rm_int8<0x35, "pmovzxdq", int_x86_sse41_pmovzxdq>; + +// Common patterns involving scalar load. +def : Pat<(int_x86_sse41_pmovsxbw (vzmovl_v2i64 addr:$src)), + (PMOVSXBWrm addr:$src)>, Requires<[HasSSE41]>; +def : Pat<(int_x86_sse41_pmovsxbw (vzload_v2i64 addr:$src)), + (PMOVSXBWrm addr:$src)>, Requires<[HasSSE41]>; + +def : Pat<(int_x86_sse41_pmovsxwd (vzmovl_v2i64 addr:$src)), + (PMOVSXWDrm addr:$src)>, Requires<[HasSSE41]>; +def : Pat<(int_x86_sse41_pmovsxwd (vzload_v2i64 addr:$src)), + (PMOVSXWDrm addr:$src)>, Requires<[HasSSE41]>; + +def : Pat<(int_x86_sse41_pmovsxdq (vzmovl_v2i64 addr:$src)), + (PMOVSXDQrm addr:$src)>, Requires<[HasSSE41]>; +def : Pat<(int_x86_sse41_pmovsxdq (vzload_v2i64 addr:$src)), + (PMOVSXDQrm addr:$src)>, Requires<[HasSSE41]>; + +def : Pat<(int_x86_sse41_pmovzxbw (vzmovl_v2i64 addr:$src)), + (PMOVZXBWrm addr:$src)>, Requires<[HasSSE41]>; +def : Pat<(int_x86_sse41_pmovzxbw (vzload_v2i64 addr:$src)), + (PMOVZXBWrm addr:$src)>, Requires<[HasSSE41]>; + +def : Pat<(int_x86_sse41_pmovzxwd (vzmovl_v2i64 addr:$src)), + (PMOVZXWDrm addr:$src)>, Requires<[HasSSE41]>; +def : Pat<(int_x86_sse41_pmovzxwd (vzload_v2i64 addr:$src)), + (PMOVZXWDrm addr:$src)>, Requires<[HasSSE41]>; + +def : Pat<(int_x86_sse41_pmovzxdq (vzmovl_v2i64 addr:$src)), + (PMOVZXDQrm addr:$src)>, Requires<[HasSSE41]>; +def : Pat<(int_x86_sse41_pmovzxdq (vzload_v2i64 addr:$src)), + (PMOVZXDQrm addr:$src)>, Requires<[HasSSE41]>; + + +multiclass SS41I_binop_rm_int4 opc, string OpcodeStr, Intrinsic IntId> { + def rr : SS48I, OpSize; + + def rm : SS48I, + OpSize; +} + +defm PMOVSXBD : SS41I_binop_rm_int4<0x21, "pmovsxbd", int_x86_sse41_pmovsxbd>; +defm PMOVSXWQ : SS41I_binop_rm_int4<0x24, "pmovsxwq", int_x86_sse41_pmovsxwq>; +defm PMOVZXBD : SS41I_binop_rm_int4<0x31, "pmovzxbd", int_x86_sse41_pmovzxbd>; +defm PMOVZXWQ : SS41I_binop_rm_int4<0x34, "pmovzxwq", int_x86_sse41_pmovzxwq>; + +// Common patterns involving scalar load +def : Pat<(int_x86_sse41_pmovsxbd (vzmovl_v4i32 addr:$src)), + (PMOVSXBDrm addr:$src)>, Requires<[HasSSE41]>; +def : Pat<(int_x86_sse41_pmovsxwq (vzmovl_v4i32 addr:$src)), + (PMOVSXWQrm addr:$src)>, Requires<[HasSSE41]>; + +def : Pat<(int_x86_sse41_pmovzxbd (vzmovl_v4i32 addr:$src)), + (PMOVZXBDrm addr:$src)>, Requires<[HasSSE41]>; +def : Pat<(int_x86_sse41_pmovzxwq (vzmovl_v4i32 addr:$src)), + (PMOVZXWQrm addr:$src)>, Requires<[HasSSE41]>; + + +multiclass SS41I_binop_rm_int2 opc, string OpcodeStr, Intrinsic IntId> { + def rr : SS48I, OpSize; + + // Expecting a i16 load any extended to i32 value. + def rm : SS48I, + OpSize; +} + +defm PMOVSXBQ : SS41I_binop_rm_int2<0x22, "pmovsxbq", int_x86_sse41_pmovsxbq>; +defm PMOVZXBQ : SS41I_binop_rm_int2<0x32, "pmovzxbq", int_x86_sse41_pmovzxbq>; + +// Common patterns involving scalar load +def : Pat<(int_x86_sse41_pmovsxbq + (bitconvert (v4i32 (X86vzmovl + (v4i32 (scalar_to_vector (loadi32 addr:$src))))))), + (PMOVSXBQrm addr:$src)>, Requires<[HasSSE41]>; + +def : Pat<(int_x86_sse41_pmovzxbq + (bitconvert (v4i32 (X86vzmovl + (v4i32 (scalar_to_vector (loadi32 addr:$src))))))), + (PMOVZXBQrm addr:$src)>, Requires<[HasSSE41]>; + + +/// SS41I_binop_ext8 - SSE 4.1 extract 8 bits to 32 bit reg or 8 bit mem +multiclass SS41I_extract8 opc, string OpcodeStr> { + def rr : SS4AIi8, + OpSize; + def mr : SS4AIi8, OpSize; +// FIXME: +// There's an AssertZext in the way of writing the store pattern +// (store (i8 (trunc (X86pextrb (v16i8 VR128:$src1), imm:$src2))), addr:$dst) +} + +defm PEXTRB : SS41I_extract8<0x14, "pextrb">; + + +/// SS41I_extract16 - SSE 4.1 extract 16 bits to memory destination +multiclass SS41I_extract16 opc, string OpcodeStr> { + def mr : SS4AIi8, OpSize; +// FIXME: +// There's an AssertZext in the way of writing the store pattern +// (store (i16 (trunc (X86pextrw (v16i8 VR128:$src1), imm:$src2))), addr:$dst) +} + +defm PEXTRW : SS41I_extract16<0x15, "pextrw">; + + +/// SS41I_extract32 - SSE 4.1 extract 32 bits to int reg or memory destination +multiclass SS41I_extract32 opc, string OpcodeStr> { + def rr : SS4AIi8, OpSize; + def mr : SS4AIi8, OpSize; +} + +defm PEXTRD : SS41I_extract32<0x16, "pextrd">; + + +/// SS41I_extractf32 - SSE 4.1 extract 32 bits fp value to int reg or memory +/// destination +multiclass SS41I_extractf32 opc, string OpcodeStr> { + def rr : SS4AIi8, + OpSize; + def mr : SS4AIi8, OpSize; +} + +defm EXTRACTPS : SS41I_extractf32<0x17, "extractps">; + +// Also match an EXTRACTPS store when the store is done as f32 instead of i32. +def : Pat<(store (f32 (bitconvert (extractelt (bc_v4i32 (v4f32 VR128:$src1)), + imm:$src2))), + addr:$dst), + (EXTRACTPSmr addr:$dst, VR128:$src1, imm:$src2)>, + Requires<[HasSSE41]>; + +let Constraints = "$src1 = $dst" in { + multiclass SS41I_insert8 opc, string OpcodeStr> { + def rr : SS4AIi8, OpSize; + def rm : SS4AIi8, OpSize; + } +} + +defm PINSRB : SS41I_insert8<0x20, "pinsrb">; + +let Constraints = "$src1 = $dst" in { + multiclass SS41I_insert32 opc, string OpcodeStr> { + def rr : SS4AIi8, + OpSize; + def rm : SS4AIi8, OpSize; + } +} + +defm PINSRD : SS41I_insert32<0x22, "pinsrd">; + +// insertps has a few different modes, there's the first two here below which +// are optimized inserts that won't zero arbitrary elements in the destination +// vector. The next one matches the intrinsic and could zero arbitrary elements +// in the target vector. +let Constraints = "$src1 = $dst" in { + multiclass SS41I_insertf32 opc, string OpcodeStr> { + def rr : SS4AIi8, + OpSize; + def rm : SS4AIi8, OpSize; + } +} + +defm INSERTPS : SS41I_insertf32<0x21, "insertps">; + +def : Pat<(int_x86_sse41_insertps VR128:$src1, VR128:$src2, imm:$src3), + (INSERTPSrr VR128:$src1, VR128:$src2, imm:$src3)>; + +// ptest instruction we'll lower to this in X86ISelLowering primarily from +// the intel intrinsic that corresponds to this. +let Defs = [EFLAGS] in { +def PTESTrr : SS48I<0x17, MRMSrcReg, (outs), (ins VR128:$src1, VR128:$src2), + "ptest \t{$src2, $src1|$src1, $src2}", + [(X86ptest VR128:$src1, VR128:$src2), + (implicit EFLAGS)]>, OpSize; +def PTESTrm : SS48I<0x17, MRMSrcMem, (outs), (ins VR128:$src1, i128mem:$src2), + "ptest \t{$src2, $src1|$src1, $src2}", + [(X86ptest VR128:$src1, (load addr:$src2)), + (implicit EFLAGS)]>, OpSize; +} + +def MOVNTDQArm : SS48I<0x2A, MRMSrcMem, (outs VR128:$dst), (ins i128mem:$src), + "movntdqa\t{$src, $dst|$dst, $src}", + [(set VR128:$dst, (int_x86_sse41_movntdqa addr:$src))]>; + + +//===----------------------------------------------------------------------===// +// SSE4.2 Instructions +//===----------------------------------------------------------------------===// + +/// SS42I_binop_rm_int - Simple SSE 4.2 binary operator +let Constraints = "$src1 = $dst" in { + multiclass SS42I_binop_rm_int opc, string OpcodeStr, + Intrinsic IntId128, bit Commutable = 0> { + def rr : SS428I, + OpSize { + let isCommutable = Commutable; + } + def rm : SS428I, OpSize; + } +} + +defm PCMPGTQ : SS42I_binop_rm_int<0x37, "pcmpgtq", int_x86_sse42_pcmpgtq>; + +def : Pat<(v2i64 (X86pcmpgtq VR128:$src1, VR128:$src2)), + (PCMPGTQrr VR128:$src1, VR128:$src2)>; +def : Pat<(v2i64 (X86pcmpgtq VR128:$src1, (memop addr:$src2))), + (PCMPGTQrm VR128:$src1, addr:$src2)>; + +// crc intrinsic instruction +// This set of instructions are only rm, the only difference is the size +// of r and m. +let Constraints = "$src1 = $dst" in { + def CRC32m8 : SS42FI<0xF0, MRMSrcMem, (outs GR32:$dst), + (ins GR32:$src1, i8mem:$src2), + "crc32 \t{$src2, $src1|$src1, $src2}", + [(set GR32:$dst, + (int_x86_sse42_crc32_8 GR32:$src1, + (load addr:$src2)))]>, OpSize; + def CRC32r8 : SS42FI<0xF0, MRMSrcReg, (outs GR32:$dst), + (ins GR32:$src1, GR8:$src2), + "crc32 \t{$src2, $src1|$src1, $src2}", + [(set GR32:$dst, + (int_x86_sse42_crc32_8 GR32:$src1, GR8:$src2))]>, + OpSize; + def CRC32m16 : SS42FI<0xF1, MRMSrcMem, (outs GR32:$dst), + (ins GR32:$src1, i16mem:$src2), + "crc32 \t{$src2, $src1|$src1, $src2}", + [(set GR32:$dst, + (int_x86_sse42_crc32_16 GR32:$src1, + (load addr:$src2)))]>, + OpSize; + def CRC32r16 : SS42FI<0xF1, MRMSrcReg, (outs GR32:$dst), + (ins GR32:$src1, GR16:$src2), + "crc32 \t{$src2, $src1|$src1, $src2}", + [(set GR32:$dst, + (int_x86_sse42_crc32_16 GR32:$src1, GR16:$src2))]>, + OpSize; + def CRC32m32 : SS42FI<0xF1, MRMSrcMem, (outs GR32:$dst), + (ins GR32:$src1, i32mem:$src2), + "crc32 \t{$src2, $src1|$src1, $src2}", + [(set GR32:$dst, + (int_x86_sse42_crc32_32 GR32:$src1, + (load addr:$src2)))]>, OpSize; + def CRC32r32 : SS42FI<0xF1, MRMSrcReg, (outs GR32:$dst), + (ins GR32:$src1, GR32:$src2), + "crc32 \t{$src2, $src1|$src1, $src2}", + [(set GR32:$dst, + (int_x86_sse42_crc32_32 GR32:$src1, GR32:$src2))]>, + OpSize; + def CRC64m64 : SS42FI<0xF0, MRMSrcMem, (outs GR64:$dst), + (ins GR64:$src1, i64mem:$src2), + "crc32 \t{$src2, $src1|$src1, $src2}", + [(set GR64:$dst, + (int_x86_sse42_crc32_64 GR64:$src1, + (load addr:$src2)))]>, + OpSize, REX_W; + def CRC64r64 : SS42FI<0xF0, MRMSrcReg, (outs GR64:$dst), + (ins GR64:$src1, GR64:$src2), + "crc32 \t{$src2, $src1|$src1, $src2}", + [(set GR64:$dst, + (int_x86_sse42_crc32_64 GR64:$src1, GR64:$src2))]>, + OpSize, REX_W; +} + +// String/text processing instructions. +let Defs = [EFLAGS], usesCustomInserter = 1 in { +def PCMPISTRM128REG : SS42AI<0, Pseudo, (outs VR128:$dst), + (ins VR128:$src1, VR128:$src2, i8imm:$src3), + "#PCMPISTRM128rr PSEUDO!", + [(set VR128:$dst, + (int_x86_sse42_pcmpistrm128 VR128:$src1, VR128:$src2, + imm:$src3))]>, OpSize; +def PCMPISTRM128MEM : SS42AI<0, Pseudo, (outs VR128:$dst), + (ins VR128:$src1, i128mem:$src2, i8imm:$src3), + "#PCMPISTRM128rm PSEUDO!", + [(set VR128:$dst, + (int_x86_sse42_pcmpistrm128 VR128:$src1, + (load addr:$src2), + imm:$src3))]>, OpSize; +} + +let Defs = [XMM0, EFLAGS] in { +def PCMPISTRM128rr : SS42AI<0x62, MRMSrcReg, (outs), + (ins VR128:$src1, VR128:$src2, i8imm:$src3), + "pcmpistrm\t{$src3, $src2, $src1|$src1, $src2, $src3}", + []>, OpSize; +def PCMPISTRM128rm : SS42AI<0x62, MRMSrcMem, (outs), + (ins VR128:$src1, i128mem:$src2, i8imm:$src3), + "pcmpistrm\t{$src3, $src2, $src1|$src1, $src2, $src3}", + []>, OpSize; +} + +let Defs = [EFLAGS], Uses = [EAX, EDX], + usesCustomInserter = 1 in { +def PCMPESTRM128REG : SS42AI<0, Pseudo, (outs VR128:$dst), + (ins VR128:$src1, VR128:$src3, i8imm:$src5), + "#PCMPESTRM128rr PSEUDO!", + [(set VR128:$dst, + (int_x86_sse42_pcmpestrm128 VR128:$src1, EAX, + VR128:$src3, + EDX, imm:$src5))]>, OpSize; +def PCMPESTRM128MEM : SS42AI<0, Pseudo, (outs VR128:$dst), + (ins VR128:$src1, i128mem:$src3, i8imm:$src5), + "#PCMPESTRM128rm PSEUDO!", + [(set VR128:$dst, + (int_x86_sse42_pcmpestrm128 VR128:$src1, EAX, + (load addr:$src3), + EDX, imm:$src5))]>, OpSize; +} + +let Defs = [XMM0, EFLAGS], Uses = [EAX, EDX] in { +def PCMPESTRM128rr : SS42AI<0x60, MRMSrcReg, (outs), + (ins VR128:$src1, VR128:$src3, i8imm:$src5), + "pcmpestrm\t{$src5, $src3, $src1|$src1, $src3, $src5}", + []>, OpSize; +def PCMPESTRM128rm : SS42AI<0x60, MRMSrcMem, (outs), + (ins VR128:$src1, i128mem:$src3, i8imm:$src5), + "pcmpestrm\t{$src5, $src3, $src1|$src1, $src3, $src5}", + []>, OpSize; +} + +let Defs = [ECX, EFLAGS] in { + multiclass SS42AI_pcmpistri { + def rr : SS42AI<0x63, MRMSrcReg, (outs), + (ins VR128:$src1, VR128:$src2, i8imm:$src3), + "pcmpistri\t{$src3, $src2, $src1|$src1, $src2, $src3}", + [(set ECX, + (IntId128 VR128:$src1, VR128:$src2, imm:$src3)), + (implicit EFLAGS)]>, + OpSize; + def rm : SS42AI<0x63, MRMSrcMem, (outs), + (ins VR128:$src1, i128mem:$src2, i8imm:$src3), + "pcmpistri\t{$src3, $src2, $src1|$src1, $src2, $src3}", + [(set ECX, + (IntId128 VR128:$src1, (load addr:$src2), imm:$src3)), + (implicit EFLAGS)]>, + OpSize; + } +} + +defm PCMPISTRI : SS42AI_pcmpistri; +defm PCMPISTRIA : SS42AI_pcmpistri; +defm PCMPISTRIC : SS42AI_pcmpistri; +defm PCMPISTRIO : SS42AI_pcmpistri; +defm PCMPISTRIS : SS42AI_pcmpistri; +defm PCMPISTRIZ : SS42AI_pcmpistri; + +let Defs = [ECX, EFLAGS] in { +let Uses = [EAX, EDX] in { + multiclass SS42AI_pcmpestri { + def rr : SS42AI<0x61, MRMSrcReg, (outs), + (ins VR128:$src1, VR128:$src3, i8imm:$src5), + "pcmpestri\t{$src5, $src3, $src1|$src1, $src3, $src5}", + [(set ECX, + (IntId128 VR128:$src1, EAX, VR128:$src3, EDX, imm:$src5)), + (implicit EFLAGS)]>, + OpSize; + def rm : SS42AI<0x61, MRMSrcMem, (outs), + (ins VR128:$src1, i128mem:$src3, i8imm:$src5), + "pcmpestri\t{$src5, $src3, $src1|$src1, $src3, $src5}", + [(set ECX, + (IntId128 VR128:$src1, EAX, (load addr:$src3), + EDX, imm:$src5)), + (implicit EFLAGS)]>, + OpSize; + } +} +} + +defm PCMPESTRI : SS42AI_pcmpestri; +defm PCMPESTRIA : SS42AI_pcmpestri; +defm PCMPESTRIC : SS42AI_pcmpestri; +defm PCMPESTRIO : SS42AI_pcmpestri; +defm PCMPESTRIS : SS42AI_pcmpestri; +defm PCMPESTRIZ : SS42AI_pcmpestri; diff --git a/libclamav/c++/llvm/lib/Target/X86/X86JITInfo.cpp b/libclamav/c++/llvm/lib/Target/X86/X86JITInfo.cpp new file mode 100644 index 000000000..ce06f0fde --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/X86/X86JITInfo.cpp @@ -0,0 +1,556 @@ +//===-- X86JITInfo.cpp - Implement the JIT interfaces for the X86 target --===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the JIT interfaces for the X86 target. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "jit" +#include "X86JITInfo.h" +#include "X86Relocations.h" +#include "X86Subtarget.h" +#include "X86TargetMachine.h" +#include "llvm/Function.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/ErrorHandling.h" +#include +#include +using namespace llvm; + +// Determine the platform we're running on +#if defined (__x86_64__) || defined (_M_AMD64) || defined (_M_X64) +# define X86_64_JIT +#elif defined(__i386__) || defined(i386) || defined(_M_IX86) +# define X86_32_JIT +#endif + +void X86JITInfo::replaceMachineCodeForFunction(void *Old, void *New) { + unsigned char *OldByte = (unsigned char *)Old; + *OldByte++ = 0xE9; // Emit JMP opcode. + unsigned *OldWord = (unsigned *)OldByte; + unsigned NewAddr = (intptr_t)New; + unsigned OldAddr = (intptr_t)OldWord; + *OldWord = NewAddr - OldAddr - 4; // Emit PC-relative addr of New code. +} + + +/// JITCompilerFunction - This contains the address of the JIT function used to +/// compile a function lazily. +static TargetJITInfo::JITCompilerFn JITCompilerFunction; + +// Get the ASMPREFIX for the current host. This is often '_'. +#ifndef __USER_LABEL_PREFIX__ +#define __USER_LABEL_PREFIX__ +#endif +#define GETASMPREFIX2(X) #X +#define GETASMPREFIX(X) GETASMPREFIX2(X) +#define ASMPREFIX GETASMPREFIX(__USER_LABEL_PREFIX__) + +// For ELF targets, use a .size and .type directive, to let tools +// know the extent of functions defined in assembler. +#if defined(__ELF__) +# define SIZE(sym) ".size " #sym ", . - " #sym "\n" +# define TYPE_FUNCTION(sym) ".type " #sym ", @function\n" +#else +# define SIZE(sym) +# define TYPE_FUNCTION(sym) +#endif + +// Provide a convenient way for disabling usage of CFI directives. +// This is needed for old/broken assemblers (for example, gas on +// Darwin is pretty old and doesn't support these directives) +#if defined(__APPLE__) +# define CFI(x) +#else +// FIXME: Disable this until we really want to use it. Also, we will +// need to add some workarounds for compilers, which support +// only subset of these directives. +# define CFI(x) +#endif + +// Provide a wrapper for X86CompilationCallback2 that saves non-traditional +// callee saved registers, for the fastcc calling convention. +extern "C" { +#if defined(X86_64_JIT) +# ifndef _MSC_VER + // No need to save EAX/EDX for X86-64. + void X86CompilationCallback(void); + asm( + ".text\n" + ".align 8\n" + ".globl " ASMPREFIX "X86CompilationCallback\n" + TYPE_FUNCTION(X86CompilationCallback) + ASMPREFIX "X86CompilationCallback:\n" + CFI(".cfi_startproc\n") + // Save RBP + "pushq %rbp\n" + CFI(".cfi_def_cfa_offset 16\n") + CFI(".cfi_offset %rbp, -16\n") + // Save RSP + "movq %rsp, %rbp\n" + CFI(".cfi_def_cfa_register %rbp\n") + // Save all int arg registers + "pushq %rdi\n" + CFI(".cfi_rel_offset %rdi, 0\n") + "pushq %rsi\n" + CFI(".cfi_rel_offset %rsi, 8\n") + "pushq %rdx\n" + CFI(".cfi_rel_offset %rdx, 16\n") + "pushq %rcx\n" + CFI(".cfi_rel_offset %rcx, 24\n") + "pushq %r8\n" + CFI(".cfi_rel_offset %r8, 32\n") + "pushq %r9\n" + CFI(".cfi_rel_offset %r9, 40\n") + // Align stack on 16-byte boundary. ESP might not be properly aligned + // (8 byte) if this is called from an indirect stub. + "andq $-16, %rsp\n" + // Save all XMM arg registers + "subq $128, %rsp\n" + "movaps %xmm0, (%rsp)\n" + "movaps %xmm1, 16(%rsp)\n" + "movaps %xmm2, 32(%rsp)\n" + "movaps %xmm3, 48(%rsp)\n" + "movaps %xmm4, 64(%rsp)\n" + "movaps %xmm5, 80(%rsp)\n" + "movaps %xmm6, 96(%rsp)\n" + "movaps %xmm7, 112(%rsp)\n" + // JIT callee + "movq %rbp, %rdi\n" // Pass prev frame and return address + "movq 8(%rbp), %rsi\n" + "call " ASMPREFIX "X86CompilationCallback2\n" + // Restore all XMM arg registers + "movaps 112(%rsp), %xmm7\n" + "movaps 96(%rsp), %xmm6\n" + "movaps 80(%rsp), %xmm5\n" + "movaps 64(%rsp), %xmm4\n" + "movaps 48(%rsp), %xmm3\n" + "movaps 32(%rsp), %xmm2\n" + "movaps 16(%rsp), %xmm1\n" + "movaps (%rsp), %xmm0\n" + // Restore RSP + "movq %rbp, %rsp\n" + CFI(".cfi_def_cfa_register %rsp\n") + // Restore all int arg registers + "subq $48, %rsp\n" + CFI(".cfi_adjust_cfa_offset 48\n") + "popq %r9\n" + CFI(".cfi_adjust_cfa_offset -8\n") + CFI(".cfi_restore %r9\n") + "popq %r8\n" + CFI(".cfi_adjust_cfa_offset -8\n") + CFI(".cfi_restore %r8\n") + "popq %rcx\n" + CFI(".cfi_adjust_cfa_offset -8\n") + CFI(".cfi_restore %rcx\n") + "popq %rdx\n" + CFI(".cfi_adjust_cfa_offset -8\n") + CFI(".cfi_restore %rdx\n") + "popq %rsi\n" + CFI(".cfi_adjust_cfa_offset -8\n") + CFI(".cfi_restore %rsi\n") + "popq %rdi\n" + CFI(".cfi_adjust_cfa_offset -8\n") + CFI(".cfi_restore %rdi\n") + // Restore RBP + "popq %rbp\n" + CFI(".cfi_adjust_cfa_offset -8\n") + CFI(".cfi_restore %rbp\n") + "ret\n" + CFI(".cfi_endproc\n") + SIZE(X86CompilationCallback) + ); +# else + // No inline assembler support on this platform. The routine is in external + // file. + void X86CompilationCallback(); + +# endif +#elif defined (X86_32_JIT) +# ifndef _MSC_VER + void X86CompilationCallback(void); + asm( + ".text\n" + ".align 8\n" + ".globl " ASMPREFIX "X86CompilationCallback\n" + TYPE_FUNCTION(X86CompilationCallback) + ASMPREFIX "X86CompilationCallback:\n" + CFI(".cfi_startproc\n") + "pushl %ebp\n" + CFI(".cfi_def_cfa_offset 8\n") + CFI(".cfi_offset %ebp, -8\n") + "movl %esp, %ebp\n" // Standard prologue + CFI(".cfi_def_cfa_register %ebp\n") + "pushl %eax\n" + CFI(".cfi_rel_offset %eax, 0\n") + "pushl %edx\n" // Save EAX/EDX/ECX + CFI(".cfi_rel_offset %edx, 4\n") + "pushl %ecx\n" + CFI(".cfi_rel_offset %ecx, 8\n") +# if defined(__APPLE__) + "andl $-16, %esp\n" // Align ESP on 16-byte boundary +# endif + "subl $16, %esp\n" + "movl 4(%ebp), %eax\n" // Pass prev frame and return address + "movl %eax, 4(%esp)\n" + "movl %ebp, (%esp)\n" + "call " ASMPREFIX "X86CompilationCallback2\n" + "movl %ebp, %esp\n" // Restore ESP + CFI(".cfi_def_cfa_register %esp\n") + "subl $12, %esp\n" + CFI(".cfi_adjust_cfa_offset 12\n") + "popl %ecx\n" + CFI(".cfi_adjust_cfa_offset -4\n") + CFI(".cfi_restore %ecx\n") + "popl %edx\n" + CFI(".cfi_adjust_cfa_offset -4\n") + CFI(".cfi_restore %edx\n") + "popl %eax\n" + CFI(".cfi_adjust_cfa_offset -4\n") + CFI(".cfi_restore %eax\n") + "popl %ebp\n" + CFI(".cfi_adjust_cfa_offset -4\n") + CFI(".cfi_restore %ebp\n") + "ret\n" + CFI(".cfi_endproc\n") + SIZE(X86CompilationCallback) + ); + + // Same as X86CompilationCallback but also saves XMM argument registers. + void X86CompilationCallback_SSE(void); + asm( + ".text\n" + ".align 8\n" + ".globl " ASMPREFIX "X86CompilationCallback_SSE\n" + TYPE_FUNCTION(X86CompilationCallback_SSE) + ASMPREFIX "X86CompilationCallback_SSE:\n" + CFI(".cfi_startproc\n") + "pushl %ebp\n" + CFI(".cfi_def_cfa_offset 8\n") + CFI(".cfi_offset %ebp, -8\n") + "movl %esp, %ebp\n" // Standard prologue + CFI(".cfi_def_cfa_register %ebp\n") + "pushl %eax\n" + CFI(".cfi_rel_offset %eax, 0\n") + "pushl %edx\n" // Save EAX/EDX/ECX + CFI(".cfi_rel_offset %edx, 4\n") + "pushl %ecx\n" + CFI(".cfi_rel_offset %ecx, 8\n") + "andl $-16, %esp\n" // Align ESP on 16-byte boundary + // Save all XMM arg registers + "subl $64, %esp\n" + // FIXME: provide frame move information for xmm registers. + // This can be tricky, because CFA register is ebp (unaligned) + // and we need to produce offsets relative to it. + "movaps %xmm0, (%esp)\n" + "movaps %xmm1, 16(%esp)\n" + "movaps %xmm2, 32(%esp)\n" + "movaps %xmm3, 48(%esp)\n" + "subl $16, %esp\n" + "movl 4(%ebp), %eax\n" // Pass prev frame and return address + "movl %eax, 4(%esp)\n" + "movl %ebp, (%esp)\n" + "call " ASMPREFIX "X86CompilationCallback2\n" + "addl $16, %esp\n" + "movaps 48(%esp), %xmm3\n" + CFI(".cfi_restore %xmm3\n") + "movaps 32(%esp), %xmm2\n" + CFI(".cfi_restore %xmm2\n") + "movaps 16(%esp), %xmm1\n" + CFI(".cfi_restore %xmm1\n") + "movaps (%esp), %xmm0\n" + CFI(".cfi_restore %xmm0\n") + "movl %ebp, %esp\n" // Restore ESP + CFI(".cfi_def_cfa_register esp\n") + "subl $12, %esp\n" + CFI(".cfi_adjust_cfa_offset 12\n") + "popl %ecx\n" + CFI(".cfi_adjust_cfa_offset -4\n") + CFI(".cfi_restore %ecx\n") + "popl %edx\n" + CFI(".cfi_adjust_cfa_offset -4\n") + CFI(".cfi_restore %edx\n") + "popl %eax\n" + CFI(".cfi_adjust_cfa_offset -4\n") + CFI(".cfi_restore %eax\n") + "popl %ebp\n" + CFI(".cfi_adjust_cfa_offset -4\n") + CFI(".cfi_restore %ebp\n") + "ret\n" + CFI(".cfi_endproc\n") + SIZE(X86CompilationCallback_SSE) + ); +# else + void X86CompilationCallback2(intptr_t *StackPtr, intptr_t RetAddr); + + _declspec(naked) void X86CompilationCallback(void) { + __asm { + push ebp + mov ebp, esp + push eax + push edx + push ecx + and esp, -16 + mov eax, dword ptr [ebp+4] + mov dword ptr [esp+4], eax + mov dword ptr [esp], ebp + call X86CompilationCallback2 + mov esp, ebp + sub esp, 12 + pop ecx + pop edx + pop eax + pop ebp + ret + } + } + +# endif // _MSC_VER + +#else // Not an i386 host + void X86CompilationCallback() { + llvm_unreachable("Cannot call X86CompilationCallback() on a non-x86 arch!"); + } +#endif +} + +/// X86CompilationCallback2 - This is the target-specific function invoked by the +/// function stub when we did not know the real target of a call. This function +/// must locate the start of the stub or call site and pass it into the JIT +/// compiler function. +extern "C" { +#if !(defined (X86_64_JIT) && defined(_MSC_VER)) + // the following function is called only from this translation unit, + // unless we are under 64bit Windows with MSC, where there is + // no support for inline assembly +static +#endif +void ATTRIBUTE_USED +X86CompilationCallback2(intptr_t *StackPtr, intptr_t RetAddr) { + intptr_t *RetAddrLoc = &StackPtr[1]; + assert(*RetAddrLoc == RetAddr && + "Could not find return address on the stack!"); + + // It's a stub if there is an interrupt marker after the call. + bool isStub = ((unsigned char*)RetAddr)[0] == 0xCE; + + // The call instruction should have pushed the return value onto the stack... +#if defined (X86_64_JIT) + RetAddr--; // Backtrack to the reference itself... +#else + RetAddr -= 4; // Backtrack to the reference itself... +#endif + +#if 0 + DEBUG(errs() << "In callback! Addr=" << (void*)RetAddr + << " ESP=" << (void*)StackPtr + << ": Resolving call to function: " + << TheVM->getFunctionReferencedName((void*)RetAddr) << "\n"); +#endif + + // Sanity check to make sure this really is a call instruction. +#if defined (X86_64_JIT) + assert(((unsigned char*)RetAddr)[-2] == 0x41 &&"Not a call instr!"); + assert(((unsigned char*)RetAddr)[-1] == 0xFF &&"Not a call instr!"); +#else + assert(((unsigned char*)RetAddr)[-1] == 0xE8 &&"Not a call instr!"); +#endif + + intptr_t NewVal = (intptr_t)JITCompilerFunction((void*)RetAddr); + + // Rewrite the call target... so that we don't end up here every time we + // execute the call. +#if defined (X86_64_JIT) + assert(isStub && + "X86-64 doesn't support rewriting non-stub lazy compilation calls:" + " the call instruction varies too much."); +#else + *(intptr_t *)RetAddr = (intptr_t)(NewVal-RetAddr-4); +#endif + + if (isStub) { + // If this is a stub, rewrite the call into an unconditional branch + // instruction so that two return addresses are not pushed onto the stack + // when the requested function finally gets called. This also makes the + // 0xCE byte (interrupt) dead, so the marker doesn't effect anything. +#if defined (X86_64_JIT) + // If the target address is within 32-bit range of the stub, use a + // PC-relative branch instead of loading the actual address. (This is + // considerably shorter than the 64-bit immediate load already there.) + // We assume here intptr_t is 64 bits. + intptr_t diff = NewVal-RetAddr+7; + if (diff >= -2147483648LL && diff <= 2147483647LL) { + *(unsigned char*)(RetAddr-0xc) = 0xE9; + *(intptr_t *)(RetAddr-0xb) = diff & 0xffffffff; + } else { + *(intptr_t *)(RetAddr - 0xa) = NewVal; + ((unsigned char*)RetAddr)[0] = (2 | (4 << 3) | (3 << 6)); + } +#else + ((unsigned char*)RetAddr)[-1] = 0xE9; +#endif + } + + // Change the return address to reexecute the call instruction... +#if defined (X86_64_JIT) + *RetAddrLoc -= 0xd; +#else + *RetAddrLoc -= 5; +#endif +} +} + +TargetJITInfo::LazyResolverFn +X86JITInfo::getLazyResolverFunction(JITCompilerFn F) { + JITCompilerFunction = F; + +#if defined (X86_32_JIT) && !defined (_MSC_VER) + if (Subtarget->hasSSE1()) + return X86CompilationCallback_SSE; +#endif + + return X86CompilationCallback; +} + +X86JITInfo::X86JITInfo(X86TargetMachine &tm) : TM(tm) { + Subtarget = &TM.getSubtarget(); + useGOT = 0; + TLSOffset = 0; +} + +void *X86JITInfo::emitGlobalValueIndirectSym(const GlobalValue* GV, void *ptr, + JITCodeEmitter &JCE) { + MachineCodeEmitter::BufferState BS; +#if defined (X86_64_JIT) + JCE.startGVStub(BS, GV, 8, 8); + JCE.emitWordLE((unsigned)(intptr_t)ptr); + JCE.emitWordLE((unsigned)(((intptr_t)ptr) >> 32)); +#else + JCE.startGVStub(BS, GV, 4, 4); + JCE.emitWordLE((intptr_t)ptr); +#endif + return JCE.finishGVStub(BS); +} + +TargetJITInfo::StubLayout X86JITInfo::getStubLayout() { + // The 64-bit stub contains: + // movabs r10 <- 8-byte-target-address # 10 bytes + // call|jmp *r10 # 3 bytes + // The 32-bit stub contains a 5-byte call|jmp. + // If the stub is a call to the compilation callback, an extra byte is added + // to mark it as a stub. + StubLayout Result = {14, 4}; + return Result; +} + +void *X86JITInfo::emitFunctionStub(const Function* F, void *Target, + JITCodeEmitter &JCE) { + MachineCodeEmitter::BufferState BS; + // Note, we cast to intptr_t here to silence a -pedantic warning that + // complains about casting a function pointer to a normal pointer. +#if defined (X86_32_JIT) && !defined (_MSC_VER) + bool NotCC = (Target != (void*)(intptr_t)X86CompilationCallback && + Target != (void*)(intptr_t)X86CompilationCallback_SSE); +#else + bool NotCC = Target != (void*)(intptr_t)X86CompilationCallback; +#endif + JCE.emitAlignment(4); + void *Result = (void*)JCE.getCurrentPCValue(); + if (NotCC) { +#if defined (X86_64_JIT) + JCE.emitByte(0x49); // REX prefix + JCE.emitByte(0xB8+2); // movabsq r10 + JCE.emitWordLE((unsigned)(intptr_t)Target); + JCE.emitWordLE((unsigned)(((intptr_t)Target) >> 32)); + JCE.emitByte(0x41); // REX prefix + JCE.emitByte(0xFF); // jmpq *r10 + JCE.emitByte(2 | (4 << 3) | (3 << 6)); +#else + JCE.emitByte(0xE9); + JCE.emitWordLE((intptr_t)Target-JCE.getCurrentPCValue()-4); +#endif + return Result; + } + +#if defined (X86_64_JIT) + JCE.emitByte(0x49); // REX prefix + JCE.emitByte(0xB8+2); // movabsq r10 + JCE.emitWordLE((unsigned)(intptr_t)Target); + JCE.emitWordLE((unsigned)(((intptr_t)Target) >> 32)); + JCE.emitByte(0x41); // REX prefix + JCE.emitByte(0xFF); // callq *r10 + JCE.emitByte(2 | (2 << 3) | (3 << 6)); +#else + JCE.emitByte(0xE8); // Call with 32 bit pc-rel destination... + + JCE.emitWordLE((intptr_t)Target-JCE.getCurrentPCValue()-4); +#endif + + // This used to use 0xCD, but that value is used by JITMemoryManager to + // initialize the buffer with garbage, which means it may follow a + // noreturn function call, confusing X86CompilationCallback2. PR 4929. + JCE.emitByte(0xCE); // Interrupt - Just a marker identifying the stub! + return Result; +} + +/// getPICJumpTableEntry - Returns the value of the jumptable entry for the +/// specific basic block. +uintptr_t X86JITInfo::getPICJumpTableEntry(uintptr_t BB, uintptr_t Entry) { +#if defined(X86_64_JIT) + return BB - Entry; +#else + return BB - PICBase; +#endif +} + +/// relocate - Before the JIT can run a block of code that has been emitted, +/// it must rewrite the code to contain the actual addresses of any +/// referenced global symbols. +void X86JITInfo::relocate(void *Function, MachineRelocation *MR, + unsigned NumRelocs, unsigned char* GOTBase) { + for (unsigned i = 0; i != NumRelocs; ++i, ++MR) { + void *RelocPos = (char*)Function + MR->getMachineCodeOffset(); + intptr_t ResultPtr = (intptr_t)MR->getResultPointer(); + switch ((X86::RelocationType)MR->getRelocationType()) { + case X86::reloc_pcrel_word: { + // PC relative relocation, add the relocated value to the value already in + // memory, after we adjust it for where the PC is. + ResultPtr = ResultPtr -(intptr_t)RelocPos - 4 - MR->getConstantVal(); + *((unsigned*)RelocPos) += (unsigned)ResultPtr; + break; + } + case X86::reloc_picrel_word: { + // PIC base relative relocation, add the relocated value to the value + // already in memory, after we adjust it for where the PIC base is. + ResultPtr = ResultPtr - ((intptr_t)Function + MR->getConstantVal()); + *((unsigned*)RelocPos) += (unsigned)ResultPtr; + break; + } + case X86::reloc_absolute_word: + case X86::reloc_absolute_word_sext: + // Absolute relocation, just add the relocated value to the value already + // in memory. + *((unsigned*)RelocPos) += (unsigned)ResultPtr; + break; + case X86::reloc_absolute_dword: + *((intptr_t*)RelocPos) += ResultPtr; + break; + } + } +} + +char* X86JITInfo::allocateThreadLocalMemory(size_t size) { +#if defined(X86_32_JIT) && !defined(__APPLE__) && !defined(_MSC_VER) + TLSOffset -= size; + return TLSOffset; +#else + llvm_unreachable("Cannot allocate thread local storage on this arch!"); + return 0; +#endif +} diff --git a/libclamav/c++/llvm/lib/Target/X86/X86JITInfo.h b/libclamav/c++/llvm/lib/Target/X86/X86JITInfo.h new file mode 100644 index 000000000..238420c23 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/X86/X86JITInfo.h @@ -0,0 +1,81 @@ +//===- X86JITInfo.h - X86 implementation of the JIT interface --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the X86 implementation of the TargetJITInfo class. +// +//===----------------------------------------------------------------------===// + +#ifndef X86JITINFO_H +#define X86JITINFO_H + +#include "llvm/Function.h" +#include "llvm/CodeGen/JITCodeEmitter.h" +#include "llvm/Target/TargetJITInfo.h" + +namespace llvm { + class X86TargetMachine; + class X86Subtarget; + + class X86JITInfo : public TargetJITInfo { + X86TargetMachine &TM; + const X86Subtarget *Subtarget; + uintptr_t PICBase; + char* TLSOffset; + public: + explicit X86JITInfo(X86TargetMachine &tm); + + /// replaceMachineCodeForFunction - Make it so that calling the function + /// whose machine code is at OLD turns into a call to NEW, perhaps by + /// overwriting OLD with a branch to NEW. This is used for self-modifying + /// code. + /// + virtual void replaceMachineCodeForFunction(void *Old, void *New); + + /// emitGlobalValueIndirectSym - Use the specified JITCodeEmitter object + /// to emit an indirect symbol which contains the address of the specified + /// ptr. + virtual void *emitGlobalValueIndirectSym(const GlobalValue* GV, void *ptr, + JITCodeEmitter &JCE); + + // getStubLayout - Returns the size and alignment of the largest call stub + // on X86. + virtual StubLayout getStubLayout(); + + /// emitFunctionStub - Use the specified JITCodeEmitter object to emit a + /// small native function that simply calls the function at the specified + /// address. + virtual void *emitFunctionStub(const Function* F, void *Target, + JITCodeEmitter &JCE); + + /// getPICJumpTableEntry - Returns the value of the jumptable entry for the + /// specific basic block. + virtual uintptr_t getPICJumpTableEntry(uintptr_t BB, uintptr_t JTBase); + + /// getLazyResolverFunction - Expose the lazy resolver to the JIT. + virtual LazyResolverFn getLazyResolverFunction(JITCompilerFn); + + /// relocate - Before the JIT can run a block of code that has been emitted, + /// it must rewrite the code to contain the actual addresses of any + /// referenced global symbols. + virtual void relocate(void *Function, MachineRelocation *MR, + unsigned NumRelocs, unsigned char* GOTBase); + + /// allocateThreadLocalMemory - Each target has its own way of + /// handling thread local variables. This method returns a value only + /// meaningful to the target. + virtual char* allocateThreadLocalMemory(size_t size); + + /// setPICBase / getPICBase - Getter / setter of PICBase, used to compute + /// PIC jumptable entry. + void setPICBase(uintptr_t Base) { PICBase = Base; } + uintptr_t getPICBase() const { return PICBase; } + }; +} + +#endif diff --git a/libclamav/c++/llvm/lib/Target/X86/X86MCAsmInfo.cpp b/libclamav/c++/llvm/lib/Target/X86/X86MCAsmInfo.cpp new file mode 100644 index 000000000..9d7e66deb --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/X86/X86MCAsmInfo.cpp @@ -0,0 +1,123 @@ +//===-- X86MCAsmInfo.cpp - X86 asm properties -----------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the declarations of the X86MCAsmInfo properties. +// +//===----------------------------------------------------------------------===// + +#include "X86MCAsmInfo.h" +#include "X86TargetMachine.h" +#include "llvm/ADT/Triple.h" +#include "llvm/Support/CommandLine.h" +using namespace llvm; + +enum AsmWriterFlavorTy { + // Note: This numbering has to match the GCC assembler dialects for inline + // asm alternatives to work right. + ATT = 0, Intel = 1 +}; + +static cl::opt +AsmWriterFlavor("x86-asm-syntax", cl::init(ATT), + cl::desc("Choose style of code to emit from X86 backend:"), + cl::values(clEnumValN(ATT, "att", "Emit AT&T-style assembly"), + clEnumValN(Intel, "intel", "Emit Intel-style assembly"), + clEnumValEnd)); + + +static const char *const x86_asm_table[] = { + "{si}", "S", + "{di}", "D", + "{ax}", "a", + "{cx}", "c", + "{memory}", "memory", + "{flags}", "", + "{dirflag}", "", + "{fpsr}", "", + "{cc}", "cc", + 0,0}; + +X86MCAsmInfoDarwin::X86MCAsmInfoDarwin(const Triple &Triple) { + AsmTransCBE = x86_asm_table; + AssemblerDialect = AsmWriterFlavor; + + bool is64Bit = Triple.getArch() == Triple::x86_64; + + TextAlignFillValue = 0x90; + + if (!is64Bit) + Data64bitsDirective = 0; // we can't emit a 64-bit unit + + // Leopard and above support aligned common symbols. + COMMDirectiveTakesAlignment = Triple.getDarwinMajorNumber() >= 9; + + CommentString = "##"; + PCSymbol = "."; + + SupportsDebugInformation = true; + DwarfUsesInlineInfoSection = true; + + // Exceptions handling + ExceptionsType = ExceptionHandling::Dwarf; + AbsoluteEHSectionOffsets = false; +} + +X86ELFMCAsmInfo::X86ELFMCAsmInfo(const Triple &Triple) { + AsmTransCBE = x86_asm_table; + AssemblerDialect = AsmWriterFlavor; + + PrivateGlobalPrefix = ".L"; + WeakRefDirective = "\t.weak\t"; + SetDirective = "\t.set\t"; + PCSymbol = "."; + + // Set up DWARF directives + HasLEB128 = true; // Target asm supports leb128 directives (little-endian) + + // Debug Information + AbsoluteDebugSectionOffsets = true; + SupportsDebugInformation = true; + + // Exceptions handling + ExceptionsType = ExceptionHandling::Dwarf; + AbsoluteEHSectionOffsets = false; + + // On Linux we must declare when we can use a non-executable stack. + if (Triple.getOS() == Triple::Linux) + NonexecutableStackDirective = "\t.section\t.note.GNU-stack,\"\",@progbits"; +} + +X86MCAsmInfoCOFF::X86MCAsmInfoCOFF(const Triple &Triple) { + AsmTransCBE = x86_asm_table; + AssemblerDialect = AsmWriterFlavor; +} + + +X86WinMCAsmInfo::X86WinMCAsmInfo(const Triple &Triple) { + AsmTransCBE = x86_asm_table; + AssemblerDialect = AsmWriterFlavor; + + GlobalPrefix = "_"; + CommentString = ";"; + + PrivateGlobalPrefix = "$"; + AlignDirective = "\tALIGN\t"; + ZeroDirective = "\tdb\t"; + ZeroDirectiveSuffix = " dup(0)"; + AsciiDirective = "\tdb\t"; + AscizDirective = 0; + Data8bitsDirective = "\tdb\t"; + Data16bitsDirective = "\tdw\t"; + Data32bitsDirective = "\tdd\t"; + Data64bitsDirective = "\tdq\t"; + HasDotTypeDotSizeDirective = false; + HasSingleParameterDotFile = false; + + AlignmentIsInBytes = true; +} diff --git a/libclamav/c++/llvm/lib/Target/X86/X86MCAsmInfo.h b/libclamav/c++/llvm/lib/Target/X86/X86MCAsmInfo.h new file mode 100644 index 000000000..18e2bdbcb --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/X86/X86MCAsmInfo.h @@ -0,0 +1,42 @@ +//=====-- X86MCAsmInfo.h - X86 asm properties -----------------*- C++ -*--====// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the declaration of the X86MCAsmInfo class. +// +//===----------------------------------------------------------------------===// + +#ifndef X86TARGETASMINFO_H +#define X86TARGETASMINFO_H + +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCAsmInfoCOFF.h" +#include "llvm/MC/MCAsmInfoDarwin.h" + +namespace llvm { + class Triple; + + struct X86MCAsmInfoDarwin : public MCAsmInfoDarwin { + explicit X86MCAsmInfoDarwin(const Triple &Triple); + }; + + struct X86ELFMCAsmInfo : public MCAsmInfo { + explicit X86ELFMCAsmInfo(const Triple &Triple); + }; + + struct X86MCAsmInfoCOFF : public MCAsmInfoCOFF { + explicit X86MCAsmInfoCOFF(const Triple &Triple); + }; + + struct X86WinMCAsmInfo : public MCAsmInfo { + explicit X86WinMCAsmInfo(const Triple &Triple); + }; + +} // namespace llvm + +#endif diff --git a/libclamav/c++/llvm/lib/Target/X86/X86MachineFunctionInfo.h b/libclamav/c++/llvm/lib/Target/X86/X86MachineFunctionInfo.h new file mode 100644 index 000000000..fafcf7e3d --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/X86/X86MachineFunctionInfo.h @@ -0,0 +1,113 @@ +//====- X86MachineFuctionInfo.h - X86 machine function 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 declares X86-specific per-machine-function information. +// +//===----------------------------------------------------------------------===// + +#ifndef X86MACHINEFUNCTIONINFO_H +#define X86MACHINEFUNCTIONINFO_H + +#include "llvm/CodeGen/MachineFunction.h" + +namespace llvm { + +enum NameDecorationStyle { + None, + StdCall, + FastCall +}; + +/// X86MachineFunctionInfo - This class is derived from MachineFunction and +/// contains private X86 target-specific information for each MachineFunction. +class X86MachineFunctionInfo : public MachineFunctionInfo { + /// ForceFramePointer - True if the function is required to use of frame + /// pointer for reasons other than it containing dynamic allocation or + /// that FP eliminatation is turned off. For example, Cygwin main function + /// contains stack pointer re-alignment code which requires FP. + bool ForceFramePointer; + + /// CalleeSavedFrameSize - Size of the callee-saved register portion of the + /// stack frame in bytes. + unsigned CalleeSavedFrameSize; + + /// BytesToPopOnReturn - Number of bytes function pops on return. + /// Used on windows platform for stdcall & fastcall name decoration + unsigned BytesToPopOnReturn; + + /// DecorationStyle - If the function requires additional name decoration, + /// DecorationStyle holds the right way to do so. + NameDecorationStyle DecorationStyle; + + /// ReturnAddrIndex - FrameIndex for return slot. + int ReturnAddrIndex; + + /// TailCallReturnAddrDelta - Delta the ReturnAddr stack slot is moved + /// Used for creating an area before the register spill area on the stack + /// the returnaddr can be savely move to this area + int TailCallReturnAddrDelta; + + /// SRetReturnReg - Some subtargets require that sret lowering includes + /// returning the value of the returned struct in a register. This field + /// holds the virtual register into which the sret argument is passed. + unsigned SRetReturnReg; + + /// GlobalBaseReg - keeps track of the virtual register initialized for + /// use as the global base register. This is used for PIC in some PIC + /// relocation models. + unsigned GlobalBaseReg; + +public: + X86MachineFunctionInfo() : ForceFramePointer(false), + CalleeSavedFrameSize(0), + BytesToPopOnReturn(0), + DecorationStyle(None), + ReturnAddrIndex(0), + TailCallReturnAddrDelta(0), + SRetReturnReg(0), + GlobalBaseReg(0) {} + + explicit X86MachineFunctionInfo(MachineFunction &MF) + : ForceFramePointer(false), + CalleeSavedFrameSize(0), + BytesToPopOnReturn(0), + DecorationStyle(None), + ReturnAddrIndex(0), + TailCallReturnAddrDelta(0), + SRetReturnReg(0), + GlobalBaseReg(0) {} + + bool getForceFramePointer() const { return ForceFramePointer;} + void setForceFramePointer(bool forceFP) { ForceFramePointer = forceFP; } + + unsigned getCalleeSavedFrameSize() const { return CalleeSavedFrameSize; } + void setCalleeSavedFrameSize(unsigned bytes) { CalleeSavedFrameSize = bytes; } + + unsigned getBytesToPopOnReturn() const { return BytesToPopOnReturn; } + void setBytesToPopOnReturn (unsigned bytes) { BytesToPopOnReturn = bytes;} + + NameDecorationStyle getDecorationStyle() const { return DecorationStyle; } + void setDecorationStyle(NameDecorationStyle style) { DecorationStyle = style;} + + int getRAIndex() const { return ReturnAddrIndex; } + void setRAIndex(int Index) { ReturnAddrIndex = Index; } + + int getTCReturnAddrDelta() const { return TailCallReturnAddrDelta; } + void setTCReturnAddrDelta(int delta) {TailCallReturnAddrDelta = delta;} + + unsigned getSRetReturnReg() const { return SRetReturnReg; } + void setSRetReturnReg(unsigned Reg) { SRetReturnReg = Reg; } + + unsigned getGlobalBaseReg() const { return GlobalBaseReg; } + void setGlobalBaseReg(unsigned Reg) { GlobalBaseReg = Reg; } +}; + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/lib/Target/X86/X86RegisterInfo.cpp b/libclamav/c++/llvm/lib/Target/X86/X86RegisterInfo.cpp new file mode 100644 index 000000000..f577fcf13 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/X86/X86RegisterInfo.cpp @@ -0,0 +1,1526 @@ +//===- X86RegisterInfo.cpp - X86 Register Information -----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the X86 implementation of the TargetRegisterInfo class. +// This file is responsible for the frame pointer elimination optimization +// on X86. +// +//===----------------------------------------------------------------------===// + +#include "X86.h" +#include "X86RegisterInfo.h" +#include "X86InstrBuilder.h" +#include "X86MachineFunctionInfo.h" +#include "X86Subtarget.h" +#include "X86TargetMachine.h" +#include "llvm/Constants.h" +#include "llvm/Function.h" +#include "llvm/Type.h" +#include "llvm/CodeGen/ValueTypes.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineLocation.h" +#include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/Target/TargetFrameInfo.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetOptions.h" +#include "llvm/ADT/BitVector.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/ErrorHandling.h" +using namespace llvm; + +X86RegisterInfo::X86RegisterInfo(X86TargetMachine &tm, + const TargetInstrInfo &tii) + : X86GenRegisterInfo(tm.getSubtarget().is64Bit() ? + X86::ADJCALLSTACKDOWN64 : + X86::ADJCALLSTACKDOWN32, + tm.getSubtarget().is64Bit() ? + X86::ADJCALLSTACKUP64 : + X86::ADJCALLSTACKUP32), + TM(tm), TII(tii) { + // Cache some information. + const X86Subtarget *Subtarget = &TM.getSubtarget(); + Is64Bit = Subtarget->is64Bit(); + IsWin64 = Subtarget->isTargetWin64(); + StackAlign = TM.getFrameInfo()->getStackAlignment(); + + if (Is64Bit) { + SlotSize = 8; + StackPtr = X86::RSP; + FramePtr = X86::RBP; + } else { + SlotSize = 4; + StackPtr = X86::ESP; + FramePtr = X86::EBP; + } +} + +/// getDwarfRegNum - This function maps LLVM register identifiers to the DWARF +/// specific numbering, used in debug info and exception tables. +int X86RegisterInfo::getDwarfRegNum(unsigned RegNo, bool isEH) const { + const X86Subtarget *Subtarget = &TM.getSubtarget(); + unsigned Flavour = DWARFFlavour::X86_64; + + if (!Subtarget->is64Bit()) { + if (Subtarget->isTargetDarwin()) { + if (isEH) + Flavour = DWARFFlavour::X86_32_DarwinEH; + else + Flavour = DWARFFlavour::X86_32_Generic; + } else if (Subtarget->isTargetCygMing()) { + // Unsupported by now, just quick fallback + Flavour = DWARFFlavour::X86_32_Generic; + } else { + Flavour = DWARFFlavour::X86_32_Generic; + } + } + + return X86GenRegisterInfo::getDwarfRegNumFull(RegNo, Flavour); +} + +/// getX86RegNum - This function maps LLVM register identifiers to their X86 +/// specific numbering, which is used in various places encoding instructions. +unsigned X86RegisterInfo::getX86RegNum(unsigned RegNo) { + switch(RegNo) { + case X86::RAX: case X86::EAX: case X86::AX: case X86::AL: return N86::EAX; + case X86::RCX: case X86::ECX: case X86::CX: case X86::CL: return N86::ECX; + case X86::RDX: case X86::EDX: case X86::DX: case X86::DL: return N86::EDX; + case X86::RBX: case X86::EBX: case X86::BX: case X86::BL: return N86::EBX; + case X86::RSP: case X86::ESP: case X86::SP: case X86::SPL: case X86::AH: + return N86::ESP; + case X86::RBP: case X86::EBP: case X86::BP: case X86::BPL: case X86::CH: + return N86::EBP; + case X86::RSI: case X86::ESI: case X86::SI: case X86::SIL: case X86::DH: + return N86::ESI; + case X86::RDI: case X86::EDI: case X86::DI: case X86::DIL: case X86::BH: + return N86::EDI; + + case X86::R8: case X86::R8D: case X86::R8W: case X86::R8B: + return N86::EAX; + case X86::R9: case X86::R9D: case X86::R9W: case X86::R9B: + return N86::ECX; + case X86::R10: case X86::R10D: case X86::R10W: case X86::R10B: + return N86::EDX; + case X86::R11: case X86::R11D: case X86::R11W: case X86::R11B: + return N86::EBX; + case X86::R12: case X86::R12D: case X86::R12W: case X86::R12B: + return N86::ESP; + case X86::R13: case X86::R13D: case X86::R13W: case X86::R13B: + return N86::EBP; + case X86::R14: case X86::R14D: case X86::R14W: case X86::R14B: + return N86::ESI; + case X86::R15: case X86::R15D: case X86::R15W: case X86::R15B: + return N86::EDI; + + case X86::ST0: case X86::ST1: case X86::ST2: case X86::ST3: + case X86::ST4: case X86::ST5: case X86::ST6: case X86::ST7: + return RegNo-X86::ST0; + + case X86::XMM0: case X86::XMM8: case X86::MM0: + return 0; + case X86::XMM1: case X86::XMM9: case X86::MM1: + return 1; + case X86::XMM2: case X86::XMM10: case X86::MM2: + return 2; + case X86::XMM3: case X86::XMM11: case X86::MM3: + return 3; + case X86::XMM4: case X86::XMM12: case X86::MM4: + return 4; + case X86::XMM5: case X86::XMM13: case X86::MM5: + return 5; + case X86::XMM6: case X86::XMM14: case X86::MM6: + return 6; + case X86::XMM7: case X86::XMM15: case X86::MM7: + return 7; + + default: + assert(isVirtualRegister(RegNo) && "Unknown physical register!"); + llvm_unreachable("Register allocator hasn't allocated reg correctly yet!"); + return 0; + } +} + +const TargetRegisterClass * +X86RegisterInfo::getMatchingSuperRegClass(const TargetRegisterClass *A, + const TargetRegisterClass *B, + unsigned SubIdx) const { + switch (SubIdx) { + default: return 0; + case 1: + // 8-bit + if (B == &X86::GR8RegClass) { + if (A->getSize() == 2 || A->getSize() == 4 || A->getSize() == 8) + return A; + } else if (B == &X86::GR8_ABCD_LRegClass || B == &X86::GR8_ABCD_HRegClass) { + if (A == &X86::GR64RegClass || A == &X86::GR64_ABCDRegClass || + A == &X86::GR64_NOREXRegClass || + A == &X86::GR64_NOSPRegClass || + A == &X86::GR64_NOREX_NOSPRegClass) + return &X86::GR64_ABCDRegClass; + else if (A == &X86::GR32RegClass || A == &X86::GR32_ABCDRegClass || + A == &X86::GR32_NOREXRegClass || + A == &X86::GR32_NOSPRegClass) + return &X86::GR32_ABCDRegClass; + else if (A == &X86::GR16RegClass || A == &X86::GR16_ABCDRegClass || + A == &X86::GR16_NOREXRegClass) + return &X86::GR16_ABCDRegClass; + } else if (B == &X86::GR8_NOREXRegClass) { + if (A == &X86::GR64RegClass || A == &X86::GR64_NOREXRegClass || + A == &X86::GR64_NOSPRegClass || A == &X86::GR64_NOREX_NOSPRegClass) + return &X86::GR64_NOREXRegClass; + else if (A == &X86::GR64_ABCDRegClass) + return &X86::GR64_ABCDRegClass; + else if (A == &X86::GR32RegClass || A == &X86::GR32_NOREXRegClass || + A == &X86::GR32_NOSPRegClass) + return &X86::GR32_NOREXRegClass; + else if (A == &X86::GR32_ABCDRegClass) + return &X86::GR32_ABCDRegClass; + else if (A == &X86::GR16RegClass || A == &X86::GR16_NOREXRegClass) + return &X86::GR16_NOREXRegClass; + else if (A == &X86::GR16_ABCDRegClass) + return &X86::GR16_ABCDRegClass; + } + break; + case 2: + // 8-bit hi + if (B == &X86::GR8_ABCD_HRegClass) { + if (A == &X86::GR64RegClass || A == &X86::GR64_ABCDRegClass || + A == &X86::GR64_NOREXRegClass || + A == &X86::GR64_NOSPRegClass || + A == &X86::GR64_NOREX_NOSPRegClass) + return &X86::GR64_ABCDRegClass; + else if (A == &X86::GR32RegClass || A == &X86::GR32_ABCDRegClass || + A == &X86::GR32_NOREXRegClass || A == &X86::GR32_NOSPRegClass) + return &X86::GR32_ABCDRegClass; + else if (A == &X86::GR16RegClass || A == &X86::GR16_ABCDRegClass || + A == &X86::GR16_NOREXRegClass) + return &X86::GR16_ABCDRegClass; + } + break; + case 3: + // 16-bit + if (B == &X86::GR16RegClass) { + if (A->getSize() == 4 || A->getSize() == 8) + return A; + } else if (B == &X86::GR16_ABCDRegClass) { + if (A == &X86::GR64RegClass || A == &X86::GR64_ABCDRegClass || + A == &X86::GR64_NOREXRegClass || + A == &X86::GR64_NOSPRegClass || + A == &X86::GR64_NOREX_NOSPRegClass) + return &X86::GR64_ABCDRegClass; + else if (A == &X86::GR32RegClass || A == &X86::GR32_ABCDRegClass || + A == &X86::GR32_NOREXRegClass || A == &X86::GR32_NOSPRegClass) + return &X86::GR32_ABCDRegClass; + } else if (B == &X86::GR16_NOREXRegClass) { + if (A == &X86::GR64RegClass || A == &X86::GR64_NOREXRegClass || + A == &X86::GR64_NOSPRegClass || A == &X86::GR64_NOREX_NOSPRegClass) + return &X86::GR64_NOREXRegClass; + else if (A == &X86::GR64_ABCDRegClass) + return &X86::GR64_ABCDRegClass; + else if (A == &X86::GR32RegClass || A == &X86::GR32_NOREXRegClass || + A == &X86::GR32_NOSPRegClass) + return &X86::GR32_NOREXRegClass; + else if (A == &X86::GR32_ABCDRegClass) + return &X86::GR64_ABCDRegClass; + } + break; + case 4: + // 32-bit + if (B == &X86::GR32RegClass || B == &X86::GR32_NOSPRegClass) { + if (A->getSize() == 8) + return A; + } else if (B == &X86::GR32_ABCDRegClass) { + if (A == &X86::GR64RegClass || A == &X86::GR64_ABCDRegClass || + A == &X86::GR64_NOREXRegClass || + A == &X86::GR64_NOSPRegClass || + A == &X86::GR64_NOREX_NOSPRegClass) + return &X86::GR64_ABCDRegClass; + } else if (B == &X86::GR32_NOREXRegClass) { + if (A == &X86::GR64RegClass || A == &X86::GR64_NOREXRegClass || + A == &X86::GR64_NOSPRegClass || A == &X86::GR64_NOREX_NOSPRegClass) + return &X86::GR64_NOREXRegClass; + else if (A == &X86::GR64_ABCDRegClass) + return &X86::GR64_ABCDRegClass; + } + break; + } + return 0; +} + +const TargetRegisterClass * +X86RegisterInfo::getPointerRegClass(unsigned Kind) const { + switch (Kind) { + default: llvm_unreachable("Unexpected Kind in getPointerRegClass!"); + case 0: // Normal GPRs. + if (TM.getSubtarget().is64Bit()) + return &X86::GR64RegClass; + return &X86::GR32RegClass; + case 1: // Normal GRPs except the stack pointer (for encoding reasons). + if (TM.getSubtarget().is64Bit()) + return &X86::GR64_NOSPRegClass; + return &X86::GR32_NOSPRegClass; + } +} + +const TargetRegisterClass * +X86RegisterInfo::getCrossCopyRegClass(const TargetRegisterClass *RC) const { + if (RC == &X86::CCRRegClass) { + if (Is64Bit) + return &X86::GR64RegClass; + else + return &X86::GR32RegClass; + } + return NULL; +} + +const unsigned * +X86RegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const { + bool callsEHReturn = false; + + if (MF) { + const MachineFrameInfo *MFI = MF->getFrameInfo(); + const MachineModuleInfo *MMI = MFI->getMachineModuleInfo(); + callsEHReturn = (MMI ? MMI->callsEHReturn() : false); + } + + static const unsigned CalleeSavedRegs32Bit[] = { + X86::ESI, X86::EDI, X86::EBX, X86::EBP, 0 + }; + + static const unsigned CalleeSavedRegs32EHRet[] = { + X86::EAX, X86::EDX, X86::ESI, X86::EDI, X86::EBX, X86::EBP, 0 + }; + + static const unsigned CalleeSavedRegs64Bit[] = { + X86::RBX, X86::R12, X86::R13, X86::R14, X86::R15, X86::RBP, 0 + }; + + static const unsigned CalleeSavedRegs64EHRet[] = { + X86::RAX, X86::RDX, X86::RBX, X86::R12, + X86::R13, X86::R14, X86::R15, X86::RBP, 0 + }; + + static const unsigned CalleeSavedRegsWin64[] = { + X86::RBX, X86::RBP, X86::RDI, X86::RSI, + X86::R12, X86::R13, X86::R14, X86::R15, + X86::XMM6, X86::XMM7, X86::XMM8, X86::XMM9, + X86::XMM10, X86::XMM11, X86::XMM12, X86::XMM13, + X86::XMM14, X86::XMM15, 0 + }; + + if (Is64Bit) { + if (IsWin64) + return CalleeSavedRegsWin64; + else + return (callsEHReturn ? CalleeSavedRegs64EHRet : CalleeSavedRegs64Bit); + } else { + return (callsEHReturn ? CalleeSavedRegs32EHRet : CalleeSavedRegs32Bit); + } +} + +const TargetRegisterClass* const* +X86RegisterInfo::getCalleeSavedRegClasses(const MachineFunction *MF) const { + bool callsEHReturn = false; + + if (MF) { + const MachineFrameInfo *MFI = MF->getFrameInfo(); + const MachineModuleInfo *MMI = MFI->getMachineModuleInfo(); + callsEHReturn = (MMI ? MMI->callsEHReturn() : false); + } + + static const TargetRegisterClass * const CalleeSavedRegClasses32Bit[] = { + &X86::GR32RegClass, &X86::GR32RegClass, + &X86::GR32RegClass, &X86::GR32RegClass, 0 + }; + static const TargetRegisterClass * const CalleeSavedRegClasses32EHRet[] = { + &X86::GR32RegClass, &X86::GR32RegClass, + &X86::GR32RegClass, &X86::GR32RegClass, + &X86::GR32RegClass, &X86::GR32RegClass, 0 + }; + static const TargetRegisterClass * const CalleeSavedRegClasses64Bit[] = { + &X86::GR64RegClass, &X86::GR64RegClass, + &X86::GR64RegClass, &X86::GR64RegClass, + &X86::GR64RegClass, &X86::GR64RegClass, 0 + }; + static const TargetRegisterClass * const CalleeSavedRegClasses64EHRet[] = { + &X86::GR64RegClass, &X86::GR64RegClass, + &X86::GR64RegClass, &X86::GR64RegClass, + &X86::GR64RegClass, &X86::GR64RegClass, + &X86::GR64RegClass, &X86::GR64RegClass, 0 + }; + static const TargetRegisterClass * const CalleeSavedRegClassesWin64[] = { + &X86::GR64RegClass, &X86::GR64RegClass, + &X86::GR64RegClass, &X86::GR64RegClass, + &X86::GR64RegClass, &X86::GR64RegClass, + &X86::GR64RegClass, &X86::GR64RegClass, + &X86::VR128RegClass, &X86::VR128RegClass, + &X86::VR128RegClass, &X86::VR128RegClass, + &X86::VR128RegClass, &X86::VR128RegClass, + &X86::VR128RegClass, &X86::VR128RegClass, + &X86::VR128RegClass, &X86::VR128RegClass, 0 + }; + + if (Is64Bit) { + if (IsWin64) + return CalleeSavedRegClassesWin64; + else + return (callsEHReturn ? + CalleeSavedRegClasses64EHRet : CalleeSavedRegClasses64Bit); + } else { + return (callsEHReturn ? + CalleeSavedRegClasses32EHRet : CalleeSavedRegClasses32Bit); + } +} + +BitVector X86RegisterInfo::getReservedRegs(const MachineFunction &MF) const { + BitVector Reserved(getNumRegs()); + // Set the stack-pointer register and its aliases as reserved. + Reserved.set(X86::RSP); + Reserved.set(X86::ESP); + Reserved.set(X86::SP); + Reserved.set(X86::SPL); + + // Set the instruction pointer register and its aliases as reserved. + Reserved.set(X86::RIP); + Reserved.set(X86::EIP); + Reserved.set(X86::IP); + + // Set the frame-pointer register and its aliases as reserved if needed. + if (hasFP(MF)) { + Reserved.set(X86::RBP); + Reserved.set(X86::EBP); + Reserved.set(X86::BP); + Reserved.set(X86::BPL); + } + + // Mark the x87 stack registers as reserved, since they don't behave normally + // with respect to liveness. We don't fully model the effects of x87 stack + // pushes and pops after stackification. + Reserved.set(X86::ST0); + Reserved.set(X86::ST1); + Reserved.set(X86::ST2); + Reserved.set(X86::ST3); + Reserved.set(X86::ST4); + Reserved.set(X86::ST5); + Reserved.set(X86::ST6); + Reserved.set(X86::ST7); + return Reserved; +} + +//===----------------------------------------------------------------------===// +// Stack Frame Processing methods +//===----------------------------------------------------------------------===// + +static unsigned calculateMaxStackAlignment(const MachineFrameInfo *FFI) { + unsigned MaxAlign = 0; + + for (int i = FFI->getObjectIndexBegin(), + e = FFI->getObjectIndexEnd(); i != e; ++i) { + if (FFI->isDeadObjectIndex(i)) + continue; + + unsigned Align = FFI->getObjectAlignment(i); + MaxAlign = std::max(MaxAlign, Align); + } + + return MaxAlign; +} + +/// hasFP - Return true if the specified function should have a dedicated frame +/// pointer register. This is true if the function has variable sized allocas +/// or if frame pointer elimination is disabled. +bool X86RegisterInfo::hasFP(const MachineFunction &MF) const { + const MachineFrameInfo *MFI = MF.getFrameInfo(); + const MachineModuleInfo *MMI = MFI->getMachineModuleInfo(); + + return (NoFramePointerElim || + needsStackRealignment(MF) || + MFI->hasVarSizedObjects() || + MFI->isFrameAddressTaken() || + MF.getInfo()->getForceFramePointer() || + (MMI && MMI->callsUnwindInit())); +} + +bool X86RegisterInfo::needsStackRealignment(const MachineFunction &MF) const { + const MachineFrameInfo *MFI = MF.getFrameInfo(); + bool requiresRealignment = + RealignStack && (MFI->getMaxAlignment() > StackAlign); + + // FIXME: Currently we don't support stack realignment for functions with + // variable-sized allocas. + // FIXME: Temporary disable the error - it seems to be too conservative. + if (0 && requiresRealignment && MFI->hasVarSizedObjects()) + llvm_report_error( + "Stack realignment in presense of dynamic allocas is not supported"); + + return (requiresRealignment && !MFI->hasVarSizedObjects()); +} + +bool X86RegisterInfo::hasReservedCallFrame(MachineFunction &MF) const { + return !MF.getFrameInfo()->hasVarSizedObjects(); +} + +bool X86RegisterInfo::hasReservedSpillSlot(MachineFunction &MF, unsigned Reg, + int &FrameIdx) const { + if (Reg == FramePtr && hasFP(MF)) { + FrameIdx = MF.getFrameInfo()->getObjectIndexBegin(); + return true; + } + return false; +} + +int +X86RegisterInfo::getFrameIndexOffset(MachineFunction &MF, int FI) const { + const TargetFrameInfo &TFI = *MF.getTarget().getFrameInfo(); + MachineFrameInfo *MFI = MF.getFrameInfo(); + int Offset = MFI->getObjectOffset(FI) - TFI.getOffsetOfLocalArea(); + uint64_t StackSize = MFI->getStackSize(); + + if (needsStackRealignment(MF)) { + if (FI < 0) { + // Skip the saved EBP. + Offset += SlotSize; + } else { + unsigned Align = MFI->getObjectAlignment(FI); + assert( (-(Offset + StackSize)) % Align == 0); + Align = 0; + return Offset + StackSize; + } + // FIXME: Support tail calls + } else { + if (!hasFP(MF)) + return Offset + StackSize; + + // Skip the saved EBP. + Offset += SlotSize; + + // Skip the RETADDR move area + X86MachineFunctionInfo *X86FI = MF.getInfo(); + int TailCallReturnAddrDelta = X86FI->getTCReturnAddrDelta(); + if (TailCallReturnAddrDelta < 0) + Offset -= TailCallReturnAddrDelta; + } + + return Offset; +} + +void X86RegisterInfo:: +eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, + MachineBasicBlock::iterator I) const { + if (!hasReservedCallFrame(MF)) { + // If the stack pointer can be changed after prologue, turn the + // adjcallstackup instruction into a 'sub ESP, ' and the + // adjcallstackdown instruction into 'add ESP, ' + // TODO: consider using push / pop instead of sub + store / add + MachineInstr *Old = I; + uint64_t Amount = Old->getOperand(0).getImm(); + if (Amount != 0) { + // We need to keep the stack aligned properly. To do this, we round the + // amount of space needed for the outgoing arguments up to the next + // alignment boundary. + Amount = (Amount + StackAlign - 1) / StackAlign * StackAlign; + + MachineInstr *New = 0; + if (Old->getOpcode() == getCallFrameSetupOpcode()) { + New = BuildMI(MF, Old->getDebugLoc(), + TII.get(Is64Bit ? X86::SUB64ri32 : X86::SUB32ri), + StackPtr) + .addReg(StackPtr) + .addImm(Amount); + } else { + assert(Old->getOpcode() == getCallFrameDestroyOpcode()); + + // Factor out the amount the callee already popped. + uint64_t CalleeAmt = Old->getOperand(1).getImm(); + Amount -= CalleeAmt; + + if (Amount) { + unsigned Opc = (Amount < 128) ? + (Is64Bit ? X86::ADD64ri8 : X86::ADD32ri8) : + (Is64Bit ? X86::ADD64ri32 : X86::ADD32ri); + New = BuildMI(MF, Old->getDebugLoc(), TII.get(Opc), StackPtr) + .addReg(StackPtr) + .addImm(Amount); + } + } + + if (New) { + // The EFLAGS implicit def is dead. + New->getOperand(3).setIsDead(); + + // Replace the pseudo instruction with a new instruction. + MBB.insert(I, New); + } + } + } else if (I->getOpcode() == getCallFrameDestroyOpcode()) { + // If we are performing frame pointer elimination and if the callee pops + // something off the stack pointer, add it back. We do this until we have + // more advanced stack pointer tracking ability. + if (uint64_t CalleeAmt = I->getOperand(1).getImm()) { + unsigned Opc = (CalleeAmt < 128) ? + (Is64Bit ? X86::SUB64ri8 : X86::SUB32ri8) : + (Is64Bit ? X86::SUB64ri32 : X86::SUB32ri); + MachineInstr *Old = I; + MachineInstr *New = + BuildMI(MF, Old->getDebugLoc(), TII.get(Opc), + StackPtr) + .addReg(StackPtr) + .addImm(CalleeAmt); + + // The EFLAGS implicit def is dead. + New->getOperand(3).setIsDead(); + MBB.insert(I, New); + } + } + + MBB.erase(I); +} + +unsigned +X86RegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, + int SPAdj, int *Value, + RegScavenger *RS) const{ + assert(SPAdj == 0 && "Unexpected"); + + unsigned i = 0; + MachineInstr &MI = *II; + MachineFunction &MF = *MI.getParent()->getParent(); + + while (!MI.getOperand(i).isFI()) { + ++i; + assert(i < MI.getNumOperands() && "Instr doesn't have FrameIndex operand!"); + } + + int FrameIndex = MI.getOperand(i).getIndex(); + unsigned BasePtr; + + if (needsStackRealignment(MF)) + BasePtr = (FrameIndex < 0 ? FramePtr : StackPtr); + else + BasePtr = (hasFP(MF) ? FramePtr : StackPtr); + + // This must be part of a four operand memory reference. Replace the + // FrameIndex with base register with EBP. Add an offset to the offset. + MI.getOperand(i).ChangeToRegister(BasePtr, false); + + // Now add the frame object offset to the offset from EBP. + if (MI.getOperand(i+3).isImm()) { + // Offset is a 32-bit integer. + int Offset = getFrameIndexOffset(MF, FrameIndex) + + (int)(MI.getOperand(i + 3).getImm()); + + MI.getOperand(i + 3).ChangeToImmediate(Offset); + } else { + // Offset is symbolic. This is extremely rare. + uint64_t Offset = getFrameIndexOffset(MF, FrameIndex) + + (uint64_t)MI.getOperand(i+3).getOffset(); + MI.getOperand(i+3).setOffset(Offset); + } + return 0; +} + +void +X86RegisterInfo::processFunctionBeforeCalleeSavedScan(MachineFunction &MF, + RegScavenger *RS) const { + MachineFrameInfo *MFI = MF.getFrameInfo(); + + // Calculate and set max stack object alignment early, so we can decide + // whether we will need stack realignment (and thus FP). + unsigned MaxAlign = std::max(MFI->getMaxAlignment(), + calculateMaxStackAlignment(MFI)); + + MFI->setMaxAlignment(MaxAlign); + + X86MachineFunctionInfo *X86FI = MF.getInfo(); + int32_t TailCallReturnAddrDelta = X86FI->getTCReturnAddrDelta(); + + if (TailCallReturnAddrDelta < 0) { + // create RETURNADDR area + // arg + // arg + // RETADDR + // { ... + // RETADDR area + // ... + // } + // [EBP] + MFI->CreateFixedObject(-TailCallReturnAddrDelta, + (-1U*SlotSize)+TailCallReturnAddrDelta, + true, false); + } + + if (hasFP(MF)) { + assert((TailCallReturnAddrDelta <= 0) && + "The Delta should always be zero or negative"); + const TargetFrameInfo &TFI = *MF.getTarget().getFrameInfo(); + + // Create a frame entry for the EBP register that must be saved. + int FrameIdx = MFI->CreateFixedObject(SlotSize, + -(int)SlotSize + + TFI.getOffsetOfLocalArea() + + TailCallReturnAddrDelta, + true, false); + assert(FrameIdx == MFI->getObjectIndexBegin() && + "Slot for EBP register must be last in order to be found!"); + FrameIdx = 0; + } +} + +/// emitSPUpdate - Emit a series of instructions to increment / decrement the +/// stack pointer by a constant value. +static +void emitSPUpdate(MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI, + unsigned StackPtr, int64_t NumBytes, bool Is64Bit, + const TargetInstrInfo &TII) { + bool isSub = NumBytes < 0; + uint64_t Offset = isSub ? -NumBytes : NumBytes; + unsigned Opc = isSub + ? ((Offset < 128) ? + (Is64Bit ? X86::SUB64ri8 : X86::SUB32ri8) : + (Is64Bit ? X86::SUB64ri32 : X86::SUB32ri)) + : ((Offset < 128) ? + (Is64Bit ? X86::ADD64ri8 : X86::ADD32ri8) : + (Is64Bit ? X86::ADD64ri32 : X86::ADD32ri)); + uint64_t Chunk = (1LL << 31) - 1; + DebugLoc DL = (MBBI != MBB.end() ? MBBI->getDebugLoc() : + DebugLoc::getUnknownLoc()); + + while (Offset) { + uint64_t ThisVal = (Offset > Chunk) ? Chunk : Offset; + MachineInstr *MI = + BuildMI(MBB, MBBI, DL, TII.get(Opc), StackPtr) + .addReg(StackPtr) + .addImm(ThisVal); + MI->getOperand(3).setIsDead(); // The EFLAGS implicit def is dead. + Offset -= ThisVal; + } +} + +/// mergeSPUpdatesUp - Merge two stack-manipulating instructions upper iterator. +static +void mergeSPUpdatesUp(MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI, + unsigned StackPtr, uint64_t *NumBytes = NULL) { + if (MBBI == MBB.begin()) return; + + MachineBasicBlock::iterator PI = prior(MBBI); + unsigned Opc = PI->getOpcode(); + if ((Opc == X86::ADD64ri32 || Opc == X86::ADD64ri8 || + Opc == X86::ADD32ri || Opc == X86::ADD32ri8) && + PI->getOperand(0).getReg() == StackPtr) { + if (NumBytes) + *NumBytes += PI->getOperand(2).getImm(); + MBB.erase(PI); + } else if ((Opc == X86::SUB64ri32 || Opc == X86::SUB64ri8 || + Opc == X86::SUB32ri || Opc == X86::SUB32ri8) && + PI->getOperand(0).getReg() == StackPtr) { + if (NumBytes) + *NumBytes -= PI->getOperand(2).getImm(); + MBB.erase(PI); + } +} + +/// mergeSPUpdatesUp - Merge two stack-manipulating instructions lower iterator. +static +void mergeSPUpdatesDown(MachineBasicBlock &MBB, + MachineBasicBlock::iterator &MBBI, + unsigned StackPtr, uint64_t *NumBytes = NULL) { + // FIXME: THIS ISN'T RUN!!! + return; + + if (MBBI == MBB.end()) return; + + MachineBasicBlock::iterator NI = next(MBBI); + if (NI == MBB.end()) return; + + unsigned Opc = NI->getOpcode(); + if ((Opc == X86::ADD64ri32 || Opc == X86::ADD64ri8 || + Opc == X86::ADD32ri || Opc == X86::ADD32ri8) && + NI->getOperand(0).getReg() == StackPtr) { + if (NumBytes) + *NumBytes -= NI->getOperand(2).getImm(); + MBB.erase(NI); + MBBI = NI; + } else if ((Opc == X86::SUB64ri32 || Opc == X86::SUB64ri8 || + Opc == X86::SUB32ri || Opc == X86::SUB32ri8) && + NI->getOperand(0).getReg() == StackPtr) { + if (NumBytes) + *NumBytes += NI->getOperand(2).getImm(); + MBB.erase(NI); + MBBI = NI; + } +} + +/// mergeSPUpdates - Checks the instruction before/after the passed +/// instruction. If it is an ADD/SUB instruction it is deleted argument and the +/// stack adjustment is returned as a positive value for ADD and a negative for +/// SUB. +static int mergeSPUpdates(MachineBasicBlock &MBB, + MachineBasicBlock::iterator &MBBI, + unsigned StackPtr, + bool doMergeWithPrevious) { + if ((doMergeWithPrevious && MBBI == MBB.begin()) || + (!doMergeWithPrevious && MBBI == MBB.end())) + return 0; + + MachineBasicBlock::iterator PI = doMergeWithPrevious ? prior(MBBI) : MBBI; + MachineBasicBlock::iterator NI = doMergeWithPrevious ? 0 : next(MBBI); + unsigned Opc = PI->getOpcode(); + int Offset = 0; + + if ((Opc == X86::ADD64ri32 || Opc == X86::ADD64ri8 || + Opc == X86::ADD32ri || Opc == X86::ADD32ri8) && + PI->getOperand(0).getReg() == StackPtr){ + Offset += PI->getOperand(2).getImm(); + MBB.erase(PI); + if (!doMergeWithPrevious) MBBI = NI; + } else if ((Opc == X86::SUB64ri32 || Opc == X86::SUB64ri8 || + Opc == X86::SUB32ri || Opc == X86::SUB32ri8) && + PI->getOperand(0).getReg() == StackPtr) { + Offset -= PI->getOperand(2).getImm(); + MBB.erase(PI); + if (!doMergeWithPrevious) MBBI = NI; + } + + return Offset; +} + +void X86RegisterInfo::emitCalleeSavedFrameMoves(MachineFunction &MF, + unsigned LabelId, + unsigned FramePtr) const { + MachineFrameInfo *MFI = MF.getFrameInfo(); + MachineModuleInfo *MMI = MFI->getMachineModuleInfo(); + if (!MMI) return; + + // Add callee saved registers to move list. + const std::vector &CSI = MFI->getCalleeSavedInfo(); + if (CSI.empty()) return; + + std::vector &Moves = MMI->getFrameMoves(); + const TargetData *TD = MF.getTarget().getTargetData(); + bool HasFP = hasFP(MF); + + // Calculate amount of bytes used for return address storing. + int stackGrowth = + (MF.getTarget().getFrameInfo()->getStackGrowthDirection() == + TargetFrameInfo::StackGrowsUp ? + TD->getPointerSize() : -TD->getPointerSize()); + + // FIXME: This is dirty hack. The code itself is pretty mess right now. + // It should be rewritten from scratch and generalized sometimes. + + // Determine maximum offset (minumum due to stack growth). + int64_t MaxOffset = 0; + for (std::vector::const_iterator + I = CSI.begin(), E = CSI.end(); I != E; ++I) + MaxOffset = std::min(MaxOffset, + MFI->getObjectOffset(I->getFrameIdx())); + + // Calculate offsets. + int64_t saveAreaOffset = (HasFP ? 3 : 2) * stackGrowth; + for (std::vector::const_iterator + I = CSI.begin(), E = CSI.end(); I != E; ++I) { + int64_t Offset = MFI->getObjectOffset(I->getFrameIdx()); + unsigned Reg = I->getReg(); + Offset = MaxOffset - Offset + saveAreaOffset; + + // Don't output a new machine move if we're re-saving the frame + // pointer. This happens when the PrologEpilogInserter has inserted an extra + // "PUSH" of the frame pointer -- the "emitPrologue" method automatically + // generates one when frame pointers are used. If we generate a "machine + // move" for this extra "PUSH", the linker will lose track of the fact that + // the frame pointer should have the value of the first "PUSH" when it's + // trying to unwind. + // + // FIXME: This looks inelegant. It's possibly correct, but it's covering up + // another bug. I.e., one where we generate a prolog like this: + // + // pushl %ebp + // movl %esp, %ebp + // pushl %ebp + // pushl %esi + // ... + // + // The immediate re-push of EBP is unnecessary. At the least, it's an + // optimization bug. EBP can be used as a scratch register in certain + // cases, but probably not when we have a frame pointer. + if (HasFP && FramePtr == Reg) + continue; + + MachineLocation CSDst(MachineLocation::VirtualFP, Offset); + MachineLocation CSSrc(Reg); + Moves.push_back(MachineMove(LabelId, CSDst, CSSrc)); + } +} + +/// emitPrologue - Push callee-saved registers onto the stack, which +/// automatically adjust the stack pointer. Adjust the stack pointer to allocate +/// space for local variables. Also emit labels used by the exception handler to +/// generate the exception handling frames. +void X86RegisterInfo::emitPrologue(MachineFunction &MF) const { + MachineBasicBlock &MBB = MF.front(); // Prologue goes in entry BB. + MachineBasicBlock::iterator MBBI = MBB.begin(); + MachineFrameInfo *MFI = MF.getFrameInfo(); + const Function *Fn = MF.getFunction(); + const X86Subtarget *Subtarget = &MF.getTarget().getSubtarget(); + MachineModuleInfo *MMI = MFI->getMachineModuleInfo(); + X86MachineFunctionInfo *X86FI = MF.getInfo(); + bool needsFrameMoves = (MMI && MMI->hasDebugInfo()) || + !Fn->doesNotThrow() || UnwindTablesMandatory; + uint64_t MaxAlign = MFI->getMaxAlignment(); // Desired stack alignment. + uint64_t StackSize = MFI->getStackSize(); // Number of bytes to allocate. + bool HasFP = hasFP(MF); + DebugLoc DL; + + // Add RETADDR move area to callee saved frame size. + int TailCallReturnAddrDelta = X86FI->getTCReturnAddrDelta(); + if (TailCallReturnAddrDelta < 0) + X86FI->setCalleeSavedFrameSize( + X86FI->getCalleeSavedFrameSize() - TailCallReturnAddrDelta); + + // If this is x86-64 and the Red Zone is not disabled, if we are a leaf + // function, and use up to 128 bytes of stack space, don't have a frame + // pointer, calls, or dynamic alloca then we do not need to adjust the + // stack pointer (we fit in the Red Zone). + if (Is64Bit && !Fn->hasFnAttr(Attribute::NoRedZone) && + !needsStackRealignment(MF) && + !MFI->hasVarSizedObjects() && // No dynamic alloca. + !MFI->hasCalls() && // No calls. + !Subtarget->isTargetWin64()) { // Win64 has no Red Zone + uint64_t MinSize = X86FI->getCalleeSavedFrameSize(); + if (HasFP) MinSize += SlotSize; + StackSize = std::max(MinSize, StackSize > 128 ? StackSize - 128 : 0); + MFI->setStackSize(StackSize); + } else if (Subtarget->isTargetWin64()) { + // We need to always allocate 32 bytes as register spill area. + // FIXME: We might reuse these 32 bytes for leaf functions. + StackSize += 32; + MFI->setStackSize(StackSize); + } + + // Insert stack pointer adjustment for later moving of return addr. Only + // applies to tail call optimized functions where the callee argument stack + // size is bigger than the callers. + if (TailCallReturnAddrDelta < 0) { + MachineInstr *MI = + BuildMI(MBB, MBBI, DL, TII.get(Is64Bit? X86::SUB64ri32 : X86::SUB32ri), + StackPtr) + .addReg(StackPtr) + .addImm(-TailCallReturnAddrDelta); + MI->getOperand(3).setIsDead(); // The EFLAGS implicit def is dead. + } + + // Mapping for machine moves: + // + // DST: VirtualFP AND + // SRC: VirtualFP => DW_CFA_def_cfa_offset + // ELSE => DW_CFA_def_cfa + // + // SRC: VirtualFP AND + // DST: Register => DW_CFA_def_cfa_register + // + // ELSE + // OFFSET < 0 => DW_CFA_offset_extended_sf + // REG < 64 => DW_CFA_offset + Reg + // ELSE => DW_CFA_offset_extended + + std::vector &Moves = MMI->getFrameMoves(); + const TargetData *TD = MF.getTarget().getTargetData(); + uint64_t NumBytes = 0; + int stackGrowth = + (MF.getTarget().getFrameInfo()->getStackGrowthDirection() == + TargetFrameInfo::StackGrowsUp ? + TD->getPointerSize() : -TD->getPointerSize()); + + if (HasFP) { + // Calculate required stack adjustment. + uint64_t FrameSize = StackSize - SlotSize; + if (needsStackRealignment(MF)) + FrameSize = (FrameSize + MaxAlign - 1) / MaxAlign * MaxAlign; + + NumBytes = FrameSize - X86FI->getCalleeSavedFrameSize(); + + // Get the offset of the stack slot for the EBP register, which is + // guaranteed to be the last slot by processFunctionBeforeFrameFinalized. + // Update the frame offset adjustment. + MFI->setOffsetAdjustment(-NumBytes); + + // Save EBP/RBP into the appropriate stack slot. + BuildMI(MBB, MBBI, DL, TII.get(Is64Bit ? X86::PUSH64r : X86::PUSH32r)) + .addReg(FramePtr, RegState::Kill); + + if (needsFrameMoves) { + // Mark the place where EBP/RBP was saved. + unsigned FrameLabelId = MMI->NextLabelID(); + BuildMI(MBB, MBBI, DL, TII.get(X86::DBG_LABEL)).addImm(FrameLabelId); + + // Define the current CFA rule to use the provided offset. + if (StackSize) { + MachineLocation SPDst(MachineLocation::VirtualFP); + MachineLocation SPSrc(MachineLocation::VirtualFP, 2 * stackGrowth); + Moves.push_back(MachineMove(FrameLabelId, SPDst, SPSrc)); + } else { + // FIXME: Verify & implement for FP + MachineLocation SPDst(StackPtr); + MachineLocation SPSrc(StackPtr, stackGrowth); + Moves.push_back(MachineMove(FrameLabelId, SPDst, SPSrc)); + } + + // Change the rule for the FramePtr to be an "offset" rule. + MachineLocation FPDst(MachineLocation::VirtualFP, + 2 * stackGrowth); + MachineLocation FPSrc(FramePtr); + Moves.push_back(MachineMove(FrameLabelId, FPDst, FPSrc)); + } + + // Update EBP with the new base value... + BuildMI(MBB, MBBI, DL, + TII.get(Is64Bit ? X86::MOV64rr : X86::MOV32rr), FramePtr) + .addReg(StackPtr); + + if (needsFrameMoves) { + // Mark effective beginning of when frame pointer becomes valid. + unsigned FrameLabelId = MMI->NextLabelID(); + BuildMI(MBB, MBBI, DL, TII.get(X86::DBG_LABEL)).addImm(FrameLabelId); + + // Define the current CFA to use the EBP/RBP register. + MachineLocation FPDst(FramePtr); + MachineLocation FPSrc(MachineLocation::VirtualFP); + Moves.push_back(MachineMove(FrameLabelId, FPDst, FPSrc)); + } + + // Mark the FramePtr as live-in in every block except the entry. + for (MachineFunction::iterator I = next(MF.begin()), E = MF.end(); + I != E; ++I) + I->addLiveIn(FramePtr); + + // Realign stack + if (needsStackRealignment(MF)) { + MachineInstr *MI = + BuildMI(MBB, MBBI, DL, + TII.get(Is64Bit ? X86::AND64ri32 : X86::AND32ri), + StackPtr).addReg(StackPtr).addImm(-MaxAlign); + + // The EFLAGS implicit def is dead. + MI->getOperand(3).setIsDead(); + } + } else { + NumBytes = StackSize - X86FI->getCalleeSavedFrameSize(); + } + + // Skip the callee-saved push instructions. + bool PushedRegs = false; + int StackOffset = 2 * stackGrowth; + + while (MBBI != MBB.end() && + (MBBI->getOpcode() == X86::PUSH32r || + MBBI->getOpcode() == X86::PUSH64r)) { + PushedRegs = true; + ++MBBI; + + if (!HasFP && needsFrameMoves) { + // Mark callee-saved push instruction. + unsigned LabelId = MMI->NextLabelID(); + BuildMI(MBB, MBBI, DL, TII.get(X86::DBG_LABEL)).addImm(LabelId); + + // Define the current CFA rule to use the provided offset. + unsigned Ptr = StackSize ? + MachineLocation::VirtualFP : StackPtr; + MachineLocation SPDst(Ptr); + MachineLocation SPSrc(Ptr, StackOffset); + Moves.push_back(MachineMove(LabelId, SPDst, SPSrc)); + StackOffset += stackGrowth; + } + } + + if (MBBI != MBB.end()) + DL = MBBI->getDebugLoc(); + + // Adjust stack pointer: ESP -= numbytes. + if (NumBytes >= 4096 && Subtarget->isTargetCygMing()) { + // Check, whether EAX is livein for this function. + bool isEAXAlive = false; + for (MachineRegisterInfo::livein_iterator + II = MF.getRegInfo().livein_begin(), + EE = MF.getRegInfo().livein_end(); (II != EE) && !isEAXAlive; ++II) { + unsigned Reg = II->first; + isEAXAlive = (Reg == X86::EAX || Reg == X86::AX || + Reg == X86::AH || Reg == X86::AL); + } + + // Function prologue calls _alloca to probe the stack when allocating more + // than 4k bytes in one go. Touching the stack at 4K increments is necessary + // to ensure that the guard pages used by the OS virtual memory manager are + // allocated in correct sequence. + if (!isEAXAlive) { + BuildMI(MBB, MBBI, DL, TII.get(X86::MOV32ri), X86::EAX) + .addImm(NumBytes); + BuildMI(MBB, MBBI, DL, TII.get(X86::CALLpcrel32)) + .addExternalSymbol("_alloca"); + } else { + // Save EAX + BuildMI(MBB, MBBI, DL, TII.get(X86::PUSH32r)) + .addReg(X86::EAX, RegState::Kill); + + // Allocate NumBytes-4 bytes on stack. We'll also use 4 already + // allocated bytes for EAX. + BuildMI(MBB, MBBI, DL, TII.get(X86::MOV32ri), X86::EAX) + .addImm(NumBytes - 4); + BuildMI(MBB, MBBI, DL, TII.get(X86::CALLpcrel32)) + .addExternalSymbol("_alloca"); + + // Restore EAX + MachineInstr *MI = addRegOffset(BuildMI(MF, DL, TII.get(X86::MOV32rm), + X86::EAX), + StackPtr, false, NumBytes - 4); + MBB.insert(MBBI, MI); + } + } else if (NumBytes) { + // If there is an SUB32ri of ESP immediately before this instruction, merge + // the two. This can be the case when tail call elimination is enabled and + // the callee has more arguments then the caller. + NumBytes -= mergeSPUpdates(MBB, MBBI, StackPtr, true); + + // If there is an ADD32ri or SUB32ri of ESP immediately after this + // instruction, merge the two instructions. + mergeSPUpdatesDown(MBB, MBBI, StackPtr, &NumBytes); + + if (NumBytes) + emitSPUpdate(MBB, MBBI, StackPtr, -(int64_t)NumBytes, Is64Bit, TII); + } + + if ((NumBytes || PushedRegs) && needsFrameMoves) { + // Mark end of stack pointer adjustment. + unsigned LabelId = MMI->NextLabelID(); + BuildMI(MBB, MBBI, DL, TII.get(X86::DBG_LABEL)).addImm(LabelId); + + if (!HasFP && NumBytes) { + // Define the current CFA rule to use the provided offset. + if (StackSize) { + MachineLocation SPDst(MachineLocation::VirtualFP); + MachineLocation SPSrc(MachineLocation::VirtualFP, + -StackSize + stackGrowth); + Moves.push_back(MachineMove(LabelId, SPDst, SPSrc)); + } else { + // FIXME: Verify & implement for FP + MachineLocation SPDst(StackPtr); + MachineLocation SPSrc(StackPtr, stackGrowth); + Moves.push_back(MachineMove(LabelId, SPDst, SPSrc)); + } + } + + // Emit DWARF info specifying the offsets of the callee-saved registers. + if (PushedRegs) + emitCalleeSavedFrameMoves(MF, LabelId, HasFP ? FramePtr : StackPtr); + } +} + +void X86RegisterInfo::emitEpilogue(MachineFunction &MF, + MachineBasicBlock &MBB) const { + const MachineFrameInfo *MFI = MF.getFrameInfo(); + X86MachineFunctionInfo *X86FI = MF.getInfo(); + MachineBasicBlock::iterator MBBI = prior(MBB.end()); + unsigned RetOpcode = MBBI->getOpcode(); + DebugLoc DL = MBBI->getDebugLoc(); + + switch (RetOpcode) { + default: + llvm_unreachable("Can only insert epilog into returning blocks"); + case X86::RET: + case X86::RETI: + case X86::TCRETURNdi: + case X86::TCRETURNri: + case X86::TCRETURNri64: + case X86::TCRETURNdi64: + case X86::EH_RETURN: + case X86::EH_RETURN64: + case X86::TAILJMPd: + case X86::TAILJMPr: + case X86::TAILJMPm: + break; // These are ok + } + + // Get the number of bytes to allocate from the FrameInfo. + uint64_t StackSize = MFI->getStackSize(); + uint64_t MaxAlign = MFI->getMaxAlignment(); + unsigned CSSize = X86FI->getCalleeSavedFrameSize(); + uint64_t NumBytes = 0; + + if (hasFP(MF)) { + // Calculate required stack adjustment. + uint64_t FrameSize = StackSize - SlotSize; + if (needsStackRealignment(MF)) + FrameSize = (FrameSize + MaxAlign - 1)/MaxAlign*MaxAlign; + + NumBytes = FrameSize - CSSize; + + // Pop EBP. + BuildMI(MBB, MBBI, DL, + TII.get(Is64Bit ? X86::POP64r : X86::POP32r), FramePtr); + } else { + NumBytes = StackSize - CSSize; + } + + // Skip the callee-saved pop instructions. + MachineBasicBlock::iterator LastCSPop = MBBI; + while (MBBI != MBB.begin()) { + MachineBasicBlock::iterator PI = prior(MBBI); + unsigned Opc = PI->getOpcode(); + + if (Opc != X86::POP32r && Opc != X86::POP64r && + !PI->getDesc().isTerminator()) + break; + + --MBBI; + } + + DL = MBBI->getDebugLoc(); + + // If there is an ADD32ri or SUB32ri of ESP immediately before this + // instruction, merge the two instructions. + if (NumBytes || MFI->hasVarSizedObjects()) + mergeSPUpdatesUp(MBB, MBBI, StackPtr, &NumBytes); + + // If dynamic alloca is used, then reset esp to point to the last callee-saved + // slot before popping them off! Same applies for the case, when stack was + // realigned. + if (needsStackRealignment(MF)) { + // We cannot use LEA here, because stack pointer was realigned. We need to + // deallocate local frame back. + if (CSSize) { + emitSPUpdate(MBB, MBBI, StackPtr, NumBytes, Is64Bit, TII); + MBBI = prior(LastCSPop); + } + + BuildMI(MBB, MBBI, DL, + TII.get(Is64Bit ? X86::MOV64rr : X86::MOV32rr), + StackPtr).addReg(FramePtr); + } else if (MFI->hasVarSizedObjects()) { + if (CSSize) { + unsigned Opc = Is64Bit ? X86::LEA64r : X86::LEA32r; + MachineInstr *MI = + addLeaRegOffset(BuildMI(MF, DL, TII.get(Opc), StackPtr), + FramePtr, false, -CSSize); + MBB.insert(MBBI, MI); + } else { + BuildMI(MBB, MBBI, DL, + TII.get(Is64Bit ? X86::MOV64rr : X86::MOV32rr), StackPtr) + .addReg(FramePtr); + } + } else if (NumBytes) { + // Adjust stack pointer back: ESP += numbytes. + emitSPUpdate(MBB, MBBI, StackPtr, NumBytes, Is64Bit, TII); + } + + // We're returning from function via eh_return. + if (RetOpcode == X86::EH_RETURN || RetOpcode == X86::EH_RETURN64) { + MBBI = prior(MBB.end()); + MachineOperand &DestAddr = MBBI->getOperand(0); + assert(DestAddr.isReg() && "Offset should be in register!"); + BuildMI(MBB, MBBI, DL, + TII.get(Is64Bit ? X86::MOV64rr : X86::MOV32rr), + StackPtr).addReg(DestAddr.getReg()); + } else if (RetOpcode == X86::TCRETURNri || RetOpcode == X86::TCRETURNdi || + RetOpcode== X86::TCRETURNri64 || RetOpcode == X86::TCRETURNdi64) { + // Tail call return: adjust the stack pointer and jump to callee. + MBBI = prior(MBB.end()); + MachineOperand &JumpTarget = MBBI->getOperand(0); + MachineOperand &StackAdjust = MBBI->getOperand(1); + assert(StackAdjust.isImm() && "Expecting immediate value."); + + // Adjust stack pointer. + int StackAdj = StackAdjust.getImm(); + int MaxTCDelta = X86FI->getTCReturnAddrDelta(); + int Offset = 0; + assert(MaxTCDelta <= 0 && "MaxTCDelta should never be positive"); + + // Incoporate the retaddr area. + Offset = StackAdj-MaxTCDelta; + assert(Offset >= 0 && "Offset should never be negative"); + + if (Offset) { + // Check for possible merge with preceeding ADD instruction. + Offset += mergeSPUpdates(MBB, MBBI, StackPtr, true); + emitSPUpdate(MBB, MBBI, StackPtr, Offset, Is64Bit, TII); + } + + // Jump to label or value in register. + if (RetOpcode == X86::TCRETURNdi|| RetOpcode == X86::TCRETURNdi64) + BuildMI(MBB, MBBI, DL, TII.get(X86::TAILJMPd)). + addGlobalAddress(JumpTarget.getGlobal(), JumpTarget.getOffset()); + else if (RetOpcode== X86::TCRETURNri64) + BuildMI(MBB, MBBI, DL, TII.get(X86::TAILJMPr64), JumpTarget.getReg()); + else + BuildMI(MBB, MBBI, DL, TII.get(X86::TAILJMPr), JumpTarget.getReg()); + + // Delete the pseudo instruction TCRETURN. + MBB.erase(MBBI); + } else if ((RetOpcode == X86::RET || RetOpcode == X86::RETI) && + (X86FI->getTCReturnAddrDelta() < 0)) { + // Add the return addr area delta back since we are not tail calling. + int delta = -1*X86FI->getTCReturnAddrDelta(); + MBBI = prior(MBB.end()); + + // Check for possible merge with preceeding ADD instruction. + delta += mergeSPUpdates(MBB, MBBI, StackPtr, true); + emitSPUpdate(MBB, MBBI, StackPtr, delta, Is64Bit, TII); + } +} + +unsigned X86RegisterInfo::getRARegister() const { + return Is64Bit ? X86::RIP // Should have dwarf #16. + : X86::EIP; // Should have dwarf #8. +} + +unsigned X86RegisterInfo::getFrameRegister(const MachineFunction &MF) const { + return hasFP(MF) ? FramePtr : StackPtr; +} + +void +X86RegisterInfo::getInitialFrameState(std::vector &Moves) const { + // Calculate amount of bytes used for return address storing + int stackGrowth = (Is64Bit ? -8 : -4); + + // Initial state of the frame pointer is esp+4. + MachineLocation Dst(MachineLocation::VirtualFP); + MachineLocation Src(StackPtr, stackGrowth); + Moves.push_back(MachineMove(0, Dst, Src)); + + // Add return address to move list + MachineLocation CSDst(StackPtr, stackGrowth); + MachineLocation CSSrc(getRARegister()); + Moves.push_back(MachineMove(0, CSDst, CSSrc)); +} + +unsigned X86RegisterInfo::getEHExceptionRegister() const { + llvm_unreachable("What is the exception register"); + return 0; +} + +unsigned X86RegisterInfo::getEHHandlerRegister() const { + llvm_unreachable("What is the exception handler register"); + return 0; +} + +namespace llvm { +unsigned getX86SubSuperRegister(unsigned Reg, EVT VT, bool High) { + switch (VT.getSimpleVT().SimpleTy) { + default: return Reg; + case MVT::i8: + if (High) { + switch (Reg) { + default: return 0; + case X86::AH: case X86::AL: case X86::AX: case X86::EAX: case X86::RAX: + return X86::AH; + case X86::DH: case X86::DL: case X86::DX: case X86::EDX: case X86::RDX: + return X86::DH; + case X86::CH: case X86::CL: case X86::CX: case X86::ECX: case X86::RCX: + return X86::CH; + case X86::BH: case X86::BL: case X86::BX: case X86::EBX: case X86::RBX: + return X86::BH; + } + } else { + switch (Reg) { + default: return 0; + case X86::AH: case X86::AL: case X86::AX: case X86::EAX: case X86::RAX: + return X86::AL; + case X86::DH: case X86::DL: case X86::DX: case X86::EDX: case X86::RDX: + return X86::DL; + case X86::CH: case X86::CL: case X86::CX: case X86::ECX: case X86::RCX: + return X86::CL; + case X86::BH: case X86::BL: case X86::BX: case X86::EBX: case X86::RBX: + return X86::BL; + case X86::SIL: case X86::SI: case X86::ESI: case X86::RSI: + return X86::SIL; + case X86::DIL: case X86::DI: case X86::EDI: case X86::RDI: + return X86::DIL; + case X86::BPL: case X86::BP: case X86::EBP: case X86::RBP: + return X86::BPL; + case X86::SPL: case X86::SP: case X86::ESP: case X86::RSP: + return X86::SPL; + case X86::R8B: case X86::R8W: case X86::R8D: case X86::R8: + return X86::R8B; + case X86::R9B: case X86::R9W: case X86::R9D: case X86::R9: + return X86::R9B; + case X86::R10B: case X86::R10W: case X86::R10D: case X86::R10: + return X86::R10B; + case X86::R11B: case X86::R11W: case X86::R11D: case X86::R11: + return X86::R11B; + case X86::R12B: case X86::R12W: case X86::R12D: case X86::R12: + return X86::R12B; + case X86::R13B: case X86::R13W: case X86::R13D: case X86::R13: + return X86::R13B; + case X86::R14B: case X86::R14W: case X86::R14D: case X86::R14: + return X86::R14B; + case X86::R15B: case X86::R15W: case X86::R15D: case X86::R15: + return X86::R15B; + } + } + case MVT::i16: + switch (Reg) { + default: return Reg; + case X86::AH: case X86::AL: case X86::AX: case X86::EAX: case X86::RAX: + return X86::AX; + case X86::DH: case X86::DL: case X86::DX: case X86::EDX: case X86::RDX: + return X86::DX; + case X86::CH: case X86::CL: case X86::CX: case X86::ECX: case X86::RCX: + return X86::CX; + case X86::BH: case X86::BL: case X86::BX: case X86::EBX: case X86::RBX: + return X86::BX; + case X86::SIL: case X86::SI: case X86::ESI: case X86::RSI: + return X86::SI; + case X86::DIL: case X86::DI: case X86::EDI: case X86::RDI: + return X86::DI; + case X86::BPL: case X86::BP: case X86::EBP: case X86::RBP: + return X86::BP; + case X86::SPL: case X86::SP: case X86::ESP: case X86::RSP: + return X86::SP; + case X86::R8B: case X86::R8W: case X86::R8D: case X86::R8: + return X86::R8W; + case X86::R9B: case X86::R9W: case X86::R9D: case X86::R9: + return X86::R9W; + case X86::R10B: case X86::R10W: case X86::R10D: case X86::R10: + return X86::R10W; + case X86::R11B: case X86::R11W: case X86::R11D: case X86::R11: + return X86::R11W; + case X86::R12B: case X86::R12W: case X86::R12D: case X86::R12: + return X86::R12W; + case X86::R13B: case X86::R13W: case X86::R13D: case X86::R13: + return X86::R13W; + case X86::R14B: case X86::R14W: case X86::R14D: case X86::R14: + return X86::R14W; + case X86::R15B: case X86::R15W: case X86::R15D: case X86::R15: + return X86::R15W; + } + case MVT::i32: + switch (Reg) { + default: return Reg; + case X86::AH: case X86::AL: case X86::AX: case X86::EAX: case X86::RAX: + return X86::EAX; + case X86::DH: case X86::DL: case X86::DX: case X86::EDX: case X86::RDX: + return X86::EDX; + case X86::CH: case X86::CL: case X86::CX: case X86::ECX: case X86::RCX: + return X86::ECX; + case X86::BH: case X86::BL: case X86::BX: case X86::EBX: case X86::RBX: + return X86::EBX; + case X86::SIL: case X86::SI: case X86::ESI: case X86::RSI: + return X86::ESI; + case X86::DIL: case X86::DI: case X86::EDI: case X86::RDI: + return X86::EDI; + case X86::BPL: case X86::BP: case X86::EBP: case X86::RBP: + return X86::EBP; + case X86::SPL: case X86::SP: case X86::ESP: case X86::RSP: + return X86::ESP; + case X86::R8B: case X86::R8W: case X86::R8D: case X86::R8: + return X86::R8D; + case X86::R9B: case X86::R9W: case X86::R9D: case X86::R9: + return X86::R9D; + case X86::R10B: case X86::R10W: case X86::R10D: case X86::R10: + return X86::R10D; + case X86::R11B: case X86::R11W: case X86::R11D: case X86::R11: + return X86::R11D; + case X86::R12B: case X86::R12W: case X86::R12D: case X86::R12: + return X86::R12D; + case X86::R13B: case X86::R13W: case X86::R13D: case X86::R13: + return X86::R13D; + case X86::R14B: case X86::R14W: case X86::R14D: case X86::R14: + return X86::R14D; + case X86::R15B: case X86::R15W: case X86::R15D: case X86::R15: + return X86::R15D; + } + case MVT::i64: + switch (Reg) { + default: return Reg; + case X86::AH: case X86::AL: case X86::AX: case X86::EAX: case X86::RAX: + return X86::RAX; + case X86::DH: case X86::DL: case X86::DX: case X86::EDX: case X86::RDX: + return X86::RDX; + case X86::CH: case X86::CL: case X86::CX: case X86::ECX: case X86::RCX: + return X86::RCX; + case X86::BH: case X86::BL: case X86::BX: case X86::EBX: case X86::RBX: + return X86::RBX; + case X86::SIL: case X86::SI: case X86::ESI: case X86::RSI: + return X86::RSI; + case X86::DIL: case X86::DI: case X86::EDI: case X86::RDI: + return X86::RDI; + case X86::BPL: case X86::BP: case X86::EBP: case X86::RBP: + return X86::RBP; + case X86::SPL: case X86::SP: case X86::ESP: case X86::RSP: + return X86::RSP; + case X86::R8B: case X86::R8W: case X86::R8D: case X86::R8: + return X86::R8; + case X86::R9B: case X86::R9W: case X86::R9D: case X86::R9: + return X86::R9; + case X86::R10B: case X86::R10W: case X86::R10D: case X86::R10: + return X86::R10; + case X86::R11B: case X86::R11W: case X86::R11D: case X86::R11: + return X86::R11; + case X86::R12B: case X86::R12W: case X86::R12D: case X86::R12: + return X86::R12; + case X86::R13B: case X86::R13W: case X86::R13D: case X86::R13: + return X86::R13; + case X86::R14B: case X86::R14W: case X86::R14D: case X86::R14: + return X86::R14; + case X86::R15B: case X86::R15W: case X86::R15D: case X86::R15: + return X86::R15; + } + } + + return Reg; +} +} + +#include "X86GenRegisterInfo.inc" + +namespace { + struct MSAC : public MachineFunctionPass { + static char ID; + MSAC() : MachineFunctionPass(&ID) {} + + virtual bool runOnMachineFunction(MachineFunction &MF) { + MachineFrameInfo *FFI = MF.getFrameInfo(); + MachineRegisterInfo &RI = MF.getRegInfo(); + + // Calculate max stack alignment of all already allocated stack objects. + unsigned MaxAlign = calculateMaxStackAlignment(FFI); + + // Be over-conservative: scan over all vreg defs and find, whether vector + // registers are used. If yes - there is probability, that vector register + // will be spilled and thus stack needs to be aligned properly. + for (unsigned RegNum = TargetRegisterInfo::FirstVirtualRegister; + RegNum < RI.getLastVirtReg(); ++RegNum) + MaxAlign = std::max(MaxAlign, RI.getRegClass(RegNum)->getAlignment()); + + if (FFI->getMaxAlignment() == MaxAlign) + return false; + + FFI->setMaxAlignment(MaxAlign); + return true; + } + + virtual const char *getPassName() const { + return "X86 Maximal Stack Alignment Calculator"; + } + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesCFG(); + MachineFunctionPass::getAnalysisUsage(AU); + } + }; + + char MSAC::ID = 0; +} + +FunctionPass* +llvm::createX86MaxStackAlignmentCalculatorPass() { return new MSAC(); } diff --git a/libclamav/c++/llvm/lib/Target/X86/X86RegisterInfo.h b/libclamav/c++/llvm/lib/Target/X86/X86RegisterInfo.h new file mode 100644 index 000000000..f281a3cf8 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/X86/X86RegisterInfo.h @@ -0,0 +1,172 @@ +//===- X86RegisterInfo.h - X86 Register Information Impl --------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the X86 implementation of the TargetRegisterInfo class. +// +//===----------------------------------------------------------------------===// + +#ifndef X86REGISTERINFO_H +#define X86REGISTERINFO_H + +#include "llvm/Target/TargetRegisterInfo.h" +#include "X86GenRegisterInfo.h.inc" + +namespace llvm { + class Type; + class TargetInstrInfo; + class X86TargetMachine; + +/// N86 namespace - Native X86 register numbers +/// +namespace N86 { + enum { + EAX = 0, ECX = 1, EDX = 2, EBX = 3, ESP = 4, EBP = 5, ESI = 6, EDI = 7 + }; +} + +namespace X86 { + /// SubregIndex - The index of various sized subregister classes. Note that + /// these indices must be kept in sync with the class indices in the + /// X86RegisterInfo.td file. + enum SubregIndex { + SUBREG_8BIT = 1, SUBREG_8BIT_HI = 2, SUBREG_16BIT = 3, SUBREG_32BIT = 4 + }; +} + +/// DWARFFlavour - Flavour of dwarf regnumbers +/// +namespace DWARFFlavour { + enum { + X86_64 = 0, X86_32_DarwinEH = 1, X86_32_Generic = 2 + }; +} + +class X86RegisterInfo : public X86GenRegisterInfo { +public: + X86TargetMachine &TM; + const TargetInstrInfo &TII; + +private: + /// Is64Bit - Is the target 64-bits. + /// + bool Is64Bit; + + /// IsWin64 - Is the target on of win64 flavours + /// + bool IsWin64; + + /// SlotSize - Stack slot size in bytes. + /// + unsigned SlotSize; + + /// StackAlign - Default stack alignment. + /// + unsigned StackAlign; + + /// StackPtr - X86 physical register used as stack ptr. + /// + unsigned StackPtr; + + /// FramePtr - X86 physical register used as frame ptr. + /// + unsigned FramePtr; + +public: + X86RegisterInfo(X86TargetMachine &tm, const TargetInstrInfo &tii); + + /// getX86RegNum - Returns the native X86 register number for the given LLVM + /// register identifier. + static unsigned getX86RegNum(unsigned RegNo); + + unsigned getStackAlignment() const { return StackAlign; } + + /// getDwarfRegNum - allows modification of X86GenRegisterInfo::getDwarfRegNum + /// (created by TableGen) for target dependencies. + int getDwarfRegNum(unsigned RegNum, bool isEH) const; + + /// Code Generation virtual methods... + /// + + /// getMatchingSuperRegClass - Return a subclass of the specified register + /// class A so that each register in it has a sub-register of the + /// specified sub-register index which is in the specified register class B. + virtual const TargetRegisterClass * + getMatchingSuperRegClass(const TargetRegisterClass *A, + const TargetRegisterClass *B, unsigned Idx) const; + + /// getPointerRegClass - Returns a TargetRegisterClass used for pointer + /// values. + const TargetRegisterClass *getPointerRegClass(unsigned Kind = 0) const; + + /// getCrossCopyRegClass - Returns a legal register class to copy a register + /// in the specified class to or from. Returns NULL if it is possible to copy + /// between a two registers of the specified class. + const TargetRegisterClass * + getCrossCopyRegClass(const TargetRegisterClass *RC) const; + + /// getCalleeSavedRegs - Return a null-terminated list of all of the + /// callee-save registers on this target. + const unsigned *getCalleeSavedRegs(const MachineFunction* MF = 0) const; + + /// getCalleeSavedRegClasses - Return a null-terminated list of the preferred + /// register classes to spill each callee-saved register with. The order and + /// length of this list match the getCalleeSavedRegs() list. + const TargetRegisterClass* const* + getCalleeSavedRegClasses(const MachineFunction *MF = 0) const; + + /// getReservedRegs - Returns a bitset indexed by physical register number + /// indicating if a register is a special register that has particular uses and + /// should be considered unavailable at all times, e.g. SP, RA. This is used by + /// register scavenger to determine what registers are free. + BitVector getReservedRegs(const MachineFunction &MF) const; + + bool hasFP(const MachineFunction &MF) const; + + bool needsStackRealignment(const MachineFunction &MF) const; + + bool hasReservedCallFrame(MachineFunction &MF) const; + + bool hasReservedSpillSlot(MachineFunction &MF, unsigned Reg, + int &FrameIdx) const; + + void eliminateCallFramePseudoInstr(MachineFunction &MF, + MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI) const; + + unsigned eliminateFrameIndex(MachineBasicBlock::iterator MI, + int SPAdj, int *Value = NULL, + RegScavenger *RS = NULL) const; + + void processFunctionBeforeCalleeSavedScan(MachineFunction &MF, + RegScavenger *RS = NULL) const; + + void emitCalleeSavedFrameMoves(MachineFunction &MF, unsigned LabelId, + unsigned FramePtr) const; + void emitPrologue(MachineFunction &MF) const; + void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const; + + // Debug information queries. + unsigned getRARegister() const; + unsigned getFrameRegister(const MachineFunction &MF) const; + int getFrameIndexOffset(MachineFunction &MF, int FI) const; + void getInitialFrameState(std::vector &Moves) const; + + // Exception handling queries. + unsigned getEHExceptionRegister() const; + unsigned getEHHandlerRegister() const; +}; + +// getX86SubSuperRegister - X86 utility function. It returns the sub or super +// register of a specific X86 register. +// e.g. getX86SubSuperRegister(X86::EAX, EVT::i16) return X86:AX +unsigned getX86SubSuperRegister(unsigned, EVT, bool High=false); + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/lib/Target/X86/X86RegisterInfo.td b/libclamav/c++/llvm/lib/Target/X86/X86RegisterInfo.td new file mode 100644 index 000000000..7bf074d49 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/X86/X86RegisterInfo.td @@ -0,0 +1,781 @@ +//===- X86RegisterInfo.td - Describe the X86 Register File --*- tablegen -*-==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file describes the X86 Register file, defining the registers themselves, +// aliases between the registers, and the register classes built out of the +// registers. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// Register definitions... +// +let Namespace = "X86" in { + + // In the register alias definitions below, we define which registers alias + // which others. We only specify which registers the small registers alias, + // because the register file generator is smart enough to figure out that + // AL aliases AX if we tell it that AX aliased AL (for example). + + // Dwarf numbering is different for 32-bit and 64-bit, and there are + // variations by target as well. Currently the first entry is for X86-64, + // second - for EH on X86-32/Darwin and third is 'generic' one (X86-32/Linux + // and debug information on X86-32/Darwin) + + // 8-bit registers + // Low registers + def AL : Register<"al">, DwarfRegNum<[0, 0, 0]>; + def DL : Register<"dl">, DwarfRegNum<[1, 2, 2]>; + def CL : Register<"cl">, DwarfRegNum<[2, 1, 1]>; + def BL : Register<"bl">, DwarfRegNum<[3, 3, 3]>; + + // X86-64 only + def SIL : Register<"sil">, DwarfRegNum<[4, 6, 6]>; + def DIL : Register<"dil">, DwarfRegNum<[5, 7, 7]>; + def BPL : Register<"bpl">, DwarfRegNum<[6, 4, 5]>; + def SPL : Register<"spl">, DwarfRegNum<[7, 5, 4]>; + def R8B : Register<"r8b">, DwarfRegNum<[8, -2, -2]>; + def R9B : Register<"r9b">, DwarfRegNum<[9, -2, -2]>; + def R10B : Register<"r10b">, DwarfRegNum<[10, -2, -2]>; + def R11B : Register<"r11b">, DwarfRegNum<[11, -2, -2]>; + def R12B : Register<"r12b">, DwarfRegNum<[12, -2, -2]>; + def R13B : Register<"r13b">, DwarfRegNum<[13, -2, -2]>; + def R14B : Register<"r14b">, DwarfRegNum<[14, -2, -2]>; + def R15B : Register<"r15b">, DwarfRegNum<[15, -2, -2]>; + + // High registers. On x86-64, these cannot be used in any instruction + // with a REX prefix. + def AH : Register<"ah">, DwarfRegNum<[0, 0, 0]>; + def DH : Register<"dh">, DwarfRegNum<[1, 2, 2]>; + def CH : Register<"ch">, DwarfRegNum<[2, 1, 1]>; + def BH : Register<"bh">, DwarfRegNum<[3, 3, 3]>; + + // 16-bit registers + def AX : RegisterWithSubRegs<"ax", [AL,AH]>, DwarfRegNum<[0, 0, 0]>; + def DX : RegisterWithSubRegs<"dx", [DL,DH]>, DwarfRegNum<[1, 2, 2]>; + def CX : RegisterWithSubRegs<"cx", [CL,CH]>, DwarfRegNum<[2, 1, 1]>; + def BX : RegisterWithSubRegs<"bx", [BL,BH]>, DwarfRegNum<[3, 3, 3]>; + def SI : RegisterWithSubRegs<"si", [SIL]>, DwarfRegNum<[4, 6, 6]>; + def DI : RegisterWithSubRegs<"di", [DIL]>, DwarfRegNum<[5, 7, 7]>; + def BP : RegisterWithSubRegs<"bp", [BPL]>, DwarfRegNum<[6, 4, 5]>; + def SP : RegisterWithSubRegs<"sp", [SPL]>, DwarfRegNum<[7, 5, 4]>; + def IP : Register<"ip">, DwarfRegNum<[16]>; + + // X86-64 only + def R8W : RegisterWithSubRegs<"r8w", [R8B]>, DwarfRegNum<[8, -2, -2]>; + def R9W : RegisterWithSubRegs<"r9w", [R9B]>, DwarfRegNum<[9, -2, -2]>; + def R10W : RegisterWithSubRegs<"r10w", [R10B]>, DwarfRegNum<[10, -2, -2]>; + def R11W : RegisterWithSubRegs<"r11w", [R11B]>, DwarfRegNum<[11, -2, -2]>; + def R12W : RegisterWithSubRegs<"r12w", [R12B]>, DwarfRegNum<[12, -2, -2]>; + def R13W : RegisterWithSubRegs<"r13w", [R13B]>, DwarfRegNum<[13, -2, -2]>; + def R14W : RegisterWithSubRegs<"r14w", [R14B]>, DwarfRegNum<[14, -2, -2]>; + def R15W : RegisterWithSubRegs<"r15w", [R15B]>, DwarfRegNum<[15, -2, -2]>; + + // 32-bit registers + def EAX : RegisterWithSubRegs<"eax", [AX]>, DwarfRegNum<[0, 0, 0]>; + def EDX : RegisterWithSubRegs<"edx", [DX]>, DwarfRegNum<[1, 2, 2]>; + def ECX : RegisterWithSubRegs<"ecx", [CX]>, DwarfRegNum<[2, 1, 1]>; + def EBX : RegisterWithSubRegs<"ebx", [BX]>, DwarfRegNum<[3, 3, 3]>; + def ESI : RegisterWithSubRegs<"esi", [SI]>, DwarfRegNum<[4, 6, 6]>; + def EDI : RegisterWithSubRegs<"edi", [DI]>, DwarfRegNum<[5, 7, 7]>; + def EBP : RegisterWithSubRegs<"ebp", [BP]>, DwarfRegNum<[6, 4, 5]>; + def ESP : RegisterWithSubRegs<"esp", [SP]>, DwarfRegNum<[7, 5, 4]>; + def EIP : RegisterWithSubRegs<"eip", [IP]>, DwarfRegNum<[16, 8, 8]>; + + // X86-64 only + def R8D : RegisterWithSubRegs<"r8d", [R8W]>, DwarfRegNum<[8, -2, -2]>; + def R9D : RegisterWithSubRegs<"r9d", [R9W]>, DwarfRegNum<[9, -2, -2]>; + def R10D : RegisterWithSubRegs<"r10d", [R10W]>, DwarfRegNum<[10, -2, -2]>; + def R11D : RegisterWithSubRegs<"r11d", [R11W]>, DwarfRegNum<[11, -2, -2]>; + def R12D : RegisterWithSubRegs<"r12d", [R12W]>, DwarfRegNum<[12, -2, -2]>; + def R13D : RegisterWithSubRegs<"r13d", [R13W]>, DwarfRegNum<[13, -2, -2]>; + def R14D : RegisterWithSubRegs<"r14d", [R14W]>, DwarfRegNum<[14, -2, -2]>; + def R15D : RegisterWithSubRegs<"r15d", [R15W]>, DwarfRegNum<[15, -2, -2]>; + + // 64-bit registers, X86-64 only + def RAX : RegisterWithSubRegs<"rax", [EAX]>, DwarfRegNum<[0, -2, -2]>; + def RDX : RegisterWithSubRegs<"rdx", [EDX]>, DwarfRegNum<[1, -2, -2]>; + def RCX : RegisterWithSubRegs<"rcx", [ECX]>, DwarfRegNum<[2, -2, -2]>; + def RBX : RegisterWithSubRegs<"rbx", [EBX]>, DwarfRegNum<[3, -2, -2]>; + def RSI : RegisterWithSubRegs<"rsi", [ESI]>, DwarfRegNum<[4, -2, -2]>; + def RDI : RegisterWithSubRegs<"rdi", [EDI]>, DwarfRegNum<[5, -2, -2]>; + def RBP : RegisterWithSubRegs<"rbp", [EBP]>, DwarfRegNum<[6, -2, -2]>; + def RSP : RegisterWithSubRegs<"rsp", [ESP]>, DwarfRegNum<[7, -2, -2]>; + + def R8 : RegisterWithSubRegs<"r8", [R8D]>, DwarfRegNum<[8, -2, -2]>; + def R9 : RegisterWithSubRegs<"r9", [R9D]>, DwarfRegNum<[9, -2, -2]>; + def R10 : RegisterWithSubRegs<"r10", [R10D]>, DwarfRegNum<[10, -2, -2]>; + def R11 : RegisterWithSubRegs<"r11", [R11D]>, DwarfRegNum<[11, -2, -2]>; + def R12 : RegisterWithSubRegs<"r12", [R12D]>, DwarfRegNum<[12, -2, -2]>; + def R13 : RegisterWithSubRegs<"r13", [R13D]>, DwarfRegNum<[13, -2, -2]>; + def R14 : RegisterWithSubRegs<"r14", [R14D]>, DwarfRegNum<[14, -2, -2]>; + def R15 : RegisterWithSubRegs<"r15", [R15D]>, DwarfRegNum<[15, -2, -2]>; + def RIP : RegisterWithSubRegs<"rip", [EIP]>, DwarfRegNum<[16, -2, -2]>; + + // MMX Registers. These are actually aliased to ST0 .. ST7 + def MM0 : Register<"mm0">, DwarfRegNum<[41, 29, 29]>; + def MM1 : Register<"mm1">, DwarfRegNum<[42, 30, 30]>; + def MM2 : Register<"mm2">, DwarfRegNum<[43, 31, 31]>; + def MM3 : Register<"mm3">, DwarfRegNum<[44, 32, 32]>; + def MM4 : Register<"mm4">, DwarfRegNum<[45, 33, 33]>; + def MM5 : Register<"mm5">, DwarfRegNum<[46, 34, 34]>; + def MM6 : Register<"mm6">, DwarfRegNum<[47, 35, 35]>; + def MM7 : Register<"mm7">, DwarfRegNum<[48, 36, 36]>; + + // Pseudo Floating Point registers + def FP0 : Register<"fp0">; + def FP1 : Register<"fp1">; + def FP2 : Register<"fp2">; + def FP3 : Register<"fp3">; + def FP4 : Register<"fp4">; + def FP5 : Register<"fp5">; + def FP6 : Register<"fp6">; + + // XMM Registers, used by the various SSE instruction set extensions + def XMM0: Register<"xmm0">, DwarfRegNum<[17, 21, 21]>; + def XMM1: Register<"xmm1">, DwarfRegNum<[18, 22, 22]>; + def XMM2: Register<"xmm2">, DwarfRegNum<[19, 23, 23]>; + def XMM3: Register<"xmm3">, DwarfRegNum<[20, 24, 24]>; + def XMM4: Register<"xmm4">, DwarfRegNum<[21, 25, 25]>; + def XMM5: Register<"xmm5">, DwarfRegNum<[22, 26, 26]>; + def XMM6: Register<"xmm6">, DwarfRegNum<[23, 27, 27]>; + def XMM7: Register<"xmm7">, DwarfRegNum<[24, 28, 28]>; + + // X86-64 only + def XMM8: Register<"xmm8">, DwarfRegNum<[25, -2, -2]>; + def XMM9: Register<"xmm9">, DwarfRegNum<[26, -2, -2]>; + def XMM10: Register<"xmm10">, DwarfRegNum<[27, -2, -2]>; + def XMM11: Register<"xmm11">, DwarfRegNum<[28, -2, -2]>; + def XMM12: Register<"xmm12">, DwarfRegNum<[29, -2, -2]>; + def XMM13: Register<"xmm13">, DwarfRegNum<[30, -2, -2]>; + def XMM14: Register<"xmm14">, DwarfRegNum<[31, -2, -2]>; + def XMM15: Register<"xmm15">, DwarfRegNum<[32, -2, -2]>; + + // YMM Registers, used by AVX instructions + def YMM0: Register<"ymm0">, DwarfRegNum<[17, 21, 21]>; + def YMM1: Register<"ymm1">, DwarfRegNum<[18, 22, 22]>; + def YMM2: Register<"ymm2">, DwarfRegNum<[19, 23, 23]>; + def YMM3: Register<"ymm3">, DwarfRegNum<[20, 24, 24]>; + def YMM4: Register<"ymm4">, DwarfRegNum<[21, 25, 25]>; + def YMM5: Register<"ymm5">, DwarfRegNum<[22, 26, 26]>; + def YMM6: Register<"ymm6">, DwarfRegNum<[23, 27, 27]>; + def YMM7: Register<"ymm7">, DwarfRegNum<[24, 28, 28]>; + def YMM8: Register<"ymm8">, DwarfRegNum<[25, -2, -2]>; + def YMM9: Register<"ymm9">, DwarfRegNum<[26, -2, -2]>; + def YMM10: Register<"ymm10">, DwarfRegNum<[27, -2, -2]>; + def YMM11: Register<"ymm11">, DwarfRegNum<[28, -2, -2]>; + def YMM12: Register<"ymm12">, DwarfRegNum<[29, -2, -2]>; + def YMM13: Register<"ymm13">, DwarfRegNum<[30, -2, -2]>; + def YMM14: Register<"ymm14">, DwarfRegNum<[31, -2, -2]>; + def YMM15: Register<"ymm15">, DwarfRegNum<[32, -2, -2]>; + + // Floating point stack registers + def ST0 : Register<"st(0)">, DwarfRegNum<[33, 12, 11]>; + def ST1 : Register<"st(1)">, DwarfRegNum<[34, 13, 12]>; + def ST2 : Register<"st(2)">, DwarfRegNum<[35, 14, 13]>; + def ST3 : Register<"st(3)">, DwarfRegNum<[36, 15, 14]>; + def ST4 : Register<"st(4)">, DwarfRegNum<[37, 16, 15]>; + def ST5 : Register<"st(5)">, DwarfRegNum<[38, 17, 16]>; + def ST6 : Register<"st(6)">, DwarfRegNum<[39, 18, 17]>; + def ST7 : Register<"st(7)">, DwarfRegNum<[40, 19, 18]>; + + // Status flags register + def EFLAGS : Register<"flags">; + + // Segment registers + def CS : Register<"cs">; + def DS : Register<"ds">; + def SS : Register<"ss">; + def ES : Register<"es">; + def FS : Register<"fs">; + def GS : Register<"gs">; +} + + +//===----------------------------------------------------------------------===// +// Subregister Set Definitions... now that we have all of the pieces, define the +// sub registers for each register. +// + +def x86_subreg_8bit : PatLeaf<(i32 1)>; +def x86_subreg_8bit_hi : PatLeaf<(i32 2)>; +def x86_subreg_16bit : PatLeaf<(i32 3)>; +def x86_subreg_32bit : PatLeaf<(i32 4)>; + +def : SubRegSet<1, [AX, CX, DX, BX, SP, BP, SI, DI, + R8W, R9W, R10W, R11W, R12W, R13W, R14W, R15W], + [AL, CL, DL, BL, SPL, BPL, SIL, DIL, + R8B, R9B, R10B, R11B, R12B, R13B, R14B, R15B]>; + +def : SubRegSet<2, [AX, CX, DX, BX], + [AH, CH, DH, BH]>; + +def : SubRegSet<1, [EAX, ECX, EDX, EBX, ESP, EBP, ESI, EDI, + R8D, R9D, R10D, R11D, R12D, R13D, R14D, R15D], + [AL, CL, DL, BL, SPL, BPL, SIL, DIL, + R8B, R9B, R10B, R11B, R12B, R13B, R14B, R15B]>; + +def : SubRegSet<2, [EAX, ECX, EDX, EBX], + [AH, CH, DH, BH]>; + +def : SubRegSet<3, [EAX, ECX, EDX, EBX, ESP, EBP, ESI, EDI, + R8D, R9D, R10D, R11D, R12D, R13D, R14D, R15D], + [AX, CX, DX, BX, SP, BP, SI, DI, + R8W, R9W, R10W, R11W, R12W, R13W, R14W, R15W]>; + +def : SubRegSet<1, [RAX, RCX, RDX, RBX, RSP, RBP, RSI, RDI, + R8, R9, R10, R11, R12, R13, R14, R15], + [AL, CL, DL, BL, SPL, BPL, SIL, DIL, + R8B, R9B, R10B, R11B, R12B, R13B, R14B, R15B]>; + +def : SubRegSet<2, [RAX, RCX, RDX, RBX], + [AH, CH, DH, BH]>; + +def : SubRegSet<3, [RAX, RCX, RDX, RBX, RSP, RBP, RSI, RDI, + R8, R9, R10, R11, R12, R13, R14, R15], + [AX, CX, DX, BX, SP, BP, SI, DI, + R8W, R9W, R10W, R11W, R12W, R13W, R14W, R15W]>; + +def : SubRegSet<4, [RAX, RCX, RDX, RBX, RSP, RBP, RSI, RDI, + R8, R9, R10, R11, R12, R13, R14, R15], + [EAX, ECX, EDX, EBX, ESP, EBP, ESI, EDI, + R8D, R9D, R10D, R11D, R12D, R13D, R14D, R15D]>; + +def : SubRegSet<1, [YMM0, YMM1, YMM2, YMM3, YMM4, YMM5, YMM6, YMM7, + YMM8, YMM9, YMM10, YMM11, YMM12, YMM13, YMM14, YMM15], + [XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6, XMM7, + XMM8, XMM9, XMM10, XMM11, XMM12, XMM13, XMM14, XMM15]>; + +//===----------------------------------------------------------------------===// +// Register Class Definitions... now that we have all of the pieces, define the +// top-level register classes. The order specified in the register list is +// implicitly defined to be the register allocation order. +// + +// List call-clobbered registers before callee-save registers. RBX, RBP, (and +// R12, R13, R14, and R15 for X86-64) are callee-save registers. +// In 64-mode, there are 12 additional i8 registers, SIL, DIL, BPL, SPL, and +// R8B, ... R15B. +// Allocate R12 and R13 last, as these require an extra byte when +// encoded in x86_64 instructions. +// FIXME: Allow AH, CH, DH, BH to be used as general-purpose registers in +// 64-bit mode. The main complication is that they cannot be encoded in an +// instruction requiring a REX prefix, while SIL, DIL, BPL, R8D, etc. +// require a REX prefix. For example, "addb %ah, %dil" and "movzbl %ah, %r8d" +// cannot be encoded. +def GR8 : RegisterClass<"X86", [i8], 8, + [AL, CL, DL, AH, CH, DH, BL, BH, SIL, DIL, BPL, SPL, + R8B, R9B, R10B, R11B, R14B, R15B, R12B, R13B]> { + let MethodProtos = [{ + iterator allocation_order_begin(const MachineFunction &MF) const; + iterator allocation_order_end(const MachineFunction &MF) const; + }]; + let MethodBodies = [{ + static const unsigned X86_GR8_AO_64[] = { + X86::AL, X86::CL, X86::DL, X86::SIL, X86::DIL, + X86::R8B, X86::R9B, X86::R10B, X86::R11B, + X86::BL, X86::R14B, X86::R15B, X86::R12B, X86::R13B, X86::BPL + }; + + GR8Class::iterator + GR8Class::allocation_order_begin(const MachineFunction &MF) const { + const TargetMachine &TM = MF.getTarget(); + const X86Subtarget &Subtarget = TM.getSubtarget(); + if (Subtarget.is64Bit()) + return X86_GR8_AO_64; + else + return begin(); + } + + GR8Class::iterator + GR8Class::allocation_order_end(const MachineFunction &MF) const { + const TargetMachine &TM = MF.getTarget(); + const TargetRegisterInfo *RI = TM.getRegisterInfo(); + const X86Subtarget &Subtarget = TM.getSubtarget(); + // Does the function dedicate RBP / EBP to being a frame ptr? + if (!Subtarget.is64Bit()) + // In 32-mode, none of the 8-bit registers aliases EBP or ESP. + return begin() + 8; + else if (RI->hasFP(MF)) + // If so, don't allocate SPL or BPL. + return array_endof(X86_GR8_AO_64) - 1; + else + // If not, just don't allocate SPL. + return array_endof(X86_GR8_AO_64); + } + }]; +} + +def GR16 : RegisterClass<"X86", [i16], 16, + [AX, CX, DX, SI, DI, BX, BP, SP, + R8W, R9W, R10W, R11W, R14W, R15W, R12W, R13W]> { + let SubRegClassList = [GR8, GR8]; + let MethodProtos = [{ + iterator allocation_order_begin(const MachineFunction &MF) const; + iterator allocation_order_end(const MachineFunction &MF) const; + }]; + let MethodBodies = [{ + static const unsigned X86_GR16_AO_64[] = { + X86::AX, X86::CX, X86::DX, X86::SI, X86::DI, + X86::R8W, X86::R9W, X86::R10W, X86::R11W, + X86::BX, X86::R14W, X86::R15W, X86::R12W, X86::R13W, X86::BP + }; + + GR16Class::iterator + GR16Class::allocation_order_begin(const MachineFunction &MF) const { + const TargetMachine &TM = MF.getTarget(); + const X86Subtarget &Subtarget = TM.getSubtarget(); + if (Subtarget.is64Bit()) + return X86_GR16_AO_64; + else + return begin(); + } + + GR16Class::iterator + GR16Class::allocation_order_end(const MachineFunction &MF) const { + const TargetMachine &TM = MF.getTarget(); + const TargetRegisterInfo *RI = TM.getRegisterInfo(); + const X86Subtarget &Subtarget = TM.getSubtarget(); + if (Subtarget.is64Bit()) { + // Does the function dedicate RBP to being a frame ptr? + if (RI->hasFP(MF)) + // If so, don't allocate SP or BP. + return array_endof(X86_GR16_AO_64) - 1; + else + // If not, just don't allocate SP. + return array_endof(X86_GR16_AO_64); + } else { + // Does the function dedicate EBP to being a frame ptr? + if (RI->hasFP(MF)) + // If so, don't allocate SP or BP. + return begin() + 6; + else + // If not, just don't allocate SP. + return begin() + 7; + } + } + }]; +} + +def GR32 : RegisterClass<"X86", [i32], 32, + [EAX, ECX, EDX, ESI, EDI, EBX, EBP, ESP, + R8D, R9D, R10D, R11D, R14D, R15D, R12D, R13D]> { + let SubRegClassList = [GR8, GR8, GR16]; + let MethodProtos = [{ + iterator allocation_order_begin(const MachineFunction &MF) const; + iterator allocation_order_end(const MachineFunction &MF) const; + }]; + let MethodBodies = [{ + static const unsigned X86_GR32_AO_64[] = { + X86::EAX, X86::ECX, X86::EDX, X86::ESI, X86::EDI, + X86::R8D, X86::R9D, X86::R10D, X86::R11D, + X86::EBX, X86::R14D, X86::R15D, X86::R12D, X86::R13D, X86::EBP + }; + + GR32Class::iterator + GR32Class::allocation_order_begin(const MachineFunction &MF) const { + const TargetMachine &TM = MF.getTarget(); + const X86Subtarget &Subtarget = TM.getSubtarget(); + if (Subtarget.is64Bit()) + return X86_GR32_AO_64; + else + return begin(); + } + + GR32Class::iterator + GR32Class::allocation_order_end(const MachineFunction &MF) const { + const TargetMachine &TM = MF.getTarget(); + const TargetRegisterInfo *RI = TM.getRegisterInfo(); + const X86Subtarget &Subtarget = TM.getSubtarget(); + if (Subtarget.is64Bit()) { + // Does the function dedicate RBP to being a frame ptr? + if (RI->hasFP(MF)) + // If so, don't allocate ESP or EBP. + return array_endof(X86_GR32_AO_64) - 1; + else + // If not, just don't allocate ESP. + return array_endof(X86_GR32_AO_64); + } else { + // Does the function dedicate EBP to being a frame ptr? + if (RI->hasFP(MF)) + // If so, don't allocate ESP or EBP. + return begin() + 6; + else + // If not, just don't allocate ESP. + return begin() + 7; + } + } + }]; +} + +// GR64 - 64-bit GPRs. This oddly includes RIP, which isn't accurate, since +// RIP isn't really a register and it can't be used anywhere except in an +// address, but it doesn't cause trouble. +def GR64 : RegisterClass<"X86", [i64], 64, + [RAX, RCX, RDX, RSI, RDI, R8, R9, R10, R11, + RBX, R14, R15, R12, R13, RBP, RSP, RIP]> { + let SubRegClassList = [GR8, GR8, GR16, GR32]; + let MethodProtos = [{ + iterator allocation_order_end(const MachineFunction &MF) const; + }]; + let MethodBodies = [{ + GR64Class::iterator + GR64Class::allocation_order_end(const MachineFunction &MF) const { + const TargetMachine &TM = MF.getTarget(); + const TargetRegisterInfo *RI = TM.getRegisterInfo(); + const X86Subtarget &Subtarget = TM.getSubtarget(); + if (!Subtarget.is64Bit()) + return begin(); // None of these are allocatable in 32-bit. + if (RI->hasFP(MF)) // Does the function dedicate RBP to being a frame ptr? + return end()-3; // If so, don't allocate RIP, RSP or RBP + else + return end()-2; // If not, just don't allocate RIP or RSP + } + }]; +} + +// Segment registers for use by MOV instructions (and others) that have a +// segment register as one operand. Always contain a 16-bit segment +// descriptor. +def SEGMENT_REG : RegisterClass<"X86", [i16], 16, [CS, DS, SS, ES, FS, GS]> { +} + +// GR8_ABCD_L, GR8_ABCD_H, GR16_ABCD, GR32_ABCD, GR64_ABCD - Subclasses of +// GR8, GR16, GR32, and GR64 which contain just the "a" "b", "c", and "d" +// registers. On x86-32, GR16_ABCD and GR32_ABCD are classes for registers +// that support 8-bit subreg operations. On x86-64, GR16_ABCD, GR32_ABCD, +// and GR64_ABCD are classes for registers that support 8-bit h-register +// operations. +def GR8_ABCD_L : RegisterClass<"X86", [i8], 8, [AL, CL, DL, BL]> { +} +def GR8_ABCD_H : RegisterClass<"X86", [i8], 8, [AH, CH, DH, BH]> { +} +def GR16_ABCD : RegisterClass<"X86", [i16], 16, [AX, CX, DX, BX]> { + let SubRegClassList = [GR8_ABCD_L, GR8_ABCD_H]; +} +def GR32_ABCD : RegisterClass<"X86", [i32], 32, [EAX, ECX, EDX, EBX]> { + let SubRegClassList = [GR8_ABCD_L, GR8_ABCD_H, GR16_ABCD]; +} +def GR64_ABCD : RegisterClass<"X86", [i64], 64, [RAX, RCX, RDX, RBX]> { + let SubRegClassList = [GR8_ABCD_L, GR8_ABCD_H, GR16_ABCD, GR32_ABCD]; +} + +// GR8_NOREX, GR16_NOREX, GR32_NOREX, GR64_NOREX - Subclasses of +// GR8, GR16, GR32, and GR64 which contain only the first 8 GPRs. +// On x86-64, GR64_NOREX, GR32_NOREX and GR16_NOREX are the classes +// of registers which do not by themselves require a REX prefix. +def GR8_NOREX : RegisterClass<"X86", [i8], 8, + [AL, CL, DL, AH, CH, DH, BL, BH, + SIL, DIL, BPL, SPL]> { + let MethodProtos = [{ + iterator allocation_order_begin(const MachineFunction &MF) const; + iterator allocation_order_end(const MachineFunction &MF) const; + }]; + let MethodBodies = [{ + static const unsigned X86_GR8_NOREX_AO_64[] = { + X86::AL, X86::CL, X86::DL, X86::SIL, X86::DIL, X86::BL, X86::BPL + }; + + GR8_NOREXClass::iterator + GR8_NOREXClass::allocation_order_begin(const MachineFunction &MF) const { + const TargetMachine &TM = MF.getTarget(); + const X86Subtarget &Subtarget = TM.getSubtarget(); + if (Subtarget.is64Bit()) + return X86_GR8_NOREX_AO_64; + else + return begin(); + } + + GR8_NOREXClass::iterator + GR8_NOREXClass::allocation_order_end(const MachineFunction &MF) const { + const TargetMachine &TM = MF.getTarget(); + const TargetRegisterInfo *RI = TM.getRegisterInfo(); + const X86Subtarget &Subtarget = TM.getSubtarget(); + // Does the function dedicate RBP / EBP to being a frame ptr? + if (!Subtarget.is64Bit()) + // In 32-mode, none of the 8-bit registers aliases EBP or ESP. + return begin() + 8; + else if (RI->hasFP(MF)) + // If so, don't allocate SPL or BPL. + return array_endof(X86_GR8_NOREX_AO_64) - 1; + else + // If not, just don't allocate SPL. + return array_endof(X86_GR8_NOREX_AO_64); + } + }]; +} +def GR16_NOREX : RegisterClass<"X86", [i16], 16, + [AX, CX, DX, SI, DI, BX, BP, SP]> { + let SubRegClassList = [GR8_NOREX, GR8_NOREX]; + let MethodProtos = [{ + iterator allocation_order_end(const MachineFunction &MF) const; + }]; + let MethodBodies = [{ + GR16_NOREXClass::iterator + GR16_NOREXClass::allocation_order_end(const MachineFunction &MF) const { + const TargetMachine &TM = MF.getTarget(); + const TargetRegisterInfo *RI = TM.getRegisterInfo(); + // Does the function dedicate RBP / EBP to being a frame ptr? + if (RI->hasFP(MF)) + // If so, don't allocate SP or BP. + return end() - 2; + else + // If not, just don't allocate SP. + return end() - 1; + } + }]; +} +// GR32_NOREX - GR32 registers which do not require a REX prefix. +def GR32_NOREX : RegisterClass<"X86", [i32], 32, + [EAX, ECX, EDX, ESI, EDI, EBX, EBP, ESP]> { + let SubRegClassList = [GR8_NOREX, GR8_NOREX, GR16_NOREX]; + let MethodProtos = [{ + iterator allocation_order_end(const MachineFunction &MF) const; + }]; + let MethodBodies = [{ + GR32_NOREXClass::iterator + GR32_NOREXClass::allocation_order_end(const MachineFunction &MF) const { + const TargetMachine &TM = MF.getTarget(); + const TargetRegisterInfo *RI = TM.getRegisterInfo(); + // Does the function dedicate RBP / EBP to being a frame ptr? + if (RI->hasFP(MF)) + // If so, don't allocate ESP or EBP. + return end() - 2; + else + // If not, just don't allocate ESP. + return end() - 1; + } + }]; +} +// GR64_NOREX - GR64 registers which do not require a REX prefix. +def GR64_NOREX : RegisterClass<"X86", [i64], 64, + [RAX, RCX, RDX, RSI, RDI, RBX, RBP, RSP, RIP]> { + let SubRegClassList = [GR8_NOREX, GR8_NOREX, GR16_NOREX, GR32_NOREX]; + let MethodProtos = [{ + iterator allocation_order_end(const MachineFunction &MF) const; + }]; + let MethodBodies = [{ + GR64_NOREXClass::iterator + GR64_NOREXClass::allocation_order_end(const MachineFunction &MF) const { + const TargetMachine &TM = MF.getTarget(); + const TargetRegisterInfo *RI = TM.getRegisterInfo(); + // Does the function dedicate RBP to being a frame ptr? + if (RI->hasFP(MF)) + // If so, don't allocate RIP, RSP or RBP. + return end() - 3; + else + // If not, just don't allocate RIP or RSP. + return end() - 2; + } + }]; +} + +// GR32_NOSP - GR32 registers except ESP. +def GR32_NOSP : RegisterClass<"X86", [i32], 32, + [EAX, ECX, EDX, ESI, EDI, EBX, EBP, + R8D, R9D, R10D, R11D, R14D, R15D, R12D, R13D]> { + let SubRegClassList = [GR8, GR8, GR16]; + let MethodProtos = [{ + iterator allocation_order_begin(const MachineFunction &MF) const; + iterator allocation_order_end(const MachineFunction &MF) const; + }]; + let MethodBodies = [{ + static const unsigned X86_GR32_NOSP_AO_64[] = { + X86::EAX, X86::ECX, X86::EDX, X86::ESI, X86::EDI, + X86::R8D, X86::R9D, X86::R10D, X86::R11D, + X86::EBX, X86::R14D, X86::R15D, X86::R12D, X86::R13D, X86::EBP + }; + + GR32_NOSPClass::iterator + GR32_NOSPClass::allocation_order_begin(const MachineFunction &MF) const { + const TargetMachine &TM = MF.getTarget(); + const X86Subtarget &Subtarget = TM.getSubtarget(); + if (Subtarget.is64Bit()) + return X86_GR32_NOSP_AO_64; + else + return begin(); + } + + GR32_NOSPClass::iterator + GR32_NOSPClass::allocation_order_end(const MachineFunction &MF) const { + const TargetMachine &TM = MF.getTarget(); + const TargetRegisterInfo *RI = TM.getRegisterInfo(); + const X86Subtarget &Subtarget = TM.getSubtarget(); + if (Subtarget.is64Bit()) { + // Does the function dedicate RBP to being a frame ptr? + if (RI->hasFP(MF)) + // If so, don't allocate EBP. + return array_endof(X86_GR32_NOSP_AO_64) - 1; + else + // If not, any reg in this class is ok. + return array_endof(X86_GR32_NOSP_AO_64); + } else { + // Does the function dedicate EBP to being a frame ptr? + if (RI->hasFP(MF)) + // If so, don't allocate EBP. + return begin() + 6; + else + // If not, any reg in this class is ok. + return begin() + 7; + } + } + }]; +} + +// GR64_NOSP - GR64 registers except RSP (and RIP). +def GR64_NOSP : RegisterClass<"X86", [i64], 64, + [RAX, RCX, RDX, RSI, RDI, R8, R9, R10, R11, + RBX, R14, R15, R12, R13, RBP]> { + let SubRegClassList = [GR8, GR8, GR16, GR32_NOSP]; + let MethodProtos = [{ + iterator allocation_order_end(const MachineFunction &MF) const; + }]; + let MethodBodies = [{ + GR64_NOSPClass::iterator + GR64_NOSPClass::allocation_order_end(const MachineFunction &MF) const { + const TargetMachine &TM = MF.getTarget(); + const TargetRegisterInfo *RI = TM.getRegisterInfo(); + const X86Subtarget &Subtarget = TM.getSubtarget(); + if (!Subtarget.is64Bit()) + return begin(); // None of these are allocatable in 32-bit. + if (RI->hasFP(MF)) // Does the function dedicate RBP to being a frame ptr? + return end()-1; // If so, don't allocate RBP + else + return end(); // If not, any reg in this class is ok. + } + }]; +} + +// GR64_NOREX_NOSP - GR64_NOREX registers except RSP. +def GR64_NOREX_NOSP : RegisterClass<"X86", [i64], 64, + [RAX, RCX, RDX, RSI, RDI, RBX, RBP]> { + let SubRegClassList = [GR8_NOREX, GR8_NOREX, GR16_NOREX, GR32_NOREX]; + let MethodProtos = [{ + iterator allocation_order_end(const MachineFunction &MF) const; + }]; + let MethodBodies = [{ + GR64_NOREX_NOSPClass::iterator + GR64_NOREX_NOSPClass::allocation_order_end(const MachineFunction &MF) const { + const TargetMachine &TM = MF.getTarget(); + const TargetRegisterInfo *RI = TM.getRegisterInfo(); + // Does the function dedicate RBP to being a frame ptr? + if (RI->hasFP(MF)) + // If so, don't allocate RBP. + return end() - 1; + else + // If not, any reg in this class is ok. + return end(); + } + }]; +} + +// A class to support the 'A' assembler constraint: EAX then EDX. +def GR32_AD : RegisterClass<"X86", [i32], 32, [EAX, EDX]> { + let SubRegClassList = [GR8_ABCD_L, GR8_ABCD_H, GR16_ABCD]; +} + +// Scalar SSE2 floating point registers. +def FR32 : RegisterClass<"X86", [f32], 32, + [XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6, XMM7, + XMM8, XMM9, XMM10, XMM11, + XMM12, XMM13, XMM14, XMM15]> { + let MethodProtos = [{ + iterator allocation_order_end(const MachineFunction &MF) const; + }]; + let MethodBodies = [{ + FR32Class::iterator + FR32Class::allocation_order_end(const MachineFunction &MF) const { + const TargetMachine &TM = MF.getTarget(); + const X86Subtarget &Subtarget = TM.getSubtarget(); + if (!Subtarget.is64Bit()) + return end()-8; // Only XMM0 to XMM7 are available in 32-bit mode. + else + return end(); + } + }]; +} + +def FR64 : RegisterClass<"X86", [f64], 64, + [XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6, XMM7, + XMM8, XMM9, XMM10, XMM11, + XMM12, XMM13, XMM14, XMM15]> { + let MethodProtos = [{ + iterator allocation_order_end(const MachineFunction &MF) const; + }]; + let MethodBodies = [{ + FR64Class::iterator + FR64Class::allocation_order_end(const MachineFunction &MF) const { + const TargetMachine &TM = MF.getTarget(); + const X86Subtarget &Subtarget = TM.getSubtarget(); + if (!Subtarget.is64Bit()) + return end()-8; // Only XMM0 to XMM7 are available in 32-bit mode. + else + return end(); + } + }]; +} + + +// FIXME: This sets up the floating point register files as though they are f64 +// values, though they really are f80 values. This will cause us to spill +// values as 64-bit quantities instead of 80-bit quantities, which is much much +// faster on common hardware. In reality, this should be controlled by a +// command line option or something. + +def RFP32 : RegisterClass<"X86",[f32], 32, [FP0, FP1, FP2, FP3, FP4, FP5, FP6]>; +def RFP64 : RegisterClass<"X86",[f64], 32, [FP0, FP1, FP2, FP3, FP4, FP5, FP6]>; +def RFP80 : RegisterClass<"X86",[f80], 32, [FP0, FP1, FP2, FP3, FP4, FP5, FP6]>; + +// Floating point stack registers (these are not allocatable by the +// register allocator - the floating point stackifier is responsible +// for transforming FPn allocations to STn registers) +def RST : RegisterClass<"X86", [f80, f64, f32], 32, + [ST0, ST1, ST2, ST3, ST4, ST5, ST6, ST7]> { + let MethodProtos = [{ + iterator allocation_order_end(const MachineFunction &MF) const; + }]; + let MethodBodies = [{ + RSTClass::iterator + RSTClass::allocation_order_end(const MachineFunction &MF) const { + return begin(); + } + }]; +} + +// Generic vector registers: VR64 and VR128. +def VR64 : RegisterClass<"X86", [v8i8, v4i16, v2i32, v1i64, v2f32], 64, + [MM0, MM1, MM2, MM3, MM4, MM5, MM6, MM7]>; +def VR128 : RegisterClass<"X86", [v16i8, v8i16, v4i32, v2i64, v4f32, v2f64],128, + [XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6, XMM7, + XMM8, XMM9, XMM10, XMM11, + XMM12, XMM13, XMM14, XMM15]> { + let MethodProtos = [{ + iterator allocation_order_end(const MachineFunction &MF) const; + }]; + let MethodBodies = [{ + VR128Class::iterator + VR128Class::allocation_order_end(const MachineFunction &MF) const { + const TargetMachine &TM = MF.getTarget(); + const X86Subtarget &Subtarget = TM.getSubtarget(); + if (!Subtarget.is64Bit()) + return end()-8; // Only XMM0 to XMM7 are available in 32-bit mode. + else + return end(); + } + }]; +} +def VR256 : RegisterClass<"X86", [ v8i32, v4i64, v8f32, v4f64],256, + [YMM0, YMM1, YMM2, YMM3, YMM4, YMM5, YMM6, YMM7, + YMM8, YMM9, YMM10, YMM11, + YMM12, YMM13, YMM14, YMM15]>; + +// Status flags registers. +def CCR : RegisterClass<"X86", [i32], 32, [EFLAGS]> { + let CopyCost = -1; // Don't allow copying of status registers. +} diff --git a/libclamav/c++/llvm/lib/Target/X86/X86Relocations.h b/libclamav/c++/llvm/lib/Target/X86/X86Relocations.h new file mode 100644 index 000000000..990962dc4 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/X86/X86Relocations.h @@ -0,0 +1,52 @@ +//===- X86Relocations.h - X86 Code Relocations ------------------*- 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 the X86 target-specific relocation types. +// +//===----------------------------------------------------------------------===// + +#ifndef X86RELOCATIONS_H +#define X86RELOCATIONS_H + +#include "llvm/CodeGen/MachineRelocation.h" + +namespace llvm { + namespace X86 { + /// RelocationType - An enum for the x86 relocation codes. Note that + /// the terminology here doesn't follow x86 convention - word means + /// 32-bit and dword means 64-bit. The relocations will be treated + /// by JIT or ObjectCode emitters, this is transparent to the x86 code + /// emitter but JIT and ObjectCode will treat them differently + enum RelocationType { + /// reloc_pcrel_word - PC relative relocation, add the relocated value to + /// the value already in memory, after we adjust it for where the PC is. + reloc_pcrel_word = 0, + + /// reloc_picrel_word - PIC base relative relocation, add the relocated + /// value to the value already in memory, after we adjust it for where the + /// PIC base is. + reloc_picrel_word = 1, + + /// reloc_absolute_word - absolute relocation, just add the relocated + /// value to the value already in memory. + reloc_absolute_word = 2, + + /// reloc_absolute_word_sext - absolute relocation, just add the relocated + /// value to the value already in memory. In object files, it represents a + /// value which must be sign-extended when resolving the relocation. + reloc_absolute_word_sext = 3, + + /// reloc_absolute_dword - absolute relocation, just add the relocated + /// value to the value already in memory. + reloc_absolute_dword = 4 + }; + } +} + +#endif diff --git a/libclamav/c++/llvm/lib/Target/X86/X86Subtarget.cpp b/libclamav/c++/llvm/lib/Target/X86/X86Subtarget.cpp new file mode 100644 index 000000000..661f56046 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/X86/X86Subtarget.cpp @@ -0,0 +1,371 @@ +//===-- X86Subtarget.cpp - X86 Subtarget Information ------------*- 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 the X86 specific subclass of TargetSubtarget. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "subtarget" +#include "X86Subtarget.h" +#include "X86InstrInfo.h" +#include "X86GenSubtarget.inc" +#include "llvm/GlobalValue.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/System/Host.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetOptions.h" +#include "llvm/ADT/SmallVector.h" +using namespace llvm; + +#if defined(_MSC_VER) +#include +#endif + +/// ClassifyBlockAddressReference - Classify a blockaddress reference for the +/// current subtarget according to how we should reference it in a non-pcrel +/// context. +unsigned char X86Subtarget:: +ClassifyBlockAddressReference() const { + if (isPICStyleGOT()) // 32-bit ELF targets. + return X86II::MO_GOTOFF; + + if (isPICStyleStubPIC()) // Darwin/32 in PIC mode. + return X86II::MO_PIC_BASE_OFFSET; + + // Direct static reference to label. + return X86II::MO_NO_FLAG; +} + +/// ClassifyGlobalReference - Classify a global variable reference for the +/// current subtarget according to how we should reference it in a non-pcrel +/// context. +unsigned char X86Subtarget:: +ClassifyGlobalReference(const GlobalValue *GV, const TargetMachine &TM) const { + // DLLImport only exists on windows, it is implemented as a load from a + // DLLIMPORT stub. + if (GV->hasDLLImportLinkage()) + return X86II::MO_DLLIMPORT; + + // GV with ghost linkage (in JIT lazy compilation mode) do not require an + // extra load from stub. + bool isDecl = GV->isDeclaration() && !GV->hasNotBeenReadFromBitcode(); + + // X86-64 in PIC mode. + if (isPICStyleRIPRel()) { + // Large model never uses stubs. + if (TM.getCodeModel() == CodeModel::Large) + return X86II::MO_NO_FLAG; + + if (isTargetDarwin()) { + // If symbol visibility is hidden, the extra load is not needed if + // target is x86-64 or the symbol is definitely defined in the current + // translation unit. + if (GV->hasDefaultVisibility() && + (isDecl || GV->isWeakForLinker())) + return X86II::MO_GOTPCREL; + } else { + assert(isTargetELF() && "Unknown rip-relative target"); + + // Extra load is needed for all externally visible. + if (!GV->hasLocalLinkage() && GV->hasDefaultVisibility()) + return X86II::MO_GOTPCREL; + } + + return X86II::MO_NO_FLAG; + } + + if (isPICStyleGOT()) { // 32-bit ELF targets. + // Extra load is needed for all externally visible. + if (GV->hasLocalLinkage() || GV->hasHiddenVisibility()) + return X86II::MO_GOTOFF; + return X86II::MO_GOT; + } + + if (isPICStyleStubPIC()) { // Darwin/32 in PIC mode. + // Determine whether we have a stub reference and/or whether the reference + // is relative to the PIC base or not. + + // If this is a strong reference to a definition, it is definitely not + // through a stub. + if (!isDecl && !GV->isWeakForLinker()) + return X86II::MO_PIC_BASE_OFFSET; + + // Unless we have a symbol with hidden visibility, we have to go through a + // normal $non_lazy_ptr stub because this symbol might be resolved late. + if (!GV->hasHiddenVisibility()) // Non-hidden $non_lazy_ptr reference. + return X86II::MO_DARWIN_NONLAZY_PIC_BASE; + + // If symbol visibility is hidden, we have a stub for common symbol + // references and external declarations. + if (isDecl || GV->hasCommonLinkage()) { + // Hidden $non_lazy_ptr reference. + return X86II::MO_DARWIN_HIDDEN_NONLAZY_PIC_BASE; + } + + // Otherwise, no stub. + return X86II::MO_PIC_BASE_OFFSET; + } + + if (isPICStyleStubNoDynamic()) { // Darwin/32 in -mdynamic-no-pic mode. + // Determine whether we have a stub reference. + + // If this is a strong reference to a definition, it is definitely not + // through a stub. + if (!isDecl && !GV->isWeakForLinker()) + return X86II::MO_NO_FLAG; + + // Unless we have a symbol with hidden visibility, we have to go through a + // normal $non_lazy_ptr stub because this symbol might be resolved late. + if (!GV->hasHiddenVisibility()) // Non-hidden $non_lazy_ptr reference. + return X86II::MO_DARWIN_NONLAZY; + + // Otherwise, no stub. + return X86II::MO_NO_FLAG; + } + + // Direct static reference to global. + return X86II::MO_NO_FLAG; +} + + +/// getBZeroEntry - This function returns the name of a function which has an +/// interface like the non-standard bzero function, if such a function exists on +/// the current subtarget and it is considered prefereable over memset with zero +/// passed as the second argument. Otherwise it returns null. +const char *X86Subtarget::getBZeroEntry() const { + // Darwin 10 has a __bzero entry point for this purpose. + if (getDarwinVers() >= 10) + return "__bzero"; + + return 0; +} + +/// IsLegalToCallImmediateAddr - Return true if the subtarget allows calls +/// to immediate address. +bool X86Subtarget::IsLegalToCallImmediateAddr(const TargetMachine &TM) const { + if (Is64Bit) + return false; + return isTargetELF() || TM.getRelocationModel() == Reloc::Static; +} + +/// getSpecialAddressLatency - For targets where it is beneficial to +/// backschedule instructions that compute addresses, return a value +/// indicating the number of scheduling cycles of backscheduling that +/// should be attempted. +unsigned X86Subtarget::getSpecialAddressLatency() const { + // For x86 out-of-order targets, back-schedule address computations so + // that loads and stores aren't blocked. + // This value was chosen arbitrarily. + return 200; +} + +/// GetCpuIDAndInfo - Execute the specified cpuid and return the 4 values in the +/// specified arguments. If we can't run cpuid on the host, return true. +static bool GetCpuIDAndInfo(unsigned value, unsigned *rEAX, + unsigned *rEBX, unsigned *rECX, unsigned *rEDX) { +#if defined(__x86_64__) || defined(_M_AMD64) || defined (_M_X64) + #if defined(__GNUC__) + // gcc doesn't know cpuid would clobber ebx/rbx. Preseve it manually. + asm ("movq\t%%rbx, %%rsi\n\t" + "cpuid\n\t" + "xchgq\t%%rbx, %%rsi\n\t" + : "=a" (*rEAX), + "=S" (*rEBX), + "=c" (*rECX), + "=d" (*rEDX) + : "a" (value)); + return false; + #elif defined(_MSC_VER) + int registers[4]; + __cpuid(registers, value); + *rEAX = registers[0]; + *rEBX = registers[1]; + *rECX = registers[2]; + *rEDX = registers[3]; + return false; + #endif +#elif defined(i386) || defined(__i386__) || defined(__x86__) || defined(_M_IX86) + #if defined(__GNUC__) + asm ("movl\t%%ebx, %%esi\n\t" + "cpuid\n\t" + "xchgl\t%%ebx, %%esi\n\t" + : "=a" (*rEAX), + "=S" (*rEBX), + "=c" (*rECX), + "=d" (*rEDX) + : "a" (value)); + return false; + #elif defined(_MSC_VER) + __asm { + mov eax,value + cpuid + mov esi,rEAX + mov dword ptr [esi],eax + mov esi,rEBX + mov dword ptr [esi],ebx + mov esi,rECX + mov dword ptr [esi],ecx + mov esi,rEDX + mov dword ptr [esi],edx + } + return false; + #endif +#endif + return true; +} + +static void DetectFamilyModel(unsigned EAX, unsigned &Family, unsigned &Model) { + Family = (EAX >> 8) & 0xf; // Bits 8 - 11 + Model = (EAX >> 4) & 0xf; // Bits 4 - 7 + if (Family == 6 || Family == 0xf) { + if (Family == 0xf) + // Examine extended family ID if family ID is F. + Family += (EAX >> 20) & 0xff; // Bits 20 - 27 + // Examine extended model ID if family ID is 6 or F. + Model += ((EAX >> 16) & 0xf) << 4; // Bits 16 - 19 + } +} + +void X86Subtarget::AutoDetectSubtargetFeatures() { + unsigned EAX = 0, EBX = 0, ECX = 0, EDX = 0; + union { + unsigned u[3]; + char c[12]; + } text; + + if (GetCpuIDAndInfo(0, &EAX, text.u+0, text.u+2, text.u+1)) + return; + + GetCpuIDAndInfo(0x1, &EAX, &EBX, &ECX, &EDX); + + if ((EDX >> 15) & 1) HasCMov = true; + if ((EDX >> 23) & 1) X86SSELevel = MMX; + if ((EDX >> 25) & 1) X86SSELevel = SSE1; + if ((EDX >> 26) & 1) X86SSELevel = SSE2; + if (ECX & 0x1) X86SSELevel = SSE3; + if ((ECX >> 9) & 1) X86SSELevel = SSSE3; + if ((ECX >> 19) & 1) X86SSELevel = SSE41; + if ((ECX >> 20) & 1) X86SSELevel = SSE42; + + bool IsIntel = memcmp(text.c, "GenuineIntel", 12) == 0; + bool IsAMD = !IsIntel && memcmp(text.c, "AuthenticAMD", 12) == 0; + + HasFMA3 = IsIntel && ((ECX >> 12) & 0x1); + HasAVX = ((ECX >> 28) & 0x1); + + if (IsIntel || IsAMD) { + // Determine if bit test memory instructions are slow. + unsigned Family = 0; + unsigned Model = 0; + DetectFamilyModel(EAX, Family, Model); + IsBTMemSlow = IsAMD || (Family == 6 && Model >= 13); + + GetCpuIDAndInfo(0x80000001, &EAX, &EBX, &ECX, &EDX); + HasX86_64 = (EDX >> 29) & 0x1; + HasSSE4A = IsAMD && ((ECX >> 6) & 0x1); + HasFMA4 = IsAMD && ((ECX >> 16) & 0x1); + } +} + +X86Subtarget::X86Subtarget(const std::string &TT, const std::string &FS, + bool is64Bit) + : PICStyle(PICStyles::None) + , X86SSELevel(NoMMXSSE) + , X863DNowLevel(NoThreeDNow) + , HasCMov(false) + , HasX86_64(false) + , HasSSE4A(false) + , HasAVX(false) + , HasFMA3(false) + , HasFMA4(false) + , IsBTMemSlow(false) + , DarwinVers(0) + , stackAlignment(8) + // FIXME: this is a known good value for Yonah. How about others? + , MaxInlineSizeThreshold(128) + , Is64Bit(is64Bit) + , TargetType(isELF) { // Default to ELF unless otherwise specified. + + // default to hard float ABI + if (FloatABIType == FloatABI::Default) + FloatABIType = FloatABI::Hard; + + // Determine default and user specified characteristics + if (!FS.empty()) { + // If feature string is not empty, parse features string. + std::string CPU = sys::getHostCPUName(); + ParseSubtargetFeatures(FS, CPU); + // All X86-64 CPUs also have SSE2, however user might request no SSE via + // -mattr, so don't force SSELevel here. + } else { + // Otherwise, use CPUID to auto-detect feature set. + AutoDetectSubtargetFeatures(); + // Make sure SSE2 is enabled; it is available on all X86-64 CPUs. + if (Is64Bit && X86SSELevel < SSE2) + X86SSELevel = SSE2; + } + + // If requesting codegen for X86-64, make sure that 64-bit features + // are enabled. + if (Is64Bit) + HasX86_64 = true; + + DEBUG(errs() << "Subtarget features: SSELevel " << X86SSELevel + << ", 3DNowLevel " << X863DNowLevel + << ", 64bit " << HasX86_64 << "\n"); + assert((!Is64Bit || HasX86_64) && + "64-bit code requested on a subtarget that doesn't support it!"); + + // Set the boolean corresponding to the current target triple, or the default + // if one cannot be determined, to true. + if (TT.length() > 5) { + size_t Pos; + if ((Pos = TT.find("-darwin")) != std::string::npos) { + TargetType = isDarwin; + + // Compute the darwin version number. + if (isdigit(TT[Pos+7])) + DarwinVers = atoi(&TT[Pos+7]); + else + DarwinVers = 8; // Minimum supported darwin is Tiger. + } else if (TT.find("linux") != std::string::npos) { + // Linux doesn't imply ELF, but we don't currently support anything else. + TargetType = isELF; + } else if (TT.find("cygwin") != std::string::npos) { + TargetType = isCygwin; + } else if (TT.find("mingw") != std::string::npos) { + TargetType = isMingw; + } else if (TT.find("win32") != std::string::npos) { + TargetType = isWindows; + } else if (TT.find("windows") != std::string::npos) { + TargetType = isWindows; + } else if (TT.find("-cl") != std::string::npos) { + TargetType = isDarwin; + DarwinVers = 9; + } + } + + // Stack alignment is 16 bytes on Darwin (both 32 and 64 bit) and for all 64 + // bit targets. + if (TargetType == isDarwin || Is64Bit) + stackAlignment = 16; + + if (StackAlignment) + stackAlignment = StackAlignment; +} + +bool X86Subtarget::enablePostRAScheduler( + CodeGenOpt::Level OptLevel, + TargetSubtarget::AntiDepBreakMode& Mode, + RegClassVector& CriticalPathRCs) const { + Mode = TargetSubtarget::ANTIDEP_CRITICAL; + CriticalPathRCs.clear(); + return OptLevel >= CodeGenOpt::Default; +} diff --git a/libclamav/c++/llvm/lib/Target/X86/X86Subtarget.h b/libclamav/c++/llvm/lib/Target/X86/X86Subtarget.h new file mode 100644 index 000000000..fb457ddd8 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/X86/X86Subtarget.h @@ -0,0 +1,233 @@ +//=====---- X86Subtarget.h - Define Subtarget for the X86 -----*- C++ -*--====// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the X86 specific subclass of TargetSubtarget. +// +//===----------------------------------------------------------------------===// + +#ifndef X86SUBTARGET_H +#define X86SUBTARGET_H + +#include "llvm/Target/TargetSubtarget.h" +#include + +namespace llvm { +class GlobalValue; +class TargetMachine; + +/// PICStyles - The X86 backend supports a number of different styles of PIC. +/// +namespace PICStyles { +enum Style { + StubPIC, // Used on i386-darwin in -fPIC mode. + StubDynamicNoPIC, // Used on i386-darwin in -mdynamic-no-pic mode. + GOT, // Used on many 32-bit unices in -fPIC mode. + RIPRel, // Used on X86-64 when not in -static mode. + None // Set when in -static mode (not PIC or DynamicNoPIC mode). +}; +} + +class X86Subtarget : public TargetSubtarget { +protected: + enum X86SSEEnum { + NoMMXSSE, MMX, SSE1, SSE2, SSE3, SSSE3, SSE41, SSE42 + }; + + enum X863DNowEnum { + NoThreeDNow, ThreeDNow, ThreeDNowA + }; + + /// PICStyle - Which PIC style to use + /// + PICStyles::Style PICStyle; + + /// X86SSELevel - MMX, SSE1, SSE2, SSE3, SSSE3, SSE41, SSE42, or + /// none supported. + X86SSEEnum X86SSELevel; + + /// X863DNowLevel - 3DNow or 3DNow Athlon, or none supported. + /// + X863DNowEnum X863DNowLevel; + + /// HasCMov - True if this processor has conditional move instructions + /// (generally pentium pro+). + bool HasCMov; + + /// HasX86_64 - True if the processor supports X86-64 instructions. + /// + bool HasX86_64; + + /// HasSSE4A - True if the processor supports SSE4A instructions. + bool HasSSE4A; + + /// HasAVX - Target has AVX instructions + bool HasAVX; + + /// HasFMA3 - Target has 3-operand fused multiply-add + bool HasFMA3; + + /// HasFMA4 - Target has 4-operand fused multiply-add + bool HasFMA4; + + /// IsBTMemSlow - True if BT (bit test) of memory instructions are slow. + bool IsBTMemSlow; + + /// DarwinVers - Nonzero if this is a darwin platform: the numeric + /// version of the platform, e.g. 8 = 10.4 (Tiger), 9 = 10.5 (Leopard), etc. + unsigned char DarwinVers; // Is any darwin-x86 platform. + + /// stackAlignment - The minimum alignment known to hold of the stack frame on + /// entry to the function and which must be maintained by every function. + unsigned stackAlignment; + + /// Max. memset / memcpy size that is turned into rep/movs, rep/stos ops. + /// + unsigned MaxInlineSizeThreshold; + +private: + /// Is64Bit - True if the processor supports 64-bit instructions and + /// pointer size is 64 bit. + bool Is64Bit; + +public: + enum { + isELF, isCygwin, isDarwin, isWindows, isMingw + } TargetType; + + /// This constructor initializes the data members to match that + /// of the specified triple. + /// + X86Subtarget(const std::string &TT, const std::string &FS, bool is64Bit); + + /// getStackAlignment - Returns the minimum alignment known to hold of the + /// stack frame on entry to the function and which must be maintained by every + /// function for this subtarget. + unsigned getStackAlignment() const { return stackAlignment; } + + /// getMaxInlineSizeThreshold - Returns the maximum memset / memcpy size + /// that still makes it profitable to inline the call. + unsigned getMaxInlineSizeThreshold() const { return MaxInlineSizeThreshold; } + + /// ParseSubtargetFeatures - Parses features string setting specified + /// subtarget options. Definition of function is auto generated by tblgen. + std::string ParseSubtargetFeatures(const std::string &FS, + const std::string &CPU); + + /// AutoDetectSubtargetFeatures - Auto-detect CPU features using CPUID + /// instruction. + void AutoDetectSubtargetFeatures(); + + bool is64Bit() const { return Is64Bit; } + + PICStyles::Style getPICStyle() const { return PICStyle; } + void setPICStyle(PICStyles::Style Style) { PICStyle = Style; } + + bool hasMMX() const { return X86SSELevel >= MMX; } + bool hasSSE1() const { return X86SSELevel >= SSE1; } + bool hasSSE2() const { return X86SSELevel >= SSE2; } + bool hasSSE3() const { return X86SSELevel >= SSE3; } + bool hasSSSE3() const { return X86SSELevel >= SSSE3; } + bool hasSSE41() const { return X86SSELevel >= SSE41; } + bool hasSSE42() const { return X86SSELevel >= SSE42; } + bool hasSSE4A() const { return HasSSE4A; } + bool has3DNow() const { return X863DNowLevel >= ThreeDNow; } + bool has3DNowA() const { return X863DNowLevel >= ThreeDNowA; } + bool hasAVX() const { return HasAVX; } + bool hasFMA3() const { return HasFMA3; } + bool hasFMA4() const { return HasFMA4; } + bool isBTMemSlow() const { return IsBTMemSlow; } + + bool isTargetDarwin() const { return TargetType == isDarwin; } + bool isTargetELF() const { return TargetType == isELF; } + + bool isTargetWindows() const { return TargetType == isWindows; } + bool isTargetMingw() const { return TargetType == isMingw; } + bool isTargetCygwin() const { return TargetType == isCygwin; } + bool isTargetCygMing() const { + return TargetType == isMingw || TargetType == isCygwin; + } + + /// isTargetCOFF - Return true if this is any COFF/Windows target variant. + bool isTargetCOFF() const { + return TargetType == isMingw || TargetType == isCygwin || + TargetType == isWindows; + } + + bool isTargetWin64() const { + return Is64Bit && (TargetType == isMingw || TargetType == isWindows); + } + + std::string getDataLayout() const { + const char *p; + if (is64Bit()) + p = "e-p:64:64-s:64-f64:64:64-i64:64:64-f80:128:128-n8:16:32:64"; + else if (isTargetDarwin()) + p = "e-p:32:32-f64:32:64-i64:32:64-f80:128:128-n8:16:32"; + else + p = "e-p:32:32-f64:32:64-i64:32:64-f80:32:32-n8:16:32"; + return std::string(p); + } + + bool isPICStyleSet() const { return PICStyle != PICStyles::None; } + bool isPICStyleGOT() const { return PICStyle == PICStyles::GOT; } + bool isPICStyleRIPRel() const { return PICStyle == PICStyles::RIPRel; } + + bool isPICStyleStubPIC() const { + return PICStyle == PICStyles::StubPIC; + } + + bool isPICStyleStubNoDynamic() const { + return PICStyle == PICStyles::StubDynamicNoPIC; + } + bool isPICStyleStubAny() const { + return PICStyle == PICStyles::StubDynamicNoPIC || + PICStyle == PICStyles::StubPIC; } + + /// getDarwinVers - Return the darwin version number, 8 = Tiger, 9 = Leopard, + /// 10 = Snow Leopard, etc. + unsigned getDarwinVers() const { return DarwinVers; } + + /// ClassifyGlobalReference - Classify a global variable reference for the + /// current subtarget according to how we should reference it in a non-pcrel + /// context. + unsigned char ClassifyGlobalReference(const GlobalValue *GV, + const TargetMachine &TM)const; + + /// ClassifyBlockAddressReference - Classify a blockaddress reference for the + /// current subtarget according to how we should reference it in a non-pcrel + /// context. + unsigned char ClassifyBlockAddressReference() const; + + /// IsLegalToCallImmediateAddr - Return true if the subtarget allows calls + /// to immediate address. + bool IsLegalToCallImmediateAddr(const TargetMachine &TM) const; + + /// This function returns the name of a function which has an interface + /// like the non-standard bzero function, if such a function exists on + /// the current subtarget and it is considered prefereable over + /// memset with zero passed as the second argument. Otherwise it + /// returns null. + const char *getBZeroEntry() const; + + /// getSpecialAddressLatency - For targets where it is beneficial to + /// backschedule instructions that compute addresses, return a value + /// indicating the number of scheduling cycles of backscheduling that + /// should be attempted. + unsigned getSpecialAddressLatency() const; + + /// enablePostRAScheduler - X86 target is enabling post-alloc scheduling + /// at 'More' optimization level. + bool enablePostRAScheduler(CodeGenOpt::Level OptLevel, + TargetSubtarget::AntiDepBreakMode& Mode, + RegClassVector& CriticalPathRCs) const; +}; + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/lib/Target/X86/X86TargetMachine.cpp b/libclamav/c++/llvm/lib/Target/X86/X86TargetMachine.cpp new file mode 100644 index 000000000..0cda8bc40 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/X86/X86TargetMachine.cpp @@ -0,0 +1,242 @@ +//===-- X86TargetMachine.cpp - Define TargetMachine for the X86 -----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the X86 specific subclass of TargetMachine. +// +//===----------------------------------------------------------------------===// + +#include "X86MCAsmInfo.h" +#include "X86TargetMachine.h" +#include "X86.h" +#include "llvm/PassManager.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/Support/FormattedStream.h" +#include "llvm/Target/TargetOptions.h" +#include "llvm/Target/TargetRegistry.h" +using namespace llvm; + +static const MCAsmInfo *createMCAsmInfo(const Target &T, StringRef TT) { + Triple TheTriple(TT); + switch (TheTriple.getOS()) { + case Triple::Darwin: + return new X86MCAsmInfoDarwin(TheTriple); + case Triple::MinGW32: + case Triple::MinGW64: + case Triple::Cygwin: + return new X86MCAsmInfoCOFF(TheTriple); + case Triple::Win32: + return new X86WinMCAsmInfo(TheTriple); + default: + return new X86ELFMCAsmInfo(TheTriple); + } +} + +extern "C" void LLVMInitializeX86Target() { + // Register the target. + RegisterTargetMachine X(TheX86_32Target); + RegisterTargetMachine Y(TheX86_64Target); + + // Register the target asm info. + RegisterAsmInfoFn A(TheX86_32Target, createMCAsmInfo); + RegisterAsmInfoFn B(TheX86_64Target, createMCAsmInfo); + + // Register the code emitter. + TargetRegistry::RegisterCodeEmitter(TheX86_32Target, createX86MCCodeEmitter); + TargetRegistry::RegisterCodeEmitter(TheX86_64Target, createX86MCCodeEmitter); +} + + +X86_32TargetMachine::X86_32TargetMachine(const Target &T, const std::string &TT, + const std::string &FS) + : X86TargetMachine(T, TT, FS, false) { +} + + +X86_64TargetMachine::X86_64TargetMachine(const Target &T, const std::string &TT, + const std::string &FS) + : X86TargetMachine(T, TT, FS, true) { +} + +/// X86TargetMachine ctor - Create an X86 target. +/// +X86TargetMachine::X86TargetMachine(const Target &T, const std::string &TT, + const std::string &FS, bool is64Bit) + : LLVMTargetMachine(T, TT), + Subtarget(TT, FS, is64Bit), + DataLayout(Subtarget.getDataLayout()), + FrameInfo(TargetFrameInfo::StackGrowsDown, + Subtarget.getStackAlignment(), + (Subtarget.isTargetWin64() ? -40 : + (Subtarget.is64Bit() ? -8 : -4))), + InstrInfo(*this), JITInfo(*this), TLInfo(*this), ELFWriterInfo(*this) { + DefRelocModel = getRelocationModel(); + + // If no relocation model was picked, default as appropriate for the target. + if (getRelocationModel() == Reloc::Default) { + if (!Subtarget.isTargetDarwin()) + setRelocationModel(Reloc::Static); + else if (Subtarget.is64Bit()) + setRelocationModel(Reloc::PIC_); + else + setRelocationModel(Reloc::DynamicNoPIC); + } + + assert(getRelocationModel() != Reloc::Default && + "Relocation mode not picked"); + + // If no code model is picked, default to small. + if (getCodeModel() == CodeModel::Default) + setCodeModel(CodeModel::Small); + + // ELF and X86-64 don't have a distinct DynamicNoPIC model. DynamicNoPIC + // is defined as a model for code which may be used in static or dynamic + // executables but not necessarily a shared library. On X86-32 we just + // compile in -static mode, in x86-64 we use PIC. + if (getRelocationModel() == Reloc::DynamicNoPIC) { + if (is64Bit) + setRelocationModel(Reloc::PIC_); + else if (!Subtarget.isTargetDarwin()) + setRelocationModel(Reloc::Static); + } + + // If we are on Darwin, disallow static relocation model in X86-64 mode, since + // the Mach-O file format doesn't support it. + if (getRelocationModel() == Reloc::Static && + Subtarget.isTargetDarwin() && + is64Bit) + setRelocationModel(Reloc::PIC_); + + // Determine the PICStyle based on the target selected. + if (getRelocationModel() == Reloc::Static) { + // Unless we're in PIC or DynamicNoPIC mode, set the PIC style to None. + Subtarget.setPICStyle(PICStyles::None); + } else if (Subtarget.isTargetCygMing()) { + Subtarget.setPICStyle(PICStyles::None); + } else if (Subtarget.isTargetDarwin()) { + if (Subtarget.is64Bit()) + Subtarget.setPICStyle(PICStyles::RIPRel); + else if (getRelocationModel() == Reloc::PIC_) + Subtarget.setPICStyle(PICStyles::StubPIC); + else { + assert(getRelocationModel() == Reloc::DynamicNoPIC); + Subtarget.setPICStyle(PICStyles::StubDynamicNoPIC); + } + } else if (Subtarget.isTargetELF()) { + if (Subtarget.is64Bit()) + Subtarget.setPICStyle(PICStyles::RIPRel); + else + Subtarget.setPICStyle(PICStyles::GOT); + } + + // Finally, if we have "none" as our PIC style, force to static mode. + if (Subtarget.getPICStyle() == PICStyles::None) + setRelocationModel(Reloc::Static); +} + +//===----------------------------------------------------------------------===// +// Pass Pipeline Configuration +//===----------------------------------------------------------------------===// + +bool X86TargetMachine::addInstSelector(PassManagerBase &PM, + CodeGenOpt::Level OptLevel) { + // Install an instruction selector. + PM.add(createX86ISelDag(*this, OptLevel)); + + // If we're using Fast-ISel, clean up the mess. + if (EnableFastISel) + PM.add(createDeadMachineInstructionElimPass()); + + // Install a pass to insert x87 FP_REG_KILL instructions, as needed. + PM.add(createX87FPRegKillInserterPass()); + + return false; +} + +bool X86TargetMachine::addPreRegAlloc(PassManagerBase &PM, + CodeGenOpt::Level OptLevel) { + // Calculate and set max stack object alignment early, so we can decide + // whether we will need stack realignment (and thus FP). + PM.add(createX86MaxStackAlignmentCalculatorPass()); + return false; // -print-machineinstr shouldn't print after this. +} + +bool X86TargetMachine::addPostRegAlloc(PassManagerBase &PM, + CodeGenOpt::Level OptLevel) { + PM.add(createX86FloatingPointStackifierPass()); + return true; // -print-machineinstr should print after this. +} + +bool X86TargetMachine::addCodeEmitter(PassManagerBase &PM, + CodeGenOpt::Level OptLevel, + MachineCodeEmitter &MCE) { + // FIXME: Move this to TargetJITInfo! + // On Darwin, do not override 64-bit setting made in X86TargetMachine(). + if (DefRelocModel == Reloc::Default && + (!Subtarget.isTargetDarwin() || !Subtarget.is64Bit())) { + setRelocationModel(Reloc::Static); + Subtarget.setPICStyle(PICStyles::None); + } + + // 64-bit JIT places everything in the same buffer except external functions. + if (Subtarget.is64Bit()) + setCodeModel(CodeModel::Large); + + PM.add(createX86CodeEmitterPass(*this, MCE)); + + return false; +} + +bool X86TargetMachine::addCodeEmitter(PassManagerBase &PM, + CodeGenOpt::Level OptLevel, + JITCodeEmitter &JCE) { + // FIXME: Move this to TargetJITInfo! + // On Darwin, do not override 64-bit setting made in X86TargetMachine(). + if (DefRelocModel == Reloc::Default && + (!Subtarget.isTargetDarwin() || !Subtarget.is64Bit())) { + setRelocationModel(Reloc::Static); + Subtarget.setPICStyle(PICStyles::None); + } + + // 64-bit JIT places everything in the same buffer except external functions. + if (Subtarget.is64Bit()) + setCodeModel(CodeModel::Large); + + PM.add(createX86JITCodeEmitterPass(*this, JCE)); + + return false; +} + +bool X86TargetMachine::addCodeEmitter(PassManagerBase &PM, + CodeGenOpt::Level OptLevel, + ObjectCodeEmitter &OCE) { + PM.add(createX86ObjectCodeEmitterPass(*this, OCE)); + return false; +} + +bool X86TargetMachine::addSimpleCodeEmitter(PassManagerBase &PM, + CodeGenOpt::Level OptLevel, + MachineCodeEmitter &MCE) { + PM.add(createX86CodeEmitterPass(*this, MCE)); + return false; +} + +bool X86TargetMachine::addSimpleCodeEmitter(PassManagerBase &PM, + CodeGenOpt::Level OptLevel, + JITCodeEmitter &JCE) { + PM.add(createX86JITCodeEmitterPass(*this, JCE)); + return false; +} + +bool X86TargetMachine::addSimpleCodeEmitter(PassManagerBase &PM, + CodeGenOpt::Level OptLevel, + ObjectCodeEmitter &OCE) { + PM.add(createX86ObjectCodeEmitterPass(*this, OCE)); + return false; +} diff --git a/libclamav/c++/llvm/lib/Target/X86/X86TargetMachine.h b/libclamav/c++/llvm/lib/Target/X86/X86TargetMachine.h new file mode 100644 index 000000000..b538408e8 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/X86/X86TargetMachine.h @@ -0,0 +1,99 @@ +//===-- X86TargetMachine.h - Define TargetMachine for the X86 ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the X86 specific subclass of TargetMachine. +// +//===----------------------------------------------------------------------===// + +#ifndef X86TARGETMACHINE_H +#define X86TARGETMACHINE_H + +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetFrameInfo.h" +#include "X86.h" +#include "X86ELFWriterInfo.h" +#include "X86InstrInfo.h" +#include "X86JITInfo.h" +#include "X86Subtarget.h" +#include "X86ISelLowering.h" + +namespace llvm { + +class formatted_raw_ostream; + +class X86TargetMachine : public LLVMTargetMachine { + X86Subtarget Subtarget; + const TargetData DataLayout; // Calculates type size & alignment + TargetFrameInfo FrameInfo; + X86InstrInfo InstrInfo; + X86JITInfo JITInfo; + X86TargetLowering TLInfo; + X86ELFWriterInfo ELFWriterInfo; + Reloc::Model DefRelocModel; // Reloc model before it's overridden. + +public: + X86TargetMachine(const Target &T, const std::string &TT, + const std::string &FS, bool is64Bit); + + virtual const X86InstrInfo *getInstrInfo() const { return &InstrInfo; } + virtual const TargetFrameInfo *getFrameInfo() const { return &FrameInfo; } + virtual X86JITInfo *getJITInfo() { return &JITInfo; } + virtual const X86Subtarget *getSubtargetImpl() const{ return &Subtarget; } + virtual X86TargetLowering *getTargetLowering() const { + return const_cast(&TLInfo); + } + virtual const X86RegisterInfo *getRegisterInfo() const { + return &InstrInfo.getRegisterInfo(); + } + virtual const TargetData *getTargetData() const { return &DataLayout; } + virtual const X86ELFWriterInfo *getELFWriterInfo() const { + return Subtarget.isTargetELF() ? &ELFWriterInfo : 0; + } + + // Set up the pass pipeline. + virtual bool addInstSelector(PassManagerBase &PM, CodeGenOpt::Level OptLevel); + virtual bool addPreRegAlloc(PassManagerBase &PM, CodeGenOpt::Level OptLevel); + virtual bool addPostRegAlloc(PassManagerBase &PM, CodeGenOpt::Level OptLevel); + virtual bool addCodeEmitter(PassManagerBase &PM, CodeGenOpt::Level OptLevel, + MachineCodeEmitter &MCE); + virtual bool addCodeEmitter(PassManagerBase &PM, CodeGenOpt::Level OptLevel, + JITCodeEmitter &JCE); + virtual bool addCodeEmitter(PassManagerBase &PM, CodeGenOpt::Level OptLevel, + ObjectCodeEmitter &OCE); + virtual bool addSimpleCodeEmitter(PassManagerBase &PM, + CodeGenOpt::Level OptLevel, + MachineCodeEmitter &MCE); + virtual bool addSimpleCodeEmitter(PassManagerBase &PM, + CodeGenOpt::Level OptLevel, + JITCodeEmitter &JCE); + virtual bool addSimpleCodeEmitter(PassManagerBase &PM, + CodeGenOpt::Level OptLevel, + ObjectCodeEmitter &OCE); +}; + +/// X86_32TargetMachine - X86 32-bit target machine. +/// +class X86_32TargetMachine : public X86TargetMachine { +public: + X86_32TargetMachine(const Target &T, const std::string &M, + const std::string &FS); +}; + +/// X86_64TargetMachine - X86 64-bit target machine. +/// +class X86_64TargetMachine : public X86TargetMachine { +public: + X86_64TargetMachine(const Target &T, const std::string &TT, + const std::string &FS); +}; + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/lib/Target/X86/X86TargetObjectFile.cpp b/libclamav/c++/llvm/lib/Target/X86/X86TargetObjectFile.cpp new file mode 100644 index 000000000..d39b3c432 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/X86/X86TargetObjectFile.cpp @@ -0,0 +1,65 @@ +//===-- llvm/Target/X86/X86TargetObjectFile.cpp - X86 Object Info ---------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "X86TargetObjectFile.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/Support/Mangler.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/CodeGen/MachineModuleInfoImpls.h" +using namespace llvm; + +const MCExpr *X8632_MachoTargetObjectFile:: +getSymbolForDwarfGlobalReference(const GlobalValue *GV, Mangler *Mang, + MachineModuleInfo *MMI, + bool &IsIndirect, bool &IsPCRel) const { + // The mach-o version of this method defaults to returning a stub reference. + IsIndirect = true; + IsPCRel = false; + + + MachineModuleInfoMachO &MachOMMI = + MMI->getObjFileInfo(); + + SmallString<128> Name; + Mang->getNameWithPrefix(Name, GV, true); + Name += "$non_lazy_ptr"; + + // Add information about the stub reference to MachOMMI so that the stub gets + // emitted by the asmprinter. + MCSymbol *Sym = getContext().GetOrCreateSymbol(Name.str()); + const MCSymbol *&StubSym = MachOMMI.getGVStubEntry(Sym); + if (StubSym == 0) { + Name.clear(); + Mang->getNameWithPrefix(Name, GV, false); + StubSym = getContext().GetOrCreateSymbol(Name.str()); + } + + return MCSymbolRefExpr::Create(Sym, getContext()); +} + +const MCExpr *X8664_MachoTargetObjectFile:: +getSymbolForDwarfGlobalReference(const GlobalValue *GV, Mangler *Mang, + MachineModuleInfo *MMI, + bool &IsIndirect, bool &IsPCRel) const { + + // On Darwin/X86-64, we can reference dwarf symbols with foo@GOTPCREL+4, which + // is an indirect pc-relative reference. + IsIndirect = true; + IsPCRel = true; + + SmallString<128> Name; + Mang->getNameWithPrefix(Name, GV, false); + Name += "@GOTPCREL"; + const MCExpr *Res = + MCSymbolRefExpr::Create(Name.str(), getContext()); + const MCExpr *Four = MCConstantExpr::Create(4, getContext()); + return MCBinaryExpr::CreateAdd(Res, Four, getContext()); +} + diff --git a/libclamav/c++/llvm/lib/Target/X86/X86TargetObjectFile.h b/libclamav/c++/llvm/lib/Target/X86/X86TargetObjectFile.h new file mode 100644 index 000000000..377a93bb7 --- /dev/null +++ b/libclamav/c++/llvm/lib/Target/X86/X86TargetObjectFile.h @@ -0,0 +1,40 @@ +//===-- llvm/Target/X86/X86TargetObjectFile.h - X86 Object Info -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TARGET_X86_TARGETOBJECTFILE_H +#define LLVM_TARGET_X86_TARGETOBJECTFILE_H + +#include "llvm/Target/TargetLoweringObjectFile.h" + +namespace llvm { + + /// X8632_MachoTargetObjectFile - This TLOF implementation is used for + /// Darwin/x86-32. + class X8632_MachoTargetObjectFile : public TargetLoweringObjectFileMachO { + public: + + virtual const MCExpr * + getSymbolForDwarfGlobalReference(const GlobalValue *GV, Mangler *Mang, + MachineModuleInfo *MMI, + bool &IsIndirect, bool &IsPCRel) const; + }; + + /// X8664_MachoTargetObjectFile - This TLOF implementation is used for + /// Darwin/x86-64. + class X8664_MachoTargetObjectFile : public TargetLoweringObjectFileMachO { + public: + + virtual const MCExpr * + getSymbolForDwarfGlobalReference(const GlobalValue *GV, Mangler *Mang, + MachineModuleInfo *MMI, + bool &IsIndirect, bool &IsPCRel) const; + }; +} // end namespace llvm + +#endif diff --git a/libclamav/c++/llvm/lib/Transforms/Hello/CMakeLists.txt b/libclamav/c++/llvm/lib/Transforms/Hello/CMakeLists.txt new file mode 100644 index 000000000..917b74562 --- /dev/null +++ b/libclamav/c++/llvm/lib/Transforms/Hello/CMakeLists.txt @@ -0,0 +1,3 @@ +add_llvm_loadable_module( LLVMHello + Hello.cpp + ) diff --git a/libclamav/c++/llvm/lib/Transforms/Hello/Hello.cpp b/libclamav/c++/llvm/lib/Transforms/Hello/Hello.cpp new file mode 100644 index 000000000..91534a754 --- /dev/null +++ b/libclamav/c++/llvm/lib/Transforms/Hello/Hello.cpp @@ -0,0 +1,65 @@ +//===- Hello.cpp - Example code from "Writing an LLVM Pass" ---------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements two versions of the LLVM "Hello World" pass described +// in docs/WritingAnLLVMPass.html +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "hello" +#include "llvm/Pass.h" +#include "llvm/Function.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/ADT/Statistic.h" +using namespace llvm; + +STATISTIC(HelloCounter, "Counts number of functions greeted"); + +namespace { + // Hello - The first implementation, without getAnalysisUsage. + struct Hello : public FunctionPass { + static char ID; // Pass identification, replacement for typeid + Hello() : FunctionPass(&ID) {} + + virtual bool runOnFunction(Function &F) { + HelloCounter++; + errs() << "Hello: "; + errs().write_escaped(F.getName()) << '\n'; + return false; + } + }; +} + +char Hello::ID = 0; +static RegisterPass X("hello", "Hello World Pass"); + +namespace { + // Hello2 - The second implementation with getAnalysisUsage implemented. + struct Hello2 : public FunctionPass { + static char ID; // Pass identification, replacement for typeid + Hello2() : FunctionPass(&ID) {} + + virtual bool runOnFunction(Function &F) { + HelloCounter++; + errs() << "Hello: "; + errs().write_escaped(F.getName()) << '\n'; + return false; + } + + // We don't modify the program, so we preserve all analyses + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + }; + }; +} + +char Hello2::ID = 0; +static RegisterPass +Y("hello2", "Hello World Pass (with getAnalysisUsage implemented)"); diff --git a/libclamav/c++/llvm/lib/Transforms/Hello/Makefile b/libclamav/c++/llvm/lib/Transforms/Hello/Makefile new file mode 100644 index 000000000..c5e75d43a --- /dev/null +++ b/libclamav/c++/llvm/lib/Transforms/Hello/Makefile @@ -0,0 +1,16 @@ +##===- lib/Transforms/Hello/Makefile -----------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LEVEL = ../../.. +LIBRARYNAME = LLVMHello +LOADABLE_MODULE = 1 +USEDLIBS = + +include $(LEVEL)/Makefile.common + diff --git a/libclamav/c++/llvm/lib/Transforms/IPO/ArgumentPromotion.cpp b/libclamav/c++/llvm/lib/Transforms/IPO/ArgumentPromotion.cpp new file mode 100644 index 000000000..dd5a6d868 --- /dev/null +++ b/libclamav/c++/llvm/lib/Transforms/IPO/ArgumentPromotion.cpp @@ -0,0 +1,875 @@ +//===-- ArgumentPromotion.cpp - Promote by-reference arguments ------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This pass promotes "by reference" arguments to be "by value" arguments. In +// practice, this means looking for internal functions that have pointer +// arguments. If it can prove, through the use of alias analysis, that an +// argument is *only* loaded, then it can pass the value into the function +// instead of the address of the value. This can cause recursive simplification +// of code and lead to the elimination of allocas (especially in C++ template +// code like the STL). +// +// This pass also handles aggregate arguments that are passed into a function, +// scalarizing them if the elements of the aggregate are only loaded. Note that +// by default it refuses to scalarize aggregates which would require passing in +// more than three operands to the function, because passing thousands of +// operands for a large array or structure is unprofitable! This limit can be +// configured or disabled, however. +// +// Note that this transformation could also be done for arguments that are only +// stored to (returning the value instead), but does not currently. This case +// would be best handled when and if LLVM begins supporting multiple return +// values from functions. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "argpromotion" +#include "llvm/Transforms/IPO.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Module.h" +#include "llvm/CallGraphSCCPass.h" +#include "llvm/Instructions.h" +#include "llvm/LLVMContext.h" +#include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/Analysis/CallGraph.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Support/CallSite.h" +#include "llvm/Support/CFG.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/ADT/DepthFirstIterator.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/ADT/StringExtras.h" +#include +using namespace llvm; + +STATISTIC(NumArgumentsPromoted , "Number of pointer arguments promoted"); +STATISTIC(NumAggregatesPromoted, "Number of aggregate arguments promoted"); +STATISTIC(NumByValArgsPromoted , "Number of byval arguments promoted"); +STATISTIC(NumArgumentsDead , "Number of dead pointer args eliminated"); + +namespace { + /// ArgPromotion - The 'by reference' to 'by value' argument promotion pass. + /// + struct ArgPromotion : public CallGraphSCCPass { + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.addRequired(); + CallGraphSCCPass::getAnalysisUsage(AU); + } + + virtual bool runOnSCC(std::vector &SCC); + static char ID; // Pass identification, replacement for typeid + explicit ArgPromotion(unsigned maxElements = 3) + : CallGraphSCCPass(&ID), maxElements(maxElements) {} + + /// A vector used to hold the indices of a single GEP instruction + typedef std::vector IndicesVector; + + private: + CallGraphNode *PromoteArguments(CallGraphNode *CGN); + bool isSafeToPromoteArgument(Argument *Arg, bool isByVal) const; + CallGraphNode *DoPromotion(Function *F, + SmallPtrSet &ArgsToPromote, + SmallPtrSet &ByValArgsToTransform); + /// The maximum number of elements to expand, or 0 for unlimited. + unsigned maxElements; + }; +} + +char ArgPromotion::ID = 0; +static RegisterPass +X("argpromotion", "Promote 'by reference' arguments to scalars"); + +Pass *llvm::createArgumentPromotionPass(unsigned maxElements) { + return new ArgPromotion(maxElements); +} + +bool ArgPromotion::runOnSCC(std::vector &SCC) { + bool Changed = false, LocalChange; + + do { // Iterate until we stop promoting from this SCC. + LocalChange = false; + // Attempt to promote arguments from all functions in this SCC. + for (unsigned i = 0, e = SCC.size(); i != e; ++i) + if (CallGraphNode *CGN = PromoteArguments(SCC[i])) { + LocalChange = true; + SCC[i] = CGN; + } + Changed |= LocalChange; // Remember that we changed something. + } while (LocalChange); + + return Changed; +} + +/// PromoteArguments - This method checks the specified function to see if there +/// are any promotable arguments and if it is safe to promote the function (for +/// example, all callers are direct). If safe to promote some arguments, it +/// calls the DoPromotion method. +/// +CallGraphNode *ArgPromotion::PromoteArguments(CallGraphNode *CGN) { + Function *F = CGN->getFunction(); + + // Make sure that it is local to this module. + if (!F || !F->hasLocalLinkage()) return 0; + + // First check: see if there are any pointer arguments! If not, quick exit. + SmallVector, 16> PointerArgs; + unsigned ArgNo = 0; + for (Function::arg_iterator I = F->arg_begin(), E = F->arg_end(); + I != E; ++I, ++ArgNo) + if (isa(I->getType())) + PointerArgs.push_back(std::pair(I, ArgNo)); + if (PointerArgs.empty()) return 0; + + // Second check: make sure that all callers are direct callers. We can't + // transform functions that have indirect callers. + if (F->hasAddressTaken()) + return 0; + + // Check to see which arguments are promotable. If an argument is promotable, + // add it to ArgsToPromote. + SmallPtrSet ArgsToPromote; + SmallPtrSet ByValArgsToTransform; + for (unsigned i = 0; i != PointerArgs.size(); ++i) { + bool isByVal = F->paramHasAttr(PointerArgs[i].second+1, Attribute::ByVal); + + // If this is a byval argument, and if the aggregate type is small, just + // pass the elements, which is always safe. + Argument *PtrArg = PointerArgs[i].first; + if (isByVal) { + const Type *AgTy = cast(PtrArg->getType())->getElementType(); + if (const StructType *STy = dyn_cast(AgTy)) { + if (maxElements > 0 && STy->getNumElements() > maxElements) { + DEBUG(errs() << "argpromotion disable promoting argument '" + << PtrArg->getName() << "' because it would require adding more" + << " than " << maxElements << " arguments to the function.\n"); + } else { + // If all the elements are single-value types, we can promote it. + bool AllSimple = true; + for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) + if (!STy->getElementType(i)->isSingleValueType()) { + AllSimple = false; + break; + } + + // Safe to transform, don't even bother trying to "promote" it. + // Passing the elements as a scalar will allow scalarrepl to hack on + // the new alloca we introduce. + if (AllSimple) { + ByValArgsToTransform.insert(PtrArg); + continue; + } + } + } + } + + // Otherwise, see if we can promote the pointer to its value. + if (isSafeToPromoteArgument(PtrArg, isByVal)) + ArgsToPromote.insert(PtrArg); + } + + // No promotable pointer arguments. + if (ArgsToPromote.empty() && ByValArgsToTransform.empty()) + return 0; + + return DoPromotion(F, ArgsToPromote, ByValArgsToTransform); +} + +/// IsAlwaysValidPointer - Return true if the specified pointer is always legal +/// to load. +static bool IsAlwaysValidPointer(Value *V) { + if (isa(V) || isa(V)) return true; + if (GetElementPtrInst *GEP = dyn_cast(V)) + return IsAlwaysValidPointer(GEP->getOperand(0)); + if (ConstantExpr *CE = dyn_cast(V)) + if (CE->getOpcode() == Instruction::GetElementPtr) + return IsAlwaysValidPointer(CE->getOperand(0)); + + return false; +} + +/// AllCalleesPassInValidPointerForArgument - Return true if we can prove that +/// all callees pass in a valid pointer for the specified function argument. +static bool AllCalleesPassInValidPointerForArgument(Argument *Arg) { + Function *Callee = Arg->getParent(); + + unsigned ArgNo = std::distance(Callee->arg_begin(), + Function::arg_iterator(Arg)); + + // Look at all call sites of the function. At this pointer we know we only + // have direct callees. + for (Value::use_iterator UI = Callee->use_begin(), E = Callee->use_end(); + UI != E; ++UI) { + CallSite CS = CallSite::get(*UI); + assert(CS.getInstruction() && "Should only have direct calls!"); + + if (!IsAlwaysValidPointer(CS.getArgument(ArgNo))) + return false; + } + return true; +} + +/// Returns true if Prefix is a prefix of longer. That means, Longer has a size +/// that is greater than or equal to the size of prefix, and each of the +/// elements in Prefix is the same as the corresponding elements in Longer. +/// +/// This means it also returns true when Prefix and Longer are equal! +static bool IsPrefix(const ArgPromotion::IndicesVector &Prefix, + const ArgPromotion::IndicesVector &Longer) { + if (Prefix.size() > Longer.size()) + return false; + for (unsigned i = 0, e = Prefix.size(); i != e; ++i) + if (Prefix[i] != Longer[i]) + return false; + return true; +} + + +/// Checks if Indices, or a prefix of Indices, is in Set. +static bool PrefixIn(const ArgPromotion::IndicesVector &Indices, + std::set &Set) { + std::set::iterator Low; + Low = Set.upper_bound(Indices); + if (Low != Set.begin()) + Low--; + // Low is now the last element smaller than or equal to Indices. This means + // it points to a prefix of Indices (possibly Indices itself), if such + // prefix exists. + // + // This load is safe if any prefix of its operands is safe to load. + return Low != Set.end() && IsPrefix(*Low, Indices); +} + +/// Mark the given indices (ToMark) as safe in the the given set of indices +/// (Safe). Marking safe usually means adding ToMark to Safe. However, if there +/// is already a prefix of Indices in Safe, Indices are implicitely marked safe +/// already. Furthermore, any indices that Indices is itself a prefix of, are +/// removed from Safe (since they are implicitely safe because of Indices now). +static void MarkIndicesSafe(const ArgPromotion::IndicesVector &ToMark, + std::set &Safe) { + std::set::iterator Low; + Low = Safe.upper_bound(ToMark); + // Guard against the case where Safe is empty + if (Low != Safe.begin()) + Low--; + // Low is now the last element smaller than or equal to Indices. This + // means it points to a prefix of Indices (possibly Indices itself), if + // such prefix exists. + if (Low != Safe.end()) { + if (IsPrefix(*Low, ToMark)) + // If there is already a prefix of these indices (or exactly these + // indices) marked a safe, don't bother adding these indices + return; + + // Increment Low, so we can use it as a "insert before" hint + ++Low; + } + // Insert + Low = Safe.insert(Low, ToMark); + ++Low; + // If there we're a prefix of longer index list(s), remove those + std::set::iterator End = Safe.end(); + while (Low != End && IsPrefix(ToMark, *Low)) { + std::set::iterator Remove = Low; + ++Low; + Safe.erase(Remove); + } +} + +/// isSafeToPromoteArgument - As you might guess from the name of this method, +/// it checks to see if it is both safe and useful to promote the argument. +/// This method limits promotion of aggregates to only promote up to three +/// elements of the aggregate in order to avoid exploding the number of +/// arguments passed in. +bool ArgPromotion::isSafeToPromoteArgument(Argument *Arg, bool isByVal) const { + typedef std::set GEPIndicesSet; + + // Quick exit for unused arguments + if (Arg->use_empty()) + return true; + + // We can only promote this argument if all of the uses are loads, or are GEP + // instructions (with constant indices) that are subsequently loaded. + // + // Promoting the argument causes it to be loaded in the caller + // unconditionally. This is only safe if we can prove that either the load + // would have happened in the callee anyway (ie, there is a load in the entry + // block) or the pointer passed in at every call site is guaranteed to be + // valid. + // In the former case, invalid loads can happen, but would have happened + // anyway, in the latter case, invalid loads won't happen. This prevents us + // from introducing an invalid load that wouldn't have happened in the + // original code. + // + // This set will contain all sets of indices that are loaded in the entry + // block, and thus are safe to unconditionally load in the caller. + GEPIndicesSet SafeToUnconditionallyLoad; + + // This set contains all the sets of indices that we are planning to promote. + // This makes it possible to limit the number of arguments added. + GEPIndicesSet ToPromote; + + // If the pointer is always valid, any load with first index 0 is valid. + if(isByVal || AllCalleesPassInValidPointerForArgument(Arg)) + SafeToUnconditionallyLoad.insert(IndicesVector(1, 0)); + + // First, iterate the entry block and mark loads of (geps of) arguments as + // safe. + BasicBlock *EntryBlock = Arg->getParent()->begin(); + // Declare this here so we can reuse it + IndicesVector Indices; + for (BasicBlock::iterator I = EntryBlock->begin(), E = EntryBlock->end(); + I != E; ++I) + if (LoadInst *LI = dyn_cast(I)) { + Value *V = LI->getPointerOperand(); + if (GetElementPtrInst *GEP = dyn_cast(V)) { + V = GEP->getPointerOperand(); + if (V == Arg) { + // This load actually loads (part of) Arg? Check the indices then. + Indices.reserve(GEP->getNumIndices()); + for (User::op_iterator II = GEP->idx_begin(), IE = GEP->idx_end(); + II != IE; ++II) + if (ConstantInt *CI = dyn_cast(*II)) + Indices.push_back(CI->getSExtValue()); + else + // We found a non-constant GEP index for this argument? Bail out + // right away, can't promote this argument at all. + return false; + + // Indices checked out, mark them as safe + MarkIndicesSafe(Indices, SafeToUnconditionallyLoad); + Indices.clear(); + } + } else if (V == Arg) { + // Direct loads are equivalent to a GEP with a single 0 index. + MarkIndicesSafe(IndicesVector(1, 0), SafeToUnconditionallyLoad); + } + } + + // Now, iterate all uses of the argument to see if there are any uses that are + // not (GEP+)loads, or any (GEP+)loads that are not safe to promote. + SmallVector Loads; + IndicesVector Operands; + for (Value::use_iterator UI = Arg->use_begin(), E = Arg->use_end(); + UI != E; ++UI) { + Operands.clear(); + if (LoadInst *LI = dyn_cast(*UI)) { + if (LI->isVolatile()) return false; // Don't hack volatile loads + Loads.push_back(LI); + // Direct loads are equivalent to a GEP with a zero index and then a load. + Operands.push_back(0); + } else if (GetElementPtrInst *GEP = dyn_cast(*UI)) { + if (GEP->use_empty()) { + // Dead GEP's cause trouble later. Just remove them if we run into + // them. + getAnalysis().deleteValue(GEP); + GEP->eraseFromParent(); + // TODO: This runs the above loop over and over again for dead GEPS + // Couldn't we just do increment the UI iterator earlier and erase the + // use? + return isSafeToPromoteArgument(Arg, isByVal); + } + + // Ensure that all of the indices are constants. + for (User::op_iterator i = GEP->idx_begin(), e = GEP->idx_end(); + i != e; ++i) + if (ConstantInt *C = dyn_cast(*i)) + Operands.push_back(C->getSExtValue()); + else + return false; // Not a constant operand GEP! + + // Ensure that the only users of the GEP are load instructions. + for (Value::use_iterator UI = GEP->use_begin(), E = GEP->use_end(); + UI != E; ++UI) + if (LoadInst *LI = dyn_cast(*UI)) { + if (LI->isVolatile()) return false; // Don't hack volatile loads + Loads.push_back(LI); + } else { + // Other uses than load? + return false; + } + } else { + return false; // Not a load or a GEP. + } + + // Now, see if it is safe to promote this load / loads of this GEP. Loading + // is safe if Operands, or a prefix of Operands, is marked as safe. + if (!PrefixIn(Operands, SafeToUnconditionallyLoad)) + return false; + + // See if we are already promoting a load with these indices. If not, check + // to make sure that we aren't promoting too many elements. If so, nothing + // to do. + if (ToPromote.find(Operands) == ToPromote.end()) { + if (maxElements > 0 && ToPromote.size() == maxElements) { + DEBUG(errs() << "argpromotion not promoting argument '" + << Arg->getName() << "' because it would require adding more " + << "than " << maxElements << " arguments to the function.\n"); + // We limit aggregate promotion to only promoting up to a fixed number + // of elements of the aggregate. + return false; + } + ToPromote.insert(Operands); + } + } + + if (Loads.empty()) return true; // No users, this is a dead argument. + + // Okay, now we know that the argument is only used by load instructions and + // it is safe to unconditionally perform all of them. Use alias analysis to + // check to see if the pointer is guaranteed to not be modified from entry of + // the function to each of the load instructions. + + // Because there could be several/many load instructions, remember which + // blocks we know to be transparent to the load. + SmallPtrSet TranspBlocks; + + AliasAnalysis &AA = getAnalysis(); + TargetData *TD = getAnalysisIfAvailable(); + if (!TD) return false; // Without TargetData, assume the worst. + + for (unsigned i = 0, e = Loads.size(); i != e; ++i) { + // Check to see if the load is invalidated from the start of the block to + // the load itself. + LoadInst *Load = Loads[i]; + BasicBlock *BB = Load->getParent(); + + const PointerType *LoadTy = + cast(Load->getPointerOperand()->getType()); + unsigned LoadSize =(unsigned)TD->getTypeStoreSize(LoadTy->getElementType()); + + if (AA.canInstructionRangeModify(BB->front(), *Load, Arg, LoadSize)) + return false; // Pointer is invalidated! + + // Now check every path from the entry block to the load for transparency. + // To do this, we perform a depth first search on the inverse CFG from the + // loading block. + for (pred_iterator PI = pred_begin(BB), E = pred_end(BB); PI != E; ++PI) + for (idf_ext_iterator > + I = idf_ext_begin(*PI, TranspBlocks), + E = idf_ext_end(*PI, TranspBlocks); I != E; ++I) + if (AA.canBasicBlockModify(**I, Arg, LoadSize)) + return false; + } + + // If the path from the entry of the function to each load is free of + // instructions that potentially invalidate the load, we can make the + // transformation! + return true; +} + +/// DoPromotion - This method actually performs the promotion of the specified +/// arguments, and returns the new function. At this point, we know that it's +/// safe to do so. +CallGraphNode *ArgPromotion::DoPromotion(Function *F, + SmallPtrSet &ArgsToPromote, + SmallPtrSet &ByValArgsToTransform) { + + // Start by computing a new prototype for the function, which is the same as + // the old function, but has modified arguments. + const FunctionType *FTy = F->getFunctionType(); + std::vector Params; + + typedef std::set ScalarizeTable; + + // ScalarizedElements - If we are promoting a pointer that has elements + // accessed out of it, keep track of which elements are accessed so that we + // can add one argument for each. + // + // Arguments that are directly loaded will have a zero element value here, to + // handle cases where there are both a direct load and GEP accesses. + // + std::map ScalarizedElements; + + // OriginalLoads - Keep track of a representative load instruction from the + // original function so that we can tell the alias analysis implementation + // what the new GEP/Load instructions we are inserting look like. + std::map OriginalLoads; + + // Attributes - Keep track of the parameter attributes for the arguments + // that we are *not* promoting. For the ones that we do promote, the parameter + // attributes are lost + SmallVector AttributesVec; + const AttrListPtr &PAL = F->getAttributes(); + + // Add any return attributes. + if (Attributes attrs = PAL.getRetAttributes()) + AttributesVec.push_back(AttributeWithIndex::get(0, attrs)); + + // First, determine the new argument list + unsigned ArgIndex = 1; + for (Function::arg_iterator I = F->arg_begin(), E = F->arg_end(); I != E; + ++I, ++ArgIndex) { + if (ByValArgsToTransform.count(I)) { + // Simple byval argument? Just add all the struct element types. + const Type *AgTy = cast(I->getType())->getElementType(); + const StructType *STy = cast(AgTy); + for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) + Params.push_back(STy->getElementType(i)); + ++NumByValArgsPromoted; + } else if (!ArgsToPromote.count(I)) { + // Unchanged argument + Params.push_back(I->getType()); + if (Attributes attrs = PAL.getParamAttributes(ArgIndex)) + AttributesVec.push_back(AttributeWithIndex::get(Params.size(), attrs)); + } else if (I->use_empty()) { + // Dead argument (which are always marked as promotable) + ++NumArgumentsDead; + } else { + // Okay, this is being promoted. This means that the only uses are loads + // or GEPs which are only used by loads + + // In this table, we will track which indices are loaded from the argument + // (where direct loads are tracked as no indices). + ScalarizeTable &ArgIndices = ScalarizedElements[I]; + for (Value::use_iterator UI = I->use_begin(), E = I->use_end(); UI != E; + ++UI) { + Instruction *User = cast(*UI); + assert(isa(User) || isa(User)); + IndicesVector Indices; + Indices.reserve(User->getNumOperands() - 1); + // Since loads will only have a single operand, and GEPs only a single + // non-index operand, this will record direct loads without any indices, + // and gep+loads with the GEP indices. + for (User::op_iterator II = User->op_begin() + 1, IE = User->op_end(); + II != IE; ++II) + Indices.push_back(cast(*II)->getSExtValue()); + // GEPs with a single 0 index can be merged with direct loads + if (Indices.size() == 1 && Indices.front() == 0) + Indices.clear(); + ArgIndices.insert(Indices); + LoadInst *OrigLoad; + if (LoadInst *L = dyn_cast(User)) + OrigLoad = L; + else + // Take any load, we will use it only to update Alias Analysis + OrigLoad = cast(User->use_back()); + OriginalLoads[Indices] = OrigLoad; + } + + // Add a parameter to the function for each element passed in. + for (ScalarizeTable::iterator SI = ArgIndices.begin(), + E = ArgIndices.end(); SI != E; ++SI) { + // not allowed to dereference ->begin() if size() is 0 + Params.push_back(GetElementPtrInst::getIndexedType(I->getType(), + SI->begin(), + SI->end())); + assert(Params.back()); + } + + if (ArgIndices.size() == 1 && ArgIndices.begin()->empty()) + ++NumArgumentsPromoted; + else + ++NumAggregatesPromoted; + } + } + + // Add any function attributes. + if (Attributes attrs = PAL.getFnAttributes()) + AttributesVec.push_back(AttributeWithIndex::get(~0, attrs)); + + const Type *RetTy = FTy->getReturnType(); + + // Work around LLVM bug PR56: the CWriter cannot emit varargs functions which + // have zero fixed arguments. + bool ExtraArgHack = false; + if (Params.empty() && FTy->isVarArg()) { + ExtraArgHack = true; + Params.push_back(Type::getInt32Ty(F->getContext())); + } + + // Construct the new function type using the new arguments. + FunctionType *NFTy = FunctionType::get(RetTy, Params, FTy->isVarArg()); + + // Create the new function body and insert it into the module. + Function *NF = Function::Create(NFTy, F->getLinkage(), F->getName()); + NF->copyAttributesFrom(F); + + + DEBUG(errs() << "ARG PROMOTION: Promoting to:" << *NF << "\n" + << "From: " << *F); + + // Recompute the parameter attributes list based on the new arguments for + // the function. + NF->setAttributes(AttrListPtr::get(AttributesVec.begin(), + AttributesVec.end())); + AttributesVec.clear(); + + F->getParent()->getFunctionList().insert(F, NF); + NF->takeName(F); + + // Get the alias analysis information that we need to update to reflect our + // changes. + AliasAnalysis &AA = getAnalysis(); + + // Get the callgraph information that we need to update to reflect our + // changes. + CallGraph &CG = getAnalysis(); + + // Get a new callgraph node for NF. + CallGraphNode *NF_CGN = CG.getOrInsertFunction(NF); + + + // Loop over all of the callers of the function, transforming the call sites + // to pass in the loaded pointers. + // + SmallVector Args; + while (!F->use_empty()) { + CallSite CS = CallSite::get(F->use_back()); + Instruction *Call = CS.getInstruction(); + const AttrListPtr &CallPAL = CS.getAttributes(); + + // Add any return attributes. + if (Attributes attrs = CallPAL.getRetAttributes()) + AttributesVec.push_back(AttributeWithIndex::get(0, attrs)); + + // Loop over the operands, inserting GEP and loads in the caller as + // appropriate. + CallSite::arg_iterator AI = CS.arg_begin(); + ArgIndex = 1; + for (Function::arg_iterator I = F->arg_begin(), E = F->arg_end(); + I != E; ++I, ++AI, ++ArgIndex) + if (!ArgsToPromote.count(I) && !ByValArgsToTransform.count(I)) { + Args.push_back(*AI); // Unmodified argument + + if (Attributes Attrs = CallPAL.getParamAttributes(ArgIndex)) + AttributesVec.push_back(AttributeWithIndex::get(Args.size(), Attrs)); + + } else if (ByValArgsToTransform.count(I)) { + // Emit a GEP and load for each element of the struct. + const Type *AgTy = cast(I->getType())->getElementType(); + const StructType *STy = cast(AgTy); + Value *Idxs[2] = { + ConstantInt::get(Type::getInt32Ty(F->getContext()), 0), 0 }; + for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) { + Idxs[1] = ConstantInt::get(Type::getInt32Ty(F->getContext()), i); + Value *Idx = GetElementPtrInst::Create(*AI, Idxs, Idxs+2, + (*AI)->getName()+"."+utostr(i), + Call); + // TODO: Tell AA about the new values? + Args.push_back(new LoadInst(Idx, Idx->getName()+".val", Call)); + } + } else if (!I->use_empty()) { + // Non-dead argument: insert GEPs and loads as appropriate. + ScalarizeTable &ArgIndices = ScalarizedElements[I]; + // Store the Value* version of the indices in here, but declare it now + // for reuse + std::vector Ops; + for (ScalarizeTable::iterator SI = ArgIndices.begin(), + E = ArgIndices.end(); SI != E; ++SI) { + Value *V = *AI; + LoadInst *OrigLoad = OriginalLoads[*SI]; + if (!SI->empty()) { + Ops.reserve(SI->size()); + const Type *ElTy = V->getType(); + for (IndicesVector::const_iterator II = SI->begin(), + IE = SI->end(); II != IE; ++II) { + // Use i32 to index structs, and i64 for others (pointers/arrays). + // This satisfies GEP constraints. + const Type *IdxTy = (isa(ElTy) ? + Type::getInt32Ty(F->getContext()) : + Type::getInt64Ty(F->getContext())); + Ops.push_back(ConstantInt::get(IdxTy, *II)); + // Keep track of the type we're currently indexing + ElTy = cast(ElTy)->getTypeAtIndex(*II); + } + // And create a GEP to extract those indices + V = GetElementPtrInst::Create(V, Ops.begin(), Ops.end(), + V->getName()+".idx", Call); + Ops.clear(); + AA.copyValue(OrigLoad->getOperand(0), V); + } + Args.push_back(new LoadInst(V, V->getName()+".val", Call)); + AA.copyValue(OrigLoad, Args.back()); + } + } + + if (ExtraArgHack) + Args.push_back(Constant::getNullValue(Type::getInt32Ty(F->getContext()))); + + // Push any varargs arguments on the list + for (; AI != CS.arg_end(); ++AI, ++ArgIndex) { + Args.push_back(*AI); + if (Attributes Attrs = CallPAL.getParamAttributes(ArgIndex)) + AttributesVec.push_back(AttributeWithIndex::get(Args.size(), Attrs)); + } + + // Add any function attributes. + if (Attributes attrs = CallPAL.getFnAttributes()) + AttributesVec.push_back(AttributeWithIndex::get(~0, attrs)); + + Instruction *New; + if (InvokeInst *II = dyn_cast(Call)) { + New = InvokeInst::Create(NF, II->getNormalDest(), II->getUnwindDest(), + Args.begin(), Args.end(), "", Call); + cast(New)->setCallingConv(CS.getCallingConv()); + cast(New)->setAttributes(AttrListPtr::get(AttributesVec.begin(), + AttributesVec.end())); + } else { + New = CallInst::Create(NF, Args.begin(), Args.end(), "", Call); + cast(New)->setCallingConv(CS.getCallingConv()); + cast(New)->setAttributes(AttrListPtr::get(AttributesVec.begin(), + AttributesVec.end())); + if (cast(Call)->isTailCall()) + cast(New)->setTailCall(); + } + Args.clear(); + AttributesVec.clear(); + + // Update the alias analysis implementation to know that we are replacing + // the old call with a new one. + AA.replaceWithNewValue(Call, New); + + // Update the callgraph to know that the callsite has been transformed. + CallGraphNode *CalleeNode = CG[Call->getParent()->getParent()]; + CalleeNode->replaceCallEdge(Call, New, NF_CGN); + + if (!Call->use_empty()) { + Call->replaceAllUsesWith(New); + New->takeName(Call); + } + + // Finally, remove the old call from the program, reducing the use-count of + // F. + Call->eraseFromParent(); + } + + // Since we have now created the new function, splice the body of the old + // function right into the new function, leaving the old rotting hulk of the + // function empty. + NF->getBasicBlockList().splice(NF->begin(), F->getBasicBlockList()); + + // Loop over the argument list, transfering uses of the old arguments over to + // the new arguments, also transfering over the names as well. + // + for (Function::arg_iterator I = F->arg_begin(), E = F->arg_end(), + I2 = NF->arg_begin(); I != E; ++I) { + if (!ArgsToPromote.count(I) && !ByValArgsToTransform.count(I)) { + // If this is an unmodified argument, move the name and users over to the + // new version. + I->replaceAllUsesWith(I2); + I2->takeName(I); + AA.replaceWithNewValue(I, I2); + ++I2; + continue; + } + + if (ByValArgsToTransform.count(I)) { + // In the callee, we create an alloca, and store each of the new incoming + // arguments into the alloca. + Instruction *InsertPt = NF->begin()->begin(); + + // Just add all the struct element types. + const Type *AgTy = cast(I->getType())->getElementType(); + Value *TheAlloca = new AllocaInst(AgTy, 0, "", InsertPt); + const StructType *STy = cast(AgTy); + Value *Idxs[2] = { + ConstantInt::get(Type::getInt32Ty(F->getContext()), 0), 0 }; + + for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) { + Idxs[1] = ConstantInt::get(Type::getInt32Ty(F->getContext()), i); + Value *Idx = + GetElementPtrInst::Create(TheAlloca, Idxs, Idxs+2, + TheAlloca->getName()+"."+Twine(i), + InsertPt); + I2->setName(I->getName()+"."+Twine(i)); + new StoreInst(I2++, Idx, InsertPt); + } + + // Anything that used the arg should now use the alloca. + I->replaceAllUsesWith(TheAlloca); + TheAlloca->takeName(I); + AA.replaceWithNewValue(I, TheAlloca); + continue; + } + + if (I->use_empty()) { + AA.deleteValue(I); + continue; + } + + // Otherwise, if we promoted this argument, then all users are load + // instructions (or GEPs with only load users), and all loads should be + // using the new argument that we added. + ScalarizeTable &ArgIndices = ScalarizedElements[I]; + + while (!I->use_empty()) { + if (LoadInst *LI = dyn_cast(I->use_back())) { + assert(ArgIndices.begin()->empty() && + "Load element should sort to front!"); + I2->setName(I->getName()+".val"); + LI->replaceAllUsesWith(I2); + AA.replaceWithNewValue(LI, I2); + LI->eraseFromParent(); + DEBUG(errs() << "*** Promoted load of argument '" << I->getName() + << "' in function '" << F->getName() << "'\n"); + } else { + GetElementPtrInst *GEP = cast(I->use_back()); + IndicesVector Operands; + Operands.reserve(GEP->getNumIndices()); + for (User::op_iterator II = GEP->idx_begin(), IE = GEP->idx_end(); + II != IE; ++II) + Operands.push_back(cast(*II)->getSExtValue()); + + // GEPs with a single 0 index can be merged with direct loads + if (Operands.size() == 1 && Operands.front() == 0) + Operands.clear(); + + Function::arg_iterator TheArg = I2; + for (ScalarizeTable::iterator It = ArgIndices.begin(); + *It != Operands; ++It, ++TheArg) { + assert(It != ArgIndices.end() && "GEP not handled??"); + } + + std::string NewName = I->getName(); + for (unsigned i = 0, e = Operands.size(); i != e; ++i) { + NewName += "." + utostr(Operands[i]); + } + NewName += ".val"; + TheArg->setName(NewName); + + DEBUG(errs() << "*** Promoted agg argument '" << TheArg->getName() + << "' of function '" << NF->getName() << "'\n"); + + // All of the uses must be load instructions. Replace them all with + // the argument specified by ArgNo. + while (!GEP->use_empty()) { + LoadInst *L = cast(GEP->use_back()); + L->replaceAllUsesWith(TheArg); + AA.replaceWithNewValue(L, TheArg); + L->eraseFromParent(); + } + AA.deleteValue(GEP); + GEP->eraseFromParent(); + } + } + + // Increment I2 past all of the arguments added for this promoted pointer. + for (unsigned i = 0, e = ArgIndices.size(); i != e; ++i) + ++I2; + } + + // Notify the alias analysis implementation that we inserted a new argument. + if (ExtraArgHack) + AA.copyValue(Constant::getNullValue(Type::getInt32Ty(F->getContext())), + NF->arg_begin()); + + + // Tell the alias analysis that the old function is about to disappear. + AA.replaceWithNewValue(F, NF); + + + NF_CGN->stealCalledFunctionsFrom(CG[F]); + + // Now that the old function is dead, delete it. + delete CG.removeFunctionFromModule(F); + + return NF_CGN; +} diff --git a/libclamav/c++/llvm/lib/Transforms/IPO/CMakeLists.txt b/libclamav/c++/llvm/lib/Transforms/IPO/CMakeLists.txt new file mode 100644 index 000000000..92bef3bb7 --- /dev/null +++ b/libclamav/c++/llvm/lib/Transforms/IPO/CMakeLists.txt @@ -0,0 +1,25 @@ +add_llvm_library(LLVMipo + ArgumentPromotion.cpp + ConstantMerge.cpp + DeadArgumentElimination.cpp + DeadTypeElimination.cpp + ExtractGV.cpp + FunctionAttrs.cpp + GlobalDCE.cpp + GlobalOpt.cpp + IPConstantPropagation.cpp + IPO.cpp + InlineAlways.cpp + InlineSimple.cpp + Inliner.cpp + Internalize.cpp + LoopExtractor.cpp + LowerSetJmp.cpp + MergeFunctions.cpp + PartialInlining.cpp + PartialSpecialization.cpp + PruneEH.cpp + StripDeadPrototypes.cpp + StripSymbols.cpp + StructRetPromotion.cpp + ) diff --git a/libclamav/c++/llvm/lib/Transforms/IPO/ConstantMerge.cpp b/libclamav/c++/llvm/lib/Transforms/IPO/ConstantMerge.cpp new file mode 100644 index 000000000..497268740 --- /dev/null +++ b/libclamav/c++/llvm/lib/Transforms/IPO/ConstantMerge.cpp @@ -0,0 +1,113 @@ +//===- ConstantMerge.cpp - Merge duplicate global constants ---------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the interface to a pass that merges duplicate global +// constants together into a single constant that is shared. This is useful +// because some passes (ie TraceValues) insert a lot of string constants into +// the program, regardless of whether or not an existing string is available. +// +// Algorithm: ConstantMerge is designed to build up a map of available constants +// and eliminate duplicates when it is initialized. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "constmerge" +#include "llvm/Transforms/IPO.h" +#include "llvm/Module.h" +#include "llvm/Pass.h" +#include "llvm/ADT/Statistic.h" +#include +using namespace llvm; + +STATISTIC(NumMerged, "Number of global constants merged"); + +namespace { + struct ConstantMerge : public ModulePass { + static char ID; // Pass identification, replacement for typeid + ConstantMerge() : ModulePass(&ID) {} + + // run - For this pass, process all of the globals in the module, + // eliminating duplicate constants. + // + bool runOnModule(Module &M); + }; +} + +char ConstantMerge::ID = 0; +static RegisterPass +X("constmerge", "Merge Duplicate Global Constants"); + +ModulePass *llvm::createConstantMergePass() { return new ConstantMerge(); } + +bool ConstantMerge::runOnModule(Module &M) { + // Map unique constant/section pairs to globals. We don't want to merge + // globals in different sections. + std::map, GlobalVariable*> CMap; + + // Replacements - This vector contains a list of replacements to perform. + std::vector > Replacements; + + bool MadeChange = false; + + // Iterate constant merging while we are still making progress. Merging two + // constants together may allow us to merge other constants together if the + // second level constants have initializers which point to the globals that + // were just merged. + while (1) { + // First pass: identify all globals that can be merged together, filling in + // the Replacements vector. We cannot do the replacement in this pass + // because doing so may cause initializers of other globals to be rewritten, + // invalidating the Constant* pointers in CMap. + // + for (Module::global_iterator GVI = M.global_begin(), E = M.global_end(); + GVI != E; ) { + GlobalVariable *GV = GVI++; + + // If this GV is dead, remove it. + GV->removeDeadConstantUsers(); + if (GV->use_empty() && GV->hasLocalLinkage()) { + GV->eraseFromParent(); + continue; + } + + // Only process constants with initializers. + if (GV->isConstant() && GV->hasDefinitiveInitializer()) { + Constant *Init = GV->getInitializer(); + + // Check to see if the initializer is already known. + GlobalVariable *&Slot = CMap[std::make_pair(Init, GV->getSection())]; + + if (Slot == 0) { // Nope, add it to the map. + Slot = GV; + } else if (GV->hasLocalLinkage()) { // Yup, this is a duplicate! + // Make all uses of the duplicate constant use the canonical version. + Replacements.push_back(std::make_pair(GV, Slot)); + } + } + } + + if (Replacements.empty()) + return MadeChange; + CMap.clear(); + + // Now that we have figured out which replacements must be made, do them all + // now. This avoid invalidating the pointers in CMap, which are unneeded + // now. + for (unsigned i = 0, e = Replacements.size(); i != e; ++i) { + // Eliminate any uses of the dead global... + Replacements[i].first->replaceAllUsesWith(Replacements[i].second); + + // Delete the global value from the module... + M.getGlobalList().erase(Replacements[i].first); + } + + NumMerged += Replacements.size(); + Replacements.clear(); + } +} diff --git a/libclamav/c++/llvm/lib/Transforms/IPO/DeadArgumentElimination.cpp b/libclamav/c++/llvm/lib/Transforms/IPO/DeadArgumentElimination.cpp new file mode 100644 index 000000000..a3db8369e --- /dev/null +++ b/libclamav/c++/llvm/lib/Transforms/IPO/DeadArgumentElimination.cpp @@ -0,0 +1,942 @@ +//===-- DeadArgumentElimination.cpp - Eliminate dead arguments ------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This pass deletes dead arguments from internal functions. Dead argument +// elimination removes arguments which are directly dead, as well as arguments +// only passed into function calls as dead arguments of other functions. This +// pass also deletes dead return values in a similar way. +// +// This pass is often useful as a cleanup pass to run after aggressive +// interprocedural passes, which add possibly-dead arguments or return values. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "deadargelim" +#include "llvm/Transforms/IPO.h" +#include "llvm/CallingConv.h" +#include "llvm/Constant.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Instructions.h" +#include "llvm/IntrinsicInst.h" +#include "llvm/LLVMContext.h" +#include "llvm/Module.h" +#include "llvm/Pass.h" +#include "llvm/Support/CallSite.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/ADT/StringExtras.h" +#include +#include +using namespace llvm; + +STATISTIC(NumArgumentsEliminated, "Number of unread args removed"); +STATISTIC(NumRetValsEliminated , "Number of unused return values removed"); + +namespace { + /// DAE - The dead argument elimination pass. + /// + class DAE : public ModulePass { + public: + + /// Struct that represents (part of) either a return value or a function + /// argument. Used so that arguments and return values can be used + /// interchangably. + struct RetOrArg { + RetOrArg(const Function* F, unsigned Idx, bool IsArg) : F(F), Idx(Idx), + IsArg(IsArg) {} + const Function *F; + unsigned Idx; + bool IsArg; + + /// Make RetOrArg comparable, so we can put it into a map. + bool operator<(const RetOrArg &O) const { + if (F != O.F) + return F < O.F; + else if (Idx != O.Idx) + return Idx < O.Idx; + else + return IsArg < O.IsArg; + } + + /// Make RetOrArg comparable, so we can easily iterate the multimap. + bool operator==(const RetOrArg &O) const { + return F == O.F && Idx == O.Idx && IsArg == O.IsArg; + } + + std::string getDescription() const { + return std::string((IsArg ? "Argument #" : "Return value #")) + + utostr(Idx) + " of function " + F->getNameStr(); + } + }; + + /// Liveness enum - During our initial pass over the program, we determine + /// that things are either alive or maybe alive. We don't mark anything + /// explicitly dead (even if we know they are), since anything not alive + /// with no registered uses (in Uses) will never be marked alive and will + /// thus become dead in the end. + enum Liveness { Live, MaybeLive }; + + /// Convenience wrapper + RetOrArg CreateRet(const Function *F, unsigned Idx) { + return RetOrArg(F, Idx, false); + } + /// Convenience wrapper + RetOrArg CreateArg(const Function *F, unsigned Idx) { + return RetOrArg(F, Idx, true); + } + + typedef std::multimap UseMap; + /// This maps a return value or argument to any MaybeLive return values or + /// arguments it uses. This allows the MaybeLive values to be marked live + /// when any of its users is marked live. + /// For example (indices are left out for clarity): + /// - Uses[ret F] = ret G + /// This means that F calls G, and F returns the value returned by G. + /// - Uses[arg F] = ret G + /// This means that some function calls G and passes its result as an + /// argument to F. + /// - Uses[ret F] = arg F + /// This means that F returns one of its own arguments. + /// - Uses[arg F] = arg G + /// This means that G calls F and passes one of its own (G's) arguments + /// directly to F. + UseMap Uses; + + typedef std::set LiveSet; + typedef std::set LiveFuncSet; + + /// This set contains all values that have been determined to be live. + LiveSet LiveValues; + /// This set contains all values that are cannot be changed in any way. + LiveFuncSet LiveFunctions; + + typedef SmallVector UseVector; + + public: + static char ID; // Pass identification, replacement for typeid + DAE() : ModulePass(&ID) {} + bool runOnModule(Module &M); + + virtual bool ShouldHackArguments() const { return false; } + + private: + Liveness MarkIfNotLive(RetOrArg Use, UseVector &MaybeLiveUses); + Liveness SurveyUse(Value::use_iterator U, UseVector &MaybeLiveUses, + unsigned RetValNum = 0); + Liveness SurveyUses(Value *V, UseVector &MaybeLiveUses); + + void SurveyFunction(Function &F); + void MarkValue(const RetOrArg &RA, Liveness L, + const UseVector &MaybeLiveUses); + void MarkLive(const RetOrArg &RA); + void MarkLive(const Function &F); + void PropagateLiveness(const RetOrArg &RA); + bool RemoveDeadStuffFromFunction(Function *F); + bool DeleteDeadVarargs(Function &Fn); + }; +} + + +char DAE::ID = 0; +static RegisterPass +X("deadargelim", "Dead Argument Elimination"); + +namespace { + /// DAH - DeadArgumentHacking pass - Same as dead argument elimination, but + /// deletes arguments to functions which are external. This is only for use + /// by bugpoint. + struct DAH : public DAE { + static char ID; + virtual bool ShouldHackArguments() const { return true; } + }; +} + +char DAH::ID = 0; +static RegisterPass +Y("deadarghaX0r", "Dead Argument Hacking (BUGPOINT USE ONLY; DO NOT USE)"); + +/// createDeadArgEliminationPass - This pass removes arguments from functions +/// which are not used by the body of the function. +/// +ModulePass *llvm::createDeadArgEliminationPass() { return new DAE(); } +ModulePass *llvm::createDeadArgHackingPass() { return new DAH(); } + +/// DeleteDeadVarargs - If this is an function that takes a ... list, and if +/// llvm.vastart is never called, the varargs list is dead for the function. +bool DAE::DeleteDeadVarargs(Function &Fn) { + assert(Fn.getFunctionType()->isVarArg() && "Function isn't varargs!"); + if (Fn.isDeclaration() || !Fn.hasLocalLinkage()) return false; + + // Ensure that the function is only directly called. + if (Fn.hasAddressTaken()) + return false; + + // Okay, we know we can transform this function if safe. Scan its body + // looking for calls to llvm.vastart. + for (Function::iterator BB = Fn.begin(), E = Fn.end(); BB != E; ++BB) { + for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ++I) { + if (IntrinsicInst *II = dyn_cast(I)) { + if (II->getIntrinsicID() == Intrinsic::vastart) + return false; + } + } + } + + // If we get here, there are no calls to llvm.vastart in the function body, + // remove the "..." and adjust all the calls. + + // Start by computing a new prototype for the function, which is the same as + // the old function, but doesn't have isVarArg set. + const FunctionType *FTy = Fn.getFunctionType(); + + std::vector Params(FTy->param_begin(), FTy->param_end()); + FunctionType *NFTy = FunctionType::get(FTy->getReturnType(), + Params, false); + unsigned NumArgs = Params.size(); + + // Create the new function body and insert it into the module... + Function *NF = Function::Create(NFTy, Fn.getLinkage()); + NF->copyAttributesFrom(&Fn); + Fn.getParent()->getFunctionList().insert(&Fn, NF); + NF->takeName(&Fn); + + // Loop over all of the callers of the function, transforming the call sites + // to pass in a smaller number of arguments into the new function. + // + std::vector Args; + while (!Fn.use_empty()) { + CallSite CS = CallSite::get(Fn.use_back()); + Instruction *Call = CS.getInstruction(); + + // Pass all the same arguments. + Args.assign(CS.arg_begin(), CS.arg_begin()+NumArgs); + + // Drop any attributes that were on the vararg arguments. + AttrListPtr PAL = CS.getAttributes(); + if (!PAL.isEmpty() && PAL.getSlot(PAL.getNumSlots() - 1).Index > NumArgs) { + SmallVector AttributesVec; + for (unsigned i = 0; PAL.getSlot(i).Index <= NumArgs; ++i) + AttributesVec.push_back(PAL.getSlot(i)); + if (Attributes FnAttrs = PAL.getFnAttributes()) + AttributesVec.push_back(AttributeWithIndex::get(~0, FnAttrs)); + PAL = AttrListPtr::get(AttributesVec.begin(), AttributesVec.end()); + } + + Instruction *New; + if (InvokeInst *II = dyn_cast(Call)) { + New = InvokeInst::Create(NF, II->getNormalDest(), II->getUnwindDest(), + Args.begin(), Args.end(), "", Call); + cast(New)->setCallingConv(CS.getCallingConv()); + cast(New)->setAttributes(PAL); + } else { + New = CallInst::Create(NF, Args.begin(), Args.end(), "", Call); + cast(New)->setCallingConv(CS.getCallingConv()); + cast(New)->setAttributes(PAL); + if (cast(Call)->isTailCall()) + cast(New)->setTailCall(); + } + Args.clear(); + + if (!Call->use_empty()) + Call->replaceAllUsesWith(New); + + New->takeName(Call); + + // Finally, remove the old call from the program, reducing the use-count of + // F. + Call->eraseFromParent(); + } + + // Since we have now created the new function, splice the body of the old + // function right into the new function, leaving the old rotting hulk of the + // function empty. + NF->getBasicBlockList().splice(NF->begin(), Fn.getBasicBlockList()); + + // Loop over the argument list, transfering uses of the old arguments over to + // the new arguments, also transfering over the names as well. While we're at + // it, remove the dead arguments from the DeadArguments list. + // + for (Function::arg_iterator I = Fn.arg_begin(), E = Fn.arg_end(), + I2 = NF->arg_begin(); I != E; ++I, ++I2) { + // Move the name and users over to the new version. + I->replaceAllUsesWith(I2); + I2->takeName(I); + } + + // Finally, nuke the old function. + Fn.eraseFromParent(); + return true; +} + +/// Convenience function that returns the number of return values. It returns 0 +/// for void functions and 1 for functions not returning a struct. It returns +/// the number of struct elements for functions returning a struct. +static unsigned NumRetVals(const Function *F) { + if (F->getReturnType() == Type::getVoidTy(F->getContext())) + return 0; + else if (const StructType *STy = dyn_cast(F->getReturnType())) + return STy->getNumElements(); + else + return 1; +} + +/// MarkIfNotLive - This checks Use for liveness in LiveValues. If Use is not +/// live, it adds Use to the MaybeLiveUses argument. Returns the determined +/// liveness of Use. +DAE::Liveness DAE::MarkIfNotLive(RetOrArg Use, UseVector &MaybeLiveUses) { + // We're live if our use or its Function is already marked as live. + if (LiveFunctions.count(Use.F) || LiveValues.count(Use)) + return Live; + + // We're maybe live otherwise, but remember that we must become live if + // Use becomes live. + MaybeLiveUses.push_back(Use); + return MaybeLive; +} + + +/// SurveyUse - This looks at a single use of an argument or return value +/// and determines if it should be alive or not. Adds this use to MaybeLiveUses +/// if it causes the used value to become MaybeAlive. +/// +/// RetValNum is the return value number to use when this use is used in a +/// return instruction. This is used in the recursion, you should always leave +/// it at 0. +DAE::Liveness DAE::SurveyUse(Value::use_iterator U, UseVector &MaybeLiveUses, + unsigned RetValNum) { + Value *V = *U; + if (ReturnInst *RI = dyn_cast(V)) { + // The value is returned from a function. It's only live when the + // function's return value is live. We use RetValNum here, for the case + // that U is really a use of an insertvalue instruction that uses the + // orginal Use. + RetOrArg Use = CreateRet(RI->getParent()->getParent(), RetValNum); + // We might be live, depending on the liveness of Use. + return MarkIfNotLive(Use, MaybeLiveUses); + } + if (InsertValueInst *IV = dyn_cast(V)) { + if (U.getOperandNo() != InsertValueInst::getAggregateOperandIndex() + && IV->hasIndices()) + // The use we are examining is inserted into an aggregate. Our liveness + // depends on all uses of that aggregate, but if it is used as a return + // value, only index at which we were inserted counts. + RetValNum = *IV->idx_begin(); + + // Note that if we are used as the aggregate operand to the insertvalue, + // we don't change RetValNum, but do survey all our uses. + + Liveness Result = MaybeLive; + for (Value::use_iterator I = IV->use_begin(), + E = V->use_end(); I != E; ++I) { + Result = SurveyUse(I, MaybeLiveUses, RetValNum); + if (Result == Live) + break; + } + return Result; + } + CallSite CS = CallSite::get(V); + if (CS.getInstruction()) { + Function *F = CS.getCalledFunction(); + if (F) { + // Used in a direct call. + + // Find the argument number. We know for sure that this use is an + // argument, since if it was the function argument this would be an + // indirect call and the we know can't be looking at a value of the + // label type (for the invoke instruction). + unsigned ArgNo = CS.getArgumentNo(U.getOperandNo()); + + if (ArgNo >= F->getFunctionType()->getNumParams()) + // The value is passed in through a vararg! Must be live. + return Live; + + assert(CS.getArgument(ArgNo) + == CS.getInstruction()->getOperand(U.getOperandNo()) + && "Argument is not where we expected it"); + + // Value passed to a normal call. It's only live when the corresponding + // argument to the called function turns out live. + RetOrArg Use = CreateArg(F, ArgNo); + return MarkIfNotLive(Use, MaybeLiveUses); + } + } + // Used in any other way? Value must be live. + return Live; +} + +/// SurveyUses - This looks at all the uses of the given value +/// Returns the Liveness deduced from the uses of this value. +/// +/// Adds all uses that cause the result to be MaybeLive to MaybeLiveRetUses. If +/// the result is Live, MaybeLiveUses might be modified but its content should +/// be ignored (since it might not be complete). +DAE::Liveness DAE::SurveyUses(Value *V, UseVector &MaybeLiveUses) { + // Assume it's dead (which will only hold if there are no uses at all..). + Liveness Result = MaybeLive; + // Check each use. + for (Value::use_iterator I = V->use_begin(), + E = V->use_end(); I != E; ++I) { + Result = SurveyUse(I, MaybeLiveUses); + if (Result == Live) + break; + } + return Result; +} + +// SurveyFunction - This performs the initial survey of the specified function, +// checking out whether or not it uses any of its incoming arguments or whether +// any callers use the return value. This fills in the LiveValues set and Uses +// map. +// +// We consider arguments of non-internal functions to be intrinsically alive as +// well as arguments to functions which have their "address taken". +// +void DAE::SurveyFunction(Function &F) { + unsigned RetCount = NumRetVals(&F); + // Assume all return values are dead + typedef SmallVector RetVals; + RetVals RetValLiveness(RetCount, MaybeLive); + + typedef SmallVector RetUses; + // These vectors map each return value to the uses that make it MaybeLive, so + // we can add those to the Uses map if the return value really turns out to be + // MaybeLive. Initialized to a list of RetCount empty lists. + RetUses MaybeLiveRetUses(RetCount); + + for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB) + if (ReturnInst *RI = dyn_cast(BB->getTerminator())) + if (RI->getNumOperands() != 0 && RI->getOperand(0)->getType() + != F.getFunctionType()->getReturnType()) { + // We don't support old style multiple return values. + MarkLive(F); + return; + } + + if (!F.hasLocalLinkage() && (!ShouldHackArguments() || F.isIntrinsic())) { + MarkLive(F); + return; + } + + DEBUG(errs() << "DAE - Inspecting callers for fn: " << F.getName() << "\n"); + // Keep track of the number of live retvals, so we can skip checks once all + // of them turn out to be live. + unsigned NumLiveRetVals = 0; + const Type *STy = dyn_cast(F.getReturnType()); + // Loop all uses of the function. + for (Value::use_iterator I = F.use_begin(), E = F.use_end(); I != E; ++I) { + // If the function is PASSED IN as an argument, its address has been + // taken. + CallSite CS = CallSite::get(*I); + if (!CS.getInstruction() || !CS.isCallee(I)) { + MarkLive(F); + return; + } + + // If this use is anything other than a call site, the function is alive. + Instruction *TheCall = CS.getInstruction(); + if (!TheCall) { // Not a direct call site? + MarkLive(F); + return; + } + + // If we end up here, we are looking at a direct call to our function. + + // Now, check how our return value(s) is/are used in this caller. Don't + // bother checking return values if all of them are live already. + if (NumLiveRetVals != RetCount) { + if (STy) { + // Check all uses of the return value. + for (Value::use_iterator I = TheCall->use_begin(), + E = TheCall->use_end(); I != E; ++I) { + ExtractValueInst *Ext = dyn_cast(*I); + if (Ext && Ext->hasIndices()) { + // This use uses a part of our return value, survey the uses of + // that part and store the results for this index only. + unsigned Idx = *Ext->idx_begin(); + if (RetValLiveness[Idx] != Live) { + RetValLiveness[Idx] = SurveyUses(Ext, MaybeLiveRetUses[Idx]); + if (RetValLiveness[Idx] == Live) + NumLiveRetVals++; + } + } else { + // Used by something else than extractvalue. Mark all return + // values as live. + for (unsigned i = 0; i != RetCount; ++i ) + RetValLiveness[i] = Live; + NumLiveRetVals = RetCount; + break; + } + } + } else { + // Single return value + RetValLiveness[0] = SurveyUses(TheCall, MaybeLiveRetUses[0]); + if (RetValLiveness[0] == Live) + NumLiveRetVals = RetCount; + } + } + } + + // Now we've inspected all callers, record the liveness of our return values. + for (unsigned i = 0; i != RetCount; ++i) + MarkValue(CreateRet(&F, i), RetValLiveness[i], MaybeLiveRetUses[i]); + + DEBUG(errs() << "DAE - Inspecting args for fn: " << F.getName() << "\n"); + + // Now, check all of our arguments. + unsigned i = 0; + UseVector MaybeLiveArgUses; + for (Function::arg_iterator AI = F.arg_begin(), + E = F.arg_end(); AI != E; ++AI, ++i) { + // See what the effect of this use is (recording any uses that cause + // MaybeLive in MaybeLiveArgUses). + Liveness Result = SurveyUses(AI, MaybeLiveArgUses); + // Mark the result. + MarkValue(CreateArg(&F, i), Result, MaybeLiveArgUses); + // Clear the vector again for the next iteration. + MaybeLiveArgUses.clear(); + } +} + +/// MarkValue - This function marks the liveness of RA depending on L. If L is +/// MaybeLive, it also takes all uses in MaybeLiveUses and records them in Uses, +/// such that RA will be marked live if any use in MaybeLiveUses gets marked +/// live later on. +void DAE::MarkValue(const RetOrArg &RA, Liveness L, + const UseVector &MaybeLiveUses) { + switch (L) { + case Live: MarkLive(RA); break; + case MaybeLive: + { + // Note any uses of this value, so this return value can be + // marked live whenever one of the uses becomes live. + for (UseVector::const_iterator UI = MaybeLiveUses.begin(), + UE = MaybeLiveUses.end(); UI != UE; ++UI) + Uses.insert(std::make_pair(*UI, RA)); + break; + } + } +} + +/// MarkLive - Mark the given Function as alive, meaning that it cannot be +/// changed in any way. Additionally, +/// mark any values that are used as this function's parameters or by its return +/// values (according to Uses) live as well. +void DAE::MarkLive(const Function &F) { + DEBUG(errs() << "DAE - Intrinsically live fn: " << F.getName() << "\n"); + // Mark the function as live. + LiveFunctions.insert(&F); + // Mark all arguments as live. + for (unsigned i = 0, e = F.arg_size(); i != e; ++i) + PropagateLiveness(CreateArg(&F, i)); + // Mark all return values as live. + for (unsigned i = 0, e = NumRetVals(&F); i != e; ++i) + PropagateLiveness(CreateRet(&F, i)); +} + +/// MarkLive - Mark the given return value or argument as live. Additionally, +/// mark any values that are used by this value (according to Uses) live as +/// well. +void DAE::MarkLive(const RetOrArg &RA) { + if (LiveFunctions.count(RA.F)) + return; // Function was already marked Live. + + if (!LiveValues.insert(RA).second) + return; // We were already marked Live. + + DEBUG(errs() << "DAE - Marking " << RA.getDescription() << " live\n"); + PropagateLiveness(RA); +} + +/// PropagateLiveness - Given that RA is a live value, propagate it's liveness +/// to any other values it uses (according to Uses). +void DAE::PropagateLiveness(const RetOrArg &RA) { + // We don't use upper_bound (or equal_range) here, because our recursive call + // to ourselves is likely to cause the upper_bound (which is the first value + // not belonging to RA) to become erased and the iterator invalidated. + UseMap::iterator Begin = Uses.lower_bound(RA); + UseMap::iterator E = Uses.end(); + UseMap::iterator I; + for (I = Begin; I != E && I->first == RA; ++I) + MarkLive(I->second); + + // Erase RA from the Uses map (from the lower bound to wherever we ended up + // after the loop). + Uses.erase(Begin, I); +} + +// RemoveDeadStuffFromFunction - Remove any arguments and return values from F +// that are not in LiveValues. Transform the function and all of the callees of +// the function to not have these arguments and return values. +// +bool DAE::RemoveDeadStuffFromFunction(Function *F) { + // Don't modify fully live functions + if (LiveFunctions.count(F)) + return false; + + // Start by computing a new prototype for the function, which is the same as + // the old function, but has fewer arguments and a different return type. + const FunctionType *FTy = F->getFunctionType(); + std::vector Params; + + // Set up to build a new list of parameter attributes. + SmallVector AttributesVec; + const AttrListPtr &PAL = F->getAttributes(); + + // The existing function return attributes. + Attributes RAttrs = PAL.getRetAttributes(); + Attributes FnAttrs = PAL.getFnAttributes(); + + // Find out the new return value. + + const Type *RetTy = FTy->getReturnType(); + const Type *NRetTy = NULL; + unsigned RetCount = NumRetVals(F); + + // -1 means unused, other numbers are the new index + SmallVector NewRetIdxs(RetCount, -1); + std::vector RetTypes; + if (RetTy == Type::getVoidTy(F->getContext())) { + NRetTy = Type::getVoidTy(F->getContext()); + } else { + const StructType *STy = dyn_cast(RetTy); + if (STy) + // Look at each of the original return values individually. + for (unsigned i = 0; i != RetCount; ++i) { + RetOrArg Ret = CreateRet(F, i); + if (LiveValues.erase(Ret)) { + RetTypes.push_back(STy->getElementType(i)); + NewRetIdxs[i] = RetTypes.size() - 1; + } else { + ++NumRetValsEliminated; + DEBUG(errs() << "DAE - Removing return value " << i << " from " + << F->getName() << "\n"); + } + } + else + // We used to return a single value. + if (LiveValues.erase(CreateRet(F, 0))) { + RetTypes.push_back(RetTy); + NewRetIdxs[0] = 0; + } else { + DEBUG(errs() << "DAE - Removing return value from " << F->getName() + << "\n"); + ++NumRetValsEliminated; + } + if (RetTypes.size() > 1) + // More than one return type? Return a struct with them. Also, if we used + // to return a struct and didn't change the number of return values, + // return a struct again. This prevents changing {something} into + // something and {} into void. + // Make the new struct packed if we used to return a packed struct + // already. + NRetTy = StructType::get(STy->getContext(), RetTypes, STy->isPacked()); + else if (RetTypes.size() == 1) + // One return type? Just a simple value then, but only if we didn't use to + // return a struct with that simple value before. + NRetTy = RetTypes.front(); + else if (RetTypes.size() == 0) + // No return types? Make it void, but only if we didn't use to return {}. + NRetTy = Type::getVoidTy(F->getContext()); + } + + assert(NRetTy && "No new return type found?"); + + // Remove any incompatible attributes, but only if we removed all return + // values. Otherwise, ensure that we don't have any conflicting attributes + // here. Currently, this should not be possible, but special handling might be + // required when new return value attributes are added. + if (NRetTy == Type::getVoidTy(F->getContext())) + RAttrs &= ~Attribute::typeIncompatible(NRetTy); + else + assert((RAttrs & Attribute::typeIncompatible(NRetTy)) == 0 + && "Return attributes no longer compatible?"); + + if (RAttrs) + AttributesVec.push_back(AttributeWithIndex::get(0, RAttrs)); + + // Remember which arguments are still alive. + SmallVector ArgAlive(FTy->getNumParams(), false); + // Construct the new parameter list from non-dead arguments. Also construct + // a new set of parameter attributes to correspond. Skip the first parameter + // attribute, since that belongs to the return value. + unsigned i = 0; + for (Function::arg_iterator I = F->arg_begin(), E = F->arg_end(); + I != E; ++I, ++i) { + RetOrArg Arg = CreateArg(F, i); + if (LiveValues.erase(Arg)) { + Params.push_back(I->getType()); + ArgAlive[i] = true; + + // Get the original parameter attributes (skipping the first one, that is + // for the return value. + if (Attributes Attrs = PAL.getParamAttributes(i + 1)) + AttributesVec.push_back(AttributeWithIndex::get(Params.size(), Attrs)); + } else { + ++NumArgumentsEliminated; + DEBUG(errs() << "DAE - Removing argument " << i << " (" << I->getName() + << ") from " << F->getName() << "\n"); + } + } + + if (FnAttrs != Attribute::None) + AttributesVec.push_back(AttributeWithIndex::get(~0, FnAttrs)); + + // Reconstruct the AttributesList based on the vector we constructed. + AttrListPtr NewPAL = AttrListPtr::get(AttributesVec.begin(), AttributesVec.end()); + + // Work around LLVM bug PR56: the CWriter cannot emit varargs functions which + // have zero fixed arguments. + // + // Note that we apply this hack for a vararg fuction that does not have any + // arguments anymore, but did have them before (so don't bother fixing + // functions that were already broken wrt CWriter). + bool ExtraArgHack = false; + if (Params.empty() && FTy->isVarArg() && FTy->getNumParams() != 0) { + ExtraArgHack = true; + Params.push_back(Type::getInt32Ty(F->getContext())); + } + + // Create the new function type based on the recomputed parameters. + FunctionType *NFTy = FunctionType::get(NRetTy, Params, + FTy->isVarArg()); + + // No change? + if (NFTy == FTy) + return false; + + // Create the new function body and insert it into the module... + Function *NF = Function::Create(NFTy, F->getLinkage()); + NF->copyAttributesFrom(F); + NF->setAttributes(NewPAL); + // Insert the new function before the old function, so we won't be processing + // it again. + F->getParent()->getFunctionList().insert(F, NF); + NF->takeName(F); + + // Loop over all of the callers of the function, transforming the call sites + // to pass in a smaller number of arguments into the new function. + // + std::vector Args; + while (!F->use_empty()) { + CallSite CS = CallSite::get(F->use_back()); + Instruction *Call = CS.getInstruction(); + + AttributesVec.clear(); + const AttrListPtr &CallPAL = CS.getAttributes(); + + // The call return attributes. + Attributes RAttrs = CallPAL.getRetAttributes(); + Attributes FnAttrs = CallPAL.getFnAttributes(); + // Adjust in case the function was changed to return void. + RAttrs &= ~Attribute::typeIncompatible(NF->getReturnType()); + if (RAttrs) + AttributesVec.push_back(AttributeWithIndex::get(0, RAttrs)); + + // Declare these outside of the loops, so we can reuse them for the second + // loop, which loops the varargs. + CallSite::arg_iterator I = CS.arg_begin(); + unsigned i = 0; + // Loop over those operands, corresponding to the normal arguments to the + // original function, and add those that are still alive. + for (unsigned e = FTy->getNumParams(); i != e; ++I, ++i) + if (ArgAlive[i]) { + Args.push_back(*I); + // Get original parameter attributes, but skip return attributes. + if (Attributes Attrs = CallPAL.getParamAttributes(i + 1)) + AttributesVec.push_back(AttributeWithIndex::get(Args.size(), Attrs)); + } + + if (ExtraArgHack) + Args.push_back(UndefValue::get(Type::getInt32Ty(F->getContext()))); + + // Push any varargs arguments on the list. Don't forget their attributes. + for (CallSite::arg_iterator E = CS.arg_end(); I != E; ++I, ++i) { + Args.push_back(*I); + if (Attributes Attrs = CallPAL.getParamAttributes(i + 1)) + AttributesVec.push_back(AttributeWithIndex::get(Args.size(), Attrs)); + } + + if (FnAttrs != Attribute::None) + AttributesVec.push_back(AttributeWithIndex::get(~0, FnAttrs)); + + // Reconstruct the AttributesList based on the vector we constructed. + AttrListPtr NewCallPAL = AttrListPtr::get(AttributesVec.begin(), + AttributesVec.end()); + + Instruction *New; + if (InvokeInst *II = dyn_cast(Call)) { + New = InvokeInst::Create(NF, II->getNormalDest(), II->getUnwindDest(), + Args.begin(), Args.end(), "", Call); + cast(New)->setCallingConv(CS.getCallingConv()); + cast(New)->setAttributes(NewCallPAL); + } else { + New = CallInst::Create(NF, Args.begin(), Args.end(), "", Call); + cast(New)->setCallingConv(CS.getCallingConv()); + cast(New)->setAttributes(NewCallPAL); + if (cast(Call)->isTailCall()) + cast(New)->setTailCall(); + } + Args.clear(); + + if (!Call->use_empty()) { + if (New->getType() == Call->getType()) { + // Return type not changed? Just replace users then. + Call->replaceAllUsesWith(New); + New->takeName(Call); + } else if (New->getType() == Type::getVoidTy(F->getContext())) { + // Our return value has uses, but they will get removed later on. + // Replace by null for now. + Call->replaceAllUsesWith(Constant::getNullValue(Call->getType())); + } else { + assert(isa(RetTy) && + "Return type changed, but not into a void. The old return type" + " must have been a struct!"); + Instruction *InsertPt = Call; + if (InvokeInst *II = dyn_cast(Call)) { + BasicBlock::iterator IP = II->getNormalDest()->begin(); + while (isa(IP)) ++IP; + InsertPt = IP; + } + + // We used to return a struct. Instead of doing smart stuff with all the + // uses of this struct, we will just rebuild it using + // extract/insertvalue chaining and let instcombine clean that up. + // + // Start out building up our return value from undef + Value *RetVal = UndefValue::get(RetTy); + for (unsigned i = 0; i != RetCount; ++i) + if (NewRetIdxs[i] != -1) { + Value *V; + if (RetTypes.size() > 1) + // We are still returning a struct, so extract the value from our + // return value + V = ExtractValueInst::Create(New, NewRetIdxs[i], "newret", + InsertPt); + else + // We are now returning a single element, so just insert that + V = New; + // Insert the value at the old position + RetVal = InsertValueInst::Create(RetVal, V, i, "oldret", InsertPt); + } + // Now, replace all uses of the old call instruction with the return + // struct we built + Call->replaceAllUsesWith(RetVal); + New->takeName(Call); + } + } + + // Finally, remove the old call from the program, reducing the use-count of + // F. + Call->eraseFromParent(); + } + + // Since we have now created the new function, splice the body of the old + // function right into the new function, leaving the old rotting hulk of the + // function empty. + NF->getBasicBlockList().splice(NF->begin(), F->getBasicBlockList()); + + // Loop over the argument list, transfering uses of the old arguments over to + // the new arguments, also transfering over the names as well. + i = 0; + for (Function::arg_iterator I = F->arg_begin(), E = F->arg_end(), + I2 = NF->arg_begin(); I != E; ++I, ++i) + if (ArgAlive[i]) { + // If this is a live argument, move the name and users over to the new + // version. + I->replaceAllUsesWith(I2); + I2->takeName(I); + ++I2; + } else { + // If this argument is dead, replace any uses of it with null constants + // (these are guaranteed to become unused later on). + I->replaceAllUsesWith(Constant::getNullValue(I->getType())); + } + + // If we change the return value of the function we must rewrite any return + // instructions. Check this now. + if (F->getReturnType() != NF->getReturnType()) + for (Function::iterator BB = NF->begin(), E = NF->end(); BB != E; ++BB) + if (ReturnInst *RI = dyn_cast(BB->getTerminator())) { + Value *RetVal; + + if (NFTy->getReturnType() == Type::getVoidTy(F->getContext())) { + RetVal = 0; + } else { + assert (isa(RetTy)); + // The original return value was a struct, insert + // extractvalue/insertvalue chains to extract only the values we need + // to return and insert them into our new result. + // This does generate messy code, but we'll let it to instcombine to + // clean that up. + Value *OldRet = RI->getOperand(0); + // Start out building up our return value from undef + RetVal = UndefValue::get(NRetTy); + for (unsigned i = 0; i != RetCount; ++i) + if (NewRetIdxs[i] != -1) { + ExtractValueInst *EV = ExtractValueInst::Create(OldRet, i, + "oldret", RI); + if (RetTypes.size() > 1) { + // We're still returning a struct, so reinsert the value into + // our new return value at the new index + + RetVal = InsertValueInst::Create(RetVal, EV, NewRetIdxs[i], + "newret", RI); + } else { + // We are now only returning a simple value, so just return the + // extracted value. + RetVal = EV; + } + } + } + // Replace the return instruction with one returning the new return + // value (possibly 0 if we became void). + ReturnInst::Create(F->getContext(), RetVal, RI); + BB->getInstList().erase(RI); + } + + // Now that the old function is dead, delete it. + F->eraseFromParent(); + + return true; +} + +bool DAE::runOnModule(Module &M) { + bool Changed = false; + + // First pass: Do a simple check to see if any functions can have their "..." + // removed. We can do this if they never call va_start. This loop cannot be + // fused with the next loop, because deleting a function invalidates + // information computed while surveying other functions. + DEBUG(errs() << "DAE - Deleting dead varargs\n"); + for (Module::iterator I = M.begin(), E = M.end(); I != E; ) { + Function &F = *I++; + if (F.getFunctionType()->isVarArg()) + Changed |= DeleteDeadVarargs(F); + } + + // Second phase:loop through the module, determining which arguments are live. + // We assume all arguments are dead unless proven otherwise (allowing us to + // determine that dead arguments passed into recursive functions are dead). + // + DEBUG(errs() << "DAE - Determining liveness\n"); + for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) + SurveyFunction(*I); + + // Now, remove all dead arguments and return values from each function in + // turn + for (Module::iterator I = M.begin(), E = M.end(); I != E; ) { + // Increment now, because the function will probably get removed (ie + // replaced by a new one). + Function *F = I++; + Changed |= RemoveDeadStuffFromFunction(F); + } + return Changed; +} diff --git a/libclamav/c++/llvm/lib/Transforms/IPO/DeadTypeElimination.cpp b/libclamav/c++/llvm/lib/Transforms/IPO/DeadTypeElimination.cpp new file mode 100644 index 000000000..025d77e0c --- /dev/null +++ b/libclamav/c++/llvm/lib/Transforms/IPO/DeadTypeElimination.cpp @@ -0,0 +1,106 @@ +//===- DeadTypeElimination.cpp - Eliminate unused types for symbol table --===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This pass is used to cleanup the output of GCC. It eliminate names for types +// that are unused in the entire translation unit, using the FindUsedTypes pass. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "deadtypeelim" +#include "llvm/Transforms/IPO.h" +#include "llvm/Analysis/FindUsedTypes.h" +#include "llvm/Module.h" +#include "llvm/TypeSymbolTable.h" +#include "llvm/DerivedTypes.h" +#include "llvm/ADT/Statistic.h" +using namespace llvm; + +STATISTIC(NumKilled, "Number of unused typenames removed from symtab"); + +namespace { + struct DTE : public ModulePass { + static char ID; // Pass identification, replacement for typeid + DTE() : ModulePass(&ID) {} + + // doPassInitialization - For this pass, it removes global symbol table + // entries for primitive types. These are never used for linking in GCC and + // they make the output uglier to look at, so we nuke them. + // + // Also, initialize instance variables. + // + bool runOnModule(Module &M); + + // getAnalysisUsage - This function needs FindUsedTypes to do its job... + // + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.addRequired(); + } + }; +} + +char DTE::ID = 0; +static RegisterPass X("deadtypeelim", "Dead Type Elimination"); + +ModulePass *llvm::createDeadTypeEliminationPass() { + return new DTE(); +} + + +// ShouldNukeSymtabEntry - Return true if this module level symbol table entry +// should be eliminated. +// +static inline bool ShouldNukeSymtabEntry(const Type *Ty){ + // Nuke all names for primitive types! + if (Ty->isPrimitiveType() || Ty->isInteger()) + return true; + + // Nuke all pointers to primitive types as well... + if (const PointerType *PT = dyn_cast(Ty)) + if (PT->getElementType()->isPrimitiveType() || + PT->getElementType()->isInteger()) + return true; + + return false; +} + +// run - For this pass, it removes global symbol table entries for primitive +// types. These are never used for linking in GCC and they make the output +// uglier to look at, so we nuke them. Also eliminate types that are never used +// in the entire program as indicated by FindUsedTypes. +// +bool DTE::runOnModule(Module &M) { + bool Changed = false; + + TypeSymbolTable &ST = M.getTypeSymbolTable(); + std::set UsedTypes = getAnalysis().getTypes(); + + // Check the symbol table for superfluous type entries... + // + // Grab the 'type' plane of the module symbol... + TypeSymbolTable::iterator TI = ST.begin(); + TypeSymbolTable::iterator TE = ST.end(); + while ( TI != TE ) { + // If this entry should be unconditionally removed, or if we detect that + // the type is not used, remove it. + const Type *RHS = TI->second; + if (ShouldNukeSymtabEntry(RHS) || !UsedTypes.count(RHS)) { + ST.remove(TI++); + ++NumKilled; + Changed = true; + } else { + ++TI; + // We only need to leave one name for each type. + UsedTypes.erase(RHS); + } + } + + return Changed; +} + +// vim: sw=2 diff --git a/libclamav/c++/llvm/lib/Transforms/IPO/ExtractGV.cpp b/libclamav/c++/llvm/lib/Transforms/IPO/ExtractGV.cpp new file mode 100644 index 000000000..7f67e48ad --- /dev/null +++ b/libclamav/c++/llvm/lib/Transforms/IPO/ExtractGV.cpp @@ -0,0 +1,175 @@ +//===-- ExtractGV.cpp - Global Value extraction pass ----------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This pass extracts global values +// +//===----------------------------------------------------------------------===// + +#include "llvm/Instructions.h" +#include "llvm/LLVMContext.h" +#include "llvm/Module.h" +#include "llvm/Pass.h" +#include "llvm/Constants.h" +#include "llvm/Transforms/IPO.h" +#include +using namespace llvm; + +namespace { + /// @brief A pass to extract specific functions and their dependencies. + class GVExtractorPass : public ModulePass { + std::vector Named; + bool deleteStuff; + bool reLink; + public: + static char ID; // Pass identification, replacement for typeid + + /// FunctionExtractorPass - If deleteFn is true, this pass deletes as the + /// specified function. Otherwise, it deletes as much of the module as + /// possible, except for the function specified. + /// + explicit GVExtractorPass(std::vector& GVs, bool deleteS = true, + bool relinkCallees = false) + : ModulePass(&ID), Named(GVs), deleteStuff(deleteS), + reLink(relinkCallees) {} + + bool runOnModule(Module &M) { + if (Named.size() == 0) { + return false; // Nothing to extract + } + + + if (deleteStuff) + return deleteGV(); + M.setModuleInlineAsm(""); + return isolateGV(M); + } + + bool deleteGV() { + for (std::vector::iterator GI = Named.begin(), + GE = Named.end(); GI != GE; ++GI) { + if (Function* NamedFunc = dyn_cast(*GI)) { + // If we're in relinking mode, set linkage of all internal callees to + // external. This will allow us extract function, and then - link + // everything together + if (reLink) { + for (Function::iterator B = NamedFunc->begin(), BE = NamedFunc->end(); + B != BE; ++B) { + for (BasicBlock::iterator I = B->begin(), E = B->end(); + I != E; ++I) { + if (CallInst* callInst = dyn_cast(&*I)) { + Function* Callee = callInst->getCalledFunction(); + if (Callee && Callee->hasLocalLinkage()) + Callee->setLinkage(GlobalValue::ExternalLinkage); + } + } + } + } + + NamedFunc->setLinkage(GlobalValue::ExternalLinkage); + NamedFunc->deleteBody(); + assert(NamedFunc->isDeclaration() && "This didn't make the function external!"); + } else { + if (!(*GI)->isDeclaration()) { + cast(*GI)->setInitializer(0); //clear the initializer + (*GI)->setLinkage(GlobalValue::ExternalLinkage); + } + } + } + return true; + } + + bool isolateGV(Module &M) { + // Mark all globals internal + // FIXME: what should we do with private linkage? + for (Module::global_iterator I = M.global_begin(), E = M.global_end(); I != E; ++I) + if (!I->isDeclaration()) { + I->setLinkage(GlobalValue::InternalLinkage); + } + for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) + if (!I->isDeclaration()) { + I->setLinkage(GlobalValue::InternalLinkage); + } + + // Make sure our result is globally accessible... + // by putting them in the used array + { + std::vector AUGs; + const Type *SBP= + Type::getInt8PtrTy(M.getContext()); + for (std::vector::iterator GI = Named.begin(), + GE = Named.end(); GI != GE; ++GI) { + (*GI)->setLinkage(GlobalValue::ExternalLinkage); + AUGs.push_back(ConstantExpr::getBitCast(*GI, SBP)); + } + ArrayType *AT = ArrayType::get(SBP, AUGs.size()); + Constant *Init = ConstantArray::get(AT, AUGs); + GlobalValue *gv = new GlobalVariable(M, AT, false, + GlobalValue::AppendingLinkage, + Init, "llvm.used"); + gv->setSection("llvm.metadata"); + } + + // All of the functions may be used by global variables or the named + // globals. Loop through them and create a new, external functions that + // can be "used", instead of ones with bodies. + std::vector NewFunctions; + + Function *Last = --M.end(); // Figure out where the last real fn is. + + for (Module::iterator I = M.begin(); ; ++I) { + if (std::find(Named.begin(), Named.end(), &*I) == Named.end()) { + Function *New = Function::Create(I->getFunctionType(), + GlobalValue::ExternalLinkage); + New->copyAttributesFrom(I); + + // If it's not the named function, delete the body of the function + I->dropAllReferences(); + + M.getFunctionList().push_back(New); + NewFunctions.push_back(New); + New->takeName(I); + } + + if (&*I == Last) break; // Stop after processing the last function + } + + // Now that we have replacements all set up, loop through the module, + // deleting the old functions, replacing them with the newly created + // functions. + if (!NewFunctions.empty()) { + unsigned FuncNum = 0; + Module::iterator I = M.begin(); + do { + if (std::find(Named.begin(), Named.end(), &*I) == Named.end()) { + // Make everything that uses the old function use the new dummy fn + I->replaceAllUsesWith(NewFunctions[FuncNum++]); + + Function *Old = I; + ++I; // Move the iterator to the new function + + // Delete the old function! + M.getFunctionList().erase(Old); + + } else { + ++I; // Skip the function we are extracting + } + } while (&*I != NewFunctions[0]); + } + + return true; + } + }; + + char GVExtractorPass::ID = 0; +} + +ModulePass *llvm::createGVExtractionPass(std::vector& GVs, + bool deleteFn, bool relinkCallees) { + return new GVExtractorPass(GVs, deleteFn, relinkCallees); +} diff --git a/libclamav/c++/llvm/lib/Transforms/IPO/FunctionAttrs.cpp b/libclamav/c++/llvm/lib/Transforms/IPO/FunctionAttrs.cpp new file mode 100644 index 000000000..a16d335ef --- /dev/null +++ b/libclamav/c++/llvm/lib/Transforms/IPO/FunctionAttrs.cpp @@ -0,0 +1,345 @@ +//===- FunctionAttrs.cpp - Pass which marks functions readnone or readonly ===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements a simple interprocedural pass which walks the +// call-graph, looking for functions which do not access or only read +// non-local memory, and marking them readnone/readonly. In addition, +// it marks function arguments (of pointer type) 'nocapture' if a call +// to the function does not create any copies of the pointer value that +// outlive the call. This more or less means that the pointer is only +// dereferenced, and not returned from the function or stored in a global. +// This pass is implemented as a bottom-up traversal of the call-graph. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "functionattrs" +#include "llvm/Transforms/IPO.h" +#include "llvm/CallGraphSCCPass.h" +#include "llvm/GlobalVariable.h" +#include "llvm/IntrinsicInst.h" +#include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/Analysis/CallGraph.h" +#include "llvm/Analysis/CaptureTracking.h" +#include "llvm/Analysis/MemoryBuiltins.h" +#include "llvm/ADT/SmallSet.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/ADT/UniqueVector.h" +#include "llvm/Support/InstIterator.h" +using namespace llvm; + +STATISTIC(NumReadNone, "Number of functions marked readnone"); +STATISTIC(NumReadOnly, "Number of functions marked readonly"); +STATISTIC(NumNoCapture, "Number of arguments marked nocapture"); +STATISTIC(NumNoAlias, "Number of function returns marked noalias"); + +namespace { + struct FunctionAttrs : public CallGraphSCCPass { + static char ID; // Pass identification, replacement for typeid + FunctionAttrs() : CallGraphSCCPass(&ID) {} + + // runOnSCC - Analyze the SCC, performing the transformation if possible. + bool runOnSCC(std::vector &SCC); + + // AddReadAttrs - Deduce readonly/readnone attributes for the SCC. + bool AddReadAttrs(const std::vector &SCC); + + // AddNoCaptureAttrs - Deduce nocapture attributes for the SCC. + bool AddNoCaptureAttrs(const std::vector &SCC); + + // IsFunctionMallocLike - Does this function allocate new memory? + bool IsFunctionMallocLike(Function *F, + SmallPtrSet &) const; + + // AddNoAliasAttrs - Deduce noalias attributes for the SCC. + bool AddNoAliasAttrs(const std::vector &SCC); + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesCFG(); + CallGraphSCCPass::getAnalysisUsage(AU); + } + + bool PointsToLocalMemory(Value *V); + }; +} + +char FunctionAttrs::ID = 0; +static RegisterPass +X("functionattrs", "Deduce function attributes"); + +Pass *llvm::createFunctionAttrsPass() { return new FunctionAttrs(); } + + +/// PointsToLocalMemory - Returns whether the given pointer value points to +/// memory that is local to the function. Global constants are considered +/// local to all functions. +bool FunctionAttrs::PointsToLocalMemory(Value *V) { + V = V->getUnderlyingObject(); + // An alloca instruction defines local memory. + if (isa(V)) + return true; + // A global constant counts as local memory for our purposes. + if (GlobalVariable *GV = dyn_cast(V)) + return GV->isConstant(); + // Could look through phi nodes and selects here, but it doesn't seem + // to be useful in practice. + return false; +} + +/// AddReadAttrs - Deduce readonly/readnone attributes for the SCC. +bool FunctionAttrs::AddReadAttrs(const std::vector &SCC) { + SmallPtrSet SCCNodes; + + // Fill SCCNodes with the elements of the SCC. Used for quickly + // looking up whether a given CallGraphNode is in this SCC. + for (unsigned i = 0, e = SCC.size(); i != e; ++i) + SCCNodes.insert(SCC[i]->getFunction()); + + // Check if any of the functions in the SCC read or write memory. If they + // write memory then they can't be marked readnone or readonly. + bool ReadsMemory = false; + for (unsigned i = 0, e = SCC.size(); i != e; ++i) { + Function *F = SCC[i]->getFunction(); + + if (F == 0) + // External node - may write memory. Just give up. + return false; + + if (F->doesNotAccessMemory()) + // Already perfect! + continue; + + // Definitions with weak linkage may be overridden at linktime with + // something that writes memory, so treat them like declarations. + if (F->isDeclaration() || F->mayBeOverridden()) { + if (!F->onlyReadsMemory()) + // May write memory. Just give up. + return false; + + ReadsMemory = true; + continue; + } + + // Scan the function body for instructions that may read or write memory. + for (inst_iterator II = inst_begin(F), E = inst_end(F); II != E; ++II) { + Instruction *I = &*II; + + // Some instructions can be ignored even if they read or write memory. + // Detect these now, skipping to the next instruction if one is found. + CallSite CS = CallSite::get(I); + if (CS.getInstruction() && CS.getCalledFunction()) { + // Ignore calls to functions in the same SCC. + if (SCCNodes.count(CS.getCalledFunction())) + continue; + } else if (LoadInst *LI = dyn_cast(I)) { + // Ignore loads from local memory. + if (PointsToLocalMemory(LI->getPointerOperand())) + continue; + } else if (StoreInst *SI = dyn_cast(I)) { + // Ignore stores to local memory. + if (PointsToLocalMemory(SI->getPointerOperand())) + continue; + } + + // Any remaining instructions need to be taken seriously! Check if they + // read or write memory. + if (I->mayWriteToMemory()) + // Writes memory. Just give up. + return false; + + if (isMalloc(I)) + // malloc claims not to write memory! PR3754. + return false; + + // If this instruction may read memory, remember that. + ReadsMemory |= I->mayReadFromMemory(); + } + } + + // Success! Functions in this SCC do not access memory, or only read memory. + // Give them the appropriate attribute. + bool MadeChange = false; + for (unsigned i = 0, e = SCC.size(); i != e; ++i) { + Function *F = SCC[i]->getFunction(); + + if (F->doesNotAccessMemory()) + // Already perfect! + continue; + + if (F->onlyReadsMemory() && ReadsMemory) + // No change. + continue; + + MadeChange = true; + + // Clear out any existing attributes. + F->removeAttribute(~0, Attribute::ReadOnly | Attribute::ReadNone); + + // Add in the new attribute. + F->addAttribute(~0, ReadsMemory? Attribute::ReadOnly : Attribute::ReadNone); + + if (ReadsMemory) + ++NumReadOnly; + else + ++NumReadNone; + } + + return MadeChange; +} + +/// AddNoCaptureAttrs - Deduce nocapture attributes for the SCC. +bool FunctionAttrs::AddNoCaptureAttrs(const std::vector &SCC) { + bool Changed = false; + + // Check each function in turn, determining which pointer arguments are not + // captured. + for (unsigned i = 0, e = SCC.size(); i != e; ++i) { + Function *F = SCC[i]->getFunction(); + + if (F == 0) + // External node - skip it; + continue; + + // Definitions with weak linkage may be overridden at linktime with + // something that writes memory, so treat them like declarations. + if (F->isDeclaration() || F->mayBeOverridden()) + continue; + + for (Function::arg_iterator A = F->arg_begin(), E = F->arg_end(); A!=E; ++A) + if (isa(A->getType()) && !A->hasNoCaptureAttr() && + !PointerMayBeCaptured(A, true, /*StoreCaptures=*/false)) { + A->addAttr(Attribute::NoCapture); + ++NumNoCapture; + Changed = true; + } + } + + return Changed; +} + +/// IsFunctionMallocLike - A function is malloc-like if it returns either null +/// or a pointer that doesn't alias any other pointer visible to the caller. +bool FunctionAttrs::IsFunctionMallocLike(Function *F, + SmallPtrSet &SCCNodes) const { + UniqueVector FlowsToReturn; + for (Function::iterator I = F->begin(), E = F->end(); I != E; ++I) + if (ReturnInst *Ret = dyn_cast(I->getTerminator())) + FlowsToReturn.insert(Ret->getReturnValue()); + + for (unsigned i = 0; i != FlowsToReturn.size(); ++i) { + Value *RetVal = FlowsToReturn[i+1]; // UniqueVector[0] is reserved. + + if (Constant *C = dyn_cast(RetVal)) { + if (!C->isNullValue() && !isa(C)) + return false; + + continue; + } + + if (isa(RetVal)) + return false; + + if (Instruction *RVI = dyn_cast(RetVal)) + switch (RVI->getOpcode()) { + // Extend the analysis by looking upwards. + case Instruction::BitCast: + case Instruction::GetElementPtr: + FlowsToReturn.insert(RVI->getOperand(0)); + continue; + case Instruction::Select: { + SelectInst *SI = cast(RVI); + FlowsToReturn.insert(SI->getTrueValue()); + FlowsToReturn.insert(SI->getFalseValue()); + continue; + } + case Instruction::PHI: { + PHINode *PN = cast(RVI); + for (int i = 0, e = PN->getNumIncomingValues(); i != e; ++i) + FlowsToReturn.insert(PN->getIncomingValue(i)); + continue; + } + + // Check whether the pointer came from an allocation. + case Instruction::Alloca: + break; + case Instruction::Call: + case Instruction::Invoke: { + CallSite CS(RVI); + if (CS.paramHasAttr(0, Attribute::NoAlias)) + break; + if (CS.getCalledFunction() && + SCCNodes.count(CS.getCalledFunction())) + break; + } // fall-through + default: + return false; // Did not come from an allocation. + } + + if (PointerMayBeCaptured(RetVal, false, /*StoreCaptures=*/false)) + return false; + } + + return true; +} + +/// AddNoAliasAttrs - Deduce noalias attributes for the SCC. +bool FunctionAttrs::AddNoAliasAttrs(const std::vector &SCC) { + SmallPtrSet SCCNodes; + + // Fill SCCNodes with the elements of the SCC. Used for quickly + // looking up whether a given CallGraphNode is in this SCC. + for (unsigned i = 0, e = SCC.size(); i != e; ++i) + SCCNodes.insert(SCC[i]->getFunction()); + + // Check each function in turn, determining which functions return noalias + // pointers. + for (unsigned i = 0, e = SCC.size(); i != e; ++i) { + Function *F = SCC[i]->getFunction(); + + if (F == 0) + // External node - skip it; + return false; + + // Already noalias. + if (F->doesNotAlias(0)) + continue; + + // Definitions with weak linkage may be overridden at linktime, so + // treat them like declarations. + if (F->isDeclaration() || F->mayBeOverridden()) + return false; + + // We annotate noalias return values, which are only applicable to + // pointer types. + if (!isa(F->getReturnType())) + continue; + + if (!IsFunctionMallocLike(F, SCCNodes)) + return false; + } + + bool MadeChange = false; + for (unsigned i = 0, e = SCC.size(); i != e; ++i) { + Function *F = SCC[i]->getFunction(); + if (F->doesNotAlias(0) || !isa(F->getReturnType())) + continue; + + F->setDoesNotAlias(0); + ++NumNoAlias; + MadeChange = true; + } + + return MadeChange; +} + +bool FunctionAttrs::runOnSCC(std::vector &SCC) { + bool Changed = AddReadAttrs(SCC); + Changed |= AddNoCaptureAttrs(SCC); + Changed |= AddNoAliasAttrs(SCC); + return Changed; +} diff --git a/libclamav/c++/llvm/lib/Transforms/IPO/GlobalDCE.cpp b/libclamav/c++/llvm/lib/Transforms/IPO/GlobalDCE.cpp new file mode 100644 index 000000000..44216a6df --- /dev/null +++ b/libclamav/c++/llvm/lib/Transforms/IPO/GlobalDCE.cpp @@ -0,0 +1,208 @@ +//===-- GlobalDCE.cpp - DCE unreachable internal functions ----------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This transform is designed to eliminate unreachable internal globals from the +// program. It uses an aggressive algorithm, searching out globals that are +// known to be alive. After it finds all of the globals which are needed, it +// deletes whatever is left over. This allows it to delete recursive chunks of +// the program which are unreachable. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "globaldce" +#include "llvm/Transforms/IPO.h" +#include "llvm/Constants.h" +#include "llvm/Module.h" +#include "llvm/Pass.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/Statistic.h" +using namespace llvm; + +STATISTIC(NumAliases , "Number of global aliases removed"); +STATISTIC(NumFunctions, "Number of functions removed"); +STATISTIC(NumVariables, "Number of global variables removed"); + +namespace { + struct GlobalDCE : public ModulePass { + static char ID; // Pass identification, replacement for typeid + GlobalDCE() : ModulePass(&ID) {} + + // run - Do the GlobalDCE pass on the specified module, optionally updating + // the specified callgraph to reflect the changes. + // + bool runOnModule(Module &M); + + private: + SmallPtrSet AliveGlobals; + + /// GlobalIsNeeded - mark the specific global value as needed, and + /// recursively mark anything that it uses as also needed. + void GlobalIsNeeded(GlobalValue *GV); + void MarkUsedGlobalsAsNeeded(Constant *C); + + bool RemoveUnusedGlobalValue(GlobalValue &GV); + }; +} + +char GlobalDCE::ID = 0; +static RegisterPass X("globaldce", "Dead Global Elimination"); + +ModulePass *llvm::createGlobalDCEPass() { return new GlobalDCE(); } + +bool GlobalDCE::runOnModule(Module &M) { + bool Changed = false; + + // Loop over the module, adding globals which are obviously necessary. + for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) { + Changed |= RemoveUnusedGlobalValue(*I); + // Functions with external linkage are needed if they have a body + if (!I->hasLocalLinkage() && !I->hasLinkOnceLinkage() && + !I->isDeclaration() && !I->hasAvailableExternallyLinkage()) + GlobalIsNeeded(I); + } + + for (Module::global_iterator I = M.global_begin(), E = M.global_end(); + I != E; ++I) { + Changed |= RemoveUnusedGlobalValue(*I); + // Externally visible & appending globals are needed, if they have an + // initializer. + if (!I->hasLocalLinkage() && !I->hasLinkOnceLinkage() && + !I->isDeclaration() && !I->hasAvailableExternallyLinkage()) + GlobalIsNeeded(I); + } + + for (Module::alias_iterator I = M.alias_begin(), E = M.alias_end(); + I != E; ++I) { + Changed |= RemoveUnusedGlobalValue(*I); + // Externally visible aliases are needed. + if (!I->hasLocalLinkage() && !I->hasLinkOnceLinkage()) + GlobalIsNeeded(I); + } + + // Now that all globals which are needed are in the AliveGlobals set, we loop + // through the program, deleting those which are not alive. + // + + // The first pass is to drop initializers of global variables which are dead. + std::vector DeadGlobalVars; // Keep track of dead globals + for (Module::global_iterator I = M.global_begin(), E = M.global_end(); + I != E; ++I) + if (!AliveGlobals.count(I)) { + DeadGlobalVars.push_back(I); // Keep track of dead globals + I->setInitializer(0); + } + + // The second pass drops the bodies of functions which are dead... + std::vector DeadFunctions; + for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) + if (!AliveGlobals.count(I)) { + DeadFunctions.push_back(I); // Keep track of dead globals + if (!I->isDeclaration()) + I->deleteBody(); + } + + // The third pass drops targets of aliases which are dead... + std::vector DeadAliases; + for (Module::alias_iterator I = M.alias_begin(), E = M.alias_end(); I != E; + ++I) + if (!AliveGlobals.count(I)) { + DeadAliases.push_back(I); + I->setAliasee(0); + } + + if (!DeadFunctions.empty()) { + // Now that all interferences have been dropped, delete the actual objects + // themselves. + for (unsigned i = 0, e = DeadFunctions.size(); i != e; ++i) { + RemoveUnusedGlobalValue(*DeadFunctions[i]); + M.getFunctionList().erase(DeadFunctions[i]); + } + NumFunctions += DeadFunctions.size(); + Changed = true; + } + + if (!DeadGlobalVars.empty()) { + for (unsigned i = 0, e = DeadGlobalVars.size(); i != e; ++i) { + RemoveUnusedGlobalValue(*DeadGlobalVars[i]); + M.getGlobalList().erase(DeadGlobalVars[i]); + } + NumVariables += DeadGlobalVars.size(); + Changed = true; + } + + // Now delete any dead aliases. + if (!DeadAliases.empty()) { + for (unsigned i = 0, e = DeadAliases.size(); i != e; ++i) { + RemoveUnusedGlobalValue(*DeadAliases[i]); + M.getAliasList().erase(DeadAliases[i]); + } + NumAliases += DeadAliases.size(); + Changed = true; + } + + // Make sure that all memory is released + AliveGlobals.clear(); + + return Changed; +} + +/// GlobalIsNeeded - the specific global value as needed, and +/// recursively mark anything that it uses as also needed. +void GlobalDCE::GlobalIsNeeded(GlobalValue *G) { + // If the global is already in the set, no need to reprocess it. + if (!AliveGlobals.insert(G)) + return; + + if (GlobalVariable *GV = dyn_cast(G)) { + // If this is a global variable, we must make sure to add any global values + // referenced by the initializer to the alive set. + if (GV->hasInitializer()) + MarkUsedGlobalsAsNeeded(GV->getInitializer()); + } else if (GlobalAlias *GA = dyn_cast(G)) { + // The target of a global alias is needed. + MarkUsedGlobalsAsNeeded(GA->getAliasee()); + } else { + // Otherwise this must be a function object. We have to scan the body of + // the function looking for constants and global values which are used as + // operands. Any operands of these types must be processed to ensure that + // any globals used will be marked as needed. + Function *F = cast(G); + + for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) + for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ++I) + for (User::op_iterator U = I->op_begin(), E = I->op_end(); U != E; ++U) + if (GlobalValue *GV = dyn_cast(*U)) + GlobalIsNeeded(GV); + else if (Constant *C = dyn_cast(*U)) + MarkUsedGlobalsAsNeeded(C); + } +} + +void GlobalDCE::MarkUsedGlobalsAsNeeded(Constant *C) { + if (GlobalValue *GV = dyn_cast(C)) + return GlobalIsNeeded(GV); + + // Loop over all of the operands of the constant, adding any globals they + // use to the list of needed globals. + for (User::op_iterator I = C->op_begin(), E = C->op_end(); I != E; ++I) + if (Constant *OpC = dyn_cast(*I)) + MarkUsedGlobalsAsNeeded(OpC); +} + +// RemoveUnusedGlobalValue - Loop over all of the uses of the specified +// GlobalValue, looking for the constant pointer ref that may be pointing to it. +// If found, check to see if the constant pointer ref is safe to destroy, and if +// so, nuke it. This will reduce the reference count on the global value, which +// might make it deader. +// +bool GlobalDCE::RemoveUnusedGlobalValue(GlobalValue &GV) { + if (GV.use_empty()) return false; + GV.removeDeadConstantUsers(); + return GV.use_empty(); +} diff --git a/libclamav/c++/llvm/lib/Transforms/IPO/GlobalOpt.cpp b/libclamav/c++/llvm/lib/Transforms/IPO/GlobalOpt.cpp new file mode 100644 index 000000000..4635d0e61 --- /dev/null +++ b/libclamav/c++/llvm/lib/Transforms/IPO/GlobalOpt.cpp @@ -0,0 +1,2558 @@ +//===- GlobalOpt.cpp - Optimize Global Variables --------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This pass transforms simple global variables that never have their address +// taken. If obviously true, it marks read/write globals as constant, deletes +// variables only stored to, etc. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "globalopt" +#include "llvm/Transforms/IPO.h" +#include "llvm/CallingConv.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Instructions.h" +#include "llvm/IntrinsicInst.h" +#include "llvm/Module.h" +#include "llvm/Pass.h" +#include "llvm/Analysis/ConstantFolding.h" +#include "llvm/Analysis/MemoryBuiltins.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Support/CallSite.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/GetElementPtrTypeIterator.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/ADT/STLExtras.h" +#include +using namespace llvm; + +STATISTIC(NumMarked , "Number of globals marked constant"); +STATISTIC(NumSRA , "Number of aggregate globals broken into scalars"); +STATISTIC(NumHeapSRA , "Number of heap objects SRA'd"); +STATISTIC(NumSubstitute,"Number of globals with initializers stored into them"); +STATISTIC(NumDeleted , "Number of globals deleted"); +STATISTIC(NumFnDeleted , "Number of functions deleted"); +STATISTIC(NumGlobUses , "Number of global uses devirtualized"); +STATISTIC(NumLocalized , "Number of globals localized"); +STATISTIC(NumShrunkToBool , "Number of global vars shrunk to booleans"); +STATISTIC(NumFastCallFns , "Number of functions converted to fastcc"); +STATISTIC(NumCtorsEvaluated, "Number of static ctors evaluated"); +STATISTIC(NumNestRemoved , "Number of nest attributes removed"); +STATISTIC(NumAliasesResolved, "Number of global aliases resolved"); +STATISTIC(NumAliasesRemoved, "Number of global aliases eliminated"); + +namespace { + struct GlobalOpt : public ModulePass { + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + } + static char ID; // Pass identification, replacement for typeid + GlobalOpt() : ModulePass(&ID) {} + + bool runOnModule(Module &M); + + private: + GlobalVariable *FindGlobalCtors(Module &M); + bool OptimizeFunctions(Module &M); + bool OptimizeGlobalVars(Module &M); + bool OptimizeGlobalAliases(Module &M); + bool OptimizeGlobalCtorsList(GlobalVariable *&GCL); + bool ProcessInternalGlobal(GlobalVariable *GV,Module::global_iterator &GVI); + }; +} + +char GlobalOpt::ID = 0; +static RegisterPass X("globalopt", "Global Variable Optimizer"); + +ModulePass *llvm::createGlobalOptimizerPass() { return new GlobalOpt(); } + +namespace { + +/// GlobalStatus - As we analyze each global, keep track of some information +/// about it. If we find out that the address of the global is taken, none of +/// this info will be accurate. +struct GlobalStatus { + /// isLoaded - True if the global is ever loaded. If the global isn't ever + /// loaded it can be deleted. + bool isLoaded; + + /// StoredType - Keep track of what stores to the global look like. + /// + enum StoredType { + /// NotStored - There is no store to this global. It can thus be marked + /// constant. + NotStored, + + /// isInitializerStored - This global is stored to, but the only thing + /// stored is the constant it was initialized with. This is only tracked + /// for scalar globals. + isInitializerStored, + + /// isStoredOnce - This global is stored to, but only its initializer and + /// one other value is ever stored to it. If this global isStoredOnce, we + /// track the value stored to it in StoredOnceValue below. This is only + /// tracked for scalar globals. + isStoredOnce, + + /// isStored - This global is stored to by multiple values or something else + /// that we cannot track. + isStored + } StoredType; + + /// StoredOnceValue - If only one value (besides the initializer constant) is + /// ever stored to this global, keep track of what value it is. + Value *StoredOnceValue; + + /// AccessingFunction/HasMultipleAccessingFunctions - These start out + /// null/false. When the first accessing function is noticed, it is recorded. + /// When a second different accessing function is noticed, + /// HasMultipleAccessingFunctions is set to true. + Function *AccessingFunction; + bool HasMultipleAccessingFunctions; + + /// HasNonInstructionUser - Set to true if this global has a user that is not + /// an instruction (e.g. a constant expr or GV initializer). + bool HasNonInstructionUser; + + /// HasPHIUser - Set to true if this global has a user that is a PHI node. + bool HasPHIUser; + + GlobalStatus() : isLoaded(false), StoredType(NotStored), StoredOnceValue(0), + AccessingFunction(0), HasMultipleAccessingFunctions(false), + HasNonInstructionUser(false), HasPHIUser(false) {} +}; + +} + +// SafeToDestroyConstant - It is safe to destroy a constant iff it is only used +// by constants itself. Note that constants cannot be cyclic, so this test is +// pretty easy to implement recursively. +// +static bool SafeToDestroyConstant(Constant *C) { + if (isa(C)) return false; + + for (Value::use_iterator UI = C->use_begin(), E = C->use_end(); UI != E; ++UI) + if (Constant *CU = dyn_cast(*UI)) { + if (!SafeToDestroyConstant(CU)) return false; + } else + return false; + return true; +} + + +/// AnalyzeGlobal - Look at all uses of the global and fill in the GlobalStatus +/// structure. If the global has its address taken, return true to indicate we +/// can't do anything with it. +/// +static bool AnalyzeGlobal(Value *V, GlobalStatus &GS, + SmallPtrSet &PHIUsers) { + for (Value::use_iterator UI = V->use_begin(), E = V->use_end(); UI != E; ++UI) + if (ConstantExpr *CE = dyn_cast(*UI)) { + GS.HasNonInstructionUser = true; + + if (AnalyzeGlobal(CE, GS, PHIUsers)) return true; + + } else if (Instruction *I = dyn_cast(*UI)) { + if (!GS.HasMultipleAccessingFunctions) { + Function *F = I->getParent()->getParent(); + if (GS.AccessingFunction == 0) + GS.AccessingFunction = F; + else if (GS.AccessingFunction != F) + GS.HasMultipleAccessingFunctions = true; + } + if (LoadInst *LI = dyn_cast(I)) { + GS.isLoaded = true; + if (LI->isVolatile()) return true; // Don't hack on volatile loads. + } else if (StoreInst *SI = dyn_cast(I)) { + // Don't allow a store OF the address, only stores TO the address. + if (SI->getOperand(0) == V) return true; + + if (SI->isVolatile()) return true; // Don't hack on volatile stores. + + // If this is a direct store to the global (i.e., the global is a scalar + // value, not an aggregate), keep more specific information about + // stores. + if (GS.StoredType != GlobalStatus::isStored) { + if (GlobalVariable *GV = dyn_cast(SI->getOperand(1))){ + Value *StoredVal = SI->getOperand(0); + if (StoredVal == GV->getInitializer()) { + if (GS.StoredType < GlobalStatus::isInitializerStored) + GS.StoredType = GlobalStatus::isInitializerStored; + } else if (isa(StoredVal) && + cast(StoredVal)->getOperand(0) == GV) { + // G = G + if (GS.StoredType < GlobalStatus::isInitializerStored) + GS.StoredType = GlobalStatus::isInitializerStored; + } else if (GS.StoredType < GlobalStatus::isStoredOnce) { + GS.StoredType = GlobalStatus::isStoredOnce; + GS.StoredOnceValue = StoredVal; + } else if (GS.StoredType == GlobalStatus::isStoredOnce && + GS.StoredOnceValue == StoredVal) { + // noop. + } else { + GS.StoredType = GlobalStatus::isStored; + } + } else { + GS.StoredType = GlobalStatus::isStored; + } + } + } else if (isa(I)) { + if (AnalyzeGlobal(I, GS, PHIUsers)) return true; + } else if (isa(I)) { + if (AnalyzeGlobal(I, GS, PHIUsers)) return true; + } else if (PHINode *PN = dyn_cast(I)) { + // PHI nodes we can check just like select or GEP instructions, but we + // have to be careful about infinite recursion. + if (PHIUsers.insert(PN)) // Not already visited. + if (AnalyzeGlobal(I, GS, PHIUsers)) return true; + GS.HasPHIUser = true; + } else if (isa(I)) { + } else if (isa(I)) { + if (I->getOperand(1) == V) + GS.StoredType = GlobalStatus::isStored; + if (I->getOperand(2) == V) + GS.isLoaded = true; + } else if (isa(I)) { + assert(I->getOperand(1) == V && "Memset only takes one pointer!"); + GS.StoredType = GlobalStatus::isStored; + } else { + return true; // Any other non-load instruction might take address! + } + } else if (Constant *C = dyn_cast(*UI)) { + GS.HasNonInstructionUser = true; + // We might have a dead and dangling constant hanging off of here. + if (!SafeToDestroyConstant(C)) + return true; + } else { + GS.HasNonInstructionUser = true; + // Otherwise must be some other user. + return true; + } + + return false; +} + +static Constant *getAggregateConstantElement(Constant *Agg, Constant *Idx) { + ConstantInt *CI = dyn_cast(Idx); + if (!CI) return 0; + unsigned IdxV = CI->getZExtValue(); + + if (ConstantStruct *CS = dyn_cast(Agg)) { + if (IdxV < CS->getNumOperands()) return CS->getOperand(IdxV); + } else if (ConstantArray *CA = dyn_cast(Agg)) { + if (IdxV < CA->getNumOperands()) return CA->getOperand(IdxV); + } else if (ConstantVector *CP = dyn_cast(Agg)) { + if (IdxV < CP->getNumOperands()) return CP->getOperand(IdxV); + } else if (isa(Agg)) { + if (const StructType *STy = dyn_cast(Agg->getType())) { + if (IdxV < STy->getNumElements()) + return Constant::getNullValue(STy->getElementType(IdxV)); + } else if (const SequentialType *STy = + dyn_cast(Agg->getType())) { + return Constant::getNullValue(STy->getElementType()); + } + } else if (isa(Agg)) { + if (const StructType *STy = dyn_cast(Agg->getType())) { + if (IdxV < STy->getNumElements()) + return UndefValue::get(STy->getElementType(IdxV)); + } else if (const SequentialType *STy = + dyn_cast(Agg->getType())) { + return UndefValue::get(STy->getElementType()); + } + } + return 0; +} + + +/// CleanupConstantGlobalUsers - We just marked GV constant. Loop over all +/// users of the global, cleaning up the obvious ones. This is largely just a +/// quick scan over the use list to clean up the easy and obvious cruft. This +/// returns true if it made a change. +static bool CleanupConstantGlobalUsers(Value *V, Constant *Init) { + bool Changed = false; + for (Value::use_iterator UI = V->use_begin(), E = V->use_end(); UI != E;) { + User *U = *UI++; + + if (LoadInst *LI = dyn_cast(U)) { + if (Init) { + // Replace the load with the initializer. + LI->replaceAllUsesWith(Init); + LI->eraseFromParent(); + Changed = true; + } + } else if (StoreInst *SI = dyn_cast(U)) { + // Store must be unreachable or storing Init into the global. + SI->eraseFromParent(); + Changed = true; + } else if (ConstantExpr *CE = dyn_cast(U)) { + if (CE->getOpcode() == Instruction::GetElementPtr) { + Constant *SubInit = 0; + if (Init) + SubInit = ConstantFoldLoadThroughGEPConstantExpr(Init, CE); + Changed |= CleanupConstantGlobalUsers(CE, SubInit); + } else if (CE->getOpcode() == Instruction::BitCast && + isa(CE->getType())) { + // Pointer cast, delete any stores and memsets to the global. + Changed |= CleanupConstantGlobalUsers(CE, 0); + } + + if (CE->use_empty()) { + CE->destroyConstant(); + Changed = true; + } + } else if (GetElementPtrInst *GEP = dyn_cast(U)) { + // Do not transform "gepinst (gep constexpr (GV))" here, because forming + // "gepconstexpr (gep constexpr (GV))" will cause the two gep's to fold + // and will invalidate our notion of what Init is. + Constant *SubInit = 0; + if (!isa(GEP->getOperand(0))) { + ConstantExpr *CE = + dyn_cast_or_null(ConstantFoldInstruction(GEP)); + if (Init && CE && CE->getOpcode() == Instruction::GetElementPtr) + SubInit = ConstantFoldLoadThroughGEPConstantExpr(Init, CE); + } + Changed |= CleanupConstantGlobalUsers(GEP, SubInit); + + if (GEP->use_empty()) { + GEP->eraseFromParent(); + Changed = true; + } + } else if (MemIntrinsic *MI = dyn_cast(U)) { // memset/cpy/mv + if (MI->getRawDest() == V) { + MI->eraseFromParent(); + Changed = true; + } + + } else if (Constant *C = dyn_cast(U)) { + // If we have a chain of dead constantexprs or other things dangling from + // us, and if they are all dead, nuke them without remorse. + if (SafeToDestroyConstant(C)) { + C->destroyConstant(); + // This could have invalidated UI, start over from scratch. + CleanupConstantGlobalUsers(V, Init); + return true; + } + } + } + return Changed; +} + +/// isSafeSROAElementUse - Return true if the specified instruction is a safe +/// user of a derived expression from a global that we want to SROA. +static bool isSafeSROAElementUse(Value *V) { + // We might have a dead and dangling constant hanging off of here. + if (Constant *C = dyn_cast(V)) + return SafeToDestroyConstant(C); + + Instruction *I = dyn_cast(V); + if (!I) return false; + + // Loads are ok. + if (isa(I)) return true; + + // Stores *to* the pointer are ok. + if (StoreInst *SI = dyn_cast(I)) + return SI->getOperand(0) != V; + + // Otherwise, it must be a GEP. + GetElementPtrInst *GEPI = dyn_cast(I); + if (GEPI == 0) return false; + + if (GEPI->getNumOperands() < 3 || !isa(GEPI->getOperand(1)) || + !cast(GEPI->getOperand(1))->isNullValue()) + return false; + + for (Value::use_iterator I = GEPI->use_begin(), E = GEPI->use_end(); + I != E; ++I) + if (!isSafeSROAElementUse(*I)) + return false; + return true; +} + + +/// IsUserOfGlobalSafeForSRA - U is a direct user of the specified global value. +/// Look at it and its uses and decide whether it is safe to SROA this global. +/// +static bool IsUserOfGlobalSafeForSRA(User *U, GlobalValue *GV) { + // The user of the global must be a GEP Inst or a ConstantExpr GEP. + if (!isa(U) && + (!isa(U) || + cast(U)->getOpcode() != Instruction::GetElementPtr)) + return false; + + // Check to see if this ConstantExpr GEP is SRA'able. In particular, we + // don't like < 3 operand CE's, and we don't like non-constant integer + // indices. This enforces that all uses are 'gep GV, 0, C, ...' for some + // value of C. + if (U->getNumOperands() < 3 || !isa(U->getOperand(1)) || + !cast(U->getOperand(1))->isNullValue() || + !isa(U->getOperand(2))) + return false; + + gep_type_iterator GEPI = gep_type_begin(U), E = gep_type_end(U); + ++GEPI; // Skip over the pointer index. + + // If this is a use of an array allocation, do a bit more checking for sanity. + if (const ArrayType *AT = dyn_cast(*GEPI)) { + uint64_t NumElements = AT->getNumElements(); + ConstantInt *Idx = cast(U->getOperand(2)); + + // Check to make sure that index falls within the array. If not, + // something funny is going on, so we won't do the optimization. + // + if (Idx->getZExtValue() >= NumElements) + return false; + + // We cannot scalar repl this level of the array unless any array + // sub-indices are in-range constants. In particular, consider: + // A[0][i]. We cannot know that the user isn't doing invalid things like + // allowing i to index an out-of-range subscript that accesses A[1]. + // + // Scalar replacing *just* the outer index of the array is probably not + // going to be a win anyway, so just give up. + for (++GEPI; // Skip array index. + GEPI != E; + ++GEPI) { + uint64_t NumElements; + if (const ArrayType *SubArrayTy = dyn_cast(*GEPI)) + NumElements = SubArrayTy->getNumElements(); + else if (const VectorType *SubVectorTy = dyn_cast(*GEPI)) + NumElements = SubVectorTy->getNumElements(); + else { + assert(isa(*GEPI) && + "Indexed GEP type is not array, vector, or struct!"); + continue; + } + + ConstantInt *IdxVal = dyn_cast(GEPI.getOperand()); + if (!IdxVal || IdxVal->getZExtValue() >= NumElements) + return false; + } + } + + for (Value::use_iterator I = U->use_begin(), E = U->use_end(); I != E; ++I) + if (!isSafeSROAElementUse(*I)) + return false; + return true; +} + +/// GlobalUsersSafeToSRA - Look at all uses of the global and decide whether it +/// is safe for us to perform this transformation. +/// +static bool GlobalUsersSafeToSRA(GlobalValue *GV) { + for (Value::use_iterator UI = GV->use_begin(), E = GV->use_end(); + UI != E; ++UI) { + if (!IsUserOfGlobalSafeForSRA(*UI, GV)) + return false; + } + return true; +} + + +/// SRAGlobal - Perform scalar replacement of aggregates on the specified global +/// variable. This opens the door for other optimizations by exposing the +/// behavior of the program in a more fine-grained way. We have determined that +/// this transformation is safe already. We return the first global variable we +/// insert so that the caller can reprocess it. +static GlobalVariable *SRAGlobal(GlobalVariable *GV, const TargetData &TD) { + // Make sure this global only has simple uses that we can SRA. + if (!GlobalUsersSafeToSRA(GV)) + return 0; + + assert(GV->hasLocalLinkage() && !GV->isConstant()); + Constant *Init = GV->getInitializer(); + const Type *Ty = Init->getType(); + + std::vector NewGlobals; + Module::GlobalListType &Globals = GV->getParent()->getGlobalList(); + + // Get the alignment of the global, either explicit or target-specific. + unsigned StartAlignment = GV->getAlignment(); + if (StartAlignment == 0) + StartAlignment = TD.getABITypeAlignment(GV->getType()); + + if (const StructType *STy = dyn_cast(Ty)) { + NewGlobals.reserve(STy->getNumElements()); + const StructLayout &Layout = *TD.getStructLayout(STy); + for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) { + Constant *In = getAggregateConstantElement(Init, + ConstantInt::get(Type::getInt32Ty(STy->getContext()), i)); + assert(In && "Couldn't get element of initializer?"); + GlobalVariable *NGV = new GlobalVariable(STy->getElementType(i), false, + GlobalVariable::InternalLinkage, + In, GV->getName()+"."+Twine(i), + GV->isThreadLocal(), + GV->getType()->getAddressSpace()); + Globals.insert(GV, NGV); + NewGlobals.push_back(NGV); + + // Calculate the known alignment of the field. If the original aggregate + // had 256 byte alignment for example, something might depend on that: + // propagate info to each field. + uint64_t FieldOffset = Layout.getElementOffset(i); + unsigned NewAlign = (unsigned)MinAlign(StartAlignment, FieldOffset); + if (NewAlign > TD.getABITypeAlignment(STy->getElementType(i))) + NGV->setAlignment(NewAlign); + } + } else if (const SequentialType *STy = dyn_cast(Ty)) { + unsigned NumElements = 0; + if (const ArrayType *ATy = dyn_cast(STy)) + NumElements = ATy->getNumElements(); + else + NumElements = cast(STy)->getNumElements(); + + if (NumElements > 16 && GV->hasNUsesOrMore(16)) + return 0; // It's not worth it. + NewGlobals.reserve(NumElements); + + uint64_t EltSize = TD.getTypeAllocSize(STy->getElementType()); + unsigned EltAlign = TD.getABITypeAlignment(STy->getElementType()); + for (unsigned i = 0, e = NumElements; i != e; ++i) { + Constant *In = getAggregateConstantElement(Init, + ConstantInt::get(Type::getInt32Ty(Init->getContext()), i)); + assert(In && "Couldn't get element of initializer?"); + + GlobalVariable *NGV = new GlobalVariable(STy->getElementType(), false, + GlobalVariable::InternalLinkage, + In, GV->getName()+"."+Twine(i), + GV->isThreadLocal(), + GV->getType()->getAddressSpace()); + Globals.insert(GV, NGV); + NewGlobals.push_back(NGV); + + // Calculate the known alignment of the field. If the original aggregate + // had 256 byte alignment for example, something might depend on that: + // propagate info to each field. + unsigned NewAlign = (unsigned)MinAlign(StartAlignment, EltSize*i); + if (NewAlign > EltAlign) + NGV->setAlignment(NewAlign); + } + } + + if (NewGlobals.empty()) + return 0; + + DEBUG(errs() << "PERFORMING GLOBAL SRA ON: " << *GV); + + Constant *NullInt =Constant::getNullValue(Type::getInt32Ty(GV->getContext())); + + // Loop over all of the uses of the global, replacing the constantexpr geps, + // with smaller constantexpr geps or direct references. + while (!GV->use_empty()) { + User *GEP = GV->use_back(); + assert(((isa(GEP) && + cast(GEP)->getOpcode()==Instruction::GetElementPtr)|| + isa(GEP)) && "NonGEP CE's are not SRAable!"); + + // Ignore the 1th operand, which has to be zero or else the program is quite + // broken (undefined). Get the 2nd operand, which is the structure or array + // index. + unsigned Val = cast(GEP->getOperand(2))->getZExtValue(); + if (Val >= NewGlobals.size()) Val = 0; // Out of bound array access. + + Value *NewPtr = NewGlobals[Val]; + + // Form a shorter GEP if needed. + if (GEP->getNumOperands() > 3) { + if (ConstantExpr *CE = dyn_cast(GEP)) { + SmallVector Idxs; + Idxs.push_back(NullInt); + for (unsigned i = 3, e = CE->getNumOperands(); i != e; ++i) + Idxs.push_back(CE->getOperand(i)); + NewPtr = ConstantExpr::getGetElementPtr(cast(NewPtr), + &Idxs[0], Idxs.size()); + } else { + GetElementPtrInst *GEPI = cast(GEP); + SmallVector Idxs; + Idxs.push_back(NullInt); + for (unsigned i = 3, e = GEPI->getNumOperands(); i != e; ++i) + Idxs.push_back(GEPI->getOperand(i)); + NewPtr = GetElementPtrInst::Create(NewPtr, Idxs.begin(), Idxs.end(), + GEPI->getName()+"."+Twine(Val),GEPI); + } + } + GEP->replaceAllUsesWith(NewPtr); + + if (GetElementPtrInst *GEPI = dyn_cast(GEP)) + GEPI->eraseFromParent(); + else + cast(GEP)->destroyConstant(); + } + + // Delete the old global, now that it is dead. + Globals.erase(GV); + ++NumSRA; + + // Loop over the new globals array deleting any globals that are obviously + // dead. This can arise due to scalarization of a structure or an array that + // has elements that are dead. + unsigned FirstGlobal = 0; + for (unsigned i = 0, e = NewGlobals.size(); i != e; ++i) + if (NewGlobals[i]->use_empty()) { + Globals.erase(NewGlobals[i]); + if (FirstGlobal == i) ++FirstGlobal; + } + + return FirstGlobal != NewGlobals.size() ? NewGlobals[FirstGlobal] : 0; +} + +/// AllUsesOfValueWillTrapIfNull - Return true if all users of the specified +/// value will trap if the value is dynamically null. PHIs keeps track of any +/// phi nodes we've seen to avoid reprocessing them. +static bool AllUsesOfValueWillTrapIfNull(Value *V, + SmallPtrSet &PHIs) { + for (Value::use_iterator UI = V->use_begin(), E = V->use_end(); UI != E; ++UI) + if (isa(*UI)) { + // Will trap. + } else if (StoreInst *SI = dyn_cast(*UI)) { + if (SI->getOperand(0) == V) { + //cerr << "NONTRAPPING USE: " << **UI; + return false; // Storing the value. + } + } else if (CallInst *CI = dyn_cast(*UI)) { + if (CI->getOperand(0) != V) { + //cerr << "NONTRAPPING USE: " << **UI; + return false; // Not calling the ptr + } + } else if (InvokeInst *II = dyn_cast(*UI)) { + if (II->getOperand(0) != V) { + //cerr << "NONTRAPPING USE: " << **UI; + return false; // Not calling the ptr + } + } else if (BitCastInst *CI = dyn_cast(*UI)) { + if (!AllUsesOfValueWillTrapIfNull(CI, PHIs)) return false; + } else if (GetElementPtrInst *GEPI = dyn_cast(*UI)) { + if (!AllUsesOfValueWillTrapIfNull(GEPI, PHIs)) return false; + } else if (PHINode *PN = dyn_cast(*UI)) { + // If we've already seen this phi node, ignore it, it has already been + // checked. + if (PHIs.insert(PN)) + return AllUsesOfValueWillTrapIfNull(PN, PHIs); + } else if (isa(*UI) && + isa(UI->getOperand(1))) { + // Ignore setcc X, null + } else { + //cerr << "NONTRAPPING USE: " << **UI; + return false; + } + return true; +} + +/// AllUsesOfLoadedValueWillTrapIfNull - Return true if all uses of any loads +/// from GV will trap if the loaded value is null. Note that this also permits +/// comparisons of the loaded value against null, as a special case. +static bool AllUsesOfLoadedValueWillTrapIfNull(GlobalVariable *GV) { + for (Value::use_iterator UI = GV->use_begin(), E = GV->use_end(); UI!=E; ++UI) + if (LoadInst *LI = dyn_cast(*UI)) { + SmallPtrSet PHIs; + if (!AllUsesOfValueWillTrapIfNull(LI, PHIs)) + return false; + } else if (isa(*UI)) { + // Ignore stores to the global. + } else { + // We don't know or understand this user, bail out. + //cerr << "UNKNOWN USER OF GLOBAL!: " << **UI; + return false; + } + + return true; +} + +static bool OptimizeAwayTrappingUsesOfValue(Value *V, Constant *NewV) { + bool Changed = false; + for (Value::use_iterator UI = V->use_begin(), E = V->use_end(); UI != E; ) { + Instruction *I = cast(*UI++); + if (LoadInst *LI = dyn_cast(I)) { + LI->setOperand(0, NewV); + Changed = true; + } else if (StoreInst *SI = dyn_cast(I)) { + if (SI->getOperand(1) == V) { + SI->setOperand(1, NewV); + Changed = true; + } + } else if (isa(I) || isa(I)) { + if (I->getOperand(0) == V) { + // Calling through the pointer! Turn into a direct call, but be careful + // that the pointer is not also being passed as an argument. + I->setOperand(0, NewV); + Changed = true; + bool PassedAsArg = false; + for (unsigned i = 1, e = I->getNumOperands(); i != e; ++i) + if (I->getOperand(i) == V) { + PassedAsArg = true; + I->setOperand(i, NewV); + } + + if (PassedAsArg) { + // Being passed as an argument also. Be careful to not invalidate UI! + UI = V->use_begin(); + } + } + } else if (CastInst *CI = dyn_cast(I)) { + Changed |= OptimizeAwayTrappingUsesOfValue(CI, + ConstantExpr::getCast(CI->getOpcode(), + NewV, CI->getType())); + if (CI->use_empty()) { + Changed = true; + CI->eraseFromParent(); + } + } else if (GetElementPtrInst *GEPI = dyn_cast(I)) { + // Should handle GEP here. + SmallVector Idxs; + Idxs.reserve(GEPI->getNumOperands()-1); + for (User::op_iterator i = GEPI->op_begin() + 1, e = GEPI->op_end(); + i != e; ++i) + if (Constant *C = dyn_cast(*i)) + Idxs.push_back(C); + else + break; + if (Idxs.size() == GEPI->getNumOperands()-1) + Changed |= OptimizeAwayTrappingUsesOfValue(GEPI, + ConstantExpr::getGetElementPtr(NewV, &Idxs[0], + Idxs.size())); + if (GEPI->use_empty()) { + Changed = true; + GEPI->eraseFromParent(); + } + } + } + + return Changed; +} + + +/// OptimizeAwayTrappingUsesOfLoads - The specified global has only one non-null +/// value stored into it. If there are uses of the loaded value that would trap +/// if the loaded value is dynamically null, then we know that they cannot be +/// reachable with a null optimize away the load. +static bool OptimizeAwayTrappingUsesOfLoads(GlobalVariable *GV, Constant *LV) { + bool Changed = false; + + // Keep track of whether we are able to remove all the uses of the global + // other than the store that defines it. + bool AllNonStoreUsesGone = true; + + // Replace all uses of loads with uses of uses of the stored value. + for (Value::use_iterator GUI = GV->use_begin(), E = GV->use_end(); GUI != E;){ + User *GlobalUser = *GUI++; + if (LoadInst *LI = dyn_cast(GlobalUser)) { + Changed |= OptimizeAwayTrappingUsesOfValue(LI, LV); + // If we were able to delete all uses of the loads + if (LI->use_empty()) { + LI->eraseFromParent(); + Changed = true; + } else { + AllNonStoreUsesGone = false; + } + } else if (isa(GlobalUser)) { + // Ignore the store that stores "LV" to the global. + assert(GlobalUser->getOperand(1) == GV && + "Must be storing *to* the global"); + } else { + AllNonStoreUsesGone = false; + + // If we get here we could have other crazy uses that are transitively + // loaded. + assert((isa(GlobalUser) || isa(GlobalUser) || + isa(GlobalUser)) && "Only expect load and stores!"); + } + } + + if (Changed) { + DEBUG(errs() << "OPTIMIZED LOADS FROM STORED ONCE POINTER: " << *GV); + ++NumGlobUses; + } + + // If we nuked all of the loads, then none of the stores are needed either, + // nor is the global. + if (AllNonStoreUsesGone) { + DEBUG(errs() << " *** GLOBAL NOW DEAD!\n"); + CleanupConstantGlobalUsers(GV, 0); + if (GV->use_empty()) { + GV->eraseFromParent(); + ++NumDeleted; + } + Changed = true; + } + return Changed; +} + +/// ConstantPropUsersOf - Walk the use list of V, constant folding all of the +/// instructions that are foldable. +static void ConstantPropUsersOf(Value *V) { + for (Value::use_iterator UI = V->use_begin(), E = V->use_end(); UI != E; ) + if (Instruction *I = dyn_cast(*UI++)) + if (Constant *NewC = ConstantFoldInstruction(I)) { + I->replaceAllUsesWith(NewC); + + // Advance UI to the next non-I use to avoid invalidating it! + // Instructions could multiply use V. + while (UI != E && *UI == I) + ++UI; + I->eraseFromParent(); + } +} + +/// OptimizeGlobalAddressOfMalloc - This function takes the specified global +/// variable, and transforms the program as if it always contained the result of +/// the specified malloc. Because it is always the result of the specified +/// malloc, there is no reason to actually DO the malloc. Instead, turn the +/// malloc into a global, and any loads of GV as uses of the new global. +static GlobalVariable *OptimizeGlobalAddressOfMalloc(GlobalVariable *GV, + CallInst *CI, + const Type *AllocTy, + Value* NElems, + TargetData* TD) { + DEBUG(errs() << "PROMOTING GLOBAL: " << *GV << " CALL = " << *CI << '\n'); + + const Type *IntPtrTy = TD->getIntPtrType(GV->getContext()); + + // CI has either 0 or 1 bitcast uses (getMallocType() would otherwise have + // returned NULL and we would not be here). + BitCastInst *BCI = NULL; + for (Value::use_iterator UI = CI->use_begin(), E = CI->use_end(); UI != E; ) + if ((BCI = dyn_cast(cast(*UI++)))) + break; + + ConstantInt *NElements = cast(NElems); + if (NElements->getZExtValue() != 1) { + // If we have an array allocation, transform it to a single element + // allocation to make the code below simpler. + Type *NewTy = ArrayType::get(AllocTy, NElements->getZExtValue()); + unsigned TypeSize = TD->getTypeAllocSize(NewTy); + if (const StructType *ST = dyn_cast(NewTy)) + TypeSize = TD->getStructLayout(ST)->getSizeInBytes(); + Instruction *NewCI = CallInst::CreateMalloc(CI, IntPtrTy, NewTy, + ConstantInt::get(IntPtrTy, TypeSize)); + Value* Indices[2]; + Indices[0] = Indices[1] = Constant::getNullValue(IntPtrTy); + Value *NewGEP = GetElementPtrInst::Create(NewCI, Indices, Indices + 2, + NewCI->getName()+".el0", CI); + Value *Cast = new BitCastInst(NewGEP, CI->getType(), "el0", CI); + if (BCI) BCI->replaceAllUsesWith(NewGEP); + CI->replaceAllUsesWith(Cast); + if (BCI) BCI->eraseFromParent(); + CI->eraseFromParent(); + BCI = dyn_cast(NewCI); + CI = BCI ? extractMallocCallFromBitCast(BCI) : cast(NewCI); + } + + // Create the new global variable. The contents of the malloc'd memory is + // undefined, so initialize with an undef value. + const Type *MAT = getMallocAllocatedType(CI); + Constant *Init = UndefValue::get(MAT); + GlobalVariable *NewGV = new GlobalVariable(*GV->getParent(), + MAT, false, + GlobalValue::InternalLinkage, Init, + GV->getName()+".body", + GV, + GV->isThreadLocal()); + + // Anything that used the malloc or its bitcast now uses the global directly. + if (BCI) BCI->replaceAllUsesWith(NewGV); + CI->replaceAllUsesWith(new BitCastInst(NewGV, CI->getType(), "newgv", CI)); + + Constant *RepValue = NewGV; + if (NewGV->getType() != GV->getType()->getElementType()) + RepValue = ConstantExpr::getBitCast(RepValue, + GV->getType()->getElementType()); + + // If there is a comparison against null, we will insert a global bool to + // keep track of whether the global was initialized yet or not. + GlobalVariable *InitBool = + new GlobalVariable(Type::getInt1Ty(GV->getContext()), false, + GlobalValue::InternalLinkage, + ConstantInt::getFalse(GV->getContext()), + GV->getName()+".init", GV->isThreadLocal()); + bool InitBoolUsed = false; + + // Loop over all uses of GV, processing them in turn. + std::vector Stores; + while (!GV->use_empty()) + if (LoadInst *LI = dyn_cast(GV->use_back())) { + while (!LI->use_empty()) { + Use &LoadUse = LI->use_begin().getUse(); + if (!isa(LoadUse.getUser())) + LoadUse = RepValue; + else { + ICmpInst *ICI = cast(LoadUse.getUser()); + // Replace the cmp X, 0 with a use of the bool value. + Value *LV = new LoadInst(InitBool, InitBool->getName()+".val", ICI); + InitBoolUsed = true; + switch (ICI->getPredicate()) { + default: llvm_unreachable("Unknown ICmp Predicate!"); + case ICmpInst::ICMP_ULT: + case ICmpInst::ICMP_SLT: // X < null -> always false + LV = ConstantInt::getFalse(GV->getContext()); + break; + case ICmpInst::ICMP_ULE: + case ICmpInst::ICMP_SLE: + case ICmpInst::ICMP_EQ: + LV = BinaryOperator::CreateNot(LV, "notinit", ICI); + break; + case ICmpInst::ICMP_NE: + case ICmpInst::ICMP_UGE: + case ICmpInst::ICMP_SGE: + case ICmpInst::ICMP_UGT: + case ICmpInst::ICMP_SGT: + break; // no change. + } + ICI->replaceAllUsesWith(LV); + ICI->eraseFromParent(); + } + } + LI->eraseFromParent(); + } else { + StoreInst *SI = cast(GV->use_back()); + // The global is initialized when the store to it occurs. + new StoreInst(ConstantInt::getTrue(GV->getContext()), InitBool, SI); + SI->eraseFromParent(); + } + + // If the initialization boolean was used, insert it, otherwise delete it. + if (!InitBoolUsed) { + while (!InitBool->use_empty()) // Delete initializations + cast(InitBool->use_back())->eraseFromParent(); + delete InitBool; + } else + GV->getParent()->getGlobalList().insert(GV, InitBool); + + + // Now the GV is dead, nuke it and the malloc (both CI and BCI). + GV->eraseFromParent(); + if (BCI) BCI->eraseFromParent(); + CI->eraseFromParent(); + + // To further other optimizations, loop over all users of NewGV and try to + // constant prop them. This will promote GEP instructions with constant + // indices into GEP constant-exprs, which will allow global-opt to hack on it. + ConstantPropUsersOf(NewGV); + if (RepValue != NewGV) + ConstantPropUsersOf(RepValue); + + return NewGV; +} + +/// ValueIsOnlyUsedLocallyOrStoredToOneGlobal - Scan the use-list of V checking +/// to make sure that there are no complex uses of V. We permit simple things +/// like dereferencing the pointer, but not storing through the address, unless +/// it is to the specified global. +static bool ValueIsOnlyUsedLocallyOrStoredToOneGlobal(Instruction *V, + GlobalVariable *GV, + SmallPtrSet &PHIs) { + for (Value::use_iterator UI = V->use_begin(), E = V->use_end(); UI != E;++UI){ + Instruction *Inst = cast(*UI); + + if (isa(Inst) || isa(Inst)) { + continue; // Fine, ignore. + } + + if (StoreInst *SI = dyn_cast(Inst)) { + if (SI->getOperand(0) == V && SI->getOperand(1) != GV) + return false; // Storing the pointer itself... bad. + continue; // Otherwise, storing through it, or storing into GV... fine. + } + + if (isa(Inst)) { + if (!ValueIsOnlyUsedLocallyOrStoredToOneGlobal(Inst, GV, PHIs)) + return false; + continue; + } + + if (PHINode *PN = dyn_cast(Inst)) { + // PHIs are ok if all uses are ok. Don't infinitely recurse through PHI + // cycles. + if (PHIs.insert(PN)) + if (!ValueIsOnlyUsedLocallyOrStoredToOneGlobal(PN, GV, PHIs)) + return false; + continue; + } + + if (BitCastInst *BCI = dyn_cast(Inst)) { + if (!ValueIsOnlyUsedLocallyOrStoredToOneGlobal(BCI, GV, PHIs)) + return false; + continue; + } + + return false; + } + return true; +} + +/// ReplaceUsesOfMallocWithGlobal - The Alloc pointer is stored into GV +/// somewhere. Transform all uses of the allocation into loads from the +/// global and uses of the resultant pointer. Further, delete the store into +/// GV. This assumes that these value pass the +/// 'ValueIsOnlyUsedLocallyOrStoredToOneGlobal' predicate. +static void ReplaceUsesOfMallocWithGlobal(Instruction *Alloc, + GlobalVariable *GV) { + while (!Alloc->use_empty()) { + Instruction *U = cast(*Alloc->use_begin()); + Instruction *InsertPt = U; + if (StoreInst *SI = dyn_cast(U)) { + // If this is the store of the allocation into the global, remove it. + if (SI->getOperand(1) == GV) { + SI->eraseFromParent(); + continue; + } + } else if (PHINode *PN = dyn_cast(U)) { + // Insert the load in the corresponding predecessor, not right before the + // PHI. + InsertPt = PN->getIncomingBlock(Alloc->use_begin())->getTerminator(); + } else if (isa(U)) { + // Must be bitcast between the malloc and store to initialize the global. + ReplaceUsesOfMallocWithGlobal(U, GV); + U->eraseFromParent(); + continue; + } else if (GetElementPtrInst *GEPI = dyn_cast(U)) { + // If this is a "GEP bitcast" and the user is a store to the global, then + // just process it as a bitcast. + if (GEPI->hasAllZeroIndices() && GEPI->hasOneUse()) + if (StoreInst *SI = dyn_cast(GEPI->use_back())) + if (SI->getOperand(1) == GV) { + // Must be bitcast GEP between the malloc and store to initialize + // the global. + ReplaceUsesOfMallocWithGlobal(GEPI, GV); + GEPI->eraseFromParent(); + continue; + } + } + + // Insert a load from the global, and use it instead of the malloc. + Value *NL = new LoadInst(GV, GV->getName()+".val", InsertPt); + U->replaceUsesOfWith(Alloc, NL); + } +} + +/// LoadUsesSimpleEnoughForHeapSRA - Verify that all uses of V (a load, or a phi +/// of a load) are simple enough to perform heap SRA on. This permits GEP's +/// that index through the array and struct field, icmps of null, and PHIs. +static bool LoadUsesSimpleEnoughForHeapSRA(Value *V, + SmallPtrSet &LoadUsingPHIs, + SmallPtrSet &LoadUsingPHIsPerLoad) { + // We permit two users of the load: setcc comparing against the null + // pointer, and a getelementptr of a specific form. + for (Value::use_iterator UI = V->use_begin(), E = V->use_end(); UI != E;++UI){ + Instruction *User = cast(*UI); + + // Comparison against null is ok. + if (ICmpInst *ICI = dyn_cast(User)) { + if (!isa(ICI->getOperand(1))) + return false; + continue; + } + + // getelementptr is also ok, but only a simple form. + if (GetElementPtrInst *GEPI = dyn_cast(User)) { + // Must index into the array and into the struct. + if (GEPI->getNumOperands() < 3) + return false; + + // Otherwise the GEP is ok. + continue; + } + + if (PHINode *PN = dyn_cast(User)) { + if (!LoadUsingPHIsPerLoad.insert(PN)) + // This means some phi nodes are dependent on each other. + // Avoid infinite looping! + return false; + if (!LoadUsingPHIs.insert(PN)) + // If we have already analyzed this PHI, then it is safe. + continue; + + // Make sure all uses of the PHI are simple enough to transform. + if (!LoadUsesSimpleEnoughForHeapSRA(PN, + LoadUsingPHIs, LoadUsingPHIsPerLoad)) + return false; + + continue; + } + + // Otherwise we don't know what this is, not ok. + return false; + } + + return true; +} + + +/// AllGlobalLoadUsesSimpleEnoughForHeapSRA - If all users of values loaded from +/// GV are simple enough to perform HeapSRA, return true. +static bool AllGlobalLoadUsesSimpleEnoughForHeapSRA(GlobalVariable *GV, + Instruction *StoredVal) { + SmallPtrSet LoadUsingPHIs; + SmallPtrSet LoadUsingPHIsPerLoad; + for (Value::use_iterator UI = GV->use_begin(), E = GV->use_end(); UI != E; + ++UI) + if (LoadInst *LI = dyn_cast(*UI)) { + if (!LoadUsesSimpleEnoughForHeapSRA(LI, LoadUsingPHIs, + LoadUsingPHIsPerLoad)) + return false; + LoadUsingPHIsPerLoad.clear(); + } + + // If we reach here, we know that all uses of the loads and transitive uses + // (through PHI nodes) are simple enough to transform. However, we don't know + // that all inputs the to the PHI nodes are in the same equivalence sets. + // Check to verify that all operands of the PHIs are either PHIS that can be + // transformed, loads from GV, or MI itself. + for (SmallPtrSet::iterator I = LoadUsingPHIs.begin(), + E = LoadUsingPHIs.end(); I != E; ++I) { + PHINode *PN = *I; + for (unsigned op = 0, e = PN->getNumIncomingValues(); op != e; ++op) { + Value *InVal = PN->getIncomingValue(op); + + // PHI of the stored value itself is ok. + if (InVal == StoredVal) continue; + + if (PHINode *InPN = dyn_cast(InVal)) { + // One of the PHIs in our set is (optimistically) ok. + if (LoadUsingPHIs.count(InPN)) + continue; + return false; + } + + // Load from GV is ok. + if (LoadInst *LI = dyn_cast(InVal)) + if (LI->getOperand(0) == GV) + continue; + + // UNDEF? NULL? + + // Anything else is rejected. + return false; + } + } + + return true; +} + +static Value *GetHeapSROAValue(Value *V, unsigned FieldNo, + DenseMap > &InsertedScalarizedValues, + std::vector > &PHIsToRewrite) { + std::vector &FieldVals = InsertedScalarizedValues[V]; + + if (FieldNo >= FieldVals.size()) + FieldVals.resize(FieldNo+1); + + // If we already have this value, just reuse the previously scalarized + // version. + if (Value *FieldVal = FieldVals[FieldNo]) + return FieldVal; + + // Depending on what instruction this is, we have several cases. + Value *Result; + if (LoadInst *LI = dyn_cast(V)) { + // This is a scalarized version of the load from the global. Just create + // a new Load of the scalarized global. + Result = new LoadInst(GetHeapSROAValue(LI->getOperand(0), FieldNo, + InsertedScalarizedValues, + PHIsToRewrite), + LI->getName()+".f"+Twine(FieldNo), LI); + } else if (PHINode *PN = dyn_cast(V)) { + // PN's type is pointer to struct. Make a new PHI of pointer to struct + // field. + const StructType *ST = + cast(cast(PN->getType())->getElementType()); + + Result = + PHINode::Create(PointerType::getUnqual(ST->getElementType(FieldNo)), + PN->getName()+".f"+Twine(FieldNo), PN); + PHIsToRewrite.push_back(std::make_pair(PN, FieldNo)); + } else { + llvm_unreachable("Unknown usable value"); + Result = 0; + } + + return FieldVals[FieldNo] = Result; +} + +/// RewriteHeapSROALoadUser - Given a load instruction and a value derived from +/// the load, rewrite the derived value to use the HeapSRoA'd load. +static void RewriteHeapSROALoadUser(Instruction *LoadUser, + DenseMap > &InsertedScalarizedValues, + std::vector > &PHIsToRewrite) { + // If this is a comparison against null, handle it. + if (ICmpInst *SCI = dyn_cast(LoadUser)) { + assert(isa(SCI->getOperand(1))); + // If we have a setcc of the loaded pointer, we can use a setcc of any + // field. + Value *NPtr = GetHeapSROAValue(SCI->getOperand(0), 0, + InsertedScalarizedValues, PHIsToRewrite); + + Value *New = new ICmpInst(SCI, SCI->getPredicate(), NPtr, + Constant::getNullValue(NPtr->getType()), + SCI->getName()); + SCI->replaceAllUsesWith(New); + SCI->eraseFromParent(); + return; + } + + // Handle 'getelementptr Ptr, Idx, i32 FieldNo ...' + if (GetElementPtrInst *GEPI = dyn_cast(LoadUser)) { + assert(GEPI->getNumOperands() >= 3 && isa(GEPI->getOperand(2)) + && "Unexpected GEPI!"); + + // Load the pointer for this field. + unsigned FieldNo = cast(GEPI->getOperand(2))->getZExtValue(); + Value *NewPtr = GetHeapSROAValue(GEPI->getOperand(0), FieldNo, + InsertedScalarizedValues, PHIsToRewrite); + + // Create the new GEP idx vector. + SmallVector GEPIdx; + GEPIdx.push_back(GEPI->getOperand(1)); + GEPIdx.append(GEPI->op_begin()+3, GEPI->op_end()); + + Value *NGEPI = GetElementPtrInst::Create(NewPtr, + GEPIdx.begin(), GEPIdx.end(), + GEPI->getName(), GEPI); + GEPI->replaceAllUsesWith(NGEPI); + GEPI->eraseFromParent(); + return; + } + + // Recursively transform the users of PHI nodes. This will lazily create the + // PHIs that are needed for individual elements. Keep track of what PHIs we + // see in InsertedScalarizedValues so that we don't get infinite loops (very + // antisocial). If the PHI is already in InsertedScalarizedValues, it has + // already been seen first by another load, so its uses have already been + // processed. + PHINode *PN = cast(LoadUser); + bool Inserted; + DenseMap >::iterator InsertPos; + tie(InsertPos, Inserted) = + InsertedScalarizedValues.insert(std::make_pair(PN, std::vector())); + if (!Inserted) return; + + // If this is the first time we've seen this PHI, recursively process all + // users. + for (Value::use_iterator UI = PN->use_begin(), E = PN->use_end(); UI != E; ) { + Instruction *User = cast(*UI++); + RewriteHeapSROALoadUser(User, InsertedScalarizedValues, PHIsToRewrite); + } +} + +/// RewriteUsesOfLoadForHeapSRoA - We are performing Heap SRoA on a global. Ptr +/// is a value loaded from the global. Eliminate all uses of Ptr, making them +/// use FieldGlobals instead. All uses of loaded values satisfy +/// AllGlobalLoadUsesSimpleEnoughForHeapSRA. +static void RewriteUsesOfLoadForHeapSRoA(LoadInst *Load, + DenseMap > &InsertedScalarizedValues, + std::vector > &PHIsToRewrite) { + for (Value::use_iterator UI = Load->use_begin(), E = Load->use_end(); + UI != E; ) { + Instruction *User = cast(*UI++); + RewriteHeapSROALoadUser(User, InsertedScalarizedValues, PHIsToRewrite); + } + + if (Load->use_empty()) { + Load->eraseFromParent(); + InsertedScalarizedValues.erase(Load); + } +} + +/// PerformHeapAllocSRoA - CI is an allocation of an array of structures. Break +/// it up into multiple allocations of arrays of the fields. +static GlobalVariable *PerformHeapAllocSRoA(GlobalVariable *GV, CallInst *CI, + Value* NElems, TargetData *TD) { + DEBUG(errs() << "SROA HEAP ALLOC: " << *GV << " MALLOC = " << *CI << '\n'); + const Type* MAT = getMallocAllocatedType(CI); + const StructType *STy = cast(MAT); + + // There is guaranteed to be at least one use of the malloc (storing + // it into GV). If there are other uses, change them to be uses of + // the global to simplify later code. This also deletes the store + // into GV. + ReplaceUsesOfMallocWithGlobal(CI, GV); + + // Okay, at this point, there are no users of the malloc. Insert N + // new mallocs at the same place as CI, and N globals. + std::vector FieldGlobals; + std::vector FieldMallocs; + + for (unsigned FieldNo = 0, e = STy->getNumElements(); FieldNo != e;++FieldNo){ + const Type *FieldTy = STy->getElementType(FieldNo); + const PointerType *PFieldTy = PointerType::getUnqual(FieldTy); + + GlobalVariable *NGV = + new GlobalVariable(*GV->getParent(), + PFieldTy, false, GlobalValue::InternalLinkage, + Constant::getNullValue(PFieldTy), + GV->getName() + ".f" + Twine(FieldNo), GV, + GV->isThreadLocal()); + FieldGlobals.push_back(NGV); + + unsigned TypeSize = TD->getTypeAllocSize(FieldTy); + if (const StructType *ST = dyn_cast(FieldTy)) + TypeSize = TD->getStructLayout(ST)->getSizeInBytes(); + const Type *IntPtrTy = TD->getIntPtrType(CI->getContext()); + Value *NMI = CallInst::CreateMalloc(CI, IntPtrTy, FieldTy, + ConstantInt::get(IntPtrTy, TypeSize), + NElems, + CI->getName() + ".f" + Twine(FieldNo)); + CallInst *NCI = dyn_cast(NMI) ? + extractMallocCallFromBitCast(NMI) : cast(NMI); + FieldMallocs.push_back(NCI); + new StoreInst(NMI, NGV, CI); + } + + // The tricky aspect of this transformation is handling the case when malloc + // fails. In the original code, malloc failing would set the result pointer + // of malloc to null. In this case, some mallocs could succeed and others + // could fail. As such, we emit code that looks like this: + // F0 = malloc(field0) + // F1 = malloc(field1) + // F2 = malloc(field2) + // if (F0 == 0 || F1 == 0 || F2 == 0) { + // if (F0) { free(F0); F0 = 0; } + // if (F1) { free(F1); F1 = 0; } + // if (F2) { free(F2); F2 = 0; } + // } + // The malloc can also fail if its argument is too large. + Constant *ConstantZero = ConstantInt::get(CI->getOperand(1)->getType(), 0); + Value *RunningOr = new ICmpInst(CI, ICmpInst::ICMP_SLT, CI->getOperand(1), + ConstantZero, "isneg"); + for (unsigned i = 0, e = FieldMallocs.size(); i != e; ++i) { + Value *Cond = new ICmpInst(CI, ICmpInst::ICMP_EQ, FieldMallocs[i], + Constant::getNullValue(FieldMallocs[i]->getType()), + "isnull"); + RunningOr = BinaryOperator::CreateOr(RunningOr, Cond, "tmp", CI); + } + + // Split the basic block at the old malloc. + BasicBlock *OrigBB = CI->getParent(); + BasicBlock *ContBB = OrigBB->splitBasicBlock(CI, "malloc_cont"); + + // Create the block to check the first condition. Put all these blocks at the + // end of the function as they are unlikely to be executed. + BasicBlock *NullPtrBlock = BasicBlock::Create(OrigBB->getContext(), + "malloc_ret_null", + OrigBB->getParent()); + + // Remove the uncond branch from OrigBB to ContBB, turning it into a cond + // branch on RunningOr. + OrigBB->getTerminator()->eraseFromParent(); + BranchInst::Create(NullPtrBlock, ContBB, RunningOr, OrigBB); + + // Within the NullPtrBlock, we need to emit a comparison and branch for each + // pointer, because some may be null while others are not. + for (unsigned i = 0, e = FieldGlobals.size(); i != e; ++i) { + Value *GVVal = new LoadInst(FieldGlobals[i], "tmp", NullPtrBlock); + Value *Cmp = new ICmpInst(*NullPtrBlock, ICmpInst::ICMP_NE, GVVal, + Constant::getNullValue(GVVal->getType()), + "tmp"); + BasicBlock *FreeBlock = BasicBlock::Create(Cmp->getContext(), "free_it", + OrigBB->getParent()); + BasicBlock *NextBlock = BasicBlock::Create(Cmp->getContext(), "next", + OrigBB->getParent()); + Instruction *BI = BranchInst::Create(FreeBlock, NextBlock, + Cmp, NullPtrBlock); + + // Fill in FreeBlock. + CallInst::CreateFree(GVVal, BI); + new StoreInst(Constant::getNullValue(GVVal->getType()), FieldGlobals[i], + FreeBlock); + BranchInst::Create(NextBlock, FreeBlock); + + NullPtrBlock = NextBlock; + } + + BranchInst::Create(ContBB, NullPtrBlock); + + // CI is no longer needed, remove it. + CI->eraseFromParent(); + + /// InsertedScalarizedLoads - As we process loads, if we can't immediately + /// update all uses of the load, keep track of what scalarized loads are + /// inserted for a given load. + DenseMap > InsertedScalarizedValues; + InsertedScalarizedValues[GV] = FieldGlobals; + + std::vector > PHIsToRewrite; + + // Okay, the malloc site is completely handled. All of the uses of GV are now + // loads, and all uses of those loads are simple. Rewrite them to use loads + // of the per-field globals instead. + for (Value::use_iterator UI = GV->use_begin(), E = GV->use_end(); UI != E;) { + Instruction *User = cast(*UI++); + + if (LoadInst *LI = dyn_cast(User)) { + RewriteUsesOfLoadForHeapSRoA(LI, InsertedScalarizedValues, PHIsToRewrite); + continue; + } + + // Must be a store of null. + StoreInst *SI = cast(User); + assert(isa(SI->getOperand(0)) && + "Unexpected heap-sra user!"); + + // Insert a store of null into each global. + for (unsigned i = 0, e = FieldGlobals.size(); i != e; ++i) { + const PointerType *PT = cast(FieldGlobals[i]->getType()); + Constant *Null = Constant::getNullValue(PT->getElementType()); + new StoreInst(Null, FieldGlobals[i], SI); + } + // Erase the original store. + SI->eraseFromParent(); + } + + // While we have PHIs that are interesting to rewrite, do it. + while (!PHIsToRewrite.empty()) { + PHINode *PN = PHIsToRewrite.back().first; + unsigned FieldNo = PHIsToRewrite.back().second; + PHIsToRewrite.pop_back(); + PHINode *FieldPN = cast(InsertedScalarizedValues[PN][FieldNo]); + assert(FieldPN->getNumIncomingValues() == 0 &&"Already processed this phi"); + + // Add all the incoming values. This can materialize more phis. + for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) { + Value *InVal = PN->getIncomingValue(i); + InVal = GetHeapSROAValue(InVal, FieldNo, InsertedScalarizedValues, + PHIsToRewrite); + FieldPN->addIncoming(InVal, PN->getIncomingBlock(i)); + } + } + + // Drop all inter-phi links and any loads that made it this far. + for (DenseMap >::iterator + I = InsertedScalarizedValues.begin(), E = InsertedScalarizedValues.end(); + I != E; ++I) { + if (PHINode *PN = dyn_cast(I->first)) + PN->dropAllReferences(); + else if (LoadInst *LI = dyn_cast(I->first)) + LI->dropAllReferences(); + } + + // Delete all the phis and loads now that inter-references are dead. + for (DenseMap >::iterator + I = InsertedScalarizedValues.begin(), E = InsertedScalarizedValues.end(); + I != E; ++I) { + if (PHINode *PN = dyn_cast(I->first)) + PN->eraseFromParent(); + else if (LoadInst *LI = dyn_cast(I->first)) + LI->eraseFromParent(); + } + + // The old global is now dead, remove it. + GV->eraseFromParent(); + + ++NumHeapSRA; + return cast(FieldGlobals[0]); +} + +/// TryToOptimizeStoreOfMallocToGlobal - This function is called when we see a +/// pointer global variable with a single value stored it that is a malloc or +/// cast of malloc. +static bool TryToOptimizeStoreOfMallocToGlobal(GlobalVariable *GV, + CallInst *CI, + const Type *AllocTy, + Module::global_iterator &GVI, + TargetData *TD) { + // If this is a malloc of an abstract type, don't touch it. + if (!AllocTy->isSized()) + return false; + + // We can't optimize this global unless all uses of it are *known* to be + // of the malloc value, not of the null initializer value (consider a use + // that compares the global's value against zero to see if the malloc has + // been reached). To do this, we check to see if all uses of the global + // would trap if the global were null: this proves that they must all + // happen after the malloc. + if (!AllUsesOfLoadedValueWillTrapIfNull(GV)) + return false; + + // We can't optimize this if the malloc itself is used in a complex way, + // for example, being stored into multiple globals. This allows the + // malloc to be stored into the specified global, loaded setcc'd, and + // GEP'd. These are all things we could transform to using the global + // for. + { + SmallPtrSet PHIs; + if (!ValueIsOnlyUsedLocallyOrStoredToOneGlobal(CI, GV, PHIs)) + return false; + } + + // If we have a global that is only initialized with a fixed size malloc, + // transform the program to use global memory instead of malloc'd memory. + // This eliminates dynamic allocation, avoids an indirection accessing the + // data, and exposes the resultant global to further GlobalOpt. + // We cannot optimize the malloc if we cannot determine malloc array size. + if (Value *NElems = getMallocArraySize(CI, TD, true)) { + if (ConstantInt *NElements = dyn_cast(NElems)) + // Restrict this transformation to only working on small allocations + // (2048 bytes currently), as we don't want to introduce a 16M global or + // something. + if (TD && + NElements->getZExtValue() * TD->getTypeAllocSize(AllocTy) < 2048) { + GVI = OptimizeGlobalAddressOfMalloc(GV, CI, AllocTy, NElems, TD); + return true; + } + + // If the allocation is an array of structures, consider transforming this + // into multiple malloc'd arrays, one for each field. This is basically + // SRoA for malloc'd memory. + + // If this is an allocation of a fixed size array of structs, analyze as a + // variable size array. malloc [100 x struct],1 -> malloc struct, 100 + if (NElems == ConstantInt::get(CI->getOperand(1)->getType(), 1)) + if (const ArrayType *AT = dyn_cast(AllocTy)) + AllocTy = AT->getElementType(); + + if (const StructType *AllocSTy = dyn_cast(AllocTy)) { + // This the structure has an unreasonable number of fields, leave it + // alone. + if (AllocSTy->getNumElements() <= 16 && AllocSTy->getNumElements() != 0 && + AllGlobalLoadUsesSimpleEnoughForHeapSRA(GV, CI)) { + + // If this is a fixed size array, transform the Malloc to be an alloc of + // structs. malloc [100 x struct],1 -> malloc struct, 100 + if (const ArrayType *AT = + dyn_cast(getMallocAllocatedType(CI))) { + const Type *IntPtrTy = TD->getIntPtrType(CI->getContext()); + unsigned TypeSize = TD->getStructLayout(AllocSTy)->getSizeInBytes(); + Value *AllocSize = ConstantInt::get(IntPtrTy, TypeSize); + Value *NumElements = ConstantInt::get(IntPtrTy, AT->getNumElements()); + Instruction *Malloc = CallInst::CreateMalloc(CI, IntPtrTy, AllocSTy, + AllocSize, NumElements, + CI->getName()); + Instruction *Cast = new BitCastInst(Malloc, CI->getType(), "tmp", CI); + CI->replaceAllUsesWith(Cast); + CI->eraseFromParent(); + CI = dyn_cast(Malloc) ? + extractMallocCallFromBitCast(Malloc) : cast(Malloc); + } + + GVI = PerformHeapAllocSRoA(GV, CI, getMallocArraySize(CI, TD, true),TD); + return true; + } + } + } + + return false; +} + +// OptimizeOnceStoredGlobal - Try to optimize globals based on the knowledge +// that only one value (besides its initializer) is ever stored to the global. +static bool OptimizeOnceStoredGlobal(GlobalVariable *GV, Value *StoredOnceVal, + Module::global_iterator &GVI, + TargetData *TD) { + // Ignore no-op GEPs and bitcasts. + StoredOnceVal = StoredOnceVal->stripPointerCasts(); + + // If we are dealing with a pointer global that is initialized to null and + // only has one (non-null) value stored into it, then we can optimize any + // users of the loaded value (often calls and loads) that would trap if the + // value was null. + if (isa(GV->getInitializer()->getType()) && + GV->getInitializer()->isNullValue()) { + if (Constant *SOVC = dyn_cast(StoredOnceVal)) { + if (GV->getInitializer()->getType() != SOVC->getType()) + SOVC = + ConstantExpr::getBitCast(SOVC, GV->getInitializer()->getType()); + + // Optimize away any trapping uses of the loaded value. + if (OptimizeAwayTrappingUsesOfLoads(GV, SOVC)) + return true; + } else if (CallInst *CI = extractMallocCall(StoredOnceVal)) { + const Type* MallocType = getMallocAllocatedType(CI); + if (MallocType && TryToOptimizeStoreOfMallocToGlobal(GV, CI, MallocType, + GVI, TD)) + return true; + } + } + + return false; +} + +/// TryToShrinkGlobalToBoolean - At this point, we have learned that the only +/// two values ever stored into GV are its initializer and OtherVal. See if we +/// can shrink the global into a boolean and select between the two values +/// whenever it is used. This exposes the values to other scalar optimizations. +static bool TryToShrinkGlobalToBoolean(GlobalVariable *GV, Constant *OtherVal) { + const Type *GVElType = GV->getType()->getElementType(); + + // If GVElType is already i1, it is already shrunk. If the type of the GV is + // an FP value, pointer or vector, don't do this optimization because a select + // between them is very expensive and unlikely to lead to later + // simplification. In these cases, we typically end up with "cond ? v1 : v2" + // where v1 and v2 both require constant pool loads, a big loss. + if (GVElType == Type::getInt1Ty(GV->getContext()) || + GVElType->isFloatingPoint() || + isa(GVElType) || isa(GVElType)) + return false; + + // Walk the use list of the global seeing if all the uses are load or store. + // If there is anything else, bail out. + for (Value::use_iterator I = GV->use_begin(), E = GV->use_end(); I != E; ++I) + if (!isa(I) && !isa(I)) + return false; + + DEBUG(errs() << " *** SHRINKING TO BOOL: " << *GV); + + // Create the new global, initializing it to false. + GlobalVariable *NewGV = new GlobalVariable(Type::getInt1Ty(GV->getContext()), + false, + GlobalValue::InternalLinkage, + ConstantInt::getFalse(GV->getContext()), + GV->getName()+".b", + GV->isThreadLocal()); + GV->getParent()->getGlobalList().insert(GV, NewGV); + + Constant *InitVal = GV->getInitializer(); + assert(InitVal->getType() != Type::getInt1Ty(GV->getContext()) && + "No reason to shrink to bool!"); + + // If initialized to zero and storing one into the global, we can use a cast + // instead of a select to synthesize the desired value. + bool IsOneZero = false; + if (ConstantInt *CI = dyn_cast(OtherVal)) + IsOneZero = InitVal->isNullValue() && CI->isOne(); + + while (!GV->use_empty()) { + Instruction *UI = cast(GV->use_back()); + if (StoreInst *SI = dyn_cast(UI)) { + // Change the store into a boolean store. + bool StoringOther = SI->getOperand(0) == OtherVal; + // Only do this if we weren't storing a loaded value. + Value *StoreVal; + if (StoringOther || SI->getOperand(0) == InitVal) + StoreVal = ConstantInt::get(Type::getInt1Ty(GV->getContext()), + StoringOther); + else { + // Otherwise, we are storing a previously loaded copy. To do this, + // change the copy from copying the original value to just copying the + // bool. + Instruction *StoredVal = cast(SI->getOperand(0)); + + // If we're already replaced the input, StoredVal will be a cast or + // select instruction. If not, it will be a load of the original + // global. + if (LoadInst *LI = dyn_cast(StoredVal)) { + assert(LI->getOperand(0) == GV && "Not a copy!"); + // Insert a new load, to preserve the saved value. + StoreVal = new LoadInst(NewGV, LI->getName()+".b", LI); + } else { + assert((isa(StoredVal) || isa(StoredVal)) && + "This is not a form that we understand!"); + StoreVal = StoredVal->getOperand(0); + assert(isa(StoreVal) && "Not a load of NewGV!"); + } + } + new StoreInst(StoreVal, NewGV, SI); + } else { + // Change the load into a load of bool then a select. + LoadInst *LI = cast(UI); + LoadInst *NLI = new LoadInst(NewGV, LI->getName()+".b", LI); + Value *NSI; + if (IsOneZero) + NSI = new ZExtInst(NLI, LI->getType(), "", LI); + else + NSI = SelectInst::Create(NLI, OtherVal, InitVal, "", LI); + NSI->takeName(LI); + LI->replaceAllUsesWith(NSI); + } + UI->eraseFromParent(); + } + + GV->eraseFromParent(); + return true; +} + + +/// ProcessInternalGlobal - Analyze the specified global variable and optimize +/// it if possible. If we make a change, return true. +bool GlobalOpt::ProcessInternalGlobal(GlobalVariable *GV, + Module::global_iterator &GVI) { + SmallPtrSet PHIUsers; + GlobalStatus GS; + GV->removeDeadConstantUsers(); + + if (GV->use_empty()) { + DEBUG(errs() << "GLOBAL DEAD: " << *GV); + GV->eraseFromParent(); + ++NumDeleted; + return true; + } + + if (!AnalyzeGlobal(GV, GS, PHIUsers)) { +#if 0 + DEBUG(errs() << "Global: " << *GV); + DEBUG(errs() << " isLoaded = " << GS.isLoaded << "\n"); + DEBUG(errs() << " StoredType = "); + switch (GS.StoredType) { + case GlobalStatus::NotStored: DEBUG(errs() << "NEVER STORED\n"); break; + case GlobalStatus::isInitializerStored: DEBUG(errs() << "INIT STORED\n"); + break; + case GlobalStatus::isStoredOnce: DEBUG(errs() << "STORED ONCE\n"); break; + case GlobalStatus::isStored: DEBUG(errs() << "stored\n"); break; + } + if (GS.StoredType == GlobalStatus::isStoredOnce && GS.StoredOnceValue) + DEBUG(errs() << " StoredOnceValue = " << *GS.StoredOnceValue << "\n"); + if (GS.AccessingFunction && !GS.HasMultipleAccessingFunctions) + DEBUG(errs() << " AccessingFunction = " << GS.AccessingFunction->getName() + << "\n"); + DEBUG(errs() << " HasMultipleAccessingFunctions = " + << GS.HasMultipleAccessingFunctions << "\n"); + DEBUG(errs() << " HasNonInstructionUser = " + << GS.HasNonInstructionUser<<"\n"); + DEBUG(errs() << "\n"); +#endif + + // If this is a first class global and has only one accessing function + // and this function is main (which we know is not recursive we can make + // this global a local variable) we replace the global with a local alloca + // in this function. + // + // NOTE: It doesn't make sense to promote non single-value types since we + // are just replacing static memory to stack memory. + // + // If the global is in different address space, don't bring it to stack. + if (!GS.HasMultipleAccessingFunctions && + GS.AccessingFunction && !GS.HasNonInstructionUser && + GV->getType()->getElementType()->isSingleValueType() && + GS.AccessingFunction->getName() == "main" && + GS.AccessingFunction->hasExternalLinkage() && + GV->getType()->getAddressSpace() == 0) { + DEBUG(errs() << "LOCALIZING GLOBAL: " << *GV); + Instruction* FirstI = GS.AccessingFunction->getEntryBlock().begin(); + const Type* ElemTy = GV->getType()->getElementType(); + // FIXME: Pass Global's alignment when globals have alignment + AllocaInst* Alloca = new AllocaInst(ElemTy, NULL, GV->getName(), FirstI); + if (!isa(GV->getInitializer())) + new StoreInst(GV->getInitializer(), Alloca, FirstI); + + GV->replaceAllUsesWith(Alloca); + GV->eraseFromParent(); + ++NumLocalized; + return true; + } + + // If the global is never loaded (but may be stored to), it is dead. + // Delete it now. + if (!GS.isLoaded) { + DEBUG(errs() << "GLOBAL NEVER LOADED: " << *GV); + + // Delete any stores we can find to the global. We may not be able to + // make it completely dead though. + bool Changed = CleanupConstantGlobalUsers(GV, GV->getInitializer()); + + // If the global is dead now, delete it. + if (GV->use_empty()) { + GV->eraseFromParent(); + ++NumDeleted; + Changed = true; + } + return Changed; + + } else if (GS.StoredType <= GlobalStatus::isInitializerStored) { + DEBUG(errs() << "MARKING CONSTANT: " << *GV); + GV->setConstant(true); + + // Clean up any obviously simplifiable users now. + CleanupConstantGlobalUsers(GV, GV->getInitializer()); + + // If the global is dead now, just nuke it. + if (GV->use_empty()) { + DEBUG(errs() << " *** Marking constant allowed us to simplify " + << "all users and delete global!\n"); + GV->eraseFromParent(); + ++NumDeleted; + } + + ++NumMarked; + return true; + } else if (!GV->getInitializer()->getType()->isSingleValueType()) { + if (TargetData *TD = getAnalysisIfAvailable()) + if (GlobalVariable *FirstNewGV = SRAGlobal(GV, *TD)) { + GVI = FirstNewGV; // Don't skip the newly produced globals! + return true; + } + } else if (GS.StoredType == GlobalStatus::isStoredOnce) { + // If the initial value for the global was an undef value, and if only + // one other value was stored into it, we can just change the + // initializer to be the stored value, then delete all stores to the + // global. This allows us to mark it constant. + if (Constant *SOVConstant = dyn_cast(GS.StoredOnceValue)) + if (isa(GV->getInitializer())) { + // Change the initial value here. + GV->setInitializer(SOVConstant); + + // Clean up any obviously simplifiable users now. + CleanupConstantGlobalUsers(GV, GV->getInitializer()); + + if (GV->use_empty()) { + DEBUG(errs() << " *** Substituting initializer allowed us to " + << "simplify all users and delete global!\n"); + GV->eraseFromParent(); + ++NumDeleted; + } else { + GVI = GV; + } + ++NumSubstitute; + return true; + } + + // Try to optimize globals based on the knowledge that only one value + // (besides its initializer) is ever stored to the global. + if (OptimizeOnceStoredGlobal(GV, GS.StoredOnceValue, GVI, + getAnalysisIfAvailable())) + return true; + + // Otherwise, if the global was not a boolean, we can shrink it to be a + // boolean. + if (Constant *SOVConstant = dyn_cast(GS.StoredOnceValue)) + if (TryToShrinkGlobalToBoolean(GV, SOVConstant)) { + ++NumShrunkToBool; + return true; + } + } + } + return false; +} + +/// ChangeCalleesToFastCall - Walk all of the direct calls of the specified +/// function, changing them to FastCC. +static void ChangeCalleesToFastCall(Function *F) { + for (Value::use_iterator UI = F->use_begin(), E = F->use_end(); UI != E;++UI){ + CallSite User(cast(*UI)); + User.setCallingConv(CallingConv::Fast); + } +} + +static AttrListPtr StripNest(const AttrListPtr &Attrs) { + for (unsigned i = 0, e = Attrs.getNumSlots(); i != e; ++i) { + if ((Attrs.getSlot(i).Attrs & Attribute::Nest) == 0) + continue; + + // There can be only one. + return Attrs.removeAttr(Attrs.getSlot(i).Index, Attribute::Nest); + } + + return Attrs; +} + +static void RemoveNestAttribute(Function *F) { + F->setAttributes(StripNest(F->getAttributes())); + for (Value::use_iterator UI = F->use_begin(), E = F->use_end(); UI != E;++UI){ + CallSite User(cast(*UI)); + User.setAttributes(StripNest(User.getAttributes())); + } +} + +bool GlobalOpt::OptimizeFunctions(Module &M) { + bool Changed = false; + // Optimize functions. + for (Module::iterator FI = M.begin(), E = M.end(); FI != E; ) { + Function *F = FI++; + // Functions without names cannot be referenced outside this module. + if (!F->hasName() && !F->isDeclaration()) + F->setLinkage(GlobalValue::InternalLinkage); + F->removeDeadConstantUsers(); + if (F->use_empty() && (F->hasLocalLinkage() || F->hasLinkOnceLinkage())) { + F->eraseFromParent(); + Changed = true; + ++NumFnDeleted; + } else if (F->hasLocalLinkage()) { + if (F->getCallingConv() == CallingConv::C && !F->isVarArg() && + !F->hasAddressTaken()) { + // If this function has C calling conventions, is not a varargs + // function, and is only called directly, promote it to use the Fast + // calling convention. + F->setCallingConv(CallingConv::Fast); + ChangeCalleesToFastCall(F); + ++NumFastCallFns; + Changed = true; + } + + if (F->getAttributes().hasAttrSomewhere(Attribute::Nest) && + !F->hasAddressTaken()) { + // The function is not used by a trampoline intrinsic, so it is safe + // to remove the 'nest' attribute. + RemoveNestAttribute(F); + ++NumNestRemoved; + Changed = true; + } + } + } + return Changed; +} + +bool GlobalOpt::OptimizeGlobalVars(Module &M) { + bool Changed = false; + for (Module::global_iterator GVI = M.global_begin(), E = M.global_end(); + GVI != E; ) { + GlobalVariable *GV = GVI++; + // Global variables without names cannot be referenced outside this module. + if (!GV->hasName() && !GV->isDeclaration()) + GV->setLinkage(GlobalValue::InternalLinkage); + // Simplify the initializer. + if (GV->hasInitializer()) + if (ConstantExpr *CE = dyn_cast(GV->getInitializer())) { + TargetData *TD = getAnalysisIfAvailable(); + Constant *New = ConstantFoldConstantExpression(CE, TD); + if (New && New != CE) + GV->setInitializer(New); + } + // Do more involved optimizations if the global is internal. + if (!GV->isConstant() && GV->hasLocalLinkage() && + GV->hasInitializer()) + Changed |= ProcessInternalGlobal(GV, GVI); + } + return Changed; +} + +/// FindGlobalCtors - Find the llvm.globalctors list, verifying that all +/// initializers have an init priority of 65535. +GlobalVariable *GlobalOpt::FindGlobalCtors(Module &M) { + for (Module::global_iterator I = M.global_begin(), E = M.global_end(); + I != E; ++I) + if (I->getName() == "llvm.global_ctors") { + // Found it, verify it's an array of { int, void()* }. + const ArrayType *ATy =dyn_cast(I->getType()->getElementType()); + if (!ATy) return 0; + const StructType *STy = dyn_cast(ATy->getElementType()); + if (!STy || STy->getNumElements() != 2 || + STy->getElementType(0) != Type::getInt32Ty(M.getContext())) return 0; + const PointerType *PFTy = dyn_cast(STy->getElementType(1)); + if (!PFTy) return 0; + const FunctionType *FTy = dyn_cast(PFTy->getElementType()); + if (!FTy || FTy->getReturnType() != Type::getVoidTy(M.getContext()) || + FTy->isVarArg() || FTy->getNumParams() != 0) + return 0; + + // Verify that the initializer is simple enough for us to handle. + if (!I->hasDefinitiveInitializer()) return 0; + ConstantArray *CA = dyn_cast(I->getInitializer()); + if (!CA) return 0; + for (User::op_iterator i = CA->op_begin(), e = CA->op_end(); i != e; ++i) + if (ConstantStruct *CS = dyn_cast(*i)) { + if (isa(CS->getOperand(1))) + continue; + + // Must have a function or null ptr. + if (!isa(CS->getOperand(1))) + return 0; + + // Init priority must be standard. + ConstantInt *CI = dyn_cast(CS->getOperand(0)); + if (!CI || CI->getZExtValue() != 65535) + return 0; + } else { + return 0; + } + + return I; + } + return 0; +} + +/// ParseGlobalCtors - Given a llvm.global_ctors list that we can understand, +/// return a list of the functions and null terminator as a vector. +static std::vector ParseGlobalCtors(GlobalVariable *GV) { + ConstantArray *CA = cast(GV->getInitializer()); + std::vector Result; + Result.reserve(CA->getNumOperands()); + for (User::op_iterator i = CA->op_begin(), e = CA->op_end(); i != e; ++i) { + ConstantStruct *CS = cast(*i); + Result.push_back(dyn_cast(CS->getOperand(1))); + } + return Result; +} + +/// InstallGlobalCtors - Given a specified llvm.global_ctors list, install the +/// specified array, returning the new global to use. +static GlobalVariable *InstallGlobalCtors(GlobalVariable *GCL, + const std::vector &Ctors) { + // If we made a change, reassemble the initializer list. + std::vector CSVals; + CSVals.push_back(ConstantInt::get(Type::getInt32Ty(GCL->getContext()),65535)); + CSVals.push_back(0); + + // Create the new init list. + std::vector CAList; + for (unsigned i = 0, e = Ctors.size(); i != e; ++i) { + if (Ctors[i]) { + CSVals[1] = Ctors[i]; + } else { + const Type *FTy = FunctionType::get(Type::getVoidTy(GCL->getContext()), + false); + const PointerType *PFTy = PointerType::getUnqual(FTy); + CSVals[1] = Constant::getNullValue(PFTy); + CSVals[0] = ConstantInt::get(Type::getInt32Ty(GCL->getContext()), + 2147483647); + } + CAList.push_back(ConstantStruct::get(GCL->getContext(), CSVals, false)); + } + + // Create the array initializer. + const Type *StructTy = + cast(GCL->getType()->getElementType())->getElementType(); + Constant *CA = ConstantArray::get(ArrayType::get(StructTy, + CAList.size()), CAList); + + // If we didn't change the number of elements, don't create a new GV. + if (CA->getType() == GCL->getInitializer()->getType()) { + GCL->setInitializer(CA); + return GCL; + } + + // Create the new global and insert it next to the existing list. + GlobalVariable *NGV = new GlobalVariable(CA->getType(), GCL->isConstant(), + GCL->getLinkage(), CA, "", + GCL->isThreadLocal()); + GCL->getParent()->getGlobalList().insert(GCL, NGV); + NGV->takeName(GCL); + + // Nuke the old list, replacing any uses with the new one. + if (!GCL->use_empty()) { + Constant *V = NGV; + if (V->getType() != GCL->getType()) + V = ConstantExpr::getBitCast(V, GCL->getType()); + GCL->replaceAllUsesWith(V); + } + GCL->eraseFromParent(); + + if (Ctors.size()) + return NGV; + else + return 0; +} + + +static Constant *getVal(DenseMap &ComputedValues, + Value *V) { + if (Constant *CV = dyn_cast(V)) return CV; + Constant *R = ComputedValues[V]; + assert(R && "Reference to an uncomputed value!"); + return R; +} + +/// isSimpleEnoughPointerToCommit - Return true if this constant is simple +/// enough for us to understand. In particular, if it is a cast of something, +/// we punt. We basically just support direct accesses to globals and GEP's of +/// globals. This should be kept up to date with CommitValueTo. +static bool isSimpleEnoughPointerToCommit(Constant *C) { + // Conservatively, avoid aggregate types. This is because we don't + // want to worry about them partially overlapping other stores. + if (!cast(C->getType())->getElementType()->isSingleValueType()) + return false; + + if (GlobalVariable *GV = dyn_cast(C)) + // Do not allow weak/linkonce/dllimport/dllexport linkage or + // external globals. + return GV->hasDefinitiveInitializer(); + + if (ConstantExpr *CE = dyn_cast(C)) + // Handle a constantexpr gep. + if (CE->getOpcode() == Instruction::GetElementPtr && + isa(CE->getOperand(0)) && + cast(CE)->isInBounds()) { + GlobalVariable *GV = cast(CE->getOperand(0)); + // Do not allow weak/linkonce/dllimport/dllexport linkage or + // external globals. + if (!GV->hasDefinitiveInitializer()) + return false; + + // The first index must be zero. + ConstantInt *CI = dyn_cast(*next(CE->op_begin())); + if (!CI || !CI->isZero()) return false; + + // The remaining indices must be compile-time known integers within the + // notional bounds of the corresponding static array types. + if (!CE->isGEPWithNoNotionalOverIndexing()) + return false; + + return ConstantFoldLoadThroughGEPConstantExpr(GV->getInitializer(), CE); + } + return false; +} + +/// EvaluateStoreInto - Evaluate a piece of a constantexpr store into a global +/// initializer. This returns 'Init' modified to reflect 'Val' stored into it. +/// At this point, the GEP operands of Addr [0, OpNo) have been stepped into. +static Constant *EvaluateStoreInto(Constant *Init, Constant *Val, + ConstantExpr *Addr, unsigned OpNo) { + // Base case of the recursion. + if (OpNo == Addr->getNumOperands()) { + assert(Val->getType() == Init->getType() && "Type mismatch!"); + return Val; + } + + if (const StructType *STy = dyn_cast(Init->getType())) { + std::vector Elts; + + // Break up the constant into its elements. + if (ConstantStruct *CS = dyn_cast(Init)) { + for (User::op_iterator i = CS->op_begin(), e = CS->op_end(); i != e; ++i) + Elts.push_back(cast(*i)); + } else if (isa(Init)) { + for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) + Elts.push_back(Constant::getNullValue(STy->getElementType(i))); + } else if (isa(Init)) { + for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) + Elts.push_back(UndefValue::get(STy->getElementType(i))); + } else { + llvm_unreachable("This code is out of sync with " + " ConstantFoldLoadThroughGEPConstantExpr"); + } + + // Replace the element that we are supposed to. + ConstantInt *CU = cast(Addr->getOperand(OpNo)); + unsigned Idx = CU->getZExtValue(); + assert(Idx < STy->getNumElements() && "Struct index out of range!"); + Elts[Idx] = EvaluateStoreInto(Elts[Idx], Val, Addr, OpNo+1); + + // Return the modified struct. + return ConstantStruct::get(Init->getContext(), &Elts[0], Elts.size(), + STy->isPacked()); + } else { + ConstantInt *CI = cast(Addr->getOperand(OpNo)); + const ArrayType *ATy = cast(Init->getType()); + + // Break up the array into elements. + std::vector Elts; + if (ConstantArray *CA = dyn_cast(Init)) { + for (User::op_iterator i = CA->op_begin(), e = CA->op_end(); i != e; ++i) + Elts.push_back(cast(*i)); + } else if (isa(Init)) { + Constant *Elt = Constant::getNullValue(ATy->getElementType()); + Elts.assign(ATy->getNumElements(), Elt); + } else if (isa(Init)) { + Constant *Elt = UndefValue::get(ATy->getElementType()); + Elts.assign(ATy->getNumElements(), Elt); + } else { + llvm_unreachable("This code is out of sync with " + " ConstantFoldLoadThroughGEPConstantExpr"); + } + + assert(CI->getZExtValue() < ATy->getNumElements()); + Elts[CI->getZExtValue()] = + EvaluateStoreInto(Elts[CI->getZExtValue()], Val, Addr, OpNo+1); + return ConstantArray::get(ATy, Elts); + } +} + +/// CommitValueTo - We have decided that Addr (which satisfies the predicate +/// isSimpleEnoughPointerToCommit) should get Val as its value. Make it happen. +static void CommitValueTo(Constant *Val, Constant *Addr) { + if (GlobalVariable *GV = dyn_cast(Addr)) { + assert(GV->hasInitializer()); + GV->setInitializer(Val); + return; + } + + ConstantExpr *CE = cast(Addr); + GlobalVariable *GV = cast(CE->getOperand(0)); + + Constant *Init = GV->getInitializer(); + Init = EvaluateStoreInto(Init, Val, CE, 2); + GV->setInitializer(Init); +} + +/// ComputeLoadResult - Return the value that would be computed by a load from +/// P after the stores reflected by 'memory' have been performed. If we can't +/// decide, return null. +static Constant *ComputeLoadResult(Constant *P, + const DenseMap &Memory) { + // If this memory location has been recently stored, use the stored value: it + // is the most up-to-date. + DenseMap::const_iterator I = Memory.find(P); + if (I != Memory.end()) return I->second; + + // Access it. + if (GlobalVariable *GV = dyn_cast(P)) { + if (GV->hasDefinitiveInitializer()) + return GV->getInitializer(); + return 0; + } + + // Handle a constantexpr getelementptr. + if (ConstantExpr *CE = dyn_cast(P)) + if (CE->getOpcode() == Instruction::GetElementPtr && + isa(CE->getOperand(0))) { + GlobalVariable *GV = cast(CE->getOperand(0)); + if (GV->hasDefinitiveInitializer()) + return ConstantFoldLoadThroughGEPConstantExpr(GV->getInitializer(), CE); + } + + return 0; // don't know how to evaluate. +} + +/// EvaluateFunction - Evaluate a call to function F, returning true if +/// successful, false if we can't evaluate it. ActualArgs contains the formal +/// arguments for the function. +static bool EvaluateFunction(Function *F, Constant *&RetVal, + const SmallVectorImpl &ActualArgs, + std::vector &CallStack, + DenseMap &MutatedMemory, + std::vector &AllocaTmps) { + // Check to see if this function is already executing (recursion). If so, + // bail out. TODO: we might want to accept limited recursion. + if (std::find(CallStack.begin(), CallStack.end(), F) != CallStack.end()) + return false; + + CallStack.push_back(F); + + /// Values - As we compute SSA register values, we store their contents here. + DenseMap Values; + + // Initialize arguments to the incoming values specified. + unsigned ArgNo = 0; + for (Function::arg_iterator AI = F->arg_begin(), E = F->arg_end(); AI != E; + ++AI, ++ArgNo) + Values[AI] = ActualArgs[ArgNo]; + + /// ExecutedBlocks - We only handle non-looping, non-recursive code. As such, + /// we can only evaluate any one basic block at most once. This set keeps + /// track of what we have executed so we can detect recursive cases etc. + SmallPtrSet ExecutedBlocks; + + // CurInst - The current instruction we're evaluating. + BasicBlock::iterator CurInst = F->begin()->begin(); + + // This is the main evaluation loop. + while (1) { + Constant *InstResult = 0; + + if (StoreInst *SI = dyn_cast(CurInst)) { + if (SI->isVolatile()) return false; // no volatile accesses. + Constant *Ptr = getVal(Values, SI->getOperand(1)); + if (!isSimpleEnoughPointerToCommit(Ptr)) + // If this is too complex for us to commit, reject it. + return false; + Constant *Val = getVal(Values, SI->getOperand(0)); + MutatedMemory[Ptr] = Val; + } else if (BinaryOperator *BO = dyn_cast(CurInst)) { + InstResult = ConstantExpr::get(BO->getOpcode(), + getVal(Values, BO->getOperand(0)), + getVal(Values, BO->getOperand(1))); + } else if (CmpInst *CI = dyn_cast(CurInst)) { + InstResult = ConstantExpr::getCompare(CI->getPredicate(), + getVal(Values, CI->getOperand(0)), + getVal(Values, CI->getOperand(1))); + } else if (CastInst *CI = dyn_cast(CurInst)) { + InstResult = ConstantExpr::getCast(CI->getOpcode(), + getVal(Values, CI->getOperand(0)), + CI->getType()); + } else if (SelectInst *SI = dyn_cast(CurInst)) { + InstResult = + ConstantExpr::getSelect(getVal(Values, SI->getOperand(0)), + getVal(Values, SI->getOperand(1)), + getVal(Values, SI->getOperand(2))); + } else if (GetElementPtrInst *GEP = dyn_cast(CurInst)) { + Constant *P = getVal(Values, GEP->getOperand(0)); + SmallVector GEPOps; + for (User::op_iterator i = GEP->op_begin() + 1, e = GEP->op_end(); + i != e; ++i) + GEPOps.push_back(getVal(Values, *i)); + InstResult = cast(GEP)->isInBounds() ? + ConstantExpr::getInBoundsGetElementPtr(P, &GEPOps[0], GEPOps.size()) : + ConstantExpr::getGetElementPtr(P, &GEPOps[0], GEPOps.size()); + } else if (LoadInst *LI = dyn_cast(CurInst)) { + if (LI->isVolatile()) return false; // no volatile accesses. + InstResult = ComputeLoadResult(getVal(Values, LI->getOperand(0)), + MutatedMemory); + if (InstResult == 0) return false; // Could not evaluate load. + } else if (AllocaInst *AI = dyn_cast(CurInst)) { + if (AI->isArrayAllocation()) return false; // Cannot handle array allocs. + const Type *Ty = AI->getType()->getElementType(); + AllocaTmps.push_back(new GlobalVariable(Ty, false, + GlobalValue::InternalLinkage, + UndefValue::get(Ty), + AI->getName())); + InstResult = AllocaTmps.back(); + } else if (CallInst *CI = dyn_cast(CurInst)) { + + // Debug info can safely be ignored here. + if (isa(CI)) { + ++CurInst; + continue; + } + + // Cannot handle inline asm. + if (isa(CI->getOperand(0))) return false; + + // Resolve function pointers. + Function *Callee = dyn_cast(getVal(Values, CI->getOperand(0))); + if (!Callee) return false; // Cannot resolve. + + SmallVector Formals; + for (User::op_iterator i = CI->op_begin() + 1, e = CI->op_end(); + i != e; ++i) + Formals.push_back(getVal(Values, *i)); + + if (Callee->isDeclaration()) { + // If this is a function we can constant fold, do it. + if (Constant *C = ConstantFoldCall(Callee, Formals.data(), + Formals.size())) { + InstResult = C; + } else { + return false; + } + } else { + if (Callee->getFunctionType()->isVarArg()) + return false; + + Constant *RetVal; + // Execute the call, if successful, use the return value. + if (!EvaluateFunction(Callee, RetVal, Formals, CallStack, + MutatedMemory, AllocaTmps)) + return false; + InstResult = RetVal; + } + } else if (isa(CurInst)) { + BasicBlock *NewBB = 0; + if (BranchInst *BI = dyn_cast(CurInst)) { + if (BI->isUnconditional()) { + NewBB = BI->getSuccessor(0); + } else { + ConstantInt *Cond = + dyn_cast(getVal(Values, BI->getCondition())); + if (!Cond) return false; // Cannot determine. + + NewBB = BI->getSuccessor(!Cond->getZExtValue()); + } + } else if (SwitchInst *SI = dyn_cast(CurInst)) { + ConstantInt *Val = + dyn_cast(getVal(Values, SI->getCondition())); + if (!Val) return false; // Cannot determine. + NewBB = SI->getSuccessor(SI->findCaseValue(Val)); + } else if (IndirectBrInst *IBI = dyn_cast(CurInst)) { + Value *Val = getVal(Values, IBI->getAddress())->stripPointerCasts(); + if (BlockAddress *BA = dyn_cast(Val)) + NewBB = BA->getBasicBlock(); + else + return false; // Cannot determine. + } else if (ReturnInst *RI = dyn_cast(CurInst)) { + if (RI->getNumOperands()) + RetVal = getVal(Values, RI->getOperand(0)); + + CallStack.pop_back(); // return from fn. + return true; // We succeeded at evaluating this ctor! + } else { + // invoke, unwind, unreachable. + return false; // Cannot handle this terminator. + } + + // Okay, we succeeded in evaluating this control flow. See if we have + // executed the new block before. If so, we have a looping function, + // which we cannot evaluate in reasonable time. + if (!ExecutedBlocks.insert(NewBB)) + return false; // looped! + + // Okay, we have never been in this block before. Check to see if there + // are any PHI nodes. If so, evaluate them with information about where + // we came from. + BasicBlock *OldBB = CurInst->getParent(); + CurInst = NewBB->begin(); + PHINode *PN; + for (; (PN = dyn_cast(CurInst)); ++CurInst) + Values[PN] = getVal(Values, PN->getIncomingValueForBlock(OldBB)); + + // Do NOT increment CurInst. We know that the terminator had no value. + continue; + } else { + // Did not know how to evaluate this! + return false; + } + + if (!CurInst->use_empty()) + Values[CurInst] = InstResult; + + // Advance program counter. + ++CurInst; + } +} + +/// EvaluateStaticConstructor - Evaluate static constructors in the function, if +/// we can. Return true if we can, false otherwise. +static bool EvaluateStaticConstructor(Function *F) { + /// MutatedMemory - For each store we execute, we update this map. Loads + /// check this to get the most up-to-date value. If evaluation is successful, + /// this state is committed to the process. + DenseMap MutatedMemory; + + /// AllocaTmps - To 'execute' an alloca, we create a temporary global variable + /// to represent its body. This vector is needed so we can delete the + /// temporary globals when we are done. + std::vector AllocaTmps; + + /// CallStack - This is used to detect recursion. In pathological situations + /// we could hit exponential behavior, but at least there is nothing + /// unbounded. + std::vector CallStack; + + // Call the function. + Constant *RetValDummy; + bool EvalSuccess = EvaluateFunction(F, RetValDummy, + SmallVector(), CallStack, + MutatedMemory, AllocaTmps); + if (EvalSuccess) { + // We succeeded at evaluation: commit the result. + DEBUG(errs() << "FULLY EVALUATED GLOBAL CTOR FUNCTION '" + << F->getName() << "' to " << MutatedMemory.size() + << " stores.\n"); + for (DenseMap::iterator I = MutatedMemory.begin(), + E = MutatedMemory.end(); I != E; ++I) + CommitValueTo(I->second, I->first); + } + + // At this point, we are done interpreting. If we created any 'alloca' + // temporaries, release them now. + while (!AllocaTmps.empty()) { + GlobalVariable *Tmp = AllocaTmps.back(); + AllocaTmps.pop_back(); + + // If there are still users of the alloca, the program is doing something + // silly, e.g. storing the address of the alloca somewhere and using it + // later. Since this is undefined, we'll just make it be null. + if (!Tmp->use_empty()) + Tmp->replaceAllUsesWith(Constant::getNullValue(Tmp->getType())); + delete Tmp; + } + + return EvalSuccess; +} + + + +/// OptimizeGlobalCtorsList - Simplify and evaluation global ctors if possible. +/// Return true if anything changed. +bool GlobalOpt::OptimizeGlobalCtorsList(GlobalVariable *&GCL) { + std::vector Ctors = ParseGlobalCtors(GCL); + bool MadeChange = false; + if (Ctors.empty()) return false; + + // Loop over global ctors, optimizing them when we can. + for (unsigned i = 0; i != Ctors.size(); ++i) { + Function *F = Ctors[i]; + // Found a null terminator in the middle of the list, prune off the rest of + // the list. + if (F == 0) { + if (i != Ctors.size()-1) { + Ctors.resize(i+1); + MadeChange = true; + } + break; + } + + // We cannot simplify external ctor functions. + if (F->empty()) continue; + + // If we can evaluate the ctor at compile time, do. + if (EvaluateStaticConstructor(F)) { + Ctors.erase(Ctors.begin()+i); + MadeChange = true; + --i; + ++NumCtorsEvaluated; + continue; + } + } + + if (!MadeChange) return false; + + GCL = InstallGlobalCtors(GCL, Ctors); + return true; +} + +bool GlobalOpt::OptimizeGlobalAliases(Module &M) { + bool Changed = false; + + for (Module::alias_iterator I = M.alias_begin(), E = M.alias_end(); + I != E;) { + Module::alias_iterator J = I++; + // Aliases without names cannot be referenced outside this module. + if (!J->hasName() && !J->isDeclaration()) + J->setLinkage(GlobalValue::InternalLinkage); + // If the aliasee may change at link time, nothing can be done - bail out. + if (J->mayBeOverridden()) + continue; + + Constant *Aliasee = J->getAliasee(); + GlobalValue *Target = cast(Aliasee->stripPointerCasts()); + Target->removeDeadConstantUsers(); + bool hasOneUse = Target->hasOneUse() && Aliasee->hasOneUse(); + + // Make all users of the alias use the aliasee instead. + if (!J->use_empty()) { + J->replaceAllUsesWith(Aliasee); + ++NumAliasesResolved; + Changed = true; + } + + // If the aliasee has internal linkage, give it the name and linkage + // of the alias, and delete the alias. This turns: + // define internal ... @f(...) + // @a = alias ... @f + // into: + // define ... @a(...) + if (!Target->hasLocalLinkage()) + continue; + + // The transform is only useful if the alias does not have internal linkage. + if (J->hasLocalLinkage()) + continue; + + // Do not perform the transform if multiple aliases potentially target the + // aliasee. This check also ensures that it is safe to replace the section + // and other attributes of the aliasee with those of the alias. + if (!hasOneUse) + continue; + + // Give the aliasee the name, linkage and other attributes of the alias. + Target->takeName(J); + Target->setLinkage(J->getLinkage()); + Target->GlobalValue::copyAttributesFrom(J); + + // Delete the alias. + M.getAliasList().erase(J); + ++NumAliasesRemoved; + Changed = true; + } + + return Changed; +} + +bool GlobalOpt::runOnModule(Module &M) { + bool Changed = false; + + // Try to find the llvm.globalctors list. + GlobalVariable *GlobalCtors = FindGlobalCtors(M); + + bool LocalChange = true; + while (LocalChange) { + LocalChange = false; + + // Delete functions that are trivially dead, ccc -> fastcc + LocalChange |= OptimizeFunctions(M); + + // Optimize global_ctors list. + if (GlobalCtors) + LocalChange |= OptimizeGlobalCtorsList(GlobalCtors); + + // Optimize non-address-taken globals. + LocalChange |= OptimizeGlobalVars(M); + + // Resolve aliases, when possible. + LocalChange |= OptimizeGlobalAliases(M); + Changed |= LocalChange; + } + + // TODO: Move all global ctors functions to the end of the module for code + // layout. + + return Changed; +} diff --git a/libclamav/c++/llvm/lib/Transforms/IPO/IPConstantPropagation.cpp b/libclamav/c++/llvm/lib/Transforms/IPO/IPConstantPropagation.cpp new file mode 100644 index 000000000..df2456f9f --- /dev/null +++ b/libclamav/c++/llvm/lib/Transforms/IPO/IPConstantPropagation.cpp @@ -0,0 +1,276 @@ +//===-- IPConstantPropagation.cpp - Propagate constants through calls -----===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This pass implements an _extremely_ simple interprocedural constant +// propagation pass. It could certainly be improved in many different ways, +// like using a worklist. This pass makes arguments dead, but does not remove +// them. The existing dead argument elimination pass should be run after this +// to clean up the mess. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "ipconstprop" +#include "llvm/Transforms/IPO.h" +#include "llvm/Constants.h" +#include "llvm/Instructions.h" +#include "llvm/Module.h" +#include "llvm/Pass.h" +#include "llvm/Analysis/ValueTracking.h" +#include "llvm/Support/CallSite.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/ADT/SmallVector.h" +using namespace llvm; + +STATISTIC(NumArgumentsProped, "Number of args turned into constants"); +STATISTIC(NumReturnValProped, "Number of return values turned into constants"); + +namespace { + /// IPCP - The interprocedural constant propagation pass + /// + struct IPCP : public ModulePass { + static char ID; // Pass identification, replacement for typeid + IPCP() : ModulePass(&ID) {} + + bool runOnModule(Module &M); + private: + bool PropagateConstantsIntoArguments(Function &F); + bool PropagateConstantReturn(Function &F); + }; +} + +char IPCP::ID = 0; +static RegisterPass +X("ipconstprop", "Interprocedural constant propagation"); + +ModulePass *llvm::createIPConstantPropagationPass() { return new IPCP(); } + +bool IPCP::runOnModule(Module &M) { + bool Changed = false; + bool LocalChange = true; + + // FIXME: instead of using smart algorithms, we just iterate until we stop + // making changes. + while (LocalChange) { + LocalChange = false; + for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) + if (!I->isDeclaration()) { + // Delete any klingons. + I->removeDeadConstantUsers(); + if (I->hasLocalLinkage()) + LocalChange |= PropagateConstantsIntoArguments(*I); + Changed |= PropagateConstantReturn(*I); + } + Changed |= LocalChange; + } + return Changed; +} + +/// PropagateConstantsIntoArguments - Look at all uses of the specified +/// function. If all uses are direct call sites, and all pass a particular +/// constant in for an argument, propagate that constant in as the argument. +/// +bool IPCP::PropagateConstantsIntoArguments(Function &F) { + if (F.arg_empty() || F.use_empty()) return false; // No arguments? Early exit. + + // For each argument, keep track of its constant value and whether it is a + // constant or not. The bool is driven to true when found to be non-constant. + SmallVector, 16> ArgumentConstants; + ArgumentConstants.resize(F.arg_size()); + + unsigned NumNonconstant = 0; + for (Value::use_iterator UI = F.use_begin(), E = F.use_end(); UI != E; ++UI) { + // Ignore blockaddress uses. + if (isa(*UI)) continue; + + // Used by a non-instruction, or not the callee of a function, do not + // transform. + if (!isa(*UI) && !isa(*UI)) + return false; + + CallSite CS = CallSite::get(cast(*UI)); + if (!CS.isCallee(UI)) + return false; + + // Check out all of the potentially constant arguments. Note that we don't + // inspect varargs here. + CallSite::arg_iterator AI = CS.arg_begin(); + Function::arg_iterator Arg = F.arg_begin(); + for (unsigned i = 0, e = ArgumentConstants.size(); i != e; + ++i, ++AI, ++Arg) { + + // If this argument is known non-constant, ignore it. + if (ArgumentConstants[i].second) + continue; + + Constant *C = dyn_cast(*AI); + if (C && ArgumentConstants[i].first == 0) { + ArgumentConstants[i].first = C; // First constant seen. + } else if (C && ArgumentConstants[i].first == C) { + // Still the constant value we think it is. + } else if (*AI == &*Arg) { + // Ignore recursive calls passing argument down. + } else { + // Argument became non-constant. If all arguments are non-constant now, + // give up on this function. + if (++NumNonconstant == ArgumentConstants.size()) + return false; + ArgumentConstants[i].second = true; + } + } + } + + // If we got to this point, there is a constant argument! + assert(NumNonconstant != ArgumentConstants.size()); + bool MadeChange = false; + Function::arg_iterator AI = F.arg_begin(); + for (unsigned i = 0, e = ArgumentConstants.size(); i != e; ++i, ++AI) { + // Do we have a constant argument? + if (ArgumentConstants[i].second || AI->use_empty() || + (AI->hasByValAttr() && !F.onlyReadsMemory())) + continue; + + Value *V = ArgumentConstants[i].first; + if (V == 0) V = UndefValue::get(AI->getType()); + AI->replaceAllUsesWith(V); + ++NumArgumentsProped; + MadeChange = true; + } + return MadeChange; +} + + +// Check to see if this function returns one or more constants. If so, replace +// all callers that use those return values with the constant value. This will +// leave in the actual return values and instructions, but deadargelim will +// clean that up. +// +// Additionally if a function always returns one of its arguments directly, +// callers will be updated to use the value they pass in directly instead of +// using the return value. +bool IPCP::PropagateConstantReturn(Function &F) { + if (F.getReturnType()->isVoidTy()) + return false; // No return value. + + // If this function could be overridden later in the link stage, we can't + // propagate information about its results into callers. + if (F.mayBeOverridden()) + return false; + + // Check to see if this function returns a constant. + SmallVector RetVals; + const StructType *STy = dyn_cast(F.getReturnType()); + if (STy) + for (unsigned i = 0, e = STy->getNumElements(); i < e; ++i) + RetVals.push_back(UndefValue::get(STy->getElementType(i))); + else + RetVals.push_back(UndefValue::get(F.getReturnType())); + + unsigned NumNonConstant = 0; + for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB) + if (ReturnInst *RI = dyn_cast(BB->getTerminator())) { + for (unsigned i = 0, e = RetVals.size(); i != e; ++i) { + // Already found conflicting return values? + Value *RV = RetVals[i]; + if (!RV) + continue; + + // Find the returned value + Value *V; + if (!STy) + V = RI->getOperand(i); + else + V = FindInsertedValue(RI->getOperand(0), i); + + if (V) { + // Ignore undefs, we can change them into anything + if (isa(V)) + continue; + + // Try to see if all the rets return the same constant or argument. + if (isa(V) || isa(V)) { + if (isa(RV)) { + // No value found yet? Try the current one. + RetVals[i] = V; + continue; + } + // Returning the same value? Good. + if (RV == V) + continue; + } + } + // Different or no known return value? Don't propagate this return + // value. + RetVals[i] = 0; + // All values non constant? Stop looking. + if (++NumNonConstant == RetVals.size()) + return false; + } + } + + // If we got here, the function returns at least one constant value. Loop + // over all users, replacing any uses of the return value with the returned + // constant. + bool MadeChange = false; + for (Value::use_iterator UI = F.use_begin(), E = F.use_end(); UI != E; ++UI) { + CallSite CS = CallSite::get(*UI); + Instruction* Call = CS.getInstruction(); + + // Not a call instruction or a call instruction that's not calling F + // directly? + if (!Call || !CS.isCallee(UI)) + continue; + + // Call result not used? + if (Call->use_empty()) + continue; + + MadeChange = true; + + if (STy == 0) { + Value* New = RetVals[0]; + if (Argument *A = dyn_cast(New)) + // Was an argument returned? Then find the corresponding argument in + // the call instruction and use that. + New = CS.getArgument(A->getArgNo()); + Call->replaceAllUsesWith(New); + continue; + } + + for (Value::use_iterator I = Call->use_begin(), E = Call->use_end(); + I != E;) { + Instruction *Ins = cast(*I); + + // Increment now, so we can remove the use + ++I; + + // Find the index of the retval to replace with + int index = -1; + if (ExtractValueInst *EV = dyn_cast(Ins)) + if (EV->hasIndices()) + index = *EV->idx_begin(); + + // If this use uses a specific return value, and we have a replacement, + // replace it. + if (index != -1) { + Value *New = RetVals[index]; + if (New) { + if (Argument *A = dyn_cast(New)) + // Was an argument returned? Then find the corresponding argument in + // the call instruction and use that. + New = CS.getArgument(A->getArgNo()); + Ins->replaceAllUsesWith(New); + Ins->eraseFromParent(); + } + } + } + } + + if (MadeChange) ++NumReturnValProped; + return MadeChange; +} diff --git a/libclamav/c++/llvm/lib/Transforms/IPO/IPO.cpp b/libclamav/c++/llvm/lib/Transforms/IPO/IPO.cpp new file mode 100644 index 000000000..83e8624fe --- /dev/null +++ b/libclamav/c++/llvm/lib/Transforms/IPO/IPO.cpp @@ -0,0 +1,75 @@ +//===-- Scalar.cpp --------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the C bindings for libLLVMIPO.a, which implements +// several transformations over the LLVM intermediate representation. +// +//===----------------------------------------------------------------------===// + +#include "llvm-c/Transforms/IPO.h" +#include "llvm/PassManager.h" +#include "llvm/Transforms/IPO.h" + +using namespace llvm; + +void LLVMAddArgumentPromotionPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(createArgumentPromotionPass()); +} + +void LLVMAddConstantMergePass(LLVMPassManagerRef PM) { + unwrap(PM)->add(createConstantMergePass()); +} + +void LLVMAddDeadArgEliminationPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(createDeadArgEliminationPass()); +} + +void LLVMAddDeadTypeEliminationPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(createDeadTypeEliminationPass()); +} + +void LLVMAddFunctionAttrsPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(createFunctionAttrsPass()); +} + +void LLVMAddFunctionInliningPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(createFunctionInliningPass()); +} + +void LLVMAddGlobalDCEPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(createGlobalDCEPass()); +} + +void LLVMAddGlobalOptimizerPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(createGlobalOptimizerPass()); +} + +void LLVMAddIPConstantPropagationPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(createIPConstantPropagationPass()); +} + +void LLVMAddLowerSetJmpPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(createLowerSetJmpPass()); +} + +void LLVMAddPruneEHPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(createPruneEHPass()); +} + +void LLVMAddRaiseAllocationsPass(LLVMPassManagerRef PM) { + // FIXME: Remove in LLVM 3.0. +} + +void LLVMAddStripDeadPrototypesPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(createStripDeadPrototypesPass()); +} + +void LLVMAddStripSymbolsPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(createStripSymbolsPass()); +} diff --git a/libclamav/c++/llvm/lib/Transforms/IPO/InlineAlways.cpp b/libclamav/c++/llvm/lib/Transforms/IPO/InlineAlways.cpp new file mode 100644 index 000000000..f11ecae8d --- /dev/null +++ b/libclamav/c++/llvm/lib/Transforms/IPO/InlineAlways.cpp @@ -0,0 +1,74 @@ +//===- InlineAlways.cpp - Code to inline always_inline functions ----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements a custom inliner that handles only functions that +// are marked as "always inline". +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "inline" +#include "llvm/CallingConv.h" +#include "llvm/Instructions.h" +#include "llvm/IntrinsicInst.h" +#include "llvm/Module.h" +#include "llvm/Type.h" +#include "llvm/Analysis/CallGraph.h" +#include "llvm/Analysis/InlineCost.h" +#include "llvm/Support/CallSite.h" +#include "llvm/Transforms/IPO.h" +#include "llvm/Transforms/IPO/InlinerPass.h" +#include "llvm/ADT/SmallPtrSet.h" + +using namespace llvm; + +namespace { + + // AlwaysInliner only inlines functions that are mark as "always inline". + class AlwaysInliner : public Inliner { + // Functions that are never inlined + SmallPtrSet NeverInline; + InlineCostAnalyzer CA; + public: + // Use extremely low threshold. + AlwaysInliner() : Inliner(&ID, -2000000000) {} + static char ID; // Pass identification, replacement for typeid + InlineCost getInlineCost(CallSite CS) { + return CA.getInlineCost(CS, NeverInline); + } + float getInlineFudgeFactor(CallSite CS) { + return CA.getInlineFudgeFactor(CS); + } + void resetCachedCostInfo(Function *Caller) { + return CA.resetCachedCostInfo(Caller); + } + virtual bool doFinalization(CallGraph &CG) { + return removeDeadFunctions(CG, &NeverInline); + } + virtual bool doInitialization(CallGraph &CG); + }; +} + +char AlwaysInliner::ID = 0; +static RegisterPass +X("always-inline", "Inliner for always_inline functions"); + +Pass *llvm::createAlwaysInlinerPass() { return new AlwaysInliner(); } + +// doInitialization - Initializes the vector of functions that have not +// been annotated with the "always inline" attribute. +bool AlwaysInliner::doInitialization(CallGraph &CG) { + Module &M = CG.getModule(); + + for (Module::iterator I = M.begin(), E = M.end(); + I != E; ++I) + if (!I->isDeclaration() && !I->hasFnAttr(Attribute::AlwaysInline)) + NeverInline.insert(I); + + return false; +} diff --git a/libclamav/c++/llvm/lib/Transforms/IPO/InlineSimple.cpp b/libclamav/c++/llvm/lib/Transforms/IPO/InlineSimple.cpp new file mode 100644 index 000000000..598043de6 --- /dev/null +++ b/libclamav/c++/llvm/lib/Transforms/IPO/InlineSimple.cpp @@ -0,0 +1,105 @@ +//===- InlineSimple.cpp - Code to perform simple function inlining --------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements bottom-up inlining of functions into callees. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "inline" +#include "llvm/CallingConv.h" +#include "llvm/Instructions.h" +#include "llvm/IntrinsicInst.h" +#include "llvm/Module.h" +#include "llvm/Type.h" +#include "llvm/Analysis/CallGraph.h" +#include "llvm/Analysis/InlineCost.h" +#include "llvm/Support/CallSite.h" +#include "llvm/Transforms/IPO.h" +#include "llvm/Transforms/IPO/InlinerPass.h" +#include "llvm/ADT/SmallPtrSet.h" + +using namespace llvm; + +namespace { + + class SimpleInliner : public Inliner { + // Functions that are never inlined + SmallPtrSet NeverInline; + InlineCostAnalyzer CA; + public: + SimpleInliner() : Inliner(&ID) {} + SimpleInliner(int Threshold) : Inliner(&ID, Threshold) {} + static char ID; // Pass identification, replacement for typeid + InlineCost getInlineCost(CallSite CS) { + return CA.getInlineCost(CS, NeverInline); + } + float getInlineFudgeFactor(CallSite CS) { + return CA.getInlineFudgeFactor(CS); + } + void resetCachedCostInfo(Function *Caller) { + CA.resetCachedCostInfo(Caller); + } + virtual bool doInitialization(CallGraph &CG); + }; +} + +char SimpleInliner::ID = 0; +static RegisterPass +X("inline", "Function Integration/Inlining"); + +Pass *llvm::createFunctionInliningPass() { return new SimpleInliner(); } + +Pass *llvm::createFunctionInliningPass(int Threshold) { + return new SimpleInliner(Threshold); +} + +// doInitialization - Initializes the vector of functions that have been +// annotated with the noinline attribute. +bool SimpleInliner::doInitialization(CallGraph &CG) { + + Module &M = CG.getModule(); + + for (Module::iterator I = M.begin(), E = M.end(); + I != E; ++I) + if (!I->isDeclaration() && I->hasFnAttr(Attribute::NoInline)) + NeverInline.insert(I); + + // Get llvm.noinline + GlobalVariable *GV = M.getNamedGlobal("llvm.noinline"); + + if (GV == 0) + return false; + + // Don't crash on invalid code + if (!GV->hasDefinitiveInitializer()) + return false; + + const ConstantArray *InitList = dyn_cast(GV->getInitializer()); + + if (InitList == 0) + return false; + + // Iterate over each element and add to the NeverInline set + for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i) { + + // Get Source + const Constant *Elt = InitList->getOperand(i); + + if (const ConstantExpr *CE = dyn_cast(Elt)) + if (CE->getOpcode() == Instruction::BitCast) + Elt = CE->getOperand(0); + + // Insert into set of functions to never inline + if (const Function *F = dyn_cast(Elt)) + NeverInline.insert(F); + } + + return false; +} + diff --git a/libclamav/c++/llvm/lib/Transforms/IPO/Inliner.cpp b/libclamav/c++/llvm/lib/Transforms/IPO/Inliner.cpp new file mode 100644 index 000000000..6918fe87c --- /dev/null +++ b/libclamav/c++/llvm/lib/Transforms/IPO/Inliner.cpp @@ -0,0 +1,481 @@ +//===- Inliner.cpp - Code common to all inliners --------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the mechanics required to implement inlining without +// missing any calls and updating the call graph. The decisions of which calls +// are profitable to inline are implemented elsewhere. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "inline" +#include "llvm/Module.h" +#include "llvm/Instructions.h" +#include "llvm/IntrinsicInst.h" +#include "llvm/Analysis/CallGraph.h" +#include "llvm/Analysis/InlineCost.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Transforms/IPO/InlinerPass.h" +#include "llvm/Transforms/Utils/Cloning.h" +#include "llvm/Transforms/Utils/Local.h" +#include "llvm/Support/CallSite.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/Statistic.h" +#include +using namespace llvm; + +STATISTIC(NumInlined, "Number of functions inlined"); +STATISTIC(NumCallsDeleted, "Number of call sites deleted, not inlined"); +STATISTIC(NumDeleted, "Number of functions deleted because all callers found"); +STATISTIC(NumMergedAllocas, "Number of allocas merged together"); + +static cl::opt +InlineLimit("inline-threshold", cl::Hidden, cl::init(200), cl::ZeroOrMore, + cl::desc("Control the amount of inlining to perform (default = 200)")); + +Inliner::Inliner(void *ID) + : CallGraphSCCPass(ID), InlineThreshold(InlineLimit) {} + +Inliner::Inliner(void *ID, int Threshold) + : CallGraphSCCPass(ID), InlineThreshold(Threshold) {} + +/// getAnalysisUsage - For this class, we declare that we require and preserve +/// the call graph. If the derived class implements this method, it should +/// always explicitly call the implementation here. +void Inliner::getAnalysisUsage(AnalysisUsage &Info) const { + CallGraphSCCPass::getAnalysisUsage(Info); +} + + +typedef DenseMap > +InlinedArrayAllocasTy; + +/// InlineCallIfPossible - If it is possible to inline the specified call site, +/// do so and update the CallGraph for this operation. +/// +/// This function also does some basic book-keeping to update the IR. The +/// InlinedArrayAllocas map keeps track of any allocas that are already +/// available from other functions inlined into the caller. If we are able to +/// inline this call site we attempt to reuse already available allocas or add +/// any new allocas to the set if not possible. +static bool InlineCallIfPossible(CallSite CS, CallGraph &CG, + const TargetData *TD, + InlinedArrayAllocasTy &InlinedArrayAllocas) { + Function *Callee = CS.getCalledFunction(); + Function *Caller = CS.getCaller(); + + // Try to inline the function. Get the list of static allocas that were + // inlined. + SmallVector StaticAllocas; + if (!InlineFunction(CS, &CG, TD, &StaticAllocas)) + return false; + + // If the inlined function had a higher stack protection level than the + // calling function, then bump up the caller's stack protection level. + if (Callee->hasFnAttr(Attribute::StackProtectReq)) + Caller->addFnAttr(Attribute::StackProtectReq); + else if (Callee->hasFnAttr(Attribute::StackProtect) && + !Caller->hasFnAttr(Attribute::StackProtectReq)) + Caller->addFnAttr(Attribute::StackProtect); + + + // Look at all of the allocas that we inlined through this call site. If we + // have already inlined other allocas through other calls into this function, + // then we know that they have disjoint lifetimes and that we can merge them. + // + // There are many heuristics possible for merging these allocas, and the + // different options have different tradeoffs. One thing that we *really* + // don't want to hurt is SRoA: once inlining happens, often allocas are no + // longer address taken and so they can be promoted. + // + // Our "solution" for that is to only merge allocas whose outermost type is an + // array type. These are usually not promoted because someone is using a + // variable index into them. These are also often the most important ones to + // merge. + // + // A better solution would be to have real memory lifetime markers in the IR + // and not have the inliner do any merging of allocas at all. This would + // allow the backend to do proper stack slot coloring of all allocas that + // *actually make it to the backend*, which is really what we want. + // + // Because we don't have this information, we do this simple and useful hack. + // + SmallPtrSet UsedAllocas; + + // Loop over all the allocas we have so far and see if they can be merged with + // a previously inlined alloca. If not, remember that we had it. + for (unsigned AllocaNo = 0, e = StaticAllocas.size(); + AllocaNo != e; ++AllocaNo) { + AllocaInst *AI = StaticAllocas[AllocaNo]; + + // Don't bother trying to merge array allocations (they will usually be + // canonicalized to be an allocation *of* an array), or allocations whose + // type is not itself an array (because we're afraid of pessimizing SRoA). + const ArrayType *ATy = dyn_cast(AI->getAllocatedType()); + if (ATy == 0 || AI->isArrayAllocation()) + continue; + + // Get the list of all available allocas for this array type. + std::vector &AllocasForType = InlinedArrayAllocas[ATy]; + + // Loop over the allocas in AllocasForType to see if we can reuse one. Note + // that we have to be careful not to reuse the same "available" alloca for + // multiple different allocas that we just inlined, we use the 'UsedAllocas' + // set to keep track of which "available" allocas are being used by this + // function. Also, AllocasForType can be empty of course! + bool MergedAwayAlloca = false; + for (unsigned i = 0, e = AllocasForType.size(); i != e; ++i) { + AllocaInst *AvailableAlloca = AllocasForType[i]; + + // The available alloca has to be in the right function, not in some other + // function in this SCC. + if (AvailableAlloca->getParent() != AI->getParent()) + continue; + + // If the inlined function already uses this alloca then we can't reuse + // it. + if (!UsedAllocas.insert(AvailableAlloca)) + continue; + + // Otherwise, we *can* reuse it, RAUW AI into AvailableAlloca and declare + // success! + DEBUG(errs() << " ***MERGED ALLOCA: " << *AI); + + AI->replaceAllUsesWith(AvailableAlloca); + AI->eraseFromParent(); + MergedAwayAlloca = true; + ++NumMergedAllocas; + break; + } + + // If we already nuked the alloca, we're done with it. + if (MergedAwayAlloca) + continue; + + // If we were unable to merge away the alloca either because there are no + // allocas of the right type available or because we reused them all + // already, remember that this alloca came from an inlined function and mark + // it used so we don't reuse it for other allocas from this inline + // operation. + AllocasForType.push_back(AI); + UsedAllocas.insert(AI); + } + + return true; +} + +/// shouldInline - Return true if the inliner should attempt to inline +/// at the given CallSite. +bool Inliner::shouldInline(CallSite CS) { + InlineCost IC = getInlineCost(CS); + + if (IC.isAlways()) { + DEBUG(errs() << " Inlining: cost=always" + << ", Call: " << *CS.getInstruction() << "\n"); + return true; + } + + if (IC.isNever()) { + DEBUG(errs() << " NOT Inlining: cost=never" + << ", Call: " << *CS.getInstruction() << "\n"); + return false; + } + + int Cost = IC.getValue(); + int CurrentThreshold = InlineThreshold; + Function *Caller = CS.getCaller(); + if (Caller && !Caller->isDeclaration() && + Caller->hasFnAttr(Attribute::OptimizeForSize) && + InlineLimit.getNumOccurrences() == 0 && + InlineThreshold != 50) + CurrentThreshold = 50; + + float FudgeFactor = getInlineFudgeFactor(CS); + if (Cost >= (int)(CurrentThreshold * FudgeFactor)) { + DEBUG(errs() << " NOT Inlining: cost=" << Cost + << ", Call: " << *CS.getInstruction() << "\n"); + return false; + } + + // Try to detect the case where the current inlining candidate caller + // (call it B) is a static function and is an inlining candidate elsewhere, + // and the current candidate callee (call it C) is large enough that + // inlining it into B would make B too big to inline later. In these + // circumstances it may be best not to inline C into B, but to inline B + // into its callers. + if (Caller->hasLocalLinkage()) { + int TotalSecondaryCost = 0; + bool outerCallsFound = false; + bool allOuterCallsWillBeInlined = true; + bool someOuterCallWouldNotBeInlined = false; + for (Value::use_iterator I = Caller->use_begin(), E =Caller->use_end(); + I != E; ++I) { + CallSite CS2 = CallSite::get(*I); + + // If this isn't a call to Caller (it could be some other sort + // of reference) skip it. + if (CS2.getInstruction() == 0 || CS2.getCalledFunction() != Caller) + continue; + + InlineCost IC2 = getInlineCost(CS2); + if (IC2.isNever()) + allOuterCallsWillBeInlined = false; + if (IC2.isAlways() || IC2.isNever()) + continue; + + outerCallsFound = true; + int Cost2 = IC2.getValue(); + int CurrentThreshold2 = InlineThreshold; + Function *Caller2 = CS2.getCaller(); + if (Caller2 && !Caller2->isDeclaration() && + Caller2->hasFnAttr(Attribute::OptimizeForSize) && + InlineThreshold != 50) + CurrentThreshold2 = 50; + + float FudgeFactor2 = getInlineFudgeFactor(CS2); + + if (Cost2 >= (int)(CurrentThreshold2 * FudgeFactor2)) + allOuterCallsWillBeInlined = false; + + // See if we have this case. We subtract off the penalty + // for the call instruction, which we would be deleting. + if (Cost2 < (int)(CurrentThreshold2 * FudgeFactor2) && + Cost2 + Cost - (InlineConstants::CallPenalty + 1) >= + (int)(CurrentThreshold2 * FudgeFactor2)) { + someOuterCallWouldNotBeInlined = true; + TotalSecondaryCost += Cost2; + } + } + // If all outer calls to Caller would get inlined, the cost for the last + // one is set very low by getInlineCost, in anticipation that Caller will + // be removed entirely. We did not account for this above unless there + // is only one caller of Caller. + if (allOuterCallsWillBeInlined && Caller->use_begin() != Caller->use_end()) + TotalSecondaryCost += InlineConstants::LastCallToStaticBonus; + + if (outerCallsFound && someOuterCallWouldNotBeInlined && + TotalSecondaryCost < Cost) { + DEBUG(errs() << " NOT Inlining: " << *CS.getInstruction() << + " Cost = " << Cost << + ", outer Cost = " << TotalSecondaryCost << '\n'); + return false; + } + } + + DEBUG(errs() << " Inlining: cost=" << Cost + << ", Call: " << *CS.getInstruction() << '\n'); + return true; +} + +bool Inliner::runOnSCC(std::vector &SCC) { + CallGraph &CG = getAnalysis(); + const TargetData *TD = getAnalysisIfAvailable(); + + SmallPtrSet SCCFunctions; + DEBUG(errs() << "Inliner visiting SCC:"); + for (unsigned i = 0, e = SCC.size(); i != e; ++i) { + Function *F = SCC[i]->getFunction(); + if (F) SCCFunctions.insert(F); + DEBUG(errs() << " " << (F ? F->getName() : "INDIRECTNODE")); + } + + // Scan through and identify all call sites ahead of time so that we only + // inline call sites in the original functions, not call sites that result + // from inlining other functions. + SmallVector CallSites; + + for (unsigned i = 0, e = SCC.size(); i != e; ++i) { + Function *F = SCC[i]->getFunction(); + if (!F) continue; + + for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) + for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ++I) { + CallSite CS = CallSite::get(I); + // If this isn't a call, or it is a call to an intrinsic, it can + // never be inlined. + if (CS.getInstruction() == 0 || isa(I)) + continue; + + // If this is a direct call to an external function, we can never inline + // it. If it is an indirect call, inlining may resolve it to be a + // direct call, so we keep it. + if (CS.getCalledFunction() && CS.getCalledFunction()->isDeclaration()) + continue; + + CallSites.push_back(CS); + } + } + + DEBUG(errs() << ": " << CallSites.size() << " call sites.\n"); + + // Now that we have all of the call sites, move the ones to functions in the + // current SCC to the end of the list. + unsigned FirstCallInSCC = CallSites.size(); + for (unsigned i = 0; i < FirstCallInSCC; ++i) + if (Function *F = CallSites[i].getCalledFunction()) + if (SCCFunctions.count(F)) + std::swap(CallSites[i--], CallSites[--FirstCallInSCC]); + + + InlinedArrayAllocasTy InlinedArrayAllocas; + + // Now that we have all of the call sites, loop over them and inline them if + // it looks profitable to do so. + bool Changed = false; + bool LocalChange; + do { + LocalChange = false; + // Iterate over the outer loop because inlining functions can cause indirect + // calls to become direct calls. + for (unsigned CSi = 0; CSi != CallSites.size(); ++CSi) { + CallSite CS = CallSites[CSi]; + + Function *Caller = CS.getCaller(); + Function *Callee = CS.getCalledFunction(); + + // If this call site is dead and it is to a readonly function, we should + // just delete the call instead of trying to inline it, regardless of + // size. This happens because IPSCCP propagates the result out of the + // call and then we're left with the dead call. + if (isInstructionTriviallyDead(CS.getInstruction())) { + DEBUG(errs() << " -> Deleting dead call: " + << *CS.getInstruction() << "\n"); + // Update the call graph by deleting the edge from Callee to Caller. + CG[Caller]->removeCallEdgeFor(CS); + CS.getInstruction()->eraseFromParent(); + ++NumCallsDeleted; + } else { + // We can only inline direct calls to non-declarations. + if (Callee == 0 || Callee->isDeclaration()) continue; + + // If the policy determines that we should inline this function, + // try to do so. + if (!shouldInline(CS)) + continue; + + // Attempt to inline the function... + if (!InlineCallIfPossible(CS, CG, TD, InlinedArrayAllocas)) + continue; + ++NumInlined; + } + + // If we inlined or deleted the last possible call site to the function, + // delete the function body now. + if (Callee && Callee->use_empty() && Callee->hasLocalLinkage() && + // TODO: Can remove if in SCC now. + !SCCFunctions.count(Callee) && + + // The function may be apparently dead, but if there are indirect + // callgraph references to the node, we cannot delete it yet, this + // could invalidate the CGSCC iterator. + CG[Callee]->getNumReferences() == 0) { + DEBUG(errs() << " -> Deleting dead function: " + << Callee->getName() << "\n"); + CallGraphNode *CalleeNode = CG[Callee]; + + // Remove any call graph edges from the callee to its callees. + CalleeNode->removeAllCalledFunctions(); + + resetCachedCostInfo(Callee); + + // Removing the node for callee from the call graph and delete it. + delete CG.removeFunctionFromModule(CalleeNode); + ++NumDeleted; + } + + // Remove any cached cost info for this caller, as inlining the + // callee has increased the size of the caller (which may be the + // same as the callee). + resetCachedCostInfo(Caller); + + // Remove this call site from the list. If possible, use + // swap/pop_back for efficiency, but do not use it if doing so would + // move a call site to a function in this SCC before the + // 'FirstCallInSCC' barrier. + if (SCC.size() == 1) { + std::swap(CallSites[CSi], CallSites.back()); + CallSites.pop_back(); + } else { + CallSites.erase(CallSites.begin()+CSi); + } + --CSi; + + Changed = true; + LocalChange = true; + } + } while (LocalChange); + + return Changed; +} + +// doFinalization - Remove now-dead linkonce functions at the end of +// processing to avoid breaking the SCC traversal. +bool Inliner::doFinalization(CallGraph &CG) { + return removeDeadFunctions(CG); +} + +/// removeDeadFunctions - Remove dead functions that are not included in +/// DNR (Do Not Remove) list. +bool Inliner::removeDeadFunctions(CallGraph &CG, + SmallPtrSet *DNR) { + SmallPtrSet FunctionsToRemove; + + // Scan for all of the functions, looking for ones that should now be removed + // from the program. Insert the dead ones in the FunctionsToRemove set. + for (CallGraph::iterator I = CG.begin(), E = CG.end(); I != E; ++I) { + CallGraphNode *CGN = I->second; + if (CGN->getFunction() == 0) + continue; + + Function *F = CGN->getFunction(); + + // If the only remaining users of the function are dead constants, remove + // them. + F->removeDeadConstantUsers(); + + if (DNR && DNR->count(F)) + continue; + if (!F->hasLinkOnceLinkage() && !F->hasLocalLinkage() && + !F->hasAvailableExternallyLinkage()) + continue; + if (!F->use_empty()) + continue; + + // Remove any call graph edges from the function to its callees. + CGN->removeAllCalledFunctions(); + + // Remove any edges from the external node to the function's call graph + // node. These edges might have been made irrelegant due to + // optimization of the program. + CG.getExternalCallingNode()->removeAnyCallEdgeTo(CGN); + + // Removing the node for callee from the call graph and delete it. + FunctionsToRemove.insert(CGN); + } + + // Now that we know which functions to delete, do so. We didn't want to do + // this inline, because that would invalidate our CallGraph::iterator + // objects. :( + // + // Note that it doesn't matter that we are iterating over a non-stable set + // here to do this, it doesn't matter which order the functions are deleted + // in. + bool Changed = false; + for (SmallPtrSet::iterator I = FunctionsToRemove.begin(), + E = FunctionsToRemove.end(); I != E; ++I) { + resetCachedCostInfo((*I)->getFunction()); + delete CG.removeFunctionFromModule(*I); + ++NumDeleted; + Changed = true; + } + + return Changed; +} diff --git a/libclamav/c++/llvm/lib/Transforms/IPO/Internalize.cpp b/libclamav/c++/llvm/lib/Transforms/IPO/Internalize.cpp new file mode 100644 index 000000000..20ae0d585 --- /dev/null +++ b/libclamav/c++/llvm/lib/Transforms/IPO/Internalize.cpp @@ -0,0 +1,186 @@ +//===-- Internalize.cpp - Mark functions internal -------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This pass loops over all of the functions in the input module, looking for a +// main function. If a main function is found, all other functions and all +// global variables with initializers are marked as internal. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "internalize" +#include "llvm/Analysis/CallGraph.h" +#include "llvm/Transforms/IPO.h" +#include "llvm/Pass.h" +#include "llvm/Module.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/ADT/Statistic.h" +#include +#include +using namespace llvm; + +STATISTIC(NumAliases , "Number of aliases internalized"); +STATISTIC(NumFunctions, "Number of functions internalized"); +STATISTIC(NumGlobals , "Number of global vars internalized"); + +// APIFile - A file which contains a list of symbols that should not be marked +// external. +static cl::opt +APIFile("internalize-public-api-file", cl::value_desc("filename"), + cl::desc("A file containing list of symbol names to preserve")); + +// APIList - A list of symbols that should not be marked internal. +static cl::list +APIList("internalize-public-api-list", cl::value_desc("list"), + cl::desc("A list of symbol names to preserve"), + cl::CommaSeparated); + +namespace { + class InternalizePass : public ModulePass { + std::set ExternalNames; + /// If no api symbols were specified and a main function is defined, + /// assume the main function is the only API + bool AllButMain; + public: + static char ID; // Pass identification, replacement for typeid + explicit InternalizePass(bool AllButMain = true); + explicit InternalizePass(const std::vector & exportList); + void LoadFile(const char *Filename); + virtual bool runOnModule(Module &M); + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesCFG(); + AU.addPreserved(); + } + }; +} // end anonymous namespace + +char InternalizePass::ID = 0; +static RegisterPass +X("internalize", "Internalize Global Symbols"); + +InternalizePass::InternalizePass(bool AllButMain) + : ModulePass(&ID), AllButMain(AllButMain){ + if (!APIFile.empty()) // If a filename is specified, use it. + LoadFile(APIFile.c_str()); + if (!APIList.empty()) // If a list is specified, use it as well. + ExternalNames.insert(APIList.begin(), APIList.end()); +} + +InternalizePass::InternalizePass(const std::vector&exportList) + : ModulePass(&ID), AllButMain(false){ + for(std::vector::const_iterator itr = exportList.begin(); + itr != exportList.end(); itr++) { + ExternalNames.insert(*itr); + } +} + +void InternalizePass::LoadFile(const char *Filename) { + // Load the APIFile... + std::ifstream In(Filename); + if (!In.good()) { + errs() << "WARNING: Internalize couldn't load file '" << Filename + << "'! Continuing as if it's empty.\n"; + return; // Just continue as if the file were empty + } + while (In) { + std::string Symbol; + In >> Symbol; + if (!Symbol.empty()) + ExternalNames.insert(Symbol); + } +} + +bool InternalizePass::runOnModule(Module &M) { + CallGraph *CG = getAnalysisIfAvailable(); + CallGraphNode *ExternalNode = CG ? CG->getExternalCallingNode() : 0; + + if (ExternalNames.empty()) { + // Return if we're not in 'all but main' mode and have no external api + if (!AllButMain) + return false; + // If no list or file of symbols was specified, check to see if there is a + // "main" symbol defined in the module. If so, use it, otherwise do not + // internalize the module, it must be a library or something. + // + Function *MainFunc = M.getFunction("main"); + if (MainFunc == 0 || MainFunc->isDeclaration()) + return false; // No main found, must be a library... + + // Preserve main, internalize all else. + ExternalNames.insert(MainFunc->getName()); + } + + bool Changed = false; + + // Mark all functions not in the api as internal. + // FIXME: maybe use private linkage? + for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) + if (!I->isDeclaration() && // Function must be defined here + !I->hasLocalLinkage() && // Can't already have internal linkage + !ExternalNames.count(I->getName())) {// Not marked to keep external? + I->setLinkage(GlobalValue::InternalLinkage); + // Remove a callgraph edge from the external node to this function. + if (ExternalNode) ExternalNode->removeOneAbstractEdgeTo((*CG)[I]); + Changed = true; + ++NumFunctions; + DEBUG(errs() << "Internalizing func " << I->getName() << "\n"); + } + + // Never internalize the llvm.used symbol. It is used to implement + // attribute((used)). + // FIXME: Shouldn't this just filter on llvm.metadata section?? + ExternalNames.insert("llvm.used"); + ExternalNames.insert("llvm.compiler.used"); + + // Never internalize anchors used by the machine module info, else the info + // won't find them. (see MachineModuleInfo.) + ExternalNames.insert("llvm.dbg.compile_units"); + ExternalNames.insert("llvm.dbg.global_variables"); + ExternalNames.insert("llvm.dbg.subprograms"); + ExternalNames.insert("llvm.global_ctors"); + ExternalNames.insert("llvm.global_dtors"); + ExternalNames.insert("llvm.noinline"); + ExternalNames.insert("llvm.global.annotations"); + + // Mark all global variables with initializers that are not in the api as + // internal as well. + // FIXME: maybe use private linkage? + for (Module::global_iterator I = M.global_begin(), E = M.global_end(); + I != E; ++I) + if (!I->isDeclaration() && !I->hasLocalLinkage() && + !ExternalNames.count(I->getName())) { + I->setLinkage(GlobalValue::InternalLinkage); + Changed = true; + ++NumGlobals; + DEBUG(errs() << "Internalized gvar " << I->getName() << "\n"); + } + + // Mark all aliases that are not in the api as internal as well. + for (Module::alias_iterator I = M.alias_begin(), E = M.alias_end(); + I != E; ++I) + if (!I->isDeclaration() && !I->hasInternalLinkage() && + !ExternalNames.count(I->getName())) { + I->setLinkage(GlobalValue::InternalLinkage); + Changed = true; + ++NumAliases; + DEBUG(errs() << "Internalized alias " << I->getName() << "\n"); + } + + return Changed; +} + +ModulePass *llvm::createInternalizePass(bool AllButMain) { + return new InternalizePass(AllButMain); +} + +ModulePass *llvm::createInternalizePass(const std::vector &el) { + return new InternalizePass(el); +} diff --git a/libclamav/c++/llvm/lib/Transforms/IPO/LoopExtractor.cpp b/libclamav/c++/llvm/lib/Transforms/IPO/LoopExtractor.cpp new file mode 100644 index 000000000..cb813303f --- /dev/null +++ b/libclamav/c++/llvm/lib/Transforms/IPO/LoopExtractor.cpp @@ -0,0 +1,242 @@ +//===- LoopExtractor.cpp - Extract each loop into a new function ----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// A pass wrapper around the ExtractLoop() scalar transformation to extract each +// top-level loop into its own new function. If the loop is the ONLY loop in a +// given function, it is not touched. This is a pass most useful for debugging +// via bugpoint. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "loop-extract" +#include "llvm/Transforms/IPO.h" +#include "llvm/Instructions.h" +#include "llvm/Module.h" +#include "llvm/Pass.h" +#include "llvm/Analysis/Dominators.h" +#include "llvm/Analysis/LoopPass.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Transforms/Scalar.h" +#include "llvm/Transforms/Utils/FunctionUtils.h" +#include "llvm/ADT/Statistic.h" +#include +#include +using namespace llvm; + +STATISTIC(NumExtracted, "Number of loops extracted"); + +namespace { + struct LoopExtractor : public LoopPass { + static char ID; // Pass identification, replacement for typeid + unsigned NumLoops; + + explicit LoopExtractor(unsigned numLoops = ~0) + : LoopPass(&ID), NumLoops(numLoops) {} + + virtual bool runOnLoop(Loop *L, LPPassManager &LPM); + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.addRequiredID(BreakCriticalEdgesID); + AU.addRequiredID(LoopSimplifyID); + AU.addRequired(); + } + }; +} + +char LoopExtractor::ID = 0; +static RegisterPass +X("loop-extract", "Extract loops into new functions"); + +namespace { + /// SingleLoopExtractor - For bugpoint. + struct SingleLoopExtractor : public LoopExtractor { + static char ID; // Pass identification, replacement for typeid + SingleLoopExtractor() : LoopExtractor(1) {} + }; +} // End anonymous namespace + +char SingleLoopExtractor::ID = 0; +static RegisterPass +Y("loop-extract-single", "Extract at most one loop into a new function"); + +// createLoopExtractorPass - This pass extracts all natural loops from the +// program into a function if it can. +// +Pass *llvm::createLoopExtractorPass() { return new LoopExtractor(); } + +bool LoopExtractor::runOnLoop(Loop *L, LPPassManager &LPM) { + // Only visit top-level loops. + if (L->getParentLoop()) + return false; + + // If LoopSimplify form is not available, stay out of trouble. + if (!L->isLoopSimplifyForm()) + return false; + + DominatorTree &DT = getAnalysis(); + bool Changed = false; + + // If there is more than one top-level loop in this function, extract all of + // the loops. Otherwise there is exactly one top-level loop; in this case if + // this function is more than a minimal wrapper around the loop, extract + // the loop. + bool ShouldExtractLoop = false; + + // Extract the loop if the entry block doesn't branch to the loop header. + TerminatorInst *EntryTI = + L->getHeader()->getParent()->getEntryBlock().getTerminator(); + if (!isa(EntryTI) || + !cast(EntryTI)->isUnconditional() || + EntryTI->getSuccessor(0) != L->getHeader()) + ShouldExtractLoop = true; + else { + // Check to see if any exits from the loop are more than just return + // blocks. + SmallVector ExitBlocks; + L->getExitBlocks(ExitBlocks); + for (unsigned i = 0, e = ExitBlocks.size(); i != e; ++i) + if (!isa(ExitBlocks[i]->getTerminator())) { + ShouldExtractLoop = true; + break; + } + } + if (ShouldExtractLoop) { + if (NumLoops == 0) return Changed; + --NumLoops; + if (ExtractLoop(DT, L) != 0) { + Changed = true; + // After extraction, the loop is replaced by a function call, so + // we shouldn't try to run any more loop passes on it. + LPM.deleteLoopFromQueue(L); + } + ++NumExtracted; + } + + return Changed; +} + +// createSingleLoopExtractorPass - This pass extracts one natural loop from the +// program into a function if it can. This is used by bugpoint. +// +Pass *llvm::createSingleLoopExtractorPass() { + return new SingleLoopExtractor(); +} + + +// BlockFile - A file which contains a list of blocks that should not be +// extracted. +static cl::opt +BlockFile("extract-blocks-file", cl::value_desc("filename"), + cl::desc("A file containing list of basic blocks to not extract"), + cl::Hidden); + +namespace { + /// BlockExtractorPass - This pass is used by bugpoint to extract all blocks + /// from the module into their own functions except for those specified by the + /// BlocksToNotExtract list. + class BlockExtractorPass : public ModulePass { + void LoadFile(const char *Filename); + + std::vector BlocksToNotExtract; + std::vector > BlocksToNotExtractByName; + public: + static char ID; // Pass identification, replacement for typeid + explicit BlockExtractorPass(const std::vector &B) + : ModulePass(&ID), BlocksToNotExtract(B) { + if (!BlockFile.empty()) + LoadFile(BlockFile.c_str()); + } + BlockExtractorPass() : ModulePass(&ID) {} + + bool runOnModule(Module &M); + }; +} + +char BlockExtractorPass::ID = 0; +static RegisterPass +XX("extract-blocks", "Extract Basic Blocks From Module (for bugpoint use)"); + +// createBlockExtractorPass - This pass extracts all blocks (except those +// specified in the argument list) from the functions in the module. +// +ModulePass *llvm::createBlockExtractorPass(const std::vector &BTNE) +{ + return new BlockExtractorPass(BTNE); +} + +void BlockExtractorPass::LoadFile(const char *Filename) { + // Load the BlockFile... + std::ifstream In(Filename); + if (!In.good()) { + errs() << "WARNING: BlockExtractor couldn't load file '" << Filename + << "'!\n"; + return; + } + while (In) { + std::string FunctionName, BlockName; + In >> FunctionName; + In >> BlockName; + if (!BlockName.empty()) + BlocksToNotExtractByName.push_back( + std::make_pair(FunctionName, BlockName)); + } +} + +bool BlockExtractorPass::runOnModule(Module &M) { + std::set TranslatedBlocksToNotExtract; + for (unsigned i = 0, e = BlocksToNotExtract.size(); i != e; ++i) { + BasicBlock *BB = BlocksToNotExtract[i]; + Function *F = BB->getParent(); + + // Map the corresponding function in this module. + Function *MF = M.getFunction(F->getName()); + assert(MF->getFunctionType() == F->getFunctionType() && "Wrong function?"); + + // Figure out which index the basic block is in its function. + Function::iterator BBI = MF->begin(); + std::advance(BBI, std::distance(F->begin(), Function::iterator(BB))); + TranslatedBlocksToNotExtract.insert(BBI); + } + + while (!BlocksToNotExtractByName.empty()) { + // There's no way to find BBs by name without looking at every BB inside + // every Function. Fortunately, this is always empty except when used by + // bugpoint in which case correctness is more important than performance. + + std::string &FuncName = BlocksToNotExtractByName.back().first; + std::string &BlockName = BlocksToNotExtractByName.back().second; + + for (Module::iterator FI = M.begin(), FE = M.end(); FI != FE; ++FI) { + Function &F = *FI; + if (F.getName() != FuncName) continue; + + for (Function::iterator BI = F.begin(), BE = F.end(); BI != BE; ++BI) { + BasicBlock &BB = *BI; + if (BB.getName() != BlockName) continue; + + TranslatedBlocksToNotExtract.insert(BI); + } + } + + BlocksToNotExtractByName.pop_back(); + } + + // Now that we know which blocks to not extract, figure out which ones we WANT + // to extract. + std::vector BlocksToExtract; + for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F) + for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) + if (!TranslatedBlocksToNotExtract.count(BB)) + BlocksToExtract.push_back(BB); + + for (unsigned i = 0, e = BlocksToExtract.size(); i != e; ++i) + ExtractBasicBlock(BlocksToExtract[i]); + + return !BlocksToExtract.empty(); +} diff --git a/libclamav/c++/llvm/lib/Transforms/IPO/LowerSetJmp.cpp b/libclamav/c++/llvm/lib/Transforms/IPO/LowerSetJmp.cpp new file mode 100644 index 000000000..4d61e8345 --- /dev/null +++ b/libclamav/c++/llvm/lib/Transforms/IPO/LowerSetJmp.cpp @@ -0,0 +1,541 @@ +//===- LowerSetJmp.cpp - Code pertaining to lowering set/long jumps -------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the lowering of setjmp and longjmp to use the +// LLVM invoke and unwind instructions as necessary. +// +// Lowering of longjmp is fairly trivial. We replace the call with a +// call to the LLVM library function "__llvm_sjljeh_throw_longjmp()". +// This unwinds the stack for us calling all of the destructors for +// objects allocated on the stack. +// +// At a setjmp call, the basic block is split and the setjmp removed. +// The calls in a function that have a setjmp are converted to invoke +// where the except part checks to see if it's a longjmp exception and, +// if so, if it's handled in the function. If it is, then it gets the +// value returned by the longjmp and goes to where the basic block was +// split. Invoke instructions are handled in a similar fashion with the +// original except block being executed if it isn't a longjmp except +// that is handled by that function. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// FIXME: This pass doesn't deal with PHI statements just yet. That is, +// we expect this to occur before SSAification is done. This would seem +// to make sense, but in general, it might be a good idea to make this +// pass invokable via the "opt" command at will. +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "lowersetjmp" +#include "llvm/Transforms/IPO.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Instructions.h" +#include "llvm/Intrinsics.h" +#include "llvm/LLVMContext.h" +#include "llvm/Module.h" +#include "llvm/Pass.h" +#include "llvm/Support/CFG.h" +#include "llvm/Support/InstVisitor.h" +#include "llvm/Transforms/Utils/Local.h" +#include "llvm/ADT/DepthFirstIterator.h" +#include "llvm/ADT/Statistic.h" +#include +using namespace llvm; + +STATISTIC(LongJmpsTransformed, "Number of longjmps transformed"); +STATISTIC(SetJmpsTransformed , "Number of setjmps transformed"); +STATISTIC(CallsTransformed , "Number of calls invokified"); +STATISTIC(InvokesTransformed , "Number of invokes modified"); + +namespace { + //===--------------------------------------------------------------------===// + // LowerSetJmp pass implementation. + class LowerSetJmp : public ModulePass, public InstVisitor { + // LLVM library functions... + Constant *InitSJMap; // __llvm_sjljeh_init_setjmpmap + Constant *DestroySJMap; // __llvm_sjljeh_destroy_setjmpmap + Constant *AddSJToMap; // __llvm_sjljeh_add_setjmp_to_map + Constant *ThrowLongJmp; // __llvm_sjljeh_throw_longjmp + Constant *TryCatchLJ; // __llvm_sjljeh_try_catching_longjmp_exception + Constant *IsLJException; // __llvm_sjljeh_is_longjmp_exception + Constant *GetLJValue; // __llvm_sjljeh_get_longjmp_value + + typedef std::pair SwitchValuePair; + + // Keep track of those basic blocks reachable via a depth-first search of + // the CFG from a setjmp call. We only need to transform those "call" and + // "invoke" instructions that are reachable from the setjmp call site. + std::set DFSBlocks; + + // The setjmp map is going to hold information about which setjmps + // were called (each setjmp gets its own number) and with which + // buffer it was called. + std::map SJMap; + + // The rethrow basic block map holds the basic block to branch to if + // the exception isn't handled in the current function and needs to + // be rethrown. + std::map RethrowBBMap; + + // The preliminary basic block map holds a basic block that grabs the + // exception and determines if it's handled by the current function. + std::map PrelimBBMap; + + // The switch/value map holds a switch inst/call inst pair. The + // switch inst controls which handler (if any) gets called and the + // value is the value returned to that handler by the call to + // __llvm_sjljeh_get_longjmp_value. + std::map SwitchValMap; + + // A map of which setjmps we've seen so far in a function. + std::map SetJmpIDMap; + + AllocaInst* GetSetJmpMap(Function* Func); + BasicBlock* GetRethrowBB(Function* Func); + SwitchValuePair GetSJSwitch(Function* Func, BasicBlock* Rethrow); + + void TransformLongJmpCall(CallInst* Inst); + void TransformSetJmpCall(CallInst* Inst); + + bool IsTransformableFunction(StringRef Name); + public: + static char ID; // Pass identification, replacement for typeid + LowerSetJmp() : ModulePass(&ID) {} + + void visitCallInst(CallInst& CI); + void visitInvokeInst(InvokeInst& II); + void visitReturnInst(ReturnInst& RI); + void visitUnwindInst(UnwindInst& UI); + + bool runOnModule(Module& M); + bool doInitialization(Module& M); + }; +} // end anonymous namespace + +char LowerSetJmp::ID = 0; +static RegisterPass X("lowersetjmp", "Lower Set Jump"); + +// run - Run the transformation on the program. We grab the function +// prototypes for longjmp and setjmp. If they are used in the program, +// then we can go directly to the places they're at and transform them. +bool LowerSetJmp::runOnModule(Module& M) { + bool Changed = false; + + // These are what the functions are called. + Function* SetJmp = M.getFunction("llvm.setjmp"); + Function* LongJmp = M.getFunction("llvm.longjmp"); + + // This program doesn't have longjmp and setjmp calls. + if ((!LongJmp || LongJmp->use_empty()) && + (!SetJmp || SetJmp->use_empty())) return false; + + // Initialize some values and functions we'll need to transform the + // setjmp/longjmp functions. + doInitialization(M); + + if (SetJmp) { + for (Value::use_iterator B = SetJmp->use_begin(), E = SetJmp->use_end(); + B != E; ++B) { + BasicBlock* BB = cast(*B)->getParent(); + for (df_ext_iterator I = df_ext_begin(BB, DFSBlocks), + E = df_ext_end(BB, DFSBlocks); I != E; ++I) + /* empty */; + } + + while (!SetJmp->use_empty()) { + assert(isa(SetJmp->use_back()) && + "User of setjmp intrinsic not a call?"); + TransformSetJmpCall(cast(SetJmp->use_back())); + Changed = true; + } + } + + if (LongJmp) + while (!LongJmp->use_empty()) { + assert(isa(LongJmp->use_back()) && + "User of longjmp intrinsic not a call?"); + TransformLongJmpCall(cast(LongJmp->use_back())); + Changed = true; + } + + // Now go through the affected functions and convert calls and invokes + // to new invokes... + for (std::map::iterator + B = SJMap.begin(), E = SJMap.end(); B != E; ++B) { + Function* F = B->first; + for (Function::iterator BB = F->begin(), BE = F->end(); BB != BE; ++BB) + for (BasicBlock::iterator IB = BB->begin(), IE = BB->end(); IB != IE; ) { + visit(*IB++); + if (IB != BB->end() && IB->getParent() != BB) + break; // The next instruction got moved to a different block! + } + } + + DFSBlocks.clear(); + SJMap.clear(); + RethrowBBMap.clear(); + PrelimBBMap.clear(); + SwitchValMap.clear(); + SetJmpIDMap.clear(); + + return Changed; +} + +// doInitialization - For the lower long/setjmp pass, this ensures that a +// module contains a declaration for the intrisic functions we are going +// to call to convert longjmp and setjmp calls. +// +// This function is always successful, unless it isn't. +bool LowerSetJmp::doInitialization(Module& M) +{ + const Type *SBPTy = Type::getInt8PtrTy(M.getContext()); + const Type *SBPPTy = PointerType::getUnqual(SBPTy); + + // N.B. See llvm/runtime/GCCLibraries/libexception/SJLJ-Exception.h for + // a description of the following library functions. + + // void __llvm_sjljeh_init_setjmpmap(void**) + InitSJMap = M.getOrInsertFunction("__llvm_sjljeh_init_setjmpmap", + Type::getVoidTy(M.getContext()), + SBPPTy, (Type *)0); + // void __llvm_sjljeh_destroy_setjmpmap(void**) + DestroySJMap = M.getOrInsertFunction("__llvm_sjljeh_destroy_setjmpmap", + Type::getVoidTy(M.getContext()), + SBPPTy, (Type *)0); + + // void __llvm_sjljeh_add_setjmp_to_map(void**, void*, unsigned) + AddSJToMap = M.getOrInsertFunction("__llvm_sjljeh_add_setjmp_to_map", + Type::getVoidTy(M.getContext()), + SBPPTy, SBPTy, + Type::getInt32Ty(M.getContext()), + (Type *)0); + + // void __llvm_sjljeh_throw_longjmp(int*, int) + ThrowLongJmp = M.getOrInsertFunction("__llvm_sjljeh_throw_longjmp", + Type::getVoidTy(M.getContext()), SBPTy, + Type::getInt32Ty(M.getContext()), + (Type *)0); + + // unsigned __llvm_sjljeh_try_catching_longjmp_exception(void **) + TryCatchLJ = + M.getOrInsertFunction("__llvm_sjljeh_try_catching_longjmp_exception", + Type::getInt32Ty(M.getContext()), SBPPTy, (Type *)0); + + // bool __llvm_sjljeh_is_longjmp_exception() + IsLJException = M.getOrInsertFunction("__llvm_sjljeh_is_longjmp_exception", + Type::getInt1Ty(M.getContext()), + (Type *)0); + + // int __llvm_sjljeh_get_longjmp_value() + GetLJValue = M.getOrInsertFunction("__llvm_sjljeh_get_longjmp_value", + Type::getInt32Ty(M.getContext()), + (Type *)0); + return true; +} + +// IsTransformableFunction - Return true if the function name isn't one +// of the ones we don't want transformed. Currently, don't transform any +// "llvm.{setjmp,longjmp}" functions and none of the setjmp/longjmp error +// handling functions (beginning with __llvm_sjljeh_...they don't throw +// exceptions). +bool LowerSetJmp::IsTransformableFunction(StringRef Name) { + return !Name.startswith("__llvm_sjljeh_"); +} + +// TransformLongJmpCall - Transform a longjmp call into a call to the +// internal __llvm_sjljeh_throw_longjmp function. It then takes care of +// throwing the exception for us. +void LowerSetJmp::TransformLongJmpCall(CallInst* Inst) +{ + const Type* SBPTy = Type::getInt8PtrTy(Inst->getContext()); + + // Create the call to "__llvm_sjljeh_throw_longjmp". This takes the + // same parameters as "longjmp", except that the buffer is cast to a + // char*. It returns "void", so it doesn't need to replace any of + // Inst's uses and doesn't get a name. + CastInst* CI = + new BitCastInst(Inst->getOperand(1), SBPTy, "LJBuf", Inst); + Value *Args[] = { CI, Inst->getOperand(2) }; + CallInst::Create(ThrowLongJmp, Args, Args + 2, "", Inst); + + SwitchValuePair& SVP = SwitchValMap[Inst->getParent()->getParent()]; + + // If the function has a setjmp call in it (they are transformed first) + // we should branch to the basic block that determines if this longjmp + // is applicable here. Otherwise, issue an unwind. + if (SVP.first) + BranchInst::Create(SVP.first->getParent(), Inst); + else + new UnwindInst(Inst->getContext(), Inst); + + // Remove all insts after the branch/unwind inst. Go from back to front to + // avoid replaceAllUsesWith if possible. + BasicBlock *BB = Inst->getParent(); + Instruction *Removed; + do { + Removed = &BB->back(); + // If the removed instructions have any users, replace them now. + if (!Removed->use_empty()) + Removed->replaceAllUsesWith(UndefValue::get(Removed->getType())); + Removed->eraseFromParent(); + } while (Removed != Inst); + + ++LongJmpsTransformed; +} + +// GetSetJmpMap - Retrieve (create and initialize, if necessary) the +// setjmp map. This map is going to hold information about which setjmps +// were called (each setjmp gets its own number) and with which buffer it +// was called. There can be only one! +AllocaInst* LowerSetJmp::GetSetJmpMap(Function* Func) +{ + if (SJMap[Func]) return SJMap[Func]; + + // Insert the setjmp map initialization before the first instruction in + // the function. + Instruction* Inst = Func->getEntryBlock().begin(); + assert(Inst && "Couldn't find even ONE instruction in entry block!"); + + // Fill in the alloca and call to initialize the SJ map. + const Type *SBPTy = + Type::getInt8PtrTy(Func->getContext()); + AllocaInst* Map = new AllocaInst(SBPTy, 0, "SJMap", Inst); + CallInst::Create(InitSJMap, Map, "", Inst); + return SJMap[Func] = Map; +} + +// GetRethrowBB - Only one rethrow basic block is needed per function. +// If this is a longjmp exception but not handled in this block, this BB +// performs the rethrow. +BasicBlock* LowerSetJmp::GetRethrowBB(Function* Func) +{ + if (RethrowBBMap[Func]) return RethrowBBMap[Func]; + + // The basic block we're going to jump to if we need to rethrow the + // exception. + BasicBlock* Rethrow = + BasicBlock::Create(Func->getContext(), "RethrowExcept", Func); + + // Fill in the "Rethrow" BB with a call to rethrow the exception. This + // is the last instruction in the BB since at this point the runtime + // should exit this function and go to the next function. + new UnwindInst(Func->getContext(), Rethrow); + return RethrowBBMap[Func] = Rethrow; +} + +// GetSJSwitch - Return the switch statement that controls which handler +// (if any) gets called and the value returned to that handler. +LowerSetJmp::SwitchValuePair LowerSetJmp::GetSJSwitch(Function* Func, + BasicBlock* Rethrow) +{ + if (SwitchValMap[Func].first) return SwitchValMap[Func]; + + BasicBlock* LongJmpPre = + BasicBlock::Create(Func->getContext(), "LongJmpBlkPre", Func); + + // Keep track of the preliminary basic block for some of the other + // transformations. + PrelimBBMap[Func] = LongJmpPre; + + // Grab the exception. + CallInst* Cond = CallInst::Create(IsLJException, "IsLJExcept", LongJmpPre); + + // The "decision basic block" gets the number associated with the + // setjmp call returning to switch on and the value returned by + // longjmp. + BasicBlock* DecisionBB = + BasicBlock::Create(Func->getContext(), "LJDecisionBB", Func); + + BranchInst::Create(DecisionBB, Rethrow, Cond, LongJmpPre); + + // Fill in the "decision" basic block. + CallInst* LJVal = CallInst::Create(GetLJValue, "LJVal", DecisionBB); + CallInst* SJNum = CallInst::Create(TryCatchLJ, GetSetJmpMap(Func), "SJNum", + DecisionBB); + + SwitchInst* SI = SwitchInst::Create(SJNum, Rethrow, 0, DecisionBB); + return SwitchValMap[Func] = SwitchValuePair(SI, LJVal); +} + +// TransformSetJmpCall - The setjmp call is a bit trickier to transform. +// We're going to convert all setjmp calls to nops. Then all "call" and +// "invoke" instructions in the function are converted to "invoke" where +// the "except" branch is used when returning from a longjmp call. +void LowerSetJmp::TransformSetJmpCall(CallInst* Inst) +{ + BasicBlock* ABlock = Inst->getParent(); + Function* Func = ABlock->getParent(); + + // Add this setjmp to the setjmp map. + const Type* SBPTy = + Type::getInt8PtrTy(Inst->getContext()); + CastInst* BufPtr = + new BitCastInst(Inst->getOperand(1), SBPTy, "SBJmpBuf", Inst); + Value *Args[] = { + GetSetJmpMap(Func), BufPtr, + ConstantInt::get(Type::getInt32Ty(Inst->getContext()), SetJmpIDMap[Func]++) + }; + CallInst::Create(AddSJToMap, Args, Args + 3, "", Inst); + + // We are guaranteed that there are no values live across basic blocks + // (because we are "not in SSA form" yet), but there can still be values live + // in basic blocks. Because of this, splitting the setjmp block can cause + // values above the setjmp to not dominate uses which are after the setjmp + // call. For all of these occasions, we must spill the value to the stack. + // + std::set InstrsAfterCall; + + // The call is probably very close to the end of the basic block, for the + // common usage pattern of: 'if (setjmp(...))', so keep track of the + // instructions after the call. + for (BasicBlock::iterator I = ++BasicBlock::iterator(Inst), E = ABlock->end(); + I != E; ++I) + InstrsAfterCall.insert(I); + + for (BasicBlock::iterator II = ABlock->begin(); + II != BasicBlock::iterator(Inst); ++II) + // Loop over all of the uses of instruction. If any of them are after the + // call, "spill" the value to the stack. + for (Value::use_iterator UI = II->use_begin(), E = II->use_end(); + UI != E; ++UI) + if (cast(*UI)->getParent() != ABlock || + InstrsAfterCall.count(cast(*UI))) { + DemoteRegToStack(*II); + break; + } + InstrsAfterCall.clear(); + + // Change the setjmp call into a branch statement. We'll remove the + // setjmp call in a little bit. No worries. + BasicBlock* SetJmpContBlock = ABlock->splitBasicBlock(Inst); + assert(SetJmpContBlock && "Couldn't split setjmp BB!!"); + + SetJmpContBlock->setName(ABlock->getName()+"SetJmpCont"); + + // Add the SetJmpContBlock to the set of blocks reachable from a setjmp. + DFSBlocks.insert(SetJmpContBlock); + + // This PHI node will be in the new block created from the + // splitBasicBlock call. + PHINode* PHI = PHINode::Create(Type::getInt32Ty(Inst->getContext()), + "SetJmpReturn", Inst); + + // Coming from a call to setjmp, the return is 0. + PHI->addIncoming(Constant::getNullValue(Type::getInt32Ty(Inst->getContext())), + ABlock); + + // Add the case for this setjmp's number... + SwitchValuePair SVP = GetSJSwitch(Func, GetRethrowBB(Func)); + SVP.first->addCase(ConstantInt::get(Type::getInt32Ty(Inst->getContext()), + SetJmpIDMap[Func] - 1), + SetJmpContBlock); + + // Value coming from the handling of the exception. + PHI->addIncoming(SVP.second, SVP.second->getParent()); + + // Replace all uses of this instruction with the PHI node created by + // the eradication of setjmp. + Inst->replaceAllUsesWith(PHI); + Inst->eraseFromParent(); + + ++SetJmpsTransformed; +} + +// visitCallInst - This converts all LLVM call instructions into invoke +// instructions. The except part of the invoke goes to the "LongJmpBlkPre" +// that grabs the exception and proceeds to determine if it's a longjmp +// exception or not. +void LowerSetJmp::visitCallInst(CallInst& CI) +{ + if (CI.getCalledFunction()) + if (!IsTransformableFunction(CI.getCalledFunction()->getName()) || + CI.getCalledFunction()->isIntrinsic()) return; + + BasicBlock* OldBB = CI.getParent(); + + // If not reachable from a setjmp call, don't transform. + if (!DFSBlocks.count(OldBB)) return; + + BasicBlock* NewBB = OldBB->splitBasicBlock(CI); + assert(NewBB && "Couldn't split BB of \"call\" instruction!!"); + DFSBlocks.insert(NewBB); + NewBB->setName("Call2Invoke"); + + Function* Func = OldBB->getParent(); + + // Construct the new "invoke" instruction. + TerminatorInst* Term = OldBB->getTerminator(); + std::vector Params(CI.op_begin() + 1, CI.op_end()); + InvokeInst* II = + InvokeInst::Create(CI.getCalledValue(), NewBB, PrelimBBMap[Func], + Params.begin(), Params.end(), CI.getName(), Term); + II->setCallingConv(CI.getCallingConv()); + II->setAttributes(CI.getAttributes()); + + // Replace the old call inst with the invoke inst and remove the call. + CI.replaceAllUsesWith(II); + CI.eraseFromParent(); + + // The old terminator is useless now that we have the invoke inst. + Term->eraseFromParent(); + ++CallsTransformed; +} + +// visitInvokeInst - Converting the "invoke" instruction is fairly +// straight-forward. The old exception part is replaced by a query asking +// if this is a longjmp exception. If it is, then it goes to the longjmp +// exception blocks. Otherwise, control is passed the old exception. +void LowerSetJmp::visitInvokeInst(InvokeInst& II) +{ + if (II.getCalledFunction()) + if (!IsTransformableFunction(II.getCalledFunction()->getName()) || + II.getCalledFunction()->isIntrinsic()) return; + + BasicBlock* BB = II.getParent(); + + // If not reachable from a setjmp call, don't transform. + if (!DFSBlocks.count(BB)) return; + + BasicBlock* ExceptBB = II.getUnwindDest(); + + Function* Func = BB->getParent(); + BasicBlock* NewExceptBB = BasicBlock::Create(II.getContext(), + "InvokeExcept", Func); + + // If this is a longjmp exception, then branch to the preliminary BB of + // the longjmp exception handling. Otherwise, go to the old exception. + CallInst* IsLJExcept = CallInst::Create(IsLJException, "IsLJExcept", + NewExceptBB); + + BranchInst::Create(PrelimBBMap[Func], ExceptBB, IsLJExcept, NewExceptBB); + + II.setUnwindDest(NewExceptBB); + ++InvokesTransformed; +} + +// visitReturnInst - We want to destroy the setjmp map upon exit from the +// function. +void LowerSetJmp::visitReturnInst(ReturnInst &RI) { + Function* Func = RI.getParent()->getParent(); + CallInst::Create(DestroySJMap, GetSetJmpMap(Func), "", &RI); +} + +// visitUnwindInst - We want to destroy the setjmp map upon exit from the +// function. +void LowerSetJmp::visitUnwindInst(UnwindInst &UI) { + Function* Func = UI.getParent()->getParent(); + CallInst::Create(DestroySJMap, GetSetJmpMap(Func), "", &UI); +} + +ModulePass *llvm::createLowerSetJmpPass() { + return new LowerSetJmp(); +} + diff --git a/libclamav/c++/llvm/lib/Transforms/IPO/Makefile b/libclamav/c++/llvm/lib/Transforms/IPO/Makefile new file mode 100644 index 000000000..5c4237413 --- /dev/null +++ b/libclamav/c++/llvm/lib/Transforms/IPO/Makefile @@ -0,0 +1,15 @@ +##===- lib/Transforms/IPO/Makefile -------------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LEVEL = ../../.. +LIBRARYNAME = LLVMipo +BUILD_ARCHIVE = 1 + +include $(LEVEL)/Makefile.common + diff --git a/libclamav/c++/llvm/lib/Transforms/IPO/MergeFunctions.cpp b/libclamav/c++/llvm/lib/Transforms/IPO/MergeFunctions.cpp new file mode 100644 index 000000000..b2bdabc0d --- /dev/null +++ b/libclamav/c++/llvm/lib/Transforms/IPO/MergeFunctions.cpp @@ -0,0 +1,665 @@ +//===- MergeFunctions.cpp - Merge identical functions ---------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This pass looks for equivalent functions that are mergable and folds them. +// +// A hash is computed from the function, based on its type and number of +// basic blocks. +// +// Once all hashes are computed, we perform an expensive equality comparison +// on each function pair. This takes n^2/2 comparisons per bucket, so it's +// important that the hash function be high quality. The equality comparison +// iterates through each instruction in each basic block. +// +// When a match is found, the functions are folded. We can only fold two +// functions when we know that the definition of one of them is not +// overridable. +// +//===----------------------------------------------------------------------===// +// +// Future work: +// +// * fold vector::push_back and vector::push_back. +// +// These two functions have different types, but in a way that doesn't matter +// to us. As long as we never see an S or T itself, using S* and S** is the +// same as using a T* and T**. +// +// * virtual functions. +// +// Many functions have their address taken by the virtual function table for +// the object they belong to. However, as long as it's only used for a lookup +// and call, this is irrelevant, and we'd like to fold such implementations. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "mergefunc" +#include "llvm/Transforms/IPO.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/FoldingSet.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/Constants.h" +#include "llvm/InlineAsm.h" +#include "llvm/Instructions.h" +#include "llvm/LLVMContext.h" +#include "llvm/Module.h" +#include "llvm/Pass.h" +#include "llvm/Support/CallSite.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +#include +#include +using namespace llvm; + +STATISTIC(NumFunctionsMerged, "Number of functions merged"); + +namespace { + struct MergeFunctions : public ModulePass { + static char ID; // Pass identification, replacement for typeid + MergeFunctions() : ModulePass(&ID) {} + + bool runOnModule(Module &M); + }; +} + +char MergeFunctions::ID = 0; +static RegisterPass +X("mergefunc", "Merge Functions"); + +ModulePass *llvm::createMergeFunctionsPass() { + return new MergeFunctions(); +} + +// ===----------------------------------------------------------------------=== +// Comparison of functions +// ===----------------------------------------------------------------------=== + +static unsigned long hash(const Function *F) { + const FunctionType *FTy = F->getFunctionType(); + + FoldingSetNodeID ID; + ID.AddInteger(F->size()); + ID.AddInteger(F->getCallingConv()); + ID.AddBoolean(F->hasGC()); + ID.AddBoolean(FTy->isVarArg()); + ID.AddInteger(FTy->getReturnType()->getTypeID()); + for (unsigned i = 0, e = FTy->getNumParams(); i != e; ++i) + ID.AddInteger(FTy->getParamType(i)->getTypeID()); + return ID.ComputeHash(); +} + +/// IgnoreBitcasts - given a bitcast, returns the first non-bitcast found by +/// walking the chain of cast operands. Otherwise, returns the argument. +static Value* IgnoreBitcasts(Value *V) { + while (BitCastInst *BC = dyn_cast(V)) + V = BC->getOperand(0); + + return V; +} + +/// isEquivalentType - any two pointers are equivalent. Otherwise, standard +/// type equivalence rules apply. +static bool isEquivalentType(const Type *Ty1, const Type *Ty2) { + if (Ty1 == Ty2) + return true; + if (Ty1->getTypeID() != Ty2->getTypeID()) + return false; + + switch(Ty1->getTypeID()) { + case Type::VoidTyID: + case Type::FloatTyID: + case Type::DoubleTyID: + case Type::X86_FP80TyID: + case Type::FP128TyID: + case Type::PPC_FP128TyID: + case Type::LabelTyID: + case Type::MetadataTyID: + return true; + + case Type::IntegerTyID: + case Type::OpaqueTyID: + // Ty1 == Ty2 would have returned true earlier. + return false; + + default: + llvm_unreachable("Unknown type!"); + return false; + + case Type::PointerTyID: { + const PointerType *PTy1 = cast(Ty1); + const PointerType *PTy2 = cast(Ty2); + return PTy1->getAddressSpace() == PTy2->getAddressSpace(); + } + + case Type::StructTyID: { + const StructType *STy1 = cast(Ty1); + const StructType *STy2 = cast(Ty2); + if (STy1->getNumElements() != STy2->getNumElements()) + return false; + + if (STy1->isPacked() != STy2->isPacked()) + return false; + + for (unsigned i = 0, e = STy1->getNumElements(); i != e; ++i) { + if (!isEquivalentType(STy1->getElementType(i), STy2->getElementType(i))) + return false; + } + return true; + } + + case Type::FunctionTyID: { + const FunctionType *FTy1 = cast(Ty1); + const FunctionType *FTy2 = cast(Ty2); + if (FTy1->getNumParams() != FTy2->getNumParams() || + FTy1->isVarArg() != FTy2->isVarArg()) + return false; + + if (!isEquivalentType(FTy1->getReturnType(), FTy2->getReturnType())) + return false; + + for (unsigned i = 0, e = FTy1->getNumParams(); i != e; ++i) { + if (!isEquivalentType(FTy1->getParamType(i), FTy2->getParamType(i))) + return false; + } + return true; + } + + case Type::ArrayTyID: + case Type::VectorTyID: { + const SequentialType *STy1 = cast(Ty1); + const SequentialType *STy2 = cast(Ty2); + return isEquivalentType(STy1->getElementType(), STy2->getElementType()); + } + } +} + +/// isEquivalentOperation - determine whether the two operations are the same +/// except that pointer-to-A and pointer-to-B are equivalent. This should be +/// kept in sync with Instruction::isSameOperationAs. +static bool +isEquivalentOperation(const Instruction *I1, const Instruction *I2) { + if (I1->getOpcode() != I2->getOpcode() || + I1->getNumOperands() != I2->getNumOperands() || + !isEquivalentType(I1->getType(), I2->getType()) || + !I1->hasSameSubclassOptionalData(I2)) + return false; + + // We have two instructions of identical opcode and #operands. Check to see + // if all operands are the same type + for (unsigned i = 0, e = I1->getNumOperands(); i != e; ++i) + if (!isEquivalentType(I1->getOperand(i)->getType(), + I2->getOperand(i)->getType())) + return false; + + // Check special state that is a part of some instructions. + if (const LoadInst *LI = dyn_cast(I1)) + return LI->isVolatile() == cast(I2)->isVolatile() && + LI->getAlignment() == cast(I2)->getAlignment(); + if (const StoreInst *SI = dyn_cast(I1)) + return SI->isVolatile() == cast(I2)->isVolatile() && + SI->getAlignment() == cast(I2)->getAlignment(); + if (const CmpInst *CI = dyn_cast(I1)) + return CI->getPredicate() == cast(I2)->getPredicate(); + if (const CallInst *CI = dyn_cast(I1)) + return CI->isTailCall() == cast(I2)->isTailCall() && + CI->getCallingConv() == cast(I2)->getCallingConv() && + CI->getAttributes().getRawPointer() == + cast(I2)->getAttributes().getRawPointer(); + if (const InvokeInst *CI = dyn_cast(I1)) + return CI->getCallingConv() == cast(I2)->getCallingConv() && + CI->getAttributes().getRawPointer() == + cast(I2)->getAttributes().getRawPointer(); + if (const InsertValueInst *IVI = dyn_cast(I1)) { + if (IVI->getNumIndices() != cast(I2)->getNumIndices()) + return false; + for (unsigned i = 0, e = IVI->getNumIndices(); i != e; ++i) + if (IVI->idx_begin()[i] != cast(I2)->idx_begin()[i]) + return false; + return true; + } + if (const ExtractValueInst *EVI = dyn_cast(I1)) { + if (EVI->getNumIndices() != cast(I2)->getNumIndices()) + return false; + for (unsigned i = 0, e = EVI->getNumIndices(); i != e; ++i) + if (EVI->idx_begin()[i] != cast(I2)->idx_begin()[i]) + return false; + return true; + } + + return true; +} + +static bool compare(const Value *V, const Value *U) { + assert(!isa(V) && !isa(U) && + "Must not compare basic blocks."); + + assert(isEquivalentType(V->getType(), U->getType()) && + "Two of the same operation have operands of different type."); + + // TODO: If the constant is an expression of F, we should accept that it's + // equal to the same expression in terms of G. + if (isa(V)) + return V == U; + + // The caller has ensured that ValueMap[V] != U. Since Arguments are + // pre-loaded into the ValueMap, and Instructions are added as we go, we know + // that this can only be a mis-match. + if (isa(V) || isa(V)) + return false; + + if (isa(V) && isa(U)) { + const InlineAsm *IAF = cast(V); + const InlineAsm *IAG = cast(U); + return IAF->getAsmString() == IAG->getAsmString() && + IAF->getConstraintString() == IAG->getConstraintString(); + } + + return false; +} + +static bool equals(const BasicBlock *BB1, const BasicBlock *BB2, + DenseMap &ValueMap, + DenseMap &SpeculationMap) { + // Speculatively add it anyways. If it's false, we'll notice a difference + // later, and this won't matter. + ValueMap[BB1] = BB2; + + BasicBlock::const_iterator FI = BB1->begin(), FE = BB1->end(); + BasicBlock::const_iterator GI = BB2->begin(), GE = BB2->end(); + + do { + if (isa(FI)) { + ++FI; + continue; + } + if (isa(GI)) { + ++GI; + continue; + } + + if (!isEquivalentOperation(FI, GI)) + return false; + + if (isa(FI)) { + const GetElementPtrInst *GEPF = cast(FI); + const GetElementPtrInst *GEPG = cast(GI); + if (GEPF->hasAllZeroIndices() && GEPG->hasAllZeroIndices()) { + // It's effectively a bitcast. + ++FI, ++GI; + continue; + } + + // TODO: we only really care about the elements before the index + if (FI->getOperand(0)->getType() != GI->getOperand(0)->getType()) + return false; + } + + if (ValueMap[FI] == GI) { + ++FI, ++GI; + continue; + } + + if (ValueMap[FI] != NULL) + return false; + + for (unsigned i = 0, e = FI->getNumOperands(); i != e; ++i) { + Value *OpF = IgnoreBitcasts(FI->getOperand(i)); + Value *OpG = IgnoreBitcasts(GI->getOperand(i)); + + if (ValueMap[OpF] == OpG) + continue; + + if (ValueMap[OpF] != NULL) + return false; + + if (OpF->getValueID() != OpG->getValueID() || + !isEquivalentType(OpF->getType(), OpG->getType())) + return false; + + if (isa(FI)) { + if (SpeculationMap[OpF] == NULL) + SpeculationMap[OpF] = OpG; + else if (SpeculationMap[OpF] != OpG) + return false; + continue; + } else if (isa(OpF)) { + assert(isa(FI) && + "BasicBlock referenced by non-Terminator non-PHI"); + // This call changes the ValueMap, hence we can't use + // Value *& = ValueMap[...] + if (!equals(cast(OpF), cast(OpG), ValueMap, + SpeculationMap)) + return false; + } else { + if (!compare(OpF, OpG)) + return false; + } + + ValueMap[OpF] = OpG; + } + + ValueMap[FI] = GI; + ++FI, ++GI; + } while (FI != FE && GI != GE); + + return FI == FE && GI == GE; +} + +static bool equals(const Function *F, const Function *G) { + // We need to recheck everything, but check the things that weren't included + // in the hash first. + + if (F->getAttributes() != G->getAttributes()) + return false; + + if (F->hasGC() != G->hasGC()) + return false; + + if (F->hasGC() && F->getGC() != G->getGC()) + return false; + + if (F->hasSection() != G->hasSection()) + return false; + + if (F->hasSection() && F->getSection() != G->getSection()) + return false; + + if (F->isVarArg() != G->isVarArg()) + return false; + + // TODO: if it's internal and only used in direct calls, we could handle this + // case too. + if (F->getCallingConv() != G->getCallingConv()) + return false; + + if (!isEquivalentType(F->getFunctionType(), G->getFunctionType())) + return false; + + DenseMap ValueMap; + DenseMap SpeculationMap; + ValueMap[F] = G; + + assert(F->arg_size() == G->arg_size() && + "Identical functions have a different number of args."); + + for (Function::const_arg_iterator fi = F->arg_begin(), gi = G->arg_begin(), + fe = F->arg_end(); fi != fe; ++fi, ++gi) + ValueMap[fi] = gi; + + if (!equals(&F->getEntryBlock(), &G->getEntryBlock(), ValueMap, + SpeculationMap)) + return false; + + for (DenseMap::iterator + I = SpeculationMap.begin(), E = SpeculationMap.end(); I != E; ++I) { + if (ValueMap[I->first] != I->second) + return false; + } + + return true; +} + +// ===----------------------------------------------------------------------=== +// Folding of functions +// ===----------------------------------------------------------------------=== + +// Cases: +// * F is external strong, G is external strong: +// turn G into a thunk to F (1) +// * F is external strong, G is external weak: +// turn G into a thunk to F (1) +// * F is external weak, G is external weak: +// unfoldable +// * F is external strong, G is internal: +// address of G taken: +// turn G into a thunk to F (1) +// address of G not taken: +// make G an alias to F (2) +// * F is internal, G is external weak +// address of F is taken: +// turn G into a thunk to F (1) +// address of F is not taken: +// make G an alias of F (2) +// * F is internal, G is internal: +// address of F and G are taken: +// turn G into a thunk to F (1) +// address of G is not taken: +// make G an alias to F (2) +// +// alias requires linkage == (external,local,weak) fallback to creating a thunk +// external means 'externally visible' linkage != (internal,private) +// internal means linkage == (internal,private) +// weak means linkage mayBeOverridable +// being external implies that the address is taken +// +// 1. turn G into a thunk to F +// 2. make G an alias to F + +enum LinkageCategory { + ExternalStrong, + ExternalWeak, + Internal +}; + +static LinkageCategory categorize(const Function *F) { + switch (F->getLinkage()) { + case GlobalValue::InternalLinkage: + case GlobalValue::PrivateLinkage: + case GlobalValue::LinkerPrivateLinkage: + return Internal; + + case GlobalValue::WeakAnyLinkage: + case GlobalValue::WeakODRLinkage: + case GlobalValue::ExternalWeakLinkage: + return ExternalWeak; + + case GlobalValue::ExternalLinkage: + case GlobalValue::AvailableExternallyLinkage: + case GlobalValue::LinkOnceAnyLinkage: + case GlobalValue::LinkOnceODRLinkage: + case GlobalValue::AppendingLinkage: + case GlobalValue::DLLImportLinkage: + case GlobalValue::DLLExportLinkage: + case GlobalValue::GhostLinkage: + case GlobalValue::CommonLinkage: + return ExternalStrong; + } + + llvm_unreachable("Unknown LinkageType."); + return ExternalWeak; +} + +static void ThunkGToF(Function *F, Function *G) { + Function *NewG = Function::Create(G->getFunctionType(), G->getLinkage(), "", + G->getParent()); + BasicBlock *BB = BasicBlock::Create(F->getContext(), "", NewG); + + std::vector Args; + unsigned i = 0; + const FunctionType *FFTy = F->getFunctionType(); + for (Function::arg_iterator AI = NewG->arg_begin(), AE = NewG->arg_end(); + AI != AE; ++AI) { + if (FFTy->getParamType(i) == AI->getType()) + Args.push_back(AI); + else { + Value *BCI = new BitCastInst(AI, FFTy->getParamType(i), "", BB); + Args.push_back(BCI); + } + ++i; + } + + CallInst *CI = CallInst::Create(F, Args.begin(), Args.end(), "", BB); + CI->setTailCall(); + CI->setCallingConv(F->getCallingConv()); + if (NewG->getReturnType() == Type::getVoidTy(F->getContext())) { + ReturnInst::Create(F->getContext(), BB); + } else if (CI->getType() != NewG->getReturnType()) { + Value *BCI = new BitCastInst(CI, NewG->getReturnType(), "", BB); + ReturnInst::Create(F->getContext(), BCI, BB); + } else { + ReturnInst::Create(F->getContext(), CI, BB); + } + + NewG->copyAttributesFrom(G); + NewG->takeName(G); + G->replaceAllUsesWith(NewG); + G->eraseFromParent(); + + // TODO: look at direct callers to G and make them all direct callers to F. +} + +static void AliasGToF(Function *F, Function *G) { + if (!G->hasExternalLinkage() && !G->hasLocalLinkage() && !G->hasWeakLinkage()) + return ThunkGToF(F, G); + + GlobalAlias *GA = new GlobalAlias( + G->getType(), G->getLinkage(), "", + ConstantExpr::getBitCast(F, G->getType()), G->getParent()); + F->setAlignment(std::max(F->getAlignment(), G->getAlignment())); + GA->takeName(G); + GA->setVisibility(G->getVisibility()); + G->replaceAllUsesWith(GA); + G->eraseFromParent(); +} + +static bool fold(std::vector &FnVec, unsigned i, unsigned j) { + Function *F = FnVec[i]; + Function *G = FnVec[j]; + + LinkageCategory catF = categorize(F); + LinkageCategory catG = categorize(G); + + if (catF == ExternalWeak || (catF == Internal && catG == ExternalStrong)) { + std::swap(FnVec[i], FnVec[j]); + std::swap(F, G); + std::swap(catF, catG); + } + + switch (catF) { + case ExternalStrong: + switch (catG) { + case ExternalStrong: + case ExternalWeak: + ThunkGToF(F, G); + break; + case Internal: + if (G->hasAddressTaken()) + ThunkGToF(F, G); + else + AliasGToF(F, G); + break; + } + break; + + case ExternalWeak: { + assert(catG == ExternalWeak); + + // Make them both thunks to the same internal function. + F->setAlignment(std::max(F->getAlignment(), G->getAlignment())); + Function *H = Function::Create(F->getFunctionType(), F->getLinkage(), "", + F->getParent()); + H->copyAttributesFrom(F); + H->takeName(F); + F->replaceAllUsesWith(H); + + ThunkGToF(F, G); + ThunkGToF(F, H); + + F->setLinkage(GlobalValue::InternalLinkage); + } break; + + case Internal: + switch (catG) { + case ExternalStrong: + llvm_unreachable(0); + // fall-through + case ExternalWeak: + if (F->hasAddressTaken()) + ThunkGToF(F, G); + else + AliasGToF(F, G); + break; + case Internal: { + bool addrTakenF = F->hasAddressTaken(); + bool addrTakenG = G->hasAddressTaken(); + if (!addrTakenF && addrTakenG) { + std::swap(FnVec[i], FnVec[j]); + std::swap(F, G); + std::swap(addrTakenF, addrTakenG); + } + + if (addrTakenF && addrTakenG) { + ThunkGToF(F, G); + } else { + assert(!addrTakenG); + AliasGToF(F, G); + } + } break; + } + break; + } + + ++NumFunctionsMerged; + return true; +} + +// ===----------------------------------------------------------------------=== +// Pass definition +// ===----------------------------------------------------------------------=== + +bool MergeFunctions::runOnModule(Module &M) { + bool Changed = false; + + std::map > FnMap; + + for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F) { + if (F->isDeclaration() || F->isIntrinsic()) + continue; + + FnMap[hash(F)].push_back(F); + } + + // TODO: instead of running in a loop, we could also fold functions in + // callgraph order. Constructing the CFG probably isn't cheaper than just + // running in a loop, unless it happened to already be available. + + bool LocalChanged; + do { + LocalChanged = false; + DEBUG(errs() << "size: " << FnMap.size() << "\n"); + for (std::map >::iterator + I = FnMap.begin(), E = FnMap.end(); I != E; ++I) { + std::vector &FnVec = I->second; + DEBUG(errs() << "hash (" << I->first << "): " << FnVec.size() << "\n"); + + for (int i = 0, e = FnVec.size(); i != e; ++i) { + for (int j = i + 1; j != e; ++j) { + bool isEqual = equals(FnVec[i], FnVec[j]); + + DEBUG(errs() << " " << FnVec[i]->getName() + << (isEqual ? " == " : " != ") + << FnVec[j]->getName() << "\n"); + + if (isEqual) { + if (fold(FnVec, i, j)) { + LocalChanged = true; + FnVec.erase(FnVec.begin() + j); + --j, --e; + } + } + } + } + + } + Changed |= LocalChanged; + } while (LocalChanged); + + return Changed; +} diff --git a/libclamav/c++/llvm/lib/Transforms/IPO/PartialInlining.cpp b/libclamav/c++/llvm/lib/Transforms/IPO/PartialInlining.cpp new file mode 100644 index 000000000..b955b9743 --- /dev/null +++ b/libclamav/c++/llvm/lib/Transforms/IPO/PartialInlining.cpp @@ -0,0 +1,176 @@ +//===- PartialInlining.cpp - Inline parts of functions --------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This pass performs partial inlining, typically by inlining an if statement +// that surrounds the body of the function. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "partialinlining" +#include "llvm/Transforms/IPO.h" +#include "llvm/Instructions.h" +#include "llvm/Module.h" +#include "llvm/Pass.h" +#include "llvm/Analysis/Dominators.h" +#include "llvm/Transforms/Utils/Cloning.h" +#include "llvm/Transforms/Utils/FunctionUtils.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/Support/CFG.h" +using namespace llvm; + +STATISTIC(NumPartialInlined, "Number of functions partially inlined"); + +namespace { + struct PartialInliner : public ModulePass { + virtual void getAnalysisUsage(AnalysisUsage &AU) const { } + static char ID; // Pass identification, replacement for typeid + PartialInliner() : ModulePass(&ID) {} + + bool runOnModule(Module& M); + + private: + Function* unswitchFunction(Function* F); + }; +} + +char PartialInliner::ID = 0; +static RegisterPass X("partial-inliner", "Partial Inliner"); + +ModulePass* llvm::createPartialInliningPass() { return new PartialInliner(); } + +Function* PartialInliner::unswitchFunction(Function* F) { + // First, verify that this function is an unswitching candidate... + BasicBlock* entryBlock = F->begin(); + BranchInst *BR = dyn_cast(entryBlock->getTerminator()); + if (!BR || BR->isUnconditional()) + return 0; + + BasicBlock* returnBlock = 0; + BasicBlock* nonReturnBlock = 0; + unsigned returnCount = 0; + for (succ_iterator SI = succ_begin(entryBlock), SE = succ_end(entryBlock); + SI != SE; ++SI) + if (isa((*SI)->getTerminator())) { + returnBlock = *SI; + returnCount++; + } else + nonReturnBlock = *SI; + + if (returnCount != 1) + return 0; + + // Clone the function, so that we can hack away on it. + DenseMap ValueMap; + Function* duplicateFunction = CloneFunction(F, ValueMap); + duplicateFunction->setLinkage(GlobalValue::InternalLinkage); + F->getParent()->getFunctionList().push_back(duplicateFunction); + BasicBlock* newEntryBlock = cast(ValueMap[entryBlock]); + BasicBlock* newReturnBlock = cast(ValueMap[returnBlock]); + BasicBlock* newNonReturnBlock = cast(ValueMap[nonReturnBlock]); + + // Go ahead and update all uses to the duplicate, so that we can just + // use the inliner functionality when we're done hacking. + F->replaceAllUsesWith(duplicateFunction); + + // Special hackery is needed with PHI nodes that have inputs from more than + // one extracted block. For simplicity, just split the PHIs into a two-level + // sequence of PHIs, some of which will go in the extracted region, and some + // of which will go outside. + BasicBlock* preReturn = newReturnBlock; + newReturnBlock = newReturnBlock->splitBasicBlock( + newReturnBlock->getFirstNonPHI()); + BasicBlock::iterator I = preReturn->begin(); + BasicBlock::iterator Ins = newReturnBlock->begin(); + while (I != preReturn->end()) { + PHINode* OldPhi = dyn_cast(I); + if (!OldPhi) break; + + PHINode* retPhi = PHINode::Create(OldPhi->getType(), "", Ins); + OldPhi->replaceAllUsesWith(retPhi); + Ins = newReturnBlock->getFirstNonPHI(); + + retPhi->addIncoming(I, preReturn); + retPhi->addIncoming(OldPhi->getIncomingValueForBlock(newEntryBlock), + newEntryBlock); + OldPhi->removeIncomingValue(newEntryBlock); + + ++I; + } + newEntryBlock->getTerminator()->replaceUsesOfWith(preReturn, newReturnBlock); + + // Gather up the blocks that we're going to extract. + std::vector toExtract; + toExtract.push_back(newNonReturnBlock); + for (Function::iterator FI = duplicateFunction->begin(), + FE = duplicateFunction->end(); FI != FE; ++FI) + if (&*FI != newEntryBlock && &*FI != newReturnBlock && + &*FI != newNonReturnBlock) + toExtract.push_back(FI); + + // The CodeExtractor needs a dominator tree. + DominatorTree DT; + DT.runOnFunction(*duplicateFunction); + + // Extract the body of the the if. + Function* extractedFunction = ExtractCodeRegion(DT, toExtract); + + // Inline the top-level if test into all callers. + std::vector Users(duplicateFunction->use_begin(), + duplicateFunction->use_end()); + for (std::vector::iterator UI = Users.begin(), UE = Users.end(); + UI != UE; ++UI) + if (CallInst* CI = dyn_cast(*UI)) + InlineFunction(CI); + else if (InvokeInst* II = dyn_cast(*UI)) + InlineFunction(II); + + // Ditch the duplicate, since we're done with it, and rewrite all remaining + // users (function pointers, etc.) back to the original function. + duplicateFunction->replaceAllUsesWith(F); + duplicateFunction->eraseFromParent(); + + ++NumPartialInlined; + + return extractedFunction; +} + +bool PartialInliner::runOnModule(Module& M) { + std::vector worklist; + worklist.reserve(M.size()); + for (Module::iterator FI = M.begin(), FE = M.end(); FI != FE; ++FI) + if (!FI->use_empty() && !FI->isDeclaration()) + worklist.push_back(&*FI); + + bool changed = false; + while (!worklist.empty()) { + Function* currFunc = worklist.back(); + worklist.pop_back(); + + if (currFunc->use_empty()) continue; + + bool recursive = false; + for (Function::use_iterator UI = currFunc->use_begin(), + UE = currFunc->use_end(); UI != UE; ++UI) + if (Instruction* I = dyn_cast(UI)) + if (I->getParent()->getParent() == currFunc) { + recursive = true; + break; + } + if (recursive) continue; + + + if (Function* newFunc = unswitchFunction(currFunc)) { + worklist.push_back(newFunc); + changed = true; + } + + } + + return changed; +} diff --git a/libclamav/c++/llvm/lib/Transforms/IPO/PartialSpecialization.cpp b/libclamav/c++/llvm/lib/Transforms/IPO/PartialSpecialization.cpp new file mode 100644 index 000000000..084b94e53 --- /dev/null +++ b/libclamav/c++/llvm/lib/Transforms/IPO/PartialSpecialization.cpp @@ -0,0 +1,190 @@ +//===-- PartialSpecialization.cpp - Specialize for common constants--------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This pass finds function arguments that are often a common constant and +// specializes a version of the called function for that constant. +// +// This pass simply does the cloning for functions it specializes. It depends +// on IPSCCP and DAE to clean up the results. +// +// The initial heuristic favors constant arguments that are used in control +// flow. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "partialspecialization" +#include "llvm/Transforms/IPO.h" +#include "llvm/Constant.h" +#include "llvm/Instructions.h" +#include "llvm/Module.h" +#include "llvm/Pass.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/Transforms/Utils/Cloning.h" +#include "llvm/Support/CallSite.h" +#include "llvm/ADT/DenseSet.h" +#include +using namespace llvm; + +STATISTIC(numSpecialized, "Number of specialized functions created"); + +// Call must be used at least occasionally +static const int CallsMin = 5; + +// Must have 10% of calls having the same constant to specialize on +static const double ConstValPercent = .1; + +namespace { + class PartSpec : public ModulePass { + void scanForInterest(Function&, SmallVector&); + int scanDistribution(Function&, int, std::map&); + public : + static char ID; // Pass identification, replacement for typeid + PartSpec() : ModulePass(&ID) {} + bool runOnModule(Module &M); + }; +} + +char PartSpec::ID = 0; +static RegisterPass +X("partialspecialization", "Partial Specialization"); + +// Specialize F by replacing the arguments (keys) in replacements with the +// constants (values). Replace all calls to F with those constants with +// a call to the specialized function. Returns the specialized function +static Function* +SpecializeFunction(Function* F, + DenseMap& replacements) { + // arg numbers of deleted arguments + DenseSet deleted; + for (DenseMap::iterator + repb = replacements.begin(), repe = replacements.end(); + repb != repe; ++repb) + deleted.insert(cast(repb->first)->getArgNo()); + + Function* NF = CloneFunction(F, replacements); + NF->setLinkage(GlobalValue::InternalLinkage); + F->getParent()->getFunctionList().push_back(NF); + + for (Value::use_iterator ii = F->use_begin(), ee = F->use_end(); + ii != ee; ) { + Value::use_iterator i = ii; + ++ii; + if (isa(i) || isa(i)) { + CallSite CS(cast(i)); + if (CS.getCalledFunction() == F) { + + SmallVector args; + for (unsigned x = 0; x < CS.arg_size(); ++x) + if (!deleted.count(x)) + args.push_back(CS.getArgument(x)); + Value* NCall; + if (CallInst *CI = dyn_cast(i)) { + NCall = CallInst::Create(NF, args.begin(), args.end(), + CI->getName(), CI); + cast(NCall)->setTailCall(CI->isTailCall()); + cast(NCall)->setCallingConv(CI->getCallingConv()); + } else { + InvokeInst *II = cast(i); + NCall = InvokeInst::Create(NF, II->getNormalDest(), + II->getUnwindDest(), + args.begin(), args.end(), + II->getName(), II); + cast(NCall)->setCallingConv(II->getCallingConv()); + } + CS.getInstruction()->replaceAllUsesWith(NCall); + CS.getInstruction()->eraseFromParent(); + } + } + } + return NF; +} + + +bool PartSpec::runOnModule(Module &M) { + bool Changed = false; + for (Module::iterator I = M.begin(); I != M.end(); ++I) { + Function &F = *I; + if (F.isDeclaration() || F.mayBeOverridden()) continue; + SmallVector interestingArgs; + scanForInterest(F, interestingArgs); + + // Find the first interesting Argument that we can specialize on + // If there are multiple interesting Arguments, then those will be found + // when processing the cloned function. + bool breakOuter = false; + for (unsigned int x = 0; !breakOuter && x < interestingArgs.size(); ++x) { + std::map distribution; + int total = scanDistribution(F, interestingArgs[x], distribution); + if (total > CallsMin) + for (std::map::iterator ii = distribution.begin(), + ee = distribution.end(); ii != ee; ++ii) + if (total > ii->second && ii->first && + ii->second > total * ConstValPercent) { + DenseMap m; + Function::arg_iterator arg = F.arg_begin(); + for (int y = 0; y < interestingArgs[x]; ++y) + ++arg; + m[&*arg] = ii->first; + SpecializeFunction(&F, m); + ++numSpecialized; + breakOuter = true; + Changed = true; + } + } + } + return Changed; +} + +/// scanForInterest - This function decides which arguments would be worth +/// specializing on. +void PartSpec::scanForInterest(Function& F, SmallVector& args) { + for(Function::arg_iterator ii = F.arg_begin(), ee = F.arg_end(); + ii != ee; ++ii) { + for(Value::use_iterator ui = ii->use_begin(), ue = ii->use_end(); + ui != ue; ++ui) { + + bool interesting = false; + + if (isa(ui)) interesting = true; + else if (isa(ui)) + interesting = ui->getOperand(0) == ii; + else if (isa(ui)) + interesting = ui->getOperand(0) == ii; + else if (isa(ui)) interesting = true; + else if (isa(ui)) interesting = true; + + if (interesting) { + args.push_back(std::distance(F.arg_begin(), ii)); + break; + } + } + } +} + +/// scanDistribution - Construct a histogram of constants for arg of F at arg. +int PartSpec::scanDistribution(Function& F, int arg, + std::map& dist) { + bool hasIndirect = false; + int total = 0; + for(Value::use_iterator ii = F.use_begin(), ee = F.use_end(); + ii != ee; ++ii) + if ((isa(ii) || isa(ii)) + && ii->getOperand(0) == &F) { + ++dist[dyn_cast(ii->getOperand(arg + 1))]; + ++total; + } else + hasIndirect = true; + + // Preserve the original address taken function even if all other uses + // will be specialized. + if (hasIndirect) ++total; + return total; +} + +ModulePass* llvm::createPartialSpecializationPass() { return new PartSpec(); } diff --git a/libclamav/c++/llvm/lib/Transforms/IPO/PruneEH.cpp b/libclamav/c++/llvm/lib/Transforms/IPO/PruneEH.cpp new file mode 100644 index 000000000..3ae771c55 --- /dev/null +++ b/libclamav/c++/llvm/lib/Transforms/IPO/PruneEH.cpp @@ -0,0 +1,251 @@ +//===- PruneEH.cpp - Pass which deletes unused exception handlers ---------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements a simple interprocedural pass which walks the +// call-graph, turning invoke instructions into calls, iff the callee cannot +// throw an exception, and marking functions 'nounwind' if they cannot throw. +// It implements this as a bottom-up traversal of the call-graph. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "prune-eh" +#include "llvm/Transforms/IPO.h" +#include "llvm/CallGraphSCCPass.h" +#include "llvm/Constants.h" +#include "llvm/Function.h" +#include "llvm/LLVMContext.h" +#include "llvm/Instructions.h" +#include "llvm/IntrinsicInst.h" +#include "llvm/Analysis/CallGraph.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/Support/CFG.h" +#include +#include +using namespace llvm; + +STATISTIC(NumRemoved, "Number of invokes removed"); +STATISTIC(NumUnreach, "Number of noreturn calls optimized"); + +namespace { + struct PruneEH : public CallGraphSCCPass { + static char ID; // Pass identification, replacement for typeid + PruneEH() : CallGraphSCCPass(&ID) {} + + // runOnSCC - Analyze the SCC, performing the transformation if possible. + bool runOnSCC(std::vector &SCC); + + bool SimplifyFunction(Function *F); + void DeleteBasicBlock(BasicBlock *BB); + }; +} + +char PruneEH::ID = 0; +static RegisterPass +X("prune-eh", "Remove unused exception handling info"); + +Pass *llvm::createPruneEHPass() { return new PruneEH(); } + + +bool PruneEH::runOnSCC(std::vector &SCC) { + SmallPtrSet SCCNodes; + CallGraph &CG = getAnalysis(); + bool MadeChange = false; + + // Fill SCCNodes with the elements of the SCC. Used for quickly + // looking up whether a given CallGraphNode is in this SCC. + for (unsigned i = 0, e = SCC.size(); i != e; ++i) + SCCNodes.insert(SCC[i]); + + // First pass, scan all of the functions in the SCC, simplifying them + // according to what we know. + for (unsigned i = 0, e = SCC.size(); i != e; ++i) + if (Function *F = SCC[i]->getFunction()) + MadeChange |= SimplifyFunction(F); + + // Next, check to see if any callees might throw or if there are any external + // functions in this SCC: if so, we cannot prune any functions in this SCC. + // Definitions that are weak and not declared non-throwing might be + // overridden at linktime with something that throws, so assume that. + // If this SCC includes the unwind instruction, we KNOW it throws, so + // obviously the SCC might throw. + // + bool SCCMightUnwind = false, SCCMightReturn = false; + for (unsigned i = 0, e = SCC.size(); + (!SCCMightUnwind || !SCCMightReturn) && i != e; ++i) { + Function *F = SCC[i]->getFunction(); + if (F == 0) { + SCCMightUnwind = true; + SCCMightReturn = true; + } else if (F->isDeclaration() || F->mayBeOverridden()) { + SCCMightUnwind |= !F->doesNotThrow(); + SCCMightReturn |= !F->doesNotReturn(); + } else { + bool CheckUnwind = !SCCMightUnwind && !F->doesNotThrow(); + bool CheckReturn = !SCCMightReturn && !F->doesNotReturn(); + + if (!CheckUnwind && !CheckReturn) + continue; + + // Check to see if this function performs an unwind or calls an + // unwinding function. + for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) { + if (CheckUnwind && isa(BB->getTerminator())) { + // Uses unwind! + SCCMightUnwind = true; + } else if (CheckReturn && isa(BB->getTerminator())) { + SCCMightReturn = true; + } + + // Invoke instructions don't allow unwinding to continue, so we are + // only interested in call instructions. + if (CheckUnwind && !SCCMightUnwind) + for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ++I) + if (CallInst *CI = dyn_cast(I)) { + if (CI->doesNotThrow()) { + // This call cannot throw. + } else if (Function *Callee = CI->getCalledFunction()) { + CallGraphNode *CalleeNode = CG[Callee]; + // If the callee is outside our current SCC then we may + // throw because it might. + if (!SCCNodes.count(CalleeNode)) { + SCCMightUnwind = true; + break; + } + } else { + // Indirect call, it might throw. + SCCMightUnwind = true; + break; + } + } + if (SCCMightUnwind && SCCMightReturn) break; + } + } + } + + // If the SCC doesn't unwind or doesn't throw, note this fact. + if (!SCCMightUnwind || !SCCMightReturn) + for (unsigned i = 0, e = SCC.size(); i != e; ++i) { + Attributes NewAttributes = Attribute::None; + + if (!SCCMightUnwind) + NewAttributes |= Attribute::NoUnwind; + if (!SCCMightReturn) + NewAttributes |= Attribute::NoReturn; + + const AttrListPtr &PAL = SCC[i]->getFunction()->getAttributes(); + const AttrListPtr &NPAL = PAL.addAttr(~0, NewAttributes); + if (PAL != NPAL) { + MadeChange = true; + SCC[i]->getFunction()->setAttributes(NPAL); + } + } + + for (unsigned i = 0, e = SCC.size(); i != e; ++i) { + // Convert any invoke instructions to non-throwing functions in this node + // into call instructions with a branch. This makes the exception blocks + // dead. + if (Function *F = SCC[i]->getFunction()) + MadeChange |= SimplifyFunction(F); + } + + return MadeChange; +} + + +// SimplifyFunction - Given information about callees, simplify the specified +// function if we have invokes to non-unwinding functions or code after calls to +// no-return functions. +bool PruneEH::SimplifyFunction(Function *F) { + bool MadeChange = false; + for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) { + if (InvokeInst *II = dyn_cast(BB->getTerminator())) + if (II->doesNotThrow()) { + SmallVector Args(II->op_begin()+3, II->op_end()); + // Insert a call instruction before the invoke. + CallInst *Call = CallInst::Create(II->getCalledValue(), + Args.begin(), Args.end(), "", II); + Call->takeName(II); + Call->setCallingConv(II->getCallingConv()); + Call->setAttributes(II->getAttributes()); + + // Anything that used the value produced by the invoke instruction + // now uses the value produced by the call instruction. Note that we + // do this even for void functions and calls with no uses so that the + // callgraph edge is updated. + II->replaceAllUsesWith(Call); + BasicBlock *UnwindBlock = II->getUnwindDest(); + UnwindBlock->removePredecessor(II->getParent()); + + // Insert a branch to the normal destination right before the + // invoke. + BranchInst::Create(II->getNormalDest(), II); + + // Finally, delete the invoke instruction! + BB->getInstList().pop_back(); + + // If the unwind block is now dead, nuke it. + if (pred_begin(UnwindBlock) == pred_end(UnwindBlock)) + DeleteBasicBlock(UnwindBlock); // Delete the new BB. + + ++NumRemoved; + MadeChange = true; + } + + for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ) + if (CallInst *CI = dyn_cast(I++)) + if (CI->doesNotReturn() && !isa(I)) { + // This call calls a function that cannot return. Insert an + // unreachable instruction after it and simplify the code. Do this + // by splitting the BB, adding the unreachable, then deleting the + // new BB. + BasicBlock *New = BB->splitBasicBlock(I); + + // Remove the uncond branch and add an unreachable. + BB->getInstList().pop_back(); + new UnreachableInst(BB->getContext(), BB); + + DeleteBasicBlock(New); // Delete the new BB. + MadeChange = true; + ++NumUnreach; + break; + } + } + + return MadeChange; +} + +/// DeleteBasicBlock - remove the specified basic block from the program, +/// updating the callgraph to reflect any now-obsolete edges due to calls that +/// exist in the BB. +void PruneEH::DeleteBasicBlock(BasicBlock *BB) { + assert(pred_begin(BB) == pred_end(BB) && "BB is not dead!"); + CallGraph &CG = getAnalysis(); + + CallGraphNode *CGN = CG[BB->getParent()]; + for (BasicBlock::iterator I = BB->end(), E = BB->begin(); I != E; ) { + --I; + if (CallInst *CI = dyn_cast(I)) { + if (!isa(I)) + CGN->removeCallEdgeFor(CI); + } else if (InvokeInst *II = dyn_cast(I)) + CGN->removeCallEdgeFor(II); + if (!I->use_empty()) + I->replaceAllUsesWith(UndefValue::get(I->getType())); + } + + // Get the list of successors of this block. + std::vector Succs(succ_begin(BB), succ_end(BB)); + + for (unsigned i = 0, e = Succs.size(); i != e; ++i) + Succs[i]->removePredecessor(BB); + + BB->eraseFromParent(); +} diff --git a/libclamav/c++/llvm/lib/Transforms/IPO/StripDeadPrototypes.cpp b/libclamav/c++/llvm/lib/Transforms/IPO/StripDeadPrototypes.cpp new file mode 100644 index 000000000..4566a7634 --- /dev/null +++ b/libclamav/c++/llvm/lib/Transforms/IPO/StripDeadPrototypes.cpp @@ -0,0 +1,71 @@ +//===-- StripDeadPrototypes.cpp - Remove unused function declarations ----===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This pass loops over all of the functions in the input module, looking for +// dead declarations and removes them. Dead declarations are declarations of +// functions for which no implementation is available (i.e., declarations for +// unused library functions). +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "strip-dead-prototypes" +#include "llvm/Transforms/IPO.h" +#include "llvm/Pass.h" +#include "llvm/Module.h" +#include "llvm/ADT/Statistic.h" +using namespace llvm; + +STATISTIC(NumDeadPrototypes, "Number of dead prototypes removed"); + +namespace { + +/// @brief Pass to remove unused function declarations. +class StripDeadPrototypesPass : public ModulePass { +public: + static char ID; // Pass identification, replacement for typeid + StripDeadPrototypesPass() : ModulePass(&ID) { } + virtual bool runOnModule(Module &M); +}; + +} // end anonymous namespace + +char StripDeadPrototypesPass::ID = 0; +static RegisterPass +X("strip-dead-prototypes", "Strip Unused Function Prototypes"); + +bool StripDeadPrototypesPass::runOnModule(Module &M) { + bool MadeChange = false; + + // Erase dead function prototypes. + for (Module::iterator I = M.begin(), E = M.end(); I != E; ) { + Function *F = I++; + // Function must be a prototype and unused. + if (F->isDeclaration() && F->use_empty()) { + F->eraseFromParent(); + ++NumDeadPrototypes; + MadeChange = true; + } + } + + // Erase dead global var prototypes. + for (Module::global_iterator I = M.global_begin(), E = M.global_end(); + I != E; ) { + GlobalVariable *GV = I++; + // Global must be a prototype and unused. + if (GV->isDeclaration() && GV->use_empty()) + GV->eraseFromParent(); + } + + // Return an indication of whether we changed anything or not. + return MadeChange; +} + +ModulePass *llvm::createStripDeadPrototypesPass() { + return new StripDeadPrototypesPass(); +} diff --git a/libclamav/c++/llvm/lib/Transforms/IPO/StripSymbols.cpp b/libclamav/c++/llvm/lib/Transforms/IPO/StripSymbols.cpp new file mode 100644 index 000000000..0b5e00706 --- /dev/null +++ b/libclamav/c++/llvm/lib/Transforms/IPO/StripSymbols.cpp @@ -0,0 +1,286 @@ +//===- StripSymbols.cpp - Strip symbols and debug info from a module ------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// The StripSymbols transformation implements code stripping. Specifically, it +// can delete: +// +// * names for virtual registers +// * symbols for internal globals and functions +// * debug information +// +// Note that this transformation makes code much less readable, so it should +// only be used in situations where the 'strip' utility would be used, such as +// reducing code size or making it harder to reverse engineer code. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Transforms/IPO.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Instructions.h" +#include "llvm/LLVMContext.h" +#include "llvm/Module.h" +#include "llvm/Pass.h" +#include "llvm/Analysis/DebugInfo.h" +#include "llvm/ValueSymbolTable.h" +#include "llvm/TypeSymbolTable.h" +#include "llvm/Transforms/Utils/Local.h" +#include "llvm/ADT/SmallPtrSet.h" +using namespace llvm; + +namespace { + class StripSymbols : public ModulePass { + bool OnlyDebugInfo; + public: + static char ID; // Pass identification, replacement for typeid + explicit StripSymbols(bool ODI = false) + : ModulePass(&ID), OnlyDebugInfo(ODI) {} + + virtual bool runOnModule(Module &M); + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + } + }; + + class StripNonDebugSymbols : public ModulePass { + public: + static char ID; // Pass identification, replacement for typeid + explicit StripNonDebugSymbols() + : ModulePass(&ID) {} + + virtual bool runOnModule(Module &M); + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + } + }; + + class StripDebugDeclare : public ModulePass { + public: + static char ID; // Pass identification, replacement for typeid + explicit StripDebugDeclare() + : ModulePass(&ID) {} + + virtual bool runOnModule(Module &M); + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + } + }; +} + +char StripSymbols::ID = 0; +static RegisterPass +X("strip", "Strip all symbols from a module"); + +ModulePass *llvm::createStripSymbolsPass(bool OnlyDebugInfo) { + return new StripSymbols(OnlyDebugInfo); +} + +char StripNonDebugSymbols::ID = 0; +static RegisterPass +Y("strip-nondebug", "Strip all symbols, except dbg symbols, from a module"); + +ModulePass *llvm::createStripNonDebugSymbolsPass() { + return new StripNonDebugSymbols(); +} + +char StripDebugDeclare::ID = 0; +static RegisterPass +Z("strip-debug-declare", "Strip all llvm.dbg.declare intrinsics"); + +ModulePass *llvm::createStripDebugDeclarePass() { + return new StripDebugDeclare(); +} + +/// OnlyUsedBy - Return true if V is only used by Usr. +static bool OnlyUsedBy(Value *V, Value *Usr) { + for(Value::use_iterator I = V->use_begin(), E = V->use_end(); I != E; ++I) { + User *U = *I; + if (U != Usr) + return false; + } + return true; +} + +static void RemoveDeadConstant(Constant *C) { + assert(C->use_empty() && "Constant is not dead!"); + SmallPtrSet Operands; + for (unsigned i = 0, e = C->getNumOperands(); i != e; ++i) + if (isa(C->getOperand(i)->getType()) && + OnlyUsedBy(C->getOperand(i), C)) + Operands.insert(cast(C->getOperand(i))); + if (GlobalVariable *GV = dyn_cast(C)) { + if (!GV->hasLocalLinkage()) return; // Don't delete non static globals. + GV->eraseFromParent(); + } + else if (!isa(C)) + if (isa(C->getType())) + C->destroyConstant(); + + // If the constant referenced anything, see if we can delete it as well. + for (SmallPtrSet::iterator OI = Operands.begin(), + OE = Operands.end(); OI != OE; ++OI) + RemoveDeadConstant(*OI); +} + +// Strip the symbol table of its names. +// +static void StripSymtab(ValueSymbolTable &ST, bool PreserveDbgInfo) { + for (ValueSymbolTable::iterator VI = ST.begin(), VE = ST.end(); VI != VE; ) { + Value *V = VI->getValue(); + ++VI; + if (!isa(V) || cast(V)->hasLocalLinkage()) { + if (!PreserveDbgInfo || !V->getName().startswith("llvm.dbg")) + // Set name to "", removing from symbol table! + V->setName(""); + } + } +} + +// Strip the symbol table of its names. +static void StripTypeSymtab(TypeSymbolTable &ST, bool PreserveDbgInfo) { + for (TypeSymbolTable::iterator TI = ST.begin(), E = ST.end(); TI != E; ) { + if (PreserveDbgInfo && strncmp(TI->first.c_str(), "llvm.dbg", 8) == 0) + ++TI; + else + ST.remove(TI++); + } +} + +/// Find values that are marked as llvm.used. +static void findUsedValues(GlobalVariable *LLVMUsed, + SmallPtrSet &UsedValues) { + if (LLVMUsed == 0) return; + UsedValues.insert(LLVMUsed); + + ConstantArray *Inits = dyn_cast(LLVMUsed->getInitializer()); + if (Inits == 0) return; + + for (unsigned i = 0, e = Inits->getNumOperands(); i != e; ++i) + if (GlobalValue *GV = + dyn_cast(Inits->getOperand(i)->stripPointerCasts())) + UsedValues.insert(GV); +} + +/// StripSymbolNames - Strip symbol names. +static bool StripSymbolNames(Module &M, bool PreserveDbgInfo) { + + SmallPtrSet llvmUsedValues; + findUsedValues(M.getGlobalVariable("llvm.used"), llvmUsedValues); + findUsedValues(M.getGlobalVariable("llvm.compiler.used"), llvmUsedValues); + + for (Module::global_iterator I = M.global_begin(), E = M.global_end(); + I != E; ++I) { + if (I->hasLocalLinkage() && llvmUsedValues.count(I) == 0) + if (!PreserveDbgInfo || !I->getName().startswith("llvm.dbg")) + I->setName(""); // Internal symbols can't participate in linkage + } + + for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) { + if (I->hasLocalLinkage() && llvmUsedValues.count(I) == 0) + if (!PreserveDbgInfo || !I->getName().startswith("llvm.dbg")) + I->setName(""); // Internal symbols can't participate in linkage + StripSymtab(I->getValueSymbolTable(), PreserveDbgInfo); + } + + // Remove all names from types. + StripTypeSymtab(M.getTypeSymbolTable(), PreserveDbgInfo); + + return true; +} + +// StripDebugInfo - Strip debug info in the module if it exists. +// To do this, we remove llvm.dbg.func.start, llvm.dbg.stoppoint, and +// llvm.dbg.region.end calls, and any globals they point to if now dead. +static bool StripDebugInfo(Module &M) { + + bool Changed = false; + + // Remove all of the calls to the debugger intrinsics, and remove them from + // the module. + if (Function *Declare = M.getFunction("llvm.dbg.declare")) { + while (!Declare->use_empty()) { + CallInst *CI = cast(Declare->use_back()); + CI->eraseFromParent(); + } + Declare->eraseFromParent(); + Changed = true; + } + + NamedMDNode *NMD = M.getNamedMetadata("llvm.dbg.gv"); + if (NMD) { + Changed = true; + NMD->eraseFromParent(); + } + MetadataContext &TheMetadata = M.getContext().getMetadata(); + unsigned MDDbgKind = TheMetadata.getMDKind("dbg"); + if (!MDDbgKind) + return Changed; + + for (Module::iterator MI = M.begin(), ME = M.end(); MI != ME; ++MI) + for (Function::iterator FI = MI->begin(), FE = MI->end(); FI != FE; + ++FI) + for (BasicBlock::iterator BI = FI->begin(), BE = FI->end(); BI != BE; + ++BI) + TheMetadata.removeMD(MDDbgKind, BI); + + return true; +} + +bool StripSymbols::runOnModule(Module &M) { + bool Changed = false; + Changed |= StripDebugInfo(M); + if (!OnlyDebugInfo) + Changed |= StripSymbolNames(M, false); + return Changed; +} + +bool StripNonDebugSymbols::runOnModule(Module &M) { + return StripSymbolNames(M, true); +} + +bool StripDebugDeclare::runOnModule(Module &M) { + + Function *Declare = M.getFunction("llvm.dbg.declare"); + std::vector DeadConstants; + + if (Declare) { + while (!Declare->use_empty()) { + CallInst *CI = cast(Declare->use_back()); + Value *Arg1 = CI->getOperand(1); + Value *Arg2 = CI->getOperand(2); + assert(CI->use_empty() && "llvm.dbg intrinsic should have void result"); + CI->eraseFromParent(); + if (Arg1->use_empty()) { + if (Constant *C = dyn_cast(Arg1)) + DeadConstants.push_back(C); + else + RecursivelyDeleteTriviallyDeadInstructions(Arg1); + } + if (Arg2->use_empty()) + if (Constant *C = dyn_cast(Arg2)) + DeadConstants.push_back(C); + } + Declare->eraseFromParent(); + } + + while (!DeadConstants.empty()) { + Constant *C = DeadConstants.back(); + DeadConstants.pop_back(); + if (GlobalVariable *GV = dyn_cast(C)) { + if (GV->hasLocalLinkage()) + RemoveDeadConstant(GV); + } else + RemoveDeadConstant(C); + } + + return true; +} diff --git a/libclamav/c++/llvm/lib/Transforms/IPO/StructRetPromotion.cpp b/libclamav/c++/llvm/lib/Transforms/IPO/StructRetPromotion.cpp new file mode 100644 index 000000000..67fc9349c --- /dev/null +++ b/libclamav/c++/llvm/lib/Transforms/IPO/StructRetPromotion.cpp @@ -0,0 +1,365 @@ +//===-- StructRetPromotion.cpp - Promote sret arguments ------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This pass finds functions that return a struct (using a pointer to the struct +// as the first argument of the function, marked with the 'sret' attribute) and +// replaces them with a new function that simply returns each of the elements of +// that struct (using multiple return values). +// +// This pass works under a number of conditions: +// 1. The returned struct must not contain other structs +// 2. The returned struct must only be used to load values from +// 3. The placeholder struct passed in is the result of an alloca +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "sretpromotion" +#include "llvm/Transforms/IPO.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/LLVMContext.h" +#include "llvm/Module.h" +#include "llvm/CallGraphSCCPass.h" +#include "llvm/Instructions.h" +#include "llvm/Analysis/CallGraph.h" +#include "llvm/Support/CallSite.h" +#include "llvm/Support/CFG.h" +#include "llvm/Support/Debug.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +STATISTIC(NumRejectedSRETUses , "Number of sret rejected due to unexpected uses"); +STATISTIC(NumSRET , "Number of sret promoted"); +namespace { + /// SRETPromotion - This pass removes sret parameter and updates + /// function to use multiple return value. + /// + struct SRETPromotion : public CallGraphSCCPass { + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + CallGraphSCCPass::getAnalysisUsage(AU); + } + + virtual bool runOnSCC(std::vector &SCC); + static char ID; // Pass identification, replacement for typeid + SRETPromotion() : CallGraphSCCPass(&ID) {} + + private: + CallGraphNode *PromoteReturn(CallGraphNode *CGN); + bool isSafeToUpdateAllCallers(Function *F); + Function *cloneFunctionBody(Function *F, const StructType *STy); + CallGraphNode *updateCallSites(Function *F, Function *NF); + bool nestedStructType(const StructType *STy); + }; +} + +char SRETPromotion::ID = 0; +static RegisterPass +X("sretpromotion", "Promote sret arguments to multiple ret values"); + +Pass *llvm::createStructRetPromotionPass() { + return new SRETPromotion(); +} + +bool SRETPromotion::runOnSCC(std::vector &SCC) { + bool Changed = false; + + for (unsigned i = 0, e = SCC.size(); i != e; ++i) + if (CallGraphNode *NewNode = PromoteReturn(SCC[i])) { + SCC[i] = NewNode; + Changed = true; + } + + return Changed; +} + +/// PromoteReturn - This method promotes function that uses StructRet paramater +/// into a function that uses multiple return values. +CallGraphNode *SRETPromotion::PromoteReturn(CallGraphNode *CGN) { + Function *F = CGN->getFunction(); + + if (!F || F->isDeclaration() || !F->hasLocalLinkage()) + return 0; + + // Make sure that function returns struct. + if (F->arg_size() == 0 || !F->hasStructRetAttr() || F->doesNotReturn()) + return 0; + + DEBUG(errs() << "SretPromotion: Looking at sret function " + << F->getName() << "\n"); + + assert(F->getReturnType() == Type::getVoidTy(F->getContext()) && + "Invalid function return type"); + Function::arg_iterator AI = F->arg_begin(); + const llvm::PointerType *FArgType = dyn_cast(AI->getType()); + assert(FArgType && "Invalid sret parameter type"); + const llvm::StructType *STy = + dyn_cast(FArgType->getElementType()); + assert(STy && "Invalid sret parameter element type"); + + // Check if it is ok to perform this promotion. + if (isSafeToUpdateAllCallers(F) == false) { + DEBUG(errs() << "SretPromotion: Not all callers can be updated\n"); + NumRejectedSRETUses++; + return 0; + } + + DEBUG(errs() << "SretPromotion: sret argument will be promoted\n"); + NumSRET++; + // [1] Replace use of sret parameter + AllocaInst *TheAlloca = new AllocaInst(STy, NULL, "mrv", + F->getEntryBlock().begin()); + Value *NFirstArg = F->arg_begin(); + NFirstArg->replaceAllUsesWith(TheAlloca); + + // [2] Find and replace ret instructions + for (Function::iterator FI = F->begin(), FE = F->end(); FI != FE; ++FI) + for(BasicBlock::iterator BI = FI->begin(), BE = FI->end(); BI != BE; ) { + Instruction *I = BI; + ++BI; + if (isa(I)) { + Value *NV = new LoadInst(TheAlloca, "mrv.ld", I); + ReturnInst *NR = ReturnInst::Create(F->getContext(), NV, I); + I->replaceAllUsesWith(NR); + I->eraseFromParent(); + } + } + + // [3] Create the new function body and insert it into the module. + Function *NF = cloneFunctionBody(F, STy); + + // [4] Update all call sites to use new function + CallGraphNode *NF_CFN = updateCallSites(F, NF); + + CallGraph &CG = getAnalysis(); + NF_CFN->stealCalledFunctionsFrom(CG[F]); + + delete CG.removeFunctionFromModule(F); + return NF_CFN; +} + +// Check if it is ok to perform this promotion. +bool SRETPromotion::isSafeToUpdateAllCallers(Function *F) { + + if (F->use_empty()) + // No users. OK to modify signature. + return true; + + for (Value::use_iterator FnUseI = F->use_begin(), FnUseE = F->use_end(); + FnUseI != FnUseE; ++FnUseI) { + // The function is passed in as an argument to (possibly) another function, + // we can't change it! + CallSite CS = CallSite::get(*FnUseI); + Instruction *Call = CS.getInstruction(); + // The function is used by something else than a call or invoke instruction, + // we can't change it! + if (!Call || !CS.isCallee(FnUseI)) + return false; + CallSite::arg_iterator AI = CS.arg_begin(); + Value *FirstArg = *AI; + + if (!isa(FirstArg)) + return false; + + // Check FirstArg's users. + for (Value::use_iterator ArgI = FirstArg->use_begin(), + ArgE = FirstArg->use_end(); ArgI != ArgE; ++ArgI) { + + // If FirstArg user is a CallInst that does not correspond to current + // call site then this function F is not suitable for sret promotion. + if (CallInst *CI = dyn_cast(ArgI)) { + if (CI != Call) + return false; + } + // If FirstArg user is a GEP whose all users are not LoadInst then + // this function F is not suitable for sret promotion. + else if (GetElementPtrInst *GEP = dyn_cast(ArgI)) { + // TODO : Use dom info and insert PHINodes to collect get results + // from multiple call sites for this GEP. + if (GEP->getParent() != Call->getParent()) + return false; + for (Value::use_iterator GEPI = GEP->use_begin(), GEPE = GEP->use_end(); + GEPI != GEPE; ++GEPI) + if (!isa(GEPI)) + return false; + } + // Any other FirstArg users make this function unsuitable for sret + // promotion. + else + return false; + } + } + + return true; +} + +/// cloneFunctionBody - Create a new function based on F and +/// insert it into module. Remove first argument. Use STy as +/// the return type for new function. +Function *SRETPromotion::cloneFunctionBody(Function *F, + const StructType *STy) { + + const FunctionType *FTy = F->getFunctionType(); + std::vector Params; + + // Attributes - Keep track of the parameter attributes for the arguments. + SmallVector AttributesVec; + const AttrListPtr &PAL = F->getAttributes(); + + // Add any return attributes. + if (Attributes attrs = PAL.getRetAttributes()) + AttributesVec.push_back(AttributeWithIndex::get(0, attrs)); + + // Skip first argument. + Function::arg_iterator I = F->arg_begin(), E = F->arg_end(); + ++I; + // 0th parameter attribute is reserved for return type. + // 1th parameter attribute is for first 1st sret argument. + unsigned ParamIndex = 2; + while (I != E) { + Params.push_back(I->getType()); + if (Attributes Attrs = PAL.getParamAttributes(ParamIndex)) + AttributesVec.push_back(AttributeWithIndex::get(ParamIndex - 1, Attrs)); + ++I; + ++ParamIndex; + } + + // Add any fn attributes. + if (Attributes attrs = PAL.getFnAttributes()) + AttributesVec.push_back(AttributeWithIndex::get(~0, attrs)); + + + FunctionType *NFTy = FunctionType::get(STy, Params, FTy->isVarArg()); + Function *NF = Function::Create(NFTy, F->getLinkage()); + NF->takeName(F); + NF->copyAttributesFrom(F); + NF->setAttributes(AttrListPtr::get(AttributesVec.begin(), AttributesVec.end())); + F->getParent()->getFunctionList().insert(F, NF); + NF->getBasicBlockList().splice(NF->begin(), F->getBasicBlockList()); + + // Replace arguments + I = F->arg_begin(); + E = F->arg_end(); + Function::arg_iterator NI = NF->arg_begin(); + ++I; + while (I != E) { + I->replaceAllUsesWith(NI); + NI->takeName(I); + ++I; + ++NI; + } + + return NF; +} + +/// updateCallSites - Update all sites that call F to use NF. +CallGraphNode *SRETPromotion::updateCallSites(Function *F, Function *NF) { + CallGraph &CG = getAnalysis(); + SmallVector Args; + + // Attributes - Keep track of the parameter attributes for the arguments. + SmallVector ArgAttrsVec; + + // Get a new callgraph node for NF. + CallGraphNode *NF_CGN = CG.getOrInsertFunction(NF); + + while (!F->use_empty()) { + CallSite CS = CallSite::get(*F->use_begin()); + Instruction *Call = CS.getInstruction(); + + const AttrListPtr &PAL = F->getAttributes(); + // Add any return attributes. + if (Attributes attrs = PAL.getRetAttributes()) + ArgAttrsVec.push_back(AttributeWithIndex::get(0, attrs)); + + // Copy arguments, however skip first one. + CallSite::arg_iterator AI = CS.arg_begin(), AE = CS.arg_end(); + Value *FirstCArg = *AI; + ++AI; + // 0th parameter attribute is reserved for return type. + // 1th parameter attribute is for first 1st sret argument. + unsigned ParamIndex = 2; + while (AI != AE) { + Args.push_back(*AI); + if (Attributes Attrs = PAL.getParamAttributes(ParamIndex)) + ArgAttrsVec.push_back(AttributeWithIndex::get(ParamIndex - 1, Attrs)); + ++ParamIndex; + ++AI; + } + + // Add any function attributes. + if (Attributes attrs = PAL.getFnAttributes()) + ArgAttrsVec.push_back(AttributeWithIndex::get(~0, attrs)); + + AttrListPtr NewPAL = AttrListPtr::get(ArgAttrsVec.begin(), ArgAttrsVec.end()); + + // Build new call instruction. + Instruction *New; + if (InvokeInst *II = dyn_cast(Call)) { + New = InvokeInst::Create(NF, II->getNormalDest(), II->getUnwindDest(), + Args.begin(), Args.end(), "", Call); + cast(New)->setCallingConv(CS.getCallingConv()); + cast(New)->setAttributes(NewPAL); + } else { + New = CallInst::Create(NF, Args.begin(), Args.end(), "", Call); + cast(New)->setCallingConv(CS.getCallingConv()); + cast(New)->setAttributes(NewPAL); + if (cast(Call)->isTailCall()) + cast(New)->setTailCall(); + } + Args.clear(); + ArgAttrsVec.clear(); + New->takeName(Call); + + // Update the callgraph to know that the callsite has been transformed. + CallGraphNode *CalleeNode = CG[Call->getParent()->getParent()]; + CalleeNode->removeCallEdgeFor(Call); + CalleeNode->addCalledFunction(New, NF_CGN); + + // Update all users of sret parameter to extract value using extractvalue. + for (Value::use_iterator UI = FirstCArg->use_begin(), + UE = FirstCArg->use_end(); UI != UE; ) { + User *U2 = *UI++; + CallInst *C2 = dyn_cast(U2); + if (C2 && (C2 == Call)) + continue; + + GetElementPtrInst *UGEP = cast(U2); + ConstantInt *Idx = cast(UGEP->getOperand(2)); + Value *GR = ExtractValueInst::Create(New, Idx->getZExtValue(), + "evi", UGEP); + while(!UGEP->use_empty()) { + // isSafeToUpdateAllCallers has checked that all GEP uses are + // LoadInsts + LoadInst *L = cast(*UGEP->use_begin()); + L->replaceAllUsesWith(GR); + L->eraseFromParent(); + } + UGEP->eraseFromParent(); + continue; + } + Call->eraseFromParent(); + } + + return NF_CGN; +} + +/// nestedStructType - Return true if STy includes any +/// other aggregate types +bool SRETPromotion::nestedStructType(const StructType *STy) { + unsigned Num = STy->getNumElements(); + for (unsigned i = 0; i < Num; i++) { + const Type *Ty = STy->getElementType(i); + if (!Ty->isSingleValueType() && Ty != Type::getVoidTy(STy->getContext())) + return true; + } + return false; +} diff --git a/libclamav/c++/llvm/lib/Transforms/Instrumentation/BlockProfiling.cpp b/libclamav/c++/llvm/lib/Transforms/Instrumentation/BlockProfiling.cpp new file mode 100644 index 000000000..211a6d628 --- /dev/null +++ b/libclamav/c++/llvm/lib/Transforms/Instrumentation/BlockProfiling.cpp @@ -0,0 +1,128 @@ +//===- BlockProfiling.cpp - Insert counters for block profiling -----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This pass instruments the specified program with counters for basic block or +// function profiling. This is the most basic form of profiling, which can tell +// which blocks are hot, but cannot reliably detect hot paths through the CFG. +// Block profiling counts the number of times each basic block executes, and +// function profiling counts the number of times each function is called. +// +// Note that this implementation is very naive. Control equivalent regions of +// the CFG should not require duplicate counters, but we do put duplicate +// counters in. +// +//===----------------------------------------------------------------------===// + +#include "llvm/DerivedTypes.h" +#include "llvm/Module.h" +#include "llvm/Pass.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Transforms/Instrumentation.h" +#include "RSProfiling.h" +#include "ProfilingUtils.h" +using namespace llvm; + +namespace { + class FunctionProfiler : public RSProfilers_std { + public: + static char ID; + bool runOnModule(Module &M); + }; +} + +char FunctionProfiler::ID = 0; + +static RegisterPass +X("insert-function-profiling", + "Insert instrumentation for function profiling"); +static RegisterAnalysisGroup XG(X); + +ModulePass *llvm::createFunctionProfilerPass() { + return new FunctionProfiler(); +} + +bool FunctionProfiler::runOnModule(Module &M) { + Function *Main = M.getFunction("main"); + if (Main == 0) { + errs() << "WARNING: cannot insert function profiling into a module" + << " with no main function!\n"; + return false; // No main, no instrumentation! + } + + unsigned NumFunctions = 0; + for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) + if (!I->isDeclaration()) + ++NumFunctions; + + const Type *ATy = ArrayType::get(Type::getInt32Ty(M.getContext()), + NumFunctions); + GlobalVariable *Counters = + new GlobalVariable(M, ATy, false, GlobalValue::InternalLinkage, + Constant::getNullValue(ATy), "FuncProfCounters"); + + // Instrument all of the functions... + unsigned i = 0; + for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) + if (!I->isDeclaration()) + // Insert counter at the start of the function + IncrementCounterInBlock(&I->getEntryBlock(), i++, Counters); + + // Add the initialization call to main. + InsertProfilingInitCall(Main, "llvm_start_func_profiling", Counters); + return true; +} + + +namespace { + class BlockProfiler : public RSProfilers_std { + bool runOnModule(Module &M); + public: + static char ID; + }; +} + +char BlockProfiler::ID = 0; +static RegisterPass +Y("insert-block-profiling", "Insert instrumentation for block profiling"); +static RegisterAnalysisGroup YG(Y); + +ModulePass *llvm::createBlockProfilerPass() { return new BlockProfiler(); } + +bool BlockProfiler::runOnModule(Module &M) { + Function *Main = M.getFunction("main"); + if (Main == 0) { + errs() << "WARNING: cannot insert block profiling into a module" + << " with no main function!\n"; + return false; // No main, no instrumentation! + } + + unsigned NumBlocks = 0; + for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) + if (!I->isDeclaration()) + NumBlocks += I->size(); + + const Type *ATy = ArrayType::get(Type::getInt32Ty(M.getContext()), NumBlocks); + GlobalVariable *Counters = + new GlobalVariable(M, ATy, false, GlobalValue::InternalLinkage, + Constant::getNullValue(ATy), "BlockProfCounters"); + + // Instrument all of the blocks... + unsigned i = 0; + for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) { + if (I->isDeclaration()) continue; + for (Function::iterator BB = I->begin(), E = I->end(); BB != E; ++BB) + // Insert counter at the start of the block + IncrementCounterInBlock(BB, i++, Counters); + } + + // Add the initialization call to main. + InsertProfilingInitCall(Main, "llvm_start_block_profiling", Counters); + return true; +} + diff --git a/libclamav/c++/llvm/lib/Transforms/Instrumentation/CMakeLists.txt b/libclamav/c++/llvm/lib/Transforms/Instrumentation/CMakeLists.txt new file mode 100644 index 000000000..494928e43 --- /dev/null +++ b/libclamav/c++/llvm/lib/Transforms/Instrumentation/CMakeLists.txt @@ -0,0 +1,7 @@ +add_llvm_library(LLVMInstrumentation + BlockProfiling.cpp + EdgeProfiling.cpp + OptimalEdgeProfiling.cpp + ProfilingUtils.cpp + RSProfiling.cpp + ) diff --git a/libclamav/c++/llvm/lib/Transforms/Instrumentation/EdgeProfiling.cpp b/libclamav/c++/llvm/lib/Transforms/Instrumentation/EdgeProfiling.cpp new file mode 100644 index 000000000..9ae378670 --- /dev/null +++ b/libclamav/c++/llvm/lib/Transforms/Instrumentation/EdgeProfiling.cpp @@ -0,0 +1,114 @@ +//===- EdgeProfiling.cpp - Insert counters for edge profiling -------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This pass instruments the specified program with counters for edge profiling. +// Edge profiling can give a reasonable approximation of the hot paths through a +// program, and is used for a wide variety of program transformations. +// +// Note that this implementation is very naive. We insert a counter for *every* +// edge in the program, instead of using control flow information to prune the +// number of counters inserted. +// +//===----------------------------------------------------------------------===// +#define DEBUG_TYPE "insert-edge-profiling" +#include "ProfilingUtils.h" +#include "llvm/Module.h" +#include "llvm/Pass.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Transforms/Utils/BasicBlockUtils.h" +#include "llvm/Transforms/Instrumentation.h" +#include "llvm/ADT/Statistic.h" +#include +using namespace llvm; + +STATISTIC(NumEdgesInserted, "The # of edges inserted."); + +namespace { + class EdgeProfiler : public ModulePass { + bool runOnModule(Module &M); + public: + static char ID; // Pass identification, replacement for typeid + EdgeProfiler() : ModulePass(&ID) {} + + virtual const char *getPassName() const { + return "Edge Profiler"; + } + }; +} + +char EdgeProfiler::ID = 0; +static RegisterPass +X("insert-edge-profiling", "Insert instrumentation for edge profiling"); + +ModulePass *llvm::createEdgeProfilerPass() { return new EdgeProfiler(); } + +bool EdgeProfiler::runOnModule(Module &M) { + Function *Main = M.getFunction("main"); + if (Main == 0) { + errs() << "WARNING: cannot insert edge profiling into a module" + << " with no main function!\n"; + return false; // No main, no instrumentation! + } + + std::set BlocksToInstrument; + unsigned NumEdges = 0; + for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F) { + if (F->isDeclaration()) continue; + // Reserve space for (0,entry) edge. + ++NumEdges; + for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) { + // Keep track of which blocks need to be instrumented. We don't want to + // instrument blocks that are added as the result of breaking critical + // edges! + BlocksToInstrument.insert(BB); + NumEdges += BB->getTerminator()->getNumSuccessors(); + } + } + + const Type *ATy = ArrayType::get(Type::getInt32Ty(M.getContext()), NumEdges); + GlobalVariable *Counters = + new GlobalVariable(M, ATy, false, GlobalValue::InternalLinkage, + Constant::getNullValue(ATy), "EdgeProfCounters"); + NumEdgesInserted = NumEdges; + + // Instrument all of the edges... + unsigned i = 0; + for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F) { + if (F->isDeclaration()) continue; + // Create counter for (0,entry) edge. + IncrementCounterInBlock(&F->getEntryBlock(), i++, Counters); + for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) + if (BlocksToInstrument.count(BB)) { // Don't instrument inserted blocks + // Okay, we have to add a counter of each outgoing edge. If the + // outgoing edge is not critical don't split it, just insert the counter + // in the source or destination of the edge. + TerminatorInst *TI = BB->getTerminator(); + for (unsigned s = 0, e = TI->getNumSuccessors(); s != e; ++s) { + // If the edge is critical, split it. + SplitCriticalEdge(TI, s, this); + + // Okay, we are guaranteed that the edge is no longer critical. If we + // only have a single successor, insert the counter in this block, + // otherwise insert it in the successor block. + if (TI->getNumSuccessors() == 1) { + // Insert counter at the start of the block + IncrementCounterInBlock(BB, i++, Counters); + } else { + // Insert counter at the start of the block + IncrementCounterInBlock(TI->getSuccessor(s), i++, Counters); + } + } + } + } + + // Add the initialization call to main. + InsertProfilingInitCall(Main, "llvm_start_edge_profiling", Counters); + return true; +} + diff --git a/libclamav/c++/llvm/lib/Transforms/Instrumentation/Makefile b/libclamav/c++/llvm/lib/Transforms/Instrumentation/Makefile new file mode 100644 index 000000000..6cbc7a9cd --- /dev/null +++ b/libclamav/c++/llvm/lib/Transforms/Instrumentation/Makefile @@ -0,0 +1,15 @@ +##===- lib/Transforms/Instrumentation/Makefile -------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LEVEL = ../../.. +LIBRARYNAME = LLVMInstrumentation +BUILD_ARCHIVE = 1 + +include $(LEVEL)/Makefile.common + diff --git a/libclamav/c++/llvm/lib/Transforms/Instrumentation/MaximumSpanningTree.h b/libclamav/c++/llvm/lib/Transforms/Instrumentation/MaximumSpanningTree.h new file mode 100644 index 000000000..2951dbcea --- /dev/null +++ b/libclamav/c++/llvm/lib/Transforms/Instrumentation/MaximumSpanningTree.h @@ -0,0 +1,95 @@ +//===- llvm/Analysis/MaximumSpanningTree.h - Interface ----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This module privides means for calculating a maximum spanning tree for a +// given set of weighted edges. The type parameter T is the type of a node. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_MAXIMUMSPANNINGTREE_H +#define LLVM_ANALYSIS_MAXIMUMSPANNINGTREE_H + +#include "llvm/ADT/EquivalenceClasses.h" +#include +#include + +namespace llvm { + + /// MaximumSpanningTree - A MST implementation. + /// The type parameter T determines the type of the nodes of the graph. + template + class MaximumSpanningTree { + + // A comparing class for comparing weighted edges. + template + struct EdgeWeightCompare { + bool operator()(typename MaximumSpanningTree::EdgeWeight X, + typename MaximumSpanningTree::EdgeWeight Y) const { + if (X.second > Y.second) return true; + if (X.second < Y.second) return false; + return false; + } + }; + + public: + typedef std::pair Edge; + typedef std::pair EdgeWeight; + typedef std::vector EdgeWeights; + protected: + typedef std::vector MaxSpanTree; + + MaxSpanTree MST; + + public: + static char ID; // Class identification, replacement for typeinfo + + /// MaximumSpanningTree() - Takes a vector of weighted edges and returns a + /// spanning tree. + MaximumSpanningTree(EdgeWeights &EdgeVector) { + + std::stable_sort(EdgeVector.begin(), EdgeVector.end(), EdgeWeightCompare()); + + // Create spanning tree, Forest contains a special data structure + // that makes checking if two nodes are already in a common (sub-)tree + // fast and cheap. + EquivalenceClasses Forest; + for (typename EdgeWeights::iterator EWi = EdgeVector.begin(), + EWe = EdgeVector.end(); EWi != EWe; ++EWi) { + Edge e = (*EWi).first; + + Forest.insert(e.first); + Forest.insert(e.second); + } + + // Iterate over the sorted edges, biggest first. + for (typename EdgeWeights::iterator EWi = EdgeVector.begin(), + EWe = EdgeVector.end(); EWi != EWe; ++EWi) { + Edge e = (*EWi).first; + + if (Forest.findLeader(e.first) != Forest.findLeader(e.second)) { + Forest.unionSets(e.first, e.second); + // So we know now that the edge is not already in a subtree, so we push + // the edge to the MST. + MST.push_back(e); + } + } + } + + typename MaxSpanTree::iterator begin() { + return MST.begin(); + } + + typename MaxSpanTree::iterator end() { + return MST.end(); + } + }; + +} // End llvm namespace + +#endif diff --git a/libclamav/c++/llvm/lib/Transforms/Instrumentation/OptimalEdgeProfiling.cpp b/libclamav/c++/llvm/lib/Transforms/Instrumentation/OptimalEdgeProfiling.cpp new file mode 100644 index 000000000..0a46fe5e8 --- /dev/null +++ b/libclamav/c++/llvm/lib/Transforms/Instrumentation/OptimalEdgeProfiling.cpp @@ -0,0 +1,218 @@ +//===- OptimalEdgeProfiling.cpp - Insert counters for opt. edge profiling -===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This pass instruments the specified program with counters for edge profiling. +// Edge profiling can give a reasonable approximation of the hot paths through a +// program, and is used for a wide variety of program transformations. +// +//===----------------------------------------------------------------------===// +#define DEBUG_TYPE "insert-optimal-edge-profiling" +#include "ProfilingUtils.h" +#include "llvm/Module.h" +#include "llvm/Pass.h" +#include "llvm/Analysis/Passes.h" +#include "llvm/Analysis/ProfileInfo.h" +#include "llvm/Analysis/ProfileInfoLoader.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/Debug.h" +#include "llvm/Transforms/Utils/BasicBlockUtils.h" +#include "llvm/Transforms/Instrumentation.h" +#include "llvm/ADT/DenseSet.h" +#include "llvm/ADT/Statistic.h" +#include "MaximumSpanningTree.h" +#include +using namespace llvm; + +STATISTIC(NumEdgesInserted, "The # of edges inserted."); + +namespace { + class OptimalEdgeProfiler : public ModulePass { + bool runOnModule(Module &M); + public: + static char ID; // Pass identification, replacement for typeid + OptimalEdgeProfiler() : ModulePass(&ID) {} + + void getAnalysisUsage(AnalysisUsage &AU) const { + AU.addRequiredID(ProfileEstimatorPassID); + AU.addRequired(); + } + + virtual const char *getPassName() const { + return "Optimal Edge Profiler"; + } + }; +} + +char OptimalEdgeProfiler::ID = 0; +static RegisterPass +X("insert-optimal-edge-profiling", + "Insert optimal instrumentation for edge profiling"); + +ModulePass *llvm::createOptimalEdgeProfilerPass() { + return new OptimalEdgeProfiler(); +} + +inline static void printEdgeCounter(ProfileInfo::Edge e, + BasicBlock* b, + unsigned i) { + DEBUG(errs() << "--Edge Counter for " << (e) << " in " \ + << ((b)?(b)->getNameStr():"0") << " (# " << (i) << ")\n"); +} + +bool OptimalEdgeProfiler::runOnModule(Module &M) { + Function *Main = M.getFunction("main"); + if (Main == 0) { + errs() << "WARNING: cannot insert edge profiling into a module" + << " with no main function!\n"; + return false; // No main, no instrumentation! + } + + // NumEdges counts all the edges that may be instrumented. Later on its + // decided which edges to actually instrument, to achieve optimal profiling. + // For the entry block a virtual edge (0,entry) is reserved, for each block + // with no successors an edge (BB,0) is reserved. These edges are necessary + // to calculate a truly optimal maximum spanning tree and thus an optimal + // instrumentation. + unsigned NumEdges = 0; + + for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F) { + if (F->isDeclaration()) continue; + // Reserve space for (0,entry) edge. + ++NumEdges; + for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) { + // Keep track of which blocks need to be instrumented. We don't want to + // instrument blocks that are added as the result of breaking critical + // edges! + if (BB->getTerminator()->getNumSuccessors() == 0) { + // Reserve space for (BB,0) edge. + ++NumEdges; + } else { + NumEdges += BB->getTerminator()->getNumSuccessors(); + } + } + } + + // In the profiling output a counter for each edge is reserved, but only few + // are used. This is done to be able to read back in the profile without + // calulating the maximum spanning tree again, instead each edge counter that + // is not used is initialised with -1 to signal that this edge counter has to + // be calculated from other edge counters on reading the profile info back + // in. + + const Type *Int32 = Type::getInt32Ty(M.getContext()); + const ArrayType *ATy = ArrayType::get(Int32, NumEdges); + GlobalVariable *Counters = + new GlobalVariable(M, ATy, false, GlobalValue::InternalLinkage, + Constant::getNullValue(ATy), "OptEdgeProfCounters"); + NumEdgesInserted = 0; + + std::vector Initializer(NumEdges); + Constant* Zero = ConstantInt::get(Int32, 0); + Constant* Uncounted = ConstantInt::get(Int32, ProfileInfoLoader::Uncounted); + + // Instrument all of the edges not in MST... + unsigned i = 0; + for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F) { + if (F->isDeclaration()) continue; + DEBUG(errs()<<"Working on "<getNameStr()<<"\n"); + + // Calculate a Maximum Spanning Tree with the edge weights determined by + // ProfileEstimator. ProfileEstimator also assign weights to the virtual + // edges (0,entry) and (BB,0) (for blocks with no successors) and this + // edges also participate in the maximum spanning tree calculation. + // The third parameter of MaximumSpanningTree() has the effect that not the + // actual MST is returned but the edges _not_ in the MST. + + ProfileInfo::EdgeWeights ECs = + getAnalysisID(ProfileEstimatorPassID, *F).getEdgeWeights(F); + std::vector EdgeVector(ECs.begin(), ECs.end()); + MaximumSpanningTree MST (EdgeVector); + std::stable_sort(MST.begin(),MST.end()); + + // Check if (0,entry) not in the MST. If not, instrument edge + // (IncrementCounterInBlock()) and set the counter initially to zero, if + // the edge is in the MST the counter is initialised to -1. + + BasicBlock *entry = &(F->getEntryBlock()); + ProfileInfo::Edge edge = ProfileInfo::getEdge(0,entry); + if (!std::binary_search(MST.begin(), MST.end(), edge)) { + printEdgeCounter(edge,entry,i); + IncrementCounterInBlock(entry, i, Counters); NumEdgesInserted++; + Initializer[i++] = (Zero); + } else{ + Initializer[i++] = (Uncounted); + } + + // InsertedBlocks contains all blocks that were inserted for splitting an + // edge, this blocks do not have to be instrumented. + DenseSet InsertedBlocks; + for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) { + // Check if block was not inserted and thus does not have to be + // instrumented. + if (InsertedBlocks.count(BB)) continue; + + // Okay, we have to add a counter of each outgoing edge not in MST. If + // the outgoing edge is not critical don't split it, just insert the + // counter in the source or destination of the edge. Also, if the block + // has no successors, the virtual edge (BB,0) is processed. + TerminatorInst *TI = BB->getTerminator(); + if (TI->getNumSuccessors() == 0) { + ProfileInfo::Edge edge = ProfileInfo::getEdge(BB,0); + if (!std::binary_search(MST.begin(), MST.end(), edge)) { + printEdgeCounter(edge,BB,i); + IncrementCounterInBlock(BB, i, Counters); NumEdgesInserted++; + Initializer[i++] = (Zero); + } else{ + Initializer[i++] = (Uncounted); + } + } + for (unsigned s = 0, e = TI->getNumSuccessors(); s != e; ++s) { + BasicBlock *Succ = TI->getSuccessor(s); + ProfileInfo::Edge edge = ProfileInfo::getEdge(BB,Succ); + if (!std::binary_search(MST.begin(), MST.end(), edge)) { + + // If the edge is critical, split it. + bool wasInserted = SplitCriticalEdge(TI, s, this); + Succ = TI->getSuccessor(s); + if (wasInserted) + InsertedBlocks.insert(Succ); + + // Okay, we are guaranteed that the edge is no longer critical. If + // we only have a single successor, insert the counter in this block, + // otherwise insert it in the successor block. + if (TI->getNumSuccessors() == 1) { + // Insert counter at the start of the block + printEdgeCounter(edge,BB,i); + IncrementCounterInBlock(BB, i, Counters); NumEdgesInserted++; + } else { + // Insert counter at the start of the block + printEdgeCounter(edge,Succ,i); + IncrementCounterInBlock(Succ, i, Counters); NumEdgesInserted++; + } + Initializer[i++] = (Zero); + } else { + Initializer[i++] = (Uncounted); + } + } + } + } + + // Check if the number of edges counted at first was the number of edges we + // considered for instrumentation. + assert(i==NumEdges && "the number of edges in counting array is wrong"); + + // Assing the now completely defined initialiser to the array. + Constant *init = ConstantArray::get(ATy, Initializer); + Counters->setInitializer(init); + + // Add the initialization call to main. + InsertProfilingInitCall(Main, "llvm_start_opt_edge_profiling", Counters); + return true; +} + diff --git a/libclamav/c++/llvm/lib/Transforms/Instrumentation/ProfilingUtils.cpp b/libclamav/c++/llvm/lib/Transforms/Instrumentation/ProfilingUtils.cpp new file mode 100644 index 000000000..1679bea08 --- /dev/null +++ b/libclamav/c++/llvm/lib/Transforms/Instrumentation/ProfilingUtils.cpp @@ -0,0 +1,131 @@ +//===- ProfilingUtils.cpp - Helper functions shared by profilers ----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements a few helper functions which are used by profile +// instrumentation code to instrument the code. This allows the profiler pass +// to worry about *what* to insert, and these functions take care of *how* to do +// it. +// +//===----------------------------------------------------------------------===// + +#include "ProfilingUtils.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Instructions.h" +#include "llvm/LLVMContext.h" +#include "llvm/Module.h" + +void llvm::InsertProfilingInitCall(Function *MainFn, const char *FnName, + GlobalValue *Array) { + LLVMContext &Context = MainFn->getContext(); + const Type *ArgVTy = + PointerType::getUnqual(Type::getInt8PtrTy(Context)); + const PointerType *UIntPtr = + Type::getInt32PtrTy(Context); + Module &M = *MainFn->getParent(); + Constant *InitFn = M.getOrInsertFunction(FnName, Type::getInt32Ty(Context), + Type::getInt32Ty(Context), + ArgVTy, UIntPtr, + Type::getInt32Ty(Context), + (Type *)0); + + // This could force argc and argv into programs that wouldn't otherwise have + // them, but instead we just pass null values in. + std::vector Args(4); + Args[0] = Constant::getNullValue(Type::getInt32Ty(Context)); + Args[1] = Constant::getNullValue(ArgVTy); + + // Skip over any allocas in the entry block. + BasicBlock *Entry = MainFn->begin(); + BasicBlock::iterator InsertPos = Entry->begin(); + while (isa(InsertPos)) ++InsertPos; + + std::vector GEPIndices(2, + Constant::getNullValue(Type::getInt32Ty(Context))); + unsigned NumElements = 0; + if (Array) { + Args[2] = ConstantExpr::getGetElementPtr(Array, &GEPIndices[0], + GEPIndices.size()); + NumElements = + cast(Array->getType()->getElementType())->getNumElements(); + } else { + // If this profiling instrumentation doesn't have a constant array, just + // pass null. + Args[2] = ConstantPointerNull::get(UIntPtr); + } + Args[3] = ConstantInt::get(Type::getInt32Ty(Context), NumElements); + + Instruction *InitCall = CallInst::Create(InitFn, Args.begin(), Args.end(), + "newargc", InsertPos); + + // If argc or argv are not available in main, just pass null values in. + Function::arg_iterator AI; + switch (MainFn->arg_size()) { + default: + case 2: + AI = MainFn->arg_begin(); ++AI; + if (AI->getType() != ArgVTy) { + Instruction::CastOps opcode = CastInst::getCastOpcode(AI, false, ArgVTy, + false); + InitCall->setOperand(2, + CastInst::Create(opcode, AI, ArgVTy, "argv.cast", InitCall)); + } else { + InitCall->setOperand(2, AI); + } + /* FALL THROUGH */ + + case 1: + AI = MainFn->arg_begin(); + // If the program looked at argc, have it look at the return value of the + // init call instead. + if (AI->getType() != Type::getInt32Ty(Context)) { + Instruction::CastOps opcode; + if (!AI->use_empty()) { + opcode = CastInst::getCastOpcode(InitCall, true, AI->getType(), true); + AI->replaceAllUsesWith( + CastInst::Create(opcode, InitCall, AI->getType(), "", InsertPos)); + } + opcode = CastInst::getCastOpcode(AI, true, + Type::getInt32Ty(Context), true); + InitCall->setOperand(1, + CastInst::Create(opcode, AI, Type::getInt32Ty(Context), + "argc.cast", InitCall)); + } else { + AI->replaceAllUsesWith(InitCall); + InitCall->setOperand(1, AI); + } + + case 0: break; + } +} + +void llvm::IncrementCounterInBlock(BasicBlock *BB, unsigned CounterNum, + GlobalValue *CounterArray) { + // Insert the increment after any alloca or PHI instructions... + BasicBlock::iterator InsertPos = BB->getFirstNonPHI(); + while (isa(InsertPos)) + ++InsertPos; + + LLVMContext &Context = BB->getContext(); + + // Create the getelementptr constant expression + std::vector Indices(2); + Indices[0] = Constant::getNullValue(Type::getInt32Ty(Context)); + Indices[1] = ConstantInt::get(Type::getInt32Ty(Context), CounterNum); + Constant *ElementPtr = + ConstantExpr::getGetElementPtr(CounterArray, &Indices[0], + Indices.size()); + + // Load, increment and store the value back. + Value *OldVal = new LoadInst(ElementPtr, "OldFuncCounter", InsertPos); + Value *NewVal = BinaryOperator::Create(Instruction::Add, OldVal, + ConstantInt::get(Type::getInt32Ty(Context), 1), + "NewFuncCounter", InsertPos); + new StoreInst(NewVal, ElementPtr, InsertPos); +} diff --git a/libclamav/c++/llvm/lib/Transforms/Instrumentation/ProfilingUtils.h b/libclamav/c++/llvm/lib/Transforms/Instrumentation/ProfilingUtils.h new file mode 100644 index 000000000..94efffec8 --- /dev/null +++ b/libclamav/c++/llvm/lib/Transforms/Instrumentation/ProfilingUtils.h @@ -0,0 +1,31 @@ +//===- ProfilingUtils.h - Helper functions shared by profilers --*- 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 a few helper functions which are used by profile +// instrumentation code to instrument the code. This allows the profiler pass +// to worry about *what* to insert, and these functions take care of *how* to do +// it. +// +//===----------------------------------------------------------------------===// + +#ifndef PROFILINGUTILS_H +#define PROFILINGUTILS_H + +namespace llvm { + class Function; + class GlobalValue; + class BasicBlock; + + void InsertProfilingInitCall(Function *MainFn, const char *FnName, + GlobalValue *Arr = 0); + void IncrementCounterInBlock(BasicBlock *BB, unsigned CounterNum, + GlobalValue *CounterArray); +} + +#endif diff --git a/libclamav/c++/llvm/lib/Transforms/Instrumentation/RSProfiling.cpp b/libclamav/c++/llvm/lib/Transforms/Instrumentation/RSProfiling.cpp new file mode 100644 index 000000000..c08efc1e4 --- /dev/null +++ b/libclamav/c++/llvm/lib/Transforms/Instrumentation/RSProfiling.cpp @@ -0,0 +1,662 @@ +//===- RSProfiling.cpp - Various profiling using random sampling ----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// These passes implement a random sampling based profiling. Different methods +// of choosing when to sample are supported, as well as different types of +// profiling. This is done as two passes. The first is a sequence of profiling +// passes which insert profiling into the program, and remember what they +// inserted. +// +// The second stage duplicates all instructions in a function, ignoring the +// profiling code, then connects the two versions togeather at the entry and at +// backedges. At each connection point a choice is made as to whether to jump +// to the profiled code (take a sample) or execute the unprofiled code. +// +// It is highly recommended that after this pass one runs mem2reg and adce +// (instcombine load-vn gdce dse also are good to run afterwards) +// +// This design is intended to make the profiling passes independent of the RS +// framework, but any profiling pass that implements the RSProfiling interface +// is compatible with the rs framework (and thus can be sampled) +// +// TODO: obviously the block and function profiling are almost identical to the +// existing ones, so they can be unified (esp since these passes are valid +// without the rs framework). +// TODO: Fix choice code so that frequency is not hard coded +// +//===----------------------------------------------------------------------===// + +#include "llvm/Pass.h" +#include "llvm/LLVMContext.h" +#include "llvm/Module.h" +#include "llvm/Instructions.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Intrinsics.h" +#include "llvm/Transforms/Scalar.h" +#include "llvm/Transforms/Utils/BasicBlockUtils.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Transforms/Instrumentation.h" +#include "RSProfiling.h" +#include +#include +#include +using namespace llvm; + +namespace { + enum RandomMeth { + GBV, GBVO, HOSTCC + }; +} + +static cl::opt RandomMethod("profile-randomness", + cl::desc("How to randomly choose to profile:"), + cl::values( + clEnumValN(GBV, "global", "global counter"), + clEnumValN(GBVO, "ra_global", + "register allocated global counter"), + clEnumValN(HOSTCC, "rdcc", "cycle counter"), + clEnumValEnd)); + +namespace { + /// NullProfilerRS - The basic profiler that does nothing. It is the default + /// profiler and thus terminates RSProfiler chains. It is useful for + /// measuring framework overhead + class NullProfilerRS : public RSProfilers { + public: + static char ID; // Pass identification, replacement for typeid + bool isProfiling(Value* v) { + return false; + } + bool runOnModule(Module &M) { + return false; + } + void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + } + }; +} + +static RegisterAnalysisGroup A("Profiling passes"); +static RegisterPass NP("insert-null-profiling-rs", + "Measure profiling framework overhead"); +static RegisterAnalysisGroup NPT(NP); + +namespace { + /// Chooser - Something that chooses when to make a sample of the profiled code + class Chooser { + public: + /// ProcessChoicePoint - is called for each basic block inserted to choose + /// between normal and sample code + virtual void ProcessChoicePoint(BasicBlock*) = 0; + /// PrepFunction - is called once per function before other work is done. + /// This gives the opertunity to insert new allocas and such. + virtual void PrepFunction(Function*) = 0; + virtual ~Chooser() {} + }; + + //Things that implement sampling policies + //A global value that is read-mod-stored to choose when to sample. + //A sample is taken when the global counter hits 0 + class GlobalRandomCounter : public Chooser { + GlobalVariable* Counter; + Value* ResetValue; + const IntegerType* T; + public: + GlobalRandomCounter(Module& M, const IntegerType* t, uint64_t resetval); + virtual ~GlobalRandomCounter(); + virtual void PrepFunction(Function* F); + virtual void ProcessChoicePoint(BasicBlock* bb); + }; + + //Same is GRC, but allow register allocation of the global counter + class GlobalRandomCounterOpt : public Chooser { + GlobalVariable* Counter; + Value* ResetValue; + AllocaInst* AI; + const IntegerType* T; + public: + GlobalRandomCounterOpt(Module& M, const IntegerType* t, uint64_t resetval); + virtual ~GlobalRandomCounterOpt(); + virtual void PrepFunction(Function* F); + virtual void ProcessChoicePoint(BasicBlock* bb); + }; + + //Use the cycle counter intrinsic as a source of pseudo randomness when + //deciding when to sample. + class CycleCounter : public Chooser { + uint64_t rm; + Constant *F; + public: + CycleCounter(Module& m, uint64_t resetmask); + virtual ~CycleCounter(); + virtual void PrepFunction(Function* F); + virtual void ProcessChoicePoint(BasicBlock* bb); + }; + + /// ProfilerRS - Insert the random sampling framework + struct ProfilerRS : public FunctionPass { + static char ID; // Pass identification, replacement for typeid + ProfilerRS() : FunctionPass(&ID) {} + + std::map TransCache; + std::set ChoicePoints; + Chooser* c; + + //Translate and duplicate values for the new profile free version of stuff + Value* Translate(Value* v); + //Duplicate an entire function (with out profiling) + void Duplicate(Function& F, RSProfilers& LI); + //Called once for each backedge, handle the insertion of choice points and + //the interconection of the two versions of the code + void ProcessBackEdge(BasicBlock* src, BasicBlock* dst, Function& F); + bool runOnFunction(Function& F); + bool doInitialization(Module &M); + virtual void getAnalysisUsage(AnalysisUsage &AU) const; + }; +} + +static RegisterPass +X("insert-rs-profiling-framework", + "Insert random sampling instrumentation framework"); + +char RSProfilers::ID = 0; +char NullProfilerRS::ID = 0; +char ProfilerRS::ID = 0; + +//Local utilities +static void ReplacePhiPred(BasicBlock* btarget, + BasicBlock* bold, BasicBlock* bnew); + +static void CollapsePhi(BasicBlock* btarget, BasicBlock* bsrc); + +template +static void recBackEdge(BasicBlock* bb, T& BackEdges, + std::map& color, + std::map& depth, + std::map& finish, + int& time); + +//find the back edges and where they go to +template +static void getBackEdges(Function& F, T& BackEdges); + + +/////////////////////////////////////// +// Methods of choosing when to profile +/////////////////////////////////////// + +GlobalRandomCounter::GlobalRandomCounter(Module& M, const IntegerType* t, + uint64_t resetval) : T(t) { + ConstantInt* Init = ConstantInt::get(T, resetval); + ResetValue = Init; + Counter = new GlobalVariable(M, T, false, GlobalValue::InternalLinkage, + Init, "RandomSteeringCounter"); +} + +GlobalRandomCounter::~GlobalRandomCounter() {} + +void GlobalRandomCounter::PrepFunction(Function* F) {} + +void GlobalRandomCounter::ProcessChoicePoint(BasicBlock* bb) { + BranchInst* t = cast(bb->getTerminator()); + + //decrement counter + LoadInst* l = new LoadInst(Counter, "counter", t); + + ICmpInst* s = new ICmpInst(t, ICmpInst::ICMP_EQ, l, + ConstantInt::get(T, 0), + "countercc"); + + Value* nv = BinaryOperator::CreateSub(l, ConstantInt::get(T, 1), + "counternew", t); + new StoreInst(nv, Counter, t); + t->setCondition(s); + + //reset counter + BasicBlock* oldnext = t->getSuccessor(0); + BasicBlock* resetblock = BasicBlock::Create(bb->getContext(), + "reset", oldnext->getParent(), + oldnext); + TerminatorInst* t2 = BranchInst::Create(oldnext, resetblock); + t->setSuccessor(0, resetblock); + new StoreInst(ResetValue, Counter, t2); + ReplacePhiPred(oldnext, bb, resetblock); +} + +GlobalRandomCounterOpt::GlobalRandomCounterOpt(Module& M, const IntegerType* t, + uint64_t resetval) + : AI(0), T(t) { + ConstantInt* Init = ConstantInt::get(T, resetval); + ResetValue = Init; + Counter = new GlobalVariable(M, T, false, GlobalValue::InternalLinkage, + Init, "RandomSteeringCounter"); +} + +GlobalRandomCounterOpt::~GlobalRandomCounterOpt() {} + +void GlobalRandomCounterOpt::PrepFunction(Function* F) { + //make a local temporary to cache the global + BasicBlock& bb = F->getEntryBlock(); + BasicBlock::iterator InsertPt = bb.begin(); + AI = new AllocaInst(T, 0, "localcounter", InsertPt); + LoadInst* l = new LoadInst(Counter, "counterload", InsertPt); + new StoreInst(l, AI, InsertPt); + + //modify all functions and return values to restore the local variable to/from + //the global variable + for(Function::iterator fib = F->begin(), fie = F->end(); + fib != fie; ++fib) + for(BasicBlock::iterator bib = fib->begin(), bie = fib->end(); + bib != bie; ++bib) + if (isa(bib)) { + LoadInst* l = new LoadInst(AI, "counter", bib); + new StoreInst(l, Counter, bib); + l = new LoadInst(Counter, "counter", ++bib); + new StoreInst(l, AI, bib--); + } else if (isa(bib)) { + LoadInst* l = new LoadInst(AI, "counter", bib); + new StoreInst(l, Counter, bib); + + BasicBlock* bb = cast(bib)->getNormalDest(); + BasicBlock::iterator i = bb->getFirstNonPHI(); + l = new LoadInst(Counter, "counter", i); + + bb = cast(bib)->getUnwindDest(); + i = bb->getFirstNonPHI(); + l = new LoadInst(Counter, "counter", i); + new StoreInst(l, AI, i); + } else if (isa(&*bib) || isa(&*bib)) { + LoadInst* l = new LoadInst(AI, "counter", bib); + new StoreInst(l, Counter, bib); + } +} + +void GlobalRandomCounterOpt::ProcessChoicePoint(BasicBlock* bb) { + BranchInst* t = cast(bb->getTerminator()); + + //decrement counter + LoadInst* l = new LoadInst(AI, "counter", t); + + ICmpInst* s = new ICmpInst(t, ICmpInst::ICMP_EQ, l, + ConstantInt::get(T, 0), + "countercc"); + + Value* nv = BinaryOperator::CreateSub(l, ConstantInt::get(T, 1), + "counternew", t); + new StoreInst(nv, AI, t); + t->setCondition(s); + + //reset counter + BasicBlock* oldnext = t->getSuccessor(0); + BasicBlock* resetblock = BasicBlock::Create(bb->getContext(), + "reset", oldnext->getParent(), + oldnext); + TerminatorInst* t2 = BranchInst::Create(oldnext, resetblock); + t->setSuccessor(0, resetblock); + new StoreInst(ResetValue, AI, t2); + ReplacePhiPred(oldnext, bb, resetblock); +} + + +CycleCounter::CycleCounter(Module& m, uint64_t resetmask) : rm(resetmask) { + F = Intrinsic::getDeclaration(&m, Intrinsic::readcyclecounter); +} + +CycleCounter::~CycleCounter() {} + +void CycleCounter::PrepFunction(Function* F) {} + +void CycleCounter::ProcessChoicePoint(BasicBlock* bb) { + BranchInst* t = cast(bb->getTerminator()); + + CallInst* c = CallInst::Create(F, "rdcc", t); + BinaryOperator* b = + BinaryOperator::CreateAnd(c, + ConstantInt::get(Type::getInt64Ty(bb->getContext()), rm), + "mrdcc", t); + + ICmpInst *s = new ICmpInst(t, ICmpInst::ICMP_EQ, b, + ConstantInt::get(Type::getInt64Ty(bb->getContext()), 0), + "mrdccc"); + + t->setCondition(s); +} + +/////////////////////////////////////// +// Profiling: +/////////////////////////////////////// +bool RSProfilers_std::isProfiling(Value* v) { + if (profcode.find(v) != profcode.end()) + return true; + //else + RSProfilers& LI = getAnalysis(); + return LI.isProfiling(v); +} + +void RSProfilers_std::IncrementCounterInBlock(BasicBlock *BB, unsigned CounterNum, + GlobalValue *CounterArray) { + // Insert the increment after any alloca or PHI instructions... + BasicBlock::iterator InsertPos = BB->getFirstNonPHI(); + while (isa(InsertPos)) + ++InsertPos; + + // Create the getelementptr constant expression + std::vector Indices(2); + Indices[0] = Constant::getNullValue(Type::getInt32Ty(BB->getContext())); + Indices[1] = ConstantInt::get(Type::getInt32Ty(BB->getContext()), CounterNum); + Constant *ElementPtr =ConstantExpr::getGetElementPtr(CounterArray, + &Indices[0], 2); + + // Load, increment and store the value back. + Value *OldVal = new LoadInst(ElementPtr, "OldCounter", InsertPos); + profcode.insert(OldVal); + Value *NewVal = BinaryOperator::CreateAdd(OldVal, + ConstantInt::get(Type::getInt32Ty(BB->getContext()), 1), + "NewCounter", InsertPos); + profcode.insert(NewVal); + profcode.insert(new StoreInst(NewVal, ElementPtr, InsertPos)); +} + +void RSProfilers_std::getAnalysisUsage(AnalysisUsage &AU) const { + //grab any outstanding profiler, or get the null one + AU.addRequired(); +} + +/////////////////////////////////////// +// RS Framework +/////////////////////////////////////// + +Value* ProfilerRS::Translate(Value* v) { + if(TransCache[v]) + return TransCache[v]; + + if (BasicBlock* bb = dyn_cast(v)) { + if (bb == &bb->getParent()->getEntryBlock()) + TransCache[bb] = bb; //don't translate entry block + else + TransCache[bb] = BasicBlock::Create(v->getContext(), + "dup_" + bb->getName(), + bb->getParent(), NULL); + return TransCache[bb]; + } else if (Instruction* i = dyn_cast(v)) { + //we have already translated this + //do not translate entry block allocas + if(&i->getParent()->getParent()->getEntryBlock() == i->getParent()) { + TransCache[i] = i; + return i; + } else { + //translate this + Instruction* i2 = i->clone(); + if (i->hasName()) + i2->setName("dup_" + i->getName()); + TransCache[i] = i2; + //NumNewInst++; + for (unsigned x = 0; x < i2->getNumOperands(); ++x) + i2->setOperand(x, Translate(i2->getOperand(x))); + return i2; + } + } else if (isa(v) || isa(v) || isa(v)) { + TransCache[v] = v; + return v; + } + llvm_unreachable("Value not handled"); + return 0; +} + +void ProfilerRS::Duplicate(Function& F, RSProfilers& LI) +{ + //perform a breadth first search, building up a duplicate of the code + std::queue worklist; + std::set seen; + + //This loop ensures proper BB order, to help performance + for (Function::iterator fib = F.begin(), fie = F.end(); fib != fie; ++fib) + worklist.push(fib); + while (!worklist.empty()) { + Translate(worklist.front()); + worklist.pop(); + } + + //remember than reg2mem created a new entry block we don't want to duplicate + worklist.push(F.getEntryBlock().getTerminator()->getSuccessor(0)); + seen.insert(&F.getEntryBlock()); + + while (!worklist.empty()) { + BasicBlock* bb = worklist.front(); + worklist.pop(); + if(seen.find(bb) == seen.end()) { + BasicBlock* bbtarget = cast(Translate(bb)); + BasicBlock::InstListType& instlist = bbtarget->getInstList(); + for (BasicBlock::iterator iib = bb->begin(), iie = bb->end(); + iib != iie; ++iib) { + //NumOldInst++; + if (!LI.isProfiling(&*iib)) { + Instruction* i = cast(Translate(iib)); + instlist.insert(bbtarget->end(), i); + } + } + //updated search state; + seen.insert(bb); + TerminatorInst* ti = bb->getTerminator(); + for (unsigned x = 0; x < ti->getNumSuccessors(); ++x) { + BasicBlock* bbs = ti->getSuccessor(x); + if (seen.find(bbs) == seen.end()) { + worklist.push(bbs); + } + } + } + } +} + +void ProfilerRS::ProcessBackEdge(BasicBlock* src, BasicBlock* dst, Function& F) { + //given a backedge from B -> A, and translations A' and B', + //a: insert C and C' + //b: add branches in C to A and A' and in C' to A and A' + //c: mod terminators@B, replace A with C + //d: mod terminators@B', replace A' with C' + //e: mod phis@A for pred B to be pred C + // if multiple entries, simplify to one + //f: mod phis@A' for pred B' to be pred C' + // if multiple entries, simplify to one + //g: for all phis@A with pred C using x + // add in edge from C' using x' + // add in edge from C using x in A' + + //a: + Function::iterator BBN = src; ++BBN; + BasicBlock* bbC = BasicBlock::Create(F.getContext(), "choice", &F, BBN); + //ChoicePoints.insert(bbC); + BBN = cast(Translate(src)); + BasicBlock* bbCp = BasicBlock::Create(F.getContext(), "choice", &F, ++BBN); + ChoicePoints.insert(bbCp); + + //b: + BranchInst::Create(cast(Translate(dst)), bbC); + BranchInst::Create(dst, cast(Translate(dst)), + ConstantInt::get(Type::getInt1Ty(src->getContext()), true), bbCp); + //c: + { + TerminatorInst* iB = src->getTerminator(); + for (unsigned x = 0; x < iB->getNumSuccessors(); ++x) + if (iB->getSuccessor(x) == dst) + iB->setSuccessor(x, bbC); + } + //d: + { + TerminatorInst* iBp = cast(Translate(src->getTerminator())); + for (unsigned x = 0; x < iBp->getNumSuccessors(); ++x) + if (iBp->getSuccessor(x) == cast(Translate(dst))) + iBp->setSuccessor(x, bbCp); + } + //e: + ReplacePhiPred(dst, src, bbC); + //src could be a switch, in which case we are replacing several edges with one + //thus collapse those edges int the Phi + CollapsePhi(dst, bbC); + //f: + ReplacePhiPred(cast(Translate(dst)), + cast(Translate(src)),bbCp); + CollapsePhi(cast(Translate(dst)), bbCp); + //g: + for(BasicBlock::iterator ib = dst->begin(), ie = dst->end(); ib != ie; + ++ib) + if (PHINode* phi = dyn_cast(&*ib)) { + for(unsigned x = 0; x < phi->getNumIncomingValues(); ++x) + if(bbC == phi->getIncomingBlock(x)) { + phi->addIncoming(Translate(phi->getIncomingValue(x)), bbCp); + cast(Translate(phi))->addIncoming(phi->getIncomingValue(x), + bbC); + } + phi->removeIncomingValue(bbC); + } +} + +bool ProfilerRS::runOnFunction(Function& F) { + if (!F.isDeclaration()) { + std::set > BackEdges; + RSProfilers& LI = getAnalysis(); + + getBackEdges(F, BackEdges); + Duplicate(F, LI); + //assume that stuff worked. now connect the duplicated basic blocks + //with the originals in such a way as to preserve ssa. yuk! + for (std::set >::iterator + ib = BackEdges.begin(), ie = BackEdges.end(); ib != ie; ++ib) + ProcessBackEdge(ib->first, ib->second, F); + + //oh, and add the edge from the reg2mem created entry node to the + //duplicated second node + TerminatorInst* T = F.getEntryBlock().getTerminator(); + ReplaceInstWithInst(T, BranchInst::Create(T->getSuccessor(0), + cast( + Translate(T->getSuccessor(0))), + ConstantInt::get(Type::getInt1Ty(F.getContext()), true))); + + //do whatever is needed now that the function is duplicated + c->PrepFunction(&F); + + //add entry node to choice points + ChoicePoints.insert(&F.getEntryBlock()); + + for (std::set::iterator + ii = ChoicePoints.begin(), ie = ChoicePoints.end(); ii != ie; ++ii) + c->ProcessChoicePoint(*ii); + + ChoicePoints.clear(); + TransCache.clear(); + + return true; + } + return false; +} + +bool ProfilerRS::doInitialization(Module &M) { + switch (RandomMethod) { + case GBV: + c = new GlobalRandomCounter(M, Type::getInt32Ty(M.getContext()), + (1 << 14) - 1); + break; + case GBVO: + c = new GlobalRandomCounterOpt(M, Type::getInt32Ty(M.getContext()), + (1 << 14) - 1); + break; + case HOSTCC: + c = new CycleCounter(M, (1 << 14) - 1); + break; + }; + return true; +} + +void ProfilerRS::getAnalysisUsage(AnalysisUsage &AU) const { + AU.addRequired(); + AU.addRequiredID(DemoteRegisterToMemoryID); +} + +/////////////////////////////////////// +// Utilities: +/////////////////////////////////////// +static void ReplacePhiPred(BasicBlock* btarget, + BasicBlock* bold, BasicBlock* bnew) { + for(BasicBlock::iterator ib = btarget->begin(), ie = btarget->end(); + ib != ie; ++ib) + if (PHINode* phi = dyn_cast(&*ib)) { + for(unsigned x = 0; x < phi->getNumIncomingValues(); ++x) + if(bold == phi->getIncomingBlock(x)) + phi->setIncomingBlock(x, bnew); + } +} + +static void CollapsePhi(BasicBlock* btarget, BasicBlock* bsrc) { + for(BasicBlock::iterator ib = btarget->begin(), ie = btarget->end(); + ib != ie; ++ib) + if (PHINode* phi = dyn_cast(&*ib)) { + std::map counter; + for(unsigned i = 0; i < phi->getNumIncomingValues(); ) { + if (counter[phi->getIncomingBlock(i)]) { + assert(phi->getIncomingValue(i) == counter[phi->getIncomingBlock(i)]); + phi->removeIncomingValue(i, false); + } else { + counter[phi->getIncomingBlock(i)] = phi->getIncomingValue(i); + ++i; + } + } + } +} + +template +static void recBackEdge(BasicBlock* bb, T& BackEdges, + std::map& color, + std::map& depth, + std::map& finish, + int& time) +{ + color[bb] = 1; + ++time; + depth[bb] = time; + TerminatorInst* t= bb->getTerminator(); + for(unsigned i = 0; i < t->getNumSuccessors(); ++i) { + BasicBlock* bbnew = t->getSuccessor(i); + if (color[bbnew] == 0) + recBackEdge(bbnew, BackEdges, color, depth, finish, time); + else if (color[bbnew] == 1) { + BackEdges.insert(std::make_pair(bb, bbnew)); + //NumBackEdges++; + } + } + color[bb] = 2; + ++time; + finish[bb] = time; +} + + + +//find the back edges and where they go to +template +static void getBackEdges(Function& F, T& BackEdges) { + std::map color; + std::map depth; + std::map finish; + int time = 0; + recBackEdge(&F.getEntryBlock(), BackEdges, color, depth, finish, time); + DEBUG(errs() << F.getName() << " " << BackEdges.size() << "\n"); +} + + +//Creation functions +ModulePass* llvm::createNullProfilerRSPass() { + return new NullProfilerRS(); +} + +FunctionPass* llvm::createRSProfilingPass() { + return new ProfilerRS(); +} diff --git a/libclamav/c++/llvm/lib/Transforms/Instrumentation/RSProfiling.h b/libclamav/c++/llvm/lib/Transforms/Instrumentation/RSProfiling.h new file mode 100644 index 000000000..8bbe7c7b2 --- /dev/null +++ b/libclamav/c++/llvm/lib/Transforms/Instrumentation/RSProfiling.h @@ -0,0 +1,31 @@ +//===- RSProfiling.h - Various profiling using random sampling ----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// See notes in RSProfiling.cpp +// +//===----------------------------------------------------------------------===// +#include "llvm/Transforms/RSProfiling.h" +#include + +namespace llvm { + /// RSProfilers_std - a simple support class for profilers that handles most + /// of the work of chaining and tracking inserted code. + struct RSProfilers_std : public RSProfilers { + static char ID; + std::set profcode; + // Lookup up values in profcode + virtual bool isProfiling(Value* v); + // handles required chaining + virtual void getAnalysisUsage(AnalysisUsage &AU) const; + // places counter updates in basic blocks and recordes added instructions in + // profcode + void IncrementCounterInBlock(BasicBlock *BB, unsigned CounterNum, + GlobalValue *CounterArray); + }; +} diff --git a/libclamav/c++/llvm/lib/Transforms/Makefile b/libclamav/c++/llvm/lib/Transforms/Makefile new file mode 100644 index 000000000..025d02ad3 --- /dev/null +++ b/libclamav/c++/llvm/lib/Transforms/Makefile @@ -0,0 +1,20 @@ +##===- lib/Transforms/Makefile -----------------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LEVEL = ../.. +PARALLEL_DIRS = Utils Instrumentation Scalar IPO Hello + +include $(LEVEL)/Makefile.config + +# No support for plugins on windows targets +ifeq ($(HOST_OS), $(filter $(HOST_OS), Cygwin MingW)) + PARALLEL_DIRS := $(filter-out Hello, $(PARALLEL_DIRS)) +endif + +include $(LEVEL)/Makefile.common diff --git a/libclamav/c++/llvm/lib/Transforms/Scalar/ABCD.cpp b/libclamav/c++/llvm/lib/Transforms/Scalar/ABCD.cpp new file mode 100644 index 000000000..e58fa6360 --- /dev/null +++ b/libclamav/c++/llvm/lib/Transforms/Scalar/ABCD.cpp @@ -0,0 +1,1117 @@ +//===------- ABCD.cpp - Removes redundant conditional branches ------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This pass removes redundant branch instructions. This algorithm was +// described by Rastislav Bodik, Rajiv Gupta and Vivek Sarkar in their paper +// "ABCD: Eliminating Array Bounds Checks on Demand (2000)". The original +// Algorithm was created to remove array bound checks for strongly typed +// languages. This implementation expands the idea and removes any conditional +// branches that can be proved redundant, not only those used in array bound +// checks. With the SSI representation, each variable has a +// constraint. By analyzing these constraints we can prove that a branch is +// redundant. When a branch is proved redundant it means that +// one direction will always be taken; thus, we can change this branch into an +// unconditional jump. +// It is advisable to run SimplifyCFG and Aggressive Dead Code Elimination +// after ABCD to clean up the code. +// This implementation was created based on the implementation of the ABCD +// algorithm implemented for the compiler Jitrino. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "abcd" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/Constants.h" +#include "llvm/Function.h" +#include "llvm/Instructions.h" +#include "llvm/Pass.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/Debug.h" +#include "llvm/Transforms/Scalar.h" +#include "llvm/Transforms/Utils/SSI.h" + +using namespace llvm; + +STATISTIC(NumBranchTested, "Number of conditional branches analyzed"); +STATISTIC(NumBranchRemoved, "Number of conditional branches removed"); + +namespace { + +class ABCD : public FunctionPass { + public: + static char ID; // Pass identification, replacement for typeid. + ABCD() : FunctionPass(&ID) {} + + void getAnalysisUsage(AnalysisUsage &AU) const { + AU.addRequired(); + } + + bool runOnFunction(Function &F); + + private: + /// Keep track of whether we've modified the program yet. + bool modified; + + enum ProveResult { + False = 0, + Reduced = 1, + True = 2 + }; + + typedef ProveResult (*meet_function)(ProveResult, ProveResult); + static ProveResult max(ProveResult res1, ProveResult res2) { + return (ProveResult) std::max(res1, res2); + } + static ProveResult min(ProveResult res1, ProveResult res2) { + return (ProveResult) std::min(res1, res2); + } + + class Bound { + public: + Bound(APInt v, bool upper) : value(v), upper_bound(upper) {} + Bound(const Bound *b, int cnst) + : value(b->value - cnst), upper_bound(b->upper_bound) {} + Bound(const Bound *b, const APInt &cnst) + : value(b->value - cnst), upper_bound(b->upper_bound) {} + + /// Test if Bound is an upper bound + bool isUpperBound() const { return upper_bound; } + + /// Get the bitwidth of this bound + int32_t getBitWidth() const { return value.getBitWidth(); } + + /// Creates a Bound incrementing the one received + static Bound *createIncrement(const Bound *b) { + return new Bound(b->isUpperBound() ? b->value+1 : b->value-1, + b->upper_bound); + } + + /// Creates a Bound decrementing the one received + static Bound *createDecrement(const Bound *b) { + return new Bound(b->isUpperBound() ? b->value-1 : b->value+1, + b->upper_bound); + } + + /// Test if two bounds are equal + static bool eq(const Bound *a, const Bound *b) { + if (!a || !b) return false; + + assert(a->isUpperBound() == b->isUpperBound()); + return a->value == b->value; + } + + /// Test if val is less than or equal to Bound b + static bool leq(APInt val, const Bound *b) { + if (!b) return false; + return b->isUpperBound() ? val.sle(b->value) : val.sge(b->value); + } + + /// Test if Bound a is less then or equal to Bound + static bool leq(const Bound *a, const Bound *b) { + if (!a || !b) return false; + + assert(a->isUpperBound() == b->isUpperBound()); + return a->isUpperBound() ? a->value.sle(b->value) : + a->value.sge(b->value); + } + + /// Test if Bound a is less then Bound b + static bool lt(const Bound *a, const Bound *b) { + if (!a || !b) return false; + + assert(a->isUpperBound() == b->isUpperBound()); + return a->isUpperBound() ? a->value.slt(b->value) : + a->value.sgt(b->value); + } + + /// Test if Bound b is greater then or equal val + static bool geq(const Bound *b, APInt val) { + return leq(val, b); + } + + /// Test if Bound a is greater then or equal Bound b + static bool geq(const Bound *a, const Bound *b) { + return leq(b, a); + } + + private: + APInt value; + bool upper_bound; + }; + + /// This class is used to store results some parts of the graph, + /// so information does not need to be recalculated. The maximum false, + /// minimum true and minimum reduced results are stored + class MemoizedResultChart { + public: + MemoizedResultChart() + : max_false(NULL), min_true(NULL), min_reduced(NULL) {} + + /// Returns the max false + Bound *getFalse() const { return max_false; } + + /// Returns the min true + Bound *getTrue() const { return min_true; } + + /// Returns the min reduced + Bound *getReduced() const { return min_reduced; } + + /// Return the stored result for this bound + ProveResult getResult(const Bound *bound) const; + + /// Stores a false found + void addFalse(Bound *bound); + + /// Stores a true found + void addTrue(Bound *bound); + + /// Stores a Reduced found + void addReduced(Bound *bound); + + /// Clears redundant reduced + /// If a min_true is smaller than a min_reduced then the min_reduced + /// is unnecessary and then removed. It also works for min_reduced + /// begin smaller than max_false. + void clearRedundantReduced(); + + void clear() { + delete max_false; + delete min_true; + delete min_reduced; + } + + private: + Bound *max_false, *min_true, *min_reduced; + }; + + /// This class stores the result found for a node of the graph, + /// so these results do not need to be recalculated, only searched for. + class MemoizedResult { + public: + /// Test if there is true result stored from b to a + /// that is less then the bound + bool hasTrue(Value *b, const Bound *bound) const { + Bound *trueBound = map.lookup(b).getTrue(); + return trueBound && Bound::leq(trueBound, bound); + } + + /// Test if there is false result stored from b to a + /// that is less then the bound + bool hasFalse(Value *b, const Bound *bound) const { + Bound *falseBound = map.lookup(b).getFalse(); + return falseBound && Bound::leq(falseBound, bound); + } + + /// Test if there is reduced result stored from b to a + /// that is less then the bound + bool hasReduced(Value *b, const Bound *bound) const { + Bound *reducedBound = map.lookup(b).getReduced(); + return reducedBound && Bound::leq(reducedBound, bound); + } + + /// Returns the stored bound for b + ProveResult getBoundResult(Value *b, Bound *bound) { + return map[b].getResult(bound); + } + + /// Clears the map + void clear() { + DenseMapIterator begin = map.begin(); + DenseMapIterator end = map.end(); + for (; begin != end; ++begin) { + begin->second.clear(); + } + map.clear(); + } + + /// Stores the bound found + void updateBound(Value *b, Bound *bound, const ProveResult res); + + private: + // Maps a nod in the graph with its results found. + DenseMap map; + }; + + /// This class represents an edge in the inequality graph used by the + /// ABCD algorithm. An edge connects node v to node u with a value c if + /// we could infer a constraint v <= u + c in the source program. + class Edge { + public: + Edge(Value *V, APInt val, bool upper) + : vertex(V), value(val), upper_bound(upper) {} + + Value *getVertex() const { return vertex; } + const APInt &getValue() const { return value; } + bool isUpperBound() const { return upper_bound; } + + private: + Value *vertex; + APInt value; + bool upper_bound; + }; + + /// Weighted and Directed graph to represent constraints. + /// There is one type of constraint, a <= b + X, which will generate an + /// edge from b to a with weight X. + class InequalityGraph { + public: + + /// Adds an edge from V_from to V_to with weight value + void addEdge(Value *V_from, Value *V_to, APInt value, bool upper); + + /// Test if there is a node V + bool hasNode(Value *V) const { return graph.count(V); } + + /// Test if there is any edge from V in the upper direction + bool hasEdge(Value *V, bool upper) const; + + /// Returns all edges pointed by vertex V + SmallPtrSet getEdges(Value *V) const { + return graph.lookup(V); + } + + /// Prints the graph in dot format. + /// Blue edges represent upper bound and Red lower bound. + void printGraph(raw_ostream &OS, Function &F) const { + printHeader(OS, F); + printBody(OS); + printFooter(OS); + } + + /// Clear the graph + void clear() { + graph.clear(); + } + + private: + DenseMap > graph; + + /// Adds a Node to the graph. + DenseMap >::iterator addNode(Value *V) { + SmallPtrSet p; + return graph.insert(std::make_pair(V, p)).first; + } + + /// Prints the header of the dot file + void printHeader(raw_ostream &OS, Function &F) const; + + /// Prints the footer of the dot file + void printFooter(raw_ostream &OS) const { + OS << "}\n"; + } + + /// Prints the body of the dot file + void printBody(raw_ostream &OS) const; + + /// Prints vertex source to the dot file + void printVertex(raw_ostream &OS, Value *source) const; + + /// Prints the edge to the dot file + void printEdge(raw_ostream &OS, Value *source, Edge *edge) const; + + void printName(raw_ostream &OS, Value *info) const; + }; + + /// Iterates through all BasicBlocks, if the Terminator Instruction + /// uses an Comparator Instruction, all operands of this comparator + /// are sent to be transformed to SSI. Only Instruction operands are + /// transformed. + void createSSI(Function &F); + + /// Creates the graphs for this function. + /// It will look for all comparators used in branches, and create them. + /// These comparators will create constraints for any instruction as an + /// operand. + void executeABCD(Function &F); + + /// Seeks redundancies in the comparator instruction CI. + /// If the ABCD algorithm can prove that the comparator CI always + /// takes one way, then the Terminator Instruction TI is substituted from + /// a conditional branch to a unconditional one. + /// This code basically receives a comparator, and verifies which kind of + /// instruction it is. Depending on the kind of instruction, we use different + /// strategies to prove its redundancy. + void seekRedundancy(ICmpInst *ICI, TerminatorInst *TI); + + /// Substitutes Terminator Instruction TI, that is a conditional branch, + /// with one unconditional branch. Succ_edge determines if the new + /// unconditional edge will be the first or second edge of the former TI + /// instruction. + void removeRedundancy(TerminatorInst *TI, bool Succ_edge); + + /// When an conditional branch is removed, the BasicBlock that is no longer + /// reachable will have problems in phi functions. This method fixes these + /// phis removing the former BasicBlock from the list of incoming BasicBlocks + /// of all phis. In case the phi remains with no predecessor it will be + /// marked to be removed later. + void fixPhi(BasicBlock *BB, BasicBlock *Succ); + + /// Removes phis that have no predecessor + void removePhis(); + + /// Creates constraints for Instructions. + /// If the constraint for this instruction has already been created + /// nothing is done. + void createConstraintInstruction(Instruction *I); + + /// Creates constraints for Binary Operators. + /// It will create constraints only for addition and subtraction, + /// the other binary operations are not treated by ABCD. + /// For additions in the form a = b + X and a = X + b, where X is a constant, + /// the constraint a <= b + X can be obtained. For this constraint, an edge + /// a->b with weight X is added to the lower bound graph, and an edge + /// b->a with weight -X is added to the upper bound graph. + /// Only subtractions in the format a = b - X is used by ABCD. + /// Edges are created using the same semantic as addition. + void createConstraintBinaryOperator(BinaryOperator *BO); + + /// Creates constraints for Comparator Instructions. + /// Only comparators that have any of the following operators + /// are used to create constraints: >=, >, <=, <. And only if + /// at least one operand is an Instruction. In a Comparator Instruction + /// a op b, there will be 4 sigma functions a_t, a_f, b_t and b_f. Where + /// t and f represent sigma for operands in true and false branches. The + /// following constraints can be obtained. a_t <= a, a_f <= a, b_t <= b and + /// b_f <= b. There are two more constraints that depend on the operator. + /// For the operator <= : a_t <= b_t and b_f <= a_f-1 + /// For the operator < : a_t <= b_t-1 and b_f <= a_f + /// For the operator >= : b_t <= a_t and a_f <= b_f-1 + /// For the operator > : b_t <= a_t-1 and a_f <= b_f + void createConstraintCmpInst(ICmpInst *ICI, TerminatorInst *TI); + + /// Creates constraints for PHI nodes. + /// In a PHI node a = phi(b,c) we can create the constraint + /// a<= max(b,c). With this constraint there will be the edges, + /// b->a and c->a with weight 0 in the lower bound graph, and the edges + /// a->b and a->c with weight 0 in the upper bound graph. + void createConstraintPHINode(PHINode *PN); + + /// Given a binary operator, we are only interest in the case + /// that one operand is an Instruction and the other is a ConstantInt. In + /// this case the method returns true, otherwise false. It also obtains the + /// Instruction and ConstantInt from the BinaryOperator and returns it. + bool createBinaryOperatorInfo(BinaryOperator *BO, Instruction **I1, + Instruction **I2, ConstantInt **C1, + ConstantInt **C2); + + /// This method creates a constraint between a Sigma and an Instruction. + /// These constraints are created as soon as we find a comparator that uses a + /// SSI variable. + void createConstraintSigInst(Instruction *I_op, BasicBlock *BB_succ_t, + BasicBlock *BB_succ_f, PHINode **SIG_op_t, + PHINode **SIG_op_f); + + /// If PN_op1 and PN_o2 are different from NULL, create a constraint + /// PN_op2 -> PN_op1 with value. In case any of them is NULL, replace + /// with the respective V_op#, if V_op# is a ConstantInt. + void createConstraintSigSig(PHINode *SIG_op1, PHINode *SIG_op2, + ConstantInt *V_op1, ConstantInt *V_op2, + APInt value); + + /// Returns the sigma representing the Instruction I in BasicBlock BB. + /// Returns NULL in case there is no sigma for this Instruction in this + /// Basic Block. This methods assume that sigmas are the first instructions + /// in a block, and that there can be only two sigmas in a block. So it will + /// only look on the first two instructions of BasicBlock BB. + PHINode *findSigma(BasicBlock *BB, Instruction *I); + + /// Original ABCD algorithm to prove redundant checks. + /// This implementation works on any kind of inequality branch. + bool demandProve(Value *a, Value *b, int c, bool upper_bound); + + /// Prove that distance between b and a is <= bound + ProveResult prove(Value *a, Value *b, Bound *bound, unsigned level); + + /// Updates the distance value for a and b + void updateMemDistance(Value *a, Value *b, Bound *bound, unsigned level, + meet_function meet); + + InequalityGraph inequality_graph; + MemoizedResult mem_result; + DenseMap active; + SmallPtrSet created; + SmallVector phis_to_remove; +}; + +} // end anonymous namespace. + +char ABCD::ID = 0; +static RegisterPass X("abcd", "ABCD: Eliminating Array Bounds Checks on Demand"); + + +bool ABCD::runOnFunction(Function &F) { + modified = false; + createSSI(F); + executeABCD(F); + DEBUG(inequality_graph.printGraph(errs(), F)); + removePhis(); + + inequality_graph.clear(); + mem_result.clear(); + active.clear(); + created.clear(); + phis_to_remove.clear(); + return modified; +} + +/// Iterates through all BasicBlocks, if the Terminator Instruction +/// uses an Comparator Instruction, all operands of this comparator +/// are sent to be transformed to SSI. Only Instruction operands are +/// transformed. +void ABCD::createSSI(Function &F) { + SSI *ssi = &getAnalysis(); + + SmallVector Insts; + + for (Function::iterator begin = F.begin(), end = F.end(); + begin != end; ++begin) { + BasicBlock *BB = begin; + TerminatorInst *TI = BB->getTerminator(); + if (TI->getNumOperands() == 0) + continue; + + if (ICmpInst *ICI = dyn_cast(TI->getOperand(0))) { + if (Instruction *I = dyn_cast(ICI->getOperand(0))) { + modified = true; // XXX: but yet createSSI might do nothing + Insts.push_back(I); + } + if (Instruction *I = dyn_cast(ICI->getOperand(1))) { + modified = true; + Insts.push_back(I); + } + } + } + ssi->createSSI(Insts); +} + +/// Creates the graphs for this function. +/// It will look for all comparators used in branches, and create them. +/// These comparators will create constraints for any instruction as an +/// operand. +void ABCD::executeABCD(Function &F) { + for (Function::iterator begin = F.begin(), end = F.end(); + begin != end; ++begin) { + BasicBlock *BB = begin; + TerminatorInst *TI = BB->getTerminator(); + if (TI->getNumOperands() == 0) + continue; + + ICmpInst *ICI = dyn_cast(TI->getOperand(0)); + if (!ICI || !isa(ICI->getOperand(0)->getType())) + continue; + + createConstraintCmpInst(ICI, TI); + seekRedundancy(ICI, TI); + } +} + +/// Seeks redundancies in the comparator instruction CI. +/// If the ABCD algorithm can prove that the comparator CI always +/// takes one way, then the Terminator Instruction TI is substituted from +/// a conditional branch to a unconditional one. +/// This code basically receives a comparator, and verifies which kind of +/// instruction it is. Depending on the kind of instruction, we use different +/// strategies to prove its redundancy. +void ABCD::seekRedundancy(ICmpInst *ICI, TerminatorInst *TI) { + CmpInst::Predicate Pred = ICI->getPredicate(); + + Value *source, *dest; + int distance1, distance2; + bool upper; + + switch(Pred) { + case CmpInst::ICMP_SGT: // signed greater than + upper = false; + distance1 = 1; + distance2 = 0; + break; + + case CmpInst::ICMP_SGE: // signed greater or equal + upper = false; + distance1 = 0; + distance2 = -1; + break; + + case CmpInst::ICMP_SLT: // signed less than + upper = true; + distance1 = -1; + distance2 = 0; + break; + + case CmpInst::ICMP_SLE: // signed less or equal + upper = true; + distance1 = 0; + distance2 = 1; + break; + + default: + return; + } + + ++NumBranchTested; + source = ICI->getOperand(0); + dest = ICI->getOperand(1); + if (demandProve(dest, source, distance1, upper)) { + removeRedundancy(TI, true); + } else if (demandProve(dest, source, distance2, !upper)) { + removeRedundancy(TI, false); + } +} + +/// Substitutes Terminator Instruction TI, that is a conditional branch, +/// with one unconditional branch. Succ_edge determines if the new +/// unconditional edge will be the first or second edge of the former TI +/// instruction. +void ABCD::removeRedundancy(TerminatorInst *TI, bool Succ_edge) { + BasicBlock *Succ; + if (Succ_edge) { + Succ = TI->getSuccessor(0); + fixPhi(TI->getParent(), TI->getSuccessor(1)); + } else { + Succ = TI->getSuccessor(1); + fixPhi(TI->getParent(), TI->getSuccessor(0)); + } + + BranchInst::Create(Succ, TI); + TI->eraseFromParent(); // XXX: invoke + ++NumBranchRemoved; + modified = true; +} + +/// When an conditional branch is removed, the BasicBlock that is no longer +/// reachable will have problems in phi functions. This method fixes these +/// phis removing the former BasicBlock from the list of incoming BasicBlocks +/// of all phis. In case the phi remains with no predecessor it will be +/// marked to be removed later. +void ABCD::fixPhi(BasicBlock *BB, BasicBlock *Succ) { + BasicBlock::iterator begin = Succ->begin(); + while (PHINode *PN = dyn_cast(begin++)) { + PN->removeIncomingValue(BB, false); + if (PN->getNumIncomingValues() == 0) + phis_to_remove.push_back(PN); + } +} + +/// Removes phis that have no predecessor +void ABCD::removePhis() { + for (unsigned i = 0, e = phis_to_remove.size(); i != e; ++i) { + PHINode *PN = phis_to_remove[i]; + PN->replaceAllUsesWith(UndefValue::get(PN->getType())); + PN->eraseFromParent(); + } +} + +/// Creates constraints for Instructions. +/// If the constraint for this instruction has already been created +/// nothing is done. +void ABCD::createConstraintInstruction(Instruction *I) { + // Test if this instruction has not been created before + if (created.insert(I)) { + if (BinaryOperator *BO = dyn_cast(I)) { + createConstraintBinaryOperator(BO); + } else if (PHINode *PN = dyn_cast(I)) { + createConstraintPHINode(PN); + } + } +} + +/// Creates constraints for Binary Operators. +/// It will create constraints only for addition and subtraction, +/// the other binary operations are not treated by ABCD. +/// For additions in the form a = b + X and a = X + b, where X is a constant, +/// the constraint a <= b + X can be obtained. For this constraint, an edge +/// a->b with weight X is added to the lower bound graph, and an edge +/// b->a with weight -X is added to the upper bound graph. +/// Only subtractions in the format a = b - X is used by ABCD. +/// Edges are created using the same semantic as addition. +void ABCD::createConstraintBinaryOperator(BinaryOperator *BO) { + Instruction *I1 = NULL, *I2 = NULL; + ConstantInt *CI1 = NULL, *CI2 = NULL; + + // Test if an operand is an Instruction and the other is a Constant + if (!createBinaryOperatorInfo(BO, &I1, &I2, &CI1, &CI2)) + return; + + Instruction *I = 0; + APInt value; + + switch (BO->getOpcode()) { + case Instruction::Add: + if (I1) { + I = I1; + value = CI2->getValue(); + } else if (I2) { + I = I2; + value = CI1->getValue(); + } + break; + + case Instruction::Sub: + // Instructions like a = X-b, where X is a constant are not represented + // in the graph. + if (!I1) + return; + + I = I1; + value = -CI2->getValue(); + break; + + default: + return; + } + + inequality_graph.addEdge(I, BO, value, true); + inequality_graph.addEdge(BO, I, -value, false); + createConstraintInstruction(I); +} + +/// Given a binary operator, we are only interest in the case +/// that one operand is an Instruction and the other is a ConstantInt. In +/// this case the method returns true, otherwise false. It also obtains the +/// Instruction and ConstantInt from the BinaryOperator and returns it. +bool ABCD::createBinaryOperatorInfo(BinaryOperator *BO, Instruction **I1, + Instruction **I2, ConstantInt **C1, + ConstantInt **C2) { + Value *op1 = BO->getOperand(0); + Value *op2 = BO->getOperand(1); + + if ((*I1 = dyn_cast(op1))) { + if ((*C2 = dyn_cast(op2))) + return true; // First is Instruction and second ConstantInt + + return false; // Both are Instruction + } else { + if ((*C1 = dyn_cast(op1)) && + (*I2 = dyn_cast(op2))) + return true; // First is ConstantInt and second Instruction + + return false; // Both are not Instruction + } +} + +/// Creates constraints for Comparator Instructions. +/// Only comparators that have any of the following operators +/// are used to create constraints: >=, >, <=, <. And only if +/// at least one operand is an Instruction. In a Comparator Instruction +/// a op b, there will be 4 sigma functions a_t, a_f, b_t and b_f. Where +/// t and f represent sigma for operands in true and false branches. The +/// following constraints can be obtained. a_t <= a, a_f <= a, b_t <= b and +/// b_f <= b. There are two more constraints that depend on the operator. +/// For the operator <= : a_t <= b_t and b_f <= a_f-1 +/// For the operator < : a_t <= b_t-1 and b_f <= a_f +/// For the operator >= : b_t <= a_t and a_f <= b_f-1 +/// For the operator > : b_t <= a_t-1 and a_f <= b_f +void ABCD::createConstraintCmpInst(ICmpInst *ICI, TerminatorInst *TI) { + Value *V_op1 = ICI->getOperand(0); + Value *V_op2 = ICI->getOperand(1); + + if (!isa(V_op1->getType())) + return; + + Instruction *I_op1 = dyn_cast(V_op1); + Instruction *I_op2 = dyn_cast(V_op2); + + // Test if at least one operand is an Instruction + if (!I_op1 && !I_op2) + return; + + BasicBlock *BB_succ_t = TI->getSuccessor(0); + BasicBlock *BB_succ_f = TI->getSuccessor(1); + + PHINode *SIG_op1_t = NULL, *SIG_op1_f = NULL, + *SIG_op2_t = NULL, *SIG_op2_f = NULL; + + createConstraintSigInst(I_op1, BB_succ_t, BB_succ_f, &SIG_op1_t, &SIG_op1_f); + createConstraintSigInst(I_op2, BB_succ_t, BB_succ_f, &SIG_op2_t, &SIG_op2_f); + + int32_t width = cast(V_op1->getType())->getBitWidth(); + APInt MinusOne = APInt::getAllOnesValue(width); + APInt Zero = APInt::getNullValue(width); + + CmpInst::Predicate Pred = ICI->getPredicate(); + ConstantInt *CI1 = dyn_cast(V_op1); + ConstantInt *CI2 = dyn_cast(V_op2); + switch (Pred) { + case CmpInst::ICMP_SGT: // signed greater than + createConstraintSigSig(SIG_op2_t, SIG_op1_t, CI2, CI1, MinusOne); + createConstraintSigSig(SIG_op1_f, SIG_op2_f, CI1, CI2, Zero); + break; + + case CmpInst::ICMP_SGE: // signed greater or equal + createConstraintSigSig(SIG_op2_t, SIG_op1_t, CI2, CI1, Zero); + createConstraintSigSig(SIG_op1_f, SIG_op2_f, CI1, CI2, MinusOne); + break; + + case CmpInst::ICMP_SLT: // signed less than + createConstraintSigSig(SIG_op1_t, SIG_op2_t, CI1, CI2, MinusOne); + createConstraintSigSig(SIG_op2_f, SIG_op1_f, CI2, CI1, Zero); + break; + + case CmpInst::ICMP_SLE: // signed less or equal + createConstraintSigSig(SIG_op1_t, SIG_op2_t, CI1, CI2, Zero); + createConstraintSigSig(SIG_op2_f, SIG_op1_f, CI2, CI1, MinusOne); + break; + + default: + break; + } + + if (I_op1) + createConstraintInstruction(I_op1); + if (I_op2) + createConstraintInstruction(I_op2); +} + +/// Creates constraints for PHI nodes. +/// In a PHI node a = phi(b,c) we can create the constraint +/// a<= max(b,c). With this constraint there will be the edges, +/// b->a and c->a with weight 0 in the lower bound graph, and the edges +/// a->b and a->c with weight 0 in the upper bound graph. +void ABCD::createConstraintPHINode(PHINode *PN) { + // FIXME: We really want to disallow sigma nodes, but I don't know the best + // way to detect the other than this. + if (PN->getNumOperands() == 2) return; + + int32_t width = cast(PN->getType())->getBitWidth(); + for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) { + Value *V = PN->getIncomingValue(i); + if (Instruction *I = dyn_cast(V)) { + createConstraintInstruction(I); + } + inequality_graph.addEdge(V, PN, APInt(width, 0), true); + inequality_graph.addEdge(V, PN, APInt(width, 0), false); + } +} + +/// This method creates a constraint between a Sigma and an Instruction. +/// These constraints are created as soon as we find a comparator that uses a +/// SSI variable. +void ABCD::createConstraintSigInst(Instruction *I_op, BasicBlock *BB_succ_t, + BasicBlock *BB_succ_f, PHINode **SIG_op_t, + PHINode **SIG_op_f) { + *SIG_op_t = findSigma(BB_succ_t, I_op); + *SIG_op_f = findSigma(BB_succ_f, I_op); + + if (*SIG_op_t) { + int32_t width = cast((*SIG_op_t)->getType())->getBitWidth(); + inequality_graph.addEdge(I_op, *SIG_op_t, APInt(width, 0), true); + inequality_graph.addEdge(*SIG_op_t, I_op, APInt(width, 0), false); + } + if (*SIG_op_f) { + int32_t width = cast((*SIG_op_f)->getType())->getBitWidth(); + inequality_graph.addEdge(I_op, *SIG_op_f, APInt(width, 0), true); + inequality_graph.addEdge(*SIG_op_f, I_op, APInt(width, 0), false); + } +} + +/// If PN_op1 and PN_o2 are different from NULL, create a constraint +/// PN_op2 -> PN_op1 with value. In case any of them is NULL, replace +/// with the respective V_op#, if V_op# is a ConstantInt. +void ABCD::createConstraintSigSig(PHINode *SIG_op1, PHINode *SIG_op2, + ConstantInt *V_op1, ConstantInt *V_op2, + APInt value) { + if (SIG_op1 && SIG_op2) { + inequality_graph.addEdge(SIG_op2, SIG_op1, value, true); + inequality_graph.addEdge(SIG_op1, SIG_op2, -value, false); + } else if (SIG_op1 && V_op2) { + inequality_graph.addEdge(V_op2, SIG_op1, value, true); + inequality_graph.addEdge(SIG_op1, V_op2, -value, false); + } else if (SIG_op2 && V_op1) { + inequality_graph.addEdge(SIG_op2, V_op1, value, true); + inequality_graph.addEdge(V_op1, SIG_op2, -value, false); + } +} + +/// Returns the sigma representing the Instruction I in BasicBlock BB. +/// Returns NULL in case there is no sigma for this Instruction in this +/// Basic Block. This methods assume that sigmas are the first instructions +/// in a block, and that there can be only two sigmas in a block. So it will +/// only look on the first two instructions of BasicBlock BB. +PHINode *ABCD::findSigma(BasicBlock *BB, Instruction *I) { + // BB has more than one predecessor, BB cannot have sigmas. + if (I == NULL || BB->getSinglePredecessor() == NULL) + return NULL; + + BasicBlock::iterator begin = BB->begin(); + BasicBlock::iterator end = BB->end(); + + for (unsigned i = 0; i < 2 && begin != end; ++i, ++begin) { + Instruction *I_succ = begin; + if (PHINode *PN = dyn_cast(I_succ)) + if (PN->getIncomingValue(0) == I) + return PN; + } + + return NULL; +} + +/// Original ABCD algorithm to prove redundant checks. +/// This implementation works on any kind of inequality branch. +bool ABCD::demandProve(Value *a, Value *b, int c, bool upper_bound) { + int32_t width = cast(a->getType())->getBitWidth(); + Bound *bound = new Bound(APInt(width, c), upper_bound); + + mem_result.clear(); + active.clear(); + + ProveResult res = prove(a, b, bound, 0); + return res != False; +} + +/// Prove that distance between b and a is <= bound +ABCD::ProveResult ABCD::prove(Value *a, Value *b, Bound *bound, + unsigned level) { + // if (C[b-a<=e] == True for some e <= bound + // Same or stronger difference was already proven + if (mem_result.hasTrue(b, bound)) + return True; + + // if (C[b-a<=e] == False for some e >= bound + // Same or weaker difference was already disproved + if (mem_result.hasFalse(b, bound)) + return False; + + // if (C[b-a<=e] == Reduced for some e <= bound + // b is on a cycle that was reduced for same or stronger difference + if (mem_result.hasReduced(b, bound)) + return Reduced; + + // traversal reached the source vertex + if (a == b && Bound::geq(bound, APInt(bound->getBitWidth(), 0, true))) + return True; + + // if b has no predecessor then fail + if (!inequality_graph.hasEdge(b, bound->isUpperBound())) + return False; + + // a cycle was encountered + if (active.count(b)) { + if (Bound::leq(active.lookup(b), bound)) + return Reduced; // a "harmless" cycle + + return False; // an amplifying cycle + } + + active[b] = bound; + PHINode *PN = dyn_cast(b); + + // Test if a Value is a Phi. If it is a PHINode with more than 1 incoming + // value, then it is a phi, if it has 1 incoming value it is a sigma. + if (PN && PN->getNumIncomingValues() > 1) + updateMemDistance(a, b, bound, level, min); + else + updateMemDistance(a, b, bound, level, max); + + active.erase(b); + + ABCD::ProveResult res = mem_result.getBoundResult(b, bound); + return res; +} + +/// Updates the distance value for a and b +void ABCD::updateMemDistance(Value *a, Value *b, Bound *bound, unsigned level, + meet_function meet) { + ABCD::ProveResult res = (meet == max) ? False : True; + + SmallPtrSet Edges = inequality_graph.getEdges(b); + SmallPtrSet::iterator begin = Edges.begin(), end = Edges.end(); + + for (; begin != end ; ++begin) { + if (((res >= Reduced) && (meet == max)) || + ((res == False) && (meet == min))) { + break; + } + Edge *in = *begin; + if (in->isUpperBound() == bound->isUpperBound()) { + Value *succ = in->getVertex(); + res = meet(res, prove(a, succ, new Bound(bound, in->getValue()), + level+1)); + } + } + + mem_result.updateBound(b, bound, res); +} + +/// Return the stored result for this bound +ABCD::ProveResult ABCD::MemoizedResultChart::getResult(const Bound *bound)const{ + if (max_false && Bound::leq(bound, max_false)) + return False; + if (min_true && Bound::leq(min_true, bound)) + return True; + if (min_reduced && Bound::leq(min_reduced, bound)) + return Reduced; + return False; +} + +/// Stores a false found +void ABCD::MemoizedResultChart::addFalse(Bound *bound) { + if (!max_false || Bound::leq(max_false, bound)) + max_false = bound; + + if (Bound::eq(max_false, min_reduced)) + min_reduced = Bound::createIncrement(min_reduced); + if (Bound::eq(max_false, min_true)) + min_true = Bound::createIncrement(min_true); + if (Bound::eq(min_reduced, min_true)) + min_reduced = NULL; + clearRedundantReduced(); +} + +/// Stores a true found +void ABCD::MemoizedResultChart::addTrue(Bound *bound) { + if (!min_true || Bound::leq(bound, min_true)) + min_true = bound; + + if (Bound::eq(min_true, min_reduced)) + min_reduced = Bound::createDecrement(min_reduced); + if (Bound::eq(min_true, max_false)) + max_false = Bound::createDecrement(max_false); + if (Bound::eq(max_false, min_reduced)) + min_reduced = NULL; + clearRedundantReduced(); +} + +/// Stores a Reduced found +void ABCD::MemoizedResultChart::addReduced(Bound *bound) { + if (!min_reduced || Bound::leq(bound, min_reduced)) + min_reduced = bound; + + if (Bound::eq(min_reduced, min_true)) + min_true = Bound::createIncrement(min_true); + if (Bound::eq(min_reduced, max_false)) + max_false = Bound::createDecrement(max_false); +} + +/// Clears redundant reduced +/// If a min_true is smaller than a min_reduced then the min_reduced +/// is unnecessary and then removed. It also works for min_reduced +/// begin smaller than max_false. +void ABCD::MemoizedResultChart::clearRedundantReduced() { + if (min_true && min_reduced && Bound::lt(min_true, min_reduced)) + min_reduced = NULL; + if (max_false && min_reduced && Bound::lt(min_reduced, max_false)) + min_reduced = NULL; +} + +/// Stores the bound found +void ABCD::MemoizedResult::updateBound(Value *b, Bound *bound, + const ProveResult res) { + if (res == False) { + map[b].addFalse(bound); + } else if (res == True) { + map[b].addTrue(bound); + } else { + map[b].addReduced(bound); + } +} + +/// Adds an edge from V_from to V_to with weight value +void ABCD::InequalityGraph::addEdge(Value *V_to, Value *V_from, + APInt value, bool upper) { + assert(V_from->getType() == V_to->getType()); + assert(cast(V_from->getType())->getBitWidth() == + value.getBitWidth()); + + DenseMap >::iterator from; + from = addNode(V_from); + from->second.insert(new Edge(V_to, value, upper)); +} + +/// Test if there is any edge from V in the upper direction +bool ABCD::InequalityGraph::hasEdge(Value *V, bool upper) const { + SmallPtrSet it = graph.lookup(V); + + SmallPtrSet::iterator begin = it.begin(); + SmallPtrSet::iterator end = it.end(); + for (; begin != end; ++begin) { + if ((*begin)->isUpperBound() == upper) { + return true; + } + } + return false; +} + +/// Prints the header of the dot file +void ABCD::InequalityGraph::printHeader(raw_ostream &OS, Function &F) const { + OS << "digraph dotgraph {\n"; + OS << "label=\"Inequality Graph for \'"; + OS << F.getNameStr() << "\' function\";\n"; + OS << "node [shape=record,fontname=\"Times-Roman\",fontsize=14];\n"; +} + +/// Prints the body of the dot file +void ABCD::InequalityGraph::printBody(raw_ostream &OS) const { + DenseMap >::const_iterator begin = + graph.begin(), end = graph.end(); + + for (; begin != end ; ++begin) { + SmallPtrSet::iterator begin_par = + begin->second.begin(), end_par = begin->second.end(); + Value *source = begin->first; + + printVertex(OS, source); + + for (; begin_par != end_par ; ++begin_par) { + Edge *edge = *begin_par; + printEdge(OS, source, edge); + } + } +} + +/// Prints vertex source to the dot file +/// +void ABCD::InequalityGraph::printVertex(raw_ostream &OS, Value *source) const { + OS << "\""; + printName(OS, source); + OS << "\""; + OS << " [label=\"{"; + printName(OS, source); + OS << "}\"];\n"; +} + +/// Prints the edge to the dot file +void ABCD::InequalityGraph::printEdge(raw_ostream &OS, Value *source, + Edge *edge) const { + Value *dest = edge->getVertex(); + APInt value = edge->getValue(); + bool upper = edge->isUpperBound(); + + OS << "\""; + printName(OS, source); + OS << "\""; + OS << " -> "; + OS << "\""; + printName(OS, dest); + OS << "\""; + OS << " [label=\"" << value << "\""; + if (upper) { + OS << "color=\"blue\""; + } else { + OS << "color=\"red\""; + } + OS << "];\n"; +} + +void ABCD::InequalityGraph::printName(raw_ostream &OS, Value *info) const { + if (ConstantInt *CI = dyn_cast(info)) { + OS << *CI; + } else { + if (!info->hasName()) { + info->setName("V"); + } + OS << info->getNameStr(); + } +} + +/// createABCDPass - The public interface to this file... +FunctionPass *llvm::createABCDPass() { + return new ABCD(); +} diff --git a/libclamav/c++/llvm/lib/Transforms/Scalar/ADCE.cpp b/libclamav/c++/llvm/lib/Transforms/Scalar/ADCE.cpp new file mode 100644 index 000000000..37f383fb5 --- /dev/null +++ b/libclamav/c++/llvm/lib/Transforms/Scalar/ADCE.cpp @@ -0,0 +1,96 @@ +//===- DCE.cpp - Code to perform dead code elimination --------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the Aggressive Dead Code Elimination pass. This pass +// optimistically assumes that all instructions are dead until proven otherwise, +// allowing it to eliminate dead computations that other DCE passes do not +// catch, particularly involving loop computations. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "adce" +#include "llvm/Transforms/Scalar.h" +#include "llvm/BasicBlock.h" +#include "llvm/Instructions.h" +#include "llvm/IntrinsicInst.h" +#include "llvm/Pass.h" +#include "llvm/Support/CFG.h" +#include "llvm/Support/InstIterator.h" +#include "llvm/ADT/DepthFirstIterator.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/Statistic.h" +using namespace llvm; + +STATISTIC(NumRemoved, "Number of instructions removed"); + +namespace { + struct ADCE : public FunctionPass { + static char ID; // Pass identification, replacement for typeid + ADCE() : FunctionPass(&ID) {} + + virtual bool runOnFunction(Function& F); + + virtual void getAnalysisUsage(AnalysisUsage& AU) const { + AU.setPreservesCFG(); + } + + }; +} + +char ADCE::ID = 0; +static RegisterPass X("adce", "Aggressive Dead Code Elimination"); + +bool ADCE::runOnFunction(Function& F) { + SmallPtrSet alive; + SmallVector worklist; + + // Collect the set of "root" instructions that are known live. + for (inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I) + if (isa(I.getInstructionIterator()) || + isa(I.getInstructionIterator()) || + I->mayHaveSideEffects()) { + alive.insert(I.getInstructionIterator()); + worklist.push_back(I.getInstructionIterator()); + } + + // Propagate liveness backwards to operands. + while (!worklist.empty()) { + Instruction* curr = worklist.back(); + worklist.pop_back(); + + for (Instruction::op_iterator OI = curr->op_begin(), OE = curr->op_end(); + OI != OE; ++OI) + if (Instruction* Inst = dyn_cast(OI)) + if (alive.insert(Inst)) + worklist.push_back(Inst); + } + + // The inverse of the live set is the dead set. These are those instructions + // which have no side effects and do not influence the control flow or return + // value of the function, and may therefore be deleted safely. + // NOTE: We reuse the worklist vector here for memory efficiency. + for (inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I) + if (!alive.count(I.getInstructionIterator())) { + worklist.push_back(I.getInstructionIterator()); + I->dropAllReferences(); + } + + for (SmallVector::iterator I = worklist.begin(), + E = worklist.end(); I != E; ++I) { + NumRemoved++; + (*I)->eraseFromParent(); + } + + return !worklist.empty(); +} + +FunctionPass *llvm::createAggressiveDCEPass() { + return new ADCE(); +} diff --git a/libclamav/c++/llvm/lib/Transforms/Scalar/BasicBlockPlacement.cpp b/libclamav/c++/llvm/lib/Transforms/Scalar/BasicBlockPlacement.cpp new file mode 100644 index 000000000..54533f504 --- /dev/null +++ b/libclamav/c++/llvm/lib/Transforms/Scalar/BasicBlockPlacement.cpp @@ -0,0 +1,147 @@ +//===-- BasicBlockPlacement.cpp - Basic Block Code Layout optimization ----===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements a very simple profile guided basic block placement +// algorithm. The idea is to put frequently executed blocks together at the +// start of the function, and hopefully increase the number of fall-through +// conditional branches. If there is no profile information for a particular +// function, this pass basically orders blocks in depth-first order +// +// The algorithm implemented here is basically "Algo1" from "Profile Guided Code +// Positioning" by Pettis and Hansen, except that it uses basic block counts +// instead of edge counts. This should be improved in many ways, but is very +// simple for now. +// +// Basically we "place" the entry block, then loop over all successors in a DFO, +// placing the most frequently executed successor until we run out of blocks. I +// told you this was _extremely_ simplistic. :) This is also much slower than it +// could be. When it becomes important, this pass will be rewritten to use a +// better algorithm, and then we can worry about efficiency. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "block-placement" +#include "llvm/Analysis/ProfileInfo.h" +#include "llvm/Function.h" +#include "llvm/Pass.h" +#include "llvm/Support/CFG.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/Transforms/Scalar.h" +#include +using namespace llvm; + +STATISTIC(NumMoved, "Number of basic blocks moved"); + +namespace { + struct BlockPlacement : public FunctionPass { + static char ID; // Pass identification, replacement for typeid + BlockPlacement() : FunctionPass(&ID) {} + + virtual bool runOnFunction(Function &F); + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesCFG(); + AU.addRequired(); + //AU.addPreserved(); // Does this work? + } + private: + /// PI - The profile information that is guiding us. + /// + ProfileInfo *PI; + + /// NumMovedBlocks - Every time we move a block, increment this counter. + /// + unsigned NumMovedBlocks; + + /// PlacedBlocks - Every time we place a block, remember it so we don't get + /// into infinite loops. + std::set PlacedBlocks; + + /// InsertPos - This an iterator to the next place we want to insert a + /// block. + Function::iterator InsertPos; + + /// PlaceBlocks - Recursively place the specified blocks and any unplaced + /// successors. + void PlaceBlocks(BasicBlock *BB); + }; +} + +char BlockPlacement::ID = 0; +static RegisterPass +X("block-placement", "Profile Guided Basic Block Placement"); + +FunctionPass *llvm::createBlockPlacementPass() { return new BlockPlacement(); } + +bool BlockPlacement::runOnFunction(Function &F) { + PI = &getAnalysis(); + + NumMovedBlocks = 0; + InsertPos = F.begin(); + + // Recursively place all blocks. + PlaceBlocks(F.begin()); + + PlacedBlocks.clear(); + NumMoved += NumMovedBlocks; + return NumMovedBlocks != 0; +} + + +/// PlaceBlocks - Recursively place the specified blocks and any unplaced +/// successors. +void BlockPlacement::PlaceBlocks(BasicBlock *BB) { + assert(!PlacedBlocks.count(BB) && "Already placed this block!"); + PlacedBlocks.insert(BB); + + // Place the specified block. + if (&*InsertPos != BB) { + // Use splice to move the block into the right place. This avoids having to + // remove the block from the function then readd it, which causes a bunch of + // symbol table traffic that is entirely pointless. + Function::BasicBlockListType &Blocks = BB->getParent()->getBasicBlockList(); + Blocks.splice(InsertPos, Blocks, BB); + + ++NumMovedBlocks; + } else { + // This block is already in the right place, we don't have to do anything. + ++InsertPos; + } + + // Keep placing successors until we run out of ones to place. Note that this + // loop is very inefficient (N^2) for blocks with many successors, like switch + // statements. FIXME! + while (1) { + // Okay, now place any unplaced successors. + succ_iterator SI = succ_begin(BB), E = succ_end(BB); + + // Scan for the first unplaced successor. + for (; SI != E && PlacedBlocks.count(*SI); ++SI) + /*empty*/; + if (SI == E) return; // No more successors to place. + + double MaxExecutionCount = PI->getExecutionCount(*SI); + BasicBlock *MaxSuccessor = *SI; + + // Scan for more frequently executed successors + for (; SI != E; ++SI) + if (!PlacedBlocks.count(*SI)) { + double Count = PI->getExecutionCount(*SI); + if (Count > MaxExecutionCount || + // Prefer to not disturb the code. + (Count == MaxExecutionCount && *SI == &*InsertPos)) { + MaxExecutionCount = Count; + MaxSuccessor = *SI; + } + } + + // Now that we picked the maximally executed successor, place it. + PlaceBlocks(MaxSuccessor); + } +} diff --git a/libclamav/c++/llvm/lib/Transforms/Scalar/CMakeLists.txt b/libclamav/c++/llvm/lib/Transforms/Scalar/CMakeLists.txt new file mode 100644 index 000000000..5a92399f6 --- /dev/null +++ b/libclamav/c++/llvm/lib/Transforms/Scalar/CMakeLists.txt @@ -0,0 +1,35 @@ +add_llvm_library(LLVMScalarOpts + ABCD.cpp + ADCE.cpp + BasicBlockPlacement.cpp + CodeGenPrepare.cpp + ConstantProp.cpp + DCE.cpp + DeadStoreElimination.cpp + GEPSplitter.cpp + GVN.cpp + IndVarSimplify.cpp + InstructionCombining.cpp + JumpThreading.cpp + LICM.cpp + LoopDeletion.cpp + LoopIndexSplit.cpp + LoopRotation.cpp + LoopStrengthReduce.cpp + LoopUnrollPass.cpp + LoopUnswitch.cpp + MemCpyOptimizer.cpp + Reassociate.cpp + Reg2Mem.cpp + SCCP.cpp + SCCVN.cpp + Scalar.cpp + ScalarReplAggregates.cpp + SimplifyCFGPass.cpp + SimplifyHalfPowrLibCalls.cpp + SimplifyLibCalls.cpp + TailDuplication.cpp + TailRecursionElimination.cpp + ) + +target_link_libraries (LLVMScalarOpts LLVMTransformUtils) diff --git a/libclamav/c++/llvm/lib/Transforms/Scalar/CodeGenPrepare.cpp b/libclamav/c++/llvm/lib/Transforms/Scalar/CodeGenPrepare.cpp new file mode 100644 index 000000000..9ca90c333 --- /dev/null +++ b/libclamav/c++/llvm/lib/Transforms/Scalar/CodeGenPrepare.cpp @@ -0,0 +1,930 @@ +//===- CodeGenPrepare.cpp - Prepare a function for code generation --------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This pass munges the code in the input function to better prepare it for +// SelectionDAG-based code generation. This works around limitations in it's +// basic-block-at-a-time approach. It should eventually be removed. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "codegenprepare" +#include "llvm/Transforms/Scalar.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Function.h" +#include "llvm/InlineAsm.h" +#include "llvm/Instructions.h" +#include "llvm/IntrinsicInst.h" +#include "llvm/LLVMContext.h" +#include "llvm/Pass.h" +#include "llvm/Analysis/ProfileInfo.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetLowering.h" +#include "llvm/Transforms/Utils/AddrModeMatcher.h" +#include "llvm/Transforms/Utils/BasicBlockUtils.h" +#include "llvm/Transforms/Utils/Local.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallSet.h" +#include "llvm/Assembly/Writer.h" +#include "llvm/Support/CallSite.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/GetElementPtrTypeIterator.h" +#include "llvm/Support/PatternMatch.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; +using namespace llvm::PatternMatch; + +static cl::opt FactorCommonPreds("split-critical-paths-tweak", + cl::init(false), cl::Hidden); + +namespace { + class CodeGenPrepare : public FunctionPass { + /// TLI - Keep a pointer of a TargetLowering to consult for determining + /// transformation profitability. + const TargetLowering *TLI; + ProfileInfo *PI; + + /// BackEdges - Keep a set of all the loop back edges. + /// + SmallSet, 8> BackEdges; + public: + static char ID; // Pass identification, replacement for typeid + explicit CodeGenPrepare(const TargetLowering *tli = 0) + : FunctionPass(&ID), TLI(tli) {} + bool runOnFunction(Function &F); + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.addPreserved(); + } + + private: + bool EliminateMostlyEmptyBlocks(Function &F); + bool CanMergeBlocks(const BasicBlock *BB, const BasicBlock *DestBB) const; + void EliminateMostlyEmptyBlock(BasicBlock *BB); + bool OptimizeBlock(BasicBlock &BB); + bool OptimizeMemoryInst(Instruction *I, Value *Addr, const Type *AccessTy, + DenseMap &SunkAddrs); + bool OptimizeInlineAsmInst(Instruction *I, CallSite CS, + DenseMap &SunkAddrs); + bool MoveExtToFormExtLoad(Instruction *I); + bool OptimizeExtUses(Instruction *I); + void findLoopBackEdges(const Function &F); + }; +} + +char CodeGenPrepare::ID = 0; +static RegisterPass X("codegenprepare", + "Optimize for code generation"); + +FunctionPass *llvm::createCodeGenPreparePass(const TargetLowering *TLI) { + return new CodeGenPrepare(TLI); +} + +/// findLoopBackEdges - Do a DFS walk to find loop back edges. +/// +void CodeGenPrepare::findLoopBackEdges(const Function &F) { + SmallVector, 32> Edges; + FindFunctionBackedges(F, Edges); + + BackEdges.insert(Edges.begin(), Edges.end()); +} + + +bool CodeGenPrepare::runOnFunction(Function &F) { + bool EverMadeChange = false; + + PI = getAnalysisIfAvailable(); + // First pass, eliminate blocks that contain only PHI nodes and an + // unconditional branch. + EverMadeChange |= EliminateMostlyEmptyBlocks(F); + + // Now find loop back edges. + findLoopBackEdges(F); + + bool MadeChange = true; + while (MadeChange) { + MadeChange = false; + for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB) + MadeChange |= OptimizeBlock(*BB); + EverMadeChange |= MadeChange; + } + return EverMadeChange; +} + +/// EliminateMostlyEmptyBlocks - eliminate blocks that contain only PHI nodes, +/// debug info directives, and an unconditional branch. Passes before isel +/// (e.g. LSR/loopsimplify) often split edges in ways that are non-optimal for +/// isel. Start by eliminating these blocks so we can split them the way we +/// want them. +bool CodeGenPrepare::EliminateMostlyEmptyBlocks(Function &F) { + bool MadeChange = false; + // Note that this intentionally skips the entry block. + for (Function::iterator I = ++F.begin(), E = F.end(); I != E; ) { + BasicBlock *BB = I++; + + // If this block doesn't end with an uncond branch, ignore it. + BranchInst *BI = dyn_cast(BB->getTerminator()); + if (!BI || !BI->isUnconditional()) + continue; + + // If the instruction before the branch (skipping debug info) isn't a phi + // node, then other stuff is happening here. + BasicBlock::iterator BBI = BI; + if (BBI != BB->begin()) { + --BBI; + while (isa(BBI)) { + if (BBI == BB->begin()) + break; + --BBI; + } + if (!isa(BBI) && !isa(BBI)) + continue; + } + + // Do not break infinite loops. + BasicBlock *DestBB = BI->getSuccessor(0); + if (DestBB == BB) + continue; + + if (!CanMergeBlocks(BB, DestBB)) + continue; + + EliminateMostlyEmptyBlock(BB); + MadeChange = true; + } + return MadeChange; +} + +/// CanMergeBlocks - Return true if we can merge BB into DestBB if there is a +/// single uncond branch between them, and BB contains no other non-phi +/// instructions. +bool CodeGenPrepare::CanMergeBlocks(const BasicBlock *BB, + const BasicBlock *DestBB) const { + // We only want to eliminate blocks whose phi nodes are used by phi nodes in + // the successor. If there are more complex condition (e.g. preheaders), + // don't mess around with them. + BasicBlock::const_iterator BBI = BB->begin(); + while (const PHINode *PN = dyn_cast(BBI++)) { + for (Value::use_const_iterator UI = PN->use_begin(), E = PN->use_end(); + UI != E; ++UI) { + const Instruction *User = cast(*UI); + if (User->getParent() != DestBB || !isa(User)) + return false; + // If User is inside DestBB block and it is a PHINode then check + // incoming value. If incoming value is not from BB then this is + // a complex condition (e.g. preheaders) we want to avoid here. + if (User->getParent() == DestBB) { + if (const PHINode *UPN = dyn_cast(User)) + for (unsigned I = 0, E = UPN->getNumIncomingValues(); I != E; ++I) { + Instruction *Insn = dyn_cast(UPN->getIncomingValue(I)); + if (Insn && Insn->getParent() == BB && + Insn->getParent() != UPN->getIncomingBlock(I)) + return false; + } + } + } + } + + // If BB and DestBB contain any common predecessors, then the phi nodes in BB + // and DestBB may have conflicting incoming values for the block. If so, we + // can't merge the block. + const PHINode *DestBBPN = dyn_cast(DestBB->begin()); + if (!DestBBPN) return true; // no conflict. + + // Collect the preds of BB. + SmallPtrSet BBPreds; + if (const PHINode *BBPN = dyn_cast(BB->begin())) { + // It is faster to get preds from a PHI than with pred_iterator. + for (unsigned i = 0, e = BBPN->getNumIncomingValues(); i != e; ++i) + BBPreds.insert(BBPN->getIncomingBlock(i)); + } else { + BBPreds.insert(pred_begin(BB), pred_end(BB)); + } + + // Walk the preds of DestBB. + for (unsigned i = 0, e = DestBBPN->getNumIncomingValues(); i != e; ++i) { + BasicBlock *Pred = DestBBPN->getIncomingBlock(i); + if (BBPreds.count(Pred)) { // Common predecessor? + BBI = DestBB->begin(); + while (const PHINode *PN = dyn_cast(BBI++)) { + const Value *V1 = PN->getIncomingValueForBlock(Pred); + const Value *V2 = PN->getIncomingValueForBlock(BB); + + // If V2 is a phi node in BB, look up what the mapped value will be. + if (const PHINode *V2PN = dyn_cast(V2)) + if (V2PN->getParent() == BB) + V2 = V2PN->getIncomingValueForBlock(Pred); + + // If there is a conflict, bail out. + if (V1 != V2) return false; + } + } + } + + return true; +} + + +/// EliminateMostlyEmptyBlock - Eliminate a basic block that have only phi's and +/// an unconditional branch in it. +void CodeGenPrepare::EliminateMostlyEmptyBlock(BasicBlock *BB) { + BranchInst *BI = cast(BB->getTerminator()); + BasicBlock *DestBB = BI->getSuccessor(0); + + DEBUG(errs() << "MERGING MOSTLY EMPTY BLOCKS - BEFORE:\n" << *BB << *DestBB); + + // If the destination block has a single pred, then this is a trivial edge, + // just collapse it. + if (BasicBlock *SinglePred = DestBB->getSinglePredecessor()) { + if (SinglePred != DestBB) { + // Remember if SinglePred was the entry block of the function. If so, we + // will need to move BB back to the entry position. + bool isEntry = SinglePred == &SinglePred->getParent()->getEntryBlock(); + MergeBasicBlockIntoOnlyPred(DestBB, this); + + if (isEntry && BB != &BB->getParent()->getEntryBlock()) + BB->moveBefore(&BB->getParent()->getEntryBlock()); + + DEBUG(errs() << "AFTER:\n" << *DestBB << "\n\n\n"); + return; + } + } + + // Otherwise, we have multiple predecessors of BB. Update the PHIs in DestBB + // to handle the new incoming edges it is about to have. + PHINode *PN; + for (BasicBlock::iterator BBI = DestBB->begin(); + (PN = dyn_cast(BBI)); ++BBI) { + // Remove the incoming value for BB, and remember it. + Value *InVal = PN->removeIncomingValue(BB, false); + + // Two options: either the InVal is a phi node defined in BB or it is some + // value that dominates BB. + PHINode *InValPhi = dyn_cast(InVal); + if (InValPhi && InValPhi->getParent() == BB) { + // Add all of the input values of the input PHI as inputs of this phi. + for (unsigned i = 0, e = InValPhi->getNumIncomingValues(); i != e; ++i) + PN->addIncoming(InValPhi->getIncomingValue(i), + InValPhi->getIncomingBlock(i)); + } else { + // Otherwise, add one instance of the dominating value for each edge that + // we will be adding. + if (PHINode *BBPN = dyn_cast(BB->begin())) { + for (unsigned i = 0, e = BBPN->getNumIncomingValues(); i != e; ++i) + PN->addIncoming(InVal, BBPN->getIncomingBlock(i)); + } else { + for (pred_iterator PI = pred_begin(BB), E = pred_end(BB); PI != E; ++PI) + PN->addIncoming(InVal, *PI); + } + } + } + + // The PHIs are now updated, change everything that refers to BB to use + // DestBB and remove BB. + BB->replaceAllUsesWith(DestBB); + if (PI) { + PI->replaceAllUses(BB, DestBB); + PI->removeEdge(ProfileInfo::getEdge(BB, DestBB)); + } + BB->eraseFromParent(); + + DEBUG(errs() << "AFTER:\n" << *DestBB << "\n\n\n"); +} + + +/// SplitEdgeNicely - Split the critical edge from TI to its specified +/// successor if it will improve codegen. We only do this if the successor has +/// phi nodes (otherwise critical edges are ok). If there is already another +/// predecessor of the succ that is empty (and thus has no phi nodes), use it +/// instead of introducing a new block. +static void SplitEdgeNicely(TerminatorInst *TI, unsigned SuccNum, + SmallSet, 8> &BackEdges, + Pass *P) { + BasicBlock *TIBB = TI->getParent(); + BasicBlock *Dest = TI->getSuccessor(SuccNum); + assert(isa(Dest->begin()) && + "This should only be called if Dest has a PHI!"); + + // Do not split edges to EH landing pads. + if (InvokeInst *Invoke = dyn_cast(TI)) { + if (Invoke->getSuccessor(1) == Dest) + return; + } + + + // As a hack, never split backedges of loops. Even though the copy for any + // PHIs inserted on the backedge would be dead for exits from the loop, we + // assume that the cost of *splitting* the backedge would be too high. + if (BackEdges.count(std::make_pair(TIBB, Dest))) + return; + + if (!FactorCommonPreds) { + /// TIPHIValues - This array is lazily computed to determine the values of + /// PHIs in Dest that TI would provide. + SmallVector TIPHIValues; + + // Check to see if Dest has any blocks that can be used as a split edge for + // this terminator. + for (pred_iterator PI = pred_begin(Dest), E = pred_end(Dest); PI != E; ++PI) { + BasicBlock *Pred = *PI; + // To be usable, the pred has to end with an uncond branch to the dest. + BranchInst *PredBr = dyn_cast(Pred->getTerminator()); + if (!PredBr || !PredBr->isUnconditional()) + continue; + // Must be empty other than the branch and debug info. + BasicBlock::iterator I = Pred->begin(); + while (isa(I)) + I++; + if (dyn_cast(I) != PredBr) + continue; + // Cannot be the entry block; its label does not get emitted. + if (Pred == &(Dest->getParent()->getEntryBlock())) + continue; + + // Finally, since we know that Dest has phi nodes in it, we have to make + // sure that jumping to Pred will have the same effect as going to Dest in + // terms of PHI values. + PHINode *PN; + unsigned PHINo = 0; + bool FoundMatch = true; + for (BasicBlock::iterator I = Dest->begin(); + (PN = dyn_cast(I)); ++I, ++PHINo) { + if (PHINo == TIPHIValues.size()) + TIPHIValues.push_back(PN->getIncomingValueForBlock(TIBB)); + + // If the PHI entry doesn't work, we can't use this pred. + if (TIPHIValues[PHINo] != PN->getIncomingValueForBlock(Pred)) { + FoundMatch = false; + break; + } + } + + // If we found a workable predecessor, change TI to branch to Succ. + if (FoundMatch) { + ProfileInfo *PI = P->getAnalysisIfAvailable(); + if (PI) + PI->splitEdge(TIBB, Dest, Pred); + Dest->removePredecessor(TIBB); + TI->setSuccessor(SuccNum, Pred); + return; + } + } + + SplitCriticalEdge(TI, SuccNum, P, true); + return; + } + + PHINode *PN; + SmallVector TIPHIValues; + for (BasicBlock::iterator I = Dest->begin(); + (PN = dyn_cast(I)); ++I) + TIPHIValues.push_back(PN->getIncomingValueForBlock(TIBB)); + + SmallVector IdenticalPreds; + for (pred_iterator PI = pred_begin(Dest), E = pred_end(Dest); PI != E; ++PI) { + BasicBlock *Pred = *PI; + if (BackEdges.count(std::make_pair(Pred, Dest))) + continue; + if (PI == TIBB) + IdenticalPreds.push_back(Pred); + else { + bool Identical = true; + unsigned PHINo = 0; + for (BasicBlock::iterator I = Dest->begin(); + (PN = dyn_cast(I)); ++I, ++PHINo) + if (TIPHIValues[PHINo] != PN->getIncomingValueForBlock(Pred)) { + Identical = false; + break; + } + if (Identical) + IdenticalPreds.push_back(Pred); + } + } + + assert(!IdenticalPreds.empty()); + SplitBlockPredecessors(Dest, &IdenticalPreds[0], IdenticalPreds.size(), + ".critedge", P); +} + + +/// OptimizeNoopCopyExpression - If the specified cast instruction is a noop +/// copy (e.g. it's casting from one pointer type to another, i32->i8 on PPC), +/// sink it into user blocks to reduce the number of virtual +/// registers that must be created and coalesced. +/// +/// Return true if any changes are made. +/// +static bool OptimizeNoopCopyExpression(CastInst *CI, const TargetLowering &TLI){ + // If this is a noop copy, + EVT SrcVT = TLI.getValueType(CI->getOperand(0)->getType()); + EVT DstVT = TLI.getValueType(CI->getType()); + + // This is an fp<->int conversion? + if (SrcVT.isInteger() != DstVT.isInteger()) + return false; + + // If this is an extension, it will be a zero or sign extension, which + // isn't a noop. + if (SrcVT.bitsLT(DstVT)) return false; + + // If these values will be promoted, find out what they will be promoted + // to. This helps us consider truncates on PPC as noop copies when they + // are. + if (TLI.getTypeAction(CI->getContext(), SrcVT) == TargetLowering::Promote) + SrcVT = TLI.getTypeToTransformTo(CI->getContext(), SrcVT); + if (TLI.getTypeAction(CI->getContext(), DstVT) == TargetLowering::Promote) + DstVT = TLI.getTypeToTransformTo(CI->getContext(), DstVT); + + // If, after promotion, these are the same types, this is a noop copy. + if (SrcVT != DstVT) + return false; + + BasicBlock *DefBB = CI->getParent(); + + /// InsertedCasts - Only insert a cast in each block once. + DenseMap InsertedCasts; + + bool MadeChange = false; + for (Value::use_iterator UI = CI->use_begin(), E = CI->use_end(); + UI != E; ) { + Use &TheUse = UI.getUse(); + Instruction *User = cast(*UI); + + // Figure out which BB this cast is used in. For PHI's this is the + // appropriate predecessor block. + BasicBlock *UserBB = User->getParent(); + if (PHINode *PN = dyn_cast(User)) { + UserBB = PN->getIncomingBlock(UI); + } + + // Preincrement use iterator so we don't invalidate it. + ++UI; + + // If this user is in the same block as the cast, don't change the cast. + if (UserBB == DefBB) continue; + + // If we have already inserted a cast into this block, use it. + CastInst *&InsertedCast = InsertedCasts[UserBB]; + + if (!InsertedCast) { + BasicBlock::iterator InsertPt = UserBB->getFirstNonPHI(); + + InsertedCast = + CastInst::Create(CI->getOpcode(), CI->getOperand(0), CI->getType(), "", + InsertPt); + MadeChange = true; + } + + // Replace a use of the cast with a use of the new cast. + TheUse = InsertedCast; + } + + // If we removed all uses, nuke the cast. + if (CI->use_empty()) { + CI->eraseFromParent(); + MadeChange = true; + } + + return MadeChange; +} + +/// OptimizeCmpExpression - sink the given CmpInst into user blocks to reduce +/// the number of virtual registers that must be created and coalesced. This is +/// a clear win except on targets with multiple condition code registers +/// (PowerPC), where it might lose; some adjustment may be wanted there. +/// +/// Return true if any changes are made. +static bool OptimizeCmpExpression(CmpInst *CI) { + BasicBlock *DefBB = CI->getParent(); + + /// InsertedCmp - Only insert a cmp in each block once. + DenseMap InsertedCmps; + + bool MadeChange = false; + for (Value::use_iterator UI = CI->use_begin(), E = CI->use_end(); + UI != E; ) { + Use &TheUse = UI.getUse(); + Instruction *User = cast(*UI); + + // Preincrement use iterator so we don't invalidate it. + ++UI; + + // Don't bother for PHI nodes. + if (isa(User)) + continue; + + // Figure out which BB this cmp is used in. + BasicBlock *UserBB = User->getParent(); + + // If this user is in the same block as the cmp, don't change the cmp. + if (UserBB == DefBB) continue; + + // If we have already inserted a cmp into this block, use it. + CmpInst *&InsertedCmp = InsertedCmps[UserBB]; + + if (!InsertedCmp) { + BasicBlock::iterator InsertPt = UserBB->getFirstNonPHI(); + + InsertedCmp = + CmpInst::Create(CI->getOpcode(), + CI->getPredicate(), CI->getOperand(0), + CI->getOperand(1), "", InsertPt); + MadeChange = true; + } + + // Replace a use of the cmp with a use of the new cmp. + TheUse = InsertedCmp; + } + + // If we removed all uses, nuke the cmp. + if (CI->use_empty()) + CI->eraseFromParent(); + + return MadeChange; +} + +//===----------------------------------------------------------------------===// +// Memory Optimization +//===----------------------------------------------------------------------===// + +/// IsNonLocalValue - Return true if the specified values are defined in a +/// different basic block than BB. +static bool IsNonLocalValue(Value *V, BasicBlock *BB) { + if (Instruction *I = dyn_cast(V)) + return I->getParent() != BB; + return false; +} + +/// OptimizeMemoryInst - Load and Store Instructions have often have +/// addressing modes that can do significant amounts of computation. As such, +/// instruction selection will try to get the load or store to do as much +/// computation as possible for the program. The problem is that isel can only +/// see within a single block. As such, we sink as much legal addressing mode +/// stuff into the block as possible. +/// +/// This method is used to optimize both load/store and inline asms with memory +/// operands. +bool CodeGenPrepare::OptimizeMemoryInst(Instruction *MemoryInst, Value *Addr, + const Type *AccessTy, + DenseMap &SunkAddrs) { + // Figure out what addressing mode will be built up for this operation. + SmallVector AddrModeInsts; + ExtAddrMode AddrMode = AddressingModeMatcher::Match(Addr, AccessTy,MemoryInst, + AddrModeInsts, *TLI); + + // Check to see if any of the instructions supersumed by this addr mode are + // non-local to I's BB. + bool AnyNonLocal = false; + for (unsigned i = 0, e = AddrModeInsts.size(); i != e; ++i) { + if (IsNonLocalValue(AddrModeInsts[i], MemoryInst->getParent())) { + AnyNonLocal = true; + break; + } + } + + // If all the instructions matched are already in this BB, don't do anything. + if (!AnyNonLocal) { + DEBUG(errs() << "CGP: Found local addrmode: " << AddrMode << "\n"); + return false; + } + + // Insert this computation right after this user. Since our caller is + // scanning from the top of the BB to the bottom, reuse of the expr are + // guaranteed to happen later. + BasicBlock::iterator InsertPt = MemoryInst; + + // Now that we determined the addressing expression we want to use and know + // that we have to sink it into this block. Check to see if we have already + // done this for some other load/store instr in this block. If so, reuse the + // computation. + Value *&SunkAddr = SunkAddrs[Addr]; + if (SunkAddr) { + DEBUG(errs() << "CGP: Reusing nonlocal addrmode: " << AddrMode << " for " + << *MemoryInst); + if (SunkAddr->getType() != Addr->getType()) + SunkAddr = new BitCastInst(SunkAddr, Addr->getType(), "tmp", InsertPt); + } else { + DEBUG(errs() << "CGP: SINKING nonlocal addrmode: " << AddrMode << " for " + << *MemoryInst); + const Type *IntPtrTy = + TLI->getTargetData()->getIntPtrType(AccessTy->getContext()); + + Value *Result = 0; + // Start with the scale value. + if (AddrMode.Scale) { + Value *V = AddrMode.ScaledReg; + if (V->getType() == IntPtrTy) { + // done. + } else if (isa(V->getType())) { + V = new PtrToIntInst(V, IntPtrTy, "sunkaddr", InsertPt); + } else if (cast(IntPtrTy)->getBitWidth() < + cast(V->getType())->getBitWidth()) { + V = new TruncInst(V, IntPtrTy, "sunkaddr", InsertPt); + } else { + V = new SExtInst(V, IntPtrTy, "sunkaddr", InsertPt); + } + if (AddrMode.Scale != 1) + V = BinaryOperator::CreateMul(V, ConstantInt::get(IntPtrTy, + AddrMode.Scale), + "sunkaddr", InsertPt); + Result = V; + } + + // Add in the base register. + if (AddrMode.BaseReg) { + Value *V = AddrMode.BaseReg; + if (isa(V->getType())) + V = new PtrToIntInst(V, IntPtrTy, "sunkaddr", InsertPt); + if (V->getType() != IntPtrTy) + V = CastInst::CreateIntegerCast(V, IntPtrTy, /*isSigned=*/true, + "sunkaddr", InsertPt); + if (Result) + Result = BinaryOperator::CreateAdd(Result, V, "sunkaddr", InsertPt); + else + Result = V; + } + + // Add in the BaseGV if present. + if (AddrMode.BaseGV) { + Value *V = new PtrToIntInst(AddrMode.BaseGV, IntPtrTy, "sunkaddr", + InsertPt); + if (Result) + Result = BinaryOperator::CreateAdd(Result, V, "sunkaddr", InsertPt); + else + Result = V; + } + + // Add in the Base Offset if present. + if (AddrMode.BaseOffs) { + Value *V = ConstantInt::get(IntPtrTy, AddrMode.BaseOffs); + if (Result) + Result = BinaryOperator::CreateAdd(Result, V, "sunkaddr", InsertPt); + else + Result = V; + } + + if (Result == 0) + SunkAddr = Constant::getNullValue(Addr->getType()); + else + SunkAddr = new IntToPtrInst(Result, Addr->getType(), "sunkaddr",InsertPt); + } + + MemoryInst->replaceUsesOfWith(Addr, SunkAddr); + + if (Addr->use_empty()) + RecursivelyDeleteTriviallyDeadInstructions(Addr); + return true; +} + +/// OptimizeInlineAsmInst - If there are any memory operands, use +/// OptimizeMemoryInst to sink their address computing into the block when +/// possible / profitable. +bool CodeGenPrepare::OptimizeInlineAsmInst(Instruction *I, CallSite CS, + DenseMap &SunkAddrs) { + bool MadeChange = false; + InlineAsm *IA = cast(CS.getCalledValue()); + + // Do a prepass over the constraints, canonicalizing them, and building up the + // ConstraintOperands list. + std::vector + ConstraintInfos = IA->ParseConstraints(); + + /// ConstraintOperands - Information about all of the constraints. + std::vector ConstraintOperands; + unsigned ArgNo = 0; // ArgNo - The argument of the CallInst. + for (unsigned i = 0, e = ConstraintInfos.size(); i != e; ++i) { + ConstraintOperands. + push_back(TargetLowering::AsmOperandInfo(ConstraintInfos[i])); + TargetLowering::AsmOperandInfo &OpInfo = ConstraintOperands.back(); + + // Compute the value type for each operand. + switch (OpInfo.Type) { + case InlineAsm::isOutput: + if (OpInfo.isIndirect) + OpInfo.CallOperandVal = CS.getArgument(ArgNo++); + break; + case InlineAsm::isInput: + OpInfo.CallOperandVal = CS.getArgument(ArgNo++); + break; + case InlineAsm::isClobber: + // Nothing to do. + break; + } + + // Compute the constraint code and ConstraintType to use. + TLI->ComputeConstraintToUse(OpInfo, SDValue(), + OpInfo.ConstraintType == TargetLowering::C_Memory); + + if (OpInfo.ConstraintType == TargetLowering::C_Memory && + OpInfo.isIndirect) { + Value *OpVal = OpInfo.CallOperandVal; + MadeChange |= OptimizeMemoryInst(I, OpVal, OpVal->getType(), SunkAddrs); + } + } + + return MadeChange; +} + +/// MoveExtToFormExtLoad - Move a zext or sext fed by a load into the same +/// basic block as the load, unless conditions are unfavorable. This allows +/// SelectionDAG to fold the extend into the load. +/// +bool CodeGenPrepare::MoveExtToFormExtLoad(Instruction *I) { + // Look for a load being extended. + LoadInst *LI = dyn_cast(I->getOperand(0)); + if (!LI) return false; + + // If they're already in the same block, there's nothing to do. + if (LI->getParent() == I->getParent()) + return false; + + // If the load has other users and the truncate is not free, this probably + // isn't worthwhile. + if (!LI->hasOneUse() && + TLI && !TLI->isTruncateFree(I->getType(), LI->getType())) + return false; + + // Check whether the target supports casts folded into loads. + unsigned LType; + if (isa(I)) + LType = ISD::ZEXTLOAD; + else { + assert(isa(I) && "Unexpected ext type!"); + LType = ISD::SEXTLOAD; + } + if (TLI && !TLI->isLoadExtLegal(LType, TLI->getValueType(LI->getType()))) + return false; + + // Move the extend into the same block as the load, so that SelectionDAG + // can fold it. + I->removeFromParent(); + I->insertAfter(LI); + return true; +} + +bool CodeGenPrepare::OptimizeExtUses(Instruction *I) { + BasicBlock *DefBB = I->getParent(); + + // If both result of the {s|z}xt and its source are live out, rewrite all + // other uses of the source with result of extension. + Value *Src = I->getOperand(0); + if (Src->hasOneUse()) + return false; + + // Only do this xform if truncating is free. + if (TLI && !TLI->isTruncateFree(I->getType(), Src->getType())) + return false; + + // Only safe to perform the optimization if the source is also defined in + // this block. + if (!isa(Src) || DefBB != cast(Src)->getParent()) + return false; + + bool DefIsLiveOut = false; + for (Value::use_iterator UI = I->use_begin(), E = I->use_end(); + UI != E; ++UI) { + Instruction *User = cast(*UI); + + // Figure out which BB this ext is used in. + BasicBlock *UserBB = User->getParent(); + if (UserBB == DefBB) continue; + DefIsLiveOut = true; + break; + } + if (!DefIsLiveOut) + return false; + + // Make sure non of the uses are PHI nodes. + for (Value::use_iterator UI = Src->use_begin(), E = Src->use_end(); + UI != E; ++UI) { + Instruction *User = cast(*UI); + BasicBlock *UserBB = User->getParent(); + if (UserBB == DefBB) continue; + // Be conservative. We don't want this xform to end up introducing + // reloads just before load / store instructions. + if (isa(User) || isa(User) || isa(User)) + return false; + } + + // InsertedTruncs - Only insert one trunc in each block once. + DenseMap InsertedTruncs; + + bool MadeChange = false; + for (Value::use_iterator UI = Src->use_begin(), E = Src->use_end(); + UI != E; ++UI) { + Use &TheUse = UI.getUse(); + Instruction *User = cast(*UI); + + // Figure out which BB this ext is used in. + BasicBlock *UserBB = User->getParent(); + if (UserBB == DefBB) continue; + + // Both src and def are live in this block. Rewrite the use. + Instruction *&InsertedTrunc = InsertedTruncs[UserBB]; + + if (!InsertedTrunc) { + BasicBlock::iterator InsertPt = UserBB->getFirstNonPHI(); + + InsertedTrunc = new TruncInst(I, Src->getType(), "", InsertPt); + } + + // Replace a use of the {s|z}ext source with a use of the result. + TheUse = InsertedTrunc; + + MadeChange = true; + } + + return MadeChange; +} + +// In this pass we look for GEP and cast instructions that are used +// across basic blocks and rewrite them to improve basic-block-at-a-time +// selection. +bool CodeGenPrepare::OptimizeBlock(BasicBlock &BB) { + bool MadeChange = false; + + // Split all critical edges where the dest block has a PHI. + TerminatorInst *BBTI = BB.getTerminator(); + if (BBTI->getNumSuccessors() > 1 && !isa(BBTI)) { + for (unsigned i = 0, e = BBTI->getNumSuccessors(); i != e; ++i) { + BasicBlock *SuccBB = BBTI->getSuccessor(i); + if (isa(SuccBB->begin()) && isCriticalEdge(BBTI, i, true)) + SplitEdgeNicely(BBTI, i, BackEdges, this); + } + } + + // Keep track of non-local addresses that have been sunk into this block. + // This allows us to avoid inserting duplicate code for blocks with multiple + // load/stores of the same address. + DenseMap SunkAddrs; + + for (BasicBlock::iterator BBI = BB.begin(), E = BB.end(); BBI != E; ) { + Instruction *I = BBI++; + + if (CastInst *CI = dyn_cast(I)) { + // If the source of the cast is a constant, then this should have + // already been constant folded. The only reason NOT to constant fold + // it is if something (e.g. LSR) was careful to place the constant + // evaluation in a block other than then one that uses it (e.g. to hoist + // the address of globals out of a loop). If this is the case, we don't + // want to forward-subst the cast. + if (isa(CI->getOperand(0))) + continue; + + bool Change = false; + if (TLI) { + Change = OptimizeNoopCopyExpression(CI, *TLI); + MadeChange |= Change; + } + + if (!Change && (isa(I) || isa(I))) { + MadeChange |= MoveExtToFormExtLoad(I); + MadeChange |= OptimizeExtUses(I); + } + } else if (CmpInst *CI = dyn_cast(I)) { + MadeChange |= OptimizeCmpExpression(CI); + } else if (LoadInst *LI = dyn_cast(I)) { + if (TLI) + MadeChange |= OptimizeMemoryInst(I, I->getOperand(0), LI->getType(), + SunkAddrs); + } else if (StoreInst *SI = dyn_cast(I)) { + if (TLI) + MadeChange |= OptimizeMemoryInst(I, SI->getOperand(1), + SI->getOperand(0)->getType(), + SunkAddrs); + } else if (GetElementPtrInst *GEPI = dyn_cast(I)) { + if (GEPI->hasAllZeroIndices()) { + /// The GEP operand must be a pointer, so must its result -> BitCast + Instruction *NC = new BitCastInst(GEPI->getOperand(0), GEPI->getType(), + GEPI->getName(), GEPI); + GEPI->replaceAllUsesWith(NC); + GEPI->eraseFromParent(); + MadeChange = true; + BBI = NC; + } + } else if (CallInst *CI = dyn_cast(I)) { + // If we found an inline asm expession, and if the target knows how to + // lower it to normal LLVM code, do so now. + if (TLI && isa(CI->getCalledValue())) { + if (TLI->ExpandInlineAsm(CI)) { + BBI = BB.begin(); + // Avoid processing instructions out of order, which could cause + // reuse before a value is defined. + SunkAddrs.clear(); + } else + // Sink address computing for memory operands into the block. + MadeChange |= OptimizeInlineAsmInst(I, &(*CI), SunkAddrs); + } + } + } + + return MadeChange; +} diff --git a/libclamav/c++/llvm/lib/Transforms/Scalar/ConstantProp.cpp b/libclamav/c++/llvm/lib/Transforms/Scalar/ConstantProp.cpp new file mode 100644 index 000000000..ea2081357 --- /dev/null +++ b/libclamav/c++/llvm/lib/Transforms/Scalar/ConstantProp.cpp @@ -0,0 +1,89 @@ +//===- ConstantProp.cpp - Code to perform Simple Constant Propagation -----===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements constant propagation and merging: +// +// Specifically, this: +// * Converts instructions like "add int 1, 2" into 3 +// +// Notice that: +// * This pass has a habit of making definitions be dead. It is a good idea +// to run a DIE pass sometime after running this pass. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "constprop" +#include "llvm/Transforms/Scalar.h" +#include "llvm/Analysis/ConstantFolding.h" +#include "llvm/Constant.h" +#include "llvm/Instruction.h" +#include "llvm/Pass.h" +#include "llvm/Support/InstIterator.h" +#include "llvm/ADT/Statistic.h" +#include +using namespace llvm; + +STATISTIC(NumInstKilled, "Number of instructions killed"); + +namespace { + struct ConstantPropagation : public FunctionPass { + static char ID; // Pass identification, replacement for typeid + ConstantPropagation() : FunctionPass(&ID) {} + + bool runOnFunction(Function &F); + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesCFG(); + } + }; +} + +char ConstantPropagation::ID = 0; +static RegisterPass +X("constprop", "Simple constant propagation"); + +FunctionPass *llvm::createConstantPropagationPass() { + return new ConstantPropagation(); +} + + +bool ConstantPropagation::runOnFunction(Function &F) { + // Initialize the worklist to all of the instructions ready to process... + std::set WorkList; + for(inst_iterator i = inst_begin(F), e = inst_end(F); i != e; ++i) { + WorkList.insert(&*i); + } + bool Changed = false; + + while (!WorkList.empty()) { + Instruction *I = *WorkList.begin(); + WorkList.erase(WorkList.begin()); // Get an element from the worklist... + + if (!I->use_empty()) // Don't muck with dead instructions... + if (Constant *C = ConstantFoldInstruction(I)) { + // Add all of the users of this instruction to the worklist, they might + // be constant propagatable now... + for (Value::use_iterator UI = I->use_begin(), UE = I->use_end(); + UI != UE; ++UI) + WorkList.insert(cast(*UI)); + + // Replace all of the uses of a variable with uses of the constant. + I->replaceAllUsesWith(C); + + // Remove the dead instruction. + WorkList.erase(I); + I->eraseFromParent(); + + // We made a change to the function... + Changed = true; + ++NumInstKilled; + } + } + return Changed; +} diff --git a/libclamav/c++/llvm/lib/Transforms/Scalar/DCE.cpp b/libclamav/c++/llvm/lib/Transforms/Scalar/DCE.cpp new file mode 100644 index 000000000..39940c35d --- /dev/null +++ b/libclamav/c++/llvm/lib/Transforms/Scalar/DCE.cpp @@ -0,0 +1,132 @@ +//===- DCE.cpp - Code to perform dead code elimination --------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements dead inst elimination and dead code elimination. +// +// Dead Inst Elimination performs a single pass over the function removing +// instructions that are obviously dead. Dead Code Elimination is similar, but +// it rechecks instructions that were used by removed instructions to see if +// they are newly dead. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "dce" +#include "llvm/Transforms/Scalar.h" +#include "llvm/Transforms/Utils/Local.h" +#include "llvm/Instruction.h" +#include "llvm/Pass.h" +#include "llvm/Support/InstIterator.h" +#include "llvm/ADT/Statistic.h" +#include +using namespace llvm; + +STATISTIC(DIEEliminated, "Number of insts removed by DIE pass"); +STATISTIC(DCEEliminated, "Number of insts removed"); + +namespace { + //===--------------------------------------------------------------------===// + // DeadInstElimination pass implementation + // + struct DeadInstElimination : public BasicBlockPass { + static char ID; // Pass identification, replacement for typeid + DeadInstElimination() : BasicBlockPass(&ID) {} + virtual bool runOnBasicBlock(BasicBlock &BB) { + bool Changed = false; + for (BasicBlock::iterator DI = BB.begin(); DI != BB.end(); ) { + Instruction *Inst = DI++; + if (isInstructionTriviallyDead(Inst)) { + Inst->eraseFromParent(); + Changed = true; + ++DIEEliminated; + } + } + return Changed; + } + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesCFG(); + } + }; +} + +char DeadInstElimination::ID = 0; +static RegisterPass +X("die", "Dead Instruction Elimination"); + +Pass *llvm::createDeadInstEliminationPass() { + return new DeadInstElimination(); +} + + +namespace { + //===--------------------------------------------------------------------===// + // DeadCodeElimination pass implementation + // + struct DCE : public FunctionPass { + static char ID; // Pass identification, replacement for typeid + DCE() : FunctionPass(&ID) {} + + virtual bool runOnFunction(Function &F); + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesCFG(); + } + }; +} + +char DCE::ID = 0; +static RegisterPass Y("dce", "Dead Code Elimination"); + +bool DCE::runOnFunction(Function &F) { + // Start out with all of the instructions in the worklist... + std::vector WorkList; + for (inst_iterator i = inst_begin(F), e = inst_end(F); i != e; ++i) + WorkList.push_back(&*i); + + // Loop over the worklist finding instructions that are dead. If they are + // dead make them drop all of their uses, making other instructions + // potentially dead, and work until the worklist is empty. + // + bool MadeChange = false; + while (!WorkList.empty()) { + Instruction *I = WorkList.back(); + WorkList.pop_back(); + + if (isInstructionTriviallyDead(I)) { // If the instruction is dead. + // Loop over all of the values that the instruction uses, if there are + // instructions being used, add them to the worklist, because they might + // go dead after this one is removed. + // + for (User::op_iterator OI = I->op_begin(), E = I->op_end(); OI != E; ++OI) + if (Instruction *Used = dyn_cast(*OI)) + WorkList.push_back(Used); + + // Remove the instruction. + I->eraseFromParent(); + + // Remove the instruction from the worklist if it still exists in it. + for (std::vector::iterator WI = WorkList.begin(); + WI != WorkList.end(); ) { + if (*WI == I) + WI = WorkList.erase(WI); + else + ++WI; + } + + MadeChange = true; + ++DCEEliminated; + } + } + return MadeChange; +} + +FunctionPass *llvm::createDeadCodeEliminationPass() { + return new DCE(); +} + diff --git a/libclamav/c++/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp b/libclamav/c++/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp new file mode 100644 index 000000000..b0988b52a --- /dev/null +++ b/libclamav/c++/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp @@ -0,0 +1,575 @@ +//===- DeadStoreElimination.cpp - Fast Dead Store Elimination -------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements a trivial dead store elimination that only considers +// basic-block local redundant stores. +// +// FIXME: This should eventually be extended to be a post-dominator tree +// traversal. Doing so would be pretty trivial. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "dse" +#include "llvm/Transforms/Scalar.h" +#include "llvm/Constants.h" +#include "llvm/Function.h" +#include "llvm/Instructions.h" +#include "llvm/IntrinsicInst.h" +#include "llvm/Pass.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/Analysis/Dominators.h" +#include "llvm/Analysis/MemoryBuiltins.h" +#include "llvm/Analysis/MemoryDependenceAnalysis.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Transforms/Utils/Local.h" +using namespace llvm; + +STATISTIC(NumFastStores, "Number of stores deleted"); +STATISTIC(NumFastOther , "Number of other instrs removed"); + +namespace { + struct DSE : public FunctionPass { + TargetData *TD; + + static char ID; // Pass identification, replacement for typeid + DSE() : FunctionPass(&ID) {} + + virtual bool runOnFunction(Function &F) { + bool Changed = false; + for (Function::iterator I = F.begin(), E = F.end(); I != E; ++I) + Changed |= runOnBasicBlock(*I); + return Changed; + } + + bool runOnBasicBlock(BasicBlock &BB); + bool handleFreeWithNonTrivialDependency(Instruction *F, MemDepResult Dep); + bool handleEndBlock(BasicBlock &BB); + bool RemoveUndeadPointers(Value* Ptr, uint64_t killPointerSize, + BasicBlock::iterator& BBI, + SmallPtrSet& deadPointers); + void DeleteDeadInstruction(Instruction *I, + SmallPtrSet *deadPointers = 0); + + + // getAnalysisUsage - We require post dominance frontiers (aka Control + // Dependence Graph) + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesCFG(); + AU.addRequired(); + AU.addRequired(); + AU.addRequired(); + AU.addPreserved(); + AU.addPreserved(); + AU.addPreserved(); + } + }; +} + +char DSE::ID = 0; +static RegisterPass X("dse", "Dead Store Elimination"); + +FunctionPass *llvm::createDeadStoreEliminationPass() { return new DSE(); } + +/// doesClobberMemory - Does this instruction clobber (write without reading) +/// some memory? +static bool doesClobberMemory(Instruction *I) { + if (isa(I)) + return true; + if (IntrinsicInst *II = dyn_cast(I)) { + switch (II->getIntrinsicID()) { + default: return false; + case Intrinsic::memset: case Intrinsic::memmove: case Intrinsic::memcpy: + case Intrinsic::init_trampoline: case Intrinsic::lifetime_end: return true; + } + } + return false; +} + +/// isElidable - If the value of this instruction and the memory it writes to is +/// unused, may we delete this instrtction? +static bool isElidable(Instruction *I) { + assert(doesClobberMemory(I)); + if (IntrinsicInst *II = dyn_cast(I)) + return II->getIntrinsicID() != Intrinsic::lifetime_end; + if (StoreInst *SI = dyn_cast(I)) + return !SI->isVolatile(); + return true; +} + +/// getPointerOperand - Return the pointer that is being clobbered. +static Value *getPointerOperand(Instruction *I) { + assert(doesClobberMemory(I)); + if (StoreInst *SI = dyn_cast(I)) + return SI->getPointerOperand(); + if (MemIntrinsic *MI = dyn_cast(I)) + return MI->getOperand(1); + IntrinsicInst *II = cast(I); + switch (II->getIntrinsicID()) { + default: + assert(false && "Unexpected intrinsic!"); + case Intrinsic::init_trampoline: + return II->getOperand(1); + case Intrinsic::lifetime_end: + return II->getOperand(2); + } +} + +/// getStoreSize - Return the length in bytes of the write by the clobbering +/// instruction. If variable or unknown, returns -1. +static unsigned getStoreSize(Instruction *I, const TargetData *TD) { + assert(doesClobberMemory(I)); + if (StoreInst *SI = dyn_cast(I)) { + if (!TD) return -1u; + return TD->getTypeStoreSize(SI->getOperand(0)->getType()); + } + + Value *Len; + if (MemIntrinsic *MI = dyn_cast(I)) { + Len = MI->getLength(); + } else { + IntrinsicInst *II = cast(I); + switch (II->getIntrinsicID()) { + default: + assert(false && "Unexpected intrinsic!"); + case Intrinsic::init_trampoline: + return -1u; + case Intrinsic::lifetime_end: + Len = II->getOperand(1); + break; + } + } + if (ConstantInt *LenCI = dyn_cast(Len)) + if (!LenCI->isAllOnesValue()) + return LenCI->getZExtValue(); + return -1u; +} + +/// isStoreAtLeastAsWideAs - Return true if the size of the store in I1 is +/// greater than or equal to the store in I2. This returns false if we don't +/// know. +/// +static bool isStoreAtLeastAsWideAs(Instruction *I1, Instruction *I2, + const TargetData *TD) { + const Type *I1Ty = getPointerOperand(I1)->getType(); + const Type *I2Ty = getPointerOperand(I2)->getType(); + + // Exactly the same type, must have exactly the same size. + if (I1Ty == I2Ty) return true; + + int I1Size = getStoreSize(I1, TD); + int I2Size = getStoreSize(I2, TD); + + return I1Size != -1 && I2Size != -1 && I1Size >= I2Size; +} + +bool DSE::runOnBasicBlock(BasicBlock &BB) { + MemoryDependenceAnalysis& MD = getAnalysis(); + TD = getAnalysisIfAvailable(); + + bool MadeChange = false; + + // Do a top-down walk on the BB. + for (BasicBlock::iterator BBI = BB.begin(), BBE = BB.end(); BBI != BBE; ) { + Instruction *Inst = BBI++; + + // If we find a store or a free, get its memory dependence. + if (!doesClobberMemory(Inst) && !isFreeCall(Inst)) + continue; + + MemDepResult InstDep = MD.getDependency(Inst); + + // Ignore non-local stores. + // FIXME: cross-block DSE would be fun. :) + if (InstDep.isNonLocal()) continue; + + // Handle frees whose dependencies are non-trivial. + if (isFreeCall(Inst)) { + MadeChange |= handleFreeWithNonTrivialDependency(Inst, InstDep); + continue; + } + + // If not a definite must-alias dependency, ignore it. + if (!InstDep.isDef()) + continue; + + // If this is a store-store dependence, then the previous store is dead so + // long as this store is at least as big as it. + if (doesClobberMemory(InstDep.getInst())) { + Instruction *DepStore = InstDep.getInst(); + if (isStoreAtLeastAsWideAs(Inst, DepStore, TD) && + isElidable(DepStore)) { + // Delete the store and now-dead instructions that feed it. + DeleteDeadInstruction(DepStore); + NumFastStores++; + MadeChange = true; + + // DeleteDeadInstruction can delete the current instruction in loop + // cases, reset BBI. + BBI = Inst; + if (BBI != BB.begin()) + --BBI; + continue; + } + } + + if (!isElidable(Inst)) + continue; + + // If we're storing the same value back to a pointer that we just + // loaded from, then the store can be removed. + if (StoreInst *SI = dyn_cast(Inst)) { + if (LoadInst *DepLoad = dyn_cast(InstDep.getInst())) { + if (SI->getPointerOperand() == DepLoad->getPointerOperand() && + SI->getOperand(0) == DepLoad) { + // DeleteDeadInstruction can delete the current instruction. Save BBI + // in case we need it. + WeakVH NextInst(BBI); + + DeleteDeadInstruction(SI); + + if (NextInst == 0) // Next instruction deleted. + BBI = BB.begin(); + else if (BBI != BB.begin()) // Revisit this instruction if possible. + --BBI; + NumFastStores++; + MadeChange = true; + continue; + } + } + } + + // If this is a lifetime end marker, we can throw away the store. + if (IntrinsicInst *II = dyn_cast(InstDep.getInst())) { + if (II->getIntrinsicID() == Intrinsic::lifetime_end) { + // Delete the store and now-dead instructions that feed it. + // DeleteDeadInstruction can delete the current instruction. Save BBI + // in case we need it. + WeakVH NextInst(BBI); + + DeleteDeadInstruction(Inst); + + if (NextInst == 0) // Next instruction deleted. + BBI = BB.begin(); + else if (BBI != BB.begin()) // Revisit this instruction if possible. + --BBI; + NumFastStores++; + MadeChange = true; + continue; + } + } + } + + // If this block ends in a return, unwind, or unreachable, all allocas are + // dead at its end, which means stores to them are also dead. + if (BB.getTerminator()->getNumSuccessors() == 0) + MadeChange |= handleEndBlock(BB); + + return MadeChange; +} + +/// handleFreeWithNonTrivialDependency - Handle frees of entire structures whose +/// dependency is a store to a field of that structure. +bool DSE::handleFreeWithNonTrivialDependency(Instruction *F, MemDepResult Dep) { + AliasAnalysis &AA = getAnalysis(); + + Instruction *Dependency = Dep.getInst(); + if (!Dependency || !doesClobberMemory(Dependency) || !isElidable(Dependency)) + return false; + + Value *DepPointer = getPointerOperand(Dependency)->getUnderlyingObject(); + + // Check for aliasing. + if (AA.alias(F->getOperand(1), 1, DepPointer, 1) != + AliasAnalysis::MustAlias) + return false; + + // DCE instructions only used to calculate that store + DeleteDeadInstruction(Dependency); + NumFastStores++; + return true; +} + +/// handleEndBlock - Remove dead stores to stack-allocated locations in the +/// function end block. Ex: +/// %A = alloca i32 +/// ... +/// store i32 1, i32* %A +/// ret void +bool DSE::handleEndBlock(BasicBlock &BB) { + AliasAnalysis &AA = getAnalysis(); + + bool MadeChange = false; + + // Pointers alloca'd in this function are dead in the end block + SmallPtrSet deadPointers; + + // Find all of the alloca'd pointers in the entry block. + BasicBlock *Entry = BB.getParent()->begin(); + for (BasicBlock::iterator I = Entry->begin(), E = Entry->end(); I != E; ++I) + if (AllocaInst *AI = dyn_cast(I)) + deadPointers.insert(AI); + + // Treat byval arguments the same, stores to them are dead at the end of the + // function. + for (Function::arg_iterator AI = BB.getParent()->arg_begin(), + AE = BB.getParent()->arg_end(); AI != AE; ++AI) + if (AI->hasByValAttr()) + deadPointers.insert(AI); + + // Scan the basic block backwards + for (BasicBlock::iterator BBI = BB.end(); BBI != BB.begin(); ){ + --BBI; + + // If we find a store whose pointer is dead. + if (doesClobberMemory(BBI)) { + if (isElidable(BBI)) { + // See through pointer-to-pointer bitcasts + Value *pointerOperand = getPointerOperand(BBI)->getUnderlyingObject(); + + // Alloca'd pointers or byval arguments (which are functionally like + // alloca's) are valid candidates for removal. + if (deadPointers.count(pointerOperand)) { + // DCE instructions only used to calculate that store. + Instruction *Dead = BBI; + BBI++; + DeleteDeadInstruction(Dead, &deadPointers); + NumFastStores++; + MadeChange = true; + continue; + } + } + + // Because a memcpy or memmove is also a load, we can't skip it if we + // didn't remove it. + if (!isa(BBI)) + continue; + } + + Value* killPointer = 0; + uint64_t killPointerSize = ~0UL; + + // If we encounter a use of the pointer, it is no longer considered dead + if (LoadInst *L = dyn_cast(BBI)) { + // However, if this load is unused and not volatile, we can go ahead and + // remove it, and not have to worry about it making our pointer undead! + if (L->use_empty() && !L->isVolatile()) { + BBI++; + DeleteDeadInstruction(L, &deadPointers); + NumFastOther++; + MadeChange = true; + continue; + } + + killPointer = L->getPointerOperand(); + } else if (VAArgInst* V = dyn_cast(BBI)) { + killPointer = V->getOperand(0); + } else if (isa(BBI) && + isa(cast(BBI)->getLength())) { + killPointer = cast(BBI)->getSource(); + killPointerSize = cast( + cast(BBI)->getLength())->getZExtValue(); + } else if (AllocaInst* A = dyn_cast(BBI)) { + deadPointers.erase(A); + + // Dead alloca's can be DCE'd when we reach them + if (A->use_empty()) { + BBI++; + DeleteDeadInstruction(A, &deadPointers); + NumFastOther++; + MadeChange = true; + } + + continue; + } else if (CallSite::get(BBI).getInstruction() != 0) { + // If this call does not access memory, it can't + // be undeadifying any of our pointers. + CallSite CS = CallSite::get(BBI); + if (AA.doesNotAccessMemory(CS)) + continue; + + unsigned modRef = 0; + unsigned other = 0; + + // Remove any pointers made undead by the call from the dead set + std::vector dead; + for (SmallPtrSet::iterator I = deadPointers.begin(), + E = deadPointers.end(); I != E; ++I) { + // HACK: if we detect that our AA is imprecise, it's not + // worth it to scan the rest of the deadPointers set. Just + // assume that the AA will return ModRef for everything, and + // go ahead and bail. + if (modRef >= 16 && other == 0) { + deadPointers.clear(); + return MadeChange; + } + + // Get size information for the alloca + unsigned pointerSize = ~0U; + if (TD) { + if (AllocaInst* A = dyn_cast(*I)) { + if (ConstantInt* C = dyn_cast(A->getArraySize())) + pointerSize = C->getZExtValue() * + TD->getTypeAllocSize(A->getAllocatedType()); + } else { + const PointerType* PT = cast( + cast(*I)->getType()); + pointerSize = TD->getTypeAllocSize(PT->getElementType()); + } + } + + // See if the call site touches it + AliasAnalysis::ModRefResult A = AA.getModRefInfo(CS, *I, pointerSize); + + if (A == AliasAnalysis::ModRef) + modRef++; + else + other++; + + if (A == AliasAnalysis::ModRef || A == AliasAnalysis::Ref) + dead.push_back(*I); + } + + for (std::vector::iterator I = dead.begin(), E = dead.end(); + I != E; ++I) + deadPointers.erase(*I); + + continue; + } else if (isInstructionTriviallyDead(BBI)) { + // For any non-memory-affecting non-terminators, DCE them as we reach them + Instruction *Inst = BBI; + BBI++; + DeleteDeadInstruction(Inst, &deadPointers); + NumFastOther++; + MadeChange = true; + continue; + } + + if (!killPointer) + continue; + + killPointer = killPointer->getUnderlyingObject(); + + // Deal with undead pointers + MadeChange |= RemoveUndeadPointers(killPointer, killPointerSize, BBI, + deadPointers); + } + + return MadeChange; +} + +/// RemoveUndeadPointers - check for uses of a pointer that make it +/// undead when scanning for dead stores to alloca's. +bool DSE::RemoveUndeadPointers(Value* killPointer, uint64_t killPointerSize, + BasicBlock::iterator &BBI, + SmallPtrSet& deadPointers) { + AliasAnalysis &AA = getAnalysis(); + + // If the kill pointer can be easily reduced to an alloca, + // don't bother doing extraneous AA queries. + if (deadPointers.count(killPointer)) { + deadPointers.erase(killPointer); + return false; + } + + // A global can't be in the dead pointer set. + if (isa(killPointer)) + return false; + + bool MadeChange = false; + + SmallVector undead; + + for (SmallPtrSet::iterator I = deadPointers.begin(), + E = deadPointers.end(); I != E; ++I) { + // Get size information for the alloca. + unsigned pointerSize = ~0U; + if (TD) { + if (AllocaInst* A = dyn_cast(*I)) { + if (ConstantInt* C = dyn_cast(A->getArraySize())) + pointerSize = C->getZExtValue() * + TD->getTypeAllocSize(A->getAllocatedType()); + } else { + const PointerType* PT = cast(cast(*I)->getType()); + pointerSize = TD->getTypeAllocSize(PT->getElementType()); + } + } + + // See if this pointer could alias it + AliasAnalysis::AliasResult A = AA.alias(*I, pointerSize, + killPointer, killPointerSize); + + // If it must-alias and a store, we can delete it + if (isa(BBI) && A == AliasAnalysis::MustAlias) { + StoreInst* S = cast(BBI); + + // Remove it! + BBI++; + DeleteDeadInstruction(S, &deadPointers); + NumFastStores++; + MadeChange = true; + + continue; + + // Otherwise, it is undead + } else if (A != AliasAnalysis::NoAlias) + undead.push_back(*I); + } + + for (SmallVector::iterator I = undead.begin(), E = undead.end(); + I != E; ++I) + deadPointers.erase(*I); + + return MadeChange; +} + +/// DeleteDeadInstruction - Delete this instruction. Before we do, go through +/// and zero out all the operands of this instruction. If any of them become +/// dead, delete them and the computation tree that feeds them. +/// +/// If ValueSet is non-null, remove any deleted instructions from it as well. +/// +void DSE::DeleteDeadInstruction(Instruction *I, + SmallPtrSet *ValueSet) { + SmallVector NowDeadInsts; + + NowDeadInsts.push_back(I); + --NumFastOther; + + // Before we touch this instruction, remove it from memdep! + MemoryDependenceAnalysis &MDA = getAnalysis(); + while (!NowDeadInsts.empty()) { + Instruction *DeadInst = NowDeadInsts.back(); + NowDeadInsts.pop_back(); + + ++NumFastOther; + + // This instruction is dead, zap it, in stages. Start by removing it from + // MemDep, which needs to know the operands and needs it to be in the + // function. + MDA.removeInstruction(DeadInst); + + for (unsigned op = 0, e = DeadInst->getNumOperands(); op != e; ++op) { + Value *Op = DeadInst->getOperand(op); + DeadInst->setOperand(op, 0); + + // If this operand just became dead, add it to the NowDeadInsts list. + if (!Op->use_empty()) continue; + + if (Instruction *OpI = dyn_cast(Op)) + if (isInstructionTriviallyDead(OpI)) + NowDeadInsts.push_back(OpI); + } + + DeadInst->eraseFromParent(); + + if (ValueSet) ValueSet->erase(DeadInst); + } +} diff --git a/libclamav/c++/llvm/lib/Transforms/Scalar/GEPSplitter.cpp b/libclamav/c++/llvm/lib/Transforms/Scalar/GEPSplitter.cpp new file mode 100644 index 000000000..610a41dae --- /dev/null +++ b/libclamav/c++/llvm/lib/Transforms/Scalar/GEPSplitter.cpp @@ -0,0 +1,81 @@ +//===- GEPSplitter.cpp - Split complex GEPs into simple ones --------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This function breaks GEPs with more than 2 non-zero operands into smaller +// GEPs each with no more than 2 non-zero operands. This exposes redundancy +// between GEPs with common initial operand sequences. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "split-geps" +#include "llvm/Transforms/Scalar.h" +#include "llvm/Constants.h" +#include "llvm/Function.h" +#include "llvm/Instructions.h" +#include "llvm/Pass.h" +using namespace llvm; + +namespace { + class GEPSplitter : public FunctionPass { + virtual bool runOnFunction(Function &F); + virtual void getAnalysisUsage(AnalysisUsage &AU) const; + public: + static char ID; // Pass identification, replacement for typeid + explicit GEPSplitter() : FunctionPass(&ID) {} + }; +} + +char GEPSplitter::ID = 0; +static RegisterPass X("split-geps", + "split complex GEPs into simple GEPs"); + +FunctionPass *llvm::createGEPSplitterPass() { + return new GEPSplitter(); +} + +bool GEPSplitter::runOnFunction(Function &F) { + bool Changed = false; + + // Visit each GEP instruction. + for (Function::iterator I = F.begin(), E = F.end(); I != E; ++I) + for (BasicBlock::iterator II = I->begin(), IE = I->end(); II != IE; ) + if (GetElementPtrInst *GEP = dyn_cast(II++)) { + unsigned NumOps = GEP->getNumOperands(); + // Ignore GEPs which are already simple. + if (NumOps <= 2) + continue; + bool FirstIndexIsZero = isa(GEP->getOperand(1)) && + cast(GEP->getOperand(1))->isZero(); + if (NumOps == 3 && FirstIndexIsZero) + continue; + // The first index is special and gets expanded with a 2-operand GEP + // (unless it's zero, in which case we can skip this). + Value *NewGEP = FirstIndexIsZero ? + GEP->getOperand(0) : + GetElementPtrInst::Create(GEP->getOperand(0), GEP->getOperand(1), + "tmp", GEP); + // All remaining indices get expanded with a 3-operand GEP with zero + // as the second operand. + Value *Idxs[2]; + Idxs[0] = ConstantInt::get(Type::getInt64Ty(F.getContext()), 0); + for (unsigned i = 2; i != NumOps; ++i) { + Idxs[1] = GEP->getOperand(i); + NewGEP = GetElementPtrInst::Create(NewGEP, Idxs, Idxs+2, "tmp", GEP); + } + GEP->replaceAllUsesWith(NewGEP); + GEP->eraseFromParent(); + Changed = true; + } + + return Changed; +} + +void GEPSplitter::getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesCFG(); +} diff --git a/libclamav/c++/llvm/lib/Transforms/Scalar/GVN.cpp b/libclamav/c++/llvm/lib/Transforms/Scalar/GVN.cpp new file mode 100644 index 000000000..72eb9002c --- /dev/null +++ b/libclamav/c++/llvm/lib/Transforms/Scalar/GVN.cpp @@ -0,0 +1,2055 @@ +//===- GVN.cpp - Eliminate redundant values and loads ---------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This pass performs global value numbering to eliminate fully redundant +// instructions. It also performs simple dead load elimination. +// +// Note that this pass does the value numbering itself; it does not use the +// ValueNumbering analysis passes. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "gvn" +#include "llvm/Transforms/Scalar.h" +#include "llvm/BasicBlock.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Function.h" +#include "llvm/IntrinsicInst.h" +#include "llvm/LLVMContext.h" +#include "llvm/Operator.h" +#include "llvm/Value.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/DepthFirstIterator.h" +#include "llvm/ADT/PostOrderIterator.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/Analysis/Dominators.h" +#include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/Analysis/MemoryBuiltins.h" +#include "llvm/Analysis/MemoryDependenceAnalysis.h" +#include "llvm/Support/CFG.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/GetElementPtrTypeIterator.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Transforms/Utils/BasicBlockUtils.h" +#include "llvm/Transforms/Utils/Local.h" +#include "llvm/Transforms/Utils/SSAUpdater.h" +#include +using namespace llvm; + +STATISTIC(NumGVNInstr, "Number of instructions deleted"); +STATISTIC(NumGVNLoad, "Number of loads deleted"); +STATISTIC(NumGVNPRE, "Number of instructions PRE'd"); +STATISTIC(NumGVNBlocks, "Number of blocks merged"); +STATISTIC(NumPRELoad, "Number of loads PRE'd"); + +static cl::opt EnablePRE("enable-pre", + cl::init(true), cl::Hidden); +static cl::opt EnableLoadPRE("enable-load-pre", cl::init(true)); + +//===----------------------------------------------------------------------===// +// ValueTable Class +//===----------------------------------------------------------------------===// + +/// This class holds the mapping between values and value numbers. It is used +/// as an efficient mechanism to determine the expression-wise equivalence of +/// two values. +namespace { + struct Expression { + enum ExpressionOpcode { ADD, FADD, SUB, FSUB, MUL, FMUL, + UDIV, SDIV, FDIV, UREM, SREM, + FREM, SHL, LSHR, ASHR, AND, OR, XOR, ICMPEQ, + ICMPNE, ICMPUGT, ICMPUGE, ICMPULT, ICMPULE, + ICMPSGT, ICMPSGE, ICMPSLT, ICMPSLE, FCMPOEQ, + FCMPOGT, FCMPOGE, FCMPOLT, FCMPOLE, FCMPONE, + FCMPORD, FCMPUNO, FCMPUEQ, FCMPUGT, FCMPUGE, + FCMPULT, FCMPULE, FCMPUNE, EXTRACT, INSERT, + SHUFFLE, SELECT, TRUNC, ZEXT, SEXT, FPTOUI, + FPTOSI, UITOFP, SITOFP, FPTRUNC, FPEXT, + PTRTOINT, INTTOPTR, BITCAST, GEP, CALL, CONSTANT, + INSERTVALUE, EXTRACTVALUE, EMPTY, TOMBSTONE }; + + ExpressionOpcode opcode; + const Type* type; + SmallVector varargs; + Value *function; + + Expression() { } + Expression(ExpressionOpcode o) : opcode(o) { } + + bool operator==(const Expression &other) const { + if (opcode != other.opcode) + return false; + else if (opcode == EMPTY || opcode == TOMBSTONE) + return true; + else if (type != other.type) + return false; + else if (function != other.function) + return false; + else { + if (varargs.size() != other.varargs.size()) + return false; + + for (size_t i = 0; i < varargs.size(); ++i) + if (varargs[i] != other.varargs[i]) + return false; + + return true; + } + } + + bool operator!=(const Expression &other) const { + return !(*this == other); + } + }; + + class ValueTable { + private: + DenseMap valueNumbering; + DenseMap expressionNumbering; + AliasAnalysis* AA; + MemoryDependenceAnalysis* MD; + DominatorTree* DT; + + uint32_t nextValueNumber; + + Expression::ExpressionOpcode getOpcode(BinaryOperator* BO); + Expression::ExpressionOpcode getOpcode(CmpInst* C); + Expression::ExpressionOpcode getOpcode(CastInst* C); + Expression create_expression(BinaryOperator* BO); + Expression create_expression(CmpInst* C); + Expression create_expression(ShuffleVectorInst* V); + Expression create_expression(ExtractElementInst* C); + Expression create_expression(InsertElementInst* V); + Expression create_expression(SelectInst* V); + Expression create_expression(CastInst* C); + Expression create_expression(GetElementPtrInst* G); + Expression create_expression(CallInst* C); + Expression create_expression(Constant* C); + Expression create_expression(ExtractValueInst* C); + Expression create_expression(InsertValueInst* C); + + uint32_t lookup_or_add_call(CallInst* C); + public: + ValueTable() : nextValueNumber(1) { } + uint32_t lookup_or_add(Value *V); + uint32_t lookup(Value *V) const; + void add(Value *V, uint32_t num); + void clear(); + void erase(Value *v); + unsigned size(); + void setAliasAnalysis(AliasAnalysis* A) { AA = A; } + AliasAnalysis *getAliasAnalysis() const { return AA; } + void setMemDep(MemoryDependenceAnalysis* M) { MD = M; } + void setDomTree(DominatorTree* D) { DT = D; } + uint32_t getNextUnusedValueNumber() { return nextValueNumber; } + void verifyRemoved(const Value *) const; + }; +} + +namespace llvm { +template <> struct DenseMapInfo { + static inline Expression getEmptyKey() { + return Expression(Expression::EMPTY); + } + + static inline Expression getTombstoneKey() { + return Expression(Expression::TOMBSTONE); + } + + static unsigned getHashValue(const Expression e) { + unsigned hash = e.opcode; + + hash = ((unsigned)((uintptr_t)e.type >> 4) ^ + (unsigned)((uintptr_t)e.type >> 9)); + + for (SmallVector::const_iterator I = e.varargs.begin(), + E = e.varargs.end(); I != E; ++I) + hash = *I + hash * 37; + + hash = ((unsigned)((uintptr_t)e.function >> 4) ^ + (unsigned)((uintptr_t)e.function >> 9)) + + hash * 37; + + return hash; + } + static bool isEqual(const Expression &LHS, const Expression &RHS) { + return LHS == RHS; + } + static bool isPod() { return true; } +}; +} + +//===----------------------------------------------------------------------===// +// ValueTable Internal Functions +//===----------------------------------------------------------------------===// +Expression::ExpressionOpcode ValueTable::getOpcode(BinaryOperator* BO) { + switch(BO->getOpcode()) { + default: // THIS SHOULD NEVER HAPPEN + llvm_unreachable("Binary operator with unknown opcode?"); + case Instruction::Add: return Expression::ADD; + case Instruction::FAdd: return Expression::FADD; + case Instruction::Sub: return Expression::SUB; + case Instruction::FSub: return Expression::FSUB; + case Instruction::Mul: return Expression::MUL; + case Instruction::FMul: return Expression::FMUL; + case Instruction::UDiv: return Expression::UDIV; + case Instruction::SDiv: return Expression::SDIV; + case Instruction::FDiv: return Expression::FDIV; + case Instruction::URem: return Expression::UREM; + case Instruction::SRem: return Expression::SREM; + case Instruction::FRem: return Expression::FREM; + case Instruction::Shl: return Expression::SHL; + case Instruction::LShr: return Expression::LSHR; + case Instruction::AShr: return Expression::ASHR; + case Instruction::And: return Expression::AND; + case Instruction::Or: return Expression::OR; + case Instruction::Xor: return Expression::XOR; + } +} + +Expression::ExpressionOpcode ValueTable::getOpcode(CmpInst* C) { + if (isa(C)) { + switch (C->getPredicate()) { + default: // THIS SHOULD NEVER HAPPEN + llvm_unreachable("Comparison with unknown predicate?"); + case ICmpInst::ICMP_EQ: return Expression::ICMPEQ; + case ICmpInst::ICMP_NE: return Expression::ICMPNE; + case ICmpInst::ICMP_UGT: return Expression::ICMPUGT; + case ICmpInst::ICMP_UGE: return Expression::ICMPUGE; + case ICmpInst::ICMP_ULT: return Expression::ICMPULT; + case ICmpInst::ICMP_ULE: return Expression::ICMPULE; + case ICmpInst::ICMP_SGT: return Expression::ICMPSGT; + case ICmpInst::ICMP_SGE: return Expression::ICMPSGE; + case ICmpInst::ICMP_SLT: return Expression::ICMPSLT; + case ICmpInst::ICMP_SLE: return Expression::ICMPSLE; + } + } else { + switch (C->getPredicate()) { + default: // THIS SHOULD NEVER HAPPEN + llvm_unreachable("Comparison with unknown predicate?"); + case FCmpInst::FCMP_OEQ: return Expression::FCMPOEQ; + case FCmpInst::FCMP_OGT: return Expression::FCMPOGT; + case FCmpInst::FCMP_OGE: return Expression::FCMPOGE; + case FCmpInst::FCMP_OLT: return Expression::FCMPOLT; + case FCmpInst::FCMP_OLE: return Expression::FCMPOLE; + case FCmpInst::FCMP_ONE: return Expression::FCMPONE; + case FCmpInst::FCMP_ORD: return Expression::FCMPORD; + case FCmpInst::FCMP_UNO: return Expression::FCMPUNO; + case FCmpInst::FCMP_UEQ: return Expression::FCMPUEQ; + case FCmpInst::FCMP_UGT: return Expression::FCMPUGT; + case FCmpInst::FCMP_UGE: return Expression::FCMPUGE; + case FCmpInst::FCMP_ULT: return Expression::FCMPULT; + case FCmpInst::FCMP_ULE: return Expression::FCMPULE; + case FCmpInst::FCMP_UNE: return Expression::FCMPUNE; + } + } +} + +Expression::ExpressionOpcode ValueTable::getOpcode(CastInst* C) { + switch(C->getOpcode()) { + default: // THIS SHOULD NEVER HAPPEN + llvm_unreachable("Cast operator with unknown opcode?"); + case Instruction::Trunc: return Expression::TRUNC; + case Instruction::ZExt: return Expression::ZEXT; + case Instruction::SExt: return Expression::SEXT; + case Instruction::FPToUI: return Expression::FPTOUI; + case Instruction::FPToSI: return Expression::FPTOSI; + case Instruction::UIToFP: return Expression::UITOFP; + case Instruction::SIToFP: return Expression::SITOFP; + case Instruction::FPTrunc: return Expression::FPTRUNC; + case Instruction::FPExt: return Expression::FPEXT; + case Instruction::PtrToInt: return Expression::PTRTOINT; + case Instruction::IntToPtr: return Expression::INTTOPTR; + case Instruction::BitCast: return Expression::BITCAST; + } +} + +Expression ValueTable::create_expression(CallInst* C) { + Expression e; + + e.type = C->getType(); + e.function = C->getCalledFunction(); + e.opcode = Expression::CALL; + + for (CallInst::op_iterator I = C->op_begin()+1, E = C->op_end(); + I != E; ++I) + e.varargs.push_back(lookup_or_add(*I)); + + return e; +} + +Expression ValueTable::create_expression(BinaryOperator* BO) { + Expression e; + e.varargs.push_back(lookup_or_add(BO->getOperand(0))); + e.varargs.push_back(lookup_or_add(BO->getOperand(1))); + e.function = 0; + e.type = BO->getType(); + e.opcode = getOpcode(BO); + + return e; +} + +Expression ValueTable::create_expression(CmpInst* C) { + Expression e; + + e.varargs.push_back(lookup_or_add(C->getOperand(0))); + e.varargs.push_back(lookup_or_add(C->getOperand(1))); + e.function = 0; + e.type = C->getType(); + e.opcode = getOpcode(C); + + return e; +} + +Expression ValueTable::create_expression(CastInst* C) { + Expression e; + + e.varargs.push_back(lookup_or_add(C->getOperand(0))); + e.function = 0; + e.type = C->getType(); + e.opcode = getOpcode(C); + + return e; +} + +Expression ValueTable::create_expression(ShuffleVectorInst* S) { + Expression e; + + e.varargs.push_back(lookup_or_add(S->getOperand(0))); + e.varargs.push_back(lookup_or_add(S->getOperand(1))); + e.varargs.push_back(lookup_or_add(S->getOperand(2))); + e.function = 0; + e.type = S->getType(); + e.opcode = Expression::SHUFFLE; + + return e; +} + +Expression ValueTable::create_expression(ExtractElementInst* E) { + Expression e; + + e.varargs.push_back(lookup_or_add(E->getOperand(0))); + e.varargs.push_back(lookup_or_add(E->getOperand(1))); + e.function = 0; + e.type = E->getType(); + e.opcode = Expression::EXTRACT; + + return e; +} + +Expression ValueTable::create_expression(InsertElementInst* I) { + Expression e; + + e.varargs.push_back(lookup_or_add(I->getOperand(0))); + e.varargs.push_back(lookup_or_add(I->getOperand(1))); + e.varargs.push_back(lookup_or_add(I->getOperand(2))); + e.function = 0; + e.type = I->getType(); + e.opcode = Expression::INSERT; + + return e; +} + +Expression ValueTable::create_expression(SelectInst* I) { + Expression e; + + e.varargs.push_back(lookup_or_add(I->getCondition())); + e.varargs.push_back(lookup_or_add(I->getTrueValue())); + e.varargs.push_back(lookup_or_add(I->getFalseValue())); + e.function = 0; + e.type = I->getType(); + e.opcode = Expression::SELECT; + + return e; +} + +Expression ValueTable::create_expression(GetElementPtrInst* G) { + Expression e; + + e.varargs.push_back(lookup_or_add(G->getPointerOperand())); + e.function = 0; + e.type = G->getType(); + e.opcode = Expression::GEP; + + for (GetElementPtrInst::op_iterator I = G->idx_begin(), E = G->idx_end(); + I != E; ++I) + e.varargs.push_back(lookup_or_add(*I)); + + return e; +} + +Expression ValueTable::create_expression(ExtractValueInst* E) { + Expression e; + + e.varargs.push_back(lookup_or_add(E->getAggregateOperand())); + for (ExtractValueInst::idx_iterator II = E->idx_begin(), IE = E->idx_end(); + II != IE; ++II) + e.varargs.push_back(*II); + e.function = 0; + e.type = E->getType(); + e.opcode = Expression::EXTRACTVALUE; + + return e; +} + +Expression ValueTable::create_expression(InsertValueInst* E) { + Expression e; + + e.varargs.push_back(lookup_or_add(E->getAggregateOperand())); + e.varargs.push_back(lookup_or_add(E->getInsertedValueOperand())); + for (InsertValueInst::idx_iterator II = E->idx_begin(), IE = E->idx_end(); + II != IE; ++II) + e.varargs.push_back(*II); + e.function = 0; + e.type = E->getType(); + e.opcode = Expression::INSERTVALUE; + + return e; +} + +//===----------------------------------------------------------------------===// +// ValueTable External Functions +//===----------------------------------------------------------------------===// + +/// add - Insert a value into the table with a specified value number. +void ValueTable::add(Value *V, uint32_t num) { + valueNumbering.insert(std::make_pair(V, num)); +} + +uint32_t ValueTable::lookup_or_add_call(CallInst* C) { + if (AA->doesNotAccessMemory(C)) { + Expression exp = create_expression(C); + uint32_t& e = expressionNumbering[exp]; + if (!e) e = nextValueNumber++; + valueNumbering[C] = e; + return e; + } else if (AA->onlyReadsMemory(C)) { + Expression exp = create_expression(C); + uint32_t& e = expressionNumbering[exp]; + if (!e) { + e = nextValueNumber++; + valueNumbering[C] = e; + return e; + } + if (!MD) { + e = nextValueNumber++; + valueNumbering[C] = e; + return e; + } + + MemDepResult local_dep = MD->getDependency(C); + + if (!local_dep.isDef() && !local_dep.isNonLocal()) { + valueNumbering[C] = nextValueNumber; + return nextValueNumber++; + } + + if (local_dep.isDef()) { + CallInst* local_cdep = cast(local_dep.getInst()); + + if (local_cdep->getNumOperands() != C->getNumOperands()) { + valueNumbering[C] = nextValueNumber; + return nextValueNumber++; + } + + for (unsigned i = 1; i < C->getNumOperands(); ++i) { + uint32_t c_vn = lookup_or_add(C->getOperand(i)); + uint32_t cd_vn = lookup_or_add(local_cdep->getOperand(i)); + if (c_vn != cd_vn) { + valueNumbering[C] = nextValueNumber; + return nextValueNumber++; + } + } + + uint32_t v = lookup_or_add(local_cdep); + valueNumbering[C] = v; + return v; + } + + // Non-local case. + const MemoryDependenceAnalysis::NonLocalDepInfo &deps = + MD->getNonLocalCallDependency(CallSite(C)); + // FIXME: call/call dependencies for readonly calls should return def, not + // clobber! Move the checking logic to MemDep! + CallInst* cdep = 0; + + // Check to see if we have a single dominating call instruction that is + // identical to C. + for (unsigned i = 0, e = deps.size(); i != e; ++i) { + const MemoryDependenceAnalysis::NonLocalDepEntry *I = &deps[i]; + // Ignore non-local dependencies. + if (I->second.isNonLocal()) + continue; + + // We don't handle non-depedencies. If we already have a call, reject + // instruction dependencies. + if (I->second.isClobber() || cdep != 0) { + cdep = 0; + break; + } + + CallInst *NonLocalDepCall = dyn_cast(I->second.getInst()); + // FIXME: All duplicated with non-local case. + if (NonLocalDepCall && DT->properlyDominates(I->first, C->getParent())){ + cdep = NonLocalDepCall; + continue; + } + + cdep = 0; + break; + } + + if (!cdep) { + valueNumbering[C] = nextValueNumber; + return nextValueNumber++; + } + + if (cdep->getNumOperands() != C->getNumOperands()) { + valueNumbering[C] = nextValueNumber; + return nextValueNumber++; + } + for (unsigned i = 1; i < C->getNumOperands(); ++i) { + uint32_t c_vn = lookup_or_add(C->getOperand(i)); + uint32_t cd_vn = lookup_or_add(cdep->getOperand(i)); + if (c_vn != cd_vn) { + valueNumbering[C] = nextValueNumber; + return nextValueNumber++; + } + } + + uint32_t v = lookup_or_add(cdep); + valueNumbering[C] = v; + return v; + + } else { + valueNumbering[C] = nextValueNumber; + return nextValueNumber++; + } +} + +/// lookup_or_add - Returns the value number for the specified value, assigning +/// it a new number if it did not have one before. +uint32_t ValueTable::lookup_or_add(Value *V) { + DenseMap::iterator VI = valueNumbering.find(V); + if (VI != valueNumbering.end()) + return VI->second; + + if (!isa(V)) { + valueNumbering[V] = nextValueNumber; + return nextValueNumber++; + } + + Instruction* I = cast(V); + Expression exp; + switch (I->getOpcode()) { + case Instruction::Call: + return lookup_or_add_call(cast(I)); + case Instruction::Add: + case Instruction::FAdd: + case Instruction::Sub: + case Instruction::FSub: + case Instruction::Mul: + case Instruction::FMul: + case Instruction::UDiv: + case Instruction::SDiv: + case Instruction::FDiv: + case Instruction::URem: + case Instruction::SRem: + case Instruction::FRem: + case Instruction::Shl: + case Instruction::LShr: + case Instruction::AShr: + case Instruction::And: + case Instruction::Or : + case Instruction::Xor: + exp = create_expression(cast(I)); + break; + case Instruction::ICmp: + case Instruction::FCmp: + exp = create_expression(cast(I)); + break; + case Instruction::Trunc: + case Instruction::ZExt: + case Instruction::SExt: + case Instruction::FPToUI: + case Instruction::FPToSI: + case Instruction::UIToFP: + case Instruction::SIToFP: + case Instruction::FPTrunc: + case Instruction::FPExt: + case Instruction::PtrToInt: + case Instruction::IntToPtr: + case Instruction::BitCast: + exp = create_expression(cast(I)); + break; + case Instruction::Select: + exp = create_expression(cast(I)); + break; + case Instruction::ExtractElement: + exp = create_expression(cast(I)); + break; + case Instruction::InsertElement: + exp = create_expression(cast(I)); + break; + case Instruction::ShuffleVector: + exp = create_expression(cast(I)); + break; + case Instruction::ExtractValue: + exp = create_expression(cast(I)); + break; + case Instruction::InsertValue: + exp = create_expression(cast(I)); + break; + case Instruction::GetElementPtr: + exp = create_expression(cast(I)); + break; + default: + valueNumbering[V] = nextValueNumber; + return nextValueNumber++; + } + + uint32_t& e = expressionNumbering[exp]; + if (!e) e = nextValueNumber++; + valueNumbering[V] = e; + return e; +} + +/// lookup - Returns the value number of the specified value. Fails if +/// the value has not yet been numbered. +uint32_t ValueTable::lookup(Value *V) const { + DenseMap::const_iterator VI = valueNumbering.find(V); + assert(VI != valueNumbering.end() && "Value not numbered?"); + return VI->second; +} + +/// clear - Remove all entries from the ValueTable +void ValueTable::clear() { + valueNumbering.clear(); + expressionNumbering.clear(); + nextValueNumber = 1; +} + +/// erase - Remove a value from the value numbering +void ValueTable::erase(Value *V) { + valueNumbering.erase(V); +} + +/// verifyRemoved - Verify that the value is removed from all internal data +/// structures. +void ValueTable::verifyRemoved(const Value *V) const { + for (DenseMap::const_iterator + I = valueNumbering.begin(), E = valueNumbering.end(); I != E; ++I) { + assert(I->first != V && "Inst still occurs in value numbering map!"); + } +} + +//===----------------------------------------------------------------------===// +// GVN Pass +//===----------------------------------------------------------------------===// + +namespace { + struct ValueNumberScope { + ValueNumberScope* parent; + DenseMap table; + + ValueNumberScope(ValueNumberScope* p) : parent(p) { } + }; +} + +namespace { + + class GVN : public FunctionPass { + bool runOnFunction(Function &F); + public: + static char ID; // Pass identification, replacement for typeid + explicit GVN(bool nopre = false, bool noloads = false) + : FunctionPass(&ID), NoPRE(nopre), NoLoads(noloads), MD(0) { } + + private: + bool NoPRE; + bool NoLoads; + MemoryDependenceAnalysis *MD; + DominatorTree *DT; + + ValueTable VN; + DenseMap localAvail; + + // This transformation requires dominator postdominator info + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.addRequired(); + if (!NoLoads) + AU.addRequired(); + AU.addRequired(); + + AU.addPreserved(); + AU.addPreserved(); + } + + // Helper fuctions + // FIXME: eliminate or document these better + bool processLoad(LoadInst* L, + SmallVectorImpl &toErase); + bool processInstruction(Instruction *I, + SmallVectorImpl &toErase); + bool processNonLocalLoad(LoadInst* L, + SmallVectorImpl &toErase); + bool processBlock(BasicBlock *BB); + void dump(DenseMap& d); + bool iterateOnFunction(Function &F); + Value *CollapsePhi(PHINode* p); + bool performPRE(Function& F); + Value *lookupNumber(BasicBlock *BB, uint32_t num); + void cleanupGlobalSets(); + void verifyRemoved(const Instruction *I) const; + }; + + char GVN::ID = 0; +} + +// createGVNPass - The public interface to this file... +FunctionPass *llvm::createGVNPass(bool NoPRE, bool NoLoads) { + return new GVN(NoPRE, NoLoads); +} + +static RegisterPass X("gvn", + "Global Value Numbering"); + +void GVN::dump(DenseMap& d) { + printf("{\n"); + for (DenseMap::iterator I = d.begin(), + E = d.end(); I != E; ++I) { + printf("%d\n", I->first); + I->second->dump(); + } + printf("}\n"); +} + +static bool isSafeReplacement(PHINode* p, Instruction *inst) { + if (!isa(inst)) + return true; + + for (Instruction::use_iterator UI = p->use_begin(), E = p->use_end(); + UI != E; ++UI) + if (PHINode* use_phi = dyn_cast(UI)) + if (use_phi->getParent() == inst->getParent()) + return false; + + return true; +} + +Value *GVN::CollapsePhi(PHINode *PN) { + Value *ConstVal = PN->hasConstantValue(DT); + if (!ConstVal) return 0; + + Instruction *Inst = dyn_cast(ConstVal); + if (!Inst) + return ConstVal; + + if (DT->dominates(Inst, PN)) + if (isSafeReplacement(PN, Inst)) + return Inst; + return 0; +} + +/// IsValueFullyAvailableInBlock - Return true if we can prove that the value +/// we're analyzing is fully available in the specified block. As we go, keep +/// track of which blocks we know are fully alive in FullyAvailableBlocks. This +/// map is actually a tri-state map with the following values: +/// 0) we know the block *is not* fully available. +/// 1) we know the block *is* fully available. +/// 2) we do not know whether the block is fully available or not, but we are +/// currently speculating that it will be. +/// 3) we are speculating for this block and have used that to speculate for +/// other blocks. +static bool IsValueFullyAvailableInBlock(BasicBlock *BB, + DenseMap &FullyAvailableBlocks) { + // Optimistically assume that the block is fully available and check to see + // if we already know about this block in one lookup. + std::pair::iterator, char> IV = + FullyAvailableBlocks.insert(std::make_pair(BB, 2)); + + // If the entry already existed for this block, return the precomputed value. + if (!IV.second) { + // If this is a speculative "available" value, mark it as being used for + // speculation of other blocks. + if (IV.first->second == 2) + IV.first->second = 3; + return IV.first->second != 0; + } + + // Otherwise, see if it is fully available in all predecessors. + pred_iterator PI = pred_begin(BB), PE = pred_end(BB); + + // If this block has no predecessors, it isn't live-in here. + if (PI == PE) + goto SpeculationFailure; + + for (; PI != PE; ++PI) + // If the value isn't fully available in one of our predecessors, then it + // isn't fully available in this block either. Undo our previous + // optimistic assumption and bail out. + if (!IsValueFullyAvailableInBlock(*PI, FullyAvailableBlocks)) + goto SpeculationFailure; + + return true; + +// SpeculationFailure - If we get here, we found out that this is not, after +// all, a fully-available block. We have a problem if we speculated on this and +// used the speculation to mark other blocks as available. +SpeculationFailure: + char &BBVal = FullyAvailableBlocks[BB]; + + // If we didn't speculate on this, just return with it set to false. + if (BBVal == 2) { + BBVal = 0; + return false; + } + + // If we did speculate on this value, we could have blocks set to 1 that are + // incorrect. Walk the (transitive) successors of this block and mark them as + // 0 if set to one. + SmallVector BBWorklist; + BBWorklist.push_back(BB); + + while (!BBWorklist.empty()) { + BasicBlock *Entry = BBWorklist.pop_back_val(); + // Note that this sets blocks to 0 (unavailable) if they happen to not + // already be in FullyAvailableBlocks. This is safe. + char &EntryVal = FullyAvailableBlocks[Entry]; + if (EntryVal == 0) continue; // Already unavailable. + + // Mark as unavailable. + EntryVal = 0; + + for (succ_iterator I = succ_begin(Entry), E = succ_end(Entry); I != E; ++I) + BBWorklist.push_back(*I); + } + + return false; +} + + +/// CanCoerceMustAliasedValueToLoad - Return true if +/// CoerceAvailableValueToLoadType will succeed. +static bool CanCoerceMustAliasedValueToLoad(Value *StoredVal, + const Type *LoadTy, + const TargetData &TD) { + // If the loaded or stored value is an first class array or struct, don't try + // to transform them. We need to be able to bitcast to integer. + if (isa(LoadTy) || isa(LoadTy) || + isa(StoredVal->getType()) || + isa(StoredVal->getType())) + return false; + + // The store has to be at least as big as the load. + if (TD.getTypeSizeInBits(StoredVal->getType()) < + TD.getTypeSizeInBits(LoadTy)) + return false; + + return true; +} + + +/// CoerceAvailableValueToLoadType - If we saw a store of a value to memory, and +/// then a load from a must-aliased pointer of a different type, try to coerce +/// the stored value. LoadedTy is the type of the load we want to replace and +/// InsertPt is the place to insert new instructions. +/// +/// If we can't do it, return null. +static Value *CoerceAvailableValueToLoadType(Value *StoredVal, + const Type *LoadedTy, + Instruction *InsertPt, + const TargetData &TD) { + if (!CanCoerceMustAliasedValueToLoad(StoredVal, LoadedTy, TD)) + return 0; + + const Type *StoredValTy = StoredVal->getType(); + + uint64_t StoreSize = TD.getTypeSizeInBits(StoredValTy); + uint64_t LoadSize = TD.getTypeSizeInBits(LoadedTy); + + // If the store and reload are the same size, we can always reuse it. + if (StoreSize == LoadSize) { + if (isa(StoredValTy) && isa(LoadedTy)) { + // Pointer to Pointer -> use bitcast. + return new BitCastInst(StoredVal, LoadedTy, "", InsertPt); + } + + // Convert source pointers to integers, which can be bitcast. + if (isa(StoredValTy)) { + StoredValTy = TD.getIntPtrType(StoredValTy->getContext()); + StoredVal = new PtrToIntInst(StoredVal, StoredValTy, "", InsertPt); + } + + const Type *TypeToCastTo = LoadedTy; + if (isa(TypeToCastTo)) + TypeToCastTo = TD.getIntPtrType(StoredValTy->getContext()); + + if (StoredValTy != TypeToCastTo) + StoredVal = new BitCastInst(StoredVal, TypeToCastTo, "", InsertPt); + + // Cast to pointer if the load needs a pointer type. + if (isa(LoadedTy)) + StoredVal = new IntToPtrInst(StoredVal, LoadedTy, "", InsertPt); + + return StoredVal; + } + + // If the loaded value is smaller than the available value, then we can + // extract out a piece from it. If the available value is too small, then we + // can't do anything. + assert(StoreSize >= LoadSize && "CanCoerceMustAliasedValueToLoad fail"); + + // Convert source pointers to integers, which can be manipulated. + if (isa(StoredValTy)) { + StoredValTy = TD.getIntPtrType(StoredValTy->getContext()); + StoredVal = new PtrToIntInst(StoredVal, StoredValTy, "", InsertPt); + } + + // Convert vectors and fp to integer, which can be manipulated. + if (!isa(StoredValTy)) { + StoredValTy = IntegerType::get(StoredValTy->getContext(), StoreSize); + StoredVal = new BitCastInst(StoredVal, StoredValTy, "", InsertPt); + } + + // If this is a big-endian system, we need to shift the value down to the low + // bits so that a truncate will work. + if (TD.isBigEndian()) { + Constant *Val = ConstantInt::get(StoredVal->getType(), StoreSize-LoadSize); + StoredVal = BinaryOperator::CreateLShr(StoredVal, Val, "tmp", InsertPt); + } + + // Truncate the integer to the right size now. + const Type *NewIntTy = IntegerType::get(StoredValTy->getContext(), LoadSize); + StoredVal = new TruncInst(StoredVal, NewIntTy, "trunc", InsertPt); + + if (LoadedTy == NewIntTy) + return StoredVal; + + // If the result is a pointer, inttoptr. + if (isa(LoadedTy)) + return new IntToPtrInst(StoredVal, LoadedTy, "inttoptr", InsertPt); + + // Otherwise, bitcast. + return new BitCastInst(StoredVal, LoadedTy, "bitcast", InsertPt); +} + +/// GetBaseWithConstantOffset - Analyze the specified pointer to see if it can +/// be expressed as a base pointer plus a constant offset. Return the base and +/// offset to the caller. +static Value *GetBaseWithConstantOffset(Value *Ptr, int64_t &Offset, + const TargetData &TD) { + Operator *PtrOp = dyn_cast(Ptr); + if (PtrOp == 0) return Ptr; + + // Just look through bitcasts. + if (PtrOp->getOpcode() == Instruction::BitCast) + return GetBaseWithConstantOffset(PtrOp->getOperand(0), Offset, TD); + + // If this is a GEP with constant indices, we can look through it. + GEPOperator *GEP = dyn_cast(PtrOp); + if (GEP == 0 || !GEP->hasAllConstantIndices()) return Ptr; + + gep_type_iterator GTI = gep_type_begin(GEP); + for (User::op_iterator I = GEP->idx_begin(), E = GEP->idx_end(); I != E; + ++I, ++GTI) { + ConstantInt *OpC = cast(*I); + if (OpC->isZero()) continue; + + // Handle a struct and array indices which add their offset to the pointer. + if (const StructType *STy = dyn_cast(*GTI)) { + Offset += TD.getStructLayout(STy)->getElementOffset(OpC->getZExtValue()); + } else { + uint64_t Size = TD.getTypeAllocSize(GTI.getIndexedType()); + Offset += OpC->getSExtValue()*Size; + } + } + + // Re-sign extend from the pointer size if needed to get overflow edge cases + // right. + unsigned PtrSize = TD.getPointerSizeInBits(); + if (PtrSize < 64) + Offset = (Offset << (64-PtrSize)) >> (64-PtrSize); + + return GetBaseWithConstantOffset(GEP->getPointerOperand(), Offset, TD); +} + + +/// AnalyzeLoadFromClobberingStore - This function is called when we have a +/// memdep query of a load that ends up being a clobbering store. This means +/// that the store *may* provide bits used by the load but we can't be sure +/// because the pointers don't mustalias. Check this case to see if there is +/// anything more we can do before we give up. This returns -1 if we have to +/// give up, or a byte number in the stored value of the piece that feeds the +/// load. +static int AnalyzeLoadFromClobberingStore(LoadInst *L, StoreInst *DepSI, + const TargetData &TD) { + // If the loaded or stored value is an first class array or struct, don't try + // to transform them. We need to be able to bitcast to integer. + if (isa(L->getType()) || isa(L->getType()) || + isa(DepSI->getOperand(0)->getType()) || + isa(DepSI->getOperand(0)->getType())) + return -1; + + int64_t StoreOffset = 0, LoadOffset = 0; + Value *StoreBase = + GetBaseWithConstantOffset(DepSI->getPointerOperand(), StoreOffset, TD); + Value *LoadBase = + GetBaseWithConstantOffset(L->getPointerOperand(), LoadOffset, TD); + if (StoreBase != LoadBase) + return -1; + + // If the load and store are to the exact same address, they should have been + // a must alias. AA must have gotten confused. + // FIXME: Study to see if/when this happens. + if (LoadOffset == StoreOffset) { +#if 0 + errs() << "STORE/LOAD DEP WITH COMMON POINTER MISSED:\n" + << "Base = " << *StoreBase << "\n" + << "Store Ptr = " << *DepSI->getPointerOperand() << "\n" + << "Store Offs = " << StoreOffset << " - " << *DepSI << "\n" + << "Load Ptr = " << *L->getPointerOperand() << "\n" + << "Load Offs = " << LoadOffset << " - " << *L << "\n\n"; + errs() << "'" << L->getParent()->getParent()->getName() << "'" + << *L->getParent(); +#endif + return -1; + } + + // If the load and store don't overlap at all, the store doesn't provide + // anything to the load. In this case, they really don't alias at all, AA + // must have gotten confused. + // FIXME: Investigate cases where this bails out, e.g. rdar://7238614. Then + // remove this check, as it is duplicated with what we have below. + uint64_t StoreSize = TD.getTypeSizeInBits(DepSI->getOperand(0)->getType()); + uint64_t LoadSize = TD.getTypeSizeInBits(L->getType()); + + if ((StoreSize & 7) | (LoadSize & 7)) + return -1; + StoreSize >>= 3; // Convert to bytes. + LoadSize >>= 3; + + + bool isAAFailure = false; + if (StoreOffset < LoadOffset) { + isAAFailure = StoreOffset+int64_t(StoreSize) <= LoadOffset; + } else { + isAAFailure = LoadOffset+int64_t(LoadSize) <= StoreOffset; + } + if (isAAFailure) { +#if 0 + errs() << "STORE LOAD DEP WITH COMMON BASE:\n" + << "Base = " << *StoreBase << "\n" + << "Store Ptr = " << *DepSI->getPointerOperand() << "\n" + << "Store Offs = " << StoreOffset << " - " << *DepSI << "\n" + << "Load Ptr = " << *L->getPointerOperand() << "\n" + << "Load Offs = " << LoadOffset << " - " << *L << "\n\n"; + errs() << "'" << L->getParent()->getParent()->getName() << "'" + << *L->getParent(); +#endif + return -1; + } + + // If the Load isn't completely contained within the stored bits, we don't + // have all the bits to feed it. We could do something crazy in the future + // (issue a smaller load then merge the bits in) but this seems unlikely to be + // valuable. + if (StoreOffset > LoadOffset || + StoreOffset+StoreSize < LoadOffset+LoadSize) + return -1; + + // Okay, we can do this transformation. Return the number of bytes into the + // store that the load is. + return LoadOffset-StoreOffset; +} + + +/// GetStoreValueForLoad - This function is called when we have a +/// memdep query of a load that ends up being a clobbering store. This means +/// that the store *may* provide bits used by the load but we can't be sure +/// because the pointers don't mustalias. Check this case to see if there is +/// anything more we can do before we give up. +static Value *GetStoreValueForLoad(Value *SrcVal, unsigned Offset, + const Type *LoadTy, + Instruction *InsertPt, const TargetData &TD){ + LLVMContext &Ctx = SrcVal->getType()->getContext(); + + uint64_t StoreSize = TD.getTypeSizeInBits(SrcVal->getType())/8; + uint64_t LoadSize = TD.getTypeSizeInBits(LoadTy)/8; + + + // Compute which bits of the stored value are being used by the load. Convert + // to an integer type to start with. + if (isa(SrcVal->getType())) + SrcVal = new PtrToIntInst(SrcVal, TD.getIntPtrType(Ctx), "tmp", InsertPt); + if (!isa(SrcVal->getType())) + SrcVal = new BitCastInst(SrcVal, IntegerType::get(Ctx, StoreSize*8), + "tmp", InsertPt); + + // Shift the bits to the least significant depending on endianness. + unsigned ShiftAmt; + if (TD.isLittleEndian()) { + ShiftAmt = Offset*8; + } else { + ShiftAmt = (StoreSize-LoadSize-Offset)*8; + } + + if (ShiftAmt) + SrcVal = BinaryOperator::CreateLShr(SrcVal, + ConstantInt::get(SrcVal->getType(), ShiftAmt), "tmp", InsertPt); + + if (LoadSize != StoreSize) + SrcVal = new TruncInst(SrcVal, IntegerType::get(Ctx, LoadSize*8), + "tmp", InsertPt); + + return CoerceAvailableValueToLoadType(SrcVal, LoadTy, InsertPt, TD); +} + +struct AvailableValueInBlock { + /// BB - The basic block in question. + BasicBlock *BB; + /// V - The value that is live out of the block. + Value *V; + /// Offset - The byte offset in V that is interesting for the load query. + unsigned Offset; + + static AvailableValueInBlock get(BasicBlock *BB, Value *V, + unsigned Offset = 0) { + AvailableValueInBlock Res; + Res.BB = BB; + Res.V = V; + Res.Offset = Offset; + return Res; + } +}; + +/// ConstructSSAForLoadSet - Given a set of loads specified by ValuesPerBlock, +/// construct SSA form, allowing us to eliminate LI. This returns the value +/// that should be used at LI's definition site. +static Value *ConstructSSAForLoadSet(LoadInst *LI, + SmallVectorImpl &ValuesPerBlock, + const TargetData *TD, + AliasAnalysis *AA) { + SmallVector NewPHIs; + SSAUpdater SSAUpdate(&NewPHIs); + SSAUpdate.Initialize(LI); + + const Type *LoadTy = LI->getType(); + + for (unsigned i = 0, e = ValuesPerBlock.size(); i != e; ++i) { + BasicBlock *BB = ValuesPerBlock[i].BB; + Value *AvailableVal = ValuesPerBlock[i].V; + unsigned Offset = ValuesPerBlock[i].Offset; + + if (SSAUpdate.HasValueForBlock(BB)) + continue; + + if (AvailableVal->getType() != LoadTy) { + assert(TD && "Need target data to handle type mismatch case"); + AvailableVal = GetStoreValueForLoad(AvailableVal, Offset, LoadTy, + BB->getTerminator(), *TD); + + if (Offset) { + DEBUG(errs() << "GVN COERCED NONLOCAL VAL:\n" + << *ValuesPerBlock[i].V << '\n' + << *AvailableVal << '\n' << "\n\n\n"); + } + + + DEBUG(errs() << "GVN COERCED NONLOCAL VAL:\n" + << *ValuesPerBlock[i].V << '\n' + << *AvailableVal << '\n' << "\n\n\n"); + } + + SSAUpdate.AddAvailableValue(BB, AvailableVal); + } + + // Perform PHI construction. + Value *V = SSAUpdate.GetValueInMiddleOfBlock(LI->getParent()); + + // If new PHI nodes were created, notify alias analysis. + if (isa(V->getType())) + for (unsigned i = 0, e = NewPHIs.size(); i != e; ++i) + AA->copyValue(LI, NewPHIs[i]); + + return V; +} + +/// processNonLocalLoad - Attempt to eliminate a load whose dependencies are +/// non-local by performing PHI construction. +bool GVN::processNonLocalLoad(LoadInst *LI, + SmallVectorImpl &toErase) { + // Find the non-local dependencies of the load. + SmallVector Deps; + MD->getNonLocalPointerDependency(LI->getOperand(0), true, LI->getParent(), + Deps); + //DEBUG(errs() << "INVESTIGATING NONLOCAL LOAD: " + // << Deps.size() << *LI << '\n'); + + // If we had to process more than one hundred blocks to find the + // dependencies, this load isn't worth worrying about. Optimizing + // it will be too expensive. + if (Deps.size() > 100) + return false; + + // If we had a phi translation failure, we'll have a single entry which is a + // clobber in the current block. Reject this early. + if (Deps.size() == 1 && Deps[0].second.isClobber()) { + DEBUG( + errs() << "GVN: non-local load "; + WriteAsOperand(errs(), LI); + errs() << " is clobbered by " << *Deps[0].second.getInst() << '\n'; + ); + return false; + } + + // Filter out useless results (non-locals, etc). Keep track of the blocks + // where we have a value available in repl, also keep track of whether we see + // dependencies that produce an unknown value for the load (such as a call + // that could potentially clobber the load). + SmallVector ValuesPerBlock; + SmallVector UnavailableBlocks; + + const TargetData *TD = 0; + + for (unsigned i = 0, e = Deps.size(); i != e; ++i) { + BasicBlock *DepBB = Deps[i].first; + MemDepResult DepInfo = Deps[i].second; + + if (DepInfo.isClobber()) { + // If the dependence is to a store that writes to a superset of the bits + // read by the load, we can extract the bits we need for the load from the + // stored value. + if (StoreInst *DepSI = dyn_cast(DepInfo.getInst())) { + if (TD == 0) + TD = getAnalysisIfAvailable(); + if (TD) { + int Offset = AnalyzeLoadFromClobberingStore(LI, DepSI, *TD); + if (Offset != -1) { + ValuesPerBlock.push_back(AvailableValueInBlock::get(DepBB, + DepSI->getOperand(0), + Offset)); + continue; + } + } + } + + // FIXME: Handle memset/memcpy. + UnavailableBlocks.push_back(DepBB); + continue; + } + + Instruction *DepInst = DepInfo.getInst(); + + // Loading the allocation -> undef. + if (isa(DepInst) || isMalloc(DepInst)) { + ValuesPerBlock.push_back(AvailableValueInBlock::get(DepBB, + UndefValue::get(LI->getType()))); + continue; + } + + // Loading immediately after lifetime begin or end -> undef. + if (IntrinsicInst* II = dyn_cast(DepInst)) { + if (II->getIntrinsicID() == Intrinsic::lifetime_start || + II->getIntrinsicID() == Intrinsic::lifetime_end) { + ValuesPerBlock.push_back(AvailableValueInBlock::get(DepBB, + UndefValue::get(LI->getType()))); + } + } + + if (StoreInst *S = dyn_cast(DepInst)) { + // Reject loads and stores that are to the same address but are of + // different types if we have to. + if (S->getOperand(0)->getType() != LI->getType()) { + if (TD == 0) + TD = getAnalysisIfAvailable(); + + // If the stored value is larger or equal to the loaded value, we can + // reuse it. + if (TD == 0 || !CanCoerceMustAliasedValueToLoad(S->getOperand(0), + LI->getType(), *TD)) { + UnavailableBlocks.push_back(DepBB); + continue; + } + } + + ValuesPerBlock.push_back(AvailableValueInBlock::get(DepBB, + S->getOperand(0))); + continue; + } + + if (LoadInst *LD = dyn_cast(DepInst)) { + // If the types mismatch and we can't handle it, reject reuse of the load. + if (LD->getType() != LI->getType()) { + if (TD == 0) + TD = getAnalysisIfAvailable(); + + // If the stored value is larger or equal to the loaded value, we can + // reuse it. + if (TD == 0 || !CanCoerceMustAliasedValueToLoad(LD, LI->getType(),*TD)){ + UnavailableBlocks.push_back(DepBB); + continue; + } + } + ValuesPerBlock.push_back(AvailableValueInBlock::get(DepBB, LD)); + continue; + } + + UnavailableBlocks.push_back(DepBB); + continue; + } + + // If we have no predecessors that produce a known value for this load, exit + // early. + if (ValuesPerBlock.empty()) return false; + + // If all of the instructions we depend on produce a known value for this + // load, then it is fully redundant and we can use PHI insertion to compute + // its value. Insert PHIs and remove the fully redundant value now. + if (UnavailableBlocks.empty()) { + DEBUG(errs() << "GVN REMOVING NONLOCAL LOAD: " << *LI << '\n'); + + // Perform PHI construction. + Value *V = ConstructSSAForLoadSet(LI, ValuesPerBlock, TD, + VN.getAliasAnalysis()); + LI->replaceAllUsesWith(V); + + if (isa(V)) + V->takeName(LI); + if (isa(V->getType())) + MD->invalidateCachedPointerInfo(V); + toErase.push_back(LI); + NumGVNLoad++; + return true; + } + + if (!EnablePRE || !EnableLoadPRE) + return false; + + // Okay, we have *some* definitions of the value. This means that the value + // is available in some of our (transitive) predecessors. Lets think about + // doing PRE of this load. This will involve inserting a new load into the + // predecessor when it's not available. We could do this in general, but + // prefer to not increase code size. As such, we only do this when we know + // that we only have to insert *one* load (which means we're basically moving + // the load, not inserting a new one). + + SmallPtrSet Blockers; + for (unsigned i = 0, e = UnavailableBlocks.size(); i != e; ++i) + Blockers.insert(UnavailableBlocks[i]); + + // Lets find first basic block with more than one predecessor. Walk backwards + // through predecessors if needed. + BasicBlock *LoadBB = LI->getParent(); + BasicBlock *TmpBB = LoadBB; + + bool isSinglePred = false; + bool allSingleSucc = true; + while (TmpBB->getSinglePredecessor()) { + isSinglePred = true; + TmpBB = TmpBB->getSinglePredecessor(); + if (!TmpBB) // If haven't found any, bail now. + return false; + if (TmpBB == LoadBB) // Infinite (unreachable) loop. + return false; + if (Blockers.count(TmpBB)) + return false; + if (TmpBB->getTerminator()->getNumSuccessors() != 1) + allSingleSucc = false; + } + + assert(TmpBB); + LoadBB = TmpBB; + + // If we have a repl set with LI itself in it, this means we have a loop where + // at least one of the values is LI. Since this means that we won't be able + // to eliminate LI even if we insert uses in the other predecessors, we will + // end up increasing code size. Reject this by scanning for LI. + for (unsigned i = 0, e = ValuesPerBlock.size(); i != e; ++i) + if (ValuesPerBlock[i].V == LI) + return false; + + if (isSinglePred) { + bool isHot = false; + for (unsigned i = 0, e = ValuesPerBlock.size(); i != e; ++i) + if (Instruction *I = dyn_cast(ValuesPerBlock[i].V)) + // "Hot" Instruction is in some loop (because it dominates its dep. + // instruction). + if (DT->dominates(LI, I)) { + isHot = true; + break; + } + + // We are interested only in "hot" instructions. We don't want to do any + // mis-optimizations here. + if (!isHot) + return false; + } + + // Okay, we have some hope :). Check to see if the loaded value is fully + // available in all but one predecessor. + // FIXME: If we could restructure the CFG, we could make a common pred with + // all the preds that don't have an available LI and insert a new load into + // that one block. + BasicBlock *UnavailablePred = 0; + + DenseMap FullyAvailableBlocks; + for (unsigned i = 0, e = ValuesPerBlock.size(); i != e; ++i) + FullyAvailableBlocks[ValuesPerBlock[i].BB] = true; + for (unsigned i = 0, e = UnavailableBlocks.size(); i != e; ++i) + FullyAvailableBlocks[UnavailableBlocks[i]] = false; + + for (pred_iterator PI = pred_begin(LoadBB), E = pred_end(LoadBB); + PI != E; ++PI) { + if (IsValueFullyAvailableInBlock(*PI, FullyAvailableBlocks)) + continue; + + // If this load is not available in multiple predecessors, reject it. + if (UnavailablePred && UnavailablePred != *PI) + return false; + UnavailablePred = *PI; + } + + assert(UnavailablePred != 0 && + "Fully available value should be eliminated above!"); + + // We don't currently handle critical edges :( + if (UnavailablePred->getTerminator()->getNumSuccessors() != 1) { + DEBUG(errs() << "COULD NOT PRE LOAD BECAUSE OF CRITICAL EDGE '" + << UnavailablePred->getName() << "': " << *LI << '\n'); + return false; + } + + // If the loaded pointer is PHI node defined in this block, do PHI translation + // to get its value in the predecessor. + Value *LoadPtr = MD->PHITranslatePointer(LI->getOperand(0), + LoadBB, UnavailablePred, TD); + // Make sure the value is live in the predecessor. MemDep found a computation + // of LPInst with the right value, but that does not dominate UnavailablePred, + // then we can't use it. + if (Instruction *LPInst = dyn_cast_or_null(LoadPtr)) + if (!DT->dominates(LPInst->getParent(), UnavailablePred)) + LoadPtr = 0; + + // If we don't have a computation of this phi translated value, try to insert + // one. + if (LoadPtr == 0) { + LoadPtr = MD->InsertPHITranslatedPointer(LI->getOperand(0), + LoadBB, UnavailablePred, TD); + if (LoadPtr == 0) { + DEBUG(errs() << "COULDN'T INSERT PHI TRANSLATED VALUE OF: " + << *LI->getOperand(0) << "\n"); + return false; + } + + // FIXME: This inserts a computation, but we don't tell scalar GVN + // optimization stuff about it. How do we do this? + DEBUG(errs() << "INSERTED PHI TRANSLATED VALUE: " << *LoadPtr << "\n"); + } + + // Make sure it is valid to move this load here. We have to watch out for: + // @1 = getelementptr (i8* p, ... + // test p and branch if == 0 + // load @1 + // It is valid to have the getelementptr before the test, even if p can be 0, + // as getelementptr only does address arithmetic. + // If we are not pushing the value through any multiple-successor blocks + // we do not have this case. Otherwise, check that the load is safe to + // put anywhere; this can be improved, but should be conservatively safe. + if (!allSingleSucc && + !isSafeToLoadUnconditionally(LoadPtr, UnavailablePred->getTerminator())) + return false; + + // Okay, we can eliminate this load by inserting a reload in the predecessor + // and using PHI construction to get the value in the other predecessors, do + // it. + DEBUG(errs() << "GVN REMOVING PRE LOAD: " << *LI << '\n'); + + Value *NewLoad = new LoadInst(LoadPtr, LI->getName()+".pre", false, + LI->getAlignment(), + UnavailablePred->getTerminator()); + + // Add the newly created load. + ValuesPerBlock.push_back(AvailableValueInBlock::get(UnavailablePred,NewLoad)); + + // Perform PHI construction. + Value *V = ConstructSSAForLoadSet(LI, ValuesPerBlock, TD, + VN.getAliasAnalysis()); + LI->replaceAllUsesWith(V); + if (isa(V)) + V->takeName(LI); + if (isa(V->getType())) + MD->invalidateCachedPointerInfo(V); + toErase.push_back(LI); + NumPRELoad++; + return true; +} + +/// processLoad - Attempt to eliminate a load, first by eliminating it +/// locally, and then attempting non-local elimination if that fails. +bool GVN::processLoad(LoadInst *L, SmallVectorImpl &toErase) { + if (!MD) + return false; + + if (L->isVolatile()) + return false; + + // ... to a pointer that has been loaded from before... + MemDepResult Dep = MD->getDependency(L); + + // If the value isn't available, don't do anything! + if (Dep.isClobber()) { + // FIXME: We should handle memset/memcpy/memmove as dependent instructions + // to forward the value if available. + //if (isa(Dep.getInst())) + //errs() << "LOAD DEPENDS ON MEM: " << *L << "\n" << *Dep.getInst()<<"\n\n"; + + // Check to see if we have something like this: + // store i32 123, i32* %P + // %A = bitcast i32* %P to i8* + // %B = gep i8* %A, i32 1 + // %C = load i8* %B + // + // We could do that by recognizing if the clobber instructions are obviously + // a common base + constant offset, and if the previous store (or memset) + // completely covers this load. This sort of thing can happen in bitfield + // access code. + if (StoreInst *DepSI = dyn_cast(Dep.getInst())) + if (const TargetData *TD = getAnalysisIfAvailable()) { + int Offset = AnalyzeLoadFromClobberingStore(L, DepSI, *TD); + if (Offset != -1) { + Value *AvailVal = GetStoreValueForLoad(DepSI->getOperand(0), Offset, + L->getType(), L, *TD); + DEBUG(errs() << "GVN COERCED STORE BITS:\n" << *DepSI << '\n' + << *AvailVal << '\n' << *L << "\n\n\n"); + + // Replace the load! + L->replaceAllUsesWith(AvailVal); + if (isa(AvailVal->getType())) + MD->invalidateCachedPointerInfo(AvailVal); + toErase.push_back(L); + NumGVNLoad++; + return true; + } + } + + DEBUG( + // fast print dep, using operator<< on instruction would be too slow + errs() << "GVN: load "; + WriteAsOperand(errs(), L); + Instruction *I = Dep.getInst(); + errs() << " is clobbered by " << *I << '\n'; + ); + return false; + } + + // If it is defined in another block, try harder. + if (Dep.isNonLocal()) + return processNonLocalLoad(L, toErase); + + Instruction *DepInst = Dep.getInst(); + if (StoreInst *DepSI = dyn_cast(DepInst)) { + Value *StoredVal = DepSI->getOperand(0); + + // The store and load are to a must-aliased pointer, but they may not + // actually have the same type. See if we know how to reuse the stored + // value (depending on its type). + const TargetData *TD = 0; + if (StoredVal->getType() != L->getType()) { + if ((TD = getAnalysisIfAvailable())) { + StoredVal = CoerceAvailableValueToLoadType(StoredVal, L->getType(), + L, *TD); + if (StoredVal == 0) + return false; + + DEBUG(errs() << "GVN COERCED STORE:\n" << *DepSI << '\n' << *StoredVal + << '\n' << *L << "\n\n\n"); + } + else + return false; + } + + // Remove it! + L->replaceAllUsesWith(StoredVal); + if (isa(StoredVal->getType())) + MD->invalidateCachedPointerInfo(StoredVal); + toErase.push_back(L); + NumGVNLoad++; + return true; + } + + if (LoadInst *DepLI = dyn_cast(DepInst)) { + Value *AvailableVal = DepLI; + + // The loads are of a must-aliased pointer, but they may not actually have + // the same type. See if we know how to reuse the previously loaded value + // (depending on its type). + const TargetData *TD = 0; + if (DepLI->getType() != L->getType()) { + if ((TD = getAnalysisIfAvailable())) { + AvailableVal = CoerceAvailableValueToLoadType(DepLI, L->getType(), L,*TD); + if (AvailableVal == 0) + return false; + + DEBUG(errs() << "GVN COERCED LOAD:\n" << *DepLI << "\n" << *AvailableVal + << "\n" << *L << "\n\n\n"); + } + else + return false; + } + + // Remove it! + L->replaceAllUsesWith(AvailableVal); + if (isa(DepLI->getType())) + MD->invalidateCachedPointerInfo(DepLI); + toErase.push_back(L); + NumGVNLoad++; + return true; + } + + // If this load really doesn't depend on anything, then we must be loading an + // undef value. This can happen when loading for a fresh allocation with no + // intervening stores, for example. + if (isa(DepInst) || isMalloc(DepInst)) { + L->replaceAllUsesWith(UndefValue::get(L->getType())); + toErase.push_back(L); + NumGVNLoad++; + return true; + } + + // If this load occurs either right after a lifetime begin or a lifetime end, + // then the loaded value is undefined. + if (IntrinsicInst* II = dyn_cast(DepInst)) { + if (II->getIntrinsicID() == Intrinsic::lifetime_start || + II->getIntrinsicID() == Intrinsic::lifetime_end) { + L->replaceAllUsesWith(UndefValue::get(L->getType())); + toErase.push_back(L); + NumGVNLoad++; + return true; + } + } + + return false; +} + +Value *GVN::lookupNumber(BasicBlock *BB, uint32_t num) { + DenseMap::iterator I = localAvail.find(BB); + if (I == localAvail.end()) + return 0; + + ValueNumberScope *Locals = I->second; + while (Locals) { + DenseMap::iterator I = Locals->table.find(num); + if (I != Locals->table.end()) + return I->second; + Locals = Locals->parent; + } + + return 0; +} + + +/// processInstruction - When calculating availability, handle an instruction +/// by inserting it into the appropriate sets +bool GVN::processInstruction(Instruction *I, + SmallVectorImpl &toErase) { + if (LoadInst *LI = dyn_cast(I)) { + bool Changed = processLoad(LI, toErase); + + if (!Changed) { + unsigned Num = VN.lookup_or_add(LI); + localAvail[I->getParent()]->table.insert(std::make_pair(Num, LI)); + } + + return Changed; + } + + uint32_t NextNum = VN.getNextUnusedValueNumber(); + unsigned Num = VN.lookup_or_add(I); + + if (BranchInst *BI = dyn_cast(I)) { + localAvail[I->getParent()]->table.insert(std::make_pair(Num, I)); + + if (!BI->isConditional() || isa(BI->getCondition())) + return false; + + Value *BranchCond = BI->getCondition(); + uint32_t CondVN = VN.lookup_or_add(BranchCond); + + BasicBlock *TrueSucc = BI->getSuccessor(0); + BasicBlock *FalseSucc = BI->getSuccessor(1); + + if (TrueSucc->getSinglePredecessor()) + localAvail[TrueSucc]->table[CondVN] = + ConstantInt::getTrue(TrueSucc->getContext()); + if (FalseSucc->getSinglePredecessor()) + localAvail[FalseSucc]->table[CondVN] = + ConstantInt::getFalse(TrueSucc->getContext()); + + return false; + + // Allocations are always uniquely numbered, so we can save time and memory + // by fast failing them. + } else if (isa(I) || isa(I)) { + localAvail[I->getParent()]->table.insert(std::make_pair(Num, I)); + return false; + } + + // Collapse PHI nodes + if (PHINode* p = dyn_cast(I)) { + Value *constVal = CollapsePhi(p); + + if (constVal) { + p->replaceAllUsesWith(constVal); + if (MD && isa(constVal->getType())) + MD->invalidateCachedPointerInfo(constVal); + VN.erase(p); + + toErase.push_back(p); + } else { + localAvail[I->getParent()]->table.insert(std::make_pair(Num, I)); + } + + // If the number we were assigned was a brand new VN, then we don't + // need to do a lookup to see if the number already exists + // somewhere in the domtree: it can't! + } else if (Num == NextNum) { + localAvail[I->getParent()]->table.insert(std::make_pair(Num, I)); + + // Perform fast-path value-number based elimination of values inherited from + // dominators. + } else if (Value *repl = lookupNumber(I->getParent(), Num)) { + // Remove it! + VN.erase(I); + I->replaceAllUsesWith(repl); + if (MD && isa(repl->getType())) + MD->invalidateCachedPointerInfo(repl); + toErase.push_back(I); + return true; + + } else { + localAvail[I->getParent()]->table.insert(std::make_pair(Num, I)); + } + + return false; +} + +/// runOnFunction - This is the main transformation entry point for a function. +bool GVN::runOnFunction(Function& F) { + if (!NoLoads) + MD = &getAnalysis(); + DT = &getAnalysis(); + VN.setAliasAnalysis(&getAnalysis()); + VN.setMemDep(MD); + VN.setDomTree(DT); + + bool Changed = false; + bool ShouldContinue = true; + + // Merge unconditional branches, allowing PRE to catch more + // optimization opportunities. + for (Function::iterator FI = F.begin(), FE = F.end(); FI != FE; ) { + BasicBlock *BB = FI; + ++FI; + bool removedBlock = MergeBlockIntoPredecessor(BB, this); + if (removedBlock) NumGVNBlocks++; + + Changed |= removedBlock; + } + + unsigned Iteration = 0; + + while (ShouldContinue) { + DEBUG(errs() << "GVN iteration: " << Iteration << "\n"); + ShouldContinue = iterateOnFunction(F); + Changed |= ShouldContinue; + ++Iteration; + } + + if (EnablePRE) { + bool PREChanged = true; + while (PREChanged) { + PREChanged = performPRE(F); + Changed |= PREChanged; + } + } + // FIXME: Should perform GVN again after PRE does something. PRE can move + // computations into blocks where they become fully redundant. Note that + // we can't do this until PRE's critical edge splitting updates memdep. + // Actually, when this happens, we should just fully integrate PRE into GVN. + + cleanupGlobalSets(); + + return Changed; +} + + +bool GVN::processBlock(BasicBlock *BB) { + // FIXME: Kill off toErase by doing erasing eagerly in a helper function (and + // incrementing BI before processing an instruction). + SmallVector toErase; + bool ChangedFunction = false; + + for (BasicBlock::iterator BI = BB->begin(), BE = BB->end(); + BI != BE;) { + ChangedFunction |= processInstruction(BI, toErase); + if (toErase.empty()) { + ++BI; + continue; + } + + // If we need some instructions deleted, do it now. + NumGVNInstr += toErase.size(); + + // Avoid iterator invalidation. + bool AtStart = BI == BB->begin(); + if (!AtStart) + --BI; + + for (SmallVector::iterator I = toErase.begin(), + E = toErase.end(); I != E; ++I) { + DEBUG(errs() << "GVN removed: " << **I << '\n'); + if (MD) MD->removeInstruction(*I); + (*I)->eraseFromParent(); + DEBUG(verifyRemoved(*I)); + } + toErase.clear(); + + if (AtStart) + BI = BB->begin(); + else + ++BI; + } + + return ChangedFunction; +} + +/// performPRE - Perform a purely local form of PRE that looks for diamond +/// control flow patterns and attempts to perform simple PRE at the join point. +bool GVN::performPRE(Function &F) { + bool Changed = false; + SmallVector, 4> toSplit; + DenseMap predMap; + for (df_iterator DI = df_begin(&F.getEntryBlock()), + DE = df_end(&F.getEntryBlock()); DI != DE; ++DI) { + BasicBlock *CurrentBlock = *DI; + + // Nothing to PRE in the entry block. + if (CurrentBlock == &F.getEntryBlock()) continue; + + for (BasicBlock::iterator BI = CurrentBlock->begin(), + BE = CurrentBlock->end(); BI != BE; ) { + Instruction *CurInst = BI++; + + if (isa(CurInst) || + isa(CurInst) || isa(CurInst) || + CurInst->getType()->isVoidTy() || + CurInst->mayReadFromMemory() || CurInst->mayHaveSideEffects() || + isa(CurInst)) + continue; + + uint32_t ValNo = VN.lookup(CurInst); + + // Look for the predecessors for PRE opportunities. We're + // only trying to solve the basic diamond case, where + // a value is computed in the successor and one predecessor, + // but not the other. We also explicitly disallow cases + // where the successor is its own predecessor, because they're + // more complicated to get right. + unsigned NumWith = 0; + unsigned NumWithout = 0; + BasicBlock *PREPred = 0; + predMap.clear(); + + for (pred_iterator PI = pred_begin(CurrentBlock), + PE = pred_end(CurrentBlock); PI != PE; ++PI) { + // We're not interested in PRE where the block is its + // own predecessor, on in blocks with predecessors + // that are not reachable. + if (*PI == CurrentBlock) { + NumWithout = 2; + break; + } else if (!localAvail.count(*PI)) { + NumWithout = 2; + break; + } + + DenseMap::iterator predV = + localAvail[*PI]->table.find(ValNo); + if (predV == localAvail[*PI]->table.end()) { + PREPred = *PI; + NumWithout++; + } else if (predV->second == CurInst) { + NumWithout = 2; + } else { + predMap[*PI] = predV->second; + NumWith++; + } + } + + // Don't do PRE when it might increase code size, i.e. when + // we would need to insert instructions in more than one pred. + if (NumWithout != 1 || NumWith == 0) + continue; + + // Don't do PRE across indirect branch. + if (isa(PREPred->getTerminator())) + continue; + + // We can't do PRE safely on a critical edge, so instead we schedule + // the edge to be split and perform the PRE the next time we iterate + // on the function. + unsigned SuccNum = 0; + for (unsigned i = 0, e = PREPred->getTerminator()->getNumSuccessors(); + i != e; ++i) + if (PREPred->getTerminator()->getSuccessor(i) == CurrentBlock) { + SuccNum = i; + break; + } + + if (isCriticalEdge(PREPred->getTerminator(), SuccNum)) { + toSplit.push_back(std::make_pair(PREPred->getTerminator(), SuccNum)); + continue; + } + + // Instantiate the expression the in predecessor that lacked it. + // Because we are going top-down through the block, all value numbers + // will be available in the predecessor by the time we need them. Any + // that weren't original present will have been instantiated earlier + // in this loop. + Instruction *PREInstr = CurInst->clone(); + bool success = true; + for (unsigned i = 0, e = CurInst->getNumOperands(); i != e; ++i) { + Value *Op = PREInstr->getOperand(i); + if (isa(Op) || isa(Op) || isa(Op)) + continue; + + if (Value *V = lookupNumber(PREPred, VN.lookup(Op))) { + PREInstr->setOperand(i, V); + } else { + success = false; + break; + } + } + + // Fail out if we encounter an operand that is not available in + // the PRE predecessor. This is typically because of loads which + // are not value numbered precisely. + if (!success) { + delete PREInstr; + DEBUG(verifyRemoved(PREInstr)); + continue; + } + + PREInstr->insertBefore(PREPred->getTerminator()); + PREInstr->setName(CurInst->getName() + ".pre"); + predMap[PREPred] = PREInstr; + VN.add(PREInstr, ValNo); + NumGVNPRE++; + + // Update the availability map to include the new instruction. + localAvail[PREPred]->table.insert(std::make_pair(ValNo, PREInstr)); + + // Create a PHI to make the value available in this block. + PHINode* Phi = PHINode::Create(CurInst->getType(), + CurInst->getName() + ".pre-phi", + CurrentBlock->begin()); + for (pred_iterator PI = pred_begin(CurrentBlock), + PE = pred_end(CurrentBlock); PI != PE; ++PI) + Phi->addIncoming(predMap[*PI], *PI); + + VN.add(Phi, ValNo); + localAvail[CurrentBlock]->table[ValNo] = Phi; + + CurInst->replaceAllUsesWith(Phi); + if (MD && isa(Phi->getType())) + MD->invalidateCachedPointerInfo(Phi); + VN.erase(CurInst); + + DEBUG(errs() << "GVN PRE removed: " << *CurInst << '\n'); + if (MD) MD->removeInstruction(CurInst); + CurInst->eraseFromParent(); + DEBUG(verifyRemoved(CurInst)); + Changed = true; + } + } + + for (SmallVector, 4>::iterator + I = toSplit.begin(), E = toSplit.end(); I != E; ++I) + SplitCriticalEdge(I->first, I->second, this); + + return Changed || toSplit.size(); +} + +/// iterateOnFunction - Executes one iteration of GVN +bool GVN::iterateOnFunction(Function &F) { + cleanupGlobalSets(); + + for (df_iterator DI = df_begin(DT->getRootNode()), + DE = df_end(DT->getRootNode()); DI != DE; ++DI) { + if (DI->getIDom()) + localAvail[DI->getBlock()] = + new ValueNumberScope(localAvail[DI->getIDom()->getBlock()]); + else + localAvail[DI->getBlock()] = new ValueNumberScope(0); + } + + // Top-down walk of the dominator tree + bool Changed = false; +#if 0 + // Needed for value numbering with phi construction to work. + ReversePostOrderTraversal RPOT(&F); + for (ReversePostOrderTraversal::rpo_iterator RI = RPOT.begin(), + RE = RPOT.end(); RI != RE; ++RI) + Changed |= processBlock(*RI); +#else + for (df_iterator DI = df_begin(DT->getRootNode()), + DE = df_end(DT->getRootNode()); DI != DE; ++DI) + Changed |= processBlock(DI->getBlock()); +#endif + + return Changed; +} + +void GVN::cleanupGlobalSets() { + VN.clear(); + + for (DenseMap::iterator + I = localAvail.begin(), E = localAvail.end(); I != E; ++I) + delete I->second; + localAvail.clear(); +} + +/// verifyRemoved - Verify that the specified instruction does not occur in our +/// internal data structures. +void GVN::verifyRemoved(const Instruction *Inst) const { + VN.verifyRemoved(Inst); + + // Walk through the value number scope to make sure the instruction isn't + // ferreted away in it. + for (DenseMap::const_iterator + I = localAvail.begin(), E = localAvail.end(); I != E; ++I) { + const ValueNumberScope *VNS = I->second; + + while (VNS) { + for (DenseMap::const_iterator + II = VNS->table.begin(), IE = VNS->table.end(); II != IE; ++II) { + assert(II->second != Inst && "Inst still in value numbering scope!"); + } + + VNS = VNS->parent; + } + } +} diff --git a/libclamav/c++/llvm/lib/Transforms/Scalar/IndVarSimplify.cpp b/libclamav/c++/llvm/lib/Transforms/Scalar/IndVarSimplify.cpp new file mode 100644 index 000000000..2912421e7 --- /dev/null +++ b/libclamav/c++/llvm/lib/Transforms/Scalar/IndVarSimplify.cpp @@ -0,0 +1,778 @@ +//===- IndVarSimplify.cpp - Induction Variable Elimination ----------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This transformation analyzes and transforms the induction variables (and +// computations derived from them) into simpler forms suitable for subsequent +// analysis and transformation. +// +// This transformation makes the following changes to each loop with an +// identifiable induction variable: +// 1. All loops are transformed to have a SINGLE canonical induction variable +// which starts at zero and steps by one. +// 2. The canonical induction variable is guaranteed to be the first PHI node +// in the loop header block. +// 3. The canonical induction variable is guaranteed to be in a wide enough +// type so that IV expressions need not be (directly) zero-extended or +// sign-extended. +// 4. Any pointer arithmetic recurrences are raised to use array subscripts. +// +// If the trip count of a loop is computable, this pass also makes the following +// changes: +// 1. The exit condition for the loop is canonicalized to compare the +// induction value against the exit value. This turns loops like: +// 'for (i = 7; i*i < 1000; ++i)' into 'for (i = 0; i != 25; ++i)' +// 2. Any use outside of the loop of an expression derived from the indvar +// is changed to compute the derived value outside of the loop, eliminating +// the dependence on the exit value of the induction variable. If the only +// purpose of the loop is to compute the exit value of some derived +// expression, this transformation will make the loop dead. +// +// This transformation should be followed by strength reduction after all of the +// desired loop transformations have been performed. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "indvars" +#include "llvm/Transforms/Scalar.h" +#include "llvm/BasicBlock.h" +#include "llvm/Constants.h" +#include "llvm/Instructions.h" +#include "llvm/LLVMContext.h" +#include "llvm/Type.h" +#include "llvm/Analysis/Dominators.h" +#include "llvm/Analysis/IVUsers.h" +#include "llvm/Analysis/ScalarEvolutionExpander.h" +#include "llvm/Analysis/LoopInfo.h" +#include "llvm/Analysis/LoopPass.h" +#include "llvm/Support/CFG.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Transforms/Utils/Local.h" +#include "llvm/Transforms/Utils/BasicBlockUtils.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/ADT/STLExtras.h" +using namespace llvm; + +STATISTIC(NumRemoved , "Number of aux indvars removed"); +STATISTIC(NumInserted, "Number of canonical indvars added"); +STATISTIC(NumReplaced, "Number of exit values replaced"); +STATISTIC(NumLFTR , "Number of loop exit tests replaced"); + +namespace { + class IndVarSimplify : public LoopPass { + IVUsers *IU; + LoopInfo *LI; + ScalarEvolution *SE; + DominatorTree *DT; + bool Changed; + public: + + static char ID; // Pass identification, replacement for typeid + IndVarSimplify() : LoopPass(&ID) {} + + virtual bool runOnLoop(Loop *L, LPPassManager &LPM); + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.addRequired(); + AU.addRequired(); + AU.addRequired(); + AU.addRequiredID(LoopSimplifyID); + AU.addRequiredID(LCSSAID); + AU.addRequired(); + AU.addPreserved(); + AU.addPreservedID(LoopSimplifyID); + AU.addPreservedID(LCSSAID); + AU.addPreserved(); + AU.setPreservesCFG(); + } + + private: + + void RewriteNonIntegerIVs(Loop *L); + + ICmpInst *LinearFunctionTestReplace(Loop *L, const SCEV *BackedgeTakenCount, + Value *IndVar, + BasicBlock *ExitingBlock, + BranchInst *BI, + SCEVExpander &Rewriter); + void RewriteLoopExitValues(Loop *L, const SCEV *BackedgeTakenCount, + SCEVExpander &Rewriter); + + void RewriteIVExpressions(Loop *L, const Type *LargestType, + SCEVExpander &Rewriter); + + void SinkUnusedInvariants(Loop *L); + + void HandleFloatingPointIV(Loop *L, PHINode *PH); + }; +} + +char IndVarSimplify::ID = 0; +static RegisterPass +X("indvars", "Canonicalize Induction Variables"); + +Pass *llvm::createIndVarSimplifyPass() { + return new IndVarSimplify(); +} + +/// LinearFunctionTestReplace - This method rewrites the exit condition of the +/// loop to be a canonical != comparison against the incremented loop induction +/// variable. This pass is able to rewrite the exit tests of any loop where the +/// SCEV analysis can determine a loop-invariant trip count of the loop, which +/// is actually a much broader range than just linear tests. +ICmpInst *IndVarSimplify::LinearFunctionTestReplace(Loop *L, + const SCEV *BackedgeTakenCount, + Value *IndVar, + BasicBlock *ExitingBlock, + BranchInst *BI, + SCEVExpander &Rewriter) { + // If the exiting block is not the same as the backedge block, we must compare + // against the preincremented value, otherwise we prefer to compare against + // the post-incremented value. + Value *CmpIndVar; + const SCEV *RHS = BackedgeTakenCount; + if (ExitingBlock == L->getLoopLatch()) { + // Add one to the "backedge-taken" count to get the trip count. + // If this addition may overflow, we have to be more pessimistic and + // cast the induction variable before doing the add. + const SCEV *Zero = SE->getIntegerSCEV(0, BackedgeTakenCount->getType()); + const SCEV *N = + SE->getAddExpr(BackedgeTakenCount, + SE->getIntegerSCEV(1, BackedgeTakenCount->getType())); + if ((isa(N) && !N->isZero()) || + SE->isLoopGuardedByCond(L, ICmpInst::ICMP_NE, N, Zero)) { + // No overflow. Cast the sum. + RHS = SE->getTruncateOrZeroExtend(N, IndVar->getType()); + } else { + // Potential overflow. Cast before doing the add. + RHS = SE->getTruncateOrZeroExtend(BackedgeTakenCount, + IndVar->getType()); + RHS = SE->getAddExpr(RHS, + SE->getIntegerSCEV(1, IndVar->getType())); + } + + // The BackedgeTaken expression contains the number of times that the + // backedge branches to the loop header. This is one less than the + // number of times the loop executes, so use the incremented indvar. + CmpIndVar = L->getCanonicalInductionVariableIncrement(); + } else { + // We have to use the preincremented value... + RHS = SE->getTruncateOrZeroExtend(BackedgeTakenCount, + IndVar->getType()); + CmpIndVar = IndVar; + } + + // Expand the code for the iteration count. + assert(RHS->isLoopInvariant(L) && + "Computed iteration count is not loop invariant!"); + Value *ExitCnt = Rewriter.expandCodeFor(RHS, IndVar->getType(), BI); + + // Insert a new icmp_ne or icmp_eq instruction before the branch. + ICmpInst::Predicate Opcode; + if (L->contains(BI->getSuccessor(0))) + Opcode = ICmpInst::ICMP_NE; + else + Opcode = ICmpInst::ICMP_EQ; + + DEBUG(errs() << "INDVARS: Rewriting loop exit condition to:\n" + << " LHS:" << *CmpIndVar << '\n' + << " op:\t" + << (Opcode == ICmpInst::ICMP_NE ? "!=" : "==") << "\n" + << " RHS:\t" << *RHS << "\n"); + + ICmpInst *Cond = new ICmpInst(BI, Opcode, CmpIndVar, ExitCnt, "exitcond"); + + Instruction *OrigCond = cast(BI->getCondition()); + // It's tempting to use replaceAllUsesWith here to fully replace the old + // comparison, but that's not immediately safe, since users of the old + // comparison may not be dominated by the new comparison. Instead, just + // update the branch to use the new comparison; in the common case this + // will make old comparison dead. + BI->setCondition(Cond); + RecursivelyDeleteTriviallyDeadInstructions(OrigCond); + + ++NumLFTR; + Changed = true; + return Cond; +} + +/// RewriteLoopExitValues - Check to see if this loop has a computable +/// loop-invariant execution count. If so, this means that we can compute the +/// final value of any expressions that are recurrent in the loop, and +/// substitute the exit values from the loop into any instructions outside of +/// the loop that use the final values of the current expressions. +/// +/// This is mostly redundant with the regular IndVarSimplify activities that +/// happen later, except that it's more powerful in some cases, because it's +/// able to brute-force evaluate arbitrary instructions as long as they have +/// constant operands at the beginning of the loop. +void IndVarSimplify::RewriteLoopExitValues(Loop *L, + const SCEV *BackedgeTakenCount, + SCEVExpander &Rewriter) { + // Verify the input to the pass in already in LCSSA form. + assert(L->isLCSSAForm()); + + SmallVector ExitBlocks; + L->getUniqueExitBlocks(ExitBlocks); + + // Find all values that are computed inside the loop, but used outside of it. + // Because of LCSSA, these values will only occur in LCSSA PHI Nodes. Scan + // the exit blocks of the loop to find them. + for (unsigned i = 0, e = ExitBlocks.size(); i != e; ++i) { + BasicBlock *ExitBB = ExitBlocks[i]; + + // If there are no PHI nodes in this exit block, then no values defined + // inside the loop are used on this path, skip it. + PHINode *PN = dyn_cast(ExitBB->begin()); + if (!PN) continue; + + unsigned NumPreds = PN->getNumIncomingValues(); + + // Iterate over all of the PHI nodes. + BasicBlock::iterator BBI = ExitBB->begin(); + while ((PN = dyn_cast(BBI++))) { + if (PN->use_empty()) + continue; // dead use, don't replace it + // Iterate over all of the values in all the PHI nodes. + for (unsigned i = 0; i != NumPreds; ++i) { + // If the value being merged in is not integer or is not defined + // in the loop, skip it. + Value *InVal = PN->getIncomingValue(i); + if (!isa(InVal) || + // SCEV only supports integer expressions for now. + (!isa(InVal->getType()) && + !isa(InVal->getType()))) + continue; + + // If this pred is for a subloop, not L itself, skip it. + if (LI->getLoopFor(PN->getIncomingBlock(i)) != L) + continue; // The Block is in a subloop, skip it. + + // Check that InVal is defined in the loop. + Instruction *Inst = cast(InVal); + if (!L->contains(Inst->getParent())) + continue; + + // Okay, this instruction has a user outside of the current loop + // and varies predictably *inside* the loop. Evaluate the value it + // contains when the loop exits, if possible. + const SCEV *ExitValue = SE->getSCEVAtScope(Inst, L->getParentLoop()); + if (!ExitValue->isLoopInvariant(L)) + continue; + + Changed = true; + ++NumReplaced; + + Value *ExitVal = Rewriter.expandCodeFor(ExitValue, PN->getType(), Inst); + + DEBUG(errs() << "INDVARS: RLEV: AfterLoopVal = " << *ExitVal << '\n' + << " LoopVal = " << *Inst << "\n"); + + PN->setIncomingValue(i, ExitVal); + + // If this instruction is dead now, delete it. + RecursivelyDeleteTriviallyDeadInstructions(Inst); + + if (NumPreds == 1) { + // Completely replace a single-pred PHI. This is safe, because the + // NewVal won't be variant in the loop, so we don't need an LCSSA phi + // node anymore. + PN->replaceAllUsesWith(ExitVal); + RecursivelyDeleteTriviallyDeadInstructions(PN); + } + } + if (NumPreds != 1) { + // Clone the PHI and delete the original one. This lets IVUsers and + // any other maps purge the original user from their records. + PHINode *NewPN = cast(PN->clone()); + NewPN->takeName(PN); + NewPN->insertBefore(PN); + PN->replaceAllUsesWith(NewPN); + PN->eraseFromParent(); + } + } + } +} + +void IndVarSimplify::RewriteNonIntegerIVs(Loop *L) { + // First step. Check to see if there are any floating-point recurrences. + // If there are, change them into integer recurrences, permitting analysis by + // the SCEV routines. + // + BasicBlock *Header = L->getHeader(); + + SmallVector PHIs; + for (BasicBlock::iterator I = Header->begin(); + PHINode *PN = dyn_cast(I); ++I) + PHIs.push_back(PN); + + for (unsigned i = 0, e = PHIs.size(); i != e; ++i) + if (PHINode *PN = dyn_cast_or_null(PHIs[i])) + HandleFloatingPointIV(L, PN); + + // If the loop previously had floating-point IV, ScalarEvolution + // may not have been able to compute a trip count. Now that we've done some + // re-writing, the trip count may be computable. + if (Changed) + SE->forgetLoop(L); +} + +bool IndVarSimplify::runOnLoop(Loop *L, LPPassManager &LPM) { + IU = &getAnalysis(); + LI = &getAnalysis(); + SE = &getAnalysis(); + DT = &getAnalysis(); + Changed = false; + + // If there are any floating-point recurrences, attempt to + // transform them to use integer recurrences. + RewriteNonIntegerIVs(L); + + BasicBlock *ExitingBlock = L->getExitingBlock(); // may be null + const SCEV *BackedgeTakenCount = SE->getBackedgeTakenCount(L); + + // Create a rewriter object which we'll use to transform the code with. + SCEVExpander Rewriter(*SE); + + // Check to see if this loop has a computable loop-invariant execution count. + // If so, this means that we can compute the final value of any expressions + // that are recurrent in the loop, and substitute the exit values from the + // loop into any instructions outside of the loop that use the final values of + // the current expressions. + // + if (!isa(BackedgeTakenCount)) + RewriteLoopExitValues(L, BackedgeTakenCount, Rewriter); + + // Compute the type of the largest recurrence expression, and decide whether + // a canonical induction variable should be inserted. + const Type *LargestType = 0; + bool NeedCannIV = false; + if (!isa(BackedgeTakenCount)) { + LargestType = BackedgeTakenCount->getType(); + LargestType = SE->getEffectiveSCEVType(LargestType); + // If we have a known trip count and a single exit block, we'll be + // rewriting the loop exit test condition below, which requires a + // canonical induction variable. + if (ExitingBlock) + NeedCannIV = true; + } + for (unsigned i = 0, e = IU->StrideOrder.size(); i != e; ++i) { + const SCEV *Stride = IU->StrideOrder[i]; + const Type *Ty = SE->getEffectiveSCEVType(Stride->getType()); + if (!LargestType || + SE->getTypeSizeInBits(Ty) > + SE->getTypeSizeInBits(LargestType)) + LargestType = Ty; + + std::map::iterator SI = + IU->IVUsesByStride.find(IU->StrideOrder[i]); + assert(SI != IU->IVUsesByStride.end() && "Stride doesn't exist!"); + + if (!SI->second->Users.empty()) + NeedCannIV = true; + } + + // Now that we know the largest of of the induction variable expressions + // in this loop, insert a canonical induction variable of the largest size. + Value *IndVar = 0; + if (NeedCannIV) { + // Check to see if the loop already has a canonical-looking induction + // variable. If one is present and it's wider than the planned canonical + // induction variable, temporarily remove it, so that the Rewriter + // doesn't attempt to reuse it. + PHINode *OldCannIV = L->getCanonicalInductionVariable(); + if (OldCannIV) { + if (SE->getTypeSizeInBits(OldCannIV->getType()) > + SE->getTypeSizeInBits(LargestType)) + OldCannIV->removeFromParent(); + else + OldCannIV = 0; + } + + IndVar = Rewriter.getOrInsertCanonicalInductionVariable(L, LargestType); + + ++NumInserted; + Changed = true; + DEBUG(errs() << "INDVARS: New CanIV: " << *IndVar << '\n'); + + // Now that the official induction variable is established, reinsert + // the old canonical-looking variable after it so that the IR remains + // consistent. It will be deleted as part of the dead-PHI deletion at + // the end of the pass. + if (OldCannIV) + OldCannIV->insertAfter(cast(IndVar)); + } + + // If we have a trip count expression, rewrite the loop's exit condition + // using it. We can currently only handle loops with a single exit. + ICmpInst *NewICmp = 0; + if (!isa(BackedgeTakenCount) && ExitingBlock) { + assert(NeedCannIV && + "LinearFunctionTestReplace requires a canonical induction variable"); + // Can't rewrite non-branch yet. + if (BranchInst *BI = dyn_cast(ExitingBlock->getTerminator())) + NewICmp = LinearFunctionTestReplace(L, BackedgeTakenCount, IndVar, + ExitingBlock, BI, Rewriter); + } + + // Rewrite IV-derived expressions. Clears the rewriter cache. + RewriteIVExpressions(L, LargestType, Rewriter); + + // The Rewriter may not be used from this point on. + + // Loop-invariant instructions in the preheader that aren't used in the + // loop may be sunk below the loop to reduce register pressure. + SinkUnusedInvariants(L); + + // For completeness, inform IVUsers of the IV use in the newly-created + // loop exit test instruction. + if (NewICmp) + IU->AddUsersIfInteresting(cast(NewICmp->getOperand(0))); + + // Clean up dead instructions. + DeleteDeadPHIs(L->getHeader()); + // Check a post-condition. + assert(L->isLCSSAForm() && "Indvars did not leave the loop in lcssa form!"); + return Changed; +} + +void IndVarSimplify::RewriteIVExpressions(Loop *L, const Type *LargestType, + SCEVExpander &Rewriter) { + SmallVector DeadInsts; + + // Rewrite all induction variable expressions in terms of the canonical + // induction variable. + // + // If there were induction variables of other sizes or offsets, manually + // add the offsets to the primary induction variable and cast, avoiding + // the need for the code evaluation methods to insert induction variables + // of different sizes. + for (unsigned i = 0, e = IU->StrideOrder.size(); i != e; ++i) { + const SCEV *Stride = IU->StrideOrder[i]; + + std::map::iterator SI = + IU->IVUsesByStride.find(IU->StrideOrder[i]); + assert(SI != IU->IVUsesByStride.end() && "Stride doesn't exist!"); + ilist &List = SI->second->Users; + for (ilist::iterator UI = List.begin(), + E = List.end(); UI != E; ++UI) { + Value *Op = UI->getOperandValToReplace(); + const Type *UseTy = Op->getType(); + Instruction *User = UI->getUser(); + + // Compute the final addrec to expand into code. + const SCEV *AR = IU->getReplacementExpr(*UI); + + // FIXME: It is an extremely bad idea to indvar substitute anything more + // complex than affine induction variables. Doing so will put expensive + // polynomial evaluations inside of the loop, and the str reduction pass + // currently can only reduce affine polynomials. For now just disable + // indvar subst on anything more complex than an affine addrec, unless + // it can be expanded to a trivial value. + if (!AR->isLoopInvariant(L) && !Stride->isLoopInvariant(L)) + continue; + + // Determine the insertion point for this user. By default, insert + // immediately before the user. The SCEVExpander class will automatically + // hoist loop invariants out of the loop. For PHI nodes, there may be + // multiple uses, so compute the nearest common dominator for the + // incoming blocks. + Instruction *InsertPt = User; + if (PHINode *PHI = dyn_cast(InsertPt)) + for (unsigned i = 0, e = PHI->getNumIncomingValues(); i != e; ++i) + if (PHI->getIncomingValue(i) == Op) { + if (InsertPt == User) + InsertPt = PHI->getIncomingBlock(i)->getTerminator(); + else + InsertPt = + DT->findNearestCommonDominator(InsertPt->getParent(), + PHI->getIncomingBlock(i)) + ->getTerminator(); + } + + // Now expand it into actual Instructions and patch it into place. + Value *NewVal = Rewriter.expandCodeFor(AR, UseTy, InsertPt); + + // Patch the new value into place. + if (Op->hasName()) + NewVal->takeName(Op); + User->replaceUsesOfWith(Op, NewVal); + UI->setOperandValToReplace(NewVal); + DEBUG(errs() << "INDVARS: Rewrote IV '" << *AR << "' " << *Op << '\n' + << " into = " << *NewVal << "\n"); + ++NumRemoved; + Changed = true; + + // The old value may be dead now. + DeadInsts.push_back(Op); + } + } + + // Clear the rewriter cache, because values that are in the rewriter's cache + // can be deleted in the loop below, causing the AssertingVH in the cache to + // trigger. + Rewriter.clear(); + // Now that we're done iterating through lists, clean up any instructions + // which are now dead. + while (!DeadInsts.empty()) { + Instruction *Inst = dyn_cast_or_null(DeadInsts.pop_back_val()); + if (Inst) + RecursivelyDeleteTriviallyDeadInstructions(Inst); + } +} + +/// If there's a single exit block, sink any loop-invariant values that +/// were defined in the preheader but not used inside the loop into the +/// exit block to reduce register pressure in the loop. +void IndVarSimplify::SinkUnusedInvariants(Loop *L) { + BasicBlock *ExitBlock = L->getExitBlock(); + if (!ExitBlock) return; + + BasicBlock *Preheader = L->getLoopPreheader(); + if (!Preheader) return; + + Instruction *InsertPt = ExitBlock->getFirstNonPHI(); + BasicBlock::iterator I = Preheader->getTerminator(); + while (I != Preheader->begin()) { + --I; + // New instructions were inserted at the end of the preheader. + if (isa(I)) + break; + // Don't move instructions which might have side effects, since the side + // effects need to complete before instructions inside the loop. Also + // don't move instructions which might read memory, since the loop may + // modify memory. Note that it's okay if the instruction might have + // undefined behavior: LoopSimplify guarantees that the preheader + // dominates the exit block. + if (I->mayHaveSideEffects() || I->mayReadFromMemory()) + continue; + // Don't sink static AllocaInsts out of the entry block, which would + // turn them into dynamic allocas! + if (AllocaInst *AI = dyn_cast(I)) + if (AI->isStaticAlloca()) + continue; + // Determine if there is a use in or before the loop (direct or + // otherwise). + bool UsedInLoop = false; + for (Value::use_iterator UI = I->use_begin(), UE = I->use_end(); + UI != UE; ++UI) { + BasicBlock *UseBB = cast(UI)->getParent(); + if (PHINode *P = dyn_cast(UI)) { + unsigned i = + PHINode::getIncomingValueNumForOperand(UI.getOperandNo()); + UseBB = P->getIncomingBlock(i); + } + if (UseBB == Preheader || L->contains(UseBB)) { + UsedInLoop = true; + break; + } + } + // If there is, the def must remain in the preheader. + if (UsedInLoop) + continue; + // Otherwise, sink it to the exit block. + Instruction *ToMove = I; + bool Done = false; + if (I != Preheader->begin()) + --I; + else + Done = true; + ToMove->moveBefore(InsertPt); + if (Done) + break; + InsertPt = ToMove; + } +} + +/// Return true if it is OK to use SIToFPInst for an inducation variable +/// with given inital and exit values. +static bool useSIToFPInst(ConstantFP &InitV, ConstantFP &ExitV, + uint64_t intIV, uint64_t intEV) { + + if (InitV.getValueAPF().isNegative() || ExitV.getValueAPF().isNegative()) + return true; + + // If the iteration range can be handled by SIToFPInst then use it. + APInt Max = APInt::getSignedMaxValue(32); + if (Max.getZExtValue() > static_cast(abs64(intEV - intIV))) + return true; + + return false; +} + +/// convertToInt - Convert APF to an integer, if possible. +static bool convertToInt(const APFloat &APF, uint64_t *intVal) { + + bool isExact = false; + if (&APF.getSemantics() == &APFloat::PPCDoubleDouble) + return false; + if (APF.convertToInteger(intVal, 32, APF.isNegative(), + APFloat::rmTowardZero, &isExact) + != APFloat::opOK) + return false; + if (!isExact) + return false; + return true; + +} + +/// HandleFloatingPointIV - If the loop has floating induction variable +/// then insert corresponding integer induction variable if possible. +/// For example, +/// for(double i = 0; i < 10000; ++i) +/// bar(i) +/// is converted into +/// for(int i = 0; i < 10000; ++i) +/// bar((double)i); +/// +void IndVarSimplify::HandleFloatingPointIV(Loop *L, PHINode *PH) { + + unsigned IncomingEdge = L->contains(PH->getIncomingBlock(0)); + unsigned BackEdge = IncomingEdge^1; + + // Check incoming value. + ConstantFP *InitValue = dyn_cast(PH->getIncomingValue(IncomingEdge)); + if (!InitValue) return; + uint64_t newInitValue = + Type::getInt32Ty(PH->getContext())->getPrimitiveSizeInBits(); + if (!convertToInt(InitValue->getValueAPF(), &newInitValue)) + return; + + // Check IV increment. Reject this PH if increement operation is not + // an add or increment value can not be represented by an integer. + BinaryOperator *Incr = + dyn_cast(PH->getIncomingValue(BackEdge)); + if (!Incr) return; + if (Incr->getOpcode() != Instruction::FAdd) return; + ConstantFP *IncrValue = NULL; + unsigned IncrVIndex = 1; + if (Incr->getOperand(1) == PH) + IncrVIndex = 0; + IncrValue = dyn_cast(Incr->getOperand(IncrVIndex)); + if (!IncrValue) return; + uint64_t newIncrValue = + Type::getInt32Ty(PH->getContext())->getPrimitiveSizeInBits(); + if (!convertToInt(IncrValue->getValueAPF(), &newIncrValue)) + return; + + // Check Incr uses. One user is PH and the other users is exit condition used + // by the conditional terminator. + Value::use_iterator IncrUse = Incr->use_begin(); + Instruction *U1 = cast(IncrUse++); + if (IncrUse == Incr->use_end()) return; + Instruction *U2 = cast(IncrUse++); + if (IncrUse != Incr->use_end()) return; + + // Find exit condition. + FCmpInst *EC = dyn_cast(U1); + if (!EC) + EC = dyn_cast(U2); + if (!EC) return; + + if (BranchInst *BI = dyn_cast(EC->getParent()->getTerminator())) { + if (!BI->isConditional()) return; + if (BI->getCondition() != EC) return; + } + + // Find exit value. If exit value can not be represented as an interger then + // do not handle this floating point PH. + ConstantFP *EV = NULL; + unsigned EVIndex = 1; + if (EC->getOperand(1) == Incr) + EVIndex = 0; + EV = dyn_cast(EC->getOperand(EVIndex)); + if (!EV) return; + uint64_t intEV = Type::getInt32Ty(PH->getContext())->getPrimitiveSizeInBits(); + if (!convertToInt(EV->getValueAPF(), &intEV)) + return; + + // Find new predicate for integer comparison. + CmpInst::Predicate NewPred = CmpInst::BAD_ICMP_PREDICATE; + switch (EC->getPredicate()) { + case CmpInst::FCMP_OEQ: + case CmpInst::FCMP_UEQ: + NewPred = CmpInst::ICMP_EQ; + break; + case CmpInst::FCMP_OGT: + case CmpInst::FCMP_UGT: + NewPred = CmpInst::ICMP_UGT; + break; + case CmpInst::FCMP_OGE: + case CmpInst::FCMP_UGE: + NewPred = CmpInst::ICMP_UGE; + break; + case CmpInst::FCMP_OLT: + case CmpInst::FCMP_ULT: + NewPred = CmpInst::ICMP_ULT; + break; + case CmpInst::FCMP_OLE: + case CmpInst::FCMP_ULE: + NewPred = CmpInst::ICMP_ULE; + break; + default: + break; + } + if (NewPred == CmpInst::BAD_ICMP_PREDICATE) return; + + // Insert new integer induction variable. + PHINode *NewPHI = PHINode::Create(Type::getInt32Ty(PH->getContext()), + PH->getName()+".int", PH); + NewPHI->addIncoming(ConstantInt::get(Type::getInt32Ty(PH->getContext()), + newInitValue), + PH->getIncomingBlock(IncomingEdge)); + + Value *NewAdd = BinaryOperator::CreateAdd(NewPHI, + ConstantInt::get(Type::getInt32Ty(PH->getContext()), + newIncrValue), + Incr->getName()+".int", Incr); + NewPHI->addIncoming(NewAdd, PH->getIncomingBlock(BackEdge)); + + // The back edge is edge 1 of newPHI, whatever it may have been in the + // original PHI. + ConstantInt *NewEV = ConstantInt::get(Type::getInt32Ty(PH->getContext()), + intEV); + Value *LHS = (EVIndex == 1 ? NewPHI->getIncomingValue(1) : NewEV); + Value *RHS = (EVIndex == 1 ? NewEV : NewPHI->getIncomingValue(1)); + ICmpInst *NewEC = new ICmpInst(EC->getParent()->getTerminator(), + NewPred, LHS, RHS, EC->getName()); + + // In the following deltions, PH may become dead and may be deleted. + // Use a WeakVH to observe whether this happens. + WeakVH WeakPH = PH; + + // Delete old, floating point, exit comparision instruction. + NewEC->takeName(EC); + EC->replaceAllUsesWith(NewEC); + RecursivelyDeleteTriviallyDeadInstructions(EC); + + // Delete old, floating point, increment instruction. + Incr->replaceAllUsesWith(UndefValue::get(Incr->getType())); + RecursivelyDeleteTriviallyDeadInstructions(Incr); + + // Replace floating induction variable, if it isn't already deleted. + // Give SIToFPInst preference over UIToFPInst because it is faster on + // platforms that are widely used. + if (WeakPH && !PH->use_empty()) { + if (useSIToFPInst(*InitValue, *EV, newInitValue, intEV)) { + SIToFPInst *Conv = new SIToFPInst(NewPHI, PH->getType(), "indvar.conv", + PH->getParent()->getFirstNonPHI()); + PH->replaceAllUsesWith(Conv); + } else { + UIToFPInst *Conv = new UIToFPInst(NewPHI, PH->getType(), "indvar.conv", + PH->getParent()->getFirstNonPHI()); + PH->replaceAllUsesWith(Conv); + } + RecursivelyDeleteTriviallyDeadInstructions(PH); + } + + // Add a new IVUsers entry for the newly-created integer PHI. + IU->AddUsersIfInteresting(NewPHI); +} diff --git a/libclamav/c++/llvm/lib/Transforms/Scalar/InstructionCombining.cpp b/libclamav/c++/llvm/lib/Transforms/Scalar/InstructionCombining.cpp new file mode 100644 index 000000000..95563b049 --- /dev/null +++ b/libclamav/c++/llvm/lib/Transforms/Scalar/InstructionCombining.cpp @@ -0,0 +1,13430 @@ +//===- InstructionCombining.cpp - Combine multiple instructions -----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// InstructionCombining - Combine instructions to form fewer, simple +// instructions. This pass does not modify the CFG. This pass is where +// algebraic simplification happens. +// +// This pass combines things like: +// %Y = add i32 %X, 1 +// %Z = add i32 %Y, 1 +// into: +// %Z = add i32 %X, 2 +// +// This is a simple worklist driven algorithm. +// +// This pass guarantees that the following canonicalizations are performed on +// the program: +// 1. If a binary operator has a constant operand, it is moved to the RHS +// 2. Bitwise operators with constant operands are always grouped so that +// shifts are performed first, then or's, then and's, then xor's. +// 3. Compare instructions are converted from <,>,<=,>= to ==,!= if possible +// 4. All cmp instructions on boolean values are replaced with logical ops +// 5. add X, X is represented as (X*2) => (X << 1) +// 6. Multiplies with a power-of-two constant argument are transformed into +// shifts. +// ... etc. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "instcombine" +#include "llvm/Transforms/Scalar.h" +#include "llvm/IntrinsicInst.h" +#include "llvm/LLVMContext.h" +#include "llvm/Pass.h" +#include "llvm/DerivedTypes.h" +#include "llvm/GlobalVariable.h" +#include "llvm/Operator.h" +#include "llvm/Analysis/ConstantFolding.h" +#include "llvm/Analysis/InstructionSimplify.h" +#include "llvm/Analysis/MemoryBuiltins.h" +#include "llvm/Analysis/ValueTracking.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Transforms/Utils/BasicBlockUtils.h" +#include "llvm/Transforms/Utils/Local.h" +#include "llvm/Support/CallSite.h" +#include "llvm/Support/ConstantRange.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/GetElementPtrTypeIterator.h" +#include "llvm/Support/InstVisitor.h" +#include "llvm/Support/IRBuilder.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/Support/PatternMatch.h" +#include "llvm/Support/TargetFolder.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/ADT/STLExtras.h" +#include +#include +using namespace llvm; +using namespace llvm::PatternMatch; + +STATISTIC(NumCombined , "Number of insts combined"); +STATISTIC(NumConstProp, "Number of constant folds"); +STATISTIC(NumDeadInst , "Number of dead inst eliminated"); +STATISTIC(NumDeadStore, "Number of dead stores eliminated"); +STATISTIC(NumSunkInst , "Number of instructions sunk"); + +namespace { + /// InstCombineWorklist - This is the worklist management logic for + /// InstCombine. + class InstCombineWorklist { + SmallVector Worklist; + DenseMap WorklistMap; + + void operator=(const InstCombineWorklist&RHS); // DO NOT IMPLEMENT + InstCombineWorklist(const InstCombineWorklist&); // DO NOT IMPLEMENT + public: + InstCombineWorklist() {} + + bool isEmpty() const { return Worklist.empty(); } + + /// Add - Add the specified instruction to the worklist if it isn't already + /// in it. + void Add(Instruction *I) { + if (WorklistMap.insert(std::make_pair(I, Worklist.size())).second) { + DEBUG(errs() << "IC: ADD: " << *I << '\n'); + Worklist.push_back(I); + } + } + + void AddValue(Value *V) { + if (Instruction *I = dyn_cast(V)) + Add(I); + } + + /// AddInitialGroup - Add the specified batch of stuff in reverse order. + /// which should only be done when the worklist is empty and when the group + /// has no duplicates. + void AddInitialGroup(Instruction *const *List, unsigned NumEntries) { + assert(Worklist.empty() && "Worklist must be empty to add initial group"); + Worklist.reserve(NumEntries+16); + DEBUG(errs() << "IC: ADDING: " << NumEntries << " instrs to worklist\n"); + for (; NumEntries; --NumEntries) { + Instruction *I = List[NumEntries-1]; + WorklistMap.insert(std::make_pair(I, Worklist.size())); + Worklist.push_back(I); + } + } + + // Remove - remove I from the worklist if it exists. + void Remove(Instruction *I) { + DenseMap::iterator It = WorklistMap.find(I); + if (It == WorklistMap.end()) return; // Not in worklist. + + // Don't bother moving everything down, just null out the slot. + Worklist[It->second] = 0; + + WorklistMap.erase(It); + } + + Instruction *RemoveOne() { + Instruction *I = Worklist.back(); + Worklist.pop_back(); + WorklistMap.erase(I); + return I; + } + + /// AddUsersToWorkList - When an instruction is simplified, add all users of + /// the instruction to the work lists because they might get more simplified + /// now. + /// + void AddUsersToWorkList(Instruction &I) { + for (Value::use_iterator UI = I.use_begin(), UE = I.use_end(); + UI != UE; ++UI) + Add(cast(*UI)); + } + + + /// Zap - check that the worklist is empty and nuke the backing store for + /// the map if it is large. + void Zap() { + assert(WorklistMap.empty() && "Worklist empty, but map not?"); + + // Do an explicit clear, this shrinks the map if needed. + WorklistMap.clear(); + } + }; +} // end anonymous namespace. + + +namespace { + /// InstCombineIRInserter - This is an IRBuilder insertion helper that works + /// just like the normal insertion helper, but also adds any new instructions + /// to the instcombine worklist. + class InstCombineIRInserter : public IRBuilderDefaultInserter { + InstCombineWorklist &Worklist; + public: + InstCombineIRInserter(InstCombineWorklist &WL) : Worklist(WL) {} + + void InsertHelper(Instruction *I, const Twine &Name, + BasicBlock *BB, BasicBlock::iterator InsertPt) const { + IRBuilderDefaultInserter::InsertHelper(I, Name, BB, InsertPt); + Worklist.Add(I); + } + }; +} // end anonymous namespace + + +namespace { + class InstCombiner : public FunctionPass, + public InstVisitor { + TargetData *TD; + bool MustPreserveLCSSA; + bool MadeIRChange; + public: + /// Worklist - All of the instructions that need to be simplified. + InstCombineWorklist Worklist; + + /// Builder - This is an IRBuilder that automatically inserts new + /// instructions into the worklist when they are created. + typedef IRBuilder BuilderTy; + BuilderTy *Builder; + + static char ID; // Pass identification, replacement for typeid + InstCombiner() : FunctionPass(&ID), TD(0), Builder(0) {} + + LLVMContext *Context; + LLVMContext *getContext() const { return Context; } + + public: + virtual bool runOnFunction(Function &F); + + bool DoOneIteration(Function &F, unsigned ItNum); + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.addPreservedID(LCSSAID); + AU.setPreservesCFG(); + } + + TargetData *getTargetData() const { return TD; } + + // Visitation implementation - Implement instruction combining for different + // instruction types. The semantics are as follows: + // Return Value: + // null - No change was made + // I - Change was made, I is still valid, I may be dead though + // otherwise - Change was made, replace I with returned instruction + // + Instruction *visitAdd(BinaryOperator &I); + Instruction *visitFAdd(BinaryOperator &I); + Value *OptimizePointerDifference(Value *LHS, Value *RHS, const Type *Ty); + Instruction *visitSub(BinaryOperator &I); + Instruction *visitFSub(BinaryOperator &I); + Instruction *visitMul(BinaryOperator &I); + Instruction *visitFMul(BinaryOperator &I); + Instruction *visitURem(BinaryOperator &I); + Instruction *visitSRem(BinaryOperator &I); + Instruction *visitFRem(BinaryOperator &I); + bool SimplifyDivRemOfSelect(BinaryOperator &I); + Instruction *commonRemTransforms(BinaryOperator &I); + Instruction *commonIRemTransforms(BinaryOperator &I); + Instruction *commonDivTransforms(BinaryOperator &I); + Instruction *commonIDivTransforms(BinaryOperator &I); + Instruction *visitUDiv(BinaryOperator &I); + Instruction *visitSDiv(BinaryOperator &I); + Instruction *visitFDiv(BinaryOperator &I); + Instruction *FoldAndOfICmps(Instruction &I, ICmpInst *LHS, ICmpInst *RHS); + Instruction *FoldAndOfFCmps(Instruction &I, FCmpInst *LHS, FCmpInst *RHS); + Instruction *visitAnd(BinaryOperator &I); + Instruction *FoldOrOfICmps(Instruction &I, ICmpInst *LHS, ICmpInst *RHS); + Instruction *FoldOrOfFCmps(Instruction &I, FCmpInst *LHS, FCmpInst *RHS); + Instruction *FoldOrWithConstants(BinaryOperator &I, Value *Op, + Value *A, Value *B, Value *C); + Instruction *visitOr (BinaryOperator &I); + Instruction *visitXor(BinaryOperator &I); + Instruction *visitShl(BinaryOperator &I); + Instruction *visitAShr(BinaryOperator &I); + Instruction *visitLShr(BinaryOperator &I); + Instruction *commonShiftTransforms(BinaryOperator &I); + Instruction *FoldFCmp_IntToFP_Cst(FCmpInst &I, Instruction *LHSI, + Constant *RHSC); + Instruction *visitFCmpInst(FCmpInst &I); + Instruction *visitICmpInst(ICmpInst &I); + Instruction *visitICmpInstWithCastAndCast(ICmpInst &ICI); + Instruction *visitICmpInstWithInstAndIntCst(ICmpInst &ICI, + Instruction *LHS, + ConstantInt *RHS); + Instruction *FoldICmpDivCst(ICmpInst &ICI, BinaryOperator *DivI, + ConstantInt *DivRHS); + + Instruction *FoldGEPICmp(GEPOperator *GEPLHS, Value *RHS, + ICmpInst::Predicate Cond, Instruction &I); + Instruction *FoldShiftByConstant(Value *Op0, ConstantInt *Op1, + BinaryOperator &I); + Instruction *commonCastTransforms(CastInst &CI); + Instruction *commonIntCastTransforms(CastInst &CI); + Instruction *commonPointerCastTransforms(CastInst &CI); + Instruction *visitTrunc(TruncInst &CI); + Instruction *visitZExt(ZExtInst &CI); + Instruction *visitSExt(SExtInst &CI); + Instruction *visitFPTrunc(FPTruncInst &CI); + Instruction *visitFPExt(CastInst &CI); + Instruction *visitFPToUI(FPToUIInst &FI); + Instruction *visitFPToSI(FPToSIInst &FI); + Instruction *visitUIToFP(CastInst &CI); + Instruction *visitSIToFP(CastInst &CI); + Instruction *visitPtrToInt(PtrToIntInst &CI); + Instruction *visitIntToPtr(IntToPtrInst &CI); + Instruction *visitBitCast(BitCastInst &CI); + Instruction *FoldSelectOpOp(SelectInst &SI, Instruction *TI, + Instruction *FI); + Instruction *FoldSelectIntoOp(SelectInst &SI, Value*, Value*); + Instruction *visitSelectInst(SelectInst &SI); + Instruction *visitSelectInstWithICmp(SelectInst &SI, ICmpInst *ICI); + Instruction *visitCallInst(CallInst &CI); + Instruction *visitInvokeInst(InvokeInst &II); + + Instruction *SliceUpIllegalIntegerPHI(PHINode &PN); + Instruction *visitPHINode(PHINode &PN); + Instruction *visitGetElementPtrInst(GetElementPtrInst &GEP); + Instruction *visitAllocaInst(AllocaInst &AI); + Instruction *visitFree(Instruction &FI); + Instruction *visitLoadInst(LoadInst &LI); + Instruction *visitStoreInst(StoreInst &SI); + Instruction *visitBranchInst(BranchInst &BI); + Instruction *visitSwitchInst(SwitchInst &SI); + Instruction *visitInsertElementInst(InsertElementInst &IE); + Instruction *visitExtractElementInst(ExtractElementInst &EI); + Instruction *visitShuffleVectorInst(ShuffleVectorInst &SVI); + Instruction *visitExtractValueInst(ExtractValueInst &EV); + + // visitInstruction - Specify what to return for unhandled instructions... + Instruction *visitInstruction(Instruction &I) { return 0; } + + private: + Instruction *visitCallSite(CallSite CS); + bool transformConstExprCastCall(CallSite CS); + Instruction *transformCallThroughTrampoline(CallSite CS); + Instruction *transformZExtICmp(ICmpInst *ICI, Instruction &CI, + bool DoXform = true); + bool WillNotOverflowSignedAdd(Value *LHS, Value *RHS); + DbgDeclareInst *hasOneUsePlusDeclare(Value *V); + + + public: + // InsertNewInstBefore - insert an instruction New before instruction Old + // in the program. Add the new instruction to the worklist. + // + Instruction *InsertNewInstBefore(Instruction *New, Instruction &Old) { + assert(New && New->getParent() == 0 && + "New instruction already inserted into a basic block!"); + BasicBlock *BB = Old.getParent(); + BB->getInstList().insert(&Old, New); // Insert inst + Worklist.Add(New); + return New; + } + + // ReplaceInstUsesWith - This method is to be used when an instruction is + // found to be dead, replacable with another preexisting expression. Here + // we add all uses of I to the worklist, replace all uses of I with the new + // value, then return I, so that the inst combiner will know that I was + // modified. + // + Instruction *ReplaceInstUsesWith(Instruction &I, Value *V) { + Worklist.AddUsersToWorkList(I); // Add all modified instrs to worklist. + + // If we are replacing the instruction with itself, this must be in a + // segment of unreachable code, so just clobber the instruction. + if (&I == V) + V = UndefValue::get(I.getType()); + + I.replaceAllUsesWith(V); + return &I; + } + + // EraseInstFromFunction - When dealing with an instruction that has side + // effects or produces a void value, we can't rely on DCE to delete the + // instruction. Instead, visit methods should return the value returned by + // this function. + Instruction *EraseInstFromFunction(Instruction &I) { + DEBUG(errs() << "IC: ERASE " << I << '\n'); + + assert(I.use_empty() && "Cannot erase instruction that is used!"); + // Make sure that we reprocess all operands now that we reduced their + // use counts. + if (I.getNumOperands() < 8) { + for (User::op_iterator i = I.op_begin(), e = I.op_end(); i != e; ++i) + if (Instruction *Op = dyn_cast(*i)) + Worklist.Add(Op); + } + Worklist.Remove(&I); + I.eraseFromParent(); + MadeIRChange = true; + return 0; // Don't do anything with FI + } + + void ComputeMaskedBits(Value *V, const APInt &Mask, APInt &KnownZero, + APInt &KnownOne, unsigned Depth = 0) const { + return llvm::ComputeMaskedBits(V, Mask, KnownZero, KnownOne, TD, Depth); + } + + bool MaskedValueIsZero(Value *V, const APInt &Mask, + unsigned Depth = 0) const { + return llvm::MaskedValueIsZero(V, Mask, TD, Depth); + } + unsigned ComputeNumSignBits(Value *Op, unsigned Depth = 0) const { + return llvm::ComputeNumSignBits(Op, TD, Depth); + } + + private: + + /// SimplifyCommutative - This performs a few simplifications for + /// commutative operators. + bool SimplifyCommutative(BinaryOperator &I); + + /// SimplifyDemandedUseBits - Attempts to replace V with a simpler value + /// based on the demanded bits. + Value *SimplifyDemandedUseBits(Value *V, APInt DemandedMask, + APInt& KnownZero, APInt& KnownOne, + unsigned Depth); + bool SimplifyDemandedBits(Use &U, APInt DemandedMask, + APInt& KnownZero, APInt& KnownOne, + unsigned Depth=0); + + /// SimplifyDemandedInstructionBits - Inst is an integer instruction that + /// SimplifyDemandedBits knows about. See if the instruction has any + /// properties that allow us to simplify its operands. + bool SimplifyDemandedInstructionBits(Instruction &Inst); + + Value *SimplifyDemandedVectorElts(Value *V, APInt DemandedElts, + APInt& UndefElts, unsigned Depth = 0); + + // FoldOpIntoPhi - Given a binary operator, cast instruction, or select + // which has a PHI node as operand #0, see if we can fold the instruction + // into the PHI (which is only possible if all operands to the PHI are + // constants). + // + // If AllowAggressive is true, FoldOpIntoPhi will allow certain transforms + // that would normally be unprofitable because they strongly encourage jump + // threading. + Instruction *FoldOpIntoPhi(Instruction &I, bool AllowAggressive = false); + + // FoldPHIArgOpIntoPHI - If all operands to a PHI node are the same "unary" + // operator and they all are only used by the PHI, PHI together their + // inputs, and do the operation once, to the result of the PHI. + Instruction *FoldPHIArgOpIntoPHI(PHINode &PN); + Instruction *FoldPHIArgBinOpIntoPHI(PHINode &PN); + Instruction *FoldPHIArgGEPIntoPHI(PHINode &PN); + Instruction *FoldPHIArgLoadIntoPHI(PHINode &PN); + + + Instruction *OptAndOp(Instruction *Op, ConstantInt *OpRHS, + ConstantInt *AndRHS, BinaryOperator &TheAnd); + + Value *FoldLogicalPlusAnd(Value *LHS, Value *RHS, ConstantInt *Mask, + bool isSub, Instruction &I); + Instruction *InsertRangeTest(Value *V, Constant *Lo, Constant *Hi, + bool isSigned, bool Inside, Instruction &IB); + Instruction *PromoteCastOfAllocation(BitCastInst &CI, AllocaInst &AI); + Instruction *MatchBSwap(BinaryOperator &I); + bool SimplifyStoreAtEndOfBlock(StoreInst &SI); + Instruction *SimplifyMemTransfer(MemIntrinsic *MI); + Instruction *SimplifyMemSet(MemSetInst *MI); + + + Value *EvaluateInDifferentType(Value *V, const Type *Ty, bool isSigned); + + bool CanEvaluateInDifferentType(Value *V, const Type *Ty, + unsigned CastOpc, int &NumCastsRemoved); + unsigned GetOrEnforceKnownAlignment(Value *V, + unsigned PrefAlign = 0); + + }; +} // end anonymous namespace + +char InstCombiner::ID = 0; +static RegisterPass +X("instcombine", "Combine redundant instructions"); + +// getComplexity: Assign a complexity or rank value to LLVM Values... +// 0 -> undef, 1 -> Const, 2 -> Other, 3 -> Arg, 3 -> Unary, 4 -> OtherInst +static unsigned getComplexity(Value *V) { + if (isa(V)) { + if (BinaryOperator::isNeg(V) || + BinaryOperator::isFNeg(V) || + BinaryOperator::isNot(V)) + return 3; + return 4; + } + if (isa(V)) return 3; + return isa(V) ? (isa(V) ? 0 : 1) : 2; +} + +// isOnlyUse - Return true if this instruction will be deleted if we stop using +// it. +static bool isOnlyUse(Value *V) { + return V->hasOneUse() || isa(V); +} + +// getPromotedType - Return the specified type promoted as it would be to pass +// though a va_arg area... +static const Type *getPromotedType(const Type *Ty) { + if (const IntegerType* ITy = dyn_cast(Ty)) { + if (ITy->getBitWidth() < 32) + return Type::getInt32Ty(Ty->getContext()); + } + return Ty; +} + +/// ShouldChangeType - Return true if it is desirable to convert a computation +/// from 'From' to 'To'. We don't want to convert from a legal to an illegal +/// type for example, or from a smaller to a larger illegal type. +static bool ShouldChangeType(const Type *From, const Type *To, + const TargetData *TD) { + assert(isa(From) && isa(To)); + + // If we don't have TD, we don't know if the source/dest are legal. + if (!TD) return false; + + unsigned FromWidth = From->getPrimitiveSizeInBits(); + unsigned ToWidth = To->getPrimitiveSizeInBits(); + bool FromLegal = TD->isLegalInteger(FromWidth); + bool ToLegal = TD->isLegalInteger(ToWidth); + + // If this is a legal integer from type, and the result would be an illegal + // type, don't do the transformation. + if (FromLegal && !ToLegal) + return false; + + // Otherwise, if both are illegal, do not increase the size of the result. We + // do allow things like i160 -> i64, but not i64 -> i160. + if (!FromLegal && !ToLegal && ToWidth > FromWidth) + return false; + + return true; +} + +/// getBitCastOperand - If the specified operand is a CastInst, a constant +/// expression bitcast, or a GetElementPtrInst with all zero indices, return the +/// operand value, otherwise return null. +static Value *getBitCastOperand(Value *V) { + if (Operator *O = dyn_cast(V)) { + if (O->getOpcode() == Instruction::BitCast) + return O->getOperand(0); + if (GEPOperator *GEP = dyn_cast(V)) + if (GEP->hasAllZeroIndices()) + return GEP->getPointerOperand(); + } + return 0; +} + +/// This function is a wrapper around CastInst::isEliminableCastPair. It +/// simply extracts arguments and returns what that function returns. +static Instruction::CastOps +isEliminableCastPair( + const CastInst *CI, ///< The first cast instruction + unsigned opcode, ///< The opcode of the second cast instruction + const Type *DstTy, ///< The target type for the second cast instruction + TargetData *TD ///< The target data for pointer size +) { + + const Type *SrcTy = CI->getOperand(0)->getType(); // A from above + const Type *MidTy = CI->getType(); // B from above + + // Get the opcodes of the two Cast instructions + Instruction::CastOps firstOp = Instruction::CastOps(CI->getOpcode()); + Instruction::CastOps secondOp = Instruction::CastOps(opcode); + + unsigned Res = CastInst::isEliminableCastPair(firstOp, secondOp, SrcTy, MidTy, + DstTy, + TD ? TD->getIntPtrType(CI->getContext()) : 0); + + // We don't want to form an inttoptr or ptrtoint that converts to an integer + // type that differs from the pointer size. + if ((Res == Instruction::IntToPtr && + (!TD || SrcTy != TD->getIntPtrType(CI->getContext()))) || + (Res == Instruction::PtrToInt && + (!TD || DstTy != TD->getIntPtrType(CI->getContext())))) + Res = 0; + + return Instruction::CastOps(Res); +} + +/// ValueRequiresCast - Return true if the cast from "V to Ty" actually results +/// in any code being generated. It does not require codegen if V is simple +/// enough or if the cast can be folded into other casts. +static bool ValueRequiresCast(Instruction::CastOps opcode, const Value *V, + const Type *Ty, TargetData *TD) { + if (V->getType() == Ty || isa(V)) return false; + + // If this is another cast that can be eliminated, it isn't codegen either. + if (const CastInst *CI = dyn_cast(V)) + if (isEliminableCastPair(CI, opcode, Ty, TD)) + return false; + return true; +} + +// SimplifyCommutative - This performs a few simplifications for commutative +// operators: +// +// 1. Order operands such that they are listed from right (least complex) to +// left (most complex). This puts constants before unary operators before +// binary operators. +// +// 2. Transform: (op (op V, C1), C2) ==> (op V, (op C1, C2)) +// 3. Transform: (op (op V1, C1), (op V2, C2)) ==> (op (op V1, V2), (op C1,C2)) +// +bool InstCombiner::SimplifyCommutative(BinaryOperator &I) { + bool Changed = false; + if (getComplexity(I.getOperand(0)) < getComplexity(I.getOperand(1))) + Changed = !I.swapOperands(); + + if (!I.isAssociative()) return Changed; + Instruction::BinaryOps Opcode = I.getOpcode(); + if (BinaryOperator *Op = dyn_cast(I.getOperand(0))) + if (Op->getOpcode() == Opcode && isa(Op->getOperand(1))) { + if (isa(I.getOperand(1))) { + Constant *Folded = ConstantExpr::get(I.getOpcode(), + cast(I.getOperand(1)), + cast(Op->getOperand(1))); + I.setOperand(0, Op->getOperand(0)); + I.setOperand(1, Folded); + return true; + } else if (BinaryOperator *Op1=dyn_cast(I.getOperand(1))) + if (Op1->getOpcode() == Opcode && isa(Op1->getOperand(1)) && + isOnlyUse(Op) && isOnlyUse(Op1)) { + Constant *C1 = cast(Op->getOperand(1)); + Constant *C2 = cast(Op1->getOperand(1)); + + // Fold (op (op V1, C1), (op V2, C2)) ==> (op (op V1, V2), (op C1,C2)) + Constant *Folded = ConstantExpr::get(I.getOpcode(), C1, C2); + Instruction *New = BinaryOperator::Create(Opcode, Op->getOperand(0), + Op1->getOperand(0), + Op1->getName(), &I); + Worklist.Add(New); + I.setOperand(0, New); + I.setOperand(1, Folded); + return true; + } + } + return Changed; +} + +// dyn_castNegVal - Given a 'sub' instruction, return the RHS of the instruction +// if the LHS is a constant zero (which is the 'negate' form). +// +static inline Value *dyn_castNegVal(Value *V) { + if (BinaryOperator::isNeg(V)) + return BinaryOperator::getNegArgument(V); + + // Constants can be considered to be negated values if they can be folded. + if (ConstantInt *C = dyn_cast(V)) + return ConstantExpr::getNeg(C); + + if (ConstantVector *C = dyn_cast(V)) + if (C->getType()->getElementType()->isInteger()) + return ConstantExpr::getNeg(C); + + return 0; +} + +// dyn_castFNegVal - Given a 'fsub' instruction, return the RHS of the +// instruction if the LHS is a constant negative zero (which is the 'negate' +// form). +// +static inline Value *dyn_castFNegVal(Value *V) { + if (BinaryOperator::isFNeg(V)) + return BinaryOperator::getFNegArgument(V); + + // Constants can be considered to be negated values if they can be folded. + if (ConstantFP *C = dyn_cast(V)) + return ConstantExpr::getFNeg(C); + + if (ConstantVector *C = dyn_cast(V)) + if (C->getType()->getElementType()->isFloatingPoint()) + return ConstantExpr::getFNeg(C); + + return 0; +} + +/// isFreeToInvert - Return true if the specified value is free to invert (apply +/// ~ to). This happens in cases where the ~ can be eliminated. +static inline bool isFreeToInvert(Value *V) { + // ~(~(X)) -> X. + if (BinaryOperator::isNot(V)) + return true; + + // Constants can be considered to be not'ed values. + if (isa(V)) + return true; + + // Compares can be inverted if they have a single use. + if (CmpInst *CI = dyn_cast(V)) + return CI->hasOneUse(); + + return false; +} + +static inline Value *dyn_castNotVal(Value *V) { + // If this is not(not(x)) don't return that this is a not: we want the two + // not's to be folded first. + if (BinaryOperator::isNot(V)) { + Value *Operand = BinaryOperator::getNotArgument(V); + if (!isFreeToInvert(Operand)) + return Operand; + } + + // Constants can be considered to be not'ed values... + if (ConstantInt *C = dyn_cast(V)) + return ConstantInt::get(C->getType(), ~C->getValue()); + return 0; +} + + + +// dyn_castFoldableMul - If this value is a multiply that can be folded into +// other computations (because it has a constant operand), return the +// non-constant operand of the multiply, and set CST to point to the multiplier. +// Otherwise, return null. +// +static inline Value *dyn_castFoldableMul(Value *V, ConstantInt *&CST) { + if (V->hasOneUse() && V->getType()->isInteger()) + if (Instruction *I = dyn_cast(V)) { + if (I->getOpcode() == Instruction::Mul) + if ((CST = dyn_cast(I->getOperand(1)))) + return I->getOperand(0); + if (I->getOpcode() == Instruction::Shl) + if ((CST = dyn_cast(I->getOperand(1)))) { + // The multiplier is really 1 << CST. + uint32_t BitWidth = cast(V->getType())->getBitWidth(); + uint32_t CSTVal = CST->getLimitedValue(BitWidth); + CST = ConstantInt::get(V->getType()->getContext(), + APInt(BitWidth, 1).shl(CSTVal)); + return I->getOperand(0); + } + } + return 0; +} + +/// AddOne - Add one to a ConstantInt +static Constant *AddOne(Constant *C) { + return ConstantExpr::getAdd(C, + ConstantInt::get(C->getType(), 1)); +} +/// SubOne - Subtract one from a ConstantInt +static Constant *SubOne(ConstantInt *C) { + return ConstantExpr::getSub(C, + ConstantInt::get(C->getType(), 1)); +} +/// MultiplyOverflows - True if the multiply can not be expressed in an int +/// this size. +static bool MultiplyOverflows(ConstantInt *C1, ConstantInt *C2, bool sign) { + uint32_t W = C1->getBitWidth(); + APInt LHSExt = C1->getValue(), RHSExt = C2->getValue(); + if (sign) { + LHSExt.sext(W * 2); + RHSExt.sext(W * 2); + } else { + LHSExt.zext(W * 2); + RHSExt.zext(W * 2); + } + + APInt MulExt = LHSExt * RHSExt; + + if (sign) { + APInt Min = APInt::getSignedMinValue(W).sext(W * 2); + APInt Max = APInt::getSignedMaxValue(W).sext(W * 2); + return MulExt.slt(Min) || MulExt.sgt(Max); + } else + return MulExt.ugt(APInt::getLowBitsSet(W * 2, W)); +} + + +/// ShrinkDemandedConstant - Check to see if the specified operand of the +/// specified instruction is a constant integer. If so, check to see if there +/// are any bits set in the constant that are not demanded. If so, shrink the +/// constant and return true. +static bool ShrinkDemandedConstant(Instruction *I, unsigned OpNo, + APInt Demanded) { + assert(I && "No instruction?"); + assert(OpNo < I->getNumOperands() && "Operand index too large"); + + // If the operand is not a constant integer, nothing to do. + ConstantInt *OpC = dyn_cast(I->getOperand(OpNo)); + if (!OpC) return false; + + // If there are no bits set that aren't demanded, nothing to do. + Demanded.zextOrTrunc(OpC->getValue().getBitWidth()); + if ((~Demanded & OpC->getValue()) == 0) + return false; + + // This instruction is producing bits that are not demanded. Shrink the RHS. + Demanded &= OpC->getValue(); + I->setOperand(OpNo, ConstantInt::get(OpC->getType(), Demanded)); + return true; +} + +// ComputeSignedMinMaxValuesFromKnownBits - Given a signed integer type and a +// set of known zero and one bits, compute the maximum and minimum values that +// could have the specified known zero and known one bits, returning them in +// min/max. +static void ComputeSignedMinMaxValuesFromKnownBits(const APInt& KnownZero, + const APInt& KnownOne, + APInt& Min, APInt& Max) { + assert(KnownZero.getBitWidth() == KnownOne.getBitWidth() && + KnownZero.getBitWidth() == Min.getBitWidth() && + KnownZero.getBitWidth() == Max.getBitWidth() && + "KnownZero, KnownOne and Min, Max must have equal bitwidth."); + APInt UnknownBits = ~(KnownZero|KnownOne); + + // The minimum value is when all unknown bits are zeros, EXCEPT for the sign + // bit if it is unknown. + Min = KnownOne; + Max = KnownOne|UnknownBits; + + if (UnknownBits.isNegative()) { // Sign bit is unknown + Min.set(Min.getBitWidth()-1); + Max.clear(Max.getBitWidth()-1); + } +} + +// ComputeUnsignedMinMaxValuesFromKnownBits - Given an unsigned integer type and +// a set of known zero and one bits, compute the maximum and minimum values that +// could have the specified known zero and known one bits, returning them in +// min/max. +static void ComputeUnsignedMinMaxValuesFromKnownBits(const APInt &KnownZero, + const APInt &KnownOne, + APInt &Min, APInt &Max) { + assert(KnownZero.getBitWidth() == KnownOne.getBitWidth() && + KnownZero.getBitWidth() == Min.getBitWidth() && + KnownZero.getBitWidth() == Max.getBitWidth() && + "Ty, KnownZero, KnownOne and Min, Max must have equal bitwidth."); + APInt UnknownBits = ~(KnownZero|KnownOne); + + // The minimum value is when the unknown bits are all zeros. + Min = KnownOne; + // The maximum value is when the unknown bits are all ones. + Max = KnownOne|UnknownBits; +} + +/// SimplifyDemandedInstructionBits - Inst is an integer instruction that +/// SimplifyDemandedBits knows about. See if the instruction has any +/// properties that allow us to simplify its operands. +bool InstCombiner::SimplifyDemandedInstructionBits(Instruction &Inst) { + unsigned BitWidth = Inst.getType()->getScalarSizeInBits(); + APInt KnownZero(BitWidth, 0), KnownOne(BitWidth, 0); + APInt DemandedMask(APInt::getAllOnesValue(BitWidth)); + + Value *V = SimplifyDemandedUseBits(&Inst, DemandedMask, + KnownZero, KnownOne, 0); + if (V == 0) return false; + if (V == &Inst) return true; + ReplaceInstUsesWith(Inst, V); + return true; +} + +/// SimplifyDemandedBits - This form of SimplifyDemandedBits simplifies the +/// specified instruction operand if possible, updating it in place. It returns +/// true if it made any change and false otherwise. +bool InstCombiner::SimplifyDemandedBits(Use &U, APInt DemandedMask, + APInt &KnownZero, APInt &KnownOne, + unsigned Depth) { + Value *NewVal = SimplifyDemandedUseBits(U.get(), DemandedMask, + KnownZero, KnownOne, Depth); + if (NewVal == 0) return false; + U = NewVal; + return true; +} + + +/// SimplifyDemandedUseBits - This function attempts to replace V with a simpler +/// value based on the demanded bits. When this function is called, it is known +/// that only the bits set in DemandedMask of the result of V are ever used +/// downstream. Consequently, depending on the mask and V, it may be possible +/// to replace V with a constant or one of its operands. In such cases, this +/// function does the replacement and returns true. In all other cases, it +/// returns false after analyzing the expression and setting KnownOne and known +/// to be one in the expression. KnownZero contains all the bits that are known +/// to be zero in the expression. These are provided to potentially allow the +/// caller (which might recursively be SimplifyDemandedBits itself) to simplify +/// the expression. KnownOne and KnownZero always follow the invariant that +/// KnownOne & KnownZero == 0. That is, a bit can't be both 1 and 0. Note that +/// the bits in KnownOne and KnownZero may only be accurate for those bits set +/// in DemandedMask. Note also that the bitwidth of V, DemandedMask, KnownZero +/// and KnownOne must all be the same. +/// +/// This returns null if it did not change anything and it permits no +/// simplification. This returns V itself if it did some simplification of V's +/// operands based on the information about what bits are demanded. This returns +/// some other non-null value if it found out that V is equal to another value +/// in the context where the specified bits are demanded, but not for all users. +Value *InstCombiner::SimplifyDemandedUseBits(Value *V, APInt DemandedMask, + APInt &KnownZero, APInt &KnownOne, + unsigned Depth) { + assert(V != 0 && "Null pointer of Value???"); + assert(Depth <= 6 && "Limit Search Depth"); + uint32_t BitWidth = DemandedMask.getBitWidth(); + const Type *VTy = V->getType(); + assert((TD || !isa(VTy)) && + "SimplifyDemandedBits needs to know bit widths!"); + assert((!TD || TD->getTypeSizeInBits(VTy->getScalarType()) == BitWidth) && + (!VTy->isIntOrIntVector() || + VTy->getScalarSizeInBits() == BitWidth) && + KnownZero.getBitWidth() == BitWidth && + KnownOne.getBitWidth() == BitWidth && + "Value *V, DemandedMask, KnownZero and KnownOne " + "must have same BitWidth"); + if (ConstantInt *CI = dyn_cast(V)) { + // We know all of the bits for a constant! + KnownOne = CI->getValue() & DemandedMask; + KnownZero = ~KnownOne & DemandedMask; + return 0; + } + if (isa(V)) { + // We know all of the bits for a constant! + KnownOne.clear(); + KnownZero = DemandedMask; + return 0; + } + + KnownZero.clear(); + KnownOne.clear(); + if (DemandedMask == 0) { // Not demanding any bits from V. + if (isa(V)) + return 0; + return UndefValue::get(VTy); + } + + if (Depth == 6) // Limit search depth. + return 0; + + APInt LHSKnownZero(BitWidth, 0), LHSKnownOne(BitWidth, 0); + APInt &RHSKnownZero = KnownZero, &RHSKnownOne = KnownOne; + + Instruction *I = dyn_cast(V); + if (!I) { + ComputeMaskedBits(V, DemandedMask, RHSKnownZero, RHSKnownOne, Depth); + return 0; // Only analyze instructions. + } + + // If there are multiple uses of this value and we aren't at the root, then + // we can't do any simplifications of the operands, because DemandedMask + // only reflects the bits demanded by *one* of the users. + if (Depth != 0 && !I->hasOneUse()) { + // Despite the fact that we can't simplify this instruction in all User's + // context, we can at least compute the knownzero/knownone bits, and we can + // do simplifications that apply to *just* the one user if we know that + // this instruction has a simpler value in that context. + if (I->getOpcode() == Instruction::And) { + // If either the LHS or the RHS are Zero, the result is zero. + ComputeMaskedBits(I->getOperand(1), DemandedMask, + RHSKnownZero, RHSKnownOne, Depth+1); + ComputeMaskedBits(I->getOperand(0), DemandedMask & ~RHSKnownZero, + LHSKnownZero, LHSKnownOne, Depth+1); + + // If all of the demanded bits are known 1 on one side, return the other. + // These bits cannot contribute to the result of the 'and' in this + // context. + if ((DemandedMask & ~LHSKnownZero & RHSKnownOne) == + (DemandedMask & ~LHSKnownZero)) + return I->getOperand(0); + if ((DemandedMask & ~RHSKnownZero & LHSKnownOne) == + (DemandedMask & ~RHSKnownZero)) + return I->getOperand(1); + + // If all of the demanded bits in the inputs are known zeros, return zero. + if ((DemandedMask & (RHSKnownZero|LHSKnownZero)) == DemandedMask) + return Constant::getNullValue(VTy); + + } else if (I->getOpcode() == Instruction::Or) { + // We can simplify (X|Y) -> X or Y in the user's context if we know that + // only bits from X or Y are demanded. + + // If either the LHS or the RHS are One, the result is One. + ComputeMaskedBits(I->getOperand(1), DemandedMask, + RHSKnownZero, RHSKnownOne, Depth+1); + ComputeMaskedBits(I->getOperand(0), DemandedMask & ~RHSKnownOne, + LHSKnownZero, LHSKnownOne, Depth+1); + + // If all of the demanded bits are known zero on one side, return the + // other. These bits cannot contribute to the result of the 'or' in this + // context. + if ((DemandedMask & ~LHSKnownOne & RHSKnownZero) == + (DemandedMask & ~LHSKnownOne)) + return I->getOperand(0); + if ((DemandedMask & ~RHSKnownOne & LHSKnownZero) == + (DemandedMask & ~RHSKnownOne)) + return I->getOperand(1); + + // If all of the potentially set bits on one side are known to be set on + // the other side, just use the 'other' side. + if ((DemandedMask & (~RHSKnownZero) & LHSKnownOne) == + (DemandedMask & (~RHSKnownZero))) + return I->getOperand(0); + if ((DemandedMask & (~LHSKnownZero) & RHSKnownOne) == + (DemandedMask & (~LHSKnownZero))) + return I->getOperand(1); + } + + // Compute the KnownZero/KnownOne bits to simplify things downstream. + ComputeMaskedBits(I, DemandedMask, KnownZero, KnownOne, Depth); + return 0; + } + + // If this is the root being simplified, allow it to have multiple uses, + // just set the DemandedMask to all bits so that we can try to simplify the + // operands. This allows visitTruncInst (for example) to simplify the + // operand of a trunc without duplicating all the logic below. + if (Depth == 0 && !V->hasOneUse()) + DemandedMask = APInt::getAllOnesValue(BitWidth); + + switch (I->getOpcode()) { + default: + ComputeMaskedBits(I, DemandedMask, RHSKnownZero, RHSKnownOne, Depth); + break; + case Instruction::And: + // If either the LHS or the RHS are Zero, the result is zero. + if (SimplifyDemandedBits(I->getOperandUse(1), DemandedMask, + RHSKnownZero, RHSKnownOne, Depth+1) || + SimplifyDemandedBits(I->getOperandUse(0), DemandedMask & ~RHSKnownZero, + LHSKnownZero, LHSKnownOne, Depth+1)) + return I; + assert(!(RHSKnownZero & RHSKnownOne) && "Bits known to be one AND zero?"); + assert(!(LHSKnownZero & LHSKnownOne) && "Bits known to be one AND zero?"); + + // If all of the demanded bits are known 1 on one side, return the other. + // These bits cannot contribute to the result of the 'and'. + if ((DemandedMask & ~LHSKnownZero & RHSKnownOne) == + (DemandedMask & ~LHSKnownZero)) + return I->getOperand(0); + if ((DemandedMask & ~RHSKnownZero & LHSKnownOne) == + (DemandedMask & ~RHSKnownZero)) + return I->getOperand(1); + + // If all of the demanded bits in the inputs are known zeros, return zero. + if ((DemandedMask & (RHSKnownZero|LHSKnownZero)) == DemandedMask) + return Constant::getNullValue(VTy); + + // If the RHS is a constant, see if we can simplify it. + if (ShrinkDemandedConstant(I, 1, DemandedMask & ~LHSKnownZero)) + return I; + + // Output known-1 bits are only known if set in both the LHS & RHS. + RHSKnownOne &= LHSKnownOne; + // Output known-0 are known to be clear if zero in either the LHS | RHS. + RHSKnownZero |= LHSKnownZero; + break; + case Instruction::Or: + // If either the LHS or the RHS are One, the result is One. + if (SimplifyDemandedBits(I->getOperandUse(1), DemandedMask, + RHSKnownZero, RHSKnownOne, Depth+1) || + SimplifyDemandedBits(I->getOperandUse(0), DemandedMask & ~RHSKnownOne, + LHSKnownZero, LHSKnownOne, Depth+1)) + return I; + assert(!(RHSKnownZero & RHSKnownOne) && "Bits known to be one AND zero?"); + assert(!(LHSKnownZero & LHSKnownOne) && "Bits known to be one AND zero?"); + + // If all of the demanded bits are known zero on one side, return the other. + // These bits cannot contribute to the result of the 'or'. + if ((DemandedMask & ~LHSKnownOne & RHSKnownZero) == + (DemandedMask & ~LHSKnownOne)) + return I->getOperand(0); + if ((DemandedMask & ~RHSKnownOne & LHSKnownZero) == + (DemandedMask & ~RHSKnownOne)) + return I->getOperand(1); + + // If all of the potentially set bits on one side are known to be set on + // the other side, just use the 'other' side. + if ((DemandedMask & (~RHSKnownZero) & LHSKnownOne) == + (DemandedMask & (~RHSKnownZero))) + return I->getOperand(0); + if ((DemandedMask & (~LHSKnownZero) & RHSKnownOne) == + (DemandedMask & (~LHSKnownZero))) + return I->getOperand(1); + + // If the RHS is a constant, see if we can simplify it. + if (ShrinkDemandedConstant(I, 1, DemandedMask)) + return I; + + // Output known-0 bits are only known if clear in both the LHS & RHS. + RHSKnownZero &= LHSKnownZero; + // Output known-1 are known to be set if set in either the LHS | RHS. + RHSKnownOne |= LHSKnownOne; + break; + case Instruction::Xor: { + if (SimplifyDemandedBits(I->getOperandUse(1), DemandedMask, + RHSKnownZero, RHSKnownOne, Depth+1) || + SimplifyDemandedBits(I->getOperandUse(0), DemandedMask, + LHSKnownZero, LHSKnownOne, Depth+1)) + return I; + assert(!(RHSKnownZero & RHSKnownOne) && "Bits known to be one AND zero?"); + assert(!(LHSKnownZero & LHSKnownOne) && "Bits known to be one AND zero?"); + + // If all of the demanded bits are known zero on one side, return the other. + // These bits cannot contribute to the result of the 'xor'. + if ((DemandedMask & RHSKnownZero) == DemandedMask) + return I->getOperand(0); + if ((DemandedMask & LHSKnownZero) == DemandedMask) + return I->getOperand(1); + + // Output known-0 bits are known if clear or set in both the LHS & RHS. + APInt KnownZeroOut = (RHSKnownZero & LHSKnownZero) | + (RHSKnownOne & LHSKnownOne); + // Output known-1 are known to be set if set in only one of the LHS, RHS. + APInt KnownOneOut = (RHSKnownZero & LHSKnownOne) | + (RHSKnownOne & LHSKnownZero); + + // If all of the demanded bits are known to be zero on one side or the + // other, turn this into an *inclusive* or. + // e.g. (A & C1)^(B & C2) -> (A & C1)|(B & C2) iff C1&C2 == 0 + if ((DemandedMask & ~RHSKnownZero & ~LHSKnownZero) == 0) { + Instruction *Or = + BinaryOperator::CreateOr(I->getOperand(0), I->getOperand(1), + I->getName()); + return InsertNewInstBefore(Or, *I); + } + + // If all of the demanded bits on one side are known, and all of the set + // bits on that side are also known to be set on the other side, turn this + // into an AND, as we know the bits will be cleared. + // e.g. (X | C1) ^ C2 --> (X | C1) & ~C2 iff (C1&C2) == C2 + if ((DemandedMask & (RHSKnownZero|RHSKnownOne)) == DemandedMask) { + // all known + if ((RHSKnownOne & LHSKnownOne) == RHSKnownOne) { + Constant *AndC = Constant::getIntegerValue(VTy, + ~RHSKnownOne & DemandedMask); + Instruction *And = + BinaryOperator::CreateAnd(I->getOperand(0), AndC, "tmp"); + return InsertNewInstBefore(And, *I); + } + } + + // If the RHS is a constant, see if we can simplify it. + // FIXME: for XOR, we prefer to force bits to 1 if they will make a -1. + if (ShrinkDemandedConstant(I, 1, DemandedMask)) + return I; + + // If our LHS is an 'and' and if it has one use, and if any of the bits we + // are flipping are known to be set, then the xor is just resetting those + // bits to zero. We can just knock out bits from the 'and' and the 'xor', + // simplifying both of them. + if (Instruction *LHSInst = dyn_cast(I->getOperand(0))) + if (LHSInst->getOpcode() == Instruction::And && LHSInst->hasOneUse() && + isa(I->getOperand(1)) && + isa(LHSInst->getOperand(1)) && + (LHSKnownOne & RHSKnownOne & DemandedMask) != 0) { + ConstantInt *AndRHS = cast(LHSInst->getOperand(1)); + ConstantInt *XorRHS = cast(I->getOperand(1)); + APInt NewMask = ~(LHSKnownOne & RHSKnownOne & DemandedMask); + + Constant *AndC = + ConstantInt::get(I->getType(), NewMask & AndRHS->getValue()); + Instruction *NewAnd = + BinaryOperator::CreateAnd(I->getOperand(0), AndC, "tmp"); + InsertNewInstBefore(NewAnd, *I); + + Constant *XorC = + ConstantInt::get(I->getType(), NewMask & XorRHS->getValue()); + Instruction *NewXor = + BinaryOperator::CreateXor(NewAnd, XorC, "tmp"); + return InsertNewInstBefore(NewXor, *I); + } + + + RHSKnownZero = KnownZeroOut; + RHSKnownOne = KnownOneOut; + break; + } + case Instruction::Select: + if (SimplifyDemandedBits(I->getOperandUse(2), DemandedMask, + RHSKnownZero, RHSKnownOne, Depth+1) || + SimplifyDemandedBits(I->getOperandUse(1), DemandedMask, + LHSKnownZero, LHSKnownOne, Depth+1)) + return I; + assert(!(RHSKnownZero & RHSKnownOne) && "Bits known to be one AND zero?"); + assert(!(LHSKnownZero & LHSKnownOne) && "Bits known to be one AND zero?"); + + // If the operands are constants, see if we can simplify them. + if (ShrinkDemandedConstant(I, 1, DemandedMask) || + ShrinkDemandedConstant(I, 2, DemandedMask)) + return I; + + // Only known if known in both the LHS and RHS. + RHSKnownOne &= LHSKnownOne; + RHSKnownZero &= LHSKnownZero; + break; + case Instruction::Trunc: { + unsigned truncBf = I->getOperand(0)->getType()->getScalarSizeInBits(); + DemandedMask.zext(truncBf); + RHSKnownZero.zext(truncBf); + RHSKnownOne.zext(truncBf); + if (SimplifyDemandedBits(I->getOperandUse(0), DemandedMask, + RHSKnownZero, RHSKnownOne, Depth+1)) + return I; + DemandedMask.trunc(BitWidth); + RHSKnownZero.trunc(BitWidth); + RHSKnownOne.trunc(BitWidth); + assert(!(RHSKnownZero & RHSKnownOne) && "Bits known to be one AND zero?"); + break; + } + case Instruction::BitCast: + if (!I->getOperand(0)->getType()->isIntOrIntVector()) + return false; // vector->int or fp->int? + + if (const VectorType *DstVTy = dyn_cast(I->getType())) { + if (const VectorType *SrcVTy = + dyn_cast(I->getOperand(0)->getType())) { + if (DstVTy->getNumElements() != SrcVTy->getNumElements()) + // Don't touch a bitcast between vectors of different element counts. + return false; + } else + // Don't touch a scalar-to-vector bitcast. + return false; + } else if (isa(I->getOperand(0)->getType())) + // Don't touch a vector-to-scalar bitcast. + return false; + + if (SimplifyDemandedBits(I->getOperandUse(0), DemandedMask, + RHSKnownZero, RHSKnownOne, Depth+1)) + return I; + assert(!(RHSKnownZero & RHSKnownOne) && "Bits known to be one AND zero?"); + break; + case Instruction::ZExt: { + // Compute the bits in the result that are not present in the input. + unsigned SrcBitWidth =I->getOperand(0)->getType()->getScalarSizeInBits(); + + DemandedMask.trunc(SrcBitWidth); + RHSKnownZero.trunc(SrcBitWidth); + RHSKnownOne.trunc(SrcBitWidth); + if (SimplifyDemandedBits(I->getOperandUse(0), DemandedMask, + RHSKnownZero, RHSKnownOne, Depth+1)) + return I; + DemandedMask.zext(BitWidth); + RHSKnownZero.zext(BitWidth); + RHSKnownOne.zext(BitWidth); + assert(!(RHSKnownZero & RHSKnownOne) && "Bits known to be one AND zero?"); + // The top bits are known to be zero. + RHSKnownZero |= APInt::getHighBitsSet(BitWidth, BitWidth - SrcBitWidth); + break; + } + case Instruction::SExt: { + // Compute the bits in the result that are not present in the input. + unsigned SrcBitWidth =I->getOperand(0)->getType()->getScalarSizeInBits(); + + APInt InputDemandedBits = DemandedMask & + APInt::getLowBitsSet(BitWidth, SrcBitWidth); + + APInt NewBits(APInt::getHighBitsSet(BitWidth, BitWidth - SrcBitWidth)); + // If any of the sign extended bits are demanded, we know that the sign + // bit is demanded. + if ((NewBits & DemandedMask) != 0) + InputDemandedBits.set(SrcBitWidth-1); + + InputDemandedBits.trunc(SrcBitWidth); + RHSKnownZero.trunc(SrcBitWidth); + RHSKnownOne.trunc(SrcBitWidth); + if (SimplifyDemandedBits(I->getOperandUse(0), InputDemandedBits, + RHSKnownZero, RHSKnownOne, Depth+1)) + return I; + InputDemandedBits.zext(BitWidth); + RHSKnownZero.zext(BitWidth); + RHSKnownOne.zext(BitWidth); + assert(!(RHSKnownZero & RHSKnownOne) && "Bits known to be one AND zero?"); + + // If the sign bit of the input is known set or clear, then we know the + // top bits of the result. + + // If the input sign bit is known zero, or if the NewBits are not demanded + // convert this into a zero extension. + if (RHSKnownZero[SrcBitWidth-1] || (NewBits & ~DemandedMask) == NewBits) { + // Convert to ZExt cast + CastInst *NewCast = new ZExtInst(I->getOperand(0), VTy, I->getName()); + return InsertNewInstBefore(NewCast, *I); + } else if (RHSKnownOne[SrcBitWidth-1]) { // Input sign bit known set + RHSKnownOne |= NewBits; + } + break; + } + case Instruction::Add: { + // Figure out what the input bits are. If the top bits of the and result + // are not demanded, then the add doesn't demand them from its input + // either. + unsigned NLZ = DemandedMask.countLeadingZeros(); + + // If there is a constant on the RHS, there are a variety of xformations + // we can do. + if (ConstantInt *RHS = dyn_cast(I->getOperand(1))) { + // If null, this should be simplified elsewhere. Some of the xforms here + // won't work if the RHS is zero. + if (RHS->isZero()) + break; + + // If the top bit of the output is demanded, demand everything from the + // input. Otherwise, we demand all the input bits except NLZ top bits. + APInt InDemandedBits(APInt::getLowBitsSet(BitWidth, BitWidth - NLZ)); + + // Find information about known zero/one bits in the input. + if (SimplifyDemandedBits(I->getOperandUse(0), InDemandedBits, + LHSKnownZero, LHSKnownOne, Depth+1)) + return I; + + // If the RHS of the add has bits set that can't affect the input, reduce + // the constant. + if (ShrinkDemandedConstant(I, 1, InDemandedBits)) + return I; + + // Avoid excess work. + if (LHSKnownZero == 0 && LHSKnownOne == 0) + break; + + // Turn it into OR if input bits are zero. + if ((LHSKnownZero & RHS->getValue()) == RHS->getValue()) { + Instruction *Or = + BinaryOperator::CreateOr(I->getOperand(0), I->getOperand(1), + I->getName()); + return InsertNewInstBefore(Or, *I); + } + + // We can say something about the output known-zero and known-one bits, + // depending on potential carries from the input constant and the + // unknowns. For example if the LHS is known to have at most the 0x0F0F0 + // bits set and the RHS constant is 0x01001, then we know we have a known + // one mask of 0x00001 and a known zero mask of 0xE0F0E. + + // To compute this, we first compute the potential carry bits. These are + // the bits which may be modified. I'm not aware of a better way to do + // this scan. + const APInt &RHSVal = RHS->getValue(); + APInt CarryBits((~LHSKnownZero + RHSVal) ^ (~LHSKnownZero ^ RHSVal)); + + // Now that we know which bits have carries, compute the known-1/0 sets. + + // Bits are known one if they are known zero in one operand and one in the + // other, and there is no input carry. + RHSKnownOne = ((LHSKnownZero & RHSVal) | + (LHSKnownOne & ~RHSVal)) & ~CarryBits; + + // Bits are known zero if they are known zero in both operands and there + // is no input carry. + RHSKnownZero = LHSKnownZero & ~RHSVal & ~CarryBits; + } else { + // If the high-bits of this ADD are not demanded, then it does not demand + // the high bits of its LHS or RHS. + if (DemandedMask[BitWidth-1] == 0) { + // Right fill the mask of bits for this ADD to demand the most + // significant bit and all those below it. + APInt DemandedFromOps(APInt::getLowBitsSet(BitWidth, BitWidth-NLZ)); + if (SimplifyDemandedBits(I->getOperandUse(0), DemandedFromOps, + LHSKnownZero, LHSKnownOne, Depth+1) || + SimplifyDemandedBits(I->getOperandUse(1), DemandedFromOps, + LHSKnownZero, LHSKnownOne, Depth+1)) + return I; + } + } + break; + } + case Instruction::Sub: + // If the high-bits of this SUB are not demanded, then it does not demand + // the high bits of its LHS or RHS. + if (DemandedMask[BitWidth-1] == 0) { + // Right fill the mask of bits for this SUB to demand the most + // significant bit and all those below it. + uint32_t NLZ = DemandedMask.countLeadingZeros(); + APInt DemandedFromOps(APInt::getLowBitsSet(BitWidth, BitWidth-NLZ)); + if (SimplifyDemandedBits(I->getOperandUse(0), DemandedFromOps, + LHSKnownZero, LHSKnownOne, Depth+1) || + SimplifyDemandedBits(I->getOperandUse(1), DemandedFromOps, + LHSKnownZero, LHSKnownOne, Depth+1)) + return I; + } + // Otherwise just hand the sub off to ComputeMaskedBits to fill in + // the known zeros and ones. + ComputeMaskedBits(V, DemandedMask, RHSKnownZero, RHSKnownOne, Depth); + break; + case Instruction::Shl: + if (ConstantInt *SA = dyn_cast(I->getOperand(1))) { + uint64_t ShiftAmt = SA->getLimitedValue(BitWidth); + APInt DemandedMaskIn(DemandedMask.lshr(ShiftAmt)); + if (SimplifyDemandedBits(I->getOperandUse(0), DemandedMaskIn, + RHSKnownZero, RHSKnownOne, Depth+1)) + return I; + assert(!(RHSKnownZero & RHSKnownOne) && "Bits known to be one AND zero?"); + RHSKnownZero <<= ShiftAmt; + RHSKnownOne <<= ShiftAmt; + // low bits known zero. + if (ShiftAmt) + RHSKnownZero |= APInt::getLowBitsSet(BitWidth, ShiftAmt); + } + break; + case Instruction::LShr: + // For a logical shift right + if (ConstantInt *SA = dyn_cast(I->getOperand(1))) { + uint64_t ShiftAmt = SA->getLimitedValue(BitWidth); + + // Unsigned shift right. + APInt DemandedMaskIn(DemandedMask.shl(ShiftAmt)); + if (SimplifyDemandedBits(I->getOperandUse(0), DemandedMaskIn, + RHSKnownZero, RHSKnownOne, Depth+1)) + return I; + assert(!(RHSKnownZero & RHSKnownOne) && "Bits known to be one AND zero?"); + RHSKnownZero = APIntOps::lshr(RHSKnownZero, ShiftAmt); + RHSKnownOne = APIntOps::lshr(RHSKnownOne, ShiftAmt); + if (ShiftAmt) { + // Compute the new bits that are at the top now. + APInt HighBits(APInt::getHighBitsSet(BitWidth, ShiftAmt)); + RHSKnownZero |= HighBits; // high bits known zero. + } + } + break; + case Instruction::AShr: + // If this is an arithmetic shift right and only the low-bit is set, we can + // always convert this into a logical shr, even if the shift amount is + // variable. The low bit of the shift cannot be an input sign bit unless + // the shift amount is >= the size of the datatype, which is undefined. + if (DemandedMask == 1) { + // Perform the logical shift right. + Instruction *NewVal = BinaryOperator::CreateLShr( + I->getOperand(0), I->getOperand(1), I->getName()); + return InsertNewInstBefore(NewVal, *I); + } + + // If the sign bit is the only bit demanded by this ashr, then there is no + // need to do it, the shift doesn't change the high bit. + if (DemandedMask.isSignBit()) + return I->getOperand(0); + + if (ConstantInt *SA = dyn_cast(I->getOperand(1))) { + uint32_t ShiftAmt = SA->getLimitedValue(BitWidth); + + // Signed shift right. + APInt DemandedMaskIn(DemandedMask.shl(ShiftAmt)); + // If any of the "high bits" are demanded, we should set the sign bit as + // demanded. + if (DemandedMask.countLeadingZeros() <= ShiftAmt) + DemandedMaskIn.set(BitWidth-1); + if (SimplifyDemandedBits(I->getOperandUse(0), DemandedMaskIn, + RHSKnownZero, RHSKnownOne, Depth+1)) + return I; + assert(!(RHSKnownZero & RHSKnownOne) && "Bits known to be one AND zero?"); + // Compute the new bits that are at the top now. + APInt HighBits(APInt::getHighBitsSet(BitWidth, ShiftAmt)); + RHSKnownZero = APIntOps::lshr(RHSKnownZero, ShiftAmt); + RHSKnownOne = APIntOps::lshr(RHSKnownOne, ShiftAmt); + + // Handle the sign bits. + APInt SignBit(APInt::getSignBit(BitWidth)); + // Adjust to where it is now in the mask. + SignBit = APIntOps::lshr(SignBit, ShiftAmt); + + // If the input sign bit is known to be zero, or if none of the top bits + // are demanded, turn this into an unsigned shift right. + if (BitWidth <= ShiftAmt || RHSKnownZero[BitWidth-ShiftAmt-1] || + (HighBits & ~DemandedMask) == HighBits) { + // Perform the logical shift right. + Instruction *NewVal = BinaryOperator::CreateLShr( + I->getOperand(0), SA, I->getName()); + return InsertNewInstBefore(NewVal, *I); + } else if ((RHSKnownOne & SignBit) != 0) { // New bits are known one. + RHSKnownOne |= HighBits; + } + } + break; + case Instruction::SRem: + if (ConstantInt *Rem = dyn_cast(I->getOperand(1))) { + APInt RA = Rem->getValue().abs(); + if (RA.isPowerOf2()) { + if (DemandedMask.ult(RA)) // srem won't affect demanded bits + return I->getOperand(0); + + APInt LowBits = RA - 1; + APInt Mask2 = LowBits | APInt::getSignBit(BitWidth); + if (SimplifyDemandedBits(I->getOperandUse(0), Mask2, + LHSKnownZero, LHSKnownOne, Depth+1)) + return I; + + if (LHSKnownZero[BitWidth-1] || ((LHSKnownZero & LowBits) == LowBits)) + LHSKnownZero |= ~LowBits; + + KnownZero |= LHSKnownZero & DemandedMask; + + assert(!(KnownZero & KnownOne) && "Bits known to be one AND zero?"); + } + } + break; + case Instruction::URem: { + APInt KnownZero2(BitWidth, 0), KnownOne2(BitWidth, 0); + APInt AllOnes = APInt::getAllOnesValue(BitWidth); + if (SimplifyDemandedBits(I->getOperandUse(0), AllOnes, + KnownZero2, KnownOne2, Depth+1) || + SimplifyDemandedBits(I->getOperandUse(1), AllOnes, + KnownZero2, KnownOne2, Depth+1)) + return I; + + unsigned Leaders = KnownZero2.countLeadingOnes(); + Leaders = std::max(Leaders, + KnownZero2.countLeadingOnes()); + KnownZero = APInt::getHighBitsSet(BitWidth, Leaders) & DemandedMask; + break; + } + case Instruction::Call: + if (IntrinsicInst *II = dyn_cast(I)) { + switch (II->getIntrinsicID()) { + default: break; + case Intrinsic::bswap: { + // If the only bits demanded come from one byte of the bswap result, + // just shift the input byte into position to eliminate the bswap. + unsigned NLZ = DemandedMask.countLeadingZeros(); + unsigned NTZ = DemandedMask.countTrailingZeros(); + + // Round NTZ down to the next byte. If we have 11 trailing zeros, then + // we need all the bits down to bit 8. Likewise, round NLZ. If we + // have 14 leading zeros, round to 8. + NLZ &= ~7; + NTZ &= ~7; + // If we need exactly one byte, we can do this transformation. + if (BitWidth-NLZ-NTZ == 8) { + unsigned ResultBit = NTZ; + unsigned InputBit = BitWidth-NTZ-8; + + // Replace this with either a left or right shift to get the byte into + // the right place. + Instruction *NewVal; + if (InputBit > ResultBit) + NewVal = BinaryOperator::CreateLShr(I->getOperand(1), + ConstantInt::get(I->getType(), InputBit-ResultBit)); + else + NewVal = BinaryOperator::CreateShl(I->getOperand(1), + ConstantInt::get(I->getType(), ResultBit-InputBit)); + NewVal->takeName(I); + return InsertNewInstBefore(NewVal, *I); + } + + // TODO: Could compute known zero/one bits based on the input. + break; + } + } + } + ComputeMaskedBits(V, DemandedMask, RHSKnownZero, RHSKnownOne, Depth); + break; + } + + // If the client is only demanding bits that we know, return the known + // constant. + if ((DemandedMask & (RHSKnownZero|RHSKnownOne)) == DemandedMask) + return Constant::getIntegerValue(VTy, RHSKnownOne); + return false; +} + + +/// SimplifyDemandedVectorElts - The specified value produces a vector with +/// any number of elements. DemandedElts contains the set of elements that are +/// actually used by the caller. This method analyzes which elements of the +/// operand are undef and returns that information in UndefElts. +/// +/// If the information about demanded elements can be used to simplify the +/// operation, the operation is simplified, then the resultant value is +/// returned. This returns null if no change was made. +Value *InstCombiner::SimplifyDemandedVectorElts(Value *V, APInt DemandedElts, + APInt& UndefElts, + unsigned Depth) { + unsigned VWidth = cast(V->getType())->getNumElements(); + APInt EltMask(APInt::getAllOnesValue(VWidth)); + assert((DemandedElts & ~EltMask) == 0 && "Invalid DemandedElts!"); + + if (isa(V)) { + // If the entire vector is undefined, just return this info. + UndefElts = EltMask; + return 0; + } else if (DemandedElts == 0) { // If nothing is demanded, provide undef. + UndefElts = EltMask; + return UndefValue::get(V->getType()); + } + + UndefElts = 0; + if (ConstantVector *CP = dyn_cast(V)) { + const Type *EltTy = cast(V->getType())->getElementType(); + Constant *Undef = UndefValue::get(EltTy); + + std::vector Elts; + for (unsigned i = 0; i != VWidth; ++i) + if (!DemandedElts[i]) { // If not demanded, set to undef. + Elts.push_back(Undef); + UndefElts.set(i); + } else if (isa(CP->getOperand(i))) { // Already undef. + Elts.push_back(Undef); + UndefElts.set(i); + } else { // Otherwise, defined. + Elts.push_back(CP->getOperand(i)); + } + + // If we changed the constant, return it. + Constant *NewCP = ConstantVector::get(Elts); + return NewCP != CP ? NewCP : 0; + } else if (isa(V)) { + // Simplify the CAZ to a ConstantVector where the non-demanded elements are + // set to undef. + + // Check if this is identity. If so, return 0 since we are not simplifying + // anything. + if (DemandedElts == ((1ULL << VWidth) -1)) + return 0; + + const Type *EltTy = cast(V->getType())->getElementType(); + Constant *Zero = Constant::getNullValue(EltTy); + Constant *Undef = UndefValue::get(EltTy); + std::vector Elts; + for (unsigned i = 0; i != VWidth; ++i) { + Constant *Elt = DemandedElts[i] ? Zero : Undef; + Elts.push_back(Elt); + } + UndefElts = DemandedElts ^ EltMask; + return ConstantVector::get(Elts); + } + + // Limit search depth. + if (Depth == 10) + return 0; + + // If multiple users are using the root value, procede with + // simplification conservatively assuming that all elements + // are needed. + if (!V->hasOneUse()) { + // Quit if we find multiple users of a non-root value though. + // They'll be handled when it's their turn to be visited by + // the main instcombine process. + if (Depth != 0) + // TODO: Just compute the UndefElts information recursively. + return 0; + + // Conservatively assume that all elements are needed. + DemandedElts = EltMask; + } + + Instruction *I = dyn_cast(V); + if (!I) return 0; // Only analyze instructions. + + bool MadeChange = false; + APInt UndefElts2(VWidth, 0); + Value *TmpV; + switch (I->getOpcode()) { + default: break; + + case Instruction::InsertElement: { + // If this is a variable index, we don't know which element it overwrites. + // demand exactly the same input as we produce. + ConstantInt *Idx = dyn_cast(I->getOperand(2)); + if (Idx == 0) { + // Note that we can't propagate undef elt info, because we don't know + // which elt is getting updated. + TmpV = SimplifyDemandedVectorElts(I->getOperand(0), DemandedElts, + UndefElts2, Depth+1); + if (TmpV) { I->setOperand(0, TmpV); MadeChange = true; } + break; + } + + // If this is inserting an element that isn't demanded, remove this + // insertelement. + unsigned IdxNo = Idx->getZExtValue(); + if (IdxNo >= VWidth || !DemandedElts[IdxNo]) { + Worklist.Add(I); + return I->getOperand(0); + } + + // Otherwise, the element inserted overwrites whatever was there, so the + // input demanded set is simpler than the output set. + APInt DemandedElts2 = DemandedElts; + DemandedElts2.clear(IdxNo); + TmpV = SimplifyDemandedVectorElts(I->getOperand(0), DemandedElts2, + UndefElts, Depth+1); + if (TmpV) { I->setOperand(0, TmpV); MadeChange = true; } + + // The inserted element is defined. + UndefElts.clear(IdxNo); + break; + } + case Instruction::ShuffleVector: { + ShuffleVectorInst *Shuffle = cast(I); + uint64_t LHSVWidth = + cast(Shuffle->getOperand(0)->getType())->getNumElements(); + APInt LeftDemanded(LHSVWidth, 0), RightDemanded(LHSVWidth, 0); + for (unsigned i = 0; i < VWidth; i++) { + if (DemandedElts[i]) { + unsigned MaskVal = Shuffle->getMaskValue(i); + if (MaskVal != -1u) { + assert(MaskVal < LHSVWidth * 2 && + "shufflevector mask index out of range!"); + if (MaskVal < LHSVWidth) + LeftDemanded.set(MaskVal); + else + RightDemanded.set(MaskVal - LHSVWidth); + } + } + } + + APInt UndefElts4(LHSVWidth, 0); + TmpV = SimplifyDemandedVectorElts(I->getOperand(0), LeftDemanded, + UndefElts4, Depth+1); + if (TmpV) { I->setOperand(0, TmpV); MadeChange = true; } + + APInt UndefElts3(LHSVWidth, 0); + TmpV = SimplifyDemandedVectorElts(I->getOperand(1), RightDemanded, + UndefElts3, Depth+1); + if (TmpV) { I->setOperand(1, TmpV); MadeChange = true; } + + bool NewUndefElts = false; + for (unsigned i = 0; i < VWidth; i++) { + unsigned MaskVal = Shuffle->getMaskValue(i); + if (MaskVal == -1u) { + UndefElts.set(i); + } else if (MaskVal < LHSVWidth) { + if (UndefElts4[MaskVal]) { + NewUndefElts = true; + UndefElts.set(i); + } + } else { + if (UndefElts3[MaskVal - LHSVWidth]) { + NewUndefElts = true; + UndefElts.set(i); + } + } + } + + if (NewUndefElts) { + // Add additional discovered undefs. + std::vector Elts; + for (unsigned i = 0; i < VWidth; ++i) { + if (UndefElts[i]) + Elts.push_back(UndefValue::get(Type::getInt32Ty(*Context))); + else + Elts.push_back(ConstantInt::get(Type::getInt32Ty(*Context), + Shuffle->getMaskValue(i))); + } + I->setOperand(2, ConstantVector::get(Elts)); + MadeChange = true; + } + break; + } + case Instruction::BitCast: { + // Vector->vector casts only. + const VectorType *VTy = dyn_cast(I->getOperand(0)->getType()); + if (!VTy) break; + unsigned InVWidth = VTy->getNumElements(); + APInt InputDemandedElts(InVWidth, 0); + unsigned Ratio; + + if (VWidth == InVWidth) { + // If we are converting from <4 x i32> -> <4 x f32>, we demand the same + // elements as are demanded of us. + Ratio = 1; + InputDemandedElts = DemandedElts; + } else if (VWidth > InVWidth) { + // Untested so far. + break; + + // If there are more elements in the result than there are in the source, + // then an input element is live if any of the corresponding output + // elements are live. + Ratio = VWidth/InVWidth; + for (unsigned OutIdx = 0; OutIdx != VWidth; ++OutIdx) { + if (DemandedElts[OutIdx]) + InputDemandedElts.set(OutIdx/Ratio); + } + } else { + // Untested so far. + break; + + // If there are more elements in the source than there are in the result, + // then an input element is live if the corresponding output element is + // live. + Ratio = InVWidth/VWidth; + for (unsigned InIdx = 0; InIdx != InVWidth; ++InIdx) + if (DemandedElts[InIdx/Ratio]) + InputDemandedElts.set(InIdx); + } + + // div/rem demand all inputs, because they don't want divide by zero. + TmpV = SimplifyDemandedVectorElts(I->getOperand(0), InputDemandedElts, + UndefElts2, Depth+1); + if (TmpV) { + I->setOperand(0, TmpV); + MadeChange = true; + } + + UndefElts = UndefElts2; + if (VWidth > InVWidth) { + llvm_unreachable("Unimp"); + // If there are more elements in the result than there are in the source, + // then an output element is undef if the corresponding input element is + // undef. + for (unsigned OutIdx = 0; OutIdx != VWidth; ++OutIdx) + if (UndefElts2[OutIdx/Ratio]) + UndefElts.set(OutIdx); + } else if (VWidth < InVWidth) { + llvm_unreachable("Unimp"); + // If there are more elements in the source than there are in the result, + // then a result element is undef if all of the corresponding input + // elements are undef. + UndefElts = ~0ULL >> (64-VWidth); // Start out all undef. + for (unsigned InIdx = 0; InIdx != InVWidth; ++InIdx) + if (!UndefElts2[InIdx]) // Not undef? + UndefElts.clear(InIdx/Ratio); // Clear undef bit. + } + break; + } + case Instruction::And: + case Instruction::Or: + case Instruction::Xor: + case Instruction::Add: + case Instruction::Sub: + case Instruction::Mul: + // div/rem demand all inputs, because they don't want divide by zero. + TmpV = SimplifyDemandedVectorElts(I->getOperand(0), DemandedElts, + UndefElts, Depth+1); + if (TmpV) { I->setOperand(0, TmpV); MadeChange = true; } + TmpV = SimplifyDemandedVectorElts(I->getOperand(1), DemandedElts, + UndefElts2, Depth+1); + if (TmpV) { I->setOperand(1, TmpV); MadeChange = true; } + + // Output elements are undefined if both are undefined. Consider things + // like undef&0. The result is known zero, not undef. + UndefElts &= UndefElts2; + break; + + case Instruction::Call: { + IntrinsicInst *II = dyn_cast(I); + if (!II) break; + switch (II->getIntrinsicID()) { + default: break; + + // Binary vector operations that work column-wise. A dest element is a + // function of the corresponding input elements from the two inputs. + case Intrinsic::x86_sse_sub_ss: + case Intrinsic::x86_sse_mul_ss: + case Intrinsic::x86_sse_min_ss: + case Intrinsic::x86_sse_max_ss: + case Intrinsic::x86_sse2_sub_sd: + case Intrinsic::x86_sse2_mul_sd: + case Intrinsic::x86_sse2_min_sd: + case Intrinsic::x86_sse2_max_sd: + TmpV = SimplifyDemandedVectorElts(II->getOperand(1), DemandedElts, + UndefElts, Depth+1); + if (TmpV) { II->setOperand(1, TmpV); MadeChange = true; } + TmpV = SimplifyDemandedVectorElts(II->getOperand(2), DemandedElts, + UndefElts2, Depth+1); + if (TmpV) { II->setOperand(2, TmpV); MadeChange = true; } + + // If only the low elt is demanded and this is a scalarizable intrinsic, + // scalarize it now. + if (DemandedElts == 1) { + switch (II->getIntrinsicID()) { + default: break; + case Intrinsic::x86_sse_sub_ss: + case Intrinsic::x86_sse_mul_ss: + case Intrinsic::x86_sse2_sub_sd: + case Intrinsic::x86_sse2_mul_sd: + // TODO: Lower MIN/MAX/ABS/etc + Value *LHS = II->getOperand(1); + Value *RHS = II->getOperand(2); + // Extract the element as scalars. + LHS = InsertNewInstBefore(ExtractElementInst::Create(LHS, + ConstantInt::get(Type::getInt32Ty(*Context), 0U, false), "tmp"), *II); + RHS = InsertNewInstBefore(ExtractElementInst::Create(RHS, + ConstantInt::get(Type::getInt32Ty(*Context), 0U, false), "tmp"), *II); + + switch (II->getIntrinsicID()) { + default: llvm_unreachable("Case stmts out of sync!"); + case Intrinsic::x86_sse_sub_ss: + case Intrinsic::x86_sse2_sub_sd: + TmpV = InsertNewInstBefore(BinaryOperator::CreateFSub(LHS, RHS, + II->getName()), *II); + break; + case Intrinsic::x86_sse_mul_ss: + case Intrinsic::x86_sse2_mul_sd: + TmpV = InsertNewInstBefore(BinaryOperator::CreateFMul(LHS, RHS, + II->getName()), *II); + break; + } + + Instruction *New = + InsertElementInst::Create( + UndefValue::get(II->getType()), TmpV, + ConstantInt::get(Type::getInt32Ty(*Context), 0U, false), II->getName()); + InsertNewInstBefore(New, *II); + return New; + } + } + + // Output elements are undefined if both are undefined. Consider things + // like undef&0. The result is known zero, not undef. + UndefElts &= UndefElts2; + break; + } + break; + } + } + return MadeChange ? I : 0; +} + + +/// AssociativeOpt - Perform an optimization on an associative operator. This +/// function is designed to check a chain of associative operators for a +/// potential to apply a certain optimization. Since the optimization may be +/// applicable if the expression was reassociated, this checks the chain, then +/// reassociates the expression as necessary to expose the optimization +/// opportunity. This makes use of a special Functor, which must define +/// 'shouldApply' and 'apply' methods. +/// +template +static Instruction *AssociativeOpt(BinaryOperator &Root, const Functor &F) { + unsigned Opcode = Root.getOpcode(); + Value *LHS = Root.getOperand(0); + + // Quick check, see if the immediate LHS matches... + if (F.shouldApply(LHS)) + return F.apply(Root); + + // Otherwise, if the LHS is not of the same opcode as the root, return. + Instruction *LHSI = dyn_cast(LHS); + while (LHSI && LHSI->getOpcode() == Opcode && LHSI->hasOneUse()) { + // Should we apply this transform to the RHS? + bool ShouldApply = F.shouldApply(LHSI->getOperand(1)); + + // If not to the RHS, check to see if we should apply to the LHS... + if (!ShouldApply && F.shouldApply(LHSI->getOperand(0))) { + cast(LHSI)->swapOperands(); // Make the LHS the RHS + ShouldApply = true; + } + + // If the functor wants to apply the optimization to the RHS of LHSI, + // reassociate the expression from ((? op A) op B) to (? op (A op B)) + if (ShouldApply) { + // Now all of the instructions are in the current basic block, go ahead + // and perform the reassociation. + Instruction *TmpLHSI = cast(Root.getOperand(0)); + + // First move the selected RHS to the LHS of the root... + Root.setOperand(0, LHSI->getOperand(1)); + + // Make what used to be the LHS of the root be the user of the root... + Value *ExtraOperand = TmpLHSI->getOperand(1); + if (&Root == TmpLHSI) { + Root.replaceAllUsesWith(Constant::getNullValue(TmpLHSI->getType())); + return 0; + } + Root.replaceAllUsesWith(TmpLHSI); // Users now use TmpLHSI + TmpLHSI->setOperand(1, &Root); // TmpLHSI now uses the root + BasicBlock::iterator ARI = &Root; ++ARI; + TmpLHSI->moveBefore(ARI); // Move TmpLHSI to after Root + ARI = Root; + + // Now propagate the ExtraOperand down the chain of instructions until we + // get to LHSI. + while (TmpLHSI != LHSI) { + Instruction *NextLHSI = cast(TmpLHSI->getOperand(0)); + // Move the instruction to immediately before the chain we are + // constructing to avoid breaking dominance properties. + NextLHSI->moveBefore(ARI); + ARI = NextLHSI; + + Value *NextOp = NextLHSI->getOperand(1); + NextLHSI->setOperand(1, ExtraOperand); + TmpLHSI = NextLHSI; + ExtraOperand = NextOp; + } + + // Now that the instructions are reassociated, have the functor perform + // the transformation... + return F.apply(Root); + } + + LHSI = dyn_cast(LHSI->getOperand(0)); + } + return 0; +} + +namespace { + +// AddRHS - Implements: X + X --> X << 1 +struct AddRHS { + Value *RHS; + explicit AddRHS(Value *rhs) : RHS(rhs) {} + bool shouldApply(Value *LHS) const { return LHS == RHS; } + Instruction *apply(BinaryOperator &Add) const { + return BinaryOperator::CreateShl(Add.getOperand(0), + ConstantInt::get(Add.getType(), 1)); + } +}; + +// AddMaskingAnd - Implements (A & C1)+(B & C2) --> (A & C1)|(B & C2) +// iff C1&C2 == 0 +struct AddMaskingAnd { + Constant *C2; + explicit AddMaskingAnd(Constant *c) : C2(c) {} + bool shouldApply(Value *LHS) const { + ConstantInt *C1; + return match(LHS, m_And(m_Value(), m_ConstantInt(C1))) && + ConstantExpr::getAnd(C1, C2)->isNullValue(); + } + Instruction *apply(BinaryOperator &Add) const { + return BinaryOperator::CreateOr(Add.getOperand(0), Add.getOperand(1)); + } +}; + +} + +static Value *FoldOperationIntoSelectOperand(Instruction &I, Value *SO, + InstCombiner *IC) { + if (CastInst *CI = dyn_cast(&I)) + return IC->Builder->CreateCast(CI->getOpcode(), SO, I.getType()); + + // Figure out if the constant is the left or the right argument. + bool ConstIsRHS = isa(I.getOperand(1)); + Constant *ConstOperand = cast(I.getOperand(ConstIsRHS)); + + if (Constant *SOC = dyn_cast(SO)) { + if (ConstIsRHS) + return ConstantExpr::get(I.getOpcode(), SOC, ConstOperand); + return ConstantExpr::get(I.getOpcode(), ConstOperand, SOC); + } + + Value *Op0 = SO, *Op1 = ConstOperand; + if (!ConstIsRHS) + std::swap(Op0, Op1); + + if (BinaryOperator *BO = dyn_cast(&I)) + return IC->Builder->CreateBinOp(BO->getOpcode(), Op0, Op1, + SO->getName()+".op"); + if (ICmpInst *CI = dyn_cast(&I)) + return IC->Builder->CreateICmp(CI->getPredicate(), Op0, Op1, + SO->getName()+".cmp"); + if (FCmpInst *CI = dyn_cast(&I)) + return IC->Builder->CreateICmp(CI->getPredicate(), Op0, Op1, + SO->getName()+".cmp"); + llvm_unreachable("Unknown binary instruction type!"); +} + +// FoldOpIntoSelect - Given an instruction with a select as one operand and a +// constant as the other operand, try to fold the binary operator into the +// select arguments. This also works for Cast instructions, which obviously do +// not have a second operand. +static Instruction *FoldOpIntoSelect(Instruction &Op, SelectInst *SI, + InstCombiner *IC) { + // Don't modify shared select instructions + if (!SI->hasOneUse()) return 0; + Value *TV = SI->getOperand(1); + Value *FV = SI->getOperand(2); + + if (isa(TV) || isa(FV)) { + // Bool selects with constant operands can be folded to logical ops. + if (SI->getType() == Type::getInt1Ty(*IC->getContext())) return 0; + + Value *SelectTrueVal = FoldOperationIntoSelectOperand(Op, TV, IC); + Value *SelectFalseVal = FoldOperationIntoSelectOperand(Op, FV, IC); + + return SelectInst::Create(SI->getCondition(), SelectTrueVal, + SelectFalseVal); + } + return 0; +} + + +/// FoldOpIntoPhi - Given a binary operator, cast instruction, or select which +/// has a PHI node as operand #0, see if we can fold the instruction into the +/// PHI (which is only possible if all operands to the PHI are constants). +/// +/// If AllowAggressive is true, FoldOpIntoPhi will allow certain transforms +/// that would normally be unprofitable because they strongly encourage jump +/// threading. +Instruction *InstCombiner::FoldOpIntoPhi(Instruction &I, + bool AllowAggressive) { + AllowAggressive = false; + PHINode *PN = cast(I.getOperand(0)); + unsigned NumPHIValues = PN->getNumIncomingValues(); + if (NumPHIValues == 0 || + // We normally only transform phis with a single use, unless we're trying + // hard to make jump threading happen. + (!PN->hasOneUse() && !AllowAggressive)) + return 0; + + + // Check to see if all of the operands of the PHI are simple constants + // (constantint/constantfp/undef). If there is one non-constant value, + // remember the BB it is in. If there is more than one or if *it* is a PHI, + // bail out. We don't do arbitrary constant expressions here because moving + // their computation can be expensive without a cost model. + BasicBlock *NonConstBB = 0; + for (unsigned i = 0; i != NumPHIValues; ++i) + if (!isa(PN->getIncomingValue(i)) || + isa(PN->getIncomingValue(i))) { + if (NonConstBB) return 0; // More than one non-const value. + if (isa(PN->getIncomingValue(i))) return 0; // Itself a phi. + NonConstBB = PN->getIncomingBlock(i); + + // If the incoming non-constant value is in I's block, we have an infinite + // loop. + if (NonConstBB == I.getParent()) + return 0; + } + + // If there is exactly one non-constant value, we can insert a copy of the + // operation in that block. However, if this is a critical edge, we would be + // inserting the computation one some other paths (e.g. inside a loop). Only + // do this if the pred block is unconditionally branching into the phi block. + if (NonConstBB != 0 && !AllowAggressive) { + BranchInst *BI = dyn_cast(NonConstBB->getTerminator()); + if (!BI || !BI->isUnconditional()) return 0; + } + + // Okay, we can do the transformation: create the new PHI node. + PHINode *NewPN = PHINode::Create(I.getType(), ""); + NewPN->reserveOperandSpace(PN->getNumOperands()/2); + InsertNewInstBefore(NewPN, *PN); + NewPN->takeName(PN); + + // Next, add all of the operands to the PHI. + if (SelectInst *SI = dyn_cast(&I)) { + // We only currently try to fold the condition of a select when it is a phi, + // not the true/false values. + Value *TrueV = SI->getTrueValue(); + Value *FalseV = SI->getFalseValue(); + BasicBlock *PhiTransBB = PN->getParent(); + for (unsigned i = 0; i != NumPHIValues; ++i) { + BasicBlock *ThisBB = PN->getIncomingBlock(i); + Value *TrueVInPred = TrueV->DoPHITranslation(PhiTransBB, ThisBB); + Value *FalseVInPred = FalseV->DoPHITranslation(PhiTransBB, ThisBB); + Value *InV = 0; + if (Constant *InC = dyn_cast(PN->getIncomingValue(i))) { + InV = InC->isNullValue() ? FalseVInPred : TrueVInPred; + } else { + assert(PN->getIncomingBlock(i) == NonConstBB); + InV = SelectInst::Create(PN->getIncomingValue(i), TrueVInPred, + FalseVInPred, + "phitmp", NonConstBB->getTerminator()); + Worklist.Add(cast(InV)); + } + NewPN->addIncoming(InV, ThisBB); + } + } else if (I.getNumOperands() == 2) { + Constant *C = cast(I.getOperand(1)); + for (unsigned i = 0; i != NumPHIValues; ++i) { + Value *InV = 0; + if (Constant *InC = dyn_cast(PN->getIncomingValue(i))) { + if (CmpInst *CI = dyn_cast(&I)) + InV = ConstantExpr::getCompare(CI->getPredicate(), InC, C); + else + InV = ConstantExpr::get(I.getOpcode(), InC, C); + } else { + assert(PN->getIncomingBlock(i) == NonConstBB); + if (BinaryOperator *BO = dyn_cast(&I)) + InV = BinaryOperator::Create(BO->getOpcode(), + PN->getIncomingValue(i), C, "phitmp", + NonConstBB->getTerminator()); + else if (CmpInst *CI = dyn_cast(&I)) + InV = CmpInst::Create(CI->getOpcode(), + CI->getPredicate(), + PN->getIncomingValue(i), C, "phitmp", + NonConstBB->getTerminator()); + else + llvm_unreachable("Unknown binop!"); + + Worklist.Add(cast(InV)); + } + NewPN->addIncoming(InV, PN->getIncomingBlock(i)); + } + } else { + CastInst *CI = cast(&I); + const Type *RetTy = CI->getType(); + for (unsigned i = 0; i != NumPHIValues; ++i) { + Value *InV; + if (Constant *InC = dyn_cast(PN->getIncomingValue(i))) { + InV = ConstantExpr::getCast(CI->getOpcode(), InC, RetTy); + } else { + assert(PN->getIncomingBlock(i) == NonConstBB); + InV = CastInst::Create(CI->getOpcode(), PN->getIncomingValue(i), + I.getType(), "phitmp", + NonConstBB->getTerminator()); + Worklist.Add(cast(InV)); + } + NewPN->addIncoming(InV, PN->getIncomingBlock(i)); + } + } + return ReplaceInstUsesWith(I, NewPN); +} + + +/// WillNotOverflowSignedAdd - Return true if we can prove that: +/// (sext (add LHS, RHS)) === (add (sext LHS), (sext RHS)) +/// This basically requires proving that the add in the original type would not +/// overflow to change the sign bit or have a carry out. +bool InstCombiner::WillNotOverflowSignedAdd(Value *LHS, Value *RHS) { + // There are different heuristics we can use for this. Here are some simple + // ones. + + // Add has the property that adding any two 2's complement numbers can only + // have one carry bit which can change a sign. As such, if LHS and RHS each + // have at least two sign bits, we know that the addition of the two values will + // sign extend fine. + if (ComputeNumSignBits(LHS) > 1 && ComputeNumSignBits(RHS) > 1) + return true; + + + // If one of the operands only has one non-zero bit, and if the other operand + // has a known-zero bit in a more significant place than it (not including the + // sign bit) the ripple may go up to and fill the zero, but won't change the + // sign. For example, (X & ~4) + 1. + + // TODO: Implement. + + return false; +} + + +Instruction *InstCombiner::visitAdd(BinaryOperator &I) { + bool Changed = SimplifyCommutative(I); + Value *LHS = I.getOperand(0), *RHS = I.getOperand(1); + + if (Constant *RHSC = dyn_cast(RHS)) { + // X + undef -> undef + if (isa(RHS)) + return ReplaceInstUsesWith(I, RHS); + + // X + 0 --> X + if (RHSC->isNullValue()) + return ReplaceInstUsesWith(I, LHS); + + if (ConstantInt *CI = dyn_cast(RHSC)) { + // X + (signbit) --> X ^ signbit + const APInt& Val = CI->getValue(); + uint32_t BitWidth = Val.getBitWidth(); + if (Val == APInt::getSignBit(BitWidth)) + return BinaryOperator::CreateXor(LHS, RHS); + + // See if SimplifyDemandedBits can simplify this. This handles stuff like + // (X & 254)+1 -> (X&254)|1 + if (SimplifyDemandedInstructionBits(I)) + return &I; + + // zext(bool) + C -> bool ? C + 1 : C + if (ZExtInst *ZI = dyn_cast(LHS)) + if (ZI->getSrcTy() == Type::getInt1Ty(*Context)) + return SelectInst::Create(ZI->getOperand(0), AddOne(CI), CI); + } + + if (isa(LHS)) + if (Instruction *NV = FoldOpIntoPhi(I)) + return NV; + + ConstantInt *XorRHS = 0; + Value *XorLHS = 0; + if (isa(RHSC) && + match(LHS, m_Xor(m_Value(XorLHS), m_ConstantInt(XorRHS)))) { + uint32_t TySizeBits = I.getType()->getScalarSizeInBits(); + const APInt& RHSVal = cast(RHSC)->getValue(); + + uint32_t Size = TySizeBits / 2; + APInt C0080Val(APInt(TySizeBits, 1ULL).shl(Size - 1)); + APInt CFF80Val(-C0080Val); + do { + if (TySizeBits > Size) { + // If we have ADD(XOR(AND(X, 0xFF), 0x80), 0xF..F80), it's a sext. + // If we have ADD(XOR(AND(X, 0xFF), 0xF..F80), 0x80), it's a sext. + if ((RHSVal == CFF80Val && XorRHS->getValue() == C0080Val) || + (RHSVal == C0080Val && XorRHS->getValue() == CFF80Val)) { + // This is a sign extend if the top bits are known zero. + if (!MaskedValueIsZero(XorLHS, + APInt::getHighBitsSet(TySizeBits, TySizeBits - Size))) + Size = 0; // Not a sign ext, but can't be any others either. + break; + } + } + Size >>= 1; + C0080Val = APIntOps::lshr(C0080Val, Size); + CFF80Val = APIntOps::ashr(CFF80Val, Size); + } while (Size >= 1); + + // FIXME: This shouldn't be necessary. When the backends can handle types + // with funny bit widths then this switch statement should be removed. It + // is just here to get the size of the "middle" type back up to something + // that the back ends can handle. + const Type *MiddleType = 0; + switch (Size) { + default: break; + case 32: MiddleType = Type::getInt32Ty(*Context); break; + case 16: MiddleType = Type::getInt16Ty(*Context); break; + case 8: MiddleType = Type::getInt8Ty(*Context); break; + } + if (MiddleType) { + Value *NewTrunc = Builder->CreateTrunc(XorLHS, MiddleType, "sext"); + return new SExtInst(NewTrunc, I.getType(), I.getName()); + } + } + } + + if (I.getType() == Type::getInt1Ty(*Context)) + return BinaryOperator::CreateXor(LHS, RHS); + + // X + X --> X << 1 + if (I.getType()->isInteger()) { + if (Instruction *Result = AssociativeOpt(I, AddRHS(RHS))) + return Result; + + if (Instruction *RHSI = dyn_cast(RHS)) { + if (RHSI->getOpcode() == Instruction::Sub) + if (LHS == RHSI->getOperand(1)) // A + (B - A) --> B + return ReplaceInstUsesWith(I, RHSI->getOperand(0)); + } + if (Instruction *LHSI = dyn_cast(LHS)) { + if (LHSI->getOpcode() == Instruction::Sub) + if (RHS == LHSI->getOperand(1)) // (B - A) + A --> B + return ReplaceInstUsesWith(I, LHSI->getOperand(0)); + } + } + + // -A + B --> B - A + // -A + -B --> -(A + B) + if (Value *LHSV = dyn_castNegVal(LHS)) { + if (LHS->getType()->isIntOrIntVector()) { + if (Value *RHSV = dyn_castNegVal(RHS)) { + Value *NewAdd = Builder->CreateAdd(LHSV, RHSV, "sum"); + return BinaryOperator::CreateNeg(NewAdd); + } + } + + return BinaryOperator::CreateSub(RHS, LHSV); + } + + // A + -B --> A - B + if (!isa(RHS)) + if (Value *V = dyn_castNegVal(RHS)) + return BinaryOperator::CreateSub(LHS, V); + + + ConstantInt *C2; + if (Value *X = dyn_castFoldableMul(LHS, C2)) { + if (X == RHS) // X*C + X --> X * (C+1) + return BinaryOperator::CreateMul(RHS, AddOne(C2)); + + // X*C1 + X*C2 --> X * (C1+C2) + ConstantInt *C1; + if (X == dyn_castFoldableMul(RHS, C1)) + return BinaryOperator::CreateMul(X, ConstantExpr::getAdd(C1, C2)); + } + + // X + X*C --> X * (C+1) + if (dyn_castFoldableMul(RHS, C2) == LHS) + return BinaryOperator::CreateMul(LHS, AddOne(C2)); + + // X + ~X --> -1 since ~X = -X-1 + if (dyn_castNotVal(LHS) == RHS || + dyn_castNotVal(RHS) == LHS) + return ReplaceInstUsesWith(I, Constant::getAllOnesValue(I.getType())); + + + // (A & C1)+(B & C2) --> (A & C1)|(B & C2) iff C1&C2 == 0 + if (match(RHS, m_And(m_Value(), m_ConstantInt(C2)))) + if (Instruction *R = AssociativeOpt(I, AddMaskingAnd(C2))) + return R; + + // A+B --> A|B iff A and B have no bits set in common. + if (const IntegerType *IT = dyn_cast(I.getType())) { + APInt Mask = APInt::getAllOnesValue(IT->getBitWidth()); + APInt LHSKnownOne(IT->getBitWidth(), 0); + APInt LHSKnownZero(IT->getBitWidth(), 0); + ComputeMaskedBits(LHS, Mask, LHSKnownZero, LHSKnownOne); + if (LHSKnownZero != 0) { + APInt RHSKnownOne(IT->getBitWidth(), 0); + APInt RHSKnownZero(IT->getBitWidth(), 0); + ComputeMaskedBits(RHS, Mask, RHSKnownZero, RHSKnownOne); + + // No bits in common -> bitwise or. + if ((LHSKnownZero|RHSKnownZero).isAllOnesValue()) + return BinaryOperator::CreateOr(LHS, RHS); + } + } + + // W*X + Y*Z --> W * (X+Z) iff W == Y + if (I.getType()->isIntOrIntVector()) { + Value *W, *X, *Y, *Z; + if (match(LHS, m_Mul(m_Value(W), m_Value(X))) && + match(RHS, m_Mul(m_Value(Y), m_Value(Z)))) { + if (W != Y) { + if (W == Z) { + std::swap(Y, Z); + } else if (Y == X) { + std::swap(W, X); + } else if (X == Z) { + std::swap(Y, Z); + std::swap(W, X); + } + } + + if (W == Y) { + Value *NewAdd = Builder->CreateAdd(X, Z, LHS->getName()); + return BinaryOperator::CreateMul(W, NewAdd); + } + } + } + + if (ConstantInt *CRHS = dyn_cast(RHS)) { + Value *X = 0; + if (match(LHS, m_Not(m_Value(X)))) // ~X + C --> (C-1) - X + return BinaryOperator::CreateSub(SubOne(CRHS), X); + + // (X & FF00) + xx00 -> (X+xx00) & FF00 + if (LHS->hasOneUse() && + match(LHS, m_And(m_Value(X), m_ConstantInt(C2)))) { + Constant *Anded = ConstantExpr::getAnd(CRHS, C2); + if (Anded == CRHS) { + // See if all bits from the first bit set in the Add RHS up are included + // in the mask. First, get the rightmost bit. + const APInt& AddRHSV = CRHS->getValue(); + + // Form a mask of all bits from the lowest bit added through the top. + APInt AddRHSHighBits(~((AddRHSV & -AddRHSV)-1)); + + // See if the and mask includes all of these bits. + APInt AddRHSHighBitsAnd(AddRHSHighBits & C2->getValue()); + + if (AddRHSHighBits == AddRHSHighBitsAnd) { + // Okay, the xform is safe. Insert the new add pronto. + Value *NewAdd = Builder->CreateAdd(X, CRHS, LHS->getName()); + return BinaryOperator::CreateAnd(NewAdd, C2); + } + } + } + + // Try to fold constant add into select arguments. + if (SelectInst *SI = dyn_cast(LHS)) + if (Instruction *R = FoldOpIntoSelect(I, SI, this)) + return R; + } + + // add (select X 0 (sub n A)) A --> select X A n + { + SelectInst *SI = dyn_cast(LHS); + Value *A = RHS; + if (!SI) { + SI = dyn_cast(RHS); + A = LHS; + } + if (SI && SI->hasOneUse()) { + Value *TV = SI->getTrueValue(); + Value *FV = SI->getFalseValue(); + Value *N; + + // Can we fold the add into the argument of the select? + // We check both true and false select arguments for a matching subtract. + if (match(FV, m_Zero()) && + match(TV, m_Sub(m_Value(N), m_Specific(A)))) + // Fold the add into the true select value. + return SelectInst::Create(SI->getCondition(), N, A); + if (match(TV, m_Zero()) && + match(FV, m_Sub(m_Value(N), m_Specific(A)))) + // Fold the add into the false select value. + return SelectInst::Create(SI->getCondition(), A, N); + } + } + + // Check for (add (sext x), y), see if we can merge this into an + // integer add followed by a sext. + if (SExtInst *LHSConv = dyn_cast(LHS)) { + // (add (sext x), cst) --> (sext (add x, cst')) + if (ConstantInt *RHSC = dyn_cast(RHS)) { + Constant *CI = + ConstantExpr::getTrunc(RHSC, LHSConv->getOperand(0)->getType()); + if (LHSConv->hasOneUse() && + ConstantExpr::getSExt(CI, I.getType()) == RHSC && + WillNotOverflowSignedAdd(LHSConv->getOperand(0), CI)) { + // Insert the new, smaller add. + Value *NewAdd = Builder->CreateNSWAdd(LHSConv->getOperand(0), + CI, "addconv"); + return new SExtInst(NewAdd, I.getType()); + } + } + + // (add (sext x), (sext y)) --> (sext (add int x, y)) + if (SExtInst *RHSConv = dyn_cast(RHS)) { + // Only do this if x/y have the same type, if at last one of them has a + // single use (so we don't increase the number of sexts), and if the + // integer add will not overflow. + if (LHSConv->getOperand(0)->getType()==RHSConv->getOperand(0)->getType()&& + (LHSConv->hasOneUse() || RHSConv->hasOneUse()) && + WillNotOverflowSignedAdd(LHSConv->getOperand(0), + RHSConv->getOperand(0))) { + // Insert the new integer add. + Value *NewAdd = Builder->CreateNSWAdd(LHSConv->getOperand(0), + RHSConv->getOperand(0), "addconv"); + return new SExtInst(NewAdd, I.getType()); + } + } + } + + return Changed ? &I : 0; +} + +Instruction *InstCombiner::visitFAdd(BinaryOperator &I) { + bool Changed = SimplifyCommutative(I); + Value *LHS = I.getOperand(0), *RHS = I.getOperand(1); + + if (Constant *RHSC = dyn_cast(RHS)) { + // X + 0 --> X + if (ConstantFP *CFP = dyn_cast(RHSC)) { + if (CFP->isExactlyValue(ConstantFP::getNegativeZero + (I.getType())->getValueAPF())) + return ReplaceInstUsesWith(I, LHS); + } + + if (isa(LHS)) + if (Instruction *NV = FoldOpIntoPhi(I)) + return NV; + } + + // -A + B --> B - A + // -A + -B --> -(A + B) + if (Value *LHSV = dyn_castFNegVal(LHS)) + return BinaryOperator::CreateFSub(RHS, LHSV); + + // A + -B --> A - B + if (!isa(RHS)) + if (Value *V = dyn_castFNegVal(RHS)) + return BinaryOperator::CreateFSub(LHS, V); + + // Check for X+0.0. Simplify it to X if we know X is not -0.0. + if (ConstantFP *CFP = dyn_cast(RHS)) + if (CFP->getValueAPF().isPosZero() && CannotBeNegativeZero(LHS)) + return ReplaceInstUsesWith(I, LHS); + + // Check for (add double (sitofp x), y), see if we can merge this into an + // integer add followed by a promotion. + if (SIToFPInst *LHSConv = dyn_cast(LHS)) { + // (add double (sitofp x), fpcst) --> (sitofp (add int x, intcst)) + // ... if the constant fits in the integer value. This is useful for things + // like (double)(x & 1234) + 4.0 -> (double)((X & 1234)+4) which no longer + // requires a constant pool load, and generally allows the add to be better + // instcombined. + if (ConstantFP *CFP = dyn_cast(RHS)) { + Constant *CI = + ConstantExpr::getFPToSI(CFP, LHSConv->getOperand(0)->getType()); + if (LHSConv->hasOneUse() && + ConstantExpr::getSIToFP(CI, I.getType()) == CFP && + WillNotOverflowSignedAdd(LHSConv->getOperand(0), CI)) { + // Insert the new integer add. + Value *NewAdd = Builder->CreateNSWAdd(LHSConv->getOperand(0), + CI, "addconv"); + return new SIToFPInst(NewAdd, I.getType()); + } + } + + // (add double (sitofp x), (sitofp y)) --> (sitofp (add int x, y)) + if (SIToFPInst *RHSConv = dyn_cast(RHS)) { + // Only do this if x/y have the same type, if at last one of them has a + // single use (so we don't increase the number of int->fp conversions), + // and if the integer add will not overflow. + if (LHSConv->getOperand(0)->getType()==RHSConv->getOperand(0)->getType()&& + (LHSConv->hasOneUse() || RHSConv->hasOneUse()) && + WillNotOverflowSignedAdd(LHSConv->getOperand(0), + RHSConv->getOperand(0))) { + // Insert the new integer add. + Value *NewAdd = Builder->CreateNSWAdd(LHSConv->getOperand(0), + RHSConv->getOperand(0),"addconv"); + return new SIToFPInst(NewAdd, I.getType()); + } + } + } + + return Changed ? &I : 0; +} + + +/// EmitGEPOffset - Given a getelementptr instruction/constantexpr, emit the +/// code necessary to compute the offset from the base pointer (without adding +/// in the base pointer). Return the result as a signed integer of intptr size. +static Value *EmitGEPOffset(User *GEP, InstCombiner &IC) { + TargetData &TD = *IC.getTargetData(); + gep_type_iterator GTI = gep_type_begin(GEP); + const Type *IntPtrTy = TD.getIntPtrType(GEP->getContext()); + Value *Result = Constant::getNullValue(IntPtrTy); + + // Build a mask for high order bits. + unsigned IntPtrWidth = TD.getPointerSizeInBits(); + uint64_t PtrSizeMask = ~0ULL >> (64-IntPtrWidth); + + for (User::op_iterator i = GEP->op_begin() + 1, e = GEP->op_end(); i != e; + ++i, ++GTI) { + Value *Op = *i; + uint64_t Size = TD.getTypeAllocSize(GTI.getIndexedType()) & PtrSizeMask; + if (ConstantInt *OpC = dyn_cast(Op)) { + if (OpC->isZero()) continue; + + // Handle a struct index, which adds its field offset to the pointer. + if (const StructType *STy = dyn_cast(*GTI)) { + Size = TD.getStructLayout(STy)->getElementOffset(OpC->getZExtValue()); + + Result = IC.Builder->CreateAdd(Result, + ConstantInt::get(IntPtrTy, Size), + GEP->getName()+".offs"); + continue; + } + + Constant *Scale = ConstantInt::get(IntPtrTy, Size); + Constant *OC = + ConstantExpr::getIntegerCast(OpC, IntPtrTy, true /*SExt*/); + Scale = ConstantExpr::getMul(OC, Scale); + // Emit an add instruction. + Result = IC.Builder->CreateAdd(Result, Scale, GEP->getName()+".offs"); + continue; + } + // Convert to correct type. + if (Op->getType() != IntPtrTy) + Op = IC.Builder->CreateIntCast(Op, IntPtrTy, true, Op->getName()+".c"); + if (Size != 1) { + Constant *Scale = ConstantInt::get(IntPtrTy, Size); + // We'll let instcombine(mul) convert this to a shl if possible. + Op = IC.Builder->CreateMul(Op, Scale, GEP->getName()+".idx"); + } + + // Emit an add instruction. + Result = IC.Builder->CreateAdd(Op, Result, GEP->getName()+".offs"); + } + return Result; +} + + +/// EvaluateGEPOffsetExpression - Return a value that can be used to compare +/// the *offset* implied by a GEP to zero. For example, if we have &A[i], we +/// want to return 'i' for "icmp ne i, 0". Note that, in general, indices can +/// be complex, and scales are involved. The above expression would also be +/// legal to codegen as "icmp ne (i*4), 0" (assuming A is a pointer to i32). +/// This later form is less amenable to optimization though, and we are allowed +/// to generate the first by knowing that pointer arithmetic doesn't overflow. +/// +/// If we can't emit an optimized form for this expression, this returns null. +/// +static Value *EvaluateGEPOffsetExpression(User *GEP, Instruction &I, + InstCombiner &IC) { + TargetData &TD = *IC.getTargetData(); + gep_type_iterator GTI = gep_type_begin(GEP); + + // Check to see if this gep only has a single variable index. If so, and if + // any constant indices are a multiple of its scale, then we can compute this + // in terms of the scale of the variable index. For example, if the GEP + // implies an offset of "12 + i*4", then we can codegen this as "3 + i", + // because the expression will cross zero at the same point. + unsigned i, e = GEP->getNumOperands(); + int64_t Offset = 0; + for (i = 1; i != e; ++i, ++GTI) { + if (ConstantInt *CI = dyn_cast(GEP->getOperand(i))) { + // Compute the aggregate offset of constant indices. + if (CI->isZero()) continue; + + // Handle a struct index, which adds its field offset to the pointer. + if (const StructType *STy = dyn_cast(*GTI)) { + Offset += TD.getStructLayout(STy)->getElementOffset(CI->getZExtValue()); + } else { + uint64_t Size = TD.getTypeAllocSize(GTI.getIndexedType()); + Offset += Size*CI->getSExtValue(); + } + } else { + // Found our variable index. + break; + } + } + + // If there are no variable indices, we must have a constant offset, just + // evaluate it the general way. + if (i == e) return 0; + + Value *VariableIdx = GEP->getOperand(i); + // Determine the scale factor of the variable element. For example, this is + // 4 if the variable index is into an array of i32. + uint64_t VariableScale = TD.getTypeAllocSize(GTI.getIndexedType()); + + // Verify that there are no other variable indices. If so, emit the hard way. + for (++i, ++GTI; i != e; ++i, ++GTI) { + ConstantInt *CI = dyn_cast(GEP->getOperand(i)); + if (!CI) return 0; + + // Compute the aggregate offset of constant indices. + if (CI->isZero()) continue; + + // Handle a struct index, which adds its field offset to the pointer. + if (const StructType *STy = dyn_cast(*GTI)) { + Offset += TD.getStructLayout(STy)->getElementOffset(CI->getZExtValue()); + } else { + uint64_t Size = TD.getTypeAllocSize(GTI.getIndexedType()); + Offset += Size*CI->getSExtValue(); + } + } + + // Okay, we know we have a single variable index, which must be a + // pointer/array/vector index. If there is no offset, life is simple, return + // the index. + unsigned IntPtrWidth = TD.getPointerSizeInBits(); + if (Offset == 0) { + // Cast to intptrty in case a truncation occurs. If an extension is needed, + // we don't need to bother extending: the extension won't affect where the + // computation crosses zero. + if (VariableIdx->getType()->getPrimitiveSizeInBits() > IntPtrWidth) + VariableIdx = new TruncInst(VariableIdx, + TD.getIntPtrType(VariableIdx->getContext()), + VariableIdx->getName(), &I); + return VariableIdx; + } + + // Otherwise, there is an index. The computation we will do will be modulo + // the pointer size, so get it. + uint64_t PtrSizeMask = ~0ULL >> (64-IntPtrWidth); + + Offset &= PtrSizeMask; + VariableScale &= PtrSizeMask; + + // To do this transformation, any constant index must be a multiple of the + // variable scale factor. For example, we can evaluate "12 + 4*i" as "3 + i", + // but we can't evaluate "10 + 3*i" in terms of i. Check that the offset is a + // multiple of the variable scale. + int64_t NewOffs = Offset / (int64_t)VariableScale; + if (Offset != NewOffs*(int64_t)VariableScale) + return 0; + + // Okay, we can do this evaluation. Start by converting the index to intptr. + const Type *IntPtrTy = TD.getIntPtrType(VariableIdx->getContext()); + if (VariableIdx->getType() != IntPtrTy) + VariableIdx = CastInst::CreateIntegerCast(VariableIdx, IntPtrTy, + true /*SExt*/, + VariableIdx->getName(), &I); + Constant *OffsetVal = ConstantInt::get(IntPtrTy, NewOffs); + return BinaryOperator::CreateAdd(VariableIdx, OffsetVal, "offset", &I); +} + + +/// Optimize pointer differences into the same array into a size. Consider: +/// &A[10] - &A[0]: we should compile this to "10". LHS/RHS are the pointer +/// operands to the ptrtoint instructions for the LHS/RHS of the subtract. +/// +Value *InstCombiner::OptimizePointerDifference(Value *LHS, Value *RHS, + const Type *Ty) { + assert(TD && "Must have target data info for this"); + + // If LHS is a gep based on RHS or RHS is a gep based on LHS, we can optimize + // this. + bool Swapped; + GetElementPtrInst *GEP; + + if ((GEP = dyn_cast(LHS)) && + GEP->getOperand(0) == RHS) + Swapped = false; + else if ((GEP = dyn_cast(RHS)) && + GEP->getOperand(0) == LHS) + Swapped = true; + else + return 0; + + // TODO: Could also optimize &A[i] - &A[j] -> "i-j". + + // Emit the offset of the GEP and an intptr_t. + Value *Result = EmitGEPOffset(GEP, *this); + + // If we have p - gep(p, ...) then we have to negate the result. + if (Swapped) + Result = Builder->CreateNeg(Result, "diff.neg"); + + return Builder->CreateIntCast(Result, Ty, true); +} + + +Instruction *InstCombiner::visitSub(BinaryOperator &I) { + Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1); + + if (Op0 == Op1) // sub X, X -> 0 + return ReplaceInstUsesWith(I, Constant::getNullValue(I.getType())); + + // If this is a 'B = x-(-A)', change to B = x+A. + if (Value *V = dyn_castNegVal(Op1)) + return BinaryOperator::CreateAdd(Op0, V); + + if (isa(Op0)) + return ReplaceInstUsesWith(I, Op0); // undef - X -> undef + if (isa(Op1)) + return ReplaceInstUsesWith(I, Op1); // X - undef -> undef + if (I.getType() == Type::getInt1Ty(*Context)) + return BinaryOperator::CreateXor(Op0, Op1); + + if (ConstantInt *C = dyn_cast(Op0)) { + // Replace (-1 - A) with (~A). + if (C->isAllOnesValue()) + return BinaryOperator::CreateNot(Op1); + + // C - ~X == X + (1+C) + Value *X = 0; + if (match(Op1, m_Not(m_Value(X)))) + return BinaryOperator::CreateAdd(X, AddOne(C)); + + // -(X >>u 31) -> (X >>s 31) + // -(X >>s 31) -> (X >>u 31) + if (C->isZero()) { + if (BinaryOperator *SI = dyn_cast(Op1)) { + if (SI->getOpcode() == Instruction::LShr) { + if (ConstantInt *CU = dyn_cast(SI->getOperand(1))) { + // Check to see if we are shifting out everything but the sign bit. + if (CU->getLimitedValue(SI->getType()->getPrimitiveSizeInBits()) == + SI->getType()->getPrimitiveSizeInBits()-1) { + // Ok, the transformation is safe. Insert AShr. + return BinaryOperator::Create(Instruction::AShr, + SI->getOperand(0), CU, SI->getName()); + } + } + } else if (SI->getOpcode() == Instruction::AShr) { + if (ConstantInt *CU = dyn_cast(SI->getOperand(1))) { + // Check to see if we are shifting out everything but the sign bit. + if (CU->getLimitedValue(SI->getType()->getPrimitiveSizeInBits()) == + SI->getType()->getPrimitiveSizeInBits()-1) { + // Ok, the transformation is safe. Insert LShr. + return BinaryOperator::CreateLShr( + SI->getOperand(0), CU, SI->getName()); + } + } + } + } + } + + // Try to fold constant sub into select arguments. + if (SelectInst *SI = dyn_cast(Op1)) + if (Instruction *R = FoldOpIntoSelect(I, SI, this)) + return R; + + // C - zext(bool) -> bool ? C - 1 : C + if (ZExtInst *ZI = dyn_cast(Op1)) + if (ZI->getSrcTy() == Type::getInt1Ty(*Context)) + return SelectInst::Create(ZI->getOperand(0), SubOne(C), C); + } + + if (BinaryOperator *Op1I = dyn_cast(Op1)) { + if (Op1I->getOpcode() == Instruction::Add) { + if (Op1I->getOperand(0) == Op0) // X-(X+Y) == -Y + return BinaryOperator::CreateNeg(Op1I->getOperand(1), + I.getName()); + else if (Op1I->getOperand(1) == Op0) // X-(Y+X) == -Y + return BinaryOperator::CreateNeg(Op1I->getOperand(0), + I.getName()); + else if (ConstantInt *CI1 = dyn_cast(I.getOperand(0))) { + if (ConstantInt *CI2 = dyn_cast(Op1I->getOperand(1))) + // C1-(X+C2) --> (C1-C2)-X + return BinaryOperator::CreateSub( + ConstantExpr::getSub(CI1, CI2), Op1I->getOperand(0)); + } + } + + if (Op1I->hasOneUse()) { + // Replace (x - (y - z)) with (x + (z - y)) if the (y - z) subexpression + // is not used by anyone else... + // + if (Op1I->getOpcode() == Instruction::Sub) { + // Swap the two operands of the subexpr... + Value *IIOp0 = Op1I->getOperand(0), *IIOp1 = Op1I->getOperand(1); + Op1I->setOperand(0, IIOp1); + Op1I->setOperand(1, IIOp0); + + // Create the new top level add instruction... + return BinaryOperator::CreateAdd(Op0, Op1); + } + + // Replace (A - (A & B)) with (A & ~B) if this is the only use of (A&B)... + // + if (Op1I->getOpcode() == Instruction::And && + (Op1I->getOperand(0) == Op0 || Op1I->getOperand(1) == Op0)) { + Value *OtherOp = Op1I->getOperand(Op1I->getOperand(0) == Op0); + + Value *NewNot = Builder->CreateNot(OtherOp, "B.not"); + return BinaryOperator::CreateAnd(Op0, NewNot); + } + + // 0 - (X sdiv C) -> (X sdiv -C) + if (Op1I->getOpcode() == Instruction::SDiv) + if (ConstantInt *CSI = dyn_cast(Op0)) + if (CSI->isZero()) + if (Constant *DivRHS = dyn_cast(Op1I->getOperand(1))) + return BinaryOperator::CreateSDiv(Op1I->getOperand(0), + ConstantExpr::getNeg(DivRHS)); + + // X - X*C --> X * (1-C) + ConstantInt *C2 = 0; + if (dyn_castFoldableMul(Op1I, C2) == Op0) { + Constant *CP1 = + ConstantExpr::getSub(ConstantInt::get(I.getType(), 1), + C2); + return BinaryOperator::CreateMul(Op0, CP1); + } + } + } + + if (BinaryOperator *Op0I = dyn_cast(Op0)) { + if (Op0I->getOpcode() == Instruction::Add) { + if (Op0I->getOperand(0) == Op1) // (Y+X)-Y == X + return ReplaceInstUsesWith(I, Op0I->getOperand(1)); + else if (Op0I->getOperand(1) == Op1) // (X+Y)-Y == X + return ReplaceInstUsesWith(I, Op0I->getOperand(0)); + } else if (Op0I->getOpcode() == Instruction::Sub) { + if (Op0I->getOperand(0) == Op1) // (X-Y)-X == -Y + return BinaryOperator::CreateNeg(Op0I->getOperand(1), + I.getName()); + } + } + + ConstantInt *C1; + if (Value *X = dyn_castFoldableMul(Op0, C1)) { + if (X == Op1) // X*C - X --> X * (C-1) + return BinaryOperator::CreateMul(Op1, SubOne(C1)); + + ConstantInt *C2; // X*C1 - X*C2 -> X * (C1-C2) + if (X == dyn_castFoldableMul(Op1, C2)) + return BinaryOperator::CreateMul(X, ConstantExpr::getSub(C1, C2)); + } + + // Optimize pointer differences into the same array into a size. Consider: + // &A[10] - &A[0]: we should compile this to "10". + if (TD) { + if (PtrToIntInst *LHS = dyn_cast(Op0)) + if (PtrToIntInst *RHS = dyn_cast(Op1)) + if (Value *Res = OptimizePointerDifference(LHS->getOperand(0), + RHS->getOperand(0), + I.getType())) + return ReplaceInstUsesWith(I, Res); + + // trunc(p)-trunc(q) -> trunc(p-q) + if (TruncInst *LHST = dyn_cast(Op0)) + if (TruncInst *RHST = dyn_cast(Op1)) + if (PtrToIntInst *LHS = dyn_cast(LHST->getOperand(0))) + if (PtrToIntInst *RHS = dyn_cast(RHST->getOperand(0))) + if (Value *Res = OptimizePointerDifference(LHS->getOperand(0), + RHS->getOperand(0), + I.getType())) + return ReplaceInstUsesWith(I, Res); + } + + return 0; +} + +Instruction *InstCombiner::visitFSub(BinaryOperator &I) { + Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1); + + // If this is a 'B = x-(-A)', change to B = x+A... + if (Value *V = dyn_castFNegVal(Op1)) + return BinaryOperator::CreateFAdd(Op0, V); + + if (BinaryOperator *Op1I = dyn_cast(Op1)) { + if (Op1I->getOpcode() == Instruction::FAdd) { + if (Op1I->getOperand(0) == Op0) // X-(X+Y) == -Y + return BinaryOperator::CreateFNeg(Op1I->getOperand(1), + I.getName()); + else if (Op1I->getOperand(1) == Op0) // X-(Y+X) == -Y + return BinaryOperator::CreateFNeg(Op1I->getOperand(0), + I.getName()); + } + } + + return 0; +} + +/// isSignBitCheck - Given an exploded icmp instruction, return true if the +/// comparison only checks the sign bit. If it only checks the sign bit, set +/// TrueIfSigned if the result of the comparison is true when the input value is +/// signed. +static bool isSignBitCheck(ICmpInst::Predicate pred, ConstantInt *RHS, + bool &TrueIfSigned) { + switch (pred) { + case ICmpInst::ICMP_SLT: // True if LHS s< 0 + TrueIfSigned = true; + return RHS->isZero(); + case ICmpInst::ICMP_SLE: // True if LHS s<= RHS and RHS == -1 + TrueIfSigned = true; + return RHS->isAllOnesValue(); + case ICmpInst::ICMP_SGT: // True if LHS s> -1 + TrueIfSigned = false; + return RHS->isAllOnesValue(); + case ICmpInst::ICMP_UGT: + // True if LHS u> RHS and RHS == high-bit-mask - 1 + TrueIfSigned = true; + return RHS->getValue() == + APInt::getSignedMaxValue(RHS->getType()->getPrimitiveSizeInBits()); + case ICmpInst::ICMP_UGE: + // True if LHS u>= RHS and RHS == high-bit-mask (2^7, 2^15, 2^31, etc) + TrueIfSigned = true; + return RHS->getValue().isSignBit(); + default: + return false; + } +} + +Instruction *InstCombiner::visitMul(BinaryOperator &I) { + bool Changed = SimplifyCommutative(I); + Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1); + + if (isa(Op1)) // undef * X -> 0 + return ReplaceInstUsesWith(I, Constant::getNullValue(I.getType())); + + // Simplify mul instructions with a constant RHS. + if (Constant *Op1C = dyn_cast(Op1)) { + if (ConstantInt *CI = dyn_cast(Op1C)) { + + // ((X << C1)*C2) == (X * (C2 << C1)) + if (BinaryOperator *SI = dyn_cast(Op0)) + if (SI->getOpcode() == Instruction::Shl) + if (Constant *ShOp = dyn_cast(SI->getOperand(1))) + return BinaryOperator::CreateMul(SI->getOperand(0), + ConstantExpr::getShl(CI, ShOp)); + + if (CI->isZero()) + return ReplaceInstUsesWith(I, Op1C); // X * 0 == 0 + if (CI->equalsInt(1)) // X * 1 == X + return ReplaceInstUsesWith(I, Op0); + if (CI->isAllOnesValue()) // X * -1 == 0 - X + return BinaryOperator::CreateNeg(Op0, I.getName()); + + const APInt& Val = cast(CI)->getValue(); + if (Val.isPowerOf2()) { // Replace X*(2^C) with X << C + return BinaryOperator::CreateShl(Op0, + ConstantInt::get(Op0->getType(), Val.logBase2())); + } + } else if (isa(Op1C->getType())) { + if (Op1C->isNullValue()) + return ReplaceInstUsesWith(I, Op1C); + + if (ConstantVector *Op1V = dyn_cast(Op1C)) { + if (Op1V->isAllOnesValue()) // X * -1 == 0 - X + return BinaryOperator::CreateNeg(Op0, I.getName()); + + // As above, vector X*splat(1.0) -> X in all defined cases. + if (Constant *Splat = Op1V->getSplatValue()) { + if (ConstantInt *CI = dyn_cast(Splat)) + if (CI->equalsInt(1)) + return ReplaceInstUsesWith(I, Op0); + } + } + } + + if (BinaryOperator *Op0I = dyn_cast(Op0)) + if (Op0I->getOpcode() == Instruction::Add && Op0I->hasOneUse() && + isa(Op0I->getOperand(1)) && isa(Op1C)) { + // Canonicalize (X+C1)*C2 -> X*C2+C1*C2. + Value *Add = Builder->CreateMul(Op0I->getOperand(0), Op1C, "tmp"); + Value *C1C2 = Builder->CreateMul(Op1C, Op0I->getOperand(1)); + return BinaryOperator::CreateAdd(Add, C1C2); + + } + + // Try to fold constant mul into select arguments. + if (SelectInst *SI = dyn_cast(Op0)) + if (Instruction *R = FoldOpIntoSelect(I, SI, this)) + return R; + + if (isa(Op0)) + if (Instruction *NV = FoldOpIntoPhi(I)) + return NV; + } + + if (Value *Op0v = dyn_castNegVal(Op0)) // -X * -Y = X*Y + if (Value *Op1v = dyn_castNegVal(Op1)) + return BinaryOperator::CreateMul(Op0v, Op1v); + + // (X / Y) * Y = X - (X % Y) + // (X / Y) * -Y = (X % Y) - X + { + Value *Op1C = Op1; + BinaryOperator *BO = dyn_cast(Op0); + if (!BO || + (BO->getOpcode() != Instruction::UDiv && + BO->getOpcode() != Instruction::SDiv)) { + Op1C = Op0; + BO = dyn_cast(Op1); + } + Value *Neg = dyn_castNegVal(Op1C); + if (BO && BO->hasOneUse() && + (BO->getOperand(1) == Op1C || BO->getOperand(1) == Neg) && + (BO->getOpcode() == Instruction::UDiv || + BO->getOpcode() == Instruction::SDiv)) { + Value *Op0BO = BO->getOperand(0), *Op1BO = BO->getOperand(1); + + // If the division is exact, X % Y is zero. + if (SDivOperator *SDiv = dyn_cast(BO)) + if (SDiv->isExact()) { + if (Op1BO == Op1C) + return ReplaceInstUsesWith(I, Op0BO); + return BinaryOperator::CreateNeg(Op0BO); + } + + Value *Rem; + if (BO->getOpcode() == Instruction::UDiv) + Rem = Builder->CreateURem(Op0BO, Op1BO); + else + Rem = Builder->CreateSRem(Op0BO, Op1BO); + Rem->takeName(BO); + + if (Op1BO == Op1C) + return BinaryOperator::CreateSub(Op0BO, Rem); + return BinaryOperator::CreateSub(Rem, Op0BO); + } + } + + /// i1 mul -> i1 and. + if (I.getType() == Type::getInt1Ty(*Context)) + return BinaryOperator::CreateAnd(Op0, Op1); + + // X*(1 << Y) --> X << Y + // (1 << Y)*X --> X << Y + { + Value *Y; + if (match(Op0, m_Shl(m_One(), m_Value(Y)))) + return BinaryOperator::CreateShl(Op1, Y); + if (match(Op1, m_Shl(m_One(), m_Value(Y)))) + return BinaryOperator::CreateShl(Op0, Y); + } + + // If one of the operands of the multiply is a cast from a boolean value, then + // we know the bool is either zero or one, so this is a 'masking' multiply. + // X * Y (where Y is 0 or 1) -> X & (0-Y) + if (!isa(I.getType())) { + // -2 is "-1 << 1" so it is all bits set except the low one. + APInt Negative2(I.getType()->getPrimitiveSizeInBits(), (uint64_t)-2, true); + + Value *BoolCast = 0, *OtherOp = 0; + if (MaskedValueIsZero(Op0, Negative2)) + BoolCast = Op0, OtherOp = Op1; + else if (MaskedValueIsZero(Op1, Negative2)) + BoolCast = Op1, OtherOp = Op0; + + if (BoolCast) { + Value *V = Builder->CreateSub(Constant::getNullValue(I.getType()), + BoolCast, "tmp"); + return BinaryOperator::CreateAnd(V, OtherOp); + } + } + + return Changed ? &I : 0; +} + +Instruction *InstCombiner::visitFMul(BinaryOperator &I) { + bool Changed = SimplifyCommutative(I); + Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1); + + // Simplify mul instructions with a constant RHS... + if (Constant *Op1C = dyn_cast(Op1)) { + if (ConstantFP *Op1F = dyn_cast(Op1C)) { + // "In IEEE floating point, x*1 is not equivalent to x for nans. However, + // ANSI says we can drop signals, so we can do this anyway." (from GCC) + if (Op1F->isExactlyValue(1.0)) + return ReplaceInstUsesWith(I, Op0); // Eliminate 'mul double %X, 1.0' + } else if (isa(Op1C->getType())) { + if (ConstantVector *Op1V = dyn_cast(Op1C)) { + // As above, vector X*splat(1.0) -> X in all defined cases. + if (Constant *Splat = Op1V->getSplatValue()) { + if (ConstantFP *F = dyn_cast(Splat)) + if (F->isExactlyValue(1.0)) + return ReplaceInstUsesWith(I, Op0); + } + } + } + + // Try to fold constant mul into select arguments. + if (SelectInst *SI = dyn_cast(Op0)) + if (Instruction *R = FoldOpIntoSelect(I, SI, this)) + return R; + + if (isa(Op0)) + if (Instruction *NV = FoldOpIntoPhi(I)) + return NV; + } + + if (Value *Op0v = dyn_castFNegVal(Op0)) // -X * -Y = X*Y + if (Value *Op1v = dyn_castFNegVal(Op1)) + return BinaryOperator::CreateFMul(Op0v, Op1v); + + return Changed ? &I : 0; +} + +/// SimplifyDivRemOfSelect - Try to fold a divide or remainder of a select +/// instruction. +bool InstCombiner::SimplifyDivRemOfSelect(BinaryOperator &I) { + SelectInst *SI = cast(I.getOperand(1)); + + // div/rem X, (Cond ? 0 : Y) -> div/rem X, Y + int NonNullOperand = -1; + if (Constant *ST = dyn_cast(SI->getOperand(1))) + if (ST->isNullValue()) + NonNullOperand = 2; + // div/rem X, (Cond ? Y : 0) -> div/rem X, Y + if (Constant *ST = dyn_cast(SI->getOperand(2))) + if (ST->isNullValue()) + NonNullOperand = 1; + + if (NonNullOperand == -1) + return false; + + Value *SelectCond = SI->getOperand(0); + + // Change the div/rem to use 'Y' instead of the select. + I.setOperand(1, SI->getOperand(NonNullOperand)); + + // Okay, we know we replace the operand of the div/rem with 'Y' with no + // problem. However, the select, or the condition of the select may have + // multiple uses. Based on our knowledge that the operand must be non-zero, + // propagate the known value for the select into other uses of it, and + // propagate a known value of the condition into its other users. + + // If the select and condition only have a single use, don't bother with this, + // early exit. + if (SI->use_empty() && SelectCond->hasOneUse()) + return true; + + // Scan the current block backward, looking for other uses of SI. + BasicBlock::iterator BBI = &I, BBFront = I.getParent()->begin(); + + while (BBI != BBFront) { + --BBI; + // If we found a call to a function, we can't assume it will return, so + // information from below it cannot be propagated above it. + if (isa(BBI) && !isa(BBI)) + break; + + // Replace uses of the select or its condition with the known values. + for (Instruction::op_iterator I = BBI->op_begin(), E = BBI->op_end(); + I != E; ++I) { + if (*I == SI) { + *I = SI->getOperand(NonNullOperand); + Worklist.Add(BBI); + } else if (*I == SelectCond) { + *I = NonNullOperand == 1 ? ConstantInt::getTrue(*Context) : + ConstantInt::getFalse(*Context); + Worklist.Add(BBI); + } + } + + // If we past the instruction, quit looking for it. + if (&*BBI == SI) + SI = 0; + if (&*BBI == SelectCond) + SelectCond = 0; + + // If we ran out of things to eliminate, break out of the loop. + if (SelectCond == 0 && SI == 0) + break; + + } + return true; +} + + +/// This function implements the transforms on div instructions that work +/// regardless of the kind of div instruction it is (udiv, sdiv, or fdiv). It is +/// used by the visitors to those instructions. +/// @brief Transforms common to all three div instructions +Instruction *InstCombiner::commonDivTransforms(BinaryOperator &I) { + Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1); + + // undef / X -> 0 for integer. + // undef / X -> undef for FP (the undef could be a snan). + if (isa(Op0)) { + if (Op0->getType()->isFPOrFPVector()) + return ReplaceInstUsesWith(I, Op0); + return ReplaceInstUsesWith(I, Constant::getNullValue(I.getType())); + } + + // X / undef -> undef + if (isa(Op1)) + return ReplaceInstUsesWith(I, Op1); + + return 0; +} + +/// This function implements the transforms common to both integer division +/// instructions (udiv and sdiv). It is called by the visitors to those integer +/// division instructions. +/// @brief Common integer divide transforms +Instruction *InstCombiner::commonIDivTransforms(BinaryOperator &I) { + Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1); + + // (sdiv X, X) --> 1 (udiv X, X) --> 1 + if (Op0 == Op1) { + if (const VectorType *Ty = dyn_cast(I.getType())) { + Constant *CI = ConstantInt::get(Ty->getElementType(), 1); + std::vector Elts(Ty->getNumElements(), CI); + return ReplaceInstUsesWith(I, ConstantVector::get(Elts)); + } + + Constant *CI = ConstantInt::get(I.getType(), 1); + return ReplaceInstUsesWith(I, CI); + } + + if (Instruction *Common = commonDivTransforms(I)) + return Common; + + // Handle cases involving: [su]div X, (select Cond, Y, Z) + // This does not apply for fdiv. + if (isa(Op1) && SimplifyDivRemOfSelect(I)) + return &I; + + if (ConstantInt *RHS = dyn_cast(Op1)) { + // div X, 1 == X + if (RHS->equalsInt(1)) + return ReplaceInstUsesWith(I, Op0); + + // (X / C1) / C2 -> X / (C1*C2) + if (Instruction *LHS = dyn_cast(Op0)) + if (Instruction::BinaryOps(LHS->getOpcode()) == I.getOpcode()) + if (ConstantInt *LHSRHS = dyn_cast(LHS->getOperand(1))) { + if (MultiplyOverflows(RHS, LHSRHS, + I.getOpcode()==Instruction::SDiv)) + return ReplaceInstUsesWith(I, Constant::getNullValue(I.getType())); + else + return BinaryOperator::Create(I.getOpcode(), LHS->getOperand(0), + ConstantExpr::getMul(RHS, LHSRHS)); + } + + if (!RHS->isZero()) { // avoid X udiv 0 + if (SelectInst *SI = dyn_cast(Op0)) + if (Instruction *R = FoldOpIntoSelect(I, SI, this)) + return R; + if (isa(Op0)) + if (Instruction *NV = FoldOpIntoPhi(I)) + return NV; + } + } + + // 0 / X == 0, we don't need to preserve faults! + if (ConstantInt *LHS = dyn_cast(Op0)) + if (LHS->equalsInt(0)) + return ReplaceInstUsesWith(I, Constant::getNullValue(I.getType())); + + // It can't be division by zero, hence it must be division by one. + if (I.getType() == Type::getInt1Ty(*Context)) + return ReplaceInstUsesWith(I, Op0); + + if (ConstantVector *Op1V = dyn_cast(Op1)) { + if (ConstantInt *X = cast_or_null(Op1V->getSplatValue())) + // div X, 1 == X + if (X->isOne()) + return ReplaceInstUsesWith(I, Op0); + } + + return 0; +} + +Instruction *InstCombiner::visitUDiv(BinaryOperator &I) { + Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1); + + // Handle the integer div common cases + if (Instruction *Common = commonIDivTransforms(I)) + return Common; + + if (ConstantInt *C = dyn_cast(Op1)) { + // X udiv C^2 -> X >> C + // Check to see if this is an unsigned division with an exact power of 2, + // if so, convert to a right shift. + if (C->getValue().isPowerOf2()) // 0 not included in isPowerOf2 + return BinaryOperator::CreateLShr(Op0, + ConstantInt::get(Op0->getType(), C->getValue().logBase2())); + + // X udiv C, where C >= signbit + if (C->getValue().isNegative()) { + Value *IC = Builder->CreateICmpULT( Op0, C); + return SelectInst::Create(IC, Constant::getNullValue(I.getType()), + ConstantInt::get(I.getType(), 1)); + } + } + + // X udiv (C1 << N), where C1 is "1< X >> (N+C2) + if (BinaryOperator *RHSI = dyn_cast(I.getOperand(1))) { + if (RHSI->getOpcode() == Instruction::Shl && + isa(RHSI->getOperand(0))) { + const APInt& C1 = cast(RHSI->getOperand(0))->getValue(); + if (C1.isPowerOf2()) { + Value *N = RHSI->getOperand(1); + const Type *NTy = N->getType(); + if (uint32_t C2 = C1.logBase2()) + N = Builder->CreateAdd(N, ConstantInt::get(NTy, C2), "tmp"); + return BinaryOperator::CreateLShr(Op0, N); + } + } + } + + // udiv X, (Select Cond, C1, C2) --> Select Cond, (shr X, C1), (shr X, C2) + // where C1&C2 are powers of two. + if (SelectInst *SI = dyn_cast(Op1)) + if (ConstantInt *STO = dyn_cast(SI->getOperand(1))) + if (ConstantInt *SFO = dyn_cast(SI->getOperand(2))) { + const APInt &TVA = STO->getValue(), &FVA = SFO->getValue(); + if (TVA.isPowerOf2() && FVA.isPowerOf2()) { + // Compute the shift amounts + uint32_t TSA = TVA.logBase2(), FSA = FVA.logBase2(); + // Construct the "on true" case of the select + Constant *TC = ConstantInt::get(Op0->getType(), TSA); + Value *TSI = Builder->CreateLShr(Op0, TC, SI->getName()+".t"); + + // Construct the "on false" case of the select + Constant *FC = ConstantInt::get(Op0->getType(), FSA); + Value *FSI = Builder->CreateLShr(Op0, FC, SI->getName()+".f"); + + // construct the select instruction and return it. + return SelectInst::Create(SI->getOperand(0), TSI, FSI, SI->getName()); + } + } + return 0; +} + +Instruction *InstCombiner::visitSDiv(BinaryOperator &I) { + Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1); + + // Handle the integer div common cases + if (Instruction *Common = commonIDivTransforms(I)) + return Common; + + if (ConstantInt *RHS = dyn_cast(Op1)) { + // sdiv X, -1 == -X + if (RHS->isAllOnesValue()) + return BinaryOperator::CreateNeg(Op0); + + // sdiv X, C --> ashr X, log2(C) + if (cast(&I)->isExact() && + RHS->getValue().isNonNegative() && + RHS->getValue().isPowerOf2()) { + Value *ShAmt = llvm::ConstantInt::get(RHS->getType(), + RHS->getValue().exactLogBase2()); + return BinaryOperator::CreateAShr(Op0, ShAmt, I.getName()); + } + + // -X/C --> X/-C provided the negation doesn't overflow. + if (SubOperator *Sub = dyn_cast(Op0)) + if (isa(Sub->getOperand(0)) && + cast(Sub->getOperand(0))->isNullValue() && + Sub->hasNoSignedWrap()) + return BinaryOperator::CreateSDiv(Sub->getOperand(1), + ConstantExpr::getNeg(RHS)); + } + + // If the sign bits of both operands are zero (i.e. we can prove they are + // unsigned inputs), turn this into a udiv. + if (I.getType()->isInteger()) { + APInt Mask(APInt::getSignBit(I.getType()->getPrimitiveSizeInBits())); + if (MaskedValueIsZero(Op0, Mask)) { + if (MaskedValueIsZero(Op1, Mask)) { + // X sdiv Y -> X udiv Y, iff X and Y don't have sign bit set + return BinaryOperator::CreateUDiv(Op0, Op1, I.getName()); + } + ConstantInt *ShiftedInt; + if (match(Op1, m_Shl(m_ConstantInt(ShiftedInt), m_Value())) && + ShiftedInt->getValue().isPowerOf2()) { + // X sdiv (1 << Y) -> X udiv (1 << Y) ( -> X u>> Y) + // Safe because the only negative value (1 << Y) can take on is + // INT_MIN, and X sdiv INT_MIN == X udiv INT_MIN == 0 if X doesn't have + // the sign bit set. + return BinaryOperator::CreateUDiv(Op0, Op1, I.getName()); + } + } + } + + return 0; +} + +Instruction *InstCombiner::visitFDiv(BinaryOperator &I) { + return commonDivTransforms(I); +} + +/// This function implements the transforms on rem instructions that work +/// regardless of the kind of rem instruction it is (urem, srem, or frem). It +/// is used by the visitors to those instructions. +/// @brief Transforms common to all three rem instructions +Instruction *InstCombiner::commonRemTransforms(BinaryOperator &I) { + Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1); + + if (isa(Op0)) { // undef % X -> 0 + if (I.getType()->isFPOrFPVector()) + return ReplaceInstUsesWith(I, Op0); // X % undef -> undef (could be SNaN) + return ReplaceInstUsesWith(I, Constant::getNullValue(I.getType())); + } + if (isa(Op1)) + return ReplaceInstUsesWith(I, Op1); // X % undef -> undef + + // Handle cases involving: rem X, (select Cond, Y, Z) + if (isa(Op1) && SimplifyDivRemOfSelect(I)) + return &I; + + return 0; +} + +/// This function implements the transforms common to both integer remainder +/// instructions (urem and srem). It is called by the visitors to those integer +/// remainder instructions. +/// @brief Common integer remainder transforms +Instruction *InstCombiner::commonIRemTransforms(BinaryOperator &I) { + Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1); + + if (Instruction *common = commonRemTransforms(I)) + return common; + + // 0 % X == 0 for integer, we don't need to preserve faults! + if (Constant *LHS = dyn_cast(Op0)) + if (LHS->isNullValue()) + return ReplaceInstUsesWith(I, Constant::getNullValue(I.getType())); + + if (ConstantInt *RHS = dyn_cast(Op1)) { + // X % 0 == undef, we don't need to preserve faults! + if (RHS->equalsInt(0)) + return ReplaceInstUsesWith(I, UndefValue::get(I.getType())); + + if (RHS->equalsInt(1)) // X % 1 == 0 + return ReplaceInstUsesWith(I, Constant::getNullValue(I.getType())); + + if (Instruction *Op0I = dyn_cast(Op0)) { + if (SelectInst *SI = dyn_cast(Op0I)) { + if (Instruction *R = FoldOpIntoSelect(I, SI, this)) + return R; + } else if (isa(Op0I)) { + if (Instruction *NV = FoldOpIntoPhi(I)) + return NV; + } + + // See if we can fold away this rem instruction. + if (SimplifyDemandedInstructionBits(I)) + return &I; + } + } + + return 0; +} + +Instruction *InstCombiner::visitURem(BinaryOperator &I) { + Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1); + + if (Instruction *common = commonIRemTransforms(I)) + return common; + + if (ConstantInt *RHS = dyn_cast(Op1)) { + // X urem C^2 -> X and C + // Check to see if this is an unsigned remainder with an exact power of 2, + // if so, convert to a bitwise and. + if (ConstantInt *C = dyn_cast(RHS)) + if (C->getValue().isPowerOf2()) + return BinaryOperator::CreateAnd(Op0, SubOne(C)); + } + + if (Instruction *RHSI = dyn_cast(I.getOperand(1))) { + // Turn A % (C << N), where C is 2^k, into A & ((C << N)-1) + if (RHSI->getOpcode() == Instruction::Shl && + isa(RHSI->getOperand(0))) { + if (cast(RHSI->getOperand(0))->getValue().isPowerOf2()) { + Constant *N1 = Constant::getAllOnesValue(I.getType()); + Value *Add = Builder->CreateAdd(RHSI, N1, "tmp"); + return BinaryOperator::CreateAnd(Op0, Add); + } + } + } + + // urem X, (select Cond, 2^C1, 2^C2) --> select Cond, (and X, C1), (and X, C2) + // where C1&C2 are powers of two. + if (SelectInst *SI = dyn_cast(Op1)) { + if (ConstantInt *STO = dyn_cast(SI->getOperand(1))) + if (ConstantInt *SFO = dyn_cast(SI->getOperand(2))) { + // STO == 0 and SFO == 0 handled above. + if ((STO->getValue().isPowerOf2()) && + (SFO->getValue().isPowerOf2())) { + Value *TrueAnd = Builder->CreateAnd(Op0, SubOne(STO), + SI->getName()+".t"); + Value *FalseAnd = Builder->CreateAnd(Op0, SubOne(SFO), + SI->getName()+".f"); + return SelectInst::Create(SI->getOperand(0), TrueAnd, FalseAnd); + } + } + } + + return 0; +} + +Instruction *InstCombiner::visitSRem(BinaryOperator &I) { + Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1); + + // Handle the integer rem common cases + if (Instruction *Common = commonIRemTransforms(I)) + return Common; + + if (Value *RHSNeg = dyn_castNegVal(Op1)) + if (!isa(RHSNeg) || + (isa(RHSNeg) && + cast(RHSNeg)->getValue().isStrictlyPositive())) { + // X % -Y -> X % Y + Worklist.AddValue(I.getOperand(1)); + I.setOperand(1, RHSNeg); + return &I; + } + + // If the sign bits of both operands are zero (i.e. we can prove they are + // unsigned inputs), turn this into a urem. + if (I.getType()->isInteger()) { + APInt Mask(APInt::getSignBit(I.getType()->getPrimitiveSizeInBits())); + if (MaskedValueIsZero(Op1, Mask) && MaskedValueIsZero(Op0, Mask)) { + // X srem Y -> X urem Y, iff X and Y don't have sign bit set + return BinaryOperator::CreateURem(Op0, Op1, I.getName()); + } + } + + // If it's a constant vector, flip any negative values positive. + if (ConstantVector *RHSV = dyn_cast(Op1)) { + unsigned VWidth = RHSV->getNumOperands(); + + bool hasNegative = false; + for (unsigned i = 0; !hasNegative && i != VWidth; ++i) + if (ConstantInt *RHS = dyn_cast(RHSV->getOperand(i))) + if (RHS->getValue().isNegative()) + hasNegative = true; + + if (hasNegative) { + std::vector Elts(VWidth); + for (unsigned i = 0; i != VWidth; ++i) { + if (ConstantInt *RHS = dyn_cast(RHSV->getOperand(i))) { + if (RHS->getValue().isNegative()) + Elts[i] = cast(ConstantExpr::getNeg(RHS)); + else + Elts[i] = RHS; + } + } + + Constant *NewRHSV = ConstantVector::get(Elts); + if (NewRHSV != RHSV) { + Worklist.AddValue(I.getOperand(1)); + I.setOperand(1, NewRHSV); + return &I; + } + } + } + + return 0; +} + +Instruction *InstCombiner::visitFRem(BinaryOperator &I) { + return commonRemTransforms(I); +} + +// isOneBitSet - Return true if there is exactly one bit set in the specified +// constant. +static bool isOneBitSet(const ConstantInt *CI) { + return CI->getValue().isPowerOf2(); +} + +// isHighOnes - Return true if the constant is of the form 1+0+. +// This is the same as lowones(~X). +static bool isHighOnes(const ConstantInt *CI) { + return (~CI->getValue() + 1).isPowerOf2(); +} + +/// getICmpCode - Encode a icmp predicate into a three bit mask. These bits +/// are carefully arranged to allow folding of expressions such as: +/// +/// (A < B) | (A > B) --> (A != B) +/// +/// Note that this is only valid if the first and second predicates have the +/// same sign. Is illegal to do: (A u< B) | (A s> B) +/// +/// Three bits are used to represent the condition, as follows: +/// 0 A > B +/// 1 A == B +/// 2 A < B +/// +/// <=> Value Definition +/// 000 0 Always false +/// 001 1 A > B +/// 010 2 A == B +/// 011 3 A >= B +/// 100 4 A < B +/// 101 5 A != B +/// 110 6 A <= B +/// 111 7 Always true +/// +static unsigned getICmpCode(const ICmpInst *ICI) { + switch (ICI->getPredicate()) { + // False -> 0 + case ICmpInst::ICMP_UGT: return 1; // 001 + case ICmpInst::ICMP_SGT: return 1; // 001 + case ICmpInst::ICMP_EQ: return 2; // 010 + case ICmpInst::ICMP_UGE: return 3; // 011 + case ICmpInst::ICMP_SGE: return 3; // 011 + case ICmpInst::ICMP_ULT: return 4; // 100 + case ICmpInst::ICMP_SLT: return 4; // 100 + case ICmpInst::ICMP_NE: return 5; // 101 + case ICmpInst::ICMP_ULE: return 6; // 110 + case ICmpInst::ICMP_SLE: return 6; // 110 + // True -> 7 + default: + llvm_unreachable("Invalid ICmp predicate!"); + return 0; + } +} + +/// getFCmpCode - Similar to getICmpCode but for FCmpInst. This encodes a fcmp +/// predicate into a three bit mask. It also returns whether it is an ordered +/// predicate by reference. +static unsigned getFCmpCode(FCmpInst::Predicate CC, bool &isOrdered) { + isOrdered = false; + switch (CC) { + case FCmpInst::FCMP_ORD: isOrdered = true; return 0; // 000 + case FCmpInst::FCMP_UNO: return 0; // 000 + case FCmpInst::FCMP_OGT: isOrdered = true; return 1; // 001 + case FCmpInst::FCMP_UGT: return 1; // 001 + case FCmpInst::FCMP_OEQ: isOrdered = true; return 2; // 010 + case FCmpInst::FCMP_UEQ: return 2; // 010 + case FCmpInst::FCMP_OGE: isOrdered = true; return 3; // 011 + case FCmpInst::FCMP_UGE: return 3; // 011 + case FCmpInst::FCMP_OLT: isOrdered = true; return 4; // 100 + case FCmpInst::FCMP_ULT: return 4; // 100 + case FCmpInst::FCMP_ONE: isOrdered = true; return 5; // 101 + case FCmpInst::FCMP_UNE: return 5; // 101 + case FCmpInst::FCMP_OLE: isOrdered = true; return 6; // 110 + case FCmpInst::FCMP_ULE: return 6; // 110 + // True -> 7 + default: + // Not expecting FCMP_FALSE and FCMP_TRUE; + llvm_unreachable("Unexpected FCmp predicate!"); + return 0; + } +} + +/// getICmpValue - This is the complement of getICmpCode, which turns an +/// opcode and two operands into either a constant true or false, or a brand +/// new ICmp instruction. The sign is passed in to determine which kind +/// of predicate to use in the new icmp instruction. +static Value *getICmpValue(bool sign, unsigned code, Value *LHS, Value *RHS, + LLVMContext *Context) { + switch (code) { + default: llvm_unreachable("Illegal ICmp code!"); + case 0: return ConstantInt::getFalse(*Context); + case 1: + if (sign) + return new ICmpInst(ICmpInst::ICMP_SGT, LHS, RHS); + else + return new ICmpInst(ICmpInst::ICMP_UGT, LHS, RHS); + case 2: return new ICmpInst(ICmpInst::ICMP_EQ, LHS, RHS); + case 3: + if (sign) + return new ICmpInst(ICmpInst::ICMP_SGE, LHS, RHS); + else + return new ICmpInst(ICmpInst::ICMP_UGE, LHS, RHS); + case 4: + if (sign) + return new ICmpInst(ICmpInst::ICMP_SLT, LHS, RHS); + else + return new ICmpInst(ICmpInst::ICMP_ULT, LHS, RHS); + case 5: return new ICmpInst(ICmpInst::ICMP_NE, LHS, RHS); + case 6: + if (sign) + return new ICmpInst(ICmpInst::ICMP_SLE, LHS, RHS); + else + return new ICmpInst(ICmpInst::ICMP_ULE, LHS, RHS); + case 7: return ConstantInt::getTrue(*Context); + } +} + +/// getFCmpValue - This is the complement of getFCmpCode, which turns an +/// opcode and two operands into either a FCmp instruction. isordered is passed +/// in to determine which kind of predicate to use in the new fcmp instruction. +static Value *getFCmpValue(bool isordered, unsigned code, + Value *LHS, Value *RHS, LLVMContext *Context) { + switch (code) { + default: llvm_unreachable("Illegal FCmp code!"); + case 0: + if (isordered) + return new FCmpInst(FCmpInst::FCMP_ORD, LHS, RHS); + else + return new FCmpInst(FCmpInst::FCMP_UNO, LHS, RHS); + case 1: + if (isordered) + return new FCmpInst(FCmpInst::FCMP_OGT, LHS, RHS); + else + return new FCmpInst(FCmpInst::FCMP_UGT, LHS, RHS); + case 2: + if (isordered) + return new FCmpInst(FCmpInst::FCMP_OEQ, LHS, RHS); + else + return new FCmpInst(FCmpInst::FCMP_UEQ, LHS, RHS); + case 3: + if (isordered) + return new FCmpInst(FCmpInst::FCMP_OGE, LHS, RHS); + else + return new FCmpInst(FCmpInst::FCMP_UGE, LHS, RHS); + case 4: + if (isordered) + return new FCmpInst(FCmpInst::FCMP_OLT, LHS, RHS); + else + return new FCmpInst(FCmpInst::FCMP_ULT, LHS, RHS); + case 5: + if (isordered) + return new FCmpInst(FCmpInst::FCMP_ONE, LHS, RHS); + else + return new FCmpInst(FCmpInst::FCMP_UNE, LHS, RHS); + case 6: + if (isordered) + return new FCmpInst(FCmpInst::FCMP_OLE, LHS, RHS); + else + return new FCmpInst(FCmpInst::FCMP_ULE, LHS, RHS); + case 7: return ConstantInt::getTrue(*Context); + } +} + +/// PredicatesFoldable - Return true if both predicates match sign or if at +/// least one of them is an equality comparison (which is signless). +static bool PredicatesFoldable(ICmpInst::Predicate p1, ICmpInst::Predicate p2) { + return (CmpInst::isSigned(p1) == CmpInst::isSigned(p2)) || + (CmpInst::isSigned(p1) && ICmpInst::isEquality(p2)) || + (CmpInst::isSigned(p2) && ICmpInst::isEquality(p1)); +} + +namespace { +// FoldICmpLogical - Implements (icmp1 A, B) & (icmp2 A, B) --> (icmp3 A, B) +struct FoldICmpLogical { + InstCombiner &IC; + Value *LHS, *RHS; + ICmpInst::Predicate pred; + FoldICmpLogical(InstCombiner &ic, ICmpInst *ICI) + : IC(ic), LHS(ICI->getOperand(0)), RHS(ICI->getOperand(1)), + pred(ICI->getPredicate()) {} + bool shouldApply(Value *V) const { + if (ICmpInst *ICI = dyn_cast(V)) + if (PredicatesFoldable(pred, ICI->getPredicate())) + return ((ICI->getOperand(0) == LHS && ICI->getOperand(1) == RHS) || + (ICI->getOperand(0) == RHS && ICI->getOperand(1) == LHS)); + return false; + } + Instruction *apply(Instruction &Log) const { + ICmpInst *ICI = cast(Log.getOperand(0)); + if (ICI->getOperand(0) != LHS) { + assert(ICI->getOperand(1) == LHS); + ICI->swapOperands(); // Swap the LHS and RHS of the ICmp + } + + ICmpInst *RHSICI = cast(Log.getOperand(1)); + unsigned LHSCode = getICmpCode(ICI); + unsigned RHSCode = getICmpCode(RHSICI); + unsigned Code; + switch (Log.getOpcode()) { + case Instruction::And: Code = LHSCode & RHSCode; break; + case Instruction::Or: Code = LHSCode | RHSCode; break; + case Instruction::Xor: Code = LHSCode ^ RHSCode; break; + default: llvm_unreachable("Illegal logical opcode!"); return 0; + } + + bool isSigned = RHSICI->isSigned() || ICI->isSigned(); + Value *RV = getICmpValue(isSigned, Code, LHS, RHS, IC.getContext()); + if (Instruction *I = dyn_cast(RV)) + return I; + // Otherwise, it's a constant boolean value... + return IC.ReplaceInstUsesWith(Log, RV); + } +}; +} // end anonymous namespace + +// OptAndOp - This handles expressions of the form ((val OP C1) & C2). Where +// the Op parameter is 'OP', OpRHS is 'C1', and AndRHS is 'C2'. Op is +// guaranteed to be a binary operator. +Instruction *InstCombiner::OptAndOp(Instruction *Op, + ConstantInt *OpRHS, + ConstantInt *AndRHS, + BinaryOperator &TheAnd) { + Value *X = Op->getOperand(0); + Constant *Together = 0; + if (!Op->isShift()) + Together = ConstantExpr::getAnd(AndRHS, OpRHS); + + switch (Op->getOpcode()) { + case Instruction::Xor: + if (Op->hasOneUse()) { + // (X ^ C1) & C2 --> (X & C2) ^ (C1&C2) + Value *And = Builder->CreateAnd(X, AndRHS); + And->takeName(Op); + return BinaryOperator::CreateXor(And, Together); + } + break; + case Instruction::Or: + if (Together == AndRHS) // (X | C) & C --> C + return ReplaceInstUsesWith(TheAnd, AndRHS); + + if (Op->hasOneUse() && Together != OpRHS) { + // (X | C1) & C2 --> (X | (C1&C2)) & C2 + Value *Or = Builder->CreateOr(X, Together); + Or->takeName(Op); + return BinaryOperator::CreateAnd(Or, AndRHS); + } + break; + case Instruction::Add: + if (Op->hasOneUse()) { + // Adding a one to a single bit bit-field should be turned into an XOR + // of the bit. First thing to check is to see if this AND is with a + // single bit constant. + const APInt& AndRHSV = cast(AndRHS)->getValue(); + + // If there is only one bit set... + if (isOneBitSet(cast(AndRHS))) { + // Ok, at this point, we know that we are masking the result of the + // ADD down to exactly one bit. If the constant we are adding has + // no bits set below this bit, then we can eliminate the ADD. + const APInt& AddRHS = cast(OpRHS)->getValue(); + + // Check to see if any bits below the one bit set in AndRHSV are set. + if ((AddRHS & (AndRHSV-1)) == 0) { + // If not, the only thing that can effect the output of the AND is + // the bit specified by AndRHSV. If that bit is set, the effect of + // the XOR is to toggle the bit. If it is clear, then the ADD has + // no effect. + if ((AddRHS & AndRHSV) == 0) { // Bit is not set, noop + TheAnd.setOperand(0, X); + return &TheAnd; + } else { + // Pull the XOR out of the AND. + Value *NewAnd = Builder->CreateAnd(X, AndRHS); + NewAnd->takeName(Op); + return BinaryOperator::CreateXor(NewAnd, AndRHS); + } + } + } + } + break; + + case Instruction::Shl: { + // We know that the AND will not produce any of the bits shifted in, so if + // the anded constant includes them, clear them now! + // + uint32_t BitWidth = AndRHS->getType()->getBitWidth(); + uint32_t OpRHSVal = OpRHS->getLimitedValue(BitWidth); + APInt ShlMask(APInt::getHighBitsSet(BitWidth, BitWidth-OpRHSVal)); + ConstantInt *CI = ConstantInt::get(*Context, AndRHS->getValue() & ShlMask); + + if (CI->getValue() == ShlMask) { + // Masking out bits that the shift already masks + return ReplaceInstUsesWith(TheAnd, Op); // No need for the and. + } else if (CI != AndRHS) { // Reducing bits set in and. + TheAnd.setOperand(1, CI); + return &TheAnd; + } + break; + } + case Instruction::LShr: + { + // We know that the AND will not produce any of the bits shifted in, so if + // the anded constant includes them, clear them now! This only applies to + // unsigned shifts, because a signed shr may bring in set bits! + // + uint32_t BitWidth = AndRHS->getType()->getBitWidth(); + uint32_t OpRHSVal = OpRHS->getLimitedValue(BitWidth); + APInt ShrMask(APInt::getLowBitsSet(BitWidth, BitWidth - OpRHSVal)); + ConstantInt *CI = ConstantInt::get(*Context, AndRHS->getValue() & ShrMask); + + if (CI->getValue() == ShrMask) { + // Masking out bits that the shift already masks. + return ReplaceInstUsesWith(TheAnd, Op); + } else if (CI != AndRHS) { + TheAnd.setOperand(1, CI); // Reduce bits set in and cst. + return &TheAnd; + } + break; + } + case Instruction::AShr: + // Signed shr. + // See if this is shifting in some sign extension, then masking it out + // with an and. + if (Op->hasOneUse()) { + uint32_t BitWidth = AndRHS->getType()->getBitWidth(); + uint32_t OpRHSVal = OpRHS->getLimitedValue(BitWidth); + APInt ShrMask(APInt::getLowBitsSet(BitWidth, BitWidth - OpRHSVal)); + Constant *C = ConstantInt::get(*Context, AndRHS->getValue() & ShrMask); + if (C == AndRHS) { // Masking out bits shifted in. + // (Val ashr C1) & C2 -> (Val lshr C1) & C2 + // Make the argument unsigned. + Value *ShVal = Op->getOperand(0); + ShVal = Builder->CreateLShr(ShVal, OpRHS, Op->getName()); + return BinaryOperator::CreateAnd(ShVal, AndRHS, TheAnd.getName()); + } + } + break; + } + return 0; +} + + +/// InsertRangeTest - Emit a computation of: (V >= Lo && V < Hi) if Inside is +/// true, otherwise (V < Lo || V >= Hi). In pratice, we emit the more efficient +/// (V-Lo) (ConstantExpr::getICmp((isSigned ? + ICmpInst::ICMP_SLE:ICmpInst::ICMP_ULE), Lo, Hi))->getZExtValue() && + "Lo is not <= Hi in range emission code!"); + + if (Inside) { + if (Lo == Hi) // Trivially false. + return new ICmpInst(ICmpInst::ICMP_NE, V, V); + + // V >= Min && V < Hi --> V < Hi + if (cast(Lo)->isMinValue(isSigned)) { + ICmpInst::Predicate pred = (isSigned ? + ICmpInst::ICMP_SLT : ICmpInst::ICMP_ULT); + return new ICmpInst(pred, V, Hi); + } + + // Emit V-Lo CreateAdd(V, NegLo, V->getName()+".off"); + Constant *UpperBound = ConstantExpr::getAdd(NegLo, Hi); + return new ICmpInst(ICmpInst::ICMP_ULT, Add, UpperBound); + } + + if (Lo == Hi) // Trivially true. + return new ICmpInst(ICmpInst::ICMP_EQ, V, V); + + // V < Min || V >= Hi -> V > Hi-1 + Hi = SubOne(cast(Hi)); + if (cast(Lo)->isMinValue(isSigned)) { + ICmpInst::Predicate pred = (isSigned ? + ICmpInst::ICMP_SGT : ICmpInst::ICMP_UGT); + return new ICmpInst(pred, V, Hi); + } + + // Emit V-Lo >u Hi-1-Lo + // Note that Hi has already had one subtracted from it, above. + ConstantInt *NegLo = cast(ConstantExpr::getNeg(Lo)); + Value *Add = Builder->CreateAdd(V, NegLo, V->getName()+".off"); + Constant *LowerBound = ConstantExpr::getAdd(NegLo, Hi); + return new ICmpInst(ICmpInst::ICMP_UGT, Add, LowerBound); +} + +// isRunOfOnes - Returns true iff Val consists of one contiguous run of 1s with +// any number of 0s on either side. The 1s are allowed to wrap from LSB to +// MSB, so 0x000FFF0, 0x0000FFFF, and 0xFF0000FF are all runs. 0x0F0F0000 is +// not, since all 1s are not contiguous. +static bool isRunOfOnes(ConstantInt *Val, uint32_t &MB, uint32_t &ME) { + const APInt& V = Val->getValue(); + uint32_t BitWidth = Val->getType()->getBitWidth(); + if (!APIntOps::isShiftedMask(BitWidth, V)) return false; + + // look for the first zero bit after the run of ones + MB = BitWidth - ((V - 1) ^ V).countLeadingZeros(); + // look for the first non-zero bit + ME = V.getActiveBits(); + return true; +} + +/// FoldLogicalPlusAnd - This is part of an expression (LHS +/- RHS) & Mask, +/// where isSub determines whether the operator is a sub. If we can fold one of +/// the following xforms: +/// +/// ((A & N) +/- B) & Mask -> (A +/- B) & Mask iff N&Mask == Mask +/// ((A | N) +/- B) & Mask -> (A +/- B) & Mask iff N&Mask == 0 +/// ((A ^ N) +/- B) & Mask -> (A +/- B) & Mask iff N&Mask == 0 +/// +/// return (A +/- B). +/// +Value *InstCombiner::FoldLogicalPlusAnd(Value *LHS, Value *RHS, + ConstantInt *Mask, bool isSub, + Instruction &I) { + Instruction *LHSI = dyn_cast(LHS); + if (!LHSI || LHSI->getNumOperands() != 2 || + !isa(LHSI->getOperand(1))) return 0; + + ConstantInt *N = cast(LHSI->getOperand(1)); + + switch (LHSI->getOpcode()) { + default: return 0; + case Instruction::And: + if (ConstantExpr::getAnd(N, Mask) == Mask) { + // If the AndRHS is a power of two minus one (0+1+), this is simple. + if ((Mask->getValue().countLeadingZeros() + + Mask->getValue().countPopulation()) == + Mask->getValue().getBitWidth()) + break; + + // Otherwise, if Mask is 0+1+0+, and if B is known to have the low 0+ + // part, we don't need any explicit masks to take them out of A. If that + // is all N is, ignore it. + uint32_t MB = 0, ME = 0; + if (isRunOfOnes(Mask, MB, ME)) { // begin/end bit of run, inclusive + uint32_t BitWidth = cast(RHS->getType())->getBitWidth(); + APInt Mask(APInt::getLowBitsSet(BitWidth, MB-1)); + if (MaskedValueIsZero(RHS, Mask)) + break; + } + } + return 0; + case Instruction::Or: + case Instruction::Xor: + // If the AndRHS is a power of two minus one (0+1+), and N&Mask == 0 + if ((Mask->getValue().countLeadingZeros() + + Mask->getValue().countPopulation()) == Mask->getValue().getBitWidth() + && ConstantExpr::getAnd(N, Mask)->isNullValue()) + break; + return 0; + } + + if (isSub) + return Builder->CreateSub(LHSI->getOperand(0), RHS, "fold"); + return Builder->CreateAdd(LHSI->getOperand(0), RHS, "fold"); +} + +/// FoldAndOfICmps - Fold (icmp)&(icmp) if possible. +Instruction *InstCombiner::FoldAndOfICmps(Instruction &I, + ICmpInst *LHS, ICmpInst *RHS) { + Value *Val, *Val2; + ConstantInt *LHSCst, *RHSCst; + ICmpInst::Predicate LHSCC, RHSCC; + + // This only handles icmp of constants: (icmp1 A, C1) & (icmp2 B, C2). + if (!match(LHS, m_ICmp(LHSCC, m_Value(Val), + m_ConstantInt(LHSCst))) || + !match(RHS, m_ICmp(RHSCC, m_Value(Val2), + m_ConstantInt(RHSCst)))) + return 0; + + // (icmp ult A, C) & (icmp ult B, C) --> (icmp ult (A|B), C) + // where C is a power of 2 + if (LHSCst == RHSCst && LHSCC == RHSCC && LHSCC == ICmpInst::ICMP_ULT && + LHSCst->getValue().isPowerOf2()) { + Value *NewOr = Builder->CreateOr(Val, Val2); + return new ICmpInst(LHSCC, NewOr, LHSCst); + } + + // From here on, we only handle: + // (icmp1 A, C1) & (icmp2 A, C2) --> something simpler. + if (Val != Val2) return 0; + + // ICMP_[US][GL]E X, CST is folded to ICMP_[US][GL]T elsewhere. + if (LHSCC == ICmpInst::ICMP_UGE || LHSCC == ICmpInst::ICMP_ULE || + RHSCC == ICmpInst::ICMP_UGE || RHSCC == ICmpInst::ICMP_ULE || + LHSCC == ICmpInst::ICMP_SGE || LHSCC == ICmpInst::ICMP_SLE || + RHSCC == ICmpInst::ICMP_SGE || RHSCC == ICmpInst::ICMP_SLE) + return 0; + + // We can't fold (ugt x, C) & (sgt x, C2). + if (!PredicatesFoldable(LHSCC, RHSCC)) + return 0; + + // Ensure that the larger constant is on the RHS. + bool ShouldSwap; + if (CmpInst::isSigned(LHSCC) || + (ICmpInst::isEquality(LHSCC) && + CmpInst::isSigned(RHSCC))) + ShouldSwap = LHSCst->getValue().sgt(RHSCst->getValue()); + else + ShouldSwap = LHSCst->getValue().ugt(RHSCst->getValue()); + + if (ShouldSwap) { + std::swap(LHS, RHS); + std::swap(LHSCst, RHSCst); + std::swap(LHSCC, RHSCC); + } + + // At this point, we know we have have two icmp instructions + // comparing a value against two constants and and'ing the result + // together. Because of the above check, we know that we only have + // icmp eq, icmp ne, icmp [su]lt, and icmp [SU]gt here. We also know + // (from the FoldICmpLogical check above), that the two constants + // are not equal and that the larger constant is on the RHS + assert(LHSCst != RHSCst && "Compares not folded above?"); + + switch (LHSCC) { + default: llvm_unreachable("Unknown integer condition code!"); + case ICmpInst::ICMP_EQ: + switch (RHSCC) { + default: llvm_unreachable("Unknown integer condition code!"); + case ICmpInst::ICMP_EQ: // (X == 13 & X == 15) -> false + case ICmpInst::ICMP_UGT: // (X == 13 & X > 15) -> false + case ICmpInst::ICMP_SGT: // (X == 13 & X > 15) -> false + return ReplaceInstUsesWith(I, ConstantInt::getFalse(*Context)); + case ICmpInst::ICMP_NE: // (X == 13 & X != 15) -> X == 13 + case ICmpInst::ICMP_ULT: // (X == 13 & X < 15) -> X == 13 + case ICmpInst::ICMP_SLT: // (X == 13 & X < 15) -> X == 13 + return ReplaceInstUsesWith(I, LHS); + } + case ICmpInst::ICMP_NE: + switch (RHSCC) { + default: llvm_unreachable("Unknown integer condition code!"); + case ICmpInst::ICMP_ULT: + if (LHSCst == SubOne(RHSCst)) // (X != 13 & X u< 14) -> X < 13 + return new ICmpInst(ICmpInst::ICMP_ULT, Val, LHSCst); + break; // (X != 13 & X u< 15) -> no change + case ICmpInst::ICMP_SLT: + if (LHSCst == SubOne(RHSCst)) // (X != 13 & X s< 14) -> X < 13 + return new ICmpInst(ICmpInst::ICMP_SLT, Val, LHSCst); + break; // (X != 13 & X s< 15) -> no change + case ICmpInst::ICMP_EQ: // (X != 13 & X == 15) -> X == 15 + case ICmpInst::ICMP_UGT: // (X != 13 & X u> 15) -> X u> 15 + case ICmpInst::ICMP_SGT: // (X != 13 & X s> 15) -> X s> 15 + return ReplaceInstUsesWith(I, RHS); + case ICmpInst::ICMP_NE: + if (LHSCst == SubOne(RHSCst)){// (X != 13 & X != 14) -> X-13 >u 1 + Constant *AddCST = ConstantExpr::getNeg(LHSCst); + Value *Add = Builder->CreateAdd(Val, AddCST, Val->getName()+".off"); + return new ICmpInst(ICmpInst::ICMP_UGT, Add, + ConstantInt::get(Add->getType(), 1)); + } + break; // (X != 13 & X != 15) -> no change + } + break; + case ICmpInst::ICMP_ULT: + switch (RHSCC) { + default: llvm_unreachable("Unknown integer condition code!"); + case ICmpInst::ICMP_EQ: // (X u< 13 & X == 15) -> false + case ICmpInst::ICMP_UGT: // (X u< 13 & X u> 15) -> false + return ReplaceInstUsesWith(I, ConstantInt::getFalse(*Context)); + case ICmpInst::ICMP_SGT: // (X u< 13 & X s> 15) -> no change + break; + case ICmpInst::ICMP_NE: // (X u< 13 & X != 15) -> X u< 13 + case ICmpInst::ICMP_ULT: // (X u< 13 & X u< 15) -> X u< 13 + return ReplaceInstUsesWith(I, LHS); + case ICmpInst::ICMP_SLT: // (X u< 13 & X s< 15) -> no change + break; + } + break; + case ICmpInst::ICMP_SLT: + switch (RHSCC) { + default: llvm_unreachable("Unknown integer condition code!"); + case ICmpInst::ICMP_EQ: // (X s< 13 & X == 15) -> false + case ICmpInst::ICMP_SGT: // (X s< 13 & X s> 15) -> false + return ReplaceInstUsesWith(I, ConstantInt::getFalse(*Context)); + case ICmpInst::ICMP_UGT: // (X s< 13 & X u> 15) -> no change + break; + case ICmpInst::ICMP_NE: // (X s< 13 & X != 15) -> X < 13 + case ICmpInst::ICMP_SLT: // (X s< 13 & X s< 15) -> X < 13 + return ReplaceInstUsesWith(I, LHS); + case ICmpInst::ICMP_ULT: // (X s< 13 & X u< 15) -> no change + break; + } + break; + case ICmpInst::ICMP_UGT: + switch (RHSCC) { + default: llvm_unreachable("Unknown integer condition code!"); + case ICmpInst::ICMP_EQ: // (X u> 13 & X == 15) -> X == 15 + case ICmpInst::ICMP_UGT: // (X u> 13 & X u> 15) -> X u> 15 + return ReplaceInstUsesWith(I, RHS); + case ICmpInst::ICMP_SGT: // (X u> 13 & X s> 15) -> no change + break; + case ICmpInst::ICMP_NE: + if (RHSCst == AddOne(LHSCst)) // (X u> 13 & X != 14) -> X u> 14 + return new ICmpInst(LHSCC, Val, RHSCst); + break; // (X u> 13 & X != 15) -> no change + case ICmpInst::ICMP_ULT: // (X u> 13 & X u< 15) -> (X-14) 13 & X s< 15) -> no change + break; + } + break; + case ICmpInst::ICMP_SGT: + switch (RHSCC) { + default: llvm_unreachable("Unknown integer condition code!"); + case ICmpInst::ICMP_EQ: // (X s> 13 & X == 15) -> X == 15 + case ICmpInst::ICMP_SGT: // (X s> 13 & X s> 15) -> X s> 15 + return ReplaceInstUsesWith(I, RHS); + case ICmpInst::ICMP_UGT: // (X s> 13 & X u> 15) -> no change + break; + case ICmpInst::ICMP_NE: + if (RHSCst == AddOne(LHSCst)) // (X s> 13 & X != 14) -> X s> 14 + return new ICmpInst(LHSCC, Val, RHSCst); + break; // (X s> 13 & X != 15) -> no change + case ICmpInst::ICMP_SLT: // (X s> 13 & X s< 15) -> (X-14) s< 1 + return InsertRangeTest(Val, AddOne(LHSCst), + RHSCst, true, true, I); + case ICmpInst::ICMP_ULT: // (X s> 13 & X u< 15) -> no change + break; + } + break; + } + + return 0; +} + +Instruction *InstCombiner::FoldAndOfFCmps(Instruction &I, FCmpInst *LHS, + FCmpInst *RHS) { + + if (LHS->getPredicate() == FCmpInst::FCMP_ORD && + RHS->getPredicate() == FCmpInst::FCMP_ORD) { + // (fcmp ord x, c) & (fcmp ord y, c) -> (fcmp ord x, y) + if (ConstantFP *LHSC = dyn_cast(LHS->getOperand(1))) + if (ConstantFP *RHSC = dyn_cast(RHS->getOperand(1))) { + // If either of the constants are nans, then the whole thing returns + // false. + if (LHSC->getValueAPF().isNaN() || RHSC->getValueAPF().isNaN()) + return ReplaceInstUsesWith(I, ConstantInt::getFalse(*Context)); + return new FCmpInst(FCmpInst::FCMP_ORD, + LHS->getOperand(0), RHS->getOperand(0)); + } + + // Handle vector zeros. This occurs because the canonical form of + // "fcmp ord x,x" is "fcmp ord x, 0". + if (isa(LHS->getOperand(1)) && + isa(RHS->getOperand(1))) + return new FCmpInst(FCmpInst::FCMP_ORD, + LHS->getOperand(0), RHS->getOperand(0)); + return 0; + } + + Value *Op0LHS = LHS->getOperand(0), *Op0RHS = LHS->getOperand(1); + Value *Op1LHS = RHS->getOperand(0), *Op1RHS = RHS->getOperand(1); + FCmpInst::Predicate Op0CC = LHS->getPredicate(), Op1CC = RHS->getPredicate(); + + + if (Op0LHS == Op1RHS && Op0RHS == Op1LHS) { + // Swap RHS operands to match LHS. + Op1CC = FCmpInst::getSwappedPredicate(Op1CC); + std::swap(Op1LHS, Op1RHS); + } + + if (Op0LHS == Op1LHS && Op0RHS == Op1RHS) { + // Simplify (fcmp cc0 x, y) & (fcmp cc1 x, y). + if (Op0CC == Op1CC) + return new FCmpInst((FCmpInst::Predicate)Op0CC, Op0LHS, Op0RHS); + + if (Op0CC == FCmpInst::FCMP_FALSE || Op1CC == FCmpInst::FCMP_FALSE) + return ReplaceInstUsesWith(I, ConstantInt::getFalse(*Context)); + if (Op0CC == FCmpInst::FCMP_TRUE) + return ReplaceInstUsesWith(I, RHS); + if (Op1CC == FCmpInst::FCMP_TRUE) + return ReplaceInstUsesWith(I, LHS); + + bool Op0Ordered; + bool Op1Ordered; + unsigned Op0Pred = getFCmpCode(Op0CC, Op0Ordered); + unsigned Op1Pred = getFCmpCode(Op1CC, Op1Ordered); + if (Op1Pred == 0) { + std::swap(LHS, RHS); + std::swap(Op0Pred, Op1Pred); + std::swap(Op0Ordered, Op1Ordered); + } + if (Op0Pred == 0) { + // uno && ueq -> uno && (uno || eq) -> ueq + // ord && olt -> ord && (ord && lt) -> olt + if (Op0Ordered == Op1Ordered) + return ReplaceInstUsesWith(I, RHS); + + // uno && oeq -> uno && (ord && eq) -> false + // uno && ord -> false + if (!Op0Ordered) + return ReplaceInstUsesWith(I, ConstantInt::getFalse(*Context)); + // ord && ueq -> ord && (uno || eq) -> oeq + return cast(getFCmpValue(true, Op1Pred, + Op0LHS, Op0RHS, Context)); + } + } + + return 0; +} + + +Instruction *InstCombiner::visitAnd(BinaryOperator &I) { + bool Changed = SimplifyCommutative(I); + Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1); + + if (Value *V = SimplifyAndInst(Op0, Op1, TD)) + return ReplaceInstUsesWith(I, V); + + + // See if we can simplify any instructions used by the instruction whose sole + // purpose is to compute bits we don't care about. + if (SimplifyDemandedInstructionBits(I)) + return &I; + + + if (ConstantInt *AndRHS = dyn_cast(Op1)) { + const APInt &AndRHSMask = AndRHS->getValue(); + APInt NotAndRHS(~AndRHSMask); + + // Optimize a variety of ((val OP C1) & C2) combinations... + if (BinaryOperator *Op0I = dyn_cast(Op0)) { + Value *Op0LHS = Op0I->getOperand(0); + Value *Op0RHS = Op0I->getOperand(1); + switch (Op0I->getOpcode()) { + default: break; + case Instruction::Xor: + case Instruction::Or: + // If the mask is only needed on one incoming arm, push it up. + if (!Op0I->hasOneUse()) break; + + if (MaskedValueIsZero(Op0LHS, NotAndRHS)) { + // Not masking anything out for the LHS, move to RHS. + Value *NewRHS = Builder->CreateAnd(Op0RHS, AndRHS, + Op0RHS->getName()+".masked"); + return BinaryOperator::Create(Op0I->getOpcode(), Op0LHS, NewRHS); + } + if (!isa(Op0RHS) && + MaskedValueIsZero(Op0RHS, NotAndRHS)) { + // Not masking anything out for the RHS, move to LHS. + Value *NewLHS = Builder->CreateAnd(Op0LHS, AndRHS, + Op0LHS->getName()+".masked"); + return BinaryOperator::Create(Op0I->getOpcode(), NewLHS, Op0RHS); + } + + break; + case Instruction::Add: + // ((A & N) + B) & AndRHS -> (A + B) & AndRHS iff N&AndRHS == AndRHS. + // ((A | N) + B) & AndRHS -> (A + B) & AndRHS iff N&AndRHS == 0 + // ((A ^ N) + B) & AndRHS -> (A + B) & AndRHS iff N&AndRHS == 0 + if (Value *V = FoldLogicalPlusAnd(Op0LHS, Op0RHS, AndRHS, false, I)) + return BinaryOperator::CreateAnd(V, AndRHS); + if (Value *V = FoldLogicalPlusAnd(Op0RHS, Op0LHS, AndRHS, false, I)) + return BinaryOperator::CreateAnd(V, AndRHS); // Add commutes + break; + + case Instruction::Sub: + // ((A & N) - B) & AndRHS -> (A - B) & AndRHS iff N&AndRHS == AndRHS. + // ((A | N) - B) & AndRHS -> (A - B) & AndRHS iff N&AndRHS == 0 + // ((A ^ N) - B) & AndRHS -> (A - B) & AndRHS iff N&AndRHS == 0 + if (Value *V = FoldLogicalPlusAnd(Op0LHS, Op0RHS, AndRHS, true, I)) + return BinaryOperator::CreateAnd(V, AndRHS); + + // (A - N) & AndRHS -> -N & AndRHS iff A&AndRHS==0 and AndRHS + // has 1's for all bits that the subtraction with A might affect. + if (Op0I->hasOneUse()) { + uint32_t BitWidth = AndRHSMask.getBitWidth(); + uint32_t Zeros = AndRHSMask.countLeadingZeros(); + APInt Mask = APInt::getLowBitsSet(BitWidth, BitWidth - Zeros); + + ConstantInt *A = dyn_cast(Op0LHS); + if (!(A && A->isZero()) && // avoid infinite recursion. + MaskedValueIsZero(Op0LHS, Mask)) { + Value *NewNeg = Builder->CreateNeg(Op0RHS); + return BinaryOperator::CreateAnd(NewNeg, AndRHS); + } + } + break; + + case Instruction::Shl: + case Instruction::LShr: + // (1 << x) & 1 --> zext(x == 0) + // (1 >> x) & 1 --> zext(x == 0) + if (AndRHSMask == 1 && Op0LHS == AndRHS) { + Value *NewICmp = + Builder->CreateICmpEQ(Op0RHS, Constant::getNullValue(I.getType())); + return new ZExtInst(NewICmp, I.getType()); + } + break; + } + + if (ConstantInt *Op0CI = dyn_cast(Op0I->getOperand(1))) + if (Instruction *Res = OptAndOp(Op0I, Op0CI, AndRHS, I)) + return Res; + } else if (CastInst *CI = dyn_cast(Op0)) { + // If this is an integer truncation or change from signed-to-unsigned, and + // if the source is an and/or with immediate, transform it. This + // frequently occurs for bitfield accesses. + if (Instruction *CastOp = dyn_cast(CI->getOperand(0))) { + if ((isa(CI) || isa(CI)) && + CastOp->getNumOperands() == 2) + if (ConstantInt *AndCI =dyn_cast(CastOp->getOperand(1))){ + if (CastOp->getOpcode() == Instruction::And) { + // Change: and (cast (and X, C1) to T), C2 + // into : and (cast X to T), trunc_or_bitcast(C1)&C2 + // This will fold the two constants together, which may allow + // other simplifications. + Value *NewCast = Builder->CreateTruncOrBitCast( + CastOp->getOperand(0), I.getType(), + CastOp->getName()+".shrunk"); + // trunc_or_bitcast(C1)&C2 + Constant *C3 = ConstantExpr::getTruncOrBitCast(AndCI,I.getType()); + C3 = ConstantExpr::getAnd(C3, AndRHS); + return BinaryOperator::CreateAnd(NewCast, C3); + } else if (CastOp->getOpcode() == Instruction::Or) { + // Change: and (cast (or X, C1) to T), C2 + // into : trunc(C1)&C2 iff trunc(C1)&C2 == C2 + Constant *C3 = ConstantExpr::getTruncOrBitCast(AndCI,I.getType()); + if (ConstantExpr::getAnd(C3, AndRHS) == AndRHS) + // trunc(C1)&C2 + return ReplaceInstUsesWith(I, AndRHS); + } + } + } + } + + // Try to fold constant and into select arguments. + if (SelectInst *SI = dyn_cast(Op0)) + if (Instruction *R = FoldOpIntoSelect(I, SI, this)) + return R; + if (isa(Op0)) + if (Instruction *NV = FoldOpIntoPhi(I)) + return NV; + } + + + // (~A & ~B) == (~(A | B)) - De Morgan's Law + if (Value *Op0NotVal = dyn_castNotVal(Op0)) + if (Value *Op1NotVal = dyn_castNotVal(Op1)) + if (Op0->hasOneUse() && Op1->hasOneUse()) { + Value *Or = Builder->CreateOr(Op0NotVal, Op1NotVal, + I.getName()+".demorgan"); + return BinaryOperator::CreateNot(Or); + } + + { + Value *A = 0, *B = 0, *C = 0, *D = 0; + // (A|B) & ~(A&B) -> A^B + if (match(Op0, m_Or(m_Value(A), m_Value(B))) && + match(Op1, m_Not(m_And(m_Value(C), m_Value(D)))) && + ((A == C && B == D) || (A == D && B == C))) + return BinaryOperator::CreateXor(A, B); + + // ~(A&B) & (A|B) -> A^B + if (match(Op1, m_Or(m_Value(A), m_Value(B))) && + match(Op0, m_Not(m_And(m_Value(C), m_Value(D)))) && + ((A == C && B == D) || (A == D && B == C))) + return BinaryOperator::CreateXor(A, B); + + if (Op0->hasOneUse() && + match(Op0, m_Xor(m_Value(A), m_Value(B)))) { + if (A == Op1) { // (A^B)&A -> A&(A^B) + I.swapOperands(); // Simplify below + std::swap(Op0, Op1); + } else if (B == Op1) { // (A^B)&B -> B&(B^A) + cast(Op0)->swapOperands(); + I.swapOperands(); // Simplify below + std::swap(Op0, Op1); + } + } + + if (Op1->hasOneUse() && + match(Op1, m_Xor(m_Value(A), m_Value(B)))) { + if (B == Op0) { // B&(A^B) -> B&(B^A) + cast(Op1)->swapOperands(); + std::swap(A, B); + } + if (A == Op0) // A&(A^B) -> A & ~B + return BinaryOperator::CreateAnd(A, Builder->CreateNot(B, "tmp")); + } + + // (A&((~A)|B)) -> A&B + if (match(Op0, m_Or(m_Not(m_Specific(Op1)), m_Value(A))) || + match(Op0, m_Or(m_Value(A), m_Not(m_Specific(Op1))))) + return BinaryOperator::CreateAnd(A, Op1); + if (match(Op1, m_Or(m_Not(m_Specific(Op0)), m_Value(A))) || + match(Op1, m_Or(m_Value(A), m_Not(m_Specific(Op0))))) + return BinaryOperator::CreateAnd(A, Op0); + } + + if (ICmpInst *RHS = dyn_cast(Op1)) { + // (icmp1 A, B) & (icmp2 A, B) --> (icmp3 A, B) + if (Instruction *R = AssociativeOpt(I, FoldICmpLogical(*this, RHS))) + return R; + + if (ICmpInst *LHS = dyn_cast(Op0)) + if (Instruction *Res = FoldAndOfICmps(I, LHS, RHS)) + return Res; + } + + // fold (and (cast A), (cast B)) -> (cast (and A, B)) + if (CastInst *Op0C = dyn_cast(Op0)) + if (CastInst *Op1C = dyn_cast(Op1)) + if (Op0C->getOpcode() == Op1C->getOpcode()) { // same cast kind ? + const Type *SrcTy = Op0C->getOperand(0)->getType(); + if (SrcTy == Op1C->getOperand(0)->getType() && + SrcTy->isIntOrIntVector() && + // Only do this if the casts both really cause code to be generated. + ValueRequiresCast(Op0C->getOpcode(), Op0C->getOperand(0), + I.getType(), TD) && + ValueRequiresCast(Op1C->getOpcode(), Op1C->getOperand(0), + I.getType(), TD)) { + Value *NewOp = Builder->CreateAnd(Op0C->getOperand(0), + Op1C->getOperand(0), I.getName()); + return CastInst::Create(Op0C->getOpcode(), NewOp, I.getType()); + } + } + + // (X >> Z) & (Y >> Z) -> (X&Y) >> Z for all shifts. + if (BinaryOperator *SI1 = dyn_cast(Op1)) { + if (BinaryOperator *SI0 = dyn_cast(Op0)) + if (SI0->isShift() && SI0->getOpcode() == SI1->getOpcode() && + SI0->getOperand(1) == SI1->getOperand(1) && + (SI0->hasOneUse() || SI1->hasOneUse())) { + Value *NewOp = + Builder->CreateAnd(SI0->getOperand(0), SI1->getOperand(0), + SI0->getName()); + return BinaryOperator::Create(SI1->getOpcode(), NewOp, + SI1->getOperand(1)); + } + } + + // If and'ing two fcmp, try combine them into one. + if (FCmpInst *LHS = dyn_cast(I.getOperand(0))) { + if (FCmpInst *RHS = dyn_cast(I.getOperand(1))) + if (Instruction *Res = FoldAndOfFCmps(I, LHS, RHS)) + return Res; + } + + return Changed ? &I : 0; +} + +/// CollectBSwapParts - Analyze the specified subexpression and see if it is +/// capable of providing pieces of a bswap. The subexpression provides pieces +/// of a bswap if it is proven that each of the non-zero bytes in the output of +/// the expression came from the corresponding "byte swapped" byte in some other +/// value. For example, if the current subexpression is "(shl i32 %X, 24)" then +/// we know that the expression deposits the low byte of %X into the high byte +/// of the bswap result and that all other bytes are zero. This expression is +/// accepted, the high byte of ByteValues is set to X to indicate a correct +/// match. +/// +/// This function returns true if the match was unsuccessful and false if so. +/// On entry to the function the "OverallLeftShift" is a signed integer value +/// indicating the number of bytes that the subexpression is later shifted. For +/// example, if the expression is later right shifted by 16 bits, the +/// OverallLeftShift value would be -2 on entry. This is used to specify which +/// byte of ByteValues is actually being set. +/// +/// Similarly, ByteMask is a bitmask where a bit is clear if its corresponding +/// byte is masked to zero by a user. For example, in (X & 255), X will be +/// processed with a bytemask of 1. Because bytemask is 32-bits, this limits +/// this function to working on up to 32-byte (256 bit) values. ByteMask is +/// always in the local (OverallLeftShift) coordinate space. +/// +static bool CollectBSwapParts(Value *V, int OverallLeftShift, uint32_t ByteMask, + SmallVector &ByteValues) { + if (Instruction *I = dyn_cast(V)) { + // If this is an or instruction, it may be an inner node of the bswap. + if (I->getOpcode() == Instruction::Or) { + return CollectBSwapParts(I->getOperand(0), OverallLeftShift, ByteMask, + ByteValues) || + CollectBSwapParts(I->getOperand(1), OverallLeftShift, ByteMask, + ByteValues); + } + + // If this is a logical shift by a constant multiple of 8, recurse with + // OverallLeftShift and ByteMask adjusted. + if (I->isLogicalShift() && isa(I->getOperand(1))) { + unsigned ShAmt = + cast(I->getOperand(1))->getLimitedValue(~0U); + // Ensure the shift amount is defined and of a byte value. + if ((ShAmt & 7) || (ShAmt > 8*ByteValues.size())) + return true; + + unsigned ByteShift = ShAmt >> 3; + if (I->getOpcode() == Instruction::Shl) { + // X << 2 -> collect(X, +2) + OverallLeftShift += ByteShift; + ByteMask >>= ByteShift; + } else { + // X >>u 2 -> collect(X, -2) + OverallLeftShift -= ByteShift; + ByteMask <<= ByteShift; + ByteMask &= (~0U >> (32-ByteValues.size())); + } + + if (OverallLeftShift >= (int)ByteValues.size()) return true; + if (OverallLeftShift <= -(int)ByteValues.size()) return true; + + return CollectBSwapParts(I->getOperand(0), OverallLeftShift, ByteMask, + ByteValues); + } + + // If this is a logical 'and' with a mask that clears bytes, clear the + // corresponding bytes in ByteMask. + if (I->getOpcode() == Instruction::And && + isa(I->getOperand(1))) { + // Scan every byte of the and mask, seeing if the byte is either 0 or 255. + unsigned NumBytes = ByteValues.size(); + APInt Byte(I->getType()->getPrimitiveSizeInBits(), 255); + const APInt &AndMask = cast(I->getOperand(1))->getValue(); + + for (unsigned i = 0; i != NumBytes; ++i, Byte <<= 8) { + // If this byte is masked out by a later operation, we don't care what + // the and mask is. + if ((ByteMask & (1 << i)) == 0) + continue; + + // If the AndMask is all zeros for this byte, clear the bit. + APInt MaskB = AndMask & Byte; + if (MaskB == 0) { + ByteMask &= ~(1U << i); + continue; + } + + // If the AndMask is not all ones for this byte, it's not a bytezap. + if (MaskB != Byte) + return true; + + // Otherwise, this byte is kept. + } + + return CollectBSwapParts(I->getOperand(0), OverallLeftShift, ByteMask, + ByteValues); + } + } + + // Okay, we got to something that isn't a shift, 'or' or 'and'. This must be + // the input value to the bswap. Some observations: 1) if more than one byte + // is demanded from this input, then it could not be successfully assembled + // into a byteswap. At least one of the two bytes would not be aligned with + // their ultimate destination. + if (!isPowerOf2_32(ByteMask)) return true; + unsigned InputByteNo = CountTrailingZeros_32(ByteMask); + + // 2) The input and ultimate destinations must line up: if byte 3 of an i32 + // is demanded, it needs to go into byte 0 of the result. This means that the + // byte needs to be shifted until it lands in the right byte bucket. The + // shift amount depends on the position: if the byte is coming from the high + // part of the value (e.g. byte 3) then it must be shifted right. If from the + // low part, it must be shifted left. + unsigned DestByteNo = InputByteNo + OverallLeftShift; + if (InputByteNo < ByteValues.size()/2) { + if (ByteValues.size()-1-DestByteNo != InputByteNo) + return true; + } else { + if (ByteValues.size()-1-DestByteNo != InputByteNo) + return true; + } + + // If the destination byte value is already defined, the values are or'd + // together, which isn't a bswap (unless it's an or of the same bits). + if (ByteValues[DestByteNo] && ByteValues[DestByteNo] != V) + return true; + ByteValues[DestByteNo] = V; + return false; +} + +/// MatchBSwap - Given an OR instruction, check to see if this is a bswap idiom. +/// If so, insert the new bswap intrinsic and return it. +Instruction *InstCombiner::MatchBSwap(BinaryOperator &I) { + const IntegerType *ITy = dyn_cast(I.getType()); + if (!ITy || ITy->getBitWidth() % 16 || + // ByteMask only allows up to 32-byte values. + ITy->getBitWidth() > 32*8) + return 0; // Can only bswap pairs of bytes. Can't do vectors. + + /// ByteValues - For each byte of the result, we keep track of which value + /// defines each byte. + SmallVector ByteValues; + ByteValues.resize(ITy->getBitWidth()/8); + + // Try to find all the pieces corresponding to the bswap. + uint32_t ByteMask = ~0U >> (32-ByteValues.size()); + if (CollectBSwapParts(&I, 0, ByteMask, ByteValues)) + return 0; + + // Check to see if all of the bytes come from the same value. + Value *V = ByteValues[0]; + if (V == 0) return 0; // Didn't find a byte? Must be zero. + + // Check to make sure that all of the bytes come from the same value. + for (unsigned i = 1, e = ByteValues.size(); i != e; ++i) + if (ByteValues[i] != V) + return 0; + const Type *Tys[] = { ITy }; + Module *M = I.getParent()->getParent()->getParent(); + Function *F = Intrinsic::getDeclaration(M, Intrinsic::bswap, Tys, 1); + return CallInst::Create(F, V); +} + +/// MatchSelectFromAndOr - We have an expression of the form (A&C)|(B&D). Check +/// If A is (cond?-1:0) and either B or D is ~(cond?-1,0) or (cond?0,-1), then +/// we can simplify this expression to "cond ? C : D or B". +static Instruction *MatchSelectFromAndOr(Value *A, Value *B, + Value *C, Value *D, + LLVMContext *Context) { + // If A is not a select of -1/0, this cannot match. + Value *Cond = 0; + if (!match(A, m_SelectCst<-1, 0>(m_Value(Cond)))) + return 0; + + // ((cond?-1:0)&C) | (B&(cond?0:-1)) -> cond ? C : B. + if (match(D, m_SelectCst<0, -1>(m_Specific(Cond)))) + return SelectInst::Create(Cond, C, B); + if (match(D, m_Not(m_SelectCst<-1, 0>(m_Specific(Cond))))) + return SelectInst::Create(Cond, C, B); + // ((cond?-1:0)&C) | ((cond?0:-1)&D) -> cond ? C : D. + if (match(B, m_SelectCst<0, -1>(m_Specific(Cond)))) + return SelectInst::Create(Cond, C, D); + if (match(B, m_Not(m_SelectCst<-1, 0>(m_Specific(Cond))))) + return SelectInst::Create(Cond, C, D); + return 0; +} + +/// FoldOrOfICmps - Fold (icmp)|(icmp) if possible. +Instruction *InstCombiner::FoldOrOfICmps(Instruction &I, + ICmpInst *LHS, ICmpInst *RHS) { + Value *Val, *Val2; + ConstantInt *LHSCst, *RHSCst; + ICmpInst::Predicate LHSCC, RHSCC; + + // This only handles icmp of constants: (icmp1 A, C1) | (icmp2 B, C2). + if (!match(LHS, m_ICmp(LHSCC, m_Value(Val), + m_ConstantInt(LHSCst))) || + !match(RHS, m_ICmp(RHSCC, m_Value(Val2), + m_ConstantInt(RHSCst)))) + return 0; + + // From here on, we only handle: + // (icmp1 A, C1) | (icmp2 A, C2) --> something simpler. + if (Val != Val2) return 0; + + // ICMP_[US][GL]E X, CST is folded to ICMP_[US][GL]T elsewhere. + if (LHSCC == ICmpInst::ICMP_UGE || LHSCC == ICmpInst::ICMP_ULE || + RHSCC == ICmpInst::ICMP_UGE || RHSCC == ICmpInst::ICMP_ULE || + LHSCC == ICmpInst::ICMP_SGE || LHSCC == ICmpInst::ICMP_SLE || + RHSCC == ICmpInst::ICMP_SGE || RHSCC == ICmpInst::ICMP_SLE) + return 0; + + // We can't fold (ugt x, C) | (sgt x, C2). + if (!PredicatesFoldable(LHSCC, RHSCC)) + return 0; + + // Ensure that the larger constant is on the RHS. + bool ShouldSwap; + if (CmpInst::isSigned(LHSCC) || + (ICmpInst::isEquality(LHSCC) && + CmpInst::isSigned(RHSCC))) + ShouldSwap = LHSCst->getValue().sgt(RHSCst->getValue()); + else + ShouldSwap = LHSCst->getValue().ugt(RHSCst->getValue()); + + if (ShouldSwap) { + std::swap(LHS, RHS); + std::swap(LHSCst, RHSCst); + std::swap(LHSCC, RHSCC); + } + + // At this point, we know we have have two icmp instructions + // comparing a value against two constants and or'ing the result + // together. Because of the above check, we know that we only have + // ICMP_EQ, ICMP_NE, ICMP_LT, and ICMP_GT here. We also know (from the + // FoldICmpLogical check above), that the two constants are not + // equal. + assert(LHSCst != RHSCst && "Compares not folded above?"); + + switch (LHSCC) { + default: llvm_unreachable("Unknown integer condition code!"); + case ICmpInst::ICMP_EQ: + switch (RHSCC) { + default: llvm_unreachable("Unknown integer condition code!"); + case ICmpInst::ICMP_EQ: + if (LHSCst == SubOne(RHSCst)) { + // (X == 13 | X == 14) -> X-13 CreateAdd(Val, AddCST, Val->getName()+".off"); + AddCST = ConstantExpr::getSub(AddOne(RHSCst), LHSCst); + return new ICmpInst(ICmpInst::ICMP_ULT, Add, AddCST); + } + break; // (X == 13 | X == 15) -> no change + case ICmpInst::ICMP_UGT: // (X == 13 | X u> 14) -> no change + case ICmpInst::ICMP_SGT: // (X == 13 | X s> 14) -> no change + break; + case ICmpInst::ICMP_NE: // (X == 13 | X != 15) -> X != 15 + case ICmpInst::ICMP_ULT: // (X == 13 | X u< 15) -> X u< 15 + case ICmpInst::ICMP_SLT: // (X == 13 | X s< 15) -> X s< 15 + return ReplaceInstUsesWith(I, RHS); + } + break; + case ICmpInst::ICMP_NE: + switch (RHSCC) { + default: llvm_unreachable("Unknown integer condition code!"); + case ICmpInst::ICMP_EQ: // (X != 13 | X == 15) -> X != 13 + case ICmpInst::ICMP_UGT: // (X != 13 | X u> 15) -> X != 13 + case ICmpInst::ICMP_SGT: // (X != 13 | X s> 15) -> X != 13 + return ReplaceInstUsesWith(I, LHS); + case ICmpInst::ICMP_NE: // (X != 13 | X != 15) -> true + case ICmpInst::ICMP_ULT: // (X != 13 | X u< 15) -> true + case ICmpInst::ICMP_SLT: // (X != 13 | X s< 15) -> true + return ReplaceInstUsesWith(I, ConstantInt::getTrue(*Context)); + } + break; + case ICmpInst::ICMP_ULT: + switch (RHSCC) { + default: llvm_unreachable("Unknown integer condition code!"); + case ICmpInst::ICMP_EQ: // (X u< 13 | X == 14) -> no change + break; + case ICmpInst::ICMP_UGT: // (X u< 13 | X u> 15) -> (X-13) u> 2 + // If RHSCst is [us]MAXINT, it is always false. Not handling + // this can cause overflow. + if (RHSCst->isMaxValue(false)) + return ReplaceInstUsesWith(I, LHS); + return InsertRangeTest(Val, LHSCst, AddOne(RHSCst), + false, false, I); + case ICmpInst::ICMP_SGT: // (X u< 13 | X s> 15) -> no change + break; + case ICmpInst::ICMP_NE: // (X u< 13 | X != 15) -> X != 15 + case ICmpInst::ICMP_ULT: // (X u< 13 | X u< 15) -> X u< 15 + return ReplaceInstUsesWith(I, RHS); + case ICmpInst::ICMP_SLT: // (X u< 13 | X s< 15) -> no change + break; + } + break; + case ICmpInst::ICMP_SLT: + switch (RHSCC) { + default: llvm_unreachable("Unknown integer condition code!"); + case ICmpInst::ICMP_EQ: // (X s< 13 | X == 14) -> no change + break; + case ICmpInst::ICMP_SGT: // (X s< 13 | X s> 15) -> (X-13) s> 2 + // If RHSCst is [us]MAXINT, it is always false. Not handling + // this can cause overflow. + if (RHSCst->isMaxValue(true)) + return ReplaceInstUsesWith(I, LHS); + return InsertRangeTest(Val, LHSCst, AddOne(RHSCst), + true, false, I); + case ICmpInst::ICMP_UGT: // (X s< 13 | X u> 15) -> no change + break; + case ICmpInst::ICMP_NE: // (X s< 13 | X != 15) -> X != 15 + case ICmpInst::ICMP_SLT: // (X s< 13 | X s< 15) -> X s< 15 + return ReplaceInstUsesWith(I, RHS); + case ICmpInst::ICMP_ULT: // (X s< 13 | X u< 15) -> no change + break; + } + break; + case ICmpInst::ICMP_UGT: + switch (RHSCC) { + default: llvm_unreachable("Unknown integer condition code!"); + case ICmpInst::ICMP_EQ: // (X u> 13 | X == 15) -> X u> 13 + case ICmpInst::ICMP_UGT: // (X u> 13 | X u> 15) -> X u> 13 + return ReplaceInstUsesWith(I, LHS); + case ICmpInst::ICMP_SGT: // (X u> 13 | X s> 15) -> no change + break; + case ICmpInst::ICMP_NE: // (X u> 13 | X != 15) -> true + case ICmpInst::ICMP_ULT: // (X u> 13 | X u< 15) -> true + return ReplaceInstUsesWith(I, ConstantInt::getTrue(*Context)); + case ICmpInst::ICMP_SLT: // (X u> 13 | X s< 15) -> no change + break; + } + break; + case ICmpInst::ICMP_SGT: + switch (RHSCC) { + default: llvm_unreachable("Unknown integer condition code!"); + case ICmpInst::ICMP_EQ: // (X s> 13 | X == 15) -> X > 13 + case ICmpInst::ICMP_SGT: // (X s> 13 | X s> 15) -> X > 13 + return ReplaceInstUsesWith(I, LHS); + case ICmpInst::ICMP_UGT: // (X s> 13 | X u> 15) -> no change + break; + case ICmpInst::ICMP_NE: // (X s> 13 | X != 15) -> true + case ICmpInst::ICMP_SLT: // (X s> 13 | X s< 15) -> true + return ReplaceInstUsesWith(I, ConstantInt::getTrue(*Context)); + case ICmpInst::ICMP_ULT: // (X s> 13 | X u< 15) -> no change + break; + } + break; + } + return 0; +} + +Instruction *InstCombiner::FoldOrOfFCmps(Instruction &I, FCmpInst *LHS, + FCmpInst *RHS) { + if (LHS->getPredicate() == FCmpInst::FCMP_UNO && + RHS->getPredicate() == FCmpInst::FCMP_UNO && + LHS->getOperand(0)->getType() == RHS->getOperand(0)->getType()) { + if (ConstantFP *LHSC = dyn_cast(LHS->getOperand(1))) + if (ConstantFP *RHSC = dyn_cast(RHS->getOperand(1))) { + // If either of the constants are nans, then the whole thing returns + // true. + if (LHSC->getValueAPF().isNaN() || RHSC->getValueAPF().isNaN()) + return ReplaceInstUsesWith(I, ConstantInt::getTrue(*Context)); + + // Otherwise, no need to compare the two constants, compare the + // rest. + return new FCmpInst(FCmpInst::FCMP_UNO, + LHS->getOperand(0), RHS->getOperand(0)); + } + + // Handle vector zeros. This occurs because the canonical form of + // "fcmp uno x,x" is "fcmp uno x, 0". + if (isa(LHS->getOperand(1)) && + isa(RHS->getOperand(1))) + return new FCmpInst(FCmpInst::FCMP_UNO, + LHS->getOperand(0), RHS->getOperand(0)); + + return 0; + } + + Value *Op0LHS = LHS->getOperand(0), *Op0RHS = LHS->getOperand(1); + Value *Op1LHS = RHS->getOperand(0), *Op1RHS = RHS->getOperand(1); + FCmpInst::Predicate Op0CC = LHS->getPredicate(), Op1CC = RHS->getPredicate(); + + if (Op0LHS == Op1RHS && Op0RHS == Op1LHS) { + // Swap RHS operands to match LHS. + Op1CC = FCmpInst::getSwappedPredicate(Op1CC); + std::swap(Op1LHS, Op1RHS); + } + if (Op0LHS == Op1LHS && Op0RHS == Op1RHS) { + // Simplify (fcmp cc0 x, y) | (fcmp cc1 x, y). + if (Op0CC == Op1CC) + return new FCmpInst((FCmpInst::Predicate)Op0CC, + Op0LHS, Op0RHS); + if (Op0CC == FCmpInst::FCMP_TRUE || Op1CC == FCmpInst::FCMP_TRUE) + return ReplaceInstUsesWith(I, ConstantInt::getTrue(*Context)); + if (Op0CC == FCmpInst::FCMP_FALSE) + return ReplaceInstUsesWith(I, RHS); + if (Op1CC == FCmpInst::FCMP_FALSE) + return ReplaceInstUsesWith(I, LHS); + bool Op0Ordered; + bool Op1Ordered; + unsigned Op0Pred = getFCmpCode(Op0CC, Op0Ordered); + unsigned Op1Pred = getFCmpCode(Op1CC, Op1Ordered); + if (Op0Ordered == Op1Ordered) { + // If both are ordered or unordered, return a new fcmp with + // or'ed predicates. + Value *RV = getFCmpValue(Op0Ordered, Op0Pred|Op1Pred, + Op0LHS, Op0RHS, Context); + if (Instruction *I = dyn_cast(RV)) + return I; + // Otherwise, it's a constant boolean value... + return ReplaceInstUsesWith(I, RV); + } + } + return 0; +} + +/// FoldOrWithConstants - This helper function folds: +/// +/// ((A | B) & C1) | (B & C2) +/// +/// into: +/// +/// (A & C1) | B +/// +/// when the XOR of the two constants is "all ones" (-1). +Instruction *InstCombiner::FoldOrWithConstants(BinaryOperator &I, Value *Op, + Value *A, Value *B, Value *C) { + ConstantInt *CI1 = dyn_cast(C); + if (!CI1) return 0; + + Value *V1 = 0; + ConstantInt *CI2 = 0; + if (!match(Op, m_And(m_Value(V1), m_ConstantInt(CI2)))) return 0; + + APInt Xor = CI1->getValue() ^ CI2->getValue(); + if (!Xor.isAllOnesValue()) return 0; + + if (V1 == A || V1 == B) { + Value *NewOp = Builder->CreateAnd((V1 == A) ? B : A, CI1); + return BinaryOperator::CreateOr(NewOp, V1); + } + + return 0; +} + +Instruction *InstCombiner::visitOr(BinaryOperator &I) { + bool Changed = SimplifyCommutative(I); + Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1); + + if (Value *V = SimplifyOrInst(Op0, Op1, TD)) + return ReplaceInstUsesWith(I, V); + + + // See if we can simplify any instructions used by the instruction whose sole + // purpose is to compute bits we don't care about. + if (SimplifyDemandedInstructionBits(I)) + return &I; + + if (ConstantInt *RHS = dyn_cast(Op1)) { + ConstantInt *C1 = 0; Value *X = 0; + // (X & C1) | C2 --> (X | C2) & (C1|C2) + if (match(Op0, m_And(m_Value(X), m_ConstantInt(C1))) && + isOnlyUse(Op0)) { + Value *Or = Builder->CreateOr(X, RHS); + Or->takeName(Op0); + return BinaryOperator::CreateAnd(Or, + ConstantInt::get(*Context, RHS->getValue() | C1->getValue())); + } + + // (X ^ C1) | C2 --> (X | C2) ^ (C1&~C2) + if (match(Op0, m_Xor(m_Value(X), m_ConstantInt(C1))) && + isOnlyUse(Op0)) { + Value *Or = Builder->CreateOr(X, RHS); + Or->takeName(Op0); + return BinaryOperator::CreateXor(Or, + ConstantInt::get(*Context, C1->getValue() & ~RHS->getValue())); + } + + // Try to fold constant and into select arguments. + if (SelectInst *SI = dyn_cast(Op0)) + if (Instruction *R = FoldOpIntoSelect(I, SI, this)) + return R; + if (isa(Op0)) + if (Instruction *NV = FoldOpIntoPhi(I)) + return NV; + } + + Value *A = 0, *B = 0; + ConstantInt *C1 = 0, *C2 = 0; + + // (A | B) | C and A | (B | C) -> bswap if possible. + // (A >> B) | (C << D) and (A << B) | (B >> C) -> bswap if possible. + if (match(Op0, m_Or(m_Value(), m_Value())) || + match(Op1, m_Or(m_Value(), m_Value())) || + (match(Op0, m_Shift(m_Value(), m_Value())) && + match(Op1, m_Shift(m_Value(), m_Value())))) { + if (Instruction *BSwap = MatchBSwap(I)) + return BSwap; + } + + // (X^C)|Y -> (X|Y)^C iff Y&C == 0 + if (Op0->hasOneUse() && + match(Op0, m_Xor(m_Value(A), m_ConstantInt(C1))) && + MaskedValueIsZero(Op1, C1->getValue())) { + Value *NOr = Builder->CreateOr(A, Op1); + NOr->takeName(Op0); + return BinaryOperator::CreateXor(NOr, C1); + } + + // Y|(X^C) -> (X|Y)^C iff Y&C == 0 + if (Op1->hasOneUse() && + match(Op1, m_Xor(m_Value(A), m_ConstantInt(C1))) && + MaskedValueIsZero(Op0, C1->getValue())) { + Value *NOr = Builder->CreateOr(A, Op0); + NOr->takeName(Op0); + return BinaryOperator::CreateXor(NOr, C1); + } + + // (A & C)|(B & D) + Value *C = 0, *D = 0; + if (match(Op0, m_And(m_Value(A), m_Value(C))) && + match(Op1, m_And(m_Value(B), m_Value(D)))) { + Value *V1 = 0, *V2 = 0, *V3 = 0; + C1 = dyn_cast(C); + C2 = dyn_cast(D); + if (C1 && C2) { // (A & C1)|(B & C2) + // If we have: ((V + N) & C1) | (V & C2) + // .. and C2 = ~C1 and C2 is 0+1+ and (N & C2) == 0 + // replace with V+N. + if (C1->getValue() == ~C2->getValue()) { + if ((C2->getValue() & (C2->getValue()+1)) == 0 && // C2 == 0+1+ + match(A, m_Add(m_Value(V1), m_Value(V2)))) { + // Add commutes, try both ways. + if (V1 == B && MaskedValueIsZero(V2, C2->getValue())) + return ReplaceInstUsesWith(I, A); + if (V2 == B && MaskedValueIsZero(V1, C2->getValue())) + return ReplaceInstUsesWith(I, A); + } + // Or commutes, try both ways. + if ((C1->getValue() & (C1->getValue()+1)) == 0 && + match(B, m_Add(m_Value(V1), m_Value(V2)))) { + // Add commutes, try both ways. + if (V1 == A && MaskedValueIsZero(V2, C1->getValue())) + return ReplaceInstUsesWith(I, B); + if (V2 == A && MaskedValueIsZero(V1, C1->getValue())) + return ReplaceInstUsesWith(I, B); + } + } + V1 = 0; V2 = 0; V3 = 0; + } + + // Check to see if we have any common things being and'ed. If so, find the + // terms for V1 & (V2|V3). + if (isOnlyUse(Op0) || isOnlyUse(Op1)) { + if (A == B) // (A & C)|(A & D) == A & (C|D) + V1 = A, V2 = C, V3 = D; + else if (A == D) // (A & C)|(B & A) == A & (B|C) + V1 = A, V2 = B, V3 = C; + else if (C == B) // (A & C)|(C & D) == C & (A|D) + V1 = C, V2 = A, V3 = D; + else if (C == D) // (A & C)|(B & C) == C & (A|B) + V1 = C, V2 = A, V3 = B; + + if (V1) { + Value *Or = Builder->CreateOr(V2, V3, "tmp"); + return BinaryOperator::CreateAnd(V1, Or); + } + } + + // (A & (C0?-1:0)) | (B & ~(C0?-1:0)) -> C0 ? A : B, and commuted variants + if (Instruction *Match = MatchSelectFromAndOr(A, B, C, D, Context)) + return Match; + if (Instruction *Match = MatchSelectFromAndOr(B, A, D, C, Context)) + return Match; + if (Instruction *Match = MatchSelectFromAndOr(C, B, A, D, Context)) + return Match; + if (Instruction *Match = MatchSelectFromAndOr(D, A, B, C, Context)) + return Match; + + // ((A&~B)|(~A&B)) -> A^B + if ((match(C, m_Not(m_Specific(D))) && + match(B, m_Not(m_Specific(A))))) + return BinaryOperator::CreateXor(A, D); + // ((~B&A)|(~A&B)) -> A^B + if ((match(A, m_Not(m_Specific(D))) && + match(B, m_Not(m_Specific(C))))) + return BinaryOperator::CreateXor(C, D); + // ((A&~B)|(B&~A)) -> A^B + if ((match(C, m_Not(m_Specific(B))) && + match(D, m_Not(m_Specific(A))))) + return BinaryOperator::CreateXor(A, B); + // ((~B&A)|(B&~A)) -> A^B + if ((match(A, m_Not(m_Specific(B))) && + match(D, m_Not(m_Specific(C))))) + return BinaryOperator::CreateXor(C, B); + } + + // (X >> Z) | (Y >> Z) -> (X|Y) >> Z for all shifts. + if (BinaryOperator *SI1 = dyn_cast(Op1)) { + if (BinaryOperator *SI0 = dyn_cast(Op0)) + if (SI0->isShift() && SI0->getOpcode() == SI1->getOpcode() && + SI0->getOperand(1) == SI1->getOperand(1) && + (SI0->hasOneUse() || SI1->hasOneUse())) { + Value *NewOp = Builder->CreateOr(SI0->getOperand(0), SI1->getOperand(0), + SI0->getName()); + return BinaryOperator::Create(SI1->getOpcode(), NewOp, + SI1->getOperand(1)); + } + } + + // ((A|B)&1)|(B&-2) -> (A&1) | B + if (match(Op0, m_And(m_Or(m_Value(A), m_Value(B)), m_Value(C))) || + match(Op0, m_And(m_Value(C), m_Or(m_Value(A), m_Value(B))))) { + Instruction *Ret = FoldOrWithConstants(I, Op1, A, B, C); + if (Ret) return Ret; + } + // (B&-2)|((A|B)&1) -> (A&1) | B + if (match(Op1, m_And(m_Or(m_Value(A), m_Value(B)), m_Value(C))) || + match(Op1, m_And(m_Value(C), m_Or(m_Value(A), m_Value(B))))) { + Instruction *Ret = FoldOrWithConstants(I, Op0, A, B, C); + if (Ret) return Ret; + } + + // (~A | ~B) == (~(A & B)) - De Morgan's Law + if (Value *Op0NotVal = dyn_castNotVal(Op0)) + if (Value *Op1NotVal = dyn_castNotVal(Op1)) + if (Op0->hasOneUse() && Op1->hasOneUse()) { + Value *And = Builder->CreateAnd(Op0NotVal, Op1NotVal, + I.getName()+".demorgan"); + return BinaryOperator::CreateNot(And); + } + + // (icmp1 A, B) | (icmp2 A, B) --> (icmp3 A, B) + if (ICmpInst *RHS = dyn_cast(I.getOperand(1))) { + if (Instruction *R = AssociativeOpt(I, FoldICmpLogical(*this, RHS))) + return R; + + if (ICmpInst *LHS = dyn_cast(I.getOperand(0))) + if (Instruction *Res = FoldOrOfICmps(I, LHS, RHS)) + return Res; + } + + // fold (or (cast A), (cast B)) -> (cast (or A, B)) + if (CastInst *Op0C = dyn_cast(Op0)) { + if (CastInst *Op1C = dyn_cast(Op1)) + if (Op0C->getOpcode() == Op1C->getOpcode()) {// same cast kind ? + if (!isa(Op0C->getOperand(0)) || + !isa(Op1C->getOperand(0))) { + const Type *SrcTy = Op0C->getOperand(0)->getType(); + if (SrcTy == Op1C->getOperand(0)->getType() && + SrcTy->isIntOrIntVector() && + // Only do this if the casts both really cause code to be + // generated. + ValueRequiresCast(Op0C->getOpcode(), Op0C->getOperand(0), + I.getType(), TD) && + ValueRequiresCast(Op1C->getOpcode(), Op1C->getOperand(0), + I.getType(), TD)) { + Value *NewOp = Builder->CreateOr(Op0C->getOperand(0), + Op1C->getOperand(0), I.getName()); + return CastInst::Create(Op0C->getOpcode(), NewOp, I.getType()); + } + } + } + } + + + // (fcmp uno x, c) | (fcmp uno y, c) -> (fcmp uno x, y) + if (FCmpInst *LHS = dyn_cast(I.getOperand(0))) { + if (FCmpInst *RHS = dyn_cast(I.getOperand(1))) + if (Instruction *Res = FoldOrOfFCmps(I, LHS, RHS)) + return Res; + } + + return Changed ? &I : 0; +} + +namespace { + +// XorSelf - Implements: X ^ X --> 0 +struct XorSelf { + Value *RHS; + XorSelf(Value *rhs) : RHS(rhs) {} + bool shouldApply(Value *LHS) const { return LHS == RHS; } + Instruction *apply(BinaryOperator &Xor) const { + return &Xor; + } +}; + +} + +Instruction *InstCombiner::visitXor(BinaryOperator &I) { + bool Changed = SimplifyCommutative(I); + Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1); + + if (isa(Op1)) { + if (isa(Op0)) + // Handle undef ^ undef -> 0 special case. This is a common + // idiom (misuse). + return ReplaceInstUsesWith(I, Constant::getNullValue(I.getType())); + return ReplaceInstUsesWith(I, Op1); // X ^ undef -> undef + } + + // xor X, X = 0, even if X is nested in a sequence of Xor's. + if (Instruction *Result = AssociativeOpt(I, XorSelf(Op1))) { + assert(Result == &I && "AssociativeOpt didn't work?"); Result=Result; + return ReplaceInstUsesWith(I, Constant::getNullValue(I.getType())); + } + + // See if we can simplify any instructions used by the instruction whose sole + // purpose is to compute bits we don't care about. + if (SimplifyDemandedInstructionBits(I)) + return &I; + if (isa(I.getType())) + if (isa(Op1)) + return ReplaceInstUsesWith(I, Op0); // X ^ <0,0> -> X + + // Is this a ~ operation? + if (Value *NotOp = dyn_castNotVal(&I)) { + if (BinaryOperator *Op0I = dyn_cast(NotOp)) { + if (Op0I->getOpcode() == Instruction::And || + Op0I->getOpcode() == Instruction::Or) { + // ~(~X & Y) --> (X | ~Y) - De Morgan's Law + // ~(~X | Y) === (X & ~Y) - De Morgan's Law + if (dyn_castNotVal(Op0I->getOperand(1))) + Op0I->swapOperands(); + if (Value *Op0NotVal = dyn_castNotVal(Op0I->getOperand(0))) { + Value *NotY = + Builder->CreateNot(Op0I->getOperand(1), + Op0I->getOperand(1)->getName()+".not"); + if (Op0I->getOpcode() == Instruction::And) + return BinaryOperator::CreateOr(Op0NotVal, NotY); + return BinaryOperator::CreateAnd(Op0NotVal, NotY); + } + + // ~(X & Y) --> (~X | ~Y) - De Morgan's Law + // ~(X | Y) === (~X & ~Y) - De Morgan's Law + if (isFreeToInvert(Op0I->getOperand(0)) && + isFreeToInvert(Op0I->getOperand(1))) { + Value *NotX = + Builder->CreateNot(Op0I->getOperand(0), "notlhs"); + Value *NotY = + Builder->CreateNot(Op0I->getOperand(1), "notrhs"); + if (Op0I->getOpcode() == Instruction::And) + return BinaryOperator::CreateOr(NotX, NotY); + return BinaryOperator::CreateAnd(NotX, NotY); + } + } + } + } + + + if (ConstantInt *RHS = dyn_cast(Op1)) { + if (RHS->isOne() && Op0->hasOneUse()) { + // xor (cmp A, B), true = not (cmp A, B) = !cmp A, B + if (ICmpInst *ICI = dyn_cast(Op0)) + return new ICmpInst(ICI->getInversePredicate(), + ICI->getOperand(0), ICI->getOperand(1)); + + if (FCmpInst *FCI = dyn_cast(Op0)) + return new FCmpInst(FCI->getInversePredicate(), + FCI->getOperand(0), FCI->getOperand(1)); + } + + // fold (xor(zext(cmp)), 1) and (xor(sext(cmp)), -1) to ext(!cmp). + if (CastInst *Op0C = dyn_cast(Op0)) { + if (CmpInst *CI = dyn_cast(Op0C->getOperand(0))) { + if (CI->hasOneUse() && Op0C->hasOneUse()) { + Instruction::CastOps Opcode = Op0C->getOpcode(); + if ((Opcode == Instruction::ZExt || Opcode == Instruction::SExt) && + (RHS == ConstantExpr::getCast(Opcode, + ConstantInt::getTrue(*Context), + Op0C->getDestTy()))) { + CI->setPredicate(CI->getInversePredicate()); + return CastInst::Create(Opcode, CI, Op0C->getType()); + } + } + } + } + + if (BinaryOperator *Op0I = dyn_cast(Op0)) { + // ~(c-X) == X-c-1 == X+(-c-1) + if (Op0I->getOpcode() == Instruction::Sub && RHS->isAllOnesValue()) + if (Constant *Op0I0C = dyn_cast(Op0I->getOperand(0))) { + Constant *NegOp0I0C = ConstantExpr::getNeg(Op0I0C); + Constant *ConstantRHS = ConstantExpr::getSub(NegOp0I0C, + ConstantInt::get(I.getType(), 1)); + return BinaryOperator::CreateAdd(Op0I->getOperand(1), ConstantRHS); + } + + if (ConstantInt *Op0CI = dyn_cast(Op0I->getOperand(1))) { + if (Op0I->getOpcode() == Instruction::Add) { + // ~(X-c) --> (-c-1)-X + if (RHS->isAllOnesValue()) { + Constant *NegOp0CI = ConstantExpr::getNeg(Op0CI); + return BinaryOperator::CreateSub( + ConstantExpr::getSub(NegOp0CI, + ConstantInt::get(I.getType(), 1)), + Op0I->getOperand(0)); + } else if (RHS->getValue().isSignBit()) { + // (X + C) ^ signbit -> (X + C + signbit) + Constant *C = ConstantInt::get(*Context, + RHS->getValue() + Op0CI->getValue()); + return BinaryOperator::CreateAdd(Op0I->getOperand(0), C); + + } + } else if (Op0I->getOpcode() == Instruction::Or) { + // (X|C1)^C2 -> X^(C1|C2) iff X&~C1 == 0 + if (MaskedValueIsZero(Op0I->getOperand(0), Op0CI->getValue())) { + Constant *NewRHS = ConstantExpr::getOr(Op0CI, RHS); + // Anything in both C1 and C2 is known to be zero, remove it from + // NewRHS. + Constant *CommonBits = ConstantExpr::getAnd(Op0CI, RHS); + NewRHS = ConstantExpr::getAnd(NewRHS, + ConstantExpr::getNot(CommonBits)); + Worklist.Add(Op0I); + I.setOperand(0, Op0I->getOperand(0)); + I.setOperand(1, NewRHS); + return &I; + } + } + } + } + + // Try to fold constant and into select arguments. + if (SelectInst *SI = dyn_cast(Op0)) + if (Instruction *R = FoldOpIntoSelect(I, SI, this)) + return R; + if (isa(Op0)) + if (Instruction *NV = FoldOpIntoPhi(I)) + return NV; + } + + if (Value *X = dyn_castNotVal(Op0)) // ~A ^ A == -1 + if (X == Op1) + return ReplaceInstUsesWith(I, Constant::getAllOnesValue(I.getType())); + + if (Value *X = dyn_castNotVal(Op1)) // A ^ ~A == -1 + if (X == Op0) + return ReplaceInstUsesWith(I, Constant::getAllOnesValue(I.getType())); + + + BinaryOperator *Op1I = dyn_cast(Op1); + if (Op1I) { + Value *A, *B; + if (match(Op1I, m_Or(m_Value(A), m_Value(B)))) { + if (A == Op0) { // B^(B|A) == (A|B)^B + Op1I->swapOperands(); + I.swapOperands(); + std::swap(Op0, Op1); + } else if (B == Op0) { // B^(A|B) == (A|B)^B + I.swapOperands(); // Simplified below. + std::swap(Op0, Op1); + } + } else if (match(Op1I, m_Xor(m_Specific(Op0), m_Value(B)))) { + return ReplaceInstUsesWith(I, B); // A^(A^B) == B + } else if (match(Op1I, m_Xor(m_Value(A), m_Specific(Op0)))) { + return ReplaceInstUsesWith(I, A); // A^(B^A) == B + } else if (match(Op1I, m_And(m_Value(A), m_Value(B))) && + Op1I->hasOneUse()){ + if (A == Op0) { // A^(A&B) -> A^(B&A) + Op1I->swapOperands(); + std::swap(A, B); + } + if (B == Op0) { // A^(B&A) -> (B&A)^A + I.swapOperands(); // Simplified below. + std::swap(Op0, Op1); + } + } + } + + BinaryOperator *Op0I = dyn_cast(Op0); + if (Op0I) { + Value *A, *B; + if (match(Op0I, m_Or(m_Value(A), m_Value(B))) && + Op0I->hasOneUse()) { + if (A == Op1) // (B|A)^B == (A|B)^B + std::swap(A, B); + if (B == Op1) // (A|B)^B == A & ~B + return BinaryOperator::CreateAnd(A, Builder->CreateNot(Op1, "tmp")); + } else if (match(Op0I, m_Xor(m_Specific(Op1), m_Value(B)))) { + return ReplaceInstUsesWith(I, B); // (A^B)^A == B + } else if (match(Op0I, m_Xor(m_Value(A), m_Specific(Op1)))) { + return ReplaceInstUsesWith(I, A); // (B^A)^A == B + } else if (match(Op0I, m_And(m_Value(A), m_Value(B))) && + Op0I->hasOneUse()){ + if (A == Op1) // (A&B)^A -> (B&A)^A + std::swap(A, B); + if (B == Op1 && // (B&A)^A == ~B & A + !isa(Op1)) { // Canonical form is (B&C)^C + return BinaryOperator::CreateAnd(Builder->CreateNot(A, "tmp"), Op1); + } + } + } + + // (X >> Z) ^ (Y >> Z) -> (X^Y) >> Z for all shifts. + if (Op0I && Op1I && Op0I->isShift() && + Op0I->getOpcode() == Op1I->getOpcode() && + Op0I->getOperand(1) == Op1I->getOperand(1) && + (Op1I->hasOneUse() || Op1I->hasOneUse())) { + Value *NewOp = + Builder->CreateXor(Op0I->getOperand(0), Op1I->getOperand(0), + Op0I->getName()); + return BinaryOperator::Create(Op1I->getOpcode(), NewOp, + Op1I->getOperand(1)); + } + + if (Op0I && Op1I) { + Value *A, *B, *C, *D; + // (A & B)^(A | B) -> A ^ B + if (match(Op0I, m_And(m_Value(A), m_Value(B))) && + match(Op1I, m_Or(m_Value(C), m_Value(D)))) { + if ((A == C && B == D) || (A == D && B == C)) + return BinaryOperator::CreateXor(A, B); + } + // (A | B)^(A & B) -> A ^ B + if (match(Op0I, m_Or(m_Value(A), m_Value(B))) && + match(Op1I, m_And(m_Value(C), m_Value(D)))) { + if ((A == C && B == D) || (A == D && B == C)) + return BinaryOperator::CreateXor(A, B); + } + + // (A & B)^(C & D) + if ((Op0I->hasOneUse() || Op1I->hasOneUse()) && + match(Op0I, m_And(m_Value(A), m_Value(B))) && + match(Op1I, m_And(m_Value(C), m_Value(D)))) { + // (X & Y)^(X & Y) -> (Y^Z) & X + Value *X = 0, *Y = 0, *Z = 0; + if (A == C) + X = A, Y = B, Z = D; + else if (A == D) + X = A, Y = B, Z = C; + else if (B == C) + X = B, Y = A, Z = D; + else if (B == D) + X = B, Y = A, Z = C; + + if (X) { + Value *NewOp = Builder->CreateXor(Y, Z, Op0->getName()); + return BinaryOperator::CreateAnd(NewOp, X); + } + } + } + + // (icmp1 A, B) ^ (icmp2 A, B) --> (icmp3 A, B) + if (ICmpInst *RHS = dyn_cast(I.getOperand(1))) + if (Instruction *R = AssociativeOpt(I, FoldICmpLogical(*this, RHS))) + return R; + + // fold (xor (cast A), (cast B)) -> (cast (xor A, B)) + if (CastInst *Op0C = dyn_cast(Op0)) { + if (CastInst *Op1C = dyn_cast(Op1)) + if (Op0C->getOpcode() == Op1C->getOpcode()) { // same cast kind? + const Type *SrcTy = Op0C->getOperand(0)->getType(); + if (SrcTy == Op1C->getOperand(0)->getType() && SrcTy->isInteger() && + // Only do this if the casts both really cause code to be generated. + ValueRequiresCast(Op0C->getOpcode(), Op0C->getOperand(0), + I.getType(), TD) && + ValueRequiresCast(Op1C->getOpcode(), Op1C->getOperand(0), + I.getType(), TD)) { + Value *NewOp = Builder->CreateXor(Op0C->getOperand(0), + Op1C->getOperand(0), I.getName()); + return CastInst::Create(Op0C->getOpcode(), NewOp, I.getType()); + } + } + } + + return Changed ? &I : 0; +} + +static ConstantInt *ExtractElement(Constant *V, Constant *Idx, + LLVMContext *Context) { + return cast(ConstantExpr::getExtractElement(V, Idx)); +} + +static bool HasAddOverflow(ConstantInt *Result, + ConstantInt *In1, ConstantInt *In2, + bool IsSigned) { + if (IsSigned) + if (In2->getValue().isNegative()) + return Result->getValue().sgt(In1->getValue()); + else + return Result->getValue().slt(In1->getValue()); + else + return Result->getValue().ult(In1->getValue()); +} + +/// AddWithOverflow - Compute Result = In1+In2, returning true if the result +/// overflowed for this type. +static bool AddWithOverflow(Constant *&Result, Constant *In1, + Constant *In2, LLVMContext *Context, + bool IsSigned = false) { + Result = ConstantExpr::getAdd(In1, In2); + + if (const VectorType *VTy = dyn_cast(In1->getType())) { + for (unsigned i = 0, e = VTy->getNumElements(); i != e; ++i) { + Constant *Idx = ConstantInt::get(Type::getInt32Ty(*Context), i); + if (HasAddOverflow(ExtractElement(Result, Idx, Context), + ExtractElement(In1, Idx, Context), + ExtractElement(In2, Idx, Context), + IsSigned)) + return true; + } + return false; + } + + return HasAddOverflow(cast(Result), + cast(In1), cast(In2), + IsSigned); +} + +static bool HasSubOverflow(ConstantInt *Result, + ConstantInt *In1, ConstantInt *In2, + bool IsSigned) { + if (IsSigned) + if (In2->getValue().isNegative()) + return Result->getValue().slt(In1->getValue()); + else + return Result->getValue().sgt(In1->getValue()); + else + return Result->getValue().ugt(In1->getValue()); +} + +/// SubWithOverflow - Compute Result = In1-In2, returning true if the result +/// overflowed for this type. +static bool SubWithOverflow(Constant *&Result, Constant *In1, + Constant *In2, LLVMContext *Context, + bool IsSigned = false) { + Result = ConstantExpr::getSub(In1, In2); + + if (const VectorType *VTy = dyn_cast(In1->getType())) { + for (unsigned i = 0, e = VTy->getNumElements(); i != e; ++i) { + Constant *Idx = ConstantInt::get(Type::getInt32Ty(*Context), i); + if (HasSubOverflow(ExtractElement(Result, Idx, Context), + ExtractElement(In1, Idx, Context), + ExtractElement(In2, Idx, Context), + IsSigned)) + return true; + } + return false; + } + + return HasSubOverflow(cast(Result), + cast(In1), cast(In2), + IsSigned); +} + + +/// FoldGEPICmp - Fold comparisons between a GEP instruction and something +/// else. At this point we know that the GEP is on the LHS of the comparison. +Instruction *InstCombiner::FoldGEPICmp(GEPOperator *GEPLHS, Value *RHS, + ICmpInst::Predicate Cond, + Instruction &I) { + // Look through bitcasts. + if (BitCastInst *BCI = dyn_cast(RHS)) + RHS = BCI->getOperand(0); + + Value *PtrBase = GEPLHS->getOperand(0); + if (TD && PtrBase == RHS && GEPLHS->isInBounds()) { + // ((gep Ptr, OFFSET) cmp Ptr) ---> (OFFSET cmp 0). + // This transformation (ignoring the base and scales) is valid because we + // know pointers can't overflow since the gep is inbounds. See if we can + // output an optimized form. + Value *Offset = EvaluateGEPOffsetExpression(GEPLHS, I, *this); + + // If not, synthesize the offset the hard way. + if (Offset == 0) + Offset = EmitGEPOffset(GEPLHS, *this); + return new ICmpInst(ICmpInst::getSignedPredicate(Cond), Offset, + Constant::getNullValue(Offset->getType())); + } else if (GEPOperator *GEPRHS = dyn_cast(RHS)) { + // If the base pointers are different, but the indices are the same, just + // compare the base pointer. + if (PtrBase != GEPRHS->getOperand(0)) { + bool IndicesTheSame = GEPLHS->getNumOperands()==GEPRHS->getNumOperands(); + IndicesTheSame &= GEPLHS->getOperand(0)->getType() == + GEPRHS->getOperand(0)->getType(); + if (IndicesTheSame) + for (unsigned i = 1, e = GEPLHS->getNumOperands(); i != e; ++i) + if (GEPLHS->getOperand(i) != GEPRHS->getOperand(i)) { + IndicesTheSame = false; + break; + } + + // If all indices are the same, just compare the base pointers. + if (IndicesTheSame) + return new ICmpInst(ICmpInst::getSignedPredicate(Cond), + GEPLHS->getOperand(0), GEPRHS->getOperand(0)); + + // Otherwise, the base pointers are different and the indices are + // different, bail out. + return 0; + } + + // If one of the GEPs has all zero indices, recurse. + bool AllZeros = true; + for (unsigned i = 1, e = GEPLHS->getNumOperands(); i != e; ++i) + if (!isa(GEPLHS->getOperand(i)) || + !cast(GEPLHS->getOperand(i))->isNullValue()) { + AllZeros = false; + break; + } + if (AllZeros) + return FoldGEPICmp(GEPRHS, GEPLHS->getOperand(0), + ICmpInst::getSwappedPredicate(Cond), I); + + // If the other GEP has all zero indices, recurse. + AllZeros = true; + for (unsigned i = 1, e = GEPRHS->getNumOperands(); i != e; ++i) + if (!isa(GEPRHS->getOperand(i)) || + !cast(GEPRHS->getOperand(i))->isNullValue()) { + AllZeros = false; + break; + } + if (AllZeros) + return FoldGEPICmp(GEPLHS, GEPRHS->getOperand(0), Cond, I); + + if (GEPLHS->getNumOperands() == GEPRHS->getNumOperands()) { + // If the GEPs only differ by one index, compare it. + unsigned NumDifferences = 0; // Keep track of # differences. + unsigned DiffOperand = 0; // The operand that differs. + for (unsigned i = 1, e = GEPRHS->getNumOperands(); i != e; ++i) + if (GEPLHS->getOperand(i) != GEPRHS->getOperand(i)) { + if (GEPLHS->getOperand(i)->getType()->getPrimitiveSizeInBits() != + GEPRHS->getOperand(i)->getType()->getPrimitiveSizeInBits()) { + // Irreconcilable differences. + NumDifferences = 2; + break; + } else { + if (NumDifferences++) break; + DiffOperand = i; + } + } + + if (NumDifferences == 0) // SAME GEP? + return ReplaceInstUsesWith(I, // No comparison is needed here. + ConstantInt::get(Type::getInt1Ty(*Context), + ICmpInst::isTrueWhenEqual(Cond))); + + else if (NumDifferences == 1) { + Value *LHSV = GEPLHS->getOperand(DiffOperand); + Value *RHSV = GEPRHS->getOperand(DiffOperand); + // Make sure we do a signed comparison here. + return new ICmpInst(ICmpInst::getSignedPredicate(Cond), LHSV, RHSV); + } + } + + // Only lower this if the icmp is the only user of the GEP or if we expect + // the result to fold to a constant! + if (TD && + (isa(GEPLHS) || GEPLHS->hasOneUse()) && + (isa(GEPRHS) || GEPRHS->hasOneUse())) { + // ((gep Ptr, OFFSET1) cmp (gep Ptr, OFFSET2) ---> (OFFSET1 cmp OFFSET2) + Value *L = EmitGEPOffset(GEPLHS, *this); + Value *R = EmitGEPOffset(GEPRHS, *this); + return new ICmpInst(ICmpInst::getSignedPredicate(Cond), L, R); + } + } + return 0; +} + +/// FoldFCmp_IntToFP_Cst - Fold fcmp ([us]itofp x, cst) if possible. +/// +Instruction *InstCombiner::FoldFCmp_IntToFP_Cst(FCmpInst &I, + Instruction *LHSI, + Constant *RHSC) { + if (!isa(RHSC)) return 0; + const APFloat &RHS = cast(RHSC)->getValueAPF(); + + // Get the width of the mantissa. We don't want to hack on conversions that + // might lose information from the integer, e.g. "i64 -> float" + int MantissaWidth = LHSI->getType()->getFPMantissaWidth(); + if (MantissaWidth == -1) return 0; // Unknown. + + // Check to see that the input is converted from an integer type that is small + // enough that preserves all bits. TODO: check here for "known" sign bits. + // This would allow us to handle (fptosi (x >>s 62) to float) if x is i64 f.e. + unsigned InputSize = LHSI->getOperand(0)->getType()->getScalarSizeInBits(); + + // If this is a uitofp instruction, we need an extra bit to hold the sign. + bool LHSUnsigned = isa(LHSI); + if (LHSUnsigned) + ++InputSize; + + // If the conversion would lose info, don't hack on this. + if ((int)InputSize > MantissaWidth) + return 0; + + // Otherwise, we can potentially simplify the comparison. We know that it + // will always come through as an integer value and we know the constant is + // not a NAN (it would have been previously simplified). + assert(!RHS.isNaN() && "NaN comparison not already folded!"); + + ICmpInst::Predicate Pred; + switch (I.getPredicate()) { + default: llvm_unreachable("Unexpected predicate!"); + case FCmpInst::FCMP_UEQ: + case FCmpInst::FCMP_OEQ: + Pred = ICmpInst::ICMP_EQ; + break; + case FCmpInst::FCMP_UGT: + case FCmpInst::FCMP_OGT: + Pred = LHSUnsigned ? ICmpInst::ICMP_UGT : ICmpInst::ICMP_SGT; + break; + case FCmpInst::FCMP_UGE: + case FCmpInst::FCMP_OGE: + Pred = LHSUnsigned ? ICmpInst::ICMP_UGE : ICmpInst::ICMP_SGE; + break; + case FCmpInst::FCMP_ULT: + case FCmpInst::FCMP_OLT: + Pred = LHSUnsigned ? ICmpInst::ICMP_ULT : ICmpInst::ICMP_SLT; + break; + case FCmpInst::FCMP_ULE: + case FCmpInst::FCMP_OLE: + Pred = LHSUnsigned ? ICmpInst::ICMP_ULE : ICmpInst::ICMP_SLE; + break; + case FCmpInst::FCMP_UNE: + case FCmpInst::FCMP_ONE: + Pred = ICmpInst::ICMP_NE; + break; + case FCmpInst::FCMP_ORD: + return ReplaceInstUsesWith(I, ConstantInt::getTrue(*Context)); + case FCmpInst::FCMP_UNO: + return ReplaceInstUsesWith(I, ConstantInt::getFalse(*Context)); + } + + const IntegerType *IntTy = cast(LHSI->getOperand(0)->getType()); + + // Now we know that the APFloat is a normal number, zero or inf. + + // See if the FP constant is too large for the integer. For example, + // comparing an i8 to 300.0. + unsigned IntWidth = IntTy->getScalarSizeInBits(); + + if (!LHSUnsigned) { + // If the RHS value is > SignedMax, fold the comparison. This handles +INF + // and large values. + APFloat SMax(RHS.getSemantics(), APFloat::fcZero, false); + SMax.convertFromAPInt(APInt::getSignedMaxValue(IntWidth), true, + APFloat::rmNearestTiesToEven); + if (SMax.compare(RHS) == APFloat::cmpLessThan) { // smax < 13123.0 + if (Pred == ICmpInst::ICMP_NE || Pred == ICmpInst::ICMP_SLT || + Pred == ICmpInst::ICMP_SLE) + return ReplaceInstUsesWith(I, ConstantInt::getTrue(*Context)); + return ReplaceInstUsesWith(I, ConstantInt::getFalse(*Context)); + } + } else { + // If the RHS value is > UnsignedMax, fold the comparison. This handles + // +INF and large values. + APFloat UMax(RHS.getSemantics(), APFloat::fcZero, false); + UMax.convertFromAPInt(APInt::getMaxValue(IntWidth), false, + APFloat::rmNearestTiesToEven); + if (UMax.compare(RHS) == APFloat::cmpLessThan) { // umax < 13123.0 + if (Pred == ICmpInst::ICMP_NE || Pred == ICmpInst::ICMP_ULT || + Pred == ICmpInst::ICMP_ULE) + return ReplaceInstUsesWith(I, ConstantInt::getTrue(*Context)); + return ReplaceInstUsesWith(I, ConstantInt::getFalse(*Context)); + } + } + + if (!LHSUnsigned) { + // See if the RHS value is < SignedMin. + APFloat SMin(RHS.getSemantics(), APFloat::fcZero, false); + SMin.convertFromAPInt(APInt::getSignedMinValue(IntWidth), true, + APFloat::rmNearestTiesToEven); + if (SMin.compare(RHS) == APFloat::cmpGreaterThan) { // smin > 12312.0 + if (Pred == ICmpInst::ICMP_NE || Pred == ICmpInst::ICMP_SGT || + Pred == ICmpInst::ICMP_SGE) + return ReplaceInstUsesWith(I, ConstantInt::getTrue(*Context)); + return ReplaceInstUsesWith(I, ConstantInt::getFalse(*Context)); + } + } + + // Okay, now we know that the FP constant fits in the range [SMIN, SMAX] or + // [0, UMAX], but it may still be fractional. See if it is fractional by + // casting the FP value to the integer value and back, checking for equality. + // Don't do this for zero, because -0.0 is not fractional. + Constant *RHSInt = LHSUnsigned + ? ConstantExpr::getFPToUI(RHSC, IntTy) + : ConstantExpr::getFPToSI(RHSC, IntTy); + if (!RHS.isZero()) { + bool Equal = LHSUnsigned + ? ConstantExpr::getUIToFP(RHSInt, RHSC->getType()) == RHSC + : ConstantExpr::getSIToFP(RHSInt, RHSC->getType()) == RHSC; + if (!Equal) { + // If we had a comparison against a fractional value, we have to adjust + // the compare predicate and sometimes the value. RHSC is rounded towards + // zero at this point. + switch (Pred) { + default: llvm_unreachable("Unexpected integer comparison!"); + case ICmpInst::ICMP_NE: // (float)int != 4.4 --> true + return ReplaceInstUsesWith(I, ConstantInt::getTrue(*Context)); + case ICmpInst::ICMP_EQ: // (float)int == 4.4 --> false + return ReplaceInstUsesWith(I, ConstantInt::getFalse(*Context)); + case ICmpInst::ICMP_ULE: + // (float)int <= 4.4 --> int <= 4 + // (float)int <= -4.4 --> false + if (RHS.isNegative()) + return ReplaceInstUsesWith(I, ConstantInt::getFalse(*Context)); + break; + case ICmpInst::ICMP_SLE: + // (float)int <= 4.4 --> int <= 4 + // (float)int <= -4.4 --> int < -4 + if (RHS.isNegative()) + Pred = ICmpInst::ICMP_SLT; + break; + case ICmpInst::ICMP_ULT: + // (float)int < -4.4 --> false + // (float)int < 4.4 --> int <= 4 + if (RHS.isNegative()) + return ReplaceInstUsesWith(I, ConstantInt::getFalse(*Context)); + Pred = ICmpInst::ICMP_ULE; + break; + case ICmpInst::ICMP_SLT: + // (float)int < -4.4 --> int < -4 + // (float)int < 4.4 --> int <= 4 + if (!RHS.isNegative()) + Pred = ICmpInst::ICMP_SLE; + break; + case ICmpInst::ICMP_UGT: + // (float)int > 4.4 --> int > 4 + // (float)int > -4.4 --> true + if (RHS.isNegative()) + return ReplaceInstUsesWith(I, ConstantInt::getTrue(*Context)); + break; + case ICmpInst::ICMP_SGT: + // (float)int > 4.4 --> int > 4 + // (float)int > -4.4 --> int >= -4 + if (RHS.isNegative()) + Pred = ICmpInst::ICMP_SGE; + break; + case ICmpInst::ICMP_UGE: + // (float)int >= -4.4 --> true + // (float)int >= 4.4 --> int > 4 + if (!RHS.isNegative()) + return ReplaceInstUsesWith(I, ConstantInt::getTrue(*Context)); + Pred = ICmpInst::ICMP_UGT; + break; + case ICmpInst::ICMP_SGE: + // (float)int >= -4.4 --> int >= -4 + // (float)int >= 4.4 --> int > 4 + if (!RHS.isNegative()) + Pred = ICmpInst::ICMP_SGT; + break; + } + } + } + + // Lower this FP comparison into an appropriate integer version of the + // comparison. + return new ICmpInst(Pred, LHSI->getOperand(0), RHSInt); +} + +Instruction *InstCombiner::visitFCmpInst(FCmpInst &I) { + bool Changed = false; + + /// Orders the operands of the compare so that they are listed from most + /// complex to least complex. This puts constants before unary operators, + /// before binary operators. + if (getComplexity(I.getOperand(0)) < getComplexity(I.getOperand(1))) { + I.swapOperands(); + Changed = true; + } + + Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1); + + if (Value *V = SimplifyFCmpInst(I.getPredicate(), Op0, Op1, TD)) + return ReplaceInstUsesWith(I, V); + + // Simplify 'fcmp pred X, X' + if (Op0 == Op1) { + switch (I.getPredicate()) { + default: llvm_unreachable("Unknown predicate!"); + case FCmpInst::FCMP_UNO: // True if unordered: isnan(X) | isnan(Y) + case FCmpInst::FCMP_ULT: // True if unordered or less than + case FCmpInst::FCMP_UGT: // True if unordered or greater than + case FCmpInst::FCMP_UNE: // True if unordered or not equal + // Canonicalize these to be 'fcmp uno %X, 0.0'. + I.setPredicate(FCmpInst::FCMP_UNO); + I.setOperand(1, Constant::getNullValue(Op0->getType())); + return &I; + + case FCmpInst::FCMP_ORD: // True if ordered (no nans) + case FCmpInst::FCMP_OEQ: // True if ordered and equal + case FCmpInst::FCMP_OGE: // True if ordered and greater than or equal + case FCmpInst::FCMP_OLE: // True if ordered and less than or equal + // Canonicalize these to be 'fcmp ord %X, 0.0'. + I.setPredicate(FCmpInst::FCMP_ORD); + I.setOperand(1, Constant::getNullValue(Op0->getType())); + return &I; + } + } + + // Handle fcmp with constant RHS + if (Constant *RHSC = dyn_cast(Op1)) { + if (Instruction *LHSI = dyn_cast(Op0)) + switch (LHSI->getOpcode()) { + case Instruction::PHI: + // Only fold fcmp into the PHI if the phi and fcmp are in the same + // block. If in the same block, we're encouraging jump threading. If + // not, we are just pessimizing the code by making an i1 phi. + if (LHSI->getParent() == I.getParent()) + if (Instruction *NV = FoldOpIntoPhi(I, true)) + return NV; + break; + case Instruction::SIToFP: + case Instruction::UIToFP: + if (Instruction *NV = FoldFCmp_IntToFP_Cst(I, LHSI, RHSC)) + return NV; + break; + case Instruction::Select: + // If either operand of the select is a constant, we can fold the + // comparison into the select arms, which will cause one to be + // constant folded and the select turned into a bitwise or. + Value *Op1 = 0, *Op2 = 0; + if (LHSI->hasOneUse()) { + if (Constant *C = dyn_cast(LHSI->getOperand(1))) { + // Fold the known value into the constant operand. + Op1 = ConstantExpr::getCompare(I.getPredicate(), C, RHSC); + // Insert a new FCmp of the other select operand. + Op2 = Builder->CreateFCmp(I.getPredicate(), + LHSI->getOperand(2), RHSC, I.getName()); + } else if (Constant *C = dyn_cast(LHSI->getOperand(2))) { + // Fold the known value into the constant operand. + Op2 = ConstantExpr::getCompare(I.getPredicate(), C, RHSC); + // Insert a new FCmp of the other select operand. + Op1 = Builder->CreateFCmp(I.getPredicate(), LHSI->getOperand(1), + RHSC, I.getName()); + } + } + + if (Op1) + return SelectInst::Create(LHSI->getOperand(0), Op1, Op2); + break; + } + } + + return Changed ? &I : 0; +} + +Instruction *InstCombiner::visitICmpInst(ICmpInst &I) { + bool Changed = false; + + /// Orders the operands of the compare so that they are listed from most + /// complex to least complex. This puts constants before unary operators, + /// before binary operators. + if (getComplexity(I.getOperand(0)) < getComplexity(I.getOperand(1))) { + I.swapOperands(); + Changed = true; + } + + Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1); + + if (Value *V = SimplifyICmpInst(I.getPredicate(), Op0, Op1, TD)) + return ReplaceInstUsesWith(I, V); + + const Type *Ty = Op0->getType(); + + // icmp's with boolean values can always be turned into bitwise operations + if (Ty == Type::getInt1Ty(*Context)) { + switch (I.getPredicate()) { + default: llvm_unreachable("Invalid icmp instruction!"); + case ICmpInst::ICMP_EQ: { // icmp eq i1 A, B -> ~(A^B) + Value *Xor = Builder->CreateXor(Op0, Op1, I.getName()+"tmp"); + return BinaryOperator::CreateNot(Xor); + } + case ICmpInst::ICMP_NE: // icmp eq i1 A, B -> A^B + return BinaryOperator::CreateXor(Op0, Op1); + + case ICmpInst::ICMP_UGT: + std::swap(Op0, Op1); // Change icmp ugt -> icmp ult + // FALL THROUGH + case ICmpInst::ICMP_ULT:{ // icmp ult i1 A, B -> ~A & B + Value *Not = Builder->CreateNot(Op0, I.getName()+"tmp"); + return BinaryOperator::CreateAnd(Not, Op1); + } + case ICmpInst::ICMP_SGT: + std::swap(Op0, Op1); // Change icmp sgt -> icmp slt + // FALL THROUGH + case ICmpInst::ICMP_SLT: { // icmp slt i1 A, B -> A & ~B + Value *Not = Builder->CreateNot(Op1, I.getName()+"tmp"); + return BinaryOperator::CreateAnd(Not, Op0); + } + case ICmpInst::ICMP_UGE: + std::swap(Op0, Op1); // Change icmp uge -> icmp ule + // FALL THROUGH + case ICmpInst::ICMP_ULE: { // icmp ule i1 A, B -> ~A | B + Value *Not = Builder->CreateNot(Op0, I.getName()+"tmp"); + return BinaryOperator::CreateOr(Not, Op1); + } + case ICmpInst::ICMP_SGE: + std::swap(Op0, Op1); // Change icmp sge -> icmp sle + // FALL THROUGH + case ICmpInst::ICMP_SLE: { // icmp sle i1 A, B -> A | ~B + Value *Not = Builder->CreateNot(Op1, I.getName()+"tmp"); + return BinaryOperator::CreateOr(Not, Op0); + } + } + } + + unsigned BitWidth = 0; + if (TD) + BitWidth = TD->getTypeSizeInBits(Ty->getScalarType()); + else if (Ty->isIntOrIntVector()) + BitWidth = Ty->getScalarSizeInBits(); + + bool isSignBit = false; + + // See if we are doing a comparison with a constant. + if (ConstantInt *CI = dyn_cast(Op1)) { + Value *A = 0, *B = 0; + + // (icmp ne/eq (sub A B) 0) -> (icmp ne/eq A, B) + if (I.isEquality() && CI->isNullValue() && + match(Op0, m_Sub(m_Value(A), m_Value(B)))) { + // (icmp cond A B) if cond is equality + return new ICmpInst(I.getPredicate(), A, B); + } + + // If we have an icmp le or icmp ge instruction, turn it into the + // appropriate icmp lt or icmp gt instruction. This allows us to rely on + // them being folded in the code below. The SimplifyICmpInst code has + // already handled the edge cases for us, so we just assert on them. + switch (I.getPredicate()) { + default: break; + case ICmpInst::ICMP_ULE: + assert(!CI->isMaxValue(false)); // A <=u MAX -> TRUE + return new ICmpInst(ICmpInst::ICMP_ULT, Op0, + AddOne(CI)); + case ICmpInst::ICMP_SLE: + assert(!CI->isMaxValue(true)); // A <=s MAX -> TRUE + return new ICmpInst(ICmpInst::ICMP_SLT, Op0, + AddOne(CI)); + case ICmpInst::ICMP_UGE: + assert(!CI->isMinValue(false)); // A >=u MIN -> TRUE + return new ICmpInst(ICmpInst::ICMP_UGT, Op0, + SubOne(CI)); + case ICmpInst::ICMP_SGE: + assert(!CI->isMinValue(true)); // A >=s MIN -> TRUE + return new ICmpInst(ICmpInst::ICMP_SGT, Op0, + SubOne(CI)); + } + + // If this comparison is a normal comparison, it demands all + // bits, if it is a sign bit comparison, it only demands the sign bit. + bool UnusedBit; + isSignBit = isSignBitCheck(I.getPredicate(), CI, UnusedBit); + } + + // See if we can fold the comparison based on range information we can get + // by checking whether bits are known to be zero or one in the input. + if (BitWidth != 0) { + APInt Op0KnownZero(BitWidth, 0), Op0KnownOne(BitWidth, 0); + APInt Op1KnownZero(BitWidth, 0), Op1KnownOne(BitWidth, 0); + + if (SimplifyDemandedBits(I.getOperandUse(0), + isSignBit ? APInt::getSignBit(BitWidth) + : APInt::getAllOnesValue(BitWidth), + Op0KnownZero, Op0KnownOne, 0)) + return &I; + if (SimplifyDemandedBits(I.getOperandUse(1), + APInt::getAllOnesValue(BitWidth), + Op1KnownZero, Op1KnownOne, 0)) + return &I; + + // Given the known and unknown bits, compute a range that the LHS could be + // in. Compute the Min, Max and RHS values based on the known bits. For the + // EQ and NE we use unsigned values. + APInt Op0Min(BitWidth, 0), Op0Max(BitWidth, 0); + APInt Op1Min(BitWidth, 0), Op1Max(BitWidth, 0); + if (I.isSigned()) { + ComputeSignedMinMaxValuesFromKnownBits(Op0KnownZero, Op0KnownOne, + Op0Min, Op0Max); + ComputeSignedMinMaxValuesFromKnownBits(Op1KnownZero, Op1KnownOne, + Op1Min, Op1Max); + } else { + ComputeUnsignedMinMaxValuesFromKnownBits(Op0KnownZero, Op0KnownOne, + Op0Min, Op0Max); + ComputeUnsignedMinMaxValuesFromKnownBits(Op1KnownZero, Op1KnownOne, + Op1Min, Op1Max); + } + + // If Min and Max are known to be the same, then SimplifyDemandedBits + // figured out that the LHS is a constant. Just constant fold this now so + // that code below can assume that Min != Max. + if (!isa(Op0) && Op0Min == Op0Max) + return new ICmpInst(I.getPredicate(), + ConstantInt::get(*Context, Op0Min), Op1); + if (!isa(Op1) && Op1Min == Op1Max) + return new ICmpInst(I.getPredicate(), Op0, + ConstantInt::get(*Context, Op1Min)); + + // Based on the range information we know about the LHS, see if we can + // simplify this comparison. For example, (x&4) < 8 is always true. + switch (I.getPredicate()) { + default: llvm_unreachable("Unknown icmp opcode!"); + case ICmpInst::ICMP_EQ: + if (Op0Max.ult(Op1Min) || Op0Min.ugt(Op1Max)) + return ReplaceInstUsesWith(I, ConstantInt::getFalse(*Context)); + break; + case ICmpInst::ICMP_NE: + if (Op0Max.ult(Op1Min) || Op0Min.ugt(Op1Max)) + return ReplaceInstUsesWith(I, ConstantInt::getTrue(*Context)); + break; + case ICmpInst::ICMP_ULT: + if (Op0Max.ult(Op1Min)) // A true if max(A) < min(B) + return ReplaceInstUsesWith(I, ConstantInt::getTrue(*Context)); + if (Op0Min.uge(Op1Max)) // A false if min(A) >= max(B) + return ReplaceInstUsesWith(I, ConstantInt::getFalse(*Context)); + if (Op1Min == Op0Max) // A A != B if max(A) == min(B) + return new ICmpInst(ICmpInst::ICMP_NE, Op0, Op1); + if (ConstantInt *CI = dyn_cast(Op1)) { + if (Op1Max == Op0Min+1) // A A == C-1 if min(A)+1 == C + return new ICmpInst(ICmpInst::ICMP_EQ, Op0, + SubOne(CI)); + + // (x (x >s -1) -> true if sign bit clear + if (CI->isMinValue(true)) + return new ICmpInst(ICmpInst::ICMP_SGT, Op0, + Constant::getAllOnesValue(Op0->getType())); + } + break; + case ICmpInst::ICMP_UGT: + if (Op0Min.ugt(Op1Max)) // A >u B -> true if min(A) > max(B) + return ReplaceInstUsesWith(I, ConstantInt::getTrue(*Context)); + if (Op0Max.ule(Op1Min)) // A >u B -> false if max(A) <= max(B) + return ReplaceInstUsesWith(I, ConstantInt::getFalse(*Context)); + + if (Op1Max == Op0Min) // A >u B -> A != B if min(A) == max(B) + return new ICmpInst(ICmpInst::ICMP_NE, Op0, Op1); + if (ConstantInt *CI = dyn_cast(Op1)) { + if (Op1Min == Op0Max-1) // A >u C -> A == C+1 if max(a)-1 == C + return new ICmpInst(ICmpInst::ICMP_EQ, Op0, + AddOne(CI)); + + // (x >u 2147483647) -> (x true if sign bit set + if (CI->isMaxValue(true)) + return new ICmpInst(ICmpInst::ICMP_SLT, Op0, + Constant::getNullValue(Op0->getType())); + } + break; + case ICmpInst::ICMP_SLT: + if (Op0Max.slt(Op1Min)) // A true if max(A) < min(C) + return ReplaceInstUsesWith(I, ConstantInt::getTrue(*Context)); + if (Op0Min.sge(Op1Max)) // A false if min(A) >= max(C) + return ReplaceInstUsesWith(I, ConstantInt::getFalse(*Context)); + if (Op1Min == Op0Max) // A A != B if max(A) == min(B) + return new ICmpInst(ICmpInst::ICMP_NE, Op0, Op1); + if (ConstantInt *CI = dyn_cast(Op1)) { + if (Op1Max == Op0Min+1) // A A == C-1 if min(A)+1 == C + return new ICmpInst(ICmpInst::ICMP_EQ, Op0, + SubOne(CI)); + } + break; + case ICmpInst::ICMP_SGT: + if (Op0Min.sgt(Op1Max)) // A >s B -> true if min(A) > max(B) + return ReplaceInstUsesWith(I, ConstantInt::getTrue(*Context)); + if (Op0Max.sle(Op1Min)) // A >s B -> false if max(A) <= min(B) + return ReplaceInstUsesWith(I, ConstantInt::getFalse(*Context)); + + if (Op1Max == Op0Min) // A >s B -> A != B if min(A) == max(B) + return new ICmpInst(ICmpInst::ICMP_NE, Op0, Op1); + if (ConstantInt *CI = dyn_cast(Op1)) { + if (Op1Min == Op0Max-1) // A >s C -> A == C+1 if max(A)-1 == C + return new ICmpInst(ICmpInst::ICMP_EQ, Op0, + AddOne(CI)); + } + break; + case ICmpInst::ICMP_SGE: + assert(!isa(Op1) && "ICMP_SGE with ConstantInt not folded!"); + if (Op0Min.sge(Op1Max)) // A >=s B -> true if min(A) >= max(B) + return ReplaceInstUsesWith(I, ConstantInt::getTrue(*Context)); + if (Op0Max.slt(Op1Min)) // A >=s B -> false if max(A) < min(B) + return ReplaceInstUsesWith(I, ConstantInt::getFalse(*Context)); + break; + case ICmpInst::ICMP_SLE: + assert(!isa(Op1) && "ICMP_SLE with ConstantInt not folded!"); + if (Op0Max.sle(Op1Min)) // A <=s B -> true if max(A) <= min(B) + return ReplaceInstUsesWith(I, ConstantInt::getTrue(*Context)); + if (Op0Min.sgt(Op1Max)) // A <=s B -> false if min(A) > max(B) + return ReplaceInstUsesWith(I, ConstantInt::getFalse(*Context)); + break; + case ICmpInst::ICMP_UGE: + assert(!isa(Op1) && "ICMP_UGE with ConstantInt not folded!"); + if (Op0Min.uge(Op1Max)) // A >=u B -> true if min(A) >= max(B) + return ReplaceInstUsesWith(I, ConstantInt::getTrue(*Context)); + if (Op0Max.ult(Op1Min)) // A >=u B -> false if max(A) < min(B) + return ReplaceInstUsesWith(I, ConstantInt::getFalse(*Context)); + break; + case ICmpInst::ICMP_ULE: + assert(!isa(Op1) && "ICMP_ULE with ConstantInt not folded!"); + if (Op0Max.ule(Op1Min)) // A <=u B -> true if max(A) <= min(B) + return ReplaceInstUsesWith(I, ConstantInt::getTrue(*Context)); + if (Op0Min.ugt(Op1Max)) // A <=u B -> false if min(A) > max(B) + return ReplaceInstUsesWith(I, ConstantInt::getFalse(*Context)); + break; + } + + // Turn a signed comparison into an unsigned one if both operands + // are known to have the same sign. + if (I.isSigned() && + ((Op0KnownZero.isNegative() && Op1KnownZero.isNegative()) || + (Op0KnownOne.isNegative() && Op1KnownOne.isNegative()))) + return new ICmpInst(I.getUnsignedPredicate(), Op0, Op1); + } + + // Test if the ICmpInst instruction is used exclusively by a select as + // part of a minimum or maximum operation. If so, refrain from doing + // any other folding. This helps out other analyses which understand + // non-obfuscated minimum and maximum idioms, such as ScalarEvolution + // and CodeGen. And in this case, at least one of the comparison + // operands has at least one user besides the compare (the select), + // which would often largely negate the benefit of folding anyway. + if (I.hasOneUse()) + if (SelectInst *SI = dyn_cast(*I.use_begin())) + if ((SI->getOperand(1) == Op0 && SI->getOperand(2) == Op1) || + (SI->getOperand(2) == Op0 && SI->getOperand(1) == Op1)) + return 0; + + // See if we are doing a comparison between a constant and an instruction that + // can be folded into the comparison. + if (ConstantInt *CI = dyn_cast(Op1)) { + // Since the RHS is a ConstantInt (CI), if the left hand side is an + // instruction, see if that instruction also has constants so that the + // instruction can be folded into the icmp + if (Instruction *LHSI = dyn_cast(Op0)) + if (Instruction *Res = visitICmpInstWithInstAndIntCst(I, LHSI, CI)) + return Res; + } + + // Handle icmp with constant (but not simple integer constant) RHS + if (Constant *RHSC = dyn_cast(Op1)) { + if (Instruction *LHSI = dyn_cast(Op0)) + switch (LHSI->getOpcode()) { + case Instruction::GetElementPtr: + if (RHSC->isNullValue()) { + // icmp pred GEP (P, int 0, int 0, int 0), null -> icmp pred P, null + bool isAllZeros = true; + for (unsigned i = 1, e = LHSI->getNumOperands(); i != e; ++i) + if (!isa(LHSI->getOperand(i)) || + !cast(LHSI->getOperand(i))->isNullValue()) { + isAllZeros = false; + break; + } + if (isAllZeros) + return new ICmpInst(I.getPredicate(), LHSI->getOperand(0), + Constant::getNullValue(LHSI->getOperand(0)->getType())); + } + break; + + case Instruction::PHI: + // Only fold icmp into the PHI if the phi and icmp are in the same + // block. If in the same block, we're encouraging jump threading. If + // not, we are just pessimizing the code by making an i1 phi. + if (LHSI->getParent() == I.getParent()) + if (Instruction *NV = FoldOpIntoPhi(I, true)) + return NV; + break; + case Instruction::Select: { + // If either operand of the select is a constant, we can fold the + // comparison into the select arms, which will cause one to be + // constant folded and the select turned into a bitwise or. + Value *Op1 = 0, *Op2 = 0; + if (LHSI->hasOneUse()) { + if (Constant *C = dyn_cast(LHSI->getOperand(1))) { + // Fold the known value into the constant operand. + Op1 = ConstantExpr::getICmp(I.getPredicate(), C, RHSC); + // Insert a new ICmp of the other select operand. + Op2 = Builder->CreateICmp(I.getPredicate(), LHSI->getOperand(2), + RHSC, I.getName()); + } else if (Constant *C = dyn_cast(LHSI->getOperand(2))) { + // Fold the known value into the constant operand. + Op2 = ConstantExpr::getICmp(I.getPredicate(), C, RHSC); + // Insert a new ICmp of the other select operand. + Op1 = Builder->CreateICmp(I.getPredicate(), LHSI->getOperand(1), + RHSC, I.getName()); + } + } + + if (Op1) + return SelectInst::Create(LHSI->getOperand(0), Op1, Op2); + break; + } + case Instruction::Call: + // If we have (malloc != null), and if the malloc has a single use, we + // can assume it is successful and remove the malloc. + if (isMalloc(LHSI) && LHSI->hasOneUse() && + isa(RHSC)) { + // Need to explicitly erase malloc call here, instead of adding it to + // Worklist, because it won't get DCE'd from the Worklist since + // isInstructionTriviallyDead() returns false for function calls. + // It is OK to replace LHSI/MallocCall with Undef because the + // instruction that uses it will be erased via Worklist. + if (extractMallocCall(LHSI)) { + LHSI->replaceAllUsesWith(UndefValue::get(LHSI->getType())); + EraseInstFromFunction(*LHSI); + return ReplaceInstUsesWith(I, + ConstantInt::get(Type::getInt1Ty(*Context), + !I.isTrueWhenEqual())); + } + if (CallInst* MallocCall = extractMallocCallFromBitCast(LHSI)) + if (MallocCall->hasOneUse()) { + MallocCall->replaceAllUsesWith( + UndefValue::get(MallocCall->getType())); + EraseInstFromFunction(*MallocCall); + Worklist.Add(LHSI); // The malloc's bitcast use. + return ReplaceInstUsesWith(I, + ConstantInt::get(Type::getInt1Ty(*Context), + !I.isTrueWhenEqual())); + } + } + break; + } + } + + // If we can optimize a 'icmp GEP, P' or 'icmp P, GEP', do so now. + if (GEPOperator *GEP = dyn_cast(Op0)) + if (Instruction *NI = FoldGEPICmp(GEP, Op1, I.getPredicate(), I)) + return NI; + if (GEPOperator *GEP = dyn_cast(Op1)) + if (Instruction *NI = FoldGEPICmp(GEP, Op0, + ICmpInst::getSwappedPredicate(I.getPredicate()), I)) + return NI; + + // Test to see if the operands of the icmp are casted versions of other + // values. If the ptr->ptr cast can be stripped off both arguments, we do so + // now. + if (BitCastInst *CI = dyn_cast(Op0)) { + if (isa(Op0->getType()) && + (isa(Op1) || isa(Op1))) { + // We keep moving the cast from the left operand over to the right + // operand, where it can often be eliminated completely. + Op0 = CI->getOperand(0); + + // If operand #1 is a bitcast instruction, it must also be a ptr->ptr cast + // so eliminate it as well. + if (BitCastInst *CI2 = dyn_cast(Op1)) + Op1 = CI2->getOperand(0); + + // If Op1 is a constant, we can fold the cast into the constant. + if (Op0->getType() != Op1->getType()) { + if (Constant *Op1C = dyn_cast(Op1)) { + Op1 = ConstantExpr::getBitCast(Op1C, Op0->getType()); + } else { + // Otherwise, cast the RHS right before the icmp + Op1 = Builder->CreateBitCast(Op1, Op0->getType()); + } + } + return new ICmpInst(I.getPredicate(), Op0, Op1); + } + } + + if (isa(Op0)) { + // Handle the special case of: icmp (cast bool to X), + // This comes up when you have code like + // int X = A < B; + // if (X) ... + // For generality, we handle any zero-extension of any operand comparison + // with a constant or another cast from the same type. + if (isa(Op1) || isa(Op1)) + if (Instruction *R = visitICmpInstWithCastAndCast(I)) + return R; + } + + // See if it's the same type of instruction on the left and right. + if (BinaryOperator *Op0I = dyn_cast(Op0)) { + if (BinaryOperator *Op1I = dyn_cast(Op1)) { + if (Op0I->getOpcode() == Op1I->getOpcode() && Op0I->hasOneUse() && + Op1I->hasOneUse() && Op0I->getOperand(1) == Op1I->getOperand(1)) { + switch (Op0I->getOpcode()) { + default: break; + case Instruction::Add: + case Instruction::Sub: + case Instruction::Xor: + if (I.isEquality()) // a+x icmp eq/ne b+x --> a icmp b + return new ICmpInst(I.getPredicate(), Op0I->getOperand(0), + Op1I->getOperand(0)); + // icmp u/s (a ^ signbit), (b ^ signbit) --> icmp s/u a, b + if (ConstantInt *CI = dyn_cast(Op0I->getOperand(1))) { + if (CI->getValue().isSignBit()) { + ICmpInst::Predicate Pred = I.isSigned() + ? I.getUnsignedPredicate() + : I.getSignedPredicate(); + return new ICmpInst(Pred, Op0I->getOperand(0), + Op1I->getOperand(0)); + } + + if (CI->getValue().isMaxSignedValue()) { + ICmpInst::Predicate Pred = I.isSigned() + ? I.getUnsignedPredicate() + : I.getSignedPredicate(); + Pred = I.getSwappedPredicate(Pred); + return new ICmpInst(Pred, Op0I->getOperand(0), + Op1I->getOperand(0)); + } + } + break; + case Instruction::Mul: + if (!I.isEquality()) + break; + + if (ConstantInt *CI = dyn_cast(Op0I->getOperand(1))) { + // a * Cst icmp eq/ne b * Cst --> a & Mask icmp b & Mask + // Mask = -1 >> count-trailing-zeros(Cst). + if (!CI->isZero() && !CI->isOne()) { + const APInt &AP = CI->getValue(); + ConstantInt *Mask = ConstantInt::get(*Context, + APInt::getLowBitsSet(AP.getBitWidth(), + AP.getBitWidth() - + AP.countTrailingZeros())); + Value *And1 = Builder->CreateAnd(Op0I->getOperand(0), Mask); + Value *And2 = Builder->CreateAnd(Op1I->getOperand(0), Mask); + return new ICmpInst(I.getPredicate(), And1, And2); + } + } + break; + } + } + } + } + + // ~x < ~y --> y < x + { Value *A, *B; + if (match(Op0, m_Not(m_Value(A))) && + match(Op1, m_Not(m_Value(B)))) + return new ICmpInst(I.getPredicate(), B, A); + } + + if (I.isEquality()) { + Value *A, *B, *C, *D; + + // -x == -y --> x == y + if (match(Op0, m_Neg(m_Value(A))) && + match(Op1, m_Neg(m_Value(B)))) + return new ICmpInst(I.getPredicate(), A, B); + + if (match(Op0, m_Xor(m_Value(A), m_Value(B)))) { + if (A == Op1 || B == Op1) { // (A^B) == A -> B == 0 + Value *OtherVal = A == Op1 ? B : A; + return new ICmpInst(I.getPredicate(), OtherVal, + Constant::getNullValue(A->getType())); + } + + if (match(Op1, m_Xor(m_Value(C), m_Value(D)))) { + // A^c1 == C^c2 --> A == C^(c1^c2) + ConstantInt *C1, *C2; + if (match(B, m_ConstantInt(C1)) && + match(D, m_ConstantInt(C2)) && Op1->hasOneUse()) { + Constant *NC = + ConstantInt::get(*Context, C1->getValue() ^ C2->getValue()); + Value *Xor = Builder->CreateXor(C, NC, "tmp"); + return new ICmpInst(I.getPredicate(), A, Xor); + } + + // A^B == A^D -> B == D + if (A == C) return new ICmpInst(I.getPredicate(), B, D); + if (A == D) return new ICmpInst(I.getPredicate(), B, C); + if (B == C) return new ICmpInst(I.getPredicate(), A, D); + if (B == D) return new ICmpInst(I.getPredicate(), A, C); + } + } + + if (match(Op1, m_Xor(m_Value(A), m_Value(B))) && + (A == Op0 || B == Op0)) { + // A == (A^B) -> B == 0 + Value *OtherVal = A == Op0 ? B : A; + return new ICmpInst(I.getPredicate(), OtherVal, + Constant::getNullValue(A->getType())); + } + + // (A-B) == A -> B == 0 + if (match(Op0, m_Sub(m_Specific(Op1), m_Value(B)))) + return new ICmpInst(I.getPredicate(), B, + Constant::getNullValue(B->getType())); + + // A == (A-B) -> B == 0 + if (match(Op1, m_Sub(m_Specific(Op0), m_Value(B)))) + return new ICmpInst(I.getPredicate(), B, + Constant::getNullValue(B->getType())); + + // (X&Z) == (Y&Z) -> (X^Y) & Z == 0 + if (Op0->hasOneUse() && Op1->hasOneUse() && + match(Op0, m_And(m_Value(A), m_Value(B))) && + match(Op1, m_And(m_Value(C), m_Value(D)))) { + Value *X = 0, *Y = 0, *Z = 0; + + if (A == C) { + X = B; Y = D; Z = A; + } else if (A == D) { + X = B; Y = C; Z = A; + } else if (B == C) { + X = A; Y = D; Z = B; + } else if (B == D) { + X = A; Y = C; Z = B; + } + + if (X) { // Build (X^Y) & Z + Op1 = Builder->CreateXor(X, Y, "tmp"); + Op1 = Builder->CreateAnd(Op1, Z, "tmp"); + I.setOperand(0, Op1); + I.setOperand(1, Constant::getNullValue(Op1->getType())); + return &I; + } + } + } + return Changed ? &I : 0; +} + + +/// FoldICmpDivCst - Fold "icmp pred, ([su]div X, DivRHS), CmpRHS" where DivRHS +/// and CmpRHS are both known to be integer constants. +Instruction *InstCombiner::FoldICmpDivCst(ICmpInst &ICI, BinaryOperator *DivI, + ConstantInt *DivRHS) { + ConstantInt *CmpRHS = cast(ICI.getOperand(1)); + const APInt &CmpRHSV = CmpRHS->getValue(); + + // FIXME: If the operand types don't match the type of the divide + // then don't attempt this transform. The code below doesn't have the + // logic to deal with a signed divide and an unsigned compare (and + // vice versa). This is because (x /s C1) getOpcode() == Instruction::SDiv; + if (!ICI.isEquality() && DivIsSigned != ICI.isSigned()) + return 0; + if (DivRHS->isZero()) + return 0; // The ProdOV computation fails on divide by zero. + if (DivIsSigned && DivRHS->isAllOnesValue()) + return 0; // The overflow computation also screws up here + if (DivRHS->isOne()) + return 0; // Not worth bothering, and eliminates some funny cases + // with INT_MIN. + + // Compute Prod = CI * DivRHS. We are essentially solving an equation + // of form X/C1=C2. We solve for X by multiplying C1 (DivRHS) and + // C2 (CI). By solving for X we can turn this into a range check + // instead of computing a divide. + Constant *Prod = ConstantExpr::getMul(CmpRHS, DivRHS); + + // Determine if the product overflows by seeing if the product is + // not equal to the divide. Make sure we do the same kind of divide + // as in the LHS instruction that we're folding. + bool ProdOV = (DivIsSigned ? ConstantExpr::getSDiv(Prod, DivRHS) : + ConstantExpr::getUDiv(Prod, DivRHS)) != CmpRHS; + + // Get the ICmp opcode + ICmpInst::Predicate Pred = ICI.getPredicate(); + + // Figure out the interval that is being checked. For example, a comparison + // like "X /u 5 == 0" is really checking that X is in the interval [0, 5). + // Compute this interval based on the constants involved and the signedness of + // the compare/divide. This computes a half-open interval, keeping track of + // whether either value in the interval overflows. After analysis each + // overflow variable is set to 0 if it's corresponding bound variable is valid + // -1 if overflowed off the bottom end, or +1 if overflowed off the top end. + int LoOverflow = 0, HiOverflow = 0; + Constant *LoBound = 0, *HiBound = 0; + + if (!DivIsSigned) { // udiv + // e.g. X/5 op 3 --> [15, 20) + LoBound = Prod; + HiOverflow = LoOverflow = ProdOV; + if (!HiOverflow) + HiOverflow = AddWithOverflow(HiBound, LoBound, DivRHS, Context, false); + } else if (DivRHS->getValue().isStrictlyPositive()) { // Divisor is > 0. + if (CmpRHSV == 0) { // (X / pos) op 0 + // Can't overflow. e.g. X/2 op 0 --> [-1, 2) + LoBound = cast(ConstantExpr::getNeg(SubOne(DivRHS))); + HiBound = DivRHS; + } else if (CmpRHSV.isStrictlyPositive()) { // (X / pos) op pos + LoBound = Prod; // e.g. X/5 op 3 --> [15, 20) + HiOverflow = LoOverflow = ProdOV; + if (!HiOverflow) + HiOverflow = AddWithOverflow(HiBound, Prod, DivRHS, Context, true); + } else { // (X / pos) op neg + // e.g. X/5 op -3 --> [-15-4, -15+1) --> [-19, -14) + HiBound = AddOne(Prod); + LoOverflow = HiOverflow = ProdOV ? -1 : 0; + if (!LoOverflow) { + ConstantInt* DivNeg = + cast(ConstantExpr::getNeg(DivRHS)); + LoOverflow = AddWithOverflow(LoBound, HiBound, DivNeg, Context, + true) ? -1 : 0; + } + } + } else if (DivRHS->getValue().isNegative()) { // Divisor is < 0. + if (CmpRHSV == 0) { // (X / neg) op 0 + // e.g. X/-5 op 0 --> [-4, 5) + LoBound = AddOne(DivRHS); + HiBound = cast(ConstantExpr::getNeg(DivRHS)); + if (HiBound == DivRHS) { // -INTMIN = INTMIN + HiOverflow = 1; // [INTMIN+1, overflow) + HiBound = 0; // e.g. X/INTMIN = 0 --> X > INTMIN + } + } else if (CmpRHSV.isStrictlyPositive()) { // (X / neg) op pos + // e.g. X/-5 op 3 --> [-19, -14) + HiBound = AddOne(Prod); + HiOverflow = LoOverflow = ProdOV ? -1 : 0; + if (!LoOverflow) + LoOverflow = AddWithOverflow(LoBound, HiBound, + DivRHS, Context, true) ? -1 : 0; + } else { // (X / neg) op neg + LoBound = Prod; // e.g. X/-5 op -3 --> [15, 20) + LoOverflow = HiOverflow = ProdOV; + if (!HiOverflow) + HiOverflow = SubWithOverflow(HiBound, Prod, DivRHS, Context, true); + } + + // Dividing by a negative swaps the condition. LT <-> GT + Pred = ICmpInst::getSwappedPredicate(Pred); + } + + Value *X = DivI->getOperand(0); + switch (Pred) { + default: llvm_unreachable("Unhandled icmp opcode!"); + case ICmpInst::ICMP_EQ: + if (LoOverflow && HiOverflow) + return ReplaceInstUsesWith(ICI, ConstantInt::getFalse(*Context)); + else if (HiOverflow) + return new ICmpInst(DivIsSigned ? ICmpInst::ICMP_SGE : + ICmpInst::ICMP_UGE, X, LoBound); + else if (LoOverflow) + return new ICmpInst(DivIsSigned ? ICmpInst::ICMP_SLT : + ICmpInst::ICMP_ULT, X, HiBound); + else + return InsertRangeTest(X, LoBound, HiBound, DivIsSigned, true, ICI); + case ICmpInst::ICMP_NE: + if (LoOverflow && HiOverflow) + return ReplaceInstUsesWith(ICI, ConstantInt::getTrue(*Context)); + else if (HiOverflow) + return new ICmpInst(DivIsSigned ? ICmpInst::ICMP_SLT : + ICmpInst::ICMP_ULT, X, LoBound); + else if (LoOverflow) + return new ICmpInst(DivIsSigned ? ICmpInst::ICMP_SGE : + ICmpInst::ICMP_UGE, X, HiBound); + else + return InsertRangeTest(X, LoBound, HiBound, DivIsSigned, false, ICI); + case ICmpInst::ICMP_ULT: + case ICmpInst::ICMP_SLT: + if (LoOverflow == +1) // Low bound is greater than input range. + return ReplaceInstUsesWith(ICI, ConstantInt::getTrue(*Context)); + if (LoOverflow == -1) // Low bound is less than input range. + return ReplaceInstUsesWith(ICI, ConstantInt::getFalse(*Context)); + return new ICmpInst(Pred, X, LoBound); + case ICmpInst::ICMP_UGT: + case ICmpInst::ICMP_SGT: + if (HiOverflow == +1) // High bound greater than input range. + return ReplaceInstUsesWith(ICI, ConstantInt::getFalse(*Context)); + else if (HiOverflow == -1) // High bound less than input range. + return ReplaceInstUsesWith(ICI, ConstantInt::getTrue(*Context)); + if (Pred == ICmpInst::ICMP_UGT) + return new ICmpInst(ICmpInst::ICMP_UGE, X, HiBound); + else + return new ICmpInst(ICmpInst::ICMP_SGE, X, HiBound); + } +} + + +/// visitICmpInstWithInstAndIntCst - Handle "icmp (instr, intcst)". +/// +Instruction *InstCombiner::visitICmpInstWithInstAndIntCst(ICmpInst &ICI, + Instruction *LHSI, + ConstantInt *RHS) { + const APInt &RHSV = RHS->getValue(); + + switch (LHSI->getOpcode()) { + case Instruction::Trunc: + if (ICI.isEquality() && LHSI->hasOneUse()) { + // Simplify icmp eq (trunc x to i8), 42 -> icmp eq x, 42|highbits if all + // of the high bits truncated out of x are known. + unsigned DstBits = LHSI->getType()->getPrimitiveSizeInBits(), + SrcBits = LHSI->getOperand(0)->getType()->getPrimitiveSizeInBits(); + APInt Mask(APInt::getHighBitsSet(SrcBits, SrcBits-DstBits)); + APInt KnownZero(SrcBits, 0), KnownOne(SrcBits, 0); + ComputeMaskedBits(LHSI->getOperand(0), Mask, KnownZero, KnownOne); + + // If all the high bits are known, we can do this xform. + if ((KnownZero|KnownOne).countLeadingOnes() >= SrcBits-DstBits) { + // Pull in the high bits from known-ones set. + APInt NewRHS(RHS->getValue()); + NewRHS.zext(SrcBits); + NewRHS |= KnownOne; + return new ICmpInst(ICI.getPredicate(), LHSI->getOperand(0), + ConstantInt::get(*Context, NewRHS)); + } + } + break; + + case Instruction::Xor: // (icmp pred (xor X, XorCST), CI) + if (ConstantInt *XorCST = dyn_cast(LHSI->getOperand(1))) { + // If this is a comparison that tests the signbit (X < 0) or (x > -1), + // fold the xor. + if ((ICI.getPredicate() == ICmpInst::ICMP_SLT && RHSV == 0) || + (ICI.getPredicate() == ICmpInst::ICMP_SGT && RHSV.isAllOnesValue())) { + Value *CompareVal = LHSI->getOperand(0); + + // If the sign bit of the XorCST is not set, there is no change to + // the operation, just stop using the Xor. + if (!XorCST->getValue().isNegative()) { + ICI.setOperand(0, CompareVal); + Worklist.Add(LHSI); + return &ICI; + } + + // Was the old condition true if the operand is positive? + bool isTrueIfPositive = ICI.getPredicate() == ICmpInst::ICMP_SGT; + + // If so, the new one isn't. + isTrueIfPositive ^= true; + + if (isTrueIfPositive) + return new ICmpInst(ICmpInst::ICMP_SGT, CompareVal, + SubOne(RHS)); + else + return new ICmpInst(ICmpInst::ICMP_SLT, CompareVal, + AddOne(RHS)); + } + + if (LHSI->hasOneUse()) { + // (icmp u/s (xor A SignBit), C) -> (icmp s/u A, (xor C SignBit)) + if (!ICI.isEquality() && XorCST->getValue().isSignBit()) { + const APInt &SignBit = XorCST->getValue(); + ICmpInst::Predicate Pred = ICI.isSigned() + ? ICI.getUnsignedPredicate() + : ICI.getSignedPredicate(); + return new ICmpInst(Pred, LHSI->getOperand(0), + ConstantInt::get(*Context, RHSV ^ SignBit)); + } + + // (icmp u/s (xor A ~SignBit), C) -> (icmp s/u (xor C ~SignBit), A) + if (!ICI.isEquality() && XorCST->getValue().isMaxSignedValue()) { + const APInt &NotSignBit = XorCST->getValue(); + ICmpInst::Predicate Pred = ICI.isSigned() + ? ICI.getUnsignedPredicate() + : ICI.getSignedPredicate(); + Pred = ICI.getSwappedPredicate(Pred); + return new ICmpInst(Pred, LHSI->getOperand(0), + ConstantInt::get(*Context, RHSV ^ NotSignBit)); + } + } + } + break; + case Instruction::And: // (icmp pred (and X, AndCST), RHS) + if (LHSI->hasOneUse() && isa(LHSI->getOperand(1)) && + LHSI->getOperand(0)->hasOneUse()) { + ConstantInt *AndCST = cast(LHSI->getOperand(1)); + + // If the LHS is an AND of a truncating cast, we can widen the + // and/compare to be the input width without changing the value + // produced, eliminating a cast. + if (TruncInst *Cast = dyn_cast(LHSI->getOperand(0))) { + // We can do this transformation if either the AND constant does not + // have its sign bit set or if it is an equality comparison. + // Extending a relational comparison when we're checking the sign + // bit would not work. + if (Cast->hasOneUse() && + (ICI.isEquality() || + (AndCST->getValue().isNonNegative() && RHSV.isNonNegative()))) { + uint32_t BitWidth = + cast(Cast->getOperand(0)->getType())->getBitWidth(); + APInt NewCST = AndCST->getValue(); + NewCST.zext(BitWidth); + APInt NewCI = RHSV; + NewCI.zext(BitWidth); + Value *NewAnd = + Builder->CreateAnd(Cast->getOperand(0), + ConstantInt::get(*Context, NewCST), LHSI->getName()); + return new ICmpInst(ICI.getPredicate(), NewAnd, + ConstantInt::get(*Context, NewCI)); + } + } + + // If this is: (X >> C1) & C2 != C3 (where any shift and any compare + // could exist), turn it into (X & (C2 << C1)) != (C3 << C1). This + // happens a LOT in code produced by the C front-end, for bitfield + // access. + BinaryOperator *Shift = dyn_cast(LHSI->getOperand(0)); + if (Shift && !Shift->isShift()) + Shift = 0; + + ConstantInt *ShAmt; + ShAmt = Shift ? dyn_cast(Shift->getOperand(1)) : 0; + const Type *Ty = Shift ? Shift->getType() : 0; // Type of the shift. + const Type *AndTy = AndCST->getType(); // Type of the and. + + // We can fold this as long as we can't shift unknown bits + // into the mask. This can only happen with signed shift + // rights, as they sign-extend. + if (ShAmt) { + bool CanFold = Shift->isLogicalShift(); + if (!CanFold) { + // To test for the bad case of the signed shr, see if any + // of the bits shifted in could be tested after the mask. + uint32_t TyBits = Ty->getPrimitiveSizeInBits(); + int ShAmtVal = TyBits - ShAmt->getLimitedValue(TyBits); + + uint32_t BitWidth = AndTy->getPrimitiveSizeInBits(); + if ((APInt::getHighBitsSet(BitWidth, BitWidth-ShAmtVal) & + AndCST->getValue()) == 0) + CanFold = true; + } + + if (CanFold) { + Constant *NewCst; + if (Shift->getOpcode() == Instruction::Shl) + NewCst = ConstantExpr::getLShr(RHS, ShAmt); + else + NewCst = ConstantExpr::getShl(RHS, ShAmt); + + // Check to see if we are shifting out any of the bits being + // compared. + if (ConstantExpr::get(Shift->getOpcode(), + NewCst, ShAmt) != RHS) { + // If we shifted bits out, the fold is not going to work out. + // As a special case, check to see if this means that the + // result is always true or false now. + if (ICI.getPredicate() == ICmpInst::ICMP_EQ) + return ReplaceInstUsesWith(ICI, ConstantInt::getFalse(*Context)); + if (ICI.getPredicate() == ICmpInst::ICMP_NE) + return ReplaceInstUsesWith(ICI, ConstantInt::getTrue(*Context)); + } else { + ICI.setOperand(1, NewCst); + Constant *NewAndCST; + if (Shift->getOpcode() == Instruction::Shl) + NewAndCST = ConstantExpr::getLShr(AndCST, ShAmt); + else + NewAndCST = ConstantExpr::getShl(AndCST, ShAmt); + LHSI->setOperand(1, NewAndCST); + LHSI->setOperand(0, Shift->getOperand(0)); + Worklist.Add(Shift); // Shift is dead. + return &ICI; + } + } + } + + // Turn ((X >> Y) & C) == 0 into (X & (C << Y)) == 0. The later is + // preferable because it allows the C<hasOneUse() && RHSV == 0 && + ICI.isEquality() && !Shift->isArithmeticShift() && + !isa(Shift->getOperand(0))) { + // Compute C << Y. + Value *NS; + if (Shift->getOpcode() == Instruction::LShr) { + NS = Builder->CreateShl(AndCST, Shift->getOperand(1), "tmp"); + } else { + // Insert a logical shift. + NS = Builder->CreateLShr(AndCST, Shift->getOperand(1), "tmp"); + } + + // Compute X & (C << Y). + Value *NewAnd = + Builder->CreateAnd(Shift->getOperand(0), NS, LHSI->getName()); + + ICI.setOperand(0, NewAnd); + return &ICI; + } + } + break; + + case Instruction::Shl: { // (icmp pred (shl X, ShAmt), CI) + ConstantInt *ShAmt = dyn_cast(LHSI->getOperand(1)); + if (!ShAmt) break; + + uint32_t TypeBits = RHSV.getBitWidth(); + + // Check that the shift amount is in range. If not, don't perform + // undefined shifts. When the shift is visited it will be + // simplified. + if (ShAmt->uge(TypeBits)) + break; + + if (ICI.isEquality()) { + // If we are comparing against bits always shifted out, the + // comparison cannot succeed. + Constant *Comp = + ConstantExpr::getShl(ConstantExpr::getLShr(RHS, ShAmt), + ShAmt); + if (Comp != RHS) {// Comparing against a bit that we know is zero. + bool IsICMP_NE = ICI.getPredicate() == ICmpInst::ICMP_NE; + Constant *Cst = ConstantInt::get(Type::getInt1Ty(*Context), IsICMP_NE); + return ReplaceInstUsesWith(ICI, Cst); + } + + if (LHSI->hasOneUse()) { + // Otherwise strength reduce the shift into an and. + uint32_t ShAmtVal = (uint32_t)ShAmt->getLimitedValue(TypeBits); + Constant *Mask = + ConstantInt::get(*Context, APInt::getLowBitsSet(TypeBits, + TypeBits-ShAmtVal)); + + Value *And = + Builder->CreateAnd(LHSI->getOperand(0),Mask, LHSI->getName()+".mask"); + return new ICmpInst(ICI.getPredicate(), And, + ConstantInt::get(*Context, RHSV.lshr(ShAmtVal))); + } + } + + // Otherwise, if this is a comparison of the sign bit, simplify to and/test. + bool TrueIfSigned = false; + if (LHSI->hasOneUse() && + isSignBitCheck(ICI.getPredicate(), RHS, TrueIfSigned)) { + // (X << 31) (X&1) != 0 + Constant *Mask = ConstantInt::get(*Context, APInt(TypeBits, 1) << + (TypeBits-ShAmt->getZExtValue()-1)); + Value *And = + Builder->CreateAnd(LHSI->getOperand(0), Mask, LHSI->getName()+".mask"); + return new ICmpInst(TrueIfSigned ? ICmpInst::ICMP_NE : ICmpInst::ICMP_EQ, + And, Constant::getNullValue(And->getType())); + } + break; + } + + case Instruction::LShr: // (icmp pred (shr X, ShAmt), CI) + case Instruction::AShr: { + // Only handle equality comparisons of shift-by-constant. + ConstantInt *ShAmt = dyn_cast(LHSI->getOperand(1)); + if (!ShAmt || !ICI.isEquality()) break; + + // Check that the shift amount is in range. If not, don't perform + // undefined shifts. When the shift is visited it will be + // simplified. + uint32_t TypeBits = RHSV.getBitWidth(); + if (ShAmt->uge(TypeBits)) + break; + + uint32_t ShAmtVal = (uint32_t)ShAmt->getLimitedValue(TypeBits); + + // If we are comparing against bits always shifted out, the + // comparison cannot succeed. + APInt Comp = RHSV << ShAmtVal; + if (LHSI->getOpcode() == Instruction::LShr) + Comp = Comp.lshr(ShAmtVal); + else + Comp = Comp.ashr(ShAmtVal); + + if (Comp != RHSV) { // Comparing against a bit that we know is zero. + bool IsICMP_NE = ICI.getPredicate() == ICmpInst::ICMP_NE; + Constant *Cst = ConstantInt::get(Type::getInt1Ty(*Context), IsICMP_NE); + return ReplaceInstUsesWith(ICI, Cst); + } + + // Otherwise, check to see if the bits shifted out are known to be zero. + // If so, we can compare against the unshifted value: + // (X & 4) >> 1 == 2 --> (X & 4) == 4. + if (LHSI->hasOneUse() && + MaskedValueIsZero(LHSI->getOperand(0), + APInt::getLowBitsSet(Comp.getBitWidth(), ShAmtVal))) { + return new ICmpInst(ICI.getPredicate(), LHSI->getOperand(0), + ConstantExpr::getShl(RHS, ShAmt)); + } + + if (LHSI->hasOneUse()) { + // Otherwise strength reduce the shift into an and. + APInt Val(APInt::getHighBitsSet(TypeBits, TypeBits - ShAmtVal)); + Constant *Mask = ConstantInt::get(*Context, Val); + + Value *And = Builder->CreateAnd(LHSI->getOperand(0), + Mask, LHSI->getName()+".mask"); + return new ICmpInst(ICI.getPredicate(), And, + ConstantExpr::getShl(RHS, ShAmt)); + } + break; + } + + case Instruction::SDiv: + case Instruction::UDiv: + // Fold: icmp pred ([us]div X, C1), C2 -> range test + // Fold this div into the comparison, producing a range check. + // Determine, based on the divide type, what the range is being + // checked. If there is an overflow on the low or high side, remember + // it, otherwise compute the range [low, hi) bounding the new value. + // See: InsertRangeTest above for the kinds of replacements possible. + if (ConstantInt *DivRHS = dyn_cast(LHSI->getOperand(1))) + if (Instruction *R = FoldICmpDivCst(ICI, cast(LHSI), + DivRHS)) + return R; + break; + + case Instruction::Add: + // Fold: icmp pred (add, X, C1), C2 + + if (!ICI.isEquality()) { + ConstantInt *LHSC = dyn_cast(LHSI->getOperand(1)); + if (!LHSC) break; + const APInt &LHSV = LHSC->getValue(); + + ConstantRange CR = ICI.makeConstantRange(ICI.getPredicate(), RHSV) + .subtract(LHSV); + + if (ICI.isSigned()) { + if (CR.getLower().isSignBit()) { + return new ICmpInst(ICmpInst::ICMP_SLT, LHSI->getOperand(0), + ConstantInt::get(*Context, CR.getUpper())); + } else if (CR.getUpper().isSignBit()) { + return new ICmpInst(ICmpInst::ICMP_SGE, LHSI->getOperand(0), + ConstantInt::get(*Context, CR.getLower())); + } + } else { + if (CR.getLower().isMinValue()) { + return new ICmpInst(ICmpInst::ICMP_ULT, LHSI->getOperand(0), + ConstantInt::get(*Context, CR.getUpper())); + } else if (CR.getUpper().isMinValue()) { + return new ICmpInst(ICmpInst::ICMP_UGE, LHSI->getOperand(0), + ConstantInt::get(*Context, CR.getLower())); + } + } + } + break; + } + + // Simplify icmp_eq and icmp_ne instructions with integer constant RHS. + if (ICI.isEquality()) { + bool isICMP_NE = ICI.getPredicate() == ICmpInst::ICMP_NE; + + // If the first operand is (add|sub|and|or|xor|rem) with a constant, and + // the second operand is a constant, simplify a bit. + if (BinaryOperator *BO = dyn_cast(LHSI)) { + switch (BO->getOpcode()) { + case Instruction::SRem: + // If we have a signed (X % (2^c)) == 0, turn it into an unsigned one. + if (RHSV == 0 && isa(BO->getOperand(1)) &&BO->hasOneUse()){ + const APInt &V = cast(BO->getOperand(1))->getValue(); + if (V.sgt(APInt(V.getBitWidth(), 1)) && V.isPowerOf2()) { + Value *NewRem = + Builder->CreateURem(BO->getOperand(0), BO->getOperand(1), + BO->getName()); + return new ICmpInst(ICI.getPredicate(), NewRem, + Constant::getNullValue(BO->getType())); + } + } + break; + case Instruction::Add: + // Replace ((add A, B) != C) with (A != C-B) if B & C are constants. + if (ConstantInt *BOp1C = dyn_cast(BO->getOperand(1))) { + if (BO->hasOneUse()) + return new ICmpInst(ICI.getPredicate(), BO->getOperand(0), + ConstantExpr::getSub(RHS, BOp1C)); + } else if (RHSV == 0) { + // Replace ((add A, B) != 0) with (A != -B) if A or B is + // efficiently invertible, or if the add has just this one use. + Value *BOp0 = BO->getOperand(0), *BOp1 = BO->getOperand(1); + + if (Value *NegVal = dyn_castNegVal(BOp1)) + return new ICmpInst(ICI.getPredicate(), BOp0, NegVal); + else if (Value *NegVal = dyn_castNegVal(BOp0)) + return new ICmpInst(ICI.getPredicate(), NegVal, BOp1); + else if (BO->hasOneUse()) { + Value *Neg = Builder->CreateNeg(BOp1); + Neg->takeName(BO); + return new ICmpInst(ICI.getPredicate(), BOp0, Neg); + } + } + break; + case Instruction::Xor: + // For the xor case, we can xor two constants together, eliminating + // the explicit xor. + if (Constant *BOC = dyn_cast(BO->getOperand(1))) + return new ICmpInst(ICI.getPredicate(), BO->getOperand(0), + ConstantExpr::getXor(RHS, BOC)); + + // FALLTHROUGH + case Instruction::Sub: + // Replace (([sub|xor] A, B) != 0) with (A != B) + if (RHSV == 0) + return new ICmpInst(ICI.getPredicate(), BO->getOperand(0), + BO->getOperand(1)); + break; + + case Instruction::Or: + // If bits are being or'd in that are not present in the constant we + // are comparing against, then the comparison could never succeed! + if (Constant *BOC = dyn_cast(BO->getOperand(1))) { + Constant *NotCI = ConstantExpr::getNot(RHS); + if (!ConstantExpr::getAnd(BOC, NotCI)->isNullValue()) + return ReplaceInstUsesWith(ICI, + ConstantInt::get(Type::getInt1Ty(*Context), + isICMP_NE)); + } + break; + + case Instruction::And: + if (ConstantInt *BOC = dyn_cast(BO->getOperand(1))) { + // If bits are being compared against that are and'd out, then the + // comparison can never succeed! + if ((RHSV & ~BOC->getValue()) != 0) + return ReplaceInstUsesWith(ICI, + ConstantInt::get(Type::getInt1Ty(*Context), + isICMP_NE)); + + // If we have ((X & C) == C), turn it into ((X & C) != 0). + if (RHS == BOC && RHSV.isPowerOf2()) + return new ICmpInst(isICMP_NE ? ICmpInst::ICMP_EQ : + ICmpInst::ICMP_NE, LHSI, + Constant::getNullValue(RHS->getType())); + + // Replace (and X, (1 << size(X)-1) != 0) with x s< 0 + if (BOC->getValue().isSignBit()) { + Value *X = BO->getOperand(0); + Constant *Zero = Constant::getNullValue(X->getType()); + ICmpInst::Predicate pred = isICMP_NE ? + ICmpInst::ICMP_SLT : ICmpInst::ICMP_SGE; + return new ICmpInst(pred, X, Zero); + } + + // ((X & ~7) == 0) --> X < 8 + if (RHSV == 0 && isHighOnes(BOC)) { + Value *X = BO->getOperand(0); + Constant *NegX = ConstantExpr::getNeg(BOC); + ICmpInst::Predicate pred = isICMP_NE ? + ICmpInst::ICMP_UGE : ICmpInst::ICMP_ULT; + return new ICmpInst(pred, X, NegX); + } + } + default: break; + } + } else if (IntrinsicInst *II = dyn_cast(LHSI)) { + // Handle icmp {eq|ne} , intcst. + if (II->getIntrinsicID() == Intrinsic::bswap) { + Worklist.Add(II); + ICI.setOperand(0, II->getOperand(1)); + ICI.setOperand(1, ConstantInt::get(*Context, RHSV.byteSwap())); + return &ICI; + } + } + } + return 0; +} + +/// visitICmpInstWithCastAndCast - Handle icmp (cast x to y), (cast/cst). +/// We only handle extending casts so far. +/// +Instruction *InstCombiner::visitICmpInstWithCastAndCast(ICmpInst &ICI) { + const CastInst *LHSCI = cast(ICI.getOperand(0)); + Value *LHSCIOp = LHSCI->getOperand(0); + const Type *SrcTy = LHSCIOp->getType(); + const Type *DestTy = LHSCI->getType(); + Value *RHSCIOp; + + // Turn icmp (ptrtoint x), (ptrtoint/c) into a compare of the input if the + // integer type is the same size as the pointer type. + if (TD && LHSCI->getOpcode() == Instruction::PtrToInt && + TD->getPointerSizeInBits() == + cast(DestTy)->getBitWidth()) { + Value *RHSOp = 0; + if (Constant *RHSC = dyn_cast(ICI.getOperand(1))) { + RHSOp = ConstantExpr::getIntToPtr(RHSC, SrcTy); + } else if (PtrToIntInst *RHSC = dyn_cast(ICI.getOperand(1))) { + RHSOp = RHSC->getOperand(0); + // If the pointer types don't match, insert a bitcast. + if (LHSCIOp->getType() != RHSOp->getType()) + RHSOp = Builder->CreateBitCast(RHSOp, LHSCIOp->getType()); + } + + if (RHSOp) + return new ICmpInst(ICI.getPredicate(), LHSCIOp, RHSOp); + } + + // The code below only handles extension cast instructions, so far. + // Enforce this. + if (LHSCI->getOpcode() != Instruction::ZExt && + LHSCI->getOpcode() != Instruction::SExt) + return 0; + + bool isSignedExt = LHSCI->getOpcode() == Instruction::SExt; + bool isSignedCmp = ICI.isSigned(); + + if (CastInst *CI = dyn_cast(ICI.getOperand(1))) { + // Not an extension from the same type? + RHSCIOp = CI->getOperand(0); + if (RHSCIOp->getType() != LHSCIOp->getType()) + return 0; + + // If the signedness of the two casts doesn't agree (i.e. one is a sext + // and the other is a zext), then we can't handle this. + if (CI->getOpcode() != LHSCI->getOpcode()) + return 0; + + // Deal with equality cases early. + if (ICI.isEquality()) + return new ICmpInst(ICI.getPredicate(), LHSCIOp, RHSCIOp); + + // A signed comparison of sign extended values simplifies into a + // signed comparison. + if (isSignedCmp && isSignedExt) + return new ICmpInst(ICI.getPredicate(), LHSCIOp, RHSCIOp); + + // The other three cases all fold into an unsigned comparison. + return new ICmpInst(ICI.getUnsignedPredicate(), LHSCIOp, RHSCIOp); + } + + // If we aren't dealing with a constant on the RHS, exit early + ConstantInt *CI = dyn_cast(ICI.getOperand(1)); + if (!CI) + return 0; + + // Compute the constant that would happen if we truncated to SrcTy then + // reextended to DestTy. + Constant *Res1 = ConstantExpr::getTrunc(CI, SrcTy); + Constant *Res2 = ConstantExpr::getCast(LHSCI->getOpcode(), + Res1, DestTy); + + // If the re-extended constant didn't change... + if (Res2 == CI) { + // Make sure that sign of the Cmp and the sign of the Cast are the same. + // For example, we might have: + // %A = sext i16 %X to i32 + // %B = icmp ugt i32 %A, 1330 + // It is incorrect to transform this into + // %B = icmp ugt i16 %X, 1330 + // because %A may have negative value. + // + // However, we allow this when the compare is EQ/NE, because they are + // signless. + if (isSignedExt == isSignedCmp || ICI.isEquality()) + return new ICmpInst(ICI.getPredicate(), LHSCIOp, Res1); + return 0; + } + + // The re-extended constant changed so the constant cannot be represented + // in the shorter type. Consequently, we cannot emit a simple comparison. + + // First, handle some easy cases. We know the result cannot be equal at this + // point so handle the ICI.isEquality() cases + if (ICI.getPredicate() == ICmpInst::ICMP_EQ) + return ReplaceInstUsesWith(ICI, ConstantInt::getFalse(*Context)); + if (ICI.getPredicate() == ICmpInst::ICMP_NE) + return ReplaceInstUsesWith(ICI, ConstantInt::getTrue(*Context)); + + // Evaluate the comparison for LT (we invert for GT below). LE and GE cases + // should have been folded away previously and not enter in here. + Value *Result; + if (isSignedCmp) { + // We're performing a signed comparison. + if (cast(CI)->getValue().isNegative()) + Result = ConstantInt::getFalse(*Context); // X < (small) --> false + else + Result = ConstantInt::getTrue(*Context); // X < (large) --> true + } else { + // We're performing an unsigned comparison. + if (isSignedExt) { + // We're performing an unsigned comp with a sign extended value. + // This is true if the input is >= 0. [aka >s -1] + Constant *NegOne = Constant::getAllOnesValue(SrcTy); + Result = Builder->CreateICmpSGT(LHSCIOp, NegOne, ICI.getName()); + } else { + // Unsigned extend & unsigned compare -> always true. + Result = ConstantInt::getTrue(*Context); + } + } + + // Finally, return the value computed. + if (ICI.getPredicate() == ICmpInst::ICMP_ULT || + ICI.getPredicate() == ICmpInst::ICMP_SLT) + return ReplaceInstUsesWith(ICI, Result); + + assert((ICI.getPredicate()==ICmpInst::ICMP_UGT || + ICI.getPredicate()==ICmpInst::ICMP_SGT) && + "ICmp should be folded!"); + if (Constant *CI = dyn_cast(Result)) + return ReplaceInstUsesWith(ICI, ConstantExpr::getNot(CI)); + return BinaryOperator::CreateNot(Result); +} + +Instruction *InstCombiner::visitShl(BinaryOperator &I) { + return commonShiftTransforms(I); +} + +Instruction *InstCombiner::visitLShr(BinaryOperator &I) { + return commonShiftTransforms(I); +} + +Instruction *InstCombiner::visitAShr(BinaryOperator &I) { + if (Instruction *R = commonShiftTransforms(I)) + return R; + + Value *Op0 = I.getOperand(0); + + // ashr int -1, X = -1 (for any arithmetic shift rights of ~0) + if (ConstantInt *CSI = dyn_cast(Op0)) + if (CSI->isAllOnesValue()) + return ReplaceInstUsesWith(I, CSI); + + // See if we can turn a signed shr into an unsigned shr. + if (MaskedValueIsZero(Op0, + APInt::getSignBit(I.getType()->getScalarSizeInBits()))) + return BinaryOperator::CreateLShr(Op0, I.getOperand(1)); + + // Arithmetic shifting an all-sign-bit value is a no-op. + unsigned NumSignBits = ComputeNumSignBits(Op0); + if (NumSignBits == Op0->getType()->getScalarSizeInBits()) + return ReplaceInstUsesWith(I, Op0); + + return 0; +} + +Instruction *InstCombiner::commonShiftTransforms(BinaryOperator &I) { + assert(I.getOperand(1)->getType() == I.getOperand(0)->getType()); + Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1); + + // shl X, 0 == X and shr X, 0 == X + // shl 0, X == 0 and shr 0, X == 0 + if (Op1 == Constant::getNullValue(Op1->getType()) || + Op0 == Constant::getNullValue(Op0->getType())) + return ReplaceInstUsesWith(I, Op0); + + if (isa(Op0)) { + if (I.getOpcode() == Instruction::AShr) // undef >>s X -> undef + return ReplaceInstUsesWith(I, Op0); + else // undef << X -> 0, undef >>u X -> 0 + return ReplaceInstUsesWith(I, Constant::getNullValue(I.getType())); + } + if (isa(Op1)) { + if (I.getOpcode() == Instruction::AShr) // X >>s undef -> X + return ReplaceInstUsesWith(I, Op0); + else // X << undef, X >>u undef -> 0 + return ReplaceInstUsesWith(I, Constant::getNullValue(I.getType())); + } + + // See if we can fold away this shift. + if (SimplifyDemandedInstructionBits(I)) + return &I; + + // Try to fold constant and into select arguments. + if (isa(Op0)) + if (SelectInst *SI = dyn_cast(Op1)) + if (Instruction *R = FoldOpIntoSelect(I, SI, this)) + return R; + + if (ConstantInt *CUI = dyn_cast(Op1)) + if (Instruction *Res = FoldShiftByConstant(Op0, CUI, I)) + return Res; + return 0; +} + +Instruction *InstCombiner::FoldShiftByConstant(Value *Op0, ConstantInt *Op1, + BinaryOperator &I) { + bool isLeftShift = I.getOpcode() == Instruction::Shl; + + // See if we can simplify any instructions used by the instruction whose sole + // purpose is to compute bits we don't care about. + uint32_t TypeBits = Op0->getType()->getScalarSizeInBits(); + + // shl i32 X, 32 = 0 and srl i8 Y, 9 = 0, ... just don't eliminate + // a signed shift. + // + if (Op1->uge(TypeBits)) { + if (I.getOpcode() != Instruction::AShr) + return ReplaceInstUsesWith(I, Constant::getNullValue(Op0->getType())); + else { + I.setOperand(1, ConstantInt::get(I.getType(), TypeBits-1)); + return &I; + } + } + + // ((X*C1) << C2) == (X * (C1 << C2)) + if (BinaryOperator *BO = dyn_cast(Op0)) + if (BO->getOpcode() == Instruction::Mul && isLeftShift) + if (Constant *BOOp = dyn_cast(BO->getOperand(1))) + return BinaryOperator::CreateMul(BO->getOperand(0), + ConstantExpr::getShl(BOOp, Op1)); + + // Try to fold constant and into select arguments. + if (SelectInst *SI = dyn_cast(Op0)) + if (Instruction *R = FoldOpIntoSelect(I, SI, this)) + return R; + if (isa(Op0)) + if (Instruction *NV = FoldOpIntoPhi(I)) + return NV; + + // Fold shift2(trunc(shift1(x,c1)), c2) -> trunc(shift2(shift1(x,c1),c2)) + if (TruncInst *TI = dyn_cast(Op0)) { + Instruction *TrOp = dyn_cast(TI->getOperand(0)); + // If 'shift2' is an ashr, we would have to get the sign bit into a funny + // place. Don't try to do this transformation in this case. Also, we + // require that the input operand is a shift-by-constant so that we have + // confidence that the shifts will get folded together. We could do this + // xform in more cases, but it is unlikely to be profitable. + if (TrOp && I.isLogicalShift() && TrOp->isShift() && + isa(TrOp->getOperand(1))) { + // Okay, we'll do this xform. Make the shift of shift. + Constant *ShAmt = ConstantExpr::getZExt(Op1, TrOp->getType()); + // (shift2 (shift1 & 0x00FF), c2) + Value *NSh = Builder->CreateBinOp(I.getOpcode(), TrOp, ShAmt,I.getName()); + + // For logical shifts, the truncation has the effect of making the high + // part of the register be zeros. Emulate this by inserting an AND to + // clear the top bits as needed. This 'and' will usually be zapped by + // other xforms later if dead. + unsigned SrcSize = TrOp->getType()->getScalarSizeInBits(); + unsigned DstSize = TI->getType()->getScalarSizeInBits(); + APInt MaskV(APInt::getLowBitsSet(SrcSize, DstSize)); + + // The mask we constructed says what the trunc would do if occurring + // between the shifts. We want to know the effect *after* the second + // shift. We know that it is a logical shift by a constant, so adjust the + // mask as appropriate. + if (I.getOpcode() == Instruction::Shl) + MaskV <<= Op1->getZExtValue(); + else { + assert(I.getOpcode() == Instruction::LShr && "Unknown logical shift"); + MaskV = MaskV.lshr(Op1->getZExtValue()); + } + + // shift1 & 0x00FF + Value *And = Builder->CreateAnd(NSh, ConstantInt::get(*Context, MaskV), + TI->getName()); + + // Return the value truncated to the interesting size. + return new TruncInst(And, I.getType()); + } + } + + if (Op0->hasOneUse()) { + if (BinaryOperator *Op0BO = dyn_cast(Op0)) { + // Turn ((X >> C) + Y) << C -> (X + (Y << C)) & (~0 << C) + Value *V1, *V2; + ConstantInt *CC; + switch (Op0BO->getOpcode()) { + default: break; + case Instruction::Add: + case Instruction::And: + case Instruction::Or: + case Instruction::Xor: { + // These operators commute. + // Turn (Y + (X >> C)) << C -> (X + (Y << C)) & (~0 << C) + if (isLeftShift && Op0BO->getOperand(1)->hasOneUse() && + match(Op0BO->getOperand(1), m_Shr(m_Value(V1), + m_Specific(Op1)))) { + Value *YS = // (Y << C) + Builder->CreateShl(Op0BO->getOperand(0), Op1, Op0BO->getName()); + // (X + (Y << C)) + Value *X = Builder->CreateBinOp(Op0BO->getOpcode(), YS, V1, + Op0BO->getOperand(1)->getName()); + uint32_t Op1Val = Op1->getLimitedValue(TypeBits); + return BinaryOperator::CreateAnd(X, ConstantInt::get(*Context, + APInt::getHighBitsSet(TypeBits, TypeBits-Op1Val))); + } + + // Turn (Y + ((X >> C) & CC)) << C -> ((X & (CC << C)) + (Y << C)) + Value *Op0BOOp1 = Op0BO->getOperand(1); + if (isLeftShift && Op0BOOp1->hasOneUse() && + match(Op0BOOp1, + m_And(m_Shr(m_Value(V1), m_Specific(Op1)), + m_ConstantInt(CC))) && + cast(Op0BOOp1)->getOperand(0)->hasOneUse()) { + Value *YS = // (Y << C) + Builder->CreateShl(Op0BO->getOperand(0), Op1, + Op0BO->getName()); + // X & (CC << C) + Value *XM = Builder->CreateAnd(V1, ConstantExpr::getShl(CC, Op1), + V1->getName()+".mask"); + return BinaryOperator::Create(Op0BO->getOpcode(), YS, XM); + } + } + + // FALL THROUGH. + case Instruction::Sub: { + // Turn ((X >> C) + Y) << C -> (X + (Y << C)) & (~0 << C) + if (isLeftShift && Op0BO->getOperand(0)->hasOneUse() && + match(Op0BO->getOperand(0), m_Shr(m_Value(V1), + m_Specific(Op1)))) { + Value *YS = // (Y << C) + Builder->CreateShl(Op0BO->getOperand(1), Op1, Op0BO->getName()); + // (X + (Y << C)) + Value *X = Builder->CreateBinOp(Op0BO->getOpcode(), V1, YS, + Op0BO->getOperand(0)->getName()); + uint32_t Op1Val = Op1->getLimitedValue(TypeBits); + return BinaryOperator::CreateAnd(X, ConstantInt::get(*Context, + APInt::getHighBitsSet(TypeBits, TypeBits-Op1Val))); + } + + // Turn (((X >> C)&CC) + Y) << C -> (X + (Y << C)) & (CC << C) + if (isLeftShift && Op0BO->getOperand(0)->hasOneUse() && + match(Op0BO->getOperand(0), + m_And(m_Shr(m_Value(V1), m_Value(V2)), + m_ConstantInt(CC))) && V2 == Op1 && + cast(Op0BO->getOperand(0)) + ->getOperand(0)->hasOneUse()) { + Value *YS = // (Y << C) + Builder->CreateShl(Op0BO->getOperand(1), Op1, Op0BO->getName()); + // X & (CC << C) + Value *XM = Builder->CreateAnd(V1, ConstantExpr::getShl(CC, Op1), + V1->getName()+".mask"); + + return BinaryOperator::Create(Op0BO->getOpcode(), XM, YS); + } + + break; + } + } + + + // If the operand is an bitwise operator with a constant RHS, and the + // shift is the only use, we can pull it out of the shift. + if (ConstantInt *Op0C = dyn_cast(Op0BO->getOperand(1))) { + bool isValid = true; // Valid only for And, Or, Xor + bool highBitSet = false; // Transform if high bit of constant set? + + switch (Op0BO->getOpcode()) { + default: isValid = false; break; // Do not perform transform! + case Instruction::Add: + isValid = isLeftShift; + break; + case Instruction::Or: + case Instruction::Xor: + highBitSet = false; + break; + case Instruction::And: + highBitSet = true; + break; + } + + // If this is a signed shift right, and the high bit is modified + // by the logical operation, do not perform the transformation. + // The highBitSet boolean indicates the value of the high bit of + // the constant which would cause it to be modified for this + // operation. + // + if (isValid && I.getOpcode() == Instruction::AShr) + isValid = Op0C->getValue()[TypeBits-1] == highBitSet; + + if (isValid) { + Constant *NewRHS = ConstantExpr::get(I.getOpcode(), Op0C, Op1); + + Value *NewShift = + Builder->CreateBinOp(I.getOpcode(), Op0BO->getOperand(0), Op1); + NewShift->takeName(Op0BO); + + return BinaryOperator::Create(Op0BO->getOpcode(), NewShift, + NewRHS); + } + } + } + } + + // Find out if this is a shift of a shift by a constant. + BinaryOperator *ShiftOp = dyn_cast(Op0); + if (ShiftOp && !ShiftOp->isShift()) + ShiftOp = 0; + + if (ShiftOp && isa(ShiftOp->getOperand(1))) { + ConstantInt *ShiftAmt1C = cast(ShiftOp->getOperand(1)); + uint32_t ShiftAmt1 = ShiftAmt1C->getLimitedValue(TypeBits); + uint32_t ShiftAmt2 = Op1->getLimitedValue(TypeBits); + assert(ShiftAmt2 != 0 && "Should have been simplified earlier"); + if (ShiftAmt1 == 0) return 0; // Will be simplified in the future. + Value *X = ShiftOp->getOperand(0); + + uint32_t AmtSum = ShiftAmt1+ShiftAmt2; // Fold into one big shift. + + const IntegerType *Ty = cast(I.getType()); + + // Check for (X << c1) << c2 and (X >> c1) >> c2 + if (I.getOpcode() == ShiftOp->getOpcode()) { + // If this is oversized composite shift, then unsigned shifts get 0, ashr + // saturates. + if (AmtSum >= TypeBits) { + if (I.getOpcode() != Instruction::AShr) + return ReplaceInstUsesWith(I, Constant::getNullValue(I.getType())); + AmtSum = TypeBits-1; // Saturate to 31 for i32 ashr. + } + + return BinaryOperator::Create(I.getOpcode(), X, + ConstantInt::get(Ty, AmtSum)); + } + + if (ShiftOp->getOpcode() == Instruction::LShr && + I.getOpcode() == Instruction::AShr) { + if (AmtSum >= TypeBits) + return ReplaceInstUsesWith(I, Constant::getNullValue(I.getType())); + + // ((X >>u C1) >>s C2) -> (X >>u (C1+C2)) since C1 != 0. + return BinaryOperator::CreateLShr(X, ConstantInt::get(Ty, AmtSum)); + } + + if (ShiftOp->getOpcode() == Instruction::AShr && + I.getOpcode() == Instruction::LShr) { + // ((X >>s C1) >>u C2) -> ((X >>s (C1+C2)) & mask) since C1 != 0. + if (AmtSum >= TypeBits) + AmtSum = TypeBits-1; + + Value *Shift = Builder->CreateAShr(X, ConstantInt::get(Ty, AmtSum)); + + APInt Mask(APInt::getLowBitsSet(TypeBits, TypeBits - ShiftAmt2)); + return BinaryOperator::CreateAnd(Shift, ConstantInt::get(*Context, Mask)); + } + + // Okay, if we get here, one shift must be left, and the other shift must be + // right. See if the amounts are equal. + if (ShiftAmt1 == ShiftAmt2) { + // If we have ((X >>? C) << C), turn this into X & (-1 << C). + if (I.getOpcode() == Instruction::Shl) { + APInt Mask(APInt::getHighBitsSet(TypeBits, TypeBits - ShiftAmt1)); + return BinaryOperator::CreateAnd(X, ConstantInt::get(*Context, Mask)); + } + // If we have ((X << C) >>u C), turn this into X & (-1 >>u C). + if (I.getOpcode() == Instruction::LShr) { + APInt Mask(APInt::getLowBitsSet(TypeBits, TypeBits - ShiftAmt1)); + return BinaryOperator::CreateAnd(X, ConstantInt::get(*Context, Mask)); + } + // We can simplify ((X << C) >>s C) into a trunc + sext. + // NOTE: we could do this for any C, but that would make 'unusual' integer + // types. For now, just stick to ones well-supported by the code + // generators. + const Type *SExtType = 0; + switch (Ty->getBitWidth() - ShiftAmt1) { + case 1 : + case 8 : + case 16 : + case 32 : + case 64 : + case 128: + SExtType = IntegerType::get(*Context, Ty->getBitWidth() - ShiftAmt1); + break; + default: break; + } + if (SExtType) + return new SExtInst(Builder->CreateTrunc(X, SExtType, "sext"), Ty); + // Otherwise, we can't handle it yet. + } else if (ShiftAmt1 < ShiftAmt2) { + uint32_t ShiftDiff = ShiftAmt2-ShiftAmt1; + + // (X >>? C1) << C2 --> X << (C2-C1) & (-1 << C2) + if (I.getOpcode() == Instruction::Shl) { + assert(ShiftOp->getOpcode() == Instruction::LShr || + ShiftOp->getOpcode() == Instruction::AShr); + Value *Shift = Builder->CreateShl(X, ConstantInt::get(Ty, ShiftDiff)); + + APInt Mask(APInt::getHighBitsSet(TypeBits, TypeBits - ShiftAmt2)); + return BinaryOperator::CreateAnd(Shift, + ConstantInt::get(*Context, Mask)); + } + + // (X << C1) >>u C2 --> X >>u (C2-C1) & (-1 >> C2) + if (I.getOpcode() == Instruction::LShr) { + assert(ShiftOp->getOpcode() == Instruction::Shl); + Value *Shift = Builder->CreateLShr(X, ConstantInt::get(Ty, ShiftDiff)); + + APInt Mask(APInt::getLowBitsSet(TypeBits, TypeBits - ShiftAmt2)); + return BinaryOperator::CreateAnd(Shift, + ConstantInt::get(*Context, Mask)); + } + + // We can't handle (X << C1) >>s C2, it shifts arbitrary bits in. + } else { + assert(ShiftAmt2 < ShiftAmt1); + uint32_t ShiftDiff = ShiftAmt1-ShiftAmt2; + + // (X >>? C1) << C2 --> X >>? (C1-C2) & (-1 << C2) + if (I.getOpcode() == Instruction::Shl) { + assert(ShiftOp->getOpcode() == Instruction::LShr || + ShiftOp->getOpcode() == Instruction::AShr); + Value *Shift = Builder->CreateBinOp(ShiftOp->getOpcode(), X, + ConstantInt::get(Ty, ShiftDiff)); + + APInt Mask(APInt::getHighBitsSet(TypeBits, TypeBits - ShiftAmt2)); + return BinaryOperator::CreateAnd(Shift, + ConstantInt::get(*Context, Mask)); + } + + // (X << C1) >>u C2 --> X << (C1-C2) & (-1 >> C2) + if (I.getOpcode() == Instruction::LShr) { + assert(ShiftOp->getOpcode() == Instruction::Shl); + Value *Shift = Builder->CreateShl(X, ConstantInt::get(Ty, ShiftDiff)); + + APInt Mask(APInt::getLowBitsSet(TypeBits, TypeBits - ShiftAmt2)); + return BinaryOperator::CreateAnd(Shift, + ConstantInt::get(*Context, Mask)); + } + + // We can't handle (X << C1) >>a C2, it shifts arbitrary bits in. + } + } + return 0; +} + + +/// DecomposeSimpleLinearExpr - Analyze 'Val', seeing if it is a simple linear +/// expression. If so, decompose it, returning some value X, such that Val is +/// X*Scale+Offset. +/// +static Value *DecomposeSimpleLinearExpr(Value *Val, unsigned &Scale, + int &Offset, LLVMContext *Context) { + assert(Val->getType() == Type::getInt32Ty(*Context) && + "Unexpected allocation size type!"); + if (ConstantInt *CI = dyn_cast(Val)) { + Offset = CI->getZExtValue(); + Scale = 0; + return ConstantInt::get(Type::getInt32Ty(*Context), 0); + } else if (BinaryOperator *I = dyn_cast(Val)) { + if (ConstantInt *RHS = dyn_cast(I->getOperand(1))) { + if (I->getOpcode() == Instruction::Shl) { + // This is a value scaled by '1 << the shift amt'. + Scale = 1U << RHS->getZExtValue(); + Offset = 0; + return I->getOperand(0); + } else if (I->getOpcode() == Instruction::Mul) { + // This value is scaled by 'RHS'. + Scale = RHS->getZExtValue(); + Offset = 0; + return I->getOperand(0); + } else if (I->getOpcode() == Instruction::Add) { + // We have X+C. Check to see if we really have (X*C2)+C1, + // where C1 is divisible by C2. + unsigned SubScale; + Value *SubVal = + DecomposeSimpleLinearExpr(I->getOperand(0), SubScale, + Offset, Context); + Offset += RHS->getZExtValue(); + Scale = SubScale; + return SubVal; + } + } + } + + // Otherwise, we can't look past this. + Scale = 1; + Offset = 0; + return Val; +} + + +/// PromoteCastOfAllocation - If we find a cast of an allocation instruction, +/// try to eliminate the cast by moving the type information into the alloc. +Instruction *InstCombiner::PromoteCastOfAllocation(BitCastInst &CI, + AllocaInst &AI) { + const PointerType *PTy = cast(CI.getType()); + + BuilderTy AllocaBuilder(*Builder); + AllocaBuilder.SetInsertPoint(AI.getParent(), &AI); + + // Remove any uses of AI that are dead. + assert(!CI.use_empty() && "Dead instructions should be removed earlier!"); + + for (Value::use_iterator UI = AI.use_begin(), E = AI.use_end(); UI != E; ) { + Instruction *User = cast(*UI++); + if (isInstructionTriviallyDead(User)) { + while (UI != E && *UI == User) + ++UI; // If this instruction uses AI more than once, don't break UI. + + ++NumDeadInst; + DEBUG(errs() << "IC: DCE: " << *User << '\n'); + EraseInstFromFunction(*User); + } + } + + // This requires TargetData to get the alloca alignment and size information. + if (!TD) return 0; + + // Get the type really allocated and the type casted to. + const Type *AllocElTy = AI.getAllocatedType(); + const Type *CastElTy = PTy->getElementType(); + if (!AllocElTy->isSized() || !CastElTy->isSized()) return 0; + + unsigned AllocElTyAlign = TD->getABITypeAlignment(AllocElTy); + unsigned CastElTyAlign = TD->getABITypeAlignment(CastElTy); + if (CastElTyAlign < AllocElTyAlign) return 0; + + // If the allocation has multiple uses, only promote it if we are strictly + // increasing the alignment of the resultant allocation. If we keep it the + // same, we open the door to infinite loops of various kinds. (A reference + // from a dbg.declare doesn't count as a use for this purpose.) + if (!AI.hasOneUse() && !hasOneUsePlusDeclare(&AI) && + CastElTyAlign == AllocElTyAlign) return 0; + + uint64_t AllocElTySize = TD->getTypeAllocSize(AllocElTy); + uint64_t CastElTySize = TD->getTypeAllocSize(CastElTy); + if (CastElTySize == 0 || AllocElTySize == 0) return 0; + + // See if we can satisfy the modulus by pulling a scale out of the array + // size argument. + unsigned ArraySizeScale; + int ArrayOffset; + Value *NumElements = // See if the array size is a decomposable linear expr. + DecomposeSimpleLinearExpr(AI.getOperand(0), ArraySizeScale, + ArrayOffset, Context); + + // If we can now satisfy the modulus, by using a non-1 scale, we really can + // do the xform. + if ((AllocElTySize*ArraySizeScale) % CastElTySize != 0 || + (AllocElTySize*ArrayOffset ) % CastElTySize != 0) return 0; + + unsigned Scale = (AllocElTySize*ArraySizeScale)/CastElTySize; + Value *Amt = 0; + if (Scale == 1) { + Amt = NumElements; + } else { + Amt = ConstantInt::get(Type::getInt32Ty(*Context), Scale); + // Insert before the alloca, not before the cast. + Amt = AllocaBuilder.CreateMul(Amt, NumElements, "tmp"); + } + + if (int Offset = (AllocElTySize*ArrayOffset)/CastElTySize) { + Value *Off = ConstantInt::get(Type::getInt32Ty(*Context), Offset, true); + Amt = AllocaBuilder.CreateAdd(Amt, Off, "tmp"); + } + + AllocaInst *New = AllocaBuilder.CreateAlloca(CastElTy, Amt); + New->setAlignment(AI.getAlignment()); + New->takeName(&AI); + + // If the allocation has one real use plus a dbg.declare, just remove the + // declare. + if (DbgDeclareInst *DI = hasOneUsePlusDeclare(&AI)) { + EraseInstFromFunction(*DI); + } + // If the allocation has multiple real uses, insert a cast and change all + // things that used it to use the new cast. This will also hack on CI, but it + // will die soon. + else if (!AI.hasOneUse()) { + // New is the allocation instruction, pointer typed. AI is the original + // allocation instruction, also pointer typed. Thus, cast to use is BitCast. + Value *NewCast = AllocaBuilder.CreateBitCast(New, AI.getType(), "tmpcast"); + AI.replaceAllUsesWith(NewCast); + } + return ReplaceInstUsesWith(CI, New); +} + +/// CanEvaluateInDifferentType - Return true if we can take the specified value +/// and return it as type Ty without inserting any new casts and without +/// changing the computed value. This is used by code that tries to decide +/// whether promoting or shrinking integer operations to wider or smaller types +/// will allow us to eliminate a truncate or extend. +/// +/// This is a truncation operation if Ty is smaller than V->getType(), or an +/// extension operation if Ty is larger. +/// +/// If CastOpc is a truncation, then Ty will be a type smaller than V. We +/// should return true if trunc(V) can be computed by computing V in the smaller +/// type. If V is an instruction, then trunc(inst(x,y)) can be computed as +/// inst(trunc(x),trunc(y)), which only makes sense if x and y can be +/// efficiently truncated. +/// +/// If CastOpc is a sext or zext, we are asking if the low bits of the value can +/// bit computed in a larger type, which is then and'd or sext_in_reg'd to get +/// the final result. +bool InstCombiner::CanEvaluateInDifferentType(Value *V, const Type *Ty, + unsigned CastOpc, + int &NumCastsRemoved){ + // We can always evaluate constants in another type. + if (isa(V)) + return true; + + Instruction *I = dyn_cast(V); + if (!I) return false; + + const Type *OrigTy = V->getType(); + + // If this is an extension or truncate, we can often eliminate it. + if (isa(I) || isa(I) || isa(I)) { + // If this is a cast from the destination type, we can trivially eliminate + // it, and this will remove a cast overall. + if (I->getOperand(0)->getType() == Ty) { + // If the first operand is itself a cast, and is eliminable, do not count + // this as an eliminable cast. We would prefer to eliminate those two + // casts first. + if (!isa(I->getOperand(0)) && I->hasOneUse()) + ++NumCastsRemoved; + return true; + } + } + + // We can't extend or shrink something that has multiple uses: doing so would + // require duplicating the instruction in general, which isn't profitable. + if (!I->hasOneUse()) return false; + + unsigned Opc = I->getOpcode(); + switch (Opc) { + case Instruction::Add: + case Instruction::Sub: + case Instruction::Mul: + case Instruction::And: + case Instruction::Or: + case Instruction::Xor: + // These operators can all arbitrarily be extended or truncated. + return CanEvaluateInDifferentType(I->getOperand(0), Ty, CastOpc, + NumCastsRemoved) && + CanEvaluateInDifferentType(I->getOperand(1), Ty, CastOpc, + NumCastsRemoved); + + case Instruction::UDiv: + case Instruction::URem: { + // UDiv and URem can be truncated if all the truncated bits are zero. + uint32_t OrigBitWidth = OrigTy->getScalarSizeInBits(); + uint32_t BitWidth = Ty->getScalarSizeInBits(); + if (BitWidth < OrigBitWidth) { + APInt Mask = APInt::getHighBitsSet(OrigBitWidth, OrigBitWidth-BitWidth); + if (MaskedValueIsZero(I->getOperand(0), Mask) && + MaskedValueIsZero(I->getOperand(1), Mask)) { + return CanEvaluateInDifferentType(I->getOperand(0), Ty, CastOpc, + NumCastsRemoved) && + CanEvaluateInDifferentType(I->getOperand(1), Ty, CastOpc, + NumCastsRemoved); + } + } + break; + } + case Instruction::Shl: + // If we are truncating the result of this SHL, and if it's a shift of a + // constant amount, we can always perform a SHL in a smaller type. + if (ConstantInt *CI = dyn_cast(I->getOperand(1))) { + uint32_t BitWidth = Ty->getScalarSizeInBits(); + if (BitWidth < OrigTy->getScalarSizeInBits() && + CI->getLimitedValue(BitWidth) < BitWidth) + return CanEvaluateInDifferentType(I->getOperand(0), Ty, CastOpc, + NumCastsRemoved); + } + break; + case Instruction::LShr: + // If this is a truncate of a logical shr, we can truncate it to a smaller + // lshr iff we know that the bits we would otherwise be shifting in are + // already zeros. + if (ConstantInt *CI = dyn_cast(I->getOperand(1))) { + uint32_t OrigBitWidth = OrigTy->getScalarSizeInBits(); + uint32_t BitWidth = Ty->getScalarSizeInBits(); + if (BitWidth < OrigBitWidth && + MaskedValueIsZero(I->getOperand(0), + APInt::getHighBitsSet(OrigBitWidth, OrigBitWidth-BitWidth)) && + CI->getLimitedValue(BitWidth) < BitWidth) { + return CanEvaluateInDifferentType(I->getOperand(0), Ty, CastOpc, + NumCastsRemoved); + } + } + break; + case Instruction::ZExt: + case Instruction::SExt: + case Instruction::Trunc: + // If this is the same kind of case as our original (e.g. zext+zext), we + // can safely replace it. Note that replacing it does not reduce the number + // of casts in the input. + if (Opc == CastOpc) + return true; + + // sext (zext ty1), ty2 -> zext ty2 + if (CastOpc == Instruction::SExt && Opc == Instruction::ZExt) + return true; + break; + case Instruction::Select: { + SelectInst *SI = cast(I); + return CanEvaluateInDifferentType(SI->getTrueValue(), Ty, CastOpc, + NumCastsRemoved) && + CanEvaluateInDifferentType(SI->getFalseValue(), Ty, CastOpc, + NumCastsRemoved); + } + case Instruction::PHI: { + // We can change a phi if we can change all operands. + PHINode *PN = cast(I); + for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) + if (!CanEvaluateInDifferentType(PN->getIncomingValue(i), Ty, CastOpc, + NumCastsRemoved)) + return false; + return true; + } + default: + // TODO: Can handle more cases here. + break; + } + + return false; +} + +/// EvaluateInDifferentType - Given an expression that +/// CanEvaluateInDifferentType returns true for, actually insert the code to +/// evaluate the expression. +Value *InstCombiner::EvaluateInDifferentType(Value *V, const Type *Ty, + bool isSigned) { + if (Constant *C = dyn_cast(V)) + return ConstantExpr::getIntegerCast(C, Ty, isSigned /*Sext or ZExt*/); + + // Otherwise, it must be an instruction. + Instruction *I = cast(V); + Instruction *Res = 0; + unsigned Opc = I->getOpcode(); + switch (Opc) { + case Instruction::Add: + case Instruction::Sub: + case Instruction::Mul: + case Instruction::And: + case Instruction::Or: + case Instruction::Xor: + case Instruction::AShr: + case Instruction::LShr: + case Instruction::Shl: + case Instruction::UDiv: + case Instruction::URem: { + Value *LHS = EvaluateInDifferentType(I->getOperand(0), Ty, isSigned); + Value *RHS = EvaluateInDifferentType(I->getOperand(1), Ty, isSigned); + Res = BinaryOperator::Create((Instruction::BinaryOps)Opc, LHS, RHS); + break; + } + case Instruction::Trunc: + case Instruction::ZExt: + case Instruction::SExt: + // If the source type of the cast is the type we're trying for then we can + // just return the source. There's no need to insert it because it is not + // new. + if (I->getOperand(0)->getType() == Ty) + return I->getOperand(0); + + // Otherwise, must be the same type of cast, so just reinsert a new one. + Res = CastInst::Create(cast(I)->getOpcode(), I->getOperand(0),Ty); + break; + case Instruction::Select: { + Value *True = EvaluateInDifferentType(I->getOperand(1), Ty, isSigned); + Value *False = EvaluateInDifferentType(I->getOperand(2), Ty, isSigned); + Res = SelectInst::Create(I->getOperand(0), True, False); + break; + } + case Instruction::PHI: { + PHINode *OPN = cast(I); + PHINode *NPN = PHINode::Create(Ty); + for (unsigned i = 0, e = OPN->getNumIncomingValues(); i != e; ++i) { + Value *V =EvaluateInDifferentType(OPN->getIncomingValue(i), Ty, isSigned); + NPN->addIncoming(V, OPN->getIncomingBlock(i)); + } + Res = NPN; + break; + } + default: + // TODO: Can handle more cases here. + llvm_unreachable("Unreachable!"); + break; + } + + Res->takeName(I); + return InsertNewInstBefore(Res, *I); +} + +/// @brief Implement the transforms common to all CastInst visitors. +Instruction *InstCombiner::commonCastTransforms(CastInst &CI) { + Value *Src = CI.getOperand(0); + + // Many cases of "cast of a cast" are eliminable. If it's eliminable we just + // eliminate it now. + if (CastInst *CSrc = dyn_cast(Src)) { // A->B->C cast + if (Instruction::CastOps opc = + isEliminableCastPair(CSrc, CI.getOpcode(), CI.getType(), TD)) { + // The first cast (CSrc) is eliminable so we need to fix up or replace + // the second cast (CI). CSrc will then have a good chance of being dead. + return CastInst::Create(opc, CSrc->getOperand(0), CI.getType()); + } + } + + // If we are casting a select then fold the cast into the select + if (SelectInst *SI = dyn_cast(Src)) + if (Instruction *NV = FoldOpIntoSelect(CI, SI, this)) + return NV; + + // If we are casting a PHI then fold the cast into the PHI + if (isa(Src)) { + // We don't do this if this would create a PHI node with an illegal type if + // it is currently legal. + if (!isa(Src->getType()) || + !isa(CI.getType()) || + ShouldChangeType(CI.getType(), Src->getType(), TD)) + if (Instruction *NV = FoldOpIntoPhi(CI)) + return NV; + } + + return 0; +} + +/// FindElementAtOffset - Given a type and a constant offset, determine whether +/// or not there is a sequence of GEP indices into the type that will land us at +/// the specified offset. If so, fill them into NewIndices and return the +/// resultant element type, otherwise return null. +static const Type *FindElementAtOffset(const Type *Ty, int64_t Offset, + SmallVectorImpl &NewIndices, + const TargetData *TD, + LLVMContext *Context) { + if (!TD) return 0; + if (!Ty->isSized()) return 0; + + // Start with the index over the outer type. Note that the type size + // might be zero (even if the offset isn't zero) if the indexed type + // is something like [0 x {int, int}] + const Type *IntPtrTy = TD->getIntPtrType(*Context); + int64_t FirstIdx = 0; + if (int64_t TySize = TD->getTypeAllocSize(Ty)) { + FirstIdx = Offset/TySize; + Offset -= FirstIdx*TySize; + + // Handle hosts where % returns negative instead of values [0..TySize). + if (Offset < 0) { + --FirstIdx; + Offset += TySize; + assert(Offset >= 0); + } + assert((uint64_t)Offset < (uint64_t)TySize && "Out of range offset"); + } + + NewIndices.push_back(ConstantInt::get(IntPtrTy, FirstIdx)); + + // Index into the types. If we fail, set OrigBase to null. + while (Offset) { + // Indexing into tail padding between struct/array elements. + if (uint64_t(Offset*8) >= TD->getTypeSizeInBits(Ty)) + return 0; + + if (const StructType *STy = dyn_cast(Ty)) { + const StructLayout *SL = TD->getStructLayout(STy); + assert(Offset < (int64_t)SL->getSizeInBytes() && + "Offset must stay within the indexed type"); + + unsigned Elt = SL->getElementContainingOffset(Offset); + NewIndices.push_back(ConstantInt::get(Type::getInt32Ty(*Context), Elt)); + + Offset -= SL->getElementOffset(Elt); + Ty = STy->getElementType(Elt); + } else if (const ArrayType *AT = dyn_cast(Ty)) { + uint64_t EltSize = TD->getTypeAllocSize(AT->getElementType()); + assert(EltSize && "Cannot index into a zero-sized array"); + NewIndices.push_back(ConstantInt::get(IntPtrTy,Offset/EltSize)); + Offset %= EltSize; + Ty = AT->getElementType(); + } else { + // Otherwise, we can't index into the middle of this atomic type, bail. + return 0; + } + } + + return Ty; +} + +/// @brief Implement the transforms for cast of pointer (bitcast/ptrtoint) +Instruction *InstCombiner::commonPointerCastTransforms(CastInst &CI) { + Value *Src = CI.getOperand(0); + + if (GetElementPtrInst *GEP = dyn_cast(Src)) { + // If casting the result of a getelementptr instruction with no offset, turn + // this into a cast of the original pointer! + if (GEP->hasAllZeroIndices()) { + // Changing the cast operand is usually not a good idea but it is safe + // here because the pointer operand is being replaced with another + // pointer operand so the opcode doesn't need to change. + Worklist.Add(GEP); + CI.setOperand(0, GEP->getOperand(0)); + return &CI; + } + + // If the GEP has a single use, and the base pointer is a bitcast, and the + // GEP computes a constant offset, see if we can convert these three + // instructions into fewer. This typically happens with unions and other + // non-type-safe code. + if (TD && GEP->hasOneUse() && isa(GEP->getOperand(0))) { + if (GEP->hasAllConstantIndices()) { + // We are guaranteed to get a constant from EmitGEPOffset. + ConstantInt *OffsetV = cast(EmitGEPOffset(GEP, *this)); + int64_t Offset = OffsetV->getSExtValue(); + + // Get the base pointer input of the bitcast, and the type it points to. + Value *OrigBase = cast(GEP->getOperand(0))->getOperand(0); + const Type *GEPIdxTy = + cast(OrigBase->getType())->getElementType(); + SmallVector NewIndices; + if (FindElementAtOffset(GEPIdxTy, Offset, NewIndices, TD, Context)) { + // If we were able to index down into an element, create the GEP + // and bitcast the result. This eliminates one bitcast, potentially + // two. + Value *NGEP = cast(GEP)->isInBounds() ? + Builder->CreateInBoundsGEP(OrigBase, + NewIndices.begin(), NewIndices.end()) : + Builder->CreateGEP(OrigBase, NewIndices.begin(), NewIndices.end()); + NGEP->takeName(GEP); + + if (isa(CI)) + return new BitCastInst(NGEP, CI.getType()); + assert(isa(CI)); + return new PtrToIntInst(NGEP, CI.getType()); + } + } + } + } + + return commonCastTransforms(CI); +} + +/// commonIntCastTransforms - This function implements the common transforms +/// for trunc, zext, and sext. +Instruction *InstCombiner::commonIntCastTransforms(CastInst &CI) { + if (Instruction *Result = commonCastTransforms(CI)) + return Result; + + Value *Src = CI.getOperand(0); + const Type *SrcTy = Src->getType(); + const Type *DestTy = CI.getType(); + uint32_t SrcBitSize = SrcTy->getScalarSizeInBits(); + uint32_t DestBitSize = DestTy->getScalarSizeInBits(); + + // See if we can simplify any instructions used by the LHS whose sole + // purpose is to compute bits we don't care about. + if (SimplifyDemandedInstructionBits(CI)) + return &CI; + + // If the source isn't an instruction or has more than one use then we + // can't do anything more. + Instruction *SrcI = dyn_cast(Src); + if (!SrcI || !Src->hasOneUse()) + return 0; + + // Attempt to propagate the cast into the instruction for int->int casts. + int NumCastsRemoved = 0; + // Only do this if the dest type is a simple type, don't convert the + // expression tree to something weird like i93 unless the source is also + // strange. + if ((isa(DestTy) || + ShouldChangeType(SrcI->getType(), DestTy, TD)) && + CanEvaluateInDifferentType(SrcI, DestTy, + CI.getOpcode(), NumCastsRemoved)) { + // If this cast is a truncate, evaluting in a different type always + // eliminates the cast, so it is always a win. If this is a zero-extension, + // we need to do an AND to maintain the clear top-part of the computation, + // so we require that the input have eliminated at least one cast. If this + // is a sign extension, we insert two new casts (to do the extension) so we + // require that two casts have been eliminated. + bool DoXForm = false; + bool JustReplace = false; + switch (CI.getOpcode()) { + default: + // All the others use floating point so we shouldn't actually + // get here because of the check above. + llvm_unreachable("Unknown cast type"); + case Instruction::Trunc: + DoXForm = true; + break; + case Instruction::ZExt: { + DoXForm = NumCastsRemoved >= 1; + + if (!DoXForm && 0) { + // If it's unnecessary to issue an AND to clear the high bits, it's + // always profitable to do this xform. + Value *TryRes = EvaluateInDifferentType(SrcI, DestTy, false); + APInt Mask(APInt::getBitsSet(DestBitSize, SrcBitSize, DestBitSize)); + if (MaskedValueIsZero(TryRes, Mask)) + return ReplaceInstUsesWith(CI, TryRes); + + if (Instruction *TryI = dyn_cast(TryRes)) + if (TryI->use_empty()) + EraseInstFromFunction(*TryI); + } + break; + } + case Instruction::SExt: { + DoXForm = NumCastsRemoved >= 2; + if (!DoXForm && !isa(SrcI) && 0) { + // If we do not have to emit the truncate + sext pair, then it's always + // profitable to do this xform. + // + // It's not safe to eliminate the trunc + sext pair if one of the + // eliminated cast is a truncate. e.g. + // t2 = trunc i32 t1 to i16 + // t3 = sext i16 t2 to i32 + // != + // i32 t1 + Value *TryRes = EvaluateInDifferentType(SrcI, DestTy, true); + unsigned NumSignBits = ComputeNumSignBits(TryRes); + if (NumSignBits > (DestBitSize - SrcBitSize)) + return ReplaceInstUsesWith(CI, TryRes); + + if (Instruction *TryI = dyn_cast(TryRes)) + if (TryI->use_empty()) + EraseInstFromFunction(*TryI); + } + break; + } + } + + if (DoXForm) { + DEBUG(errs() << "ICE: EvaluateInDifferentType converting expression type" + " to avoid cast: " << CI); + Value *Res = EvaluateInDifferentType(SrcI, DestTy, + CI.getOpcode() == Instruction::SExt); + if (JustReplace) + // Just replace this cast with the result. + return ReplaceInstUsesWith(CI, Res); + + assert(Res->getType() == DestTy); + switch (CI.getOpcode()) { + default: llvm_unreachable("Unknown cast type!"); + case Instruction::Trunc: + // Just replace this cast with the result. + return ReplaceInstUsesWith(CI, Res); + case Instruction::ZExt: { + assert(SrcBitSize < DestBitSize && "Not a zext?"); + + // If the high bits are already zero, just replace this cast with the + // result. + APInt Mask(APInt::getBitsSet(DestBitSize, SrcBitSize, DestBitSize)); + if (MaskedValueIsZero(Res, Mask)) + return ReplaceInstUsesWith(CI, Res); + + // We need to emit an AND to clear the high bits. + Constant *C = ConstantInt::get(*Context, + APInt::getLowBitsSet(DestBitSize, SrcBitSize)); + return BinaryOperator::CreateAnd(Res, C); + } + case Instruction::SExt: { + // If the high bits are already filled with sign bit, just replace this + // cast with the result. + unsigned NumSignBits = ComputeNumSignBits(Res); + if (NumSignBits > (DestBitSize - SrcBitSize)) + return ReplaceInstUsesWith(CI, Res); + + // We need to emit a cast to truncate, then a cast to sext. + return new SExtInst(Builder->CreateTrunc(Res, Src->getType()), DestTy); + } + } + } + } + + Value *Op0 = SrcI->getNumOperands() > 0 ? SrcI->getOperand(0) : 0; + Value *Op1 = SrcI->getNumOperands() > 1 ? SrcI->getOperand(1) : 0; + + switch (SrcI->getOpcode()) { + case Instruction::Add: + case Instruction::Mul: + case Instruction::And: + case Instruction::Or: + case Instruction::Xor: + // If we are discarding information, rewrite. + if (DestBitSize < SrcBitSize && DestBitSize != 1) { + // Don't insert two casts unless at least one can be eliminated. + if (!ValueRequiresCast(CI.getOpcode(), Op1, DestTy, TD) || + !ValueRequiresCast(CI.getOpcode(), Op0, DestTy, TD)) { + Value *Op0c = Builder->CreateTrunc(Op0, DestTy, Op0->getName()); + Value *Op1c = Builder->CreateTrunc(Op1, DestTy, Op1->getName()); + return BinaryOperator::Create( + cast(SrcI)->getOpcode(), Op0c, Op1c); + } + } + + // cast (xor bool X, true) to int --> xor (cast bool X to int), 1 + if (isa(CI) && SrcBitSize == 1 && + SrcI->getOpcode() == Instruction::Xor && + Op1 == ConstantInt::getTrue(*Context) && + (!Op0->hasOneUse() || !isa(Op0))) { + Value *New = Builder->CreateZExt(Op0, DestTy, Op0->getName()); + return BinaryOperator::CreateXor(New, + ConstantInt::get(CI.getType(), 1)); + } + break; + + case Instruction::Shl: { + // Canonicalize trunc inside shl, if we can. + ConstantInt *CI = dyn_cast(Op1); + if (CI && DestBitSize < SrcBitSize && + CI->getLimitedValue(DestBitSize) < DestBitSize) { + Value *Op0c = Builder->CreateTrunc(Op0, DestTy, Op0->getName()); + Value *Op1c = Builder->CreateTrunc(Op1, DestTy, Op1->getName()); + return BinaryOperator::CreateShl(Op0c, Op1c); + } + break; + } + } + return 0; +} + +Instruction *InstCombiner::visitTrunc(TruncInst &CI) { + if (Instruction *Result = commonIntCastTransforms(CI)) + return Result; + + Value *Src = CI.getOperand(0); + const Type *Ty = CI.getType(); + uint32_t DestBitWidth = Ty->getScalarSizeInBits(); + uint32_t SrcBitWidth = Src->getType()->getScalarSizeInBits(); + + // Canonicalize trunc x to i1 -> (icmp ne (and x, 1), 0) + if (DestBitWidth == 1) { + Constant *One = ConstantInt::get(Src->getType(), 1); + Src = Builder->CreateAnd(Src, One, "tmp"); + Value *Zero = Constant::getNullValue(Src->getType()); + return new ICmpInst(ICmpInst::ICMP_NE, Src, Zero); + } + + // Optimize trunc(lshr(), c) to pull the shift through the truncate. + ConstantInt *ShAmtV = 0; + Value *ShiftOp = 0; + if (Src->hasOneUse() && + match(Src, m_LShr(m_Value(ShiftOp), m_ConstantInt(ShAmtV)))) { + uint32_t ShAmt = ShAmtV->getLimitedValue(SrcBitWidth); + + // Get a mask for the bits shifting in. + APInt Mask(APInt::getLowBitsSet(SrcBitWidth, ShAmt).shl(DestBitWidth)); + if (MaskedValueIsZero(ShiftOp, Mask)) { + if (ShAmt >= DestBitWidth) // All zeros. + return ReplaceInstUsesWith(CI, Constant::getNullValue(Ty)); + + // Okay, we can shrink this. Truncate the input, then return a new + // shift. + Value *V1 = Builder->CreateTrunc(ShiftOp, Ty, ShiftOp->getName()); + Value *V2 = ConstantExpr::getTrunc(ShAmtV, Ty); + return BinaryOperator::CreateLShr(V1, V2); + } + } + + return 0; +} + +/// transformZExtICmp - Transform (zext icmp) to bitwise / integer operations +/// in order to eliminate the icmp. +Instruction *InstCombiner::transformZExtICmp(ICmpInst *ICI, Instruction &CI, + bool DoXform) { + // If we are just checking for a icmp eq of a single bit and zext'ing it + // to an integer, then shift the bit to the appropriate place and then + // cast to integer to avoid the comparison. + if (ConstantInt *Op1C = dyn_cast(ICI->getOperand(1))) { + const APInt &Op1CV = Op1C->getValue(); + + // zext (x x>>u31 true if signbit set. + // zext (x >s -1) to i32 --> (x>>u31)^1 true if signbit clear. + if ((ICI->getPredicate() == ICmpInst::ICMP_SLT && Op1CV == 0) || + (ICI->getPredicate() == ICmpInst::ICMP_SGT &&Op1CV.isAllOnesValue())) { + if (!DoXform) return ICI; + + Value *In = ICI->getOperand(0); + Value *Sh = ConstantInt::get(In->getType(), + In->getType()->getScalarSizeInBits()-1); + In = Builder->CreateLShr(In, Sh, In->getName()+".lobit"); + if (In->getType() != CI.getType()) + In = Builder->CreateIntCast(In, CI.getType(), false/*ZExt*/, "tmp"); + + if (ICI->getPredicate() == ICmpInst::ICMP_SGT) { + Constant *One = ConstantInt::get(In->getType(), 1); + In = Builder->CreateXor(In, One, In->getName()+".not"); + } + + return ReplaceInstUsesWith(CI, In); + } + + + + // zext (X == 0) to i32 --> X^1 iff X has only the low bit set. + // zext (X == 0) to i32 --> (X>>1)^1 iff X has only the 2nd bit set. + // zext (X == 1) to i32 --> X iff X has only the low bit set. + // zext (X == 2) to i32 --> X>>1 iff X has only the 2nd bit set. + // zext (X != 0) to i32 --> X iff X has only the low bit set. + // zext (X != 0) to i32 --> X>>1 iff X has only the 2nd bit set. + // zext (X != 1) to i32 --> X^1 iff X has only the low bit set. + // zext (X != 2) to i32 --> (X>>1)^1 iff X has only the 2nd bit set. + if ((Op1CV == 0 || Op1CV.isPowerOf2()) && + // This only works for EQ and NE + ICI->isEquality()) { + // If Op1C some other power of two, convert: + uint32_t BitWidth = Op1C->getType()->getBitWidth(); + APInt KnownZero(BitWidth, 0), KnownOne(BitWidth, 0); + APInt TypeMask(APInt::getAllOnesValue(BitWidth)); + ComputeMaskedBits(ICI->getOperand(0), TypeMask, KnownZero, KnownOne); + + APInt KnownZeroMask(~KnownZero); + if (KnownZeroMask.isPowerOf2()) { // Exactly 1 possible 1? + if (!DoXform) return ICI; + + bool isNE = ICI->getPredicate() == ICmpInst::ICMP_NE; + if (Op1CV != 0 && (Op1CV != KnownZeroMask)) { + // (X&4) == 2 --> false + // (X&4) != 2 --> true + Constant *Res = ConstantInt::get(Type::getInt1Ty(*Context), isNE); + Res = ConstantExpr::getZExt(Res, CI.getType()); + return ReplaceInstUsesWith(CI, Res); + } + + uint32_t ShiftAmt = KnownZeroMask.logBase2(); + Value *In = ICI->getOperand(0); + if (ShiftAmt) { + // Perform a logical shr by shiftamt. + // Insert the shift to put the result in the low bit. + In = Builder->CreateLShr(In, ConstantInt::get(In->getType(),ShiftAmt), + In->getName()+".lobit"); + } + + if ((Op1CV != 0) == isNE) { // Toggle the low bit. + Constant *One = ConstantInt::get(In->getType(), 1); + In = Builder->CreateXor(In, One, "tmp"); + } + + if (CI.getType() == In->getType()) + return ReplaceInstUsesWith(CI, In); + else + return CastInst::CreateIntegerCast(In, CI.getType(), false/*ZExt*/); + } + } + } + + // icmp ne A, B is equal to xor A, B when A and B only really have one bit. + // It is also profitable to transform icmp eq into not(xor(A, B)) because that + // may lead to additional simplifications. + if (ICI->isEquality() && CI.getType() == ICI->getOperand(0)->getType()) { + if (const IntegerType *ITy = dyn_cast(CI.getType())) { + uint32_t BitWidth = ITy->getBitWidth(); + if (BitWidth > 1) { + Value *LHS = ICI->getOperand(0); + Value *RHS = ICI->getOperand(1); + + APInt KnownZeroLHS(BitWidth, 0), KnownOneLHS(BitWidth, 0); + APInt KnownZeroRHS(BitWidth, 0), KnownOneRHS(BitWidth, 0); + APInt TypeMask(APInt::getHighBitsSet(BitWidth, BitWidth-1)); + ComputeMaskedBits(LHS, TypeMask, KnownZeroLHS, KnownOneLHS); + ComputeMaskedBits(RHS, TypeMask, KnownZeroRHS, KnownOneRHS); + + if (KnownZeroLHS.countLeadingOnes() == BitWidth-1 && + KnownZeroRHS.countLeadingOnes() == BitWidth-1) { + if (!DoXform) return ICI; + + Value *Xor = Builder->CreateXor(LHS, RHS); + if (ICI->getPredicate() == ICmpInst::ICMP_EQ) + Xor = Builder->CreateXor(Xor, ConstantInt::get(ITy, 1)); + Xor->takeName(ICI); + return ReplaceInstUsesWith(CI, Xor); + } + } + } + } + + return 0; +} + +Instruction *InstCombiner::visitZExt(ZExtInst &CI) { + // If one of the common conversion will work .. + if (Instruction *Result = commonIntCastTransforms(CI)) + return Result; + + Value *Src = CI.getOperand(0); + + // If this is a TRUNC followed by a ZEXT then we are dealing with integral + // types and if the sizes are just right we can convert this into a logical + // 'and' which will be much cheaper than the pair of casts. + if (TruncInst *CSrc = dyn_cast(Src)) { // A->B->C cast + // Get the sizes of the types involved. We know that the intermediate type + // will be smaller than A or C, but don't know the relation between A and C. + Value *A = CSrc->getOperand(0); + unsigned SrcSize = A->getType()->getScalarSizeInBits(); + unsigned MidSize = CSrc->getType()->getScalarSizeInBits(); + unsigned DstSize = CI.getType()->getScalarSizeInBits(); + // If we're actually extending zero bits, then if + // SrcSize < DstSize: zext(a & mask) + // SrcSize == DstSize: a & mask + // SrcSize > DstSize: trunc(a) & mask + if (SrcSize < DstSize) { + APInt AndValue(APInt::getLowBitsSet(SrcSize, MidSize)); + Constant *AndConst = ConstantInt::get(A->getType(), AndValue); + Value *And = Builder->CreateAnd(A, AndConst, CSrc->getName()+".mask"); + return new ZExtInst(And, CI.getType()); + } + + if (SrcSize == DstSize) { + APInt AndValue(APInt::getLowBitsSet(SrcSize, MidSize)); + return BinaryOperator::CreateAnd(A, ConstantInt::get(A->getType(), + AndValue)); + } + if (SrcSize > DstSize) { + Value *Trunc = Builder->CreateTrunc(A, CI.getType(), "tmp"); + APInt AndValue(APInt::getLowBitsSet(DstSize, MidSize)); + return BinaryOperator::CreateAnd(Trunc, + ConstantInt::get(Trunc->getType(), + AndValue)); + } + } + + if (ICmpInst *ICI = dyn_cast(Src)) + return transformZExtICmp(ICI, CI); + + BinaryOperator *SrcI = dyn_cast(Src); + if (SrcI && SrcI->getOpcode() == Instruction::Or) { + // zext (or icmp, icmp) --> or (zext icmp), (zext icmp) if at least one + // of the (zext icmp) will be transformed. + ICmpInst *LHS = dyn_cast(SrcI->getOperand(0)); + ICmpInst *RHS = dyn_cast(SrcI->getOperand(1)); + if (LHS && RHS && LHS->hasOneUse() && RHS->hasOneUse() && + (transformZExtICmp(LHS, CI, false) || + transformZExtICmp(RHS, CI, false))) { + Value *LCast = Builder->CreateZExt(LHS, CI.getType(), LHS->getName()); + Value *RCast = Builder->CreateZExt(RHS, CI.getType(), RHS->getName()); + return BinaryOperator::Create(Instruction::Or, LCast, RCast); + } + } + + // zext(trunc(t) & C) -> (t & zext(C)). + if (SrcI && SrcI->getOpcode() == Instruction::And && SrcI->hasOneUse()) + if (ConstantInt *C = dyn_cast(SrcI->getOperand(1))) + if (TruncInst *TI = dyn_cast(SrcI->getOperand(0))) { + Value *TI0 = TI->getOperand(0); + if (TI0->getType() == CI.getType()) + return + BinaryOperator::CreateAnd(TI0, + ConstantExpr::getZExt(C, CI.getType())); + } + + // zext((trunc(t) & C) ^ C) -> ((t & zext(C)) ^ zext(C)). + if (SrcI && SrcI->getOpcode() == Instruction::Xor && SrcI->hasOneUse()) + if (ConstantInt *C = dyn_cast(SrcI->getOperand(1))) + if (BinaryOperator *And = dyn_cast(SrcI->getOperand(0))) + if (And->getOpcode() == Instruction::And && And->hasOneUse() && + And->getOperand(1) == C) + if (TruncInst *TI = dyn_cast(And->getOperand(0))) { + Value *TI0 = TI->getOperand(0); + if (TI0->getType() == CI.getType()) { + Constant *ZC = ConstantExpr::getZExt(C, CI.getType()); + Value *NewAnd = Builder->CreateAnd(TI0, ZC, "tmp"); + return BinaryOperator::CreateXor(NewAnd, ZC); + } + } + + return 0; +} + +Instruction *InstCombiner::visitSExt(SExtInst &CI) { + if (Instruction *I = commonIntCastTransforms(CI)) + return I; + + Value *Src = CI.getOperand(0); + + // Canonicalize sign-extend from i1 to a select. + if (Src->getType() == Type::getInt1Ty(*Context)) + return SelectInst::Create(Src, + Constant::getAllOnesValue(CI.getType()), + Constant::getNullValue(CI.getType())); + + // See if the value being truncated is already sign extended. If so, just + // eliminate the trunc/sext pair. + if (Operator::getOpcode(Src) == Instruction::Trunc) { + Value *Op = cast(Src)->getOperand(0); + unsigned OpBits = Op->getType()->getScalarSizeInBits(); + unsigned MidBits = Src->getType()->getScalarSizeInBits(); + unsigned DestBits = CI.getType()->getScalarSizeInBits(); + unsigned NumSignBits = ComputeNumSignBits(Op); + + if (OpBits == DestBits) { + // Op is i32, Mid is i8, and Dest is i32. If Op has more than 24 sign + // bits, it is already ready. + if (NumSignBits > DestBits-MidBits) + return ReplaceInstUsesWith(CI, Op); + } else if (OpBits < DestBits) { + // Op is i32, Mid is i8, and Dest is i64. If Op has more than 24 sign + // bits, just sext from i32. + if (NumSignBits > OpBits-MidBits) + return new SExtInst(Op, CI.getType(), "tmp"); + } else { + // Op is i64, Mid is i8, and Dest is i32. If Op has more than 56 sign + // bits, just truncate to i32. + if (NumSignBits > OpBits-MidBits) + return new TruncInst(Op, CI.getType(), "tmp"); + } + } + + // If the input is a shl/ashr pair of a same constant, then this is a sign + // extension from a smaller value. If we could trust arbitrary bitwidth + // integers, we could turn this into a truncate to the smaller bit and then + // use a sext for the whole extension. Since we don't, look deeper and check + // for a truncate. If the source and dest are the same type, eliminate the + // trunc and extend and just do shifts. For example, turn: + // %a = trunc i32 %i to i8 + // %b = shl i8 %a, 6 + // %c = ashr i8 %b, 6 + // %d = sext i8 %c to i32 + // into: + // %a = shl i32 %i, 30 + // %d = ashr i32 %a, 30 + Value *A = 0; + ConstantInt *BA = 0, *CA = 0; + if (match(Src, m_AShr(m_Shl(m_Value(A), m_ConstantInt(BA)), + m_ConstantInt(CA))) && + BA == CA && isa(A)) { + Value *I = cast(A)->getOperand(0); + if (I->getType() == CI.getType()) { + unsigned MidSize = Src->getType()->getScalarSizeInBits(); + unsigned SrcDstSize = CI.getType()->getScalarSizeInBits(); + unsigned ShAmt = CA->getZExtValue()+SrcDstSize-MidSize; + Constant *ShAmtV = ConstantInt::get(CI.getType(), ShAmt); + I = Builder->CreateShl(I, ShAmtV, CI.getName()); + return BinaryOperator::CreateAShr(I, ShAmtV); + } + } + + return 0; +} + +/// FitsInFPType - Return a Constant* for the specified FP constant if it fits +/// in the specified FP type without changing its value. +static Constant *FitsInFPType(ConstantFP *CFP, const fltSemantics &Sem, + LLVMContext *Context) { + bool losesInfo; + APFloat F = CFP->getValueAPF(); + (void)F.convert(Sem, APFloat::rmNearestTiesToEven, &losesInfo); + if (!losesInfo) + return ConstantFP::get(*Context, F); + return 0; +} + +/// LookThroughFPExtensions - If this is an fp extension instruction, look +/// through it until we get the source value. +static Value *LookThroughFPExtensions(Value *V, LLVMContext *Context) { + if (Instruction *I = dyn_cast(V)) + if (I->getOpcode() == Instruction::FPExt) + return LookThroughFPExtensions(I->getOperand(0), Context); + + // If this value is a constant, return the constant in the smallest FP type + // that can accurately represent it. This allows us to turn + // (float)((double)X+2.0) into x+2.0f. + if (ConstantFP *CFP = dyn_cast(V)) { + if (CFP->getType() == Type::getPPC_FP128Ty(*Context)) + return V; // No constant folding of this. + // See if the value can be truncated to float and then reextended. + if (Value *V = FitsInFPType(CFP, APFloat::IEEEsingle, Context)) + return V; + if (CFP->getType() == Type::getDoubleTy(*Context)) + return V; // Won't shrink. + if (Value *V = FitsInFPType(CFP, APFloat::IEEEdouble, Context)) + return V; + // Don't try to shrink to various long double types. + } + + return V; +} + +Instruction *InstCombiner::visitFPTrunc(FPTruncInst &CI) { + if (Instruction *I = commonCastTransforms(CI)) + return I; + + // If we have fptrunc(fadd (fpextend x), (fpextend y)), where x and y are + // smaller than the destination type, we can eliminate the truncate by doing + // the add as the smaller type. This applies to fadd/fsub/fmul/fdiv as well as + // many builtins (sqrt, etc). + BinaryOperator *OpI = dyn_cast(CI.getOperand(0)); + if (OpI && OpI->hasOneUse()) { + switch (OpI->getOpcode()) { + default: break; + case Instruction::FAdd: + case Instruction::FSub: + case Instruction::FMul: + case Instruction::FDiv: + case Instruction::FRem: + const Type *SrcTy = OpI->getType(); + Value *LHSTrunc = LookThroughFPExtensions(OpI->getOperand(0), Context); + Value *RHSTrunc = LookThroughFPExtensions(OpI->getOperand(1), Context); + if (LHSTrunc->getType() != SrcTy && + RHSTrunc->getType() != SrcTy) { + unsigned DstSize = CI.getType()->getScalarSizeInBits(); + // If the source types were both smaller than the destination type of + // the cast, do this xform. + if (LHSTrunc->getType()->getScalarSizeInBits() <= DstSize && + RHSTrunc->getType()->getScalarSizeInBits() <= DstSize) { + LHSTrunc = Builder->CreateFPExt(LHSTrunc, CI.getType()); + RHSTrunc = Builder->CreateFPExt(RHSTrunc, CI.getType()); + return BinaryOperator::Create(OpI->getOpcode(), LHSTrunc, RHSTrunc); + } + } + break; + } + } + return 0; +} + +Instruction *InstCombiner::visitFPExt(CastInst &CI) { + return commonCastTransforms(CI); +} + +Instruction *InstCombiner::visitFPToUI(FPToUIInst &FI) { + Instruction *OpI = dyn_cast(FI.getOperand(0)); + if (OpI == 0) + return commonCastTransforms(FI); + + // fptoui(uitofp(X)) --> X + // fptoui(sitofp(X)) --> X + // This is safe if the intermediate type has enough bits in its mantissa to + // accurately represent all values of X. For example, do not do this with + // i64->float->i64. This is also safe for sitofp case, because any negative + // 'X' value would cause an undefined result for the fptoui. + if ((isa(OpI) || isa(OpI)) && + OpI->getOperand(0)->getType() == FI.getType() && + (int)FI.getType()->getScalarSizeInBits() < /*extra bit for sign */ + OpI->getType()->getFPMantissaWidth()) + return ReplaceInstUsesWith(FI, OpI->getOperand(0)); + + return commonCastTransforms(FI); +} + +Instruction *InstCombiner::visitFPToSI(FPToSIInst &FI) { + Instruction *OpI = dyn_cast(FI.getOperand(0)); + if (OpI == 0) + return commonCastTransforms(FI); + + // fptosi(sitofp(X)) --> X + // fptosi(uitofp(X)) --> X + // This is safe if the intermediate type has enough bits in its mantissa to + // accurately represent all values of X. For example, do not do this with + // i64->float->i64. This is also safe for sitofp case, because any negative + // 'X' value would cause an undefined result for the fptoui. + if ((isa(OpI) || isa(OpI)) && + OpI->getOperand(0)->getType() == FI.getType() && + (int)FI.getType()->getScalarSizeInBits() <= + OpI->getType()->getFPMantissaWidth()) + return ReplaceInstUsesWith(FI, OpI->getOperand(0)); + + return commonCastTransforms(FI); +} + +Instruction *InstCombiner::visitUIToFP(CastInst &CI) { + return commonCastTransforms(CI); +} + +Instruction *InstCombiner::visitSIToFP(CastInst &CI) { + return commonCastTransforms(CI); +} + +Instruction *InstCombiner::visitPtrToInt(PtrToIntInst &CI) { + // If the destination integer type is smaller than the intptr_t type for + // this target, do a ptrtoint to intptr_t then do a trunc. This allows the + // trunc to be exposed to other transforms. Don't do this for extending + // ptrtoint's, because we don't know if the target sign or zero extends its + // pointers. + if (TD && + CI.getType()->getScalarSizeInBits() < TD->getPointerSizeInBits()) { + Value *P = Builder->CreatePtrToInt(CI.getOperand(0), + TD->getIntPtrType(CI.getContext()), + "tmp"); + return new TruncInst(P, CI.getType()); + } + + return commonPointerCastTransforms(CI); +} + +Instruction *InstCombiner::visitIntToPtr(IntToPtrInst &CI) { + // If the source integer type is larger than the intptr_t type for + // this target, do a trunc to the intptr_t type, then inttoptr of it. This + // allows the trunc to be exposed to other transforms. Don't do this for + // extending inttoptr's, because we don't know if the target sign or zero + // extends to pointers. + if (TD && CI.getOperand(0)->getType()->getScalarSizeInBits() > + TD->getPointerSizeInBits()) { + Value *P = Builder->CreateTrunc(CI.getOperand(0), + TD->getIntPtrType(CI.getContext()), "tmp"); + return new IntToPtrInst(P, CI.getType()); + } + + if (Instruction *I = commonCastTransforms(CI)) + return I; + + return 0; +} + +Instruction *InstCombiner::visitBitCast(BitCastInst &CI) { + // If the operands are integer typed then apply the integer transforms, + // otherwise just apply the common ones. + Value *Src = CI.getOperand(0); + const Type *SrcTy = Src->getType(); + const Type *DestTy = CI.getType(); + + if (isa(SrcTy)) { + if (Instruction *I = commonPointerCastTransforms(CI)) + return I; + } else { + if (Instruction *Result = commonCastTransforms(CI)) + return Result; + } + + + // Get rid of casts from one type to the same type. These are useless and can + // be replaced by the operand. + if (DestTy == Src->getType()) + return ReplaceInstUsesWith(CI, Src); + + if (const PointerType *DstPTy = dyn_cast(DestTy)) { + const PointerType *SrcPTy = cast(SrcTy); + const Type *DstElTy = DstPTy->getElementType(); + const Type *SrcElTy = SrcPTy->getElementType(); + + // If the address spaces don't match, don't eliminate the bitcast, which is + // required for changing types. + if (SrcPTy->getAddressSpace() != DstPTy->getAddressSpace()) + return 0; + + // If we are casting a alloca to a pointer to a type of the same + // size, rewrite the allocation instruction to allocate the "right" type. + // There is no need to modify malloc calls because it is their bitcast that + // needs to be cleaned up. + if (AllocaInst *AI = dyn_cast(Src)) + if (Instruction *V = PromoteCastOfAllocation(CI, *AI)) + return V; + + // If the source and destination are pointers, and this cast is equivalent + // to a getelementptr X, 0, 0, 0... turn it into the appropriate gep. + // This can enhance SROA and other transforms that want type-safe pointers. + Constant *ZeroUInt = Constant::getNullValue(Type::getInt32Ty(*Context)); + unsigned NumZeros = 0; + while (SrcElTy != DstElTy && + isa(SrcElTy) && !isa(SrcElTy) && + SrcElTy->getNumContainedTypes() /* not "{}" */) { + SrcElTy = cast(SrcElTy)->getTypeAtIndex(ZeroUInt); + ++NumZeros; + } + + // If we found a path from the src to dest, create the getelementptr now. + if (SrcElTy == DstElTy) { + SmallVector Idxs(NumZeros+1, ZeroUInt); + return GetElementPtrInst::CreateInBounds(Src, Idxs.begin(), Idxs.end(), "", + ((Instruction*) NULL)); + } + } + + if (const VectorType *DestVTy = dyn_cast(DestTy)) { + if (DestVTy->getNumElements() == 1) { + if (!isa(SrcTy)) { + Value *Elem = Builder->CreateBitCast(Src, DestVTy->getElementType()); + return InsertElementInst::Create(UndefValue::get(DestTy), Elem, + Constant::getNullValue(Type::getInt32Ty(*Context))); + } + // FIXME: Canonicalize bitcast(insertelement) -> insertelement(bitcast) + } + } + + if (const VectorType *SrcVTy = dyn_cast(SrcTy)) { + if (SrcVTy->getNumElements() == 1) { + if (!isa(DestTy)) { + Value *Elem = + Builder->CreateExtractElement(Src, + Constant::getNullValue(Type::getInt32Ty(*Context))); + return CastInst::Create(Instruction::BitCast, Elem, DestTy); + } + } + } + + if (ShuffleVectorInst *SVI = dyn_cast(Src)) { + if (SVI->hasOneUse()) { + // Okay, we have (bitconvert (shuffle ..)). Check to see if this is + // a bitconvert to a vector with the same # elts. + if (isa(DestTy) && + cast(DestTy)->getNumElements() == + SVI->getType()->getNumElements() && + SVI->getType()->getNumElements() == + cast(SVI->getOperand(0)->getType())->getNumElements()) { + CastInst *Tmp; + // If either of the operands is a cast from CI.getType(), then + // evaluating the shuffle in the casted destination's type will allow + // us to eliminate at least one cast. + if (((Tmp = dyn_cast(SVI->getOperand(0))) && + Tmp->getOperand(0)->getType() == DestTy) || + ((Tmp = dyn_cast(SVI->getOperand(1))) && + Tmp->getOperand(0)->getType() == DestTy)) { + Value *LHS = Builder->CreateBitCast(SVI->getOperand(0), DestTy); + Value *RHS = Builder->CreateBitCast(SVI->getOperand(1), DestTy); + // Return a new shuffle vector. Use the same element ID's, as we + // know the vector types match #elts. + return new ShuffleVectorInst(LHS, RHS, SVI->getOperand(2)); + } + } + } + } + return 0; +} + +/// GetSelectFoldableOperands - We want to turn code that looks like this: +/// %C = or %A, %B +/// %D = select %cond, %C, %A +/// into: +/// %C = select %cond, %B, 0 +/// %D = or %A, %C +/// +/// Assuming that the specified instruction is an operand to the select, return +/// a bitmask indicating which operands of this instruction are foldable if they +/// equal the other incoming value of the select. +/// +static unsigned GetSelectFoldableOperands(Instruction *I) { + switch (I->getOpcode()) { + case Instruction::Add: + case Instruction::Mul: + case Instruction::And: + case Instruction::Or: + case Instruction::Xor: + return 3; // Can fold through either operand. + case Instruction::Sub: // Can only fold on the amount subtracted. + case Instruction::Shl: // Can only fold on the shift amount. + case Instruction::LShr: + case Instruction::AShr: + return 1; + default: + return 0; // Cannot fold + } +} + +/// GetSelectFoldableConstant - For the same transformation as the previous +/// function, return the identity constant that goes into the select. +static Constant *GetSelectFoldableConstant(Instruction *I, + LLVMContext *Context) { + switch (I->getOpcode()) { + default: llvm_unreachable("This cannot happen!"); + case Instruction::Add: + case Instruction::Sub: + case Instruction::Or: + case Instruction::Xor: + case Instruction::Shl: + case Instruction::LShr: + case Instruction::AShr: + return Constant::getNullValue(I->getType()); + case Instruction::And: + return Constant::getAllOnesValue(I->getType()); + case Instruction::Mul: + return ConstantInt::get(I->getType(), 1); + } +} + +/// FoldSelectOpOp - Here we have (select c, TI, FI), and we know that TI and FI +/// have the same opcode and only one use each. Try to simplify this. +Instruction *InstCombiner::FoldSelectOpOp(SelectInst &SI, Instruction *TI, + Instruction *FI) { + if (TI->getNumOperands() == 1) { + // If this is a non-volatile load or a cast from the same type, + // merge. + if (TI->isCast()) { + if (TI->getOperand(0)->getType() != FI->getOperand(0)->getType()) + return 0; + } else { + return 0; // unknown unary op. + } + + // Fold this by inserting a select from the input values. + SelectInst *NewSI = SelectInst::Create(SI.getCondition(), TI->getOperand(0), + FI->getOperand(0), SI.getName()+".v"); + InsertNewInstBefore(NewSI, SI); + return CastInst::Create(Instruction::CastOps(TI->getOpcode()), NewSI, + TI->getType()); + } + + // Only handle binary operators here. + if (!isa(TI)) + return 0; + + // Figure out if the operations have any operands in common. + Value *MatchOp, *OtherOpT, *OtherOpF; + bool MatchIsOpZero; + if (TI->getOperand(0) == FI->getOperand(0)) { + MatchOp = TI->getOperand(0); + OtherOpT = TI->getOperand(1); + OtherOpF = FI->getOperand(1); + MatchIsOpZero = true; + } else if (TI->getOperand(1) == FI->getOperand(1)) { + MatchOp = TI->getOperand(1); + OtherOpT = TI->getOperand(0); + OtherOpF = FI->getOperand(0); + MatchIsOpZero = false; + } else if (!TI->isCommutative()) { + return 0; + } else if (TI->getOperand(0) == FI->getOperand(1)) { + MatchOp = TI->getOperand(0); + OtherOpT = TI->getOperand(1); + OtherOpF = FI->getOperand(0); + MatchIsOpZero = true; + } else if (TI->getOperand(1) == FI->getOperand(0)) { + MatchOp = TI->getOperand(1); + OtherOpT = TI->getOperand(0); + OtherOpF = FI->getOperand(1); + MatchIsOpZero = true; + } else { + return 0; + } + + // If we reach here, they do have operations in common. + SelectInst *NewSI = SelectInst::Create(SI.getCondition(), OtherOpT, + OtherOpF, SI.getName()+".v"); + InsertNewInstBefore(NewSI, SI); + + if (BinaryOperator *BO = dyn_cast(TI)) { + if (MatchIsOpZero) + return BinaryOperator::Create(BO->getOpcode(), MatchOp, NewSI); + else + return BinaryOperator::Create(BO->getOpcode(), NewSI, MatchOp); + } + llvm_unreachable("Shouldn't get here"); + return 0; +} + +static bool isSelect01(Constant *C1, Constant *C2) { + ConstantInt *C1I = dyn_cast(C1); + if (!C1I) + return false; + ConstantInt *C2I = dyn_cast(C2); + if (!C2I) + return false; + return (C1I->isZero() || C1I->isOne()) && (C2I->isZero() || C2I->isOne()); +} + +/// FoldSelectIntoOp - Try fold the select into one of the operands to +/// facilitate further optimization. +Instruction *InstCombiner::FoldSelectIntoOp(SelectInst &SI, Value *TrueVal, + Value *FalseVal) { + // See the comment above GetSelectFoldableOperands for a description of the + // transformation we are doing here. + if (Instruction *TVI = dyn_cast(TrueVal)) { + if (TVI->hasOneUse() && TVI->getNumOperands() == 2 && + !isa(FalseVal)) { + if (unsigned SFO = GetSelectFoldableOperands(TVI)) { + unsigned OpToFold = 0; + if ((SFO & 1) && FalseVal == TVI->getOperand(0)) { + OpToFold = 1; + } else if ((SFO & 2) && FalseVal == TVI->getOperand(1)) { + OpToFold = 2; + } + + if (OpToFold) { + Constant *C = GetSelectFoldableConstant(TVI, Context); + Value *OOp = TVI->getOperand(2-OpToFold); + // Avoid creating select between 2 constants unless it's selecting + // between 0 and 1. + if (!isa(OOp) || isSelect01(C, cast(OOp))) { + Instruction *NewSel = SelectInst::Create(SI.getCondition(), OOp, C); + InsertNewInstBefore(NewSel, SI); + NewSel->takeName(TVI); + if (BinaryOperator *BO = dyn_cast(TVI)) + return BinaryOperator::Create(BO->getOpcode(), FalseVal, NewSel); + llvm_unreachable("Unknown instruction!!"); + } + } + } + } + } + + if (Instruction *FVI = dyn_cast(FalseVal)) { + if (FVI->hasOneUse() && FVI->getNumOperands() == 2 && + !isa(TrueVal)) { + if (unsigned SFO = GetSelectFoldableOperands(FVI)) { + unsigned OpToFold = 0; + if ((SFO & 1) && TrueVal == FVI->getOperand(0)) { + OpToFold = 1; + } else if ((SFO & 2) && TrueVal == FVI->getOperand(1)) { + OpToFold = 2; + } + + if (OpToFold) { + Constant *C = GetSelectFoldableConstant(FVI, Context); + Value *OOp = FVI->getOperand(2-OpToFold); + // Avoid creating select between 2 constants unless it's selecting + // between 0 and 1. + if (!isa(OOp) || isSelect01(C, cast(OOp))) { + Instruction *NewSel = SelectInst::Create(SI.getCondition(), C, OOp); + InsertNewInstBefore(NewSel, SI); + NewSel->takeName(FVI); + if (BinaryOperator *BO = dyn_cast(FVI)) + return BinaryOperator::Create(BO->getOpcode(), TrueVal, NewSel); + llvm_unreachable("Unknown instruction!!"); + } + } + } + } + } + + return 0; +} + +/// visitSelectInstWithICmp - Visit a SelectInst that has an +/// ICmpInst as its first operand. +/// +Instruction *InstCombiner::visitSelectInstWithICmp(SelectInst &SI, + ICmpInst *ICI) { + bool Changed = false; + ICmpInst::Predicate Pred = ICI->getPredicate(); + Value *CmpLHS = ICI->getOperand(0); + Value *CmpRHS = ICI->getOperand(1); + Value *TrueVal = SI.getTrueValue(); + Value *FalseVal = SI.getFalseValue(); + + // Check cases where the comparison is with a constant that + // can be adjusted to fit the min/max idiom. We may edit ICI in + // place here, so make sure the select is the only user. + if (ICI->hasOneUse()) + if (ConstantInt *CI = dyn_cast(CmpRHS)) { + switch (Pred) { + default: break; + case ICmpInst::ICMP_ULT: + case ICmpInst::ICMP_SLT: { + // X < MIN ? T : F --> F + if (CI->isMinValue(Pred == ICmpInst::ICMP_SLT)) + return ReplaceInstUsesWith(SI, FalseVal); + // X < C ? X : C-1 --> X > C-1 ? C-1 : X + Constant *AdjustedRHS = SubOne(CI); + if ((CmpLHS == TrueVal && AdjustedRHS == FalseVal) || + (CmpLHS == FalseVal && AdjustedRHS == TrueVal)) { + Pred = ICmpInst::getSwappedPredicate(Pred); + CmpRHS = AdjustedRHS; + std::swap(FalseVal, TrueVal); + ICI->setPredicate(Pred); + ICI->setOperand(1, CmpRHS); + SI.setOperand(1, TrueVal); + SI.setOperand(2, FalseVal); + Changed = true; + } + break; + } + case ICmpInst::ICMP_UGT: + case ICmpInst::ICMP_SGT: { + // X > MAX ? T : F --> F + if (CI->isMaxValue(Pred == ICmpInst::ICMP_SGT)) + return ReplaceInstUsesWith(SI, FalseVal); + // X > C ? X : C+1 --> X < C+1 ? C+1 : X + Constant *AdjustedRHS = AddOne(CI); + if ((CmpLHS == TrueVal && AdjustedRHS == FalseVal) || + (CmpLHS == FalseVal && AdjustedRHS == TrueVal)) { + Pred = ICmpInst::getSwappedPredicate(Pred); + CmpRHS = AdjustedRHS; + std::swap(FalseVal, TrueVal); + ICI->setPredicate(Pred); + ICI->setOperand(1, CmpRHS); + SI.setOperand(1, TrueVal); + SI.setOperand(2, FalseVal); + Changed = true; + } + break; + } + } + + // (x ashr x, 31 -> all ones if signed + // (x >s -1) ? -1 : 0 -> ashr x, 31 -> all ones if not signed + CmpInst::Predicate Pred = CmpInst::BAD_ICMP_PREDICATE; + if (match(TrueVal, m_ConstantInt<-1>()) && + match(FalseVal, m_ConstantInt<0>())) + Pred = ICI->getPredicate(); + else if (match(TrueVal, m_ConstantInt<0>()) && + match(FalseVal, m_ConstantInt<-1>())) + Pred = CmpInst::getInversePredicate(ICI->getPredicate()); + + if (Pred != CmpInst::BAD_ICMP_PREDICATE) { + // If we are just checking for a icmp eq of a single bit and zext'ing it + // to an integer, then shift the bit to the appropriate place and then + // cast to integer to avoid the comparison. + const APInt &Op1CV = CI->getValue(); + + // sext (x x>>s31 true if signbit set. + // sext (x >s -1) to i32 --> (x>>s31)^-1 true if signbit clear. + if ((Pred == ICmpInst::ICMP_SLT && Op1CV == 0) || + (Pred == ICmpInst::ICMP_SGT && Op1CV.isAllOnesValue())) { + Value *In = ICI->getOperand(0); + Value *Sh = ConstantInt::get(In->getType(), + In->getType()->getScalarSizeInBits()-1); + In = InsertNewInstBefore(BinaryOperator::CreateAShr(In, Sh, + In->getName()+".lobit"), + *ICI); + if (In->getType() != SI.getType()) + In = CastInst::CreateIntegerCast(In, SI.getType(), + true/*SExt*/, "tmp", ICI); + + if (Pred == ICmpInst::ICMP_SGT) + In = InsertNewInstBefore(BinaryOperator::CreateNot(In, + In->getName()+".not"), *ICI); + + return ReplaceInstUsesWith(SI, In); + } + } + } + + if (CmpLHS == TrueVal && CmpRHS == FalseVal) { + // Transform (X == Y) ? X : Y -> Y + if (Pred == ICmpInst::ICMP_EQ) + return ReplaceInstUsesWith(SI, FalseVal); + // Transform (X != Y) ? X : Y -> X + if (Pred == ICmpInst::ICMP_NE) + return ReplaceInstUsesWith(SI, TrueVal); + /// NOTE: if we wanted to, this is where to detect integer MIN/MAX + + } else if (CmpLHS == FalseVal && CmpRHS == TrueVal) { + // Transform (X == Y) ? Y : X -> X + if (Pred == ICmpInst::ICMP_EQ) + return ReplaceInstUsesWith(SI, FalseVal); + // Transform (X != Y) ? Y : X -> Y + if (Pred == ICmpInst::ICMP_NE) + return ReplaceInstUsesWith(SI, TrueVal); + /// NOTE: if we wanted to, this is where to detect integer MIN/MAX + } + + /// NOTE: if we wanted to, this is where to detect integer ABS + + return Changed ? &SI : 0; +} + + +/// CanSelectOperandBeMappingIntoPredBlock - SI is a select whose condition is a +/// PHI node (but the two may be in different blocks). See if the true/false +/// values (V) are live in all of the predecessor blocks of the PHI. For +/// example, cases like this cannot be mapped: +/// +/// X = phi [ C1, BB1], [C2, BB2] +/// Y = add +/// Z = select X, Y, 0 +/// +/// because Y is not live in BB1/BB2. +/// +static bool CanSelectOperandBeMappingIntoPredBlock(const Value *V, + const SelectInst &SI) { + // If the value is a non-instruction value like a constant or argument, it + // can always be mapped. + const Instruction *I = dyn_cast(V); + if (I == 0) return true; + + // If V is a PHI node defined in the same block as the condition PHI, we can + // map the arguments. + const PHINode *CondPHI = cast(SI.getCondition()); + + if (const PHINode *VP = dyn_cast(I)) + if (VP->getParent() == CondPHI->getParent()) + return true; + + // Otherwise, if the PHI and select are defined in the same block and if V is + // defined in a different block, then we can transform it. + if (SI.getParent() == CondPHI->getParent() && + I->getParent() != CondPHI->getParent()) + return true; + + // Otherwise we have a 'hard' case and we can't tell without doing more + // detailed dominator based analysis, punt. + return false; +} + +Instruction *InstCombiner::visitSelectInst(SelectInst &SI) { + Value *CondVal = SI.getCondition(); + Value *TrueVal = SI.getTrueValue(); + Value *FalseVal = SI.getFalseValue(); + + // select true, X, Y -> X + // select false, X, Y -> Y + if (ConstantInt *C = dyn_cast(CondVal)) + return ReplaceInstUsesWith(SI, C->getZExtValue() ? TrueVal : FalseVal); + + // select C, X, X -> X + if (TrueVal == FalseVal) + return ReplaceInstUsesWith(SI, TrueVal); + + if (isa(TrueVal)) // select C, undef, X -> X + return ReplaceInstUsesWith(SI, FalseVal); + if (isa(FalseVal)) // select C, X, undef -> X + return ReplaceInstUsesWith(SI, TrueVal); + if (isa(CondVal)) { // select undef, X, Y -> X or Y + if (isa(TrueVal)) + return ReplaceInstUsesWith(SI, TrueVal); + else + return ReplaceInstUsesWith(SI, FalseVal); + } + + if (SI.getType() == Type::getInt1Ty(*Context)) { + if (ConstantInt *C = dyn_cast(TrueVal)) { + if (C->getZExtValue()) { + // Change: A = select B, true, C --> A = or B, C + return BinaryOperator::CreateOr(CondVal, FalseVal); + } else { + // Change: A = select B, false, C --> A = and !B, C + Value *NotCond = + InsertNewInstBefore(BinaryOperator::CreateNot(CondVal, + "not."+CondVal->getName()), SI); + return BinaryOperator::CreateAnd(NotCond, FalseVal); + } + } else if (ConstantInt *C = dyn_cast(FalseVal)) { + if (C->getZExtValue() == false) { + // Change: A = select B, C, false --> A = and B, C + return BinaryOperator::CreateAnd(CondVal, TrueVal); + } else { + // Change: A = select B, C, true --> A = or !B, C + Value *NotCond = + InsertNewInstBefore(BinaryOperator::CreateNot(CondVal, + "not."+CondVal->getName()), SI); + return BinaryOperator::CreateOr(NotCond, TrueVal); + } + } + + // select a, b, a -> a&b + // select a, a, b -> a|b + if (CondVal == TrueVal) + return BinaryOperator::CreateOr(CondVal, FalseVal); + else if (CondVal == FalseVal) + return BinaryOperator::CreateAnd(CondVal, TrueVal); + } + + // Selecting between two integer constants? + if (ConstantInt *TrueValC = dyn_cast(TrueVal)) + if (ConstantInt *FalseValC = dyn_cast(FalseVal)) { + // select C, 1, 0 -> zext C to int + if (FalseValC->isZero() && TrueValC->getValue() == 1) { + return CastInst::Create(Instruction::ZExt, CondVal, SI.getType()); + } else if (TrueValC->isZero() && FalseValC->getValue() == 1) { + // select C, 0, 1 -> zext !C to int + Value *NotCond = + InsertNewInstBefore(BinaryOperator::CreateNot(CondVal, + "not."+CondVal->getName()), SI); + return CastInst::Create(Instruction::ZExt, NotCond, SI.getType()); + } + + if (ICmpInst *IC = dyn_cast(SI.getCondition())) { + // If one of the constants is zero (we know they can't both be) and we + // have an icmp instruction with zero, and we have an 'and' with the + // non-constant value, eliminate this whole mess. This corresponds to + // cases like this: ((X & 27) ? 27 : 0) + if (TrueValC->isZero() || FalseValC->isZero()) + if (IC->isEquality() && isa(IC->getOperand(1)) && + cast(IC->getOperand(1))->isNullValue()) + if (Instruction *ICA = dyn_cast(IC->getOperand(0))) + if (ICA->getOpcode() == Instruction::And && + isa(ICA->getOperand(1)) && + (ICA->getOperand(1) == TrueValC || + ICA->getOperand(1) == FalseValC) && + isOneBitSet(cast(ICA->getOperand(1)))) { + // Okay, now we know that everything is set up, we just don't + // know whether we have a icmp_ne or icmp_eq and whether the + // true or false val is the zero. + bool ShouldNotVal = !TrueValC->isZero(); + ShouldNotVal ^= IC->getPredicate() == ICmpInst::ICMP_NE; + Value *V = ICA; + if (ShouldNotVal) + V = InsertNewInstBefore(BinaryOperator::Create( + Instruction::Xor, V, ICA->getOperand(1)), SI); + return ReplaceInstUsesWith(SI, V); + } + } + } + + // See if we are selecting two values based on a comparison of the two values. + if (FCmpInst *FCI = dyn_cast(CondVal)) { + if (FCI->getOperand(0) == TrueVal && FCI->getOperand(1) == FalseVal) { + // Transform (X == Y) ? X : Y -> Y + if (FCI->getPredicate() == FCmpInst::FCMP_OEQ) { + // This is not safe in general for floating point: + // consider X== -0, Y== +0. + // It becomes safe if either operand is a nonzero constant. + ConstantFP *CFPt, *CFPf; + if (((CFPt = dyn_cast(TrueVal)) && + !CFPt->getValueAPF().isZero()) || + ((CFPf = dyn_cast(FalseVal)) && + !CFPf->getValueAPF().isZero())) + return ReplaceInstUsesWith(SI, FalseVal); + } + // Transform (X != Y) ? X : Y -> X + if (FCI->getPredicate() == FCmpInst::FCMP_ONE) + return ReplaceInstUsesWith(SI, TrueVal); + // NOTE: if we wanted to, this is where to detect MIN/MAX + + } else if (FCI->getOperand(0) == FalseVal && FCI->getOperand(1) == TrueVal){ + // Transform (X == Y) ? Y : X -> X + if (FCI->getPredicate() == FCmpInst::FCMP_OEQ) { + // This is not safe in general for floating point: + // consider X== -0, Y== +0. + // It becomes safe if either operand is a nonzero constant. + ConstantFP *CFPt, *CFPf; + if (((CFPt = dyn_cast(TrueVal)) && + !CFPt->getValueAPF().isZero()) || + ((CFPf = dyn_cast(FalseVal)) && + !CFPf->getValueAPF().isZero())) + return ReplaceInstUsesWith(SI, FalseVal); + } + // Transform (X != Y) ? Y : X -> Y + if (FCI->getPredicate() == FCmpInst::FCMP_ONE) + return ReplaceInstUsesWith(SI, TrueVal); + // NOTE: if we wanted to, this is where to detect MIN/MAX + } + // NOTE: if we wanted to, this is where to detect ABS + } + + // See if we are selecting two values based on a comparison of the two values. + if (ICmpInst *ICI = dyn_cast(CondVal)) + if (Instruction *Result = visitSelectInstWithICmp(SI, ICI)) + return Result; + + if (Instruction *TI = dyn_cast(TrueVal)) + if (Instruction *FI = dyn_cast(FalseVal)) + if (TI->hasOneUse() && FI->hasOneUse()) { + Instruction *AddOp = 0, *SubOp = 0; + + // Turn (select C, (op X, Y), (op X, Z)) -> (op X, (select C, Y, Z)) + if (TI->getOpcode() == FI->getOpcode()) + if (Instruction *IV = FoldSelectOpOp(SI, TI, FI)) + return IV; + + // Turn select C, (X+Y), (X-Y) --> (X+(select C, Y, (-Y))). This is + // even legal for FP. + if ((TI->getOpcode() == Instruction::Sub && + FI->getOpcode() == Instruction::Add) || + (TI->getOpcode() == Instruction::FSub && + FI->getOpcode() == Instruction::FAdd)) { + AddOp = FI; SubOp = TI; + } else if ((FI->getOpcode() == Instruction::Sub && + TI->getOpcode() == Instruction::Add) || + (FI->getOpcode() == Instruction::FSub && + TI->getOpcode() == Instruction::FAdd)) { + AddOp = TI; SubOp = FI; + } + + if (AddOp) { + Value *OtherAddOp = 0; + if (SubOp->getOperand(0) == AddOp->getOperand(0)) { + OtherAddOp = AddOp->getOperand(1); + } else if (SubOp->getOperand(0) == AddOp->getOperand(1)) { + OtherAddOp = AddOp->getOperand(0); + } + + if (OtherAddOp) { + // So at this point we know we have (Y -> OtherAddOp): + // select C, (add X, Y), (sub X, Z) + Value *NegVal; // Compute -Z + if (Constant *C = dyn_cast(SubOp->getOperand(1))) { + NegVal = ConstantExpr::getNeg(C); + } else { + NegVal = InsertNewInstBefore( + BinaryOperator::CreateNeg(SubOp->getOperand(1), + "tmp"), SI); + } + + Value *NewTrueOp = OtherAddOp; + Value *NewFalseOp = NegVal; + if (AddOp != TI) + std::swap(NewTrueOp, NewFalseOp); + Instruction *NewSel = + SelectInst::Create(CondVal, NewTrueOp, + NewFalseOp, SI.getName() + ".p"); + + NewSel = InsertNewInstBefore(NewSel, SI); + return BinaryOperator::CreateAdd(SubOp->getOperand(0), NewSel); + } + } + } + + // See if we can fold the select into one of our operands. + if (SI.getType()->isInteger()) { + Instruction *FoldI = FoldSelectIntoOp(SI, TrueVal, FalseVal); + if (FoldI) + return FoldI; + } + + // See if we can fold the select into a phi node if the condition is a select. + if (isa(SI.getCondition())) + // The true/false values have to be live in the PHI predecessor's blocks. + if (CanSelectOperandBeMappingIntoPredBlock(TrueVal, SI) && + CanSelectOperandBeMappingIntoPredBlock(FalseVal, SI)) + if (Instruction *NV = FoldOpIntoPhi(SI)) + return NV; + + if (BinaryOperator::isNot(CondVal)) { + SI.setOperand(0, BinaryOperator::getNotArgument(CondVal)); + SI.setOperand(1, FalseVal); + SI.setOperand(2, TrueVal); + return &SI; + } + + return 0; +} + +/// EnforceKnownAlignment - If the specified pointer points to an object that +/// we control, modify the object's alignment to PrefAlign. This isn't +/// often possible though. If alignment is important, a more reliable approach +/// is to simply align all global variables and allocation instructions to +/// their preferred alignment from the beginning. +/// +static unsigned EnforceKnownAlignment(Value *V, + unsigned Align, unsigned PrefAlign) { + + User *U = dyn_cast(V); + if (!U) return Align; + + switch (Operator::getOpcode(U)) { + default: break; + case Instruction::BitCast: + return EnforceKnownAlignment(U->getOperand(0), Align, PrefAlign); + case Instruction::GetElementPtr: { + // If all indexes are zero, it is just the alignment of the base pointer. + bool AllZeroOperands = true; + for (User::op_iterator i = U->op_begin() + 1, e = U->op_end(); i != e; ++i) + if (!isa(*i) || + !cast(*i)->isNullValue()) { + AllZeroOperands = false; + break; + } + + if (AllZeroOperands) { + // Treat this like a bitcast. + return EnforceKnownAlignment(U->getOperand(0), Align, PrefAlign); + } + break; + } + } + + if (GlobalValue *GV = dyn_cast(V)) { + // If there is a large requested alignment and we can, bump up the alignment + // of the global. + if (!GV->isDeclaration()) { + if (GV->getAlignment() >= PrefAlign) + Align = GV->getAlignment(); + else { + GV->setAlignment(PrefAlign); + Align = PrefAlign; + } + } + } else if (AllocaInst *AI = dyn_cast(V)) { + // If there is a requested alignment and if this is an alloca, round up. + if (AI->getAlignment() >= PrefAlign) + Align = AI->getAlignment(); + else { + AI->setAlignment(PrefAlign); + Align = PrefAlign; + } + } + + return Align; +} + +/// GetOrEnforceKnownAlignment - If the specified pointer has an alignment that +/// we can determine, return it, otherwise return 0. If PrefAlign is specified, +/// and it is more than the alignment of the ultimate object, see if we can +/// increase the alignment of the ultimate object, making this check succeed. +unsigned InstCombiner::GetOrEnforceKnownAlignment(Value *V, + unsigned PrefAlign) { + unsigned BitWidth = TD ? TD->getTypeSizeInBits(V->getType()) : + sizeof(PrefAlign) * CHAR_BIT; + APInt Mask = APInt::getAllOnesValue(BitWidth); + APInt KnownZero(BitWidth, 0), KnownOne(BitWidth, 0); + ComputeMaskedBits(V, Mask, KnownZero, KnownOne); + unsigned TrailZ = KnownZero.countTrailingOnes(); + unsigned Align = 1u << std::min(BitWidth - 1, TrailZ); + + if (PrefAlign > Align) + Align = EnforceKnownAlignment(V, Align, PrefAlign); + + // We don't need to make any adjustment. + return Align; +} + +Instruction *InstCombiner::SimplifyMemTransfer(MemIntrinsic *MI) { + unsigned DstAlign = GetOrEnforceKnownAlignment(MI->getOperand(1)); + unsigned SrcAlign = GetOrEnforceKnownAlignment(MI->getOperand(2)); + unsigned MinAlign = std::min(DstAlign, SrcAlign); + unsigned CopyAlign = MI->getAlignment(); + + if (CopyAlign < MinAlign) { + MI->setAlignment(ConstantInt::get(MI->getAlignmentType(), + MinAlign, false)); + return MI; + } + + // If MemCpyInst length is 1/2/4/8 bytes then replace memcpy with + // load/store. + ConstantInt *MemOpLength = dyn_cast(MI->getOperand(3)); + if (MemOpLength == 0) return 0; + + // Source and destination pointer types are always "i8*" for intrinsic. See + // if the size is something we can handle with a single primitive load/store. + // A single load+store correctly handles overlapping memory in the memmove + // case. + unsigned Size = MemOpLength->getZExtValue(); + if (Size == 0) return MI; // Delete this mem transfer. + + if (Size > 8 || (Size&(Size-1))) + return 0; // If not 1/2/4/8 bytes, exit. + + // Use an integer load+store unless we can find something better. + Type *NewPtrTy = + PointerType::getUnqual(IntegerType::get(*Context, Size<<3)); + + // Memcpy forces the use of i8* for the source and destination. That means + // that if you're using memcpy to move one double around, you'll get a cast + // from double* to i8*. We'd much rather use a double load+store rather than + // an i64 load+store, here because this improves the odds that the source or + // dest address will be promotable. See if we can find a better type than the + // integer datatype. + if (Value *Op = getBitCastOperand(MI->getOperand(1))) { + const Type *SrcETy = cast(Op->getType())->getElementType(); + if (TD && SrcETy->isSized() && TD->getTypeStoreSize(SrcETy) == Size) { + // The SrcETy might be something like {{{double}}} or [1 x double]. Rip + // down through these levels if so. + while (!SrcETy->isSingleValueType()) { + if (const StructType *STy = dyn_cast(SrcETy)) { + if (STy->getNumElements() == 1) + SrcETy = STy->getElementType(0); + else + break; + } else if (const ArrayType *ATy = dyn_cast(SrcETy)) { + if (ATy->getNumElements() == 1) + SrcETy = ATy->getElementType(); + else + break; + } else + break; + } + + if (SrcETy->isSingleValueType()) + NewPtrTy = PointerType::getUnqual(SrcETy); + } + } + + + // If the memcpy/memmove provides better alignment info than we can + // infer, use it. + SrcAlign = std::max(SrcAlign, CopyAlign); + DstAlign = std::max(DstAlign, CopyAlign); + + Value *Src = Builder->CreateBitCast(MI->getOperand(2), NewPtrTy); + Value *Dest = Builder->CreateBitCast(MI->getOperand(1), NewPtrTy); + Instruction *L = new LoadInst(Src, "tmp", false, SrcAlign); + InsertNewInstBefore(L, *MI); + InsertNewInstBefore(new StoreInst(L, Dest, false, DstAlign), *MI); + + // Set the size of the copy to 0, it will be deleted on the next iteration. + MI->setOperand(3, Constant::getNullValue(MemOpLength->getType())); + return MI; +} + +Instruction *InstCombiner::SimplifyMemSet(MemSetInst *MI) { + unsigned Alignment = GetOrEnforceKnownAlignment(MI->getDest()); + if (MI->getAlignment() < Alignment) { + MI->setAlignment(ConstantInt::get(MI->getAlignmentType(), + Alignment, false)); + return MI; + } + + // Extract the length and alignment and fill if they are constant. + ConstantInt *LenC = dyn_cast(MI->getLength()); + ConstantInt *FillC = dyn_cast(MI->getValue()); + if (!LenC || !FillC || FillC->getType() != Type::getInt8Ty(*Context)) + return 0; + uint64_t Len = LenC->getZExtValue(); + Alignment = MI->getAlignment(); + + // If the length is zero, this is a no-op + if (Len == 0) return MI; // memset(d,c,0,a) -> noop + + // memset(s,c,n) -> store s, c (for n=1,2,4,8) + if (Len <= 8 && isPowerOf2_32((uint32_t)Len)) { + const Type *ITy = IntegerType::get(*Context, Len*8); // n=1 -> i8. + + Value *Dest = MI->getDest(); + Dest = Builder->CreateBitCast(Dest, PointerType::getUnqual(ITy)); + + // Alignment 0 is identity for alignment 1 for memset, but not store. + if (Alignment == 0) Alignment = 1; + + // Extract the fill value and store. + uint64_t Fill = FillC->getZExtValue()*0x0101010101010101ULL; + InsertNewInstBefore(new StoreInst(ConstantInt::get(ITy, Fill), + Dest, false, Alignment), *MI); + + // Set the size of the copy to 0, it will be deleted on the next iteration. + MI->setLength(Constant::getNullValue(LenC->getType())); + return MI; + } + + return 0; +} + + +/// visitCallInst - CallInst simplification. This mostly only handles folding +/// of intrinsic instructions. For normal calls, it allows visitCallSite to do +/// the heavy lifting. +/// +Instruction *InstCombiner::visitCallInst(CallInst &CI) { + if (isFreeCall(&CI)) + return visitFree(CI); + + // If the caller function is nounwind, mark the call as nounwind, even if the + // callee isn't. + if (CI.getParent()->getParent()->doesNotThrow() && + !CI.doesNotThrow()) { + CI.setDoesNotThrow(); + return &CI; + } + + IntrinsicInst *II = dyn_cast(&CI); + if (!II) return visitCallSite(&CI); + + // Intrinsics cannot occur in an invoke, so handle them here instead of in + // visitCallSite. + if (MemIntrinsic *MI = dyn_cast(II)) { + bool Changed = false; + + // memmove/cpy/set of zero bytes is a noop. + if (Constant *NumBytes = dyn_cast(MI->getLength())) { + if (NumBytes->isNullValue()) return EraseInstFromFunction(CI); + + if (ConstantInt *CI = dyn_cast(NumBytes)) + if (CI->getZExtValue() == 1) { + // Replace the instruction with just byte operations. We would + // transform other cases to loads/stores, but we don't know if + // alignment is sufficient. + } + } + + // If we have a memmove and the source operation is a constant global, + // then the source and dest pointers can't alias, so we can change this + // into a call to memcpy. + if (MemMoveInst *MMI = dyn_cast(MI)) { + if (GlobalVariable *GVSrc = dyn_cast(MMI->getSource())) + if (GVSrc->isConstant()) { + Module *M = CI.getParent()->getParent()->getParent(); + Intrinsic::ID MemCpyID = Intrinsic::memcpy; + const Type *Tys[1]; + Tys[0] = CI.getOperand(3)->getType(); + CI.setOperand(0, + Intrinsic::getDeclaration(M, MemCpyID, Tys, 1)); + Changed = true; + } + + // memmove(x,x,size) -> noop. + if (MMI->getSource() == MMI->getDest()) + return EraseInstFromFunction(CI); + } + + // If we can determine a pointer alignment that is bigger than currently + // set, update the alignment. + if (isa(MI)) { + if (Instruction *I = SimplifyMemTransfer(MI)) + return I; + } else if (MemSetInst *MSI = dyn_cast(MI)) { + if (Instruction *I = SimplifyMemSet(MSI)) + return I; + } + + if (Changed) return II; + } + + switch (II->getIntrinsicID()) { + default: break; + case Intrinsic::bswap: + // bswap(bswap(x)) -> x + if (IntrinsicInst *Operand = dyn_cast(II->getOperand(1))) + if (Operand->getIntrinsicID() == Intrinsic::bswap) + return ReplaceInstUsesWith(CI, Operand->getOperand(1)); + break; + case Intrinsic::uadd_with_overflow: { + Value *LHS = II->getOperand(1), *RHS = II->getOperand(2); + const IntegerType *IT = cast(II->getOperand(1)->getType()); + uint32_t BitWidth = IT->getBitWidth(); + APInt Mask = APInt::getSignBit(BitWidth); + APInt LHSKnownZero(BitWidth, 0); + APInt LHSKnownOne(BitWidth, 0); + ComputeMaskedBits(LHS, Mask, LHSKnownZero, LHSKnownOne); + bool LHSKnownNegative = LHSKnownOne[BitWidth - 1]; + bool LHSKnownPositive = LHSKnownZero[BitWidth - 1]; + + if (LHSKnownNegative || LHSKnownPositive) { + APInt RHSKnownZero(BitWidth, 0); + APInt RHSKnownOne(BitWidth, 0); + ComputeMaskedBits(RHS, Mask, RHSKnownZero, RHSKnownOne); + bool RHSKnownNegative = RHSKnownOne[BitWidth - 1]; + bool RHSKnownPositive = RHSKnownZero[BitWidth - 1]; + if (LHSKnownNegative && RHSKnownNegative) { + // The sign bit is set in both cases: this MUST overflow. + // Create a simple add instruction, and insert it into the struct. + Instruction *Add = BinaryOperator::CreateAdd(LHS, RHS, "", &CI); + Worklist.Add(Add); + Constant *V[2]; + V[0] = UndefValue::get(LHS->getType()); + V[1] = ConstantInt::getTrue(*Context); + Constant *Struct = ConstantStruct::get(*Context, V, 2, false); + return InsertValueInst::Create(Struct, Add, 0); + } + + if (LHSKnownPositive && RHSKnownPositive) { + // The sign bit is clear in both cases: this CANNOT overflow. + // Create a simple add instruction, and insert it into the struct. + Instruction *Add = BinaryOperator::CreateNUWAdd(LHS, RHS, "", &CI); + Worklist.Add(Add); + Constant *V[2]; + V[0] = UndefValue::get(LHS->getType()); + V[1] = ConstantInt::getFalse(*Context); + Constant *Struct = ConstantStruct::get(*Context, V, 2, false); + return InsertValueInst::Create(Struct, Add, 0); + } + } + } + // FALL THROUGH uadd into sadd + case Intrinsic::sadd_with_overflow: + // Canonicalize constants into the RHS. + if (isa(II->getOperand(1)) && + !isa(II->getOperand(2))) { + Value *LHS = II->getOperand(1); + II->setOperand(1, II->getOperand(2)); + II->setOperand(2, LHS); + return II; + } + + // X + undef -> undef + if (isa(II->getOperand(2))) + return ReplaceInstUsesWith(CI, UndefValue::get(II->getType())); + + if (ConstantInt *RHS = dyn_cast(II->getOperand(2))) { + // X + 0 -> {X, false} + if (RHS->isZero()) { + Constant *V[] = { + UndefValue::get(II->getType()), ConstantInt::getFalse(*Context) + }; + Constant *Struct = ConstantStruct::get(*Context, V, 2, false); + return InsertValueInst::Create(Struct, II->getOperand(1), 0); + } + } + break; + case Intrinsic::usub_with_overflow: + case Intrinsic::ssub_with_overflow: + // undef - X -> undef + // X - undef -> undef + if (isa(II->getOperand(1)) || + isa(II->getOperand(2))) + return ReplaceInstUsesWith(CI, UndefValue::get(II->getType())); + + if (ConstantInt *RHS = dyn_cast(II->getOperand(2))) { + // X - 0 -> {X, false} + if (RHS->isZero()) { + Constant *V[] = { + UndefValue::get(II->getType()), ConstantInt::getFalse(*Context) + }; + Constant *Struct = ConstantStruct::get(*Context, V, 2, false); + return InsertValueInst::Create(Struct, II->getOperand(1), 0); + } + } + break; + case Intrinsic::umul_with_overflow: + case Intrinsic::smul_with_overflow: + // Canonicalize constants into the RHS. + if (isa(II->getOperand(1)) && + !isa(II->getOperand(2))) { + Value *LHS = II->getOperand(1); + II->setOperand(1, II->getOperand(2)); + II->setOperand(2, LHS); + return II; + } + + // X * undef -> undef + if (isa(II->getOperand(2))) + return ReplaceInstUsesWith(CI, UndefValue::get(II->getType())); + + if (ConstantInt *RHSI = dyn_cast(II->getOperand(2))) { + // X*0 -> {0, false} + if (RHSI->isZero()) + return ReplaceInstUsesWith(CI, Constant::getNullValue(II->getType())); + + // X * 1 -> {X, false} + if (RHSI->equalsInt(1)) { + Constant *V[2]; + V[0] = UndefValue::get(II->getType()); + V[1] = ConstantInt::getFalse(*Context); + Constant *Struct = ConstantStruct::get(*Context, V, 2, false); + return InsertValueInst::Create(Struct, II->getOperand(1), 1); + } + } + break; + case Intrinsic::ppc_altivec_lvx: + case Intrinsic::ppc_altivec_lvxl: + case Intrinsic::x86_sse_loadu_ps: + case Intrinsic::x86_sse2_loadu_pd: + case Intrinsic::x86_sse2_loadu_dq: + // Turn PPC lvx -> load if the pointer is known aligned. + // Turn X86 loadups -> load if the pointer is known aligned. + if (GetOrEnforceKnownAlignment(II->getOperand(1), 16) >= 16) { + Value *Ptr = Builder->CreateBitCast(II->getOperand(1), + PointerType::getUnqual(II->getType())); + return new LoadInst(Ptr); + } + break; + case Intrinsic::ppc_altivec_stvx: + case Intrinsic::ppc_altivec_stvxl: + // Turn stvx -> store if the pointer is known aligned. + if (GetOrEnforceKnownAlignment(II->getOperand(2), 16) >= 16) { + const Type *OpPtrTy = + PointerType::getUnqual(II->getOperand(1)->getType()); + Value *Ptr = Builder->CreateBitCast(II->getOperand(2), OpPtrTy); + return new StoreInst(II->getOperand(1), Ptr); + } + break; + case Intrinsic::x86_sse_storeu_ps: + case Intrinsic::x86_sse2_storeu_pd: + case Intrinsic::x86_sse2_storeu_dq: + // Turn X86 storeu -> store if the pointer is known aligned. + if (GetOrEnforceKnownAlignment(II->getOperand(1), 16) >= 16) { + const Type *OpPtrTy = + PointerType::getUnqual(II->getOperand(2)->getType()); + Value *Ptr = Builder->CreateBitCast(II->getOperand(1), OpPtrTy); + return new StoreInst(II->getOperand(2), Ptr); + } + break; + + case Intrinsic::x86_sse_cvttss2si: { + // These intrinsics only demands the 0th element of its input vector. If + // we can simplify the input based on that, do so now. + unsigned VWidth = + cast(II->getOperand(1)->getType())->getNumElements(); + APInt DemandedElts(VWidth, 1); + APInt UndefElts(VWidth, 0); + if (Value *V = SimplifyDemandedVectorElts(II->getOperand(1), DemandedElts, + UndefElts)) { + II->setOperand(1, V); + return II; + } + break; + } + + case Intrinsic::ppc_altivec_vperm: + // Turn vperm(V1,V2,mask) -> shuffle(V1,V2,mask) if mask is a constant. + if (ConstantVector *Mask = dyn_cast(II->getOperand(3))) { + assert(Mask->getNumOperands() == 16 && "Bad type for intrinsic!"); + + // Check that all of the elements are integer constants or undefs. + bool AllEltsOk = true; + for (unsigned i = 0; i != 16; ++i) { + if (!isa(Mask->getOperand(i)) && + !isa(Mask->getOperand(i))) { + AllEltsOk = false; + break; + } + } + + if (AllEltsOk) { + // Cast the input vectors to byte vectors. + Value *Op0 = Builder->CreateBitCast(II->getOperand(1), Mask->getType()); + Value *Op1 = Builder->CreateBitCast(II->getOperand(2), Mask->getType()); + Value *Result = UndefValue::get(Op0->getType()); + + // Only extract each element once. + Value *ExtractedElts[32]; + memset(ExtractedElts, 0, sizeof(ExtractedElts)); + + for (unsigned i = 0; i != 16; ++i) { + if (isa(Mask->getOperand(i))) + continue; + unsigned Idx=cast(Mask->getOperand(i))->getZExtValue(); + Idx &= 31; // Match the hardware behavior. + + if (ExtractedElts[Idx] == 0) { + ExtractedElts[Idx] = + Builder->CreateExtractElement(Idx < 16 ? Op0 : Op1, + ConstantInt::get(Type::getInt32Ty(*Context), Idx&15, false), + "tmp"); + } + + // Insert this value into the result vector. + Result = Builder->CreateInsertElement(Result, ExtractedElts[Idx], + ConstantInt::get(Type::getInt32Ty(*Context), i, false), + "tmp"); + } + return CastInst::Create(Instruction::BitCast, Result, CI.getType()); + } + } + break; + + case Intrinsic::stackrestore: { + // If the save is right next to the restore, remove the restore. This can + // happen when variable allocas are DCE'd. + if (IntrinsicInst *SS = dyn_cast(II->getOperand(1))) { + if (SS->getIntrinsicID() == Intrinsic::stacksave) { + BasicBlock::iterator BI = SS; + if (&*++BI == II) + return EraseInstFromFunction(CI); + } + } + + // Scan down this block to see if there is another stack restore in the + // same block without an intervening call/alloca. + BasicBlock::iterator BI = II; + TerminatorInst *TI = II->getParent()->getTerminator(); + bool CannotRemove = false; + for (++BI; &*BI != TI; ++BI) { + if (isa(BI) || isMalloc(BI)) { + CannotRemove = true; + break; + } + if (CallInst *BCI = dyn_cast(BI)) { + if (IntrinsicInst *II = dyn_cast(BCI)) { + // If there is a stackrestore below this one, remove this one. + if (II->getIntrinsicID() == Intrinsic::stackrestore) + return EraseInstFromFunction(CI); + // Otherwise, ignore the intrinsic. + } else { + // If we found a non-intrinsic call, we can't remove the stack + // restore. + CannotRemove = true; + break; + } + } + } + + // If the stack restore is in a return/unwind block and if there are no + // allocas or calls between the restore and the return, nuke the restore. + if (!CannotRemove && (isa(TI) || isa(TI))) + return EraseInstFromFunction(CI); + break; + } + } + + return visitCallSite(II); +} + +// InvokeInst simplification +// +Instruction *InstCombiner::visitInvokeInst(InvokeInst &II) { + return visitCallSite(&II); +} + +/// isSafeToEliminateVarargsCast - If this cast does not affect the value +/// passed through the varargs area, we can eliminate the use of the cast. +static bool isSafeToEliminateVarargsCast(const CallSite CS, + const CastInst * const CI, + const TargetData * const TD, + const int ix) { + if (!CI->isLosslessCast()) + return false; + + // The size of ByVal arguments is derived from the type, so we + // can't change to a type with a different size. If the size were + // passed explicitly we could avoid this check. + if (!CS.paramHasAttr(ix, Attribute::ByVal)) + return true; + + const Type* SrcTy = + cast(CI->getOperand(0)->getType())->getElementType(); + const Type* DstTy = cast(CI->getType())->getElementType(); + if (!SrcTy->isSized() || !DstTy->isSized()) + return false; + if (!TD || TD->getTypeAllocSize(SrcTy) != TD->getTypeAllocSize(DstTy)) + return false; + return true; +} + +// visitCallSite - Improvements for call and invoke instructions. +// +Instruction *InstCombiner::visitCallSite(CallSite CS) { + bool Changed = false; + + // If the callee is a constexpr cast of a function, attempt to move the cast + // to the arguments of the call/invoke. + if (transformConstExprCastCall(CS)) return 0; + + Value *Callee = CS.getCalledValue(); + + if (Function *CalleeF = dyn_cast(Callee)) + if (CalleeF->getCallingConv() != CS.getCallingConv()) { + Instruction *OldCall = CS.getInstruction(); + // If the call and callee calling conventions don't match, this call must + // be unreachable, as the call is undefined. + new StoreInst(ConstantInt::getTrue(*Context), + UndefValue::get(Type::getInt1PtrTy(*Context)), + OldCall); + // If OldCall dues not return void then replaceAllUsesWith undef. + // This allows ValueHandlers and custom metadata to adjust itself. + if (!OldCall->getType()->isVoidTy()) + OldCall->replaceAllUsesWith(UndefValue::get(OldCall->getType())); + if (isa(OldCall)) // Not worth removing an invoke here. + return EraseInstFromFunction(*OldCall); + return 0; + } + + if (isa(Callee) || isa(Callee)) { + // This instruction is not reachable, just remove it. We insert a store to + // undef so that we know that this code is not reachable, despite the fact + // that we can't modify the CFG here. + new StoreInst(ConstantInt::getTrue(*Context), + UndefValue::get(Type::getInt1PtrTy(*Context)), + CS.getInstruction()); + + // If CS dues not return void then replaceAllUsesWith undef. + // This allows ValueHandlers and custom metadata to adjust itself. + if (!CS.getInstruction()->getType()->isVoidTy()) + CS.getInstruction()-> + replaceAllUsesWith(UndefValue::get(CS.getInstruction()->getType())); + + if (InvokeInst *II = dyn_cast(CS.getInstruction())) { + // Don't break the CFG, insert a dummy cond branch. + BranchInst::Create(II->getNormalDest(), II->getUnwindDest(), + ConstantInt::getTrue(*Context), II); + } + return EraseInstFromFunction(*CS.getInstruction()); + } + + if (BitCastInst *BC = dyn_cast(Callee)) + if (IntrinsicInst *In = dyn_cast(BC->getOperand(0))) + if (In->getIntrinsicID() == Intrinsic::init_trampoline) + return transformCallThroughTrampoline(CS); + + const PointerType *PTy = cast(Callee->getType()); + const FunctionType *FTy = cast(PTy->getElementType()); + if (FTy->isVarArg()) { + int ix = FTy->getNumParams() + (isa(Callee) ? 3 : 1); + // See if we can optimize any arguments passed through the varargs area of + // the call. + for (CallSite::arg_iterator I = CS.arg_begin()+FTy->getNumParams(), + E = CS.arg_end(); I != E; ++I, ++ix) { + CastInst *CI = dyn_cast(*I); + if (CI && isSafeToEliminateVarargsCast(CS, CI, TD, ix)) { + *I = CI->getOperand(0); + Changed = true; + } + } + } + + if (isa(Callee) && !CS.doesNotThrow()) { + // Inline asm calls cannot throw - mark them 'nounwind'. + CS.setDoesNotThrow(); + Changed = true; + } + + return Changed ? CS.getInstruction() : 0; +} + +// transformConstExprCastCall - If the callee is a constexpr cast of a function, +// attempt to move the cast to the arguments of the call/invoke. +// +bool InstCombiner::transformConstExprCastCall(CallSite CS) { + if (!isa(CS.getCalledValue())) return false; + ConstantExpr *CE = cast(CS.getCalledValue()); + if (CE->getOpcode() != Instruction::BitCast || + !isa(CE->getOperand(0))) + return false; + Function *Callee = cast(CE->getOperand(0)); + Instruction *Caller = CS.getInstruction(); + const AttrListPtr &CallerPAL = CS.getAttributes(); + + // Okay, this is a cast from a function to a different type. Unless doing so + // would cause a type conversion of one of our arguments, change this call to + // be a direct call with arguments casted to the appropriate types. + // + const FunctionType *FT = Callee->getFunctionType(); + const Type *OldRetTy = Caller->getType(); + const Type *NewRetTy = FT->getReturnType(); + + if (isa(NewRetTy)) + return false; // TODO: Handle multiple return values. + + // Check to see if we are changing the return type... + if (OldRetTy != NewRetTy) { + if (Callee->isDeclaration() && + // Conversion is ok if changing from one pointer type to another or from + // a pointer to an integer of the same size. + !((isa(OldRetTy) || !TD || + OldRetTy == TD->getIntPtrType(Caller->getContext())) && + (isa(NewRetTy) || !TD || + NewRetTy == TD->getIntPtrType(Caller->getContext())))) + return false; // Cannot transform this return value. + + if (!Caller->use_empty() && + // void -> non-void is handled specially + !NewRetTy->isVoidTy() && !CastInst::isCastable(NewRetTy, OldRetTy)) + return false; // Cannot transform this return value. + + if (!CallerPAL.isEmpty() && !Caller->use_empty()) { + Attributes RAttrs = CallerPAL.getRetAttributes(); + if (RAttrs & Attribute::typeIncompatible(NewRetTy)) + return false; // Attribute not compatible with transformed value. + } + + // If the callsite is an invoke instruction, and the return value is used by + // a PHI node in a successor, we cannot change the return type of the call + // because there is no place to put the cast instruction (without breaking + // the critical edge). Bail out in this case. + if (!Caller->use_empty()) + if (InvokeInst *II = dyn_cast(Caller)) + for (Value::use_iterator UI = II->use_begin(), E = II->use_end(); + UI != E; ++UI) + if (PHINode *PN = dyn_cast(*UI)) + if (PN->getParent() == II->getNormalDest() || + PN->getParent() == II->getUnwindDest()) + return false; + } + + unsigned NumActualArgs = unsigned(CS.arg_end()-CS.arg_begin()); + unsigned NumCommonArgs = std::min(FT->getNumParams(), NumActualArgs); + + CallSite::arg_iterator AI = CS.arg_begin(); + for (unsigned i = 0, e = NumCommonArgs; i != e; ++i, ++AI) { + const Type *ParamTy = FT->getParamType(i); + const Type *ActTy = (*AI)->getType(); + + if (!CastInst::isCastable(ActTy, ParamTy)) + return false; // Cannot transform this parameter value. + + if (CallerPAL.getParamAttributes(i + 1) + & Attribute::typeIncompatible(ParamTy)) + return false; // Attribute not compatible with transformed value. + + // Converting from one pointer type to another or between a pointer and an + // integer of the same size is safe even if we do not have a body. + bool isConvertible = ActTy == ParamTy || + (TD && ((isa(ParamTy) || + ParamTy == TD->getIntPtrType(Caller->getContext())) && + (isa(ActTy) || + ActTy == TD->getIntPtrType(Caller->getContext())))); + if (Callee->isDeclaration() && !isConvertible) return false; + } + + if (FT->getNumParams() < NumActualArgs && !FT->isVarArg() && + Callee->isDeclaration()) + return false; // Do not delete arguments unless we have a function body. + + if (FT->getNumParams() < NumActualArgs && FT->isVarArg() && + !CallerPAL.isEmpty()) + // In this case we have more arguments than the new function type, but we + // won't be dropping them. Check that these extra arguments have attributes + // that are compatible with being a vararg call argument. + for (unsigned i = CallerPAL.getNumSlots(); i; --i) { + if (CallerPAL.getSlot(i - 1).Index <= FT->getNumParams()) + break; + Attributes PAttrs = CallerPAL.getSlot(i - 1).Attrs; + if (PAttrs & Attribute::VarArgsIncompatible) + return false; + } + + // Okay, we decided that this is a safe thing to do: go ahead and start + // inserting cast instructions as necessary... + std::vector Args; + Args.reserve(NumActualArgs); + SmallVector attrVec; + attrVec.reserve(NumCommonArgs); + + // Get any return attributes. + Attributes RAttrs = CallerPAL.getRetAttributes(); + + // If the return value is not being used, the type may not be compatible + // with the existing attributes. Wipe out any problematic attributes. + RAttrs &= ~Attribute::typeIncompatible(NewRetTy); + + // Add the new return attributes. + if (RAttrs) + attrVec.push_back(AttributeWithIndex::get(0, RAttrs)); + + AI = CS.arg_begin(); + for (unsigned i = 0; i != NumCommonArgs; ++i, ++AI) { + const Type *ParamTy = FT->getParamType(i); + if ((*AI)->getType() == ParamTy) { + Args.push_back(*AI); + } else { + Instruction::CastOps opcode = CastInst::getCastOpcode(*AI, + false, ParamTy, false); + Args.push_back(Builder->CreateCast(opcode, *AI, ParamTy, "tmp")); + } + + // Add any parameter attributes. + if (Attributes PAttrs = CallerPAL.getParamAttributes(i + 1)) + attrVec.push_back(AttributeWithIndex::get(i + 1, PAttrs)); + } + + // If the function takes more arguments than the call was taking, add them + // now. + for (unsigned i = NumCommonArgs; i != FT->getNumParams(); ++i) + Args.push_back(Constant::getNullValue(FT->getParamType(i))); + + // If we are removing arguments to the function, emit an obnoxious warning. + if (FT->getNumParams() < NumActualArgs) { + if (!FT->isVarArg()) { + errs() << "WARNING: While resolving call to function '" + << Callee->getName() << "' arguments were dropped!\n"; + } else { + // Add all of the arguments in their promoted form to the arg list. + for (unsigned i = FT->getNumParams(); i != NumActualArgs; ++i, ++AI) { + const Type *PTy = getPromotedType((*AI)->getType()); + if (PTy != (*AI)->getType()) { + // Must promote to pass through va_arg area! + Instruction::CastOps opcode = + CastInst::getCastOpcode(*AI, false, PTy, false); + Args.push_back(Builder->CreateCast(opcode, *AI, PTy, "tmp")); + } else { + Args.push_back(*AI); + } + + // Add any parameter attributes. + if (Attributes PAttrs = CallerPAL.getParamAttributes(i + 1)) + attrVec.push_back(AttributeWithIndex::get(i + 1, PAttrs)); + } + } + } + + if (Attributes FnAttrs = CallerPAL.getFnAttributes()) + attrVec.push_back(AttributeWithIndex::get(~0, FnAttrs)); + + if (NewRetTy->isVoidTy()) + Caller->setName(""); // Void type should not have a name. + + const AttrListPtr &NewCallerPAL = AttrListPtr::get(attrVec.begin(), + attrVec.end()); + + Instruction *NC; + if (InvokeInst *II = dyn_cast(Caller)) { + NC = InvokeInst::Create(Callee, II->getNormalDest(), II->getUnwindDest(), + Args.begin(), Args.end(), + Caller->getName(), Caller); + cast(NC)->setCallingConv(II->getCallingConv()); + cast(NC)->setAttributes(NewCallerPAL); + } else { + NC = CallInst::Create(Callee, Args.begin(), Args.end(), + Caller->getName(), Caller); + CallInst *CI = cast(Caller); + if (CI->isTailCall()) + cast(NC)->setTailCall(); + cast(NC)->setCallingConv(CI->getCallingConv()); + cast(NC)->setAttributes(NewCallerPAL); + } + + // Insert a cast of the return type as necessary. + Value *NV = NC; + if (OldRetTy != NV->getType() && !Caller->use_empty()) { + if (!NV->getType()->isVoidTy()) { + Instruction::CastOps opcode = CastInst::getCastOpcode(NC, false, + OldRetTy, false); + NV = NC = CastInst::Create(opcode, NC, OldRetTy, "tmp"); + + // If this is an invoke instruction, we should insert it after the first + // non-phi, instruction in the normal successor block. + if (InvokeInst *II = dyn_cast(Caller)) { + BasicBlock::iterator I = II->getNormalDest()->getFirstNonPHI(); + InsertNewInstBefore(NC, *I); + } else { + // Otherwise, it's a call, just insert cast right after the call instr + InsertNewInstBefore(NC, *Caller); + } + Worklist.AddUsersToWorkList(*Caller); + } else { + NV = UndefValue::get(Caller->getType()); + } + } + + + if (!Caller->use_empty()) + Caller->replaceAllUsesWith(NV); + + EraseInstFromFunction(*Caller); + return true; +} + +// transformCallThroughTrampoline - Turn a call to a function created by the +// init_trampoline intrinsic into a direct call to the underlying function. +// +Instruction *InstCombiner::transformCallThroughTrampoline(CallSite CS) { + Value *Callee = CS.getCalledValue(); + const PointerType *PTy = cast(Callee->getType()); + const FunctionType *FTy = cast(PTy->getElementType()); + const AttrListPtr &Attrs = CS.getAttributes(); + + // If the call already has the 'nest' attribute somewhere then give up - + // otherwise 'nest' would occur twice after splicing in the chain. + if (Attrs.hasAttrSomewhere(Attribute::Nest)) + return 0; + + IntrinsicInst *Tramp = + cast(cast(Callee)->getOperand(0)); + + Function *NestF = cast(Tramp->getOperand(2)->stripPointerCasts()); + const PointerType *NestFPTy = cast(NestF->getType()); + const FunctionType *NestFTy = cast(NestFPTy->getElementType()); + + const AttrListPtr &NestAttrs = NestF->getAttributes(); + if (!NestAttrs.isEmpty()) { + unsigned NestIdx = 1; + const Type *NestTy = 0; + Attributes NestAttr = Attribute::None; + + // Look for a parameter marked with the 'nest' attribute. + for (FunctionType::param_iterator I = NestFTy->param_begin(), + E = NestFTy->param_end(); I != E; ++NestIdx, ++I) + if (NestAttrs.paramHasAttr(NestIdx, Attribute::Nest)) { + // Record the parameter type and any other attributes. + NestTy = *I; + NestAttr = NestAttrs.getParamAttributes(NestIdx); + break; + } + + if (NestTy) { + Instruction *Caller = CS.getInstruction(); + std::vector NewArgs; + NewArgs.reserve(unsigned(CS.arg_end()-CS.arg_begin())+1); + + SmallVector NewAttrs; + NewAttrs.reserve(Attrs.getNumSlots() + 1); + + // Insert the nest argument into the call argument list, which may + // mean appending it. Likewise for attributes. + + // Add any result attributes. + if (Attributes Attr = Attrs.getRetAttributes()) + NewAttrs.push_back(AttributeWithIndex::get(0, Attr)); + + { + unsigned Idx = 1; + CallSite::arg_iterator I = CS.arg_begin(), E = CS.arg_end(); + do { + if (Idx == NestIdx) { + // Add the chain argument and attributes. + Value *NestVal = Tramp->getOperand(3); + if (NestVal->getType() != NestTy) + NestVal = new BitCastInst(NestVal, NestTy, "nest", Caller); + NewArgs.push_back(NestVal); + NewAttrs.push_back(AttributeWithIndex::get(NestIdx, NestAttr)); + } + + if (I == E) + break; + + // Add the original argument and attributes. + NewArgs.push_back(*I); + if (Attributes Attr = Attrs.getParamAttributes(Idx)) + NewAttrs.push_back + (AttributeWithIndex::get(Idx + (Idx >= NestIdx), Attr)); + + ++Idx, ++I; + } while (1); + } + + // Add any function attributes. + if (Attributes Attr = Attrs.getFnAttributes()) + NewAttrs.push_back(AttributeWithIndex::get(~0, Attr)); + + // The trampoline may have been bitcast to a bogus type (FTy). + // Handle this by synthesizing a new function type, equal to FTy + // with the chain parameter inserted. + + std::vector NewTypes; + NewTypes.reserve(FTy->getNumParams()+1); + + // Insert the chain's type into the list of parameter types, which may + // mean appending it. + { + unsigned Idx = 1; + FunctionType::param_iterator I = FTy->param_begin(), + E = FTy->param_end(); + + do { + if (Idx == NestIdx) + // Add the chain's type. + NewTypes.push_back(NestTy); + + if (I == E) + break; + + // Add the original type. + NewTypes.push_back(*I); + + ++Idx, ++I; + } while (1); + } + + // Replace the trampoline call with a direct call. Let the generic + // code sort out any function type mismatches. + FunctionType *NewFTy = FunctionType::get(FTy->getReturnType(), NewTypes, + FTy->isVarArg()); + Constant *NewCallee = + NestF->getType() == PointerType::getUnqual(NewFTy) ? + NestF : ConstantExpr::getBitCast(NestF, + PointerType::getUnqual(NewFTy)); + const AttrListPtr &NewPAL = AttrListPtr::get(NewAttrs.begin(), + NewAttrs.end()); + + Instruction *NewCaller; + if (InvokeInst *II = dyn_cast(Caller)) { + NewCaller = InvokeInst::Create(NewCallee, + II->getNormalDest(), II->getUnwindDest(), + NewArgs.begin(), NewArgs.end(), + Caller->getName(), Caller); + cast(NewCaller)->setCallingConv(II->getCallingConv()); + cast(NewCaller)->setAttributes(NewPAL); + } else { + NewCaller = CallInst::Create(NewCallee, NewArgs.begin(), NewArgs.end(), + Caller->getName(), Caller); + if (cast(Caller)->isTailCall()) + cast(NewCaller)->setTailCall(); + cast(NewCaller)-> + setCallingConv(cast(Caller)->getCallingConv()); + cast(NewCaller)->setAttributes(NewPAL); + } + if (!Caller->getType()->isVoidTy()) + Caller->replaceAllUsesWith(NewCaller); + Caller->eraseFromParent(); + Worklist.Remove(Caller); + return 0; + } + } + + // Replace the trampoline call with a direct call. Since there is no 'nest' + // parameter, there is no need to adjust the argument list. Let the generic + // code sort out any function type mismatches. + Constant *NewCallee = + NestF->getType() == PTy ? NestF : + ConstantExpr::getBitCast(NestF, PTy); + CS.setCalledFunction(NewCallee); + return CS.getInstruction(); +} + +/// FoldPHIArgBinOpIntoPHI - If we have something like phi [add (a,b), add(a,c)] +/// and if a/b/c and the add's all have a single use, turn this into a phi +/// and a single binop. +Instruction *InstCombiner::FoldPHIArgBinOpIntoPHI(PHINode &PN) { + Instruction *FirstInst = cast(PN.getIncomingValue(0)); + assert(isa(FirstInst) || isa(FirstInst)); + unsigned Opc = FirstInst->getOpcode(); + Value *LHSVal = FirstInst->getOperand(0); + Value *RHSVal = FirstInst->getOperand(1); + + const Type *LHSType = LHSVal->getType(); + const Type *RHSType = RHSVal->getType(); + + // Scan to see if all operands are the same opcode, and all have one use. + for (unsigned i = 1; i != PN.getNumIncomingValues(); ++i) { + Instruction *I = dyn_cast(PN.getIncomingValue(i)); + if (!I || I->getOpcode() != Opc || !I->hasOneUse() || + // Verify type of the LHS matches so we don't fold cmp's of different + // types or GEP's with different index types. + I->getOperand(0)->getType() != LHSType || + I->getOperand(1)->getType() != RHSType) + return 0; + + // If they are CmpInst instructions, check their predicates + if (Opc == Instruction::ICmp || Opc == Instruction::FCmp) + if (cast(I)->getPredicate() != + cast(FirstInst)->getPredicate()) + return 0; + + // Keep track of which operand needs a phi node. + if (I->getOperand(0) != LHSVal) LHSVal = 0; + if (I->getOperand(1) != RHSVal) RHSVal = 0; + } + + // If both LHS and RHS would need a PHI, don't do this transformation, + // because it would increase the number of PHIs entering the block, + // which leads to higher register pressure. This is especially + // bad when the PHIs are in the header of a loop. + if (!LHSVal && !RHSVal) + return 0; + + // Otherwise, this is safe to transform! + + Value *InLHS = FirstInst->getOperand(0); + Value *InRHS = FirstInst->getOperand(1); + PHINode *NewLHS = 0, *NewRHS = 0; + if (LHSVal == 0) { + NewLHS = PHINode::Create(LHSType, + FirstInst->getOperand(0)->getName() + ".pn"); + NewLHS->reserveOperandSpace(PN.getNumOperands()/2); + NewLHS->addIncoming(InLHS, PN.getIncomingBlock(0)); + InsertNewInstBefore(NewLHS, PN); + LHSVal = NewLHS; + } + + if (RHSVal == 0) { + NewRHS = PHINode::Create(RHSType, + FirstInst->getOperand(1)->getName() + ".pn"); + NewRHS->reserveOperandSpace(PN.getNumOperands()/2); + NewRHS->addIncoming(InRHS, PN.getIncomingBlock(0)); + InsertNewInstBefore(NewRHS, PN); + RHSVal = NewRHS; + } + + // Add all operands to the new PHIs. + if (NewLHS || NewRHS) { + for (unsigned i = 1, e = PN.getNumIncomingValues(); i != e; ++i) { + Instruction *InInst = cast(PN.getIncomingValue(i)); + if (NewLHS) { + Value *NewInLHS = InInst->getOperand(0); + NewLHS->addIncoming(NewInLHS, PN.getIncomingBlock(i)); + } + if (NewRHS) { + Value *NewInRHS = InInst->getOperand(1); + NewRHS->addIncoming(NewInRHS, PN.getIncomingBlock(i)); + } + } + } + + if (BinaryOperator *BinOp = dyn_cast(FirstInst)) + return BinaryOperator::Create(BinOp->getOpcode(), LHSVal, RHSVal); + CmpInst *CIOp = cast(FirstInst); + return CmpInst::Create(CIOp->getOpcode(), CIOp->getPredicate(), + LHSVal, RHSVal); +} + +Instruction *InstCombiner::FoldPHIArgGEPIntoPHI(PHINode &PN) { + GetElementPtrInst *FirstInst =cast(PN.getIncomingValue(0)); + + SmallVector FixedOperands(FirstInst->op_begin(), + FirstInst->op_end()); + // This is true if all GEP bases are allocas and if all indices into them are + // constants. + bool AllBasePointersAreAllocas = true; + + // We don't want to replace this phi if the replacement would require + // more than one phi, which leads to higher register pressure. This is + // especially bad when the PHIs are in the header of a loop. + bool NeededPhi = false; + + // Scan to see if all operands are the same opcode, and all have one use. + for (unsigned i = 1; i != PN.getNumIncomingValues(); ++i) { + GetElementPtrInst *GEP= dyn_cast(PN.getIncomingValue(i)); + if (!GEP || !GEP->hasOneUse() || GEP->getType() != FirstInst->getType() || + GEP->getNumOperands() != FirstInst->getNumOperands()) + return 0; + + // Keep track of whether or not all GEPs are of alloca pointers. + if (AllBasePointersAreAllocas && + (!isa(GEP->getOperand(0)) || + !GEP->hasAllConstantIndices())) + AllBasePointersAreAllocas = false; + + // Compare the operand lists. + for (unsigned op = 0, e = FirstInst->getNumOperands(); op != e; ++op) { + if (FirstInst->getOperand(op) == GEP->getOperand(op)) + continue; + + // Don't merge two GEPs when two operands differ (introducing phi nodes) + // if one of the PHIs has a constant for the index. The index may be + // substantially cheaper to compute for the constants, so making it a + // variable index could pessimize the path. This also handles the case + // for struct indices, which must always be constant. + if (isa(FirstInst->getOperand(op)) || + isa(GEP->getOperand(op))) + return 0; + + if (FirstInst->getOperand(op)->getType() !=GEP->getOperand(op)->getType()) + return 0; + + // If we already needed a PHI for an earlier operand, and another operand + // also requires a PHI, we'd be introducing more PHIs than we're + // eliminating, which increases register pressure on entry to the PHI's + // block. + if (NeededPhi) + return 0; + + FixedOperands[op] = 0; // Needs a PHI. + NeededPhi = true; + } + } + + // If all of the base pointers of the PHI'd GEPs are from allocas, don't + // bother doing this transformation. At best, this will just save a bit of + // offset calculation, but all the predecessors will have to materialize the + // stack address into a register anyway. We'd actually rather *clone* the + // load up into the predecessors so that we have a load of a gep of an alloca, + // which can usually all be folded into the load. + if (AllBasePointersAreAllocas) + return 0; + + // Otherwise, this is safe to transform. Insert PHI nodes for each operand + // that is variable. + SmallVector OperandPhis(FixedOperands.size()); + + bool HasAnyPHIs = false; + for (unsigned i = 0, e = FixedOperands.size(); i != e; ++i) { + if (FixedOperands[i]) continue; // operand doesn't need a phi. + Value *FirstOp = FirstInst->getOperand(i); + PHINode *NewPN = PHINode::Create(FirstOp->getType(), + FirstOp->getName()+".pn"); + InsertNewInstBefore(NewPN, PN); + + NewPN->reserveOperandSpace(e); + NewPN->addIncoming(FirstOp, PN.getIncomingBlock(0)); + OperandPhis[i] = NewPN; + FixedOperands[i] = NewPN; + HasAnyPHIs = true; + } + + + // Add all operands to the new PHIs. + if (HasAnyPHIs) { + for (unsigned i = 1, e = PN.getNumIncomingValues(); i != e; ++i) { + GetElementPtrInst *InGEP =cast(PN.getIncomingValue(i)); + BasicBlock *InBB = PN.getIncomingBlock(i); + + for (unsigned op = 0, e = OperandPhis.size(); op != e; ++op) + if (PHINode *OpPhi = OperandPhis[op]) + OpPhi->addIncoming(InGEP->getOperand(op), InBB); + } + } + + Value *Base = FixedOperands[0]; + return cast(FirstInst)->isInBounds() ? + GetElementPtrInst::CreateInBounds(Base, FixedOperands.begin()+1, + FixedOperands.end()) : + GetElementPtrInst::Create(Base, FixedOperands.begin()+1, + FixedOperands.end()); +} + + +/// isSafeAndProfitableToSinkLoad - Return true if we know that it is safe to +/// sink the load out of the block that defines it. This means that it must be +/// obvious the value of the load is not changed from the point of the load to +/// the end of the block it is in. +/// +/// Finally, it is safe, but not profitable, to sink a load targetting a +/// non-address-taken alloca. Doing so will cause us to not promote the alloca +/// to a register. +static bool isSafeAndProfitableToSinkLoad(LoadInst *L) { + BasicBlock::iterator BBI = L, E = L->getParent()->end(); + + for (++BBI; BBI != E; ++BBI) + if (BBI->mayWriteToMemory()) + return false; + + // Check for non-address taken alloca. If not address-taken already, it isn't + // profitable to do this xform. + if (AllocaInst *AI = dyn_cast(L->getOperand(0))) { + bool isAddressTaken = false; + for (Value::use_iterator UI = AI->use_begin(), E = AI->use_end(); + UI != E; ++UI) { + if (isa(UI)) continue; + if (StoreInst *SI = dyn_cast(*UI)) { + // If storing TO the alloca, then the address isn't taken. + if (SI->getOperand(1) == AI) continue; + } + isAddressTaken = true; + break; + } + + if (!isAddressTaken && AI->isStaticAlloca()) + return false; + } + + // If this load is a load from a GEP with a constant offset from an alloca, + // then we don't want to sink it. In its present form, it will be + // load [constant stack offset]. Sinking it will cause us to have to + // materialize the stack addresses in each predecessor in a register only to + // do a shared load from register in the successor. + if (GetElementPtrInst *GEP = dyn_cast(L->getOperand(0))) + if (AllocaInst *AI = dyn_cast(GEP->getOperand(0))) + if (AI->isStaticAlloca() && GEP->hasAllConstantIndices()) + return false; + + return true; +} + +Instruction *InstCombiner::FoldPHIArgLoadIntoPHI(PHINode &PN) { + LoadInst *FirstLI = cast(PN.getIncomingValue(0)); + + // When processing loads, we need to propagate two bits of information to the + // sunk load: whether it is volatile, and what its alignment is. We currently + // don't sink loads when some have their alignment specified and some don't. + // visitLoadInst will propagate an alignment onto the load when TD is around, + // and if TD isn't around, we can't handle the mixed case. + bool isVolatile = FirstLI->isVolatile(); + unsigned LoadAlignment = FirstLI->getAlignment(); + + // We can't sink the load if the loaded value could be modified between the + // load and the PHI. + if (FirstLI->getParent() != PN.getIncomingBlock(0) || + !isSafeAndProfitableToSinkLoad(FirstLI)) + return 0; + + // If the PHI is of volatile loads and the load block has multiple + // successors, sinking it would remove a load of the volatile value from + // the path through the other successor. + if (isVolatile && + FirstLI->getParent()->getTerminator()->getNumSuccessors() != 1) + return 0; + + // Check to see if all arguments are the same operation. + for (unsigned i = 1, e = PN.getNumIncomingValues(); i != e; ++i) { + LoadInst *LI = dyn_cast(PN.getIncomingValue(i)); + if (!LI || !LI->hasOneUse()) + return 0; + + // We can't sink the load if the loaded value could be modified between + // the load and the PHI. + if (LI->isVolatile() != isVolatile || + LI->getParent() != PN.getIncomingBlock(i) || + !isSafeAndProfitableToSinkLoad(LI)) + return 0; + + // If some of the loads have an alignment specified but not all of them, + // we can't do the transformation. + if ((LoadAlignment != 0) != (LI->getAlignment() != 0)) + return 0; + + LoadAlignment = std::min(LoadAlignment, LI->getAlignment()); + + // If the PHI is of volatile loads and the load block has multiple + // successors, sinking it would remove a load of the volatile value from + // the path through the other successor. + if (isVolatile && + LI->getParent()->getTerminator()->getNumSuccessors() != 1) + return 0; + } + + // Okay, they are all the same operation. Create a new PHI node of the + // correct type, and PHI together all of the LHS's of the instructions. + PHINode *NewPN = PHINode::Create(FirstLI->getOperand(0)->getType(), + PN.getName()+".in"); + NewPN->reserveOperandSpace(PN.getNumOperands()/2); + + Value *InVal = FirstLI->getOperand(0); + NewPN->addIncoming(InVal, PN.getIncomingBlock(0)); + + // Add all operands to the new PHI. + for (unsigned i = 1, e = PN.getNumIncomingValues(); i != e; ++i) { + Value *NewInVal = cast(PN.getIncomingValue(i))->getOperand(0); + if (NewInVal != InVal) + InVal = 0; + NewPN->addIncoming(NewInVal, PN.getIncomingBlock(i)); + } + + Value *PhiVal; + if (InVal) { + // The new PHI unions all of the same values together. This is really + // common, so we handle it intelligently here for compile-time speed. + PhiVal = InVal; + delete NewPN; + } else { + InsertNewInstBefore(NewPN, PN); + PhiVal = NewPN; + } + + // If this was a volatile load that we are merging, make sure to loop through + // and mark all the input loads as non-volatile. If we don't do this, we will + // insert a new volatile load and the old ones will not be deletable. + if (isVolatile) + for (unsigned i = 0, e = PN.getNumIncomingValues(); i != e; ++i) + cast(PN.getIncomingValue(i))->setVolatile(false); + + return new LoadInst(PhiVal, "", isVolatile, LoadAlignment); +} + + + +/// FoldPHIArgOpIntoPHI - If all operands to a PHI node are the same "unary" +/// operator and they all are only used by the PHI, PHI together their +/// inputs, and do the operation once, to the result of the PHI. +Instruction *InstCombiner::FoldPHIArgOpIntoPHI(PHINode &PN) { + Instruction *FirstInst = cast(PN.getIncomingValue(0)); + + if (isa(FirstInst)) + return FoldPHIArgGEPIntoPHI(PN); + if (isa(FirstInst)) + return FoldPHIArgLoadIntoPHI(PN); + + // Scan the instruction, looking for input operations that can be folded away. + // If all input operands to the phi are the same instruction (e.g. a cast from + // the same type or "+42") we can pull the operation through the PHI, reducing + // code size and simplifying code. + Constant *ConstantOp = 0; + const Type *CastSrcTy = 0; + + if (isa(FirstInst)) { + CastSrcTy = FirstInst->getOperand(0)->getType(); + + // Be careful about transforming integer PHIs. We don't want to pessimize + // the code by turning an i32 into an i1293. + if (isa(PN.getType()) && isa(CastSrcTy)) { + if (!ShouldChangeType(PN.getType(), CastSrcTy, TD)) + return 0; + } + } else if (isa(FirstInst) || isa(FirstInst)) { + // Can fold binop, compare or shift here if the RHS is a constant, + // otherwise call FoldPHIArgBinOpIntoPHI. + ConstantOp = dyn_cast(FirstInst->getOperand(1)); + if (ConstantOp == 0) + return FoldPHIArgBinOpIntoPHI(PN); + } else { + return 0; // Cannot fold this operation. + } + + // Check to see if all arguments are the same operation. + for (unsigned i = 1, e = PN.getNumIncomingValues(); i != e; ++i) { + Instruction *I = dyn_cast(PN.getIncomingValue(i)); + if (I == 0 || !I->hasOneUse() || !I->isSameOperationAs(FirstInst)) + return 0; + if (CastSrcTy) { + if (I->getOperand(0)->getType() != CastSrcTy) + return 0; // Cast operation must match. + } else if (I->getOperand(1) != ConstantOp) { + return 0; + } + } + + // Okay, they are all the same operation. Create a new PHI node of the + // correct type, and PHI together all of the LHS's of the instructions. + PHINode *NewPN = PHINode::Create(FirstInst->getOperand(0)->getType(), + PN.getName()+".in"); + NewPN->reserveOperandSpace(PN.getNumOperands()/2); + + Value *InVal = FirstInst->getOperand(0); + NewPN->addIncoming(InVal, PN.getIncomingBlock(0)); + + // Add all operands to the new PHI. + for (unsigned i = 1, e = PN.getNumIncomingValues(); i != e; ++i) { + Value *NewInVal = cast(PN.getIncomingValue(i))->getOperand(0); + if (NewInVal != InVal) + InVal = 0; + NewPN->addIncoming(NewInVal, PN.getIncomingBlock(i)); + } + + Value *PhiVal; + if (InVal) { + // The new PHI unions all of the same values together. This is really + // common, so we handle it intelligently here for compile-time speed. + PhiVal = InVal; + delete NewPN; + } else { + InsertNewInstBefore(NewPN, PN); + PhiVal = NewPN; + } + + // Insert and return the new operation. + if (CastInst *FirstCI = dyn_cast(FirstInst)) + return CastInst::Create(FirstCI->getOpcode(), PhiVal, PN.getType()); + + if (BinaryOperator *BinOp = dyn_cast(FirstInst)) + return BinaryOperator::Create(BinOp->getOpcode(), PhiVal, ConstantOp); + + CmpInst *CIOp = cast(FirstInst); + return CmpInst::Create(CIOp->getOpcode(), CIOp->getPredicate(), + PhiVal, ConstantOp); +} + +/// DeadPHICycle - Return true if this PHI node is only used by a PHI node cycle +/// that is dead. +static bool DeadPHICycle(PHINode *PN, + SmallPtrSet &PotentiallyDeadPHIs) { + if (PN->use_empty()) return true; + if (!PN->hasOneUse()) return false; + + // Remember this node, and if we find the cycle, return. + if (!PotentiallyDeadPHIs.insert(PN)) + return true; + + // Don't scan crazily complex things. + if (PotentiallyDeadPHIs.size() == 16) + return false; + + if (PHINode *PU = dyn_cast(PN->use_back())) + return DeadPHICycle(PU, PotentiallyDeadPHIs); + + return false; +} + +/// PHIsEqualValue - Return true if this phi node is always equal to +/// NonPhiInVal. This happens with mutually cyclic phi nodes like: +/// z = some value; x = phi (y, z); y = phi (x, z) +static bool PHIsEqualValue(PHINode *PN, Value *NonPhiInVal, + SmallPtrSet &ValueEqualPHIs) { + // See if we already saw this PHI node. + if (!ValueEqualPHIs.insert(PN)) + return true; + + // Don't scan crazily complex things. + if (ValueEqualPHIs.size() == 16) + return false; + + // Scan the operands to see if they are either phi nodes or are equal to + // the value. + for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) { + Value *Op = PN->getIncomingValue(i); + if (PHINode *OpPN = dyn_cast(Op)) { + if (!PHIsEqualValue(OpPN, NonPhiInVal, ValueEqualPHIs)) + return false; + } else if (Op != NonPhiInVal) + return false; + } + + return true; +} + + +namespace { +struct PHIUsageRecord { + unsigned PHIId; // The ID # of the PHI (something determinstic to sort on) + unsigned Shift; // The amount shifted. + Instruction *Inst; // The trunc instruction. + + PHIUsageRecord(unsigned pn, unsigned Sh, Instruction *User) + : PHIId(pn), Shift(Sh), Inst(User) {} + + bool operator<(const PHIUsageRecord &RHS) const { + if (PHIId < RHS.PHIId) return true; + if (PHIId > RHS.PHIId) return false; + if (Shift < RHS.Shift) return true; + if (Shift > RHS.Shift) return false; + return Inst->getType()->getPrimitiveSizeInBits() < + RHS.Inst->getType()->getPrimitiveSizeInBits(); + } +}; + +struct LoweredPHIRecord { + PHINode *PN; // The PHI that was lowered. + unsigned Shift; // The amount shifted. + unsigned Width; // The width extracted. + + LoweredPHIRecord(PHINode *pn, unsigned Sh, const Type *Ty) + : PN(pn), Shift(Sh), Width(Ty->getPrimitiveSizeInBits()) {} + + // Ctor form used by DenseMap. + LoweredPHIRecord(PHINode *pn, unsigned Sh) + : PN(pn), Shift(Sh), Width(0) {} +}; +} + +namespace llvm { + template<> + struct DenseMapInfo { + static inline LoweredPHIRecord getEmptyKey() { + return LoweredPHIRecord(0, 0); + } + static inline LoweredPHIRecord getTombstoneKey() { + return LoweredPHIRecord(0, 1); + } + static unsigned getHashValue(const LoweredPHIRecord &Val) { + return DenseMapInfo::getHashValue(Val.PN) ^ (Val.Shift>>3) ^ + (Val.Width>>3); + } + static bool isEqual(const LoweredPHIRecord &LHS, + const LoweredPHIRecord &RHS) { + return LHS.PN == RHS.PN && LHS.Shift == RHS.Shift && + LHS.Width == RHS.Width; + } + static bool isPod() { return true; } + }; +} + + +/// SliceUpIllegalIntegerPHI - This is an integer PHI and we know that it has an +/// illegal type: see if it is only used by trunc or trunc(lshr) operations. If +/// so, we split the PHI into the various pieces being extracted. This sort of +/// thing is introduced when SROA promotes an aggregate to large integer values. +/// +/// TODO: The user of the trunc may be an bitcast to float/double/vector or an +/// inttoptr. We should produce new PHIs in the right type. +/// +Instruction *InstCombiner::SliceUpIllegalIntegerPHI(PHINode &FirstPhi) { + // PHIUsers - Keep track of all of the truncated values extracted from a set + // of PHIs, along with their offset. These are the things we want to rewrite. + SmallVector PHIUsers; + + // PHIs are often mutually cyclic, so we keep track of a whole set of PHI + // nodes which are extracted from. PHIsToSlice is a set we use to avoid + // revisiting PHIs, PHIsInspected is a ordered list of PHIs that we need to + // check the uses of (to ensure they are all extracts). + SmallVector PHIsToSlice; + SmallPtrSet PHIsInspected; + + PHIsToSlice.push_back(&FirstPhi); + PHIsInspected.insert(&FirstPhi); + + for (unsigned PHIId = 0; PHIId != PHIsToSlice.size(); ++PHIId) { + PHINode *PN = PHIsToSlice[PHIId]; + + for (Value::use_iterator UI = PN->use_begin(), E = PN->use_end(); + UI != E; ++UI) { + Instruction *User = cast(*UI); + + // If the user is a PHI, inspect its uses recursively. + if (PHINode *UserPN = dyn_cast(User)) { + if (PHIsInspected.insert(UserPN)) + PHIsToSlice.push_back(UserPN); + continue; + } + + // Truncates are always ok. + if (isa(User)) { + PHIUsers.push_back(PHIUsageRecord(PHIId, 0, User)); + continue; + } + + // Otherwise it must be a lshr which can only be used by one trunc. + if (User->getOpcode() != Instruction::LShr || + !User->hasOneUse() || !isa(User->use_back()) || + !isa(User->getOperand(1))) + return 0; + + unsigned Shift = cast(User->getOperand(1))->getZExtValue(); + PHIUsers.push_back(PHIUsageRecord(PHIId, Shift, User->use_back())); + } + } + + // If we have no users, they must be all self uses, just nuke the PHI. + if (PHIUsers.empty()) + return ReplaceInstUsesWith(FirstPhi, UndefValue::get(FirstPhi.getType())); + + // If this phi node is transformable, create new PHIs for all the pieces + // extracted out of it. First, sort the users by their offset and size. + array_pod_sort(PHIUsers.begin(), PHIUsers.end()); + + DEBUG(errs() << "SLICING UP PHI: " << FirstPhi << '\n'; + for (unsigned i = 1, e = PHIsToSlice.size(); i != e; ++i) + errs() << "AND USER PHI #" << i << ": " << *PHIsToSlice[i] <<'\n'; + ); + + // PredValues - This is a temporary used when rewriting PHI nodes. It is + // hoisted out here to avoid construction/destruction thrashing. + DenseMap PredValues; + + // ExtractedVals - Each new PHI we introduce is saved here so we don't + // introduce redundant PHIs. + DenseMap ExtractedVals; + + for (unsigned UserI = 0, UserE = PHIUsers.size(); UserI != UserE; ++UserI) { + unsigned PHIId = PHIUsers[UserI].PHIId; + PHINode *PN = PHIsToSlice[PHIId]; + unsigned Offset = PHIUsers[UserI].Shift; + const Type *Ty = PHIUsers[UserI].Inst->getType(); + + PHINode *EltPHI; + + // If we've already lowered a user like this, reuse the previously lowered + // value. + if ((EltPHI = ExtractedVals[LoweredPHIRecord(PN, Offset, Ty)]) == 0) { + + // Otherwise, Create the new PHI node for this user. + EltPHI = PHINode::Create(Ty, PN->getName()+".off"+Twine(Offset), PN); + assert(EltPHI->getType() != PN->getType() && + "Truncate didn't shrink phi?"); + + for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) { + BasicBlock *Pred = PN->getIncomingBlock(i); + Value *&PredVal = PredValues[Pred]; + + // If we already have a value for this predecessor, reuse it. + if (PredVal) { + EltPHI->addIncoming(PredVal, Pred); + continue; + } + + // Handle the PHI self-reuse case. + Value *InVal = PN->getIncomingValue(i); + if (InVal == PN) { + PredVal = EltPHI; + EltPHI->addIncoming(PredVal, Pred); + continue; + } else if (PHINode *InPHI = dyn_cast(PN)) { + // If the incoming value was a PHI, and if it was one of the PHIs we + // already rewrote it, just use the lowered value. + if (Value *Res = ExtractedVals[LoweredPHIRecord(InPHI, Offset, Ty)]) { + PredVal = Res; + EltPHI->addIncoming(PredVal, Pred); + continue; + } + } + + // Otherwise, do an extract in the predecessor. + Builder->SetInsertPoint(Pred, Pred->getTerminator()); + Value *Res = InVal; + if (Offset) + Res = Builder->CreateLShr(Res, ConstantInt::get(InVal->getType(), + Offset), "extract"); + Res = Builder->CreateTrunc(Res, Ty, "extract.t"); + PredVal = Res; + EltPHI->addIncoming(Res, Pred); + + // If the incoming value was a PHI, and if it was one of the PHIs we are + // rewriting, we will ultimately delete the code we inserted. This + // means we need to revisit that PHI to make sure we extract out the + // needed piece. + if (PHINode *OldInVal = dyn_cast(PN->getIncomingValue(i))) + if (PHIsInspected.count(OldInVal)) { + unsigned RefPHIId = std::find(PHIsToSlice.begin(),PHIsToSlice.end(), + OldInVal)-PHIsToSlice.begin(); + PHIUsers.push_back(PHIUsageRecord(RefPHIId, Offset, + cast(Res))); + ++UserE; + } + } + PredValues.clear(); + + DEBUG(errs() << " Made element PHI for offset " << Offset << ": " + << *EltPHI << '\n'); + ExtractedVals[LoweredPHIRecord(PN, Offset, Ty)] = EltPHI; + } + + // Replace the use of this piece with the PHI node. + ReplaceInstUsesWith(*PHIUsers[UserI].Inst, EltPHI); + } + + // Replace all the remaining uses of the PHI nodes (self uses and the lshrs) + // with undefs. + Value *Undef = UndefValue::get(FirstPhi.getType()); + for (unsigned i = 1, e = PHIsToSlice.size(); i != e; ++i) + ReplaceInstUsesWith(*PHIsToSlice[i], Undef); + return ReplaceInstUsesWith(FirstPhi, Undef); +} + +// PHINode simplification +// +Instruction *InstCombiner::visitPHINode(PHINode &PN) { + // If LCSSA is around, don't mess with Phi nodes + if (MustPreserveLCSSA) return 0; + + if (Value *V = PN.hasConstantValue()) + return ReplaceInstUsesWith(PN, V); + + // If all PHI operands are the same operation, pull them through the PHI, + // reducing code size. + if (isa(PN.getIncomingValue(0)) && + isa(PN.getIncomingValue(1)) && + cast(PN.getIncomingValue(0))->getOpcode() == + cast(PN.getIncomingValue(1))->getOpcode() && + // FIXME: The hasOneUse check will fail for PHIs that use the value more + // than themselves more than once. + PN.getIncomingValue(0)->hasOneUse()) + if (Instruction *Result = FoldPHIArgOpIntoPHI(PN)) + return Result; + + // If this is a trivial cycle in the PHI node graph, remove it. Basically, if + // this PHI only has a single use (a PHI), and if that PHI only has one use (a + // PHI)... break the cycle. + if (PN.hasOneUse()) { + Instruction *PHIUser = cast(PN.use_back()); + if (PHINode *PU = dyn_cast(PHIUser)) { + SmallPtrSet PotentiallyDeadPHIs; + PotentiallyDeadPHIs.insert(&PN); + if (DeadPHICycle(PU, PotentiallyDeadPHIs)) + return ReplaceInstUsesWith(PN, UndefValue::get(PN.getType())); + } + + // If this phi has a single use, and if that use just computes a value for + // the next iteration of a loop, delete the phi. This occurs with unused + // induction variables, e.g. "for (int j = 0; ; ++j);". Detecting this + // common case here is good because the only other things that catch this + // are induction variable analysis (sometimes) and ADCE, which is only run + // late. + if (PHIUser->hasOneUse() && + (isa(PHIUser) || isa(PHIUser)) && + PHIUser->use_back() == &PN) { + return ReplaceInstUsesWith(PN, UndefValue::get(PN.getType())); + } + } + + // We sometimes end up with phi cycles that non-obviously end up being the + // same value, for example: + // z = some value; x = phi (y, z); y = phi (x, z) + // where the phi nodes don't necessarily need to be in the same block. Do a + // quick check to see if the PHI node only contains a single non-phi value, if + // so, scan to see if the phi cycle is actually equal to that value. + { + unsigned InValNo = 0, NumOperandVals = PN.getNumIncomingValues(); + // Scan for the first non-phi operand. + while (InValNo != NumOperandVals && + isa(PN.getIncomingValue(InValNo))) + ++InValNo; + + if (InValNo != NumOperandVals) { + Value *NonPhiInVal = PN.getOperand(InValNo); + + // Scan the rest of the operands to see if there are any conflicts, if so + // there is no need to recursively scan other phis. + for (++InValNo; InValNo != NumOperandVals; ++InValNo) { + Value *OpVal = PN.getIncomingValue(InValNo); + if (OpVal != NonPhiInVal && !isa(OpVal)) + break; + } + + // If we scanned over all operands, then we have one unique value plus + // phi values. Scan PHI nodes to see if they all merge in each other or + // the value. + if (InValNo == NumOperandVals) { + SmallPtrSet ValueEqualPHIs; + if (PHIsEqualValue(&PN, NonPhiInVal, ValueEqualPHIs)) + return ReplaceInstUsesWith(PN, NonPhiInVal); + } + } + } + + // If there are multiple PHIs, sort their operands so that they all list + // the blocks in the same order. This will help identical PHIs be eliminated + // by other passes. Other passes shouldn't depend on this for correctness + // however. + PHINode *FirstPN = cast(PN.getParent()->begin()); + if (&PN != FirstPN) + for (unsigned i = 0, e = FirstPN->getNumIncomingValues(); i != e; ++i) { + BasicBlock *BBA = PN.getIncomingBlock(i); + BasicBlock *BBB = FirstPN->getIncomingBlock(i); + if (BBA != BBB) { + Value *VA = PN.getIncomingValue(i); + unsigned j = PN.getBasicBlockIndex(BBB); + Value *VB = PN.getIncomingValue(j); + PN.setIncomingBlock(i, BBB); + PN.setIncomingValue(i, VB); + PN.setIncomingBlock(j, BBA); + PN.setIncomingValue(j, VA); + // NOTE: Instcombine normally would want us to "return &PN" if we + // modified any of the operands of an instruction. However, since we + // aren't adding or removing uses (just rearranging them) we don't do + // this in this case. + } + } + + // If this is an integer PHI and we know that it has an illegal type, see if + // it is only used by trunc or trunc(lshr) operations. If so, we split the + // PHI into the various pieces being extracted. This sort of thing is + // introduced when SROA promotes an aggregate to a single large integer type. + if (isa(PN.getType()) && TD && + !TD->isLegalInteger(PN.getType()->getPrimitiveSizeInBits())) + if (Instruction *Res = SliceUpIllegalIntegerPHI(PN)) + return Res; + + return 0; +} + +Instruction *InstCombiner::visitGetElementPtrInst(GetElementPtrInst &GEP) { + SmallVector Ops(GEP.op_begin(), GEP.op_end()); + + if (Value *V = SimplifyGEPInst(&Ops[0], Ops.size(), TD)) + return ReplaceInstUsesWith(GEP, V); + + Value *PtrOp = GEP.getOperand(0); + + if (isa(GEP.getOperand(0))) + return ReplaceInstUsesWith(GEP, UndefValue::get(GEP.getType())); + + // Eliminate unneeded casts for indices. + if (TD) { + bool MadeChange = false; + unsigned PtrSize = TD->getPointerSizeInBits(); + + gep_type_iterator GTI = gep_type_begin(GEP); + for (User::op_iterator I = GEP.op_begin() + 1, E = GEP.op_end(); + I != E; ++I, ++GTI) { + if (!isa(*GTI)) continue; + + // If we are using a wider index than needed for this platform, shrink it + // to what we need. If narrower, sign-extend it to what we need. This + // explicit cast can make subsequent optimizations more obvious. + unsigned OpBits = cast((*I)->getType())->getBitWidth(); + if (OpBits == PtrSize) + continue; + + *I = Builder->CreateIntCast(*I, TD->getIntPtrType(GEP.getContext()),true); + MadeChange = true; + } + if (MadeChange) return &GEP; + } + + // Combine Indices - If the source pointer to this getelementptr instruction + // is a getelementptr instruction, combine the indices of the two + // getelementptr instructions into a single instruction. + // + if (GEPOperator *Src = dyn_cast(PtrOp)) { + // Note that if our source is a gep chain itself that we wait for that + // chain to be resolved before we perform this transformation. This + // avoids us creating a TON of code in some cases. + // + if (GetElementPtrInst *SrcGEP = + dyn_cast(Src->getOperand(0))) + if (SrcGEP->getNumOperands() == 2) + return 0; // Wait until our source is folded to completion. + + SmallVector Indices; + + // Find out whether the last index in the source GEP is a sequential idx. + bool EndsWithSequential = false; + for (gep_type_iterator I = gep_type_begin(*Src), E = gep_type_end(*Src); + I != E; ++I) + EndsWithSequential = !isa(*I); + + // Can we combine the two pointer arithmetics offsets? + if (EndsWithSequential) { + // Replace: gep (gep %P, long B), long A, ... + // With: T = long A+B; gep %P, T, ... + // + Value *Sum; + Value *SO1 = Src->getOperand(Src->getNumOperands()-1); + Value *GO1 = GEP.getOperand(1); + if (SO1 == Constant::getNullValue(SO1->getType())) { + Sum = GO1; + } else if (GO1 == Constant::getNullValue(GO1->getType())) { + Sum = SO1; + } else { + // If they aren't the same type, then the input hasn't been processed + // by the loop above yet (which canonicalizes sequential index types to + // intptr_t). Just avoid transforming this until the input has been + // normalized. + if (SO1->getType() != GO1->getType()) + return 0; + Sum = Builder->CreateAdd(SO1, GO1, PtrOp->getName()+".sum"); + } + + // Update the GEP in place if possible. + if (Src->getNumOperands() == 2) { + GEP.setOperand(0, Src->getOperand(0)); + GEP.setOperand(1, Sum); + return &GEP; + } + Indices.append(Src->op_begin()+1, Src->op_end()-1); + Indices.push_back(Sum); + Indices.append(GEP.op_begin()+2, GEP.op_end()); + } else if (isa(*GEP.idx_begin()) && + cast(*GEP.idx_begin())->isNullValue() && + Src->getNumOperands() != 1) { + // Otherwise we can do the fold if the first index of the GEP is a zero + Indices.append(Src->op_begin()+1, Src->op_end()); + Indices.append(GEP.idx_begin()+1, GEP.idx_end()); + } + + if (!Indices.empty()) + return (cast(&GEP)->isInBounds() && + Src->isInBounds()) ? + GetElementPtrInst::CreateInBounds(Src->getOperand(0), Indices.begin(), + Indices.end(), GEP.getName()) : + GetElementPtrInst::Create(Src->getOperand(0), Indices.begin(), + Indices.end(), GEP.getName()); + } + + // Handle gep(bitcast x) and gep(gep x, 0, 0, 0). + if (Value *X = getBitCastOperand(PtrOp)) { + assert(isa(X->getType()) && "Must be cast from pointer"); + + // If the input bitcast is actually "bitcast(bitcast(x))", then we don't + // want to change the gep until the bitcasts are eliminated. + if (getBitCastOperand(X)) { + Worklist.AddValue(PtrOp); + return 0; + } + + bool HasZeroPointerIndex = false; + if (ConstantInt *C = dyn_cast(GEP.getOperand(1))) + HasZeroPointerIndex = C->isZero(); + + // Transform: GEP (bitcast [10 x i8]* X to [0 x i8]*), i32 0, ... + // into : GEP [10 x i8]* X, i32 0, ... + // + // Likewise, transform: GEP (bitcast i8* X to [0 x i8]*), i32 0, ... + // into : GEP i8* X, ... + // + // This occurs when the program declares an array extern like "int X[];" + if (HasZeroPointerIndex) { + const PointerType *CPTy = cast(PtrOp->getType()); + const PointerType *XTy = cast(X->getType()); + if (const ArrayType *CATy = + dyn_cast(CPTy->getElementType())) { + // GEP (bitcast i8* X to [0 x i8]*), i32 0, ... ? + if (CATy->getElementType() == XTy->getElementType()) { + // -> GEP i8* X, ... + SmallVector Indices(GEP.idx_begin()+1, GEP.idx_end()); + return cast(&GEP)->isInBounds() ? + GetElementPtrInst::CreateInBounds(X, Indices.begin(), Indices.end(), + GEP.getName()) : + GetElementPtrInst::Create(X, Indices.begin(), Indices.end(), + GEP.getName()); + } + + if (const ArrayType *XATy = dyn_cast(XTy->getElementType())){ + // GEP (bitcast [10 x i8]* X to [0 x i8]*), i32 0, ... ? + if (CATy->getElementType() == XATy->getElementType()) { + // -> GEP [10 x i8]* X, i32 0, ... + // At this point, we know that the cast source type is a pointer + // to an array of the same type as the destination pointer + // array. Because the array type is never stepped over (there + // is a leading zero) we can fold the cast into this GEP. + GEP.setOperand(0, X); + return &GEP; + } + } + } + } else if (GEP.getNumOperands() == 2) { + // Transform things like: + // %t = getelementptr i32* bitcast ([2 x i32]* %str to i32*), i32 %V + // into: %t1 = getelementptr [2 x i32]* %str, i32 0, i32 %V; bitcast + const Type *SrcElTy = cast(X->getType())->getElementType(); + const Type *ResElTy=cast(PtrOp->getType())->getElementType(); + if (TD && isa(SrcElTy) && + TD->getTypeAllocSize(cast(SrcElTy)->getElementType()) == + TD->getTypeAllocSize(ResElTy)) { + Value *Idx[2]; + Idx[0] = Constant::getNullValue(Type::getInt32Ty(*Context)); + Idx[1] = GEP.getOperand(1); + Value *NewGEP = cast(&GEP)->isInBounds() ? + Builder->CreateInBoundsGEP(X, Idx, Idx + 2, GEP.getName()) : + Builder->CreateGEP(X, Idx, Idx + 2, GEP.getName()); + // V and GEP are both pointer types --> BitCast + return new BitCastInst(NewGEP, GEP.getType()); + } + + // Transform things like: + // getelementptr i8* bitcast ([100 x double]* X to i8*), i32 %tmp + // (where tmp = 8*tmp2) into: + // getelementptr [100 x double]* %arr, i32 0, i32 %tmp2; bitcast + + if (TD && isa(SrcElTy) && ResElTy == Type::getInt8Ty(*Context)) { + uint64_t ArrayEltSize = + TD->getTypeAllocSize(cast(SrcElTy)->getElementType()); + + // Check to see if "tmp" is a scale by a multiple of ArrayEltSize. We + // allow either a mul, shift, or constant here. + Value *NewIdx = 0; + ConstantInt *Scale = 0; + if (ArrayEltSize == 1) { + NewIdx = GEP.getOperand(1); + Scale = ConstantInt::get(cast(NewIdx->getType()), 1); + } else if (ConstantInt *CI = dyn_cast(GEP.getOperand(1))) { + NewIdx = ConstantInt::get(CI->getType(), 1); + Scale = CI; + } else if (Instruction *Inst =dyn_cast(GEP.getOperand(1))){ + if (Inst->getOpcode() == Instruction::Shl && + isa(Inst->getOperand(1))) { + ConstantInt *ShAmt = cast(Inst->getOperand(1)); + uint32_t ShAmtVal = ShAmt->getLimitedValue(64); + Scale = ConstantInt::get(cast(Inst->getType()), + 1ULL << ShAmtVal); + NewIdx = Inst->getOperand(0); + } else if (Inst->getOpcode() == Instruction::Mul && + isa(Inst->getOperand(1))) { + Scale = cast(Inst->getOperand(1)); + NewIdx = Inst->getOperand(0); + } + } + + // If the index will be to exactly the right offset with the scale taken + // out, perform the transformation. Note, we don't know whether Scale is + // signed or not. We'll use unsigned version of division/modulo + // operation after making sure Scale doesn't have the sign bit set. + if (ArrayEltSize && Scale && Scale->getSExtValue() >= 0LL && + Scale->getZExtValue() % ArrayEltSize == 0) { + Scale = ConstantInt::get(Scale->getType(), + Scale->getZExtValue() / ArrayEltSize); + if (Scale->getZExtValue() != 1) { + Constant *C = ConstantExpr::getIntegerCast(Scale, NewIdx->getType(), + false /*ZExt*/); + NewIdx = Builder->CreateMul(NewIdx, C, "idxscale"); + } + + // Insert the new GEP instruction. + Value *Idx[2]; + Idx[0] = Constant::getNullValue(Type::getInt32Ty(*Context)); + Idx[1] = NewIdx; + Value *NewGEP = cast(&GEP)->isInBounds() ? + Builder->CreateInBoundsGEP(X, Idx, Idx + 2, GEP.getName()) : + Builder->CreateGEP(X, Idx, Idx + 2, GEP.getName()); + // The NewGEP must be pointer typed, so must the old one -> BitCast + return new BitCastInst(NewGEP, GEP.getType()); + } + } + } + } + + /// See if we can simplify: + /// X = bitcast A* to B* + /// Y = gep X, <...constant indices...> + /// into a gep of the original struct. This is important for SROA and alias + /// analysis of unions. If "A" is also a bitcast, wait for A/X to be merged. + if (BitCastInst *BCI = dyn_cast(PtrOp)) { + if (TD && + !isa(BCI->getOperand(0)) && GEP.hasAllConstantIndices()) { + // Determine how much the GEP moves the pointer. We are guaranteed to get + // a constant back from EmitGEPOffset. + ConstantInt *OffsetV = cast(EmitGEPOffset(&GEP, *this)); + int64_t Offset = OffsetV->getSExtValue(); + + // If this GEP instruction doesn't move the pointer, just replace the GEP + // with a bitcast of the real input to the dest type. + if (Offset == 0) { + // If the bitcast is of an allocation, and the allocation will be + // converted to match the type of the cast, don't touch this. + if (isa(BCI->getOperand(0)) || + isMalloc(BCI->getOperand(0))) { + // See if the bitcast simplifies, if so, don't nuke this GEP yet. + if (Instruction *I = visitBitCast(*BCI)) { + if (I != BCI) { + I->takeName(BCI); + BCI->getParent()->getInstList().insert(BCI, I); + ReplaceInstUsesWith(*BCI, I); + } + return &GEP; + } + } + return new BitCastInst(BCI->getOperand(0), GEP.getType()); + } + + // Otherwise, if the offset is non-zero, we need to find out if there is a + // field at Offset in 'A's type. If so, we can pull the cast through the + // GEP. + SmallVector NewIndices; + const Type *InTy = + cast(BCI->getOperand(0)->getType())->getElementType(); + if (FindElementAtOffset(InTy, Offset, NewIndices, TD, Context)) { + Value *NGEP = cast(&GEP)->isInBounds() ? + Builder->CreateInBoundsGEP(BCI->getOperand(0), NewIndices.begin(), + NewIndices.end()) : + Builder->CreateGEP(BCI->getOperand(0), NewIndices.begin(), + NewIndices.end()); + + if (NGEP->getType() == GEP.getType()) + return ReplaceInstUsesWith(GEP, NGEP); + NGEP->takeName(&GEP); + return new BitCastInst(NGEP, GEP.getType()); + } + } + } + + return 0; +} + +Instruction *InstCombiner::visitAllocaInst(AllocaInst &AI) { + // Convert: alloca Ty, C - where C is a constant != 1 into: alloca [C x Ty], 1 + if (AI.isArrayAllocation()) { // Check C != 1 + if (const ConstantInt *C = dyn_cast(AI.getArraySize())) { + const Type *NewTy = + ArrayType::get(AI.getAllocatedType(), C->getZExtValue()); + assert(isa(AI) && "Unknown type of allocation inst!"); + AllocaInst *New = Builder->CreateAlloca(NewTy, 0, AI.getName()); + New->setAlignment(AI.getAlignment()); + + // Scan to the end of the allocation instructions, to skip over a block of + // allocas if possible...also skip interleaved debug info + // + BasicBlock::iterator It = New; + while (isa(*It) || isa(*It)) ++It; + + // Now that I is pointing to the first non-allocation-inst in the block, + // insert our getelementptr instruction... + // + Value *NullIdx = Constant::getNullValue(Type::getInt32Ty(*Context)); + Value *Idx[2]; + Idx[0] = NullIdx; + Idx[1] = NullIdx; + Value *V = GetElementPtrInst::CreateInBounds(New, Idx, Idx + 2, + New->getName()+".sub", It); + + // Now make everything use the getelementptr instead of the original + // allocation. + return ReplaceInstUsesWith(AI, V); + } else if (isa(AI.getArraySize())) { + return ReplaceInstUsesWith(AI, Constant::getNullValue(AI.getType())); + } + } + + if (TD && isa(AI) && AI.getAllocatedType()->isSized()) { + // If alloca'ing a zero byte object, replace the alloca with a null pointer. + // Note that we only do this for alloca's, because malloc should allocate + // and return a unique pointer, even for a zero byte allocation. + if (TD->getTypeAllocSize(AI.getAllocatedType()) == 0) + return ReplaceInstUsesWith(AI, Constant::getNullValue(AI.getType())); + + // If the alignment is 0 (unspecified), assign it the preferred alignment. + if (AI.getAlignment() == 0) + AI.setAlignment(TD->getPrefTypeAlignment(AI.getAllocatedType())); + } + + return 0; +} + +Instruction *InstCombiner::visitFree(Instruction &FI) { + Value *Op = FI.getOperand(1); + + // free undef -> unreachable. + if (isa(Op)) { + // Insert a new store to null because we cannot modify the CFG here. + new StoreInst(ConstantInt::getTrue(*Context), + UndefValue::get(Type::getInt1PtrTy(*Context)), &FI); + return EraseInstFromFunction(FI); + } + + // If we have 'free null' delete the instruction. This can happen in stl code + // when lots of inlining happens. + if (isa(Op)) + return EraseInstFromFunction(FI); + + // If we have a malloc call whose only use is a free call, delete both. + if (isMalloc(Op)) { + if (CallInst* CI = extractMallocCallFromBitCast(Op)) { + if (Op->hasOneUse() && CI->hasOneUse()) { + EraseInstFromFunction(FI); + EraseInstFromFunction(*CI); + return EraseInstFromFunction(*cast(Op)); + } + } else { + // Op is a call to malloc + if (Op->hasOneUse()) { + EraseInstFromFunction(FI); + return EraseInstFromFunction(*cast(Op)); + } + } + } + + return 0; +} + +/// InstCombineLoadCast - Fold 'load (cast P)' -> cast (load P)' when possible. +static Instruction *InstCombineLoadCast(InstCombiner &IC, LoadInst &LI, + const TargetData *TD) { + User *CI = cast(LI.getOperand(0)); + Value *CastOp = CI->getOperand(0); + LLVMContext *Context = IC.getContext(); + + const PointerType *DestTy = cast(CI->getType()); + const Type *DestPTy = DestTy->getElementType(); + if (const PointerType *SrcTy = dyn_cast(CastOp->getType())) { + + // If the address spaces don't match, don't eliminate the cast. + if (DestTy->getAddressSpace() != SrcTy->getAddressSpace()) + return 0; + + const Type *SrcPTy = SrcTy->getElementType(); + + if (DestPTy->isInteger() || isa(DestPTy) || + isa(DestPTy)) { + // If the source is an array, the code below will not succeed. Check to + // see if a trivial 'gep P, 0, 0' will help matters. Only do this for + // constants. + if (const ArrayType *ASrcTy = dyn_cast(SrcPTy)) + if (Constant *CSrc = dyn_cast(CastOp)) + if (ASrcTy->getNumElements() != 0) { + Value *Idxs[2]; + Idxs[0] = Constant::getNullValue(Type::getInt32Ty(*Context)); + Idxs[1] = Idxs[0]; + CastOp = ConstantExpr::getGetElementPtr(CSrc, Idxs, 2); + SrcTy = cast(CastOp->getType()); + SrcPTy = SrcTy->getElementType(); + } + + if (IC.getTargetData() && + (SrcPTy->isInteger() || isa(SrcPTy) || + isa(SrcPTy)) && + // Do not allow turning this into a load of an integer, which is then + // casted to a pointer, this pessimizes pointer analysis a lot. + (isa(SrcPTy) == isa(LI.getType())) && + IC.getTargetData()->getTypeSizeInBits(SrcPTy) == + IC.getTargetData()->getTypeSizeInBits(DestPTy)) { + + // Okay, we are casting from one integer or pointer type to another of + // the same size. Instead of casting the pointer before the load, cast + // the result of the loaded value. + Value *NewLoad = + IC.Builder->CreateLoad(CastOp, LI.isVolatile(), CI->getName()); + // Now cast the result of the load. + return new BitCastInst(NewLoad, LI.getType()); + } + } + } + return 0; +} + +Instruction *InstCombiner::visitLoadInst(LoadInst &LI) { + Value *Op = LI.getOperand(0); + + // Attempt to improve the alignment. + if (TD) { + unsigned KnownAlign = + GetOrEnforceKnownAlignment(Op, TD->getPrefTypeAlignment(LI.getType())); + if (KnownAlign > + (LI.getAlignment() == 0 ? TD->getABITypeAlignment(LI.getType()) : + LI.getAlignment())) + LI.setAlignment(KnownAlign); + } + + // load (cast X) --> cast (load X) iff safe. + if (isa(Op)) + if (Instruction *Res = InstCombineLoadCast(*this, LI, TD)) + return Res; + + // None of the following transforms are legal for volatile loads. + if (LI.isVolatile()) return 0; + + // Do really simple store-to-load forwarding and load CSE, to catch cases + // where there are several consequtive memory accesses to the same location, + // separated by a few arithmetic operations. + BasicBlock::iterator BBI = &LI; + if (Value *AvailableVal = FindAvailableLoadedValue(Op, LI.getParent(), BBI,6)) + return ReplaceInstUsesWith(LI, AvailableVal); + + // load(gep null, ...) -> unreachable + if (GetElementPtrInst *GEPI = dyn_cast(Op)) { + const Value *GEPI0 = GEPI->getOperand(0); + // TODO: Consider a target hook for valid address spaces for this xform. + if (isa(GEPI0) && GEPI->getPointerAddressSpace() == 0){ + // Insert a new store to null instruction before the load to indicate + // that this code is not reachable. We do this instead of inserting + // an unreachable instruction directly because we cannot modify the + // CFG. + new StoreInst(UndefValue::get(LI.getType()), + Constant::getNullValue(Op->getType()), &LI); + return ReplaceInstUsesWith(LI, UndefValue::get(LI.getType())); + } + } + + // load null/undef -> unreachable + // TODO: Consider a target hook for valid address spaces for this xform. + if (isa(Op) || + (isa(Op) && LI.getPointerAddressSpace() == 0)) { + // Insert a new store to null instruction before the load to indicate that + // this code is not reachable. We do this instead of inserting an + // unreachable instruction directly because we cannot modify the CFG. + new StoreInst(UndefValue::get(LI.getType()), + Constant::getNullValue(Op->getType()), &LI); + return ReplaceInstUsesWith(LI, UndefValue::get(LI.getType())); + } + + // Instcombine load (constantexpr_cast global) -> cast (load global) + if (ConstantExpr *CE = dyn_cast(Op)) + if (CE->isCast()) + if (Instruction *Res = InstCombineLoadCast(*this, LI, TD)) + return Res; + + if (Op->hasOneUse()) { + // Change select and PHI nodes to select values instead of addresses: this + // helps alias analysis out a lot, allows many others simplifications, and + // exposes redundancy in the code. + // + // Note that we cannot do the transformation unless we know that the + // introduced loads cannot trap! Something like this is valid as long as + // the condition is always false: load (select bool %C, int* null, int* %G), + // but it would not be valid if we transformed it to load from null + // unconditionally. + // + if (SelectInst *SI = dyn_cast(Op)) { + // load (select (Cond, &V1, &V2)) --> select(Cond, load &V1, load &V2). + if (isSafeToLoadUnconditionally(SI->getOperand(1), SI) && + isSafeToLoadUnconditionally(SI->getOperand(2), SI)) { + Value *V1 = Builder->CreateLoad(SI->getOperand(1), + SI->getOperand(1)->getName()+".val"); + Value *V2 = Builder->CreateLoad(SI->getOperand(2), + SI->getOperand(2)->getName()+".val"); + return SelectInst::Create(SI->getCondition(), V1, V2); + } + + // load (select (cond, null, P)) -> load P + if (Constant *C = dyn_cast(SI->getOperand(1))) + if (C->isNullValue()) { + LI.setOperand(0, SI->getOperand(2)); + return &LI; + } + + // load (select (cond, P, null)) -> load P + if (Constant *C = dyn_cast(SI->getOperand(2))) + if (C->isNullValue()) { + LI.setOperand(0, SI->getOperand(1)); + return &LI; + } + } + } + return 0; +} + +/// InstCombineStoreToCast - Fold store V, (cast P) -> store (cast V), P +/// when possible. This makes it generally easy to do alias analysis and/or +/// SROA/mem2reg of the memory object. +static Instruction *InstCombineStoreToCast(InstCombiner &IC, StoreInst &SI) { + User *CI = cast(SI.getOperand(1)); + Value *CastOp = CI->getOperand(0); + + const Type *DestPTy = cast(CI->getType())->getElementType(); + const PointerType *SrcTy = dyn_cast(CastOp->getType()); + if (SrcTy == 0) return 0; + + const Type *SrcPTy = SrcTy->getElementType(); + + if (!DestPTy->isInteger() && !isa(DestPTy)) + return 0; + + /// NewGEPIndices - If SrcPTy is an aggregate type, we can emit a "noop gep" + /// to its first element. This allows us to handle things like: + /// store i32 xxx, (bitcast {foo*, float}* %P to i32*) + /// on 32-bit hosts. + SmallVector NewGEPIndices; + + // If the source is an array, the code below will not succeed. Check to + // see if a trivial 'gep P, 0, 0' will help matters. Only do this for + // constants. + if (isa(SrcPTy) || isa(SrcPTy)) { + // Index through pointer. + Constant *Zero = Constant::getNullValue(Type::getInt32Ty(*IC.getContext())); + NewGEPIndices.push_back(Zero); + + while (1) { + if (const StructType *STy = dyn_cast(SrcPTy)) { + if (!STy->getNumElements()) /* Struct can be empty {} */ + break; + NewGEPIndices.push_back(Zero); + SrcPTy = STy->getElementType(0); + } else if (const ArrayType *ATy = dyn_cast(SrcPTy)) { + NewGEPIndices.push_back(Zero); + SrcPTy = ATy->getElementType(); + } else { + break; + } + } + + SrcTy = PointerType::get(SrcPTy, SrcTy->getAddressSpace()); + } + + if (!SrcPTy->isInteger() && !isa(SrcPTy)) + return 0; + + // If the pointers point into different address spaces or if they point to + // values with different sizes, we can't do the transformation. + if (!IC.getTargetData() || + SrcTy->getAddressSpace() != + cast(CI->getType())->getAddressSpace() || + IC.getTargetData()->getTypeSizeInBits(SrcPTy) != + IC.getTargetData()->getTypeSizeInBits(DestPTy)) + return 0; + + // Okay, we are casting from one integer or pointer type to another of + // the same size. Instead of casting the pointer before + // the store, cast the value to be stored. + Value *NewCast; + Value *SIOp0 = SI.getOperand(0); + Instruction::CastOps opcode = Instruction::BitCast; + const Type* CastSrcTy = SIOp0->getType(); + const Type* CastDstTy = SrcPTy; + if (isa(CastDstTy)) { + if (CastSrcTy->isInteger()) + opcode = Instruction::IntToPtr; + } else if (isa(CastDstTy)) { + if (isa(SIOp0->getType())) + opcode = Instruction::PtrToInt; + } + + // SIOp0 is a pointer to aggregate and this is a store to the first field, + // emit a GEP to index into its first field. + if (!NewGEPIndices.empty()) + CastOp = IC.Builder->CreateInBoundsGEP(CastOp, NewGEPIndices.begin(), + NewGEPIndices.end()); + + NewCast = IC.Builder->CreateCast(opcode, SIOp0, CastDstTy, + SIOp0->getName()+".c"); + return new StoreInst(NewCast, CastOp); +} + +/// equivalentAddressValues - Test if A and B will obviously have the same +/// value. This includes recognizing that %t0 and %t1 will have the same +/// value in code like this: +/// %t0 = getelementptr \@a, 0, 3 +/// store i32 0, i32* %t0 +/// %t1 = getelementptr \@a, 0, 3 +/// %t2 = load i32* %t1 +/// +static bool equivalentAddressValues(Value *A, Value *B) { + // Test if the values are trivially equivalent. + if (A == B) return true; + + // Test if the values come form identical arithmetic instructions. + // This uses isIdenticalToWhenDefined instead of isIdenticalTo because + // its only used to compare two uses within the same basic block, which + // means that they'll always either have the same value or one of them + // will have an undefined value. + if (isa(A) || + isa(A) || + isa(A) || + isa(A)) + if (Instruction *BI = dyn_cast(B)) + if (cast(A)->isIdenticalToWhenDefined(BI)) + return true; + + // Otherwise they may not be equivalent. + return false; +} + +// If this instruction has two uses, one of which is a llvm.dbg.declare, +// return the llvm.dbg.declare. +DbgDeclareInst *InstCombiner::hasOneUsePlusDeclare(Value *V) { + if (!V->hasNUses(2)) + return 0; + for (Value::use_iterator UI = V->use_begin(), E = V->use_end(); + UI != E; ++UI) { + if (DbgDeclareInst *DI = dyn_cast(UI)) + return DI; + if (isa(UI) && UI->hasOneUse()) { + if (DbgDeclareInst *DI = dyn_cast(UI->use_begin())) + return DI; + } + } + return 0; +} + +Instruction *InstCombiner::visitStoreInst(StoreInst &SI) { + Value *Val = SI.getOperand(0); + Value *Ptr = SI.getOperand(1); + + // If the RHS is an alloca with a single use, zapify the store, making the + // alloca dead. + // If the RHS is an alloca with a two uses, the other one being a + // llvm.dbg.declare, zapify the store and the declare, making the + // alloca dead. We must do this to prevent declare's from affecting + // codegen. + if (!SI.isVolatile()) { + if (Ptr->hasOneUse()) { + if (isa(Ptr)) { + EraseInstFromFunction(SI); + ++NumCombined; + return 0; + } + if (GetElementPtrInst *GEP = dyn_cast(Ptr)) { + if (isa(GEP->getOperand(0))) { + if (GEP->getOperand(0)->hasOneUse()) { + EraseInstFromFunction(SI); + ++NumCombined; + return 0; + } + if (DbgDeclareInst *DI = hasOneUsePlusDeclare(GEP->getOperand(0))) { + EraseInstFromFunction(*DI); + EraseInstFromFunction(SI); + ++NumCombined; + return 0; + } + } + } + } + if (DbgDeclareInst *DI = hasOneUsePlusDeclare(Ptr)) { + EraseInstFromFunction(*DI); + EraseInstFromFunction(SI); + ++NumCombined; + return 0; + } + } + + // Attempt to improve the alignment. + if (TD) { + unsigned KnownAlign = + GetOrEnforceKnownAlignment(Ptr, TD->getPrefTypeAlignment(Val->getType())); + if (KnownAlign > + (SI.getAlignment() == 0 ? TD->getABITypeAlignment(Val->getType()) : + SI.getAlignment())) + SI.setAlignment(KnownAlign); + } + + // Do really simple DSE, to catch cases where there are several consecutive + // stores to the same location, separated by a few arithmetic operations. This + // situation often occurs with bitfield accesses. + BasicBlock::iterator BBI = &SI; + for (unsigned ScanInsts = 6; BBI != SI.getParent()->begin() && ScanInsts; + --ScanInsts) { + --BBI; + // Don't count debug info directives, lest they affect codegen, + // and we skip pointer-to-pointer bitcasts, which are NOPs. + // It is necessary for correctness to skip those that feed into a + // llvm.dbg.declare, as these are not present when debugging is off. + if (isa(BBI) || + (isa(BBI) && isa(BBI->getType()))) { + ScanInsts++; + continue; + } + + if (StoreInst *PrevSI = dyn_cast(BBI)) { + // Prev store isn't volatile, and stores to the same location? + if (!PrevSI->isVolatile() &&equivalentAddressValues(PrevSI->getOperand(1), + SI.getOperand(1))) { + ++NumDeadStore; + ++BBI; + EraseInstFromFunction(*PrevSI); + continue; + } + break; + } + + // If this is a load, we have to stop. However, if the loaded value is from + // the pointer we're loading and is producing the pointer we're storing, + // then *this* store is dead (X = load P; store X -> P). + if (LoadInst *LI = dyn_cast(BBI)) { + if (LI == Val && equivalentAddressValues(LI->getOperand(0), Ptr) && + !SI.isVolatile()) { + EraseInstFromFunction(SI); + ++NumCombined; + return 0; + } + // Otherwise, this is a load from some other location. Stores before it + // may not be dead. + break; + } + + // Don't skip over loads or things that can modify memory. + if (BBI->mayWriteToMemory() || BBI->mayReadFromMemory()) + break; + } + + + if (SI.isVolatile()) return 0; // Don't hack volatile stores. + + // store X, null -> turns into 'unreachable' in SimplifyCFG + if (isa(Ptr) && SI.getPointerAddressSpace() == 0) { + if (!isa(Val)) { + SI.setOperand(0, UndefValue::get(Val->getType())); + if (Instruction *U = dyn_cast(Val)) + Worklist.Add(U); // Dropped a use. + ++NumCombined; + } + return 0; // Do not modify these! + } + + // store undef, Ptr -> noop + if (isa(Val)) { + EraseInstFromFunction(SI); + ++NumCombined; + return 0; + } + + // If the pointer destination is a cast, see if we can fold the cast into the + // source instead. + if (isa(Ptr)) + if (Instruction *Res = InstCombineStoreToCast(*this, SI)) + return Res; + if (ConstantExpr *CE = dyn_cast(Ptr)) + if (CE->isCast()) + if (Instruction *Res = InstCombineStoreToCast(*this, SI)) + return Res; + + + // If this store is the last instruction in the basic block (possibly + // excepting debug info instructions and the pointer bitcasts that feed + // into them), and if the block ends with an unconditional branch, try + // to move it to the successor block. + BBI = &SI; + do { + ++BBI; + } while (isa(BBI) || + (isa(BBI) && isa(BBI->getType()))); + if (BranchInst *BI = dyn_cast(BBI)) + if (BI->isUnconditional()) + if (SimplifyStoreAtEndOfBlock(SI)) + return 0; // xform done! + + return 0; +} + +/// SimplifyStoreAtEndOfBlock - Turn things like: +/// if () { *P = v1; } else { *P = v2 } +/// into a phi node with a store in the successor. +/// +/// Simplify things like: +/// *P = v1; if () { *P = v2; } +/// into a phi node with a store in the successor. +/// +bool InstCombiner::SimplifyStoreAtEndOfBlock(StoreInst &SI) { + BasicBlock *StoreBB = SI.getParent(); + + // Check to see if the successor block has exactly two incoming edges. If + // so, see if the other predecessor contains a store to the same location. + // if so, insert a PHI node (if needed) and move the stores down. + BasicBlock *DestBB = StoreBB->getTerminator()->getSuccessor(0); + + // Determine whether Dest has exactly two predecessors and, if so, compute + // the other predecessor. + pred_iterator PI = pred_begin(DestBB); + BasicBlock *OtherBB = 0; + if (*PI != StoreBB) + OtherBB = *PI; + ++PI; + if (PI == pred_end(DestBB)) + return false; + + if (*PI != StoreBB) { + if (OtherBB) + return false; + OtherBB = *PI; + } + if (++PI != pred_end(DestBB)) + return false; + + // Bail out if all the relevant blocks aren't distinct (this can happen, + // for example, if SI is in an infinite loop) + if (StoreBB == DestBB || OtherBB == DestBB) + return false; + + // Verify that the other block ends in a branch and is not otherwise empty. + BasicBlock::iterator BBI = OtherBB->getTerminator(); + BranchInst *OtherBr = dyn_cast(BBI); + if (!OtherBr || BBI == OtherBB->begin()) + return false; + + // If the other block ends in an unconditional branch, check for the 'if then + // else' case. there is an instruction before the branch. + StoreInst *OtherStore = 0; + if (OtherBr->isUnconditional()) { + --BBI; + // Skip over debugging info. + while (isa(BBI) || + (isa(BBI) && isa(BBI->getType()))) { + if (BBI==OtherBB->begin()) + return false; + --BBI; + } + // If this isn't a store, isn't a store to the same location, or if the + // alignments differ, bail out. + OtherStore = dyn_cast(BBI); + if (!OtherStore || OtherStore->getOperand(1) != SI.getOperand(1) || + OtherStore->getAlignment() != SI.getAlignment()) + return false; + } else { + // Otherwise, the other block ended with a conditional branch. If one of the + // destinations is StoreBB, then we have the if/then case. + if (OtherBr->getSuccessor(0) != StoreBB && + OtherBr->getSuccessor(1) != StoreBB) + return false; + + // Okay, we know that OtherBr now goes to Dest and StoreBB, so this is an + // if/then triangle. See if there is a store to the same ptr as SI that + // lives in OtherBB. + for (;; --BBI) { + // Check to see if we find the matching store. + if ((OtherStore = dyn_cast(BBI))) { + if (OtherStore->getOperand(1) != SI.getOperand(1) || + OtherStore->getAlignment() != SI.getAlignment()) + return false; + break; + } + // If we find something that may be using or overwriting the stored + // value, or if we run out of instructions, we can't do the xform. + if (BBI->mayReadFromMemory() || BBI->mayWriteToMemory() || + BBI == OtherBB->begin()) + return false; + } + + // In order to eliminate the store in OtherBr, we have to + // make sure nothing reads or overwrites the stored value in + // StoreBB. + for (BasicBlock::iterator I = StoreBB->begin(); &*I != &SI; ++I) { + // FIXME: This should really be AA driven. + if (I->mayReadFromMemory() || I->mayWriteToMemory()) + return false; + } + } + + // Insert a PHI node now if we need it. + Value *MergedVal = OtherStore->getOperand(0); + if (MergedVal != SI.getOperand(0)) { + PHINode *PN = PHINode::Create(MergedVal->getType(), "storemerge"); + PN->reserveOperandSpace(2); + PN->addIncoming(SI.getOperand(0), SI.getParent()); + PN->addIncoming(OtherStore->getOperand(0), OtherBB); + MergedVal = InsertNewInstBefore(PN, DestBB->front()); + } + + // Advance to a place where it is safe to insert the new store and + // insert it. + BBI = DestBB->getFirstNonPHI(); + InsertNewInstBefore(new StoreInst(MergedVal, SI.getOperand(1), + OtherStore->isVolatile(), + SI.getAlignment()), *BBI); + + // Nuke the old stores. + EraseInstFromFunction(SI); + EraseInstFromFunction(*OtherStore); + ++NumCombined; + return true; +} + + +Instruction *InstCombiner::visitBranchInst(BranchInst &BI) { + // Change br (not X), label True, label False to: br X, label False, True + Value *X = 0; + BasicBlock *TrueDest; + BasicBlock *FalseDest; + if (match(&BI, m_Br(m_Not(m_Value(X)), TrueDest, FalseDest)) && + !isa(X)) { + // Swap Destinations and condition... + BI.setCondition(X); + BI.setSuccessor(0, FalseDest); + BI.setSuccessor(1, TrueDest); + return &BI; + } + + // Cannonicalize fcmp_one -> fcmp_oeq + FCmpInst::Predicate FPred; Value *Y; + if (match(&BI, m_Br(m_FCmp(FPred, m_Value(X), m_Value(Y)), + TrueDest, FalseDest)) && + BI.getCondition()->hasOneUse()) + if (FPred == FCmpInst::FCMP_ONE || FPred == FCmpInst::FCMP_OLE || + FPred == FCmpInst::FCMP_OGE) { + FCmpInst *Cond = cast(BI.getCondition()); + Cond->setPredicate(FCmpInst::getInversePredicate(FPred)); + + // Swap Destinations and condition. + BI.setSuccessor(0, FalseDest); + BI.setSuccessor(1, TrueDest); + Worklist.Add(Cond); + return &BI; + } + + // Cannonicalize icmp_ne -> icmp_eq + ICmpInst::Predicate IPred; + if (match(&BI, m_Br(m_ICmp(IPred, m_Value(X), m_Value(Y)), + TrueDest, FalseDest)) && + BI.getCondition()->hasOneUse()) + if (IPred == ICmpInst::ICMP_NE || IPred == ICmpInst::ICMP_ULE || + IPred == ICmpInst::ICMP_SLE || IPred == ICmpInst::ICMP_UGE || + IPred == ICmpInst::ICMP_SGE) { + ICmpInst *Cond = cast(BI.getCondition()); + Cond->setPredicate(ICmpInst::getInversePredicate(IPred)); + // Swap Destinations and condition. + BI.setSuccessor(0, FalseDest); + BI.setSuccessor(1, TrueDest); + Worklist.Add(Cond); + return &BI; + } + + return 0; +} + +Instruction *InstCombiner::visitSwitchInst(SwitchInst &SI) { + Value *Cond = SI.getCondition(); + if (Instruction *I = dyn_cast(Cond)) { + if (I->getOpcode() == Instruction::Add) + if (ConstantInt *AddRHS = dyn_cast(I->getOperand(1))) { + // change 'switch (X+4) case 1:' into 'switch (X) case -3' + for (unsigned i = 2, e = SI.getNumOperands(); i != e; i += 2) + SI.setOperand(i, + ConstantExpr::getSub(cast(SI.getOperand(i)), + AddRHS)); + SI.setOperand(0, I->getOperand(0)); + Worklist.Add(I); + return &SI; + } + } + return 0; +} + +Instruction *InstCombiner::visitExtractValueInst(ExtractValueInst &EV) { + Value *Agg = EV.getAggregateOperand(); + + if (!EV.hasIndices()) + return ReplaceInstUsesWith(EV, Agg); + + if (Constant *C = dyn_cast(Agg)) { + if (isa(C)) + return ReplaceInstUsesWith(EV, UndefValue::get(EV.getType())); + + if (isa(C)) + return ReplaceInstUsesWith(EV, Constant::getNullValue(EV.getType())); + + if (isa(C) || isa(C)) { + // Extract the element indexed by the first index out of the constant + Value *V = C->getOperand(*EV.idx_begin()); + if (EV.getNumIndices() > 1) + // Extract the remaining indices out of the constant indexed by the + // first index + return ExtractValueInst::Create(V, EV.idx_begin() + 1, EV.idx_end()); + else + return ReplaceInstUsesWith(EV, V); + } + return 0; // Can't handle other constants + } + if (InsertValueInst *IV = dyn_cast(Agg)) { + // We're extracting from an insertvalue instruction, compare the indices + const unsigned *exti, *exte, *insi, *inse; + for (exti = EV.idx_begin(), insi = IV->idx_begin(), + exte = EV.idx_end(), inse = IV->idx_end(); + exti != exte && insi != inse; + ++exti, ++insi) { + if (*insi != *exti) + // The insert and extract both reference distinctly different elements. + // This means the extract is not influenced by the insert, and we can + // replace the aggregate operand of the extract with the aggregate + // operand of the insert. i.e., replace + // %I = insertvalue { i32, { i32 } } %A, { i32 } { i32 42 }, 1 + // %E = extractvalue { i32, { i32 } } %I, 0 + // with + // %E = extractvalue { i32, { i32 } } %A, 0 + return ExtractValueInst::Create(IV->getAggregateOperand(), + EV.idx_begin(), EV.idx_end()); + } + if (exti == exte && insi == inse) + // Both iterators are at the end: Index lists are identical. Replace + // %B = insertvalue { i32, { i32 } } %A, i32 42, 1, 0 + // %C = extractvalue { i32, { i32 } } %B, 1, 0 + // with "i32 42" + return ReplaceInstUsesWith(EV, IV->getInsertedValueOperand()); + if (exti == exte) { + // The extract list is a prefix of the insert list. i.e. replace + // %I = insertvalue { i32, { i32 } } %A, i32 42, 1, 0 + // %E = extractvalue { i32, { i32 } } %I, 1 + // with + // %X = extractvalue { i32, { i32 } } %A, 1 + // %E = insertvalue { i32 } %X, i32 42, 0 + // by switching the order of the insert and extract (though the + // insertvalue should be left in, since it may have other uses). + Value *NewEV = Builder->CreateExtractValue(IV->getAggregateOperand(), + EV.idx_begin(), EV.idx_end()); + return InsertValueInst::Create(NewEV, IV->getInsertedValueOperand(), + insi, inse); + } + if (insi == inse) + // The insert list is a prefix of the extract list + // We can simply remove the common indices from the extract and make it + // operate on the inserted value instead of the insertvalue result. + // i.e., replace + // %I = insertvalue { i32, { i32 } } %A, { i32 } { i32 42 }, 1 + // %E = extractvalue { i32, { i32 } } %I, 1, 0 + // with + // %E extractvalue { i32 } { i32 42 }, 0 + return ExtractValueInst::Create(IV->getInsertedValueOperand(), + exti, exte); + } + if (IntrinsicInst *II = dyn_cast(Agg)) { + // We're extracting from an intrinsic, see if we're the only user, which + // allows us to simplify multiple result intrinsics to simpler things that + // just get one value.. + if (II->hasOneUse()) { + // Check if we're grabbing the overflow bit or the result of a 'with + // overflow' intrinsic. If it's the latter we can remove the intrinsic + // and replace it with a traditional binary instruction. + switch (II->getIntrinsicID()) { + case Intrinsic::uadd_with_overflow: + case Intrinsic::sadd_with_overflow: + if (*EV.idx_begin() == 0) { // Normal result. + Value *LHS = II->getOperand(1), *RHS = II->getOperand(2); + II->replaceAllUsesWith(UndefValue::get(II->getType())); + EraseInstFromFunction(*II); + return BinaryOperator::CreateAdd(LHS, RHS); + } + break; + case Intrinsic::usub_with_overflow: + case Intrinsic::ssub_with_overflow: + if (*EV.idx_begin() == 0) { // Normal result. + Value *LHS = II->getOperand(1), *RHS = II->getOperand(2); + II->replaceAllUsesWith(UndefValue::get(II->getType())); + EraseInstFromFunction(*II); + return BinaryOperator::CreateSub(LHS, RHS); + } + break; + case Intrinsic::umul_with_overflow: + case Intrinsic::smul_with_overflow: + if (*EV.idx_begin() == 0) { // Normal result. + Value *LHS = II->getOperand(1), *RHS = II->getOperand(2); + II->replaceAllUsesWith(UndefValue::get(II->getType())); + EraseInstFromFunction(*II); + return BinaryOperator::CreateMul(LHS, RHS); + } + break; + default: + break; + } + } + } + // Can't simplify extracts from other values. Note that nested extracts are + // already simplified implicitely by the above (extract ( extract (insert) ) + // will be translated into extract ( insert ( extract ) ) first and then just + // the value inserted, if appropriate). + return 0; +} + +/// CheapToScalarize - Return true if the value is cheaper to scalarize than it +/// is to leave as a vector operation. +static bool CheapToScalarize(Value *V, bool isConstant) { + if (isa(V)) + return true; + if (ConstantVector *C = dyn_cast(V)) { + if (isConstant) return true; + // If all elts are the same, we can extract. + Constant *Op0 = C->getOperand(0); + for (unsigned i = 1; i < C->getNumOperands(); ++i) + if (C->getOperand(i) != Op0) + return false; + return true; + } + Instruction *I = dyn_cast(V); + if (!I) return false; + + // Insert element gets simplified to the inserted element or is deleted if + // this is constant idx extract element and its a constant idx insertelt. + if (I->getOpcode() == Instruction::InsertElement && isConstant && + isa(I->getOperand(2))) + return true; + if (I->getOpcode() == Instruction::Load && I->hasOneUse()) + return true; + if (BinaryOperator *BO = dyn_cast(I)) + if (BO->hasOneUse() && + (CheapToScalarize(BO->getOperand(0), isConstant) || + CheapToScalarize(BO->getOperand(1), isConstant))) + return true; + if (CmpInst *CI = dyn_cast(I)) + if (CI->hasOneUse() && + (CheapToScalarize(CI->getOperand(0), isConstant) || + CheapToScalarize(CI->getOperand(1), isConstant))) + return true; + + return false; +} + +/// Read and decode a shufflevector mask. +/// +/// It turns undef elements into values that are larger than the number of +/// elements in the input. +static std::vector getShuffleMask(const ShuffleVectorInst *SVI) { + unsigned NElts = SVI->getType()->getNumElements(); + if (isa(SVI->getOperand(2))) + return std::vector(NElts, 0); + if (isa(SVI->getOperand(2))) + return std::vector(NElts, 2*NElts); + + std::vector Result; + const ConstantVector *CP = cast(SVI->getOperand(2)); + for (User::const_op_iterator i = CP->op_begin(), e = CP->op_end(); i!=e; ++i) + if (isa(*i)) + Result.push_back(NElts*2); // undef -> 8 + else + Result.push_back(cast(*i)->getZExtValue()); + return Result; +} + +/// FindScalarElement - Given a vector and an element number, see if the scalar +/// value is already around as a register, for example if it were inserted then +/// extracted from the vector. +static Value *FindScalarElement(Value *V, unsigned EltNo, + LLVMContext *Context) { + assert(isa(V->getType()) && "Not looking at a vector?"); + const VectorType *PTy = cast(V->getType()); + unsigned Width = PTy->getNumElements(); + if (EltNo >= Width) // Out of range access. + return UndefValue::get(PTy->getElementType()); + + if (isa(V)) + return UndefValue::get(PTy->getElementType()); + else if (isa(V)) + return Constant::getNullValue(PTy->getElementType()); + else if (ConstantVector *CP = dyn_cast(V)) + return CP->getOperand(EltNo); + else if (InsertElementInst *III = dyn_cast(V)) { + // If this is an insert to a variable element, we don't know what it is. + if (!isa(III->getOperand(2))) + return 0; + unsigned IIElt = cast(III->getOperand(2))->getZExtValue(); + + // If this is an insert to the element we are looking for, return the + // inserted value. + if (EltNo == IIElt) + return III->getOperand(1); + + // Otherwise, the insertelement doesn't modify the value, recurse on its + // vector input. + return FindScalarElement(III->getOperand(0), EltNo, Context); + } else if (ShuffleVectorInst *SVI = dyn_cast(V)) { + unsigned LHSWidth = + cast(SVI->getOperand(0)->getType())->getNumElements(); + unsigned InEl = getShuffleMask(SVI)[EltNo]; + if (InEl < LHSWidth) + return FindScalarElement(SVI->getOperand(0), InEl, Context); + else if (InEl < LHSWidth*2) + return FindScalarElement(SVI->getOperand(1), InEl - LHSWidth, Context); + else + return UndefValue::get(PTy->getElementType()); + } + + // Otherwise, we don't know. + return 0; +} + +Instruction *InstCombiner::visitExtractElementInst(ExtractElementInst &EI) { + // If vector val is undef, replace extract with scalar undef. + if (isa(EI.getOperand(0))) + return ReplaceInstUsesWith(EI, UndefValue::get(EI.getType())); + + // If vector val is constant 0, replace extract with scalar 0. + if (isa(EI.getOperand(0))) + return ReplaceInstUsesWith(EI, Constant::getNullValue(EI.getType())); + + if (ConstantVector *C = dyn_cast(EI.getOperand(0))) { + // If vector val is constant with all elements the same, replace EI with + // that element. When the elements are not identical, we cannot replace yet + // (we do that below, but only when the index is constant). + Constant *op0 = C->getOperand(0); + for (unsigned i = 1; i != C->getNumOperands(); ++i) + if (C->getOperand(i) != op0) { + op0 = 0; + break; + } + if (op0) + return ReplaceInstUsesWith(EI, op0); + } + + // If extracting a specified index from the vector, see if we can recursively + // find a previously computed scalar that was inserted into the vector. + if (ConstantInt *IdxC = dyn_cast(EI.getOperand(1))) { + unsigned IndexVal = IdxC->getZExtValue(); + unsigned VectorWidth = EI.getVectorOperandType()->getNumElements(); + + // If this is extracting an invalid index, turn this into undef, to avoid + // crashing the code below. + if (IndexVal >= VectorWidth) + return ReplaceInstUsesWith(EI, UndefValue::get(EI.getType())); + + // This instruction only demands the single element from the input vector. + // If the input vector has a single use, simplify it based on this use + // property. + if (EI.getOperand(0)->hasOneUse() && VectorWidth != 1) { + APInt UndefElts(VectorWidth, 0); + APInt DemandedMask(VectorWidth, 1 << IndexVal); + if (Value *V = SimplifyDemandedVectorElts(EI.getOperand(0), + DemandedMask, UndefElts)) { + EI.setOperand(0, V); + return &EI; + } + } + + if (Value *Elt = FindScalarElement(EI.getOperand(0), IndexVal, Context)) + return ReplaceInstUsesWith(EI, Elt); + + // If the this extractelement is directly using a bitcast from a vector of + // the same number of elements, see if we can find the source element from + // it. In this case, we will end up needing to bitcast the scalars. + if (BitCastInst *BCI = dyn_cast(EI.getOperand(0))) { + if (const VectorType *VT = + dyn_cast(BCI->getOperand(0)->getType())) + if (VT->getNumElements() == VectorWidth) + if (Value *Elt = FindScalarElement(BCI->getOperand(0), + IndexVal, Context)) + return new BitCastInst(Elt, EI.getType()); + } + } + + if (Instruction *I = dyn_cast(EI.getOperand(0))) { + // Push extractelement into predecessor operation if legal and + // profitable to do so + if (BinaryOperator *BO = dyn_cast(I)) { + if (I->hasOneUse() && + CheapToScalarize(BO, isa(EI.getOperand(1)))) { + Value *newEI0 = + Builder->CreateExtractElement(BO->getOperand(0), EI.getOperand(1), + EI.getName()+".lhs"); + Value *newEI1 = + Builder->CreateExtractElement(BO->getOperand(1), EI.getOperand(1), + EI.getName()+".rhs"); + return BinaryOperator::Create(BO->getOpcode(), newEI0, newEI1); + } + } else if (InsertElementInst *IE = dyn_cast(I)) { + // Extracting the inserted element? + if (IE->getOperand(2) == EI.getOperand(1)) + return ReplaceInstUsesWith(EI, IE->getOperand(1)); + // If the inserted and extracted elements are constants, they must not + // be the same value, extract from the pre-inserted value instead. + if (isa(IE->getOperand(2)) && isa(EI.getOperand(1))) { + Worklist.AddValue(EI.getOperand(0)); + EI.setOperand(0, IE->getOperand(0)); + return &EI; + } + } else if (ShuffleVectorInst *SVI = dyn_cast(I)) { + // If this is extracting an element from a shufflevector, figure out where + // it came from and extract from the appropriate input element instead. + if (ConstantInt *Elt = dyn_cast(EI.getOperand(1))) { + unsigned SrcIdx = getShuffleMask(SVI)[Elt->getZExtValue()]; + Value *Src; + unsigned LHSWidth = + cast(SVI->getOperand(0)->getType())->getNumElements(); + + if (SrcIdx < LHSWidth) + Src = SVI->getOperand(0); + else if (SrcIdx < LHSWidth*2) { + SrcIdx -= LHSWidth; + Src = SVI->getOperand(1); + } else { + return ReplaceInstUsesWith(EI, UndefValue::get(EI.getType())); + } + return ExtractElementInst::Create(Src, + ConstantInt::get(Type::getInt32Ty(*Context), SrcIdx, + false)); + } + } + // FIXME: Canonicalize extractelement(bitcast) -> bitcast(extractelement) + } + return 0; +} + +/// CollectSingleShuffleElements - If V is a shuffle of values that ONLY returns +/// elements from either LHS or RHS, return the shuffle mask and true. +/// Otherwise, return false. +static bool CollectSingleShuffleElements(Value *V, Value *LHS, Value *RHS, + std::vector &Mask, + LLVMContext *Context) { + assert(V->getType() == LHS->getType() && V->getType() == RHS->getType() && + "Invalid CollectSingleShuffleElements"); + unsigned NumElts = cast(V->getType())->getNumElements(); + + if (isa(V)) { + Mask.assign(NumElts, UndefValue::get(Type::getInt32Ty(*Context))); + return true; + } else if (V == LHS) { + for (unsigned i = 0; i != NumElts; ++i) + Mask.push_back(ConstantInt::get(Type::getInt32Ty(*Context), i)); + return true; + } else if (V == RHS) { + for (unsigned i = 0; i != NumElts; ++i) + Mask.push_back(ConstantInt::get(Type::getInt32Ty(*Context), i+NumElts)); + return true; + } else if (InsertElementInst *IEI = dyn_cast(V)) { + // If this is an insert of an extract from some other vector, include it. + Value *VecOp = IEI->getOperand(0); + Value *ScalarOp = IEI->getOperand(1); + Value *IdxOp = IEI->getOperand(2); + + if (!isa(IdxOp)) + return false; + unsigned InsertedIdx = cast(IdxOp)->getZExtValue(); + + if (isa(ScalarOp)) { // inserting undef into vector. + // Okay, we can handle this if the vector we are insertinting into is + // transitively ok. + if (CollectSingleShuffleElements(VecOp, LHS, RHS, Mask, Context)) { + // If so, update the mask to reflect the inserted undef. + Mask[InsertedIdx] = UndefValue::get(Type::getInt32Ty(*Context)); + return true; + } + } else if (ExtractElementInst *EI = dyn_cast(ScalarOp)){ + if (isa(EI->getOperand(1)) && + EI->getOperand(0)->getType() == V->getType()) { + unsigned ExtractedIdx = + cast(EI->getOperand(1))->getZExtValue(); + + // This must be extracting from either LHS or RHS. + if (EI->getOperand(0) == LHS || EI->getOperand(0) == RHS) { + // Okay, we can handle this if the vector we are insertinting into is + // transitively ok. + if (CollectSingleShuffleElements(VecOp, LHS, RHS, Mask, Context)) { + // If so, update the mask to reflect the inserted value. + if (EI->getOperand(0) == LHS) { + Mask[InsertedIdx % NumElts] = + ConstantInt::get(Type::getInt32Ty(*Context), ExtractedIdx); + } else { + assert(EI->getOperand(0) == RHS); + Mask[InsertedIdx % NumElts] = + ConstantInt::get(Type::getInt32Ty(*Context), ExtractedIdx+NumElts); + + } + return true; + } + } + } + } + } + // TODO: Handle shufflevector here! + + return false; +} + +/// CollectShuffleElements - We are building a shuffle of V, using RHS as the +/// RHS of the shuffle instruction, if it is not null. Return a shuffle mask +/// that computes V and the LHS value of the shuffle. +static Value *CollectShuffleElements(Value *V, std::vector &Mask, + Value *&RHS, LLVMContext *Context) { + assert(isa(V->getType()) && + (RHS == 0 || V->getType() == RHS->getType()) && + "Invalid shuffle!"); + unsigned NumElts = cast(V->getType())->getNumElements(); + + if (isa(V)) { + Mask.assign(NumElts, UndefValue::get(Type::getInt32Ty(*Context))); + return V; + } else if (isa(V)) { + Mask.assign(NumElts, ConstantInt::get(Type::getInt32Ty(*Context), 0)); + return V; + } else if (InsertElementInst *IEI = dyn_cast(V)) { + // If this is an insert of an extract from some other vector, include it. + Value *VecOp = IEI->getOperand(0); + Value *ScalarOp = IEI->getOperand(1); + Value *IdxOp = IEI->getOperand(2); + + if (ExtractElementInst *EI = dyn_cast(ScalarOp)) { + if (isa(EI->getOperand(1)) && isa(IdxOp) && + EI->getOperand(0)->getType() == V->getType()) { + unsigned ExtractedIdx = + cast(EI->getOperand(1))->getZExtValue(); + unsigned InsertedIdx = cast(IdxOp)->getZExtValue(); + + // Either the extracted from or inserted into vector must be RHSVec, + // otherwise we'd end up with a shuffle of three inputs. + if (EI->getOperand(0) == RHS || RHS == 0) { + RHS = EI->getOperand(0); + Value *V = CollectShuffleElements(VecOp, Mask, RHS, Context); + Mask[InsertedIdx % NumElts] = + ConstantInt::get(Type::getInt32Ty(*Context), NumElts+ExtractedIdx); + return V; + } + + if (VecOp == RHS) { + Value *V = CollectShuffleElements(EI->getOperand(0), Mask, + RHS, Context); + // Everything but the extracted element is replaced with the RHS. + for (unsigned i = 0; i != NumElts; ++i) { + if (i != InsertedIdx) + Mask[i] = ConstantInt::get(Type::getInt32Ty(*Context), NumElts+i); + } + return V; + } + + // If this insertelement is a chain that comes from exactly these two + // vectors, return the vector and the effective shuffle. + if (CollectSingleShuffleElements(IEI, EI->getOperand(0), RHS, Mask, + Context)) + return EI->getOperand(0); + + } + } + } + // TODO: Handle shufflevector here! + + // Otherwise, can't do anything fancy. Return an identity vector. + for (unsigned i = 0; i != NumElts; ++i) + Mask.push_back(ConstantInt::get(Type::getInt32Ty(*Context), i)); + return V; +} + +Instruction *InstCombiner::visitInsertElementInst(InsertElementInst &IE) { + Value *VecOp = IE.getOperand(0); + Value *ScalarOp = IE.getOperand(1); + Value *IdxOp = IE.getOperand(2); + + // Inserting an undef or into an undefined place, remove this. + if (isa(ScalarOp) || isa(IdxOp)) + ReplaceInstUsesWith(IE, VecOp); + + // If the inserted element was extracted from some other vector, and if the + // indexes are constant, try to turn this into a shufflevector operation. + if (ExtractElementInst *EI = dyn_cast(ScalarOp)) { + if (isa(EI->getOperand(1)) && isa(IdxOp) && + EI->getOperand(0)->getType() == IE.getType()) { + unsigned NumVectorElts = IE.getType()->getNumElements(); + unsigned ExtractedIdx = + cast(EI->getOperand(1))->getZExtValue(); + unsigned InsertedIdx = cast(IdxOp)->getZExtValue(); + + if (ExtractedIdx >= NumVectorElts) // Out of range extract. + return ReplaceInstUsesWith(IE, VecOp); + + if (InsertedIdx >= NumVectorElts) // Out of range insert. + return ReplaceInstUsesWith(IE, UndefValue::get(IE.getType())); + + // If we are extracting a value from a vector, then inserting it right + // back into the same place, just use the input vector. + if (EI->getOperand(0) == VecOp && ExtractedIdx == InsertedIdx) + return ReplaceInstUsesWith(IE, VecOp); + + // If this insertelement isn't used by some other insertelement, turn it + // (and any insertelements it points to), into one big shuffle. + if (!IE.hasOneUse() || !isa(IE.use_back())) { + std::vector Mask; + Value *RHS = 0; + Value *LHS = CollectShuffleElements(&IE, Mask, RHS, Context); + if (RHS == 0) RHS = UndefValue::get(LHS->getType()); + // We now have a shuffle of LHS, RHS, Mask. + return new ShuffleVectorInst(LHS, RHS, + ConstantVector::get(Mask)); + } + } + } + + unsigned VWidth = cast(VecOp->getType())->getNumElements(); + APInt UndefElts(VWidth, 0); + APInt AllOnesEltMask(APInt::getAllOnesValue(VWidth)); + if (SimplifyDemandedVectorElts(&IE, AllOnesEltMask, UndefElts)) + return &IE; + + return 0; +} + + +Instruction *InstCombiner::visitShuffleVectorInst(ShuffleVectorInst &SVI) { + Value *LHS = SVI.getOperand(0); + Value *RHS = SVI.getOperand(1); + std::vector Mask = getShuffleMask(&SVI); + + bool MadeChange = false; + + // Undefined shuffle mask -> undefined value. + if (isa(SVI.getOperand(2))) + return ReplaceInstUsesWith(SVI, UndefValue::get(SVI.getType())); + + unsigned VWidth = cast(SVI.getType())->getNumElements(); + + if (VWidth != cast(LHS->getType())->getNumElements()) + return 0; + + APInt UndefElts(VWidth, 0); + APInt AllOnesEltMask(APInt::getAllOnesValue(VWidth)); + if (SimplifyDemandedVectorElts(&SVI, AllOnesEltMask, UndefElts)) { + LHS = SVI.getOperand(0); + RHS = SVI.getOperand(1); + MadeChange = true; + } + + // Canonicalize shuffle(x ,x,mask) -> shuffle(x, undef,mask') + // Canonicalize shuffle(undef,x,mask) -> shuffle(x, undef,mask'). + if (LHS == RHS || isa(LHS)) { + if (isa(LHS) && LHS == RHS) { + // shuffle(undef,undef,mask) -> undef. + return ReplaceInstUsesWith(SVI, LHS); + } + + // Remap any references to RHS to use LHS. + std::vector Elts; + for (unsigned i = 0, e = Mask.size(); i != e; ++i) { + if (Mask[i] >= 2*e) + Elts.push_back(UndefValue::get(Type::getInt32Ty(*Context))); + else { + if ((Mask[i] >= e && isa(RHS)) || + (Mask[i] < e && isa(LHS))) { + Mask[i] = 2*e; // Turn into undef. + Elts.push_back(UndefValue::get(Type::getInt32Ty(*Context))); + } else { + Mask[i] = Mask[i] % e; // Force to LHS. + Elts.push_back(ConstantInt::get(Type::getInt32Ty(*Context), Mask[i])); + } + } + } + SVI.setOperand(0, SVI.getOperand(1)); + SVI.setOperand(1, UndefValue::get(RHS->getType())); + SVI.setOperand(2, ConstantVector::get(Elts)); + LHS = SVI.getOperand(0); + RHS = SVI.getOperand(1); + MadeChange = true; + } + + // Analyze the shuffle, are the LHS or RHS and identity shuffles? + bool isLHSID = true, isRHSID = true; + + for (unsigned i = 0, e = Mask.size(); i != e; ++i) { + if (Mask[i] >= e*2) continue; // Ignore undef values. + // Is this an identity shuffle of the LHS value? + isLHSID &= (Mask[i] == i); + + // Is this an identity shuffle of the RHS value? + isRHSID &= (Mask[i]-e == i); + } + + // Eliminate identity shuffles. + if (isLHSID) return ReplaceInstUsesWith(SVI, LHS); + if (isRHSID) return ReplaceInstUsesWith(SVI, RHS); + + // If the LHS is a shufflevector itself, see if we can combine it with this + // one without producing an unusual shuffle. Here we are really conservative: + // we are absolutely afraid of producing a shuffle mask not in the input + // program, because the code gen may not be smart enough to turn a merged + // shuffle into two specific shuffles: it may produce worse code. As such, + // we only merge two shuffles if the result is one of the two input shuffle + // masks. In this case, merging the shuffles just removes one instruction, + // which we know is safe. This is good for things like turning: + // (splat(splat)) -> splat. + if (ShuffleVectorInst *LHSSVI = dyn_cast(LHS)) { + if (isa(RHS)) { + std::vector LHSMask = getShuffleMask(LHSSVI); + + if (LHSMask.size() == Mask.size()) { + std::vector NewMask; + for (unsigned i = 0, e = Mask.size(); i != e; ++i) + if (Mask[i] >= e) + NewMask.push_back(2*e); + else + NewMask.push_back(LHSMask[Mask[i]]); + + // If the result mask is equal to the src shuffle or this + // shuffle mask, do the replacement. + if (NewMask == LHSMask || NewMask == Mask) { + unsigned LHSInNElts = + cast(LHSSVI->getOperand(0)->getType())-> + getNumElements(); + std::vector Elts; + for (unsigned i = 0, e = NewMask.size(); i != e; ++i) { + if (NewMask[i] >= LHSInNElts*2) { + Elts.push_back(UndefValue::get(Type::getInt32Ty(*Context))); + } else { + Elts.push_back(ConstantInt::get(Type::getInt32Ty(*Context), + NewMask[i])); + } + } + return new ShuffleVectorInst(LHSSVI->getOperand(0), + LHSSVI->getOperand(1), + ConstantVector::get(Elts)); + } + } + } + } + + return MadeChange ? &SVI : 0; +} + + + + +/// TryToSinkInstruction - Try to move the specified instruction from its +/// current block into the beginning of DestBlock, which can only happen if it's +/// safe to move the instruction past all of the instructions between it and the +/// end of its block. +static bool TryToSinkInstruction(Instruction *I, BasicBlock *DestBlock) { + assert(I->hasOneUse() && "Invariants didn't hold!"); + + // Cannot move control-flow-involving, volatile loads, vaarg, etc. + if (isa(I) || I->mayHaveSideEffects() || isa(I)) + return false; + + // Do not sink alloca instructions out of the entry block. + if (isa(I) && I->getParent() == + &DestBlock->getParent()->getEntryBlock()) + return false; + + // We can only sink load instructions if there is nothing between the load and + // the end of block that could change the value. + if (I->mayReadFromMemory()) { + for (BasicBlock::iterator Scan = I, E = I->getParent()->end(); + Scan != E; ++Scan) + if (Scan->mayWriteToMemory()) + return false; + } + + BasicBlock::iterator InsertPos = DestBlock->getFirstNonPHI(); + + CopyPrecedingStopPoint(I, InsertPos); + I->moveBefore(InsertPos); + ++NumSunkInst; + return true; +} + + +/// AddReachableCodeToWorklist - Walk the function in depth-first order, adding +/// all reachable code to the worklist. +/// +/// This has a couple of tricks to make the code faster and more powerful. In +/// particular, we constant fold and DCE instructions as we go, to avoid adding +/// them to the worklist (this significantly speeds up instcombine on code where +/// many instructions are dead or constant). Additionally, if we find a branch +/// whose condition is a known constant, we only visit the reachable successors. +/// +static bool AddReachableCodeToWorklist(BasicBlock *BB, + SmallPtrSet &Visited, + InstCombiner &IC, + const TargetData *TD) { + bool MadeIRChange = false; + SmallVector Worklist; + Worklist.push_back(BB); + + std::vector InstrsForInstCombineWorklist; + InstrsForInstCombineWorklist.reserve(128); + + SmallPtrSet FoldedConstants; + + while (!Worklist.empty()) { + BB = Worklist.back(); + Worklist.pop_back(); + + // We have now visited this block! If we've already been here, ignore it. + if (!Visited.insert(BB)) continue; + + for (BasicBlock::iterator BBI = BB->begin(), E = BB->end(); BBI != E; ) { + Instruction *Inst = BBI++; + + // DCE instruction if trivially dead. + if (isInstructionTriviallyDead(Inst)) { + ++NumDeadInst; + DEBUG(errs() << "IC: DCE: " << *Inst << '\n'); + Inst->eraseFromParent(); + continue; + } + + // ConstantProp instruction if trivially constant. + if (!Inst->use_empty() && isa(Inst->getOperand(0))) + if (Constant *C = ConstantFoldInstruction(Inst, TD)) { + DEBUG(errs() << "IC: ConstFold to: " << *C << " from: " + << *Inst << '\n'); + Inst->replaceAllUsesWith(C); + ++NumConstProp; + Inst->eraseFromParent(); + continue; + } + + + + if (TD) { + // See if we can constant fold its operands. + for (User::op_iterator i = Inst->op_begin(), e = Inst->op_end(); + i != e; ++i) { + ConstantExpr *CE = dyn_cast(i); + if (CE == 0) continue; + + // If we already folded this constant, don't try again. + if (!FoldedConstants.insert(CE)) + continue; + + Constant *NewC = ConstantFoldConstantExpression(CE, TD); + if (NewC && NewC != CE) { + *i = NewC; + MadeIRChange = true; + } + } + } + + + InstrsForInstCombineWorklist.push_back(Inst); + } + + // Recursively visit successors. If this is a branch or switch on a + // constant, only visit the reachable successor. + TerminatorInst *TI = BB->getTerminator(); + if (BranchInst *BI = dyn_cast(TI)) { + if (BI->isConditional() && isa(BI->getCondition())) { + bool CondVal = cast(BI->getCondition())->getZExtValue(); + BasicBlock *ReachableBB = BI->getSuccessor(!CondVal); + Worklist.push_back(ReachableBB); + continue; + } + } else if (SwitchInst *SI = dyn_cast(TI)) { + if (ConstantInt *Cond = dyn_cast(SI->getCondition())) { + // See if this is an explicit destination. + for (unsigned i = 1, e = SI->getNumSuccessors(); i != e; ++i) + if (SI->getCaseValue(i) == Cond) { + BasicBlock *ReachableBB = SI->getSuccessor(i); + Worklist.push_back(ReachableBB); + continue; + } + + // Otherwise it is the default destination. + Worklist.push_back(SI->getSuccessor(0)); + continue; + } + } + + for (unsigned i = 0, e = TI->getNumSuccessors(); i != e; ++i) + Worklist.push_back(TI->getSuccessor(i)); + } + + // Once we've found all of the instructions to add to instcombine's worklist, + // add them in reverse order. This way instcombine will visit from the top + // of the function down. This jives well with the way that it adds all uses + // of instructions to the worklist after doing a transformation, thus avoiding + // some N^2 behavior in pathological cases. + IC.Worklist.AddInitialGroup(&InstrsForInstCombineWorklist[0], + InstrsForInstCombineWorklist.size()); + + return MadeIRChange; +} + +bool InstCombiner::DoOneIteration(Function &F, unsigned Iteration) { + MadeIRChange = false; + + DEBUG(errs() << "\n\nINSTCOMBINE ITERATION #" << Iteration << " on " + << F.getNameStr() << "\n"); + + { + // Do a depth-first traversal of the function, populate the worklist with + // the reachable instructions. Ignore blocks that are not reachable. Keep + // track of which blocks we visit. + SmallPtrSet Visited; + MadeIRChange |= AddReachableCodeToWorklist(F.begin(), Visited, *this, TD); + + // Do a quick scan over the function. If we find any blocks that are + // unreachable, remove any instructions inside of them. This prevents + // the instcombine code from having to deal with some bad special cases. + for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB) + if (!Visited.count(BB)) { + Instruction *Term = BB->getTerminator(); + while (Term != BB->begin()) { // Remove instrs bottom-up + BasicBlock::iterator I = Term; --I; + + DEBUG(errs() << "IC: DCE: " << *I << '\n'); + // A debug intrinsic shouldn't force another iteration if we weren't + // going to do one without it. + if (!isa(I)) { + ++NumDeadInst; + MadeIRChange = true; + } + + // If I is not void type then replaceAllUsesWith undef. + // This allows ValueHandlers and custom metadata to adjust itself. + if (!I->getType()->isVoidTy()) + I->replaceAllUsesWith(UndefValue::get(I->getType())); + I->eraseFromParent(); + } + } + } + + while (!Worklist.isEmpty()) { + Instruction *I = Worklist.RemoveOne(); + if (I == 0) continue; // skip null values. + + // Check to see if we can DCE the instruction. + if (isInstructionTriviallyDead(I)) { + DEBUG(errs() << "IC: DCE: " << *I << '\n'); + EraseInstFromFunction(*I); + ++NumDeadInst; + MadeIRChange = true; + continue; + } + + // Instruction isn't dead, see if we can constant propagate it. + if (!I->use_empty() && isa(I->getOperand(0))) + if (Constant *C = ConstantFoldInstruction(I, TD)) { + DEBUG(errs() << "IC: ConstFold to: " << *C << " from: " << *I << '\n'); + + // Add operands to the worklist. + ReplaceInstUsesWith(*I, C); + ++NumConstProp; + EraseInstFromFunction(*I); + MadeIRChange = true; + continue; + } + + // See if we can trivially sink this instruction to a successor basic block. + if (I->hasOneUse()) { + BasicBlock *BB = I->getParent(); + Instruction *UserInst = cast(I->use_back()); + BasicBlock *UserParent; + + // Get the block the use occurs in. + if (PHINode *PN = dyn_cast(UserInst)) + UserParent = PN->getIncomingBlock(I->use_begin().getUse()); + else + UserParent = UserInst->getParent(); + + if (UserParent != BB) { + bool UserIsSuccessor = false; + // See if the user is one of our successors. + for (succ_iterator SI = succ_begin(BB), E = succ_end(BB); SI != E; ++SI) + if (*SI == UserParent) { + UserIsSuccessor = true; + break; + } + + // If the user is one of our immediate successors, and if that successor + // only has us as a predecessors (we'd have to split the critical edge + // otherwise), we can keep going. + if (UserIsSuccessor && UserParent->getSinglePredecessor()) + // Okay, the CFG is simple enough, try to sink this instruction. + MadeIRChange |= TryToSinkInstruction(I, UserParent); + } + } + + // Now that we have an instruction, try combining it to simplify it. + Builder->SetInsertPoint(I->getParent(), I); + +#ifndef NDEBUG + std::string OrigI; +#endif + DEBUG(raw_string_ostream SS(OrigI); I->print(SS); OrigI = SS.str();); + DEBUG(errs() << "IC: Visiting: " << OrigI << '\n'); + + if (Instruction *Result = visit(*I)) { + ++NumCombined; + // Should we replace the old instruction with a new one? + if (Result != I) { + DEBUG(errs() << "IC: Old = " << *I << '\n' + << " New = " << *Result << '\n'); + + // Everything uses the new instruction now. + I->replaceAllUsesWith(Result); + + // Push the new instruction and any users onto the worklist. + Worklist.Add(Result); + Worklist.AddUsersToWorkList(*Result); + + // Move the name to the new instruction first. + Result->takeName(I); + + // Insert the new instruction into the basic block... + BasicBlock *InstParent = I->getParent(); + BasicBlock::iterator InsertPos = I; + + if (!isa(Result)) // If combining a PHI, don't insert + while (isa(InsertPos)) // middle of a block of PHIs. + ++InsertPos; + + InstParent->getInstList().insert(InsertPos, Result); + + EraseInstFromFunction(*I); + } else { +#ifndef NDEBUG + DEBUG(errs() << "IC: Mod = " << OrigI << '\n' + << " New = " << *I << '\n'); +#endif + + // If the instruction was modified, it's possible that it is now dead. + // if so, remove it. + if (isInstructionTriviallyDead(I)) { + EraseInstFromFunction(*I); + } else { + Worklist.Add(I); + Worklist.AddUsersToWorkList(*I); + } + } + MadeIRChange = true; + } + } + + Worklist.Zap(); + return MadeIRChange; +} + + +bool InstCombiner::runOnFunction(Function &F) { + MustPreserveLCSSA = mustPreserveAnalysisID(LCSSAID); + Context = &F.getContext(); + TD = getAnalysisIfAvailable(); + + + /// Builder - This is an IRBuilder that automatically inserts new + /// instructions into the worklist when they are created. + IRBuilder + TheBuilder(F.getContext(), TargetFolder(TD), + InstCombineIRInserter(Worklist)); + Builder = &TheBuilder; + + bool EverMadeChange = false; + + // Iterate while there is work to do. + unsigned Iteration = 0; + while (DoOneIteration(F, Iteration++)) + EverMadeChange = true; + + Builder = 0; + return EverMadeChange; +} + +FunctionPass *llvm::createInstructionCombiningPass() { + return new InstCombiner(); +} diff --git a/libclamav/c++/llvm/lib/Transforms/Scalar/JumpThreading.cpp b/libclamav/c++/llvm/lib/Transforms/Scalar/JumpThreading.cpp new file mode 100644 index 000000000..58641135e --- /dev/null +++ b/libclamav/c++/llvm/lib/Transforms/Scalar/JumpThreading.cpp @@ -0,0 +1,1389 @@ +//===- JumpThreading.cpp - Thread control through conditional blocks ------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the Jump Threading pass. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "jump-threading" +#include "llvm/Transforms/Scalar.h" +#include "llvm/IntrinsicInst.h" +#include "llvm/LLVMContext.h" +#include "llvm/Pass.h" +#include "llvm/Analysis/InstructionSimplify.h" +#include "llvm/Analysis/LazyValueInfo.h" +#include "llvm/Transforms/Utils/BasicBlockUtils.h" +#include "llvm/Transforms/Utils/Local.h" +#include "llvm/Transforms/Utils/SSAUpdater.h" +#include "llvm/Target/TargetData.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallSet.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +STATISTIC(NumThreads, "Number of jumps threaded"); +STATISTIC(NumFolds, "Number of terminators folded"); +STATISTIC(NumDupes, "Number of branch blocks duplicated to eliminate phi"); + +static cl::opt +Threshold("jump-threading-threshold", + cl::desc("Max block size to duplicate for jump threading"), + cl::init(6), cl::Hidden); + +// Turn on use of LazyValueInfo. +static cl::opt +EnableLVI("enable-jump-threading-lvi", cl::ReallyHidden); + + + +namespace { + /// This pass performs 'jump threading', which looks at blocks that have + /// multiple predecessors and multiple successors. If one or more of the + /// predecessors of the block can be proven to always jump to one of the + /// successors, we forward the edge from the predecessor to the successor by + /// duplicating the contents of this block. + /// + /// An example of when this can occur is code like this: + /// + /// if () { ... + /// X = 4; + /// } + /// if (X < 3) { + /// + /// In this case, the unconditional branch at the end of the first if can be + /// revectored to the false side of the second if. + /// + class JumpThreading : public FunctionPass { + TargetData *TD; + LazyValueInfo *LVI; +#ifdef NDEBUG + SmallPtrSet LoopHeaders; +#else + SmallSet, 16> LoopHeaders; +#endif + public: + static char ID; // Pass identification + JumpThreading() : FunctionPass(&ID) {} + + bool runOnFunction(Function &F); + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + if (EnableLVI) + AU.addRequired(); + } + + void FindLoopHeaders(Function &F); + bool ProcessBlock(BasicBlock *BB); + bool ThreadEdge(BasicBlock *BB, const SmallVectorImpl &PredBBs, + BasicBlock *SuccBB); + bool DuplicateCondBranchOnPHIIntoPred(BasicBlock *BB, + BasicBlock *PredBB); + + typedef SmallVectorImpl > PredValueInfo; + + bool ComputeValueKnownInPredecessors(Value *V, BasicBlock *BB, + PredValueInfo &Result); + bool ProcessThreadableEdges(Value *Cond, BasicBlock *BB); + + + bool ProcessBranchOnDuplicateCond(BasicBlock *PredBB, BasicBlock *DestBB); + bool ProcessSwitchOnDuplicateCond(BasicBlock *PredBB, BasicBlock *DestBB); + + bool ProcessJumpOnPHI(PHINode *PN); + + bool SimplifyPartiallyRedundantLoad(LoadInst *LI); + }; +} + +char JumpThreading::ID = 0; +static RegisterPass +X("jump-threading", "Jump Threading"); + +// Public interface to the Jump Threading pass +FunctionPass *llvm::createJumpThreadingPass() { return new JumpThreading(); } + +/// runOnFunction - Top level algorithm. +/// +bool JumpThreading::runOnFunction(Function &F) { + DEBUG(errs() << "Jump threading on function '" << F.getName() << "'\n"); + TD = getAnalysisIfAvailable(); + LVI = EnableLVI ? &getAnalysis() : 0; + + FindLoopHeaders(F); + + bool AnotherIteration = true, EverChanged = false; + while (AnotherIteration) { + AnotherIteration = false; + bool Changed = false; + for (Function::iterator I = F.begin(), E = F.end(); I != E;) { + BasicBlock *BB = I; + // Thread all of the branches we can over this block. + while (ProcessBlock(BB)) + Changed = true; + + ++I; + + // If the block is trivially dead, zap it. This eliminates the successor + // edges which simplifies the CFG. + if (pred_begin(BB) == pred_end(BB) && + BB != &BB->getParent()->getEntryBlock()) { + DEBUG(errs() << " JT: Deleting dead block '" << BB->getName() + << "' with terminator: " << *BB->getTerminator() << '\n'); + LoopHeaders.erase(BB); + DeleteDeadBlock(BB); + Changed = true; + } else if (BranchInst *BI = dyn_cast(BB->getTerminator())) { + // Can't thread an unconditional jump, but if the block is "almost + // empty", we can replace uses of it with uses of the successor and make + // this dead. + if (BI->isUnconditional() && + BB != &BB->getParent()->getEntryBlock()) { + BasicBlock::iterator BBI = BB->getFirstNonPHI(); + // Ignore dbg intrinsics. + while (isa(BBI)) + ++BBI; + // If the terminator is the only non-phi instruction, try to nuke it. + if (BBI->isTerminator()) { + // Since TryToSimplifyUncondBranchFromEmptyBlock may delete the + // block, we have to make sure it isn't in the LoopHeaders set. We + // reinsert afterward in the rare case when the block isn't deleted. + bool ErasedFromLoopHeaders = LoopHeaders.erase(BB); + + if (TryToSimplifyUncondBranchFromEmptyBlock(BB)) + Changed = true; + else if (ErasedFromLoopHeaders) + LoopHeaders.insert(BB); + } + } + } + } + AnotherIteration = Changed; + EverChanged |= Changed; + } + + LoopHeaders.clear(); + return EverChanged; +} + +/// getJumpThreadDuplicationCost - Return the cost of duplicating this block to +/// thread across it. +static unsigned getJumpThreadDuplicationCost(const BasicBlock *BB) { + /// Ignore PHI nodes, these will be flattened when duplication happens. + BasicBlock::const_iterator I = BB->getFirstNonPHI(); + + // FIXME: THREADING will delete values that are just used to compute the + // branch, so they shouldn't count against the duplication cost. + + + // Sum up the cost of each instruction until we get to the terminator. Don't + // include the terminator because the copy won't include it. + unsigned Size = 0; + for (; !isa(I); ++I) { + // Debugger intrinsics don't incur code size. + if (isa(I)) continue; + + // If this is a pointer->pointer bitcast, it is free. + if (isa(I) && isa(I->getType())) + continue; + + // All other instructions count for at least one unit. + ++Size; + + // Calls are more expensive. If they are non-intrinsic calls, we model them + // as having cost of 4. If they are a non-vector intrinsic, we model them + // as having cost of 2 total, and if they are a vector intrinsic, we model + // them as having cost 1. + if (const CallInst *CI = dyn_cast(I)) { + if (!isa(CI)) + Size += 3; + else if (!isa(CI->getType())) + Size += 1; + } + } + + // Threading through a switch statement is particularly profitable. If this + // block ends in a switch, decrease its cost to make it more likely to happen. + if (isa(I)) + Size = Size > 6 ? Size-6 : 0; + + return Size; +} + +/// FindLoopHeaders - We do not want jump threading to turn proper loop +/// structures into irreducible loops. Doing this breaks up the loop nesting +/// hierarchy and pessimizes later transformations. To prevent this from +/// happening, we first have to find the loop headers. Here we approximate this +/// by finding targets of backedges in the CFG. +/// +/// Note that there definitely are cases when we want to allow threading of +/// edges across a loop header. For example, threading a jump from outside the +/// loop (the preheader) to an exit block of the loop is definitely profitable. +/// It is also almost always profitable to thread backedges from within the loop +/// to exit blocks, and is often profitable to thread backedges to other blocks +/// within the loop (forming a nested loop). This simple analysis is not rich +/// enough to track all of these properties and keep it up-to-date as the CFG +/// mutates, so we don't allow any of these transformations. +/// +void JumpThreading::FindLoopHeaders(Function &F) { + SmallVector, 32> Edges; + FindFunctionBackedges(F, Edges); + + for (unsigned i = 0, e = Edges.size(); i != e; ++i) + LoopHeaders.insert(const_cast(Edges[i].second)); +} + +/// ComputeValueKnownInPredecessors - Given a basic block BB and a value V, see +/// if we can infer that the value is a known ConstantInt in any of our +/// predecessors. If so, return the known list of value and pred BB in the +/// result vector. If a value is known to be undef, it is returned as null. +/// +/// This returns true if there were any known values. +/// +bool JumpThreading:: +ComputeValueKnownInPredecessors(Value *V, BasicBlock *BB,PredValueInfo &Result){ + // If V is a constantint, then it is known in all predecessors. + if (isa(V) || isa(V)) { + ConstantInt *CI = dyn_cast(V); + + for (pred_iterator PI = pred_begin(BB), E = pred_end(BB); PI != E; ++PI) + Result.push_back(std::make_pair(CI, *PI)); + return true; + } + + // If V is a non-instruction value, or an instruction in a different block, + // then it can't be derived from a PHI. + Instruction *I = dyn_cast(V); + if (I == 0 || I->getParent() != BB) { + + // Okay, if this is a live-in value, see if it has a known value at the end + // of any of our predecessors. + // + // FIXME: This should be an edge property, not a block end property. + /// TODO: Per PR2563, we could infer value range information about a + /// predecessor based on its terminator. + // + if (LVI) { + // FIXME: change this to use the more-rich 'getPredicateOnEdge' method if + // "I" is a non-local compare-with-a-constant instruction. This would be + // able to handle value inequalities better, for example if the compare is + // "X < 4" and "X < 3" is known true but "X < 4" itself is not available. + // Perhaps getConstantOnEdge should be smart enough to do this? + + for (pred_iterator PI = pred_begin(BB), E = pred_end(BB); PI != E; ++PI) { + // If the value is known by LazyValueInfo to be a constant in a + // predecessor, use that information to try to thread this block. + Constant *PredCst = LVI->getConstantOnEdge(V, *PI, BB); + if (PredCst == 0 || + (!isa(PredCst) && !isa(PredCst))) + continue; + + Result.push_back(std::make_pair(dyn_cast(PredCst), *PI)); + } + + return !Result.empty(); + } + + return false; + } + + /// If I is a PHI node, then we know the incoming values for any constants. + if (PHINode *PN = dyn_cast(I)) { + for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) { + Value *InVal = PN->getIncomingValue(i); + if (isa(InVal) || isa(InVal)) { + ConstantInt *CI = dyn_cast(InVal); + Result.push_back(std::make_pair(CI, PN->getIncomingBlock(i))); + } + } + return !Result.empty(); + } + + SmallVector, 8> LHSVals, RHSVals; + + // Handle some boolean conditions. + if (I->getType()->getPrimitiveSizeInBits() == 1) { + // X | true -> true + // X & false -> false + if (I->getOpcode() == Instruction::Or || + I->getOpcode() == Instruction::And) { + ComputeValueKnownInPredecessors(I->getOperand(0), BB, LHSVals); + ComputeValueKnownInPredecessors(I->getOperand(1), BB, RHSVals); + + if (LHSVals.empty() && RHSVals.empty()) + return false; + + ConstantInt *InterestingVal; + if (I->getOpcode() == Instruction::Or) + InterestingVal = ConstantInt::getTrue(I->getContext()); + else + InterestingVal = ConstantInt::getFalse(I->getContext()); + + // Scan for the sentinel. + for (unsigned i = 0, e = LHSVals.size(); i != e; ++i) + if (LHSVals[i].first == InterestingVal || LHSVals[i].first == 0) + Result.push_back(LHSVals[i]); + for (unsigned i = 0, e = RHSVals.size(); i != e; ++i) + if (RHSVals[i].first == InterestingVal || RHSVals[i].first == 0) + Result.push_back(RHSVals[i]); + return !Result.empty(); + } + + // Handle the NOT form of XOR. + if (I->getOpcode() == Instruction::Xor && + isa(I->getOperand(1)) && + cast(I->getOperand(1))->isOne()) { + ComputeValueKnownInPredecessors(I->getOperand(0), BB, Result); + if (Result.empty()) + return false; + + // Invert the known values. + for (unsigned i = 0, e = Result.size(); i != e; ++i) + if (Result[i].first) + Result[i].first = + cast(ConstantExpr::getNot(Result[i].first)); + return true; + } + } + + // Handle compare with phi operand, where the PHI is defined in this block. + if (CmpInst *Cmp = dyn_cast(I)) { + PHINode *PN = dyn_cast(Cmp->getOperand(0)); + if (PN && PN->getParent() == BB) { + // We can do this simplification if any comparisons fold to true or false. + // See if any do. + for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) { + BasicBlock *PredBB = PN->getIncomingBlock(i); + Value *LHS = PN->getIncomingValue(i); + Value *RHS = Cmp->getOperand(1)->DoPHITranslation(BB, PredBB); + + Value *Res = SimplifyCmpInst(Cmp->getPredicate(), LHS, RHS, TD); + if (Res == 0) { + if (!LVI || !isa(RHS)) + continue; + + LazyValueInfo::Tristate + ResT = LVI->getPredicateOnEdge(Cmp->getPredicate(), LHS, + cast(RHS), PredBB, BB); + if (ResT == LazyValueInfo::Unknown) + continue; + Res = ConstantInt::get(Type::getInt1Ty(LHS->getContext()), ResT); + } + + if (isa(Res)) + Result.push_back(std::make_pair((ConstantInt*)0, PredBB)); + else if (ConstantInt *CI = dyn_cast(Res)) + Result.push_back(std::make_pair(CI, PredBB)); + } + + return !Result.empty(); + } + + + // If comparing a live-in value against a constant, see if we know the + // live-in value on any predecessors. + if (LVI && isa(Cmp->getOperand(1)) && + Cmp->getType()->isInteger() && // Not vector compare. + (!isa(Cmp->getOperand(0)) || + cast(Cmp->getOperand(0))->getParent() != BB)) { + Constant *RHSCst = cast(Cmp->getOperand(1)); + + for (pred_iterator PI = pred_begin(BB), E = pred_end(BB); PI != E; ++PI) { + // If the value is known by LazyValueInfo to be a constant in a + // predecessor, use that information to try to thread this block. + LazyValueInfo::Tristate + Res = LVI->getPredicateOnEdge(Cmp->getPredicate(), Cmp->getOperand(0), + RHSCst, *PI, BB); + if (Res == LazyValueInfo::Unknown) + continue; + + Constant *ResC = ConstantInt::get(Cmp->getType(), Res); + Result.push_back(std::make_pair(cast(ResC), *PI)); + } + + return !Result.empty(); + } + } + return false; +} + + + +/// GetBestDestForBranchOnUndef - If we determine that the specified block ends +/// in an undefined jump, decide which block is best to revector to. +/// +/// Since we can pick an arbitrary destination, we pick the successor with the +/// fewest predecessors. This should reduce the in-degree of the others. +/// +static unsigned GetBestDestForJumpOnUndef(BasicBlock *BB) { + TerminatorInst *BBTerm = BB->getTerminator(); + unsigned MinSucc = 0; + BasicBlock *TestBB = BBTerm->getSuccessor(MinSucc); + // Compute the successor with the minimum number of predecessors. + unsigned MinNumPreds = std::distance(pred_begin(TestBB), pred_end(TestBB)); + for (unsigned i = 1, e = BBTerm->getNumSuccessors(); i != e; ++i) { + TestBB = BBTerm->getSuccessor(i); + unsigned NumPreds = std::distance(pred_begin(TestBB), pred_end(TestBB)); + if (NumPreds < MinNumPreds) + MinSucc = i; + } + + return MinSucc; +} + +/// ProcessBlock - If there are any predecessors whose control can be threaded +/// through to a successor, transform them now. +bool JumpThreading::ProcessBlock(BasicBlock *BB) { + // If this block has a single predecessor, and if that pred has a single + // successor, merge the blocks. This encourages recursive jump threading + // because now the condition in this block can be threaded through + // predecessors of our predecessor block. + if (BasicBlock *SinglePred = BB->getSinglePredecessor()) { + if (SinglePred->getTerminator()->getNumSuccessors() == 1 && + SinglePred != BB) { + // If SinglePred was a loop header, BB becomes one. + if (LoopHeaders.erase(SinglePred)) + LoopHeaders.insert(BB); + + // Remember if SinglePred was the entry block of the function. If so, we + // will need to move BB back to the entry position. + bool isEntry = SinglePred == &SinglePred->getParent()->getEntryBlock(); + MergeBasicBlockIntoOnlyPred(BB); + + if (isEntry && BB != &BB->getParent()->getEntryBlock()) + BB->moveBefore(&BB->getParent()->getEntryBlock()); + return true; + } + } + + // Look to see if the terminator is a branch of switch, if not we can't thread + // it. + Value *Condition; + if (BranchInst *BI = dyn_cast(BB->getTerminator())) { + // Can't thread an unconditional jump. + if (BI->isUnconditional()) return false; + Condition = BI->getCondition(); + } else if (SwitchInst *SI = dyn_cast(BB->getTerminator())) + Condition = SI->getCondition(); + else + return false; // Must be an invoke. + + // If the terminator of this block is branching on a constant, simplify the + // terminator to an unconditional branch. This can occur due to threading in + // other blocks. + if (isa(Condition)) { + DEBUG(errs() << " In block '" << BB->getName() + << "' folding terminator: " << *BB->getTerminator() << '\n'); + ++NumFolds; + ConstantFoldTerminator(BB); + return true; + } + + // If the terminator is branching on an undef, we can pick any of the + // successors to branch to. Let GetBestDestForJumpOnUndef decide. + if (isa(Condition)) { + unsigned BestSucc = GetBestDestForJumpOnUndef(BB); + + // Fold the branch/switch. + TerminatorInst *BBTerm = BB->getTerminator(); + for (unsigned i = 0, e = BBTerm->getNumSuccessors(); i != e; ++i) { + if (i == BestSucc) continue; + RemovePredecessorAndSimplify(BBTerm->getSuccessor(i), BB, TD); + } + + DEBUG(errs() << " In block '" << BB->getName() + << "' folding undef terminator: " << *BBTerm << '\n'); + BranchInst::Create(BBTerm->getSuccessor(BestSucc), BBTerm); + BBTerm->eraseFromParent(); + return true; + } + + Instruction *CondInst = dyn_cast(Condition); + + // If the condition is an instruction defined in another block, see if a + // predecessor has the same condition: + // br COND, BBX, BBY + // BBX: + // br COND, BBZ, BBW + if (!LVI && + !Condition->hasOneUse() && // Multiple uses. + (CondInst == 0 || CondInst->getParent() != BB)) { // Non-local definition. + pred_iterator PI = pred_begin(BB), E = pred_end(BB); + if (isa(BB->getTerminator())) { + for (; PI != E; ++PI) + if (BranchInst *PBI = dyn_cast((*PI)->getTerminator())) + if (PBI->isConditional() && PBI->getCondition() == Condition && + ProcessBranchOnDuplicateCond(*PI, BB)) + return true; + } else { + assert(isa(BB->getTerminator()) && "Unknown jump terminator"); + for (; PI != E; ++PI) + if (SwitchInst *PSI = dyn_cast((*PI)->getTerminator())) + if (PSI->getCondition() == Condition && + ProcessSwitchOnDuplicateCond(*PI, BB)) + return true; + } + } + + // All the rest of our checks depend on the condition being an instruction. + if (CondInst == 0) { + // FIXME: Unify this with code below. + if (LVI && ProcessThreadableEdges(Condition, BB)) + return true; + return false; + } + + + // See if this is a phi node in the current block. + if (PHINode *PN = dyn_cast(CondInst)) + if (PN->getParent() == BB) + return ProcessJumpOnPHI(PN); + + if (CmpInst *CondCmp = dyn_cast(CondInst)) { + if (!LVI && + (!isa(CondCmp->getOperand(0)) || + cast(CondCmp->getOperand(0))->getParent() != BB)) { + // If we have a comparison, loop over the predecessors to see if there is + // a condition with a lexically identical value. + pred_iterator PI = pred_begin(BB), E = pred_end(BB); + for (; PI != E; ++PI) + if (BranchInst *PBI = dyn_cast((*PI)->getTerminator())) + if (PBI->isConditional() && *PI != BB) { + if (CmpInst *CI = dyn_cast(PBI->getCondition())) { + if (CI->getOperand(0) == CondCmp->getOperand(0) && + CI->getOperand(1) == CondCmp->getOperand(1) && + CI->getPredicate() == CondCmp->getPredicate()) { + // TODO: Could handle things like (x != 4) --> (x == 17) + if (ProcessBranchOnDuplicateCond(*PI, BB)) + return true; + } + } + } + } + } + + // Check for some cases that are worth simplifying. Right now we want to look + // for loads that are used by a switch or by the condition for the branch. If + // we see one, check to see if it's partially redundant. If so, insert a PHI + // which can then be used to thread the values. + // + // This is particularly important because reg2mem inserts loads and stores all + // over the place, and this blocks jump threading if we don't zap them. + Value *SimplifyValue = CondInst; + if (CmpInst *CondCmp = dyn_cast(SimplifyValue)) + if (isa(CondCmp->getOperand(1))) + SimplifyValue = CondCmp->getOperand(0); + + // TODO: There are other places where load PRE would be profitable, such as + // more complex comparisons. + if (LoadInst *LI = dyn_cast(SimplifyValue)) + if (SimplifyPartiallyRedundantLoad(LI)) + return true; + + + // Handle a variety of cases where we are branching on something derived from + // a PHI node in the current block. If we can prove that any predecessors + // compute a predictable value based on a PHI node, thread those predecessors. + // + if (ProcessThreadableEdges(CondInst, BB)) + return true; + + + // TODO: If we have: "br (X > 0)" and we have a predecessor where we know + // "(X == 4)" thread through this block. + + return false; +} + +/// ProcessBranchOnDuplicateCond - We found a block and a predecessor of that +/// block that jump on exactly the same condition. This means that we almost +/// always know the direction of the edge in the DESTBB: +/// PREDBB: +/// br COND, DESTBB, BBY +/// DESTBB: +/// br COND, BBZ, BBW +/// +/// If DESTBB has multiple predecessors, we can't just constant fold the branch +/// in DESTBB, we have to thread over it. +bool JumpThreading::ProcessBranchOnDuplicateCond(BasicBlock *PredBB, + BasicBlock *BB) { + BranchInst *PredBI = cast(PredBB->getTerminator()); + + // If both successors of PredBB go to DESTBB, we don't know anything. We can + // fold the branch to an unconditional one, which allows other recursive + // simplifications. + bool BranchDir; + if (PredBI->getSuccessor(1) != BB) + BranchDir = true; + else if (PredBI->getSuccessor(0) != BB) + BranchDir = false; + else { + DEBUG(errs() << " In block '" << PredBB->getName() + << "' folding terminator: " << *PredBB->getTerminator() << '\n'); + ++NumFolds; + ConstantFoldTerminator(PredBB); + return true; + } + + BranchInst *DestBI = cast(BB->getTerminator()); + + // If the dest block has one predecessor, just fix the branch condition to a + // constant and fold it. + if (BB->getSinglePredecessor()) { + DEBUG(errs() << " In block '" << BB->getName() + << "' folding condition to '" << BranchDir << "': " + << *BB->getTerminator() << '\n'); + ++NumFolds; + Value *OldCond = DestBI->getCondition(); + DestBI->setCondition(ConstantInt::get(Type::getInt1Ty(BB->getContext()), + BranchDir)); + ConstantFoldTerminator(BB); + RecursivelyDeleteTriviallyDeadInstructions(OldCond); + return true; + } + + + // Next, figure out which successor we are threading to. + BasicBlock *SuccBB = DestBI->getSuccessor(!BranchDir); + + SmallVector Preds; + Preds.push_back(PredBB); + + // Ok, try to thread it! + return ThreadEdge(BB, Preds, SuccBB); +} + +/// ProcessSwitchOnDuplicateCond - We found a block and a predecessor of that +/// block that switch on exactly the same condition. This means that we almost +/// always know the direction of the edge in the DESTBB: +/// PREDBB: +/// switch COND [... DESTBB, BBY ... ] +/// DESTBB: +/// switch COND [... BBZ, BBW ] +/// +/// Optimizing switches like this is very important, because simplifycfg builds +/// switches out of repeated 'if' conditions. +bool JumpThreading::ProcessSwitchOnDuplicateCond(BasicBlock *PredBB, + BasicBlock *DestBB) { + // Can't thread edge to self. + if (PredBB == DestBB) + return false; + + SwitchInst *PredSI = cast(PredBB->getTerminator()); + SwitchInst *DestSI = cast(DestBB->getTerminator()); + + // There are a variety of optimizations that we can potentially do on these + // blocks: we order them from most to least preferable. + + // If DESTBB *just* contains the switch, then we can forward edges from PREDBB + // directly to their destination. This does not introduce *any* code size + // growth. Skip debug info first. + BasicBlock::iterator BBI = DestBB->begin(); + while (isa(BBI)) + BBI++; + + // FIXME: Thread if it just contains a PHI. + if (isa(BBI)) { + bool MadeChange = false; + // Ignore the default edge for now. + for (unsigned i = 1, e = DestSI->getNumSuccessors(); i != e; ++i) { + ConstantInt *DestVal = DestSI->getCaseValue(i); + BasicBlock *DestSucc = DestSI->getSuccessor(i); + + // Okay, DestSI has a case for 'DestVal' that goes to 'DestSucc'. See if + // PredSI has an explicit case for it. If so, forward. If it is covered + // by the default case, we can't update PredSI. + unsigned PredCase = PredSI->findCaseValue(DestVal); + if (PredCase == 0) continue; + + // If PredSI doesn't go to DestBB on this value, then it won't reach the + // case on this condition. + if (PredSI->getSuccessor(PredCase) != DestBB && + DestSI->getSuccessor(i) != DestBB) + continue; + + // Otherwise, we're safe to make the change. Make sure that the edge from + // DestSI to DestSucc is not critical and has no PHI nodes. + DEBUG(errs() << "FORWARDING EDGE " << *DestVal << " FROM: " << *PredSI); + DEBUG(errs() << "THROUGH: " << *DestSI); + + // If the destination has PHI nodes, just split the edge for updating + // simplicity. + if (isa(DestSucc->begin()) && !DestSucc->getSinglePredecessor()){ + SplitCriticalEdge(DestSI, i, this); + DestSucc = DestSI->getSuccessor(i); + } + FoldSingleEntryPHINodes(DestSucc); + PredSI->setSuccessor(PredCase, DestSucc); + MadeChange = true; + } + + if (MadeChange) + return true; + } + + return false; +} + + +/// SimplifyPartiallyRedundantLoad - If LI is an obviously partially redundant +/// load instruction, eliminate it by replacing it with a PHI node. This is an +/// important optimization that encourages jump threading, and needs to be run +/// interlaced with other jump threading tasks. +bool JumpThreading::SimplifyPartiallyRedundantLoad(LoadInst *LI) { + // Don't hack volatile loads. + if (LI->isVolatile()) return false; + + // If the load is defined in a block with exactly one predecessor, it can't be + // partially redundant. + BasicBlock *LoadBB = LI->getParent(); + if (LoadBB->getSinglePredecessor()) + return false; + + Value *LoadedPtr = LI->getOperand(0); + + // If the loaded operand is defined in the LoadBB, it can't be available. + // TODO: Could do simple PHI translation, that would be fun :) + if (Instruction *PtrOp = dyn_cast(LoadedPtr)) + if (PtrOp->getParent() == LoadBB) + return false; + + // Scan a few instructions up from the load, to see if it is obviously live at + // the entry to its block. + BasicBlock::iterator BBIt = LI; + + if (Value *AvailableVal = + FindAvailableLoadedValue(LoadedPtr, LoadBB, BBIt, 6)) { + // If the value if the load is locally available within the block, just use + // it. This frequently occurs for reg2mem'd allocas. + //cerr << "LOAD ELIMINATED:\n" << *BBIt << *LI << "\n"; + + // If the returned value is the load itself, replace with an undef. This can + // only happen in dead loops. + if (AvailableVal == LI) AvailableVal = UndefValue::get(LI->getType()); + LI->replaceAllUsesWith(AvailableVal); + LI->eraseFromParent(); + return true; + } + + // Otherwise, if we scanned the whole block and got to the top of the block, + // we know the block is locally transparent to the load. If not, something + // might clobber its value. + if (BBIt != LoadBB->begin()) + return false; + + + SmallPtrSet PredsScanned; + typedef SmallVector, 8> AvailablePredsTy; + AvailablePredsTy AvailablePreds; + BasicBlock *OneUnavailablePred = 0; + + // If we got here, the loaded value is transparent through to the start of the + // block. Check to see if it is available in any of the predecessor blocks. + for (pred_iterator PI = pred_begin(LoadBB), PE = pred_end(LoadBB); + PI != PE; ++PI) { + BasicBlock *PredBB = *PI; + + // If we already scanned this predecessor, skip it. + if (!PredsScanned.insert(PredBB)) + continue; + + // Scan the predecessor to see if the value is available in the pred. + BBIt = PredBB->end(); + Value *PredAvailable = FindAvailableLoadedValue(LoadedPtr, PredBB, BBIt, 6); + if (!PredAvailable) { + OneUnavailablePred = PredBB; + continue; + } + + // If so, this load is partially redundant. Remember this info so that we + // can create a PHI node. + AvailablePreds.push_back(std::make_pair(PredBB, PredAvailable)); + } + + // If the loaded value isn't available in any predecessor, it isn't partially + // redundant. + if (AvailablePreds.empty()) return false; + + // Okay, the loaded value is available in at least one (and maybe all!) + // predecessors. If the value is unavailable in more than one unique + // predecessor, we want to insert a merge block for those common predecessors. + // This ensures that we only have to insert one reload, thus not increasing + // code size. + BasicBlock *UnavailablePred = 0; + + // If there is exactly one predecessor where the value is unavailable, the + // already computed 'OneUnavailablePred' block is it. If it ends in an + // unconditional branch, we know that it isn't a critical edge. + if (PredsScanned.size() == AvailablePreds.size()+1 && + OneUnavailablePred->getTerminator()->getNumSuccessors() == 1) { + UnavailablePred = OneUnavailablePred; + } else if (PredsScanned.size() != AvailablePreds.size()) { + // Otherwise, we had multiple unavailable predecessors or we had a critical + // edge from the one. + SmallVector PredsToSplit; + SmallPtrSet AvailablePredSet; + + for (unsigned i = 0, e = AvailablePreds.size(); i != e; ++i) + AvailablePredSet.insert(AvailablePreds[i].first); + + // Add all the unavailable predecessors to the PredsToSplit list. + for (pred_iterator PI = pred_begin(LoadBB), PE = pred_end(LoadBB); + PI != PE; ++PI) + if (!AvailablePredSet.count(*PI)) + PredsToSplit.push_back(*PI); + + // Split them out to their own block. + UnavailablePred = + SplitBlockPredecessors(LoadBB, &PredsToSplit[0], PredsToSplit.size(), + "thread-pre-split", this); + } + + // If the value isn't available in all predecessors, then there will be + // exactly one where it isn't available. Insert a load on that edge and add + // it to the AvailablePreds list. + if (UnavailablePred) { + assert(UnavailablePred->getTerminator()->getNumSuccessors() == 1 && + "Can't handle critical edge here!"); + Value *NewVal = new LoadInst(LoadedPtr, LI->getName()+".pr", false, + LI->getAlignment(), + UnavailablePred->getTerminator()); + AvailablePreds.push_back(std::make_pair(UnavailablePred, NewVal)); + } + + // Now we know that each predecessor of this block has a value in + // AvailablePreds, sort them for efficient access as we're walking the preds. + array_pod_sort(AvailablePreds.begin(), AvailablePreds.end()); + + // Create a PHI node at the start of the block for the PRE'd load value. + PHINode *PN = PHINode::Create(LI->getType(), "", LoadBB->begin()); + PN->takeName(LI); + + // Insert new entries into the PHI for each predecessor. A single block may + // have multiple entries here. + for (pred_iterator PI = pred_begin(LoadBB), E = pred_end(LoadBB); PI != E; + ++PI) { + AvailablePredsTy::iterator I = + std::lower_bound(AvailablePreds.begin(), AvailablePreds.end(), + std::make_pair(*PI, (Value*)0)); + + assert(I != AvailablePreds.end() && I->first == *PI && + "Didn't find entry for predecessor!"); + + PN->addIncoming(I->second, I->first); + } + + //cerr << "PRE: " << *LI << *PN << "\n"; + + LI->replaceAllUsesWith(PN); + LI->eraseFromParent(); + + return true; +} + +/// FindMostPopularDest - The specified list contains multiple possible +/// threadable destinations. Pick the one that occurs the most frequently in +/// the list. +static BasicBlock * +FindMostPopularDest(BasicBlock *BB, + const SmallVectorImpl > &PredToDestList) { + assert(!PredToDestList.empty()); + + // Determine popularity. If there are multiple possible destinations, we + // explicitly choose to ignore 'undef' destinations. We prefer to thread + // blocks with known and real destinations to threading undef. We'll handle + // them later if interesting. + DenseMap DestPopularity; + for (unsigned i = 0, e = PredToDestList.size(); i != e; ++i) + if (PredToDestList[i].second) + DestPopularity[PredToDestList[i].second]++; + + // Find the most popular dest. + DenseMap::iterator DPI = DestPopularity.begin(); + BasicBlock *MostPopularDest = DPI->first; + unsigned Popularity = DPI->second; + SmallVector SamePopularity; + + for (++DPI; DPI != DestPopularity.end(); ++DPI) { + // If the popularity of this entry isn't higher than the popularity we've + // seen so far, ignore it. + if (DPI->second < Popularity) + ; // ignore. + else if (DPI->second == Popularity) { + // If it is the same as what we've seen so far, keep track of it. + SamePopularity.push_back(DPI->first); + } else { + // If it is more popular, remember it. + SamePopularity.clear(); + MostPopularDest = DPI->first; + Popularity = DPI->second; + } + } + + // Okay, now we know the most popular destination. If there is more than + // destination, we need to determine one. This is arbitrary, but we need + // to make a deterministic decision. Pick the first one that appears in the + // successor list. + if (!SamePopularity.empty()) { + SamePopularity.push_back(MostPopularDest); + TerminatorInst *TI = BB->getTerminator(); + for (unsigned i = 0; ; ++i) { + assert(i != TI->getNumSuccessors() && "Didn't find any successor!"); + + if (std::find(SamePopularity.begin(), SamePopularity.end(), + TI->getSuccessor(i)) == SamePopularity.end()) + continue; + + MostPopularDest = TI->getSuccessor(i); + break; + } + } + + // Okay, we have finally picked the most popular destination. + return MostPopularDest; +} + +bool JumpThreading::ProcessThreadableEdges(Value *Cond, BasicBlock *BB) { + // If threading this would thread across a loop header, don't even try to + // thread the edge. + if (LoopHeaders.count(BB)) + return false; + + SmallVector, 8> PredValues; + if (!ComputeValueKnownInPredecessors(Cond, BB, PredValues)) + return false; + assert(!PredValues.empty() && + "ComputeValueKnownInPredecessors returned true with no values"); + + DEBUG(errs() << "IN BB: " << *BB; + for (unsigned i = 0, e = PredValues.size(); i != e; ++i) { + errs() << " BB '" << BB->getName() << "': FOUND condition = "; + if (PredValues[i].first) + errs() << *PredValues[i].first; + else + errs() << "UNDEF"; + errs() << " for pred '" << PredValues[i].second->getName() + << "'.\n"; + }); + + // Decide what we want to thread through. Convert our list of known values to + // a list of known destinations for each pred. This also discards duplicate + // predecessors and keeps track of the undefined inputs (which are represented + // as a null dest in the PredToDestList). + SmallPtrSet SeenPreds; + SmallVector, 16> PredToDestList; + + BasicBlock *OnlyDest = 0; + BasicBlock *MultipleDestSentinel = (BasicBlock*)(intptr_t)~0ULL; + + for (unsigned i = 0, e = PredValues.size(); i != e; ++i) { + BasicBlock *Pred = PredValues[i].second; + if (!SeenPreds.insert(Pred)) + continue; // Duplicate predecessor entry. + + // If the predecessor ends with an indirect goto, we can't change its + // destination. + if (isa(Pred->getTerminator())) + continue; + + ConstantInt *Val = PredValues[i].first; + + BasicBlock *DestBB; + if (Val == 0) // Undef. + DestBB = 0; + else if (BranchInst *BI = dyn_cast(BB->getTerminator())) + DestBB = BI->getSuccessor(Val->isZero()); + else { + SwitchInst *SI = cast(BB->getTerminator()); + DestBB = SI->getSuccessor(SI->findCaseValue(Val)); + } + + // If we have exactly one destination, remember it for efficiency below. + if (i == 0) + OnlyDest = DestBB; + else if (OnlyDest != DestBB) + OnlyDest = MultipleDestSentinel; + + PredToDestList.push_back(std::make_pair(Pred, DestBB)); + } + + // If all edges were unthreadable, we fail. + if (PredToDestList.empty()) + return false; + + // Determine which is the most common successor. If we have many inputs and + // this block is a switch, we want to start by threading the batch that goes + // to the most popular destination first. If we only know about one + // threadable destination (the common case) we can avoid this. + BasicBlock *MostPopularDest = OnlyDest; + + if (MostPopularDest == MultipleDestSentinel) + MostPopularDest = FindMostPopularDest(BB, PredToDestList); + + // Now that we know what the most popular destination is, factor all + // predecessors that will jump to it into a single predecessor. + SmallVector PredsToFactor; + for (unsigned i = 0, e = PredToDestList.size(); i != e; ++i) + if (PredToDestList[i].second == MostPopularDest) { + BasicBlock *Pred = PredToDestList[i].first; + + // This predecessor may be a switch or something else that has multiple + // edges to the block. Factor each of these edges by listing them + // according to # occurrences in PredsToFactor. + TerminatorInst *PredTI = Pred->getTerminator(); + for (unsigned i = 0, e = PredTI->getNumSuccessors(); i != e; ++i) + if (PredTI->getSuccessor(i) == BB) + PredsToFactor.push_back(Pred); + } + + // If the threadable edges are branching on an undefined value, we get to pick + // the destination that these predecessors should get to. + if (MostPopularDest == 0) + MostPopularDest = BB->getTerminator()-> + getSuccessor(GetBestDestForJumpOnUndef(BB)); + + // Ok, try to thread it! + return ThreadEdge(BB, PredsToFactor, MostPopularDest); +} + +/// ProcessJumpOnPHI - We have a conditional branch or switch on a PHI node in +/// the current block. See if there are any simplifications we can do based on +/// inputs to the phi node. +/// +bool JumpThreading::ProcessJumpOnPHI(PHINode *PN) { + BasicBlock *BB = PN->getParent(); + + // If any of the predecessor blocks end in an unconditional branch, we can + // *duplicate* the jump into that block in order to further encourage jump + // threading and to eliminate cases where we have branch on a phi of an icmp + // (branch on icmp is much better). + + // We don't want to do this tranformation for switches, because we don't + // really want to duplicate a switch. + if (isa(BB->getTerminator())) + return false; + + // Look for unconditional branch predecessors. + for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) { + BasicBlock *PredBB = PN->getIncomingBlock(i); + if (BranchInst *PredBr = dyn_cast(PredBB->getTerminator())) + if (PredBr->isUnconditional() && + // Try to duplicate BB into PredBB. + DuplicateCondBranchOnPHIIntoPred(BB, PredBB)) + return true; + } + + return false; +} + + +/// AddPHINodeEntriesForMappedBlock - We're adding 'NewPred' as a new +/// predecessor to the PHIBB block. If it has PHI nodes, add entries for +/// NewPred using the entries from OldPred (suitably mapped). +static void AddPHINodeEntriesForMappedBlock(BasicBlock *PHIBB, + BasicBlock *OldPred, + BasicBlock *NewPred, + DenseMap &ValueMap) { + for (BasicBlock::iterator PNI = PHIBB->begin(); + PHINode *PN = dyn_cast(PNI); ++PNI) { + // Ok, we have a PHI node. Figure out what the incoming value was for the + // DestBlock. + Value *IV = PN->getIncomingValueForBlock(OldPred); + + // Remap the value if necessary. + if (Instruction *Inst = dyn_cast(IV)) { + DenseMap::iterator I = ValueMap.find(Inst); + if (I != ValueMap.end()) + IV = I->second; + } + + PN->addIncoming(IV, NewPred); + } +} + +/// ThreadEdge - We have decided that it is safe and profitable to factor the +/// blocks in PredBBs to one predecessor, then thread an edge from it to SuccBB +/// across BB. Transform the IR to reflect this change. +bool JumpThreading::ThreadEdge(BasicBlock *BB, + const SmallVectorImpl &PredBBs, + BasicBlock *SuccBB) { + // If threading to the same block as we come from, we would infinite loop. + if (SuccBB == BB) { + DEBUG(errs() << " Not threading across BB '" << BB->getName() + << "' - would thread to self!\n"); + return false; + } + + // If threading this would thread across a loop header, don't thread the edge. + // See the comments above FindLoopHeaders for justifications and caveats. + if (LoopHeaders.count(BB)) { + DEBUG(errs() << " Not threading across loop header BB '" << BB->getName() + << "' to dest BB '" << SuccBB->getName() + << "' - it might create an irreducible loop!\n"); + return false; + } + + unsigned JumpThreadCost = getJumpThreadDuplicationCost(BB); + if (JumpThreadCost > Threshold) { + DEBUG(errs() << " Not threading BB '" << BB->getName() + << "' - Cost is too high: " << JumpThreadCost << "\n"); + return false; + } + + // And finally, do it! Start by factoring the predecessors is needed. + BasicBlock *PredBB; + if (PredBBs.size() == 1) + PredBB = PredBBs[0]; + else { + DEBUG(errs() << " Factoring out " << PredBBs.size() + << " common predecessors.\n"); + PredBB = SplitBlockPredecessors(BB, &PredBBs[0], PredBBs.size(), + ".thr_comm", this); + } + + // And finally, do it! + DEBUG(errs() << " Threading edge from '" << PredBB->getName() << "' to '" + << SuccBB->getName() << "' with cost: " << JumpThreadCost + << ", across block:\n " + << *BB << "\n"); + + // We are going to have to map operands from the original BB block to the new + // copy of the block 'NewBB'. If there are PHI nodes in BB, evaluate them to + // account for entry from PredBB. + DenseMap ValueMapping; + + BasicBlock *NewBB = BasicBlock::Create(BB->getContext(), + BB->getName()+".thread", + BB->getParent(), BB); + NewBB->moveAfter(PredBB); + + BasicBlock::iterator BI = BB->begin(); + for (; PHINode *PN = dyn_cast(BI); ++BI) + ValueMapping[PN] = PN->getIncomingValueForBlock(PredBB); + + // Clone the non-phi instructions of BB into NewBB, keeping track of the + // mapping and using it to remap operands in the cloned instructions. + for (; !isa(BI); ++BI) { + Instruction *New = BI->clone(); + New->setName(BI->getName()); + NewBB->getInstList().push_back(New); + ValueMapping[BI] = New; + + // Remap operands to patch up intra-block references. + for (unsigned i = 0, e = New->getNumOperands(); i != e; ++i) + if (Instruction *Inst = dyn_cast(New->getOperand(i))) { + DenseMap::iterator I = ValueMapping.find(Inst); + if (I != ValueMapping.end()) + New->setOperand(i, I->second); + } + } + + // We didn't copy the terminator from BB over to NewBB, because there is now + // an unconditional jump to SuccBB. Insert the unconditional jump. + BranchInst::Create(SuccBB, NewBB); + + // Check to see if SuccBB has PHI nodes. If so, we need to add entries to the + // PHI nodes for NewBB now. + AddPHINodeEntriesForMappedBlock(SuccBB, BB, NewBB, ValueMapping); + + // If there were values defined in BB that are used outside the block, then we + // now have to update all uses of the value to use either the original value, + // the cloned value, or some PHI derived value. This can require arbitrary + // PHI insertion, of which we are prepared to do, clean these up now. + SSAUpdater SSAUpdate; + SmallVector UsesToRename; + for (BasicBlock::iterator I = BB->begin(); I != BB->end(); ++I) { + // Scan all uses of this instruction to see if it is used outside of its + // block, and if so, record them in UsesToRename. + for (Value::use_iterator UI = I->use_begin(), E = I->use_end(); UI != E; + ++UI) { + Instruction *User = cast(*UI); + if (PHINode *UserPN = dyn_cast(User)) { + if (UserPN->getIncomingBlock(UI) == BB) + continue; + } else if (User->getParent() == BB) + continue; + + UsesToRename.push_back(&UI.getUse()); + } + + // If there are no uses outside the block, we're done with this instruction. + if (UsesToRename.empty()) + continue; + + DEBUG(errs() << "JT: Renaming non-local uses of: " << *I << "\n"); + + // We found a use of I outside of BB. Rename all uses of I that are outside + // its block to be uses of the appropriate PHI node etc. See ValuesInBlocks + // with the two values we know. + SSAUpdate.Initialize(I); + SSAUpdate.AddAvailableValue(BB, I); + SSAUpdate.AddAvailableValue(NewBB, ValueMapping[I]); + + while (!UsesToRename.empty()) + SSAUpdate.RewriteUse(*UsesToRename.pop_back_val()); + DEBUG(errs() << "\n"); + } + + + // Ok, NewBB is good to go. Update the terminator of PredBB to jump to + // NewBB instead of BB. This eliminates predecessors from BB, which requires + // us to simplify any PHI nodes in BB. + TerminatorInst *PredTerm = PredBB->getTerminator(); + for (unsigned i = 0, e = PredTerm->getNumSuccessors(); i != e; ++i) + if (PredTerm->getSuccessor(i) == BB) { + RemovePredecessorAndSimplify(BB, PredBB, TD); + PredTerm->setSuccessor(i, NewBB); + } + + // At this point, the IR is fully up to date and consistent. Do a quick scan + // over the new instructions and zap any that are constants or dead. This + // frequently happens because of phi translation. + BI = NewBB->begin(); + for (BasicBlock::iterator E = NewBB->end(); BI != E; ) { + Instruction *Inst = BI++; + + if (Value *V = SimplifyInstruction(Inst, TD)) { + WeakVH BIHandle(BI); + ReplaceAndSimplifyAllUses(Inst, V, TD); + if (BIHandle == 0) + BI = NewBB->begin(); + continue; + } + + RecursivelyDeleteTriviallyDeadInstructions(Inst); + } + + // Threaded an edge! + ++NumThreads; + return true; +} + +/// DuplicateCondBranchOnPHIIntoPred - PredBB contains an unconditional branch +/// to BB which contains an i1 PHI node and a conditional branch on that PHI. +/// If we can duplicate the contents of BB up into PredBB do so now, this +/// improves the odds that the branch will be on an analyzable instruction like +/// a compare. +bool JumpThreading::DuplicateCondBranchOnPHIIntoPred(BasicBlock *BB, + BasicBlock *PredBB) { + // If BB is a loop header, then duplicating this block outside the loop would + // cause us to transform this into an irreducible loop, don't do this. + // See the comments above FindLoopHeaders for justifications and caveats. + if (LoopHeaders.count(BB)) { + DEBUG(errs() << " Not duplicating loop header '" << BB->getName() + << "' into predecessor block '" << PredBB->getName() + << "' - it might create an irreducible loop!\n"); + return false; + } + + unsigned DuplicationCost = getJumpThreadDuplicationCost(BB); + if (DuplicationCost > Threshold) { + DEBUG(errs() << " Not duplicating BB '" << BB->getName() + << "' - Cost is too high: " << DuplicationCost << "\n"); + return false; + } + + // Okay, we decided to do this! Clone all the instructions in BB onto the end + // of PredBB. + DEBUG(errs() << " Duplicating block '" << BB->getName() << "' into end of '" + << PredBB->getName() << "' to eliminate branch on phi. Cost: " + << DuplicationCost << " block is:" << *BB << "\n"); + + // We are going to have to map operands from the original BB block into the + // PredBB block. Evaluate PHI nodes in BB. + DenseMap ValueMapping; + + BasicBlock::iterator BI = BB->begin(); + for (; PHINode *PN = dyn_cast(BI); ++BI) + ValueMapping[PN] = PN->getIncomingValueForBlock(PredBB); + + BranchInst *OldPredBranch = cast(PredBB->getTerminator()); + + // Clone the non-phi instructions of BB into PredBB, keeping track of the + // mapping and using it to remap operands in the cloned instructions. + for (; BI != BB->end(); ++BI) { + Instruction *New = BI->clone(); + New->setName(BI->getName()); + PredBB->getInstList().insert(OldPredBranch, New); + ValueMapping[BI] = New; + + // Remap operands to patch up intra-block references. + for (unsigned i = 0, e = New->getNumOperands(); i != e; ++i) + if (Instruction *Inst = dyn_cast(New->getOperand(i))) { + DenseMap::iterator I = ValueMapping.find(Inst); + if (I != ValueMapping.end()) + New->setOperand(i, I->second); + } + } + + // Check to see if the targets of the branch had PHI nodes. If so, we need to + // add entries to the PHI nodes for branch from PredBB now. + BranchInst *BBBranch = cast(BB->getTerminator()); + AddPHINodeEntriesForMappedBlock(BBBranch->getSuccessor(0), BB, PredBB, + ValueMapping); + AddPHINodeEntriesForMappedBlock(BBBranch->getSuccessor(1), BB, PredBB, + ValueMapping); + + // If there were values defined in BB that are used outside the block, then we + // now have to update all uses of the value to use either the original value, + // the cloned value, or some PHI derived value. This can require arbitrary + // PHI insertion, of which we are prepared to do, clean these up now. + SSAUpdater SSAUpdate; + SmallVector UsesToRename; + for (BasicBlock::iterator I = BB->begin(); I != BB->end(); ++I) { + // Scan all uses of this instruction to see if it is used outside of its + // block, and if so, record them in UsesToRename. + for (Value::use_iterator UI = I->use_begin(), E = I->use_end(); UI != E; + ++UI) { + Instruction *User = cast(*UI); + if (PHINode *UserPN = dyn_cast(User)) { + if (UserPN->getIncomingBlock(UI) == BB) + continue; + } else if (User->getParent() == BB) + continue; + + UsesToRename.push_back(&UI.getUse()); + } + + // If there are no uses outside the block, we're done with this instruction. + if (UsesToRename.empty()) + continue; + + DEBUG(errs() << "JT: Renaming non-local uses of: " << *I << "\n"); + + // We found a use of I outside of BB. Rename all uses of I that are outside + // its block to be uses of the appropriate PHI node etc. See ValuesInBlocks + // with the two values we know. + SSAUpdate.Initialize(I); + SSAUpdate.AddAvailableValue(BB, I); + SSAUpdate.AddAvailableValue(PredBB, ValueMapping[I]); + + while (!UsesToRename.empty()) + SSAUpdate.RewriteUse(*UsesToRename.pop_back_val()); + DEBUG(errs() << "\n"); + } + + // PredBB no longer jumps to BB, remove entries in the PHI node for the edge + // that we nuked. + RemovePredecessorAndSimplify(BB, PredBB, TD); + + // Remove the unconditional branch at the end of the PredBB block. + OldPredBranch->eraseFromParent(); + + ++NumDupes; + return true; +} + + diff --git a/libclamav/c++/llvm/lib/Transforms/Scalar/LICM.cpp b/libclamav/c++/llvm/lib/Transforms/Scalar/LICM.cpp new file mode 100644 index 000000000..5511387c8 --- /dev/null +++ b/libclamav/c++/llvm/lib/Transforms/Scalar/LICM.cpp @@ -0,0 +1,882 @@ +//===-- LICM.cpp - Loop Invariant Code Motion Pass ------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This pass performs loop invariant code motion, attempting to remove as much +// code from the body of a loop as possible. It does this by either hoisting +// code into the preheader block, or by sinking code to the exit blocks if it is +// safe. This pass also promotes must-aliased memory locations in the loop to +// live in registers, thus hoisting and sinking "invariant" loads and stores. +// +// This pass uses alias analysis for two purposes: +// +// 1. Moving loop invariant loads and calls out of loops. If we can determine +// that a load or call inside of a loop never aliases anything stored to, +// we can hoist it or sink it like any other instruction. +// 2. Scalar Promotion of Memory - If there is a store instruction inside of +// the loop, we try to move the store to happen AFTER the loop instead of +// inside of the loop. This can only happen if a few conditions are true: +// A. The pointer stored through is loop invariant +// B. There are no stores or loads in the loop which _may_ alias the +// pointer. There are no calls in the loop which mod/ref the pointer. +// If these conditions are true, we can promote the loads and stores in the +// loop of the pointer to use a temporary alloca'd variable. We then use +// the mem2reg functionality to construct the appropriate SSA form for the +// variable. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "licm" +#include "llvm/Transforms/Scalar.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/IntrinsicInst.h" +#include "llvm/Instructions.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Analysis/LoopInfo.h" +#include "llvm/Analysis/LoopPass.h" +#include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/Analysis/AliasSetTracker.h" +#include "llvm/Analysis/Dominators.h" +#include "llvm/Analysis/ScalarEvolution.h" +#include "llvm/Transforms/Utils/PromoteMemToReg.h" +#include "llvm/Support/CFG.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/Debug.h" +#include "llvm/ADT/Statistic.h" +#include +using namespace llvm; + +STATISTIC(NumSunk , "Number of instructions sunk out of loop"); +STATISTIC(NumHoisted , "Number of instructions hoisted out of loop"); +STATISTIC(NumMovedLoads, "Number of load insts hoisted or sunk"); +STATISTIC(NumMovedCalls, "Number of call insts hoisted or sunk"); +STATISTIC(NumPromoted , "Number of memory locations promoted to registers"); + +static cl::opt +DisablePromotion("disable-licm-promotion", cl::Hidden, + cl::desc("Disable memory promotion in LICM pass")); + +namespace { + struct LICM : public LoopPass { + static char ID; // Pass identification, replacement for typeid + LICM() : LoopPass(&ID) {} + + virtual bool runOnLoop(Loop *L, LPPassManager &LPM); + + /// This transformation requires natural loop information & requires that + /// loop preheaders be inserted into the CFG... + /// + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesCFG(); + AU.addRequiredID(LoopSimplifyID); + AU.addRequired(); + AU.addRequired(); + AU.addRequired(); // For scalar promotion (mem2reg) + AU.addRequired(); + AU.addPreserved(); + AU.addPreserved(); + AU.addPreservedID(LoopSimplifyID); + } + + bool doFinalization() { + // Free the values stored in the map + for (std::map::iterator + I = LoopToAliasMap.begin(), E = LoopToAliasMap.end(); I != E; ++I) + delete I->second; + + LoopToAliasMap.clear(); + return false; + } + + private: + // Various analyses that we use... + AliasAnalysis *AA; // Current AliasAnalysis information + LoopInfo *LI; // Current LoopInfo + DominatorTree *DT; // Dominator Tree for the current Loop... + DominanceFrontier *DF; // Current Dominance Frontier + + // State that is updated as we process loops + bool Changed; // Set to true when we change anything. + BasicBlock *Preheader; // The preheader block of the current loop... + Loop *CurLoop; // The current loop we are working on... + AliasSetTracker *CurAST; // AliasSet information for the current loop... + std::map LoopToAliasMap; + + /// cloneBasicBlockAnalysis - Simple Analysis hook. Clone alias set info. + void cloneBasicBlockAnalysis(BasicBlock *From, BasicBlock *To, Loop *L); + + /// deleteAnalysisValue - Simple Analysis hook. Delete value V from alias + /// set. + void deleteAnalysisValue(Value *V, Loop *L); + + /// SinkRegion - Walk the specified region of the CFG (defined by all blocks + /// dominated by the specified block, and that are in the current loop) in + /// reverse depth first order w.r.t the DominatorTree. This allows us to + /// visit uses before definitions, allowing us to sink a loop body in one + /// pass without iteration. + /// + void SinkRegion(DomTreeNode *N); + + /// HoistRegion - Walk the specified region of the CFG (defined by all + /// blocks dominated by the specified block, and that are in the current + /// loop) in depth first order w.r.t the DominatorTree. This allows us to + /// visit definitions before uses, allowing us to hoist a loop body in one + /// pass without iteration. + /// + void HoistRegion(DomTreeNode *N); + + /// inSubLoop - Little predicate that returns true if the specified basic + /// block is in a subloop of the current one, not the current one itself. + /// + bool inSubLoop(BasicBlock *BB) { + assert(CurLoop->contains(BB) && "Only valid if BB is IN the loop"); + for (Loop::iterator I = CurLoop->begin(), E = CurLoop->end(); I != E; ++I) + if ((*I)->contains(BB)) + return true; // A subloop actually contains this block! + return false; + } + + /// isExitBlockDominatedByBlockInLoop - This method checks to see if the + /// specified exit block of the loop is dominated by the specified block + /// that is in the body of the loop. We use these constraints to + /// dramatically limit the amount of the dominator tree that needs to be + /// searched. + bool isExitBlockDominatedByBlockInLoop(BasicBlock *ExitBlock, + BasicBlock *BlockInLoop) const { + // If the block in the loop is the loop header, it must be dominated! + BasicBlock *LoopHeader = CurLoop->getHeader(); + if (BlockInLoop == LoopHeader) + return true; + + DomTreeNode *BlockInLoopNode = DT->getNode(BlockInLoop); + DomTreeNode *IDom = DT->getNode(ExitBlock); + + // Because the exit block is not in the loop, we know we have to get _at + // least_ its immediate dominator. + do { + // Get next Immediate Dominator. + IDom = IDom->getIDom(); + + // If we have got to the header of the loop, then the instructions block + // did not dominate the exit node, so we can't hoist it. + if (IDom->getBlock() == LoopHeader) + return false; + + } while (IDom != BlockInLoopNode); + + return true; + } + + /// sink - When an instruction is found to only be used outside of the loop, + /// this function moves it to the exit blocks and patches up SSA form as + /// needed. + /// + void sink(Instruction &I); + + /// hoist - When an instruction is found to only use loop invariant operands + /// that is safe to hoist, this instruction is called to do the dirty work. + /// + void hoist(Instruction &I); + + /// isSafeToExecuteUnconditionally - Only sink or hoist an instruction if it + /// is not a trapping instruction or if it is a trapping instruction and is + /// guaranteed to execute. + /// + bool isSafeToExecuteUnconditionally(Instruction &I); + + /// pointerInvalidatedByLoop - Return true if the body of this loop may + /// store into the memory location pointed to by V. + /// + bool pointerInvalidatedByLoop(Value *V, unsigned Size) { + // Check to see if any of the basic blocks in CurLoop invalidate *V. + return CurAST->getAliasSetForPointer(V, Size).isMod(); + } + + bool canSinkOrHoistInst(Instruction &I); + bool isLoopInvariantInst(Instruction &I); + bool isNotUsedInLoop(Instruction &I); + + /// PromoteValuesInLoop - Look at the stores in the loop and promote as many + /// to scalars as we can. + /// + void PromoteValuesInLoop(); + + /// FindPromotableValuesInLoop - Check the current loop for stores to + /// definite pointers, which are not loaded and stored through may aliases. + /// If these are found, create an alloca for the value, add it to the + /// PromotedValues list, and keep track of the mapping from value to + /// alloca... + /// + void FindPromotableValuesInLoop( + std::vector > &PromotedValues, + std::map &Val2AlMap); + }; +} + +char LICM::ID = 0; +static RegisterPass X("licm", "Loop Invariant Code Motion"); + +Pass *llvm::createLICMPass() { return new LICM(); } + +/// Hoist expressions out of the specified loop. Note, alias info for inner +/// loop is not preserved so it is not a good idea to run LICM multiple +/// times on one loop. +/// +bool LICM::runOnLoop(Loop *L, LPPassManager &LPM) { + Changed = false; + + // Get our Loop and Alias Analysis information... + LI = &getAnalysis(); + AA = &getAnalysis(); + DF = &getAnalysis(); + DT = &getAnalysis(); + + CurAST = new AliasSetTracker(*AA); + // Collect Alias info from subloops + for (Loop::iterator LoopItr = L->begin(), LoopItrE = L->end(); + LoopItr != LoopItrE; ++LoopItr) { + Loop *InnerL = *LoopItr; + AliasSetTracker *InnerAST = LoopToAliasMap[InnerL]; + assert (InnerAST && "Where is my AST?"); + + // What if InnerLoop was modified by other passes ? + CurAST->add(*InnerAST); + } + + CurLoop = L; + + // Get the preheader block to move instructions into... + Preheader = L->getLoopPreheader(); + + // Loop over the body of this loop, looking for calls, invokes, and stores. + // Because subloops have already been incorporated into AST, we skip blocks in + // subloops. + // + for (Loop::block_iterator I = L->block_begin(), E = L->block_end(); + I != E; ++I) { + BasicBlock *BB = *I; + if (LI->getLoopFor(BB) == L) // Ignore blocks in subloops... + CurAST->add(*BB); // Incorporate the specified basic block + } + + // We want to visit all of the instructions in this loop... that are not parts + // of our subloops (they have already had their invariants hoisted out of + // their loop, into this loop, so there is no need to process the BODIES of + // the subloops). + // + // Traverse the body of the loop in depth first order on the dominator tree so + // that we are guaranteed to see definitions before we see uses. This allows + // us to sink instructions in one pass, without iteration. After sinking + // instructions, we perform another pass to hoist them out of the loop. + // + if (L->hasDedicatedExits()) + SinkRegion(DT->getNode(L->getHeader())); + if (Preheader) + HoistRegion(DT->getNode(L->getHeader())); + + // Now that all loop invariants have been removed from the loop, promote any + // memory references to scalars that we can... + if (!DisablePromotion && Preheader && L->hasDedicatedExits()) + PromoteValuesInLoop(); + + // Clear out loops state information for the next iteration + CurLoop = 0; + Preheader = 0; + + LoopToAliasMap[L] = CurAST; + return Changed; +} + +/// SinkRegion - Walk the specified region of the CFG (defined by all blocks +/// dominated by the specified block, and that are in the current loop) in +/// reverse depth first order w.r.t the DominatorTree. This allows us to visit +/// uses before definitions, allowing us to sink a loop body in one pass without +/// iteration. +/// +void LICM::SinkRegion(DomTreeNode *N) { + assert(N != 0 && "Null dominator tree node?"); + BasicBlock *BB = N->getBlock(); + + // If this subregion is not in the top level loop at all, exit. + if (!CurLoop->contains(BB)) return; + + // We are processing blocks in reverse dfo, so process children first... + const std::vector &Children = N->getChildren(); + for (unsigned i = 0, e = Children.size(); i != e; ++i) + SinkRegion(Children[i]); + + // Only need to process the contents of this block if it is not part of a + // subloop (which would already have been processed). + if (inSubLoop(BB)) return; + + for (BasicBlock::iterator II = BB->end(); II != BB->begin(); ) { + Instruction &I = *--II; + + // Check to see if we can sink this instruction to the exit blocks + // of the loop. We can do this if the all users of the instruction are + // outside of the loop. In this case, it doesn't even matter if the + // operands of the instruction are loop invariant. + // + if (isNotUsedInLoop(I) && canSinkOrHoistInst(I)) { + ++II; + sink(I); + } + } +} + +/// HoistRegion - Walk the specified region of the CFG (defined by all blocks +/// dominated by the specified block, and that are in the current loop) in depth +/// first order w.r.t the DominatorTree. This allows us to visit definitions +/// before uses, allowing us to hoist a loop body in one pass without iteration. +/// +void LICM::HoistRegion(DomTreeNode *N) { + assert(N != 0 && "Null dominator tree node?"); + BasicBlock *BB = N->getBlock(); + + // If this subregion is not in the top level loop at all, exit. + if (!CurLoop->contains(BB)) return; + + // Only need to process the contents of this block if it is not part of a + // subloop (which would already have been processed). + if (!inSubLoop(BB)) + for (BasicBlock::iterator II = BB->begin(), E = BB->end(); II != E; ) { + Instruction &I = *II++; + + // Try hoisting the instruction out to the preheader. We can only do this + // if all of the operands of the instruction are loop invariant and if it + // is safe to hoist the instruction. + // + if (isLoopInvariantInst(I) && canSinkOrHoistInst(I) && + isSafeToExecuteUnconditionally(I)) + hoist(I); + } + + const std::vector &Children = N->getChildren(); + for (unsigned i = 0, e = Children.size(); i != e; ++i) + HoistRegion(Children[i]); +} + +/// canSinkOrHoistInst - Return true if the hoister and sinker can handle this +/// instruction. +/// +bool LICM::canSinkOrHoistInst(Instruction &I) { + // Loads have extra constraints we have to verify before we can hoist them. + if (LoadInst *LI = dyn_cast(&I)) { + if (LI->isVolatile()) + return false; // Don't hoist volatile loads! + + // Loads from constant memory are always safe to move, even if they end up + // in the same alias set as something that ends up being modified. + if (AA->pointsToConstantMemory(LI->getOperand(0))) + return true; + + // Don't hoist loads which have may-aliased stores in loop. + unsigned Size = 0; + if (LI->getType()->isSized()) + Size = AA->getTypeStoreSize(LI->getType()); + return !pointerInvalidatedByLoop(LI->getOperand(0), Size); + } else if (CallInst *CI = dyn_cast(&I)) { + if (isa(CI)) { + // Don't hoist/sink dbgstoppoints, we handle them separately + return false; + } + // Handle obvious cases efficiently. + AliasAnalysis::ModRefBehavior Behavior = AA->getModRefBehavior(CI); + if (Behavior == AliasAnalysis::DoesNotAccessMemory) + return true; + else if (Behavior == AliasAnalysis::OnlyReadsMemory) { + // If this call only reads from memory and there are no writes to memory + // in the loop, we can hoist or sink the call as appropriate. + bool FoundMod = false; + for (AliasSetTracker::iterator I = CurAST->begin(), E = CurAST->end(); + I != E; ++I) { + AliasSet &AS = *I; + if (!AS.isForwardingAliasSet() && AS.isMod()) { + FoundMod = true; + break; + } + } + if (!FoundMod) return true; + } + + // FIXME: This should use mod/ref information to see if we can hoist or sink + // the call. + + return false; + } + + // Otherwise these instructions are hoistable/sinkable + return isa(I) || isa(I) || + isa(I) || isa(I) || isa(I) || + isa(I) || isa(I) || + isa(I); +} + +/// isNotUsedInLoop - Return true if the only users of this instruction are +/// outside of the loop. If this is true, we can sink the instruction to the +/// exit blocks of the loop. +/// +bool LICM::isNotUsedInLoop(Instruction &I) { + for (Value::use_iterator UI = I.use_begin(), E = I.use_end(); UI != E; ++UI) { + Instruction *User = cast(*UI); + if (PHINode *PN = dyn_cast(User)) { + // PHI node uses occur in predecessor blocks! + for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) + if (PN->getIncomingValue(i) == &I) + if (CurLoop->contains(PN->getIncomingBlock(i))) + return false; + } else if (CurLoop->contains(User->getParent())) { + return false; + } + } + return true; +} + + +/// isLoopInvariantInst - Return true if all operands of this instruction are +/// loop invariant. We also filter out non-hoistable instructions here just for +/// efficiency. +/// +bool LICM::isLoopInvariantInst(Instruction &I) { + // The instruction is loop invariant if all of its operands are loop-invariant + for (unsigned i = 0, e = I.getNumOperands(); i != e; ++i) + if (!CurLoop->isLoopInvariant(I.getOperand(i))) + return false; + + // If we got this far, the instruction is loop invariant! + return true; +} + +/// sink - When an instruction is found to only be used outside of the loop, +/// this function moves it to the exit blocks and patches up SSA form as needed. +/// This method is guaranteed to remove the original instruction from its +/// position, and may either delete it or move it to outside of the loop. +/// +void LICM::sink(Instruction &I) { + DEBUG(errs() << "LICM sinking instruction: " << I); + + SmallVector ExitBlocks; + CurLoop->getExitBlocks(ExitBlocks); + + if (isa(I)) ++NumMovedLoads; + else if (isa(I)) ++NumMovedCalls; + ++NumSunk; + Changed = true; + + // The case where there is only a single exit node of this loop is common + // enough that we handle it as a special (more efficient) case. It is more + // efficient to handle because there are no PHI nodes that need to be placed. + if (ExitBlocks.size() == 1) { + if (!isExitBlockDominatedByBlockInLoop(ExitBlocks[0], I.getParent())) { + // Instruction is not used, just delete it. + CurAST->deleteValue(&I); + // If I has users in unreachable blocks, eliminate. + // If I is not void type then replaceAllUsesWith undef. + // This allows ValueHandlers and custom metadata to adjust itself. + if (!I.getType()->isVoidTy()) + I.replaceAllUsesWith(UndefValue::get(I.getType())); + I.eraseFromParent(); + } else { + // Move the instruction to the start of the exit block, after any PHI + // nodes in it. + I.removeFromParent(); + BasicBlock::iterator InsertPt = ExitBlocks[0]->getFirstNonPHI(); + ExitBlocks[0]->getInstList().insert(InsertPt, &I); + } + } else if (ExitBlocks.empty()) { + // The instruction is actually dead if there ARE NO exit blocks. + CurAST->deleteValue(&I); + // If I has users in unreachable blocks, eliminate. + // If I is not void type then replaceAllUsesWith undef. + // This allows ValueHandlers and custom metadata to adjust itself. + if (!I.getType()->isVoidTy()) + I.replaceAllUsesWith(UndefValue::get(I.getType())); + I.eraseFromParent(); + } else { + // Otherwise, if we have multiple exits, use the PromoteMem2Reg function to + // do all of the hard work of inserting PHI nodes as necessary. We convert + // the value into a stack object to get it to do this. + + // Firstly, we create a stack object to hold the value... + AllocaInst *AI = 0; + + if (!I.getType()->isVoidTy()) { + AI = new AllocaInst(I.getType(), 0, I.getName(), + I.getParent()->getParent()->getEntryBlock().begin()); + CurAST->add(AI); + } + + // Secondly, insert load instructions for each use of the instruction + // outside of the loop. + while (!I.use_empty()) { + Instruction *U = cast(I.use_back()); + + // If the user is a PHI Node, we actually have to insert load instructions + // in all predecessor blocks, not in the PHI block itself! + if (PHINode *UPN = dyn_cast(U)) { + // Only insert into each predecessor once, so that we don't have + // different incoming values from the same block! + std::map InsertedBlocks; + for (unsigned i = 0, e = UPN->getNumIncomingValues(); i != e; ++i) + if (UPN->getIncomingValue(i) == &I) { + BasicBlock *Pred = UPN->getIncomingBlock(i); + Value *&PredVal = InsertedBlocks[Pred]; + if (!PredVal) { + // Insert a new load instruction right before the terminator in + // the predecessor block. + PredVal = new LoadInst(AI, "", Pred->getTerminator()); + CurAST->add(cast(PredVal)); + } + + UPN->setIncomingValue(i, PredVal); + } + + } else { + LoadInst *L = new LoadInst(AI, "", U); + U->replaceUsesOfWith(&I, L); + CurAST->add(L); + } + } + + // Thirdly, insert a copy of the instruction in each exit block of the loop + // that is dominated by the instruction, storing the result into the memory + // location. Be careful not to insert the instruction into any particular + // basic block more than once. + std::set InsertedBlocks; + BasicBlock *InstOrigBB = I.getParent(); + + for (unsigned i = 0, e = ExitBlocks.size(); i != e; ++i) { + BasicBlock *ExitBlock = ExitBlocks[i]; + + if (isExitBlockDominatedByBlockInLoop(ExitBlock, InstOrigBB)) { + // If we haven't already processed this exit block, do so now. + if (InsertedBlocks.insert(ExitBlock).second) { + // Insert the code after the last PHI node... + BasicBlock::iterator InsertPt = ExitBlock->getFirstNonPHI(); + + // If this is the first exit block processed, just move the original + // instruction, otherwise clone the original instruction and insert + // the copy. + Instruction *New; + if (InsertedBlocks.size() == 1) { + I.removeFromParent(); + ExitBlock->getInstList().insert(InsertPt, &I); + New = &I; + } else { + New = I.clone(); + CurAST->copyValue(&I, New); + if (!I.getName().empty()) + New->setName(I.getName()+".le"); + ExitBlock->getInstList().insert(InsertPt, New); + } + + // Now that we have inserted the instruction, store it into the alloca + if (AI) new StoreInst(New, AI, InsertPt); + } + } + } + + // If the instruction doesn't dominate any exit blocks, it must be dead. + if (InsertedBlocks.empty()) { + CurAST->deleteValue(&I); + I.eraseFromParent(); + } + + // Finally, promote the fine value to SSA form. + if (AI) { + std::vector Allocas; + Allocas.push_back(AI); + PromoteMemToReg(Allocas, *DT, *DF, CurAST); + } + } +} + +/// hoist - When an instruction is found to only use loop invariant operands +/// that is safe to hoist, this instruction is called to do the dirty work. +/// +void LICM::hoist(Instruction &I) { + DEBUG(errs() << "LICM hoisting to " << Preheader->getName() << ": " + << I << "\n"); + + // Remove the instruction from its current basic block... but don't delete the + // instruction. + I.removeFromParent(); + + // Insert the new node in Preheader, before the terminator. + Preheader->getInstList().insert(Preheader->getTerminator(), &I); + + if (isa(I)) ++NumMovedLoads; + else if (isa(I)) ++NumMovedCalls; + ++NumHoisted; + Changed = true; +} + +/// isSafeToExecuteUnconditionally - Only sink or hoist an instruction if it is +/// not a trapping instruction or if it is a trapping instruction and is +/// guaranteed to execute. +/// +bool LICM::isSafeToExecuteUnconditionally(Instruction &Inst) { + // If it is not a trapping instruction, it is always safe to hoist. + if (Inst.isSafeToSpeculativelyExecute()) + return true; + + // Otherwise we have to check to make sure that the instruction dominates all + // of the exit blocks. If it doesn't, then there is a path out of the loop + // which does not execute this instruction, so we can't hoist it. + + // If the instruction is in the header block for the loop (which is very + // common), it is always guaranteed to dominate the exit blocks. Since this + // is a common case, and can save some work, check it now. + if (Inst.getParent() == CurLoop->getHeader()) + return true; + + // Get the exit blocks for the current loop. + SmallVector ExitBlocks; + CurLoop->getExitBlocks(ExitBlocks); + + // For each exit block, get the DT node and walk up the DT until the + // instruction's basic block is found or we exit the loop. + for (unsigned i = 0, e = ExitBlocks.size(); i != e; ++i) + if (!isExitBlockDominatedByBlockInLoop(ExitBlocks[i], Inst.getParent())) + return false; + + return true; +} + + +/// PromoteValuesInLoop - Try to promote memory values to scalars by sinking +/// stores out of the loop and moving loads to before the loop. We do this by +/// looping over the stores in the loop, looking for stores to Must pointers +/// which are loop invariant. We promote these memory locations to use allocas +/// instead. These allocas can easily be raised to register values by the +/// PromoteMem2Reg functionality. +/// +void LICM::PromoteValuesInLoop() { + // PromotedValues - List of values that are promoted out of the loop. Each + // value has an alloca instruction for it, and a canonical version of the + // pointer. + std::vector > PromotedValues; + std::map ValueToAllocaMap; // Map of ptr to alloca + + FindPromotableValuesInLoop(PromotedValues, ValueToAllocaMap); + if (ValueToAllocaMap.empty()) return; // If there are values to promote. + + Changed = true; + NumPromoted += PromotedValues.size(); + + std::vector PointerValueNumbers; + + // Emit a copy from the value into the alloca'd value in the loop preheader + TerminatorInst *LoopPredInst = Preheader->getTerminator(); + for (unsigned i = 0, e = PromotedValues.size(); i != e; ++i) { + Value *Ptr = PromotedValues[i].second; + + // If we are promoting a pointer value, update alias information for the + // inserted load. + Value *LoadValue = 0; + if (isa(cast(Ptr->getType())->getElementType())) { + // Locate a load or store through the pointer, and assign the same value + // to LI as we are loading or storing. Since we know that the value is + // stored in this loop, this will always succeed. + for (Value::use_iterator UI = Ptr->use_begin(), E = Ptr->use_end(); + UI != E; ++UI) + if (LoadInst *LI = dyn_cast(*UI)) { + LoadValue = LI; + break; + } else if (StoreInst *SI = dyn_cast(*UI)) { + if (SI->getOperand(1) == Ptr) { + LoadValue = SI->getOperand(0); + break; + } + } + assert(LoadValue && "No store through the pointer found!"); + PointerValueNumbers.push_back(LoadValue); // Remember this for later. + } + + // Load from the memory we are promoting. + LoadInst *LI = new LoadInst(Ptr, Ptr->getName()+".promoted", LoopPredInst); + + if (LoadValue) CurAST->copyValue(LoadValue, LI); + + // Store into the temporary alloca. + new StoreInst(LI, PromotedValues[i].first, LoopPredInst); + } + + // Scan the basic blocks in the loop, replacing uses of our pointers with + // uses of the allocas in question. + // + for (Loop::block_iterator I = CurLoop->block_begin(), + E = CurLoop->block_end(); I != E; ++I) { + BasicBlock *BB = *I; + // Rewrite all loads and stores in the block of the pointer... + for (BasicBlock::iterator II = BB->begin(), E = BB->end(); II != E; ++II) { + if (LoadInst *L = dyn_cast(II)) { + std::map::iterator + I = ValueToAllocaMap.find(L->getOperand(0)); + if (I != ValueToAllocaMap.end()) + L->setOperand(0, I->second); // Rewrite load instruction... + } else if (StoreInst *S = dyn_cast(II)) { + std::map::iterator + I = ValueToAllocaMap.find(S->getOperand(1)); + if (I != ValueToAllocaMap.end()) + S->setOperand(1, I->second); // Rewrite store instruction... + } + } + } + + // Now that the body of the loop uses the allocas instead of the original + // memory locations, insert code to copy the alloca value back into the + // original memory location on all exits from the loop. Note that we only + // want to insert one copy of the code in each exit block, though the loop may + // exit to the same block more than once. + // + SmallPtrSet ProcessedBlocks; + + SmallVector ExitBlocks; + CurLoop->getExitBlocks(ExitBlocks); + for (unsigned i = 0, e = ExitBlocks.size(); i != e; ++i) { + if (!ProcessedBlocks.insert(ExitBlocks[i])) + continue; + + // Copy all of the allocas into their memory locations. + BasicBlock::iterator BI = ExitBlocks[i]->getFirstNonPHI(); + Instruction *InsertPos = BI; + unsigned PVN = 0; + for (unsigned i = 0, e = PromotedValues.size(); i != e; ++i) { + // Load from the alloca. + LoadInst *LI = new LoadInst(PromotedValues[i].first, "", InsertPos); + + // If this is a pointer type, update alias info appropriately. + if (isa(LI->getType())) + CurAST->copyValue(PointerValueNumbers[PVN++], LI); + + // Store into the memory we promoted. + new StoreInst(LI, PromotedValues[i].second, InsertPos); + } + } + + // Now that we have done the deed, use the mem2reg functionality to promote + // all of the new allocas we just created into real SSA registers. + // + std::vector PromotedAllocas; + PromotedAllocas.reserve(PromotedValues.size()); + for (unsigned i = 0, e = PromotedValues.size(); i != e; ++i) + PromotedAllocas.push_back(PromotedValues[i].first); + PromoteMemToReg(PromotedAllocas, *DT, *DF, CurAST); +} + +/// FindPromotableValuesInLoop - Check the current loop for stores to definite +/// pointers, which are not loaded and stored through may aliases and are safe +/// for promotion. If these are found, create an alloca for the value, add it +/// to the PromotedValues list, and keep track of the mapping from value to +/// alloca. +void LICM::FindPromotableValuesInLoop( + std::vector > &PromotedValues, + std::map &ValueToAllocaMap) { + Instruction *FnStart = CurLoop->getHeader()->getParent()->begin()->begin(); + + // Loop over all of the alias sets in the tracker object. + for (AliasSetTracker::iterator I = CurAST->begin(), E = CurAST->end(); + I != E; ++I) { + AliasSet &AS = *I; + // We can promote this alias set if it has a store, if it is a "Must" alias + // set, if the pointer is loop invariant, and if we are not eliminating any + // volatile loads or stores. + if (AS.isForwardingAliasSet() || !AS.isMod() || !AS.isMustAlias() || + AS.isVolatile() || !CurLoop->isLoopInvariant(AS.begin()->getValue())) + continue; + + assert(!AS.empty() && + "Must alias set should have at least one pointer element in it!"); + Value *V = AS.begin()->getValue(); + + // Check that all of the pointers in the alias set have the same type. We + // cannot (yet) promote a memory location that is loaded and stored in + // different sizes. + { + bool PointerOk = true; + for (AliasSet::iterator I = AS.begin(), E = AS.end(); I != E; ++I) + if (V->getType() != I->getValue()->getType()) { + PointerOk = false; + break; + } + if (!PointerOk) + continue; + } + + // It isn't safe to promote a load/store from the loop if the load/store is + // conditional. For example, turning: + // + // for () { if (c) *P += 1; } + // + // into: + // + // tmp = *P; for () { if (c) tmp +=1; } *P = tmp; + // + // is not safe, because *P may only be valid to access if 'c' is true. + // + // It is safe to promote P if all uses are direct load/stores and if at + // least one is guaranteed to be executed. + bool GuaranteedToExecute = false; + bool InvalidInst = false; + for (Value::use_iterator UI = V->use_begin(), UE = V->use_end(); + UI != UE; ++UI) { + // Ignore instructions not in this loop. + Instruction *Use = dyn_cast(*UI); + if (!Use || !CurLoop->contains(Use->getParent())) + continue; + + if (!isa(Use) && !isa(Use)) { + InvalidInst = true; + break; + } + + if (!GuaranteedToExecute) + GuaranteedToExecute = isSafeToExecuteUnconditionally(*Use); + } + + // If there is an non-load/store instruction in the loop, we can't promote + // it. If there isn't a guaranteed-to-execute instruction, we can't + // promote. + if (InvalidInst || !GuaranteedToExecute) + continue; + + const Type *Ty = cast(V->getType())->getElementType(); + AllocaInst *AI = new AllocaInst(Ty, 0, V->getName()+".tmp", FnStart); + PromotedValues.push_back(std::make_pair(AI, V)); + + // Update the AST and alias analysis. + CurAST->copyValue(V, AI); + + for (AliasSet::iterator I = AS.begin(), E = AS.end(); I != E; ++I) + ValueToAllocaMap.insert(std::make_pair(I->getValue(), AI)); + + DEBUG(errs() << "LICM: Promoting value: " << *V << "\n"); + } +} + +/// cloneBasicBlockAnalysis - Simple Analysis hook. Clone alias set info. +void LICM::cloneBasicBlockAnalysis(BasicBlock *From, BasicBlock *To, Loop *L) { + AliasSetTracker *AST = LoopToAliasMap[L]; + if (!AST) + return; + + AST->copyValue(From, To); +} + +/// deleteAnalysisValue - Simple Analysis hook. Delete value V from alias +/// set. +void LICM::deleteAnalysisValue(Value *V, Loop *L) { + AliasSetTracker *AST = LoopToAliasMap[L]; + if (!AST) + return; + + AST->deleteValue(V); +} diff --git a/libclamav/c++/llvm/lib/Transforms/Scalar/LoopDeletion.cpp b/libclamav/c++/llvm/lib/Transforms/Scalar/LoopDeletion.cpp new file mode 100644 index 000000000..48817ab9d --- /dev/null +++ b/libclamav/c++/llvm/lib/Transforms/Scalar/LoopDeletion.cpp @@ -0,0 +1,232 @@ +//===- LoopDeletion.cpp - Dead Loop Deletion Pass ---------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the Dead Loop Deletion Pass. This pass is responsible +// for eliminating loops with non-infinite computable trip counts that have no +// side effects or volatile instructions, and do not contribute to the +// computation of the function's return value. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "loop-delete" +#include "llvm/Transforms/Scalar.h" +#include "llvm/Analysis/LoopPass.h" +#include "llvm/Analysis/ScalarEvolution.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/ADT/SmallVector.h" +using namespace llvm; + +STATISTIC(NumDeleted, "Number of loops deleted"); + +namespace { + class LoopDeletion : public LoopPass { + public: + static char ID; // Pass ID, replacement for typeid + LoopDeletion() : LoopPass(&ID) {} + + // Possibly eliminate loop L if it is dead. + bool runOnLoop(Loop* L, LPPassManager& LPM); + + bool IsLoopDead(Loop* L, SmallVector& exitingBlocks, + SmallVector& exitBlocks, + bool &Changed, BasicBlock *Preheader); + + virtual void getAnalysisUsage(AnalysisUsage& AU) const { + AU.addRequired(); + AU.addRequired(); + AU.addRequired(); + AU.addRequiredID(LoopSimplifyID); + AU.addRequiredID(LCSSAID); + + AU.addPreserved(); + AU.addPreserved(); + AU.addPreserved(); + AU.addPreservedID(LoopSimplifyID); + AU.addPreservedID(LCSSAID); + AU.addPreserved(); + } + }; +} + +char LoopDeletion::ID = 0; +static RegisterPass X("loop-deletion", "Delete dead loops"); + +Pass* llvm::createLoopDeletionPass() { + return new LoopDeletion(); +} + +/// IsLoopDead - Determined if a loop is dead. This assumes that we've already +/// checked for unique exit and exiting blocks, and that the code is in LCSSA +/// form. +bool LoopDeletion::IsLoopDead(Loop* L, + SmallVector& exitingBlocks, + SmallVector& exitBlocks, + bool &Changed, BasicBlock *Preheader) { + BasicBlock* exitingBlock = exitingBlocks[0]; + BasicBlock* exitBlock = exitBlocks[0]; + + // Make sure that all PHI entries coming from the loop are loop invariant. + // Because the code is in LCSSA form, any values used outside of the loop + // must pass through a PHI in the exit block, meaning that this check is + // sufficient to guarantee that no loop-variant values are used outside + // of the loop. + BasicBlock::iterator BI = exitBlock->begin(); + while (PHINode* P = dyn_cast(BI)) { + Value* incoming = P->getIncomingValueForBlock(exitingBlock); + if (Instruction* I = dyn_cast(incoming)) + if (!L->makeLoopInvariant(I, Changed, Preheader->getTerminator())) + return false; + + BI++; + } + + // Make sure that no instructions in the block have potential side-effects. + // This includes instructions that could write to memory, and loads that are + // marked volatile. This could be made more aggressive by using aliasing + // information to identify readonly and readnone calls. + for (Loop::block_iterator LI = L->block_begin(), LE = L->block_end(); + LI != LE; ++LI) { + for (BasicBlock::iterator BI = (*LI)->begin(), BE = (*LI)->end(); + BI != BE; ++BI) { + if (BI->mayHaveSideEffects()) + return false; + } + } + + return true; +} + +/// runOnLoop - Remove dead loops, by which we mean loops that do not impact the +/// observable behavior of the program other than finite running time. Note +/// we do ensure that this never remove a loop that might be infinite, as doing +/// so could change the halting/non-halting nature of a program. +/// NOTE: This entire process relies pretty heavily on LoopSimplify and LCSSA +/// in order to make various safety checks work. +bool LoopDeletion::runOnLoop(Loop* L, LPPassManager& LPM) { + // We can only remove the loop if there is a preheader that we can + // branch from after removing it. + BasicBlock* preheader = L->getLoopPreheader(); + if (!preheader) + return false; + + // If LoopSimplify form is not available, stay out of trouble. + if (!L->hasDedicatedExits()) + return false; + + // We can't remove loops that contain subloops. If the subloops were dead, + // they would already have been removed in earlier executions of this pass. + if (L->begin() != L->end()) + return false; + + SmallVector exitingBlocks; + L->getExitingBlocks(exitingBlocks); + + SmallVector exitBlocks; + L->getUniqueExitBlocks(exitBlocks); + + // We require that the loop only have a single exit block. Otherwise, we'd + // be in the situation of needing to be able to solve statically which exit + // block will be branched to, or trying to preserve the branching logic in + // a loop invariant manner. + if (exitBlocks.size() != 1) + return false; + + // Loops with multiple exits are too complicated to handle correctly. + if (exitingBlocks.size() != 1) + return false; + + // Finally, we have to check that the loop really is dead. + bool Changed = false; + if (!IsLoopDead(L, exitingBlocks, exitBlocks, Changed, preheader)) + return Changed; + + // Don't remove loops for which we can't solve the trip count. + // They could be infinite, in which case we'd be changing program behavior. + ScalarEvolution& SE = getAnalysis(); + const SCEV *S = SE.getMaxBackedgeTakenCount(L); + if (isa(S)) + return Changed; + + // Now that we know the removal is safe, remove the loop by changing the + // branch from the preheader to go to the single exit block. + BasicBlock* exitBlock = exitBlocks[0]; + BasicBlock* exitingBlock = exitingBlocks[0]; + + // Because we're deleting a large chunk of code at once, the sequence in which + // we remove things is very important to avoid invalidation issues. Don't + // mess with this unless you have good reason and know what you're doing. + + // Tell ScalarEvolution that the loop is deleted. Do this before + // deleting the loop so that ScalarEvolution can look at the loop + // to determine what it needs to clean up. + SE.forgetLoop(L); + + // Connect the preheader directly to the exit block. + TerminatorInst* TI = preheader->getTerminator(); + TI->replaceUsesOfWith(L->getHeader(), exitBlock); + + // Rewrite phis in the exit block to get their inputs from + // the preheader instead of the exiting block. + BasicBlock::iterator BI = exitBlock->begin(); + while (PHINode* P = dyn_cast(BI)) { + P->replaceUsesOfWith(exitingBlock, preheader); + BI++; + } + + // Update the dominator tree and remove the instructions and blocks that will + // be deleted from the reference counting scheme. + DominatorTree& DT = getAnalysis(); + DominanceFrontier* DF = getAnalysisIfAvailable(); + SmallPtrSet ChildNodes; + for (Loop::block_iterator LI = L->block_begin(), LE = L->block_end(); + LI != LE; ++LI) { + // Move all of the block's children to be children of the preheader, which + // allows us to remove the domtree entry for the block. + ChildNodes.insert(DT[*LI]->begin(), DT[*LI]->end()); + for (SmallPtrSet::iterator DI = ChildNodes.begin(), + DE = ChildNodes.end(); DI != DE; ++DI) { + DT.changeImmediateDominator(*DI, DT[preheader]); + if (DF) DF->changeImmediateDominator((*DI)->getBlock(), preheader, &DT); + } + + ChildNodes.clear(); + DT.eraseNode(*LI); + if (DF) DF->removeBlock(*LI); + + // Remove the block from the reference counting scheme, so that we can + // delete it freely later. + (*LI)->dropAllReferences(); + } + + // Erase the instructions and the blocks without having to worry + // about ordering because we already dropped the references. + // NOTE: This iteration is safe because erasing the block does not remove its + // entry from the loop's block list. We do that in the next section. + for (Loop::block_iterator LI = L->block_begin(), LE = L->block_end(); + LI != LE; ++LI) + (*LI)->eraseFromParent(); + + // Finally, the blocks from loopinfo. This has to happen late because + // otherwise our loop iterators won't work. + LoopInfo& loopInfo = getAnalysis(); + SmallPtrSet blocks; + blocks.insert(L->block_begin(), L->block_end()); + for (SmallPtrSet::iterator I = blocks.begin(), + E = blocks.end(); I != E; ++I) + loopInfo.removeBlock(*I); + + // The last step is to inform the loop pass manager that we've + // eliminated this loop. + LPM.deleteLoopFromQueue(L); + Changed = true; + + NumDeleted++; + + return Changed; +} diff --git a/libclamav/c++/llvm/lib/Transforms/Scalar/LoopIndexSplit.cpp b/libclamav/c++/llvm/lib/Transforms/Scalar/LoopIndexSplit.cpp new file mode 100644 index 000000000..8b6a23343 --- /dev/null +++ b/libclamav/c++/llvm/lib/Transforms/Scalar/LoopIndexSplit.cpp @@ -0,0 +1,1251 @@ +//===- LoopIndexSplit.cpp - Loop Index Splitting Pass ---------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements Loop Index Splitting Pass. This pass handles three +// kinds of loops. +// +// [1] A loop may be eliminated if the body is executed exactly once. +// For example, +// +// for (i = 0; i < N; ++i) { +// if (i == X) { +// body; +// } +// } +// +// is transformed to +// +// i = X; +// body; +// +// [2] A loop's iteration space may be shrunk if the loop body is executed +// for a proper sub-range of the loop's iteration space. For example, +// +// for (i = 0; i < N; ++i) { +// if (i > A && i < B) { +// ... +// } +// } +// +// is transformed to iterators from A to B, if A > 0 and B < N. +// +// [3] A loop may be split if the loop body is dominated by a branch. +// For example, +// +// for (i = LB; i < UB; ++i) { if (i < SV) A; else B; } +// +// is transformed into +// +// AEV = BSV = SV +// for (i = LB; i < min(UB, AEV); ++i) +// A; +// for (i = max(LB, BSV); i < UB; ++i); +// B; +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "loop-index-split" +#include "llvm/Transforms/Scalar.h" +#include "llvm/IntrinsicInst.h" +#include "llvm/LLVMContext.h" +#include "llvm/Analysis/LoopPass.h" +#include "llvm/Analysis/ScalarEvolution.h" +#include "llvm/Analysis/Dominators.h" +#include "llvm/Transforms/Utils/BasicBlockUtils.h" +#include "llvm/Transforms/Utils/Cloning.h" +#include "llvm/Transforms/Utils/Local.h" +#include "llvm/ADT/DepthFirstIterator.h" +#include "llvm/ADT/Statistic.h" + +using namespace llvm; + +STATISTIC(NumIndexSplit, "Number of loop index split"); +STATISTIC(NumIndexSplitRemoved, "Number of loops eliminated by loop index split"); +STATISTIC(NumRestrictBounds, "Number of loop iteration space restricted"); + +namespace { + + class LoopIndexSplit : public LoopPass { + public: + static char ID; // Pass ID, replacement for typeid + LoopIndexSplit() : LoopPass(&ID) {} + + // Index split Loop L. Return true if loop is split. + bool runOnLoop(Loop *L, LPPassManager &LPM); + + void getAnalysisUsage(AnalysisUsage &AU) const { + AU.addPreserved(); + AU.addRequiredID(LCSSAID); + AU.addPreservedID(LCSSAID); + AU.addRequired(); + AU.addPreserved(); + AU.addRequiredID(LoopSimplifyID); + AU.addPreservedID(LoopSimplifyID); + AU.addRequired(); + AU.addRequired(); + AU.addPreserved(); + AU.addPreserved(); + } + + private: + /// processOneIterationLoop -- Eliminate loop if loop body is executed + /// only once. For example, + /// for (i = 0; i < N; ++i) { + /// if ( i == X) { + /// ... + /// } + /// } + /// + bool processOneIterationLoop(); + + // -- Routines used by updateLoopIterationSpace(); + + /// updateLoopIterationSpace -- Update loop's iteration space if loop + /// body is executed for certain IV range only. For example, + /// + /// for (i = 0; i < N; ++i) { + /// if ( i > A && i < B) { + /// ... + /// } + /// } + /// is transformed to iterators from A to B, if A > 0 and B < N. + /// + bool updateLoopIterationSpace(); + + /// restrictLoopBound - Op dominates loop body. Op compares an IV based value + /// with a loop invariant value. Update loop's lower and upper bound based on + /// the loop invariant value. + bool restrictLoopBound(ICmpInst &Op); + + // --- Routines used by splitLoop(). --- / + + bool splitLoop(); + + /// removeBlocks - Remove basic block DeadBB and all blocks dominated by + /// DeadBB. This routine is used to remove split condition's dead branch, + /// dominated by DeadBB. LiveBB dominates split conidition's other branch. + void removeBlocks(BasicBlock *DeadBB, Loop *LP, BasicBlock *LiveBB); + + /// moveExitCondition - Move exit condition EC into split condition block. + void moveExitCondition(BasicBlock *CondBB, BasicBlock *ActiveBB, + BasicBlock *ExitBB, ICmpInst *EC, ICmpInst *SC, + PHINode *IV, Instruction *IVAdd, Loop *LP, + unsigned); + + /// updatePHINodes - CFG has been changed. + /// Before + /// - ExitBB's single predecessor was Latch + /// - Latch's second successor was Header + /// Now + /// - ExitBB's single predecessor was Header + /// - Latch's one and only successor was Header + /// + /// Update ExitBB PHINodes' to reflect this change. + void updatePHINodes(BasicBlock *ExitBB, BasicBlock *Latch, + BasicBlock *Header, + PHINode *IV, Instruction *IVIncrement, Loop *LP); + + // --- Utility routines --- / + + /// cleanBlock - A block is considered clean if all non terminal + /// instructions are either PHINodes or IV based values. + bool cleanBlock(BasicBlock *BB); + + /// IVisLT - If Op is comparing IV based value with an loop invariant and + /// IV based value is less than the loop invariant then return the loop + /// invariant. Otherwise return NULL. + Value * IVisLT(ICmpInst &Op); + + /// IVisLE - If Op is comparing IV based value with an loop invariant and + /// IV based value is less than or equal to the loop invariant then + /// return the loop invariant. Otherwise return NULL. + Value * IVisLE(ICmpInst &Op); + + /// IVisGT - If Op is comparing IV based value with an loop invariant and + /// IV based value is greater than the loop invariant then return the loop + /// invariant. Otherwise return NULL. + Value * IVisGT(ICmpInst &Op); + + /// IVisGE - If Op is comparing IV based value with an loop invariant and + /// IV based value is greater than or equal to the loop invariant then + /// return the loop invariant. Otherwise return NULL. + Value * IVisGE(ICmpInst &Op); + + private: + + // Current Loop information. + Loop *L; + LPPassManager *LPM; + LoopInfo *LI; + DominatorTree *DT; + DominanceFrontier *DF; + + PHINode *IndVar; + ICmpInst *ExitCondition; + ICmpInst *SplitCondition; + Value *IVStartValue; + Value *IVExitValue; + Instruction *IVIncrement; + SmallPtrSet IVBasedValues; + }; +} + +char LoopIndexSplit::ID = 0; +static RegisterPass +X("loop-index-split", "Index Split Loops"); + +Pass *llvm::createLoopIndexSplitPass() { + return new LoopIndexSplit(); +} + +// Index split Loop L. Return true if loop is split. +bool LoopIndexSplit::runOnLoop(Loop *IncomingLoop, LPPassManager &LPM_Ref) { + L = IncomingLoop; + LPM = &LPM_Ref; + + // If LoopSimplify form is not available, stay out of trouble. + if (!L->isLoopSimplifyForm()) + return false; + + // FIXME - Nested loops make dominator info updates tricky. + if (!L->getSubLoops().empty()) + return false; + + DT = &getAnalysis(); + LI = &getAnalysis(); + DF = &getAnalysis(); + + // Initialize loop data. + IndVar = L->getCanonicalInductionVariable(); + if (!IndVar) return false; + + bool P1InLoop = L->contains(IndVar->getIncomingBlock(1)); + IVStartValue = IndVar->getIncomingValue(!P1InLoop); + IVIncrement = dyn_cast(IndVar->getIncomingValue(P1InLoop)); + if (!IVIncrement) return false; + + IVBasedValues.clear(); + IVBasedValues.insert(IndVar); + IVBasedValues.insert(IVIncrement); + for (Loop::block_iterator I = L->block_begin(), E = L->block_end(); + I != E; ++I) + for(BasicBlock::iterator BI = (*I)->begin(), BE = (*I)->end(); + BI != BE; ++BI) { + if (BinaryOperator *BO = dyn_cast(BI)) + if (BO != IVIncrement + && (BO->getOpcode() == Instruction::Add + || BO->getOpcode() == Instruction::Sub)) + if (IVBasedValues.count(BO->getOperand(0)) + && L->isLoopInvariant(BO->getOperand(1))) + IVBasedValues.insert(BO); + } + + // Reject loop if loop exit condition is not suitable. + BasicBlock *ExitingBlock = L->getExitingBlock(); + if (!ExitingBlock) + return false; + BranchInst *EBR = dyn_cast(ExitingBlock->getTerminator()); + if (!EBR) return false; + ExitCondition = dyn_cast(EBR->getCondition()); + if (!ExitCondition) return false; + if (ExitingBlock != L->getLoopLatch()) return false; + IVExitValue = ExitCondition->getOperand(1); + if (!L->isLoopInvariant(IVExitValue)) + IVExitValue = ExitCondition->getOperand(0); + if (!L->isLoopInvariant(IVExitValue)) + return false; + if (!IVBasedValues.count( + ExitCondition->getOperand(IVExitValue == ExitCondition->getOperand(0)))) + return false; + + // If start value is more then exit value where induction variable + // increments by 1 then we are potentially dealing with an infinite loop. + // Do not index split this loop. + if (ConstantInt *SV = dyn_cast(IVStartValue)) + if (ConstantInt *EV = dyn_cast(IVExitValue)) + if (SV->getSExtValue() > EV->getSExtValue()) + return false; + + if (processOneIterationLoop()) + return true; + + if (updateLoopIterationSpace()) + return true; + + if (splitLoop()) + return true; + + return false; +} + +// --- Helper routines --- +// isUsedOutsideLoop - Returns true iff V is used outside the loop L. +static bool isUsedOutsideLoop(Value *V, Loop *L) { + for(Value::use_iterator UI = V->use_begin(), E = V->use_end(); UI != E; ++UI) + if (!L->contains(cast(*UI)->getParent())) + return true; + return false; +} + +// Return V+1 +static Value *getPlusOne(Value *V, bool Sign, Instruction *InsertPt, + LLVMContext &Context) { + Constant *One = ConstantInt::get(V->getType(), 1, Sign); + return BinaryOperator::CreateAdd(V, One, "lsp", InsertPt); +} + +// Return V-1 +static Value *getMinusOne(Value *V, bool Sign, Instruction *InsertPt, + LLVMContext &Context) { + Constant *One = ConstantInt::get(V->getType(), 1, Sign); + return BinaryOperator::CreateSub(V, One, "lsp", InsertPt); +} + +// Return min(V1, V1) +static Value *getMin(Value *V1, Value *V2, bool Sign, Instruction *InsertPt) { + + Value *C = new ICmpInst(InsertPt, + Sign ? ICmpInst::ICMP_SLT : ICmpInst::ICMP_ULT, + V1, V2, "lsp"); + return SelectInst::Create(C, V1, V2, "lsp", InsertPt); +} + +// Return max(V1, V2) +static Value *getMax(Value *V1, Value *V2, bool Sign, Instruction *InsertPt) { + + Value *C = new ICmpInst(InsertPt, + Sign ? ICmpInst::ICMP_SLT : ICmpInst::ICMP_ULT, + V1, V2, "lsp"); + return SelectInst::Create(C, V2, V1, "lsp", InsertPt); +} + +/// processOneIterationLoop -- Eliminate loop if loop body is executed +/// only once. For example, +/// for (i = 0; i < N; ++i) { +/// if ( i == X) { +/// ... +/// } +/// } +/// +bool LoopIndexSplit::processOneIterationLoop() { + SplitCondition = NULL; + BasicBlock *Latch = L->getLoopLatch(); + BasicBlock *Header = L->getHeader(); + BranchInst *BR = dyn_cast(Header->getTerminator()); + if (!BR) return false; + if (!isa(Latch->getTerminator())) return false; + if (BR->isUnconditional()) return false; + SplitCondition = dyn_cast(BR->getCondition()); + if (!SplitCondition) return false; + if (SplitCondition == ExitCondition) return false; + if (SplitCondition->getPredicate() != ICmpInst::ICMP_EQ) return false; + if (BR->getOperand(1) != Latch) return false; + if (!IVBasedValues.count(SplitCondition->getOperand(0)) + && !IVBasedValues.count(SplitCondition->getOperand(1))) + return false; + + // If IV is used outside the loop then this loop traversal is required. + // FIXME: Calculate and use last IV value. + if (isUsedOutsideLoop(IVIncrement, L)) + return false; + + // If BR operands are not IV or not loop invariants then skip this loop. + Value *OPV = SplitCondition->getOperand(0); + Value *SplitValue = SplitCondition->getOperand(1); + if (!L->isLoopInvariant(SplitValue)) + std::swap(OPV, SplitValue); + if (!L->isLoopInvariant(SplitValue)) + return false; + Instruction *OPI = dyn_cast(OPV); + if (!OPI) + return false; + if (OPI->getParent() != Header || isUsedOutsideLoop(OPI, L)) + return false; + Value *StartValue = IVStartValue; + Value *ExitValue = IVExitValue;; + + if (OPV != IndVar) { + // If BR operand is IV based then use this operand to calculate + // effective conditions for loop body. + BinaryOperator *BOPV = dyn_cast(OPV); + if (!BOPV) + return false; + if (BOPV->getOpcode() != Instruction::Add) + return false; + StartValue = BinaryOperator::CreateAdd(OPV, StartValue, "" , BR); + ExitValue = BinaryOperator::CreateAdd(OPV, ExitValue, "" , BR); + } + + if (!cleanBlock(Header)) + return false; + + if (!cleanBlock(Latch)) + return false; + + // If the merge point for BR is not loop latch then skip this loop. + if (BR->getSuccessor(0) != Latch) { + DominanceFrontier::iterator DF0 = DF->find(BR->getSuccessor(0)); + assert (DF0 != DF->end() && "Unable to find dominance frontier"); + if (!DF0->second.count(Latch)) + return false; + } + + if (BR->getSuccessor(1) != Latch) { + DominanceFrontier::iterator DF1 = DF->find(BR->getSuccessor(1)); + assert (DF1 != DF->end() && "Unable to find dominance frontier"); + if (!DF1->second.count(Latch)) + return false; + } + + // Now, Current loop L contains compare instruction + // that compares induction variable, IndVar, against loop invariant. And + // entire (i.e. meaningful) loop body is dominated by this compare + // instruction. In such case eliminate + // loop structure surrounding this loop body. For example, + // for (int i = start; i < end; ++i) { + // if ( i == somevalue) { + // loop_body + // } + // } + // can be transformed into + // if (somevalue >= start && somevalue < end) { + // i = somevalue; + // loop_body + // } + + // Replace index variable with split value in loop body. Loop body is executed + // only when index variable is equal to split value. + IndVar->replaceAllUsesWith(SplitValue); + + // Replace split condition in header. + // Transform + // SplitCondition : icmp eq i32 IndVar, SplitValue + // into + // c1 = icmp uge i32 SplitValue, StartValue + // c2 = icmp ult i32 SplitValue, ExitValue + // and i32 c1, c2 + Instruction *C1 = new ICmpInst(BR, ExitCondition->isSigned() ? + ICmpInst::ICMP_SGE : ICmpInst::ICMP_UGE, + SplitValue, StartValue, "lisplit"); + + CmpInst::Predicate C2P = ExitCondition->getPredicate(); + BranchInst *LatchBR = cast(Latch->getTerminator()); + if (LatchBR->getOperand(1) != Header) + C2P = CmpInst::getInversePredicate(C2P); + Instruction *C2 = new ICmpInst(BR, C2P, SplitValue, ExitValue, "lisplit"); + Instruction *NSplitCond = BinaryOperator::CreateAnd(C1, C2, "lisplit", BR); + + SplitCondition->replaceAllUsesWith(NSplitCond); + SplitCondition->eraseFromParent(); + + // Remove Latch to Header edge. + BasicBlock *LatchSucc = NULL; + Header->removePredecessor(Latch); + for (succ_iterator SI = succ_begin(Latch), E = succ_end(Latch); + SI != E; ++SI) { + if (Header != *SI) + LatchSucc = *SI; + } + + // Clean up latch block. + Value *LatchBRCond = LatchBR->getCondition(); + LatchBR->setUnconditionalDest(LatchSucc); + RecursivelyDeleteTriviallyDeadInstructions(LatchBRCond); + + LPM->deleteLoopFromQueue(L); + + // Update Dominator Info. + // Only CFG change done is to remove Latch to Header edge. This + // does not change dominator tree because Latch did not dominate + // Header. + if (DF) { + DominanceFrontier::iterator HeaderDF = DF->find(Header); + if (HeaderDF != DF->end()) + DF->removeFromFrontier(HeaderDF, Header); + + DominanceFrontier::iterator LatchDF = DF->find(Latch); + if (LatchDF != DF->end()) + DF->removeFromFrontier(LatchDF, Header); + } + + ++NumIndexSplitRemoved; + return true; +} + +/// restrictLoopBound - Op dominates loop body. Op compares an IV based value +/// with a loop invariant value. Update loop's lower and upper bound based on +/// the loop invariant value. +bool LoopIndexSplit::restrictLoopBound(ICmpInst &Op) { + bool Sign = Op.isSigned(); + Instruction *PHTerm = L->getLoopPreheader()->getTerminator(); + + if (IVisGT(*ExitCondition) || IVisGE(*ExitCondition)) { + BranchInst *EBR = + cast(ExitCondition->getParent()->getTerminator()); + ExitCondition->setPredicate(ExitCondition->getInversePredicate()); + BasicBlock *T = EBR->getSuccessor(0); + EBR->setSuccessor(0, EBR->getSuccessor(1)); + EBR->setSuccessor(1, T); + } + + LLVMContext &Context = Op.getContext(); + + // New upper and lower bounds. + Value *NLB = NULL; + Value *NUB = NULL; + if (Value *V = IVisLT(Op)) { + // Restrict upper bound. + if (IVisLE(*ExitCondition)) + V = getMinusOne(V, Sign, PHTerm, Context); + NUB = getMin(V, IVExitValue, Sign, PHTerm); + } else if (Value *V = IVisLE(Op)) { + // Restrict upper bound. + if (IVisLT(*ExitCondition)) + V = getPlusOne(V, Sign, PHTerm, Context); + NUB = getMin(V, IVExitValue, Sign, PHTerm); + } else if (Value *V = IVisGT(Op)) { + // Restrict lower bound. + V = getPlusOne(V, Sign, PHTerm, Context); + NLB = getMax(V, IVStartValue, Sign, PHTerm); + } else if (Value *V = IVisGE(Op)) + // Restrict lower bound. + NLB = getMax(V, IVStartValue, Sign, PHTerm); + + if (!NLB && !NUB) + return false; + + if (NLB) { + unsigned i = IndVar->getBasicBlockIndex(L->getLoopPreheader()); + IndVar->setIncomingValue(i, NLB); + } + + if (NUB) { + unsigned i = (ExitCondition->getOperand(0) != IVExitValue); + ExitCondition->setOperand(i, NUB); + } + return true; +} + +/// updateLoopIterationSpace -- Update loop's iteration space if loop +/// body is executed for certain IV range only. For example, +/// +/// for (i = 0; i < N; ++i) { +/// if ( i > A && i < B) { +/// ... +/// } +/// } +/// is transformed to iterators from A to B, if A > 0 and B < N. +/// +bool LoopIndexSplit::updateLoopIterationSpace() { + SplitCondition = NULL; + if (ExitCondition->getPredicate() == ICmpInst::ICMP_NE + || ExitCondition->getPredicate() == ICmpInst::ICMP_EQ) + return false; + BasicBlock *Latch = L->getLoopLatch(); + BasicBlock *Header = L->getHeader(); + BranchInst *BR = dyn_cast(Header->getTerminator()); + if (!BR) return false; + if (!isa(Latch->getTerminator())) return false; + if (BR->isUnconditional()) return false; + BinaryOperator *AND = dyn_cast(BR->getCondition()); + if (!AND) return false; + if (AND->getOpcode() != Instruction::And) return false; + ICmpInst *Op0 = dyn_cast(AND->getOperand(0)); + ICmpInst *Op1 = dyn_cast(AND->getOperand(1)); + if (!Op0 || !Op1) + return false; + IVBasedValues.insert(AND); + IVBasedValues.insert(Op0); + IVBasedValues.insert(Op1); + if (!cleanBlock(Header)) return false; + BasicBlock *ExitingBlock = ExitCondition->getParent(); + if (!cleanBlock(ExitingBlock)) return false; + + // If the merge point for BR is not loop latch then skip this loop. + if (BR->getSuccessor(0) != Latch) { + DominanceFrontier::iterator DF0 = DF->find(BR->getSuccessor(0)); + assert (DF0 != DF->end() && "Unable to find dominance frontier"); + if (!DF0->second.count(Latch)) + return false; + } + + if (BR->getSuccessor(1) != Latch) { + DominanceFrontier::iterator DF1 = DF->find(BR->getSuccessor(1)); + assert (DF1 != DF->end() && "Unable to find dominance frontier"); + if (!DF1->second.count(Latch)) + return false; + } + + // Verify that loop exiting block has only two predecessor, where one pred + // is split condition block. The other predecessor will become exiting block's + // dominator after CFG is updated. TODO : Handle CFG's where exiting block has + // more then two predecessors. This requires extra work in updating dominator + // information. + BasicBlock *ExitingBBPred = NULL; + for (pred_iterator PI = pred_begin(ExitingBlock), PE = pred_end(ExitingBlock); + PI != PE; ++PI) { + BasicBlock *BB = *PI; + if (Header == BB) + continue; + if (ExitingBBPred) + return false; + else + ExitingBBPred = BB; + } + + if (!restrictLoopBound(*Op0)) + return false; + + if (!restrictLoopBound(*Op1)) + return false; + + // Update CFG. + if (BR->getSuccessor(0) == ExitingBlock) + BR->setUnconditionalDest(BR->getSuccessor(1)); + else + BR->setUnconditionalDest(BR->getSuccessor(0)); + + AND->eraseFromParent(); + if (Op0->use_empty()) + Op0->eraseFromParent(); + if (Op1->use_empty()) + Op1->eraseFromParent(); + + // Update domiantor info. Now, ExitingBlock has only one predecessor, + // ExitingBBPred, and it is ExitingBlock's immediate domiantor. + DT->changeImmediateDominator(ExitingBlock, ExitingBBPred); + + BasicBlock *ExitBlock = ExitingBlock->getTerminator()->getSuccessor(1); + if (L->contains(ExitBlock)) + ExitBlock = ExitingBlock->getTerminator()->getSuccessor(0); + + // If ExitingBlock is a member of the loop basic blocks' DF list then + // replace ExitingBlock with header and exit block in the DF list + DominanceFrontier::iterator ExitingBlockDF = DF->find(ExitingBlock); + for (Loop::block_iterator I = L->block_begin(), E = L->block_end(); + I != E; ++I) { + BasicBlock *BB = *I; + if (BB == Header || BB == ExitingBlock) + continue; + DominanceFrontier::iterator BBDF = DF->find(BB); + DominanceFrontier::DomSetType::iterator DomSetI = BBDF->second.begin(); + DominanceFrontier::DomSetType::iterator DomSetE = BBDF->second.end(); + while (DomSetI != DomSetE) { + DominanceFrontier::DomSetType::iterator CurrentItr = DomSetI; + ++DomSetI; + BasicBlock *DFBB = *CurrentItr; + if (DFBB == ExitingBlock) { + BBDF->second.erase(DFBB); + for (DominanceFrontier::DomSetType::iterator + EBI = ExitingBlockDF->second.begin(), + EBE = ExitingBlockDF->second.end(); EBI != EBE; ++EBI) + BBDF->second.insert(*EBI); + } + } + } + NumRestrictBounds++; + return true; +} + +/// removeBlocks - Remove basic block DeadBB and all blocks dominated by DeadBB. +/// This routine is used to remove split condition's dead branch, dominated by +/// DeadBB. LiveBB dominates split conidition's other branch. +void LoopIndexSplit::removeBlocks(BasicBlock *DeadBB, Loop *LP, + BasicBlock *LiveBB) { + + // First update DeadBB's dominance frontier. + SmallVector FrontierBBs; + DominanceFrontier::iterator DeadBBDF = DF->find(DeadBB); + if (DeadBBDF != DF->end()) { + SmallVector PredBlocks; + + DominanceFrontier::DomSetType DeadBBSet = DeadBBDF->second; + for (DominanceFrontier::DomSetType::iterator DeadBBSetI = DeadBBSet.begin(), + DeadBBSetE = DeadBBSet.end(); DeadBBSetI != DeadBBSetE; ++DeadBBSetI) + { + BasicBlock *FrontierBB = *DeadBBSetI; + FrontierBBs.push_back(FrontierBB); + + // Rremove any PHI incoming edge from blocks dominated by DeadBB. + PredBlocks.clear(); + for(pred_iterator PI = pred_begin(FrontierBB), PE = pred_end(FrontierBB); + PI != PE; ++PI) { + BasicBlock *P = *PI; + if (P == DeadBB || DT->dominates(DeadBB, P)) + PredBlocks.push_back(P); + } + + for(BasicBlock::iterator FBI = FrontierBB->begin(), FBE = FrontierBB->end(); + FBI != FBE; ++FBI) { + if (PHINode *PN = dyn_cast(FBI)) { + for(SmallVector::iterator PI = PredBlocks.begin(), + PE = PredBlocks.end(); PI != PE; ++PI) { + BasicBlock *P = *PI; + PN->removeIncomingValue(P); + } + } + else + break; + } + } + } + + // Now remove DeadBB and all nodes dominated by DeadBB in df order. + SmallVector WorkList; + DomTreeNode *DN = DT->getNode(DeadBB); + for (df_iterator DI = df_begin(DN), + E = df_end(DN); DI != E; ++DI) { + BasicBlock *BB = DI->getBlock(); + WorkList.push_back(BB); + BB->replaceAllUsesWith(UndefValue::get( + Type::getLabelTy(DeadBB->getContext()))); + } + + while (!WorkList.empty()) { + BasicBlock *BB = WorkList.back(); WorkList.pop_back(); + LPM->deleteSimpleAnalysisValue(BB, LP); + for(BasicBlock::iterator BBI = BB->begin(), BBE = BB->end(); + BBI != BBE; ) { + Instruction *I = BBI; + ++BBI; + I->replaceAllUsesWith(UndefValue::get(I->getType())); + LPM->deleteSimpleAnalysisValue(I, LP); + I->eraseFromParent(); + } + DT->eraseNode(BB); + DF->removeBlock(BB); + LI->removeBlock(BB); + BB->eraseFromParent(); + } + + // Update Frontier BBs' dominator info. + while (!FrontierBBs.empty()) { + BasicBlock *FBB = FrontierBBs.back(); FrontierBBs.pop_back(); + BasicBlock *NewDominator = FBB->getSinglePredecessor(); + if (!NewDominator) { + pred_iterator PI = pred_begin(FBB), PE = pred_end(FBB); + NewDominator = *PI; + ++PI; + if (NewDominator != LiveBB) { + for(; PI != PE; ++PI) { + BasicBlock *P = *PI; + if (P == LiveBB) { + NewDominator = LiveBB; + break; + } + NewDominator = DT->findNearestCommonDominator(NewDominator, P); + } + } + } + assert (NewDominator && "Unable to fix dominator info."); + DT->changeImmediateDominator(FBB, NewDominator); + DF->changeImmediateDominator(FBB, NewDominator, DT); + } + +} + +// moveExitCondition - Move exit condition EC into split condition block CondBB. +void LoopIndexSplit::moveExitCondition(BasicBlock *CondBB, BasicBlock *ActiveBB, + BasicBlock *ExitBB, ICmpInst *EC, + ICmpInst *SC, PHINode *IV, + Instruction *IVAdd, Loop *LP, + unsigned ExitValueNum) { + + BasicBlock *ExitingBB = EC->getParent(); + Instruction *CurrentBR = CondBB->getTerminator(); + + // Move exit condition into split condition block. + EC->moveBefore(CurrentBR); + EC->setOperand(ExitValueNum == 0 ? 1 : 0, IV); + + // Move exiting block's branch into split condition block. Update its branch + // destination. + BranchInst *ExitingBR = cast(ExitingBB->getTerminator()); + ExitingBR->moveBefore(CurrentBR); + BasicBlock *OrigDestBB = NULL; + if (ExitingBR->getSuccessor(0) == ExitBB) { + OrigDestBB = ExitingBR->getSuccessor(1); + ExitingBR->setSuccessor(1, ActiveBB); + } + else { + OrigDestBB = ExitingBR->getSuccessor(0); + ExitingBR->setSuccessor(0, ActiveBB); + } + + // Remove split condition and current split condition branch. + SC->eraseFromParent(); + CurrentBR->eraseFromParent(); + + // Connect exiting block to original destination. + BranchInst::Create(OrigDestBB, ExitingBB); + + // Update PHINodes + updatePHINodes(ExitBB, ExitingBB, CondBB, IV, IVAdd, LP); + + // Fix dominator info. + // ExitBB is now dominated by CondBB + DT->changeImmediateDominator(ExitBB, CondBB); + DF->changeImmediateDominator(ExitBB, CondBB, DT); + + // Blocks outside the loop may have been in the dominance frontier of blocks + // inside the condition; this is now impossible because the blocks inside the + // condition no loger dominate the exit. Remove the relevant blocks from + // the dominance frontiers. + for (Loop::block_iterator I = LP->block_begin(), E = LP->block_end(); + I != E; ++I) { + if (*I == CondBB || !DT->dominates(CondBB, *I)) continue; + DominanceFrontier::iterator BBDF = DF->find(*I); + DominanceFrontier::DomSetType::iterator DomSetI = BBDF->second.begin(); + DominanceFrontier::DomSetType::iterator DomSetE = BBDF->second.end(); + while (DomSetI != DomSetE) { + DominanceFrontier::DomSetType::iterator CurrentItr = DomSetI; + ++DomSetI; + BasicBlock *DFBB = *CurrentItr; + if (!LP->contains(DFBB)) + BBDF->second.erase(DFBB); + } + } +} + +/// updatePHINodes - CFG has been changed. +/// Before +/// - ExitBB's single predecessor was Latch +/// - Latch's second successor was Header +/// Now +/// - ExitBB's single predecessor is Header +/// - Latch's one and only successor is Header +/// +/// Update ExitBB PHINodes' to reflect this change. +void LoopIndexSplit::updatePHINodes(BasicBlock *ExitBB, BasicBlock *Latch, + BasicBlock *Header, + PHINode *IV, Instruction *IVIncrement, + Loop *LP) { + + for (BasicBlock::iterator BI = ExitBB->begin(), BE = ExitBB->end(); + BI != BE; ) { + PHINode *PN = dyn_cast(BI); + ++BI; + if (!PN) + break; + + Value *V = PN->getIncomingValueForBlock(Latch); + if (PHINode *PHV = dyn_cast(V)) { + // PHV is in Latch. PHV has one use is in ExitBB PHINode. And one use + // in Header which is new incoming value for PN. + Value *NewV = NULL; + for (Value::use_iterator UI = PHV->use_begin(), E = PHV->use_end(); + UI != E; ++UI) + if (PHINode *U = dyn_cast(*UI)) + if (LP->contains(U->getParent())) { + NewV = U; + break; + } + + // Add incoming value from header only if PN has any use inside the loop. + if (NewV) + PN->addIncoming(NewV, Header); + + } else if (Instruction *PHI = dyn_cast(V)) { + // If this instruction is IVIncrement then IV is new incoming value + // from header otherwise this instruction must be incoming value from + // header because loop is in LCSSA form. + if (PHI == IVIncrement) + PN->addIncoming(IV, Header); + else + PN->addIncoming(V, Header); + } else + // Otherwise this is an incoming value from header because loop is in + // LCSSA form. + PN->addIncoming(V, Header); + + // Remove incoming value from Latch. + PN->removeIncomingValue(Latch); + } +} + +bool LoopIndexSplit::splitLoop() { + SplitCondition = NULL; + if (ExitCondition->getPredicate() == ICmpInst::ICMP_NE + || ExitCondition->getPredicate() == ICmpInst::ICMP_EQ) + return false; + BasicBlock *Header = L->getHeader(); + BasicBlock *Latch = L->getLoopLatch(); + BranchInst *SBR = NULL; // Split Condition Branch + BranchInst *EBR = cast(ExitCondition->getParent()->getTerminator()); + // If Exiting block includes loop variant instructions then this + // loop may not be split safely. + BasicBlock *ExitingBlock = ExitCondition->getParent(); + if (!cleanBlock(ExitingBlock)) return false; + + LLVMContext &Context = Header->getContext(); + + for (Loop::block_iterator I = L->block_begin(), E = L->block_end(); + I != E; ++I) { + BranchInst *BR = dyn_cast((*I)->getTerminator()); + if (!BR || BR->isUnconditional()) continue; + ICmpInst *CI = dyn_cast(BR->getCondition()); + if (!CI || CI == ExitCondition + || CI->getPredicate() == ICmpInst::ICMP_NE + || CI->getPredicate() == ICmpInst::ICMP_EQ) + continue; + + // Unable to handle triangle loops at the moment. + // In triangle loop, split condition is in header and one of the + // the split destination is loop latch. If split condition is EQ + // then such loops are already handle in processOneIterationLoop(). + if (Header == (*I) + && (Latch == BR->getSuccessor(0) || Latch == BR->getSuccessor(1))) + continue; + + // If the block does not dominate the latch then this is not a diamond. + // Such loop may not benefit from index split. + if (!DT->dominates((*I), Latch)) + continue; + + // If split condition branches heads do not have single predecessor, + // SplitCondBlock, then is not possible to remove inactive branch. + if (!BR->getSuccessor(0)->getSinglePredecessor() + || !BR->getSuccessor(1)->getSinglePredecessor()) + return false; + + // If the merge point for BR is not loop latch then skip this condition. + if (BR->getSuccessor(0) != Latch) { + DominanceFrontier::iterator DF0 = DF->find(BR->getSuccessor(0)); + assert (DF0 != DF->end() && "Unable to find dominance frontier"); + if (!DF0->second.count(Latch)) + continue; + } + + if (BR->getSuccessor(1) != Latch) { + DominanceFrontier::iterator DF1 = DF->find(BR->getSuccessor(1)); + assert (DF1 != DF->end() && "Unable to find dominance frontier"); + if (!DF1->second.count(Latch)) + continue; + } + SplitCondition = CI; + SBR = BR; + break; + } + + if (!SplitCondition) + return false; + + // If the predicate sign does not match then skip. + if (ExitCondition->isSigned() != SplitCondition->isSigned()) + return false; + + unsigned EVOpNum = (ExitCondition->getOperand(1) == IVExitValue); + unsigned SVOpNum = IVBasedValues.count(SplitCondition->getOperand(0)); + Value *SplitValue = SplitCondition->getOperand(SVOpNum); + if (!L->isLoopInvariant(SplitValue)) + return false; + if (!IVBasedValues.count(SplitCondition->getOperand(!SVOpNum))) + return false; + + // Normalize loop conditions so that it is easier to calculate new loop + // bounds. + if (IVisGT(*ExitCondition) || IVisGE(*ExitCondition)) { + ExitCondition->setPredicate(ExitCondition->getInversePredicate()); + BasicBlock *T = EBR->getSuccessor(0); + EBR->setSuccessor(0, EBR->getSuccessor(1)); + EBR->setSuccessor(1, T); + } + + if (IVisGT(*SplitCondition) || IVisGE(*SplitCondition)) { + SplitCondition->setPredicate(SplitCondition->getInversePredicate()); + BasicBlock *T = SBR->getSuccessor(0); + SBR->setSuccessor(0, SBR->getSuccessor(1)); + SBR->setSuccessor(1, T); + } + + //[*] Calculate new loop bounds. + Value *AEV = SplitValue; + Value *BSV = SplitValue; + bool Sign = SplitCondition->isSigned(); + Instruction *PHTerm = L->getLoopPreheader()->getTerminator(); + + if (IVisLT(*ExitCondition)) { + if (IVisLT(*SplitCondition)) { + /* Do nothing */ + } + else if (IVisLE(*SplitCondition)) { + AEV = getPlusOne(SplitValue, Sign, PHTerm, Context); + BSV = getPlusOne(SplitValue, Sign, PHTerm, Context); + } else { + assert (0 && "Unexpected split condition!"); + } + } + else if (IVisLE(*ExitCondition)) { + if (IVisLT(*SplitCondition)) { + AEV = getMinusOne(SplitValue, Sign, PHTerm, Context); + } + else if (IVisLE(*SplitCondition)) { + BSV = getPlusOne(SplitValue, Sign, PHTerm, Context); + } else { + assert (0 && "Unexpected split condition!"); + } + } else { + assert (0 && "Unexpected exit condition!"); + } + AEV = getMin(AEV, IVExitValue, Sign, PHTerm); + BSV = getMax(BSV, IVStartValue, Sign, PHTerm); + + // [*] Clone Loop + DenseMap ValueMap; + Loop *BLoop = CloneLoop(L, LPM, LI, ValueMap, this); + Loop *ALoop = L; + + // [*] ALoop's exiting edge enters BLoop's header. + // ALoop's original exit block becomes BLoop's exit block. + PHINode *B_IndVar = cast(ValueMap[IndVar]); + BasicBlock *A_ExitingBlock = ExitCondition->getParent(); + BranchInst *A_ExitInsn = + dyn_cast(A_ExitingBlock->getTerminator()); + assert (A_ExitInsn && "Unable to find suitable loop exit branch"); + BasicBlock *B_ExitBlock = A_ExitInsn->getSuccessor(1); + BasicBlock *B_Header = BLoop->getHeader(); + if (ALoop->contains(B_ExitBlock)) { + B_ExitBlock = A_ExitInsn->getSuccessor(0); + A_ExitInsn->setSuccessor(0, B_Header); + } else + A_ExitInsn->setSuccessor(1, B_Header); + + // [*] Update ALoop's exit value using new exit value. + ExitCondition->setOperand(EVOpNum, AEV); + + // [*] Update BLoop's header phi nodes. Remove incoming PHINode's from + // original loop's preheader. Add incoming PHINode values from + // ALoop's exiting block. Update BLoop header's domiantor info. + + // Collect inverse map of Header PHINodes. + DenseMap InverseMap; + for (BasicBlock::iterator BI = ALoop->getHeader()->begin(), + BE = ALoop->getHeader()->end(); BI != BE; ++BI) { + if (PHINode *PN = dyn_cast(BI)) { + PHINode *PNClone = cast(ValueMap[PN]); + InverseMap[PNClone] = PN; + } else + break; + } + + BasicBlock *A_Preheader = ALoop->getLoopPreheader(); + for (BasicBlock::iterator BI = B_Header->begin(), BE = B_Header->end(); + BI != BE; ++BI) { + if (PHINode *PN = dyn_cast(BI)) { + // Remove incoming value from original preheader. + PN->removeIncomingValue(A_Preheader); + + // Add incoming value from A_ExitingBlock. + if (PN == B_IndVar) + PN->addIncoming(BSV, A_ExitingBlock); + else { + PHINode *OrigPN = cast(InverseMap[PN]); + Value *V2 = NULL; + // If loop header is also loop exiting block then + // OrigPN is incoming value for B loop header. + if (A_ExitingBlock == ALoop->getHeader()) + V2 = OrigPN; + else + V2 = OrigPN->getIncomingValueForBlock(A_ExitingBlock); + PN->addIncoming(V2, A_ExitingBlock); + } + } else + break; + } + + DT->changeImmediateDominator(B_Header, A_ExitingBlock); + DF->changeImmediateDominator(B_Header, A_ExitingBlock, DT); + + // [*] Update BLoop's exit block. Its new predecessor is BLoop's exit + // block. Remove incoming PHINode values from ALoop's exiting block. + // Add new incoming values from BLoop's incoming exiting value. + // Update BLoop exit block's dominator info.. + BasicBlock *B_ExitingBlock = cast(ValueMap[A_ExitingBlock]); + for (BasicBlock::iterator BI = B_ExitBlock->begin(), BE = B_ExitBlock->end(); + BI != BE; ++BI) { + if (PHINode *PN = dyn_cast(BI)) { + PN->addIncoming(ValueMap[PN->getIncomingValueForBlock(A_ExitingBlock)], + B_ExitingBlock); + PN->removeIncomingValue(A_ExitingBlock); + } else + break; + } + + DT->changeImmediateDominator(B_ExitBlock, B_ExitingBlock); + DF->changeImmediateDominator(B_ExitBlock, B_ExitingBlock, DT); + + //[*] Split ALoop's exit edge. This creates a new block which + // serves two purposes. First one is to hold PHINode defnitions + // to ensure that ALoop's LCSSA form. Second use it to act + // as a preheader for BLoop. + BasicBlock *A_ExitBlock = SplitEdge(A_ExitingBlock, B_Header, this); + + //[*] Preserve ALoop's LCSSA form. Create new forwarding PHINodes + // in A_ExitBlock to redefine outgoing PHI definitions from ALoop. + for(BasicBlock::iterator BI = B_Header->begin(), BE = B_Header->end(); + BI != BE; ++BI) { + if (PHINode *PN = dyn_cast(BI)) { + Value *V1 = PN->getIncomingValueForBlock(A_ExitBlock); + PHINode *newPHI = PHINode::Create(PN->getType(), PN->getName()); + newPHI->addIncoming(V1, A_ExitingBlock); + A_ExitBlock->getInstList().push_front(newPHI); + PN->removeIncomingValue(A_ExitBlock); + PN->addIncoming(newPHI, A_ExitBlock); + } else + break; + } + + //[*] Eliminate split condition's inactive branch from ALoop. + BasicBlock *A_SplitCondBlock = SplitCondition->getParent(); + BranchInst *A_BR = cast(A_SplitCondBlock->getTerminator()); + BasicBlock *A_InactiveBranch = NULL; + BasicBlock *A_ActiveBranch = NULL; + A_ActiveBranch = A_BR->getSuccessor(0); + A_InactiveBranch = A_BR->getSuccessor(1); + A_BR->setUnconditionalDest(A_ActiveBranch); + removeBlocks(A_InactiveBranch, L, A_ActiveBranch); + + //[*] Eliminate split condition's inactive branch in from BLoop. + BasicBlock *B_SplitCondBlock = cast(ValueMap[A_SplitCondBlock]); + BranchInst *B_BR = cast(B_SplitCondBlock->getTerminator()); + BasicBlock *B_InactiveBranch = NULL; + BasicBlock *B_ActiveBranch = NULL; + B_ActiveBranch = B_BR->getSuccessor(1); + B_InactiveBranch = B_BR->getSuccessor(0); + B_BR->setUnconditionalDest(B_ActiveBranch); + removeBlocks(B_InactiveBranch, BLoop, B_ActiveBranch); + + BasicBlock *A_Header = ALoop->getHeader(); + if (A_ExitingBlock == A_Header) + return true; + + //[*] Move exit condition into split condition block to avoid + // executing dead loop iteration. + ICmpInst *B_ExitCondition = cast(ValueMap[ExitCondition]); + Instruction *B_IndVarIncrement = cast(ValueMap[IVIncrement]); + ICmpInst *B_SplitCondition = cast(ValueMap[SplitCondition]); + + moveExitCondition(A_SplitCondBlock, A_ActiveBranch, A_ExitBlock, ExitCondition, + cast(SplitCondition), IndVar, IVIncrement, + ALoop, EVOpNum); + + moveExitCondition(B_SplitCondBlock, B_ActiveBranch, + B_ExitBlock, B_ExitCondition, + B_SplitCondition, B_IndVar, B_IndVarIncrement, + BLoop, EVOpNum); + + NumIndexSplit++; + return true; +} + +/// cleanBlock - A block is considered clean if all non terminal instructions +/// are either, PHINodes, IV based. +bool LoopIndexSplit::cleanBlock(BasicBlock *BB) { + Instruction *Terminator = BB->getTerminator(); + for(BasicBlock::iterator BI = BB->begin(), BE = BB->end(); + BI != BE; ++BI) { + Instruction *I = BI; + + if (isa(I) || I == Terminator || I == ExitCondition + || I == SplitCondition || IVBasedValues.count(I) + || isa(I)) + continue; + + if (I->mayHaveSideEffects()) + return false; + + // I is used only inside this block then it is OK. + bool usedOutsideBB = false; + for (Value::use_iterator UI = I->use_begin(), UE = I->use_end(); + UI != UE; ++UI) { + Instruction *U = cast(UI); + if (U->getParent() != BB) + usedOutsideBB = true; + } + if (!usedOutsideBB) + continue; + + // Otherwise we have a instruction that may not allow loop spliting. + return false; + } + return true; +} + +/// IVisLT - If Op is comparing IV based value with an loop invariant and +/// IV based value is less than the loop invariant then return the loop +/// invariant. Otherwise return NULL. +Value * LoopIndexSplit::IVisLT(ICmpInst &Op) { + ICmpInst::Predicate P = Op.getPredicate(); + if ((P == ICmpInst::ICMP_SLT || P == ICmpInst::ICMP_ULT) + && IVBasedValues.count(Op.getOperand(0)) + && L->isLoopInvariant(Op.getOperand(1))) + return Op.getOperand(1); + + if ((P == ICmpInst::ICMP_SGT || P == ICmpInst::ICMP_UGT) + && IVBasedValues.count(Op.getOperand(1)) + && L->isLoopInvariant(Op.getOperand(0))) + return Op.getOperand(0); + + return NULL; +} + +/// IVisLE - If Op is comparing IV based value with an loop invariant and +/// IV based value is less than or equal to the loop invariant then +/// return the loop invariant. Otherwise return NULL. +Value * LoopIndexSplit::IVisLE(ICmpInst &Op) { + ICmpInst::Predicate P = Op.getPredicate(); + if ((P == ICmpInst::ICMP_SLE || P == ICmpInst::ICMP_ULE) + && IVBasedValues.count(Op.getOperand(0)) + && L->isLoopInvariant(Op.getOperand(1))) + return Op.getOperand(1); + + if ((P == ICmpInst::ICMP_SGE || P == ICmpInst::ICMP_UGE) + && IVBasedValues.count(Op.getOperand(1)) + && L->isLoopInvariant(Op.getOperand(0))) + return Op.getOperand(0); + + return NULL; +} + +/// IVisGT - If Op is comparing IV based value with an loop invariant and +/// IV based value is greater than the loop invariant then return the loop +/// invariant. Otherwise return NULL. +Value * LoopIndexSplit::IVisGT(ICmpInst &Op) { + ICmpInst::Predicate P = Op.getPredicate(); + if ((P == ICmpInst::ICMP_SGT || P == ICmpInst::ICMP_UGT) + && IVBasedValues.count(Op.getOperand(0)) + && L->isLoopInvariant(Op.getOperand(1))) + return Op.getOperand(1); + + if ((P == ICmpInst::ICMP_SLT || P == ICmpInst::ICMP_ULT) + && IVBasedValues.count(Op.getOperand(1)) + && L->isLoopInvariant(Op.getOperand(0))) + return Op.getOperand(0); + + return NULL; +} + +/// IVisGE - If Op is comparing IV based value with an loop invariant and +/// IV based value is greater than or equal to the loop invariant then +/// return the loop invariant. Otherwise return NULL. +Value * LoopIndexSplit::IVisGE(ICmpInst &Op) { + ICmpInst::Predicate P = Op.getPredicate(); + if ((P == ICmpInst::ICMP_SGE || P == ICmpInst::ICMP_UGE) + && IVBasedValues.count(Op.getOperand(0)) + && L->isLoopInvariant(Op.getOperand(1))) + return Op.getOperand(1); + + if ((P == ICmpInst::ICMP_SLE || P == ICmpInst::ICMP_ULE) + && IVBasedValues.count(Op.getOperand(1)) + && L->isLoopInvariant(Op.getOperand(0))) + return Op.getOperand(0); + + return NULL; +} + diff --git a/libclamav/c++/llvm/lib/Transforms/Scalar/LoopRotation.cpp b/libclamav/c++/llvm/lib/Transforms/Scalar/LoopRotation.cpp new file mode 100644 index 000000000..5004483e0 --- /dev/null +++ b/libclamav/c++/llvm/lib/Transforms/Scalar/LoopRotation.cpp @@ -0,0 +1,403 @@ +//===- LoopRotation.cpp - Loop Rotation Pass ------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements Loop Rotation Pass. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "loop-rotate" +#include "llvm/Transforms/Scalar.h" +#include "llvm/Function.h" +#include "llvm/IntrinsicInst.h" +#include "llvm/Analysis/LoopPass.h" +#include "llvm/Analysis/Dominators.h" +#include "llvm/Analysis/ScalarEvolution.h" +#include "llvm/Transforms/Utils/Local.h" +#include "llvm/Transforms/Utils/BasicBlockUtils.h" +#include "llvm/Transforms/Utils/SSAUpdater.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/ADT/SmallVector.h" +using namespace llvm; + +#define MAX_HEADER_SIZE 16 + +STATISTIC(NumRotated, "Number of loops rotated"); +namespace { + + class LoopRotate : public LoopPass { + public: + static char ID; // Pass ID, replacement for typeid + LoopRotate() : LoopPass(&ID) {} + + // Rotate Loop L as many times as possible. Return true if + // loop is rotated at least once. + bool runOnLoop(Loop *L, LPPassManager &LPM); + + // LCSSA form makes instruction renaming easier. + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.addRequiredID(LoopSimplifyID); + AU.addPreservedID(LoopSimplifyID); + AU.addRequiredID(LCSSAID); + AU.addPreservedID(LCSSAID); + AU.addPreserved(); + AU.addRequired(); + AU.addPreserved(); + AU.addPreserved(); + AU.addPreserved(); + } + + // Helper functions + + /// Do actual work + bool rotateLoop(Loop *L, LPPassManager &LPM); + + /// Initialize local data + void initialize(); + + /// After loop rotation, loop pre-header has multiple sucessors. + /// Insert one forwarding basic block to ensure that loop pre-header + /// has only one successor. + void preserveCanonicalLoopForm(LPPassManager &LPM); + + private: + Loop *L; + BasicBlock *OrigHeader; + BasicBlock *OrigPreHeader; + BasicBlock *OrigLatch; + BasicBlock *NewHeader; + BasicBlock *Exit; + LPPassManager *LPM_Ptr; + }; +} + +char LoopRotate::ID = 0; +static RegisterPass X("loop-rotate", "Rotate Loops"); + +Pass *llvm::createLoopRotatePass() { return new LoopRotate(); } + +/// Rotate Loop L as many times as possible. Return true if +/// the loop is rotated at least once. +bool LoopRotate::runOnLoop(Loop *Lp, LPPassManager &LPM) { + + bool RotatedOneLoop = false; + initialize(); + LPM_Ptr = &LPM; + + // One loop can be rotated multiple times. + while (rotateLoop(Lp,LPM)) { + RotatedOneLoop = true; + initialize(); + } + + return RotatedOneLoop; +} + +/// Rotate loop LP. Return true if the loop is rotated. +bool LoopRotate::rotateLoop(Loop *Lp, LPPassManager &LPM) { + L = Lp; + + OrigPreHeader = L->getLoopPreheader(); + if (!OrigPreHeader) return false; + + OrigLatch = L->getLoopLatch(); + if (!OrigLatch) return false; + + OrigHeader = L->getHeader(); + + // If the loop has only one block then there is not much to rotate. + if (L->getBlocks().size() == 1) + return false; + + // If the loop header is not one of the loop exiting blocks then + // either this loop is already rotated or it is not + // suitable for loop rotation transformations. + if (!L->isLoopExiting(OrigHeader)) + return false; + + BranchInst *BI = dyn_cast(OrigHeader->getTerminator()); + if (!BI) + return false; + assert(BI->isConditional() && "Branch Instruction is not conditional"); + + // Updating PHInodes in loops with multiple exits adds complexity. + // Keep it simple, and restrict loop rotation to loops with one exit only. + // In future, lift this restriction and support for multiple exits if + // required. + SmallVector ExitBlocks; + L->getExitBlocks(ExitBlocks); + if (ExitBlocks.size() > 1) + return false; + + // Check size of original header and reject + // loop if it is very big. + unsigned Size = 0; + + // FIXME: Use common api to estimate size. + for (BasicBlock::const_iterator OI = OrigHeader->begin(), + OE = OrigHeader->end(); OI != OE; ++OI) { + if (isa(OI)) + continue; // PHI nodes don't count. + if (isa(OI)) + continue; // Debug intrinsics don't count as size. + Size++; + } + + if (Size > MAX_HEADER_SIZE) + return false; + + // Now, this loop is suitable for rotation. + + // Anything ScalarEvolution may know about this loop or the PHI nodes + // in its header will soon be invalidated. + if (ScalarEvolution *SE = getAnalysisIfAvailable()) + SE->forgetLoop(L); + + // Find new Loop header. NewHeader is a Header's one and only successor + // that is inside loop. Header's other successor is outside the + // loop. Otherwise loop is not suitable for rotation. + Exit = BI->getSuccessor(0); + NewHeader = BI->getSuccessor(1); + if (L->contains(Exit)) + std::swap(Exit, NewHeader); + assert(NewHeader && "Unable to determine new loop header"); + assert(L->contains(NewHeader) && !L->contains(Exit) && + "Unable to determine loop header and exit blocks"); + + // This code assumes that the new header has exactly one predecessor. + // Remove any single-entry PHI nodes in it. + assert(NewHeader->getSinglePredecessor() && + "New header doesn't have one pred!"); + FoldSingleEntryPHINodes(NewHeader); + + // Begin by walking OrigHeader and populating ValueMap with an entry for + // each Instruction. + BasicBlock::iterator I = OrigHeader->begin(), E = OrigHeader->end(); + DenseMap ValueMap; + + // For PHI nodes, the value available in OldPreHeader is just the + // incoming value from OldPreHeader. + for (; PHINode *PN = dyn_cast(I); ++I) + ValueMap[PN] = PN->getIncomingValue(PN->getBasicBlockIndex(OrigPreHeader)); + + // For the rest of the instructions, create a clone in the OldPreHeader. + TerminatorInst *LoopEntryBranch = OrigPreHeader->getTerminator(); + for (; I != E; ++I) { + Instruction *C = I->clone(); + C->setName(I->getName()); + C->insertBefore(LoopEntryBranch); + ValueMap[I] = C; + } + + // Along with all the other instructions, we just cloned OrigHeader's + // terminator into OrigPreHeader. Fix up the PHI nodes in each of OrigHeader's + // successors by duplicating their incoming values for OrigHeader. + TerminatorInst *TI = OrigHeader->getTerminator(); + for (unsigned i = 0, e = TI->getNumSuccessors(); i != e; ++i) + for (BasicBlock::iterator BI = TI->getSuccessor(i)->begin(); + PHINode *PN = dyn_cast(BI); ++BI) + PN->addIncoming(PN->getIncomingValueForBlock(OrigHeader), OrigPreHeader); + + // Now that OrigPreHeader has a clone of OrigHeader's terminator, remove + // OrigPreHeader's old terminator (the original branch into the loop), and + // remove the corresponding incoming values from the PHI nodes in OrigHeader. + LoopEntryBranch->eraseFromParent(); + for (I = OrigHeader->begin(); PHINode *PN = dyn_cast(I); ++I) + PN->removeIncomingValue(PN->getBasicBlockIndex(OrigPreHeader)); + + // Now fix up users of the instructions in OrigHeader, inserting PHI nodes + // as necessary. + SSAUpdater SSA; + for (I = OrigHeader->begin(); I != E; ++I) { + Value *OrigHeaderVal = I; + Value *OrigPreHeaderVal = ValueMap[OrigHeaderVal]; + + // The value now exits in two versions: the initial value in the preheader + // and the loop "next" value in the original header. + SSA.Initialize(OrigHeaderVal); + SSA.AddAvailableValue(OrigHeader, OrigHeaderVal); + SSA.AddAvailableValue(OrigPreHeader, OrigPreHeaderVal); + + // Visit each use of the OrigHeader instruction. + for (Value::use_iterator UI = OrigHeaderVal->use_begin(), + UE = OrigHeaderVal->use_end(); UI != UE; ) { + // Grab the use before incrementing the iterator. + Use &U = UI.getUse(); + + // Increment the iterator before removing the use from the list. + ++UI; + + // SSAUpdater can't handle a non-PHI use in the same block as an + // earlier def. We can easily handle those cases manually. + Instruction *UserInst = cast(U.getUser()); + if (!isa(UserInst)) { + BasicBlock *UserBB = UserInst->getParent(); + + // The original users in the OrigHeader are already using the + // original definitions. + if (UserBB == OrigHeader) + continue; + + // Users in the OrigPreHeader need to use the value to which the + // original definitions are mapped. + if (UserBB == OrigPreHeader) { + U = OrigPreHeaderVal; + continue; + } + } + + // Anything else can be handled by SSAUpdater. + SSA.RewriteUse(U); + } + } + + // NewHeader is now the header of the loop. + L->moveToHeader(NewHeader); + + preserveCanonicalLoopForm(LPM); + + NumRotated++; + return true; +} + +/// Initialize local data +void LoopRotate::initialize() { + L = NULL; + OrigHeader = NULL; + OrigPreHeader = NULL; + NewHeader = NULL; + Exit = NULL; +} + +/// After loop rotation, loop pre-header has multiple sucessors. +/// Insert one forwarding basic block to ensure that loop pre-header +/// has only one successor. +void LoopRotate::preserveCanonicalLoopForm(LPPassManager &LPM) { + + // Right now original pre-header has two successors, new header and + // exit block. Insert new block between original pre-header and + // new header such that loop's new pre-header has only one successor. + BasicBlock *NewPreHeader = BasicBlock::Create(OrigHeader->getContext(), + "bb.nph", + OrigHeader->getParent(), + NewHeader); + LoopInfo &LI = getAnalysis(); + if (Loop *PL = LI.getLoopFor(OrigPreHeader)) + PL->addBasicBlockToLoop(NewPreHeader, LI.getBase()); + BranchInst::Create(NewHeader, NewPreHeader); + + BranchInst *OrigPH_BI = cast(OrigPreHeader->getTerminator()); + if (OrigPH_BI->getSuccessor(0) == NewHeader) + OrigPH_BI->setSuccessor(0, NewPreHeader); + else { + assert(OrigPH_BI->getSuccessor(1) == NewHeader && + "Unexpected original pre-header terminator"); + OrigPH_BI->setSuccessor(1, NewPreHeader); + } + + PHINode *PN; + for (BasicBlock::iterator I = NewHeader->begin(); + (PN = dyn_cast(I)); ++I) { + int index = PN->getBasicBlockIndex(OrigPreHeader); + assert(index != -1 && "Expected incoming value from Original PreHeader"); + PN->setIncomingBlock(index, NewPreHeader); + assert(PN->getBasicBlockIndex(OrigPreHeader) == -1 && + "Expected only one incoming value from Original PreHeader"); + } + + if (DominatorTree *DT = getAnalysisIfAvailable()) { + DT->addNewBlock(NewPreHeader, OrigPreHeader); + DT->changeImmediateDominator(L->getHeader(), NewPreHeader); + DT->changeImmediateDominator(Exit, OrigPreHeader); + for (Loop::block_iterator BI = L->block_begin(), BE = L->block_end(); + BI != BE; ++BI) { + BasicBlock *B = *BI; + if (L->getHeader() != B) { + DomTreeNode *Node = DT->getNode(B); + if (Node && Node->getBlock() == OrigHeader) + DT->changeImmediateDominator(*BI, L->getHeader()); + } + } + DT->changeImmediateDominator(OrigHeader, OrigLatch); + } + + if (DominanceFrontier *DF = getAnalysisIfAvailable()) { + // New Preheader's dominance frontier is Exit block. + DominanceFrontier::DomSetType NewPHSet; + NewPHSet.insert(Exit); + DF->addBasicBlock(NewPreHeader, NewPHSet); + + // New Header's dominance frontier now includes itself and Exit block + DominanceFrontier::iterator HeadI = DF->find(L->getHeader()); + if (HeadI != DF->end()) { + DominanceFrontier::DomSetType & HeaderSet = HeadI->second; + HeaderSet.clear(); + HeaderSet.insert(L->getHeader()); + HeaderSet.insert(Exit); + } else { + DominanceFrontier::DomSetType HeaderSet; + HeaderSet.insert(L->getHeader()); + HeaderSet.insert(Exit); + DF->addBasicBlock(L->getHeader(), HeaderSet); + } + + // Original header (new Loop Latch)'s dominance frontier is Exit. + DominanceFrontier::iterator LatchI = DF->find(L->getLoopLatch()); + if (LatchI != DF->end()) { + DominanceFrontier::DomSetType &LatchSet = LatchI->second; + LatchSet = LatchI->second; + LatchSet.clear(); + LatchSet.insert(Exit); + } else { + DominanceFrontier::DomSetType LatchSet; + LatchSet.insert(Exit); + DF->addBasicBlock(L->getHeader(), LatchSet); + } + + // If a loop block dominates new loop latch then add to its frontiers + // new header and Exit and remove new latch (which is equal to original + // header). + BasicBlock *NewLatch = L->getLoopLatch(); + + assert(NewLatch == OrigHeader && "NewLatch is inequal to OrigHeader"); + + if (DominatorTree *DT = getAnalysisIfAvailable()) { + for (Loop::block_iterator BI = L->block_begin(), BE = L->block_end(); + BI != BE; ++BI) { + BasicBlock *B = *BI; + if (DT->dominates(B, NewLatch)) { + DominanceFrontier::iterator BDFI = DF->find(B); + if (BDFI != DF->end()) { + DominanceFrontier::DomSetType &BSet = BDFI->second; + BSet.erase(NewLatch); + BSet.insert(L->getHeader()); + BSet.insert(Exit); + } else { + DominanceFrontier::DomSetType BSet; + BSet.insert(L->getHeader()); + BSet.insert(Exit); + DF->addBasicBlock(B, BSet); + } + } + } + } + } + + // Preserve canonical loop form, which means Exit block should + // have only one predecessor. + SplitEdge(L->getLoopLatch(), Exit, this); + + assert(NewHeader && L->getHeader() == NewHeader && + "Invalid loop header after loop rotation"); + assert(NewPreHeader && L->getLoopPreheader() == NewPreHeader && + "Invalid loop preheader after loop rotation"); + assert(L->getLoopLatch() && + "Invalid loop latch after loop rotation"); +} diff --git a/libclamav/c++/llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp b/libclamav/c++/llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp new file mode 100644 index 000000000..564c7ac06 --- /dev/null +++ b/libclamav/c++/llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp @@ -0,0 +1,2810 @@ +//===- LoopStrengthReduce.cpp - Strength Reduce IVs in Loops --------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This transformation analyzes and transforms the induction variables (and +// computations derived from them) into forms suitable for efficient execution +// on the target. +// +// This pass performs a strength reduction on array references inside loops that +// have as one or more of their components the loop induction variable, it +// rewrites expressions to take advantage of scaled-index addressing modes +// available on the target, and it performs a variety of other optimizations +// related to loop induction variables. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "loop-reduce" +#include "llvm/Transforms/Scalar.h" +#include "llvm/Constants.h" +#include "llvm/Instructions.h" +#include "llvm/IntrinsicInst.h" +#include "llvm/Type.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Analysis/Dominators.h" +#include "llvm/Analysis/IVUsers.h" +#include "llvm/Analysis/LoopInfo.h" +#include "llvm/Analysis/LoopPass.h" +#include "llvm/Analysis/ScalarEvolutionExpander.h" +#include "llvm/Transforms/Utils/AddrModeMatcher.h" +#include "llvm/Transforms/Utils/BasicBlockUtils.h" +#include "llvm/Transforms/Utils/Local.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/Support/CFG.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/ValueHandle.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Target/TargetLowering.h" +#include +using namespace llvm; + +STATISTIC(NumReduced , "Number of IV uses strength reduced"); +STATISTIC(NumInserted, "Number of PHIs inserted"); +STATISTIC(NumVariable, "Number of PHIs with variable strides"); +STATISTIC(NumEliminated, "Number of strides eliminated"); +STATISTIC(NumShadow, "Number of Shadow IVs optimized"); +STATISTIC(NumImmSunk, "Number of common expr immediates sunk into uses"); +STATISTIC(NumLoopCond, "Number of loop terminating conds optimized"); +STATISTIC(NumCountZero, "Number of count iv optimized to count toward zero"); + +static cl::opt EnableFullLSRMode("enable-full-lsr", + cl::init(false), + cl::Hidden); + +namespace { + + struct BasedUser; + + /// IVInfo - This structure keeps track of one IV expression inserted during + /// StrengthReduceStridedIVUsers. It contains the stride, the common base, as + /// well as the PHI node and increment value created for rewrite. + struct IVExpr { + const SCEV *Stride; + const SCEV *Base; + PHINode *PHI; + + IVExpr(const SCEV *const stride, const SCEV *const base, PHINode *phi) + : Stride(stride), Base(base), PHI(phi) {} + }; + + /// IVsOfOneStride - This structure keeps track of all IV expression inserted + /// during StrengthReduceStridedIVUsers for a particular stride of the IV. + struct IVsOfOneStride { + std::vector IVs; + + void addIV(const SCEV *const Stride, const SCEV *const Base, PHINode *PHI) { + IVs.push_back(IVExpr(Stride, Base, PHI)); + } + }; + + class LoopStrengthReduce : public LoopPass { + IVUsers *IU; + LoopInfo *LI; + DominatorTree *DT; + ScalarEvolution *SE; + bool Changed; + + /// IVsByStride - Keep track of all IVs that have been inserted for a + /// particular stride. + std::map IVsByStride; + + /// StrideNoReuse - Keep track of all the strides whose ivs cannot be + /// reused (nor should they be rewritten to reuse other strides). + SmallSet StrideNoReuse; + + /// DeadInsts - Keep track of instructions we may have made dead, so that + /// we can remove them after we are done working. + SmallVector DeadInsts; + + /// TLI - Keep a pointer of a TargetLowering to consult for determining + /// transformation profitability. + const TargetLowering *TLI; + + public: + static char ID; // Pass ID, replacement for typeid + explicit LoopStrengthReduce(const TargetLowering *tli = NULL) : + LoopPass(&ID), TLI(tli) { + } + + bool runOnLoop(Loop *L, LPPassManager &LPM); + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + // We split critical edges, so we change the CFG. However, we do update + // many analyses if they are around. + AU.addPreservedID(LoopSimplifyID); + AU.addPreserved(); + AU.addPreserved(); + AU.addPreserved(); + + AU.addRequiredID(LoopSimplifyID); + AU.addRequired(); + AU.addRequired(); + AU.addRequired(); + AU.addPreserved(); + AU.addRequired(); + AU.addPreserved(); + } + + private: + void OptimizeIndvars(Loop *L); + + /// OptimizeLoopTermCond - Change loop terminating condition to use the + /// postinc iv when possible. + void OptimizeLoopTermCond(Loop *L); + + /// OptimizeShadowIV - If IV is used in a int-to-float cast + /// inside the loop then try to eliminate the cast opeation. + void OptimizeShadowIV(Loop *L); + + /// OptimizeMax - Rewrite the loop's terminating condition + /// if it uses a max computation. + ICmpInst *OptimizeMax(Loop *L, ICmpInst *Cond, + IVStrideUse* &CondUse); + + /// OptimizeLoopCountIV - If, after all sharing of IVs, the IV used for + /// deciding when to exit the loop is used only for that purpose, try to + /// rearrange things so it counts down to a test against zero. + bool OptimizeLoopCountIV(Loop *L); + bool OptimizeLoopCountIVOfStride(const SCEV* &Stride, + IVStrideUse* &CondUse, Loop *L); + + /// StrengthReduceIVUsersOfStride - Strength reduce all of the users of a + /// single stride of IV. All of the users may have different starting + /// values, and this may not be the only stride. + void StrengthReduceIVUsersOfStride(const SCEV *const &Stride, + IVUsersOfOneStride &Uses, + Loop *L); + void StrengthReduceIVUsers(Loop *L); + + ICmpInst *ChangeCompareStride(Loop *L, ICmpInst *Cond, + IVStrideUse* &CondUse, + const SCEV* &CondStride, + bool PostPass = false); + + bool FindIVUserForCond(ICmpInst *Cond, IVStrideUse *&CondUse, + const SCEV* &CondStride); + bool RequiresTypeConversion(const Type *Ty, const Type *NewTy); + const SCEV *CheckForIVReuse(bool, bool, bool, const SCEV *const&, + IVExpr&, const Type*, + const std::vector& UsersToProcess); + bool ValidScale(bool, int64_t, + const std::vector& UsersToProcess); + bool ValidOffset(bool, int64_t, int64_t, + const std::vector& UsersToProcess); + const SCEV *CollectIVUsers(const SCEV *const &Stride, + IVUsersOfOneStride &Uses, + Loop *L, + bool &AllUsesAreAddresses, + bool &AllUsesAreOutsideLoop, + std::vector &UsersToProcess); + bool StrideMightBeShared(const SCEV *Stride, Loop *L, bool CheckPreInc); + bool ShouldUseFullStrengthReductionMode( + const std::vector &UsersToProcess, + const Loop *L, + bool AllUsesAreAddresses, + const SCEV *Stride); + void PrepareToStrengthReduceFully( + std::vector &UsersToProcess, + const SCEV *Stride, + const SCEV *CommonExprs, + const Loop *L, + SCEVExpander &PreheaderRewriter); + void PrepareToStrengthReduceFromSmallerStride( + std::vector &UsersToProcess, + Value *CommonBaseV, + const IVExpr &ReuseIV, + Instruction *PreInsertPt); + void PrepareToStrengthReduceWithNewPhi( + std::vector &UsersToProcess, + const SCEV *Stride, + const SCEV *CommonExprs, + Value *CommonBaseV, + Instruction *IVIncInsertPt, + const Loop *L, + SCEVExpander &PreheaderRewriter); + + void DeleteTriviallyDeadInstructions(); + }; +} + +char LoopStrengthReduce::ID = 0; +static RegisterPass +X("loop-reduce", "Loop Strength Reduction"); + +Pass *llvm::createLoopStrengthReducePass(const TargetLowering *TLI) { + return new LoopStrengthReduce(TLI); +} + +/// DeleteTriviallyDeadInstructions - If any of the instructions is the +/// specified set are trivially dead, delete them and see if this makes any of +/// their operands subsequently dead. +void LoopStrengthReduce::DeleteTriviallyDeadInstructions() { + if (DeadInsts.empty()) return; + + while (!DeadInsts.empty()) { + Instruction *I = dyn_cast_or_null(DeadInsts.back()); + DeadInsts.pop_back(); + + if (I == 0 || !isInstructionTriviallyDead(I)) + continue; + + for (User::op_iterator OI = I->op_begin(), E = I->op_end(); OI != E; ++OI) { + if (Instruction *U = dyn_cast(*OI)) { + *OI = 0; + if (U->use_empty()) + DeadInsts.push_back(U); + } + } + + I->eraseFromParent(); + Changed = true; + } +} + +/// containsAddRecFromDifferentLoop - Determine whether expression S involves a +/// subexpression that is an AddRec from a loop other than L. An outer loop +/// of L is OK, but not an inner loop nor a disjoint loop. +static bool containsAddRecFromDifferentLoop(const SCEV *S, Loop *L) { + // This is very common, put it first. + if (isa(S)) + return false; + if (const SCEVCommutativeExpr *AE = dyn_cast(S)) { + for (unsigned int i=0; i< AE->getNumOperands(); i++) + if (containsAddRecFromDifferentLoop(AE->getOperand(i), L)) + return true; + return false; + } + if (const SCEVAddRecExpr *AE = dyn_cast(S)) { + if (const Loop *newLoop = AE->getLoop()) { + if (newLoop == L) + return false; + // if newLoop is an outer loop of L, this is OK. + if (!LoopInfo::isNotAlreadyContainedIn(L, newLoop)) + return false; + } + return true; + } + if (const SCEVUDivExpr *DE = dyn_cast(S)) + return containsAddRecFromDifferentLoop(DE->getLHS(), L) || + containsAddRecFromDifferentLoop(DE->getRHS(), L); +#if 0 + // SCEVSDivExpr has been backed out temporarily, but will be back; we'll + // need this when it is. + if (const SCEVSDivExpr *DE = dyn_cast(S)) + return containsAddRecFromDifferentLoop(DE->getLHS(), L) || + containsAddRecFromDifferentLoop(DE->getRHS(), L); +#endif + if (const SCEVCastExpr *CE = dyn_cast(S)) + return containsAddRecFromDifferentLoop(CE->getOperand(), L); + return false; +} + +/// isAddressUse - Returns true if the specified instruction is using the +/// specified value as an address. +static bool isAddressUse(Instruction *Inst, Value *OperandVal) { + bool isAddress = isa(Inst); + if (StoreInst *SI = dyn_cast(Inst)) { + if (SI->getOperand(1) == OperandVal) + isAddress = true; + } else if (IntrinsicInst *II = dyn_cast(Inst)) { + // Addressing modes can also be folded into prefetches and a variety + // of intrinsics. + switch (II->getIntrinsicID()) { + default: break; + case Intrinsic::prefetch: + case Intrinsic::x86_sse2_loadu_dq: + case Intrinsic::x86_sse2_loadu_pd: + case Intrinsic::x86_sse_loadu_ps: + case Intrinsic::x86_sse_storeu_ps: + case Intrinsic::x86_sse2_storeu_pd: + case Intrinsic::x86_sse2_storeu_dq: + case Intrinsic::x86_sse2_storel_dq: + if (II->getOperand(1) == OperandVal) + isAddress = true; + break; + } + } + return isAddress; +} + +/// getAccessType - Return the type of the memory being accessed. +static const Type *getAccessType(const Instruction *Inst) { + const Type *AccessTy = Inst->getType(); + if (const StoreInst *SI = dyn_cast(Inst)) + AccessTy = SI->getOperand(0)->getType(); + else if (const IntrinsicInst *II = dyn_cast(Inst)) { + // Addressing modes can also be folded into prefetches and a variety + // of intrinsics. + switch (II->getIntrinsicID()) { + default: break; + case Intrinsic::x86_sse_storeu_ps: + case Intrinsic::x86_sse2_storeu_pd: + case Intrinsic::x86_sse2_storeu_dq: + case Intrinsic::x86_sse2_storel_dq: + AccessTy = II->getOperand(1)->getType(); + break; + } + } + return AccessTy; +} + +namespace { + /// BasedUser - For a particular base value, keep information about how we've + /// partitioned the expression so far. + struct BasedUser { + /// SE - The current ScalarEvolution object. + ScalarEvolution *SE; + + /// Base - The Base value for the PHI node that needs to be inserted for + /// this use. As the use is processed, information gets moved from this + /// field to the Imm field (below). BasedUser values are sorted by this + /// field. + const SCEV *Base; + + /// Inst - The instruction using the induction variable. + Instruction *Inst; + + /// OperandValToReplace - The operand value of Inst to replace with the + /// EmittedBase. + Value *OperandValToReplace; + + /// Imm - The immediate value that should be added to the base immediately + /// before Inst, because it will be folded into the imm field of the + /// instruction. This is also sometimes used for loop-variant values that + /// must be added inside the loop. + const SCEV *Imm; + + /// Phi - The induction variable that performs the striding that + /// should be used for this user. + PHINode *Phi; + + // isUseOfPostIncrementedValue - True if this should use the + // post-incremented version of this IV, not the preincremented version. + // This can only be set in special cases, such as the terminating setcc + // instruction for a loop and uses outside the loop that are dominated by + // the loop. + bool isUseOfPostIncrementedValue; + + BasedUser(IVStrideUse &IVSU, ScalarEvolution *se) + : SE(se), Base(IVSU.getOffset()), Inst(IVSU.getUser()), + OperandValToReplace(IVSU.getOperandValToReplace()), + Imm(SE->getIntegerSCEV(0, Base->getType())), + isUseOfPostIncrementedValue(IVSU.isUseOfPostIncrementedValue()) {} + + // Once we rewrite the code to insert the new IVs we want, update the + // operands of Inst to use the new expression 'NewBase', with 'Imm' added + // to it. + void RewriteInstructionToUseNewBase(const SCEV *const &NewBase, + Instruction *InsertPt, + SCEVExpander &Rewriter, Loop *L, Pass *P, + LoopInfo &LI, + SmallVectorImpl &DeadInsts); + + Value *InsertCodeForBaseAtPosition(const SCEV *const &NewBase, + const Type *Ty, + SCEVExpander &Rewriter, + Instruction *IP, Loop *L, + LoopInfo &LI); + void dump() const; + }; +} + +void BasedUser::dump() const { + errs() << " Base=" << *Base; + errs() << " Imm=" << *Imm; + errs() << " Inst: " << *Inst; +} + +Value *BasedUser::InsertCodeForBaseAtPosition(const SCEV *const &NewBase, + const Type *Ty, + SCEVExpander &Rewriter, + Instruction *IP, Loop *L, + LoopInfo &LI) { + // Figure out where we *really* want to insert this code. In particular, if + // the user is inside of a loop that is nested inside of L, we really don't + // want to insert this expression before the user, we'd rather pull it out as + // many loops as possible. + Instruction *BaseInsertPt = IP; + + // Figure out the most-nested loop that IP is in. + Loop *InsertLoop = LI.getLoopFor(IP->getParent()); + + // If InsertLoop is not L, and InsertLoop is nested inside of L, figure out + // the preheader of the outer-most loop where NewBase is not loop invariant. + if (L->contains(IP->getParent())) + while (InsertLoop && NewBase->isLoopInvariant(InsertLoop)) { + BaseInsertPt = InsertLoop->getLoopPreheader()->getTerminator(); + InsertLoop = InsertLoop->getParentLoop(); + } + + Value *Base = Rewriter.expandCodeFor(NewBase, 0, BaseInsertPt); + + const SCEV *NewValSCEV = SE->getUnknown(Base); + + // Always emit the immediate into the same block as the user. + NewValSCEV = SE->getAddExpr(NewValSCEV, Imm); + + return Rewriter.expandCodeFor(NewValSCEV, Ty, IP); +} + + +// Once we rewrite the code to insert the new IVs we want, update the +// operands of Inst to use the new expression 'NewBase', with 'Imm' added +// to it. NewBasePt is the last instruction which contributes to the +// value of NewBase in the case that it's a diffferent instruction from +// the PHI that NewBase is computed from, or null otherwise. +// +void BasedUser::RewriteInstructionToUseNewBase(const SCEV *const &NewBase, + Instruction *NewBasePt, + SCEVExpander &Rewriter, Loop *L, Pass *P, + LoopInfo &LI, + SmallVectorImpl &DeadInsts) { + if (!isa(Inst)) { + // By default, insert code at the user instruction. + BasicBlock::iterator InsertPt = Inst; + + // However, if the Operand is itself an instruction, the (potentially + // complex) inserted code may be shared by many users. Because of this, we + // want to emit code for the computation of the operand right before its old + // computation. This is usually safe, because we obviously used to use the + // computation when it was computed in its current block. However, in some + // cases (e.g. use of a post-incremented induction variable) the NewBase + // value will be pinned to live somewhere after the original computation. + // In this case, we have to back off. + // + // If this is a use outside the loop (which means after, since it is based + // on a loop indvar) we use the post-incremented value, so that we don't + // artificially make the preinc value live out the bottom of the loop. + if (!isUseOfPostIncrementedValue && L->contains(Inst->getParent())) { + if (NewBasePt && isa(OperandValToReplace)) { + InsertPt = NewBasePt; + ++InsertPt; + } else if (Instruction *OpInst + = dyn_cast(OperandValToReplace)) { + InsertPt = OpInst; + while (isa(InsertPt)) ++InsertPt; + } + } + Value *NewVal = InsertCodeForBaseAtPosition(NewBase, + OperandValToReplace->getType(), + Rewriter, InsertPt, L, LI); + // Replace the use of the operand Value with the new Phi we just created. + Inst->replaceUsesOfWith(OperandValToReplace, NewVal); + + DEBUG(errs() << " Replacing with "); + DEBUG(WriteAsOperand(errs(), NewVal, /*PrintType=*/false)); + DEBUG(errs() << ", which has value " << *NewBase << " plus IMM " + << *Imm << "\n"); + return; + } + + // PHI nodes are more complex. We have to insert one copy of the NewBase+Imm + // expression into each operand block that uses it. Note that PHI nodes can + // have multiple entries for the same predecessor. We use a map to make sure + // that a PHI node only has a single Value* for each predecessor (which also + // prevents us from inserting duplicate code in some blocks). + DenseMap InsertedCode; + PHINode *PN = cast(Inst); + for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) { + if (PN->getIncomingValue(i) == OperandValToReplace) { + // If the original expression is outside the loop, put the replacement + // code in the same place as the original expression, + // which need not be an immediate predecessor of this PHI. This way we + // need only one copy of it even if it is referenced multiple times in + // the PHI. We don't do this when the original expression is inside the + // loop because multiple copies sometimes do useful sinking of code in + // that case(?). + Instruction *OldLoc = dyn_cast(OperandValToReplace); + BasicBlock *PHIPred = PN->getIncomingBlock(i); + if (L->contains(OldLoc->getParent())) { + // If this is a critical edge, split the edge so that we do not insert + // the code on all predecessor/successor paths. We do this unless this + // is the canonical backedge for this loop, as this can make some + // inserted code be in an illegal position. + if (e != 1 && PHIPred->getTerminator()->getNumSuccessors() > 1 && + !isa(PHIPred->getTerminator()) && + (PN->getParent() != L->getHeader() || !L->contains(PHIPred))) { + + // First step, split the critical edge. + BasicBlock *NewBB = SplitCriticalEdge(PHIPred, PN->getParent(), + P, false); + + // Next step: move the basic block. In particular, if the PHI node + // is outside of the loop, and PredTI is in the loop, we want to + // move the block to be immediately before the PHI block, not + // immediately after PredTI. + if (L->contains(PHIPred) && !L->contains(PN->getParent())) + NewBB->moveBefore(PN->getParent()); + + // Splitting the edge can reduce the number of PHI entries we have. + e = PN->getNumIncomingValues(); + PHIPred = NewBB; + i = PN->getBasicBlockIndex(PHIPred); + } + } + Value *&Code = InsertedCode[PHIPred]; + if (!Code) { + // Insert the code into the end of the predecessor block. + Instruction *InsertPt = (L->contains(OldLoc->getParent())) ? + PHIPred->getTerminator() : + OldLoc->getParent()->getTerminator(); + Code = InsertCodeForBaseAtPosition(NewBase, PN->getType(), + Rewriter, InsertPt, L, LI); + + DEBUG(errs() << " Changing PHI use to "); + DEBUG(WriteAsOperand(errs(), Code, /*PrintType=*/false)); + DEBUG(errs() << ", which has value " << *NewBase << " plus IMM " + << *Imm << "\n"); + } + + // Replace the use of the operand Value with the new Phi we just created. + PN->setIncomingValue(i, Code); + Rewriter.clear(); + } + } + + // PHI node might have become a constant value after SplitCriticalEdge. + DeadInsts.push_back(Inst); +} + + +/// fitsInAddressMode - Return true if V can be subsumed within an addressing +/// mode, and does not need to be put in a register first. +static bool fitsInAddressMode(const SCEV *const &V, const Type *AccessTy, + const TargetLowering *TLI, bool HasBaseReg) { + if (const SCEVConstant *SC = dyn_cast(V)) { + int64_t VC = SC->getValue()->getSExtValue(); + if (TLI) { + TargetLowering::AddrMode AM; + AM.BaseOffs = VC; + AM.HasBaseReg = HasBaseReg; + return TLI->isLegalAddressingMode(AM, AccessTy); + } else { + // Defaults to PPC. PPC allows a sign-extended 16-bit immediate field. + return (VC > -(1 << 16) && VC < (1 << 16)-1); + } + } + + if (const SCEVUnknown *SU = dyn_cast(V)) + if (GlobalValue *GV = dyn_cast(SU->getValue())) { + if (TLI) { + TargetLowering::AddrMode AM; + AM.BaseGV = GV; + AM.HasBaseReg = HasBaseReg; + return TLI->isLegalAddressingMode(AM, AccessTy); + } else { + // Default: assume global addresses are not legal. + } + } + + return false; +} + +/// MoveLoopVariantsToImmediateField - Move any subexpressions from Val that are +/// loop varying to the Imm operand. +static void MoveLoopVariantsToImmediateField(const SCEV *&Val, const SCEV *&Imm, + Loop *L, ScalarEvolution *SE) { + if (Val->isLoopInvariant(L)) return; // Nothing to do. + + if (const SCEVAddExpr *SAE = dyn_cast(Val)) { + SmallVector NewOps; + NewOps.reserve(SAE->getNumOperands()); + + for (unsigned i = 0; i != SAE->getNumOperands(); ++i) + if (!SAE->getOperand(i)->isLoopInvariant(L)) { + // If this is a loop-variant expression, it must stay in the immediate + // field of the expression. + Imm = SE->getAddExpr(Imm, SAE->getOperand(i)); + } else { + NewOps.push_back(SAE->getOperand(i)); + } + + if (NewOps.empty()) + Val = SE->getIntegerSCEV(0, Val->getType()); + else + Val = SE->getAddExpr(NewOps); + } else if (const SCEVAddRecExpr *SARE = dyn_cast(Val)) { + // Try to pull immediates out of the start value of nested addrec's. + const SCEV *Start = SARE->getStart(); + MoveLoopVariantsToImmediateField(Start, Imm, L, SE); + + SmallVector Ops(SARE->op_begin(), SARE->op_end()); + Ops[0] = Start; + Val = SE->getAddRecExpr(Ops, SARE->getLoop()); + } else { + // Otherwise, all of Val is variant, move the whole thing over. + Imm = SE->getAddExpr(Imm, Val); + Val = SE->getIntegerSCEV(0, Val->getType()); + } +} + + +/// MoveImmediateValues - Look at Val, and pull out any additions of constants +/// that can fit into the immediate field of instructions in the target. +/// Accumulate these immediate values into the Imm value. +static void MoveImmediateValues(const TargetLowering *TLI, + const Type *AccessTy, + const SCEV *&Val, const SCEV *&Imm, + bool isAddress, Loop *L, + ScalarEvolution *SE) { + if (const SCEVAddExpr *SAE = dyn_cast(Val)) { + SmallVector NewOps; + NewOps.reserve(SAE->getNumOperands()); + + for (unsigned i = 0; i != SAE->getNumOperands(); ++i) { + const SCEV *NewOp = SAE->getOperand(i); + MoveImmediateValues(TLI, AccessTy, NewOp, Imm, isAddress, L, SE); + + if (!NewOp->isLoopInvariant(L)) { + // If this is a loop-variant expression, it must stay in the immediate + // field of the expression. + Imm = SE->getAddExpr(Imm, NewOp); + } else { + NewOps.push_back(NewOp); + } + } + + if (NewOps.empty()) + Val = SE->getIntegerSCEV(0, Val->getType()); + else + Val = SE->getAddExpr(NewOps); + return; + } else if (const SCEVAddRecExpr *SARE = dyn_cast(Val)) { + // Try to pull immediates out of the start value of nested addrec's. + const SCEV *Start = SARE->getStart(); + MoveImmediateValues(TLI, AccessTy, Start, Imm, isAddress, L, SE); + + if (Start != SARE->getStart()) { + SmallVector Ops(SARE->op_begin(), SARE->op_end()); + Ops[0] = Start; + Val = SE->getAddRecExpr(Ops, SARE->getLoop()); + } + return; + } else if (const SCEVMulExpr *SME = dyn_cast(Val)) { + // Transform "8 * (4 + v)" -> "32 + 8*V" if "32" fits in the immed field. + if (isAddress && + fitsInAddressMode(SME->getOperand(0), AccessTy, TLI, false) && + SME->getNumOperands() == 2 && SME->isLoopInvariant(L)) { + + const SCEV *SubImm = SE->getIntegerSCEV(0, Val->getType()); + const SCEV *NewOp = SME->getOperand(1); + MoveImmediateValues(TLI, AccessTy, NewOp, SubImm, isAddress, L, SE); + + // If we extracted something out of the subexpressions, see if we can + // simplify this! + if (NewOp != SME->getOperand(1)) { + // Scale SubImm up by "8". If the result is a target constant, we are + // good. + SubImm = SE->getMulExpr(SubImm, SME->getOperand(0)); + if (fitsInAddressMode(SubImm, AccessTy, TLI, false)) { + // Accumulate the immediate. + Imm = SE->getAddExpr(Imm, SubImm); + + // Update what is left of 'Val'. + Val = SE->getMulExpr(SME->getOperand(0), NewOp); + return; + } + } + } + } + + // Loop-variant expressions must stay in the immediate field of the + // expression. + if ((isAddress && fitsInAddressMode(Val, AccessTy, TLI, false)) || + !Val->isLoopInvariant(L)) { + Imm = SE->getAddExpr(Imm, Val); + Val = SE->getIntegerSCEV(0, Val->getType()); + return; + } + + // Otherwise, no immediates to move. +} + +static void MoveImmediateValues(const TargetLowering *TLI, + Instruction *User, + const SCEV *&Val, const SCEV *&Imm, + bool isAddress, Loop *L, + ScalarEvolution *SE) { + const Type *AccessTy = getAccessType(User); + MoveImmediateValues(TLI, AccessTy, Val, Imm, isAddress, L, SE); +} + +/// SeparateSubExprs - Decompose Expr into all of the subexpressions that are +/// added together. This is used to reassociate common addition subexprs +/// together for maximal sharing when rewriting bases. +static void SeparateSubExprs(SmallVector &SubExprs, + const SCEV *Expr, + ScalarEvolution *SE) { + if (const SCEVAddExpr *AE = dyn_cast(Expr)) { + for (unsigned j = 0, e = AE->getNumOperands(); j != e; ++j) + SeparateSubExprs(SubExprs, AE->getOperand(j), SE); + } else if (const SCEVAddRecExpr *SARE = dyn_cast(Expr)) { + const SCEV *Zero = SE->getIntegerSCEV(0, Expr->getType()); + if (SARE->getOperand(0) == Zero) { + SubExprs.push_back(Expr); + } else { + // Compute the addrec with zero as its base. + SmallVector Ops(SARE->op_begin(), SARE->op_end()); + Ops[0] = Zero; // Start with zero base. + SubExprs.push_back(SE->getAddRecExpr(Ops, SARE->getLoop())); + + + SeparateSubExprs(SubExprs, SARE->getOperand(0), SE); + } + } else if (!Expr->isZero()) { + // Do not add zero. + SubExprs.push_back(Expr); + } +} + +// This is logically local to the following function, but C++ says we have +// to make it file scope. +struct SubExprUseData { unsigned Count; bool notAllUsesAreFree; }; + +/// RemoveCommonExpressionsFromUseBases - Look through all of the Bases of all +/// the Uses, removing any common subexpressions, except that if all such +/// subexpressions can be folded into an addressing mode for all uses inside +/// the loop (this case is referred to as "free" in comments herein) we do +/// not remove anything. This looks for things like (a+b+c) and +/// (a+c+d) and computes the common (a+c) subexpression. The common expression +/// is *removed* from the Bases and returned. +static const SCEV * +RemoveCommonExpressionsFromUseBases(std::vector &Uses, + ScalarEvolution *SE, Loop *L, + const TargetLowering *TLI) { + unsigned NumUses = Uses.size(); + + // Only one use? This is a very common case, so we handle it specially and + // cheaply. + const SCEV *Zero = SE->getIntegerSCEV(0, Uses[0].Base->getType()); + const SCEV *Result = Zero; + const SCEV *FreeResult = Zero; + if (NumUses == 1) { + // If the use is inside the loop, use its base, regardless of what it is: + // it is clearly shared across all the IV's. If the use is outside the loop + // (which means after it) we don't want to factor anything *into* the loop, + // so just use 0 as the base. + if (L->contains(Uses[0].Inst->getParent())) + std::swap(Result, Uses[0].Base); + return Result; + } + + // To find common subexpressions, count how many of Uses use each expression. + // If any subexpressions are used Uses.size() times, they are common. + // Also track whether all uses of each expression can be moved into an + // an addressing mode "for free"; such expressions are left within the loop. + // struct SubExprUseData { unsigned Count; bool notAllUsesAreFree; }; + std::map SubExpressionUseData; + + // UniqueSubExprs - Keep track of all of the subexpressions we see in the + // order we see them. + SmallVector UniqueSubExprs; + + SmallVector SubExprs; + unsigned NumUsesInsideLoop = 0; + for (unsigned i = 0; i != NumUses; ++i) { + // If the user is outside the loop, just ignore it for base computation. + // Since the user is outside the loop, it must be *after* the loop (if it + // were before, it could not be based on the loop IV). We don't want users + // after the loop to affect base computation of values *inside* the loop, + // because we can always add their offsets to the result IV after the loop + // is done, ensuring we get good code inside the loop. + if (!L->contains(Uses[i].Inst->getParent())) + continue; + NumUsesInsideLoop++; + + // If the base is zero (which is common), return zero now, there are no + // CSEs we can find. + if (Uses[i].Base == Zero) return Zero; + + // If this use is as an address we may be able to put CSEs in the addressing + // mode rather than hoisting them. + bool isAddrUse = isAddressUse(Uses[i].Inst, Uses[i].OperandValToReplace); + // We may need the AccessTy below, but only when isAddrUse, so compute it + // only in that case. + const Type *AccessTy = 0; + if (isAddrUse) + AccessTy = getAccessType(Uses[i].Inst); + + // Split the expression into subexprs. + SeparateSubExprs(SubExprs, Uses[i].Base, SE); + // Add one to SubExpressionUseData.Count for each subexpr present, and + // if the subexpr is not a valid immediate within an addressing mode use, + // set SubExpressionUseData.notAllUsesAreFree. We definitely want to + // hoist these out of the loop (if they are common to all uses). + for (unsigned j = 0, e = SubExprs.size(); j != e; ++j) { + if (++SubExpressionUseData[SubExprs[j]].Count == 1) + UniqueSubExprs.push_back(SubExprs[j]); + if (!isAddrUse || !fitsInAddressMode(SubExprs[j], AccessTy, TLI, false)) + SubExpressionUseData[SubExprs[j]].notAllUsesAreFree = true; + } + SubExprs.clear(); + } + + // Now that we know how many times each is used, build Result. Iterate over + // UniqueSubexprs so that we have a stable ordering. + for (unsigned i = 0, e = UniqueSubExprs.size(); i != e; ++i) { + std::map::iterator I = + SubExpressionUseData.find(UniqueSubExprs[i]); + assert(I != SubExpressionUseData.end() && "Entry not found?"); + if (I->second.Count == NumUsesInsideLoop) { // Found CSE! + if (I->second.notAllUsesAreFree) + Result = SE->getAddExpr(Result, I->first); + else + FreeResult = SE->getAddExpr(FreeResult, I->first); + } else + // Remove non-cse's from SubExpressionUseData. + SubExpressionUseData.erase(I); + } + + if (FreeResult != Zero) { + // We have some subexpressions that can be subsumed into addressing + // modes in every use inside the loop. However, it's possible that + // there are so many of them that the combined FreeResult cannot + // be subsumed, or that the target cannot handle both a FreeResult + // and a Result in the same instruction (for example because it would + // require too many registers). Check this. + for (unsigned i=0; icontains(Uses[i].Inst->getParent())) + continue; + // We know this is an addressing mode use; if there are any uses that + // are not, FreeResult would be Zero. + const Type *AccessTy = getAccessType(Uses[i].Inst); + if (!fitsInAddressMode(FreeResult, AccessTy, TLI, Result!=Zero)) { + // FIXME: could split up FreeResult into pieces here, some hoisted + // and some not. There is no obvious advantage to this. + Result = SE->getAddExpr(Result, FreeResult); + FreeResult = Zero; + break; + } + } + } + + // If we found no CSE's, return now. + if (Result == Zero) return Result; + + // If we still have a FreeResult, remove its subexpressions from + // SubExpressionUseData. This means they will remain in the use Bases. + if (FreeResult != Zero) { + SeparateSubExprs(SubExprs, FreeResult, SE); + for (unsigned j = 0, e = SubExprs.size(); j != e; ++j) { + std::map::iterator I = + SubExpressionUseData.find(SubExprs[j]); + SubExpressionUseData.erase(I); + } + SubExprs.clear(); + } + + // Otherwise, remove all of the CSE's we found from each of the base values. + for (unsigned i = 0; i != NumUses; ++i) { + // Uses outside the loop don't necessarily include the common base, but + // the final IV value coming into those uses does. Instead of trying to + // remove the pieces of the common base, which might not be there, + // subtract off the base to compensate for this. + if (!L->contains(Uses[i].Inst->getParent())) { + Uses[i].Base = SE->getMinusSCEV(Uses[i].Base, Result); + continue; + } + + // Split the expression into subexprs. + SeparateSubExprs(SubExprs, Uses[i].Base, SE); + + // Remove any common subexpressions. + for (unsigned j = 0, e = SubExprs.size(); j != e; ++j) + if (SubExpressionUseData.count(SubExprs[j])) { + SubExprs.erase(SubExprs.begin()+j); + --j; --e; + } + + // Finally, add the non-shared expressions together. + if (SubExprs.empty()) + Uses[i].Base = Zero; + else + Uses[i].Base = SE->getAddExpr(SubExprs); + SubExprs.clear(); + } + + return Result; +} + +/// ValidScale - Check whether the given Scale is valid for all loads and +/// stores in UsersToProcess. +/// +bool LoopStrengthReduce::ValidScale(bool HasBaseReg, int64_t Scale, + const std::vector& UsersToProcess) { + if (!TLI) + return true; + + for (unsigned i = 0, e = UsersToProcess.size(); i!=e; ++i) { + // If this is a load or other access, pass the type of the access in. + const Type *AccessTy = + Type::getVoidTy(UsersToProcess[i].Inst->getContext()); + if (isAddressUse(UsersToProcess[i].Inst, + UsersToProcess[i].OperandValToReplace)) + AccessTy = getAccessType(UsersToProcess[i].Inst); + else if (isa(UsersToProcess[i].Inst)) + continue; + + TargetLowering::AddrMode AM; + if (const SCEVConstant *SC = dyn_cast(UsersToProcess[i].Imm)) + AM.BaseOffs = SC->getValue()->getSExtValue(); + AM.HasBaseReg = HasBaseReg || !UsersToProcess[i].Base->isZero(); + AM.Scale = Scale; + + // If load[imm+r*scale] is illegal, bail out. + if (!TLI->isLegalAddressingMode(AM, AccessTy)) + return false; + } + return true; +} + +/// ValidOffset - Check whether the given Offset is valid for all loads and +/// stores in UsersToProcess. +/// +bool LoopStrengthReduce::ValidOffset(bool HasBaseReg, + int64_t Offset, + int64_t Scale, + const std::vector& UsersToProcess) { + if (!TLI) + return true; + + for (unsigned i=0, e = UsersToProcess.size(); i!=e; ++i) { + // If this is a load or other access, pass the type of the access in. + const Type *AccessTy = + Type::getVoidTy(UsersToProcess[i].Inst->getContext()); + if (isAddressUse(UsersToProcess[i].Inst, + UsersToProcess[i].OperandValToReplace)) + AccessTy = getAccessType(UsersToProcess[i].Inst); + else if (isa(UsersToProcess[i].Inst)) + continue; + + TargetLowering::AddrMode AM; + if (const SCEVConstant *SC = dyn_cast(UsersToProcess[i].Imm)) + AM.BaseOffs = SC->getValue()->getSExtValue(); + AM.BaseOffs = (uint64_t)AM.BaseOffs + (uint64_t)Offset; + AM.HasBaseReg = HasBaseReg || !UsersToProcess[i].Base->isZero(); + AM.Scale = Scale; + + // If load[imm+r*scale] is illegal, bail out. + if (!TLI->isLegalAddressingMode(AM, AccessTy)) + return false; + } + return true; +} + +/// RequiresTypeConversion - Returns true if converting Ty1 to Ty2 is not +/// a nop. +bool LoopStrengthReduce::RequiresTypeConversion(const Type *Ty1, + const Type *Ty2) { + if (Ty1 == Ty2) + return false; + Ty1 = SE->getEffectiveSCEVType(Ty1); + Ty2 = SE->getEffectiveSCEVType(Ty2); + if (Ty1 == Ty2) + return false; + if (Ty1->canLosslesslyBitCastTo(Ty2)) + return false; + if (TLI && TLI->isTruncateFree(Ty1, Ty2)) + return false; + return true; +} + +/// CheckForIVReuse - Returns the multiple if the stride is the multiple +/// of a previous stride and it is a legal value for the target addressing +/// mode scale component and optional base reg. This allows the users of +/// this stride to be rewritten as prev iv * factor. It returns 0 if no +/// reuse is possible. Factors can be negative on same targets, e.g. ARM. +/// +/// If all uses are outside the loop, we don't require that all multiplies +/// be folded into the addressing mode, nor even that the factor be constant; +/// a multiply (executed once) outside the loop is better than another IV +/// within. Well, usually. +const SCEV *LoopStrengthReduce::CheckForIVReuse(bool HasBaseReg, + bool AllUsesAreAddresses, + bool AllUsesAreOutsideLoop, + const SCEV *const &Stride, + IVExpr &IV, const Type *Ty, + const std::vector& UsersToProcess) { + if (StrideNoReuse.count(Stride)) + return SE->getIntegerSCEV(0, Stride->getType()); + + if (const SCEVConstant *SC = dyn_cast(Stride)) { + int64_t SInt = SC->getValue()->getSExtValue(); + for (unsigned NewStride = 0, e = IU->StrideOrder.size(); + NewStride != e; ++NewStride) { + std::map::iterator SI = + IVsByStride.find(IU->StrideOrder[NewStride]); + if (SI == IVsByStride.end() || !isa(SI->first) || + StrideNoReuse.count(SI->first)) + continue; + // The other stride has no uses, don't reuse it. + std::map::iterator UI = + IU->IVUsesByStride.find(IU->StrideOrder[NewStride]); + if (UI->second->Users.empty()) + continue; + int64_t SSInt = cast(SI->first)->getValue()->getSExtValue(); + if (SI->first != Stride && + (unsigned(abs64(SInt)) < SSInt || (SInt % SSInt) != 0)) + continue; + int64_t Scale = SInt / SSInt; + // Check that this stride is valid for all the types used for loads and + // stores; if it can be used for some and not others, we might as well use + // the original stride everywhere, since we have to create the IV for it + // anyway. If the scale is 1, then we don't need to worry about folding + // multiplications. + if (Scale == 1 || + (AllUsesAreAddresses && + ValidScale(HasBaseReg, Scale, UsersToProcess))) { + // Prefer to reuse an IV with a base of zero. + for (std::vector::iterator II = SI->second.IVs.begin(), + IE = SI->second.IVs.end(); II != IE; ++II) + // Only reuse previous IV if it would not require a type conversion + // and if the base difference can be folded. + if (II->Base->isZero() && + !RequiresTypeConversion(II->Base->getType(), Ty)) { + IV = *II; + return SE->getIntegerSCEV(Scale, Stride->getType()); + } + // Otherwise, settle for an IV with a foldable base. + if (AllUsesAreAddresses) + for (std::vector::iterator II = SI->second.IVs.begin(), + IE = SI->second.IVs.end(); II != IE; ++II) + // Only reuse previous IV if it would not require a type conversion + // and if the base difference can be folded. + if (SE->getEffectiveSCEVType(II->Base->getType()) == + SE->getEffectiveSCEVType(Ty) && + isa(II->Base)) { + int64_t Base = + cast(II->Base)->getValue()->getSExtValue(); + if (Base > INT32_MIN && Base <= INT32_MAX && + ValidOffset(HasBaseReg, -Base * Scale, + Scale, UsersToProcess)) { + IV = *II; + return SE->getIntegerSCEV(Scale, Stride->getType()); + } + } + } + } + } else if (AllUsesAreOutsideLoop) { + // Accept nonconstant strides here; it is really really right to substitute + // an existing IV if we can. + for (unsigned NewStride = 0, e = IU->StrideOrder.size(); + NewStride != e; ++NewStride) { + std::map::iterator SI = + IVsByStride.find(IU->StrideOrder[NewStride]); + if (SI == IVsByStride.end() || !isa(SI->first)) + continue; + int64_t SSInt = cast(SI->first)->getValue()->getSExtValue(); + if (SI->first != Stride && SSInt != 1) + continue; + for (std::vector::iterator II = SI->second.IVs.begin(), + IE = SI->second.IVs.end(); II != IE; ++II) + // Accept nonzero base here. + // Only reuse previous IV if it would not require a type conversion. + if (!RequiresTypeConversion(II->Base->getType(), Ty)) { + IV = *II; + return Stride; + } + } + // Special case, old IV is -1*x and this one is x. Can treat this one as + // -1*old. + for (unsigned NewStride = 0, e = IU->StrideOrder.size(); + NewStride != e; ++NewStride) { + std::map::iterator SI = + IVsByStride.find(IU->StrideOrder[NewStride]); + if (SI == IVsByStride.end()) + continue; + if (const SCEVMulExpr *ME = dyn_cast(SI->first)) + if (const SCEVConstant *SC = dyn_cast(ME->getOperand(0))) + if (Stride == ME->getOperand(1) && + SC->getValue()->getSExtValue() == -1LL) + for (std::vector::iterator II = SI->second.IVs.begin(), + IE = SI->second.IVs.end(); II != IE; ++II) + // Accept nonzero base here. + // Only reuse previous IV if it would not require type conversion. + if (!RequiresTypeConversion(II->Base->getType(), Ty)) { + IV = *II; + return SE->getIntegerSCEV(-1LL, Stride->getType()); + } + } + } + return SE->getIntegerSCEV(0, Stride->getType()); +} + +/// PartitionByIsUseOfPostIncrementedValue - Simple boolean predicate that +/// returns true if Val's isUseOfPostIncrementedValue is true. +static bool PartitionByIsUseOfPostIncrementedValue(const BasedUser &Val) { + return Val.isUseOfPostIncrementedValue; +} + +/// isNonConstantNegative - Return true if the specified scev is negated, but +/// not a constant. +static bool isNonConstantNegative(const SCEV *const &Expr) { + const SCEVMulExpr *Mul = dyn_cast(Expr); + if (!Mul) return false; + + // If there is a constant factor, it will be first. + const SCEVConstant *SC = dyn_cast(Mul->getOperand(0)); + if (!SC) return false; + + // Return true if the value is negative, this matches things like (-42 * V). + return SC->getValue()->getValue().isNegative(); +} + +/// CollectIVUsers - Transform our list of users and offsets to a bit more +/// complex table. In this new vector, each 'BasedUser' contains 'Base', the +/// base of the strided accesses, as well as the old information from Uses. We +/// progressively move information from the Base field to the Imm field, until +/// we eventually have the full access expression to rewrite the use. +const SCEV *LoopStrengthReduce::CollectIVUsers(const SCEV *const &Stride, + IVUsersOfOneStride &Uses, + Loop *L, + bool &AllUsesAreAddresses, + bool &AllUsesAreOutsideLoop, + std::vector &UsersToProcess) { + // FIXME: Generalize to non-affine IV's. + if (!Stride->isLoopInvariant(L)) + return SE->getIntegerSCEV(0, Stride->getType()); + + UsersToProcess.reserve(Uses.Users.size()); + for (ilist::iterator I = Uses.Users.begin(), + E = Uses.Users.end(); I != E; ++I) { + UsersToProcess.push_back(BasedUser(*I, SE)); + + // Move any loop variant operands from the offset field to the immediate + // field of the use, so that we don't try to use something before it is + // computed. + MoveLoopVariantsToImmediateField(UsersToProcess.back().Base, + UsersToProcess.back().Imm, L, SE); + assert(UsersToProcess.back().Base->isLoopInvariant(L) && + "Base value is not loop invariant!"); + } + + // We now have a whole bunch of uses of like-strided induction variables, but + // they might all have different bases. We want to emit one PHI node for this + // stride which we fold as many common expressions (between the IVs) into as + // possible. Start by identifying the common expressions in the base values + // for the strides (e.g. if we have "A+C+B" and "A+B+D" as our bases, find + // "A+B"), emit it to the preheader, then remove the expression from the + // UsersToProcess base values. + const SCEV *CommonExprs = + RemoveCommonExpressionsFromUseBases(UsersToProcess, SE, L, TLI); + + // Next, figure out what we can represent in the immediate fields of + // instructions. If we can represent anything there, move it to the imm + // fields of the BasedUsers. We do this so that it increases the commonality + // of the remaining uses. + unsigned NumPHI = 0; + bool HasAddress = false; + for (unsigned i = 0, e = UsersToProcess.size(); i != e; ++i) { + // If the user is not in the current loop, this means it is using the exit + // value of the IV. Do not put anything in the base, make sure it's all in + // the immediate field to allow as much factoring as possible. + if (!L->contains(UsersToProcess[i].Inst->getParent())) { + UsersToProcess[i].Imm = SE->getAddExpr(UsersToProcess[i].Imm, + UsersToProcess[i].Base); + UsersToProcess[i].Base = + SE->getIntegerSCEV(0, UsersToProcess[i].Base->getType()); + } else { + // Not all uses are outside the loop. + AllUsesAreOutsideLoop = false; + + // Addressing modes can be folded into loads and stores. Be careful that + // the store is through the expression, not of the expression though. + bool isPHI = false; + bool isAddress = isAddressUse(UsersToProcess[i].Inst, + UsersToProcess[i].OperandValToReplace); + if (isa(UsersToProcess[i].Inst)) { + isPHI = true; + ++NumPHI; + } + + if (isAddress) + HasAddress = true; + + // If this use isn't an address, then not all uses are addresses. + if (!isAddress && !isPHI) + AllUsesAreAddresses = false; + + MoveImmediateValues(TLI, UsersToProcess[i].Inst, UsersToProcess[i].Base, + UsersToProcess[i].Imm, isAddress, L, SE); + } + } + + // If one of the use is a PHI node and all other uses are addresses, still + // allow iv reuse. Essentially we are trading one constant multiplication + // for one fewer iv. + if (NumPHI > 1) + AllUsesAreAddresses = false; + + // There are no in-loop address uses. + if (AllUsesAreAddresses && (!HasAddress && !AllUsesAreOutsideLoop)) + AllUsesAreAddresses = false; + + return CommonExprs; +} + +/// ShouldUseFullStrengthReductionMode - Test whether full strength-reduction +/// is valid and profitable for the given set of users of a stride. In +/// full strength-reduction mode, all addresses at the current stride are +/// strength-reduced all the way down to pointer arithmetic. +/// +bool LoopStrengthReduce::ShouldUseFullStrengthReductionMode( + const std::vector &UsersToProcess, + const Loop *L, + bool AllUsesAreAddresses, + const SCEV *Stride) { + if (!EnableFullLSRMode) + return false; + + // The heuristics below aim to avoid increasing register pressure, but + // fully strength-reducing all the addresses increases the number of + // add instructions, so don't do this when optimizing for size. + // TODO: If the loop is large, the savings due to simpler addresses + // may oughtweight the costs of the extra increment instructions. + if (L->getHeader()->getParent()->hasFnAttr(Attribute::OptimizeForSize)) + return false; + + // TODO: For now, don't do full strength reduction if there could + // potentially be greater-stride multiples of the current stride + // which could reuse the current stride IV. + if (IU->StrideOrder.back() != Stride) + return false; + + // Iterate through the uses to find conditions that automatically rule out + // full-lsr mode. + for (unsigned i = 0, e = UsersToProcess.size(); i != e; ) { + const SCEV *Base = UsersToProcess[i].Base; + const SCEV *Imm = UsersToProcess[i].Imm; + // If any users have a loop-variant component, they can't be fully + // strength-reduced. + if (Imm && !Imm->isLoopInvariant(L)) + return false; + // If there are to users with the same base and the difference between + // the two Imm values can't be folded into the address, full + // strength reduction would increase register pressure. + do { + const SCEV *CurImm = UsersToProcess[i].Imm; + if ((CurImm || Imm) && CurImm != Imm) { + if (!CurImm) CurImm = SE->getIntegerSCEV(0, Stride->getType()); + if (!Imm) Imm = SE->getIntegerSCEV(0, Stride->getType()); + const Instruction *Inst = UsersToProcess[i].Inst; + const Type *AccessTy = getAccessType(Inst); + const SCEV *Diff = SE->getMinusSCEV(UsersToProcess[i].Imm, Imm); + if (!Diff->isZero() && + (!AllUsesAreAddresses || + !fitsInAddressMode(Diff, AccessTy, TLI, /*HasBaseReg=*/true))) + return false; + } + } while (++i != e && Base == UsersToProcess[i].Base); + } + + // If there's exactly one user in this stride, fully strength-reducing it + // won't increase register pressure. If it's starting from a non-zero base, + // it'll be simpler this way. + if (UsersToProcess.size() == 1 && !UsersToProcess[0].Base->isZero()) + return true; + + // Otherwise, if there are any users in this stride that don't require + // a register for their base, full strength-reduction will increase + // register pressure. + for (unsigned i = 0, e = UsersToProcess.size(); i != e; ++i) + if (UsersToProcess[i].Base->isZero()) + return false; + + // Otherwise, go for it. + return true; +} + +/// InsertAffinePhi Create and insert a PHI node for an induction variable +/// with the specified start and step values in the specified loop. +/// +/// If NegateStride is true, the stride should be negated by using a +/// subtract instead of an add. +/// +/// Return the created phi node. +/// +static PHINode *InsertAffinePhi(const SCEV *Start, const SCEV *Step, + Instruction *IVIncInsertPt, + const Loop *L, + SCEVExpander &Rewriter) { + assert(Start->isLoopInvariant(L) && "New PHI start is not loop invariant!"); + assert(Step->isLoopInvariant(L) && "New PHI stride is not loop invariant!"); + + BasicBlock *Header = L->getHeader(); + BasicBlock *Preheader = L->getLoopPreheader(); + BasicBlock *LatchBlock = L->getLoopLatch(); + const Type *Ty = Start->getType(); + Ty = Rewriter.SE.getEffectiveSCEVType(Ty); + + PHINode *PN = PHINode::Create(Ty, "lsr.iv", Header->begin()); + PN->addIncoming(Rewriter.expandCodeFor(Start, Ty, Preheader->getTerminator()), + Preheader); + + // If the stride is negative, insert a sub instead of an add for the + // increment. + bool isNegative = isNonConstantNegative(Step); + const SCEV *IncAmount = Step; + if (isNegative) + IncAmount = Rewriter.SE.getNegativeSCEV(Step); + + // Insert an add instruction right before the terminator corresponding + // to the back-edge or just before the only use. The location is determined + // by the caller and passed in as IVIncInsertPt. + Value *StepV = Rewriter.expandCodeFor(IncAmount, Ty, + Preheader->getTerminator()); + Instruction *IncV; + if (isNegative) { + IncV = BinaryOperator::CreateSub(PN, StepV, "lsr.iv.next", + IVIncInsertPt); + } else { + IncV = BinaryOperator::CreateAdd(PN, StepV, "lsr.iv.next", + IVIncInsertPt); + } + if (!isa(StepV)) ++NumVariable; + + PN->addIncoming(IncV, LatchBlock); + + ++NumInserted; + return PN; +} + +static void SortUsersToProcess(std::vector &UsersToProcess) { + // We want to emit code for users inside the loop first. To do this, we + // rearrange BasedUser so that the entries at the end have + // isUseOfPostIncrementedValue = false, because we pop off the end of the + // vector (so we handle them first). + std::partition(UsersToProcess.begin(), UsersToProcess.end(), + PartitionByIsUseOfPostIncrementedValue); + + // Sort this by base, so that things with the same base are handled + // together. By partitioning first and stable-sorting later, we are + // guaranteed that within each base we will pop off users from within the + // loop before users outside of the loop with a particular base. + // + // We would like to use stable_sort here, but we can't. The problem is that + // const SCEV *'s don't have a deterministic ordering w.r.t to each other, so + // we don't have anything to do a '<' comparison on. Because we think the + // number of uses is small, do a horrible bubble sort which just relies on + // ==. + for (unsigned i = 0, e = UsersToProcess.size(); i != e; ++i) { + // Get a base value. + const SCEV *Base = UsersToProcess[i].Base; + + // Compact everything with this base to be consecutive with this one. + for (unsigned j = i+1; j != e; ++j) { + if (UsersToProcess[j].Base == Base) { + std::swap(UsersToProcess[i+1], UsersToProcess[j]); + ++i; + } + } + } +} + +/// PrepareToStrengthReduceFully - Prepare to fully strength-reduce +/// UsersToProcess, meaning lowering addresses all the way down to direct +/// pointer arithmetic. +/// +void +LoopStrengthReduce::PrepareToStrengthReduceFully( + std::vector &UsersToProcess, + const SCEV *Stride, + const SCEV *CommonExprs, + const Loop *L, + SCEVExpander &PreheaderRewriter) { + DEBUG(errs() << " Fully reducing all users\n"); + + // Rewrite the UsersToProcess records, creating a separate PHI for each + // unique Base value. + Instruction *IVIncInsertPt = L->getLoopLatch()->getTerminator(); + for (unsigned i = 0, e = UsersToProcess.size(); i != e; ) { + // TODO: The uses are grouped by base, but not sorted. We arbitrarily + // pick the first Imm value here to start with, and adjust it for the + // other uses. + const SCEV *Imm = UsersToProcess[i].Imm; + const SCEV *Base = UsersToProcess[i].Base; + const SCEV *Start = SE->getAddExpr(CommonExprs, Base, Imm); + PHINode *Phi = InsertAffinePhi(Start, Stride, IVIncInsertPt, L, + PreheaderRewriter); + // Loop over all the users with the same base. + do { + UsersToProcess[i].Base = SE->getIntegerSCEV(0, Stride->getType()); + UsersToProcess[i].Imm = SE->getMinusSCEV(UsersToProcess[i].Imm, Imm); + UsersToProcess[i].Phi = Phi; + assert(UsersToProcess[i].Imm->isLoopInvariant(L) && + "ShouldUseFullStrengthReductionMode should reject this!"); + } while (++i != e && Base == UsersToProcess[i].Base); + } +} + +/// FindIVIncInsertPt - Return the location to insert the increment instruction. +/// If the only use if a use of postinc value, (must be the loop termination +/// condition), then insert it just before the use. +static Instruction *FindIVIncInsertPt(std::vector &UsersToProcess, + const Loop *L) { + if (UsersToProcess.size() == 1 && + UsersToProcess[0].isUseOfPostIncrementedValue && + L->contains(UsersToProcess[0].Inst->getParent())) + return UsersToProcess[0].Inst; + return L->getLoopLatch()->getTerminator(); +} + +/// PrepareToStrengthReduceWithNewPhi - Insert a new induction variable for the +/// given users to share. +/// +void +LoopStrengthReduce::PrepareToStrengthReduceWithNewPhi( + std::vector &UsersToProcess, + const SCEV *Stride, + const SCEV *CommonExprs, + Value *CommonBaseV, + Instruction *IVIncInsertPt, + const Loop *L, + SCEVExpander &PreheaderRewriter) { + DEBUG(errs() << " Inserting new PHI:\n"); + + PHINode *Phi = InsertAffinePhi(SE->getUnknown(CommonBaseV), + Stride, IVIncInsertPt, L, + PreheaderRewriter); + + // Remember this in case a later stride is multiple of this. + IVsByStride[Stride].addIV(Stride, CommonExprs, Phi); + + // All the users will share this new IV. + for (unsigned i = 0, e = UsersToProcess.size(); i != e; ++i) + UsersToProcess[i].Phi = Phi; + + DEBUG(errs() << " IV="); + DEBUG(WriteAsOperand(errs(), Phi, /*PrintType=*/false)); + DEBUG(errs() << "\n"); +} + +/// PrepareToStrengthReduceFromSmallerStride - Prepare for the given users to +/// reuse an induction variable with a stride that is a factor of the current +/// induction variable. +/// +void +LoopStrengthReduce::PrepareToStrengthReduceFromSmallerStride( + std::vector &UsersToProcess, + Value *CommonBaseV, + const IVExpr &ReuseIV, + Instruction *PreInsertPt) { + DEBUG(errs() << " Rewriting in terms of existing IV of STRIDE " + << *ReuseIV.Stride << " and BASE " << *ReuseIV.Base << "\n"); + + // All the users will share the reused IV. + for (unsigned i = 0, e = UsersToProcess.size(); i != e; ++i) + UsersToProcess[i].Phi = ReuseIV.PHI; + + Constant *C = dyn_cast(CommonBaseV); + if (C && + (!C->isNullValue() && + !fitsInAddressMode(SE->getUnknown(CommonBaseV), CommonBaseV->getType(), + TLI, false))) + // We want the common base emitted into the preheader! This is just + // using cast as a copy so BitCast (no-op cast) is appropriate + CommonBaseV = new BitCastInst(CommonBaseV, CommonBaseV->getType(), + "commonbase", PreInsertPt); +} + +static bool IsImmFoldedIntoAddrMode(GlobalValue *GV, int64_t Offset, + const Type *AccessTy, + std::vector &UsersToProcess, + const TargetLowering *TLI) { + SmallVector AddrModeInsts; + for (unsigned i = 0, e = UsersToProcess.size(); i != e; ++i) { + if (UsersToProcess[i].isUseOfPostIncrementedValue) + continue; + ExtAddrMode AddrMode = + AddressingModeMatcher::Match(UsersToProcess[i].OperandValToReplace, + AccessTy, UsersToProcess[i].Inst, + AddrModeInsts, *TLI); + if (GV && GV != AddrMode.BaseGV) + return false; + if (Offset && !AddrMode.BaseOffs) + // FIXME: How to accurate check it's immediate offset is folded. + return false; + AddrModeInsts.clear(); + } + return true; +} + +/// StrengthReduceIVUsersOfStride - Strength reduce all of the users of a single +/// stride of IV. All of the users may have different starting values, and this +/// may not be the only stride. +void +LoopStrengthReduce::StrengthReduceIVUsersOfStride(const SCEV *const &Stride, + IVUsersOfOneStride &Uses, + Loop *L) { + // If all the users are moved to another stride, then there is nothing to do. + if (Uses.Users.empty()) + return; + + // Keep track if every use in UsersToProcess is an address. If they all are, + // we may be able to rewrite the entire collection of them in terms of a + // smaller-stride IV. + bool AllUsesAreAddresses = true; + + // Keep track if every use of a single stride is outside the loop. If so, + // we want to be more aggressive about reusing a smaller-stride IV; a + // multiply outside the loop is better than another IV inside. Well, usually. + bool AllUsesAreOutsideLoop = true; + + // Transform our list of users and offsets to a bit more complex table. In + // this new vector, each 'BasedUser' contains 'Base' the base of the + // strided accessas well as the old information from Uses. We progressively + // move information from the Base field to the Imm field, until we eventually + // have the full access expression to rewrite the use. + std::vector UsersToProcess; + const SCEV *CommonExprs = CollectIVUsers(Stride, Uses, L, AllUsesAreAddresses, + AllUsesAreOutsideLoop, + UsersToProcess); + + // Sort the UsersToProcess array so that users with common bases are + // next to each other. + SortUsersToProcess(UsersToProcess); + + // If we managed to find some expressions in common, we'll need to carry + // their value in a register and add it in for each use. This will take up + // a register operand, which potentially restricts what stride values are + // valid. + bool HaveCommonExprs = !CommonExprs->isZero(); + const Type *ReplacedTy = CommonExprs->getType(); + + // If all uses are addresses, consider sinking the immediate part of the + // common expression back into uses if they can fit in the immediate fields. + if (TLI && HaveCommonExprs && AllUsesAreAddresses) { + const SCEV *NewCommon = CommonExprs; + const SCEV *Imm = SE->getIntegerSCEV(0, ReplacedTy); + MoveImmediateValues(TLI, Type::getVoidTy( + L->getLoopPreheader()->getContext()), + NewCommon, Imm, true, L, SE); + if (!Imm->isZero()) { + bool DoSink = true; + + // If the immediate part of the common expression is a GV, check if it's + // possible to fold it into the target addressing mode. + GlobalValue *GV = 0; + if (const SCEVUnknown *SU = dyn_cast(Imm)) + GV = dyn_cast(SU->getValue()); + int64_t Offset = 0; + if (const SCEVConstant *SC = dyn_cast(Imm)) + Offset = SC->getValue()->getSExtValue(); + if (GV || Offset) + // Pass VoidTy as the AccessTy to be conservative, because + // there could be multiple access types among all the uses. + DoSink = IsImmFoldedIntoAddrMode(GV, Offset, + Type::getVoidTy(L->getLoopPreheader()->getContext()), + UsersToProcess, TLI); + + if (DoSink) { + DEBUG(errs() << " Sinking " << *Imm << " back down into uses\n"); + for (unsigned i = 0, e = UsersToProcess.size(); i != e; ++i) + UsersToProcess[i].Imm = SE->getAddExpr(UsersToProcess[i].Imm, Imm); + CommonExprs = NewCommon; + HaveCommonExprs = !CommonExprs->isZero(); + ++NumImmSunk; + } + } + } + + // Now that we know what we need to do, insert the PHI node itself. + // + DEBUG(errs() << "LSR: Examining IVs of TYPE " << *ReplacedTy << " of STRIDE " + << *Stride << ":\n" + << " Common base: " << *CommonExprs << "\n"); + + SCEVExpander Rewriter(*SE); + SCEVExpander PreheaderRewriter(*SE); + + BasicBlock *Preheader = L->getLoopPreheader(); + Instruction *PreInsertPt = Preheader->getTerminator(); + BasicBlock *LatchBlock = L->getLoopLatch(); + Instruction *IVIncInsertPt = LatchBlock->getTerminator(); + + Value *CommonBaseV = Constant::getNullValue(ReplacedTy); + + const SCEV *RewriteFactor = SE->getIntegerSCEV(0, ReplacedTy); + IVExpr ReuseIV(SE->getIntegerSCEV(0, + Type::getInt32Ty(Preheader->getContext())), + SE->getIntegerSCEV(0, + Type::getInt32Ty(Preheader->getContext())), + 0); + + // Choose a strength-reduction strategy and prepare for it by creating + // the necessary PHIs and adjusting the bookkeeping. + if (ShouldUseFullStrengthReductionMode(UsersToProcess, L, + AllUsesAreAddresses, Stride)) { + PrepareToStrengthReduceFully(UsersToProcess, Stride, CommonExprs, L, + PreheaderRewriter); + } else { + // Emit the initial base value into the loop preheader. + CommonBaseV = PreheaderRewriter.expandCodeFor(CommonExprs, ReplacedTy, + PreInsertPt); + + // If all uses are addresses, check if it is possible to reuse an IV. The + // new IV must have a stride that is a multiple of the old stride; the + // multiple must be a number that can be encoded in the scale field of the + // target addressing mode; and we must have a valid instruction after this + // substitution, including the immediate field, if any. + RewriteFactor = CheckForIVReuse(HaveCommonExprs, AllUsesAreAddresses, + AllUsesAreOutsideLoop, + Stride, ReuseIV, ReplacedTy, + UsersToProcess); + if (!RewriteFactor->isZero()) + PrepareToStrengthReduceFromSmallerStride(UsersToProcess, CommonBaseV, + ReuseIV, PreInsertPt); + else { + IVIncInsertPt = FindIVIncInsertPt(UsersToProcess, L); + PrepareToStrengthReduceWithNewPhi(UsersToProcess, Stride, CommonExprs, + CommonBaseV, IVIncInsertPt, + L, PreheaderRewriter); + } + } + + // Process all the users now, replacing their strided uses with + // strength-reduced forms. This outer loop handles all bases, the inner + // loop handles all users of a particular base. + while (!UsersToProcess.empty()) { + const SCEV *Base = UsersToProcess.back().Base; + Instruction *Inst = UsersToProcess.back().Inst; + + // Emit the code for Base into the preheader. + Value *BaseV = 0; + if (!Base->isZero()) { + BaseV = PreheaderRewriter.expandCodeFor(Base, 0, PreInsertPt); + + DEBUG(errs() << " INSERTING code for BASE = " << *Base << ":"); + if (BaseV->hasName()) + DEBUG(errs() << " Result value name = %" << BaseV->getName()); + DEBUG(errs() << "\n"); + + // If BaseV is a non-zero constant, make sure that it gets inserted into + // the preheader, instead of being forward substituted into the uses. We + // do this by forcing a BitCast (noop cast) to be inserted into the + // preheader in this case. + if (!fitsInAddressMode(Base, getAccessType(Inst), TLI, false) && + isa(BaseV)) { + // We want this constant emitted into the preheader! This is just + // using cast as a copy so BitCast (no-op cast) is appropriate + BaseV = new BitCastInst(BaseV, BaseV->getType(), "preheaderinsert", + PreInsertPt); + } + } + + // Emit the code to add the immediate offset to the Phi value, just before + // the instructions that we identified as using this stride and base. + do { + // FIXME: Use emitted users to emit other users. + BasedUser &User = UsersToProcess.back(); + + DEBUG(errs() << " Examining "); + if (User.isUseOfPostIncrementedValue) + DEBUG(errs() << "postinc"); + else + DEBUG(errs() << "preinc"); + DEBUG(errs() << " use "); + DEBUG(WriteAsOperand(errs(), UsersToProcess.back().OperandValToReplace, + /*PrintType=*/false)); + DEBUG(errs() << " in Inst: " << *User.Inst); + + // If this instruction wants to use the post-incremented value, move it + // after the post-inc and use its value instead of the PHI. + Value *RewriteOp = User.Phi; + if (User.isUseOfPostIncrementedValue) { + RewriteOp = User.Phi->getIncomingValueForBlock(LatchBlock); + // If this user is in the loop, make sure it is the last thing in the + // loop to ensure it is dominated by the increment. In case it's the + // only use of the iv, the increment instruction is already before the + // use. + if (L->contains(User.Inst->getParent()) && User.Inst != IVIncInsertPt) + User.Inst->moveBefore(IVIncInsertPt); + } + + const SCEV *RewriteExpr = SE->getUnknown(RewriteOp); + + if (SE->getEffectiveSCEVType(RewriteOp->getType()) != + SE->getEffectiveSCEVType(ReplacedTy)) { + assert(SE->getTypeSizeInBits(RewriteOp->getType()) > + SE->getTypeSizeInBits(ReplacedTy) && + "Unexpected widening cast!"); + RewriteExpr = SE->getTruncateExpr(RewriteExpr, ReplacedTy); + } + + // If we had to insert new instructions for RewriteOp, we have to + // consider that they may not have been able to end up immediately + // next to RewriteOp, because non-PHI instructions may never precede + // PHI instructions in a block. In this case, remember where the last + // instruction was inserted so that if we're replacing a different + // PHI node, we can use the later point to expand the final + // RewriteExpr. + Instruction *NewBasePt = dyn_cast(RewriteOp); + if (RewriteOp == User.Phi) NewBasePt = 0; + + // Clear the SCEVExpander's expression map so that we are guaranteed + // to have the code emitted where we expect it. + Rewriter.clear(); + + // If we are reusing the iv, then it must be multiplied by a constant + // factor to take advantage of the addressing mode scale component. + if (!RewriteFactor->isZero()) { + // If we're reusing an IV with a nonzero base (currently this happens + // only when all reuses are outside the loop) subtract that base here. + // The base has been used to initialize the PHI node but we don't want + // it here. + if (!ReuseIV.Base->isZero()) { + const SCEV *typedBase = ReuseIV.Base; + if (SE->getEffectiveSCEVType(RewriteExpr->getType()) != + SE->getEffectiveSCEVType(ReuseIV.Base->getType())) { + // It's possible the original IV is a larger type than the new IV, + // in which case we have to truncate the Base. We checked in + // RequiresTypeConversion that this is valid. + assert(SE->getTypeSizeInBits(RewriteExpr->getType()) < + SE->getTypeSizeInBits(ReuseIV.Base->getType()) && + "Unexpected lengthening conversion!"); + typedBase = SE->getTruncateExpr(ReuseIV.Base, + RewriteExpr->getType()); + } + RewriteExpr = SE->getMinusSCEV(RewriteExpr, typedBase); + } + + // Multiply old variable, with base removed, by new scale factor. + RewriteExpr = SE->getMulExpr(RewriteFactor, + RewriteExpr); + + // The common base is emitted in the loop preheader. But since we + // are reusing an IV, it has not been used to initialize the PHI node. + // Add it to the expression used to rewrite the uses. + // When this use is outside the loop, we earlier subtracted the + // common base, and are adding it back here. Use the same expression + // as before, rather than CommonBaseV, so DAGCombiner will zap it. + if (!CommonExprs->isZero()) { + if (L->contains(User.Inst->getParent())) + RewriteExpr = SE->getAddExpr(RewriteExpr, + SE->getUnknown(CommonBaseV)); + else + RewriteExpr = SE->getAddExpr(RewriteExpr, CommonExprs); + } + } + + // Now that we know what we need to do, insert code before User for the + // immediate and any loop-variant expressions. + if (BaseV) + // Add BaseV to the PHI value if needed. + RewriteExpr = SE->getAddExpr(RewriteExpr, SE->getUnknown(BaseV)); + + User.RewriteInstructionToUseNewBase(RewriteExpr, NewBasePt, + Rewriter, L, this, *LI, + DeadInsts); + + // Mark old value we replaced as possibly dead, so that it is eliminated + // if we just replaced the last use of that value. + DeadInsts.push_back(User.OperandValToReplace); + + UsersToProcess.pop_back(); + ++NumReduced; + + // If there are any more users to process with the same base, process them + // now. We sorted by base above, so we just have to check the last elt. + } while (!UsersToProcess.empty() && UsersToProcess.back().Base == Base); + // TODO: Next, find out which base index is the most common, pull it out. + } + + // IMPORTANT TODO: Figure out how to partition the IV's with this stride, but + // different starting values, into different PHIs. +} + +void LoopStrengthReduce::StrengthReduceIVUsers(Loop *L) { + // Note: this processes each stride/type pair individually. All users + // passed into StrengthReduceIVUsersOfStride have the same type AND stride. + // Also, note that we iterate over IVUsesByStride indirectly by using + // StrideOrder. This extra layer of indirection makes the ordering of + // strides deterministic - not dependent on map order. + for (unsigned Stride = 0, e = IU->StrideOrder.size(); Stride != e; ++Stride) { + std::map::iterator SI = + IU->IVUsesByStride.find(IU->StrideOrder[Stride]); + assert(SI != IU->IVUsesByStride.end() && "Stride doesn't exist!"); + // FIXME: Generalize to non-affine IV's. + if (!SI->first->isLoopInvariant(L)) + continue; + StrengthReduceIVUsersOfStride(SI->first, *SI->second, L); + } +} + +/// FindIVUserForCond - If Cond has an operand that is an expression of an IV, +/// set the IV user and stride information and return true, otherwise return +/// false. +bool LoopStrengthReduce::FindIVUserForCond(ICmpInst *Cond, + IVStrideUse *&CondUse, + const SCEV* &CondStride) { + for (unsigned Stride = 0, e = IU->StrideOrder.size(); + Stride != e && !CondUse; ++Stride) { + std::map::iterator SI = + IU->IVUsesByStride.find(IU->StrideOrder[Stride]); + assert(SI != IU->IVUsesByStride.end() && "Stride doesn't exist!"); + + for (ilist::iterator UI = SI->second->Users.begin(), + E = SI->second->Users.end(); UI != E; ++UI) + if (UI->getUser() == Cond) { + // NOTE: we could handle setcc instructions with multiple uses here, but + // InstCombine does it as well for simple uses, it's not clear that it + // occurs enough in real life to handle. + CondUse = UI; + CondStride = SI->first; + return true; + } + } + return false; +} + +namespace { + // Constant strides come first which in turns are sorted by their absolute + // values. If absolute values are the same, then positive strides comes first. + // e.g. + // 4, -1, X, 1, 2 ==> 1, -1, 2, 4, X + struct StrideCompare { + const ScalarEvolution *SE; + explicit StrideCompare(const ScalarEvolution *se) : SE(se) {} + + bool operator()(const SCEV *const &LHS, const SCEV *const &RHS) { + const SCEVConstant *LHSC = dyn_cast(LHS); + const SCEVConstant *RHSC = dyn_cast(RHS); + if (LHSC && RHSC) { + int64_t LV = LHSC->getValue()->getSExtValue(); + int64_t RV = RHSC->getValue()->getSExtValue(); + uint64_t ALV = (LV < 0) ? -LV : LV; + uint64_t ARV = (RV < 0) ? -RV : RV; + if (ALV == ARV) { + if (LV != RV) + return LV > RV; + } else { + return ALV < ARV; + } + + // If it's the same value but different type, sort by bit width so + // that we emit larger induction variables before smaller + // ones, letting the smaller be re-written in terms of larger ones. + return SE->getTypeSizeInBits(RHS->getType()) < + SE->getTypeSizeInBits(LHS->getType()); + } + return LHSC && !RHSC; + } + }; +} + +/// ChangeCompareStride - If a loop termination compare instruction is the +/// only use of its stride, and the compaison is against a constant value, +/// try eliminate the stride by moving the compare instruction to another +/// stride and change its constant operand accordingly. e.g. +/// +/// loop: +/// ... +/// v1 = v1 + 3 +/// v2 = v2 + 1 +/// if (v2 < 10) goto loop +/// => +/// loop: +/// ... +/// v1 = v1 + 3 +/// if (v1 < 30) goto loop +ICmpInst *LoopStrengthReduce::ChangeCompareStride(Loop *L, ICmpInst *Cond, + IVStrideUse* &CondUse, + const SCEV* &CondStride, + bool PostPass) { + // If there's only one stride in the loop, there's nothing to do here. + if (IU->StrideOrder.size() < 2) + return Cond; + // If there are other users of the condition's stride, don't bother + // trying to change the condition because the stride will still + // remain. + std::map::iterator I = + IU->IVUsesByStride.find(CondStride); + if (I == IU->IVUsesByStride.end()) + return Cond; + if (I->second->Users.size() > 1) { + for (ilist::iterator II = I->second->Users.begin(), + EE = I->second->Users.end(); II != EE; ++II) { + if (II->getUser() == Cond) + continue; + if (!isInstructionTriviallyDead(II->getUser())) + return Cond; + } + } + // Only handle constant strides for now. + const SCEVConstant *SC = dyn_cast(CondStride); + if (!SC) return Cond; + + ICmpInst::Predicate Predicate = Cond->getPredicate(); + int64_t CmpSSInt = SC->getValue()->getSExtValue(); + unsigned BitWidth = SE->getTypeSizeInBits(CondStride->getType()); + uint64_t SignBit = 1ULL << (BitWidth-1); + const Type *CmpTy = Cond->getOperand(0)->getType(); + const Type *NewCmpTy = NULL; + unsigned TyBits = SE->getTypeSizeInBits(CmpTy); + unsigned NewTyBits = 0; + const SCEV *NewStride = NULL; + Value *NewCmpLHS = NULL; + Value *NewCmpRHS = NULL; + int64_t Scale = 1; + const SCEV *NewOffset = SE->getIntegerSCEV(0, CmpTy); + + if (ConstantInt *C = dyn_cast(Cond->getOperand(1))) { + int64_t CmpVal = C->getValue().getSExtValue(); + + // Check the relevant induction variable for conformance to + // the pattern. + const SCEV *IV = SE->getSCEV(Cond->getOperand(0)); + const SCEVAddRecExpr *AR = dyn_cast(IV); + if (!AR || !AR->isAffine()) + return Cond; + + const SCEVConstant *StartC = dyn_cast(AR->getStart()); + // Check stride constant and the comparision constant signs to detect + // overflow. + if (StartC) { + if ((StartC->getValue()->getSExtValue() < CmpVal && CmpSSInt < 0) || + (StartC->getValue()->getSExtValue() > CmpVal && CmpSSInt > 0)) + return Cond; + } else { + // More restrictive check for the other cases. + if ((CmpVal & SignBit) != (CmpSSInt & SignBit)) + return Cond; + } + + // Look for a suitable stride / iv as replacement. + for (unsigned i = 0, e = IU->StrideOrder.size(); i != e; ++i) { + std::map::iterator SI = + IU->IVUsesByStride.find(IU->StrideOrder[i]); + if (!isa(SI->first) || SI->second->Users.empty()) + continue; + int64_t SSInt = cast(SI->first)->getValue()->getSExtValue(); + if (SSInt == CmpSSInt || + abs64(SSInt) < abs64(CmpSSInt) || + (SSInt % CmpSSInt) != 0) + continue; + + Scale = SSInt / CmpSSInt; + int64_t NewCmpVal = CmpVal * Scale; + + // If old icmp value fits in icmp immediate field, but the new one doesn't + // try something else. + if (TLI && + TLI->isLegalICmpImmediate(CmpVal) && + !TLI->isLegalICmpImmediate(NewCmpVal)) + continue; + + APInt Mul = APInt(BitWidth*2, CmpVal, true); + Mul = Mul * APInt(BitWidth*2, Scale, true); + // Check for overflow. + if (!Mul.isSignedIntN(BitWidth)) + continue; + // Check for overflow in the stride's type too. + if (!Mul.isSignedIntN(SE->getTypeSizeInBits(SI->first->getType()))) + continue; + + // Watch out for overflow. + if (ICmpInst::isSigned(Predicate) && + (CmpVal & SignBit) != (NewCmpVal & SignBit)) + continue; + + // Pick the best iv to use trying to avoid a cast. + NewCmpLHS = NULL; + for (ilist::iterator UI = SI->second->Users.begin(), + E = SI->second->Users.end(); UI != E; ++UI) { + Value *Op = UI->getOperandValToReplace(); + + // If the IVStrideUse implies a cast, check for an actual cast which + // can be used to find the original IV expression. + if (SE->getEffectiveSCEVType(Op->getType()) != + SE->getEffectiveSCEVType(SI->first->getType())) { + CastInst *CI = dyn_cast(Op); + // If it's not a simple cast, it's complicated. + if (!CI) + continue; + // If it's a cast from a type other than the stride type, + // it's complicated. + if (CI->getOperand(0)->getType() != SI->first->getType()) + continue; + // Ok, we found the IV expression in the stride's type. + Op = CI->getOperand(0); + } + + NewCmpLHS = Op; + if (NewCmpLHS->getType() == CmpTy) + break; + } + if (!NewCmpLHS) + continue; + + NewCmpTy = NewCmpLHS->getType(); + NewTyBits = SE->getTypeSizeInBits(NewCmpTy); + const Type *NewCmpIntTy = IntegerType::get(Cond->getContext(), NewTyBits); + if (RequiresTypeConversion(NewCmpTy, CmpTy)) { + // Check if it is possible to rewrite it using + // an iv / stride of a smaller integer type. + unsigned Bits = NewTyBits; + if (ICmpInst::isSigned(Predicate)) + --Bits; + uint64_t Mask = (1ULL << Bits) - 1; + if (((uint64_t)NewCmpVal & Mask) != (uint64_t)NewCmpVal) + continue; + } + + // Don't rewrite if use offset is non-constant and the new type is + // of a different type. + // FIXME: too conservative? + if (NewTyBits != TyBits && !isa(CondUse->getOffset())) + continue; + + if (!PostPass) { + bool AllUsesAreAddresses = true; + bool AllUsesAreOutsideLoop = true; + std::vector UsersToProcess; + const SCEV *CommonExprs = CollectIVUsers(SI->first, *SI->second, L, + AllUsesAreAddresses, + AllUsesAreOutsideLoop, + UsersToProcess); + // Avoid rewriting the compare instruction with an iv of new stride + // if it's likely the new stride uses will be rewritten using the + // stride of the compare instruction. + if (AllUsesAreAddresses && + ValidScale(!CommonExprs->isZero(), Scale, UsersToProcess)) + continue; + } + + // Avoid rewriting the compare instruction with an iv which has + // implicit extension or truncation built into it. + // TODO: This is over-conservative. + if (SE->getTypeSizeInBits(CondUse->getOffset()->getType()) != TyBits) + continue; + + // If scale is negative, use swapped predicate unless it's testing + // for equality. + if (Scale < 0 && !Cond->isEquality()) + Predicate = ICmpInst::getSwappedPredicate(Predicate); + + NewStride = IU->StrideOrder[i]; + if (!isa(NewCmpTy)) + NewCmpRHS = ConstantInt::get(NewCmpTy, NewCmpVal); + else { + Constant *CI = ConstantInt::get(NewCmpIntTy, NewCmpVal); + NewCmpRHS = ConstantExpr::getIntToPtr(CI, NewCmpTy); + } + NewOffset = TyBits == NewTyBits + ? SE->getMulExpr(CondUse->getOffset(), + SE->getConstant(CmpTy, Scale)) + : SE->getConstant(NewCmpIntTy, + cast(CondUse->getOffset())->getValue() + ->getSExtValue()*Scale); + break; + } + } + + // Forgo this transformation if it the increment happens to be + // unfortunately positioned after the condition, and the condition + // has multiple uses which prevent it from being moved immediately + // before the branch. See + // test/Transforms/LoopStrengthReduce/change-compare-stride-trickiness-*.ll + // for an example of this situation. + if (!Cond->hasOneUse()) { + for (BasicBlock::iterator I = Cond, E = Cond->getParent()->end(); + I != E; ++I) + if (I == NewCmpLHS) + return Cond; + } + + if (NewCmpRHS) { + // Create a new compare instruction using new stride / iv. + ICmpInst *OldCond = Cond; + // Insert new compare instruction. + Cond = new ICmpInst(OldCond, Predicate, NewCmpLHS, NewCmpRHS, + L->getHeader()->getName() + ".termcond"); + + DEBUG(errs() << " Change compare stride in Inst " << *OldCond); + DEBUG(errs() << " to " << *Cond << '\n'); + + // Remove the old compare instruction. The old indvar is probably dead too. + DeadInsts.push_back(CondUse->getOperandValToReplace()); + OldCond->replaceAllUsesWith(Cond); + OldCond->eraseFromParent(); + + IU->IVUsesByStride[NewStride]->addUser(NewOffset, Cond, NewCmpLHS); + CondUse = &IU->IVUsesByStride[NewStride]->Users.back(); + CondStride = NewStride; + ++NumEliminated; + Changed = true; + } + + return Cond; +} + +/// OptimizeMax - Rewrite the loop's terminating condition if it uses +/// a max computation. +/// +/// This is a narrow solution to a specific, but acute, problem. For loops +/// like this: +/// +/// i = 0; +/// do { +/// p[i] = 0.0; +/// } while (++i < n); +/// +/// the trip count isn't just 'n', because 'n' might not be positive. And +/// unfortunately this can come up even for loops where the user didn't use +/// a C do-while loop. For example, seemingly well-behaved top-test loops +/// will commonly be lowered like this: +// +/// if (n > 0) { +/// i = 0; +/// do { +/// p[i] = 0.0; +/// } while (++i < n); +/// } +/// +/// and then it's possible for subsequent optimization to obscure the if +/// test in such a way that indvars can't find it. +/// +/// When indvars can't find the if test in loops like this, it creates a +/// max expression, which allows it to give the loop a canonical +/// induction variable: +/// +/// i = 0; +/// max = n < 1 ? 1 : n; +/// do { +/// p[i] = 0.0; +/// } while (++i != max); +/// +/// Canonical induction variables are necessary because the loop passes +/// are designed around them. The most obvious example of this is the +/// LoopInfo analysis, which doesn't remember trip count values. It +/// expects to be able to rediscover the trip count each time it is +/// needed, and it does this using a simple analyis that only succeeds if +/// the loop has a canonical induction variable. +/// +/// However, when it comes time to generate code, the maximum operation +/// can be quite costly, especially if it's inside of an outer loop. +/// +/// This function solves this problem by detecting this type of loop and +/// rewriting their conditions from ICMP_NE back to ICMP_SLT, and deleting +/// the instructions for the maximum computation. +/// +ICmpInst *LoopStrengthReduce::OptimizeMax(Loop *L, ICmpInst *Cond, + IVStrideUse* &CondUse) { + // Check that the loop matches the pattern we're looking for. + if (Cond->getPredicate() != CmpInst::ICMP_EQ && + Cond->getPredicate() != CmpInst::ICMP_NE) + return Cond; + + SelectInst *Sel = dyn_cast(Cond->getOperand(1)); + if (!Sel || !Sel->hasOneUse()) return Cond; + + const SCEV *BackedgeTakenCount = SE->getBackedgeTakenCount(L); + if (isa(BackedgeTakenCount)) + return Cond; + const SCEV *One = SE->getIntegerSCEV(1, BackedgeTakenCount->getType()); + + // Add one to the backedge-taken count to get the trip count. + const SCEV *IterationCount = SE->getAddExpr(BackedgeTakenCount, One); + + // Check for a max calculation that matches the pattern. + if (!isa(IterationCount) && !isa(IterationCount)) + return Cond; + const SCEVNAryExpr *Max = cast(IterationCount); + if (Max != SE->getSCEV(Sel)) return Cond; + + // To handle a max with more than two operands, this optimization would + // require additional checking and setup. + if (Max->getNumOperands() != 2) + return Cond; + + const SCEV *MaxLHS = Max->getOperand(0); + const SCEV *MaxRHS = Max->getOperand(1); + if (!MaxLHS || MaxLHS != One) return Cond; + + // Check the relevant induction variable for conformance to + // the pattern. + const SCEV *IV = SE->getSCEV(Cond->getOperand(0)); + const SCEVAddRecExpr *AR = dyn_cast(IV); + if (!AR || !AR->isAffine() || + AR->getStart() != One || + AR->getStepRecurrence(*SE) != One) + return Cond; + + assert(AR->getLoop() == L && + "Loop condition operand is an addrec in a different loop!"); + + // Check the right operand of the select, and remember it, as it will + // be used in the new comparison instruction. + Value *NewRHS = 0; + if (SE->getSCEV(Sel->getOperand(1)) == MaxRHS) + NewRHS = Sel->getOperand(1); + else if (SE->getSCEV(Sel->getOperand(2)) == MaxRHS) + NewRHS = Sel->getOperand(2); + if (!NewRHS) return Cond; + + // Determine the new comparison opcode. It may be signed or unsigned, + // and the original comparison may be either equality or inequality. + CmpInst::Predicate Pred = + isa(Max) ? CmpInst::ICMP_SLT : CmpInst::ICMP_ULT; + if (Cond->getPredicate() == CmpInst::ICMP_EQ) + Pred = CmpInst::getInversePredicate(Pred); + + // Ok, everything looks ok to change the condition into an SLT or SGE and + // delete the max calculation. + ICmpInst *NewCond = + new ICmpInst(Cond, Pred, Cond->getOperand(0), NewRHS, "scmp"); + + // Delete the max calculation instructions. + Cond->replaceAllUsesWith(NewCond); + CondUse->setUser(NewCond); + Instruction *Cmp = cast(Sel->getOperand(0)); + Cond->eraseFromParent(); + Sel->eraseFromParent(); + if (Cmp->use_empty()) + Cmp->eraseFromParent(); + return NewCond; +} + +/// OptimizeShadowIV - If IV is used in a int-to-float cast +/// inside the loop then try to eliminate the cast opeation. +void LoopStrengthReduce::OptimizeShadowIV(Loop *L) { + + const SCEV *BackedgeTakenCount = SE->getBackedgeTakenCount(L); + if (isa(BackedgeTakenCount)) + return; + + for (unsigned Stride = 0, e = IU->StrideOrder.size(); Stride != e; + ++Stride) { + std::map::iterator SI = + IU->IVUsesByStride.find(IU->StrideOrder[Stride]); + assert(SI != IU->IVUsesByStride.end() && "Stride doesn't exist!"); + if (!isa(SI->first)) + continue; + + for (ilist::iterator UI = SI->second->Users.begin(), + E = SI->second->Users.end(); UI != E; /* empty */) { + ilist::iterator CandidateUI = UI; + ++UI; + Instruction *ShadowUse = CandidateUI->getUser(); + const Type *DestTy = NULL; + + /* If shadow use is a int->float cast then insert a second IV + to eliminate this cast. + + for (unsigned i = 0; i < n; ++i) + foo((double)i); + + is transformed into + + double d = 0.0; + for (unsigned i = 0; i < n; ++i, ++d) + foo(d); + */ + if (UIToFPInst *UCast = dyn_cast(CandidateUI->getUser())) + DestTy = UCast->getDestTy(); + else if (SIToFPInst *SCast = dyn_cast(CandidateUI->getUser())) + DestTy = SCast->getDestTy(); + if (!DestTy) continue; + + if (TLI) { + // If target does not support DestTy natively then do not apply + // this transformation. + EVT DVT = TLI->getValueType(DestTy); + if (!TLI->isTypeLegal(DVT)) continue; + } + + PHINode *PH = dyn_cast(ShadowUse->getOperand(0)); + if (!PH) continue; + if (PH->getNumIncomingValues() != 2) continue; + + const Type *SrcTy = PH->getType(); + int Mantissa = DestTy->getFPMantissaWidth(); + if (Mantissa == -1) continue; + if ((int)SE->getTypeSizeInBits(SrcTy) > Mantissa) + continue; + + unsigned Entry, Latch; + if (PH->getIncomingBlock(0) == L->getLoopPreheader()) { + Entry = 0; + Latch = 1; + } else { + Entry = 1; + Latch = 0; + } + + ConstantInt *Init = dyn_cast(PH->getIncomingValue(Entry)); + if (!Init) continue; + Constant *NewInit = ConstantFP::get(DestTy, Init->getZExtValue()); + + BinaryOperator *Incr = + dyn_cast(PH->getIncomingValue(Latch)); + if (!Incr) continue; + if (Incr->getOpcode() != Instruction::Add + && Incr->getOpcode() != Instruction::Sub) + continue; + + /* Initialize new IV, double d = 0.0 in above example. */ + ConstantInt *C = NULL; + if (Incr->getOperand(0) == PH) + C = dyn_cast(Incr->getOperand(1)); + else if (Incr->getOperand(1) == PH) + C = dyn_cast(Incr->getOperand(0)); + else + continue; + + if (!C) continue; + + // Ignore negative constants, as the code below doesn't handle them + // correctly. TODO: Remove this restriction. + if (!C->getValue().isStrictlyPositive()) continue; + + /* Add new PHINode. */ + PHINode *NewPH = PHINode::Create(DestTy, "IV.S.", PH); + + /* create new increment. '++d' in above example. */ + Constant *CFP = ConstantFP::get(DestTy, C->getZExtValue()); + BinaryOperator *NewIncr = + BinaryOperator::Create(Incr->getOpcode() == Instruction::Add ? + Instruction::FAdd : Instruction::FSub, + NewPH, CFP, "IV.S.next.", Incr); + + NewPH->addIncoming(NewInit, PH->getIncomingBlock(Entry)); + NewPH->addIncoming(NewIncr, PH->getIncomingBlock(Latch)); + + /* Remove cast operation */ + ShadowUse->replaceAllUsesWith(NewPH); + ShadowUse->eraseFromParent(); + NumShadow++; + break; + } + } +} + +/// OptimizeIndvars - Now that IVUsesByStride is set up with all of the indvar +/// uses in the loop, look to see if we can eliminate some, in favor of using +/// common indvars for the different uses. +void LoopStrengthReduce::OptimizeIndvars(Loop *L) { + // TODO: implement optzns here. + + OptimizeShadowIV(L); +} + +bool LoopStrengthReduce::StrideMightBeShared(const SCEV* Stride, Loop *L, + bool CheckPreInc) { + int64_t SInt = cast(Stride)->getValue()->getSExtValue(); + for (unsigned i = 0, e = IU->StrideOrder.size(); i != e; ++i) { + std::map::iterator SI = + IU->IVUsesByStride.find(IU->StrideOrder[i]); + const SCEV *Share = SI->first; + if (!isa(SI->first) || Share == Stride) + continue; + int64_t SSInt = cast(Share)->getValue()->getSExtValue(); + if (SSInt == SInt) + return true; // This can definitely be reused. + if (unsigned(abs64(SSInt)) < SInt || (SSInt % SInt) != 0) + continue; + int64_t Scale = SSInt / SInt; + bool AllUsesAreAddresses = true; + bool AllUsesAreOutsideLoop = true; + std::vector UsersToProcess; + const SCEV *CommonExprs = CollectIVUsers(SI->first, *SI->second, L, + AllUsesAreAddresses, + AllUsesAreOutsideLoop, + UsersToProcess); + if (AllUsesAreAddresses && + ValidScale(!CommonExprs->isZero(), Scale, UsersToProcess)) { + if (!CheckPreInc) + return true; + // Any pre-inc iv use? + IVUsersOfOneStride &StrideUses = *IU->IVUsesByStride[Share]; + for (ilist::iterator I = StrideUses.Users.begin(), + E = StrideUses.Users.end(); I != E; ++I) { + if (!I->isUseOfPostIncrementedValue()) + return true; + } + } + } + return false; +} + +/// isUsedByExitBranch - Return true if icmp is used by a loop terminating +/// conditional branch or it's and / or with other conditions before being used +/// as the condition. +static bool isUsedByExitBranch(ICmpInst *Cond, Loop *L) { + BasicBlock *CondBB = Cond->getParent(); + if (!L->isLoopExiting(CondBB)) + return false; + BranchInst *TermBr = dyn_cast(CondBB->getTerminator()); + if (!TermBr || !TermBr->isConditional()) + return false; + + Value *User = *Cond->use_begin(); + Instruction *UserInst = dyn_cast(User); + while (UserInst && + (UserInst->getOpcode() == Instruction::And || + UserInst->getOpcode() == Instruction::Or)) { + if (!UserInst->hasOneUse() || UserInst->getParent() != CondBB) + return false; + User = *User->use_begin(); + UserInst = dyn_cast(User); + } + return User == TermBr; +} + +static bool ShouldCountToZero(ICmpInst *Cond, IVStrideUse* &CondUse, + ScalarEvolution *SE, Loop *L, + const TargetLowering *TLI = 0) { + if (!L->contains(Cond->getParent())) + return false; + + if (!isa(CondUse->getOffset())) + return false; + + // Handle only tests for equality for the moment. + if (!Cond->isEquality() || !Cond->hasOneUse()) + return false; + if (!isUsedByExitBranch(Cond, L)) + return false; + + Value *CondOp0 = Cond->getOperand(0); + const SCEV *IV = SE->getSCEV(CondOp0); + const SCEVAddRecExpr *AR = dyn_cast(IV); + if (!AR || !AR->isAffine()) + return false; + + const SCEVConstant *SC = dyn_cast(AR->getStepRecurrence(*SE)); + if (!SC || SC->getValue()->getSExtValue() < 0) + // If it's already counting down, don't do anything. + return false; + + // If the RHS of the comparison is not an loop invariant, the rewrite + // cannot be done. Also bail out if it's already comparing against a zero. + // If we are checking this before cmp stride optimization, check if it's + // comparing against a already legal immediate. + Value *RHS = Cond->getOperand(1); + ConstantInt *RHSC = dyn_cast(RHS); + if (!L->isLoopInvariant(RHS) || + (RHSC && RHSC->isZero()) || + (RHSC && TLI && TLI->isLegalICmpImmediate(RHSC->getSExtValue()))) + return false; + + // Make sure the IV is only used for counting. Value may be preinc or + // postinc; 2 uses in either case. + if (!CondOp0->hasNUses(2)) + return false; + + return true; +} + +/// OptimizeLoopTermCond - Change loop terminating condition to use the +/// postinc iv when possible. +void LoopStrengthReduce::OptimizeLoopTermCond(Loop *L) { + BasicBlock *LatchBlock = L->getLoopLatch(); + bool LatchExit = L->isLoopExiting(LatchBlock); + SmallVector ExitingBlocks; + L->getExitingBlocks(ExitingBlocks); + + for (unsigned i = 0, e = ExitingBlocks.size(); i != e; ++i) { + BasicBlock *ExitingBlock = ExitingBlocks[i]; + + // Finally, get the terminating condition for the loop if possible. If we + // can, we want to change it to use a post-incremented version of its + // induction variable, to allow coalescing the live ranges for the IV into + // one register value. + + BranchInst *TermBr = dyn_cast(ExitingBlock->getTerminator()); + if (!TermBr) + continue; + // FIXME: Overly conservative, termination condition could be an 'or' etc.. + if (TermBr->isUnconditional() || !isa(TermBr->getCondition())) + continue; + + // Search IVUsesByStride to find Cond's IVUse if there is one. + IVStrideUse *CondUse = 0; + const SCEV *CondStride = 0; + ICmpInst *Cond = cast(TermBr->getCondition()); + if (!FindIVUserForCond(Cond, CondUse, CondStride)) + continue; + + // If the latch block is exiting and it's not a single block loop, it's + // not safe to use postinc iv in other exiting blocks. FIXME: overly + // conservative? How about icmp stride optimization? + bool UsePostInc = !(e > 1 && LatchExit && ExitingBlock != LatchBlock); + if (UsePostInc && ExitingBlock != LatchBlock) { + if (!Cond->hasOneUse()) + // See below, we don't want the condition to be cloned. + UsePostInc = false; + else { + // If exiting block is the latch block, we know it's safe and profitable + // to transform the icmp to use post-inc iv. Otherwise do so only if it + // would not reuse another iv and its iv would be reused by other uses. + // We are optimizing for the case where the icmp is the only use of the + // iv. + IVUsersOfOneStride &StrideUses = *IU->IVUsesByStride[CondStride]; + for (ilist::iterator I = StrideUses.Users.begin(), + E = StrideUses.Users.end(); I != E; ++I) { + if (I->getUser() == Cond) + continue; + if (!I->isUseOfPostIncrementedValue()) { + UsePostInc = false; + break; + } + } + } + + // If iv for the stride might be shared and any of the users use pre-inc + // iv might be used, then it's not safe to use post-inc iv. + if (UsePostInc && + isa(CondStride) && + StrideMightBeShared(CondStride, L, true)) + UsePostInc = false; + } + + // If the trip count is computed in terms of a max (due to ScalarEvolution + // being unable to find a sufficient guard, for example), change the loop + // comparison to use SLT or ULT instead of NE. + Cond = OptimizeMax(L, Cond, CondUse); + + // If possible, change stride and operands of the compare instruction to + // eliminate one stride. However, avoid rewriting the compare instruction + // with an iv of new stride if it's likely the new stride uses will be + // rewritten using the stride of the compare instruction. + if (ExitingBlock == LatchBlock && isa(CondStride)) { + // If the condition stride is a constant and it's the only use, we might + // want to optimize it first by turning it to count toward zero. + if (!StrideMightBeShared(CondStride, L, false) && + !ShouldCountToZero(Cond, CondUse, SE, L, TLI)) + Cond = ChangeCompareStride(L, Cond, CondUse, CondStride); + } + + if (!UsePostInc) + continue; + + DEBUG(errs() << " Change loop exiting icmp to use postinc iv: " + << *Cond << '\n'); + + // It's possible for the setcc instruction to be anywhere in the loop, and + // possible for it to have multiple users. If it is not immediately before + // the exiting block branch, move it. + if (&*++BasicBlock::iterator(Cond) != (Instruction*)TermBr) { + if (Cond->hasOneUse()) { // Condition has a single use, just move it. + Cond->moveBefore(TermBr); + } else { + // Otherwise, clone the terminating condition and insert into the + // loopend. + Cond = cast(Cond->clone()); + Cond->setName(L->getHeader()->getName() + ".termcond"); + ExitingBlock->getInstList().insert(TermBr, Cond); + + // Clone the IVUse, as the old use still exists! + IU->IVUsesByStride[CondStride]->addUser(CondUse->getOffset(), Cond, + CondUse->getOperandValToReplace()); + CondUse = &IU->IVUsesByStride[CondStride]->Users.back(); + } + } + + // If we get to here, we know that we can transform the setcc instruction to + // use the post-incremented version of the IV, allowing us to coalesce the + // live ranges for the IV correctly. + CondUse->setOffset(SE->getMinusSCEV(CondUse->getOffset(), CondStride)); + CondUse->setIsUseOfPostIncrementedValue(true); + Changed = true; + + ++NumLoopCond; + } +} + +bool LoopStrengthReduce::OptimizeLoopCountIVOfStride(const SCEV* &Stride, + IVStrideUse* &CondUse, + Loop *L) { + // If the only use is an icmp of a loop exiting conditional branch, then + // attempt the optimization. + BasedUser User = BasedUser(*CondUse, SE); + assert(isa(User.Inst) && "Expecting an ICMPInst!"); + ICmpInst *Cond = cast(User.Inst); + + // Less strict check now that compare stride optimization is done. + if (!ShouldCountToZero(Cond, CondUse, SE, L)) + return false; + + Value *CondOp0 = Cond->getOperand(0); + PHINode *PHIExpr = dyn_cast(CondOp0); + Instruction *Incr; + if (!PHIExpr) { + // Value tested is postinc. Find the phi node. + Incr = dyn_cast(CondOp0); + // FIXME: Just use User.OperandValToReplace here? + if (!Incr || Incr->getOpcode() != Instruction::Add) + return false; + + PHIExpr = dyn_cast(Incr->getOperand(0)); + if (!PHIExpr) + return false; + // 1 use for preinc value, the increment. + if (!PHIExpr->hasOneUse()) + return false; + } else { + assert(isa(CondOp0) && + "Unexpected loop exiting counting instruction sequence!"); + PHIExpr = cast(CondOp0); + // Value tested is preinc. Find the increment. + // A CmpInst is not a BinaryOperator; we depend on this. + Instruction::use_iterator UI = PHIExpr->use_begin(); + Incr = dyn_cast(UI); + if (!Incr) + Incr = dyn_cast(++UI); + // One use for postinc value, the phi. Unnecessarily conservative? + if (!Incr || !Incr->hasOneUse() || Incr->getOpcode() != Instruction::Add) + return false; + } + + // Replace the increment with a decrement. + DEBUG(errs() << "LSR: Examining use "); + DEBUG(WriteAsOperand(errs(), CondOp0, /*PrintType=*/false)); + DEBUG(errs() << " in Inst: " << *Cond << '\n'); + BinaryOperator *Decr = BinaryOperator::Create(Instruction::Sub, + Incr->getOperand(0), Incr->getOperand(1), "tmp", Incr); + Incr->replaceAllUsesWith(Decr); + Incr->eraseFromParent(); + + // Substitute endval-startval for the original startval, and 0 for the + // original endval. Since we're only testing for equality this is OK even + // if the computation wraps around. + BasicBlock *Preheader = L->getLoopPreheader(); + Instruction *PreInsertPt = Preheader->getTerminator(); + unsigned InBlock = L->contains(PHIExpr->getIncomingBlock(0)) ? 1 : 0; + Value *StartVal = PHIExpr->getIncomingValue(InBlock); + Value *EndVal = Cond->getOperand(1); + DEBUG(errs() << " Optimize loop counting iv to count down [" + << *EndVal << " .. " << *StartVal << "]\n"); + + // FIXME: check for case where both are constant. + Constant* Zero = ConstantInt::get(Cond->getOperand(1)->getType(), 0); + BinaryOperator *NewStartVal = BinaryOperator::Create(Instruction::Sub, + EndVal, StartVal, "tmp", PreInsertPt); + PHIExpr->setIncomingValue(InBlock, NewStartVal); + Cond->setOperand(1, Zero); + DEBUG(errs() << " New icmp: " << *Cond << "\n"); + + int64_t SInt = cast(Stride)->getValue()->getSExtValue(); + const SCEV *NewStride = 0; + bool Found = false; + for (unsigned i = 0, e = IU->StrideOrder.size(); i != e; ++i) { + const SCEV *OldStride = IU->StrideOrder[i]; + if (const SCEVConstant *SC = dyn_cast(OldStride)) + if (SC->getValue()->getSExtValue() == -SInt) { + Found = true; + NewStride = OldStride; + break; + } + } + + if (!Found) + NewStride = SE->getIntegerSCEV(-SInt, Stride->getType()); + IU->AddUser(NewStride, CondUse->getOffset(), Cond, Cond->getOperand(0)); + IU->IVUsesByStride[Stride]->removeUser(CondUse); + + CondUse = &IU->IVUsesByStride[NewStride]->Users.back(); + Stride = NewStride; + + ++NumCountZero; + + return true; +} + +/// OptimizeLoopCountIV - If, after all sharing of IVs, the IV used for deciding +/// when to exit the loop is used only for that purpose, try to rearrange things +/// so it counts down to a test against zero. +bool LoopStrengthReduce::OptimizeLoopCountIV(Loop *L) { + bool ThisChanged = false; + for (unsigned i = 0, e = IU->StrideOrder.size(); i != e; ++i) { + const SCEV *Stride = IU->StrideOrder[i]; + std::map::iterator SI = + IU->IVUsesByStride.find(Stride); + assert(SI != IU->IVUsesByStride.end() && "Stride doesn't exist!"); + // FIXME: Generalize to non-affine IV's. + if (!SI->first->isLoopInvariant(L)) + continue; + // If stride is a constant and it has an icmpinst use, check if we can + // optimize the loop to count down. + if (isa(Stride) && SI->second->Users.size() == 1) { + Instruction *User = SI->second->Users.begin()->getUser(); + if (!isa(User)) + continue; + const SCEV *CondStride = Stride; + IVStrideUse *Use = &*SI->second->Users.begin(); + if (!OptimizeLoopCountIVOfStride(CondStride, Use, L)) + continue; + ThisChanged = true; + + // Now check if it's possible to reuse this iv for other stride uses. + for (unsigned j = 0, ee = IU->StrideOrder.size(); j != ee; ++j) { + const SCEV *SStride = IU->StrideOrder[j]; + if (SStride == CondStride) + continue; + std::map::iterator SII = + IU->IVUsesByStride.find(SStride); + assert(SII != IU->IVUsesByStride.end() && "Stride doesn't exist!"); + // FIXME: Generalize to non-affine IV's. + if (!SII->first->isLoopInvariant(L)) + continue; + // FIXME: Rewrite other stride using CondStride. + } + } + } + + Changed |= ThisChanged; + return ThisChanged; +} + +bool LoopStrengthReduce::runOnLoop(Loop *L, LPPassManager &LPM) { + IU = &getAnalysis(); + LI = &getAnalysis(); + DT = &getAnalysis(); + SE = &getAnalysis(); + Changed = false; + + // If LoopSimplify form is not available, stay out of trouble. + if (!L->getLoopPreheader() || !L->getLoopLatch()) + return false; + + if (!IU->IVUsesByStride.empty()) { + DEBUG(errs() << "\nLSR on \"" << L->getHeader()->getParent()->getName() + << "\" "; + L->dump()); + + // Sort the StrideOrder so we process larger strides first. + std::stable_sort(IU->StrideOrder.begin(), IU->StrideOrder.end(), + StrideCompare(SE)); + + // Optimize induction variables. Some indvar uses can be transformed to use + // strides that will be needed for other purposes. A common example of this + // is the exit test for the loop, which can often be rewritten to use the + // computation of some other indvar to decide when to terminate the loop. + OptimizeIndvars(L); + + // Change loop terminating condition to use the postinc iv when possible + // and optimize loop terminating compare. FIXME: Move this after + // StrengthReduceIVUsersOfStride? + OptimizeLoopTermCond(L); + + // FIXME: We can shrink overlarge IV's here. e.g. if the code has + // computation in i64 values and the target doesn't support i64, demote + // the computation to 32-bit if safe. + + // FIXME: Attempt to reuse values across multiple IV's. In particular, we + // could have something like "for(i) { foo(i*8); bar(i*16) }", which should + // be codegened as "for (j = 0;; j+=8) { foo(j); bar(j+j); }" on X86/PPC. + // Need to be careful that IV's are all the same type. Only works for + // intptr_t indvars. + + // IVsByStride keeps IVs for one particular loop. + assert(IVsByStride.empty() && "Stale entries in IVsByStride?"); + + StrengthReduceIVUsers(L); + + // After all sharing is done, see if we can adjust the loop to test against + // zero instead of counting up to a maximum. This is usually faster. + OptimizeLoopCountIV(L); + } + + // We're done analyzing this loop; release all the state we built up for it. + IVsByStride.clear(); + StrideNoReuse.clear(); + + // Clean up after ourselves + if (!DeadInsts.empty()) + DeleteTriviallyDeadInstructions(); + + // At this point, it is worth checking to see if any recurrence PHIs are also + // dead, so that we can remove them as well. + DeleteDeadPHIs(L->getHeader()); + + return Changed; +} diff --git a/libclamav/c++/llvm/lib/Transforms/Scalar/LoopUnrollPass.cpp b/libclamav/c++/llvm/lib/Transforms/Scalar/LoopUnrollPass.cpp new file mode 100644 index 000000000..c2bf9f2c5 --- /dev/null +++ b/libclamav/c++/llvm/lib/Transforms/Scalar/LoopUnrollPass.cpp @@ -0,0 +1,151 @@ +//===-- LoopUnroll.cpp - Loop unroller pass -------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This pass implements a simple loop unroller. It works best when loops have +// been canonicalized by the -indvars pass, allowing it to determine the trip +// counts of loops easily. +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "loop-unroll" +#include "llvm/IntrinsicInst.h" +#include "llvm/Transforms/Scalar.h" +#include "llvm/Analysis/LoopPass.h" +#include "llvm/Analysis/InlineCost.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Transforms/Utils/UnrollLoop.h" +#include + +using namespace llvm; + +static cl::opt +UnrollThreshold("unroll-threshold", cl::init(100), cl::Hidden, + cl::desc("The cut-off point for automatic loop unrolling")); + +static cl::opt +UnrollCount("unroll-count", cl::init(0), cl::Hidden, + cl::desc("Use this unroll count for all loops, for testing purposes")); + +static cl::opt +UnrollAllowPartial("unroll-allow-partial", cl::init(false), cl::Hidden, + cl::desc("Allows loops to be partially unrolled until " + "-unroll-threshold loop size is reached.")); + +namespace { + class LoopUnroll : public LoopPass { + public: + static char ID; // Pass ID, replacement for typeid + LoopUnroll() : LoopPass(&ID) {} + + /// A magic value for use with the Threshold parameter to indicate + /// that the loop unroll should be performed regardless of how much + /// code expansion would result. + static const unsigned NoThreshold = UINT_MAX; + + bool runOnLoop(Loop *L, LPPassManager &LPM); + + /// This transformation requires natural loop information & requires that + /// loop preheaders be inserted into the CFG... + /// + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.addRequiredID(LoopSimplifyID); + AU.addRequiredID(LCSSAID); + AU.addRequired(); + AU.addPreservedID(LCSSAID); + AU.addPreserved(); + // FIXME: Loop unroll requires LCSSA. And LCSSA requires dom info. + // If loop unroll does not preserve dom info then LCSSA pass on next + // loop will receive invalid dom info. + // For now, recreate dom info, if loop is unrolled. + AU.addPreserved(); + AU.addPreserved(); + } + }; +} + +char LoopUnroll::ID = 0; +static RegisterPass X("loop-unroll", "Unroll loops"); + +Pass *llvm::createLoopUnrollPass() { return new LoopUnroll(); } + +/// ApproximateLoopSize - Approximate the size of the loop. +static unsigned ApproximateLoopSize(const Loop *L) { + CodeMetrics Metrics; + for (Loop::block_iterator I = L->block_begin(), E = L->block_end(); + I != E; ++I) + Metrics.analyzeBasicBlock(*I); + return Metrics.NumInsts; +} + +bool LoopUnroll::runOnLoop(Loop *L, LPPassManager &LPM) { + assert(L->isLCSSAForm()); + LoopInfo *LI = &getAnalysis(); + + BasicBlock *Header = L->getHeader(); + DEBUG(errs() << "Loop Unroll: F[" << Header->getParent()->getName() + << "] Loop %" << Header->getName() << "\n"); + (void)Header; + + // Find trip count + unsigned TripCount = L->getSmallConstantTripCount(); + unsigned Count = UnrollCount; + + // Automatically select an unroll count. + if (Count == 0) { + // Conservative heuristic: if we know the trip count, see if we can + // completely unroll (subject to the threshold, checked below); otherwise + // try to find greatest modulo of the trip count which is still under + // threshold value. + if (TripCount == 0) + return false; + Count = TripCount; + } + + // Enforce the threshold. + if (UnrollThreshold != NoThreshold) { + unsigned LoopSize = ApproximateLoopSize(L); + DEBUG(errs() << " Loop Size = " << LoopSize << "\n"); + uint64_t Size = (uint64_t)LoopSize*Count; + if (TripCount != 1 && Size > UnrollThreshold) { + DEBUG(errs() << " Too large to fully unroll with count: " << Count + << " because size: " << Size << ">" << UnrollThreshold << "\n"); + if (!UnrollAllowPartial) { + DEBUG(errs() << " will not try to unroll partially because " + << "-unroll-allow-partial not given\n"); + return false; + } + // Reduce unroll count to be modulo of TripCount for partial unrolling + Count = UnrollThreshold / LoopSize; + while (Count != 0 && TripCount%Count != 0) { + Count--; + } + if (Count < 2) { + DEBUG(errs() << " could not unroll partially\n"); + return false; + } + DEBUG(errs() << " partially unrolling with count: " << Count << "\n"); + } + } + + // Unroll the loop. + Function *F = L->getHeader()->getParent(); + if (!UnrollLoop(L, Count, LI, &LPM)) + return false; + + // FIXME: Reconstruct dom info, because it is not preserved properly. + DominatorTree *DT = getAnalysisIfAvailable(); + if (DT) { + DT->runOnFunction(*F); + DominanceFrontier *DF = getAnalysisIfAvailable(); + if (DF) + DF->runOnFunction(*F); + } + return true; +} diff --git a/libclamav/c++/llvm/lib/Transforms/Scalar/LoopUnswitch.cpp b/libclamav/c++/llvm/lib/Transforms/Scalar/LoopUnswitch.cpp new file mode 100644 index 000000000..38d267aa6 --- /dev/null +++ b/libclamav/c++/llvm/lib/Transforms/Scalar/LoopUnswitch.cpp @@ -0,0 +1,1075 @@ +//===-- LoopUnswitch.cpp - Hoist loop-invariant conditionals in loop ------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This pass transforms loops that contain branches on loop-invariant conditions +// to have multiple loops. For example, it turns the left into the right code: +// +// for (...) if (lic) +// A for (...) +// if (lic) A; B; C +// B else +// C for (...) +// A; C +// +// This can increase the size of the code exponentially (doubling it every time +// a loop is unswitched) so we only unswitch if the resultant code will be +// smaller than a threshold. +// +// This pass expects LICM to be run before it to hoist invariant conditions out +// of the loop, to make the unswitching opportunity obvious. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "loop-unswitch" +#include "llvm/Transforms/Scalar.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Function.h" +#include "llvm/Instructions.h" +#include "llvm/Analysis/ConstantFolding.h" +#include "llvm/Analysis/InlineCost.h" +#include "llvm/Analysis/LoopInfo.h" +#include "llvm/Analysis/LoopPass.h" +#include "llvm/Analysis/Dominators.h" +#include "llvm/Transforms/Utils/Cloning.h" +#include "llvm/Transforms/Utils/Local.h" +#include "llvm/Transforms/Utils/BasicBlockUtils.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" +#include +#include +using namespace llvm; + +STATISTIC(NumBranches, "Number of branches unswitched"); +STATISTIC(NumSwitches, "Number of switches unswitched"); +STATISTIC(NumSelects , "Number of selects unswitched"); +STATISTIC(NumTrivial , "Number of unswitches that are trivial"); +STATISTIC(NumSimplify, "Number of simplifications of unswitched code"); + +// The specific value of 50 here was chosen based only on intuition and a +// few specific examples. +static cl::opt +Threshold("loop-unswitch-threshold", cl::desc("Max loop size to unswitch"), + cl::init(50), cl::Hidden); + +namespace { + class LoopUnswitch : public LoopPass { + LoopInfo *LI; // Loop information + LPPassManager *LPM; + + // LoopProcessWorklist - Used to check if second loop needs processing + // after RewriteLoopBodyWithConditionConstant rewrites first loop. + std::vector LoopProcessWorklist; + SmallPtrSet UnswitchedVals; + + bool OptimizeForSize; + bool redoLoop; + + Loop *currentLoop; + DominanceFrontier *DF; + DominatorTree *DT; + BasicBlock *loopHeader; + BasicBlock *loopPreheader; + + // LoopBlocks contains all of the basic blocks of the loop, including the + // preheader of the loop, the body of the loop, and the exit blocks of the + // loop, in that order. + std::vector LoopBlocks; + // NewBlocks contained cloned copy of basic blocks from LoopBlocks. + std::vector NewBlocks; + + public: + static char ID; // Pass ID, replacement for typeid + explicit LoopUnswitch(bool Os = false) : + LoopPass(&ID), OptimizeForSize(Os), redoLoop(false), + currentLoop(NULL), DF(NULL), DT(NULL), loopHeader(NULL), + loopPreheader(NULL) {} + + bool runOnLoop(Loop *L, LPPassManager &LPM); + bool processCurrentLoop(); + + /// This transformation requires natural loop information & requires that + /// loop preheaders be inserted into the CFG... + /// + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.addRequiredID(LoopSimplifyID); + AU.addPreservedID(LoopSimplifyID); + AU.addRequired(); + AU.addPreserved(); + AU.addRequiredID(LCSSAID); + AU.addPreservedID(LCSSAID); + AU.addPreserved(); + AU.addPreserved(); + } + + private: + + virtual void releaseMemory() { + UnswitchedVals.clear(); + } + + /// RemoveLoopFromWorklist - If the specified loop is on the loop worklist, + /// remove it. + void RemoveLoopFromWorklist(Loop *L) { + std::vector::iterator I = std::find(LoopProcessWorklist.begin(), + LoopProcessWorklist.end(), L); + if (I != LoopProcessWorklist.end()) + LoopProcessWorklist.erase(I); + } + + void initLoopData() { + loopHeader = currentLoop->getHeader(); + loopPreheader = currentLoop->getLoopPreheader(); + } + + /// Split all of the edges from inside the loop to their exit blocks. + /// Update the appropriate Phi nodes as we do so. + void SplitExitEdges(Loop *L, const SmallVector &ExitBlocks); + + bool UnswitchIfProfitable(Value *LoopCond, Constant *Val); + void UnswitchTrivialCondition(Loop *L, Value *Cond, Constant *Val, + BasicBlock *ExitBlock); + void UnswitchNontrivialCondition(Value *LIC, Constant *OnVal, Loop *L); + + void RewriteLoopBodyWithConditionConstant(Loop *L, Value *LIC, + Constant *Val, bool isEqual); + + void EmitPreheaderBranchOnCondition(Value *LIC, Constant *Val, + BasicBlock *TrueDest, + BasicBlock *FalseDest, + Instruction *InsertPt); + + void SimplifyCode(std::vector &Worklist, Loop *L); + void RemoveBlockIfDead(BasicBlock *BB, + std::vector &Worklist, Loop *l); + void RemoveLoopFromHierarchy(Loop *L); + bool IsTrivialUnswitchCondition(Value *Cond, Constant **Val = 0, + BasicBlock **LoopExit = 0); + + }; +} +char LoopUnswitch::ID = 0; +static RegisterPass X("loop-unswitch", "Unswitch loops"); + +Pass *llvm::createLoopUnswitchPass(bool Os) { + return new LoopUnswitch(Os); +} + +/// FindLIVLoopCondition - Cond is a condition that occurs in L. If it is +/// invariant in the loop, or has an invariant piece, return the invariant. +/// Otherwise, return null. +static Value *FindLIVLoopCondition(Value *Cond, Loop *L, bool &Changed) { + // Constants should be folded, not unswitched on! + if (isa(Cond)) return 0; + + // TODO: Handle: br (VARIANT|INVARIANT). + + // Hoist simple values out. + if (L->makeLoopInvariant(Cond, Changed)) + return Cond; + + if (BinaryOperator *BO = dyn_cast(Cond)) + if (BO->getOpcode() == Instruction::And || + BO->getOpcode() == Instruction::Or) { + // If either the left or right side is invariant, we can unswitch on this, + // which will cause the branch to go away in one loop and the condition to + // simplify in the other one. + if (Value *LHS = FindLIVLoopCondition(BO->getOperand(0), L, Changed)) + return LHS; + if (Value *RHS = FindLIVLoopCondition(BO->getOperand(1), L, Changed)) + return RHS; + } + + return 0; +} + +bool LoopUnswitch::runOnLoop(Loop *L, LPPassManager &LPM_Ref) { + LI = &getAnalysis(); + LPM = &LPM_Ref; + DF = getAnalysisIfAvailable(); + DT = getAnalysisIfAvailable(); + currentLoop = L; + Function *F = currentLoop->getHeader()->getParent(); + bool Changed = false; + do { + assert(currentLoop->isLCSSAForm()); + redoLoop = false; + Changed |= processCurrentLoop(); + } while(redoLoop); + + if (Changed) { + // FIXME: Reconstruct dom info, because it is not preserved properly. + if (DT) + DT->runOnFunction(*F); + if (DF) + DF->runOnFunction(*F); + } + return Changed; +} + +/// processCurrentLoop - Do actual work and unswitch loop if possible +/// and profitable. +bool LoopUnswitch::processCurrentLoop() { + bool Changed = false; + LLVMContext &Context = currentLoop->getHeader()->getContext(); + + // Loop over all of the basic blocks in the loop. If we find an interior + // block that is branching on a loop-invariant condition, we can unswitch this + // loop. + for (Loop::block_iterator I = currentLoop->block_begin(), + E = currentLoop->block_end(); + I != E; ++I) { + TerminatorInst *TI = (*I)->getTerminator(); + if (BranchInst *BI = dyn_cast(TI)) { + // If this isn't branching on an invariant condition, we can't unswitch + // it. + if (BI->isConditional()) { + // See if this, or some part of it, is loop invariant. If so, we can + // unswitch on it if we desire. + Value *LoopCond = FindLIVLoopCondition(BI->getCondition(), + currentLoop, Changed); + if (LoopCond && UnswitchIfProfitable(LoopCond, + ConstantInt::getTrue(Context))) { + ++NumBranches; + return true; + } + } + } else if (SwitchInst *SI = dyn_cast(TI)) { + Value *LoopCond = FindLIVLoopCondition(SI->getCondition(), + currentLoop, Changed); + if (LoopCond && SI->getNumCases() > 1) { + // Find a value to unswitch on: + // FIXME: this should chose the most expensive case! + Constant *UnswitchVal = SI->getCaseValue(1); + // Do not process same value again and again. + if (!UnswitchedVals.insert(UnswitchVal)) + continue; + + if (UnswitchIfProfitable(LoopCond, UnswitchVal)) { + ++NumSwitches; + return true; + } + } + } + + // Scan the instructions to check for unswitchable values. + for (BasicBlock::iterator BBI = (*I)->begin(), E = (*I)->end(); + BBI != E; ++BBI) + if (SelectInst *SI = dyn_cast(BBI)) { + Value *LoopCond = FindLIVLoopCondition(SI->getCondition(), + currentLoop, Changed); + if (LoopCond && UnswitchIfProfitable(LoopCond, + ConstantInt::getTrue(Context))) { + ++NumSelects; + return true; + } + } + } + return Changed; +} + +/// isTrivialLoopExitBlock - Check to see if all paths from BB either: +/// 1. Exit the loop with no side effects. +/// 2. Branch to the latch block with no side-effects. +/// +/// If these conditions are true, we return true and set ExitBB to the block we +/// exit through. +/// +static bool isTrivialLoopExitBlockHelper(Loop *L, BasicBlock *BB, + BasicBlock *&ExitBB, + std::set &Visited) { + if (!Visited.insert(BB).second) { + // Already visited and Ok, end of recursion. + return true; + } else if (!L->contains(BB)) { + // Otherwise, this is a loop exit, this is fine so long as this is the + // first exit. + if (ExitBB != 0) return false; + ExitBB = BB; + return true; + } + + // Otherwise, this is an unvisited intra-loop node. Check all successors. + for (succ_iterator SI = succ_begin(BB), E = succ_end(BB); SI != E; ++SI) { + // Check to see if the successor is a trivial loop exit. + if (!isTrivialLoopExitBlockHelper(L, *SI, ExitBB, Visited)) + return false; + } + + // Okay, everything after this looks good, check to make sure that this block + // doesn't include any side effects. + for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ++I) + if (I->mayHaveSideEffects()) + return false; + + return true; +} + +/// isTrivialLoopExitBlock - Return true if the specified block unconditionally +/// leads to an exit from the specified loop, and has no side-effects in the +/// process. If so, return the block that is exited to, otherwise return null. +static BasicBlock *isTrivialLoopExitBlock(Loop *L, BasicBlock *BB) { + std::set Visited; + Visited.insert(L->getHeader()); // Branches to header are ok. + BasicBlock *ExitBB = 0; + if (isTrivialLoopExitBlockHelper(L, BB, ExitBB, Visited)) + return ExitBB; + return 0; +} + +/// IsTrivialUnswitchCondition - Check to see if this unswitch condition is +/// trivial: that is, that the condition controls whether or not the loop does +/// anything at all. If this is a trivial condition, unswitching produces no +/// code duplications (equivalently, it produces a simpler loop and a new empty +/// loop, which gets deleted). +/// +/// If this is a trivial condition, return true, otherwise return false. When +/// returning true, this sets Cond and Val to the condition that controls the +/// trivial condition: when Cond dynamically equals Val, the loop is known to +/// exit. Finally, this sets LoopExit to the BB that the loop exits to when +/// Cond == Val. +/// +bool LoopUnswitch::IsTrivialUnswitchCondition(Value *Cond, Constant **Val, + BasicBlock **LoopExit) { + BasicBlock *Header = currentLoop->getHeader(); + TerminatorInst *HeaderTerm = Header->getTerminator(); + LLVMContext &Context = Header->getContext(); + + BasicBlock *LoopExitBB = 0; + if (BranchInst *BI = dyn_cast(HeaderTerm)) { + // If the header block doesn't end with a conditional branch on Cond, we + // can't handle it. + if (!BI->isConditional() || BI->getCondition() != Cond) + return false; + + // Check to see if a successor of the branch is guaranteed to go to the + // latch block or exit through a one exit block without having any + // side-effects. If so, determine the value of Cond that causes it to do + // this. + if ((LoopExitBB = isTrivialLoopExitBlock(currentLoop, + BI->getSuccessor(0)))) { + if (Val) *Val = ConstantInt::getTrue(Context); + } else if ((LoopExitBB = isTrivialLoopExitBlock(currentLoop, + BI->getSuccessor(1)))) { + if (Val) *Val = ConstantInt::getFalse(Context); + } + } else if (SwitchInst *SI = dyn_cast(HeaderTerm)) { + // If this isn't a switch on Cond, we can't handle it. + if (SI->getCondition() != Cond) return false; + + // Check to see if a successor of the switch is guaranteed to go to the + // latch block or exit through a one exit block without having any + // side-effects. If so, determine the value of Cond that causes it to do + // this. Note that we can't trivially unswitch on the default case. + for (unsigned i = 1, e = SI->getNumSuccessors(); i != e; ++i) + if ((LoopExitBB = isTrivialLoopExitBlock(currentLoop, + SI->getSuccessor(i)))) { + // Okay, we found a trivial case, remember the value that is trivial. + if (Val) *Val = SI->getCaseValue(i); + break; + } + } + + // If we didn't find a single unique LoopExit block, or if the loop exit block + // contains phi nodes, this isn't trivial. + if (!LoopExitBB || isa(LoopExitBB->begin())) + return false; // Can't handle this. + + if (LoopExit) *LoopExit = LoopExitBB; + + // We already know that nothing uses any scalar values defined inside of this + // loop. As such, we just have to check to see if this loop will execute any + // side-effecting instructions (e.g. stores, calls, volatile loads) in the + // part of the loop that the code *would* execute. We already checked the + // tail, check the header now. + for (BasicBlock::iterator I = Header->begin(), E = Header->end(); I != E; ++I) + if (I->mayHaveSideEffects()) + return false; + return true; +} + +/// UnswitchIfProfitable - We have found that we can unswitch currentLoop when +/// LoopCond == Val to simplify the loop. If we decide that this is profitable, +/// unswitch the loop, reprocess the pieces, then return true. +bool LoopUnswitch::UnswitchIfProfitable(Value *LoopCond, Constant *Val){ + + initLoopData(); + Function *F = loopHeader->getParent(); + + // If LoopSimplify was unable to form a preheader, don't do any unswitching. + if (!loopPreheader) + return false; + + // If the condition is trivial, always unswitch. There is no code growth for + // this case. + if (!IsTrivialUnswitchCondition(LoopCond)) { + // Check to see if it would be profitable to unswitch current loop. + + // Do not do non-trivial unswitch while optimizing for size. + if (OptimizeForSize || F->hasFnAttr(Attribute::OptimizeForSize)) + return false; + + // FIXME: This is overly conservative because it does not take into + // consideration code simplification opportunities and code that can + // be shared by the resultant unswitched loops. + CodeMetrics Metrics; + for (Loop::block_iterator I = currentLoop->block_begin(), + E = currentLoop->block_end(); + I != E; ++I) + Metrics.analyzeBasicBlock(*I); + + // Limit the number of instructions to avoid causing significant code + // expansion, and the number of basic blocks, to avoid loops with + // large numbers of branches which cause loop unswitching to go crazy. + // This is a very ad-hoc heuristic. + if (Metrics.NumInsts > Threshold || + Metrics.NumBlocks * 5 > Threshold || + Metrics.NeverInline) { + DEBUG(errs() << "NOT unswitching loop %" + << currentLoop->getHeader()->getName() << ", cost too high: " + << currentLoop->getBlocks().size() << "\n"); + return false; + } + } + + Constant *CondVal; + BasicBlock *ExitBlock; + if (IsTrivialUnswitchCondition(LoopCond, &CondVal, &ExitBlock)) { + UnswitchTrivialCondition(currentLoop, LoopCond, CondVal, ExitBlock); + } else { + UnswitchNontrivialCondition(LoopCond, Val, currentLoop); + } + + return true; +} + +// RemapInstruction - Convert the instruction operands from referencing the +// current values into those specified by ValueMap. +// +static inline void RemapInstruction(Instruction *I, + DenseMap &ValueMap) { + for (unsigned op = 0, E = I->getNumOperands(); op != E; ++op) { + Value *Op = I->getOperand(op); + DenseMap::iterator It = ValueMap.find(Op); + if (It != ValueMap.end()) Op = It->second; + I->setOperand(op, Op); + } +} + +/// CloneLoop - Recursively clone the specified loop and all of its children, +/// mapping the blocks with the specified map. +static Loop *CloneLoop(Loop *L, Loop *PL, DenseMap &VM, + LoopInfo *LI, LPPassManager *LPM) { + Loop *New = new Loop(); + + LPM->insertLoop(New, PL); + + // Add all of the blocks in L to the new loop. + for (Loop::block_iterator I = L->block_begin(), E = L->block_end(); + I != E; ++I) + if (LI->getLoopFor(*I) == L) + New->addBasicBlockToLoop(cast(VM[*I]), LI->getBase()); + + // Add all of the subloops to the new loop. + for (Loop::iterator I = L->begin(), E = L->end(); I != E; ++I) + CloneLoop(*I, New, VM, LI, LPM); + + return New; +} + +/// EmitPreheaderBranchOnCondition - Emit a conditional branch on two values +/// if LIC == Val, branch to TrueDst, otherwise branch to FalseDest. Insert the +/// code immediately before InsertPt. +void LoopUnswitch::EmitPreheaderBranchOnCondition(Value *LIC, Constant *Val, + BasicBlock *TrueDest, + BasicBlock *FalseDest, + Instruction *InsertPt) { + // Insert a conditional branch on LIC to the two preheaders. The original + // code is the true version and the new code is the false version. + Value *BranchVal = LIC; + if (!isa(Val) || + Val->getType() != Type::getInt1Ty(LIC->getContext())) + BranchVal = new ICmpInst(InsertPt, ICmpInst::ICMP_EQ, LIC, Val, "tmp"); + else if (Val != ConstantInt::getTrue(Val->getContext())) + // We want to enter the new loop when the condition is true. + std::swap(TrueDest, FalseDest); + + // Insert the new branch. + BranchInst *BI = BranchInst::Create(TrueDest, FalseDest, BranchVal, InsertPt); + + // If either edge is critical, split it. This helps preserve LoopSimplify + // form for enclosing loops. + SplitCriticalEdge(BI, 0, this); + SplitCriticalEdge(BI, 1, this); +} + +/// UnswitchTrivialCondition - Given a loop that has a trivial unswitchable +/// condition in it (a cond branch from its header block to its latch block, +/// where the path through the loop that doesn't execute its body has no +/// side-effects), unswitch it. This doesn't involve any code duplication, just +/// moving the conditional branch outside of the loop and updating loop info. +void LoopUnswitch::UnswitchTrivialCondition(Loop *L, Value *Cond, + Constant *Val, + BasicBlock *ExitBlock) { + DEBUG(errs() << "loop-unswitch: Trivial-Unswitch loop %" + << loopHeader->getName() << " [" << L->getBlocks().size() + << " blocks] in Function " << L->getHeader()->getParent()->getName() + << " on cond: " << *Val << " == " << *Cond << "\n"); + + // First step, split the preheader, so that we know that there is a safe place + // to insert the conditional branch. We will change loopPreheader to have a + // conditional branch on Cond. + BasicBlock *NewPH = SplitEdge(loopPreheader, loopHeader, this); + + // Now that we have a place to insert the conditional branch, create a place + // to branch to: this is the exit block out of the loop that we should + // short-circuit to. + + // Split this block now, so that the loop maintains its exit block, and so + // that the jump from the preheader can execute the contents of the exit block + // without actually branching to it (the exit block should be dominated by the + // loop header, not the preheader). + assert(!L->contains(ExitBlock) && "Exit block is in the loop?"); + BasicBlock *NewExit = SplitBlock(ExitBlock, ExitBlock->begin(), this); + + // Okay, now we have a position to branch from and a position to branch to, + // insert the new conditional branch. + EmitPreheaderBranchOnCondition(Cond, Val, NewExit, NewPH, + loopPreheader->getTerminator()); + LPM->deleteSimpleAnalysisValue(loopPreheader->getTerminator(), L); + loopPreheader->getTerminator()->eraseFromParent(); + + // We need to reprocess this loop, it could be unswitched again. + redoLoop = true; + + // Now that we know that the loop is never entered when this condition is a + // particular value, rewrite the loop with this info. We know that this will + // at least eliminate the old branch. + RewriteLoopBodyWithConditionConstant(L, Cond, Val, false); + ++NumTrivial; +} + +/// SplitExitEdges - Split all of the edges from inside the loop to their exit +/// blocks. Update the appropriate Phi nodes as we do so. +void LoopUnswitch::SplitExitEdges(Loop *L, + const SmallVector &ExitBlocks) +{ + + for (unsigned i = 0, e = ExitBlocks.size(); i != e; ++i) { + BasicBlock *ExitBlock = ExitBlocks[i]; + SmallVector Preds(pred_begin(ExitBlock), + pred_end(ExitBlock)); + SplitBlockPredecessors(ExitBlock, Preds.data(), Preds.size(), + ".us-lcssa", this); + } +} + +/// UnswitchNontrivialCondition - We determined that the loop is profitable +/// to unswitch when LIC equal Val. Split it into loop versions and test the +/// condition outside of either loop. Return the loops created as Out1/Out2. +void LoopUnswitch::UnswitchNontrivialCondition(Value *LIC, Constant *Val, + Loop *L) { + Function *F = loopHeader->getParent(); + DEBUG(errs() << "loop-unswitch: Unswitching loop %" + << loopHeader->getName() << " [" << L->getBlocks().size() + << " blocks] in Function " << F->getName() + << " when '" << *Val << "' == " << *LIC << "\n"); + + LoopBlocks.clear(); + NewBlocks.clear(); + + // First step, split the preheader and exit blocks, and add these blocks to + // the LoopBlocks list. + BasicBlock *NewPreheader = SplitEdge(loopPreheader, loopHeader, this); + LoopBlocks.push_back(NewPreheader); + + // We want the loop to come after the preheader, but before the exit blocks. + LoopBlocks.insert(LoopBlocks.end(), L->block_begin(), L->block_end()); + + SmallVector ExitBlocks; + L->getUniqueExitBlocks(ExitBlocks); + + // Split all of the edges from inside the loop to their exit blocks. Update + // the appropriate Phi nodes as we do so. + SplitExitEdges(L, ExitBlocks); + + // The exit blocks may have been changed due to edge splitting, recompute. + ExitBlocks.clear(); + L->getUniqueExitBlocks(ExitBlocks); + + // Add exit blocks to the loop blocks. + LoopBlocks.insert(LoopBlocks.end(), ExitBlocks.begin(), ExitBlocks.end()); + + // Next step, clone all of the basic blocks that make up the loop (including + // the loop preheader and exit blocks), keeping track of the mapping between + // the instructions and blocks. + NewBlocks.reserve(LoopBlocks.size()); + DenseMap ValueMap; + for (unsigned i = 0, e = LoopBlocks.size(); i != e; ++i) { + BasicBlock *New = CloneBasicBlock(LoopBlocks[i], ValueMap, ".us", F); + NewBlocks.push_back(New); + ValueMap[LoopBlocks[i]] = New; // Keep the BB mapping. + LPM->cloneBasicBlockSimpleAnalysis(LoopBlocks[i], New, L); + } + + // Splice the newly inserted blocks into the function right before the + // original preheader. + F->getBasicBlockList().splice(LoopBlocks[0], F->getBasicBlockList(), + NewBlocks[0], F->end()); + + // Now we create the new Loop object for the versioned loop. + Loop *NewLoop = CloneLoop(L, L->getParentLoop(), ValueMap, LI, LPM); + Loop *ParentLoop = L->getParentLoop(); + if (ParentLoop) { + // Make sure to add the cloned preheader and exit blocks to the parent loop + // as well. + ParentLoop->addBasicBlockToLoop(NewBlocks[0], LI->getBase()); + } + + for (unsigned i = 0, e = ExitBlocks.size(); i != e; ++i) { + BasicBlock *NewExit = cast(ValueMap[ExitBlocks[i]]); + // The new exit block should be in the same loop as the old one. + if (Loop *ExitBBLoop = LI->getLoopFor(ExitBlocks[i])) + ExitBBLoop->addBasicBlockToLoop(NewExit, LI->getBase()); + + assert(NewExit->getTerminator()->getNumSuccessors() == 1 && + "Exit block should have been split to have one successor!"); + BasicBlock *ExitSucc = NewExit->getTerminator()->getSuccessor(0); + + // If the successor of the exit block had PHI nodes, add an entry for + // NewExit. + PHINode *PN; + for (BasicBlock::iterator I = ExitSucc->begin(); + (PN = dyn_cast(I)); ++I) { + Value *V = PN->getIncomingValueForBlock(ExitBlocks[i]); + DenseMap::iterator It = ValueMap.find(V); + if (It != ValueMap.end()) V = It->second; + PN->addIncoming(V, NewExit); + } + } + + // Rewrite the code to refer to itself. + for (unsigned i = 0, e = NewBlocks.size(); i != e; ++i) + for (BasicBlock::iterator I = NewBlocks[i]->begin(), + E = NewBlocks[i]->end(); I != E; ++I) + RemapInstruction(I, ValueMap); + + // Rewrite the original preheader to select between versions of the loop. + BranchInst *OldBR = cast(loopPreheader->getTerminator()); + assert(OldBR->isUnconditional() && OldBR->getSuccessor(0) == LoopBlocks[0] && + "Preheader splitting did not work correctly!"); + + // Emit the new branch that selects between the two versions of this loop. + EmitPreheaderBranchOnCondition(LIC, Val, NewBlocks[0], LoopBlocks[0], OldBR); + LPM->deleteSimpleAnalysisValue(OldBR, L); + OldBR->eraseFromParent(); + + LoopProcessWorklist.push_back(NewLoop); + redoLoop = true; + + // Now we rewrite the original code to know that the condition is true and the + // new code to know that the condition is false. + RewriteLoopBodyWithConditionConstant(L , LIC, Val, false); + + // It's possible that simplifying one loop could cause the other to be + // deleted. If so, don't simplify it. + if (!LoopProcessWorklist.empty() && LoopProcessWorklist.back() == NewLoop) + RewriteLoopBodyWithConditionConstant(NewLoop, LIC, Val, true); + +} + +/// RemoveFromWorklist - Remove all instances of I from the worklist vector +/// specified. +static void RemoveFromWorklist(Instruction *I, + std::vector &Worklist) { + std::vector::iterator WI = std::find(Worklist.begin(), + Worklist.end(), I); + while (WI != Worklist.end()) { + unsigned Offset = WI-Worklist.begin(); + Worklist.erase(WI); + WI = std::find(Worklist.begin()+Offset, Worklist.end(), I); + } +} + +/// ReplaceUsesOfWith - When we find that I really equals V, remove I from the +/// program, replacing all uses with V and update the worklist. +static void ReplaceUsesOfWith(Instruction *I, Value *V, + std::vector &Worklist, + Loop *L, LPPassManager *LPM) { + DEBUG(errs() << "Replace with '" << *V << "': " << *I); + + // Add uses to the worklist, which may be dead now. + for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i) + if (Instruction *Use = dyn_cast(I->getOperand(i))) + Worklist.push_back(Use); + + // Add users to the worklist which may be simplified now. + for (Value::use_iterator UI = I->use_begin(), E = I->use_end(); + UI != E; ++UI) + Worklist.push_back(cast(*UI)); + LPM->deleteSimpleAnalysisValue(I, L); + RemoveFromWorklist(I, Worklist); + I->replaceAllUsesWith(V); + I->eraseFromParent(); + ++NumSimplify; +} + +/// RemoveBlockIfDead - If the specified block is dead, remove it, update loop +/// information, and remove any dead successors it has. +/// +void LoopUnswitch::RemoveBlockIfDead(BasicBlock *BB, + std::vector &Worklist, + Loop *L) { + if (pred_begin(BB) != pred_end(BB)) { + // This block isn't dead, since an edge to BB was just removed, see if there + // are any easy simplifications we can do now. + if (BasicBlock *Pred = BB->getSinglePredecessor()) { + // If it has one pred, fold phi nodes in BB. + while (isa(BB->begin())) + ReplaceUsesOfWith(BB->begin(), + cast(BB->begin())->getIncomingValue(0), + Worklist, L, LPM); + + // If this is the header of a loop and the only pred is the latch, we now + // have an unreachable loop. + if (Loop *L = LI->getLoopFor(BB)) + if (loopHeader == BB && L->contains(Pred)) { + // Remove the branch from the latch to the header block, this makes + // the header dead, which will make the latch dead (because the header + // dominates the latch). + LPM->deleteSimpleAnalysisValue(Pred->getTerminator(), L); + Pred->getTerminator()->eraseFromParent(); + new UnreachableInst(BB->getContext(), Pred); + + // The loop is now broken, remove it from LI. + RemoveLoopFromHierarchy(L); + + // Reprocess the header, which now IS dead. + RemoveBlockIfDead(BB, Worklist, L); + return; + } + + // If pred ends in a uncond branch, add uncond branch to worklist so that + // the two blocks will get merged. + if (BranchInst *BI = dyn_cast(Pred->getTerminator())) + if (BI->isUnconditional()) + Worklist.push_back(BI); + } + return; + } + + DEBUG(errs() << "Nuking dead block: " << *BB); + + // Remove the instructions in the basic block from the worklist. + for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ++I) { + RemoveFromWorklist(I, Worklist); + + // Anything that uses the instructions in this basic block should have their + // uses replaced with undefs. + // If I is not void type then replaceAllUsesWith undef. + // This allows ValueHandlers and custom metadata to adjust itself. + if (!I->getType()->isVoidTy()) + I->replaceAllUsesWith(UndefValue::get(I->getType())); + } + + // If this is the edge to the header block for a loop, remove the loop and + // promote all subloops. + if (Loop *BBLoop = LI->getLoopFor(BB)) { + if (BBLoop->getLoopLatch() == BB) + RemoveLoopFromHierarchy(BBLoop); + } + + // Remove the block from the loop info, which removes it from any loops it + // was in. + LI->removeBlock(BB); + + + // Remove phi node entries in successors for this block. + TerminatorInst *TI = BB->getTerminator(); + SmallVector Succs; + for (unsigned i = 0, e = TI->getNumSuccessors(); i != e; ++i) { + Succs.push_back(TI->getSuccessor(i)); + TI->getSuccessor(i)->removePredecessor(BB); + } + + // Unique the successors, remove anything with multiple uses. + array_pod_sort(Succs.begin(), Succs.end()); + Succs.erase(std::unique(Succs.begin(), Succs.end()), Succs.end()); + + // Remove the basic block, including all of the instructions contained in it. + LPM->deleteSimpleAnalysisValue(BB, L); + BB->eraseFromParent(); + // Remove successor blocks here that are not dead, so that we know we only + // have dead blocks in this list. Nondead blocks have a way of becoming dead, + // then getting removed before we revisit them, which is badness. + // + for (unsigned i = 0; i != Succs.size(); ++i) + if (pred_begin(Succs[i]) != pred_end(Succs[i])) { + // One exception is loop headers. If this block was the preheader for a + // loop, then we DO want to visit the loop so the loop gets deleted. + // We know that if the successor is a loop header, that this loop had to + // be the preheader: the case where this was the latch block was handled + // above and headers can only have two predecessors. + if (!LI->isLoopHeader(Succs[i])) { + Succs.erase(Succs.begin()+i); + --i; + } + } + + for (unsigned i = 0, e = Succs.size(); i != e; ++i) + RemoveBlockIfDead(Succs[i], Worklist, L); +} + +/// RemoveLoopFromHierarchy - We have discovered that the specified loop has +/// become unwrapped, either because the backedge was deleted, or because the +/// edge into the header was removed. If the edge into the header from the +/// latch block was removed, the loop is unwrapped but subloops are still alive, +/// so they just reparent loops. If the loops are actually dead, they will be +/// removed later. +void LoopUnswitch::RemoveLoopFromHierarchy(Loop *L) { + LPM->deleteLoopFromQueue(L); + RemoveLoopFromWorklist(L); +} + +// RewriteLoopBodyWithConditionConstant - We know either that the value LIC has +// the value specified by Val in the specified loop, or we know it does NOT have +// that value. Rewrite any uses of LIC or of properties correlated to it. +void LoopUnswitch::RewriteLoopBodyWithConditionConstant(Loop *L, Value *LIC, + Constant *Val, + bool IsEqual) { + assert(!isa(LIC) && "Why are we unswitching on a constant?"); + + // FIXME: Support correlated properties, like: + // for (...) + // if (li1 < li2) + // ... + // if (li1 > li2) + // ... + + // FOLD boolean conditions (X|LIC), (X&LIC). Fold conditional branches, + // selects, switches. + std::vector Users(LIC->use_begin(), LIC->use_end()); + std::vector Worklist; + LLVMContext &Context = Val->getContext(); + + + // If we know that LIC == Val, or that LIC == NotVal, just replace uses of LIC + // in the loop with the appropriate one directly. + if (IsEqual || (isa(Val) && + Val->getType() == Type::getInt1Ty(Val->getContext()))) { + Value *Replacement; + if (IsEqual) + Replacement = Val; + else + Replacement = ConstantInt::get(Type::getInt1Ty(Val->getContext()), + !cast(Val)->getZExtValue()); + + for (unsigned i = 0, e = Users.size(); i != e; ++i) + if (Instruction *U = cast(Users[i])) { + if (!L->contains(U->getParent())) + continue; + U->replaceUsesOfWith(LIC, Replacement); + Worklist.push_back(U); + } + } else { + // Otherwise, we don't know the precise value of LIC, but we do know that it + // is certainly NOT "Val". As such, simplify any uses in the loop that we + // can. This case occurs when we unswitch switch statements. + for (unsigned i = 0, e = Users.size(); i != e; ++i) + if (Instruction *U = cast(Users[i])) { + if (!L->contains(U->getParent())) + continue; + + Worklist.push_back(U); + + // If we know that LIC is not Val, use this info to simplify code. + if (SwitchInst *SI = dyn_cast(U)) { + for (unsigned i = 1, e = SI->getNumCases(); i != e; ++i) { + if (SI->getCaseValue(i) == Val) { + // Found a dead case value. Don't remove PHI nodes in the + // successor if they become single-entry, those PHI nodes may + // be in the Users list. + + // FIXME: This is a hack. We need to keep the successor around + // and hooked up so as to preserve the loop structure, because + // trying to update it is complicated. So instead we preserve the + // loop structure and put the block on a dead code path. + BasicBlock *Switch = SI->getParent(); + SplitEdge(Switch, SI->getSuccessor(i), this); + // Compute the successors instead of relying on the return value + // of SplitEdge, since it may have split the switch successor + // after PHI nodes. + BasicBlock *NewSISucc = SI->getSuccessor(i); + BasicBlock *OldSISucc = *succ_begin(NewSISucc); + // Create an "unreachable" destination. + BasicBlock *Abort = BasicBlock::Create(Context, "us-unreachable", + Switch->getParent(), + OldSISucc); + new UnreachableInst(Context, Abort); + // Force the new case destination to branch to the "unreachable" + // block while maintaining a (dead) CFG edge to the old block. + NewSISucc->getTerminator()->eraseFromParent(); + BranchInst::Create(Abort, OldSISucc, + ConstantInt::getTrue(Context), NewSISucc); + // Release the PHI operands for this edge. + for (BasicBlock::iterator II = NewSISucc->begin(); + PHINode *PN = dyn_cast(II); ++II) + PN->setIncomingValue(PN->getBasicBlockIndex(Switch), + UndefValue::get(PN->getType())); + // Tell the domtree about the new block. We don't fully update the + // domtree here -- instead we force it to do a full recomputation + // after the pass is complete -- but we do need to inform it of + // new blocks. + if (DT) + DT->addNewBlock(Abort, NewSISucc); + break; + } + } + } + + // TODO: We could do other simplifications, for example, turning + // LIC == Val -> false. + } + } + + SimplifyCode(Worklist, L); +} + +/// SimplifyCode - Okay, now that we have simplified some instructions in the +/// loop, walk over it and constant prop, dce, and fold control flow where +/// possible. Note that this is effectively a very simple loop-structure-aware +/// optimizer. During processing of this loop, L could very well be deleted, so +/// it must not be used. +/// +/// FIXME: When the loop optimizer is more mature, separate this out to a new +/// pass. +/// +void LoopUnswitch::SimplifyCode(std::vector &Worklist, Loop *L) { + while (!Worklist.empty()) { + Instruction *I = Worklist.back(); + Worklist.pop_back(); + + // Simple constant folding. + if (Constant *C = ConstantFoldInstruction(I)) { + ReplaceUsesOfWith(I, C, Worklist, L, LPM); + continue; + } + + // Simple DCE. + if (isInstructionTriviallyDead(I)) { + DEBUG(errs() << "Remove dead instruction '" << *I); + + // Add uses to the worklist, which may be dead now. + for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i) + if (Instruction *Use = dyn_cast(I->getOperand(i))) + Worklist.push_back(Use); + LPM->deleteSimpleAnalysisValue(I, L); + RemoveFromWorklist(I, Worklist); + I->eraseFromParent(); + ++NumSimplify; + continue; + } + + // Special case hacks that appear commonly in unswitched code. + switch (I->getOpcode()) { + case Instruction::Select: + if (ConstantInt *CB = dyn_cast(I->getOperand(0))) { + ReplaceUsesOfWith(I, I->getOperand(!CB->getZExtValue()+1), Worklist, L, + LPM); + continue; + } + break; + case Instruction::And: + if (isa(I->getOperand(0)) && + // constant -> RHS + I->getOperand(0)->getType() == Type::getInt1Ty(I->getContext())) + cast(I)->swapOperands(); + if (ConstantInt *CB = dyn_cast(I->getOperand(1))) + if (CB->getType() == Type::getInt1Ty(I->getContext())) { + if (CB->isOne()) // X & 1 -> X + ReplaceUsesOfWith(I, I->getOperand(0), Worklist, L, LPM); + else // X & 0 -> 0 + ReplaceUsesOfWith(I, I->getOperand(1), Worklist, L, LPM); + continue; + } + break; + case Instruction::Or: + if (isa(I->getOperand(0)) && + // constant -> RHS + I->getOperand(0)->getType() == Type::getInt1Ty(I->getContext())) + cast(I)->swapOperands(); + if (ConstantInt *CB = dyn_cast(I->getOperand(1))) + if (CB->getType() == Type::getInt1Ty(I->getContext())) { + if (CB->isOne()) // X | 1 -> 1 + ReplaceUsesOfWith(I, I->getOperand(1), Worklist, L, LPM); + else // X | 0 -> X + ReplaceUsesOfWith(I, I->getOperand(0), Worklist, L, LPM); + continue; + } + break; + case Instruction::Br: { + BranchInst *BI = cast(I); + if (BI->isUnconditional()) { + // If BI's parent is the only pred of the successor, fold the two blocks + // together. + BasicBlock *Pred = BI->getParent(); + BasicBlock *Succ = BI->getSuccessor(0); + BasicBlock *SinglePred = Succ->getSinglePredecessor(); + if (!SinglePred) continue; // Nothing to do. + assert(SinglePred == Pred && "CFG broken"); + + DEBUG(errs() << "Merging blocks: " << Pred->getName() << " <- " + << Succ->getName() << "\n"); + + // Resolve any single entry PHI nodes in Succ. + while (PHINode *PN = dyn_cast(Succ->begin())) + ReplaceUsesOfWith(PN, PN->getIncomingValue(0), Worklist, L, LPM); + + // Move all of the successor contents from Succ to Pred. + Pred->getInstList().splice(BI, Succ->getInstList(), Succ->begin(), + Succ->end()); + LPM->deleteSimpleAnalysisValue(BI, L); + BI->eraseFromParent(); + RemoveFromWorklist(BI, Worklist); + + // If Succ has any successors with PHI nodes, update them to have + // entries coming from Pred instead of Succ. + Succ->replaceAllUsesWith(Pred); + + // Remove Succ from the loop tree. + LI->removeBlock(Succ); + LPM->deleteSimpleAnalysisValue(Succ, L); + Succ->eraseFromParent(); + ++NumSimplify; + } else if (ConstantInt *CB = dyn_cast(BI->getCondition())){ + // Conditional branch. Turn it into an unconditional branch, then + // remove dead blocks. + break; // FIXME: Enable. + + DEBUG(errs() << "Folded branch: " << *BI); + BasicBlock *DeadSucc = BI->getSuccessor(CB->getZExtValue()); + BasicBlock *LiveSucc = BI->getSuccessor(!CB->getZExtValue()); + DeadSucc->removePredecessor(BI->getParent(), true); + Worklist.push_back(BranchInst::Create(LiveSucc, BI)); + LPM->deleteSimpleAnalysisValue(BI, L); + BI->eraseFromParent(); + RemoveFromWorklist(BI, Worklist); + ++NumSimplify; + + RemoveBlockIfDead(DeadSucc, Worklist, L); + } + break; + } + } + } +} diff --git a/libclamav/c++/llvm/lib/Transforms/Scalar/Makefile b/libclamav/c++/llvm/lib/Transforms/Scalar/Makefile new file mode 100644 index 000000000..cc42fd00a --- /dev/null +++ b/libclamav/c++/llvm/lib/Transforms/Scalar/Makefile @@ -0,0 +1,15 @@ +##===- lib/Transforms/Scalar/Makefile ----------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LEVEL = ../../.. +LIBRARYNAME = LLVMScalarOpts +BUILD_ARCHIVE = 1 + +include $(LEVEL)/Makefile.common + diff --git a/libclamav/c++/llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp b/libclamav/c++/llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp new file mode 100644 index 000000000..c92281483 --- /dev/null +++ b/libclamav/c++/llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp @@ -0,0 +1,786 @@ +//===- MemCpyOptimizer.cpp - Optimize use of memcpy and friends -----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This pass performs various transformations related to eliminating memcpy +// calls, or transforming sets of stores into memset's. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "memcpyopt" +#include "llvm/Transforms/Scalar.h" +#include "llvm/IntrinsicInst.h" +#include "llvm/Instructions.h" +#include "llvm/LLVMContext.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/Analysis/Dominators.h" +#include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/Analysis/MemoryDependenceAnalysis.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/GetElementPtrTypeIterator.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Target/TargetData.h" +#include +using namespace llvm; + +STATISTIC(NumMemCpyInstr, "Number of memcpy instructions deleted"); +STATISTIC(NumMemSetInfer, "Number of memsets inferred"); +STATISTIC(NumMoveToCpy, "Number of memmoves converted to memcpy"); + +/// isBytewiseValue - If the specified value can be set by repeating the same +/// byte in memory, return the i8 value that it is represented with. This is +/// true for all i8 values obviously, but is also true for i32 0, i32 -1, +/// i16 0xF0F0, double 0.0 etc. If the value can't be handled with a repeated +/// byte store (e.g. i16 0x1234), return null. +static Value *isBytewiseValue(Value *V) { + LLVMContext &Context = V->getContext(); + + // All byte-wide stores are splatable, even of arbitrary variables. + if (V->getType() == Type::getInt8Ty(Context)) return V; + + // Constant float and double values can be handled as integer values if the + // corresponding integer value is "byteable". An important case is 0.0. + if (ConstantFP *CFP = dyn_cast(V)) { + if (CFP->getType()->isFloatTy()) + V = ConstantExpr::getBitCast(CFP, Type::getInt32Ty(Context)); + if (CFP->getType()->isDoubleTy()) + V = ConstantExpr::getBitCast(CFP, Type::getInt64Ty(Context)); + // Don't handle long double formats, which have strange constraints. + } + + // We can handle constant integers that are power of two in size and a + // multiple of 8 bits. + if (ConstantInt *CI = dyn_cast(V)) { + unsigned Width = CI->getBitWidth(); + if (isPowerOf2_32(Width) && Width > 8) { + // We can handle this value if the recursive binary decomposition is the + // same at all levels. + APInt Val = CI->getValue(); + APInt Val2; + while (Val.getBitWidth() != 8) { + unsigned NextWidth = Val.getBitWidth()/2; + Val2 = Val.lshr(NextWidth); + Val2.trunc(Val.getBitWidth()/2); + Val.trunc(Val.getBitWidth()/2); + + // If the top/bottom halves aren't the same, reject it. + if (Val != Val2) + return 0; + } + return ConstantInt::get(Context, Val); + } + } + + // Conceptually, we could handle things like: + // %a = zext i8 %X to i16 + // %b = shl i16 %a, 8 + // %c = or i16 %a, %b + // but until there is an example that actually needs this, it doesn't seem + // worth worrying about. + return 0; +} + +static int64_t GetOffsetFromIndex(const GetElementPtrInst *GEP, unsigned Idx, + bool &VariableIdxFound, TargetData &TD) { + // Skip over the first indices. + gep_type_iterator GTI = gep_type_begin(GEP); + for (unsigned i = 1; i != Idx; ++i, ++GTI) + /*skip along*/; + + // Compute the offset implied by the rest of the indices. + int64_t Offset = 0; + for (unsigned i = Idx, e = GEP->getNumOperands(); i != e; ++i, ++GTI) { + ConstantInt *OpC = dyn_cast(GEP->getOperand(i)); + if (OpC == 0) + return VariableIdxFound = true; + if (OpC->isZero()) continue; // No offset. + + // Handle struct indices, which add their field offset to the pointer. + if (const StructType *STy = dyn_cast(*GTI)) { + Offset += TD.getStructLayout(STy)->getElementOffset(OpC->getZExtValue()); + continue; + } + + // Otherwise, we have a sequential type like an array or vector. Multiply + // the index by the ElementSize. + uint64_t Size = TD.getTypeAllocSize(GTI.getIndexedType()); + Offset += Size*OpC->getSExtValue(); + } + + return Offset; +} + +/// IsPointerOffset - Return true if Ptr1 is provably equal to Ptr2 plus a +/// constant offset, and return that constant offset. For example, Ptr1 might +/// be &A[42], and Ptr2 might be &A[40]. In this case offset would be -8. +static bool IsPointerOffset(Value *Ptr1, Value *Ptr2, int64_t &Offset, + TargetData &TD) { + // Right now we handle the case when Ptr1/Ptr2 are both GEPs with an identical + // base. After that base, they may have some number of common (and + // potentially variable) indices. After that they handle some constant + // offset, which determines their offset from each other. At this point, we + // handle no other case. + GetElementPtrInst *GEP1 = dyn_cast(Ptr1); + GetElementPtrInst *GEP2 = dyn_cast(Ptr2); + if (!GEP1 || !GEP2 || GEP1->getOperand(0) != GEP2->getOperand(0)) + return false; + + // Skip any common indices and track the GEP types. + unsigned Idx = 1; + for (; Idx != GEP1->getNumOperands() && Idx != GEP2->getNumOperands(); ++Idx) + if (GEP1->getOperand(Idx) != GEP2->getOperand(Idx)) + break; + + bool VariableIdxFound = false; + int64_t Offset1 = GetOffsetFromIndex(GEP1, Idx, VariableIdxFound, TD); + int64_t Offset2 = GetOffsetFromIndex(GEP2, Idx, VariableIdxFound, TD); + if (VariableIdxFound) return false; + + Offset = Offset2-Offset1; + return true; +} + + +/// MemsetRange - Represents a range of memset'd bytes with the ByteVal value. +/// This allows us to analyze stores like: +/// store 0 -> P+1 +/// store 0 -> P+0 +/// store 0 -> P+3 +/// store 0 -> P+2 +/// which sometimes happens with stores to arrays of structs etc. When we see +/// the first store, we make a range [1, 2). The second store extends the range +/// to [0, 2). The third makes a new range [2, 3). The fourth store joins the +/// two ranges into [0, 3) which is memset'able. +namespace { +struct MemsetRange { + // Start/End - A semi range that describes the span that this range covers. + // The range is closed at the start and open at the end: [Start, End). + int64_t Start, End; + + /// StartPtr - The getelementptr instruction that points to the start of the + /// range. + Value *StartPtr; + + /// Alignment - The known alignment of the first store. + unsigned Alignment; + + /// TheStores - The actual stores that make up this range. + SmallVector TheStores; + + bool isProfitableToUseMemset(const TargetData &TD) const; + +}; +} // end anon namespace + +bool MemsetRange::isProfitableToUseMemset(const TargetData &TD) const { + // If we found more than 8 stores to merge or 64 bytes, use memset. + if (TheStores.size() >= 8 || End-Start >= 64) return true; + + // Assume that the code generator is capable of merging pairs of stores + // together if it wants to. + if (TheStores.size() <= 2) return false; + + // If we have fewer than 8 stores, it can still be worthwhile to do this. + // For example, merging 4 i8 stores into an i32 store is useful almost always. + // However, merging 2 32-bit stores isn't useful on a 32-bit architecture (the + // memset will be split into 2 32-bit stores anyway) and doing so can + // pessimize the llvm optimizer. + // + // Since we don't have perfect knowledge here, make some assumptions: assume + // the maximum GPR width is the same size as the pointer size and assume that + // this width can be stored. If so, check to see whether we will end up + // actually reducing the number of stores used. + unsigned Bytes = unsigned(End-Start); + unsigned NumPointerStores = Bytes/TD.getPointerSize(); + + // Assume the remaining bytes if any are done a byte at a time. + unsigned NumByteStores = Bytes - NumPointerStores*TD.getPointerSize(); + + // If we will reduce the # stores (according to this heuristic), do the + // transformation. This encourages merging 4 x i8 -> i32 and 2 x i16 -> i32 + // etc. + return TheStores.size() > NumPointerStores+NumByteStores; +} + + +namespace { +class MemsetRanges { + /// Ranges - A sorted list of the memset ranges. We use std::list here + /// because each element is relatively large and expensive to copy. + std::list Ranges; + typedef std::list::iterator range_iterator; + TargetData &TD; +public: + MemsetRanges(TargetData &td) : TD(td) {} + + typedef std::list::const_iterator const_iterator; + const_iterator begin() const { return Ranges.begin(); } + const_iterator end() const { return Ranges.end(); } + bool empty() const { return Ranges.empty(); } + + void addStore(int64_t OffsetFromFirst, StoreInst *SI); +}; + +} // end anon namespace + + +/// addStore - Add a new store to the MemsetRanges data structure. This adds a +/// new range for the specified store at the specified offset, merging into +/// existing ranges as appropriate. +void MemsetRanges::addStore(int64_t Start, StoreInst *SI) { + int64_t End = Start+TD.getTypeStoreSize(SI->getOperand(0)->getType()); + + // Do a linear search of the ranges to see if this can be joined and/or to + // find the insertion point in the list. We keep the ranges sorted for + // simplicity here. This is a linear search of a linked list, which is ugly, + // however the number of ranges is limited, so this won't get crazy slow. + range_iterator I = Ranges.begin(), E = Ranges.end(); + + while (I != E && Start > I->End) + ++I; + + // We now know that I == E, in which case we didn't find anything to merge + // with, or that Start <= I->End. If End < I->Start or I == E, then we need + // to insert a new range. Handle this now. + if (I == E || End < I->Start) { + MemsetRange &R = *Ranges.insert(I, MemsetRange()); + R.Start = Start; + R.End = End; + R.StartPtr = SI->getPointerOperand(); + R.Alignment = SI->getAlignment(); + R.TheStores.push_back(SI); + return; + } + + // This store overlaps with I, add it. + I->TheStores.push_back(SI); + + // At this point, we may have an interval that completely contains our store. + // If so, just add it to the interval and return. + if (I->Start <= Start && I->End >= End) + return; + + // Now we know that Start <= I->End and End >= I->Start so the range overlaps + // but is not entirely contained within the range. + + // See if the range extends the start of the range. In this case, it couldn't + // possibly cause it to join the prior range, because otherwise we would have + // stopped on *it*. + if (Start < I->Start) { + I->Start = Start; + I->StartPtr = SI->getPointerOperand(); + I->Alignment = SI->getAlignment(); + } + + // Now we know that Start <= I->End and Start >= I->Start (so the startpoint + // is in or right at the end of I), and that End >= I->Start. Extend I out to + // End. + if (End > I->End) { + I->End = End; + range_iterator NextI = I; + while (++NextI != E && End >= NextI->Start) { + // Merge the range in. + I->TheStores.append(NextI->TheStores.begin(), NextI->TheStores.end()); + if (NextI->End > I->End) + I->End = NextI->End; + Ranges.erase(NextI); + NextI = I; + } + } +} + +//===----------------------------------------------------------------------===// +// MemCpyOpt Pass +//===----------------------------------------------------------------------===// + +namespace { + class MemCpyOpt : public FunctionPass { + bool runOnFunction(Function &F); + public: + static char ID; // Pass identification, replacement for typeid + MemCpyOpt() : FunctionPass(&ID) {} + + private: + // This transformation requires dominator postdominator info + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesCFG(); + AU.addRequired(); + AU.addRequired(); + AU.addRequired(); + AU.addPreserved(); + AU.addPreserved(); + } + + // Helper fuctions + bool processStore(StoreInst *SI, BasicBlock::iterator &BBI); + bool processMemCpy(MemCpyInst *M); + bool processMemMove(MemMoveInst *M); + bool performCallSlotOptzn(MemCpyInst *cpy, CallInst *C); + bool iterateOnFunction(Function &F); + }; + + char MemCpyOpt::ID = 0; +} + +// createMemCpyOptPass - The public interface to this file... +FunctionPass *llvm::createMemCpyOptPass() { return new MemCpyOpt(); } + +static RegisterPass X("memcpyopt", + "MemCpy Optimization"); + + + +/// processStore - When GVN is scanning forward over instructions, we look for +/// some other patterns to fold away. In particular, this looks for stores to +/// neighboring locations of memory. If it sees enough consequtive ones +/// (currently 4) it attempts to merge them together into a memcpy/memset. +bool MemCpyOpt::processStore(StoreInst *SI, BasicBlock::iterator &BBI) { + if (SI->isVolatile()) return false; + + LLVMContext &Context = SI->getContext(); + + // There are two cases that are interesting for this code to handle: memcpy + // and memset. Right now we only handle memset. + + // Ensure that the value being stored is something that can be memset'able a + // byte at a time like "0" or "-1" or any width, as well as things like + // 0xA0A0A0A0 and 0.0. + Value *ByteVal = isBytewiseValue(SI->getOperand(0)); + if (!ByteVal) + return false; + + TargetData *TD = getAnalysisIfAvailable(); + if (!TD) return false; + AliasAnalysis &AA = getAnalysis(); + Module *M = SI->getParent()->getParent()->getParent(); + + // Okay, so we now have a single store that can be splatable. Scan to find + // all subsequent stores of the same value to offset from the same pointer. + // Join these together into ranges, so we can decide whether contiguous blocks + // are stored. + MemsetRanges Ranges(*TD); + + Value *StartPtr = SI->getPointerOperand(); + + BasicBlock::iterator BI = SI; + for (++BI; !isa(BI); ++BI) { + if (isa(BI) || isa(BI)) { + // If the call is readnone, ignore it, otherwise bail out. We don't even + // allow readonly here because we don't want something like: + // A[1] = 2; strlen(A); A[2] = 2; -> memcpy(A, ...); strlen(A). + if (AA.getModRefBehavior(CallSite::get(BI)) == + AliasAnalysis::DoesNotAccessMemory) + continue; + + // TODO: If this is a memset, try to join it in. + + break; + } else if (isa(BI) || isa(BI)) + break; + + // If this is a non-store instruction it is fine, ignore it. + StoreInst *NextStore = dyn_cast(BI); + if (NextStore == 0) continue; + + // If this is a store, see if we can merge it in. + if (NextStore->isVolatile()) break; + + // Check to see if this stored value is of the same byte-splattable value. + if (ByteVal != isBytewiseValue(NextStore->getOperand(0))) + break; + + // Check to see if this store is to a constant offset from the start ptr. + int64_t Offset; + if (!IsPointerOffset(StartPtr, NextStore->getPointerOperand(), Offset, *TD)) + break; + + Ranges.addStore(Offset, NextStore); + } + + // If we have no ranges, then we just had a single store with nothing that + // could be merged in. This is a very common case of course. + if (Ranges.empty()) + return false; + + // If we had at least one store that could be merged in, add the starting + // store as well. We try to avoid this unless there is at least something + // interesting as a small compile-time optimization. + Ranges.addStore(0, SI); + + Function *MemSetF = 0; + + // Now that we have full information about ranges, loop over the ranges and + // emit memset's for anything big enough to be worthwhile. + bool MadeChange = false; + for (MemsetRanges::const_iterator I = Ranges.begin(), E = Ranges.end(); + I != E; ++I) { + const MemsetRange &Range = *I; + + if (Range.TheStores.size() == 1) continue; + + // If it is profitable to lower this range to memset, do so now. + if (!Range.isProfitableToUseMemset(*TD)) + continue; + + // Otherwise, we do want to transform this! Create a new memset. We put + // the memset right before the first instruction that isn't part of this + // memset block. This ensure that the memset is dominated by any addressing + // instruction needed by the start of the block. + BasicBlock::iterator InsertPt = BI; + + if (MemSetF == 0) { + const Type *Ty = Type::getInt64Ty(Context); + MemSetF = Intrinsic::getDeclaration(M, Intrinsic::memset, &Ty, 1); + } + + // Get the starting pointer of the block. + StartPtr = Range.StartPtr; + + // Cast the start ptr to be i8* as memset requires. + const Type *i8Ptr = Type::getInt8PtrTy(Context); + if (StartPtr->getType() != i8Ptr) + StartPtr = new BitCastInst(StartPtr, i8Ptr, StartPtr->getName(), + InsertPt); + + Value *Ops[] = { + StartPtr, ByteVal, // Start, value + // size + ConstantInt::get(Type::getInt64Ty(Context), Range.End-Range.Start), + // align + ConstantInt::get(Type::getInt32Ty(Context), Range.Alignment) + }; + Value *C = CallInst::Create(MemSetF, Ops, Ops+4, "", InsertPt); + DEBUG(errs() << "Replace stores:\n"; + for (unsigned i = 0, e = Range.TheStores.size(); i != e; ++i) + errs() << *Range.TheStores[i]; + errs() << "With: " << *C); C=C; + + // Don't invalidate the iterator + BBI = BI; + + // Zap all the stores. + for (SmallVector::const_iterator + SI = Range.TheStores.begin(), + SE = Range.TheStores.end(); SI != SE; ++SI) + (*SI)->eraseFromParent(); + ++NumMemSetInfer; + MadeChange = true; + } + + return MadeChange; +} + + +/// performCallSlotOptzn - takes a memcpy and a call that it depends on, +/// and checks for the possibility of a call slot optimization by having +/// the call write its result directly into the destination of the memcpy. +bool MemCpyOpt::performCallSlotOptzn(MemCpyInst *cpy, CallInst *C) { + // The general transformation to keep in mind is + // + // call @func(..., src, ...) + // memcpy(dest, src, ...) + // + // -> + // + // memcpy(dest, src, ...) + // call @func(..., dest, ...) + // + // Since moving the memcpy is technically awkward, we additionally check that + // src only holds uninitialized values at the moment of the call, meaning that + // the memcpy can be discarded rather than moved. + + // Deliberately get the source and destination with bitcasts stripped away, + // because we'll need to do type comparisons based on the underlying type. + Value *cpyDest = cpy->getDest(); + Value *cpySrc = cpy->getSource(); + CallSite CS = CallSite::get(C); + + // We need to be able to reason about the size of the memcpy, so we require + // that it be a constant. + ConstantInt *cpyLength = dyn_cast(cpy->getLength()); + if (!cpyLength) + return false; + + // Require that src be an alloca. This simplifies the reasoning considerably. + AllocaInst *srcAlloca = dyn_cast(cpySrc); + if (!srcAlloca) + return false; + + // Check that all of src is copied to dest. + TargetData *TD = getAnalysisIfAvailable(); + if (!TD) return false; + + ConstantInt *srcArraySize = dyn_cast(srcAlloca->getArraySize()); + if (!srcArraySize) + return false; + + uint64_t srcSize = TD->getTypeAllocSize(srcAlloca->getAllocatedType()) * + srcArraySize->getZExtValue(); + + if (cpyLength->getZExtValue() < srcSize) + return false; + + // Check that accessing the first srcSize bytes of dest will not cause a + // trap. Otherwise the transform is invalid since it might cause a trap + // to occur earlier than it otherwise would. + if (AllocaInst *A = dyn_cast(cpyDest)) { + // The destination is an alloca. Check it is larger than srcSize. + ConstantInt *destArraySize = dyn_cast(A->getArraySize()); + if (!destArraySize) + return false; + + uint64_t destSize = TD->getTypeAllocSize(A->getAllocatedType()) * + destArraySize->getZExtValue(); + + if (destSize < srcSize) + return false; + } else if (Argument *A = dyn_cast(cpyDest)) { + // If the destination is an sret parameter then only accesses that are + // outside of the returned struct type can trap. + if (!A->hasStructRetAttr()) + return false; + + const Type *StructTy = cast(A->getType())->getElementType(); + uint64_t destSize = TD->getTypeAllocSize(StructTy); + + if (destSize < srcSize) + return false; + } else { + return false; + } + + // Check that src is not accessed except via the call and the memcpy. This + // guarantees that it holds only undefined values when passed in (so the final + // memcpy can be dropped), that it is not read or written between the call and + // the memcpy, and that writing beyond the end of it is undefined. + SmallVector srcUseList(srcAlloca->use_begin(), + srcAlloca->use_end()); + while (!srcUseList.empty()) { + User *UI = srcUseList.back(); + srcUseList.pop_back(); + + if (isa(UI)) { + for (User::use_iterator I = UI->use_begin(), E = UI->use_end(); + I != E; ++I) + srcUseList.push_back(*I); + } else if (GetElementPtrInst *G = dyn_cast(UI)) { + if (G->hasAllZeroIndices()) + for (User::use_iterator I = UI->use_begin(), E = UI->use_end(); + I != E; ++I) + srcUseList.push_back(*I); + else + return false; + } else if (UI != C && UI != cpy) { + return false; + } + } + + // Since we're changing the parameter to the callsite, we need to make sure + // that what would be the new parameter dominates the callsite. + DominatorTree &DT = getAnalysis(); + if (Instruction *cpyDestInst = dyn_cast(cpyDest)) + if (!DT.dominates(cpyDestInst, C)) + return false; + + // In addition to knowing that the call does not access src in some + // unexpected manner, for example via a global, which we deduce from + // the use analysis, we also need to know that it does not sneakily + // access dest. We rely on AA to figure this out for us. + AliasAnalysis &AA = getAnalysis(); + if (AA.getModRefInfo(C, cpy->getRawDest(), srcSize) != + AliasAnalysis::NoModRef) + return false; + + // All the checks have passed, so do the transformation. + bool changedArgument = false; + for (unsigned i = 0; i < CS.arg_size(); ++i) + if (CS.getArgument(i)->stripPointerCasts() == cpySrc) { + if (cpySrc->getType() != cpyDest->getType()) + cpyDest = CastInst::CreatePointerCast(cpyDest, cpySrc->getType(), + cpyDest->getName(), C); + changedArgument = true; + if (CS.getArgument(i)->getType() == cpyDest->getType()) + CS.setArgument(i, cpyDest); + else + CS.setArgument(i, CastInst::CreatePointerCast(cpyDest, + CS.getArgument(i)->getType(), cpyDest->getName(), C)); + } + + if (!changedArgument) + return false; + + // Drop any cached information about the call, because we may have changed + // its dependence information by changing its parameter. + MemoryDependenceAnalysis &MD = getAnalysis(); + MD.removeInstruction(C); + + // Remove the memcpy + MD.removeInstruction(cpy); + cpy->eraseFromParent(); + NumMemCpyInstr++; + + return true; +} + +/// processMemCpy - perform simplication of memcpy's. If we have memcpy A which +/// copies X to Y, and memcpy B which copies Y to Z, then we can rewrite B to be +/// a memcpy from X to Z (or potentially a memmove, depending on circumstances). +/// This allows later passes to remove the first memcpy altogether. +bool MemCpyOpt::processMemCpy(MemCpyInst *M) { + MemoryDependenceAnalysis &MD = getAnalysis(); + + // The are two possible optimizations we can do for memcpy: + // a) memcpy-memcpy xform which exposes redundance for DSE. + // b) call-memcpy xform for return slot optimization. + MemDepResult dep = MD.getDependency(M); + if (!dep.isClobber()) + return false; + if (!isa(dep.getInst())) { + if (CallInst *C = dyn_cast(dep.getInst())) + return performCallSlotOptzn(M, C); + return false; + } + + MemCpyInst *MDep = cast(dep.getInst()); + + // We can only transforms memcpy's where the dest of one is the source of the + // other + if (M->getSource() != MDep->getDest()) + return false; + + // Second, the length of the memcpy's must be the same, or the preceeding one + // must be larger than the following one. + ConstantInt *C1 = dyn_cast(MDep->getLength()); + ConstantInt *C2 = dyn_cast(M->getLength()); + if (!C1 || !C2) + return false; + + uint64_t DepSize = C1->getValue().getZExtValue(); + uint64_t CpySize = C2->getValue().getZExtValue(); + + if (DepSize < CpySize) + return false; + + // Finally, we have to make sure that the dest of the second does not + // alias the source of the first + AliasAnalysis &AA = getAnalysis(); + if (AA.alias(M->getRawDest(), CpySize, MDep->getRawSource(), DepSize) != + AliasAnalysis::NoAlias) + return false; + else if (AA.alias(M->getRawDest(), CpySize, M->getRawSource(), CpySize) != + AliasAnalysis::NoAlias) + return false; + else if (AA.alias(MDep->getRawDest(), DepSize, MDep->getRawSource(), DepSize) + != AliasAnalysis::NoAlias) + return false; + + // If all checks passed, then we can transform these memcpy's + const Type *Ty = M->getLength()->getType(); + Function *MemCpyFun = Intrinsic::getDeclaration( + M->getParent()->getParent()->getParent(), + M->getIntrinsicID(), &Ty, 1); + + Value *Args[4] = { + M->getRawDest(), MDep->getRawSource(), M->getLength(), M->getAlignmentCst() + }; + + CallInst *C = CallInst::Create(MemCpyFun, Args, Args+4, "", M); + + + // If C and M don't interfere, then this is a valid transformation. If they + // did, this would mean that the two sources overlap, which would be bad. + if (MD.getDependency(C) == dep) { + MD.removeInstruction(M); + M->eraseFromParent(); + NumMemCpyInstr++; + return true; + } + + // Otherwise, there was no point in doing this, so we remove the call we + // inserted and act like nothing happened. + MD.removeInstruction(C); + C->eraseFromParent(); + return false; +} + +/// processMemMove - Transforms memmove calls to memcpy calls when the src/dst +/// are guaranteed not to alias. +bool MemCpyOpt::processMemMove(MemMoveInst *M) { + AliasAnalysis &AA = getAnalysis(); + + // If the memmove is a constant size, use it for the alias query, this allows + // us to optimize things like: memmove(P, P+64, 64); + uint64_t MemMoveSize = ~0ULL; + if (ConstantInt *Len = dyn_cast(M->getLength())) + MemMoveSize = Len->getZExtValue(); + + // See if the pointers alias. + if (AA.alias(M->getRawDest(), MemMoveSize, M->getRawSource(), MemMoveSize) != + AliasAnalysis::NoAlias) + return false; + + DEBUG(errs() << "MemCpyOpt: Optimizing memmove -> memcpy: " << *M << "\n"); + + // If not, then we know we can transform this. + Module *Mod = M->getParent()->getParent()->getParent(); + const Type *Ty = M->getLength()->getType(); + M->setOperand(0, Intrinsic::getDeclaration(Mod, Intrinsic::memcpy, &Ty, 1)); + + // MemDep may have over conservative information about this instruction, just + // conservatively flush it from the cache. + getAnalysis().removeInstruction(M); + + ++NumMoveToCpy; + return true; +} + + +// MemCpyOpt::iterateOnFunction - Executes one iteration of GVN. +bool MemCpyOpt::iterateOnFunction(Function &F) { + bool MadeChange = false; + + // Walk all instruction in the function. + for (Function::iterator BB = F.begin(), BBE = F.end(); BB != BBE; ++BB) { + for (BasicBlock::iterator BI = BB->begin(), BE = BB->end(); + BI != BE;) { + // Avoid invalidating the iterator. + Instruction *I = BI++; + + if (StoreInst *SI = dyn_cast(I)) + MadeChange |= processStore(SI, BI); + else if (MemCpyInst *M = dyn_cast(I)) + MadeChange |= processMemCpy(M); + else if (MemMoveInst *M = dyn_cast(I)) { + if (processMemMove(M)) { + --BI; // Reprocess the new memcpy. + MadeChange = true; + } + } + } + } + + return MadeChange; +} + +// MemCpyOpt::runOnFunction - This is the main transformation entry point for a +// function. +// +bool MemCpyOpt::runOnFunction(Function &F) { + bool MadeChange = false; + while (1) { + if (!iterateOnFunction(F)) + break; + MadeChange = true; + } + + return MadeChange; +} + + + diff --git a/libclamav/c++/llvm/lib/Transforms/Scalar/Reassociate.cpp b/libclamav/c++/llvm/lib/Transforms/Scalar/Reassociate.cpp new file mode 100644 index 000000000..8466918a0 --- /dev/null +++ b/libclamav/c++/llvm/lib/Transforms/Scalar/Reassociate.cpp @@ -0,0 +1,896 @@ +//===- Reassociate.cpp - Reassociate binary expressions -------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This pass reassociates commutative expressions in an order that is designed +// to promote better constant propagation, GCSE, LICM, PRE... +// +// For example: 4 + (x + 5) -> x + (4 + 5) +// +// In the implementation of this algorithm, constants are assigned rank = 0, +// function arguments are rank = 1, and other values are assigned ranks +// corresponding to the reverse post order traversal of current function +// (starting at 2), which effectively gives values in deep loops higher rank +// than values not in loops. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "reassociate" +#include "llvm/Transforms/Scalar.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Function.h" +#include "llvm/Instructions.h" +#include "llvm/IntrinsicInst.h" +#include "llvm/Pass.h" +#include "llvm/Assembly/Writer.h" +#include "llvm/Support/CFG.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ValueHandle.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/ADT/PostOrderIterator.h" +#include "llvm/ADT/Statistic.h" +#include +#include +using namespace llvm; + +STATISTIC(NumLinear , "Number of insts linearized"); +STATISTIC(NumChanged, "Number of insts reassociated"); +STATISTIC(NumAnnihil, "Number of expr tree annihilated"); +STATISTIC(NumFactor , "Number of multiplies factored"); + +namespace { + struct ValueEntry { + unsigned Rank; + Value *Op; + ValueEntry(unsigned R, Value *O) : Rank(R), Op(O) {} + }; + inline bool operator<(const ValueEntry &LHS, const ValueEntry &RHS) { + return LHS.Rank > RHS.Rank; // Sort so that highest rank goes to start. + } +} + +#ifndef NDEBUG +/// PrintOps - Print out the expression identified in the Ops list. +/// +static void PrintOps(Instruction *I, const std::vector &Ops) { + Module *M = I->getParent()->getParent()->getParent(); + errs() << Instruction::getOpcodeName(I->getOpcode()) << " " + << *Ops[0].Op->getType(); + for (unsigned i = 0, e = Ops.size(); i != e; ++i) { + WriteAsOperand(errs() << " ", Ops[i].Op, false, M); + errs() << "," << Ops[i].Rank; + } +} +#endif + +namespace { + class Reassociate : public FunctionPass { + std::map RankMap; + std::map, unsigned> ValueRankMap; + bool MadeChange; + public: + static char ID; // Pass identification, replacement for typeid + Reassociate() : FunctionPass(&ID) {} + + bool runOnFunction(Function &F); + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesCFG(); + } + private: + void BuildRankMap(Function &F); + unsigned getRank(Value *V); + void ReassociateExpression(BinaryOperator *I); + void RewriteExprTree(BinaryOperator *I, std::vector &Ops, + unsigned Idx = 0); + Value *OptimizeExpression(BinaryOperator *I, std::vector &Ops); + void LinearizeExprTree(BinaryOperator *I, std::vector &Ops); + void LinearizeExpr(BinaryOperator *I); + Value *RemoveFactorFromExpression(Value *V, Value *Factor); + void ReassociateBB(BasicBlock *BB); + + void RemoveDeadBinaryOp(Value *V); + }; +} + +char Reassociate::ID = 0; +static RegisterPass X("reassociate", "Reassociate expressions"); + +// Public interface to the Reassociate pass +FunctionPass *llvm::createReassociatePass() { return new Reassociate(); } + +void Reassociate::RemoveDeadBinaryOp(Value *V) { + Instruction *Op = dyn_cast(V); + if (!Op || !isa(Op) || !isa(Op) || !Op->use_empty()) + return; + + Value *LHS = Op->getOperand(0), *RHS = Op->getOperand(1); + RemoveDeadBinaryOp(LHS); + RemoveDeadBinaryOp(RHS); +} + + +static bool isUnmovableInstruction(Instruction *I) { + if (I->getOpcode() == Instruction::PHI || + I->getOpcode() == Instruction::Alloca || + I->getOpcode() == Instruction::Load || + I->getOpcode() == Instruction::Invoke || + (I->getOpcode() == Instruction::Call && + !isa(I)) || + I->getOpcode() == Instruction::UDiv || + I->getOpcode() == Instruction::SDiv || + I->getOpcode() == Instruction::FDiv || + I->getOpcode() == Instruction::URem || + I->getOpcode() == Instruction::SRem || + I->getOpcode() == Instruction::FRem) + return true; + return false; +} + +void Reassociate::BuildRankMap(Function &F) { + unsigned i = 2; + + // Assign distinct ranks to function arguments + for (Function::arg_iterator I = F.arg_begin(), E = F.arg_end(); I != E; ++I) + ValueRankMap[&*I] = ++i; + + ReversePostOrderTraversal RPOT(&F); + for (ReversePostOrderTraversal::rpo_iterator I = RPOT.begin(), + E = RPOT.end(); I != E; ++I) { + BasicBlock *BB = *I; + unsigned BBRank = RankMap[BB] = ++i << 16; + + // Walk the basic block, adding precomputed ranks for any instructions that + // we cannot move. This ensures that the ranks for these instructions are + // all different in the block. + for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ++I) + if (isUnmovableInstruction(I)) + ValueRankMap[&*I] = ++BBRank; + } +} + +unsigned Reassociate::getRank(Value *V) { + if (isa(V)) return ValueRankMap[V]; // Function argument... + + Instruction *I = dyn_cast(V); + if (I == 0) return 0; // Otherwise it's a global or constant, rank 0. + + unsigned &CachedRank = ValueRankMap[I]; + if (CachedRank) return CachedRank; // Rank already known? + + // If this is an expression, return the 1+MAX(rank(LHS), rank(RHS)) so that + // we can reassociate expressions for code motion! Since we do not recurse + // for PHI nodes, we cannot have infinite recursion here, because there + // cannot be loops in the value graph that do not go through PHI nodes. + unsigned Rank = 0, MaxRank = RankMap[I->getParent()]; + for (unsigned i = 0, e = I->getNumOperands(); + i != e && Rank != MaxRank; ++i) + Rank = std::max(Rank, getRank(I->getOperand(i))); + + // If this is a not or neg instruction, do not count it for rank. This + // assures us that X and ~X will have the same rank. + if (!I->getType()->isInteger() || + (!BinaryOperator::isNot(I) && !BinaryOperator::isNeg(I))) + ++Rank; + + //DEBUG(errs() << "Calculated Rank[" << V->getName() << "] = " + // << Rank << "\n"); + + return CachedRank = Rank; +} + +/// isReassociableOp - Return true if V is an instruction of the specified +/// opcode and if it only has one use. +static BinaryOperator *isReassociableOp(Value *V, unsigned Opcode) { + if ((V->hasOneUse() || V->use_empty()) && isa(V) && + cast(V)->getOpcode() == Opcode) + return cast(V); + return 0; +} + +/// LowerNegateToMultiply - Replace 0-X with X*-1. +/// +static Instruction *LowerNegateToMultiply(Instruction *Neg, + std::map, unsigned> &ValueRankMap) { + Constant *Cst = Constant::getAllOnesValue(Neg->getType()); + + Instruction *Res = BinaryOperator::CreateMul(Neg->getOperand(1), Cst, "",Neg); + ValueRankMap.erase(Neg); + Res->takeName(Neg); + Neg->replaceAllUsesWith(Res); + Neg->eraseFromParent(); + return Res; +} + +// Given an expression of the form '(A+B)+(D+C)', turn it into '(((A+B)+C)+D)'. +// Note that if D is also part of the expression tree that we recurse to +// linearize it as well. Besides that case, this does not recurse into A,B, or +// C. +void Reassociate::LinearizeExpr(BinaryOperator *I) { + BinaryOperator *LHS = cast(I->getOperand(0)); + BinaryOperator *RHS = cast(I->getOperand(1)); + assert(isReassociableOp(LHS, I->getOpcode()) && + isReassociableOp(RHS, I->getOpcode()) && + "Not an expression that needs linearization?"); + + DEBUG(errs() << "Linear" << *LHS << '\n' << *RHS << '\n' << *I << '\n'); + + // Move the RHS instruction to live immediately before I, avoiding breaking + // dominator properties. + RHS->moveBefore(I); + + // Move operands around to do the linearization. + I->setOperand(1, RHS->getOperand(0)); + RHS->setOperand(0, LHS); + I->setOperand(0, RHS); + + ++NumLinear; + MadeChange = true; + DEBUG(errs() << "Linearized: " << *I << '\n'); + + // If D is part of this expression tree, tail recurse. + if (isReassociableOp(I->getOperand(1), I->getOpcode())) + LinearizeExpr(I); +} + + +/// LinearizeExprTree - Given an associative binary expression tree, traverse +/// all of the uses putting it into canonical form. This forces a left-linear +/// form of the the expression (((a+b)+c)+d), and collects information about the +/// rank of the non-tree operands. +/// +/// NOTE: These intentionally destroys the expression tree operands (turning +/// them into undef values) to reduce #uses of the values. This means that the +/// caller MUST use something like RewriteExprTree to put the values back in. +/// +void Reassociate::LinearizeExprTree(BinaryOperator *I, + std::vector &Ops) { + Value *LHS = I->getOperand(0), *RHS = I->getOperand(1); + unsigned Opcode = I->getOpcode(); + + // First step, linearize the expression if it is in ((A+B)+(C+D)) form. + BinaryOperator *LHSBO = isReassociableOp(LHS, Opcode); + BinaryOperator *RHSBO = isReassociableOp(RHS, Opcode); + + // If this is a multiply expression tree and it contains internal negations, + // transform them into multiplies by -1 so they can be reassociated. + if (I->getOpcode() == Instruction::Mul) { + if (!LHSBO && LHS->hasOneUse() && BinaryOperator::isNeg(LHS)) { + LHS = LowerNegateToMultiply(cast(LHS), ValueRankMap); + LHSBO = isReassociableOp(LHS, Opcode); + } + if (!RHSBO && RHS->hasOneUse() && BinaryOperator::isNeg(RHS)) { + RHS = LowerNegateToMultiply(cast(RHS), ValueRankMap); + RHSBO = isReassociableOp(RHS, Opcode); + } + } + + if (!LHSBO) { + if (!RHSBO) { + // Neither the LHS or RHS as part of the tree, thus this is a leaf. As + // such, just remember these operands and their rank. + Ops.push_back(ValueEntry(getRank(LHS), LHS)); + Ops.push_back(ValueEntry(getRank(RHS), RHS)); + + // Clear the leaves out. + I->setOperand(0, UndefValue::get(I->getType())); + I->setOperand(1, UndefValue::get(I->getType())); + return; + } else { + // Turn X+(Y+Z) -> (Y+Z)+X + std::swap(LHSBO, RHSBO); + std::swap(LHS, RHS); + bool Success = !I->swapOperands(); + assert(Success && "swapOperands failed"); + Success = false; + MadeChange = true; + } + } else if (RHSBO) { + // Turn (A+B)+(C+D) -> (((A+B)+C)+D). This guarantees the the RHS is not + // part of the expression tree. + LinearizeExpr(I); + LHS = LHSBO = cast(I->getOperand(0)); + RHS = I->getOperand(1); + RHSBO = 0; + } + + // Okay, now we know that the LHS is a nested expression and that the RHS is + // not. Perform reassociation. + assert(!isReassociableOp(RHS, Opcode) && "LinearizeExpr failed!"); + + // Move LHS right before I to make sure that the tree expression dominates all + // values. + LHSBO->moveBefore(I); + + // Linearize the expression tree on the LHS. + LinearizeExprTree(LHSBO, Ops); + + // Remember the RHS operand and its rank. + Ops.push_back(ValueEntry(getRank(RHS), RHS)); + + // Clear the RHS leaf out. + I->setOperand(1, UndefValue::get(I->getType())); +} + +// RewriteExprTree - Now that the operands for this expression tree are +// linearized and optimized, emit them in-order. This function is written to be +// tail recursive. +void Reassociate::RewriteExprTree(BinaryOperator *I, + std::vector &Ops, + unsigned i) { + if (i+2 == Ops.size()) { + if (I->getOperand(0) != Ops[i].Op || + I->getOperand(1) != Ops[i+1].Op) { + Value *OldLHS = I->getOperand(0); + DEBUG(errs() << "RA: " << *I << '\n'); + I->setOperand(0, Ops[i].Op); + I->setOperand(1, Ops[i+1].Op); + DEBUG(errs() << "TO: " << *I << '\n'); + MadeChange = true; + ++NumChanged; + + // If we reassociated a tree to fewer operands (e.g. (1+a+2) -> (a+3) + // delete the extra, now dead, nodes. + RemoveDeadBinaryOp(OldLHS); + } + return; + } + assert(i+2 < Ops.size() && "Ops index out of range!"); + + if (I->getOperand(1) != Ops[i].Op) { + DEBUG(errs() << "RA: " << *I << '\n'); + I->setOperand(1, Ops[i].Op); + DEBUG(errs() << "TO: " << *I << '\n'); + MadeChange = true; + ++NumChanged; + } + + BinaryOperator *LHS = cast(I->getOperand(0)); + assert(LHS->getOpcode() == I->getOpcode() && + "Improper expression tree!"); + + // Compactify the tree instructions together with each other to guarantee + // that the expression tree is dominated by all of Ops. + LHS->moveBefore(I); + RewriteExprTree(LHS, Ops, i+1); +} + + + +// NegateValue - Insert instructions before the instruction pointed to by BI, +// that computes the negative version of the value specified. The negative +// version of the value is returned, and BI is left pointing at the instruction +// that should be processed next by the reassociation pass. +// +static Value *NegateValue(Value *V, Instruction *BI) { + // We are trying to expose opportunity for reassociation. One of the things + // that we want to do to achieve this is to push a negation as deep into an + // expression chain as possible, to expose the add instructions. In practice, + // this means that we turn this: + // X = -(A+12+C+D) into X = -A + -12 + -C + -D = -12 + -A + -C + -D + // so that later, a: Y = 12+X could get reassociated with the -12 to eliminate + // the constants. We assume that instcombine will clean up the mess later if + // we introduce tons of unnecessary negation instructions... + // + if (Instruction *I = dyn_cast(V)) + if (I->getOpcode() == Instruction::Add && I->hasOneUse()) { + // Push the negates through the add. + I->setOperand(0, NegateValue(I->getOperand(0), BI)); + I->setOperand(1, NegateValue(I->getOperand(1), BI)); + + // We must move the add instruction here, because the neg instructions do + // not dominate the old add instruction in general. By moving it, we are + // assured that the neg instructions we just inserted dominate the + // instruction we are about to insert after them. + // + I->moveBefore(BI); + I->setName(I->getName()+".neg"); + return I; + } + + // Insert a 'neg' instruction that subtracts the value from zero to get the + // negation. + // + return BinaryOperator::CreateNeg(V, V->getName() + ".neg", BI); +} + +/// ShouldBreakUpSubtract - Return true if we should break up this subtract of +/// X-Y into (X + -Y). +static bool ShouldBreakUpSubtract(Instruction *Sub) { + // If this is a negation, we can't split it up! + if (BinaryOperator::isNeg(Sub)) + return false; + + // Don't bother to break this up unless either the LHS is an associable add or + // subtract or if this is only used by one. + if (isReassociableOp(Sub->getOperand(0), Instruction::Add) || + isReassociableOp(Sub->getOperand(0), Instruction::Sub)) + return true; + if (isReassociableOp(Sub->getOperand(1), Instruction::Add) || + isReassociableOp(Sub->getOperand(1), Instruction::Sub)) + return true; + if (Sub->hasOneUse() && + (isReassociableOp(Sub->use_back(), Instruction::Add) || + isReassociableOp(Sub->use_back(), Instruction::Sub))) + return true; + + return false; +} + +/// BreakUpSubtract - If we have (X-Y), and if either X is an add, or if this is +/// only used by an add, transform this into (X+(0-Y)) to promote better +/// reassociation. +static Instruction *BreakUpSubtract(Instruction *Sub, + std::map, unsigned> &ValueRankMap) { + // Convert a subtract into an add and a neg instruction... so that sub + // instructions can be commuted with other add instructions... + // + // Calculate the negative value of Operand 1 of the sub instruction... + // and set it as the RHS of the add instruction we just made... + // + Value *NegVal = NegateValue(Sub->getOperand(1), Sub); + Instruction *New = + BinaryOperator::CreateAdd(Sub->getOperand(0), NegVal, "", Sub); + New->takeName(Sub); + + // Everyone now refers to the add instruction. + ValueRankMap.erase(Sub); + Sub->replaceAllUsesWith(New); + Sub->eraseFromParent(); + + DEBUG(errs() << "Negated: " << *New << '\n'); + return New; +} + +/// ConvertShiftToMul - If this is a shift of a reassociable multiply or is used +/// by one, change this into a multiply by a constant to assist with further +/// reassociation. +static Instruction *ConvertShiftToMul(Instruction *Shl, + std::map, unsigned> &ValueRankMap) { + // If an operand of this shift is a reassociable multiply, or if the shift + // is used by a reassociable multiply or add, turn into a multiply. + if (isReassociableOp(Shl->getOperand(0), Instruction::Mul) || + (Shl->hasOneUse() && + (isReassociableOp(Shl->use_back(), Instruction::Mul) || + isReassociableOp(Shl->use_back(), Instruction::Add)))) { + Constant *MulCst = ConstantInt::get(Shl->getType(), 1); + MulCst = + ConstantExpr::getShl(MulCst, cast(Shl->getOperand(1))); + + Instruction *Mul = BinaryOperator::CreateMul(Shl->getOperand(0), MulCst, + "", Shl); + ValueRankMap.erase(Shl); + Mul->takeName(Shl); + Shl->replaceAllUsesWith(Mul); + Shl->eraseFromParent(); + return Mul; + } + return 0; +} + +// Scan backwards and forwards among values with the same rank as element i to +// see if X exists. If X does not exist, return i. +static unsigned FindInOperandList(std::vector &Ops, unsigned i, + Value *X) { + unsigned XRank = Ops[i].Rank; + unsigned e = Ops.size(); + for (unsigned j = i+1; j != e && Ops[j].Rank == XRank; ++j) + if (Ops[j].Op == X) + return j; + // Scan backwards + for (unsigned j = i-1; j != ~0U && Ops[j].Rank == XRank; --j) + if (Ops[j].Op == X) + return j; + return i; +} + +/// EmitAddTreeOfValues - Emit a tree of add instructions, summing Ops together +/// and returning the result. Insert the tree before I. +static Value *EmitAddTreeOfValues(Instruction *I, std::vector &Ops) { + if (Ops.size() == 1) return Ops.back(); + + Value *V1 = Ops.back(); + Ops.pop_back(); + Value *V2 = EmitAddTreeOfValues(I, Ops); + return BinaryOperator::CreateAdd(V2, V1, "tmp", I); +} + +/// RemoveFactorFromExpression - If V is an expression tree that is a +/// multiplication sequence, and if this sequence contains a multiply by Factor, +/// remove Factor from the tree and return the new tree. +Value *Reassociate::RemoveFactorFromExpression(Value *V, Value *Factor) { + BinaryOperator *BO = isReassociableOp(V, Instruction::Mul); + if (!BO) return 0; + + std::vector Factors; + LinearizeExprTree(BO, Factors); + + bool FoundFactor = false; + for (unsigned i = 0, e = Factors.size(); i != e; ++i) + if (Factors[i].Op == Factor) { + FoundFactor = true; + Factors.erase(Factors.begin()+i); + break; + } + if (!FoundFactor) { + // Make sure to restore the operands to the expression tree. + RewriteExprTree(BO, Factors); + return 0; + } + + if (Factors.size() == 1) return Factors[0].Op; + + RewriteExprTree(BO, Factors); + return BO; +} + +/// FindSingleUseMultiplyFactors - If V is a single-use multiply, recursively +/// add its operands as factors, otherwise add V to the list of factors. +static void FindSingleUseMultiplyFactors(Value *V, + std::vector &Factors) { + BinaryOperator *BO; + if ((!V->hasOneUse() && !V->use_empty()) || + !(BO = dyn_cast(V)) || + BO->getOpcode() != Instruction::Mul) { + Factors.push_back(V); + return; + } + + // Otherwise, add the LHS and RHS to the list of factors. + FindSingleUseMultiplyFactors(BO->getOperand(1), Factors); + FindSingleUseMultiplyFactors(BO->getOperand(0), Factors); +} + + + +Value *Reassociate::OptimizeExpression(BinaryOperator *I, + std::vector &Ops) { + // Now that we have the linearized expression tree, try to optimize it. + // Start by folding any constants that we found. + bool IterateOptimization = false; + if (Ops.size() == 1) return Ops[0].Op; + + unsigned Opcode = I->getOpcode(); + + if (Constant *V1 = dyn_cast(Ops[Ops.size()-2].Op)) + if (Constant *V2 = dyn_cast(Ops.back().Op)) { + Ops.pop_back(); + Ops.back().Op = ConstantExpr::get(Opcode, V1, V2); + return OptimizeExpression(I, Ops); + } + + // Check for destructive annihilation due to a constant being used. + if (ConstantInt *CstVal = dyn_cast(Ops.back().Op)) + switch (Opcode) { + default: break; + case Instruction::And: + if (CstVal->isZero()) { // ... & 0 -> 0 + ++NumAnnihil; + return CstVal; + } else if (CstVal->isAllOnesValue()) { // ... & -1 -> ... + Ops.pop_back(); + } + break; + case Instruction::Mul: + if (CstVal->isZero()) { // ... * 0 -> 0 + ++NumAnnihil; + return CstVal; + } else if (cast(CstVal)->isOne()) { + Ops.pop_back(); // ... * 1 -> ... + } + break; + case Instruction::Or: + if (CstVal->isAllOnesValue()) { // ... | -1 -> -1 + ++NumAnnihil; + return CstVal; + } + // FALLTHROUGH! + case Instruction::Add: + case Instruction::Xor: + if (CstVal->isZero()) // ... [|^+] 0 -> ... + Ops.pop_back(); + break; + } + if (Ops.size() == 1) return Ops[0].Op; + + // Handle destructive annihilation do to identities between elements in the + // argument list here. + switch (Opcode) { + default: break; + case Instruction::And: + case Instruction::Or: + case Instruction::Xor: + // Scan the operand lists looking for X and ~X pairs, along with X,X pairs. + // If we find any, we can simplify the expression. X&~X == 0, X|~X == -1. + for (unsigned i = 0, e = Ops.size(); i != e; ++i) { + // First, check for X and ~X in the operand list. + assert(i < Ops.size()); + if (BinaryOperator::isNot(Ops[i].Op)) { // Cannot occur for ^. + Value *X = BinaryOperator::getNotArgument(Ops[i].Op); + unsigned FoundX = FindInOperandList(Ops, i, X); + if (FoundX != i) { + if (Opcode == Instruction::And) { // ...&X&~X = 0 + ++NumAnnihil; + return Constant::getNullValue(X->getType()); + } else if (Opcode == Instruction::Or) { // ...|X|~X = -1 + ++NumAnnihil; + return Constant::getAllOnesValue(X->getType()); + } + } + } + + // Next, check for duplicate pairs of values, which we assume are next to + // each other, due to our sorting criteria. + assert(i < Ops.size()); + if (i+1 != Ops.size() && Ops[i+1].Op == Ops[i].Op) { + if (Opcode == Instruction::And || Opcode == Instruction::Or) { + // Drop duplicate values. + Ops.erase(Ops.begin()+i); + --i; --e; + IterateOptimization = true; + ++NumAnnihil; + } else { + assert(Opcode == Instruction::Xor); + if (e == 2) { + ++NumAnnihil; + return Constant::getNullValue(Ops[0].Op->getType()); + } + // ... X^X -> ... + Ops.erase(Ops.begin()+i, Ops.begin()+i+2); + i -= 1; e -= 2; + IterateOptimization = true; + ++NumAnnihil; + } + } + } + break; + + case Instruction::Add: + // Scan the operand lists looking for X and -X pairs. If we find any, we + // can simplify the expression. X+-X == 0. + for (unsigned i = 0, e = Ops.size(); i != e; ++i) { + assert(i < Ops.size()); + // Check for X and -X in the operand list. + if (BinaryOperator::isNeg(Ops[i].Op)) { + Value *X = BinaryOperator::getNegArgument(Ops[i].Op); + unsigned FoundX = FindInOperandList(Ops, i, X); + if (FoundX != i) { + // Remove X and -X from the operand list. + if (Ops.size() == 2) { + ++NumAnnihil; + return Constant::getNullValue(X->getType()); + } else { + Ops.erase(Ops.begin()+i); + if (i < FoundX) + --FoundX; + else + --i; // Need to back up an extra one. + Ops.erase(Ops.begin()+FoundX); + IterateOptimization = true; + ++NumAnnihil; + --i; // Revisit element. + e -= 2; // Removed two elements. + } + } + } + } + + + // Scan the operand list, checking to see if there are any common factors + // between operands. Consider something like A*A+A*B*C+D. We would like to + // reassociate this to A*(A+B*C)+D, which reduces the number of multiplies. + // To efficiently find this, we count the number of times a factor occurs + // for any ADD operands that are MULs. + std::map FactorOccurrences; + unsigned MaxOcc = 0; + Value *MaxOccVal = 0; + for (unsigned i = 0, e = Ops.size(); i != e; ++i) { + if (BinaryOperator *BOp = dyn_cast(Ops[i].Op)) { + if (BOp->getOpcode() == Instruction::Mul && BOp->use_empty()) { + // Compute all of the factors of this added value. + std::vector Factors; + FindSingleUseMultiplyFactors(BOp, Factors); + assert(Factors.size() > 1 && "Bad linearize!"); + + // Add one to FactorOccurrences for each unique factor in this op. + if (Factors.size() == 2) { + unsigned Occ = ++FactorOccurrences[Factors[0]]; + if (Occ > MaxOcc) { MaxOcc = Occ; MaxOccVal = Factors[0]; } + if (Factors[0] != Factors[1]) { // Don't double count A*A. + Occ = ++FactorOccurrences[Factors[1]]; + if (Occ > MaxOcc) { MaxOcc = Occ; MaxOccVal = Factors[1]; } + } + } else { + std::set Duplicates; + for (unsigned i = 0, e = Factors.size(); i != e; ++i) { + if (Duplicates.insert(Factors[i]).second) { + unsigned Occ = ++FactorOccurrences[Factors[i]]; + if (Occ > MaxOcc) { MaxOcc = Occ; MaxOccVal = Factors[i]; } + } + } + } + } + } + } + + // If any factor occurred more than one time, we can pull it out. + if (MaxOcc > 1) { + DEBUG(errs() << "\nFACTORING [" << MaxOcc << "]: " << *MaxOccVal << "\n"); + + // Create a new instruction that uses the MaxOccVal twice. If we don't do + // this, we could otherwise run into situations where removing a factor + // from an expression will drop a use of maxocc, and this can cause + // RemoveFactorFromExpression on successive values to behave differently. + Instruction *DummyInst = BinaryOperator::CreateAdd(MaxOccVal, MaxOccVal); + std::vector NewMulOps; + for (unsigned i = 0, e = Ops.size(); i != e; ++i) { + if (Value *V = RemoveFactorFromExpression(Ops[i].Op, MaxOccVal)) { + NewMulOps.push_back(V); + Ops.erase(Ops.begin()+i); + --i; --e; + } + } + + // No need for extra uses anymore. + delete DummyInst; + + unsigned NumAddedValues = NewMulOps.size(); + Value *V = EmitAddTreeOfValues(I, NewMulOps); + Value *V2 = BinaryOperator::CreateMul(V, MaxOccVal, "tmp", I); + + // Now that we have inserted V and its sole use, optimize it. This allows + // us to handle cases that require multiple factoring steps, such as this: + // A*A*B + A*A*C --> A*(A*B+A*C) --> A*(A*(B+C)) + if (NumAddedValues > 1) + ReassociateExpression(cast(V)); + + ++NumFactor; + + if (Ops.empty()) + return V2; + + // Add the new value to the list of things being added. + Ops.insert(Ops.begin(), ValueEntry(getRank(V2), V2)); + + // Rewrite the tree so that there is now a use of V. + RewriteExprTree(I, Ops); + return OptimizeExpression(I, Ops); + } + break; + //case Instruction::Mul: + } + + if (IterateOptimization) + return OptimizeExpression(I, Ops); + return 0; +} + + +/// ReassociateBB - Inspect all of the instructions in this basic block, +/// reassociating them as we go. +void Reassociate::ReassociateBB(BasicBlock *BB) { + for (BasicBlock::iterator BBI = BB->begin(); BBI != BB->end(); ) { + Instruction *BI = BBI++; + if (BI->getOpcode() == Instruction::Shl && + isa(BI->getOperand(1))) + if (Instruction *NI = ConvertShiftToMul(BI, ValueRankMap)) { + MadeChange = true; + BI = NI; + } + + // Reject cases where it is pointless to do this. + if (!isa(BI) || BI->getType()->isFloatingPoint() || + isa(BI->getType())) + continue; // Floating point ops are not associative. + + // If this is a subtract instruction which is not already in negate form, + // see if we can convert it to X+-Y. + if (BI->getOpcode() == Instruction::Sub) { + if (ShouldBreakUpSubtract(BI)) { + BI = BreakUpSubtract(BI, ValueRankMap); + MadeChange = true; + } else if (BinaryOperator::isNeg(BI)) { + // Otherwise, this is a negation. See if the operand is a multiply tree + // and if this is not an inner node of a multiply tree. + if (isReassociableOp(BI->getOperand(1), Instruction::Mul) && + (!BI->hasOneUse() || + !isReassociableOp(BI->use_back(), Instruction::Mul))) { + BI = LowerNegateToMultiply(BI, ValueRankMap); + MadeChange = true; + } + } + } + + // If this instruction is a commutative binary operator, process it. + if (!BI->isAssociative()) continue; + BinaryOperator *I = cast(BI); + + // If this is an interior node of a reassociable tree, ignore it until we + // get to the root of the tree, to avoid N^2 analysis. + if (I->hasOneUse() && isReassociableOp(I->use_back(), I->getOpcode())) + continue; + + // If this is an add tree that is used by a sub instruction, ignore it + // until we process the subtract. + if (I->hasOneUse() && I->getOpcode() == Instruction::Add && + cast(I->use_back())->getOpcode() == Instruction::Sub) + continue; + + ReassociateExpression(I); + } +} + +void Reassociate::ReassociateExpression(BinaryOperator *I) { + + // First, walk the expression tree, linearizing the tree, collecting + std::vector Ops; + LinearizeExprTree(I, Ops); + + DEBUG(errs() << "RAIn:\t"; PrintOps(I, Ops); errs() << "\n"); + + // Now that we have linearized the tree to a list and have gathered all of + // the operands and their ranks, sort the operands by their rank. Use a + // stable_sort so that values with equal ranks will have their relative + // positions maintained (and so the compiler is deterministic). Note that + // this sorts so that the highest ranking values end up at the beginning of + // the vector. + std::stable_sort(Ops.begin(), Ops.end()); + + // OptimizeExpression - Now that we have the expression tree in a convenient + // sorted form, optimize it globally if possible. + if (Value *V = OptimizeExpression(I, Ops)) { + // This expression tree simplified to something that isn't a tree, + // eliminate it. + DEBUG(errs() << "Reassoc to scalar: " << *V << "\n"); + I->replaceAllUsesWith(V); + RemoveDeadBinaryOp(I); + return; + } + + // We want to sink immediates as deeply as possible except in the case where + // this is a multiply tree used only by an add, and the immediate is a -1. + // In this case we reassociate to put the negation on the outside so that we + // can fold the negation into the add: (-X)*Y + Z -> Z-X*Y + if (I->getOpcode() == Instruction::Mul && I->hasOneUse() && + cast(I->use_back())->getOpcode() == Instruction::Add && + isa(Ops.back().Op) && + cast(Ops.back().Op)->isAllOnesValue()) { + Ops.insert(Ops.begin(), Ops.back()); + Ops.pop_back(); + } + + DEBUG(errs() << "RAOut:\t"; PrintOps(I, Ops); errs() << "\n"); + + if (Ops.size() == 1) { + // This expression tree simplified to something that isn't a tree, + // eliminate it. + I->replaceAllUsesWith(Ops[0].Op); + RemoveDeadBinaryOp(I); + } else { + // Now that we ordered and optimized the expressions, splat them back into + // the expression tree, removing any unneeded nodes. + RewriteExprTree(I, Ops); + } +} + + +bool Reassociate::runOnFunction(Function &F) { + // Recalculate the rank map for F + BuildRankMap(F); + + MadeChange = false; + for (Function::iterator FI = F.begin(), FE = F.end(); FI != FE; ++FI) + ReassociateBB(FI); + + // We are done with the rank map... + RankMap.clear(); + ValueRankMap.clear(); + return MadeChange; +} + diff --git a/libclamav/c++/llvm/lib/Transforms/Scalar/Reg2Mem.cpp b/libclamav/c++/llvm/lib/Transforms/Scalar/Reg2Mem.cpp new file mode 100644 index 000000000..99e12522c --- /dev/null +++ b/libclamav/c++/llvm/lib/Transforms/Scalar/Reg2Mem.cpp @@ -0,0 +1,129 @@ +//===- Reg2Mem.cpp - Convert registers to allocas -------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file demotes all registers to memory references. It is intented to be +// the inverse of PromoteMemoryToRegister. By converting to loads, the only +// values live accross basic blocks are allocas and loads before phi nodes. +// It is intended that this should make CFG hacking much easier. +// To make later hacking easier, the entry block is split into two, such that +// all introduced allocas and nothing else are in the entry block. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "reg2mem" +#include "llvm/Transforms/Scalar.h" +#include "llvm/Transforms/Utils/Local.h" +#include "llvm/Pass.h" +#include "llvm/Function.h" +#include "llvm/LLVMContext.h" +#include "llvm/Module.h" +#include "llvm/BasicBlock.h" +#include "llvm/Instructions.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/Support/CFG.h" +#include +using namespace llvm; + +STATISTIC(NumRegsDemoted, "Number of registers demoted"); +STATISTIC(NumPhisDemoted, "Number of phi-nodes demoted"); + +namespace { + struct RegToMem : public FunctionPass { + static char ID; // Pass identification, replacement for typeid + RegToMem() : FunctionPass(&ID) {} + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.addRequiredID(BreakCriticalEdgesID); + AU.addPreservedID(BreakCriticalEdgesID); + } + + bool valueEscapes(const Instruction *Inst) const { + const BasicBlock *BB = Inst->getParent(); + for (Value::use_const_iterator UI = Inst->use_begin(),E = Inst->use_end(); + UI != E; ++UI) + if (cast(*UI)->getParent() != BB || + isa(*UI)) + return true; + return false; + } + + virtual bool runOnFunction(Function &F); + }; +} + +char RegToMem::ID = 0; +static RegisterPass +X("reg2mem", "Demote all values to stack slots"); + + +bool RegToMem::runOnFunction(Function &F) { + if (F.isDeclaration()) + return false; + + // Insert all new allocas into entry block. + BasicBlock *BBEntry = &F.getEntryBlock(); + assert(pred_begin(BBEntry) == pred_end(BBEntry) && + "Entry block to function must not have predecessors!"); + + // Find first non-alloca instruction and create insertion point. This is + // safe if block is well-formed: it always have terminator, otherwise + // we'll get and assertion. + BasicBlock::iterator I = BBEntry->begin(); + while (isa(I)) ++I; + + CastInst *AllocaInsertionPoint = + new BitCastInst(Constant::getNullValue(Type::getInt32Ty(F.getContext())), + Type::getInt32Ty(F.getContext()), + "reg2mem alloca point", I); + + // Find the escaped instructions. But don't create stack slots for + // allocas in entry block. + std::list WorkList; + for (Function::iterator ibb = F.begin(), ibe = F.end(); + ibb != ibe; ++ibb) + for (BasicBlock::iterator iib = ibb->begin(), iie = ibb->end(); + iib != iie; ++iib) { + if (!(isa(iib) && iib->getParent() == BBEntry) && + valueEscapes(iib)) { + WorkList.push_front(&*iib); + } + } + + // Demote escaped instructions + NumRegsDemoted += WorkList.size(); + for (std::list::iterator ilb = WorkList.begin(), + ile = WorkList.end(); ilb != ile; ++ilb) + DemoteRegToStack(**ilb, false, AllocaInsertionPoint); + + WorkList.clear(); + + // Find all phi's + for (Function::iterator ibb = F.begin(), ibe = F.end(); + ibb != ibe; ++ibb) + for (BasicBlock::iterator iib = ibb->begin(), iie = ibb->end(); + iib != iie; ++iib) + if (isa(iib)) + WorkList.push_front(&*iib); + + // Demote phi nodes + NumPhisDemoted += WorkList.size(); + for (std::list::iterator ilb = WorkList.begin(), + ile = WorkList.end(); ilb != ile; ++ilb) + DemotePHIToStack(cast(*ilb), AllocaInsertionPoint); + + return true; +} + + +// createDemoteRegisterToMemory - Provide an entry point to create this pass. +// +const PassInfo *const llvm::DemoteRegisterToMemoryID = &X; +FunctionPass *llvm::createDemoteRegisterToMemoryPass() { + return new RegToMem(); +} diff --git a/libclamav/c++/llvm/lib/Transforms/Scalar/SCCP.cpp b/libclamav/c++/llvm/lib/Transforms/Scalar/SCCP.cpp new file mode 100644 index 000000000..d8c59b1d7 --- /dev/null +++ b/libclamav/c++/llvm/lib/Transforms/Scalar/SCCP.cpp @@ -0,0 +1,1957 @@ +//===- SCCP.cpp - Sparse Conditional Constant Propagation -----------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements sparse conditional constant propagation and merging: +// +// Specifically, this: +// * Assumes values are constant unless proven otherwise +// * Assumes BasicBlocks are dead unless proven otherwise +// * Proves values to be constant, and replaces them with constants +// * Proves conditional branches to be unconditional +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "sccp" +#include "llvm/Transforms/Scalar.h" +#include "llvm/Transforms/IPO.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Instructions.h" +#include "llvm/Pass.h" +#include "llvm/Analysis/ConstantFolding.h" +#include "llvm/Analysis/ValueTracking.h" +#include "llvm/Transforms/Utils/Local.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Support/CallSite.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/InstVisitor.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/DenseSet.h" +#include "llvm/ADT/PointerIntPair.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/ADT/STLExtras.h" +#include +#include +using namespace llvm; + +STATISTIC(NumInstRemoved, "Number of instructions removed"); +STATISTIC(NumDeadBlocks , "Number of basic blocks unreachable"); + +STATISTIC(IPNumInstRemoved, "Number of instructions removed by IPSCCP"); +STATISTIC(IPNumArgsElimed ,"Number of arguments constant propagated by IPSCCP"); +STATISTIC(IPNumGlobalConst, "Number of globals found to be constant by IPSCCP"); + +namespace { +/// LatticeVal class - This class represents the different lattice values that +/// an LLVM value may occupy. It is a simple class with value semantics. +/// +class LatticeVal { + enum LatticeValueTy { + /// undefined - This LLVM Value has no known value yet. + undefined, + + /// constant - This LLVM Value has a specific constant value. + constant, + + /// forcedconstant - This LLVM Value was thought to be undef until + /// ResolvedUndefsIn. This is treated just like 'constant', but if merged + /// with another (different) constant, it goes to overdefined, instead of + /// asserting. + forcedconstant, + + /// overdefined - This instruction is not known to be constant, and we know + /// it has a value. + overdefined + }; + + /// Val: This stores the current lattice value along with the Constant* for + /// the constant if this is a 'constant' or 'forcedconstant' value. + PointerIntPair Val; + + LatticeValueTy getLatticeValue() const { + return Val.getInt(); + } + +public: + LatticeVal() : Val(0, undefined) {} + + bool isUndefined() const { return getLatticeValue() == undefined; } + bool isConstant() const { + return getLatticeValue() == constant || getLatticeValue() == forcedconstant; + } + bool isOverdefined() const { return getLatticeValue() == overdefined; } + + Constant *getConstant() const { + assert(isConstant() && "Cannot get the constant of a non-constant!"); + return Val.getPointer(); + } + + /// markOverdefined - Return true if this is a change in status. + bool markOverdefined() { + if (isOverdefined()) + return false; + + Val.setInt(overdefined); + return true; + } + + /// markConstant - Return true if this is a change in status. + bool markConstant(Constant *V) { + if (getLatticeValue() == constant) { // Constant but not forcedconstant. + assert(getConstant() == V && "Marking constant with different value"); + return false; + } + + if (isUndefined()) { + Val.setInt(constant); + assert(V && "Marking constant with NULL"); + Val.setPointer(V); + } else { + assert(getLatticeValue() == forcedconstant && + "Cannot move from overdefined to constant!"); + // Stay at forcedconstant if the constant is the same. + if (V == getConstant()) return false; + + // Otherwise, we go to overdefined. Assumptions made based on the + // forced value are possibly wrong. Assuming this is another constant + // could expose a contradiction. + Val.setInt(overdefined); + } + return true; + } + + /// getConstantInt - If this is a constant with a ConstantInt value, return it + /// otherwise return null. + ConstantInt *getConstantInt() const { + if (isConstant()) + return dyn_cast(getConstant()); + return 0; + } + + void markForcedConstant(Constant *V) { + assert(isUndefined() && "Can't force a defined value!"); + Val.setInt(forcedconstant); + Val.setPointer(V); + } +}; +} // end anonymous namespace. + + +namespace { + +//===----------------------------------------------------------------------===// +// +/// SCCPSolver - This class is a general purpose solver for Sparse Conditional +/// Constant Propagation. +/// +class SCCPSolver : public InstVisitor { + const TargetData *TD; + SmallPtrSet BBExecutable;// The BBs that are executable. + DenseMap ValueState; // The state each value is in. + + /// StructValueState - This maintains ValueState for values that have + /// StructType, for example for formal arguments, calls, insertelement, etc. + /// + DenseMap, LatticeVal> StructValueState; + + /// GlobalValue - If we are tracking any values for the contents of a global + /// variable, we keep a mapping from the constant accessor to the element of + /// the global, to the currently known value. If the value becomes + /// overdefined, it's entry is simply removed from this map. + DenseMap TrackedGlobals; + + /// TrackedRetVals - If we are tracking arguments into and the return + /// value out of a function, it will have an entry in this map, indicating + /// what the known return value for the function is. + DenseMap TrackedRetVals; + + /// TrackedMultipleRetVals - Same as TrackedRetVals, but used for functions + /// that return multiple values. + DenseMap, LatticeVal> TrackedMultipleRetVals; + + /// MRVFunctionsTracked - Each function in TrackedMultipleRetVals is + /// represented here for efficient lookup. + SmallPtrSet MRVFunctionsTracked; + + /// TrackingIncomingArguments - This is the set of functions for whose + /// arguments we make optimistic assumptions about and try to prove as + /// constants. + SmallPtrSet TrackingIncomingArguments; + + /// The reason for two worklists is that overdefined is the lowest state + /// on the lattice, and moving things to overdefined as fast as possible + /// makes SCCP converge much faster. + /// + /// By having a separate worklist, we accomplish this because everything + /// possibly overdefined will become overdefined at the soonest possible + /// point. + SmallVector OverdefinedInstWorkList; + SmallVector InstWorkList; + + + SmallVector BBWorkList; // The BasicBlock work list + + /// UsersOfOverdefinedPHIs - Keep track of any users of PHI nodes that are not + /// overdefined, despite the fact that the PHI node is overdefined. + std::multimap UsersOfOverdefinedPHIs; + + /// KnownFeasibleEdges - Entries in this set are edges which have already had + /// PHI nodes retriggered. + typedef std::pair Edge; + DenseSet KnownFeasibleEdges; +public: + SCCPSolver(const TargetData *td) : TD(td) {} + + /// MarkBlockExecutable - This method can be used by clients to mark all of + /// the blocks that are known to be intrinsically live in the processed unit. + /// + /// This returns true if the block was not considered live before. + bool MarkBlockExecutable(BasicBlock *BB) { + if (!BBExecutable.insert(BB)) return false; + DEBUG(errs() << "Marking Block Executable: " << BB->getName() << "\n"); + BBWorkList.push_back(BB); // Add the block to the work list! + return true; + } + + /// TrackValueOfGlobalVariable - Clients can use this method to + /// inform the SCCPSolver that it should track loads and stores to the + /// specified global variable if it can. This is only legal to call if + /// performing Interprocedural SCCP. + void TrackValueOfGlobalVariable(GlobalVariable *GV) { + // We only track the contents of scalar globals. + if (GV->getType()->getElementType()->isSingleValueType()) { + LatticeVal &IV = TrackedGlobals[GV]; + if (!isa(GV->getInitializer())) + IV.markConstant(GV->getInitializer()); + } + } + + /// AddTrackedFunction - If the SCCP solver is supposed to track calls into + /// and out of the specified function (which cannot have its address taken), + /// this method must be called. + void AddTrackedFunction(Function *F) { + // Add an entry, F -> undef. + if (const StructType *STy = dyn_cast(F->getReturnType())) { + MRVFunctionsTracked.insert(F); + for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) + TrackedMultipleRetVals.insert(std::make_pair(std::make_pair(F, i), + LatticeVal())); + } else + TrackedRetVals.insert(std::make_pair(F, LatticeVal())); + } + + void AddArgumentTrackedFunction(Function *F) { + TrackingIncomingArguments.insert(F); + } + + /// Solve - Solve for constants and executable blocks. + /// + void Solve(); + + /// ResolvedUndefsIn - While solving the dataflow for a function, we assume + /// that branches on undef values cannot reach any of their successors. + /// However, this is not a safe assumption. After we solve dataflow, this + /// method should be use to handle this. If this returns true, the solver + /// should be rerun. + bool ResolvedUndefsIn(Function &F); + + bool isBlockExecutable(BasicBlock *BB) const { + return BBExecutable.count(BB); + } + + LatticeVal getLatticeValueFor(Value *V) const { + DenseMap::const_iterator I = ValueState.find(V); + assert(I != ValueState.end() && "V is not in valuemap!"); + return I->second; + } + + LatticeVal getStructLatticeValueFor(Value *V, unsigned i) const { + DenseMap, LatticeVal>::const_iterator I = + StructValueState.find(std::make_pair(V, i)); + assert(I != StructValueState.end() && "V is not in valuemap!"); + return I->second; + } + + /// getTrackedRetVals - Get the inferred return value map. + /// + const DenseMap &getTrackedRetVals() { + return TrackedRetVals; + } + + /// getTrackedGlobals - Get and return the set of inferred initializers for + /// global variables. + const DenseMap &getTrackedGlobals() { + return TrackedGlobals; + } + + void markOverdefined(Value *V) { + assert(!isa(V->getType()) && "Should use other method"); + markOverdefined(ValueState[V], V); + } + + /// markAnythingOverdefined - Mark the specified value overdefined. This + /// works with both scalars and structs. + void markAnythingOverdefined(Value *V) { + if (const StructType *STy = dyn_cast(V->getType())) + for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) + markOverdefined(getStructValueState(V, i), V); + else + markOverdefined(V); + } + +private: + // markConstant - Make a value be marked as "constant". If the value + // is not already a constant, add it to the instruction work list so that + // the users of the instruction are updated later. + // + void markConstant(LatticeVal &IV, Value *V, Constant *C) { + if (!IV.markConstant(C)) return; + DEBUG(errs() << "markConstant: " << *C << ": " << *V << '\n'); + InstWorkList.push_back(V); + } + + void markConstant(Value *V, Constant *C) { + assert(!isa(V->getType()) && "Should use other method"); + markConstant(ValueState[V], V, C); + } + + void markForcedConstant(Value *V, Constant *C) { + assert(!isa(V->getType()) && "Should use other method"); + ValueState[V].markForcedConstant(C); + DEBUG(errs() << "markForcedConstant: " << *C << ": " << *V << '\n'); + InstWorkList.push_back(V); + } + + + // markOverdefined - Make a value be marked as "overdefined". If the + // value is not already overdefined, add it to the overdefined instruction + // work list so that the users of the instruction are updated later. + void markOverdefined(LatticeVal &IV, Value *V) { + if (!IV.markOverdefined()) return; + + DEBUG(errs() << "markOverdefined: "; + if (Function *F = dyn_cast(V)) + errs() << "Function '" << F->getName() << "'\n"; + else + errs() << *V << '\n'); + // Only instructions go on the work list + OverdefinedInstWorkList.push_back(V); + } + + void mergeInValue(LatticeVal &IV, Value *V, LatticeVal MergeWithV) { + if (IV.isOverdefined() || MergeWithV.isUndefined()) + return; // Noop. + if (MergeWithV.isOverdefined()) + markOverdefined(IV, V); + else if (IV.isUndefined()) + markConstant(IV, V, MergeWithV.getConstant()); + else if (IV.getConstant() != MergeWithV.getConstant()) + markOverdefined(IV, V); + } + + void mergeInValue(Value *V, LatticeVal MergeWithV) { + assert(!isa(V->getType()) && "Should use other method"); + mergeInValue(ValueState[V], V, MergeWithV); + } + + + /// getValueState - Return the LatticeVal object that corresponds to the + /// value. This function handles the case when the value hasn't been seen yet + /// by properly seeding constants etc. + LatticeVal &getValueState(Value *V) { + assert(!isa(V->getType()) && "Should use getStructValueState"); + + std::pair::iterator, bool> I = + ValueState.insert(std::make_pair(V, LatticeVal())); + LatticeVal &LV = I.first->second; + + if (!I.second) + return LV; // Common case, already in the map. + + if (Constant *C = dyn_cast(V)) { + // Undef values remain undefined. + if (!isa(V)) + LV.markConstant(C); // Constants are constant + } + + // All others are underdefined by default. + return LV; + } + + /// getStructValueState - Return the LatticeVal object that corresponds to the + /// value/field pair. This function handles the case when the value hasn't + /// been seen yet by properly seeding constants etc. + LatticeVal &getStructValueState(Value *V, unsigned i) { + assert(isa(V->getType()) && "Should use getValueState"); + assert(i < cast(V->getType())->getNumElements() && + "Invalid element #"); + + std::pair, LatticeVal>::iterator, + bool> I = StructValueState.insert( + std::make_pair(std::make_pair(V, i), LatticeVal())); + LatticeVal &LV = I.first->second; + + if (!I.second) + return LV; // Common case, already in the map. + + if (Constant *C = dyn_cast(V)) { + if (isa(C)) + ; // Undef values remain undefined. + else if (ConstantStruct *CS = dyn_cast(C)) + LV.markConstant(CS->getOperand(i)); // Constants are constant. + else if (isa(C)) { + const Type *FieldTy = cast(V->getType())->getElementType(i); + LV.markConstant(Constant::getNullValue(FieldTy)); + } else + LV.markOverdefined(); // Unknown sort of constant. + } + + // All others are underdefined by default. + return LV; + } + + + /// markEdgeExecutable - Mark a basic block as executable, adding it to the BB + /// work list if it is not already executable. + void markEdgeExecutable(BasicBlock *Source, BasicBlock *Dest) { + if (!KnownFeasibleEdges.insert(Edge(Source, Dest)).second) + return; // This edge is already known to be executable! + + if (!MarkBlockExecutable(Dest)) { + // If the destination is already executable, we just made an *edge* + // feasible that wasn't before. Revisit the PHI nodes in the block + // because they have potentially new operands. + DEBUG(errs() << "Marking Edge Executable: " << Source->getName() + << " -> " << Dest->getName() << "\n"); + + PHINode *PN; + for (BasicBlock::iterator I = Dest->begin(); + (PN = dyn_cast(I)); ++I) + visitPHINode(*PN); + } + } + + // getFeasibleSuccessors - Return a vector of booleans to indicate which + // successors are reachable from a given terminator instruction. + // + void getFeasibleSuccessors(TerminatorInst &TI, SmallVector &Succs); + + // isEdgeFeasible - Return true if the control flow edge from the 'From' basic + // block to the 'To' basic block is currently feasible. + // + bool isEdgeFeasible(BasicBlock *From, BasicBlock *To); + + // OperandChangedState - This method is invoked on all of the users of an + // instruction that was just changed state somehow. Based on this + // information, we need to update the specified user of this instruction. + // + void OperandChangedState(Instruction *I) { + if (BBExecutable.count(I->getParent())) // Inst is executable? + visit(*I); + } + + /// RemoveFromOverdefinedPHIs - If I has any entries in the + /// UsersOfOverdefinedPHIs map for PN, remove them now. + void RemoveFromOverdefinedPHIs(Instruction *I, PHINode *PN) { + if (UsersOfOverdefinedPHIs.empty()) return; + std::multimap::iterator It, E; + tie(It, E) = UsersOfOverdefinedPHIs.equal_range(PN); + while (It != E) { + if (It->second == I) + UsersOfOverdefinedPHIs.erase(It++); + else + ++It; + } + } + +private: + friend class InstVisitor; + + // visit implementations - Something changed in this instruction. Either an + // operand made a transition, or the instruction is newly executable. Change + // the value type of I to reflect these changes if appropriate. + void visitPHINode(PHINode &I); + + // Terminators + void visitReturnInst(ReturnInst &I); + void visitTerminatorInst(TerminatorInst &TI); + + void visitCastInst(CastInst &I); + void visitSelectInst(SelectInst &I); + void visitBinaryOperator(Instruction &I); + void visitCmpInst(CmpInst &I); + void visitExtractElementInst(ExtractElementInst &I); + void visitInsertElementInst(InsertElementInst &I); + void visitShuffleVectorInst(ShuffleVectorInst &I); + void visitExtractValueInst(ExtractValueInst &EVI); + void visitInsertValueInst(InsertValueInst &IVI); + + // Instructions that cannot be folded away. + void visitStoreInst (StoreInst &I); + void visitLoadInst (LoadInst &I); + void visitGetElementPtrInst(GetElementPtrInst &I); + void visitCallInst (CallInst &I) { + visitCallSite(CallSite::get(&I)); + } + void visitInvokeInst (InvokeInst &II) { + visitCallSite(CallSite::get(&II)); + visitTerminatorInst(II); + } + void visitCallSite (CallSite CS); + void visitUnwindInst (TerminatorInst &I) { /*returns void*/ } + void visitUnreachableInst(TerminatorInst &I) { /*returns void*/ } + void visitAllocaInst (Instruction &I) { markOverdefined(&I); } + void visitVANextInst (Instruction &I) { markOverdefined(&I); } + void visitVAArgInst (Instruction &I) { markAnythingOverdefined(&I); } + + void visitInstruction(Instruction &I) { + // If a new instruction is added to LLVM that we don't handle. + errs() << "SCCP: Don't know how to handle: " << I; + markAnythingOverdefined(&I); // Just in case + } +}; + +} // end anonymous namespace + + +// getFeasibleSuccessors - Return a vector of booleans to indicate which +// successors are reachable from a given terminator instruction. +// +void SCCPSolver::getFeasibleSuccessors(TerminatorInst &TI, + SmallVector &Succs) { + Succs.resize(TI.getNumSuccessors()); + if (BranchInst *BI = dyn_cast(&TI)) { + if (BI->isUnconditional()) { + Succs[0] = true; + return; + } + + LatticeVal BCValue = getValueState(BI->getCondition()); + ConstantInt *CI = BCValue.getConstantInt(); + if (CI == 0) { + // Overdefined condition variables, and branches on unfoldable constant + // conditions, mean the branch could go either way. + if (!BCValue.isUndefined()) + Succs[0] = Succs[1] = true; + return; + } + + // Constant condition variables mean the branch can only go a single way. + Succs[CI->isZero()] = true; + return; + } + + if (isa(TI)) { + // Invoke instructions successors are always executable. + Succs[0] = Succs[1] = true; + return; + } + + if (SwitchInst *SI = dyn_cast(&TI)) { + LatticeVal SCValue = getValueState(SI->getCondition()); + ConstantInt *CI = SCValue.getConstantInt(); + + if (CI == 0) { // Overdefined or undefined condition? + // All destinations are executable! + if (!SCValue.isUndefined()) + Succs.assign(TI.getNumSuccessors(), true); + return; + } + + Succs[SI->findCaseValue(CI)] = true; + return; + } + + // TODO: This could be improved if the operand is a [cast of a] BlockAddress. + if (isa(&TI)) { + // Just mark all destinations executable! + Succs.assign(TI.getNumSuccessors(), true); + return; + } + +#ifndef NDEBUG + errs() << "Unknown terminator instruction: " << TI << '\n'; +#endif + llvm_unreachable("SCCP: Don't know how to handle this terminator!"); +} + + +// isEdgeFeasible - Return true if the control flow edge from the 'From' basic +// block to the 'To' basic block is currently feasible. +// +bool SCCPSolver::isEdgeFeasible(BasicBlock *From, BasicBlock *To) { + assert(BBExecutable.count(To) && "Dest should always be alive!"); + + // Make sure the source basic block is executable!! + if (!BBExecutable.count(From)) return false; + + // Check to make sure this edge itself is actually feasible now. + TerminatorInst *TI = From->getTerminator(); + if (BranchInst *BI = dyn_cast(TI)) { + if (BI->isUnconditional()) + return true; + + LatticeVal BCValue = getValueState(BI->getCondition()); + + // Overdefined condition variables mean the branch could go either way, + // undef conditions mean that neither edge is feasible yet. + ConstantInt *CI = BCValue.getConstantInt(); + if (CI == 0) + return !BCValue.isUndefined(); + + // Constant condition variables mean the branch can only go a single way. + return BI->getSuccessor(CI->isZero()) == To; + } + + // Invoke instructions successors are always executable. + if (isa(TI)) + return true; + + if (SwitchInst *SI = dyn_cast(TI)) { + LatticeVal SCValue = getValueState(SI->getCondition()); + ConstantInt *CI = SCValue.getConstantInt(); + + if (CI == 0) + return !SCValue.isUndefined(); + + // Make sure to skip the "default value" which isn't a value + for (unsigned i = 1, E = SI->getNumSuccessors(); i != E; ++i) + if (SI->getSuccessorValue(i) == CI) // Found the taken branch. + return SI->getSuccessor(i) == To; + + // If the constant value is not equal to any of the branches, we must + // execute default branch. + return SI->getDefaultDest() == To; + } + + // Just mark all destinations executable! + // TODO: This could be improved if the operand is a [cast of a] BlockAddress. + if (isa(&TI)) + return true; + +#ifndef NDEBUG + errs() << "Unknown terminator instruction: " << *TI << '\n'; +#endif + llvm_unreachable(0); +} + +// visit Implementations - Something changed in this instruction, either an +// operand made a transition, or the instruction is newly executable. Change +// the value type of I to reflect these changes if appropriate. This method +// makes sure to do the following actions: +// +// 1. If a phi node merges two constants in, and has conflicting value coming +// from different branches, or if the PHI node merges in an overdefined +// value, then the PHI node becomes overdefined. +// 2. If a phi node merges only constants in, and they all agree on value, the +// PHI node becomes a constant value equal to that. +// 3. If V <- x (op) y && isConstant(x) && isConstant(y) V = Constant +// 4. If V <- x (op) y && (isOverdefined(x) || isOverdefined(y)) V = Overdefined +// 5. If V <- MEM or V <- CALL or V <- (unknown) then V = Overdefined +// 6. If a conditional branch has a value that is constant, make the selected +// destination executable +// 7. If a conditional branch has a value that is overdefined, make all +// successors executable. +// +void SCCPSolver::visitPHINode(PHINode &PN) { + // If this PN returns a struct, just mark the result overdefined. + // TODO: We could do a lot better than this if code actually uses this. + if (isa(PN.getType())) + return markAnythingOverdefined(&PN); + + if (getValueState(&PN).isOverdefined()) { + // There may be instructions using this PHI node that are not overdefined + // themselves. If so, make sure that they know that the PHI node operand + // changed. + std::multimap::iterator I, E; + tie(I, E) = UsersOfOverdefinedPHIs.equal_range(&PN); + if (I == E) + return; + + SmallVector Users; + for (; I != E; ++I) + Users.push_back(I->second); + while (!Users.empty()) + visit(Users.pop_back_val()); + return; // Quick exit + } + + // Super-extra-high-degree PHI nodes are unlikely to ever be marked constant, + // and slow us down a lot. Just mark them overdefined. + if (PN.getNumIncomingValues() > 64) + return markOverdefined(&PN); + + // Look at all of the executable operands of the PHI node. If any of them + // are overdefined, the PHI becomes overdefined as well. If they are all + // constant, and they agree with each other, the PHI becomes the identical + // constant. If they are constant and don't agree, the PHI is overdefined. + // If there are no executable operands, the PHI remains undefined. + // + Constant *OperandVal = 0; + for (unsigned i = 0, e = PN.getNumIncomingValues(); i != e; ++i) { + LatticeVal IV = getValueState(PN.getIncomingValue(i)); + if (IV.isUndefined()) continue; // Doesn't influence PHI node. + + if (!isEdgeFeasible(PN.getIncomingBlock(i), PN.getParent())) + continue; + + if (IV.isOverdefined()) // PHI node becomes overdefined! + return markOverdefined(&PN); + + if (OperandVal == 0) { // Grab the first value. + OperandVal = IV.getConstant(); + continue; + } + + // There is already a reachable operand. If we conflict with it, + // then the PHI node becomes overdefined. If we agree with it, we + // can continue on. + + // Check to see if there are two different constants merging, if so, the PHI + // node is overdefined. + if (IV.getConstant() != OperandVal) + return markOverdefined(&PN); + } + + // If we exited the loop, this means that the PHI node only has constant + // arguments that agree with each other(and OperandVal is the constant) or + // OperandVal is null because there are no defined incoming arguments. If + // this is the case, the PHI remains undefined. + // + if (OperandVal) + markConstant(&PN, OperandVal); // Acquire operand value +} + + + + +void SCCPSolver::visitReturnInst(ReturnInst &I) { + if (I.getNumOperands() == 0) return; // ret void + + Function *F = I.getParent()->getParent(); + Value *ResultOp = I.getOperand(0); + + // If we are tracking the return value of this function, merge it in. + if (!TrackedRetVals.empty() && !isa(ResultOp->getType())) { + DenseMap::iterator TFRVI = + TrackedRetVals.find(F); + if (TFRVI != TrackedRetVals.end()) { + mergeInValue(TFRVI->second, F, getValueState(ResultOp)); + return; + } + } + + // Handle functions that return multiple values. + if (!TrackedMultipleRetVals.empty()) { + if (const StructType *STy = dyn_cast(ResultOp->getType())) + if (MRVFunctionsTracked.count(F)) + for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) + mergeInValue(TrackedMultipleRetVals[std::make_pair(F, i)], F, + getStructValueState(ResultOp, i)); + + } +} + +void SCCPSolver::visitTerminatorInst(TerminatorInst &TI) { + SmallVector SuccFeasible; + getFeasibleSuccessors(TI, SuccFeasible); + + BasicBlock *BB = TI.getParent(); + + // Mark all feasible successors executable. + for (unsigned i = 0, e = SuccFeasible.size(); i != e; ++i) + if (SuccFeasible[i]) + markEdgeExecutable(BB, TI.getSuccessor(i)); +} + +void SCCPSolver::visitCastInst(CastInst &I) { + LatticeVal OpSt = getValueState(I.getOperand(0)); + if (OpSt.isOverdefined()) // Inherit overdefinedness of operand + markOverdefined(&I); + else if (OpSt.isConstant()) // Propagate constant value + markConstant(&I, ConstantExpr::getCast(I.getOpcode(), + OpSt.getConstant(), I.getType())); +} + + +void SCCPSolver::visitExtractValueInst(ExtractValueInst &EVI) { + // If this returns a struct, mark all elements over defined, we don't track + // structs in structs. + if (isa(EVI.getType())) + return markAnythingOverdefined(&EVI); + + // If this is extracting from more than one level of struct, we don't know. + if (EVI.getNumIndices() != 1) + return markOverdefined(&EVI); + + Value *AggVal = EVI.getAggregateOperand(); + if (isa(AggVal->getType())) { + unsigned i = *EVI.idx_begin(); + LatticeVal EltVal = getStructValueState(AggVal, i); + mergeInValue(getValueState(&EVI), &EVI, EltVal); + } else { + // Otherwise, must be extracting from an array. + return markOverdefined(&EVI); + } +} + +void SCCPSolver::visitInsertValueInst(InsertValueInst &IVI) { + const StructType *STy = dyn_cast(IVI.getType()); + if (STy == 0) + return markOverdefined(&IVI); + + // If this has more than one index, we can't handle it, drive all results to + // undef. + if (IVI.getNumIndices() != 1) + return markAnythingOverdefined(&IVI); + + Value *Aggr = IVI.getAggregateOperand(); + unsigned Idx = *IVI.idx_begin(); + + // Compute the result based on what we're inserting. + for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) { + // This passes through all values that aren't the inserted element. + if (i != Idx) { + LatticeVal EltVal = getStructValueState(Aggr, i); + mergeInValue(getStructValueState(&IVI, i), &IVI, EltVal); + continue; + } + + Value *Val = IVI.getInsertedValueOperand(); + if (isa(Val->getType())) + // We don't track structs in structs. + markOverdefined(getStructValueState(&IVI, i), &IVI); + else { + LatticeVal InVal = getValueState(Val); + mergeInValue(getStructValueState(&IVI, i), &IVI, InVal); + } + } +} + +void SCCPSolver::visitSelectInst(SelectInst &I) { + // If this select returns a struct, just mark the result overdefined. + // TODO: We could do a lot better than this if code actually uses this. + if (isa(I.getType())) + return markAnythingOverdefined(&I); + + LatticeVal CondValue = getValueState(I.getCondition()); + if (CondValue.isUndefined()) + return; + + if (ConstantInt *CondCB = CondValue.getConstantInt()) { + Value *OpVal = CondCB->isZero() ? I.getFalseValue() : I.getTrueValue(); + mergeInValue(&I, getValueState(OpVal)); + return; + } + + // Otherwise, the condition is overdefined or a constant we can't evaluate. + // See if we can produce something better than overdefined based on the T/F + // value. + LatticeVal TVal = getValueState(I.getTrueValue()); + LatticeVal FVal = getValueState(I.getFalseValue()); + + // select ?, C, C -> C. + if (TVal.isConstant() && FVal.isConstant() && + TVal.getConstant() == FVal.getConstant()) + return markConstant(&I, FVal.getConstant()); + + if (TVal.isUndefined()) // select ?, undef, X -> X. + return mergeInValue(&I, FVal); + if (FVal.isUndefined()) // select ?, X, undef -> X. + return mergeInValue(&I, TVal); + markOverdefined(&I); +} + +// Handle Binary Operators. +void SCCPSolver::visitBinaryOperator(Instruction &I) { + LatticeVal V1State = getValueState(I.getOperand(0)); + LatticeVal V2State = getValueState(I.getOperand(1)); + + LatticeVal &IV = ValueState[&I]; + if (IV.isOverdefined()) return; + + if (V1State.isConstant() && V2State.isConstant()) + return markConstant(IV, &I, + ConstantExpr::get(I.getOpcode(), V1State.getConstant(), + V2State.getConstant())); + + // If something is undef, wait for it to resolve. + if (!V1State.isOverdefined() && !V2State.isOverdefined()) + return; + + // Otherwise, one of our operands is overdefined. Try to produce something + // better than overdefined with some tricks. + + // If this is an AND or OR with 0 or -1, it doesn't matter that the other + // operand is overdefined. + if (I.getOpcode() == Instruction::And || I.getOpcode() == Instruction::Or) { + LatticeVal *NonOverdefVal = 0; + if (!V1State.isOverdefined()) + NonOverdefVal = &V1State; + else if (!V2State.isOverdefined()) + NonOverdefVal = &V2State; + + if (NonOverdefVal) { + if (NonOverdefVal->isUndefined()) { + // Could annihilate value. + if (I.getOpcode() == Instruction::And) + markConstant(IV, &I, Constant::getNullValue(I.getType())); + else if (const VectorType *PT = dyn_cast(I.getType())) + markConstant(IV, &I, Constant::getAllOnesValue(PT)); + else + markConstant(IV, &I, + Constant::getAllOnesValue(I.getType())); + return; + } + + if (I.getOpcode() == Instruction::And) { + // X and 0 = 0 + if (NonOverdefVal->getConstant()->isNullValue()) + return markConstant(IV, &I, NonOverdefVal->getConstant()); + } else { + if (ConstantInt *CI = NonOverdefVal->getConstantInt()) + if (CI->isAllOnesValue()) // X or -1 = -1 + return markConstant(IV, &I, NonOverdefVal->getConstant()); + } + } + } + + + // If both operands are PHI nodes, it is possible that this instruction has + // a constant value, despite the fact that the PHI node doesn't. Check for + // this condition now. + if (PHINode *PN1 = dyn_cast(I.getOperand(0))) + if (PHINode *PN2 = dyn_cast(I.getOperand(1))) + if (PN1->getParent() == PN2->getParent()) { + // Since the two PHI nodes are in the same basic block, they must have + // entries for the same predecessors. Walk the predecessor list, and + // if all of the incoming values are constants, and the result of + // evaluating this expression with all incoming value pairs is the + // same, then this expression is a constant even though the PHI node + // is not a constant! + LatticeVal Result; + for (unsigned i = 0, e = PN1->getNumIncomingValues(); i != e; ++i) { + LatticeVal In1 = getValueState(PN1->getIncomingValue(i)); + BasicBlock *InBlock = PN1->getIncomingBlock(i); + LatticeVal In2 =getValueState(PN2->getIncomingValueForBlock(InBlock)); + + if (In1.isOverdefined() || In2.isOverdefined()) { + Result.markOverdefined(); + break; // Cannot fold this operation over the PHI nodes! + } + + if (In1.isConstant() && In2.isConstant()) { + Constant *V = ConstantExpr::get(I.getOpcode(), In1.getConstant(), + In2.getConstant()); + if (Result.isUndefined()) + Result.markConstant(V); + else if (Result.isConstant() && Result.getConstant() != V) { + Result.markOverdefined(); + break; + } + } + } + + // If we found a constant value here, then we know the instruction is + // constant despite the fact that the PHI nodes are overdefined. + if (Result.isConstant()) { + markConstant(IV, &I, Result.getConstant()); + // Remember that this instruction is virtually using the PHI node + // operands. + UsersOfOverdefinedPHIs.insert(std::make_pair(PN1, &I)); + UsersOfOverdefinedPHIs.insert(std::make_pair(PN2, &I)); + return; + } + + if (Result.isUndefined()) + return; + + // Okay, this really is overdefined now. Since we might have + // speculatively thought that this was not overdefined before, and + // added ourselves to the UsersOfOverdefinedPHIs list for the PHIs, + // make sure to clean out any entries that we put there, for + // efficiency. + RemoveFromOverdefinedPHIs(&I, PN1); + RemoveFromOverdefinedPHIs(&I, PN2); + } + + markOverdefined(&I); +} + +// Handle ICmpInst instruction. +void SCCPSolver::visitCmpInst(CmpInst &I) { + LatticeVal V1State = getValueState(I.getOperand(0)); + LatticeVal V2State = getValueState(I.getOperand(1)); + + LatticeVal &IV = ValueState[&I]; + if (IV.isOverdefined()) return; + + if (V1State.isConstant() && V2State.isConstant()) + return markConstant(IV, &I, ConstantExpr::getCompare(I.getPredicate(), + V1State.getConstant(), + V2State.getConstant())); + + // If operands are still undefined, wait for it to resolve. + if (!V1State.isOverdefined() && !V2State.isOverdefined()) + return; + + // If something is overdefined, use some tricks to avoid ending up and over + // defined if we can. + + // If both operands are PHI nodes, it is possible that this instruction has + // a constant value, despite the fact that the PHI node doesn't. Check for + // this condition now. + if (PHINode *PN1 = dyn_cast(I.getOperand(0))) + if (PHINode *PN2 = dyn_cast(I.getOperand(1))) + if (PN1->getParent() == PN2->getParent()) { + // Since the two PHI nodes are in the same basic block, they must have + // entries for the same predecessors. Walk the predecessor list, and + // if all of the incoming values are constants, and the result of + // evaluating this expression with all incoming value pairs is the + // same, then this expression is a constant even though the PHI node + // is not a constant! + LatticeVal Result; + for (unsigned i = 0, e = PN1->getNumIncomingValues(); i != e; ++i) { + LatticeVal In1 = getValueState(PN1->getIncomingValue(i)); + BasicBlock *InBlock = PN1->getIncomingBlock(i); + LatticeVal In2 =getValueState(PN2->getIncomingValueForBlock(InBlock)); + + if (In1.isOverdefined() || In2.isOverdefined()) { + Result.markOverdefined(); + break; // Cannot fold this operation over the PHI nodes! + } + + if (In1.isConstant() && In2.isConstant()) { + Constant *V = ConstantExpr::getCompare(I.getPredicate(), + In1.getConstant(), + In2.getConstant()); + if (Result.isUndefined()) + Result.markConstant(V); + else if (Result.isConstant() && Result.getConstant() != V) { + Result.markOverdefined(); + break; + } + } + } + + // If we found a constant value here, then we know the instruction is + // constant despite the fact that the PHI nodes are overdefined. + if (Result.isConstant()) { + markConstant(&I, Result.getConstant()); + // Remember that this instruction is virtually using the PHI node + // operands. + UsersOfOverdefinedPHIs.insert(std::make_pair(PN1, &I)); + UsersOfOverdefinedPHIs.insert(std::make_pair(PN2, &I)); + return; + } + + if (Result.isUndefined()) + return; + + // Okay, this really is overdefined now. Since we might have + // speculatively thought that this was not overdefined before, and + // added ourselves to the UsersOfOverdefinedPHIs list for the PHIs, + // make sure to clean out any entries that we put there, for + // efficiency. + RemoveFromOverdefinedPHIs(&I, PN1); + RemoveFromOverdefinedPHIs(&I, PN2); + } + + markOverdefined(&I); +} + +void SCCPSolver::visitExtractElementInst(ExtractElementInst &I) { + // TODO : SCCP does not handle vectors properly. + return markOverdefined(&I); + +#if 0 + LatticeVal &ValState = getValueState(I.getOperand(0)); + LatticeVal &IdxState = getValueState(I.getOperand(1)); + + if (ValState.isOverdefined() || IdxState.isOverdefined()) + markOverdefined(&I); + else if(ValState.isConstant() && IdxState.isConstant()) + markConstant(&I, ConstantExpr::getExtractElement(ValState.getConstant(), + IdxState.getConstant())); +#endif +} + +void SCCPSolver::visitInsertElementInst(InsertElementInst &I) { + // TODO : SCCP does not handle vectors properly. + return markOverdefined(&I); +#if 0 + LatticeVal &ValState = getValueState(I.getOperand(0)); + LatticeVal &EltState = getValueState(I.getOperand(1)); + LatticeVal &IdxState = getValueState(I.getOperand(2)); + + if (ValState.isOverdefined() || EltState.isOverdefined() || + IdxState.isOverdefined()) + markOverdefined(&I); + else if(ValState.isConstant() && EltState.isConstant() && + IdxState.isConstant()) + markConstant(&I, ConstantExpr::getInsertElement(ValState.getConstant(), + EltState.getConstant(), + IdxState.getConstant())); + else if (ValState.isUndefined() && EltState.isConstant() && + IdxState.isConstant()) + markConstant(&I,ConstantExpr::getInsertElement(UndefValue::get(I.getType()), + EltState.getConstant(), + IdxState.getConstant())); +#endif +} + +void SCCPSolver::visitShuffleVectorInst(ShuffleVectorInst &I) { + // TODO : SCCP does not handle vectors properly. + return markOverdefined(&I); +#if 0 + LatticeVal &V1State = getValueState(I.getOperand(0)); + LatticeVal &V2State = getValueState(I.getOperand(1)); + LatticeVal &MaskState = getValueState(I.getOperand(2)); + + if (MaskState.isUndefined() || + (V1State.isUndefined() && V2State.isUndefined())) + return; // Undefined output if mask or both inputs undefined. + + if (V1State.isOverdefined() || V2State.isOverdefined() || + MaskState.isOverdefined()) { + markOverdefined(&I); + } else { + // A mix of constant/undef inputs. + Constant *V1 = V1State.isConstant() ? + V1State.getConstant() : UndefValue::get(I.getType()); + Constant *V2 = V2State.isConstant() ? + V2State.getConstant() : UndefValue::get(I.getType()); + Constant *Mask = MaskState.isConstant() ? + MaskState.getConstant() : UndefValue::get(I.getOperand(2)->getType()); + markConstant(&I, ConstantExpr::getShuffleVector(V1, V2, Mask)); + } +#endif +} + +// Handle getelementptr instructions. If all operands are constants then we +// can turn this into a getelementptr ConstantExpr. +// +void SCCPSolver::visitGetElementPtrInst(GetElementPtrInst &I) { + if (ValueState[&I].isOverdefined()) return; + + SmallVector Operands; + Operands.reserve(I.getNumOperands()); + + for (unsigned i = 0, e = I.getNumOperands(); i != e; ++i) { + LatticeVal State = getValueState(I.getOperand(i)); + if (State.isUndefined()) + return; // Operands are not resolved yet. + + if (State.isOverdefined()) + return markOverdefined(&I); + + assert(State.isConstant() && "Unknown state!"); + Operands.push_back(State.getConstant()); + } + + Constant *Ptr = Operands[0]; + markConstant(&I, ConstantExpr::getGetElementPtr(Ptr, &Operands[0]+1, + Operands.size()-1)); +} + +void SCCPSolver::visitStoreInst(StoreInst &SI) { + // If this store is of a struct, ignore it. + if (isa(SI.getOperand(0)->getType())) + return; + + if (TrackedGlobals.empty() || !isa(SI.getOperand(1))) + return; + + GlobalVariable *GV = cast(SI.getOperand(1)); + DenseMap::iterator I = TrackedGlobals.find(GV); + if (I == TrackedGlobals.end() || I->second.isOverdefined()) return; + + // Get the value we are storing into the global, then merge it. + mergeInValue(I->second, GV, getValueState(SI.getOperand(0))); + if (I->second.isOverdefined()) + TrackedGlobals.erase(I); // No need to keep tracking this! +} + + +// Handle load instructions. If the operand is a constant pointer to a constant +// global, we can replace the load with the loaded constant value! +void SCCPSolver::visitLoadInst(LoadInst &I) { + // If this load is of a struct, just mark the result overdefined. + if (isa(I.getType())) + return markAnythingOverdefined(&I); + + LatticeVal PtrVal = getValueState(I.getOperand(0)); + if (PtrVal.isUndefined()) return; // The pointer is not resolved yet! + + LatticeVal &IV = ValueState[&I]; + if (IV.isOverdefined()) return; + + if (!PtrVal.isConstant() || I.isVolatile()) + return markOverdefined(IV, &I); + + Constant *Ptr = PtrVal.getConstant(); + + // load null -> null + if (isa(Ptr) && I.getPointerAddressSpace() == 0) + return markConstant(IV, &I, Constant::getNullValue(I.getType())); + + // Transform load (constant global) into the value loaded. + if (GlobalVariable *GV = dyn_cast(Ptr)) { + if (!TrackedGlobals.empty()) { + // If we are tracking this global, merge in the known value for it. + DenseMap::iterator It = + TrackedGlobals.find(GV); + if (It != TrackedGlobals.end()) { + mergeInValue(IV, &I, It->second); + return; + } + } + } + + // Transform load from a constant into a constant if possible. + if (Constant *C = ConstantFoldLoadFromConstPtr(Ptr, TD)) + return markConstant(IV, &I, C); + + // Otherwise we cannot say for certain what value this load will produce. + // Bail out. + markOverdefined(IV, &I); +} + +void SCCPSolver::visitCallSite(CallSite CS) { + Function *F = CS.getCalledFunction(); + Instruction *I = CS.getInstruction(); + + // The common case is that we aren't tracking the callee, either because we + // are not doing interprocedural analysis or the callee is indirect, or is + // external. Handle these cases first. + if (F == 0 || F->isDeclaration()) { +CallOverdefined: + // Void return and not tracking callee, just bail. + if (I->getType()->isVoidTy()) return; + + // Otherwise, if we have a single return value case, and if the function is + // a declaration, maybe we can constant fold it. + if (F && F->isDeclaration() && !isa(I->getType()) && + canConstantFoldCallTo(F)) { + + SmallVector Operands; + for (CallSite::arg_iterator AI = CS.arg_begin(), E = CS.arg_end(); + AI != E; ++AI) { + LatticeVal State = getValueState(*AI); + + if (State.isUndefined()) + return; // Operands are not resolved yet. + if (State.isOverdefined()) + return markOverdefined(I); + assert(State.isConstant() && "Unknown state!"); + Operands.push_back(State.getConstant()); + } + + // If we can constant fold this, mark the result of the call as a + // constant. + if (Constant *C = ConstantFoldCall(F, Operands.data(), Operands.size())) + return markConstant(I, C); + } + + // Otherwise, we don't know anything about this call, mark it overdefined. + return markAnythingOverdefined(I); + } + + // If this is a local function that doesn't have its address taken, mark its + // entry block executable and merge in the actual arguments to the call into + // the formal arguments of the function. + if (!TrackingIncomingArguments.empty() && TrackingIncomingArguments.count(F)){ + MarkBlockExecutable(F->begin()); + + // Propagate information from this call site into the callee. + CallSite::arg_iterator CAI = CS.arg_begin(); + for (Function::arg_iterator AI = F->arg_begin(), E = F->arg_end(); + AI != E; ++AI, ++CAI) { + // If this argument is byval, and if the function is not readonly, there + // will be an implicit copy formed of the input aggregate. + if (AI->hasByValAttr() && !F->onlyReadsMemory()) { + markOverdefined(AI); + continue; + } + + if (const StructType *STy = dyn_cast(AI->getType())) { + for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) { + LatticeVal CallArg = getStructValueState(*CAI, i); + mergeInValue(getStructValueState(AI, i), AI, CallArg); + } + } else { + mergeInValue(AI, getValueState(*CAI)); + } + } + } + + // If this is a single/zero retval case, see if we're tracking the function. + if (const StructType *STy = dyn_cast(F->getReturnType())) { + if (!MRVFunctionsTracked.count(F)) + goto CallOverdefined; // Not tracking this callee. + + // If we are tracking this callee, propagate the result of the function + // into this call site. + for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) + mergeInValue(getStructValueState(I, i), I, + TrackedMultipleRetVals[std::make_pair(F, i)]); + } else { + DenseMap::iterator TFRVI = TrackedRetVals.find(F); + if (TFRVI == TrackedRetVals.end()) + goto CallOverdefined; // Not tracking this callee. + + // If so, propagate the return value of the callee into this call result. + mergeInValue(I, TFRVI->second); + } +} + +void SCCPSolver::Solve() { + // Process the work lists until they are empty! + while (!BBWorkList.empty() || !InstWorkList.empty() || + !OverdefinedInstWorkList.empty()) { + // Process the overdefined instruction's work list first, which drives other + // things to overdefined more quickly. + while (!OverdefinedInstWorkList.empty()) { + Value *I = OverdefinedInstWorkList.pop_back_val(); + + DEBUG(errs() << "\nPopped off OI-WL: " << *I << '\n'); + + // "I" got into the work list because it either made the transition from + // bottom to constant + // + // Anything on this worklist that is overdefined need not be visited + // since all of its users will have already been marked as overdefined + // Update all of the users of this instruction's value. + // + for (Value::use_iterator UI = I->use_begin(), E = I->use_end(); + UI != E; ++UI) + if (Instruction *I = dyn_cast(*UI)) + OperandChangedState(I); + } + + // Process the instruction work list. + while (!InstWorkList.empty()) { + Value *I = InstWorkList.pop_back_val(); + + DEBUG(errs() << "\nPopped off I-WL: " << *I << '\n'); + + // "I" got into the work list because it made the transition from undef to + // constant. + // + // Anything on this worklist that is overdefined need not be visited + // since all of its users will have already been marked as overdefined. + // Update all of the users of this instruction's value. + // + if (isa(I->getType()) || !getValueState(I).isOverdefined()) + for (Value::use_iterator UI = I->use_begin(), E = I->use_end(); + UI != E; ++UI) + if (Instruction *I = dyn_cast(*UI)) + OperandChangedState(I); + } + + // Process the basic block work list. + while (!BBWorkList.empty()) { + BasicBlock *BB = BBWorkList.back(); + BBWorkList.pop_back(); + + DEBUG(errs() << "\nPopped off BBWL: " << *BB << '\n'); + + // Notify all instructions in this basic block that they are newly + // executable. + visit(BB); + } + } +} + +/// ResolvedUndefsIn - While solving the dataflow for a function, we assume +/// that branches on undef values cannot reach any of their successors. +/// However, this is not a safe assumption. After we solve dataflow, this +/// method should be use to handle this. If this returns true, the solver +/// should be rerun. +/// +/// This method handles this by finding an unresolved branch and marking it one +/// of the edges from the block as being feasible, even though the condition +/// doesn't say it would otherwise be. This allows SCCP to find the rest of the +/// CFG and only slightly pessimizes the analysis results (by marking one, +/// potentially infeasible, edge feasible). This cannot usefully modify the +/// constraints on the condition of the branch, as that would impact other users +/// of the value. +/// +/// This scan also checks for values that use undefs, whose results are actually +/// defined. For example, 'zext i8 undef to i32' should produce all zeros +/// conservatively, as "(zext i8 X -> i32) & 0xFF00" must always return zero, +/// even if X isn't defined. +bool SCCPSolver::ResolvedUndefsIn(Function &F) { + for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB) { + if (!BBExecutable.count(BB)) + continue; + + for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ++I) { + // Look for instructions which produce undef values. + if (I->getType()->isVoidTy()) continue; + + if (const StructType *STy = dyn_cast(I->getType())) { + // Only a few things that can be structs matter for undef. Just send + // all their results to overdefined. We could be more precise than this + // but it isn't worth bothering. + if (isa(I) || isa(I)) { + for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) { + LatticeVal &LV = getStructValueState(I, i); + if (LV.isUndefined()) + markOverdefined(LV, I); + } + } + continue; + } + + LatticeVal &LV = getValueState(I); + if (!LV.isUndefined()) continue; + + // No instructions using structs need disambiguation. + if (isa(I->getOperand(0)->getType())) + continue; + + // Get the lattice values of the first two operands for use below. + LatticeVal Op0LV = getValueState(I->getOperand(0)); + LatticeVal Op1LV; + if (I->getNumOperands() == 2) { + // No instructions using structs need disambiguation. + if (isa(I->getOperand(1)->getType())) + continue; + + // If this is a two-operand instruction, and if both operands are + // undefs, the result stays undef. + Op1LV = getValueState(I->getOperand(1)); + if (Op0LV.isUndefined() && Op1LV.isUndefined()) + continue; + } + + // If this is an instructions whose result is defined even if the input is + // not fully defined, propagate the information. + const Type *ITy = I->getType(); + switch (I->getOpcode()) { + default: break; // Leave the instruction as an undef. + case Instruction::ZExt: + // After a zero extend, we know the top part is zero. SExt doesn't have + // to be handled here, because we don't know whether the top part is 1's + // or 0's. + markForcedConstant(I, Constant::getNullValue(ITy)); + return true; + case Instruction::Mul: + case Instruction::And: + // undef * X -> 0. X could be zero. + // undef & X -> 0. X could be zero. + markForcedConstant(I, Constant::getNullValue(ITy)); + return true; + + case Instruction::Or: + // undef | X -> -1. X could be -1. + markForcedConstant(I, Constant::getAllOnesValue(ITy)); + return true; + + case Instruction::SDiv: + case Instruction::UDiv: + case Instruction::SRem: + case Instruction::URem: + // X / undef -> undef. No change. + // X % undef -> undef. No change. + if (Op1LV.isUndefined()) break; + + // undef / X -> 0. X could be maxint. + // undef % X -> 0. X could be 1. + markForcedConstant(I, Constant::getNullValue(ITy)); + return true; + + case Instruction::AShr: + // undef >>s X -> undef. No change. + if (Op0LV.isUndefined()) break; + + // X >>s undef -> X. X could be 0, X could have the high-bit known set. + if (Op0LV.isConstant()) + markForcedConstant(I, Op0LV.getConstant()); + else + markOverdefined(I); + return true; + case Instruction::LShr: + case Instruction::Shl: + // undef >> X -> undef. No change. + // undef << X -> undef. No change. + if (Op0LV.isUndefined()) break; + + // X >> undef -> 0. X could be 0. + // X << undef -> 0. X could be 0. + markForcedConstant(I, Constant::getNullValue(ITy)); + return true; + case Instruction::Select: + // undef ? X : Y -> X or Y. There could be commonality between X/Y. + if (Op0LV.isUndefined()) { + if (!Op1LV.isConstant()) // Pick the constant one if there is any. + Op1LV = getValueState(I->getOperand(2)); + } else if (Op1LV.isUndefined()) { + // c ? undef : undef -> undef. No change. + Op1LV = getValueState(I->getOperand(2)); + if (Op1LV.isUndefined()) + break; + // Otherwise, c ? undef : x -> x. + } else { + // Leave Op1LV as Operand(1)'s LatticeValue. + } + + if (Op1LV.isConstant()) + markForcedConstant(I, Op1LV.getConstant()); + else + markOverdefined(I); + return true; + case Instruction::Call: + // If a call has an undef result, it is because it is constant foldable + // but one of the inputs was undef. Just force the result to + // overdefined. + markOverdefined(I); + return true; + } + } + + TerminatorInst *TI = BB->getTerminator(); + if (BranchInst *BI = dyn_cast(TI)) { + if (!BI->isConditional()) continue; + if (!getValueState(BI->getCondition()).isUndefined()) + continue; + } else if (SwitchInst *SI = dyn_cast(TI)) { + if (SI->getNumSuccessors() < 2) // no cases + continue; + if (!getValueState(SI->getCondition()).isUndefined()) + continue; + } else { + continue; + } + + // If the edge to the second successor isn't thought to be feasible yet, + // mark it so now. We pick the second one so that this goes to some + // enumerated value in a switch instead of going to the default destination. + if (KnownFeasibleEdges.count(Edge(BB, TI->getSuccessor(1)))) + continue; + + // Otherwise, it isn't already thought to be feasible. Mark it as such now + // and return. This will make other blocks reachable, which will allow new + // values to be discovered and existing ones to be moved in the lattice. + markEdgeExecutable(BB, TI->getSuccessor(1)); + + // This must be a conditional branch of switch on undef. At this point, + // force the old terminator to branch to the first successor. This is + // required because we are now influencing the dataflow of the function with + // the assumption that this edge is taken. If we leave the branch condition + // as undef, then further analysis could think the undef went another way + // leading to an inconsistent set of conclusions. + if (BranchInst *BI = dyn_cast(TI)) { + BI->setCondition(ConstantInt::getFalse(BI->getContext())); + } else { + SwitchInst *SI = cast(TI); + SI->setCondition(SI->getCaseValue(1)); + } + + return true; + } + + return false; +} + + +namespace { + //===--------------------------------------------------------------------===// + // + /// SCCP Class - This class uses the SCCPSolver to implement a per-function + /// Sparse Conditional Constant Propagator. + /// + struct SCCP : public FunctionPass { + static char ID; // Pass identification, replacement for typeid + SCCP() : FunctionPass(&ID) {} + + // runOnFunction - Run the Sparse Conditional Constant Propagation + // algorithm, and return true if the function was modified. + // + bool runOnFunction(Function &F); + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesCFG(); + } + }; +} // end anonymous namespace + +char SCCP::ID = 0; +static RegisterPass +X("sccp", "Sparse Conditional Constant Propagation"); + +// createSCCPPass - This is the public interface to this file. +FunctionPass *llvm::createSCCPPass() { + return new SCCP(); +} + +static void DeleteInstructionInBlock(BasicBlock *BB) { + DEBUG(errs() << " BasicBlock Dead:" << *BB); + ++NumDeadBlocks; + + // Delete the instructions backwards, as it has a reduced likelihood of + // having to update as many def-use and use-def chains. + while (!isa(BB->begin())) { + Instruction *I = --BasicBlock::iterator(BB->getTerminator()); + + if (!I->use_empty()) + I->replaceAllUsesWith(UndefValue::get(I->getType())); + BB->getInstList().erase(I); + ++NumInstRemoved; + } +} + +// runOnFunction() - Run the Sparse Conditional Constant Propagation algorithm, +// and return true if the function was modified. +// +bool SCCP::runOnFunction(Function &F) { + DEBUG(errs() << "SCCP on function '" << F.getName() << "'\n"); + SCCPSolver Solver(getAnalysisIfAvailable()); + + // Mark the first block of the function as being executable. + Solver.MarkBlockExecutable(F.begin()); + + // Mark all arguments to the function as being overdefined. + for (Function::arg_iterator AI = F.arg_begin(), E = F.arg_end(); AI != E;++AI) + Solver.markAnythingOverdefined(AI); + + // Solve for constants. + bool ResolvedUndefs = true; + while (ResolvedUndefs) { + Solver.Solve(); + DEBUG(errs() << "RESOLVING UNDEFs\n"); + ResolvedUndefs = Solver.ResolvedUndefsIn(F); + } + + bool MadeChanges = false; + + // If we decided that there are basic blocks that are dead in this function, + // delete their contents now. Note that we cannot actually delete the blocks, + // as we cannot modify the CFG of the function. + + for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB) { + if (!Solver.isBlockExecutable(BB)) { + DeleteInstructionInBlock(BB); + MadeChanges = true; + continue; + } + + // Iterate over all of the instructions in a function, replacing them with + // constants if we have found them to be of constant values. + // + for (BasicBlock::iterator BI = BB->begin(), E = BB->end(); BI != E; ) { + Instruction *Inst = BI++; + if (Inst->getType()->isVoidTy() || isa(Inst)) + continue; + + // TODO: Reconstruct structs from their elements. + if (isa(Inst->getType())) + continue; + + LatticeVal IV = Solver.getLatticeValueFor(Inst); + if (IV.isOverdefined()) + continue; + + Constant *Const = IV.isConstant() + ? IV.getConstant() : UndefValue::get(Inst->getType()); + DEBUG(errs() << " Constant: " << *Const << " = " << *Inst); + + // Replaces all of the uses of a variable with uses of the constant. + Inst->replaceAllUsesWith(Const); + + // Delete the instruction. + Inst->eraseFromParent(); + + // Hey, we just changed something! + MadeChanges = true; + ++NumInstRemoved; + } + } + + return MadeChanges; +} + +namespace { + //===--------------------------------------------------------------------===// + // + /// IPSCCP Class - This class implements interprocedural Sparse Conditional + /// Constant Propagation. + /// + struct IPSCCP : public ModulePass { + static char ID; + IPSCCP() : ModulePass(&ID) {} + bool runOnModule(Module &M); + }; +} // end anonymous namespace + +char IPSCCP::ID = 0; +static RegisterPass +Y("ipsccp", "Interprocedural Sparse Conditional Constant Propagation"); + +// createIPSCCPPass - This is the public interface to this file. +ModulePass *llvm::createIPSCCPPass() { + return new IPSCCP(); +} + + +static bool AddressIsTaken(GlobalValue *GV) { + // Delete any dead constantexpr klingons. + GV->removeDeadConstantUsers(); + + for (Value::use_iterator UI = GV->use_begin(), E = GV->use_end(); + UI != E; ++UI) + if (StoreInst *SI = dyn_cast(*UI)) { + if (SI->getOperand(0) == GV || SI->isVolatile()) + return true; // Storing addr of GV. + } else if (isa(*UI) || isa(*UI)) { + // Make sure we are calling the function, not passing the address. + if (UI.getOperandNo() != 0) + return true; + } else if (LoadInst *LI = dyn_cast(*UI)) { + if (LI->isVolatile()) + return true; + } else if (isa(*UI)) { + // blockaddress doesn't take the address of the function, it takes addr + // of label. + } else { + return true; + } + return false; +} + +bool IPSCCP::runOnModule(Module &M) { + SCCPSolver Solver(getAnalysisIfAvailable()); + + // Loop over all functions, marking arguments to those with their addresses + // taken or that are external as overdefined. + // + for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F) { + if (F->isDeclaration()) + continue; + + // If this is a strong or ODR definition of this function, then we can + // propagate information about its result into callsites of it. + if (!F->mayBeOverridden()) + Solver.AddTrackedFunction(F); + + // If this function only has direct calls that we can see, we can track its + // arguments and return value aggressively, and can assume it is not called + // unless we see evidence to the contrary. + if (F->hasLocalLinkage() && !AddressIsTaken(F)) { + Solver.AddArgumentTrackedFunction(F); + continue; + } + + // Assume the function is called. + Solver.MarkBlockExecutable(F->begin()); + + // Assume nothing about the incoming arguments. + for (Function::arg_iterator AI = F->arg_begin(), E = F->arg_end(); + AI != E; ++AI) + Solver.markAnythingOverdefined(AI); + } + + // Loop over global variables. We inform the solver about any internal global + // variables that do not have their 'addresses taken'. If they don't have + // their addresses taken, we can propagate constants through them. + for (Module::global_iterator G = M.global_begin(), E = M.global_end(); + G != E; ++G) + if (!G->isConstant() && G->hasLocalLinkage() && !AddressIsTaken(G)) + Solver.TrackValueOfGlobalVariable(G); + + // Solve for constants. + bool ResolvedUndefs = true; + while (ResolvedUndefs) { + Solver.Solve(); + + DEBUG(errs() << "RESOLVING UNDEFS\n"); + ResolvedUndefs = false; + for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F) + ResolvedUndefs |= Solver.ResolvedUndefsIn(*F); + } + + bool MadeChanges = false; + + // Iterate over all of the instructions in the module, replacing them with + // constants if we have found them to be of constant values. + // + SmallVector BlocksToErase; + + for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F) { + if (Solver.isBlockExecutable(F->begin())) { + for (Function::arg_iterator AI = F->arg_begin(), E = F->arg_end(); + AI != E; ++AI) { + if (AI->use_empty() || isa(AI->getType())) continue; + + // TODO: Could use getStructLatticeValueFor to find out if the entire + // result is a constant and replace it entirely if so. + + LatticeVal IV = Solver.getLatticeValueFor(AI); + if (IV.isOverdefined()) continue; + + Constant *CST = IV.isConstant() ? + IV.getConstant() : UndefValue::get(AI->getType()); + DEBUG(errs() << "*** Arg " << *AI << " = " << *CST <<"\n"); + + // Replaces all of the uses of a variable with uses of the + // constant. + AI->replaceAllUsesWith(CST); + ++IPNumArgsElimed; + } + } + + for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) { + if (!Solver.isBlockExecutable(BB)) { + DeleteInstructionInBlock(BB); + MadeChanges = true; + + TerminatorInst *TI = BB->getTerminator(); + for (unsigned i = 0, e = TI->getNumSuccessors(); i != e; ++i) { + BasicBlock *Succ = TI->getSuccessor(i); + if (!Succ->empty() && isa(Succ->begin())) + TI->getSuccessor(i)->removePredecessor(BB); + } + if (!TI->use_empty()) + TI->replaceAllUsesWith(UndefValue::get(TI->getType())); + TI->eraseFromParent(); + + if (&*BB != &F->front()) + BlocksToErase.push_back(BB); + else + new UnreachableInst(M.getContext(), BB); + continue; + } + + for (BasicBlock::iterator BI = BB->begin(), E = BB->end(); BI != E; ) { + Instruction *Inst = BI++; + if (Inst->getType()->isVoidTy() || isa(Inst->getType())) + continue; + + // TODO: Could use getStructLatticeValueFor to find out if the entire + // result is a constant and replace it entirely if so. + + LatticeVal IV = Solver.getLatticeValueFor(Inst); + if (IV.isOverdefined()) + continue; + + Constant *Const = IV.isConstant() + ? IV.getConstant() : UndefValue::get(Inst->getType()); + DEBUG(errs() << " Constant: " << *Const << " = " << *Inst); + + // Replaces all of the uses of a variable with uses of the + // constant. + Inst->replaceAllUsesWith(Const); + + // Delete the instruction. + if (!isa(Inst) && !isa(Inst)) + Inst->eraseFromParent(); + + // Hey, we just changed something! + MadeChanges = true; + ++IPNumInstRemoved; + } + } + + // Now that all instructions in the function are constant folded, erase dead + // blocks, because we can now use ConstantFoldTerminator to get rid of + // in-edges. + for (unsigned i = 0, e = BlocksToErase.size(); i != e; ++i) { + // If there are any PHI nodes in this successor, drop entries for BB now. + BasicBlock *DeadBB = BlocksToErase[i]; + for (Value::use_iterator UI = DeadBB->use_begin(), UE = DeadBB->use_end(); + UI != UE; ) { + // Grab the user and then increment the iterator early, as the user + // will be deleted. Step past all adjacent uses from the same user. + Instruction *I = dyn_cast(*UI); + do { ++UI; } while (UI != UE && *UI == I); + + // Ignore blockaddress users; BasicBlock's dtor will handle them. + if (!I) continue; + + bool Folded = ConstantFoldTerminator(I->getParent()); + if (!Folded) { + // The constant folder may not have been able to fold the terminator + // if this is a branch or switch on undef. Fold it manually as a + // branch to the first successor. +#ifndef NDEBUG + if (BranchInst *BI = dyn_cast(I)) { + assert(BI->isConditional() && isa(BI->getCondition()) && + "Branch should be foldable!"); + } else if (SwitchInst *SI = dyn_cast(I)) { + assert(isa(SI->getCondition()) && "Switch should fold"); + } else { + llvm_unreachable("Didn't fold away reference to block!"); + } +#endif + + // Make this an uncond branch to the first successor. + TerminatorInst *TI = I->getParent()->getTerminator(); + BranchInst::Create(TI->getSuccessor(0), TI); + + // Remove entries in successor phi nodes to remove edges. + for (unsigned i = 1, e = TI->getNumSuccessors(); i != e; ++i) + TI->getSuccessor(i)->removePredecessor(TI->getParent()); + + // Remove the old terminator. + TI->eraseFromParent(); + } + } + + // Finally, delete the basic block. + F->getBasicBlockList().erase(DeadBB); + } + BlocksToErase.clear(); + } + + // If we inferred constant or undef return values for a function, we replaced + // all call uses with the inferred value. This means we don't need to bother + // actually returning anything from the function. Replace all return + // instructions with return undef. + // TODO: Process multiple value ret instructions also. + const DenseMap &RV = Solver.getTrackedRetVals(); + for (DenseMap::const_iterator I = RV.begin(), + E = RV.end(); I != E; ++I) { + Function *F = I->first; + if (I->second.isOverdefined() || F->getReturnType()->isVoidTy()) + continue; + + // We can only do this if we know that nothing else can call the function. + if (!F->hasLocalLinkage() || AddressIsTaken(F)) + continue; + + for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) + if (ReturnInst *RI = dyn_cast(BB->getTerminator())) + if (!isa(RI->getOperand(0))) + RI->setOperand(0, UndefValue::get(F->getReturnType())); + } + + // If we infered constant or undef values for globals variables, we can delete + // the global and any stores that remain to it. + const DenseMap &TG = Solver.getTrackedGlobals(); + for (DenseMap::const_iterator I = TG.begin(), + E = TG.end(); I != E; ++I) { + GlobalVariable *GV = I->first; + assert(!I->second.isOverdefined() && + "Overdefined values should have been taken out of the map!"); + DEBUG(errs() << "Found that GV '" << GV->getName() << "' is constant!\n"); + while (!GV->use_empty()) { + StoreInst *SI = cast(GV->use_back()); + SI->eraseFromParent(); + } + M.getGlobalList().erase(GV); + ++IPNumGlobalConst; + } + + return MadeChanges; +} diff --git a/libclamav/c++/llvm/lib/Transforms/Scalar/SCCVN.cpp b/libclamav/c++/llvm/lib/Transforms/Scalar/SCCVN.cpp new file mode 100644 index 000000000..001267a7d --- /dev/null +++ b/libclamav/c++/llvm/lib/Transforms/Scalar/SCCVN.cpp @@ -0,0 +1,717 @@ +//===- SCCVN.cpp - Eliminate redundant values -----------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This pass performs global value numbering to eliminate fully redundant +// instructions. This is based on the paper "SCC-based Value Numbering" +// by Cooper, et al. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "sccvn" +#include "llvm/Transforms/Scalar.h" +#include "llvm/BasicBlock.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Function.h" +#include "llvm/LLVMContext.h" +#include "llvm/Operator.h" +#include "llvm/Value.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/DepthFirstIterator.h" +#include "llvm/ADT/PostOrderIterator.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/SparseBitVector.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/Analysis/Dominators.h" +#include "llvm/Support/CFG.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Transforms/Utils/SSAUpdater.h" +#include +using namespace llvm; + +STATISTIC(NumSCCVNInstr, "Number of instructions deleted by SCCVN"); +STATISTIC(NumSCCVNPhi, "Number of phis deleted by SCCVN"); + +//===----------------------------------------------------------------------===// +// ValueTable Class +//===----------------------------------------------------------------------===// + +/// This class holds the mapping between values and value numbers. It is used +/// as an efficient mechanism to determine the expression-wise equivalence of +/// two values. +namespace { + struct Expression { + enum ExpressionOpcode { ADD, FADD, SUB, FSUB, MUL, FMUL, + UDIV, SDIV, FDIV, UREM, SREM, + FREM, SHL, LSHR, ASHR, AND, OR, XOR, ICMPEQ, + ICMPNE, ICMPUGT, ICMPUGE, ICMPULT, ICMPULE, + ICMPSGT, ICMPSGE, ICMPSLT, ICMPSLE, FCMPOEQ, + FCMPOGT, FCMPOGE, FCMPOLT, FCMPOLE, FCMPONE, + FCMPORD, FCMPUNO, FCMPUEQ, FCMPUGT, FCMPUGE, + FCMPULT, FCMPULE, FCMPUNE, EXTRACT, INSERT, + SHUFFLE, SELECT, TRUNC, ZEXT, SEXT, FPTOUI, + FPTOSI, UITOFP, SITOFP, FPTRUNC, FPEXT, + PTRTOINT, INTTOPTR, BITCAST, GEP, CALL, CONSTANT, + INSERTVALUE, EXTRACTVALUE, EMPTY, TOMBSTONE }; + + ExpressionOpcode opcode; + const Type* type; + SmallVector varargs; + + Expression() { } + Expression(ExpressionOpcode o) : opcode(o) { } + + bool operator==(const Expression &other) const { + if (opcode != other.opcode) + return false; + else if (opcode == EMPTY || opcode == TOMBSTONE) + return true; + else if (type != other.type) + return false; + else { + if (varargs.size() != other.varargs.size()) + return false; + + for (size_t i = 0; i < varargs.size(); ++i) + if (varargs[i] != other.varargs[i]) + return false; + + return true; + } + } + + bool operator!=(const Expression &other) const { + return !(*this == other); + } + }; + + class ValueTable { + private: + DenseMap valueNumbering; + DenseMap expressionNumbering; + DenseMap constantsNumbering; + + uint32_t nextValueNumber; + + Expression::ExpressionOpcode getOpcode(BinaryOperator* BO); + Expression::ExpressionOpcode getOpcode(CmpInst* C); + Expression::ExpressionOpcode getOpcode(CastInst* C); + Expression create_expression(BinaryOperator* BO); + Expression create_expression(CmpInst* C); + Expression create_expression(ShuffleVectorInst* V); + Expression create_expression(ExtractElementInst* C); + Expression create_expression(InsertElementInst* V); + Expression create_expression(SelectInst* V); + Expression create_expression(CastInst* C); + Expression create_expression(GetElementPtrInst* G); + Expression create_expression(CallInst* C); + Expression create_expression(Constant* C); + Expression create_expression(ExtractValueInst* C); + Expression create_expression(InsertValueInst* C); + public: + ValueTable() : nextValueNumber(1) { } + uint32_t computeNumber(Value *V); + uint32_t lookup(Value *V); + void add(Value *V, uint32_t num); + void clear(); + void clearExpressions(); + void erase(Value *v); + unsigned size(); + void verifyRemoved(const Value *) const; + }; +} + +namespace llvm { +template <> struct DenseMapInfo { + static inline Expression getEmptyKey() { + return Expression(Expression::EMPTY); + } + + static inline Expression getTombstoneKey() { + return Expression(Expression::TOMBSTONE); + } + + static unsigned getHashValue(const Expression e) { + unsigned hash = e.opcode; + + hash = ((unsigned)((uintptr_t)e.type >> 4) ^ + (unsigned)((uintptr_t)e.type >> 9)); + + for (SmallVector::const_iterator I = e.varargs.begin(), + E = e.varargs.end(); I != E; ++I) + hash = *I + hash * 37; + + return hash; + } + static bool isEqual(const Expression &LHS, const Expression &RHS) { + return LHS == RHS; + } + static bool isPod() { return true; } +}; +} + +//===----------------------------------------------------------------------===// +// ValueTable Internal Functions +//===----------------------------------------------------------------------===// +Expression::ExpressionOpcode ValueTable::getOpcode(BinaryOperator* BO) { + switch(BO->getOpcode()) { + default: // THIS SHOULD NEVER HAPPEN + llvm_unreachable("Binary operator with unknown opcode?"); + case Instruction::Add: return Expression::ADD; + case Instruction::FAdd: return Expression::FADD; + case Instruction::Sub: return Expression::SUB; + case Instruction::FSub: return Expression::FSUB; + case Instruction::Mul: return Expression::MUL; + case Instruction::FMul: return Expression::FMUL; + case Instruction::UDiv: return Expression::UDIV; + case Instruction::SDiv: return Expression::SDIV; + case Instruction::FDiv: return Expression::FDIV; + case Instruction::URem: return Expression::UREM; + case Instruction::SRem: return Expression::SREM; + case Instruction::FRem: return Expression::FREM; + case Instruction::Shl: return Expression::SHL; + case Instruction::LShr: return Expression::LSHR; + case Instruction::AShr: return Expression::ASHR; + case Instruction::And: return Expression::AND; + case Instruction::Or: return Expression::OR; + case Instruction::Xor: return Expression::XOR; + } +} + +Expression::ExpressionOpcode ValueTable::getOpcode(CmpInst* C) { + if (isa(C)) { + switch (C->getPredicate()) { + default: // THIS SHOULD NEVER HAPPEN + llvm_unreachable("Comparison with unknown predicate?"); + case ICmpInst::ICMP_EQ: return Expression::ICMPEQ; + case ICmpInst::ICMP_NE: return Expression::ICMPNE; + case ICmpInst::ICMP_UGT: return Expression::ICMPUGT; + case ICmpInst::ICMP_UGE: return Expression::ICMPUGE; + case ICmpInst::ICMP_ULT: return Expression::ICMPULT; + case ICmpInst::ICMP_ULE: return Expression::ICMPULE; + case ICmpInst::ICMP_SGT: return Expression::ICMPSGT; + case ICmpInst::ICMP_SGE: return Expression::ICMPSGE; + case ICmpInst::ICMP_SLT: return Expression::ICMPSLT; + case ICmpInst::ICMP_SLE: return Expression::ICMPSLE; + } + } else { + switch (C->getPredicate()) { + default: // THIS SHOULD NEVER HAPPEN + llvm_unreachable("Comparison with unknown predicate?"); + case FCmpInst::FCMP_OEQ: return Expression::FCMPOEQ; + case FCmpInst::FCMP_OGT: return Expression::FCMPOGT; + case FCmpInst::FCMP_OGE: return Expression::FCMPOGE; + case FCmpInst::FCMP_OLT: return Expression::FCMPOLT; + case FCmpInst::FCMP_OLE: return Expression::FCMPOLE; + case FCmpInst::FCMP_ONE: return Expression::FCMPONE; + case FCmpInst::FCMP_ORD: return Expression::FCMPORD; + case FCmpInst::FCMP_UNO: return Expression::FCMPUNO; + case FCmpInst::FCMP_UEQ: return Expression::FCMPUEQ; + case FCmpInst::FCMP_UGT: return Expression::FCMPUGT; + case FCmpInst::FCMP_UGE: return Expression::FCMPUGE; + case FCmpInst::FCMP_ULT: return Expression::FCMPULT; + case FCmpInst::FCMP_ULE: return Expression::FCMPULE; + case FCmpInst::FCMP_UNE: return Expression::FCMPUNE; + } + } +} + +Expression::ExpressionOpcode ValueTable::getOpcode(CastInst* C) { + switch(C->getOpcode()) { + default: // THIS SHOULD NEVER HAPPEN + llvm_unreachable("Cast operator with unknown opcode?"); + case Instruction::Trunc: return Expression::TRUNC; + case Instruction::ZExt: return Expression::ZEXT; + case Instruction::SExt: return Expression::SEXT; + case Instruction::FPToUI: return Expression::FPTOUI; + case Instruction::FPToSI: return Expression::FPTOSI; + case Instruction::UIToFP: return Expression::UITOFP; + case Instruction::SIToFP: return Expression::SITOFP; + case Instruction::FPTrunc: return Expression::FPTRUNC; + case Instruction::FPExt: return Expression::FPEXT; + case Instruction::PtrToInt: return Expression::PTRTOINT; + case Instruction::IntToPtr: return Expression::INTTOPTR; + case Instruction::BitCast: return Expression::BITCAST; + } +} + +Expression ValueTable::create_expression(CallInst* C) { + Expression e; + + e.type = C->getType(); + e.opcode = Expression::CALL; + + e.varargs.push_back(lookup(C->getCalledFunction())); + for (CallInst::op_iterator I = C->op_begin()+1, E = C->op_end(); + I != E; ++I) + e.varargs.push_back(lookup(*I)); + + return e; +} + +Expression ValueTable::create_expression(BinaryOperator* BO) { + Expression e; + e.varargs.push_back(lookup(BO->getOperand(0))); + e.varargs.push_back(lookup(BO->getOperand(1))); + e.type = BO->getType(); + e.opcode = getOpcode(BO); + + return e; +} + +Expression ValueTable::create_expression(CmpInst* C) { + Expression e; + + e.varargs.push_back(lookup(C->getOperand(0))); + e.varargs.push_back(lookup(C->getOperand(1))); + e.type = C->getType(); + e.opcode = getOpcode(C); + + return e; +} + +Expression ValueTable::create_expression(CastInst* C) { + Expression e; + + e.varargs.push_back(lookup(C->getOperand(0))); + e.type = C->getType(); + e.opcode = getOpcode(C); + + return e; +} + +Expression ValueTable::create_expression(ShuffleVectorInst* S) { + Expression e; + + e.varargs.push_back(lookup(S->getOperand(0))); + e.varargs.push_back(lookup(S->getOperand(1))); + e.varargs.push_back(lookup(S->getOperand(2))); + e.type = S->getType(); + e.opcode = Expression::SHUFFLE; + + return e; +} + +Expression ValueTable::create_expression(ExtractElementInst* E) { + Expression e; + + e.varargs.push_back(lookup(E->getOperand(0))); + e.varargs.push_back(lookup(E->getOperand(1))); + e.type = E->getType(); + e.opcode = Expression::EXTRACT; + + return e; +} + +Expression ValueTable::create_expression(InsertElementInst* I) { + Expression e; + + e.varargs.push_back(lookup(I->getOperand(0))); + e.varargs.push_back(lookup(I->getOperand(1))); + e.varargs.push_back(lookup(I->getOperand(2))); + e.type = I->getType(); + e.opcode = Expression::INSERT; + + return e; +} + +Expression ValueTable::create_expression(SelectInst* I) { + Expression e; + + e.varargs.push_back(lookup(I->getCondition())); + e.varargs.push_back(lookup(I->getTrueValue())); + e.varargs.push_back(lookup(I->getFalseValue())); + e.type = I->getType(); + e.opcode = Expression::SELECT; + + return e; +} + +Expression ValueTable::create_expression(GetElementPtrInst* G) { + Expression e; + + e.varargs.push_back(lookup(G->getPointerOperand())); + e.type = G->getType(); + e.opcode = Expression::GEP; + + for (GetElementPtrInst::op_iterator I = G->idx_begin(), E = G->idx_end(); + I != E; ++I) + e.varargs.push_back(lookup(*I)); + + return e; +} + +Expression ValueTable::create_expression(ExtractValueInst* E) { + Expression e; + + e.varargs.push_back(lookup(E->getAggregateOperand())); + for (ExtractValueInst::idx_iterator II = E->idx_begin(), IE = E->idx_end(); + II != IE; ++II) + e.varargs.push_back(*II); + e.type = E->getType(); + e.opcode = Expression::EXTRACTVALUE; + + return e; +} + +Expression ValueTable::create_expression(InsertValueInst* E) { + Expression e; + + e.varargs.push_back(lookup(E->getAggregateOperand())); + e.varargs.push_back(lookup(E->getInsertedValueOperand())); + for (InsertValueInst::idx_iterator II = E->idx_begin(), IE = E->idx_end(); + II != IE; ++II) + e.varargs.push_back(*II); + e.type = E->getType(); + e.opcode = Expression::INSERTVALUE; + + return e; +} + +//===----------------------------------------------------------------------===// +// ValueTable External Functions +//===----------------------------------------------------------------------===// + +/// add - Insert a value into the table with a specified value number. +void ValueTable::add(Value *V, uint32_t num) { + valueNumbering[V] = num; +} + +/// computeNumber - Returns the value number for the specified value, assigning +/// it a new number if it did not have one before. +uint32_t ValueTable::computeNumber(Value *V) { + if (uint32_t v = valueNumbering[V]) + return v; + else if (uint32_t v= constantsNumbering[V]) + return v; + + if (!isa(V)) { + constantsNumbering[V] = nextValueNumber; + return nextValueNumber++; + } + + Instruction* I = cast(V); + Expression exp; + switch (I->getOpcode()) { + case Instruction::Add: + case Instruction::FAdd: + case Instruction::Sub: + case Instruction::FSub: + case Instruction::Mul: + case Instruction::FMul: + case Instruction::UDiv: + case Instruction::SDiv: + case Instruction::FDiv: + case Instruction::URem: + case Instruction::SRem: + case Instruction::FRem: + case Instruction::Shl: + case Instruction::LShr: + case Instruction::AShr: + case Instruction::And: + case Instruction::Or : + case Instruction::Xor: + exp = create_expression(cast(I)); + break; + case Instruction::ICmp: + case Instruction::FCmp: + exp = create_expression(cast(I)); + break; + case Instruction::Trunc: + case Instruction::ZExt: + case Instruction::SExt: + case Instruction::FPToUI: + case Instruction::FPToSI: + case Instruction::UIToFP: + case Instruction::SIToFP: + case Instruction::FPTrunc: + case Instruction::FPExt: + case Instruction::PtrToInt: + case Instruction::IntToPtr: + case Instruction::BitCast: + exp = create_expression(cast(I)); + break; + case Instruction::Select: + exp = create_expression(cast(I)); + break; + case Instruction::ExtractElement: + exp = create_expression(cast(I)); + break; + case Instruction::InsertElement: + exp = create_expression(cast(I)); + break; + case Instruction::ShuffleVector: + exp = create_expression(cast(I)); + break; + case Instruction::ExtractValue: + exp = create_expression(cast(I)); + break; + case Instruction::InsertValue: + exp = create_expression(cast(I)); + break; + case Instruction::GetElementPtr: + exp = create_expression(cast(I)); + break; + default: + valueNumbering[V] = nextValueNumber; + return nextValueNumber++; + } + + uint32_t& e = expressionNumbering[exp]; + if (!e) e = nextValueNumber++; + valueNumbering[V] = e; + + return e; +} + +/// lookup - Returns the value number of the specified value. Returns 0 if +/// the value has not yet been numbered. +uint32_t ValueTable::lookup(Value *V) { + if (!isa(V)) { + if (!constantsNumbering.count(V)) + constantsNumbering[V] = nextValueNumber++; + return constantsNumbering[V]; + } + + return valueNumbering[V]; +} + +/// clear - Remove all entries from the ValueTable +void ValueTable::clear() { + valueNumbering.clear(); + expressionNumbering.clear(); + constantsNumbering.clear(); + nextValueNumber = 1; +} + +void ValueTable::clearExpressions() { + expressionNumbering.clear(); + constantsNumbering.clear(); + nextValueNumber = 1; +} + +/// erase - Remove a value from the value numbering +void ValueTable::erase(Value *V) { + valueNumbering.erase(V); +} + +/// verifyRemoved - Verify that the value is removed from all internal data +/// structures. +void ValueTable::verifyRemoved(const Value *V) const { + for (DenseMap::const_iterator + I = valueNumbering.begin(), E = valueNumbering.end(); I != E; ++I) { + assert(I->first != V && "Inst still occurs in value numbering map!"); + } +} + +//===----------------------------------------------------------------------===// +// SCCVN Pass +//===----------------------------------------------------------------------===// + +namespace { + + struct ValueNumberScope { + ValueNumberScope* parent; + DenseMap table; + SparseBitVector<128> availIn; + SparseBitVector<128> availOut; + + ValueNumberScope(ValueNumberScope* p) : parent(p) { } + }; + + class SCCVN : public FunctionPass { + bool runOnFunction(Function &F); + public: + static char ID; // Pass identification, replacement for typeid + SCCVN() : FunctionPass(&ID) { } + + private: + ValueTable VT; + DenseMap BBMap; + + // This transformation requires dominator postdominator info + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.addRequired(); + + AU.addPreserved(); + AU.setPreservesCFG(); + } + }; + + char SCCVN::ID = 0; +} + +// createSCCVNPass - The public interface to this file... +FunctionPass *llvm::createSCCVNPass() { return new SCCVN(); } + +static RegisterPass X("sccvn", + "SCC Value Numbering"); + +static Value *lookupNumber(ValueNumberScope *Locals, uint32_t num) { + while (Locals) { + DenseMap::iterator I = Locals->table.find(num); + if (I != Locals->table.end()) + return I->second; + Locals = Locals->parent; + } + + return 0; +} + +bool SCCVN::runOnFunction(Function& F) { + // Implement the RPO version of the SCCVN algorithm. Conceptually, + // we optimisitically assume that all instructions with the same opcode have + // the same VN. Then we deepen our comparison by one level, to all + // instructions whose operands have the same opcodes get the same VN. We + // iterate this process until the partitioning stops changing, at which + // point we have computed a full numbering. + ReversePostOrderTraversal RPOT(&F); + bool done = false; + while (!done) { + done = true; + VT.clearExpressions(); + for (ReversePostOrderTraversal::rpo_iterator I = RPOT.begin(), + E = RPOT.end(); I != E; ++I) { + BasicBlock* BB = *I; + for (BasicBlock::iterator BI = BB->begin(), BE = BB->end(); + BI != BE; ++BI) { + uint32_t origVN = VT.lookup(BI); + uint32_t newVN = VT.computeNumber(BI); + if (origVN != newVN) + done = false; + } + } + } + + // Now, do a dominator walk, eliminating simple, dominated redundancies as we + // go. Also, build the ValueNumberScope structure that will be used for + // computing full availability. + DominatorTree& DT = getAnalysis(); + bool changed = false; + for (df_iterator DI = df_begin(DT.getRootNode()), + DE = df_end(DT.getRootNode()); DI != DE; ++DI) { + BasicBlock* BB = DI->getBlock(); + if (DI->getIDom()) + BBMap[BB] = new ValueNumberScope(BBMap[DI->getIDom()->getBlock()]); + else + BBMap[BB] = new ValueNumberScope(0); + + for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ) { + uint32_t num = VT.lookup(I); + Value* repl = lookupNumber(BBMap[BB], num); + + if (repl) { + if (isa(I)) + ++NumSCCVNPhi; + else + ++NumSCCVNInstr; + I->replaceAllUsesWith(repl); + Instruction* OldInst = I; + ++I; + BBMap[BB]->table[num] = repl; + OldInst->eraseFromParent(); + changed = true; + } else { + BBMap[BB]->table[num] = I; + BBMap[BB]->availOut.set(num); + + ++I; + } + } + } + + // Perform a forward data-flow to compute availability at all points on + // the CFG. + do { + changed = false; + for (ReversePostOrderTraversal::rpo_iterator I = RPOT.begin(), + E = RPOT.end(); I != E; ++I) { + BasicBlock* BB = *I; + ValueNumberScope *VNS = BBMap[BB]; + + SparseBitVector<128> preds; + bool first = true; + for (pred_iterator PI = pred_begin(BB), PE = pred_end(BB); + PI != PE; ++PI) { + if (first) { + preds = BBMap[*PI]->availOut; + first = false; + } else { + preds &= BBMap[*PI]->availOut; + } + } + + changed |= (VNS->availIn |= preds); + changed |= (VNS->availOut |= preds); + } + } while (changed); + + // Use full availability information to perform non-dominated replacements. + SSAUpdater SSU; + for (Function::iterator FI = F.begin(), FE = F.end(); FI != FE; ++FI) { + if (!BBMap.count(FI)) continue; + for (BasicBlock::iterator BI = FI->begin(), BE = FI->end(); + BI != BE; ) { + uint32_t num = VT.lookup(BI); + if (!BBMap[FI]->availIn.test(num)) { + ++BI; + continue; + } + + SSU.Initialize(BI); + + SmallPtrSet visited; + SmallVector stack; + visited.insert(FI); + for (pred_iterator PI = pred_begin(FI), PE = pred_end(FI); + PI != PE; ++PI) + if (!visited.count(*PI)) + stack.push_back(*PI); + + while (!stack.empty()) { + BasicBlock* CurrBB = stack.back(); + stack.pop_back(); + visited.insert(CurrBB); + + ValueNumberScope* S = BBMap[CurrBB]; + if (S->table.count(num)) { + SSU.AddAvailableValue(CurrBB, S->table[num]); + } else { + for (pred_iterator PI = pred_begin(CurrBB), PE = pred_end(CurrBB); + PI != PE; ++PI) + if (!visited.count(*PI)) + stack.push_back(*PI); + } + } + + Value* repl = SSU.GetValueInMiddleOfBlock(FI); + BI->replaceAllUsesWith(repl); + Instruction* CurInst = BI; + ++BI; + BBMap[FI]->table[num] = repl; + if (isa(CurInst)) + ++NumSCCVNPhi; + else + ++NumSCCVNInstr; + + CurInst->eraseFromParent(); + } + } + + VT.clear(); + for (DenseMap::iterator + I = BBMap.begin(), E = BBMap.end(); I != E; ++I) + delete I->second; + BBMap.clear(); + + return changed; +} diff --git a/libclamav/c++/llvm/lib/Transforms/Scalar/Scalar.cpp b/libclamav/c++/llvm/lib/Transforms/Scalar/Scalar.cpp new file mode 100644 index 000000000..b54565cb8 --- /dev/null +++ b/libclamav/c++/llvm/lib/Transforms/Scalar/Scalar.cpp @@ -0,0 +1,107 @@ +//===-- Scalar.cpp --------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the C bindings for libLLVMScalarOpts.a, which implements +// several scalar transformations over the LLVM intermediate representation. +// +//===----------------------------------------------------------------------===// + +#include "llvm-c/Transforms/Scalar.h" +#include "llvm/PassManager.h" +#include "llvm/Transforms/Scalar.h" + +using namespace llvm; + +void LLVMAddAggressiveDCEPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(createAggressiveDCEPass()); +} + +void LLVMAddCFGSimplificationPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(createCFGSimplificationPass()); +} + +void LLVMAddDeadStoreEliminationPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(createDeadStoreEliminationPass()); +} + +void LLVMAddGVNPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(createGVNPass()); +} + +void LLVMAddIndVarSimplifyPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(createIndVarSimplifyPass()); +} + +void LLVMAddInstructionCombiningPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(createInstructionCombiningPass()); +} + +void LLVMAddJumpThreadingPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(createJumpThreadingPass()); +} + +void LLVMAddLICMPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(createLICMPass()); +} + +void LLVMAddLoopDeletionPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(createLoopDeletionPass()); +} + +void LLVMAddLoopIndexSplitPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(createLoopIndexSplitPass()); +} + +void LLVMAddLoopRotatePass(LLVMPassManagerRef PM) { + unwrap(PM)->add(createLoopRotatePass()); +} + +void LLVMAddLoopUnrollPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(createLoopUnrollPass()); +} + +void LLVMAddLoopUnswitchPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(createLoopUnswitchPass()); +} + +void LLVMAddMemCpyOptPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(createMemCpyOptPass()); +} + +void LLVMAddPromoteMemoryToRegisterPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(createPromoteMemoryToRegisterPass()); +} + +void LLVMAddReassociatePass(LLVMPassManagerRef PM) { + unwrap(PM)->add(createReassociatePass()); +} + +void LLVMAddSCCPPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(createSCCPPass()); +} + +void LLVMAddScalarReplAggregatesPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(createScalarReplAggregatesPass()); +} + +void LLVMAddSimplifyLibCallsPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(createSimplifyLibCallsPass()); +} + +void LLVMAddTailCallEliminationPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(createTailCallEliminationPass()); +} + +void LLVMAddConstantPropagationPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(createConstantPropagationPass()); +} + +void LLVMAddDemoteMemoryToRegisterPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(createDemoteRegisterToMemoryPass()); +} diff --git a/libclamav/c++/llvm/lib/Transforms/Scalar/ScalarReplAggregates.cpp b/libclamav/c++/llvm/lib/Transforms/Scalar/ScalarReplAggregates.cpp new file mode 100644 index 000000000..047d279e8 --- /dev/null +++ b/libclamav/c++/llvm/lib/Transforms/Scalar/ScalarReplAggregates.cpp @@ -0,0 +1,1860 @@ +//===- ScalarReplAggregates.cpp - Scalar Replacement of Aggregates --------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This transformation implements the well known scalar replacement of +// aggregates transformation. This xform breaks up alloca instructions of +// aggregate type (structure or array) into individual alloca instructions for +// each member (if possible). Then, if possible, it transforms the individual +// alloca instructions into nice clean scalar SSA form. +// +// This combines a simple SRoA algorithm with the Mem2Reg algorithm because +// often interact, especially for C++ programs. As such, iterating between +// SRoA, then Mem2Reg until we run out of things to promote works well. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "scalarrepl" +#include "llvm/Transforms/Scalar.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Function.h" +#include "llvm/GlobalVariable.h" +#include "llvm/Instructions.h" +#include "llvm/IntrinsicInst.h" +#include "llvm/LLVMContext.h" +#include "llvm/Pass.h" +#include "llvm/Analysis/Dominators.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Transforms/Utils/PromoteMemToReg.h" +#include "llvm/Transforms/Utils/Local.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/GetElementPtrTypeIterator.h" +#include "llvm/Support/IRBuilder.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/Statistic.h" +using namespace llvm; + +STATISTIC(NumReplaced, "Number of allocas broken up"); +STATISTIC(NumPromoted, "Number of allocas promoted"); +STATISTIC(NumConverted, "Number of aggregates converted to scalar"); +STATISTIC(NumGlobals, "Number of allocas copied from constant global"); + +namespace { + struct SROA : public FunctionPass { + static char ID; // Pass identification, replacement for typeid + explicit SROA(signed T = -1) : FunctionPass(&ID) { + if (T == -1) + SRThreshold = 128; + else + SRThreshold = T; + } + + bool runOnFunction(Function &F); + + bool performScalarRepl(Function &F); + bool performPromotion(Function &F); + + // getAnalysisUsage - This pass does not require any passes, but we know it + // will not alter the CFG, so say so. + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.addRequired(); + AU.addRequired(); + AU.setPreservesCFG(); + } + + private: + TargetData *TD; + + /// AllocaInfo - When analyzing uses of an alloca instruction, this captures + /// information about the uses. All these fields are initialized to false + /// and set to true when something is learned. + struct AllocaInfo { + /// isUnsafe - This is set to true if the alloca cannot be SROA'd. + bool isUnsafe : 1; + + /// needsCleanup - This is set to true if there is some use of the alloca + /// that requires cleanup. + bool needsCleanup : 1; + + /// isMemCpySrc - This is true if this aggregate is memcpy'd from. + bool isMemCpySrc : 1; + + /// isMemCpyDst - This is true if this aggregate is memcpy'd into. + bool isMemCpyDst : 1; + + AllocaInfo() + : isUnsafe(false), needsCleanup(false), + isMemCpySrc(false), isMemCpyDst(false) {} + }; + + unsigned SRThreshold; + + void MarkUnsafe(AllocaInfo &I) { I.isUnsafe = true; } + + int isSafeAllocaToScalarRepl(AllocaInst *AI); + + void isSafeUseOfAllocation(Instruction *User, AllocaInst *AI, + AllocaInfo &Info); + void isSafeElementUse(Value *Ptr, bool isFirstElt, AllocaInst *AI, + AllocaInfo &Info); + void isSafeMemIntrinsicOnAllocation(MemIntrinsic *MI, AllocaInst *AI, + unsigned OpNo, AllocaInfo &Info); + void isSafeUseOfBitCastedAllocation(BitCastInst *User, AllocaInst *AI, + AllocaInfo &Info); + + void DoScalarReplacement(AllocaInst *AI, + std::vector &WorkList); + void CleanupGEP(GetElementPtrInst *GEP); + void CleanupAllocaUsers(AllocaInst *AI); + AllocaInst *AddNewAlloca(Function &F, const Type *Ty, AllocaInst *Base); + + void RewriteBitCastUserOfAlloca(Instruction *BCInst, AllocaInst *AI, + SmallVector &NewElts); + + void RewriteMemIntrinUserOfAlloca(MemIntrinsic *MI, Instruction *BCInst, + AllocaInst *AI, + SmallVector &NewElts); + void RewriteStoreUserOfWholeAlloca(StoreInst *SI, AllocaInst *AI, + SmallVector &NewElts); + void RewriteLoadUserOfWholeAlloca(LoadInst *LI, AllocaInst *AI, + SmallVector &NewElts); + + bool CanConvertToScalar(Value *V, bool &IsNotTrivial, const Type *&VecTy, + bool &SawVec, uint64_t Offset, unsigned AllocaSize); + void ConvertUsesToScalar(Value *Ptr, AllocaInst *NewAI, uint64_t Offset); + Value *ConvertScalar_ExtractValue(Value *NV, const Type *ToType, + uint64_t Offset, IRBuilder<> &Builder); + Value *ConvertScalar_InsertValue(Value *StoredVal, Value *ExistingVal, + uint64_t Offset, IRBuilder<> &Builder); + static Instruction *isOnlyCopiedFromConstantGlobal(AllocaInst *AI); + }; +} + +char SROA::ID = 0; +static RegisterPass X("scalarrepl", "Scalar Replacement of Aggregates"); + +// Public interface to the ScalarReplAggregates pass +FunctionPass *llvm::createScalarReplAggregatesPass(signed int Threshold) { + return new SROA(Threshold); +} + + +bool SROA::runOnFunction(Function &F) { + TD = getAnalysisIfAvailable(); + + bool Changed = performPromotion(F); + + // FIXME: ScalarRepl currently depends on TargetData more than it + // theoretically needs to. It should be refactored in order to support + // target-independent IR. Until this is done, just skip the actual + // scalar-replacement portion of this pass. + if (!TD) return Changed; + + while (1) { + bool LocalChange = performScalarRepl(F); + if (!LocalChange) break; // No need to repromote if no scalarrepl + Changed = true; + LocalChange = performPromotion(F); + if (!LocalChange) break; // No need to re-scalarrepl if no promotion + } + + return Changed; +} + + +bool SROA::performPromotion(Function &F) { + std::vector Allocas; + DominatorTree &DT = getAnalysis(); + DominanceFrontier &DF = getAnalysis(); + + BasicBlock &BB = F.getEntryBlock(); // Get the entry node for the function + + bool Changed = false; + + while (1) { + Allocas.clear(); + + // Find allocas that are safe to promote, by looking at all instructions in + // the entry node + for (BasicBlock::iterator I = BB.begin(), E = --BB.end(); I != E; ++I) + if (AllocaInst *AI = dyn_cast(I)) // Is it an alloca? + if (isAllocaPromotable(AI)) + Allocas.push_back(AI); + + if (Allocas.empty()) break; + + PromoteMemToReg(Allocas, DT, DF); + NumPromoted += Allocas.size(); + Changed = true; + } + + return Changed; +} + +/// getNumSAElements - Return the number of elements in the specific struct or +/// array. +static uint64_t getNumSAElements(const Type *T) { + if (const StructType *ST = dyn_cast(T)) + return ST->getNumElements(); + return cast(T)->getNumElements(); +} + +// performScalarRepl - This algorithm is a simple worklist driven algorithm, +// which runs on all of the malloc/alloca instructions in the function, removing +// them if they are only used by getelementptr instructions. +// +bool SROA::performScalarRepl(Function &F) { + std::vector WorkList; + + // Scan the entry basic block, adding any alloca's and mallocs to the worklist + BasicBlock &BB = F.getEntryBlock(); + for (BasicBlock::iterator I = BB.begin(), E = BB.end(); I != E; ++I) + if (AllocaInst *A = dyn_cast(I)) + WorkList.push_back(A); + + // Process the worklist + bool Changed = false; + while (!WorkList.empty()) { + AllocaInst *AI = WorkList.back(); + WorkList.pop_back(); + + // Handle dead allocas trivially. These can be formed by SROA'ing arrays + // with unused elements. + if (AI->use_empty()) { + AI->eraseFromParent(); + continue; + } + + // If this alloca is impossible for us to promote, reject it early. + if (AI->isArrayAllocation() || !AI->getAllocatedType()->isSized()) + continue; + + // Check to see if this allocation is only modified by a memcpy/memmove from + // a constant global. If this is the case, we can change all users to use + // the constant global instead. This is commonly produced by the CFE by + // constructs like "void foo() { int A[] = {1,2,3,4,5,6,7,8,9...}; }" if 'A' + // is only subsequently read. + if (Instruction *TheCopy = isOnlyCopiedFromConstantGlobal(AI)) { + DEBUG(errs() << "Found alloca equal to global: " << *AI << '\n'); + DEBUG(errs() << " memcpy = " << *TheCopy << '\n'); + Constant *TheSrc = cast(TheCopy->getOperand(2)); + AI->replaceAllUsesWith(ConstantExpr::getBitCast(TheSrc, AI->getType())); + TheCopy->eraseFromParent(); // Don't mutate the global. + AI->eraseFromParent(); + ++NumGlobals; + Changed = true; + continue; + } + + // Check to see if we can perform the core SROA transformation. We cannot + // transform the allocation instruction if it is an array allocation + // (allocations OF arrays are ok though), and an allocation of a scalar + // value cannot be decomposed at all. + uint64_t AllocaSize = TD->getTypeAllocSize(AI->getAllocatedType()); + + // Do not promote [0 x %struct]. + if (AllocaSize == 0) continue; + + // Do not promote any struct whose size is too big. + if (AllocaSize > SRThreshold) continue; + + if ((isa(AI->getAllocatedType()) || + isa(AI->getAllocatedType())) && + // Do not promote any struct into more than "32" separate vars. + getNumSAElements(AI->getAllocatedType()) <= SRThreshold/4) { + // Check that all of the users of the allocation are capable of being + // transformed. + switch (isSafeAllocaToScalarRepl(AI)) { + default: llvm_unreachable("Unexpected value!"); + case 0: // Not safe to scalar replace. + break; + case 1: // Safe, but requires cleanup/canonicalizations first + CleanupAllocaUsers(AI); + // FALL THROUGH. + case 3: // Safe to scalar replace. + DoScalarReplacement(AI, WorkList); + Changed = true; + continue; + } + } + + // If we can turn this aggregate value (potentially with casts) into a + // simple scalar value that can be mem2reg'd into a register value. + // IsNotTrivial tracks whether this is something that mem2reg could have + // promoted itself. If so, we don't want to transform it needlessly. Note + // that we can't just check based on the type: the alloca may be of an i32 + // but that has pointer arithmetic to set byte 3 of it or something. + bool IsNotTrivial = false; + const Type *VectorTy = 0; + bool HadAVector = false; + if (CanConvertToScalar(AI, IsNotTrivial, VectorTy, HadAVector, + 0, unsigned(AllocaSize)) && IsNotTrivial) { + AllocaInst *NewAI; + // If we were able to find a vector type that can handle this with + // insert/extract elements, and if there was at least one use that had + // a vector type, promote this to a vector. We don't want to promote + // random stuff that doesn't use vectors (e.g. <9 x double>) because then + // we just get a lot of insert/extracts. If at least one vector is + // involved, then we probably really do have a union of vector/array. + if (VectorTy && isa(VectorTy) && HadAVector) { + DEBUG(errs() << "CONVERT TO VECTOR: " << *AI << "\n TYPE = " + << *VectorTy << '\n'); + + // Create and insert the vector alloca. + NewAI = new AllocaInst(VectorTy, 0, "", AI->getParent()->begin()); + ConvertUsesToScalar(AI, NewAI, 0); + } else { + DEBUG(errs() << "CONVERT TO SCALAR INTEGER: " << *AI << "\n"); + + // Create and insert the integer alloca. + const Type *NewTy = IntegerType::get(AI->getContext(), AllocaSize*8); + NewAI = new AllocaInst(NewTy, 0, "", AI->getParent()->begin()); + ConvertUsesToScalar(AI, NewAI, 0); + } + NewAI->takeName(AI); + AI->eraseFromParent(); + ++NumConverted; + Changed = true; + continue; + } + + // Otherwise, couldn't process this alloca. + } + + return Changed; +} + +/// DoScalarReplacement - This alloca satisfied the isSafeAllocaToScalarRepl +/// predicate, do SROA now. +void SROA::DoScalarReplacement(AllocaInst *AI, + std::vector &WorkList) { + DEBUG(errs() << "Found inst to SROA: " << *AI << '\n'); + SmallVector ElementAllocas; + if (const StructType *ST = dyn_cast(AI->getAllocatedType())) { + ElementAllocas.reserve(ST->getNumContainedTypes()); + for (unsigned i = 0, e = ST->getNumContainedTypes(); i != e; ++i) { + AllocaInst *NA = new AllocaInst(ST->getContainedType(i), 0, + AI->getAlignment(), + AI->getName() + "." + Twine(i), AI); + ElementAllocas.push_back(NA); + WorkList.push_back(NA); // Add to worklist for recursive processing + } + } else { + const ArrayType *AT = cast(AI->getAllocatedType()); + ElementAllocas.reserve(AT->getNumElements()); + const Type *ElTy = AT->getElementType(); + for (unsigned i = 0, e = AT->getNumElements(); i != e; ++i) { + AllocaInst *NA = new AllocaInst(ElTy, 0, AI->getAlignment(), + AI->getName() + "." + Twine(i), AI); + ElementAllocas.push_back(NA); + WorkList.push_back(NA); // Add to worklist for recursive processing + } + } + + // Now that we have created the alloca instructions that we want to use, + // expand the getelementptr instructions to use them. + // + while (!AI->use_empty()) { + Instruction *User = cast(AI->use_back()); + if (BitCastInst *BCInst = dyn_cast(User)) { + RewriteBitCastUserOfAlloca(BCInst, AI, ElementAllocas); + BCInst->eraseFromParent(); + continue; + } + + // Replace: + // %res = load { i32, i32 }* %alloc + // with: + // %load.0 = load i32* %alloc.0 + // %insert.0 insertvalue { i32, i32 } zeroinitializer, i32 %load.0, 0 + // %load.1 = load i32* %alloc.1 + // %insert = insertvalue { i32, i32 } %insert.0, i32 %load.1, 1 + // (Also works for arrays instead of structs) + if (LoadInst *LI = dyn_cast(User)) { + Value *Insert = UndefValue::get(LI->getType()); + for (unsigned i = 0, e = ElementAllocas.size(); i != e; ++i) { + Value *Load = new LoadInst(ElementAllocas[i], "load", LI); + Insert = InsertValueInst::Create(Insert, Load, i, "insert", LI); + } + LI->replaceAllUsesWith(Insert); + LI->eraseFromParent(); + continue; + } + + // Replace: + // store { i32, i32 } %val, { i32, i32 }* %alloc + // with: + // %val.0 = extractvalue { i32, i32 } %val, 0 + // store i32 %val.0, i32* %alloc.0 + // %val.1 = extractvalue { i32, i32 } %val, 1 + // store i32 %val.1, i32* %alloc.1 + // (Also works for arrays instead of structs) + if (StoreInst *SI = dyn_cast(User)) { + Value *Val = SI->getOperand(0); + for (unsigned i = 0, e = ElementAllocas.size(); i != e; ++i) { + Value *Extract = ExtractValueInst::Create(Val, i, Val->getName(), SI); + new StoreInst(Extract, ElementAllocas[i], SI); + } + SI->eraseFromParent(); + continue; + } + + GetElementPtrInst *GEPI = cast(User); + // We now know that the GEP is of the form: GEP , 0, + unsigned Idx = + (unsigned)cast(GEPI->getOperand(2))->getZExtValue(); + + assert(Idx < ElementAllocas.size() && "Index out of range?"); + AllocaInst *AllocaToUse = ElementAllocas[Idx]; + + Value *RepValue; + if (GEPI->getNumOperands() == 3) { + // Do not insert a new getelementptr instruction with zero indices, only + // to have it optimized out later. + RepValue = AllocaToUse; + } else { + // We are indexing deeply into the structure, so we still need a + // getelement ptr instruction to finish the indexing. This may be + // expanded itself once the worklist is rerun. + // + SmallVector NewArgs; + NewArgs.push_back(Constant::getNullValue( + Type::getInt32Ty(AI->getContext()))); + NewArgs.append(GEPI->op_begin()+3, GEPI->op_end()); + RepValue = GetElementPtrInst::Create(AllocaToUse, NewArgs.begin(), + NewArgs.end(), "", GEPI); + RepValue->takeName(GEPI); + } + + // If this GEP is to the start of the aggregate, check for memcpys. + if (Idx == 0 && GEPI->hasAllZeroIndices()) + RewriteBitCastUserOfAlloca(GEPI, AI, ElementAllocas); + + // Move all of the users over to the new GEP. + GEPI->replaceAllUsesWith(RepValue); + // Delete the old GEP + GEPI->eraseFromParent(); + } + + // Finally, delete the Alloca instruction + AI->eraseFromParent(); + NumReplaced++; +} + + +/// isSafeElementUse - Check to see if this use is an allowed use for a +/// getelementptr instruction of an array aggregate allocation. isFirstElt +/// indicates whether Ptr is known to the start of the aggregate. +/// +void SROA::isSafeElementUse(Value *Ptr, bool isFirstElt, AllocaInst *AI, + AllocaInfo &Info) { + for (Value::use_iterator I = Ptr->use_begin(), E = Ptr->use_end(); + I != E; ++I) { + Instruction *User = cast(*I); + switch (User->getOpcode()) { + case Instruction::Load: break; + case Instruction::Store: + // Store is ok if storing INTO the pointer, not storing the pointer + if (User->getOperand(0) == Ptr) return MarkUnsafe(Info); + break; + case Instruction::GetElementPtr: { + GetElementPtrInst *GEP = cast(User); + bool AreAllZeroIndices = isFirstElt; + if (GEP->getNumOperands() > 1) { + if (!isa(GEP->getOperand(1)) || + !cast(GEP->getOperand(1))->isZero()) + // Using pointer arithmetic to navigate the array. + return MarkUnsafe(Info); + + if (AreAllZeroIndices) + AreAllZeroIndices = GEP->hasAllZeroIndices(); + } + isSafeElementUse(GEP, AreAllZeroIndices, AI, Info); + if (Info.isUnsafe) return; + break; + } + case Instruction::BitCast: + if (isFirstElt) { + isSafeUseOfBitCastedAllocation(cast(User), AI, Info); + if (Info.isUnsafe) return; + break; + } + DEBUG(errs() << " Transformation preventing inst: " << *User << '\n'); + return MarkUnsafe(Info); + case Instruction::Call: + if (MemIntrinsic *MI = dyn_cast(User)) { + if (isFirstElt) { + isSafeMemIntrinsicOnAllocation(MI, AI, I.getOperandNo(), Info); + if (Info.isUnsafe) return; + break; + } + } + DEBUG(errs() << " Transformation preventing inst: " << *User << '\n'); + return MarkUnsafe(Info); + default: + DEBUG(errs() << " Transformation preventing inst: " << *User << '\n'); + return MarkUnsafe(Info); + } + } + return; // All users look ok :) +} + +/// AllUsersAreLoads - Return true if all users of this value are loads. +static bool AllUsersAreLoads(Value *Ptr) { + for (Value::use_iterator I = Ptr->use_begin(), E = Ptr->use_end(); + I != E; ++I) + if (cast(*I)->getOpcode() != Instruction::Load) + return false; + return true; +} + +/// isSafeUseOfAllocation - Check to see if this user is an allowed use for an +/// aggregate allocation. +/// +void SROA::isSafeUseOfAllocation(Instruction *User, AllocaInst *AI, + AllocaInfo &Info) { + if (BitCastInst *C = dyn_cast(User)) + return isSafeUseOfBitCastedAllocation(C, AI, Info); + + if (LoadInst *LI = dyn_cast(User)) + if (!LI->isVolatile()) + return;// Loads (returning a first class aggregrate) are always rewritable + + if (StoreInst *SI = dyn_cast(User)) + if (!SI->isVolatile() && SI->getOperand(0) != AI) + return;// Store is ok if storing INTO the pointer, not storing the pointer + + GetElementPtrInst *GEPI = dyn_cast(User); + if (GEPI == 0) + return MarkUnsafe(Info); + + gep_type_iterator I = gep_type_begin(GEPI), E = gep_type_end(GEPI); + + // The GEP is not safe to transform if not of the form "GEP , 0, ". + if (I == E || + I.getOperand() != Constant::getNullValue(I.getOperand()->getType())) { + return MarkUnsafe(Info); + } + + ++I; + if (I == E) return MarkUnsafe(Info); // ran out of GEP indices?? + + bool IsAllZeroIndices = true; + + // If the first index is a non-constant index into an array, see if we can + // handle it as a special case. + if (const ArrayType *AT = dyn_cast(*I)) { + if (!isa(I.getOperand())) { + IsAllZeroIndices = 0; + uint64_t NumElements = AT->getNumElements(); + + // If this is an array index and the index is not constant, we cannot + // promote... that is unless the array has exactly one or two elements in + // it, in which case we CAN promote it, but we have to canonicalize this + // out if this is the only problem. + if ((NumElements == 1 || NumElements == 2) && + AllUsersAreLoads(GEPI)) { + Info.needsCleanup = true; + return; // Canonicalization required! + } + return MarkUnsafe(Info); + } + } + + // Walk through the GEP type indices, checking the types that this indexes + // into. + for (; I != E; ++I) { + // Ignore struct elements, no extra checking needed for these. + if (isa(*I)) + continue; + + ConstantInt *IdxVal = dyn_cast(I.getOperand()); + if (!IdxVal) return MarkUnsafe(Info); + + // Are all indices still zero? + IsAllZeroIndices &= IdxVal->isZero(); + + if (const ArrayType *AT = dyn_cast(*I)) { + // This GEP indexes an array. Verify that this is an in-range constant + // integer. Specifically, consider A[0][i]. We cannot know that the user + // isn't doing invalid things like allowing i to index an out-of-range + // subscript that accesses A[1]. Because of this, we have to reject SROA + // of any accesses into structs where any of the components are variables. + if (IdxVal->getZExtValue() >= AT->getNumElements()) + return MarkUnsafe(Info); + } else if (const VectorType *VT = dyn_cast(*I)) { + if (IdxVal->getZExtValue() >= VT->getNumElements()) + return MarkUnsafe(Info); + } + } + + // If there are any non-simple uses of this getelementptr, make sure to reject + // them. + return isSafeElementUse(GEPI, IsAllZeroIndices, AI, Info); +} + +/// isSafeMemIntrinsicOnAllocation - Return true if the specified memory +/// intrinsic can be promoted by SROA. At this point, we know that the operand +/// of the memintrinsic is a pointer to the beginning of the allocation. +void SROA::isSafeMemIntrinsicOnAllocation(MemIntrinsic *MI, AllocaInst *AI, + unsigned OpNo, AllocaInfo &Info) { + // If not constant length, give up. + ConstantInt *Length = dyn_cast(MI->getLength()); + if (!Length) return MarkUnsafe(Info); + + // If not the whole aggregate, give up. + if (Length->getZExtValue() != + TD->getTypeAllocSize(AI->getType()->getElementType())) + return MarkUnsafe(Info); + + // We only know about memcpy/memset/memmove. + if (!isa(MI)) + return MarkUnsafe(Info); + + // Otherwise, we can transform it. Determine whether this is a memcpy/set + // into or out of the aggregate. + if (OpNo == 1) + Info.isMemCpyDst = true; + else { + assert(OpNo == 2); + Info.isMemCpySrc = true; + } +} + +/// isSafeUseOfBitCastedAllocation - Return true if all users of this bitcast +/// are +void SROA::isSafeUseOfBitCastedAllocation(BitCastInst *BC, AllocaInst *AI, + AllocaInfo &Info) { + for (Value::use_iterator UI = BC->use_begin(), E = BC->use_end(); + UI != E; ++UI) { + if (BitCastInst *BCU = dyn_cast(UI)) { + isSafeUseOfBitCastedAllocation(BCU, AI, Info); + } else if (MemIntrinsic *MI = dyn_cast(UI)) { + isSafeMemIntrinsicOnAllocation(MI, AI, UI.getOperandNo(), Info); + } else if (StoreInst *SI = dyn_cast(UI)) { + if (SI->isVolatile()) + return MarkUnsafe(Info); + + // If storing the entire alloca in one chunk through a bitcasted pointer + // to integer, we can transform it. This happens (for example) when you + // cast a {i32,i32}* to i64* and store through it. This is similar to the + // memcpy case and occurs in various "byval" cases and emulated memcpys. + if (isa(SI->getOperand(0)->getType()) && + TD->getTypeAllocSize(SI->getOperand(0)->getType()) == + TD->getTypeAllocSize(AI->getType()->getElementType())) { + Info.isMemCpyDst = true; + continue; + } + return MarkUnsafe(Info); + } else if (LoadInst *LI = dyn_cast(UI)) { + if (LI->isVolatile()) + return MarkUnsafe(Info); + + // If loading the entire alloca in one chunk through a bitcasted pointer + // to integer, we can transform it. This happens (for example) when you + // cast a {i32,i32}* to i64* and load through it. This is similar to the + // memcpy case and occurs in various "byval" cases and emulated memcpys. + if (isa(LI->getType()) && + TD->getTypeAllocSize(LI->getType()) == + TD->getTypeAllocSize(AI->getType()->getElementType())) { + Info.isMemCpySrc = true; + continue; + } + return MarkUnsafe(Info); + } else if (isa(UI)) { + // If one user is DbgInfoIntrinsic then check if all users are + // DbgInfoIntrinsics. + if (OnlyUsedByDbgInfoIntrinsics(BC)) { + Info.needsCleanup = true; + return; + } + else + MarkUnsafe(Info); + } + else { + return MarkUnsafe(Info); + } + if (Info.isUnsafe) return; + } +} + +/// RewriteBitCastUserOfAlloca - BCInst (transitively) bitcasts AI, or indexes +/// to its first element. Transform users of the cast to use the new values +/// instead. +void SROA::RewriteBitCastUserOfAlloca(Instruction *BCInst, AllocaInst *AI, + SmallVector &NewElts) { + Value::use_iterator UI = BCInst->use_begin(), UE = BCInst->use_end(); + while (UI != UE) { + Instruction *User = cast(*UI++); + if (BitCastInst *BCU = dyn_cast(User)) { + RewriteBitCastUserOfAlloca(BCU, AI, NewElts); + if (BCU->use_empty()) BCU->eraseFromParent(); + continue; + } + + if (MemIntrinsic *MI = dyn_cast(User)) { + // This must be memcpy/memmove/memset of the entire aggregate. + // Split into one per element. + RewriteMemIntrinUserOfAlloca(MI, BCInst, AI, NewElts); + continue; + } + + if (StoreInst *SI = dyn_cast(User)) { + // If this is a store of the entire alloca from an integer, rewrite it. + RewriteStoreUserOfWholeAlloca(SI, AI, NewElts); + continue; + } + + if (LoadInst *LI = dyn_cast(User)) { + // If this is a load of the entire alloca to an integer, rewrite it. + RewriteLoadUserOfWholeAlloca(LI, AI, NewElts); + continue; + } + + // Otherwise it must be some other user of a gep of the first pointer. Just + // leave these alone. + continue; + } +} + +/// RewriteMemIntrinUserOfAlloca - MI is a memcpy/memset/memmove from or to AI. +/// Rewrite it to copy or set the elements of the scalarized memory. +void SROA::RewriteMemIntrinUserOfAlloca(MemIntrinsic *MI, Instruction *BCInst, + AllocaInst *AI, + SmallVector &NewElts) { + + // If this is a memcpy/memmove, construct the other pointer as the + // appropriate type. The "Other" pointer is the pointer that goes to memory + // that doesn't have anything to do with the alloca that we are promoting. For + // memset, this Value* stays null. + Value *OtherPtr = 0; + LLVMContext &Context = MI->getContext(); + unsigned MemAlignment = MI->getAlignment(); + if (MemTransferInst *MTI = dyn_cast(MI)) { // memmove/memcopy + if (BCInst == MTI->getRawDest()) + OtherPtr = MTI->getRawSource(); + else { + assert(BCInst == MTI->getRawSource()); + OtherPtr = MTI->getRawDest(); + } + } + + // If there is an other pointer, we want to convert it to the same pointer + // type as AI has, so we can GEP through it safely. + if (OtherPtr) { + // It is likely that OtherPtr is a bitcast, if so, remove it. + if (BitCastInst *BC = dyn_cast(OtherPtr)) + OtherPtr = BC->getOperand(0); + // All zero GEPs are effectively bitcasts. + if (GetElementPtrInst *GEP = dyn_cast(OtherPtr)) + if (GEP->hasAllZeroIndices()) + OtherPtr = GEP->getOperand(0); + + if (ConstantExpr *BCE = dyn_cast(OtherPtr)) + if (BCE->getOpcode() == Instruction::BitCast) + OtherPtr = BCE->getOperand(0); + + // If the pointer is not the right type, insert a bitcast to the right + // type. + if (OtherPtr->getType() != AI->getType()) + OtherPtr = new BitCastInst(OtherPtr, AI->getType(), OtherPtr->getName(), + MI); + } + + // Process each element of the aggregate. + Value *TheFn = MI->getOperand(0); + const Type *BytePtrTy = MI->getRawDest()->getType(); + bool SROADest = MI->getRawDest() == BCInst; + + Constant *Zero = Constant::getNullValue(Type::getInt32Ty(MI->getContext())); + + for (unsigned i = 0, e = NewElts.size(); i != e; ++i) { + // If this is a memcpy/memmove, emit a GEP of the other element address. + Value *OtherElt = 0; + unsigned OtherEltAlign = MemAlignment; + + if (OtherPtr) { + Value *Idx[2] = { Zero, + ConstantInt::get(Type::getInt32Ty(MI->getContext()), i) }; + OtherElt = GetElementPtrInst::Create(OtherPtr, Idx, Idx + 2, + OtherPtr->getNameStr()+"."+Twine(i), + MI); + uint64_t EltOffset; + const PointerType *OtherPtrTy = cast(OtherPtr->getType()); + if (const StructType *ST = + dyn_cast(OtherPtrTy->getElementType())) { + EltOffset = TD->getStructLayout(ST)->getElementOffset(i); + } else { + const Type *EltTy = + cast(OtherPtr->getType())->getElementType(); + EltOffset = TD->getTypeAllocSize(EltTy)*i; + } + + // The alignment of the other pointer is the guaranteed alignment of the + // element, which is affected by both the known alignment of the whole + // mem intrinsic and the alignment of the element. If the alignment of + // the memcpy (f.e.) is 32 but the element is at a 4-byte offset, then the + // known alignment is just 4 bytes. + OtherEltAlign = (unsigned)MinAlign(OtherEltAlign, EltOffset); + } + + Value *EltPtr = NewElts[i]; + const Type *EltTy = cast(EltPtr->getType())->getElementType(); + + // If we got down to a scalar, insert a load or store as appropriate. + if (EltTy->isSingleValueType()) { + if (isa(MI)) { + if (SROADest) { + // From Other to Alloca. + Value *Elt = new LoadInst(OtherElt, "tmp", false, OtherEltAlign, MI); + new StoreInst(Elt, EltPtr, MI); + } else { + // From Alloca to Other. + Value *Elt = new LoadInst(EltPtr, "tmp", MI); + new StoreInst(Elt, OtherElt, false, OtherEltAlign, MI); + } + continue; + } + assert(isa(MI)); + + // If the stored element is zero (common case), just store a null + // constant. + Constant *StoreVal; + if (ConstantInt *CI = dyn_cast(MI->getOperand(2))) { + if (CI->isZero()) { + StoreVal = Constant::getNullValue(EltTy); // 0.0, null, 0, <0,0> + } else { + // If EltTy is a vector type, get the element type. + const Type *ValTy = EltTy->getScalarType(); + + // Construct an integer with the right value. + unsigned EltSize = TD->getTypeSizeInBits(ValTy); + APInt OneVal(EltSize, CI->getZExtValue()); + APInt TotalVal(OneVal); + // Set each byte. + for (unsigned i = 0; 8*i < EltSize; ++i) { + TotalVal = TotalVal.shl(8); + TotalVal |= OneVal; + } + + // Convert the integer value to the appropriate type. + StoreVal = ConstantInt::get(Context, TotalVal); + if (isa(ValTy)) + StoreVal = ConstantExpr::getIntToPtr(StoreVal, ValTy); + else if (ValTy->isFloatingPoint()) + StoreVal = ConstantExpr::getBitCast(StoreVal, ValTy); + assert(StoreVal->getType() == ValTy && "Type mismatch!"); + + // If the requested value was a vector constant, create it. + if (EltTy != ValTy) { + unsigned NumElts = cast(ValTy)->getNumElements(); + SmallVector Elts(NumElts, StoreVal); + StoreVal = ConstantVector::get(&Elts[0], NumElts); + } + } + new StoreInst(StoreVal, EltPtr, MI); + continue; + } + // Otherwise, if we're storing a byte variable, use a memset call for + // this element. + } + + // Cast the element pointer to BytePtrTy. + if (EltPtr->getType() != BytePtrTy) + EltPtr = new BitCastInst(EltPtr, BytePtrTy, EltPtr->getNameStr(), MI); + + // Cast the other pointer (if we have one) to BytePtrTy. + if (OtherElt && OtherElt->getType() != BytePtrTy) + OtherElt = new BitCastInst(OtherElt, BytePtrTy,OtherElt->getNameStr(), + MI); + + unsigned EltSize = TD->getTypeAllocSize(EltTy); + + // Finally, insert the meminst for this element. + if (isa(MI)) { + Value *Ops[] = { + SROADest ? EltPtr : OtherElt, // Dest ptr + SROADest ? OtherElt : EltPtr, // Src ptr + ConstantInt::get(MI->getOperand(3)->getType(), EltSize), // Size + // Align + ConstantInt::get(Type::getInt32Ty(MI->getContext()), OtherEltAlign) + }; + CallInst::Create(TheFn, Ops, Ops + 4, "", MI); + } else { + assert(isa(MI)); + Value *Ops[] = { + EltPtr, MI->getOperand(2), // Dest, Value, + ConstantInt::get(MI->getOperand(3)->getType(), EltSize), // Size + Zero // Align + }; + CallInst::Create(TheFn, Ops, Ops + 4, "", MI); + } + } + MI->eraseFromParent(); +} + +/// RewriteStoreUserOfWholeAlloca - We found an store of an integer that +/// overwrites the entire allocation. Extract out the pieces of the stored +/// integer and store them individually. +void SROA::RewriteStoreUserOfWholeAlloca(StoreInst *SI, AllocaInst *AI, + SmallVector &NewElts){ + // Extract each element out of the integer according to its structure offset + // and store the element value to the individual alloca. + Value *SrcVal = SI->getOperand(0); + const Type *AllocaEltTy = AI->getType()->getElementType(); + uint64_t AllocaSizeBits = TD->getTypeAllocSizeInBits(AllocaEltTy); + + // If this isn't a store of an integer to the whole alloca, it may be a store + // to the first element. Just ignore the store in this case and normal SROA + // will handle it. + if (!isa(SrcVal->getType()) || + TD->getTypeAllocSizeInBits(SrcVal->getType()) != AllocaSizeBits) + return; + // Handle tail padding by extending the operand + if (TD->getTypeSizeInBits(SrcVal->getType()) != AllocaSizeBits) + SrcVal = new ZExtInst(SrcVal, + IntegerType::get(SI->getContext(), AllocaSizeBits), + "", SI); + + DEBUG(errs() << "PROMOTING STORE TO WHOLE ALLOCA: " << *AI << '\n' << *SI + << '\n'); + + // There are two forms here: AI could be an array or struct. Both cases + // have different ways to compute the element offset. + if (const StructType *EltSTy = dyn_cast(AllocaEltTy)) { + const StructLayout *Layout = TD->getStructLayout(EltSTy); + + for (unsigned i = 0, e = NewElts.size(); i != e; ++i) { + // Get the number of bits to shift SrcVal to get the value. + const Type *FieldTy = EltSTy->getElementType(i); + uint64_t Shift = Layout->getElementOffsetInBits(i); + + if (TD->isBigEndian()) + Shift = AllocaSizeBits-Shift-TD->getTypeAllocSizeInBits(FieldTy); + + Value *EltVal = SrcVal; + if (Shift) { + Value *ShiftVal = ConstantInt::get(EltVal->getType(), Shift); + EltVal = BinaryOperator::CreateLShr(EltVal, ShiftVal, + "sroa.store.elt", SI); + } + + // Truncate down to an integer of the right size. + uint64_t FieldSizeBits = TD->getTypeSizeInBits(FieldTy); + + // Ignore zero sized fields like {}, they obviously contain no data. + if (FieldSizeBits == 0) continue; + + if (FieldSizeBits != AllocaSizeBits) + EltVal = new TruncInst(EltVal, + IntegerType::get(SI->getContext(), FieldSizeBits), + "", SI); + Value *DestField = NewElts[i]; + if (EltVal->getType() == FieldTy) { + // Storing to an integer field of this size, just do it. + } else if (FieldTy->isFloatingPoint() || isa(FieldTy)) { + // Bitcast to the right element type (for fp/vector values). + EltVal = new BitCastInst(EltVal, FieldTy, "", SI); + } else { + // Otherwise, bitcast the dest pointer (for aggregates). + DestField = new BitCastInst(DestField, + PointerType::getUnqual(EltVal->getType()), + "", SI); + } + new StoreInst(EltVal, DestField, SI); + } + + } else { + const ArrayType *ATy = cast(AllocaEltTy); + const Type *ArrayEltTy = ATy->getElementType(); + uint64_t ElementOffset = TD->getTypeAllocSizeInBits(ArrayEltTy); + uint64_t ElementSizeBits = TD->getTypeSizeInBits(ArrayEltTy); + + uint64_t Shift; + + if (TD->isBigEndian()) + Shift = AllocaSizeBits-ElementOffset; + else + Shift = 0; + + for (unsigned i = 0, e = NewElts.size(); i != e; ++i) { + // Ignore zero sized fields like {}, they obviously contain no data. + if (ElementSizeBits == 0) continue; + + Value *EltVal = SrcVal; + if (Shift) { + Value *ShiftVal = ConstantInt::get(EltVal->getType(), Shift); + EltVal = BinaryOperator::CreateLShr(EltVal, ShiftVal, + "sroa.store.elt", SI); + } + + // Truncate down to an integer of the right size. + if (ElementSizeBits != AllocaSizeBits) + EltVal = new TruncInst(EltVal, + IntegerType::get(SI->getContext(), + ElementSizeBits),"",SI); + Value *DestField = NewElts[i]; + if (EltVal->getType() == ArrayEltTy) { + // Storing to an integer field of this size, just do it. + } else if (ArrayEltTy->isFloatingPoint() || isa(ArrayEltTy)) { + // Bitcast to the right element type (for fp/vector values). + EltVal = new BitCastInst(EltVal, ArrayEltTy, "", SI); + } else { + // Otherwise, bitcast the dest pointer (for aggregates). + DestField = new BitCastInst(DestField, + PointerType::getUnqual(EltVal->getType()), + "", SI); + } + new StoreInst(EltVal, DestField, SI); + + if (TD->isBigEndian()) + Shift -= ElementOffset; + else + Shift += ElementOffset; + } + } + + SI->eraseFromParent(); +} + +/// RewriteLoadUserOfWholeAlloca - We found an load of the entire allocation to +/// an integer. Load the individual pieces to form the aggregate value. +void SROA::RewriteLoadUserOfWholeAlloca(LoadInst *LI, AllocaInst *AI, + SmallVector &NewElts) { + // Extract each element out of the NewElts according to its structure offset + // and form the result value. + const Type *AllocaEltTy = AI->getType()->getElementType(); + uint64_t AllocaSizeBits = TD->getTypeAllocSizeInBits(AllocaEltTy); + + // If this isn't a load of the whole alloca to an integer, it may be a load + // of the first element. Just ignore the load in this case and normal SROA + // will handle it. + if (!isa(LI->getType()) || + TD->getTypeAllocSizeInBits(LI->getType()) != AllocaSizeBits) + return; + + DEBUG(errs() << "PROMOTING LOAD OF WHOLE ALLOCA: " << *AI << '\n' << *LI + << '\n'); + + // There are two forms here: AI could be an array or struct. Both cases + // have different ways to compute the element offset. + const StructLayout *Layout = 0; + uint64_t ArrayEltBitOffset = 0; + if (const StructType *EltSTy = dyn_cast(AllocaEltTy)) { + Layout = TD->getStructLayout(EltSTy); + } else { + const Type *ArrayEltTy = cast(AllocaEltTy)->getElementType(); + ArrayEltBitOffset = TD->getTypeAllocSizeInBits(ArrayEltTy); + } + + Value *ResultVal = + Constant::getNullValue(IntegerType::get(LI->getContext(), AllocaSizeBits)); + + for (unsigned i = 0, e = NewElts.size(); i != e; ++i) { + // Load the value from the alloca. If the NewElt is an aggregate, cast + // the pointer to an integer of the same size before doing the load. + Value *SrcField = NewElts[i]; + const Type *FieldTy = + cast(SrcField->getType())->getElementType(); + uint64_t FieldSizeBits = TD->getTypeSizeInBits(FieldTy); + + // Ignore zero sized fields like {}, they obviously contain no data. + if (FieldSizeBits == 0) continue; + + const IntegerType *FieldIntTy = IntegerType::get(LI->getContext(), + FieldSizeBits); + if (!isa(FieldTy) && !FieldTy->isFloatingPoint() && + !isa(FieldTy)) + SrcField = new BitCastInst(SrcField, + PointerType::getUnqual(FieldIntTy), + "", LI); + SrcField = new LoadInst(SrcField, "sroa.load.elt", LI); + + // If SrcField is a fp or vector of the right size but that isn't an + // integer type, bitcast to an integer so we can shift it. + if (SrcField->getType() != FieldIntTy) + SrcField = new BitCastInst(SrcField, FieldIntTy, "", LI); + + // Zero extend the field to be the same size as the final alloca so that + // we can shift and insert it. + if (SrcField->getType() != ResultVal->getType()) + SrcField = new ZExtInst(SrcField, ResultVal->getType(), "", LI); + + // Determine the number of bits to shift SrcField. + uint64_t Shift; + if (Layout) // Struct case. + Shift = Layout->getElementOffsetInBits(i); + else // Array case. + Shift = i*ArrayEltBitOffset; + + if (TD->isBigEndian()) + Shift = AllocaSizeBits-Shift-FieldIntTy->getBitWidth(); + + if (Shift) { + Value *ShiftVal = ConstantInt::get(SrcField->getType(), Shift); + SrcField = BinaryOperator::CreateShl(SrcField, ShiftVal, "", LI); + } + + ResultVal = BinaryOperator::CreateOr(SrcField, ResultVal, "", LI); + } + + // Handle tail padding by truncating the result + if (TD->getTypeSizeInBits(LI->getType()) != AllocaSizeBits) + ResultVal = new TruncInst(ResultVal, LI->getType(), "", LI); + + LI->replaceAllUsesWith(ResultVal); + LI->eraseFromParent(); +} + + +/// HasPadding - Return true if the specified type has any structure or +/// alignment padding, false otherwise. +static bool HasPadding(const Type *Ty, const TargetData &TD) { + if (const StructType *STy = dyn_cast(Ty)) { + const StructLayout *SL = TD.getStructLayout(STy); + unsigned PrevFieldBitOffset = 0; + for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) { + unsigned FieldBitOffset = SL->getElementOffsetInBits(i); + + // Padding in sub-elements? + if (HasPadding(STy->getElementType(i), TD)) + return true; + + // Check to see if there is any padding between this element and the + // previous one. + if (i) { + unsigned PrevFieldEnd = + PrevFieldBitOffset+TD.getTypeSizeInBits(STy->getElementType(i-1)); + if (PrevFieldEnd < FieldBitOffset) + return true; + } + + PrevFieldBitOffset = FieldBitOffset; + } + + // Check for tail padding. + if (unsigned EltCount = STy->getNumElements()) { + unsigned PrevFieldEnd = PrevFieldBitOffset + + TD.getTypeSizeInBits(STy->getElementType(EltCount-1)); + if (PrevFieldEnd < SL->getSizeInBits()) + return true; + } + + } else if (const ArrayType *ATy = dyn_cast(Ty)) { + return HasPadding(ATy->getElementType(), TD); + } else if (const VectorType *VTy = dyn_cast(Ty)) { + return HasPadding(VTy->getElementType(), TD); + } + return TD.getTypeSizeInBits(Ty) != TD.getTypeAllocSizeInBits(Ty); +} + +/// isSafeStructAllocaToScalarRepl - Check to see if the specified allocation of +/// an aggregate can be broken down into elements. Return 0 if not, 3 if safe, +/// or 1 if safe after canonicalization has been performed. +/// +int SROA::isSafeAllocaToScalarRepl(AllocaInst *AI) { + // Loop over the use list of the alloca. We can only transform it if all of + // the users are safe to transform. + AllocaInfo Info; + + for (Value::use_iterator I = AI->use_begin(), E = AI->use_end(); + I != E; ++I) { + isSafeUseOfAllocation(cast(*I), AI, Info); + if (Info.isUnsafe) { + DEBUG(errs() << "Cannot transform: " << *AI << "\n due to user: " + << **I << '\n'); + return 0; + } + } + + // Okay, we know all the users are promotable. If the aggregate is a memcpy + // source and destination, we have to be careful. In particular, the memcpy + // could be moving around elements that live in structure padding of the LLVM + // types, but may actually be used. In these cases, we refuse to promote the + // struct. + if (Info.isMemCpySrc && Info.isMemCpyDst && + HasPadding(AI->getType()->getElementType(), *TD)) + return 0; + + // If we require cleanup, return 1, otherwise return 3. + return Info.needsCleanup ? 1 : 3; +} + +/// CleanupGEP - GEP is used by an Alloca, which can be prompted after the GEP +/// is canonicalized here. +void SROA::CleanupGEP(GetElementPtrInst *GEPI) { + gep_type_iterator I = gep_type_begin(GEPI); + ++I; + + const ArrayType *AT = dyn_cast(*I); + if (!AT) + return; + + uint64_t NumElements = AT->getNumElements(); + + if (isa(I.getOperand())) + return; + + if (NumElements == 1) { + GEPI->setOperand(2, + Constant::getNullValue(Type::getInt32Ty(GEPI->getContext()))); + return; + } + + assert(NumElements == 2 && "Unhandled case!"); + // All users of the GEP must be loads. At each use of the GEP, insert + // two loads of the appropriate indexed GEP and select between them. + Value *IsOne = new ICmpInst(GEPI, ICmpInst::ICMP_NE, I.getOperand(), + Constant::getNullValue(I.getOperand()->getType()), + "isone"); + // Insert the new GEP instructions, which are properly indexed. + SmallVector Indices(GEPI->op_begin()+1, GEPI->op_end()); + Indices[1] = Constant::getNullValue(Type::getInt32Ty(GEPI->getContext())); + Value *ZeroIdx = GetElementPtrInst::Create(GEPI->getOperand(0), + Indices.begin(), + Indices.end(), + GEPI->getName()+".0", GEPI); + Indices[1] = ConstantInt::get(Type::getInt32Ty(GEPI->getContext()), 1); + Value *OneIdx = GetElementPtrInst::Create(GEPI->getOperand(0), + Indices.begin(), + Indices.end(), + GEPI->getName()+".1", GEPI); + // Replace all loads of the variable index GEP with loads from both + // indexes and a select. + while (!GEPI->use_empty()) { + LoadInst *LI = cast(GEPI->use_back()); + Value *Zero = new LoadInst(ZeroIdx, LI->getName()+".0", LI); + Value *One = new LoadInst(OneIdx , LI->getName()+".1", LI); + Value *R = SelectInst::Create(IsOne, One, Zero, LI->getName(), LI); + LI->replaceAllUsesWith(R); + LI->eraseFromParent(); + } + GEPI->eraseFromParent(); +} + + +/// CleanupAllocaUsers - If SROA reported that it can promote the specified +/// allocation, but only if cleaned up, perform the cleanups required. +void SROA::CleanupAllocaUsers(AllocaInst *AI) { + // At this point, we know that the end result will be SROA'd and promoted, so + // we can insert ugly code if required so long as sroa+mem2reg will clean it + // up. + for (Value::use_iterator UI = AI->use_begin(), E = AI->use_end(); + UI != E; ) { + User *U = *UI++; + if (GetElementPtrInst *GEPI = dyn_cast(U)) + CleanupGEP(GEPI); + else { + Instruction *I = cast(U); + SmallVector DbgInUses; + if (!isa(I) && OnlyUsedByDbgInfoIntrinsics(I, &DbgInUses)) { + // Safe to remove debug info uses. + while (!DbgInUses.empty()) { + DbgInfoIntrinsic *DI = DbgInUses.back(); DbgInUses.pop_back(); + DI->eraseFromParent(); + } + I->eraseFromParent(); + } + } + } +} + +/// MergeInType - Add the 'In' type to the accumulated type (Accum) so far at +/// the offset specified by Offset (which is specified in bytes). +/// +/// There are two cases we handle here: +/// 1) A union of vector types of the same size and potentially its elements. +/// Here we turn element accesses into insert/extract element operations. +/// This promotes a <4 x float> with a store of float to the third element +/// into a <4 x float> that uses insert element. +/// 2) A fully general blob of memory, which we turn into some (potentially +/// large) integer type with extract and insert operations where the loads +/// and stores would mutate the memory. +static void MergeInType(const Type *In, uint64_t Offset, const Type *&VecTy, + unsigned AllocaSize, const TargetData &TD, + LLVMContext &Context) { + // If this could be contributing to a vector, analyze it. + if (VecTy != Type::getVoidTy(Context)) { // either null or a vector type. + + // If the In type is a vector that is the same size as the alloca, see if it + // matches the existing VecTy. + if (const VectorType *VInTy = dyn_cast(In)) { + if (VInTy->getBitWidth()/8 == AllocaSize && Offset == 0) { + // If we're storing/loading a vector of the right size, allow it as a + // vector. If this the first vector we see, remember the type so that + // we know the element size. + if (VecTy == 0) + VecTy = VInTy; + return; + } + } else if (In->isFloatTy() || In->isDoubleTy() || + (isa(In) && In->getPrimitiveSizeInBits() >= 8 && + isPowerOf2_32(In->getPrimitiveSizeInBits()))) { + // If we're accessing something that could be an element of a vector, see + // if the implied vector agrees with what we already have and if Offset is + // compatible with it. + unsigned EltSize = In->getPrimitiveSizeInBits()/8; + if (Offset % EltSize == 0 && + AllocaSize % EltSize == 0 && + (VecTy == 0 || + cast(VecTy)->getElementType() + ->getPrimitiveSizeInBits()/8 == EltSize)) { + if (VecTy == 0) + VecTy = VectorType::get(In, AllocaSize/EltSize); + return; + } + } + } + + // Otherwise, we have a case that we can't handle with an optimized vector + // form. We can still turn this into a large integer. + VecTy = Type::getVoidTy(Context); +} + +/// CanConvertToScalar - V is a pointer. If we can convert the pointee and all +/// its accesses to use a to single vector type, return true, and set VecTy to +/// the new type. If we could convert the alloca into a single promotable +/// integer, return true but set VecTy to VoidTy. Further, if the use is not a +/// completely trivial use that mem2reg could promote, set IsNotTrivial. Offset +/// is the current offset from the base of the alloca being analyzed. +/// +/// If we see at least one access to the value that is as a vector type, set the +/// SawVec flag. +/// +bool SROA::CanConvertToScalar(Value *V, bool &IsNotTrivial, const Type *&VecTy, + bool &SawVec, uint64_t Offset, + unsigned AllocaSize) { + for (Value::use_iterator UI = V->use_begin(), E = V->use_end(); UI!=E; ++UI) { + Instruction *User = cast(*UI); + + if (LoadInst *LI = dyn_cast(User)) { + // Don't break volatile loads. + if (LI->isVolatile()) + return false; + MergeInType(LI->getType(), Offset, VecTy, + AllocaSize, *TD, V->getContext()); + SawVec |= isa(LI->getType()); + continue; + } + + if (StoreInst *SI = dyn_cast(User)) { + // Storing the pointer, not into the value? + if (SI->getOperand(0) == V || SI->isVolatile()) return 0; + MergeInType(SI->getOperand(0)->getType(), Offset, + VecTy, AllocaSize, *TD, V->getContext()); + SawVec |= isa(SI->getOperand(0)->getType()); + continue; + } + + if (BitCastInst *BCI = dyn_cast(User)) { + if (!CanConvertToScalar(BCI, IsNotTrivial, VecTy, SawVec, Offset, + AllocaSize)) + return false; + IsNotTrivial = true; + continue; + } + + if (GetElementPtrInst *GEP = dyn_cast(User)) { + // If this is a GEP with a variable indices, we can't handle it. + if (!GEP->hasAllConstantIndices()) + return false; + + // Compute the offset that this GEP adds to the pointer. + SmallVector Indices(GEP->op_begin()+1, GEP->op_end()); + uint64_t GEPOffset = TD->getIndexedOffset(GEP->getOperand(0)->getType(), + &Indices[0], Indices.size()); + // See if all uses can be converted. + if (!CanConvertToScalar(GEP, IsNotTrivial, VecTy, SawVec,Offset+GEPOffset, + AllocaSize)) + return false; + IsNotTrivial = true; + continue; + } + + // If this is a constant sized memset of a constant value (e.g. 0) we can + // handle it. + if (MemSetInst *MSI = dyn_cast(User)) { + // Store of constant value and constant size. + if (isa(MSI->getValue()) && + isa(MSI->getLength())) { + IsNotTrivial = true; + continue; + } + } + + // If this is a memcpy or memmove into or out of the whole allocation, we + // can handle it like a load or store of the scalar type. + if (MemTransferInst *MTI = dyn_cast(User)) { + if (ConstantInt *Len = dyn_cast(MTI->getLength())) + if (Len->getZExtValue() == AllocaSize && Offset == 0) { + IsNotTrivial = true; + continue; + } + } + + // Ignore dbg intrinsic. + if (isa(User)) + continue; + + // Otherwise, we cannot handle this! + return false; + } + + return true; +} + + +/// ConvertUsesToScalar - Convert all of the users of Ptr to use the new alloca +/// directly. This happens when we are converting an "integer union" to a +/// single integer scalar, or when we are converting a "vector union" to a +/// vector with insert/extractelement instructions. +/// +/// Offset is an offset from the original alloca, in bits that need to be +/// shifted to the right. By the end of this, there should be no uses of Ptr. +void SROA::ConvertUsesToScalar(Value *Ptr, AllocaInst *NewAI, uint64_t Offset) { + while (!Ptr->use_empty()) { + Instruction *User = cast(Ptr->use_back()); + + if (BitCastInst *CI = dyn_cast(User)) { + ConvertUsesToScalar(CI, NewAI, Offset); + CI->eraseFromParent(); + continue; + } + + if (GetElementPtrInst *GEP = dyn_cast(User)) { + // Compute the offset that this GEP adds to the pointer. + SmallVector Indices(GEP->op_begin()+1, GEP->op_end()); + uint64_t GEPOffset = TD->getIndexedOffset(GEP->getOperand(0)->getType(), + &Indices[0], Indices.size()); + ConvertUsesToScalar(GEP, NewAI, Offset+GEPOffset*8); + GEP->eraseFromParent(); + continue; + } + + IRBuilder<> Builder(User->getParent(), User); + + if (LoadInst *LI = dyn_cast(User)) { + // The load is a bit extract from NewAI shifted right by Offset bits. + Value *LoadedVal = Builder.CreateLoad(NewAI, "tmp"); + Value *NewLoadVal + = ConvertScalar_ExtractValue(LoadedVal, LI->getType(), Offset, Builder); + LI->replaceAllUsesWith(NewLoadVal); + LI->eraseFromParent(); + continue; + } + + if (StoreInst *SI = dyn_cast(User)) { + assert(SI->getOperand(0) != Ptr && "Consistency error!"); + // FIXME: Remove once builder has Twine API. + Value *Old = Builder.CreateLoad(NewAI, (NewAI->getName()+".in").str().c_str()); + Value *New = ConvertScalar_InsertValue(SI->getOperand(0), Old, Offset, + Builder); + Builder.CreateStore(New, NewAI); + SI->eraseFromParent(); + continue; + } + + // If this is a constant sized memset of a constant value (e.g. 0) we can + // transform it into a store of the expanded constant value. + if (MemSetInst *MSI = dyn_cast(User)) { + assert(MSI->getRawDest() == Ptr && "Consistency error!"); + unsigned NumBytes = cast(MSI->getLength())->getZExtValue(); + if (NumBytes != 0) { + unsigned Val = cast(MSI->getValue())->getZExtValue(); + + // Compute the value replicated the right number of times. + APInt APVal(NumBytes*8, Val); + + // Splat the value if non-zero. + if (Val) + for (unsigned i = 1; i != NumBytes; ++i) + APVal |= APVal << 8; + + // FIXME: Remove once builder has Twine API. + Value *Old = Builder.CreateLoad(NewAI, (NewAI->getName()+".in").str().c_str()); + Value *New = ConvertScalar_InsertValue( + ConstantInt::get(User->getContext(), APVal), + Old, Offset, Builder); + Builder.CreateStore(New, NewAI); + } + MSI->eraseFromParent(); + continue; + } + + // If this is a memcpy or memmove into or out of the whole allocation, we + // can handle it like a load or store of the scalar type. + if (MemTransferInst *MTI = dyn_cast(User)) { + assert(Offset == 0 && "must be store to start of alloca"); + + // If the source and destination are both to the same alloca, then this is + // a noop copy-to-self, just delete it. Otherwise, emit a load and store + // as appropriate. + AllocaInst *OrigAI = cast(Ptr->getUnderlyingObject()); + + if (MTI->getSource()->getUnderlyingObject() != OrigAI) { + // Dest must be OrigAI, change this to be a load from the original + // pointer (bitcasted), then a store to our new alloca. + assert(MTI->getRawDest() == Ptr && "Neither use is of pointer?"); + Value *SrcPtr = MTI->getSource(); + SrcPtr = Builder.CreateBitCast(SrcPtr, NewAI->getType()); + + LoadInst *SrcVal = Builder.CreateLoad(SrcPtr, "srcval"); + SrcVal->setAlignment(MTI->getAlignment()); + Builder.CreateStore(SrcVal, NewAI); + } else if (MTI->getDest()->getUnderlyingObject() != OrigAI) { + // Src must be OrigAI, change this to be a load from NewAI then a store + // through the original dest pointer (bitcasted). + assert(MTI->getRawSource() == Ptr && "Neither use is of pointer?"); + LoadInst *SrcVal = Builder.CreateLoad(NewAI, "srcval"); + + Value *DstPtr = Builder.CreateBitCast(MTI->getDest(), NewAI->getType()); + StoreInst *NewStore = Builder.CreateStore(SrcVal, DstPtr); + NewStore->setAlignment(MTI->getAlignment()); + } else { + // Noop transfer. Src == Dst + } + + + MTI->eraseFromParent(); + continue; + } + + // If user is a dbg info intrinsic then it is safe to remove it. + if (isa(User)) { + User->eraseFromParent(); + continue; + } + + llvm_unreachable("Unsupported operation!"); + } +} + +/// ConvertScalar_ExtractValue - Extract a value of type ToType from an integer +/// or vector value FromVal, extracting the bits from the offset specified by +/// Offset. This returns the value, which is of type ToType. +/// +/// This happens when we are converting an "integer union" to a single +/// integer scalar, or when we are converting a "vector union" to a vector with +/// insert/extractelement instructions. +/// +/// Offset is an offset from the original alloca, in bits that need to be +/// shifted to the right. +Value *SROA::ConvertScalar_ExtractValue(Value *FromVal, const Type *ToType, + uint64_t Offset, IRBuilder<> &Builder) { + // If the load is of the whole new alloca, no conversion is needed. + if (FromVal->getType() == ToType && Offset == 0) + return FromVal; + + // If the result alloca is a vector type, this is either an element + // access or a bitcast to another vector type of the same size. + if (const VectorType *VTy = dyn_cast(FromVal->getType())) { + if (isa(ToType)) + return Builder.CreateBitCast(FromVal, ToType, "tmp"); + + // Otherwise it must be an element access. + unsigned Elt = 0; + if (Offset) { + unsigned EltSize = TD->getTypeAllocSizeInBits(VTy->getElementType()); + Elt = Offset/EltSize; + assert(EltSize*Elt == Offset && "Invalid modulus in validity checking"); + } + // Return the element extracted out of it. + Value *V = Builder.CreateExtractElement(FromVal, ConstantInt::get( + Type::getInt32Ty(FromVal->getContext()), Elt), "tmp"); + if (V->getType() != ToType) + V = Builder.CreateBitCast(V, ToType, "tmp"); + return V; + } + + // If ToType is a first class aggregate, extract out each of the pieces and + // use insertvalue's to form the FCA. + if (const StructType *ST = dyn_cast(ToType)) { + const StructLayout &Layout = *TD->getStructLayout(ST); + Value *Res = UndefValue::get(ST); + for (unsigned i = 0, e = ST->getNumElements(); i != e; ++i) { + Value *Elt = ConvertScalar_ExtractValue(FromVal, ST->getElementType(i), + Offset+Layout.getElementOffsetInBits(i), + Builder); + Res = Builder.CreateInsertValue(Res, Elt, i, "tmp"); + } + return Res; + } + + if (const ArrayType *AT = dyn_cast(ToType)) { + uint64_t EltSize = TD->getTypeAllocSizeInBits(AT->getElementType()); + Value *Res = UndefValue::get(AT); + for (unsigned i = 0, e = AT->getNumElements(); i != e; ++i) { + Value *Elt = ConvertScalar_ExtractValue(FromVal, AT->getElementType(), + Offset+i*EltSize, Builder); + Res = Builder.CreateInsertValue(Res, Elt, i, "tmp"); + } + return Res; + } + + // Otherwise, this must be a union that was converted to an integer value. + const IntegerType *NTy = cast(FromVal->getType()); + + // If this is a big-endian system and the load is narrower than the + // full alloca type, we need to do a shift to get the right bits. + int ShAmt = 0; + if (TD->isBigEndian()) { + // On big-endian machines, the lowest bit is stored at the bit offset + // from the pointer given by getTypeStoreSizeInBits. This matters for + // integers with a bitwidth that is not a multiple of 8. + ShAmt = TD->getTypeStoreSizeInBits(NTy) - + TD->getTypeStoreSizeInBits(ToType) - Offset; + } else { + ShAmt = Offset; + } + + // Note: we support negative bitwidths (with shl) which are not defined. + // We do this to support (f.e.) loads off the end of a structure where + // only some bits are used. + if (ShAmt > 0 && (unsigned)ShAmt < NTy->getBitWidth()) + FromVal = Builder.CreateLShr(FromVal, + ConstantInt::get(FromVal->getType(), + ShAmt), "tmp"); + else if (ShAmt < 0 && (unsigned)-ShAmt < NTy->getBitWidth()) + FromVal = Builder.CreateShl(FromVal, + ConstantInt::get(FromVal->getType(), + -ShAmt), "tmp"); + + // Finally, unconditionally truncate the integer to the right width. + unsigned LIBitWidth = TD->getTypeSizeInBits(ToType); + if (LIBitWidth < NTy->getBitWidth()) + FromVal = + Builder.CreateTrunc(FromVal, IntegerType::get(FromVal->getContext(), + LIBitWidth), "tmp"); + else if (LIBitWidth > NTy->getBitWidth()) + FromVal = + Builder.CreateZExt(FromVal, IntegerType::get(FromVal->getContext(), + LIBitWidth), "tmp"); + + // If the result is an integer, this is a trunc or bitcast. + if (isa(ToType)) { + // Should be done. + } else if (ToType->isFloatingPoint() || isa(ToType)) { + // Just do a bitcast, we know the sizes match up. + FromVal = Builder.CreateBitCast(FromVal, ToType, "tmp"); + } else { + // Otherwise must be a pointer. + FromVal = Builder.CreateIntToPtr(FromVal, ToType, "tmp"); + } + assert(FromVal->getType() == ToType && "Didn't convert right?"); + return FromVal; +} + + +/// ConvertScalar_InsertValue - Insert the value "SV" into the existing integer +/// or vector value "Old" at the offset specified by Offset. +/// +/// This happens when we are converting an "integer union" to a +/// single integer scalar, or when we are converting a "vector union" to a +/// vector with insert/extractelement instructions. +/// +/// Offset is an offset from the original alloca, in bits that need to be +/// shifted to the right. +Value *SROA::ConvertScalar_InsertValue(Value *SV, Value *Old, + uint64_t Offset, IRBuilder<> &Builder) { + + // Convert the stored type to the actual type, shift it left to insert + // then 'or' into place. + const Type *AllocaType = Old->getType(); + LLVMContext &Context = Old->getContext(); + + if (const VectorType *VTy = dyn_cast(AllocaType)) { + uint64_t VecSize = TD->getTypeAllocSizeInBits(VTy); + uint64_t ValSize = TD->getTypeAllocSizeInBits(SV->getType()); + + // Changing the whole vector with memset or with an access of a different + // vector type? + if (ValSize == VecSize) + return Builder.CreateBitCast(SV, AllocaType, "tmp"); + + uint64_t EltSize = TD->getTypeAllocSizeInBits(VTy->getElementType()); + + // Must be an element insertion. + unsigned Elt = Offset/EltSize; + + if (SV->getType() != VTy->getElementType()) + SV = Builder.CreateBitCast(SV, VTy->getElementType(), "tmp"); + + SV = Builder.CreateInsertElement(Old, SV, + ConstantInt::get(Type::getInt32Ty(SV->getContext()), Elt), + "tmp"); + return SV; + } + + // If SV is a first-class aggregate value, insert each value recursively. + if (const StructType *ST = dyn_cast(SV->getType())) { + const StructLayout &Layout = *TD->getStructLayout(ST); + for (unsigned i = 0, e = ST->getNumElements(); i != e; ++i) { + Value *Elt = Builder.CreateExtractValue(SV, i, "tmp"); + Old = ConvertScalar_InsertValue(Elt, Old, + Offset+Layout.getElementOffsetInBits(i), + Builder); + } + return Old; + } + + if (const ArrayType *AT = dyn_cast(SV->getType())) { + uint64_t EltSize = TD->getTypeAllocSizeInBits(AT->getElementType()); + for (unsigned i = 0, e = AT->getNumElements(); i != e; ++i) { + Value *Elt = Builder.CreateExtractValue(SV, i, "tmp"); + Old = ConvertScalar_InsertValue(Elt, Old, Offset+i*EltSize, Builder); + } + return Old; + } + + // If SV is a float, convert it to the appropriate integer type. + // If it is a pointer, do the same. + unsigned SrcWidth = TD->getTypeSizeInBits(SV->getType()); + unsigned DestWidth = TD->getTypeSizeInBits(AllocaType); + unsigned SrcStoreWidth = TD->getTypeStoreSizeInBits(SV->getType()); + unsigned DestStoreWidth = TD->getTypeStoreSizeInBits(AllocaType); + if (SV->getType()->isFloatingPoint() || isa(SV->getType())) + SV = Builder.CreateBitCast(SV, + IntegerType::get(SV->getContext(),SrcWidth), "tmp"); + else if (isa(SV->getType())) + SV = Builder.CreatePtrToInt(SV, TD->getIntPtrType(SV->getContext()), "tmp"); + + // Zero extend or truncate the value if needed. + if (SV->getType() != AllocaType) { + if (SV->getType()->getPrimitiveSizeInBits() < + AllocaType->getPrimitiveSizeInBits()) + SV = Builder.CreateZExt(SV, AllocaType, "tmp"); + else { + // Truncation may be needed if storing more than the alloca can hold + // (undefined behavior). + SV = Builder.CreateTrunc(SV, AllocaType, "tmp"); + SrcWidth = DestWidth; + SrcStoreWidth = DestStoreWidth; + } + } + + // If this is a big-endian system and the store is narrower than the + // full alloca type, we need to do a shift to get the right bits. + int ShAmt = 0; + if (TD->isBigEndian()) { + // On big-endian machines, the lowest bit is stored at the bit offset + // from the pointer given by getTypeStoreSizeInBits. This matters for + // integers with a bitwidth that is not a multiple of 8. + ShAmt = DestStoreWidth - SrcStoreWidth - Offset; + } else { + ShAmt = Offset; + } + + // Note: we support negative bitwidths (with shr) which are not defined. + // We do this to support (f.e.) stores off the end of a structure where + // only some bits in the structure are set. + APInt Mask(APInt::getLowBitsSet(DestWidth, SrcWidth)); + if (ShAmt > 0 && (unsigned)ShAmt < DestWidth) { + SV = Builder.CreateShl(SV, ConstantInt::get(SV->getType(), + ShAmt), "tmp"); + Mask <<= ShAmt; + } else if (ShAmt < 0 && (unsigned)-ShAmt < DestWidth) { + SV = Builder.CreateLShr(SV, ConstantInt::get(SV->getType(), + -ShAmt), "tmp"); + Mask = Mask.lshr(-ShAmt); + } + + // Mask out the bits we are about to insert from the old value, and or + // in the new bits. + if (SrcWidth != DestWidth) { + assert(DestWidth > SrcWidth); + Old = Builder.CreateAnd(Old, ConstantInt::get(Context, ~Mask), "mask"); + SV = Builder.CreateOr(Old, SV, "ins"); + } + return SV; +} + + + +/// PointsToConstantGlobal - Return true if V (possibly indirectly) points to +/// some part of a constant global variable. This intentionally only accepts +/// constant expressions because we don't can't rewrite arbitrary instructions. +static bool PointsToConstantGlobal(Value *V) { + if (GlobalVariable *GV = dyn_cast(V)) + return GV->isConstant(); + if (ConstantExpr *CE = dyn_cast(V)) + if (CE->getOpcode() == Instruction::BitCast || + CE->getOpcode() == Instruction::GetElementPtr) + return PointsToConstantGlobal(CE->getOperand(0)); + return false; +} + +/// isOnlyCopiedFromConstantGlobal - Recursively walk the uses of a (derived) +/// pointer to an alloca. Ignore any reads of the pointer, return false if we +/// see any stores or other unknown uses. If we see pointer arithmetic, keep +/// track of whether it moves the pointer (with isOffset) but otherwise traverse +/// the uses. If we see a memcpy/memmove that targets an unoffseted pointer to +/// the alloca, and if the source pointer is a pointer to a constant global, we +/// can optimize this. +static bool isOnlyCopiedFromConstantGlobal(Value *V, Instruction *&TheCopy, + bool isOffset) { + for (Value::use_iterator UI = V->use_begin(), E = V->use_end(); UI!=E; ++UI) { + if (LoadInst *LI = dyn_cast(*UI)) + // Ignore non-volatile loads, they are always ok. + if (!LI->isVolatile()) + continue; + + if (BitCastInst *BCI = dyn_cast(*UI)) { + // If uses of the bitcast are ok, we are ok. + if (!isOnlyCopiedFromConstantGlobal(BCI, TheCopy, isOffset)) + return false; + continue; + } + if (GetElementPtrInst *GEP = dyn_cast(*UI)) { + // If the GEP has all zero indices, it doesn't offset the pointer. If it + // doesn't, it does. + if (!isOnlyCopiedFromConstantGlobal(GEP, TheCopy, + isOffset || !GEP->hasAllZeroIndices())) + return false; + continue; + } + + // If this is isn't our memcpy/memmove, reject it as something we can't + // handle. + if (!isa(*UI)) + return false; + + // If we already have seen a copy, reject the second one. + if (TheCopy) return false; + + // If the pointer has been offset from the start of the alloca, we can't + // safely handle this. + if (isOffset) return false; + + // If the memintrinsic isn't using the alloca as the dest, reject it. + if (UI.getOperandNo() != 1) return false; + + MemIntrinsic *MI = cast(*UI); + + // If the source of the memcpy/move is not a constant global, reject it. + if (!PointsToConstantGlobal(MI->getOperand(2))) + return false; + + // Otherwise, the transform is safe. Remember the copy instruction. + TheCopy = MI; + } + return true; +} + +/// isOnlyCopiedFromConstantGlobal - Return true if the specified alloca is only +/// modified by a copy from a constant global. If we can prove this, we can +/// replace any uses of the alloca with uses of the global directly. +Instruction *SROA::isOnlyCopiedFromConstantGlobal(AllocaInst *AI) { + Instruction *TheCopy = 0; + if (::isOnlyCopiedFromConstantGlobal(AI, TheCopy, false)) + return TheCopy; + return 0; +} diff --git a/libclamav/c++/llvm/lib/Transforms/Scalar/SimplifyCFGPass.cpp b/libclamav/c++/llvm/lib/Transforms/Scalar/SimplifyCFGPass.cpp new file mode 100644 index 000000000..e905952c5 --- /dev/null +++ b/libclamav/c++/llvm/lib/Transforms/Scalar/SimplifyCFGPass.cpp @@ -0,0 +1,238 @@ +//===- SimplifyCFGPass.cpp - CFG Simplification Pass ----------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements dead code elimination and basic block merging, along +// with a collection of other peephole control flow optimizations. For example: +// +// * Removes basic blocks with no predecessors. +// * Merges a basic block into its predecessor if there is only one and the +// predecessor only has one successor. +// * Eliminates PHI nodes for basic blocks with a single predecessor. +// * Eliminates a basic block that only contains an unconditional branch. +// * Changes invoke instructions to nounwind functions to be calls. +// * Change things like "if (x) if (y)" into "if (x&y)". +// * etc.. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "simplifycfg" +#include "llvm/Transforms/Scalar.h" +#include "llvm/Transforms/Utils/Local.h" +#include "llvm/Constants.h" +#include "llvm/Instructions.h" +#include "llvm/Module.h" +#include "llvm/Attributes.h" +#include "llvm/Support/CFG.h" +#include "llvm/Pass.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/Statistic.h" +using namespace llvm; + +STATISTIC(NumSimpl, "Number of blocks simplified"); + +namespace { + struct CFGSimplifyPass : public FunctionPass { + static char ID; // Pass identification, replacement for typeid + CFGSimplifyPass() : FunctionPass(&ID) {} + + virtual bool runOnFunction(Function &F); + }; +} + +char CFGSimplifyPass::ID = 0; +static RegisterPass X("simplifycfg", "Simplify the CFG"); + +// Public interface to the CFGSimplification pass +FunctionPass *llvm::createCFGSimplificationPass() { + return new CFGSimplifyPass(); +} + +/// ChangeToUnreachable - Insert an unreachable instruction before the specified +/// instruction, making it and the rest of the code in the block dead. +static void ChangeToUnreachable(Instruction *I) { + BasicBlock *BB = I->getParent(); + // Loop over all of the successors, removing BB's entry from any PHI + // nodes. + for (succ_iterator SI = succ_begin(BB), SE = succ_end(BB); SI != SE; ++SI) + (*SI)->removePredecessor(BB); + + new UnreachableInst(I->getContext(), I); + + // All instructions after this are dead. + BasicBlock::iterator BBI = I, BBE = BB->end(); + while (BBI != BBE) { + if (!BBI->use_empty()) + BBI->replaceAllUsesWith(UndefValue::get(BBI->getType())); + BB->getInstList().erase(BBI++); + } +} + +/// ChangeToCall - Convert the specified invoke into a normal call. +static void ChangeToCall(InvokeInst *II) { + BasicBlock *BB = II->getParent(); + SmallVector Args(II->op_begin()+3, II->op_end()); + CallInst *NewCall = CallInst::Create(II->getCalledValue(), Args.begin(), + Args.end(), "", II); + NewCall->takeName(II); + NewCall->setCallingConv(II->getCallingConv()); + NewCall->setAttributes(II->getAttributes()); + II->replaceAllUsesWith(NewCall); + + // Follow the call by a branch to the normal destination. + BranchInst::Create(II->getNormalDest(), II); + + // Update PHI nodes in the unwind destination + II->getUnwindDest()->removePredecessor(BB); + BB->getInstList().erase(II); +} + +static bool MarkAliveBlocks(BasicBlock *BB, + SmallPtrSet &Reachable) { + + SmallVector Worklist; + Worklist.push_back(BB); + bool Changed = false; + while (!Worklist.empty()) { + BB = Worklist.back(); + Worklist.pop_back(); + + if (!Reachable.insert(BB)) + continue; + + // Do a quick scan of the basic block, turning any obviously unreachable + // instructions into LLVM unreachable insts. The instruction combining pass + // canonicalizes unreachable insts into stores to null or undef. + for (BasicBlock::iterator BBI = BB->begin(), E = BB->end(); BBI != E;++BBI){ + if (CallInst *CI = dyn_cast(BBI)) { + if (CI->doesNotReturn()) { + // If we found a call to a no-return function, insert an unreachable + // instruction after it. Make sure there isn't *already* one there + // though. + ++BBI; + if (!isa(BBI)) { + ChangeToUnreachable(BBI); + Changed = true; + } + break; + } + } + + // Store to undef and store to null are undefined and used to signal that + // they should be changed to unreachable by passes that can't modify the + // CFG. + if (StoreInst *SI = dyn_cast(BBI)) { + Value *Ptr = SI->getOperand(1); + + if (isa(Ptr) || + (isa(Ptr) && + SI->getPointerAddressSpace() == 0)) { + ChangeToUnreachable(SI); + Changed = true; + break; + } + } + } + + // Turn invokes that call 'nounwind' functions into ordinary calls. + if (InvokeInst *II = dyn_cast(BB->getTerminator())) + if (II->doesNotThrow()) { + ChangeToCall(II); + Changed = true; + } + + Changed |= ConstantFoldTerminator(BB); + for (succ_iterator SI = succ_begin(BB), SE = succ_end(BB); SI != SE; ++SI) + Worklist.push_back(*SI); + } + return Changed; +} + +/// RemoveUnreachableBlocksFromFn - Remove blocks that are not reachable, even +/// if they are in a dead cycle. Return true if a change was made, false +/// otherwise. +static bool RemoveUnreachableBlocksFromFn(Function &F) { + SmallPtrSet Reachable; + bool Changed = MarkAliveBlocks(F.begin(), Reachable); + + // If there are unreachable blocks in the CFG... + if (Reachable.size() == F.size()) + return Changed; + + assert(Reachable.size() < F.size()); + NumSimpl += F.size()-Reachable.size(); + + // Loop over all of the basic blocks that are not reachable, dropping all of + // their internal references... + for (Function::iterator BB = ++F.begin(), E = F.end(); BB != E; ++BB) { + if (Reachable.count(BB)) + continue; + + for (succ_iterator SI = succ_begin(BB), SE = succ_end(BB); SI != SE; ++SI) + if (Reachable.count(*SI)) + (*SI)->removePredecessor(BB); + BB->dropAllReferences(); + } + + for (Function::iterator I = ++F.begin(); I != F.end();) + if (!Reachable.count(I)) + I = F.getBasicBlockList().erase(I); + else + ++I; + + return true; +} + +/// IterativeSimplifyCFG - Call SimplifyCFG on all the blocks in the function, +/// iterating until no more changes are made. +static bool IterativeSimplifyCFG(Function &F) { + bool Changed = false; + bool LocalChange = true; + while (LocalChange) { + LocalChange = false; + + // Loop over all of the basic blocks (except the first one) and remove them + // if they are unneeded... + // + for (Function::iterator BBIt = ++F.begin(); BBIt != F.end(); ) { + if (SimplifyCFG(BBIt++)) { + LocalChange = true; + ++NumSimpl; + } + } + Changed |= LocalChange; + } + return Changed; +} + +// It is possible that we may require multiple passes over the code to fully +// simplify the CFG. +// +bool CFGSimplifyPass::runOnFunction(Function &F) { + bool EverChanged = RemoveUnreachableBlocksFromFn(F); + EverChanged |= IterativeSimplifyCFG(F); + + // If neither pass changed anything, we're done. + if (!EverChanged) return false; + + // IterativeSimplifyCFG can (rarely) make some loops dead. If this happens, + // RemoveUnreachableBlocksFromFn is needed to nuke them, which means we should + // iterate between the two optimizations. We structure the code like this to + // avoid reruning IterativeSimplifyCFG if the second pass of + // RemoveUnreachableBlocksFromFn doesn't do anything. + if (!RemoveUnreachableBlocksFromFn(F)) + return true; + + do { + EverChanged = IterativeSimplifyCFG(F); + EverChanged |= RemoveUnreachableBlocksFromFn(F); + } while (EverChanged); + + return true; +} diff --git a/libclamav/c++/llvm/lib/Transforms/Scalar/SimplifyHalfPowrLibCalls.cpp b/libclamav/c++/llvm/lib/Transforms/Scalar/SimplifyHalfPowrLibCalls.cpp new file mode 100644 index 000000000..13077fe64 --- /dev/null +++ b/libclamav/c++/llvm/lib/Transforms/Scalar/SimplifyHalfPowrLibCalls.cpp @@ -0,0 +1,156 @@ +//===- SimplifyHalfPowrLibCalls.cpp - Optimize specific half_powr calls ---===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements a simple pass that applies an experimental +// transformation on calls to specific functions. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "simplify-libcalls-halfpowr" +#include "llvm/Transforms/Scalar.h" +#include "llvm/Instructions.h" +#include "llvm/Intrinsics.h" +#include "llvm/Module.h" +#include "llvm/Pass.h" +#include "llvm/Transforms/Utils/BasicBlockUtils.h" +#include "llvm/Transforms/Utils/Cloning.h" +#include "llvm/Target/TargetData.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/Support/Debug.h" +using namespace llvm; + +namespace { + /// This pass optimizes well half_powr function calls. + /// + class SimplifyHalfPowrLibCalls : public FunctionPass { + const TargetData *TD; + public: + static char ID; // Pass identification + SimplifyHalfPowrLibCalls() : FunctionPass(&ID) {} + + bool runOnFunction(Function &F); + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + } + + Instruction * + InlineHalfPowrs(const std::vector &HalfPowrs, + Instruction *InsertPt); + }; + char SimplifyHalfPowrLibCalls::ID = 0; +} // end anonymous namespace. + +static RegisterPass +X("simplify-libcalls-halfpowr", "Simplify half_powr library calls"); + +// Public interface to the Simplify HalfPowr LibCalls pass. +FunctionPass *llvm::createSimplifyHalfPowrLibCallsPass() { + return new SimplifyHalfPowrLibCalls(); +} + +/// InlineHalfPowrs - Inline a sequence of adjacent half_powr calls, rearranging +/// their control flow to better facilitate subsequent optimization. +Instruction * +SimplifyHalfPowrLibCalls:: +InlineHalfPowrs(const std::vector &HalfPowrs, + Instruction *InsertPt) { + std::vector Bodies; + BasicBlock *NewBlock = 0; + + for (unsigned i = 0, e = HalfPowrs.size(); i != e; ++i) { + CallInst *Call = cast(HalfPowrs[i]); + Function *Callee = Call->getCalledFunction(); + + // Minimally sanity-check the CFG of half_powr to ensure that it contains + // the the kind of code we expect. If we're running this pass, we have + // reason to believe it will be what we expect. + Function::iterator I = Callee->begin(); + BasicBlock *Prologue = I++; + if (I == Callee->end()) break; + BasicBlock *SubnormalHandling = I++; + if (I == Callee->end()) break; + BasicBlock *Body = I++; + if (I != Callee->end()) break; + if (SubnormalHandling->getSinglePredecessor() != Prologue) + break; + BranchInst *PBI = dyn_cast(Prologue->getTerminator()); + if (!PBI || !PBI->isConditional()) + break; + BranchInst *SNBI = dyn_cast(SubnormalHandling->getTerminator()); + if (!SNBI || SNBI->isConditional()) + break; + if (!isa(Body->getTerminator())) + break; + + Instruction *NextInst = next(BasicBlock::iterator(Call)); + + // Inline the call, taking care of what code ends up where. + NewBlock = SplitBlock(NextInst->getParent(), NextInst, this); + + bool B = InlineFunction(Call, 0, TD); + assert(B && "half_powr didn't inline?"); B=B; + + BasicBlock *NewBody = NewBlock->getSinglePredecessor(); + assert(NewBody); + Bodies.push_back(NewBody); + } + + if (!NewBlock) + return InsertPt; + + // Put the code for all the bodies into one block, to facilitate + // subsequent optimization. + (void)SplitEdge(NewBlock->getSinglePredecessor(), NewBlock, this); + for (unsigned i = 0, e = Bodies.size(); i != e; ++i) { + BasicBlock *Body = Bodies[i]; + Instruction *FNP = Body->getFirstNonPHI(); + // Splice the insts from body into NewBlock. + NewBlock->getInstList().splice(NewBlock->begin(), Body->getInstList(), + FNP, Body->getTerminator()); + } + + return NewBlock->begin(); +} + +/// runOnFunction - Top level algorithm. +/// +bool SimplifyHalfPowrLibCalls::runOnFunction(Function &F) { + TD = getAnalysisIfAvailable(); + + bool Changed = false; + std::vector HalfPowrs; + for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB) { + for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ++I) { + // Look for calls. + bool IsHalfPowr = false; + if (CallInst *CI = dyn_cast(I)) { + // Look for direct calls and calls to non-external functions. + Function *Callee = CI->getCalledFunction(); + if (Callee && Callee->hasExternalLinkage()) { + // Look for calls with well-known names. + if (Callee->getName() == "__half_powrf4") + IsHalfPowr = true; + } + } + if (IsHalfPowr) + HalfPowrs.push_back(I); + // We're looking for sequences of up to three such calls, which we'll + // simplify as a group. + if ((!IsHalfPowr && !HalfPowrs.empty()) || HalfPowrs.size() == 3) { + I = InlineHalfPowrs(HalfPowrs, I); + E = I->getParent()->end(); + HalfPowrs.clear(); + Changed = true; + } + } + assert(HalfPowrs.empty() && "Block had no terminator!"); + } + + return Changed; +} diff --git a/libclamav/c++/llvm/lib/Transforms/Scalar/SimplifyLibCalls.cpp b/libclamav/c++/llvm/lib/Transforms/Scalar/SimplifyLibCalls.cpp new file mode 100644 index 000000000..f9b929c7e --- /dev/null +++ b/libclamav/c++/llvm/lib/Transforms/Scalar/SimplifyLibCalls.cpp @@ -0,0 +1,2661 @@ +//===- SimplifyLibCalls.cpp - Optimize specific well-known library calls --===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements a simple pass that applies a variety of small +// optimizations for calls to specific well-known function calls (e.g. runtime +// library functions). Any optimization that takes the very simple form +// "replace call to library function with simpler code that provides the same +// result" belongs in this file. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "simplify-libcalls" +#include "llvm/Transforms/Scalar.h" +#include "llvm/Intrinsics.h" +#include "llvm/LLVMContext.h" +#include "llvm/Module.h" +#include "llvm/Pass.h" +#include "llvm/Support/IRBuilder.h" +#include "llvm/Analysis/ValueTracking.h" +#include "llvm/Target/TargetData.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Config/config.h" +using namespace llvm; + +STATISTIC(NumSimplified, "Number of library calls simplified"); +STATISTIC(NumAnnotated, "Number of attributes added to library functions"); + +//===----------------------------------------------------------------------===// +// Optimizer Base Class +//===----------------------------------------------------------------------===// + +/// This class is the abstract base class for the set of optimizations that +/// corresponds to one library call. +namespace { +class LibCallOptimization { +protected: + Function *Caller; + const TargetData *TD; + LLVMContext* Context; +public: + LibCallOptimization() { } + virtual ~LibCallOptimization() {} + + /// CallOptimizer - This pure virtual method is implemented by base classes to + /// do various optimizations. If this returns null then no transformation was + /// performed. If it returns CI, then it transformed the call and CI is to be + /// deleted. If it returns something else, replace CI with the new value and + /// delete CI. + virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) + =0; + + Value *OptimizeCall(CallInst *CI, const TargetData *TD, IRBuilder<> &B) { + Caller = CI->getParent()->getParent(); + this->TD = TD; + if (CI->getCalledFunction()) + Context = &CI->getCalledFunction()->getContext(); + return CallOptimizer(CI->getCalledFunction(), CI, B); + } + + /// CastToCStr - Return V if it is an i8*, otherwise cast it to i8*. + Value *CastToCStr(Value *V, IRBuilder<> &B); + + /// EmitStrLen - Emit a call to the strlen function to the builder, for the + /// specified pointer. Ptr is required to be some pointer type, and the + /// return value has 'intptr_t' type. + Value *EmitStrLen(Value *Ptr, IRBuilder<> &B); + + /// EmitMemCpy - Emit a call to the memcpy function to the builder. This + /// always expects that the size has type 'intptr_t' and Dst/Src are pointers. + Value *EmitMemCpy(Value *Dst, Value *Src, Value *Len, + unsigned Align, IRBuilder<> &B); + + /// EmitMemMove - Emit a call to the memmove function to the builder. This + /// always expects that the size has type 'intptr_t' and Dst/Src are pointers. + Value *EmitMemMove(Value *Dst, Value *Src, Value *Len, + unsigned Align, IRBuilder<> &B); + + /// EmitMemChr - Emit a call to the memchr function. This assumes that Ptr is + /// a pointer, Val is an i32 value, and Len is an 'intptr_t' value. + Value *EmitMemChr(Value *Ptr, Value *Val, Value *Len, IRBuilder<> &B); + + /// EmitMemCmp - Emit a call to the memcmp function. + Value *EmitMemCmp(Value *Ptr1, Value *Ptr2, Value *Len, IRBuilder<> &B); + + /// EmitMemSet - Emit a call to the memset function + Value *EmitMemSet(Value *Dst, Value *Val, Value *Len, IRBuilder<> &B); + + /// EmitUnaryFloatFnCall - Emit a call to the unary function named 'Name' (e.g. + /// 'floor'). This function is known to take a single of type matching 'Op' + /// and returns one value with the same type. If 'Op' is a long double, 'l' + /// is added as the suffix of name, if 'Op' is a float, we add a 'f' suffix. + Value *EmitUnaryFloatFnCall(Value *Op, const char *Name, IRBuilder<> &B, + const AttrListPtr &Attrs); + + /// EmitPutChar - Emit a call to the putchar function. This assumes that Char + /// is an integer. + Value *EmitPutChar(Value *Char, IRBuilder<> &B); + + /// EmitPutS - Emit a call to the puts function. This assumes that Str is + /// some pointer. + void EmitPutS(Value *Str, IRBuilder<> &B); + + /// EmitFPutC - Emit a call to the fputc function. This assumes that Char is + /// an i32, and File is a pointer to FILE. + void EmitFPutC(Value *Char, Value *File, IRBuilder<> &B); + + /// EmitFPutS - Emit a call to the puts function. Str is required to be a + /// pointer and File is a pointer to FILE. + void EmitFPutS(Value *Str, Value *File, IRBuilder<> &B); + + /// EmitFWrite - Emit a call to the fwrite function. This assumes that Ptr is + /// a pointer, Size is an 'intptr_t', and File is a pointer to FILE. + void EmitFWrite(Value *Ptr, Value *Size, Value *File, IRBuilder<> &B); + +}; +} // End anonymous namespace. + +/// CastToCStr - Return V if it is an i8*, otherwise cast it to i8*. +Value *LibCallOptimization::CastToCStr(Value *V, IRBuilder<> &B) { + return + B.CreateBitCast(V, Type::getInt8PtrTy(*Context), "cstr"); +} + +/// EmitStrLen - Emit a call to the strlen function to the builder, for the +/// specified pointer. This always returns an integer value of size intptr_t. +Value *LibCallOptimization::EmitStrLen(Value *Ptr, IRBuilder<> &B) { + Module *M = Caller->getParent(); + AttributeWithIndex AWI[2]; + AWI[0] = AttributeWithIndex::get(1, Attribute::NoCapture); + AWI[1] = AttributeWithIndex::get(~0u, Attribute::ReadOnly | + Attribute::NoUnwind); + + Constant *StrLen =M->getOrInsertFunction("strlen", AttrListPtr::get(AWI, 2), + TD->getIntPtrType(*Context), + Type::getInt8PtrTy(*Context), + NULL); + CallInst *CI = B.CreateCall(StrLen, CastToCStr(Ptr, B), "strlen"); + if (const Function *F = dyn_cast(StrLen->stripPointerCasts())) + CI->setCallingConv(F->getCallingConv()); + + return CI; +} + +/// EmitMemCpy - Emit a call to the memcpy function to the builder. This always +/// expects that the size has type 'intptr_t' and Dst/Src are pointers. +Value *LibCallOptimization::EmitMemCpy(Value *Dst, Value *Src, Value *Len, + unsigned Align, IRBuilder<> &B) { + Module *M = Caller->getParent(); + Intrinsic::ID IID = Intrinsic::memcpy; + const Type *Tys[1]; + Tys[0] = Len->getType(); + Value *MemCpy = Intrinsic::getDeclaration(M, IID, Tys, 1); + return B.CreateCall4(MemCpy, CastToCStr(Dst, B), CastToCStr(Src, B), Len, + ConstantInt::get(Type::getInt32Ty(*Context), Align)); +} + +/// EmitMemMOve - Emit a call to the memmove function to the builder. This +/// always expects that the size has type 'intptr_t' and Dst/Src are pointers. +Value *LibCallOptimization::EmitMemMove(Value *Dst, Value *Src, Value *Len, + unsigned Align, IRBuilder<> &B) { + Module *M = Caller->getParent(); + Intrinsic::ID IID = Intrinsic::memmove; + const Type *Tys[1]; + Tys[0] = TD->getIntPtrType(*Context); + Value *MemMove = Intrinsic::getDeclaration(M, IID, Tys, 1); + Value *D = CastToCStr(Dst, B); + Value *S = CastToCStr(Src, B); + Value *A = ConstantInt::get(Type::getInt32Ty(*Context), Align); + return B.CreateCall4(MemMove, D, S, Len, A); +} + +/// EmitMemChr - Emit a call to the memchr function. This assumes that Ptr is +/// a pointer, Val is an i32 value, and Len is an 'intptr_t' value. +Value *LibCallOptimization::EmitMemChr(Value *Ptr, Value *Val, + Value *Len, IRBuilder<> &B) { + Module *M = Caller->getParent(); + AttributeWithIndex AWI; + AWI = AttributeWithIndex::get(~0u, Attribute::ReadOnly | Attribute::NoUnwind); + + Value *MemChr = M->getOrInsertFunction("memchr", AttrListPtr::get(&AWI, 1), + Type::getInt8PtrTy(*Context), + Type::getInt8PtrTy(*Context), + Type::getInt32Ty(*Context), + TD->getIntPtrType(*Context), + NULL); + CallInst *CI = B.CreateCall3(MemChr, CastToCStr(Ptr, B), Val, Len, "memchr"); + + if (const Function *F = dyn_cast(MemChr->stripPointerCasts())) + CI->setCallingConv(F->getCallingConv()); + + return CI; +} + +/// EmitMemCmp - Emit a call to the memcmp function. +Value *LibCallOptimization::EmitMemCmp(Value *Ptr1, Value *Ptr2, + Value *Len, IRBuilder<> &B) { + Module *M = Caller->getParent(); + AttributeWithIndex AWI[3]; + AWI[0] = AttributeWithIndex::get(1, Attribute::NoCapture); + AWI[1] = AttributeWithIndex::get(2, Attribute::NoCapture); + AWI[2] = AttributeWithIndex::get(~0u, Attribute::ReadOnly | + Attribute::NoUnwind); + + Value *MemCmp = M->getOrInsertFunction("memcmp", AttrListPtr::get(AWI, 3), + Type::getInt32Ty(*Context), + Type::getInt8PtrTy(*Context), + Type::getInt8PtrTy(*Context), + TD->getIntPtrType(*Context), NULL); + CallInst *CI = B.CreateCall3(MemCmp, CastToCStr(Ptr1, B), CastToCStr(Ptr2, B), + Len, "memcmp"); + + if (const Function *F = dyn_cast(MemCmp->stripPointerCasts())) + CI->setCallingConv(F->getCallingConv()); + + return CI; +} + +/// EmitMemSet - Emit a call to the memset function +Value *LibCallOptimization::EmitMemSet(Value *Dst, Value *Val, + Value *Len, IRBuilder<> &B) { + Module *M = Caller->getParent(); + Intrinsic::ID IID = Intrinsic::memset; + const Type *Tys[1]; + Tys[0] = Len->getType(); + Value *MemSet = Intrinsic::getDeclaration(M, IID, Tys, 1); + Value *Align = ConstantInt::get(Type::getInt32Ty(*Context), 1); + return B.CreateCall4(MemSet, CastToCStr(Dst, B), Val, Len, Align); +} + +/// EmitUnaryFloatFnCall - Emit a call to the unary function named 'Name' (e.g. +/// 'floor'). This function is known to take a single of type matching 'Op' and +/// returns one value with the same type. If 'Op' is a long double, 'l' is +/// added as the suffix of name, if 'Op' is a float, we add a 'f' suffix. +Value *LibCallOptimization::EmitUnaryFloatFnCall(Value *Op, const char *Name, + IRBuilder<> &B, + const AttrListPtr &Attrs) { + char NameBuffer[20]; + if (!Op->getType()->isDoubleTy()) { + // If we need to add a suffix, copy into NameBuffer. + unsigned NameLen = strlen(Name); + assert(NameLen < sizeof(NameBuffer)-2); + memcpy(NameBuffer, Name, NameLen); + if (Op->getType()->isFloatTy()) + NameBuffer[NameLen] = 'f'; // floorf + else + NameBuffer[NameLen] = 'l'; // floorl + NameBuffer[NameLen+1] = 0; + Name = NameBuffer; + } + + Module *M = Caller->getParent(); + Value *Callee = M->getOrInsertFunction(Name, Op->getType(), + Op->getType(), NULL); + CallInst *CI = B.CreateCall(Callee, Op, Name); + CI->setAttributes(Attrs); + if (const Function *F = dyn_cast(Callee->stripPointerCasts())) + CI->setCallingConv(F->getCallingConv()); + + return CI; +} + +/// EmitPutChar - Emit a call to the putchar function. This assumes that Char +/// is an integer. +Value *LibCallOptimization::EmitPutChar(Value *Char, IRBuilder<> &B) { + Module *M = Caller->getParent(); + Value *PutChar = M->getOrInsertFunction("putchar", Type::getInt32Ty(*Context), + Type::getInt32Ty(*Context), NULL); + CallInst *CI = B.CreateCall(PutChar, + B.CreateIntCast(Char, + Type::getInt32Ty(*Context), + /*isSigned*/true, + "chari"), + "putchar"); + + if (const Function *F = dyn_cast(PutChar->stripPointerCasts())) + CI->setCallingConv(F->getCallingConv()); + return CI; +} + +/// EmitPutS - Emit a call to the puts function. This assumes that Str is +/// some pointer. +void LibCallOptimization::EmitPutS(Value *Str, IRBuilder<> &B) { + Module *M = Caller->getParent(); + AttributeWithIndex AWI[2]; + AWI[0] = AttributeWithIndex::get(1, Attribute::NoCapture); + AWI[1] = AttributeWithIndex::get(~0u, Attribute::NoUnwind); + + Value *PutS = M->getOrInsertFunction("puts", AttrListPtr::get(AWI, 2), + Type::getInt32Ty(*Context), + Type::getInt8PtrTy(*Context), + NULL); + CallInst *CI = B.CreateCall(PutS, CastToCStr(Str, B), "puts"); + if (const Function *F = dyn_cast(PutS->stripPointerCasts())) + CI->setCallingConv(F->getCallingConv()); + +} + +/// EmitFPutC - Emit a call to the fputc function. This assumes that Char is +/// an integer and File is a pointer to FILE. +void LibCallOptimization::EmitFPutC(Value *Char, Value *File, IRBuilder<> &B) { + Module *M = Caller->getParent(); + AttributeWithIndex AWI[2]; + AWI[0] = AttributeWithIndex::get(2, Attribute::NoCapture); + AWI[1] = AttributeWithIndex::get(~0u, Attribute::NoUnwind); + Constant *F; + if (isa(File->getType())) + F = M->getOrInsertFunction("fputc", AttrListPtr::get(AWI, 2), + Type::getInt32Ty(*Context), + Type::getInt32Ty(*Context), File->getType(), + NULL); + else + F = M->getOrInsertFunction("fputc", + Type::getInt32Ty(*Context), + Type::getInt32Ty(*Context), + File->getType(), NULL); + Char = B.CreateIntCast(Char, Type::getInt32Ty(*Context), /*isSigned*/true, + "chari"); + CallInst *CI = B.CreateCall2(F, Char, File, "fputc"); + + if (const Function *Fn = dyn_cast(F->stripPointerCasts())) + CI->setCallingConv(Fn->getCallingConv()); +} + +/// EmitFPutS - Emit a call to the puts function. Str is required to be a +/// pointer and File is a pointer to FILE. +void LibCallOptimization::EmitFPutS(Value *Str, Value *File, IRBuilder<> &B) { + Module *M = Caller->getParent(); + AttributeWithIndex AWI[3]; + AWI[0] = AttributeWithIndex::get(1, Attribute::NoCapture); + AWI[1] = AttributeWithIndex::get(2, Attribute::NoCapture); + AWI[2] = AttributeWithIndex::get(~0u, Attribute::NoUnwind); + Constant *F; + if (isa(File->getType())) + F = M->getOrInsertFunction("fputs", AttrListPtr::get(AWI, 3), + Type::getInt32Ty(*Context), + Type::getInt8PtrTy(*Context), + File->getType(), NULL); + else + F = M->getOrInsertFunction("fputs", Type::getInt32Ty(*Context), + Type::getInt8PtrTy(*Context), + File->getType(), NULL); + CallInst *CI = B.CreateCall2(F, CastToCStr(Str, B), File, "fputs"); + + if (const Function *Fn = dyn_cast(F->stripPointerCasts())) + CI->setCallingConv(Fn->getCallingConv()); +} + +/// EmitFWrite - Emit a call to the fwrite function. This assumes that Ptr is +/// a pointer, Size is an 'intptr_t', and File is a pointer to FILE. +void LibCallOptimization::EmitFWrite(Value *Ptr, Value *Size, Value *File, + IRBuilder<> &B) { + Module *M = Caller->getParent(); + AttributeWithIndex AWI[3]; + AWI[0] = AttributeWithIndex::get(1, Attribute::NoCapture); + AWI[1] = AttributeWithIndex::get(4, Attribute::NoCapture); + AWI[2] = AttributeWithIndex::get(~0u, Attribute::NoUnwind); + Constant *F; + if (isa(File->getType())) + F = M->getOrInsertFunction("fwrite", AttrListPtr::get(AWI, 3), + TD->getIntPtrType(*Context), + Type::getInt8PtrTy(*Context), + TD->getIntPtrType(*Context), + TD->getIntPtrType(*Context), + File->getType(), NULL); + else + F = M->getOrInsertFunction("fwrite", TD->getIntPtrType(*Context), + Type::getInt8PtrTy(*Context), + TD->getIntPtrType(*Context), + TD->getIntPtrType(*Context), + File->getType(), NULL); + CallInst *CI = B.CreateCall4(F, CastToCStr(Ptr, B), Size, + ConstantInt::get(TD->getIntPtrType(*Context), 1), File); + + if (const Function *Fn = dyn_cast(F->stripPointerCasts())) + CI->setCallingConv(Fn->getCallingConv()); +} + +//===----------------------------------------------------------------------===// +// Helper Functions +//===----------------------------------------------------------------------===// + +/// GetStringLengthH - If we can compute the length of the string pointed to by +/// the specified pointer, return 'len+1'. If we can't, return 0. +static uint64_t GetStringLengthH(Value *V, SmallPtrSet &PHIs) { + // Look through noop bitcast instructions. + if (BitCastInst *BCI = dyn_cast(V)) + return GetStringLengthH(BCI->getOperand(0), PHIs); + + // If this is a PHI node, there are two cases: either we have already seen it + // or we haven't. + if (PHINode *PN = dyn_cast(V)) { + if (!PHIs.insert(PN)) + return ~0ULL; // already in the set. + + // If it was new, see if all the input strings are the same length. + uint64_t LenSoFar = ~0ULL; + for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) { + uint64_t Len = GetStringLengthH(PN->getIncomingValue(i), PHIs); + if (Len == 0) return 0; // Unknown length -> unknown. + + if (Len == ~0ULL) continue; + + if (Len != LenSoFar && LenSoFar != ~0ULL) + return 0; // Disagree -> unknown. + LenSoFar = Len; + } + + // Success, all agree. + return LenSoFar; + } + + // strlen(select(c,x,y)) -> strlen(x) ^ strlen(y) + if (SelectInst *SI = dyn_cast(V)) { + uint64_t Len1 = GetStringLengthH(SI->getTrueValue(), PHIs); + if (Len1 == 0) return 0; + uint64_t Len2 = GetStringLengthH(SI->getFalseValue(), PHIs); + if (Len2 == 0) return 0; + if (Len1 == ~0ULL) return Len2; + if (Len2 == ~0ULL) return Len1; + if (Len1 != Len2) return 0; + return Len1; + } + + // If the value is not a GEP instruction nor a constant expression with a + // GEP instruction, then return unknown. + User *GEP = 0; + if (GetElementPtrInst *GEPI = dyn_cast(V)) { + GEP = GEPI; + } else if (ConstantExpr *CE = dyn_cast(V)) { + if (CE->getOpcode() != Instruction::GetElementPtr) + return 0; + GEP = CE; + } else { + return 0; + } + + // Make sure the GEP has exactly three arguments. + if (GEP->getNumOperands() != 3) + return 0; + + // Check to make sure that the first operand of the GEP is an integer and + // has value 0 so that we are sure we're indexing into the initializer. + if (ConstantInt *Idx = dyn_cast(GEP->getOperand(1))) { + if (!Idx->isZero()) + return 0; + } else + return 0; + + // If the second index isn't a ConstantInt, then this is a variable index + // into the array. If this occurs, we can't say anything meaningful about + // the string. + uint64_t StartIdx = 0; + if (ConstantInt *CI = dyn_cast(GEP->getOperand(2))) + StartIdx = CI->getZExtValue(); + else + return 0; + + // The GEP instruction, constant or instruction, must reference a global + // variable that is a constant and is initialized. The referenced constant + // initializer is the array that we'll use for optimization. + GlobalVariable* GV = dyn_cast(GEP->getOperand(0)); + if (!GV || !GV->isConstant() || !GV->hasInitializer() || + GV->mayBeOverridden()) + return 0; + Constant *GlobalInit = GV->getInitializer(); + + // Handle the ConstantAggregateZero case, which is a degenerate case. The + // initializer is constant zero so the length of the string must be zero. + if (isa(GlobalInit)) + return 1; // Len = 0 offset by 1. + + // Must be a Constant Array + ConstantArray *Array = dyn_cast(GlobalInit); + if (!Array || + Array->getType()->getElementType() != Type::getInt8Ty(V->getContext())) + return false; + + // Get the number of elements in the array + uint64_t NumElts = Array->getType()->getNumElements(); + + // Traverse the constant array from StartIdx (derived above) which is + // the place the GEP refers to in the array. + for (unsigned i = StartIdx; i != NumElts; ++i) { + Constant *Elt = Array->getOperand(i); + ConstantInt *CI = dyn_cast(Elt); + if (!CI) // This array isn't suitable, non-int initializer. + return 0; + if (CI->isZero()) + return i-StartIdx+1; // We found end of string, success! + } + + return 0; // The array isn't null terminated, conservatively return 'unknown'. +} + +/// GetStringLength - If we can compute the length of the string pointed to by +/// the specified pointer, return 'len+1'. If we can't, return 0. +static uint64_t GetStringLength(Value *V) { + if (!isa(V->getType())) return 0; + + SmallPtrSet PHIs; + uint64_t Len = GetStringLengthH(V, PHIs); + // If Len is ~0ULL, we had an infinite phi cycle: this is dead code, so return + // an empty string as a length. + return Len == ~0ULL ? 1 : Len; +} + +/// IsOnlyUsedInZeroEqualityComparison - Return true if it only matters that the +/// value is equal or not-equal to zero. +static bool IsOnlyUsedInZeroEqualityComparison(Value *V) { + for (Value::use_iterator UI = V->use_begin(), E = V->use_end(); + UI != E; ++UI) { + if (ICmpInst *IC = dyn_cast(*UI)) + if (IC->isEquality()) + if (Constant *C = dyn_cast(IC->getOperand(1))) + if (C->isNullValue()) + continue; + // Unknown instruction. + return false; + } + return true; +} + +//===----------------------------------------------------------------------===// +// String and Memory LibCall Optimizations +//===----------------------------------------------------------------------===// + +//===---------------------------------------===// +// 'strcat' Optimizations +namespace { +struct StrCatOpt : public LibCallOptimization { + virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) { + // Verify the "strcat" function prototype. + const FunctionType *FT = Callee->getFunctionType(); + if (FT->getNumParams() != 2 || + FT->getReturnType() != Type::getInt8PtrTy(*Context) || + FT->getParamType(0) != FT->getReturnType() || + FT->getParamType(1) != FT->getReturnType()) + return 0; + + // Extract some information from the instruction + Value *Dst = CI->getOperand(1); + Value *Src = CI->getOperand(2); + + // See if we can get the length of the input string. + uint64_t Len = GetStringLength(Src); + if (Len == 0) return 0; + --Len; // Unbias length. + + // Handle the simple, do-nothing case: strcat(x, "") -> x + if (Len == 0) + return Dst; + + // These optimizations require TargetData. + if (!TD) return 0; + + EmitStrLenMemCpy(Src, Dst, Len, B); + return Dst; + } + + void EmitStrLenMemCpy(Value *Src, Value *Dst, uint64_t Len, IRBuilder<> &B) { + // We need to find the end of the destination string. That's where the + // memory is to be moved to. We just generate a call to strlen. + Value *DstLen = EmitStrLen(Dst, B); + + // Now that we have the destination's length, we must index into the + // destination's pointer to get the actual memcpy destination (end of + // the string .. we're concatenating). + Value *CpyDst = B.CreateGEP(Dst, DstLen, "endptr"); + + // We have enough information to now generate the memcpy call to do the + // concatenation for us. Make a memcpy to copy the nul byte with align = 1. + EmitMemCpy(CpyDst, Src, + ConstantInt::get(TD->getIntPtrType(*Context), Len+1), 1, B); + } +}; + +//===---------------------------------------===// +// 'strncat' Optimizations + +struct StrNCatOpt : public StrCatOpt { + virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) { + // Verify the "strncat" function prototype. + const FunctionType *FT = Callee->getFunctionType(); + if (FT->getNumParams() != 3 || + FT->getReturnType() != Type::getInt8PtrTy(*Context) || + FT->getParamType(0) != FT->getReturnType() || + FT->getParamType(1) != FT->getReturnType() || + !isa(FT->getParamType(2))) + return 0; + + // Extract some information from the instruction + Value *Dst = CI->getOperand(1); + Value *Src = CI->getOperand(2); + uint64_t Len; + + // We don't do anything if length is not constant + if (ConstantInt *LengthArg = dyn_cast(CI->getOperand(3))) + Len = LengthArg->getZExtValue(); + else + return 0; + + // See if we can get the length of the input string. + uint64_t SrcLen = GetStringLength(Src); + if (SrcLen == 0) return 0; + --SrcLen; // Unbias length. + + // Handle the simple, do-nothing cases: + // strncat(x, "", c) -> x + // strncat(x, c, 0) -> x + if (SrcLen == 0 || Len == 0) return Dst; + + // These optimizations require TargetData. + if (!TD) return 0; + + // We don't optimize this case + if (Len < SrcLen) return 0; + + // strncat(x, s, c) -> strcat(x, s) + // s is constant so the strcat can be optimized further + EmitStrLenMemCpy(Src, Dst, SrcLen, B); + return Dst; + } +}; + +//===---------------------------------------===// +// 'strchr' Optimizations + +struct StrChrOpt : public LibCallOptimization { + virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) { + // Verify the "strchr" function prototype. + const FunctionType *FT = Callee->getFunctionType(); + if (FT->getNumParams() != 2 || + FT->getReturnType() != Type::getInt8PtrTy(*Context) || + FT->getParamType(0) != FT->getReturnType()) + return 0; + + Value *SrcStr = CI->getOperand(1); + + // If the second operand is non-constant, see if we can compute the length + // of the input string and turn this into memchr. + ConstantInt *CharC = dyn_cast(CI->getOperand(2)); + if (CharC == 0) { + // These optimizations require TargetData. + if (!TD) return 0; + + uint64_t Len = GetStringLength(SrcStr); + if (Len == 0 || + FT->getParamType(1) != Type::getInt32Ty(*Context)) // memchr needs i32. + return 0; + + return EmitMemChr(SrcStr, CI->getOperand(2), // include nul. + ConstantInt::get(TD->getIntPtrType(*Context), Len), B); + } + + // Otherwise, the character is a constant, see if the first argument is + // a string literal. If so, we can constant fold. + std::string Str; + if (!GetConstantStringInfo(SrcStr, Str)) + return 0; + + // strchr can find the nul character. + Str += '\0'; + char CharValue = CharC->getSExtValue(); + + // Compute the offset. + uint64_t i = 0; + while (1) { + if (i == Str.size()) // Didn't find the char. strchr returns null. + return Constant::getNullValue(CI->getType()); + // Did we find our match? + if (Str[i] == CharValue) + break; + ++i; + } + + // strchr(s+n,c) -> gep(s+n+i,c) + Value *Idx = ConstantInt::get(Type::getInt64Ty(*Context), i); + return B.CreateGEP(SrcStr, Idx, "strchr"); + } +}; + +//===---------------------------------------===// +// 'strcmp' Optimizations + +struct StrCmpOpt : public LibCallOptimization { + virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) { + // Verify the "strcmp" function prototype. + const FunctionType *FT = Callee->getFunctionType(); + if (FT->getNumParams() != 2 || + FT->getReturnType() != Type::getInt32Ty(*Context) || + FT->getParamType(0) != FT->getParamType(1) || + FT->getParamType(0) != Type::getInt8PtrTy(*Context)) + return 0; + + Value *Str1P = CI->getOperand(1), *Str2P = CI->getOperand(2); + if (Str1P == Str2P) // strcmp(x,x) -> 0 + return ConstantInt::get(CI->getType(), 0); + + std::string Str1, Str2; + bool HasStr1 = GetConstantStringInfo(Str1P, Str1); + bool HasStr2 = GetConstantStringInfo(Str2P, Str2); + + if (HasStr1 && Str1.empty()) // strcmp("", x) -> *x + return B.CreateZExt(B.CreateLoad(Str2P, "strcmpload"), CI->getType()); + + if (HasStr2 && Str2.empty()) // strcmp(x,"") -> *x + return B.CreateZExt(B.CreateLoad(Str1P, "strcmpload"), CI->getType()); + + // strcmp(x, y) -> cnst (if both x and y are constant strings) + if (HasStr1 && HasStr2) + return ConstantInt::get(CI->getType(), + strcmp(Str1.c_str(),Str2.c_str())); + + // strcmp(P, "x") -> memcmp(P, "x", 2) + uint64_t Len1 = GetStringLength(Str1P); + uint64_t Len2 = GetStringLength(Str2P); + if (Len1 && Len2) { + // These optimizations require TargetData. + if (!TD) return 0; + + return EmitMemCmp(Str1P, Str2P, + ConstantInt::get(TD->getIntPtrType(*Context), + std::min(Len1, Len2)), B); + } + + return 0; + } +}; + +//===---------------------------------------===// +// 'strncmp' Optimizations + +struct StrNCmpOpt : public LibCallOptimization { + virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) { + // Verify the "strncmp" function prototype. + const FunctionType *FT = Callee->getFunctionType(); + if (FT->getNumParams() != 3 || + FT->getReturnType() != Type::getInt32Ty(*Context) || + FT->getParamType(0) != FT->getParamType(1) || + FT->getParamType(0) != Type::getInt8PtrTy(*Context) || + !isa(FT->getParamType(2))) + return 0; + + Value *Str1P = CI->getOperand(1), *Str2P = CI->getOperand(2); + if (Str1P == Str2P) // strncmp(x,x,n) -> 0 + return ConstantInt::get(CI->getType(), 0); + + // Get the length argument if it is constant. + uint64_t Length; + if (ConstantInt *LengthArg = dyn_cast(CI->getOperand(3))) + Length = LengthArg->getZExtValue(); + else + return 0; + + if (Length == 0) // strncmp(x,y,0) -> 0 + return ConstantInt::get(CI->getType(), 0); + + std::string Str1, Str2; + bool HasStr1 = GetConstantStringInfo(Str1P, Str1); + bool HasStr2 = GetConstantStringInfo(Str2P, Str2); + + if (HasStr1 && Str1.empty()) // strncmp("", x, n) -> *x + return B.CreateZExt(B.CreateLoad(Str2P, "strcmpload"), CI->getType()); + + if (HasStr2 && Str2.empty()) // strncmp(x, "", n) -> *x + return B.CreateZExt(B.CreateLoad(Str1P, "strcmpload"), CI->getType()); + + // strncmp(x, y) -> cnst (if both x and y are constant strings) + if (HasStr1 && HasStr2) + return ConstantInt::get(CI->getType(), + strncmp(Str1.c_str(), Str2.c_str(), Length)); + return 0; + } +}; + + +//===---------------------------------------===// +// 'strcpy' Optimizations + +struct StrCpyOpt : public LibCallOptimization { + virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) { + // Verify the "strcpy" function prototype. + const FunctionType *FT = Callee->getFunctionType(); + if (FT->getNumParams() != 2 || FT->getReturnType() != FT->getParamType(0) || + FT->getParamType(0) != FT->getParamType(1) || + FT->getParamType(0) != Type::getInt8PtrTy(*Context)) + return 0; + + Value *Dst = CI->getOperand(1), *Src = CI->getOperand(2); + if (Dst == Src) // strcpy(x,x) -> x + return Src; + + // These optimizations require TargetData. + if (!TD) return 0; + + // See if we can get the length of the input string. + uint64_t Len = GetStringLength(Src); + if (Len == 0) return 0; + + // We have enough information to now generate the memcpy call to do the + // concatenation for us. Make a memcpy to copy the nul byte with align = 1. + EmitMemCpy(Dst, Src, + ConstantInt::get(TD->getIntPtrType(*Context), Len), 1, B); + return Dst; + } +}; + +//===---------------------------------------===// +// 'strncpy' Optimizations + +struct StrNCpyOpt : public LibCallOptimization { + virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) { + const FunctionType *FT = Callee->getFunctionType(); + if (FT->getNumParams() != 3 || FT->getReturnType() != FT->getParamType(0) || + FT->getParamType(0) != FT->getParamType(1) || + FT->getParamType(0) != Type::getInt8PtrTy(*Context) || + !isa(FT->getParamType(2))) + return 0; + + Value *Dst = CI->getOperand(1); + Value *Src = CI->getOperand(2); + Value *LenOp = CI->getOperand(3); + + // See if we can get the length of the input string. + uint64_t SrcLen = GetStringLength(Src); + if (SrcLen == 0) return 0; + --SrcLen; + + if (SrcLen == 0) { + // strncpy(x, "", y) -> memset(x, '\0', y, 1) + EmitMemSet(Dst, ConstantInt::get(Type::getInt8Ty(*Context), '\0'), LenOp, + B); + return Dst; + } + + uint64_t Len; + if (ConstantInt *LengthArg = dyn_cast(LenOp)) + Len = LengthArg->getZExtValue(); + else + return 0; + + if (Len == 0) return Dst; // strncpy(x, y, 0) -> x + + // These optimizations require TargetData. + if (!TD) return 0; + + // Let strncpy handle the zero padding + if (Len > SrcLen+1) return 0; + + // strncpy(x, s, c) -> memcpy(x, s, c, 1) [s and c are constant] + EmitMemCpy(Dst, Src, + ConstantInt::get(TD->getIntPtrType(*Context), Len), 1, B); + + return Dst; + } +}; + +//===---------------------------------------===// +// 'strlen' Optimizations + +struct StrLenOpt : public LibCallOptimization { + virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) { + const FunctionType *FT = Callee->getFunctionType(); + if (FT->getNumParams() != 1 || + FT->getParamType(0) != Type::getInt8PtrTy(*Context) || + !isa(FT->getReturnType())) + return 0; + + Value *Src = CI->getOperand(1); + + // Constant folding: strlen("xyz") -> 3 + if (uint64_t Len = GetStringLength(Src)) + return ConstantInt::get(CI->getType(), Len-1); + + // Handle strlen(p) != 0. + if (!IsOnlyUsedInZeroEqualityComparison(CI)) return 0; + + // strlen(x) != 0 --> *x != 0 + // strlen(x) == 0 --> *x == 0 + return B.CreateZExt(B.CreateLoad(Src, "strlenfirst"), CI->getType()); + } +}; + +//===---------------------------------------===// +// 'strto*' Optimizations + +struct StrToOpt : public LibCallOptimization { + virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) { + const FunctionType *FT = Callee->getFunctionType(); + if ((FT->getNumParams() != 2 && FT->getNumParams() != 3) || + !isa(FT->getParamType(0)) || + !isa(FT->getParamType(1))) + return 0; + + Value *EndPtr = CI->getOperand(2); + if (isa(EndPtr)) { + CI->setOnlyReadsMemory(); + CI->addAttribute(1, Attribute::NoCapture); + } + + return 0; + } +}; + + +//===---------------------------------------===// +// 'memcmp' Optimizations + +struct MemCmpOpt : public LibCallOptimization { + virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) { + const FunctionType *FT = Callee->getFunctionType(); + if (FT->getNumParams() != 3 || !isa(FT->getParamType(0)) || + !isa(FT->getParamType(1)) || + FT->getReturnType() != Type::getInt32Ty(*Context)) + return 0; + + Value *LHS = CI->getOperand(1), *RHS = CI->getOperand(2); + + if (LHS == RHS) // memcmp(s,s,x) -> 0 + return Constant::getNullValue(CI->getType()); + + // Make sure we have a constant length. + ConstantInt *LenC = dyn_cast(CI->getOperand(3)); + if (!LenC) return 0; + uint64_t Len = LenC->getZExtValue(); + + if (Len == 0) // memcmp(s1,s2,0) -> 0 + return Constant::getNullValue(CI->getType()); + + if (Len == 1) { // memcmp(S1,S2,1) -> *LHS - *RHS + Value *LHSV = B.CreateLoad(CastToCStr(LHS, B), "lhsv"); + Value *RHSV = B.CreateLoad(CastToCStr(RHS, B), "rhsv"); + return B.CreateSExt(B.CreateSub(LHSV, RHSV, "chardiff"), CI->getType()); + } + + // memcmp(S1,S2,2) != 0 -> (*(short*)LHS ^ *(short*)RHS) != 0 + // memcmp(S1,S2,4) != 0 -> (*(int*)LHS ^ *(int*)RHS) != 0 + if ((Len == 2 || Len == 4) && IsOnlyUsedInZeroEqualityComparison(CI)) { + const Type *PTy = PointerType::getUnqual(Len == 2 ? + Type::getInt16Ty(*Context) : Type::getInt32Ty(*Context)); + LHS = B.CreateBitCast(LHS, PTy, "tmp"); + RHS = B.CreateBitCast(RHS, PTy, "tmp"); + LoadInst *LHSV = B.CreateLoad(LHS, "lhsv"); + LoadInst *RHSV = B.CreateLoad(RHS, "rhsv"); + LHSV->setAlignment(1); RHSV->setAlignment(1); // Unaligned loads. + return B.CreateZExt(B.CreateXor(LHSV, RHSV, "shortdiff"), CI->getType()); + } + + // Constant folding: memcmp(x, y, l) -> cnst (all arguments are constant) + std::string LHSStr, RHSStr; + if (GetConstantStringInfo(LHS, LHSStr) && + GetConstantStringInfo(RHS, RHSStr)) { + // Make sure we're not reading out-of-bounds memory. + if (Len > LHSStr.length() || Len > RHSStr.length()) + return 0; + uint64_t Ret = memcmp(LHSStr.data(), RHSStr.data(), Len); + return ConstantInt::get(CI->getType(), Ret); + } + + return 0; + } +}; + +//===---------------------------------------===// +// 'memcpy' Optimizations + +struct MemCpyOpt : public LibCallOptimization { + virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) { + // These optimizations require TargetData. + if (!TD) return 0; + + const FunctionType *FT = Callee->getFunctionType(); + if (FT->getNumParams() != 3 || FT->getReturnType() != FT->getParamType(0) || + !isa(FT->getParamType(0)) || + !isa(FT->getParamType(1)) || + FT->getParamType(2) != TD->getIntPtrType(*Context)) + return 0; + + // memcpy(x, y, n) -> llvm.memcpy(x, y, n, 1) + EmitMemCpy(CI->getOperand(1), CI->getOperand(2), CI->getOperand(3), 1, B); + return CI->getOperand(1); + } +}; + +//===---------------------------------------===// +// 'memmove' Optimizations + +struct MemMoveOpt : public LibCallOptimization { + virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) { + // These optimizations require TargetData. + if (!TD) return 0; + + const FunctionType *FT = Callee->getFunctionType(); + if (FT->getNumParams() != 3 || FT->getReturnType() != FT->getParamType(0) || + !isa(FT->getParamType(0)) || + !isa(FT->getParamType(1)) || + FT->getParamType(2) != TD->getIntPtrType(*Context)) + return 0; + + // memmove(x, y, n) -> llvm.memmove(x, y, n, 1) + EmitMemMove(CI->getOperand(1), CI->getOperand(2), CI->getOperand(3), 1, B); + return CI->getOperand(1); + } +}; + +//===---------------------------------------===// +// 'memset' Optimizations + +struct MemSetOpt : public LibCallOptimization { + virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) { + // These optimizations require TargetData. + if (!TD) return 0; + + const FunctionType *FT = Callee->getFunctionType(); + if (FT->getNumParams() != 3 || FT->getReturnType() != FT->getParamType(0) || + !isa(FT->getParamType(0)) || + !isa(FT->getParamType(1)) || + FT->getParamType(2) != TD->getIntPtrType(*Context)) + return 0; + + // memset(p, v, n) -> llvm.memset(p, v, n, 1) + Value *Val = B.CreateIntCast(CI->getOperand(2), Type::getInt8Ty(*Context), + false); + EmitMemSet(CI->getOperand(1), Val, CI->getOperand(3), B); + return CI->getOperand(1); + } +}; + +//===----------------------------------------------------------------------===// +// Object Size Checking Optimizations +//===----------------------------------------------------------------------===// + +//===---------------------------------------===// +// 'object size' +namespace { +struct SizeOpt : public LibCallOptimization { + virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) { + // TODO: We can do more with this, but delaying to here should be no change + // in behavior. + ConstantInt *Const = dyn_cast(CI->getOperand(2)); + + if (!Const) return 0; + + const Type *Ty = Callee->getFunctionType()->getReturnType(); + + if (Const->getZExtValue() < 2) + return Constant::getAllOnesValue(Ty); + else + return ConstantInt::get(Ty, 0); + } +}; +} + +//===---------------------------------------===// +// 'memcpy_chk' Optimizations + +struct MemCpyChkOpt : public LibCallOptimization { + virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) { + // These optimizations require TargetData. + if (!TD) return 0; + + const FunctionType *FT = Callee->getFunctionType(); + if (FT->getNumParams() != 4 || FT->getReturnType() != FT->getParamType(0) || + !isa(FT->getParamType(0)) || + !isa(FT->getParamType(1)) || + !isa(FT->getParamType(3)) || + FT->getParamType(2) != TD->getIntPtrType(*Context)) + return 0; + + ConstantInt *SizeCI = dyn_cast(CI->getOperand(4)); + if (!SizeCI) + return 0; + if (SizeCI->isAllOnesValue()) { + EmitMemCpy(CI->getOperand(1), CI->getOperand(2), CI->getOperand(3), 1, B); + return CI->getOperand(1); + } + + return 0; + } +}; + +//===---------------------------------------===// +// 'memset_chk' Optimizations + +struct MemSetChkOpt : public LibCallOptimization { + virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) { + // These optimizations require TargetData. + if (!TD) return 0; + + const FunctionType *FT = Callee->getFunctionType(); + if (FT->getNumParams() != 4 || FT->getReturnType() != FT->getParamType(0) || + !isa(FT->getParamType(0)) || + !isa(FT->getParamType(1)) || + !isa(FT->getParamType(3)) || + FT->getParamType(2) != TD->getIntPtrType(*Context)) + return 0; + + ConstantInt *SizeCI = dyn_cast(CI->getOperand(4)); + if (!SizeCI) + return 0; + if (SizeCI->isAllOnesValue()) { + Value *Val = B.CreateIntCast(CI->getOperand(2), Type::getInt8Ty(*Context), + false); + EmitMemSet(CI->getOperand(1), Val, CI->getOperand(3), B); + return CI->getOperand(1); + } + + return 0; + } +}; + +//===---------------------------------------===// +// 'memmove_chk' Optimizations + +struct MemMoveChkOpt : public LibCallOptimization { + virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) { + // These optimizations require TargetData. + if (!TD) return 0; + + const FunctionType *FT = Callee->getFunctionType(); + if (FT->getNumParams() != 4 || FT->getReturnType() != FT->getParamType(0) || + !isa(FT->getParamType(0)) || + !isa(FT->getParamType(1)) || + !isa(FT->getParamType(3)) || + FT->getParamType(2) != TD->getIntPtrType(*Context)) + return 0; + + ConstantInt *SizeCI = dyn_cast(CI->getOperand(4)); + if (!SizeCI) + return 0; + if (SizeCI->isAllOnesValue()) { + EmitMemMove(CI->getOperand(1), CI->getOperand(2), CI->getOperand(3), + 1, B); + return CI->getOperand(1); + } + + return 0; + } +}; + +//===----------------------------------------------------------------------===// +// Math Library Optimizations +//===----------------------------------------------------------------------===// + +//===---------------------------------------===// +// 'pow*' Optimizations + +struct PowOpt : public LibCallOptimization { + virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) { + const FunctionType *FT = Callee->getFunctionType(); + // Just make sure this has 2 arguments of the same FP type, which match the + // result type. + if (FT->getNumParams() != 2 || FT->getReturnType() != FT->getParamType(0) || + FT->getParamType(0) != FT->getParamType(1) || + !FT->getParamType(0)->isFloatingPoint()) + return 0; + + Value *Op1 = CI->getOperand(1), *Op2 = CI->getOperand(2); + if (ConstantFP *Op1C = dyn_cast(Op1)) { + if (Op1C->isExactlyValue(1.0)) // pow(1.0, x) -> 1.0 + return Op1C; + if (Op1C->isExactlyValue(2.0)) // pow(2.0, x) -> exp2(x) + return EmitUnaryFloatFnCall(Op2, "exp2", B, Callee->getAttributes()); + } + + ConstantFP *Op2C = dyn_cast(Op2); + if (Op2C == 0) return 0; + + if (Op2C->getValueAPF().isZero()) // pow(x, 0.0) -> 1.0 + return ConstantFP::get(CI->getType(), 1.0); + + if (Op2C->isExactlyValue(0.5)) { + // Expand pow(x, 0.5) to (x == -infinity ? +infinity : fabs(sqrt(x))). + // This is faster than calling pow, and still handles negative zero + // and negative infinite correctly. + // TODO: In fast-math mode, this could be just sqrt(x). + // TODO: In finite-only mode, this could be just fabs(sqrt(x)). + Value *Inf = ConstantFP::getInfinity(CI->getType()); + Value *NegInf = ConstantFP::getInfinity(CI->getType(), true); + Value *Sqrt = EmitUnaryFloatFnCall(Op1, "sqrt", B, + Callee->getAttributes()); + Value *FAbs = EmitUnaryFloatFnCall(Sqrt, "fabs", B, + Callee->getAttributes()); + Value *FCmp = B.CreateFCmpOEQ(Op1, NegInf, "tmp"); + Value *Sel = B.CreateSelect(FCmp, Inf, FAbs, "tmp"); + return Sel; + } + + if (Op2C->isExactlyValue(1.0)) // pow(x, 1.0) -> x + return Op1; + if (Op2C->isExactlyValue(2.0)) // pow(x, 2.0) -> x*x + return B.CreateFMul(Op1, Op1, "pow2"); + if (Op2C->isExactlyValue(-1.0)) // pow(x, -1.0) -> 1.0/x + return B.CreateFDiv(ConstantFP::get(CI->getType(), 1.0), + Op1, "powrecip"); + return 0; + } +}; + +//===---------------------------------------===// +// 'exp2' Optimizations + +struct Exp2Opt : public LibCallOptimization { + virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) { + const FunctionType *FT = Callee->getFunctionType(); + // Just make sure this has 1 argument of FP type, which matches the + // result type. + if (FT->getNumParams() != 1 || FT->getReturnType() != FT->getParamType(0) || + !FT->getParamType(0)->isFloatingPoint()) + return 0; + + Value *Op = CI->getOperand(1); + // Turn exp2(sitofp(x)) -> ldexp(1.0, sext(x)) if sizeof(x) <= 32 + // Turn exp2(uitofp(x)) -> ldexp(1.0, zext(x)) if sizeof(x) < 32 + Value *LdExpArg = 0; + if (SIToFPInst *OpC = dyn_cast(Op)) { + if (OpC->getOperand(0)->getType()->getPrimitiveSizeInBits() <= 32) + LdExpArg = B.CreateSExt(OpC->getOperand(0), + Type::getInt32Ty(*Context), "tmp"); + } else if (UIToFPInst *OpC = dyn_cast(Op)) { + if (OpC->getOperand(0)->getType()->getPrimitiveSizeInBits() < 32) + LdExpArg = B.CreateZExt(OpC->getOperand(0), + Type::getInt32Ty(*Context), "tmp"); + } + + if (LdExpArg) { + const char *Name; + if (Op->getType()->isFloatTy()) + Name = "ldexpf"; + else if (Op->getType()->isDoubleTy()) + Name = "ldexp"; + else + Name = "ldexpl"; + + Constant *One = ConstantFP::get(*Context, APFloat(1.0f)); + if (!Op->getType()->isFloatTy()) + One = ConstantExpr::getFPExtend(One, Op->getType()); + + Module *M = Caller->getParent(); + Value *Callee = M->getOrInsertFunction(Name, Op->getType(), + Op->getType(), + Type::getInt32Ty(*Context),NULL); + CallInst *CI = B.CreateCall2(Callee, One, LdExpArg); + if (const Function *F = dyn_cast(Callee->stripPointerCasts())) + CI->setCallingConv(F->getCallingConv()); + + return CI; + } + return 0; + } +}; + +//===---------------------------------------===// +// Double -> Float Shrinking Optimizations for Unary Functions like 'floor' + +struct UnaryDoubleFPOpt : public LibCallOptimization { + virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) { + const FunctionType *FT = Callee->getFunctionType(); + if (FT->getNumParams() != 1 || !FT->getReturnType()->isDoubleTy() || + !FT->getParamType(0)->isDoubleTy()) + return 0; + + // If this is something like 'floor((double)floatval)', convert to floorf. + FPExtInst *Cast = dyn_cast(CI->getOperand(1)); + if (Cast == 0 || !Cast->getOperand(0)->getType()->isFloatTy()) + return 0; + + // floor((double)floatval) -> (double)floorf(floatval) + Value *V = Cast->getOperand(0); + V = EmitUnaryFloatFnCall(V, Callee->getName().data(), B, + Callee->getAttributes()); + return B.CreateFPExt(V, Type::getDoubleTy(*Context)); + } +}; + +//===----------------------------------------------------------------------===// +// Integer Optimizations +//===----------------------------------------------------------------------===// + +//===---------------------------------------===// +// 'ffs*' Optimizations + +struct FFSOpt : public LibCallOptimization { + virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) { + const FunctionType *FT = Callee->getFunctionType(); + // Just make sure this has 2 arguments of the same FP type, which match the + // result type. + if (FT->getNumParams() != 1 || + FT->getReturnType() != Type::getInt32Ty(*Context) || + !isa(FT->getParamType(0))) + return 0; + + Value *Op = CI->getOperand(1); + + // Constant fold. + if (ConstantInt *CI = dyn_cast(Op)) { + if (CI->getValue() == 0) // ffs(0) -> 0. + return Constant::getNullValue(CI->getType()); + return ConstantInt::get(Type::getInt32Ty(*Context), // ffs(c) -> cttz(c)+1 + CI->getValue().countTrailingZeros()+1); + } + + // ffs(x) -> x != 0 ? (i32)llvm.cttz(x)+1 : 0 + const Type *ArgType = Op->getType(); + Value *F = Intrinsic::getDeclaration(Callee->getParent(), + Intrinsic::cttz, &ArgType, 1); + Value *V = B.CreateCall(F, Op, "cttz"); + V = B.CreateAdd(V, ConstantInt::get(V->getType(), 1), "tmp"); + V = B.CreateIntCast(V, Type::getInt32Ty(*Context), false, "tmp"); + + Value *Cond = B.CreateICmpNE(Op, Constant::getNullValue(ArgType), "tmp"); + return B.CreateSelect(Cond, V, + ConstantInt::get(Type::getInt32Ty(*Context), 0)); + } +}; + +//===---------------------------------------===// +// 'isdigit' Optimizations + +struct IsDigitOpt : public LibCallOptimization { + virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) { + const FunctionType *FT = Callee->getFunctionType(); + // We require integer(i32) + if (FT->getNumParams() != 1 || !isa(FT->getReturnType()) || + FT->getParamType(0) != Type::getInt32Ty(*Context)) + return 0; + + // isdigit(c) -> (c-'0') getOperand(1); + Op = B.CreateSub(Op, ConstantInt::get(Type::getInt32Ty(*Context), '0'), + "isdigittmp"); + Op = B.CreateICmpULT(Op, ConstantInt::get(Type::getInt32Ty(*Context), 10), + "isdigit"); + return B.CreateZExt(Op, CI->getType()); + } +}; + +//===---------------------------------------===// +// 'isascii' Optimizations + +struct IsAsciiOpt : public LibCallOptimization { + virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) { + const FunctionType *FT = Callee->getFunctionType(); + // We require integer(i32) + if (FT->getNumParams() != 1 || !isa(FT->getReturnType()) || + FT->getParamType(0) != Type::getInt32Ty(*Context)) + return 0; + + // isascii(c) -> c getOperand(1); + Op = B.CreateICmpULT(Op, ConstantInt::get(Type::getInt32Ty(*Context), 128), + "isascii"); + return B.CreateZExt(Op, CI->getType()); + } +}; + +//===---------------------------------------===// +// 'abs', 'labs', 'llabs' Optimizations + +struct AbsOpt : public LibCallOptimization { + virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) { + const FunctionType *FT = Callee->getFunctionType(); + // We require integer(integer) where the types agree. + if (FT->getNumParams() != 1 || !isa(FT->getReturnType()) || + FT->getParamType(0) != FT->getReturnType()) + return 0; + + // abs(x) -> x >s -1 ? x : -x + Value *Op = CI->getOperand(1); + Value *Pos = B.CreateICmpSGT(Op, + Constant::getAllOnesValue(Op->getType()), + "ispos"); + Value *Neg = B.CreateNeg(Op, "neg"); + return B.CreateSelect(Pos, Op, Neg); + } +}; + + +//===---------------------------------------===// +// 'toascii' Optimizations + +struct ToAsciiOpt : public LibCallOptimization { + virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) { + const FunctionType *FT = Callee->getFunctionType(); + // We require i32(i32) + if (FT->getNumParams() != 1 || FT->getReturnType() != FT->getParamType(0) || + FT->getParamType(0) != Type::getInt32Ty(*Context)) + return 0; + + // isascii(c) -> c & 0x7f + return B.CreateAnd(CI->getOperand(1), + ConstantInt::get(CI->getType(),0x7F)); + } +}; + +//===----------------------------------------------------------------------===// +// Formatting and IO Optimizations +//===----------------------------------------------------------------------===// + +//===---------------------------------------===// +// 'printf' Optimizations + +struct PrintFOpt : public LibCallOptimization { + virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) { + // Require one fixed pointer argument and an integer/void result. + const FunctionType *FT = Callee->getFunctionType(); + if (FT->getNumParams() < 1 || !isa(FT->getParamType(0)) || + !(isa(FT->getReturnType()) || + FT->getReturnType()->isVoidTy())) + return 0; + + // Check for a fixed format string. + std::string FormatStr; + if (!GetConstantStringInfo(CI->getOperand(1), FormatStr)) + return 0; + + // Empty format string -> noop. + if (FormatStr.empty()) // Tolerate printf's declared void. + return CI->use_empty() ? (Value*)CI : + ConstantInt::get(CI->getType(), 0); + + // printf("x") -> putchar('x'), even for '%'. Return the result of putchar + // in case there is an error writing to stdout. + if (FormatStr.size() == 1) { + Value *Res = EmitPutChar(ConstantInt::get(Type::getInt32Ty(*Context), + FormatStr[0]), B); + if (CI->use_empty()) return CI; + return B.CreateIntCast(Res, CI->getType(), true); + } + + // printf("foo\n") --> puts("foo") + if (FormatStr[FormatStr.size()-1] == '\n' && + FormatStr.find('%') == std::string::npos) { // no format characters. + // Create a string literal with no \n on it. We expect the constant merge + // pass to be run after this pass, to merge duplicate strings. + FormatStr.erase(FormatStr.end()-1); + Constant *C = ConstantArray::get(*Context, FormatStr, true); + C = new GlobalVariable(*Callee->getParent(), C->getType(), true, + GlobalVariable::InternalLinkage, C, "str"); + EmitPutS(C, B); + return CI->use_empty() ? (Value*)CI : + ConstantInt::get(CI->getType(), FormatStr.size()+1); + } + + // Optimize specific format strings. + // printf("%c", chr) --> putchar(*(i8*)dst) + if (FormatStr == "%c" && CI->getNumOperands() > 2 && + isa(CI->getOperand(2)->getType())) { + Value *Res = EmitPutChar(CI->getOperand(2), B); + + if (CI->use_empty()) return CI; + return B.CreateIntCast(Res, CI->getType(), true); + } + + // printf("%s\n", str) --> puts(str) + if (FormatStr == "%s\n" && CI->getNumOperands() > 2 && + isa(CI->getOperand(2)->getType()) && + CI->use_empty()) { + EmitPutS(CI->getOperand(2), B); + return CI; + } + return 0; + } +}; + +//===---------------------------------------===// +// 'sprintf' Optimizations + +struct SPrintFOpt : public LibCallOptimization { + virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) { + // Require two fixed pointer arguments and an integer result. + const FunctionType *FT = Callee->getFunctionType(); + if (FT->getNumParams() != 2 || !isa(FT->getParamType(0)) || + !isa(FT->getParamType(1)) || + !isa(FT->getReturnType())) + return 0; + + // Check for a fixed format string. + std::string FormatStr; + if (!GetConstantStringInfo(CI->getOperand(2), FormatStr)) + return 0; + + // If we just have a format string (nothing else crazy) transform it. + if (CI->getNumOperands() == 3) { + // Make sure there's no % in the constant array. We could try to handle + // %% -> % in the future if we cared. + for (unsigned i = 0, e = FormatStr.size(); i != e; ++i) + if (FormatStr[i] == '%') + return 0; // we found a format specifier, bail out. + + // These optimizations require TargetData. + if (!TD) return 0; + + // sprintf(str, fmt) -> llvm.memcpy(str, fmt, strlen(fmt)+1, 1) + EmitMemCpy(CI->getOperand(1), CI->getOperand(2), // Copy the nul byte. + ConstantInt::get(TD->getIntPtrType(*Context), FormatStr.size()+1),1,B); + return ConstantInt::get(CI->getType(), FormatStr.size()); + } + + // The remaining optimizations require the format string to be "%s" or "%c" + // and have an extra operand. + if (FormatStr.size() != 2 || FormatStr[0] != '%' || CI->getNumOperands() <4) + return 0; + + // Decode the second character of the format string. + if (FormatStr[1] == 'c') { + // sprintf(dst, "%c", chr) --> *(i8*)dst = chr; *((i8*)dst+1) = 0 + if (!isa(CI->getOperand(3)->getType())) return 0; + Value *V = B.CreateTrunc(CI->getOperand(3), + Type::getInt8Ty(*Context), "char"); + Value *Ptr = CastToCStr(CI->getOperand(1), B); + B.CreateStore(V, Ptr); + Ptr = B.CreateGEP(Ptr, ConstantInt::get(Type::getInt32Ty(*Context), 1), + "nul"); + B.CreateStore(Constant::getNullValue(Type::getInt8Ty(*Context)), Ptr); + + return ConstantInt::get(CI->getType(), 1); + } + + if (FormatStr[1] == 's') { + // These optimizations require TargetData. + if (!TD) return 0; + + // sprintf(dest, "%s", str) -> llvm.memcpy(dest, str, strlen(str)+1, 1) + if (!isa(CI->getOperand(3)->getType())) return 0; + + Value *Len = EmitStrLen(CI->getOperand(3), B); + Value *IncLen = B.CreateAdd(Len, + ConstantInt::get(Len->getType(), 1), + "leninc"); + EmitMemCpy(CI->getOperand(1), CI->getOperand(3), IncLen, 1, B); + + // The sprintf result is the unincremented number of bytes in the string. + return B.CreateIntCast(Len, CI->getType(), false); + } + return 0; + } +}; + +//===---------------------------------------===// +// 'fwrite' Optimizations + +struct FWriteOpt : public LibCallOptimization { + virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) { + // Require a pointer, an integer, an integer, a pointer, returning integer. + const FunctionType *FT = Callee->getFunctionType(); + if (FT->getNumParams() != 4 || !isa(FT->getParamType(0)) || + !isa(FT->getParamType(1)) || + !isa(FT->getParamType(2)) || + !isa(FT->getParamType(3)) || + !isa(FT->getReturnType())) + return 0; + + // Get the element size and count. + ConstantInt *SizeC = dyn_cast(CI->getOperand(2)); + ConstantInt *CountC = dyn_cast(CI->getOperand(3)); + if (!SizeC || !CountC) return 0; + uint64_t Bytes = SizeC->getZExtValue()*CountC->getZExtValue(); + + // If this is writing zero records, remove the call (it's a noop). + if (Bytes == 0) + return ConstantInt::get(CI->getType(), 0); + + // If this is writing one byte, turn it into fputc. + if (Bytes == 1) { // fwrite(S,1,1,F) -> fputc(S[0],F) + Value *Char = B.CreateLoad(CastToCStr(CI->getOperand(1), B), "char"); + EmitFPutC(Char, CI->getOperand(4), B); + return ConstantInt::get(CI->getType(), 1); + } + + return 0; + } +}; + +//===---------------------------------------===// +// 'fputs' Optimizations + +struct FPutsOpt : public LibCallOptimization { + virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) { + // These optimizations require TargetData. + if (!TD) return 0; + + // Require two pointers. Also, we can't optimize if return value is used. + const FunctionType *FT = Callee->getFunctionType(); + if (FT->getNumParams() != 2 || !isa(FT->getParamType(0)) || + !isa(FT->getParamType(1)) || + !CI->use_empty()) + return 0; + + // fputs(s,F) --> fwrite(s,1,strlen(s),F) + uint64_t Len = GetStringLength(CI->getOperand(1)); + if (!Len) return 0; + EmitFWrite(CI->getOperand(1), + ConstantInt::get(TD->getIntPtrType(*Context), Len-1), + CI->getOperand(2), B); + return CI; // Known to have no uses (see above). + } +}; + +//===---------------------------------------===// +// 'fprintf' Optimizations + +struct FPrintFOpt : public LibCallOptimization { + virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) { + // Require two fixed paramters as pointers and integer result. + const FunctionType *FT = Callee->getFunctionType(); + if (FT->getNumParams() != 2 || !isa(FT->getParamType(0)) || + !isa(FT->getParamType(1)) || + !isa(FT->getReturnType())) + return 0; + + // All the optimizations depend on the format string. + std::string FormatStr; + if (!GetConstantStringInfo(CI->getOperand(2), FormatStr)) + return 0; + + // fprintf(F, "foo") --> fwrite("foo", 3, 1, F) + if (CI->getNumOperands() == 3) { + for (unsigned i = 0, e = FormatStr.size(); i != e; ++i) + if (FormatStr[i] == '%') // Could handle %% -> % if we cared. + return 0; // We found a format specifier. + + // These optimizations require TargetData. + if (!TD) return 0; + + EmitFWrite(CI->getOperand(2), ConstantInt::get(TD->getIntPtrType(*Context), + FormatStr.size()), + CI->getOperand(1), B); + return ConstantInt::get(CI->getType(), FormatStr.size()); + } + + // The remaining optimizations require the format string to be "%s" or "%c" + // and have an extra operand. + if (FormatStr.size() != 2 || FormatStr[0] != '%' || CI->getNumOperands() <4) + return 0; + + // Decode the second character of the format string. + if (FormatStr[1] == 'c') { + // fprintf(F, "%c", chr) --> *(i8*)dst = chr + if (!isa(CI->getOperand(3)->getType())) return 0; + EmitFPutC(CI->getOperand(3), CI->getOperand(1), B); + return ConstantInt::get(CI->getType(), 1); + } + + if (FormatStr[1] == 's') { + // fprintf(F, "%s", str) -> fputs(str, F) + if (!isa(CI->getOperand(3)->getType()) || !CI->use_empty()) + return 0; + EmitFPutS(CI->getOperand(3), CI->getOperand(1), B); + return CI; + } + return 0; + } +}; + +} // end anonymous namespace. + +//===----------------------------------------------------------------------===// +// SimplifyLibCalls Pass Implementation +//===----------------------------------------------------------------------===// + +namespace { + /// This pass optimizes well known library functions from libc and libm. + /// + class SimplifyLibCalls : public FunctionPass { + StringMap Optimizations; + // String and Memory LibCall Optimizations + StrCatOpt StrCat; StrNCatOpt StrNCat; StrChrOpt StrChr; StrCmpOpt StrCmp; + StrNCmpOpt StrNCmp; StrCpyOpt StrCpy; StrNCpyOpt StrNCpy; StrLenOpt StrLen; + StrToOpt StrTo; MemCmpOpt MemCmp; MemCpyOpt MemCpy; MemMoveOpt MemMove; + MemSetOpt MemSet; + // Math Library Optimizations + PowOpt Pow; Exp2Opt Exp2; UnaryDoubleFPOpt UnaryDoubleFP; + // Integer Optimizations + FFSOpt FFS; AbsOpt Abs; IsDigitOpt IsDigit; IsAsciiOpt IsAscii; + ToAsciiOpt ToAscii; + // Formatting and IO Optimizations + SPrintFOpt SPrintF; PrintFOpt PrintF; + FWriteOpt FWrite; FPutsOpt FPuts; FPrintFOpt FPrintF; + + // Object Size Checking + SizeOpt ObjectSize; + MemCpyChkOpt MemCpyChk; MemSetChkOpt MemSetChk; MemMoveChkOpt MemMoveChk; + + bool Modified; // This is only used by doInitialization. + public: + static char ID; // Pass identification + SimplifyLibCalls() : FunctionPass(&ID) {} + + void InitOptimizations(); + bool runOnFunction(Function &F); + + void setDoesNotAccessMemory(Function &F); + void setOnlyReadsMemory(Function &F); + void setDoesNotThrow(Function &F); + void setDoesNotCapture(Function &F, unsigned n); + void setDoesNotAlias(Function &F, unsigned n); + bool doInitialization(Module &M); + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + } + }; + char SimplifyLibCalls::ID = 0; +} // end anonymous namespace. + +static RegisterPass +X("simplify-libcalls", "Simplify well-known library calls"); + +// Public interface to the Simplify LibCalls pass. +FunctionPass *llvm::createSimplifyLibCallsPass() { + return new SimplifyLibCalls(); +} + +/// Optimizations - Populate the Optimizations map with all the optimizations +/// we know. +void SimplifyLibCalls::InitOptimizations() { + // String and Memory LibCall Optimizations + Optimizations["strcat"] = &StrCat; + Optimizations["strncat"] = &StrNCat; + Optimizations["strchr"] = &StrChr; + Optimizations["strcmp"] = &StrCmp; + Optimizations["strncmp"] = &StrNCmp; + Optimizations["strcpy"] = &StrCpy; + Optimizations["strncpy"] = &StrNCpy; + Optimizations["strlen"] = &StrLen; + Optimizations["strtol"] = &StrTo; + Optimizations["strtod"] = &StrTo; + Optimizations["strtof"] = &StrTo; + Optimizations["strtoul"] = &StrTo; + Optimizations["strtoll"] = &StrTo; + Optimizations["strtold"] = &StrTo; + Optimizations["strtoull"] = &StrTo; + Optimizations["memcmp"] = &MemCmp; + Optimizations["memcpy"] = &MemCpy; + Optimizations["memmove"] = &MemMove; + Optimizations["memset"] = &MemSet; + + // Math Library Optimizations + Optimizations["powf"] = &Pow; + Optimizations["pow"] = &Pow; + Optimizations["powl"] = &Pow; + Optimizations["llvm.pow.f32"] = &Pow; + Optimizations["llvm.pow.f64"] = &Pow; + Optimizations["llvm.pow.f80"] = &Pow; + Optimizations["llvm.pow.f128"] = &Pow; + Optimizations["llvm.pow.ppcf128"] = &Pow; + Optimizations["exp2l"] = &Exp2; + Optimizations["exp2"] = &Exp2; + Optimizations["exp2f"] = &Exp2; + Optimizations["llvm.exp2.ppcf128"] = &Exp2; + Optimizations["llvm.exp2.f128"] = &Exp2; + Optimizations["llvm.exp2.f80"] = &Exp2; + Optimizations["llvm.exp2.f64"] = &Exp2; + Optimizations["llvm.exp2.f32"] = &Exp2; + +#ifdef HAVE_FLOORF + Optimizations["floor"] = &UnaryDoubleFP; +#endif +#ifdef HAVE_CEILF + Optimizations["ceil"] = &UnaryDoubleFP; +#endif +#ifdef HAVE_ROUNDF + Optimizations["round"] = &UnaryDoubleFP; +#endif +#ifdef HAVE_RINTF + Optimizations["rint"] = &UnaryDoubleFP; +#endif +#ifdef HAVE_NEARBYINTF + Optimizations["nearbyint"] = &UnaryDoubleFP; +#endif + + // Integer Optimizations + Optimizations["ffs"] = &FFS; + Optimizations["ffsl"] = &FFS; + Optimizations["ffsll"] = &FFS; + Optimizations["abs"] = &Abs; + Optimizations["labs"] = &Abs; + Optimizations["llabs"] = &Abs; + Optimizations["isdigit"] = &IsDigit; + Optimizations["isascii"] = &IsAscii; + Optimizations["toascii"] = &ToAscii; + + // Formatting and IO Optimizations + Optimizations["sprintf"] = &SPrintF; + Optimizations["printf"] = &PrintF; + Optimizations["fwrite"] = &FWrite; + Optimizations["fputs"] = &FPuts; + Optimizations["fprintf"] = &FPrintF; + + // Object Size Checking + Optimizations["llvm.objectsize.i32"] = &ObjectSize; + Optimizations["llvm.objectsize.i64"] = &ObjectSize; + Optimizations["__memcpy_chk"] = &MemCpyChk; + Optimizations["__memset_chk"] = &MemSetChk; + Optimizations["__memmove_chk"] = &MemMoveChk; +} + + +/// runOnFunction - Top level algorithm. +/// +bool SimplifyLibCalls::runOnFunction(Function &F) { + if (Optimizations.empty()) + InitOptimizations(); + + const TargetData *TD = getAnalysisIfAvailable(); + + IRBuilder<> Builder(F.getContext()); + + bool Changed = false; + for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB) { + for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ) { + // Ignore non-calls. + CallInst *CI = dyn_cast(I++); + if (!CI) continue; + + // Ignore indirect calls and calls to non-external functions. + Function *Callee = CI->getCalledFunction(); + if (Callee == 0 || !Callee->isDeclaration() || + !(Callee->hasExternalLinkage() || Callee->hasDLLImportLinkage())) + continue; + + // Ignore unknown calls. + LibCallOptimization *LCO = Optimizations.lookup(Callee->getName()); + if (!LCO) continue; + + // Set the builder to the instruction after the call. + Builder.SetInsertPoint(BB, I); + + // Try to optimize this call. + Value *Result = LCO->OptimizeCall(CI, TD, Builder); + if (Result == 0) continue; + + DEBUG(errs() << "SimplifyLibCalls simplified: " << *CI; + errs() << " into: " << *Result << "\n"); + + // Something changed! + Changed = true; + ++NumSimplified; + + // Inspect the instruction after the call (which was potentially just + // added) next. + I = CI; ++I; + + if (CI != Result && !CI->use_empty()) { + CI->replaceAllUsesWith(Result); + if (!Result->hasName()) + Result->takeName(CI); + } + CI->eraseFromParent(); + } + } + return Changed; +} + +// Utility methods for doInitialization. + +void SimplifyLibCalls::setDoesNotAccessMemory(Function &F) { + if (!F.doesNotAccessMemory()) { + F.setDoesNotAccessMemory(); + ++NumAnnotated; + Modified = true; + } +} +void SimplifyLibCalls::setOnlyReadsMemory(Function &F) { + if (!F.onlyReadsMemory()) { + F.setOnlyReadsMemory(); + ++NumAnnotated; + Modified = true; + } +} +void SimplifyLibCalls::setDoesNotThrow(Function &F) { + if (!F.doesNotThrow()) { + F.setDoesNotThrow(); + ++NumAnnotated; + Modified = true; + } +} +void SimplifyLibCalls::setDoesNotCapture(Function &F, unsigned n) { + if (!F.doesNotCapture(n)) { + F.setDoesNotCapture(n); + ++NumAnnotated; + Modified = true; + } +} +void SimplifyLibCalls::setDoesNotAlias(Function &F, unsigned n) { + if (!F.doesNotAlias(n)) { + F.setDoesNotAlias(n); + ++NumAnnotated; + Modified = true; + } +} + +/// doInitialization - Add attributes to well-known functions. +/// +bool SimplifyLibCalls::doInitialization(Module &M) { + Modified = false; + for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) { + Function &F = *I; + if (!F.isDeclaration()) + continue; + + if (!F.hasName()) + continue; + + const FunctionType *FTy = F.getFunctionType(); + + StringRef Name = F.getName(); + switch (Name[0]) { + case 's': + if (Name == "strlen") { + if (FTy->getNumParams() != 1 || + !isa(FTy->getParamType(0))) + continue; + setOnlyReadsMemory(F); + setDoesNotThrow(F); + setDoesNotCapture(F, 1); + } else if (Name == "strcpy" || + Name == "stpcpy" || + Name == "strcat" || + Name == "strtol" || + Name == "strtod" || + Name == "strtof" || + Name == "strtoul" || + Name == "strtoll" || + Name == "strtold" || + Name == "strncat" || + Name == "strncpy" || + Name == "strtoull") { + if (FTy->getNumParams() < 2 || + !isa(FTy->getParamType(1))) + continue; + setDoesNotThrow(F); + setDoesNotCapture(F, 2); + } else if (Name == "strxfrm") { + if (FTy->getNumParams() != 3 || + !isa(FTy->getParamType(0)) || + !isa(FTy->getParamType(1))) + continue; + setDoesNotThrow(F); + setDoesNotCapture(F, 1); + setDoesNotCapture(F, 2); + } else if (Name == "strcmp" || + Name == "strspn" || + Name == "strncmp" || + Name ==" strcspn" || + Name == "strcoll" || + Name == "strcasecmp" || + Name == "strncasecmp") { + if (FTy->getNumParams() < 2 || + !isa(FTy->getParamType(0)) || + !isa(FTy->getParamType(1))) + continue; + setOnlyReadsMemory(F); + setDoesNotThrow(F); + setDoesNotCapture(F, 1); + setDoesNotCapture(F, 2); + } else if (Name == "strstr" || + Name == "strpbrk") { + if (FTy->getNumParams() != 2 || + !isa(FTy->getParamType(1))) + continue; + setOnlyReadsMemory(F); + setDoesNotThrow(F); + setDoesNotCapture(F, 2); + } else if (Name == "strtok" || + Name == "strtok_r") { + if (FTy->getNumParams() < 2 || + !isa(FTy->getParamType(1))) + continue; + setDoesNotThrow(F); + setDoesNotCapture(F, 2); + } else if (Name == "scanf" || + Name == "setbuf" || + Name == "setvbuf") { + if (FTy->getNumParams() < 1 || + !isa(FTy->getParamType(0))) + continue; + setDoesNotThrow(F); + setDoesNotCapture(F, 1); + } else if (Name == "strdup" || + Name == "strndup") { + if (FTy->getNumParams() < 1 || + !isa(FTy->getReturnType()) || + !isa(FTy->getParamType(0))) + continue; + setDoesNotThrow(F); + setDoesNotAlias(F, 0); + setDoesNotCapture(F, 1); + } else if (Name == "stat" || + Name == "sscanf" || + Name == "sprintf" || + Name == "statvfs") { + if (FTy->getNumParams() < 2 || + !isa(FTy->getParamType(0)) || + !isa(FTy->getParamType(1))) + continue; + setDoesNotThrow(F); + setDoesNotCapture(F, 1); + setDoesNotCapture(F, 2); + } else if (Name == "snprintf") { + if (FTy->getNumParams() != 3 || + !isa(FTy->getParamType(0)) || + !isa(FTy->getParamType(2))) + continue; + setDoesNotThrow(F); + setDoesNotCapture(F, 1); + setDoesNotCapture(F, 3); + } else if (Name == "setitimer") { + if (FTy->getNumParams() != 3 || + !isa(FTy->getParamType(1)) || + !isa(FTy->getParamType(2))) + continue; + setDoesNotThrow(F); + setDoesNotCapture(F, 2); + setDoesNotCapture(F, 3); + } else if (Name == "system") { + if (FTy->getNumParams() != 1 || + !isa(FTy->getParamType(0))) + continue; + // May throw; "system" is a valid pthread cancellation point. + setDoesNotCapture(F, 1); + } + break; + case 'm': + if (Name == "malloc") { + if (FTy->getNumParams() != 1 || + !isa(FTy->getReturnType())) + continue; + setDoesNotThrow(F); + setDoesNotAlias(F, 0); + } else if (Name == "memcmp") { + if (FTy->getNumParams() != 3 || + !isa(FTy->getParamType(0)) || + !isa(FTy->getParamType(1))) + continue; + setOnlyReadsMemory(F); + setDoesNotThrow(F); + setDoesNotCapture(F, 1); + setDoesNotCapture(F, 2); + } else if (Name == "memchr" || + Name == "memrchr") { + if (FTy->getNumParams() != 3) + continue; + setOnlyReadsMemory(F); + setDoesNotThrow(F); + } else if (Name == "modf" || + Name == "modff" || + Name == "modfl" || + Name == "memcpy" || + Name == "memccpy" || + Name == "memmove") { + if (FTy->getNumParams() < 2 || + !isa(FTy->getParamType(1))) + continue; + setDoesNotThrow(F); + setDoesNotCapture(F, 2); + } else if (Name == "memalign") { + if (!isa(FTy->getReturnType())) + continue; + setDoesNotAlias(F, 0); + } else if (Name == "mkdir" || + Name == "mktime") { + if (FTy->getNumParams() == 0 || + !isa(FTy->getParamType(0))) + continue; + setDoesNotThrow(F); + setDoesNotCapture(F, 1); + } + break; + case 'r': + if (Name == "realloc") { + if (FTy->getNumParams() != 2 || + !isa(FTy->getParamType(0)) || + !isa(FTy->getReturnType())) + continue; + setDoesNotThrow(F); + setDoesNotAlias(F, 0); + setDoesNotCapture(F, 1); + } else if (Name == "read") { + if (FTy->getNumParams() != 3 || + !isa(FTy->getParamType(1))) + continue; + // May throw; "read" is a valid pthread cancellation point. + setDoesNotCapture(F, 2); + } else if (Name == "rmdir" || + Name == "rewind" || + Name == "remove" || + Name == "realpath") { + if (FTy->getNumParams() < 1 || + !isa(FTy->getParamType(0))) + continue; + setDoesNotThrow(F); + setDoesNotCapture(F, 1); + } else if (Name == "rename" || + Name == "readlink") { + if (FTy->getNumParams() < 2 || + !isa(FTy->getParamType(0)) || + !isa(FTy->getParamType(1))) + continue; + setDoesNotThrow(F); + setDoesNotCapture(F, 1); + setDoesNotCapture(F, 2); + } + break; + case 'w': + if (Name == "write") { + if (FTy->getNumParams() != 3 || + !isa(FTy->getParamType(1))) + continue; + // May throw; "write" is a valid pthread cancellation point. + setDoesNotCapture(F, 2); + } + break; + case 'b': + if (Name == "bcopy") { + if (FTy->getNumParams() != 3 || + !isa(FTy->getParamType(0)) || + !isa(FTy->getParamType(1))) + continue; + setDoesNotThrow(F); + setDoesNotCapture(F, 1); + setDoesNotCapture(F, 2); + } else if (Name == "bcmp") { + if (FTy->getNumParams() != 3 || + !isa(FTy->getParamType(0)) || + !isa(FTy->getParamType(1))) + continue; + setDoesNotThrow(F); + setOnlyReadsMemory(F); + setDoesNotCapture(F, 1); + setDoesNotCapture(F, 2); + } else if (Name == "bzero") { + if (FTy->getNumParams() != 2 || + !isa(FTy->getParamType(0))) + continue; + setDoesNotThrow(F); + setDoesNotCapture(F, 1); + } + break; + case 'c': + if (Name == "calloc") { + if (FTy->getNumParams() != 2 || + !isa(FTy->getReturnType())) + continue; + setDoesNotThrow(F); + setDoesNotAlias(F, 0); + } else if (Name == "chmod" || + Name == "chown" || + Name == "ctermid" || + Name == "clearerr" || + Name == "closedir") { + if (FTy->getNumParams() == 0 || + !isa(FTy->getParamType(0))) + continue; + setDoesNotThrow(F); + setDoesNotCapture(F, 1); + } + break; + case 'a': + if (Name == "atoi" || + Name == "atol" || + Name == "atof" || + Name == "atoll") { + if (FTy->getNumParams() != 1 || + !isa(FTy->getParamType(0))) + continue; + setDoesNotThrow(F); + setOnlyReadsMemory(F); + setDoesNotCapture(F, 1); + } else if (Name == "access") { + if (FTy->getNumParams() != 2 || + !isa(FTy->getParamType(0))) + continue; + setDoesNotThrow(F); + setDoesNotCapture(F, 1); + } + break; + case 'f': + if (Name == "fopen") { + if (FTy->getNumParams() != 2 || + !isa(FTy->getReturnType()) || + !isa(FTy->getParamType(0)) || + !isa(FTy->getParamType(1))) + continue; + setDoesNotThrow(F); + setDoesNotAlias(F, 0); + setDoesNotCapture(F, 1); + setDoesNotCapture(F, 2); + } else if (Name == "fdopen") { + if (FTy->getNumParams() != 2 || + !isa(FTy->getReturnType()) || + !isa(FTy->getParamType(1))) + continue; + setDoesNotThrow(F); + setDoesNotAlias(F, 0); + setDoesNotCapture(F, 2); + } else if (Name == "feof" || + Name == "free" || + Name == "fseek" || + Name == "ftell" || + Name == "fgetc" || + Name == "fseeko" || + Name == "ftello" || + Name == "fileno" || + Name == "fflush" || + Name == "fclose" || + Name == "fsetpos" || + Name == "flockfile" || + Name == "funlockfile" || + Name == "ftrylockfile") { + if (FTy->getNumParams() == 0 || + !isa(FTy->getParamType(0))) + continue; + setDoesNotThrow(F); + setDoesNotCapture(F, 1); + } else if (Name == "ferror") { + if (FTy->getNumParams() != 1 || + !isa(FTy->getParamType(0))) + continue; + setDoesNotThrow(F); + setDoesNotCapture(F, 1); + setOnlyReadsMemory(F); + } else if (Name == "fputc" || + Name == "fstat" || + Name == "frexp" || + Name == "frexpf" || + Name == "frexpl" || + Name == "fstatvfs") { + if (FTy->getNumParams() != 2 || + !isa(FTy->getParamType(1))) + continue; + setDoesNotThrow(F); + setDoesNotCapture(F, 2); + } else if (Name == "fgets") { + if (FTy->getNumParams() != 3 || + !isa(FTy->getParamType(0)) || + !isa(FTy->getParamType(2))) + continue; + setDoesNotThrow(F); + setDoesNotCapture(F, 3); + } else if (Name == "fread" || + Name == "fwrite") { + if (FTy->getNumParams() != 4 || + !isa(FTy->getParamType(0)) || + !isa(FTy->getParamType(3))) + continue; + setDoesNotThrow(F); + setDoesNotCapture(F, 1); + setDoesNotCapture(F, 4); + } else if (Name == "fputs" || + Name == "fscanf" || + Name == "fprintf" || + Name == "fgetpos") { + if (FTy->getNumParams() < 2 || + !isa(FTy->getParamType(0)) || + !isa(FTy->getParamType(1))) + continue; + setDoesNotThrow(F); + setDoesNotCapture(F, 1); + setDoesNotCapture(F, 2); + } + break; + case 'g': + if (Name == "getc" || + Name == "getlogin_r" || + Name == "getc_unlocked") { + if (FTy->getNumParams() == 0 || + !isa(FTy->getParamType(0))) + continue; + setDoesNotThrow(F); + setDoesNotCapture(F, 1); + } else if (Name == "getenv") { + if (FTy->getNumParams() != 1 || + !isa(FTy->getParamType(0))) + continue; + setDoesNotThrow(F); + setOnlyReadsMemory(F); + setDoesNotCapture(F, 1); + } else if (Name == "gets" || + Name == "getchar") { + setDoesNotThrow(F); + } else if (Name == "getitimer") { + if (FTy->getNumParams() != 2 || + !isa(FTy->getParamType(1))) + continue; + setDoesNotThrow(F); + setDoesNotCapture(F, 2); + } else if (Name == "getpwnam") { + if (FTy->getNumParams() != 1 || + !isa(FTy->getParamType(0))) + continue; + setDoesNotThrow(F); + setDoesNotCapture(F, 1); + } + break; + case 'u': + if (Name == "ungetc") { + if (FTy->getNumParams() != 2 || + !isa(FTy->getParamType(1))) + continue; + setDoesNotThrow(F); + setDoesNotCapture(F, 2); + } else if (Name == "uname" || + Name == "unlink" || + Name == "unsetenv") { + if (FTy->getNumParams() != 1 || + !isa(FTy->getParamType(0))) + continue; + setDoesNotThrow(F); + setDoesNotCapture(F, 1); + } else if (Name == "utime" || + Name == "utimes") { + if (FTy->getNumParams() != 2 || + !isa(FTy->getParamType(0)) || + !isa(FTy->getParamType(1))) + continue; + setDoesNotThrow(F); + setDoesNotCapture(F, 1); + setDoesNotCapture(F, 2); + } + break; + case 'p': + if (Name == "putc") { + if (FTy->getNumParams() != 2 || + !isa(FTy->getParamType(1))) + continue; + setDoesNotThrow(F); + setDoesNotCapture(F, 2); + } else if (Name == "puts" || + Name == "printf" || + Name == "perror") { + if (FTy->getNumParams() != 1 || + !isa(FTy->getParamType(0))) + continue; + setDoesNotThrow(F); + setDoesNotCapture(F, 1); + } else if (Name == "pread" || + Name == "pwrite") { + if (FTy->getNumParams() != 4 || + !isa(FTy->getParamType(1))) + continue; + // May throw; these are valid pthread cancellation points. + setDoesNotCapture(F, 2); + } else if (Name == "putchar") { + setDoesNotThrow(F); + } else if (Name == "popen") { + if (FTy->getNumParams() != 2 || + !isa(FTy->getReturnType()) || + !isa(FTy->getParamType(0)) || + !isa(FTy->getParamType(1))) + continue; + setDoesNotThrow(F); + setDoesNotAlias(F, 0); + setDoesNotCapture(F, 1); + setDoesNotCapture(F, 2); + } else if (Name == "pclose") { + if (FTy->getNumParams() != 1 || + !isa(FTy->getParamType(0))) + continue; + setDoesNotThrow(F); + setDoesNotCapture(F, 1); + } + break; + case 'v': + if (Name == "vscanf") { + if (FTy->getNumParams() != 2 || + !isa(FTy->getParamType(1))) + continue; + setDoesNotThrow(F); + setDoesNotCapture(F, 1); + } else if (Name == "vsscanf" || + Name == "vfscanf") { + if (FTy->getNumParams() != 3 || + !isa(FTy->getParamType(1)) || + !isa(FTy->getParamType(2))) + continue; + setDoesNotThrow(F); + setDoesNotCapture(F, 1); + setDoesNotCapture(F, 2); + } else if (Name == "valloc") { + if (!isa(FTy->getReturnType())) + continue; + setDoesNotThrow(F); + setDoesNotAlias(F, 0); + } else if (Name == "vprintf") { + if (FTy->getNumParams() != 2 || + !isa(FTy->getParamType(0))) + continue; + setDoesNotThrow(F); + setDoesNotCapture(F, 1); + } else if (Name == "vfprintf" || + Name == "vsprintf") { + if (FTy->getNumParams() != 3 || + !isa(FTy->getParamType(0)) || + !isa(FTy->getParamType(1))) + continue; + setDoesNotThrow(F); + setDoesNotCapture(F, 1); + setDoesNotCapture(F, 2); + } else if (Name == "vsnprintf") { + if (FTy->getNumParams() != 4 || + !isa(FTy->getParamType(0)) || + !isa(FTy->getParamType(2))) + continue; + setDoesNotThrow(F); + setDoesNotCapture(F, 1); + setDoesNotCapture(F, 3); + } + break; + case 'o': + if (Name == "open") { + if (FTy->getNumParams() < 2 || + !isa(FTy->getParamType(0))) + continue; + // May throw; "open" is a valid pthread cancellation point. + setDoesNotCapture(F, 1); + } else if (Name == "opendir") { + if (FTy->getNumParams() != 1 || + !isa(FTy->getReturnType()) || + !isa(FTy->getParamType(0))) + continue; + setDoesNotThrow(F); + setDoesNotAlias(F, 0); + setDoesNotCapture(F, 1); + } + break; + case 't': + if (Name == "tmpfile") { + if (!isa(FTy->getReturnType())) + continue; + setDoesNotThrow(F); + setDoesNotAlias(F, 0); + } else if (Name == "times") { + if (FTy->getNumParams() != 1 || + !isa(FTy->getParamType(0))) + continue; + setDoesNotThrow(F); + setDoesNotCapture(F, 1); + } + break; + case 'h': + if (Name == "htonl" || + Name == "htons") { + setDoesNotThrow(F); + setDoesNotAccessMemory(F); + } + break; + case 'n': + if (Name == "ntohl" || + Name == "ntohs") { + setDoesNotThrow(F); + setDoesNotAccessMemory(F); + } + break; + case 'l': + if (Name == "lstat") { + if (FTy->getNumParams() != 2 || + !isa(FTy->getParamType(0)) || + !isa(FTy->getParamType(1))) + continue; + setDoesNotThrow(F); + setDoesNotCapture(F, 1); + setDoesNotCapture(F, 2); + } else if (Name == "lchown") { + if (FTy->getNumParams() != 3 || + !isa(FTy->getParamType(0))) + continue; + setDoesNotThrow(F); + setDoesNotCapture(F, 1); + } + break; + case 'q': + if (Name == "qsort") { + if (FTy->getNumParams() != 4 || + !isa(FTy->getParamType(3))) + continue; + // May throw; places call through function pointer. + setDoesNotCapture(F, 4); + } + break; + case '_': + if (Name == "__strdup" || + Name == "__strndup") { + if (FTy->getNumParams() < 1 || + !isa(FTy->getReturnType()) || + !isa(FTy->getParamType(0))) + continue; + setDoesNotThrow(F); + setDoesNotAlias(F, 0); + setDoesNotCapture(F, 1); + } else if (Name == "__strtok_r") { + if (FTy->getNumParams() != 3 || + !isa(FTy->getParamType(1))) + continue; + setDoesNotThrow(F); + setDoesNotCapture(F, 2); + } else if (Name == "_IO_getc") { + if (FTy->getNumParams() != 1 || + !isa(FTy->getParamType(0))) + continue; + setDoesNotThrow(F); + setDoesNotCapture(F, 1); + } else if (Name == "_IO_putc") { + if (FTy->getNumParams() != 2 || + !isa(FTy->getParamType(1))) + continue; + setDoesNotThrow(F); + setDoesNotCapture(F, 2); + } + break; + case 1: + if (Name == "\1__isoc99_scanf") { + if (FTy->getNumParams() < 1 || + !isa(FTy->getParamType(0))) + continue; + setDoesNotThrow(F); + setDoesNotCapture(F, 1); + } else if (Name == "\1stat64" || + Name == "\1lstat64" || + Name == "\1statvfs64" || + Name == "\1__isoc99_sscanf") { + if (FTy->getNumParams() < 1 || + !isa(FTy->getParamType(0)) || + !isa(FTy->getParamType(1))) + continue; + setDoesNotThrow(F); + setDoesNotCapture(F, 1); + setDoesNotCapture(F, 2); + } else if (Name == "\1fopen64") { + if (FTy->getNumParams() != 2 || + !isa(FTy->getReturnType()) || + !isa(FTy->getParamType(0)) || + !isa(FTy->getParamType(1))) + continue; + setDoesNotThrow(F); + setDoesNotAlias(F, 0); + setDoesNotCapture(F, 1); + setDoesNotCapture(F, 2); + } else if (Name == "\1fseeko64" || + Name == "\1ftello64") { + if (FTy->getNumParams() == 0 || + !isa(FTy->getParamType(0))) + continue; + setDoesNotThrow(F); + setDoesNotCapture(F, 1); + } else if (Name == "\1tmpfile64") { + if (!isa(FTy->getReturnType())) + continue; + setDoesNotThrow(F); + setDoesNotAlias(F, 0); + } else if (Name == "\1fstat64" || + Name == "\1fstatvfs64") { + if (FTy->getNumParams() != 2 || + !isa(FTy->getParamType(1))) + continue; + setDoesNotThrow(F); + setDoesNotCapture(F, 2); + } else if (Name == "\1open64") { + if (FTy->getNumParams() < 2 || + !isa(FTy->getParamType(0))) + continue; + // May throw; "open" is a valid pthread cancellation point. + setDoesNotCapture(F, 1); + } + break; + } + } + return Modified; +} + +// TODO: +// Additional cases that we need to add to this file: +// +// cbrt: +// * cbrt(expN(X)) -> expN(x/3) +// * cbrt(sqrt(x)) -> pow(x,1/6) +// * cbrt(sqrt(x)) -> pow(x,1/9) +// +// cos, cosf, cosl: +// * cos(-x) -> cos(x) +// +// exp, expf, expl: +// * exp(log(x)) -> x +// +// log, logf, logl: +// * log(exp(x)) -> x +// * log(x**y) -> y*log(x) +// * log(exp(y)) -> y*log(e) +// * log(exp2(y)) -> y*log(2) +// * log(exp10(y)) -> y*log(10) +// * log(sqrt(x)) -> 0.5*log(x) +// * log(pow(x,y)) -> y*log(x) +// +// lround, lroundf, lroundl: +// * lround(cnst) -> cnst' +// +// pow, powf, powl: +// * pow(exp(x),y) -> exp(x*y) +// * pow(sqrt(x),y) -> pow(x,y*0.5) +// * pow(pow(x,y),z)-> pow(x,y*z) +// +// puts: +// * puts("") -> putchar("\n") +// +// round, roundf, roundl: +// * round(cnst) -> cnst' +// +// signbit: +// * signbit(cnst) -> cnst' +// * signbit(nncst) -> 0 (if pstv is a non-negative constant) +// +// sqrt, sqrtf, sqrtl: +// * sqrt(expN(x)) -> expN(x*0.5) +// * sqrt(Nroot(x)) -> pow(x,1/(2*N)) +// * sqrt(pow(x,y)) -> pow(|x|,y*0.5) +// +// stpcpy: +// * stpcpy(str, "literal") -> +// llvm.memcpy(str,"literal",strlen("literal")+1,1) +// strrchr: +// * strrchr(s,c) -> reverse_offset_of_in(c,s) +// (if c is a constant integer and s is a constant string) +// * strrchr(s1,0) -> strchr(s1,0) +// +// strpbrk: +// * strpbrk(s,a) -> offset_in_for(s,a) +// (if s and a are both constant strings) +// * strpbrk(s,"") -> 0 +// * strpbrk(s,a) -> strchr(s,a[0]) (if a is constant string of length 1) +// +// strspn, strcspn: +// * strspn(s,a) -> const_int (if both args are constant) +// * strspn("",a) -> 0 +// * strspn(s,"") -> 0 +// * strcspn(s,a) -> const_int (if both args are constant) +// * strcspn("",a) -> 0 +// * strcspn(s,"") -> strlen(a) +// +// strstr: +// * strstr(x,x) -> x +// * strstr(s1,s2) -> offset_of_s2_in(s1) +// (if s1 and s2 are constant strings) +// +// tan, tanf, tanl: +// * tan(atan(x)) -> x +// +// trunc, truncf, truncl: +// * trunc(cnst) -> cnst' +// +// diff --git a/libclamav/c++/llvm/lib/Transforms/Scalar/TailDuplication.cpp b/libclamav/c++/llvm/lib/Transforms/Scalar/TailDuplication.cpp new file mode 100644 index 000000000..b06ae3def --- /dev/null +++ b/libclamav/c++/llvm/lib/Transforms/Scalar/TailDuplication.cpp @@ -0,0 +1,370 @@ +//===- TailDuplication.cpp - Simplify CFG through tail duplication --------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This pass performs a limited form of tail duplication, intended to simplify +// CFGs by removing some unconditional branches. This pass is necessary to +// straighten out loops created by the C front-end, but also is capable of +// making other code nicer. After this pass is run, the CFG simplify pass +// should be run to clean up the mess. +// +// This pass could be enhanced in the future to use profile information to be +// more aggressive. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "tailduplicate" +#include "llvm/Transforms/Scalar.h" +#include "llvm/Constant.h" +#include "llvm/Function.h" +#include "llvm/Instructions.h" +#include "llvm/IntrinsicInst.h" +#include "llvm/Pass.h" +#include "llvm/Type.h" +#include "llvm/Support/CFG.h" +#include "llvm/Analysis/ConstantFolding.h" +#include "llvm/Transforms/Utils/Local.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/ADT/SmallPtrSet.h" +#include +using namespace llvm; + +STATISTIC(NumEliminated, "Number of unconditional branches eliminated"); + +static cl::opt +TailDupThreshold("taildup-threshold", + cl::desc("Max block size to tail duplicate"), + cl::init(1), cl::Hidden); + +namespace { + class TailDup : public FunctionPass { + bool runOnFunction(Function &F); + public: + static char ID; // Pass identification, replacement for typeid + TailDup() : FunctionPass(&ID) {} + + private: + inline bool shouldEliminateUnconditionalBranch(TerminatorInst *, unsigned); + inline void eliminateUnconditionalBranch(BranchInst *BI); + SmallPtrSet CycleDetector; + }; +} + +char TailDup::ID = 0; +static RegisterPass X("tailduplicate", "Tail Duplication"); + +// Public interface to the Tail Duplication pass +FunctionPass *llvm::createTailDuplicationPass() { return new TailDup(); } + +/// runOnFunction - Top level algorithm - Loop over each unconditional branch in +/// the function, eliminating it if it looks attractive enough. CycleDetector +/// prevents infinite loops by checking that we aren't redirecting a branch to +/// a place it already pointed to earlier; see PR 2323. +bool TailDup::runOnFunction(Function &F) { + bool Changed = false; + CycleDetector.clear(); + for (Function::iterator I = F.begin(), E = F.end(); I != E; ) { + if (shouldEliminateUnconditionalBranch(I->getTerminator(), + TailDupThreshold)) { + eliminateUnconditionalBranch(cast(I->getTerminator())); + Changed = true; + } else { + ++I; + CycleDetector.clear(); + } + } + return Changed; +} + +/// shouldEliminateUnconditionalBranch - Return true if this branch looks +/// attractive to eliminate. We eliminate the branch if the destination basic +/// block has <= 5 instructions in it, not counting PHI nodes. In practice, +/// since one of these is a terminator instruction, this means that we will add +/// up to 4 instructions to the new block. +/// +/// We don't count PHI nodes in the count since they will be removed when the +/// contents of the block are copied over. +/// +bool TailDup::shouldEliminateUnconditionalBranch(TerminatorInst *TI, + unsigned Threshold) { + BranchInst *BI = dyn_cast(TI); + if (!BI || !BI->isUnconditional()) return false; // Not an uncond branch! + + BasicBlock *Dest = BI->getSuccessor(0); + if (Dest == BI->getParent()) return false; // Do not loop infinitely! + + // Do not inline a block if we will just get another branch to the same block! + TerminatorInst *DTI = Dest->getTerminator(); + if (BranchInst *DBI = dyn_cast(DTI)) + if (DBI->isUnconditional() && DBI->getSuccessor(0) == Dest) + return false; // Do not loop infinitely! + + // FIXME: DemoteRegToStack cannot yet demote invoke instructions to the stack, + // because doing so would require breaking critical edges. This should be + // fixed eventually. + if (!DTI->use_empty()) + return false; + + // Do not bother with blocks with only a single predecessor: simplify + // CFG will fold these two blocks together! + pred_iterator PI = pred_begin(Dest), PE = pred_end(Dest); + ++PI; + if (PI == PE) return false; // Exactly one predecessor! + + BasicBlock::iterator I = Dest->getFirstNonPHI(); + + for (unsigned Size = 0; I != Dest->end(); ++I) { + if (Size == Threshold) return false; // The block is too large. + + // Don't tail duplicate call instructions. They are very large compared to + // other instructions. + if (isa(I) || isa(I)) return false; + + // Also alloca and malloc. + if (isa(I)) return false; + + // Some vector instructions can expand into a number of instructions. + if (isa(I) || isa(I) || + isa(I)) return false; + + // Only count instructions that are not debugger intrinsics. + if (!isa(I)) ++Size; + } + + // Do not tail duplicate a block that has thousands of successors into a block + // with a single successor if the block has many other predecessors. This can + // cause an N^2 explosion in CFG edges (and PHI node entries), as seen in + // cases that have a large number of indirect gotos. + unsigned NumSuccs = DTI->getNumSuccessors(); + if (NumSuccs > 8) { + unsigned TooMany = 128; + if (NumSuccs >= TooMany) return false; + TooMany = TooMany/NumSuccs; + for (; PI != PE; ++PI) + if (TooMany-- == 0) return false; + } + + // If this unconditional branch is a fall-through, be careful about + // tail duplicating it. In particular, we don't want to taildup it if the + // original block will still be there after taildup is completed: doing so + // would eliminate the fall-through, requiring unconditional branches. + Function::iterator DestI = Dest; + if (&*--DestI == BI->getParent()) { + // The uncond branch is a fall-through. Tail duplication of the block is + // will eliminate the fall-through-ness and end up cloning the terminator + // at the end of the Dest block. Since the original Dest block will + // continue to exist, this means that one or the other will not be able to + // fall through. One typical example that this helps with is code like: + // if (a) + // foo(); + // if (b) + // foo(); + // Cloning the 'if b' block into the end of the first foo block is messy. + + // The messy case is when the fall-through block falls through to other + // blocks. This is what we would be preventing if we cloned the block. + DestI = Dest; + if (++DestI != Dest->getParent()->end()) { + BasicBlock *DestSucc = DestI; + // If any of Dest's successors are fall-throughs, don't do this xform. + for (succ_iterator SI = succ_begin(Dest), SE = succ_end(Dest); + SI != SE; ++SI) + if (*SI == DestSucc) + return false; + } + } + + // Finally, check that we haven't redirected to this target block earlier; + // there are cases where we loop forever if we don't check this (PR 2323). + if (!CycleDetector.insert(Dest)) + return false; + + return true; +} + +/// FindObviousSharedDomOf - We know there is a branch from SrcBlock to +/// DestBlock, and that SrcBlock is not the only predecessor of DstBlock. If we +/// can find a predecessor of SrcBlock that is a dominator of both SrcBlock and +/// DstBlock, return it. +static BasicBlock *FindObviousSharedDomOf(BasicBlock *SrcBlock, + BasicBlock *DstBlock) { + // SrcBlock must have a single predecessor. + pred_iterator PI = pred_begin(SrcBlock), PE = pred_end(SrcBlock); + if (PI == PE || ++PI != PE) return 0; + + BasicBlock *SrcPred = *pred_begin(SrcBlock); + + // Look at the predecessors of DstBlock. One of them will be SrcBlock. If + // there is only one other pred, get it, otherwise we can't handle it. + PI = pred_begin(DstBlock); PE = pred_end(DstBlock); + BasicBlock *DstOtherPred = 0; + if (*PI == SrcBlock) { + if (++PI == PE) return 0; + DstOtherPred = *PI; + if (++PI != PE) return 0; + } else { + DstOtherPred = *PI; + if (++PI == PE || *PI != SrcBlock || ++PI != PE) return 0; + } + + // We can handle two situations here: "if then" and "if then else" blocks. An + // 'if then' situation is just where DstOtherPred == SrcPred. + if (DstOtherPred == SrcPred) + return SrcPred; + + // Check to see if we have an "if then else" situation, which means that + // DstOtherPred will have a single predecessor and it will be SrcPred. + PI = pred_begin(DstOtherPred); PE = pred_end(DstOtherPred); + if (PI != PE && *PI == SrcPred) { + if (++PI != PE) return 0; // Not a single pred. + return SrcPred; // Otherwise, it's an "if then" situation. Return the if. + } + + // Otherwise, this is something we can't handle. + return 0; +} + + +/// eliminateUnconditionalBranch - Clone the instructions from the destination +/// block into the source block, eliminating the specified unconditional branch. +/// If the destination block defines values used by successors of the dest +/// block, we may need to insert PHI nodes. +/// +void TailDup::eliminateUnconditionalBranch(BranchInst *Branch) { + BasicBlock *SourceBlock = Branch->getParent(); + BasicBlock *DestBlock = Branch->getSuccessor(0); + assert(SourceBlock != DestBlock && "Our predicate is broken!"); + + DEBUG(errs() << "TailDuplication[" << SourceBlock->getParent()->getName() + << "]: Eliminating branch: " << *Branch); + + // See if we can avoid duplicating code by moving it up to a dominator of both + // blocks. + if (BasicBlock *DomBlock = FindObviousSharedDomOf(SourceBlock, DestBlock)) { + DEBUG(errs() << "Found shared dominator: " << DomBlock->getName() << "\n"); + + // If there are non-phi instructions in DestBlock that have no operands + // defined in DestBlock, and if the instruction has no side effects, we can + // move the instruction to DomBlock instead of duplicating it. + BasicBlock::iterator BBI = DestBlock->getFirstNonPHI(); + while (!isa(BBI)) { + Instruction *I = BBI++; + + bool CanHoist = I->isSafeToSpeculativelyExecute() && + !I->mayReadFromMemory(); + if (CanHoist) { + for (unsigned op = 0, e = I->getNumOperands(); op != e; ++op) + if (Instruction *OpI = dyn_cast(I->getOperand(op))) + if (OpI->getParent() == DestBlock || + (isa(OpI) && OpI->getParent() == DomBlock)) { + CanHoist = false; + break; + } + if (CanHoist) { + // Remove from DestBlock, move right before the term in DomBlock. + DestBlock->getInstList().remove(I); + DomBlock->getInstList().insert(DomBlock->getTerminator(), I); + DEBUG(errs() << "Hoisted: " << *I); + } + } + } + } + + // Tail duplication can not update SSA properties correctly if the values + // defined in the duplicated tail are used outside of the tail itself. For + // this reason, we spill all values that are used outside of the tail to the + // stack. + for (BasicBlock::iterator I = DestBlock->begin(); I != DestBlock->end(); ++I) + if (I->isUsedOutsideOfBlock(DestBlock)) { + // We found a use outside of the tail. Create a new stack slot to + // break this inter-block usage pattern. + DemoteRegToStack(*I); + } + + // We are going to have to map operands from the original block B to the new + // copy of the block B'. If there are PHI nodes in the DestBlock, these PHI + // nodes also define part of this mapping. Loop over these PHI nodes, adding + // them to our mapping. + // + std::map ValueMapping; + + BasicBlock::iterator BI = DestBlock->begin(); + bool HadPHINodes = isa(BI); + for (; PHINode *PN = dyn_cast(BI); ++BI) + ValueMapping[PN] = PN->getIncomingValueForBlock(SourceBlock); + + // Clone the non-phi instructions of the dest block into the source block, + // keeping track of the mapping... + // + for (; BI != DestBlock->end(); ++BI) { + Instruction *New = BI->clone(); + New->setName(BI->getName()); + SourceBlock->getInstList().push_back(New); + ValueMapping[BI] = New; + } + + // Now that we have built the mapping information and cloned all of the + // instructions (giving us a new terminator, among other things), walk the new + // instructions, rewriting references of old instructions to use new + // instructions. + // + BI = Branch; ++BI; // Get an iterator to the first new instruction + for (; BI != SourceBlock->end(); ++BI) + for (unsigned i = 0, e = BI->getNumOperands(); i != e; ++i) { + std::map::const_iterator I = + ValueMapping.find(BI->getOperand(i)); + if (I != ValueMapping.end()) + BI->setOperand(i, I->second); + } + + // Next we check to see if any of the successors of DestBlock had PHI nodes. + // If so, we need to add entries to the PHI nodes for SourceBlock now. + for (succ_iterator SI = succ_begin(DestBlock), SE = succ_end(DestBlock); + SI != SE; ++SI) { + BasicBlock *Succ = *SI; + for (BasicBlock::iterator PNI = Succ->begin(); isa(PNI); ++PNI) { + PHINode *PN = cast(PNI); + // Ok, we have a PHI node. Figure out what the incoming value was for the + // DestBlock. + Value *IV = PN->getIncomingValueForBlock(DestBlock); + + // Remap the value if necessary... + std::map::const_iterator I = ValueMapping.find(IV); + if (I != ValueMapping.end()) + IV = I->second; + PN->addIncoming(IV, SourceBlock); + } + } + + // Next, remove the old branch instruction, and any PHI node entries that we + // had. + BI = Branch; ++BI; // Get an iterator to the first new instruction + DestBlock->removePredecessor(SourceBlock); // Remove entries in PHI nodes... + SourceBlock->getInstList().erase(Branch); // Destroy the uncond branch... + + // Final step: now that we have finished everything up, walk the cloned + // instructions one last time, constant propagating and DCE'ing them, because + // they may not be needed anymore. + // + if (HadPHINodes) { + while (BI != SourceBlock->end()) { + Instruction *Inst = BI++; + if (isInstructionTriviallyDead(Inst)) + Inst->eraseFromParent(); + else if (Constant *C = ConstantFoldInstruction(Inst)) { + Inst->replaceAllUsesWith(C); + Inst->eraseFromParent(); + } + } + } + + ++NumEliminated; // We just killed a branch! +} diff --git a/libclamav/c++/llvm/lib/Transforms/Scalar/TailRecursionElimination.cpp b/libclamav/c++/llvm/lib/Transforms/Scalar/TailRecursionElimination.cpp new file mode 100644 index 000000000..4119cb9db --- /dev/null +++ b/libclamav/c++/llvm/lib/Transforms/Scalar/TailRecursionElimination.cpp @@ -0,0 +1,496 @@ +//===- TailRecursionElimination.cpp - Eliminate Tail Calls ----------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file transforms calls of the current function (self recursion) followed +// by a return instruction with a branch to the entry of the function, creating +// a loop. This pass also implements the following extensions to the basic +// algorithm: +// +// 1. Trivial instructions between the call and return do not prevent the +// transformation from taking place, though currently the analysis cannot +// support moving any really useful instructions (only dead ones). +// 2. This pass transforms functions that are prevented from being tail +// recursive by an associative expression to use an accumulator variable, +// thus compiling the typical naive factorial or 'fib' implementation into +// efficient code. +// 3. TRE is performed if the function returns void, if the return +// returns the result returned by the call, or if the function returns a +// run-time constant on all exits from the function. It is possible, though +// unlikely, that the return returns something else (like constant 0), and +// can still be TRE'd. It can be TRE'd if ALL OTHER return instructions in +// the function return the exact same value. +// 4. If it can prove that callees do not access their caller stack frame, +// they are marked as eligible for tail call elimination (by the code +// generator). +// +// There are several improvements that could be made: +// +// 1. If the function has any alloca instructions, these instructions will be +// moved out of the entry block of the function, causing them to be +// evaluated each time through the tail recursion. Safely keeping allocas +// in the entry block requires analysis to proves that the tail-called +// function does not read or write the stack object. +// 2. Tail recursion is only performed if the call immediately preceeds the +// return instruction. It's possible that there could be a jump between +// the call and the return. +// 3. There can be intervening operations between the call and the return that +// prevent the TRE from occurring. For example, there could be GEP's and +// stores to memory that will not be read or written by the call. This +// requires some substantial analysis (such as with DSA) to prove safe to +// move ahead of the call, but doing so could allow many more TREs to be +// performed, for example in TreeAdd/TreeAlloc from the treeadd benchmark. +// 4. The algorithm we use to detect if callees access their caller stack +// frames is very primitive. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "tailcallelim" +#include "llvm/Transforms/Scalar.h" +#include "llvm/Transforms/Utils/Local.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Function.h" +#include "llvm/Instructions.h" +#include "llvm/Pass.h" +#include "llvm/Analysis/CaptureTracking.h" +#include "llvm/Support/CFG.h" +#include "llvm/ADT/Statistic.h" +using namespace llvm; + +STATISTIC(NumEliminated, "Number of tail calls removed"); +STATISTIC(NumAccumAdded, "Number of accumulators introduced"); + +namespace { + struct TailCallElim : public FunctionPass { + static char ID; // Pass identification, replacement for typeid + TailCallElim() : FunctionPass(&ID) {} + + virtual bool runOnFunction(Function &F); + + private: + bool ProcessReturningBlock(ReturnInst *RI, BasicBlock *&OldEntry, + bool &TailCallsAreMarkedTail, + SmallVector &ArgumentPHIs, + bool CannotTailCallElimCallsMarkedTail); + bool CanMoveAboveCall(Instruction *I, CallInst *CI); + Value *CanTransformAccumulatorRecursion(Instruction *I, CallInst *CI); + }; +} + +char TailCallElim::ID = 0; +static RegisterPass X("tailcallelim", "Tail Call Elimination"); + +// Public interface to the TailCallElimination pass +FunctionPass *llvm::createTailCallEliminationPass() { + return new TailCallElim(); +} + +/// AllocaMightEscapeToCalls - Return true if this alloca may be accessed by +/// callees of this function. We only do very simple analysis right now, this +/// could be expanded in the future to use mod/ref information for particular +/// call sites if desired. +static bool AllocaMightEscapeToCalls(AllocaInst *AI) { + // FIXME: do simple 'address taken' analysis. + return true; +} + +/// CheckForEscapingAllocas - Scan the specified basic block for alloca +/// instructions. If it contains any that might be accessed by calls, return +/// true. +static bool CheckForEscapingAllocas(BasicBlock *BB, + bool &CannotTCETailMarkedCall) { + bool RetVal = false; + for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ++I) + if (AllocaInst *AI = dyn_cast(I)) { + RetVal |= AllocaMightEscapeToCalls(AI); + + // If this alloca is in the body of the function, or if it is a variable + // sized allocation, we cannot tail call eliminate calls marked 'tail' + // with this mechanism. + if (BB != &BB->getParent()->getEntryBlock() || + !isa(AI->getArraySize())) + CannotTCETailMarkedCall = true; + } + return RetVal; +} + +bool TailCallElim::runOnFunction(Function &F) { + // If this function is a varargs function, we won't be able to PHI the args + // right, so don't even try to convert it... + if (F.getFunctionType()->isVarArg()) return false; + + BasicBlock *OldEntry = 0; + bool TailCallsAreMarkedTail = false; + SmallVector ArgumentPHIs; + bool MadeChange = false; + + bool FunctionContainsEscapingAllocas = false; + + // CannotTCETailMarkedCall - If true, we cannot perform TCE on tail calls + // marked with the 'tail' attribute, because doing so would cause the stack + // size to increase (real TCE would deallocate variable sized allocas, TCE + // doesn't). + bool CannotTCETailMarkedCall = false; + + // Loop over the function, looking for any returning blocks, and keeping track + // of whether this function has any non-trivially used allocas. + for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB) { + if (FunctionContainsEscapingAllocas && CannotTCETailMarkedCall) + break; + + FunctionContainsEscapingAllocas |= + CheckForEscapingAllocas(BB, CannotTCETailMarkedCall); + } + + /// FIXME: The code generator produces really bad code when an 'escaping + /// alloca' is changed from being a static alloca to being a dynamic alloca. + /// Until this is resolved, disable this transformation if that would ever + /// happen. This bug is PR962. + if (FunctionContainsEscapingAllocas) + return false; + + // Second pass, change any tail calls to loops. + for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB) + if (ReturnInst *Ret = dyn_cast(BB->getTerminator())) + MadeChange |= ProcessReturningBlock(Ret, OldEntry, TailCallsAreMarkedTail, + ArgumentPHIs,CannotTCETailMarkedCall); + + // If we eliminated any tail recursions, it's possible that we inserted some + // silly PHI nodes which just merge an initial value (the incoming operand) + // with themselves. Check to see if we did and clean up our mess if so. This + // occurs when a function passes an argument straight through to its tail + // call. + if (!ArgumentPHIs.empty()) { + for (unsigned i = 0, e = ArgumentPHIs.size(); i != e; ++i) { + PHINode *PN = ArgumentPHIs[i]; + + // If the PHI Node is a dynamic constant, replace it with the value it is. + if (Value *PNV = PN->hasConstantValue()) { + PN->replaceAllUsesWith(PNV); + PN->eraseFromParent(); + } + } + } + + // Finally, if this function contains no non-escaping allocas, mark all calls + // in the function as eligible for tail calls (there is no stack memory for + // them to access). + if (!FunctionContainsEscapingAllocas) + for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB) + for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ++I) + if (CallInst *CI = dyn_cast(I)) { + CI->setTailCall(); + MadeChange = true; + } + + return MadeChange; +} + + +/// CanMoveAboveCall - Return true if it is safe to move the specified +/// instruction from after the call to before the call, assuming that all +/// instructions between the call and this instruction are movable. +/// +bool TailCallElim::CanMoveAboveCall(Instruction *I, CallInst *CI) { + // FIXME: We can move load/store/call/free instructions above the call if the + // call does not mod/ref the memory location being processed. + if (I->mayHaveSideEffects()) // This also handles volatile loads. + return false; + + if (LoadInst *L = dyn_cast(I)) { + // Loads may always be moved above calls without side effects. + if (CI->mayHaveSideEffects()) { + // Non-volatile loads may be moved above a call with side effects if it + // does not write to memory and the load provably won't trap. + // FIXME: Writes to memory only matter if they may alias the pointer + // being loaded from. + if (CI->mayWriteToMemory() || + !isSafeToLoadUnconditionally(L->getPointerOperand(), L)) + return false; + } + } + + // Otherwise, if this is a side-effect free instruction, check to make sure + // that it does not use the return value of the call. If it doesn't use the + // return value of the call, it must only use things that are defined before + // the call, or movable instructions between the call and the instruction + // itself. + for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i) + if (I->getOperand(i) == CI) + return false; + return true; +} + +// isDynamicConstant - Return true if the specified value is the same when the +// return would exit as it was when the initial iteration of the recursive +// function was executed. +// +// We currently handle static constants and arguments that are not modified as +// part of the recursion. +// +static bool isDynamicConstant(Value *V, CallInst *CI, ReturnInst *RI) { + if (isa(V)) return true; // Static constants are always dyn consts + + // Check to see if this is an immutable argument, if so, the value + // will be available to initialize the accumulator. + if (Argument *Arg = dyn_cast(V)) { + // Figure out which argument number this is... + unsigned ArgNo = 0; + Function *F = CI->getParent()->getParent(); + for (Function::arg_iterator AI = F->arg_begin(); &*AI != Arg; ++AI) + ++ArgNo; + + // If we are passing this argument into call as the corresponding + // argument operand, then the argument is dynamically constant. + // Otherwise, we cannot transform this function safely. + if (CI->getOperand(ArgNo+1) == Arg) + return true; + } + + // Switch cases are always constant integers. If the value is being switched + // on and the return is only reachable from one of its cases, it's + // effectively constant. + if (BasicBlock *UniquePred = RI->getParent()->getUniquePredecessor()) + if (SwitchInst *SI = dyn_cast(UniquePred->getTerminator())) + if (SI->getCondition() == V) + return SI->getDefaultDest() != RI->getParent(); + + // Not a constant or immutable argument, we can't safely transform. + return false; +} + +// getCommonReturnValue - Check to see if the function containing the specified +// return instruction and tail call consistently returns the same +// runtime-constant value at all exit points. If so, return the returned value. +// +static Value *getCommonReturnValue(ReturnInst *TheRI, CallInst *CI) { + Function *F = TheRI->getParent()->getParent(); + Value *ReturnedValue = 0; + + for (Function::iterator BBI = F->begin(), E = F->end(); BBI != E; ++BBI) + if (ReturnInst *RI = dyn_cast(BBI->getTerminator())) + if (RI != TheRI) { + Value *RetOp = RI->getOperand(0); + + // We can only perform this transformation if the value returned is + // evaluatable at the start of the initial invocation of the function, + // instead of at the end of the evaluation. + // + if (!isDynamicConstant(RetOp, CI, RI)) + return 0; + + if (ReturnedValue && RetOp != ReturnedValue) + return 0; // Cannot transform if differing values are returned. + ReturnedValue = RetOp; + } + return ReturnedValue; +} + +/// CanTransformAccumulatorRecursion - If the specified instruction can be +/// transformed using accumulator recursion elimination, return the constant +/// which is the start of the accumulator value. Otherwise return null. +/// +Value *TailCallElim::CanTransformAccumulatorRecursion(Instruction *I, + CallInst *CI) { + if (!I->isAssociative()) return 0; + assert(I->getNumOperands() == 2 && + "Associative operations should have 2 args!"); + + // Exactly one operand should be the result of the call instruction... + if ((I->getOperand(0) == CI && I->getOperand(1) == CI) || + (I->getOperand(0) != CI && I->getOperand(1) != CI)) + return 0; + + // The only user of this instruction we allow is a single return instruction. + if (!I->hasOneUse() || !isa(I->use_back())) + return 0; + + // Ok, now we have to check all of the other return instructions in this + // function. If they return non-constants or differing values, then we cannot + // transform the function safely. + return getCommonReturnValue(cast(I->use_back()), CI); +} + +bool TailCallElim::ProcessReturningBlock(ReturnInst *Ret, BasicBlock *&OldEntry, + bool &TailCallsAreMarkedTail, + SmallVector &ArgumentPHIs, + bool CannotTailCallElimCallsMarkedTail) { + BasicBlock *BB = Ret->getParent(); + Function *F = BB->getParent(); + + if (&BB->front() == Ret) // Make sure there is something before the ret... + return false; + + // If the return is in the entry block, then making this transformation would + // turn infinite recursion into an infinite loop. This transformation is ok + // in theory, but breaks some code like: + // double fabs(double f) { return __builtin_fabs(f); } // a 'fabs' call + // disable this xform in this case, because the code generator will lower the + // call to fabs into inline code. + if (BB == &F->getEntryBlock()) + return false; + + // Scan backwards from the return, checking to see if there is a tail call in + // this block. If so, set CI to it. + CallInst *CI; + BasicBlock::iterator BBI = Ret; + while (1) { + CI = dyn_cast(BBI); + if (CI && CI->getCalledFunction() == F) + break; + + if (BBI == BB->begin()) + return false; // Didn't find a potential tail call. + --BBI; + } + + // If this call is marked as a tail call, and if there are dynamic allocas in + // the function, we cannot perform this optimization. + if (CI->isTailCall() && CannotTailCallElimCallsMarkedTail) + return false; + + // If we are introducing accumulator recursion to eliminate associative + // operations after the call instruction, this variable contains the initial + // value for the accumulator. If this value is set, we actually perform + // accumulator recursion elimination instead of simple tail recursion + // elimination. + Value *AccumulatorRecursionEliminationInitVal = 0; + Instruction *AccumulatorRecursionInstr = 0; + + // Ok, we found a potential tail call. We can currently only transform the + // tail call if all of the instructions between the call and the return are + // movable to above the call itself, leaving the call next to the return. + // Check that this is the case now. + for (BBI = CI, ++BBI; &*BBI != Ret; ++BBI) + if (!CanMoveAboveCall(BBI, CI)) { + // If we can't move the instruction above the call, it might be because it + // is an associative operation that could be tranformed using accumulator + // recursion elimination. Check to see if this is the case, and if so, + // remember the initial accumulator value for later. + if ((AccumulatorRecursionEliminationInitVal = + CanTransformAccumulatorRecursion(BBI, CI))) { + // Yes, this is accumulator recursion. Remember which instruction + // accumulates. + AccumulatorRecursionInstr = BBI; + } else { + return false; // Otherwise, we cannot eliminate the tail recursion! + } + } + + // We can only transform call/return pairs that either ignore the return value + // of the call and return void, ignore the value of the call and return a + // constant, return the value returned by the tail call, or that are being + // accumulator recursion variable eliminated. + if (Ret->getNumOperands() == 1 && Ret->getReturnValue() != CI && + !isa(Ret->getReturnValue()) && + AccumulatorRecursionEliminationInitVal == 0 && + !getCommonReturnValue(Ret, CI)) + return false; + + // OK! We can transform this tail call. If this is the first one found, + // create the new entry block, allowing us to branch back to the old entry. + if (OldEntry == 0) { + OldEntry = &F->getEntryBlock(); + BasicBlock *NewEntry = BasicBlock::Create(F->getContext(), "", F, OldEntry); + NewEntry->takeName(OldEntry); + OldEntry->setName("tailrecurse"); + BranchInst::Create(OldEntry, NewEntry); + + // If this tail call is marked 'tail' and if there are any allocas in the + // entry block, move them up to the new entry block. + TailCallsAreMarkedTail = CI->isTailCall(); + if (TailCallsAreMarkedTail) + // Move all fixed sized allocas from OldEntry to NewEntry. + for (BasicBlock::iterator OEBI = OldEntry->begin(), E = OldEntry->end(), + NEBI = NewEntry->begin(); OEBI != E; ) + if (AllocaInst *AI = dyn_cast(OEBI++)) + if (isa(AI->getArraySize())) + AI->moveBefore(NEBI); + + // Now that we have created a new block, which jumps to the entry + // block, insert a PHI node for each argument of the function. + // For now, we initialize each PHI to only have the real arguments + // which are passed in. + Instruction *InsertPos = OldEntry->begin(); + for (Function::arg_iterator I = F->arg_begin(), E = F->arg_end(); + I != E; ++I) { + PHINode *PN = PHINode::Create(I->getType(), + I->getName() + ".tr", InsertPos); + I->replaceAllUsesWith(PN); // Everyone use the PHI node now! + PN->addIncoming(I, NewEntry); + ArgumentPHIs.push_back(PN); + } + } + + // If this function has self recursive calls in the tail position where some + // are marked tail and some are not, only transform one flavor or another. We + // have to choose whether we move allocas in the entry block to the new entry + // block or not, so we can't make a good choice for both. NOTE: We could do + // slightly better here in the case that the function has no entry block + // allocas. + if (TailCallsAreMarkedTail && !CI->isTailCall()) + return false; + + // Ok, now that we know we have a pseudo-entry block WITH all of the + // required PHI nodes, add entries into the PHI node for the actual + // parameters passed into the tail-recursive call. + for (unsigned i = 0, e = CI->getNumOperands()-1; i != e; ++i) + ArgumentPHIs[i]->addIncoming(CI->getOperand(i+1), BB); + + // If we are introducing an accumulator variable to eliminate the recursion, + // do so now. Note that we _know_ that no subsequent tail recursion + // eliminations will happen on this function because of the way the + // accumulator recursion predicate is set up. + // + if (AccumulatorRecursionEliminationInitVal) { + Instruction *AccRecInstr = AccumulatorRecursionInstr; + // Start by inserting a new PHI node for the accumulator. + PHINode *AccPN = PHINode::Create(AccRecInstr->getType(), "accumulator.tr", + OldEntry->begin()); + + // Loop over all of the predecessors of the tail recursion block. For the + // real entry into the function we seed the PHI with the initial value, + // computed earlier. For any other existing branches to this block (due to + // other tail recursions eliminated) the accumulator is not modified. + // Because we haven't added the branch in the current block to OldEntry yet, + // it will not show up as a predecessor. + for (pred_iterator PI = pred_begin(OldEntry), PE = pred_end(OldEntry); + PI != PE; ++PI) { + if (*PI == &F->getEntryBlock()) + AccPN->addIncoming(AccumulatorRecursionEliminationInitVal, *PI); + else + AccPN->addIncoming(AccPN, *PI); + } + + // Add an incoming argument for the current block, which is computed by our + // associative accumulator instruction. + AccPN->addIncoming(AccRecInstr, BB); + + // Next, rewrite the accumulator recursion instruction so that it does not + // use the result of the call anymore, instead, use the PHI node we just + // inserted. + AccRecInstr->setOperand(AccRecInstr->getOperand(0) != CI, AccPN); + + // Finally, rewrite any return instructions in the program to return the PHI + // node instead of the "initval" that they do currently. This loop will + // actually rewrite the return value we are destroying, but that's ok. + for (Function::iterator BBI = F->begin(), E = F->end(); BBI != E; ++BBI) + if (ReturnInst *RI = dyn_cast(BBI->getTerminator())) + RI->setOperand(0, AccPN); + ++NumAccumAdded; + } + + // Now that all of the PHI nodes are in place, remove the call and + // ret instructions, replacing them with an unconditional branch. + BranchInst::Create(OldEntry, Ret); + BB->getInstList().erase(Ret); // Remove return. + BB->getInstList().erase(CI); // Remove call. + ++NumEliminated; + return true; +} diff --git a/libclamav/c++/llvm/lib/Transforms/Utils/AddrModeMatcher.cpp b/libclamav/c++/llvm/lib/Transforms/Utils/AddrModeMatcher.cpp new file mode 100644 index 000000000..135a621f5 --- /dev/null +++ b/libclamav/c++/llvm/lib/Transforms/Utils/AddrModeMatcher.cpp @@ -0,0 +1,595 @@ +//===- AddrModeMatcher.cpp - Addressing mode matching facility --*- 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 target addressing mode matcher class. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Transforms/Utils/AddrModeMatcher.h" +#include "llvm/DerivedTypes.h" +#include "llvm/GlobalValue.h" +#include "llvm/Instruction.h" +#include "llvm/Assembly/Writer.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Support/GetElementPtrTypeIterator.h" +#include "llvm/Support/PatternMatch.h" +#include "llvm/Support/raw_ostream.h" + +using namespace llvm; +using namespace llvm::PatternMatch; + +void ExtAddrMode::print(raw_ostream &OS) const { + bool NeedPlus = false; + OS << "["; + if (BaseGV) { + OS << (NeedPlus ? " + " : "") + << "GV:"; + WriteAsOperand(OS, BaseGV, /*PrintType=*/false); + NeedPlus = true; + } + + if (BaseOffs) + OS << (NeedPlus ? " + " : "") << BaseOffs, NeedPlus = true; + + if (BaseReg) { + OS << (NeedPlus ? " + " : "") + << "Base:"; + WriteAsOperand(OS, BaseReg, /*PrintType=*/false); + NeedPlus = true; + } + if (Scale) { + OS << (NeedPlus ? " + " : "") + << Scale << "*"; + WriteAsOperand(OS, ScaledReg, /*PrintType=*/false); + NeedPlus = true; + } + + OS << ']'; +} + +void ExtAddrMode::dump() const { + print(errs()); + errs() << '\n'; +} + + +/// MatchScaledValue - Try adding ScaleReg*Scale to the current addressing mode. +/// Return true and update AddrMode if this addr mode is legal for the target, +/// false if not. +bool AddressingModeMatcher::MatchScaledValue(Value *ScaleReg, int64_t Scale, + unsigned Depth) { + // If Scale is 1, then this is the same as adding ScaleReg to the addressing + // mode. Just process that directly. + if (Scale == 1) + return MatchAddr(ScaleReg, Depth); + + // If the scale is 0, it takes nothing to add this. + if (Scale == 0) + return true; + + // If we already have a scale of this value, we can add to it, otherwise, we + // need an available scale field. + if (AddrMode.Scale != 0 && AddrMode.ScaledReg != ScaleReg) + return false; + + ExtAddrMode TestAddrMode = AddrMode; + + // Add scale to turn X*4+X*3 -> X*7. This could also do things like + // [A+B + A*7] -> [B+A*8]. + TestAddrMode.Scale += Scale; + TestAddrMode.ScaledReg = ScaleReg; + + // If the new address isn't legal, bail out. + if (!TLI.isLegalAddressingMode(TestAddrMode, AccessTy)) + return false; + + // It was legal, so commit it. + AddrMode = TestAddrMode; + + // Okay, we decided that we can add ScaleReg+Scale to AddrMode. Check now + // to see if ScaleReg is actually X+C. If so, we can turn this into adding + // X*Scale + C*Scale to addr mode. + ConstantInt *CI = 0; Value *AddLHS = 0; + if (isa(ScaleReg) && // not a constant expr. + match(ScaleReg, m_Add(m_Value(AddLHS), m_ConstantInt(CI)))) { + TestAddrMode.ScaledReg = AddLHS; + TestAddrMode.BaseOffs += CI->getSExtValue()*TestAddrMode.Scale; + + // If this addressing mode is legal, commit it and remember that we folded + // this instruction. + if (TLI.isLegalAddressingMode(TestAddrMode, AccessTy)) { + AddrModeInsts.push_back(cast(ScaleReg)); + AddrMode = TestAddrMode; + return true; + } + } + + // Otherwise, not (x+c)*scale, just return what we have. + return true; +} + +/// MightBeFoldableInst - This is a little filter, which returns true if an +/// addressing computation involving I might be folded into a load/store +/// accessing it. This doesn't need to be perfect, but needs to accept at least +/// the set of instructions that MatchOperationAddr can. +static bool MightBeFoldableInst(Instruction *I) { + switch (I->getOpcode()) { + case Instruction::BitCast: + // Don't touch identity bitcasts. + if (I->getType() == I->getOperand(0)->getType()) + return false; + return isa(I->getType()) || isa(I->getType()); + case Instruction::PtrToInt: + // PtrToInt is always a noop, as we know that the int type is pointer sized. + return true; + case Instruction::IntToPtr: + // We know the input is intptr_t, so this is foldable. + return true; + case Instruction::Add: + return true; + case Instruction::Mul: + case Instruction::Shl: + // Can only handle X*C and X << C. + return isa(I->getOperand(1)); + case Instruction::GetElementPtr: + return true; + default: + return false; + } +} + + +/// MatchOperationAddr - Given an instruction or constant expr, see if we can +/// fold the operation into the addressing mode. If so, update the addressing +/// mode and return true, otherwise return false without modifying AddrMode. +bool AddressingModeMatcher::MatchOperationAddr(User *AddrInst, unsigned Opcode, + unsigned Depth) { + // Avoid exponential behavior on extremely deep expression trees. + if (Depth >= 5) return false; + + switch (Opcode) { + case Instruction::PtrToInt: + // PtrToInt is always a noop, as we know that the int type is pointer sized. + return MatchAddr(AddrInst->getOperand(0), Depth); + case Instruction::IntToPtr: + // This inttoptr is a no-op if the integer type is pointer sized. + if (TLI.getValueType(AddrInst->getOperand(0)->getType()) == + TLI.getPointerTy()) + return MatchAddr(AddrInst->getOperand(0), Depth); + return false; + case Instruction::BitCast: + // BitCast is always a noop, and we can handle it as long as it is + // int->int or pointer->pointer (we don't want int<->fp or something). + if ((isa(AddrInst->getOperand(0)->getType()) || + isa(AddrInst->getOperand(0)->getType())) && + // Don't touch identity bitcasts. These were probably put here by LSR, + // and we don't want to mess around with them. Assume it knows what it + // is doing. + AddrInst->getOperand(0)->getType() != AddrInst->getType()) + return MatchAddr(AddrInst->getOperand(0), Depth); + return false; + case Instruction::Add: { + // Check to see if we can merge in the RHS then the LHS. If so, we win. + ExtAddrMode BackupAddrMode = AddrMode; + unsigned OldSize = AddrModeInsts.size(); + if (MatchAddr(AddrInst->getOperand(1), Depth+1) && + MatchAddr(AddrInst->getOperand(0), Depth+1)) + return true; + + // Restore the old addr mode info. + AddrMode = BackupAddrMode; + AddrModeInsts.resize(OldSize); + + // Otherwise this was over-aggressive. Try merging in the LHS then the RHS. + if (MatchAddr(AddrInst->getOperand(0), Depth+1) && + MatchAddr(AddrInst->getOperand(1), Depth+1)) + return true; + + // Otherwise we definitely can't merge the ADD in. + AddrMode = BackupAddrMode; + AddrModeInsts.resize(OldSize); + break; + } + //case Instruction::Or: + // TODO: We can handle "Or Val, Imm" iff this OR is equivalent to an ADD. + //break; + case Instruction::Mul: + case Instruction::Shl: { + // Can only handle X*C and X << C. + ConstantInt *RHS = dyn_cast(AddrInst->getOperand(1)); + if (!RHS) return false; + int64_t Scale = RHS->getSExtValue(); + if (Opcode == Instruction::Shl) + Scale = 1LL << Scale; + + return MatchScaledValue(AddrInst->getOperand(0), Scale, Depth); + } + case Instruction::GetElementPtr: { + // Scan the GEP. We check it if it contains constant offsets and at most + // one variable offset. + int VariableOperand = -1; + unsigned VariableScale = 0; + + int64_t ConstantOffset = 0; + const TargetData *TD = TLI.getTargetData(); + gep_type_iterator GTI = gep_type_begin(AddrInst); + for (unsigned i = 1, e = AddrInst->getNumOperands(); i != e; ++i, ++GTI) { + if (const StructType *STy = dyn_cast(*GTI)) { + const StructLayout *SL = TD->getStructLayout(STy); + unsigned Idx = + cast(AddrInst->getOperand(i))->getZExtValue(); + ConstantOffset += SL->getElementOffset(Idx); + } else { + uint64_t TypeSize = TD->getTypeAllocSize(GTI.getIndexedType()); + if (ConstantInt *CI = dyn_cast(AddrInst->getOperand(i))) { + ConstantOffset += CI->getSExtValue()*TypeSize; + } else if (TypeSize) { // Scales of zero don't do anything. + // We only allow one variable index at the moment. + if (VariableOperand != -1) + return false; + + // Remember the variable index. + VariableOperand = i; + VariableScale = TypeSize; + } + } + } + + // A common case is for the GEP to only do a constant offset. In this case, + // just add it to the disp field and check validity. + if (VariableOperand == -1) { + AddrMode.BaseOffs += ConstantOffset; + if (ConstantOffset == 0 || TLI.isLegalAddressingMode(AddrMode, AccessTy)){ + // Check to see if we can fold the base pointer in too. + if (MatchAddr(AddrInst->getOperand(0), Depth+1)) + return true; + } + AddrMode.BaseOffs -= ConstantOffset; + return false; + } + + // Save the valid addressing mode in case we can't match. + ExtAddrMode BackupAddrMode = AddrMode; + unsigned OldSize = AddrModeInsts.size(); + + // See if the scale and offset amount is valid for this target. + AddrMode.BaseOffs += ConstantOffset; + + // Match the base operand of the GEP. + if (!MatchAddr(AddrInst->getOperand(0), Depth+1)) { + // If it couldn't be matched, just stuff the value in a register. + if (AddrMode.HasBaseReg) { + AddrMode = BackupAddrMode; + AddrModeInsts.resize(OldSize); + return false; + } + AddrMode.HasBaseReg = true; + AddrMode.BaseReg = AddrInst->getOperand(0); + } + + // Match the remaining variable portion of the GEP. + if (!MatchScaledValue(AddrInst->getOperand(VariableOperand), VariableScale, + Depth)) { + // If it couldn't be matched, try stuffing the base into a register + // instead of matching it, and retrying the match of the scale. + AddrMode = BackupAddrMode; + AddrModeInsts.resize(OldSize); + if (AddrMode.HasBaseReg) + return false; + AddrMode.HasBaseReg = true; + AddrMode.BaseReg = AddrInst->getOperand(0); + AddrMode.BaseOffs += ConstantOffset; + if (!MatchScaledValue(AddrInst->getOperand(VariableOperand), + VariableScale, Depth)) { + // If even that didn't work, bail. + AddrMode = BackupAddrMode; + AddrModeInsts.resize(OldSize); + return false; + } + } + + return true; + } + } + return false; +} + +/// MatchAddr - If we can, try to add the value of 'Addr' into the current +/// addressing mode. If Addr can't be added to AddrMode this returns false and +/// leaves AddrMode unmodified. This assumes that Addr is either a pointer type +/// or intptr_t for the target. +/// +bool AddressingModeMatcher::MatchAddr(Value *Addr, unsigned Depth) { + if (ConstantInt *CI = dyn_cast(Addr)) { + // Fold in immediates if legal for the target. + AddrMode.BaseOffs += CI->getSExtValue(); + if (TLI.isLegalAddressingMode(AddrMode, AccessTy)) + return true; + AddrMode.BaseOffs -= CI->getSExtValue(); + } else if (GlobalValue *GV = dyn_cast(Addr)) { + // If this is a global variable, try to fold it into the addressing mode. + if (AddrMode.BaseGV == 0) { + AddrMode.BaseGV = GV; + if (TLI.isLegalAddressingMode(AddrMode, AccessTy)) + return true; + AddrMode.BaseGV = 0; + } + } else if (Instruction *I = dyn_cast(Addr)) { + ExtAddrMode BackupAddrMode = AddrMode; + unsigned OldSize = AddrModeInsts.size(); + + // Check to see if it is possible to fold this operation. + if (MatchOperationAddr(I, I->getOpcode(), Depth)) { + // Okay, it's possible to fold this. Check to see if it is actually + // *profitable* to do so. We use a simple cost model to avoid increasing + // register pressure too much. + if (I->hasOneUse() || + IsProfitableToFoldIntoAddressingMode(I, BackupAddrMode, AddrMode)) { + AddrModeInsts.push_back(I); + return true; + } + + // It isn't profitable to do this, roll back. + //cerr << "NOT FOLDING: " << *I; + AddrMode = BackupAddrMode; + AddrModeInsts.resize(OldSize); + } + } else if (ConstantExpr *CE = dyn_cast(Addr)) { + if (MatchOperationAddr(CE, CE->getOpcode(), Depth)) + return true; + } else if (isa(Addr)) { + // Null pointer gets folded without affecting the addressing mode. + return true; + } + + // Worse case, the target should support [reg] addressing modes. :) + if (!AddrMode.HasBaseReg) { + AddrMode.HasBaseReg = true; + AddrMode.BaseReg = Addr; + // Still check for legality in case the target supports [imm] but not [i+r]. + if (TLI.isLegalAddressingMode(AddrMode, AccessTy)) + return true; + AddrMode.HasBaseReg = false; + AddrMode.BaseReg = 0; + } + + // If the base register is already taken, see if we can do [r+r]. + if (AddrMode.Scale == 0) { + AddrMode.Scale = 1; + AddrMode.ScaledReg = Addr; + if (TLI.isLegalAddressingMode(AddrMode, AccessTy)) + return true; + AddrMode.Scale = 0; + AddrMode.ScaledReg = 0; + } + // Couldn't match. + return false; +} + + +/// IsOperandAMemoryOperand - Check to see if all uses of OpVal by the specified +/// inline asm call are due to memory operands. If so, return true, otherwise +/// return false. +static bool IsOperandAMemoryOperand(CallInst *CI, InlineAsm *IA, Value *OpVal, + const TargetLowering &TLI) { + std::vector + Constraints = IA->ParseConstraints(); + + unsigned ArgNo = 1; // ArgNo - The operand of the CallInst. + for (unsigned i = 0, e = Constraints.size(); i != e; ++i) { + TargetLowering::AsmOperandInfo OpInfo(Constraints[i]); + + // Compute the value type for each operand. + switch (OpInfo.Type) { + case InlineAsm::isOutput: + if (OpInfo.isIndirect) + OpInfo.CallOperandVal = CI->getOperand(ArgNo++); + break; + case InlineAsm::isInput: + OpInfo.CallOperandVal = CI->getOperand(ArgNo++); + break; + case InlineAsm::isClobber: + // Nothing to do. + break; + } + + // Compute the constraint code and ConstraintType to use. + TLI.ComputeConstraintToUse(OpInfo, SDValue(), + OpInfo.ConstraintType == TargetLowering::C_Memory); + + // If this asm operand is our Value*, and if it isn't an indirect memory + // operand, we can't fold it! + if (OpInfo.CallOperandVal == OpVal && + (OpInfo.ConstraintType != TargetLowering::C_Memory || + !OpInfo.isIndirect)) + return false; + } + + return true; +} + + +/// FindAllMemoryUses - Recursively walk all the uses of I until we find a +/// memory use. If we find an obviously non-foldable instruction, return true. +/// Add the ultimately found memory instructions to MemoryUses. +static bool FindAllMemoryUses(Instruction *I, + SmallVectorImpl > &MemoryUses, + SmallPtrSet &ConsideredInsts, + const TargetLowering &TLI) { + // If we already considered this instruction, we're done. + if (!ConsideredInsts.insert(I)) + return false; + + // If this is an obviously unfoldable instruction, bail out. + if (!MightBeFoldableInst(I)) + return true; + + // Loop over all the uses, recursively processing them. + for (Value::use_iterator UI = I->use_begin(), E = I->use_end(); + UI != E; ++UI) { + if (LoadInst *LI = dyn_cast(*UI)) { + MemoryUses.push_back(std::make_pair(LI, UI.getOperandNo())); + continue; + } + + if (StoreInst *SI = dyn_cast(*UI)) { + if (UI.getOperandNo() == 0) return true; // Storing addr, not into addr. + MemoryUses.push_back(std::make_pair(SI, UI.getOperandNo())); + continue; + } + + if (CallInst *CI = dyn_cast(*UI)) { + InlineAsm *IA = dyn_cast(CI->getCalledValue()); + if (IA == 0) return true; + + // If this is a memory operand, we're cool, otherwise bail out. + if (!IsOperandAMemoryOperand(CI, IA, I, TLI)) + return true; + continue; + } + + if (FindAllMemoryUses(cast(*UI), MemoryUses, ConsideredInsts, + TLI)) + return true; + } + + return false; +} + + +/// ValueAlreadyLiveAtInst - Retrn true if Val is already known to be live at +/// the use site that we're folding it into. If so, there is no cost to +/// include it in the addressing mode. KnownLive1 and KnownLive2 are two values +/// that we know are live at the instruction already. +bool AddressingModeMatcher::ValueAlreadyLiveAtInst(Value *Val,Value *KnownLive1, + Value *KnownLive2) { + // If Val is either of the known-live values, we know it is live! + if (Val == 0 || Val == KnownLive1 || Val == KnownLive2) + return true; + + // All values other than instructions and arguments (e.g. constants) are live. + if (!isa(Val) && !isa(Val)) return true; + + // If Val is a constant sized alloca in the entry block, it is live, this is + // true because it is just a reference to the stack/frame pointer, which is + // live for the whole function. + if (AllocaInst *AI = dyn_cast(Val)) + if (AI->isStaticAlloca()) + return true; + + // Check to see if this value is already used in the memory instruction's + // block. If so, it's already live into the block at the very least, so we + // can reasonably fold it. + BasicBlock *MemBB = MemoryInst->getParent(); + for (Value::use_iterator UI = Val->use_begin(), E = Val->use_end(); + UI != E; ++UI) + // We know that uses of arguments and instructions have to be instructions. + if (cast(*UI)->getParent() == MemBB) + return true; + + return false; +} + + + +/// IsProfitableToFoldIntoAddressingMode - It is possible for the addressing +/// mode of the machine to fold the specified instruction into a load or store +/// that ultimately uses it. However, the specified instruction has multiple +/// uses. Given this, it may actually increase register pressure to fold it +/// into the load. For example, consider this code: +/// +/// X = ... +/// Y = X+1 +/// use(Y) -> nonload/store +/// Z = Y+1 +/// load Z +/// +/// In this case, Y has multiple uses, and can be folded into the load of Z +/// (yielding load [X+2]). However, doing this will cause both "X" and "X+1" to +/// be live at the use(Y) line. If we don't fold Y into load Z, we use one +/// fewer register. Since Y can't be folded into "use(Y)" we don't increase the +/// number of computations either. +/// +/// Note that this (like most of CodeGenPrepare) is just a rough heuristic. If +/// X was live across 'load Z' for other reasons, we actually *would* want to +/// fold the addressing mode in the Z case. This would make Y die earlier. +bool AddressingModeMatcher:: +IsProfitableToFoldIntoAddressingMode(Instruction *I, ExtAddrMode &AMBefore, + ExtAddrMode &AMAfter) { + if (IgnoreProfitability) return true; + + // AMBefore is the addressing mode before this instruction was folded into it, + // and AMAfter is the addressing mode after the instruction was folded. Get + // the set of registers referenced by AMAfter and subtract out those + // referenced by AMBefore: this is the set of values which folding in this + // address extends the lifetime of. + // + // Note that there are only two potential values being referenced here, + // BaseReg and ScaleReg (global addresses are always available, as are any + // folded immediates). + Value *BaseReg = AMAfter.BaseReg, *ScaledReg = AMAfter.ScaledReg; + + // If the BaseReg or ScaledReg was referenced by the previous addrmode, their + // lifetime wasn't extended by adding this instruction. + if (ValueAlreadyLiveAtInst(BaseReg, AMBefore.BaseReg, AMBefore.ScaledReg)) + BaseReg = 0; + if (ValueAlreadyLiveAtInst(ScaledReg, AMBefore.BaseReg, AMBefore.ScaledReg)) + ScaledReg = 0; + + // If folding this instruction (and it's subexprs) didn't extend any live + // ranges, we're ok with it. + if (BaseReg == 0 && ScaledReg == 0) + return true; + + // If all uses of this instruction are ultimately load/store/inlineasm's, + // check to see if their addressing modes will include this instruction. If + // so, we can fold it into all uses, so it doesn't matter if it has multiple + // uses. + SmallVector, 16> MemoryUses; + SmallPtrSet ConsideredInsts; + if (FindAllMemoryUses(I, MemoryUses, ConsideredInsts, TLI)) + return false; // Has a non-memory, non-foldable use! + + // Now that we know that all uses of this instruction are part of a chain of + // computation involving only operations that could theoretically be folded + // into a memory use, loop over each of these uses and see if they could + // *actually* fold the instruction. + SmallVector MatchedAddrModeInsts; + for (unsigned i = 0, e = MemoryUses.size(); i != e; ++i) { + Instruction *User = MemoryUses[i].first; + unsigned OpNo = MemoryUses[i].second; + + // Get the access type of this use. If the use isn't a pointer, we don't + // know what it accesses. + Value *Address = User->getOperand(OpNo); + if (!isa(Address->getType())) + return false; + const Type *AddressAccessTy = + cast(Address->getType())->getElementType(); + + // Do a match against the root of this address, ignoring profitability. This + // will tell us if the addressing mode for the memory operation will + // *actually* cover the shared instruction. + ExtAddrMode Result; + AddressingModeMatcher Matcher(MatchedAddrModeInsts, TLI, AddressAccessTy, + MemoryInst, Result); + Matcher.IgnoreProfitability = true; + bool Success = Matcher.MatchAddr(Address, 0); + Success = Success; assert(Success && "Couldn't select *anything*?"); + + // If the match didn't cover I, then it won't be shared by it. + if (std::find(MatchedAddrModeInsts.begin(), MatchedAddrModeInsts.end(), + I) == MatchedAddrModeInsts.end()) + return false; + + MatchedAddrModeInsts.clear(); + } + + return true; +} diff --git a/libclamav/c++/llvm/lib/Transforms/Utils/BasicBlockUtils.cpp b/libclamav/c++/llvm/lib/Transforms/Utils/BasicBlockUtils.cpp new file mode 100644 index 000000000..2974592fb --- /dev/null +++ b/libclamav/c++/llvm/lib/Transforms/Utils/BasicBlockUtils.cpp @@ -0,0 +1,689 @@ +//===-- BasicBlockUtils.cpp - BasicBlock Utilities -------------------------==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This family of functions perform manipulations on basic blocks, and +// instructions contained within basic blocks. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Transforms/Utils/BasicBlockUtils.h" +#include "llvm/Function.h" +#include "llvm/Instructions.h" +#include "llvm/IntrinsicInst.h" +#include "llvm/LLVMContext.h" +#include "llvm/Constant.h" +#include "llvm/Type.h" +#include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/Analysis/LoopInfo.h" +#include "llvm/Analysis/Dominators.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Transforms/Utils/Local.h" +#include "llvm/Transforms/Scalar.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/ValueHandle.h" +#include +using namespace llvm; + +/// DeleteDeadBlock - Delete the specified block, which must have no +/// predecessors. +void llvm::DeleteDeadBlock(BasicBlock *BB) { + assert((pred_begin(BB) == pred_end(BB) || + // Can delete self loop. + BB->getSinglePredecessor() == BB) && "Block is not dead!"); + TerminatorInst *BBTerm = BB->getTerminator(); + + // Loop through all of our successors and make sure they know that one + // of their predecessors is going away. + for (unsigned i = 0, e = BBTerm->getNumSuccessors(); i != e; ++i) + BBTerm->getSuccessor(i)->removePredecessor(BB); + + // Zap all the instructions in the block. + while (!BB->empty()) { + Instruction &I = BB->back(); + // If this instruction is used, replace uses with an arbitrary value. + // Because control flow can't get here, we don't care what we replace the + // value with. Note that since this block is unreachable, and all values + // contained within it must dominate their uses, that all uses will + // eventually be removed (they are themselves dead). + if (!I.use_empty()) + I.replaceAllUsesWith(UndefValue::get(I.getType())); + BB->getInstList().pop_back(); + } + + // Zap the block! + BB->eraseFromParent(); +} + +/// FoldSingleEntryPHINodes - We know that BB has one predecessor. If there are +/// any single-entry PHI nodes in it, fold them away. This handles the case +/// when all entries to the PHI nodes in a block are guaranteed equal, such as +/// when the block has exactly one predecessor. +void llvm::FoldSingleEntryPHINodes(BasicBlock *BB) { + while (PHINode *PN = dyn_cast(BB->begin())) { + if (PN->getIncomingValue(0) != PN) + PN->replaceAllUsesWith(PN->getIncomingValue(0)); + else + PN->replaceAllUsesWith(UndefValue::get(PN->getType())); + PN->eraseFromParent(); + } +} + + +/// DeleteDeadPHIs - Examine each PHI in the given block and delete it if it +/// is dead. Also recursively delete any operands that become dead as +/// a result. This includes tracing the def-use list from the PHI to see if +/// it is ultimately unused or if it reaches an unused cycle. +void llvm::DeleteDeadPHIs(BasicBlock *BB) { + // Recursively deleting a PHI may cause multiple PHIs to be deleted + // or RAUW'd undef, so use an array of WeakVH for the PHIs to delete. + SmallVector PHIs; + for (BasicBlock::iterator I = BB->begin(); + PHINode *PN = dyn_cast(I); ++I) + PHIs.push_back(PN); + + for (unsigned i = 0, e = PHIs.size(); i != e; ++i) + if (PHINode *PN = dyn_cast_or_null(PHIs[i].operator Value*())) + RecursivelyDeleteDeadPHINode(PN); +} + +/// MergeBlockIntoPredecessor - Attempts to merge a block into its predecessor, +/// if possible. The return value indicates success or failure. +bool llvm::MergeBlockIntoPredecessor(BasicBlock *BB, Pass *P) { + pred_iterator PI(pred_begin(BB)), PE(pred_end(BB)); + // Can't merge the entry block. Don't merge away blocks who have their + // address taken: this is a bug if the predecessor block is the entry node + // (because we'd end up taking the address of the entry) and undesirable in + // any case. + if (pred_begin(BB) == pred_end(BB) || + BB->hasAddressTaken()) return false; + + BasicBlock *PredBB = *PI++; + for (; PI != PE; ++PI) // Search all predecessors, see if they are all same + if (*PI != PredBB) { + PredBB = 0; // There are multiple different predecessors... + break; + } + + // Can't merge if there are multiple predecessors. + if (!PredBB) return false; + // Don't break self-loops. + if (PredBB == BB) return false; + // Don't break invokes. + if (isa(PredBB->getTerminator())) return false; + + succ_iterator SI(succ_begin(PredBB)), SE(succ_end(PredBB)); + BasicBlock* OnlySucc = BB; + for (; SI != SE; ++SI) + if (*SI != OnlySucc) { + OnlySucc = 0; // There are multiple distinct successors! + break; + } + + // Can't merge if there are multiple successors. + if (!OnlySucc) return false; + + // Can't merge if there is PHI loop. + for (BasicBlock::iterator BI = BB->begin(), BE = BB->end(); BI != BE; ++BI) { + if (PHINode *PN = dyn_cast(BI)) { + for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) + if (PN->getIncomingValue(i) == PN) + return false; + } else + break; + } + + // Begin by getting rid of unneeded PHIs. + while (PHINode *PN = dyn_cast(&BB->front())) { + PN->replaceAllUsesWith(PN->getIncomingValue(0)); + BB->getInstList().pop_front(); // Delete the phi node... + } + + // Delete the unconditional branch from the predecessor... + PredBB->getInstList().pop_back(); + + // Move all definitions in the successor to the predecessor... + PredBB->getInstList().splice(PredBB->end(), BB->getInstList()); + + // Make all PHI nodes that referred to BB now refer to Pred as their + // source... + BB->replaceAllUsesWith(PredBB); + + // Inherit predecessors name if it exists. + if (!PredBB->hasName()) + PredBB->takeName(BB); + + // Finally, erase the old block and update dominator info. + if (P) { + if (DominatorTree* DT = P->getAnalysisIfAvailable()) { + DomTreeNode* DTN = DT->getNode(BB); + DomTreeNode* PredDTN = DT->getNode(PredBB); + + if (DTN) { + SmallPtrSet Children(DTN->begin(), DTN->end()); + for (SmallPtrSet::iterator DI = Children.begin(), + DE = Children.end(); DI != DE; ++DI) + DT->changeImmediateDominator(*DI, PredDTN); + + DT->eraseNode(BB); + } + } + } + + BB->eraseFromParent(); + + + return true; +} + +/// ReplaceInstWithValue - Replace all uses of an instruction (specified by BI) +/// with a value, then remove and delete the original instruction. +/// +void llvm::ReplaceInstWithValue(BasicBlock::InstListType &BIL, + BasicBlock::iterator &BI, Value *V) { + Instruction &I = *BI; + // Replaces all of the uses of the instruction with uses of the value + I.replaceAllUsesWith(V); + + // Make sure to propagate a name if there is one already. + if (I.hasName() && !V->hasName()) + V->takeName(&I); + + // Delete the unnecessary instruction now... + BI = BIL.erase(BI); +} + + +/// ReplaceInstWithInst - Replace the instruction specified by BI with the +/// instruction specified by I. The original instruction is deleted and BI is +/// updated to point to the new instruction. +/// +void llvm::ReplaceInstWithInst(BasicBlock::InstListType &BIL, + BasicBlock::iterator &BI, Instruction *I) { + assert(I->getParent() == 0 && + "ReplaceInstWithInst: Instruction already inserted into basic block!"); + + // Insert the new instruction into the basic block... + BasicBlock::iterator New = BIL.insert(BI, I); + + // Replace all uses of the old instruction, and delete it. + ReplaceInstWithValue(BIL, BI, I); + + // Move BI back to point to the newly inserted instruction + BI = New; +} + +/// ReplaceInstWithInst - Replace the instruction specified by From with the +/// instruction specified by To. +/// +void llvm::ReplaceInstWithInst(Instruction *From, Instruction *To) { + BasicBlock::iterator BI(From); + ReplaceInstWithInst(From->getParent()->getInstList(), BI, To); +} + +/// RemoveSuccessor - Change the specified terminator instruction such that its +/// successor SuccNum no longer exists. Because this reduces the outgoing +/// degree of the current basic block, the actual terminator instruction itself +/// may have to be changed. In the case where the last successor of the block +/// is deleted, a return instruction is inserted in its place which can cause a +/// surprising change in program behavior if it is not expected. +/// +void llvm::RemoveSuccessor(TerminatorInst *TI, unsigned SuccNum) { + assert(SuccNum < TI->getNumSuccessors() && + "Trying to remove a nonexistant successor!"); + + // If our old successor block contains any PHI nodes, remove the entry in the + // PHI nodes that comes from this branch... + // + BasicBlock *BB = TI->getParent(); + TI->getSuccessor(SuccNum)->removePredecessor(BB); + + TerminatorInst *NewTI = 0; + switch (TI->getOpcode()) { + case Instruction::Br: + // If this is a conditional branch... convert to unconditional branch. + if (TI->getNumSuccessors() == 2) { + cast(TI)->setUnconditionalDest(TI->getSuccessor(1-SuccNum)); + } else { // Otherwise convert to a return instruction... + Value *RetVal = 0; + + // Create a value to return... if the function doesn't return null... + if (BB->getParent()->getReturnType() != Type::getVoidTy(TI->getContext())) + RetVal = Constant::getNullValue(BB->getParent()->getReturnType()); + + // Create the return... + NewTI = ReturnInst::Create(TI->getContext(), RetVal); + } + break; + + case Instruction::Invoke: // Should convert to call + case Instruction::Switch: // Should remove entry + default: + case Instruction::Ret: // Cannot happen, has no successors! + llvm_unreachable("Unhandled terminator instruction type in RemoveSuccessor!"); + } + + if (NewTI) // If it's a different instruction, replace. + ReplaceInstWithInst(TI, NewTI); +} + +/// SplitEdge - Split the edge connecting specified block. Pass P must +/// not be NULL. +BasicBlock *llvm::SplitEdge(BasicBlock *BB, BasicBlock *Succ, Pass *P) { + TerminatorInst *LatchTerm = BB->getTerminator(); + unsigned SuccNum = 0; +#ifndef NDEBUG + unsigned e = LatchTerm->getNumSuccessors(); +#endif + for (unsigned i = 0; ; ++i) { + assert(i != e && "Didn't find edge?"); + if (LatchTerm->getSuccessor(i) == Succ) { + SuccNum = i; + break; + } + } + + // If this is a critical edge, let SplitCriticalEdge do it. + if (SplitCriticalEdge(BB->getTerminator(), SuccNum, P)) + return LatchTerm->getSuccessor(SuccNum); + + // If the edge isn't critical, then BB has a single successor or Succ has a + // single pred. Split the block. + BasicBlock::iterator SplitPoint; + if (BasicBlock *SP = Succ->getSinglePredecessor()) { + // If the successor only has a single pred, split the top of the successor + // block. + assert(SP == BB && "CFG broken"); + SP = NULL; + return SplitBlock(Succ, Succ->begin(), P); + } else { + // Otherwise, if BB has a single successor, split it at the bottom of the + // block. + assert(BB->getTerminator()->getNumSuccessors() == 1 && + "Should have a single succ!"); + return SplitBlock(BB, BB->getTerminator(), P); + } +} + +/// SplitBlock - Split the specified block at the specified instruction - every +/// thing before SplitPt stays in Old and everything starting with SplitPt moves +/// to a new block. The two blocks are joined by an unconditional branch and +/// the loop info is updated. +/// +BasicBlock *llvm::SplitBlock(BasicBlock *Old, Instruction *SplitPt, Pass *P) { + BasicBlock::iterator SplitIt = SplitPt; + while (isa(SplitIt)) + ++SplitIt; + BasicBlock *New = Old->splitBasicBlock(SplitIt, Old->getName()+".split"); + + // The new block lives in whichever loop the old one did. This preserves + // LCSSA as well, because we force the split point to be after any PHI nodes. + if (LoopInfo* LI = P->getAnalysisIfAvailable()) + if (Loop *L = LI->getLoopFor(Old)) + L->addBasicBlockToLoop(New, LI->getBase()); + + if (DominatorTree *DT = P->getAnalysisIfAvailable()) + { + // Old dominates New. New node domiantes all other nodes dominated by Old. + DomTreeNode *OldNode = DT->getNode(Old); + std::vector Children; + for (DomTreeNode::iterator I = OldNode->begin(), E = OldNode->end(); + I != E; ++I) + Children.push_back(*I); + + DomTreeNode *NewNode = DT->addNewBlock(New,Old); + + for (std::vector::iterator I = Children.begin(), + E = Children.end(); I != E; ++I) + DT->changeImmediateDominator(*I, NewNode); + } + + if (DominanceFrontier *DF = P->getAnalysisIfAvailable()) + DF->splitBlock(Old); + + return New; +} + + +/// SplitBlockPredecessors - This method transforms BB by introducing a new +/// basic block into the function, and moving some of the predecessors of BB to +/// be predecessors of the new block. The new predecessors are indicated by the +/// Preds array, which has NumPreds elements in it. The new block is given a +/// suffix of 'Suffix'. +/// +/// This currently updates the LLVM IR, AliasAnalysis, DominatorTree, +/// DominanceFrontier, LoopInfo, and LCCSA but no other analyses. +/// In particular, it does not preserve LoopSimplify (because it's +/// complicated to handle the case where one of the edges being split +/// is an exit of a loop with other exits). +/// +BasicBlock *llvm::SplitBlockPredecessors(BasicBlock *BB, + BasicBlock *const *Preds, + unsigned NumPreds, const char *Suffix, + Pass *P) { + // Create new basic block, insert right before the original block. + BasicBlock *NewBB = BasicBlock::Create(BB->getContext(), BB->getName()+Suffix, + BB->getParent(), BB); + + // The new block unconditionally branches to the old block. + BranchInst *BI = BranchInst::Create(BB, NewBB); + + LoopInfo *LI = P ? P->getAnalysisIfAvailable() : 0; + Loop *L = LI ? LI->getLoopFor(BB) : 0; + bool PreserveLCSSA = P->mustPreserveAnalysisID(LCSSAID); + + // Move the edges from Preds to point to NewBB instead of BB. + // While here, if we need to preserve loop analyses, collect + // some information about how this split will affect loops. + bool HasLoopExit = false; + bool IsLoopEntry = !!L; + bool SplitMakesNewLoopHeader = false; + for (unsigned i = 0; i != NumPreds; ++i) { + // This is slightly more strict than necessary; the minimum requirement + // is that there be no more than one indirectbr branching to BB. And + // all BlockAddress uses would need to be updated. + assert(!isa(Preds[i]->getTerminator()) && + "Cannot split an edge from an IndirectBrInst"); + + Preds[i]->getTerminator()->replaceUsesOfWith(BB, NewBB); + + if (LI) { + // If we need to preserve LCSSA, determine if any of + // the preds is a loop exit. + if (PreserveLCSSA) + if (Loop *PL = LI->getLoopFor(Preds[i])) + if (!PL->contains(BB)) + HasLoopExit = true; + // If we need to preserve LoopInfo, note whether any of the + // preds crosses an interesting loop boundary. + if (L) { + if (L->contains(Preds[i])) + IsLoopEntry = false; + else + SplitMakesNewLoopHeader = true; + } + } + } + + // Update dominator tree and dominator frontier if available. + DominatorTree *DT = P ? P->getAnalysisIfAvailable() : 0; + if (DT) + DT->splitBlock(NewBB); + if (DominanceFrontier *DF = P ? P->getAnalysisIfAvailable():0) + DF->splitBlock(NewBB); + + // Insert a new PHI node into NewBB for every PHI node in BB and that new PHI + // node becomes an incoming value for BB's phi node. However, if the Preds + // list is empty, we need to insert dummy entries into the PHI nodes in BB to + // account for the newly created predecessor. + if (NumPreds == 0) { + // Insert dummy values as the incoming value. + for (BasicBlock::iterator I = BB->begin(); isa(I); ++I) + cast(I)->addIncoming(UndefValue::get(I->getType()), NewBB); + return NewBB; + } + + AliasAnalysis *AA = P ? P->getAnalysisIfAvailable() : 0; + + if (L) { + if (IsLoopEntry) { + // Add the new block to the nearest enclosing loop (and not an + // adjacent loop). To find this, examine each of the predecessors and + // determine which loops enclose them, and select the most-nested loop + // which contains the loop containing the block being split. + Loop *InnermostPredLoop = 0; + for (unsigned i = 0; i != NumPreds; ++i) + if (Loop *PredLoop = LI->getLoopFor(Preds[i])) { + // Seek a loop which actually contains the block being split (to + // avoid adjacent loops). + while (PredLoop && !PredLoop->contains(BB)) + PredLoop = PredLoop->getParentLoop(); + // Select the most-nested of these loops which contains the block. + if (PredLoop && + PredLoop->contains(BB) && + (!InnermostPredLoop || + InnermostPredLoop->getLoopDepth() < PredLoop->getLoopDepth())) + InnermostPredLoop = PredLoop; + } + if (InnermostPredLoop) + InnermostPredLoop->addBasicBlockToLoop(NewBB, LI->getBase()); + } else { + L->addBasicBlockToLoop(NewBB, LI->getBase()); + if (SplitMakesNewLoopHeader) + L->moveToHeader(NewBB); + } + } + + // Otherwise, create a new PHI node in NewBB for each PHI node in BB. + for (BasicBlock::iterator I = BB->begin(); isa(I); ) { + PHINode *PN = cast(I++); + + // Check to see if all of the values coming in are the same. If so, we + // don't need to create a new PHI node, unless it's needed for LCSSA. + Value *InVal = 0; + if (!HasLoopExit) { + InVal = PN->getIncomingValueForBlock(Preds[0]); + for (unsigned i = 1; i != NumPreds; ++i) + if (InVal != PN->getIncomingValueForBlock(Preds[i])) { + InVal = 0; + break; + } + } + + if (InVal) { + // If all incoming values for the new PHI would be the same, just don't + // make a new PHI. Instead, just remove the incoming values from the old + // PHI. + for (unsigned i = 0; i != NumPreds; ++i) + PN->removeIncomingValue(Preds[i], false); + } else { + // If the values coming into the block are not the same, we need a PHI. + // Create the new PHI node, insert it into NewBB at the end of the block + PHINode *NewPHI = + PHINode::Create(PN->getType(), PN->getName()+".ph", BI); + if (AA) AA->copyValue(PN, NewPHI); + + // Move all of the PHI values for 'Preds' to the new PHI. + for (unsigned i = 0; i != NumPreds; ++i) { + Value *V = PN->removeIncomingValue(Preds[i], false); + NewPHI->addIncoming(V, Preds[i]); + } + InVal = NewPHI; + } + + // Add an incoming value to the PHI node in the loop for the preheader + // edge. + PN->addIncoming(InVal, NewBB); + } + + return NewBB; +} + +/// FindFunctionBackedges - Analyze the specified function to find all of the +/// loop backedges in the function and return them. This is a relatively cheap +/// (compared to computing dominators and loop info) analysis. +/// +/// The output is added to Result, as pairs of edge info. +void llvm::FindFunctionBackedges(const Function &F, + SmallVectorImpl > &Result) { + const BasicBlock *BB = &F.getEntryBlock(); + if (succ_begin(BB) == succ_end(BB)) + return; + + SmallPtrSet Visited; + SmallVector, 8> VisitStack; + SmallPtrSet InStack; + + Visited.insert(BB); + VisitStack.push_back(std::make_pair(BB, succ_begin(BB))); + InStack.insert(BB); + do { + std::pair &Top = VisitStack.back(); + const BasicBlock *ParentBB = Top.first; + succ_const_iterator &I = Top.second; + + bool FoundNew = false; + while (I != succ_end(ParentBB)) { + BB = *I++; + if (Visited.insert(BB)) { + FoundNew = true; + break; + } + // Successor is in VisitStack, it's a back edge. + if (InStack.count(BB)) + Result.push_back(std::make_pair(ParentBB, BB)); + } + + if (FoundNew) { + // Go down one level if there is a unvisited successor. + InStack.insert(BB); + VisitStack.push_back(std::make_pair(BB, succ_begin(BB))); + } else { + // Go up one level. + InStack.erase(VisitStack.pop_back_val().first); + } + } while (!VisitStack.empty()); + + +} + + + +/// AreEquivalentAddressValues - Test if A and B will obviously have the same +/// value. This includes recognizing that %t0 and %t1 will have the same +/// value in code like this: +/// %t0 = getelementptr \@a, 0, 3 +/// store i32 0, i32* %t0 +/// %t1 = getelementptr \@a, 0, 3 +/// %t2 = load i32* %t1 +/// +static bool AreEquivalentAddressValues(const Value *A, const Value *B) { + // Test if the values are trivially equivalent. + if (A == B) return true; + + // Test if the values come from identical arithmetic instructions. + // Use isIdenticalToWhenDefined instead of isIdenticalTo because + // this function is only used when one address use dominates the + // other, which means that they'll always either have the same + // value or one of them will have an undefined value. + if (isa(A) || isa(A) || + isa(A) || isa(A)) + if (const Instruction *BI = dyn_cast(B)) + if (cast(A)->isIdenticalToWhenDefined(BI)) + return true; + + // Otherwise they may not be equivalent. + return false; +} + +/// FindAvailableLoadedValue - Scan the ScanBB block backwards (starting at the +/// instruction before ScanFrom) checking to see if we have the value at the +/// memory address *Ptr locally available within a small number of instructions. +/// If the value is available, return it. +/// +/// If not, return the iterator for the last validated instruction that the +/// value would be live through. If we scanned the entire block and didn't find +/// something that invalidates *Ptr or provides it, ScanFrom would be left at +/// begin() and this returns null. ScanFrom could also be left +/// +/// MaxInstsToScan specifies the maximum instructions to scan in the block. If +/// it is set to 0, it will scan the whole block. You can also optionally +/// specify an alias analysis implementation, which makes this more precise. +Value *llvm::FindAvailableLoadedValue(Value *Ptr, BasicBlock *ScanBB, + BasicBlock::iterator &ScanFrom, + unsigned MaxInstsToScan, + AliasAnalysis *AA) { + if (MaxInstsToScan == 0) MaxInstsToScan = ~0U; + + // If we're using alias analysis to disambiguate get the size of *Ptr. + unsigned AccessSize = 0; + if (AA) { + const Type *AccessTy = cast(Ptr->getType())->getElementType(); + AccessSize = AA->getTypeStoreSize(AccessTy); + } + + while (ScanFrom != ScanBB->begin()) { + // We must ignore debug info directives when counting (otherwise they + // would affect codegen). + Instruction *Inst = --ScanFrom; + if (isa(Inst)) + continue; + // We skip pointer-to-pointer bitcasts, which are NOPs. + // It is necessary for correctness to skip those that feed into a + // llvm.dbg.declare, as these are not present when debugging is off. + if (isa(Inst) && isa(Inst->getType())) + continue; + + // Restore ScanFrom to expected value in case next test succeeds + ScanFrom++; + + // Don't scan huge blocks. + if (MaxInstsToScan-- == 0) return 0; + + --ScanFrom; + // If this is a load of Ptr, the loaded value is available. + if (LoadInst *LI = dyn_cast(Inst)) + if (AreEquivalentAddressValues(LI->getOperand(0), Ptr)) + return LI; + + if (StoreInst *SI = dyn_cast(Inst)) { + // If this is a store through Ptr, the value is available! + if (AreEquivalentAddressValues(SI->getOperand(1), Ptr)) + return SI->getOperand(0); + + // If Ptr is an alloca and this is a store to a different alloca, ignore + // the store. This is a trivial form of alias analysis that is important + // for reg2mem'd code. + if ((isa(Ptr) || isa(Ptr)) && + (isa(SI->getOperand(1)) || + isa(SI->getOperand(1)))) + continue; + + // If we have alias analysis and it says the store won't modify the loaded + // value, ignore the store. + if (AA && + (AA->getModRefInfo(SI, Ptr, AccessSize) & AliasAnalysis::Mod) == 0) + continue; + + // Otherwise the store that may or may not alias the pointer, bail out. + ++ScanFrom; + return 0; + } + + // If this is some other instruction that may clobber Ptr, bail out. + if (Inst->mayWriteToMemory()) { + // If alias analysis claims that it really won't modify the load, + // ignore it. + if (AA && + (AA->getModRefInfo(Inst, Ptr, AccessSize) & AliasAnalysis::Mod) == 0) + continue; + + // May modify the pointer, bail out. + ++ScanFrom; + return 0; + } + } + + // Got to the start of the block, we didn't find it, but are done for this + // block. + return 0; +} + +/// CopyPrecedingStopPoint - If I is immediately preceded by a StopPoint, +/// make a copy of the stoppoint before InsertPos (presumably before copying +/// or moving I). +void llvm::CopyPrecedingStopPoint(Instruction *I, + BasicBlock::iterator InsertPos) { + if (I != I->getParent()->begin()) { + BasicBlock::iterator BBI = I; --BBI; + if (DbgStopPointInst *DSPI = dyn_cast(BBI)) { + CallInst *newDSPI = cast(DSPI->clone()); + newDSPI->insertBefore(InsertPos); + } + } +} diff --git a/libclamav/c++/llvm/lib/Transforms/Utils/BasicInliner.cpp b/libclamav/c++/llvm/lib/Transforms/Utils/BasicInliner.cpp new file mode 100644 index 000000000..b5ffe0606 --- /dev/null +++ b/libclamav/c++/llvm/lib/Transforms/Utils/BasicInliner.cpp @@ -0,0 +1,181 @@ +//===- BasicInliner.cpp - Basic function level inliner --------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines a simple function based inliner that does not use +// call graph information. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "basicinliner" +#include "llvm/Module.h" +#include "llvm/Function.h" +#include "llvm/Transforms/Utils/BasicInliner.h" +#include "llvm/Transforms/Utils/Cloning.h" +#include "llvm/Support/CallSite.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/ADT/SmallPtrSet.h" +#include + +using namespace llvm; + +static cl::opt +BasicInlineThreshold("basic-inline-threshold", cl::Hidden, cl::init(200), + cl::desc("Control the amount of basic inlining to perform (default = 200)")); + +namespace llvm { + + /// BasicInlinerImpl - BasicInliner implemantation class. This hides + /// container info, used by basic inliner, from public interface. + struct BasicInlinerImpl { + + BasicInlinerImpl(const BasicInlinerImpl&); // DO NOT IMPLEMENT + void operator=(const BasicInlinerImpl&); // DO NO IMPLEMENT + public: + BasicInlinerImpl(TargetData *T) : TD(T) {} + + /// addFunction - Add function into the list of functions to process. + /// All functions must be inserted using this interface before invoking + /// inlineFunctions(). + void addFunction(Function *F) { + Functions.push_back(F); + } + + /// neverInlineFunction - Sometimes a function is never to be inlined + /// because of one or other reason. + void neverInlineFunction(Function *F) { + NeverInline.insert(F); + } + + /// inlineFuctions - Walk all call sites in all functions supplied by + /// client. Inline as many call sites as possible. Delete completely + /// inlined functions. + void inlineFunctions(); + + private: + TargetData *TD; + std::vector Functions; + SmallPtrSet NeverInline; + SmallPtrSet DeadFunctions; + InlineCostAnalyzer CA; + }; + +/// inlineFuctions - Walk all call sites in all functions supplied by +/// client. Inline as many call sites as possible. Delete completely +/// inlined functions. +void BasicInlinerImpl::inlineFunctions() { + + // Scan through and identify all call sites ahead of time so that we only + // inline call sites in the original functions, not call sites that result + // from inlining other functions. + std::vector CallSites; + + for (std::vector::iterator FI = Functions.begin(), + FE = Functions.end(); FI != FE; ++FI) { + Function *F = *FI; + for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) + for (BasicBlock::iterator I = BB->begin(); I != BB->end(); ++I) { + CallSite CS = CallSite::get(I); + if (CS.getInstruction() && CS.getCalledFunction() + && !CS.getCalledFunction()->isDeclaration()) + CallSites.push_back(CS); + } + } + + DEBUG(errs() << ": " << CallSites.size() << " call sites.\n"); + + // Inline call sites. + bool Changed = false; + do { + Changed = false; + for (unsigned index = 0; index != CallSites.size() && !CallSites.empty(); + ++index) { + CallSite CS = CallSites[index]; + if (Function *Callee = CS.getCalledFunction()) { + + // Eliminate calls that are never inlinable. + if (Callee->isDeclaration() || + CS.getInstruction()->getParent()->getParent() == Callee) { + CallSites.erase(CallSites.begin() + index); + --index; + continue; + } + InlineCost IC = CA.getInlineCost(CS, NeverInline); + if (IC.isAlways()) { + DEBUG(errs() << " Inlining: cost=always" + <<", call: " << *CS.getInstruction()); + } else if (IC.isNever()) { + DEBUG(errs() << " NOT Inlining: cost=never" + <<", call: " << *CS.getInstruction()); + continue; + } else { + int Cost = IC.getValue(); + + if (Cost >= (int) BasicInlineThreshold) { + DEBUG(errs() << " NOT Inlining: cost = " << Cost + << ", call: " << *CS.getInstruction()); + continue; + } else { + DEBUG(errs() << " Inlining: cost = " << Cost + << ", call: " << *CS.getInstruction()); + } + } + + // Inline + if (InlineFunction(CS, NULL, TD)) { + if (Callee->use_empty() && (Callee->hasLocalLinkage() || + Callee->hasAvailableExternallyLinkage())) + DeadFunctions.insert(Callee); + Changed = true; + CallSites.erase(CallSites.begin() + index); + --index; + } + } + } + } while (Changed); + + // Remove completely inlined functions from module. + for(SmallPtrSet::iterator I = DeadFunctions.begin(), + E = DeadFunctions.end(); I != E; ++I) { + Function *D = *I; + Module *M = D->getParent(); + M->getFunctionList().remove(D); + } +} + +BasicInliner::BasicInliner(TargetData *TD) { + Impl = new BasicInlinerImpl(TD); +} + +BasicInliner::~BasicInliner() { + delete Impl; +} + +/// addFunction - Add function into the list of functions to process. +/// All functions must be inserted using this interface before invoking +/// inlineFunctions(). +void BasicInliner::addFunction(Function *F) { + Impl->addFunction(F); +} + +/// neverInlineFunction - Sometimes a function is never to be inlined because +/// of one or other reason. +void BasicInliner::neverInlineFunction(Function *F) { + Impl->neverInlineFunction(F); +} + +/// inlineFuctions - Walk all call sites in all functions supplied by +/// client. Inline as many call sites as possible. Delete completely +/// inlined functions. +void BasicInliner::inlineFunctions() { + Impl->inlineFunctions(); +} + +} diff --git a/libclamav/c++/llvm/lib/Transforms/Utils/BreakCriticalEdges.cpp b/libclamav/c++/llvm/lib/Transforms/Utils/BreakCriticalEdges.cpp new file mode 100644 index 000000000..ccd97c8bc --- /dev/null +++ b/libclamav/c++/llvm/lib/Transforms/Utils/BreakCriticalEdges.cpp @@ -0,0 +1,390 @@ +//===- BreakCriticalEdges.cpp - Critical Edge Elimination Pass ------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// BreakCriticalEdges pass - Break all of the critical edges in the CFG by +// inserting a dummy basic block. This pass may be "required" by passes that +// cannot deal with critical edges. For this usage, the structure type is +// forward declared. This pass obviously invalidates the CFG, but can update +// forward dominator (set, immediate dominators, tree, and frontier) +// information. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "break-crit-edges" +#include "llvm/Transforms/Scalar.h" +#include "llvm/Transforms/Utils/BasicBlockUtils.h" +#include "llvm/Analysis/Dominators.h" +#include "llvm/Analysis/LoopInfo.h" +#include "llvm/Analysis/ProfileInfo.h" +#include "llvm/Function.h" +#include "llvm/Instructions.h" +#include "llvm/Type.h" +#include "llvm/Support/CFG.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/Statistic.h" +using namespace llvm; + +STATISTIC(NumBroken, "Number of blocks inserted"); + +namespace { + struct BreakCriticalEdges : public FunctionPass { + static char ID; // Pass identification, replacement for typeid + BreakCriticalEdges() : FunctionPass(&ID) {} + + virtual bool runOnFunction(Function &F); + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.addPreserved(); + AU.addPreserved(); + AU.addPreserved(); + AU.addPreserved(); + + // No loop canonicalization guarantees are broken by this pass. + AU.addPreservedID(LoopSimplifyID); + } + }; +} + +char BreakCriticalEdges::ID = 0; +static RegisterPass +X("break-crit-edges", "Break critical edges in CFG"); + +// Publically exposed interface to pass... +const PassInfo *const llvm::BreakCriticalEdgesID = &X; +FunctionPass *llvm::createBreakCriticalEdgesPass() { + return new BreakCriticalEdges(); +} + +// runOnFunction - Loop over all of the edges in the CFG, breaking critical +// edges as they are found. +// +bool BreakCriticalEdges::runOnFunction(Function &F) { + bool Changed = false; + for (Function::iterator I = F.begin(), E = F.end(); I != E; ++I) { + TerminatorInst *TI = I->getTerminator(); + if (TI->getNumSuccessors() > 1 && !isa(TI)) + for (unsigned i = 0, e = TI->getNumSuccessors(); i != e; ++i) + if (SplitCriticalEdge(TI, i, this)) { + ++NumBroken; + Changed = true; + } + } + + return Changed; +} + +//===----------------------------------------------------------------------===// +// Implementation of the external critical edge manipulation functions +//===----------------------------------------------------------------------===// + +// isCriticalEdge - Return true if the specified edge is a critical edge. +// Critical edges are edges from a block with multiple successors to a block +// with multiple predecessors. +// +bool llvm::isCriticalEdge(const TerminatorInst *TI, unsigned SuccNum, + bool AllowIdenticalEdges) { + assert(SuccNum < TI->getNumSuccessors() && "Illegal edge specification!"); + if (TI->getNumSuccessors() == 1) return false; + + const BasicBlock *Dest = TI->getSuccessor(SuccNum); + pred_const_iterator I = pred_begin(Dest), E = pred_end(Dest); + + // If there is more than one predecessor, this is a critical edge... + assert(I != E && "No preds, but we have an edge to the block?"); + const BasicBlock *FirstPred = *I; + ++I; // Skip one edge due to the incoming arc from TI. + if (!AllowIdenticalEdges) + return I != E; + + // If AllowIdenticalEdges is true, then we allow this edge to be considered + // non-critical iff all preds come from TI's block. + while (I != E) { + if (*I != FirstPred) + return true; + // Note: leave this as is until no one ever compiles with either gcc 4.0.1 + // or Xcode 2. This seems to work around the pred_iterator assert in PR 2207 + E = pred_end(*I); + ++I; + } + return false; +} + +/// CreatePHIsForSplitLoopExit - When a loop exit edge is split, LCSSA form +/// may require new PHIs in the new exit block. This function inserts the +/// new PHIs, as needed. Preds is a list of preds inside the loop, SplitBB +/// is the new loop exit block, and DestBB is the old loop exit, now the +/// successor of SplitBB. +static void CreatePHIsForSplitLoopExit(SmallVectorImpl &Preds, + BasicBlock *SplitBB, + BasicBlock *DestBB) { + // SplitBB shouldn't have anything non-trivial in it yet. + assert(SplitBB->getFirstNonPHI() == SplitBB->getTerminator() && + "SplitBB has non-PHI nodes!"); + + // For each PHI in the destination block... + for (BasicBlock::iterator I = DestBB->begin(); + PHINode *PN = dyn_cast(I); ++I) { + unsigned Idx = PN->getBasicBlockIndex(SplitBB); + Value *V = PN->getIncomingValue(Idx); + // If the input is a PHI which already satisfies LCSSA, don't create + // a new one. + if (const PHINode *VP = dyn_cast(V)) + if (VP->getParent() == SplitBB) + continue; + // Otherwise a new PHI is needed. Create one and populate it. + PHINode *NewPN = PHINode::Create(PN->getType(), "split", + SplitBB->getTerminator()); + for (unsigned i = 0, e = Preds.size(); i != e; ++i) + NewPN->addIncoming(V, Preds[i]); + // Update the original PHI. + PN->setIncomingValue(Idx, NewPN); + } +} + +/// SplitCriticalEdge - If this edge is a critical edge, insert a new node to +/// split the critical edge. This will update DominatorTree and +/// DominatorFrontier information if it is available, thus calling this pass +/// will not invalidate either of them. This returns the new block if the edge +/// was split, null otherwise. +/// +/// If MergeIdenticalEdges is true (not the default), *all* edges from TI to the +/// specified successor will be merged into the same critical edge block. +/// This is most commonly interesting with switch instructions, which may +/// have many edges to any one destination. This ensures that all edges to that +/// dest go to one block instead of each going to a different block, but isn't +/// the standard definition of a "critical edge". +/// +/// It is invalid to call this function on a critical edge that starts at an +/// IndirectBrInst. Splitting these edges will almost always create an invalid +/// program because the address of the new block won't be the one that is jumped +/// to. +/// +BasicBlock *llvm::SplitCriticalEdge(TerminatorInst *TI, unsigned SuccNum, + Pass *P, bool MergeIdenticalEdges) { + if (!isCriticalEdge(TI, SuccNum, MergeIdenticalEdges)) return 0; + + assert(!isa(TI) && + "Cannot split critical edge from IndirectBrInst"); + + BasicBlock *TIBB = TI->getParent(); + BasicBlock *DestBB = TI->getSuccessor(SuccNum); + + // Create a new basic block, linking it into the CFG. + BasicBlock *NewBB = BasicBlock::Create(TI->getContext(), + TIBB->getName() + "." + DestBB->getName() + "_crit_edge"); + // Create our unconditional branch... + BranchInst::Create(DestBB, NewBB); + + // Branch to the new block, breaking the edge. + TI->setSuccessor(SuccNum, NewBB); + + // Insert the block into the function... right after the block TI lives in. + Function &F = *TIBB->getParent(); + Function::iterator FBBI = TIBB; + F.getBasicBlockList().insert(++FBBI, NewBB); + + // If there are any PHI nodes in DestBB, we need to update them so that they + // merge incoming values from NewBB instead of from TIBB. + // + for (BasicBlock::iterator I = DestBB->begin(); isa(I); ++I) { + PHINode *PN = cast(I); + // We no longer enter through TIBB, now we come in through NewBB. Revector + // exactly one entry in the PHI node that used to come from TIBB to come + // from NewBB. + int BBIdx = PN->getBasicBlockIndex(TIBB); + PN->setIncomingBlock(BBIdx, NewBB); + } + + // If there are any other edges from TIBB to DestBB, update those to go + // through the split block, making those edges non-critical as well (and + // reducing the number of phi entries in the DestBB if relevant). + if (MergeIdenticalEdges) { + for (unsigned i = SuccNum+1, e = TI->getNumSuccessors(); i != e; ++i) { + if (TI->getSuccessor(i) != DestBB) continue; + + // Remove an entry for TIBB from DestBB phi nodes. + DestBB->removePredecessor(TIBB); + + // We found another edge to DestBB, go to NewBB instead. + TI->setSuccessor(i, NewBB); + } + } + + + + // If we don't have a pass object, we can't update anything... + if (P == 0) return NewBB; + + // Now update analysis information. Since the only predecessor of NewBB is + // the TIBB, TIBB clearly dominates NewBB. TIBB usually doesn't dominate + // anything, as there are other successors of DestBB. However, if all other + // predecessors of DestBB are already dominated by DestBB (e.g. DestBB is a + // loop header) then NewBB dominates DestBB. + SmallVector OtherPreds; + + for (pred_iterator I = pred_begin(DestBB), E = pred_end(DestBB); I != E; ++I) + if (*I != NewBB) + OtherPreds.push_back(*I); + + bool NewBBDominatesDestBB = true; + + // Should we update DominatorTree information? + if (DominatorTree *DT = P->getAnalysisIfAvailable()) { + DomTreeNode *TINode = DT->getNode(TIBB); + + // The new block is not the immediate dominator for any other nodes, but + // TINode is the immediate dominator for the new node. + // + if (TINode) { // Don't break unreachable code! + DomTreeNode *NewBBNode = DT->addNewBlock(NewBB, TIBB); + DomTreeNode *DestBBNode = 0; + + // If NewBBDominatesDestBB hasn't been computed yet, do so with DT. + if (!OtherPreds.empty()) { + DestBBNode = DT->getNode(DestBB); + while (!OtherPreds.empty() && NewBBDominatesDestBB) { + if (DomTreeNode *OPNode = DT->getNode(OtherPreds.back())) + NewBBDominatesDestBB = DT->dominates(DestBBNode, OPNode); + OtherPreds.pop_back(); + } + OtherPreds.clear(); + } + + // If NewBBDominatesDestBB, then NewBB dominates DestBB, otherwise it + // doesn't dominate anything. + if (NewBBDominatesDestBB) { + if (!DestBBNode) DestBBNode = DT->getNode(DestBB); + DT->changeImmediateDominator(DestBBNode, NewBBNode); + } + } + } + + // Should we update DominanceFrontier information? + if (DominanceFrontier *DF = P->getAnalysisIfAvailable()) { + // If NewBBDominatesDestBB hasn't been computed yet, do so with DF. + if (!OtherPreds.empty()) { + // FIXME: IMPLEMENT THIS! + llvm_unreachable("Requiring domfrontiers but not idom/domtree/domset." + " not implemented yet!"); + } + + // Since the new block is dominated by its only predecessor TIBB, + // it cannot be in any block's dominance frontier. If NewBB dominates + // DestBB, its dominance frontier is the same as DestBB's, otherwise it is + // just {DestBB}. + DominanceFrontier::DomSetType NewDFSet; + if (NewBBDominatesDestBB) { + DominanceFrontier::iterator I = DF->find(DestBB); + if (I != DF->end()) { + DF->addBasicBlock(NewBB, I->second); + + if (I->second.count(DestBB)) { + // However NewBB's frontier does not include DestBB. + DominanceFrontier::iterator NF = DF->find(NewBB); + DF->removeFromFrontier(NF, DestBB); + } + } + else + DF->addBasicBlock(NewBB, DominanceFrontier::DomSetType()); + } else { + DominanceFrontier::DomSetType NewDFSet; + NewDFSet.insert(DestBB); + DF->addBasicBlock(NewBB, NewDFSet); + } + } + + // Update LoopInfo if it is around. + if (LoopInfo *LI = P->getAnalysisIfAvailable()) { + if (Loop *TIL = LI->getLoopFor(TIBB)) { + // If one or the other blocks were not in a loop, the new block is not + // either, and thus LI doesn't need to be updated. + if (Loop *DestLoop = LI->getLoopFor(DestBB)) { + if (TIL == DestLoop) { + // Both in the same loop, the NewBB joins loop. + DestLoop->addBasicBlockToLoop(NewBB, LI->getBase()); + } else if (TIL->contains(DestLoop->getHeader())) { + // Edge from an outer loop to an inner loop. Add to the outer loop. + TIL->addBasicBlockToLoop(NewBB, LI->getBase()); + } else if (DestLoop->contains(TIL->getHeader())) { + // Edge from an inner loop to an outer loop. Add to the outer loop. + DestLoop->addBasicBlockToLoop(NewBB, LI->getBase()); + } else { + // Edge from two loops with no containment relation. Because these + // are natural loops, we know that the destination block must be the + // header of its loop (adding a branch into a loop elsewhere would + // create an irreducible loop). + assert(DestLoop->getHeader() == DestBB && + "Should not create irreducible loops!"); + if (Loop *P = DestLoop->getParentLoop()) + P->addBasicBlockToLoop(NewBB, LI->getBase()); + } + } + // If TIBB is in a loop and DestBB is outside of that loop, split the + // other exit blocks of the loop that also have predecessors outside + // the loop, to maintain a LoopSimplify guarantee. + if (!TIL->contains(DestBB) && + P->mustPreserveAnalysisID(LoopSimplifyID)) { + assert(!TIL->contains(NewBB) && + "Split point for loop exit is contained in loop!"); + + // Update LCSSA form in the newly created exit block. + if (P->mustPreserveAnalysisID(LCSSAID)) { + SmallVector OrigPred; + OrigPred.push_back(TIBB); + CreatePHIsForSplitLoopExit(OrigPred, NewBB, DestBB); + } + + // For each unique exit block... + SmallVector ExitBlocks; + TIL->getExitBlocks(ExitBlocks); + for (unsigned i = 0, e = ExitBlocks.size(); i != e; ++i) { + // Collect all the preds that are inside the loop, and note + // whether there are any preds outside the loop. + SmallVector Preds; + bool HasPredOutsideOfLoop = false; + BasicBlock *Exit = ExitBlocks[i]; + for (pred_iterator I = pred_begin(Exit), E = pred_end(Exit); + I != E; ++I) + if (TIL->contains(*I)) + Preds.push_back(*I); + else + HasPredOutsideOfLoop = true; + // If there are any preds not in the loop, we'll need to split + // the edges. The Preds.empty() check is needed because a block + // may appear multiple times in the list. We can't use + // getUniqueExitBlocks above because that depends on LoopSimplify + // form, which we're in the process of restoring! + if (!Preds.empty() && HasPredOutsideOfLoop) { + BasicBlock *NewExitBB = + SplitBlockPredecessors(Exit, Preds.data(), Preds.size(), + "split", P); + if (P->mustPreserveAnalysisID(LCSSAID)) + CreatePHIsForSplitLoopExit(Preds, NewExitBB, Exit); + } + } + } + // LCSSA form was updated above for the case where LoopSimplify is + // available, which means that all predecessors of loop exit blocks + // are within the loop. Without LoopSimplify form, it would be + // necessary to insert a new phi. + assert((!P->mustPreserveAnalysisID(LCSSAID) || + P->mustPreserveAnalysisID(LoopSimplifyID)) && + "SplitCriticalEdge doesn't know how to update LCCSA form " + "without LoopSimplify!"); + } + } + + // Update ProfileInfo if it is around. + if (ProfileInfo *PI = P->getAnalysisIfAvailable()) { + PI->splitEdge(TIBB,DestBB,NewBB,MergeIdenticalEdges); + } + + return NewBB; +} diff --git a/libclamav/c++/llvm/lib/Transforms/Utils/CMakeLists.txt b/libclamav/c++/llvm/lib/Transforms/Utils/CMakeLists.txt new file mode 100644 index 000000000..93577b47f --- /dev/null +++ b/libclamav/c++/llvm/lib/Transforms/Utils/CMakeLists.txt @@ -0,0 +1,28 @@ +add_llvm_library(LLVMTransformUtils + AddrModeMatcher.cpp + BasicBlockUtils.cpp + BasicInliner.cpp + BreakCriticalEdges.cpp + CloneFunction.cpp + CloneLoop.cpp + CloneModule.cpp + CodeExtractor.cpp + DemoteRegToStack.cpp + InlineFunction.cpp + InstructionNamer.cpp + LCSSA.cpp + Local.cpp + LoopSimplify.cpp + LoopUnroll.cpp + LowerInvoke.cpp + LowerSwitch.cpp + Mem2Reg.cpp + PromoteMemoryToRegister.cpp + SSAUpdater.cpp + SSI.cpp + SimplifyCFG.cpp + UnifyFunctionExitNodes.cpp + ValueMapper.cpp + ) + +target_link_libraries (LLVMTransformUtils LLVMSupport) diff --git a/libclamav/c++/llvm/lib/Transforms/Utils/CloneFunction.cpp b/libclamav/c++/llvm/lib/Transforms/Utils/CloneFunction.cpp new file mode 100644 index 000000000..162d7b350 --- /dev/null +++ b/libclamav/c++/llvm/lib/Transforms/Utils/CloneFunction.cpp @@ -0,0 +1,589 @@ +//===- CloneFunction.cpp - Clone a function into another function ---------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the CloneFunctionInto interface, which is used as the +// low-level function cloner. This is used by the CloneFunction and function +// inliner to do the dirty work of copying the body of a function around. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Transforms/Utils/Cloning.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Instructions.h" +#include "llvm/IntrinsicInst.h" +#include "llvm/GlobalVariable.h" +#include "llvm/Function.h" +#include "llvm/LLVMContext.h" +#include "llvm/Support/CFG.h" +#include "llvm/Transforms/Utils/ValueMapper.h" +#include "llvm/Analysis/ConstantFolding.h" +#include "llvm/Analysis/DebugInfo.h" +#include "llvm/ADT/SmallVector.h" +#include +using namespace llvm; + +// CloneBasicBlock - See comments in Cloning.h +BasicBlock *llvm::CloneBasicBlock(const BasicBlock *BB, + DenseMap &ValueMap, + const char *NameSuffix, Function *F, + ClonedCodeInfo *CodeInfo) { + BasicBlock *NewBB = BasicBlock::Create(BB->getContext(), "", F); + if (BB->hasName()) NewBB->setName(BB->getName()+NameSuffix); + + bool hasCalls = false, hasDynamicAllocas = false, hasStaticAllocas = false; + + // Loop over all instructions, and copy them over. + for (BasicBlock::const_iterator II = BB->begin(), IE = BB->end(); + II != IE; ++II) { + Instruction *NewInst = II->clone(); + if (II->hasName()) + NewInst->setName(II->getName()+NameSuffix); + NewBB->getInstList().push_back(NewInst); + ValueMap[II] = NewInst; // Add instruction map to value. + + hasCalls |= (isa(II) && !isa(II)); + if (const AllocaInst *AI = dyn_cast(II)) { + if (isa(AI->getArraySize())) + hasStaticAllocas = true; + else + hasDynamicAllocas = true; + } + } + + if (CodeInfo) { + CodeInfo->ContainsCalls |= hasCalls; + CodeInfo->ContainsUnwinds |= isa(BB->getTerminator()); + CodeInfo->ContainsDynamicAllocas |= hasDynamicAllocas; + CodeInfo->ContainsDynamicAllocas |= hasStaticAllocas && + BB != &BB->getParent()->getEntryBlock(); + } + return NewBB; +} + +// Clone OldFunc into NewFunc, transforming the old arguments into references to +// ArgMap values. +// +void llvm::CloneFunctionInto(Function *NewFunc, const Function *OldFunc, + DenseMap &ValueMap, + SmallVectorImpl &Returns, + const char *NameSuffix, ClonedCodeInfo *CodeInfo) { + assert(NameSuffix && "NameSuffix cannot be null!"); + +#ifndef NDEBUG + for (Function::const_arg_iterator I = OldFunc->arg_begin(), + E = OldFunc->arg_end(); I != E; ++I) + assert(ValueMap.count(I) && "No mapping from source argument specified!"); +#endif + + // Clone any attributes. + if (NewFunc->arg_size() == OldFunc->arg_size()) + NewFunc->copyAttributesFrom(OldFunc); + else { + //Some arguments were deleted with the ValueMap. Copy arguments one by one + for (Function::const_arg_iterator I = OldFunc->arg_begin(), + E = OldFunc->arg_end(); I != E; ++I) + if (Argument* Anew = dyn_cast(ValueMap[I])) + Anew->addAttr( OldFunc->getAttributes() + .getParamAttributes(I->getArgNo() + 1)); + NewFunc->setAttributes(NewFunc->getAttributes() + .addAttr(0, OldFunc->getAttributes() + .getRetAttributes())); + NewFunc->setAttributes(NewFunc->getAttributes() + .addAttr(~0, OldFunc->getAttributes() + .getFnAttributes())); + + } + + // Loop over all of the basic blocks in the function, cloning them as + // appropriate. Note that we save BE this way in order to handle cloning of + // recursive functions into themselves. + // + for (Function::const_iterator BI = OldFunc->begin(), BE = OldFunc->end(); + BI != BE; ++BI) { + const BasicBlock &BB = *BI; + + // Create a new basic block and copy instructions into it! + BasicBlock *CBB = CloneBasicBlock(&BB, ValueMap, NameSuffix, NewFunc, + CodeInfo); + ValueMap[&BB] = CBB; // Add basic block mapping. + + if (ReturnInst *RI = dyn_cast(CBB->getTerminator())) + Returns.push_back(RI); + } + + // Loop over all of the instructions in the function, fixing up operand + // references as we go. This uses ValueMap to do all the hard work. + // + for (Function::iterator BB = cast(ValueMap[OldFunc->begin()]), + BE = NewFunc->end(); BB != BE; ++BB) + // Loop over all instructions, fixing each one as we find it... + for (BasicBlock::iterator II = BB->begin(); II != BB->end(); ++II) + RemapInstruction(II, ValueMap); +} + +/// CloneFunction - Return a copy of the specified function, but without +/// embedding the function into another module. Also, any references specified +/// in the ValueMap are changed to refer to their mapped value instead of the +/// original one. If any of the arguments to the function are in the ValueMap, +/// the arguments are deleted from the resultant function. The ValueMap is +/// updated to include mappings from all of the instructions and basicblocks in +/// the function from their old to new values. +/// +Function *llvm::CloneFunction(const Function *F, + DenseMap &ValueMap, + ClonedCodeInfo *CodeInfo) { + std::vector ArgTypes; + + // The user might be deleting arguments to the function by specifying them in + // the ValueMap. If so, we need to not add the arguments to the arg ty vector + // + for (Function::const_arg_iterator I = F->arg_begin(), E = F->arg_end(); + I != E; ++I) + if (ValueMap.count(I) == 0) // Haven't mapped the argument to anything yet? + ArgTypes.push_back(I->getType()); + + // Create a new function type... + FunctionType *FTy = FunctionType::get(F->getFunctionType()->getReturnType(), + ArgTypes, F->getFunctionType()->isVarArg()); + + // Create the new function... + Function *NewF = Function::Create(FTy, F->getLinkage(), F->getName()); + + // Loop over the arguments, copying the names of the mapped arguments over... + Function::arg_iterator DestI = NewF->arg_begin(); + for (Function::const_arg_iterator I = F->arg_begin(), E = F->arg_end(); + I != E; ++I) + if (ValueMap.count(I) == 0) { // Is this argument preserved? + DestI->setName(I->getName()); // Copy the name over... + ValueMap[I] = DestI++; // Add mapping to ValueMap + } + + SmallVector Returns; // Ignore returns cloned. + CloneFunctionInto(NewF, F, ValueMap, Returns, "", CodeInfo); + return NewF; +} + + + +namespace { + /// PruningFunctionCloner - This class is a private class used to implement + /// the CloneAndPruneFunctionInto method. + struct PruningFunctionCloner { + Function *NewFunc; + const Function *OldFunc; + DenseMap &ValueMap; + SmallVectorImpl &Returns; + const char *NameSuffix; + ClonedCodeInfo *CodeInfo; + const TargetData *TD; + Value *DbgFnStart; + public: + PruningFunctionCloner(Function *newFunc, const Function *oldFunc, + DenseMap &valueMap, + SmallVectorImpl &returns, + const char *nameSuffix, + ClonedCodeInfo *codeInfo, + const TargetData *td) + : NewFunc(newFunc), OldFunc(oldFunc), ValueMap(valueMap), Returns(returns), + NameSuffix(nameSuffix), CodeInfo(codeInfo), TD(td), DbgFnStart(NULL) { + } + + /// CloneBlock - The specified block is found to be reachable, clone it and + /// anything that it can reach. + void CloneBlock(const BasicBlock *BB, + std::vector &ToClone); + + public: + /// ConstantFoldMappedInstruction - Constant fold the specified instruction, + /// mapping its operands through ValueMap if they are available. + Constant *ConstantFoldMappedInstruction(const Instruction *I); + }; +} + +/// CloneBlock - The specified block is found to be reachable, clone it and +/// anything that it can reach. +void PruningFunctionCloner::CloneBlock(const BasicBlock *BB, + std::vector &ToClone){ + Value *&BBEntry = ValueMap[BB]; + + // Have we already cloned this block? + if (BBEntry) return; + + // Nope, clone it now. + BasicBlock *NewBB; + BBEntry = NewBB = BasicBlock::Create(BB->getContext()); + if (BB->hasName()) NewBB->setName(BB->getName()+NameSuffix); + + bool hasCalls = false, hasDynamicAllocas = false, hasStaticAllocas = false; + + // Loop over all instructions, and copy them over, DCE'ing as we go. This + // loop doesn't include the terminator. + for (BasicBlock::const_iterator II = BB->begin(), IE = --BB->end(); + II != IE; ++II) { + // If this instruction constant folds, don't bother cloning the instruction, + // instead, just add the constant to the value map. + if (Constant *C = ConstantFoldMappedInstruction(II)) { + ValueMap[II] = C; + continue; + } + + // Do not clone llvm.dbg.region.end. It will be adjusted by the inliner. + if (const DbgFuncStartInst *DFSI = dyn_cast(II)) { + if (DbgFnStart == NULL) { + DISubprogram SP(DFSI->getSubprogram()); + if (SP.describes(BB->getParent())) + DbgFnStart = DFSI->getSubprogram(); + } + } + if (const DbgRegionEndInst *DREIS = dyn_cast(II)) { + if (DREIS->getContext() == DbgFnStart) + continue; + } + + Instruction *NewInst = II->clone(); + if (II->hasName()) + NewInst->setName(II->getName()+NameSuffix); + NewBB->getInstList().push_back(NewInst); + ValueMap[II] = NewInst; // Add instruction map to value. + + hasCalls |= (isa(II) && !isa(II)); + if (const AllocaInst *AI = dyn_cast(II)) { + if (isa(AI->getArraySize())) + hasStaticAllocas = true; + else + hasDynamicAllocas = true; + } + } + + // Finally, clone over the terminator. + const TerminatorInst *OldTI = BB->getTerminator(); + bool TerminatorDone = false; + if (const BranchInst *BI = dyn_cast(OldTI)) { + if (BI->isConditional()) { + // If the condition was a known constant in the callee... + ConstantInt *Cond = dyn_cast(BI->getCondition()); + // Or is a known constant in the caller... + if (Cond == 0) + Cond = dyn_cast_or_null(ValueMap[BI->getCondition()]); + + // Constant fold to uncond branch! + if (Cond) { + BasicBlock *Dest = BI->getSuccessor(!Cond->getZExtValue()); + ValueMap[OldTI] = BranchInst::Create(Dest, NewBB); + ToClone.push_back(Dest); + TerminatorDone = true; + } + } + } else if (const SwitchInst *SI = dyn_cast(OldTI)) { + // If switching on a value known constant in the caller. + ConstantInt *Cond = dyn_cast(SI->getCondition()); + if (Cond == 0) // Or known constant after constant prop in the callee... + Cond = dyn_cast_or_null(ValueMap[SI->getCondition()]); + if (Cond) { // Constant fold to uncond branch! + BasicBlock *Dest = SI->getSuccessor(SI->findCaseValue(Cond)); + ValueMap[OldTI] = BranchInst::Create(Dest, NewBB); + ToClone.push_back(Dest); + TerminatorDone = true; + } + } + + if (!TerminatorDone) { + Instruction *NewInst = OldTI->clone(); + if (OldTI->hasName()) + NewInst->setName(OldTI->getName()+NameSuffix); + NewBB->getInstList().push_back(NewInst); + ValueMap[OldTI] = NewInst; // Add instruction map to value. + + // Recursively clone any reachable successor blocks. + const TerminatorInst *TI = BB->getTerminator(); + for (unsigned i = 0, e = TI->getNumSuccessors(); i != e; ++i) + ToClone.push_back(TI->getSuccessor(i)); + } + + if (CodeInfo) { + CodeInfo->ContainsCalls |= hasCalls; + CodeInfo->ContainsUnwinds |= isa(OldTI); + CodeInfo->ContainsDynamicAllocas |= hasDynamicAllocas; + CodeInfo->ContainsDynamicAllocas |= hasStaticAllocas && + BB != &BB->getParent()->front(); + } + + if (ReturnInst *RI = dyn_cast(NewBB->getTerminator())) + Returns.push_back(RI); +} + +/// ConstantFoldMappedInstruction - Constant fold the specified instruction, +/// mapping its operands through ValueMap if they are available. +Constant *PruningFunctionCloner:: +ConstantFoldMappedInstruction(const Instruction *I) { + SmallVector Ops; + for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i) + if (Constant *Op = dyn_cast_or_null(MapValue(I->getOperand(i), + ValueMap))) + Ops.push_back(Op); + else + return 0; // All operands not constant! + + if (const CmpInst *CI = dyn_cast(I)) + return ConstantFoldCompareInstOperands(CI->getPredicate(), Ops[0], Ops[1], + TD); + + if (const LoadInst *LI = dyn_cast(I)) + if (ConstantExpr *CE = dyn_cast(Ops[0])) + if (!LI->isVolatile() && CE->getOpcode() == Instruction::GetElementPtr) + if (GlobalVariable *GV = dyn_cast(CE->getOperand(0))) + if (GV->isConstant() && GV->hasDefinitiveInitializer()) + return ConstantFoldLoadThroughGEPConstantExpr(GV->getInitializer(), + CE); + + return ConstantFoldInstOperands(I->getOpcode(), I->getType(), &Ops[0], + Ops.size(), TD); +} + +static MDNode *UpdateInlinedAtInfo(MDNode *InsnMD, MDNode *TheCallMD, + LLVMContext &Context) { + DILocation ILoc(InsnMD); + if (ILoc.isNull()) return InsnMD; + + DILocation CallLoc(TheCallMD); + if (CallLoc.isNull()) return InsnMD; + + DILocation OrigLocation = ILoc.getOrigLocation(); + MDNode *NewLoc = TheCallMD; + if (!OrigLocation.isNull()) + NewLoc = UpdateInlinedAtInfo(OrigLocation.getNode(), TheCallMD, Context); + + SmallVector MDVs; + MDVs.push_back(InsnMD->getElement(0)); // Line + MDVs.push_back(InsnMD->getElement(1)); // Col + MDVs.push_back(InsnMD->getElement(2)); // Scope + MDVs.push_back(NewLoc); + return MDNode::get(Context, MDVs.data(), MDVs.size()); +} + +/// CloneAndPruneFunctionInto - This works exactly like CloneFunctionInto, +/// except that it does some simple constant prop and DCE on the fly. The +/// effect of this is to copy significantly less code in cases where (for +/// example) a function call with constant arguments is inlined, and those +/// constant arguments cause a significant amount of code in the callee to be +/// dead. Since this doesn't produce an exact copy of the input, it can't be +/// used for things like CloneFunction or CloneModule. +void llvm::CloneAndPruneFunctionInto(Function *NewFunc, const Function *OldFunc, + DenseMap &ValueMap, + SmallVectorImpl &Returns, + const char *NameSuffix, + ClonedCodeInfo *CodeInfo, + const TargetData *TD, + Instruction *TheCall) { + assert(NameSuffix && "NameSuffix cannot be null!"); + +#ifndef NDEBUG + for (Function::const_arg_iterator II = OldFunc->arg_begin(), + E = OldFunc->arg_end(); II != E; ++II) + assert(ValueMap.count(II) && "No mapping from source argument specified!"); +#endif + + PruningFunctionCloner PFC(NewFunc, OldFunc, ValueMap, Returns, + NameSuffix, CodeInfo, TD); + + // Clone the entry block, and anything recursively reachable from it. + std::vector CloneWorklist; + CloneWorklist.push_back(&OldFunc->getEntryBlock()); + while (!CloneWorklist.empty()) { + const BasicBlock *BB = CloneWorklist.back(); + CloneWorklist.pop_back(); + PFC.CloneBlock(BB, CloneWorklist); + } + + // Loop over all of the basic blocks in the old function. If the block was + // reachable, we have cloned it and the old block is now in the value map: + // insert it into the new function in the right order. If not, ignore it. + // + // Defer PHI resolution until rest of function is resolved. + SmallVector PHIToResolve; + for (Function::const_iterator BI = OldFunc->begin(), BE = OldFunc->end(); + BI != BE; ++BI) { + BasicBlock *NewBB = cast_or_null(ValueMap[BI]); + if (NewBB == 0) continue; // Dead block. + + // Add the new block to the new function. + NewFunc->getBasicBlockList().push_back(NewBB); + + // Loop over all of the instructions in the block, fixing up operand + // references as we go. This uses ValueMap to do all the hard work. + // + BasicBlock::iterator I = NewBB->begin(); + + LLVMContext &Context = OldFunc->getContext(); + unsigned DbgKind = Context.getMetadata().getMDKind("dbg"); + MDNode *TheCallMD = NULL; + SmallVector MDVs; + if (TheCall && TheCall->hasMetadata()) + TheCallMD = Context.getMetadata().getMD(DbgKind, TheCall); + + // Handle PHI nodes specially, as we have to remove references to dead + // blocks. + if (PHINode *PN = dyn_cast(I)) { + // Skip over all PHI nodes, remembering them for later. + BasicBlock::const_iterator OldI = BI->begin(); + for (; (PN = dyn_cast(I)); ++I, ++OldI) { + if (I->hasMetadata()) { + if (TheCallMD) { + if (MDNode *IMD = Context.getMetadata().getMD(DbgKind, I)) { + MDNode *NewMD = UpdateInlinedAtInfo(IMD, TheCallMD, Context); + Context.getMetadata().addMD(DbgKind, NewMD, I); + } + } else { + // The cloned instruction has dbg info but the call instruction + // does not have dbg info. Remove dbg info from cloned instruction. + Context.getMetadata().removeMD(DbgKind, I); + } + } + PHIToResolve.push_back(cast(OldI)); + } + } + + // Otherwise, remap the rest of the instructions normally. + for (; I != NewBB->end(); ++I) { + if (I->hasMetadata()) { + if (TheCallMD) { + if (MDNode *IMD = Context.getMetadata().getMD(DbgKind, I)) { + MDNode *NewMD = UpdateInlinedAtInfo(IMD, TheCallMD, Context); + Context.getMetadata().addMD(DbgKind, NewMD, I); + } + } else { + // The cloned instruction has dbg info but the call instruction + // does not have dbg info. Remove dbg info from cloned instruction. + Context.getMetadata().removeMD(DbgKind, I); + } + } + RemapInstruction(I, ValueMap); + } + } + + // Defer PHI resolution until rest of function is resolved, PHI resolution + // requires the CFG to be up-to-date. + for (unsigned phino = 0, e = PHIToResolve.size(); phino != e; ) { + const PHINode *OPN = PHIToResolve[phino]; + unsigned NumPreds = OPN->getNumIncomingValues(); + const BasicBlock *OldBB = OPN->getParent(); + BasicBlock *NewBB = cast(ValueMap[OldBB]); + + // Map operands for blocks that are live and remove operands for blocks + // that are dead. + for (; phino != PHIToResolve.size() && + PHIToResolve[phino]->getParent() == OldBB; ++phino) { + OPN = PHIToResolve[phino]; + PHINode *PN = cast(ValueMap[OPN]); + for (unsigned pred = 0, e = NumPreds; pred != e; ++pred) { + if (BasicBlock *MappedBlock = + cast_or_null(ValueMap[PN->getIncomingBlock(pred)])) { + Value *InVal = MapValue(PN->getIncomingValue(pred), + ValueMap); + assert(InVal && "Unknown input value?"); + PN->setIncomingValue(pred, InVal); + PN->setIncomingBlock(pred, MappedBlock); + } else { + PN->removeIncomingValue(pred, false); + --pred, --e; // Revisit the next entry. + } + } + } + + // The loop above has removed PHI entries for those blocks that are dead + // and has updated others. However, if a block is live (i.e. copied over) + // but its terminator has been changed to not go to this block, then our + // phi nodes will have invalid entries. Update the PHI nodes in this + // case. + PHINode *PN = cast(NewBB->begin()); + NumPreds = std::distance(pred_begin(NewBB), pred_end(NewBB)); + if (NumPreds != PN->getNumIncomingValues()) { + assert(NumPreds < PN->getNumIncomingValues()); + // Count how many times each predecessor comes to this block. + std::map PredCount; + for (pred_iterator PI = pred_begin(NewBB), E = pred_end(NewBB); + PI != E; ++PI) + --PredCount[*PI]; + + // Figure out how many entries to remove from each PHI. + for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) + ++PredCount[PN->getIncomingBlock(i)]; + + // At this point, the excess predecessor entries are positive in the + // map. Loop over all of the PHIs and remove excess predecessor + // entries. + BasicBlock::iterator I = NewBB->begin(); + for (; (PN = dyn_cast(I)); ++I) { + for (std::map::iterator PCI =PredCount.begin(), + E = PredCount.end(); PCI != E; ++PCI) { + BasicBlock *Pred = PCI->first; + for (unsigned NumToRemove = PCI->second; NumToRemove; --NumToRemove) + PN->removeIncomingValue(Pred, false); + } + } + } + + // If the loops above have made these phi nodes have 0 or 1 operand, + // replace them with undef or the input value. We must do this for + // correctness, because 0-operand phis are not valid. + PN = cast(NewBB->begin()); + if (PN->getNumIncomingValues() == 0) { + BasicBlock::iterator I = NewBB->begin(); + BasicBlock::const_iterator OldI = OldBB->begin(); + while ((PN = dyn_cast(I++))) { + Value *NV = UndefValue::get(PN->getType()); + PN->replaceAllUsesWith(NV); + assert(ValueMap[OldI] == PN && "ValueMap mismatch"); + ValueMap[OldI] = NV; + PN->eraseFromParent(); + ++OldI; + } + } + // NOTE: We cannot eliminate single entry phi nodes here, because of + // ValueMap. Single entry phi nodes can have multiple ValueMap entries + // pointing at them. Thus, deleting one would require scanning the ValueMap + // to update any entries in it that would require that. This would be + // really slow. + } + + // Now that the inlined function body has been fully constructed, go through + // and zap unconditional fall-through branches. This happen all the time when + // specializing code: code specialization turns conditional branches into + // uncond branches, and this code folds them. + Function::iterator I = cast(ValueMap[&OldFunc->getEntryBlock()]); + while (I != NewFunc->end()) { + BranchInst *BI = dyn_cast(I->getTerminator()); + if (!BI || BI->isConditional()) { ++I; continue; } + + // Note that we can't eliminate uncond branches if the destination has + // single-entry PHI nodes. Eliminating the single-entry phi nodes would + // require scanning the ValueMap to update any entries that point to the phi + // node. + BasicBlock *Dest = BI->getSuccessor(0); + if (!Dest->getSinglePredecessor() || isa(Dest->begin())) { + ++I; continue; + } + + // We know all single-entry PHI nodes in the inlined function have been + // removed, so we just need to splice the blocks. + BI->eraseFromParent(); + + // Move all the instructions in the succ to the pred. + I->getInstList().splice(I->end(), Dest->getInstList()); + + // Make all PHI nodes that referred to Dest now refer to I as their source. + Dest->replaceAllUsesWith(I); + + // Remove the dest block. + Dest->eraseFromParent(); + + // Do not increment I, iteratively merge all things this block branches to. + } +} diff --git a/libclamav/c++/llvm/lib/Transforms/Utils/CloneLoop.cpp b/libclamav/c++/llvm/lib/Transforms/Utils/CloneLoop.cpp new file mode 100644 index 000000000..7e000a1a7 --- /dev/null +++ b/libclamav/c++/llvm/lib/Transforms/Utils/CloneLoop.cpp @@ -0,0 +1,152 @@ +//===- CloneLoop.cpp - Clone loop nest ------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the CloneLoop interface which makes a copy of a loop. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Transforms/Utils/Cloning.h" +#include "llvm/BasicBlock.h" +#include "llvm/Analysis/LoopPass.h" +#include "llvm/Analysis/Dominators.h" +#include "llvm/ADT/DenseMap.h" + + +using namespace llvm; + +/// CloneDominatorInfo - Clone basicblock's dominator tree and, if available, +/// dominance info. It is expected that basic block is already cloned. +static void CloneDominatorInfo(BasicBlock *BB, + DenseMap &ValueMap, + DominatorTree *DT, + DominanceFrontier *DF) { + + assert (DT && "DominatorTree is not available"); + DenseMap::iterator BI = ValueMap.find(BB); + assert (BI != ValueMap.end() && "BasicBlock clone is missing"); + BasicBlock *NewBB = cast(BI->second); + + // NewBB already got dominator info. + if (DT->getNode(NewBB)) + return; + + assert (DT->getNode(BB) && "BasicBlock does not have dominator info"); + // Entry block is not expected here. Infinite loops are not to cloned. + assert (DT->getNode(BB)->getIDom() && "BasicBlock does not have immediate dominator"); + BasicBlock *BBDom = DT->getNode(BB)->getIDom()->getBlock(); + + // NewBB's dominator is either BB's dominator or BB's dominator's clone. + BasicBlock *NewBBDom = BBDom; + DenseMap::iterator BBDomI = ValueMap.find(BBDom); + if (BBDomI != ValueMap.end()) { + NewBBDom = cast(BBDomI->second); + if (!DT->getNode(NewBBDom)) + CloneDominatorInfo(BBDom, ValueMap, DT, DF); + } + DT->addNewBlock(NewBB, NewBBDom); + + // Copy cloned dominance frontiner set + if (DF) { + DominanceFrontier::DomSetType NewDFSet; + DominanceFrontier::iterator DFI = DF->find(BB); + if ( DFI != DF->end()) { + DominanceFrontier::DomSetType S = DFI->second; + for (DominanceFrontier::DomSetType::iterator I = S.begin(), E = S.end(); + I != E; ++I) { + BasicBlock *DB = *I; + DenseMap::iterator IDM = ValueMap.find(DB); + if (IDM != ValueMap.end()) + NewDFSet.insert(cast(IDM->second)); + else + NewDFSet.insert(DB); + } + } + DF->addBasicBlock(NewBB, NewDFSet); + } +} + +/// CloneLoop - Clone Loop. Clone dominator info. Populate ValueMap +/// using old blocks to new blocks mapping. +Loop *llvm::CloneLoop(Loop *OrigL, LPPassManager *LPM, LoopInfo *LI, + DenseMap &ValueMap, Pass *P) { + + DominatorTree *DT = NULL; + DominanceFrontier *DF = NULL; + if (P) { + DT = P->getAnalysisIfAvailable(); + DF = P->getAnalysisIfAvailable(); + } + + SmallVector NewBlocks; + + // Populate loop nest. + SmallVector LoopNest; + LoopNest.push_back(OrigL); + + + Loop *NewParentLoop = NULL; + while (!LoopNest.empty()) { + Loop *L = LoopNest.pop_back_val(); + Loop *NewLoop = new Loop(); + + if (!NewParentLoop) + NewParentLoop = NewLoop; + + LPM->insertLoop(NewLoop, L->getParentLoop()); + + // Clone Basic Blocks. + for (Loop::block_iterator I = L->block_begin(), E = L->block_end(); + I != E; ++I) { + BasicBlock *BB = *I; + BasicBlock *NewBB = CloneBasicBlock(BB, ValueMap, ".clone"); + ValueMap[BB] = NewBB; + if (P) + LPM->cloneBasicBlockSimpleAnalysis(BB, NewBB, L); + NewLoop->addBasicBlockToLoop(NewBB, LI->getBase()); + NewBlocks.push_back(NewBB); + } + + // Clone dominator info. + if (DT) + for (Loop::block_iterator I = L->block_begin(), E = L->block_end(); + I != E; ++I) { + BasicBlock *BB = *I; + CloneDominatorInfo(BB, ValueMap, DT, DF); + } + + // Process sub loops + for (Loop::iterator I = L->begin(), E = L->end(); I != E; ++I) + LoopNest.push_back(*I); + } + + // Remap instructions to reference operands from ValueMap. + for(SmallVector::iterator NBItr = NewBlocks.begin(), + NBE = NewBlocks.end(); NBItr != NBE; ++NBItr) { + BasicBlock *NB = *NBItr; + for(BasicBlock::iterator BI = NB->begin(), BE = NB->end(); + BI != BE; ++BI) { + Instruction *Insn = BI; + for (unsigned index = 0, num_ops = Insn->getNumOperands(); + index != num_ops; ++index) { + Value *Op = Insn->getOperand(index); + DenseMap::iterator OpItr = ValueMap.find(Op); + if (OpItr != ValueMap.end()) + Insn->setOperand(index, OpItr->second); + } + } + } + + BasicBlock *Latch = OrigL->getLoopLatch(); + Function *F = Latch->getParent(); + F->getBasicBlockList().insert(OrigL->getHeader(), + NewBlocks.begin(), NewBlocks.end()); + + + return NewParentLoop; +} diff --git a/libclamav/c++/llvm/lib/Transforms/Utils/CloneModule.cpp b/libclamav/c++/llvm/lib/Transforms/Utils/CloneModule.cpp new file mode 100644 index 000000000..a163f89cc --- /dev/null +++ b/libclamav/c++/llvm/lib/Transforms/Utils/CloneModule.cpp @@ -0,0 +1,127 @@ +//===- CloneModule.cpp - Clone an entire module ---------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the CloneModule interface which makes a copy of an +// entire module. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Transforms/Utils/Cloning.h" +#include "llvm/Module.h" +#include "llvm/DerivedTypes.h" +#include "llvm/TypeSymbolTable.h" +#include "llvm/Constant.h" +#include "llvm/Transforms/Utils/ValueMapper.h" +using namespace llvm; + +/// CloneModule - Return an exact copy of the specified module. This is not as +/// easy as it might seem because we have to worry about making copies of global +/// variables and functions, and making their (initializers and references, +/// respectively) refer to the right globals. +/// +Module *llvm::CloneModule(const Module *M) { + // Create the value map that maps things from the old module over to the new + // module. + DenseMap ValueMap; + return CloneModule(M, ValueMap); +} + +Module *llvm::CloneModule(const Module *M, + DenseMap &ValueMap) { + // First off, we need to create the new module... + Module *New = new Module(M->getModuleIdentifier(), M->getContext()); + New->setDataLayout(M->getDataLayout()); + New->setTargetTriple(M->getTargetTriple()); + New->setModuleInlineAsm(M->getModuleInlineAsm()); + + // Copy all of the type symbol table entries over. + const TypeSymbolTable &TST = M->getTypeSymbolTable(); + for (TypeSymbolTable::const_iterator TI = TST.begin(), TE = TST.end(); + TI != TE; ++TI) + New->addTypeName(TI->first, TI->second); + + // Copy all of the dependent libraries over. + for (Module::lib_iterator I = M->lib_begin(), E = M->lib_end(); I != E; ++I) + New->addLibrary(*I); + + // Loop over all of the global variables, making corresponding globals in the + // new module. Here we add them to the ValueMap and to the new Module. We + // don't worry about attributes or initializers, they will come later. + // + for (Module::const_global_iterator I = M->global_begin(), E = M->global_end(); + I != E; ++I) { + GlobalVariable *GV = new GlobalVariable(*New, + I->getType()->getElementType(), + false, + GlobalValue::ExternalLinkage, 0, + I->getName()); + GV->setAlignment(I->getAlignment()); + ValueMap[I] = GV; + } + + // Loop over the functions in the module, making external functions as before + for (Module::const_iterator I = M->begin(), E = M->end(); I != E; ++I) { + Function *NF = + Function::Create(cast(I->getType()->getElementType()), + GlobalValue::ExternalLinkage, I->getName(), New); + NF->copyAttributesFrom(I); + ValueMap[I] = NF; + } + + // Loop over the aliases in the module + for (Module::const_alias_iterator I = M->alias_begin(), E = M->alias_end(); + I != E; ++I) + ValueMap[I] = new GlobalAlias(I->getType(), GlobalAlias::ExternalLinkage, + I->getName(), NULL, New); + + // Now that all of the things that global variable initializer can refer to + // have been created, loop through and copy the global variable referrers + // over... We also set the attributes on the global now. + // + for (Module::const_global_iterator I = M->global_begin(), E = M->global_end(); + I != E; ++I) { + GlobalVariable *GV = cast(ValueMap[I]); + if (I->hasInitializer()) + GV->setInitializer(cast(MapValue(I->getInitializer(), + ValueMap))); + GV->setLinkage(I->getLinkage()); + GV->setThreadLocal(I->isThreadLocal()); + GV->setConstant(I->isConstant()); + } + + // Similarly, copy over function bodies now... + // + for (Module::const_iterator I = M->begin(), E = M->end(); I != E; ++I) { + Function *F = cast(ValueMap[I]); + if (!I->isDeclaration()) { + Function::arg_iterator DestI = F->arg_begin(); + for (Function::const_arg_iterator J = I->arg_begin(); J != I->arg_end(); + ++J) { + DestI->setName(J->getName()); + ValueMap[J] = DestI++; + } + + SmallVector Returns; // Ignore returns cloned. + CloneFunctionInto(F, I, ValueMap, Returns); + } + + F->setLinkage(I->getLinkage()); + } + + // And aliases + for (Module::const_alias_iterator I = M->alias_begin(), E = M->alias_end(); + I != E; ++I) { + GlobalAlias *GA = cast(ValueMap[I]); + GA->setLinkage(I->getLinkage()); + if (const Constant* C = I->getAliasee()) + GA->setAliasee(cast(MapValue(C, ValueMap))); + } + + return New; +} diff --git a/libclamav/c++/llvm/lib/Transforms/Utils/CodeExtractor.cpp b/libclamav/c++/llvm/lib/Transforms/Utils/CodeExtractor.cpp new file mode 100644 index 000000000..f966681db --- /dev/null +++ b/libclamav/c++/llvm/lib/Transforms/Utils/CodeExtractor.cpp @@ -0,0 +1,800 @@ +//===- CodeExtractor.cpp - Pull code region into a new function -----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the interface to tear out a code region, such as an +// individual loop or a parallel section, into a new function, replacing it with +// a call to the new function. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Transforms/Utils/FunctionUtils.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Instructions.h" +#include "llvm/Intrinsics.h" +#include "llvm/LLVMContext.h" +#include "llvm/Module.h" +#include "llvm/Pass.h" +#include "llvm/Analysis/Dominators.h" +#include "llvm/Analysis/LoopInfo.h" +#include "llvm/Analysis/Verifier.h" +#include "llvm/Transforms/Utils/BasicBlockUtils.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/ADT/StringExtras.h" +#include +#include +using namespace llvm; + +// Provide a command-line option to aggregate function arguments into a struct +// for functions produced by the code extractor. This is useful when converting +// extracted functions to pthread-based code, as only one argument (void*) can +// be passed in to pthread_create(). +static cl::opt +AggregateArgsOpt("aggregate-extracted-args", cl::Hidden, + cl::desc("Aggregate arguments to code-extracted functions")); + +namespace { + class CodeExtractor { + typedef std::vector Values; + std::set BlocksToExtract; + DominatorTree* DT; + bool AggregateArgs; + unsigned NumExitBlocks; + const Type *RetTy; + public: + CodeExtractor(DominatorTree* dt = 0, bool AggArgs = false) + : DT(dt), AggregateArgs(AggArgs||AggregateArgsOpt), NumExitBlocks(~0U) {} + + Function *ExtractCodeRegion(const std::vector &code); + + bool isEligible(const std::vector &code); + + private: + /// definedInRegion - Return true if the specified value is defined in the + /// extracted region. + bool definedInRegion(Value *V) const { + if (Instruction *I = dyn_cast(V)) + if (BlocksToExtract.count(I->getParent())) + return true; + return false; + } + + /// definedInCaller - Return true if the specified value is defined in the + /// function being code extracted, but not in the region being extracted. + /// These values must be passed in as live-ins to the function. + bool definedInCaller(Value *V) const { + if (isa(V)) return true; + if (Instruction *I = dyn_cast(V)) + if (!BlocksToExtract.count(I->getParent())) + return true; + return false; + } + + void severSplitPHINodes(BasicBlock *&Header); + void splitReturnBlocks(); + void findInputsOutputs(Values &inputs, Values &outputs); + + Function *constructFunction(const Values &inputs, + const Values &outputs, + BasicBlock *header, + BasicBlock *newRootNode, BasicBlock *newHeader, + Function *oldFunction, Module *M); + + void moveCodeToFunction(Function *newFunction); + + void emitCallAndSwitchStatement(Function *newFunction, + BasicBlock *newHeader, + Values &inputs, + Values &outputs); + + }; +} + +/// severSplitPHINodes - If a PHI node has multiple inputs from outside of the +/// region, we need to split the entry block of the region so that the PHI node +/// is easier to deal with. +void CodeExtractor::severSplitPHINodes(BasicBlock *&Header) { + bool HasPredsFromRegion = false; + unsigned NumPredsOutsideRegion = 0; + + if (Header != &Header->getParent()->getEntryBlock()) { + PHINode *PN = dyn_cast(Header->begin()); + if (!PN) return; // No PHI nodes. + + // If the header node contains any PHI nodes, check to see if there is more + // than one entry from outside the region. If so, we need to sever the + // header block into two. + for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) + if (BlocksToExtract.count(PN->getIncomingBlock(i))) + HasPredsFromRegion = true; + else + ++NumPredsOutsideRegion; + + // If there is one (or fewer) predecessor from outside the region, we don't + // need to do anything special. + if (NumPredsOutsideRegion <= 1) return; + } + + // Otherwise, we need to split the header block into two pieces: one + // containing PHI nodes merging values from outside of the region, and a + // second that contains all of the code for the block and merges back any + // incoming values from inside of the region. + BasicBlock::iterator AfterPHIs = Header->getFirstNonPHI(); + BasicBlock *NewBB = Header->splitBasicBlock(AfterPHIs, + Header->getName()+".ce"); + + // We only want to code extract the second block now, and it becomes the new + // header of the region. + BasicBlock *OldPred = Header; + BlocksToExtract.erase(OldPred); + BlocksToExtract.insert(NewBB); + Header = NewBB; + + // Okay, update dominator sets. The blocks that dominate the new one are the + // blocks that dominate TIBB plus the new block itself. + if (DT) + DT->splitBlock(NewBB); + + // Okay, now we need to adjust the PHI nodes and any branches from within the + // region to go to the new header block instead of the old header block. + if (HasPredsFromRegion) { + PHINode *PN = cast(OldPred->begin()); + // Loop over all of the predecessors of OldPred that are in the region, + // changing them to branch to NewBB instead. + for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) + if (BlocksToExtract.count(PN->getIncomingBlock(i))) { + TerminatorInst *TI = PN->getIncomingBlock(i)->getTerminator(); + TI->replaceUsesOfWith(OldPred, NewBB); + } + + // Okay, everthing within the region is now branching to the right block, we + // just have to update the PHI nodes now, inserting PHI nodes into NewBB. + for (AfterPHIs = OldPred->begin(); isa(AfterPHIs); ++AfterPHIs) { + PHINode *PN = cast(AfterPHIs); + // Create a new PHI node in the new region, which has an incoming value + // from OldPred of PN. + PHINode *NewPN = PHINode::Create(PN->getType(), PN->getName()+".ce", + NewBB->begin()); + NewPN->addIncoming(PN, OldPred); + + // Loop over all of the incoming value in PN, moving them to NewPN if they + // are from the extracted region. + for (unsigned i = 0; i != PN->getNumIncomingValues(); ++i) { + if (BlocksToExtract.count(PN->getIncomingBlock(i))) { + NewPN->addIncoming(PN->getIncomingValue(i), PN->getIncomingBlock(i)); + PN->removeIncomingValue(i); + --i; + } + } + } + } +} + +void CodeExtractor::splitReturnBlocks() { + for (std::set::iterator I = BlocksToExtract.begin(), + E = BlocksToExtract.end(); I != E; ++I) + if (ReturnInst *RI = dyn_cast((*I)->getTerminator())) { + BasicBlock *New = (*I)->splitBasicBlock(RI, (*I)->getName()+".ret"); + if (DT) { + // Old dominates New. New node domiantes all other nodes dominated + //by Old. + DomTreeNode *OldNode = DT->getNode(*I); + SmallVector Children; + for (DomTreeNode::iterator DI = OldNode->begin(), DE = OldNode->end(); + DI != DE; ++DI) + Children.push_back(*DI); + + DomTreeNode *NewNode = DT->addNewBlock(New, *I); + + for (SmallVector::iterator I = Children.begin(), + E = Children.end(); I != E; ++I) + DT->changeImmediateDominator(*I, NewNode); + } + } +} + +// findInputsOutputs - Find inputs to, outputs from the code region. +// +void CodeExtractor::findInputsOutputs(Values &inputs, Values &outputs) { + std::set ExitBlocks; + for (std::set::const_iterator ci = BlocksToExtract.begin(), + ce = BlocksToExtract.end(); ci != ce; ++ci) { + BasicBlock *BB = *ci; + + for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ++I) { + // If a used value is defined outside the region, it's an input. If an + // instruction is used outside the region, it's an output. + for (User::op_iterator O = I->op_begin(), E = I->op_end(); O != E; ++O) + if (definedInCaller(*O)) + inputs.push_back(*O); + + // Consider uses of this instruction (outputs). + for (Value::use_iterator UI = I->use_begin(), E = I->use_end(); + UI != E; ++UI) + if (!definedInRegion(*UI)) { + outputs.push_back(I); + break; + } + } // for: insts + + // Keep track of the exit blocks from the region. + TerminatorInst *TI = BB->getTerminator(); + for (unsigned i = 0, e = TI->getNumSuccessors(); i != e; ++i) + if (!BlocksToExtract.count(TI->getSuccessor(i))) + ExitBlocks.insert(TI->getSuccessor(i)); + } // for: basic blocks + + NumExitBlocks = ExitBlocks.size(); + + // Eliminate duplicates. + std::sort(inputs.begin(), inputs.end()); + inputs.erase(std::unique(inputs.begin(), inputs.end()), inputs.end()); + std::sort(outputs.begin(), outputs.end()); + outputs.erase(std::unique(outputs.begin(), outputs.end()), outputs.end()); +} + +/// constructFunction - make a function based on inputs and outputs, as follows: +/// f(in0, ..., inN, out0, ..., outN) +/// +Function *CodeExtractor::constructFunction(const Values &inputs, + const Values &outputs, + BasicBlock *header, + BasicBlock *newRootNode, + BasicBlock *newHeader, + Function *oldFunction, + Module *M) { + DEBUG(errs() << "inputs: " << inputs.size() << "\n"); + DEBUG(errs() << "outputs: " << outputs.size() << "\n"); + + // This function returns unsigned, outputs will go back by reference. + switch (NumExitBlocks) { + case 0: + case 1: RetTy = Type::getVoidTy(header->getContext()); break; + case 2: RetTy = Type::getInt1Ty(header->getContext()); break; + default: RetTy = Type::getInt16Ty(header->getContext()); break; + } + + std::vector paramTy; + + // Add the types of the input values to the function's argument list + for (Values::const_iterator i = inputs.begin(), + e = inputs.end(); i != e; ++i) { + const Value *value = *i; + DEBUG(errs() << "value used in func: " << *value << "\n"); + paramTy.push_back(value->getType()); + } + + // Add the types of the output values to the function's argument list. + for (Values::const_iterator I = outputs.begin(), E = outputs.end(); + I != E; ++I) { + DEBUG(errs() << "instr used in func: " << **I << "\n"); + if (AggregateArgs) + paramTy.push_back((*I)->getType()); + else + paramTy.push_back(PointerType::getUnqual((*I)->getType())); + } + + DEBUG(errs() << "Function type: " << *RetTy << " f("); + for (std::vector::iterator i = paramTy.begin(), + e = paramTy.end(); i != e; ++i) + DEBUG(errs() << **i << ", "); + DEBUG(errs() << ")\n"); + + if (AggregateArgs && (inputs.size() + outputs.size() > 0)) { + PointerType *StructPtr = + PointerType::getUnqual(StructType::get(M->getContext(), paramTy)); + paramTy.clear(); + paramTy.push_back(StructPtr); + } + const FunctionType *funcType = + FunctionType::get(RetTy, paramTy, false); + + // Create the new function + Function *newFunction = Function::Create(funcType, + GlobalValue::InternalLinkage, + oldFunction->getName() + "_" + + header->getName(), M); + // If the old function is no-throw, so is the new one. + if (oldFunction->doesNotThrow()) + newFunction->setDoesNotThrow(true); + + newFunction->getBasicBlockList().push_back(newRootNode); + + // Create an iterator to name all of the arguments we inserted. + Function::arg_iterator AI = newFunction->arg_begin(); + + // Rewrite all users of the inputs in the extracted region to use the + // arguments (or appropriate addressing into struct) instead. + for (unsigned i = 0, e = inputs.size(); i != e; ++i) { + Value *RewriteVal; + if (AggregateArgs) { + Value *Idx[2]; + Idx[0] = Constant::getNullValue(Type::getInt32Ty(header->getContext())); + Idx[1] = ConstantInt::get(Type::getInt32Ty(header->getContext()), i); + TerminatorInst *TI = newFunction->begin()->getTerminator(); + GetElementPtrInst *GEP = + GetElementPtrInst::Create(AI, Idx, Idx+2, + "gep_" + inputs[i]->getName(), TI); + RewriteVal = new LoadInst(GEP, "loadgep_" + inputs[i]->getName(), TI); + } else + RewriteVal = AI++; + + std::vector Users(inputs[i]->use_begin(), inputs[i]->use_end()); + for (std::vector::iterator use = Users.begin(), useE = Users.end(); + use != useE; ++use) + if (Instruction* inst = dyn_cast(*use)) + if (BlocksToExtract.count(inst->getParent())) + inst->replaceUsesOfWith(inputs[i], RewriteVal); + } + + // Set names for input and output arguments. + if (!AggregateArgs) { + AI = newFunction->arg_begin(); + for (unsigned i = 0, e = inputs.size(); i != e; ++i, ++AI) + AI->setName(inputs[i]->getName()); + for (unsigned i = 0, e = outputs.size(); i != e; ++i, ++AI) + AI->setName(outputs[i]->getName()+".out"); + } + + // Rewrite branches to basic blocks outside of the loop to new dummy blocks + // within the new function. This must be done before we lose track of which + // blocks were originally in the code region. + std::vector Users(header->use_begin(), header->use_end()); + for (unsigned i = 0, e = Users.size(); i != e; ++i) + // The BasicBlock which contains the branch is not in the region + // modify the branch target to a new block + if (TerminatorInst *TI = dyn_cast(Users[i])) + if (!BlocksToExtract.count(TI->getParent()) && + TI->getParent()->getParent() == oldFunction) + TI->replaceUsesOfWith(header, newHeader); + + return newFunction; +} + +/// FindPhiPredForUseInBlock - Given a value and a basic block, find a PHI +/// that uses the value within the basic block, and return the predecessor +/// block associated with that use, or return 0 if none is found. +static BasicBlock* FindPhiPredForUseInBlock(Value* Used, BasicBlock* BB) { + for (Value::use_iterator UI = Used->use_begin(), + UE = Used->use_end(); UI != UE; ++UI) { + PHINode *P = dyn_cast(*UI); + if (P && P->getParent() == BB) + return P->getIncomingBlock(UI); + } + + return 0; +} + +/// emitCallAndSwitchStatement - This method sets up the caller side by adding +/// the call instruction, splitting any PHI nodes in the header block as +/// necessary. +void CodeExtractor:: +emitCallAndSwitchStatement(Function *newFunction, BasicBlock *codeReplacer, + Values &inputs, Values &outputs) { + // Emit a call to the new function, passing in: *pointer to struct (if + // aggregating parameters), or plan inputs and allocated memory for outputs + std::vector params, StructValues, ReloadOutputs, Reloads; + + LLVMContext &Context = newFunction->getContext(); + + // Add inputs as params, or to be filled into the struct + for (Values::iterator i = inputs.begin(), e = inputs.end(); i != e; ++i) + if (AggregateArgs) + StructValues.push_back(*i); + else + params.push_back(*i); + + // Create allocas for the outputs + for (Values::iterator i = outputs.begin(), e = outputs.end(); i != e; ++i) { + if (AggregateArgs) { + StructValues.push_back(*i); + } else { + AllocaInst *alloca = + new AllocaInst((*i)->getType(), 0, (*i)->getName()+".loc", + codeReplacer->getParent()->begin()->begin()); + ReloadOutputs.push_back(alloca); + params.push_back(alloca); + } + } + + AllocaInst *Struct = 0; + if (AggregateArgs && (inputs.size() + outputs.size() > 0)) { + std::vector ArgTypes; + for (Values::iterator v = StructValues.begin(), + ve = StructValues.end(); v != ve; ++v) + ArgTypes.push_back((*v)->getType()); + + // Allocate a struct at the beginning of this function + Type *StructArgTy = StructType::get(newFunction->getContext(), ArgTypes); + Struct = + new AllocaInst(StructArgTy, 0, "structArg", + codeReplacer->getParent()->begin()->begin()); + params.push_back(Struct); + + for (unsigned i = 0, e = inputs.size(); i != e; ++i) { + Value *Idx[2]; + Idx[0] = Constant::getNullValue(Type::getInt32Ty(Context)); + Idx[1] = ConstantInt::get(Type::getInt32Ty(Context), i); + GetElementPtrInst *GEP = + GetElementPtrInst::Create(Struct, Idx, Idx + 2, + "gep_" + StructValues[i]->getName()); + codeReplacer->getInstList().push_back(GEP); + StoreInst *SI = new StoreInst(StructValues[i], GEP); + codeReplacer->getInstList().push_back(SI); + } + } + + // Emit the call to the function + CallInst *call = CallInst::Create(newFunction, params.begin(), params.end(), + NumExitBlocks > 1 ? "targetBlock" : ""); + codeReplacer->getInstList().push_back(call); + + Function::arg_iterator OutputArgBegin = newFunction->arg_begin(); + unsigned FirstOut = inputs.size(); + if (!AggregateArgs) + std::advance(OutputArgBegin, inputs.size()); + + // Reload the outputs passed in by reference + for (unsigned i = 0, e = outputs.size(); i != e; ++i) { + Value *Output = 0; + if (AggregateArgs) { + Value *Idx[2]; + Idx[0] = Constant::getNullValue(Type::getInt32Ty(Context)); + Idx[1] = ConstantInt::get(Type::getInt32Ty(Context), FirstOut + i); + GetElementPtrInst *GEP + = GetElementPtrInst::Create(Struct, Idx, Idx + 2, + "gep_reload_" + outputs[i]->getName()); + codeReplacer->getInstList().push_back(GEP); + Output = GEP; + } else { + Output = ReloadOutputs[i]; + } + LoadInst *load = new LoadInst(Output, outputs[i]->getName()+".reload"); + Reloads.push_back(load); + codeReplacer->getInstList().push_back(load); + std::vector Users(outputs[i]->use_begin(), outputs[i]->use_end()); + for (unsigned u = 0, e = Users.size(); u != e; ++u) { + Instruction *inst = cast(Users[u]); + if (!BlocksToExtract.count(inst->getParent())) + inst->replaceUsesOfWith(outputs[i], load); + } + } + + // Now we can emit a switch statement using the call as a value. + SwitchInst *TheSwitch = + SwitchInst::Create(Constant::getNullValue(Type::getInt16Ty(Context)), + codeReplacer, 0, codeReplacer); + + // Since there may be multiple exits from the original region, make the new + // function return an unsigned, switch on that number. This loop iterates + // over all of the blocks in the extracted region, updating any terminator + // instructions in the to-be-extracted region that branch to blocks that are + // not in the region to be extracted. + std::map ExitBlockMap; + + unsigned switchVal = 0; + for (std::set::const_iterator i = BlocksToExtract.begin(), + e = BlocksToExtract.end(); i != e; ++i) { + TerminatorInst *TI = (*i)->getTerminator(); + for (unsigned i = 0, e = TI->getNumSuccessors(); i != e; ++i) + if (!BlocksToExtract.count(TI->getSuccessor(i))) { + BasicBlock *OldTarget = TI->getSuccessor(i); + // add a new basic block which returns the appropriate value + BasicBlock *&NewTarget = ExitBlockMap[OldTarget]; + if (!NewTarget) { + // If we don't already have an exit stub for this non-extracted + // destination, create one now! + NewTarget = BasicBlock::Create(Context, + OldTarget->getName() + ".exitStub", + newFunction); + unsigned SuccNum = switchVal++; + + Value *brVal = 0; + switch (NumExitBlocks) { + case 0: + case 1: break; // No value needed. + case 2: // Conditional branch, return a bool + brVal = ConstantInt::get(Type::getInt1Ty(Context), !SuccNum); + break; + default: + brVal = ConstantInt::get(Type::getInt16Ty(Context), SuccNum); + break; + } + + ReturnInst *NTRet = ReturnInst::Create(Context, brVal, NewTarget); + + // Update the switch instruction. + TheSwitch->addCase(ConstantInt::get(Type::getInt16Ty(Context), + SuccNum), + OldTarget); + + // Restore values just before we exit + Function::arg_iterator OAI = OutputArgBegin; + for (unsigned out = 0, e = outputs.size(); out != e; ++out) { + // For an invoke, the normal destination is the only one that is + // dominated by the result of the invocation + BasicBlock *DefBlock = cast(outputs[out])->getParent(); + + bool DominatesDef = true; + + if (InvokeInst *Invoke = dyn_cast(outputs[out])) { + DefBlock = Invoke->getNormalDest(); + + // Make sure we are looking at the original successor block, not + // at a newly inserted exit block, which won't be in the dominator + // info. + for (std::map::iterator I = + ExitBlockMap.begin(), E = ExitBlockMap.end(); I != E; ++I) + if (DefBlock == I->second) { + DefBlock = I->first; + break; + } + + // In the extract block case, if the block we are extracting ends + // with an invoke instruction, make sure that we don't emit a + // store of the invoke value for the unwind block. + if (!DT && DefBlock != OldTarget) + DominatesDef = false; + } + + if (DT) { + DominatesDef = DT->dominates(DefBlock, OldTarget); + + // If the output value is used by a phi in the target block, + // then we need to test for dominance of the phi's predecessor + // instead. Unfortunately, this a little complicated since we + // have already rewritten uses of the value to uses of the reload. + BasicBlock* pred = FindPhiPredForUseInBlock(Reloads[out], + OldTarget); + if (pred && DT && DT->dominates(DefBlock, pred)) + DominatesDef = true; + } + + if (DominatesDef) { + if (AggregateArgs) { + Value *Idx[2]; + Idx[0] = Constant::getNullValue(Type::getInt32Ty(Context)); + Idx[1] = ConstantInt::get(Type::getInt32Ty(Context), + FirstOut+out); + GetElementPtrInst *GEP = + GetElementPtrInst::Create(OAI, Idx, Idx + 2, + "gep_" + outputs[out]->getName(), + NTRet); + new StoreInst(outputs[out], GEP, NTRet); + } else { + new StoreInst(outputs[out], OAI, NTRet); + } + } + // Advance output iterator even if we don't emit a store + if (!AggregateArgs) ++OAI; + } + } + + // rewrite the original branch instruction with this new target + TI->setSuccessor(i, NewTarget); + } + } + + // Now that we've done the deed, simplify the switch instruction. + const Type *OldFnRetTy = TheSwitch->getParent()->getParent()->getReturnType(); + switch (NumExitBlocks) { + case 0: + // There are no successors (the block containing the switch itself), which + // means that previously this was the last part of the function, and hence + // this should be rewritten as a `ret' + + // Check if the function should return a value + if (OldFnRetTy == Type::getVoidTy(Context)) { + ReturnInst::Create(Context, 0, TheSwitch); // Return void + } else if (OldFnRetTy == TheSwitch->getCondition()->getType()) { + // return what we have + ReturnInst::Create(Context, TheSwitch->getCondition(), TheSwitch); + } else { + // Otherwise we must have code extracted an unwind or something, just + // return whatever we want. + ReturnInst::Create(Context, + Constant::getNullValue(OldFnRetTy), TheSwitch); + } + + TheSwitch->eraseFromParent(); + break; + case 1: + // Only a single destination, change the switch into an unconditional + // branch. + BranchInst::Create(TheSwitch->getSuccessor(1), TheSwitch); + TheSwitch->eraseFromParent(); + break; + case 2: + BranchInst::Create(TheSwitch->getSuccessor(1), TheSwitch->getSuccessor(2), + call, TheSwitch); + TheSwitch->eraseFromParent(); + break; + default: + // Otherwise, make the default destination of the switch instruction be one + // of the other successors. + TheSwitch->setOperand(0, call); + TheSwitch->setSuccessor(0, TheSwitch->getSuccessor(NumExitBlocks)); + TheSwitch->removeCase(NumExitBlocks); // Remove redundant case + break; + } +} + +void CodeExtractor::moveCodeToFunction(Function *newFunction) { + Function *oldFunc = (*BlocksToExtract.begin())->getParent(); + Function::BasicBlockListType &oldBlocks = oldFunc->getBasicBlockList(); + Function::BasicBlockListType &newBlocks = newFunction->getBasicBlockList(); + + for (std::set::const_iterator i = BlocksToExtract.begin(), + e = BlocksToExtract.end(); i != e; ++i) { + // Delete the basic block from the old function, and the list of blocks + oldBlocks.remove(*i); + + // Insert this basic block into the new function + newBlocks.push_back(*i); + } +} + +/// ExtractRegion - Removes a loop from a function, replaces it with a call to +/// new function. Returns pointer to the new function. +/// +/// algorithm: +/// +/// find inputs and outputs for the region +/// +/// for inputs: add to function as args, map input instr* to arg# +/// for outputs: add allocas for scalars, +/// add to func as args, map output instr* to arg# +/// +/// rewrite func to use argument #s instead of instr* +/// +/// for each scalar output in the function: at every exit, store intermediate +/// computed result back into memory. +/// +Function *CodeExtractor:: +ExtractCodeRegion(const std::vector &code) { + if (!isEligible(code)) + return 0; + + // 1) Find inputs, outputs + // 2) Construct new function + // * Add allocas for defs, pass as args by reference + // * Pass in uses as args + // 3) Move code region, add call instr to func + // + BlocksToExtract.insert(code.begin(), code.end()); + + Values inputs, outputs; + + // Assumption: this is a single-entry code region, and the header is the first + // block in the region. + BasicBlock *header = code[0]; + + for (unsigned i = 1, e = code.size(); i != e; ++i) + for (pred_iterator PI = pred_begin(code[i]), E = pred_end(code[i]); + PI != E; ++PI) + assert(BlocksToExtract.count(*PI) && + "No blocks in this region may have entries from outside the region" + " except for the first block!"); + + // If we have to split PHI nodes or the entry block, do so now. + severSplitPHINodes(header); + + // If we have any return instructions in the region, split those blocks so + // that the return is not in the region. + splitReturnBlocks(); + + Function *oldFunction = header->getParent(); + + // This takes place of the original loop + BasicBlock *codeReplacer = BasicBlock::Create(header->getContext(), + "codeRepl", oldFunction, + header); + + // The new function needs a root node because other nodes can branch to the + // head of the region, but the entry node of a function cannot have preds. + BasicBlock *newFuncRoot = BasicBlock::Create(header->getContext(), + "newFuncRoot"); + newFuncRoot->getInstList().push_back(BranchInst::Create(header)); + + // Find inputs to, outputs from the code region. + findInputsOutputs(inputs, outputs); + + // Construct new function based on inputs/outputs & add allocas for all defs. + Function *newFunction = constructFunction(inputs, outputs, header, + newFuncRoot, + codeReplacer, oldFunction, + oldFunction->getParent()); + + emitCallAndSwitchStatement(newFunction, codeReplacer, inputs, outputs); + + moveCodeToFunction(newFunction); + + // Loop over all of the PHI nodes in the header block, and change any + // references to the old incoming edge to be the new incoming edge. + for (BasicBlock::iterator I = header->begin(); isa(I); ++I) { + PHINode *PN = cast(I); + for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) + if (!BlocksToExtract.count(PN->getIncomingBlock(i))) + PN->setIncomingBlock(i, newFuncRoot); + } + + // Look at all successors of the codeReplacer block. If any of these blocks + // had PHI nodes in them, we need to update the "from" block to be the code + // replacer, not the original block in the extracted region. + std::vector Succs(succ_begin(codeReplacer), + succ_end(codeReplacer)); + for (unsigned i = 0, e = Succs.size(); i != e; ++i) + for (BasicBlock::iterator I = Succs[i]->begin(); isa(I); ++I) { + PHINode *PN = cast(I); + std::set ProcessedPreds; + for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) + if (BlocksToExtract.count(PN->getIncomingBlock(i))) { + if (ProcessedPreds.insert(PN->getIncomingBlock(i)).second) + PN->setIncomingBlock(i, codeReplacer); + else { + // There were multiple entries in the PHI for this block, now there + // is only one, so remove the duplicated entries. + PN->removeIncomingValue(i, false); + --i; --e; + } + } + } + + //cerr << "NEW FUNCTION: " << *newFunction; + // verifyFunction(*newFunction); + + // cerr << "OLD FUNCTION: " << *oldFunction; + // verifyFunction(*oldFunction); + + DEBUG(if (verifyFunction(*newFunction)) + llvm_report_error("verifyFunction failed!")); + return newFunction; +} + +bool CodeExtractor::isEligible(const std::vector &code) { + // Deny code region if it contains allocas or vastarts. + for (std::vector::const_iterator BB = code.begin(), e=code.end(); + BB != e; ++BB) + for (BasicBlock::const_iterator I = (*BB)->begin(), Ie = (*BB)->end(); + I != Ie; ++I) + if (isa(*I)) + return false; + else if (const CallInst *CI = dyn_cast(I)) + if (const Function *F = CI->getCalledFunction()) + if (F->getIntrinsicID() == Intrinsic::vastart) + return false; + return true; +} + + +/// ExtractCodeRegion - slurp a sequence of basic blocks into a brand new +/// function +/// +Function* llvm::ExtractCodeRegion(DominatorTree &DT, + const std::vector &code, + bool AggregateArgs) { + return CodeExtractor(&DT, AggregateArgs).ExtractCodeRegion(code); +} + +/// ExtractBasicBlock - slurp a natural loop into a brand new function +/// +Function* llvm::ExtractLoop(DominatorTree &DT, Loop *L, bool AggregateArgs) { + return CodeExtractor(&DT, AggregateArgs).ExtractCodeRegion(L->getBlocks()); +} + +/// ExtractBasicBlock - slurp a basic block into a brand new function +/// +Function* llvm::ExtractBasicBlock(BasicBlock *BB, bool AggregateArgs) { + std::vector Blocks; + Blocks.push_back(BB); + return CodeExtractor(0, AggregateArgs).ExtractCodeRegion(Blocks); +} diff --git a/libclamav/c++/llvm/lib/Transforms/Utils/DemoteRegToStack.cpp b/libclamav/c++/llvm/lib/Transforms/Utils/DemoteRegToStack.cpp new file mode 100644 index 000000000..c908b4a55 --- /dev/null +++ b/libclamav/c++/llvm/lib/Transforms/Utils/DemoteRegToStack.cpp @@ -0,0 +1,146 @@ +//===- DemoteRegToStack.cpp - Move a virtual register to the stack --------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provide the function DemoteRegToStack(). This function takes a +// virtual register computed by an Instruction and replaces it with a slot in +// the stack frame, allocated via alloca. It returns the pointer to the +// AllocaInst inserted. After this function is called on an instruction, we are +// guaranteed that the only user of the instruction is a store that is +// immediately after it. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Transforms/Utils/Local.h" +#include "llvm/Function.h" +#include "llvm/Instructions.h" +#include "llvm/Type.h" +#include +using namespace llvm; + +/// DemoteRegToStack - This function takes a virtual register computed by an +/// Instruction and replaces it with a slot in the stack frame, allocated via +/// alloca. This allows the CFG to be changed around without fear of +/// invalidating the SSA information for the value. It returns the pointer to +/// the alloca inserted to create a stack slot for I. +/// +AllocaInst* llvm::DemoteRegToStack(Instruction &I, bool VolatileLoads, + Instruction *AllocaPoint) { + if (I.use_empty()) { + I.eraseFromParent(); + return 0; + } + + // Create a stack slot to hold the value. + AllocaInst *Slot; + if (AllocaPoint) { + Slot = new AllocaInst(I.getType(), 0, + I.getName()+".reg2mem", AllocaPoint); + } else { + Function *F = I.getParent()->getParent(); + Slot = new AllocaInst(I.getType(), 0, I.getName()+".reg2mem", + F->getEntryBlock().begin()); + } + + // Change all of the users of the instruction to read from the stack slot + // instead. + while (!I.use_empty()) { + Instruction *U = cast(I.use_back()); + if (PHINode *PN = dyn_cast(U)) { + // If this is a PHI node, we can't insert a load of the value before the + // use. Instead, insert the load in the predecessor block corresponding + // to the incoming value. + // + // Note that if there are multiple edges from a basic block to this PHI + // node that we cannot multiple loads. The problem is that the resultant + // PHI node will have multiple values (from each load) coming in from the + // same block, which is illegal SSA form. For this reason, we keep track + // and reuse loads we insert. + std::map Loads; + for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) + if (PN->getIncomingValue(i) == &I) { + Value *&V = Loads[PN->getIncomingBlock(i)]; + if (V == 0) { + // Insert the load into the predecessor block + V = new LoadInst(Slot, I.getName()+".reload", VolatileLoads, + PN->getIncomingBlock(i)->getTerminator()); + } + PN->setIncomingValue(i, V); + } + + } else { + // If this is a normal instruction, just insert a load. + Value *V = new LoadInst(Slot, I.getName()+".reload", VolatileLoads, U); + U->replaceUsesOfWith(&I, V); + } + } + + + // Insert stores of the computed value into the stack slot. We have to be + // careful is I is an invoke instruction though, because we can't insert the + // store AFTER the terminator instruction. + BasicBlock::iterator InsertPt; + if (!isa(I)) { + InsertPt = &I; + ++InsertPt; + } else { + // We cannot demote invoke instructions to the stack if their normal edge + // is critical. + InvokeInst &II = cast(I); + assert(II.getNormalDest()->getSinglePredecessor() && + "Cannot demote invoke with a critical successor!"); + InsertPt = II.getNormalDest()->begin(); + } + + for (; isa(InsertPt); ++InsertPt) + /* empty */; // Don't insert before any PHI nodes. + new StoreInst(&I, Slot, InsertPt); + + return Slot; +} + + +/// DemotePHIToStack - This function takes a virtual register computed by a phi +/// node and replaces it with a slot in the stack frame, allocated via alloca. +/// The phi node is deleted and it returns the pointer to the alloca inserted. +AllocaInst* llvm::DemotePHIToStack(PHINode *P, Instruction *AllocaPoint) { + if (P->use_empty()) { + P->eraseFromParent(); + return 0; + } + + // Create a stack slot to hold the value. + AllocaInst *Slot; + if (AllocaPoint) { + Slot = new AllocaInst(P->getType(), 0, + P->getName()+".reg2mem", AllocaPoint); + } else { + Function *F = P->getParent()->getParent(); + Slot = new AllocaInst(P->getType(), 0, P->getName()+".reg2mem", + F->getEntryBlock().begin()); + } + + // Iterate over each operand, insert store in each predecessor. + for (unsigned i = 0, e = P->getNumIncomingValues(); i < e; ++i) { + if (InvokeInst *II = dyn_cast(P->getIncomingValue(i))) { + assert(II->getParent() != P->getIncomingBlock(i) && + "Invoke edge not supported yet"); II=II; + } + new StoreInst(P->getIncomingValue(i), Slot, + P->getIncomingBlock(i)->getTerminator()); + } + + // Insert load in place of the phi and replace all uses. + Value *V = new LoadInst(Slot, P->getName()+".reload", P); + P->replaceAllUsesWith(V); + + // Delete phi. + P->eraseFromParent(); + + return Slot; +} diff --git a/libclamav/c++/llvm/lib/Transforms/Utils/InlineFunction.cpp b/libclamav/c++/llvm/lib/Transforms/Utils/InlineFunction.cpp new file mode 100644 index 000000000..043046c81 --- /dev/null +++ b/libclamav/c++/llvm/lib/Transforms/Utils/InlineFunction.cpp @@ -0,0 +1,687 @@ +//===- InlineFunction.cpp - Code to perform function inlining -------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements inlining of a function into a call site, resolving +// parameters and the return value as appropriate. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Transforms/Utils/Cloning.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/LLVMContext.h" +#include "llvm/Module.h" +#include "llvm/Instructions.h" +#include "llvm/IntrinsicInst.h" +#include "llvm/Intrinsics.h" +#include "llvm/Attributes.h" +#include "llvm/Analysis/CallGraph.h" +#include "llvm/Analysis/DebugInfo.h" +#include "llvm/Target/TargetData.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/Support/CallSite.h" +using namespace llvm; + +bool llvm::InlineFunction(CallInst *CI, CallGraph *CG, const TargetData *TD, + SmallVectorImpl *StaticAllocas) { + return InlineFunction(CallSite(CI), CG, TD, StaticAllocas); +} +bool llvm::InlineFunction(InvokeInst *II, CallGraph *CG, const TargetData *TD, + SmallVectorImpl *StaticAllocas) { + return InlineFunction(CallSite(II), CG, TD, StaticAllocas); +} + + +/// HandleCallsInBlockInlinedThroughInvoke - When we inline a basic block into +/// an invoke, we have to turn all of the calls that can throw into +/// invokes. This function analyze BB to see if there are any calls, and if so, +/// it rewrites them to be invokes that jump to InvokeDest and fills in the PHI +/// nodes in that block with the values specified in InvokeDestPHIValues. +/// +static void HandleCallsInBlockInlinedThroughInvoke(BasicBlock *BB, + BasicBlock *InvokeDest, + const SmallVectorImpl &InvokeDestPHIValues) { + for (BasicBlock::iterator BBI = BB->begin(), E = BB->end(); BBI != E; ) { + Instruction *I = BBI++; + + // We only need to check for function calls: inlined invoke + // instructions require no special handling. + CallInst *CI = dyn_cast(I); + if (CI == 0) continue; + + // If this call cannot unwind, don't convert it to an invoke. + if (CI->doesNotThrow()) + continue; + + // Convert this function call into an invoke instruction. + // First, split the basic block. + BasicBlock *Split = BB->splitBasicBlock(CI, CI->getName()+".noexc"); + + // Next, create the new invoke instruction, inserting it at the end + // of the old basic block. + SmallVector InvokeArgs(CI->op_begin()+1, CI->op_end()); + InvokeInst *II = + InvokeInst::Create(CI->getCalledValue(), Split, InvokeDest, + InvokeArgs.begin(), InvokeArgs.end(), + CI->getName(), BB->getTerminator()); + II->setCallingConv(CI->getCallingConv()); + II->setAttributes(CI->getAttributes()); + + // Make sure that anything using the call now uses the invoke! This also + // updates the CallGraph if present. + CI->replaceAllUsesWith(II); + + // Delete the unconditional branch inserted by splitBasicBlock + BB->getInstList().pop_back(); + Split->getInstList().pop_front(); // Delete the original call + + // Update any PHI nodes in the exceptional block to indicate that + // there is now a new entry in them. + unsigned i = 0; + for (BasicBlock::iterator I = InvokeDest->begin(); + isa(I); ++I, ++i) + cast(I)->addIncoming(InvokeDestPHIValues[i], BB); + + // This basic block is now complete, the caller will continue scanning the + // next one. + return; + } +} + + +/// HandleInlinedInvoke - If we inlined an invoke site, we need to convert calls +/// in the body of the inlined function into invokes and turn unwind +/// instructions into branches to the invoke unwind dest. +/// +/// II is the invoke instruction being inlined. FirstNewBlock is the first +/// block of the inlined code (the last block is the end of the function), +/// and InlineCodeInfo is information about the code that got inlined. +static void HandleInlinedInvoke(InvokeInst *II, BasicBlock *FirstNewBlock, + ClonedCodeInfo &InlinedCodeInfo) { + BasicBlock *InvokeDest = II->getUnwindDest(); + SmallVector InvokeDestPHIValues; + + // If there are PHI nodes in the unwind destination block, we need to + // keep track of which values came into them from this invoke, then remove + // the entry for this block. + BasicBlock *InvokeBlock = II->getParent(); + for (BasicBlock::iterator I = InvokeDest->begin(); isa(I); ++I) { + PHINode *PN = cast(I); + // Save the value to use for this edge. + InvokeDestPHIValues.push_back(PN->getIncomingValueForBlock(InvokeBlock)); + } + + Function *Caller = FirstNewBlock->getParent(); + + // The inlined code is currently at the end of the function, scan from the + // start of the inlined code to its end, checking for stuff we need to + // rewrite. If the code doesn't have calls or unwinds, we know there is + // nothing to rewrite. + if (!InlinedCodeInfo.ContainsCalls && !InlinedCodeInfo.ContainsUnwinds) { + // Now that everything is happy, we have one final detail. The PHI nodes in + // the exception destination block still have entries due to the original + // invoke instruction. Eliminate these entries (which might even delete the + // PHI node) now. + InvokeDest->removePredecessor(II->getParent()); + return; + } + + for (Function::iterator BB = FirstNewBlock, E = Caller->end(); BB != E; ++BB){ + if (InlinedCodeInfo.ContainsCalls) + HandleCallsInBlockInlinedThroughInvoke(BB, InvokeDest, + InvokeDestPHIValues); + + if (UnwindInst *UI = dyn_cast(BB->getTerminator())) { + // An UnwindInst requires special handling when it gets inlined into an + // invoke site. Once this happens, we know that the unwind would cause + // a control transfer to the invoke exception destination, so we can + // transform it into a direct branch to the exception destination. + BranchInst::Create(InvokeDest, UI); + + // Delete the unwind instruction! + UI->eraseFromParent(); + + // Update any PHI nodes in the exceptional block to indicate that + // there is now a new entry in them. + unsigned i = 0; + for (BasicBlock::iterator I = InvokeDest->begin(); + isa(I); ++I, ++i) { + PHINode *PN = cast(I); + PN->addIncoming(InvokeDestPHIValues[i], BB); + } + } + } + + // Now that everything is happy, we have one final detail. The PHI nodes in + // the exception destination block still have entries due to the original + // invoke instruction. Eliminate these entries (which might even delete the + // PHI node) now. + InvokeDest->removePredecessor(II->getParent()); +} + +/// UpdateCallGraphAfterInlining - Once we have cloned code over from a callee +/// into the caller, update the specified callgraph to reflect the changes we +/// made. Note that it's possible that not all code was copied over, so only +/// some edges of the callgraph may remain. +static void UpdateCallGraphAfterInlining(CallSite CS, + Function::iterator FirstNewBlock, + DenseMap &ValueMap, + CallGraph &CG) { + const Function *Caller = CS.getInstruction()->getParent()->getParent(); + const Function *Callee = CS.getCalledFunction(); + CallGraphNode *CalleeNode = CG[Callee]; + CallGraphNode *CallerNode = CG[Caller]; + + // Since we inlined some uninlined call sites in the callee into the caller, + // add edges from the caller to all of the callees of the callee. + CallGraphNode::iterator I = CalleeNode->begin(), E = CalleeNode->end(); + + // Consider the case where CalleeNode == CallerNode. + CallGraphNode::CalledFunctionsVector CallCache; + if (CalleeNode == CallerNode) { + CallCache.assign(I, E); + I = CallCache.begin(); + E = CallCache.end(); + } + + for (; I != E; ++I) { + const Value *OrigCall = I->first; + + DenseMap::iterator VMI = ValueMap.find(OrigCall); + // Only copy the edge if the call was inlined! + if (VMI == ValueMap.end() || VMI->second == 0) + continue; + + // If the call was inlined, but then constant folded, there is no edge to + // add. Check for this case. + if (Instruction *NewCall = dyn_cast(VMI->second)) + CallerNode->addCalledFunction(CallSite::get(NewCall), I->second); + } + + // Update the call graph by deleting the edge from Callee to Caller. We must + // do this after the loop above in case Caller and Callee are the same. + CallerNode->removeCallEdgeFor(CS); +} + +/// findFnRegionEndMarker - This is a utility routine that is used by +/// InlineFunction. Return llvm.dbg.region.end intrinsic that corresponds +/// to the llvm.dbg.func.start of the function F. Otherwise return NULL. +/// +static const DbgRegionEndInst *findFnRegionEndMarker(const Function *F) { + + MDNode *FnStart = NULL; + const DbgRegionEndInst *FnEnd = NULL; + for (Function::const_iterator FI = F->begin(), FE =F->end(); FI != FE; ++FI) + for (BasicBlock::const_iterator BI = FI->begin(), BE = FI->end(); BI != BE; + ++BI) { + if (FnStart == NULL) { + if (const DbgFuncStartInst *FSI = dyn_cast(BI)) { + DISubprogram SP(FSI->getSubprogram()); + assert (SP.isNull() == false && "Invalid llvm.dbg.func.start"); + if (SP.describes(F)) + FnStart = SP.getNode(); + } + continue; + } + + if (const DbgRegionEndInst *REI = dyn_cast(BI)) + if (REI->getContext() == FnStart) + FnEnd = REI; + } + return FnEnd; +} + +// InlineFunction - This function inlines the called function into the basic +// block of the caller. This returns false if it is not possible to inline this +// call. The program is still in a well defined state if this occurs though. +// +// Note that this only does one level of inlining. For example, if the +// instruction 'call B' is inlined, and 'B' calls 'C', then the call to 'C' now +// exists in the instruction stream. Similiarly this will inline a recursive +// function by one level. +// +bool llvm::InlineFunction(CallSite CS, CallGraph *CG, const TargetData *TD, + SmallVectorImpl *StaticAllocas) { + Instruction *TheCall = CS.getInstruction(); + LLVMContext &Context = TheCall->getContext(); + assert(TheCall->getParent() && TheCall->getParent()->getParent() && + "Instruction not in function!"); + + const Function *CalledFunc = CS.getCalledFunction(); + if (CalledFunc == 0 || // Can't inline external function or indirect + CalledFunc->isDeclaration() || // call, or call to a vararg function! + CalledFunc->getFunctionType()->isVarArg()) return false; + + + // If the call to the callee is not a tail call, we must clear the 'tail' + // flags on any calls that we inline. + bool MustClearTailCallFlags = + !(isa(TheCall) && cast(TheCall)->isTailCall()); + + // If the call to the callee cannot throw, set the 'nounwind' flag on any + // calls that we inline. + bool MarkNoUnwind = CS.doesNotThrow(); + + BasicBlock *OrigBB = TheCall->getParent(); + Function *Caller = OrigBB->getParent(); + + // GC poses two hazards to inlining, which only occur when the callee has GC: + // 1. If the caller has no GC, then the callee's GC must be propagated to the + // caller. + // 2. If the caller has a differing GC, it is invalid to inline. + if (CalledFunc->hasGC()) { + if (!Caller->hasGC()) + Caller->setGC(CalledFunc->getGC()); + else if (CalledFunc->getGC() != Caller->getGC()) + return false; + } + + // Get an iterator to the last basic block in the function, which will have + // the new function inlined after it. + // + Function::iterator LastBlock = &Caller->back(); + + // Make sure to capture all of the return instructions from the cloned + // function. + SmallVector Returns; + ClonedCodeInfo InlinedFunctionInfo; + Function::iterator FirstNewBlock; + + { // Scope to destroy ValueMap after cloning. + DenseMap ValueMap; + + assert(CalledFunc->arg_size() == CS.arg_size() && + "No varargs calls can be inlined!"); + + // Calculate the vector of arguments to pass into the function cloner, which + // matches up the formal to the actual argument values. + CallSite::arg_iterator AI = CS.arg_begin(); + unsigned ArgNo = 0; + for (Function::const_arg_iterator I = CalledFunc->arg_begin(), + E = CalledFunc->arg_end(); I != E; ++I, ++AI, ++ArgNo) { + Value *ActualArg = *AI; + + // When byval arguments actually inlined, we need to make the copy implied + // by them explicit. However, we don't do this if the callee is readonly + // or readnone, because the copy would be unneeded: the callee doesn't + // modify the struct. + if (CalledFunc->paramHasAttr(ArgNo+1, Attribute::ByVal) && + !CalledFunc->onlyReadsMemory()) { + const Type *AggTy = cast(I->getType())->getElementType(); + const Type *VoidPtrTy = + Type::getInt8PtrTy(Context); + + // Create the alloca. If we have TargetData, use nice alignment. + unsigned Align = 1; + if (TD) Align = TD->getPrefTypeAlignment(AggTy); + Value *NewAlloca = new AllocaInst(AggTy, 0, Align, + I->getName(), + &*Caller->begin()->begin()); + // Emit a memcpy. + const Type *Tys[] = { Type::getInt64Ty(Context) }; + Function *MemCpyFn = Intrinsic::getDeclaration(Caller->getParent(), + Intrinsic::memcpy, + Tys, 1); + Value *DestCast = new BitCastInst(NewAlloca, VoidPtrTy, "tmp", TheCall); + Value *SrcCast = new BitCastInst(*AI, VoidPtrTy, "tmp", TheCall); + + Value *Size; + if (TD == 0) + Size = ConstantExpr::getSizeOf(AggTy); + else + Size = ConstantInt::get(Type::getInt64Ty(Context), + TD->getTypeStoreSize(AggTy)); + + // Always generate a memcpy of alignment 1 here because we don't know + // the alignment of the src pointer. Other optimizations can infer + // better alignment. + Value *CallArgs[] = { + DestCast, SrcCast, Size, + ConstantInt::get(Type::getInt32Ty(Context), 1) + }; + CallInst *TheMemCpy = + CallInst::Create(MemCpyFn, CallArgs, CallArgs+4, "", TheCall); + + // If we have a call graph, update it. + if (CG) { + CallGraphNode *MemCpyCGN = CG->getOrInsertFunction(MemCpyFn); + CallGraphNode *CallerNode = (*CG)[Caller]; + CallerNode->addCalledFunction(TheMemCpy, MemCpyCGN); + } + + // Uses of the argument in the function should use our new alloca + // instead. + ActualArg = NewAlloca; + } + + ValueMap[I] = ActualArg; + } + + // Adjust llvm.dbg.region.end. If the CalledFunc has region end + // marker then clone that marker after next stop point at the + // call site. The function body cloner does not clone original + // region end marker from the CalledFunc. This will ensure that + // inlined function's scope ends at the right place. + if (const DbgRegionEndInst *DREI = findFnRegionEndMarker(CalledFunc)) { + for (BasicBlock::iterator BI = TheCall, BE = TheCall->getParent()->end(); + BI != BE; ++BI) { + if (DbgStopPointInst *DSPI = dyn_cast(BI)) { + if (DbgRegionEndInst *NewDREI = + dyn_cast(DREI->clone())) + NewDREI->insertAfter(DSPI); + break; + } + } + } + + // We want the inliner to prune the code as it copies. We would LOVE to + // have no dead or constant instructions leftover after inlining occurs + // (which can happen, e.g., because an argument was constant), but we'll be + // happy with whatever the cloner can do. + CloneAndPruneFunctionInto(Caller, CalledFunc, ValueMap, Returns, ".i", + &InlinedFunctionInfo, TD, TheCall); + + // Remember the first block that is newly cloned over. + FirstNewBlock = LastBlock; ++FirstNewBlock; + + // Update the callgraph if requested. + if (CG) + UpdateCallGraphAfterInlining(CS, FirstNewBlock, ValueMap, *CG); + } + + // If there are any alloca instructions in the block that used to be the entry + // block for the callee, move them to the entry block of the caller. First + // calculate which instruction they should be inserted before. We insert the + // instructions at the end of the current alloca list. + // + { + BasicBlock::iterator InsertPoint = Caller->begin()->begin(); + for (BasicBlock::iterator I = FirstNewBlock->begin(), + E = FirstNewBlock->end(); I != E; ) { + AllocaInst *AI = dyn_cast(I++); + if (AI == 0) continue; + + // If the alloca is now dead, remove it. This often occurs due to code + // specialization. + if (AI->use_empty()) { + AI->eraseFromParent(); + continue; + } + + if (!isa(AI->getArraySize())) + continue; + + // Keep track of the static allocas that we inline into the caller if the + // StaticAllocas pointer is non-null. + if (StaticAllocas) StaticAllocas->push_back(AI); + + // Scan for the block of allocas that we can move over, and move them + // all at once. + while (isa(I) && + isa(cast(I)->getArraySize())) { + if (StaticAllocas) StaticAllocas->push_back(cast(I)); + ++I; + } + + // Transfer all of the allocas over in a block. Using splice means + // that the instructions aren't removed from the symbol table, then + // reinserted. + Caller->getEntryBlock().getInstList().splice(InsertPoint, + FirstNewBlock->getInstList(), + AI, I); + } + } + + // If the inlined code contained dynamic alloca instructions, wrap the inlined + // code with llvm.stacksave/llvm.stackrestore intrinsics. + if (InlinedFunctionInfo.ContainsDynamicAllocas) { + Module *M = Caller->getParent(); + // Get the two intrinsics we care about. + Function *StackSave = Intrinsic::getDeclaration(M, Intrinsic::stacksave); + Function *StackRestore=Intrinsic::getDeclaration(M,Intrinsic::stackrestore); + + // If we are preserving the callgraph, add edges to the stacksave/restore + // functions for the calls we insert. + CallGraphNode *StackSaveCGN = 0, *StackRestoreCGN = 0, *CallerNode = 0; + if (CG) { + StackSaveCGN = CG->getOrInsertFunction(StackSave); + StackRestoreCGN = CG->getOrInsertFunction(StackRestore); + CallerNode = (*CG)[Caller]; + } + + // Insert the llvm.stacksave. + CallInst *SavedPtr = CallInst::Create(StackSave, "savedstack", + FirstNewBlock->begin()); + if (CG) CallerNode->addCalledFunction(SavedPtr, StackSaveCGN); + + // Insert a call to llvm.stackrestore before any return instructions in the + // inlined function. + for (unsigned i = 0, e = Returns.size(); i != e; ++i) { + CallInst *CI = CallInst::Create(StackRestore, SavedPtr, "", Returns[i]); + if (CG) CallerNode->addCalledFunction(CI, StackRestoreCGN); + } + + // Count the number of StackRestore calls we insert. + unsigned NumStackRestores = Returns.size(); + + // If we are inlining an invoke instruction, insert restores before each + // unwind. These unwinds will be rewritten into branches later. + if (InlinedFunctionInfo.ContainsUnwinds && isa(TheCall)) { + for (Function::iterator BB = FirstNewBlock, E = Caller->end(); + BB != E; ++BB) + if (UnwindInst *UI = dyn_cast(BB->getTerminator())) { + CallInst *CI = CallInst::Create(StackRestore, SavedPtr, "", UI); + if (CG) CallerNode->addCalledFunction(CI, StackRestoreCGN); + ++NumStackRestores; + } + } + } + + // If we are inlining tail call instruction through a call site that isn't + // marked 'tail', we must remove the tail marker for any calls in the inlined + // code. Also, calls inlined through a 'nounwind' call site should be marked + // 'nounwind'. + if (InlinedFunctionInfo.ContainsCalls && + (MustClearTailCallFlags || MarkNoUnwind)) { + for (Function::iterator BB = FirstNewBlock, E = Caller->end(); + BB != E; ++BB) + for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ++I) + if (CallInst *CI = dyn_cast(I)) { + if (MustClearTailCallFlags) + CI->setTailCall(false); + if (MarkNoUnwind) + CI->setDoesNotThrow(); + } + } + + // If we are inlining through a 'nounwind' call site then any inlined 'unwind' + // instructions are unreachable. + if (InlinedFunctionInfo.ContainsUnwinds && MarkNoUnwind) + for (Function::iterator BB = FirstNewBlock, E = Caller->end(); + BB != E; ++BB) { + TerminatorInst *Term = BB->getTerminator(); + if (isa(Term)) { + new UnreachableInst(Context, Term); + BB->getInstList().erase(Term); + } + } + + // If we are inlining for an invoke instruction, we must make sure to rewrite + // any inlined 'unwind' instructions into branches to the invoke exception + // destination, and call instructions into invoke instructions. + if (InvokeInst *II = dyn_cast(TheCall)) + HandleInlinedInvoke(II, FirstNewBlock, InlinedFunctionInfo); + + // If we cloned in _exactly one_ basic block, and if that block ends in a + // return instruction, we splice the body of the inlined callee directly into + // the calling basic block. + if (Returns.size() == 1 && std::distance(FirstNewBlock, Caller->end()) == 1) { + // Move all of the instructions right before the call. + OrigBB->getInstList().splice(TheCall, FirstNewBlock->getInstList(), + FirstNewBlock->begin(), FirstNewBlock->end()); + // Remove the cloned basic block. + Caller->getBasicBlockList().pop_back(); + + // If the call site was an invoke instruction, add a branch to the normal + // destination. + if (InvokeInst *II = dyn_cast(TheCall)) + BranchInst::Create(II->getNormalDest(), TheCall); + + // If the return instruction returned a value, replace uses of the call with + // uses of the returned value. + if (!TheCall->use_empty()) { + ReturnInst *R = Returns[0]; + if (TheCall == R->getReturnValue()) + TheCall->replaceAllUsesWith(UndefValue::get(TheCall->getType())); + else + TheCall->replaceAllUsesWith(R->getReturnValue()); + } + // Since we are now done with the Call/Invoke, we can delete it. + TheCall->eraseFromParent(); + + // Since we are now done with the return instruction, delete it also. + Returns[0]->eraseFromParent(); + + // We are now done with the inlining. + return true; + } + + // Otherwise, we have the normal case, of more than one block to inline or + // multiple return sites. + + // We want to clone the entire callee function into the hole between the + // "starter" and "ender" blocks. How we accomplish this depends on whether + // this is an invoke instruction or a call instruction. + BasicBlock *AfterCallBB; + if (InvokeInst *II = dyn_cast(TheCall)) { + + // Add an unconditional branch to make this look like the CallInst case... + BranchInst *NewBr = BranchInst::Create(II->getNormalDest(), TheCall); + + // Split the basic block. This guarantees that no PHI nodes will have to be + // updated due to new incoming edges, and make the invoke case more + // symmetric to the call case. + AfterCallBB = OrigBB->splitBasicBlock(NewBr, + CalledFunc->getName()+".exit"); + + } else { // It's a call + // If this is a call instruction, we need to split the basic block that + // the call lives in. + // + AfterCallBB = OrigBB->splitBasicBlock(TheCall, + CalledFunc->getName()+".exit"); + } + + // Change the branch that used to go to AfterCallBB to branch to the first + // basic block of the inlined function. + // + TerminatorInst *Br = OrigBB->getTerminator(); + assert(Br && Br->getOpcode() == Instruction::Br && + "splitBasicBlock broken!"); + Br->setOperand(0, FirstNewBlock); + + + // Now that the function is correct, make it a little bit nicer. In + // particular, move the basic blocks inserted from the end of the function + // into the space made by splitting the source basic block. + Caller->getBasicBlockList().splice(AfterCallBB, Caller->getBasicBlockList(), + FirstNewBlock, Caller->end()); + + // Handle all of the return instructions that we just cloned in, and eliminate + // any users of the original call/invoke instruction. + const Type *RTy = CalledFunc->getReturnType(); + + if (Returns.size() > 1) { + // The PHI node should go at the front of the new basic block to merge all + // possible incoming values. + PHINode *PHI = 0; + if (!TheCall->use_empty()) { + PHI = PHINode::Create(RTy, TheCall->getName(), + AfterCallBB->begin()); + // Anything that used the result of the function call should now use the + // PHI node as their operand. + TheCall->replaceAllUsesWith(PHI); + } + + // Loop over all of the return instructions adding entries to the PHI node + // as appropriate. + if (PHI) { + for (unsigned i = 0, e = Returns.size(); i != e; ++i) { + ReturnInst *RI = Returns[i]; + assert(RI->getReturnValue()->getType() == PHI->getType() && + "Ret value not consistent in function!"); + PHI->addIncoming(RI->getReturnValue(), RI->getParent()); + } + + // Now that we inserted the PHI, check to see if it has a single value + // (e.g. all the entries are the same or undef). If so, remove the PHI so + // it doesn't block other optimizations. + if (Value *V = PHI->hasConstantValue()) { + PHI->replaceAllUsesWith(V); + PHI->eraseFromParent(); + } + } + + + // Add a branch to the merge points and remove return instructions. + for (unsigned i = 0, e = Returns.size(); i != e; ++i) { + ReturnInst *RI = Returns[i]; + BranchInst::Create(AfterCallBB, RI); + RI->eraseFromParent(); + } + } else if (!Returns.empty()) { + // Otherwise, if there is exactly one return value, just replace anything + // using the return value of the call with the computed value. + if (!TheCall->use_empty()) { + if (TheCall == Returns[0]->getReturnValue()) + TheCall->replaceAllUsesWith(UndefValue::get(TheCall->getType())); + else + TheCall->replaceAllUsesWith(Returns[0]->getReturnValue()); + } + + // Splice the code from the return block into the block that it will return + // to, which contains the code that was after the call. + BasicBlock *ReturnBB = Returns[0]->getParent(); + AfterCallBB->getInstList().splice(AfterCallBB->begin(), + ReturnBB->getInstList()); + + // Update PHI nodes that use the ReturnBB to use the AfterCallBB. + ReturnBB->replaceAllUsesWith(AfterCallBB); + + // Delete the return instruction now and empty ReturnBB now. + Returns[0]->eraseFromParent(); + ReturnBB->eraseFromParent(); + } else if (!TheCall->use_empty()) { + // No returns, but something is using the return value of the call. Just + // nuke the result. + TheCall->replaceAllUsesWith(UndefValue::get(TheCall->getType())); + } + + // Since we are now done with the Call/Invoke, we can delete it. + TheCall->eraseFromParent(); + + // We should always be able to fold the entry block of the function into the + // single predecessor of the block... + assert(cast(Br)->isUnconditional() && "splitBasicBlock broken!"); + BasicBlock *CalleeEntry = cast(Br)->getSuccessor(0); + + // Splice the code entry block into calling block, right before the + // unconditional branch. + OrigBB->getInstList().splice(Br, CalleeEntry->getInstList()); + CalleeEntry->replaceAllUsesWith(OrigBB); // Update PHI nodes + + // Remove the unconditional branch. + OrigBB->getInstList().erase(Br); + + // Now we can remove the CalleeEntry block, which is now empty. + Caller->getBasicBlockList().erase(CalleeEntry); + + return true; +} diff --git a/libclamav/c++/llvm/lib/Transforms/Utils/InstructionNamer.cpp b/libclamav/c++/llvm/lib/Transforms/Utils/InstructionNamer.cpp new file mode 100644 index 000000000..7f11acf4d --- /dev/null +++ b/libclamav/c++/llvm/lib/Transforms/Utils/InstructionNamer.cpp @@ -0,0 +1,63 @@ +//===- InstructionNamer.cpp - Give anonymous instructions names -----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This is a little utility pass that gives instructions names, this is mostly +// useful when diffing the effect of an optimization because deleting an +// unnamed instruction can change all other instruction numbering, making the +// diff very noisy. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Transforms/Scalar.h" +#include "llvm/Function.h" +#include "llvm/Pass.h" +#include "llvm/Type.h" +using namespace llvm; + +namespace { + struct InstNamer : public FunctionPass { + static char ID; // Pass identification, replacement for typeid + InstNamer() : FunctionPass(&ID) {} + + void getAnalysisUsage(AnalysisUsage &Info) const { + Info.setPreservesAll(); + } + + bool runOnFunction(Function &F) { + for (Function::arg_iterator AI = F.arg_begin(), AE = F.arg_end(); + AI != AE; ++AI) + if (!AI->hasName() && AI->getType() != Type::getVoidTy(F.getContext())) + AI->setName("arg"); + + for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB) { + if (!BB->hasName()) + BB->setName("bb"); + + for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ++I) + if (!I->hasName() && I->getType() != Type::getVoidTy(F.getContext())) + I->setName("tmp"); + } + return true; + } + }; + + char InstNamer::ID = 0; + static RegisterPass X("instnamer", + "Assign names to anonymous instructions"); +} + + +const PassInfo *const llvm::InstructionNamerID = &X; +//===----------------------------------------------------------------------===// +// +// InstructionNamer - Give any unnamed non-void instructions "tmp" names. +// +FunctionPass *llvm::createInstructionNamerPass() { + return new InstNamer(); +} diff --git a/libclamav/c++/llvm/lib/Transforms/Utils/LCSSA.cpp b/libclamav/c++/llvm/lib/Transforms/Utils/LCSSA.cpp new file mode 100644 index 000000000..590d667a1 --- /dev/null +++ b/libclamav/c++/llvm/lib/Transforms/Utils/LCSSA.cpp @@ -0,0 +1,274 @@ +//===-- LCSSA.cpp - Convert loops into loop-closed SSA form ---------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This pass transforms loops by placing phi nodes at the end of the loops for +// all values that are live across the loop boundary. For example, it turns +// the left into the right code: +// +// for (...) for (...) +// if (c) if (c) +// X1 = ... X1 = ... +// else else +// X2 = ... X2 = ... +// X3 = phi(X1, X2) X3 = phi(X1, X2) +// ... = X3 + 4 X4 = phi(X3) +// ... = X4 + 4 +// +// This is still valid LLVM; the extra phi nodes are purely redundant, and will +// be trivially eliminated by InstCombine. The major benefit of this +// transformation is that it makes many other loop optimizations, such as +// LoopUnswitching, simpler. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "lcssa" +#include "llvm/Transforms/Scalar.h" +#include "llvm/Constants.h" +#include "llvm/Pass.h" +#include "llvm/Function.h" +#include "llvm/Instructions.h" +#include "llvm/Analysis/Dominators.h" +#include "llvm/Analysis/LoopPass.h" +#include "llvm/Analysis/ScalarEvolution.h" +#include "llvm/Transforms/Utils/SSAUpdater.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/Support/PredIteratorCache.h" +using namespace llvm; + +STATISTIC(NumLCSSA, "Number of live out of a loop variables"); + +namespace { + struct LCSSA : public LoopPass { + static char ID; // Pass identification, replacement for typeid + LCSSA() : LoopPass(&ID) {} + + // Cached analysis information for the current function. + DominatorTree *DT; + std::vector LoopBlocks; + PredIteratorCache PredCache; + Loop *L; + + virtual bool runOnLoop(Loop *L, LPPassManager &LPM); + + /// This transformation requires natural loop information & requires that + /// loop preheaders be inserted into the CFG. It maintains both of these, + /// as well as the CFG. It also requires dominator information. + /// + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesCFG(); + + // LCSSA doesn't actually require LoopSimplify, but the PassManager + // doesn't know how to schedule LoopSimplify by itself. + AU.addRequiredID(LoopSimplifyID); + AU.addPreservedID(LoopSimplifyID); + AU.addRequiredTransitive(); + AU.addPreserved(); + AU.addRequiredTransitive(); + AU.addPreserved(); + AU.addPreserved(); + + // Request DominanceFrontier now, even though LCSSA does + // not use it. This allows Pass Manager to schedule Dominance + // Frontier early enough such that one LPPassManager can handle + // multiple loop transformation passes. + AU.addRequired(); + AU.addPreserved(); + } + private: + bool ProcessInstruction(Instruction *Inst, + const SmallVectorImpl &ExitBlocks); + + /// verifyAnalysis() - Verify loop nest. + virtual void verifyAnalysis() const { + // Check the special guarantees that LCSSA makes. + assert(L->isLCSSAForm() && "LCSSA form not preserved!"); + } + + /// inLoop - returns true if the given block is within the current loop + bool inLoop(BasicBlock *B) const { + return std::binary_search(LoopBlocks.begin(), LoopBlocks.end(), B); + } + }; +} + +char LCSSA::ID = 0; +static RegisterPass X("lcssa", "Loop-Closed SSA Form Pass"); + +Pass *llvm::createLCSSAPass() { return new LCSSA(); } +const PassInfo *const llvm::LCSSAID = &X; + + +/// BlockDominatesAnExit - Return true if the specified block dominates at least +/// one of the blocks in the specified list. +static bool BlockDominatesAnExit(BasicBlock *BB, + const SmallVectorImpl &ExitBlocks, + DominatorTree *DT) { + DomTreeNode *DomNode = DT->getNode(BB); + for (unsigned i = 0, e = ExitBlocks.size(); i != e; ++i) + if (DT->dominates(DomNode, DT->getNode(ExitBlocks[i]))) + return true; + + return false; +} + + +/// runOnFunction - Process all loops in the function, inner-most out. +bool LCSSA::runOnLoop(Loop *TheLoop, LPPassManager &LPM) { + L = TheLoop; + + DT = &getAnalysis(); + + // Get the set of exiting blocks. + SmallVector ExitBlocks; + L->getExitBlocks(ExitBlocks); + + if (ExitBlocks.empty()) + return false; + + // Speed up queries by creating a sorted vector of blocks. + LoopBlocks.clear(); + LoopBlocks.insert(LoopBlocks.end(), L->block_begin(), L->block_end()); + array_pod_sort(LoopBlocks.begin(), LoopBlocks.end()); + + // Look at all the instructions in the loop, checking to see if they have uses + // outside the loop. If so, rewrite those uses. + bool MadeChange = false; + + for (Loop::block_iterator BBI = L->block_begin(), E = L->block_end(); + BBI != E; ++BBI) { + BasicBlock *BB = *BBI; + + // For large loops, avoid use-scanning by using dominance information: In + // particular, if a block does not dominate any of the loop exits, then none + // of the values defined in the block could be used outside the loop. + if (!BlockDominatesAnExit(BB, ExitBlocks, DT)) + continue; + + for (BasicBlock::iterator I = BB->begin(), E = BB->end(); + I != E; ++I) { + // Reject two common cases fast: instructions with no uses (like stores) + // and instructions with one use that is in the same block as this. + if (I->use_empty() || + (I->hasOneUse() && I->use_back()->getParent() == BB && + !isa(I->use_back()))) + continue; + + MadeChange |= ProcessInstruction(I, ExitBlocks); + } + } + + assert(L->isLCSSAForm()); + PredCache.clear(); + + return MadeChange; +} + +/// isExitBlock - Return true if the specified block is in the list. +static bool isExitBlock(BasicBlock *BB, + const SmallVectorImpl &ExitBlocks) { + for (unsigned i = 0, e = ExitBlocks.size(); i != e; ++i) + if (ExitBlocks[i] == BB) + return true; + return false; +} + +/// ProcessInstruction - Given an instruction in the loop, check to see if it +/// has any uses that are outside the current loop. If so, insert LCSSA PHI +/// nodes and rewrite the uses. +bool LCSSA::ProcessInstruction(Instruction *Inst, + const SmallVectorImpl &ExitBlocks) { + SmallVector UsesToRewrite; + + BasicBlock *InstBB = Inst->getParent(); + + for (Value::use_iterator UI = Inst->use_begin(), E = Inst->use_end(); + UI != E; ++UI) { + BasicBlock *UserBB = cast(*UI)->getParent(); + if (PHINode *PN = dyn_cast(*UI)) + UserBB = PN->getIncomingBlock(UI); + + if (InstBB != UserBB && !inLoop(UserBB)) + UsesToRewrite.push_back(&UI.getUse()); + } + + // If there are no uses outside the loop, exit with no change. + if (UsesToRewrite.empty()) return false; + + ++NumLCSSA; // We are applying the transformation + + // Invoke instructions are special in that their result value is not available + // along their unwind edge. The code below tests to see whether DomBB dominates + // the value, so adjust DomBB to the normal destination block, which is + // effectively where the value is first usable. + BasicBlock *DomBB = Inst->getParent(); + if (InvokeInst *Inv = dyn_cast(Inst)) + DomBB = Inv->getNormalDest(); + + DomTreeNode *DomNode = DT->getNode(DomBB); + + SSAUpdater SSAUpdate; + SSAUpdate.Initialize(Inst); + + // Insert the LCSSA phi's into all of the exit blocks dominated by the + // value, and add them to the Phi's map. + for (SmallVectorImpl::const_iterator BBI = ExitBlocks.begin(), + BBE = ExitBlocks.end(); BBI != BBE; ++BBI) { + BasicBlock *ExitBB = *BBI; + if (!DT->dominates(DomNode, DT->getNode(ExitBB))) continue; + + // If we already inserted something for this BB, don't reprocess it. + if (SSAUpdate.HasValueForBlock(ExitBB)) continue; + + PHINode *PN = PHINode::Create(Inst->getType(), Inst->getName()+".lcssa", + ExitBB->begin()); + PN->reserveOperandSpace(PredCache.GetNumPreds(ExitBB)); + + // Add inputs from inside the loop for this PHI. + for (BasicBlock **PI = PredCache.GetPreds(ExitBB); *PI; ++PI) { + PN->addIncoming(Inst, *PI); + + // If the exit block has a predecessor not within the loop, arrange for + // the incoming value use corresponding to that predecessor to be + // rewritten in terms of a different LCSSA PHI. + if (!inLoop(*PI)) + UsesToRewrite.push_back( + &PN->getOperandUse( + PN->getOperandNumForIncomingValue(PN->getNumIncomingValues()-1))); + } + + // Remember that this phi makes the value alive in this block. + SSAUpdate.AddAvailableValue(ExitBB, PN); + } + + // Rewrite all uses outside the loop in terms of the new PHIs we just + // inserted. + for (unsigned i = 0, e = UsesToRewrite.size(); i != e; ++i) { + // If this use is in an exit block, rewrite to use the newly inserted PHI. + // This is required for correctness because SSAUpdate doesn't handle uses in + // the same block. It assumes the PHI we inserted is at the end of the + // block. + Instruction *User = cast(UsesToRewrite[i]->getUser()); + BasicBlock *UserBB = User->getParent(); + if (PHINode *PN = dyn_cast(User)) + UserBB = PN->getIncomingBlock(*UsesToRewrite[i]); + + if (isa(UserBB->begin()) && + isExitBlock(UserBB, ExitBlocks)) { + UsesToRewrite[i]->set(UserBB->begin()); + continue; + } + + // Otherwise, do full PHI insertion. + SSAUpdate.RewriteUse(*UsesToRewrite[i]); + } + + return true; +} + diff --git a/libclamav/c++/llvm/lib/Transforms/Utils/Local.cpp b/libclamav/c++/llvm/lib/Transforms/Utils/Local.cpp new file mode 100644 index 000000000..aef0f5f03 --- /dev/null +++ b/libclamav/c++/llvm/lib/Transforms/Utils/Local.cpp @@ -0,0 +1,605 @@ +//===-- Local.cpp - Functions to perform local transformations ------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This family of functions perform various local transformations to the +// program. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Transforms/Utils/Local.h" +#include "llvm/Constants.h" +#include "llvm/GlobalAlias.h" +#include "llvm/GlobalVariable.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Instructions.h" +#include "llvm/Intrinsics.h" +#include "llvm/IntrinsicInst.h" +#include "llvm/LLVMContext.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/Analysis/ConstantFolding.h" +#include "llvm/Analysis/DebugInfo.h" +#include "llvm/Analysis/InstructionSimplify.h" +#include "llvm/Analysis/ProfileInfo.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Support/CFG.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/GetElementPtrTypeIterator.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +//===----------------------------------------------------------------------===// +// Local analysis. +// + +/// isSafeToLoadUnconditionally - Return true if we know that executing a load +/// from this value cannot trap. If it is not obviously safe to load from the +/// specified pointer, we do a quick local scan of the basic block containing +/// ScanFrom, to determine if the address is already accessed. +bool llvm::isSafeToLoadUnconditionally(Value *V, Instruction *ScanFrom) { + // If it is an alloca it is always safe to load from. + if (isa(V)) return true; + + // If it is a global variable it is mostly safe to load from. + if (const GlobalValue *GV = dyn_cast(V)) + // Don't try to evaluate aliases. External weak GV can be null. + return !isa(GV) && !GV->hasExternalWeakLinkage(); + + // Otherwise, be a little bit agressive by scanning the local block where we + // want to check to see if the pointer is already being loaded or stored + // from/to. If so, the previous load or store would have already trapped, + // so there is no harm doing an extra load (also, CSE will later eliminate + // the load entirely). + BasicBlock::iterator BBI = ScanFrom, E = ScanFrom->getParent()->begin(); + + while (BBI != E) { + --BBI; + + // If we see a free or a call which may write to memory (i.e. which might do + // a free) the pointer could be marked invalid. + if (isa(BBI) && BBI->mayWriteToMemory() && + !isa(BBI)) + return false; + + if (LoadInst *LI = dyn_cast(BBI)) { + if (LI->getOperand(0) == V) return true; + } else if (StoreInst *SI = dyn_cast(BBI)) { + if (SI->getOperand(1) == V) return true; + } + } + return false; +} + + +//===----------------------------------------------------------------------===// +// Local constant propagation. +// + +// ConstantFoldTerminator - If a terminator instruction is predicated on a +// constant value, convert it into an unconditional branch to the constant +// destination. +// +bool llvm::ConstantFoldTerminator(BasicBlock *BB) { + TerminatorInst *T = BB->getTerminator(); + + // Branch - See if we are conditional jumping on constant + if (BranchInst *BI = dyn_cast(T)) { + if (BI->isUnconditional()) return false; // Can't optimize uncond branch + BasicBlock *Dest1 = BI->getSuccessor(0); + BasicBlock *Dest2 = BI->getSuccessor(1); + + if (ConstantInt *Cond = dyn_cast(BI->getCondition())) { + // Are we branching on constant? + // YES. Change to unconditional branch... + BasicBlock *Destination = Cond->getZExtValue() ? Dest1 : Dest2; + BasicBlock *OldDest = Cond->getZExtValue() ? Dest2 : Dest1; + + //cerr << "Function: " << T->getParent()->getParent() + // << "\nRemoving branch from " << T->getParent() + // << "\n\nTo: " << OldDest << endl; + + // Let the basic block know that we are letting go of it. Based on this, + // it will adjust it's PHI nodes. + assert(BI->getParent() && "Terminator not inserted in block!"); + OldDest->removePredecessor(BI->getParent()); + + // Set the unconditional destination, and change the insn to be an + // unconditional branch. + BI->setUnconditionalDest(Destination); + return true; + } + + if (Dest2 == Dest1) { // Conditional branch to same location? + // This branch matches something like this: + // br bool %cond, label %Dest, label %Dest + // and changes it into: br label %Dest + + // Let the basic block know that we are letting go of one copy of it. + assert(BI->getParent() && "Terminator not inserted in block!"); + Dest1->removePredecessor(BI->getParent()); + + // Change a conditional branch to unconditional. + BI->setUnconditionalDest(Dest1); + return true; + } + return false; + } + + if (SwitchInst *SI = dyn_cast(T)) { + // If we are switching on a constant, we can convert the switch into a + // single branch instruction! + ConstantInt *CI = dyn_cast(SI->getCondition()); + BasicBlock *TheOnlyDest = SI->getSuccessor(0); // The default dest + BasicBlock *DefaultDest = TheOnlyDest; + assert(TheOnlyDest == SI->getDefaultDest() && + "Default destination is not successor #0?"); + + // Figure out which case it goes to. + for (unsigned i = 1, e = SI->getNumSuccessors(); i != e; ++i) { + // Found case matching a constant operand? + if (SI->getSuccessorValue(i) == CI) { + TheOnlyDest = SI->getSuccessor(i); + break; + } + + // Check to see if this branch is going to the same place as the default + // dest. If so, eliminate it as an explicit compare. + if (SI->getSuccessor(i) == DefaultDest) { + // Remove this entry. + DefaultDest->removePredecessor(SI->getParent()); + SI->removeCase(i); + --i; --e; // Don't skip an entry... + continue; + } + + // Otherwise, check to see if the switch only branches to one destination. + // We do this by reseting "TheOnlyDest" to null when we find two non-equal + // destinations. + if (SI->getSuccessor(i) != TheOnlyDest) TheOnlyDest = 0; + } + + if (CI && !TheOnlyDest) { + // Branching on a constant, but not any of the cases, go to the default + // successor. + TheOnlyDest = SI->getDefaultDest(); + } + + // If we found a single destination that we can fold the switch into, do so + // now. + if (TheOnlyDest) { + // Insert the new branch. + BranchInst::Create(TheOnlyDest, SI); + BasicBlock *BB = SI->getParent(); + + // Remove entries from PHI nodes which we no longer branch to... + for (unsigned i = 0, e = SI->getNumSuccessors(); i != e; ++i) { + // Found case matching a constant operand? + BasicBlock *Succ = SI->getSuccessor(i); + if (Succ == TheOnlyDest) + TheOnlyDest = 0; // Don't modify the first branch to TheOnlyDest + else + Succ->removePredecessor(BB); + } + + // Delete the old switch. + BB->getInstList().erase(SI); + return true; + } + + if (SI->getNumSuccessors() == 2) { + // Otherwise, we can fold this switch into a conditional branch + // instruction if it has only one non-default destination. + Value *Cond = new ICmpInst(SI, ICmpInst::ICMP_EQ, SI->getCondition(), + SI->getSuccessorValue(1), "cond"); + // Insert the new branch. + BranchInst::Create(SI->getSuccessor(1), SI->getSuccessor(0), Cond, SI); + + // Delete the old switch. + SI->eraseFromParent(); + return true; + } + return false; + } + + if (IndirectBrInst *IBI = dyn_cast(T)) { + // indirectbr blockaddress(@F, @BB) -> br label @BB + if (BlockAddress *BA = + dyn_cast(IBI->getAddress()->stripPointerCasts())) { + BasicBlock *TheOnlyDest = BA->getBasicBlock(); + // Insert the new branch. + BranchInst::Create(TheOnlyDest, IBI); + + for (unsigned i = 0, e = IBI->getNumDestinations(); i != e; ++i) { + if (IBI->getDestination(i) == TheOnlyDest) + TheOnlyDest = 0; + else + IBI->getDestination(i)->removePredecessor(IBI->getParent()); + } + IBI->eraseFromParent(); + + // If we didn't find our destination in the IBI successor list, then we + // have undefined behavior. Replace the unconditional branch with an + // 'unreachable' instruction. + if (TheOnlyDest) { + BB->getTerminator()->eraseFromParent(); + new UnreachableInst(BB->getContext(), BB); + } + + return true; + } + } + + return false; +} + + +//===----------------------------------------------------------------------===// +// Local dead code elimination. +// + +/// isInstructionTriviallyDead - Return true if the result produced by the +/// instruction is not used, and the instruction has no side effects. +/// +bool llvm::isInstructionTriviallyDead(Instruction *I) { + if (!I->use_empty() || isa(I)) return false; + + // We don't want debug info removed by anything this general. + if (isa(I)) return false; + + // Likewise for memory use markers. + if (isa(I)) return false; + + if (!I->mayHaveSideEffects()) return true; + + // Special case intrinsics that "may have side effects" but can be deleted + // when dead. + if (IntrinsicInst *II = dyn_cast(I)) + // Safe to delete llvm.stacksave if dead. + if (II->getIntrinsicID() == Intrinsic::stacksave) + return true; + return false; +} + +/// RecursivelyDeleteTriviallyDeadInstructions - If the specified value is a +/// trivially dead instruction, delete it. If that makes any of its operands +/// trivially dead, delete them too, recursively. +void llvm::RecursivelyDeleteTriviallyDeadInstructions(Value *V) { + Instruction *I = dyn_cast(V); + if (!I || !I->use_empty() || !isInstructionTriviallyDead(I)) + return; + + SmallVector DeadInsts; + DeadInsts.push_back(I); + + while (!DeadInsts.empty()) { + I = DeadInsts.pop_back_val(); + + // Null out all of the instruction's operands to see if any operand becomes + // dead as we go. + for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i) { + Value *OpV = I->getOperand(i); + I->setOperand(i, 0); + + if (!OpV->use_empty()) continue; + + // If the operand is an instruction that became dead as we nulled out the + // operand, and if it is 'trivially' dead, delete it in a future loop + // iteration. + if (Instruction *OpI = dyn_cast(OpV)) + if (isInstructionTriviallyDead(OpI)) + DeadInsts.push_back(OpI); + } + + I->eraseFromParent(); + } +} + +/// RecursivelyDeleteDeadPHINode - If the specified value is an effectively +/// dead PHI node, due to being a def-use chain of single-use nodes that +/// either forms a cycle or is terminated by a trivially dead instruction, +/// delete it. If that makes any of its operands trivially dead, delete them +/// too, recursively. +void +llvm::RecursivelyDeleteDeadPHINode(PHINode *PN) { + // We can remove a PHI if it is on a cycle in the def-use graph + // where each node in the cycle has degree one, i.e. only one use, + // and is an instruction with no side effects. + if (!PN->hasOneUse()) + return; + + SmallPtrSet PHIs; + PHIs.insert(PN); + for (Instruction *J = cast(*PN->use_begin()); + J->hasOneUse() && !J->mayHaveSideEffects(); + J = cast(*J->use_begin())) + // If we find a PHI more than once, we're on a cycle that + // won't prove fruitful. + if (PHINode *JP = dyn_cast(J)) + if (!PHIs.insert(cast(JP))) { + // Break the cycle and delete the PHI and its operands. + JP->replaceAllUsesWith(UndefValue::get(JP->getType())); + RecursivelyDeleteTriviallyDeadInstructions(JP); + break; + } +} + +//===----------------------------------------------------------------------===// +// Control Flow Graph Restructuring. +// + + +/// RemovePredecessorAndSimplify - Like BasicBlock::removePredecessor, this +/// method is called when we're about to delete Pred as a predecessor of BB. If +/// BB contains any PHI nodes, this drops the entries in the PHI nodes for Pred. +/// +/// Unlike the removePredecessor method, this attempts to simplify uses of PHI +/// nodes that collapse into identity values. For example, if we have: +/// x = phi(1, 0, 0, 0) +/// y = and x, z +/// +/// .. and delete the predecessor corresponding to the '1', this will attempt to +/// recursively fold the and to 0. +void llvm::RemovePredecessorAndSimplify(BasicBlock *BB, BasicBlock *Pred, + TargetData *TD) { + // This only adjusts blocks with PHI nodes. + if (!isa(BB->begin())) + return; + + // Remove the entries for Pred from the PHI nodes in BB, but do not simplify + // them down. This will leave us with single entry phi nodes and other phis + // that can be removed. + BB->removePredecessor(Pred, true); + + WeakVH PhiIt = &BB->front(); + while (PHINode *PN = dyn_cast(PhiIt)) { + PhiIt = &*++BasicBlock::iterator(cast(PhiIt)); + + Value *PNV = PN->hasConstantValue(); + if (PNV == 0) continue; + + // If we're able to simplify the phi to a single value, substitute the new + // value into all of its uses. + assert(PNV != PN && "hasConstantValue broken"); + + ReplaceAndSimplifyAllUses(PN, PNV, TD); + + // If recursive simplification ended up deleting the next PHI node we would + // iterate to, then our iterator is invalid, restart scanning from the top + // of the block. + if (PhiIt == 0) PhiIt = &BB->front(); + } +} + + +/// MergeBasicBlockIntoOnlyPred - DestBB is a block with one predecessor and its +/// predecessor is known to have one successor (DestBB!). Eliminate the edge +/// between them, moving the instructions in the predecessor into DestBB and +/// deleting the predecessor block. +/// +void llvm::MergeBasicBlockIntoOnlyPred(BasicBlock *DestBB, Pass *P) { + // If BB has single-entry PHI nodes, fold them. + while (PHINode *PN = dyn_cast(DestBB->begin())) { + Value *NewVal = PN->getIncomingValue(0); + // Replace self referencing PHI with undef, it must be dead. + if (NewVal == PN) NewVal = UndefValue::get(PN->getType()); + PN->replaceAllUsesWith(NewVal); + PN->eraseFromParent(); + } + + BasicBlock *PredBB = DestBB->getSinglePredecessor(); + assert(PredBB && "Block doesn't have a single predecessor!"); + + // Splice all the instructions from PredBB to DestBB. + PredBB->getTerminator()->eraseFromParent(); + DestBB->getInstList().splice(DestBB->begin(), PredBB->getInstList()); + + // Anything that branched to PredBB now branches to DestBB. + PredBB->replaceAllUsesWith(DestBB); + + if (P) { + ProfileInfo *PI = P->getAnalysisIfAvailable(); + if (PI) { + PI->replaceAllUses(PredBB, DestBB); + PI->removeEdge(ProfileInfo::getEdge(PredBB, DestBB)); + } + } + // Nuke BB. + PredBB->eraseFromParent(); +} + +/// CanPropagatePredecessorsForPHIs - Return true if we can fold BB, an +/// almost-empty BB ending in an unconditional branch to Succ, into succ. +/// +/// Assumption: Succ is the single successor for BB. +/// +static bool CanPropagatePredecessorsForPHIs(BasicBlock *BB, BasicBlock *Succ) { + assert(*succ_begin(BB) == Succ && "Succ is not successor of BB!"); + + DEBUG(errs() << "Looking to fold " << BB->getName() << " into " + << Succ->getName() << "\n"); + // Shortcut, if there is only a single predecessor it must be BB and merging + // is always safe + if (Succ->getSinglePredecessor()) return true; + + // Make a list of the predecessors of BB + typedef SmallPtrSet BlockSet; + BlockSet BBPreds(pred_begin(BB), pred_end(BB)); + + // Use that list to make another list of common predecessors of BB and Succ + BlockSet CommonPreds; + for (pred_iterator PI = pred_begin(Succ), PE = pred_end(Succ); + PI != PE; ++PI) + if (BBPreds.count(*PI)) + CommonPreds.insert(*PI); + + // Shortcut, if there are no common predecessors, merging is always safe + if (CommonPreds.empty()) + return true; + + // Look at all the phi nodes in Succ, to see if they present a conflict when + // merging these blocks + for (BasicBlock::iterator I = Succ->begin(); isa(I); ++I) { + PHINode *PN = cast(I); + + // If the incoming value from BB is again a PHINode in + // BB which has the same incoming value for *PI as PN does, we can + // merge the phi nodes and then the blocks can still be merged + PHINode *BBPN = dyn_cast(PN->getIncomingValueForBlock(BB)); + if (BBPN && BBPN->getParent() == BB) { + for (BlockSet::iterator PI = CommonPreds.begin(), PE = CommonPreds.end(); + PI != PE; PI++) { + if (BBPN->getIncomingValueForBlock(*PI) + != PN->getIncomingValueForBlock(*PI)) { + DEBUG(errs() << "Can't fold, phi node " << PN->getName() << " in " + << Succ->getName() << " is conflicting with " + << BBPN->getName() << " with regard to common predecessor " + << (*PI)->getName() << "\n"); + return false; + } + } + } else { + Value* Val = PN->getIncomingValueForBlock(BB); + for (BlockSet::iterator PI = CommonPreds.begin(), PE = CommonPreds.end(); + PI != PE; PI++) { + // See if the incoming value for the common predecessor is equal to the + // one for BB, in which case this phi node will not prevent the merging + // of the block. + if (Val != PN->getIncomingValueForBlock(*PI)) { + DEBUG(errs() << "Can't fold, phi node " << PN->getName() << " in " + << Succ->getName() << " is conflicting with regard to common " + << "predecessor " << (*PI)->getName() << "\n"); + return false; + } + } + } + } + + return true; +} + +/// TryToSimplifyUncondBranchFromEmptyBlock - BB is known to contain an +/// unconditional branch, and contains no instructions other than PHI nodes, +/// potential debug intrinsics and the branch. If possible, eliminate BB by +/// rewriting all the predecessors to branch to the successor block and return +/// true. If we can't transform, return false. +bool llvm::TryToSimplifyUncondBranchFromEmptyBlock(BasicBlock *BB) { + // We can't eliminate infinite loops. + BasicBlock *Succ = cast(BB->getTerminator())->getSuccessor(0); + if (BB == Succ) return false; + + // Check to see if merging these blocks would cause conflicts for any of the + // phi nodes in BB or Succ. If not, we can safely merge. + if (!CanPropagatePredecessorsForPHIs(BB, Succ)) return false; + + // Check for cases where Succ has multiple predecessors and a PHI node in BB + // has uses which will not disappear when the PHI nodes are merged. It is + // possible to handle such cases, but difficult: it requires checking whether + // BB dominates Succ, which is non-trivial to calculate in the case where + // Succ has multiple predecessors. Also, it requires checking whether + // constructing the necessary self-referential PHI node doesn't intoduce any + // conflicts; this isn't too difficult, but the previous code for doing this + // was incorrect. + // + // Note that if this check finds a live use, BB dominates Succ, so BB is + // something like a loop pre-header (or rarely, a part of an irreducible CFG); + // folding the branch isn't profitable in that case anyway. + if (!Succ->getSinglePredecessor()) { + BasicBlock::iterator BBI = BB->begin(); + while (isa(*BBI)) { + for (Value::use_iterator UI = BBI->use_begin(), E = BBI->use_end(); + UI != E; ++UI) { + if (PHINode* PN = dyn_cast(*UI)) { + if (PN->getIncomingBlock(UI) != BB) + return false; + } else { + return false; + } + } + ++BBI; + } + } + + DEBUG(errs() << "Killing Trivial BB: \n" << *BB); + + if (isa(Succ->begin())) { + // If there is more than one pred of succ, and there are PHI nodes in + // the successor, then we need to add incoming edges for the PHI nodes + // + const SmallVector BBPreds(pred_begin(BB), pred_end(BB)); + + // Loop over all of the PHI nodes in the successor of BB. + for (BasicBlock::iterator I = Succ->begin(); isa(I); ++I) { + PHINode *PN = cast(I); + Value *OldVal = PN->removeIncomingValue(BB, false); + assert(OldVal && "No entry in PHI for Pred BB!"); + + // If this incoming value is one of the PHI nodes in BB, the new entries + // in the PHI node are the entries from the old PHI. + if (isa(OldVal) && cast(OldVal)->getParent() == BB) { + PHINode *OldValPN = cast(OldVal); + for (unsigned i = 0, e = OldValPN->getNumIncomingValues(); i != e; ++i) + // Note that, since we are merging phi nodes and BB and Succ might + // have common predecessors, we could end up with a phi node with + // identical incoming branches. This will be cleaned up later (and + // will trigger asserts if we try to clean it up now, without also + // simplifying the corresponding conditional branch). + PN->addIncoming(OldValPN->getIncomingValue(i), + OldValPN->getIncomingBlock(i)); + } else { + // Add an incoming value for each of the new incoming values. + for (unsigned i = 0, e = BBPreds.size(); i != e; ++i) + PN->addIncoming(OldVal, BBPreds[i]); + } + } + } + + while (PHINode *PN = dyn_cast(&BB->front())) { + if (Succ->getSinglePredecessor()) { + // BB is the only predecessor of Succ, so Succ will end up with exactly + // the same predecessors BB had. + Succ->getInstList().splice(Succ->begin(), + BB->getInstList(), BB->begin()); + } else { + // We explicitly check for such uses in CanPropagatePredecessorsForPHIs. + assert(PN->use_empty() && "There shouldn't be any uses here!"); + PN->eraseFromParent(); + } + } + + // Everything that jumped to BB now goes to Succ. + BB->replaceAllUsesWith(Succ); + if (!Succ->hasName()) Succ->takeName(BB); + BB->eraseFromParent(); // Delete the old basic block. + return true; +} + + + +/// OnlyUsedByDbgIntrinsics - Return true if the instruction I is only used +/// by DbgIntrinsics. If DbgInUses is specified then the vector is filled +/// with the DbgInfoIntrinsic that use the instruction I. +bool llvm::OnlyUsedByDbgInfoIntrinsics(Instruction *I, + SmallVectorImpl *DbgInUses) { + if (DbgInUses) + DbgInUses->clear(); + + for (Value::use_iterator UI = I->use_begin(), UE = I->use_end(); UI != UE; + ++UI) { + if (DbgInfoIntrinsic *DI = dyn_cast(*UI)) { + if (DbgInUses) + DbgInUses->push_back(DI); + } else { + if (DbgInUses) + DbgInUses->clear(); + return false; + } + } + return true; +} + diff --git a/libclamav/c++/llvm/lib/Transforms/Utils/LoopSimplify.cpp b/libclamav/c++/llvm/lib/Transforms/Utils/LoopSimplify.cpp new file mode 100644 index 000000000..690972dc5 --- /dev/null +++ b/libclamav/c++/llvm/lib/Transforms/Utils/LoopSimplify.cpp @@ -0,0 +1,694 @@ +//===- LoopSimplify.cpp - Loop Canonicalization Pass ----------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This pass performs several transformations to transform natural loops into a +// simpler form, which makes subsequent analyses and transformations simpler and +// more effective. +// +// Loop pre-header insertion guarantees that there is a single, non-critical +// entry edge from outside of the loop to the loop header. This simplifies a +// number of analyses and transformations, such as LICM. +// +// Loop exit-block insertion guarantees that all exit blocks from the loop +// (blocks which are outside of the loop that have predecessors inside of the +// loop) only have predecessors from inside of the loop (and are thus dominated +// by the loop header). This simplifies transformations such as store-sinking +// that are built into LICM. +// +// This pass also guarantees that loops will have exactly one backedge. +// +// Indirectbr instructions introduce several complications. If the loop +// contains or is entered by an indirectbr instruction, it may not be possible +// to transform the loop and make these guarantees. Client code should check +// that these conditions are true before relying on them. +// +// Note that the simplifycfg pass will clean up blocks which are split out but +// end up being unnecessary, so usage of this pass should not pessimize +// generated code. +// +// This pass obviously modifies the CFG, but updates loop information and +// dominator information. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "loopsimplify" +#include "llvm/Transforms/Scalar.h" +#include "llvm/Constants.h" +#include "llvm/Instructions.h" +#include "llvm/Function.h" +#include "llvm/LLVMContext.h" +#include "llvm/Type.h" +#include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/Analysis/Dominators.h" +#include "llvm/Analysis/LoopPass.h" +#include "llvm/Analysis/ScalarEvolution.h" +#include "llvm/Transforms/Utils/BasicBlockUtils.h" +#include "llvm/Transforms/Utils/Local.h" +#include "llvm/Support/CFG.h" +#include "llvm/ADT/SetOperations.h" +#include "llvm/ADT/SetVector.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/ADT/DepthFirstIterator.h" +using namespace llvm; + +STATISTIC(NumInserted, "Number of pre-header or exit blocks inserted"); +STATISTIC(NumNested , "Number of nested loops split out"); + +namespace { + struct LoopSimplify : public LoopPass { + static char ID; // Pass identification, replacement for typeid + LoopSimplify() : LoopPass(&ID) {} + + // AA - If we have an alias analysis object to update, this is it, otherwise + // this is null. + AliasAnalysis *AA; + LoopInfo *LI; + DominatorTree *DT; + Loop *L; + virtual bool runOnLoop(Loop *L, LPPassManager &LPM); + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + // We need loop information to identify the loops... + AU.addRequiredTransitive(); + AU.addRequiredTransitive(); + + AU.addPreserved(); + AU.addPreserved(); + AU.addPreserved(); + AU.addPreserved(); + AU.addPreserved(); + AU.addPreservedID(BreakCriticalEdgesID); // No critical edges added. + } + + /// verifyAnalysis() - Verify LoopSimplifyForm's guarantees. + void verifyAnalysis() const; + + private: + bool ProcessLoop(Loop *L, LPPassManager &LPM); + BasicBlock *RewriteLoopExitBlock(Loop *L, BasicBlock *Exit); + BasicBlock *InsertPreheaderForLoop(Loop *L); + Loop *SeparateNestedLoop(Loop *L, LPPassManager &LPM); + BasicBlock *InsertUniqueBackedgeBlock(Loop *L, BasicBlock *Preheader); + void PlaceSplitBlockCarefully(BasicBlock *NewBB, + SmallVectorImpl &SplitPreds, + Loop *L); + }; +} + +char LoopSimplify::ID = 0; +static RegisterPass +X("loopsimplify", "Canonicalize natural loops", true); + +// Publically exposed interface to pass... +const PassInfo *const llvm::LoopSimplifyID = &X; +Pass *llvm::createLoopSimplifyPass() { return new LoopSimplify(); } + +/// runOnFunction - Run down all loops in the CFG (recursively, but we could do +/// it in any convenient order) inserting preheaders... +/// +bool LoopSimplify::runOnLoop(Loop *l, LPPassManager &LPM) { + L = l; + bool Changed = false; + LI = &getAnalysis(); + AA = getAnalysisIfAvailable(); + DT = &getAnalysis(); + + Changed |= ProcessLoop(L, LPM); + + return Changed; +} + +/// ProcessLoop - Walk the loop structure in depth first order, ensuring that +/// all loops have preheaders. +/// +bool LoopSimplify::ProcessLoop(Loop *L, LPPassManager &LPM) { + bool Changed = false; +ReprocessLoop: + + // Check to see that no blocks (other than the header) in this loop that has + // predecessors that are not in the loop. This is not valid for natural + // loops, but can occur if the blocks are unreachable. Since they are + // unreachable we can just shamelessly delete those CFG edges! + for (Loop::block_iterator BB = L->block_begin(), E = L->block_end(); + BB != E; ++BB) { + if (*BB == L->getHeader()) continue; + + SmallPtrSet BadPreds; + for (pred_iterator PI = pred_begin(*BB), PE = pred_end(*BB); PI != PE; ++PI) + if (!L->contains(*PI)) + BadPreds.insert(*PI); + + // Delete each unique out-of-loop (and thus dead) predecessor. + for (SmallPtrSet::iterator I = BadPreds.begin(), + E = BadPreds.end(); I != E; ++I) { + // Inform each successor of each dead pred. + for (succ_iterator SI = succ_begin(*I), SE = succ_end(*I); SI != SE; ++SI) + (*SI)->removePredecessor(*I); + // Zap the dead pred's terminator and replace it with unreachable. + TerminatorInst *TI = (*I)->getTerminator(); + TI->replaceAllUsesWith(UndefValue::get(TI->getType())); + (*I)->getTerminator()->eraseFromParent(); + new UnreachableInst((*I)->getContext(), *I); + Changed = true; + } + } + + // Does the loop already have a preheader? If so, don't insert one. + BasicBlock *Preheader = L->getLoopPreheader(); + if (!Preheader) { + Preheader = InsertPreheaderForLoop(L); + if (Preheader) { + NumInserted++; + Changed = true; + } + } + + // Next, check to make sure that all exit nodes of the loop only have + // predecessors that are inside of the loop. This check guarantees that the + // loop preheader/header will dominate the exit blocks. If the exit block has + // predecessors from outside of the loop, split the edge now. + SmallVector ExitBlocks; + L->getExitBlocks(ExitBlocks); + + SetVector ExitBlockSet(ExitBlocks.begin(), ExitBlocks.end()); + for (SetVector::iterator I = ExitBlockSet.begin(), + E = ExitBlockSet.end(); I != E; ++I) { + BasicBlock *ExitBlock = *I; + for (pred_iterator PI = pred_begin(ExitBlock), PE = pred_end(ExitBlock); + PI != PE; ++PI) + // Must be exactly this loop: no subloops, parent loops, or non-loop preds + // allowed. + if (!L->contains(*PI)) { + if (RewriteLoopExitBlock(L, ExitBlock)) { + NumInserted++; + Changed = true; + } + break; + } + } + + // If the header has more than two predecessors at this point (from the + // preheader and from multiple backedges), we must adjust the loop. + BasicBlock *LoopLatch = L->getLoopLatch(); + if (!LoopLatch) { + // If this is really a nested loop, rip it out into a child loop. Don't do + // this for loops with a giant number of backedges, just factor them into a + // common backedge instead. + if (L->getNumBackEdges() < 8) { + if (SeparateNestedLoop(L, LPM)) { + ++NumNested; + // This is a big restructuring change, reprocess the whole loop. + Changed = true; + // GCC doesn't tail recursion eliminate this. + goto ReprocessLoop; + } + } + + // If we either couldn't, or didn't want to, identify nesting of the loops, + // insert a new block that all backedges target, then make it jump to the + // loop header. + LoopLatch = InsertUniqueBackedgeBlock(L, Preheader); + if (LoopLatch) { + NumInserted++; + Changed = true; + } + } + + // Scan over the PHI nodes in the loop header. Since they now have only two + // incoming values (the loop is canonicalized), we may have simplified the PHI + // down to 'X = phi [X, Y]', which should be replaced with 'Y'. + PHINode *PN; + for (BasicBlock::iterator I = L->getHeader()->begin(); + (PN = dyn_cast(I++)); ) + if (Value *V = PN->hasConstantValue(DT)) { + if (AA) AA->deleteValue(PN); + PN->replaceAllUsesWith(V); + PN->eraseFromParent(); + } + + // If this loop has muliple exits and the exits all go to the same + // block, attempt to merge the exits. This helps several passes, such + // as LoopRotation, which do not support loops with multiple exits. + // SimplifyCFG also does this (and this code uses the same utility + // function), however this code is loop-aware, where SimplifyCFG is + // not. That gives it the advantage of being able to hoist + // loop-invariant instructions out of the way to open up more + // opportunities, and the disadvantage of having the responsibility + // to preserve dominator information. + bool UniqueExit = true; + if (!ExitBlocks.empty()) + for (unsigned i = 1, e = ExitBlocks.size(); i != e; ++i) + if (ExitBlocks[i] != ExitBlocks[0]) { + UniqueExit = false; + break; + } + if (UniqueExit) { + SmallVector ExitingBlocks; + L->getExitingBlocks(ExitingBlocks); + for (unsigned i = 0, e = ExitingBlocks.size(); i != e; ++i) { + BasicBlock *ExitingBlock = ExitingBlocks[i]; + if (!ExitingBlock->getSinglePredecessor()) continue; + BranchInst *BI = dyn_cast(ExitingBlock->getTerminator()); + if (!BI || !BI->isConditional()) continue; + CmpInst *CI = dyn_cast(BI->getCondition()); + if (!CI || CI->getParent() != ExitingBlock) continue; + + // Attempt to hoist out all instructions except for the + // comparison and the branch. + bool AllInvariant = true; + for (BasicBlock::iterator I = ExitingBlock->begin(); &*I != BI; ) { + Instruction *Inst = I++; + if (Inst == CI) + continue; + if (!L->makeLoopInvariant(Inst, Changed, + Preheader ? Preheader->getTerminator() : 0)) { + AllInvariant = false; + break; + } + } + if (!AllInvariant) continue; + + // The block has now been cleared of all instructions except for + // a comparison and a conditional branch. SimplifyCFG may be able + // to fold it now. + if (!FoldBranchToCommonDest(BI)) continue; + + // Success. The block is now dead, so remove it from the loop, + // update the dominator tree and dominance frontier, and delete it. + assert(pred_begin(ExitingBlock) == pred_end(ExitingBlock)); + Changed = true; + LI->removeBlock(ExitingBlock); + + DominanceFrontier *DF = getAnalysisIfAvailable(); + DomTreeNode *Node = DT->getNode(ExitingBlock); + const std::vector *> &Children = + Node->getChildren(); + while (!Children.empty()) { + DomTreeNode *Child = Children.front(); + DT->changeImmediateDominator(Child, Node->getIDom()); + if (DF) DF->changeImmediateDominator(Child->getBlock(), + Node->getIDom()->getBlock(), + DT); + } + DT->eraseNode(ExitingBlock); + if (DF) DF->removeBlock(ExitingBlock); + + BI->getSuccessor(0)->removePredecessor(ExitingBlock); + BI->getSuccessor(1)->removePredecessor(ExitingBlock); + ExitingBlock->eraseFromParent(); + } + } + + // If there are duplicate phi nodes (for example, from loop rotation), + // get rid of them. + for (Loop::block_iterator BB = L->block_begin(), E = L->block_end(); + BB != E; ++BB) + EliminateDuplicatePHINodes(*BB); + + return Changed; +} + +/// InsertPreheaderForLoop - Once we discover that a loop doesn't have a +/// preheader, this method is called to insert one. This method has two phases: +/// preheader insertion and analysis updating. +/// +BasicBlock *LoopSimplify::InsertPreheaderForLoop(Loop *L) { + BasicBlock *Header = L->getHeader(); + + // Compute the set of predecessors of the loop that are not in the loop. + SmallVector OutsideBlocks; + for (pred_iterator PI = pred_begin(Header), PE = pred_end(Header); + PI != PE; ++PI) + if (!L->contains(*PI)) { // Coming in from outside the loop? + // If the loop is branched to from an indirect branch, we won't + // be able to fully transform the loop, because it prohibits + // edge splitting. + if (isa((*PI)->getTerminator())) return 0; + + // Keep track of it. + OutsideBlocks.push_back(*PI); + } + + // Split out the loop pre-header. + BasicBlock *NewBB = + SplitBlockPredecessors(Header, &OutsideBlocks[0], OutsideBlocks.size(), + ".preheader", this); + + // Make sure that NewBB is put someplace intelligent, which doesn't mess up + // code layout too horribly. + PlaceSplitBlockCarefully(NewBB, OutsideBlocks, L); + + return NewBB; +} + +/// RewriteLoopExitBlock - Ensure that the loop preheader dominates all exit +/// blocks. This method is used to split exit blocks that have predecessors +/// outside of the loop. +BasicBlock *LoopSimplify::RewriteLoopExitBlock(Loop *L, BasicBlock *Exit) { + SmallVector LoopBlocks; + for (pred_iterator I = pred_begin(Exit), E = pred_end(Exit); I != E; ++I) + if (L->contains(*I)) { + // Don't do this if the loop is exited via an indirect branch. + if (isa((*I)->getTerminator())) return 0; + + LoopBlocks.push_back(*I); + } + + assert(!LoopBlocks.empty() && "No edges coming in from outside the loop?"); + BasicBlock *NewBB = SplitBlockPredecessors(Exit, &LoopBlocks[0], + LoopBlocks.size(), ".loopexit", + this); + + return NewBB; +} + +/// AddBlockAndPredsToSet - Add the specified block, and all of its +/// predecessors, to the specified set, if it's not already in there. Stop +/// predecessor traversal when we reach StopBlock. +static void AddBlockAndPredsToSet(BasicBlock *InputBB, BasicBlock *StopBlock, + std::set &Blocks) { + std::vector WorkList; + WorkList.push_back(InputBB); + do { + BasicBlock *BB = WorkList.back(); WorkList.pop_back(); + if (Blocks.insert(BB).second && BB != StopBlock) + // If BB is not already processed and it is not a stop block then + // insert its predecessor in the work list + for (pred_iterator I = pred_begin(BB), E = pred_end(BB); I != E; ++I) { + BasicBlock *WBB = *I; + WorkList.push_back(WBB); + } + } while(!WorkList.empty()); +} + +/// FindPHIToPartitionLoops - The first part of loop-nestification is to find a +/// PHI node that tells us how to partition the loops. +static PHINode *FindPHIToPartitionLoops(Loop *L, DominatorTree *DT, + AliasAnalysis *AA) { + for (BasicBlock::iterator I = L->getHeader()->begin(); isa(I); ) { + PHINode *PN = cast(I); + ++I; + if (Value *V = PN->hasConstantValue(DT)) { + // This is a degenerate PHI already, don't modify it! + PN->replaceAllUsesWith(V); + if (AA) AA->deleteValue(PN); + PN->eraseFromParent(); + continue; + } + + // Scan this PHI node looking for a use of the PHI node by itself. + for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) + if (PN->getIncomingValue(i) == PN && + L->contains(PN->getIncomingBlock(i))) + // We found something tasty to remove. + return PN; + } + return 0; +} + +// PlaceSplitBlockCarefully - If the block isn't already, move the new block to +// right after some 'outside block' block. This prevents the preheader from +// being placed inside the loop body, e.g. when the loop hasn't been rotated. +void LoopSimplify::PlaceSplitBlockCarefully(BasicBlock *NewBB, + SmallVectorImpl &SplitPreds, + Loop *L) { + // Check to see if NewBB is already well placed. + Function::iterator BBI = NewBB; --BBI; + for (unsigned i = 0, e = SplitPreds.size(); i != e; ++i) { + if (&*BBI == SplitPreds[i]) + return; + } + + // If it isn't already after an outside block, move it after one. This is + // always good as it makes the uncond branch from the outside block into a + // fall-through. + + // Figure out *which* outside block to put this after. Prefer an outside + // block that neighbors a BB actually in the loop. + BasicBlock *FoundBB = 0; + for (unsigned i = 0, e = SplitPreds.size(); i != e; ++i) { + Function::iterator BBI = SplitPreds[i]; + if (++BBI != NewBB->getParent()->end() && + L->contains(BBI)) { + FoundBB = SplitPreds[i]; + break; + } + } + + // If our heuristic for a *good* bb to place this after doesn't find + // anything, just pick something. It's likely better than leaving it within + // the loop. + if (!FoundBB) + FoundBB = SplitPreds[0]; + NewBB->moveAfter(FoundBB); +} + + +/// SeparateNestedLoop - If this loop has multiple backedges, try to pull one of +/// them out into a nested loop. This is important for code that looks like +/// this: +/// +/// Loop: +/// ... +/// br cond, Loop, Next +/// ... +/// br cond2, Loop, Out +/// +/// To identify this common case, we look at the PHI nodes in the header of the +/// loop. PHI nodes with unchanging values on one backedge correspond to values +/// that change in the "outer" loop, but not in the "inner" loop. +/// +/// If we are able to separate out a loop, return the new outer loop that was +/// created. +/// +Loop *LoopSimplify::SeparateNestedLoop(Loop *L, LPPassManager &LPM) { + PHINode *PN = FindPHIToPartitionLoops(L, DT, AA); + if (PN == 0) return 0; // No known way to partition. + + // Pull out all predecessors that have varying values in the loop. This + // handles the case when a PHI node has multiple instances of itself as + // arguments. + SmallVector OuterLoopPreds; + for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) + if (PN->getIncomingValue(i) != PN || + !L->contains(PN->getIncomingBlock(i))) { + // We can't split indirectbr edges. + if (isa(PN->getIncomingBlock(i)->getTerminator())) + return 0; + + OuterLoopPreds.push_back(PN->getIncomingBlock(i)); + } + + BasicBlock *Header = L->getHeader(); + BasicBlock *NewBB = SplitBlockPredecessors(Header, &OuterLoopPreds[0], + OuterLoopPreds.size(), + ".outer", this); + + // Make sure that NewBB is put someplace intelligent, which doesn't mess up + // code layout too horribly. + PlaceSplitBlockCarefully(NewBB, OuterLoopPreds, L); + + // Create the new outer loop. + Loop *NewOuter = new Loop(); + + // Change the parent loop to use the outer loop as its child now. + if (Loop *Parent = L->getParentLoop()) + Parent->replaceChildLoopWith(L, NewOuter); + else + LI->changeTopLevelLoop(L, NewOuter); + + // L is now a subloop of our outer loop. + NewOuter->addChildLoop(L); + + // Add the new loop to the pass manager queue. + LPM.insertLoopIntoQueue(NewOuter); + + for (Loop::block_iterator I = L->block_begin(), E = L->block_end(); + I != E; ++I) + NewOuter->addBlockEntry(*I); + + // Now reset the header in L, which had been moved by + // SplitBlockPredecessors for the outer loop. + L->moveToHeader(Header); + + // Determine which blocks should stay in L and which should be moved out to + // the Outer loop now. + std::set BlocksInL; + for (pred_iterator PI = pred_begin(Header), E = pred_end(Header); PI!=E; ++PI) + if (DT->dominates(Header, *PI)) + AddBlockAndPredsToSet(*PI, Header, BlocksInL); + + + // Scan all of the loop children of L, moving them to OuterLoop if they are + // not part of the inner loop. + const std::vector &SubLoops = L->getSubLoops(); + for (size_t I = 0; I != SubLoops.size(); ) + if (BlocksInL.count(SubLoops[I]->getHeader())) + ++I; // Loop remains in L + else + NewOuter->addChildLoop(L->removeChildLoop(SubLoops.begin() + I)); + + // Now that we know which blocks are in L and which need to be moved to + // OuterLoop, move any blocks that need it. + for (unsigned i = 0; i != L->getBlocks().size(); ++i) { + BasicBlock *BB = L->getBlocks()[i]; + if (!BlocksInL.count(BB)) { + // Move this block to the parent, updating the exit blocks sets + L->removeBlockFromLoop(BB); + if ((*LI)[BB] == L) + LI->changeLoopFor(BB, NewOuter); + --i; + } + } + + return NewOuter; +} + + + +/// InsertUniqueBackedgeBlock - This method is called when the specified loop +/// has more than one backedge in it. If this occurs, revector all of these +/// backedges to target a new basic block and have that block branch to the loop +/// header. This ensures that loops have exactly one backedge. +/// +BasicBlock * +LoopSimplify::InsertUniqueBackedgeBlock(Loop *L, BasicBlock *Preheader) { + assert(L->getNumBackEdges() > 1 && "Must have > 1 backedge!"); + + // Get information about the loop + BasicBlock *Header = L->getHeader(); + Function *F = Header->getParent(); + + // Unique backedge insertion currently depends on having a preheader. + if (!Preheader) + return 0; + + // Figure out which basic blocks contain back-edges to the loop header. + std::vector BackedgeBlocks; + for (pred_iterator I = pred_begin(Header), E = pred_end(Header); I != E; ++I) + if (*I != Preheader) BackedgeBlocks.push_back(*I); + + // Create and insert the new backedge block... + BasicBlock *BEBlock = BasicBlock::Create(Header->getContext(), + Header->getName()+".backedge", F); + BranchInst *BETerminator = BranchInst::Create(Header, BEBlock); + + // Move the new backedge block to right after the last backedge block. + Function::iterator InsertPos = BackedgeBlocks.back(); ++InsertPos; + F->getBasicBlockList().splice(InsertPos, F->getBasicBlockList(), BEBlock); + + // Now that the block has been inserted into the function, create PHI nodes in + // the backedge block which correspond to any PHI nodes in the header block. + for (BasicBlock::iterator I = Header->begin(); isa(I); ++I) { + PHINode *PN = cast(I); + PHINode *NewPN = PHINode::Create(PN->getType(), PN->getName()+".be", + BETerminator); + NewPN->reserveOperandSpace(BackedgeBlocks.size()); + if (AA) AA->copyValue(PN, NewPN); + + // Loop over the PHI node, moving all entries except the one for the + // preheader over to the new PHI node. + unsigned PreheaderIdx = ~0U; + bool HasUniqueIncomingValue = true; + Value *UniqueValue = 0; + for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) { + BasicBlock *IBB = PN->getIncomingBlock(i); + Value *IV = PN->getIncomingValue(i); + if (IBB == Preheader) { + PreheaderIdx = i; + } else { + NewPN->addIncoming(IV, IBB); + if (HasUniqueIncomingValue) { + if (UniqueValue == 0) + UniqueValue = IV; + else if (UniqueValue != IV) + HasUniqueIncomingValue = false; + } + } + } + + // Delete all of the incoming values from the old PN except the preheader's + assert(PreheaderIdx != ~0U && "PHI has no preheader entry??"); + if (PreheaderIdx != 0) { + PN->setIncomingValue(0, PN->getIncomingValue(PreheaderIdx)); + PN->setIncomingBlock(0, PN->getIncomingBlock(PreheaderIdx)); + } + // Nuke all entries except the zero'th. + for (unsigned i = 0, e = PN->getNumIncomingValues()-1; i != e; ++i) + PN->removeIncomingValue(e-i, false); + + // Finally, add the newly constructed PHI node as the entry for the BEBlock. + PN->addIncoming(NewPN, BEBlock); + + // As an optimization, if all incoming values in the new PhiNode (which is a + // subset of the incoming values of the old PHI node) have the same value, + // eliminate the PHI Node. + if (HasUniqueIncomingValue) { + NewPN->replaceAllUsesWith(UniqueValue); + if (AA) AA->deleteValue(NewPN); + BEBlock->getInstList().erase(NewPN); + } + } + + // Now that all of the PHI nodes have been inserted and adjusted, modify the + // backedge blocks to just to the BEBlock instead of the header. + for (unsigned i = 0, e = BackedgeBlocks.size(); i != e; ++i) { + TerminatorInst *TI = BackedgeBlocks[i]->getTerminator(); + for (unsigned Op = 0, e = TI->getNumSuccessors(); Op != e; ++Op) + if (TI->getSuccessor(Op) == Header) + TI->setSuccessor(Op, BEBlock); + } + + //===--- Update all analyses which we must preserve now -----------------===// + + // Update Loop Information - we know that this block is now in the current + // loop and all parent loops. + L->addBasicBlockToLoop(BEBlock, LI->getBase()); + + // Update dominator information + DT->splitBlock(BEBlock); + if (DominanceFrontier *DF = getAnalysisIfAvailable()) + DF->splitBlock(BEBlock); + + return BEBlock; +} + +void LoopSimplify::verifyAnalysis() const { + // It used to be possible to just assert L->isLoopSimplifyForm(), however + // with the introduction of indirectbr, there are now cases where it's + // not possible to transform a loop as necessary. We can at least check + // that there is an indirectbr near any time there's trouble. + + // Indirectbr can interfere with preheader and unique backedge insertion. + if (!L->getLoopPreheader() || !L->getLoopLatch()) { + bool HasIndBrPred = false; + for (pred_iterator PI = pred_begin(L->getHeader()), + PE = pred_end(L->getHeader()); PI != PE; ++PI) + if (isa((*PI)->getTerminator())) { + HasIndBrPred = true; + break; + } + assert(HasIndBrPred && + "LoopSimplify has no excuse for missing loop header info!"); + } + + // Indirectbr can interfere with exit block canonicalization. + if (!L->hasDedicatedExits()) { + bool HasIndBrExiting = false; + SmallVector ExitingBlocks; + L->getExitingBlocks(ExitingBlocks); + for (unsigned i = 0, e = ExitingBlocks.size(); i != e; ++i) + if (isa((ExitingBlocks[i])->getTerminator())) { + HasIndBrExiting = true; + break; + } + assert(HasIndBrExiting && + "LoopSimplify has no excuse for missing exit block info!"); + } +} diff --git a/libclamav/c++/llvm/lib/Transforms/Utils/LoopUnroll.cpp b/libclamav/c++/llvm/lib/Transforms/Utils/LoopUnroll.cpp new file mode 100644 index 000000000..6232f3286 --- /dev/null +++ b/libclamav/c++/llvm/lib/Transforms/Utils/LoopUnroll.cpp @@ -0,0 +1,382 @@ +//===-- UnrollLoop.cpp - Loop unrolling utilities -------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements some loop unrolling utilities. It does not define any +// actual pass or policy, but provides a single function to perform loop +// unrolling. +// +// It works best when loops have been canonicalized by the -indvars pass, +// allowing it to determine the trip counts of loops easily. +// +// The process of unrolling can produce extraneous basic blocks linked with +// unconditional branches. This will be corrected in the future. +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "loop-unroll" +#include "llvm/Transforms/Utils/UnrollLoop.h" +#include "llvm/BasicBlock.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/Analysis/ConstantFolding.h" +#include "llvm/Analysis/LoopPass.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Transforms/Utils/BasicBlockUtils.h" +#include "llvm/Transforms/Utils/Cloning.h" +#include "llvm/Transforms/Utils/Local.h" +#include + +using namespace llvm; + +// TODO: Should these be here or in LoopUnroll? +STATISTIC(NumCompletelyUnrolled, "Number of loops completely unrolled"); +STATISTIC(NumUnrolled, "Number of loops unrolled (completely or otherwise)"); + +/// RemapInstruction - Convert the instruction operands from referencing the +/// current values into those specified by ValueMap. +static inline void RemapInstruction(Instruction *I, + DenseMap &ValueMap) { + for (unsigned op = 0, E = I->getNumOperands(); op != E; ++op) { + Value *Op = I->getOperand(op); + DenseMap::iterator It = ValueMap.find(Op); + if (It != ValueMap.end()) + I->setOperand(op, It->second); + } +} + +/// FoldBlockIntoPredecessor - Folds a basic block into its predecessor if it +/// only has one predecessor, and that predecessor only has one successor. +/// The LoopInfo Analysis that is passed will be kept consistent. +/// Returns the new combined block. +static BasicBlock *FoldBlockIntoPredecessor(BasicBlock *BB, LoopInfo* LI) { + // Merge basic blocks into their predecessor if there is only one distinct + // pred, and if there is only one distinct successor of the predecessor, and + // if there are no PHI nodes. + BasicBlock *OnlyPred = BB->getSinglePredecessor(); + if (!OnlyPred) return 0; + + if (OnlyPred->getTerminator()->getNumSuccessors() != 1) + return 0; + + DEBUG(errs() << "Merging: " << *BB << "into: " << *OnlyPred); + + // Resolve any PHI nodes at the start of the block. They are all + // guaranteed to have exactly one entry if they exist, unless there are + // multiple duplicate (but guaranteed to be equal) entries for the + // incoming edges. This occurs when there are multiple edges from + // OnlyPred to OnlySucc. + FoldSingleEntryPHINodes(BB); + + // Delete the unconditional branch from the predecessor... + OnlyPred->getInstList().pop_back(); + + // Move all definitions in the successor to the predecessor... + OnlyPred->getInstList().splice(OnlyPred->end(), BB->getInstList()); + + // Make all PHI nodes that referred to BB now refer to Pred as their + // source... + BB->replaceAllUsesWith(OnlyPred); + + std::string OldName = BB->getName(); + + // Erase basic block from the function... + LI->removeBlock(BB); + BB->eraseFromParent(); + + // Inherit predecessor's name if it exists... + if (!OldName.empty() && !OnlyPred->hasName()) + OnlyPred->setName(OldName); + + return OnlyPred; +} + +/// Unroll the given loop by Count. The loop must be in LCSSA form. Returns true +/// if unrolling was succesful, or false if the loop was unmodified. Unrolling +/// can only fail when the loop's latch block is not terminated by a conditional +/// branch instruction. However, if the trip count (and multiple) are not known, +/// loop unrolling will mostly produce more code that is no faster. +/// +/// The LoopInfo Analysis that is passed will be kept consistent. +/// +/// If a LoopPassManager is passed in, and the loop is fully removed, it will be +/// removed from the LoopPassManager as well. LPM can also be NULL. +bool llvm::UnrollLoop(Loop *L, unsigned Count, LoopInfo* LI, LPPassManager* LPM) { + assert(L->isLCSSAForm()); + + BasicBlock *Preheader = L->getLoopPreheader(); + if (!Preheader) { + DEBUG(errs() << " Can't unroll; loop preheader-insertion failed.\n"); + return false; + } + + BasicBlock *LatchBlock = L->getLoopLatch(); + if (!LatchBlock) { + DEBUG(errs() << " Can't unroll; loop exit-block-insertion failed.\n"); + return false; + } + + BasicBlock *Header = L->getHeader(); + BranchInst *BI = dyn_cast(LatchBlock->getTerminator()); + + if (!BI || BI->isUnconditional()) { + // The loop-rotate pass can be helpful to avoid this in many cases. + DEBUG(errs() << + " Can't unroll; loop not terminated by a conditional branch.\n"); + return false; + } + + // Find trip count + unsigned TripCount = L->getSmallConstantTripCount(); + // Find trip multiple if count is not available + unsigned TripMultiple = 1; + if (TripCount == 0) + TripMultiple = L->getSmallConstantTripMultiple(); + + if (TripCount != 0) + DEBUG(errs() << " Trip Count = " << TripCount << "\n"); + if (TripMultiple != 1) + DEBUG(errs() << " Trip Multiple = " << TripMultiple << "\n"); + + // Effectively "DCE" unrolled iterations that are beyond the tripcount + // and will never be executed. + if (TripCount != 0 && Count > TripCount) + Count = TripCount; + + assert(Count > 0); + assert(TripMultiple > 0); + assert(TripCount == 0 || TripCount % TripMultiple == 0); + + // Are we eliminating the loop control altogether? + bool CompletelyUnroll = Count == TripCount; + + // If we know the trip count, we know the multiple... + unsigned BreakoutTrip = 0; + if (TripCount != 0) { + BreakoutTrip = TripCount % Count; + TripMultiple = 0; + } else { + // Figure out what multiple to use. + BreakoutTrip = TripMultiple = + (unsigned)GreatestCommonDivisor64(Count, TripMultiple); + } + + if (CompletelyUnroll) { + DEBUG(errs() << "COMPLETELY UNROLLING loop %" << Header->getName() + << " with trip count " << TripCount << "!\n"); + } else { + DEBUG(errs() << "UNROLLING loop %" << Header->getName() + << " by " << Count); + if (TripMultiple == 0 || BreakoutTrip != TripMultiple) { + DEBUG(errs() << " with a breakout at trip " << BreakoutTrip); + } else if (TripMultiple != 1) { + DEBUG(errs() << " with " << TripMultiple << " trips per branch"); + } + DEBUG(errs() << "!\n"); + } + + std::vector LoopBlocks = L->getBlocks(); + + bool ContinueOnTrue = L->contains(BI->getSuccessor(0)); + BasicBlock *LoopExit = BI->getSuccessor(ContinueOnTrue); + + // For the first iteration of the loop, we should use the precloned values for + // PHI nodes. Insert associations now. + typedef DenseMap ValueMapTy; + ValueMapTy LastValueMap; + std::vector OrigPHINode; + for (BasicBlock::iterator I = Header->begin(); isa(I); ++I) { + PHINode *PN = cast(I); + OrigPHINode.push_back(PN); + if (Instruction *I = + dyn_cast(PN->getIncomingValueForBlock(LatchBlock))) + if (L->contains(I->getParent())) + LastValueMap[I] = I; + } + + std::vector Headers; + std::vector Latches; + Headers.push_back(Header); + Latches.push_back(LatchBlock); + + for (unsigned It = 1; It != Count; ++It) { + char SuffixBuffer[100]; + sprintf(SuffixBuffer, ".%d", It); + + std::vector NewBlocks; + + for (std::vector::iterator BB = LoopBlocks.begin(), + E = LoopBlocks.end(); BB != E; ++BB) { + ValueMapTy ValueMap; + BasicBlock *New = CloneBasicBlock(*BB, ValueMap, SuffixBuffer); + Header->getParent()->getBasicBlockList().push_back(New); + + // Loop over all of the PHI nodes in the block, changing them to use the + // incoming values from the previous block. + if (*BB == Header) + for (unsigned i = 0, e = OrigPHINode.size(); i != e; ++i) { + PHINode *NewPHI = cast(ValueMap[OrigPHINode[i]]); + Value *InVal = NewPHI->getIncomingValueForBlock(LatchBlock); + if (Instruction *InValI = dyn_cast(InVal)) + if (It > 1 && L->contains(InValI->getParent())) + InVal = LastValueMap[InValI]; + ValueMap[OrigPHINode[i]] = InVal; + New->getInstList().erase(NewPHI); + } + + // Update our running map of newest clones + LastValueMap[*BB] = New; + for (ValueMapTy::iterator VI = ValueMap.begin(), VE = ValueMap.end(); + VI != VE; ++VI) + LastValueMap[VI->first] = VI->second; + + L->addBasicBlockToLoop(New, LI->getBase()); + + // Add phi entries for newly created values to all exit blocks except + // the successor of the latch block. The successor of the exit block will + // be updated specially after unrolling all the way. + if (*BB != LatchBlock) + for (Value::use_iterator UI = (*BB)->use_begin(), UE = (*BB)->use_end(); + UI != UE;) { + Instruction *UseInst = cast(*UI); + ++UI; + if (isa(UseInst) && !L->contains(UseInst->getParent())) { + PHINode *phi = cast(UseInst); + Value *Incoming = phi->getIncomingValueForBlock(*BB); + phi->addIncoming(Incoming, New); + } + } + + // Keep track of new headers and latches as we create them, so that + // we can insert the proper branches later. + if (*BB == Header) + Headers.push_back(New); + if (*BB == LatchBlock) { + Latches.push_back(New); + + // Also, clear out the new latch's back edge so that it doesn't look + // like a new loop, so that it's amenable to being merged with adjacent + // blocks later on. + TerminatorInst *Term = New->getTerminator(); + assert(L->contains(Term->getSuccessor(!ContinueOnTrue))); + assert(Term->getSuccessor(ContinueOnTrue) == LoopExit); + Term->setSuccessor(!ContinueOnTrue, NULL); + } + + NewBlocks.push_back(New); + } + + // Remap all instructions in the most recent iteration + for (unsigned i = 0; i < NewBlocks.size(); ++i) + for (BasicBlock::iterator I = NewBlocks[i]->begin(), + E = NewBlocks[i]->end(); I != E; ++I) + RemapInstruction(I, LastValueMap); + } + + // The latch block exits the loop. If there are any PHI nodes in the + // successor blocks, update them to use the appropriate values computed as the + // last iteration of the loop. + if (Count != 1) { + SmallPtrSet Users; + for (Value::use_iterator UI = LatchBlock->use_begin(), + UE = LatchBlock->use_end(); UI != UE; ++UI) + if (PHINode *phi = dyn_cast(*UI)) + Users.insert(phi); + + BasicBlock *LastIterationBB = cast(LastValueMap[LatchBlock]); + for (SmallPtrSet::iterator SI = Users.begin(), SE = Users.end(); + SI != SE; ++SI) { + PHINode *PN = *SI; + Value *InVal = PN->removeIncomingValue(LatchBlock, false); + // If this value was defined in the loop, take the value defined by the + // last iteration of the loop. + if (Instruction *InValI = dyn_cast(InVal)) { + if (L->contains(InValI->getParent())) + InVal = LastValueMap[InVal]; + } + PN->addIncoming(InVal, LastIterationBB); + } + } + + // Now, if we're doing complete unrolling, loop over the PHI nodes in the + // original block, setting them to their incoming values. + if (CompletelyUnroll) { + BasicBlock *Preheader = L->getLoopPreheader(); + for (unsigned i = 0, e = OrigPHINode.size(); i != e; ++i) { + PHINode *PN = OrigPHINode[i]; + PN->replaceAllUsesWith(PN->getIncomingValueForBlock(Preheader)); + Header->getInstList().erase(PN); + } + } + + // Now that all the basic blocks for the unrolled iterations are in place, + // set up the branches to connect them. + for (unsigned i = 0, e = Latches.size(); i != e; ++i) { + // The original branch was replicated in each unrolled iteration. + BranchInst *Term = cast(Latches[i]->getTerminator()); + + // The branch destination. + unsigned j = (i + 1) % e; + BasicBlock *Dest = Headers[j]; + bool NeedConditional = true; + + // For a complete unroll, make the last iteration end with a branch + // to the exit block. + if (CompletelyUnroll && j == 0) { + Dest = LoopExit; + NeedConditional = false; + } + + // If we know the trip count or a multiple of it, we can safely use an + // unconditional branch for some iterations. + if (j != BreakoutTrip && (TripMultiple == 0 || j % TripMultiple != 0)) { + NeedConditional = false; + } + + if (NeedConditional) { + // Update the conditional branch's successor for the following + // iteration. + Term->setSuccessor(!ContinueOnTrue, Dest); + } else { + Term->setUnconditionalDest(Dest); + // Merge adjacent basic blocks, if possible. + if (BasicBlock *Fold = FoldBlockIntoPredecessor(Dest, LI)) { + std::replace(Latches.begin(), Latches.end(), Dest, Fold); + std::replace(Headers.begin(), Headers.end(), Dest, Fold); + } + } + } + + // At this point, the code is well formed. We now do a quick sweep over the + // inserted code, doing constant propagation and dead code elimination as we + // go. + const std::vector &NewLoopBlocks = L->getBlocks(); + for (std::vector::const_iterator BB = NewLoopBlocks.begin(), + BBE = NewLoopBlocks.end(); BB != BBE; ++BB) + for (BasicBlock::iterator I = (*BB)->begin(), E = (*BB)->end(); I != E; ) { + Instruction *Inst = I++; + + if (isInstructionTriviallyDead(Inst)) + (*BB)->getInstList().erase(Inst); + else if (Constant *C = ConstantFoldInstruction(Inst)) { + Inst->replaceAllUsesWith(C); + (*BB)->getInstList().erase(Inst); + } + } + + NumCompletelyUnrolled += CompletelyUnroll; + ++NumUnrolled; + // Remove the loop from the LoopPassManager if it's completely removed. + if (CompletelyUnroll && LPM != NULL) + LPM->deleteLoopFromQueue(L); + + // If we didn't completely unroll the loop, it should still be in LCSSA form. + if (!CompletelyUnroll) + assert(L->isLCSSAForm()); + + return true; +} diff --git a/libclamav/c++/llvm/lib/Transforms/Utils/LowerInvoke.cpp b/libclamav/c++/llvm/lib/Transforms/Utils/LowerInvoke.cpp new file mode 100644 index 000000000..6e6e8d228 --- /dev/null +++ b/libclamav/c++/llvm/lib/Transforms/Utils/LowerInvoke.cpp @@ -0,0 +1,629 @@ +//===- LowerInvoke.cpp - Eliminate Invoke & Unwind instructions -----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This transformation is designed for use by code generators which do not yet +// support stack unwinding. This pass supports two models of exception handling +// lowering, the 'cheap' support and the 'expensive' support. +// +// 'Cheap' exception handling support gives the program the ability to execute +// any program which does not "throw an exception", by turning 'invoke' +// instructions into calls and by turning 'unwind' instructions into calls to +// abort(). If the program does dynamically use the unwind instruction, the +// program will print a message then abort. +// +// 'Expensive' exception handling support gives the full exception handling +// support to the program at the cost of making the 'invoke' instruction +// really expensive. It basically inserts setjmp/longjmp calls to emulate the +// exception handling as necessary. +// +// Because the 'expensive' support slows down programs a lot, and EH is only +// used for a subset of the programs, it must be specifically enabled by an +// option. +// +// Note that after this pass runs the CFG is not entirely accurate (exceptional +// control flow edges are not correct anymore) so only very simple things should +// be done after the lowerinvoke pass has run (like generation of native code). +// This should not be used as a general purpose "my LLVM-to-LLVM pass doesn't +// support the invoke instruction yet" lowering pass. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "lowerinvoke" +#include "llvm/Transforms/Scalar.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Instructions.h" +#include "llvm/Intrinsics.h" +#include "llvm/LLVMContext.h" +#include "llvm/Module.h" +#include "llvm/Pass.h" +#include "llvm/Transforms/Utils/BasicBlockUtils.h" +#include "llvm/Transforms/Utils/Local.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Target/TargetLowering.h" +#include +#include +using namespace llvm; + +STATISTIC(NumInvokes, "Number of invokes replaced"); +STATISTIC(NumUnwinds, "Number of unwinds replaced"); +STATISTIC(NumSpilled, "Number of registers live across unwind edges"); + +static cl::opt ExpensiveEHSupport("enable-correct-eh-support", + cl::desc("Make the -lowerinvoke pass insert expensive, but correct, EH code")); + +namespace { + class LowerInvoke : public FunctionPass { + // Used for both models. + Constant *WriteFn; + Constant *AbortFn; + Value *AbortMessage; + unsigned AbortMessageLength; + + // Used for expensive EH support. + const Type *JBLinkTy; + GlobalVariable *JBListHead; + Constant *SetJmpFn, *LongJmpFn; + + // We peek in TLI to grab the target's jmp_buf size and alignment + const TargetLowering *TLI; + + public: + static char ID; // Pass identification, replacement for typeid + explicit LowerInvoke(const TargetLowering *tli = NULL) + : FunctionPass(&ID), TLI(tli) { } + bool doInitialization(Module &M); + bool runOnFunction(Function &F); + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + // This is a cluster of orthogonal Transforms + AU.addPreservedID(PromoteMemoryToRegisterID); + AU.addPreservedID(LowerSwitchID); + } + + private: + void createAbortMessage(Module *M); + void writeAbortMessage(Instruction *IB); + bool insertCheapEHSupport(Function &F); + void splitLiveRangesLiveAcrossInvokes(std::vector &Invokes); + void rewriteExpensiveInvoke(InvokeInst *II, unsigned InvokeNo, + AllocaInst *InvokeNum, SwitchInst *CatchSwitch); + bool insertExpensiveEHSupport(Function &F); + }; +} + +char LowerInvoke::ID = 0; +static RegisterPass +X("lowerinvoke", "Lower invoke and unwind, for unwindless code generators"); + +const PassInfo *const llvm::LowerInvokePassID = &X; + +// Public Interface To the LowerInvoke pass. +FunctionPass *llvm::createLowerInvokePass(const TargetLowering *TLI) { + return new LowerInvoke(TLI); +} + +// doInitialization - Make sure that there is a prototype for abort in the +// current module. +bool LowerInvoke::doInitialization(Module &M) { + const Type *VoidPtrTy = + Type::getInt8PtrTy(M.getContext()); + AbortMessage = 0; + if (ExpensiveEHSupport) { + // Insert a type for the linked list of jump buffers. + unsigned JBSize = TLI ? TLI->getJumpBufSize() : 0; + JBSize = JBSize ? JBSize : 200; + const Type *JmpBufTy = ArrayType::get(VoidPtrTy, JBSize); + + { // The type is recursive, so use a type holder. + std::vector Elements; + Elements.push_back(JmpBufTy); + OpaqueType *OT = OpaqueType::get(M.getContext()); + Elements.push_back(PointerType::getUnqual(OT)); + PATypeHolder JBLType(StructType::get(M.getContext(), Elements)); + OT->refineAbstractTypeTo(JBLType.get()); // Complete the cycle. + JBLinkTy = JBLType.get(); + M.addTypeName("llvm.sjljeh.jmpbufty", JBLinkTy); + } + + const Type *PtrJBList = PointerType::getUnqual(JBLinkTy); + + // Now that we've done that, insert the jmpbuf list head global, unless it + // already exists. + if (!(JBListHead = M.getGlobalVariable("llvm.sjljeh.jblist", PtrJBList))) { + JBListHead = new GlobalVariable(M, PtrJBList, false, + GlobalValue::LinkOnceAnyLinkage, + Constant::getNullValue(PtrJBList), + "llvm.sjljeh.jblist"); + } + +// VisualStudio defines setjmp as _setjmp via #include / , +// so it looks like Intrinsic::_setjmp +#if defined(_MSC_VER) && defined(setjmp) +#define setjmp_undefined_for_visual_studio +#undef setjmp +#endif + + SetJmpFn = Intrinsic::getDeclaration(&M, Intrinsic::setjmp); + +#if defined(_MSC_VER) && defined(setjmp_undefined_for_visual_studio) +// let's return it to _setjmp state in case anyone ever needs it after this +// point under VisualStudio +#define setjmp _setjmp +#endif + + LongJmpFn = Intrinsic::getDeclaration(&M, Intrinsic::longjmp); + } + + // We need the 'write' and 'abort' functions for both models. + AbortFn = M.getOrInsertFunction("abort", Type::getVoidTy(M.getContext()), + (Type *)0); +#if 0 // "write" is Unix-specific.. code is going away soon anyway. + WriteFn = M.getOrInsertFunction("write", Type::VoidTy, Type::Int32Ty, + VoidPtrTy, Type::Int32Ty, (Type *)0); +#else + WriteFn = 0; +#endif + return true; +} + +void LowerInvoke::createAbortMessage(Module *M) { + if (ExpensiveEHSupport) { + // The abort message for expensive EH support tells the user that the + // program 'unwound' without an 'invoke' instruction. + Constant *Msg = + ConstantArray::get(M->getContext(), + "ERROR: Exception thrown, but not caught!\n"); + AbortMessageLength = Msg->getNumOperands()-1; // don't include \0 + + GlobalVariable *MsgGV = new GlobalVariable(*M, Msg->getType(), true, + GlobalValue::InternalLinkage, + Msg, "abortmsg"); + std::vector GEPIdx(2, + Constant::getNullValue(Type::getInt32Ty(M->getContext()))); + AbortMessage = ConstantExpr::getGetElementPtr(MsgGV, &GEPIdx[0], 2); + } else { + // The abort message for cheap EH support tells the user that EH is not + // enabled. + Constant *Msg = + ConstantArray::get(M->getContext(), + "Exception handler needed, but not enabled." + "Recompile program with -enable-correct-eh-support.\n"); + AbortMessageLength = Msg->getNumOperands()-1; // don't include \0 + + GlobalVariable *MsgGV = new GlobalVariable(*M, Msg->getType(), true, + GlobalValue::InternalLinkage, + Msg, "abortmsg"); + std::vector GEPIdx(2, Constant::getNullValue( + Type::getInt32Ty(M->getContext()))); + AbortMessage = ConstantExpr::getGetElementPtr(MsgGV, &GEPIdx[0], 2); + } +} + + +void LowerInvoke::writeAbortMessage(Instruction *IB) { +#if 0 + if (AbortMessage == 0) + createAbortMessage(IB->getParent()->getParent()->getParent()); + + // These are the arguments we WANT... + Value* Args[3]; + Args[0] = ConstantInt::get(Type::Int32Ty, 2); + Args[1] = AbortMessage; + Args[2] = ConstantInt::get(Type::Int32Ty, AbortMessageLength); + (new CallInst(WriteFn, Args, 3, "", IB))->setTailCall(); +#endif +} + +bool LowerInvoke::insertCheapEHSupport(Function &F) { + bool Changed = false; + for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB) + if (InvokeInst *II = dyn_cast(BB->getTerminator())) { + std::vector CallArgs(II->op_begin()+3, II->op_end()); + // Insert a normal call instruction... + CallInst *NewCall = CallInst::Create(II->getCalledValue(), + CallArgs.begin(), CallArgs.end(), "",II); + NewCall->takeName(II); + NewCall->setCallingConv(II->getCallingConv()); + NewCall->setAttributes(II->getAttributes()); + II->replaceAllUsesWith(NewCall); + + // Insert an unconditional branch to the normal destination. + BranchInst::Create(II->getNormalDest(), II); + + // Remove any PHI node entries from the exception destination. + II->getUnwindDest()->removePredecessor(BB); + + // Remove the invoke instruction now. + BB->getInstList().erase(II); + + ++NumInvokes; Changed = true; + } else if (UnwindInst *UI = dyn_cast(BB->getTerminator())) { + // Insert a new call to write(2, AbortMessage, AbortMessageLength); + writeAbortMessage(UI); + + // Insert a call to abort() + CallInst::Create(AbortFn, "", UI)->setTailCall(); + + // Insert a return instruction. This really should be a "barrier", as it + // is unreachable. + ReturnInst::Create(F.getContext(), + F.getReturnType() == Type::getVoidTy(F.getContext()) ? + 0 : Constant::getNullValue(F.getReturnType()), UI); + + // Remove the unwind instruction now. + BB->getInstList().erase(UI); + + ++NumUnwinds; Changed = true; + } + return Changed; +} + +/// rewriteExpensiveInvoke - Insert code and hack the function to replace the +/// specified invoke instruction with a call. +void LowerInvoke::rewriteExpensiveInvoke(InvokeInst *II, unsigned InvokeNo, + AllocaInst *InvokeNum, + SwitchInst *CatchSwitch) { + ConstantInt *InvokeNoC = ConstantInt::get(Type::getInt32Ty(II->getContext()), + InvokeNo); + + // If the unwind edge has phi nodes, split the edge. + if (isa(II->getUnwindDest()->begin())) { + SplitCriticalEdge(II, 1, this); + + // If there are any phi nodes left, they must have a single predecessor. + while (PHINode *PN = dyn_cast(II->getUnwindDest()->begin())) { + PN->replaceAllUsesWith(PN->getIncomingValue(0)); + PN->eraseFromParent(); + } + } + + // Insert a store of the invoke num before the invoke and store zero into the + // location afterward. + new StoreInst(InvokeNoC, InvokeNum, true, II); // volatile + + BasicBlock::iterator NI = II->getNormalDest()->getFirstNonPHI(); + // nonvolatile. + new StoreInst(Constant::getNullValue(Type::getInt32Ty(II->getContext())), + InvokeNum, false, NI); + + // Add a switch case to our unwind block. + CatchSwitch->addCase(InvokeNoC, II->getUnwindDest()); + + // Insert a normal call instruction. + std::vector CallArgs(II->op_begin()+3, II->op_end()); + CallInst *NewCall = CallInst::Create(II->getCalledValue(), + CallArgs.begin(), CallArgs.end(), "", + II); + NewCall->takeName(II); + NewCall->setCallingConv(II->getCallingConv()); + NewCall->setAttributes(II->getAttributes()); + II->replaceAllUsesWith(NewCall); + + // Replace the invoke with an uncond branch. + BranchInst::Create(II->getNormalDest(), NewCall->getParent()); + II->eraseFromParent(); +} + +/// MarkBlocksLiveIn - Insert BB and all of its predescessors into LiveBBs until +/// we reach blocks we've already seen. +static void MarkBlocksLiveIn(BasicBlock *BB, std::set &LiveBBs) { + if (!LiveBBs.insert(BB).second) return; // already been here. + + for (pred_iterator PI = pred_begin(BB), E = pred_end(BB); PI != E; ++PI) + MarkBlocksLiveIn(*PI, LiveBBs); +} + +// First thing we need to do is scan the whole function for values that are +// live across unwind edges. Each value that is live across an unwind edge +// we spill into a stack location, guaranteeing that there is nothing live +// across the unwind edge. This process also splits all critical edges +// coming out of invoke's. +void LowerInvoke:: +splitLiveRangesLiveAcrossInvokes(std::vector &Invokes) { + // First step, split all critical edges from invoke instructions. + for (unsigned i = 0, e = Invokes.size(); i != e; ++i) { + InvokeInst *II = Invokes[i]; + SplitCriticalEdge(II, 0, this); + SplitCriticalEdge(II, 1, this); + assert(!isa(II->getNormalDest()) && + !isa(II->getUnwindDest()) && + "critical edge splitting left single entry phi nodes?"); + } + + Function *F = Invokes.back()->getParent()->getParent(); + + // To avoid having to handle incoming arguments specially, we lower each arg + // to a copy instruction in the entry block. This ensures that the argument + // value itself cannot be live across the entry block. + BasicBlock::iterator AfterAllocaInsertPt = F->begin()->begin(); + while (isa(AfterAllocaInsertPt) && + isa(cast(AfterAllocaInsertPt)->getArraySize())) + ++AfterAllocaInsertPt; + for (Function::arg_iterator AI = F->arg_begin(), E = F->arg_end(); + AI != E; ++AI) { + // This is always a no-op cast because we're casting AI to AI->getType() so + // src and destination types are identical. BitCast is the only possibility. + CastInst *NC = new BitCastInst( + AI, AI->getType(), AI->getName()+".tmp", AfterAllocaInsertPt); + AI->replaceAllUsesWith(NC); + // Normally its is forbidden to replace a CastInst's operand because it + // could cause the opcode to reflect an illegal conversion. However, we're + // replacing it here with the same value it was constructed with to simply + // make NC its user. + NC->setOperand(0, AI); + } + + // Finally, scan the code looking for instructions with bad live ranges. + for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) + for (BasicBlock::iterator II = BB->begin(), E = BB->end(); II != E; ++II) { + // Ignore obvious cases we don't have to handle. In particular, most + // instructions either have no uses or only have a single use inside the + // current block. Ignore them quickly. + Instruction *Inst = II; + if (Inst->use_empty()) continue; + if (Inst->hasOneUse() && + cast(Inst->use_back())->getParent() == BB && + !isa(Inst->use_back())) continue; + + // If this is an alloca in the entry block, it's not a real register + // value. + if (AllocaInst *AI = dyn_cast(Inst)) + if (isa(AI->getArraySize()) && BB == F->begin()) + continue; + + // Avoid iterator invalidation by copying users to a temporary vector. + std::vector Users; + for (Value::use_iterator UI = Inst->use_begin(), E = Inst->use_end(); + UI != E; ++UI) { + Instruction *User = cast(*UI); + if (User->getParent() != BB || isa(User)) + Users.push_back(User); + } + + // Scan all of the uses and see if the live range is live across an unwind + // edge. If we find a use live across an invoke edge, create an alloca + // and spill the value. + std::set InvokesWithStoreInserted; + + // Find all of the blocks that this value is live in. + std::set LiveBBs; + LiveBBs.insert(Inst->getParent()); + while (!Users.empty()) { + Instruction *U = Users.back(); + Users.pop_back(); + + if (!isa(U)) { + MarkBlocksLiveIn(U->getParent(), LiveBBs); + } else { + // Uses for a PHI node occur in their predecessor block. + PHINode *PN = cast(U); + for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) + if (PN->getIncomingValue(i) == Inst) + MarkBlocksLiveIn(PN->getIncomingBlock(i), LiveBBs); + } + } + + // Now that we know all of the blocks that this thing is live in, see if + // it includes any of the unwind locations. + bool NeedsSpill = false; + for (unsigned i = 0, e = Invokes.size(); i != e; ++i) { + BasicBlock *UnwindBlock = Invokes[i]->getUnwindDest(); + if (UnwindBlock != BB && LiveBBs.count(UnwindBlock)) { + NeedsSpill = true; + } + } + + // If we decided we need a spill, do it. + if (NeedsSpill) { + ++NumSpilled; + DemoteRegToStack(*Inst, true); + } + } +} + +bool LowerInvoke::insertExpensiveEHSupport(Function &F) { + std::vector Returns; + std::vector Unwinds; + std::vector Invokes; + + for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB) + if (ReturnInst *RI = dyn_cast(BB->getTerminator())) { + // Remember all return instructions in case we insert an invoke into this + // function. + Returns.push_back(RI); + } else if (InvokeInst *II = dyn_cast(BB->getTerminator())) { + Invokes.push_back(II); + } else if (UnwindInst *UI = dyn_cast(BB->getTerminator())) { + Unwinds.push_back(UI); + } + + if (Unwinds.empty() && Invokes.empty()) return false; + + NumInvokes += Invokes.size(); + NumUnwinds += Unwinds.size(); + + // TODO: This is not an optimal way to do this. In particular, this always + // inserts setjmp calls into the entries of functions with invoke instructions + // even though there are possibly paths through the function that do not + // execute any invokes. In particular, for functions with early exits, e.g. + // the 'addMove' method in hexxagon, it would be nice to not have to do the + // setjmp stuff on the early exit path. This requires a bit of dataflow, but + // would not be too hard to do. + + // If we have an invoke instruction, insert a setjmp that dominates all + // invokes. After the setjmp, use a cond branch that goes to the original + // code path on zero, and to a designated 'catch' block of nonzero. + Value *OldJmpBufPtr = 0; + if (!Invokes.empty()) { + // First thing we need to do is scan the whole function for values that are + // live across unwind edges. Each value that is live across an unwind edge + // we spill into a stack location, guaranteeing that there is nothing live + // across the unwind edge. This process also splits all critical edges + // coming out of invoke's. + splitLiveRangesLiveAcrossInvokes(Invokes); + + BasicBlock *EntryBB = F.begin(); + + // Create an alloca for the incoming jump buffer ptr and the new jump buffer + // that needs to be restored on all exits from the function. This is an + // alloca because the value needs to be live across invokes. + unsigned Align = TLI ? TLI->getJumpBufAlignment() : 0; + AllocaInst *JmpBuf = + new AllocaInst(JBLinkTy, 0, Align, + "jblink", F.begin()->begin()); + + std::vector Idx; + Idx.push_back(Constant::getNullValue(Type::getInt32Ty(F.getContext()))); + Idx.push_back(ConstantInt::get(Type::getInt32Ty(F.getContext()), 1)); + OldJmpBufPtr = GetElementPtrInst::Create(JmpBuf, Idx.begin(), Idx.end(), + "OldBuf", + EntryBB->getTerminator()); + + // Copy the JBListHead to the alloca. + Value *OldBuf = new LoadInst(JBListHead, "oldjmpbufptr", true, + EntryBB->getTerminator()); + new StoreInst(OldBuf, OldJmpBufPtr, true, EntryBB->getTerminator()); + + // Add the new jumpbuf to the list. + new StoreInst(JmpBuf, JBListHead, true, EntryBB->getTerminator()); + + // Create the catch block. The catch block is basically a big switch + // statement that goes to all of the invoke catch blocks. + BasicBlock *CatchBB = + BasicBlock::Create(F.getContext(), "setjmp.catch", &F); + + // Create an alloca which keeps track of which invoke is currently + // executing. For normal calls it contains zero. + AllocaInst *InvokeNum = new AllocaInst(Type::getInt32Ty(F.getContext()), 0, + "invokenum",EntryBB->begin()); + new StoreInst(ConstantInt::get(Type::getInt32Ty(F.getContext()), 0), + InvokeNum, true, EntryBB->getTerminator()); + + // Insert a load in the Catch block, and a switch on its value. By default, + // we go to a block that just does an unwind (which is the correct action + // for a standard call). + BasicBlock *UnwindBB = BasicBlock::Create(F.getContext(), "unwindbb", &F); + Unwinds.push_back(new UnwindInst(F.getContext(), UnwindBB)); + + Value *CatchLoad = new LoadInst(InvokeNum, "invoke.num", true, CatchBB); + SwitchInst *CatchSwitch = + SwitchInst::Create(CatchLoad, UnwindBB, Invokes.size(), CatchBB); + + // Now that things are set up, insert the setjmp call itself. + + // Split the entry block to insert the conditional branch for the setjmp. + BasicBlock *ContBlock = EntryBB->splitBasicBlock(EntryBB->getTerminator(), + "setjmp.cont"); + + Idx[1] = ConstantInt::get(Type::getInt32Ty(F.getContext()), 0); + Value *JmpBufPtr = GetElementPtrInst::Create(JmpBuf, Idx.begin(), Idx.end(), + "TheJmpBuf", + EntryBB->getTerminator()); + JmpBufPtr = new BitCastInst(JmpBufPtr, + Type::getInt8PtrTy(F.getContext()), + "tmp", EntryBB->getTerminator()); + Value *SJRet = CallInst::Create(SetJmpFn, JmpBufPtr, "sjret", + EntryBB->getTerminator()); + + // Compare the return value to zero. + Value *IsNormal = new ICmpInst(EntryBB->getTerminator(), + ICmpInst::ICMP_EQ, SJRet, + Constant::getNullValue(SJRet->getType()), + "notunwind"); + // Nuke the uncond branch. + EntryBB->getTerminator()->eraseFromParent(); + + // Put in a new condbranch in its place. + BranchInst::Create(ContBlock, CatchBB, IsNormal, EntryBB); + + // At this point, we are all set up, rewrite each invoke instruction. + for (unsigned i = 0, e = Invokes.size(); i != e; ++i) + rewriteExpensiveInvoke(Invokes[i], i+1, InvokeNum, CatchSwitch); + } + + // We know that there is at least one unwind. + + // Create three new blocks, the block to load the jmpbuf ptr and compare + // against null, the block to do the longjmp, and the error block for if it + // is null. Add them at the end of the function because they are not hot. + BasicBlock *UnwindHandler = BasicBlock::Create(F.getContext(), + "dounwind", &F); + BasicBlock *UnwindBlock = BasicBlock::Create(F.getContext(), "unwind", &F); + BasicBlock *TermBlock = BasicBlock::Create(F.getContext(), "unwinderror", &F); + + // If this function contains an invoke, restore the old jumpbuf ptr. + Value *BufPtr; + if (OldJmpBufPtr) { + // Before the return, insert a copy from the saved value to the new value. + BufPtr = new LoadInst(OldJmpBufPtr, "oldjmpbufptr", UnwindHandler); + new StoreInst(BufPtr, JBListHead, UnwindHandler); + } else { + BufPtr = new LoadInst(JBListHead, "ehlist", UnwindHandler); + } + + // Load the JBList, if it's null, then there was no catch! + Value *NotNull = new ICmpInst(*UnwindHandler, ICmpInst::ICMP_NE, BufPtr, + Constant::getNullValue(BufPtr->getType()), + "notnull"); + BranchInst::Create(UnwindBlock, TermBlock, NotNull, UnwindHandler); + + // Create the block to do the longjmp. + // Get a pointer to the jmpbuf and longjmp. + std::vector Idx; + Idx.push_back(Constant::getNullValue(Type::getInt32Ty(F.getContext()))); + Idx.push_back(ConstantInt::get(Type::getInt32Ty(F.getContext()), 0)); + Idx[0] = GetElementPtrInst::Create(BufPtr, Idx.begin(), Idx.end(), "JmpBuf", + UnwindBlock); + Idx[0] = new BitCastInst(Idx[0], + Type::getInt8PtrTy(F.getContext()), + "tmp", UnwindBlock); + Idx[1] = ConstantInt::get(Type::getInt32Ty(F.getContext()), 1); + CallInst::Create(LongJmpFn, Idx.begin(), Idx.end(), "", UnwindBlock); + new UnreachableInst(F.getContext(), UnwindBlock); + + // Set up the term block ("throw without a catch"). + new UnreachableInst(F.getContext(), TermBlock); + + // Insert a new call to write(2, AbortMessage, AbortMessageLength); + writeAbortMessage(TermBlock->getTerminator()); + + // Insert a call to abort() + CallInst::Create(AbortFn, "", + TermBlock->getTerminator())->setTailCall(); + + + // Replace all unwinds with a branch to the unwind handler. + for (unsigned i = 0, e = Unwinds.size(); i != e; ++i) { + BranchInst::Create(UnwindHandler, Unwinds[i]); + Unwinds[i]->eraseFromParent(); + } + + // Finally, for any returns from this function, if this function contains an + // invoke, restore the old jmpbuf pointer to its input value. + if (OldJmpBufPtr) { + for (unsigned i = 0, e = Returns.size(); i != e; ++i) { + ReturnInst *R = Returns[i]; + + // Before the return, insert a copy from the saved value to the new value. + Value *OldBuf = new LoadInst(OldJmpBufPtr, "oldjmpbufptr", true, R); + new StoreInst(OldBuf, JBListHead, true, R); + } + } + + return true; +} + +bool LowerInvoke::runOnFunction(Function &F) { + if (ExpensiveEHSupport) + return insertExpensiveEHSupport(F); + else + return insertCheapEHSupport(F); +} diff --git a/libclamav/c++/llvm/lib/Transforms/Utils/LowerSwitch.cpp b/libclamav/c++/llvm/lib/Transforms/Utils/LowerSwitch.cpp new file mode 100644 index 000000000..8c18b591a --- /dev/null +++ b/libclamav/c++/llvm/lib/Transforms/Utils/LowerSwitch.cpp @@ -0,0 +1,322 @@ +//===- LowerSwitch.cpp - Eliminate Switch instructions --------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// The LowerSwitch transformation rewrites switch instructions with a sequence +// of branches, which allows targets to get away with not implementing the +// switch instruction until it is convenient. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Transforms/Scalar.h" +#include "llvm/Transforms/Utils/UnifyFunctionExitNodes.h" +#include "llvm/Constants.h" +#include "llvm/Function.h" +#include "llvm/Instructions.h" +#include "llvm/LLVMContext.h" +#include "llvm/Pass.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" +#include +using namespace llvm; + +namespace { + /// LowerSwitch Pass - Replace all SwitchInst instructions with chained branch + /// instructions. Note that this cannot be a BasicBlock pass because it + /// modifies the CFG! + class LowerSwitch : public FunctionPass { + public: + static char ID; // Pass identification, replacement for typeid + LowerSwitch() : FunctionPass(&ID) {} + + virtual bool runOnFunction(Function &F); + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + // This is a cluster of orthogonal Transforms + AU.addPreserved(); + AU.addPreservedID(PromoteMemoryToRegisterID); + AU.addPreservedID(LowerInvokePassID); + } + + struct CaseRange { + Constant* Low; + Constant* High; + BasicBlock* BB; + + CaseRange() : Low(0), High(0), BB(0) { } + CaseRange(Constant* low, Constant* high, BasicBlock* bb) : + Low(low), High(high), BB(bb) { } + }; + + typedef std::vector CaseVector; + typedef std::vector::iterator CaseItr; + private: + void processSwitchInst(SwitchInst *SI); + + BasicBlock* switchConvert(CaseItr Begin, CaseItr End, Value* Val, + BasicBlock* OrigBlock, BasicBlock* Default); + BasicBlock* newLeafBlock(CaseRange& Leaf, Value* Val, + BasicBlock* OrigBlock, BasicBlock* Default); + unsigned Clusterify(CaseVector& Cases, SwitchInst *SI); + }; + + /// The comparison function for sorting the switch case values in the vector. + /// WARNING: Case ranges should be disjoint! + struct CaseCmp { + bool operator () (const LowerSwitch::CaseRange& C1, + const LowerSwitch::CaseRange& C2) { + + const ConstantInt* CI1 = cast(C1.Low); + const ConstantInt* CI2 = cast(C2.High); + return CI1->getValue().slt(CI2->getValue()); + } + }; +} + +char LowerSwitch::ID = 0; +static RegisterPass +X("lowerswitch", "Lower SwitchInst's to branches"); + +// Publically exposed interface to pass... +const PassInfo *const llvm::LowerSwitchID = &X; +// createLowerSwitchPass - Interface to this file... +FunctionPass *llvm::createLowerSwitchPass() { + return new LowerSwitch(); +} + +bool LowerSwitch::runOnFunction(Function &F) { + bool Changed = false; + + for (Function::iterator I = F.begin(), E = F.end(); I != E; ) { + BasicBlock *Cur = I++; // Advance over block so we don't traverse new blocks + + if (SwitchInst *SI = dyn_cast(Cur->getTerminator())) { + Changed = true; + processSwitchInst(SI); + } + } + + return Changed; +} + +// operator<< - Used for debugging purposes. +// +static raw_ostream& operator<<(raw_ostream &O, + const LowerSwitch::CaseVector &C) ATTRIBUTE_USED; +static raw_ostream& operator<<(raw_ostream &O, + const LowerSwitch::CaseVector &C) { + O << "["; + + for (LowerSwitch::CaseVector::const_iterator B = C.begin(), + E = C.end(); B != E; ) { + O << *B->Low << " -" << *B->High; + if (++B != E) O << ", "; + } + + return O << "]"; +} + +// switchConvert - Convert the switch statement into a binary lookup of +// the case values. The function recursively builds this tree. +// +BasicBlock* LowerSwitch::switchConvert(CaseItr Begin, CaseItr End, + Value* Val, BasicBlock* OrigBlock, + BasicBlock* Default) +{ + unsigned Size = End - Begin; + + if (Size == 1) + return newLeafBlock(*Begin, Val, OrigBlock, Default); + + unsigned Mid = Size / 2; + std::vector LHS(Begin, Begin + Mid); + DEBUG(errs() << "LHS: " << LHS << "\n"); + std::vector RHS(Begin + Mid, End); + DEBUG(errs() << "RHS: " << RHS << "\n"); + + CaseRange& Pivot = *(Begin + Mid); + DEBUG(errs() << "Pivot ==> " + << cast(Pivot.Low)->getValue() << " -" + << cast(Pivot.High)->getValue() << "\n"); + + BasicBlock* LBranch = switchConvert(LHS.begin(), LHS.end(), Val, + OrigBlock, Default); + BasicBlock* RBranch = switchConvert(RHS.begin(), RHS.end(), Val, + OrigBlock, Default); + + // Create a new node that checks if the value is < pivot. Go to the + // left branch if it is and right branch if not. + Function* F = OrigBlock->getParent(); + BasicBlock* NewNode = BasicBlock::Create(Val->getContext(), "NodeBlock"); + Function::iterator FI = OrigBlock; + F->getBasicBlockList().insert(++FI, NewNode); + + ICmpInst* Comp = new ICmpInst(ICmpInst::ICMP_SLT, + Val, Pivot.Low, "Pivot"); + NewNode->getInstList().push_back(Comp); + BranchInst::Create(LBranch, RBranch, Comp, NewNode); + return NewNode; +} + +// newLeafBlock - Create a new leaf block for the binary lookup tree. It +// checks if the switch's value == the case's value. If not, then it +// jumps to the default branch. At this point in the tree, the value +// can't be another valid case value, so the jump to the "default" branch +// is warranted. +// +BasicBlock* LowerSwitch::newLeafBlock(CaseRange& Leaf, Value* Val, + BasicBlock* OrigBlock, + BasicBlock* Default) +{ + Function* F = OrigBlock->getParent(); + BasicBlock* NewLeaf = BasicBlock::Create(Val->getContext(), "LeafBlock"); + Function::iterator FI = OrigBlock; + F->getBasicBlockList().insert(++FI, NewLeaf); + + // Emit comparison + ICmpInst* Comp = NULL; + if (Leaf.Low == Leaf.High) { + // Make the seteq instruction... + Comp = new ICmpInst(*NewLeaf, ICmpInst::ICMP_EQ, Val, + Leaf.Low, "SwitchLeaf"); + } else { + // Make range comparison + if (cast(Leaf.Low)->isMinValue(true /*isSigned*/)) { + // Val >= Min && Val <= Hi --> Val <= Hi + Comp = new ICmpInst(*NewLeaf, ICmpInst::ICMP_SLE, Val, Leaf.High, + "SwitchLeaf"); + } else if (cast(Leaf.Low)->isZero()) { + // Val >= 0 && Val <= Hi --> Val <=u Hi + Comp = new ICmpInst(*NewLeaf, ICmpInst::ICMP_ULE, Val, Leaf.High, + "SwitchLeaf"); + } else { + // Emit V-Lo <=u Hi-Lo + Constant* NegLo = ConstantExpr::getNeg(Leaf.Low); + Instruction* Add = BinaryOperator::CreateAdd(Val, NegLo, + Val->getName()+".off", + NewLeaf); + Constant *UpperBound = ConstantExpr::getAdd(NegLo, Leaf.High); + Comp = new ICmpInst(*NewLeaf, ICmpInst::ICMP_ULE, Add, UpperBound, + "SwitchLeaf"); + } + } + + // Make the conditional branch... + BasicBlock* Succ = Leaf.BB; + BranchInst::Create(Succ, Default, Comp, NewLeaf); + + // If there were any PHI nodes in this successor, rewrite one entry + // from OrigBlock to come from NewLeaf. + for (BasicBlock::iterator I = Succ->begin(); isa(I); ++I) { + PHINode* PN = cast(I); + // Remove all but one incoming entries from the cluster + uint64_t Range = cast(Leaf.High)->getSExtValue() - + cast(Leaf.Low)->getSExtValue(); + for (uint64_t j = 0; j < Range; ++j) { + PN->removeIncomingValue(OrigBlock); + } + + int BlockIdx = PN->getBasicBlockIndex(OrigBlock); + assert(BlockIdx != -1 && "Switch didn't go to this successor??"); + PN->setIncomingBlock((unsigned)BlockIdx, NewLeaf); + } + + return NewLeaf; +} + +// Clusterify - Transform simple list of Cases into list of CaseRange's +unsigned LowerSwitch::Clusterify(CaseVector& Cases, SwitchInst *SI) { + unsigned numCmps = 0; + + // Start with "simple" cases + for (unsigned i = 1; i < SI->getNumSuccessors(); ++i) + Cases.push_back(CaseRange(SI->getSuccessorValue(i), + SI->getSuccessorValue(i), + SI->getSuccessor(i))); + std::sort(Cases.begin(), Cases.end(), CaseCmp()); + + // Merge case into clusters + if (Cases.size()>=2) + for (CaseItr I=Cases.begin(), J=next(Cases.begin()); J!=Cases.end(); ) { + int64_t nextValue = cast(J->Low)->getSExtValue(); + int64_t currentValue = cast(I->High)->getSExtValue(); + BasicBlock* nextBB = J->BB; + BasicBlock* currentBB = I->BB; + + // If the two neighboring cases go to the same destination, merge them + // into a single case. + if ((nextValue-currentValue==1) && (currentBB == nextBB)) { + I->High = J->High; + J = Cases.erase(J); + } else { + I = J++; + } + } + + for (CaseItr I=Cases.begin(), E=Cases.end(); I!=E; ++I, ++numCmps) { + if (I->Low != I->High) + // A range counts double, since it requires two compares. + ++numCmps; + } + + return numCmps; +} + +// processSwitchInst - Replace the specified switch instruction with a sequence +// of chained if-then insts in a balanced binary search. +// +void LowerSwitch::processSwitchInst(SwitchInst *SI) { + BasicBlock *CurBlock = SI->getParent(); + BasicBlock *OrigBlock = CurBlock; + Function *F = CurBlock->getParent(); + Value *Val = SI->getOperand(0); // The value we are switching on... + BasicBlock* Default = SI->getDefaultDest(); + + // If there is only the default destination, don't bother with the code below. + if (SI->getNumOperands() == 2) { + BranchInst::Create(SI->getDefaultDest(), CurBlock); + CurBlock->getInstList().erase(SI); + return; + } + + // Create a new, empty default block so that the new hierarchy of + // if-then statements go to this and the PHI nodes are happy. + BasicBlock* NewDefault = BasicBlock::Create(SI->getContext(), "NewDefault"); + F->getBasicBlockList().insert(Default, NewDefault); + + BranchInst::Create(Default, NewDefault); + + // If there is an entry in any PHI nodes for the default edge, make sure + // to update them as well. + for (BasicBlock::iterator I = Default->begin(); isa(I); ++I) { + PHINode *PN = cast(I); + int BlockIdx = PN->getBasicBlockIndex(OrigBlock); + assert(BlockIdx != -1 && "Switch didn't go to this successor??"); + PN->setIncomingBlock((unsigned)BlockIdx, NewDefault); + } + + // Prepare cases vector. + CaseVector Cases; + unsigned numCmps = Clusterify(Cases, SI); + + DEBUG(errs() << "Clusterify finished. Total clusters: " << Cases.size() + << ". Total compares: " << numCmps << "\n"); + DEBUG(errs() << "Cases: " << Cases << "\n"); + (void)numCmps; + + BasicBlock* SwitchBlock = switchConvert(Cases.begin(), Cases.end(), Val, + OrigBlock, NewDefault); + + // Branch to our shiny new if-then stuff... + BranchInst::Create(SwitchBlock, OrigBlock); + + // We are now done with the switch instruction, delete it. + CurBlock->getInstList().erase(SI); +} diff --git a/libclamav/c++/llvm/lib/Transforms/Utils/Makefile b/libclamav/c++/llvm/lib/Transforms/Utils/Makefile new file mode 100644 index 000000000..d1e9336d6 --- /dev/null +++ b/libclamav/c++/llvm/lib/Transforms/Utils/Makefile @@ -0,0 +1,15 @@ +##===- lib/Transforms/Utils/Makefile -----------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LEVEL = ../../.. +LIBRARYNAME = LLVMTransformUtils +BUILD_ARCHIVE = 1 + +include $(LEVEL)/Makefile.common + diff --git a/libclamav/c++/llvm/lib/Transforms/Utils/Mem2Reg.cpp b/libclamav/c++/llvm/lib/Transforms/Utils/Mem2Reg.cpp new file mode 100644 index 000000000..99203b662 --- /dev/null +++ b/libclamav/c++/llvm/lib/Transforms/Utils/Mem2Reg.cpp @@ -0,0 +1,90 @@ +//===- Mem2Reg.cpp - The -mem2reg pass, a wrapper around the Utils lib ----===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This pass is a simple pass wrapper around the PromoteMemToReg function call +// exposed by the Utils library. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "mem2reg" +#include "llvm/Transforms/Scalar.h" +#include "llvm/Transforms/Utils/PromoteMemToReg.h" +#include "llvm/Transforms/Utils/UnifyFunctionExitNodes.h" +#include "llvm/Analysis/Dominators.h" +#include "llvm/Instructions.h" +#include "llvm/Function.h" +#include "llvm/ADT/Statistic.h" +using namespace llvm; + +STATISTIC(NumPromoted, "Number of alloca's promoted"); + +namespace { + struct PromotePass : public FunctionPass { + static char ID; // Pass identification, replacement for typeid + PromotePass() : FunctionPass(&ID) {} + + // runOnFunction - To run this pass, first we calculate the alloca + // instructions that are safe for promotion, then we promote each one. + // + virtual bool runOnFunction(Function &F); + + // getAnalysisUsage - We need dominance frontiers + // + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.addRequired(); + AU.addRequired(); + AU.setPreservesCFG(); + // This is a cluster of orthogonal Transforms + AU.addPreserved(); + AU.addPreservedID(LowerSwitchID); + AU.addPreservedID(LowerInvokePassID); + } + }; +} // end of anonymous namespace + +char PromotePass::ID = 0; +static RegisterPass X("mem2reg", "Promote Memory to Register"); + +bool PromotePass::runOnFunction(Function &F) { + std::vector Allocas; + + BasicBlock &BB = F.getEntryBlock(); // Get the entry node for the function + + bool Changed = false; + + DominatorTree &DT = getAnalysis(); + DominanceFrontier &DF = getAnalysis(); + + while (1) { + Allocas.clear(); + + // Find allocas that are safe to promote, by looking at all instructions in + // the entry node + for (BasicBlock::iterator I = BB.begin(), E = --BB.end(); I != E; ++I) + if (AllocaInst *AI = dyn_cast(I)) // Is it an alloca? + if (isAllocaPromotable(AI)) + Allocas.push_back(AI); + + if (Allocas.empty()) break; + + PromoteMemToReg(Allocas, DT, DF); + NumPromoted += Allocas.size(); + Changed = true; + } + + return Changed; +} + +// Publically exposed interface to pass... +const PassInfo *const llvm::PromoteMemoryToRegisterID = &X; +// createPromoteMemoryToRegister - Provide an entry point to create this pass. +// +FunctionPass *llvm::createPromoteMemoryToRegisterPass() { + return new PromotePass(); +} diff --git a/libclamav/c++/llvm/lib/Transforms/Utils/PromoteMemoryToRegister.cpp b/libclamav/c++/llvm/lib/Transforms/Utils/PromoteMemoryToRegister.cpp new file mode 100644 index 000000000..e25f9e2a9 --- /dev/null +++ b/libclamav/c++/llvm/lib/Transforms/Utils/PromoteMemoryToRegister.cpp @@ -0,0 +1,1007 @@ +//===- PromoteMemoryToRegister.cpp - Convert allocas to registers ---------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file promotes memory references to be register references. It promotes +// alloca instructions which only have loads and stores as uses. An alloca is +// transformed by using dominator frontiers to place PHI nodes, then traversing +// the function in depth-first order to rewrite loads and stores as appropriate. +// This is just the standard SSA construction algorithm to construct "pruned" +// SSA form. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "mem2reg" +#include "llvm/Transforms/Utils/PromoteMemToReg.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Function.h" +#include "llvm/Instructions.h" +#include "llvm/IntrinsicInst.h" +#include "llvm/Analysis/Dominators.h" +#include "llvm/Analysis/AliasSetTracker.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/Support/CFG.h" +#include +using namespace llvm; + +STATISTIC(NumLocalPromoted, "Number of alloca's promoted within one block"); +STATISTIC(NumSingleStore, "Number of alloca's promoted with a single store"); +STATISTIC(NumDeadAlloca, "Number of dead alloca's removed"); +STATISTIC(NumPHIInsert, "Number of PHI nodes inserted"); + +namespace llvm { +template<> +struct DenseMapInfo > { + typedef std::pair EltTy; + static inline EltTy getEmptyKey() { + return EltTy(reinterpret_cast(-1), ~0U); + } + static inline EltTy getTombstoneKey() { + return EltTy(reinterpret_cast(-2), 0U); + } + static unsigned getHashValue(const std::pair &Val) { + return DenseMapInfo::getHashValue(Val.first) + Val.second*2; + } + static bool isEqual(const EltTy &LHS, const EltTy &RHS) { + return LHS == RHS; + } + static bool isPod() { return true; } +}; +} + +/// isAllocaPromotable - Return true if this alloca is legal for promotion. +/// This is true if there are only loads and stores to the alloca. +/// +bool llvm::isAllocaPromotable(const AllocaInst *AI) { + // FIXME: If the memory unit is of pointer or integer type, we can permit + // assignments to subsections of the memory unit. + + // Only allow direct and non-volatile loads and stores... + for (Value::use_const_iterator UI = AI->use_begin(), UE = AI->use_end(); + UI != UE; ++UI) // Loop over all of the uses of the alloca + if (const LoadInst *LI = dyn_cast(*UI)) { + if (LI->isVolatile()) + return false; + } else if (const StoreInst *SI = dyn_cast(*UI)) { + if (SI->getOperand(0) == AI) + return false; // Don't allow a store OF the AI, only INTO the AI. + if (SI->isVolatile()) + return false; + } else if (const BitCastInst *BC = dyn_cast(*UI)) { + // A bitcast that does not feed into debug info inhibits promotion. + if (!BC->hasOneUse() || !isa(*BC->use_begin())) + return false; + // If the only use is by debug info, this alloca will not exist in + // non-debug code, so don't try to promote; this ensures the same + // codegen with debug info. Otherwise, debug info should not + // inhibit promotion (but we must examine other uses). + if (AI->hasOneUse()) + return false; + } else { + return false; + } + + return true; +} + +namespace { + struct AllocaInfo; + + // Data package used by RenamePass() + class RenamePassData { + public: + typedef std::vector ValVector; + + RenamePassData() {} + RenamePassData(BasicBlock *B, BasicBlock *P, + const ValVector &V) : BB(B), Pred(P), Values(V) {} + BasicBlock *BB; + BasicBlock *Pred; + ValVector Values; + + void swap(RenamePassData &RHS) { + std::swap(BB, RHS.BB); + std::swap(Pred, RHS.Pred); + Values.swap(RHS.Values); + } + }; + + /// LargeBlockInfo - This assigns and keeps a per-bb relative ordering of + /// load/store instructions in the block that directly load or store an alloca. + /// + /// This functionality is important because it avoids scanning large basic + /// blocks multiple times when promoting many allocas in the same block. + class LargeBlockInfo { + /// InstNumbers - For each instruction that we track, keep the index of the + /// instruction. The index starts out as the number of the instruction from + /// the start of the block. + DenseMap InstNumbers; + public: + + /// isInterestingInstruction - This code only looks at accesses to allocas. + static bool isInterestingInstruction(const Instruction *I) { + return (isa(I) && isa(I->getOperand(0))) || + (isa(I) && isa(I->getOperand(1))); + } + + /// getInstructionIndex - Get or calculate the index of the specified + /// instruction. + unsigned getInstructionIndex(const Instruction *I) { + assert(isInterestingInstruction(I) && + "Not a load/store to/from an alloca?"); + + // If we already have this instruction number, return it. + DenseMap::iterator It = InstNumbers.find(I); + if (It != InstNumbers.end()) return It->second; + + // Scan the whole block to get the instruction. This accumulates + // information for every interesting instruction in the block, in order to + // avoid gratuitus rescans. + const BasicBlock *BB = I->getParent(); + unsigned InstNo = 0; + for (BasicBlock::const_iterator BBI = BB->begin(), E = BB->end(); + BBI != E; ++BBI) + if (isInterestingInstruction(BBI)) + InstNumbers[BBI] = InstNo++; + It = InstNumbers.find(I); + + assert(It != InstNumbers.end() && "Didn't insert instruction?"); + return It->second; + } + + void deleteValue(const Instruction *I) { + InstNumbers.erase(I); + } + + void clear() { + InstNumbers.clear(); + } + }; + + struct PromoteMem2Reg { + /// Allocas - The alloca instructions being promoted. + /// + std::vector Allocas; + DominatorTree &DT; + DominanceFrontier &DF; + + /// AST - An AliasSetTracker object to update. If null, don't update it. + /// + AliasSetTracker *AST; + + /// AllocaLookup - Reverse mapping of Allocas. + /// + std::map AllocaLookup; + + /// NewPhiNodes - The PhiNodes we're adding. + /// + DenseMap, PHINode*> NewPhiNodes; + + /// PhiToAllocaMap - For each PHI node, keep track of which entry in Allocas + /// it corresponds to. + DenseMap PhiToAllocaMap; + + /// PointerAllocaValues - If we are updating an AliasSetTracker, then for + /// each alloca that is of pointer type, we keep track of what to copyValue + /// to the inserted PHI nodes here. + /// + std::vector PointerAllocaValues; + + /// Visited - The set of basic blocks the renamer has already visited. + /// + SmallPtrSet Visited; + + /// BBNumbers - Contains a stable numbering of basic blocks to avoid + /// non-determinstic behavior. + DenseMap BBNumbers; + + /// BBNumPreds - Lazily compute the number of predecessors a block has. + DenseMap BBNumPreds; + public: + PromoteMem2Reg(const std::vector &A, DominatorTree &dt, + DominanceFrontier &df, AliasSetTracker *ast) + : Allocas(A), DT(dt), DF(df), AST(ast) {} + + void run(); + + /// properlyDominates - Return true if I1 properly dominates I2. + /// + bool properlyDominates(Instruction *I1, Instruction *I2) const { + if (InvokeInst *II = dyn_cast(I1)) + I1 = II->getNormalDest()->begin(); + return DT.properlyDominates(I1->getParent(), I2->getParent()); + } + + /// dominates - Return true if BB1 dominates BB2 using the DominatorTree. + /// + bool dominates(BasicBlock *BB1, BasicBlock *BB2) const { + return DT.dominates(BB1, BB2); + } + + private: + void RemoveFromAllocasList(unsigned &AllocaIdx) { + Allocas[AllocaIdx] = Allocas.back(); + Allocas.pop_back(); + --AllocaIdx; + } + + unsigned getNumPreds(const BasicBlock *BB) { + unsigned &NP = BBNumPreds[BB]; + if (NP == 0) + NP = std::distance(pred_begin(BB), pred_end(BB))+1; + return NP-1; + } + + void DetermineInsertionPoint(AllocaInst *AI, unsigned AllocaNum, + AllocaInfo &Info); + void ComputeLiveInBlocks(AllocaInst *AI, AllocaInfo &Info, + const SmallPtrSet &DefBlocks, + SmallPtrSet &LiveInBlocks); + + void RewriteSingleStoreAlloca(AllocaInst *AI, AllocaInfo &Info, + LargeBlockInfo &LBI); + void PromoteSingleBlockAlloca(AllocaInst *AI, AllocaInfo &Info, + LargeBlockInfo &LBI); + + + void RenamePass(BasicBlock *BB, BasicBlock *Pred, + RenamePassData::ValVector &IncVals, + std::vector &Worklist); + bool QueuePhiNode(BasicBlock *BB, unsigned AllocaIdx, unsigned &Version, + SmallPtrSet &InsertedPHINodes); + }; + + struct AllocaInfo { + std::vector DefiningBlocks; + std::vector UsingBlocks; + + StoreInst *OnlyStore; + BasicBlock *OnlyBlock; + bool OnlyUsedInOneBlock; + + Value *AllocaPointerVal; + + void clear() { + DefiningBlocks.clear(); + UsingBlocks.clear(); + OnlyStore = 0; + OnlyBlock = 0; + OnlyUsedInOneBlock = true; + AllocaPointerVal = 0; + } + + /// AnalyzeAlloca - Scan the uses of the specified alloca, filling in our + /// ivars. + void AnalyzeAlloca(AllocaInst *AI) { + clear(); + + // As we scan the uses of the alloca instruction, keep track of stores, + // and decide whether all of the loads and stores to the alloca are within + // the same basic block. + for (Value::use_iterator UI = AI->use_begin(), E = AI->use_end(); + UI != E;) { + Instruction *User = cast(*UI++); + if (BitCastInst *BC = dyn_cast(User)) { + // Remove any uses of this alloca in DbgInfoInstrinsics. + assert(BC->hasOneUse() && "Unexpected alloca uses!"); + DbgInfoIntrinsic *DI = cast(*BC->use_begin()); + DI->eraseFromParent(); + BC->eraseFromParent(); + continue; + } + + if (StoreInst *SI = dyn_cast(User)) { + // Remember the basic blocks which define new values for the alloca + DefiningBlocks.push_back(SI->getParent()); + AllocaPointerVal = SI->getOperand(0); + OnlyStore = SI; + } else { + LoadInst *LI = cast(User); + // Otherwise it must be a load instruction, keep track of variable + // reads. + UsingBlocks.push_back(LI->getParent()); + AllocaPointerVal = LI; + } + + if (OnlyUsedInOneBlock) { + if (OnlyBlock == 0) + OnlyBlock = User->getParent(); + else if (OnlyBlock != User->getParent()) + OnlyUsedInOneBlock = false; + } + } + } + }; +} // end of anonymous namespace + + +void PromoteMem2Reg::run() { + Function &F = *DF.getRoot()->getParent(); + + if (AST) PointerAllocaValues.resize(Allocas.size()); + + AllocaInfo Info; + LargeBlockInfo LBI; + + for (unsigned AllocaNum = 0; AllocaNum != Allocas.size(); ++AllocaNum) { + AllocaInst *AI = Allocas[AllocaNum]; + + assert(isAllocaPromotable(AI) && + "Cannot promote non-promotable alloca!"); + assert(AI->getParent()->getParent() == &F && + "All allocas should be in the same function, which is same as DF!"); + + if (AI->use_empty()) { + // If there are no uses of the alloca, just delete it now. + if (AST) AST->deleteValue(AI); + AI->eraseFromParent(); + + // Remove the alloca from the Allocas list, since it has been processed + RemoveFromAllocasList(AllocaNum); + ++NumDeadAlloca; + continue; + } + + // Calculate the set of read and write-locations for each alloca. This is + // analogous to finding the 'uses' and 'definitions' of each variable. + Info.AnalyzeAlloca(AI); + + // If there is only a single store to this value, replace any loads of + // it that are directly dominated by the definition with the value stored. + if (Info.DefiningBlocks.size() == 1) { + RewriteSingleStoreAlloca(AI, Info, LBI); + + // Finally, after the scan, check to see if the store is all that is left. + if (Info.UsingBlocks.empty()) { + // Remove the (now dead) store and alloca. + Info.OnlyStore->eraseFromParent(); + LBI.deleteValue(Info.OnlyStore); + + if (AST) AST->deleteValue(AI); + AI->eraseFromParent(); + LBI.deleteValue(AI); + + // The alloca has been processed, move on. + RemoveFromAllocasList(AllocaNum); + + ++NumSingleStore; + continue; + } + } + + // If the alloca is only read and written in one basic block, just perform a + // linear sweep over the block to eliminate it. + if (Info.OnlyUsedInOneBlock) { + PromoteSingleBlockAlloca(AI, Info, LBI); + + // Finally, after the scan, check to see if the stores are all that is + // left. + if (Info.UsingBlocks.empty()) { + + // Remove the (now dead) stores and alloca. + while (!AI->use_empty()) { + StoreInst *SI = cast(AI->use_back()); + SI->eraseFromParent(); + LBI.deleteValue(SI); + } + + if (AST) AST->deleteValue(AI); + AI->eraseFromParent(); + LBI.deleteValue(AI); + + // The alloca has been processed, move on. + RemoveFromAllocasList(AllocaNum); + + ++NumLocalPromoted; + continue; + } + } + + // If we haven't computed a numbering for the BB's in the function, do so + // now. + if (BBNumbers.empty()) { + unsigned ID = 0; + for (Function::iterator I = F.begin(), E = F.end(); I != E; ++I) + BBNumbers[I] = ID++; + } + + // If we have an AST to keep updated, remember some pointer value that is + // stored into the alloca. + if (AST) + PointerAllocaValues[AllocaNum] = Info.AllocaPointerVal; + + // Keep the reverse mapping of the 'Allocas' array for the rename pass. + AllocaLookup[Allocas[AllocaNum]] = AllocaNum; + + // At this point, we're committed to promoting the alloca using IDF's, and + // the standard SSA construction algorithm. Determine which blocks need PHI + // nodes and see if we can optimize out some work by avoiding insertion of + // dead phi nodes. + DetermineInsertionPoint(AI, AllocaNum, Info); + } + + if (Allocas.empty()) + return; // All of the allocas must have been trivial! + + LBI.clear(); + + + // Set the incoming values for the basic block to be null values for all of + // the alloca's. We do this in case there is a load of a value that has not + // been stored yet. In this case, it will get this null value. + // + RenamePassData::ValVector Values(Allocas.size()); + for (unsigned i = 0, e = Allocas.size(); i != e; ++i) + Values[i] = UndefValue::get(Allocas[i]->getAllocatedType()); + + // Walks all basic blocks in the function performing the SSA rename algorithm + // and inserting the phi nodes we marked as necessary + // + std::vector RenamePassWorkList; + RenamePassWorkList.push_back(RenamePassData(F.begin(), 0, Values)); + while (!RenamePassWorkList.empty()) { + RenamePassData RPD; + RPD.swap(RenamePassWorkList.back()); + RenamePassWorkList.pop_back(); + // RenamePass may add new worklist entries. + RenamePass(RPD.BB, RPD.Pred, RPD.Values, RenamePassWorkList); + } + + // The renamer uses the Visited set to avoid infinite loops. Clear it now. + Visited.clear(); + + // Remove the allocas themselves from the function. + for (unsigned i = 0, e = Allocas.size(); i != e; ++i) { + Instruction *A = Allocas[i]; + + // If there are any uses of the alloca instructions left, they must be in + // sections of dead code that were not processed on the dominance frontier. + // Just delete the users now. + // + if (!A->use_empty()) + A->replaceAllUsesWith(UndefValue::get(A->getType())); + if (AST) AST->deleteValue(A); + A->eraseFromParent(); + } + + + // Loop over all of the PHI nodes and see if there are any that we can get + // rid of because they merge all of the same incoming values. This can + // happen due to undef values coming into the PHI nodes. This process is + // iterative, because eliminating one PHI node can cause others to be removed. + bool EliminatedAPHI = true; + while (EliminatedAPHI) { + EliminatedAPHI = false; + + for (DenseMap, PHINode*>::iterator I = + NewPhiNodes.begin(), E = NewPhiNodes.end(); I != E;) { + PHINode *PN = I->second; + + // If this PHI node merges one value and/or undefs, get the value. + if (Value *V = PN->hasConstantValue(&DT)) { + if (AST && isa(PN->getType())) + AST->deleteValue(PN); + PN->replaceAllUsesWith(V); + PN->eraseFromParent(); + NewPhiNodes.erase(I++); + EliminatedAPHI = true; + continue; + } + ++I; + } + } + + // At this point, the renamer has added entries to PHI nodes for all reachable + // code. Unfortunately, there may be unreachable blocks which the renamer + // hasn't traversed. If this is the case, the PHI nodes may not + // have incoming values for all predecessors. Loop over all PHI nodes we have + // created, inserting undef values if they are missing any incoming values. + // + for (DenseMap, PHINode*>::iterator I = + NewPhiNodes.begin(), E = NewPhiNodes.end(); I != E; ++I) { + // We want to do this once per basic block. As such, only process a block + // when we find the PHI that is the first entry in the block. + PHINode *SomePHI = I->second; + BasicBlock *BB = SomePHI->getParent(); + if (&BB->front() != SomePHI) + continue; + + // Only do work here if there the PHI nodes are missing incoming values. We + // know that all PHI nodes that were inserted in a block will have the same + // number of incoming values, so we can just check any of them. + if (SomePHI->getNumIncomingValues() == getNumPreds(BB)) + continue; + + // Get the preds for BB. + SmallVector Preds(pred_begin(BB), pred_end(BB)); + + // Ok, now we know that all of the PHI nodes are missing entries for some + // basic blocks. Start by sorting the incoming predecessors for efficient + // access. + std::sort(Preds.begin(), Preds.end()); + + // Now we loop through all BB's which have entries in SomePHI and remove + // them from the Preds list. + for (unsigned i = 0, e = SomePHI->getNumIncomingValues(); i != e; ++i) { + // Do a log(n) search of the Preds list for the entry we want. + SmallVector::iterator EntIt = + std::lower_bound(Preds.begin(), Preds.end(), + SomePHI->getIncomingBlock(i)); + assert(EntIt != Preds.end() && *EntIt == SomePHI->getIncomingBlock(i)&& + "PHI node has entry for a block which is not a predecessor!"); + + // Remove the entry + Preds.erase(EntIt); + } + + // At this point, the blocks left in the preds list must have dummy + // entries inserted into every PHI nodes for the block. Update all the phi + // nodes in this block that we are inserting (there could be phis before + // mem2reg runs). + unsigned NumBadPreds = SomePHI->getNumIncomingValues(); + BasicBlock::iterator BBI = BB->begin(); + while ((SomePHI = dyn_cast(BBI++)) && + SomePHI->getNumIncomingValues() == NumBadPreds) { + Value *UndefVal = UndefValue::get(SomePHI->getType()); + for (unsigned pred = 0, e = Preds.size(); pred != e; ++pred) + SomePHI->addIncoming(UndefVal, Preds[pred]); + } + } + + NewPhiNodes.clear(); +} + + +/// ComputeLiveInBlocks - Determine which blocks the value is live in. These +/// are blocks which lead to uses. Knowing this allows us to avoid inserting +/// PHI nodes into blocks which don't lead to uses (thus, the inserted phi nodes +/// would be dead). +void PromoteMem2Reg:: +ComputeLiveInBlocks(AllocaInst *AI, AllocaInfo &Info, + const SmallPtrSet &DefBlocks, + SmallPtrSet &LiveInBlocks) { + + // To determine liveness, we must iterate through the predecessors of blocks + // where the def is live. Blocks are added to the worklist if we need to + // check their predecessors. Start with all the using blocks. + SmallVector LiveInBlockWorklist; + LiveInBlockWorklist.insert(LiveInBlockWorklist.end(), + Info.UsingBlocks.begin(), Info.UsingBlocks.end()); + + // If any of the using blocks is also a definition block, check to see if the + // definition occurs before or after the use. If it happens before the use, + // the value isn't really live-in. + for (unsigned i = 0, e = LiveInBlockWorklist.size(); i != e; ++i) { + BasicBlock *BB = LiveInBlockWorklist[i]; + if (!DefBlocks.count(BB)) continue; + + // Okay, this is a block that both uses and defines the value. If the first + // reference to the alloca is a def (store), then we know it isn't live-in. + for (BasicBlock::iterator I = BB->begin(); ; ++I) { + if (StoreInst *SI = dyn_cast(I)) { + if (SI->getOperand(1) != AI) continue; + + // We found a store to the alloca before a load. The alloca is not + // actually live-in here. + LiveInBlockWorklist[i] = LiveInBlockWorklist.back(); + LiveInBlockWorklist.pop_back(); + --i, --e; + break; + } + + if (LoadInst *LI = dyn_cast(I)) { + if (LI->getOperand(0) != AI) continue; + + // Okay, we found a load before a store to the alloca. It is actually + // live into this block. + break; + } + } + } + + // Now that we have a set of blocks where the phi is live-in, recursively add + // their predecessors until we find the full region the value is live. + while (!LiveInBlockWorklist.empty()) { + BasicBlock *BB = LiveInBlockWorklist.pop_back_val(); + + // The block really is live in here, insert it into the set. If already in + // the set, then it has already been processed. + if (!LiveInBlocks.insert(BB)) + continue; + + // Since the value is live into BB, it is either defined in a predecessor or + // live into it to. Add the preds to the worklist unless they are a + // defining block. + for (pred_iterator PI = pred_begin(BB), E = pred_end(BB); PI != E; ++PI) { + BasicBlock *P = *PI; + + // The value is not live into a predecessor if it defines the value. + if (DefBlocks.count(P)) + continue; + + // Otherwise it is, add to the worklist. + LiveInBlockWorklist.push_back(P); + } + } +} + +/// DetermineInsertionPoint - At this point, we're committed to promoting the +/// alloca using IDF's, and the standard SSA construction algorithm. Determine +/// which blocks need phi nodes and see if we can optimize out some work by +/// avoiding insertion of dead phi nodes. +void PromoteMem2Reg::DetermineInsertionPoint(AllocaInst *AI, unsigned AllocaNum, + AllocaInfo &Info) { + + // Unique the set of defining blocks for efficient lookup. + SmallPtrSet DefBlocks; + DefBlocks.insert(Info.DefiningBlocks.begin(), Info.DefiningBlocks.end()); + + // Determine which blocks the value is live in. These are blocks which lead + // to uses. + SmallPtrSet LiveInBlocks; + ComputeLiveInBlocks(AI, Info, DefBlocks, LiveInBlocks); + + // Compute the locations where PhiNodes need to be inserted. Look at the + // dominance frontier of EACH basic-block we have a write in. + unsigned CurrentVersion = 0; + SmallPtrSet InsertedPHINodes; + std::vector > DFBlocks; + while (!Info.DefiningBlocks.empty()) { + BasicBlock *BB = Info.DefiningBlocks.back(); + Info.DefiningBlocks.pop_back(); + + // Look up the DF for this write, add it to defining blocks. + DominanceFrontier::const_iterator it = DF.find(BB); + if (it == DF.end()) continue; + + const DominanceFrontier::DomSetType &S = it->second; + + // In theory we don't need the indirection through the DFBlocks vector. + // In practice, the order of calling QueuePhiNode would depend on the + // (unspecified) ordering of basic blocks in the dominance frontier, + // which would give PHI nodes non-determinstic subscripts. Fix this by + // processing blocks in order of the occurance in the function. + for (DominanceFrontier::DomSetType::const_iterator P = S.begin(), + PE = S.end(); P != PE; ++P) { + // If the frontier block is not in the live-in set for the alloca, don't + // bother processing it. + if (!LiveInBlocks.count(*P)) + continue; + + DFBlocks.push_back(std::make_pair(BBNumbers[*P], *P)); + } + + // Sort by which the block ordering in the function. + if (DFBlocks.size() > 1) + std::sort(DFBlocks.begin(), DFBlocks.end()); + + for (unsigned i = 0, e = DFBlocks.size(); i != e; ++i) { + BasicBlock *BB = DFBlocks[i].second; + if (QueuePhiNode(BB, AllocaNum, CurrentVersion, InsertedPHINodes)) + Info.DefiningBlocks.push_back(BB); + } + DFBlocks.clear(); + } +} + +/// RewriteSingleStoreAlloca - If there is only a single store to this value, +/// replace any loads of it that are directly dominated by the definition with +/// the value stored. +void PromoteMem2Reg::RewriteSingleStoreAlloca(AllocaInst *AI, + AllocaInfo &Info, + LargeBlockInfo &LBI) { + StoreInst *OnlyStore = Info.OnlyStore; + bool StoringGlobalVal = !isa(OnlyStore->getOperand(0)); + BasicBlock *StoreBB = OnlyStore->getParent(); + int StoreIndex = -1; + + // Clear out UsingBlocks. We will reconstruct it here if needed. + Info.UsingBlocks.clear(); + + for (Value::use_iterator UI = AI->use_begin(), E = AI->use_end(); UI != E; ) { + Instruction *UserInst = cast(*UI++); + if (!isa(UserInst)) { + assert(UserInst == OnlyStore && "Should only have load/stores"); + continue; + } + LoadInst *LI = cast(UserInst); + + // Okay, if we have a load from the alloca, we want to replace it with the + // only value stored to the alloca. We can do this if the value is + // dominated by the store. If not, we use the rest of the mem2reg machinery + // to insert the phi nodes as needed. + if (!StoringGlobalVal) { // Non-instructions are always dominated. + if (LI->getParent() == StoreBB) { + // If we have a use that is in the same block as the store, compare the + // indices of the two instructions to see which one came first. If the + // load came before the store, we can't handle it. + if (StoreIndex == -1) + StoreIndex = LBI.getInstructionIndex(OnlyStore); + + if (unsigned(StoreIndex) > LBI.getInstructionIndex(LI)) { + // Can't handle this load, bail out. + Info.UsingBlocks.push_back(StoreBB); + continue; + } + + } else if (LI->getParent() != StoreBB && + !dominates(StoreBB, LI->getParent())) { + // If the load and store are in different blocks, use BB dominance to + // check their relationships. If the store doesn't dom the use, bail + // out. + Info.UsingBlocks.push_back(LI->getParent()); + continue; + } + } + + // Otherwise, we *can* safely rewrite this load. + Value *ReplVal = OnlyStore->getOperand(0); + // If the replacement value is the load, this must occur in unreachable + // code. + if (ReplVal == LI) + ReplVal = UndefValue::get(LI->getType()); + LI->replaceAllUsesWith(ReplVal); + if (AST && isa(LI->getType())) + AST->deleteValue(LI); + LI->eraseFromParent(); + LBI.deleteValue(LI); + } +} + +namespace { + +/// StoreIndexSearchPredicate - This is a helper predicate used to search by the +/// first element of a pair. +struct StoreIndexSearchPredicate { + bool operator()(const std::pair &LHS, + const std::pair &RHS) { + return LHS.first < RHS.first; + } +}; + +} + +/// PromoteSingleBlockAlloca - Many allocas are only used within a single basic +/// block. If this is the case, avoid traversing the CFG and inserting a lot of +/// potentially useless PHI nodes by just performing a single linear pass over +/// the basic block using the Alloca. +/// +/// If we cannot promote this alloca (because it is read before it is written), +/// return true. This is necessary in cases where, due to control flow, the +/// alloca is potentially undefined on some control flow paths. e.g. code like +/// this is potentially correct: +/// +/// for (...) { if (c) { A = undef; undef = B; } } +/// +/// ... so long as A is not used before undef is set. +/// +void PromoteMem2Reg::PromoteSingleBlockAlloca(AllocaInst *AI, AllocaInfo &Info, + LargeBlockInfo &LBI) { + // The trickiest case to handle is when we have large blocks. Because of this, + // this code is optimized assuming that large blocks happen. This does not + // significantly pessimize the small block case. This uses LargeBlockInfo to + // make it efficient to get the index of various operations in the block. + + // Clear out UsingBlocks. We will reconstruct it here if needed. + Info.UsingBlocks.clear(); + + // Walk the use-def list of the alloca, getting the locations of all stores. + typedef SmallVector, 64> StoresByIndexTy; + StoresByIndexTy StoresByIndex; + + for (Value::use_iterator UI = AI->use_begin(), E = AI->use_end(); + UI != E; ++UI) + if (StoreInst *SI = dyn_cast(*UI)) + StoresByIndex.push_back(std::make_pair(LBI.getInstructionIndex(SI), SI)); + + // If there are no stores to the alloca, just replace any loads with undef. + if (StoresByIndex.empty()) { + for (Value::use_iterator UI = AI->use_begin(), E = AI->use_end(); UI != E;) + if (LoadInst *LI = dyn_cast(*UI++)) { + LI->replaceAllUsesWith(UndefValue::get(LI->getType())); + if (AST && isa(LI->getType())) + AST->deleteValue(LI); + LBI.deleteValue(LI); + LI->eraseFromParent(); + } + return; + } + + // Sort the stores by their index, making it efficient to do a lookup with a + // binary search. + std::sort(StoresByIndex.begin(), StoresByIndex.end()); + + // Walk all of the loads from this alloca, replacing them with the nearest + // store above them, if any. + for (Value::use_iterator UI = AI->use_begin(), E = AI->use_end(); UI != E;) { + LoadInst *LI = dyn_cast(*UI++); + if (!LI) continue; + + unsigned LoadIdx = LBI.getInstructionIndex(LI); + + // Find the nearest store that has a lower than this load. + StoresByIndexTy::iterator I = + std::lower_bound(StoresByIndex.begin(), StoresByIndex.end(), + std::pair(LoadIdx, 0), + StoreIndexSearchPredicate()); + + // If there is no store before this load, then we can't promote this load. + if (I == StoresByIndex.begin()) { + // Can't handle this load, bail out. + Info.UsingBlocks.push_back(LI->getParent()); + continue; + } + + // Otherwise, there was a store before this load, the load takes its value. + --I; + LI->replaceAllUsesWith(I->second->getOperand(0)); + if (AST && isa(LI->getType())) + AST->deleteValue(LI); + LI->eraseFromParent(); + LBI.deleteValue(LI); + } +} + + +// QueuePhiNode - queues a phi-node to be added to a basic-block for a specific +// Alloca returns true if there wasn't already a phi-node for that variable +// +bool PromoteMem2Reg::QueuePhiNode(BasicBlock *BB, unsigned AllocaNo, + unsigned &Version, + SmallPtrSet &InsertedPHINodes) { + // Look up the basic-block in question. + PHINode *&PN = NewPhiNodes[std::make_pair(BB, AllocaNo)]; + + // If the BB already has a phi node added for the i'th alloca then we're done! + if (PN) return false; + + // Create a PhiNode using the dereferenced type... and add the phi-node to the + // BasicBlock. + PN = PHINode::Create(Allocas[AllocaNo]->getAllocatedType(), + Allocas[AllocaNo]->getName() + "." + Twine(Version++), + BB->begin()); + ++NumPHIInsert; + PhiToAllocaMap[PN] = AllocaNo; + PN->reserveOperandSpace(getNumPreds(BB)); + + InsertedPHINodes.insert(PN); + + if (AST && isa(PN->getType())) + AST->copyValue(PointerAllocaValues[AllocaNo], PN); + + return true; +} + +// RenamePass - Recursively traverse the CFG of the function, renaming loads and +// stores to the allocas which we are promoting. IncomingVals indicates what +// value each Alloca contains on exit from the predecessor block Pred. +// +void PromoteMem2Reg::RenamePass(BasicBlock *BB, BasicBlock *Pred, + RenamePassData::ValVector &IncomingVals, + std::vector &Worklist) { +NextIteration: + // If we are inserting any phi nodes into this BB, they will already be in the + // block. + if (PHINode *APN = dyn_cast(BB->begin())) { + // If we have PHI nodes to update, compute the number of edges from Pred to + // BB. + if (PhiToAllocaMap.count(APN)) { + // We want to be able to distinguish between PHI nodes being inserted by + // this invocation of mem2reg from those phi nodes that already existed in + // the IR before mem2reg was run. We determine that APN is being inserted + // because it is missing incoming edges. All other PHI nodes being + // inserted by this pass of mem2reg will have the same number of incoming + // operands so far. Remember this count. + unsigned NewPHINumOperands = APN->getNumOperands(); + + unsigned NumEdges = 0; + for (succ_iterator I = succ_begin(Pred), E = succ_end(Pred); I != E; ++I) + if (*I == BB) + ++NumEdges; + assert(NumEdges && "Must be at least one edge from Pred to BB!"); + + // Add entries for all the phis. + BasicBlock::iterator PNI = BB->begin(); + do { + unsigned AllocaNo = PhiToAllocaMap[APN]; + + // Add N incoming values to the PHI node. + for (unsigned i = 0; i != NumEdges; ++i) + APN->addIncoming(IncomingVals[AllocaNo], Pred); + + // The currently active variable for this block is now the PHI. + IncomingVals[AllocaNo] = APN; + + // Get the next phi node. + ++PNI; + APN = dyn_cast(PNI); + if (APN == 0) break; + + // Verify that it is missing entries. If not, it is not being inserted + // by this mem2reg invocation so we want to ignore it. + } while (APN->getNumOperands() == NewPHINumOperands); + } + } + + // Don't revisit blocks. + if (!Visited.insert(BB)) return; + + for (BasicBlock::iterator II = BB->begin(); !isa(II); ) { + Instruction *I = II++; // get the instruction, increment iterator + + if (LoadInst *LI = dyn_cast(I)) { + AllocaInst *Src = dyn_cast(LI->getPointerOperand()); + if (!Src) continue; + + std::map::iterator AI = AllocaLookup.find(Src); + if (AI == AllocaLookup.end()) continue; + + Value *V = IncomingVals[AI->second]; + + // Anything using the load now uses the current value. + LI->replaceAllUsesWith(V); + if (AST && isa(LI->getType())) + AST->deleteValue(LI); + BB->getInstList().erase(LI); + } else if (StoreInst *SI = dyn_cast(I)) { + // Delete this instruction and mark the name as the current holder of the + // value + AllocaInst *Dest = dyn_cast(SI->getPointerOperand()); + if (!Dest) continue; + + std::map::iterator ai = AllocaLookup.find(Dest); + if (ai == AllocaLookup.end()) + continue; + + // what value were we writing? + IncomingVals[ai->second] = SI->getOperand(0); + BB->getInstList().erase(SI); + } + } + + // 'Recurse' to our successors. + succ_iterator I = succ_begin(BB), E = succ_end(BB); + if (I == E) return; + + // Keep track of the successors so we don't visit the same successor twice + SmallPtrSet VisitedSuccs; + + // Handle the first successor without using the worklist. + VisitedSuccs.insert(*I); + Pred = BB; + BB = *I; + ++I; + + for (; I != E; ++I) + if (VisitedSuccs.insert(*I)) + Worklist.push_back(RenamePassData(*I, Pred, IncomingVals)); + + goto NextIteration; +} + +/// PromoteMemToReg - Promote the specified list of alloca instructions into +/// scalar registers, inserting PHI nodes as appropriate. This function makes +/// use of DominanceFrontier information. This function does not modify the CFG +/// of the function at all. All allocas must be from the same function. +/// +/// If AST is specified, the specified tracker is updated to reflect changes +/// made to the IR. +/// +void llvm::PromoteMemToReg(const std::vector &Allocas, + DominatorTree &DT, DominanceFrontier &DF, + AliasSetTracker *AST) { + // If there is nothing to do, bail out... + if (Allocas.empty()) return; + + PromoteMem2Reg(Allocas, DT, DF, AST).run(); +} diff --git a/libclamav/c++/llvm/lib/Transforms/Utils/SSAUpdater.cpp b/libclamav/c++/llvm/lib/Transforms/Utils/SSAUpdater.cpp new file mode 100644 index 000000000..8a07c35f3 --- /dev/null +++ b/libclamav/c++/llvm/lib/Transforms/Utils/SSAUpdater.cpp @@ -0,0 +1,336 @@ +//===- SSAUpdater.cpp - Unstructured SSA Update Tool ----------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the SSAUpdater class. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Transforms/Utils/SSAUpdater.h" +#include "llvm/Instructions.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/Support/CFG.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ValueHandle.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +typedef DenseMap > AvailableValsTy; +typedef std::vector > > + IncomingPredInfoTy; + +static AvailableValsTy &getAvailableVals(void *AV) { + return *static_cast(AV); +} + +static IncomingPredInfoTy &getIncomingPredInfo(void *IPI) { + return *static_cast(IPI); +} + + +SSAUpdater::SSAUpdater(SmallVectorImpl *NewPHI) + : AV(0), PrototypeValue(0), IPI(0), InsertedPHIs(NewPHI) {} + +SSAUpdater::~SSAUpdater() { + delete &getAvailableVals(AV); + delete &getIncomingPredInfo(IPI); +} + +/// Initialize - Reset this object to get ready for a new set of SSA +/// updates. ProtoValue is the value used to name PHI nodes. +void SSAUpdater::Initialize(Value *ProtoValue) { + if (AV == 0) + AV = new AvailableValsTy(); + else + getAvailableVals(AV).clear(); + + if (IPI == 0) + IPI = new IncomingPredInfoTy(); + else + getIncomingPredInfo(IPI).clear(); + PrototypeValue = ProtoValue; +} + +/// HasValueForBlock - Return true if the SSAUpdater already has a value for +/// the specified block. +bool SSAUpdater::HasValueForBlock(BasicBlock *BB) const { + return getAvailableVals(AV).count(BB); +} + +/// AddAvailableValue - Indicate that a rewritten value is available in the +/// specified block with the specified value. +void SSAUpdater::AddAvailableValue(BasicBlock *BB, Value *V) { + assert(PrototypeValue != 0 && "Need to initialize SSAUpdater"); + assert(PrototypeValue->getType() == V->getType() && + "All rewritten values must have the same type"); + getAvailableVals(AV)[BB] = V; +} + +/// GetValueAtEndOfBlock - Construct SSA form, materializing a value that is +/// live at the end of the specified block. +Value *SSAUpdater::GetValueAtEndOfBlock(BasicBlock *BB) { + assert(getIncomingPredInfo(IPI).empty() && "Unexpected Internal State"); + Value *Res = GetValueAtEndOfBlockInternal(BB); + assert(getIncomingPredInfo(IPI).empty() && "Unexpected Internal State"); + return Res; +} + +/// GetValueInMiddleOfBlock - Construct SSA form, materializing a value that +/// is live in the middle of the specified block. +/// +/// GetValueInMiddleOfBlock is the same as GetValueAtEndOfBlock except in one +/// important case: if there is a definition of the rewritten value after the +/// 'use' in BB. Consider code like this: +/// +/// X1 = ... +/// SomeBB: +/// use(X) +/// X2 = ... +/// br Cond, SomeBB, OutBB +/// +/// In this case, there are two values (X1 and X2) added to the AvailableVals +/// set by the client of the rewriter, and those values are both live out of +/// their respective blocks. However, the use of X happens in the *middle* of +/// a block. Because of this, we need to insert a new PHI node in SomeBB to +/// merge the appropriate values, and this value isn't live out of the block. +/// +Value *SSAUpdater::GetValueInMiddleOfBlock(BasicBlock *BB) { + // If there is no definition of the renamed variable in this block, just use + // GetValueAtEndOfBlock to do our work. + if (!getAvailableVals(AV).count(BB)) + return GetValueAtEndOfBlock(BB); + + // Otherwise, we have the hard case. Get the live-in values for each + // predecessor. + SmallVector, 8> PredValues; + Value *SingularValue = 0; + + // We can get our predecessor info by walking the pred_iterator list, but it + // is relatively slow. If we already have PHI nodes in this block, walk one + // of them to get the predecessor list instead. + if (PHINode *SomePhi = dyn_cast(BB->begin())) { + for (unsigned i = 0, e = SomePhi->getNumIncomingValues(); i != e; ++i) { + BasicBlock *PredBB = SomePhi->getIncomingBlock(i); + Value *PredVal = GetValueAtEndOfBlock(PredBB); + PredValues.push_back(std::make_pair(PredBB, PredVal)); + + // Compute SingularValue. + if (i == 0) + SingularValue = PredVal; + else if (PredVal != SingularValue) + SingularValue = 0; + } + } else { + bool isFirstPred = true; + for (pred_iterator PI = pred_begin(BB), E = pred_end(BB); PI != E; ++PI) { + BasicBlock *PredBB = *PI; + Value *PredVal = GetValueAtEndOfBlock(PredBB); + PredValues.push_back(std::make_pair(PredBB, PredVal)); + + // Compute SingularValue. + if (isFirstPred) { + SingularValue = PredVal; + isFirstPred = false; + } else if (PredVal != SingularValue) + SingularValue = 0; + } + } + + // If there are no predecessors, just return undef. + if (PredValues.empty()) + return UndefValue::get(PrototypeValue->getType()); + + // Otherwise, if all the merged values are the same, just use it. + if (SingularValue != 0) + return SingularValue; + + // Otherwise, we do need a PHI: insert one now. + PHINode *InsertedPHI = PHINode::Create(PrototypeValue->getType(), + PrototypeValue->getName(), + &BB->front()); + InsertedPHI->reserveOperandSpace(PredValues.size()); + + // Fill in all the predecessors of the PHI. + for (unsigned i = 0, e = PredValues.size(); i != e; ++i) + InsertedPHI->addIncoming(PredValues[i].second, PredValues[i].first); + + // See if the PHI node can be merged to a single value. This can happen in + // loop cases when we get a PHI of itself and one other value. + if (Value *ConstVal = InsertedPHI->hasConstantValue()) { + InsertedPHI->eraseFromParent(); + return ConstVal; + } + + // If the client wants to know about all new instructions, tell it. + if (InsertedPHIs) InsertedPHIs->push_back(InsertedPHI); + + DEBUG(errs() << " Inserted PHI: " << *InsertedPHI << "\n"); + return InsertedPHI; +} + +/// RewriteUse - Rewrite a use of the symbolic value. This handles PHI nodes, +/// which use their value in the corresponding predecessor. +void SSAUpdater::RewriteUse(Use &U) { + Instruction *User = cast(U.getUser()); + + Value *V; + if (PHINode *UserPN = dyn_cast(User)) + V = GetValueAtEndOfBlock(UserPN->getIncomingBlock(U)); + else + V = GetValueInMiddleOfBlock(User->getParent()); + + U.set(V); +} + + +/// GetValueAtEndOfBlockInternal - Check to see if AvailableVals has an entry +/// for the specified BB and if so, return it. If not, construct SSA form by +/// walking predecessors inserting PHI nodes as needed until we get to a block +/// where the value is available. +/// +Value *SSAUpdater::GetValueAtEndOfBlockInternal(BasicBlock *BB) { + AvailableValsTy &AvailableVals = getAvailableVals(AV); + + // Query AvailableVals by doing an insertion of null. + std::pair InsertRes = + AvailableVals.insert(std::make_pair(BB, WeakVH())); + + // Handle the case when the insertion fails because we have already seen BB. + if (!InsertRes.second) { + // If the insertion failed, there are two cases. The first case is that the + // value is already available for the specified block. If we get this, just + // return the value. + if (InsertRes.first->second != 0) + return InsertRes.first->second; + + // Otherwise, if the value we find is null, then this is the value is not + // known but it is being computed elsewhere in our recursion. This means + // that we have a cycle. Handle this by inserting a PHI node and returning + // it. When we get back to the first instance of the recursion we will fill + // in the PHI node. + return InsertRes.first->second = + PHINode::Create(PrototypeValue->getType(), PrototypeValue->getName(), + &BB->front()); + } + + // Okay, the value isn't in the map and we just inserted a null in the entry + // to indicate that we're processing the block. Since we have no idea what + // value is in this block, we have to recurse through our predecessors. + // + // While we're walking our predecessors, we keep track of them in a vector, + // then insert a PHI node in the end if we actually need one. We could use a + // smallvector here, but that would take a lot of stack space for every level + // of the recursion, just use IncomingPredInfo as an explicit stack. + IncomingPredInfoTy &IncomingPredInfo = getIncomingPredInfo(IPI); + unsigned FirstPredInfoEntry = IncomingPredInfo.size(); + + // As we're walking the predecessors, keep track of whether they are all + // producing the same value. If so, this value will capture it, if not, it + // will get reset to null. We distinguish the no-predecessor case explicitly + // below. + TrackingVH SingularValue; + + // We can get our predecessor info by walking the pred_iterator list, but it + // is relatively slow. If we already have PHI nodes in this block, walk one + // of them to get the predecessor list instead. + if (PHINode *SomePhi = dyn_cast(BB->begin())) { + for (unsigned i = 0, e = SomePhi->getNumIncomingValues(); i != e; ++i) { + BasicBlock *PredBB = SomePhi->getIncomingBlock(i); + Value *PredVal = GetValueAtEndOfBlockInternal(PredBB); + IncomingPredInfo.push_back(std::make_pair(PredBB, PredVal)); + + // Compute SingularValue. + if (i == 0) + SingularValue = PredVal; + else if (PredVal != SingularValue) + SingularValue = 0; + } + } else { + bool isFirstPred = true; + for (pred_iterator PI = pred_begin(BB), E = pred_end(BB); PI != E; ++PI) { + BasicBlock *PredBB = *PI; + Value *PredVal = GetValueAtEndOfBlockInternal(PredBB); + IncomingPredInfo.push_back(std::make_pair(PredBB, PredVal)); + + // Compute SingularValue. + if (isFirstPred) { + SingularValue = PredVal; + isFirstPred = false; + } else if (PredVal != SingularValue) + SingularValue = 0; + } + } + + // If there are no predecessors, then we must have found an unreachable block + // just return 'undef'. Since there are no predecessors, InsertRes must not + // be invalidated. + if (IncomingPredInfo.size() == FirstPredInfoEntry) + return InsertRes.first->second = UndefValue::get(PrototypeValue->getType()); + + /// Look up BB's entry in AvailableVals. 'InsertRes' may be invalidated. If + /// this block is involved in a loop, a no-entry PHI node will have been + /// inserted as InsertedVal. Otherwise, we'll still have the null we inserted + /// above. + TrackingVH &InsertedVal = AvailableVals[BB]; + + // If all the predecessor values are the same then we don't need to insert a + // PHI. This is the simple and common case. + if (SingularValue) { + // If a PHI node got inserted, replace it with the singlar value and delete + // it. + if (InsertedVal) { + PHINode *OldVal = cast(InsertedVal); + // Be careful about dead loops. These RAUW's also update InsertedVal. + if (InsertedVal != SingularValue) + OldVal->replaceAllUsesWith(SingularValue); + else + OldVal->replaceAllUsesWith(UndefValue::get(InsertedVal->getType())); + OldVal->eraseFromParent(); + } else { + InsertedVal = SingularValue; + } + + // Drop the entries we added in IncomingPredInfo to restore the stack. + IncomingPredInfo.erase(IncomingPredInfo.begin()+FirstPredInfoEntry, + IncomingPredInfo.end()); + return InsertedVal; + } + + // Otherwise, we do need a PHI: insert one now if we don't already have one. + if (InsertedVal == 0) + InsertedVal = PHINode::Create(PrototypeValue->getType(), + PrototypeValue->getName(), &BB->front()); + + PHINode *InsertedPHI = cast(InsertedVal); + InsertedPHI->reserveOperandSpace(IncomingPredInfo.size()-FirstPredInfoEntry); + + // Fill in all the predecessors of the PHI. + for (IncomingPredInfoTy::iterator I = + IncomingPredInfo.begin()+FirstPredInfoEntry, + E = IncomingPredInfo.end(); I != E; ++I) + InsertedPHI->addIncoming(I->second, I->first); + + // Drop the entries we added in IncomingPredInfo to restore the stack. + IncomingPredInfo.erase(IncomingPredInfo.begin()+FirstPredInfoEntry, + IncomingPredInfo.end()); + + // See if the PHI node can be merged to a single value. This can happen in + // loop cases when we get a PHI of itself and one other value. + if (Value *ConstVal = InsertedPHI->hasConstantValue()) { + InsertedPHI->replaceAllUsesWith(ConstVal); + InsertedPHI->eraseFromParent(); + InsertedVal = ConstVal; + } else { + DEBUG(errs() << " Inserted PHI: " << *InsertedPHI << "\n"); + + // If the client wants to know about all new instructions, tell it. + if (InsertedPHIs) InsertedPHIs->push_back(InsertedPHI); + } + + return InsertedVal; +} diff --git a/libclamav/c++/llvm/lib/Transforms/Utils/SSI.cpp b/libclamav/c++/llvm/lib/Transforms/Utils/SSI.cpp new file mode 100644 index 000000000..1c4afffeb --- /dev/null +++ b/libclamav/c++/llvm/lib/Transforms/Utils/SSI.cpp @@ -0,0 +1,432 @@ +//===------------------- SSI.cpp - Creates SSI Representation -------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This pass converts a list of variables to the Static Single Information +// form. This is a program representation described by Scott Ananian in his +// Master Thesis: "The Static Single Information Form (1999)". +// We are building an on-demand representation, that is, we do not convert +// every single variable in the target function to SSI form. Rather, we receive +// a list of target variables that must be converted. We also do not +// completely convert a target variable to the SSI format. Instead, we only +// change the variable in the points where new information can be attached +// to its live range, that is, at branch points. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "ssi" + +#include "llvm/Transforms/Scalar.h" +#include "llvm/Transforms/Utils/SSI.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/Analysis/Dominators.h" + +using namespace llvm; + +static const std::string SSI_PHI = "SSI_phi"; +static const std::string SSI_SIG = "SSI_sigma"; + +STATISTIC(NumSigmaInserted, "Number of sigma functions inserted"); +STATISTIC(NumPhiInserted, "Number of phi functions inserted"); + +void SSI::getAnalysisUsage(AnalysisUsage &AU) const { + AU.addRequiredTransitive(); + AU.addRequiredTransitive(); + AU.setPreservesAll(); +} + +bool SSI::runOnFunction(Function &F) { + DT_ = &getAnalysis(); + return false; +} + +/// This methods creates the SSI representation for the list of values +/// received. It will only create SSI representation if a value is used +/// to decide a branch. Repeated values are created only once. +/// +void SSI::createSSI(SmallVectorImpl &value) { + init(value); + + SmallPtrSet needConstruction; + for (SmallVectorImpl::iterator I = value.begin(), + E = value.end(); I != E; ++I) + if (created.insert(*I)) + needConstruction.insert(*I); + + insertSigmaFunctions(needConstruction); + + // Test if there is a need to transform to SSI + if (!needConstruction.empty()) { + insertPhiFunctions(needConstruction); + renameInit(needConstruction); + rename(DT_->getRoot()); + fixPhis(); + } + + clean(); +} + +/// Insert sigma functions (a sigma function is a phi function with one +/// operator) +/// +void SSI::insertSigmaFunctions(SmallPtrSet &value) { + for (SmallPtrSet::iterator I = value.begin(), + E = value.end(); I != E; ++I) { + for (Value::use_iterator begin = (*I)->use_begin(), + end = (*I)->use_end(); begin != end; ++begin) { + // Test if the Use of the Value is in a comparator + if (CmpInst *CI = dyn_cast(begin)) { + // Iterates through all uses of CmpInst + for (Value::use_iterator begin_ci = CI->use_begin(), + end_ci = CI->use_end(); begin_ci != end_ci; ++begin_ci) { + // Test if any use of CmpInst is in a Terminator + if (TerminatorInst *TI = dyn_cast(begin_ci)) { + insertSigma(TI, *I); + } + } + } + } + } +} + +/// Inserts Sigma Functions in every BasicBlock successor to Terminator +/// Instruction TI. All inserted Sigma Function are related to Instruction I. +/// +void SSI::insertSigma(TerminatorInst *TI, Instruction *I) { + // Basic Block of the Terminator Instruction + BasicBlock *BB = TI->getParent(); + for (unsigned i = 0, e = TI->getNumSuccessors(); i < e; ++i) { + // Next Basic Block + BasicBlock *BB_next = TI->getSuccessor(i); + if (BB_next != BB && + BB_next->getSinglePredecessor() != NULL && + dominateAny(BB_next, I)) { + PHINode *PN = PHINode::Create(I->getType(), SSI_SIG, BB_next->begin()); + PN->addIncoming(I, BB); + sigmas[PN] = I; + created.insert(PN); + defsites[I].push_back(BB_next); + ++NumSigmaInserted; + } + } +} + +/// Insert phi functions when necessary +/// +void SSI::insertPhiFunctions(SmallPtrSet &value) { + DominanceFrontier *DF = &getAnalysis(); + for (SmallPtrSet::iterator I = value.begin(), + E = value.end(); I != E; ++I) { + // Test if there were any sigmas for this variable + SmallPtrSet BB_visited; + + // Insert phi functions if there is any sigma function + while (!defsites[*I].empty()) { + + BasicBlock *BB = defsites[*I].back(); + + defsites[*I].pop_back(); + DominanceFrontier::iterator DF_BB = DF->find(BB); + + // The BB is unreachable. Skip it. + if (DF_BB == DF->end()) + continue; + + // Iterates through all the dominance frontier of BB + for (std::set::iterator DF_BB_begin = + DF_BB->second.begin(), DF_BB_end = DF_BB->second.end(); + DF_BB_begin != DF_BB_end; ++DF_BB_begin) { + BasicBlock *BB_dominated = *DF_BB_begin; + + // Test if has not yet visited this node and if the + // original definition dominates this node + if (BB_visited.insert(BB_dominated) && + DT_->properlyDominates(value_original[*I], BB_dominated) && + dominateAny(BB_dominated, *I)) { + PHINode *PN = PHINode::Create( + (*I)->getType(), SSI_PHI, BB_dominated->begin()); + phis.insert(std::make_pair(PN, *I)); + created.insert(PN); + + defsites[*I].push_back(BB_dominated); + ++NumPhiInserted; + } + } + } + BB_visited.clear(); + } +} + +/// Some initialization for the rename part +/// +void SSI::renameInit(SmallPtrSet &value) { + for (SmallPtrSet::iterator I = value.begin(), + E = value.end(); I != E; ++I) + value_stack[*I].push_back(*I); +} + +/// Renames all variables in the specified BasicBlock. +/// Only variables that need to be rename will be. +/// +void SSI::rename(BasicBlock *BB) { + SmallPtrSet defined; + + // Iterate through instructions and make appropriate renaming. + // For SSI_PHI (b = PHI()), store b at value_stack as a new + // definition of the variable it represents. + // For SSI_SIG (b = PHI(a)), substitute a with the current + // value of a, present in the value_stack. + // Then store bin the value_stack as the new definition of a. + // For all other instructions (b = OP(a, c, d, ...)), we need to substitute + // all operands with its current value, present in value_stack. + for (BasicBlock::iterator begin = BB->begin(), end = BB->end(); + begin != end; ++begin) { + Instruction *I = begin; + if (PHINode *PN = dyn_cast(I)) { // Treat PHI functions + Instruction* position; + + // Treat SSI_PHI + if ((position = getPositionPhi(PN))) { + value_stack[position].push_back(PN); + defined.insert(position); + // Treat SSI_SIG + } else if ((position = getPositionSigma(PN))) { + substituteUse(I); + value_stack[position].push_back(PN); + defined.insert(position); + } + + // Treat all other PHI functions + else { + substituteUse(I); + } + } + + // Treat all other functions + else { + substituteUse(I); + } + } + + // This loop iterates in all BasicBlocks that are successors of the current + // BasicBlock. For each SSI_PHI instruction found, insert an operand. + // This operand is the current operand in value_stack for the variable + // in "position". And the BasicBlock this operand represents is the current + // BasicBlock. + for (succ_iterator SI = succ_begin(BB), SE = succ_end(BB); SI != SE; ++SI) { + BasicBlock *BB_succ = *SI; + + for (BasicBlock::iterator begin = BB_succ->begin(), + notPhi = BB_succ->getFirstNonPHI(); begin != *notPhi; ++begin) { + Instruction *I = begin; + PHINode *PN = dyn_cast(I); + Instruction* position; + if (PN && ((position = getPositionPhi(PN)))) { + PN->addIncoming(value_stack[position].back(), BB); + } + } + } + + // This loop calls rename on all children from this block. This time children + // refers to a successor block in the dominance tree. + DomTreeNode *DTN = DT_->getNode(BB); + for (DomTreeNode::iterator begin = DTN->begin(), end = DTN->end(); + begin != end; ++begin) { + DomTreeNodeBase *DTN_children = *begin; + BasicBlock *BB_children = DTN_children->getBlock(); + rename(BB_children); + } + + // Now we remove all inserted definitions of a variable from the top of + // the stack leaving the previous one as the top. + for (SmallPtrSet::iterator DI = defined.begin(), + DE = defined.end(); DI != DE; ++DI) + value_stack[*DI].pop_back(); +} + +/// Substitute any use in this instruction for the last definition of +/// the variable +/// +void SSI::substituteUse(Instruction *I) { + for (unsigned i = 0, e = I->getNumOperands(); i < e; ++i) { + Value *operand = I->getOperand(i); + for (DenseMap >::iterator + VI = value_stack.begin(), VE = value_stack.end(); VI != VE; ++VI) { + if (operand == VI->second.front() && + I != VI->second.back()) { + PHINode *PN_I = dyn_cast(I); + PHINode *PN_vs = dyn_cast(VI->second.back()); + + // If a phi created in a BasicBlock is used as an operand of another + // created in the same BasicBlock, this step marks this second phi, + // to fix this issue later. It cannot be fixed now, because the + // operands of the first phi are not final yet. + if (PN_I && PN_vs && + VI->second.back()->getParent() == I->getParent()) { + + phisToFix.insert(PN_I); + } + + I->setOperand(i, VI->second.back()); + break; + } + } + } +} + +/// Test if the BasicBlock BB dominates any use or definition of value. +/// If it dominates a phi instruction that is on the same BasicBlock, +/// that does not count. +/// +bool SSI::dominateAny(BasicBlock *BB, Instruction *value) { + for (Value::use_iterator begin = value->use_begin(), + end = value->use_end(); begin != end; ++begin) { + Instruction *I = cast(*begin); + BasicBlock *BB_father = I->getParent(); + if (BB == BB_father && isa(I)) + continue; + if (DT_->dominates(BB, BB_father)) { + return true; + } + } + return false; +} + +/// When there is a phi node that is created in a BasicBlock and it is used +/// as an operand of another phi function used in the same BasicBlock, +/// LLVM looks this as an error. So on the second phi, the first phi is called +/// P and the BasicBlock it incomes is B. This P will be replaced by the value +/// it has for BasicBlock B. It also includes undef values for predecessors +/// that were not included in the phi. +/// +void SSI::fixPhis() { + for (SmallPtrSet::iterator begin = phisToFix.begin(), + end = phisToFix.end(); begin != end; ++begin) { + PHINode *PN = *begin; + for (unsigned i = 0, e = PN->getNumIncomingValues(); i < e; ++i) { + PHINode *PN_father = dyn_cast(PN->getIncomingValue(i)); + if (PN_father && PN->getParent() == PN_father->getParent() && + !DT_->dominates(PN->getParent(), PN->getIncomingBlock(i))) { + BasicBlock *BB = PN->getIncomingBlock(i); + int pos = PN_father->getBasicBlockIndex(BB); + PN->setIncomingValue(i, PN_father->getIncomingValue(pos)); + } + } + } + + for (DenseMapIterator begin = phis.begin(), + end = phis.end(); begin != end; ++begin) { + PHINode *PN = begin->first; + BasicBlock *BB = PN->getParent(); + pred_iterator PI = pred_begin(BB), PE = pred_end(BB); + SmallVector Preds(PI, PE); + for (unsigned size = Preds.size(); + PI != PE && PN->getNumIncomingValues() != size; ++PI) { + bool found = false; + for (unsigned i = 0, pn_end = PN->getNumIncomingValues(); + i < pn_end; ++i) { + if (PN->getIncomingBlock(i) == *PI) { + found = true; + break; + } + } + if (!found) { + PN->addIncoming(UndefValue::get(PN->getType()), *PI); + } + } + } +} + +/// Return which variable (position on the vector of variables) this phi +/// represents on the phis list. +/// +Instruction* SSI::getPositionPhi(PHINode *PN) { + DenseMap::iterator val = phis.find(PN); + if (val == phis.end()) + return 0; + else + return val->second; +} + +/// Return which variable (position on the vector of variables) this phi +/// represents on the sigmas list. +/// +Instruction* SSI::getPositionSigma(PHINode *PN) { + DenseMap::iterator val = sigmas.find(PN); + if (val == sigmas.end()) + return 0; + else + return val->second; +} + +/// Initializes +/// +void SSI::init(SmallVectorImpl &value) { + for (SmallVectorImpl::iterator I = value.begin(), + E = value.end(); I != E; ++I) { + value_original[*I] = (*I)->getParent(); + defsites[*I].push_back((*I)->getParent()); + } +} + +/// Clean all used resources in this creation of SSI +/// +void SSI::clean() { + phis.clear(); + sigmas.clear(); + phisToFix.clear(); + + defsites.clear(); + value_stack.clear(); + value_original.clear(); +} + +/// createSSIPass - The public interface to this file... +/// +FunctionPass *llvm::createSSIPass() { return new SSI(); } + +char SSI::ID = 0; +static RegisterPass X("ssi", "Static Single Information Construction"); + +/// SSIEverything - A pass that runs createSSI on every non-void variable, +/// intended for debugging. +namespace { + struct SSIEverything : public FunctionPass { + static char ID; // Pass identification, replacement for typeid + SSIEverything() : FunctionPass(&ID) {} + + bool runOnFunction(Function &F); + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.addRequired(); + } + }; +} + +bool SSIEverything::runOnFunction(Function &F) { + SmallVector Insts; + SSI &ssi = getAnalysis(); + + if (F.isDeclaration() || F.isIntrinsic()) return false; + + for (Function::iterator B = F.begin(), BE = F.end(); B != BE; ++B) + for (BasicBlock::iterator I = B->begin(), E = B->end(); I != E; ++I) + if (I->getType() != Type::getVoidTy(F.getContext())) + Insts.push_back(I); + + ssi.createSSI(Insts); + return true; +} + +/// createSSIEverythingPass - The public interface to this file... +/// +FunctionPass *llvm::createSSIEverythingPass() { return new SSIEverything(); } + +char SSIEverything::ID = 0; +static RegisterPass +Y("ssi-everything", "Static Single Information Construction"); diff --git a/libclamav/c++/llvm/lib/Transforms/Utils/SimplifyCFG.cpp b/libclamav/c++/llvm/lib/Transforms/Utils/SimplifyCFG.cpp new file mode 100644 index 000000000..89b0bd9b3 --- /dev/null +++ b/libclamav/c++/llvm/lib/Transforms/Utils/SimplifyCFG.cpp @@ -0,0 +1,2107 @@ +//===- SimplifyCFG.cpp - Code to perform CFG simplification ---------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Peephole optimize the CFG. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "simplifycfg" +#include "llvm/Transforms/Utils/Local.h" +#include "llvm/Constants.h" +#include "llvm/Instructions.h" +#include "llvm/IntrinsicInst.h" +#include "llvm/Type.h" +#include "llvm/DerivedTypes.h" +#include "llvm/GlobalVariable.h" +#include "llvm/Support/CFG.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Analysis/ConstantFolding.h" +#include "llvm/Transforms/Utils/BasicBlockUtils.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/Statistic.h" +#include +#include +#include +#include +using namespace llvm; + +STATISTIC(NumSpeculations, "Number of speculative executed instructions"); + +/// SafeToMergeTerminators - Return true if it is safe to merge these two +/// terminator instructions together. +/// +static bool SafeToMergeTerminators(TerminatorInst *SI1, TerminatorInst *SI2) { + if (SI1 == SI2) return false; // Can't merge with self! + + // It is not safe to merge these two switch instructions if they have a common + // successor, and if that successor has a PHI node, and if *that* PHI node has + // conflicting incoming values from the two switch blocks. + BasicBlock *SI1BB = SI1->getParent(); + BasicBlock *SI2BB = SI2->getParent(); + SmallPtrSet SI1Succs(succ_begin(SI1BB), succ_end(SI1BB)); + + for (succ_iterator I = succ_begin(SI2BB), E = succ_end(SI2BB); I != E; ++I) + if (SI1Succs.count(*I)) + for (BasicBlock::iterator BBI = (*I)->begin(); + isa(BBI); ++BBI) { + PHINode *PN = cast(BBI); + if (PN->getIncomingValueForBlock(SI1BB) != + PN->getIncomingValueForBlock(SI2BB)) + return false; + } + + return true; +} + +/// AddPredecessorToBlock - Update PHI nodes in Succ to indicate that there will +/// now be entries in it from the 'NewPred' block. The values that will be +/// flowing into the PHI nodes will be the same as those coming in from +/// ExistPred, an existing predecessor of Succ. +static void AddPredecessorToBlock(BasicBlock *Succ, BasicBlock *NewPred, + BasicBlock *ExistPred) { + assert(std::find(succ_begin(ExistPred), succ_end(ExistPred), Succ) != + succ_end(ExistPred) && "ExistPred is not a predecessor of Succ!"); + if (!isa(Succ->begin())) return; // Quick exit if nothing to do + + PHINode *PN; + for (BasicBlock::iterator I = Succ->begin(); + (PN = dyn_cast(I)); ++I) + PN->addIncoming(PN->getIncomingValueForBlock(ExistPred), NewPred); +} + + +/// GetIfCondition - Given a basic block (BB) with two predecessors (and +/// presumably PHI nodes in it), check to see if the merge at this block is due +/// to an "if condition". If so, return the boolean condition that determines +/// which entry into BB will be taken. Also, return by references the block +/// that will be entered from if the condition is true, and the block that will +/// be entered if the condition is false. +/// +/// +static Value *GetIfCondition(BasicBlock *BB, + BasicBlock *&IfTrue, BasicBlock *&IfFalse) { + assert(std::distance(pred_begin(BB), pred_end(BB)) == 2 && + "Function can only handle blocks with 2 predecessors!"); + BasicBlock *Pred1 = *pred_begin(BB); + BasicBlock *Pred2 = *++pred_begin(BB); + + // We can only handle branches. Other control flow will be lowered to + // branches if possible anyway. + if (!isa(Pred1->getTerminator()) || + !isa(Pred2->getTerminator())) + return 0; + BranchInst *Pred1Br = cast(Pred1->getTerminator()); + BranchInst *Pred2Br = cast(Pred2->getTerminator()); + + // Eliminate code duplication by ensuring that Pred1Br is conditional if + // either are. + if (Pred2Br->isConditional()) { + // If both branches are conditional, we don't have an "if statement". In + // reality, we could transform this case, but since the condition will be + // required anyway, we stand no chance of eliminating it, so the xform is + // probably not profitable. + if (Pred1Br->isConditional()) + return 0; + + std::swap(Pred1, Pred2); + std::swap(Pred1Br, Pred2Br); + } + + if (Pred1Br->isConditional()) { + // If we found a conditional branch predecessor, make sure that it branches + // to BB and Pred2Br. If it doesn't, this isn't an "if statement". + if (Pred1Br->getSuccessor(0) == BB && + Pred1Br->getSuccessor(1) == Pred2) { + IfTrue = Pred1; + IfFalse = Pred2; + } else if (Pred1Br->getSuccessor(0) == Pred2 && + Pred1Br->getSuccessor(1) == BB) { + IfTrue = Pred2; + IfFalse = Pred1; + } else { + // We know that one arm of the conditional goes to BB, so the other must + // go somewhere unrelated, and this must not be an "if statement". + return 0; + } + + // The only thing we have to watch out for here is to make sure that Pred2 + // doesn't have incoming edges from other blocks. If it does, the condition + // doesn't dominate BB. + if (++pred_begin(Pred2) != pred_end(Pred2)) + return 0; + + return Pred1Br->getCondition(); + } + + // Ok, if we got here, both predecessors end with an unconditional branch to + // BB. Don't panic! If both blocks only have a single (identical) + // predecessor, and THAT is a conditional branch, then we're all ok! + if (pred_begin(Pred1) == pred_end(Pred1) || + ++pred_begin(Pred1) != pred_end(Pred1) || + pred_begin(Pred2) == pred_end(Pred2) || + ++pred_begin(Pred2) != pred_end(Pred2) || + *pred_begin(Pred1) != *pred_begin(Pred2)) + return 0; + + // Otherwise, if this is a conditional branch, then we can use it! + BasicBlock *CommonPred = *pred_begin(Pred1); + if (BranchInst *BI = dyn_cast(CommonPred->getTerminator())) { + assert(BI->isConditional() && "Two successors but not conditional?"); + if (BI->getSuccessor(0) == Pred1) { + IfTrue = Pred1; + IfFalse = Pred2; + } else { + IfTrue = Pred2; + IfFalse = Pred1; + } + return BI->getCondition(); + } + return 0; +} + +/// DominatesMergePoint - If we have a merge point of an "if condition" as +/// accepted above, return true if the specified value dominates the block. We +/// don't handle the true generality of domination here, just a special case +/// which works well enough for us. +/// +/// If AggressiveInsts is non-null, and if V does not dominate BB, we check to +/// see if V (which must be an instruction) is cheap to compute and is +/// non-trapping. If both are true, the instruction is inserted into the set +/// and true is returned. +static bool DominatesMergePoint(Value *V, BasicBlock *BB, + std::set *AggressiveInsts) { + Instruction *I = dyn_cast(V); + if (!I) { + // Non-instructions all dominate instructions, but not all constantexprs + // can be executed unconditionally. + if (ConstantExpr *C = dyn_cast(V)) + if (C->canTrap()) + return false; + return true; + } + BasicBlock *PBB = I->getParent(); + + // We don't want to allow weird loops that might have the "if condition" in + // the bottom of this block. + if (PBB == BB) return false; + + // If this instruction is defined in a block that contains an unconditional + // branch to BB, then it must be in the 'conditional' part of the "if + // statement". + if (BranchInst *BI = dyn_cast(PBB->getTerminator())) + if (BI->isUnconditional() && BI->getSuccessor(0) == BB) { + if (!AggressiveInsts) return false; + // Okay, it looks like the instruction IS in the "condition". Check to + // see if its a cheap instruction to unconditionally compute, and if it + // only uses stuff defined outside of the condition. If so, hoist it out. + if (!I->isSafeToSpeculativelyExecute()) + return false; + + switch (I->getOpcode()) { + default: return false; // Cannot hoist this out safely. + case Instruction::Load: { + // We have to check to make sure there are no instructions before the + // load in its basic block, as we are going to hoist the loop out to + // its predecessor. + BasicBlock::iterator IP = PBB->begin(); + while (isa(IP)) + IP++; + if (IP != BasicBlock::iterator(I)) + return false; + break; + } + case Instruction::Add: + case Instruction::Sub: + case Instruction::And: + case Instruction::Or: + case Instruction::Xor: + case Instruction::Shl: + case Instruction::LShr: + case Instruction::AShr: + case Instruction::ICmp: + break; // These are all cheap and non-trapping instructions. + } + + // Okay, we can only really hoist these out if their operands are not + // defined in the conditional region. + for (User::op_iterator i = I->op_begin(), e = I->op_end(); i != e; ++i) + if (!DominatesMergePoint(*i, BB, 0)) + return false; + // Okay, it's safe to do this! Remember this instruction. + AggressiveInsts->insert(I); + } + + return true; +} + +/// GatherConstantSetEQs - Given a potentially 'or'd together collection of +/// icmp_eq instructions that compare a value against a constant, return the +/// value being compared, and stick the constant into the Values vector. +static Value *GatherConstantSetEQs(Value *V, std::vector &Values){ + if (Instruction *Inst = dyn_cast(V)) { + if (Inst->getOpcode() == Instruction::ICmp && + cast(Inst)->getPredicate() == ICmpInst::ICMP_EQ) { + if (ConstantInt *C = dyn_cast(Inst->getOperand(1))) { + Values.push_back(C); + return Inst->getOperand(0); + } else if (ConstantInt *C = dyn_cast(Inst->getOperand(0))) { + Values.push_back(C); + return Inst->getOperand(1); + } + } else if (Inst->getOpcode() == Instruction::Or) { + if (Value *LHS = GatherConstantSetEQs(Inst->getOperand(0), Values)) + if (Value *RHS = GatherConstantSetEQs(Inst->getOperand(1), Values)) + if (LHS == RHS) + return LHS; + } + } + return 0; +} + +/// GatherConstantSetNEs - Given a potentially 'and'd together collection of +/// setne instructions that compare a value against a constant, return the value +/// being compared, and stick the constant into the Values vector. +static Value *GatherConstantSetNEs(Value *V, std::vector &Values){ + if (Instruction *Inst = dyn_cast(V)) { + if (Inst->getOpcode() == Instruction::ICmp && + cast(Inst)->getPredicate() == ICmpInst::ICMP_NE) { + if (ConstantInt *C = dyn_cast(Inst->getOperand(1))) { + Values.push_back(C); + return Inst->getOperand(0); + } else if (ConstantInt *C = dyn_cast(Inst->getOperand(0))) { + Values.push_back(C); + return Inst->getOperand(1); + } + } else if (Inst->getOpcode() == Instruction::And) { + if (Value *LHS = GatherConstantSetNEs(Inst->getOperand(0), Values)) + if (Value *RHS = GatherConstantSetNEs(Inst->getOperand(1), Values)) + if (LHS == RHS) + return LHS; + } + } + return 0; +} + +/// GatherValueComparisons - If the specified Cond is an 'and' or 'or' of a +/// bunch of comparisons of one value against constants, return the value and +/// the constants being compared. +static bool GatherValueComparisons(Instruction *Cond, Value *&CompVal, + std::vector &Values) { + if (Cond->getOpcode() == Instruction::Or) { + CompVal = GatherConstantSetEQs(Cond, Values); + + // Return true to indicate that the condition is true if the CompVal is + // equal to one of the constants. + return true; + } else if (Cond->getOpcode() == Instruction::And) { + CompVal = GatherConstantSetNEs(Cond, Values); + + // Return false to indicate that the condition is false if the CompVal is + // equal to one of the constants. + return false; + } + return false; +} + +static void EraseTerminatorInstAndDCECond(TerminatorInst *TI) { + Instruction* Cond = 0; + if (SwitchInst *SI = dyn_cast(TI)) { + Cond = dyn_cast(SI->getCondition()); + } else if (BranchInst *BI = dyn_cast(TI)) { + if (BI->isConditional()) + Cond = dyn_cast(BI->getCondition()); + } + + TI->eraseFromParent(); + if (Cond) RecursivelyDeleteTriviallyDeadInstructions(Cond); +} + +/// isValueEqualityComparison - Return true if the specified terminator checks +/// to see if a value is equal to constant integer value. +static Value *isValueEqualityComparison(TerminatorInst *TI) { + if (SwitchInst *SI = dyn_cast(TI)) { + // Do not permit merging of large switch instructions into their + // predecessors unless there is only one predecessor. + if (SI->getNumSuccessors() * std::distance(pred_begin(SI->getParent()), + pred_end(SI->getParent())) > 128) + return 0; + + return SI->getCondition(); + } + if (BranchInst *BI = dyn_cast(TI)) + if (BI->isConditional() && BI->getCondition()->hasOneUse()) + if (ICmpInst *ICI = dyn_cast(BI->getCondition())) + if ((ICI->getPredicate() == ICmpInst::ICMP_EQ || + ICI->getPredicate() == ICmpInst::ICMP_NE) && + isa(ICI->getOperand(1))) + return ICI->getOperand(0); + return 0; +} + +/// GetValueEqualityComparisonCases - Given a value comparison instruction, +/// decode all of the 'cases' that it represents and return the 'default' block. +static BasicBlock * +GetValueEqualityComparisonCases(TerminatorInst *TI, + std::vector > &Cases) { + if (SwitchInst *SI = dyn_cast(TI)) { + Cases.reserve(SI->getNumCases()); + for (unsigned i = 1, e = SI->getNumCases(); i != e; ++i) + Cases.push_back(std::make_pair(SI->getCaseValue(i), SI->getSuccessor(i))); + return SI->getDefaultDest(); + } + + BranchInst *BI = cast(TI); + ICmpInst *ICI = cast(BI->getCondition()); + Cases.push_back(std::make_pair(cast(ICI->getOperand(1)), + BI->getSuccessor(ICI->getPredicate() == + ICmpInst::ICMP_NE))); + return BI->getSuccessor(ICI->getPredicate() == ICmpInst::ICMP_EQ); +} + + +/// EliminateBlockCases - Given a vector of bb/value pairs, remove any entries +/// in the list that match the specified block. +static void EliminateBlockCases(BasicBlock *BB, + std::vector > &Cases) { + for (unsigned i = 0, e = Cases.size(); i != e; ++i) + if (Cases[i].second == BB) { + Cases.erase(Cases.begin()+i); + --i; --e; + } +} + +/// ValuesOverlap - Return true if there are any keys in C1 that exist in C2 as +/// well. +static bool +ValuesOverlap(std::vector > &C1, + std::vector > &C2) { + std::vector > *V1 = &C1, *V2 = &C2; + + // Make V1 be smaller than V2. + if (V1->size() > V2->size()) + std::swap(V1, V2); + + if (V1->size() == 0) return false; + if (V1->size() == 1) { + // Just scan V2. + ConstantInt *TheVal = (*V1)[0].first; + for (unsigned i = 0, e = V2->size(); i != e; ++i) + if (TheVal == (*V2)[i].first) + return true; + } + + // Otherwise, just sort both lists and compare element by element. + std::sort(V1->begin(), V1->end()); + std::sort(V2->begin(), V2->end()); + unsigned i1 = 0, i2 = 0, e1 = V1->size(), e2 = V2->size(); + while (i1 != e1 && i2 != e2) { + if ((*V1)[i1].first == (*V2)[i2].first) + return true; + if ((*V1)[i1].first < (*V2)[i2].first) + ++i1; + else + ++i2; + } + return false; +} + +/// SimplifyEqualityComparisonWithOnlyPredecessor - If TI is known to be a +/// terminator instruction and its block is known to only have a single +/// predecessor block, check to see if that predecessor is also a value +/// comparison with the same value, and if that comparison determines the +/// outcome of this comparison. If so, simplify TI. This does a very limited +/// form of jump threading. +static bool SimplifyEqualityComparisonWithOnlyPredecessor(TerminatorInst *TI, + BasicBlock *Pred) { + Value *PredVal = isValueEqualityComparison(Pred->getTerminator()); + if (!PredVal) return false; // Not a value comparison in predecessor. + + Value *ThisVal = isValueEqualityComparison(TI); + assert(ThisVal && "This isn't a value comparison!!"); + if (ThisVal != PredVal) return false; // Different predicates. + + // Find out information about when control will move from Pred to TI's block. + std::vector > PredCases; + BasicBlock *PredDef = GetValueEqualityComparisonCases(Pred->getTerminator(), + PredCases); + EliminateBlockCases(PredDef, PredCases); // Remove default from cases. + + // Find information about how control leaves this block. + std::vector > ThisCases; + BasicBlock *ThisDef = GetValueEqualityComparisonCases(TI, ThisCases); + EliminateBlockCases(ThisDef, ThisCases); // Remove default from cases. + + // If TI's block is the default block from Pred's comparison, potentially + // simplify TI based on this knowledge. + if (PredDef == TI->getParent()) { + // If we are here, we know that the value is none of those cases listed in + // PredCases. If there are any cases in ThisCases that are in PredCases, we + // can simplify TI. + if (ValuesOverlap(PredCases, ThisCases)) { + if (isa(TI)) { + // Okay, one of the successors of this condbr is dead. Convert it to a + // uncond br. + assert(ThisCases.size() == 1 && "Branch can only have one case!"); + // Insert the new branch. + Instruction *NI = BranchInst::Create(ThisDef, TI); + (void) NI; + + // Remove PHI node entries for the dead edge. + ThisCases[0].second->removePredecessor(TI->getParent()); + + DEBUG(errs() << "Threading pred instr: " << *Pred->getTerminator() + << "Through successor TI: " << *TI << "Leaving: " << *NI << "\n"); + + EraseTerminatorInstAndDCECond(TI); + return true; + + } else { + SwitchInst *SI = cast(TI); + // Okay, TI has cases that are statically dead, prune them away. + SmallPtrSet DeadCases; + for (unsigned i = 0, e = PredCases.size(); i != e; ++i) + DeadCases.insert(PredCases[i].first); + + DEBUG(errs() << "Threading pred instr: " << *Pred->getTerminator() + << "Through successor TI: " << *TI); + + for (unsigned i = SI->getNumCases()-1; i != 0; --i) + if (DeadCases.count(SI->getCaseValue(i))) { + SI->getSuccessor(i)->removePredecessor(TI->getParent()); + SI->removeCase(i); + } + + DEBUG(errs() << "Leaving: " << *TI << "\n"); + return true; + } + } + + } else { + // Otherwise, TI's block must correspond to some matched value. Find out + // which value (or set of values) this is. + ConstantInt *TIV = 0; + BasicBlock *TIBB = TI->getParent(); + for (unsigned i = 0, e = PredCases.size(); i != e; ++i) + if (PredCases[i].second == TIBB) { + if (TIV == 0) + TIV = PredCases[i].first; + else + return false; // Cannot handle multiple values coming to this block. + } + assert(TIV && "No edge from pred to succ?"); + + // Okay, we found the one constant that our value can be if we get into TI's + // BB. Find out which successor will unconditionally be branched to. + BasicBlock *TheRealDest = 0; + for (unsigned i = 0, e = ThisCases.size(); i != e; ++i) + if (ThisCases[i].first == TIV) { + TheRealDest = ThisCases[i].second; + break; + } + + // If not handled by any explicit cases, it is handled by the default case. + if (TheRealDest == 0) TheRealDest = ThisDef; + + // Remove PHI node entries for dead edges. + BasicBlock *CheckEdge = TheRealDest; + for (succ_iterator SI = succ_begin(TIBB), e = succ_end(TIBB); SI != e; ++SI) + if (*SI != CheckEdge) + (*SI)->removePredecessor(TIBB); + else + CheckEdge = 0; + + // Insert the new branch. + Instruction *NI = BranchInst::Create(TheRealDest, TI); + (void) NI; + + DEBUG(errs() << "Threading pred instr: " << *Pred->getTerminator() + << "Through successor TI: " << *TI << "Leaving: " << *NI << "\n"); + + EraseTerminatorInstAndDCECond(TI); + return true; + } + return false; +} + +namespace { + /// ConstantIntOrdering - This class implements a stable ordering of constant + /// integers that does not depend on their address. This is important for + /// applications that sort ConstantInt's to ensure uniqueness. + struct ConstantIntOrdering { + bool operator()(const ConstantInt *LHS, const ConstantInt *RHS) const { + return LHS->getValue().ult(RHS->getValue()); + } + }; +} + +/// FoldValueComparisonIntoPredecessors - The specified terminator is a value +/// equality comparison instruction (either a switch or a branch on "X == c"). +/// See if any of the predecessors of the terminator block are value comparisons +/// on the same value. If so, and if safe to do so, fold them together. +static bool FoldValueComparisonIntoPredecessors(TerminatorInst *TI) { + BasicBlock *BB = TI->getParent(); + Value *CV = isValueEqualityComparison(TI); // CondVal + assert(CV && "Not a comparison?"); + bool Changed = false; + + SmallVector Preds(pred_begin(BB), pred_end(BB)); + while (!Preds.empty()) { + BasicBlock *Pred = Preds.pop_back_val(); + + // See if the predecessor is a comparison with the same value. + TerminatorInst *PTI = Pred->getTerminator(); + Value *PCV = isValueEqualityComparison(PTI); // PredCondVal + + if (PCV == CV && SafeToMergeTerminators(TI, PTI)) { + // Figure out which 'cases' to copy from SI to PSI. + std::vector > BBCases; + BasicBlock *BBDefault = GetValueEqualityComparisonCases(TI, BBCases); + + std::vector > PredCases; + BasicBlock *PredDefault = GetValueEqualityComparisonCases(PTI, PredCases); + + // Based on whether the default edge from PTI goes to BB or not, fill in + // PredCases and PredDefault with the new switch cases we would like to + // build. + SmallVector NewSuccessors; + + if (PredDefault == BB) { + // If this is the default destination from PTI, only the edges in TI + // that don't occur in PTI, or that branch to BB will be activated. + std::set PTIHandled; + for (unsigned i = 0, e = PredCases.size(); i != e; ++i) + if (PredCases[i].second != BB) + PTIHandled.insert(PredCases[i].first); + else { + // The default destination is BB, we don't need explicit targets. + std::swap(PredCases[i], PredCases.back()); + PredCases.pop_back(); + --i; --e; + } + + // Reconstruct the new switch statement we will be building. + if (PredDefault != BBDefault) { + PredDefault->removePredecessor(Pred); + PredDefault = BBDefault; + NewSuccessors.push_back(BBDefault); + } + for (unsigned i = 0, e = BBCases.size(); i != e; ++i) + if (!PTIHandled.count(BBCases[i].first) && + BBCases[i].second != BBDefault) { + PredCases.push_back(BBCases[i]); + NewSuccessors.push_back(BBCases[i].second); + } + + } else { + // If this is not the default destination from PSI, only the edges + // in SI that occur in PSI with a destination of BB will be + // activated. + std::set PTIHandled; + for (unsigned i = 0, e = PredCases.size(); i != e; ++i) + if (PredCases[i].second == BB) { + PTIHandled.insert(PredCases[i].first); + std::swap(PredCases[i], PredCases.back()); + PredCases.pop_back(); + --i; --e; + } + + // Okay, now we know which constants were sent to BB from the + // predecessor. Figure out where they will all go now. + for (unsigned i = 0, e = BBCases.size(); i != e; ++i) + if (PTIHandled.count(BBCases[i].first)) { + // If this is one we are capable of getting... + PredCases.push_back(BBCases[i]); + NewSuccessors.push_back(BBCases[i].second); + PTIHandled.erase(BBCases[i].first);// This constant is taken care of + } + + // If there are any constants vectored to BB that TI doesn't handle, + // they must go to the default destination of TI. + for (std::set::iterator I = + PTIHandled.begin(), + E = PTIHandled.end(); I != E; ++I) { + PredCases.push_back(std::make_pair(*I, BBDefault)); + NewSuccessors.push_back(BBDefault); + } + } + + // Okay, at this point, we know which new successor Pred will get. Make + // sure we update the number of entries in the PHI nodes for these + // successors. + for (unsigned i = 0, e = NewSuccessors.size(); i != e; ++i) + AddPredecessorToBlock(NewSuccessors[i], Pred, BB); + + // Now that the successors are updated, create the new Switch instruction. + SwitchInst *NewSI = SwitchInst::Create(CV, PredDefault, + PredCases.size(), PTI); + for (unsigned i = 0, e = PredCases.size(); i != e; ++i) + NewSI->addCase(PredCases[i].first, PredCases[i].second); + + EraseTerminatorInstAndDCECond(PTI); + + // Okay, last check. If BB is still a successor of PSI, then we must + // have an infinite loop case. If so, add an infinitely looping block + // to handle the case to preserve the behavior of the code. + BasicBlock *InfLoopBlock = 0; + for (unsigned i = 0, e = NewSI->getNumSuccessors(); i != e; ++i) + if (NewSI->getSuccessor(i) == BB) { + if (InfLoopBlock == 0) { + // Insert it at the end of the function, because it's either code, + // or it won't matter if it's hot. :) + InfLoopBlock = BasicBlock::Create(BB->getContext(), + "infloop", BB->getParent()); + BranchInst::Create(InfLoopBlock, InfLoopBlock); + } + NewSI->setSuccessor(i, InfLoopBlock); + } + + Changed = true; + } + } + return Changed; +} + +// isSafeToHoistInvoke - If we would need to insert a select that uses the +// value of this invoke (comments in HoistThenElseCodeToIf explain why we +// would need to do this), we can't hoist the invoke, as there is nowhere +// to put the select in this case. +static bool isSafeToHoistInvoke(BasicBlock *BB1, BasicBlock *BB2, + Instruction *I1, Instruction *I2) { + for (succ_iterator SI = succ_begin(BB1), E = succ_end(BB1); SI != E; ++SI) { + PHINode *PN; + for (BasicBlock::iterator BBI = SI->begin(); + (PN = dyn_cast(BBI)); ++BBI) { + Value *BB1V = PN->getIncomingValueForBlock(BB1); + Value *BB2V = PN->getIncomingValueForBlock(BB2); + if (BB1V != BB2V && (BB1V==I1 || BB2V==I2)) { + return false; + } + } + } + return true; +} + +/// HoistThenElseCodeToIf - Given a conditional branch that goes to BB1 and +/// BB2, hoist any common code in the two blocks up into the branch block. The +/// caller of this function guarantees that BI's block dominates BB1 and BB2. +static bool HoistThenElseCodeToIf(BranchInst *BI) { + // This does very trivial matching, with limited scanning, to find identical + // instructions in the two blocks. In particular, we don't want to get into + // O(M*N) situations here where M and N are the sizes of BB1 and BB2. As + // such, we currently just scan for obviously identical instructions in an + // identical order. + BasicBlock *BB1 = BI->getSuccessor(0); // The true destination. + BasicBlock *BB2 = BI->getSuccessor(1); // The false destination + + BasicBlock::iterator BB1_Itr = BB1->begin(); + BasicBlock::iterator BB2_Itr = BB2->begin(); + + Instruction *I1 = BB1_Itr++, *I2 = BB2_Itr++; + while (isa(I1)) + I1 = BB1_Itr++; + while (isa(I2)) + I2 = BB2_Itr++; + if (I1->getOpcode() != I2->getOpcode() || isa(I1) || + !I1->isIdenticalToWhenDefined(I2) || + (isa(I1) && !isSafeToHoistInvoke(BB1, BB2, I1, I2))) + return false; + + // If we get here, we can hoist at least one instruction. + BasicBlock *BIParent = BI->getParent(); + + do { + // If we are hoisting the terminator instruction, don't move one (making a + // broken BB), instead clone it, and remove BI. + if (isa(I1)) + goto HoistTerminator; + + // For a normal instruction, we just move one to right before the branch, + // then replace all uses of the other with the first. Finally, we remove + // the now redundant second instruction. + BIParent->getInstList().splice(BI, BB1->getInstList(), I1); + if (!I2->use_empty()) + I2->replaceAllUsesWith(I1); + I1->intersectOptionalDataWith(I2); + BB2->getInstList().erase(I2); + + I1 = BB1_Itr++; + while (isa(I1)) + I1 = BB1_Itr++; + I2 = BB2_Itr++; + while (isa(I2)) + I2 = BB2_Itr++; + } while (I1->getOpcode() == I2->getOpcode() && + I1->isIdenticalToWhenDefined(I2)); + + return true; + +HoistTerminator: + // It may not be possible to hoist an invoke. + if (isa(I1) && !isSafeToHoistInvoke(BB1, BB2, I1, I2)) + return true; + + // Okay, it is safe to hoist the terminator. + Instruction *NT = I1->clone(); + BIParent->getInstList().insert(BI, NT); + if (NT->getType() != Type::getVoidTy(BB1->getContext())) { + I1->replaceAllUsesWith(NT); + I2->replaceAllUsesWith(NT); + NT->takeName(I1); + } + + // Hoisting one of the terminators from our successor is a great thing. + // Unfortunately, the successors of the if/else blocks may have PHI nodes in + // them. If they do, all PHI entries for BB1/BB2 must agree for all PHI + // nodes, so we insert select instruction to compute the final result. + std::map, SelectInst*> InsertedSelects; + for (succ_iterator SI = succ_begin(BB1), E = succ_end(BB1); SI != E; ++SI) { + PHINode *PN; + for (BasicBlock::iterator BBI = SI->begin(); + (PN = dyn_cast(BBI)); ++BBI) { + Value *BB1V = PN->getIncomingValueForBlock(BB1); + Value *BB2V = PN->getIncomingValueForBlock(BB2); + if (BB1V != BB2V) { + // These values do not agree. Insert a select instruction before NT + // that determines the right value. + SelectInst *&SI = InsertedSelects[std::make_pair(BB1V, BB2V)]; + if (SI == 0) + SI = SelectInst::Create(BI->getCondition(), BB1V, BB2V, + BB1V->getName()+"."+BB2V->getName(), NT); + // Make the PHI node use the select for all incoming values for BB1/BB2 + for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) + if (PN->getIncomingBlock(i) == BB1 || PN->getIncomingBlock(i) == BB2) + PN->setIncomingValue(i, SI); + } + } + } + + // Update any PHI nodes in our new successors. + for (succ_iterator SI = succ_begin(BB1), E = succ_end(BB1); SI != E; ++SI) + AddPredecessorToBlock(*SI, BIParent, BB1); + + EraseTerminatorInstAndDCECond(BI); + return true; +} + +/// SpeculativelyExecuteBB - Given a conditional branch that goes to BB1 +/// and an BB2 and the only successor of BB1 is BB2, hoist simple code +/// (for now, restricted to a single instruction that's side effect free) from +/// the BB1 into the branch block to speculatively execute it. +static bool SpeculativelyExecuteBB(BranchInst *BI, BasicBlock *BB1) { + // Only speculatively execution a single instruction (not counting the + // terminator) for now. + Instruction *HInst = NULL; + Instruction *Term = BB1->getTerminator(); + for (BasicBlock::iterator BBI = BB1->begin(), BBE = BB1->end(); + BBI != BBE; ++BBI) { + Instruction *I = BBI; + // Skip debug info. + if (isa(I)) continue; + if (I == Term) break; + + if (!HInst) + HInst = I; + else + return false; + } + if (!HInst) + return false; + + // Be conservative for now. FP select instruction can often be expensive. + Value *BrCond = BI->getCondition(); + if (isa(BrCond) && + cast(BrCond)->getOpcode() == Instruction::FCmp) + return false; + + // If BB1 is actually on the false edge of the conditional branch, remember + // to swap the select operands later. + bool Invert = false; + if (BB1 != BI->getSuccessor(0)) { + assert(BB1 == BI->getSuccessor(1) && "No edge from 'if' block?"); + Invert = true; + } + + // Turn + // BB: + // %t1 = icmp + // br i1 %t1, label %BB1, label %BB2 + // BB1: + // %t3 = add %t2, c + // br label BB2 + // BB2: + // => + // BB: + // %t1 = icmp + // %t4 = add %t2, c + // %t3 = select i1 %t1, %t2, %t3 + switch (HInst->getOpcode()) { + default: return false; // Not safe / profitable to hoist. + case Instruction::Add: + case Instruction::Sub: + // Not worth doing for vector ops. + if (isa(HInst->getType())) + return false; + break; + case Instruction::And: + case Instruction::Or: + case Instruction::Xor: + case Instruction::Shl: + case Instruction::LShr: + case Instruction::AShr: + // Don't mess with vector operations. + if (isa(HInst->getType())) + return false; + break; // These are all cheap and non-trapping instructions. + } + + // If the instruction is obviously dead, don't try to predicate it. + if (HInst->use_empty()) { + HInst->eraseFromParent(); + return true; + } + + // Can we speculatively execute the instruction? And what is the value + // if the condition is false? Consider the phi uses, if the incoming value + // from the "if" block are all the same V, then V is the value of the + // select if the condition is false. + BasicBlock *BIParent = BI->getParent(); + SmallVector PHIUses; + Value *FalseV = NULL; + + BasicBlock *BB2 = BB1->getTerminator()->getSuccessor(0); + for (Value::use_iterator UI = HInst->use_begin(), E = HInst->use_end(); + UI != E; ++UI) { + // Ignore any user that is not a PHI node in BB2. These can only occur in + // unreachable blocks, because they would not be dominated by the instr. + PHINode *PN = dyn_cast(UI); + if (!PN || PN->getParent() != BB2) + return false; + PHIUses.push_back(PN); + + Value *PHIV = PN->getIncomingValueForBlock(BIParent); + if (!FalseV) + FalseV = PHIV; + else if (FalseV != PHIV) + return false; // Inconsistent value when condition is false. + } + + assert(FalseV && "Must have at least one user, and it must be a PHI"); + + // Do not hoist the instruction if any of its operands are defined but not + // used in this BB. The transformation will prevent the operand from + // being sunk into the use block. + for (User::op_iterator i = HInst->op_begin(), e = HInst->op_end(); + i != e; ++i) { + Instruction *OpI = dyn_cast(*i); + if (OpI && OpI->getParent() == BIParent && + !OpI->isUsedInBasicBlock(BIParent)) + return false; + } + + // If we get here, we can hoist the instruction. Try to place it + // before the icmp instruction preceding the conditional branch. + BasicBlock::iterator InsertPos = BI; + if (InsertPos != BIParent->begin()) + --InsertPos; + // Skip debug info between condition and branch. + while (InsertPos != BIParent->begin() && isa(InsertPos)) + --InsertPos; + if (InsertPos == BrCond && !isa(BrCond)) { + SmallPtrSet BB1Insns; + for(BasicBlock::iterator BB1I = BB1->begin(), BB1E = BB1->end(); + BB1I != BB1E; ++BB1I) + BB1Insns.insert(BB1I); + for(Value::use_iterator UI = BrCond->use_begin(), UE = BrCond->use_end(); + UI != UE; ++UI) { + Instruction *Use = cast(*UI); + if (BB1Insns.count(Use)) { + // If BrCond uses the instruction that place it just before + // branch instruction. + InsertPos = BI; + break; + } + } + } else + InsertPos = BI; + BIParent->getInstList().splice(InsertPos, BB1->getInstList(), HInst); + + // Create a select whose true value is the speculatively executed value and + // false value is the previously determined FalseV. + SelectInst *SI; + if (Invert) + SI = SelectInst::Create(BrCond, FalseV, HInst, + FalseV->getName() + "." + HInst->getName(), BI); + else + SI = SelectInst::Create(BrCond, HInst, FalseV, + HInst->getName() + "." + FalseV->getName(), BI); + + // Make the PHI node use the select for all incoming values for "then" and + // "if" blocks. + for (unsigned i = 0, e = PHIUses.size(); i != e; ++i) { + PHINode *PN = PHIUses[i]; + for (unsigned j = 0, ee = PN->getNumIncomingValues(); j != ee; ++j) + if (PN->getIncomingBlock(j) == BB1 || + PN->getIncomingBlock(j) == BIParent) + PN->setIncomingValue(j, SI); + } + + ++NumSpeculations; + return true; +} + +/// BlockIsSimpleEnoughToThreadThrough - Return true if we can thread a branch +/// across this block. +static bool BlockIsSimpleEnoughToThreadThrough(BasicBlock *BB) { + BranchInst *BI = cast(BB->getTerminator()); + unsigned Size = 0; + + for (BasicBlock::iterator BBI = BB->begin(); &*BBI != BI; ++BBI) { + if (isa(BBI)) + continue; + if (Size > 10) return false; // Don't clone large BB's. + ++Size; + + // We can only support instructions that do not define values that are + // live outside of the current basic block. + for (Value::use_iterator UI = BBI->use_begin(), E = BBI->use_end(); + UI != E; ++UI) { + Instruction *U = cast(*UI); + if (U->getParent() != BB || isa(U)) return false; + } + + // Looks ok, continue checking. + } + + return true; +} + +/// FoldCondBranchOnPHI - If we have a conditional branch on a PHI node value +/// that is defined in the same block as the branch and if any PHI entries are +/// constants, thread edges corresponding to that entry to be branches to their +/// ultimate destination. +static bool FoldCondBranchOnPHI(BranchInst *BI) { + BasicBlock *BB = BI->getParent(); + PHINode *PN = dyn_cast(BI->getCondition()); + // NOTE: we currently cannot transform this case if the PHI node is used + // outside of the block. + if (!PN || PN->getParent() != BB || !PN->hasOneUse()) + return false; + + // Degenerate case of a single entry PHI. + if (PN->getNumIncomingValues() == 1) { + FoldSingleEntryPHINodes(PN->getParent()); + return true; + } + + // Now we know that this block has multiple preds and two succs. + if (!BlockIsSimpleEnoughToThreadThrough(BB)) return false; + + // Okay, this is a simple enough basic block. See if any phi values are + // constants. + for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) { + ConstantInt *CB; + if ((CB = dyn_cast(PN->getIncomingValue(i))) && + CB->getType() == Type::getInt1Ty(BB->getContext())) { + // Okay, we now know that all edges from PredBB should be revectored to + // branch to RealDest. + BasicBlock *PredBB = PN->getIncomingBlock(i); + BasicBlock *RealDest = BI->getSuccessor(!CB->getZExtValue()); + + if (RealDest == BB) continue; // Skip self loops. + + // The dest block might have PHI nodes, other predecessors and other + // difficult cases. Instead of being smart about this, just insert a new + // block that jumps to the destination block, effectively splitting + // the edge we are about to create. + BasicBlock *EdgeBB = BasicBlock::Create(BB->getContext(), + RealDest->getName()+".critedge", + RealDest->getParent(), RealDest); + BranchInst::Create(RealDest, EdgeBB); + PHINode *PN; + for (BasicBlock::iterator BBI = RealDest->begin(); + (PN = dyn_cast(BBI)); ++BBI) { + Value *V = PN->getIncomingValueForBlock(BB); + PN->addIncoming(V, EdgeBB); + } + + // BB may have instructions that are being threaded over. Clone these + // instructions into EdgeBB. We know that there will be no uses of the + // cloned instructions outside of EdgeBB. + BasicBlock::iterator InsertPt = EdgeBB->begin(); + std::map TranslateMap; // Track translated values. + for (BasicBlock::iterator BBI = BB->begin(); &*BBI != BI; ++BBI) { + if (PHINode *PN = dyn_cast(BBI)) { + TranslateMap[PN] = PN->getIncomingValueForBlock(PredBB); + } else { + // Clone the instruction. + Instruction *N = BBI->clone(); + if (BBI->hasName()) N->setName(BBI->getName()+".c"); + + // Update operands due to translation. + for (User::op_iterator i = N->op_begin(), e = N->op_end(); + i != e; ++i) { + std::map::iterator PI = + TranslateMap.find(*i); + if (PI != TranslateMap.end()) + *i = PI->second; + } + + // Check for trivial simplification. + if (Constant *C = ConstantFoldInstruction(N)) { + TranslateMap[BBI] = C; + delete N; // Constant folded away, don't need actual inst + } else { + // Insert the new instruction into its new home. + EdgeBB->getInstList().insert(InsertPt, N); + if (!BBI->use_empty()) + TranslateMap[BBI] = N; + } + } + } + + // Loop over all of the edges from PredBB to BB, changing them to branch + // to EdgeBB instead. + TerminatorInst *PredBBTI = PredBB->getTerminator(); + for (unsigned i = 0, e = PredBBTI->getNumSuccessors(); i != e; ++i) + if (PredBBTI->getSuccessor(i) == BB) { + BB->removePredecessor(PredBB); + PredBBTI->setSuccessor(i, EdgeBB); + } + + // Recurse, simplifying any other constants. + return FoldCondBranchOnPHI(BI) | true; + } + } + + return false; +} + +/// FoldTwoEntryPHINode - Given a BB that starts with the specified two-entry +/// PHI node, see if we can eliminate it. +static bool FoldTwoEntryPHINode(PHINode *PN) { + // Ok, this is a two entry PHI node. Check to see if this is a simple "if + // statement", which has a very simple dominance structure. Basically, we + // are trying to find the condition that is being branched on, which + // subsequently causes this merge to happen. We really want control + // dependence information for this check, but simplifycfg can't keep it up + // to date, and this catches most of the cases we care about anyway. + // + BasicBlock *BB = PN->getParent(); + BasicBlock *IfTrue, *IfFalse; + Value *IfCond = GetIfCondition(BB, IfTrue, IfFalse); + if (!IfCond) return false; + + // Okay, we found that we can merge this two-entry phi node into a select. + // Doing so would require us to fold *all* two entry phi nodes in this block. + // At some point this becomes non-profitable (particularly if the target + // doesn't support cmov's). Only do this transformation if there are two or + // fewer PHI nodes in this block. + unsigned NumPhis = 0; + for (BasicBlock::iterator I = BB->begin(); isa(I); ++NumPhis, ++I) + if (NumPhis > 2) + return false; + + DEBUG(errs() << "FOUND IF CONDITION! " << *IfCond << " T: " + << IfTrue->getName() << " F: " << IfFalse->getName() << "\n"); + + // Loop over the PHI's seeing if we can promote them all to select + // instructions. While we are at it, keep track of the instructions + // that need to be moved to the dominating block. + std::set AggressiveInsts; + + BasicBlock::iterator AfterPHIIt = BB->begin(); + while (isa(AfterPHIIt)) { + PHINode *PN = cast(AfterPHIIt++); + if (PN->getIncomingValue(0) == PN->getIncomingValue(1)) { + if (PN->getIncomingValue(0) != PN) + PN->replaceAllUsesWith(PN->getIncomingValue(0)); + else + PN->replaceAllUsesWith(UndefValue::get(PN->getType())); + } else if (!DominatesMergePoint(PN->getIncomingValue(0), BB, + &AggressiveInsts) || + !DominatesMergePoint(PN->getIncomingValue(1), BB, + &AggressiveInsts)) { + return false; + } + } + + // If we all PHI nodes are promotable, check to make sure that all + // instructions in the predecessor blocks can be promoted as well. If + // not, we won't be able to get rid of the control flow, so it's not + // worth promoting to select instructions. + BasicBlock *DomBlock = 0, *IfBlock1 = 0, *IfBlock2 = 0; + PN = cast(BB->begin()); + BasicBlock *Pred = PN->getIncomingBlock(0); + if (cast(Pred->getTerminator())->isUnconditional()) { + IfBlock1 = Pred; + DomBlock = *pred_begin(Pred); + for (BasicBlock::iterator I = Pred->begin(); + !isa(I); ++I) + if (!AggressiveInsts.count(I) && !isa(I)) { + // This is not an aggressive instruction that we can promote. + // Because of this, we won't be able to get rid of the control + // flow, so the xform is not worth it. + return false; + } + } + + Pred = PN->getIncomingBlock(1); + if (cast(Pred->getTerminator())->isUnconditional()) { + IfBlock2 = Pred; + DomBlock = *pred_begin(Pred); + for (BasicBlock::iterator I = Pred->begin(); + !isa(I); ++I) + if (!AggressiveInsts.count(I) && !isa(I)) { + // This is not an aggressive instruction that we can promote. + // Because of this, we won't be able to get rid of the control + // flow, so the xform is not worth it. + return false; + } + } + + // If we can still promote the PHI nodes after this gauntlet of tests, + // do all of the PHI's now. + + // Move all 'aggressive' instructions, which are defined in the + // conditional parts of the if's up to the dominating block. + if (IfBlock1) { + DomBlock->getInstList().splice(DomBlock->getTerminator(), + IfBlock1->getInstList(), + IfBlock1->begin(), + IfBlock1->getTerminator()); + } + if (IfBlock2) { + DomBlock->getInstList().splice(DomBlock->getTerminator(), + IfBlock2->getInstList(), + IfBlock2->begin(), + IfBlock2->getTerminator()); + } + + while (PHINode *PN = dyn_cast(BB->begin())) { + // Change the PHI node into a select instruction. + Value *TrueVal = + PN->getIncomingValue(PN->getIncomingBlock(0) == IfFalse); + Value *FalseVal = + PN->getIncomingValue(PN->getIncomingBlock(0) == IfTrue); + + Value *NV = SelectInst::Create(IfCond, TrueVal, FalseVal, "", AfterPHIIt); + PN->replaceAllUsesWith(NV); + NV->takeName(PN); + + BB->getInstList().erase(PN); + } + return true; +} + +/// isTerminatorFirstRelevantInsn - Return true if Term is very first +/// instruction ignoring Phi nodes and dbg intrinsics. +static bool isTerminatorFirstRelevantInsn(BasicBlock *BB, Instruction *Term) { + BasicBlock::iterator BBI = Term; + while (BBI != BB->begin()) { + --BBI; + if (!isa(BBI)) + break; + } + + if (isa(BBI) || &*BBI == Term || isa(BBI)) + return true; + return false; +} + +/// SimplifyCondBranchToTwoReturns - If we found a conditional branch that goes +/// to two returning blocks, try to merge them together into one return, +/// introducing a select if the return values disagree. +static bool SimplifyCondBranchToTwoReturns(BranchInst *BI) { + assert(BI->isConditional() && "Must be a conditional branch"); + BasicBlock *TrueSucc = BI->getSuccessor(0); + BasicBlock *FalseSucc = BI->getSuccessor(1); + ReturnInst *TrueRet = cast(TrueSucc->getTerminator()); + ReturnInst *FalseRet = cast(FalseSucc->getTerminator()); + + // Check to ensure both blocks are empty (just a return) or optionally empty + // with PHI nodes. If there are other instructions, merging would cause extra + // computation on one path or the other. + if (!isTerminatorFirstRelevantInsn(TrueSucc, TrueRet)) + return false; + if (!isTerminatorFirstRelevantInsn(FalseSucc, FalseRet)) + return false; + + // Okay, we found a branch that is going to two return nodes. If + // there is no return value for this function, just change the + // branch into a return. + if (FalseRet->getNumOperands() == 0) { + TrueSucc->removePredecessor(BI->getParent()); + FalseSucc->removePredecessor(BI->getParent()); + ReturnInst::Create(BI->getContext(), 0, BI); + EraseTerminatorInstAndDCECond(BI); + return true; + } + + // Otherwise, figure out what the true and false return values are + // so we can insert a new select instruction. + Value *TrueValue = TrueRet->getReturnValue(); + Value *FalseValue = FalseRet->getReturnValue(); + + // Unwrap any PHI nodes in the return blocks. + if (PHINode *TVPN = dyn_cast_or_null(TrueValue)) + if (TVPN->getParent() == TrueSucc) + TrueValue = TVPN->getIncomingValueForBlock(BI->getParent()); + if (PHINode *FVPN = dyn_cast_or_null(FalseValue)) + if (FVPN->getParent() == FalseSucc) + FalseValue = FVPN->getIncomingValueForBlock(BI->getParent()); + + // In order for this transformation to be safe, we must be able to + // unconditionally execute both operands to the return. This is + // normally the case, but we could have a potentially-trapping + // constant expression that prevents this transformation from being + // safe. + if (ConstantExpr *TCV = dyn_cast_or_null(TrueValue)) + if (TCV->canTrap()) + return false; + if (ConstantExpr *FCV = dyn_cast_or_null(FalseValue)) + if (FCV->canTrap()) + return false; + + // Okay, we collected all the mapped values and checked them for sanity, and + // defined to really do this transformation. First, update the CFG. + TrueSucc->removePredecessor(BI->getParent()); + FalseSucc->removePredecessor(BI->getParent()); + + // Insert select instructions where needed. + Value *BrCond = BI->getCondition(); + if (TrueValue) { + // Insert a select if the results differ. + if (TrueValue == FalseValue || isa(FalseValue)) { + } else if (isa(TrueValue)) { + TrueValue = FalseValue; + } else { + TrueValue = SelectInst::Create(BrCond, TrueValue, + FalseValue, "retval", BI); + } + } + + Value *RI = !TrueValue ? + ReturnInst::Create(BI->getContext(), BI) : + ReturnInst::Create(BI->getContext(), TrueValue, BI); + (void) RI; + + DEBUG(errs() << "\nCHANGING BRANCH TO TWO RETURNS INTO SELECT:" + << "\n " << *BI << "NewRet = " << *RI + << "TRUEBLOCK: " << *TrueSucc << "FALSEBLOCK: "<< *FalseSucc); + + EraseTerminatorInstAndDCECond(BI); + + return true; +} + +/// FoldBranchToCommonDest - If this basic block is ONLY a setcc and a branch, +/// and if a predecessor branches to us and one of our successors, fold the +/// setcc into the predecessor and use logical operations to pick the right +/// destination. +bool llvm::FoldBranchToCommonDest(BranchInst *BI) { + BasicBlock *BB = BI->getParent(); + Instruction *Cond = dyn_cast(BI->getCondition()); + if (Cond == 0) return false; + + + // Only allow this if the condition is a simple instruction that can be + // executed unconditionally. It must be in the same block as the branch, and + // must be at the front of the block. + BasicBlock::iterator FrontIt = BB->front(); + // Ignore dbg intrinsics. + while(isa(FrontIt)) + ++FrontIt; + if ((!isa(Cond) && !isa(Cond)) || + Cond->getParent() != BB || &*FrontIt != Cond || !Cond->hasOneUse()) { + return false; + } + + // Make sure the instruction after the condition is the cond branch. + BasicBlock::iterator CondIt = Cond; ++CondIt; + // Ingore dbg intrinsics. + while(isa(CondIt)) + ++CondIt; + if (&*CondIt != BI) { + assert (!isa(CondIt) && "Hey do not forget debug info!"); + return false; + } + + // Cond is known to be a compare or binary operator. Check to make sure that + // neither operand is a potentially-trapping constant expression. + if (ConstantExpr *CE = dyn_cast(Cond->getOperand(0))) + if (CE->canTrap()) + return false; + if (ConstantExpr *CE = dyn_cast(Cond->getOperand(1))) + if (CE->canTrap()) + return false; + + + // Finally, don't infinitely unroll conditional loops. + BasicBlock *TrueDest = BI->getSuccessor(0); + BasicBlock *FalseDest = BI->getSuccessor(1); + if (TrueDest == BB || FalseDest == BB) + return false; + + for (pred_iterator PI = pred_begin(BB), E = pred_end(BB); PI != E; ++PI) { + BasicBlock *PredBlock = *PI; + BranchInst *PBI = dyn_cast(PredBlock->getTerminator()); + + // Check that we have two conditional branches. If there is a PHI node in + // the common successor, verify that the same value flows in from both + // blocks. + if (PBI == 0 || PBI->isUnconditional() || + !SafeToMergeTerminators(BI, PBI)) + continue; + + Instruction::BinaryOps Opc; + bool InvertPredCond = false; + + if (PBI->getSuccessor(0) == TrueDest) + Opc = Instruction::Or; + else if (PBI->getSuccessor(1) == FalseDest) + Opc = Instruction::And; + else if (PBI->getSuccessor(0) == FalseDest) + Opc = Instruction::And, InvertPredCond = true; + else if (PBI->getSuccessor(1) == TrueDest) + Opc = Instruction::Or, InvertPredCond = true; + else + continue; + + DEBUG(errs() << "FOLDING BRANCH TO COMMON DEST:\n" << *PBI << *BB); + + // If we need to invert the condition in the pred block to match, do so now. + if (InvertPredCond) { + Value *NewCond = + BinaryOperator::CreateNot(PBI->getCondition(), + PBI->getCondition()->getName()+".not", PBI); + PBI->setCondition(NewCond); + BasicBlock *OldTrue = PBI->getSuccessor(0); + BasicBlock *OldFalse = PBI->getSuccessor(1); + PBI->setSuccessor(0, OldFalse); + PBI->setSuccessor(1, OldTrue); + } + + // Clone Cond into the predecessor basic block, and or/and the + // two conditions together. + Instruction *New = Cond->clone(); + PredBlock->getInstList().insert(PBI, New); + New->takeName(Cond); + Cond->setName(New->getName()+".old"); + + Value *NewCond = BinaryOperator::Create(Opc, PBI->getCondition(), + New, "or.cond", PBI); + PBI->setCondition(NewCond); + if (PBI->getSuccessor(0) == BB) { + AddPredecessorToBlock(TrueDest, PredBlock, BB); + PBI->setSuccessor(0, TrueDest); + } + if (PBI->getSuccessor(1) == BB) { + AddPredecessorToBlock(FalseDest, PredBlock, BB); + PBI->setSuccessor(1, FalseDest); + } + return true; + } + return false; +} + +/// SimplifyCondBranchToCondBranch - If we have a conditional branch as a +/// predecessor of another block, this function tries to simplify it. We know +/// that PBI and BI are both conditional branches, and BI is in one of the +/// successor blocks of PBI - PBI branches to BI. +static bool SimplifyCondBranchToCondBranch(BranchInst *PBI, BranchInst *BI) { + assert(PBI->isConditional() && BI->isConditional()); + BasicBlock *BB = BI->getParent(); + + // If this block ends with a branch instruction, and if there is a + // predecessor that ends on a branch of the same condition, make + // this conditional branch redundant. + if (PBI->getCondition() == BI->getCondition() && + PBI->getSuccessor(0) != PBI->getSuccessor(1)) { + // Okay, the outcome of this conditional branch is statically + // knowable. If this block had a single pred, handle specially. + if (BB->getSinglePredecessor()) { + // Turn this into a branch on constant. + bool CondIsTrue = PBI->getSuccessor(0) == BB; + BI->setCondition(ConstantInt::get(Type::getInt1Ty(BB->getContext()), + CondIsTrue)); + return true; // Nuke the branch on constant. + } + + // Otherwise, if there are multiple predecessors, insert a PHI that merges + // in the constant and simplify the block result. Subsequent passes of + // simplifycfg will thread the block. + if (BlockIsSimpleEnoughToThreadThrough(BB)) { + PHINode *NewPN = PHINode::Create(Type::getInt1Ty(BB->getContext()), + BI->getCondition()->getName() + ".pr", + BB->begin()); + // Okay, we're going to insert the PHI node. Since PBI is not the only + // predecessor, compute the PHI'd conditional value for all of the preds. + // Any predecessor where the condition is not computable we keep symbolic. + for (pred_iterator PI = pred_begin(BB), E = pred_end(BB); PI != E; ++PI) + if ((PBI = dyn_cast((*PI)->getTerminator())) && + PBI != BI && PBI->isConditional() && + PBI->getCondition() == BI->getCondition() && + PBI->getSuccessor(0) != PBI->getSuccessor(1)) { + bool CondIsTrue = PBI->getSuccessor(0) == BB; + NewPN->addIncoming(ConstantInt::get(Type::getInt1Ty(BB->getContext()), + CondIsTrue), *PI); + } else { + NewPN->addIncoming(BI->getCondition(), *PI); + } + + BI->setCondition(NewPN); + return true; + } + } + + // If this is a conditional branch in an empty block, and if any + // predecessors is a conditional branch to one of our destinations, + // fold the conditions into logical ops and one cond br. + BasicBlock::iterator BBI = BB->begin(); + // Ignore dbg intrinsics. + while (isa(BBI)) + ++BBI; + if (&*BBI != BI) + return false; + + + if (ConstantExpr *CE = dyn_cast(BI->getCondition())) + if (CE->canTrap()) + return false; + + int PBIOp, BIOp; + if (PBI->getSuccessor(0) == BI->getSuccessor(0)) + PBIOp = BIOp = 0; + else if (PBI->getSuccessor(0) == BI->getSuccessor(1)) + PBIOp = 0, BIOp = 1; + else if (PBI->getSuccessor(1) == BI->getSuccessor(0)) + PBIOp = 1, BIOp = 0; + else if (PBI->getSuccessor(1) == BI->getSuccessor(1)) + PBIOp = BIOp = 1; + else + return false; + + // Check to make sure that the other destination of this branch + // isn't BB itself. If so, this is an infinite loop that will + // keep getting unwound. + if (PBI->getSuccessor(PBIOp) == BB) + return false; + + // Do not perform this transformation if it would require + // insertion of a large number of select instructions. For targets + // without predication/cmovs, this is a big pessimization. + BasicBlock *CommonDest = PBI->getSuccessor(PBIOp); + + unsigned NumPhis = 0; + for (BasicBlock::iterator II = CommonDest->begin(); + isa(II); ++II, ++NumPhis) + if (NumPhis > 2) // Disable this xform. + return false; + + // Finally, if everything is ok, fold the branches to logical ops. + BasicBlock *OtherDest = BI->getSuccessor(BIOp ^ 1); + + DEBUG(errs() << "FOLDING BRs:" << *PBI->getParent() + << "AND: " << *BI->getParent()); + + + // If OtherDest *is* BB, then BB is a basic block with a single conditional + // branch in it, where one edge (OtherDest) goes back to itself but the other + // exits. We don't *know* that the program avoids the infinite loop + // (even though that seems likely). If we do this xform naively, we'll end up + // recursively unpeeling the loop. Since we know that (after the xform is + // done) that the block *is* infinite if reached, we just make it an obviously + // infinite loop with no cond branch. + if (OtherDest == BB) { + // Insert it at the end of the function, because it's either code, + // or it won't matter if it's hot. :) + BasicBlock *InfLoopBlock = BasicBlock::Create(BB->getContext(), + "infloop", BB->getParent()); + BranchInst::Create(InfLoopBlock, InfLoopBlock); + OtherDest = InfLoopBlock; + } + + DEBUG(errs() << *PBI->getParent()->getParent()); + + // BI may have other predecessors. Because of this, we leave + // it alone, but modify PBI. + + // Make sure we get to CommonDest on True&True directions. + Value *PBICond = PBI->getCondition(); + if (PBIOp) + PBICond = BinaryOperator::CreateNot(PBICond, + PBICond->getName()+".not", + PBI); + Value *BICond = BI->getCondition(); + if (BIOp) + BICond = BinaryOperator::CreateNot(BICond, + BICond->getName()+".not", + PBI); + // Merge the conditions. + Value *Cond = BinaryOperator::CreateOr(PBICond, BICond, "brmerge", PBI); + + // Modify PBI to branch on the new condition to the new dests. + PBI->setCondition(Cond); + PBI->setSuccessor(0, CommonDest); + PBI->setSuccessor(1, OtherDest); + + // OtherDest may have phi nodes. If so, add an entry from PBI's + // block that are identical to the entries for BI's block. + PHINode *PN; + for (BasicBlock::iterator II = OtherDest->begin(); + (PN = dyn_cast(II)); ++II) { + Value *V = PN->getIncomingValueForBlock(BB); + PN->addIncoming(V, PBI->getParent()); + } + + // We know that the CommonDest already had an edge from PBI to + // it. If it has PHIs though, the PHIs may have different + // entries for BB and PBI's BB. If so, insert a select to make + // them agree. + for (BasicBlock::iterator II = CommonDest->begin(); + (PN = dyn_cast(II)); ++II) { + Value *BIV = PN->getIncomingValueForBlock(BB); + unsigned PBBIdx = PN->getBasicBlockIndex(PBI->getParent()); + Value *PBIV = PN->getIncomingValue(PBBIdx); + if (BIV != PBIV) { + // Insert a select in PBI to pick the right value. + Value *NV = SelectInst::Create(PBICond, PBIV, BIV, + PBIV->getName()+".mux", PBI); + PN->setIncomingValue(PBBIdx, NV); + } + } + + DEBUG(errs() << "INTO: " << *PBI->getParent()); + DEBUG(errs() << *PBI->getParent()->getParent()); + + // This basic block is probably dead. We know it has at least + // one fewer predecessor. + return true; +} + +/// EliminateDuplicatePHINodes - Check for and eliminate duplicate PHI +/// nodes in this block. This doesn't try to be clever about PHI nodes +/// which differ only in the order of the incoming values, but instcombine +/// orders them so it usually won't matter. +/// +bool llvm::EliminateDuplicatePHINodes(BasicBlock *BB) { + bool Changed = false; + + // This implementation doesn't currently consider undef operands + // specially. Theroetically, two phis which are identical except for + // one having an undef where the other doesn't could be collapsed. + + // Map from PHI hash values to PHI nodes. If multiple PHIs have + // the same hash value, the element is the first PHI in the + // linked list in CollisionMap. + DenseMap HashMap; + + // Maintain linked lists of PHI nodes with common hash values. + DenseMap CollisionMap; + + // Examine each PHI. + for (BasicBlock::iterator I = BB->begin(); + PHINode *PN = dyn_cast(I++); ) { + // Compute a hash value on the operands. Instcombine will likely have sorted + // them, which helps expose duplicates, but we have to check all the + // operands to be safe in case instcombine hasn't run. + uintptr_t Hash = 0; + for (User::op_iterator I = PN->op_begin(), E = PN->op_end(); I != E; ++I) { + // This hash algorithm is quite weak as hash functions go, but it seems + // to do a good enough job for this particular purpose, and is very quick. + Hash ^= reinterpret_cast(static_cast(*I)); + Hash = (Hash << 7) | (Hash >> (sizeof(uintptr_t) * CHAR_BIT - 7)); + } + // If we've never seen this hash value before, it's a unique PHI. + std::pair::iterator, bool> Pair = + HashMap.insert(std::make_pair(Hash, PN)); + if (Pair.second) continue; + // Otherwise it's either a duplicate or a hash collision. + for (PHINode *OtherPN = Pair.first->second; ; ) { + if (OtherPN->isIdenticalTo(PN)) { + // A duplicate. Replace this PHI with its duplicate. + PN->replaceAllUsesWith(OtherPN); + PN->eraseFromParent(); + Changed = true; + break; + } + // A non-duplicate hash collision. + DenseMap::iterator I = CollisionMap.find(OtherPN); + if (I == CollisionMap.end()) { + // Set this PHI to be the head of the linked list of colliding PHIs. + PHINode *Old = Pair.first->second; + Pair.first->second = PN; + CollisionMap[PN] = Old; + break; + } + // Procede to the next PHI in the list. + OtherPN = I->second; + } + } + + return Changed; +} + +/// SimplifyCFG - This function is used to do simplification of a CFG. For +/// example, it adjusts branches to branches to eliminate the extra hop, it +/// eliminates unreachable basic blocks, and does other "peephole" optimization +/// of the CFG. It returns true if a modification was made. +/// +/// WARNING: The entry node of a function may not be simplified. +/// +bool llvm::SimplifyCFG(BasicBlock *BB) { + bool Changed = false; + Function *M = BB->getParent(); + + assert(BB && BB->getParent() && "Block not embedded in function!"); + assert(BB->getTerminator() && "Degenerate basic block encountered!"); + assert(&BB->getParent()->getEntryBlock() != BB && + "Can't Simplify entry block!"); + + // Remove basic blocks that have no predecessors... or that just have themself + // as a predecessor. These are unreachable. + if (pred_begin(BB) == pred_end(BB) || BB->getSinglePredecessor() == BB) { + DEBUG(errs() << "Removing BB: \n" << *BB); + DeleteDeadBlock(BB); + return true; + } + + // Check to see if we can constant propagate this terminator instruction + // away... + Changed |= ConstantFoldTerminator(BB); + + // Check for and eliminate duplicate PHI nodes in this block. + Changed |= EliminateDuplicatePHINodes(BB); + + // If there is a trivial two-entry PHI node in this basic block, and we can + // eliminate it, do so now. + if (PHINode *PN = dyn_cast(BB->begin())) + if (PN->getNumIncomingValues() == 2) + Changed |= FoldTwoEntryPHINode(PN); + + // If this is a returning block with only PHI nodes in it, fold the return + // instruction into any unconditional branch predecessors. + // + // If any predecessor is a conditional branch that just selects among + // different return values, fold the replace the branch/return with a select + // and return. + if (ReturnInst *RI = dyn_cast(BB->getTerminator())) { + if (isTerminatorFirstRelevantInsn(BB, BB->getTerminator())) { + // Find predecessors that end with branches. + SmallVector UncondBranchPreds; + SmallVector CondBranchPreds; + for (pred_iterator PI = pred_begin(BB), E = pred_end(BB); PI != E; ++PI) { + TerminatorInst *PTI = (*PI)->getTerminator(); + if (BranchInst *BI = dyn_cast(PTI)) { + if (BI->isUnconditional()) + UncondBranchPreds.push_back(*PI); + else + CondBranchPreds.push_back(BI); + } + } + + // If we found some, do the transformation! + if (!UncondBranchPreds.empty()) { + while (!UncondBranchPreds.empty()) { + BasicBlock *Pred = UncondBranchPreds.pop_back_val(); + DEBUG(errs() << "FOLDING: " << *BB + << "INTO UNCOND BRANCH PRED: " << *Pred); + Instruction *UncondBranch = Pred->getTerminator(); + // Clone the return and add it to the end of the predecessor. + Instruction *NewRet = RI->clone(); + Pred->getInstList().push_back(NewRet); + + BasicBlock::iterator BBI = RI; + if (BBI != BB->begin()) { + // Move region end info into the predecessor. + if (DbgRegionEndInst *DREI = dyn_cast(--BBI)) + DREI->moveBefore(NewRet); + } + + // If the return instruction returns a value, and if the value was a + // PHI node in "BB", propagate the right value into the return. + for (User::op_iterator i = NewRet->op_begin(), e = NewRet->op_end(); + i != e; ++i) + if (PHINode *PN = dyn_cast(*i)) + if (PN->getParent() == BB) + *i = PN->getIncomingValueForBlock(Pred); + + // Update any PHI nodes in the returning block to realize that we no + // longer branch to them. + BB->removePredecessor(Pred); + Pred->getInstList().erase(UncondBranch); + } + + // If we eliminated all predecessors of the block, delete the block now. + if (pred_begin(BB) == pred_end(BB)) + // We know there are no successors, so just nuke the block. + M->getBasicBlockList().erase(BB); + + return true; + } + + // Check out all of the conditional branches going to this return + // instruction. If any of them just select between returns, change the + // branch itself into a select/return pair. + while (!CondBranchPreds.empty()) { + BranchInst *BI = CondBranchPreds.pop_back_val(); + + // Check to see if the non-BB successor is also a return block. + if (isa(BI->getSuccessor(0)->getTerminator()) && + isa(BI->getSuccessor(1)->getTerminator()) && + SimplifyCondBranchToTwoReturns(BI)) + return true; + } + } + } else if (isa(BB->begin())) { + // Check to see if the first instruction in this block is just an unwind. + // If so, replace any invoke instructions which use this as an exception + // destination with call instructions. + // + SmallVector Preds(pred_begin(BB), pred_end(BB)); + while (!Preds.empty()) { + BasicBlock *Pred = Preds.back(); + if (InvokeInst *II = dyn_cast(Pred->getTerminator())) + if (II->getUnwindDest() == BB) { + // Insert a new branch instruction before the invoke, because this + // is now a fall through. + BranchInst *BI = BranchInst::Create(II->getNormalDest(), II); + Pred->getInstList().remove(II); // Take out of symbol table + + // Insert the call now. + SmallVector Args(II->op_begin()+3, II->op_end()); + CallInst *CI = CallInst::Create(II->getCalledValue(), + Args.begin(), Args.end(), + II->getName(), BI); + CI->setCallingConv(II->getCallingConv()); + CI->setAttributes(II->getAttributes()); + // If the invoke produced a value, the Call now does instead. + II->replaceAllUsesWith(CI); + delete II; + Changed = true; + } + + Preds.pop_back(); + } + + // If this block is now dead, remove it. + if (pred_begin(BB) == pred_end(BB)) { + // We know there are no successors, so just nuke the block. + M->getBasicBlockList().erase(BB); + return true; + } + + } else if (SwitchInst *SI = dyn_cast(BB->getTerminator())) { + if (isValueEqualityComparison(SI)) { + // If we only have one predecessor, and if it is a branch on this value, + // see if that predecessor totally determines the outcome of this switch. + if (BasicBlock *OnlyPred = BB->getSinglePredecessor()) + if (SimplifyEqualityComparisonWithOnlyPredecessor(SI, OnlyPred)) + return SimplifyCFG(BB) || 1; + + // If the block only contains the switch, see if we can fold the block + // away into any preds. + BasicBlock::iterator BBI = BB->begin(); + // Ignore dbg intrinsics. + while (isa(BBI)) + ++BBI; + if (SI == &*BBI) + if (FoldValueComparisonIntoPredecessors(SI)) + return SimplifyCFG(BB) || 1; + } + } else if (BranchInst *BI = dyn_cast(BB->getTerminator())) { + if (BI->isUnconditional()) { + BasicBlock::iterator BBI = BB->getFirstNonPHI(); + + // Ignore dbg intrinsics. + while (isa(BBI)) + ++BBI; + if (BBI->isTerminator()) // Terminator is the only non-phi instruction! + if (TryToSimplifyUncondBranchFromEmptyBlock(BB)) + return true; + + } else { // Conditional branch + if (isValueEqualityComparison(BI)) { + // If we only have one predecessor, and if it is a branch on this value, + // see if that predecessor totally determines the outcome of this + // switch. + if (BasicBlock *OnlyPred = BB->getSinglePredecessor()) + if (SimplifyEqualityComparisonWithOnlyPredecessor(BI, OnlyPred)) + return SimplifyCFG(BB) || 1; + + // This block must be empty, except for the setcond inst, if it exists. + // Ignore dbg intrinsics. + BasicBlock::iterator I = BB->begin(); + // Ignore dbg intrinsics. + while (isa(I)) + ++I; + if (&*I == BI) { + if (FoldValueComparisonIntoPredecessors(BI)) + return SimplifyCFG(BB) | true; + } else if (&*I == cast(BI->getCondition())){ + ++I; + // Ignore dbg intrinsics. + while (isa(I)) + ++I; + if(&*I == BI) { + if (FoldValueComparisonIntoPredecessors(BI)) + return SimplifyCFG(BB) | true; + } + } + } + + // If this is a branch on a phi node in the current block, thread control + // through this block if any PHI node entries are constants. + if (PHINode *PN = dyn_cast(BI->getCondition())) + if (PN->getParent() == BI->getParent()) + if (FoldCondBranchOnPHI(BI)) + return SimplifyCFG(BB) | true; + + // If this basic block is ONLY a setcc and a branch, and if a predecessor + // branches to us and one of our successors, fold the setcc into the + // predecessor and use logical operations to pick the right destination. + if (FoldBranchToCommonDest(BI)) + return SimplifyCFG(BB) | 1; + + + // Scan predecessor blocks for conditional branches. + for (pred_iterator PI = pred_begin(BB), E = pred_end(BB); PI != E; ++PI) + if (BranchInst *PBI = dyn_cast((*PI)->getTerminator())) + if (PBI != BI && PBI->isConditional()) + if (SimplifyCondBranchToCondBranch(PBI, BI)) + return SimplifyCFG(BB) | true; + } + } else if (isa(BB->getTerminator())) { + // If there are any instructions immediately before the unreachable that can + // be removed, do so. + Instruction *Unreachable = BB->getTerminator(); + while (Unreachable != BB->begin()) { + BasicBlock::iterator BBI = Unreachable; + --BBI; + // Do not delete instructions that can have side effects, like calls + // (which may never return) and volatile loads and stores. + if (isa(BBI) && !isa(BBI)) break; + + if (StoreInst *SI = dyn_cast(BBI)) + if (SI->isVolatile()) + break; + + if (LoadInst *LI = dyn_cast(BBI)) + if (LI->isVolatile()) + break; + + // Delete this instruction + BB->getInstList().erase(BBI); + Changed = true; + } + + // If the unreachable instruction is the first in the block, take a gander + // at all of the predecessors of this instruction, and simplify them. + if (&BB->front() == Unreachable) { + SmallVector Preds(pred_begin(BB), pred_end(BB)); + for (unsigned i = 0, e = Preds.size(); i != e; ++i) { + TerminatorInst *TI = Preds[i]->getTerminator(); + + if (BranchInst *BI = dyn_cast(TI)) { + if (BI->isUnconditional()) { + if (BI->getSuccessor(0) == BB) { + new UnreachableInst(TI->getContext(), TI); + TI->eraseFromParent(); + Changed = true; + } + } else { + if (BI->getSuccessor(0) == BB) { + BranchInst::Create(BI->getSuccessor(1), BI); + EraseTerminatorInstAndDCECond(BI); + } else if (BI->getSuccessor(1) == BB) { + BranchInst::Create(BI->getSuccessor(0), BI); + EraseTerminatorInstAndDCECond(BI); + Changed = true; + } + } + } else if (SwitchInst *SI = dyn_cast(TI)) { + for (unsigned i = 1, e = SI->getNumCases(); i != e; ++i) + if (SI->getSuccessor(i) == BB) { + BB->removePredecessor(SI->getParent()); + SI->removeCase(i); + --i; --e; + Changed = true; + } + // If the default value is unreachable, figure out the most popular + // destination and make it the default. + if (SI->getSuccessor(0) == BB) { + std::map Popularity; + for (unsigned i = 1, e = SI->getNumCases(); i != e; ++i) + Popularity[SI->getSuccessor(i)]++; + + // Find the most popular block. + unsigned MaxPop = 0; + BasicBlock *MaxBlock = 0; + for (std::map::iterator + I = Popularity.begin(), E = Popularity.end(); I != E; ++I) { + if (I->second > MaxPop) { + MaxPop = I->second; + MaxBlock = I->first; + } + } + if (MaxBlock) { + // Make this the new default, allowing us to delete any explicit + // edges to it. + SI->setSuccessor(0, MaxBlock); + Changed = true; + + // If MaxBlock has phinodes in it, remove MaxPop-1 entries from + // it. + if (isa(MaxBlock->begin())) + for (unsigned i = 0; i != MaxPop-1; ++i) + MaxBlock->removePredecessor(SI->getParent()); + + for (unsigned i = 1, e = SI->getNumCases(); i != e; ++i) + if (SI->getSuccessor(i) == MaxBlock) { + SI->removeCase(i); + --i; --e; + } + } + } + } else if (InvokeInst *II = dyn_cast(TI)) { + if (II->getUnwindDest() == BB) { + // Convert the invoke to a call instruction. This would be a good + // place to note that the call does not throw though. + BranchInst *BI = BranchInst::Create(II->getNormalDest(), II); + II->removeFromParent(); // Take out of symbol table + + // Insert the call now... + SmallVector Args(II->op_begin()+3, II->op_end()); + CallInst *CI = CallInst::Create(II->getCalledValue(), + Args.begin(), Args.end(), + II->getName(), BI); + CI->setCallingConv(II->getCallingConv()); + CI->setAttributes(II->getAttributes()); + // If the invoke produced a value, the Call does now instead. + II->replaceAllUsesWith(CI); + delete II; + Changed = true; + } + } + } + + // If this block is now dead, remove it. + if (pred_begin(BB) == pred_end(BB)) { + // We know there are no successors, so just nuke the block. + M->getBasicBlockList().erase(BB); + return true; + } + } + } + + // Merge basic blocks into their predecessor if there is only one distinct + // pred, and if there is only one distinct successor of the predecessor, and + // if there are no PHI nodes. + // + if (MergeBlockIntoPredecessor(BB)) + return true; + + // Otherwise, if this block only has a single predecessor, and if that block + // is a conditional branch, see if we can hoist any code from this block up + // into our predecessor. + pred_iterator PI(pred_begin(BB)), PE(pred_end(BB)); + BasicBlock *OnlyPred = *PI++; + for (; PI != PE; ++PI) // Search all predecessors, see if they are all same + if (*PI != OnlyPred) { + OnlyPred = 0; // There are multiple different predecessors... + break; + } + + if (OnlyPred) + if (BranchInst *BI = dyn_cast(OnlyPred->getTerminator())) + if (BI->isConditional()) { + // Get the other block. + BasicBlock *OtherBB = BI->getSuccessor(BI->getSuccessor(0) == BB); + PI = pred_begin(OtherBB); + ++PI; + + if (PI == pred_end(OtherBB)) { + // We have a conditional branch to two blocks that are only reachable + // from the condbr. We know that the condbr dominates the two blocks, + // so see if there is any identical code in the "then" and "else" + // blocks. If so, we can hoist it up to the branching block. + Changed |= HoistThenElseCodeToIf(BI); + } else { + BasicBlock* OnlySucc = NULL; + for (succ_iterator SI = succ_begin(BB), SE = succ_end(BB); + SI != SE; ++SI) { + if (!OnlySucc) + OnlySucc = *SI; + else if (*SI != OnlySucc) { + OnlySucc = 0; // There are multiple distinct successors! + break; + } + } + + if (OnlySucc == OtherBB) { + // If BB's only successor is the other successor of the predecessor, + // i.e. a triangle, see if we can hoist any code from this block up + // to the "if" block. + Changed |= SpeculativelyExecuteBB(BI, BB); + } + } + } + + for (pred_iterator PI = pred_begin(BB), E = pred_end(BB); PI != E; ++PI) + if (BranchInst *BI = dyn_cast((*PI)->getTerminator())) + // Change br (X == 0 | X == 1), T, F into a switch instruction. + if (BI->isConditional() && isa(BI->getCondition())) { + Instruction *Cond = cast(BI->getCondition()); + // If this is a bunch of seteq's or'd together, or if it's a bunch of + // 'setne's and'ed together, collect them. + Value *CompVal = 0; + std::vector Values; + bool TrueWhenEqual = GatherValueComparisons(Cond, CompVal, Values); + if (CompVal && CompVal->getType()->isInteger()) { + // There might be duplicate constants in the list, which the switch + // instruction can't handle, remove them now. + std::sort(Values.begin(), Values.end(), ConstantIntOrdering()); + Values.erase(std::unique(Values.begin(), Values.end()), Values.end()); + + // Figure out which block is which destination. + BasicBlock *DefaultBB = BI->getSuccessor(1); + BasicBlock *EdgeBB = BI->getSuccessor(0); + if (!TrueWhenEqual) std::swap(DefaultBB, EdgeBB); + + // Create the new switch instruction now. + SwitchInst *New = SwitchInst::Create(CompVal, DefaultBB, + Values.size(), BI); + + // Add all of the 'cases' to the switch instruction. + for (unsigned i = 0, e = Values.size(); i != e; ++i) + New->addCase(Values[i], EdgeBB); + + // We added edges from PI to the EdgeBB. As such, if there were any + // PHI nodes in EdgeBB, they need entries to be added corresponding to + // the number of edges added. + for (BasicBlock::iterator BBI = EdgeBB->begin(); + isa(BBI); ++BBI) { + PHINode *PN = cast(BBI); + Value *InVal = PN->getIncomingValueForBlock(*PI); + for (unsigned i = 0, e = Values.size()-1; i != e; ++i) + PN->addIncoming(InVal, *PI); + } + + // Erase the old branch instruction. + EraseTerminatorInstAndDCECond(BI); + return true; + } + } + + return Changed; +} diff --git a/libclamav/c++/llvm/lib/Transforms/Utils/UnifyFunctionExitNodes.cpp b/libclamav/c++/llvm/lib/Transforms/Utils/UnifyFunctionExitNodes.cpp new file mode 100644 index 000000000..30cb94d90 --- /dev/null +++ b/libclamav/c++/llvm/lib/Transforms/Utils/UnifyFunctionExitNodes.cpp @@ -0,0 +1,141 @@ +//===- UnifyFunctionExitNodes.cpp - Make all functions have a single exit -===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This pass is used to ensure that functions have at most one return +// instruction in them. Additionally, it keeps track of which node is the new +// exit node of the CFG. If there are no exit nodes in the CFG, the getExitNode +// method will return a null pointer. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Transforms/Utils/UnifyFunctionExitNodes.h" +#include "llvm/Transforms/Scalar.h" +#include "llvm/BasicBlock.h" +#include "llvm/Function.h" +#include "llvm/Instructions.h" +#include "llvm/Type.h" +#include "llvm/ADT/StringExtras.h" +using namespace llvm; + +char UnifyFunctionExitNodes::ID = 0; +static RegisterPass +X("mergereturn", "Unify function exit nodes"); + +Pass *llvm::createUnifyFunctionExitNodesPass() { + return new UnifyFunctionExitNodes(); +} + +void UnifyFunctionExitNodes::getAnalysisUsage(AnalysisUsage &AU) const{ + // We preserve the non-critical-edgeness property + AU.addPreservedID(BreakCriticalEdgesID); + // This is a cluster of orthogonal Transforms + AU.addPreservedID(PromoteMemoryToRegisterID); + AU.addPreservedID(LowerSwitchID); +} + +// UnifyAllExitNodes - Unify all exit nodes of the CFG by creating a new +// BasicBlock, and converting all returns to unconditional branches to this +// new basic block. The singular exit node is returned. +// +// If there are no return stmts in the Function, a null pointer is returned. +// +bool UnifyFunctionExitNodes::runOnFunction(Function &F) { + // Loop over all of the blocks in a function, tracking all of the blocks that + // return. + // + std::vector ReturningBlocks; + std::vector UnwindingBlocks; + std::vector UnreachableBlocks; + for(Function::iterator I = F.begin(), E = F.end(); I != E; ++I) + if (isa(I->getTerminator())) + ReturningBlocks.push_back(I); + else if (isa(I->getTerminator())) + UnwindingBlocks.push_back(I); + else if (isa(I->getTerminator())) + UnreachableBlocks.push_back(I); + + // Handle unwinding blocks first. + if (UnwindingBlocks.empty()) { + UnwindBlock = 0; + } else if (UnwindingBlocks.size() == 1) { + UnwindBlock = UnwindingBlocks.front(); + } else { + UnwindBlock = BasicBlock::Create(F.getContext(), "UnifiedUnwindBlock", &F); + new UnwindInst(F.getContext(), UnwindBlock); + + for (std::vector::iterator I = UnwindingBlocks.begin(), + E = UnwindingBlocks.end(); I != E; ++I) { + BasicBlock *BB = *I; + BB->getInstList().pop_back(); // Remove the unwind insn + BranchInst::Create(UnwindBlock, BB); + } + } + + // Then unreachable blocks. + if (UnreachableBlocks.empty()) { + UnreachableBlock = 0; + } else if (UnreachableBlocks.size() == 1) { + UnreachableBlock = UnreachableBlocks.front(); + } else { + UnreachableBlock = BasicBlock::Create(F.getContext(), + "UnifiedUnreachableBlock", &F); + new UnreachableInst(F.getContext(), UnreachableBlock); + + for (std::vector::iterator I = UnreachableBlocks.begin(), + E = UnreachableBlocks.end(); I != E; ++I) { + BasicBlock *BB = *I; + BB->getInstList().pop_back(); // Remove the unreachable inst. + BranchInst::Create(UnreachableBlock, BB); + } + } + + // Now handle return blocks. + if (ReturningBlocks.empty()) { + ReturnBlock = 0; + return false; // No blocks return + } else if (ReturningBlocks.size() == 1) { + ReturnBlock = ReturningBlocks.front(); // Already has a single return block + return false; + } + + // Otherwise, we need to insert a new basic block into the function, add a PHI + // nodes (if the function returns values), and convert all of the return + // instructions into unconditional branches. + // + BasicBlock *NewRetBlock = BasicBlock::Create(F.getContext(), + "UnifiedReturnBlock", &F); + + PHINode *PN = 0; + if (F.getReturnType() == Type::getVoidTy(F.getContext())) { + ReturnInst::Create(F.getContext(), NULL, NewRetBlock); + } else { + // If the function doesn't return void... add a PHI node to the block... + PN = PHINode::Create(F.getReturnType(), "UnifiedRetVal"); + NewRetBlock->getInstList().push_back(PN); + ReturnInst::Create(F.getContext(), PN, NewRetBlock); + } + + // Loop over all of the blocks, replacing the return instruction with an + // unconditional branch. + // + for (std::vector::iterator I = ReturningBlocks.begin(), + E = ReturningBlocks.end(); I != E; ++I) { + BasicBlock *BB = *I; + + // Add an incoming element to the PHI node for every return instruction that + // is merging into this new block... + if (PN) + PN->addIncoming(BB->getTerminator()->getOperand(0), BB); + + BB->getInstList().pop_back(); // Remove the return insn + BranchInst::Create(NewRetBlock, BB); + } + ReturnBlock = NewRetBlock; + return true; +} diff --git a/libclamav/c++/llvm/lib/Transforms/Utils/ValueMapper.cpp b/libclamav/c++/llvm/lib/Transforms/Utils/ValueMapper.cpp new file mode 100644 index 000000000..39331d781 --- /dev/null +++ b/libclamav/c++/llvm/lib/Transforms/Utils/ValueMapper.cpp @@ -0,0 +1,133 @@ +//===- ValueMapper.cpp - Interface shared by lib/Transforms/Utils ---------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the MapValue function, which is shared by various parts of +// the lib/Transforms/Utils library. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Transforms/Utils/ValueMapper.h" +#include "llvm/DerivedTypes.h" // For getNullValue(Type::Int32Ty) +#include "llvm/Constants.h" +#include "llvm/Function.h" +#include "llvm/Metadata.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/ErrorHandling.h" +using namespace llvm; + +Value *llvm::MapValue(const Value *V, ValueMapTy &VM) { + Value *&VMSlot = VM[V]; + if (VMSlot) return VMSlot; // Does it exist in the map yet? + + // NOTE: VMSlot can be invalidated by any reference to VM, which can grow the + // DenseMap. This includes any recursive calls to MapValue. + + // Global values and metadata do not need to be seeded into the ValueMap if + // they are using the identity mapping. + if (isa(V) || isa(V) || isa(V)) + return VMSlot = const_cast(V); + + Constant *C = const_cast(dyn_cast(V)); + if (C == 0) return 0; + + if (isa(C) || isa(C) || + isa(C) || isa(C) || + isa(C) || isa(C)) + return VMSlot = C; // Primitive constants map directly + + if (ConstantArray *CA = dyn_cast(C)) { + for (User::op_iterator b = CA->op_begin(), i = b, e = CA->op_end(); + i != e; ++i) { + Value *MV = MapValue(*i, VM); + if (MV != *i) { + // This array must contain a reference to a global, make a new array + // and return it. + // + std::vector Values; + Values.reserve(CA->getNumOperands()); + for (User::op_iterator j = b; j != i; ++j) + Values.push_back(cast(*j)); + Values.push_back(cast(MV)); + for (++i; i != e; ++i) + Values.push_back(cast(MapValue(*i, VM))); + return VM[V] = ConstantArray::get(CA->getType(), Values); + } + } + return VM[V] = C; + } + + if (ConstantStruct *CS = dyn_cast(C)) { + for (User::op_iterator b = CS->op_begin(), i = b, e = CS->op_end(); + i != e; ++i) { + Value *MV = MapValue(*i, VM); + if (MV != *i) { + // This struct must contain a reference to a global, make a new struct + // and return it. + // + std::vector Values; + Values.reserve(CS->getNumOperands()); + for (User::op_iterator j = b; j != i; ++j) + Values.push_back(cast(*j)); + Values.push_back(cast(MV)); + for (++i; i != e; ++i) + Values.push_back(cast(MapValue(*i, VM))); + return VM[V] = ConstantStruct::get(CS->getType(), Values); + } + } + return VM[V] = C; + } + + if (ConstantExpr *CE = dyn_cast(C)) { + std::vector Ops; + for (User::op_iterator i = CE->op_begin(), e = CE->op_end(); i != e; ++i) + Ops.push_back(cast(MapValue(*i, VM))); + return VM[V] = CE->getWithOperands(Ops); + } + + if (ConstantVector *CV = dyn_cast(C)) { + for (User::op_iterator b = CV->op_begin(), i = b, e = CV->op_end(); + i != e; ++i) { + Value *MV = MapValue(*i, VM); + if (MV != *i) { + // This vector value must contain a reference to a global, make a new + // vector constant and return it. + // + std::vector Values; + Values.reserve(CV->getNumOperands()); + for (User::op_iterator j = b; j != i; ++j) + Values.push_back(cast(*j)); + Values.push_back(cast(MV)); + for (++i; i != e; ++i) + Values.push_back(cast(MapValue(*i, VM))); + return VM[V] = ConstantVector::get(Values); + } + } + return VM[V] = C; + } + + if (BlockAddress *BA = dyn_cast(C)) { + Function *F = cast(MapValue(BA->getFunction(), VM)); + BasicBlock *BB = cast_or_null(MapValue(BA->getBasicBlock(),VM)); + return VM[V] = BlockAddress::get(F, BB ? BB : BA->getBasicBlock()); + } + + llvm_unreachable("Unknown type of constant!"); + return 0; +} + +/// RemapInstruction - Convert the instruction operands from referencing the +/// current values into those specified by ValueMap. +/// +void llvm::RemapInstruction(Instruction *I, ValueMapTy &ValueMap) { + for (User::op_iterator op = I->op_begin(), E = I->op_end(); op != E; ++op) { + Value *V = MapValue(*op, ValueMap); + assert(V && "Referenced value not in value map!"); + *op = V; + } +} diff --git a/libclamav/c++/llvm/lib/VMCore/AsmWriter.cpp b/libclamav/c++/llvm/lib/VMCore/AsmWriter.cpp new file mode 100644 index 000000000..82d791477 --- /dev/null +++ b/libclamav/c++/llvm/lib/VMCore/AsmWriter.cpp @@ -0,0 +1,2176 @@ +//===-- AsmWriter.cpp - Printing LLVM as an assembly file -----------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This library implements the functionality defined in llvm/Assembly/Writer.h +// +// Note that these routines must be extremely tolerant of various errors in the +// LLVM code, because it can be used for debugging transformations. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Assembly/Writer.h" +#include "llvm/Assembly/PrintModulePass.h" +#include "llvm/Assembly/AsmAnnotationWriter.h" +#include "llvm/CallingConv.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/InlineAsm.h" +#include "llvm/Instruction.h" +#include "llvm/Instructions.h" +#include "llvm/LLVMContext.h" +#include "llvm/Operator.h" +#include "llvm/Metadata.h" +#include "llvm/Module.h" +#include "llvm/ValueSymbolTable.h" +#include "llvm/TypeSymbolTable.h" +#include "llvm/ADT/DenseSet.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/Support/CFG.h" +#include "llvm/Support/Dwarf.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/Support/FormattedStream.h" +#include +#include +#include +using namespace llvm; + +// Make virtual table appear in this compilation unit. +AssemblyAnnotationWriter::~AssemblyAnnotationWriter() {} + +//===----------------------------------------------------------------------===// +// Helper Functions +//===----------------------------------------------------------------------===// + +static const Module *getModuleFromVal(const Value *V) { + if (const Argument *MA = dyn_cast(V)) + return MA->getParent() ? MA->getParent()->getParent() : 0; + + if (const BasicBlock *BB = dyn_cast(V)) + return BB->getParent() ? BB->getParent()->getParent() : 0; + + if (const Instruction *I = dyn_cast(V)) { + const Function *M = I->getParent() ? I->getParent()->getParent() : 0; + return M ? M->getParent() : 0; + } + + if (const GlobalValue *GV = dyn_cast(V)) + return GV->getParent(); + return 0; +} + +// PrintEscapedString - Print each character of the specified string, escaping +// it if it is not printable or if it is an escape char. +static void PrintEscapedString(const StringRef &Name, + raw_ostream &Out) { + for (unsigned i = 0, e = Name.size(); i != e; ++i) { + unsigned char C = Name[i]; + if (isprint(C) && C != '\\' && C != '"') + Out << C; + else + Out << '\\' << hexdigit(C >> 4) << hexdigit(C & 0x0F); + } +} + +enum PrefixType { + GlobalPrefix, + LabelPrefix, + LocalPrefix, + NoPrefix +}; + +/// PrintLLVMName - Turn the specified name into an 'LLVM name', which is either +/// prefixed with % (if the string only contains simple characters) or is +/// surrounded with ""'s (if it has special chars in it). Print it out. +static void PrintLLVMName(raw_ostream &OS, const StringRef &Name, + PrefixType Prefix) { + assert(Name.data() && "Cannot get empty name!"); + switch (Prefix) { + default: llvm_unreachable("Bad prefix!"); + case NoPrefix: break; + case GlobalPrefix: OS << '@'; break; + case LabelPrefix: break; + case LocalPrefix: OS << '%'; break; + } + + // Scan the name to see if it needs quotes first. + bool NeedsQuotes = isdigit(Name[0]); + if (!NeedsQuotes) { + for (unsigned i = 0, e = Name.size(); i != e; ++i) { + char C = Name[i]; + if (!isalnum(C) && C != '-' && C != '.' && C != '_') { + NeedsQuotes = true; + break; + } + } + } + + // If we didn't need any quotes, just write out the name in one blast. + if (!NeedsQuotes) { + OS << Name; + return; + } + + // Okay, we need quotes. Output the quotes and escape any scary characters as + // needed. + OS << '"'; + PrintEscapedString(Name, OS); + OS << '"'; +} + +/// PrintLLVMName - Turn the specified name into an 'LLVM name', which is either +/// prefixed with % (if the string only contains simple characters) or is +/// surrounded with ""'s (if it has special chars in it). Print it out. +static void PrintLLVMName(raw_ostream &OS, const Value *V) { + PrintLLVMName(OS, V->getName(), + isa(V) ? GlobalPrefix : LocalPrefix); +} + +//===----------------------------------------------------------------------===// +// TypePrinting Class: Type printing machinery +//===----------------------------------------------------------------------===// + +static DenseMap &getTypeNamesMap(void *M) { + return *static_cast*>(M); +} + +void TypePrinting::clear() { + getTypeNamesMap(TypeNames).clear(); +} + +bool TypePrinting::hasTypeName(const Type *Ty) const { + return getTypeNamesMap(TypeNames).count(Ty); +} + +void TypePrinting::addTypeName(const Type *Ty, const std::string &N) { + getTypeNamesMap(TypeNames).insert(std::make_pair(Ty, N)); +} + + +TypePrinting::TypePrinting() { + TypeNames = new DenseMap(); +} + +TypePrinting::~TypePrinting() { + delete &getTypeNamesMap(TypeNames); +} + +/// CalcTypeName - Write the specified type to the specified raw_ostream, making +/// use of type names or up references to shorten the type name where possible. +void TypePrinting::CalcTypeName(const Type *Ty, + SmallVectorImpl &TypeStack, + raw_ostream &OS, bool IgnoreTopLevelName) { + // Check to see if the type is named. + if (!IgnoreTopLevelName) { + DenseMap &TM = getTypeNamesMap(TypeNames); + DenseMap::iterator I = TM.find(Ty); + if (I != TM.end()) { + OS << I->second; + return; + } + } + + // Check to see if the Type is already on the stack... + unsigned Slot = 0, CurSize = TypeStack.size(); + while (Slot < CurSize && TypeStack[Slot] != Ty) ++Slot; // Scan for type + + // This is another base case for the recursion. In this case, we know + // that we have looped back to a type that we have previously visited. + // Generate the appropriate upreference to handle this. + if (Slot < CurSize) { + OS << '\\' << unsigned(CurSize-Slot); // Here's the upreference + return; + } + + TypeStack.push_back(Ty); // Recursive case: Add us to the stack.. + + switch (Ty->getTypeID()) { + case Type::VoidTyID: OS << "void"; break; + case Type::FloatTyID: OS << "float"; break; + case Type::DoubleTyID: OS << "double"; break; + case Type::X86_FP80TyID: OS << "x86_fp80"; break; + case Type::FP128TyID: OS << "fp128"; break; + case Type::PPC_FP128TyID: OS << "ppc_fp128"; break; + case Type::LabelTyID: OS << "label"; break; + case Type::MetadataTyID: OS << "metadata"; break; + case Type::IntegerTyID: + OS << 'i' << cast(Ty)->getBitWidth(); + break; + + case Type::FunctionTyID: { + const FunctionType *FTy = cast(Ty); + CalcTypeName(FTy->getReturnType(), TypeStack, OS); + OS << " ("; + for (FunctionType::param_iterator I = FTy->param_begin(), + E = FTy->param_end(); I != E; ++I) { + if (I != FTy->param_begin()) + OS << ", "; + CalcTypeName(*I, TypeStack, OS); + } + if (FTy->isVarArg()) { + if (FTy->getNumParams()) OS << ", "; + OS << "..."; + } + OS << ')'; + break; + } + case Type::StructTyID: { + const StructType *STy = cast(Ty); + if (STy->isPacked()) + OS << '<'; + OS << "{ "; + for (StructType::element_iterator I = STy->element_begin(), + E = STy->element_end(); I != E; ++I) { + CalcTypeName(*I, TypeStack, OS); + if (next(I) != STy->element_end()) + OS << ','; + OS << ' '; + } + OS << '}'; + if (STy->isPacked()) + OS << '>'; + break; + } + case Type::PointerTyID: { + const PointerType *PTy = cast(Ty); + CalcTypeName(PTy->getElementType(), TypeStack, OS); + if (unsigned AddressSpace = PTy->getAddressSpace()) + OS << " addrspace(" << AddressSpace << ')'; + OS << '*'; + break; + } + case Type::ArrayTyID: { + const ArrayType *ATy = cast(Ty); + OS << '[' << ATy->getNumElements() << " x "; + CalcTypeName(ATy->getElementType(), TypeStack, OS); + OS << ']'; + break; + } + case Type::VectorTyID: { + const VectorType *PTy = cast(Ty); + OS << "<" << PTy->getNumElements() << " x "; + CalcTypeName(PTy->getElementType(), TypeStack, OS); + OS << '>'; + break; + } + case Type::OpaqueTyID: + OS << "opaque"; + break; + default: + OS << ""; + break; + } + + TypeStack.pop_back(); // Remove self from stack. +} + +/// printTypeInt - The internal guts of printing out a type that has a +/// potentially named portion. +/// +void TypePrinting::print(const Type *Ty, raw_ostream &OS, + bool IgnoreTopLevelName) { + // Check to see if the type is named. + DenseMap &TM = getTypeNamesMap(TypeNames); + if (!IgnoreTopLevelName) { + DenseMap::iterator I = TM.find(Ty); + if (I != TM.end()) { + OS << I->second; + return; + } + } + + // Otherwise we have a type that has not been named but is a derived type. + // Carefully recurse the type hierarchy to print out any contained symbolic + // names. + SmallVector TypeStack; + std::string TypeName; + + raw_string_ostream TypeOS(TypeName); + CalcTypeName(Ty, TypeStack, TypeOS, IgnoreTopLevelName); + OS << TypeOS.str(); + + // Cache type name for later use. + if (!IgnoreTopLevelName) + TM.insert(std::make_pair(Ty, TypeOS.str())); +} + +namespace { + class TypeFinder { + // To avoid walking constant expressions multiple times and other IR + // objects, we keep several helper maps. + DenseSet VisitedConstants; + DenseSet VisitedTypes; + + TypePrinting &TP; + std::vector &NumberedTypes; + public: + TypeFinder(TypePrinting &tp, std::vector &numberedTypes) + : TP(tp), NumberedTypes(numberedTypes) {} + + void Run(const Module &M) { + // Get types from the type symbol table. This gets opaque types referened + // only through derived named types. + const TypeSymbolTable &ST = M.getTypeSymbolTable(); + for (TypeSymbolTable::const_iterator TI = ST.begin(), E = ST.end(); + TI != E; ++TI) + IncorporateType(TI->second); + + // Get types from global variables. + for (Module::const_global_iterator I = M.global_begin(), + E = M.global_end(); I != E; ++I) { + IncorporateType(I->getType()); + if (I->hasInitializer()) + IncorporateValue(I->getInitializer()); + } + + // Get types from aliases. + for (Module::const_alias_iterator I = M.alias_begin(), + E = M.alias_end(); I != E; ++I) { + IncorporateType(I->getType()); + IncorporateValue(I->getAliasee()); + } + + // Get types from functions. + for (Module::const_iterator FI = M.begin(), E = M.end(); FI != E; ++FI) { + IncorporateType(FI->getType()); + + for (Function::const_iterator BB = FI->begin(), E = FI->end(); + BB != E;++BB) + for (BasicBlock::const_iterator II = BB->begin(), + E = BB->end(); II != E; ++II) { + const Instruction &I = *II; + // Incorporate the type of the instruction and all its operands. + IncorporateType(I.getType()); + for (User::const_op_iterator OI = I.op_begin(), OE = I.op_end(); + OI != OE; ++OI) + IncorporateValue(*OI); + } + } + } + + private: + void IncorporateType(const Type *Ty) { + // Check to see if we're already visited this type. + if (!VisitedTypes.insert(Ty).second) + return; + + // If this is a structure or opaque type, add a name for the type. + if (((isa(Ty) && cast(Ty)->getNumElements()) + || isa(Ty)) && !TP.hasTypeName(Ty)) { + TP.addTypeName(Ty, "%"+utostr(unsigned(NumberedTypes.size()))); + NumberedTypes.push_back(Ty); + } + + // Recursively walk all contained types. + for (Type::subtype_iterator I = Ty->subtype_begin(), + E = Ty->subtype_end(); I != E; ++I) + IncorporateType(*I); + } + + /// IncorporateValue - This method is used to walk operand lists finding + /// types hiding in constant expressions and other operands that won't be + /// walked in other ways. GlobalValues, basic blocks, instructions, and + /// inst operands are all explicitly enumerated. + void IncorporateValue(const Value *V) { + if (V == 0 || !isa(V) || isa(V)) return; + + // Already visited? + if (!VisitedConstants.insert(V).second) + return; + + // Check this type. + IncorporateType(V->getType()); + + // Look in operands for types. + const Constant *C = cast(V); + for (Constant::const_op_iterator I = C->op_begin(), + E = C->op_end(); I != E;++I) + IncorporateValue(*I); + } + }; +} // end anonymous namespace + + +/// AddModuleTypesToPrinter - Add all of the symbolic type names for types in +/// the specified module to the TypePrinter and all numbered types to it and the +/// NumberedTypes table. +static void AddModuleTypesToPrinter(TypePrinting &TP, + std::vector &NumberedTypes, + const Module *M) { + if (M == 0) return; + + // If the module has a symbol table, take all global types and stuff their + // names into the TypeNames map. + const TypeSymbolTable &ST = M->getTypeSymbolTable(); + for (TypeSymbolTable::const_iterator TI = ST.begin(), E = ST.end(); + TI != E; ++TI) { + const Type *Ty = cast(TI->second); + + // As a heuristic, don't insert pointer to primitive types, because + // they are used too often to have a single useful name. + if (const PointerType *PTy = dyn_cast(Ty)) { + const Type *PETy = PTy->getElementType(); + if ((PETy->isPrimitiveType() || PETy->isInteger()) && + !isa(PETy)) + continue; + } + + // Likewise don't insert primitives either. + if (Ty->isInteger() || Ty->isPrimitiveType()) + continue; + + // Get the name as a string and insert it into TypeNames. + std::string NameStr; + raw_string_ostream NameROS(NameStr); + formatted_raw_ostream NameOS(NameROS); + PrintLLVMName(NameOS, TI->first, LocalPrefix); + NameOS.flush(); + TP.addTypeName(Ty, NameStr); + } + + // Walk the entire module to find references to unnamed structure and opaque + // types. This is required for correctness by opaque types (because multiple + // uses of an unnamed opaque type needs to be referred to by the same ID) and + // it shrinks complex recursive structure types substantially in some cases. + TypeFinder(TP, NumberedTypes).Run(*M); +} + + +/// WriteTypeSymbolic - This attempts to write the specified type as a symbolic +/// type, iff there is an entry in the modules symbol table for the specified +/// type or one of it's component types. +/// +void llvm::WriteTypeSymbolic(raw_ostream &OS, const Type *Ty, const Module *M) { + TypePrinting Printer; + std::vector NumberedTypes; + AddModuleTypesToPrinter(Printer, NumberedTypes, M); + Printer.print(Ty, OS); +} + +//===----------------------------------------------------------------------===// +// SlotTracker Class: Enumerate slot numbers for unnamed values +//===----------------------------------------------------------------------===// + +namespace { + +/// This class provides computation of slot numbers for LLVM Assembly writing. +/// +class SlotTracker { +public: + /// ValueMap - A mapping of Values to slot numbers. + typedef DenseMap ValueMap; + +private: + /// TheModule - The module for which we are holding slot numbers. + const Module* TheModule; + + /// TheFunction - The function for which we are holding slot numbers. + const Function* TheFunction; + bool FunctionProcessed; + + /// TheMDNode - The MDNode for which we are holding slot numbers. + const MDNode *TheMDNode; + + /// TheNamedMDNode - The MDNode for which we are holding slot numbers. + const NamedMDNode *TheNamedMDNode; + + /// mMap - The TypePlanes map for the module level data. + ValueMap mMap; + unsigned mNext; + + /// fMap - The TypePlanes map for the function level data. + ValueMap fMap; + unsigned fNext; + + /// mdnMap - Map for MDNodes. + ValueMap mdnMap; + unsigned mdnNext; +public: + /// Construct from a module + explicit SlotTracker(const Module *M); + /// Construct from a function, starting out in incorp state. + explicit SlotTracker(const Function *F); + /// Construct from a mdnode. + explicit SlotTracker(const MDNode *N); + /// Construct from a named mdnode. + explicit SlotTracker(const NamedMDNode *N); + + /// Return the slot number of the specified value in it's type + /// plane. If something is not in the SlotTracker, return -1. + int getLocalSlot(const Value *V); + int getGlobalSlot(const GlobalValue *V); + int getMetadataSlot(const MDNode *N); + + /// If you'd like to deal with a function instead of just a module, use + /// this method to get its data into the SlotTracker. + void incorporateFunction(const Function *F) { + TheFunction = F; + FunctionProcessed = false; + } + + /// After calling incorporateFunction, use this method to remove the + /// most recently incorporated function from the SlotTracker. This + /// will reset the state of the machine back to just the module contents. + void purgeFunction(); + + /// MDNode map iterators. + ValueMap::iterator mdnBegin() { return mdnMap.begin(); } + ValueMap::iterator mdnEnd() { return mdnMap.end(); } + unsigned mdnSize() const { return mdnMap.size(); } + bool mdnEmpty() const { return mdnMap.empty(); } + + /// This function does the actual initialization. + inline void initialize(); + + // Implementation Details +private: + /// CreateModuleSlot - Insert the specified GlobalValue* into the slot table. + void CreateModuleSlot(const GlobalValue *V); + + /// CreateMetadataSlot - Insert the specified MDNode* into the slot table. + void CreateMetadataSlot(const MDNode *N); + + /// CreateFunctionSlot - Insert the specified Value* into the slot table. + void CreateFunctionSlot(const Value *V); + + /// Add all of the module level global variables (and their initializers) + /// and function declarations, but not the contents of those functions. + void processModule(); + + /// Add all of the functions arguments, basic blocks, and instructions. + void processFunction(); + + /// Add all MDNode operands. + void processMDNode(); + + /// Add all MDNode operands. + void processNamedMDNode(); + + SlotTracker(const SlotTracker &); // DO NOT IMPLEMENT + void operator=(const SlotTracker &); // DO NOT IMPLEMENT +}; + +} // end anonymous namespace + + +static SlotTracker *createSlotTracker(const Value *V) { + if (const Argument *FA = dyn_cast(V)) + return new SlotTracker(FA->getParent()); + + if (const Instruction *I = dyn_cast(V)) + return new SlotTracker(I->getParent()->getParent()); + + if (const BasicBlock *BB = dyn_cast(V)) + return new SlotTracker(BB->getParent()); + + if (const GlobalVariable *GV = dyn_cast(V)) + return new SlotTracker(GV->getParent()); + + if (const GlobalAlias *GA = dyn_cast(V)) + return new SlotTracker(GA->getParent()); + + if (const Function *Func = dyn_cast(V)) + return new SlotTracker(Func); + + return 0; +} + +#if 0 +#define ST_DEBUG(X) errs() << X +#else +#define ST_DEBUG(X) +#endif + +// Module level constructor. Causes the contents of the Module (sans functions) +// to be added to the slot table. +SlotTracker::SlotTracker(const Module *M) + : TheModule(M), TheFunction(0), FunctionProcessed(false), TheMDNode(0), + TheNamedMDNode(0), mNext(0), fNext(0), mdnNext(0) { +} + +// Function level constructor. Causes the contents of the Module and the one +// function provided to be added to the slot table. +SlotTracker::SlotTracker(const Function *F) + : TheModule(F ? F->getParent() : 0), TheFunction(F), FunctionProcessed(false), + TheMDNode(0), TheNamedMDNode(0), mNext(0), fNext(0), mdnNext(0) { +} + +// Constructor to handle single MDNode. +SlotTracker::SlotTracker(const MDNode *C) + : TheModule(0), TheFunction(0), FunctionProcessed(false), TheMDNode(C), + TheNamedMDNode(0), mNext(0), fNext(0), mdnNext(0) { +} + +// Constructor to handle single NamedMDNode. +SlotTracker::SlotTracker(const NamedMDNode *N) + : TheModule(0), TheFunction(0), FunctionProcessed(false), TheMDNode(0), + TheNamedMDNode(N), mNext(0), fNext(0), mdnNext(0) { +} + +inline void SlotTracker::initialize() { + if (TheModule) { + processModule(); + TheModule = 0; ///< Prevent re-processing next time we're called. + } + + if (TheFunction && !FunctionProcessed) + processFunction(); + + if (TheMDNode) + processMDNode(); + + if (TheNamedMDNode) + processNamedMDNode(); +} + +// Iterate through all the global variables, functions, and global +// variable initializers and create slots for them. +void SlotTracker::processModule() { + ST_DEBUG("begin processModule!\n"); + + // Add all of the unnamed global variables to the value table. + for (Module::const_global_iterator I = TheModule->global_begin(), + E = TheModule->global_end(); I != E; ++I) { + if (!I->hasName()) + CreateModuleSlot(I); + if (I->hasInitializer()) { + if (MDNode *N = dyn_cast(I->getInitializer())) + CreateMetadataSlot(N); + } + } + + // Add metadata used by named metadata. + for (Module::const_named_metadata_iterator + I = TheModule->named_metadata_begin(), + E = TheModule->named_metadata_end(); I != E; ++I) { + const NamedMDNode *NMD = I; + for (unsigned i = 0, e = NMD->getNumElements(); i != e; ++i) { + MDNode *MD = dyn_cast_or_null(NMD->getElement(i)); + if (MD) + CreateMetadataSlot(MD); + } + } + + // Add all the unnamed functions to the table. + for (Module::const_iterator I = TheModule->begin(), E = TheModule->end(); + I != E; ++I) + if (!I->hasName()) + CreateModuleSlot(I); + + ST_DEBUG("end processModule!\n"); +} + +// Process the arguments, basic blocks, and instructions of a function. +void SlotTracker::processFunction() { + ST_DEBUG("begin processFunction!\n"); + fNext = 0; + + // Add all the function arguments with no names. + for(Function::const_arg_iterator AI = TheFunction->arg_begin(), + AE = TheFunction->arg_end(); AI != AE; ++AI) + if (!AI->hasName()) + CreateFunctionSlot(AI); + + ST_DEBUG("Inserting Instructions:\n"); + + MetadataContext &TheMetadata = TheFunction->getContext().getMetadata(); + typedef SmallVector >, 2> MDMapTy; + MDMapTy MDs; + + // Add all of the basic blocks and instructions with no names. + for (Function::const_iterator BB = TheFunction->begin(), + E = TheFunction->end(); BB != E; ++BB) { + if (!BB->hasName()) + CreateFunctionSlot(BB); + for (BasicBlock::const_iterator I = BB->begin(), E = BB->end(); I != E; + ++I) { + if (I->getType() != Type::getVoidTy(TheFunction->getContext()) && + !I->hasName()) + CreateFunctionSlot(I); + for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i) + if (MDNode *N = dyn_cast_or_null(I->getOperand(i))) + CreateMetadataSlot(N); + + // Process metadata attached with this instruction. + MDs.clear(); + TheMetadata.getMDs(I, MDs); + for (MDMapTy::const_iterator MI = MDs.begin(), ME = MDs.end(); MI != ME; + ++MI) + CreateMetadataSlot(MI->second); + } + } + + FunctionProcessed = true; + + ST_DEBUG("end processFunction!\n"); +} + +/// processMDNode - Process TheMDNode. +void SlotTracker::processMDNode() { + ST_DEBUG("begin processMDNode!\n"); + mdnNext = 0; + CreateMetadataSlot(TheMDNode); + TheMDNode = 0; + ST_DEBUG("end processMDNode!\n"); +} + +/// processNamedMDNode - Process TheNamedMDNode. +void SlotTracker::processNamedMDNode() { + ST_DEBUG("begin processNamedMDNode!\n"); + mdnNext = 0; + for (unsigned i = 0, e = TheNamedMDNode->getNumElements(); i != e; ++i) { + MDNode *MD = dyn_cast_or_null(TheNamedMDNode->getElement(i)); + if (MD) + CreateMetadataSlot(MD); + } + TheNamedMDNode = 0; + ST_DEBUG("end processNamedMDNode!\n"); +} + +/// Clean up after incorporating a function. This is the only way to get out of +/// the function incorporation state that affects get*Slot/Create*Slot. Function +/// incorporation state is indicated by TheFunction != 0. +void SlotTracker::purgeFunction() { + ST_DEBUG("begin purgeFunction!\n"); + fMap.clear(); // Simply discard the function level map + TheFunction = 0; + FunctionProcessed = false; + ST_DEBUG("end purgeFunction!\n"); +} + +/// getGlobalSlot - Get the slot number of a global value. +int SlotTracker::getGlobalSlot(const GlobalValue *V) { + // Check for uninitialized state and do lazy initialization. + initialize(); + + // Find the type plane in the module map + ValueMap::iterator MI = mMap.find(V); + return MI == mMap.end() ? -1 : (int)MI->second; +} + +/// getGlobalSlot - Get the slot number of a MDNode. +int SlotTracker::getMetadataSlot(const MDNode *N) { + // Check for uninitialized state and do lazy initialization. + initialize(); + + // Find the type plane in the module map + ValueMap::iterator MI = mdnMap.find(N); + return MI == mdnMap.end() ? -1 : (int)MI->second; +} + + +/// getLocalSlot - Get the slot number for a value that is local to a function. +int SlotTracker::getLocalSlot(const Value *V) { + assert(!isa(V) && "Can't get a constant or global slot with this!"); + + // Check for uninitialized state and do lazy initialization. + initialize(); + + ValueMap::iterator FI = fMap.find(V); + return FI == fMap.end() ? -1 : (int)FI->second; +} + + +/// CreateModuleSlot - Insert the specified GlobalValue* into the slot table. +void SlotTracker::CreateModuleSlot(const GlobalValue *V) { + assert(V && "Can't insert a null Value into SlotTracker!"); + assert(V->getType() != Type::getVoidTy(V->getContext()) && + "Doesn't need a slot!"); + assert(!V->hasName() && "Doesn't need a slot!"); + + unsigned DestSlot = mNext++; + mMap[V] = DestSlot; + + ST_DEBUG(" Inserting value [" << V->getType() << "] = " << V << " slot=" << + DestSlot << " ["); + // G = Global, F = Function, A = Alias, o = other + ST_DEBUG((isa(V) ? 'G' : + (isa(V) ? 'F' : + (isa(V) ? 'A' : 'o'))) << "]\n"); +} + +/// CreateSlot - Create a new slot for the specified value if it has no name. +void SlotTracker::CreateFunctionSlot(const Value *V) { + assert(V->getType() != Type::getVoidTy(TheFunction->getContext()) && + !V->hasName() && "Doesn't need a slot!"); + + unsigned DestSlot = fNext++; + fMap[V] = DestSlot; + + // G = Global, F = Function, o = other + ST_DEBUG(" Inserting value [" << V->getType() << "] = " << V << " slot=" << + DestSlot << " [o]\n"); +} + +/// CreateModuleSlot - Insert the specified MDNode* into the slot table. +void SlotTracker::CreateMetadataSlot(const MDNode *N) { + assert(N && "Can't insert a null Value into SlotTracker!"); + + ValueMap::iterator I = mdnMap.find(N); + if (I != mdnMap.end()) + return; + + unsigned DestSlot = mdnNext++; + mdnMap[N] = DestSlot; + + for (unsigned i = 0, e = N->getNumElements(); i != e; ++i) { + const Value *TV = N->getElement(i); + if (TV) + if (const MDNode *N2 = dyn_cast(TV)) + CreateMetadataSlot(N2); + } +} + +//===----------------------------------------------------------------------===// +// AsmWriter Implementation +//===----------------------------------------------------------------------===// + +static void WriteAsOperandInternal(raw_ostream &Out, const Value *V, + TypePrinting *TypePrinter, + SlotTracker *Machine); + + + +static const char *getPredicateText(unsigned predicate) { + const char * pred = "unknown"; + switch (predicate) { + case FCmpInst::FCMP_FALSE: pred = "false"; break; + case FCmpInst::FCMP_OEQ: pred = "oeq"; break; + case FCmpInst::FCMP_OGT: pred = "ogt"; break; + case FCmpInst::FCMP_OGE: pred = "oge"; break; + case FCmpInst::FCMP_OLT: pred = "olt"; break; + case FCmpInst::FCMP_OLE: pred = "ole"; break; + case FCmpInst::FCMP_ONE: pred = "one"; break; + case FCmpInst::FCMP_ORD: pred = "ord"; break; + case FCmpInst::FCMP_UNO: pred = "uno"; break; + case FCmpInst::FCMP_UEQ: pred = "ueq"; break; + case FCmpInst::FCMP_UGT: pred = "ugt"; break; + case FCmpInst::FCMP_UGE: pred = "uge"; break; + case FCmpInst::FCMP_ULT: pred = "ult"; break; + case FCmpInst::FCMP_ULE: pred = "ule"; break; + case FCmpInst::FCMP_UNE: pred = "une"; break; + case FCmpInst::FCMP_TRUE: pred = "true"; break; + case ICmpInst::ICMP_EQ: pred = "eq"; break; + case ICmpInst::ICMP_NE: pred = "ne"; break; + case ICmpInst::ICMP_SGT: pred = "sgt"; break; + case ICmpInst::ICMP_SGE: pred = "sge"; break; + case ICmpInst::ICMP_SLT: pred = "slt"; break; + case ICmpInst::ICMP_SLE: pred = "sle"; break; + case ICmpInst::ICMP_UGT: pred = "ugt"; break; + case ICmpInst::ICMP_UGE: pred = "uge"; break; + case ICmpInst::ICMP_ULT: pred = "ult"; break; + case ICmpInst::ICMP_ULE: pred = "ule"; break; + } + return pred; +} + +static void WriteMDNodeComment(const MDNode *Node, + formatted_raw_ostream &Out) { + if (Node->getNumElements() < 1) + return; + ConstantInt *CI = dyn_cast_or_null(Node->getElement(0)); + if (!CI) return; + unsigned Val = CI->getZExtValue(); + unsigned Tag = Val & ~LLVMDebugVersionMask; + if (Val >= LLVMDebugVersion) { + if (Tag == dwarf::DW_TAG_auto_variable) + Out << "; [ DW_TAG_auto_variable ]"; + else if (Tag == dwarf::DW_TAG_arg_variable) + Out << "; [ DW_TAG_arg_variable ]"; + else if (Tag == dwarf::DW_TAG_return_variable) + Out << "; [ DW_TAG_return_variable ]"; + else if (Tag == dwarf::DW_TAG_vector_type) + Out << "; [ DW_TAG_vector_type ]"; + else if (Tag == dwarf::DW_TAG_user_base) + Out << "; [ DW_TAG_user_base ]"; + else + Out << "; [" << dwarf::TagString(Tag) << " ]"; + } +} + +static void WriteMDNodes(formatted_raw_ostream &Out, TypePrinting &TypePrinter, + SlotTracker &Machine) { + SmallVector Nodes; + Nodes.resize(Machine.mdnSize()); + for (SlotTracker::ValueMap::iterator I = + Machine.mdnBegin(), E = Machine.mdnEnd(); I != E; ++I) + Nodes[I->second] = cast(I->first); + + for (unsigned i = 0, e = Nodes.size(); i != e; ++i) { + Out << '!' << i << " = metadata "; + const MDNode *Node = Nodes[i]; + Out << "!{"; + for (unsigned mi = 0, me = Node->getNumElements(); mi != me; ++mi) { + const Value *V = Node->getElement(mi); + if (!V) + Out << "null"; + else if (const MDNode *N = dyn_cast(V)) { + Out << "metadata "; + Out << '!' << Machine.getMetadataSlot(N); + } + else { + TypePrinter.print(V->getType(), Out); + Out << ' '; + WriteAsOperandInternal(Out, Node->getElement(mi), + &TypePrinter, &Machine); + } + if (mi + 1 != me) + Out << ", "; + } + + Out << "}"; + WriteMDNodeComment(Node, Out); + Out << "\n"; + } +} + +static void WriteOptimizationInfo(raw_ostream &Out, const User *U) { + if (const OverflowingBinaryOperator *OBO = + dyn_cast(U)) { + if (OBO->hasNoUnsignedWrap()) + Out << " nuw"; + if (OBO->hasNoSignedWrap()) + Out << " nsw"; + } else if (const SDivOperator *Div = dyn_cast(U)) { + if (Div->isExact()) + Out << " exact"; + } else if (const GEPOperator *GEP = dyn_cast(U)) { + if (GEP->isInBounds()) + Out << " inbounds"; + } +} + +static void WriteConstantInt(raw_ostream &Out, const Constant *CV, + TypePrinting &TypePrinter, SlotTracker *Machine) { + if (const ConstantInt *CI = dyn_cast(CV)) { + if (CI->getType() == Type::getInt1Ty(CV->getContext())) { + Out << (CI->getZExtValue() ? "true" : "false"); + return; + } + Out << CI->getValue(); + return; + } + + if (const ConstantFP *CFP = dyn_cast(CV)) { + if (&CFP->getValueAPF().getSemantics() == &APFloat::IEEEdouble || + &CFP->getValueAPF().getSemantics() == &APFloat::IEEEsingle) { + // We would like to output the FP constant value in exponential notation, + // but we cannot do this if doing so will lose precision. Check here to + // make sure that we only output it in exponential format if we can parse + // the value back and get the same value. + // + bool ignored; + bool isDouble = &CFP->getValueAPF().getSemantics()==&APFloat::IEEEdouble; + double Val = isDouble ? CFP->getValueAPF().convertToDouble() : + CFP->getValueAPF().convertToFloat(); + std::string StrVal = ftostr(CFP->getValueAPF()); + + // Check to make sure that the stringized number is not some string like + // "Inf" or NaN, that atof will accept, but the lexer will not. Check + // that the string matches the "[-+]?[0-9]" regex. + // + if ((StrVal[0] >= '0' && StrVal[0] <= '9') || + ((StrVal[0] == '-' || StrVal[0] == '+') && + (StrVal[1] >= '0' && StrVal[1] <= '9'))) { + // Reparse stringized version! + if (atof(StrVal.c_str()) == Val) { + Out << StrVal; + return; + } + } + // Otherwise we could not reparse it to exactly the same value, so we must + // output the string in hexadecimal format! Note that loading and storing + // floating point types changes the bits of NaNs on some hosts, notably + // x86, so we must not use these types. + assert(sizeof(double) == sizeof(uint64_t) && + "assuming that double is 64 bits!"); + char Buffer[40]; + APFloat apf = CFP->getValueAPF(); + // Floats are represented in ASCII IR as double, convert. + if (!isDouble) + apf.convert(APFloat::IEEEdouble, APFloat::rmNearestTiesToEven, + &ignored); + Out << "0x" << + utohex_buffer(uint64_t(apf.bitcastToAPInt().getZExtValue()), + Buffer+40); + return; + } + + // Some form of long double. These appear as a magic letter identifying + // the type, then a fixed number of hex digits. + Out << "0x"; + if (&CFP->getValueAPF().getSemantics() == &APFloat::x87DoubleExtended) { + Out << 'K'; + // api needed to prevent premature destruction + APInt api = CFP->getValueAPF().bitcastToAPInt(); + const uint64_t* p = api.getRawData(); + uint64_t word = p[1]; + int shiftcount=12; + int width = api.getBitWidth(); + for (int j=0; j>shiftcount) & 15; + if (nibble < 10) + Out << (unsigned char)(nibble + '0'); + else + Out << (unsigned char)(nibble - 10 + 'A'); + if (shiftcount == 0 && j+4 < width) { + word = *p; + shiftcount = 64; + if (width-j-4 < 64) + shiftcount = width-j-4; + } + } + return; + } else if (&CFP->getValueAPF().getSemantics() == &APFloat::IEEEquad) + Out << 'L'; + else if (&CFP->getValueAPF().getSemantics() == &APFloat::PPCDoubleDouble) + Out << 'M'; + else + llvm_unreachable("Unsupported floating point type"); + // api needed to prevent premature destruction + APInt api = CFP->getValueAPF().bitcastToAPInt(); + const uint64_t* p = api.getRawData(); + uint64_t word = *p; + int shiftcount=60; + int width = api.getBitWidth(); + for (int j=0; j>shiftcount) & 15; + if (nibble < 10) + Out << (unsigned char)(nibble + '0'); + else + Out << (unsigned char)(nibble - 10 + 'A'); + if (shiftcount == 0 && j+4 < width) { + word = *(++p); + shiftcount = 64; + if (width-j-4 < 64) + shiftcount = width-j-4; + } + } + return; + } + + if (isa(CV)) { + Out << "zeroinitializer"; + return; + } + + if (const BlockAddress *BA = dyn_cast(CV)) { + Out << "blockaddress("; + WriteAsOperandInternal(Out, BA->getFunction(), &TypePrinter, Machine); + Out << ", "; + WriteAsOperandInternal(Out, BA->getBasicBlock(), &TypePrinter, Machine); + Out << ")"; + return; + } + + if (const ConstantArray *CA = dyn_cast(CV)) { + // As a special case, print the array as a string if it is an array of + // i8 with ConstantInt values. + // + const Type *ETy = CA->getType()->getElementType(); + if (CA->isString()) { + Out << "c\""; + PrintEscapedString(CA->getAsString(), Out); + Out << '"'; + } else { // Cannot output in string format... + Out << '['; + if (CA->getNumOperands()) { + TypePrinter.print(ETy, Out); + Out << ' '; + WriteAsOperandInternal(Out, CA->getOperand(0), + &TypePrinter, Machine); + for (unsigned i = 1, e = CA->getNumOperands(); i != e; ++i) { + Out << ", "; + TypePrinter.print(ETy, Out); + Out << ' '; + WriteAsOperandInternal(Out, CA->getOperand(i), &TypePrinter, Machine); + } + } + Out << ']'; + } + return; + } + + if (const ConstantStruct *CS = dyn_cast(CV)) { + if (CS->getType()->isPacked()) + Out << '<'; + Out << '{'; + unsigned N = CS->getNumOperands(); + if (N) { + Out << ' '; + TypePrinter.print(CS->getOperand(0)->getType(), Out); + Out << ' '; + + WriteAsOperandInternal(Out, CS->getOperand(0), &TypePrinter, Machine); + + for (unsigned i = 1; i < N; i++) { + Out << ", "; + TypePrinter.print(CS->getOperand(i)->getType(), Out); + Out << ' '; + + WriteAsOperandInternal(Out, CS->getOperand(i), &TypePrinter, Machine); + } + Out << ' '; + } + + Out << '}'; + if (CS->getType()->isPacked()) + Out << '>'; + return; + } + + if (const ConstantVector *CP = dyn_cast(CV)) { + const Type *ETy = CP->getType()->getElementType(); + assert(CP->getNumOperands() > 0 && + "Number of operands for a PackedConst must be > 0"); + Out << '<'; + TypePrinter.print(ETy, Out); + Out << ' '; + WriteAsOperandInternal(Out, CP->getOperand(0), &TypePrinter, Machine); + for (unsigned i = 1, e = CP->getNumOperands(); i != e; ++i) { + Out << ", "; + TypePrinter.print(ETy, Out); + Out << ' '; + WriteAsOperandInternal(Out, CP->getOperand(i), &TypePrinter, Machine); + } + Out << '>'; + return; + } + + if (isa(CV)) { + Out << "null"; + return; + } + + if (isa(CV)) { + Out << "undef"; + return; + } + + if (const MDNode *Node = dyn_cast(CV)) { + Out << "!" << Machine->getMetadataSlot(Node); + return; + } + + if (const ConstantExpr *CE = dyn_cast(CV)) { + Out << CE->getOpcodeName(); + WriteOptimizationInfo(Out, CE); + if (CE->isCompare()) + Out << ' ' << getPredicateText(CE->getPredicate()); + Out << " ("; + + for (User::const_op_iterator OI=CE->op_begin(); OI != CE->op_end(); ++OI) { + TypePrinter.print((*OI)->getType(), Out); + Out << ' '; + WriteAsOperandInternal(Out, *OI, &TypePrinter, Machine); + if (OI+1 != CE->op_end()) + Out << ", "; + } + + if (CE->hasIndices()) { + const SmallVector &Indices = CE->getIndices(); + for (unsigned i = 0, e = Indices.size(); i != e; ++i) + Out << ", " << Indices[i]; + } + + if (CE->isCast()) { + Out << " to "; + TypePrinter.print(CE->getType(), Out); + } + + Out << ')'; + return; + } + + Out << ""; +} + + +/// WriteAsOperand - Write the name of the specified value out to the specified +/// ostream. This can be useful when you just want to print int %reg126, not +/// the whole instruction that generated it. +/// +static void WriteAsOperandInternal(raw_ostream &Out, const Value *V, + TypePrinting *TypePrinter, + SlotTracker *Machine) { + if (V->hasName()) { + PrintLLVMName(Out, V); + return; + } + + const Constant *CV = dyn_cast(V); + if (CV && !isa(CV)) { + assert(TypePrinter && "Constants require TypePrinting!"); + WriteConstantInt(Out, CV, *TypePrinter, Machine); + return; + } + + if (const InlineAsm *IA = dyn_cast(V)) { + Out << "asm "; + if (IA->hasSideEffects()) + Out << "sideeffect "; + if (IA->isAlignStack()) + Out << "alignstack "; + Out << '"'; + PrintEscapedString(IA->getAsmString(), Out); + Out << "\", \""; + PrintEscapedString(IA->getConstraintString(), Out); + Out << '"'; + return; + } + + if (const MDNode *N = dyn_cast(V)) { + Out << '!' << Machine->getMetadataSlot(N); + return; + } + + if (const MDString *MDS = dyn_cast(V)) { + Out << "!\""; + PrintEscapedString(MDS->getString(), Out); + Out << '"'; + return; + } + + if (V->getValueID() == Value::PseudoSourceValueVal || + V->getValueID() == Value::FixedStackPseudoSourceValueVal) { + V->print(Out); + return; + } + + char Prefix = '%'; + int Slot; + if (Machine) { + if (const GlobalValue *GV = dyn_cast(V)) { + Slot = Machine->getGlobalSlot(GV); + Prefix = '@'; + } else { + Slot = Machine->getLocalSlot(V); + } + } else { + Machine = createSlotTracker(V); + if (Machine) { + if (const GlobalValue *GV = dyn_cast(V)) { + Slot = Machine->getGlobalSlot(GV); + Prefix = '@'; + } else { + Slot = Machine->getLocalSlot(V); + } + delete Machine; + } else { + Slot = -1; + } + } + + if (Slot != -1) + Out << Prefix << Slot; + else + Out << ""; +} + +void llvm::WriteAsOperand(raw_ostream &Out, const Value *V, + bool PrintType, const Module *Context) { + + // Fast path: Don't construct and populate a TypePrinting object if we + // won't be needing any types printed. + if (!PrintType && + (!isa(V) || V->hasName() || isa(V))) { + WriteAsOperandInternal(Out, V, 0, 0); + return; + } + + if (Context == 0) Context = getModuleFromVal(V); + + TypePrinting TypePrinter; + std::vector NumberedTypes; + AddModuleTypesToPrinter(TypePrinter, NumberedTypes, Context); + if (PrintType) { + TypePrinter.print(V->getType(), Out); + Out << ' '; + } + + WriteAsOperandInternal(Out, V, &TypePrinter, 0); +} + +namespace { + +class AssemblyWriter { + formatted_raw_ostream &Out; + SlotTracker &Machine; + const Module *TheModule; + TypePrinting TypePrinter; + AssemblyAnnotationWriter *AnnotationWriter; + std::vector NumberedTypes; + DenseMap MDNames; + +public: + inline AssemblyWriter(formatted_raw_ostream &o, SlotTracker &Mac, + const Module *M, + AssemblyAnnotationWriter *AAW) + : Out(o), Machine(Mac), TheModule(M), AnnotationWriter(AAW) { + AddModuleTypesToPrinter(TypePrinter, NumberedTypes, M); + // FIXME: Provide MDPrinter + if (M) { + MetadataContext &TheMetadata = M->getContext().getMetadata(); + SmallVector, 4> Names; + TheMetadata.getHandlerNames(Names); + for (SmallVector, 4>::iterator + I = Names.begin(), + E = Names.end(); I != E; ++I) { + MDNames[I->first] = I->second; + } + } + } + + void write(const Module *M) { printModule(M); } + + void write(const GlobalValue *G) { + if (const GlobalVariable *GV = dyn_cast(G)) + printGlobal(GV); + else if (const GlobalAlias *GA = dyn_cast(G)) + printAlias(GA); + else if (const Function *F = dyn_cast(G)) + printFunction(F); + else + llvm_unreachable("Unknown global"); + } + + void write(const BasicBlock *BB) { printBasicBlock(BB); } + void write(const Instruction *I) { printInstruction(*I); } + + void writeOperand(const Value *Op, bool PrintType); + void writeParamOperand(const Value *Operand, Attributes Attrs); + +private: + void printModule(const Module *M); + void printTypeSymbolTable(const TypeSymbolTable &ST); + void printGlobal(const GlobalVariable *GV); + void printAlias(const GlobalAlias *GV); + void printFunction(const Function *F); + void printArgument(const Argument *FA, Attributes Attrs); + void printBasicBlock(const BasicBlock *BB); + void printInstruction(const Instruction &I); + + // printInfoComment - Print a little comment after the instruction indicating + // which slot it occupies. + void printInfoComment(const Value &V); +}; +} // end of anonymous namespace + + +void AssemblyWriter::writeOperand(const Value *Operand, bool PrintType) { + if (Operand == 0) { + Out << ""; + } else { + if (PrintType) { + TypePrinter.print(Operand->getType(), Out); + Out << ' '; + } + WriteAsOperandInternal(Out, Operand, &TypePrinter, &Machine); + } +} + +void AssemblyWriter::writeParamOperand(const Value *Operand, + Attributes Attrs) { + if (Operand == 0) { + Out << ""; + } else { + // Print the type + TypePrinter.print(Operand->getType(), Out); + // Print parameter attributes list + if (Attrs != Attribute::None) + Out << ' ' << Attribute::getAsString(Attrs); + Out << ' '; + // Print the operand + WriteAsOperandInternal(Out, Operand, &TypePrinter, &Machine); + } +} + +void AssemblyWriter::printModule(const Module *M) { + if (!M->getModuleIdentifier().empty() && + // Don't print the ID if it will start a new line (which would + // require a comment char before it). + M->getModuleIdentifier().find('\n') == std::string::npos) + Out << "; ModuleID = '" << M->getModuleIdentifier() << "'\n"; + + if (!M->getDataLayout().empty()) + Out << "target datalayout = \"" << M->getDataLayout() << "\"\n"; + if (!M->getTargetTriple().empty()) + Out << "target triple = \"" << M->getTargetTriple() << "\"\n"; + + if (!M->getModuleInlineAsm().empty()) { + // Split the string into lines, to make it easier to read the .ll file. + std::string Asm = M->getModuleInlineAsm(); + size_t CurPos = 0; + size_t NewLine = Asm.find_first_of('\n', CurPos); + Out << '\n'; + while (NewLine != std::string::npos) { + // We found a newline, print the portion of the asm string from the + // last newline up to this newline. + Out << "module asm \""; + PrintEscapedString(std::string(Asm.begin()+CurPos, Asm.begin()+NewLine), + Out); + Out << "\"\n"; + CurPos = NewLine+1; + NewLine = Asm.find_first_of('\n', CurPos); + } + Out << "module asm \""; + PrintEscapedString(std::string(Asm.begin()+CurPos, Asm.end()), Out); + Out << "\"\n"; + } + + // Loop over the dependent libraries and emit them. + Module::lib_iterator LI = M->lib_begin(); + Module::lib_iterator LE = M->lib_end(); + if (LI != LE) { + Out << '\n'; + Out << "deplibs = [ "; + while (LI != LE) { + Out << '"' << *LI << '"'; + ++LI; + if (LI != LE) + Out << ", "; + } + Out << " ]"; + } + + // Loop over the symbol table, emitting all id'd types. + if (!M->getTypeSymbolTable().empty() || !NumberedTypes.empty()) Out << '\n'; + printTypeSymbolTable(M->getTypeSymbolTable()); + + // Output all globals. + if (!M->global_empty()) Out << '\n'; + for (Module::const_global_iterator I = M->global_begin(), E = M->global_end(); + I != E; ++I) + printGlobal(I); + + // Output all aliases. + if (!M->alias_empty()) Out << "\n"; + for (Module::const_alias_iterator I = M->alias_begin(), E = M->alias_end(); + I != E; ++I) + printAlias(I); + + // Output all of the functions. + for (Module::const_iterator I = M->begin(), E = M->end(); I != E; ++I) + printFunction(I); + + // Output named metadata. + if (!M->named_metadata_empty()) Out << '\n'; + for (Module::const_named_metadata_iterator I = M->named_metadata_begin(), + E = M->named_metadata_end(); I != E; ++I) { + const NamedMDNode *NMD = I; + Out << "!" << NMD->getName() << " = !{"; + for (unsigned i = 0, e = NMD->getNumElements(); i != e; ++i) { + if (i) Out << ", "; + MDNode *MD = dyn_cast_or_null(NMD->getElement(i)); + Out << '!' << Machine.getMetadataSlot(MD); + } + Out << "}\n"; + } + + // Output metadata. + if (!Machine.mdnEmpty()) Out << '\n'; + WriteMDNodes(Out, TypePrinter, Machine); +} + +static void PrintLinkage(GlobalValue::LinkageTypes LT, + formatted_raw_ostream &Out) { + switch (LT) { + case GlobalValue::ExternalLinkage: break; + case GlobalValue::PrivateLinkage: Out << "private "; break; + case GlobalValue::LinkerPrivateLinkage: Out << "linker_private "; break; + case GlobalValue::InternalLinkage: Out << "internal "; break; + case GlobalValue::LinkOnceAnyLinkage: Out << "linkonce "; break; + case GlobalValue::LinkOnceODRLinkage: Out << "linkonce_odr "; break; + case GlobalValue::WeakAnyLinkage: Out << "weak "; break; + case GlobalValue::WeakODRLinkage: Out << "weak_odr "; break; + case GlobalValue::CommonLinkage: Out << "common "; break; + case GlobalValue::AppendingLinkage: Out << "appending "; break; + case GlobalValue::DLLImportLinkage: Out << "dllimport "; break; + case GlobalValue::DLLExportLinkage: Out << "dllexport "; break; + case GlobalValue::ExternalWeakLinkage: Out << "extern_weak "; break; + case GlobalValue::AvailableExternallyLinkage: + Out << "available_externally "; + break; + // This is invalid syntax and just a debugging aid. + case GlobalValue::GhostLinkage: Out << "ghost "; break; + } +} + + +static void PrintVisibility(GlobalValue::VisibilityTypes Vis, + formatted_raw_ostream &Out) { + switch (Vis) { + default: llvm_unreachable("Invalid visibility style!"); + case GlobalValue::DefaultVisibility: break; + case GlobalValue::HiddenVisibility: Out << "hidden "; break; + case GlobalValue::ProtectedVisibility: Out << "protected "; break; + } +} + +void AssemblyWriter::printGlobal(const GlobalVariable *GV) { + WriteAsOperandInternal(Out, GV, &TypePrinter, &Machine); + Out << " = "; + + if (!GV->hasInitializer() && GV->hasExternalLinkage()) + Out << "external "; + + PrintLinkage(GV->getLinkage(), Out); + PrintVisibility(GV->getVisibility(), Out); + + if (GV->isThreadLocal()) Out << "thread_local "; + if (unsigned AddressSpace = GV->getType()->getAddressSpace()) + Out << "addrspace(" << AddressSpace << ") "; + Out << (GV->isConstant() ? "constant " : "global "); + TypePrinter.print(GV->getType()->getElementType(), Out); + + if (GV->hasInitializer()) { + Out << ' '; + writeOperand(GV->getInitializer(), false); + } + + if (GV->hasSection()) + Out << ", section \"" << GV->getSection() << '"'; + if (GV->getAlignment()) + Out << ", align " << GV->getAlignment(); + + printInfoComment(*GV); + Out << '\n'; +} + +void AssemblyWriter::printAlias(const GlobalAlias *GA) { + // Don't crash when dumping partially built GA + if (!GA->hasName()) + Out << "<> = "; + else { + PrintLLVMName(Out, GA); + Out << " = "; + } + PrintVisibility(GA->getVisibility(), Out); + + Out << "alias "; + + PrintLinkage(GA->getLinkage(), Out); + + const Constant *Aliasee = GA->getAliasee(); + + if (const GlobalVariable *GV = dyn_cast(Aliasee)) { + TypePrinter.print(GV->getType(), Out); + Out << ' '; + PrintLLVMName(Out, GV); + } else if (const Function *F = dyn_cast(Aliasee)) { + TypePrinter.print(F->getFunctionType(), Out); + Out << "* "; + + WriteAsOperandInternal(Out, F, &TypePrinter, &Machine); + } else if (const GlobalAlias *GA = dyn_cast(Aliasee)) { + TypePrinter.print(GA->getType(), Out); + Out << ' '; + PrintLLVMName(Out, GA); + } else { + const ConstantExpr *CE = cast(Aliasee); + // The only valid GEP is an all zero GEP. + assert((CE->getOpcode() == Instruction::BitCast || + CE->getOpcode() == Instruction::GetElementPtr) && + "Unsupported aliasee"); + writeOperand(CE, false); + } + + printInfoComment(*GA); + Out << '\n'; +} + +void AssemblyWriter::printTypeSymbolTable(const TypeSymbolTable &ST) { + // Emit all numbered types. + for (unsigned i = 0, e = NumberedTypes.size(); i != e; ++i) { + Out << '%' << i << " = type "; + + // Make sure we print out at least one level of the type structure, so + // that we do not get %2 = type %2 + TypePrinter.printAtLeastOneLevel(NumberedTypes[i], Out); + Out << '\n'; + } + + // Print the named types. + for (TypeSymbolTable::const_iterator TI = ST.begin(), TE = ST.end(); + TI != TE; ++TI) { + PrintLLVMName(Out, TI->first, LocalPrefix); + Out << " = type "; + + // Make sure we print out at least one level of the type structure, so + // that we do not get %FILE = type %FILE + TypePrinter.printAtLeastOneLevel(TI->second, Out); + Out << '\n'; + } +} + +/// printFunction - Print all aspects of a function. +/// +void AssemblyWriter::printFunction(const Function *F) { + // Print out the return type and name. + Out << '\n'; + + if (AnnotationWriter) AnnotationWriter->emitFunctionAnnot(F, Out); + + if (F->isDeclaration()) + Out << "declare "; + else + Out << "define "; + + PrintLinkage(F->getLinkage(), Out); + PrintVisibility(F->getVisibility(), Out); + + // Print the calling convention. + switch (F->getCallingConv()) { + case CallingConv::C: break; // default + case CallingConv::Fast: Out << "fastcc "; break; + case CallingConv::Cold: Out << "coldcc "; break; + case CallingConv::X86_StdCall: Out << "x86_stdcallcc "; break; + case CallingConv::X86_FastCall: Out << "x86_fastcallcc "; break; + case CallingConv::ARM_APCS: Out << "arm_apcscc "; break; + case CallingConv::ARM_AAPCS: Out << "arm_aapcscc "; break; + case CallingConv::ARM_AAPCS_VFP:Out << "arm_aapcs_vfpcc "; break; + default: Out << "cc" << F->getCallingConv() << " "; break; + } + + const FunctionType *FT = F->getFunctionType(); + const AttrListPtr &Attrs = F->getAttributes(); + Attributes RetAttrs = Attrs.getRetAttributes(); + if (RetAttrs != Attribute::None) + Out << Attribute::getAsString(Attrs.getRetAttributes()) << ' '; + TypePrinter.print(F->getReturnType(), Out); + Out << ' '; + WriteAsOperandInternal(Out, F, &TypePrinter, &Machine); + Out << '('; + Machine.incorporateFunction(F); + + // Loop over the arguments, printing them... + + unsigned Idx = 1; + if (!F->isDeclaration()) { + // If this isn't a declaration, print the argument names as well. + for (Function::const_arg_iterator I = F->arg_begin(), E = F->arg_end(); + I != E; ++I) { + // Insert commas as we go... the first arg doesn't get a comma + if (I != F->arg_begin()) Out << ", "; + printArgument(I, Attrs.getParamAttributes(Idx)); + Idx++; + } + } else { + // Otherwise, print the types from the function type. + for (unsigned i = 0, e = FT->getNumParams(); i != e; ++i) { + // Insert commas as we go... the first arg doesn't get a comma + if (i) Out << ", "; + + // Output type... + TypePrinter.print(FT->getParamType(i), Out); + + Attributes ArgAttrs = Attrs.getParamAttributes(i+1); + if (ArgAttrs != Attribute::None) + Out << ' ' << Attribute::getAsString(ArgAttrs); + } + } + + // Finish printing arguments... + if (FT->isVarArg()) { + if (FT->getNumParams()) Out << ", "; + Out << "..."; // Output varargs portion of signature! + } + Out << ')'; + Attributes FnAttrs = Attrs.getFnAttributes(); + if (FnAttrs != Attribute::None) + Out << ' ' << Attribute::getAsString(Attrs.getFnAttributes()); + if (F->hasSection()) + Out << " section \"" << F->getSection() << '"'; + if (F->getAlignment()) + Out << " align " << F->getAlignment(); + if (F->hasGC()) + Out << " gc \"" << F->getGC() << '"'; + if (F->isDeclaration()) { + Out << "\n"; + } else { + Out << " {"; + + // Output all of its basic blocks... for the function + for (Function::const_iterator I = F->begin(), E = F->end(); I != E; ++I) + printBasicBlock(I); + + Out << "}\n"; + } + + Machine.purgeFunction(); +} + +/// printArgument - This member is called for every argument that is passed into +/// the function. Simply print it out +/// +void AssemblyWriter::printArgument(const Argument *Arg, + Attributes Attrs) { + // Output type... + TypePrinter.print(Arg->getType(), Out); + + // Output parameter attributes list + if (Attrs != Attribute::None) + Out << ' ' << Attribute::getAsString(Attrs); + + // Output name, if available... + if (Arg->hasName()) { + Out << ' '; + PrintLLVMName(Out, Arg); + } +} + +/// printBasicBlock - This member is called for each basic block in a method. +/// +void AssemblyWriter::printBasicBlock(const BasicBlock *BB) { + if (BB->hasName()) { // Print out the label if it exists... + Out << "\n"; + PrintLLVMName(Out, BB->getName(), LabelPrefix); + Out << ':'; + } else if (!BB->use_empty()) { // Don't print block # of no uses... + Out << "\n;

    } + +define void @getAndMoveToFrontDecode() { + br label %endif.2 + +endif.2: ; preds = %loopexit.5, %0 + br i1 false, label %loopentry.5, label %UnifiedExitNode + +loopentry.5: ; preds = %loopexit.6, %endif.2 + br i1 false, label %loopentry.6, label %UnifiedExitNode + +loopentry.6: ; preds = %loopentry.7, %loopentry.5 + br i1 false, label %loopentry.7, label %loopexit.6 + +loopentry.7: ; preds = %loopentry.7, %loopentry.6 + br i1 false, label %loopentry.7, label %loopentry.6 + +loopexit.6: ; preds = %loopentry.6 + br i1 false, label %loopentry.5, label %loopexit.5 + +loopexit.5: ; preds = %loopexit.6 + br i1 false, label %endif.2, label %UnifiedExitNode + +UnifiedExitNode: ; preds = %loopexit.5, %loopentry.5, %endif.2 + ret void +} diff --git a/libclamav/c++/llvm/test/Analysis/LoopInfo/dg.exp b/libclamav/c++/llvm/test/Analysis/LoopInfo/dg.exp new file mode 100644 index 000000000..f2005891a --- /dev/null +++ b/libclamav/c++/llvm/test/Analysis/LoopInfo/dg.exp @@ -0,0 +1,3 @@ +load_lib llvm.exp + +RunLLVMTests [lsort [glob -nocomplain $srcdir/$subdir/*.{ll,c,cpp}]] diff --git a/libclamav/c++/llvm/test/Analysis/PointerTracking/dg.exp b/libclamav/c++/llvm/test/Analysis/PointerTracking/dg.exp new file mode 100644 index 000000000..f2005891a --- /dev/null +++ b/libclamav/c++/llvm/test/Analysis/PointerTracking/dg.exp @@ -0,0 +1,3 @@ +load_lib llvm.exp + +RunLLVMTests [lsort [glob -nocomplain $srcdir/$subdir/*.{ll,c,cpp}]] diff --git a/libclamav/c++/llvm/test/Analysis/PointerTracking/sizes.ll b/libclamav/c++/llvm/test/Analysis/PointerTracking/sizes.ll new file mode 100644 index 000000000..c8ca648e8 --- /dev/null +++ b/libclamav/c++/llvm/test/Analysis/PointerTracking/sizes.ll @@ -0,0 +1,86 @@ +; RUN: opt < %s -pointertracking -analyze | FileCheck %s +target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128" +target triple = "x86_64-unknown-linux-gnu" +@.str = internal constant [5 x i8] c"1234\00" ; <[5 x i8]*> [#uses=1] +@test1p = global i8* getelementptr ([5 x i8]* @.str, i32 0, i32 0), align 8 ; [#uses=1] +@test1a = global [5 x i8] c"1234\00", align 1 ; <[5 x i8]*> [#uses=1] +@test2a = global [5 x i32] [i32 1, i32 2, i32 3, i32 4, i32 5], align 4 ; <[5 x i32]*> [#uses=2] +@test2p = global i32* getelementptr ([5 x i32]* @test2a, i32 0, i32 0), align 8 ; [#uses=1] +@test0p = common global i32* null, align 8 ; [#uses=1] +@test0i = common global i32 0, align 4 ; [#uses=1] + +define i32 @foo0() nounwind { +entry: + %tmp = load i32** @test0p ; [#uses=1] + %conv = bitcast i32* %tmp to i8* ; [#uses=1] + %call = tail call i32 @bar(i8* %conv) nounwind ; [#uses=1] + %tmp1 = load i8** @test1p ; [#uses=1] + %call2 = tail call i32 @bar(i8* %tmp1) nounwind ; [#uses=1] + %call3 = tail call i32 @bar(i8* getelementptr ([5 x i8]* @test1a, i32 0, i32 0)) nounwind ; [#uses=1] + %call5 = tail call i32 @bar(i8* bitcast ([5 x i32]* @test2a to i8*)) nounwind ; [#uses=1] + %tmp7 = load i32** @test2p ; [#uses=1] + %conv8 = bitcast i32* %tmp7 to i8* ; [#uses=1] + %call9 = tail call i32 @bar(i8* %conv8) nounwind ; [#uses=1] + %call11 = tail call i32 @bar(i8* bitcast (i32* @test0i to i8*)) nounwind ; [#uses=1] + %add = add i32 %call2, %call ; [#uses=1] + %add4 = add i32 %add, %call3 ; [#uses=1] + %add6 = add i32 %add4, %call5 ; [#uses=1] + %add10 = add i32 %add6, %call9 ; [#uses=1] + %add12 = add i32 %add10, %call11 ; [#uses=1] + ret i32 %add12 +} + +declare i32 @bar(i8*) + +define i32 @foo1(i32 %n) nounwind { +entry: +; CHECK: 'foo1': + %test4a = alloca [10 x i8], align 1 ; <[10 x i8]*> [#uses=1] +; CHECK: %test4a = +; CHECK: ==> 1 elements, 10 bytes allocated + %test6a = alloca [10 x i32], align 4 ; <[10 x i32]*> [#uses=1] +; CHECK: %test6a = +; CHECK: ==> 1 elements, 40 bytes allocated + %vla = alloca i8, i32 %n, align 1 ; [#uses=1] +; CHECK: %vla = +; CHECK: ==> %n elements, %n bytes allocated + %0 = shl i32 %n, 2 ; [#uses=1] + %vla7 = alloca i8, i32 %0, align 1 ; [#uses=1] +; CHECK: %vla7 = +; CHECK: ==> (4 * %n) elements, (4 * %n) bytes allocated + %call = call i32 @bar(i8* %vla) nounwind ; [#uses=1] + %arraydecay = getelementptr [10 x i8]* %test4a, i64 0, i64 0 ; [#uses=1] + %call10 = call i32 @bar(i8* %arraydecay) nounwind ; [#uses=1] + %call11 = call i32 @bar(i8* %vla7) nounwind ; [#uses=1] + %ptrconv14 = bitcast [10 x i32]* %test6a to i8* ; [#uses=1] + %call15 = call i32 @bar(i8* %ptrconv14) nounwind ; [#uses=1] + %add = add i32 %call10, %call ; [#uses=1] + %add12 = add i32 %add, %call11 ; [#uses=1] + %add16 = add i32 %add12, %call15 ; [#uses=1] + ret i32 %add16 +} + +define i32 @foo2(i64 %n) nounwind { +entry: + %call = tail call i8* @malloc(i64 %n) ; [#uses=1] +; CHECK: %call = +; CHECK: ==> %n elements, %n bytes allocated + %call2 = tail call i8* @calloc(i64 2, i64 4) nounwind ; [#uses=1] +; CHECK: %call2 = +; CHECK: ==> 8 elements, 8 bytes allocated + %call4 = tail call i8* @realloc(i8* null, i64 16) nounwind ; [#uses=1] +; CHECK: %call4 = +; CHECK: ==> 16 elements, 16 bytes allocated + %call6 = tail call i32 @bar(i8* %call) nounwind ; [#uses=1] + %call8 = tail call i32 @bar(i8* %call2) nounwind ; [#uses=1] + %call10 = tail call i32 @bar(i8* %call4) nounwind ; [#uses=1] + %add = add i32 %call8, %call6 ; [#uses=1] + %add11 = add i32 %add, %call10 ; [#uses=1] + ret i32 %add11 +} + +declare noalias i8* @malloc(i64) nounwind + +declare noalias i8* @calloc(i64, i64) nounwind + +declare noalias i8* @realloc(i8* nocapture, i64) nounwind diff --git a/libclamav/c++/llvm/test/Analysis/PostDominators/2006-09-26-PostDominanceFrontier.ll b/libclamav/c++/llvm/test/Analysis/PostDominators/2006-09-26-PostDominanceFrontier.ll new file mode 100644 index 000000000..b73b7f03f --- /dev/null +++ b/libclamav/c++/llvm/test/Analysis/PostDominators/2006-09-26-PostDominanceFrontier.ll @@ -0,0 +1,97 @@ +; RUN: opt < %s -analyze -postdomfrontier \ +; RUN: -disable-verify +; ModuleID = '2006-09-26-PostDominanceFrontier.bc' +target datalayout = "e-p:64:64" +target triple = "alphaev67-unknown-linux-gnu" + %struct.FILE = type { i32, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, %struct._IO_marker*, %struct.FILE*, i32, i32, i64, i16, i8, [1 x i8], i8*, i64, i8*, i8*, i32, [44 x i8] } + %struct._IO_marker = type { %struct._IO_marker*, %struct.FILE*, i32 } +@TOP = external global i64* ; [#uses=1] +@BOT = external global i64* ; [#uses=1] +@str = external global [2 x i8] ; <[2 x i8]*> [#uses=0] + +declare void @fopen() + +define void @main(i8** %argv) { +entry: + %netSelect.i507 = alloca i64, align 8 ; [#uses=0] + %topStart.i = alloca i64, align 8 ; [#uses=0] + %topEnd.i = alloca i64, align 8 ; [#uses=0] + %botStart.i = alloca i64, align 8 ; [#uses=0] + %botEnd.i = alloca i64, align 8 ; [#uses=0] + %c1.i154 = alloca i32, align 4 ; [#uses=0] + %b1.i155 = alloca i32, align 4 ; [#uses=0] + %t1.i156 = alloca i32, align 4 ; [#uses=0] + %c1.i = alloca i32, align 4 ; [#uses=0] + %b1.i = alloca i32, align 4 ; [#uses=0] + %t1.i = alloca i32, align 4 ; [#uses=0] + %netSelect.i5 = alloca i64, align 8 ; [#uses=0] + %netSelect.i = alloca i64, align 8 ; [#uses=0] + %tmp2.i = getelementptr i8** %argv, i32 1 ; [#uses=1] + %tmp3.i4 = load i8** %tmp2.i ; [#uses=0] + call void @fopen( ) + br i1 false, label %DimensionChannel.exit, label %bb.backedge.i + +bb.backedge.i: ; preds = %entry + ret void + +DimensionChannel.exit: ; preds = %entry + %tmp13.i137 = malloc i64, i32 0 ; [#uses=1] + %tmp610.i = malloc i64, i32 0 ; [#uses=1] + br label %cond_true.i143 + +cond_true.i143: ; preds = %cond_true.i143, %DimensionChannel.exit + %tmp9.i140 = getelementptr i64* %tmp13.i137, i64 0 ; [#uses=0] + %tmp12.i = getelementptr i64* %tmp610.i, i64 0 ; [#uses=0] + br i1 false, label %bb18.i144, label %cond_true.i143 + +bb18.i144: ; preds = %cond_true.i143 + call void @fopen( ) + %tmp76.i105 = malloc i64, i32 0 ; [#uses=3] + %tmp674.i = malloc i64, i32 0 ; [#uses=2] + %tmp1072.i = malloc i64, i32 0 ; [#uses=2] + %tmp1470.i = malloc i64, i32 0 ; [#uses=1] + br label %cond_true.i114 + +cond_true.i114: ; preds = %cond_true.i114, %bb18.i144 + %tmp17.i108 = getelementptr i64* %tmp76.i105, i64 0 ; [#uses=0] + %tmp20.i = getelementptr i64* %tmp674.i, i64 0 ; [#uses=0] + %tmp23.i111 = getelementptr i64* %tmp1470.i, i64 0 ; [#uses=0] + br i1 false, label %cond_true40.i, label %cond_true.i114 + +cond_true40.i: ; preds = %cond_true40.i, %cond_true.i114 + %tmp33.i115 = getelementptr i64* %tmp1072.i, i64 0 ; [#uses=0] + br i1 false, label %bb142.i, label %cond_true40.i + +cond_next54.i: ; preds = %cond_true76.i + %tmp57.i = getelementptr i64* %tmp55.i, i64 0 ; [#uses=0] + br i1 false, label %bb64.i, label %bb69.i + +bb64.i: ; preds = %cond_true76.i, %cond_next54.i + %tmp67.i117 = getelementptr i64* %tmp76.i105, i64 0 ; [#uses=0] + br i1 false, label %bb114.i, label %cond_true111.i + +bb69.i: ; preds = %cond_next54.i + br i1 false, label %bb79.i, label %cond_true76.i + +cond_true76.i: ; preds = %bb142.i, %bb69.i + %tmp48.i = getelementptr i64* %tmp46.i, i64 0 ; [#uses=0] + br i1 false, label %bb64.i, label %cond_next54.i + +bb79.i: ; preds = %bb69.i + br i1 false, label %bb114.i, label %cond_true111.i + +cond_true111.i: ; preds = %bb79.i, %bb64.i + %tmp84.i127 = getelementptr i64* %tmp46.i, i64 0 ; [#uses=0] + ret void + +bb114.i: ; preds = %bb142.i, %bb79.i, %bb64.i + %tmp117.i = getelementptr i64* %tmp76.i105, i64 0 ; [#uses=0] + %tmp132.i131 = getelementptr i64* %tmp674.i, i64 0 ; [#uses=0] + %tmp122.i = getelementptr i64* %tmp1072.i, i64 0 ; [#uses=0] + ret void + +bb142.i: ; preds = %cond_true40.i + %tmp46.i = load i64** @BOT ; [#uses=2] + %tmp55.i = load i64** @TOP ; [#uses=1] + br i1 false, label %bb114.i, label %cond_true76.i +} diff --git a/libclamav/c++/llvm/test/Analysis/PostDominators/2007-04-17-PostDominanceFrontier.ll b/libclamav/c++/llvm/test/Analysis/PostDominators/2007-04-17-PostDominanceFrontier.ll new file mode 100644 index 000000000..1ec056bc3 --- /dev/null +++ b/libclamav/c++/llvm/test/Analysis/PostDominators/2007-04-17-PostDominanceFrontier.ll @@ -0,0 +1,692 @@ +; RUN: opt < %s -postdomfrontier -disable-output + +define void @SManager() { +entry: + br label %bb.outer + +bb.outer: ; preds = %bb193, %entry + br label %bb.outer156 + +bb.loopexit: ; preds = %bb442 + br label %bb.outer156 + +bb.outer156: ; preds = %bb.loopexit, %bb.outer + br label %bb + +bb: ; preds = %bb.backedge, %bb.outer156 + br i1 false, label %cond_true, label %bb.cond_next_crit_edge + +bb.cond_next_crit_edge: ; preds = %bb + br label %cond_next + +cond_true: ; preds = %bb + br label %cond_next + +cond_next: ; preds = %cond_true, %bb.cond_next_crit_edge + br i1 false, label %cond_next.bb.backedge_crit_edge, label %cond_next107 + +cond_next.bb.backedge_crit_edge: ; preds = %cond_next + br label %bb.backedge + +bb.backedge: ; preds = %cond_true112.bb.backedge_crit_edge, %cond_next.bb.backedge_crit_edge + br label %bb + +cond_next107: ; preds = %cond_next + br i1 false, label %cond_true112, label %cond_next197 + +cond_true112: ; preds = %cond_next107 + br i1 false, label %cond_true118, label %cond_true112.bb.backedge_crit_edge + +cond_true112.bb.backedge_crit_edge: ; preds = %cond_true112 + br label %bb.backedge + +cond_true118: ; preds = %cond_true112 + br i1 false, label %bb123.preheader, label %cond_true118.bb148_crit_edge + +cond_true118.bb148_crit_edge: ; preds = %cond_true118 + br label %bb148 + +bb123.preheader: ; preds = %cond_true118 + br label %bb123 + +bb123: ; preds = %bb142.bb123_crit_edge, %bb123.preheader + br i1 false, label %bb123.bb142_crit_edge, label %cond_next.i57 + +bb123.bb142_crit_edge: ; preds = %bb123 + br label %bb142 + +cond_next.i57: ; preds = %bb123 + br i1 false, label %cond_true135, label %cond_next.i57.bb142_crit_edge + +cond_next.i57.bb142_crit_edge: ; preds = %cond_next.i57 + br label %bb142 + +cond_true135: ; preds = %cond_next.i57 + br label %bb142 + +bb142: ; preds = %cond_true135, %cond_next.i57.bb142_crit_edge, %bb123.bb142_crit_edge + br i1 false, label %bb148.loopexit, label %bb142.bb123_crit_edge + +bb142.bb123_crit_edge: ; preds = %bb142 + br label %bb123 + +bb148.loopexit: ; preds = %bb142 + br label %bb148 + +bb148: ; preds = %bb148.loopexit, %cond_true118.bb148_crit_edge + br i1 false, label %bb151.preheader, label %bb148.bb177_crit_edge + +bb148.bb177_crit_edge: ; preds = %bb148 + br label %bb177 + +bb151.preheader: ; preds = %bb148 + br label %bb151 + +bb151: ; preds = %bb171.bb151_crit_edge, %bb151.preheader + br i1 false, label %bb151.bb171_crit_edge, label %cond_next.i49 + +bb151.bb171_crit_edge: ; preds = %bb151 + br label %bb171 + +cond_next.i49: ; preds = %bb151 + br i1 false, label %cond_true164, label %cond_next.i49.bb171_crit_edge + +cond_next.i49.bb171_crit_edge: ; preds = %cond_next.i49 + br label %bb171 + +cond_true164: ; preds = %cond_next.i49 + br label %bb171 + +bb171: ; preds = %cond_true164, %cond_next.i49.bb171_crit_edge, %bb151.bb171_crit_edge + br i1 false, label %bb177.loopexit, label %bb171.bb151_crit_edge + +bb171.bb151_crit_edge: ; preds = %bb171 + br label %bb151 + +bb177.loopexit: ; preds = %bb171 + br label %bb177 + +bb177: ; preds = %bb177.loopexit, %bb148.bb177_crit_edge + br i1 false, label %bb180.preheader, label %bb177.bb193_crit_edge + +bb177.bb193_crit_edge: ; preds = %bb177 + br label %bb193 + +bb180.preheader: ; preds = %bb177 + br label %bb180 + +bb180: ; preds = %bb180.bb180_crit_edge, %bb180.preheader + br i1 false, label %bb193.loopexit, label %bb180.bb180_crit_edge + +bb180.bb180_crit_edge: ; preds = %bb180 + br label %bb180 + +bb193.loopexit: ; preds = %bb180 + br label %bb193 + +bb193: ; preds = %bb193.loopexit, %bb177.bb193_crit_edge + br label %bb.outer + +cond_next197: ; preds = %cond_next107 + br i1 false, label %cond_next210, label %cond_true205 + +cond_true205: ; preds = %cond_next197 + br i1 false, label %cond_true205.bb213_crit_edge, label %cond_true205.bb299_crit_edge + +cond_true205.bb299_crit_edge: ; preds = %cond_true205 + br label %bb299 + +cond_true205.bb213_crit_edge: ; preds = %cond_true205 + br label %bb213 + +cond_next210: ; preds = %cond_next197 + br label %bb293 + +bb213: ; preds = %bb293.bb213_crit_edge, %cond_true205.bb213_crit_edge + br i1 false, label %bb213.cond_next290_crit_edge, label %cond_true248 + +bb213.cond_next290_crit_edge: ; preds = %bb213 + br label %cond_next290 + +cond_true248: ; preds = %bb213 + br i1 false, label %cond_true248.cond_next290_crit_edge, label %cond_true255 + +cond_true248.cond_next290_crit_edge: ; preds = %cond_true248 + br label %cond_next290 + +cond_true255: ; preds = %cond_true248 + br i1 false, label %cond_true266, label %cond_true255.cond_next271_crit_edge + +cond_true255.cond_next271_crit_edge: ; preds = %cond_true255 + br label %cond_next271 + +cond_true266: ; preds = %cond_true255 + br label %cond_next271 + +cond_next271: ; preds = %cond_true266, %cond_true255.cond_next271_crit_edge + br label %cond_next290 + +cond_next290: ; preds = %cond_next271, %cond_true248.cond_next290_crit_edge, %bb213.cond_next290_crit_edge + br label %bb293 + +bb293: ; preds = %cond_next290, %cond_next210 + br i1 false, label %bb293.bb213_crit_edge, label %bb293.bb299_crit_edge + +bb293.bb299_crit_edge: ; preds = %bb293 + br label %bb299 + +bb293.bb213_crit_edge: ; preds = %bb293 + br label %bb213 + +bb299: ; preds = %bb293.bb299_crit_edge, %cond_true205.bb299_crit_edge + br i1 false, label %bb302.preheader, label %bb299.bb390_crit_edge + +bb299.bb390_crit_edge: ; preds = %bb299 + br label %bb390 + +bb302.preheader: ; preds = %bb299 + br label %bb302 + +bb302: ; preds = %bb384.bb302_crit_edge, %bb302.preheader + br i1 false, label %bb302.bb384_crit_edge, label %cond_true339 + +bb302.bb384_crit_edge: ; preds = %bb302 + br label %bb384 + +cond_true339: ; preds = %bb302 + br i1 false, label %cond_true339.bb384_crit_edge, label %cond_true346 + +cond_true339.bb384_crit_edge: ; preds = %cond_true339 + br label %bb384 + +cond_true346: ; preds = %cond_true339 + br i1 false, label %cond_true357, label %cond_true346.cond_next361_crit_edge + +cond_true346.cond_next361_crit_edge: ; preds = %cond_true346 + br label %cond_next361 + +cond_true357: ; preds = %cond_true346 + br label %cond_next361 + +cond_next361: ; preds = %cond_true357, %cond_true346.cond_next361_crit_edge + br label %bb384 + +bb384: ; preds = %cond_next361, %cond_true339.bb384_crit_edge, %bb302.bb384_crit_edge + br i1 false, label %bb390.loopexit, label %bb384.bb302_crit_edge + +bb384.bb302_crit_edge: ; preds = %bb384 + br label %bb302 + +bb390.loopexit: ; preds = %bb384 + br label %bb390 + +bb390: ; preds = %bb390.loopexit, %bb299.bb390_crit_edge + br i1 false, label %bb391.preheader, label %bb390.bb442.preheader_crit_edge + +bb390.bb442.preheader_crit_edge: ; preds = %bb390 + br label %bb442.preheader + +bb391.preheader: ; preds = %bb390 + br label %bb391 + +bb391: ; preds = %bb413.bb391_crit_edge, %bb391.preheader + br i1 false, label %bb391.bb413_crit_edge, label %cond_next404 + +bb391.bb413_crit_edge: ; preds = %bb391 + br label %bb413 + +cond_next404: ; preds = %bb391 + br i1 false, label %cond_next404.HWrite.exit_crit_edge, label %cond_next.i13 + +cond_next404.HWrite.exit_crit_edge: ; preds = %cond_next404 + br label %HWrite.exit + +cond_next.i13: ; preds = %cond_next404 + br i1 false, label %cond_next.i13.cond_next13.i_crit_edge, label %cond_true12.i + +cond_next.i13.cond_next13.i_crit_edge: ; preds = %cond_next.i13 + br label %cond_next13.i + +cond_true12.i: ; preds = %cond_next.i13 + br label %cond_next13.i + +cond_next13.i: ; preds = %cond_true12.i, %cond_next.i13.cond_next13.i_crit_edge + br i1 false, label %cond_next13.i.bb.i22_crit_edge, label %cond_next43.i + +cond_next13.i.bb.i22_crit_edge: ; preds = %cond_next13.i + br label %bb.i22 + +cond_next43.i: ; preds = %cond_next13.i + br i1 false, label %cond_next43.i.bb.i22_crit_edge, label %bb60.i + +cond_next43.i.bb.i22_crit_edge: ; preds = %cond_next43.i + br label %bb.i22 + +bb.i22: ; preds = %cond_next43.i.bb.i22_crit_edge, %cond_next13.i.bb.i22_crit_edge + br label %bb413 + +bb60.i: ; preds = %cond_next43.i + br i1 false, label %bb60.i.HWrite.exit_crit_edge, label %cond_true81.i + +bb60.i.HWrite.exit_crit_edge: ; preds = %bb60.i + br label %HWrite.exit + +cond_true81.i: ; preds = %bb60.i + br label %bb413 + +HWrite.exit: ; preds = %bb60.i.HWrite.exit_crit_edge, %cond_next404.HWrite.exit_crit_edge + br label %bb413 + +bb413: ; preds = %HWrite.exit, %cond_true81.i, %bb.i22, %bb391.bb413_crit_edge + br i1 false, label %bb442.preheader.loopexit, label %bb413.bb391_crit_edge + +bb413.bb391_crit_edge: ; preds = %bb413 + br label %bb391 + +bb442.preheader.loopexit: ; preds = %bb413 + br label %bb442.preheader + +bb442.preheader: ; preds = %bb442.preheader.loopexit, %bb390.bb442.preheader_crit_edge + br label %bb442.outer + +bb420: ; preds = %bb442 + br i1 false, label %bb439.loopexit, label %cond_next433 + +cond_next433: ; preds = %bb420 + br i1 false, label %cond_next433.HRead.exit.loopexit_crit_edge, label %cond_next.i + +cond_next433.HRead.exit.loopexit_crit_edge: ; preds = %cond_next433 + br label %HRead.exit.loopexit + +cond_next.i: ; preds = %cond_next433 + br i1 false, label %cond_true9.i, label %cond_false223.i + +cond_true9.i: ; preds = %cond_next.i + switch i32 0, label %cond_false.i [ + i32 1, label %cond_true9.i.cond_true15.i_crit_edge + i32 5, label %cond_true9.i.cond_true15.i_crit_edge9 + ] + +cond_true9.i.cond_true15.i_crit_edge9: ; preds = %cond_true9.i + br label %cond_true15.i + +cond_true9.i.cond_true15.i_crit_edge: ; preds = %cond_true9.i + br label %cond_true15.i + +cond_true15.i: ; preds = %cond_true9.i.cond_true15.i_crit_edge, %cond_true9.i.cond_true15.i_crit_edge9 + br i1 false, label %cond_true15.i.cond_true44.i_crit_edge, label %cond_true15.i.cond_false49.i_crit_edge + +cond_true15.i.cond_false49.i_crit_edge: ; preds = %cond_true15.i + br label %cond_false49.i + +cond_true15.i.cond_true44.i_crit_edge: ; preds = %cond_true15.i + br label %cond_true44.i + +cond_false.i: ; preds = %cond_true9.i + br i1 false, label %cond_false.i.cond_next39.i_crit_edge, label %cond_true30.i + +cond_false.i.cond_next39.i_crit_edge: ; preds = %cond_false.i + br label %cond_next39.i + +cond_true30.i: ; preds = %cond_false.i + br label %cond_next39.i + +cond_next39.i: ; preds = %cond_true30.i, %cond_false.i.cond_next39.i_crit_edge + br i1 false, label %cond_next39.i.cond_true44.i_crit_edge, label %cond_next39.i.cond_false49.i_crit_edge + +cond_next39.i.cond_false49.i_crit_edge: ; preds = %cond_next39.i + br label %cond_false49.i + +cond_next39.i.cond_true44.i_crit_edge: ; preds = %cond_next39.i + br label %cond_true44.i + +cond_true44.i: ; preds = %cond_next39.i.cond_true44.i_crit_edge, %cond_true15.i.cond_true44.i_crit_edge + br i1 false, label %cond_true44.i.cond_next70.i_crit_edge, label %cond_true44.i.cond_true61.i_crit_edge + +cond_true44.i.cond_true61.i_crit_edge: ; preds = %cond_true44.i + br label %cond_true61.i + +cond_true44.i.cond_next70.i_crit_edge: ; preds = %cond_true44.i + br label %cond_next70.i + +cond_false49.i: ; preds = %cond_next39.i.cond_false49.i_crit_edge, %cond_true15.i.cond_false49.i_crit_edge + br i1 false, label %cond_false49.i.cond_next70.i_crit_edge, label %cond_false49.i.cond_true61.i_crit_edge + +cond_false49.i.cond_true61.i_crit_edge: ; preds = %cond_false49.i + br label %cond_true61.i + +cond_false49.i.cond_next70.i_crit_edge: ; preds = %cond_false49.i + br label %cond_next70.i + +cond_true61.i: ; preds = %cond_false49.i.cond_true61.i_crit_edge, %cond_true44.i.cond_true61.i_crit_edge + br i1 false, label %cond_true61.i.cond_next70.i_crit_edge, label %cond_true67.i + +cond_true61.i.cond_next70.i_crit_edge: ; preds = %cond_true61.i + br label %cond_next70.i + +cond_true67.i: ; preds = %cond_true61.i + br label %cond_next70.i + +cond_next70.i: ; preds = %cond_true67.i, %cond_true61.i.cond_next70.i_crit_edge, %cond_false49.i.cond_next70.i_crit_edge, %cond_true44.i.cond_next70.i_crit_edge + br i1 false, label %cond_true77.i, label %cond_next81.i + +cond_true77.i: ; preds = %cond_next70.i + br label %bb442.outer.backedge + +cond_next81.i: ; preds = %cond_next70.i + br i1 false, label %cond_true87.i, label %cond_false94.i + +cond_true87.i: ; preds = %cond_next81.i + br i1 false, label %cond_true87.i.cond_true130.i_crit_edge, label %cond_true87.i.cond_next135.i_crit_edge + +cond_true87.i.cond_next135.i_crit_edge: ; preds = %cond_true87.i + br label %cond_next135.i + +cond_true87.i.cond_true130.i_crit_edge: ; preds = %cond_true87.i + br label %cond_true130.i + +cond_false94.i: ; preds = %cond_next81.i + switch i32 0, label %cond_false94.i.cond_next125.i_crit_edge [ + i32 1, label %cond_false94.i.cond_true100.i_crit_edge + i32 5, label %cond_false94.i.cond_true100.i_crit_edge10 + ] + +cond_false94.i.cond_true100.i_crit_edge10: ; preds = %cond_false94.i + br label %cond_true100.i + +cond_false94.i.cond_true100.i_crit_edge: ; preds = %cond_false94.i + br label %cond_true100.i + +cond_false94.i.cond_next125.i_crit_edge: ; preds = %cond_false94.i + br label %cond_next125.i + +cond_true100.i: ; preds = %cond_false94.i.cond_true100.i_crit_edge, %cond_false94.i.cond_true100.i_crit_edge10 + br i1 false, label %cond_true107.i, label %cond_true100.i.cond_next109.i_crit_edge + +cond_true100.i.cond_next109.i_crit_edge: ; preds = %cond_true100.i + br label %cond_next109.i + +cond_true107.i: ; preds = %cond_true100.i + br label %cond_next109.i + +cond_next109.i: ; preds = %cond_true107.i, %cond_true100.i.cond_next109.i_crit_edge + br i1 false, label %cond_next109.i.cond_next125.i_crit_edge, label %cond_true116.i + +cond_next109.i.cond_next125.i_crit_edge: ; preds = %cond_next109.i + br label %cond_next125.i + +cond_true116.i: ; preds = %cond_next109.i + br label %cond_next125.i + +cond_next125.i: ; preds = %cond_true116.i, %cond_next109.i.cond_next125.i_crit_edge, %cond_false94.i.cond_next125.i_crit_edge + br i1 false, label %cond_next125.i.cond_true130.i_crit_edge, label %cond_next125.i.cond_next135.i_crit_edge + +cond_next125.i.cond_next135.i_crit_edge: ; preds = %cond_next125.i + br label %cond_next135.i + +cond_next125.i.cond_true130.i_crit_edge: ; preds = %cond_next125.i + br label %cond_true130.i + +cond_true130.i: ; preds = %cond_next125.i.cond_true130.i_crit_edge, %cond_true87.i.cond_true130.i_crit_edge + br label %cond_next135.i + +cond_next135.i: ; preds = %cond_true130.i, %cond_next125.i.cond_next135.i_crit_edge, %cond_true87.i.cond_next135.i_crit_edge + br i1 false, label %cond_true142.i, label %cond_next135.i.cond_next149.i_crit_edge + +cond_next135.i.cond_next149.i_crit_edge: ; preds = %cond_next135.i + br label %cond_next149.i + +cond_true142.i: ; preds = %cond_next135.i + br label %cond_next149.i + +cond_next149.i: ; preds = %cond_true142.i, %cond_next135.i.cond_next149.i_crit_edge + br i1 false, label %cond_true156.i, label %cond_next149.i.cond_next163.i_crit_edge + +cond_next149.i.cond_next163.i_crit_edge: ; preds = %cond_next149.i + br label %cond_next163.i + +cond_true156.i: ; preds = %cond_next149.i + br label %cond_next163.i + +cond_next163.i: ; preds = %cond_true156.i, %cond_next149.i.cond_next163.i_crit_edge + br i1 false, label %cond_true182.i, label %cond_next163.i.cond_next380.i_crit_edge + +cond_next163.i.cond_next380.i_crit_edge: ; preds = %cond_next163.i + br label %cond_next380.i + +cond_true182.i: ; preds = %cond_next163.i + br i1 false, label %cond_true182.i.cond_next380.i_crit_edge, label %cond_true196.i + +cond_true182.i.cond_next380.i_crit_edge: ; preds = %cond_true182.i + br label %cond_next380.i + +cond_true196.i: ; preds = %cond_true182.i + br i1 false, label %cond_true210.i, label %cond_true196.i.cond_next380.i_crit_edge + +cond_true196.i.cond_next380.i_crit_edge: ; preds = %cond_true196.i + br label %cond_next380.i + +cond_true210.i: ; preds = %cond_true196.i + br i1 false, label %cond_true216.i, label %cond_true210.i.cond_next380.i_crit_edge + +cond_true210.i.cond_next380.i_crit_edge: ; preds = %cond_true210.i + br label %cond_next380.i + +cond_true216.i: ; preds = %cond_true210.i + br label %cond_next380.i + +cond_false223.i: ; preds = %cond_next.i + br i1 false, label %cond_true229.i, label %cond_false355.i + +cond_true229.i: ; preds = %cond_false223.i + br i1 false, label %cond_true229.i.HRead.exit.loopexit_crit_edge, label %cond_next243.i + +cond_true229.i.HRead.exit.loopexit_crit_edge: ; preds = %cond_true229.i + br label %HRead.exit.loopexit + +cond_next243.i: ; preds = %cond_true229.i + br i1 false, label %cond_true248.i, label %cond_false255.i + +cond_true248.i: ; preds = %cond_next243.i + br label %cond_next260.i + +cond_false255.i: ; preds = %cond_next243.i + br label %cond_next260.i + +cond_next260.i: ; preds = %cond_false255.i, %cond_true248.i + br i1 false, label %cond_true267.i, label %cond_next273.i + +cond_true267.i: ; preds = %cond_next260.i + br label %bb442.backedge + +bb442.backedge: ; preds = %bb.i, %cond_true267.i + br label %bb442 + +cond_next273.i: ; preds = %cond_next260.i + br i1 false, label %cond_true281.i, label %cond_next273.i.cond_next288.i_crit_edge + +cond_next273.i.cond_next288.i_crit_edge: ; preds = %cond_next273.i + br label %cond_next288.i + +cond_true281.i: ; preds = %cond_next273.i + br label %cond_next288.i + +cond_next288.i: ; preds = %cond_true281.i, %cond_next273.i.cond_next288.i_crit_edge + br i1 false, label %cond_true295.i, label %cond_next288.i.cond_next302.i_crit_edge + +cond_next288.i.cond_next302.i_crit_edge: ; preds = %cond_next288.i + br label %cond_next302.i + +cond_true295.i: ; preds = %cond_next288.i + br label %cond_next302.i + +cond_next302.i: ; preds = %cond_true295.i, %cond_next288.i.cond_next302.i_crit_edge + br i1 false, label %cond_next302.i.cond_next380.i_crit_edge, label %cond_true328.i + +cond_next302.i.cond_next380.i_crit_edge: ; preds = %cond_next302.i + br label %cond_next380.i + +cond_true328.i: ; preds = %cond_next302.i + br i1 false, label %cond_true343.i, label %cond_true328.i.cond_next380.i_crit_edge + +cond_true328.i.cond_next380.i_crit_edge: ; preds = %cond_true328.i + br label %cond_next380.i + +cond_true343.i: ; preds = %cond_true328.i + br i1 false, label %cond_true349.i, label %cond_true343.i.cond_next380.i_crit_edge + +cond_true343.i.cond_next380.i_crit_edge: ; preds = %cond_true343.i + br label %cond_next380.i + +cond_true349.i: ; preds = %cond_true343.i + br label %cond_next380.i + +cond_false355.i: ; preds = %cond_false223.i + br i1 false, label %cond_false355.i.bb.i_crit_edge, label %cond_next363.i + +cond_false355.i.bb.i_crit_edge: ; preds = %cond_false355.i + br label %bb.i + +cond_next363.i: ; preds = %cond_false355.i + br i1 false, label %bb377.i, label %cond_next363.i.bb.i_crit_edge + +cond_next363.i.bb.i_crit_edge: ; preds = %cond_next363.i + br label %bb.i + +bb.i: ; preds = %cond_next363.i.bb.i_crit_edge, %cond_false355.i.bb.i_crit_edge + br label %bb442.backedge + +bb377.i: ; preds = %cond_next363.i + br label %cond_next380.i + +cond_next380.i: ; preds = %bb377.i, %cond_true349.i, %cond_true343.i.cond_next380.i_crit_edge, %cond_true328.i.cond_next380.i_crit_edge, %cond_next302.i.cond_next380.i_crit_edge, %cond_true216.i, %cond_true210.i.cond_next380.i_crit_edge, %cond_true196.i.cond_next380.i_crit_edge, %cond_true182.i.cond_next380.i_crit_edge, %cond_next163.i.cond_next380.i_crit_edge + br i1 false, label %cond_next380.i.HRead.exit_crit_edge, label %cond_true391.i + +cond_next380.i.HRead.exit_crit_edge: ; preds = %cond_next380.i + br label %HRead.exit + +cond_true391.i: ; preds = %cond_next380.i + br label %bb442.outer.backedge + +bb442.outer.backedge: ; preds = %bb439, %cond_true391.i, %cond_true77.i + br label %bb442.outer + +HRead.exit.loopexit: ; preds = %cond_true229.i.HRead.exit.loopexit_crit_edge, %cond_next433.HRead.exit.loopexit_crit_edge + br label %HRead.exit + +HRead.exit: ; preds = %HRead.exit.loopexit, %cond_next380.i.HRead.exit_crit_edge + br label %bb439 + +bb439.loopexit: ; preds = %bb420 + br label %bb439 + +bb439: ; preds = %bb439.loopexit, %HRead.exit + br label %bb442.outer.backedge + +bb442.outer: ; preds = %bb442.outer.backedge, %bb442.preheader + br label %bb442 + +bb442: ; preds = %bb442.outer, %bb442.backedge + br i1 false, label %bb420, label %bb.loopexit +} + +define void @Invalidate() { +entry: + br i1 false, label %cond_false, label %cond_true + +cond_true: ; preds = %entry + br i1 false, label %cond_true40, label %cond_true.cond_next_crit_edge + +cond_true.cond_next_crit_edge: ; preds = %cond_true + br label %cond_next + +cond_true40: ; preds = %cond_true + br label %cond_next + +cond_next: ; preds = %cond_true40, %cond_true.cond_next_crit_edge + br i1 false, label %cond_true68, label %cond_next.cond_next73_crit_edge + +cond_next.cond_next73_crit_edge: ; preds = %cond_next + br label %cond_next73 + +cond_true68: ; preds = %cond_next + br label %cond_next73 + +cond_next73: ; preds = %cond_true68, %cond_next.cond_next73_crit_edge + br i1 false, label %cond_true91, label %cond_next73.cond_next96_crit_edge + +cond_next73.cond_next96_crit_edge: ; preds = %cond_next73 + br label %cond_next96 + +cond_true91: ; preds = %cond_next73 + br label %cond_next96 + +cond_next96: ; preds = %cond_true91, %cond_next73.cond_next96_crit_edge + br i1 false, label %cond_next96.cond_next112_crit_edge, label %cond_true105 + +cond_next96.cond_next112_crit_edge: ; preds = %cond_next96 + br label %cond_next112 + +cond_true105: ; preds = %cond_next96 + br label %cond_next112 + +cond_next112: ; preds = %cond_true105, %cond_next96.cond_next112_crit_edge + br i1 false, label %cond_next112.cond_next127_crit_edge, label %cond_true119 + +cond_next112.cond_next127_crit_edge: ; preds = %cond_next112 + br label %cond_next127 + +cond_true119: ; preds = %cond_next112 + br label %cond_next127 + +cond_next127: ; preds = %cond_true119, %cond_next112.cond_next127_crit_edge + br i1 false, label %cond_next141, label %cond_true134 + +cond_true134: ; preds = %cond_next127 + br i1 false, label %cond_true134.bb161_crit_edge, label %cond_true134.bb_crit_edge + +cond_true134.bb_crit_edge: ; preds = %cond_true134 + br label %bb + +cond_true134.bb161_crit_edge: ; preds = %cond_true134 + br label %bb161 + +cond_next141: ; preds = %cond_next127 + br label %bb154 + +bb: ; preds = %bb154.bb_crit_edge, %cond_true134.bb_crit_edge + br label %bb154 + +bb154: ; preds = %bb, %cond_next141 + br i1 false, label %bb154.bb161_crit_edge, label %bb154.bb_crit_edge + +bb154.bb_crit_edge: ; preds = %bb154 + br label %bb + +bb154.bb161_crit_edge: ; preds = %bb154 + br label %bb161 + +bb161: ; preds = %bb154.bb161_crit_edge, %cond_true134.bb161_crit_edge + br i1 false, label %bb161.cond_next201_crit_edge, label %cond_true198 + +bb161.cond_next201_crit_edge: ; preds = %bb161 + br label %cond_next201 + +cond_true198: ; preds = %bb161 + br label %cond_next201 + +cond_next201: ; preds = %cond_true198, %bb161.cond_next201_crit_edge + br i1 false, label %cond_next212, label %cond_true206 + +cond_true206: ; preds = %cond_next201 + br label %UnifiedReturnBlock + +cond_false: ; preds = %entry + br label %UnifiedReturnBlock + +cond_next212: ; preds = %cond_next201 + br label %UnifiedReturnBlock + +UnifiedReturnBlock: ; preds = %cond_next212, %cond_false, %cond_true206 + ret void +} diff --git a/libclamav/c++/llvm/test/Analysis/PostDominators/2007-04-20-PostDom-Reset.ll b/libclamav/c++/llvm/test/Analysis/PostDominators/2007-04-20-PostDom-Reset.ll new file mode 100644 index 000000000..767e5db94 --- /dev/null +++ b/libclamav/c++/llvm/test/Analysis/PostDominators/2007-04-20-PostDom-Reset.ll @@ -0,0 +1,28 @@ +; RUN: opt < %s -postdomfrontier -disable-output + +define void @args_out_of_range() { +entry: + br label %bb + +bb: ; preds = %bb, %entry + br label %bb +} + +define void @args_out_of_range_3() { +entry: + br label %bb + +bb: ; preds = %bb, %entry + br label %bb +} + +define void @Feq() { +entry: + br i1 false, label %cond_true, label %cond_next + +cond_true: ; preds = %entry + unreachable + +cond_next: ; preds = %entry + unreachable +} diff --git a/libclamav/c++/llvm/test/Analysis/PostDominators/dg.exp b/libclamav/c++/llvm/test/Analysis/PostDominators/dg.exp new file mode 100644 index 000000000..f2005891a --- /dev/null +++ b/libclamav/c++/llvm/test/Analysis/PostDominators/dg.exp @@ -0,0 +1,3 @@ +load_lib llvm.exp + +RunLLVMTests [lsort [glob -nocomplain $srcdir/$subdir/*.{ll,c,cpp}]] diff --git a/libclamav/c++/llvm/test/Analysis/PostDominators/pr1098.ll b/libclamav/c++/llvm/test/Analysis/PostDominators/pr1098.ll new file mode 100644 index 000000000..afb47769e --- /dev/null +++ b/libclamav/c++/llvm/test/Analysis/PostDominators/pr1098.ll @@ -0,0 +1,14 @@ +; RUN: opt < %s -postdomtree -analyze | grep entry +; PR932 + +define void @foo(i1 %x) { +entry: + br i1 %x, label %bb1, label %bb0 +bb0: ; preds = %entry, bb0 + br label %bb0 +bb1: ; preds = %entry + br label %bb2 +bb2: ; preds = %bb1 + ret void +} + diff --git a/libclamav/c++/llvm/test/Analysis/Profiling/dg.exp b/libclamav/c++/llvm/test/Analysis/Profiling/dg.exp new file mode 100644 index 000000000..1eb4755c4 --- /dev/null +++ b/libclamav/c++/llvm/test/Analysis/Profiling/dg.exp @@ -0,0 +1,4 @@ +load_lib llvm.exp + +RunLLVMTests [lsort [glob -nocomplain $srcdir/$subdir/*.{ll,c,cpp}]] + diff --git a/libclamav/c++/llvm/test/Analysis/Profiling/edge-profiling.ll b/libclamav/c++/llvm/test/Analysis/Profiling/edge-profiling.ll new file mode 100644 index 000000000..cbaf47617 --- /dev/null +++ b/libclamav/c++/llvm/test/Analysis/Profiling/edge-profiling.ll @@ -0,0 +1,139 @@ +; Test the edge profiling instrumentation. +; RUN: opt < %s -insert-edge-profiling -S | FileCheck %s + +; ModuleID = '' + +@.str = private constant [12 x i8] c"hello world\00", align 1 ; <[12 x i8]*> [#uses=1] +@.str1 = private constant [6 x i8] c"franz\00", align 1 ; <[6 x i8]*> [#uses=1] +@.str2 = private constant [9 x i8] c"argc > 2\00", align 1 ; <[9 x i8]*> [#uses=1] +@.str3 = private constant [9 x i8] c"argc = 1\00", align 1 ; <[9 x i8]*> [#uses=1] +@.str4 = private constant [6 x i8] c"fritz\00", align 1 ; <[6 x i8]*> [#uses=1] +@.str5 = private constant [10 x i8] c"argc <= 1\00", align 1 ; <[10 x i8]*> [#uses=1] +; CHECK:@EdgeProfCounters +; CHECK:[19 x i32] +; CHECK:zeroinitializer + +define void @oneblock() nounwind { +entry: +; CHECK:entry: +; CHECK:%OldFuncCounter +; CHECK:load +; CHECK:getelementptr +; CHECK:@EdgeProfCounters +; CHECK:i32 0 +; CHECK:i32 0 +; CHECK:%NewFuncCounter +; CHECK:add +; CHECK:%OldFuncCounter +; CHECK:store +; CHECK:%NewFuncCounter +; CHECK:getelementptr +; CHECK:@EdgeProfCounters + %0 = call i32 @puts(i8* getelementptr inbounds ([12 x i8]* @.str, i64 0, i64 0)) nounwind ; [#uses=0] + ret void +} + +declare i32 @puts(i8*) + +define i32 @main(i32 %argc, i8** %argv) nounwind { +entry: +; CHECK:entry: + %argc_addr = alloca i32 ; [#uses=4] + %argv_addr = alloca i8** ; [#uses=1] + %retval = alloca i32 ; [#uses=2] + %j = alloca i32 ; [#uses=4] + %i = alloca i32 ; [#uses=4] + %0 = alloca i32 ; [#uses=2] +; CHECK:call +; CHECK:@llvm_start_edge_profiling +; CHECK:@EdgeProfCounters + %"alloca point" = bitcast i32 0 to i32 ; [#uses=0] + store i32 %argc, i32* %argc_addr + store i8** %argv, i8*** %argv_addr + store i32 0, i32* %i, align 4 + br label %bb10 + +bb: ; preds = %bb10 +; CHECK:bb: + %1 = load i32* %argc_addr, align 4 ; [#uses=1] + %2 = icmp sgt i32 %1, 1 ; [#uses=1] + br i1 %2, label %bb1, label %bb8 + +bb1: ; preds = %bb +; CHECK:bb1: + store i32 0, i32* %j, align 4 + br label %bb6 + +bb2: ; preds = %bb6 +; CHECK:bb2: + %3 = call i32 @puts(i8* getelementptr inbounds ([6 x i8]* @.str1, i64 0, i64 0)) nounwind ; [#uses=0] + %4 = load i32* %argc_addr, align 4 ; [#uses=1] + %5 = icmp sgt i32 %4, 2 ; [#uses=1] + br i1 %5, label %bb3, label %bb4 + +bb3: ; preds = %bb2 +; CHECK:bb3: + %6 = call i32 @puts(i8* getelementptr inbounds ([9 x i8]* @.str2, i64 0, i64 0)) nounwind ; [#uses=0] + br label %bb5 + +bb4: ; preds = %bb2 +; CHECK:bb4: + %7 = call i32 @puts(i8* getelementptr inbounds ([9 x i8]* @.str3, i64 0, i64 0)) nounwind ; [#uses=0] + br label %bb11 + +bb5: ; preds = %bb3 +; CHECK:bb5: + %8 = call i32 @puts(i8* getelementptr inbounds ([6 x i8]* @.str4, i64 0, i64 0)) nounwind ; [#uses=0] + %9 = load i32* %j, align 4 ; [#uses=1] + %10 = add nsw i32 %9, 1 ; [#uses=1] + store i32 %10, i32* %j, align 4 + br label %bb6 + +bb6: ; preds = %bb5, %bb1 +; CHECK:bb6: + %11 = load i32* %j, align 4 ; [#uses=1] + %12 = load i32* %argc_addr, align 4 ; [#uses=1] + %13 = icmp slt i32 %11, %12 ; [#uses=1] + br i1 %13, label %bb2, label %bb7 + +bb7: ; preds = %bb6 +; CHECK:bb7: + br label %bb9 + +bb8: ; preds = %bb +; CHECK:bb8: + %14 = call i32 @puts(i8* getelementptr inbounds ([10 x i8]* @.str5, i64 0, i64 0)) nounwind ; [#uses=0] + br label %bb9 + +bb9: ; preds = %bb8, %bb7 +; CHECK:bb9: + %15 = load i32* %i, align 4 ; [#uses=1] + %16 = add nsw i32 %15, 1 ; [#uses=1] + store i32 %16, i32* %i, align 4 + br label %bb10 + +bb10: ; preds = %bb9, %entry +; CHECK:bb10: + %17 = load i32* %i, align 4 ; [#uses=1] + %18 = icmp ne i32 %17, 3 ; [#uses=1] + br i1 %18, label %bb, label %bb11 +; CHECK:br +; CHECK:label %bb10.bb11_crit_edge + +; CHECK:bb10.bb11_crit_edge: +; CHECK:br +; CHECK:label %bb11 + +bb11: ; preds = %bb10, %bb4 +; CHECK:bb11: + call void @oneblock() nounwind + store i32 0, i32* %0, align 4 + %19 = load i32* %0, align 4 ; [#uses=1] + store i32 %19, i32* %retval, align 4 + br label %return + +return: ; preds = %bb11 +; CHECK:return: + %retval12 = load i32* %retval ; [#uses=1] + ret i32 %retval12 +} diff --git a/libclamav/c++/llvm/test/Analysis/Profiling/profiling-tool-chain.ll b/libclamav/c++/llvm/test/Analysis/Profiling/profiling-tool-chain.ll new file mode 100644 index 000000000..5ac31b59b --- /dev/null +++ b/libclamav/c++/llvm/test/Analysis/Profiling/profiling-tool-chain.ll @@ -0,0 +1,212 @@ +; RUN: llvm-as %s -o %t1 + +; FIXME: The RUX parts of the test are disabled for now, they aren't working on +; llvm-gcc-x86_64-darwin10-selfhost. + +; Test the edge optimal profiling instrumentation. +; RUN: opt %t1 -insert-optimal-edge-profiling -o %t2 +; RUX: llvm-dis < %t2 | FileCheck --check-prefix=INST %s + +; Test the creation, reading and displaying of profile +; RUX: rm -f llvmprof.out +; RUX: lli -load %llvmlibsdir/profile_rt%shlibext %t2 +; RUX: lli -load %llvmlibsdir/profile_rt%shlibext %t2 1 2 +; RUX: llvm-prof -print-all-code %t1 | FileCheck --check-prefix=PROF %s + +; Test the loaded profile also with verifier. +; RUX opt %t1 -profile-loader -profile-verifier -o %t3 + +; Test profile estimator. +; RUN: opt %t1 -profile-estimator -profile-verifier -o %t3 + +; PROF: 1. 2/4 oneblock +; PROF: 2. 2/4 main +; PROF: 1. 15.7895% 12/76 main() - bb6 +; PROF: 2. 11.8421% 9/76 main() - bb2 +; PROF: 3. 11.8421% 9/76 main() - bb3 +; PROF: 4. 11.8421% 9/76 main() - bb5 +; PROF: 5. 10.5263% 8/76 main() - bb10 +; PROF: 6. 7.89474% 6/76 main() - bb +; PROF: 7. 7.89474% 6/76 main() - bb9 +; PROF: 8. 3.94737% 3/76 main() - bb1 +; PROF: 9. 3.94737% 3/76 main() - bb7 +; PROF: 10. 3.94737% 3/76 main() - bb8 +; PROF: 11. 2.63158% 2/76 oneblock() - entry +; PROF: 12. 2.63158% 2/76 main() - entry +; PROF: 13. 2.63158% 2/76 main() - bb11 +; PROF: 14. 2.63158% 2/76 main() - return + +; ModuleID = '' + +@.str = private constant [12 x i8] c"hello world\00", align 1 ; <[12 x i8]*> [#uses=1] +@.str1 = private constant [6 x i8] c"franz\00", align 1 ; <[6 x i8]*> [#uses=1] +@.str2 = private constant [9 x i8] c"argc > 2\00", align 1 ; <[9 x i8]*> [#uses=1] +@.str3 = private constant [9 x i8] c"argc = 1\00", align 1 ; <[9 x i8]*> [#uses=1] +@.str4 = private constant [6 x i8] c"fritz\00", align 1 ; <[6 x i8]*> [#uses=1] +@.str5 = private constant [10 x i8] c"argc <= 1\00", align 1 ; <[10 x i8]*> [#uses=1] +; INST:@OptEdgeProfCounters +; INST:[21 x i32] +; INST:[i32 0, +; INST:i32 -1, +; INST:i32 -1, +; INST:i32 -1, +; INST:i32 -1, +; INST:i32 -1, +; INST:i32 -1, +; INST:i32 -1, +; INST:i32 -1, +; INST:i32 0, +; INST:i32 0, +; INST:i32 -1, +; INST:i32 -1, +; INST:i32 -1, +; INST:i32 0, +; INST:i32 0, +; INST:i32 -1, +; INST:i32 -1, +; INST:i32 0, +; INST:i32 -1, +; INST:i32 -1] + +; PROF:;;; %oneblock called 2 times. +; PROF:;;; +define void @oneblock() nounwind { +entry: +; PROF:entry: +; PROF: ;;; Basic block executed 2 times. + %0 = call i32 @puts(i8* getelementptr inbounds ([12 x i8]* @.str, i64 0, i64 0)) nounwind ; [#uses=0] + ret void +} + +declare i32 @puts(i8*) + +; PROF:;;; %main called 2 times. +; PROF:;;; +define i32 @main(i32 %argc, i8** %argv) nounwind { +entry: +; PROF:entry: +; PROF: ;;; Basic block executed 2 times. + %argc_addr = alloca i32 ; [#uses=4] + %argv_addr = alloca i8** ; [#uses=1] + %retval = alloca i32 ; [#uses=2] + %j = alloca i32 ; [#uses=4] + %i = alloca i32 ; [#uses=4] + %0 = alloca i32 ; [#uses=2] +; INST:call +; INST:@llvm_start_opt_edge_profiling +; INST:@OptEdgeProfCounters + %"alloca point" = bitcast i32 0 to i32 ; [#uses=0] + store i32 %argc, i32* %argc_addr + store i8** %argv, i8*** %argv_addr + store i32 0, i32* %i, align 4 + br label %bb10 +; PROF: ;;; Out-edge counts: [2.000000e+00 -> bb10] + +bb: ; preds = %bb10 +; PROF:bb: +; PROF: ;;; Basic block executed 6 times. + %1 = load i32* %argc_addr, align 4 ; [#uses=1] + %2 = icmp sgt i32 %1, 1 ; [#uses=1] + br i1 %2, label %bb1, label %bb8 +; PROF: ;;; Out-edge counts: [3.000000e+00 -> bb1] [3.000000e+00 -> bb8] + +bb1: ; preds = %bb +; PROF:bb1: +; PROF: ;;; Basic block executed 3 times. + store i32 0, i32* %j, align 4 + br label %bb6 +; PROF: ;;; Out-edge counts: [3.000000e+00 -> bb6] + +bb2: ; preds = %bb6 +; PROF:bb2: +; PROF: ;;; Basic block executed 9 times. + %3 = call i32 @puts(i8* getelementptr inbounds ([6 x i8]* @.str1, i64 0, i64 0)) nounwind ; [#uses=0] + %4 = load i32* %argc_addr, align 4 ; [#uses=1] + %5 = icmp sgt i32 %4, 2 ; [#uses=1] + br i1 %5, label %bb3, label %bb4 +; PROF: ;;; Out-edge counts: [9.000000e+00 -> bb3] + +bb3: ; preds = %bb2 +; PROF:bb3: +; PROF: ;;; Basic block executed 9 times. + %6 = call i32 @puts(i8* getelementptr inbounds ([9 x i8]* @.str2, i64 0, i64 0)) nounwind ; [#uses=0] + br label %bb5 +; PROF: ;;; Out-edge counts: [9.000000e+00 -> bb5] + +bb4: ; preds = %bb2 +; PROF:bb4: +; PROF: ;;; Never executed! + %7 = call i32 @puts(i8* getelementptr inbounds ([9 x i8]* @.str3, i64 0, i64 0)) nounwind ; [#uses=0] + br label %bb11 + +bb5: ; preds = %bb3 +; PROF:bb5: +; PROF: ;;; Basic block executed 9 times. + %8 = call i32 @puts(i8* getelementptr inbounds ([6 x i8]* @.str4, i64 0, i64 0)) nounwind ; [#uses=0] + %9 = load i32* %j, align 4 ; [#uses=1] + %10 = add nsw i32 %9, 1 ; [#uses=1] + store i32 %10, i32* %j, align 4 + br label %bb6 +; PROF: ;;; Out-edge counts: [9.000000e+00 -> bb6] + +bb6: ; preds = %bb5, %bb1 +; PROF:bb6: +; PROF: ;;; Basic block executed 12 times. + %11 = load i32* %j, align 4 ; [#uses=1] + %12 = load i32* %argc_addr, align 4 ; [#uses=1] + %13 = icmp slt i32 %11, %12 ; [#uses=1] + br i1 %13, label %bb2, label %bb7 +; PROF: ;;; Out-edge counts: [9.000000e+00 -> bb2] [3.000000e+00 -> bb7] + +bb7: ; preds = %bb6 +; PROF:bb7: +; PROF: ;;; Basic block executed 3 times. + br label %bb9 +; PROF: ;;; Out-edge counts: [3.000000e+00 -> bb9] + +bb8: ; preds = %bb +; PROF:bb8: +; PROF: ;;; Basic block executed 3 times. + %14 = call i32 @puts(i8* getelementptr inbounds ([10 x i8]* @.str5, i64 0, i64 0)) nounwind ; [#uses=0] + br label %bb9 +; PROF: ;;; Out-edge counts: [3.000000e+00 -> bb9] + +bb9: ; preds = %bb8, %bb7 +; PROF:bb9: +; PROF: ;;; Basic block executed 6 times. + %15 = load i32* %i, align 4 ; [#uses=1] + %16 = add nsw i32 %15, 1 ; [#uses=1] + store i32 %16, i32* %i, align 4 + br label %bb10 +; PROF: ;;; Out-edge counts: [6.000000e+00 -> bb10] + +bb10: ; preds = %bb9, %entry +; PROF:bb10: +; PROF: ;;; Basic block executed 8 times. + %17 = load i32* %i, align 4 ; [#uses=1] + %18 = icmp ne i32 %17, 3 ; [#uses=1] + br i1 %18, label %bb, label %bb11 +; INST:br +; INST:label %bb10.bb11_crit_edge +; PROF: ;;; Out-edge counts: [6.000000e+00 -> bb] [2.000000e+00 -> bb11] + +; INST:bb10.bb11_crit_edge: +; INST:br +; INST:label %bb11 + +bb11: ; preds = %bb10, %bb4 +; PROF:bb11: +; PROF: ;;; Basic block executed 2 times. + call void @oneblock() nounwind + store i32 0, i32* %0, align 4 + %19 = load i32* %0, align 4 ; [#uses=1] + store i32 %19, i32* %retval, align 4 + br label %return +; PROF: ;;; Out-edge counts: [2.000000e+00 -> return] + +return: ; preds = %bb11 +; PROF:return: +; PROF: ;;; Basic block executed 2 times. + %retval12 = load i32* %retval ; [#uses=1] + ret i32 %retval12 +} diff --git a/libclamav/c++/llvm/test/Analysis/ScalarEvolution/2007-07-15-NegativeStride.ll b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/2007-07-15-NegativeStride.ll new file mode 100644 index 000000000..7f82ea435 --- /dev/null +++ b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/2007-07-15-NegativeStride.ll @@ -0,0 +1,21 @@ +; RUN: opt < %s -analyze -scalar-evolution -disable-output \ +; RUN: -scalar-evolution-max-iterations=0 | grep {Loop bb: backedge-taken count is 100} +; PR1533 + +@array = weak global [101 x i32] zeroinitializer, align 32 ; <[100 x i32]*> [#uses=1] + +define void @loop(i32 %x) { +entry: + br label %bb + +bb: ; preds = %bb, %entry + %i.01.0 = phi i32 [ 100, %entry ], [ %tmp4, %bb ] ; [#uses=2] + %tmp1 = getelementptr [101 x i32]* @array, i32 0, i32 %i.01.0 ; [#uses=1] + store i32 %x, i32* %tmp1 + %tmp4 = add i32 %i.01.0, -1 ; [#uses=2] + %tmp7 = icmp sgt i32 %tmp4, -1 ; [#uses=1] + br i1 %tmp7, label %bb, label %return + +return: ; preds = %bb + ret void +} diff --git a/libclamav/c++/llvm/test/Analysis/ScalarEvolution/2007-08-06-MisinterpretBranch.ll b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/2007-08-06-MisinterpretBranch.ll new file mode 100644 index 000000000..e67e4d00d --- /dev/null +++ b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/2007-08-06-MisinterpretBranch.ll @@ -0,0 +1,18 @@ +; RUN: opt < %s -indvars -adce -simplifycfg -S | grep "icmp s" +; PR1598 + +define i32 @f(i32 %a, i32 %b, i32 %x, i32 %y) { +entry: + %tmp3 = icmp eq i32 %a, %b ; [#uses=1] + br i1 %tmp3, label %return, label %bb + +bb: ; preds = %bb, %entry + %x_addr.0 = phi i32 [ %tmp6, %bb ], [ %x, %entry ] ; [#uses=1] + %tmp6 = add i32 %x_addr.0, 1 ; [#uses=3] + %tmp9 = icmp slt i32 %tmp6, %y ; [#uses=1] + br i1 %tmp9, label %bb, label %return + +return: ; preds = %bb, %entry + %x_addr.1 = phi i32 [ %x, %entry ], [ %tmp6, %bb ] ; [#uses=1] + ret i32 %x_addr.1 +} diff --git a/libclamav/c++/llvm/test/Analysis/ScalarEvolution/2007-08-06-Unsigned.ll b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/2007-08-06-Unsigned.ll new file mode 100644 index 000000000..f623da1b2 --- /dev/null +++ b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/2007-08-06-Unsigned.ll @@ -0,0 +1,30 @@ +; RUN: opt < %s -scalar-evolution -analyze -disable-output | grep {Loop bb: backedge-taken count is (-1 + (-1 \\* %x) + %y)} +; PR1597 + +define i32 @f(i32 %x, i32 %y) { +entry: + %tmp63 = icmp ult i32 %x, %y ; [#uses=1] + br i1 %tmp63, label %bb.preheader, label %bb8 + +bb.preheader: ; preds = %entry + br label %bb + +bb: ; preds = %bb3, %bb.preheader + %x_addr.0 = phi i32 [ %tmp2, %bb3 ], [ %x, %bb.preheader ] ; [#uses=1] + %tmp2 = add i32 %x_addr.0, 1 ; [#uses=3] + br label %bb3 + +bb3: ; preds = %bb + %tmp6 = icmp ult i32 %tmp2, %y ; [#uses=1] + br i1 %tmp6, label %bb, label %bb8.loopexit + +bb8.loopexit: ; preds = %bb3 + br label %bb8 + +bb8: ; preds = %bb8.loopexit, %entry + %x_addr.1 = phi i32 [ %x, %entry ], [ %tmp2, %bb8.loopexit ] ; [#uses=1] + br label %return + +return: ; preds = %bb8 + ret i32 %x_addr.1 +} diff --git a/libclamav/c++/llvm/test/Analysis/ScalarEvolution/2007-09-27-LargeStepping.ll b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/2007-09-27-LargeStepping.ll new file mode 100644 index 000000000..817090ffe --- /dev/null +++ b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/2007-09-27-LargeStepping.ll @@ -0,0 +1,22 @@ +; RUN: opt < %s -analyze -scalar-evolution -disable-output \ +; RUN: -scalar-evolution-max-iterations=0 | grep {backedge-taken count is 13} +; PR1706 + +define i32 @f() { +entry: + br label %bb5 + +bb: ; preds = %bb5 + %tmp2 = shl i32 %j.0, 1 ; [#uses=1] + %tmp4 = add i32 %i.0, 268435456 ; [#uses=1] + br label %bb5 + +bb5: ; preds = %bb, %entry + %j.0 = phi i32 [ 1, %entry ], [ %tmp2, %bb ] ; [#uses=2] + %i.0 = phi i32 [ -1879048192, %entry ], [ %tmp4, %bb ] ; [#uses=2] + %tmp7 = icmp slt i32 %i.0, 1610612736 ; [#uses=1] + br i1 %tmp7, label %bb, label %return + +return: ; preds = %bb5 + ret i32 %j.0 +} diff --git a/libclamav/c++/llvm/test/Analysis/ScalarEvolution/2007-11-14-SignedAddRec.ll b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/2007-11-14-SignedAddRec.ll new file mode 100644 index 000000000..514920f0f --- /dev/null +++ b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/2007-11-14-SignedAddRec.ll @@ -0,0 +1,24 @@ +; RUN: opt < %s -indvars -S | grep printd | grep 1206807378 +; PR1798 + +declare void @printd(i32) + +define i32 @test() { +entry: + br label %bb6 + +bb: ; preds = %bb6 + %tmp3 = add i32 %x.0, %i.0 ; [#uses=1] + %tmp5 = add i32 %i.0, 1 ; [#uses=1] + br label %bb6 + +bb6: ; preds = %bb, %entry + %i.0 = phi i32 [ 0, %entry ], [ %tmp5, %bb ] ; [#uses=3] + %x.0 = phi i32 [ 0, %entry ], [ %tmp3, %bb ] ; [#uses=3] + %tmp8 = icmp slt i32 %i.0, 123456789 ; [#uses=1] + br i1 %tmp8, label %bb, label %bb10 + +bb10: ; preds = %bb6 + call void @printd(i32 %x.0) + ret i32 0 +} diff --git a/libclamav/c++/llvm/test/Analysis/ScalarEvolution/2007-11-18-OrInstruction.ll b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/2007-11-18-OrInstruction.ll new file mode 100644 index 000000000..27fe71408 --- /dev/null +++ b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/2007-11-18-OrInstruction.ll @@ -0,0 +1,21 @@ +; RUN: opt < %s -analyze -scalar-evolution -disable-output | FileCheck %s +; PR1810 + +define void @fun() { +entry: + br label %header +header: + %i = phi i32 [ 1, %entry ], [ %i.next, %body ] + %cond = icmp eq i32 %i, 10 + br i1 %cond, label %exit, label %body +body: + %a = mul i32 %i, 5 + %b = or i32 %a, 1 + %i.next = add i32 %i, 1 + br label %header +exit: + ret void +} + +; CHECK: --> %b + diff --git a/libclamav/c++/llvm/test/Analysis/ScalarEvolution/2008-02-11-ReversedCondition.ll b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/2008-02-11-ReversedCondition.ll new file mode 100644 index 000000000..c8e483e7d --- /dev/null +++ b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/2008-02-11-ReversedCondition.ll @@ -0,0 +1,15 @@ +; RUN: opt < %s -scalar-evolution -analyze -disable-output | grep {Loop header: backedge-taken count is (0 smax %n)} + +define void @foo(i32 %n) { +entry: + br label %header +header: + %i = phi i32 [ 0, %entry ], [ %i.inc, %next ] + %cond = icmp sgt i32 %n, %i + br i1 %cond, label %next, label %return +next: + %i.inc = add i32 %i, 1 + br label %header +return: + ret void +} diff --git a/libclamav/c++/llvm/test/Analysis/ScalarEvolution/2008-02-12-SMAXTripCount.ll b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/2008-02-12-SMAXTripCount.ll new file mode 100644 index 000000000..cb9a1829e --- /dev/null +++ b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/2008-02-12-SMAXTripCount.ll @@ -0,0 +1,16 @@ +; RUN: opt < %s -scalar-evolution -analyze -disable-output | grep {Loop loop: backedge-taken count is (100 + (-100 smax %n))} +; PR2002 + +define void @foo(i8 %n) { +entry: + br label %loop +loop: + %i = phi i8 [ -100, %entry ], [ %i.inc, %next ] + %cond = icmp slt i8 %i, %n + br i1 %cond, label %next, label %return +next: + %i.inc = add i8 %i, 1 + br label %loop +return: + ret void +} diff --git a/libclamav/c++/llvm/test/Analysis/ScalarEvolution/2008-02-15-UMax.ll b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/2008-02-15-UMax.ll new file mode 100644 index 000000000..bf9f4a9e8 --- /dev/null +++ b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/2008-02-15-UMax.ll @@ -0,0 +1,17 @@ +; RUN: opt < %s -analyze -scalar-evolution -disable-output | grep umax +; PR2003 + +define i32 @foo(i32 %n) { +entry: + br label %header +header: + %i = phi i32 [ 100, %entry ], [ %i.inc, %next ] + %cond = icmp ult i32 %i, %n + br i1 %cond, label %next, label %return +next: + %i.inc = add i32 %i, 1 + br label %header +return: + ret i32 %i +} + diff --git a/libclamav/c++/llvm/test/Analysis/ScalarEvolution/2008-05-25-NegativeStepToZero.ll b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/2008-05-25-NegativeStepToZero.ll new file mode 100644 index 000000000..8d15b772f --- /dev/null +++ b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/2008-05-25-NegativeStepToZero.ll @@ -0,0 +1,22 @@ +; RUN: opt < %s -analyze -scalar-evolution -disable-output \ +; RUN: -scalar-evolution-max-iterations=0 | grep {backedge-taken count is 61} +; PR2364 + +define i32 @func_6() nounwind { +entry: + br label %bb5 + +bb: ; preds = %bb5 + %tmp2 = add i32 %i.0, 1 ; [#uses=1] + %tmp4 = add i8 %x.0, -4 ; [#uses=1] + br label %bb5 + +bb5: ; preds = %bb, %entry + %x.0 = phi i8 [ 0, %entry ], [ %tmp4, %bb ] ; [#uses=2] + %i.0 = phi i32 [ 0, %entry ], [ %tmp2, %bb ] ; [#uses=2] + %tmp7 = icmp eq i8 %x.0, 12 ; [#uses=1] + br i1 %tmp7, label %return, label %bb + +return: ; preds = %bb5 + ret i32 %i.0 +} diff --git a/libclamav/c++/llvm/test/Analysis/ScalarEvolution/2008-06-12-BinomialInt64.ll b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/2008-06-12-BinomialInt64.ll new file mode 100644 index 000000000..d50332929 --- /dev/null +++ b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/2008-06-12-BinomialInt64.ll @@ -0,0 +1,43 @@ +; RUN: opt < %s -analyze -scalar-evolution 2>/dev/null +; PR2433 + +define i32 @main1(i32 %argc, i8** %argv) nounwind { +entry: + br i1 false, label %bb10, label %bb23 + +bb10: ; preds = %bb10, %entry + %accum.03 = phi i64 [ %tmp14, %bb10 ], [ 0, %entry ] ; [#uses=1] + %i.02 = phi i32 [ %tmp16, %bb10 ], [ 0, %entry ] ; [#uses=1] + %d.1.01 = phi i64 [ %tmp5.i, %bb10 ], [ 0, %entry ] ; [#uses=1] + %tmp5.i = add i64 %d.1.01, 1 ; [#uses=2] + %tmp14 = add i64 %accum.03, %tmp5.i ; [#uses=2] + %tmp16 = add i32 %i.02, 1 ; [#uses=2] + %tmp20 = icmp slt i32 %tmp16, 0 ; [#uses=1] + br i1 %tmp20, label %bb10, label %bb23 + +bb23: ; preds = %bb10, %entry + %accum.0.lcssa = phi i64 [ 0, %entry ], [ %tmp14, %bb10 ] ; [#uses=0] + ret i32 0 +} + +define i32 @main2(i32 %argc, i8** %argv) { +entry: + %tmp8 = tail call i32 @atoi( i8* null ) nounwind readonly ; [#uses=1] + br i1 false, label %bb9, label %bb21 + +bb9: ; preds = %bb9, %entry + %accum.03 = phi i64 [ %tmp12, %bb9 ], [ 0, %entry ] ; [#uses=1] + %i.02 = phi i32 [ %tmp14, %bb9 ], [ 0, %entry ] ; [#uses=1] + %d.1.01 = phi i64 [ %tmp4.i, %bb9 ], [ 0, %entry ] ; [#uses=1] + %tmp4.i = add i64 %d.1.01, 1 ; [#uses=2] + %tmp12 = add i64 %accum.03, %tmp4.i ; [#uses=2] + %tmp14 = add i32 %i.02, 1 ; [#uses=2] + %tmp18 = icmp slt i32 %tmp14, %tmp8 ; [#uses=1] + br i1 %tmp18, label %bb9, label %bb21 + +bb21: ; preds = %bb9, %entry + %accum.0.lcssa = phi i64 [ 0, %entry ], [ %tmp12, %bb9 ] ; [#uses=0] + ret i32 0 +} + +declare i32 @atoi(i8*) nounwind readonly diff --git a/libclamav/c++/llvm/test/Analysis/ScalarEvolution/2008-07-12-UnneededSelect1.ll b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/2008-07-12-UnneededSelect1.ll new file mode 100644 index 000000000..850b6708f --- /dev/null +++ b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/2008-07-12-UnneededSelect1.ll @@ -0,0 +1,36 @@ +; RUN: opt < %s -analyze -scalar-evolution -disable-output |& not grep smax +; PR2261 + +@lut = common global [256 x i8] zeroinitializer, align 32 ; <[256 x i8]*> [#uses=1] + +define void @foo(i32 %count, i32* %srcptr, i32* %dstptr) nounwind { +entry: + icmp sgt i32 %count, 0 ; :0 [#uses=1] + br i1 %0, label %bb.nph, label %return + +bb.nph: ; preds = %entry + br label %bb + +bb: ; preds = %bb1, %bb.nph + %j.01 = phi i32 [ %8, %bb1 ], [ 0, %bb.nph ] ; [#uses=1] + load i32* %srcptr, align 4 ; :1 [#uses=2] + and i32 %1, 255 ; :2 [#uses=1] + and i32 %1, -256 ; :3 [#uses=1] + getelementptr [256 x i8]* @lut, i32 0, i32 %2 ; :4 [#uses=1] + load i8* %4, align 1 ; :5 [#uses=1] + zext i8 %5 to i32 ; :6 [#uses=1] + or i32 %6, %3 ; :7 [#uses=1] + store i32 %7, i32* %dstptr, align 4 + add i32 %j.01, 1 ; :8 [#uses=2] + br label %bb1 + +bb1: ; preds = %bb + icmp slt i32 %8, %count ; :9 [#uses=1] + br i1 %9, label %bb, label %bb1.return_crit_edge + +bb1.return_crit_edge: ; preds = %bb1 + br label %return + +return: ; preds = %bb1.return_crit_edge, %entry + ret void +} diff --git a/libclamav/c++/llvm/test/Analysis/ScalarEvolution/2008-07-12-UnneededSelect2.ll b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/2008-07-12-UnneededSelect2.ll new file mode 100644 index 000000000..59e9fda41 --- /dev/null +++ b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/2008-07-12-UnneededSelect2.ll @@ -0,0 +1,30 @@ +; RUN: opt < %s -analyze -scalar-evolution -disable-output |& not grep smax +; PR2070 + +define i32 @a(i32 %x) nounwind { +entry: + icmp sgt i32 %x, 1 ; :0 [#uses=1] + br i1 %0, label %bb.nph, label %bb2 + +bb.nph: ; preds = %entry + br label %bb + +bb: ; preds = %bb1, %bb.nph + %z.02 = phi i32 [ %1, %bb1 ], [ 1, %bb.nph ] ; [#uses=1] + %i.01 = phi i32 [ %2, %bb1 ], [ 1, %bb.nph ] ; [#uses=2] + mul i32 %z.02, %i.01 ; :1 [#uses=2] + add i32 %i.01, 1 ; :2 [#uses=2] + br label %bb1 + +bb1: ; preds = %bb + icmp slt i32 %2, %x ; :3 [#uses=1] + br i1 %3, label %bb, label %bb1.bb2_crit_edge + +bb1.bb2_crit_edge: ; preds = %bb1 + %.lcssa = phi i32 [ %1, %bb1 ] ; [#uses=1] + br label %bb2 + +bb2: ; preds = %bb1.bb2_crit_edge, %entry + %z.0.lcssa = phi i32 [ %.lcssa, %bb1.bb2_crit_edge ], [ 1, %entry ] ; [#uses=1] + ret i32 %z.0.lcssa +} diff --git a/libclamav/c++/llvm/test/Analysis/ScalarEvolution/2008-07-19-InfiniteLoop.ll b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/2008-07-19-InfiniteLoop.ll new file mode 100644 index 000000000..989ac5122 --- /dev/null +++ b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/2008-07-19-InfiniteLoop.ll @@ -0,0 +1,15 @@ +; RUN: opt < %s -analyze -scalar-evolution -disable-output \ +; RUN: -scalar-evolution-max-iterations=0 | grep Unpredictable +; PR2088 + +define void @fun() { +entry: + br label %loop +loop: + %i = phi i8 [ 0, %entry ], [ %i.next, %loop ] + %i.next = add i8 %i, 4 + %cond = icmp ne i8 %i.next, 6 + br i1 %cond, label %loop, label %exit +exit: + ret void +} diff --git a/libclamav/c++/llvm/test/Analysis/ScalarEvolution/2008-07-19-WrappingIV.ll b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/2008-07-19-WrappingIV.ll new file mode 100644 index 000000000..803c7d110 --- /dev/null +++ b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/2008-07-19-WrappingIV.ll @@ -0,0 +1,15 @@ +; RUN: opt < %s -analyze -scalar-evolution -disable-output \ +; RUN: -scalar-evolution-max-iterations=0 | grep {backedge-taken count is 113} +; PR2088 + +define void @fun() { +entry: + br label %loop +loop: + %i = phi i8 [ 0, %entry ], [ %i.next, %loop ] + %i.next = add i8 %i, 18 + %cond = icmp ne i8 %i.next, 4 + br i1 %cond, label %loop, label %exit +exit: + ret void +} diff --git a/libclamav/c++/llvm/test/Analysis/ScalarEvolution/2008-07-29-SGTTripCount.ll b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/2008-07-29-SGTTripCount.ll new file mode 100644 index 000000000..37b5b94b8 --- /dev/null +++ b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/2008-07-29-SGTTripCount.ll @@ -0,0 +1,28 @@ +; RUN: opt < %s -analyze -scalar-evolution -disable-output \ +; RUN: -scalar-evolution-max-iterations=0 | FileCheck %s +; PR2607 + +define i32 @_Z1aj(i32 %j) nounwind { +entry: + icmp sgt i32 0, %j ; :0 [#uses=1] + br i1 %0, label %bb.preheader, label %return + +bb.preheader: ; preds = %entry + br label %bb + +bb: ; preds = %bb, %bb.preheader + %i.01 = phi i32 [ %1, %bb ], [ 0, %bb.preheader ] ; [#uses=1] + add i32 %i.01, -1 ; :1 [#uses=3] + icmp sgt i32 %1, %j ; :2 [#uses=1] + br i1 %2, label %bb, label %return.loopexit + +return.loopexit: ; preds = %bb + br label %return + +return: ; preds = %return.loopexit, %entry + %i.0.lcssa = phi i32 [ 0, %entry ], [ %1, %return.loopexit ] ; [#uses=1] + ret i32 %i.0.lcssa +} + +; CHECK: backedge-taken count is (-1 + (-1 * %j)) + diff --git a/libclamav/c++/llvm/test/Analysis/ScalarEvolution/2008-07-29-SMinExpr.ll b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/2008-07-29-SMinExpr.ll new file mode 100644 index 000000000..d54b3b4e9 --- /dev/null +++ b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/2008-07-29-SMinExpr.ll @@ -0,0 +1,26 @@ +; RUN: opt < %s -analyze -scalar-evolution -disable-output \ +; RUN: -scalar-evolution-max-iterations=0 | FileCheck %s +; PR2607 + +define i32 @b(i32 %x, i32 %y) nounwind { +entry: + %cmp2 = icmp slt i32 %y, %x + %cond3 = select i1 %cmp2, i32 %y, i32 %x + %cmp54 = icmp slt i32 %cond3, -2147483632 + br i1 %cmp54, label %forinc, label %afterfor + +forinc: ; preds = %forinc, %entry + %j.01 = phi i32 [ %dec, %forinc ], [ -2147483632, %entry ] + %dec = add i32 %j.01, -1 + %cmp = icmp slt i32 %y, %x + %cond = select i1 %cmp, i32 %y, i32 %x + %cmp5 = icmp sgt i32 %dec, %cond + br i1 %cmp5, label %forinc, label %afterfor + +afterfor: ; preds = %forinc, %entry + %j.0.lcssa = phi i32 [ -2147483632, %entry ], [ %dec, %forinc ] + ret i32 %j.0.lcssa +} + +; CHECK: backedge-taken count is (-2147483632 + ((-1 + (-1 * %x)) smax (-1 + (-1 * %y)))) + diff --git a/libclamav/c++/llvm/test/Analysis/ScalarEvolution/2008-08-04-IVOverflow.ll b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/2008-08-04-IVOverflow.ll new file mode 100644 index 000000000..06200ae06 --- /dev/null +++ b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/2008-08-04-IVOverflow.ll @@ -0,0 +1,27 @@ +; RUN: opt < %s -analyze -scalar-evolution -disable-output \ +; RUN: -scalar-evolution-max-iterations=0 | FileCheck %s +; PR2621 + +define i32 @a() nounwind { +entry: + br label %bb1 + +bb: + trunc i32 %i.0 to i16 + add i16 %0, %x16.0 + add i32 %i.0, 1 + br label %bb1 + +bb1: + %i.0 = phi i32 [ 0, %entry ], [ %2, %bb ] + %x16.0 = phi i16 [ 0, %entry ], [ %1, %bb ] + icmp ult i32 %i.0, 888888 + br i1 %3, label %bb, label %bb2 + +bb2: + zext i16 %x16.0 to i32 + ret i32 %4 +} + +; CHECK: Exits: 20028 + diff --git a/libclamav/c++/llvm/test/Analysis/ScalarEvolution/2008-08-04-LongAddRec.ll b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/2008-08-04-LongAddRec.ll new file mode 100644 index 000000000..f3c703afa --- /dev/null +++ b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/2008-08-04-LongAddRec.ll @@ -0,0 +1,58 @@ +; RUN: opt < %s -analyze -scalar-evolution -disable-output \ +; RUN: -scalar-evolution-max-iterations=0 | FileCheck %s +; PR2621 + +define i32 @a() nounwind { +entry: + br label %bb1 + +bb: ; preds = %bb1 + add i16 %x17.0, 1 ; :0 [#uses=2] + add i16 %0, %x16.0 ; :1 [#uses=2] + add i16 %1, %x15.0 ; :2 [#uses=2] + add i16 %2, %x14.0 ; :3 [#uses=2] + add i16 %3, %x13.0 ; :4 [#uses=2] + add i16 %4, %x12.0 ; :5 [#uses=2] + add i16 %5, %x11.0 ; :6 [#uses=2] + add i16 %6, %x10.0 ; :7 [#uses=2] + add i16 %7, %x9.0 ; :8 [#uses=2] + add i16 %8, %x8.0 ; :9 [#uses=2] + add i16 %9, %x7.0 ; :10 [#uses=2] + add i16 %10, %x6.0 ; :11 [#uses=2] + add i16 %11, %x5.0 ; :12 [#uses=2] + add i16 %12, %x4.0 ; :13 [#uses=2] + add i16 %13, %x3.0 ; :14 [#uses=2] + add i16 %14, %x2.0 ; :15 [#uses=2] + add i16 %15, %x1.0 ; :16 [#uses=1] + add i32 %i.0, 1 ; :17 [#uses=1] + br label %bb1 + +bb1: ; preds = %bb, %entry + %x2.0 = phi i16 [ 0, %entry ], [ %15, %bb ] ; [#uses=1] + %x3.0 = phi i16 [ 0, %entry ], [ %14, %bb ] ; [#uses=1] + %x4.0 = phi i16 [ 0, %entry ], [ %13, %bb ] ; [#uses=1] + %x5.0 = phi i16 [ 0, %entry ], [ %12, %bb ] ; [#uses=1] + %x6.0 = phi i16 [ 0, %entry ], [ %11, %bb ] ; [#uses=1] + %x7.0 = phi i16 [ 0, %entry ], [ %10, %bb ] ; [#uses=1] + %x8.0 = phi i16 [ 0, %entry ], [ %9, %bb ] ; [#uses=1] + %x9.0 = phi i16 [ 0, %entry ], [ %8, %bb ] ; [#uses=1] + %x10.0 = phi i16 [ 0, %entry ], [ %7, %bb ] ; [#uses=1] + %x11.0 = phi i16 [ 0, %entry ], [ %6, %bb ] ; [#uses=1] + %x12.0 = phi i16 [ 0, %entry ], [ %5, %bb ] ; [#uses=1] + %x13.0 = phi i16 [ 0, %entry ], [ %4, %bb ] ; [#uses=1] + %x14.0 = phi i16 [ 0, %entry ], [ %3, %bb ] ; [#uses=1] + %x15.0 = phi i16 [ 0, %entry ], [ %2, %bb ] ; [#uses=1] + %x16.0 = phi i16 [ 0, %entry ], [ %1, %bb ] ; [#uses=1] + %x17.0 = phi i16 [ 0, %entry ], [ %0, %bb ] ; [#uses=1] + %i.0 = phi i32 [ 0, %entry ], [ %17, %bb ] ; [#uses=2] + %x1.0 = phi i16 [ 0, %entry ], [ %16, %bb ] ; [#uses=2] + icmp ult i32 %i.0, 8888 ; :18 [#uses=1] + br i1 %18, label %bb, label %bb2 + +bb2: ; preds = %bb1 + zext i16 %x1.0 to i32 ; :19 [#uses=1] + ret i32 %19 +} + +; CHECK: Exits: -19168 + diff --git a/libclamav/c++/llvm/test/Analysis/ScalarEvolution/2008-11-02-QuadraticCrash.ll b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/2008-11-02-QuadraticCrash.ll new file mode 100644 index 000000000..9daff991a --- /dev/null +++ b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/2008-11-02-QuadraticCrash.ll @@ -0,0 +1,21 @@ +; RUN: opt < %s -analyze -scalar-evolution -disable-output +; PR1827 + +declare void @use(i32) + +define void @foo() { +entry: + br label %loop_1 + +loop_1: ; preds = %loop_1, %entry + %a = phi i32 [ 2, %entry ], [ %b, %loop_1 ] ; [#uses=2] + %c = phi i32 [ 5, %entry ], [ %d, %loop_1 ] ; [#uses=1] + %b = add i32 %a, 1 ; [#uses=1] + %d = add i32 %c, %a ; [#uses=3] + %A = icmp ult i32 %d, 50 ; [#uses=1] + br i1 %A, label %loop_1, label %endloop + +endloop: ; preds = %loop_1 + call void @use(i32 %d) + ret void +} diff --git a/libclamav/c++/llvm/test/Analysis/ScalarEvolution/2008-11-15-CubicOOM.ll b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/2008-11-15-CubicOOM.ll new file mode 100644 index 000000000..5a2c36659 --- /dev/null +++ b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/2008-11-15-CubicOOM.ll @@ -0,0 +1,19 @@ +; RUN: opt < %s -analyze -scalar-evolution -disable-output +; PR2602 + +define i32 @a() nounwind { +entry: + br label %bb + +bb: ; preds = %bb, %entry + %w.0 = phi i32 [ 0, %entry ], [ %tmp, %bb ] ; [#uses=2] + %e.0 = phi i32 [ 0, %entry ], [ %e.1, %bb ] ; [#uses=2] + %w.1 = add i32 0, %w.0 ; :0 [#uses=1] + %tmp = add i32 %e.0, %w.0 ; :1 [#uses=1] + %e.1 = add i32 %e.0, 1 ; :2 [#uses=1] + %cond = icmp eq i32 %w.1, -1 ; :3 [#uses=1] + br i1 %cond, label %return, label %bb + +return: ; preds = %bb + ret i32 undef +} diff --git a/libclamav/c++/llvm/test/Analysis/ScalarEvolution/2008-11-18-LessThanOrEqual.ll b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/2008-11-18-LessThanOrEqual.ll new file mode 100644 index 000000000..daeb26a20 --- /dev/null +++ b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/2008-11-18-LessThanOrEqual.ll @@ -0,0 +1,32 @@ +; RUN: opt < %s -analyze -scalar-evolution -disable-output |& \ +; RUN: grep {Loop bb: backedge-taken count is (7 + (-1 \\* %argc))} +; XFAIL: * + +define i32 @main(i32 %argc, i8** %argv) nounwind { +entry: + %0 = icmp ugt i32 %argc, 7 ; [#uses=1] + br i1 %0, label %bb2, label %bb.nph + +bb.nph: ; preds = %entry + br label %bb + +bb: ; preds = %bb.nph, %bb1 + %indvar = phi i32 [ 0, %bb.nph ], [ %indvar.next, %bb1 ] ; [#uses=2] + %argc_addr.04 = add i32 %indvar, %argc ; [#uses=1] + tail call void (...)* @Test() nounwind + %1 = add i32 %argc_addr.04, 1 ; [#uses=1] + br label %bb1 + +bb1: ; preds = %bb + %phitmp = icmp ugt i32 %1, 7 ; [#uses=1] + %indvar.next = add i32 %indvar, 1 ; [#uses=1] + br i1 %phitmp, label %bb1.bb2_crit_edge, label %bb + +bb1.bb2_crit_edge: ; preds = %bb1 + br label %bb2 + +bb2: ; preds = %bb1.bb2_crit_edge, %entry + ret i32 0 +} + +declare void @Test(...) diff --git a/libclamav/c++/llvm/test/Analysis/ScalarEvolution/2008-11-18-Stride1.ll b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/2008-11-18-Stride1.ll new file mode 100644 index 000000000..9dda78b21 --- /dev/null +++ b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/2008-11-18-Stride1.ll @@ -0,0 +1,35 @@ +; RUN: opt < %s -analyze -scalar-evolution -disable-output \ +; RUN: | grep {Loop bb: Unpredictable backedge-taken count\\.} + +; ScalarEvolution can't compute a trip count because it doesn't know if +; dividing by the stride will have a remainder. This could theoretically +; be teaching it how to use a more elaborate trip count computation. + +define i32 @f(i32 %x) nounwind readnone { +entry: + %0 = icmp ugt i32 %x, 4 ; [#uses=1] + br i1 %0, label %bb.nph, label %bb2 + +bb.nph: ; preds = %entry + br label %bb + +bb: ; preds = %bb.nph, %bb1 + %indvar = phi i32 [ 0, %bb.nph ], [ %indvar.next, %bb1 ] ; [#uses=2] + %tmp = mul i32 %indvar, -3 ; [#uses=1] + %x_addr.04 = add i32 %tmp, %x ; [#uses=1] + %1 = add i32 %x_addr.04, -3 ; [#uses=2] + br label %bb1 + +bb1: ; preds = %bb + %2 = icmp ugt i32 %1, 4 ; [#uses=1] + %indvar.next = add i32 %indvar, 1 ; [#uses=1] + br i1 %2, label %bb, label %bb1.bb2_crit_edge + +bb1.bb2_crit_edge: ; preds = %bb1 + %.lcssa = phi i32 [ %1, %bb1 ] ; [#uses=1] + br label %bb2 + +bb2: ; preds = %bb1.bb2_crit_edge, %entry + %x_addr.0.lcssa = phi i32 [ %.lcssa, %bb1.bb2_crit_edge ], [ %x, %entry ] ; [#uses=1] + ret i32 %x_addr.0.lcssa +} diff --git a/libclamav/c++/llvm/test/Analysis/ScalarEvolution/2008-11-18-Stride2.ll b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/2008-11-18-Stride2.ll new file mode 100644 index 000000000..bcbe92f50 --- /dev/null +++ b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/2008-11-18-Stride2.ll @@ -0,0 +1,31 @@ +; RUN: opt < %s -analyze -scalar-evolution -disable-output |& grep {/u 3} +; XFAIL: * + +define i32 @f(i32 %x) nounwind readnone { +entry: + %0 = icmp ugt i32 %x, 999 ; [#uses=1] + br i1 %0, label %bb2, label %bb.nph + +bb.nph: ; preds = %entry + br label %bb + +bb: ; preds = %bb.nph, %bb1 + %indvar = phi i32 [ 0, %bb.nph ], [ %indvar.next, %bb1 ] ; [#uses=2] + %tmp = mul i32 %indvar, 3 ; [#uses=1] + %x_addr.04 = add i32 %tmp, %x ; [#uses=1] + %1 = add i32 %x_addr.04, 3 ; [#uses=2] + br label %bb1 + +bb1: ; preds = %bb + %2 = icmp ugt i32 %1, 999 ; [#uses=1] + %indvar.next = add i32 %indvar, 1 ; [#uses=1] + br i1 %2, label %bb1.bb2_crit_edge, label %bb + +bb1.bb2_crit_edge: ; preds = %bb1 + %.lcssa = phi i32 [ %1, %bb1 ] ; [#uses=1] + br label %bb2 + +bb2: ; preds = %bb1.bb2_crit_edge, %entry + %x_addr.0.lcssa = phi i32 [ %.lcssa, %bb1.bb2_crit_edge ], [ %x, %entry ] ; [#uses=1] + ret i32 %x_addr.0.lcssa +} diff --git a/libclamav/c++/llvm/test/Analysis/ScalarEvolution/2008-12-08-FiniteSGE.ll b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/2008-12-08-FiniteSGE.ll new file mode 100644 index 000000000..2ee107a4a --- /dev/null +++ b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/2008-12-08-FiniteSGE.ll @@ -0,0 +1,25 @@ +; RUN: opt < %s -analyze -scalar-evolution -disable-output | grep {backedge-taken count is 255} +; XFAIL: * + +define i32 @foo(i32 %x, i32 %y, i32* %lam, i32* %alp) nounwind { +bb1.thread: + br label %bb1 + +bb1: ; preds = %bb1, %bb1.thread + %indvar = phi i32 [ 0, %bb1.thread ], [ %indvar.next, %bb1 ] ; [#uses=4] + %i.0.reg2mem.0 = sub i32 255, %indvar ; [#uses=2] + %0 = getelementptr i32* %alp, i32 %i.0.reg2mem.0 ; [#uses=1] + %1 = load i32* %0, align 4 ; [#uses=1] + %2 = getelementptr i32* %lam, i32 %i.0.reg2mem.0 ; [#uses=1] + store i32 %1, i32* %2, align 4 + %3 = sub i32 254, %indvar ; [#uses=1] + %4 = icmp slt i32 %3, 0 ; [#uses=1] + %indvar.next = add i32 %indvar, 1 ; [#uses=1] + br i1 %4, label %bb2, label %bb1 + +bb2: ; preds = %bb1 + %tmp10 = mul i32 %indvar, %x ; [#uses=1] + %z.0.reg2mem.0 = add i32 %tmp10, %y ; [#uses=1] + %5 = add i32 %z.0.reg2mem.0, %x ; [#uses=1] + ret i32 %5 +} diff --git a/libclamav/c++/llvm/test/Analysis/ScalarEvolution/2008-12-11-SMaxOverflow.ll b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/2008-12-11-SMaxOverflow.ll new file mode 100644 index 000000000..0cfd84c99 --- /dev/null +++ b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/2008-12-11-SMaxOverflow.ll @@ -0,0 +1,28 @@ +; RUN: opt < %s -analyze -scalar-evolution -disable-output | grep {0 smax} +; XFAIL: * + +define i32 @f(i32 %c.idx.val) { + +bb2: + %k.018 = add i32 %c.idx.val, -1 ; [#uses=2] + %a14 = icmp slt i32 %k.018, 0 ; [#uses=1] + br i1 %a14, label %bb19, label %bb16.preheader + +bb16.preheader: + %k.019 = phi i32 [ %k.0, %bb18 ], [ %k.018, %bb2 ] ; [#uses=5] + %x = phi i32 [ 0, %bb2 ], [ %x.1, %bb18] + br label %bb18 + +bb18: ; preds = %bb18.loopexit + %x.1 = add i32 %x, 1 + %k.0 = add i32 %k.019, -1 ; [#uses=2] + %a107 = icmp slt i32 %k.0, 0 ; [#uses=1] + br i1 %a107, label %bb18.bb19_crit_edge, label %bb16.preheader + +bb18.bb19_crit_edge: + ret i32 %x + +bb19: + ret i32 0 + +} diff --git a/libclamav/c++/llvm/test/Analysis/ScalarEvolution/2008-12-14-StrideAndSigned.ll b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/2008-12-14-StrideAndSigned.ll new file mode 100644 index 000000000..4ec358c8a --- /dev/null +++ b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/2008-12-14-StrideAndSigned.ll @@ -0,0 +1,22 @@ +; RUN: opt < %s -analyze -scalar-evolution -disable-output |& \ +; RUN: grep {(((-1 \\* %i0) + (100005 smax %i0)) /u 5)} +; XFAIL: * + +define i32 @foo0(i32 %i0) nounwind { +entry: + br label %bb1 + +bb: ; preds = %bb1 + %0 = add i32 %j.0, 1 ; [#uses=1] + %1 = add i32 %i.0, 5 ; [#uses=1] + br label %bb1 + +bb1: ; preds = %bb, %entry + %j.0 = phi i32 [ 0, %entry ], [ %0, %bb ] ; [#uses=2] + %i.0 = phi i32 [ %i0, %entry ], [ %1, %bb ] ; [#uses=2] + %2 = icmp sgt i32 %i.0, 100000 ; [#uses=1] + br i1 %2, label %return, label %bb + +return: ; preds = %bb1 + ret i32 %j.0 +} diff --git a/libclamav/c++/llvm/test/Analysis/ScalarEvolution/2008-12-15-DontUseSDiv.ll b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/2008-12-15-DontUseSDiv.ll new file mode 100644 index 000000000..1fe10689f --- /dev/null +++ b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/2008-12-15-DontUseSDiv.ll @@ -0,0 +1,21 @@ +; RUN: opt < %s -analyze -scalar-evolution -disable-output |& grep {/u 5} +; XFAIL: * + +define i8 @foo0(i8 %i0) nounwind { +entry: + br label %bb1 + +bb: ; preds = %bb1 + %0 = add i8 %j.0, 1 ; [#uses=1] + %1 = add i8 %i.0, 5 ; [#uses=1] + br label %bb1 + +bb1: ; preds = %bb, %entry + %j.0 = phi i8 [ 0, %entry ], [ %0, %bb ] ; [#uses=2] + %i.0 = phi i8 [ %i0, %entry ], [ %1, %bb ] ; [#uses=2] + %2 = icmp sgt i8 %i.0, 100 ; [#uses=1] + br i1 %2, label %return, label %bb + +return: ; preds = %bb1 + ret i8 %j.0 +} diff --git a/libclamav/c++/llvm/test/Analysis/ScalarEvolution/2009-01-02-SignedNegativeStride.ll b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/2009-01-02-SignedNegativeStride.ll new file mode 100644 index 000000000..9d13695c3 --- /dev/null +++ b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/2009-01-02-SignedNegativeStride.ll @@ -0,0 +1,40 @@ +; RUN: opt < %s -analyze -scalar-evolution -disable-output | not grep {/u -1} +; PR3275 + +@g_16 = external global i16 ; [#uses=3] +@.str = external constant [4 x i8] ; <[4 x i8]*> [#uses=0] + +define void @func_15() nounwind { +entry: + %0 = load i16* @g_16, align 2 ; [#uses=1] + %1 = icmp sgt i16 %0, 0 ; [#uses=1] + br i1 %1, label %bb2, label %bb.nph + +bb.nph: ; preds = %entry + %g_16.promoted = load i16* @g_16 ; [#uses=1] + br label %bb + +bb: ; preds = %bb1, %bb.nph + %g_16.tmp.0 = phi i16 [ %g_16.promoted, %bb.nph ], [ %2, %bb1 ] ; [#uses=1] + %2 = add i16 %g_16.tmp.0, -1 ; [#uses=3] + br label %bb1 + +bb1: ; preds = %bb + %3 = icmp sgt i16 %2, 0 ; [#uses=1] + br i1 %3, label %bb1.bb2_crit_edge, label %bb + +bb1.bb2_crit_edge: ; preds = %bb1 + store i16 %2, i16* @g_16 + br label %bb2 + +bb2: ; preds = %bb1.bb2_crit_edge, %entry + br label %return + +return: ; preds = %bb2 + ret void +} + +declare i32 @main() nounwind + +declare i32 @printf(i8*, ...) nounwind + diff --git a/libclamav/c++/llvm/test/Analysis/ScalarEvolution/2009-04-22-TruncCast.ll b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/2009-04-22-TruncCast.ll new file mode 100644 index 000000000..78a7fd016 --- /dev/null +++ b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/2009-04-22-TruncCast.ll @@ -0,0 +1,37 @@ +; RUN: opt < %s -analyze -scalar-evolution -disable-output | grep {(trunc i} | not grep ext + +define i16 @test1(i8 %x) { + %A = sext i8 %x to i32 + %B = trunc i32 %A to i16 + ret i16 %B +} + +define i8 @test2(i16 %x) { + %A = sext i16 %x to i32 + %B = trunc i32 %A to i8 + ret i8 %B +} + +define i16 @test3(i16 %x) { + %A = sext i16 %x to i32 + %B = trunc i32 %A to i16 + ret i16 %B +} + +define i16 @test4(i8 %x) { + %A = zext i8 %x to i32 + %B = trunc i32 %A to i16 + ret i16 %B +} + +define i8 @test5(i16 %x) { + %A = zext i16 %x to i32 + %B = trunc i32 %A to i8 + ret i8 %B +} + +define i16 @test6(i16 %x) { + %A = zext i16 %x to i32 + %B = trunc i32 %A to i16 + ret i16 %B +} diff --git a/libclamav/c++/llvm/test/Analysis/ScalarEvolution/2009-05-09-PointerEdgeCount.ll b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/2009-05-09-PointerEdgeCount.ll new file mode 100644 index 000000000..e81530e1b --- /dev/null +++ b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/2009-05-09-PointerEdgeCount.ll @@ -0,0 +1,28 @@ +; RUN: opt < %s -analyze -scalar-evolution -disable-output | grep {count is 2} +; PR3171 +target datalayout = "E-p:64:64:64-a0:0:8-f32:32:32-f64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-v64:64:64-v128:128:128" + + %struct.Foo = type { i32 } + %struct.NonPod = type { [2 x %struct.Foo] } + +define void @_Z3foov() nounwind { +entry: + %x = alloca %struct.NonPod, align 8 ; <%struct.NonPod*> [#uses=2] + %0 = getelementptr %struct.NonPod* %x, i32 0, i32 0 ; <[2 x %struct.Foo]*> [#uses=1] + %1 = getelementptr [2 x %struct.Foo]* %0, i32 1, i32 0 ; <%struct.Foo*> [#uses=1] + br label %bb1.i + +bb1.i: ; preds = %bb2.i, %entry + %.0.i = phi %struct.Foo* [ %1, %entry ], [ %4, %bb2.i ] ; <%struct.Foo*> [#uses=2] + %2 = getelementptr %struct.NonPod* %x, i32 0, i32 0, i32 0 ; <%struct.Foo*> [#uses=1] + %3 = icmp eq %struct.Foo* %.0.i, %2 ; [#uses=1] + br i1 %3, label %_ZN6NonPodD1Ev.exit, label %bb2.i + +bb2.i: ; preds = %bb1.i + %4 = getelementptr %struct.Foo* %.0.i, i32 -1 ; <%struct.Foo*> [#uses=1] + br label %bb1.i + +_ZN6NonPodD1Ev.exit: ; preds = %bb1.i + ret void +} + diff --git a/libclamav/c++/llvm/test/Analysis/ScalarEvolution/2009-07-04-GroupConstantsWidthMismatch.ll b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/2009-07-04-GroupConstantsWidthMismatch.ll new file mode 100644 index 000000000..a4358aa63 --- /dev/null +++ b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/2009-07-04-GroupConstantsWidthMismatch.ll @@ -0,0 +1,16 @@ +; RUN: opt < %s -analyze -scalar-evolution +; PR4501 + +define void @test() { +entry: + %0 = load i16* undef, align 1 + %1 = lshr i16 %0, 8 + %2 = and i16 %1, 3 + %3 = zext i16 %2 to i32 + %4 = load i8* undef, align 1 + %5 = lshr i8 %4, 4 + %6 = and i8 %5, 1 + %7 = zext i8 %6 to i32 + %t1 = add i32 %3, %7 + ret void +} diff --git a/libclamav/c++/llvm/test/Analysis/ScalarEvolution/SolveQuadraticEquation.ll b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/SolveQuadraticEquation.ll new file mode 100644 index 000000000..fcc6fc329 --- /dev/null +++ b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/SolveQuadraticEquation.ll @@ -0,0 +1,32 @@ +; RUN: opt < %s -analyze -scalar-evolution -disable-output \ +; RUN: -scalar-evolution-max-iterations=0 | grep {backedge-taken count is 100} +; PR1101 + +@A = weak global [1000 x i32] zeroinitializer, align 32 + + +define void @test(i32 %N) { +entry: + "alloca point" = bitcast i32 0 to i32 ; [#uses=0] + br label %bb3 + +bb: ; preds = %bb3 + %tmp = getelementptr [1000 x i32]* @A, i32 0, i32 %i.0 ; [#uses=1] + store i32 123, i32* %tmp + %tmp2 = add i32 %i.0, 1 ; [#uses=1] + br label %bb3 + +bb3: ; preds = %bb, %entry + %i.0 = phi i32 [ 2, %entry ], [ %tmp2, %bb ] ; [#uses=3] + %SQ = mul i32 %i.0, %i.0 + %tmp4 = mul i32 %i.0, 2 + %tmp5 = sub i32 %SQ, %tmp4 + %tmp3 = icmp sle i32 %tmp5, 9999 ; [#uses=1] + br i1 %tmp3, label %bb, label %bb5 + +bb5: ; preds = %bb3 + br label %return + +return: ; preds = %bb5 + ret void +} diff --git a/libclamav/c++/llvm/test/Analysis/ScalarEvolution/and-xor.ll b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/and-xor.ll new file mode 100644 index 000000000..90d947f15 --- /dev/null +++ b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/and-xor.ll @@ -0,0 +1,8 @@ +; RUN: opt < %s -scalar-evolution -analyze -disable-output \ +; RUN: | grep {\\--> (zext} | count 2 + +define i32 @foo(i32 %x) { + %n = and i32 %x, 255 + %y = xor i32 %n, 255 + ret i32 %y +} diff --git a/libclamav/c++/llvm/test/Analysis/ScalarEvolution/avoid-infinite-recursion-0.ll b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/avoid-infinite-recursion-0.ll new file mode 100644 index 000000000..f638eb340 --- /dev/null +++ b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/avoid-infinite-recursion-0.ll @@ -0,0 +1,30 @@ +; RUN: opt < %s -analyze -scalar-evolution -disable-output +; PR4537 + +; ModuleID = 'b.bc' +target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128" +target triple = "x86_64-unknown-linux-gnu" + +define i32 @test() { +entry: + %0 = load i32** undef, align 8 ; [#uses=1] + %1 = ptrtoint i32* %0 to i64 ; [#uses=1] + %2 = sub i64 undef, %1 ; [#uses=1] + %3 = lshr i64 %2, 3 ; [#uses=1] + %4 = trunc i64 %3 to i32 ; [#uses=2] + br i1 undef, label %bb10, label %bb4.i + +bb4.i: ; preds = %bb4.i, %entry + %i.0.i6 = phi i32 [ %8, %bb4.i ], [ 0, %entry ] ; [#uses=2] + %5 = sub i32 %4, %i.0.i6 ; [#uses=1] + %6 = sext i32 %5 to i64 ; [#uses=1] + %7 = udiv i64 undef, %6 ; [#uses=1] + %8 = add i32 %i.0.i6, 1 ; [#uses=2] + %phitmp = icmp eq i64 %7, 0 ; [#uses=1] + %.not.i = icmp sge i32 %8, %4 ; [#uses=1] + %or.cond.i = or i1 %phitmp, %.not.i ; [#uses=1] + br i1 %or.cond.i, label %bb10, label %bb4.i + +bb10: ; preds = %bb4.i, %entry + unreachable +} diff --git a/libclamav/c++/llvm/test/Analysis/ScalarEvolution/avoid-infinite-recursion-1.ll b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/avoid-infinite-recursion-1.ll new file mode 100644 index 000000000..31b95e147 --- /dev/null +++ b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/avoid-infinite-recursion-1.ll @@ -0,0 +1,354 @@ +; RUN: opt < %s -iv-users +; PR4538 + +; ModuleID = 'bugpoint-reduced-simplified.bc' +target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128" +target triple = "x86_64-unknown-freebsd8.0" +module asm ".ident\09\22$FreeBSD: head/sys/kern/vfs_subr.c 195285 2009-07-02 14:19:33Z jamie $\22" +module asm ".section set_pcpu, \22aw\22, @progbits" +module asm ".previous" + type <{ [40 x i8] }> ; type %0 + type <{ %struct.vm_object*, %struct.vm_object** }> ; type %1 + type <{ %struct.vm_object* }> ; type %2 + type <{ %struct.vm_page*, %struct.vm_page** }> ; type %3 + type <{ %struct.pv_entry*, %struct.pv_entry** }> ; type %4 + type <{ %struct.vm_reserv* }> ; type %5 + type <{ %struct.bufobj*, %struct.bufobj** }> ; type %6 + type <{ %struct.proc*, %struct.proc** }> ; type %7 + type <{ %struct.thread*, %struct.thread** }> ; type %8 + type <{ %struct.prison*, %struct.prison** }> ; type %9 + type <{ %struct.prison* }> ; type %10 + type <{ %struct.task* }> ; type %11 + type <{ %struct.osd*, %struct.osd** }> ; type %12 + type <{ %struct.proc* }> ; type %13 + type <{ %struct.ksiginfo*, %struct.ksiginfo** }> ; type %14 + type <{ %struct.pv_chunk*, %struct.pv_chunk** }> ; type %15 + type <{ %struct.pgrp*, %struct.pgrp** }> ; type %16 + type <{ %struct.knote*, %struct.knote** }> ; type %17 + type <{ %struct.ktr_request*, %struct.ktr_request** }> ; type %18 + type <{ %struct.mqueue_notifier* }> ; type %19 + type <{ %struct.turnstile* }> ; type %20 + type <{ %struct.namecache* }> ; type %21 + type <{ %struct.namecache*, %struct.namecache** }> ; type %22 + type <{ %struct.lockf*, %struct.lockf** }> ; type %23 + type <{ %struct.lockf_entry*, %struct.lockf_entry** }> ; type %24 + type <{ %struct.lockf_edge*, %struct.lockf_edge** }> ; type %25 + %struct.__siginfo = type <{ i32, i32, i32, i32, i32, i32, i8*, %union.sigval, %0 }> + %struct.__sigset = type <{ [4 x i32] }> + %struct.acl = type <{ i32, i32, [4 x i32], [254 x %struct.acl_entry] }> + %struct.acl_entry = type <{ i32, i32, i32, i16, i16 }> + %struct.au_mask = type <{ i32, i32 }> + %struct.au_tid_addr = type <{ i32, i32, [4 x i32] }> + %struct.auditinfo_addr = type <{ i32, %struct.au_mask, %struct.au_tid_addr, i32, i64 }> + %struct.bintime = type <{ i64, i64 }> + %struct.buf = type <{ %struct.bufobj*, i64, i8*, i8*, i32, i8, i8, i8, i8, i64, i64, void (%struct.buf*)*, i64, i64, %struct.buflists, %struct.buf*, %struct.buf*, i32, i8, i8, i8, i8, %struct.buflists, i16, i8, i8, i32, i8, i8, i8, i8, i8, i8, i8, i8, %struct.lock, i64, i64, i8*, i32, i8, i8, i8, i8, i64, %struct.vnode*, i32, i32, %struct.ucred*, %struct.ucred*, i8*, %union.pager_info, i8, i8, i8, i8, %union.anon, [32 x %struct.vm_page*], i32, i8, i8, i8, i8, %struct.workhead, i8*, i8*, i8*, i32, i8, i8, i8, i8 }> + %struct.buf_ops = type <{ i8*, i32 (%struct.buf*)*, void (%struct.bufobj*, %struct.buf*)*, i32 (%struct.bufobj*, i32)*, void (%struct.bufobj*, %struct.buf*)* }> + %struct.buflists = type <{ %struct.buf*, %struct.buf** }> + %struct.bufobj = type <{ %struct.mtx, %struct.bufv, %struct.bufv, i64, i32, i8, i8, i8, i8, %struct.buf_ops*, i32, i8, i8, i8, i8, %struct.vm_object*, %6, i8*, %struct.vnode* }> + %struct.bufv = type <{ %struct.buflists, %struct.buf*, i32, i8, i8, i8, i8 }> + %struct.callout = type <{ %union.anon, i32, i8, i8, i8, i8, i8*, void (i8*)*, %struct.lock_object*, i32, i32 }> + %struct.cdev_privdata = type opaque + %struct.cluster_save = type <{ i64, i64, i8*, i32, i8, i8, i8, i8, %struct.buf** }> + %struct.componentname = type <{ i64, i64, %struct.thread*, %struct.ucred*, i32, i8, i8, i8, i8, i8*, i8*, i64, i64 }> + %struct.cpuset = type opaque + %struct.cv = type <{ i8*, i32, i8, i8, i8, i8 }> + %struct.fid = type <{ i16, i16, [16 x i8] }> + %struct.file = type <{ i8*, %struct.fileops*, %struct.ucred*, %struct.vnode*, i16, i16, i32, i32, i32, i64, %struct.cdev_privdata*, i64, i8* }> + %struct.filedesc = type opaque + %struct.filedesc_to_leader = type opaque + %struct.fileops = type <{ i32 (%struct.file*, %struct.uio*, %struct.ucred*, i32, %struct.thread*)*, i32 (%struct.file*, %struct.uio*, %struct.ucred*, i32, %struct.thread*)*, i32 (%struct.file*, i64, %struct.ucred*, %struct.thread*)*, i32 (%struct.file*, i64, i8*, %struct.ucred*, %struct.thread*)*, i32 (%struct.file*, i32, %struct.ucred*, %struct.thread*)*, i32 (%struct.file*, %struct.knote*)*, i32 (%struct.file*, %struct.stat*, %struct.ucred*, %struct.thread*)*, i32 (%struct.file*, %struct.thread*)*, i32, i8, i8, i8, i8 }> + %struct.filterops = type <{ i32, i8, i8, i8, i8, i32 (%struct.knote*)*, void (%struct.knote*)*, i32 (%struct.knote*, i64)* }> + %struct.flock = type <{ i64, i64, i32, i16, i16, i32, i8, i8, i8, i8 }> + %struct.freelst = type <{ %struct.vnode*, %struct.vnode** }> + %struct.fsid = type <{ [2 x i32] }> + %struct.in6_addr = type opaque + %struct.in_addr = type opaque + %struct.inode = type opaque + %struct.iovec = type <{ i8*, i64 }> + %struct.itimers = type opaque + %struct.itimerval = type <{ %struct.bintime, %struct.bintime }> + %struct.kaioinfo = type opaque + %struct.kaudit_record = type opaque + %struct.kdtrace_proc = type opaque + %struct.kdtrace_thread = type opaque + %struct.kevent = type <{ i64, i16, i16, i32, i64, i8* }> + %struct.klist = type <{ %struct.knote* }> + %struct.knlist = type <{ %struct.klist, void (i8*)*, void (i8*)*, void (i8*)*, void (i8*)*, i8* }> + %struct.knote = type <{ %struct.klist, %struct.klist, %struct.knlist*, %17, %struct.kqueue*, %struct.kevent, i32, i32, i64, %union.sigval, %struct.filterops*, i8* }> + %struct.kqueue = type opaque + %struct.ksiginfo = type <{ %14, %struct.__siginfo, i32, i8, i8, i8, i8, %struct.sigqueue* }> + %struct.ktr_request = type opaque + %struct.label = type opaque + %struct.lock = type <{ %struct.lock_object, i64, i32, i32 }> + %struct.lock_list_entry = type opaque + %struct.lock_object = type <{ i8*, i32, i32, %struct.witness* }> + %struct.lock_owner = type opaque + %struct.lock_profile_object = type opaque + %struct.lockf = type <{ %23, %struct.mtx, %struct.lockf_entry_list, %struct.lockf_entry_list, i32, i8, i8, i8, i8 }> + %struct.lockf_edge = type <{ %25, %25, %struct.lockf_entry*, %struct.lockf_entry* }> + %struct.lockf_edge_list = type <{ %struct.lockf_edge* }> + %struct.lockf_entry = type <{ i16, i16, i8, i8, i8, i8, i64, i64, %struct.lock_owner*, %struct.vnode*, %struct.inode*, %struct.task*, %24, %struct.lockf_edge_list, %struct.lockf_edge_list, i32, i8, i8, i8, i8 }> + %struct.lockf_entry_list = type <{ %struct.lockf_entry* }> + %struct.lpohead = type <{ %struct.lock_profile_object* }> + %struct.md_page = type <{ %4 }> + %struct.mdproc = type <{ %struct.cv*, %struct.system_segment_descriptor }> + %struct.mdthread = type <{ i32, i8, i8, i8, i8, i64 }> + %struct.mntarg = type opaque + %struct.mntlist = type <{ %struct.mount*, %struct.mount** }> + %struct.mount = type <{ %struct.mtx, i32, i8, i8, i8, i8, %struct.mntlist, %struct.vfsops*, %struct.vfsconf*, %struct.vnode*, %struct.vnode*, i32, i8, i8, i8, i8, %struct.freelst, i32, i32, i32, i32, i32, i32, %struct.vfsoptlist*, %struct.vfsoptlist*, i32, i8, i8, i8, i8, %struct.statfs, %struct.ucred*, i8*, i64, i32, i8, i8, i8, i8, %struct.netexport*, %struct.label*, i32, i32, i32, i32, %struct.thread*, i8*, %struct.lock }> + %struct.mqueue_notifier = type opaque + %struct.mtx = type <{ %struct.lock_object, i64 }> + %struct.namecache = type opaque + %struct.netexport = type opaque + %struct.nlminfo = type opaque + %struct.osd = type <{ i32, i8, i8, i8, i8, i8**, %12 }> + %struct.p_sched = type opaque + %struct.pargs = type <{ i32, i32, [1 x i8], i8, i8, i8 }> + %struct.pcb = type opaque + %struct.pgrp = type <{ %16, %13, %struct.session*, %struct.sigiolst, i32, i32, %struct.mtx }> + %struct.plimit = type opaque + %struct.pmap = type <{ %struct.mtx, i64*, %15, i32, i8, i8, i8, i8, %struct.bintime, %struct.vm_page* }> + %struct.prison = type <{ %9, i32, i32, i32, i32, %10, %9, %struct.prison*, %struct.mtx, %struct.task, %struct.osd, %struct.cpuset*, %struct.vnet*, %struct.vnode*, i32, i32, %struct.in_addr*, %struct.in6_addr*, [4 x i8*], i32, i32, i32, i32, i32, [5 x i32], i64, [256 x i8], [1024 x i8], [256 x i8], [256 x i8], [64 x i8] }> + %struct.proc = type <{ %7, %8, %struct.mtx, %struct.ucred*, %struct.filedesc*, %struct.filedesc_to_leader*, %struct.pstats*, %struct.plimit*, %struct.callout, %struct.sigacts*, i32, i32, i32, i8, i8, i8, i8, %7, %7, %struct.proc*, %7, %13, %struct.mtx, %struct.ksiginfo*, %struct.sigqueue, i32, i8, i8, i8, i8, %struct.vmspace*, i32, i8, i8, i8, i8, %struct.itimerval, %struct.rusage, %struct.rusage_ext, %struct.rusage_ext, i32, i32, i32, i8, i8, i8, i8, %struct.vnode*, %struct.ucred*, %struct.vnode*, i32, i8, i8, i8, i8, %struct.sigiolst, i32, i32, i64, i32, i32, i8, i8, i8, i8, i8, i8, i8, i8, %struct.nlminfo*, %struct.kaioinfo*, %struct.thread*, i32, i8, i8, i8, i8, %struct.thread*, i32, i32, %struct.itimers*, i32, i32, [20 x i8], i8, i8, i8, i8, %struct.pgrp*, %struct.sysentvec*, %struct.pargs*, i64, i8, i8, i8, i8, i32, i16, i8, i8, i8, i8, i8, i8, %struct.knlist, i32, i8, i8, i8, i8, %struct.mdproc, %struct.callout, i16, i8, i8, i8, i8, i8, i8, %struct.proc*, %struct.proc*, i8*, %struct.label*, %struct.p_sched*, %18, %19, %struct.kdtrace_proc*, %struct.cv }> + %struct.pstats = type opaque + %struct.pv_chunk = type <{ %struct.pmap*, %15, [3 x i64], [2 x i64], [168 x %struct.pv_entry] }> + %struct.pv_entry = type <{ i64, %4 }> + %struct.rusage = type <{ %struct.bintime, %struct.bintime, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64 }> + %struct.rusage_ext = type <{ i64, i64, i64, i64, i64, i64, i64 }> + %struct.selfd = type opaque + %struct.selfdlist = type <{ %struct.selfd*, %struct.selfd** }> + %struct.selinfo = type <{ %struct.selfdlist, %struct.knlist, %struct.mtx* }> + %struct.seltd = type opaque + %struct.session = type <{ i32, i8, i8, i8, i8, %struct.proc*, %struct.vnode*, %struct.tty*, i32, [24 x i8], i8, i8, i8, i8, %struct.mtx }> + %struct.shmmap_state = type opaque + %struct.sigacts = type <{ [128 x void (i32)*], [128 x %struct.__sigset], %struct.__sigset, %struct.__sigset, %struct.__sigset, %struct.__sigset, %struct.__sigset, %struct.__sigset, %struct.__sigset, %struct.__sigset, %struct.__sigset, %struct.__sigset, i32, i32, %struct.mtx }> + %struct.sigaltstack = type <{ i8*, i64, i32, i8, i8, i8, i8 }> + %struct.sigio = type <{ %union.sigval, %struct.sigiolst, %struct.sigio**, %struct.ucred*, i32, i8, i8, i8, i8 }> + %struct.sigiolst = type <{ %struct.sigio* }> + %struct.sigqueue = type <{ %struct.__sigset, %struct.__sigset, %14, %struct.proc*, i32, i8, i8, i8, i8 }> + %struct.sleepqueue = type opaque + %struct.sockaddr = type opaque + %struct.stat = type <{ i32, i32, i16, i16, i32, i32, i32, %struct.bintime, %struct.bintime, %struct.bintime, i64, i64, i32, i32, i32, i32, %struct.bintime }> + %struct.statfs = type <{ i32, i32, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, [10 x i64], i32, i32, %struct.fsid, [80 x i8], [16 x i8], [88 x i8], [88 x i8] }> + %struct.sysctl_req = type <{ %struct.thread*, i32, i8, i8, i8, i8, i8*, i64, i64, i32 (%struct.sysctl_req*, i8*, i64)*, i8*, i64, i64, i32 (%struct.sysctl_req*, i8*, i64)*, i64, i32, i8, i8, i8, i8 }> + %struct.sysentvec = type opaque + %struct.system_segment_descriptor = type <{ i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8 }> + %struct.task = type <{ %11, i16, i16, i8, i8, i8, i8, void (i8*, i32)*, i8* }> + %struct.td_sched = type opaque + %struct.thread = type <{ %struct.mtx*, %struct.proc*, %8, %8, %8, %8, %struct.cpuset*, %struct.seltd*, %struct.sleepqueue*, %struct.turnstile*, %struct.umtx_q*, i32, i8, i8, i8, i8, %struct.sigqueue, i32, i32, i32, i32, i32, i8, i8, i8, i8, i8*, i8*, i8, i8, i8, i8, i16, i16, i16, i8, i8, i8, i8, i8, i8, %struct.turnstile*, i8*, %20, %struct.lock_list_entry*, i32, i32, %struct.ucred*, i32, i32, %struct.rusage, i64, i64, i32, i32, i32, i32, i32, %struct.__sigset, %struct.__sigset, i32, %struct.sigaltstack, i32, i8, i8, i8, i8, i64, i32, [20 x i8], %struct.file*, i32, i32, %struct.osd, i8, i8, i8, i8, i8, i8, i8, i8, %struct.pcb*, i32, i8, i8, i8, i8, [2 x i64], %struct.callout, %struct.trapframe*, %struct.vm_object*, i64, i32, i8, i8, i8, i8, %struct.vm_object*, i64, i32, i32, %struct.mdthread, %struct.td_sched*, %struct.kaudit_record*, i32, i8, i8, i8, i8, [2 x %struct.lpohead], %struct.kdtrace_thread*, i32, i8, i8, i8, i8, %struct.vnet*, i8* }> + %struct.trapframe = type <{ i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i32, i16, i16, i64, i32, i16, i16, i64, i64, i64, i64, i64, i64 }> + %struct.tty = type opaque + %struct.turnstile = type opaque + %struct.ucred = type <{ i32, i32, i32, i32, i32, i32, i32, i8, i8, i8, i8, %struct.uidinfo*, %struct.uidinfo*, %struct.prison*, %struct.vimage*, i32, i8, i8, i8, i8, [2 x i8*], %struct.label*, %struct.auditinfo_addr, i32*, i32, i8, i8, i8, i8 }> + %struct.uidinfo = type opaque + %struct.uio = type <{ %struct.iovec*, i32, i8, i8, i8, i8, i64, i64, i32, i32, %struct.thread* }> + %struct.umtx_q = type opaque + %struct.vattr = type <{ i32, i16, i16, i32, i32, i32, i8, i8, i8, i8, i64, i64, i64, %struct.bintime, %struct.bintime, %struct.bintime, %struct.bintime, i64, i64, i32, i8, i8, i8, i8, i64, i64, i32, i8, i8, i8, i8, i64 }> + %struct.vfsconf = type <{ i32, [16 x i8], i8, i8, i8, i8, %struct.vfsops*, i32, i32, i32, i8, i8, i8, i8, %struct.vfsoptdecl*, %struct.vfsconfhead }> + %struct.vfsconfhead = type <{ %struct.vfsconf*, %struct.vfsconf** }> + %struct.vfsops = type <{ i32 (%struct.mount*)*, i32 (%struct.mntarg*, i8*, i32)*, i32 (%struct.mount*, i32)*, i32 (%struct.mount*, i32, %struct.vnode**)*, i32 (%struct.mount*, i32, i32, i8*)*, i32 (%struct.mount*, %struct.statfs*)*, i32 (%struct.mount*, i32)*, i32 (%struct.mount*, i32, i32, %struct.vnode**)*, i32 (%struct.mount*, %struct.fid*, %struct.vnode**)*, i32 (%struct.mount*, %struct.sockaddr*, i32*, %struct.ucred**, i32*, i32**)*, i32 (%struct.vfsconf*)*, i32 (%struct.vfsconf*)*, i32 (%struct.mount*, i32, %struct.vnode*, i32, i8*)*, i32 (%struct.mount*, i32, %struct.sysctl_req*)*, void (%struct.mount*)* }> + %struct.vfsopt = type <{ %struct.vfsoptlist, i8*, i8*, i32, i32, i32, i8, i8, i8, i8 }> + %struct.vfsoptdecl = type opaque + %struct.vfsoptlist = type <{ %struct.vfsopt*, %struct.vfsopt** }> + %struct.vimage = type opaque + %struct.vm_map = type <{ %struct.vm_map_entry, %struct.mtx, %struct.mtx, i32, i8, i8, i8, i8, i64, i32, i8, i8, i8, i8, %struct.vm_map_entry*, %struct.pmap*, %struct.vm_map_entry* }> + %struct.vm_map_entry = type <{ %struct.vm_map_entry*, %struct.vm_map_entry*, %struct.vm_map_entry*, %struct.vm_map_entry*, i64, i64, i64, i64, i64, %union.sigval, i64, i32, i8, i8, i8, i8, i32, i8, i8, i8, i8, i64, %struct.uidinfo* }> + %struct.vm_object = type <{ %struct.mtx, %1, %2, %1, %3, %struct.vm_page*, i64, i32, i32, i32, i8, i8, i16, i16, i16, i32, %struct.vm_object*, i64, %1, %5, %struct.vm_page*, i8*, %union.anon, %struct.uidinfo*, i64 }> + %struct.vm_page = type <{ %3, %3, %struct.vm_page*, %struct.vm_page*, %struct.vm_object*, i64, i64, %struct.md_page, i8, i8, i16, i8, i8, i16, i32, i16, i16, i8, i8, i8, i8, i8, i8, i8, i8 }> + %struct.vm_reserv = type opaque + %struct.vmspace = type <{ %struct.vm_map, %struct.shmmap_state*, i64, i64, i64, i64, i8*, i8*, i8*, i32, i8, i8, i8, i8, %struct.pmap }> + %struct.vnet = type opaque + %struct.vnode = type <{ i32, i8, i8, i8, i8, i8*, %struct.vop_vector*, i8*, %struct.mount*, %struct.freelst, %union.sigval, %struct.freelst, i32, i8, i8, i8, i8, %21, %22, %struct.namecache*, i64, i64, i64, i32, i8, i8, i8, i8, %struct.lock, %struct.mtx, %struct.lock*, i32, i32, i64, i64, i32, i8, i8, i8, i8, %struct.freelst, %struct.bufobj, %struct.vpollinfo*, %struct.label*, %struct.lockf* }> + %struct.vnodeop_desc = type <{ i8*, i32, i8, i8, i8, i8, i32 (%struct.vop_generic_args*)*, i32*, i32, i32, i32, i32 }> + %struct.vop_access_args = type <{ %struct.vop_generic_args, %struct.vnode*, i32, i8, i8, i8, i8, %struct.ucred*, %struct.thread* }> + %struct.vop_aclcheck_args = type <{ %struct.vop_generic_args, %struct.vnode*, i32, i8, i8, i8, i8, %struct.acl*, %struct.ucred*, %struct.thread* }> + %struct.vop_advlock_args = type <{ %struct.vop_generic_args, %struct.vnode*, i8*, i32, i8, i8, i8, i8, %struct.flock*, i32, i8, i8, i8, i8 }> + %struct.vop_advlockasync_args = type <{ %struct.vop_generic_args, %struct.vnode*, i8*, i32, i8, i8, i8, i8, %struct.flock*, i32, i8, i8, i8, i8, %struct.task*, i8** }> + %struct.vop_bmap_args = type <{ %struct.vop_generic_args, %struct.vnode*, i64, %struct.bufobj**, i64*, i32*, i32* }> + %struct.vop_cachedlookup_args = type <{ %struct.vop_generic_args, %struct.vnode*, %struct.vnode**, %struct.componentname* }> + %struct.vop_create_args = type <{ %struct.vop_generic_args, %struct.vnode*, %struct.vnode**, %struct.componentname*, %struct.vattr* }> + %struct.vop_deleteextattr_args = type <{ %struct.vop_generic_args, %struct.vnode*, i32, i8, i8, i8, i8, i8*, %struct.ucred*, %struct.thread* }> + %struct.vop_fsync_args = type <{ %struct.vop_generic_args, %struct.vnode*, i32, i8, i8, i8, i8, %struct.thread* }> + %struct.vop_generic_args = type <{ %struct.vnodeop_desc* }> + %struct.vop_getattr_args = type <{ %struct.vop_generic_args, %struct.vnode*, %struct.vattr*, %struct.ucred* }> + %struct.vop_getextattr_args = type <{ %struct.vop_generic_args, %struct.vnode*, i32, i8, i8, i8, i8, i8*, %struct.uio*, i64*, %struct.ucred*, %struct.thread* }> + %struct.vop_getpages_args = type <{ %struct.vop_generic_args, %struct.vnode*, %struct.vm_page**, i32, i32, i64 }> + %struct.vop_getwritemount_args = type <{ %struct.vop_generic_args, %struct.vnode*, %struct.mount** }> + %struct.vop_inactive_args = type <{ %struct.vop_generic_args, %struct.vnode*, %struct.thread* }> + %struct.vop_ioctl_args = type <{ %struct.vop_generic_args, %struct.vnode*, i64, i8*, i32, i8, i8, i8, i8, %struct.ucred*, %struct.thread* }> + %struct.vop_islocked_args = type <{ %struct.vop_generic_args, %struct.vnode* }> + %struct.vop_kqfilter_args = type <{ %struct.vop_generic_args, %struct.vnode*, %struct.knote* }> + %struct.vop_link_args = type <{ %struct.vop_generic_args, %struct.vnode*, %struct.vnode*, %struct.componentname* }> + %struct.vop_listextattr_args = type <{ %struct.vop_generic_args, %struct.vnode*, i32, i8, i8, i8, i8, %struct.uio*, i64*, %struct.ucred*, %struct.thread* }> + %struct.vop_lock1_args = type <{ %struct.vop_generic_args, %struct.vnode*, i32, i8, i8, i8, i8, i8*, i32, i8, i8, i8, i8 }> + %struct.vop_open_args = type <{ %struct.vop_generic_args, %struct.vnode*, i32, i8, i8, i8, i8, %struct.ucred*, %struct.thread*, %struct.file* }> + %struct.vop_openextattr_args = type <{ %struct.vop_generic_args, %struct.vnode*, %struct.ucred*, %struct.thread* }> + %struct.vop_pathconf_args = type <{ %struct.vop_generic_args, %struct.vnode*, i32, i8, i8, i8, i8, i64* }> + %struct.vop_putpages_args = type <{ %struct.vop_generic_args, %struct.vnode*, %struct.vm_page**, i32, i32, i32*, i64 }> + %struct.vop_read_args = type <{ %struct.vop_generic_args, %struct.vnode*, %struct.uio*, i32, i8, i8, i8, i8, %struct.ucred* }> + %struct.vop_readdir_args = type <{ %struct.vop_generic_args, %struct.vnode*, %struct.uio*, %struct.ucred*, i32*, i32*, i64** }> + %struct.vop_readlink_args = type <{ %struct.vop_generic_args, %struct.vnode*, %struct.uio*, %struct.ucred* }> + %struct.vop_reallocblks_args = type <{ %struct.vop_generic_args, %struct.vnode*, %struct.cluster_save* }> + %struct.vop_rename_args = type <{ %struct.vop_generic_args, %struct.vnode*, %struct.vnode*, %struct.componentname*, %struct.vnode*, %struct.vnode*, %struct.componentname* }> + %struct.vop_revoke_args = type <{ %struct.vop_generic_args, %struct.vnode*, i32, i8, i8, i8, i8 }> + %struct.vop_setextattr_args = type <{ %struct.vop_generic_args, %struct.vnode*, i32, i8, i8, i8, i8, i8*, %struct.uio*, %struct.ucred*, %struct.thread* }> + %struct.vop_setlabel_args = type <{ %struct.vop_generic_args, %struct.vnode*, %struct.label*, %struct.ucred*, %struct.thread* }> + %struct.vop_strategy_args = type <{ %struct.vop_generic_args, %struct.vnode*, %struct.buf* }> + %struct.vop_symlink_args = type <{ %struct.vop_generic_args, %struct.vnode*, %struct.vnode**, %struct.componentname*, %struct.vattr*, i8* }> + %struct.vop_vector = type <{ %struct.vop_vector*, i32 (%struct.vop_generic_args*)*, i32 (%struct.vop_islocked_args*)*, i32 (%struct.vop_cachedlookup_args*)*, i32 (%struct.vop_cachedlookup_args*)*, i32 (%struct.vop_create_args*)*, i32 (%struct.vop_whiteout_args*)*, i32 (%struct.vop_create_args*)*, i32 (%struct.vop_open_args*)*, i32 (%struct.vop_access_args*)*, i32 (%struct.vop_access_args*)*, i32 (%struct.vop_access_args*)*, i32 (%struct.vop_getattr_args*)*, i32 (%struct.vop_getattr_args*)*, i32 (%struct.vop_islocked_args*)*, i32 (%struct.vop_read_args*)*, i32 (%struct.vop_read_args*)*, i32 (%struct.vop_ioctl_args*)*, i32 (%struct.vop_access_args*)*, i32 (%struct.vop_kqfilter_args*)*, i32 (%struct.vop_revoke_args*)*, i32 (%struct.vop_fsync_args*)*, i32 (%struct.vop_link_args*)*, i32 (%struct.vop_link_args*)*, i32 (%struct.vop_rename_args*)*, i32 (%struct.vop_create_args*)*, i32 (%struct.vop_link_args*)*, i32 (%struct.vop_symlink_args*)*, i32 (%struct.vop_readdir_args*)*, i32 (%struct.vop_readlink_args*)*, i32 (%struct.vop_inactive_args*)*, i32 (%struct.vop_inactive_args*)*, i32 (%struct.vop_lock1_args*)*, i32 (%struct.vop_revoke_args*)*, i32 (%struct.vop_bmap_args*)*, i32 (%struct.vop_strategy_args*)*, i32 (%struct.vop_getwritemount_args*)*, i32 (%struct.vop_islocked_args*)*, i32 (%struct.vop_pathconf_args*)*, i32 (%struct.vop_advlock_args*)*, i32 (%struct.vop_advlockasync_args*)*, i32 (%struct.vop_reallocblks_args*)*, i32 (%struct.vop_getpages_args*)*, i32 (%struct.vop_putpages_args*)*, i32 (%struct.vop_aclcheck_args*)*, i32 (%struct.vop_aclcheck_args*)*, i32 (%struct.vop_aclcheck_args*)*, i32 (%struct.vop_access_args*)*, i32 (%struct.vop_getextattr_args*)*, i32 (%struct.vop_listextattr_args*)*, i32 (%struct.vop_openextattr_args*)*, i32 (%struct.vop_deleteextattr_args*)*, i32 (%struct.vop_setextattr_args*)*, i32 (%struct.vop_setlabel_args*)*, i32 (%struct.vop_vptofh_args*)*, i32 (%struct.vop_vptocnp_args*)* }> + %struct.vop_vptocnp_args = type <{ %struct.vop_generic_args, %struct.vnode*, %struct.vnode**, %struct.ucred*, i8*, i32* }> + %struct.vop_vptofh_args = type <{ %struct.vop_generic_args, %struct.vnode*, %struct.fid* }> + %struct.vop_whiteout_args = type <{ %struct.vop_generic_args, %struct.vnode*, %struct.componentname*, i32, i8, i8, i8, i8 }> + %struct.vpollinfo = type <{ %struct.mtx, %struct.selinfo, i16, i16, i8, i8, i8, i8 }> + %struct.witness = type opaque + %struct.workhead = type <{ %struct.worklist* }> + %struct.worklist = type opaque + %union.anon = type <{ [16 x i8] }> + %union.pager_info = type <{ [4 x i8] }> + %union.sigval = type <{ [8 x i8] }> + +define i32 @vlrureclaim(%struct.mount* %mp) nounwind { +entry: + br i1 undef, label %if.then11, label %do.end + +if.then11: ; preds = %entry + br label %do.end + +do.end: ; preds = %if.then11, %entry + br label %while.cond.outer + +while.cond.outer: ; preds = %while.cond.outer.backedge, %do.end + %count.0.ph = phi i32 [ undef, %do.end ], [ undef, %while.cond.outer.backedge ] ; [#uses=1] + br label %while.cond + +while.cond: ; preds = %next_iter, %while.cond.outer + %count.0 = phi i32 [ %dec, %next_iter ], [ %count.0.ph, %while.cond.outer ] ; [#uses=2] + %cmp21 = icmp eq i32 %count.0, 0 ; [#uses=1] + br i1 %cmp21, label %do.body288.loopexit4, label %while.body + +while.body: ; preds = %while.cond + br label %while.cond27 + +while.cond27: ; preds = %while.body36, %while.body + br i1 undef, label %do.body288.loopexit, label %land.rhs + +land.rhs: ; preds = %while.cond27 + br i1 undef, label %while.body36, label %while.end + +while.body36: ; preds = %land.rhs + br label %while.cond27 + +while.end: ; preds = %land.rhs + br i1 undef, label %do.body288.loopexit4, label %do.body46 + +do.body46: ; preds = %while.end + br i1 undef, label %if.else64, label %if.then53 + +if.then53: ; preds = %do.body46 + br label %if.end72 + +if.else64: ; preds = %do.body46 + br label %if.end72 + +if.end72: ; preds = %if.else64, %if.then53 + %dec = add i32 %count.0, -1 ; [#uses=2] + br i1 undef, label %next_iter, label %if.end111 + +if.end111: ; preds = %if.end72 + br i1 undef, label %lor.lhs.false, label %do.body145 + +lor.lhs.false: ; preds = %if.end111 + br i1 undef, label %lor.lhs.false122, label %do.body145 + +lor.lhs.false122: ; preds = %lor.lhs.false + br i1 undef, label %lor.lhs.false128, label %do.body145 + +lor.lhs.false128: ; preds = %lor.lhs.false122 + br i1 undef, label %do.body162, label %land.lhs.true + +land.lhs.true: ; preds = %lor.lhs.false128 + br i1 undef, label %do.body145, label %do.body162 + +do.body145: ; preds = %land.lhs.true, %lor.lhs.false122, %lor.lhs.false, %if.end111 + br i1 undef, label %if.then156, label %next_iter + +if.then156: ; preds = %do.body145 + br label %next_iter + +do.body162: ; preds = %land.lhs.true, %lor.lhs.false128 + br i1 undef, label %if.then173, label %do.end177 + +if.then173: ; preds = %do.body162 + br label %do.end177 + +do.end177: ; preds = %if.then173, %do.body162 + br i1 undef, label %do.body185, label %if.then182 + +if.then182: ; preds = %do.end177 + br label %next_iter_mntunlocked + +do.body185: ; preds = %do.end177 + br i1 undef, label %if.then196, label %do.end202 + +if.then196: ; preds = %do.body185 + br label %do.end202 + +do.end202: ; preds = %if.then196, %do.body185 + br i1 undef, label %lor.lhs.false207, label %if.then231 + +lor.lhs.false207: ; preds = %do.end202 + br i1 undef, label %lor.lhs.false214, label %if.then231 + +lor.lhs.false214: ; preds = %lor.lhs.false207 + br i1 undef, label %do.end236, label %land.lhs.true221 + +land.lhs.true221: ; preds = %lor.lhs.false214 + br i1 undef, label %if.then231, label %do.end236 + +if.then231: ; preds = %land.lhs.true221, %lor.lhs.false207, %do.end202 + br label %next_iter_mntunlocked + +do.end236: ; preds = %land.lhs.true221, %lor.lhs.false214 + br label %next_iter_mntunlocked + +next_iter_mntunlocked: ; preds = %do.end236, %if.then231, %if.then182 + br i1 undef, label %yield, label %do.body269 + +next_iter: ; preds = %if.then156, %do.body145, %if.end72 + %rem2482 = and i32 %dec, 255 ; [#uses=1] + %cmp249 = icmp eq i32 %rem2482, 0 ; [#uses=1] + br i1 %cmp249, label %do.body253, label %while.cond + +do.body253: ; preds = %next_iter + br i1 undef, label %if.then264, label %yield + +if.then264: ; preds = %do.body253 + br label %yield + +yield: ; preds = %if.then264, %do.body253, %next_iter_mntunlocked + br label %do.body269 + +do.body269: ; preds = %yield, %next_iter_mntunlocked + br i1 undef, label %if.then280, label %while.cond.outer.backedge + +if.then280: ; preds = %do.body269 + br label %while.cond.outer.backedge + +while.cond.outer.backedge: ; preds = %if.then280, %do.body269 + br label %while.cond.outer + +do.body288.loopexit: ; preds = %while.cond27 + br label %do.body288 + +do.body288.loopexit4: ; preds = %while.end, %while.cond + br label %do.body288 + +do.body288: ; preds = %do.body288.loopexit4, %do.body288.loopexit + br i1 undef, label %if.then299, label %do.end303 + +if.then299: ; preds = %do.body288 + br label %do.end303 + +do.end303: ; preds = %if.then299, %do.body288 + ret i32 undef +} diff --git a/libclamav/c++/llvm/test/Analysis/ScalarEvolution/avoid-smax-0.ll b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/avoid-smax-0.ll new file mode 100644 index 000000000..b733d6acb --- /dev/null +++ b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/avoid-smax-0.ll @@ -0,0 +1,35 @@ +; RUN: opt < %s -scalar-evolution -analyze -disable-output | grep {Loop bb3: backedge-taken count is (-1 + %n)} + +; We don't want to use a max in the trip count expression in +; this testcase. + +define void @foo(i32 %n, i32* %p, i32* %q) nounwind { +entry: + icmp sgt i32 %n, 0 + br i1 %0, label %bb, label %return + +bb: + load i32* %q, align 4 + icmp eq i32 %1, 0 + br i1 %2, label %return, label %bb3.preheader + +bb3.preheader: + br label %bb3 + +bb3: + %i.0 = phi i32 [ %7, %bb3 ], [ 0, %bb3.preheader ] + getelementptr i32* %p, i32 %i.0 + load i32* %3, align 4 + add i32 %4, 1 + getelementptr i32* %p, i32 %i.0 + store i32 %5, i32* %6, align 4 + add i32 %i.0, 1 + icmp slt i32 %7, %n + br i1 %8, label %bb3, label %return.loopexit + +return.loopexit: + br label %return + +return: + ret void +} diff --git a/libclamav/c++/llvm/test/Analysis/ScalarEvolution/avoid-smax-1.ll b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/avoid-smax-1.ll new file mode 100644 index 000000000..0bc9ce824 --- /dev/null +++ b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/avoid-smax-1.ll @@ -0,0 +1,236 @@ +; RUN: opt < %s -indvars -S > %t +; RUN: grep select %t | count 2 +; RUN: grep {icmp ne i32.\* %w } %t + +; Indvars should be able to insert a canonical induction variable +; for the bb6 loop without using a maximum calculation (icmp, select) +; because it should be able to prove that the comparison is guarded +; by an appropriate conditional branch. Unfortunately, indvars is +; not yet able to find the comparison for the other two loops in +; this testcase. + +target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128" +target triple = "i386-apple-darwin9" + +define void @foo(i8* %r, i32 %s, i32 %w, i32 %x, i8* %j, i32 %d) nounwind { +entry: + %0 = mul i32 %x, %w ; [#uses=2] + %1 = mul i32 %x, %w ; [#uses=1] + %2 = sdiv i32 %1, 4 ; [#uses=1] + %.sum2 = add i32 %2, %0 ; [#uses=2] + %cond = icmp eq i32 %d, 1 ; [#uses=1] + br i1 %cond, label %bb29, label %bb10.preheader + +bb10.preheader: ; preds = %entry + %3 = icmp sgt i32 %x, 0 ; [#uses=1] + br i1 %3, label %bb.nph9, label %bb18.loopexit + +bb.nph7: ; preds = %bb7.preheader + %4 = mul i32 %y.08, %w ; [#uses=1] + %5 = mul i32 %y.08, %s ; [#uses=1] + %6 = add i32 %5, 1 ; [#uses=1] + br label %bb6 + +bb6: ; preds = %bb7, %bb.nph7 + %x.06 = phi i32 [ %13, %bb7 ], [ 0, %bb.nph7 ] ; [#uses=3] + %7 = add i32 %x.06, %4 ; [#uses=1] + %8 = shl i32 %x.06, 1 ; [#uses=1] + %9 = add i32 %6, %8 ; [#uses=1] + %10 = getelementptr i8* %r, i32 %9 ; [#uses=1] + %11 = load i8* %10, align 1 ; [#uses=1] + %12 = getelementptr i8* %j, i32 %7 ; [#uses=1] + store i8 %11, i8* %12, align 1 + %13 = add i32 %x.06, 1 ; [#uses=2] + br label %bb7 + +bb7: ; preds = %bb6 + %14 = icmp slt i32 %13, %w ; [#uses=1] + br i1 %14, label %bb6, label %bb7.bb9_crit_edge + +bb7.bb9_crit_edge: ; preds = %bb7 + br label %bb9 + +bb9: ; preds = %bb7.preheader, %bb7.bb9_crit_edge + %15 = add i32 %y.08, 1 ; [#uses=2] + br label %bb10 + +bb10: ; preds = %bb9 + %16 = icmp slt i32 %15, %x ; [#uses=1] + br i1 %16, label %bb7.preheader, label %bb10.bb18.loopexit_crit_edge + +bb10.bb18.loopexit_crit_edge: ; preds = %bb10 + br label %bb10.bb18.loopexit_crit_edge.split + +bb10.bb18.loopexit_crit_edge.split: ; preds = %bb.nph9, %bb10.bb18.loopexit_crit_edge + br label %bb18.loopexit + +bb.nph9: ; preds = %bb10.preheader + %17 = icmp sgt i32 %w, 0 ; [#uses=1] + br i1 %17, label %bb.nph9.split, label %bb10.bb18.loopexit_crit_edge.split + +bb.nph9.split: ; preds = %bb.nph9 + br label %bb7.preheader + +bb7.preheader: ; preds = %bb.nph9.split, %bb10 + %y.08 = phi i32 [ %15, %bb10 ], [ 0, %bb.nph9.split ] ; [#uses=3] + br i1 true, label %bb.nph7, label %bb9 + +bb.nph5: ; preds = %bb18.loopexit + %18 = sdiv i32 %w, 2 ; [#uses=1] + %19 = icmp slt i32 %w, 2 ; [#uses=1] + %20 = sdiv i32 %x, 2 ; [#uses=1] + br i1 %19, label %bb18.bb20_crit_edge.split, label %bb.nph5.split + +bb.nph5.split: ; preds = %bb.nph5 + br label %bb13 + +bb13: ; preds = %bb18, %bb.nph5.split + %y.14 = phi i32 [ %42, %bb18 ], [ 0, %bb.nph5.split ] ; [#uses=4] + %21 = mul i32 %18, %y.14 ; [#uses=2] + %22 = shl i32 %y.14, 1 ; [#uses=1] + %23 = srem i32 %y.14, 2 ; [#uses=1] + %24 = add i32 %23, %22 ; [#uses=1] + %25 = mul i32 %24, %s ; [#uses=2] + br i1 true, label %bb.nph3, label %bb17 + +bb.nph3: ; preds = %bb13 + %26 = add i32 %21, %0 ; [#uses=1] + %27 = add i32 %21, %.sum2 ; [#uses=1] + %28 = sdiv i32 %w, 2 ; [#uses=1] + br label %bb14 + +bb14: ; preds = %bb15, %bb.nph3 + %x.12 = phi i32 [ %40, %bb15 ], [ 0, %bb.nph3 ] ; [#uses=5] + %29 = shl i32 %x.12, 2 ; [#uses=1] + %30 = add i32 %29, %25 ; [#uses=1] + %31 = getelementptr i8* %r, i32 %30 ; [#uses=1] + %32 = load i8* %31, align 1 ; [#uses=1] + %.sum = add i32 %26, %x.12 ; [#uses=1] + %33 = getelementptr i8* %j, i32 %.sum ; [#uses=1] + store i8 %32, i8* %33, align 1 + %34 = shl i32 %x.12, 2 ; [#uses=1] + %35 = or i32 %34, 2 ; [#uses=1] + %36 = add i32 %35, %25 ; [#uses=1] + %37 = getelementptr i8* %r, i32 %36 ; [#uses=1] + %38 = load i8* %37, align 1 ; [#uses=1] + %.sum6 = add i32 %27, %x.12 ; [#uses=1] + %39 = getelementptr i8* %j, i32 %.sum6 ; [#uses=1] + store i8 %38, i8* %39, align 1 + %40 = add i32 %x.12, 1 ; [#uses=2] + br label %bb15 + +bb15: ; preds = %bb14 + %41 = icmp sgt i32 %28, %40 ; [#uses=1] + br i1 %41, label %bb14, label %bb15.bb17_crit_edge + +bb15.bb17_crit_edge: ; preds = %bb15 + br label %bb17 + +bb17: ; preds = %bb15.bb17_crit_edge, %bb13 + %42 = add i32 %y.14, 1 ; [#uses=2] + br label %bb18 + +bb18.loopexit: ; preds = %bb10.bb18.loopexit_crit_edge.split, %bb10.preheader + %43 = icmp slt i32 %x, 2 ; [#uses=1] + br i1 %43, label %bb20, label %bb.nph5 + +bb18: ; preds = %bb17 + %44 = icmp sgt i32 %20, %42 ; [#uses=1] + br i1 %44, label %bb13, label %bb18.bb20_crit_edge + +bb18.bb20_crit_edge: ; preds = %bb18 + br label %bb18.bb20_crit_edge.split + +bb18.bb20_crit_edge.split: ; preds = %bb18.bb20_crit_edge, %bb.nph5 + br label %bb20 + +bb20: ; preds = %bb18.bb20_crit_edge.split, %bb18.loopexit + switch i32 %d, label %return [ + i32 3, label %bb22 + i32 1, label %bb29 + ] + +bb22: ; preds = %bb20 + %45 = mul i32 %x, %w ; [#uses=1] + %46 = sdiv i32 %45, 4 ; [#uses=1] + %.sum3 = add i32 %46, %.sum2 ; [#uses=2] + %47 = add i32 %x, 15 ; [#uses=1] + %48 = and i32 %47, -16 ; [#uses=1] + %49 = add i32 %w, 15 ; [#uses=1] + %50 = and i32 %49, -16 ; [#uses=1] + %51 = mul i32 %48, %s ; [#uses=1] + %52 = icmp sgt i32 %x, 0 ; [#uses=1] + br i1 %52, label %bb.nph, label %bb26 + +bb.nph: ; preds = %bb22 + br label %bb23 + +bb23: ; preds = %bb24, %bb.nph + %y.21 = phi i32 [ %57, %bb24 ], [ 0, %bb.nph ] ; [#uses=3] + %53 = mul i32 %y.21, %50 ; [#uses=1] + %.sum1 = add i32 %53, %51 ; [#uses=1] + %54 = getelementptr i8* %r, i32 %.sum1 ; [#uses=1] + %55 = mul i32 %y.21, %w ; [#uses=1] + %.sum5 = add i32 %55, %.sum3 ; [#uses=1] + %56 = getelementptr i8* %j, i32 %.sum5 ; [#uses=1] + tail call void @llvm.memcpy.i32(i8* %56, i8* %54, i32 %w, i32 1) + %57 = add i32 %y.21, 1 ; [#uses=2] + br label %bb24 + +bb24: ; preds = %bb23 + %58 = icmp slt i32 %57, %x ; [#uses=1] + br i1 %58, label %bb23, label %bb24.bb26_crit_edge + +bb24.bb26_crit_edge: ; preds = %bb24 + br label %bb26 + +bb26: ; preds = %bb24.bb26_crit_edge, %bb22 + %59 = mul i32 %x, %w ; [#uses=1] + %.sum4 = add i32 %.sum3, %59 ; [#uses=1] + %60 = getelementptr i8* %j, i32 %.sum4 ; [#uses=1] + %61 = mul i32 %x, %w ; [#uses=1] + %62 = sdiv i32 %61, 2 ; [#uses=1] + tail call void @llvm.memset.i32(i8* %60, i8 -128, i32 %62, i32 1) + ret void + +bb29: ; preds = %bb20, %entry + %63 = add i32 %w, 15 ; [#uses=1] + %64 = and i32 %63, -16 ; [#uses=1] + %65 = icmp sgt i32 %x, 0 ; [#uses=1] + br i1 %65, label %bb.nph11, label %bb33 + +bb.nph11: ; preds = %bb29 + br label %bb30 + +bb30: ; preds = %bb31, %bb.nph11 + %y.310 = phi i32 [ %70, %bb31 ], [ 0, %bb.nph11 ] ; [#uses=3] + %66 = mul i32 %y.310, %64 ; [#uses=1] + %67 = getelementptr i8* %r, i32 %66 ; [#uses=1] + %68 = mul i32 %y.310, %w ; [#uses=1] + %69 = getelementptr i8* %j, i32 %68 ; [#uses=1] + tail call void @llvm.memcpy.i32(i8* %69, i8* %67, i32 %w, i32 1) + %70 = add i32 %y.310, 1 ; [#uses=2] + br label %bb31 + +bb31: ; preds = %bb30 + %71 = icmp slt i32 %70, %x ; [#uses=1] + br i1 %71, label %bb30, label %bb31.bb33_crit_edge + +bb31.bb33_crit_edge: ; preds = %bb31 + br label %bb33 + +bb33: ; preds = %bb31.bb33_crit_edge, %bb29 + %72 = mul i32 %x, %w ; [#uses=1] + %73 = getelementptr i8* %j, i32 %72 ; [#uses=1] + %74 = mul i32 %x, %w ; [#uses=1] + %75 = sdiv i32 %74, 2 ; [#uses=1] + tail call void @llvm.memset.i32(i8* %73, i8 -128, i32 %75, i32 1) + ret void + +return: ; preds = %bb20 + ret void +} + +declare void @llvm.memcpy.i32(i8*, i8*, i32, i32) nounwind + +declare void @llvm.memset.i32(i8*, i8, i32, i32) nounwind diff --git a/libclamav/c++/llvm/test/Analysis/ScalarEvolution/dg.exp b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/dg.exp new file mode 100644 index 000000000..b65a2503a --- /dev/null +++ b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/dg.exp @@ -0,0 +1,3 @@ +load_lib llvm.exp + +RunLLVMTests [lsort [glob -nocomplain $srcdir/$subdir/*.ll]] diff --git a/libclamav/c++/llvm/test/Analysis/ScalarEvolution/div-overflow.ll b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/div-overflow.ll new file mode 100644 index 000000000..0c01044b9 --- /dev/null +++ b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/div-overflow.ll @@ -0,0 +1,10 @@ +; RUN: opt < %s -scalar-evolution -analyze -disable-output \ +; RUN: | grep {\\--> ((-128 \\* %a) /u -128)} + +; Don't let ScalarEvolution fold this div away. + +define i8 @foo(i8 %a) { + %t0 = shl i8 %a, 7 + %t1 = lshr i8 %t0, 7 + ret i8 %t1 +} diff --git a/libclamav/c++/llvm/test/Analysis/ScalarEvolution/do-loop.ll b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/do-loop.ll new file mode 100644 index 000000000..f8d7da7c9 --- /dev/null +++ b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/do-loop.ll @@ -0,0 +1,18 @@ +; RUN: opt < %s -analyze -scalar-evolution -disable-output | grep smax +; PR1614 + +define i32 @f(i32 %x, i32 %y) { +entry: + br label %bb + +bb: ; preds = %bb, %entry + %indvar = phi i32 [ 0, %entry ], [ %indvar.next, %bb ] ; [#uses=2] + %x_addr.0 = add i32 %indvar, %x ; [#uses=1] + %tmp2 = add i32 %x_addr.0, 1 ; [#uses=2] + %tmp5 = icmp slt i32 %tmp2, %y ; [#uses=1] + %indvar.next = add i32 %indvar, 1 ; [#uses=1] + br i1 %tmp5, label %bb, label %bb7 + +bb7: ; preds = %bb + ret i32 %tmp2 +} diff --git a/libclamav/c++/llvm/test/Analysis/ScalarEvolution/max-trip-count.ll b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/max-trip-count.ll new file mode 100644 index 000000000..506401daf --- /dev/null +++ b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/max-trip-count.ll @@ -0,0 +1,34 @@ +; RUN: opt < %s -analyze -scalar-evolution -disable-output \ +; RUN: | grep {\{%d,+,\[^\{\}\]\*\}} + +; ScalarEvolution should be able to understand the loop and eliminate the casts. + +define void @foo(i32* nocapture %d, i32 %n) nounwind { +entry: + %0 = icmp sgt i32 %n, 0 ; [#uses=1] + br i1 %0, label %bb.nph, label %return + +bb.nph: ; preds = %entry + br label %bb + +bb: ; preds = %bb1, %bb.nph + %i.02 = phi i32 [ %5, %bb1 ], [ 0, %bb.nph ] ; [#uses=2] + %p.01 = phi i8 [ %4, %bb1 ], [ -1, %bb.nph ] ; [#uses=2] + %1 = sext i8 %p.01 to i32 ; [#uses=1] + %2 = sext i32 %i.02 to i64 ; [#uses=1] + %3 = getelementptr i32* %d, i64 %2 ; [#uses=1] + store i32 %1, i32* %3, align 4 + %4 = add i8 %p.01, 1 ; [#uses=1] + %5 = add i32 %i.02, 1 ; [#uses=2] + br label %bb1 + +bb1: ; preds = %bb + %6 = icmp slt i32 %5, %n ; [#uses=1] + br i1 %6, label %bb, label %bb1.return_crit_edge + +bb1.return_crit_edge: ; preds = %bb1 + br label %return + +return: ; preds = %bb1.return_crit_edge, %entry + ret void +} diff --git a/libclamav/c++/llvm/test/Analysis/ScalarEvolution/nsw-offset.ll b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/nsw-offset.ll new file mode 100644 index 000000000..1e165bf62 --- /dev/null +++ b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/nsw-offset.ll @@ -0,0 +1,76 @@ +; RUN: opt < %s -S -analyze -scalar-evolution -disable-output | FileCheck %s + +; ScalarEvolution should be able to fold away the sign-extensions +; on this loop with a primary induction variable incremented with +; a nsw add of 2. + +target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128" + +define void @foo(i32 %n, double* nocapture %d, double* nocapture %q) nounwind { +entry: + %0 = icmp sgt i32 %n, 0 ; [#uses=1] + br i1 %0, label %bb.nph, label %return + +bb.nph: ; preds = %entry + br label %bb + +bb: ; preds = %bb.nph, %bb1 + %i.01 = phi i32 [ %16, %bb1 ], [ 0, %bb.nph ] ; [#uses=5] + +; CHECK: %1 = sext i32 %i.01 to i64 +; CHECK: --> {0,+,2} + %1 = sext i32 %i.01 to i64 ; [#uses=1] + +; CHECK: %2 = getelementptr inbounds double* %d, i64 %1 +; CHECK: --> {%d,+,16} + %2 = getelementptr inbounds double* %d, i64 %1 ; [#uses=1] + + %3 = load double* %2, align 8 ; [#uses=1] + %4 = sext i32 %i.01 to i64 ; [#uses=1] + %5 = getelementptr inbounds double* %q, i64 %4 ; [#uses=1] + %6 = load double* %5, align 8 ; [#uses=1] + %7 = or i32 %i.01, 1 ; [#uses=1] + +; CHECK: %8 = sext i32 %7 to i64 +; CHECK: --> {1,+,2} + %8 = sext i32 %7 to i64 ; [#uses=1] + +; CHECK: %9 = getelementptr inbounds double* %q, i64 %8 +; CHECK: {(8 + %q),+,16} + %9 = getelementptr inbounds double* %q, i64 %8 ; [#uses=1] + +; Artificially repeat the above three instructions, this time using +; add nsw instead of or. + %t7 = add nsw i32 %i.01, 1 ; [#uses=1] + +; CHECK: %t8 = sext i32 %t7 to i64 +; CHECK: --> {1,+,2} + %t8 = sext i32 %t7 to i64 ; [#uses=1] + +; CHECK: %t9 = getelementptr inbounds double* %q, i64 %t8 +; CHECK: {(8 + %q),+,16} + %t9 = getelementptr inbounds double* %q, i64 %t8 ; [#uses=1] + + %10 = load double* %9, align 8 ; [#uses=1] + %11 = fadd double %6, %10 ; [#uses=1] + %12 = fadd double %11, 3.200000e+00 ; [#uses=1] + %13 = fmul double %3, %12 ; [#uses=1] + %14 = sext i32 %i.01 to i64 ; [#uses=1] + %15 = getelementptr inbounds double* %d, i64 %14 ; [#uses=1] + store double %13, double* %15, align 8 + %16 = add nsw i32 %i.01, 2 ; [#uses=2] + br label %bb1 + +bb1: ; preds = %bb + %17 = icmp slt i32 %16, %n ; [#uses=1] + br i1 %17, label %bb, label %bb1.return_crit_edge + +bb1.return_crit_edge: ; preds = %bb1 + br label %return + +return: ; preds = %bb1.return_crit_edge, %entry + ret void +} + +; CHECK: Loop bb: backedge-taken count is ((-1 + %n) /u 2) +; CHECK: Loop bb: max backedge-taken count is 1073741823 diff --git a/libclamav/c++/llvm/test/Analysis/ScalarEvolution/nsw.ll b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/nsw.ll new file mode 100644 index 000000000..c31edabf3 --- /dev/null +++ b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/nsw.ll @@ -0,0 +1,40 @@ +; RUN: opt < %s -analyze -scalar-evolution -disable-output | grep { --> {.*,+,.*}} | count 8 + +; The addrecs in this loop are analyzable only by using nsw information. + +target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64" + +define void @foo(double* %p) nounwind { +entry: + %tmp = load double* %p, align 8 ; [#uses=1] + %tmp1 = fcmp ogt double %tmp, 2.000000e+00 ; [#uses=1] + br i1 %tmp1, label %bb.nph, label %return + +bb.nph: ; preds = %entry + br label %bb + +bb: ; preds = %bb1, %bb.nph + %i.01 = phi i32 [ %tmp8, %bb1 ], [ 0, %bb.nph ] ; [#uses=3] + %tmp2 = sext i32 %i.01 to i64 ; [#uses=1] + %tmp3 = getelementptr double* %p, i64 %tmp2 ; [#uses=1] + %tmp4 = load double* %tmp3, align 8 ; [#uses=1] + %tmp5 = fmul double %tmp4, 9.200000e+00 ; [#uses=1] + %tmp6 = sext i32 %i.01 to i64 ; [#uses=1] + %tmp7 = getelementptr double* %p, i64 %tmp6 ; [#uses=1] + store double %tmp5, double* %tmp7, align 8 + %tmp8 = add nsw i32 %i.01, 1 ; [#uses=2] + br label %bb1 + +bb1: ; preds = %bb + %phitmp = sext i32 %tmp8 to i64 ; [#uses=1] + %tmp9 = getelementptr double* %p, i64 %phitmp ; [#uses=1] + %tmp10 = load double* %tmp9, align 8 ; [#uses=1] + %tmp11 = fcmp ogt double %tmp10, 2.000000e+00 ; [#uses=1] + br i1 %tmp11, label %bb, label %bb1.return_crit_edge + +bb1.return_crit_edge: ; preds = %bb1 + br label %return + +return: ; preds = %bb1.return_crit_edge, %entry + ret void +} diff --git a/libclamav/c++/llvm/test/Analysis/ScalarEvolution/pointer-sign-bits.ll b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/pointer-sign-bits.ll new file mode 100644 index 000000000..4de006c4e --- /dev/null +++ b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/pointer-sign-bits.ll @@ -0,0 +1,220 @@ +; RUN: opt < %s -analyze -scalar-evolution -disable-output + +target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32" + %JavaObject = type { [0 x i32 (...)*]*, i8* } + +define void @JnJVM_antlr_CSharpCodeGenerator_genBitSet__Lantlr_collections_impl_BitSet_2I(%JavaObject*, %JavaObject*, i32) { +start: + br i1 undef, label %"stack overflow", label %"no stack overflow" + +"GOTO or IF*2": ; preds = %"true verifyAndComputePtr89", %verifyNullCont84 + unreachable + +"GOTO or IF*5": ; preds = %"true verifyAndComputePtr127", %"GOTO or IF*6" + unreachable + +"GOTO or IF*6": ; preds = %"true verifyAndComputePtr131.GOTO or IF*6_crit_edge", %"true verifyAndComputePtr89" + %indvar = phi i32 [ %indvar.next, %"true verifyAndComputePtr131.GOTO or IF*6_crit_edge" ], [ 0, %"true verifyAndComputePtr89" ] ; [#uses=2] + %.0.in = add i32 %indvar, 0 ; [#uses=1] + %.0 = add i32 %.0.in, 1 ; [#uses=1] + %3 = icmp slt i32 %.0, %4 ; [#uses=1] + br i1 %3, label %verifyNullCont126, label %"GOTO or IF*5" + +end: ; preds = %"no exception block35" + ret void + +"stack overflow": ; preds = %start + ret void + +"no stack overflow": ; preds = %start + br i1 undef, label %verifyNullCont, label %"no stack overflow.end_crit_edge" + +"no stack overflow.end_crit_edge": ; preds = %"no stack overflow" + ret void + +verifyNullCont: ; preds = %"no stack overflow" + br i1 undef, label %verifyNullCont9, label %verifyNullCont.end_crit_edge + +verifyNullCont.end_crit_edge: ; preds = %verifyNullCont + ret void + +verifyNullCont9: ; preds = %verifyNullCont + br i1 undef, label %verifyNullCont12, label %verifyNullCont9.end_crit_edge + +verifyNullCont9.end_crit_edge: ; preds = %verifyNullCont9 + ret void + +verifyNullCont12: ; preds = %verifyNullCont9 + br i1 undef, label %"no exception block13", label %verifyNullCont12.end_crit_edge + +verifyNullCont12.end_crit_edge: ; preds = %verifyNullCont12 + ret void + +"no exception block13": ; preds = %verifyNullCont12 + br i1 undef, label %verifyNullExit14, label %verifyNullCont15 + +verifyNullExit14: ; preds = %"no exception block13" + ret void + +verifyNullCont15: ; preds = %"no exception block13" + br i1 undef, label %"no exception block16", label %verifyNullCont15.end_crit_edge + +verifyNullCont15.end_crit_edge: ; preds = %verifyNullCont15 + ret void + +"no exception block16": ; preds = %verifyNullCont15 + br i1 undef, label %verifyNullExit17, label %verifyNullCont18 + +verifyNullExit17: ; preds = %"no exception block16" + ret void + +verifyNullCont18: ; preds = %"no exception block16" + br i1 undef, label %"no exception block19", label %verifyNullCont18.end_crit_edge + +verifyNullCont18.end_crit_edge: ; preds = %verifyNullCont18 + ret void + +"no exception block19": ; preds = %verifyNullCont18 + br i1 undef, label %verifyNullExit20, label %verifyNullCont21 + +verifyNullExit20: ; preds = %"no exception block19" + ret void + +verifyNullCont21: ; preds = %"no exception block19" + br i1 undef, label %verifyNullCont24, label %verifyNullCont21.end_crit_edge + +verifyNullCont21.end_crit_edge: ; preds = %verifyNullCont21 + ret void + +verifyNullCont24: ; preds = %verifyNullCont21 + br i1 undef, label %verifyNullCont27, label %verifyNullCont24.end_crit_edge + +verifyNullCont24.end_crit_edge: ; preds = %verifyNullCont24 + ret void + +verifyNullCont27: ; preds = %verifyNullCont24 + br i1 undef, label %verifyNullCont32, label %verifyNullCont27.end_crit_edge + +verifyNullCont27.end_crit_edge: ; preds = %verifyNullCont27 + ret void + +verifyNullCont32: ; preds = %verifyNullCont27 + br i1 undef, label %verifyNullExit33, label %verifyNullCont34 + +verifyNullExit33: ; preds = %verifyNullCont32 + ret void + +verifyNullCont34: ; preds = %verifyNullCont32 + br i1 undef, label %"no exception block35", label %verifyNullCont34.end_crit_edge + +verifyNullCont34.end_crit_edge: ; preds = %verifyNullCont34 + ret void + +"no exception block35": ; preds = %verifyNullCont34 + br i1 undef, label %end, label %verifyNullCont60 + +verifyNullCont60: ; preds = %"no exception block35" + br i1 undef, label %verifyNullCont63, label %verifyNullCont60.end_crit_edge + +verifyNullCont60.end_crit_edge: ; preds = %verifyNullCont60 + ret void + +verifyNullCont63: ; preds = %verifyNullCont60 + br i1 undef, label %"no exception block64", label %verifyNullCont63.end_crit_edge + +verifyNullCont63.end_crit_edge: ; preds = %verifyNullCont63 + ret void + +"no exception block64": ; preds = %verifyNullCont63 + br i1 undef, label %verifyNullExit65, label %verifyNullCont66 + +verifyNullExit65: ; preds = %"no exception block64" + ret void + +verifyNullCont66: ; preds = %"no exception block64" + br i1 undef, label %"no exception block67", label %verifyNullCont66.end_crit_edge + +verifyNullCont66.end_crit_edge: ; preds = %verifyNullCont66 + ret void + +"no exception block67": ; preds = %verifyNullCont66 + br i1 undef, label %verifyNullExit68, label %verifyNullCont69 + +verifyNullExit68: ; preds = %"no exception block67" + ret void + +verifyNullCont69: ; preds = %"no exception block67" + br i1 undef, label %"no exception block70", label %verifyNullCont69.end_crit_edge + +verifyNullCont69.end_crit_edge: ; preds = %verifyNullCont69 + ret void + +"no exception block70": ; preds = %verifyNullCont69 + br i1 undef, label %verifyNullExit71, label %verifyNullCont72 + +verifyNullExit71: ; preds = %"no exception block70" + ret void + +verifyNullCont72: ; preds = %"no exception block70" + br i1 undef, label %verifyNullCont75, label %verifyNullCont72.end_crit_edge + +verifyNullCont72.end_crit_edge: ; preds = %verifyNullCont72 + ret void + +verifyNullCont75: ; preds = %verifyNullCont72 + br i1 undef, label %verifyNullCont78, label %verifyNullCont75.end_crit_edge + +verifyNullCont75.end_crit_edge: ; preds = %verifyNullCont75 + ret void + +verifyNullCont78: ; preds = %verifyNullCont75 + br i1 undef, label %"verifyNullCont78.GOTO or IF*4_crit_edge", label %verifyNullCont78.end_crit_edge + +"verifyNullCont78.GOTO or IF*4_crit_edge": ; preds = %verifyNullCont78 + br i1 undef, label %verifyNullExit80, label %verifyNullCont81 + +verifyNullCont78.end_crit_edge: ; preds = %verifyNullCont78 + ret void + +verifyNullExit80: ; preds = %"verifyNullCont78.GOTO or IF*4_crit_edge" + ret void + +verifyNullCont81: ; preds = %"verifyNullCont78.GOTO or IF*4_crit_edge" + %4 = ptrtoint i8* undef to i32 ; [#uses=2] + %5 = icmp slt i32 0, %4 ; [#uses=1] + br i1 %5, label %verifyNullCont84, label %verifyNullCont172 + +verifyNullCont84: ; preds = %verifyNullCont81 + br i1 undef, label %"GOTO or IF*2", label %verifyNullCont86 + +verifyNullCont86: ; preds = %verifyNullCont84 + br i1 undef, label %"true verifyAndComputePtr", label %"false verifyAndComputePtr" + +"true verifyAndComputePtr": ; preds = %verifyNullCont86 + br i1 undef, label %"true verifyAndComputePtr89", label %"false verifyAndComputePtr90" + +"false verifyAndComputePtr": ; preds = %verifyNullCont86 + ret void + +"true verifyAndComputePtr89": ; preds = %"true verifyAndComputePtr" + br i1 undef, label %"GOTO or IF*6", label %"GOTO or IF*2" + +"false verifyAndComputePtr90": ; preds = %"true verifyAndComputePtr" + ret void + +verifyNullCont126: ; preds = %"GOTO or IF*6" + br i1 undef, label %"true verifyAndComputePtr127", label %"false verifyAndComputePtr128" + +"true verifyAndComputePtr127": ; preds = %verifyNullCont126 + br i1 undef, label %"true verifyAndComputePtr131.GOTO or IF*6_crit_edge", label %"GOTO or IF*5" + +"false verifyAndComputePtr128": ; preds = %verifyNullCont126 + ret void + +"true verifyAndComputePtr131.GOTO or IF*6_crit_edge": ; preds = %"true verifyAndComputePtr127" + %indvar.next = add i32 %indvar, 1 ; [#uses=1] + br label %"GOTO or IF*6" + +verifyNullCont172: ; preds = %verifyNullCont81 + unreachable +} diff --git a/libclamav/c++/llvm/test/Analysis/ScalarEvolution/pr3909.ll b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/pr3909.ll new file mode 100644 index 000000000..10e328ddf --- /dev/null +++ b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/pr3909.ll @@ -0,0 +1,30 @@ +; RUN: opt < %s -indvars -disable-output +; PR 3909 + + + type { i32, %1* } ; type %0 + type { i32, i8* } ; type %1 + +define x86_stdcallcc i32 @_Dmain(%0 %unnamed) { +entry: + br label %whilebody + +whilebody: ; preds = %endwhile5, %entry + %i.0 = phi i64 [ 0, %entry ], [ %tmp11, %endwhile5 ] ; [#uses=1] + %m.0 = phi i64 [ 0, %entry ], [ %tmp11, %endwhile5 ] ; [#uses=2] + %tmp2 = mul i64 %m.0, %m.0 ; [#uses=1] + br label %whilecond3 + +whilecond3: ; preds = %whilebody4, %whilebody + %j.0 = phi i64 [ %tmp2, %whilebody ], [ %tmp9, %whilebody4 ] ; [#uses=2] + %tmp7 = icmp ne i64 %j.0, 0 ; [#uses=1] + br i1 %tmp7, label %whilebody4, label %endwhile5 + +whilebody4: ; preds = %whilecond3 + %tmp9 = add i64 %j.0, 1 ; [#uses=1] + br label %whilecond3 + +endwhile5: ; preds = %whilecond3 + %tmp11 = add i64 %i.0, 1 ; [#uses=2] + br label %whilebody +} diff --git a/libclamav/c++/llvm/test/Analysis/ScalarEvolution/scev-aa.ll b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/scev-aa.ll new file mode 100644 index 000000000..371d07c7c --- /dev/null +++ b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/scev-aa.ll @@ -0,0 +1,194 @@ +; RUN: opt < %s -scev-aa -aa-eval -print-all-alias-modref-info \ +; RUN: |& FileCheck %s + +; At the time of this writing, -basicaa only misses the example of the form +; A[i+(j+1)] != A[i+j]. However, it does get A[(i+j)+1] != A[i+j]. + +target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64" + +; p[i] and p[i+1] don't alias. + +; CHECK: Function: loop: 3 pointers, 0 call sites +; CHECK: NoAlias: double* %pi, double* %pi.next + +define void @loop(double* nocapture %p, i64 %n) nounwind { +entry: + %j = icmp sgt i64 %n, 0 + br i1 %j, label %bb, label %return + +bb: + %i = phi i64 [ 0, %entry ], [ %i.next, %bb ] + %pi = getelementptr double* %p, i64 %i + %i.next = add i64 %i, 1 + %pi.next = getelementptr double* %p, i64 %i.next + %x = load double* %pi + %y = load double* %pi.next + %z = fmul double %x, %y + store double %z, double* %pi + %exitcond = icmp eq i64 %i.next, %n + br i1 %exitcond, label %return, label %bb + +return: + ret void +} + +; Slightly more involved: p[j][i], p[j][i+1], and p[j+1][i] don't alias. + +; CHECK: Function: nestedloop: 4 pointers, 0 call sites +; CHECK: NoAlias: double* %pi.j, double* %pi.next.j +; CHECK: NoAlias: double* %pi.j, double* %pi.j.next +; CHECK: NoAlias: double* %pi.j.next, double* %pi.next.j + +define void @nestedloop(double* nocapture %p, i64 %m) nounwind { +entry: + %k = icmp sgt i64 %m, 0 + br i1 %k, label %guard, label %return + +guard: + %l = icmp sgt i64 91, 0 + br i1 %l, label %outer.loop, label %return + +outer.loop: + %j = phi i64 [ 0, %guard ], [ %j.next, %outer.latch ] + br label %bb + +bb: + %i = phi i64 [ 0, %outer.loop ], [ %i.next, %bb ] + %i.next = add i64 %i, 1 + + %e = add i64 %i, %j + %pi.j = getelementptr double* %p, i64 %e + %f = add i64 %i.next, %j + %pi.next.j = getelementptr double* %p, i64 %f + %x = load double* %pi.j + %y = load double* %pi.next.j + %z = fmul double %x, %y + store double %z, double* %pi.j + + %o = add i64 %j, 91 + %g = add i64 %i, %o + %pi.j.next = getelementptr double* %p, i64 %g + %a = load double* %pi.j.next + %b = fmul double %x, %a + store double %b, double* %pi.j.next + + %exitcond = icmp eq i64 %i.next, 91 + br i1 %exitcond, label %outer.latch, label %bb + +outer.latch: + %j.next = add i64 %j, 91 + %h = icmp eq i64 %j.next, %m + br i1 %h, label %return, label %outer.loop + +return: + ret void +} + +; Even more involved: same as nestedloop, but with a variable extent. +; When n is 1, p[j+1][i] does alias p[j][i+1], and there's no way to +; prove whether n will be greater than 1, so that relation will always +; by MayAlias. The loop is guarded by a n > 0 test though, so +; p[j+1][i] and p[j][i] can theoretically be determined to be NoAlias, +; however the analysis currently doesn't do that. +; TODO: Make the analysis smarter and turn that MayAlias into a NoAlias. + +; CHECK: Function: nestedloop_more: 4 pointers, 0 call sites +; CHECK: NoAlias: double* %pi.j, double* %pi.next.j +; CHECK: MayAlias: double* %pi.j, double* %pi.j.next + +define void @nestedloop_more(double* nocapture %p, i64 %n, i64 %m) nounwind { +entry: + %k = icmp sgt i64 %m, 0 + br i1 %k, label %guard, label %return + +guard: + %l = icmp sgt i64 %n, 0 + br i1 %l, label %outer.loop, label %return + +outer.loop: + %j = phi i64 [ 0, %guard ], [ %j.next, %outer.latch ] + br label %bb + +bb: + %i = phi i64 [ 0, %outer.loop ], [ %i.next, %bb ] + %i.next = add i64 %i, 1 + + %e = add i64 %i, %j + %pi.j = getelementptr double* %p, i64 %e + %f = add i64 %i.next, %j + %pi.next.j = getelementptr double* %p, i64 %f + %x = load double* %pi.j + %y = load double* %pi.next.j + %z = fmul double %x, %y + store double %z, double* %pi.j + + %o = add i64 %j, %n + %g = add i64 %i, %o + %pi.j.next = getelementptr double* %p, i64 %g + %a = load double* %pi.j.next + %b = fmul double %x, %a + store double %b, double* %pi.j.next + + %exitcond = icmp eq i64 %i.next, %n + br i1 %exitcond, label %outer.latch, label %bb + +outer.latch: + %j.next = add i64 %j, %n + %h = icmp eq i64 %j.next, %m + br i1 %h, label %return, label %outer.loop + +return: + ret void +} + +; ScalarEvolution expands field offsets into constants, which allows it to +; do aggressive analysis. Contrast this with BasicAA, which works by +; recognizing GEP idioms. + +%struct.A = type { %struct.B, i32, i32 } +%struct.B = type { double } + +; CHECK: Function: foo: 7 pointers, 0 call sites +; CHECK: NoAlias: %struct.B* %B, i32* %Z +; CHECK: NoAlias: %struct.B* %B, %struct.B* %C +; CHECK: MustAlias: %struct.B* %C, i32* %Z +; CHECK: NoAlias: %struct.B* %B, i32* %X +; CHECK: MustAlias: i32* %X, i32* %Z +; CHECK: MustAlias: %struct.B* %C, i32* %Y +; CHECK: MustAlias: i32* %X, i32* %Y + +define void @foo() { +entry: + %A = alloca %struct.A + %B = getelementptr %struct.A* %A, i32 0, i32 0 + %Q = bitcast %struct.B* %B to %struct.A* + %Z = getelementptr %struct.A* %Q, i32 0, i32 1 + %C = getelementptr %struct.B* %B, i32 1 + %X = bitcast %struct.B* %C to i32* + %Y = getelementptr %struct.A* %A, i32 0, i32 1 + ret void +} + +; CHECK: Function: bar: 7 pointers, 0 call sites +; CHECK: NoAlias: %struct.B* %N, i32* %P +; CHECK: NoAlias: %struct.B* %N, %struct.B* %R +; CHECK: MustAlias: %struct.B* %R, i32* %P +; CHECK: NoAlias: %struct.B* %N, i32* %W +; CHECK: MustAlias: i32* %P, i32* %W +; CHECK: MustAlias: %struct.B* %R, i32* %V +; CHECK: MustAlias: i32* %V, i32* %W + +define void @bar() { + %M = alloca %struct.A + %N = getelementptr %struct.A* %M, i32 0, i32 0 + %O = bitcast %struct.B* %N to %struct.A* + %P = getelementptr %struct.A* %O, i32 0, i32 1 + %R = getelementptr %struct.B* %N, i32 1 + %W = bitcast %struct.B* %R to i32* + %V = getelementptr %struct.A* %M, i32 0, i32 1 + ret void +} + +; CHECK: 13 no alias responses +; CHECK: 26 may alias responses +; CHECK: 18 must alias responses diff --git a/libclamav/c++/llvm/test/Analysis/ScalarEvolution/sext-inreg.ll b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/sext-inreg.ll new file mode 100644 index 000000000..16128354a --- /dev/null +++ b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/sext-inreg.ll @@ -0,0 +1,30 @@ +; RUN: opt < %s -analyze -scalar-evolution -disable-output > %t +; RUN: grep {sext i57 \{0,+,199\} to i64} %t | count 1 +; RUN: grep {sext i59 \{0,+,199\} to i64} %t | count 1 + +target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128" +target triple = "i386-apple-darwin9.6" + +define i64 @foo(i64* nocapture %x, i64 %n) nounwind { +entry: + %t0 = icmp sgt i64 %n, 0 ; [#uses=1] + br i1 %t0, label %bb, label %return + +bb: ; preds = %bb, %entry + %i.01 = phi i64 [ 0, %entry ], [ %indvar.next, %bb ] ; [#uses=2] + %t1 = shl i64 %i.01, 7 ; [#uses=1] + %t2 = ashr i64 %t1, 7 ; [#uses=1] + %s1 = shl i64 %i.01, 5 ; [#uses=1] + %s2 = ashr i64 %s1, 5 ; [#uses=1] + %t3 = getelementptr i64* %x, i64 %i.01 ; [#uses=1] + store i64 0, i64* %t3, align 1 + %indvar.next = add i64 %i.01, 199 ; [#uses=2] + %exitcond = icmp eq i64 %indvar.next, %n ; [#uses=1] + br i1 %exitcond, label %return, label %bb + +return: ; preds = %bb, %entry + %p = phi i64 [ 0, %entry ], [ %t2, %bb ] + %q = phi i64 [ 0, %entry ], [ %s2, %bb ] + %v = xor i64 %p, %q + ret i64 %v +} diff --git a/libclamav/c++/llvm/test/Analysis/ScalarEvolution/sext-iv-0.ll b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/sext-iv-0.ll new file mode 100644 index 000000000..8f887c4a5 --- /dev/null +++ b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/sext-iv-0.ll @@ -0,0 +1,31 @@ +; RUN: opt < %s -disable-output -scalar-evolution -analyze \ +; RUN: | grep { --> \{-128,+,1\} Exits: 127} | count 5 + +; Convert (sext {-128,+,1}) to {sext(-128),+,sext(1)}, since the +; trip count is within range where this is safe. + +target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128" +target triple = "x86_64-unknown-linux-gnu" + +define void @foo(double* nocapture %x) nounwind { +bb1.thread: + br label %bb1 + +bb1: ; preds = %bb1, %bb1.thread + %i.0.reg2mem.0 = phi i64 [ -128, %bb1.thread ], [ %8, %bb1 ] ; [#uses=3] + %0 = trunc i64 %i.0.reg2mem.0 to i8 ; [#uses=1] + %1 = trunc i64 %i.0.reg2mem.0 to i9 ; [#uses=1] + %2 = sext i9 %1 to i64 ; [#uses=1] + %3 = getelementptr double* %x, i64 %2 ; [#uses=1] + %4 = load double* %3, align 8 ; [#uses=1] + %5 = fmul double %4, 3.900000e+00 ; [#uses=1] + %6 = sext i8 %0 to i64 ; [#uses=1] + %7 = getelementptr double* %x, i64 %6 ; [#uses=1] + store double %5, double* %7, align 8 + %8 = add i64 %i.0.reg2mem.0, 1 ; [#uses=2] + %9 = icmp sgt i64 %8, 127 ; [#uses=1] + br i1 %9, label %return, label %bb1 + +return: ; preds = %bb1 + ret void +} diff --git a/libclamav/c++/llvm/test/Analysis/ScalarEvolution/sext-iv-1.ll b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/sext-iv-1.ll new file mode 100644 index 000000000..02c3206c6 --- /dev/null +++ b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/sext-iv-1.ll @@ -0,0 +1,100 @@ +; RUN: opt < %s -disable-output -scalar-evolution -analyze \ +; RUN: | grep { --> (sext i. \{.\*,+,.\*\} to i64)} | count 5 + +; Don't convert (sext {...,+,...}) to {sext(...),+,sext(...)} in cases +; where the trip count is not within range. + +target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128" +target triple = "x86_64-unknown-linux-gnu" + +define void @foo0(double* nocapture %x) nounwind { +bb1.thread: + br label %bb1 + +bb1: ; preds = %bb1, %bb1.thread + %i.0.reg2mem.0 = phi i64 [ -128, %bb1.thread ], [ %8, %bb1 ] ; [#uses=3] + %0 = trunc i64 %i.0.reg2mem.0 to i7 ; [#uses=1] + %1 = trunc i64 %i.0.reg2mem.0 to i9 ; [#uses=1] + %2 = sext i9 %1 to i64 ; [#uses=1] + %3 = getelementptr double* %x, i64 %2 ; [#uses=1] + %4 = load double* %3, align 8 ; [#uses=1] + %5 = fmul double %4, 3.900000e+00 ; [#uses=1] + %6 = sext i7 %0 to i64 ; [#uses=1] + %7 = getelementptr double* %x, i64 %6 ; [#uses=1] + store double %5, double* %7, align 8 + %8 = add i64 %i.0.reg2mem.0, 1 ; [#uses=2] + %9 = icmp sgt i64 %8, 127 ; [#uses=1] + br i1 %9, label %return, label %bb1 + +return: ; preds = %bb1 + ret void +} + +define void @foo1(double* nocapture %x) nounwind { +bb1.thread: + br label %bb1 + +bb1: ; preds = %bb1, %bb1.thread + %i.0.reg2mem.0 = phi i64 [ -128, %bb1.thread ], [ %8, %bb1 ] ; [#uses=3] + %0 = trunc i64 %i.0.reg2mem.0 to i8 ; [#uses=1] + %1 = trunc i64 %i.0.reg2mem.0 to i9 ; [#uses=1] + %2 = sext i9 %1 to i64 ; [#uses=1] + %3 = getelementptr double* %x, i64 %2 ; [#uses=1] + %4 = load double* %3, align 8 ; [#uses=1] + %5 = fmul double %4, 3.900000e+00 ; [#uses=1] + %6 = sext i8 %0 to i64 ; [#uses=1] + %7 = getelementptr double* %x, i64 %6 ; [#uses=1] + store double %5, double* %7, align 8 + %8 = add i64 %i.0.reg2mem.0, 1 ; [#uses=2] + %9 = icmp sgt i64 %8, 128 ; [#uses=1] + br i1 %9, label %return, label %bb1 + +return: ; preds = %bb1 + ret void +} + +define void @foo2(double* nocapture %x) nounwind { +bb1.thread: + br label %bb1 + +bb1: ; preds = %bb1, %bb1.thread + %i.0.reg2mem.0 = phi i64 [ -129, %bb1.thread ], [ %8, %bb1 ] ; [#uses=3] + %0 = trunc i64 %i.0.reg2mem.0 to i8 ; [#uses=1] + %1 = trunc i64 %i.0.reg2mem.0 to i9 ; [#uses=1] + %2 = sext i9 %1 to i64 ; [#uses=1] + %3 = getelementptr double* %x, i64 %2 ; [#uses=1] + %4 = load double* %3, align 8 ; [#uses=1] + %5 = fmul double %4, 3.900000e+00 ; [#uses=1] + %6 = sext i8 %0 to i64 ; [#uses=1] + %7 = getelementptr double* %x, i64 %6 ; [#uses=1] + store double %5, double* %7, align 8 + %8 = add i64 %i.0.reg2mem.0, 1 ; [#uses=2] + %9 = icmp sgt i64 %8, 127 ; [#uses=1] + br i1 %9, label %return, label %bb1 + +return: ; preds = %bb1 + ret void +} + +define void @foo3(double* nocapture %x) nounwind { +bb1.thread: + br label %bb1 + +bb1: ; preds = %bb1, %bb1.thread + %i.0.reg2mem.0 = phi i64 [ -128, %bb1.thread ], [ %8, %bb1 ] ; [#uses=3] + %0 = trunc i64 %i.0.reg2mem.0 to i8 ; [#uses=1] + %1 = trunc i64 %i.0.reg2mem.0 to i9 ; [#uses=1] + %2 = sext i9 %1 to i64 ; [#uses=1] + %3 = getelementptr double* %x, i64 %2 ; [#uses=1] + %4 = load double* %3, align 8 ; [#uses=1] + %5 = fmul double %4, 3.900000e+00 ; [#uses=1] + %6 = sext i8 %0 to i64 ; [#uses=1] + %7 = getelementptr double* %x, i64 %6 ; [#uses=1] + store double %5, double* %7, align 8 + %8 = add i64 %i.0.reg2mem.0, -1 ; [#uses=2] + %9 = icmp sgt i64 %8, 127 ; [#uses=1] + br i1 %9, label %return, label %bb1 + +return: ; preds = %bb1 + ret void +} diff --git a/libclamav/c++/llvm/test/Analysis/ScalarEvolution/sext-iv-2.ll b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/sext-iv-2.ll new file mode 100644 index 000000000..b25c23795 --- /dev/null +++ b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/sext-iv-2.ll @@ -0,0 +1,74 @@ +; RUN: opt < %s -analyze -scalar-evolution -disable-output | FileCheck %s + +; CHECK: %tmp3 = sext i8 %tmp2 to i32 +; CHECK: --> (sext i8 {0,+,1} to i32) Exits: -1 +; CHECK: %tmp4 = mul i32 %tmp3, %i.02 +; CHECK: --> ((sext i8 {0,+,1} to i32) * {0,+,1}) Exits: {0,+,-1} + +; These sexts are not foldable. + +target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64" + +@table = common global [32 x [256 x i32]] zeroinitializer, align 32 ; <[32 x [256 x i32]]*> [#uses=2] + +define i32 @main() nounwind { +entry: + br i1 false, label %bb5, label %bb.nph3 + +bb.nph3: ; preds = %entry + br label %bb + +bb: ; preds = %bb4, %bb.nph3 + %i.02 = phi i32 [ %tmp10, %bb4 ], [ 0, %bb.nph3 ] ; [#uses=3] + br i1 false, label %bb3, label %bb.nph + +bb.nph: ; preds = %bb + br label %bb1 + +bb1: ; preds = %bb2, %bb.nph + %j.01 = phi i32 [ %tmp8, %bb2 ], [ 0, %bb.nph ] ; [#uses=3] + %tmp2 = trunc i32 %j.01 to i8 ; [#uses=1] + %tmp3 = sext i8 %tmp2 to i32 ; [#uses=1] + %tmp4 = mul i32 %tmp3, %i.02 ; [#uses=1] + %tmp5 = sext i32 %i.02 to i64 ; [#uses=1] + %tmp6 = sext i32 %j.01 to i64 ; [#uses=1] + %tmp7 = getelementptr [32 x [256 x i32]]* @table, i64 0, i64 %tmp5, i64 %tmp6 ; [#uses=1] + store i32 %tmp4, i32* %tmp7, align 4 + %tmp8 = add i32 %j.01, 1 ; [#uses=2] + br label %bb2 + +bb2: ; preds = %bb1 + %phitmp1 = icmp sgt i32 %tmp8, 255 ; [#uses=1] + br i1 %phitmp1, label %bb2.bb3_crit_edge, label %bb1 + +bb2.bb3_crit_edge: ; preds = %bb2 + br label %bb3 + +bb3: ; preds = %bb2.bb3_crit_edge, %bb + %tmp10 = add i32 %i.02, 1 ; [#uses=2] + br label %bb4 + +bb4: ; preds = %bb3 + %phitmp = icmp sgt i32 %tmp10, 31 ; [#uses=1] + br i1 %phitmp, label %bb4.bb5_crit_edge, label %bb + +bb4.bb5_crit_edge: ; preds = %bb4 + br label %bb5 + +bb5: ; preds = %bb4.bb5_crit_edge, %entry + %tmp12 = load i32* getelementptr ([32 x [256 x i32]]* @table, i64 0, i64 9, i64 132), align 16 ; [#uses=1] + %tmp13 = icmp eq i32 %tmp12, -1116 ; [#uses=1] + br i1 %tmp13, label %bb7, label %bb6 + +bb6: ; preds = %bb5 + call void @abort() noreturn nounwind + unreachable + +bb7: ; preds = %bb5 + br label %return + +return: ; preds = %bb7 + ret i32 0 +} + +declare void @abort() noreturn nounwind diff --git a/libclamav/c++/llvm/test/Analysis/ScalarEvolution/smax.ll b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/smax.ll new file mode 100644 index 000000000..39de8d6c5 --- /dev/null +++ b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/smax.ll @@ -0,0 +1,12 @@ +; RUN: opt < %s -analyze -scalar-evolution -disable-output | grep smax | count 2 +; RUN: opt < %s -analyze -scalar-evolution -disable-output | grep \ +; RUN: {%. smax %. smax %.} +; PR1614 + +define i32 @x(i32 %a, i32 %b, i32 %c) { + %A = icmp sgt i32 %a, %b + %B = select i1 %A, i32 %a, i32 %b + %C = icmp sle i32 %c, %B + %D = select i1 %C, i32 %B, i32 %c + ret i32 %D +} diff --git a/libclamav/c++/llvm/test/Analysis/ScalarEvolution/trip-count.ll b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/trip-count.ll new file mode 100644 index 000000000..66cc30491 --- /dev/null +++ b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/trip-count.ll @@ -0,0 +1,29 @@ +; RUN: opt < %s -analyze -scalar-evolution -disable-output \ +; RUN: -scalar-evolution-max-iterations=0 | grep {backedge-taken count is 10000} +; PR1101 + +@A = weak global [1000 x i32] zeroinitializer, align 32 + + +define void @test(i32 %N) { +entry: + "alloca point" = bitcast i32 0 to i32 ; [#uses=0] + br label %bb3 + +bb: ; preds = %bb3 + %tmp = getelementptr [1000 x i32]* @A, i32 0, i32 %i.0 ; [#uses=1] + store i32 123, i32* %tmp + %tmp2 = add i32 %i.0, 1 ; [#uses=1] + br label %bb3 + +bb3: ; preds = %bb, %entry + %i.0 = phi i32 [ 0, %entry ], [ %tmp2, %bb ] ; [#uses=3] + %tmp3 = icmp sle i32 %i.0, 9999 ; [#uses=1] + br i1 %tmp3, label %bb, label %bb5 + +bb5: ; preds = %bb3 + br label %return + +return: ; preds = %bb5 + ret void +} diff --git a/libclamav/c++/llvm/test/Analysis/ScalarEvolution/trip-count2.ll b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/trip-count2.ll new file mode 100644 index 000000000..bbe64358d --- /dev/null +++ b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/trip-count2.ll @@ -0,0 +1,35 @@ +; RUN: opt < %s -analyze -scalar-evolution -disable-output | \ +; RUN: grep {backedge-taken count is 4} +; PR1101 + +@A = weak global [1000 x i32] zeroinitializer, align 32 + + +define void @test(i32 %N) { +entry: + "alloca point" = bitcast i32 0 to i32 ; [#uses=0] + br label %bb3 + +bb: ; preds = %bb3 + %tmp = getelementptr [1000 x i32]* @A, i32 0, i32 %i.0 ; [#uses=1] + store i32 123, i32* %tmp + %tmp4 = mul i32 %i.0, 4 ; [#uses=1] + %tmp5 = or i32 %tmp4, 1 + %tmp61 = xor i32 %tmp5, -2147483648 + %tmp6 = trunc i32 %tmp61 to i16 + %tmp71 = shl i16 %tmp6, 2 + %tmp7 = zext i16 %tmp71 to i32 + %tmp2 = add i32 %tmp7, %i.0 + br label %bb3 + +bb3: ; preds = %bb, %entry + %i.0 = phi i32 [ 0, %entry ], [ %tmp2, %bb ] ; [#uses=3] + %tmp3 = icmp sle i32 %i.0, 9999 ; [#uses=1] + br i1 %tmp3, label %bb, label %bb5 + +bb5: ; preds = %bb3 + br label %return + +return: ; preds = %bb5 + ret void +} diff --git a/libclamav/c++/llvm/test/Analysis/ScalarEvolution/trip-count3.ll b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/trip-count3.ll new file mode 100644 index 000000000..240983178 --- /dev/null +++ b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/trip-count3.ll @@ -0,0 +1,78 @@ +; RUN: opt < %s -scalar-evolution -analyze -disable-output \ +; RUN: | grep {Loop bb3\\.i: Unpredictable backedge-taken count\\.} + +; ScalarEvolution can't compute a trip count because it doesn't know if +; dividing by the stride will have a remainder. This could theoretically +; be teaching it how to use a more elaborate trip count computation. + +target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128" +target triple = "x86_64-unknown-linux-gnu" + %struct.FILE = type { i32, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, %struct._IO_marker*, %struct.FILE*, i32, i32, i64, i16, i8, [1 x i8], i8*, i64, i8*, i8*, i8*, i8*, i64, i32, [20 x i8] } + %struct.SHA_INFO = type { [5 x i32], i32, i32, [16 x i32] } + %struct._IO_marker = type { %struct._IO_marker*, %struct.FILE*, i32 } +@_2E_str = external constant [26 x i8] ; <[26 x i8]*> [#uses=0] +@stdin = external global %struct.FILE* ; <%struct.FILE**> [#uses=0] +@_2E_str1 = external constant [3 x i8] ; <[3 x i8]*> [#uses=0] +@_2E_str12 = external constant [30 x i8] ; <[30 x i8]*> [#uses=0] + +declare void @sha_init(%struct.SHA_INFO* nocapture) nounwind + +declare fastcc void @sha_transform(%struct.SHA_INFO* nocapture) nounwind + +declare void @sha_print(%struct.SHA_INFO* nocapture) nounwind + +declare i32 @printf(i8* nocapture, ...) nounwind + +declare void @sha_final(%struct.SHA_INFO* nocapture) nounwind + +declare void @llvm.memset.i64(i8* nocapture, i8, i64, i32) nounwind + +declare void @sha_update(%struct.SHA_INFO* nocapture, i8* nocapture, i32) nounwind + +declare void @llvm.memcpy.i64(i8* nocapture, i8* nocapture, i64, i32) nounwind + +declare i64 @fread(i8* noalias nocapture, i64, i64, %struct.FILE* noalias nocapture) nounwind + +declare i32 @main(i32, i8** nocapture) nounwind + +declare noalias %struct.FILE* @fopen(i8* noalias nocapture, i8* noalias nocapture) nounwind + +declare i32 @fclose(%struct.FILE* nocapture) nounwind + +declare void @sha_stream(%struct.SHA_INFO* nocapture, %struct.FILE* nocapture) nounwind + +define void @sha_stream_bb3_2E_i(%struct.SHA_INFO* %sha_info, i8* %data1, i32, i8** %buffer_addr.0.i.out, i32* %count_addr.0.i.out) nounwind { +newFuncRoot: + br label %bb3.i + +sha_update.exit.exitStub: ; preds = %bb3.i + store i8* %buffer_addr.0.i, i8** %buffer_addr.0.i.out + store i32 %count_addr.0.i, i32* %count_addr.0.i.out + ret void + +bb2.i: ; preds = %bb3.i + %1 = getelementptr %struct.SHA_INFO* %sha_info, i64 0, i32 3 ; <[16 x i32]*> [#uses=1] + %2 = bitcast [16 x i32]* %1 to i8* ; [#uses=1] + call void @llvm.memcpy.i64(i8* %2, i8* %buffer_addr.0.i, i64 64, i32 1) nounwind + %3 = getelementptr %struct.SHA_INFO* %sha_info, i64 0, i32 3, i64 0 ; [#uses=1] + %4 = bitcast i32* %3 to i8* ; [#uses=1] + br label %codeRepl + +codeRepl: ; preds = %bb2.i + call void @sha_stream_bb3_2E_i_bb1_2E_i_2E_i(i8* %4) + br label %byte_reverse.exit.i + +byte_reverse.exit.i: ; preds = %codeRepl + call fastcc void @sha_transform(%struct.SHA_INFO* %sha_info) nounwind + %5 = getelementptr i8* %buffer_addr.0.i, i64 64 ; [#uses=1] + %6 = add i32 %count_addr.0.i, -64 ; [#uses=1] + br label %bb3.i + +bb3.i: ; preds = %byte_reverse.exit.i, %newFuncRoot + %buffer_addr.0.i = phi i8* [ %data1, %newFuncRoot ], [ %5, %byte_reverse.exit.i ] ; [#uses=3] + %count_addr.0.i = phi i32 [ %0, %newFuncRoot ], [ %6, %byte_reverse.exit.i ] ; [#uses=3] + %7 = icmp sgt i32 %count_addr.0.i, 63 ; [#uses=1] + br i1 %7, label %bb2.i, label %sha_update.exit.exitStub +} + +declare void @sha_stream_bb3_2E_i_bb1_2E_i_2E_i(i8*) nounwind diff --git a/libclamav/c++/llvm/test/Analysis/ScalarEvolution/trip-count4.ll b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/trip-count4.ll new file mode 100644 index 000000000..e8d59cf55 --- /dev/null +++ b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/trip-count4.ll @@ -0,0 +1,24 @@ +; RUN: opt < %s -analyze -scalar-evolution -disable-output \ +; RUN: | grep {sext.*trunc.*Exits: 11} + +; ScalarEvolution should be able to compute a loop exit value for %indvar.i8. + +define void @another_count_down_signed(double* %d, i64 %n) nounwind { +entry: + br label %loop + +loop: ; preds = %loop, %entry + %indvar = phi i64 [ %n, %entry ], [ %indvar.next, %loop ] ; [#uses=4] + %s0 = shl i64 %indvar, 8 ; [#uses=1] + %indvar.i8 = ashr i64 %s0, 8 ; [#uses=1] + %t0 = getelementptr double* %d, i64 %indvar.i8 ; [#uses=2] + %t1 = load double* %t0 ; [#uses=1] + %t2 = fmul double %t1, 1.000000e-01 ; [#uses=1] + store double %t2, double* %t0 + %indvar.next = sub i64 %indvar, 1 ; [#uses=2] + %exitcond = icmp eq i64 %indvar.next, 10 ; [#uses=1] + br i1 %exitcond, label %return, label %loop + +return: ; preds = %loop + ret void +} diff --git a/libclamav/c++/llvm/test/Analysis/ScalarEvolution/trip-count5.ll b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/trip-count5.ll new file mode 100644 index 000000000..2512a966e --- /dev/null +++ b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/trip-count5.ll @@ -0,0 +1,48 @@ +; RUN: opt < %s -analyze -scalar-evolution -disable-output > %t +; RUN: grep sext %t | count 2 +; RUN: not grep {(sext} %t + +; ScalarEvolution should be able to compute a maximum trip count +; value sufficient to fold away both sext casts. + +target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128" + +define float @t(float* %pTmp1, float* %peakWeight, float* %nrgReducePeakrate, i32 %bim) nounwind { +entry: + %tmp3 = load float* %peakWeight, align 4 ; [#uses=2] + %tmp2538 = icmp sgt i32 %bim, 0 ; [#uses=1] + br i1 %tmp2538, label %bb.nph, label %bb4 + +bb.nph: ; preds = %entry + br label %bb + +bb: ; preds = %bb1, %bb.nph + %distERBhi.036 = phi float [ %tmp10, %bb1 ], [ 0.000000e+00, %bb.nph ] ; [#uses=1] + %hiPart.035 = phi i32 [ %tmp12, %bb1 ], [ 0, %bb.nph ] ; [#uses=2] + %peakCount.034 = phi float [ %tmp19, %bb1 ], [ %tmp3, %bb.nph ] ; [#uses=1] + %tmp6 = sext i32 %hiPart.035 to i64 ; [#uses=1] + %tmp7 = getelementptr float* %pTmp1, i64 %tmp6 ; [#uses=1] + %tmp8 = load float* %tmp7, align 4 ; [#uses=1] + %tmp10 = fadd float %tmp8, %distERBhi.036 ; [#uses=3] + %tmp12 = add i32 %hiPart.035, 1 ; [#uses=3] + %tmp15 = sext i32 %tmp12 to i64 ; [#uses=1] + %tmp16 = getelementptr float* %peakWeight, i64 %tmp15 ; [#uses=1] + %tmp17 = load float* %tmp16, align 4 ; [#uses=1] + %tmp19 = fadd float %tmp17, %peakCount.034 ; [#uses=2] + br label %bb1 + +bb1: ; preds = %bb + %tmp21 = fcmp olt float %tmp10, 2.500000e+00 ; [#uses=1] + %tmp25 = icmp slt i32 %tmp12, %bim ; [#uses=1] + %tmp27 = and i1 %tmp21, %tmp25 ; [#uses=1] + br i1 %tmp27, label %bb, label %bb1.bb4_crit_edge + +bb1.bb4_crit_edge: ; preds = %bb1 + br label %bb4 + +bb4: ; preds = %bb1.bb4_crit_edge, %entry + %distERBhi.0.lcssa = phi float [ %tmp10, %bb1.bb4_crit_edge ], [ 0.000000e+00, %entry ] ; [#uses=1] + %peakCount.0.lcssa = phi float [ %tmp19, %bb1.bb4_crit_edge ], [ %tmp3, %entry ] ; [#uses=1] + %tmp31 = fdiv float %peakCount.0.lcssa, %distERBhi.0.lcssa ; [#uses=1] + ret float %tmp31 +} diff --git a/libclamav/c++/llvm/test/Analysis/ScalarEvolution/trip-count6.ll b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/trip-count6.ll new file mode 100644 index 000000000..583328631 --- /dev/null +++ b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/trip-count6.ll @@ -0,0 +1,37 @@ +; RUN: opt < %s -analyze -disable-output -scalar-evolution \ +; RUN: | grep {max backedge-taken count is 1\$} + +@mode_table = global [4 x i32] zeroinitializer ; <[4 x i32]*> [#uses=1] + +define i8 @f() { +entry: + tail call i32 @fegetround( ) ; :0 [#uses=1] + br label %bb + +bb: ; preds = %bb4, %entry + %mode.0 = phi i8 [ 0, %entry ], [ %indvar.next, %bb4 ] ; [#uses=4] + zext i8 %mode.0 to i32 ; :1 [#uses=1] + getelementptr [4 x i32]* @mode_table, i32 0, i32 %1 ; :2 [#uses=1] + load i32* %2, align 4 ; :3 [#uses=1] + icmp eq i32 %3, %0 ; :4 [#uses=1] + br i1 %4, label %bb1, label %bb2 + +bb1: ; preds = %bb + ret i8 %mode.0 + +bb2: ; preds = %bb + icmp eq i8 %mode.0, 1 ; :5 [#uses=1] + br i1 %5, label %bb5, label %bb4 + +bb4: ; preds = %bb2 + %indvar.next = add i8 %mode.0, 1 ; [#uses=1] + br label %bb + +bb5: ; preds = %bb2 + tail call void @raise_exception( ) noreturn + unreachable +} + +declare i32 @fegetround() + +declare void @raise_exception() noreturn diff --git a/libclamav/c++/llvm/test/Analysis/ScalarEvolution/trip-count7.ll b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/trip-count7.ll new file mode 100644 index 000000000..0cd8d7c4a --- /dev/null +++ b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/trip-count7.ll @@ -0,0 +1,150 @@ +; RUN: opt < %s -analyze -scalar-evolution -disable-output \ +; RUN: | grep {Loop bb7.i: Unpredictable backedge-taken count\\.} + +target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128" + + %struct.complex = type { float, float } + %struct.element = type { i32, i32 } + %struct.node = type { %struct.node*, %struct.node*, i32 } +@seed = external global i64 ; [#uses=0] +@_2E_str = external constant [18 x i8], align 1 ; <[18 x i8]*> [#uses=0] +@_2E_str1 = external constant [4 x i8], align 1 ; <[4 x i8]*> [#uses=0] +@value = external global float ; [#uses=0] +@fixed = external global float ; [#uses=0] +@floated = external global float ; [#uses=0] +@permarray = external global [11 x i32], align 32 ; <[11 x i32]*> [#uses=0] +@pctr = external global i32 ; [#uses=0] +@tree = external global %struct.node* ; <%struct.node**> [#uses=0] +@stack = external global [4 x i32], align 16 ; <[4 x i32]*> [#uses=0] +@cellspace = external global [19 x %struct.element], align 32 ; <[19 x %struct.element]*> [#uses=0] +@freelist = external global i32 ; [#uses=0] +@movesdone = external global i32 ; [#uses=0] +@ima = external global [41 x [41 x i32]], align 32 ; <[41 x [41 x i32]]*> [#uses=0] +@imb = external global [41 x [41 x i32]], align 32 ; <[41 x [41 x i32]]*> [#uses=0] +@imr = external global [41 x [41 x i32]], align 32 ; <[41 x [41 x i32]]*> [#uses=0] +@rma = external global [41 x [41 x float]], align 32 ; <[41 x [41 x float]]*> [#uses=0] +@rmb = external global [41 x [41 x float]], align 32 ; <[41 x [41 x float]]*> [#uses=0] +@rmr = external global [41 x [41 x float]], align 32 ; <[41 x [41 x float]]*> [#uses=0] +@piececount = external global [4 x i32], align 16 ; <[4 x i32]*> [#uses=0] +@class = external global [13 x i32], align 32 ; <[13 x i32]*> [#uses=0] +@piecemax = external global [13 x i32], align 32 ; <[13 x i32]*> [#uses=0] +@puzzl = external global [512 x i32], align 32 ; <[512 x i32]*> [#uses=0] +@p = external global [13 x [512 x i32]], align 32 ; <[13 x [512 x i32]]*> [#uses=0] +@n = external global i32 ; [#uses=0] +@kount = external global i32 ; [#uses=0] +@sortlist = external global [5001 x i32], align 32 ; <[5001 x i32]*> [#uses=0] +@biggest = external global i32 ; [#uses=0] +@littlest = external global i32 ; [#uses=0] +@top = external global i32 ; [#uses=0] +@z = external global [257 x %struct.complex], align 32 ; <[257 x %struct.complex]*> [#uses=0] +@w = external global [257 x %struct.complex], align 32 ; <[257 x %struct.complex]*> [#uses=0] +@e = external global [130 x %struct.complex], align 32 ; <[130 x %struct.complex]*> [#uses=0] +@zr = external global float ; [#uses=0] +@zi = external global float ; [#uses=0] + +declare void @Initrand() nounwind + +declare i32 @Rand() nounwind + +declare void @Try(i32, i32*, i32*, i32*, i32*, i32*) nounwind + +declare i32 @puts(i8* nocapture) nounwind + +declare void @Queens(i32) nounwind + +declare i32 @printf(i8* nocapture, ...) nounwind + +declare i32 @main() nounwind + +declare void @Doit() nounwind + +declare void @Doit_bb7([15 x i32]*, [17 x i32]*, [9 x i32]*) nounwind + +define void @Doit_bb7_2E_i([9 x i32]* %x1, [15 x i32]* %c, [17 x i32]* %b, [9 x i32]* %a, i32* %q, i32* %x1.sub, i32* %b9, i32* %a10, i32* %c11) nounwind { +newFuncRoot: + br label %bb7.i + +Try.exit.exitStub: ; preds = %bb7.i + ret void + +bb.i: ; preds = %bb7.i + %tmp = add i32 %j.0.i, 1 ; [#uses=5] + store i32 0, i32* %q, align 4 + %tmp1 = sext i32 %tmp to i64 ; [#uses=1] + %tmp2 = getelementptr [9 x i32]* %a, i64 0, i64 %tmp1 ; [#uses=1] + %tmp3 = load i32* %tmp2, align 4 ; [#uses=1] + %tmp4 = icmp eq i32 %tmp3, 0 ; [#uses=1] + br i1 %tmp4, label %bb.i.bb7.i.backedge_crit_edge, label %bb1.i + +bb1.i: ; preds = %bb.i + %tmp5 = add i32 %j.0.i, 2 ; [#uses=1] + %tmp6 = sext i32 %tmp5 to i64 ; [#uses=1] + %tmp7 = getelementptr [17 x i32]* %b, i64 0, i64 %tmp6 ; [#uses=1] + %tmp8 = load i32* %tmp7, align 4 ; [#uses=1] + %tmp9 = icmp eq i32 %tmp8, 0 ; [#uses=1] + br i1 %tmp9, label %bb1.i.bb7.i.backedge_crit_edge, label %bb2.i + +bb2.i: ; preds = %bb1.i + %tmp10 = sub i32 7, %j.0.i ; [#uses=1] + %tmp11 = sext i32 %tmp10 to i64 ; [#uses=1] + %tmp12 = getelementptr [15 x i32]* %c, i64 0, i64 %tmp11 ; [#uses=1] + %tmp13 = load i32* %tmp12, align 4 ; [#uses=1] + %tmp14 = icmp eq i32 %tmp13, 0 ; [#uses=1] + br i1 %tmp14, label %bb2.i.bb7.i.backedge_crit_edge, label %bb3.i + +bb3.i: ; preds = %bb2.i + %tmp15 = getelementptr [9 x i32]* %x1, i64 0, i64 1 ; [#uses=1] + store i32 %tmp, i32* %tmp15, align 4 + %tmp16 = sext i32 %tmp to i64 ; [#uses=1] + %tmp17 = getelementptr [9 x i32]* %a, i64 0, i64 %tmp16 ; [#uses=1] + store i32 0, i32* %tmp17, align 4 + %tmp18 = add i32 %j.0.i, 2 ; [#uses=1] + %tmp19 = sext i32 %tmp18 to i64 ; [#uses=1] + %tmp20 = getelementptr [17 x i32]* %b, i64 0, i64 %tmp19 ; [#uses=1] + store i32 0, i32* %tmp20, align 4 + %tmp21 = sub i32 7, %j.0.i ; [#uses=1] + %tmp22 = sext i32 %tmp21 to i64 ; [#uses=1] + %tmp23 = getelementptr [15 x i32]* %c, i64 0, i64 %tmp22 ; [#uses=1] + store i32 0, i32* %tmp23, align 4 + call void @Try(i32 2, i32* %q, i32* %b9, i32* %a10, i32* %c11, i32* %x1.sub) nounwind + %tmp24 = load i32* %q, align 4 ; [#uses=1] + %tmp25 = icmp eq i32 %tmp24, 0 ; [#uses=1] + br i1 %tmp25, label %bb5.i, label %bb3.i.bb7.i.backedge_crit_edge + +bb5.i: ; preds = %bb3.i + %tmp26 = sext i32 %tmp to i64 ; [#uses=1] + %tmp27 = getelementptr [9 x i32]* %a, i64 0, i64 %tmp26 ; [#uses=1] + store i32 1, i32* %tmp27, align 4 + %tmp28 = add i32 %j.0.i, 2 ; [#uses=1] + %tmp29 = sext i32 %tmp28 to i64 ; [#uses=1] + %tmp30 = getelementptr [17 x i32]* %b, i64 0, i64 %tmp29 ; [#uses=1] + store i32 1, i32* %tmp30, align 4 + %tmp31 = sub i32 7, %j.0.i ; [#uses=1] + %tmp32 = sext i32 %tmp31 to i64 ; [#uses=1] + %tmp33 = getelementptr [15 x i32]* %c, i64 0, i64 %tmp32 ; [#uses=1] + store i32 1, i32* %tmp33, align 4 + br label %bb7.i.backedge + +bb7.i.backedge: ; preds = %bb3.i.bb7.i.backedge_crit_edge, %bb2.i.bb7.i.backedge_crit_edge, %bb1.i.bb7.i.backedge_crit_edge, %bb.i.bb7.i.backedge_crit_edge, %bb5.i + br label %bb7.i + +bb7.i: ; preds = %bb7.i.backedge, %newFuncRoot + %j.0.i = phi i32 [ 0, %newFuncRoot ], [ %tmp, %bb7.i.backedge ] ; [#uses=8] + %tmp34 = load i32* %q, align 4 ; [#uses=1] + %tmp35 = icmp eq i32 %tmp34, 0 ; [#uses=1] + %tmp36 = icmp ne i32 %j.0.i, 8 ; [#uses=1] + %tmp37 = and i1 %tmp35, %tmp36 ; [#uses=1] + br i1 %tmp37, label %bb.i, label %Try.exit.exitStub + +bb.i.bb7.i.backedge_crit_edge: ; preds = %bb.i + br label %bb7.i.backedge + +bb1.i.bb7.i.backedge_crit_edge: ; preds = %bb1.i + br label %bb7.i.backedge + +bb2.i.bb7.i.backedge_crit_edge: ; preds = %bb2.i + br label %bb7.i.backedge + +bb3.i.bb7.i.backedge_crit_edge: ; preds = %bb3.i + br label %bb7.i.backedge +} diff --git a/libclamav/c++/llvm/test/Analysis/ScalarEvolution/trip-count8.ll b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/trip-count8.ll new file mode 100644 index 000000000..c49f5ceea --- /dev/null +++ b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/trip-count8.ll @@ -0,0 +1,37 @@ +; RUN: opt < %s -analyze -scalar-evolution -disable-output \ +; RUN: | grep {Loop for\\.body: backedge-taken count is (-1 + \[%\]ecx)} +; PR4599 + +target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128" + +define i32 @foo(i32 %ecx) nounwind { +entry: + %cmp2 = icmp eq i32 %ecx, 0 ; [#uses=1] + br i1 %cmp2, label %for.end, label %bb.nph + +for.cond: ; preds = %for.inc + %cmp = icmp ult i32 %inc, %ecx ; [#uses=1] + br i1 %cmp, label %for.body, label %for.cond.for.end_crit_edge + +for.cond.for.end_crit_edge: ; preds = %for.cond + %phitmp = add i32 %i.01, 2 ; [#uses=1] + br label %for.end + +bb.nph: ; preds = %entry + br label %for.body + +for.body: ; preds = %bb.nph, %for.cond + %i.01 = phi i32 [ %inc, %for.cond ], [ 0, %bb.nph ] ; [#uses=3] + %call = call i32 @bar(i32 %i.01) nounwind ; [#uses=0] + br label %for.inc + +for.inc: ; preds = %for.body + %inc = add i32 %i.01, 1 ; [#uses=2] + br label %for.cond + +for.end: ; preds = %for.cond.for.end_crit_edge, %entry + %i.0.lcssa = phi i32 [ %phitmp, %for.cond.for.end_crit_edge ], [ 1, %entry ] ; [#uses=1] + ret i32 %i.0.lcssa +} + +declare i32 @bar(i32) diff --git a/libclamav/c++/llvm/test/Analysis/ScalarEvolution/xor-and.ll b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/xor-and.ll new file mode 100644 index 000000000..c8339d713 --- /dev/null +++ b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/xor-and.ll @@ -0,0 +1,12 @@ +; RUN: opt < %s -scalar-evolution -disable-output -analyze \ +; RUN: | grep {\\--> (zext i4 (-8 + (trunc i64 (8 \\* %x) to i4)) to i64)} + +; ScalarEvolution shouldn't try to analyze %z into something like +; --> (zext i4 (-1 + (-1 * (trunc i64 (8 * %x) to i4))) to i64) + +define i64 @foo(i64 %x) { + %a = shl i64 %x, 3 + %t = and i64 %a, 8 + %z = xor i64 %t, 8 + ret i64 %z +} diff --git a/libclamav/c++/llvm/test/Analysis/ScalarEvolution/zext-wrap.ll b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/zext-wrap.ll new file mode 100644 index 000000000..9ff99be73 --- /dev/null +++ b/libclamav/c++/llvm/test/Analysis/ScalarEvolution/zext-wrap.ll @@ -0,0 +1,24 @@ +; RUN: opt < %s -analyze -scalar-evolution -disable-output \ +; RUN: | FileCheck %s +; PR4569 + +define i16 @main() nounwind { +entry: + br label %bb.i + +bb.i: ; preds = %bb1.i, %bb.nph + %l_95.0.i1 = phi i8 [ %tmp1, %bb.i ], [ 0, %entry ] + +; This cast shouldn't be folded into the addrec. +; CHECK: %tmp = zext i8 %l_95.0.i1 to i16 +; CHECK: --> (zext i8 {0,+,-1} to i16) Exits: 2 + + %tmp = zext i8 %l_95.0.i1 to i16 + + %tmp1 = add i8 %l_95.0.i1, -1 + %phitmp = icmp eq i8 %tmp1, 1 + br i1 %phitmp, label %bb1.i.func_36.exit_crit_edge, label %bb.i + +bb1.i.func_36.exit_crit_edge: + ret i16 %tmp +} diff --git a/libclamav/c++/llvm/test/Assembler/2002-01-24-BadSymbolTableAssert.ll b/libclamav/c++/llvm/test/Assembler/2002-01-24-BadSymbolTableAssert.ll new file mode 100644 index 000000000..7c49e2bd9 --- /dev/null +++ b/libclamav/c++/llvm/test/Assembler/2002-01-24-BadSymbolTableAssert.ll @@ -0,0 +1,11 @@ +; RUN: llvm-as %s -o /dev/null + +; This testcase failed due to a bad assertion in SymbolTable.cpp, removed in +; the 1.20 revision. Basically the symbol table assumed that if there was an +; abstract type in the symbol table, [in this case for the entry %foo of type +; void(opaque)* ], that there should have also been named types by now. This +; was obviously not the case here, and this is valid. Assertion disabled. + +%bb = type i32 + +declare void @foo(i32) diff --git a/libclamav/c++/llvm/test/Assembler/2002-01-24-ValueRefineAbsType.ll b/libclamav/c++/llvm/test/Assembler/2002-01-24-ValueRefineAbsType.ll new file mode 100644 index 000000000..6e49674a3 --- /dev/null +++ b/libclamav/c++/llvm/test/Assembler/2002-01-24-ValueRefineAbsType.ll @@ -0,0 +1,23 @@ +; RUN: llvm-as %s -o /dev/null + +; This testcase used to fail due to a lack of this diff in Value.cpp: +; diff -r1.16 Value.cpp +; 11c11 +; < #include "llvm/Type.h" +; --- +; > #include "llvm/DerivedTypes.h" +; 74c74,76 +; < assert(Ty.get() == (const Type*)OldTy &&"Can't refine anything but my type!"); +; --- +; > assert(Ty.get() == OldTy &&"Can't refine anything but my type!"); +; > if (OldTy == NewTy && !OldTy->isAbstract()) +; > Ty.removeUserFromConcrete(); +; +; This was causing an assertion failure, due to the "foo" Method object never +; releasing it's reference to the opaque %bb value. +; + +%bb = type i32 +%exception_descriptor = type i32 + +declare void @foo(i32) diff --git a/libclamav/c++/llvm/test/Assembler/2002-02-19-TypeParsing.ll b/libclamav/c++/llvm/test/Assembler/2002-02-19-TypeParsing.ll new file mode 100644 index 000000000..0df678497 --- /dev/null +++ b/libclamav/c++/llvm/test/Assembler/2002-02-19-TypeParsing.ll @@ -0,0 +1,3 @@ +; RUN: llvm-as %s -o /dev/null + +%Hosp = type { i32, i32, i32, { \2*, { i32, i32, i32, { [4 x \3], \2, \5, %Hosp, i32, i32 }* }*, \2* }, { \2*, { i32, i32, i32, { [4 x \3], \2, \5, %Hosp, i32, i32 }* }*, \2* }, { \2*, { i32, i32, i32, { [4 x \3], \2, \5, %Hosp, i32, i32 }* }*, \2* }, { \2*, { i32, i32, i32, { [4 x \3], \2, \5, %Hosp, i32, i32 }* }*, \2* } } diff --git a/libclamav/c++/llvm/test/Assembler/2002-03-08-NameCollision.ll b/libclamav/c++/llvm/test/Assembler/2002-03-08-NameCollision.ll new file mode 100644 index 000000000..b49789b29 --- /dev/null +++ b/libclamav/c++/llvm/test/Assembler/2002-03-08-NameCollision.ll @@ -0,0 +1,15 @@ +; RUN: llvm-as %s -o /dev/null + +; Method arguments were being checked for collisions at the global scope before +; the method object was created by the parser. Because of this, false +; collisions could occur that would cause the following error message to be +; produced: +; +; Redefinition of value named 'X' in the 'int *' type plane! +; +; Fixed by delaying binding of variable names until _after_ the method symtab is +; created. +; +@X = global i32 4 ; [#uses=0] + +declare i32 @xxx(i32*) diff --git a/libclamav/c++/llvm/test/Assembler/2002-03-08-NameCollision2.ll b/libclamav/c++/llvm/test/Assembler/2002-03-08-NameCollision2.ll new file mode 100644 index 000000000..1f7a4e16f --- /dev/null +++ b/libclamav/c++/llvm/test/Assembler/2002-03-08-NameCollision2.ll @@ -0,0 +1,12 @@ +; RUN: llvm-as %s -o /dev/null + +; Another name collision problem. Here the problem was that if a forward +; declaration for a method was found, that this would cause spurious conflicts +; to be detected between locals and globals. +; +@Var = external global i32 ; [#uses=0] + +define void @foo() { + %Var = alloca i32 ; [#uses=0] + ret void +} diff --git a/libclamav/c++/llvm/test/Assembler/2002-04-04-PureVirtMethCall.ll b/libclamav/c++/llvm/test/Assembler/2002-04-04-PureVirtMethCall.ll new file mode 100644 index 000000000..29aed55a3 --- /dev/null +++ b/libclamav/c++/llvm/test/Assembler/2002-04-04-PureVirtMethCall.ll @@ -0,0 +1,6 @@ +; RUN: llvm-as %s -o /dev/null + + type { { \2 *, \4 ** }, + { \2 *, \4 ** } + } + diff --git a/libclamav/c++/llvm/test/Assembler/2002-04-04-PureVirtMethCall2.ll b/libclamav/c++/llvm/test/Assembler/2002-04-04-PureVirtMethCall2.ll new file mode 100644 index 000000000..a0968999a --- /dev/null +++ b/libclamav/c++/llvm/test/Assembler/2002-04-04-PureVirtMethCall2.ll @@ -0,0 +1,5 @@ +; RUN: llvm-as %s -o /dev/null + +%t = type { { \2*, \2 }, + { \2*, \2 } + } diff --git a/libclamav/c++/llvm/test/Assembler/2002-04-05-TypeParsing.ll b/libclamav/c++/llvm/test/Assembler/2002-04-05-TypeParsing.ll new file mode 100644 index 000000000..f725944b9 --- /dev/null +++ b/libclamav/c++/llvm/test/Assembler/2002-04-05-TypeParsing.ll @@ -0,0 +1,3 @@ +; RUN: llvm-as %s -o /dev/null + + %Hosp = type { { \2*, { \2, %Hosp }* }, { \2*, { \2, %Hosp }* } } diff --git a/libclamav/c++/llvm/test/Assembler/2002-04-07-HexFloatConstants.ll b/libclamav/c++/llvm/test/Assembler/2002-04-07-HexFloatConstants.ll new file mode 100644 index 000000000..b0d7cc0e4 --- /dev/null +++ b/libclamav/c++/llvm/test/Assembler/2002-04-07-HexFloatConstants.ll @@ -0,0 +1,16 @@ +; This testcase checks to make sure that the assembler can handle floating +; point constants in IEEE hex format. This also checks that the disassembler, +; when presented with a FP constant that cannot be represented exactly in +; exponential form, outputs it correctly in hex format. This is a distillation +; of the bug that was causing the Olden Health benchmark to output incorrect +; results! +; +; RUN: opt -constprop -S > %t.1 < %s +; RUN: llvm-as < %s | llvm-dis | llvm-as | opt -constprop | \ +; RUN: llvm-dis > %t.2 +; RUN: diff %t.1 %t.2 + +define double @test() { + %tmp = fmul double 7.200000e+101, 0x427F4000 ; [#uses=1] + ret double %tmp +} diff --git a/libclamav/c++/llvm/test/Assembler/2002-04-07-InfConstant.ll b/libclamav/c++/llvm/test/Assembler/2002-04-07-InfConstant.ll new file mode 100644 index 000000000..71837c943 --- /dev/null +++ b/libclamav/c++/llvm/test/Assembler/2002-04-07-InfConstant.ll @@ -0,0 +1,9 @@ +; The output formater prints out 1.0e100 as Inf! +; +; RUN: llvm-as < %s | llvm-dis | llvm-as | llvm-dis | grep 0x7FF0000000000000 + +define float @test() { + %tmp = fmul float 0x7FF0000000000000, 1.000000e+01 ; [#uses=1] + ret float %tmp +} + diff --git a/libclamav/c++/llvm/test/Assembler/2002-04-29-NameBinding.ll b/libclamav/c++/llvm/test/Assembler/2002-04-29-NameBinding.ll new file mode 100644 index 000000000..7960c20dd --- /dev/null +++ b/libclamav/c++/llvm/test/Assembler/2002-04-29-NameBinding.ll @@ -0,0 +1,18 @@ +; There should be NO references to the global v1. The local v1 should +; have all of the references! +; +; Check by running globaldce, which will remove the constant if there are +; no references to it! +; +; RUN: opt < %s -globaldce -S | \ +; RUN: not grep constant +; + +@v1 = internal constant i32 5 + +define i32 @createtask() { + %v1 = alloca i32 ;; Alloca should have one use! + %reg112 = load i32* %v1 ;; This load should not use the global! + ret i32 %reg112 +} + diff --git a/libclamav/c++/llvm/test/Assembler/2002-05-02-InvalidForwardRef.ll b/libclamav/c++/llvm/test/Assembler/2002-05-02-InvalidForwardRef.ll new file mode 100644 index 000000000..234545c29 --- /dev/null +++ b/libclamav/c++/llvm/test/Assembler/2002-05-02-InvalidForwardRef.ll @@ -0,0 +1,10 @@ +; RUN: llvm-as %s -o /dev/null +; It looks like the assembler is not forward resolving the function declaraion +; correctly. + +define void @test() { + call void @foo( ) + ret void +} + +declare void @foo() diff --git a/libclamav/c++/llvm/test/Assembler/2002-05-02-ParseError.ll b/libclamav/c++/llvm/test/Assembler/2002-05-02-ParseError.ll new file mode 100644 index 000000000..5a9817c1e --- /dev/null +++ b/libclamav/c++/llvm/test/Assembler/2002-05-02-ParseError.ll @@ -0,0 +1,7 @@ +; RUN: llvm-as %s -o /dev/null + +%T = type i32 * + +define %T @test() { + ret %T null +} diff --git a/libclamav/c++/llvm/test/Assembler/2002-07-08-HugePerformanceProblem.ll b/libclamav/c++/llvm/test/Assembler/2002-07-08-HugePerformanceProblem.ll new file mode 100644 index 000000000..52c90af18 --- /dev/null +++ b/libclamav/c++/llvm/test/Assembler/2002-07-08-HugePerformanceProblem.ll @@ -0,0 +1,67 @@ +; This file takes about 48 __MINUTES__ to assemble using as. This is WAY too +; long. The type resolution code needs to be sped up a lot. +; RUN: llvm-as %s -o /dev/null + %ALL_INTERSECTIONS_METHOD = type i32 (%OBJECT*, %RAY*, %ISTACK*)* + %BBOX = type { %BBOX_VECT, %BBOX_VECT } + %BBOX_TREE = type { i16, i16, %BBOX, %BBOX_TREE** } + %BBOX_VECT = type [3 x float] + %BLEND_MAP = type { i16, i16, i16, i32, %BLEND_MAP_ENTRY* } + %BLEND_MAP_ENTRY = type { float, i8, { %COLOUR, %PIGMENT*, %TNORMAL*, %TEXTURE*, %UV_VECT } } + %CAMERA = type { %VECTOR, %VECTOR, %VECTOR, %VECTOR, %VECTOR, %VECTOR, double, double, i32, double, double, i32, double, %TNORMAL* } + %COLOUR = type [5 x float] + %COPY_METHOD = type i8* (%OBJECT*)* + %COUNTER = type { i32, i32 } + %DENSITY_FILE = type { i32, %DENSITY_FILE_DATA* } + %DENSITY_FILE_DATA = type { i32, i8*, i32, i32, i32, i8*** } + %DESTROY_METHOD = type void (%OBJECT*)* + %FILE = type { i32, i8*, i8*, i8, i8, i32, i32, i32 } + %FILE_HANDLE = type { i8*, i32, i32, i32, i32, i8*, %FILE*, i32, i32 (%FILE_HANDLE*, i8*, i32*, i32*, i32, i32)*, void (%FILE_HANDLE*, %COLOUR*, i32)*, i32 (%FILE_HANDLE*, %COLOUR*, i32*)*, void (%IMAGE*, i8*)*, void (%FILE_HANDLE*)* } + %FINISH = type { float, float, float, float, float, float, float, float, float, float, float, float, float, float, float, %BBOX_VECT, %BBOX_VECT } + %FOG = type { i32, double, double, double, %COLOUR, %VECTOR, %TURB*, float, %FOG* } + %FRAME = type { %CAMERA*, i32, i32, i32, %LIGHT_SOURCE*, %OBJECT*, double, double, %COLOUR, %COLOUR, %COLOUR, %IMEDIA*, %FOG*, %RAINBOW*, %SKYSPHERE* } + %FRAMESEQ = type { i32, double, i32, i32, double, i32, i32, double, i32, double, i32, double, i32, i32 } + %IMAGE = type { i32, i32, i32, i32, i32, i16, i16, %VECTOR, float, float, i32, i32, i16, %IMAGE_COLOUR*, { %IMAGE_LINE*, i8** } } + %IMAGE_COLOUR = type { i16, i16, i16, i16, i16 } + %IMAGE_LINE = type { i8*, i8*, i8*, i8* } + %IMEDIA = type { i32, i32, i32, i32, i32, double, double, i32, i32, i32, i32, %COLOUR, %COLOUR, %COLOUR, %COLOUR, double, double, double, double*, %PIGMENT*, %IMEDIA* } + %INSIDE_METHOD = type i32 (double*, %OBJECT*)* + %INTERIOR = type { i32, i32, float, float, float, float, float, %IMEDIA* } + %INTERSECTION = type { double, %VECTOR, %VECTOR, %OBJECT*, i32, i32, double, double, i8* } + %INVERT_METHOD = type void (%OBJECT*)* + %ISTACK = type { %ISTACK*, %INTERSECTION*, i32 } + %LIGHT_SOURCE = type { %METHODS*, i32, %OBJECT*, %TEXTURE*, %INTERIOR*, %OBJECT*, %OBJECT*, %BBOX, i32, %OBJECT*, %COLOUR, %VECTOR, %VECTOR, %VECTOR, %VECTOR, %VECTOR, double, double, double, double, double, %LIGHT_SOURCE*, i8, i8, i8, i8, i32, i32, i32, i32, i32, %COLOUR**, %OBJECT*, [6 x %PROJECT_TREE_NODE*] } + %MATRIX = type [4 x %VECTOR_4D] + %METHODS = type { %ALL_INTERSECTIONS_METHOD, %INSIDE_METHOD, %NORMAL_METHOD, %COPY_METHOD, %ROTATE_METHOD, %ROTATE_METHOD, %ROTATE_METHOD, %TRANSFORM_METHOD, %DESTROY_METHOD, %DESTROY_METHOD } + %NORMAL_METHOD = type void (double*, %OBJECT*, %INTERSECTION*)* + %OBJECT = type { %METHODS*, i32, %OBJECT*, %TEXTURE*, %INTERIOR*, %OBJECT*, %OBJECT*, %BBOX, i32 } + %Opts = type { i32, i32, i8, i8, i8, i32, [150 x i8], [150 x i8], [150 x i8], [150 x i8], [150 x i8], double, double, i32, i32, double, double, i32, [25 x i8*], i32, i32, i32, double, double, i32, i32, double, double, double, i32, i32, i32, i32, i32, %FRAMESEQ, double, i32, double, double, double, double, double, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, [150 x i8], %SHELLDATA*, [150 x i8], i32, i32 } + %PIGMENT = type { i16, i16, i16, i32, float, float, float, %WARP*, %TPATTERN*, %BLEND_MAP*, { %DENSITY_FILE*, %IMAGE*, %VECTOR, float, i16, i16, i16, { float, %VECTOR }, %complex.float }, %COLOUR } + %PRIORITY_QUEUE = type { i32, i32, %QELEM* } + %PROJECT = type { i32, i32, i32, i32 } + %PROJECT_QUEUE = type { i32, i32, %PROJECT_TREE_NODE** } + %PROJECT_TREE_NODE = type { i16, %BBOX_TREE*, %PROJECT, i16, %PROJECT_TREE_NODE** } + %QELEM = type { double, %BBOX_TREE* } + %RAINBOW = type { double, double, double, double, double, double, double, %VECTOR, %VECTOR, %VECTOR, %PIGMENT*, %RAINBOW* } + %RAY = type { %VECTOR, %VECTOR, i32, [100 x %INTERIOR*] } + %RAYINFO = type { %VECTOR, %VECTOR, %VECTORI, %VECTORI } + %RGB = type [3 x float] + %ROTATE_METHOD = type void (%OBJECT*, double*, %TRANSFORM*)* + %SCALE_METHOD = type void (%OBJECT*, double*, %TRANSFORM*)* + %SHELLDATA = type { i32, i32, [250 x i8] } + %SKYSPHERE = type { i32, %PIGMENT**, %TRANSFORM* } + %SNGL_VECT = type [3 x float] + %TEXTURE = type { i16, i16, i16, i32, float, float, float, %WARP*, %TPATTERN*, %BLEND_MAP*, { %DENSITY_FILE*, %IMAGE*, %VECTOR, float, i16, i16, i16, { float, %VECTOR }, %complex.float }, %TEXTURE*, %PIGMENT*, %TNORMAL*, %FINISH*, %TEXTURE*, i32 } + %TNORMAL = type { i16, i16, i16, i32, float, float, float, %WARP*, %TPATTERN*, %BLEND_MAP*, { %DENSITY_FILE*, %IMAGE*, %VECTOR, float, i16, i16, i16, { float, %VECTOR }, %complex.float }, float } + %TPATTERN = type { i16, i16, i16, i32, float, float, float, %WARP*, %TPATTERN*, %BLEND_MAP*, { %DENSITY_FILE*, %IMAGE*, %VECTOR, float, i16, i16, i16, { float, %VECTOR }, %complex.float } } + %TRANSFORM = type { %MATRIX, %MATRIX } + %TRANSFORM_METHOD = type void (%OBJECT*, %TRANSFORM*)* + %TRANSLATE_METHOD = type void (%OBJECT*, double*, %TRANSFORM*)* + %TURB = type { i16, %WARP*, %VECTOR, i32, float, float } + %UV_VECT = type [2 x double] + %VECTOR = type [3 x double] + %VECTORI = type [3 x i32] + %VECTOR_4D = type [4 x double] + %WARP = type { i16, %WARP* } + %__FILE = type { i32, i8*, i8*, i8, i8, i32, i32, i32 } + %_h_val = type { [2 x i32], double } + %complex.float = type { float, float } diff --git a/libclamav/c++/llvm/test/Assembler/2002-07-14-InternalLossage.ll b/libclamav/c++/llvm/test/Assembler/2002-07-14-InternalLossage.ll new file mode 100644 index 000000000..f93f1c4a5 --- /dev/null +++ b/libclamav/c++/llvm/test/Assembler/2002-07-14-InternalLossage.ll @@ -0,0 +1,9 @@ +; Test to make sure that the 'internal' tag is not lost! +; +; RUN: llvm-as < %s | llvm-dis | grep internal + +declare void @foo() + +define internal void @foo() { + ret void +} diff --git a/libclamav/c++/llvm/test/Assembler/2002-07-14-OpaqueType.ll b/libclamav/c++/llvm/test/Assembler/2002-07-14-OpaqueType.ll new file mode 100644 index 000000000..662fb0f31 --- /dev/null +++ b/libclamav/c++/llvm/test/Assembler/2002-07-14-OpaqueType.ll @@ -0,0 +1,10 @@ +; Test that opaque types are preserved correctly +; RUN: llvm-as < %s | llvm-dis | llvm-as | llvm-dis +; + +%Ty = type opaque + +define %Ty* @func() { + ret %Ty* null +} + diff --git a/libclamav/c++/llvm/test/Assembler/2002-07-25-ParserAssertionFailure.ll b/libclamav/c++/llvm/test/Assembler/2002-07-25-ParserAssertionFailure.ll new file mode 100644 index 000000000..3c5c5546b --- /dev/null +++ b/libclamav/c++/llvm/test/Assembler/2002-07-25-ParserAssertionFailure.ll @@ -0,0 +1,13 @@ +; Make sure we don't get an assertion failure, even though this is a parse +; error +; RUN: not llvm-as %s -o /dev/null |& grep {'@foo' defined with} + +%ty = type void (i32) + +declare %ty* @foo() + +define void @test() { + call %ty* @foo( ) ; <%ty*>:0 [#uses=0] + ret void +} + diff --git a/libclamav/c++/llvm/test/Assembler/2002-07-25-QuoteInString.ll b/libclamav/c++/llvm/test/Assembler/2002-07-25-QuoteInString.ll new file mode 100644 index 000000000..facc5bdae --- /dev/null +++ b/libclamav/c++/llvm/test/Assembler/2002-07-25-QuoteInString.ll @@ -0,0 +1,5 @@ +; Test double quotes in strings work correctly! +; RUN: llvm-as < %s | llvm-dis | llvm-as | llvm-dis +; +@str = internal global [6 x i8] c"\22foo\22\00" ; <[6 x i8]*> [#uses=0] + diff --git a/libclamav/c++/llvm/test/Assembler/2002-07-25-ReturnPtrFunction.ll b/libclamav/c++/llvm/test/Assembler/2002-07-25-ReturnPtrFunction.ll new file mode 100644 index 000000000..515d105c1 --- /dev/null +++ b/libclamav/c++/llvm/test/Assembler/2002-07-25-ReturnPtrFunction.ll @@ -0,0 +1,15 @@ +; Test that returning a pointer to a function causes the disassembler to print +; the right thing. +; +; RUN: llvm-as < %s | llvm-dis | llvm-as + +%ty = type void (i32) + +declare %ty* @foo() + +define void @test() { + call %ty* ()* @foo( ) ; <%ty*>:1 [#uses=0] + ret void +} + + diff --git a/libclamav/c++/llvm/test/Assembler/2002-07-31-SlashInString.ll b/libclamav/c++/llvm/test/Assembler/2002-07-31-SlashInString.ll new file mode 100644 index 000000000..ff4825887 --- /dev/null +++ b/libclamav/c++/llvm/test/Assembler/2002-07-31-SlashInString.ll @@ -0,0 +1,5 @@ +; RUN: llvm-as < %s | llvm-dis | llvm-as + +; Make sure that \\ works in a string initializer +@Slashtest = internal global [8 x i8] c"\5Cbegin{\00" + diff --git a/libclamav/c++/llvm/test/Assembler/2002-08-15-CastAmbiguity.ll b/libclamav/c++/llvm/test/Assembler/2002-08-15-CastAmbiguity.ll new file mode 100644 index 000000000..c71652446 --- /dev/null +++ b/libclamav/c++/llvm/test/Assembler/2002-08-15-CastAmbiguity.ll @@ -0,0 +1,6 @@ +; RUN: llvm-as %s -o /dev/null + +define void @test(i32 %X) { + call void @test( i32 6 ) + ret void +} diff --git a/libclamav/c++/llvm/test/Assembler/2002-08-15-ConstantExprProblem.ll b/libclamav/c++/llvm/test/Assembler/2002-08-15-ConstantExprProblem.ll new file mode 100644 index 000000000..02b9ea9ad --- /dev/null +++ b/libclamav/c++/llvm/test/Assembler/2002-08-15-ConstantExprProblem.ll @@ -0,0 +1,16 @@ +; RUN: llvm-as %s -o /dev/null + +@.LC0 = internal global [12 x i8] c"hello world\00" ; <[12 x i8]*> [#uses=1] + +define i8* @test() { +;

    operation never modifies the archive. + +=item q[Rfz] + +Quickly append files to the end of the archive. The F, F, and F +modifiers apply to this operation. This operation quickly adds the +F to the archive without checking for duplicates that should be +removed first. If no F are specified, the archive is not modified. +Because of the way that B constructs the archive file, its dubious +whether the F operation is any faster than the F operation. + +=item r[Rabfuz] + +Replace or insert file members. The F, F, F, F, F, and F +modifiers apply to this operation. This operation will replace existing +F or insert them at the end of the archive if they do not exist. If no +F are specified, the archive is not modified. + +=item t[v] + +Print the table of contents. Without any modifiers, this operation just prints +the names of the members to the standard output. With the F modifier, +B also prints out the file type (B=bitcode, Z=compressed, S=symbol +table, blank=regular file), the permission mode, the owner and group, the +size, and the date. If any F are specified, the listing is only for +those files. If no F are specified, the table of contents for the +whole archive is printed. + +=item x[oP] + +Extract archive members back to files. The F modifier applies to this +operation. This operation retrieves the indicated F from the archive +and writes them back to the operating system's file system. If no +F are specified, the entire archive is extract. + +=back + +=head2 Modifiers (operation specific) + +The modifiers below are specific to certain operations. See the Operations +section (above) to determine which modifiers are applicable to which operations. + +=over + +=item [a] + +When inserting or moving member files, this option specifies the destination of +the new files as being Cfter the F member. If F is not found, +the files are placed at the end of the archive. + +=item [b] + +When inserting or moving member files, this option specifies the destination of +the new files as being Cefore the F member. If F is not +found, the files are placed at the end of the archive. This modifier is +identical to the the F modifier. + +=item [f] + +Normally, B stores the full path name to a file as presented to it on +the command line. With this option, truncated (15 characters max) names are +used. This ensures name compatibility with older versions of C but may also +thwart correct extraction of the files (duplicates may overwrite). If used with +the F option, the directory recursion will be performed but the file names +will all be Clattened to simple file names. + +=item [i] + +A synonym for the F option. + +=item [k] + +Normally, B will not print the contents of bitcode files when the +F